diff --git a/.cirrus.yml b/.cirrus.yml index de0727cb097a76410262dd670c2b049c544db797..62a9b57530b5dcfd440c88d66150f5ae2b13ee6d 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -6,37 +6,130 @@ freebsd_12_task: image_family: freebsd-12-1 cpu: 8 memory: 8G - install_script: ASSUME_ALWAYS_YES=yes pkg bootstrap -f ; pkg install -y - bash bison curl cyrus-sasl git glib gmake gnutls gsed - nettle perl5 pixman pkgconf png usbredir + 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 - - ../configure || { cat config.log; exit 1; } - - gmake -j8 - - gmake -j8 V=1 check + - ../configure --enable-werror || { 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: + timeout_in: 90m osx_instance: - image: mojave-base + image: catalina-base install_script: - - brew install pkg-config python gnu-sed glib pixman make sdl2 + - brew install pkg-config python gnu-sed glib pixman make sdl2 bash ninja script: - mkdir build - cd build - - ../configure --python=/usr/local/bin/python3 || { cat config.log; exit 1; } + - ../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 -j$(sysctl -n hw.ncpu) + - gmake check V=1 macos_xcode_task: + timeout_in: 90m osx_instance: # this is an alias for the latest Xcode - image: mojave-xcode + image: catalina-xcode install_script: - - brew install pkg-config gnu-sed glib pixman make sdl2 + - brew install pkg-config gnu-sed glib pixman make sdl2 bash ninja script: - mkdir build - cd build - - ../configure --cc=clang || { cat config.log; exit 1; } + - ../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 -j$(sysctl -n hw.ncpu) + - gmake check V=1 + +windows_msys2_task: + timeout_in: 90m + windows_container: + image: cirrusci/windowsservercore:2019 + os_version: 2019 + cpu: 8 + memory: 8G + env: + CIRRUS_SHELL: powershell + MSYS: winsymlinks:nativestrict + MSYSTEM: MINGW64 + CHERE_INVOKING: 1 + setup_script: + - choco install -y --no-progress 7zip + - Write-Output $env:PATH + msys2_cache: + folder: C:\tools\archive + reupload_on_changes: false + fingerprint_script: cat .cirrus.yml + populate_script: + - | + md C:\tools + md C:\tools\archive + $start_time = Get-Date + cd C:\tools + bitsadmin /transfer msys_download /dynamic /download /priority FOREGROUND https://github.com/msys2/msys2-installer/releases/download/2020-09-03/msys2-base-x86_64-20200903.sfx.exe C:\tools\base.exe + Write-Output "Download time taken: $((Get-Date).Subtract($start_time).Seconds) second(s)" + C:\tools\base.exe -y + ((Get-Content -path C:\tools\msys64\etc\\post-install\\07-pacman-key.post -Raw) -replace '--refresh-keys', '--version') | Set-Content -Path C:\tools\msys64\etc\\post-install\\07-pacman-key.post + C:\tools\msys64\usr\bin\bash.exe -lc "sed -i 's/^CheckSpace/#CheckSpace/g' /etc/pacman.conf" + C:\tools\msys64\usr\bin\bash.exe -lc "export" + C:\tools\msys64\usr\bin\pacman.exe --noconfirm -Sy + echo Y | C:\tools\msys64\usr\bin\pacman.exe --noconfirm -Suu --overwrite=* + taskkill /F /FI "MODULES eq msys-2.0.dll" + tasklist + C:\tools\msys64\usr\bin\bash.exe -lc "mv -f /etc/pacman.conf.pacnew /etc/pacman.conf || true" + C:\tools\msys64\usr\bin\bash.exe -lc "pacman --noconfirm -Suu --overwrite=*" + C:\tools\msys64\usr\bin\bash.exe -lc "pacman --noconfirm -S --needed \ + diffutils git grep make pkg-config sed \ + mingw-w64-x86_64-python \ + mingw-w64-x86_64-toolchain \ + mingw-w64-x86_64-SDL2 \ + mingw-w64-x86_64-SDL2_image \ + mingw-w64-x86_64-gtk3 \ + mingw-w64-x86_64-glib2 \ + mingw-w64-x86_64-ninja \ + mingw-w64-x86_64-jemalloc \ + mingw-w64-x86_64-lzo2 \ + mingw-w64-x86_64-zstd \ + mingw-w64-x86_64-libjpeg-turbo \ + mingw-w64-x86_64-pixman \ + mingw-w64-x86_64-libgcrypt \ + mingw-w64-x86_64-libpng \ + mingw-w64-x86_64-libssh \ + mingw-w64-x86_64-libxml2 \ + mingw-w64-x86_64-snappy \ + mingw-w64-x86_64-libusb \ + mingw-w64-x86_64-usbredir \ + mingw-w64-x86_64-libtasn1 \ + mingw-w64-x86_64-nettle \ + mingw-w64-x86_64-cyrus-sasl \ + mingw-w64-x86_64-curl \ + mingw-w64-x86_64-gnutls \ + mingw-w64-x86_64-libnfs \ + " + bitsadmin /transfer msys_download /dynamic /download /priority FOREGROUND ` + https://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-python-sphinx-2.3.1-1-any.pkg.tar.xz ` + C:\tools\mingw-w64-x86_64-python-sphinx-2.3.1-1-any.pkg.tar.xz + C:\tools\msys64\usr\bin\bash.exe -lc "pacman --noconfirm -U /c/tools/mingw-w64-x86_64-python-sphinx-2.3.1-1-any.pkg.tar.xz" + del C:\tools\mingw-w64-x86_64-python-sphinx-2.3.1-1-any.pkg.tar.xz + C:\tools\msys64\usr\bin\bash.exe -lc "rm -rf /var/cache/pacman/pkg/*" + cd C:\tools\msys64 + echo "Start archive" + cmd /C "7z a -ttar . -so | 7z a -txz -simsys2-x86_64.tar C:\tools\archive\msys2-x86_64.tar.xz" + install_script: + - | + cd C:\tools + cmd /C "7z x C:\tools\archive\msys2-x86_64.tar.xz -so | 7z x -aoa -simsys2-x86_64.tar -ttar -omsys64" + C:\tools\msys64\usr\bin\bash.exe -lc "export" + + script: + - C:\tools\msys64\usr\bin\bash.exe -lc "mkdir build" + - C:\tools\msys64\usr\bin\bash.exe -lc "cd build && ../configure --python=python3" + - C:\tools\msys64\usr\bin\bash.exe -lc "cd build && make -j8" + test_script: + - C:\tools\msys64\usr\bin\bash.exe -lc "cd build && make V=1 check" diff --git a/.editorconfig b/.editorconfig index a001f340bd8be482016d1f62a00913cf5b765b2b..22681d91c6ff3c6256b04e7b064da6c5510f8de2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -22,9 +22,10 @@ indent_style = tab indent_size = 8 file_type_emacs = makefile -[*.{c,h}] +[*.{c,h,c.inc,h.inc}] indent_style = space indent_size = 4 +file_type_emacs = c [*.sh] indent_style = space diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..3d2fe2ecda8b3d8338ccf602b571a3f8e3dc31f1 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +*.c.inc diff=c +*.h.inc diff=c diff --git a/.gitignore b/.gitignore index 0c5af83aa74548554e1a90d31518609546797713..b32bca1315e1d303d62b58989a78787863efa052 100644 --- a/.gitignore +++ b/.gitignore @@ -1,163 +1,12 @@ -/.doctrees -/config-devices.* -/config-all-devices.* -/config-all-disas.* -/config-host.* -/config-target.* -/config.status -/config-temp -/tools/virtiofsd/50-qemu-virtiofsd.json -/elf2dmp -/trace-events-all -/trace/generated-events.h -/trace/generated-events.c -/trace/generated-helpers-wrappers.h -/trace/generated-helpers.h -/trace/generated-helpers.c -/trace/generated-tcg-tracers.h -/ui/shader/texture-blit-frag.h -/ui/shader/texture-blit-vert.h -/ui/shader/texture-blit-flip-vert.h -/ui/input-keymap-*.c -*-timestamp -/*-softmmu -/*-darwin-user -/*-linux-user -/*-bsd-user -/ivshmem-client -/ivshmem-server -/libdis* -/libuser -/linux-headers/asm -/qga/qapi-generated -/qapi-gen-timestamp -/qapi/qapi-builtin-types.[ch] -/qapi/qapi-builtin-visit.[ch] -/qapi/qapi-commands-*.[ch] -/qapi/qapi-commands.[ch] -/qapi/qapi-emit-events.[ch] -/qapi/qapi-events-*.[ch] -/qapi/qapi-events.[ch] -/qapi/qapi-init-commands.[ch] -/qapi/qapi-introspect.[ch] -/qapi/qapi-types-*.[ch] -/qapi/qapi-types.[ch] -/qapi/qapi-visit-*.[ch] -!/qapi/qapi-visit-core.c -/qapi/qapi-visit.[ch] -/qapi/qapi-doc.texi -/qemu-edid -/qemu-img -/qemu-nbd -/qemu-options.def -/qemu-options.texi -/qemu-img-cmds.texi -/qemu-img-cmds.h -/qemu-io -/qemu-ga -/qemu-bridge-helper -/qemu-keymap -/qemu-monitor.texi -/qemu-monitor-info.texi -/qemu-version.h -/qemu-version.h.tmp -/module_block.h -/scsi/qemu-pr-helper -/vhost-user-scsi -/vhost-user-blk -/vhost-user-gpu -/vhost-user-input -/fsdev/virtfs-proxy-helper -*.tmp -*.[1-9] -*.a -*.aux -*.cp -*.exe -*.msi -*.dll -*.so -*.mo -*.fn -*.ky -*.log -*.pdf -*.pod -*.cps -*.fns -*.kys -*.pg +/GNUmakefile +/build/ *.pyc -*.toc -*.tp -*.vr -*.d -!/scripts/qemu-guest-agent/fsfreeze-hook.d -*.o .sdk -*.gcda -*.gcno -*.gcov -/pc-bios/bios-pq/status -/pc-bios/edk2-*.fd -/pc-bios/vgabios-pq/status -/pc-bios/optionrom/linuxboot.asm -/pc-bios/optionrom/linuxboot.bin -/pc-bios/optionrom/linuxboot.raw -/pc-bios/optionrom/linuxboot.img -/pc-bios/optionrom/linuxboot_dma.asm -/pc-bios/optionrom/linuxboot_dma.bin -/pc-bios/optionrom/linuxboot_dma.raw -/pc-bios/optionrom/linuxboot_dma.img -/pc-bios/optionrom/pvh.asm -/pc-bios/optionrom/pvh.bin -/pc-bios/optionrom/pvh.raw -/pc-bios/optionrom/pvh.img -/pc-bios/optionrom/multiboot.asm -/pc-bios/optionrom/multiboot.bin -/pc-bios/optionrom/multiboot.raw -/pc-bios/optionrom/multiboot.img -/pc-bios/optionrom/kvmvapic.asm -/pc-bios/optionrom/kvmvapic.bin -/pc-bios/optionrom/kvmvapic.raw -/pc-bios/optionrom/kvmvapic.img -/pc-bios/s390-ccw/s390-ccw.elf -/pc-bios/s390-ccw/s390-ccw.img -/docs/built -/docs/interop/qemu-ga-qapi.texi -/docs/interop/qemu-ga-ref.html -/docs/interop/qemu-ga-ref.info* -/docs/interop/qemu-ga-ref.txt -/docs/interop/qemu-qmp-qapi.texi -/docs/interop/qemu-qmp-ref.html -/docs/interop/qemu-qmp-ref.info* -/docs/interop/qemu-qmp-ref.txt -/docs/version.texi -/contrib/vhost-user-gpu/50-qemu-gpu.json -*.tps .stgit-* .git-submodule-status cscope.* tags TAGS -docker-src.* *~ *.ast_raw *.depend_raw -trace.h -trace.c -trace-ust.h -trace-ust.h -trace-dtrace.h -trace-dtrace.dtrace -trace-root.h -trace-root.c -trace-ust-root.h -trace-ust-root.h -trace-ust-all.h -trace-ust-all.c -trace-dtrace-root.h -trace-dtrace-root.dtrace -trace-ust-all.h -trace-ust-all.c -/target/arm/decode-sve.inc.c diff --git a/.gitlab-ci.d/check-dco.py b/.gitlab-ci.d/check-dco.py new file mode 100755 index 0000000000000000000000000000000000000000..632c8bcce87e630733ad2bbac693d532ac05b107 --- /dev/null +++ b/.gitlab-ci.d/check-dco.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +# +# check-dco.py: validate all commits are signed off +# +# Copyright (C) 2020 Red Hat, Inc. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import os.path +import sys +import subprocess + +namespace = "qemu-project" +if len(sys.argv) >= 2: + namespace = sys.argv[1] + +cwd = os.getcwd() +reponame = os.path.basename(cwd) +repourl = "https://gitlab.com/%s/%s.git" % (namespace, reponame) + +subprocess.check_call(["git", "remote", "add", "check-dco", repourl]) +subprocess.check_call(["git", "fetch", "check-dco", "master"], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) + +ancestor = subprocess.check_output(["git", "merge-base", + "check-dco/master", "HEAD"], + universal_newlines=True) + +ancestor = ancestor.strip() + +subprocess.check_call(["git", "remote", "rm", "check-dco"]) + +errors = False + +print("\nChecking for 'Signed-off-by: NAME ' " + + "on all commits since %s...\n" % ancestor) + +log = subprocess.check_output(["git", "log", "--format=%H %s", + ancestor + "..."], + universal_newlines=True) + +if log == "": + commits = [] +else: + commits = [[c[0:40], c[41:]] for c in log.strip().split("\n")] + +for sha, subject in commits: + + msg = subprocess.check_output(["git", "show", "-s", sha], + universal_newlines=True) + lines = msg.strip().split("\n") + + print("🔍 %s %s" % (sha, subject)) + sob = False + for line in lines: + if "Signed-off-by:" in line: + sob = True + if "localhost" in line: + print(" ❌ FAIL: bad email in %s" % line) + errors = True + + if not sob: + print(" ❌ FAIL missing Signed-off-by tag") + errors = True + +if errors: + print(""" + +❌ ERROR: One or more commits are missing a valid Signed-off-By tag. + + +This project requires all contributors to assert that their contributions +are provided in compliance with the terms of the Developer's Certificate +of Origin 1.1 (DCO): + + https://developercertificate.org/ + +To indicate acceptance of the DCO every commit must have a tag + + Signed-off-by: REAL NAME + +This can be achieved by passing the "-s" flag to the "git commit" command. + +To bulk update all commits on current branch "git rebase" can be used: + + git rebase -i master -x 'git commit --amend --no-edit -s' + +""") + + sys.exit(1) + +sys.exit(0) diff --git a/.gitlab-ci.d/check-patch.py b/.gitlab-ci.d/check-patch.py new file mode 100755 index 0000000000000000000000000000000000000000..39e2b403c9eb901079e644234191d1d023c99142 --- /dev/null +++ b/.gitlab-ci.d/check-patch.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# +# check-patch.py: run checkpatch.pl across all commits in a branch +# +# Copyright (C) 2020 Red Hat, Inc. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import os.path +import sys +import subprocess + +namespace = "qemu-project" +if len(sys.argv) >= 2: + namespace = sys.argv[1] + +cwd = os.getcwd() +reponame = os.path.basename(cwd) +repourl = "https://gitlab.com/%s/%s.git" % (namespace, reponame) + +# GitLab CI environment does not give us any direct info about the +# base for the user's branch. We thus need to figure out a common +# ancestor between the user's branch and current git master. +subprocess.check_call(["git", "remote", "add", "check-patch", repourl]) +subprocess.check_call(["git", "fetch", "check-patch", "master"], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) + +ancestor = subprocess.check_output(["git", "merge-base", + "check-patch/master", "HEAD"], + universal_newlines=True) + +ancestor = ancestor.strip() + +log = subprocess.check_output(["git", "log", "--format=%H %s", + ancestor + "..."], + universal_newlines=True) + +subprocess.check_call(["git", "remote", "rm", "check-patch"]) + +if log == "": + print("\nNo commits since %s, skipping checks\n" % ancestor) + sys.exit(0) + +errors = False + +print("\nChecking all commits since %s...\n" % ancestor, flush=True) + +ret = subprocess.run(["scripts/checkpatch.pl", "--terse", ancestor + "..."]) + +if ret.returncode != 0: + print(" ❌ FAIL one or more commits failed scripts/checkpatch.pl") + sys.exit(1) + +sys.exit(0) diff --git a/.gitlab-ci.d/containers.yml b/.gitlab-ci.d/containers.yml new file mode 100644 index 0000000000000000000000000000000000000000..892ca8d838ce80feceaf875c2ff06d1f906009fb --- /dev/null +++ b/.gitlab-ci.d/containers.yml @@ -0,0 +1,248 @@ +.container_job_template: &container_job_definition + image: docker:stable + stage: containers + services: + - docker:dind + before_script: + - export TAG="$CI_REGISTRY_IMAGE/qemu/$NAME:latest" + - export COMMON_TAG="$CI_REGISTRY/qemu-project/qemu/$NAME:latest" + - apk add python3 + - docker info + - docker login $CI_REGISTRY -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" + script: + - echo "TAG:$TAG" + - echo "COMMON_TAG:$COMMON_TAG" + - docker pull "$TAG" || docker pull "$COMMON_TAG" || true + - ./tests/docker/docker.py --engine docker build + -t "qemu/$NAME" -f "tests/docker/dockerfiles/$NAME.docker" + -r $CI_REGISTRY_IMAGE + - docker tag "qemu/$NAME" "$TAG" + - docker push "$TAG" + after_script: + - docker logout + rules: + - changes: + - .gitlab-ci.d/containers.yml + - tests/docker/* + - tests/docker/dockerfiles/* + - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' + - if: '$CI_COMMIT_REF_NAME == "testing/next"' + +amd64-centos7-container: + <<: *container_job_definition + variables: + NAME: centos7 + +amd64-centos8-container: + <<: *container_job_definition + variables: + NAME: centos8 + +amd64-debian10-container: + <<: *container_job_definition + variables: + NAME: debian10 + +amd64-debian11-container: + <<: *container_job_definition + variables: + NAME: debian11 + +alpha-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-alpha-cross + +amd64-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-amd64-cross + +amd64-debian-user-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-all-test-cross + +amd64-debian-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-amd64 + +arm64-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-arm64-cross + +arm64-test-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian11-container'] + variables: + NAME: debian-arm64-test-cross + +armel-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-armel-cross + +armhf-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-armhf-cross + +hppa-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-hppa-cross + +m68k-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-m68k-cross + +mips64-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-mips64-cross + +mips64el-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-mips64el-cross + +mips-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-mips-cross + +mipsel-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-mipsel-cross + +powerpc-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-powerpc-cross + +ppc64-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-ppc64-cross + +ppc64el-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-ppc64el-cross + +riscv64-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-riscv64-cross + +s390x-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-s390x-cross + +sh4-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-sh4-cross + +sparc64-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-sparc64-cross + +tricore-debian-cross-container: + <<: *container_job_definition + stage: containers-layer2 + needs: ['amd64-debian10-container'] + variables: + NAME: debian-tricore-cross + +xtensa-debian-cross-container: + <<: *container_job_definition + variables: + NAME: debian-xtensa-cross + +cris-fedora-cross-container: + <<: *container_job_definition + variables: + NAME: fedora-cris-cross + +amd64-fedora-container: + <<: *container_job_definition + variables: + NAME: fedora + +i386-fedora-cross-container: + <<: *container_job_definition + variables: + NAME: fedora-i386-cross + +win32-fedora-cross-container: + <<: *container_job_definition + variables: + NAME: fedora-win32-cross + +win64-fedora-cross-container: + <<: *container_job_definition + variables: + NAME: fedora-win64-cross + +amd64-ubuntu1804-container: + <<: *container_job_definition + variables: + NAME: ubuntu1804 + +amd64-ubuntu2004-container: + <<: *container_job_definition + variables: + NAME: ubuntu2004 + +amd64-ubuntu-container: + <<: *container_job_definition + variables: + NAME: ubuntu diff --git a/.gitlab-ci.d/crossbuilds.yml b/.gitlab-ci.d/crossbuilds.yml new file mode 100644 index 0000000000000000000000000000000000000000..03ebfabb3fac09351c33c2b46886cab3f43d42d1 --- /dev/null +++ b/.gitlab-ci.d/crossbuilds.yml @@ -0,0 +1,114 @@ + +.cross_system_build_job_template: &cross_system_build_job_definition + stage: build + image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest + timeout: 80m + script: + - mkdir build + - cd build + - PKG_CONFIG_PATH=$PKG_CONFIG_PATH + ../configure --enable-werror $QEMU_CONFIGURE_OPTS --disable-user + --target-list-exclude="aarch64-softmmu i386-softmmu microblaze-softmmu + mips-softmmu mipsel-softmmu mips64-softmmu ppc64-softmmu sh4-softmmu + xtensa-softmmu" + - make -j$(expr $(nproc) + 1) all check-build + +.cross_user_build_job_template: &cross_user_build_job_definition + stage: build + image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest + script: + - mkdir build + - cd build + - PKG_CONFIG_PATH=$PKG_CONFIG_PATH + ../configure --enable-werror $QEMU_CONFIGURE_OPTS --disable-system + - make -j$(expr $(nproc) + 1) all check-build + +cross-armel-system: + <<: *cross_system_build_job_definition + variables: + IMAGE: debian-armel-cross + +cross-armel-user: + <<: *cross_user_build_job_definition + variables: + IMAGE: debian-armel-cross + +cross-armhf-system: + <<: *cross_system_build_job_definition + variables: + IMAGE: debian-armhf-cross + +cross-armhf-user: + <<: *cross_user_build_job_definition + variables: + IMAGE: debian-armhf-cross + +cross-arm64-system: + <<: *cross_system_build_job_definition + variables: + IMAGE: debian-arm64-cross + +cross-arm64-user: + <<: *cross_user_build_job_definition + variables: + IMAGE: debian-arm64-cross + +cross-mips-system: + <<: *cross_system_build_job_definition + variables: + IMAGE: debian-mips-cross + +cross-mips-user: + <<: *cross_user_build_job_definition + variables: + IMAGE: debian-mips-cross + +cross-mipsel-system: + <<: *cross_system_build_job_definition + variables: + IMAGE: debian-mipsel-cross + +cross-mipsel-user: + <<: *cross_user_build_job_definition + variables: + IMAGE: debian-mipsel-cross + +cross-mips64el-system: + <<: *cross_system_build_job_definition + variables: + IMAGE: debian-mips64el-cross + +cross-mips64el-user: + <<: *cross_user_build_job_definition + variables: + IMAGE: debian-mips64el-cross + +cross-ppc64el-system: + <<: *cross_system_build_job_definition + variables: + IMAGE: debian-ppc64el-cross + +cross-ppc64el-user: + <<: *cross_user_build_job_definition + variables: + IMAGE: debian-ppc64el-cross + +cross-s390x-system: + <<: *cross_system_build_job_definition + variables: + IMAGE: debian-s390x-cross + +cross-s390x-user: + <<: *cross_user_build_job_definition + variables: + IMAGE: debian-s390x-cross + +cross-win32-system: + <<: *cross_system_build_job_definition + variables: + IMAGE: fedora-win32-cross + +cross-win64-system: + <<: *cross_system_build_job_definition + variables: + IMAGE: fedora-win64-cross diff --git a/.gitlab-ci-edk2.yml b/.gitlab-ci.d/edk2.yml similarity index 97% rename from .gitlab-ci-edk2.yml rename to .gitlab-ci.d/edk2.yml index 088ba4b43a33f86d3fbd35a400ac7fa6efbdb75f..e1e0452416612b281653e887ad791a3521bf5f43 100644 --- a/.gitlab-ci-edk2.yml +++ b/.gitlab-ci.d/edk2.yml @@ -1,8 +1,8 @@ docker-edk2: - stage: build + stage: containers rules: # Only run this job when the Dockerfile is modified - changes: - - .gitlab-ci-edk2.yml + - .gitlab-ci.d/edk2.yml - .gitlab-ci.d/edk2/Dockerfile when: always image: docker:19.03.1 @@ -24,6 +24,7 @@ docker-edk2: - docker push $IMAGE_TAG build-edk2: + stage: build rules: # Only run this job when ... - changes: # ... roms/edk2/ is modified (submodule updated) - roms/edk2/* diff --git a/.gitlab-ci-opensbi.yml b/.gitlab-ci.d/opensbi.yml similarity index 59% rename from .gitlab-ci-opensbi.yml rename to .gitlab-ci.d/opensbi.yml index dd051c01245d6bf128a0bf2eb4404de49448111b..5b13047e2ab0e3350846e5d49d0c0ebab6e73001 100644 --- a/.gitlab-ci-opensbi.yml +++ b/.gitlab-ci.d/opensbi.yml @@ -1,8 +1,8 @@ docker-opensbi: - stage: build + stage: containers rules: # Only run this job when the Dockerfile is modified - changes: - - .gitlab-ci-opensbi.yml + - .gitlab-ci.d/opensbi.yml - .gitlab-ci.d/opensbi/Dockerfile when: always image: docker:19.03.1 @@ -24,6 +24,7 @@ docker-opensbi: - docker push $IMAGE_TAG build-opensbi: + stage: build rules: # Only run this job when ... - changes: # ... roms/opensbi/ is modified (submodule updated) - roms/opensbi/* @@ -34,18 +35,14 @@ build-opensbi: when: always artifacts: paths: # 'artifacts.zip' will contains the following files: - - pc-bios/opensbi-riscv32-sifive_u-fw_jump.bin - - pc-bios/opensbi-riscv32-virt-fw_jump.bin - - pc-bios/opensbi-riscv64-sifive_u-fw_jump.bin - - pc-bios/opensbi-riscv64-virt-fw_jump.bin - - opensbi32-virt-stdout.log - - opensbi32-virt-stderr.log - - opensbi64-virt-stdout.log - - opensbi64-virt-stderr.log - - opensbi32-sifive_u-stdout.log - - opensbi32-sifive_u-stderr.log - - opensbi64-sifive_u-stdout.log - - opensbi64-sifive_u-stderr.log + - pc-bios/opensbi-riscv32-generic-fw_dynamic.bin + - pc-bios/opensbi-riscv32-generic-fw_dynamic.elf + - pc-bios/opensbi-riscv64-generic-fw_dynamic.bin + - pc-bios/opensbi-riscv64-generic-fw_dynamic.elf + - opensbi32-generic-stdout.log + - opensbi32-generic-stderr.log + - opensbi64-generic-stdout.log + - opensbi64-generic-stderr.log image: $CI_REGISTRY_IMAGE:opensbi-cross-build variables: GIT_DEPTH: 3 @@ -54,10 +51,6 @@ build-opensbi: - export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1)) - echo "=== Using ${JOBS} simultaneous jobs ===" - make -j${JOBS} -C roms/opensbi clean - - make -j${JOBS} -C roms opensbi32-virt 2>&1 1>opensbi32-virt-stdout.log | tee -a opensbi32-virt-stderr.log >&2 - - make -j${JOBS} -C roms/opensbi clean - - make -j${JOBS} -C roms opensbi64-virt 2>&1 1>opensbi64-virt-stdout.log | tee -a opensbi64-virt-stderr.log >&2 - - make -j${JOBS} -C roms/opensbi clean - - make -j${JOBS} -C roms opensbi32-sifive_u 2>&1 1>opensbi32-sifive_u-stdout.log | tee -a opensbi32-sifive_u-stderr.log >&2 + - make -j${JOBS} -C roms opensbi32-generic 2>&1 1>opensbi32-generic-stdout.log | tee -a opensbi32-generic-stderr.log >&2 - make -j${JOBS} -C roms/opensbi clean - - make -j${JOBS} -C roms opensbi64-sifive_u 2>&1 1>opensbi64-sifive_u-stdout.log | tee -a opensbi64-sifive_u-stderr.log >&2 + - make -j${JOBS} -C roms opensbi64-generic 2>&1 1>opensbi64-generic-stdout.log | tee -a opensbi64-generic-stderr.log >&2 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b889fb96b6324929027fd595101043db5c9797b8..d0173e82b16f731acefca34af6d8ece77255fab8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,104 +1,470 @@ +# Currently we have two build stages after our containers are built: +# - build (for traditional build and test or first stage build) +# - test (for test stages, using build artefacts from a build stage) +stages: + - containers + - containers-layer2 + - build + - test + include: - - local: '/.gitlab-ci-edk2.yml' - - local: '/.gitlab-ci-opensbi.yml' - -before_script: - - apt-get update -qq - - apt-get install -y -qq flex bison libglib2.0-dev libpixman-1-dev genisoimage - -build-system1: - script: - - apt-get install -y -qq libgtk-3-dev libvte-dev nettle-dev libcacard-dev - libusb-dev libvde-dev libspice-protocol-dev libgl1-mesa-dev libvdeplug-dev - - mkdir build - - cd build - - ../configure --enable-werror --target-list="aarch64-softmmu alpha-softmmu - cris-softmmu hppa-softmmu lm32-softmmu moxie-softmmu microblazeel-softmmu - mips64el-softmmu m68k-softmmu ppc-softmmu riscv64-softmmu sparc-softmmu" - - make -j2 - - make -j2 check - -build-system2: - script: - - apt-get install -y -qq libsdl2-dev libgcrypt-dev libbrlapi-dev libaio-dev - libfdt-dev liblzo2-dev librdmacm-dev libibverbs-dev libibumad-dev - libzstd-dev - - mkdir build - - cd build - - ../configure --enable-werror --target-list="tricore-softmmu unicore32-softmmu - microblaze-softmmu mips-softmmu riscv32-softmmu s390x-softmmu sh4-softmmu - sparc64-softmmu x86_64-softmmu xtensa-softmmu nios2-softmmu or1k-softmmu" - - make -j2 - - make -j2 check + - local: '/.gitlab-ci.d/edk2.yml' + - local: '/.gitlab-ci.d/opensbi.yml' + - local: '/.gitlab-ci.d/containers.yml' + - local: '/.gitlab-ci.d/crossbuilds.yml' + +.native_build_job_template: &native_build_job_definition + stage: build + image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest + before_script: + - JOBS=$(expr $(nproc) + 1) + - sed -i s,git.qemu.org/git,gitlab.com/qemu-project, .gitmodules + script: + - mkdir build + - cd build + - if test -n "$TARGETS"; + then + ../configure --enable-werror $CONFIGURE_ARGS --target-list="$TARGETS" ; + else + ../configure --enable-werror $CONFIGURE_ARGS ; + fi || { cat config.log meson-logs/meson-log.txt && exit 1; } + - make -j"$JOBS" + - if test -n "$MAKE_CHECK_ARGS"; + then + make -j"$JOBS" $MAKE_CHECK_ARGS ; + fi + +.native_test_job_template: &native_test_job_definition + stage: test + image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest + script: + - cd build + - find . -type f -exec touch {} + + - make $MAKE_CHECK_ARGS + +.acceptance_template: &acceptance_definition + cache: + key: "${CI_JOB_NAME}-cache" + paths: + - ${CI_PROJECT_DIR}/avocado-cache + policy: pull-push + artifacts: + paths: + - build/tests/results/latest/results.xml + reports: + junit: build/tests/results/latest/results.xml + before_script: + - mkdir -p ~/.config/avocado + - echo "[datadir.paths]" > ~/.config/avocado/avocado.conf + - echo "cache_dirs = ['${CI_PROJECT_DIR}/avocado-cache']" + >> ~/.config/avocado/avocado.conf + - if [ -d ${CI_PROJECT_DIR}/avocado-cache ]; then + du -chs ${CI_PROJECT_DIR}/avocado-cache ; + fi + - export AVOCADO_ALLOW_UNTRUSTED_CODE=1 + after_script: + - cd build + - python3 -c 'import json; r = json.load(open("tests/results/latest/results.json")); [print(t["logfile"]) for t in r["tests"] if t["status"] not in ("PASS", "SKIP", "CANCEL")]' | xargs cat + - du -chs ${CI_PROJECT_DIR}/avocado-cache + +build-system-ubuntu: + <<: *native_build_job_definition + variables: + IMAGE: ubuntu2004 + TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu + moxie-softmmu microblazeel-softmmu mips64el-softmmu + MAKE_CHECK_ARGS: check-build + CONFIGURE_ARGS: --enable-docs + artifacts: + expire_in: 2 days + paths: + - build + +check-system-ubuntu: + <<: *native_test_job_definition + needs: + - job: build-system-ubuntu + artifacts: true + variables: + IMAGE: ubuntu2004 + MAKE_CHECK_ARGS: check + +acceptance-system-ubuntu: + <<: *native_test_job_definition + needs: + - job: build-system-ubuntu + artifacts: true + variables: + IMAGE: ubuntu2004 + MAKE_CHECK_ARGS: check-acceptance + <<: *acceptance_definition + +build-system-debian: + <<: *native_build_job_definition + variables: + IMAGE: debian-amd64 + TARGETS: arm-softmmu avr-softmmu i386-softmmu mipsel-softmmu + riscv64-softmmu sh4eb-softmmu sparc-softmmu xtensaeb-softmmu + MAKE_CHECK_ARGS: check-build + CONFIGURE_ARGS: --enable-docs + artifacts: + expire_in: 2 days + paths: + - build + +check-system-debian: + <<: *native_test_job_definition + needs: + - job: build-system-debian + artifacts: true + variables: + IMAGE: debian-amd64 + MAKE_CHECK_ARGS: check + +acceptance-system-debian: + <<: *native_test_job_definition + needs: + - job: build-system-debian + artifacts: true + variables: + IMAGE: debian-amd64 + MAKE_CHECK_ARGS: check-acceptance + <<: *acceptance_definition + +build-system-fedora: + <<: *native_build_job_definition + variables: + IMAGE: fedora + CONFIGURE_ARGS: --disable-gcrypt --enable-nettle --enable-docs + TARGETS: tricore-softmmu microblaze-softmmu mips-softmmu + xtensa-softmmu m68k-softmmu riscv32-softmmu ppc-softmmu sparc64-softmmu + MAKE_CHECK_ARGS: check-build + artifacts: + expire_in: 2 days + paths: + - build + +check-system-fedora: + <<: *native_test_job_definition + needs: + - job: build-system-fedora + artifacts: true + variables: + IMAGE: fedora + MAKE_CHECK_ARGS: check + +acceptance-system-fedora: + <<: *native_test_job_definition + needs: + - job: build-system-fedora + artifacts: true + variables: + IMAGE: fedora + MAKE_CHECK_ARGS: check-acceptance + <<: *acceptance_definition + +build-system-centos: + <<: *native_build_job_definition + variables: + IMAGE: centos8 + CONFIGURE_ARGS: --disable-nettle --enable-gcrypt + TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu + x86_64-softmmu rx-softmmu sh4-softmmu nios2-softmmu + MAKE_CHECK_ARGS: check-build + artifacts: + expire_in: 2 days + paths: + - build + +check-system-centos: + <<: *native_test_job_definition + needs: + - job: build-system-centos + artifacts: true + variables: + IMAGE: centos8 + MAKE_CHECK_ARGS: check + +acceptance-system-centos: + <<: *native_test_job_definition + needs: + - job: build-system-centos + artifacts: true + variables: + IMAGE: centos8 + MAKE_CHECK_ARGS: check-acceptance + <<: *acceptance_definition build-disabled: - script: - - mkdir build - - cd build - - ../configure --enable-werror --disable-rdma --disable-slirp --disable-curl - --disable-capstone --disable-live-block-migration --disable-glusterfs - --disable-replication --disable-coroutine-pool --disable-smartcard - --disable-guest-agent --disable-curses --disable-libxml2 --disable-tpm - --disable-qom-cast-debug --disable-spice --disable-vhost-vsock - --disable-vhost-net --disable-vhost-crypto --disable-vhost-user - --target-list="i386-softmmu ppc64-softmmu mips64-softmmu i386-linux-user" - - make -j2 - - make -j2 check-qtest SPEED=slow + <<: *native_build_job_definition + variables: + IMAGE: fedora + CONFIGURE_ARGS: --disable-attr --disable-avx2 --disable-bochs + --disable-brlapi --disable-bzip2 --disable-cap-ng --disable-capstone + --disable-cloop --disable-coroutine-pool --disable-curl --disable-curses + --disable-dmg --disable-docs --disable-glusterfs --disable-gnutls + --disable-gtk --disable-guest-agent --disable-iconv --disable-kvm + --disable-libiscsi --disable-libpmem --disable-libssh --disable-libusb + --disable-libxml2 --disable-linux-aio --disable-live-block-migration + --disable-lzo --disable-malloc-trim --disable-mpath --disable-nettle + --disable-numa --disable-parallels --disable-pie --disable-qcow1 + --disable-qed --disable-qom-cast-debug --disable-rbd --disable-rdma + --disable-replication --disable-sdl --disable-seccomp --disable-sheepdog + --disable-slirp --disable-smartcard --disable-snappy --disable-spice + --disable-strip --disable-tpm --disable-usb-redir --disable-vdi + --disable-vhost-crypto --disable-vhost-net --disable-vhost-scsi + --disable-vhost-user --disable-vhost-vdpa --disable-vhost-vsock + --disable-virglrenderer --disable-vnc --disable-vte --disable-vvfat + --disable-xen --disable-zstd + TARGETS: arm-softmmu i386-softmmu ppc64-softmmu mips64-softmmu + s390x-softmmu i386-linux-user + MAKE_CHECK_ARGS: check-qtest SPEED=slow build-tcg-disabled: - script: - - apt-get install -y -qq clang libgtk-3-dev libusb-dev - - mkdir build - - cd build - - ../configure --cc=clang --enable-werror --disable-tcg --audio-drv-list="" - - make -j2 - - make check-unit - - make check-qapi-schema - - cd tests/qemu-iotests/ - - ./check -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048 + <<: *native_build_job_definition + variables: + IMAGE: centos8 + script: + - mkdir build + - cd build + - ../configure --disable-tcg --audio-drv-list="" || { cat config.log meson-logs/meson-log.txt && exit 1; } + - make -j"$JOBS" + - make check-unit + - make check-qapi-schema + - cd tests/qemu-iotests/ + - ./check -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048 052 063 077 086 101 104 106 113 148 150 151 152 157 159 160 163 170 171 183 184 192 194 197 208 215 221 222 226 227 236 253 277 - - ./check -qcow2 028 051 056 057 058 065 067 068 082 085 091 095 096 102 122 + - ./check -qcow2 028 051 056 057 058 065 068 082 085 091 095 096 102 122 124 132 139 142 144 145 151 152 155 157 165 194 196 197 200 202 208 209 215 216 218 222 227 234 246 247 248 250 254 255 257 258 260 261 262 263 264 270 272 273 277 279 build-user: - script: - - mkdir build - - cd build - - ../configure --enable-werror --disable-system --disable-guest-agent - --disable-capstone --disable-slirp --disable-fdt - - make -j2 - - make run-tcg-tests-i386-linux-user run-tcg-tests-x86_64-linux-user + <<: *native_build_job_definition + variables: + IMAGE: debian-all-test-cross + CONFIGURE_ARGS: --disable-tools --disable-system + MAKE_CHECK_ARGS: check-tcg + +# Only build the softmmu targets we have check-tcg tests for +build-some-softmmu: + <<: *native_build_job_definition + variables: + IMAGE: debian-all-test-cross + CONFIGURE_ARGS: --disable-tools --enable-debug-tcg + 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: + <<: *native_build_job_definition + 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: + <<: *native_build_job_definition + 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 build-clang: - script: - - apt-get install -y -qq clang libsdl2-dev libattr1-dev libcap-ng-dev - xfslibs-dev libiscsi-dev libnfs-dev libseccomp-dev gnutls-dev librbd-dev - - mkdir build - - cd build - - ../configure --cc=clang --cxx=clang++ --enable-werror - --target-list="alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu - ppc-softmmu s390x-softmmu x86_64-softmmu arm-linux-user" - - make -j2 - - make -j2 check + <<: *native_build_job_definition + variables: + IMAGE: fedora + CONFIGURE_ARGS: --cc=clang --cxx=clang++ + TARGETS: alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu + ppc-softmmu s390x-softmmu arm-linux-user + MAKE_CHECK_ARGS: check + +# These targets are on the way out +build-deprecated: + <<: *native_build_job_definition + variables: + IMAGE: debian-all-test-cross + CONFIGURE_ARGS: --disable-docs --disable-tools + MAKE_CHECK_ARGS: build-tcg + TARGETS: ppc64abi32-linux-user tilegx-linux-user lm32-softmmu + unicore32-softmmu + artifacts: + expire_in: 2 days + paths: + - build + +# We split the check-tcg step as test failures are expected but we still +# want to catch the build breaking. +check-deprecated: + <<: *native_test_job_definition + needs: + - job: build-deprecated + artifacts: true + variables: + IMAGE: debian-all-test-cross + MAKE_CHECK_ARGS: check-tcg + allow_failure: true + +build-oss-fuzz: + <<: *native_build_job_definition + variables: + IMAGE: fedora + script: + - mkdir build-oss-fuzz + - CC="clang" CXX="clang++" CFLAGS="-fsanitize=address" + ./scripts/oss-fuzz/build.sh + - export ASAN_OPTIONS="fast_unwind_on_malloc=0" + - for fuzzer in $(find ./build-oss-fuzz/DEST_DIR/ -executable -type f + | grep -v slirp); do + grep "LLVMFuzzerTestOneInput" ${fuzzer} > /dev/null 2>&1 || continue ; + echo Testing ${fuzzer} ... ; + "${fuzzer}" -runs=1 -seed=1 || exit 1 ; + done + # Unrelated to fuzzer: run some tests with -fsanitize=address + - cd build-oss-fuzz && make check-qtest-i386 check-unit build-tci: - script: - - TARGETS="aarch64 alpha arm hppa m68k microblaze moxie ppc64 s390x x86_64" - - mkdir build - - cd build - - ../configure --enable-tcg-interpreter - --target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)" - - make -j2 - - make run-tcg-tests-x86_64-softmmu - - make tests/qtest/boot-serial-test tests/qtest/cdrom-test tests/qtest/pxe-test - - for tg in $TARGETS ; do - export QTEST_QEMU_BINARY="${tg}-softmmu/qemu-system-${tg}" ; - ./tests/qtest/boot-serial-test || exit 1 ; - ./tests/qtest/cdrom-test || exit 1 ; - done - - QTEST_QEMU_BINARY="x86_64-softmmu/qemu-system-x86_64" ./tests/qtest/pxe-test - - QTEST_QEMU_BINARY="s390x-softmmu/qemu-system-s390x" - ./tests/qtest/pxe-test -m slow + <<: *native_build_job_definition + variables: + IMAGE: fedora + script: + - TARGETS="aarch64 alpha arm hppa m68k microblaze moxie ppc64 s390x x86_64" + - mkdir build + - cd build + - ../configure --enable-tcg-interpreter + --target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)" || { cat config.log meson-logs/meson-log.txt && exit 1; } + - make -j"$JOBS" + - make run-tcg-tests-x86_64-softmmu + - make tests/qtest/boot-serial-test tests/qtest/cdrom-test tests/qtest/pxe-test + - for tg in $TARGETS ; do + export QTEST_QEMU_BINARY="./qemu-system-${tg}" ; + ./tests/qtest/boot-serial-test || exit 1 ; + ./tests/qtest/cdrom-test || exit 1 ; + done + - QTEST_QEMU_BINARY="./qemu-system-x86_64" ./tests/qtest/pxe-test + - QTEST_QEMU_BINARY="./qemu-system-s390x" ./tests/qtest/pxe-test -m slow + +# Most jobs test latest gcrypt or nettle builds +# +# These jobs test old gcrypt and nettle from RHEL7 +# which had some API differences. +build-crypto-old-nettle: + <<: *native_build_job_definition + variables: + IMAGE: centos7 + TARGETS: x86_64-softmmu x86_64-linux-user + CONFIGURE_ARGS: --disable-gcrypt --enable-nettle + MAKE_CHECK_ARGS: check-build + artifacts: + paths: + - build + +check-crypto-old-nettle: + <<: *native_test_job_definition + needs: + - job: build-crypto-old-nettle + artifacts: true + variables: + IMAGE: centos7 + MAKE_CHECK_ARGS: check + + +build-crypto-old-gcrypt: + <<: *native_build_job_definition + variables: + IMAGE: centos7 + TARGETS: x86_64-softmmu x86_64-linux-user + CONFIGURE_ARGS: --disable-nettle --enable-gcrypt + MAKE_CHECK_ARGS: check-build + artifacts: + paths: + - build + +check-crypto-old-gcrypt: + <<: *native_test_job_definition + needs: + - job: build-crypto-old-gcrypt + artifacts: true + variables: + IMAGE: centos7 + MAKE_CHECK_ARGS: check + + +build-crypto-only-gnutls: + <<: *native_build_job_definition + variables: + IMAGE: centos7 + TARGETS: x86_64-softmmu x86_64-linux-user + CONFIGURE_ARGS: --disable-nettle --disable-gcrypt --enable-gnutls + MAKE_CHECK_ARGS: check-build + artifacts: + paths: + - build + +check-crypto-only-gnutls: + <<: *native_test_job_definition + needs: + - job: build-crypto-only-gnutls + artifacts: true + variables: + IMAGE: centos7 + MAKE_CHECK_ARGS: check + +# We don't need to exercise every backend with every front-end +build-trace-multi-user: + <<: *native_build_job_definition + variables: + IMAGE: ubuntu2004 + CONFIGURE_ARGS: --enable-trace-backends=log,simple,syslog --disable-system + +build-trace-ftrace-system: + <<: *native_build_job_definition + variables: + IMAGE: ubuntu2004 + CONFIGURE_ARGS: --enable-trace-backends=ftrace --target-list=x86_64-softmmu + +build-trace-ust-system: + <<: *native_build_job_definition + variables: + IMAGE: ubuntu2004 + CONFIGURE_ARGS: --enable-trace-backends=ust --target-list=x86_64-softmmu + +check-patch: + stage: build + image: $CI_REGISTRY_IMAGE/qemu/centos8:latest + script: .gitlab-ci.d/check-patch.py + except: + variables: + - $CI_PROJECT_NAMESPACE == 'qemu-project' && $CI_COMMIT_BRANCH == 'master' + variables: + GIT_DEPTH: 1000 + allow_failure: true + +check-dco: + stage: build + image: $CI_REGISTRY_IMAGE/qemu/centos8:latest + script: .gitlab-ci.d/check-dco.py + except: + variables: + - $CI_PROJECT_NAMESPACE == 'qemu-project' && $CI_COMMIT_BRANCH == 'master' + variables: + GIT_DEPTH: 1000 + +pages: + image: $CI_REGISTRY_IMAGE/qemu/ubuntu2004:latest + stage: test + needs: + - job: build-system-ubuntu + artifacts: true + script: + - mkdir public + - mv build/docs/index.html public/ + - for i in devel interop specs system tools user ; do mv build/docs/$i public/ ; done + artifacts: + paths: + - public diff --git a/.gitmodules b/.gitmodules index 9c0501a4d4e4ba73c07c423ea9d9ed0884c6d333..2bdeeacef888c03e532e5391bab0500bd3e544e3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -57,4 +57,10 @@ url = https://git.qemu.org/git/opensbi.git [submodule "roms/qboot"] path = roms/qboot - url = https://github.com/bonzini/qboot + url = https://git.qemu.org/git/qboot.git +[submodule "meson"] + path = meson + url = https://git.qemu.org/git/meson.git +[submodule "roms/vbootrom"] + path = roms/vbootrom + url = https://git.qemu.org/git/vbootrom.git diff --git a/.mailmap b/.mailmap index e3628c7a6613b371e0994f897147b062c6c44a36..663819fb0172a0b32e273f0ed695b792b40650cd 100644 --- a/.mailmap +++ b/.mailmap @@ -44,13 +44,19 @@ Aleksandar Markovic Aleksandar Rikalo Aleksandar Rikalo +Alexander Graf Anthony Liguori Anthony Liguori +Filip Bozuta +Frederic Konrad +Greg Kurz James Hogan Leif Lindholm -Paul Burton -Paul Burton -Paul Burton -Philippe Mathieu-DaudĂ© +Radoslaw Biernacki +Paul Burton +Paul Burton +Paul Burton +Paul Burton +Stefan Brankovic Yongbok Kim # Also list preferred name forms where people have changed their @@ -79,6 +85,7 @@ Christophe Lyon Collin L. Walling Daniel P. BerrangĂ© Eduardo Otubo +Erik Smit Fabrice Desclaux Fernando Luis VĂĄzquez Cao Fernando Luis VĂĄzquez Cao @@ -136,6 +143,7 @@ Roger Pau MonnĂ© Shin'ichiro Kawasaki Shin'ichiro Kawasaki Sochin Jiang +Stefan Berger Takashi Yoshii Thomas Huth Thomas Knych diff --git a/.readthedocs.yml b/.readthedocs.yml index 8355dbc63436faf55cbce8de000fec0b7c9257da..7fb7b8dd61add42f8b374ba53513d205bfa710c8 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -17,4 +17,4 @@ formats: all # we require for other Python in our codebase (our conf.py # enforces this, and some code needs it.) python: - version: 3.5 + version: 3.6 diff --git a/.shippable.yml b/.shippable.yml index 2cce7b568905c74fcc53a26cb23a453aa184d12b..14350e6de8a1e7c6471822322b6d27a6ec7caf27 100644 --- a/.shippable.yml +++ b/.shippable.yml @@ -7,10 +7,6 @@ env: matrix: - IMAGE=debian-amd64 TARGET_LIST=x86_64-softmmu,x86_64-linux-user - - IMAGE=debian-win32-cross - TARGET_LIST=arm-softmmu,i386-softmmu,lm32-softmmu - - IMAGE=debian-win64-cross - TARGET_LIST=aarch64-softmmu,sparc64-softmmu,x86_64-softmmu - IMAGE=debian-armel-cross TARGET_LIST=arm-softmmu,arm-linux-user,armeb-linux-user - IMAGE=debian-armhf-cross @@ -26,12 +22,10 @@ env: - IMAGE=debian-ppc64el-cross TARGET_LIST=ppc64-softmmu,ppc64-linux-user,ppc64abi32-linux-user build: - pre_ci: - - make docker-image-${IMAGE} V=1 pre_ci_boot: - image_name: qemu - image_tag: ${IMAGE} - pull: false + image_name: registry.gitlab.com/qemu-project/qemu/qemu/${IMAGE} + image_tag: latest + pull: true options: "-e HOME=/root" ci: - unset CC diff --git a/.travis.yml b/.travis.yml index 1ec8a7b46574ad77ec81a9ec1a27cf51624596b2..1f80bdb6249b73fc4c3d4d6f23ce6e4f0bcf3d14 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ # Additional builds with specific requirements for a full VM need to # be added as additional matrix: entries later on os: linux -dist: xenial +dist: focal language: c compiler: - gcc @@ -10,7 +10,7 @@ cache: # There is one cache per branch and compiler version. # characteristics of each job are used to identify the cache: # - OS name (currently only linux) - # - OS distribution (for Linux, xenial, trusty, or precise) + # - OS distribution (for Linux, bionic or focal) # - Names and values of visible environment variables set in .travis.yml or Settings panel timeout: 1200 ccache: true @@ -27,7 +27,7 @@ addons: - libattr1-dev - libbrlapi-dev - libcap-ng-dev - - libgcc-4.8-dev + - libgcc-7-dev - libgnutls28-dev - libgtk-3-dev - libiscsi-dev @@ -49,6 +49,7 @@ addons: - libvdeplug-dev - libvte-2.91-dev - libzstd-dev + - ninja-build - sparse - uuid-dev - gcovr @@ -94,7 +95,7 @@ before_install: # Configure step - may be overridden before_script: - mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR} - - ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; } + - ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log meson-logs/meson-log.txt && exit 1; } # Main build & test - rarely overridden - controlled by TEST_CMD script: @@ -123,22 +124,8 @@ jobs: - CONFIG="--disable-system --static" - CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default" - - # we split the system builds as it takes a while to build them all - - name: "GCC (main-softmmu)" - env: - - CONFIG="--disable-user --target-list=${MAIN_SOFTMMU_TARGETS}" - - CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default" - - - - name: "GCC (other-softmmu)" - env: - - CONFIG="--disable-user --target-list-exclude=${MAIN_SOFTMMU_TARGETS}" - - CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default" - - # Just build tools and run minimal unit and softfloat checks - - name: "GCC check-softfloat (user)" + - name: "GCC check-unit and check-softfloat" env: - BASE_CONFIG="--enable-tools" - CONFIG="--disable-user --disable-system" @@ -159,12 +146,6 @@ jobs: - CONFIG="--enable-debug-tcg --disable-system" - CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg" - - - name: "GCC some libs disabled (main-softmmu)" - env: - - CONFIG="--disable-linux-aio --disable-cap-ng --disable-attr --disable-brlapi --disable-libusb --disable-replication --target-list=${MAIN_SOFTMMU_TARGETS}" - - # Module builds are mostly of interest to major distros - name: "GCC modules (main-softmmu)" env: @@ -197,40 +178,48 @@ jobs: addons: apt: packages: + - ninja-build - python3-sphinx - - texinfo - perl # Test with Clang for compile portability (Travis uses clang-5.0) - name: "Clang (user)" env: - - CONFIG="--disable-system" + - CONFIG="--disable-system --host-cc=clang --cxx=clang++" - CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-default" compiler: clang - name: "Clang (main-softmmu)" env: - - CONFIG="--target-list=${MAIN_SOFTMMU_TARGETS} " + - CONFIG="--target-list=${MAIN_SOFTMMU_TARGETS} + --host-cc=clang --cxx=clang++" - CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-sanitize" compiler: clang before_script: - mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR} - - ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-fsanitize=undefined -Werror" || { cat config.log && exit 1; } + - ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-fsanitize=undefined -Werror" || { cat config.log meson-logs/meson-log.txt && exit 1; } - name: "Clang (other-softmmu)" env: - - CONFIG="--disable-user --target-list-exclude=${MAIN_SOFTMMU_TARGETS}" + - CONFIG="--disable-user --target-list-exclude=${MAIN_SOFTMMU_TARGETS} + --host-cc=clang --cxx=clang++" - CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-default" compiler: clang # gprof/gcov are GCC features - name: "GCC gprof/gcov" + dist: bionic + addons: + apt: + packages: + - ninja-build env: - - CONFIG="--enable-gprof --enable-gcov --disable-pie --target-list=${MAIN_SOFTMMU_TARGETS}" + - CONFIG="--enable-gprof --enable-gcov --disable-libssh + --target-list=${MAIN_SOFTMMU_TARGETS}" after_success: - ${SRC_DIR}/scripts/travis/coverage-summary.sh @@ -243,75 +232,9 @@ jobs: - TEST_CMD="" - # Check the TCG interpreter (TCI) - - name: "GCC TCI" - env: - - CONFIG="--enable-debug-tcg --enable-tcg-interpreter --disable-kvm --disable-containers - --target-list=alpha-softmmu,arm-softmmu,hppa-softmmu,m68k-softmmu,microblaze-softmmu,moxie-softmmu,ppc-softmmu,s390x-softmmu,x86_64-softmmu" - - TEST_CMD="make check-qtest check-tcg V=1" - - - # We don't need to exercise every backend with every front-end - - name: "GCC trace log,simple,syslog (user)" - env: - - CONFIG="--enable-trace-backends=log,simple,syslog --disable-system" - - TEST_CMD="" - - - - name: "GCC trace ftrace (x86_64-softmmu)" - env: - - CONFIG="--enable-trace-backends=ftrace --target-list=x86_64-softmmu" - - TEST_CMD="" - - - - name: "GCC trace ust (x86_64-softmmu)" - env: - - CONFIG="--enable-trace-backends=ust --target-list=x86_64-softmmu" - - TEST_CMD="" - - - # Python builds - - name: "GCC Python 3.5 (x86_64-softmmu)" - env: - - CONFIG="--target-list=x86_64-softmmu" - - CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default" - language: python - python: 3.5 - - - - name: "GCC Python 3.6 (x86_64-softmmu)" - env: - - CONFIG="--target-list=x86_64-softmmu" - - CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default" - language: python - python: 3.6 - - - # Acceptance (Functional) tests - - name: "GCC check-acceptance" - dist: bionic - env: - - CONFIG="--enable-tools --target-list=aarch64-softmmu,alpha-softmmu,arm-softmmu,m68k-softmmu,microblaze-softmmu,mips-softmmu,mips64el-softmmu,nios2-softmmu,or1k-softmmu,ppc-softmmu,ppc64-softmmu,s390x-softmmu,sparc-softmmu,x86_64-softmmu,xtensa-softmmu" - - TEST_CMD="make check-acceptance" - - CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-acceptance" - after_script: - - python3 -c 'import json; r = json.load(open("tests/results/latest/results.json")); [print(t["logfile"]) for t in r["tests"] if t["status"] not in ("PASS", "SKIP")]' | xargs cat - - du -chs $HOME/avocado/data/cache - addons: - apt: - packages: - - python3-pil - - python3-pip - - python3-numpy - - python3-opencv - - python3-venv - - rpm2cpio - - tesseract-ocr - - tesseract-ocr-eng - - # Using newer GCC with sanitizers - name: "GCC9 with sanitizers (softmmu)" + dist: bionic addons: apt: update: true @@ -327,7 +250,7 @@ jobs: - libattr1-dev - libbrlapi-dev - libcap-ng-dev - - libgnutls-dev + - libgnutls28-dev - libgtk-3-dev - libiscsi-dev - liblttng-ust-dev @@ -335,70 +258,33 @@ jobs: - libncurses5-dev - libnss3-dev - libpixman-1-dev - - libpng12-dev + - libpng-dev - librados-dev - libsdl2-dev - libsdl2-image-dev - libseccomp-dev - libspice-protocol-dev - libspice-server-dev - - libssh-dev - liburcu-dev - libusb-1.0-0-dev - libvte-2.91-dev + - ninja-build - sparse - uuid-dev language: generic compiler: none env: - COMPILER_NAME=gcc CXX=g++-9 CC=gcc-9 - - CONFIG="--cc=gcc-9 --cxx=g++-9 --disable-pie --disable-linux-user" + - CONFIG="--cc=gcc-9 --cxx=g++-9 --disable-linux-user" - TEST_CMD="" before_script: - mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR} - - ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-g3 -O0 -Wno-error=stringop-truncation -fsanitize=thread" --extra-ldflags="-fuse-ld=gold" || { cat config.log && exit 1; } - - - # Run check-tcg against linux-user - - name: "GCC check-tcg (user)" - env: - - CONFIG="--disable-system --enable-debug-tcg" - - TEST_BUILD_CMD="make build-tcg" - - TEST_CMD="make check-tcg" - - CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-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 - - name: "GCC plugins check-tcg (user)" - env: - - CONFIG="--disable-system --enable-plugins --enable-debug-tcg --target-list-exclude=sparc64-linux-user,cris-linux-user" - - TEST_BUILD_CMD="make build-tcg" - - TEST_CMD="make check-tcg" - - CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg" + - ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-g3 -O0 -fsanitize=thread" || { cat config.log meson-logs/meson-log.txt && exit 1; } - # Run check-tcg against softmmu targets - - name: "GCC check-tcg (some-softmmu)" - env: - - CONFIG="--enable-debug-tcg --target-list=xtensa-softmmu,arm-softmmu,aarch64-softmmu,alpha-softmmu" - - TEST_BUILD_CMD="make build-tcg" - - TEST_CMD="make check-tcg" - - CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg" - - - # Run check-tcg against softmmu targets (with plugins) - - name: "GCC plugins check-tcg (some-softmmu)" - env: - - CONFIG="--enable-plugins --enable-debug-tcg --target-list=xtensa-softmmu,arm-softmmu,aarch64-softmmu,alpha-softmmu" - - TEST_BUILD_CMD="make build-tcg" - - TEST_CMD="make check-tcg" - - CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg" - - name: "[aarch64] GCC check-tcg" arch: arm64 - dist: xenial + dist: focal addons: apt_packages: - libaio-dev @@ -422,15 +308,17 @@ jobs: - libusb-1.0-0-dev - libvdeplug-dev - libvte-2.91-dev + - ninja-build # Tests dependencies - genisoimage env: - TEST_CMD="make check check-tcg V=1" - CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS}" + - UNRELIABLE=true - name: "[ppc64] GCC check-tcg" arch: ppc64le - dist: xenial + dist: focal addons: apt_packages: - libaio-dev @@ -454,6 +342,7 @@ jobs: - libusb-1.0-0-dev - libvdeplug-dev - libvte-2.91-dev + - ninja-build # Tests dependencies - genisoimage env: @@ -486,13 +375,14 @@ jobs: - libusb-1.0-0-dev - libvdeplug-dev - libvte-2.91-dev + - ninja-build # Tests dependencies - genisoimage env: - TEST_CMD="make check check-tcg V=1" - CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS},s390x-linux-user" + - UNRELIABLE=true script: - - ( cd ${SRC_DIR} ; git submodule update --init roms/SLOF ) - BUILD_RC=0 && make -j${JOBS} || BUILD_RC=$? - | if [ "$BUILD_RC" -eq 0 ] ; then @@ -502,6 +392,47 @@ jobs: $(exit $BUILD_RC); fi + - name: "[s390x] GCC (other-softmmu)" + arch: s390x + dist: bionic + addons: + apt_packages: + - libaio-dev + - libattr1-dev + - libcap-ng-dev + - libgnutls28-dev + - libiscsi-dev + - liblttng-ust-dev + - liblzo2-dev + - libncurses-dev + - libnfs-dev + - libnss3-dev + - libpixman-1-dev + - libsdl2-dev + - libsdl2-image-dev + - libseccomp-dev + - libsnappy-dev + - libzstd-dev + - nettle-dev + - xfslibs-dev + - ninja-build + # Tests dependencies + - genisoimage + env: + - CONFIG="--disable-containers --audio-drv-list=sdl --disable-user + --target-list-exclude=${MAIN_SOFTMMU_TARGETS}" + + - name: "[s390x] GCC (user)" + arch: s390x + dist: bionic + addons: + apt_packages: + - libgcrypt20-dev + - libgnutls28-dev + - ninja-build + env: + - CONFIG="--disable-containers --disable-system" + - name: "[s390x] Clang (disable-tcg)" arch: s390x dist: bionic @@ -529,10 +460,12 @@ jobs: - libusb-1.0-0-dev - libvdeplug-dev - libvte-2.91-dev + - ninja-build env: - TEST_CMD="make check-unit" - CONFIG="--disable-containers --disable-tcg --enable-kvm --disable-tools --host-cc=clang --cxx=clang++" + - UNRELIABLE=true # Release builds # The make-release script expect a QEMU version, so our tag must start with a 'v'. @@ -552,5 +485,7 @@ jobs: - ls -l ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2 - tar -xf ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2 && cd qemu-${QEMU_VERSION} - mkdir -p release-build && cd release-build - - ../configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; } + - ../configure ${BASE_CONFIG} ${CONFIG} || { cat config.log meson-logs/meson-log.txt && exit 1; } - make install + allow_failures: + - env: UNRELIABLE=true diff --git a/CODING_STYLE.rst b/CODING_STYLE.rst index 427699e0e425431ea99d4046e40543bdcc22e9c5..8b13ef0669ebfd31bfbd2fb63890b56e78bb5d3a 100644 --- a/CODING_STYLE.rst +++ b/CODING_STYLE.rst @@ -109,8 +109,41 @@ names are lower_case_with_underscores_ending_with_a_t, like the POSIX uint64_t and family. Note that this last convention contradicts POSIX and is therefore likely to be changed. -When wrapping standard library functions, use the prefix ``qemu_`` to alert -readers that they are seeing a wrapped version; otherwise avoid this prefix. +Variable Naming Conventions +--------------------------- + +A number of short naming conventions exist for variables that use +common QEMU types. For example, the architecture independent CPUState +is often held as a ``cs`` pointer variable, whereas the concrete +CPUArchState is usually held in a pointer called ``env``. + +Likewise, in device emulation code the common DeviceState is usually +called ``dev``. + +Function Naming Conventions +--------------------------- + +Wrapped version of standard library or GLib functions use a ``qemu_`` +prefix to alert readers that they are seeing a wrapped version, for +example ``qemu_strtol`` or ``qemu_mutex_lock``. Other utility functions +that are widely called from across the codebase should not have any +prefix, for example ``pstrcpy`` or bit manipulation functions such as +``find_first_bit``. + +The ``qemu_`` prefix is also used for functions that modify global +emulator state, for example ``qemu_add_vm_change_state_handler``. +However, if there is an obvious subsystem-specific prefix it should be +used instead. + +Public functions from a file or subsystem (declared in headers) tend +to have a consistent prefix to show where they came from. For example, +``tlb_`` for functions from ``cputlb.c`` or ``cpu_`` for functions +from cpus.c. + +If there are two versions of a function to be called with or without a +lock held, the function that expects the lock to be already held +usually uses the suffix ``_locked``. + Block structure =============== diff --git a/Changelog b/Changelog deleted file mode 100644 index 4a90bb9e8b058b7e85b79aff31f3a238c84e63be..0000000000000000000000000000000000000000 --- a/Changelog +++ /dev/null @@ -1,580 +0,0 @@ -This file documents changes for QEMU releases 0.12 and earlier. -For changelog information for later releases, see -https://wiki.qemu.org/ChangeLog or look at the git history for -more detailed information. - - -version 0.12.0: - - - Update to SeaBIOS 0.5.0 - - e1000: fix device link status in Linux (Anthony Liguori) - - monitor: fix QMP for balloon command (Luiz Capitulino) - - QMP: Return an empty dict by default (Luiz Capitulino) - - QMP: Only handle converted commands (Luiz Capitulino) - - pci: support PCI based option rom loading (Gerd Hoffman/Anthony Liguori) - - Fix backcompat for hotplug of SCSI controllers (Daniel P. Berrange) - - fdc: fix migration from 0.11 (Juan Quintela) - - vmware-vga: fix segv on cursor resize. (Dave Airlie) - - vmware-vga: various fixes (Dave Airlie/Anthony Liguori) - - qdev: improve property error reporting. (Gerd Hoffmann) - - fix vga names in default_list (Gerd Hoffmann) - - usb-host: check mon before using it. (Gerd Hoffmann) - - usb-net: use qdev for -usbdevice (Gerd Hoffmann) - - monitor: Catch printing to non-existent monitor (Luiz Capitulino) - - Avoid permanently disabled QEMU monitor when UNIX migration fails (Daniel P. Berrange) - - Fix loading of ELF multiboot kernels (Kevin Wolf) - - qemu-io: Fix memory leak (Kevin Wolf) - - Fix thinko in linuxboot.S (Paolo Bonzini) - - target-i386: Fix evaluation of DR7 register (Jan Kiszka) - - vnc: hextile: do not generate ForegroundSpecified and SubrectsColoured tiles (Anthony Liguori) - - S390: Bail out without KVM (Alexander Graf) - - S390: Don't tell guest we're updating config space (Alexander Graf) - - target-s390: Fail on unknown instructions (Alexander Graf) - - osdep: Fix runtime failure on older Linux kernels (Andre Przywara) - - Fix a make -j race (Juergen Lock) - - target-alpha: Fix generic ctz64. (Richard Henderson) - - s390: Fix buggy assignment (Stefan Weil) - - target-mips: fix user-mode emulation startup (Nathan Froyd) - - target-i386: Update CPUID feature set for TCG (Andre Przywara) - - s390: fix build on 32 bit host (Michael S. Tsirkin) - -version 0.12.0-rc2: - - - v2: properly save kvm system time msr registers (Glauber Costa) - - convert more monitor commands to qmp (Luiz Capitulino) - - vnc: fix capslock tracking logic. (Gerd Hoffmann) - - QemuOpts: allow larger option values. (Gerd Hoffmann) - - scsi: fix drive hotplug. (Gerd Hoffmann) - - pci: don't hw_error() when no slot is available. (Gerd Hoffmann) - - pci: don't abort() when trying to hotplug with acpi off. (Gerd Hoffmann) - - allow default devices to be implemented in config file (Gerd Hoffman) - - vc: colorize chardev title line with blue background. (Gerd Hoffmann) - - chardev: make chardevs specified in config file work. (Gerd Hoffmann) - - qdev: also match bus name for global properties (Gerd Hoffmann) - - qdev: add command line option to set global defaults for properties. (Gerd Hoffmann) - - kvm: x86: Save/restore exception_index (Jan Kiszka) - - qdev: Replace device names containing whitespace (Markus Armbruster) - - fix rtc-td-hack on host without high-res timers (Gleb Natapov) - - virtio: verify features on load (Michael S. Tsirkin) - - vmware_vga: add rom file so that it boots. (Dave Airlie) - - Do not abort on qemu_malloc(0) in production builds (Anthony Liguori) - - Fix ARM userspace strex implementation. (Paul Brook) - - qemu: delete rule target on error (Michael S. Tsirkin) - - QMP: add human-readable description to error response (Markus Armbruster) - - convert more monitor commands to QError (Markus Armbruster) - - monitor: Fix double-prompt after "change vnc passwd BLA" (Markus Armbruster) - - monitor: do_cont(): Don't ask for passwords (Luiz Capitulino) - - monitor: Introduce 'block_passwd' command (Luiz Capitulino) - - pci: interrupt disable bit support (Michael S. Tsirkin) - - pci: interrupt status bit implementation (Michael S. Tsirkin) - - pci: prepare irq code for interrupt state (Michael S. Tsirkin) - - msix: function mask support (Michael S. Tsirkin) - - msix: macro rename for function mask support (Michael S. Tsirkin) - - cpuid: Fix multicore setup on Intel (Andre Przywara) - - kvm: x86: Fix initial kvm_has_msr_star (Jan Kiszka) - - Update OpenBIOS images to r640 (Aurelien Jarno) - -version 0.10.2: - - - fix savevm/loadvm (Anthony Liguori) - - live migration: fix dirty tracking windows (Glauber Costa) - - live migration: improve error propagation (Glauber Costa) - - qcow2: fix image creation for > ~2TB images (Chris Wright) - - hotplug: fix error handling for if= parameter (Eduardo Habkost) - - qcow2: fix data corruption (Nolan Leake) - - virtio: fix guest oops with 2.6.25 kernels (Rusty Russell) - - SH4: add support for -kernel (Takashi Yoshii, Aurelien Jarno) - - hotplug: fix closing of char devices (Jan Kiszka) - - hotplug: remove incorrect check for device name (Eduardo Habkost) - - enable -k on win32 (Herve Poussineau) - - configure: use LANG=C for grep (Andreas Faerber) - - fix VGA regression (malc) - -version 0.10.1: - - - virtio-net: check right return size on sg list (Alex Williamson) - - Make qemu_announce_self handle holes (live migration after hotplug) - (Marcelo Tosatti) - - Revert r6804-r6808 (qcow2 allocation info). This series of changes added - a high cost to startup for large qcow2 images (Anthony Liguori) - - qemu-img: fix help message (Aurelien Jarno) - - Fix build for non-default installs of SDL (Anthony Liguori) - - Fix race condition in env->interrupt_request. When using TCG and a dynticks - host timer, this condition could cause TCG to get stuck in an infinite - loop (Aurelien Jarno) - - Fix reading encrypted hard disk passwords during early startup (Jan Kiszka) - - Fix encrypted disk reporting in 'info block' (Jan Kiszka) - - Fix console size with tiny displays (MusicPal) (Jan Kiszka) - - Improve error handling in bdrv_open2 (Jan Kiszka) - - Avoid leaking data in mux'ed character devices (Jan Kiszka) - - Fix initial character device reset (no banner in monitor) (Jan Kiszka) - - Fix cpuid KVM crash on i386 host (Lubomir Rintel) - - Fix SLES10sp2 installation by adding ISTAT1 register to LSI SCSI emulation - (Ryan Harper) - -version 0.10.0: - - - TCG support (No longer requires GCC 3.x) - - Kernel Virtual Machine acceleration support - - BSD userspace emulation - - Bluetooth emulation and host passthrough support - - GDB XML register description support - - Intel e1000 emulation - - HPET emulation - - VirtIO paravirtual device support - - Marvell 88w8618 / MusicPal emulation - - Nokia N-series tablet emulation / OMAP2 processor emulation - - PCI hotplug support - - Live migration and new save/restore formats - - Curses display support - - qemu-nbd utility to mount supported block formats - - Altivec support in PPC emulation and new firmware (OpenBIOS) - - Multiple VNC clients are now supported - - TLS encryption is now supported in VNC - - MIPS Magnum R4000 machine (HervĂ© Poussineau) - - Braille support (Samuel Thibault) - - Freecom MusicPal system emulation (Jan Kiszka) - - OMAP242x and Nokia N800, N810 machines (Andrzej Zaborowski) - - EsounD audio driver (Frederick Reeve) - - Gravis Ultrasound GF1 sound card (Tibor "TS" SchĂŒtz) - - Many, many, bug fixes and new features - -version 0.9.1: - - - TFTP booting from host directory (Anthony Liguori, Erwan Velu) - - Tap device emulation for Solaris (Sittichai Palanisong) - - Monitor multiplexing to several I/O channels (Jason Wessel) - - ds1225y nvram support (Herve Poussineau) - - CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau) - - Several Sparc fixes (Aurelien Jarno, Blue Swirl, Robert Reif) - - MIPS 64-bit FPU support (Thiemo Seufer) - - Xscale PDA emulation (Andrzej Zaborowski) - - ColdFire system emulation (Paul Brook) - - Improved SH4 support (Magnus Damm) - - MIPS64 support (Aurelien Jarno, Thiemo Seufer) - - Preliminary Alpha guest support (J. Mayer) - - Read-only support for Parallels disk images (Alex Beregszaszi) - - SVM (x86 virtualization) support (Alexander Graf) - - CRIS emulation (Edgar E. Iglesias) - - SPARC32PLUS execution support (Blue Swirl) - - MIPS mipssim pseudo machine (Thiemo Seufer) - - Strace for Linux userland emulation (Stuart Anderson, Thayne Harbaugh) - - OMAP310 MPU emulation plus Palm T|E machine (Andrzej Zaborowski) - - ARM v6, v7, NEON SIMD and SMP emulation (Paul Brook/CodeSourcery) - - Gumstix boards: connex and verdex emulation (Thorsten Zitterell) - - Intel mainstone II board emulation (Armin Kuster) - - VMware SVGA II graphics card support (Andrzej Zaborowski) - -version 0.9.0: - - - Support for relative paths in backing files for disk images - - Async file I/O API - - New qcow2 disk image format - - Support of multiple VM snapshots - - Linux: specific host CDROM and floppy support - - SMM support - - Moved PCI init, MP table init and ACPI table init to Bochs BIOS - - Support for MIPS32 Release 2 instruction set (Thiemo Seufer) - - MIPS Malta system emulation (Aurelien Jarno, Stefan Weil) - - Darwin userspace emulation (Pierre d'Herbemont) - - m68k user support (Paul Brook) - - several x86 and x86_64 emulation fixes - - Mouse relative offset VNC extension (Anthony Liguori) - - PXE boot support (Anthony Liguori) - - '-daemonize' option (Anthony Liguori) - -version 0.8.2: - - - ACPI support - - PC VGA BIOS fixes - - switch to OpenBios for SPARC targets (Blue Swirl) - - VNC server fixes - - MIPS FPU support (Marius Groeger) - - Solaris/SPARC host support (Juergen Keil) - - PPC breakpoints and single stepping (Jason Wessel) - - USB updates (Paul Brook) - - UDP/TCP/telnet character devices (Jason Wessel) - - Windows sparse file support (Frediano Ziglio) - - RTL8139 NIC TCP segmentation offloading (Igor Kovalenko) - - PCNET NIC support (Antony T Curtis) - - Support for variable frequency host CPUs - - Workaround for win32 SMP hosts - - Support for AMD Flash memories (Jocelyn Mayer) - - Audio capture to WAV files support (malc) - -version 0.8.1: - - - USB tablet support (Brad Campbell, Anthony Liguori) - - win32 host serial support (Kazu) - - PC speaker support (Joachim Henke) - - IDE LBA48 support (Jens Axboe) - - SSE3 support - - Solaris port (Juergen Keil) - - Preliminary SH4 target (Samuel Tardieu) - - VNC server (Anthony Liguori) - - slirp fixes (Ed Swierk et al.) - - USB fixes - - ARM Versatile Platform Baseboard emulation (Paul Brook) - -version 0.8.0: - - - ARM system emulation: Arm Integrator/CP board with an arm1026ej-s - cpu (Paul Brook) - - SMP support - - Mac OS X cocoa improvements (Mike Kronenberg) - - Mac OS X CoreAudio driver (Mike Kronenberg) - - DirectSound driver (malc) - - ALSA audio driver (malc) - - new audio options: '-soundhw' and '-audio-help' (malc) - - ES1370 PCI audio device (malc) - - Initial USB support - - Linux host serial port access - - Linux host low level parallel port access - - New network emulation code supporting VLANs. - - MIPS and MIPSel User Linux emulation - - MIPS fixes to boot Linux (Daniel Jacobowitz) - - NX bit support - - Initial SPARC SMP support (Blue Swirl) - - Major overhaul of the virtual FAT driver for read/write support - (Johannes Schindelin) - -version 0.7.2: - - - x86_64 fixes (Win2000 and Linux 2.6 boot in 32 bit) - - merge self modifying code handling in dirty ram page mecanism. - - MIPS fixes (Ralf Baechle) - - better user net performances - -version 0.7.1: - - - read-only Virtual FAT support (Johannes Schindelin) - - Windows 2000 install disk full hack (original idea from Vladimir - N. Oleynik) - - VMDK disk image creation (Filip Navara) - - SPARC64 progress (Blue Swirl) - - initial MIPS support (Jocelyn mayer) - - MIPS improvements (Ralf Baechle) - - 64 bit fixes in user networking (initial patch by Gwenole Beauchesne) - - IOAPIC support (Filip Navara) - -version 0.7.0: - - - better BIOS translation and HDD geometry auto-detection - - user mode networking bug fix - - undocumented FPU ops support - - Cirrus VGA: support for 1280x1024x[8,15,16] modes - - 'pidfile' option - - .dmg disk image format support (Johannes Schindelin) - - keymaps support (initial patch by Johannes Schindelin) - - big endian ARM support (Lennert Buytenhek) - - added generic 64 bit target support - - x86_64 target support - - initial APIC support - - MMX/SSE/SSE2/PNI support - - PC parallel port support (Mark Jonckheere) - - initial SPARC64 support (Blue Swirl) - - SPARC target boots Linux (Blue Swirl) - - armv5te user mode support (Paul Brook) - - ARM VFP support (Paul Brook) - - ARM "Angel" semihosting syscalls (Paul Brook) - - user mode gdb stub support (Paul Brook) - - Samba 3 support - - initial Cocoa support (Pierre d'Herbemont) - - generic FPU emulation code - - Virtual PC read-only disk image support (Alex Beregszaszi) - -version 0.6.1: - - - Mac OS X port (Pierre d'Herbemont) - - Virtual console support - - Better monitor line edition - - New block device layer - - New 'qcow' growable disk image support with AES encryption and - transparent decompression - - VMware 3 and 4 read-only disk image support (untested) - - Support for up to 4 serial ports - - TFTP server support (Magnus Damm) - - Port redirection support in user mode networking - - Support for not executable data sections - - Compressed loop disk image support (Johannes Schindelin) - - Level triggered IRQ fix (aka NE2000 PCI performance fix) (Steve - Wormley) - - Fixed Fedora Core 2 problems (now you can run qemu without any - LD_ASSUME_KERNEL tricks on FC2) - - DHCP fix for Windows (accept DHCPREQUEST alone) - - SPARC system emulation (Blue Swirl) - - Automatic Samba configuration for host file access from Windows. - - '-loadvm' and '-full-screen' options - - ne2000 savevm support (Johannes Schindelin) - - Ctrl-Alt is now the default grab key. Ctrl-Alt-[0-9] switches to - the virtual consoles. - - BIOS floppy fix for NT4 (Mike Nordell, Derek Fawcus, Volker Ruppert) - - Floppy fixes for NT4 and NT5 (Mike Nordell) - - NT4 IDE fixes (Ben Pfaf, Mike Nordell) - - SDL Audio support and SB16 fixes (malc) - - ENTER instruction bug fix (initial patch by Stefan Kisdaroczi) - - VGA font change fix - - VGA read-only CRTC register fix - -version 0.6.0: - - - minimalist FPU exception support (NetBSD FPU probe fix) - - cr0.ET fix (Win95 boot) - - *BSD port (Markus Niemisto) - - I/O access fix (signaled by Mark Jonckheere) - - IDE drives serial number fix (Mike Nordell) - - int13 CDROM BIOS fix (aka Solaris x86 install CD fix) - - int15, ah=86 BIOS fix (aka Solaris x86 hardware probe hang up fix) - - BSR/BSF "undefined behaviour" fix - - vmdk2raw: convert VMware disk images to raw images - - PCI support - - NE2K PCI support - - dummy VGA PCI support - - VGA font selection fix (Daniel Serpell) - - PIC reset fix (Hidemi KAWAI) - - PIC spurious irq support (aka Solaris install bug) - - added '-localtime' option - - Cirrus CL-GD54xx VGA support (initial patch by Makoto Suzuki (suzu)) - - APM and system shutdown support - - Fixed system reset - - Support for other PC BIOSes - - Initial PowerMac hardware emulation - - PowerMac/PREP OpenFirmware compatible BIOS (Jocelyn Mayer) - - initial IDE BMDMA support (needed for Darwin x86) - - Set the default memory size for PC emulation to 128 MB - -version 0.5.5: - - - SDL full screen support (initial patch by malc) - - VGA support on PowerPC PREP - - VBE fixes (Matthew Mastracci) - - PIT fixes (aka Win98 hardware probe and "VGA slowness" bug) - - IDE master only fixes (aka Win98 CD-ROM probe bug) - - ARM load/store half word fix (Ulrich Hecht) - - FDC fixes for Win98 - -version 0.5.4: - - - qemu-fast fixes - - BIOS area protection fix (aka EMM386.EXE fix) (Mike Nordell) - - keyboard/mouse fix (Mike Nordell) - - IDE fixes (Linux did not recognized slave drivers) - - VM86 EIP masking fix (aka NT5 install fix) (Mike Nordell) - - QEMU can now boot a PowerPC Linux kernel (Jocelyn Mayer) - - User mode network stack - - imul imm8 fix + 0x82 opcode support (Hidemi KAWAI) - - precise self modifying code (aka BeOS install bug) - -version 0.5.3: - - - added Bochs VESA VBE support - - VGA memory map mode 3 access fix (OS/2 install fix) - - IDE fixes (Jens Axboe) - - CPU interrupt fixes - - fixed various TLB invalidation cases (NT install) - - fixed cr0.WP semantics (XP install) - - direct chaining support for SPARC and PowerPC (faster) - - ARM NWFPE support (initial patch by Ulrich Hecht) - - added specific x86 to x86 translator (close to native performance - in qemu-i386 and qemu-fast) - - shm syscalls support (Paul McKerras) - - added accurate CR0.MP/ME/TS emulation - - fixed DMA memory write access (Win95 boot floppy fix) - - graphical x86 linux loader - - command line monitor - - generic removable device support - - support of CD-ROM change - - multiple network interface support - - initial x86-64 host support (Gwenole Beauchesne) - - lret to outer privilege fix (OS/2 install fix) - - task switch fixes (SkyOS boot) - - VM save/restore commands - - new timer API - - more precise RTC emulation (periodic timers + time updates) - - Win32 port (initial patch by Kazu) - -version 0.5.2: - - - improved soft MMU speed (assembly functions and specializing) - - improved multitasking speed by avoiding flushing TBs when - switching tasks - - improved qemu-fast speed - - improved self modifying code handling (big performance gain in - softmmu mode). - - fixed IO checking - - fixed CD-ROM detection (win98 install CD) - - fixed addseg real mode bug (GRUB boot fix) - - added ROM memory support (win98 boot) - - fixed 'call Ev' in case of paging exception - - updated the script 'qemu-binfmt-conf.sh' to use QEMU automagically - when launching executables for the supported target CPUs. - - PowerPC system emulation update (Jocelyn Mayer) - - PC floppy emulation and DMA fixes (Jocelyn Mayer) - - polled mode for PIC (Jocelyn Mayer) - - fixed PTE dirty bit handling - - fixed xadd same reg bug - - fixed cmpxchg exception safeness - - access to virtual memory in gdb stub - - task gate and NT flag fixes - - eflags optimisation fix for string operations - -version 0.5.1: - - - float access fixes when using soft mmu - - PC emulation support on PowerPC - - A20 support - - IDE CD-ROM emulation - - ARM fixes (Ulrich Hecht) - - SB16 emulation (malc) - - IRET and INT fixes in VM86 mode with IOPL=3 - - Port I/Os use TSS io map - - Full task switching/task gate support - - added verr, verw, arpl, fcmovxx - - PowerPC target support (Jocelyn Mayer) - - Major SPARC target fixes (dynamically linked programs begin to work) - -version 0.5.0: - - - full hardware level VGA emulation - - graphical display with SDL - - added PS/2 mouse and keyboard emulation - - popw (%esp) fix - - mov to/from segment data width fix - - added real mode support - - added Bochs BIOS and LGPL'ed VGA BIOS loader in qemu - - m68k host port (Richard Zidlicky) - - partial soft MMU support for memory mapped I/Os - - multi-target build - - fixed: no error code in hardware interrupts - - fixed: pop ss, mov ss, x and sti disable hardware irqs for the next insn - - correct single stepping through string operations - - preliminary SPARC target support (Thomas M. Ogrisegg) - - tun-fd option (Rusty Russell) - - automatic IDE geometry detection - - renamed 'vl' to qemu[-fast] and user qemu to qemu-{cpu}. - - added man page - - added full soft mmu mode to launch unpatched OSes. - -version 0.4.3: - - - x86 exception fix in case of nop instruction. - - gcc 3.2.2 bug workaround (RedHat 9 fix) - - sparc and Alpha host fixes - - many ARM target fixes: 'ls' and 'bash' can be launched. - -version 0.4.2: - - - many exception handling fixes (can compile a Linux kernel inside vl) - - IDE emulation support - - initial GDB stub support - - deferred update support for disk images (Rusty Russell) - - accept User Mode Linux Copy On Write disk images - - SMP kernels can at least be booted - -version 0.4.1: - - - more accurate timer support in vl. - - more reliable NE2000 probe in vl. - - added 2.5.66 kernel in vl-test. - - added VLTMPDIR environment variable in vl. - -version 0.4: - - - initial support for ring 0 x86 processor emulation - - fixed signal handling for correct dosemu DPMI emulation - - fast x86 MMU emulation with mmap() - - fixed popl (%esp) case - - Linux kernel can be executed by QEMU with the 'vl' command. - -version 0.3: - - - initial support for ARM emulation - - added fnsave, frstor, fnstenv, fldenv FPU instructions - - added FPU register save in signal emulation - - initial ARM port - - Sparc and Alpha ports work on the regression test - - generic ioctl number conversion - - fixed ioctl type conversion - -version 0.2: - - - PowerPC disassembly and ELF symbols output (Rusty Russell) - - flock support (Rusty Russell) - - ugetrlimit support (Rusty Russell) - - fstat64 fix (Rusty Russell) - - initial Alpha port (Falk Hueffner) - - initial IA64 port (Matt Wilson) - - initial Sparc and Sparc64 port (David S. Miller) - - added HLT instruction - - LRET instruction fix. - - added GPF generation for I/Os. - - added INT3 and TF flag support. - - SHL instruction C flag fix. - - mmap emulation for host page size > 4KB - - self-modifying code support - - better VM86 support (dosemu works on non trivial programs) - - precise exception support (EIP is computed correctly in most cases) - - more precise LDT/GDT/IDT emulation - - faster segment load in vm86 mode - - direct chaining of basic blocks (faster emulation) - -version 0.1.6: - - - automatic library search system. QEMU can now work with unpatched - ELF dynamic loader and libc (Rusty Russell). - - ISO C warning fixes (Alistair Strachan) - - first self-virtualizable version (works only as long as the - translation cache is not flushed) - - RH9 fixes - -version 0.1.5: - - - ppc64 support + personality() patch (Rusty Russell) - - first Alpha CPU patches (Falk Hueffner) - - removed bfd.h dependency - - fixed shrd, shld, idivl and divl on PowerPC. - - fixed buggy glibc PowerPC rint() function (test-i386 passes now on PowerPC). - -version 0.1.4: - - - more accurate VM86 emulation (can launch small DOS 16 bit - executables in wine). - - fixed push/pop fs/gs - - added iret instruction. - - added times() syscall and SIOCATMARK ioctl. - -version 0.1.3: - - - S390 support (Ulrich Weigand) - - glibc 2.3.x compile fix (Ulrich Weigand) - - socketcall endian fix (Ulrich Weigand) - - struct sockaddr endian fix (Ulrich Weigand) - - sendmsg/recvmsg endian fix (Ulrich Weigand) - - execve endian fix (Ulrich Weigand) - - fdset endian fix (Ulrich Weigand) - - partial setsockopt syscall support (Ulrich Weigand) - - more accurate pushf/popf emulation - - first partial vm86() syscall support (can be used with runcom example). - - added bound, cmpxchg8b, cpuid instructions - - added 16 bit addressing support/override for string operations - - poll() fix - -version 0.1.2: - - - compile fixes - - xlat instruction - - xchg instruction memory lock - - added simple vm86 example (not working with QEMU yet). The 54 byte - DOS executable 'pi_10.com' program was released by Bertram - Felgenhauer (more information at http://www.boo.net/~jasonp/pipage.html). - -version 0.1.1: - - - glibc 2.2 compilation fixes - - added -s and -L options - - binary distribution of x86 glibc and wine - - big endian fixes in ELF loader and getdents. - -version 0.1: - - - initial public release. diff --git a/Kconfig b/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..bf694c42afe83fd7992674aef545d8a92aa5e1fb --- /dev/null +++ b/Kconfig @@ -0,0 +1,4 @@ +source Kconfig.host +source backends/Kconfig +source accel/Kconfig +source hw/Kconfig diff --git a/Kconfig.host b/Kconfig.host index 55136e037d83a4981fa57201726ecb929a9a6b80..a9a55a9c315cd3560d4758f2c43b0e90a13a112e 100644 --- a/Kconfig.host +++ b/Kconfig.host @@ -1,9 +1,6 @@ # These are "proxy" symbols used to pass config-host.mak values -# down to Kconfig. See also MINIKCONF_ARGS in the Makefile: -# these two need to be kept in sync. - -config KVM - bool +# down to Kconfig. See also kconfig_external_symbols in +# meson.build: these two need to be kept in sync. config LINUX bool @@ -27,13 +24,13 @@ config VHOST_USER bool select VHOST -config VHOST_KERNEL +config VHOST_VDPA bool select VHOST -config XEN +config VHOST_KERNEL bool - select FSDEV_9P if VIRTFS + select VHOST config VIRTFS bool diff --git a/MAINTAINERS b/MAINTAINERS index a209b5d8cef0980344f3d7c8d24495492a866bb1..68bc160f41bc202f4e661b2d651dfecdbf486fd1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -85,6 +85,7 @@ Architecture support -------------------- S390 general architecture support M: Cornelia Huck +M: Thomas Huth S: Supported F: default-configs/s390x-softmmu.mak F: gdb-xml/s390*.xml @@ -111,12 +112,11 @@ L: qemu-s390x@nongnu.org Guest CPU cores (TCG) --------------------- Overall TCG CPUs -M: Richard Henderson +M: Richard Henderson R: Paolo Bonzini S: Maintained -F: cpus.c +F: softmmu/cpus.c F: cpus-common.c -F: exec.c F: accel/tcg/ F: accel/stubs/tcg-stub.c F: scripts/decodetree.py @@ -138,7 +138,7 @@ F: include/fpu/ F: tests/fp/ Alpha TCG CPUs -M: Richard Henderson +M: Richard Henderson S: Maintained F: target/alpha/ F: tests/tcg/alpha/ @@ -158,6 +158,7 @@ F: disas/arm.c F: disas/arm-a64.cc F: disas/libvixl/ F: docs/system/target-arm.rst +F: docs/system/arm/cpu-features.rst ARM SMMU M: Eric Auger @@ -166,6 +167,15 @@ S: Maintained F: hw/arm/smmu* F: include/hw/arm/smmu* +AVR TCG CPUs +M: Michael Rolnik +R: Sarah Harris +S: Maintained +F: docs/system/target-avr.rst +F: gdb-xml/avr-cpu.xml +F: target/avr/ +F: tests/acceptance/machine_avr6.py + CRIS TCG CPUs M: Edgar E. Iglesias S: Maintained @@ -176,7 +186,7 @@ F: tests/tcg/cris/ F: disas/cris.c HPPA (PA-RISC) TCG CPUs -M: Richard Henderson +M: Richard Henderson S: Maintained F: target/hppa/ F: hw/hppa/ @@ -211,13 +221,14 @@ F: hw/microblaze/ F: disas/microblaze.c MIPS TCG CPUs -M: Aleksandar Markovic +M: Philippe Mathieu-DaudĂ© R: Aurelien Jarno +R: Jiaxun Yang R: Aleksandar Rikalo -S: Maintained +S: Odd Fixes F: target/mips/ F: default-configs/*mips* -F: disas/*mips* +F: disas/mips.c F: docs/system/cpu-models-mips.rst.inc F: hw/intc/mips_gic.c F: hw/mips/ @@ -227,11 +238,13 @@ F: include/hw/intc/mips_gic.h F: include/hw/mips/ F: include/hw/misc/mips_* F: include/hw/timer/mips_gictimer.h -F: tests/acceptance/linux_ssh_mips_malta.py -F: tests/acceptance/machine_mips_malta.py F: tests/tcg/mips/ K: ^Subject:.*(?i)mips +MIPS TCG CPUs (nanoMIPS ISA) +S: Orphan +F: disas/nanomips.* + Moxie TCG CPUs M: Anthony Green S: Maintained @@ -281,11 +294,11 @@ F: linux-user/host/riscv64/ RENESAS RX CPUs M: Yoshinori Sato -S: Maintained +S: Odd Fixes F: target/rx/ S390 TCG CPUs -M: Richard Henderson +M: Richard Henderson M: David Hildenbrand S: Maintained F: target/s390x/ @@ -295,7 +308,7 @@ F: tests/tcg/s390x/ L: qemu-s390x@nongnu.org SH4 TCG CPUs -M: Aurelien Jarno +M: Yoshinori Sato S: Odd Fixes F: target/sh4/ F: hw/sh4/ @@ -321,7 +334,7 @@ F: include/hw/unicore32/ X86 TCG CPUs M: Paolo Bonzini -M: Richard Henderson +M: Richard Henderson M: Eduardo Habkost S: Maintained F: target/i386/ @@ -361,7 +374,7 @@ Overall KVM CPUs M: Paolo Bonzini L: kvm@vger.kernel.org S: Supported -F: */kvm.* +F: */*/kvm* F: accel/kvm/ F: accel/stubs/kvm-stub.c F: include/hw/kvm/ @@ -375,7 +388,7 @@ S: Maintained F: target/arm/kvm.c MIPS KVM CPUs -M: Aleksandar Markovic +M: Huacai Chen S: Odd Fixes F: target/mips/kvm.c @@ -415,8 +428,21 @@ S: Supported F: target/i386/kvm.c F: scripts/kvm/vmxcap +Guest CPU Cores (other accelerators) +------------------------------------ +Overall +M: Richard Henderson +R: Paolo Bonzini +S: Maintained +F: include/sysemu/accel.h +F: accel/accel.c +F: accel/Makefile.objs +F: accel/stubs/Makefile.objs + X86 HVF CPUs +M: Cameron Esfahani M: Roman Bolshakov +W: https://wiki.qemu.org/Features/HVF S: Maintained F: accel/stubs/hvf-stub.c F: target/i386/hvf/ @@ -426,6 +452,7 @@ WHPX CPUs M: Sunil Muthuswamy S: Supported F: target/i386/whpx-all.c +F: target/i386/whpx-cpus.c F: target/i386/whp-dispatch.h F: accel/stubs/whpx-stub.c F: include/sysemu/whpx.h @@ -439,6 +466,7 @@ M: Paul Durrant L: xen-devel@lists.xenproject.org S: Supported F: */xen* +F: accel/xen/* F: hw/9pfs/xen-9p* F: hw/char/xen_console.c F: hw/display/xenfb.c @@ -452,7 +480,9 @@ F: hw/i386/xen/ F: hw/pci-host/xen_igd_pt.c F: include/hw/block/dataplane/xen* F: include/hw/xen/ +F: include/sysemu/xen.h F: include/sysemu/xen-mapcache.h +F: stubs/xen-hw-stub.c Guest CPU Cores (HAXM) --------------------- @@ -462,6 +492,7 @@ M: Colin Xu L: haxm-team@intel.com W: https://github.com/intel/haxm/issues S: Maintained +F: accel/stubs/hax-stub.c F: include/sysemu/hax.h F: target/i386/hax-* @@ -504,7 +535,7 @@ F: qemu.nsi Alpha Machines -------------- -M: Richard Henderson +M: Richard Henderson S: Maintained F: hw/alpha/ F: hw/isa/smc37c669-superio.c @@ -528,7 +559,7 @@ S: Maintained F: hw/*/allwinner-h3* F: include/hw/*/allwinner-h3* F: hw/arm/orangepi.c -F: docs/system/orangepi.rst +F: docs/system/arm/orangepi.rst ARM PrimeCell and CMSDK devices M: Peter Maydell @@ -609,6 +640,7 @@ F: include/hw/arm/digic.h F: hw/*/digic* F: include/hw/*/digic* F: tests/acceptance/machine_arm_canona1100.py +F: docs/system/arm/digic.rst Goldfish RTC M: Anup Patel @@ -624,6 +656,7 @@ R: Philippe Mathieu-DaudĂ© L: qemu-arm@nongnu.org S: Odd Fixes F: hw/arm/gumstix.c +F: docs/system/arm/gumstix.rst i.MX25 PDK M: Peter Maydell @@ -720,6 +753,18 @@ S: Odd Fixes F: hw/arm/musicpal.c F: docs/system/arm/musicpal.rst +Nuvoton NPCM7xx +M: Havard Skinnemoen +M: Tyrone Ting +L: qemu-arm@nongnu.org +S: Supported +F: hw/*/npcm7xx* +F: include/hw/*/npcm7xx* +F: tests/qtest/npcm7xx* +F: pc-bios/npcm7xx_bootrom.bin +F: roms/vbootrom +F: docs/system/arm/nuvoton.rst + nSeries M: Andrzej Zaborowski M: Peter Maydell @@ -758,6 +803,7 @@ F: hw/arm/raspi_platform.h F: hw/*/bcm283* F: include/hw/arm/raspi* F: include/hw/*/bcm283* +F: docs/system/arm/raspi.rst Real View M: Peter Maydell @@ -784,6 +830,7 @@ F: hw/gpio/max7310.c F: hw/gpio/zaurus.c F: hw/misc/mst_fpga.c F: hw/misc/max111x.c +F: include/hw/misc/max111x.h F: include/hw/arm/pxa.h F: include/hw/arm/sharpsl.h F: include/hw/display/tc6393xb.h @@ -805,12 +852,13 @@ F: include/hw/misc/imx6_*.h F: include/hw/ssi/imx_spi.h SBSA-REF -M: Radoslaw Biernacki +M: Radoslaw Biernacki M: Peter Maydell R: Leif Lindholm L: qemu-arm@nongnu.org S: Maintained F: hw/arm/sbsa-ref.c +F: docs/system/arm/sbsa.rst Sharp SL-5500 (Collie) PDA M: Peter Maydell @@ -818,6 +866,7 @@ L: qemu-arm@nongnu.org S: Odd Fixes F: hw/arm/collie.c F: hw/arm/strongarm* +F: docs/system/arm/collie.rst Stellaris M: Peter Maydell @@ -839,6 +888,7 @@ M: Peter Maydell L: qemu-arm@nongnu.org S: Maintained F: hw/*/versatile* +F: include/hw/i2c/arm_sbcon_i2c.h F: hw/misc/arm_sysctl.c F: docs/system/arm/versatile.rst @@ -848,6 +898,7 @@ L: qemu-arm@nongnu.org S: Maintained F: hw/arm/virt* F: include/hw/arm/virt.h +F: docs/system/arm/virt.rst Xilinx Zynq M: Edgar E. Iglesias @@ -861,7 +912,7 @@ F: hw/misc/zynq* F: include/hw/misc/zynq* X: hw/ssi/xilinx_* -Xilinx ZynqMP +Xilinx ZynqMP and Versal M: Alistair Francis M: Edgar E. Iglesias M: Peter Maydell @@ -872,6 +923,7 @@ F: include/hw/*/xlnx*.h F: include/hw/ssi/xilinx_spips.h F: hw/display/dpcd.c F: include/hw/display/dpcd.h +F: docs/system/arm/xlnx-versal-virt.rst ARM ACPI Subsystem M: Shannon Zhao @@ -951,6 +1003,7 @@ F: include/hw/*/*aspeed* F: include/hw/misc/pca9552*.h F: hw/net/ftgmac100.c F: include/hw/net/ftgmac100.h +F: docs/system/arm/aspeed.rst NRF51 M: Joel Stanley @@ -963,6 +1016,28 @@ F: include/hw/*/nrf51*.h F: include/hw/*/microbit*.h F: tests/qtest/microbit-test.c +AVR Machines +------------- + +AVR MCUs +M: Michael Rolnik +R: Sarah Harris +S: Maintained +F: default-configs/avr-softmmu.mak +F: hw/avr/ +F: include/hw/char/avr_usart.h +F: hw/char/avr_usart.c +F: include/hw/timer/avr_timer16.h +F: hw/timer/avr_timer16.c +F: include/hw/misc/avr_power.h +F: hw/misc/avr_power.c + +Arduino +M: Philippe Mathieu-DaudĂ© +R: Sarah Harris +S: Maintained +F: hw/avr/arduino.c + CRIS Machines ------------- Axis Dev88 @@ -974,7 +1049,7 @@ F: hw/*/etraxfs_*.c HP-PARISC Machines ------------------ HP B160L -M: Richard Henderson +M: Richard Henderson R: Helge Deller S: Odd Fixes F: default-configs/hppa-softmmu.mak @@ -1055,10 +1130,9 @@ F: hw/display/jazz_led.c F: hw/dma/rc4030.c Malta -M: Aleksandar Markovic M: Philippe Mathieu-DaudĂ© R: Aurelien Jarno -S: Maintained +S: Odd Fixes F: hw/isa/piix4.c F: hw/acpi/piix4.c F: hw/mips/malta.c @@ -1068,23 +1142,14 @@ F: tests/acceptance/linux_ssh_mips_malta.py F: tests/acceptance/machine_mips_malta.py Mipssim -M: Aleksandar Markovic R: Aleksandar Rikalo -S: Odd Fixes +S: Orphaned F: hw/mips/mipssim.c F: hw/net/mipsnet.c -R4000 -M: Aleksandar Markovic -R: Aurelien Jarno -R: Aleksandar Rikalo -S: Obsolete -F: hw/mips/r4k.c - Fuloong 2E M: Huacai Chen M: Philippe Mathieu-DaudĂ© -M: Aleksandar Markovic R: Jiaxun Yang S: Odd Fixes F: hw/mips/fuloong2e.c @@ -1092,10 +1157,16 @@ F: hw/isa/vt82c686.c F: hw/pci-host/bonito.c F: include/hw/isa/vt82c686.h +Loongson-3 virtual platforms +M: Huacai Chen +R: Jiaxun Yang +S: Maintained +F: hw/intc/loongson_liointc.c + Boston -M: Paul Burton +M: Paul Burton R: Aleksandar Rikalo -S: Maintained +S: Odd Fixes F: hw/core/loader-fit.c F: hw/mips/boston.c F: hw/pci-host/xilinx-pcie.c @@ -1215,7 +1286,9 @@ S: Maintained F: hw/ppc/pnv* F: hw/intc/pnv* F: hw/intc/xics_pnv.c +F: hw/pci-host/pnv* F: include/hw/ppc/pnv* +F: include/hw/pci-host/pnv* F: pc-bios/skiboot.lid F: tests/qtest/pnv* @@ -1238,19 +1311,60 @@ F: pc-bios/canyonlands.dt[sb] F: pc-bios/u-boot-sam460ex-20100605.bin F: roms/u-boot-sam460ex +RISC-V Machines +--------------- +OpenTitan +M: Alistair Francis +L: qemu-riscv@nongnu.org +S: Supported +F: hw/riscv/opentitan.c +F: hw/char/ibex_uart.c +F: hw/intc/ibex_plic.c +F: include/hw/riscv/opentitan.h +F: include/hw/char/ibex_uart.h +F: include/hw/intc/ibex_plic.h + +Microchip PolarFire SoC Icicle Kit +M: Bin Meng +L: qemu-riscv@nongnu.org +S: Supported +F: hw/riscv/microchip_pfsoc.c +F: hw/char/mchp_pfsoc_mmuart.c +F: hw/misc/mchp_pfsoc_dmc.c +F: hw/misc/mchp_pfsoc_ioscb.c +F: hw/misc/mchp_pfsoc_sysreg.c +F: include/hw/riscv/microchip_pfsoc.h +F: include/hw/char/mchp_pfsoc_mmuart.h +F: include/hw/misc/mchp_pfsoc_dmc.h +F: include/hw/misc/mchp_pfsoc_ioscb.h +F: include/hw/misc/mchp_pfsoc_sysreg.h + +RX Machines +----------- +rx-gdbsim +M: Yoshinori Sato +S: Odd Fixes +F: docs/system/target-rx.rst +F: hw/rx/rx-gdbsim.c +F: tests/acceptance/machine_rx_gdbsim.py + SH4 Machines ------------ R2D -M: Magnus Damm -S: Maintained +M: Yoshinori Sato +R: Magnus Damm +S: Odd Fixes F: hw/sh4/r2d.c F: hw/intc/sh_intc.c -F: hw/timer/sh_timer.c +F: include/hw/sh4/sh_intc.h Shix -M: Magnus Damm +M: Yoshinori Sato +R: Magnus Damm S: Odd Fixes F: hw/sh4/shix.c +F: hw/intc/sh_intc.c +F: include/hw/sh4/sh_intc.h SPARC Machines -------------- @@ -1280,6 +1394,7 @@ F: include/hw/pci-host/sabre.h F: hw/pci-bridge/simba.c F: include/hw/pci-bridge/simba.h F: pc-bios/openbios-sparc64 +F: tests/acceptance/machine_sparc64_sun4u.py Sun4v M: Artyom Tarasenko @@ -1330,6 +1445,7 @@ S390 PCI M: Matthew Rosato S: Supported F: hw/s390x/s390-pci* +F: include/hw/s390x/s390-pci* L: qemu-s390x@nongnu.org UniCore32 Machines @@ -1412,6 +1528,7 @@ Machine core M: Eduardo Habkost M: Marcel Apfelbaum S: Supported +F: cpu.c F: hw/core/cpu.c F: hw/core/machine-qmp-cmds.c F: hw/core/machine.c @@ -1465,7 +1582,7 @@ F: tests/qtest/ide-test.c F: tests/qtest/ahci-test.c F: tests/qtest/cdrom-test.c F: tests/qtest/libqos/ahci* -T: git https://github.com/jnsnow/qemu.git ide +T: git https://gitlab.com/jsnow/qemu.git ide IPMI M: Corey Minyard @@ -1483,7 +1600,7 @@ S: Supported F: hw/block/fdc.c F: include/hw/block/fdc.h F: tests/qtest/fdc-test.c -T: git https://github.com/jnsnow/qemu.git ide +T: git https://gitlab.com/jsnow/qemu.git ide OMAP M: Peter Maydell @@ -1491,6 +1608,7 @@ L: qemu-arm@nongnu.org S: Maintained F: hw/*/omap* F: include/hw/arm/omap.h +F: docs/system/arm/sx1.rst IPack M: Alberto Garcia @@ -1506,6 +1624,7 @@ F: include/hw/pci/* F: hw/misc/pci-testdev.c F: hw/pci/* F: hw/pci-bridge/* +F: qapi/pci.json F: docs/pci* F: docs/specs/*pci* F: default-configs/pci.mak @@ -1521,7 +1640,8 @@ F: hw/acpi/* F: hw/smbios/* F: hw/i386/acpi-build.[hc] F: hw/arm/virt-acpi-build.c -F: tests/qtest/bios-tables-test.c +F: qapi/acpi.json +F: tests/qtest/bios-tables-test* F: tests/qtest/acpi-utils.[hc] F: tests/data/acpi/ @@ -1590,6 +1710,7 @@ F: hw/ssi/xilinx_* SD (Secure Card) M: Philippe Mathieu-DaudĂ© +L: qemu-block@nongnu.org S: Odd Fixes F: include/hw/sd/sd* F: hw/sd/core.c @@ -1670,7 +1791,7 @@ M: David Hildenbrand S: Maintained F: hw/virtio/virtio-balloon*.c F: include/hw/virtio/virtio-balloon.h -F: balloon.c +F: softmmu/balloon.c F: include/sysemu/balloon.h virtio-9p @@ -1752,12 +1873,25 @@ F: hw/virtio/virtio-crypto.c F: hw/virtio/virtio-crypto-pci.c F: include/hw/virtio/virtio-crypto.h +virtio-mem +M: David Hildenbrand +S: Supported +W: https://virtio-mem.gitlab.io/ +F: hw/virtio/virtio-mem.c +F: hw/virtio/virtio-mem-pci.h +F: hw/virtio/virtio-mem-pci.c +F: include/hw/virtio/virtio-mem.h + nvme M: Keith Busch +M: Klaus Jensen L: qemu-block@nongnu.org S: Supported F: hw/block/nvme* +F: include/block/nvme.h F: tests/qtest/nvme-test.c +F: docs/specs/nvme.txt +T: git git://git.infradead.org/qemu-nvme.git nvme-next megasas M: Hannes Reinecke @@ -1786,6 +1920,7 @@ Rocker M: Jiri Pirko S: Maintained F: hw/net/rocker/ +F: qapi/rocker.json F: tests/rocker/ F: docs/specs/rocker.txt @@ -1847,6 +1982,12 @@ F: docs/specs/vmgenid.txt F: tests/qtest/vmgenid-test.c F: stubs/vmgenid.c +LED +M: Philippe Mathieu-DaudĂ© +S: Maintained +F: include/hw/misc/led.h +F: hw/misc/led.c + Unimplemented device M: Peter Maydell R: Philippe Mathieu-DaudĂ© @@ -1854,6 +1995,13 @@ S: Maintained F: include/hw/misc/unimp.h F: hw/misc/unimp.c +Empty slot +M: Artyom Tarasenko +R: Philippe Mathieu-DaudĂ© +S: Maintained +F: include/hw/misc/empty_slot.h +F: hw/misc/empty_slot.c + Standard VGA M: Gerd Hoffmann S: Maintained @@ -1921,7 +2069,7 @@ R: Laszlo Ersek R: Gerd Hoffmann S: Supported F: docs/specs/fw_cfg.txt -F: hw/nvram/fw_cfg.c +F: hw/nvram/fw_cfg*.c F: stubs/fw_cfg.c F: include/hw/nvram/fw_cfg.h F: include/standard-headers/linux/qemu_fw_cfg.h @@ -1938,6 +2086,35 @@ F: hw/*/*xive* F: include/hw/*/*xive* F: docs/*/*xive* +Renesas peripherals +M: Yoshinori Sato +R: Magnus Damm +S: Odd Fixes +F: hw/char/renesas_sci.c +F: hw/char/sh_serial.c +F: hw/timer/renesas_*.c +F: hw/timer/sh_timer.c +F: include/hw/char/renesas_sci.h +F: include/hw/sh4/sh.h +F: include/hw/timer/renesas_*.h + +Renesas RX peripherals +M: Yoshinori Sato +S: Odd Fixes +F: hw/intc/rx_icu.c +F: hw/rx/ +F: include/hw/intc/rx_icu.h +F: include/hw/rx/ + +CAN bus subsystem and hardware +M: Pavel Pisa +M: Vikram Garhwal +S: Maintained +W: https://canbus.pages.fel.cvut.cz/ +F: net/can/* +F: hw/net/can/* +F: include/net/can_*.h + Subsystems ---------- Audio @@ -1946,6 +2123,7 @@ S: Maintained F: audio/ F: hw/audio/ F: include/hw/audio/ +F: qapi/audio.json F: tests/qtest/ac97-test.c F: tests/qtest/es1370-test.c F: tests/qtest/intel-hda-test.c @@ -1982,6 +2160,7 @@ F: migration/block* F: include/block/aio.h F: include/block/aio-wait.h F: scripts/qemugdb/aio.py +F: tests/test-fdmon-epoll.c T: git https://github.com/stefanha/qemu.git block Block SCSI subsystem @@ -2006,7 +2185,7 @@ F: block/commit.c F: block/stream.c F: block/mirror.c F: qapi/job.json -T: git https://github.com/jnsnow/qemu.git jobs +T: git https://gitlab.com/jsnow/qemu.git jobs Block QAPI, monitor, command line M: Markus Armbruster @@ -2071,7 +2250,7 @@ Device Tree M: Alistair Francis R: David Gibson S: Maintained -F: device_tree.c +F: softmmu/device_tree.c F: include/sysemu/device_tree.h Dump @@ -2100,6 +2279,7 @@ F: scripts/coccinelle/error-use-after-free.cocci F: scripts/coccinelle/error_propagate_null.cocci F: scripts/coccinelle/remove_local_err.cocci F: scripts/coccinelle/use-error_fatal.cocci +F: scripts/coccinelle/errp-guard.cocci GDB stub M: Alex BennĂ©e @@ -2112,14 +2292,15 @@ Memory API M: Paolo Bonzini S: Supported F: include/exec/ioport.h -F: ioport.c F: include/exec/memop.h F: include/exec/memory.h F: include/exec/ram_addr.h F: include/exec/ramblock.h -F: memory.c +F: softmmu/dma-helpers.c +F: softmmu/ioport.c +F: softmmu/memory.c +F: softmmu/physmem.c F: include/exec/memory-internal.h -F: exec.c F: scripts/coccinelle/memory-region-housekeeping.cocci SPICE @@ -2149,15 +2330,26 @@ F: ui/cocoa.m Main loop M: Paolo Bonzini S: Maintained -F: cpus.c F: include/qemu/main-loop.h F: include/sysemu/runstate.h F: util/main-loop.c F: util/qemu-timer.c F: softmmu/vl.c F: softmmu/main.c +F: softmmu/cpus.c +F: softmmu/cpu-throttle.c +F: softmmu/cpu-timers.c +F: softmmu/icount.c F: qapi/run-state.json +Read, Copy, Update (RCU) +M: Paolo Bonzini +S: Maintained +F: include/qemu/rcu*.h +F: tests/rcutorture.c +F: tests/test-rcu-*.c +F: util/rcu.c + Human Monitor (HMP) M: Dr. David Alan Gilbert S: Maintained @@ -2203,11 +2395,18 @@ S: Maintained F: include/sysemu/cryptodev*.h F: backends/cryptodev*.c +Python library +M: John Snow +M: Cleber Rosa +R: Eduardo Habkost +S: Maintained +F: python/ +T: git https://gitlab.com/jsnow/qemu.git python + Python scripts M: Eduardo Habkost M: Cleber Rosa S: Odd fixes -F: python/qemu/*py F: scripts/*.py F: tests/*.py @@ -2232,6 +2431,7 @@ F: tests/test-qmp-*.c F: tests/test-visitor-serialization.c F: scripts/qapi-gen.py F: scripts/qapi/* +F: docs/sphinx/qapidoc.py F: docs/devel/qapi* T: git https://repo.or.cz/qemu/armbru.git qapi-next @@ -2265,9 +2465,9 @@ M: Michael Roth S: Maintained F: qga/ F: docs/interop/qemu-ga.rst +F: docs/interop/qemu-ga-ref.rst F: scripts/qemu-guest-agent/ F: tests/test-qga.c -F: docs/interop/qemu-ga-ref.texi T: git https://github.com/mdroth/qemu.git qga QOM @@ -2277,17 +2477,25 @@ R: Eduardo Habkost S: Supported F: docs/qdev-device-use.txt F: hw/core/qdev* +F: hw/core/bus.c +F: hw/core/sysbus.c F: include/hw/qdev* F: include/monitor/qdev.h F: include/qom/ F: qapi/qom.json F: qapi/qdev.json -F: qdev-monitor.c +F: scripts/coccinelle/qom-parent-type.cocci +F: softmmu/qdev-monitor.c F: qom/ F: tests/check-qom-interface.c F: tests/check-qom-proplist.c F: tests/test-qdev-global-props.c +QOM boilerplate conversion script +M: Eduardo Habkost +S: Maintained +F: scripts/codeconverter/ + QMP M: Markus Armbruster S: Supported @@ -2295,7 +2503,9 @@ F: monitor/monitor-internal.h F: monitor/qmp* F: monitor/misc.c F: monitor/monitor.c +F: qapi/control.json F: qapi/error.json +F: qapi/introspect.json F: docs/devel/*qmp-* F: docs/interop/*qmp-* F: scripts/qmp/ @@ -2308,17 +2518,21 @@ M: Thomas Huth M: Laurent Vivier R: Paolo Bonzini S: Maintained -F: qtest.c -F: accel/qtest.c +F: softmmu/qtest.c +F: accel/qtest/ F: tests/qtest/ +X: tests/qtest/bios-tables-test* Device Fuzzing M: Alexander Bulekov R: Paolo Bonzini R: Bandan Das R: Stefan Hajnoczi +R: Thomas Huth S: Maintained F: tests/qtest/fuzz/ +F: scripts/oss-fuzz/ +F: docs/devel/fuzzing.rst Register API M: Alistair Francis @@ -2352,6 +2566,7 @@ S: Maintained F: trace/ F: trace-events F: docs/qemu-option-trace.rst.inc +F: qapi/trace.json F: scripts/tracetool.py F: scripts/tracetool/ F: scripts/qemu-trace-stap* @@ -2368,7 +2583,7 @@ F: hw/tpm/* F: include/hw/acpi/tpm.h F: include/sysemu/tpm* F: qapi/tpm.json -F: backends/tpm.c +F: backends/tpm/ F: tests/qtest/*tpm* T: git https://github.com/stefanberger/qemu-tpm.git tpm-next @@ -2403,7 +2618,7 @@ F: docs/interop/dbus-vmstate.rst Seccomp M: Eduardo Otubo S: Supported -F: qemu-seccomp.c +F: softmmu/qemu-seccomp.c F: include/sysemu/seccomp.h Cryptography @@ -2411,6 +2626,7 @@ M: Daniel P. Berrange S: Maintained F: crypto/ F: include/crypto/ +F: qapi/crypto.json F: tests/test-crypto-* F: tests/benchmark-crypto-* F: tests/crypto-tls-* @@ -2507,6 +2723,9 @@ F: net/filter-replay.c F: include/sysemu/replay.h F: docs/replay.txt F: stubs/replay.c +F: tests/acceptance/replay_kernel.py +F: tests/acceptance/reverse_debugging.py +F: qapi/replay.json IOVA Tree M: Peter Xu @@ -2531,6 +2750,14 @@ F: include/hw/i2c/smbus_master.h F: include/hw/i2c/smbus_slave.h F: include/hw/i2c/smbus_eeprom.h +Firmware schema specifications +M: Laszlo Ersek +M: Philippe Mathieu-DaudĂ© +R: Daniel P. Berrange +R: Kashyap Chamarthy +S: Maintained +F: docs/interop/firmware.json + EDK2 Firmware M: Laszlo Ersek M: Philippe Mathieu-DaudĂ© @@ -2542,9 +2769,25 @@ F: roms/edk2 F: roms/edk2-* F: tests/data/uefi-boot-images/ F: tests/uefi-test-tools/ -F: .gitlab-ci-edk2.yml +F: .gitlab-ci.d/edk2.yml F: .gitlab-ci.d/edk2/ +VT-d Emulation +M: Michael S. Tsirkin +M: Peter Xu +R: Jason Wang +S: Supported +F: hw/i386/intel_iommu.c +F: hw/i386/intel_iommu_internal.h +F: include/hw/i386/intel_iommu.h + +OpenSBI Firmware +M: Bin Meng +S: Supported +F: pc-bios/opensbi-* +F: .gitlab-ci.d/opensbi.yml +F: .gitlab-ci.d/opensbi/ + Usermode Emulation ------------------ Overall usermode emulation @@ -2559,8 +2802,7 @@ F: bsd-user/ F: default-configs/*-bsd-user.mak Linux user -M: Riku Voipio -R: Laurent Vivier +M: Laurent Vivier S: Maintained F: linux-user/ F: default-configs/*-linux-user.mak @@ -2572,7 +2814,7 @@ F: scripts/gensyscalls.sh Tiny Code Generator (TCG) ------------------------- Common TCG code -M: Richard Henderson +M: Richard Henderson S: Maintained F: tcg/ F: include/tcg/ @@ -2582,7 +2824,8 @@ M: Alex BennĂ©e S: Maintained F: docs/devel/tcg-plugins.rst F: plugins/ -F: tests/plugin +F: tests/plugin/ +F: contrib/plugins/ AArch64 TCG target M: Richard Henderson @@ -2600,20 +2843,22 @@ F: tcg/arm/ F: disas/arm.c i386 TCG target -M: Richard Henderson +M: Richard Henderson S: Maintained F: tcg/i386/ F: disas/i386.c MIPS TCG target -M: Aleksandar Markovic +M: Philippe Mathieu-DaudĂ© R: Aurelien Jarno +R: Huacai Chen +R: Jiaxun Yang R: Aleksandar Rikalo -S: Maintained +S: Odd Fixes F: tcg/mips/ PPC TCG target -M: Richard Henderson +M: Richard Henderson S: Odd Fixes F: tcg/ppc/ F: disas/ppc.c @@ -2627,7 +2872,7 @@ F: tcg/riscv/ F: disas/riscv.c S390 TCG target -M: Richard Henderson +M: Richard Henderson S: Maintained F: tcg/s390/ F: disas/s390.c @@ -2662,7 +2907,6 @@ F: block/rbd.c Sheepdog M: Liu Yuan L: qemu-block@nongnu.org -L: sheepdog@lists.wpkg.org S: Odd Fixes F: block/sheepdog.c @@ -2730,15 +2974,18 @@ S: Supported F: block/null.c NVMe Block Driver -M: Fam Zheng +M: Stefan Hajnoczi +R: Fam Zheng L: qemu-block@nongnu.org S: Supported F: block/nvme* +F: include/block/nvme.h +T: git https://github.com/stefanha/qemu.git block Bootdevice M: Gonglei S: Maintained -F: bootdevice.c +F: softmmu/bootdevice.c Quorum M: Alberto Garcia @@ -2840,7 +3087,7 @@ F: block/vpc.c vvfat M: Kevin Wolf L: qemu-block@nongnu.org -S: Supported +S: Odd Fixes F: block/vvfat.c Image format fuzzer @@ -2849,6 +3096,15 @@ L: qemu-block@nongnu.org S: Supported F: tests/image-fuzzer/ +Vhost-user block device backend server +M: Coiby Xu +S: Maintained +F: block/export/vhost-user-blk-server.c +F: block/export/vhost-user-blk-server.h +F: include/qemu/vhost-user-server.h +F: tests/qtest/libqos/vhost-user-blk.c +F: util/vhost-user-server.c + Replication M: Wen Congyang M: Xie Changlong @@ -2901,8 +3157,14 @@ W: https://cirrus-ci.com/github/qemu/qemu GitLab Continuous Integration M: Thomas Huth +M: Philippe Mathieu-DaudĂ© +M: Alex BennĂ©e +R: Wainer dos Santos Moschetta S: Maintained F: .gitlab-ci.yml +F: .gitlab-ci.d/crossbuilds.yml +F: .gitlab-ci.d/*py +F: scripts/ci/gitlab-pipeline-status Guest Test Compilation Support M: Alex BennĂ©e @@ -2911,6 +3173,14 @@ S: Maintained F: tests/tcg/Makefile F: tests/tcg/Makefile.include +Acceptance (Integration) Testing with the Avocado framework +W: https://trello.com/b/6Qi1pxVn/avocado-qemu +R: Cleber Rosa +R: Philippe Mathieu-DaudĂ© +R: Wainer dos Santos Moschetta +S: Odd Fixes +F: tests/acceptance/ + Documentation ------------- Build system architecture @@ -2936,7 +3206,7 @@ S: Odd Fixes F: scripts/git-submodule.sh UI translations -M: Aleksandar Markovic +S: Orphaned F: po/*.po Sphinx documentation configuration and build machinery @@ -2944,3 +3214,11 @@ M: Peter Maydell S: Maintained F: docs/conf.py F: docs/*/conf.py +F: docs/sphinx/ + +Miscellaneous +------------- +Performance Tools and Tests +M: Ahmed Karaman +S: Maintained +F: scripts/performance/ diff --git a/Makefile b/Makefile index 40e4f7677bde5d088c08cf8e7044c450a025e8d8..76dbb917f5cd3085ad93cb634c14ba88b380ab53 100644 --- a/Makefile +++ b/Makefile @@ -10,18 +10,41 @@ BUILD_DIR=$(CURDIR) # Before including a proper config-host.mak, assume we are in the source tree SRC_PATH=. +# Don't use implicit rules or variables +# we have explicit rules for everything +MAKEFLAGS += -rR + +SHELL = /usr/bin/env bash -o pipefail + +# Usage: $(call quiet-command,command and args,"NAME","args to print") +# This will run "command and args", and either: +# if V=1 just print the whole command and args +# otherwise print the 'quiet' output in the format " NAME args to print" +# NAME should be a short name of the command, 7 letters or fewer. +# If called with only a single argument, will print nothing in quiet mode. +quiet-command-run = $(if $(V),,$(if $2,printf " %-7s %s\n" $2 $3 && ))$1 +quiet-@ = $(if $(V),,@) +quiet-command = $(quiet-@)$(call quiet-command-run,$1,$2,$3) + UNCHECKED_GOALS := %clean TAGS cscope ctags dist \ - html info pdf txt \ help check-help print-% \ docker docker-% vm-help vm-test vm-build-% +all: +.PHONY: all clean distclean recurse-all dist msi FORCE + +# Don't try to regenerate Makefile or configure +# We don't generate any of them +Makefile: ; +configure: ; + # All following code might depend on configuration variables ifneq ($(wildcard config-host.mak),) -# Put the all: rule here so that config-host.mak can contain dependencies. -all: include config-host.mak git-submodule-update: +.git-submodule-status: git-submodule-update config-host.mak +Makefile: .git-submodule-status .PHONY: git-submodule-update @@ -49,7 +72,7 @@ git-submodule-update: endif endif -.git-submodule-status: git-submodule-update config-host.mak +# 0. ensure the build tree is okay # Check that we're not trying to do an out-of-tree build from # a tree that's been used for an in-tree build. @@ -61,1234 +84,236 @@ seems to have been used for an in-tree build. You can fix this by running \ endif endif -CONFIG_SOFTMMU := $(if $(filter %-softmmu,$(TARGET_DIRS)),y) -CONFIG_USER_ONLY := $(if $(filter %-user,$(TARGET_DIRS)),y) -CONFIG_XEN := $(CONFIG_XEN_BACKEND) -CONFIG_ALL=y --include config-all-devices.mak --include config-all-disas.mak - -config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/pc-bios $(SRC_PATH)/VERSION - @echo $@ is out-of-date, running configure - @./config.status - -# Force configure to re-run if the API symbols are updated -ifeq ($(CONFIG_PLUGIN),y) -config-host.mak: $(SRC_PATH)/plugins/qemu-plugins.symbols +# force a rerun of configure if config-host.mak is too old or corrupted +ifeq ($(MESON),) +.PHONY: config-host.mak +x := $(shell rm -rf meson-private meson-info meson-logs) endif - +ifeq ($(NINJA),) +.PHONY: config-host.mak +x := $(shell rm -rf meson-private meson-info meson-logs) else -config-host.mak: -ifneq ($(filter-out $(UNCHECKED_GOALS),$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail)) - @echo "Please call configure before running make!" - @exit 1 +export NINJA endif +ifeq ($(wildcard build.ninja),) +.PHONY: config-host.mak +x := $(shell rm -rf meson-private meson-info meson-logs) endif - -include $(SRC_PATH)/rules.mak - -# lor is defined in rules.mak -CONFIG_BLOCK := $(call lor,$(CONFIG_SOFTMMU),$(CONFIG_TOOLS)) - -# Create QEMU_PKGVERSION and FULL_VERSION strings -# If PKGVERSION is set, use that; otherwise get version and -dirty status from git -QEMU_PKGVERSION := $(if $(PKGVERSION),$(PKGVERSION),$(shell \ - cd $(SRC_PATH); \ - if test -e .git; then \ - git describe --match 'v*' 2>/dev/null | tr -d '\n'; \ - if ! git diff-index --quiet HEAD &>/dev/null; then \ - echo "-dirty"; \ - fi; \ - fi)) - -# Either "version (pkgversion)", or just "version" if pkgversion not set -FULL_VERSION := $(if $(QEMU_PKGVERSION),$(VERSION) ($(QEMU_PKGVERSION)),$(VERSION)) - -generated-files-y = qemu-version.h config-host.h qemu-options.def - -GENERATED_QAPI_FILES = qapi/qapi-builtin-types.h qapi/qapi-builtin-types.c -GENERATED_QAPI_FILES += qapi/qapi-types.h qapi/qapi-types.c -GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-types-%.h) -GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-types-%.c) -GENERATED_QAPI_FILES += qapi/qapi-builtin-visit.h qapi/qapi-builtin-visit.c -GENERATED_QAPI_FILES += qapi/qapi-visit.h qapi/qapi-visit.c -GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-visit-%.h) -GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-visit-%.c) -GENERATED_QAPI_FILES += qapi/qapi-init-commands.h qapi/qapi-init-commands.c -GENERATED_QAPI_FILES += qapi/qapi-commands.h qapi/qapi-commands.c -GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-commands-%.h) -GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-commands-%.c) -GENERATED_QAPI_FILES += qapi/qapi-emit-events.h qapi/qapi-emit-events.c -GENERATED_QAPI_FILES += qapi/qapi-events.h qapi/qapi-events.c -GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-events-%.h) -GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-events-%.c) -GENERATED_QAPI_FILES += qapi/qapi-introspect.c qapi/qapi-introspect.h -GENERATED_QAPI_FILES += qapi/qapi-doc.texi - -# The following list considers only the storage daemon main module. All other -# modules are currently shared with the main schema, so we don't actually -# generate additional files. - -GENERATED_STORAGE_DAEMON_QAPI_FILES = storage-daemon/qapi/qapi-commands.h -GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-commands.c -GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-emit-events.h -GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-emit-events.c -GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-events.h -GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-events.c -GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-init-commands.h -GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-init-commands.c -GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-introspect.h -GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-introspect.c -GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-types.h -GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-types.c -GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-visit.h -GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-visit.c -GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-doc.texi - -generated-files-y += $(GENERATED_QAPI_FILES) -generated-files-y += $(GENERATED_STORAGE_DAEMON_QAPI_FILES) - -generated-files-y += trace/generated-tcg-tracers.h - -generated-files-y += trace/generated-helpers-wrappers.h -generated-files-y += trace/generated-helpers.h -generated-files-y += trace/generated-helpers.c - -generated-files-$(CONFIG_TRACE_UST) += trace-ust-all.h -generated-files-$(CONFIG_TRACE_UST) += trace-ust-all.c - -generated-files-y += module_block.h - -TRACE_HEADERS = trace-root.h $(trace-events-subdirs:%=%/trace.h) -TRACE_SOURCES = trace-root.c $(trace-events-subdirs:%=%/trace.c) -TRACE_DTRACE = -ifdef CONFIG_TRACE_DTRACE -TRACE_HEADERS += trace-dtrace-root.h $(trace-events-subdirs:%=%/trace-dtrace.h) -TRACE_DTRACE += trace-dtrace-root.dtrace $(trace-events-subdirs:%=%/trace-dtrace.dtrace) -endif -ifdef CONFIG_TRACE_UST -TRACE_HEADERS += trace-ust-root.h $(trace-events-subdirs:%=%/trace-ust.h) +ifeq ($(origin prefix),file) +.PHONY: config-host.mak +x := $(shell rm -rf meson-private meson-info meson-logs) endif -generated-files-y += $(TRACE_HEADERS) -generated-files-y += $(TRACE_SOURCES) -generated-files-y += $(BUILD_DIR)/trace-events-all -generated-files-y += .git-submodule-status - -trace-group-name = $(shell dirname $1 | sed -e 's/[^a-zA-Z0-9]/_/g') - -tracetool-y = $(SRC_PATH)/scripts/tracetool.py -tracetool-y += $(shell find $(SRC_PATH)/scripts/tracetool -name "*.py") - -%/trace.h: %/trace.h-timestamp - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ -%/trace.h-timestamp: $(SRC_PATH)/%/trace-events $(tracetool-y) $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(TRACETOOL) \ - --group=$(call trace-group-name,$@) \ - --format=h \ - --backends=$(TRACE_BACKENDS) \ - $< > $@,"GEN","$(@:%-timestamp=%)") - -%/trace.c: %/trace.c-timestamp - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ -%/trace.c-timestamp: $(SRC_PATH)/%/trace-events $(tracetool-y) $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(TRACETOOL) \ - --group=$(call trace-group-name,$@) \ - --format=c \ - --backends=$(TRACE_BACKENDS) \ - $< > $@,"GEN","$(@:%-timestamp=%)") - -%/trace-ust.h: %/trace-ust.h-timestamp - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ -%/trace-ust.h-timestamp: $(SRC_PATH)/%/trace-events $(tracetool-y) $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(TRACETOOL) \ - --group=$(call trace-group-name,$@) \ - --format=ust-events-h \ - --backends=$(TRACE_BACKENDS) \ - $< > $@,"GEN","$(@:%-timestamp=%)") - -%/trace-dtrace.dtrace: %/trace-dtrace.dtrace-timestamp - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ -%/trace-dtrace.dtrace-timestamp: $(SRC_PATH)/%/trace-events $(BUILD_DIR)/config-host.mak $(tracetool-y) - $(call quiet-command,$(TRACETOOL) \ - --group=$(call trace-group-name,$@) \ - --format=d \ - --backends=$(TRACE_BACKENDS) \ - $< > $@,"GEN","$(@:%-timestamp=%)") - -%/trace-dtrace.h: %/trace-dtrace.dtrace $(tracetool-y) - $(call quiet-command,dtrace -o $@ -h -s $<, "GEN","$@") - -%/trace-dtrace.o: %/trace-dtrace.dtrace $(tracetool-y) - - -trace-root.h: trace-root.h-timestamp - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ -trace-root.h-timestamp: $(SRC_PATH)/trace-events $(tracetool-y) $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(TRACETOOL) \ - --group=root \ - --format=h \ - --backends=$(TRACE_BACKENDS) \ - $< > $@,"GEN","$(@:%-timestamp=%)") - -trace-root.c: trace-root.c-timestamp - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ -trace-root.c-timestamp: $(SRC_PATH)/trace-events $(tracetool-y) $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(TRACETOOL) \ - --group=root \ - --format=c \ - --backends=$(TRACE_BACKENDS) \ - $< > $@,"GEN","$(@:%-timestamp=%)") - -trace-ust-root.h: trace-ust-root.h-timestamp - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ -trace-ust-root.h-timestamp: $(SRC_PATH)/trace-events $(tracetool-y) $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(TRACETOOL) \ - --group=root \ - --format=ust-events-h \ - --backends=$(TRACE_BACKENDS) \ - $< > $@,"GEN","$(@:%-timestamp=%)") - -trace-ust-all.h: trace-ust-all.h-timestamp - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ -trace-ust-all.h-timestamp: $(trace-events-files) $(tracetool-y) $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(TRACETOOL) \ - --group=all \ - --format=ust-events-h \ - --backends=$(TRACE_BACKENDS) \ - $(trace-events-files) > $@,"GEN","$(@:%-timestamp=%)") - -trace-ust-all.c: trace-ust-all.c-timestamp - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ -trace-ust-all.c-timestamp: $(trace-events-files) $(tracetool-y) $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(TRACETOOL) \ - --group=all \ - --format=ust-events-c \ - --backends=$(TRACE_BACKENDS) \ - $(trace-events-files) > $@,"GEN","$(@:%-timestamp=%)") - -trace-dtrace-root.dtrace: trace-dtrace-root.dtrace-timestamp - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ -trace-dtrace-root.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak $(tracetool-y) - $(call quiet-command,$(TRACETOOL) \ - --group=root \ - --format=d \ - --backends=$(TRACE_BACKENDS) \ - $< > $@,"GEN","$(@:%-timestamp=%)") - -trace-dtrace-root.h: trace-dtrace-root.dtrace - $(call quiet-command,dtrace -o $@ -h -s $<, "GEN","$@") - -trace-dtrace-root.o: trace-dtrace-root.dtrace - -KEYCODEMAP_GEN = $(SRC_PATH)/ui/keycodemapdb/tools/keymap-gen -KEYCODEMAP_CSV = $(SRC_PATH)/ui/keycodemapdb/data/keymaps.csv - -KEYCODEMAP_FILES = \ - ui/input-keymap-atset1-to-qcode.c \ - ui/input-keymap-linux-to-qcode.c \ - ui/input-keymap-qcode-to-atset1.c \ - ui/input-keymap-qcode-to-atset2.c \ - ui/input-keymap-qcode-to-atset3.c \ - ui/input-keymap-qcode-to-linux.c \ - ui/input-keymap-qcode-to-qnum.c \ - ui/input-keymap-qcode-to-sun.c \ - ui/input-keymap-qnum-to-qcode.c \ - ui/input-keymap-usb-to-qcode.c \ - ui/input-keymap-win32-to-qcode.c \ - ui/input-keymap-x11-to-qcode.c \ - ui/input-keymap-xorgevdev-to-qcode.c \ - ui/input-keymap-xorgkbd-to-qcode.c \ - ui/input-keymap-xorgxquartz-to-qcode.c \ - ui/input-keymap-xorgxwin-to-qcode.c \ - ui/input-keymap-osx-to-qcode.c \ - $(NULL) - -generated-files-$(CONFIG_SOFTMMU) += $(KEYCODEMAP_FILES) - -ui/input-keymap-%.c: $(KEYCODEMAP_GEN) $(KEYCODEMAP_CSV) $(SRC_PATH)/ui/Makefile.objs - $(call quiet-command,\ - stem=$* && src=$${stem%-to-*} dst=$${stem#*-to-} && \ - test -e $(KEYCODEMAP_GEN) && \ - $(PYTHON) $(KEYCODEMAP_GEN) \ - --lang glib2 \ - --varname qemu_input_map_$${src}_to_$${dst} \ - code-map $(KEYCODEMAP_CSV) $${src} $${dst} \ - > $@ || rm -f $@, "GEN", "$@") - -$(KEYCODEMAP_GEN): .git-submodule-status -$(KEYCODEMAP_CSV): .git-submodule-status - -edk2-decompressed = $(basename $(wildcard pc-bios/edk2-*.fd.bz2)) -pc-bios/edk2-%.fd: pc-bios/edk2-%.fd.bz2 - $(call quiet-command,bzip2 -d -c $< > $@,"BUNZIP2",$<) - -# Don't try to regenerate Makefile or configure -# We don't generate any of them -Makefile: ; -configure: ; - -.PHONY: all clean cscope distclean html info install install-doc \ - pdf txt recurse-all dist msi FORCE - -$(call set-vpath, $(SRC_PATH)) - -LIBS+=-lz $(LIBS_TOOLS) - -vhost-user-json-y = -HELPERS-y = - -HELPERS-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_LINUX)) = qemu-bridge-helper$(EXESUF) - -ifeq ($(CONFIG_LINUX)$(CONFIG_VIRGL)$(CONFIG_GBM)$(CONFIG_TOOLS),yyyy) -HELPERS-y += vhost-user-gpu$(EXESUF) -vhost-user-json-y += contrib/vhost-user-gpu/50-qemu-gpu.json -endif - -ifeq ($(CONFIG_LINUX)$(CONFIG_SECCOMP)$(CONFIG_LIBCAP_NG),yyy) -HELPERS-y += virtiofsd$(EXESUF) -vhost-user-json-y += tools/virtiofsd/50-qemu-virtiofsd.json -endif - -# Sphinx does not allow building manuals into the same directory as -# the source files, so if we're doing an in-tree QEMU build we must -# build the manuals into a subdirectory (and then install them from -# there for 'make install'). For an out-of-tree build we can just -# use the docs/ subdirectory in the build tree as normal. -ifeq ($(realpath $(SRC_PATH)),$(realpath .)) -MANUAL_BUILDDIR := docs/built -else -MANUAL_BUILDDIR := docs -endif - -ifdef BUILD_DOCS -DOCS+=$(MANUAL_BUILDDIR)/system/qemu.1 -DOCS+=$(MANUAL_BUILDDIR)/tools/qemu-img.1 -DOCS+=$(MANUAL_BUILDDIR)/tools/qemu-nbd.8 -DOCS+=$(MANUAL_BUILDDIR)/interop/qemu-ga.8 -ifeq ($(CONFIG_LINUX)$(CONFIG_SECCOMP)$(CONFIG_LIBCAP_NG),yyy) -DOCS+=$(MANUAL_BUILDDIR)/tools/virtiofsd.1 -endif -DOCS+=$(MANUAL_BUILDDIR)/system/qemu-block-drivers.7 -DOCS+=docs/interop/qemu-qmp-ref.html docs/interop/qemu-qmp-ref.txt docs/interop/qemu-qmp-ref.7 -DOCS+=docs/interop/qemu-ga-ref.html docs/interop/qemu-ga-ref.txt docs/interop/qemu-ga-ref.7 -DOCS+=$(MANUAL_BUILDDIR)/system/qemu-cpu-models.7 -DOCS+=$(MANUAL_BUILDDIR)/index.html -ifdef CONFIG_VIRTFS -DOCS+=$(MANUAL_BUILDDIR)/tools/virtfs-proxy-helper.1 -endif -ifdef CONFIG_TRACE_SYSTEMTAP -DOCS+=$(MANUAL_BUILDDIR)/tools/qemu-trace-stap.1 -endif -else -DOCS= +# 1. ensure config-host.mak is up-to-date +config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/pc-bios $(SRC_PATH)/VERSION + @echo config-host.mak is out-of-date, running configure + @if test -f meson-private/coredata.dat; then \ + ./config.status --skip-meson; \ + else \ + ./config.status && touch build.ninja.stamp; \ + fi + +# 2. meson.stamp exists if meson has run at least once (so ninja reconfigure +# works), but otherwise never needs to be updated +meson-private/coredata.dat: meson.stamp +meson.stamp: config-host.mak + @touch meson.stamp + +# 3. ensure generated build files are up-to-date + +ifneq ($(NINJA),) +Makefile.ninja: build.ninja + $(quiet-@){ \ + echo 'ninja-targets = \'; \ + $(NINJA) -t targets all | sed 's/:.*//; $$!s/$$/ \\/'; \ + echo 'build-files = \'; \ + $(NINJA) -t query build.ninja | sed -n '1,/^ input:/d; /^ outputs:/q; s/$$/ \\/p'; \ + } > $@.tmp && mv $@.tmp $@ +-include Makefile.ninja + +# A separate rule is needed for Makefile dependencies to avoid -n +build.ninja: build.ninja.stamp +build.ninja.stamp: meson.stamp $(build-files) + $(NINJA) $(if $V,-v,) build.ninja && touch $@ +endif + +ifneq ($(MESON),) +Makefile.mtest: build.ninja scripts/mtest2make.py + $(MESON) introspect --targets --tests --benchmarks | $(PYTHON) scripts/mtest2make.py > $@ +-include Makefile.mtest +endif + +# 4. Rules to bridge to other makefiles + +ifneq ($(NINJA),) +MAKE.n = $(findstring n,$(firstword $(MAKEFLAGS))) +MAKE.k = $(findstring k,$(firstword $(MAKEFLAGS))) +MAKE.q = $(findstring q,$(firstword $(MAKEFLAGS))) +MAKE.nq = $(if $(word 2, $(MAKE.n) $(MAKE.q)),nq) +NINJAFLAGS = $(if $V,-v) $(if $(MAKE.n), -n) $(if $(MAKE.k), -k0) \ + $(filter-out -j, $(lastword -j1 $(filter -l% -j%, $(MAKEFLAGS)))) \ + +ninja-cmd-goals = $(or $(MAKECMDGOALS), all) +ninja-cmd-goals += $(foreach t, $(.tests), $(.test.deps.$t)) + +makefile-targets := build.ninja ctags TAGS cscope dist clean uninstall +# "ninja -t targets" also lists all prerequisites. If build system +# files are marked as PHONY, however, Make will always try to execute +# "ninja build.ninja". +ninja-targets := $(filter-out $(build-files) $(makefile-targets), $(ninja-targets)) +.PHONY: $(ninja-targets) run-ninja +$(ninja-targets): run-ninja + +# Use "| cat" to give Ninja a more "make-y" output. Use "+" to bypass the +# --output-sync line. +run-ninja: config-host.mak +ifneq ($(filter $(ninja-targets), $(ninja-cmd-goals)),) + +$(quiet-@)$(if $(MAKE.nq),@:, $(NINJA) \ + $(NINJAFLAGS) $(sort $(filter $(ninja-targets), $(ninja-cmd-goals))) | cat) endif - -SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory --quiet) BUILD_DIR=$(BUILD_DIR) -SUBDIR_DEVICES_MAK=$(patsubst %, %/config-devices.mak, $(filter %-softmmu, $(TARGET_DIRS))) -SUBDIR_DEVICES_MAK_DEP=$(patsubst %, %.d, $(SUBDIR_DEVICES_MAK)) - -ifeq ($(SUBDIR_DEVICES_MAK),) -config-all-devices.mak: config-host.mak - $(call quiet-command,echo '# no devices' > $@,"GEN","$@") -else -config-all-devices.mak: $(SUBDIR_DEVICES_MAK) config-host.mak - $(call quiet-command, sed -n \ - 's|^\([^=]*\)=\(.*\)$$|\1:=$$(findstring y,$$(\1)\2)|p' \ - $(SUBDIR_DEVICES_MAK) | sort -u > $@, \ - "GEN","$@") endif --include $(SUBDIR_DEVICES_MAK_DEP) - -# This has to be kept in sync with Kconfig.host. -MINIKCONF_ARGS = \ - $(CONFIG_MINIKCONF_MODE) \ - $@ $*/config-devices.mak.d $< $(MINIKCONF_INPUTS) \ - CONFIG_KVM=$(CONFIG_KVM) \ - CONFIG_SPICE=$(CONFIG_SPICE) \ - CONFIG_IVSHMEM=$(CONFIG_IVSHMEM) \ - CONFIG_TPM=$(CONFIG_TPM) \ - CONFIG_XEN=$(CONFIG_XEN) \ - CONFIG_OPENGL=$(CONFIG_OPENGL) \ - CONFIG_X11=$(CONFIG_X11) \ - CONFIG_VHOST_USER=$(CONFIG_VHOST_USER) \ - CONFIG_VHOST_KERNEL=$(CONFIG_VHOST_KERNEL) \ - CONFIG_VIRTFS=$(CONFIG_VIRTFS) \ - CONFIG_LINUX=$(CONFIG_LINUX) \ - CONFIG_PVRDMA=$(CONFIG_PVRDMA) - -MINIKCONF_INPUTS = $(SRC_PATH)/Kconfig.host $(SRC_PATH)/hw/Kconfig -MINIKCONF_DEPS = $(MINIKCONF_INPUTS) $(wildcard $(SRC_PATH)/hw/*/Kconfig) -MINIKCONF = $(PYTHON) $(SRC_PATH)/scripts/minikconf.py \ - -$(SUBDIR_DEVICES_MAK): %/config-devices.mak: default-configs/%.mak $(MINIKCONF_DEPS) $(BUILD_DIR)/config-host.mak - $(call quiet-command, $(MINIKCONF) $(MINIKCONF_ARGS) > $@.tmp, "GEN", "$@.tmp") - $(call quiet-command, if test -f $@; then \ - if cmp -s $@.old $@; then \ - mv $@.tmp $@; \ - cp -p $@ $@.old; \ - else \ - if test -f $@.old; then \ - echo "WARNING: $@ (user modified) out of date.";\ - else \ - echo "WARNING: $@ out of date.";\ - fi; \ - echo "Run \"$(MAKE) defconfig\" to regenerate."; \ - rm $@.tmp; \ - fi; \ - else \ - mv $@.tmp $@; \ - cp -p $@ $@.old; \ - fi,"GEN","$@"); +# Force configure to re-run if the API symbols are updated +ifeq ($(CONFIG_PLUGIN),y) +config-host.mak: $(SRC_PATH)/plugins/qemu-plugins.symbols -defconfig: - rm -f config-all-devices.mak $(SUBDIR_DEVICES_MAK) +.PHONY: plugins +plugins: + $(call quiet-command,\ + $(MAKE) $(SUBDIR_MAKEFLAGS) -C contrib/plugins V="$(V)", \ + "BUILD", "example plugins") +endif # $(CONFIG_PLUGIN) -ifneq ($(wildcard config-host.mak),) -include $(SRC_PATH)/Makefile.objs +else # config-host.mak does not exist +config-host.mak: +ifneq ($(filter-out $(UNCHECKED_GOALS),$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail)) + @echo "Please call configure before running make!" + @exit 1 endif +endif # config-host.mak does not exist -dummy := $(call unnest-vars,, \ - stub-obj-y \ - authz-obj-y \ - chardev-obj-y \ - util-obj-y \ - qga-obj-y \ - elf2dmp-obj-y \ - ivshmem-client-obj-y \ - ivshmem-server-obj-y \ - virtiofsd-obj-y \ - rdmacm-mux-obj-y \ - libvhost-user-obj-y \ - vhost-user-scsi-obj-y \ - vhost-user-blk-obj-y \ - vhost-user-input-obj-y \ - vhost-user-gpu-obj-y \ - qga-vss-dll-obj-y \ - block-obj-y \ - block-obj-m \ - storage-daemon-obj-y \ - storage-daemon-obj-m \ - crypto-obj-y \ - qom-obj-y \ - io-obj-y \ - common-obj-y \ - common-obj-m \ - trace-obj-y) +SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory --quiet) include $(SRC_PATH)/tests/Makefile.include -all: $(DOCS) $(if $(BUILD_DOCS),sphinxdocs) $(TOOLS) $(HELPERS-y) recurse-all modules $(vhost-user-json-y) - -qemu-version.h: FORCE - $(call quiet-command, \ - (printf '#define QEMU_PKGVERSION "$(QEMU_PKGVERSION)"\n'; \ - printf '#define QEMU_FULL_VERSION "$(FULL_VERSION)"\n'; \ - ) > $@.tmp) - $(call quiet-command, if ! cmp -s $@ $@.tmp; then \ - mv $@.tmp $@; \ - else \ - rm $@.tmp; \ - fi) - -config-host.h: config-host.h-timestamp -config-host.h-timestamp: config-host.mak -qemu-options.def: $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/scripts/hxtool - $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"GEN","$@") - -TARGET_DIRS_RULES := $(foreach t, all fuzz clean install, $(addsuffix /$(t), $(TARGET_DIRS))) - -SOFTMMU_ALL_RULES=$(filter %-softmmu/all, $(TARGET_DIRS_RULES)) -$(SOFTMMU_ALL_RULES): $(authz-obj-y) -$(SOFTMMU_ALL_RULES): $(block-obj-y) -$(SOFTMMU_ALL_RULES): $(storage-daemon-obj-y) -$(SOFTMMU_ALL_RULES): $(chardev-obj-y) -$(SOFTMMU_ALL_RULES): $(crypto-obj-y) -$(SOFTMMU_ALL_RULES): $(io-obj-y) -$(SOFTMMU_ALL_RULES): config-all-devices.mak -ifdef DECOMPRESS_EDK2_BLOBS -$(SOFTMMU_ALL_RULES): $(edk2-decompressed) -endif - -SOFTMMU_FUZZ_RULES=$(filter %-softmmu/fuzz, $(TARGET_DIRS_RULES)) -$(SOFTMMU_FUZZ_RULES): $(authz-obj-y) -$(SOFTMMU_FUZZ_RULES): $(block-obj-y) -$(SOFTMMU_FUZZ_RULES): $(chardev-obj-y) -$(SOFTMMU_FUZZ_RULES): $(crypto-obj-y) -$(SOFTMMU_FUZZ_RULES): $(io-obj-y) -$(SOFTMMU_FUZZ_RULES): config-all-devices.mak -$(SOFTMMU_FUZZ_RULES): $(edk2-decompressed) - -.PHONY: $(TARGET_DIRS_RULES) -# The $(TARGET_DIRS_RULES) are of the form SUBDIR/GOAL, so that -# $(dir $@) yields the sub-directory, and $(notdir $@) yields the sub-goal -$(TARGET_DIRS_RULES): - $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" TARGET_DIR="$(dir $@)" $(notdir $@),) - -DTC_MAKE_ARGS=-I$(SRC_PATH)/dtc VPATH=$(SRC_PATH)/dtc -C dtc V="$(V)" LIBFDT_srcdir=$(SRC_PATH)/dtc/libfdt -DTC_CFLAGS=$(CFLAGS) $(QEMU_CFLAGS) -DTC_CPPFLAGS=-I$(BUILD_DIR)/dtc -I$(SRC_PATH)/dtc -I$(SRC_PATH)/dtc/libfdt - -.PHONY: dtc/all -dtc/all: .git-submodule-status dtc/libfdt dtc/tests - $(call quiet-command,$(MAKE) $(DTC_MAKE_ARGS) CPPFLAGS="$(DTC_CPPFLAGS)" CFLAGS="$(DTC_CFLAGS)" LDFLAGS="$(QEMU_LDFLAGS)" ARFLAGS="$(ARFLAGS)" CC="$(CC)" AR="$(AR)" LD="$(LD)" $(SUBDIR_MAKEFLAGS) libfdt/libfdt.a,) - -dtc/%: .git-submodule-status - @mkdir -p $@ - -# Overriding CFLAGS causes us to lose defines added in the sub-makefile. -# Not overriding CFLAGS leads to mis-matches between compilation modes. -# Therefore we replicate some of the logic in the sub-makefile. -# Remove all the extra -Warning flags that QEMU uses that Capstone doesn't; -# no need to annoy QEMU developers with such things. -CAP_CFLAGS = $(patsubst -W%,,$(CFLAGS) $(QEMU_CFLAGS)) -CAP_CFLAGS += -DCAPSTONE_USE_SYS_DYN_MEM -CAP_CFLAGS += -DCAPSTONE_HAS_ARM -CAP_CFLAGS += -DCAPSTONE_HAS_ARM64 -CAP_CFLAGS += -DCAPSTONE_HAS_POWERPC -CAP_CFLAGS += -DCAPSTONE_HAS_X86 - -.PHONY: capstone/all -capstone/all: .git-submodule-status - $(call quiet-command,$(MAKE) -C $(SRC_PATH)/capstone CAPSTONE_SHARED=no BUILDDIR="$(BUILD_DIR)/capstone" CC="$(CC)" AR="$(AR)" LD="$(LD)" RANLIB="$(RANLIB)" CFLAGS="$(CAP_CFLAGS)" $(SUBDIR_MAKEFLAGS) $(BUILD_DIR)/capstone/$(LIBCAPSTONE)) - -.PHONY: slirp/all -slirp/all: .git-submodule-status - $(call quiet-command,$(MAKE) -C $(SRC_PATH)/slirp \ - BUILD_DIR="$(BUILD_DIR)/slirp" \ - PKG_CONFIG="$(PKG_CONFIG)" \ - CC="$(CC)" AR="$(AR)" LD="$(LD)" RANLIB="$(RANLIB)" \ - CFLAGS="$(QEMU_CFLAGS) $(CFLAGS)" LDFLAGS="$(QEMU_LDFLAGS)") - -# Compatibility gunk to keep make working across the rename of targets -# for recursion, to be removed some time after 4.1. -subdir-dtc: dtc/all -subdir-capstone: capstone/all -subdir-slirp: slirp/all - -$(filter %/all, $(TARGET_DIRS_RULES)): libqemuutil.a $(common-obj-y) \ - $(qom-obj-y) - -$(filter %/fuzz, $(TARGET_DIRS_RULES)): libqemuutil.a $(common-obj-y) \ - $(qom-obj-y) $(crypto-user-obj-$(CONFIG_USER_ONLY)) +all: recurse-all ROM_DIRS = $(addprefix pc-bios/, $(ROMS)) ROM_DIRS_RULES=$(foreach t, all clean, $(addsuffix /$(t), $(ROM_DIRS))) # Only keep -O and -g cflags .PHONY: $(ROM_DIRS_RULES) $(ROM_DIRS_RULES): - $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" TARGET_DIR="$(dir $@)" CFLAGS="$(filter -O% -g%,$(CFLAGS))" $(notdir $@),) - -.PHONY: recurse-all recurse-clean recurse-install -recurse-all: $(addsuffix /all, $(TARGET_DIRS) $(ROM_DIRS)) -recurse-clean: $(addsuffix /clean, $(TARGET_DIRS) $(ROM_DIRS)) -recurse-install: $(addsuffix /install, $(TARGET_DIRS)) -$(addsuffix /install, $(TARGET_DIRS)): all - -$(BUILD_DIR)/version.o: $(SRC_PATH)/version.rc config-host.h - $(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<,"RC","version.o") - -Makefile: $(version-obj-y) - -###################################################################### -# Build libraries + $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" TARGET_DIR="$(dir $@)" $(notdir $@),) -libqemuutil.a: $(util-obj-y) $(trace-obj-y) $(stub-obj-y) -libvhost-user.a: $(libvhost-user-obj-y) $(util-obj-y) $(stub-obj-y) +.PHONY: recurse-all recurse-clean +recurse-all: $(addsuffix /all, $(ROM_DIRS)) +recurse-clean: $(addsuffix /clean, $(ROM_DIRS)) ###################################################################### -COMMON_LDADDS = libqemuutil.a - -qemu-img.o: qemu-img-cmds.h - -qemu-img$(EXESUF): qemu-img.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS) -qemu-nbd$(EXESUF): qemu-nbd.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS) -qemu-io$(EXESUF): qemu-io.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS) -qemu-storage-daemon$(EXESUF): qemu-storage-daemon.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(chardev-obj-y) $(io-obj-y) $(qom-obj-y) $(storage-daemon-obj-y) $(COMMON_LDADDS) - -qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o $(COMMON_LDADDS) - -qemu-keymap$(EXESUF): qemu-keymap.o ui/input-keymap.o $(COMMON_LDADDS) - -qemu-edid$(EXESUF): qemu-edid.o hw/display/edid-generate.o $(COMMON_LDADDS) - -fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/9p-marshal.o fsdev/9p-iov-marshal.o $(COMMON_LDADDS) - -scsi/qemu-pr-helper$(EXESUF): scsi/qemu-pr-helper.o scsi/utils.o $(authz-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS) -ifdef CONFIG_MPATH -scsi/qemu-pr-helper$(EXESUF): LIBS += -ludev -lmultipath -lmpathpersist -endif - -qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool - $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"GEN","$@") - -qemu-ga$(EXESUF): LIBS = $(LIBS_QGA) -qemu-ga$(EXESUF): QEMU_CFLAGS += -I qga/qapi-generated - -qemu-keymap$(EXESUF): LIBS += $(XKBCOMMON_LIBS) -qemu-keymap$(EXESUF): QEMU_CFLAGS += $(XKBCOMMON_CFLAGS) - -qapi-py = $(SRC_PATH)/scripts/qapi/__init__.py \ -$(SRC_PATH)/scripts/qapi/commands.py \ -$(SRC_PATH)/scripts/qapi/common.py \ -$(SRC_PATH)/scripts/qapi/doc.py \ -$(SRC_PATH)/scripts/qapi/error.py \ -$(SRC_PATH)/scripts/qapi/events.py \ -$(SRC_PATH)/scripts/qapi/expr.py \ -$(SRC_PATH)/scripts/qapi/gen.py \ -$(SRC_PATH)/scripts/qapi/introspect.py \ -$(SRC_PATH)/scripts/qapi/parser.py \ -$(SRC_PATH)/scripts/qapi/schema.py \ -$(SRC_PATH)/scripts/qapi/source.py \ -$(SRC_PATH)/scripts/qapi/types.py \ -$(SRC_PATH)/scripts/qapi/visit.py \ -$(SRC_PATH)/scripts/qapi-gen.py - -qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h \ -qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h \ -qga/qapi-generated/qga-qapi-commands.h qga/qapi-generated/qga-qapi-commands.c \ -qga/qapi-generated/qga-qapi-init-commands.h qga/qapi-generated/qga-qapi-init-commands.c \ -qga/qapi-generated/qga-qapi-doc.texi: \ -qga/qapi-generated/qapi-gen-timestamp ; -qga/qapi-generated/qapi-gen-timestamp: $(SRC_PATH)/qga/qapi-schema.json $(qapi-py) - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \ - -o qga/qapi-generated -p "qga-" $<, \ - "GEN","$(@:%-timestamp=%)") - @>$@ - -qapi-modules = $(SRC_PATH)/qapi/qapi-schema.json \ - $(QAPI_MODULES:%=$(SRC_PATH)/qapi/%.json) - -$(GENERATED_QAPI_FILES): qapi-gen-timestamp ; -qapi-gen-timestamp: $(qapi-modules) $(qapi-py) - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \ - -o "qapi" -b $<, \ - "GEN","$(@:%-timestamp=%)") - @>$@ - -qapi-modules-storage-daemon = \ - $(SRC_PATH)/storage-daemon/qapi/qapi-schema.json \ - $(QAPI_MODULES_STORAGE_DAEMON:%=$(SRC_PATH)/qapi/%.json) - -$(GENERATED_STORAGE_DAEMON_QAPI_FILES): storage-daemon/qapi/qapi-gen-timestamp ; -storage-daemon/qapi/qapi-gen-timestamp: $(qapi-modules-storage-daemon) $(qapi-py) - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \ - -o "storage-daemon/qapi" $<, \ - "GEN","$(@:%-timestamp=%)") - @>$@ - -QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qapi-commands.h qga-qapi-init-commands.h) -$(qga-obj-y): $(QGALIB_GEN) - -qemu-ga$(EXESUF): $(qga-obj-y) $(COMMON_LDADDS) - $(call LINK, $^) - -ifdef QEMU_GA_MSI_ENABLED -QEMU_GA_MSI=qemu-ga-$(ARCH).msi - -msi: $(QEMU_GA_MSI) - -$(QEMU_GA_MSI): qemu-ga.exe $(QGA_VSS_PROVIDER) - -$(QEMU_GA_MSI): config-host.mak - -$(QEMU_GA_MSI): $(SRC_PATH)/qga/installer/qemu-ga.wxs - $(call quiet-command,QEMU_GA_VERSION="$(QEMU_GA_VERSION)" QEMU_GA_MANUFACTURER="$(QEMU_GA_MANUFACTURER)" QEMU_GA_DISTRO="$(QEMU_GA_DISTRO)" BUILD_DIR="$(BUILD_DIR)" \ - wixl -o $@ $(QEMU_GA_MSI_ARCH) $(QEMU_GA_MSI_WITH_VSS) $(QEMU_GA_MSI_MINGW_DLL_PATH) $<,"WIXL","$@") -else -msi: - @echo "MSI build not configured or dependency resolution failed (reconfigure with --enable-guest-agent-msi option)" -endif - -ifneq ($(EXESUF),) -.PHONY: qemu-ga -qemu-ga: qemu-ga$(EXESUF) $(QGA_VSS_PROVIDER) $(QEMU_GA_MSI) -endif - -elf2dmp$(EXESUF): $(elf2dmp-obj-y) - $(call LINK, $^) - -ifdef CONFIG_IVSHMEM -ivshmem-client$(EXESUF): $(ivshmem-client-obj-y) $(COMMON_LDADDS) - $(call LINK, $^) -ivshmem-server$(EXESUF): $(ivshmem-server-obj-y) $(COMMON_LDADDS) - $(call LINK, $^) -endif -vhost-user-scsi$(EXESUF): $(vhost-user-scsi-obj-y) libvhost-user.a - $(call LINK, $^) -vhost-user-blk$(EXESUF): $(vhost-user-blk-obj-y) libvhost-user.a - $(call LINK, $^) - -rdmacm-mux$(EXESUF): LIBS += "-libumad" -rdmacm-mux$(EXESUF): $(rdmacm-mux-obj-y) $(COMMON_LDADDS) - $(call LINK, $^) - -# relies on Linux-specific syscalls -ifeq ($(CONFIG_LINUX)$(CONFIG_SECCOMP)$(CONFIG_LIBCAP_NG),yyy) -virtiofsd$(EXESUF): $(virtiofsd-obj-y) libvhost-user.a $(COMMON_LDADDS) - $(call LINK, $^) -endif - -vhost-user-gpu$(EXESUF): $(vhost-user-gpu-obj-y) $(libvhost-user-obj-y) libqemuutil.a libqemustub.a - $(call LINK, $^) - -ifdef CONFIG_VHOST_USER_INPUT -ifdef CONFIG_LINUX -vhost-user-input$(EXESUF): $(vhost-user-input-obj-y) libvhost-user.a libqemuutil.a - $(call LINK, $^) - -# build by default, do not install -all: vhost-user-input$(EXESUF) -endif -endif - -module_block.h: $(SRC_PATH)/scripts/modules/module_block.py config-host.mak - $(call quiet-command,$(PYTHON) $< $@ \ - $(addprefix $(SRC_PATH)/,$(patsubst %.mo,%.c,$(block-obj-m))), \ - "GEN","$@") - -ifdef CONFIG_GCOV -.PHONY: clean-coverage -clean-coverage: - $(call quiet-command, \ - find . \( -name '*.gcda' -o -name '*.gcov' \) -type f -exec rm {} +, \ - "CLEAN", "coverage files") -endif - clean: recurse-clean + -$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean || : + -$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) clean-ctlist || : # avoid old build problems by removing potentially incorrect old files rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h - rm -f qemu-options.def - rm -f *.msi - find . \( -name '*.so' -o -name '*.dll' -o -name '*.mo' -o -name '*.[oda]' \) -type f \ + find . \( -name '*.so' -o -name '*.dll' -o -name '*.[oda]' \) -type f \ ! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-aarch64.a \ ! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-arm.a \ - ! -path ./roms/edk2/BaseTools/Source/Python/UPT/Dll/sqlite3.dll \ -exec rm {} + - rm -f $(edk2-decompressed) - rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) TAGS cscope.* *.pod *~ */*~ + rm -f TAGS cscope.* *.pod *~ */*~ rm -f fsdev/*.pod scsi/*.pod - rm -f qemu-img-cmds.h - rm -f ui/shader/*-vert.h ui/shader/*-frag.h - @# May not be present in generated-files-y - rm -f trace/generated-tracers-dtrace.dtrace* - rm -f trace/generated-tracers-dtrace.h* - rm -f $(foreach f,$(generated-files-y),$(f) $(f)-timestamp) - rm -f qapi-gen-timestamp - rm -f storage-daemon/qapi/qapi-gen-timestamp - rm -rf qga/qapi-generated - rm -f config-all-devices.mak -VERSION ?= $(shell cat VERSION) +VERSION = $(shell cat $(SRC_PATH)/VERSION) dist: qemu-$(VERSION).tar.bz2 qemu-%.tar.bz2: $(SRC_PATH)/scripts/make-release "$(SRC_PATH)" "$(patsubst qemu-%.tar.bz2,%,$@)" -define clean-manual = -rm -rf $(MANUAL_BUILDDIR)/$1/_static -rm -f $(MANUAL_BUILDDIR)/$1/objects.inv $(MANUAL_BUILDDIR)/$1/searchindex.js $(MANUAL_BUILDDIR)/$1/*.html -endef - distclean: clean - rm -f config-host.mak config-host.h* $(DOCS) + -$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean -g || : + rm -f config-host.mak config-host.h* rm -f tests/tcg/config-*.mak - rm -f config-all-devices.mak config-all-disas.mak config.status - rm -f $(SUBDIR_DEVICES_MAK) - rm -f po/*.mo tests/qemu-iotests/common.env + rm -f config-all-disas.mak config.status + rm -f tests/qemu-iotests/common.env rm -f roms/seabios/config.mak roms/vgabios/config.mak rm -f qemu-plugins-ld.symbols qemu-plugins-ld64.symbols + rm -f *-config-target.h *-config-devices.mak *-config-devices.h + rm -rf meson-private meson-logs meson-info compile_commands.json + rm -f Makefile.ninja Makefile.mtest build.ninja.stamp meson.stamp rm -f config.log rm -f linux-headers/asm - rm -f docs/version.texi - rm -f docs/interop/qemu-ga-qapi.texi docs/interop/qemu-qmp-qapi.texi - rm -f docs/interop/qemu-qmp-ref.7 docs/interop/qemu-ga-ref.7 - rm -f docs/interop/qemu-qmp-ref.txt docs/interop/qemu-ga-ref.txt - rm -f docs/interop/qemu-qmp-ref.pdf docs/interop/qemu-ga-ref.pdf - rm -f docs/interop/qemu-qmp-ref.html docs/interop/qemu-ga-ref.html - rm -rf .doctrees - $(call clean-manual,devel) - $(call clean-manual,interop) - $(call clean-manual,specs) - $(call clean-manual,system) - $(call clean-manual,tools) - $(call clean-manual,user) - for d in $(TARGET_DIRS); do \ - rm -rf $$d || exit 1 ; \ - done rm -Rf .sdk - if test -f dtc/version_gen.h; then $(MAKE) $(DTC_MAKE_ARGS) clean; fi - -KEYMAPS=da en-gb et fr fr-ch is lt no pt-br sv \ -ar de en-us fi fr-be hr it lv nl pl ru th \ -de-ch es fo fr-ca hu ja mk pt sl tr \ -bepo cz - -ifdef INSTALL_BLOBS -BLOBS=bios.bin bios-256k.bin bios-microvm.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \ -vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin vgabios-virtio.bin \ -vgabios-ramfb.bin vgabios-bochs-display.bin vgabios-ati.bin \ -openbios-sparc32 openbios-sparc64 openbios-ppc QEMU,tcx.bin QEMU,cgthree.bin \ -pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \ -pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \ -efi-e1000.rom efi-eepro100.rom efi-ne2k_pci.rom \ -efi-pcnet.rom efi-rtl8139.rom efi-virtio.rom \ -efi-e1000e.rom efi-vmxnet3.rom \ -qemu-nsis.bmp \ -bamboo.dtb canyonlands.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \ -multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin pvh.bin \ -s390-ccw.img s390-netboot.img \ -slof.bin skiboot.lid \ -palcode-clipper \ -u-boot.e500 u-boot-sam460-20100605.bin \ -qemu_vga.ndrv \ -edk2-licenses.txt \ -hppa-firmware.img \ -opensbi-riscv32-sifive_u-fw_jump.bin opensbi-riscv32-virt-fw_jump.bin \ -opensbi-riscv64-sifive_u-fw_jump.bin opensbi-riscv64-virt-fw_jump.bin - - -DESCS=50-edk2-i386-secure.json 50-edk2-x86_64-secure.json \ -60-edk2-aarch64.json 60-edk2-arm.json 60-edk2-i386.json 60-edk2-x86_64.json -else -BLOBS= -DESCS= -endif - -# Note that we manually filter-out the non-Sphinx documentation which -# is currently built into the docs/interop directory in the build tree, -# and also any sphinx-built manpages. -define install-manual = -for d in $$(cd $(MANUAL_BUILDDIR) && find $1 -type d); do $(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)/$$d"; done -for f in $$(cd $(MANUAL_BUILDDIR) && find $1 -type f -a '!' '(' -name '*.[0-9]' -o -name 'qemu-*-qapi.*' -o -name 'qemu-*-ref.*' ')' ); do $(INSTALL_DATA) "$(MANUAL_BUILDDIR)/$$f" "$(DESTDIR)$(qemu_docdir)/$$f"; done -endef - -# Note that we deliberately do not install the "devel" manual: it is -# for QEMU developers, and not interesting to our users. -.PHONY: install-sphinxdocs -install-sphinxdocs: sphinxdocs - $(call install-manual,interop) - $(call install-manual,specs) - $(call install-manual,system) - $(call install-manual,tools) - $(call install-manual,user) - -install-doc: $(DOCS) install-sphinxdocs - $(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)" - $(INSTALL_DATA) $(MANUAL_BUILDDIR)/index.html "$(DESTDIR)$(qemu_docdir)" - $(INSTALL_DATA) docs/interop/qemu-qmp-ref.html "$(DESTDIR)$(qemu_docdir)" - $(INSTALL_DATA) docs/interop/qemu-qmp-ref.txt "$(DESTDIR)$(qemu_docdir)" -ifdef CONFIG_POSIX - $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1" - $(INSTALL_DATA) $(MANUAL_BUILDDIR)/system/qemu.1 "$(DESTDIR)$(mandir)/man1" - $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man7" - $(INSTALL_DATA) docs/interop/qemu-qmp-ref.7 "$(DESTDIR)$(mandir)/man7" - $(INSTALL_DATA) $(MANUAL_BUILDDIR)/system/qemu-block-drivers.7 "$(DESTDIR)$(mandir)/man7" - $(INSTALL_DATA) $(MANUAL_BUILDDIR)/system/qemu-cpu-models.7 "$(DESTDIR)$(mandir)/man7" -ifeq ($(CONFIG_TOOLS),y) - $(INSTALL_DATA) $(MANUAL_BUILDDIR)/tools/qemu-img.1 "$(DESTDIR)$(mandir)/man1" - $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man8" - $(INSTALL_DATA) $(MANUAL_BUILDDIR)/tools/qemu-nbd.8 "$(DESTDIR)$(mandir)/man8" -endif -ifdef CONFIG_TRACE_SYSTEMTAP - $(INSTALL_DATA) $(MANUAL_BUILDDIR)/tools/qemu-trace-stap.1 "$(DESTDIR)$(mandir)/man1" -endif -ifneq (,$(findstring qemu-ga,$(TOOLS))) - $(INSTALL_DATA) $(MANUAL_BUILDDIR)/interop/qemu-ga.8 "$(DESTDIR)$(mandir)/man8" - $(INSTALL_DATA) docs/interop/qemu-ga-ref.html "$(DESTDIR)$(qemu_docdir)" - $(INSTALL_DATA) docs/interop/qemu-ga-ref.txt "$(DESTDIR)$(qemu_docdir)" - $(INSTALL_DATA) docs/interop/qemu-ga-ref.7 "$(DESTDIR)$(mandir)/man7" -endif -endif -ifdef CONFIG_VIRTFS - $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1" - $(INSTALL_DATA) $(MANUAL_BUILDDIR)/tools/virtfs-proxy-helper.1 "$(DESTDIR)$(mandir)/man1" -endif -ifeq ($(CONFIG_LINUX)$(CONFIG_SECCOMP)$(CONFIG_LIBCAP_NG),yyy) - $(INSTALL_DATA) $(MANUAL_BUILDDIR)/tools/virtiofsd.1 "$(DESTDIR)$(mandir)/man1" -endif - -install-datadir: - $(INSTALL_DIR) "$(DESTDIR)$(qemu_datadir)" - -install-localstatedir: -ifdef CONFIG_POSIX -ifneq (,$(findstring qemu-ga,$(TOOLS))) - $(INSTALL_DIR) "$(DESTDIR)$(qemu_localstatedir)"/run -endif -endif - -ICON_SIZES=16x16 24x24 32x32 48x48 64x64 128x128 256x256 512x512 -install-includedir: - $(INSTALL_DIR) "$(DESTDIR)$(includedir)" - -install: all $(if $(BUILD_DOCS),install-doc) \ - install-datadir install-localstatedir install-includedir \ - $(if $(INSTALL_BLOBS),$(edk2-decompressed)) \ - recurse-install -ifneq ($(TOOLS),) - $(call install-prog,$(TOOLS),$(DESTDIR)$(bindir)) -endif -ifneq ($(CONFIG_MODULES),) - $(INSTALL_DIR) "$(DESTDIR)$(qemu_moddir)" - for s in $(modules-m:.mo=$(DSOSUF)); do \ - t="$(DESTDIR)$(qemu_moddir)/$$(echo $$s | tr / -)"; \ - $(INSTALL_LIB) $$s "$$t"; \ - test -z "$(STRIP)" || $(STRIP) "$$t"; \ - done -endif -ifneq ($(HELPERS-y),) - $(call install-prog,$(HELPERS-y),$(DESTDIR)$(libexecdir)) -endif -ifneq ($(vhost-user-json-y),) - $(INSTALL_DIR) "$(DESTDIR)$(qemu_datadir)/vhost-user/" - for x in $(vhost-user-json-y); do \ - $(INSTALL_DATA) $$x "$(DESTDIR)$(qemu_datadir)/vhost-user/"; \ - done -endif -ifdef CONFIG_TRACE_SYSTEMTAP - $(INSTALL_PROG) "scripts/qemu-trace-stap" $(DESTDIR)$(bindir) -endif -ifneq ($(BLOBS),) - set -e; for x in $(BLOBS); do \ - $(INSTALL_DATA) $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(qemu_datadir)"; \ - done -endif -ifdef INSTALL_BLOBS - set -e; for x in $(edk2-decompressed); do \ - $(INSTALL_DATA) $$x "$(DESTDIR)$(qemu_datadir)"; \ - done -endif -ifneq ($(DESCS),) - $(INSTALL_DIR) "$(DESTDIR)$(qemu_datadir)/firmware" - set -e; tmpf=$$(mktemp); trap 'rm -f -- "$$tmpf"' EXIT; \ - for x in $(DESCS); do \ - sed -e 's,@DATADIR@,$(qemu_datadir),' \ - "$(SRC_PATH)/pc-bios/descriptors/$$x" > "$$tmpf"; \ - $(INSTALL_DATA) "$$tmpf" \ - "$(DESTDIR)$(qemu_datadir)/firmware/$$x"; \ - done -endif - for s in $(ICON_SIZES); do \ - mkdir -p "$(DESTDIR)$(qemu_icondir)/hicolor/$${s}/apps"; \ - $(INSTALL_DATA) $(SRC_PATH)/ui/icons/qemu_$${s}.png \ - "$(DESTDIR)$(qemu_icondir)/hicolor/$${s}/apps/qemu.png"; \ - done; \ - mkdir -p "$(DESTDIR)$(qemu_icondir)/hicolor/32x32/apps"; \ - $(INSTALL_DATA) $(SRC_PATH)/ui/icons/qemu_32x32.bmp \ - "$(DESTDIR)$(qemu_icondir)/hicolor/32x32/apps/qemu.bmp"; \ - mkdir -p "$(DESTDIR)$(qemu_icondir)/hicolor/scalable/apps"; \ - $(INSTALL_DATA) $(SRC_PATH)/ui/icons/qemu.svg \ - "$(DESTDIR)$(qemu_icondir)/hicolor/scalable/apps/qemu.svg" - mkdir -p "$(DESTDIR)$(qemu_desktopdir)" - $(INSTALL_DATA) $(SRC_PATH)/ui/qemu.desktop \ - "$(DESTDIR)$(qemu_desktopdir)/qemu.desktop" -ifdef CONFIG_GTK - $(MAKE) -C po $@ -endif -ifeq ($(CONFIG_PLUGIN),y) - $(INSTALL_DATA) $(SRC_PATH)/include/qemu/qemu-plugin.h "$(DESTDIR)$(includedir)/qemu-plugin.h" -endif - $(INSTALL_DIR) "$(DESTDIR)$(qemu_datadir)/keymaps" - set -e; for x in $(KEYMAPS); do \ - $(INSTALL_DATA) $(SRC_PATH)/pc-bios/keymaps/$$x "$(DESTDIR)$(qemu_datadir)/keymaps"; \ - done - $(INSTALL_DATA) $(BUILD_DIR)/trace-events-all "$(DESTDIR)$(qemu_datadir)/trace-events-all" +find-src-path = find "$(SRC_PATH)/" -path "$(SRC_PATH)/meson" -prune -o \( -name "*.[chsS]" -o -name "*.[ch].inc" \) .PHONY: ctags ctags: - rm -f tags - find "$(SRC_PATH)" -name '*.[hc]' -exec ctags --append {} + + rm -f "$(SRC_PATH)/"tags + $(find-src-path) -exec ctags -f "$(SRC_PATH)/"tags --append {} + .PHONY: TAGS TAGS: - rm -f TAGS - find "$(SRC_PATH)" -name '*.[hc]' -exec etags --append {} + + rm -f "$(SRC_PATH)/"TAGS + $(find-src-path) -exec etags -f "$(SRC_PATH)/"TAGS --append {} + +.PHONY: cscope cscope: rm -f "$(SRC_PATH)"/cscope.* - find "$(SRC_PATH)/" -name "*.[chsS]" -print | sed 's,^\./,,' > "$(SRC_PATH)/cscope.files" - cscope -b -i"$(SRC_PATH)/cscope.files" - -# opengl shader programs -ui/shader/%-vert.h: $(SRC_PATH)/ui/shader/%.vert $(SRC_PATH)/scripts/shaderinclude.pl - @mkdir -p $(dir $@) - $(call quiet-command,\ - perl $(SRC_PATH)/scripts/shaderinclude.pl $< > $@,\ - "VERT","$@") - -ui/shader/%-frag.h: $(SRC_PATH)/ui/shader/%.frag $(SRC_PATH)/scripts/shaderinclude.pl - @mkdir -p $(dir $@) - $(call quiet-command,\ - perl $(SRC_PATH)/scripts/shaderinclude.pl $< > $@,\ - "FRAG","$@") - -ui/shader.o: $(SRC_PATH)/ui/shader.c \ - ui/shader/texture-blit-vert.h \ - ui/shader/texture-blit-flip-vert.h \ - ui/shader/texture-blit-frag.h - -# documentation -MAKEINFO=makeinfo -MAKEINFOINCLUDES= -I docs -I $( $@,"GEN","$@") - -%.html: %.texi docs/version.texi - $(call quiet-command,LC_ALL=C $(MAKEINFO) $(MAKEINFOFLAGS) --no-headers \ - --html $< -o $@,"GEN","$@") - -%.info: %.texi docs/version.texi - $(call quiet-command,$(MAKEINFO) $(MAKEINFOFLAGS) $< -o $@,"GEN","$@") - -%.txt: %.texi docs/version.texi - $(call quiet-command,LC_ALL=C $(MAKEINFO) $(MAKEINFOFLAGS) --no-headers \ - --plaintext $< -o $@,"GEN","$@") - -%.pdf: %.texi docs/version.texi - $(call quiet-command,texi2pdf $(TEXI2PDFFLAGS) $< -o $@,"GEN","$@") - -# Sphinx builds all its documentation at once in one invocation -# and handles "don't rebuild things unless necessary" itself. -# The '.doctrees' files are cached information to speed this up. -.PHONY: sphinxdocs -sphinxdocs: $(MANUAL_BUILDDIR)/devel/index.html \ - $(MANUAL_BUILDDIR)/interop/index.html \ - $(MANUAL_BUILDDIR)/specs/index.html \ - $(MANUAL_BUILDDIR)/system/index.html \ - $(MANUAL_BUILDDIR)/tools/index.html \ - $(MANUAL_BUILDDIR)/user/index.html - -# Canned command to build a single manual -# Arguments: $1 = manual name, $2 = Sphinx builder ('html' or 'man') -# Note the use of different doctree for each (manual, builder) tuple; -# this works around Sphinx not handling parallel invocation on -# a single doctree: https://github.com/sphinx-doc/sphinx/issues/2946 -build-manual = $(call quiet-command,CONFDIR="$(qemu_confdir)" $(SPHINX_BUILD) $(if $(V),,-q) $(SPHINX_WERROR) -b $2 -D version=$(VERSION) -D release="$(FULL_VERSION)" -d .doctrees/$1-$2 $(SRC_PATH)/docs/$1 $(MANUAL_BUILDDIR)/$1 ,"SPHINX","$(MANUAL_BUILDDIR)/$1") -# We assume all RST files in the manual's directory are used in it -manual-deps = $(wildcard $(SRC_PATH)/docs/$1/*.rst $(SRC_PATH)/docs/$1/*/*.rst) \ - $(SRC_PATH)/docs/defs.rst.inc \ - $(SRC_PATH)/docs/$1/conf.py $(SRC_PATH)/docs/conf.py \ - $(SRC_PATH)/docs/sphinx/*.py -# Macro to write out the rule and dependencies for building manpages -# Usage: $(call define-manpage-rule,manualname,manpage1 manpage2...[,extradeps]) -# 'extradeps' is optional, and specifies extra files (eg .hx files) that -# the manual page depends on. -define define-manpage-rule -$(call atomic,$(foreach manpage,$2,$(MANUAL_BUILDDIR)/$1/$(manpage)),$(call manual-deps,$1) $3) - $(call build-manual,$1,man) -endef - -$(MANUAL_BUILDDIR)/devel/index.html: $(call manual-deps,devel) - $(call build-manual,devel,html) - -$(MANUAL_BUILDDIR)/interop/index.html: $(call manual-deps,interop) - $(call build-manual,interop,html) - -$(MANUAL_BUILDDIR)/specs/index.html: $(call manual-deps,specs) - $(call build-manual,specs,html) - -$(MANUAL_BUILDDIR)/system/index.html: $(call manual-deps,system) $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/qemu-options.hx - $(call build-manual,system,html) - -$(MANUAL_BUILDDIR)/tools/index.html: $(call manual-deps,tools) $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/docs/qemu-option-trace.rst.inc - $(call build-manual,tools,html) - -$(MANUAL_BUILDDIR)/user/index.html: $(call manual-deps,user) - $(call build-manual,user,html) - -$(call define-manpage-rule,interop,qemu-ga.8) - -$(call define-manpage-rule,system,qemu.1 qemu-block-drivers.7 qemu-cpu-models.7) - -$(call define-manpage-rule,tools,\ - qemu-img.1 qemu-nbd.8 qemu-trace-stap.1\ - virtiofsd.1 virtfs-proxy-helper.1,\ - $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/docs/qemu-option-trace.rst.inc) - -$(MANUAL_BUILDDIR)/index.html: $(SRC_PATH)/docs/index.html.in qemu-version.h - @mkdir -p "$(MANUAL_BUILDDIR)" - $(call quiet-command, sed "s|@@VERSION@@|${VERSION}|g" $< >$@, \ - "GEN","$@") - -docs/interop/qemu-qmp-qapi.texi: qapi/qapi-doc.texi - @cp -p $< $@ - -docs/interop/qemu-ga-qapi.texi: qga/qapi-generated/qga-qapi-doc.texi - @cp -p $< $@ - -html: docs/interop/qemu-qmp-ref.html docs/interop/qemu-ga-ref.html sphinxdocs -info: docs/interop/qemu-qmp-ref.info docs/interop/qemu-ga-ref.info -pdf: docs/interop/qemu-qmp-ref.pdf docs/interop/qemu-ga-ref.pdf -txt: docs/interop/qemu-qmp-ref.txt docs/interop/qemu-ga-ref.txt + $(find-src-path) -print | sed -e 's,^\./,,' > "$(SRC_PATH)/cscope.files" + cscope -b -i"$(SRC_PATH)/cscope.files" -f"$(SRC_PATH)"/cscope.out -docs/interop/qemu-ga-ref.dvi docs/interop/qemu-ga-ref.html \ - docs/interop/qemu-ga-ref.info docs/interop/qemu-ga-ref.pdf \ - docs/interop/qemu-ga-ref.txt docs/interop/qemu-ga-ref.7: \ - docs/interop/qemu-ga-ref.texi docs/interop/qemu-ga-qapi.texi - -docs/interop/qemu-qmp-ref.dvi docs/interop/qemu-qmp-ref.html \ - docs/interop/qemu-qmp-ref.info docs/interop/qemu-qmp-ref.pdf \ - docs/interop/qemu-qmp-ref.txt docs/interop/qemu-qmp-ref.7: \ - docs/interop/qemu-qmp-ref.texi docs/interop/qemu-qmp-qapi.texi - -$(filter %.1 %.7 %.8,$(DOCS)): scripts/texi2pod.pl - -# Reports/Analysis - -%/coverage-report.html: - @mkdir -p $* - $(call quiet-command,\ - gcovr -r $(SRC_PATH) \ - $(foreach t, $(TARGET_DIRS), --object-directory $(BUILD_DIR)/$(t)) \ - --object-directory $(BUILD_DIR) \ - -p --html --html-details -o $@, \ - "GEN", "coverage-report.html") - -.PHONY: coverage-report -coverage-report: $(CURDIR)/reports/coverage/coverage-report.html - -ifdef CONFIG_WIN32 - -INSTALLER = qemu-setup-$(VERSION)$(EXESUF) - -nsisflags = -V2 -NOCD - -ifneq ($(wildcard $(SRC_PATH)/dll),) -ifeq ($(ARCH),x86_64) -# 64 bit executables -DLL_PATH = $(SRC_PATH)/dll/w64 -nsisflags += -DW64 -else -# 32 bit executables -DLL_PATH = $(SRC_PATH)/dll/w32 -endif -endif - -.PHONY: installer -installer: $(INSTALLER) - -INSTDIR=/tmp/qemu-nsis - -$(INSTALLER): install-doc $(SRC_PATH)/qemu.nsi - $(MAKE) install prefix=${INSTDIR} -ifdef SIGNCODE - (cd ${INSTDIR}; \ - for i in *.exe; do \ - $(SIGNCODE) $${i}; \ - done \ - ) -endif # SIGNCODE - (cd ${INSTDIR}; \ - for i in qemu-system-*.exe; do \ - arch=$${i%.exe}; \ - arch=$${arch#qemu-system-}; \ - echo Section \"$$arch\" Section_$$arch; \ - echo SetOutPath \"\$$INSTDIR\"; \ - echo File \"\$${BINDIR}\\$$i\"; \ - echo SectionEnd; \ - done \ - ) >${INSTDIR}/system-emulations.nsh - makensis $(nsisflags) \ - $(if $(BUILD_DOCS),-DCONFIG_DOCUMENTATION="y") \ - $(if $(CONFIG_GTK),-DCONFIG_GTK="y") \ - -DBINDIR="${INSTDIR}" \ - $(if $(DLL_PATH),-DDLLDIR="$(DLL_PATH)") \ - -DSRCDIR="$(SRC_PATH)" \ - -DOUTFILE="$(INSTALLER)" \ - -DDISPLAYVERSION="$(VERSION)" \ - $(SRC_PATH)/qemu.nsi - rm -r ${INSTDIR} -ifdef SIGNCODE - $(SIGNCODE) $(INSTALLER) -endif # SIGNCODE -endif # CONFIG_WIN - -# Add a dependency on the generated files, so that they are always -# rebuilt before other object files -ifneq ($(wildcard config-host.mak),) -ifneq ($(filter-out $(UNCHECKED_GOALS),$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail)) -Makefile: $(generated-files-y) -endif -endif - -.SECONDARY: $(TRACE_HEADERS) $(TRACE_HEADERS:%=%-timestamp) \ - $(TRACE_SOURCES) $(TRACE_SOURCES:%=%-timestamp) \ - $(TRACE_DTRACE) $(TRACE_DTRACE:%=%-timestamp) - -# Include automatically generated dependency files -# Dependencies in Makefile.objs files come from our recursive subdir rules --include $(wildcard *.d tests/*.d) +# Needed by "meson install" +export DESTDIR include $(SRC_PATH)/tests/docker/Makefile.include include $(SRC_PATH)/tests/vm/Makefile.include print-help-run = printf " %-30s - %s\\n" "$1" "$2" -print-help = $(quiet-@)$(call print-help-run,$1,$2) +print-help = @$(call print-help-run,$1,$2) .PHONY: help help: @echo 'Generic targets:' $(call print-help,all,Build all) -ifdef CONFIG_MODULES - $(call print-help,modules,Build all modules) -endif $(call print-help,dir/file.o,Build specified target only) $(call print-help,install,Install QEMU, documentation and tools) $(call print-help,ctags/TAGS,Generate tags file for editors) $(call print-help,cscope,Generate cscope index) + $(call print-help,sparse,Run sparse on the QEMU source) + @echo '' +ifeq ($(CONFIG_PLUGIN),y) + @echo 'Plugin targets:' + $(call print-help,plugins,Build the example TCG plugins) @echo '' - @$(if $(TARGET_DIRS), \ - echo 'Architecture specific targets:'; \ - $(foreach t, $(TARGET_DIRS), \ - $(call print-help-run,$(t)/all,Build for $(t)); \ - $(if $(CONFIG_FUZZ), \ - $(if $(findstring softmmu,$(t)), \ - $(call print-help-run,$(t)/fuzz,Build fuzzer for $(t)); \ - ))) \ - echo '') - @$(if $(TOOLS), \ - echo 'Tools targets:'; \ - $(foreach t, $(TOOLS), \ - $(call print-help-run,$(t),Build $(shell basename $(t)) tool);) \ - echo '') +endif @echo 'Cleaning targets:' $(call print-help,clean,Remove most generated files but keep the config) -ifdef CONFIG_GCOV - $(call print-help,clean-coverage,Remove coverage files) -endif $(call print-help,distclean,Remove all generated files) $(call print-help,dist,Build a distributable tarball) @echo '' @echo 'Test targets:' $(call print-help,check,Run all tests (check-help for details)) + $(call print-help,bench,Run all benchmarks) $(call print-help,docker,Help about targets running tests inside containers) $(call print-help,vm-help,Help about targets running tests inside VM) @echo '' @echo 'Documentation targets:' - $(call print-help,html info pdf txt,Build documentation in specified format) -ifdef CONFIG_GCOV - $(call print-help,coverage-report,Create code coverage report) -endif + $(call print-help,html man,Build documentation in specified format) @echo '' ifdef CONFIG_WIN32 @echo 'Windows targets:' $(call print-help,installer,Build NSIS-based installer for QEMU) -ifdef QEMU_GA_MSI_ENABLED +ifdef CONFIG_QGA_MSI $(call print-help,msi,Build MSI-based installer for qemu-ga) endif @echo '' endif $(call print-help,$(MAKE) [targets],(quiet build, default)) $(call print-help,$(MAKE) V=1 [targets],(verbose build)) + +# will delete the target of a rule if commands exit with a nonzero exit status +.DELETE_ON_ERROR: + +print-%: + @echo '$*=$($*)' diff --git a/Makefile.objs b/Makefile.objs deleted file mode 100644 index 99774cfd25457ef030dfa15fff1184ae7b9ee161..0000000000000000000000000000000000000000 --- a/Makefile.objs +++ /dev/null @@ -1,211 +0,0 @@ -####################################################################### -# Common libraries for tools and emulators -stub-obj-y = stubs/ -util-obj-y = crypto/ util/ qobject/ qapi/ -qom-obj-y = qom/ - -####################################################################### -# code used by both qemu system emulation and qemu-img - -ifeq ($(call lor,$(CONFIG_SOFTMMU),$(CONFIG_TOOLS)),y) - -chardev-obj-y = chardev/ - -authz-obj-y = authz/ - -block-obj-y = block/ block/monitor/ nbd/ scsi/ -block-obj-y += block.o blockjob.o job.o -block-obj-y += qemu-io-cmds.o -block-obj-$(CONFIG_REPLICATION) += replication.o - -block-obj-m = block/ - -crypto-obj-y = crypto/ - -io-obj-y = io/ - -endif # CONFIG_SOFTMMU or CONFIG_TOOLS - -####################################################################### -# storage-daemon-obj-y is code used by qemu-storage-daemon (these objects are -# used for system emulation, too, but specified separately there) - -storage-daemon-obj-y = block/ monitor/ qapi/ qom/ storage-daemon/ -storage-daemon-obj-y += blockdev.o blockdev-nbd.o iothread.o job-qmp.o -storage-daemon-obj-$(CONFIG_WIN32) += os-win32.o -storage-daemon-obj-$(CONFIG_POSIX) += os-posix.o - -###################################################################### -# Target independent part of system emulation. The long term path is to -# suppress *all* target specific code in case of system emulation, i.e. a -# single QEMU executable should support all CPUs and machines. - -ifeq ($(CONFIG_SOFTMMU),y) -common-obj-y = blockdev.o blockdev-nbd.o block/ -common-obj-y += bootdevice.o iothread.o -common-obj-y += dump/ -common-obj-y += job-qmp.o -common-obj-y += monitor/ -common-obj-y += net/ -common-obj-y += qdev-monitor.o -common-obj-$(CONFIG_WIN32) += os-win32.o -common-obj-$(CONFIG_POSIX) += os-posix.o - -common-obj-$(CONFIG_LINUX) += fsdev/ - -common-obj-y += accel/ -common-obj-y += migration/ - -common-obj-y += audio/ -common-obj-m += audio/ -common-obj-y += hw/ - -common-obj-y += replay/ - -common-obj-y += ui/ -common-obj-m += ui/ - -common-obj-y += dma-helpers.o -common-obj-$(CONFIG_TPM) += tpm.o - -common-obj-y += backends/ -common-obj-y += chardev/ - -common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o -qemu-seccomp.o-cflags := $(SECCOMP_CFLAGS) -qemu-seccomp.o-libs := $(SECCOMP_LIBS) - -common-obj-$(CONFIG_FDT) += device_tree.o - -common-obj-y += qapi/ - -endif # CONFIG_SOFTMMU - -####################################################################### -# Target-independent parts used in system and user emulation -common-obj-y += cpus-common.o -common-obj-y += hw/ -common-obj-y += qom/ -common-obj-y += disas/ - -###################################################################### -# Resource file for Windows executables -version-obj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.o - -###################################################################### -# tracing -util-obj-y += trace/ - -###################################################################### -# guest agent - -# FIXME: a few definitions from qapi/qapi-types.o and -# qapi/qapi-visit.o are needed by libqemuutil.a. These should be -# extracted into a QAPI schema module, or perhaps a separate schema. -qga-obj-y = qga/ -qga-vss-dll-obj-y = qga/ - -###################################################################### -# contrib -elf2dmp-obj-y = contrib/elf2dmp/ -ivshmem-client-obj-$(CONFIG_IVSHMEM) = contrib/ivshmem-client/ -ivshmem-server-obj-$(CONFIG_IVSHMEM) = contrib/ivshmem-server/ -libvhost-user-obj-y = contrib/libvhost-user/ -vhost-user-scsi.o-cflags := $(LIBISCSI_CFLAGS) -vhost-user-scsi.o-libs := $(LIBISCSI_LIBS) -vhost-user-scsi-obj-y = contrib/vhost-user-scsi/ -vhost-user-blk-obj-y = contrib/vhost-user-blk/ -rdmacm-mux-obj-y = contrib/rdmacm-mux/ -vhost-user-input-obj-y = contrib/vhost-user-input/ -vhost-user-gpu-obj-y = contrib/vhost-user-gpu/ -virtiofsd-obj-y = tools/virtiofsd/ - -###################################################################### -trace-events-subdirs = -trace-events-subdirs += accel/kvm -trace-events-subdirs += accel/tcg -trace-events-subdirs += backends -trace-events-subdirs += crypto -trace-events-subdirs += monitor -ifeq ($(CONFIG_USER_ONLY),y) -trace-events-subdirs += linux-user -endif -ifeq ($(CONFIG_BLOCK),y) -trace-events-subdirs += authz -trace-events-subdirs += block -trace-events-subdirs += io -trace-events-subdirs += nbd -trace-events-subdirs += scsi -endif -ifeq ($(CONFIG_SOFTMMU),y) -trace-events-subdirs += audio -trace-events-subdirs += chardev -trace-events-subdirs += hw/9pfs -trace-events-subdirs += hw/acpi -trace-events-subdirs += hw/alpha -trace-events-subdirs += hw/arm -trace-events-subdirs += hw/audio -trace-events-subdirs += hw/block -trace-events-subdirs += hw/block/dataplane -trace-events-subdirs += hw/char -trace-events-subdirs += hw/dma -trace-events-subdirs += hw/hppa -trace-events-subdirs += hw/i2c -trace-events-subdirs += hw/i386 -trace-events-subdirs += hw/i386/xen -trace-events-subdirs += hw/ide -trace-events-subdirs += hw/input -trace-events-subdirs += hw/intc -trace-events-subdirs += hw/isa -trace-events-subdirs += hw/mem -trace-events-subdirs += hw/mips -trace-events-subdirs += hw/misc -trace-events-subdirs += hw/misc/macio -trace-events-subdirs += hw/net -trace-events-subdirs += hw/nvram -trace-events-subdirs += hw/pci -trace-events-subdirs += hw/pci-host -trace-events-subdirs += hw/ppc -trace-events-subdirs += hw/rdma -trace-events-subdirs += hw/rdma/vmw -trace-events-subdirs += hw/rtc -trace-events-subdirs += hw/s390x -trace-events-subdirs += hw/scsi -trace-events-subdirs += hw/sd -trace-events-subdirs += hw/sparc -trace-events-subdirs += hw/sparc64 -trace-events-subdirs += hw/ssi -trace-events-subdirs += hw/timer -trace-events-subdirs += hw/tpm -trace-events-subdirs += hw/usb -trace-events-subdirs += hw/vfio -trace-events-subdirs += hw/virtio -trace-events-subdirs += hw/watchdog -trace-events-subdirs += hw/xen -trace-events-subdirs += hw/gpio -trace-events-subdirs += hw/riscv -trace-events-subdirs += migration -trace-events-subdirs += net -trace-events-subdirs += ui -endif -trace-events-subdirs += hw/core -trace-events-subdirs += hw/display -trace-events-subdirs += qapi -trace-events-subdirs += qom -trace-events-subdirs += target/arm -trace-events-subdirs += target/hppa -trace-events-subdirs += target/i386 -trace-events-subdirs += target/mips -trace-events-subdirs += target/ppc -trace-events-subdirs += target/riscv -trace-events-subdirs += target/s390x -trace-events-subdirs += target/sparc -trace-events-subdirs += util - -trace-events-files = $(SRC_PATH)/trace-events $(trace-events-subdirs:%=$(SRC_PATH)/%/trace-events) - -trace-obj-y = trace-root.o -trace-obj-y += $(trace-events-subdirs:%=%/trace.o) -trace-obj-$(CONFIG_TRACE_UST) += trace-ust-all.o -trace-obj-$(CONFIG_TRACE_DTRACE) += trace-dtrace-root.o -trace-obj-$(CONFIG_TRACE_DTRACE) += $(trace-events-subdirs:%=%/trace-dtrace.o) diff --git a/Makefile.target b/Makefile.target deleted file mode 100644 index 8ed1eba95b9c29ab4e47349cbdb2dbdf174d9106..0000000000000000000000000000000000000000 --- a/Makefile.target +++ /dev/null @@ -1,276 +0,0 @@ -# -*- Mode: makefile -*- - -BUILD_DIR?=$(CURDIR)/.. - -include ../config-host.mak -include config-target.mak -include $(SRC_PATH)/rules.mak - -ifdef CONFIG_SOFTMMU -include config-devices.mak -endif - -$(call set-vpath, $(SRC_PATH):$(BUILD_DIR)) -ifdef CONFIG_LINUX -QEMU_CFLAGS += -isystem ../linux-headers -endif -QEMU_CFLAGS += -iquote .. -iquote $(SRC_PATH)/target/$(TARGET_BASE_ARCH) -DNEED_CPU_H - -QEMU_CFLAGS+=-iquote $(SRC_PATH)/include - -ifdef CONFIG_USER_ONLY -# user emulator name -QEMU_PROG=qemu-$(TARGET_NAME) -QEMU_PROG_BUILD = $(QEMU_PROG) -else -# system emulator name -QEMU_PROG=qemu-system-$(TARGET_NAME)$(EXESUF) -ifneq (,$(findstring -mwindows,$(SDL_LIBS))) -# Terminate program name with a 'w' because the linker builds a windows executable. -QEMU_PROGW=qemu-system-$(TARGET_NAME)w$(EXESUF) -$(QEMU_PROG): $(QEMU_PROGW) - $(call quiet-command,$(OBJCOPY) --subsystem console $(QEMU_PROGW) $(QEMU_PROG),"GEN","$(TARGET_DIR)$(QEMU_PROG)") -QEMU_PROG_BUILD = $(QEMU_PROGW) -else -QEMU_PROG_BUILD = $(QEMU_PROG) -endif -endif - -PROGS=$(QEMU_PROG) $(QEMU_PROGW) -STPFILES= - -config-target.h: config-target.h-timestamp -config-target.h-timestamp: config-target.mak - -config-devices.h: config-devices.h-timestamp -config-devices.h-timestamp: config-devices.mak - -ifdef CONFIG_TRACE_SYSTEMTAP -stap: $(QEMU_PROG).stp-installed $(QEMU_PROG).stp $(QEMU_PROG)-simpletrace.stp $(QEMU_PROG)-log.stp - -ifdef CONFIG_USER_ONLY -TARGET_TYPE=user -else -TARGET_TYPE=system -endif - -tracetool-y = $(SRC_PATH)/scripts/tracetool.py -tracetool-y += $(shell find $(SRC_PATH)/scripts/tracetool -name "*.py") - -$(QEMU_PROG).stp-installed: $(BUILD_DIR)/trace-events-all $(tracetool-y) - $(call quiet-command,$(TRACETOOL) \ - --group=all \ - --format=stap \ - --backends=$(TRACE_BACKENDS) \ - --binary=$(bindir)/$(QEMU_PROG) \ - --target-name=$(TARGET_NAME) \ - --target-type=$(TARGET_TYPE) \ - $< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG).stp-installed") - -$(QEMU_PROG).stp: $(BUILD_DIR)/trace-events-all $(tracetool-y) - $(call quiet-command,$(TRACETOOL) \ - --group=all \ - --format=stap \ - --backends=$(TRACE_BACKENDS) \ - --binary=$(realpath .)/$(QEMU_PROG) \ - --target-name=$(TARGET_NAME) \ - --target-type=$(TARGET_TYPE) \ - $< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG).stp") - -$(QEMU_PROG)-simpletrace.stp: $(BUILD_DIR)/trace-events-all $(tracetool-y) - $(call quiet-command,$(TRACETOOL) \ - --group=all \ - --format=simpletrace-stap \ - --backends=$(TRACE_BACKENDS) \ - --probe-prefix=qemu.$(TARGET_TYPE).$(TARGET_NAME) \ - $< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG)-simpletrace.stp") - -$(QEMU_PROG)-log.stp: $(BUILD_DIR)/trace-events-all $(tracetool-y) - $(call quiet-command,$(TRACETOOL) \ - --group=all \ - --format=log-stap \ - --backends=$(TRACE_BACKENDS) \ - --probe-prefix=qemu.$(TARGET_TYPE).$(TARGET_NAME) \ - $< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG)-log.stp") - -else -stap: -endif -.PHONY: stap - -all: $(PROGS) stap - -# Dummy command so that make thinks it has done something - @true - -obj-y += trace/ - -######################################################### -# cpu emulator library -obj-y += exec.o exec-vary.o -obj-y += accel/ -obj-$(CONFIG_TCG) += tcg/tcg.o tcg/tcg-op.o tcg/tcg-op-vec.o tcg/tcg-op-gvec.o -obj-$(CONFIG_TCG) += tcg/tcg-common.o tcg/optimize.o -obj-$(CONFIG_TCG_INTERPRETER) += tcg/tci.o -obj-$(CONFIG_TCG_INTERPRETER) += disas/tci.o -obj-$(CONFIG_TCG) += fpu/softfloat.o -obj-y += target/$(TARGET_BASE_ARCH)/ -obj-y += disas.o -obj-$(call notempty,$(TARGET_XML_FILES)) += gdbstub-xml.o -LIBS := $(libs_cpu) $(LIBS) - -obj-$(CONFIG_PLUGIN) += plugins/ - -######################################################### -# Linux user emulator target - -ifdef CONFIG_LINUX_USER - -QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) \ - -I$(SRC_PATH)/linux-user/host/$(ARCH) \ - -I$(SRC_PATH)/linux-user \ - -Ilinux-user/$(TARGET_ABI_DIR) - -obj-y += linux-user/ -obj-y += gdbstub.o thunk.o - -endif #CONFIG_LINUX_USER - -######################################################### -# BSD user emulator target - -ifdef CONFIG_BSD_USER - -QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ABI_DIR) \ - -I$(SRC_PATH)/bsd-user/$(HOST_VARIANT_DIR) - -obj-y += bsd-user/ -obj-y += gdbstub.o - -endif #CONFIG_BSD_USER - -######################################################### -# System emulator target -ifdef CONFIG_SOFTMMU -obj-y += arch_init.o cpus.o gdbstub.o balloon.o ioport.o -obj-y += qtest.o -obj-y += dump/ -obj-y += hw/ -obj-y += monitor/ -obj-y += qapi/ -obj-y += memory.o -obj-y += memory_mapping.o -obj-y += migration/ram.o -obj-y += softmmu/ -LIBS := $(libs_softmmu) $(LIBS) - -# Hardware support -ifeq ($(TARGET_NAME), sparc64) -obj-y += hw/sparc64/ -else -obj-y += hw/$(TARGET_BASE_ARCH)/ -endif - -generated-files-y += hmp-commands.h hmp-commands-info.h -generated-files-y += config-devices.h - -endif # CONFIG_SOFTMMU - -dummy := $(call unnest-vars,,obj-y) -all-obj-y := $(obj-y) - -include $(SRC_PATH)/Makefile.objs -dummy := $(call unnest-vars,.., \ - authz-obj-y \ - block-obj-y \ - block-obj-m \ - chardev-obj-y \ - crypto-obj-y \ - qom-obj-y \ - io-obj-y \ - common-obj-y \ - common-obj-m) -all-obj-y += $(common-obj-y) -all-obj-y += $(qom-obj-y) -all-obj-$(CONFIG_SOFTMMU) += $(authz-obj-y) -all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y) $(chardev-obj-y) -all-obj-$(CONFIG_SOFTMMU) += $(crypto-obj-y) -all-obj-$(CONFIG_SOFTMMU) += $(io-obj-y) - -ifdef CONFIG_SOFTMMU -$(QEMU_PROG_BUILD): config-devices.mak -endif - -COMMON_LDADDS = ../libqemuutil.a - -# build either PROG or PROGW -$(QEMU_PROG_BUILD): $(all-obj-y) $(COMMON_LDADDS) $(softmmu-main-y) - $(call LINK, $(filter-out %.mak, $^)) -ifdef CONFIG_DARWIN - $(call quiet-command,Rez -append $(SRC_PATH)/pc-bios/qemu.rsrc -o $@,"REZ","$(TARGET_DIR)$@") - $(call quiet-command,SetFile -a C $@,"SETFILE","$(TARGET_DIR)$@") -endif - -gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh - $(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES),"GEN","$(TARGET_DIR)$@") - -hmp-commands.h: $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/scripts/hxtool - $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"GEN","$(TARGET_DIR)$@") - -hmp-commands-info.h: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxtool - $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"GEN","$(TARGET_DIR)$@") - -clean: clean-target - rm -f *.a *~ $(PROGS) - rm -f $(shell find . -name '*.[od]') - rm -f hmp-commands.h gdbstub-xml.c - rm -f trace/generated-helpers.c trace/generated-helpers.c-timestamp -ifdef CONFIG_TRACE_SYSTEMTAP - rm -f *.stp -endif - -ifdef CONFIG_FUZZ -include $(SRC_PATH)/tests/qtest/fuzz/Makefile.include -include $(SRC_PATH)/tests/qtest/Makefile.include - -fuzz: fuzz-vars -fuzz-vars: QEMU_CFLAGS := $(FUZZ_CFLAGS) $(QEMU_CFLAGS) -fuzz-vars: QEMU_LDFLAGS := $(FUZZ_LDFLAGS) $(QEMU_LDFLAGS) -fuzz-vars: $(QEMU_PROG_FUZZ) -dummy := $(call unnest-vars,, fuzz-obj-y) - - -$(QEMU_PROG_FUZZ): config-devices.mak $(all-obj-y) $(COMMON_LDADDS) $(fuzz-obj-y) - $(call LINK, $(filter-out %.mak, $^)) - -endif - -install: all -ifneq ($(PROGS),) - $(call install-prog,$(PROGS),$(DESTDIR)$(bindir)) -endif -ifdef CONFIG_TRACE_SYSTEMTAP - $(INSTALL_DIR) "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset" - $(INSTALL_DATA) $(QEMU_PROG).stp-installed "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset/$(QEMU_PROG).stp" - $(INSTALL_DATA) $(QEMU_PROG)-simpletrace.stp "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset/$(QEMU_PROG)-simpletrace.stp" - $(INSTALL_DATA) $(QEMU_PROG)-log.stp "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset/$(QEMU_PROG)-log.stp" -endif - -generated-files-y += config-target.h -Makefile: $(generated-files-y) - -# Reports/Analysis -# -# The target specific coverage report only cares about target specific -# blobs and not the shared code. -# - -%/coverage-report.html: - @mkdir -p $* - $(call quiet-command,\ - gcovr -r $(SRC_PATH) --object-directory $(CURDIR) \ - -p --html --html-details -o $@, \ - "GEN", "coverage-report.html") - -.PHONY: coverage-report -coverage-report: $(CURDIR)/reports/coverage/coverage-report.html diff --git a/README.rst b/README.rst index 7497709291dc921877d768c779fe0f75f167777b..58b9f2dc15c471e933c2375ecc6a4e47e839a87e 100644 --- a/README.rst +++ b/README.rst @@ -134,6 +134,14 @@ For additional information on bug reporting consult: * ``_ +ChangeLog +========= + +For version history and release notes, please visit +``_ or look at the git history for +more detailed information. + + Contact ======= diff --git a/VERSION b/VERSION index a480698ce543697af0b7ca941f4689bfc97a4515..91ff57278e37ef9cecfeaea47f0d77966799af28 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.0.50 +5.2.0 diff --git a/accel/Kconfig b/accel/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..2ad94a383991cf85047731748093c845d9a23905 --- /dev/null +++ b/accel/Kconfig @@ -0,0 +1,9 @@ +config TCG + bool + +config KVM + bool + +config XEN + bool + select FSDEV_9P if VIRTFS diff --git a/accel/Makefile.objs b/accel/Makefile.objs deleted file mode 100644 index 17e5ac60616a753afe8e6ec8b1e0404d87e778f5..0000000000000000000000000000000000000000 --- a/accel/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -common-obj-$(CONFIG_SOFTMMU) += accel.o -obj-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_POSIX)) += qtest.o -obj-$(CONFIG_KVM) += kvm/ -obj-$(CONFIG_TCG) += tcg/ -obj-y += stubs/ diff --git a/accel/dummy-cpus.c b/accel/dummy-cpus.c new file mode 100644 index 0000000000000000000000000000000000000000..10429fdfb2552511214a410ffcdc284f400a020f --- /dev/null +++ b/accel/dummy-cpus.c @@ -0,0 +1,72 @@ +/* + * Dummy cpu thread code + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qemu/rcu.h" +#include "sysemu/cpus.h" +#include "qemu/guest-random.h" +#include "qemu/main-loop.h" +#include "hw/core/cpu.h" + +static void *dummy_cpu_thread_fn(void *arg) +{ + CPUState *cpu = arg; + sigset_t waitset; + int r; + + rcu_register_thread(); + + qemu_mutex_lock_iothread(); + qemu_thread_get_self(cpu->thread); + cpu->thread_id = qemu_get_thread_id(); + cpu->can_do_io = 1; + current_cpu = cpu; + + sigemptyset(&waitset); + sigaddset(&waitset, SIG_IPI); + + /* signal CPU creation */ + cpu_thread_signal_created(cpu); + qemu_guest_random_seed_thread_part2(cpu->random_seed); + + do { + qemu_mutex_unlock_iothread(); + do { + int sig; + r = sigwait(&waitset, &sig); + } while (r == -1 && (errno == EAGAIN || errno == EINTR)); + if (r == -1) { + perror("sigwait"); + exit(1); + } + qemu_mutex_lock_iothread(); + qemu_wait_io_event(cpu); + } while (!cpu->unplug); + + qemu_mutex_unlock_iothread(); + rcu_unregister_thread(); + return NULL; +} + +void dummy_start_vcpu_thread(CPUState *cpu) +{ + char thread_name[VCPU_THREAD_NAME_SIZE]; + + cpu->thread = g_malloc0(sizeof(QemuThread)); + cpu->halt_cond = g_malloc0(sizeof(QemuCond)); + qemu_cond_init(cpu->halt_cond); + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/DUMMY", + cpu->cpu_index); + qemu_thread_create(cpu->thread, thread_name, dummy_cpu_thread_fn, cpu, + QEMU_THREAD_JOINABLE); +} diff --git a/accel/kvm/Makefile.objs b/accel/kvm/Makefile.objs deleted file mode 100644 index fdfa48157877e7867e89ecabedc751beb8842ae2..0000000000000000000000000000000000000000 --- a/accel/kvm/Makefile.objs +++ /dev/null @@ -1,2 +0,0 @@ -obj-y += kvm-all.o -obj-$(call lnot,$(CONFIG_SEV)) += sev-stub.o diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index d06cc04079d88e9337a719916d1477fc80467e1a..baaa54249d4f31c41f0a87ead013578a2d6ce701 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -40,11 +40,13 @@ #include "trace.h" #include "hw/irq.h" #include "sysemu/sev.h" -#include "sysemu/balloon.h" #include "qapi/visitor.h" #include "qapi/qapi-types-common.h" #include "qapi/qapi-visit-common.h" #include "sysemu/reset.h" +#include "qemu/guest-random.h" +#include "sysemu/hw_accel.h" +#include "kvm-cpus.h" #include "hw/boards.h" @@ -101,7 +103,7 @@ struct KVMState bool kernel_irqchip_required; OnOffAuto kernel_irqchip_split; bool sync_mmu; - bool manual_dirty_log_protect; + uint64_t manual_dirty_log_protect; /* The man page (and posix) say ioctl numbers are signed int, but * they're not. Linux, glibc and *BSD all treat ioctl numbers as * unsigned, and treating them as signed here can break things */ @@ -160,9 +162,59 @@ static const KVMCapabilityInfo kvm_required_capabilites[] = { static NotifierList kvm_irqchip_change_notifiers = NOTIFIER_LIST_INITIALIZER(kvm_irqchip_change_notifiers); +struct KVMResampleFd { + int gsi; + EventNotifier *resample_event; + QLIST_ENTRY(KVMResampleFd) node; +}; +typedef struct KVMResampleFd KVMResampleFd; + +/* + * Only used with split irqchip where we need to do the resample fd + * kick for the kernel from userspace. + */ +static QLIST_HEAD(, KVMResampleFd) kvm_resample_fd_list = + QLIST_HEAD_INITIALIZER(kvm_resample_fd_list); + #define kvm_slots_lock(kml) qemu_mutex_lock(&(kml)->slots_lock) #define kvm_slots_unlock(kml) qemu_mutex_unlock(&(kml)->slots_lock) +static inline void kvm_resample_fd_remove(int gsi) +{ + KVMResampleFd *rfd; + + QLIST_FOREACH(rfd, &kvm_resample_fd_list, node) { + if (rfd->gsi == gsi) { + QLIST_REMOVE(rfd, node); + g_free(rfd); + break; + } + } +} + +static inline void kvm_resample_fd_insert(int gsi, EventNotifier *event) +{ + KVMResampleFd *rfd = g_new0(KVMResampleFd, 1); + + rfd->gsi = gsi; + rfd->resample_event = event; + + QLIST_INSERT_HEAD(&kvm_resample_fd_list, rfd, node); +} + +void kvm_resample_fd_notify(int gsi) +{ + KVMResampleFd *rfd; + + QLIST_FOREACH(rfd, &kvm_resample_fd_list, node) { + if (rfd->gsi == gsi) { + event_notifier_set(rfd->resample_event); + trace_kvm_resample_fd_notify(gsi); + return; + } + } +} + int kvm_get_max_memslots(void) { KVMState *s = KVM_STATE(current_accel()); @@ -329,7 +381,7 @@ err: return ret; } -int kvm_destroy_vcpu(CPUState *cpu) +static int do_kvm_destroy_vcpu(CPUState *cpu) { KVMState *s = kvm_state; long mmap_size; @@ -363,6 +415,14 @@ err: return ret; } +void kvm_destroy_vcpu(CPUState *cpu) +{ + if (do_kvm_destroy_vcpu(cpu) < 0) { + error_report("kvm_destroy_vcpu failed"); + exit(EXIT_FAILURE); + } +} + static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id) { struct KVMParkedVcpu *cpu; @@ -381,17 +441,18 @@ static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id) return kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)vcpu_id); } -int kvm_init_vcpu(CPUState *cpu) +int kvm_init_vcpu(CPUState *cpu, Error **errp) { KVMState *s = kvm_state; long mmap_size; int ret; - DPRINTF("kvm_init_vcpu\n"); + trace_kvm_init_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); ret = kvm_get_vcpu(s, kvm_arch_vcpu_id(cpu)); if (ret < 0) { - DPRINTF("kvm_create_vcpu failed\n"); + error_setg_errno(errp, -ret, "kvm_init_vcpu: kvm_get_vcpu failed (%lu)", + kvm_arch_vcpu_id(cpu)); goto err; } @@ -402,7 +463,8 @@ int kvm_init_vcpu(CPUState *cpu) mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0); if (mmap_size < 0) { ret = mmap_size; - DPRINTF("KVM_GET_VCPU_MMAP_SIZE failed\n"); + error_setg_errno(errp, -mmap_size, + "kvm_init_vcpu: KVM_GET_VCPU_MMAP_SIZE failed"); goto err; } @@ -410,7 +472,9 @@ int kvm_init_vcpu(CPUState *cpu) cpu->kvm_fd, 0); if (cpu->kvm_run == MAP_FAILED) { ret = -errno; - DPRINTF("mmap'ing vcpu state failed\n"); + error_setg_errno(errp, ret, + "kvm_init_vcpu: mmap'ing vcpu state failed (%lu)", + kvm_arch_vcpu_id(cpu)); goto err; } @@ -420,6 +484,11 @@ int kvm_init_vcpu(CPUState *cpu) } ret = kvm_arch_init_vcpu(cpu); + if (ret < 0) { + error_setg_errno(errp, -ret, + "kvm_init_vcpu: kvm_arch_init_vcpu failed (%lu)", + kvm_arch_vcpu_id(cpu)); + } err: return ret; } @@ -1662,9 +1731,13 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg, return kvm_update_routing_entry(s, &kroute); } -static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int rfd, int virq, +static int kvm_irqchip_assign_irqfd(KVMState *s, EventNotifier *event, + EventNotifier *resample, int virq, bool assign) { + int fd = event_notifier_get_fd(event); + int rfd = resample ? event_notifier_get_fd(resample) : -1; + struct kvm_irqfd irqfd = { .fd = fd, .gsi = virq, @@ -1672,8 +1745,33 @@ static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int rfd, int virq, }; if (rfd != -1) { - irqfd.flags |= KVM_IRQFD_FLAG_RESAMPLE; - irqfd.resamplefd = rfd; + assert(assign); + if (kvm_irqchip_is_split()) { + /* + * When the slow irqchip (e.g. IOAPIC) is in the + * userspace, KVM kernel resamplefd will not work because + * the EOI of the interrupt will be delivered to userspace + * instead, so the KVM kernel resamplefd kick will be + * skipped. The userspace here mimics what the kernel + * provides with resamplefd, remember the resamplefd and + * kick it when we receive EOI of this IRQ. + * + * This is hackery because IOAPIC is mostly bypassed + * (except EOI broadcasts) when irqfd is used. However + * this can bring much performance back for split irqchip + * with INTx IRQs (for VFIO, this gives 93% perf of the + * full fast path, which is 46% perf boost comparing to + * the INTx slow path). + */ + kvm_resample_fd_insert(virq, resample); + } else { + irqfd.flags |= KVM_IRQFD_FLAG_RESAMPLE; + irqfd.resamplefd = rfd; + } + } else if (!assign) { + if (kvm_irqchip_is_split()) { + kvm_resample_fd_remove(virq); + } } if (!kvm_irqfds_enabled()) { @@ -1769,7 +1867,9 @@ int kvm_irqchip_add_hv_sint_route(KVMState *s, uint32_t vcpu, uint32_t sint) return -ENOSYS; } -static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign) +static int kvm_irqchip_assign_irqfd(KVMState *s, EventNotifier *event, + EventNotifier *resample, int virq, + bool assign) { abort(); } @@ -1783,15 +1883,13 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg) int kvm_irqchip_add_irqfd_notifier_gsi(KVMState *s, EventNotifier *n, EventNotifier *rn, int virq) { - return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n), - rn ? event_notifier_get_fd(rn) : -1, virq, true); + return kvm_irqchip_assign_irqfd(s, n, rn, virq, true); } int kvm_irqchip_remove_irqfd_notifier_gsi(KVMState *s, EventNotifier *n, int virq) { - return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n), -1, virq, - false); + return kvm_irqchip_assign_irqfd(s, n, NULL, virq, false); } int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, @@ -1916,6 +2014,7 @@ static int kvm_init(MachineState *ms) int ret; int type = 0; const char *kvm_type; + uint64_t dirty_log_manual_caps; s = KVM_STATE(ms->accelerator); @@ -1934,7 +2033,7 @@ static int kvm_init(MachineState *ms) #endif QLIST_INIT(&s->kvm_parked_vcpus); s->vmfd = -1; - s->fd = qemu_open("/dev/kvm", O_RDWR); + s->fd = qemu_open_old("/dev/kvm", O_RDWR); if (s->fd == -1) { fprintf(stderr, "Could not access KVM kernel module: %m\n"); ret = -errno; @@ -2041,14 +2140,20 @@ static int kvm_init(MachineState *ms) s->coalesced_pio = s->coalesced_mmio && kvm_check_extension(s, KVM_CAP_COALESCED_PIO); - s->manual_dirty_log_protect = + dirty_log_manual_caps = kvm_check_extension(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2); - if (s->manual_dirty_log_protect) { - ret = kvm_vm_enable_cap(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2, 0, 1); + dirty_log_manual_caps &= (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | + KVM_DIRTY_LOG_INITIALLY_SET); + s->manual_dirty_log_protect = dirty_log_manual_caps; + if (dirty_log_manual_caps) { + ret = kvm_vm_enable_cap(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2, 0, + dirty_log_manual_caps); if (ret) { - warn_report("Trying to enable KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 " - "but failed. Falling back to the legacy mode. "); - s->manual_dirty_log_protect = false; + warn_report("Trying to enable capability %"PRIu64" of " + "KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 but failed. " + "Falling back to the legacy mode. ", + dirty_log_manual_caps); + s->manual_dirty_log_protect = 0; } } @@ -2134,8 +2239,10 @@ static int kvm_init(MachineState *ms) kvm_memory_listener_register(s, &s->memory_listener, &address_space_memory, 0); - memory_listener_register(&kvm_io_listener, - &address_space_io); + if (kvm_eventfds_allowed) { + memory_listener_register(&kvm_io_listener, + &address_space_io); + } memory_listener_register(&kvm_coalesced_pio_listener, &address_space_io); @@ -2143,9 +2250,11 @@ static int kvm_init(MachineState *ms) s->sync_mmu = !!kvm_vm_check_extension(kvm_state, KVM_CAP_SYNC_MMU); if (!s->sync_mmu) { - qemu_balloon_inhibit(true); + ret = ram_block_discard_disable(true); + assert(!ret); } + cpus_register_accel(&kvm_cpus); return 0; err: @@ -2293,7 +2402,7 @@ static __thread bool have_sigbus_pending; static void kvm_cpu_kick(CPUState *cpu) { - atomic_set(&cpu->kvm_run->immediate_exit, 1); + qatomic_set(&cpu->kvm_run->immediate_exit, 1); } static void kvm_cpu_kick_self(void) @@ -2314,7 +2423,7 @@ static void kvm_eat_signals(CPUState *cpu) int r; if (kvm_immediate_exit) { - atomic_set(&cpu->kvm_run->immediate_exit, 0); + qatomic_set(&cpu->kvm_run->immediate_exit, 0); /* Write kvm_run->immediate_exit before the cpu->exit_request * write in kvm_cpu_exec. */ @@ -2348,7 +2457,7 @@ int kvm_cpu_exec(CPUState *cpu) DPRINTF("kvm_cpu_exec()\n"); if (kvm_arch_process_async_events(cpu)) { - atomic_set(&cpu->exit_request, 0); + qatomic_set(&cpu->exit_request, 0); return EXCP_HLT; } @@ -2364,7 +2473,7 @@ int kvm_cpu_exec(CPUState *cpu) } kvm_arch_pre_run(cpu, run); - if (atomic_read(&cpu->exit_request)) { + if (qatomic_read(&cpu->exit_request)) { DPRINTF("interrupt exit requested\n"); /* * KVM requires us to reenter the kernel after IO exits to complete @@ -2491,7 +2600,7 @@ int kvm_cpu_exec(CPUState *cpu) vm_stop(RUN_STATE_INTERNAL_ERROR); } - atomic_set(&cpu->exit_request, 0); + qatomic_set(&cpu->exit_request, 0); return ret; } @@ -2908,7 +3017,7 @@ int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr) have_sigbus_pending = true; pending_sigbus_addr = addr; pending_sigbus_code = code; - atomic_set(&cpu->exit_request, 1); + qatomic_set(&cpu->exit_request, 1); return 0; #else return 1; @@ -3027,12 +3136,9 @@ static void kvm_set_kvm_shadow_mem(Object *obj, Visitor *v, Error **errp) { KVMState *s = KVM_STATE(obj); - Error *error = NULL; int64_t value; - visit_type_int(v, name, &value, &error); - if (error) { - error_propagate(errp, error); + if (!visit_type_int(v, name, &value, errp)) { return; } @@ -3043,37 +3149,33 @@ static void kvm_set_kernel_irqchip(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - Error *err = NULL; KVMState *s = KVM_STATE(obj); OnOffSplit mode; - visit_type_OnOffSplit(v, name, &mode, &err); - if (err) { - error_propagate(errp, err); + if (!visit_type_OnOffSplit(v, name, &mode, errp)) { return; - } else { - switch (mode) { - case ON_OFF_SPLIT_ON: - s->kernel_irqchip_allowed = true; - s->kernel_irqchip_required = true; - s->kernel_irqchip_split = ON_OFF_AUTO_OFF; - break; - case ON_OFF_SPLIT_OFF: - s->kernel_irqchip_allowed = false; - s->kernel_irqchip_required = false; - s->kernel_irqchip_split = ON_OFF_AUTO_OFF; - break; - case ON_OFF_SPLIT_SPLIT: - s->kernel_irqchip_allowed = true; - s->kernel_irqchip_required = true; - s->kernel_irqchip_split = ON_OFF_AUTO_ON; - break; - default: - /* The value was checked in visit_type_OnOffSplit() above. If - * we get here, then something is wrong in QEMU. - */ - abort(); - } + } + switch (mode) { + case ON_OFF_SPLIT_ON: + s->kernel_irqchip_allowed = true; + s->kernel_irqchip_required = true; + s->kernel_irqchip_split = ON_OFF_AUTO_OFF; + break; + case ON_OFF_SPLIT_OFF: + s->kernel_irqchip_allowed = false; + s->kernel_irqchip_required = false; + s->kernel_irqchip_split = ON_OFF_AUTO_OFF; + break; + case ON_OFF_SPLIT_SPLIT: + s->kernel_irqchip_allowed = true; + s->kernel_irqchip_required = true; + s->kernel_irqchip_split = ON_OFF_AUTO_ON; + break; + default: + /* The value was checked in visit_type_OnOffSplit() above. If + * we get here, then something is wrong in QEMU. + */ + abort(); } } diff --git a/accel/kvm/kvm-cpus.c b/accel/kvm/kvm-cpus.c new file mode 100644 index 0000000000000000000000000000000000000000..d809b1e74c94c10200bf37e2daf534346f3af8b4 --- /dev/null +++ b/accel/kvm/kvm-cpus.c @@ -0,0 +1,84 @@ +/* + * QEMU KVM support + * + * Copyright IBM, Corp. 2008 + * Red Hat, Inc. 2008 + * + * Authors: + * Anthony Liguori + * Glauber Costa + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" +#include "sysemu/kvm_int.h" +#include "sysemu/runstate.h" +#include "sysemu/cpus.h" +#include "qemu/guest-random.h" +#include "qapi/error.h" + +#include "kvm-cpus.h" + +static void *kvm_vcpu_thread_fn(void *arg) +{ + CPUState *cpu = arg; + int r; + + rcu_register_thread(); + + qemu_mutex_lock_iothread(); + qemu_thread_get_self(cpu->thread); + cpu->thread_id = qemu_get_thread_id(); + cpu->can_do_io = 1; + current_cpu = cpu; + + r = kvm_init_vcpu(cpu, &error_fatal); + kvm_init_cpu_signals(cpu); + + /* signal CPU creation */ + cpu_thread_signal_created(cpu); + qemu_guest_random_seed_thread_part2(cpu->random_seed); + + do { + if (cpu_can_run(cpu)) { + r = kvm_cpu_exec(cpu); + if (r == EXCP_DEBUG) { + cpu_handle_guest_debug(cpu); + } + } + qemu_wait_io_event(cpu); + } while (!cpu->unplug || cpu_can_run(cpu)); + + kvm_destroy_vcpu(cpu); + cpu_thread_signal_destroyed(cpu); + qemu_mutex_unlock_iothread(); + rcu_unregister_thread(); + return NULL; +} + +static void kvm_start_vcpu_thread(CPUState *cpu) +{ + char thread_name[VCPU_THREAD_NAME_SIZE]; + + cpu->thread = g_malloc0(sizeof(QemuThread)); + cpu->halt_cond = g_malloc0(sizeof(QemuCond)); + qemu_cond_init(cpu->halt_cond); + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/KVM", + cpu->cpu_index); + qemu_thread_create(cpu->thread, thread_name, kvm_vcpu_thread_fn, + cpu, QEMU_THREAD_JOINABLE); +} + +const CpusAccel kvm_cpus = { + .create_vcpu_thread = kvm_start_vcpu_thread, + + .synchronize_post_reset = kvm_cpu_synchronize_post_reset, + .synchronize_post_init = kvm_cpu_synchronize_post_init, + .synchronize_state = kvm_cpu_synchronize_state, + .synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm, +}; diff --git a/accel/kvm/kvm-cpus.h b/accel/kvm/kvm-cpus.h new file mode 100644 index 0000000000000000000000000000000000000000..3df732b816c13665821d91a7fb429779e371ba63 --- /dev/null +++ b/accel/kvm/kvm-cpus.h @@ -0,0 +1,24 @@ +/* + * Accelerator CPUS Interface + * + * Copyright 2020 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef KVM_CPUS_H +#define KVM_CPUS_H + +#include "sysemu/cpus.h" + +extern const CpusAccel kvm_cpus; + +int kvm_init_vcpu(CPUState *cpu, Error **errp); +int kvm_cpu_exec(CPUState *cpu); +void kvm_destroy_vcpu(CPUState *cpu); +void kvm_cpu_synchronize_post_reset(CPUState *cpu); +void kvm_cpu_synchronize_post_init(CPUState *cpu); +void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu); + +#endif /* KVM_CPUS_H */ diff --git a/accel/kvm/meson.build b/accel/kvm/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..7e9dafe24c50c12c11f55b9b1def2fba44adfe1c --- /dev/null +++ b/accel/kvm/meson.build @@ -0,0 +1,8 @@ +kvm_ss = ss.source_set() +kvm_ss.add(files( + 'kvm-all.c', + 'kvm-cpus.c', +)) +kvm_ss.add(when: 'CONFIG_SEV', if_false: files('sev-stub.c')) + +specific_ss.add_all(when: 'CONFIG_KVM', if_true: kvm_ss) diff --git a/accel/kvm/trace-events b/accel/kvm/trace-events index 4fb6e59d1977750d6db684bc2fb778f9a69afd83..e15ae8980d3dcc63bda180b3f5a5c402e6e61c8a 100644 --- a/accel/kvm/trace-events +++ b/accel/kvm/trace-events @@ -8,6 +8,7 @@ kvm_run_exit(int cpu_index, uint32_t reason) "cpu_index %d, reason %d" kvm_device_ioctl(int fd, int type, void *arg) "dev fd %d, type 0x%x, arg %p" kvm_failed_reg_get(uint64_t id, const char *msg) "Warning: Unable to retrieve ONEREG %" PRIu64 " from KVM: %s" kvm_failed_reg_set(uint64_t id, const char *msg) "Warning: Unable to set ONEREG %" PRIu64 " to KVM: %s" +kvm_init_vcpu(int cpu_index, unsigned long arch_cpu_id) "index: %d id: %lu" kvm_irqchip_commit_routes(void) "" kvm_irqchip_add_msi_route(char *name, int vector, int virq) "dev %s vector %d virq %d" kvm_irqchip_update_msi_route(int virq) "Updating MSI route virq=%d" @@ -16,4 +17,5 @@ kvm_set_ioeventfd_mmio(int fd, uint64_t addr, uint32_t val, bool assign, uint32_ kvm_set_ioeventfd_pio(int fd, uint16_t addr, uint32_t val, bool assign, uint32_t size, bool datamatch) "fd: %d @0x%x val=0x%x assign: %d size: %d match: %d" kvm_set_user_memory(uint32_t slot, uint32_t flags, uint64_t guest_phys_addr, uint64_t memory_size, uint64_t userspace_addr, int ret) "Slot#%d flags=0x%x gpa=0x%"PRIx64 " size=0x%"PRIx64 " ua=0x%"PRIx64 " ret=%d" kvm_clear_dirty_log(uint32_t slot, uint64_t start, uint32_t size) "slot#%"PRId32" start 0x%"PRIx64" size 0x%"PRIx32 +kvm_resample_fd_notify(int gsi) "gsi %d" diff --git a/accel/kvm/trace.h b/accel/kvm/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..67c935a6f7817b31863399a01969ac1a1bdb8ef9 --- /dev/null +++ b/accel/kvm/trace.h @@ -0,0 +1 @@ +#include "trace/trace-accel_kvm.h" diff --git a/accel/meson.build b/accel/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..b26cca227a4075145283dcc057c5e0da1218b14c --- /dev/null +++ b/accel/meson.build @@ -0,0 +1,15 @@ +softmmu_ss.add(files('accel.c')) + +subdir('qtest') +subdir('kvm') +subdir('tcg') +subdir('xen') +subdir('stubs') + +dummy_ss = ss.source_set() +dummy_ss.add(files( + 'dummy-cpus.c', +)) + +specific_ss.add_all(when: ['CONFIG_SOFTMMU', 'CONFIG_POSIX'], if_true: dummy_ss) +specific_ss.add_all(when: ['CONFIG_XEN'], if_true: dummy_ss) diff --git a/accel/qtest/meson.build b/accel/qtest/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..a2f327645980bf76cbef36811d192d5171ed1847 --- /dev/null +++ b/accel/qtest/meson.build @@ -0,0 +1,6 @@ +qtest_ss = ss.source_set() +qtest_ss.add(files( + 'qtest.c', +)) + +specific_ss.add_all(when: ['CONFIG_SOFTMMU', 'CONFIG_POSIX'], if_true: qtest_ss) diff --git a/accel/qtest.c b/accel/qtest/qtest.c similarity index 77% rename from accel/qtest.c rename to accel/qtest/qtest.c index 5b88f55921920d9525c55afa34d729f6384fea69..b282cea5cfc6f7e34e3cb70c8a696a0f02b024aa 100644 --- a/accel/qtest.c +++ b/accel/qtest/qtest.c @@ -12,6 +12,7 @@ */ #include "qemu/osdep.h" +#include "qemu/rcu.h" #include "qapi/error.h" #include "qemu/module.h" #include "qemu/option.h" @@ -19,14 +20,19 @@ #include "sysemu/accel.h" #include "sysemu/qtest.h" #include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" +#include "qemu/guest-random.h" +#include "qemu/main-loop.h" +#include "hw/core/cpu.h" + +const CpusAccel qtest_cpus = { + .create_vcpu_thread = dummy_start_vcpu_thread, + .get_virtual_clock = qtest_get_virtual_clock, +}; static int qtest_init_accel(MachineState *ms) { - QemuOpts *opts = qemu_opts_create(qemu_find_opts("icount"), NULL, 0, - &error_abort); - qemu_opt_set(opts, "shift", "0", &error_abort); - configure_icount(opts, &error_abort); - qemu_opts_del(opts); + cpus_register_accel(&qtest_cpus); return 0; } diff --git a/accel/stubs/Makefile.objs b/accel/stubs/Makefile.objs deleted file mode 100644 index 3894caf95da64d525c9cb6fabeab64e27e0a0bd2..0000000000000000000000000000000000000000 --- a/accel/stubs/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -obj-$(call lnot,$(CONFIG_HAX)) += hax-stub.o -obj-$(call lnot,$(CONFIG_HVF)) += hvf-stub.o -obj-$(call lnot,$(CONFIG_WHPX)) += whpx-stub.o -obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o -obj-$(call lnot,$(CONFIG_TCG)) += tcg-stub.o diff --git a/accel/stubs/hax-stub.c b/accel/stubs/hax-stub.c index 7ad190cae23de887ce4e8e66b197893b9336a442..49077f88e3c88490bdcee000a22a1f12f5b19236 100644 --- a/accel/stubs/hax-stub.c +++ b/accel/stubs/hax-stub.c @@ -14,20 +14,9 @@ */ #include "qemu/osdep.h" -#include "cpu.h" #include "sysemu/hax.h" int hax_sync_vcpus(void) { return 0; } - -int hax_init_vcpu(CPUState *cpu) -{ - return -ENOSYS; -} - -int hax_smp_cpu_exec(CPUState *cpu) -{ - return -ENOSYS; -} diff --git a/accel/stubs/hvf-stub.c b/accel/stubs/hvf-stub.c deleted file mode 100644 index e81dfe888cd9262b2219a5e529e5e107048d6487..0000000000000000000000000000000000000000 --- a/accel/stubs/hvf-stub.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * QEMU HVF support - * - * Copyright 2017 Red Hat, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2 or later, as published by the Free Software Foundation, - * and may be copied, distributed, and modified under those terms. - * - * See the COPYING file in the top-level directory. - * - */ - -#include "qemu/osdep.h" -#include "cpu.h" -#include "sysemu/hvf.h" - -int hvf_init_vcpu(CPUState *cpu) -{ - return -ENOSYS; -} - -int hvf_vcpu_exec(CPUState *cpu) -{ - return -ENOSYS; -} - -void hvf_vcpu_destroy(CPUState *cpu) -{ -} diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c index 82f118d2df908088bc515a07bdb51a28d02c2fe5..680e0994637ac71093c852d2e94c314020acf88b 100644 --- a/accel/stubs/kvm-stub.c +++ b/accel/stubs/kvm-stub.c @@ -32,16 +32,6 @@ bool kvm_readonly_mem_allowed; bool kvm_ioeventfd_any_length_allowed; bool kvm_msi_use_devid; -int kvm_destroy_vcpu(CPUState *cpu) -{ - return -ENOSYS; -} - -int kvm_init_vcpu(CPUState *cpu) -{ - return -ENOSYS; -} - void kvm_flush_coalesced_mmio_buffer(void) { } @@ -50,19 +40,6 @@ void kvm_cpu_synchronize_state(CPUState *cpu) { } -void kvm_cpu_synchronize_post_reset(CPUState *cpu) -{ -} - -void kvm_cpu_synchronize_post_init(CPUState *cpu) -{ -} - -int kvm_cpu_exec(CPUState *cpu) -{ - abort(); -} - bool kvm_has_sync_mmu(void) { return false; diff --git a/accel/stubs/meson.build b/accel/stubs/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..12dd1539afa7f6e50854a6f330866a9dbde361f0 --- /dev/null +++ b/accel/stubs/meson.build @@ -0,0 +1,4 @@ +specific_ss.add(when: 'CONFIG_HAX', if_false: files('hax-stub.c')) +specific_ss.add(when: 'CONFIG_XEN', if_false: files('xen-stub.c')) +specific_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c')) +specific_ss.add(when: 'CONFIG_TCG', if_false: files('tcg-stub.c')) diff --git a/accel/stubs/tcg-stub.c b/accel/stubs/tcg-stub.c index 677191a69cf2630677829cafa6f37d6669cefc22..e4bbf997aaf50ac6e318fb4b1a844ded5e1fadcb 100644 --- a/accel/stubs/tcg-stub.c +++ b/accel/stubs/tcg-stub.c @@ -22,3 +22,10 @@ void tb_flush(CPUState *cpu) void tlb_set_dirty(CPUState *cpu, target_ulong vaddr) { } + +void *probe_access(CPUArchState *env, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) +{ + /* Handled by hardware accelerator. */ + g_assert_not_reached(); +} diff --git a/accel/stubs/whpx-stub.c b/accel/stubs/whpx-stub.c deleted file mode 100644 index 1efb89f25e0c7edd47a2ff11e676ef007cb2b862..0000000000000000000000000000000000000000 --- a/accel/stubs/whpx-stub.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * QEMU Windows Hypervisor Platform accelerator (WHPX) stub - * - * Copyright Microsoft Corp. 2017 - * - * 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 "cpu.h" -#include "sysemu/whpx.h" - -int whpx_init_vcpu(CPUState *cpu) -{ - return -1; -} - -int whpx_vcpu_exec(CPUState *cpu) -{ - return -1; -} - -void whpx_destroy_vcpu(CPUState *cpu) -{ -} - -void whpx_vcpu_kick(CPUState *cpu) -{ -} - -void whpx_cpu_synchronize_state(CPUState *cpu) -{ -} - -void whpx_cpu_synchronize_post_reset(CPUState *cpu) -{ -} - -void whpx_cpu_synchronize_post_init(CPUState *cpu) -{ -} - -void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu) -{ -} diff --git a/stubs/xen-common.c b/accel/stubs/xen-stub.c similarity index 60% rename from stubs/xen-common.c rename to accel/stubs/xen-stub.c index f5efcae362e217ea3db0aa8943b0e5644e9be666..7054965c4802518ed30734b84bd9f66f9a8afd11 100644 --- a/stubs/xen-common.c +++ b/accel/stubs/xen-stub.c @@ -6,8 +6,11 @@ */ #include "qemu/osdep.h" -#include "hw/xen/xen.h" +#include "sysemu/xen.h" +#include "qapi/qapi-commands-migration.h" -void xenstore_store_pv_console_info(int i, Chardev *chr) +bool xen_allowed; + +void qmp_xen_set_global_dirty_log(bool enable, Error **errp) { } diff --git a/accel/tcg/Makefile.objs b/accel/tcg/Makefile.objs deleted file mode 100644 index a92f2c454b9a789794980246943ee5cdbb42ac52..0000000000000000000000000000000000000000 --- a/accel/tcg/Makefile.objs +++ /dev/null @@ -1,9 +0,0 @@ -obj-$(CONFIG_SOFTMMU) += tcg-all.o -obj-$(CONFIG_SOFTMMU) += cputlb.o -obj-y += tcg-runtime.o tcg-runtime-gvec.o -obj-y += cpu-exec.o cpu-exec-common.o translate-all.o -obj-y += translator.o - -obj-$(CONFIG_USER_ONLY) += user-exec.o -obj-$(call lnot,$(CONFIG_SOFTMMU)) += user-exec-stub.o -obj-$(CONFIG_PLUGIN) += plugin-gen.o diff --git a/accel/tcg/atomic_common.inc.c b/accel/tcg/atomic_common.c.inc similarity index 100% rename from accel/tcg/atomic_common.inc.c rename to accel/tcg/atomic_common.c.inc diff --git a/accel/tcg/atomic_template.h b/accel/tcg/atomic_template.h index 26969487d6d6e2b7308e922a7401f9c58f6018f5..0ff7f913e1fcc93b6f29180f62940abd9135fadc 100644 --- a/accel/tcg/atomic_template.h +++ b/accel/tcg/atomic_template.h @@ -83,7 +83,7 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr, #if DATA_SIZE == 16 ret = atomic16_cmpxchg(haddr, cmpv, newv); #else - ret = atomic_cmpxchg__nocheck(haddr, cmpv, newv); + ret = qatomic_cmpxchg__nocheck(haddr, cmpv, newv); #endif ATOMIC_MMU_CLEANUP; atomic_trace_rmw_post(env, addr, info); @@ -131,7 +131,7 @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ATOMIC_MMU_IDX); atomic_trace_rmw_pre(env, addr, info); - ret = atomic_xchg__nocheck(haddr, val); + ret = qatomic_xchg__nocheck(haddr, val); ATOMIC_MMU_CLEANUP; atomic_trace_rmw_post(env, addr, info); return ret; @@ -147,7 +147,7 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \ uint16_t info = trace_mem_build_info(SHIFT, false, 0, false, \ ATOMIC_MMU_IDX); \ atomic_trace_rmw_pre(env, addr, info); \ - ret = atomic_##X(haddr, val); \ + ret = qatomic_##X(haddr, val); \ ATOMIC_MMU_CLEANUP; \ atomic_trace_rmw_post(env, addr, info); \ return ret; \ @@ -182,10 +182,10 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \ ATOMIC_MMU_IDX); \ atomic_trace_rmw_pre(env, addr, info); \ smp_mb(); \ - cmp = atomic_read__nocheck(haddr); \ + cmp = qatomic_read__nocheck(haddr); \ do { \ old = cmp; new = FN(old, val); \ - cmp = atomic_cmpxchg__nocheck(haddr, old, new); \ + cmp = qatomic_cmpxchg__nocheck(haddr, old, new); \ } while (cmp != old); \ ATOMIC_MMU_CLEANUP; \ atomic_trace_rmw_post(env, addr, info); \ @@ -230,7 +230,7 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr, #if DATA_SIZE == 16 ret = atomic16_cmpxchg(haddr, BSWAP(cmpv), BSWAP(newv)); #else - ret = atomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv)); + ret = qatomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv)); #endif ATOMIC_MMU_CLEANUP; atomic_trace_rmw_post(env, addr, info); @@ -280,7 +280,7 @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ATOMIC_MMU_IDX); atomic_trace_rmw_pre(env, addr, info); - ret = atomic_xchg__nocheck(haddr, BSWAP(val)); + ret = qatomic_xchg__nocheck(haddr, BSWAP(val)); ATOMIC_MMU_CLEANUP; atomic_trace_rmw_post(env, addr, info); return BSWAP(ret); @@ -296,7 +296,7 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \ uint16_t info = trace_mem_build_info(SHIFT, false, MO_BSWAP, \ false, ATOMIC_MMU_IDX); \ atomic_trace_rmw_pre(env, addr, info); \ - ret = atomic_##X(haddr, BSWAP(val)); \ + ret = qatomic_##X(haddr, BSWAP(val)); \ ATOMIC_MMU_CLEANUP; \ atomic_trace_rmw_post(env, addr, info); \ return BSWAP(ret); \ @@ -329,10 +329,10 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \ false, ATOMIC_MMU_IDX); \ atomic_trace_rmw_pre(env, addr, info); \ smp_mb(); \ - ldn = atomic_read__nocheck(haddr); \ + ldn = qatomic_read__nocheck(haddr); \ do { \ ldo = ldn; old = BSWAP(ldo); new = FN(old, val); \ - ldn = atomic_cmpxchg__nocheck(haddr, ldo, BSWAP(new)); \ + ldn = qatomic_cmpxchg__nocheck(haddr, ldo, BSWAP(new)); \ } while (ldo != ldn); \ ATOMIC_MMU_CLEANUP; \ atomic_trace_rmw_post(env, addr, info); \ diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index d95c4848a47bcc1e82372deb3f9488736c7ccb95..58aea605d805e1da6dc43d327dbda309f2ba3f2e 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/qemu-print.h" #include "cpu.h" #include "trace.h" #include "disas/disas.h" @@ -36,6 +37,8 @@ #include "hw/i386/apic.h" #endif #include "sysemu/cpus.h" +#include "exec/cpu-all.h" +#include "sysemu/cpu-timers.h" #include "sysemu/replay.h" /* -icount align implementation. */ @@ -56,6 +59,9 @@ typedef struct SyncClocks { #define MAX_DELAY_PRINT_RATE 2000000000LL #define MAX_NB_PRINTS 100 +static int64_t max_delay; +static int64_t max_advance; + static void align_clocks(SyncClocks *sc, CPUState *cpu) { int64_t cpu_icount; @@ -65,7 +71,7 @@ static void align_clocks(SyncClocks *sc, CPUState *cpu) } cpu_icount = cpu->icount_extra + cpu_neg(cpu)->icount_decr.u16.low; - sc->diff_clk += cpu_icount_to_ns(sc->last_cpu_icount - cpu_icount); + sc->diff_clk += icount_to_ns(sc->last_cpu_icount - cpu_icount); sc->last_cpu_icount = cpu_icount; if (sc->diff_clk > VM_CLOCK_ADVANCE) { @@ -98,9 +104,9 @@ static void print_delay(const SyncClocks *sc) (-sc->diff_clk / (float)1000000000LL < (threshold_delay - THRESHOLD_REDUCE))) { threshold_delay = (-sc->diff_clk / 1000000000LL) + 1; - printf("Warning: The guest is now late by %.1f to %.1f seconds\n", - threshold_delay - 1, - threshold_delay); + qemu_printf("Warning: The guest is now late by %.1f to %.1f seconds\n", + threshold_delay - 1, + threshold_delay); nb_prints++; last_realtime_clock = sc->realtime_clock; } @@ -367,7 +373,8 @@ static inline void tb_add_jump(TranslationBlock *tb, int n, goto out_unlock_next; } /* Atomically claim the jump destination slot only if it was NULL */ - old = atomic_cmpxchg(&tb->jmp_dest[n], (uintptr_t)NULL, (uintptr_t)tb_next); + old = qatomic_cmpxchg(&tb->jmp_dest[n], (uintptr_t)NULL, + (uintptr_t)tb_next); if (old) { goto out_unlock_next; } @@ -407,7 +414,7 @@ static inline TranslationBlock *tb_find(CPUState *cpu, tb = tb_gen_code(cpu, pc, cs_base, flags, cf_mask); mmap_unlock(); /* We add the TB in the virtual pc hash table for the fast lookup */ - atomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb); + qatomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb); } #ifndef CONFIG_USER_ONLY /* We don't take care of direct jumps when address mapping changes in @@ -429,8 +436,7 @@ static inline bool cpu_handle_halt(CPUState *cpu) { if (cpu->halted) { #if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY) - if ((cpu->interrupt_request & CPU_INTERRUPT_POLL) - && replay_interrupt()) { + if (cpu->interrupt_request & CPU_INTERRUPT_POLL) { X86CPU *x86_cpu = X86_CPU(cpu); qemu_mutex_lock_iothread(); apic_poll_irq(x86_cpu->apic_state); @@ -504,6 +510,17 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret) cc->do_interrupt(cpu); qemu_mutex_unlock_iothread(); cpu->exception_index = -1; + + if (unlikely(cpu->singlestep_enabled)) { + /* + * After processing the exception, ensure an EXCP_DEBUG is + * raised when single-stepping so that GDB doesn't miss the + * next instruction. + */ + *ret = EXCP_DEBUG; + cpu_handle_debug_exception(cpu); + return true; + } } else if (!replay_has_interrupt()) { /* give a chance to iothread in replay mode */ *ret = EXCP_INTERRUPT; @@ -515,6 +532,20 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret) return false; } +/* + * CPU_INTERRUPT_POLL is a virtual event which gets converted into a + * "real" interrupt event later. It does not need to be recorded for + * replay purposes. + */ +static inline bool need_replay_interrupt(int interrupt_request) +{ +#if defined(TARGET_I386) + return !(interrupt_request & CPU_INTERRUPT_POLL); +#else + return true; +#endif +} + static inline bool cpu_handle_interrupt(CPUState *cpu, TranslationBlock **last_tb) { @@ -525,9 +556,9 @@ static inline bool cpu_handle_interrupt(CPUState *cpu, * Ensure zeroing happens before reading cpu->exit_request or * cpu->interrupt_request (see also smp_wmb in cpu_exit()) */ - atomic_mb_set(&cpu_neg(cpu)->icount_decr.u16.high, 0); + qatomic_mb_set(&cpu_neg(cpu)->icount_decr.u16.high, 0); - if (unlikely(atomic_read(&cpu->interrupt_request))) { + if (unlikely(qatomic_read(&cpu->interrupt_request))) { int interrupt_request; qemu_mutex_lock_iothread(); interrupt_request = cpu->interrupt_request; @@ -576,8 +607,16 @@ static inline bool cpu_handle_interrupt(CPUState *cpu, and via longjmp via cpu_loop_exit. */ else { if (cc->cpu_exec_interrupt(cpu, interrupt_request)) { - replay_interrupt(); - cpu->exception_index = -1; + if (need_replay_interrupt(interrupt_request)) { + replay_interrupt(); + } + /* + * After processing the interrupt, ensure an EXCP_DEBUG is + * raised when single-stepping so that GDB doesn't miss the + * next instruction. + */ + cpu->exception_index = + (cpu->singlestep_enabled ? EXCP_DEBUG : -1); *last_tb = NULL; } /* The target hook may have updated the 'cpu->interrupt_request'; @@ -596,10 +635,10 @@ static inline bool cpu_handle_interrupt(CPUState *cpu, } /* Finally, check if we need to exit to the main loop. */ - if (unlikely(atomic_read(&cpu->exit_request)) - || (use_icount + if (unlikely(qatomic_read(&cpu->exit_request)) + || (icount_enabled() && cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra == 0)) { - atomic_set(&cpu->exit_request, 0); + qatomic_set(&cpu->exit_request, 0); if (cpu->exception_index == -1) { cpu->exception_index = EXCP_INTERRUPT; } @@ -625,7 +664,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb, } *last_tb = NULL; - insns_left = atomic_read(&cpu_neg(cpu)->icount_decr.u32); + insns_left = qatomic_read(&cpu_neg(cpu)->icount_decr.u32); if (insns_left < 0) { /* Something asked us to stop executing chained TBs; just * continue round the main loop. Whatever requested the exit @@ -638,10 +677,10 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb, } /* Instruction counter expired. */ - assert(use_icount); + assert(icount_enabled()); #ifndef CONFIG_USER_ONLY /* Ensure global icount has gone forward */ - cpu_update_icount(cpu); + icount_update(cpu); /* Refill decrementer and continue execution. */ insns_left = MIN(0xffff, cpu->icount_budget); cpu_neg(cpu)->icount_decr.u16.low = insns_left; @@ -741,3 +780,26 @@ int cpu_exec(CPUState *cpu) return ret; } + +#ifndef CONFIG_USER_ONLY + +void dump_drift_info(void) +{ + if (!icount_enabled()) { + return; + } + + qemu_printf("Host - Guest clock %"PRIi64" ms\n", + (cpu_get_clock() - icount_get()) / SCALE_MS); + if (icount_align_option) { + qemu_printf("Max guest delay %"PRIi64" ms\n", + -max_delay / SCALE_MS); + qemu_printf("Max guest advance %"PRIi64" ms\n", + max_advance / SCALE_MS); + } else { + qemu_printf("Max guest delay NA\n"); + qemu_printf("Max guest advance NA\n"); + } +} + +#endif /* !CONFIG_USER_ONLY */ diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index eb2cf9de5e6c6055bf661b3d99aca0302cd12e1b..42ab79c1a5827ccfd95223d3c52112bfe0bae93d 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -34,7 +34,7 @@ #include "qemu/atomic.h" #include "qemu/atomic128.h" #include "translate-all.h" -#include "trace-root.h" +#include "trace/trace-root.h" #include "trace/mem.h" #ifdef CONFIG_PLUGIN #include "qemu/plugin-memory.h" @@ -270,6 +270,21 @@ void tlb_init(CPUState *cpu) } } +void tlb_destroy(CPUState *cpu) +{ + CPUArchState *env = cpu->env_ptr; + int i; + + qemu_spin_destroy(&env_tlb(env)->c.lock); + for (i = 0; i < NB_MMU_MODES; i++) { + CPUTLBDesc *desc = &env_tlb(env)->d[i]; + CPUTLBDescFast *fast = &env_tlb(env)->f[i]; + + g_free(fast->table); + g_free(desc->iotlb); + } +} + /* flush_all_helper: run fn across all cpus * * If the wait flag is set then the src cpu's helper will be queued as @@ -297,9 +312,9 @@ void tlb_flush_counts(size_t *pfull, size_t *ppart, size_t *pelide) CPU_FOREACH(cpu) { CPUArchState *env = cpu->env_ptr; - full += atomic_read(&env_tlb(env)->c.full_flush_count); - part += atomic_read(&env_tlb(env)->c.part_flush_count); - elide += atomic_read(&env_tlb(env)->c.elide_flush_count); + full += qatomic_read(&env_tlb(env)->c.full_flush_count); + part += qatomic_read(&env_tlb(env)->c.part_flush_count); + elide += qatomic_read(&env_tlb(env)->c.elide_flush_count); } *pfull = full; *ppart = part; @@ -334,13 +349,13 @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data) cpu_tb_jmp_cache_clear(cpu); if (to_clean == ALL_MMUIDX_BITS) { - atomic_set(&env_tlb(env)->c.full_flush_count, + qatomic_set(&env_tlb(env)->c.full_flush_count, env_tlb(env)->c.full_flush_count + 1); } else { - atomic_set(&env_tlb(env)->c.part_flush_count, + qatomic_set(&env_tlb(env)->c.part_flush_count, env_tlb(env)->c.part_flush_count + ctpop16(to_clean)); if (to_clean != asked) { - atomic_set(&env_tlb(env)->c.elide_flush_count, + qatomic_set(&env_tlb(env)->c.elide_flush_count, env_tlb(env)->c.elide_flush_count + ctpop16(asked & ~to_clean)); } @@ -394,12 +409,21 @@ void tlb_flush_all_cpus_synced(CPUState *src_cpu) tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, ALL_MMUIDX_BITS); } +static bool tlb_hit_page_mask_anyprot(CPUTLBEntry *tlb_entry, + target_ulong page, target_ulong mask) +{ + page &= mask; + mask &= TARGET_PAGE_MASK | TLB_INVALID_MASK; + + return (page == (tlb_entry->addr_read & mask) || + page == (tlb_addr_write(tlb_entry) & mask) || + page == (tlb_entry->addr_code & mask)); +} + static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tlb_entry, target_ulong page) { - return tlb_hit_page(tlb_entry->addr_read, page) || - tlb_hit_page(tlb_addr_write(tlb_entry), page) || - tlb_hit_page(tlb_entry->addr_code, page); + return tlb_hit_page_mask_anyprot(tlb_entry, page, -1); } /** @@ -412,31 +436,45 @@ static inline bool tlb_entry_is_empty(const CPUTLBEntry *te) } /* Called with tlb_c.lock held */ -static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry, - target_ulong page) +static bool tlb_flush_entry_mask_locked(CPUTLBEntry *tlb_entry, + target_ulong page, + target_ulong mask) { - if (tlb_hit_page_anyprot(tlb_entry, page)) { + if (tlb_hit_page_mask_anyprot(tlb_entry, page, mask)) { memset(tlb_entry, -1, sizeof(*tlb_entry)); return true; } return false; } +static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry, + target_ulong page) +{ + return tlb_flush_entry_mask_locked(tlb_entry, page, -1); +} + /* Called with tlb_c.lock held */ -static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx, - target_ulong page) +static void tlb_flush_vtlb_page_mask_locked(CPUArchState *env, int mmu_idx, + target_ulong page, + target_ulong mask) { CPUTLBDesc *d = &env_tlb(env)->d[mmu_idx]; int k; assert_cpu_is_self(env_cpu(env)); for (k = 0; k < CPU_VTLB_SIZE; k++) { - if (tlb_flush_entry_locked(&d->vtable[k], page)) { + if (tlb_flush_entry_mask_locked(&d->vtable[k], page, mask)) { tlb_n_used_entries_dec(env, mmu_idx); } } } +static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx, + target_ulong page) +{ + tlb_flush_vtlb_page_mask_locked(env, mmu_idx, page, -1); +} + static void tlb_flush_page_locked(CPUArchState *env, int midx, target_ulong page) { @@ -651,6 +689,240 @@ void tlb_flush_page_all_cpus_synced(CPUState *src, target_ulong addr) tlb_flush_page_by_mmuidx_all_cpus_synced(src, addr, ALL_MMUIDX_BITS); } +static void tlb_flush_page_bits_locked(CPUArchState *env, int midx, + target_ulong page, unsigned bits) +{ + CPUTLBDesc *d = &env_tlb(env)->d[midx]; + CPUTLBDescFast *f = &env_tlb(env)->f[midx]; + target_ulong mask = MAKE_64BIT_MASK(0, bits); + + /* + * If @bits is smaller than the tlb size, there may be multiple entries + * within the TLB; otherwise all addresses that match under @mask hit + * the same TLB entry. + * + * TODO: Perhaps allow bits to be a few bits less than the size. + * For now, just flush the entire TLB. + */ + if (mask < f->mask) { + tlb_debug("forcing full flush midx %d (" + TARGET_FMT_lx "/" TARGET_FMT_lx ")\n", + midx, page, mask); + tlb_flush_one_mmuidx_locked(env, midx, get_clock_realtime()); + return; + } + + /* Check if we need to flush due to large pages. */ + if ((page & d->large_page_mask) == d->large_page_addr) { + tlb_debug("forcing full flush midx %d (" + TARGET_FMT_lx "/" TARGET_FMT_lx ")\n", + midx, d->large_page_addr, d->large_page_mask); + tlb_flush_one_mmuidx_locked(env, midx, get_clock_realtime()); + return; + } + + if (tlb_flush_entry_mask_locked(tlb_entry(env, midx, page), page, mask)) { + tlb_n_used_entries_dec(env, midx); + } + tlb_flush_vtlb_page_mask_locked(env, midx, page, mask); +} + +typedef struct { + target_ulong addr; + uint16_t idxmap; + uint16_t bits; +} TLBFlushPageBitsByMMUIdxData; + +static void +tlb_flush_page_bits_by_mmuidx_async_0(CPUState *cpu, + TLBFlushPageBitsByMMUIdxData d) +{ + CPUArchState *env = cpu->env_ptr; + int mmu_idx; + + assert_cpu_is_self(cpu); + + tlb_debug("page addr:" TARGET_FMT_lx "/%u mmu_map:0x%x\n", + d.addr, d.bits, d.idxmap); + + qemu_spin_lock(&env_tlb(env)->c.lock); + for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) { + if ((d.idxmap >> mmu_idx) & 1) { + tlb_flush_page_bits_locked(env, mmu_idx, d.addr, d.bits); + } + } + qemu_spin_unlock(&env_tlb(env)->c.lock); + + tb_flush_jmp_cache(cpu, d.addr); +} + +static bool encode_pbm_to_runon(run_on_cpu_data *out, + TLBFlushPageBitsByMMUIdxData d) +{ + /* We need 6 bits to hold to hold @bits up to 63. */ + if (d.idxmap <= MAKE_64BIT_MASK(0, TARGET_PAGE_BITS - 6)) { + *out = RUN_ON_CPU_TARGET_PTR(d.addr | (d.idxmap << 6) | d.bits); + return true; + } + return false; +} + +static TLBFlushPageBitsByMMUIdxData +decode_runon_to_pbm(run_on_cpu_data data) +{ + target_ulong addr_map_bits = (target_ulong) data.target_ptr; + return (TLBFlushPageBitsByMMUIdxData){ + .addr = addr_map_bits & TARGET_PAGE_MASK, + .idxmap = (addr_map_bits & ~TARGET_PAGE_MASK) >> 6, + .bits = addr_map_bits & 0x3f + }; +} + +static void tlb_flush_page_bits_by_mmuidx_async_1(CPUState *cpu, + run_on_cpu_data runon) +{ + tlb_flush_page_bits_by_mmuidx_async_0(cpu, decode_runon_to_pbm(runon)); +} + +static void tlb_flush_page_bits_by_mmuidx_async_2(CPUState *cpu, + run_on_cpu_data data) +{ + TLBFlushPageBitsByMMUIdxData *d = data.host_ptr; + tlb_flush_page_bits_by_mmuidx_async_0(cpu, *d); + g_free(d); +} + +void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr, + uint16_t idxmap, unsigned bits) +{ + TLBFlushPageBitsByMMUIdxData d; + run_on_cpu_data runon; + + /* If all bits are significant, this devolves to tlb_flush_page. */ + if (bits >= TARGET_LONG_BITS) { + tlb_flush_page_by_mmuidx(cpu, addr, idxmap); + return; + } + /* If no page bits are significant, this devolves to tlb_flush. */ + if (bits < TARGET_PAGE_BITS) { + tlb_flush_by_mmuidx(cpu, idxmap); + return; + } + + /* This should already be page aligned */ + d.addr = addr & TARGET_PAGE_MASK; + d.idxmap = idxmap; + d.bits = bits; + + if (qemu_cpu_is_self(cpu)) { + tlb_flush_page_bits_by_mmuidx_async_0(cpu, d); + } else if (encode_pbm_to_runon(&runon, d)) { + async_run_on_cpu(cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon); + } else { + TLBFlushPageBitsByMMUIdxData *p + = g_new(TLBFlushPageBitsByMMUIdxData, 1); + + /* Otherwise allocate a structure, freed by the worker. */ + *p = d; + async_run_on_cpu(cpu, tlb_flush_page_bits_by_mmuidx_async_2, + RUN_ON_CPU_HOST_PTR(p)); + } +} + +void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *src_cpu, + target_ulong addr, + uint16_t idxmap, + unsigned bits) +{ + TLBFlushPageBitsByMMUIdxData d; + run_on_cpu_data runon; + + /* If all bits are significant, this devolves to tlb_flush_page. */ + if (bits >= TARGET_LONG_BITS) { + tlb_flush_page_by_mmuidx_all_cpus(src_cpu, addr, idxmap); + return; + } + /* If no page bits are significant, this devolves to tlb_flush. */ + if (bits < TARGET_PAGE_BITS) { + tlb_flush_by_mmuidx_all_cpus(src_cpu, idxmap); + return; + } + + /* This should already be page aligned */ + d.addr = addr & TARGET_PAGE_MASK; + d.idxmap = idxmap; + d.bits = bits; + + if (encode_pbm_to_runon(&runon, d)) { + flush_all_helper(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon); + } else { + CPUState *dst_cpu; + TLBFlushPageBitsByMMUIdxData *p; + + /* Allocate a separate data block for each destination cpu. */ + CPU_FOREACH(dst_cpu) { + if (dst_cpu != src_cpu) { + p = g_new(TLBFlushPageBitsByMMUIdxData, 1); + *p = d; + async_run_on_cpu(dst_cpu, + tlb_flush_page_bits_by_mmuidx_async_2, + RUN_ON_CPU_HOST_PTR(p)); + } + } + } + + tlb_flush_page_bits_by_mmuidx_async_0(src_cpu, d); +} + +void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *src_cpu, + target_ulong addr, + uint16_t idxmap, + unsigned bits) +{ + TLBFlushPageBitsByMMUIdxData d; + run_on_cpu_data runon; + + /* If all bits are significant, this devolves to tlb_flush_page. */ + if (bits >= TARGET_LONG_BITS) { + tlb_flush_page_by_mmuidx_all_cpus_synced(src_cpu, addr, idxmap); + return; + } + /* If no page bits are significant, this devolves to tlb_flush. */ + if (bits < TARGET_PAGE_BITS) { + tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, idxmap); + return; + } + + /* This should already be page aligned */ + d.addr = addr & TARGET_PAGE_MASK; + d.idxmap = idxmap; + d.bits = bits; + + if (encode_pbm_to_runon(&runon, d)) { + flush_all_helper(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon); + async_safe_run_on_cpu(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1, + runon); + } else { + CPUState *dst_cpu; + TLBFlushPageBitsByMMUIdxData *p; + + /* Allocate a separate data block for each destination cpu. */ + CPU_FOREACH(dst_cpu) { + if (dst_cpu != src_cpu) { + p = g_new(TLBFlushPageBitsByMMUIdxData, 1); + *p = d; + async_run_on_cpu(dst_cpu, tlb_flush_page_bits_by_mmuidx_async_2, + RUN_ON_CPU_HOST_PTR(p)); + } + } + + p = g_new(TLBFlushPageBitsByMMUIdxData, 1); + *p = d; + async_safe_run_on_cpu(src_cpu, tlb_flush_page_bits_by_mmuidx_async_2, + RUN_ON_CPU_HOST_PTR(p)); + } +} + /* update the TLBs so that writes to code in the virtual page 'addr' can be detected */ void tlb_protect_code(ram_addr_t ram_addr) @@ -678,7 +950,7 @@ void tlb_unprotect_code(ram_addr_t ram_addr) * generated code. * * Other vCPUs might be reading their TLBs during guest execution, so we update - * te->addr_write with atomic_set. We don't need to worry about this for + * te->addr_write with qatomic_set. We don't need to worry about this for * oversized guests as MTTCG is disabled for them. * * Called with tlb_c.lock held. @@ -696,7 +968,7 @@ static void tlb_reset_dirty_range_locked(CPUTLBEntry *tlb_entry, #if TCG_OVERSIZED_GUEST tlb_entry->addr_write |= TLB_NOTDIRTY; #else - atomic_set(&tlb_entry->addr_write, + qatomic_set(&tlb_entry->addr_write, tlb_entry->addr_write | TLB_NOTDIRTY); #endif } @@ -1038,7 +1310,7 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry, cpu_io_recompile(cpu, retaddr); } - if (mr->global_locking && !qemu_mutex_iothread_locked()) { + if (!qemu_mutex_iothread_locked()) { qemu_mutex_lock_iothread(); locked = true; } @@ -1058,6 +1330,22 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry, return val; } +/* + * Save a potentially trashed IOTLB entry for later lookup by plugin. + * This is read by tlb_plugin_lookup if the iotlb entry doesn't match + * because of the side effect of io_writex changing memory layout. + */ +static void save_iotlb_data(CPUState *cs, hwaddr addr, + MemoryRegionSection *section, hwaddr mr_offset) +{ +#ifdef CONFIG_PLUGIN + SavedIOTLB *saved = &cs->saved_iotlb; + saved->addr = addr; + saved->section = section; + saved->mr_offset = mr_offset; +#endif +} + static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry, int mmu_idx, uint64_t val, target_ulong addr, uintptr_t retaddr, MemOp op) @@ -1077,7 +1365,13 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry, } cpu->mem_io_pc = retaddr; - if (mr->global_locking && !qemu_mutex_iothread_locked()) { + /* + * The memory_region_dispatch may trigger a flush/resize + * so for plugins we save the iotlb_data just in case. + */ + save_iotlb_data(cpu, iotlbentry->addr, section, mr_offset); + + if (!qemu_mutex_iothread_locked()) { qemu_mutex_lock_iothread(); locked = true; } @@ -1101,8 +1395,8 @@ static inline target_ulong tlb_read_ofs(CPUTLBEntry *entry, size_t ofs) #if TCG_OVERSIZED_GUEST return *(target_ulong *)((uintptr_t)entry + ofs); #else - /* ofs might correspond to .addr_write, so use atomic_read */ - return atomic_read((target_ulong *)((uintptr_t)entry + ofs)); + /* ofs might correspond to .addr_write, so use qatomic_read */ + return qatomic_read((target_ulong *)((uintptr_t)entry + ofs)); #endif } @@ -1118,11 +1412,11 @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index, CPUTLBEntry *vtlb = &env_tlb(env)->d[mmu_idx].vtable[vidx]; target_ulong cmp; - /* elt_ofs might correspond to .addr_write, so use atomic_read */ + /* elt_ofs might correspond to .addr_write, so use qatomic_read */ #if TCG_OVERSIZED_GUEST cmp = *(target_ulong *)((uintptr_t)vtlb + elt_ofs); #else - cmp = atomic_read((target_ulong *)((uintptr_t)vtlb + elt_ofs)); + cmp = qatomic_read((target_ulong *)((uintptr_t)vtlb + elt_ofs)); #endif if (cmp == page) { @@ -1366,8 +1660,12 @@ void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr, * in the softmmu lookup code (or helper). We don't handle re-fills or * checking the victim table. This is purely informational. * - * This should never fail as the memory access being instrumented - * should have just filled the TLB. + * This almost never fails as the memory access being instrumented + * should have just filled the TLB. The one corner case is io_writex + * which can cause TLB flushes and potential resizing of the TLBs + * losing the information we need. In those cases we need to recover + * data from a copy of the iotlbentry. As long as this always occurs + * from the same thread (which a mem callback will be) this is safe. */ bool tlb_plugin_lookup(CPUState *cpu, target_ulong addr, int mmu_idx, @@ -1391,8 +1689,13 @@ bool tlb_plugin_lookup(CPUState *cpu, target_ulong addr, int mmu_idx, data->v.ram.hostaddr = addr + tlbe->addend; } return true; + } else { + SavedIOTLB *saved = &cpu->saved_iotlb; + data->is_io = true; + data->v.io.section = saved->section; + data->v.io.offset = saved->mr_offset; + return true; } - return false; } #endif @@ -1963,6 +2266,80 @@ store_memop(void *haddr, uint64_t val, MemOp op) } } +static void __attribute__((noinline)) +store_helper_unaligned(CPUArchState *env, target_ulong addr, uint64_t val, + uintptr_t retaddr, size_t size, uintptr_t mmu_idx, + bool big_endian) +{ + const size_t tlb_off = offsetof(CPUTLBEntry, addr_write); + uintptr_t index, index2; + CPUTLBEntry *entry, *entry2; + target_ulong page2, tlb_addr, tlb_addr2; + TCGMemOpIdx oi; + size_t size2; + int i; + + /* + * Ensure the second page is in the TLB. Note that the first page + * is already guaranteed to be filled, and that the second page + * cannot evict the first. + */ + page2 = (addr + size) & TARGET_PAGE_MASK; + size2 = (addr + size) & ~TARGET_PAGE_MASK; + index2 = tlb_index(env, mmu_idx, page2); + entry2 = tlb_entry(env, mmu_idx, page2); + + tlb_addr2 = tlb_addr_write(entry2); + if (!tlb_hit_page(tlb_addr2, page2)) { + if (!victim_tlb_hit(env, mmu_idx, index2, tlb_off, page2)) { + tlb_fill(env_cpu(env), page2, size2, MMU_DATA_STORE, + mmu_idx, retaddr); + index2 = tlb_index(env, mmu_idx, page2); + entry2 = tlb_entry(env, mmu_idx, page2); + } + tlb_addr2 = tlb_addr_write(entry2); + } + + index = tlb_index(env, mmu_idx, addr); + entry = tlb_entry(env, mmu_idx, addr); + tlb_addr = tlb_addr_write(entry); + + /* + * Handle watchpoints. Since this may trap, all checks + * must happen before any store. + */ + if (unlikely(tlb_addr & TLB_WATCHPOINT)) { + cpu_check_watchpoint(env_cpu(env), addr, size - size2, + env_tlb(env)->d[mmu_idx].iotlb[index].attrs, + BP_MEM_WRITE, retaddr); + } + if (unlikely(tlb_addr2 & TLB_WATCHPOINT)) { + cpu_check_watchpoint(env_cpu(env), page2, size2, + env_tlb(env)->d[mmu_idx].iotlb[index2].attrs, + BP_MEM_WRITE, retaddr); + } + + /* + * XXX: not efficient, but simple. + * This loop must go in the forward direction to avoid issues + * with self-modifying code in Windows 64-bit. + */ + oi = make_memop_idx(MO_UB, mmu_idx); + if (big_endian) { + for (i = 0; i < size; ++i) { + /* Big-endian extract. */ + uint8_t val8 = val >> (((size - 1) * 8) - (i * 8)); + helper_ret_stb_mmu(env, addr + i, val8, oi, retaddr); + } + } else { + for (i = 0; i < size; ++i) { + /* Little-endian extract. */ + uint8_t val8 = val >> (i * 8); + helper_ret_stb_mmu(env, addr + i, val8, oi, retaddr); + } + } +} + static inline void QEMU_ALWAYS_INLINE store_helper(CPUArchState *env, target_ulong addr, uint64_t val, TCGMemOpIdx oi, uintptr_t retaddr, MemOp op) @@ -2051,64 +2428,9 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val, if (size > 1 && unlikely((addr & ~TARGET_PAGE_MASK) + size - 1 >= TARGET_PAGE_SIZE)) { - int i; - uintptr_t index2; - CPUTLBEntry *entry2; - target_ulong page2, tlb_addr2; - size_t size2; - do_unaligned_access: - /* - * Ensure the second page is in the TLB. Note that the first page - * is already guaranteed to be filled, and that the second page - * cannot evict the first. - */ - page2 = (addr + size) & TARGET_PAGE_MASK; - size2 = (addr + size) & ~TARGET_PAGE_MASK; - index2 = tlb_index(env, mmu_idx, page2); - entry2 = tlb_entry(env, mmu_idx, page2); - tlb_addr2 = tlb_addr_write(entry2); - if (!tlb_hit_page(tlb_addr2, page2)) { - if (!victim_tlb_hit(env, mmu_idx, index2, tlb_off, page2)) { - tlb_fill(env_cpu(env), page2, size2, MMU_DATA_STORE, - mmu_idx, retaddr); - index2 = tlb_index(env, mmu_idx, page2); - entry2 = tlb_entry(env, mmu_idx, page2); - } - tlb_addr2 = tlb_addr_write(entry2); - } - - /* - * Handle watchpoints. Since this may trap, all checks - * must happen before any store. - */ - if (unlikely(tlb_addr & TLB_WATCHPOINT)) { - cpu_check_watchpoint(env_cpu(env), addr, size - size2, - env_tlb(env)->d[mmu_idx].iotlb[index].attrs, - BP_MEM_WRITE, retaddr); - } - if (unlikely(tlb_addr2 & TLB_WATCHPOINT)) { - cpu_check_watchpoint(env_cpu(env), page2, size2, - env_tlb(env)->d[mmu_idx].iotlb[index2].attrs, - BP_MEM_WRITE, retaddr); - } - - /* - * XXX: not efficient, but simple. - * This loop must go in the forward direction to avoid issues - * with self-modifying code in Windows 64-bit. - */ - for (i = 0; i < size; ++i) { - uint8_t val8; - if (memop_big_endian(op)) { - /* Big-endian extract. */ - val8 = val >> (((size - 1) * 8) - (i * 8)); - } else { - /* Little-endian extract. */ - val8 = val >> (i * 8); - } - helper_ret_stb_mmu(env, addr + i, val8, oi, retaddr); - } + store_helper_unaligned(env, addr, val, retaddr, size, + mmu_idx, memop_big_endian(op)); return; } @@ -2116,8 +2438,9 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val, store_memop(haddr, val, op); } -void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val, - TCGMemOpIdx oi, uintptr_t retaddr) +void __attribute__((noinline)) +helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val, + TCGMemOpIdx oi, uintptr_t retaddr) { store_helper(env, addr, val, oi, retaddr, MO_UB); } @@ -2308,7 +2631,7 @@ void cpu_stq_le_data(CPUArchState *env, target_ulong ptr, uint64_t val) #define ATOMIC_MMU_CLEANUP #define ATOMIC_MMU_IDX get_mmuidx(oi) -#include "atomic_common.inc.c" +#include "atomic_common.c.inc" #define DATA_SIZE 1 #include "atomic_template.h" diff --git a/accel/tcg/meson.build b/accel/tcg/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..19b9343d5bfbf770d1022ed3a5e47f9c201736d7 --- /dev/null +++ b/accel/tcg/meson.build @@ -0,0 +1,15 @@ +tcg_ss = ss.source_set() +tcg_ss.add(files( + 'cpu-exec-common.c', + 'cpu-exec.c', + 'tcg-runtime-gvec.c', + 'tcg-runtime.c', + 'translate-all.c', + 'translator.c', +)) +tcg_ss.add(when: 'CONFIG_USER_ONLY', if_true: files('user-exec.c')) +tcg_ss.add(when: 'CONFIG_SOFTMMU', if_false: files('user-exec-stub.c')) +tcg_ss.add(when: 'CONFIG_PLUGIN', if_true: [files('plugin-gen.c'), libdl]) +specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss) + +specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: files('tcg-all.c', 'cputlb.c', 'tcg-cpus.c')) diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c index 3b4fda5640d2f3fc12a6ff3239ee9b339651bbd1..fa1208158fce594383acd159f6de6faf30f5bcaf 100644 --- a/accel/tcg/tcg-all.c +++ b/accel/tcg/tcg-all.c @@ -24,54 +24,28 @@ */ #include "qemu/osdep.h" -#include "sysemu/accel.h" +#include "qemu-common.h" #include "sysemu/tcg.h" -#include "qom/object.h" -#include "cpu.h" -#include "sysemu/cpus.h" -#include "qemu/main-loop.h" +#include "sysemu/cpu-timers.h" #include "tcg/tcg.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "hw/boards.h" #include "qapi/qapi-builtin-visit.h" +#include "tcg-cpus.h" -typedef struct TCGState { +struct TCGState { AccelState parent_obj; bool mttcg_enabled; unsigned long tb_size; -} TCGState; +}; +typedef struct TCGState TCGState; #define TYPE_TCG_ACCEL ACCEL_CLASS_NAME("tcg") -#define TCG_STATE(obj) \ - OBJECT_CHECK(TCGState, (obj), TYPE_TCG_ACCEL) - -/* mask must never be zero, except for A20 change call */ -static void tcg_handle_interrupt(CPUState *cpu, int mask) -{ - int old_mask; - g_assert(qemu_mutex_iothread_locked()); - - old_mask = cpu->interrupt_request; - cpu->interrupt_request |= mask; - - /* - * If called from iothread context, wake the target cpu in - * case its halted. - */ - if (!qemu_cpu_is_self(cpu)) { - qemu_cpu_kick(cpu); - } else { - atomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1); - if (use_icount && - !cpu->can_do_io - && (mask & ~old_mask) != 0) { - cpu_abort(cpu, "Raised interrupt while not in I/O function"); - } - } -} +DECLARE_INSTANCE_CHECKER(TCGState, TCG_STATE, + TYPE_TCG_ACCEL) /* * We default to false if we know other options have been enabled @@ -104,7 +78,7 @@ static bool check_tcg_memory_orders_compatible(void) static bool default_mttcg_enabled(void) { - if (use_icount || TCG_OVERSIZED_GUEST) { + if (icount_enabled() || TCG_OVERSIZED_GUEST) { return false; } else { #ifdef TARGET_SUPPORTS_MTTCG @@ -122,13 +96,16 @@ static void tcg_accel_instance_init(Object *obj) s->mttcg_enabled = default_mttcg_enabled(); } +bool mttcg_enabled; + static int tcg_init(MachineState *ms) { TCGState *s = TCG_STATE(current_accel()); tcg_exec_init(s->tb_size * 1024 * 1024); - cpu_interrupt_handler = tcg_handle_interrupt; mttcg_enabled = s->mttcg_enabled; + cpus_register_accel(&tcg_cpus); + return 0; } @@ -146,7 +123,7 @@ static void tcg_set_thread(Object *obj, const char *value, Error **errp) if (strcmp(value, "multi") == 0) { if (TCG_OVERSIZED_GUEST) { error_setg(errp, "No MTTCG when guest word size > hosts"); - } else if (use_icount) { + } else if (icount_enabled()) { error_setg(errp, "No MTTCG when icount is enabled"); } else { #ifndef TARGET_SUPPORTS_MTTCG @@ -182,12 +159,9 @@ static void tcg_set_tb_size(Object *obj, Visitor *v, Error **errp) { TCGState *s = TCG_STATE(obj); - Error *error = NULL; uint32_t value; - visit_type_uint32(v, name, &value, &error); - if (error) { - error_propagate(errp, error); + if (!visit_type_uint32(v, name, &value, errp)) { return; } diff --git a/accel/tcg/tcg-cpus.c b/accel/tcg/tcg-cpus.c new file mode 100644 index 0000000000000000000000000000000000000000..da1c63d8f60802da2137fa0e55656a423f0bbd4a --- /dev/null +++ b/accel/tcg/tcg-cpus.c @@ -0,0 +1,570 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2014 Red Hat Inc. + * + * 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 "qemu-common.h" +#include "sysemu/tcg.h" +#include "sysemu/replay.h" +#include "qemu/main-loop.h" +#include "qemu/guest-random.h" +#include "exec/exec-all.h" +#include "hw/boards.h" + +#include "tcg-cpus.h" + +/* Kick all RR vCPUs */ +static void qemu_cpu_kick_rr_cpus(void) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + cpu_exit(cpu); + }; +} + +static void tcg_kick_vcpu_thread(CPUState *cpu) +{ + if (qemu_tcg_mttcg_enabled()) { + cpu_exit(cpu); + } else { + qemu_cpu_kick_rr_cpus(); + } +} + +/* + * TCG vCPU kick timer + * + * The kick timer is responsible for moving single threaded vCPU + * emulation on to the next vCPU. If more than one vCPU is running a + * timer event with force a cpu->exit so the next vCPU can get + * scheduled. + * + * The timer is removed if all vCPUs are idle and restarted again once + * idleness is complete. + */ + +static QEMUTimer *tcg_kick_vcpu_timer; +static CPUState *tcg_current_rr_cpu; + +#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10) + +static inline int64_t qemu_tcg_next_kick(void) +{ + return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + TCG_KICK_PERIOD; +} + +/* Kick the currently round-robin scheduled vCPU to next */ +static void qemu_cpu_kick_rr_next_cpu(void) +{ + CPUState *cpu; + do { + cpu = qatomic_mb_read(&tcg_current_rr_cpu); + if (cpu) { + cpu_exit(cpu); + } + } while (cpu != qatomic_mb_read(&tcg_current_rr_cpu)); +} + +static void kick_tcg_thread(void *opaque) +{ + timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick()); + qemu_cpu_kick_rr_next_cpu(); +} + +static void start_tcg_kick_timer(void) +{ + assert(!mttcg_enabled); + if (!tcg_kick_vcpu_timer && CPU_NEXT(first_cpu)) { + tcg_kick_vcpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, + kick_tcg_thread, NULL); + } + if (tcg_kick_vcpu_timer && !timer_pending(tcg_kick_vcpu_timer)) { + timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick()); + } +} + +static void stop_tcg_kick_timer(void) +{ + assert(!mttcg_enabled); + if (tcg_kick_vcpu_timer && timer_pending(tcg_kick_vcpu_timer)) { + timer_del(tcg_kick_vcpu_timer); + } +} + +static void qemu_tcg_destroy_vcpu(CPUState *cpu) +{ +} + +static void qemu_tcg_rr_wait_io_event(void) +{ + CPUState *cpu; + + while (all_cpu_threads_idle()) { + stop_tcg_kick_timer(); + qemu_cond_wait_iothread(first_cpu->halt_cond); + } + + start_tcg_kick_timer(); + + CPU_FOREACH(cpu) { + qemu_wait_io_event_common(cpu); + } +} + +static int64_t tcg_get_icount_limit(void) +{ + int64_t deadline; + + if (replay_mode != REPLAY_MODE_PLAY) { + /* + * Include all the timers, because they may need an attention. + * Too long CPU execution may create unnecessary delay in UI. + */ + deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, + QEMU_TIMER_ATTR_ALL); + /* Check realtime timers, because they help with input processing */ + deadline = qemu_soonest_timeout(deadline, + qemu_clock_deadline_ns_all(QEMU_CLOCK_REALTIME, + QEMU_TIMER_ATTR_ALL)); + + /* + * Maintain prior (possibly buggy) behaviour where if no deadline + * was set (as there is no QEMU_CLOCK_VIRTUAL timer) or it is more than + * INT32_MAX nanoseconds ahead, we still use INT32_MAX + * nanoseconds. + */ + if ((deadline < 0) || (deadline > INT32_MAX)) { + deadline = INT32_MAX; + } + + return icount_round(deadline); + } else { + return replay_get_instructions(); + } +} + +static void notify_aio_contexts(void) +{ + /* Wake up other AioContexts. */ + qemu_clock_notify(QEMU_CLOCK_VIRTUAL); + qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL); +} + +static void handle_icount_deadline(void) +{ + assert(qemu_in_vcpu_thread()); + if (icount_enabled()) { + int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, + QEMU_TIMER_ATTR_ALL); + + if (deadline == 0) { + notify_aio_contexts(); + } + } +} + +static void prepare_icount_for_run(CPUState *cpu) +{ + if (icount_enabled()) { + int insns_left; + + /* + * These should always be cleared by process_icount_data after + * each vCPU execution. However u16.high can be raised + * asynchronously by cpu_exit/cpu_interrupt/tcg_handle_interrupt + */ + g_assert(cpu_neg(cpu)->icount_decr.u16.low == 0); + g_assert(cpu->icount_extra == 0); + + cpu->icount_budget = tcg_get_icount_limit(); + insns_left = MIN(0xffff, cpu->icount_budget); + cpu_neg(cpu)->icount_decr.u16.low = insns_left; + cpu->icount_extra = cpu->icount_budget - insns_left; + + replay_mutex_lock(); + + if (cpu->icount_budget == 0 && replay_has_checkpoint()) { + notify_aio_contexts(); + } + } +} + +static void process_icount_data(CPUState *cpu) +{ + if (icount_enabled()) { + /* Account for executed instructions */ + icount_update(cpu); + + /* Reset the counters */ + cpu_neg(cpu)->icount_decr.u16.low = 0; + cpu->icount_extra = 0; + cpu->icount_budget = 0; + + replay_account_executed_instructions(); + + replay_mutex_unlock(); + } +} + +static int tcg_cpu_exec(CPUState *cpu) +{ + int ret; +#ifdef CONFIG_PROFILER + int64_t ti; +#endif + + assert(tcg_enabled()); +#ifdef CONFIG_PROFILER + ti = profile_getclock(); +#endif + cpu_exec_start(cpu); + ret = cpu_exec(cpu); + cpu_exec_end(cpu); +#ifdef CONFIG_PROFILER + qatomic_set(&tcg_ctx->prof.cpu_exec_time, + tcg_ctx->prof.cpu_exec_time + profile_getclock() - ti); +#endif + return ret; +} + +/* + * Destroy any remaining vCPUs which have been unplugged and have + * finished running + */ +static void deal_with_unplugged_cpus(void) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + if (cpu->unplug && !cpu_can_run(cpu)) { + qemu_tcg_destroy_vcpu(cpu); + cpu_thread_signal_destroyed(cpu); + break; + } + } +} + +/* + * Single-threaded TCG + * + * In the single-threaded case each vCPU is simulated in turn. If + * there is more than a single vCPU we create a simple timer to kick + * the vCPU and ensure we don't get stuck in a tight loop in one vCPU. + * This is done explicitly rather than relying on side-effects + * elsewhere. + */ + +static void *tcg_rr_cpu_thread_fn(void *arg) +{ + CPUState *cpu = arg; + + assert(tcg_enabled()); + rcu_register_thread(); + tcg_register_thread(); + + qemu_mutex_lock_iothread(); + qemu_thread_get_self(cpu->thread); + + cpu->thread_id = qemu_get_thread_id(); + cpu->can_do_io = 1; + cpu_thread_signal_created(cpu); + qemu_guest_random_seed_thread_part2(cpu->random_seed); + + /* wait for initial kick-off after machine start */ + while (first_cpu->stopped) { + qemu_cond_wait_iothread(first_cpu->halt_cond); + + /* process any pending work */ + CPU_FOREACH(cpu) { + current_cpu = cpu; + qemu_wait_io_event_common(cpu); + } + } + + start_tcg_kick_timer(); + + cpu = first_cpu; + + /* process any pending work */ + cpu->exit_request = 1; + + while (1) { + qemu_mutex_unlock_iothread(); + replay_mutex_lock(); + qemu_mutex_lock_iothread(); + /* Account partial waits to QEMU_CLOCK_VIRTUAL. */ + icount_account_warp_timer(); + + /* + * Run the timers here. This is much more efficient than + * waking up the I/O thread and waiting for completion. + */ + handle_icount_deadline(); + + replay_mutex_unlock(); + + if (!cpu) { + cpu = first_cpu; + } + + while (cpu && cpu_work_list_empty(cpu) && !cpu->exit_request) { + + qatomic_mb_set(&tcg_current_rr_cpu, cpu); + current_cpu = cpu; + + qemu_clock_enable(QEMU_CLOCK_VIRTUAL, + (cpu->singlestep_enabled & SSTEP_NOTIMER) == 0); + + if (cpu_can_run(cpu)) { + int r; + + qemu_mutex_unlock_iothread(); + prepare_icount_for_run(cpu); + + r = tcg_cpu_exec(cpu); + + process_icount_data(cpu); + qemu_mutex_lock_iothread(); + + if (r == EXCP_DEBUG) { + cpu_handle_guest_debug(cpu); + break; + } else if (r == EXCP_ATOMIC) { + qemu_mutex_unlock_iothread(); + cpu_exec_step_atomic(cpu); + qemu_mutex_lock_iothread(); + break; + } + } else if (cpu->stop) { + if (cpu->unplug) { + cpu = CPU_NEXT(cpu); + } + break; + } + + cpu = CPU_NEXT(cpu); + } /* while (cpu && !cpu->exit_request).. */ + + /* Does not need qatomic_mb_set because a spurious wakeup is okay. */ + qatomic_set(&tcg_current_rr_cpu, NULL); + + if (cpu && cpu->exit_request) { + qatomic_mb_set(&cpu->exit_request, 0); + } + + if (icount_enabled() && all_cpu_threads_idle()) { + /* + * When all cpus are sleeping (e.g in WFI), to avoid a deadlock + * in the main_loop, wake it up in order to start the warp timer. + */ + qemu_notify_event(); + } + + qemu_tcg_rr_wait_io_event(); + deal_with_unplugged_cpus(); + } + + rcu_unregister_thread(); + return NULL; +} + +/* + * Multi-threaded TCG + * + * In the multi-threaded case each vCPU has its own thread. The TLS + * variable current_cpu can be used deep in the code to find the + * current CPUState for a given thread. + */ + +static void *tcg_cpu_thread_fn(void *arg) +{ + CPUState *cpu = arg; + + assert(tcg_enabled()); + g_assert(!icount_enabled()); + + rcu_register_thread(); + tcg_register_thread(); + + qemu_mutex_lock_iothread(); + qemu_thread_get_self(cpu->thread); + + cpu->thread_id = qemu_get_thread_id(); + cpu->can_do_io = 1; + current_cpu = cpu; + cpu_thread_signal_created(cpu); + qemu_guest_random_seed_thread_part2(cpu->random_seed); + + /* process any pending work */ + cpu->exit_request = 1; + + do { + if (cpu_can_run(cpu)) { + int r; + qemu_mutex_unlock_iothread(); + r = tcg_cpu_exec(cpu); + qemu_mutex_lock_iothread(); + switch (r) { + case EXCP_DEBUG: + cpu_handle_guest_debug(cpu); + break; + case EXCP_HALTED: + /* + * during start-up the vCPU is reset and the thread is + * kicked several times. If we don't ensure we go back + * to sleep in the halted state we won't cleanly + * start-up when the vCPU is enabled. + * + * cpu->halted should ensure we sleep in wait_io_event + */ + g_assert(cpu->halted); + break; + case EXCP_ATOMIC: + qemu_mutex_unlock_iothread(); + cpu_exec_step_atomic(cpu); + qemu_mutex_lock_iothread(); + default: + /* Ignore everything else? */ + break; + } + } + + qatomic_mb_set(&cpu->exit_request, 0); + qemu_wait_io_event(cpu); + } while (!cpu->unplug || cpu_can_run(cpu)); + + qemu_tcg_destroy_vcpu(cpu); + cpu_thread_signal_destroyed(cpu); + qemu_mutex_unlock_iothread(); + rcu_unregister_thread(); + return NULL; +} + +static void tcg_start_vcpu_thread(CPUState *cpu) +{ + char thread_name[VCPU_THREAD_NAME_SIZE]; + static QemuCond *single_tcg_halt_cond; + static QemuThread *single_tcg_cpu_thread; + static int tcg_region_inited; + + assert(tcg_enabled()); + /* + * Initialize TCG regions--once. Now is a good time, because: + * (1) TCG's init context, prologue and target globals have been set up. + * (2) qemu_tcg_mttcg_enabled() works now (TCG init code runs before the + * -accel flag is processed, so the check doesn't work then). + */ + if (!tcg_region_inited) { + tcg_region_inited = 1; + tcg_region_init(); + parallel_cpus = qemu_tcg_mttcg_enabled() && current_machine->smp.max_cpus > 1; + } + + if (qemu_tcg_mttcg_enabled() || !single_tcg_cpu_thread) { + cpu->thread = g_malloc0(sizeof(QemuThread)); + cpu->halt_cond = g_malloc0(sizeof(QemuCond)); + qemu_cond_init(cpu->halt_cond); + + if (qemu_tcg_mttcg_enabled()) { + /* create a thread per vCPU with TCG (MTTCG) */ + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/TCG", + cpu->cpu_index); + + qemu_thread_create(cpu->thread, thread_name, tcg_cpu_thread_fn, + cpu, QEMU_THREAD_JOINABLE); + + } else { + /* share a single thread for all cpus with TCG */ + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "ALL CPUs/TCG"); + qemu_thread_create(cpu->thread, thread_name, + tcg_rr_cpu_thread_fn, + cpu, QEMU_THREAD_JOINABLE); + + single_tcg_halt_cond = cpu->halt_cond; + single_tcg_cpu_thread = cpu->thread; + } +#ifdef _WIN32 + cpu->hThread = qemu_thread_get_handle(cpu->thread); +#endif + } else { + /* For non-MTTCG cases we share the thread */ + cpu->thread = single_tcg_cpu_thread; + cpu->halt_cond = single_tcg_halt_cond; + cpu->thread_id = first_cpu->thread_id; + cpu->can_do_io = 1; + cpu->created = true; + } +} + +static int64_t tcg_get_virtual_clock(void) +{ + if (icount_enabled()) { + return icount_get(); + } + return cpu_get_clock(); +} + +static int64_t tcg_get_elapsed_ticks(void) +{ + if (icount_enabled()) { + return icount_get(); + } + return cpu_get_ticks(); +} + +/* mask must never be zero, except for A20 change call */ +static void tcg_handle_interrupt(CPUState *cpu, int mask) +{ + int old_mask; + g_assert(qemu_mutex_iothread_locked()); + + old_mask = cpu->interrupt_request; + cpu->interrupt_request |= mask; + + /* + * If called from iothread context, wake the target cpu in + * case its halted. + */ + if (!qemu_cpu_is_self(cpu)) { + qemu_cpu_kick(cpu); + } else { + qatomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1); + if (icount_enabled() && + !cpu->can_do_io + && (mask & ~old_mask) != 0) { + cpu_abort(cpu, "Raised interrupt while not in I/O function"); + } + } +} + +const CpusAccel tcg_cpus = { + .create_vcpu_thread = tcg_start_vcpu_thread, + .kick_vcpu_thread = tcg_kick_vcpu_thread, + + .handle_interrupt = tcg_handle_interrupt, + + .get_virtual_clock = tcg_get_virtual_clock, + .get_elapsed_ticks = tcg_get_elapsed_ticks, +}; diff --git a/accel/tcg/tcg-cpus.h b/accel/tcg/tcg-cpus.h new file mode 100644 index 0000000000000000000000000000000000000000..8b1d9d2abc8d19889e3bfc9d562eafa1905613ff --- /dev/null +++ b/accel/tcg/tcg-cpus.h @@ -0,0 +1,17 @@ +/* + * Accelerator CPUS Interface + * + * Copyright 2020 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef TCG_CPUS_H +#define TCG_CPUS_H + +#include "sysemu/cpus.h" + +extern const CpusAccel tcg_cpus; + +#endif /* TCG_CPUS_H */ diff --git a/accel/tcg/tcg-runtime-gvec.c b/accel/tcg/tcg-runtime-gvec.c index ca449702e67d3957475714892e27df11f8dcf837..521da4a813768817dfb9934810aa3fcc12e80866 100644 --- a/accel/tcg/tcg-runtime-gvec.c +++ b/accel/tcg/tcg-runtime-gvec.c @@ -716,6 +716,54 @@ void HELPER(gvec_sar64i)(void *d, void *a, uint32_t desc) clear_high(d, oprsz, desc); } +void HELPER(gvec_rotl8i)(void *d, void *a, uint32_t desc) +{ + intptr_t oprsz = simd_oprsz(desc); + int shift = simd_data(desc); + intptr_t i; + + for (i = 0; i < oprsz; i += sizeof(uint8_t)) { + *(uint8_t *)(d + i) = rol8(*(uint8_t *)(a + i), shift); + } + clear_high(d, oprsz, desc); +} + +void HELPER(gvec_rotl16i)(void *d, void *a, uint32_t desc) +{ + intptr_t oprsz = simd_oprsz(desc); + int shift = simd_data(desc); + intptr_t i; + + for (i = 0; i < oprsz; i += sizeof(uint16_t)) { + *(uint16_t *)(d + i) = rol16(*(uint16_t *)(a + i), shift); + } + clear_high(d, oprsz, desc); +} + +void HELPER(gvec_rotl32i)(void *d, void *a, uint32_t desc) +{ + intptr_t oprsz = simd_oprsz(desc); + int shift = simd_data(desc); + intptr_t i; + + for (i = 0; i < oprsz; i += sizeof(uint32_t)) { + *(uint32_t *)(d + i) = rol32(*(uint32_t *)(a + i), shift); + } + clear_high(d, oprsz, desc); +} + +void HELPER(gvec_rotl64i)(void *d, void *a, uint32_t desc) +{ + intptr_t oprsz = simd_oprsz(desc); + int shift = simd_data(desc); + intptr_t i; + + for (i = 0; i < oprsz; i += sizeof(uint64_t)) { + *(uint64_t *)(d + i) = rol64(*(uint64_t *)(a + i), shift); + } + clear_high(d, oprsz, desc); +} + void HELPER(gvec_shl8v)(void *d, void *a, void *b, uint32_t desc) { intptr_t oprsz = simd_oprsz(desc); @@ -860,6 +908,102 @@ void HELPER(gvec_sar64v)(void *d, void *a, void *b, uint32_t desc) clear_high(d, oprsz, desc); } +void HELPER(gvec_rotl8v)(void *d, void *a, void *b, uint32_t desc) +{ + intptr_t oprsz = simd_oprsz(desc); + intptr_t i; + + for (i = 0; i < oprsz; i += sizeof(uint8_t)) { + uint8_t sh = *(uint8_t *)(b + i) & 7; + *(uint8_t *)(d + i) = rol8(*(uint8_t *)(a + i), sh); + } + clear_high(d, oprsz, desc); +} + +void HELPER(gvec_rotl16v)(void *d, void *a, void *b, uint32_t desc) +{ + intptr_t oprsz = simd_oprsz(desc); + intptr_t i; + + for (i = 0; i < oprsz; i += sizeof(uint16_t)) { + uint8_t sh = *(uint16_t *)(b + i) & 15; + *(uint16_t *)(d + i) = rol16(*(uint16_t *)(a + i), sh); + } + clear_high(d, oprsz, desc); +} + +void HELPER(gvec_rotl32v)(void *d, void *a, void *b, uint32_t desc) +{ + intptr_t oprsz = simd_oprsz(desc); + intptr_t i; + + for (i = 0; i < oprsz; i += sizeof(uint32_t)) { + uint8_t sh = *(uint32_t *)(b + i) & 31; + *(uint32_t *)(d + i) = rol32(*(uint32_t *)(a + i), sh); + } + clear_high(d, oprsz, desc); +} + +void HELPER(gvec_rotl64v)(void *d, void *a, void *b, uint32_t desc) +{ + intptr_t oprsz = simd_oprsz(desc); + intptr_t i; + + for (i = 0; i < oprsz; i += sizeof(uint64_t)) { + uint8_t sh = *(uint64_t *)(b + i) & 63; + *(uint64_t *)(d + i) = rol64(*(uint64_t *)(a + i), sh); + } + clear_high(d, oprsz, desc); +} + +void HELPER(gvec_rotr8v)(void *d, void *a, void *b, uint32_t desc) +{ + intptr_t oprsz = simd_oprsz(desc); + intptr_t i; + + for (i = 0; i < oprsz; i += sizeof(uint8_t)) { + uint8_t sh = *(uint8_t *)(b + i) & 7; + *(uint8_t *)(d + i) = ror8(*(uint8_t *)(a + i), sh); + } + clear_high(d, oprsz, desc); +} + +void HELPER(gvec_rotr16v)(void *d, void *a, void *b, uint32_t desc) +{ + intptr_t oprsz = simd_oprsz(desc); + intptr_t i; + + for (i = 0; i < oprsz; i += sizeof(uint16_t)) { + uint8_t sh = *(uint16_t *)(b + i) & 15; + *(uint16_t *)(d + i) = ror16(*(uint16_t *)(a + i), sh); + } + clear_high(d, oprsz, desc); +} + +void HELPER(gvec_rotr32v)(void *d, void *a, void *b, uint32_t desc) +{ + intptr_t oprsz = simd_oprsz(desc); + intptr_t i; + + for (i = 0; i < oprsz; i += sizeof(uint32_t)) { + uint8_t sh = *(uint32_t *)(b + i) & 31; + *(uint32_t *)(d + i) = ror32(*(uint32_t *)(a + i), sh); + } + clear_high(d, oprsz, desc); +} + +void HELPER(gvec_rotr64v)(void *d, void *a, void *b, uint32_t desc) +{ + intptr_t oprsz = simd_oprsz(desc); + intptr_t i; + + for (i = 0; i < oprsz; i += sizeof(uint64_t)) { + uint8_t sh = *(uint64_t *)(b + i) & 63; + *(uint64_t *)(d + i) = ror64(*(uint64_t *)(a + i), sh); + } + clear_high(d, oprsz, desc); +} + #define DO_CMP1(NAME, TYPE, OP) \ void HELPER(NAME)(void *d, void *a, void *b, uint32_t desc) \ { \ diff --git a/accel/tcg/tcg-runtime.h b/accel/tcg/tcg-runtime.h index 4fa61b49b437eb939e21194665a6d5f0aafb8f4a..4eda24e63af46de4873822cdabf5faa070a41e85 100644 --- a/accel/tcg/tcg-runtime.h +++ b/accel/tcg/tcg-runtime.h @@ -259,6 +259,11 @@ DEF_HELPER_FLAGS_3(gvec_sar16i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) DEF_HELPER_FLAGS_3(gvec_sar32i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) DEF_HELPER_FLAGS_3(gvec_sar64i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) +DEF_HELPER_FLAGS_3(gvec_rotl8i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) +DEF_HELPER_FLAGS_3(gvec_rotl16i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) +DEF_HELPER_FLAGS_3(gvec_rotl32i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) +DEF_HELPER_FLAGS_3(gvec_rotl64i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) + DEF_HELPER_FLAGS_4(gvec_shl8v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_shl16v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_shl32v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) @@ -274,6 +279,16 @@ DEF_HELPER_FLAGS_4(gvec_sar16v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_sar32v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_sar64v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_rotl8v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_rotl16v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_rotl32v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_rotl64v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(gvec_rotr8v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_rotr16v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_rotr32v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_rotr64v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + DEF_HELPER_FLAGS_4(gvec_eq8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_eq16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_eq32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) diff --git a/accel/tcg/trace.h b/accel/tcg/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..db61fad3c6ff5565bd944c59f5284b4fe016f613 --- /dev/null +++ b/accel/tcg/trace.h @@ -0,0 +1 @@ +#include "trace/trace-accel_tcg.h" diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 42ce1dfcff77eeaa96c2cdb3040e6330b651dfc3..4572b4901fb54592ba18b109a02dc089e1af25c1 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -57,6 +57,7 @@ #include "qemu/main-loop.h" #include "exec/log.h" #include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" #include "sysemu/tcg.h" /* #define DEBUG_TB_INVALIDATE */ @@ -369,7 +370,7 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb, found: if (reset_icount && (tb_cflags(tb) & CF_USE_ICOUNT)) { - assert(use_icount); + assert(icount_enabled()); /* Reset the cycle counter to the start of the block and shift if to the number of actually executed instructions */ cpu_neg(cpu)->icount_decr.u16.low += num_insns - i; @@ -377,13 +378,18 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb, restore_state_to_opc(env, tb, data); #ifdef CONFIG_PROFILER - atomic_set(&prof->restore_time, + qatomic_set(&prof->restore_time, prof->restore_time + profile_getclock() - ti); - atomic_set(&prof->restore_count, prof->restore_count + 1); + qatomic_set(&prof->restore_count, prof->restore_count + 1); #endif return 0; } +void tb_destroy(TranslationBlock *tb) +{ + qemu_spin_destroy(&tb->jmp_lock); +} + bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit) { TranslationBlock *tb; @@ -413,6 +419,7 @@ bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit) /* one-shot translation, invalidate it immediately */ tb_phys_invalidate(tb, -1); tcg_tb_remove(tb); + tb_destroy(tb); } r = true; } @@ -503,7 +510,7 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc) /* Level 2..N-1. */ for (i = v_l2_levels; i > 0; i--) { - void **p = atomic_rcu_read(lp); + void **p = qatomic_rcu_read(lp); if (p == NULL) { void *existing; @@ -512,7 +519,7 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc) return NULL; } p = g_new0(void *, V_L2_SIZE); - existing = atomic_cmpxchg(lp, NULL, p); + existing = qatomic_cmpxchg(lp, NULL, p); if (unlikely(existing)) { g_free(p); p = existing; @@ -522,7 +529,7 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc) lp = p + ((index >> (i * V_L2_BITS)) & (V_L2_SIZE - 1)); } - pd = atomic_rcu_read(lp); + pd = qatomic_rcu_read(lp); if (pd == NULL) { void *existing; @@ -539,8 +546,17 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc) } } #endif - existing = atomic_cmpxchg(lp, NULL, pd); + existing = qatomic_cmpxchg(lp, NULL, pd); if (unlikely(existing)) { +#ifndef CONFIG_USER_ONLY + { + int i; + + for (i = 0; i < V_L2_SIZE; i++) { + qemu_spin_destroy(&pd[i].lock); + } + } +#endif g_free(pd); pd = existing; } @@ -961,7 +977,12 @@ static inline size_t size_code_gen_buffer(size_t tb_size) { /* Size the buffer. */ if (tb_size == 0) { - tb_size = DEFAULT_CODE_GEN_BUFFER_SIZE; + size_t phys_mem = qemu_get_host_physmem(); + if (phys_mem == 0) { + tb_size = DEFAULT_CODE_GEN_BUFFER_SIZE; + } else { + tb_size = MIN(DEFAULT_CODE_GEN_BUFFER_SIZE, phys_mem / 8); + } } if (tb_size < MIN_CODE_GEN_BUFFER_SIZE) { tb_size = MIN_CODE_GEN_BUFFER_SIZE; @@ -1233,7 +1254,7 @@ static void do_tb_flush(CPUState *cpu, run_on_cpu_data tb_flush_count) tcg_region_reset_all(); /* XXX: flush processor icache at this point if cache flush is expensive */ - atomic_mb_set(&tb_ctx.tb_flush_count, tb_ctx.tb_flush_count + 1); + qatomic_mb_set(&tb_ctx.tb_flush_count, tb_ctx.tb_flush_count + 1); done: mmap_unlock(); @@ -1245,7 +1266,7 @@ done: void tb_flush(CPUState *cpu) { if (tcg_enabled()) { - unsigned tb_flush_count = atomic_mb_read(&tb_ctx.tb_flush_count); + unsigned tb_flush_count = qatomic_mb_read(&tb_ctx.tb_flush_count); if (cpu_in_exclusive_context(cpu)) { do_tb_flush(cpu, RUN_ON_CPU_HOST_INT(tb_flush_count)); @@ -1338,7 +1359,7 @@ static inline void tb_remove_from_jmp_list(TranslationBlock *orig, int n_orig) int n; /* mark the LSB of jmp_dest[] so that no further jumps can be inserted */ - ptr = atomic_or_fetch(&orig->jmp_dest[n_orig], 1); + ptr = qatomic_or_fetch(&orig->jmp_dest[n_orig], 1); dest = (TranslationBlock *)(ptr & ~1); if (dest == NULL) { return; @@ -1349,7 +1370,7 @@ static inline void tb_remove_from_jmp_list(TranslationBlock *orig, int n_orig) * While acquiring the lock, the jump might have been removed if the * destination TB was invalidated; check again. */ - ptr_locked = atomic_read(&orig->jmp_dest[n_orig]); + ptr_locked = qatomic_read(&orig->jmp_dest[n_orig]); if (ptr_locked != ptr) { qemu_spin_unlock(&dest->jmp_lock); /* @@ -1395,7 +1416,7 @@ static inline void tb_jmp_unlink(TranslationBlock *dest) TB_FOR_EACH_JMP(dest, tb, n) { tb_reset_jump(tb, n); - atomic_and(&tb->jmp_dest[n], (uintptr_t)NULL | 1); + qatomic_and(&tb->jmp_dest[n], (uintptr_t)NULL | 1); /* No need to clear the list entry; setting the dest ptr is enough */ } dest->jmp_list_head = (uintptr_t)NULL; @@ -1419,7 +1440,7 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) /* make sure no further incoming jumps will be chained to this TB */ qemu_spin_lock(&tb->jmp_lock); - atomic_set(&tb->cflags, tb->cflags | CF_INVALID); + qatomic_set(&tb->cflags, tb->cflags | CF_INVALID); qemu_spin_unlock(&tb->jmp_lock); /* remove the TB from the hash list */ @@ -1446,8 +1467,8 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) /* remove the TB from the hash list */ h = tb_jmp_cache_hash_func(tb->pc); CPU_FOREACH(cpu) { - if (atomic_read(&cpu->tb_jmp_cache[h]) == tb) { - atomic_set(&cpu->tb_jmp_cache[h], NULL); + if (qatomic_read(&cpu->tb_jmp_cache[h]) == tb) { + qatomic_set(&cpu->tb_jmp_cache[h], NULL); } } @@ -1458,7 +1479,7 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) /* suppress any remaining jumps to this TB */ tb_jmp_unlink(tb); - atomic_set(&tcg_ctx->tb_phys_invalidate_count, + qatomic_set(&tcg_ctx->tb_phys_invalidate_count, tcg_ctx->tb_phys_invalidate_count + 1); } @@ -1713,7 +1734,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, #ifdef CONFIG_PROFILER /* includes aborted translations because of exceptions */ - atomic_set(&prof->tb_count1, prof->tb_count1 + 1); + qatomic_set(&prof->tb_count1, prof->tb_count1 + 1); ti = profile_getclock(); #endif @@ -1738,8 +1759,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu, } #ifdef CONFIG_PROFILER - atomic_set(&prof->tb_count, prof->tb_count + 1); - atomic_set(&prof->interm_time, prof->interm_time + profile_getclock() - ti); + qatomic_set(&prof->tb_count, prof->tb_count + 1); + qatomic_set(&prof->interm_time, + prof->interm_time + profile_getclock() - ti); ti = profile_getclock(); #endif @@ -1784,10 +1806,10 @@ TranslationBlock *tb_gen_code(CPUState *cpu, tb->tc.size = gen_code_size; #ifdef CONFIG_PROFILER - atomic_set(&prof->code_time, prof->code_time + profile_getclock() - ti); - atomic_set(&prof->code_in_len, prof->code_in_len + tb->size); - atomic_set(&prof->code_out_len, prof->code_out_len + gen_code_size); - atomic_set(&prof->search_out_len, prof->search_out_len + search_size); + qatomic_set(&prof->code_time, prof->code_time + profile_getclock() - ti); + qatomic_set(&prof->code_in_len, prof->code_in_len + tb->size); + qatomic_set(&prof->code_out_len, prof->code_out_len + gen_code_size); + qatomic_set(&prof->search_out_len, prof->search_out_len + search_size); #endif #ifdef DEBUG_DISAS @@ -1795,10 +1817,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu, qemu_log_in_addr_range(tb->pc)) { FILE *logfile = qemu_log_lock(); int code_size, data_size = 0; - g_autoptr(GString) note = g_string_new("[tb header & initial instruction]"); - size_t chunk_start = 0; + size_t chunk_start; int insn = 0; - qemu_log("OUT: [size=%d]\n", gen_code_size); + if (tcg_ctx->data_gen_ptr) { code_size = tcg_ctx->data_gen_ptr - tb->tc.ptr; data_size = gen_code_size - code_size; @@ -1807,26 +1828,33 @@ TranslationBlock *tb_gen_code(CPUState *cpu, } /* Dump header and the first instruction */ + qemu_log("OUT: [size=%d]\n", gen_code_size); + qemu_log(" -- guest addr 0x" TARGET_FMT_lx " + tb prologue\n", + tcg_ctx->gen_insn_data[insn][0]); chunk_start = tcg_ctx->gen_insn_end_off[insn]; - log_disas(tb->tc.ptr, chunk_start, note->str); + log_disas(tb->tc.ptr, chunk_start); /* * Dump each instruction chunk, wrapping up empty chunks into * the next instruction. The whole array is offset so the * first entry is the beginning of the 2nd instruction. */ - while (insn <= tb->icount && chunk_start < code_size) { + while (insn < tb->icount) { size_t chunk_end = tcg_ctx->gen_insn_end_off[insn]; if (chunk_end > chunk_start) { - g_string_printf(note, "[guest addr: " TARGET_FMT_lx "]", - tcg_ctx->gen_insn_data[insn][0]); - log_disas(tb->tc.ptr + chunk_start, chunk_end - chunk_start, - note->str); + qemu_log(" -- guest addr 0x" TARGET_FMT_lx "\n", + tcg_ctx->gen_insn_data[insn][0]); + log_disas(tb->tc.ptr + chunk_start, chunk_end - chunk_start); chunk_start = chunk_end; } insn++; } + if (chunk_start < code_size) { + qemu_log(" -- tb slow paths + alignment\n"); + log_disas(tb->tc.ptr + chunk_start, code_size - chunk_start); + } + /* Finally dump any data we may have after the block */ if (data_size) { int i; @@ -1849,7 +1877,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, } #endif - atomic_set(&tcg_ctx->code_gen_ptr, (void *) + qatomic_set(&tcg_ctx->code_gen_ptr, (void *) ROUND_UP((uintptr_t)gen_code_buf + gen_code_size + search_size, CODE_GEN_ALIGN)); @@ -1885,7 +1913,8 @@ TranslationBlock *tb_gen_code(CPUState *cpu, uintptr_t orig_aligned = (uintptr_t)gen_code_buf; orig_aligned -= ROUND_UP(sizeof(*tb), qemu_icache_linesize); - atomic_set(&tcg_ctx->code_gen_ptr, (void *)orig_aligned); + qatomic_set(&tcg_ctx->code_gen_ptr, (void *)orig_aligned); + tb_destroy(tb); return existing_tb; } tcg_tb_insert(tb); @@ -2235,8 +2264,13 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr) tb_phys_invalidate(tb->orig_tb, -1); } tcg_tb_remove(tb); + tb_destroy(tb); } + qemu_log_mask_and_addr(CPU_LOG_EXEC, tb->pc, + "cpu_io_recompile: rewound execution of TB to " + TARGET_FMT_lx "\n", tb->pc); + /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not * the first in the TB) then we end up generating a whole new TB and * repeating the fault, which is horribly inefficient. @@ -2251,7 +2285,7 @@ static void tb_jmp_cache_clear_page(CPUState *cpu, target_ulong page_addr) unsigned int i, i0 = tb_jmp_cache_hash_page(page_addr); for (i = 0; i < TB_JMP_PAGE_SIZE; i++) { - atomic_set(&cpu->tb_jmp_cache[i0 + i], NULL); + qatomic_set(&cpu->tb_jmp_cache[i0 + i], NULL); } } @@ -2371,7 +2405,7 @@ void dump_exec_info(void) qemu_printf("\nStatistics:\n"); qemu_printf("TB flush count %u\n", - atomic_read(&tb_ctx.tb_flush_count)); + qatomic_read(&tb_ctx.tb_flush_count)); qemu_printf("TB invalidate count %zu\n", tcg_tb_phys_invalidate_count()); @@ -2393,7 +2427,7 @@ void cpu_interrupt(CPUState *cpu, int mask) { g_assert(qemu_mutex_iothread_locked()); cpu->interrupt_request |= mask; - atomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1); + qatomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1); } /* @@ -2565,9 +2599,9 @@ int page_check_range(target_ulong start, target_ulong len, int flags) /* This function should never be called with addresses outside the guest address space. If this assert fires, it probably indicates a missing call to h2g_valid. */ -#if TARGET_ABI_BITS > L1_MAP_ADDR_SPACE_BITS - assert(start < ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS)); -#endif + if (TARGET_ABI_BITS > L1_MAP_ADDR_SPACE_BITS) { + assert(start < ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS)); + } if (len == 0) { return 0; diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 603d17ff831df0e4a9b8446666e91139605a8597..fb1e19c58585236788e3c7f15f8c0a409ace458f 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -17,6 +17,7 @@ #include "exec/log.h" #include "exec/translator.h" #include "exec/plugin-gen.h" +#include "sysemu/replay.h" /* Pairs with tcg_clear_temp_count. To be called by #TranslatorOps.{translate_insn,tb_stop} if diff --git a/accel/tcg/user-exec-stub.c b/accel/tcg/user-exec-stub.c index f6d8c8fb6f2daabb75f0a20f05aa3eb549d46c43..b876f5c1e45df8dbf216aba5a1b5be8ba6c318db 100644 --- a/accel/tcg/user-exec-stub.c +++ b/accel/tcg/user-exec-stub.c @@ -9,6 +9,10 @@ void cpu_resume(CPUState *cpu) { } +void cpu_remove_sync(CPUState *cpu) +{ +} + void qemu_init_vcpu(CPUState *cpu) { } diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c index 52359949df58b02391b63fc8a52e2533ffd709ba..4ebe25461af44bafb9aef0f6aaa2c498411fa014 100644 --- a/accel/tcg/user-exec.c +++ b/accel/tcg/user-exec.c @@ -26,7 +26,7 @@ #include "translate-all.h" #include "exec/helper-proto.h" #include "qemu/atomic128.h" -#include "trace-root.h" +#include "trace/trace-root.h" #include "trace/mem.h" #undef EAX @@ -88,7 +88,7 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info, * use that value directly. Within cpu_restore_state_from_tb, we * assume PC comes from GETPC(), as used by the helper functions, * so we adjust the address by -GETPC_ADJ to form an address that - * is within the call insn, so that the address does not accidentially + * is within the call insn, so that the address does not accidentally * match the beginning of the next guest insn. However, when the * pc comes from the signal frame it points to the actual faulting * host memory insn and not the return from a call insn. @@ -517,6 +517,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, #if defined(__NetBSD__) #include +#include #endif int cpu_signal_handler(int host_signum, void *pinfo, @@ -525,10 +526,12 @@ int cpu_signal_handler(int host_signum, void *pinfo, siginfo_t *info = pinfo; #if defined(__NetBSD__) ucontext_t *uc = puc; + siginfo_t *si = pinfo; #else ucontext_t *uc = puc; #endif unsigned long pc; + uint32_t fsr; int is_write; #if defined(__NetBSD__) @@ -539,15 +542,48 @@ int cpu_signal_handler(int host_signum, void *pinfo, pc = uc->uc_mcontext.arm_pc; #endif - /* error_code is the FSR value, in which bit 11 is WnR (assuming a v6 or - * later processor; on v5 we will always report this as a read). +#ifdef __NetBSD__ + fsr = si->si_trap; +#else + fsr = uc->uc_mcontext.error_code; +#endif + /* + * In the FSR, bit 11 is WnR, assuming a v6 or + * later processor. On v5 we will always report + * this as a read, which will fail later. */ - is_write = extract32(uc->uc_mcontext.error_code, 11, 1); + is_write = extract32(fsr, 11, 1); return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask); } #elif defined(__aarch64__) +#if defined(__NetBSD__) + +#include +#include + +int cpu_signal_handler(int host_signum, void *pinfo, void *puc) +{ + ucontext_t *uc = puc; + siginfo_t *si = pinfo; + unsigned long pc; + int is_write; + uint32_t esr; + + pc = uc->uc_mcontext.__gregs[_REG_PC]; + esr = si->si_trap; + + /* + * siginfo_t::si_trap is the ESR value, for data aborts ESR.EC + * is 0b10010x: then bit 6 is the WnR bit + */ + is_write = extract32(esr, 27, 5) == 0x12 && extract32(esr, 6, 1) == 1; + return handle_cpu_signal(pc, si, is_write, &uc->uc_sigmask); +} + +#else + #ifndef ESR_MAGIC /* Pre-3.16 kernel headers don't have these, so provide fallback definitions */ #define ESR_MAGIC 0x45535201 @@ -610,6 +646,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, void *puc) } return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask); } +#endif #elif defined(__s390__) @@ -665,16 +702,51 @@ int cpu_signal_handler(int host_signum, void *pinfo, #elif defined(__mips__) +#if defined(__misp16) || defined(__mips_micromips) +#error "Unsupported encoding" +#endif + int cpu_signal_handler(int host_signum, void *pinfo, void *puc) { siginfo_t *info = pinfo; ucontext_t *uc = puc; - greg_t pc = uc->uc_mcontext.pc; - int is_write; + uintptr_t pc = uc->uc_mcontext.pc; + uint32_t insn = *(uint32_t *)pc; + int is_write = 0; + + /* Detect all store instructions at program counter. */ + switch((insn >> 26) & 077) { + case 050: /* SB */ + case 051: /* SH */ + case 052: /* SWL */ + case 053: /* SW */ + case 054: /* SDL */ + case 055: /* SDR */ + case 056: /* SWR */ + case 070: /* SC */ + case 071: /* SWC1 */ + case 074: /* SCD */ + case 075: /* SDC1 */ + case 077: /* SD */ +#if !defined(__mips_isa_rev) || __mips_isa_rev < 6 + case 072: /* SWC2 */ + case 076: /* SDC2 */ +#endif + is_write = 1; + break; + case 023: /* COP1X */ + /* Required in all versions of MIPS64 since + MIPS64r1 and subsequent versions of MIPS32r2. */ + switch (insn & 077) { + case 010: /* SWXC1 */ + case 011: /* SDXC1 */ + case 015: /* SUXC1 */ + is_write = 1; + } + break; + } - /* XXX: compute is_write */ - is_write = 0; return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask); } @@ -1152,7 +1224,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr, #define ATOMIC_NAME(X) HELPER(glue(glue(atomic_ ## X, SUFFIX), END)) #define EXTRA_ARGS -#include "atomic_common.inc.c" +#include "atomic_common.c.inc" #define DATA_SIZE 1 #include "atomic_template.h" diff --git a/accel/xen/meson.build b/accel/xen/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..002bdb03c62930e7f9915464d59e2d3a9fa67766 --- /dev/null +++ b/accel/xen/meson.build @@ -0,0 +1 @@ +specific_ss.add(when: 'CONFIG_XEN', if_true: files('xen-all.c')) diff --git a/hw/xen/xen-common.c b/accel/xen/xen-all.c similarity index 95% rename from hw/xen/xen-common.c rename to accel/xen/xen-all.c index 70564cc952d57234c8cf51044ec8472fdf66ca08..878a4089d97abec31349de7a7e895c99999ecdda 100644 --- a/hw/xen/xen-common.c +++ b/accel/xen/xen-all.c @@ -16,6 +16,8 @@ #include "hw/xen/xen_pt.h" #include "chardev/char.h" #include "sysemu/accel.h" +#include "sysemu/cpus.h" +#include "sysemu/xen.h" #include "sysemu/runstate.h" #include "migration/misc.h" #include "migration/global_state.h" @@ -31,6 +33,8 @@ do { } while (0) #endif +bool xen_allowed; + xc_interface *xen_xc; xenforeignmemory_handle *xen_fmem; xendevicemodel_handle *xen_dmod; @@ -129,12 +133,12 @@ static void xen_change_state_handler(void *opaque, int running, static bool xen_get_igd_gfx_passthru(Object *obj, Error **errp) { - return has_igd_gfx_passthru; + return xen_igd_gfx_pt_enabled(); } static void xen_set_igd_gfx_passthru(Object *obj, bool value, Error **errp) { - has_igd_gfx_passthru = value; + xen_igd_gfx_pt_set(value, errp); } static void xen_setup_post(MachineState *ms, AccelState *accel) @@ -150,6 +154,10 @@ static void xen_setup_post(MachineState *ms, AccelState *accel) } } +const CpusAccel xen_cpus = { + .create_vcpu_thread = dummy_start_vcpu_thread, +}; + static int xen_init(MachineState *ms) { MachineClass *mc = MACHINE_GET_CLASS(ms); @@ -177,6 +185,9 @@ static int xen_init(MachineState *ms) * opt out of system RAM being allocated by generic code */ mc->default_ram_id = NULL; + + cpus_register_accel(&xen_cpus); + return 0; } diff --git a/audio/Makefile.objs b/audio/Makefile.objs deleted file mode 100644 index b4a4c11f312207c03857fc994ea512cdf136cba2..0000000000000000000000000000000000000000 --- a/audio/Makefile.objs +++ /dev/null @@ -1,35 +0,0 @@ -common-obj-y = audio.o audio_legacy.o noaudio.o wavaudio.o mixeng.o -common-obj-$(CONFIG_SPICE) += spiceaudio.o -common-obj-$(CONFIG_AUDIO_COREAUDIO) += coreaudio.o -common-obj-$(CONFIG_AUDIO_DSOUND) += dsoundaudio.o -common-obj-$(CONFIG_AUDIO_WIN_INT) += audio_win_int.o -common-obj-y += wavcapture.o - -coreaudio.o-libs := $(COREAUDIO_LIBS) -dsoundaudio.o-libs := $(DSOUND_LIBS) - -# alsa module -common-obj-$(CONFIG_AUDIO_ALSA) += alsa.mo -alsa.mo-objs = alsaaudio.o -alsa.mo-libs := $(ALSA_LIBS) - -# oss module -common-obj-$(CONFIG_AUDIO_OSS) += oss.mo -oss.mo-objs = ossaudio.o -oss.mo-libs := $(OSS_LIBS) - -# pulseaudio module -common-obj-$(CONFIG_AUDIO_PA) += pa.mo -pa.mo-objs = paaudio.o -pa.mo-libs := $(PULSE_LIBS) - -# sdl module -common-obj-$(CONFIG_AUDIO_SDL) += sdl.mo -sdl.mo-objs = sdlaudio.o -sdl.mo-cflags := $(SDL_CFLAGS) -sdl.mo-libs := $(SDL_LIBS) - -# jack module -common-obj-$(CONFIG_AUDIO_JACK) += jack.mo -jack.mo-objs = jackaudio.o -jack.mo-libs := $(JACK_LIBS) diff --git a/audio/audio.c b/audio/audio.c index ce8c6dec5f47d4fd18967216212c1c546544cbc9..46578e4a583b9ad5c5fd4d40c7114697113a2323 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -34,6 +34,7 @@ #include "qemu/module.h" #include "sysemu/replay.h" #include "sysemu/runstate.h" +#include "ui/qemu-spice.h" #include "trace.h" #define AUDIO_CAP "audio" @@ -1089,14 +1090,18 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) size_t clipped = 0; while (live) { - size_t size, decr, proc; + size_t size = live * hw->info.bytes_per_frame; + size_t decr, proc; void *buf = hw->pcm_ops->get_buffer_out(hw, &size); - if (!buf || size == 0) { + + if (size == 0) { break; } decr = MIN(size / hw->info.bytes_per_frame, live); - audio_pcm_hw_clip_out(hw, buf, decr); + if (buf) { + audio_pcm_hw_clip_out(hw, buf, decr); + } proc = hw->pcm_ops->put_buffer_out(hw, buf, decr * hw->info.bytes_per_frame) / hw->info.bytes_per_frame; @@ -1182,6 +1187,9 @@ static void audio_run_out (AudioState *s) } } } + if (hw->pcm_ops->run_buffer_out) { + hw->pcm_ops->run_buffer_out(hw); + } continue; } @@ -1257,7 +1265,6 @@ static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples) assert(size % hw->info.bytes_per_frame == 0); if (size == 0) { - hw->pcm_ops->put_buffer_in(hw, buf, size); break; } @@ -1481,22 +1488,54 @@ size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size) size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size) { - size_t dst_size, copy_size; - void *dst = hw->pcm_ops->get_buffer_out(hw, &dst_size); - copy_size = MIN(size, dst_size); + size_t total = 0; + + while (total < size) { + size_t dst_size = size - total; + size_t copy_size, proc; + void *dst = hw->pcm_ops->get_buffer_out(hw, &dst_size); + + if (dst_size == 0) { + break; + } + + copy_size = MIN(size - total, dst_size); + if (dst) { + memcpy(dst, (char *)buf + total, copy_size); + } + proc = hw->pcm_ops->put_buffer_out(hw, dst, copy_size); + total += proc; + + if (proc == 0 || proc < copy_size) { + break; + } + } - memcpy(dst, buf, copy_size); - return hw->pcm_ops->put_buffer_out(hw, dst, copy_size); + if (hw->pcm_ops->run_buffer_out) { + hw->pcm_ops->run_buffer_out(hw); + } + + return total; } size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size) { - void *src = hw->pcm_ops->get_buffer_in(hw, &size); + size_t total = 0; - memcpy(buf, src, size); - hw->pcm_ops->put_buffer_in(hw, src, size); + while (total < size) { + size_t src_size = size - total; + void *src = hw->pcm_ops->get_buffer_in(hw, &src_size); - return size; + if (src_size == 0) { + break; + } + + memcpy((char *)buf + total, src, src_size); + hw->pcm_ops->put_buffer_in(hw, src, src_size); + total += src_size; + } + + return total; } static int audio_driver_init(AudioState *s, struct audio_driver *drv, @@ -1658,6 +1697,21 @@ static AudioState *audio_init(Audiodev *dev, const char *name) /* silence gcc warning about uninitialized variable */ AudiodevListHead head = QSIMPLEQ_HEAD_INITIALIZER(head); + if (using_spice) { + /* + * When using spice allow the spice audio driver being picked + * as default. + * + * Temporary hack. Using audio devices without explicit + * audiodev= property is already deprecated. Same goes for + * the -soundhw switch. Once this support gets finally + * removed we can also drop the concept of a default audio + * backend and this can go away. + */ + driver = audio_driver_lookup("spice"); + driver->can_be_default = 1; + } + if (dev) { /* -audiodev option */ legacy_config = false; @@ -1674,7 +1728,7 @@ static AudioState *audio_init(Audiodev *dev, const char *name) head = audio_handle_legacy_opts(); /* * In case of legacy initialization, all Audiodevs in the list will have - * the same configuration (except the driver), so it does't matter which + * the same configuration (except the driver), so it doesn't matter which * one we chose. We need an Audiodev to set up AudioState before we can * init a driver. Also note that dev at this point is still in the * list. diff --git a/audio/audio_legacy.c b/audio/audio_legacy.c index ebd7d9fa0dfc6bd7129de8fe1e49300c6763ac68..ffdbd0bcce8c7e568051fa59e3b0c1c8e757d91e 100644 --- a/audio/audio_legacy.c +++ b/audio/audio_legacy.c @@ -421,11 +421,12 @@ typedef struct { GList *path; } LegacyPrintVisitor; -static void lv_start_struct(Visitor *v, const char *name, void **obj, +static bool lv_start_struct(Visitor *v, const char *name, void **obj, size_t size, Error **errp) { LegacyPrintVisitor *lv = (LegacyPrintVisitor *) v; lv->path = g_list_append(lv->path, g_strdup(name)); + return true; } static void lv_end_struct(Visitor *v, void **obj) @@ -453,27 +454,30 @@ static void lv_print_key(Visitor *v, const char *name) printf("%s=", name); } -static void lv_type_int64(Visitor *v, const char *name, int64_t *obj, +static bool lv_type_int64(Visitor *v, const char *name, int64_t *obj, Error **errp) { lv_print_key(v, name); printf("%" PRIi64, *obj); + return true; } -static void lv_type_uint64(Visitor *v, const char *name, uint64_t *obj, +static bool lv_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp) { lv_print_key(v, name); printf("%" PRIu64, *obj); + return true; } -static void lv_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) +static bool lv_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) { lv_print_key(v, name); printf("%s", *obj ? "on" : "off"); + return true; } -static void lv_type_str(Visitor *v, const char *name, char **obj, Error **errp) +static bool lv_type_str(Visitor *v, const char *name, char **obj, Error **errp) { const char *str = *obj; lv_print_key(v, name); @@ -484,6 +488,7 @@ static void lv_type_str(Visitor *v, const char *name, char **obj, Error **errp) } putchar(*str++); } + return true; } static void lv_complete(Visitor *v, void *opaque) diff --git a/audio/jackaudio.c b/audio/jackaudio.c index 722ddb1dfe43335eb9897e57c9166412257fde19..3b7c18443dbee0c405b48556e7abf51372c012ee 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "qemu/module.h" #include "qemu/atomic.h" +#include "qemu/main-loop.h" #include "qemu-common.h" #include "audio.h" @@ -38,7 +39,6 @@ struct QJack; typedef enum QJackState { QJACK_STATE_DISCONNECTED, - QJACK_STATE_STOPPED, QJACK_STATE_RUNNING, QJACK_STATE_SHUTDOWN } @@ -57,13 +57,14 @@ typedef struct QJackClient { AudiodevJackPerDirectionOptions *opt; bool out; - bool finished; + bool enabled; bool connect_ports; int packets; QJackState state; jack_client_t *client; jack_nframes_t freq; + QEMUBH *shutdown_bh; struct QJack *j; int nchannels; @@ -88,6 +89,7 @@ QJackIn; static int qjack_client_init(QJackClient *c); static void qjack_client_connect_ports(QJackClient *c); static void qjack_client_fini(QJackClient *c); +static QemuMutex qjack_shutdown_lock; static void qjack_buffer_create(QJackBuffer *buffer, int channels, int frames) { @@ -105,7 +107,7 @@ static void qjack_buffer_create(QJackBuffer *buffer, int channels, int frames) static void qjack_buffer_clear(QJackBuffer *buffer) { assert(buffer->data); - atomic_store_release(&buffer->used, 0); + qatomic_store_release(&buffer->used, 0); buffer->rptr = 0; buffer->wptr = 0; } @@ -130,7 +132,7 @@ static int qjack_buffer_write(QJackBuffer *buffer, float *data, int size) assert(buffer->data); const int samples = size / sizeof(float); int frames = samples / buffer->channels; - const int avail = buffer->frames - atomic_load_acquire(&buffer->used); + const int avail = buffer->frames - qatomic_load_acquire(&buffer->used); if (frames > avail) { frames = avail; @@ -154,7 +156,7 @@ static int qjack_buffer_write(QJackBuffer *buffer, float *data, int size) buffer->wptr = wptr; - atomic_add(&buffer->used, frames); + qatomic_add(&buffer->used, frames); return frames * buffer->channels * sizeof(float); }; @@ -162,7 +164,7 @@ static int qjack_buffer_write(QJackBuffer *buffer, float *data, int size) static int qjack_buffer_write_l(QJackBuffer *buffer, float **dest, int frames) { assert(buffer->data); - const int avail = buffer->frames - atomic_load_acquire(&buffer->used); + const int avail = buffer->frames - qatomic_load_acquire(&buffer->used); int wptr = buffer->wptr; if (frames > avail) { @@ -186,7 +188,7 @@ static int qjack_buffer_write_l(QJackBuffer *buffer, float **dest, int frames) } buffer->wptr = wptr; - atomic_add(&buffer->used, frames); + qatomic_add(&buffer->used, frames); return frames; } @@ -196,7 +198,7 @@ static int qjack_buffer_read(QJackBuffer *buffer, float *dest, int size) assert(buffer->data); const int samples = size / sizeof(float); int frames = samples / buffer->channels; - const int avail = atomic_load_acquire(&buffer->used); + const int avail = qatomic_load_acquire(&buffer->used); if (frames > avail) { frames = avail; @@ -220,7 +222,7 @@ static int qjack_buffer_read(QJackBuffer *buffer, float *dest, int size) buffer->rptr = rptr; - atomic_sub(&buffer->used, frames); + qatomic_sub(&buffer->used, frames); return frames * buffer->channels * sizeof(float); } @@ -229,7 +231,7 @@ static int qjack_buffer_read_l(QJackBuffer *buffer, float **dest, int frames) { assert(buffer->data); int copy = frames; - const int used = atomic_load_acquire(&buffer->used); + const int used = qatomic_load_acquire(&buffer->used); int rptr = buffer->rptr; if (copy > used) { @@ -253,7 +255,7 @@ static int qjack_buffer_read_l(QJackBuffer *buffer, float **dest, int frames) } buffer->rptr = rptr; - atomic_sub(&buffer->used, copy); + qatomic_sub(&buffer->used, copy); return copy; } @@ -272,9 +274,17 @@ static int qjack_process(jack_nframes_t nframes, void *arg) } if (c->out) { - qjack_buffer_read_l(&c->fifo, buffers, nframes); + if (likely(c->enabled)) { + qjack_buffer_read_l(&c->fifo, buffers, nframes); + } else { + for(int i = 0; i < c->nchannels; ++i) { + memset(buffers[i], 0, nframes * sizeof(float)); + } + } } else { - qjack_buffer_write_l(&c->fifo, buffers, nframes); + if (likely(c->enabled)) { + qjack_buffer_write_l(&c->fifo, buffers, nframes); + } } return 0; @@ -299,24 +309,30 @@ static int qjack_xrun(void *arg) return 0; } +static void qjack_shutdown_bh(void *opaque) +{ + QJackClient *c = (QJackClient *)opaque; + qjack_client_fini(c); +} + static void qjack_shutdown(void *arg) { QJackClient *c = (QJackClient *)arg; c->state = QJACK_STATE_SHUTDOWN; + qemu_bh_schedule(c->shutdown_bh); } static void qjack_client_recover(QJackClient *c) { - if (c->state == QJACK_STATE_SHUTDOWN) { - qjack_client_fini(c); + if (c->state != QJACK_STATE_DISCONNECTED) { + return; } /* packets is used simply to throttle this */ - if (c->state == QJACK_STATE_DISCONNECTED && - c->packets % 100 == 0) { + if (c->packets % 100 == 0) { - /* if not finished then attempt to recover */ - if (!c->finished) { + /* if enabled then attempt to recover */ + if (c->enabled) { dolog("attempting to reconnect to server\n"); qjack_client_init(c); } @@ -388,7 +404,10 @@ static int qjack_client_init(QJackClient *c) char client_name[jack_client_name_size()]; jack_options_t options = JackNullOption; - c->finished = false; + if (c->state == QJACK_STATE_RUNNING) { + return 0; + } + c->connect_ports = true; snprintf(client_name, sizeof(client_name), "%s-%s", @@ -434,17 +453,6 @@ static int qjack_client_init(QJackClient *c) jack_set_xrun_callback(c->client, qjack_xrun, c); jack_on_shutdown(c->client, qjack_shutdown, c); - /* - * ensure the buffersize is no smaller then 512 samples, some (all?) qemu - * virtual devices do not work correctly otherwise - */ - if (c->buffersize < 512) { - c->buffersize = 512; - } - - /* create a 2 period buffer */ - qjack_buffer_create(&c->fifo, c->nchannels, c->buffersize * 2); - /* allocate and register the ports */ c->port = g_malloc(sizeof(jack_port_t *) * c->nchannels); for (int i = 0; i < c->nchannels; ++i) { @@ -468,6 +476,17 @@ static int qjack_client_init(QJackClient *c) jack_activate(c->client); c->buffersize = jack_get_buffer_size(c->client); + /* + * ensure the buffersize is no smaller then 512 samples, some (all?) qemu + * virtual devices do not work correctly otherwise + */ + if (c->buffersize < 512) { + c->buffersize = 512; + } + + /* create a 2 period buffer */ + qjack_buffer_create(&c->fifo, c->nchannels, c->buffersize * 2); + qjack_client_connect_ports(c); c->state = QJACK_STATE_RUNNING; return 0; @@ -479,15 +498,16 @@ static int qjack_init_out(HWVoiceOut *hw, struct audsettings *as, QJackOut *jo = (QJackOut *)hw; Audiodev *dev = (Audiodev *)drv_opaque; - if (jo->c.state != QJACK_STATE_DISCONNECTED) { - return 0; - } - jo->c.out = true; + jo->c.enabled = false; jo->c.nchannels = as->nchannels; jo->c.opt = dev->u.jack.out; + + jo->c.shutdown_bh = qemu_bh_new(qjack_shutdown_bh, &jo->c); + int ret = qjack_client_init(&jo->c); if (ret != 0) { + qemu_bh_delete(jo->c.shutdown_bh); return ret; } @@ -515,15 +535,16 @@ static int qjack_init_in(HWVoiceIn *hw, struct audsettings *as, QJackIn *ji = (QJackIn *)hw; Audiodev *dev = (Audiodev *)drv_opaque; - if (ji->c.state != QJACK_STATE_DISCONNECTED) { - return 0; - } - ji->c.out = false; + ji->c.enabled = false; ji->c.nchannels = as->nchannels; ji->c.opt = dev->u.jack.in; + + ji->c.shutdown_bh = qemu_bh_new(qjack_shutdown_bh, &ji->c); + int ret = qjack_client_init(&ji->c); if (ret != 0) { + qemu_bh_delete(ji->c.shutdown_bh); return ret; } @@ -545,53 +566,61 @@ static int qjack_init_in(HWVoiceIn *hw, struct audsettings *as, return 0; } -static void qjack_client_fini(QJackClient *c) +static void qjack_client_fini_locked(QJackClient *c) { switch (c->state) { case QJACK_STATE_RUNNING: - /* fallthrough */ - - case QJACK_STATE_STOPPED: - for (int i = 0; i < c->nchannels; ++i) { - jack_port_unregister(c->client, c->port[i]); - } jack_deactivate(c->client); /* fallthrough */ case QJACK_STATE_SHUTDOWN: jack_client_close(c->client); + c->client = NULL; + + qjack_buffer_free(&c->fifo); + g_free(c->port); + + c->state = QJACK_STATE_DISCONNECTED; /* fallthrough */ case QJACK_STATE_DISCONNECTED: break; } +} - qjack_buffer_free(&c->fifo); - g_free(c->port); - - c->state = QJACK_STATE_DISCONNECTED; +static void qjack_client_fini(QJackClient *c) +{ + qemu_mutex_lock(&qjack_shutdown_lock); + qjack_client_fini_locked(c); + qemu_mutex_unlock(&qjack_shutdown_lock); } static void qjack_fini_out(HWVoiceOut *hw) { QJackOut *jo = (QJackOut *)hw; - jo->c.finished = true; qjack_client_fini(&jo->c); + + qemu_bh_delete(jo->c.shutdown_bh); } static void qjack_fini_in(HWVoiceIn *hw) { QJackIn *ji = (QJackIn *)hw; - ji->c.finished = true; qjack_client_fini(&ji->c); + + qemu_bh_delete(ji->c.shutdown_bh); } static void qjack_enable_out(HWVoiceOut *hw, bool enable) { + QJackOut *jo = (QJackOut *)hw; + jo->c.enabled = enable; } static void qjack_enable_in(HWVoiceIn *hw, bool enable) { + QJackIn *ji = (QJackIn *)hw; + ji->c.enabled = enable; } static int qjack_thread_creator(jack_native_thread_t *thread, @@ -611,9 +640,6 @@ static int qjack_thread_creator(jack_native_thread_t *thread, static void *qjack_init(Audiodev *dev) { assert(dev->driver == AUDIODEV_DRIVER_JACK); - - dev->u.jack.has_in = false; - return dev; } @@ -659,6 +685,7 @@ static void qjack_info(const char *msg) static void register_audio_jack(void) { + qemu_mutex_init(&qjack_shutdown_lock); audio_driver_register(&jack_driver); jack_set_thread_creator(qjack_thread_creator); jack_set_error_function(qjack_error); diff --git a/audio/meson.build b/audio/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..7d53b0f920ff0a89072bfaa0115d05fb33eae1d3 --- /dev/null +++ b/audio/meson.build @@ -0,0 +1,30 @@ +softmmu_ss.add([spice_headers, files('audio.c')]) +softmmu_ss.add(files( + 'audio_legacy.c', + 'mixeng.c', + 'noaudio.c', + 'wavaudio.c', + 'wavcapture.c', +)) + +softmmu_ss.add(when: [coreaudio, 'CONFIG_AUDIO_COREAUDIO'], if_true: files('coreaudio.c')) +softmmu_ss.add(when: [dsound, 'CONFIG_AUDIO_DSOUND'], if_true: files('dsoundaudio.c')) +softmmu_ss.add(when: ['CONFIG_AUDIO_WIN_INT'], if_true: files('audio_win_int.c')) + +audio_modules = {} +foreach m : [ + ['CONFIG_AUDIO_ALSA', 'alsa', alsa, 'alsaaudio.c'], + ['CONFIG_AUDIO_OSS', 'oss', oss, 'ossaudio.c'], + ['CONFIG_AUDIO_PA', 'pa', pulse, 'paaudio.c'], + ['CONFIG_AUDIO_SDL', 'sdl', sdl, 'sdlaudio.c'], + ['CONFIG_AUDIO_JACK', 'jack', jack, 'jackaudio.c'], + ['CONFIG_SPICE', 'spice', spice, 'spiceaudio.c'] +] + if config_host.has_key(m[0]) + module_ss = ss.source_set() + module_ss.add(when: m[2], if_true: files(m[3])) + audio_modules += {m[1] : module_ss} + endif +endforeach + +modules += {'audio': audio_modules} diff --git a/audio/ossaudio.c b/audio/ossaudio.c index f88d076ec236a8de9507f36c3ab151d60d34cf0e..a7dcaa31adebf23a31864a70955b232ae175e486 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -691,6 +691,7 @@ static size_t oss_read(HWVoiceIn *hw, void *buf, size_t len) len, dst); break; } + break; } pos += nread; diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index b6b5da4812f28f9ba52da1b0d23a16c9d2c02f80..8967cca1292558b69b93466ffb3b30ff187d7886 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -106,7 +106,7 @@ static int line_out_init(HWVoiceOut *hw, struct audsettings *as, out->active = 0; out->sin.base.sif = &playback_sif.base; - qemu_spice_add_interface (&out->sin.base); + qemu_spice.add_interface(&out->sin.base); #if SPICE_INTERFACE_PLAYBACK_MAJOR > 1 || SPICE_INTERFACE_PLAYBACK_MINOR >= 3 spice_server_set_playback_rate(&out->sin, settings.freq); #endif @@ -130,12 +130,11 @@ static void *line_out_get_buffer(HWVoiceOut *hw, size_t *size) } if (out->frame) { - *size = audio_rate_get_bytes( - &hw->info, &out->rate, - (out->fsize - out->fpos) * hw->info.bytes_per_frame); - } else { - audio_rate_start(&out->rate); + *size = MIN((out->fsize - out->fpos) << 2, *size); } + + *size = audio_rate_get_bytes(&hw->info, &out->rate, *size); + return out->frame + out->fpos; } @@ -143,12 +142,14 @@ static size_t line_out_put_buffer(HWVoiceOut *hw, void *buf, size_t size) { SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw); - assert(buf == out->frame + out->fpos && out->fpos <= out->fsize); - out->fpos += size >> 2; + if (buf) { + assert(buf == out->frame + out->fpos && out->fpos <= out->fsize); + out->fpos += size >> 2; - if (out->fpos == out->fsize) { /* buffer full */ - spice_server_playback_put_samples(&out->sin, out->frame); - out->frame = NULL; + if (out->fpos == out->fsize) { /* buffer full */ + spice_server_playback_put_samples(&out->sin, out->frame); + out->frame = NULL; + } } return size; @@ -214,7 +215,7 @@ static int line_in_init(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) in->active = 0; in->sin.base.sif = &record_sif.base; - qemu_spice_add_interface (&in->sin.base); + qemu_spice.add_interface(&in->sin.base); #if SPICE_INTERFACE_RECORD_MAJOR > 2 || SPICE_INTERFACE_RECORD_MINOR >= 3 spice_server_set_record_rate(&in->sin, settings.freq); #endif @@ -310,11 +311,6 @@ static struct audio_driver spice_audio_driver = { .voice_size_in = sizeof (SpiceVoiceIn), }; -void qemu_spice_audio_init (void) -{ - spice_audio_driver.can_be_default = 1; -} - static void register_audio_spice(void) { audio_driver_register(&spice_audio_driver); diff --git a/audio/trace-events b/audio/trace-events index a1d1eccb8a3713cf78ac5f5ac1aee77e59f5a2a7..6aec53576388173b177c37485377374070157f7a 100644 --- a/audio/trace-events +++ b/audio/trace-events @@ -9,12 +9,9 @@ alsa_read_zero(long len) "Failed to read %ld frames (read zero)" alsa_xrun_out(void) "Recovering from playback xrun" alsa_xrun_in(void) "Recovering from capture xrun" alsa_resume_out(void) "Resuming suspended output stream" -alsa_resume_in(void) "Resuming suspended input stream" -alsa_no_frames(int state) "No frames available and ALSA state is %d" # ossaudio.c oss_version(int version) "OSS version = 0x%x" -oss_invalid_available_size(int size, int bufsize) "Invalid available size, size=%d bufsize=%d" # audio.c audio_timer_start(int interval) "interval %d ms" diff --git a/audio/trace.h b/audio/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..4072a11b0f955dc88f8eae8b4eb2139fb1d0a5ca --- /dev/null +++ b/audio/trace.h @@ -0,0 +1 @@ +#include "trace/trace-audio.h" diff --git a/audio/wavcapture.c b/audio/wavcapture.c index 17e87ed6f45eecbf817faed4692434ad2a88c637..c60286e1628bc25ae7d1d329d455bb6e06e78e02 100644 --- a/audio/wavcapture.c +++ b/audio/wavcapture.c @@ -1,5 +1,5 @@ #include "qemu/osdep.h" -#include "monitor/monitor.h" +#include "qemu/qemu-print.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "audio.h" @@ -94,9 +94,9 @@ static void wav_capture_info (void *opaque) WAVState *wav = opaque; char *path = wav->path; - monitor_printf (cur_mon, "Capturing audio(%d,%d,%d) to %s: %d bytes\n", - wav->freq, wav->bits, wav->nchannels, - path ? path : "", wav->bytes); + qemu_printf("Capturing audio(%d,%d,%d) to %s: %d bytes\n", + wav->freq, wav->bits, wav->nchannels, + path ? path : "", wav->bytes); } static struct capture_ops wav_capture_ops = { diff --git a/authz/Makefile.objs b/authz/Makefile.objs deleted file mode 100644 index ed7b273596cd4443010ce0f8b54f6e25c4985b87..0000000000000000000000000000000000000000 --- a/authz/Makefile.objs +++ /dev/null @@ -1,7 +0,0 @@ -authz-obj-y += base.o -authz-obj-y += simple.o -authz-obj-y += list.o -authz-obj-y += listfile.o -authz-obj-$(CONFIG_AUTH_PAM) += pamacct.o - -pamacct.o-libs = -lpam diff --git a/authz/base.c b/authz/base.c index c75bce3fd134ef2d88033e2c588fd014f5b7cec6..f2b7fbe9c13aa25d81a83c5ae8b500d3b7a2856d 100644 --- a/authz/base.c +++ b/authz/base.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/authz/list.c b/authz/list.c index 8e904bfc9304f8900e1135111800ee113c4e1d43..0e17eed8974ec94c3ef8cfab81b0ebac1c96626c 100644 --- a/authz/list.c +++ b/authz/list.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -252,7 +252,6 @@ static const TypeInfo qauthz_list_info = { .name = TYPE_QAUTHZ_LIST, .instance_size = sizeof(QAuthZList), .instance_finalize = qauthz_list_finalize, - .class_size = sizeof(QAuthZListClass), .class_init = qauthz_list_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_USER_CREATABLE }, diff --git a/authz/listfile.c b/authz/listfile.c index 666df872ad276d88f78a70e6c2625bf0669fa514..da3a0e69a2ed472c053a2b64113405f371e1b2e1 100644 --- a/authz/listfile.c +++ b/authz/listfile.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -73,7 +73,8 @@ qauthz_list_file_load(QAuthZListFile *fauthz, Error **errp) pdict = qobject_to(QDict, obj); if (!pdict) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "obj", "dict"); + error_setg(errp, "File '%s' must contain a JSON object", + fauthz->filename); goto cleanup; } @@ -122,7 +123,15 @@ qauthz_list_file_complete(UserCreatable *uc, Error **errp) QAuthZListFile *fauthz = QAUTHZ_LIST_FILE(uc); gchar *dir = NULL, *file = NULL; + if (!fauthz->filename) { + error_setg(errp, "filename not provided"); + return; + } + fauthz->list = qauthz_list_file_load(fauthz, errp); + if (!fauthz->list) { + return; + } if (!fauthz->refresh) { return; @@ -263,7 +272,6 @@ static const TypeInfo qauthz_list_file_info = { .instance_init = qauthz_list_file_init, .instance_size = sizeof(QAuthZListFile), .instance_finalize = qauthz_list_file_finalize, - .class_size = sizeof(QAuthZListFileClass), .class_init = qauthz_list_file_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_USER_CREATABLE }, diff --git a/authz/meson.build b/authz/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..88fa7769cb1b2ff0d4a5c2f383817979deef910a --- /dev/null +++ b/authz/meson.build @@ -0,0 +1,9 @@ +authz_ss.add(genh) +authz_ss.add(files( + 'base.c', + 'list.c', + 'listfile.c', + 'simple.c', +)) + +authz_ss.add(when: ['CONFIG_AUTH_PAM', pam], if_true: files('pamacct.c')) diff --git a/authz/pamacct.c b/authz/pamacct.c index 3c6be43916deb474a006a49628cf426b41b3601d..c862d9ff39b2d7f3dd747835b26a61fe9abe3472 100644 --- a/authz/pamacct.c +++ b/authz/pamacct.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -84,6 +84,12 @@ qauthz_pam_prop_get_service(Object *obj, static void qauthz_pam_complete(UserCreatable *uc, Error **errp) { + QAuthZPAM *pauthz = QAUTHZ_PAM(uc); + + if (!pauthz->service) { + error_setg(errp, "The 'service' property must be set"); + return; + } } @@ -129,7 +135,6 @@ static const TypeInfo qauthz_pam_info = { .name = TYPE_QAUTHZ_PAM, .instance_size = sizeof(QAuthZPAM), .instance_finalize = qauthz_pam_finalize, - .class_size = sizeof(QAuthZPAMClass), .class_init = qauthz_pam_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_USER_CREATABLE }, diff --git a/authz/simple.c b/authz/simple.c index 84954b80a577fab423b94adc1c382de299a50618..0597dcd8ea5a3a2ad3611a37df11177a24d9d490 100644 --- a/authz/simple.c +++ b/authz/simple.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -65,11 +65,25 @@ qauthz_simple_finalize(Object *obj) } +static void +qauthz_simple_complete(UserCreatable *uc, Error **errp) +{ + QAuthZSimple *sauthz = QAUTHZ_SIMPLE(uc); + + if (!sauthz->identity) { + error_setg(errp, "The 'identity' property must be set"); + return; + } +} + + static void qauthz_simple_class_init(ObjectClass *oc, void *data) { QAuthZClass *authz = QAUTHZ_CLASS(oc); + UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); + ucc->complete = qauthz_simple_complete; authz->is_allowed = qauthz_simple_is_allowed; object_class_property_add_str(oc, "identity", @@ -96,7 +110,6 @@ static const TypeInfo qauthz_simple_info = { .name = TYPE_QAUTHZ_SIMPLE, .instance_size = sizeof(QAuthZSimple), .instance_finalize = qauthz_simple_finalize, - .class_size = sizeof(QAuthZSimpleClass), .class_init = qauthz_simple_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_USER_CREATABLE }, diff --git a/authz/trace.h b/authz/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..3176c127f7ab84db0c5382019b8f5fdbd6316a06 --- /dev/null +++ b/authz/trace.h @@ -0,0 +1 @@ +#include "trace/trace-authz.h" diff --git a/backends/Kconfig b/backends/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..f35abc16092808b1fe5b033a346908e2d66bff0b --- /dev/null +++ b/backends/Kconfig @@ -0,0 +1 @@ +source tpm/Kconfig diff --git a/backends/Makefile.objs b/backends/Makefile.objs deleted file mode 100644 index 28a847cd571d96edf61c32ddd9d19dad2f3213b6..0000000000000000000000000000000000000000 --- a/backends/Makefile.objs +++ /dev/null @@ -1,23 +0,0 @@ -common-obj-y += rng.o rng-egd.o rng-builtin.o -common-obj-$(CONFIG_POSIX) += rng-random.o - -common-obj-$(CONFIG_TPM) += tpm.o - -common-obj-y += hostmem.o hostmem-ram.o -common-obj-$(CONFIG_POSIX) += hostmem-file.o - -common-obj-y += cryptodev.o -common-obj-y += cryptodev-builtin.o - -ifeq ($(CONFIG_VIRTIO_CRYPTO),y) -common-obj-y += cryptodev-vhost.o -common-obj-$(CONFIG_VHOST_CRYPTO) += cryptodev-vhost-user.o -endif - -common-obj-$(call land,$(CONFIG_VHOST_USER),$(CONFIG_VIRTIO)) += vhost-user.o - -common-obj-$(CONFIG_LINUX) += hostmem-memfd.o - -common-obj-$(CONFIG_GIO) += dbus-vmstate.o -dbus-vmstate.o-cflags = $(GIO_CFLAGS) -dbus-vmstate.o-libs = $(GIO_LIBS) diff --git a/backends/cryptodev-builtin.c b/backends/cryptodev-builtin.c index 14316333fedb6f32eb38d60980ba1833aa38722b..0671bf9f3e5ee0b51465badce95c8e49b35b9d62 100644 --- a/backends/cryptodev-builtin.c +++ b/backends/cryptodev-builtin.c @@ -9,7 +9,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -26,6 +26,7 @@ #include "qapi/error.h" #include "standard-headers/linux/virtio_crypto.h" #include "crypto/cipher.h" +#include "qom/object.h" /** @@ -34,12 +35,8 @@ */ #define TYPE_CRYPTODEV_BACKEND_BUILTIN "cryptodev-backend-builtin" -#define CRYPTODEV_BACKEND_BUILTIN(obj) \ - OBJECT_CHECK(CryptoDevBackendBuiltin, \ - (obj), TYPE_CRYPTODEV_BACKEND_BUILTIN) +OBJECT_DECLARE_SIMPLE_TYPE(CryptoDevBackendBuiltin, CRYPTODEV_BACKEND_BUILTIN) -typedef struct CryptoDevBackendBuiltin - CryptoDevBackendBuiltin; typedef struct CryptoDevBackendBuiltinSession { QCryptoCipher *cipher; diff --git a/backends/cryptodev-vhost-user.c b/backends/cryptodev-vhost-user.c index 8b8cbc4223dd07d6eae244bf8a16f602e61a7d3f..bedb4524742e95968809998a3a62692190bf142d 100644 --- a/backends/cryptodev-vhost-user.c +++ b/backends/cryptodev-vhost-user.c @@ -9,7 +9,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -30,6 +30,7 @@ #include "sysemu/cryptodev-vhost.h" #include "chardev/char-fe.h" #include "sysemu/cryptodev-vhost-user.h" +#include "qom/object.h" /** @@ -38,12 +39,10 @@ */ #define TYPE_CRYPTODEV_BACKEND_VHOST_USER "cryptodev-vhost-user" -#define CRYPTODEV_BACKEND_VHOST_USER(obj) \ - OBJECT_CHECK(CryptoDevBackendVhostUser, \ - (obj), TYPE_CRYPTODEV_BACKEND_VHOST_USER) +OBJECT_DECLARE_SIMPLE_TYPE(CryptoDevBackendVhostUser, CRYPTODEV_BACKEND_VHOST_USER) -typedef struct CryptoDevBackendVhostUser { +struct CryptoDevBackendVhostUser { CryptoDevBackend parent_obj; VhostUserState vhost_user; @@ -51,7 +50,7 @@ typedef struct CryptoDevBackendVhostUser { char *chr_name; bool opened; CryptoDevBackendVhost *vhost_crypto[MAX_CRYPTO_QUEUE_NUM]; -} CryptoDevBackendVhostUser; +}; static int cryptodev_vhost_user_running( @@ -209,8 +208,7 @@ static void cryptodev_vhost_user_init( backend->conf.peers.ccs[i] = cc; if (i == 0) { - if (!qemu_chr_fe_init(&s->chr, chr, &local_err)) { - error_propagate(errp, local_err); + if (!qemu_chr_fe_init(&s->chr, chr, errp)) { return; } } @@ -336,13 +334,6 @@ cryptodev_vhost_user_get_chardev(Object *obj, Error **errp) return NULL; } -static void cryptodev_vhost_user_instance_int(Object *obj) -{ - object_property_add_str(obj, "chardev", - cryptodev_vhost_user_get_chardev, - cryptodev_vhost_user_set_chardev); -} - static void cryptodev_vhost_user_finalize(Object *obj) { CryptoDevBackendVhostUser *s = @@ -363,13 +354,17 @@ cryptodev_vhost_user_class_init(ObjectClass *oc, void *data) bc->create_session = cryptodev_vhost_user_sym_create_session; bc->close_session = cryptodev_vhost_user_sym_close_session; bc->do_sym_op = NULL; + + object_class_property_add_str(oc, "chardev", + cryptodev_vhost_user_get_chardev, + cryptodev_vhost_user_set_chardev); + } static const TypeInfo cryptodev_vhost_user_info = { .name = TYPE_CRYPTODEV_BACKEND_VHOST_USER, .parent = TYPE_CRYPTODEV_BACKEND, .class_init = cryptodev_vhost_user_class_init, - .instance_init = cryptodev_vhost_user_instance_int, .instance_finalize = cryptodev_vhost_user_finalize, .instance_size = sizeof(CryptoDevBackendVhostUser), }; diff --git a/backends/cryptodev-vhost.c b/backends/cryptodev-vhost.c index 8337c9a495f0b28086d50fc303c67c929f31cfd9..8231e7f1bca9d3c35f90232c0d038abc77cc0e57 100644 --- a/backends/cryptodev-vhost.c +++ b/backends/cryptodev-vhost.c @@ -10,7 +10,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/backends/cryptodev.c b/backends/cryptodev.c index a3841c4e419d1e0c6ace6bc9864b1fafae213c99..bf524761663a530fdac9201da58e19595991c735 100644 --- a/backends/cryptodev.c +++ b/backends/cryptodev.c @@ -9,7 +9,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -154,21 +154,17 @@ cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj); - Error *local_err = NULL; uint32_t value; - visit_type_uint32(v, name, &value, &local_err); - if (local_err) { - goto out; + if (!visit_type_uint32(v, name, &value, errp)) { + return; } if (!value) { - error_setg(&local_err, "Property '%s.%s' doesn't take value '%" - PRIu32 "'", object_get_typename(obj), name, value); - goto out; + error_setg(errp, "Property '%s.%s' doesn't take value '%" PRIu32 "'", + object_get_typename(obj), name, value); + return; } backend->conf.peers.queues = value; -out: - error_propagate(errp, local_err); } static void @@ -210,12 +206,8 @@ cryptodev_backend_can_be_deleted(UserCreatable *uc) static void cryptodev_backend_instance_init(Object *obj) { - object_property_add(obj, "queues", "uint32", - cryptodev_backend_get_queues, - cryptodev_backend_set_queues, - NULL, NULL); /* Initialize devices' queues property to 1 */ - object_property_set_int(obj, 1, "queues", NULL); + object_property_set_int(obj, "queues", 1, NULL); } static void cryptodev_backend_finalize(Object *obj) @@ -234,6 +226,10 @@ cryptodev_backend_class_init(ObjectClass *oc, void *data) ucc->can_be_deleted = cryptodev_backend_can_be_deleted; QTAILQ_INIT(&crypto_clients); + object_class_property_add(oc, "queues", "uint32", + cryptodev_backend_get_queues, + cryptodev_backend_set_queues, + NULL, NULL); } static const TypeInfo cryptodev_backend_info = { diff --git a/backends/dbus-vmstate.c b/backends/dbus-vmstate.c index 56361a6272f8cc64673b6aff268fe1b6a85472c7..bd050e8e9cabc36bce994cda90e9a120328ce456 100644 --- a/backends/dbus-vmstate.c +++ b/backends/dbus-vmstate.c @@ -19,21 +19,13 @@ #include "qapi/qmp/qerror.h" #include "migration/vmstate.h" #include "trace.h" +#include "qom/object.h" -typedef struct DBusVMState DBusVMState; -typedef struct DBusVMStateClass DBusVMStateClass; #define TYPE_DBUS_VMSTATE "dbus-vmstate" -#define DBUS_VMSTATE(obj) \ - OBJECT_CHECK(DBusVMState, (obj), TYPE_DBUS_VMSTATE) -#define DBUS_VMSTATE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(DBusVMStateClass, (obj), TYPE_DBUS_VMSTATE) -#define DBUS_VMSTATE_CLASS(klass) \ - OBJECT_CLASS_CHECK(DBusVMStateClass, (klass), TYPE_DBUS_VMSTATE) - -struct DBusVMStateClass { - ObjectClass parent_class; -}; +OBJECT_DECLARE_SIMPLE_TYPE(DBusVMState, + DBUS_VMSTATE) + struct DBusVMState { Object parent; @@ -491,7 +483,6 @@ static const TypeInfo dbus_vmstate_info = { .parent = TYPE_OBJECT, .instance_size = sizeof(DBusVMState), .instance_finalize = dbus_vmstate_finalize, - .class_size = sizeof(DBusVMStateClass), .class_init = dbus_vmstate_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_USER_CREATABLE }, diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c index cdabb412e699cf0a9cc6faa86adf8a4da51b96b2..40e1e5b3e3bb2d9ee6b83a6d5d38bea8bf7884a2 100644 --- a/backends/hostmem-file.c +++ b/backends/hostmem-file.c @@ -17,11 +17,10 @@ #include "sysemu/hostmem.h" #include "sysemu/sysemu.h" #include "qom/object_interfaces.h" +#include "qom/object.h" -#define MEMORY_BACKEND_FILE(obj) \ - OBJECT_CHECK(HostMemoryBackendFile, (obj), TYPE_MEMORY_BACKEND_FILE) +OBJECT_DECLARE_SIMPLE_TYPE(HostMemoryBackendFile, MEMORY_BACKEND_FILE) -typedef struct HostMemoryBackendFile HostMemoryBackendFile; struct HostMemoryBackendFile { HostMemoryBackend parent_obj; @@ -110,23 +109,18 @@ static void file_memory_backend_set_align(Object *o, Visitor *v, { HostMemoryBackend *backend = MEMORY_BACKEND(o); HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o); - Error *local_err = NULL; uint64_t val; if (host_memory_backend_mr_inited(backend)) { - error_setg(&local_err, "cannot change property '%s' of %s", - name, object_get_typename(o)); - goto out; + error_setg(errp, "cannot change property '%s' of %s", name, + object_get_typename(o)); + return; } - visit_type_size(v, name, &val, &local_err); - if (local_err) { - goto out; + if (!visit_type_size(v, name, &val, errp)) { + return; } fb->align = val; - - out: - error_propagate(errp, local_err); } static bool file_memory_backend_get_pmem(Object *o, Error **errp) @@ -140,7 +134,6 @@ static void file_memory_backend_set_pmem(Object *o, bool value, Error **errp) HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o); if (host_memory_backend_mr_inited(backend)) { - error_setg(errp, "cannot change property 'pmem' of %s.", object_get_typename(o)); return; @@ -148,13 +141,9 @@ static void file_memory_backend_set_pmem(Object *o, bool value, Error **errp) #ifndef CONFIG_LIBPMEM if (value) { - Error *local_err = NULL; - - error_setg(&local_err, - "Lack of libpmem support while setting the 'pmem=on'" + error_setg(errp, "Lack of libpmem support while setting the 'pmem=on'" " of %s. We can't ensure data persistence.", object_get_typename(o)); - error_propagate(errp, local_err); return; } #endif diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c index 1b5e4bfe0d8c169cd06c9bb0cf1edff7d0fbddc2..e5626d4330641cdb5b98709e220bf13695e7cccf 100644 --- a/backends/hostmem-memfd.c +++ b/backends/hostmem-memfd.c @@ -17,13 +17,12 @@ #include "qemu/memfd.h" #include "qemu/module.h" #include "qapi/error.h" +#include "qom/object.h" #define TYPE_MEMORY_BACKEND_MEMFD "memory-backend-memfd" -#define MEMORY_BACKEND_MEMFD(obj) \ - OBJECT_CHECK(HostMemoryBackendMemfd, (obj), TYPE_MEMORY_BACKEND_MEMFD) +OBJECT_DECLARE_SIMPLE_TYPE(HostMemoryBackendMemfd, MEMORY_BACKEND_MEMFD) -typedef struct HostMemoryBackendMemfd HostMemoryBackendMemfd; struct HostMemoryBackendMemfd { HostMemoryBackend parent_obj; @@ -77,26 +76,22 @@ memfd_backend_set_hugetlbsize(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj); - Error *local_err = NULL; uint64_t value; if (host_memory_backend_mr_inited(MEMORY_BACKEND(obj))) { - error_setg(&local_err, "cannot change property value"); - goto out; + error_setg(errp, "cannot change property value"); + return; } - visit_type_size(v, name, &value, &local_err); - if (local_err) { - goto out; + if (!visit_type_size(v, name, &value, errp)) { + return; } if (!value) { - error_setg(&local_err, "Property '%s.%s' doesn't take value '%" - PRIu64 "'", object_get_typename(obj), name, value); - goto out; + error_setg(errp, "Property '%s.%s' doesn't take value '%" PRIu64 "'", + object_get_typename(obj), name, value); + return; } m->hugetlbsize = value; -out: - error_propagate(errp, local_err); } static void diff --git a/backends/hostmem.c b/backends/hostmem.c index 4ee435489873855765645d2988e83766607b3fe6..4bde00e8e74de4b20917a35cac495c63b2c2534d 100644 --- a/backends/hostmem.c +++ b/backends/hostmem.c @@ -33,7 +33,7 @@ char * host_memory_backend_get_name(HostMemoryBackend *backend) { if (!backend->use_canonical_path) { - return object_get_canonical_path_component(OBJECT(backend)); + return g_strdup(object_get_canonical_path_component(OBJECT(backend))); } return object_get_canonical_path(OBJECT(backend)); @@ -54,28 +54,24 @@ host_memory_backend_set_size(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { HostMemoryBackend *backend = MEMORY_BACKEND(obj); - Error *local_err = NULL; uint64_t value; if (host_memory_backend_mr_inited(backend)) { - error_setg(&local_err, "cannot change property %s of %s ", - name, object_get_typename(obj)); - goto out; + error_setg(errp, "cannot change property %s of %s ", name, + object_get_typename(obj)); + return; } - visit_type_size(v, name, &value, &local_err); - if (local_err) { - goto out; + if (!visit_type_size(v, name, &value, errp)) { + return; } if (!value) { - error_setg(&local_err, + error_setg(errp, "property '%s' of %s doesn't take value '%" PRIu64 "'", name, object_get_typename(obj), value); - goto out; + return; } backend->size = value; -out: - error_propagate(errp, local_err); } static void @@ -254,22 +250,17 @@ static void host_memory_backend_set_prealloc_threads(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { HostMemoryBackend *backend = MEMORY_BACKEND(obj); - Error *local_err = NULL; uint32_t value; - visit_type_uint32(v, name, &value, &local_err); - if (local_err) { - goto out; + if (!visit_type_uint32(v, name, &value, errp)) { + return; } if (value <= 0) { - error_setg(&local_err, - "property '%s' of %s doesn't take value '%d'", - name, object_get_typename(obj), value); - goto out; + error_setg(errp, "property '%s' of %s doesn't take value '%d'", name, + object_get_typename(obj), value); + return; } backend->prealloc_threads = value; -out: - error_propagate(errp, local_err); } static void host_memory_backend_init(Object *obj) @@ -383,8 +374,10 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp) assert(sizeof(backend->host_nodes) >= BITS_TO_LONGS(MAX_NODES + 1) * sizeof(unsigned long)); assert(maxnode <= MAX_NODES); - if (mbind(ptr, sz, backend->policy, - maxnode ? backend->host_nodes : NULL, maxnode + 1, flags)) { + + if (maxnode && + mbind(ptr, sz, backend->policy, backend->host_nodes, maxnode + 1, + flags)) { if (backend->policy != MPOL_DEFAULT || errno != ENOSYS) { error_setg_errno(errp, errno, "cannot bind memory to host NUMA nodes"); diff --git a/backends/meson.build b/backends/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..484456ece7afb60534d24ecb7110f0a0d2a0d06c --- /dev/null +++ b/backends/meson.build @@ -0,0 +1,19 @@ +softmmu_ss.add([files( + 'cryptodev-builtin.c', + 'cryptodev.c', + 'hostmem-ram.c', + 'hostmem.c', + 'rng-builtin.c', + 'rng-egd.c', + 'rng.c', +), numa]) + +softmmu_ss.add(when: 'CONFIG_POSIX', if_true: files('rng-random.c')) +softmmu_ss.add(when: 'CONFIG_POSIX', if_true: files('hostmem-file.c')) +softmmu_ss.add(when: 'CONFIG_LINUX', if_true: files('hostmem-memfd.c')) +softmmu_ss.add(when: ['CONFIG_VHOST_USER', 'CONFIG_VIRTIO'], if_true: files('vhost-user.c')) +softmmu_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('cryptodev-vhost.c')) +softmmu_ss.add(when: ['CONFIG_VIRTIO_CRYPTO', 'CONFIG_VHOST_CRYPTO'], if_true: files('cryptodev-vhost-user.c')) +softmmu_ss.add(when: 'CONFIG_GIO', if_true: [files('dbus-vmstate.c'), gio]) + +subdir('tpm') diff --git a/backends/rng-builtin.c b/backends/rng-builtin.c index ba1b8d66b83e1d422ee7ba1aed30a5954fddd1bc..f38dff117d150a3a80618d2d1aebfc129e6d3e85 100644 --- a/backends/rng-builtin.c +++ b/backends/rng-builtin.c @@ -9,13 +9,14 @@ #include "sysemu/rng.h" #include "qemu/main-loop.h" #include "qemu/guest-random.h" +#include "qom/object.h" -#define RNG_BUILTIN(obj) OBJECT_CHECK(RngBuiltin, (obj), TYPE_RNG_BUILTIN) +OBJECT_DECLARE_SIMPLE_TYPE(RngBuiltin, RNG_BUILTIN) -typedef struct RngBuiltin { +struct RngBuiltin { RngBackend parent; QEMUBH *bh; -} RngBuiltin; +}; static void rng_builtin_receive_entropy_bh(void *opaque) { diff --git a/backends/rng-egd.c b/backends/rng-egd.c index 7aaa6ee2393560869dff4a752fea9e93c8ece29e..4de142b9dc368195af7e65e13ed98c1109344859 100644 --- a/backends/rng-egd.c +++ b/backends/rng-egd.c @@ -16,17 +16,17 @@ #include "qapi/error.h" #include "qapi/qmp/qerror.h" #include "qemu/module.h" +#include "qom/object.h" #define TYPE_RNG_EGD "rng-egd" -#define RNG_EGD(obj) OBJECT_CHECK(RngEgd, (obj), TYPE_RNG_EGD) +OBJECT_DECLARE_SIMPLE_TYPE(RngEgd, RNG_EGD) -typedef struct RngEgd -{ +struct RngEgd { RngBackend parent; CharBackend chr; char *chr_name; -} RngEgd; +}; static void rng_egd_request_entropy(RngBackend *b, RngRequest *req) { @@ -135,12 +135,6 @@ static char *rng_egd_get_chardev(Object *obj, Error **errp) return NULL; } -static void rng_egd_init(Object *obj) -{ - object_property_add_str(obj, "chardev", - rng_egd_get_chardev, rng_egd_set_chardev); -} - static void rng_egd_finalize(Object *obj) { RngEgd *s = RNG_EGD(obj); @@ -155,6 +149,8 @@ static void rng_egd_class_init(ObjectClass *klass, void *data) rbc->request_entropy = rng_egd_request_entropy; rbc->opened = rng_egd_opened; + object_class_property_add_str(klass, "chardev", + rng_egd_get_chardev, rng_egd_set_chardev); } static const TypeInfo rng_egd_info = { @@ -162,7 +158,6 @@ static const TypeInfo rng_egd_info = { .parent = TYPE_RNG_BACKEND, .instance_size = sizeof(RngEgd), .class_init = rng_egd_class_init, - .instance_init = rng_egd_init, .instance_finalize = rng_egd_finalize, }; diff --git a/backends/rng-random.c b/backends/rng-random.c index 32998d8ee71ed5d1aec117f882be910328f1ba49..7add272edddf3ec446ce50b3276deb065aeee9fd 100644 --- a/backends/rng-random.c +++ b/backends/rng-random.c @@ -75,7 +75,7 @@ static void rng_random_opened(RngBackend *b, Error **errp) error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "filename", "a valid filename"); } else { - s->fd = qemu_open(s->filename, O_RDONLY | O_NONBLOCK); + s->fd = qemu_open_old(s->filename, O_RDONLY | O_NONBLOCK); if (s->fd == -1) { error_setg_file_open(errp, errno, s->filename); } @@ -108,10 +108,6 @@ static void rng_random_init(Object *obj) { RngRandom *s = RNG_RANDOM(obj); - object_property_add_str(obj, "filename", - rng_random_get_filename, - rng_random_set_filename); - s->filename = g_strdup("/dev/urandom"); s->fd = -1; } @@ -134,6 +130,10 @@ static void rng_random_class_init(ObjectClass *klass, void *data) rbc->request_entropy = rng_random_request_entropy; rbc->opened = rng_random_opened; + object_class_property_add_str(klass, "filename", + rng_random_get_filename, + rng_random_set_filename); + } static const TypeInfo rng_random_info = { diff --git a/backends/rng.c b/backends/rng.c index 597f0ec268751cfb2563a9bbd0ee1adfee257ef9..3757b044855c64d8820c777766e8d19a1bbd77b3 100644 --- a/backends/rng.c +++ b/backends/rng.c @@ -48,7 +48,7 @@ static bool rng_backend_prop_get_opened(Object *obj, Error **errp) static void rng_backend_complete(UserCreatable *uc, Error **errp) { - object_property_set_bool(OBJECT(uc), true, "opened", errp); + object_property_set_bool(OBJECT(uc), "opened", true, errp); } static void rng_backend_prop_set_opened(Object *obj, bool value, Error **errp) @@ -105,10 +105,6 @@ static void rng_backend_init(Object *obj) RngBackend *s = RNG_BACKEND(obj); QSIMPLEQ_INIT(&s->requests); - - object_property_add_bool(obj, "opened", - rng_backend_prop_get_opened, - rng_backend_prop_set_opened); } static void rng_backend_finalize(Object *obj) @@ -123,6 +119,10 @@ static void rng_backend_class_init(ObjectClass *oc, void *data) UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); ucc->complete = rng_backend_complete; + + object_class_property_add_bool(oc, "opened", + rng_backend_prop_get_opened, + rng_backend_prop_set_opened); } static const TypeInfo rng_backend_info = { diff --git a/backends/tpm/Kconfig b/backends/tpm/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..5d91eb89c20ffcd6f74382be2055de4b2c8f9e85 --- /dev/null +++ b/backends/tpm/Kconfig @@ -0,0 +1,14 @@ +config TPM_BACKEND + bool + depends on TPM + +config TPM_PASSTHROUGH + bool + default y + # FIXME: should check for x86 host as well + depends on TPM_BACKEND && LINUX + +config TPM_EMULATOR + bool + default y + depends on TPM_BACKEND diff --git a/backends/tpm/meson.build b/backends/tpm/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..857929082ea9b97305587df335344046e704416c --- /dev/null +++ b/backends/tpm/meson.build @@ -0,0 +1,8 @@ +tpm_ss = ss.source_set() + +tpm_ss.add(files('tpm_backend.c')) +tpm_ss.add(files('tpm_util.c')) +tpm_ss.add(when: 'CONFIG_TPM_PASSTHROUGH', if_true: files('tpm_passthrough.c')) +tpm_ss.add(when: 'CONFIG_TPM_EMULATOR', if_true: files('tpm_emulator.c')) + +softmmu_ss.add_all(when: 'CONFIG_TPM', if_true: tpm_ss) diff --git a/backends/tpm.c b/backends/tpm/tpm_backend.c similarity index 100% rename from backends/tpm.c rename to backends/tpm/tpm_backend.c diff --git a/hw/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c similarity index 97% rename from hw/tpm/tpm_emulator.c rename to backends/tpm/tpm_emulator.c index 3a0fc442f387f85133c8edb7cffc1804e82cf039..a012adc193417b460967c373d81598a4241ebf2d 100644 --- a/hw/tpm/tpm_emulator.c +++ b/backends/tpm/tpm_emulator.c @@ -14,7 +14,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -32,8 +32,8 @@ #include "qemu/sockets.h" #include "io/channel-socket.h" #include "sysemu/tpm_backend.h" +#include "sysemu/tpm_util.h" #include "tpm_int.h" -#include "tpm_util.h" #include "tpm_ioctl.h" #include "migration/blocker.h" #include "migration/vmstate.h" @@ -42,10 +42,10 @@ #include "qapi/qapi-visit-tpm.h" #include "chardev/char-fe.h" #include "trace.h" +#include "qom/object.h" #define TYPE_TPM_EMULATOR "tpm-emulator" -#define TPM_EMULATOR(obj) \ - OBJECT_CHECK(TPMEmulator, (obj), TYPE_TPM_EMULATOR) +OBJECT_DECLARE_SIMPLE_TYPE(TPMEmulator, TPM_EMULATOR) #define TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(S, cap) (((S)->caps & (cap)) == (cap)) @@ -63,7 +63,7 @@ typedef struct TPMBlobBuffers { TPMSizedBuffer savestate; } TPMBlobBuffers; -typedef struct TPMEmulator { +struct TPMEmulator { TPMBackend parent; TPMEmulatorOptions *options; @@ -80,7 +80,7 @@ typedef struct TPMEmulator { unsigned int established_flag_cached:1; TPMBlobBuffers state_blobs; -} TPMEmulator; +}; struct tpm_error { uint32_t tpm_result; @@ -549,27 +549,30 @@ err_exit: static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_emu, QemuOpts *opts) { const char *value; + Error *err = NULL; + Chardev *dev; value = qemu_opt_get(opts, "chardev"); - if (value) { - Error *err = NULL; - Chardev *dev = qemu_chr_find(value); - - if (!dev) { - error_report("tpm-emulator: tpm chardev '%s' not found.", value); - goto err; - } + if (!value) { + error_report("tpm-emulator: parameter 'chardev' is missing"); + goto err; + } - if (!qemu_chr_fe_init(&tpm_emu->ctrl_chr, dev, &err)) { - error_prepend(&err, "tpm-emulator: No valid chardev found at '%s':", - value); - error_report_err(err); - goto err; - } + dev = qemu_chr_find(value); + if (!dev) { + error_report("tpm-emulator: tpm chardev '%s' not found", value); + goto err; + } - tpm_emu->options->chardev = g_strdup(value); + if (!qemu_chr_fe_init(&tpm_emu->ctrl_chr, dev, &err)) { + error_prepend(&err, "tpm-emulator: No valid chardev found at '%s':", + value); + error_report_err(err); + goto err; } + tpm_emu->options->chardev = g_strdup(value); + if (tpm_emulator_prepare_data_fd(tpm_emu) < 0) { goto err; } @@ -925,6 +928,11 @@ static void tpm_emulator_shutdown(TPMEmulator *tpm_emu) { ptm_res res; + if (!tpm_emu->options->chardev) { + /* was never properly initialized */ + return; + } + if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SHUTDOWN, &res, 0, sizeof(res)) < 0) { error_report("tpm-emulator: Could not cleanly shutdown the TPM: %s", strerror(errno)); diff --git a/hw/tpm/tpm_int.h b/backends/tpm/tpm_int.h similarity index 81% rename from hw/tpm/tpm_int.h rename to backends/tpm/tpm_int.h index 3fb28a9d6c5ba996625eccd8a1847967bce2cea4..ba6109306e505af5c3e7c7fa9ed8642f9cf72ebf 100644 --- a/hw/tpm/tpm_int.h +++ b/backends/tpm/tpm_int.h @@ -9,8 +9,11 @@ * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. */ -#ifndef TPM_TPM_INT_H -#define TPM_TPM_INT_H +#ifndef BACKENDS_TPM_INT_H +#define BACKENDS_TPM_INT_H + +#include "qemu/option.h" +#include "sysemu/tpm.h" #define TPM_STANDARD_CMDLINE_OPTS \ { \ @@ -72,4 +75,14 @@ struct tpm_resp_hdr { #define TPM_RC_FAILURE 0x101 #define TPM_RC_LOCALITY 0x907 -#endif /* TPM_TPM_INT_H */ +int tpm_util_get_buffer_size(int tpm_fd, TPMVersion tpm_version, + size_t *buffersize); + +typedef struct TPMSizedBuffer { + uint32_t size; + uint8_t *buffer; +} TPMSizedBuffer; + +void tpm_sized_buffer_reset(TPMSizedBuffer *tsb); + +#endif /* BACKENDS_TPM_INT_H */ diff --git a/hw/tpm/tpm_ioctl.h b/backends/tpm/tpm_ioctl.h similarity index 99% rename from hw/tpm/tpm_ioctl.h rename to backends/tpm/tpm_ioctl.h index f5f5c553a9147ebc9dce8d2ea971720db47ed04e..bd6c12cb86c14052a421bc54f89b17ad8ad53500 100644 --- a/hw/tpm/tpm_ioctl.h +++ b/backends/tpm/tpm_ioctl.h @@ -12,6 +12,10 @@ #include #include +#ifdef HAVE_SYS_IOCCOM_H +#include +#endif + /* * Every response from a command involving a TPM command execution must hold * the ptm_res as the first element. diff --git a/hw/tpm/tpm_passthrough.c b/backends/tpm/tpm_passthrough.c similarity index 96% rename from hw/tpm/tpm_passthrough.c rename to backends/tpm/tpm_passthrough.c index f67244b5d4fc260e25afb871156dbbed95dc1a5f..21b74591838ad116f5ba7281aa7b01f0896342dd 100644 --- a/hw/tpm/tpm_passthrough.c +++ b/backends/tpm/tpm_passthrough.c @@ -11,7 +11,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -28,15 +28,15 @@ #include "qemu/module.h" #include "qemu/sockets.h" #include "sysemu/tpm_backend.h" +#include "sysemu/tpm_util.h" #include "tpm_int.h" #include "qapi/clone-visitor.h" #include "qapi/qapi-visit-tpm.h" -#include "tpm_util.h" #include "trace.h" +#include "qom/object.h" #define TYPE_TPM_PASSTHROUGH "tpm-passthrough" -#define TPM_PASSTHROUGH(obj) \ - OBJECT_CHECK(TPMPassthruState, (obj), TYPE_TPM_PASSTHROUGH) +OBJECT_DECLARE_SIMPLE_TYPE(TPMPassthruState, TPM_PASSTHROUGH) /* data structures */ struct TPMPassthruState { @@ -53,7 +53,6 @@ struct TPMPassthruState { size_t tpm_buffersize; }; -typedef struct TPMPassthruState TPMPassthruState; #define TPM_PASSTHROUGH_DEFAULT_DEVICE "/dev/tpm0" @@ -217,7 +216,7 @@ static int tpm_passthrough_open_sysfs_cancel(TPMPassthruState *tpm_pt) char path[PATH_MAX]; if (tpm_pt->options->cancel_path) { - fd = qemu_open(tpm_pt->options->cancel_path, O_WRONLY); + fd = qemu_open_old(tpm_pt->options->cancel_path, O_WRONLY); if (fd < 0) { error_report("tpm_passthrough: Could not open TPM cancel path: %s", strerror(errno)); @@ -235,11 +234,11 @@ static int tpm_passthrough_open_sysfs_cancel(TPMPassthruState *tpm_pt) dev++; if (snprintf(path, sizeof(path), "/sys/class/tpm/%s/device/cancel", dev) < sizeof(path)) { - fd = qemu_open(path, O_WRONLY); + fd = qemu_open_old(path, O_WRONLY); if (fd < 0) { if (snprintf(path, sizeof(path), "/sys/class/misc/%s/device/cancel", dev) < sizeof(path)) { - fd = qemu_open(path, O_WRONLY); + fd = qemu_open_old(path, O_WRONLY); } } } @@ -271,7 +270,7 @@ tpm_passthrough_handle_device_opts(TPMPassthruState *tpm_pt, QemuOpts *opts) } tpm_pt->tpm_dev = value ? value : TPM_PASSTHROUGH_DEFAULT_DEVICE; - tpm_pt->tpm_fd = qemu_open(tpm_pt->tpm_dev, O_RDWR); + tpm_pt->tpm_fd = qemu_open_old(tpm_pt->tpm_dev, O_RDWR); if (tpm_pt->tpm_fd < 0) { error_report("Cannot access TPM device using '%s': %s", tpm_pt->tpm_dev, strerror(errno)); diff --git a/hw/tpm/tpm_util.c b/backends/tpm/tpm_util.c similarity index 97% rename from hw/tpm/tpm_util.c rename to backends/tpm/tpm_util.c index c0a0f3d71f7449ddd1aba548b66b4fd4c52bcb7f..e6aeb63587fcb56aa62f82115adf02625c369648 100644 --- a/hw/tpm/tpm_util.c +++ b/backends/tpm/tpm_util.c @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -23,11 +23,11 @@ #include "qemu/error-report.h" #include "qapi/error.h" #include "qapi/visitor.h" -#include "tpm_util.h" #include "tpm_int.h" #include "exec/memory.h" #include "hw/qdev-properties.h" #include "sysemu/tpm_backend.h" +#include "sysemu/tpm_util.h" #include "trace.h" /* tpm backend property */ @@ -48,7 +48,6 @@ static void set_tpm(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { DeviceState *dev = DEVICE(obj); - Error *local_err = NULL; Property *prop = opaque; TPMBackend *s, **be = qdev_get_prop_ptr(dev, prop); char *str; @@ -58,9 +57,7 @@ static void set_tpm(Object *obj, Visitor *v, const char *name, void *opaque, return; } - visit_type_str(v, name, &str, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_str(v, name, &str, errp)) { return; } @@ -357,6 +354,9 @@ void tpm_util_show_buffer(const unsigned char *buffer, size_t len, i; char *line_buffer, *p; + if (!trace_event_get_state_backends(TRACE_TPM_UTIL_SHOW_BUFFER)) { + return; + } len = MIN(tpm_cmd_get_size(buffer), buffer_size); /* diff --git a/backends/tpm/trace-events b/backends/tpm/trace-events new file mode 100644 index 0000000000000000000000000000000000000000..0a2591fb2d65497543863ccb5ec81f42d181fa67 --- /dev/null +++ b/backends/tpm/trace-events @@ -0,0 +1,33 @@ +# See docs/devel/tracing.txt for syntax documentation. + +# tpm_passthrough.c +tpm_passthrough_handle_request(void *cmd) "processing command %p" +tpm_passthrough_reset(void) "reset" + +# tpm_util.c +tpm_util_get_buffer_size_hdr_len(uint32_t len, size_t expected) "tpm_resp->hdr.len = %u, expected = %zu" +tpm_util_get_buffer_size_len(uint32_t len, size_t expected) "tpm_resp->len = %u, expected = %zu" +tpm_util_get_buffer_size_hdr_len2(uint32_t len, size_t expected) "tpm2_resp->hdr.len = %u, expected = %zu" +tpm_util_get_buffer_size_len2(uint32_t len, size_t expected) "tpm2_resp->len = %u, expected = %zu" +tpm_util_get_buffer_size(size_t len) "buffersize of device: %zu" +tpm_util_show_buffer(const char *direction, size_t len, const char *buf) "direction: %s len: %zu\n%s" + +# tpm_emulator.c +tpm_emulator_set_locality(uint8_t locty) "setting locality to %d" +tpm_emulator_handle_request(void) "processing TPM command" +tpm_emulator_probe_caps(uint64_t caps) "capabilities: 0x%"PRIx64 +tpm_emulator_set_buffer_size(uint32_t buffersize, uint32_t minsize, uint32_t maxsize) "buffer size: %u, min: %u, max: %u" +tpm_emulator_startup_tpm_resume(bool is_resume, size_t buffersize) "is_resume: %d, buffer size: %zu" +tpm_emulator_get_tpm_established_flag(uint8_t flag) "got established flag: %d" +tpm_emulator_cancel_cmd_not_supt(void) "Backend does not support CANCEL_TPM_CMD" +tpm_emulator_handle_device_opts_tpm12(void) "TPM Version 1.2" +tpm_emulator_handle_device_opts_tpm2(void) "TPM Version 2" +tpm_emulator_handle_device_opts_unspec(void) "TPM Version Unspecified" +tpm_emulator_handle_device_opts_startup_error(void) "Startup error" +tpm_emulator_get_state_blob(uint8_t type, uint32_t size, uint32_t flags) "got state blob type %d, %u bytes, flags 0x%08x" +tpm_emulator_set_state_blob(uint8_t type, uint32_t size, uint32_t flags) "set state blob type %d, %u bytes, flags 0x%08x" +tpm_emulator_set_state_blobs(void) "setting state blobs" +tpm_emulator_set_state_blobs_error(const char *msg) "error while setting state blobs: %s" +tpm_emulator_set_state_blobs_done(void) "Done setting state blobs" +tpm_emulator_pre_save(void) "" +tpm_emulator_inst_init(void) "" diff --git a/backends/tpm/trace.h b/backends/tpm/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..40c4729884237f795e85fad1fbefe9c65df54751 --- /dev/null +++ b/backends/tpm/trace.h @@ -0,0 +1 @@ +#include "trace/trace-backends_tpm.h" diff --git a/backends/trace.h b/backends/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..77fe57f36ca5dbb87f24de526c6192dcfb247cf7 --- /dev/null +++ b/backends/trace.h @@ -0,0 +1 @@ +#include "trace/trace-backends.h" diff --git a/backends/vhost-user.c b/backends/vhost-user.c index 9e6e19854652dff6778bd6099eb0f0b27b317224..b366610e16e3181a2499be1c7884e5fba65e08c3 100644 --- a/backends/vhost-user.c +++ b/backends/vhost-user.c @@ -175,9 +175,9 @@ static char *get_chardev(Object *obj, Error **errp) return NULL; } -static void vhost_user_backend_init(Object *obj) +static void vhost_user_backend_class_init(ObjectClass *oc, void *data) { - object_property_add_str(obj, "chardev", get_chardev, set_chardev); + object_class_property_add_str(oc, "chardev", get_chardev, set_chardev); } static void vhost_user_backend_finalize(Object *obj) @@ -195,9 +195,8 @@ static const TypeInfo vhost_user_backend_info = { .name = TYPE_VHOST_USER_BACKEND, .parent = TYPE_OBJECT, .instance_size = sizeof(VhostUserBackend), - .instance_init = vhost_user_backend_init, + .class_init = vhost_user_backend_class_init, .instance_finalize = vhost_user_backend_finalize, - .class_size = sizeof(VhostUserBackendClass), }; static void register_types(void) diff --git a/block.c b/block.c index 8416376c9b712eec6587da3971f6d02950c9bfa5..f1cedac362577c2796b69e3972e9c74a89d55dc9 100644 --- a/block.c +++ b/block.c @@ -29,7 +29,7 @@ #include "block/nbd.h" #include "block/qdict.h" #include "qemu/error-report.h" -#include "module_block.h" +#include "block/module_block.h" #include "qemu/main-loop.h" #include "qemu/module.h" #include "qapi/error.h" @@ -48,6 +48,7 @@ #include "qemu/timer.h" #include "qemu/cutils.h" #include "qemu/id.h" +#include "block/coroutines.h" #ifdef CONFIG_BSD #include @@ -433,9 +434,11 @@ static int bdrv_format_is_whitelisted(const char *format_name, bool read_only) { static const char *whitelist_rw[] = { CONFIG_BDRV_RW_WHITELIST + NULL }; static const char *whitelist_ro[] = { CONFIG_BDRV_RO_WHITELIST + NULL }; const char **p; @@ -710,11 +713,12 @@ int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp) int bdrv_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz) { BlockDriver *drv = bs->drv; + BlockDriverState *filtered = bdrv_filter_bs(bs); if (drv && drv->bdrv_probe_blocksizes) { return drv->bdrv_probe_blocksizes(bs, bsz); - } else if (drv && drv->is_filter && bs->file) { - return bdrv_probe_blocksizes(bs->file->bs, bsz); + } else if (filtered) { + return bdrv_probe_blocksizes(filtered, bsz); } return -ENOTSUP; @@ -729,11 +733,12 @@ int bdrv_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz) int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo) { BlockDriver *drv = bs->drv; + BlockDriverState *filtered = bdrv_filter_bs(bs); if (drv && drv->bdrv_probe_geometry) { return drv->bdrv_probe_geometry(bs, geo); - } else if (drv && drv->is_filter && bs->file) { - return bdrv_probe_geometry(bs->file->bs, geo); + } else if (filtered) { + return bdrv_probe_geometry(filtered, geo); } return -ENOTSUP; @@ -1151,10 +1156,6 @@ static void bdrv_backing_attach(BdrvChild *c) bdrv_refresh_filename(backing_hd); parent->open_flags &= ~BDRV_O_NO_BACKING; - pstrcpy(parent->backing_file, sizeof(parent->backing_file), - backing_hd->filename); - pstrcpy(parent->backing_format, sizeof(parent->backing_format), - backing_hd->drv ? backing_hd->drv->format_name : ""); bdrv_op_block_all(backing_hd, parent->backing_blocker); /* Otherwise we won't be able to commit or stream */ @@ -1206,7 +1207,8 @@ static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base, } ret = bdrv_change_backing_file(parent, filename, - base->drv ? base->drv->format_name : ""); + base->drv ? base->drv->format_name : "", + false); if (ret < 0) { error_setg_errno(errp, -ret, "Could not update backing file link"); } @@ -1629,9 +1631,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file, assert(options != NULL && bs->options != options); opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { ret = -EINVAL; goto fail_opts; } @@ -1695,7 +1695,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file, } /* bdrv_new() and bdrv_close() make it so */ - assert(atomic_read(&bs->copy_on_read) == 0); + assert(qatomic_read(&bs->copy_on_read) == 0); if (bs->open_flags & BDRV_O_COPY_ON_READ) { if (!bs->read_only) { @@ -2026,6 +2026,22 @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q, return -EPERM; } + /* + * Unaligned requests will automatically be aligned to bl.request_alignment + * and without RESIZE we can't extend requests to write to space beyond the + * end of the image, so it's required that the image size is aligned. + */ + if ((cumulative_perms & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) && + !(cumulative_perms & BLK_PERM_RESIZE)) + { + if ((bs->total_sectors * BDRV_SECTOR_SIZE) % bs->bl.request_alignment) { + error_setg(errp, "Cannot get 'write' permission without 'resize': " + "Image size is not a multiple of request " + "alignment"); + return -EPERM; + } + } + /* Check this node */ if (!drv) { return 0; @@ -2587,7 +2603,7 @@ static void bdrv_replace_child_noperm(BdrvChild *child, /* * Updates @child to change its reference to point to @new_bs, including - * checking and applying the necessary permisson updates both to the old node + * checking and applying the necessary permission updates both to the old node * and to @new_bs. * * NULL is passed as @new_bs for removing the reference before freeing @child. @@ -2595,12 +2611,15 @@ static void bdrv_replace_child_noperm(BdrvChild *child, * If @new_bs is not NULL, bdrv_check_perm() must be called beforehand, as this * function uses bdrv_set_perm() to update the permissions according to the new * reference that @new_bs gets. + * + * Callers must ensure that child->frozen is false. */ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs) { BlockDriverState *old_bs = child->bs; uint64_t perm, shared_perm; + /* Asserts that child->frozen == false */ bdrv_replace_child_noperm(child, new_bs); /* @@ -2761,6 +2780,7 @@ static void bdrv_detach_child(BdrvChild *child) g_free(child); } +/* Callers must ensure that child->frozen is false. */ void bdrv_root_unref_child(BdrvChild *child) { BlockDriverState *child_bs; @@ -2798,6 +2818,7 @@ static void bdrv_unset_inherits_from(BlockDriverState *root, BdrvChild *child) } } +/* Callers must ensure that child->frozen is false. */ void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child) { if (child == NULL) { @@ -2846,7 +2867,7 @@ static BdrvChildRole bdrv_backing_role(BlockDriverState *bs) } /* - * Sets the backing file link of a BDS. A new reference is created; callers + * Sets the bs->backing link of a BDS. A new reference is created; callers * which don't need their own reference any more must call bdrv_unref(). */ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, @@ -2855,7 +2876,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, bool update_inherits_from = bdrv_chain_contains(bs, backing_hd) && bdrv_inherits_from_recursive(backing_hd, bs); - if (bdrv_is_backing_chain_frozen(bs, backing_bs(bs), errp)) { + if (bdrv_is_backing_chain_frozen(bs, child_bs(bs->backing), errp)) { return; } @@ -2864,6 +2885,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, } if (bs->backing) { + /* Cannot be frozen, we checked that above */ bdrv_unref_child(bs, bs->backing); bs->backing = NULL; } @@ -3979,7 +4001,7 @@ static int bdrv_reopen_parse_backing(BDRVReopenState *reopen_state, Error **errp) { BlockDriverState *bs = reopen_state->bs; - BlockDriverState *overlay_bs, *new_backing_bs; + BlockDriverState *overlay_bs, *below_bs, *new_backing_bs; QObject *value; const char *str; @@ -4018,26 +4040,57 @@ static int bdrv_reopen_parse_backing(BDRVReopenState *reopen_state, } } + /* + * Ensure that @bs can really handle backing files, because we are + * about to give it one (or swap the existing one) + */ + if (bs->drv->is_filter) { + /* Filters always have a file or a backing child */ + if (!bs->backing) { + error_setg(errp, "'%s' is a %s filter node that does not support a " + "backing child", bs->node_name, bs->drv->format_name); + return -EINVAL; + } + } else if (!bs->drv->supports_backing) { + error_setg(errp, "Driver '%s' of node '%s' does not support backing " + "files", bs->drv->format_name, bs->node_name); + return -EINVAL; + } + /* * Find the "actual" backing file by skipping all links that point * to an implicit node, if any (e.g. a commit filter node). + * We cannot use any of the bdrv_skip_*() functions here because + * those return the first explicit node, while we are looking for + * its overlay here. */ overlay_bs = bs; - while (backing_bs(overlay_bs) && backing_bs(overlay_bs)->implicit) { - overlay_bs = backing_bs(overlay_bs); + for (below_bs = bdrv_filter_or_cow_bs(overlay_bs); + below_bs && below_bs->implicit; + below_bs = bdrv_filter_or_cow_bs(overlay_bs)) + { + overlay_bs = below_bs; } /* If we want to replace the backing file we need some extra checks */ - if (new_backing_bs != backing_bs(overlay_bs)) { + if (new_backing_bs != bdrv_filter_or_cow_bs(overlay_bs)) { /* Check for implicit nodes between bs and its backing file */ if (bs != overlay_bs) { error_setg(errp, "Cannot change backing link if '%s' has " "an implicit backing file", bs->node_name); return -EPERM; } - /* Check if the backing link that we want to replace is frozen */ - if (bdrv_is_backing_chain_frozen(overlay_bs, backing_bs(overlay_bs), - errp)) { + /* + * Check if the backing link that we want to replace is frozen. + * Note that + * bdrv_filter_or_cow_child(overlay_bs) == overlay_bs->backing, + * because we know that overlay_bs == bs, and that @bs + * either is a filter that uses ->backing or a COW format BDS + * with bs->drv->supports_backing == true. + */ + if (bdrv_is_backing_chain_frozen(overlay_bs, + child_bs(overlay_bs->backing), errp)) + { return -EPERM; } reopen_state->replace_backing_bs = true; @@ -4091,9 +4144,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue, /* Process generic block layer options */ opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, reopen_state->options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, reopen_state->options, errp)) { ret = -EINVAL; goto error; } @@ -4188,7 +4239,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue, * its metadata. Otherwise the 'backing' option can be omitted. */ if (drv->supports_backing && reopen_state->backing_missing && - (backing_bs(reopen_state->bs) || reopen_state->bs->backing_file[0])) { + (reopen_state->bs->backing || reopen_state->bs->backing_file[0])) { error_setg(errp, "backing is missing for '%s'", reopen_state->bs->node_name); ret = -EINVAL; @@ -4329,7 +4380,7 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state) * from bdrv_set_backing_hd()) has the new values. */ if (reopen_state->replace_backing_bs) { - BlockDriverState *old_backing_bs = backing_bs(bs); + BlockDriverState *old_backing_bs = child_bs(bs->backing); assert(!old_backing_bs || !old_backing_bs->implicit); /* Abort the permission update on the backing bs we're detaching */ if (old_backing_bs) { @@ -4372,6 +4423,7 @@ static void bdrv_close(BlockDriverState *bs) if (bs->drv) { if (bs->drv->bdrv_close) { + /* Must unfreeze all children, so bdrv_unref_child() works */ bs->drv->bdrv_close(bs); } bs->drv = NULL; @@ -4385,7 +4437,7 @@ static void bdrv_close(BlockDriverState *bs) bs->file = NULL; g_free(bs->opaque); bs->opaque = NULL; - atomic_set(&bs->copy_on_read, 0); + qatomic_set(&bs->copy_on_read, 0); bs->backing_file[0] = '\0'; bs->backing_format[0] = '\0'; bs->total_sectors = 0; @@ -4406,12 +4458,21 @@ static void bdrv_close(BlockDriverState *bs) } QLIST_INIT(&bs->aio_notifiers); bdrv_drained_end(bs); + + /* + * If we're still inside some bdrv_drain_all_begin()/end() sections, end + * them now since this BDS won't exist anymore when bdrv_drain_all_end() + * gets called. + */ + if (bs->quiesce_counter) { + bdrv_drain_all_end_quiesce(bs); + } } void bdrv_close_all(void) { assert(job_next(NULL) == NULL); - nbd_export_close_all(); + blk_exp_close_all(); /* Drop references from requests still in flight, such as canceled block * jobs whose AIO context has not been polled yet */ @@ -4502,8 +4563,16 @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to) return ret; } -void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, - Error **errp) +/* + * With auto_skip=true bdrv_replace_node_common skips updating from parents + * if it creates a parent-child relation loop or if parent is block-job. + * + * With auto_skip=false the error is returned if from has a parent which should + * not be updated. + */ +static void bdrv_replace_node_common(BlockDriverState *from, + BlockDriverState *to, + bool auto_skip, Error **errp) { BdrvChild *c, *next; GSList *list = NULL, *p; @@ -4522,7 +4591,12 @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, QLIST_FOREACH_SAFE(c, &from->parents, next_parent, next) { assert(c->bs == from); if (!should_update_child(c, to)) { - continue; + if (auto_skip) { + continue; + } + error_setg(errp, "Should not change '%s' link to '%s'", + c->name, from->node_name); + goto out; } if (c->frozen) { error_setg(errp, "Cannot change '%s' link to '%s'", @@ -4562,6 +4636,12 @@ out: bdrv_unref(from); } +void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, + Error **errp) +{ + return bdrv_replace_node_common(from, to, true, errp); +} + /* * Add new bs contents at the top of an image chain while the chain is * live, while keeping required fields on the top layer. @@ -4625,8 +4705,8 @@ static void bdrv_delete(BlockDriverState *bs) * free of errors) or -errno when an internal error occurred. The results of the * check are stored in res. */ -static int coroutine_fn bdrv_co_check(BlockDriverState *bs, - BdrvCheckResult *res, BdrvCheckMode fix) +int coroutine_fn bdrv_co_check(BlockDriverState *bs, + BdrvCheckResult *res, BdrvCheckMode fix) { if (bs->drv == NULL) { return -ENOMEDIUM; @@ -4639,43 +4719,6 @@ static int coroutine_fn bdrv_co_check(BlockDriverState *bs, return bs->drv->bdrv_co_check(bs, res, fix); } -typedef struct CheckCo { - BlockDriverState *bs; - BdrvCheckResult *res; - BdrvCheckMode fix; - int ret; -} CheckCo; - -static void coroutine_fn bdrv_check_co_entry(void *opaque) -{ - CheckCo *cco = opaque; - cco->ret = bdrv_co_check(cco->bs, cco->res, cco->fix); - aio_wait_kick(); -} - -int bdrv_check(BlockDriverState *bs, - BdrvCheckResult *res, BdrvCheckMode fix) -{ - Coroutine *co; - CheckCo cco = { - .bs = bs, - .res = res, - .ret = -EINPROGRESS, - .fix = fix, - }; - - if (qemu_in_coroutine()) { - /* Fast-path if already in coroutine context */ - bdrv_check_co_entry(&cco); - } else { - co = qemu_coroutine_create(bdrv_check_co_entry, &cco); - bdrv_coroutine_enter(bs, co); - BDRV_POLL_WHILE(bs, cco.ret == -EINPROGRESS); - } - - return cco.ret; -} - /* * Return values: * 0 - success @@ -4684,8 +4727,8 @@ int bdrv_check(BlockDriverState *bs, * image file header * -ENOTSUP - format driver doesn't support changing the backing file */ -int bdrv_change_backing_file(BlockDriverState *bs, - const char *backing_file, const char *backing_fmt) +int bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file, + const char *backing_fmt, bool warn) { BlockDriver *drv = bs->drv; int ret; @@ -4699,6 +4742,12 @@ int bdrv_change_backing_file(BlockDriverState *bs, return -EINVAL; } + if (warn && backing_file && !backing_fmt) { + warn_report("Deprecated use of backing file without explicit " + "backing format, use of this image requires " + "potentially unsafe format probing"); + } + if (drv->bdrv_change_backing_file != NULL) { ret = drv->bdrv_change_backing_file(bs, backing_file, backing_fmt); } else { @@ -4715,9 +4764,9 @@ int bdrv_change_backing_file(BlockDriverState *bs, } /* - * Finds the image layer in the chain that has 'bs' as its backing file. - * - * active is the current topmost image. + * Finds the first non-filter node above bs in the chain between + * active and bs. The returned node is either an immediate parent of + * bs, or there are only filter nodes between the two. * * Returns NULL if bs is not found in active's image chain, * or if active == bs. @@ -4727,11 +4776,18 @@ int bdrv_change_backing_file(BlockDriverState *bs, BlockDriverState *bdrv_find_overlay(BlockDriverState *active, BlockDriverState *bs) { - while (active && bs != backing_bs(active)) { - active = backing_bs(active); + bs = bdrv_skip_filters(bs); + active = bdrv_skip_filters(active); + + while (active) { + BlockDriverState *next = bdrv_backing_chain_next(active); + if (bs == next) { + return active; + } + active = next; } - return active; + return NULL; } /* Given a BDS, searches for the base layer. */ @@ -4741,20 +4797,22 @@ BlockDriverState *bdrv_find_base(BlockDriverState *bs) } /* - * Return true if at least one of the backing links between @bs and - * @base is frozen. @errp is set if that's the case. + * Return true if at least one of the COW (backing) and filter links + * between @bs and @base is frozen. @errp is set if that's the case. * @base must be reachable from @bs, or NULL. */ bool bdrv_is_backing_chain_frozen(BlockDriverState *bs, BlockDriverState *base, Error **errp) { BlockDriverState *i; + BdrvChild *child; + + for (i = bs; i != base; i = child_bs(child)) { + child = bdrv_filter_or_cow_child(i); - for (i = bs; i != base; i = backing_bs(i)) { - if (i->backing && i->backing->frozen) { + if (child && child->frozen) { error_setg(errp, "Cannot change '%s' link from '%s' to '%s'", - i->backing->name, i->node_name, - backing_bs(i)->node_name); + child->name, i->node_name, child->bs->node_name); return true; } } @@ -4763,7 +4821,7 @@ bool bdrv_is_backing_chain_frozen(BlockDriverState *bs, BlockDriverState *base, } /* - * Freeze all backing links between @bs and @base. + * Freeze all COW (backing) and filter links between @bs and @base. * If any of the links is already frozen the operation is aborted and * none of the links are modified. * @base must be reachable from @bs, or NULL. @@ -4773,22 +4831,25 @@ int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base, Error **errp) { BlockDriverState *i; + BdrvChild *child; if (bdrv_is_backing_chain_frozen(bs, base, errp)) { return -EPERM; } - for (i = bs; i != base; i = backing_bs(i)) { - if (i->backing && backing_bs(i)->never_freeze) { + for (i = bs; i != base; i = child_bs(child)) { + child = bdrv_filter_or_cow_child(i); + if (child && child->bs->never_freeze) { error_setg(errp, "Cannot freeze '%s' link to '%s'", - i->backing->name, backing_bs(i)->node_name); + child->name, child->bs->node_name); return -EPERM; } } - for (i = bs; i != base; i = backing_bs(i)) { - if (i->backing) { - i->backing->frozen = true; + for (i = bs; i != base; i = child_bs(child)) { + child = bdrv_filter_or_cow_child(i); + if (child) { + child->frozen = true; } } @@ -4796,18 +4857,21 @@ int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base, } /* - * Unfreeze all backing links between @bs and @base. The caller must - * ensure that all links are frozen before using this function. + * Unfreeze all COW (backing) and filter links between @bs and @base. + * The caller must ensure that all links are frozen before using this + * function. * @base must be reachable from @bs, or NULL. */ void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base) { BlockDriverState *i; + BdrvChild *child; - for (i = bs; i != base; i = backing_bs(i)) { - if (i->backing) { - assert(i->backing->frozen); - i->backing->frozen = false; + for (i = bs; i != base; i = child_bs(child)) { + child = bdrv_filter_or_cow_child(i); + if (child) { + assert(child->frozen); + child->frozen = false; } } } @@ -4846,9 +4910,11 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, { BlockDriverState *explicit_top = top; bool update_inherits_from; - BdrvChild *c, *next; + BdrvChild *c; Error *local_err = NULL; int ret = -EIO; + g_autoptr(GSList) updated_children = NULL; + GSList *p; bdrv_ref(top); bdrv_subtree_drained_begin(top); @@ -4862,22 +4928,12 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, goto exit; } - /* This function changes all links that point to top and makes - * them point to base. Check that none of them is frozen. */ - QLIST_FOREACH(c, &top->parents, next_parent) { - if (c->frozen) { - goto exit; - } - } - /* If 'base' recursively inherits from 'top' then we should set * base->inherits_from to top->inherits_from after 'top' and all * other intermediate nodes have been dropped. * If 'top' is an implicit node (e.g. "commit_top") we should skip * it because no one inherits from it. We use explicit_top for that. */ - while (explicit_top && explicit_top->implicit) { - explicit_top = backing_bs(explicit_top); - } + explicit_top = bdrv_skip_implicit_filters(explicit_top); update_inherits_from = bdrv_inherits_from_recursive(base, explicit_top); /* success - we can delete the intermediate states, and link top->base */ @@ -4888,33 +4944,36 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, backing_file_str = base->filename; } - QLIST_FOREACH_SAFE(c, &top->parents, next_parent, next) { - /* Check whether we are allowed to switch c from top to base */ - GSList *ignore_children = g_slist_prepend(NULL, c); - ret = bdrv_check_update_perm(base, NULL, c->perm, c->shared_perm, - ignore_children, NULL, &local_err); - g_slist_free(ignore_children); - if (ret < 0) { - error_report_err(local_err); - goto exit; - } + QLIST_FOREACH(c, &top->parents, next_parent) { + updated_children = g_slist_prepend(updated_children, c); + } + + bdrv_replace_node_common(top, base, false, &local_err); + if (local_err) { + error_report_err(local_err); + goto exit; + } + + for (p = updated_children; p; p = p->next) { + c = p->data; - /* If so, update the backing file path in the image file */ if (c->klass->update_filename) { ret = c->klass->update_filename(c, base, backing_file_str, &local_err); if (ret < 0) { - bdrv_abort_perm_update(base); + /* + * TODO: Actually, we want to rollback all previous iterations + * of this loop, and (which is almost impossible) previous + * bdrv_replace_node()... + * + * Note, that c->klass->update_filename may lead to permission + * update, so it's a bad idea to call it inside permission + * update transaction of bdrv_replace_node. + */ error_report_err(local_err); goto exit; } } - - /* Do the actual switch in the in-memory graph. - * Completes bdrv_check_update_perm() transaction internally. */ - bdrv_ref(base); - bdrv_replace_child(c, base); - bdrv_unref(top); } if (update_inherits_from) { @@ -4928,6 +4987,31 @@ exit: return ret; } +/** + * Implementation of BlockDriver.bdrv_get_allocated_file_size() that + * sums the size of all data-bearing children. (This excludes backing + * children.) + */ +static int64_t bdrv_sum_allocated_file_size(BlockDriverState *bs) +{ + BdrvChild *child; + int64_t child_size, sum = 0; + + QLIST_FOREACH(child, &bs->children, next) { + if (child->role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA | + BDRV_CHILD_FILTERED)) + { + child_size = bdrv_get_allocated_file_size(child->bs); + if (child_size < 0) { + return child_size; + } + sum += child_size; + } + } + + return sum; +} + /** * Length of a allocated file in bytes. Sparse files are counted by actual * allocated space. Return < 0 if error or unknown. @@ -4941,10 +5025,21 @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs) if (drv->bdrv_get_allocated_file_size) { return drv->bdrv_get_allocated_file_size(bs); } - if (bs->file) { - return bdrv_get_allocated_file_size(bs->file->bs); + + if (drv->bdrv_file_open) { + /* + * Protocol drivers default to -ENOTSUP (most of their data is + * not stored in any of their children (if they even have any), + * so there is no generic way to figure it out). + */ + return -ENOTSUP; + } else if (drv->is_filter) { + /* Filter drivers default to the size of their filtered child */ + return bdrv_get_allocated_file_size(bdrv_filter_bs(bs)); + } else { + /* Other drivers default to summing their children's sizes */ + return bdrv_sum_allocated_file_size(bs); } - return -ENOTSUP; } /* @@ -5009,8 +5104,13 @@ int64_t bdrv_getlength(BlockDriverState *bs) { int64_t ret = bdrv_nb_sectors(bs); - ret = ret > INT64_MAX / BDRV_SECTOR_SIZE ? -EFBIG : ret; - return ret < 0 ? ret : ret * BDRV_SECTOR_SIZE; + if (ret < 0) { + return ret; + } + if (ret > INT64_MAX / BDRV_SECTOR_SIZE) { + return -EFBIG; + } + return ret * BDRV_SECTOR_SIZE; } /* return 0 as number of sectors if no device present or error */ @@ -5026,12 +5126,27 @@ bool bdrv_is_sg(BlockDriverState *bs) return bs->sg; } -bool bdrv_is_encrypted(BlockDriverState *bs) +/** + * Return whether the given node supports compressed writes. + */ +bool bdrv_supports_compressed_writes(BlockDriverState *bs) { - if (bs->backing && bs->backing->bs->encrypted) { - return true; + BlockDriverState *filtered; + + if (!bs->drv || !block_driver_can_compress(bs->drv)) { + return false; } - return bs->encrypted; + + filtered = bdrv_filter_bs(bs); + if (filtered) { + /* + * Filters can only forward compressed writes, so we have to + * check the child. + */ + return bdrv_supports_compressed_writes(filtered); + } + + return true; } const char *bdrv_get_format_name(BlockDriverState *bs) @@ -5123,7 +5238,7 @@ BlockDriverState *bdrv_find_node(const char *node_name) BlockDeviceInfoList *bdrv_named_nodes_list(bool flat, Error **errp) { - BlockDeviceInfoList *list, *entry; + BlockDeviceInfoList *list; BlockDriverState *bs; list = NULL; @@ -5133,22 +5248,12 @@ BlockDeviceInfoList *bdrv_named_nodes_list(bool flat, qapi_free_BlockDeviceInfoList(list); return NULL; } - entry = g_malloc0(sizeof(*entry)); - entry->value = info; - entry->next = list; - list = entry; + QAPI_LIST_PREPEND(list, info); } return list; } -#define QAPI_LIST_ADD(list, element) do { \ - typeof(list) _tmp = g_new(typeof(*(list)), 1); \ - _tmp->value = (element); \ - _tmp->next = (list); \ - (list) = _tmp; \ -} while (0) - typedef struct XDbgBlockGraphConstructor { XDbgBlockGraph *graph; GHashTable *graph_nodes; @@ -5203,7 +5308,7 @@ static void xdbg_graph_add_node(XDbgBlockGraphConstructor *gr, void *node, n->type = type; n->name = g_strdup(name); - QAPI_LIST_ADD(gr->graph->nodes, n); + QAPI_LIST_PREPEND(gr->graph->nodes, n); } static void xdbg_graph_add_edge(XDbgBlockGraphConstructor *gr, void *parent, @@ -5222,14 +5327,14 @@ static void xdbg_graph_add_edge(XDbgBlockGraphConstructor *gr, void *parent, uint64_t flag = bdrv_qapi_perm_to_blk_perm(qapi_perm); if (flag & child->perm) { - QAPI_LIST_ADD(edge->perm, qapi_perm); + QAPI_LIST_PREPEND(edge->perm, qapi_perm); } if (flag & child->shared_perm) { - QAPI_LIST_ADD(edge->shared_perm, qapi_perm); + QAPI_LIST_PREPEND(edge->shared_perm, qapi_perm); } } - QAPI_LIST_ADD(gr->graph->edges, edge); + QAPI_LIST_PREPEND(gr->graph->edges, edge); } @@ -5316,7 +5421,7 @@ BlockDriverState *bdrv_lookup_bs(const char *device, bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base) { while (top && top != base) { - top = backing_bs(top); + top = bdrv_filter_or_cow_bs(top); } return top != NULL; @@ -5388,41 +5493,30 @@ int bdrv_has_zero_init_1(BlockDriverState *bs) int bdrv_has_zero_init(BlockDriverState *bs) { + BlockDriverState *filtered; + if (!bs->drv) { return 0; } /* If BS is a copy on write image, it is initialized to the contents of the base image, which may not be zeroes. */ - if (bs->backing) { + if (bdrv_cow_child(bs)) { return 0; } if (bs->drv->bdrv_has_zero_init) { return bs->drv->bdrv_has_zero_init(bs); } - if (bs->file && bs->drv->is_filter) { - return bdrv_has_zero_init(bs->file->bs); + + filtered = bdrv_filter_bs(bs); + if (filtered) { + return bdrv_has_zero_init(filtered); } /* safe default */ return 0; } -bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs) -{ - BlockDriverInfo bdi; - - if (bs->backing) { - return false; - } - - if (bdrv_get_info(bs, &bdi) == 0) { - return bdi.unallocated_blocks_are_zero; - } - - return false; -} - bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs) { if (!(bs->open_flags & BDRV_O_UNMAP)) { @@ -5446,8 +5540,9 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) return -ENOMEDIUM; } if (!drv->bdrv_get_info) { - if (bs->file && drv->is_filter) { - return bdrv_get_info(bs->file->bs, bdi); + BlockDriverState *filtered = bdrv_filter_bs(bs); + if (filtered) { + return bdrv_get_info(filtered, bdi); } return -ENOTSUP; } @@ -5486,17 +5581,7 @@ void bdrv_debug_event(BlockDriverState *bs, BlkdebugEvent event) static BlockDriverState *bdrv_find_debug_node(BlockDriverState *bs) { while (bs && bs->drv && !bs->drv->bdrv_debug_breakpoint) { - if (bs->file) { - bs = bs->file->bs; - continue; - } - - if (bs->drv->is_filter && bs->backing) { - bs = bs->backing->bs; - continue; - } - - break; + bs = bdrv_primary_bs(bs); } if (bs && bs->drv && bs->drv->bdrv_debug_breakpoint) { @@ -5531,7 +5616,7 @@ int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag) int bdrv_debug_resume(BlockDriverState *bs, const char *tag) { while (bs && (!bs->drv || !bs->drv->bdrv_debug_resume)) { - bs = bs->file ? bs->file->bs : NULL; + bs = bdrv_primary_bs(bs); } if (bs && bs->drv && bs->drv->bdrv_debug_resume) { @@ -5544,7 +5629,7 @@ int bdrv_debug_resume(BlockDriverState *bs, const char *tag) bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag) { while (bs && bs->drv && !bs->drv->bdrv_debug_is_suspended) { - bs = bs->file ? bs->file->bs : NULL; + bs = bdrv_primary_bs(bs); } if (bs && bs->drv && bs->drv->bdrv_debug_is_suspended) { @@ -5565,8 +5650,10 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, char *backing_file_full = NULL; char *filename_tmp = NULL; int is_protocol = 0; + bool filenames_refreshed = false; BlockDriverState *curr_bs = NULL; BlockDriverState *retval = NULL; + BlockDriverState *bs_below; if (!bs || !bs->drv || !backing_file) { return NULL; @@ -5577,15 +5664,47 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, is_protocol = path_has_protocol(backing_file); - for (curr_bs = bs; curr_bs->backing; curr_bs = curr_bs->backing->bs) { + /* + * Being largely a legacy function, skip any filters here + * (because filters do not have normal filenames, so they cannot + * match anyway; and allowing json:{} filenames is a bit out of + * scope). + */ + for (curr_bs = bdrv_skip_filters(bs); + bdrv_cow_child(curr_bs) != NULL; + curr_bs = bs_below) + { + bs_below = bdrv_backing_chain_next(curr_bs); + + if (bdrv_backing_overridden(curr_bs)) { + /* + * If the backing file was overridden, we can only compare + * directly against the backing node's filename. + */ + + if (!filenames_refreshed) { + /* + * This will automatically refresh all of the + * filenames in the rest of the backing chain, so we + * only need to do this once. + */ + bdrv_refresh_filename(bs_below); + filenames_refreshed = true; + } - /* If either of the filename paths is actually a protocol, then - * compare unmodified paths; otherwise make paths relative */ - if (is_protocol || path_has_protocol(curr_bs->backing_file)) { + if (strcmp(backing_file, bs_below->filename) == 0) { + retval = bs_below; + break; + } + } else if (is_protocol || path_has_protocol(curr_bs->backing_file)) { + /* + * If either of the filename paths is actually a protocol, then + * compare unmodified paths; otherwise make paths relative. + */ char *backing_file_full_ret; if (strcmp(backing_file, curr_bs->backing_file) == 0) { - retval = curr_bs->backing->bs; + retval = bs_below; break; } /* Also check against the full backing filename for the image */ @@ -5595,7 +5714,7 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, bool equal = strcmp(backing_file, backing_file_full_ret) == 0; g_free(backing_file_full_ret); if (equal) { - retval = curr_bs->backing->bs; + retval = bs_below; break; } } @@ -5621,7 +5740,7 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, g_free(filename_tmp); if (strcmp(backing_file_full, filename_full) == 0) { - retval = curr_bs->backing->bs; + retval = bs_below; break; } } @@ -5643,8 +5762,7 @@ void bdrv_init_with_whitelist(void) bdrv_init(); } -static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, - Error **errp) +int coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp) { BdrvChild *child, *parent; uint64_t perm, shared_perm; @@ -5653,14 +5771,14 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, BdrvDirtyBitmap *bm; if (!bs->drv) { - return; + return -ENOMEDIUM; } QLIST_FOREACH(child, &bs->children, next) { bdrv_co_invalidate_cache(child->bs, &local_err); if (local_err) { error_propagate(errp, local_err); - return; + return -EINVAL; } } @@ -5680,11 +5798,11 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, if (bs->open_flags & BDRV_O_INACTIVE) { bs->open_flags &= ~BDRV_O_INACTIVE; bdrv_get_cumulative_perm(bs, &perm, &shared_perm); - ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, NULL, &local_err); + ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, NULL, errp); if (ret < 0) { + bdrv_abort_perm_update(bs); bs->open_flags |= BDRV_O_INACTIVE; - error_propagate(errp, local_err); - return; + return ret; } bdrv_set_perm(bs, perm, shared_perm); @@ -5693,7 +5811,7 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, if (local_err) { bs->open_flags |= BDRV_O_INACTIVE; error_propagate(errp, local_err); - return; + return -EINVAL; } } @@ -5705,7 +5823,7 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, if (ret < 0) { bs->open_flags |= BDRV_O_INACTIVE; error_setg_errno(errp, -ret, "Could not refresh total sector count"); - return; + return ret; } } @@ -5715,59 +5833,27 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, if (local_err) { bs->open_flags |= BDRV_O_INACTIVE; error_propagate(errp, local_err); - return; + return -EINVAL; } } } -} - -typedef struct InvalidateCacheCo { - BlockDriverState *bs; - Error **errp; - bool done; -} InvalidateCacheCo; - -static void coroutine_fn bdrv_invalidate_cache_co_entry(void *opaque) -{ - InvalidateCacheCo *ico = opaque; - bdrv_co_invalidate_cache(ico->bs, ico->errp); - ico->done = true; - aio_wait_kick(); -} - -void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp) -{ - Coroutine *co; - InvalidateCacheCo ico = { - .bs = bs, - .done = false, - .errp = errp - }; - if (qemu_in_coroutine()) { - /* Fast-path if already in coroutine context */ - bdrv_invalidate_cache_co_entry(&ico); - } else { - co = qemu_coroutine_create(bdrv_invalidate_cache_co_entry, &ico); - bdrv_coroutine_enter(bs, co); - BDRV_POLL_WHILE(bs, !ico.done); - } + return 0; } void bdrv_invalidate_cache_all(Error **errp) { BlockDriverState *bs; - Error *local_err = NULL; BdrvNextIterator it; for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) { AioContext *aio_context = bdrv_get_aio_context(bs); + int ret; aio_context_acquire(aio_context); - bdrv_invalidate_cache(bs, &local_err); + ret = bdrv_invalidate_cache(bs, errp); aio_context_release(aio_context); - if (local_err) { - error_propagate(errp, local_err); + if (ret < 0) { bdrv_next_cleanup(&it); return; } @@ -6078,8 +6164,7 @@ void bdrv_img_create(const char *filename, const char *fmt, /* Parse -o options */ if (options) { - qemu_opts_do_parse(opts, options, NULL, &local_err); - if (local_err) { + if (!qemu_opts_do_parse(opts, options, NULL, errp)) { goto out; } } @@ -6092,8 +6177,8 @@ void bdrv_img_create(const char *filename, const char *fmt, } if (base_filename) { - qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, base_filename, &local_err); - if (local_err) { + if (!qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, base_filename, + NULL)) { error_setg(errp, "Backing file not supported for file format '%s'", fmt); goto out; @@ -6101,8 +6186,7 @@ void bdrv_img_create(const char *filename, const char *fmt, } if (base_fmt) { - qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, base_fmt, &local_err); - if (local_err) { + if (!qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, base_fmt, NULL)) { error_setg(errp, "Backing file format not supported for file " "format '%s'", fmt); goto out; @@ -6116,6 +6200,10 @@ void bdrv_img_create(const char *filename, const char *fmt, "same filename as the backing file"); goto out; } + if (backing_file[0] == '\0') { + error_setg(errp, "Expected backing file name, got empty string"); + goto out; + } } backing_fmt = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT); @@ -6150,18 +6238,30 @@ void bdrv_img_create(const char *filename, const char *fmt, bs = bdrv_open(full_backing, NULL, backing_options, back_flags, &local_err); g_free(full_backing); - if (!bs && size != -1) { - /* Couldn't open BS, but we have a size, so it's nonfatal */ - warn_reportf_err(local_err, - "Could not verify backing image. " - "This may become an error in future versions.\n"); - local_err = NULL; - } else if (!bs) { - /* Couldn't open bs, do not have size */ - error_append_hint(&local_err, - "Could not open backing image to determine size.\n"); + if (!bs) { + error_append_hint(&local_err, "Could not open backing image.\n"); goto out; } else { + if (!backing_fmt) { + warn_report("Deprecated use of backing file without explicit " + "backing format (detected format of %s)", + bs->drv->format_name); + if (bs->drv != &bdrv_raw) { + /* + * A probe of raw deserves the most attention: + * leaving the backing format out of the image + * will ensure bs->probed is set (ensuring we + * don't accidentally commit into the backing + * file), and allow more spots to warn the users + * to fix their toolchain when opening this image + * later. For other images, we can safely record + * the format that we probed. + */ + backing_fmt = bs->drv->format_name; + qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, backing_fmt, + NULL); + } + } if (size == -1) { /* Opened BS, have no size */ size = bdrv_getlength(bs); @@ -6175,7 +6275,12 @@ void bdrv_img_create(const char *filename, const char *fmt, } bdrv_unref(bs); } - } /* (backing_file && !(flags & BDRV_O_NO_BACKING)) */ + /* (backing_file && !(flags & BDRV_O_NO_BACKING)) */ + } else if (backing_file && !backing_fmt) { + warn_report("Deprecated use of unopened backing file without " + "explicit backing format, use of this image requires " + "potentially unsafe format probing"); + } if (size == -1) { error_setg(errp, "Image creation needs a size parameter"); @@ -6186,6 +6291,7 @@ void bdrv_img_create(const char *filename, const char *fmt, printf("Formatting '%s', fmt=%s ", filename, fmt); qemu_opts_print(opts, " "); puts(""); + fflush(stdout); } ret = bdrv_create(drv, filename, opts, &local_err); @@ -6215,6 +6321,56 @@ AioContext *bdrv_get_aio_context(BlockDriverState *bs) return bs ? bs->aio_context : qemu_get_aio_context(); } +AioContext *coroutine_fn bdrv_co_enter(BlockDriverState *bs) +{ + Coroutine *self = qemu_coroutine_self(); + AioContext *old_ctx = qemu_coroutine_get_aio_context(self); + AioContext *new_ctx; + + /* + * Increase bs->in_flight to ensure that this operation is completed before + * moving the node to a different AioContext. Read new_ctx only afterwards. + */ + bdrv_inc_in_flight(bs); + + new_ctx = bdrv_get_aio_context(bs); + aio_co_reschedule_self(new_ctx); + return old_ctx; +} + +void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx) +{ + aio_co_reschedule_self(old_ctx); + bdrv_dec_in_flight(bs); +} + +void coroutine_fn bdrv_co_lock(BlockDriverState *bs) +{ + AioContext *ctx = bdrv_get_aio_context(bs); + + /* In the main thread, bs->aio_context won't change concurrently */ + assert(qemu_get_current_aio_context() == qemu_get_aio_context()); + + /* + * We're in coroutine context, so we already hold the lock of the main + * loop AioContext. Don't lock it twice to avoid deadlocks. + */ + assert(qemu_in_coroutine()); + if (ctx != qemu_get_aio_context()) { + aio_context_acquire(ctx); + } +} + +void coroutine_fn bdrv_co_unlock(BlockDriverState *bs) +{ + AioContext *ctx = bdrv_get_aio_context(bs); + + assert(qemu_in_coroutine()); + if (ctx != qemu_get_aio_context()) { + aio_context_release(ctx); + } +} + void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co) { aio_co_enter(bdrv_get_aio_context(bs), co); @@ -6482,6 +6638,7 @@ void bdrv_remove_aio_context_notifier(BlockDriverState *bs, int bdrv_amend_options(BlockDriverState *bs, QemuOpts *opts, BlockDriverAmendStatusCB *status_cb, void *cb_opaque, + bool force, Error **errp) { if (!bs->drv) { @@ -6493,7 +6650,8 @@ int bdrv_amend_options(BlockDriverState *bs, QemuOpts *opts, bs->drv->format_name); return -ENOTSUP; } - return bs->drv->bdrv_amend_options(bs, opts, status_cb, cb_opaque, errp); + return bs->drv->bdrv_amend_options(bs, opts, status_cb, + cb_opaque, force, errp); } /* @@ -6511,6 +6669,8 @@ int bdrv_amend_options(BlockDriverState *bs, QemuOpts *opts, bool bdrv_recurse_can_replace(BlockDriverState *bs, BlockDriverState *to_replace) { + BlockDriverState *filtered; + if (!bs || !bs->drv) { return false; } @@ -6525,9 +6685,9 @@ bool bdrv_recurse_can_replace(BlockDriverState *bs, } /* For filters without an own implementation, we can recurse on our own */ - if (bs->drv->is_filter) { - BdrvChild *child = bs->file ?: bs->backing; - return bdrv_recurse_can_replace(child->bs, to_replace); + filtered = bdrv_filter_bs(bs); + if (filtered) { + return bdrv_recurse_can_replace(filtered, to_replace); } /* Safe default */ @@ -6678,7 +6838,7 @@ static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs) /* Note: This function may return false positives; it may return true * even if opening the backing file specified by bs's image header * would result in exactly bs->backing. */ -static bool bdrv_backing_overridden(BlockDriverState *bs) +bool bdrv_backing_overridden(BlockDriverState *bs) { if (bs->backing) { return strcmp(bs->auto_backing_file, @@ -6706,6 +6866,7 @@ void bdrv_refresh_filename(BlockDriverState *bs) { BlockDriver *drv = bs->drv; BdrvChild *child; + BlockDriverState *primary_child_bs; QDict *opts; bool backing_overridden; bool generate_json_filename; /* Whether our default implementation should @@ -6775,20 +6936,30 @@ void bdrv_refresh_filename(BlockDriverState *bs) qobject_unref(bs->full_open_options); bs->full_open_options = opts; + primary_child_bs = bdrv_primary_bs(bs); + if (drv->bdrv_refresh_filename) { /* Obsolete information is of no use here, so drop the old file name * information before refreshing it */ bs->exact_filename[0] = '\0'; drv->bdrv_refresh_filename(bs); - } else if (bs->file) { - /* Try to reconstruct valid information from the underlying file */ + } else if (primary_child_bs) { + /* + * Try to reconstruct valid information from the underlying + * file -- this only works for format nodes (filter nodes + * cannot be probed and as such must be selected by the user + * either through an options dict, or through a special + * filename which the filter driver must construct in its + * .bdrv_refresh_filename() implementation). + */ bs->exact_filename[0] = '\0'; /* * We can use the underlying file's filename if: * - it has a filename, + * - the current BDS is not a filter, * - the file is a protocol BDS, and * - opening that file (as this BDS's format) will automatically create * the BDS tree we have right now, that is: @@ -6797,11 +6968,11 @@ void bdrv_refresh_filename(BlockDriverState *bs) * - no non-file child of this BDS has been overridden by the user * Both of these conditions are represented by generate_json_filename. */ - if (bs->file->bs->exact_filename[0] && - bs->file->bs->drv->bdrv_file_open && - !generate_json_filename) + if (primary_child_bs->exact_filename[0] && + primary_child_bs->drv->bdrv_file_open && + !drv->is_filter && !generate_json_filename) { - strcpy(bs->exact_filename, bs->file->bs->exact_filename); + strcpy(bs->exact_filename, primary_child_bs->exact_filename); } } @@ -6809,8 +6980,11 @@ void bdrv_refresh_filename(BlockDriverState *bs) pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename); } else { QString *json = qobject_to_json(QOBJECT(bs->full_open_options)); - snprintf(bs->filename, sizeof(bs->filename), "json:%s", - qstring_get_str(json)); + if (snprintf(bs->filename, sizeof(bs->filename), "json:%s", + qstring_get_str(json)) >= sizeof(bs->filename)) { + /* Give user a hint if we truncated things. */ + strcpy(bs->filename + sizeof(bs->filename) - 4, "..."); + } qobject_unref(json); } } @@ -6818,6 +6992,7 @@ void bdrv_refresh_filename(BlockDriverState *bs) char *bdrv_dirname(BlockDriverState *bs, Error **errp) { BlockDriver *drv = bs->drv; + BlockDriverState *child_bs; if (!drv) { error_setg(errp, "Node '%s' is ejected", bs->node_name); @@ -6828,8 +7003,9 @@ char *bdrv_dirname(BlockDriverState *bs, Error **errp) return drv->bdrv_dirname(bs, errp); } - if (bs->file) { - return bdrv_dirname(bs->file->bs, errp); + child_bs = bdrv_primary_bs(bs); + if (child_bs) { + return bdrv_dirname(child_bs, errp); } bdrv_refresh_filename(bs); @@ -6913,3 +7089,156 @@ int bdrv_make_empty(BdrvChild *c, Error **errp) return 0; } + +/* + * Return the child that @bs acts as an overlay for, and from which data may be + * copied in COW or COR operations. Usually this is the backing file. + */ +BdrvChild *bdrv_cow_child(BlockDriverState *bs) +{ + if (!bs || !bs->drv) { + return NULL; + } + + if (bs->drv->is_filter) { + return NULL; + } + + if (!bs->backing) { + return NULL; + } + + assert(bs->backing->role & BDRV_CHILD_COW); + return bs->backing; +} + +/* + * If @bs acts as a filter for exactly one of its children, return + * that child. + */ +BdrvChild *bdrv_filter_child(BlockDriverState *bs) +{ + BdrvChild *c; + + if (!bs || !bs->drv) { + return NULL; + } + + if (!bs->drv->is_filter) { + return NULL; + } + + /* Only one of @backing or @file may be used */ + assert(!(bs->backing && bs->file)); + + c = bs->backing ?: bs->file; + if (!c) { + return NULL; + } + + assert(c->role & BDRV_CHILD_FILTERED); + return c; +} + +/* + * Return either the result of bdrv_cow_child() or bdrv_filter_child(), + * whichever is non-NULL. + * + * Return NULL if both are NULL. + */ +BdrvChild *bdrv_filter_or_cow_child(BlockDriverState *bs) +{ + BdrvChild *cow_child = bdrv_cow_child(bs); + BdrvChild *filter_child = bdrv_filter_child(bs); + + /* Filter nodes cannot have COW backing files */ + assert(!(cow_child && filter_child)); + + return cow_child ?: filter_child; +} + +/* + * Return the primary child of this node: For filters, that is the + * filtered child. For other nodes, that is usually the child storing + * metadata. + * (A generally more helpful description is that this is (usually) the + * child that has the same filename as @bs.) + * + * Drivers do not necessarily have a primary child; for example quorum + * does not. + */ +BdrvChild *bdrv_primary_child(BlockDriverState *bs) +{ + BdrvChild *c, *found = NULL; + + QLIST_FOREACH(c, &bs->children, next) { + if (c->role & BDRV_CHILD_PRIMARY) { + assert(!found); + found = c; + } + } + + return found; +} + +static BlockDriverState *bdrv_do_skip_filters(BlockDriverState *bs, + bool stop_on_explicit_filter) +{ + BdrvChild *c; + + if (!bs) { + return NULL; + } + + while (!(stop_on_explicit_filter && !bs->implicit)) { + c = bdrv_filter_child(bs); + if (!c) { + /* + * A filter that is embedded in a working block graph must + * have a child. Assert this here so this function does + * not return a filter node that is not expected by the + * caller. + */ + assert(!bs->drv || !bs->drv->is_filter); + break; + } + bs = c->bs; + } + /* + * Note that this treats nodes with bs->drv == NULL as not being + * filters (bs->drv == NULL should be replaced by something else + * anyway). + * The advantage of this behavior is that this function will thus + * always return a non-NULL value (given a non-NULL @bs). + */ + + return bs; +} + +/* + * Return the first BDS that has not been added implicitly or that + * does not have a filtered child down the chain starting from @bs + * (including @bs itself). + */ +BlockDriverState *bdrv_skip_implicit_filters(BlockDriverState *bs) +{ + return bdrv_do_skip_filters(bs, true); +} + +/* + * Return the first BDS that does not have a filtered child down the + * chain starting from @bs (including @bs itself). + */ +BlockDriverState *bdrv_skip_filters(BlockDriverState *bs) +{ + return bdrv_do_skip_filters(bs, false); +} + +/* + * For a backing chain, return the first non-filter backing image of + * the first non-filter image. + */ +BlockDriverState *bdrv_backing_chain_next(BlockDriverState *bs) +{ + return bdrv_skip_filters(bdrv_cow_bs(bdrv_skip_filters(bs))); +} diff --git a/block/Makefile.objs b/block/Makefile.objs deleted file mode 100644 index 3635b6b4c18660e435598b0a4d43401041d7701b..0000000000000000000000000000000000000000 --- a/block/Makefile.objs +++ /dev/null @@ -1,76 +0,0 @@ -block-obj-y += raw-format.o vmdk.o vpc.o -block-obj-$(CONFIG_QCOW1) += qcow.o -block-obj-$(CONFIG_VDI) += vdi.o -block-obj-$(CONFIG_CLOOP) += cloop.o -block-obj-$(CONFIG_BOCHS) += bochs.o -block-obj-$(CONFIG_VVFAT) += vvfat.o -block-obj-$(CONFIG_DMG) += dmg.o - -block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o qcow2-bitmap.o qcow2-threads.o -block-obj-$(CONFIG_QED) += qed.o qed-l2-cache.o qed-table.o qed-cluster.o -block-obj-$(CONFIG_QED) += qed-check.o -block-obj-y += vhdx.o vhdx-endian.o vhdx-log.o -block-obj-y += quorum.o -block-obj-y += blkdebug.o blkverify.o blkreplay.o -block-obj-$(CONFIG_PARALLELS) += parallels.o -block-obj-y += blklogwrites.o -block-obj-y += block-backend.o snapshot.o qapi.o -block-obj-$(CONFIG_WIN32) += file-win32.o win32-aio.o -block-obj-$(CONFIG_POSIX) += file-posix.o -block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o -block-obj-$(CONFIG_LINUX_IO_URING) += io_uring.o -block-obj-y += null.o mirror.o commit.o io.o create.o -block-obj-y += throttle-groups.o -block-obj-$(CONFIG_LINUX) += nvme.o - -block-obj-y += nbd.o -block-obj-$(CONFIG_SHEEPDOG) += sheepdog.o -block-obj-$(CONFIG_LIBISCSI) += iscsi.o -block-obj-$(if $(CONFIG_LIBISCSI),y,n) += iscsi-opts.o -block-obj-$(CONFIG_LIBNFS) += nfs.o -block-obj-$(CONFIG_CURL) += curl.o -block-obj-$(CONFIG_RBD) += rbd.o -block-obj-$(CONFIG_GLUSTERFS) += gluster.o -block-obj-$(CONFIG_VXHS) += vxhs.o -block-obj-$(CONFIG_LIBSSH) += ssh.o -block-obj-y += accounting.o dirty-bitmap.o -block-obj-y += write-threshold.o -block-obj-y += backup.o -block-obj-$(CONFIG_REPLICATION) += replication.o -block-obj-y += throttle.o copy-on-read.o -block-obj-y += block-copy.o - -block-obj-y += crypto.o - -block-obj-y += aio_task.o -block-obj-y += backup-top.o -block-obj-y += filter-compress.o -common-obj-y += monitor/ - -block-obj-y += stream.o - -common-obj-y += qapi-sysemu.o - -nfs.o-libs := $(LIBNFS_LIBS) -iscsi.o-cflags := $(LIBISCSI_CFLAGS) -iscsi.o-libs := $(LIBISCSI_LIBS) -curl.o-cflags := $(CURL_CFLAGS) -curl.o-libs := $(CURL_LIBS) -rbd.o-cflags := $(RBD_CFLAGS) -rbd.o-libs := $(RBD_LIBS) -gluster.o-cflags := $(GLUSTERFS_CFLAGS) -gluster.o-libs := $(GLUSTERFS_LIBS) -vxhs.o-libs := $(VXHS_LIBS) -ssh.o-cflags := $(LIBSSH_CFLAGS) -ssh.o-libs := $(LIBSSH_LIBS) -block-obj-dmg-bz2-$(CONFIG_BZIP2) += dmg-bz2.o -block-obj-$(if $(CONFIG_DMG),m,n) += $(block-obj-dmg-bz2-y) -dmg-bz2.o-libs := $(BZIP2_LIBS) -block-obj-$(if $(CONFIG_LZFSE),m,n) += dmg-lzfse.o -dmg-lzfse.o-libs := $(LZFSE_LIBS) -qcow.o-libs := -lz -linux-aio.o-libs := -laio -io_uring.o-cflags := $(LINUX_IO_URING_CFLAGS) -io_uring.o-libs := $(LINUX_IO_URING_LIBS) -parallels.o-cflags := $(LIBXML2_CFLAGS) -parallels.o-libs := $(LIBXML2_LIBS) diff --git a/block/amend.c b/block/amend.c new file mode 100644 index 0000000000000000000000000000000000000000..392df9ef83f5dd72cb67bfe73e1208b5928934e1 --- /dev/null +++ b/block/amend.c @@ -0,0 +1,117 @@ +/* + * Block layer code related to image options amend + * + * Copyright (c) 2018 Kevin Wolf + * Copyright (c) 2020 Red Hat. Inc + * + * Heavily based on create.c + * + * 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 "block/block_int.h" +#include "qemu/job.h" +#include "qemu/main-loop.h" +#include "qapi/qapi-commands-block-core.h" +#include "qapi/qapi-visit-block-core.h" +#include "qapi/clone-visitor.h" +#include "qapi/error.h" + +typedef struct BlockdevAmendJob { + Job common; + BlockdevAmendOptions *opts; + BlockDriverState *bs; + bool force; +} BlockdevAmendJob; + +static int coroutine_fn blockdev_amend_run(Job *job, Error **errp) +{ + BlockdevAmendJob *s = container_of(job, BlockdevAmendJob, common); + int ret; + + job_progress_set_remaining(&s->common, 1); + ret = s->bs->drv->bdrv_co_amend(s->bs, s->opts, s->force, errp); + job_progress_update(&s->common, 1); + qapi_free_BlockdevAmendOptions(s->opts); + return ret; +} + +static const JobDriver blockdev_amend_job_driver = { + .instance_size = sizeof(BlockdevAmendJob), + .job_type = JOB_TYPE_AMEND, + .run = blockdev_amend_run, +}; + +void qmp_x_blockdev_amend(const char *job_id, + const char *node_name, + BlockdevAmendOptions *options, + bool has_force, + bool force, + Error **errp) +{ + BlockdevAmendJob *s; + const char *fmt = BlockdevDriver_str(options->driver); + BlockDriver *drv = bdrv_find_format(fmt); + BlockDriverState *bs; + + bs = bdrv_lookup_bs(NULL, node_name, errp); + if (!bs) { + return; + } + + if (!drv) { + error_setg(errp, "Block driver '%s' not found or not supported", fmt); + return; + } + + /* + * If the driver is in the schema, we know that it exists. But it may not + * be whitelisted. + */ + if (bdrv_uses_whitelist() && !bdrv_is_whitelisted(drv, false)) { + error_setg(errp, "Driver is not whitelisted"); + return; + } + + if (bs->drv != drv) { + error_setg(errp, + "x-blockdev-amend doesn't support changing the block driver"); + return; + } + + /* Error out if the driver doesn't support .bdrv_co_amend */ + if (!drv->bdrv_co_amend) { + error_setg(errp, "Driver does not support x-blockdev-amend"); + return; + } + + /* Create the block job */ + s = job_create(job_id, &blockdev_amend_job_driver, NULL, + bdrv_get_aio_context(bs), JOB_DEFAULT | JOB_MANUAL_DISMISS, + NULL, NULL, errp); + if (!s) { + return; + } + + s->bs = bs, + s->opts = QAPI_CLONE(BlockdevAmendOptions, options), + s->force = has_force ? force : false; + job_start(&s->common); +} diff --git a/block/backup-top.c b/block/backup-top.c index af2f20f34698dc9ba0f2227e7055b5a604d5e245..fe6883cc970965ff1acf3c17cbbde98355ce0486 100644 --- a/block/backup-top.c +++ b/block/backup-top.c @@ -175,8 +175,6 @@ BlockDriver bdrv_backup_top_filter = { .bdrv_co_pdiscard = backup_top_co_pdiscard, .bdrv_co_flush = backup_top_co_flush, - .bdrv_co_block_status = bdrv_co_block_status_from_backing, - .bdrv_refresh_filename = backup_top_refresh_filename, .bdrv_child_perm = backup_top_child_perm, @@ -281,7 +279,7 @@ void bdrv_backup_top_drop(BlockDriverState *bs) s->active = false; bdrv_child_refresh_perms(bs, bs->backing, &error_abort); - bdrv_replace_node(bs, backing_bs(bs), &error_abort); + bdrv_replace_node(bs, bs->backing->bs, &error_abort); bdrv_set_backing_hd(bs, NULL, &error_abort); bdrv_drained_end(bs); diff --git a/block/backup.c b/block/backup.c index 4f13bb20a5ef10b70c1a7181c6f480c820eee51c..9afa0bf3b41229536a5b9e67df8d2965c734406f 100644 --- a/block/backup.c +++ b/block/backup.c @@ -297,6 +297,7 @@ static int64_t backup_calculate_cluster_size(BlockDriverState *target, { int ret; BlockDriverInfo bdi; + bool target_does_cow = bdrv_backing_chain_next(target); /* * If there is no backing file on the target, we cannot rely on COW if our @@ -304,7 +305,7 @@ static int64_t backup_calculate_cluster_size(BlockDriverState *target, * targets with a backing file, try to avoid COW if possible. */ ret = bdrv_get_info(target, &bdi); - if (ret == -ENOTSUP && !target->backing) { + if (ret == -ENOTSUP && !target_does_cow) { /* Cluster size is not defined */ warn_report("The target block device doesn't provide " "information about the block size and it doesn't have a " @@ -313,14 +314,14 @@ static int64_t backup_calculate_cluster_size(BlockDriverState *target, "this default, the backup may be unusable", BACKUP_CLUSTER_SIZE_DEFAULT); return BACKUP_CLUSTER_SIZE_DEFAULT; - } else if (ret < 0 && !target->backing) { + } else if (ret < 0 && !target_does_cow) { error_setg_errno(errp, -ret, "Couldn't determine the cluster size of the target image, " "which has no backing file"); error_append_hint(errp, "Aborting, since this may create an unusable destination image\n"); return ret; - } else if (ret < 0 && target->backing) { + } else if (ret < 0 && target_does_cow) { /* Not fatal; just trudge on ahead. */ return BACKUP_CLUSTER_SIZE_DEFAULT; } @@ -371,7 +372,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, return NULL; } - if (compress && !block_driver_can_compress(target->drv)) { + if (compress && !bdrv_supports_compressed_writes(target)) { error_setg(errp, "Compression is not supported for this drive %s", bdrv_get_device_name(target)); return NULL; diff --git a/block/blkdebug.c b/block/blkdebug.c index 7194bc7f06338031d2f49e9bf9c78e97f1a27211..5fe6172da98902056062cfb2fe490bd9841b5898 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -173,7 +173,7 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp) { struct add_rule_data *d = opaque; BDRVBlkdebugState *s = d->s; - const char* event_name; + const char *event_name; int event; struct BlkdebugRule *rule; int64_t sector; @@ -215,6 +215,7 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp) BLKDEBUG_IO_TYPE__MAX, &local_error); if (local_error) { error_propagate(errp, local_error); + g_free(rule); return -1; } if (iotype != BLKDEBUG_IO_TYPE__MAX) { @@ -359,7 +360,6 @@ static int blkdebug_parse_perm_list(uint64_t *dest, QDict *options, QObject *crumpled_subqdict = NULL; Visitor *v = NULL; BlockPermissionList *perm_list = NULL, *element; - Error *local_err = NULL; *dest = 0; @@ -375,9 +375,7 @@ static int blkdebug_parse_perm_list(uint64_t *dest, QDict *options, } v = qobject_input_visitor_new(crumpled_subqdict); - visit_type_BlockPermissionList(v, NULL, &perm_list, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_BlockPermissionList(v, NULL, &perm_list, errp)) { ret = -EINVAL; goto out; } @@ -472,9 +470,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, uint64_t align; opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { ret = -EINVAL; goto out; } @@ -757,8 +753,11 @@ static int coroutine_fn blkdebug_co_block_status(BlockDriverState *bs, return err; } - return bdrv_co_block_status_from_file(bs, want_zero, offset, bytes, - pnum, map, file); + assert(bs->file && bs->file->bs); + *pnum = bytes; + *map = offset; + *file = bs->file->bs; + return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID; } static void blkdebug_close(BlockDriverState *bs) diff --git a/block/blklogwrites.c b/block/blklogwrites.c index 6753bd9a3eca078a8c9fe7642e0bf1b8f09d5479..13ae63983bc0c4ed89d3b6a6dce1fa2578e95c3b 100644 --- a/block/blklogwrites.c +++ b/block/blklogwrites.c @@ -149,10 +149,8 @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags, bool log_append; opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { + if (!qemu_opts_absorb_qdict(opts, options, errp)) { ret = -EINVAL; - error_propagate(errp, local_err); goto fail; } @@ -517,7 +515,6 @@ static BlockDriver bdrv_blk_log_writes = { .bdrv_co_pwrite_zeroes = blk_log_writes_co_pwrite_zeroes, .bdrv_co_flush_to_disk = blk_log_writes_co_flush_to_disk, .bdrv_co_pdiscard = blk_log_writes_co_pdiscard, - .bdrv_co_block_status = bdrv_co_block_status_from_file, .is_filter = true, .strong_runtime_opts = blk_log_writes_strong_runtime_opts, diff --git a/block/blkverify.c b/block/blkverify.c index 2f261de24b350a4e4abd6e6998c9b0f884857e44..4aed53ab598205f2d2c2a0221232426867f60327 100644 --- a/block/blkverify.c +++ b/block/blkverify.c @@ -116,9 +116,7 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags, int ret; opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { ret = -EINVAL; goto fail; } diff --git a/block/block-backend.c b/block/block-backend.c index 6936b25c836c9d92e05d077ee7a189e0186b98b7..ce78d30794ade042fa9f1b8d2b68284f29ed5a15 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -808,6 +808,7 @@ void blk_remove_bs(BlockBackend *blk) { ThrottleGroupMember *tgm = &blk->public.throttle_group_member; BlockDriverState *bs; + BdrvChild *root; notifier_list_notify(&blk->remove_bs_notifiers, blk); if (tgm->throttle_state) { @@ -825,8 +826,9 @@ void blk_remove_bs(BlockBackend *blk) * to avoid that and a potential QEMU crash. */ blk_drain(blk); - bdrv_root_unref_child(blk->root); + root = blk->root; blk->root = NULL; + bdrv_root_unref_child(root); } /* @@ -1351,12 +1353,12 @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags) void blk_inc_in_flight(BlockBackend *blk) { - atomic_inc(&blk->in_flight); + qatomic_inc(&blk->in_flight); } void blk_dec_in_flight(BlockBackend *blk) { - atomic_dec(&blk->in_flight); + qatomic_dec(&blk->in_flight); aio_wait_kick(); } @@ -1392,8 +1394,16 @@ typedef struct BlkAioEmAIOCB { bool has_returned; } BlkAioEmAIOCB; +static AioContext *blk_aio_em_aiocb_get_aio_context(BlockAIOCB *acb_) +{ + BlkAioEmAIOCB *acb = container_of(acb_, BlkAioEmAIOCB, common); + + return blk_get_aio_context(acb->rwco.blk); +} + static const AIOCBInfo blk_aio_em_aiocb_info = { .aiocb_size = sizeof(BlkAioEmAIOCB), + .get_aio_context = blk_aio_em_aiocb_get_aio_context, }; static void blk_aio_complete(BlkAioEmAIOCB *acb) @@ -1710,7 +1720,7 @@ void blk_drain(BlockBackend *blk) /* We may have -ENOMEDIUM completions in flight */ AIO_WAIT_WHILE(blk_get_aio_context(blk), - atomic_mb_read(&blk->in_flight) > 0); + qatomic_mb_read(&blk->in_flight) > 0); if (bs) { bdrv_drained_end(bs); @@ -1729,7 +1739,7 @@ void blk_drain_all(void) aio_context_acquire(ctx); /* We may have -ENOMEDIUM completions in flight */ - AIO_WAIT_WHILE(ctx, atomic_mb_read(&blk->in_flight) > 0); + AIO_WAIT_WHILE(ctx, qatomic_mb_read(&blk->in_flight) > 0); aio_context_release(ctx); } @@ -2269,10 +2279,13 @@ int blk_commit_all(void) while ((blk = blk_all_next(blk)) != NULL) { AioContext *aio_context = blk_get_aio_context(blk); + BlockDriverState *unfiltered_bs = bdrv_skip_filters(blk_bs(blk)); aio_context_acquire(aio_context); - if (blk_is_inserted(blk) && blk->root->bs->backing) { - int ret = bdrv_commit(blk->root->bs); + if (blk_is_inserted(blk) && bdrv_cow_child(unfiltered_bs)) { + int ret; + + ret = bdrv_commit(unfiltered_bs); if (ret < 0) { aio_context_release(aio_context); return ret; @@ -2333,6 +2346,7 @@ void blk_io_limits_update_group(BlockBackend *blk, const char *group) static void blk_root_drained_begin(BdrvChild *child) { BlockBackend *blk = child->opaque; + ThrottleGroupMember *tgm = &blk->public.throttle_group_member; if (++blk->quiesce_counter == 1) { if (blk->dev_ops && blk->dev_ops->drained_begin) { @@ -2343,8 +2357,8 @@ static void blk_root_drained_begin(BdrvChild *child) /* Note that blk->root may not be accessible here yet if we are just * attaching to a BlockDriverState that is drained. Use child instead. */ - if (atomic_fetch_inc(&blk->public.throttle_group_member.io_limits_disabled) == 0) { - throttle_group_restart_tgm(&blk->public.throttle_group_member); + if (qatomic_fetch_inc(&tgm->io_limits_disabled) == 0) { + throttle_group_restart_tgm(tgm); } } @@ -2361,7 +2375,7 @@ static void blk_root_drained_end(BdrvChild *child, int *drained_end_counter) assert(blk->quiesce_counter); assert(blk->public.throttle_group_member.io_limits_disabled); - atomic_dec(&blk->public.throttle_group_member.io_limits_disabled); + qatomic_dec(&blk->public.throttle_group_member.io_limits_disabled); if (--blk->quiesce_counter == 0) { if (blk->dev_ops && blk->dev_ops->drained_end) { diff --git a/block/block-copy.c b/block/block-copy.c index bb8d0569f2bd1a5258d98457748dbc157a671b77..cd9bc47c8f6d0509fe7240b53341092458b6b487 100644 --- a/block/block-copy.c +++ b/block/block-copy.c @@ -142,6 +142,9 @@ static BlockCopyTask *block_copy_task_create(BlockCopyState *s, return NULL; } + assert(QEMU_IS_ALIGNED(offset, s->cluster_size)); + bytes = QEMU_ALIGN_UP(bytes, s->cluster_size); + /* region is dirty, so no existent tasks possible in it */ assert(!find_conflicting_task(s, offset, bytes)); @@ -437,8 +440,8 @@ static int block_copy_block_status(BlockCopyState *s, int64_t offset, BlockDriverState *base; int ret; - if (s->skip_unallocated && s->source->bs->backing) { - base = s->source->bs->backing->bs; + if (s->skip_unallocated) { + base = bdrv_backing_chain_next(s->source->bs); } else { base = NULL; } @@ -622,8 +625,10 @@ out: * block_copy_task_run. If it fails, it means some task already failed * for real reason, let's return first failure. * Still, assert that we don't rewrite failure by success. + * + * Note: ret may be positive here because of block-status result. */ - assert(ret == 0 || aio_task_pool_status(aio) < 0); + assert(ret >= 0 || aio_task_pool_status(aio) < 0); ret = aio_task_pool_status(aio); aio_task_pool_free(aio); diff --git a/block/block-gen.h b/block/block-gen.h new file mode 100644 index 0000000000000000000000000000000000000000..f80cf4897d115fdbbef9b5128b807a42d3700cec --- /dev/null +++ b/block/block-gen.h @@ -0,0 +1,49 @@ +/* + * Block coroutine wrapping core, used by auto-generated block/block-gen.c + * + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2020 Virtuozzo International GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef BLOCK_BLOCK_GEN_H +#define BLOCK_BLOCK_GEN_H + +#include "block/block_int.h" + +/* Base structure for argument packing structures */ +typedef struct BdrvPollCo { + BlockDriverState *bs; + bool in_progress; + int ret; + Coroutine *co; /* Keep pointer here for debugging */ +} BdrvPollCo; + +static inline int bdrv_poll_co(BdrvPollCo *s) +{ + assert(!qemu_in_coroutine()); + + bdrv_coroutine_enter(s->bs, s->co); + BDRV_POLL_WHILE(s->bs, s->in_progress); + + return s->ret; +} + +#endif /* BLOCK_BLOCK_GEN_H */ diff --git a/block/commit.c b/block/commit.c index 7732d02dfe8f98a420bfbc95574cb80b1b0acabd..71db7ba7472e7c64b6b306823644a37759d33e0b 100644 --- a/block/commit.c +++ b/block/commit.c @@ -37,6 +37,7 @@ typedef struct CommitBlockJob { BlockBackend *top; BlockBackend *base; BlockDriverState *base_bs; + BlockDriverState *base_overlay; BlockdevOnError on_error; bool base_read_only; bool chain_frozen; @@ -89,7 +90,7 @@ static void commit_abort(Job *job) * XXX Can (or should) we somehow keep 'consistent read' blocked even * after the failed/cancelled commit job is gone? If we already wrote * something to base, the intermediate images aren't valid any more. */ - bdrv_replace_node(s->commit_top_bs, backing_bs(s->commit_top_bs), + bdrv_replace_node(s->commit_top_bs, s->commit_top_bs->backing->bs, &error_abort); bdrv_unref(s->commit_top_bs); @@ -153,9 +154,9 @@ static int coroutine_fn commit_run(Job *job, Error **errp) break; } /* Copy if allocated above the base */ - ret = bdrv_is_allocated_above(blk_bs(s->top), blk_bs(s->base), false, + ret = bdrv_is_allocated_above(blk_bs(s->top), s->base_overlay, true, offset, COMMIT_BUFFER_SIZE, &n); - copy = (ret == 1); + copy = (ret > 0); trace_commit_one_iteration(s, offset, n, ret); if (copy) { assert(n < SIZE_MAX); @@ -237,7 +238,6 @@ static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c, static BlockDriver bdrv_commit_top = { .format_name = "commit_top", .bdrv_co_preadv = bdrv_commit_top_preadv, - .bdrv_co_block_status = bdrv_co_block_status_from_backing, .bdrv_refresh_filename = bdrv_commit_top_refresh_filename, .bdrv_child_perm = bdrv_commit_top_child_perm, @@ -253,15 +253,35 @@ void commit_start(const char *job_id, BlockDriverState *bs, CommitBlockJob *s; BlockDriverState *iter; BlockDriverState *commit_top_bs = NULL; + BlockDriverState *filtered_base; Error *local_err = NULL; + int64_t base_size, top_size; + uint64_t base_perms, iter_shared_perms; int ret; assert(top != bs); - if (top == base) { + if (bdrv_skip_filters(top) == bdrv_skip_filters(base)) { error_setg(errp, "Invalid files for merge: top and base are the same"); return; } + base_size = bdrv_getlength(base); + if (base_size < 0) { + error_setg_errno(errp, -base_size, "Could not inquire base image size"); + return; + } + + top_size = bdrv_getlength(top); + if (top_size < 0) { + error_setg_errno(errp, -top_size, "Could not inquire top image size"); + return; + } + + base_perms = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE; + if (base_size < top_size) { + base_perms |= BLK_PERM_RESIZE; + } + s = block_job_create(job_id, &commit_job_driver, NULL, bs, 0, BLK_PERM_ALL, speed, creation_flags, NULL, NULL, errp); if (!s) { @@ -301,17 +321,43 @@ void commit_start(const char *job_id, BlockDriverState *bs, s->commit_top_bs = commit_top_bs; - /* Block all nodes between top and base, because they will - * disappear from the chain after this operation. */ - assert(bdrv_chain_contains(top, base)); - for (iter = top; iter != base; iter = backing_bs(iter)) { - /* XXX BLK_PERM_WRITE needs to be allowed so we don't block ourselves - * at s->base (if writes are blocked for a node, they are also blocked - * for its backing file). The other options would be a second filter - * driver above s->base. */ + /* + * Block all nodes between top and base, because they will + * disappear from the chain after this operation. + * Note that this assumes that the user is fine with removing all + * nodes (including R/W filters) between top and base. Assuring + * this is the responsibility of the interface (i.e. whoever calls + * commit_start()). + */ + s->base_overlay = bdrv_find_overlay(top, base); + assert(s->base_overlay); + + /* + * The topmost node with + * bdrv_skip_filters(filtered_base) == bdrv_skip_filters(base) + */ + filtered_base = bdrv_cow_bs(s->base_overlay); + assert(bdrv_skip_filters(filtered_base) == bdrv_skip_filters(base)); + + /* + * XXX BLK_PERM_WRITE needs to be allowed so we don't block ourselves + * at s->base (if writes are blocked for a node, they are also blocked + * for its backing file). The other options would be a second filter + * driver above s->base. + */ + iter_shared_perms = BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE; + + for (iter = top; iter != base; iter = bdrv_filter_or_cow_bs(iter)) { + if (iter == filtered_base) { + /* + * From here on, all nodes are filters on the base. This + * allows us to share BLK_PERM_CONSISTENT_READ. + */ + iter_shared_perms |= BLK_PERM_CONSISTENT_READ; + } + ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0, - BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE, - errp); + iter_shared_perms, errp); if (ret < 0) { goto fail; } @@ -328,9 +374,7 @@ void commit_start(const char *job_id, BlockDriverState *bs, } s->base = blk_new(s->common.job.aio_context, - BLK_PERM_CONSISTENT_READ - | BLK_PERM_WRITE - | BLK_PERM_RESIZE, + base_perms, BLK_PERM_CONSISTENT_READ | BLK_PERM_GRAPH_MOD | BLK_PERM_WRITE_UNCHANGED); @@ -398,19 +442,22 @@ int bdrv_commit(BlockDriverState *bs) if (!drv) return -ENOMEDIUM; - if (!bs->backing) { + backing_file_bs = bdrv_cow_bs(bs); + + if (!backing_file_bs) { return -ENOTSUP; } if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT_SOURCE, NULL) || - bdrv_op_is_blocked(bs->backing->bs, BLOCK_OP_TYPE_COMMIT_TARGET, NULL)) { + bdrv_op_is_blocked(backing_file_bs, BLOCK_OP_TYPE_COMMIT_TARGET, NULL)) + { return -EBUSY; } - ro = bs->backing->bs->read_only; + ro = backing_file_bs->read_only; if (ro) { - if (bdrv_reopen_set_read_only(bs->backing->bs, false, NULL)) { + if (bdrv_reopen_set_read_only(backing_file_bs, false, NULL)) { return -EACCES; } } @@ -428,8 +475,6 @@ int bdrv_commit(BlockDriverState *bs) } /* Insert commit_top block node above backing, so we can write to it */ - backing_file_bs = backing_bs(bs); - commit_top_bs = bdrv_new_open_driver(&bdrv_commit_top, NULL, BDRV_O_RDWR, &local_err); if (commit_top_bs == NULL) { @@ -515,7 +560,7 @@ ro_cleanup: qemu_vfree(buf); blk_unref(backing); - if (backing_file_bs) { + if (bdrv_cow_bs(bs) != backing_file_bs) { bdrv_set_backing_hd(bs, backing_file_bs, &error_abort); } bdrv_unref(commit_top_bs); @@ -523,7 +568,7 @@ ro_cleanup: if (ro) { /* ignoring error return here */ - bdrv_reopen_set_read_only(bs->backing->bs, true, NULL); + bdrv_reopen_set_read_only(backing_file_bs, true, NULL); } return ret; diff --git a/block/copy-on-read.c b/block/copy-on-read.c index a6e3c74a687e0a25b9e0be9499346a4784f8aed1..2816e61afeb03cbfec2f59363c84132ccfe67672 100644 --- a/block/copy-on-read.c +++ b/block/copy-on-read.c @@ -107,6 +107,16 @@ static int coroutine_fn cor_co_pdiscard(BlockDriverState *bs, } +static int coroutine_fn cor_co_pwritev_compressed(BlockDriverState *bs, + uint64_t offset, + uint64_t bytes, + QEMUIOVector *qiov) +{ + return bdrv_co_pwritev(bs->file, offset, bytes, qiov, + BDRV_REQ_WRITE_COMPRESSED); +} + + static void cor_eject(BlockDriverState *bs, bool eject_flag) { bdrv_eject(bs->file->bs, eject_flag); @@ -131,12 +141,11 @@ static BlockDriver bdrv_copy_on_read = { .bdrv_co_pwritev = cor_co_pwritev, .bdrv_co_pwrite_zeroes = cor_co_pwrite_zeroes, .bdrv_co_pdiscard = cor_co_pdiscard, + .bdrv_co_pwritev_compressed = cor_co_pwritev_compressed, .bdrv_eject = cor_eject, .bdrv_lock_medium = cor_lock_medium, - .bdrv_co_block_status = bdrv_co_block_status_from_file, - .has_variable_length = true, .is_filter = true, }; diff --git a/block/coroutines.h b/block/coroutines.h new file mode 100644 index 0000000000000000000000000000000000000000..4cfb4946e65e8d3e691e4d64feb81152f737e40a --- /dev/null +++ b/block/coroutines.h @@ -0,0 +1,69 @@ +/* + * Block layer I/O functions + * + * Copyright (c) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef BLOCK_COROUTINES_INT_H +#define BLOCK_COROUTINES_INT_H + +#include "block/block_int.h" + +int coroutine_fn bdrv_co_check(BlockDriverState *bs, + BdrvCheckResult *res, BdrvCheckMode fix); +int coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp); + +int generated_co_wrapper +bdrv_preadv(BdrvChild *child, int64_t offset, unsigned int bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags); +int generated_co_wrapper +bdrv_pwritev(BdrvChild *child, int64_t offset, unsigned int bytes, + QEMUIOVector *qiov, BdrvRequestFlags flags); + +int coroutine_fn +bdrv_co_common_block_status_above(BlockDriverState *bs, + BlockDriverState *base, + bool include_base, + bool want_zero, + int64_t offset, + int64_t bytes, + int64_t *pnum, + int64_t *map, + BlockDriverState **file, + int *depth); +int generated_co_wrapper +bdrv_common_block_status_above(BlockDriverState *bs, + BlockDriverState *base, + bool include_base, + bool want_zero, + int64_t offset, + int64_t bytes, + int64_t *pnum, + int64_t *map, + BlockDriverState **file, + int *depth); + +int coroutine_fn bdrv_co_readv_vmstate(BlockDriverState *bs, + QEMUIOVector *qiov, int64_t pos); +int coroutine_fn bdrv_co_writev_vmstate(BlockDriverState *bs, + QEMUIOVector *qiov, int64_t pos); + +#endif /* BLOCK_COROUTINES_INT_H */ diff --git a/block/crypto.c b/block/crypto.c index b216e12c3154b99fcbdef72b391a1d67a31aa9c8..aef5a5721a929eec2b3614fab73e6549497d4b93 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -37,6 +37,7 @@ typedef struct BlockCrypto BlockCrypto; struct BlockCrypto { QCryptoBlock *block; + bool updating_keys; }; @@ -71,6 +72,24 @@ static ssize_t block_crypto_read_func(QCryptoBlock *block, return ret; } +static ssize_t block_crypto_write_func(QCryptoBlock *block, + size_t offset, + const uint8_t *buf, + size_t buflen, + void *opaque, + Error **errp) +{ + BlockDriverState *bs = opaque; + ssize_t ret; + + ret = bdrv_pwrite(bs->file, offset, buf, buflen); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not write encryption header"); + return ret; + } + return ret; +} + struct BlockCryptoCreateData { BlockBackend *blk; @@ -79,12 +98,12 @@ struct BlockCryptoCreateData { }; -static ssize_t block_crypto_write_func(QCryptoBlock *block, - size_t offset, - const uint8_t *buf, - size_t buflen, - void *opaque, - Error **errp) +static ssize_t block_crypto_create_write_func(QCryptoBlock *block, + size_t offset, + const uint8_t *buf, + size_t buflen, + void *opaque, + Error **errp) { struct BlockCryptoCreateData *data = opaque; ssize_t ret; @@ -97,11 +116,10 @@ static ssize_t block_crypto_write_func(QCryptoBlock *block, return ret; } - -static ssize_t block_crypto_init_func(QCryptoBlock *block, - size_t headerlen, - void *opaque, - Error **errp) +static ssize_t block_crypto_create_init_func(QCryptoBlock *block, + size_t headerlen, + void *opaque, + Error **errp) { struct BlockCryptoCreateData *data = opaque; Error *local_error = NULL; @@ -167,6 +185,19 @@ static QemuOptsList block_crypto_create_opts_luks = { }; +static QemuOptsList block_crypto_amend_opts_luks = { + .name = "crypto", + .head = QTAILQ_HEAD_INITIALIZER(block_crypto_create_opts_luks.head), + .desc = { + BLOCK_CRYPTO_OPT_DEF_LUKS_STATE(""), + BLOCK_CRYPTO_OPT_DEF_LUKS_KEYSLOT(""), + BLOCK_CRYPTO_OPT_DEF_LUKS_OLD_SECRET(""), + BLOCK_CRYPTO_OPT_DEF_LUKS_NEW_SECRET(""), + BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME(""), + { /* end of list */ } + }, +}; + QCryptoBlockOpenOptions * block_crypto_open_opts_init(QDict *opts, Error **errp) { @@ -202,6 +233,23 @@ block_crypto_create_opts_init(QDict *opts, Error **errp) return ret; } +QCryptoBlockAmendOptions * +block_crypto_amend_opts_init(QDict *opts, Error **errp) +{ + Visitor *v; + QCryptoBlockAmendOptions *ret; + + v = qobject_input_visitor_new_flat_confused(opts, errp); + if (!v) { + return NULL; + } + + visit_type_QCryptoBlockAmendOptions(v, NULL, &ret, errp); + + visit_free(v); + return ret; +} + static int block_crypto_open_generic(QCryptoBlockFormat format, QemuOptsList *opts_spec, @@ -212,7 +260,6 @@ static int block_crypto_open_generic(QCryptoBlockFormat format, { BlockCrypto *crypto = bs->opaque; QemuOpts *opts = NULL; - Error *local_err = NULL; int ret = -EINVAL; QCryptoBlockOpenOptions *open_opts = NULL; unsigned int cflags = 0; @@ -228,9 +275,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format, bs->file->bs->supported_write_flags; opts = qemu_opts_create(opts_spec, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { goto cleanup; } @@ -296,8 +341,8 @@ static int block_crypto_co_create_generic(BlockDriverState *bs, }; crypto = qcrypto_block_create(opts, NULL, - block_crypto_init_func, - block_crypto_write_func, + block_crypto_create_init_func, + block_crypto_create_write_func, &data, errp); @@ -552,7 +597,7 @@ static BlockMeasureInfo *block_crypto_measure(QemuOpts *opts, * Unallocated blocks are still encrypted so allocation status makes no * difference to the file size. */ - info = g_new(BlockMeasureInfo, 1); + info = g_new0(BlockMeasureInfo, 1); info->fully_allocated = luks_payload_size + size; info->required = luks_payload_size + size; return info; @@ -710,7 +755,6 @@ static int block_crypto_get_info_luks(BlockDriverState *bs, return ret; } - bdi->unallocated_blocks_are_zero = false; bdi->cluster_size = subbdi.cluster_size; return 0; @@ -742,6 +786,131 @@ block_crypto_get_specific_info_luks(BlockDriverState *bs, Error **errp) return spec_info; } +static int +block_crypto_amend_options_generic_luks(BlockDriverState *bs, + QCryptoBlockAmendOptions *amend_options, + bool force, + Error **errp) +{ + BlockCrypto *crypto = bs->opaque; + int ret; + + assert(crypto); + assert(crypto->block); + + /* apply for exclusive read/write permissions to the underlying file*/ + crypto->updating_keys = true; + ret = bdrv_child_refresh_perms(bs, bs->file, errp); + if (ret) { + goto cleanup; + } + + ret = qcrypto_block_amend_options(crypto->block, + block_crypto_read_func, + block_crypto_write_func, + bs, + amend_options, + force, + errp); +cleanup: + /* release exclusive read/write permissions to the underlying file*/ + crypto->updating_keys = false; + bdrv_child_refresh_perms(bs, bs->file, errp); + return ret; +} + +static int +block_crypto_amend_options_luks(BlockDriverState *bs, + QemuOpts *opts, + BlockDriverAmendStatusCB *status_cb, + void *cb_opaque, + bool force, + Error **errp) +{ + BlockCrypto *crypto = bs->opaque; + QDict *cryptoopts = NULL; + QCryptoBlockAmendOptions *amend_options = NULL; + int ret = -EINVAL; + + assert(crypto); + assert(crypto->block); + + cryptoopts = qemu_opts_to_qdict(opts, NULL); + qdict_put_str(cryptoopts, "format", "luks"); + amend_options = block_crypto_amend_opts_init(cryptoopts, errp); + qobject_unref(cryptoopts); + if (!amend_options) { + goto cleanup; + } + ret = block_crypto_amend_options_generic_luks(bs, amend_options, + force, errp); +cleanup: + qapi_free_QCryptoBlockAmendOptions(amend_options); + return ret; +} + +static int +coroutine_fn block_crypto_co_amend_luks(BlockDriverState *bs, + BlockdevAmendOptions *opts, + bool force, + Error **errp) +{ + QCryptoBlockAmendOptions amend_opts; + + amend_opts = (QCryptoBlockAmendOptions) { + .format = Q_CRYPTO_BLOCK_FORMAT_LUKS, + .u.luks = *qapi_BlockdevAmendOptionsLUKS_base(&opts->u.luks), + }; + return block_crypto_amend_options_generic_luks(bs, &amend_opts, + force, errp); +} + +static void +block_crypto_child_perms(BlockDriverState *bs, BdrvChild *c, + const BdrvChildRole role, + BlockReopenQueue *reopen_queue, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +{ + + BlockCrypto *crypto = bs->opaque; + + bdrv_default_perms(bs, c, role, reopen_queue, perm, shared, nperm, nshared); + + /* + * For backward compatibility, manually share the write + * and resize permission + */ + *nshared |= shared & (BLK_PERM_WRITE | BLK_PERM_RESIZE); + /* + * Since we are not fully a format driver, don't always request + * the read/resize permission but only when explicitly + * requested + */ + *nperm &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE); + *nperm |= perm & (BLK_PERM_WRITE | BLK_PERM_RESIZE); + + /* + * This driver doesn't modify LUKS metadata except + * when updating the encryption slots. + * Thus unlike a proper format driver we don't ask for + * shared write/read permission. However we need it + * when we are updating the keys, to ensure that only we + * have access to the device. + * + * Encryption update will set the crypto->updating_keys + * during that period and refresh permissions + * + */ + if (crypto->updating_keys) { + /* need exclusive write access for header update */ + *nperm |= BLK_PERM_WRITE; + /* unshare read and write permission */ + *nshared &= ~(BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE); + } +} + + static const char *const block_crypto_strong_runtime_opts[] = { BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET, @@ -754,13 +923,12 @@ static BlockDriver bdrv_crypto_luks = { .bdrv_probe = block_crypto_probe_luks, .bdrv_open = block_crypto_open_luks, .bdrv_close = block_crypto_close, - /* This driver doesn't modify LUKS metadata except when creating image. - * Allow share-rw=on as a special case. */ - .bdrv_child_perm = bdrv_default_perms, + .bdrv_child_perm = block_crypto_child_perms, .bdrv_co_create = block_crypto_co_create_luks, .bdrv_co_create_opts = block_crypto_co_create_opts_luks, .bdrv_co_truncate = block_crypto_co_truncate, .create_opts = &block_crypto_create_opts_luks, + .amend_opts = &block_crypto_amend_opts_luks, .bdrv_reopen_prepare = block_crypto_reopen_prepare, .bdrv_refresh_limits = block_crypto_refresh_limits, @@ -770,6 +938,8 @@ static BlockDriver bdrv_crypto_luks = { .bdrv_measure = block_crypto_measure, .bdrv_get_info = block_crypto_get_info_luks, .bdrv_get_specific_info = block_crypto_get_specific_info_luks, + .bdrv_amend_options = block_crypto_amend_options_luks, + .bdrv_co_amend = block_crypto_co_amend_luks, .is_format = true, diff --git a/block/crypto.h b/block/crypto.h index b935695e79886bc52d3b60441b6fe9f1f744eab9..72e792c9af1c333e05fd91a5d9262c1860cb22fa 100644 --- a/block/crypto.h +++ b/block/crypto.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -41,6 +41,11 @@ #define BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG "ivgen-hash-alg" #define BLOCK_CRYPTO_OPT_LUKS_HASH_ALG "hash-alg" #define BLOCK_CRYPTO_OPT_LUKS_ITER_TIME "iter-time" +#define BLOCK_CRYPTO_OPT_LUKS_KEYSLOT "keyslot" +#define BLOCK_CRYPTO_OPT_LUKS_STATE "state" +#define BLOCK_CRYPTO_OPT_LUKS_OLD_SECRET "old-secret" +#define BLOCK_CRYPTO_OPT_LUKS_NEW_SECRET "new-secret" + #define BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(prefix) \ BLOCK_CRYPTO_OPT_DEF_KEY_SECRET(prefix, \ @@ -88,9 +93,41 @@ .help = "Time to spend in PBKDF in milliseconds", \ } +#define BLOCK_CRYPTO_OPT_DEF_LUKS_STATE(prefix) \ + { \ + .name = prefix BLOCK_CRYPTO_OPT_LUKS_STATE, \ + .type = QEMU_OPT_STRING, \ + .help = "Select new state of affected keyslots (active/inactive)",\ + } + +#define BLOCK_CRYPTO_OPT_DEF_LUKS_KEYSLOT(prefix) \ + { \ + .name = prefix BLOCK_CRYPTO_OPT_LUKS_KEYSLOT, \ + .type = QEMU_OPT_NUMBER, \ + .help = "Select a single keyslot to modify explicitly",\ + } + +#define BLOCK_CRYPTO_OPT_DEF_LUKS_OLD_SECRET(prefix) \ + { \ + .name = prefix BLOCK_CRYPTO_OPT_LUKS_OLD_SECRET, \ + .type = QEMU_OPT_STRING, \ + .help = "Select all keyslots that match this password", \ + } + +#define BLOCK_CRYPTO_OPT_DEF_LUKS_NEW_SECRET(prefix) \ + { \ + .name = prefix BLOCK_CRYPTO_OPT_LUKS_NEW_SECRET, \ + .type = QEMU_OPT_STRING, \ + .help = "New secret to set in the matching keyslots. " \ + "Empty string to erase", \ + } + QCryptoBlockCreateOptions * block_crypto_create_opts_init(QDict *opts, Error **errp); +QCryptoBlockAmendOptions * +block_crypto_amend_opts_init(QDict *opts, Error **errp); + QCryptoBlockOpenOptions * block_crypto_open_opts_init(QDict *opts, Error **errp); diff --git a/block/curl.c b/block/curl.c index 6e325901dc68e4a12a76047a52b550bf498e5702..4f907c47befe460ee3be9f64134b8853ce3fd888 100644 --- a/block/curl.c +++ b/block/curl.c @@ -669,7 +669,6 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, BDRVCURLState *s = bs->opaque; CURLState *state = NULL; QemuOpts *opts; - Error *local_err = NULL; const char *file; const char *cookie; const char *cookie_secret; @@ -695,9 +694,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, qemu_mutex_init(&s->mutex); opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { goto out_noclean; } diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index f9bfc77985e86707d8287f9ea9c1547a1d1f7567..c01319b188c3c37e380092ca7c5a5b69f8ebc1b3 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -818,6 +818,19 @@ bool bdrv_has_readonly_bitmaps(BlockDriverState *bs) return false; } +bool bdrv_has_named_bitmaps(BlockDriverState *bs) +{ + BdrvDirtyBitmap *bm; + + QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { + if (bdrv_dirty_bitmap_name(bm)) { + return true; + } + } + + return false; +} + /* Called with BQL taken. */ void bdrv_dirty_bitmap_set_persistence(BdrvDirtyBitmap *bitmap, bool persistent) { diff --git a/block/dmg-lzfse.c b/block/dmg-lzfse.c index 19d25bc6466a7987a4d3ebf06f14480cd10a9a82..6798cf4fbfffe2b05b17d1e452edd3e434a87df5 100644 --- a/block/dmg-lzfse.c +++ b/block/dmg-lzfse.c @@ -22,7 +22,6 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include "qemu-common.h" #include "dmg.h" #include diff --git a/block/dmg.c b/block/dmg.c index 0d6c3172963cb45d3c5d70845166944878451f44..ef35a505f2662049fb2b32007fd6dcb313ddff9a 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -559,7 +559,7 @@ static void dmg_refresh_limits(BlockDriverState *bs, Error **errp) bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */ } -static inline int is_sector_in_chunk(BDRVDMGState* s, +static inline int is_sector_in_chunk(BDRVDMGState *s, uint32_t chunk_num, uint64_t sector_num) { if (chunk_num >= s->n_chunks || s->sectors[chunk_num] > sector_num || diff --git a/block/export/export.c b/block/export/export.c new file mode 100644 index 0000000000000000000000000000000000000000..bad6f21b1c15ac849cf4f3f82a5bca56228e7573 --- /dev/null +++ b/block/export/export.c @@ -0,0 +1,360 @@ +/* + * Common block export infrastructure + * + * Copyright (c) 2012, 2020 Red Hat, Inc. + * + * Authors: + * Paolo Bonzini + * Kevin Wolf + * + * 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 "block/block.h" +#include "sysemu/block-backend.h" +#include "sysemu/iothread.h" +#include "block/export.h" +#include "block/nbd.h" +#include "qapi/error.h" +#include "qapi/qapi-commands-block-export.h" +#include "qapi/qapi-events-block-export.h" +#include "qemu/id.h" +#ifdef CONFIG_VHOST_USER_BLK_SERVER +#include "vhost-user-blk-server.h" +#endif + +static const BlockExportDriver *blk_exp_drivers[] = { + &blk_exp_nbd, +#ifdef CONFIG_VHOST_USER_BLK_SERVER + &blk_exp_vhost_user_blk, +#endif +}; + +/* Only accessed from the main thread */ +static QLIST_HEAD(, BlockExport) block_exports = + QLIST_HEAD_INITIALIZER(block_exports); + +BlockExport *blk_exp_find(const char *id) +{ + BlockExport *exp; + + QLIST_FOREACH(exp, &block_exports, next) { + if (strcmp(id, exp->id) == 0) { + return exp; + } + } + + return NULL; +} + +static const BlockExportDriver *blk_exp_find_driver(BlockExportType type) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(blk_exp_drivers); i++) { + if (blk_exp_drivers[i]->type == type) { + return blk_exp_drivers[i]; + } + } + return NULL; +} + +BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp) +{ + bool fixed_iothread = export->has_fixed_iothread && export->fixed_iothread; + const BlockExportDriver *drv; + BlockExport *exp = NULL; + BlockDriverState *bs; + BlockBackend *blk = NULL; + AioContext *ctx; + uint64_t perm; + int ret; + + if (!id_wellformed(export->id)) { + error_setg(errp, "Invalid block export id"); + return NULL; + } + if (blk_exp_find(export->id)) { + error_setg(errp, "Block export id '%s' is already in use", export->id); + return NULL; + } + + drv = blk_exp_find_driver(export->type); + if (!drv) { + error_setg(errp, "No driver found for the requested export type"); + return NULL; + } + + bs = bdrv_lookup_bs(NULL, export->node_name, errp); + if (!bs) { + return NULL; + } + + if (!export->has_writable) { + export->writable = false; + } + if (bdrv_is_read_only(bs) && export->writable) { + error_setg(errp, "Cannot export read-only node as writable"); + return NULL; + } + + ctx = bdrv_get_aio_context(bs); + aio_context_acquire(ctx); + + if (export->has_iothread) { + IOThread *iothread; + AioContext *new_ctx; + + iothread = iothread_by_id(export->iothread); + if (!iothread) { + error_setg(errp, "iothread \"%s\" not found", export->iothread); + goto fail; + } + + new_ctx = iothread_get_aio_context(iothread); + + ret = bdrv_try_set_aio_context(bs, new_ctx, errp); + if (ret == 0) { + aio_context_release(ctx); + aio_context_acquire(new_ctx); + ctx = new_ctx; + } else if (fixed_iothread) { + goto fail; + } + } + + /* + * Block exports are used for non-shared storage migration. Make sure + * that BDRV_O_INACTIVE is cleared and the image is ready for write + * access since the export could be available before migration handover. + * ctx was acquired in the caller. + */ + bdrv_invalidate_cache(bs, NULL); + + perm = BLK_PERM_CONSISTENT_READ; + if (export->writable) { + perm |= BLK_PERM_WRITE; + } + + blk = blk_new(ctx, perm, BLK_PERM_ALL); + + if (!fixed_iothread) { + blk_set_allow_aio_context_change(blk, true); + } + + ret = blk_insert_bs(blk, bs, errp); + if (ret < 0) { + goto fail; + } + + if (!export->has_writethrough) { + export->writethrough = false; + } + blk_set_enable_write_cache(blk, !export->writethrough); + + assert(drv->instance_size >= sizeof(BlockExport)); + exp = g_malloc0(drv->instance_size); + *exp = (BlockExport) { + .drv = drv, + .refcount = 1, + .user_owned = true, + .id = g_strdup(export->id), + .ctx = ctx, + .blk = blk, + }; + + ret = drv->create(exp, export, errp); + if (ret < 0) { + goto fail; + } + + assert(exp->blk != NULL); + + QLIST_INSERT_HEAD(&block_exports, exp, next); + + aio_context_release(ctx); + return exp; + +fail: + blk_unref(blk); + aio_context_release(ctx); + if (exp) { + g_free(exp->id); + g_free(exp); + } + return NULL; +} + +/* Callers must hold exp->ctx lock */ +void blk_exp_ref(BlockExport *exp) +{ + assert(exp->refcount > 0); + exp->refcount++; +} + +/* Runs in the main thread */ +static void blk_exp_delete_bh(void *opaque) +{ + BlockExport *exp = opaque; + AioContext *aio_context = exp->ctx; + + aio_context_acquire(aio_context); + + assert(exp->refcount == 0); + QLIST_REMOVE(exp, next); + exp->drv->delete(exp); + blk_unref(exp->blk); + qapi_event_send_block_export_deleted(exp->id); + g_free(exp->id); + g_free(exp); + + aio_context_release(aio_context); +} + +/* Callers must hold exp->ctx lock */ +void blk_exp_unref(BlockExport *exp) +{ + assert(exp->refcount > 0); + if (--exp->refcount == 0) { + /* Touch the block_exports list only in the main thread */ + aio_bh_schedule_oneshot(qemu_get_aio_context(), blk_exp_delete_bh, + exp); + } +} + +/* + * Drops the user reference to the export and requests that all client + * connections and other internally held references start to shut down. When + * the function returns, there may still be active references while the export + * is in the process of shutting down. + * + * Acquires exp->ctx internally. Callers must *not* hold the lock. + */ +void blk_exp_request_shutdown(BlockExport *exp) +{ + AioContext *aio_context = exp->ctx; + + aio_context_acquire(aio_context); + + /* + * If the user doesn't own the export any more, it is already shutting + * down. We must not call .request_shutdown and decrease the refcount a + * second time. + */ + if (!exp->user_owned) { + goto out; + } + + exp->drv->request_shutdown(exp); + + assert(exp->user_owned); + exp->user_owned = false; + blk_exp_unref(exp); + +out: + aio_context_release(aio_context); +} + +/* + * Returns whether a block export of the given type exists. + * type == BLOCK_EXPORT_TYPE__MAX checks for an export of any type. + */ +static bool blk_exp_has_type(BlockExportType type) +{ + BlockExport *exp; + + if (type == BLOCK_EXPORT_TYPE__MAX) { + return !QLIST_EMPTY(&block_exports); + } + + QLIST_FOREACH(exp, &block_exports, next) { + if (exp->drv->type == type) { + return true; + } + } + + return false; +} + +/* type == BLOCK_EXPORT_TYPE__MAX for all types */ +void blk_exp_close_all_type(BlockExportType type) +{ + BlockExport *exp, *next; + + assert(in_aio_context_home_thread(qemu_get_aio_context())); + + QLIST_FOREACH_SAFE(exp, &block_exports, next, next) { + if (type != BLOCK_EXPORT_TYPE__MAX && exp->drv->type != type) { + continue; + } + blk_exp_request_shutdown(exp); + } + + AIO_WAIT_WHILE(NULL, blk_exp_has_type(type)); +} + +void blk_exp_close_all(void) +{ + blk_exp_close_all_type(BLOCK_EXPORT_TYPE__MAX); +} + +void qmp_block_export_add(BlockExportOptions *export, Error **errp) +{ + blk_exp_add(export, errp); +} + +void qmp_block_export_del(const char *id, + bool has_mode, BlockExportRemoveMode mode, + Error **errp) +{ + ERRP_GUARD(); + BlockExport *exp; + + exp = blk_exp_find(id); + if (exp == NULL) { + error_setg(errp, "Export '%s' is not found", id); + return; + } + if (!exp->user_owned) { + error_setg(errp, "Export '%s' is already shutting down", id); + return; + } + + if (!has_mode) { + mode = BLOCK_EXPORT_REMOVE_MODE_SAFE; + } + if (mode == BLOCK_EXPORT_REMOVE_MODE_SAFE && exp->refcount > 1) { + error_setg(errp, "export '%s' still in use", exp->id); + error_append_hint(errp, "Use mode='hard' to force client " + "disconnect\n"); + return; + } + + blk_exp_request_shutdown(exp); +} + +BlockExportInfoList *qmp_query_block_exports(Error **errp) +{ + BlockExportInfoList *head = NULL, **p_next = &head; + BlockExport *exp; + + QLIST_FOREACH(exp, &block_exports, next) { + BlockExportInfoList *entry = g_new0(BlockExportInfoList, 1); + BlockExportInfo *info = g_new(BlockExportInfo, 1); + *info = (BlockExportInfo) { + .id = g_strdup(exp->id), + .type = exp->drv->type, + .node_name = g_strdup(bdrv_get_node_name(blk_bs(exp->blk))), + .shutting_down = !exp->user_owned, + }; + + entry->value = info; + *p_next = entry; + p_next = &entry->next; + } + + return head; +} diff --git a/block/export/meson.build b/block/export/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..135b356775b378cc91b6600a99186d2eaeb53caa --- /dev/null +++ b/block/export/meson.build @@ -0,0 +1,5 @@ +blockdev_ss.add(files('export.c')) + +if have_vhost_user_blk_server + blockdev_ss.add(files('vhost-user-blk-server.c')) +endif diff --git a/block/export/vhost-user-blk-server.c b/block/export/vhost-user-blk-server.c new file mode 100644 index 0000000000000000000000000000000000000000..62672d1cb95a37a104b9d4b2e91b92ab6ccfc929 --- /dev/null +++ b/block/export/vhost-user-blk-server.c @@ -0,0 +1,433 @@ +/* + * Sharing QEMU block devices via vhost-user protocal + * + * Parts of the code based on nbd/server.c. + * + * Copyright (c) Coiby Xu . + * Copyright (c) 2020 Red Hat, Inc. + * + * 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 "block/block.h" +#include "contrib/libvhost-user/libvhost-user.h" +#include "standard-headers/linux/virtio_blk.h" +#include "qemu/vhost-user-server.h" +#include "vhost-user-blk-server.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "sysemu/block-backend.h" +#include "util/block-helpers.h" + +enum { + VHOST_USER_BLK_NUM_QUEUES_DEFAULT = 1, +}; +struct virtio_blk_inhdr { + unsigned char status; +}; + +typedef struct VuBlkReq { + VuVirtqElement elem; + int64_t sector_num; + size_t size; + struct virtio_blk_inhdr *in; + struct virtio_blk_outhdr out; + VuServer *server; + struct VuVirtq *vq; +} VuBlkReq; + +/* vhost user block device */ +typedef struct { + BlockExport export; + VuServer vu_server; + uint32_t blk_size; + QIOChannelSocket *sioc; + struct virtio_blk_config blkcfg; + bool writable; +} VuBlkExport; + +static void vu_blk_req_complete(VuBlkReq *req) +{ + VuDev *vu_dev = &req->server->vu_dev; + + /* IO size with 1 extra status byte */ + vu_queue_push(vu_dev, req->vq, &req->elem, req->size + 1); + vu_queue_notify(vu_dev, req->vq); + + free(req); +} + +static int coroutine_fn +vu_blk_discard_write_zeroes(BlockBackend *blk, struct iovec *iov, + uint32_t iovcnt, uint32_t type) +{ + struct virtio_blk_discard_write_zeroes desc; + ssize_t size = iov_to_buf(iov, iovcnt, 0, &desc, sizeof(desc)); + if (unlikely(size != sizeof(desc))) { + error_report("Invalid size %zd, expect %zu", size, sizeof(desc)); + return -EINVAL; + } + + uint64_t range[2] = { le64_to_cpu(desc.sector) << 9, + le32_to_cpu(desc.num_sectors) << 9 }; + if (type == VIRTIO_BLK_T_DISCARD) { + if (blk_co_pdiscard(blk, range[0], range[1]) == 0) { + return 0; + } + } else if (type == VIRTIO_BLK_T_WRITE_ZEROES) { + if (blk_co_pwrite_zeroes(blk, range[0], range[1], 0) == 0) { + return 0; + } + } + + return -EINVAL; +} + +static void coroutine_fn vu_blk_virtio_process_req(void *opaque) +{ + VuBlkReq *req = opaque; + VuServer *server = req->server; + VuVirtqElement *elem = &req->elem; + uint32_t type; + + VuBlkExport *vexp = container_of(server, VuBlkExport, vu_server); + BlockBackend *blk = vexp->export.blk; + + struct iovec *in_iov = elem->in_sg; + struct iovec *out_iov = elem->out_sg; + unsigned in_num = elem->in_num; + unsigned out_num = elem->out_num; + + /* refer to hw/block/virtio_blk.c */ + if (elem->out_num < 1 || elem->in_num < 1) { + error_report("virtio-blk request missing headers"); + goto err; + } + + if (unlikely(iov_to_buf(out_iov, out_num, 0, &req->out, + sizeof(req->out)) != sizeof(req->out))) { + error_report("virtio-blk request outhdr too short"); + goto err; + } + + iov_discard_front(&out_iov, &out_num, sizeof(req->out)); + + if (in_iov[in_num - 1].iov_len < sizeof(struct virtio_blk_inhdr)) { + error_report("virtio-blk request inhdr too short"); + goto err; + } + + /* We always touch the last byte, so just see how big in_iov is. */ + req->in = (void *)in_iov[in_num - 1].iov_base + + in_iov[in_num - 1].iov_len + - sizeof(struct virtio_blk_inhdr); + iov_discard_back(in_iov, &in_num, sizeof(struct virtio_blk_inhdr)); + + type = le32_to_cpu(req->out.type); + switch (type & ~VIRTIO_BLK_T_BARRIER) { + case VIRTIO_BLK_T_IN: + case VIRTIO_BLK_T_OUT: { + ssize_t ret = 0; + bool is_write = type & VIRTIO_BLK_T_OUT; + req->sector_num = le64_to_cpu(req->out.sector); + + if (is_write && !vexp->writable) { + req->in->status = VIRTIO_BLK_S_IOERR; + break; + } + + int64_t offset = req->sector_num * vexp->blk_size; + QEMUIOVector qiov; + if (is_write) { + qemu_iovec_init_external(&qiov, out_iov, out_num); + ret = blk_co_pwritev(blk, offset, qiov.size, &qiov, 0); + } else { + qemu_iovec_init_external(&qiov, in_iov, in_num); + ret = blk_co_preadv(blk, offset, qiov.size, &qiov, 0); + } + if (ret >= 0) { + req->in->status = VIRTIO_BLK_S_OK; + } else { + req->in->status = VIRTIO_BLK_S_IOERR; + } + break; + } + case VIRTIO_BLK_T_FLUSH: + if (blk_co_flush(blk) == 0) { + req->in->status = VIRTIO_BLK_S_OK; + } else { + req->in->status = VIRTIO_BLK_S_IOERR; + } + break; + case VIRTIO_BLK_T_GET_ID: { + size_t size = MIN(iov_size(&elem->in_sg[0], in_num), + VIRTIO_BLK_ID_BYTES); + snprintf(elem->in_sg[0].iov_base, size, "%s", "vhost_user_blk"); + req->in->status = VIRTIO_BLK_S_OK; + req->size = elem->in_sg[0].iov_len; + break; + } + case VIRTIO_BLK_T_DISCARD: + case VIRTIO_BLK_T_WRITE_ZEROES: { + int rc; + + if (!vexp->writable) { + req->in->status = VIRTIO_BLK_S_IOERR; + break; + } + + rc = vu_blk_discard_write_zeroes(blk, &elem->out_sg[1], out_num, type); + if (rc == 0) { + req->in->status = VIRTIO_BLK_S_OK; + } else { + req->in->status = VIRTIO_BLK_S_IOERR; + } + break; + } + default: + req->in->status = VIRTIO_BLK_S_UNSUPP; + break; + } + + vu_blk_req_complete(req); + return; + +err: + free(req); +} + +static void vu_blk_process_vq(VuDev *vu_dev, int idx) +{ + VuServer *server = container_of(vu_dev, VuServer, vu_dev); + VuVirtq *vq = vu_get_queue(vu_dev, idx); + + while (1) { + VuBlkReq *req; + + req = vu_queue_pop(vu_dev, vq, sizeof(VuBlkReq)); + if (!req) { + break; + } + + req->server = server; + req->vq = vq; + + Coroutine *co = + qemu_coroutine_create(vu_blk_virtio_process_req, req); + qemu_coroutine_enter(co); + } +} + +static void vu_blk_queue_set_started(VuDev *vu_dev, int idx, bool started) +{ + VuVirtq *vq; + + assert(vu_dev); + + vq = vu_get_queue(vu_dev, idx); + vu_set_queue_handler(vu_dev, vq, started ? vu_blk_process_vq : NULL); +} + +static uint64_t vu_blk_get_features(VuDev *dev) +{ + uint64_t features; + VuServer *server = container_of(dev, VuServer, vu_dev); + VuBlkExport *vexp = container_of(server, VuBlkExport, vu_server); + features = 1ull << VIRTIO_BLK_F_SIZE_MAX | + 1ull << VIRTIO_BLK_F_SEG_MAX | + 1ull << VIRTIO_BLK_F_TOPOLOGY | + 1ull << VIRTIO_BLK_F_BLK_SIZE | + 1ull << VIRTIO_BLK_F_FLUSH | + 1ull << VIRTIO_BLK_F_DISCARD | + 1ull << VIRTIO_BLK_F_WRITE_ZEROES | + 1ull << VIRTIO_BLK_F_CONFIG_WCE | + 1ull << VIRTIO_BLK_F_MQ | + 1ull << VIRTIO_F_VERSION_1 | + 1ull << VIRTIO_RING_F_INDIRECT_DESC | + 1ull << VIRTIO_RING_F_EVENT_IDX | + 1ull << VHOST_USER_F_PROTOCOL_FEATURES; + + if (!vexp->writable) { + features |= 1ull << VIRTIO_BLK_F_RO; + } + + return features; +} + +static uint64_t vu_blk_get_protocol_features(VuDev *dev) +{ + return 1ull << VHOST_USER_PROTOCOL_F_CONFIG | + 1ull << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD; +} + +static int +vu_blk_get_config(VuDev *vu_dev, uint8_t *config, uint32_t len) +{ + VuServer *server = container_of(vu_dev, VuServer, vu_dev); + VuBlkExport *vexp = container_of(server, VuBlkExport, vu_server); + + g_return_val_if_fail(len <= sizeof(struct virtio_blk_config), -1); + + memcpy(config, &vexp->blkcfg, len); + return 0; +} + +static int +vu_blk_set_config(VuDev *vu_dev, const uint8_t *data, + uint32_t offset, uint32_t size, uint32_t flags) +{ + VuServer *server = container_of(vu_dev, VuServer, vu_dev); + VuBlkExport *vexp = container_of(server, VuBlkExport, vu_server); + uint8_t wce; + + /* don't support live migration */ + if (flags != VHOST_SET_CONFIG_TYPE_MASTER) { + return -EINVAL; + } + + if (offset != offsetof(struct virtio_blk_config, wce) || + size != 1) { + return -EINVAL; + } + + wce = *data; + vexp->blkcfg.wce = wce; + blk_set_enable_write_cache(vexp->export.blk, wce); + return 0; +} + +/* + * When the client disconnects, it sends a VHOST_USER_NONE request + * and vu_process_message will simple call exit which cause the VM + * to exit abruptly. + * To avoid this issue, process VHOST_USER_NONE request ahead + * of vu_process_message. + * + */ +static int vu_blk_process_msg(VuDev *dev, VhostUserMsg *vmsg, int *do_reply) +{ + if (vmsg->request == VHOST_USER_NONE) { + dev->panic(dev, "disconnect"); + return true; + } + return false; +} + +static const VuDevIface vu_blk_iface = { + .get_features = vu_blk_get_features, + .queue_set_started = vu_blk_queue_set_started, + .get_protocol_features = vu_blk_get_protocol_features, + .get_config = vu_blk_get_config, + .set_config = vu_blk_set_config, + .process_msg = vu_blk_process_msg, +}; + +static void blk_aio_attached(AioContext *ctx, void *opaque) +{ + VuBlkExport *vexp = opaque; + + vexp->export.ctx = ctx; + vhost_user_server_attach_aio_context(&vexp->vu_server, ctx); +} + +static void blk_aio_detach(void *opaque) +{ + VuBlkExport *vexp = opaque; + + vhost_user_server_detach_aio_context(&vexp->vu_server); + vexp->export.ctx = NULL; +} + +static void +vu_blk_initialize_config(BlockDriverState *bs, + struct virtio_blk_config *config, + uint32_t blk_size, + uint16_t num_queues) +{ + config->capacity = cpu_to_le64(bdrv_getlength(bs) >> BDRV_SECTOR_BITS); + config->blk_size = cpu_to_le32(blk_size); + config->size_max = cpu_to_le32(0); + config->seg_max = cpu_to_le32(128 - 2); + config->min_io_size = cpu_to_le16(1); + config->opt_io_size = cpu_to_le32(1); + config->num_queues = cpu_to_le16(num_queues); + config->max_discard_sectors = cpu_to_le32(32768); + config->max_discard_seg = cpu_to_le32(1); + config->discard_sector_alignment = cpu_to_le32(config->blk_size >> 9); + config->max_write_zeroes_sectors = cpu_to_le32(32768); + config->max_write_zeroes_seg = cpu_to_le32(1); +} + +static void vu_blk_exp_request_shutdown(BlockExport *exp) +{ + VuBlkExport *vexp = container_of(exp, VuBlkExport, export); + + vhost_user_server_stop(&vexp->vu_server); +} + +static int vu_blk_exp_create(BlockExport *exp, BlockExportOptions *opts, + Error **errp) +{ + VuBlkExport *vexp = container_of(exp, VuBlkExport, export); + BlockExportOptionsVhostUserBlk *vu_opts = &opts->u.vhost_user_blk; + Error *local_err = NULL; + uint64_t logical_block_size; + uint16_t num_queues = VHOST_USER_BLK_NUM_QUEUES_DEFAULT; + + vexp->writable = opts->writable; + vexp->blkcfg.wce = 0; + + if (vu_opts->has_logical_block_size) { + logical_block_size = vu_opts->logical_block_size; + } else { + logical_block_size = BDRV_SECTOR_SIZE; + } + check_block_size(exp->id, "logical-block-size", logical_block_size, + &local_err); + if (local_err) { + error_propagate(errp, local_err); + return -EINVAL; + } + vexp->blk_size = logical_block_size; + blk_set_guest_block_size(exp->blk, logical_block_size); + + if (vu_opts->has_num_queues) { + num_queues = vu_opts->num_queues; + } + if (num_queues == 0) { + error_setg(errp, "num-queues must be greater than 0"); + return -EINVAL; + } + + vu_blk_initialize_config(blk_bs(exp->blk), &vexp->blkcfg, + logical_block_size, num_queues); + + blk_add_aio_context_notifier(exp->blk, blk_aio_attached, blk_aio_detach, + vexp); + + if (!vhost_user_server_start(&vexp->vu_server, vu_opts->addr, exp->ctx, + num_queues, &vu_blk_iface, errp)) { + blk_remove_aio_context_notifier(exp->blk, blk_aio_attached, + blk_aio_detach, vexp); + return -EADDRNOTAVAIL; + } + + return 0; +} + +static void vu_blk_exp_delete(BlockExport *exp) +{ + VuBlkExport *vexp = container_of(exp, VuBlkExport, export); + + blk_remove_aio_context_notifier(exp->blk, blk_aio_attached, blk_aio_detach, + vexp); +} + +const BlockExportDriver blk_exp_vhost_user_blk = { + .type = BLOCK_EXPORT_TYPE_VHOST_USER_BLK, + .instance_size = sizeof(VuBlkExport), + .create = vu_blk_exp_create, + .delete = vu_blk_exp_delete, + .request_shutdown = vu_blk_exp_request_shutdown, +}; diff --git a/block/export/vhost-user-blk-server.h b/block/export/vhost-user-blk-server.h new file mode 100644 index 0000000000000000000000000000000000000000..fcf46fc8a5fce9b362a35a8a6837ec3a6bb80cb2 --- /dev/null +++ b/block/export/vhost-user-blk-server.h @@ -0,0 +1,19 @@ +/* + * Sharing QEMU block devices via vhost-user protocal + * + * Copyright (c) Coiby Xu . + * Copyright (c) 2020 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * later. See the COPYING file in the top-level directory. + */ + +#ifndef VHOST_USER_BLK_SERVER_H +#define VHOST_USER_BLK_SERVER_H + +#include "block/export.h" + +/* For block/export/export.c */ +extern const BlockExportDriver blk_exp_vhost_user_blk; + +#endif /* VHOST_USER_BLK_SERVER_H */ diff --git a/block/file-posix.c b/block/file-posix.c index 3ab8f5a0fa7720e2ae166cda25a8c423d7abcea8..d5fd1dbcd20bddc320a86c0cdaca03bca3b73974 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -30,6 +30,7 @@ #include "block/block_int.h" #include "qemu/module.h" #include "qemu/option.h" +#include "qemu/units.h" #include "trace.h" #include "block/thread-pool.h" #include "qemu/iov.h" @@ -61,10 +62,12 @@ #include #include #include +#include #include #include #include #include +#include #include #ifdef __s390__ #include @@ -299,6 +302,28 @@ static int probe_physical_blocksize(int fd, unsigned int *blk_size) #endif } +/* + * Returns true if no alignment restrictions are necessary even for files + * opened with O_DIRECT. + * + * raw_probe_alignment() probes the required alignment and assume that 1 means + * the probing failed, so it falls back to a safe default of 4k. This can be + * avoided if we know that byte alignment is okay for the file. + */ +static bool dio_byte_aligned(int fd) +{ +#ifdef __linux__ + struct statfs buf; + int ret; + + ret = fstatfs(fd, &buf); + if (ret == 0 && buf.f_type == NFS_SUPER_MAGIC) { + return true; + } +#endif + return false; +} + /* Check if read is allowed with given memory buffer and length. * * This function is used to check O_DIRECT memory buffer and request alignment. @@ -400,6 +425,39 @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp) } } +static int check_hdev_writable(int fd) +{ +#if defined(BLKROGET) + /* Linux block devices can be configured "read-only" using blockdev(8). + * This is independent of device node permissions and therefore open(2) + * with O_RDWR succeeds. Actual writes fail with EPERM. + * + * bdrv_open() is supposed to fail if the disk is read-only. Explicitly + * check for read-only block devices so that Linux block devices behave + * properly. + */ + struct stat st; + int readonly = 0; + + if (fstat(fd, &st)) { + return -errno; + } + + if (!S_ISBLK(st.st_mode)) { + return 0; + } + + if (ioctl(fd, BLKROGET, &readonly) < 0) { + return -errno; + } + + if (readonly) { + return -EACCES; + } +#endif /* defined(BLKROGET) */ + return 0; +} + static void raw_parse_flags(int bdrv_flags, int *open_flags, bool has_writers) { bool read_write = false; @@ -490,9 +548,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, OnOffAuto locking; opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { ret = -EINVAL; goto fail; } @@ -574,11 +630,10 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, raw_parse_flags(bdrv_flags, &s->open_flags, false); s->fd = -1; - fd = qemu_open(filename, s->open_flags, 0644); + fd = qemu_open(filename, s->open_flags, errp); ret = fd < 0 ? -errno : 0; if (ret < 0) { - error_setg_file_open(errp, -ret, filename); if (ret == -EROFS) { ret = -EACCES; } @@ -586,6 +641,15 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, } s->fd = fd; + /* Check s->open_flags rather than bdrv_flags due to auto-read-only */ + if (s->open_flags & O_RDWR) { + ret = check_hdev_writable(s->fd); + if (ret < 0) { + error_setg_errno(errp, -ret, "The device is not writable"); + goto fail; + } + } + s->perm = 0; s->shared_perm = BLK_PERM_ALL; @@ -630,7 +694,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, s->has_discard = true; s->has_write_zeroes = true; - if ((bs->open_flags & BDRV_O_NOCACHE) != 0) { + if ((bs->open_flags & BDRV_O_NOCACHE) != 0 && !dio_byte_aligned(s->fd)) { s->needs_alignment = true; } @@ -708,6 +772,9 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, } ret = 0; fail: + if (ret < 0 && s->fd != -1) { + qemu_close(s->fd); + } if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) { unlink(filename); } @@ -969,15 +1036,22 @@ static int raw_reconfigure_getfd(BlockDriverState *bs, int flags, const char *normalized_filename = bs->filename; ret = raw_normalize_devicepath(&normalized_filename, errp); if (ret >= 0) { - assert(!(*open_flags & O_CREAT)); - fd = qemu_open(normalized_filename, *open_flags); + fd = qemu_open(normalized_filename, *open_flags, errp); if (fd == -1) { - error_setg_errno(errp, errno, "Could not reopen file"); return -1; } } } + if (fd != -1 && (*open_flags & O_RDWR)) { + ret = check_hdev_writable(fd); + if (ret < 0) { + qemu_close(fd); + error_setg_errno(errp, -ret, "The device is not writable"); + return -1; + } + } + return fd; } @@ -1000,9 +1074,7 @@ static int raw_reopen_prepare(BDRVReopenState *state, /* Handle options changes */ opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, state->options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, state->options, errp)) { ret = -EINVAL; goto out; } @@ -1623,7 +1695,12 @@ static int handle_aiocb_write_zeroes_unmap(void *opaque) #ifdef CONFIG_FALLOCATE_PUNCH_HOLE int ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, aiocb->aio_offset, aiocb->aio_nbytes); - if (ret != -ENOTSUP) { + switch (ret) { + case -ENOTSUP: + case -EINVAL: + case -EBUSY: + break; + default: return ret; } #endif @@ -2322,12 +2399,19 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp) if (!file_opts->has_preallocation) { file_opts->preallocation = PREALLOC_MODE_OFF; } + if (!file_opts->has_extent_size_hint) { + file_opts->extent_size_hint = 1 * MiB; + } + if (file_opts->extent_size_hint > UINT32_MAX) { + result = -EINVAL; + error_setg(errp, "Extent size hint is too large"); + goto out; + } /* Create file */ - fd = qemu_open(file_opts->filename, O_RDWR | O_CREAT | O_BINARY, 0644); + fd = qemu_create(file_opts->filename, O_RDWR | O_BINARY, 0644, errp); if (fd < 0) { result = -errno; - error_setg_errno(errp, -result, "Could not create file"); goto out; } @@ -2379,6 +2463,27 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp) } #endif } +#ifdef FS_IOC_FSSETXATTR + /* + * Try to set the extent size hint. Failure is not fatal, and a warning is + * only printed if the option was explicitly specified. + */ + { + struct fsxattr attr; + result = ioctl(fd, FS_IOC_FSGETXATTR, &attr); + if (result == 0) { + attr.fsx_xflags |= FS_XFLAG_EXTSIZE; + attr.fsx_extsize = file_opts->extent_size_hint; + result = ioctl(fd, FS_IOC_FSSETXATTR, &attr); + } + if (result < 0 && file_opts->has_extent_size_hint && + file_opts->extent_size_hint) + { + warn_report("Failed to set extent size hint: %s", + strerror(errno)); + } + } +#endif /* Resize and potentially preallocate the file to the desired * final size */ @@ -2414,6 +2519,8 @@ static int coroutine_fn raw_co_create_opts(BlockDriver *drv, { BlockdevCreateOptions options; int64_t total_size = 0; + int64_t extent_size_hint = 0; + bool has_extent_size_hint = false; bool nocow = false; PreallocMode prealloc; char *buf = NULL; @@ -2425,6 +2532,11 @@ static int coroutine_fn raw_co_create_opts(BlockDriver *drv, /* Read out options */ total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), BDRV_SECTOR_SIZE); + if (qemu_opt_get(opts, BLOCK_OPT_EXTENT_SIZE_HINT)) { + has_extent_size_hint = true; + extent_size_hint = + qemu_opt_get_size_del(opts, BLOCK_OPT_EXTENT_SIZE_HINT, -1); + } nocow = qemu_opt_get_bool(opts, BLOCK_OPT_NOCOW, false); buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC); prealloc = qapi_enum_parse(&PreallocMode_lookup, buf, @@ -2444,6 +2556,8 @@ static int coroutine_fn raw_co_create_opts(BlockDriver *drv, .preallocation = prealloc, .has_nocow = true, .nocow = nocow, + .has_extent_size_hint = has_extent_size_hint, + .extent_size_hint = extent_size_hint, }, }; return raw_co_create(&options, errp); @@ -2878,9 +2992,6 @@ static int coroutine_fn raw_co_pwrite_zeroes( static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { - BDRVRawState *s = bs->opaque; - - bdi->unallocated_blocks_are_zero = s->discard_zeroes; return 0; } @@ -2937,6 +3048,11 @@ static QemuOptsList raw_create_opts = { #endif ", full)" }, + { + .name = BLOCK_OPT_EXTENT_SIZE_HINT, + .type = QEMU_OPT_SIZE, + .help = "Extent size hint for the image file, 0 to disable" + }, { /* end of list */ } } }; @@ -3216,7 +3332,7 @@ static bool setup_cdrom(char *bsd_path, Error **errp) for (index = 0; index < num_of_test_partitions; index++) { snprintf(test_partition, sizeof(test_partition), "%ss%d", bsd_path, index); - fd = qemu_open(test_partition, O_RDONLY | O_BINARY | O_LARGEFILE); + fd = qemu_open(test_partition, O_RDONLY | O_BINARY | O_LARGEFILE, NULL); if (fd >= 0) { partition_found = true; qemu_close(fd); @@ -3262,39 +3378,6 @@ static int hdev_probe_device(const char *filename) return 0; } -static int check_hdev_writable(BDRVRawState *s) -{ -#if defined(BLKROGET) - /* Linux block devices can be configured "read-only" using blockdev(8). - * This is independent of device node permissions and therefore open(2) - * with O_RDWR succeeds. Actual writes fail with EPERM. - * - * bdrv_open() is supposed to fail if the disk is read-only. Explicitly - * check for read-only block devices so that Linux block devices behave - * properly. - */ - struct stat st; - int readonly = 0; - - if (fstat(s->fd, &st)) { - return -errno; - } - - if (!S_ISBLK(st.st_mode)) { - return 0; - } - - if (ioctl(s->fd, BLKROGET, &readonly) < 0) { - return -errno; - } - - if (readonly) { - return -EACCES; - } -#endif /* defined(BLKROGET) */ - return 0; -} - static void hdev_parse_filename(const char *filename, QDict *options, Error **errp) { @@ -3336,7 +3419,6 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVRawState *s = bs->opaque; - Error *local_err = NULL; int ret; #if defined(__APPLE__) && defined(__MACH__) @@ -3401,9 +3483,8 @@ hdev_open_Mac_error: s->type = FTYPE_FILE; - ret = raw_open_common(bs, options, flags, 0, true, &local_err); + ret = raw_open_common(bs, options, flags, 0, true, errp); if (ret < 0) { - error_propagate(errp, local_err); #if defined(__APPLE__) && defined(__MACH__) if (*bsd_path) { filename = bsd_path; @@ -3419,15 +3500,6 @@ hdev_open_Mac_error: /* Since this does ioctl the device must be already opened */ bs->sg = hdev_is_sg(bs); - if (flags & BDRV_O_RDWR) { - ret = check_hdev_writable(s); - if (ret < 0) { - raw_close(bs); - error_setg_errno(errp, -ret, "The device is not writable"); - return ret; - } - } - return ret; } @@ -3578,7 +3650,7 @@ static int cdrom_probe_device(const char *filename) int prio = 0; struct stat st; - fd = qemu_open(filename, O_RDONLY | O_NONBLOCK); + fd = qemu_open(filename, O_RDONLY | O_NONBLOCK, NULL); if (fd < 0) { goto out; } @@ -3679,14 +3751,12 @@ static int cdrom_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVRawState *s = bs->opaque; - Error *local_err = NULL; int ret; s->type = FTYPE_CD; - ret = raw_open_common(bs, options, flags, 0, true, &local_err); + ret = raw_open_common(bs, options, flags, 0, true, errp); if (ret) { - error_propagate(errp, local_err); return ret; } @@ -3714,7 +3784,7 @@ static int cdrom_reopen(BlockDriverState *bs) */ if (s->fd >= 0) qemu_close(s->fd); - fd = qemu_open(bs->filename, s->open_flags, 0644); + fd = qemu_open(bs->filename, s->open_flags, NULL); if (fd < 0) { s->fd = -1; return -EIO; diff --git a/block/file-win32.c b/block/file-win32.c index 221aaf713e24fea3ea6e87a4b2983f35c500fd0a..2642088bd6eecb87e9032b135ccc6ec629c8f27b 100644 --- a/block/file-win32.c +++ b/block/file-win32.c @@ -299,6 +299,11 @@ static QemuOptsList raw_runtime_opts = { .type = QEMU_OPT_STRING, .help = "host AIO implementation (threads, native)", }, + { + .name = "locking", + .type = QEMU_OPT_STRING, + .help = "file locking mode (on/off/auto, default: auto)", + }, { /* end of list */ } }, }; @@ -333,22 +338,35 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, Error *local_err = NULL; const char *filename; bool use_aio; + OnOffAuto locking; int ret; s->type = FTYPE_FILE; opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { + ret = -EINVAL; + goto fail; + } + + locking = qapi_enum_parse(&OnOffAuto_lookup, + qemu_opt_get(opts, "locking"), + ON_OFF_AUTO_AUTO, &local_err); if (local_err) { error_propagate(errp, local_err); ret = -EINVAL; goto fail; } - - if (qdict_get_try_bool(options, "locking", false)) { + switch (locking) { + case ON_OFF_AUTO_ON: error_setg(errp, "locking=on is not supported on Windows"); ret = -EINVAL; goto fail; + case ON_OFF_AUTO_OFF: + case ON_OFF_AUTO_AUTO: + break; + default: + g_assert_not_reached(); } filename = qemu_opt_get(opts, "filename"); @@ -578,10 +596,9 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp) return -EINVAL; } - fd = qemu_open(file_opts->filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, - 0644); + fd = qemu_create(file_opts->filename, O_WRONLY | O_TRUNC | O_BINARY, + 0644, errp); if (fd < 0) { - error_setg_errno(errp, errno, "Could not create file"); return -EIO; } set_sparse(fd); @@ -739,9 +756,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags, QemuOpts *opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { ret = -EINVAL; goto done; } diff --git a/block/filter-compress.c b/block/filter-compress.c index 8ec1991c1f216ef04e4c5eaf6e82b072ddab0f51..5136371bf8b98cbd3dd1a4941bfa591cd01186ca 100644 --- a/block/filter-compress.c +++ b/block/filter-compress.c @@ -146,8 +146,6 @@ static BlockDriver bdrv_compress = { .bdrv_eject = compress_eject, .bdrv_lock_medium = compress_lock_medium, - .bdrv_co_block_status = bdrv_co_block_status_from_file, - .has_variable_length = true, .is_filter = true, }; diff --git a/block/gluster.c b/block/gluster.c index 31233cac696a6c18ae901b9db28da15dc1ceb5e4..4f1448e2bc88e7990beb431337d11ac715490d21 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -523,8 +523,7 @@ static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf, /* create opts info from runtime_json_opts list */ opts = qemu_opts_create(&runtime_json_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { + if (!qemu_opts_absorb_qdict(opts, options, errp)) { goto out; } @@ -555,8 +554,7 @@ static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf, /* create opts info from runtime_type_opts list */ opts = qemu_opts_create(&runtime_type_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, backing_options, &local_err); - if (local_err) { + if (!qemu_opts_absorb_qdict(opts, backing_options, errp)) { goto out; } @@ -586,8 +584,7 @@ static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf, if (gsconf->type == SOCKET_ADDRESS_TYPE_INET) { /* create opts info from runtime_inet_opts list */ opts = qemu_opts_create(&runtime_inet_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, backing_options, &local_err); - if (local_err) { + if (!qemu_opts_absorb_qdict(opts, backing_options, errp)) { goto out; } @@ -635,8 +632,7 @@ static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf, } else { /* create opts info from runtime_unix_opts list */ opts = qemu_opts_create(&runtime_unix_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, backing_options, &local_err); - if (local_err) { + if (!qemu_opts_absorb_qdict(opts, backing_options, errp)) { goto out; } @@ -815,13 +811,10 @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options, int ret = 0; BlockdevOptionsGluster *gconf = NULL; QemuOpts *opts; - Error *local_err = NULL; const char *filename, *logfile; opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { ret = -EINVAL; goto out; } diff --git a/block/io.c b/block/io.c index 121ce17a490f0d50e7b087a5a16b125414f47f58..ec5e152bb70f62371b608e95d51432f76b002d6c 100644 --- a/block/io.c +++ b/block/io.c @@ -29,14 +29,13 @@ #include "block/blockjob.h" #include "block/blockjob_int.h" #include "block/block_int.h" +#include "block/coroutines.h" #include "qemu/cutils.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/main-loop.h" #include "sysemu/replay.h" -#define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */ - /* Maximum bounce buffer for copy-on-read and write zeroes, in bytes */ #define MAX_BOUNCE_BUFFER (32768 << BDRV_SECTOR_BITS) @@ -71,7 +70,7 @@ void bdrv_parent_drained_end_single(BdrvChild *c) { int drained_end_counter = 0; bdrv_parent_drained_end_single_no_poll(c, &drained_end_counter); - BDRV_POLL_WHILE(c->bs, atomic_read(&drained_end_counter) > 0); + BDRV_POLL_WHILE(c->bs, qatomic_read(&drained_end_counter) > 0); } static void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore, @@ -137,6 +136,8 @@ static void bdrv_merge_limits(BlockLimits *dst, const BlockLimits *src) void bdrv_refresh_limits(BlockDriverState *bs, Error **errp) { BlockDriver *drv = bs->drv; + BdrvChild *c; + bool have_limits; Error *local_err = NULL; memset(&bs->bl, 0, sizeof(bs->bl)); @@ -151,14 +152,21 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp) drv->bdrv_co_preadv_part) ? 1 : 512; /* Take some limits from the children as a default */ - if (bs->file) { - bdrv_refresh_limits(bs->file->bs, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; + have_limits = false; + QLIST_FOREACH(c, &bs->children, next) { + if (c->role & (BDRV_CHILD_DATA | BDRV_CHILD_FILTERED | BDRV_CHILD_COW)) + { + bdrv_refresh_limits(c->bs, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + bdrv_merge_limits(&bs->bl, &c->bs->bl); + have_limits = true; } - bdrv_merge_limits(&bs->bl, &bs->file->bs->bl); - } else { + } + + if (!have_limits) { bs->bl.min_mem_alignment = 512; bs->bl.opt_mem_alignment = qemu_real_host_page_size; @@ -166,15 +174,6 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp) bs->bl.max_iov = IOV_MAX; } - if (bs->backing) { - bdrv_refresh_limits(bs->backing->bs, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - bdrv_merge_limits(&bs->bl, &bs->backing->bs->bl); - } - /* Then let the driver override it */ if (drv->bdrv_refresh_limits) { drv->bdrv_refresh_limits(bs, errp); @@ -188,12 +187,12 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp) */ void bdrv_enable_copy_on_read(BlockDriverState *bs) { - atomic_inc(&bs->copy_on_read); + qatomic_inc(&bs->copy_on_read); } void bdrv_disable_copy_on_read(BlockDriverState *bs) { - int old = atomic_fetch_dec(&bs->copy_on_read); + int old = qatomic_fetch_dec(&bs->copy_on_read); assert(old >= 1); } @@ -221,9 +220,9 @@ static void coroutine_fn bdrv_drain_invoke_entry(void *opaque) } /* Set data->done and decrement drained_end_counter before bdrv_wakeup() */ - atomic_mb_set(&data->done, true); + qatomic_mb_set(&data->done, true); if (!data->begin) { - atomic_dec(data->drained_end_counter); + qatomic_dec(data->drained_end_counter); } bdrv_dec_in_flight(bs); @@ -250,7 +249,7 @@ static void bdrv_drain_invoke(BlockDriverState *bs, bool begin, }; if (!begin) { - atomic_inc(drained_end_counter); + qatomic_inc(drained_end_counter); } /* Make sure the driver callback completes during the polling phase for @@ -270,7 +269,7 @@ bool bdrv_drain_poll(BlockDriverState *bs, bool recursive, return true; } - if (atomic_read(&bs->in_flight)) { + if (qatomic_read(&bs->in_flight)) { return true; } @@ -384,7 +383,7 @@ void bdrv_do_drained_begin_quiesce(BlockDriverState *bs, assert(!qemu_in_coroutine()); /* Stop things in parent-to-child order */ - if (atomic_fetch_inc(&bs->quiesce_counter) == 0) { + if (qatomic_fetch_inc(&bs->quiesce_counter) == 0) { aio_disable_external(bdrv_get_aio_context(bs)); } @@ -475,7 +474,7 @@ static void bdrv_do_drained_end(BlockDriverState *bs, bool recursive, bdrv_parent_drained_end(bs, parent, ignore_bds_parents, drained_end_counter); - old_quiesce_counter = atomic_fetch_dec(&bs->quiesce_counter); + old_quiesce_counter = qatomic_fetch_dec(&bs->quiesce_counter); if (old_quiesce_counter == 1) { aio_enable_external(bdrv_get_aio_context(bs)); } @@ -494,7 +493,7 @@ void bdrv_drained_end(BlockDriverState *bs) { int drained_end_counter = 0; bdrv_do_drained_end(bs, false, NULL, false, &drained_end_counter); - BDRV_POLL_WHILE(bs, atomic_read(&drained_end_counter) > 0); + BDRV_POLL_WHILE(bs, qatomic_read(&drained_end_counter) > 0); } void bdrv_drained_end_no_poll(BlockDriverState *bs, int *drained_end_counter) @@ -506,7 +505,7 @@ void bdrv_subtree_drained_end(BlockDriverState *bs) { int drained_end_counter = 0; bdrv_do_drained_end(bs, true, NULL, false, &drained_end_counter); - BDRV_POLL_WHILE(bs, atomic_read(&drained_end_counter) > 0); + BDRV_POLL_WHILE(bs, qatomic_read(&drained_end_counter) > 0); } void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent) @@ -528,7 +527,7 @@ void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent) &drained_end_counter); } - BDRV_POLL_WHILE(child->bs, atomic_read(&drained_end_counter) > 0); + BDRV_POLL_WHILE(child->bs, qatomic_read(&drained_end_counter) > 0); } /* @@ -555,7 +554,7 @@ static void bdrv_drain_assert_idle(BlockDriverState *bs) { BdrvChild *child, *next; - assert(atomic_read(&bs->in_flight) == 0); + assert(qatomic_read(&bs->in_flight) == 0); QLIST_FOREACH_SAFE(child, &bs->children, next, next) { bdrv_drain_assert_idle(child->bs); } @@ -634,6 +633,19 @@ void bdrv_drain_all_begin(void) } } +void bdrv_drain_all_end_quiesce(BlockDriverState *bs) +{ + int drained_end_counter = 0; + + g_assert(bs->quiesce_counter > 0); + g_assert(!bs->refcnt); + + while (bs->quiesce_counter) { + bdrv_do_drained_end(bs, false, NULL, true, &drained_end_counter); + } + BDRV_POLL_WHILE(bs, qatomic_read(&drained_end_counter) > 0); +} + void bdrv_drain_all_end(void) { BlockDriverState *bs = NULL; @@ -657,7 +669,7 @@ void bdrv_drain_all_end(void) } assert(qemu_get_current_aio_context() == qemu_get_aio_context()); - AIO_WAIT_WHILE(NULL, atomic_read(&drained_end_counter) > 0); + AIO_WAIT_WHILE(NULL, qatomic_read(&drained_end_counter) > 0); assert(bdrv_drain_all_count > 0); bdrv_drain_all_count--; @@ -677,7 +689,7 @@ void bdrv_drain_all(void) static void tracked_request_end(BdrvTrackedRequest *req) { if (req->serialising) { - atomic_dec(&req->bs->serialising_in_flight); + qatomic_dec(&req->bs->serialising_in_flight); } qemu_co_mutex_lock(&req->bs->reqs_lock); @@ -779,7 +791,7 @@ bool bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align) qemu_co_mutex_lock(&bs->reqs_lock); if (!req->serialising) { - atomic_inc(&req->bs->serialising_in_flight); + qatomic_inc(&req->bs->serialising_in_flight); req->serialising = true; } @@ -843,7 +855,7 @@ static int bdrv_get_cluster_size(BlockDriverState *bs) void bdrv_inc_in_flight(BlockDriverState *bs) { - atomic_inc(&bs->in_flight); + qatomic_inc(&bs->in_flight); } void bdrv_wakeup(BlockDriverState *bs) @@ -853,7 +865,7 @@ void bdrv_wakeup(BlockDriverState *bs) void bdrv_dec_in_flight(BlockDriverState *bs) { - atomic_dec(&bs->in_flight); + qatomic_dec(&bs->in_flight); bdrv_wakeup(bs); } @@ -862,7 +874,7 @@ static bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self BlockDriverState *bs = self->bs; bool waited = false; - if (!atomic_read(&bs->serialising_in_flight)) { + if (!qatomic_read(&bs->serialising_in_flight)) { return false; } @@ -891,65 +903,10 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset, return 0; } -typedef struct RwCo { - BdrvChild *child; - int64_t offset; - QEMUIOVector *qiov; - bool is_write; - int ret; - BdrvRequestFlags flags; -} RwCo; - -static void coroutine_fn bdrv_rw_co_entry(void *opaque) -{ - RwCo *rwco = opaque; - - if (!rwco->is_write) { - rwco->ret = bdrv_co_preadv(rwco->child, rwco->offset, - rwco->qiov->size, rwco->qiov, - rwco->flags); - } else { - rwco->ret = bdrv_co_pwritev(rwco->child, rwco->offset, - rwco->qiov->size, rwco->qiov, - rwco->flags); - } - aio_wait_kick(); -} - -/* - * Process a vectored synchronous request using coroutines - */ -static int bdrv_prwv_co(BdrvChild *child, int64_t offset, - QEMUIOVector *qiov, bool is_write, - BdrvRequestFlags flags) -{ - Coroutine *co; - RwCo rwco = { - .child = child, - .offset = offset, - .qiov = qiov, - .is_write = is_write, - .ret = NOT_DONE, - .flags = flags, - }; - - if (qemu_in_coroutine()) { - /* Fast-path if already in coroutine context */ - bdrv_rw_co_entry(&rwco); - } else { - co = qemu_coroutine_create(bdrv_rw_co_entry, &rwco); - bdrv_coroutine_enter(child->bs, co); - BDRV_POLL_WHILE(child->bs, rwco.ret == NOT_DONE); - } - return rwco.ret; -} - int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset, int bytes, BdrvRequestFlags flags) { - QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, bytes); - - return bdrv_prwv_co(child, offset, &qiov, true, + return bdrv_pwritev(child, offset, bytes, NULL, BDRV_REQ_ZERO_WRITE | flags); } @@ -994,41 +951,19 @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags) } } -/* return < 0 if error. See bdrv_pwrite() for the return codes */ -int bdrv_preadv(BdrvChild *child, int64_t offset, QEMUIOVector *qiov) -{ - int ret; - - ret = bdrv_prwv_co(child, offset, qiov, false, 0); - if (ret < 0) { - return ret; - } - - return qiov->size; -} - /* See bdrv_pwrite() for the return codes */ int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int bytes) { + int ret; QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes); if (bytes < 0) { return -EINVAL; } - return bdrv_preadv(child, offset, &qiov); -} + ret = bdrv_preadv(child, offset, bytes, &qiov, 0); -int bdrv_pwritev(BdrvChild *child, int64_t offset, QEMUIOVector *qiov) -{ - int ret; - - ret = bdrv_prwv_co(child, offset, qiov, true, 0); - if (ret < 0) { - return ret; - } - - return qiov->size; + return ret < 0 ? ret : bytes; } /* Return no. of bytes on success or < 0 on error. Important errors are: @@ -1039,13 +974,16 @@ int bdrv_pwritev(BdrvChild *child, int64_t offset, QEMUIOVector *qiov) */ int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf, int bytes) { + int ret; QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes); if (bytes < 0) { return -EINVAL; } - return bdrv_pwritev(child, offset, &qiov); + ret = bdrv_pwritev(child, offset, bytes, &qiov, 0); + + return ret < 0 ? ret : bytes; } /* @@ -1502,12 +1440,13 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child, assert(num); ret = bdrv_driver_preadv(bs, offset + bytes - bytes_remaining, - num, qiov, bytes - bytes_remaining, 0); + num, qiov, + qiov_offset + bytes - bytes_remaining, 0); max_bytes -= num; } else { num = bytes_remaining; - ret = qemu_iovec_memset(qiov, bytes - bytes_remaining, 0, - bytes_remaining); + ret = qemu_iovec_memset(qiov, qiov_offset + bytes - bytes_remaining, + 0, bytes_remaining); } if (ret < 0) { goto out; @@ -1724,7 +1663,7 @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child, bdrv_inc_in_flight(bs); /* Don't do copy-on-read if we read data before write operation */ - if (atomic_read(&bs->copy_on_read)) { + if (qatomic_read(&bs->copy_on_read)) { flags |= BDRV_REQ_COPY_ON_READ; } @@ -1912,7 +1851,7 @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, uint64_t bytes, int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE); BlockDriverState *bs = child->bs; - atomic_inc(&bs->write_gen); + qatomic_inc(&bs->write_gen); /* * Discard cannot extend the image, but in error handling cases, such as @@ -2010,7 +1949,8 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, } ret = bdrv_driver_pwritev(bs, offset + bytes - bytes_remaining, - num, qiov, bytes - bytes_remaining, + num, qiov, + qiov_offset + bytes - bytes_remaining, local_flags); if (ret < 0) { break; @@ -2219,50 +2159,6 @@ int bdrv_flush_all(void) return result; } - -typedef struct BdrvCoBlockStatusData { - BlockDriverState *bs; - BlockDriverState *base; - bool want_zero; - int64_t offset; - int64_t bytes; - int64_t *pnum; - int64_t *map; - BlockDriverState **file; - int ret; - bool done; -} BdrvCoBlockStatusData; - -int coroutine_fn bdrv_co_block_status_from_file(BlockDriverState *bs, - bool want_zero, - int64_t offset, - int64_t bytes, - int64_t *pnum, - int64_t *map, - BlockDriverState **file) -{ - assert(bs->file && bs->file->bs); - *pnum = bytes; - *map = offset; - *file = bs->file->bs; - return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID; -} - -int coroutine_fn bdrv_co_block_status_from_backing(BlockDriverState *bs, - bool want_zero, - int64_t offset, - int64_t bytes, - int64_t *pnum, - int64_t *map, - BlockDriverState **file) -{ - assert(bs->backing && bs->backing->bs); - *pnum = bytes; - *map = offset; - *file = bs->backing->bs; - return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID; -} - /* * Returns the allocation status of the specified sectors. * Drivers not implementing the functionality are assumed to not support @@ -2303,6 +2199,7 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs, BlockDriverState *local_file = NULL; int64_t aligned_offset, aligned_bytes; uint32_t align; + bool has_filtered_child; assert(pnum); *pnum = 0; @@ -2328,7 +2225,8 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs, /* Must be non-NULL or bdrv_getlength() would have failed */ assert(bs->drv); - if (!bs->drv->bdrv_co_block_status) { + has_filtered_child = bdrv_filter_child(bs); + if (!bs->drv->bdrv_co_block_status && !has_filtered_child) { *pnum = bytes; ret = BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED; if (offset + bytes == total_size) { @@ -2349,9 +2247,20 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs, aligned_offset = QEMU_ALIGN_DOWN(offset, align); aligned_bytes = ROUND_UP(offset + bytes, align) - aligned_offset; - ret = bs->drv->bdrv_co_block_status(bs, want_zero, aligned_offset, - aligned_bytes, pnum, &local_map, - &local_file); + if (bs->drv->bdrv_co_block_status) { + ret = bs->drv->bdrv_co_block_status(bs, want_zero, aligned_offset, + aligned_bytes, pnum, &local_map, + &local_file); + } else { + /* Default code for filters */ + + local_file = bdrv_filter_bs(bs); + assert(local_file); + + *pnum = aligned_bytes; + local_map = aligned_offset; + ret = BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID; + } if (ret < 0) { *pnum = 0; goto out; @@ -2386,12 +2295,13 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs, if (ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ZERO)) { ret |= BDRV_BLOCK_ALLOCATED; - } else if (want_zero) { - if (bdrv_unallocated_blocks_are_zero(bs)) { + } else if (bs->drv->supports_backing) { + BlockDriverState *cow_bs = bdrv_cow_bs(bs); + + if (!cow_bs) { ret |= BDRV_BLOCK_ZERO; - } else if (bs->backing) { - BlockDriverState *bs2 = bs->backing->bs; - int64_t size2 = bdrv_getlength(bs2); + } else if (want_zero) { + int64_t size2 = bdrv_getlength(cow_bs); if (size2 >= 0 && offset >= size2) { ret |= BDRV_BLOCK_ZERO; @@ -2443,119 +2353,158 @@ early_out: return ret; } -static int coroutine_fn bdrv_co_block_status_above(BlockDriverState *bs, - BlockDriverState *base, - bool want_zero, - int64_t offset, - int64_t bytes, - int64_t *pnum, - int64_t *map, - BlockDriverState **file) +int coroutine_fn +bdrv_co_common_block_status_above(BlockDriverState *bs, + BlockDriverState *base, + bool include_base, + bool want_zero, + int64_t offset, + int64_t bytes, + int64_t *pnum, + int64_t *map, + BlockDriverState **file, + int *depth) { + int ret; BlockDriverState *p; - int ret = 0; - bool first = true; + int64_t eof = 0; + int dummy; + + assert(!include_base || base); /* Can't include NULL base */ - assert(bs != base); - for (p = bs; p != base; p = backing_bs(p)) { + if (!depth) { + depth = &dummy; + } + *depth = 0; + + if (!include_base && bs == base) { + *pnum = bytes; + return 0; + } + + ret = bdrv_co_block_status(bs, want_zero, offset, bytes, pnum, map, file); + ++*depth; + if (ret < 0 || *pnum == 0 || ret & BDRV_BLOCK_ALLOCATED || bs == base) { + return ret; + } + + if (ret & BDRV_BLOCK_EOF) { + eof = offset + *pnum; + } + + assert(*pnum <= bytes); + bytes = *pnum; + + for (p = bdrv_filter_or_cow_bs(bs); include_base || p != base; + p = bdrv_filter_or_cow_bs(p)) + { ret = bdrv_co_block_status(p, want_zero, offset, bytes, pnum, map, file); + ++*depth; if (ret < 0) { - break; + return ret; } - if (ret & BDRV_BLOCK_ZERO && ret & BDRV_BLOCK_EOF && !first) { + if (*pnum == 0) { /* - * Reading beyond the end of the file continues to read - * zeroes, but we can only widen the result to the - * unallocated length we learned from an earlier - * iteration. + * The top layer deferred to this layer, and because this layer is + * short, any zeroes that we synthesize beyond EOF behave as if they + * were allocated at this layer. + * + * We don't include BDRV_BLOCK_EOF into ret, as upper layer may be + * larger. We'll add BDRV_BLOCK_EOF if needed at function end, see + * below. */ + assert(ret & BDRV_BLOCK_EOF); *pnum = bytes; + if (file) { + *file = p; + } + ret = BDRV_BLOCK_ZERO | BDRV_BLOCK_ALLOCATED; + break; } - if (ret & (BDRV_BLOCK_ZERO | BDRV_BLOCK_DATA)) { + if (ret & BDRV_BLOCK_ALLOCATED) { + /* + * We've found the node and the status, we must break. + * + * Drop BDRV_BLOCK_EOF, as it's not for upper layer, which may be + * larger. We'll add BDRV_BLOCK_EOF if needed at function end, see + * below. + */ + ret &= ~BDRV_BLOCK_EOF; break; } - /* [offset, pnum] unallocated on this layer, which could be only - * the first part of [offset, bytes]. */ - bytes = MIN(bytes, *pnum); - first = false; - } - return ret; -} -/* Coroutine wrapper for bdrv_block_status_above() */ -static void coroutine_fn bdrv_block_status_above_co_entry(void *opaque) -{ - BdrvCoBlockStatusData *data = opaque; - - data->ret = bdrv_co_block_status_above(data->bs, data->base, - data->want_zero, - data->offset, data->bytes, - data->pnum, data->map, data->file); - data->done = true; - aio_wait_kick(); -} + if (p == base) { + assert(include_base); + break; + } -/* - * Synchronous wrapper around bdrv_co_block_status_above(). - * - * See bdrv_co_block_status_above() for details. - */ -static int bdrv_common_block_status_above(BlockDriverState *bs, - BlockDriverState *base, - bool want_zero, int64_t offset, - int64_t bytes, int64_t *pnum, - int64_t *map, - BlockDriverState **file) -{ - Coroutine *co; - BdrvCoBlockStatusData data = { - .bs = bs, - .base = base, - .want_zero = want_zero, - .offset = offset, - .bytes = bytes, - .pnum = pnum, - .map = map, - .file = file, - .done = false, - }; + /* + * OK, [offset, offset + *pnum) region is unallocated on this layer, + * let's continue the diving. + */ + assert(*pnum <= bytes); + bytes = *pnum; + } - if (qemu_in_coroutine()) { - /* Fast-path if already in coroutine context */ - bdrv_block_status_above_co_entry(&data); - } else { - co = qemu_coroutine_create(bdrv_block_status_above_co_entry, &data); - bdrv_coroutine_enter(bs, co); - BDRV_POLL_WHILE(bs, !data.done); + if (offset + *pnum == eof) { + ret |= BDRV_BLOCK_EOF; } - return data.ret; + + return ret; } int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file) { - return bdrv_common_block_status_above(bs, base, true, offset, bytes, - pnum, map, file); + return bdrv_common_block_status_above(bs, base, false, true, offset, bytes, + pnum, map, file, NULL); } int bdrv_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file) { - return bdrv_block_status_above(bs, backing_bs(bs), + return bdrv_block_status_above(bs, bdrv_filter_or_cow_bs(bs), offset, bytes, pnum, map, file); } +/* + * Check @bs (and its backing chain) to see if the range defined + * by @offset and @bytes is known to read as zeroes. + * Return 1 if that is the case, 0 otherwise and -errno on error. + * This test is meant to be fast rather than accurate so returning 0 + * does not guarantee non-zero data. + */ +int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, + int64_t bytes) +{ + int ret; + int64_t pnum = bytes; + + if (!bytes) { + return 1; + } + + ret = bdrv_common_block_status_above(bs, NULL, false, false, offset, + bytes, &pnum, NULL, NULL, NULL); + + if (ret < 0) { + return ret; + } + + return (pnum == bytes) && (ret & BDRV_BLOCK_ZERO); +} + int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t *pnum) { int ret; int64_t dummy; - ret = bdrv_common_block_status_above(bs, backing_bs(bs), false, offset, + ret = bdrv_common_block_status_above(bs, bs, true, false, offset, bytes, pnum ? pnum : &dummy, NULL, - NULL); + NULL, NULL); if (ret < 0) { return ret; } @@ -2565,8 +2514,9 @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset, /* * Given an image chain: ... -> [BASE] -> [INTER1] -> [INTER2] -> [TOP] * - * Return 1 if (a prefix of) the given range is allocated in any image - * between BASE and TOP (BASE is only included if include_base is set). + * Return a positive depth if (a prefix of) the given range is allocated + * in any image between BASE and TOP (BASE is only included if include_base + * is set). Depth 1 is TOP, 2 is the first backing layer, and so forth. * BASE can be NULL to check if the given offset is allocated in any * image of the chain. Return 0 otherwise, or negative errno on * failure. @@ -2577,152 +2527,90 @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset, * at 'offset + *pnum' may return the same allocation status (in other * words, the result is not necessarily the maximum possible range); * but 'pnum' will only be 0 when end of file is reached. - * */ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base, bool include_base, int64_t offset, int64_t bytes, int64_t *pnum) { - BlockDriverState *intermediate; - int ret; - int64_t n = bytes; - - assert(base || !include_base); - - intermediate = top; - while (include_base || intermediate != base) { - int64_t pnum_inter; - int64_t size_inter; - - assert(intermediate); - ret = bdrv_is_allocated(intermediate, offset, bytes, &pnum_inter); - if (ret < 0) { - return ret; - } - if (ret) { - *pnum = pnum_inter; - return 1; - } - - size_inter = bdrv_getlength(intermediate); - if (size_inter < 0) { - return size_inter; - } - if (n > pnum_inter && - (intermediate == top || offset + pnum_inter < size_inter)) { - n = pnum_inter; - } - - if (intermediate == base) { - break; - } - - intermediate = backing_bs(intermediate); + int depth; + int ret = bdrv_common_block_status_above(top, base, include_base, false, + offset, bytes, pnum, NULL, NULL, + &depth); + if (ret < 0) { + return ret; } - *pnum = n; + if (ret & BDRV_BLOCK_ALLOCATED) { + return depth; + } return 0; } -typedef struct BdrvVmstateCo { - BlockDriverState *bs; - QEMUIOVector *qiov; - int64_t pos; - bool is_read; - int ret; -} BdrvVmstateCo; - -static int coroutine_fn -bdrv_co_rw_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos, - bool is_read) +int coroutine_fn +bdrv_co_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos) { BlockDriver *drv = bs->drv; + BlockDriverState *child_bs = bdrv_primary_bs(bs); int ret = -ENOTSUP; + if (!drv) { + return -ENOMEDIUM; + } + bdrv_inc_in_flight(bs); - if (!drv) { - ret = -ENOMEDIUM; - } else if (drv->bdrv_load_vmstate) { - if (is_read) { - ret = drv->bdrv_load_vmstate(bs, qiov, pos); - } else { - ret = drv->bdrv_save_vmstate(bs, qiov, pos); - } - } else if (bs->file) { - ret = bdrv_co_rw_vmstate(bs->file->bs, qiov, pos, is_read); + if (drv->bdrv_load_vmstate) { + ret = drv->bdrv_load_vmstate(bs, qiov, pos); + } else if (child_bs) { + ret = bdrv_co_readv_vmstate(child_bs, qiov, pos); } bdrv_dec_in_flight(bs); + return ret; } -static void coroutine_fn bdrv_co_rw_vmstate_entry(void *opaque) +int coroutine_fn +bdrv_co_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos) { - BdrvVmstateCo *co = opaque; - co->ret = bdrv_co_rw_vmstate(co->bs, co->qiov, co->pos, co->is_read); - aio_wait_kick(); -} + BlockDriver *drv = bs->drv; + BlockDriverState *child_bs = bdrv_primary_bs(bs); + int ret = -ENOTSUP; -static inline int -bdrv_rw_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos, - bool is_read) -{ - if (qemu_in_coroutine()) { - return bdrv_co_rw_vmstate(bs, qiov, pos, is_read); - } else { - BdrvVmstateCo data = { - .bs = bs, - .qiov = qiov, - .pos = pos, - .is_read = is_read, - .ret = -EINPROGRESS, - }; - Coroutine *co = qemu_coroutine_create(bdrv_co_rw_vmstate_entry, &data); + if (!drv) { + return -ENOMEDIUM; + } + + bdrv_inc_in_flight(bs); - bdrv_coroutine_enter(bs, co); - BDRV_POLL_WHILE(bs, data.ret == -EINPROGRESS); - return data.ret; + if (drv->bdrv_save_vmstate) { + ret = drv->bdrv_save_vmstate(bs, qiov, pos); + } else if (child_bs) { + ret = bdrv_co_writev_vmstate(child_bs, qiov, pos); } + + bdrv_dec_in_flight(bs); + + return ret; } int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf, int64_t pos, int size) { QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, size); - int ret; - - ret = bdrv_writev_vmstate(bs, &qiov, pos); - if (ret < 0) { - return ret; - } - - return size; -} + int ret = bdrv_writev_vmstate(bs, &qiov, pos); -int bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos) -{ - return bdrv_rw_vmstate(bs, qiov, pos, false); + return ret < 0 ? ret : size; } int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size) { QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, size); - int ret; - - ret = bdrv_readv_vmstate(bs, &qiov, pos); - if (ret < 0) { - return ret; - } + int ret = bdrv_readv_vmstate(bs, &qiov, pos); - return size; -} - -int bdrv_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos) -{ - return bdrv_rw_vmstate(bs, qiov, pos, true); + return ret < 0 ? ret : size; } /**************************************************************/ @@ -2762,22 +2650,10 @@ void bdrv_aio_cancel_async(BlockAIOCB *acb) /**************************************************************/ /* Coroutine block device emulation */ -typedef struct FlushCo { - BlockDriverState *bs; - int ret; -} FlushCo; - - -static void coroutine_fn bdrv_flush_co_entry(void *opaque) -{ - FlushCo *rwco = opaque; - - rwco->ret = bdrv_co_flush(rwco->bs); - aio_wait_kick(); -} - int coroutine_fn bdrv_co_flush(BlockDriverState *bs) { + BdrvChild *primary_child = bdrv_primary_child(bs); + BdrvChild *child; int current_gen; int ret = 0; @@ -2789,7 +2665,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs) } qemu_co_mutex_lock(&bs->reqs_lock); - current_gen = atomic_read(&bs->write_gen); + current_gen = qatomic_read(&bs->write_gen); /* Wait until any previous flushes are completed */ while (bs->active_flush_req) { @@ -2807,7 +2683,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs) } /* Write back cached data to the OS even with cache=unsafe */ - BLKDBG_EVENT(bs->file, BLKDBG_FLUSH_TO_OS); + BLKDBG_EVENT(primary_child, BLKDBG_FLUSH_TO_OS); if (bs->drv->bdrv_co_flush_to_os) { ret = bs->drv->bdrv_co_flush_to_os(bs); if (ret < 0) { @@ -2817,15 +2693,15 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs) /* But don't actually force it to the disk with cache=unsafe */ if (bs->open_flags & BDRV_O_NO_FLUSH) { - goto flush_parent; + goto flush_children; } /* Check if we really need to flush anything */ if (bs->flushed_gen == current_gen) { - goto flush_parent; + goto flush_children; } - BLKDBG_EVENT(bs->file, BLKDBG_FLUSH_TO_DISK); + BLKDBG_EVENT(primary_child, BLKDBG_FLUSH_TO_DISK); if (!bs->drv) { /* bs->drv->bdrv_co_flush() might have ejected the BDS * (even in case of apparent success) */ @@ -2869,8 +2745,17 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs) /* Now flush the underlying protocol. It will also have BDRV_O_NO_FLUSH * in the case of cache=unsafe, so there are no useless flushes. */ -flush_parent: - ret = bs->file ? bdrv_co_flush(bs->file->bs) : 0; +flush_children: + ret = 0; + QLIST_FOREACH(child, &bs->children, next) { + if (child->perm & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) { + int this_child_ret = bdrv_co_flush(child->bs); + if (!ret) { + ret = this_child_ret; + } + } + } + out: /* Notify any pending flushes that we have completed */ if (ret == 0) { @@ -2888,40 +2773,6 @@ early_exit: return ret; } -int bdrv_flush(BlockDriverState *bs) -{ - Coroutine *co; - FlushCo flush_co = { - .bs = bs, - .ret = NOT_DONE, - }; - - if (qemu_in_coroutine()) { - /* Fast-path if already in coroutine context */ - bdrv_flush_co_entry(&flush_co); - } else { - co = qemu_coroutine_create(bdrv_flush_co_entry, &flush_co); - bdrv_coroutine_enter(bs, co); - BDRV_POLL_WHILE(bs, flush_co.ret == NOT_DONE); - } - - return flush_co.ret; -} - -typedef struct DiscardCo { - BdrvChild *child; - int64_t offset; - int64_t bytes; - int ret; -} DiscardCo; -static void coroutine_fn bdrv_pdiscard_co_entry(void *opaque) -{ - DiscardCo *rwco = opaque; - - rwco->ret = bdrv_co_pdiscard(rwco->child, rwco->offset, rwco->bytes); - aio_wait_kick(); -} - int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes) { @@ -3036,28 +2887,6 @@ out: return ret; } -int bdrv_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes) -{ - Coroutine *co; - DiscardCo rwco = { - .child = child, - .offset = offset, - .bytes = bytes, - .ret = NOT_DONE, - }; - - if (qemu_in_coroutine()) { - /* Fast-path if already in coroutine context */ - bdrv_pdiscard_co_entry(&rwco); - } else { - co = qemu_coroutine_create(bdrv_pdiscard_co_entry, &rwco); - bdrv_coroutine_enter(child->bs, co); - BDRV_POLL_WHILE(child->bs, rwco.ret == NOT_DONE); - } - - return rwco.ret; -} - int bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf) { BlockDriver *drv = bs->drv; @@ -3155,7 +2984,7 @@ void bdrv_io_plug(BlockDriverState *bs) bdrv_io_plug(child->bs); } - if (atomic_fetch_inc(&bs->io_plugged) == 0) { + if (qatomic_fetch_inc(&bs->io_plugged) == 0) { BlockDriver *drv = bs->drv; if (drv && drv->bdrv_io_plug) { drv->bdrv_io_plug(bs); @@ -3168,7 +2997,7 @@ void bdrv_io_unplug(BlockDriverState *bs) BdrvChild *child; assert(bs->io_plugged); - if (atomic_fetch_dec(&bs->io_plugged) == 1) { + if (qatomic_fetch_dec(&bs->io_plugged) == 1) { BlockDriver *drv = bs->drv; if (drv && drv->bdrv_io_unplug) { drv->bdrv_io_unplug(bs); @@ -3344,6 +3173,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, Error **errp) { BlockDriverState *bs = child->bs; + BdrvChild *filtered, *backing; BlockDriver *drv = bs->drv; BdrvTrackedRequest req; int64_t old_size, new_bytes; @@ -3395,6 +3225,9 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, goto out; } + filtered = bdrv_filter_child(bs); + backing = bdrv_cow_child(bs); + /* * If the image has a backing file that is large enough that it would * provide data for the new area, we cannot leave it unallocated because @@ -3405,10 +3238,10 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, * backing file, taking care of keeping things consistent with that backing * file is the user's responsibility. */ - if (new_bytes && bs->backing) { + if (new_bytes && backing) { int64_t backing_len; - backing_len = bdrv_getlength(backing_bs(bs)); + backing_len = bdrv_getlength(backing->bs); if (backing_len < 0) { ret = backing_len; error_setg_errno(errp, -ret, "Could not get backing file size"); @@ -3427,8 +3260,8 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, goto out; } ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp); - } else if (bs->file && drv->is_filter) { - ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp); + } else if (filtered) { + ret = bdrv_co_truncate(filtered, offset, exact, prealloc, flags, errp); } else { error_setg(errp, "Image format driver does not support resize"); ret = -ENOTSUP; @@ -3455,47 +3288,3 @@ out: return ret; } - -typedef struct TruncateCo { - BdrvChild *child; - int64_t offset; - bool exact; - PreallocMode prealloc; - BdrvRequestFlags flags; - Error **errp; - int ret; -} TruncateCo; - -static void coroutine_fn bdrv_truncate_co_entry(void *opaque) -{ - TruncateCo *tco = opaque; - tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->exact, - tco->prealloc, tco->flags, tco->errp); - aio_wait_kick(); -} - -int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact, - PreallocMode prealloc, BdrvRequestFlags flags, Error **errp) -{ - Coroutine *co; - TruncateCo tco = { - .child = child, - .offset = offset, - .exact = exact, - .prealloc = prealloc, - .flags = flags, - .errp = errp, - .ret = NOT_DONE, - }; - - if (qemu_in_coroutine()) { - /* Fast-path if already in coroutine context */ - bdrv_truncate_co_entry(&tco); - } else { - co = qemu_coroutine_create(bdrv_truncate_co_entry, &tco); - bdrv_coroutine_enter(child->bs, co); - BDRV_POLL_WHILE(child->bs, tco.ret == NOT_DONE); - } - - return tco.ret; -} diff --git a/block/io_uring.c b/block/io_uring.c index a3142ca98905b912257b3c3606f748586ab125d6..00a3ee9fb852c82295aace92f71517afa45bf9be 100644 --- a/block/io_uring.c +++ b/block/io_uring.c @@ -231,7 +231,7 @@ static int ioq_submit(LuringState *s) trace_luring_io_uring_submit(s, ret); /* Prevent infinite loop if submission is refused */ if (ret <= 0) { - if (ret == -EAGAIN) { + if (ret == -EAGAIN || ret == -EINTR) { continue; } break; @@ -277,13 +277,10 @@ static void qemu_luring_completion_cb(void *opaque) static bool qemu_luring_poll_cb(void *opaque) { LuringState *s = opaque; - struct io_uring_cqe *cqes; - if (io_uring_peek_cqe(&s->ring, &cqes) == 0) { - if (cqes) { - luring_process_completions_and_submit(s); - return true; - } + if (io_uring_cq_ready(&s->ring)) { + luring_process_completions_and_submit(s); + return true; } return false; @@ -428,6 +425,6 @@ LuringState *luring_init(Error **errp) void luring_cleanup(LuringState *s) { io_uring_queue_exit(&s->ring); - g_free(s); trace_luring_cleanup_state(s); + g_free(s); } diff --git a/block/iscsi.c b/block/iscsi.c index a8b76979d8be483e1b483b47167f22861aaa3e5d..e30a7e3606b6e10495fa969c5c986af4cfb8e0ee 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -42,7 +42,7 @@ #include "qemu/uuid.h" #include "sysemu/replay.h" #include "qapi/error.h" -#include "qapi/qapi-commands-misc.h" +#include "qapi/qapi-commands-machine.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qstring.h" #include "crypto/secret.h" @@ -241,9 +241,11 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status, iTask->status = status; iTask->do_retry = 0; + iTask->err_code = 0; iTask->task = task; if (status != SCSI_STATUS_GOOD) { + iTask->err_code = -EIO; if (iTask->retries++ < ISCSI_CMD_RETRIES) { if (status == SCSI_STATUS_BUSY || status == SCSI_STATUS_TIMEOUT || @@ -266,16 +268,16 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status, timer_mod(&iTask->retry_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + retry_time); iTask->do_retry = 1; - } - } else if (status == SCSI_STATUS_CHECK_CONDITION) { - int error = iscsi_translate_sense(&task->sense); - if (error == EAGAIN) { - error_report("iSCSI CheckCondition: %s", - iscsi_get_error(iscsi)); - iTask->do_retry = 1; - } else { - iTask->err_code = -error; - iTask->err_str = g_strdup(iscsi_get_error(iscsi)); + } else if (status == SCSI_STATUS_CHECK_CONDITION) { + int error = iscsi_translate_sense(&task->sense); + if (error == EAGAIN) { + error_report("iSCSI CheckCondition: %s", + iscsi_get_error(iscsi)); + iTask->do_retry = 1; + } else { + iTask->err_code = -error; + iTask->err_str = g_strdup(iscsi_get_error(iscsi)); + } } } } @@ -1792,9 +1794,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, int i, ret = 0, timeout = 0, lun; opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { ret = -EINVAL; goto out; } @@ -2163,7 +2163,6 @@ static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset, static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { IscsiLun *iscsilun = bs->opaque; - bdi->unallocated_blocks_are_zero = iscsilun->lbprz; bdi->cluster_size = iscsilun->cluster_size; return 0; } diff --git a/block/meson.build b/block/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..5dcc1e5cceb0ca05e382ebc265d3bac1ecf8b9a2 --- /dev/null +++ b/block/meson.build @@ -0,0 +1,126 @@ +block_ss.add(genh) +block_ss.add(files( + 'accounting.c', + 'aio_task.c', + 'amend.c', + 'backup.c', + 'backup-top.c', + 'blkdebug.c', + 'blklogwrites.c', + 'blkverify.c', + 'block-backend.c', + 'block-copy.c', + 'commit.c', + 'copy-on-read.c', + 'create.c', + 'crypto.c', + 'dirty-bitmap.c', + 'filter-compress.c', + 'io.c', + 'mirror.c', + 'nbd.c', + 'null.c', + 'qapi.c', + 'qcow2-bitmap.c', + 'qcow2-cache.c', + 'qcow2-cluster.c', + 'qcow2-refcount.c', + 'qcow2-snapshot.c', + 'qcow2-threads.c', + 'qcow2.c', + 'quorum.c', + 'raw-format.c', + 'snapshot.c', + 'throttle-groups.c', + 'throttle.c', + 'vhdx-endian.c', + 'vhdx-log.c', + 'vhdx.c', + 'vmdk.c', + 'vpc.c', + 'write-threshold.c', +), zstd, zlib) + +softmmu_ss.add(when: 'CONFIG_TCG', if_true: files('blkreplay.c')) + +block_ss.add(when: 'CONFIG_QCOW1', if_true: files('qcow.c')) +block_ss.add(when: 'CONFIG_VDI', if_true: files('vdi.c')) +block_ss.add(when: 'CONFIG_CLOOP', if_true: files('cloop.c')) +block_ss.add(when: 'CONFIG_BOCHS', if_true: files('bochs.c')) +block_ss.add(when: 'CONFIG_VVFAT', if_true: files('vvfat.c')) +block_ss.add(when: 'CONFIG_DMG', if_true: files('dmg.c')) +block_ss.add(when: 'CONFIG_QED', if_true: files( + 'qed-check.c', + 'qed-cluster.c', + 'qed-l2-cache.c', + 'qed-table.c', + 'qed.c', +)) +block_ss.add(when: [libxml2, 'CONFIG_PARALLELS'], if_true: files('parallels.c')) +block_ss.add(when: 'CONFIG_WIN32', if_true: files('file-win32.c', 'win32-aio.c')) +block_ss.add(when: 'CONFIG_POSIX', if_true: [files('file-posix.c'), coref, iokit]) +block_ss.add(when: 'CONFIG_LIBISCSI', if_true: files('iscsi-opts.c')) +block_ss.add(when: 'CONFIG_LINUX', if_true: files('nvme.c')) +block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c')) +block_ss.add(when: 'CONFIG_SHEEPDOG', if_true: files('sheepdog.c')) +block_ss.add(when: ['CONFIG_LINUX_AIO', libaio], if_true: files('linux-aio.c')) +block_ss.add(when: ['CONFIG_LINUX_IO_URING', linux_io_uring], if_true: files('io_uring.c')) + +block_modules = {} + +modsrc = [] +foreach m : [ + ['CONFIG_CURL', 'curl', [curl, glib], 'curl.c'], + ['CONFIG_GLUSTERFS', 'gluster', glusterfs, 'gluster.c'], + ['CONFIG_LIBISCSI', 'iscsi', libiscsi, 'iscsi.c'], + ['CONFIG_LIBNFS', 'nfs', libnfs, 'nfs.c'], + ['CONFIG_LIBSSH', 'ssh', libssh, 'ssh.c'], + ['CONFIG_RBD', 'rbd', rbd, 'rbd.c'], +] + if config_host.has_key(m[0]) + if enable_modules + modsrc += files(m[3]) + endif + module_ss = ss.source_set() + module_ss.add(when: m[2], if_true: files(m[3])) + block_modules += {m[1] : module_ss} + endif +endforeach + +# those are not exactly regular block modules, so treat them apart +if 'CONFIG_DMG' in config_host + foreach m : [ + ['CONFIG_LZFSE', 'dmg-lzfse', liblzfse, 'dmg-lzfse.c'], + ['CONFIG_BZIP2', 'dmg-bz2', [glib, libbzip2], 'dmg-bz2.c'] + ] + if config_host.has_key(m[0]) + module_ss = ss.source_set() + module_ss.add(when: m[2], if_true: files(m[3])) + block_modules += {m[1] : module_ss} + endif + endforeach +endif + +module_block_py = find_program('../scripts/modules/module_block.py') +module_block_h = custom_target('module_block.h', + output: 'module_block.h', + input: modsrc, + command: [module_block_py, '@OUTPUT0@', modsrc]) +block_ss.add(module_block_h) + +wrapper_py = find_program('../scripts/block-coroutine-wrapper.py') +block_gen_c = custom_target('block-gen.c', + output: 'block-gen.c', + input: files('../include/block/block.h', + 'coroutines.h'), + command: [wrapper_py, '@OUTPUT@', '@INPUT@']) +block_ss.add(block_gen_c) + +block_ss.add(files('stream.c')) + +softmmu_ss.add(files('qapi-sysemu.c')) + +subdir('export') +subdir('monitor') + +modules += {'block': block_modules} diff --git a/block/mirror.c b/block/mirror.c index e8e8844afc409e0c517c8b0f1c7d7686e0326ae2..8e1ad6eceb57bd5943d62b7d016a1990010ad230 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -42,6 +42,7 @@ typedef struct MirrorBlockJob { BlockBackend *target; BlockDriverState *mirror_top_bs; BlockDriverState *base; + BlockDriverState *base_overlay; /* The name of the graph node to replace */ char *replaces; @@ -677,8 +678,10 @@ static int mirror_exit_common(Job *job) &error_abort); if (!abort && s->backing_mode == MIRROR_SOURCE_BACKING_CHAIN) { BlockDriverState *backing = s->is_none_mode ? src : s->base; - if (backing_bs(target_bs) != backing) { - bdrv_set_backing_hd(target_bs, backing, &local_err); + BlockDriverState *unfiltered_target = bdrv_skip_filters(target_bs); + + if (bdrv_cow_bs(unfiltered_target) != backing) { + bdrv_set_backing_hd(unfiltered_target, backing, &local_err); if (local_err) { error_report_err(local_err); local_err = NULL; @@ -740,7 +743,7 @@ static int mirror_exit_common(Job *job) * valid. */ block_job_remove_all_bdrv(bjob); - bdrv_replace_node(mirror_top_bs, backing_bs(mirror_top_bs), &error_abort); + bdrv_replace_node(mirror_top_bs, mirror_top_bs->backing->bs, &error_abort); /* We just changed the BDS the job BB refers to (with either or both of the * bdrv_replace_node() calls), so switch the BB back so the cleanup does @@ -786,7 +789,6 @@ static void coroutine_fn mirror_throttle(MirrorBlockJob *s) static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s) { int64_t offset; - BlockDriverState *base = s->base; BlockDriverState *bs = s->mirror_top_bs->backing->bs; BlockDriverState *target_bs = blk_bs(s->target); int ret; @@ -837,13 +839,14 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s) return 0; } - ret = bdrv_is_allocated_above(bs, base, false, offset, bytes, &count); + ret = bdrv_is_allocated_above(bs, s->base_overlay, true, offset, bytes, + &count); if (ret < 0) { return ret; } assert(count); - if (ret == 1) { + if (ret > 0) { bdrv_set_dirty_bitmap(s->dirty_bitmap, offset, count); } offset += count; @@ -936,7 +939,7 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) } else { s->target_cluster_size = BDRV_SECTOR_SIZE; } - if (backing_filename[0] && !target_bs->backing && + if (backing_filename[0] && !bdrv_backing_chain_next(target_bs) && s->granularity < s->target_cluster_size) { s->buf_size = MAX(s->buf_size, s->target_cluster_size); s->cow_bitmap = bitmap_new(length); @@ -1116,8 +1119,9 @@ static void mirror_complete(Job *job, Error **errp) if (s->backing_mode == MIRROR_OPEN_BACKING_CHAIN) { int ret; - assert(!target->backing); - ret = bdrv_open_backing_file(target, NULL, "backing", errp); + assert(!bdrv_backing_chain_next(target)); + ret = bdrv_open_backing_file(bdrv_skip_filters(target), NULL, + "backing", errp); if (ret < 0) { return; } @@ -1527,7 +1531,6 @@ static BlockDriver bdrv_mirror_top = { .bdrv_co_pwrite_zeroes = bdrv_mirror_top_pwrite_zeroes, .bdrv_co_pdiscard = bdrv_mirror_top_pdiscard, .bdrv_co_flush = bdrv_mirror_top_flush, - .bdrv_co_block_status = bdrv_co_block_status_from_backing, .bdrv_refresh_filename = bdrv_mirror_top_refresh_filename, .bdrv_child_perm = bdrv_mirror_top_child_perm, @@ -1555,8 +1558,8 @@ static BlockJob *mirror_start_job( MirrorBlockJob *s; MirrorBDSOpaque *bs_opaque; BlockDriverState *mirror_top_bs; - bool target_graph_mod; bool target_is_backing; + uint64_t target_perms, target_shared_perms; Error *local_err = NULL; int ret; @@ -1575,7 +1578,7 @@ static BlockJob *mirror_start_job( buf_size = DEFAULT_MIRROR_BUF_SIZE; } - if (bs == target) { + if (bdrv_skip_filters(bs) == bdrv_skip_filters(target)) { error_setg(errp, "Can't mirror node into itself"); return NULL; } @@ -1639,15 +1642,50 @@ static BlockJob *mirror_start_job( * In the case of active commit, things look a bit different, though, * because the target is an already populated backing file in active use. * We can allow anything except resize there.*/ + + target_perms = BLK_PERM_WRITE; + target_shared_perms = BLK_PERM_WRITE_UNCHANGED; + target_is_backing = bdrv_chain_contains(bs, target); - target_graph_mod = (backing_mode != MIRROR_LEAVE_BACKING_CHAIN); + if (target_is_backing) { + int64_t bs_size, target_size; + bs_size = bdrv_getlength(bs); + if (bs_size < 0) { + error_setg_errno(errp, -bs_size, + "Could not inquire top image size"); + goto fail; + } + + target_size = bdrv_getlength(target); + if (target_size < 0) { + error_setg_errno(errp, -target_size, + "Could not inquire base image size"); + goto fail; + } + + if (target_size < bs_size) { + target_perms |= BLK_PERM_RESIZE; + } + + target_shared_perms |= BLK_PERM_CONSISTENT_READ + | BLK_PERM_WRITE + | BLK_PERM_GRAPH_MOD; + } else if (bdrv_chain_contains(bs, bdrv_skip_filters(target))) { + /* + * We may want to allow this in the future, but it would + * require taking some extra care. + */ + error_setg(errp, "Cannot mirror to a filter on top of a node in the " + "source's backing chain"); + goto fail; + } + + if (backing_mode != MIRROR_LEAVE_BACKING_CHAIN) { + target_perms |= BLK_PERM_GRAPH_MOD; + } + s->target = blk_new(s->common.job.aio_context, - BLK_PERM_WRITE | BLK_PERM_RESIZE | - (target_graph_mod ? BLK_PERM_GRAPH_MOD : 0), - BLK_PERM_WRITE_UNCHANGED | - (target_is_backing ? BLK_PERM_CONSISTENT_READ | - BLK_PERM_WRITE | - BLK_PERM_GRAPH_MOD : 0)); + target_perms, target_shared_perms); ret = blk_insert_bs(s->target, target, errp); if (ret < 0) { goto fail; @@ -1672,6 +1710,7 @@ static BlockJob *mirror_start_job( s->zero_target = zero_target; s->copy_mode = copy_mode; s->base = base; + s->base_overlay = bdrv_find_overlay(bs, base); s->granularity = granularity; s->buf_size = ROUND_UP(buf_size, granularity); s->unmap = unmap; @@ -1702,15 +1741,39 @@ static BlockJob *mirror_start_job( /* In commit_active_start() all intermediate nodes disappear, so * any jobs in them must be blocked */ if (target_is_backing) { - BlockDriverState *iter; - for (iter = backing_bs(bs); iter != target; iter = backing_bs(iter)) { - /* XXX BLK_PERM_WRITE needs to be allowed so we don't block - * ourselves at s->base (if writes are blocked for a node, they are - * also blocked for its backing file). The other options would be a - * second filter driver above s->base (== target). */ + BlockDriverState *iter, *filtered_target; + uint64_t iter_shared_perms; + + /* + * The topmost node with + * bdrv_skip_filters(filtered_target) == bdrv_skip_filters(target) + */ + filtered_target = bdrv_cow_bs(bdrv_find_overlay(bs, target)); + + assert(bdrv_skip_filters(filtered_target) == + bdrv_skip_filters(target)); + + /* + * XXX BLK_PERM_WRITE needs to be allowed so we don't block + * ourselves at s->base (if writes are blocked for a node, they are + * also blocked for its backing file). The other options would be a + * second filter driver above s->base (== target). + */ + iter_shared_perms = BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE; + + for (iter = bdrv_filter_or_cow_bs(bs); iter != target; + iter = bdrv_filter_or_cow_bs(iter)) + { + if (iter == filtered_target) { + /* + * From here on, all nodes are filters on the base. + * This allows us to share BLK_PERM_CONSISTENT_READ. + */ + iter_shared_perms |= BLK_PERM_CONSISTENT_READ; + } + ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0, - BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE, - errp); + iter_shared_perms, errp); if (ret < 0) { goto fail; } @@ -1746,7 +1809,7 @@ fail: bs_opaque->stop = true; bdrv_child_refresh_perms(mirror_top_bs, mirror_top_bs->backing, &error_abort); - bdrv_replace_node(mirror_top_bs, backing_bs(mirror_top_bs), &error_abort); + bdrv_replace_node(mirror_top_bs, mirror_top_bs->backing->bs, &error_abort); bdrv_unref(mirror_top_bs); @@ -1774,7 +1837,7 @@ void mirror_start(const char *job_id, BlockDriverState *bs, return; } is_none_mode = mode == MIRROR_SYNC_MODE_NONE; - base = mode == MIRROR_SYNC_MODE_TOP ? backing_bs(bs) : NULL; + base = mode == MIRROR_SYNC_MODE_TOP ? bdrv_backing_chain_next(bs) : NULL; mirror_start_job(job_id, bs, creation_flags, target, replaces, speed, granularity, buf_size, backing_mode, zero_target, on_source_error, on_target_error, unmap, NULL, NULL, diff --git a/block/monitor/Makefile.objs b/block/monitor/Makefile.objs deleted file mode 100644 index 39acf85022241c5bd4572c9d3c8655450c2a6657..0000000000000000000000000000000000000000 --- a/block/monitor/Makefile.objs +++ /dev/null @@ -1,2 +0,0 @@ -common-obj-y += block-hmp-cmds.o -block-obj-y += bitmap-qmp-cmds.o diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c index 4c8c37517243fe0e4e2cfab94e3da3354a561913..d15a2be827bb469340dd6cf3d797373d15ed58fb 100644 --- a/block/monitor/block-hmp-cmds.c +++ b/block/monitor/block-hmp-cmds.c @@ -40,6 +40,7 @@ #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "qapi/qapi-commands-block.h" +#include "qapi/qapi-commands-block-export.h" #include "qapi/qmp/qdict.h" #include "qapi/error.h" #include "qapi/qmp/qerror.h" @@ -217,7 +218,7 @@ void hmp_commit(Monitor *mon, const QDict *qdict) return; } - bs = blk_bs(blk); + bs = bdrv_skip_implicit_filters(blk_bs(blk)); aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); @@ -397,7 +398,7 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict) Error *local_err = NULL; BlockInfoList *block_list, *info; SocketAddress *addr; - BlockExportNbd export; + NbdServerAddOptions export; if (writable && !all) { error_setg(&local_err, "-w only valid together with -a"); @@ -410,7 +411,7 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict) goto exit; } - nbd_server_start(addr, NULL, NULL, &local_err); + nbd_server_start(addr, NULL, NULL, 0, &local_err); qapi_free_SocketAddress(addr); if (local_err != NULL) { goto exit; @@ -430,7 +431,7 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict) continue; } - export = (BlockExportNbd) { + export = (NbdServerAddOptions) { .device = info->value->device, .has_writable = true, .writable = writable, @@ -457,7 +458,7 @@ void hmp_nbd_server_add(Monitor *mon, const QDict *qdict) bool writable = qdict_get_try_bool(qdict, "writable", false); Error *local_err = NULL; - BlockExportNbd export = { + NbdServerAddOptions export = { .device = (char *) device, .has_name = !!name, .name = (char *) name, @@ -475,8 +476,8 @@ void hmp_nbd_server_remove(Monitor *mon, const QDict *qdict) bool force = qdict_get_try_bool(qdict, "force", false); Error *err = NULL; - /* Rely on NBD_SERVER_REMOVE_MODE_SAFE being the default */ - qmp_nbd_server_remove(name, force, NBD_SERVER_REMOVE_MODE_HARD, &err); + /* Rely on BLOCK_EXPORT_REMOVE_MODE_SAFE being the default */ + qmp_nbd_server_remove(name, force, BLOCK_EXPORT_REMOVE_MODE_HARD, &err); hmp_handle_error(mon, err); } diff --git a/block/monitor/meson.build b/block/monitor/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..374aac1140caaafa5a282c9810902814432770a6 --- /dev/null +++ b/block/monitor/meson.build @@ -0,0 +1,2 @@ +softmmu_ss.add(files('block-hmp-cmds.c')) +block_ss.add(files('bitmap-qmp-cmds.c')) diff --git a/block/nbd.c b/block/nbd.c index 4ac23c8f62994c025467f3958a6870ea2db89efd..42536702b6f9ca996c8adbf8c5feb6b89111f621 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -38,6 +38,7 @@ #include "qapi/qapi-visit-sockets.h" #include "qapi/qmp/qstring.h" +#include "qapi/clone-visitor.h" #include "block/qdict.h" #include "block/nbd.h" @@ -62,6 +63,47 @@ typedef enum NBDClientState { NBD_CLIENT_QUIT } NBDClientState; +typedef enum NBDConnectThreadState { + /* No thread, no pending results */ + CONNECT_THREAD_NONE, + + /* Thread is running, no results for now */ + CONNECT_THREAD_RUNNING, + + /* + * Thread is running, but requestor exited. Thread should close + * the new socket and free the connect state on exit. + */ + CONNECT_THREAD_RUNNING_DETACHED, + + /* Thread finished, results are stored in a state */ + CONNECT_THREAD_FAIL, + CONNECT_THREAD_SUCCESS +} NBDConnectThreadState; + +typedef struct NBDConnectThread { + /* Initialization constants */ + SocketAddress *saddr; /* address to connect to */ + /* + * Bottom half to schedule on completion. Scheduled only if bh_ctx is not + * NULL + */ + QEMUBHFunc *bh_func; + void *bh_opaque; + + /* + * Result of last attempt. Valid in FAIL and SUCCESS states. + * If you want to steal error, don't forget to set pointer to NULL. + */ + QIOChannelSocket *sioc; + Error *err; + + /* state and bh_ctx are protected by mutex */ + QemuMutex mutex; + NBDConnectThreadState state; /* current state of the thread */ + AioContext *bh_ctx; /* where to schedule bh (NULL means don't schedule) */ +} NBDConnectThread; + typedef struct BDRVNBDState { QIOChannelSocket *sioc; /* The master data channel */ QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */ @@ -80,6 +122,8 @@ typedef struct BDRVNBDState { Error *connect_err; bool wait_in_flight; + QEMUTimer *reconnect_delay_timer; + NBDClientRequest requests[MAX_NBD_REQUESTS]; NBDReply reply; BlockDriverState *bs; @@ -91,9 +135,20 @@ typedef struct BDRVNBDState { QCryptoTLSCreds *tlscreds; const char *hostname; char *x_dirty_bitmap; + bool alloc_depth; + + bool wait_connect; + NBDConnectThread *connect_thread; } BDRVNBDState; -static int nbd_client_connect(BlockDriverState *bs, Error **errp); +static QIOChannelSocket *nbd_establish_connection(SocketAddress *saddr, + Error **errp); +static QIOChannelSocket *nbd_co_establish_connection(BlockDriverState *bs, + Error **errp); +static void nbd_co_establish_connection_cancel(BlockDriverState *bs, + bool detach); +static int nbd_client_handshake(BlockDriverState *bs, QIOChannelSocket *sioc, + Error **errp); static void nbd_clear_bdrvstate(BDRVNBDState *s) { @@ -136,10 +191,49 @@ static void nbd_recv_coroutines_wake_all(BDRVNBDState *s) } } +static void reconnect_delay_timer_del(BDRVNBDState *s) +{ + if (s->reconnect_delay_timer) { + timer_del(s->reconnect_delay_timer); + timer_free(s->reconnect_delay_timer); + s->reconnect_delay_timer = NULL; + } +} + +static void reconnect_delay_timer_cb(void *opaque) +{ + BDRVNBDState *s = opaque; + + if (s->state == NBD_CLIENT_CONNECTING_WAIT) { + s->state = NBD_CLIENT_CONNECTING_NOWAIT; + while (qemu_co_enter_next(&s->free_sema, NULL)) { + /* Resume all queued requests */ + } + } + + reconnect_delay_timer_del(s); +} + +static void reconnect_delay_timer_init(BDRVNBDState *s, uint64_t expire_time_ns) +{ + if (s->state != NBD_CLIENT_CONNECTING_WAIT) { + return; + } + + assert(!s->reconnect_delay_timer); + s->reconnect_delay_timer = aio_timer_new(bdrv_get_aio_context(s->bs), + QEMU_CLOCK_REALTIME, + SCALE_NS, + reconnect_delay_timer_cb, s); + timer_mod(s->reconnect_delay_timer, expire_time_ns); +} + static void nbd_client_detach_aio_context(BlockDriverState *bs) { BDRVNBDState *s = (BDRVNBDState *)bs->opaque; + /* Timer is deleted in nbd_client_co_drain_begin() */ + assert(!s->reconnect_delay_timer); qio_channel_detach_aio_context(QIO_CHANNEL(s->ioc)); } @@ -188,6 +282,15 @@ static void coroutine_fn nbd_client_co_drain_begin(BlockDriverState *bs) if (s->connection_co_sleep_ns_state) { qemu_co_sleep_wake(s->connection_co_sleep_ns_state); } + + nbd_co_establish_connection_cancel(bs, false); + + reconnect_delay_timer_del(s); + + if (s->state == NBD_CLIENT_CONNECTING_WAIT) { + s->state = NBD_CLIENT_CONNECTING_NOWAIT; + qemu_co_queue_restart_all(&s->free_sema); + } } static void coroutine_fn nbd_client_co_drain_end(BlockDriverState *bs) @@ -206,16 +309,21 @@ static void nbd_teardown_connection(BlockDriverState *bs) { BDRVNBDState *s = (BDRVNBDState *)bs->opaque; - if (s->state == NBD_CLIENT_CONNECTED) { + if (s->ioc) { /* finish any pending coroutines */ - assert(s->ioc); qio_channel_shutdown(s->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); + } else if (s->sioc) { + /* abort negotiation */ + qio_channel_shutdown(QIO_CHANNEL(s->sioc), QIO_CHANNEL_SHUTDOWN_BOTH, + NULL); } + s->state = NBD_CLIENT_QUIT; if (s->connection_co) { if (s->connection_co_sleep_ns_state) { qemu_co_sleep_wake(s->connection_co_sleep_ns_state); } + nbd_co_establish_connection_cancel(bs, true); } if (qemu_in_coroutine()) { s->teardown_co = qemu_coroutine_self(); @@ -239,9 +347,221 @@ static bool nbd_client_connecting_wait(BDRVNBDState *s) return s->state == NBD_CLIENT_CONNECTING_WAIT; } +static void connect_bh(void *opaque) +{ + BDRVNBDState *state = opaque; + + assert(state->wait_connect); + state->wait_connect = false; + aio_co_wake(state->connection_co); +} + +static void nbd_init_connect_thread(BDRVNBDState *s) +{ + s->connect_thread = g_new(NBDConnectThread, 1); + + *s->connect_thread = (NBDConnectThread) { + .saddr = QAPI_CLONE(SocketAddress, s->saddr), + .state = CONNECT_THREAD_NONE, + .bh_func = connect_bh, + .bh_opaque = s, + }; + + qemu_mutex_init(&s->connect_thread->mutex); +} + +static void nbd_free_connect_thread(NBDConnectThread *thr) +{ + if (thr->sioc) { + qio_channel_close(QIO_CHANNEL(thr->sioc), NULL); + } + error_free(thr->err); + qapi_free_SocketAddress(thr->saddr); + g_free(thr); +} + +static void *connect_thread_func(void *opaque) +{ + NBDConnectThread *thr = opaque; + int ret; + bool do_free = false; + + thr->sioc = qio_channel_socket_new(); + + error_free(thr->err); + thr->err = NULL; + ret = qio_channel_socket_connect_sync(thr->sioc, thr->saddr, &thr->err); + if (ret < 0) { + object_unref(OBJECT(thr->sioc)); + thr->sioc = NULL; + } + + qemu_mutex_lock(&thr->mutex); + + switch (thr->state) { + case CONNECT_THREAD_RUNNING: + thr->state = ret < 0 ? CONNECT_THREAD_FAIL : CONNECT_THREAD_SUCCESS; + if (thr->bh_ctx) { + aio_bh_schedule_oneshot(thr->bh_ctx, thr->bh_func, thr->bh_opaque); + + /* play safe, don't reuse bh_ctx on further connection attempts */ + thr->bh_ctx = NULL; + } + break; + case CONNECT_THREAD_RUNNING_DETACHED: + do_free = true; + break; + default: + abort(); + } + + qemu_mutex_unlock(&thr->mutex); + + if (do_free) { + nbd_free_connect_thread(thr); + } + + return NULL; +} + +static QIOChannelSocket *coroutine_fn +nbd_co_establish_connection(BlockDriverState *bs, Error **errp) +{ + QemuThread thread; + BDRVNBDState *s = bs->opaque; + QIOChannelSocket *res; + NBDConnectThread *thr = s->connect_thread; + + qemu_mutex_lock(&thr->mutex); + + switch (thr->state) { + case CONNECT_THREAD_FAIL: + case CONNECT_THREAD_NONE: + error_free(thr->err); + thr->err = NULL; + thr->state = CONNECT_THREAD_RUNNING; + qemu_thread_create(&thread, "nbd-connect", + connect_thread_func, thr, QEMU_THREAD_DETACHED); + break; + case CONNECT_THREAD_SUCCESS: + /* Previous attempt finally succeeded in background */ + thr->state = CONNECT_THREAD_NONE; + res = thr->sioc; + thr->sioc = NULL; + qemu_mutex_unlock(&thr->mutex); + return res; + case CONNECT_THREAD_RUNNING: + /* Already running, will wait */ + break; + default: + abort(); + } + + thr->bh_ctx = qemu_get_current_aio_context(); + + qemu_mutex_unlock(&thr->mutex); + + + /* + * We are going to wait for connect-thread finish, but + * nbd_client_co_drain_begin() can interrupt. + * + * Note that wait_connect variable is not visible for connect-thread. It + * doesn't need mutex protection, it used only inside home aio context of + * bs. + */ + s->wait_connect = true; + qemu_coroutine_yield(); + + qemu_mutex_lock(&thr->mutex); + + switch (thr->state) { + case CONNECT_THREAD_SUCCESS: + case CONNECT_THREAD_FAIL: + thr->state = CONNECT_THREAD_NONE; + error_propagate(errp, thr->err); + thr->err = NULL; + res = thr->sioc; + thr->sioc = NULL; + break; + case CONNECT_THREAD_RUNNING: + case CONNECT_THREAD_RUNNING_DETACHED: + /* + * Obviously, drained section wants to start. Report the attempt as + * failed. Still connect thread is executing in background, and its + * result may be used for next connection attempt. + */ + res = NULL; + error_setg(errp, "Connection attempt cancelled by other operation"); + break; + + case CONNECT_THREAD_NONE: + /* + * Impossible. We've seen this thread running. So it should be + * running or at least give some results. + */ + abort(); + + default: + abort(); + } + + qemu_mutex_unlock(&thr->mutex); + + return res; +} + +/* + * nbd_co_establish_connection_cancel + * Cancel nbd_co_establish_connection asynchronously: it will finish soon, to + * allow drained section to begin. + * + * If detach is true, also cleanup the state (or if thread is running, move it + * to CONNECT_THREAD_RUNNING_DETACHED state). s->connect_thread becomes NULL if + * detach is true. + */ +static void nbd_co_establish_connection_cancel(BlockDriverState *bs, + bool detach) +{ + BDRVNBDState *s = bs->opaque; + NBDConnectThread *thr = s->connect_thread; + bool wake = false; + bool do_free = false; + + qemu_mutex_lock(&thr->mutex); + + if (thr->state == CONNECT_THREAD_RUNNING) { + /* We can cancel only in running state, when bh is not yet scheduled */ + thr->bh_ctx = NULL; + if (s->wait_connect) { + s->wait_connect = false; + wake = true; + } + if (detach) { + thr->state = CONNECT_THREAD_RUNNING_DETACHED; + s->connect_thread = NULL; + } + } else if (detach) { + do_free = true; + } + + qemu_mutex_unlock(&thr->mutex); + + if (do_free) { + nbd_free_connect_thread(thr); + s->connect_thread = NULL; + } + + if (wake) { + aio_co_wake(s->connection_co); + } +} + static coroutine_fn void nbd_reconnect_attempt(BDRVNBDState *s) { + int ret; Error *local_err = NULL; + QIOChannelSocket *sioc; if (!nbd_client_connecting(s)) { return; @@ -273,47 +593,61 @@ static coroutine_fn void nbd_reconnect_attempt(BDRVNBDState *s) /* Finalize previous connection if any */ if (s->ioc) { - nbd_client_detach_aio_context(s->bs); + qio_channel_detach_aio_context(QIO_CHANNEL(s->ioc)); object_unref(OBJECT(s->sioc)); s->sioc = NULL; object_unref(OBJECT(s->ioc)); s->ioc = NULL; } - s->connect_status = nbd_client_connect(s->bs, &local_err); + sioc = nbd_co_establish_connection(s->bs, &local_err); + if (!sioc) { + ret = -ECONNREFUSED; + goto out; + } + + bdrv_dec_in_flight(s->bs); + + ret = nbd_client_handshake(s->bs, sioc, &local_err); + + if (s->drained) { + s->wait_drained_end = true; + while (s->drained) { + /* + * We may be entered once from nbd_client_attach_aio_context_bh + * and then from nbd_client_co_drain_end. So here is a loop. + */ + qemu_coroutine_yield(); + } + } + bdrv_inc_in_flight(s->bs); + +out: + s->connect_status = ret; error_free(s->connect_err); s->connect_err = NULL; error_propagate(&s->connect_err, local_err); - if (s->connect_status < 0) { - /* failed attempt */ - return; + if (ret >= 0) { + /* successfully connected */ + s->state = NBD_CLIENT_CONNECTED; + qemu_co_queue_restart_all(&s->free_sema); } - - /* successfully connected */ - s->state = NBD_CLIENT_CONNECTED; - qemu_co_queue_restart_all(&s->free_sema); } static coroutine_fn void nbd_co_reconnect_loop(BDRVNBDState *s) { - uint64_t start_time_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); - uint64_t delay_ns = s->reconnect_delay * NANOSECONDS_PER_SECOND; uint64_t timeout = 1 * NANOSECONDS_PER_SECOND; uint64_t max_timeout = 16 * NANOSECONDS_PER_SECOND; + if (s->state == NBD_CLIENT_CONNECTING_WAIT) { + reconnect_delay_timer_init(s, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + + s->reconnect_delay * NANOSECONDS_PER_SECOND); + } + nbd_reconnect_attempt(s); while (nbd_client_connecting(s)) { - if (s->state == NBD_CLIENT_CONNECTING_WAIT && - qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - start_time_ns > delay_ns) - { - s->state = NBD_CLIENT_CONNECTING_NOWAIT; - qemu_co_queue_restart_all(&s->free_sema); - } - - qemu_co_sleep_ns_wakeable(QEMU_CLOCK_REALTIME, timeout, - &s->connection_co_sleep_ns_state); if (s->drained) { bdrv_dec_in_flight(s->bs); s->wait_drained_end = true; @@ -325,13 +659,21 @@ static coroutine_fn void nbd_co_reconnect_loop(BDRVNBDState *s) qemu_coroutine_yield(); } bdrv_inc_in_flight(s->bs); - } - if (timeout < max_timeout) { - timeout *= 2; + } else { + qemu_co_sleep_ns_wakeable(QEMU_CLOCK_REALTIME, timeout, + &s->connection_co_sleep_ns_state); + if (s->drained) { + continue; + } + if (timeout < max_timeout) { + timeout *= 2; + } } nbd_reconnect_attempt(s); } + + reconnect_delay_timer_del(s); } static coroutine_fn void nbd_connection_entry(void *opaque) @@ -410,7 +752,7 @@ static coroutine_fn void nbd_connection_entry(void *opaque) s->connection_co = NULL; if (s->ioc) { - nbd_client_detach_aio_context(s->bs); + qio_channel_detach_aio_context(QIO_CHANNEL(s->ioc)); object_unref(OBJECT(s->sioc)); s->sioc = NULL; object_unref(OBJECT(s->ioc)); @@ -620,6 +962,16 @@ static int nbd_parse_blockstatus_payload(BDRVNBDState *s, trace_nbd_parse_blockstatus_compliance("extent length too large"); } + /* + * HACK: if we are using x-dirty-bitmaps to access + * qemu:allocation-depth, treat all depths > 2 the same as 2, + * since nbd_client_co_block_status is only expecting the low two + * bits to be set. + */ + if (s->alloc_depth && extent->flags > 2) { + extent->flags = 2; + } + return 0; } @@ -1408,16 +1760,15 @@ static void nbd_client_close(BlockDriverState *bs) static QIOChannelSocket *nbd_establish_connection(SocketAddress *saddr, Error **errp) { + ERRP_GUARD(); QIOChannelSocket *sioc; - Error *local_err = NULL; sioc = qio_channel_socket_new(); qio_channel_set_name(QIO_CHANNEL(sioc), "nbd-client"); - qio_channel_socket_connect_sync(sioc, saddr, &local_err); - if (local_err) { + qio_channel_socket_connect_sync(sioc, saddr, errp); + if (*errp) { object_unref(OBJECT(sioc)); - error_propagate(errp, local_err); return NULL; } @@ -1426,24 +1777,18 @@ static QIOChannelSocket *nbd_establish_connection(SocketAddress *saddr, return sioc; } -static int nbd_client_connect(BlockDriverState *bs, Error **errp) +/* nbd_client_handshake takes ownership on sioc. On failure it is unref'ed. */ +static int nbd_client_handshake(BlockDriverState *bs, QIOChannelSocket *sioc, + Error **errp) { BDRVNBDState *s = (BDRVNBDState *)bs->opaque; AioContext *aio_context = bdrv_get_aio_context(bs); int ret; - /* - * establish TCP connection, return error if it fails - * TODO: Configurable retry-until-timeout behaviour. - */ - QIOChannelSocket *sioc = nbd_establish_connection(s->saddr, errp); + trace_nbd_client_handshake(s->export); - if (!sioc) { - return -ECONNREFUSED; - } + s->sioc = sioc; - /* NBD handshake */ - trace_nbd_client_connect(s->export); qio_channel_set_blocking(QIO_CHANNEL(sioc), false, NULL); qio_channel_attach_aio_context(QIO_CHANNEL(sioc), aio_context); @@ -1458,13 +1803,19 @@ static int nbd_client_connect(BlockDriverState *bs, Error **errp) g_free(s->info.name); if (ret < 0) { object_unref(OBJECT(sioc)); + s->sioc = NULL; return ret; } - if (s->x_dirty_bitmap && !s->info.base_allocation) { - error_setg(errp, "requested x-dirty-bitmap %s not found", - s->x_dirty_bitmap); - ret = -EINVAL; - goto fail; + if (s->x_dirty_bitmap) { + if (!s->info.base_allocation) { + error_setg(errp, "requested x-dirty-bitmap %s not found", + s->x_dirty_bitmap); + ret = -EINVAL; + goto fail; + } + if (strcmp(s->x_dirty_bitmap, "qemu:allocation-depth") == 0) { + s->alloc_depth = true; + } } if (s->info.flags & NBD_FLAG_READ_ONLY) { ret = bdrv_apply_auto_read_only(bs, "NBD export is read-only", errp); @@ -1483,14 +1834,12 @@ static int nbd_client_connect(BlockDriverState *bs, Error **errp) } } - s->sioc = sioc; - if (!s->ioc) { s->ioc = QIO_CHANNEL(sioc); object_ref(OBJECT(s->ioc)); } - trace_nbd_client_connect_success(s->export); + trace_nbd_client_handshake_success(s->export); return 0; @@ -1505,6 +1854,7 @@ static int nbd_client_connect(BlockDriverState *bs, Error **errp) nbd_send_request(s->ioc ?: QIO_CHANNEL(sioc), &request); object_unref(OBJECT(sioc)); + s->sioc = NULL; return ret; } @@ -1726,7 +2076,6 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDict *options, SocketAddress *saddr = NULL; QDict *addr = NULL; Visitor *iv = NULL; - Error *local_err = NULL; qdict_extract_subqdict(options, &addr, "server."); if (!qdict_size(addr)) { @@ -1739,9 +2088,7 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDict *options, goto done; } - visit_type_SocketAddress(iv, NULL, &saddr, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_SocketAddress(iv, NULL, &saddr, errp)) { goto done; } @@ -1836,13 +2183,10 @@ static int nbd_process_options(BlockDriverState *bs, QDict *options, { BDRVNBDState *s = bs->opaque; QemuOpts *opts; - Error *local_err = NULL; int ret = -EINVAL; opts = qemu_opts_create(&nbd_runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { goto error; } @@ -1901,6 +2245,7 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags, { int ret; BDRVNBDState *s = (BDRVNBDState *)bs->opaque; + QIOChannelSocket *sioc; ret = nbd_process_options(bs, options, errp); if (ret < 0) { @@ -1911,7 +2256,16 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags, qemu_co_mutex_init(&s->send_mutex); qemu_co_queue_init(&s->free_sema); - ret = nbd_client_connect(bs, errp); + /* + * establish TCP connection, return error if it fails + * TODO: Configurable retry-until-timeout behaviour. + */ + sioc = nbd_establish_connection(s->saddr, errp); + if (!sioc) { + return -ECONNREFUSED; + } + + ret = nbd_client_handshake(bs, sioc, errp); if (ret < 0) { nbd_clear_bdrvstate(s); return ret; @@ -1919,6 +2273,8 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags, /* successfully connected */ s->state = NBD_CLIENT_CONNECTED; + nbd_init_connect_thread(s); + s->connection_co = qemu_coroutine_create(nbd_connection_entry, s); bdrv_inc_in_flight(bs); aio_co_schedule(bdrv_get_aio_context(bs), s->connection_co); @@ -1973,6 +2329,33 @@ static void nbd_close(BlockDriverState *bs) nbd_clear_bdrvstate(s); } +/* + * NBD cannot truncate, but if the caller asks to truncate to the same size, or + * to a smaller size with exact=false, there is no reason to fail the + * operation. + * + * Preallocation mode is ignored since it does not seems useful to fail when + * we never change anything. + */ +static int coroutine_fn nbd_co_truncate(BlockDriverState *bs, int64_t offset, + bool exact, PreallocMode prealloc, + BdrvRequestFlags flags, Error **errp) +{ + BDRVNBDState *s = bs->opaque; + + if (offset != s->info.size && exact) { + error_setg(errp, "Cannot resize NBD nodes"); + return -ENOTSUP; + } + + if (offset > s->info.size) { + error_setg(errp, "Cannot grow NBD nodes"); + return -EINVAL; + } + + return 0; +} + static int64_t nbd_getlength(BlockDriverState *bs) { BDRVNBDState *s = bs->opaque; @@ -1984,6 +2367,7 @@ static void nbd_refresh_filename(BlockDriverState *bs) { BDRVNBDState *s = bs->opaque; const char *host = NULL, *port = NULL, *path = NULL; + size_t len = 0; if (s->saddr->type == SOCKET_ADDRESS_TYPE_INET) { const InetSocketAddress *inet = &s->saddr->u.inet; @@ -1996,17 +2380,21 @@ static void nbd_refresh_filename(BlockDriverState *bs) } /* else can't represent as pseudo-filename */ if (path && s->export) { - snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nbd+unix:///%s?socket=%s", s->export, path); + len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "nbd+unix:///%s?socket=%s", s->export, path); } else if (path && !s->export) { - snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nbd+unix://?socket=%s", path); + len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "nbd+unix://?socket=%s", path); } else if (host && s->export) { - snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nbd://%s:%s/%s", host, port, s->export); + len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "nbd://%s:%s/%s", host, port, s->export); } else if (host && !s->export) { - snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nbd://%s:%s", host, port); + len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "nbd://%s:%s", host, port); + } + if (len >= sizeof(bs->exact_filename)) { + /* Name is too long to represent exactly, so leave it empty. */ + bs->exact_filename[0] = '\0'; } } @@ -2047,6 +2435,7 @@ static BlockDriver bdrv_nbd = { .bdrv_co_flush_to_os = nbd_co_flush, .bdrv_co_pdiscard = nbd_client_co_pdiscard, .bdrv_refresh_limits = nbd_refresh_limits, + .bdrv_co_truncate = nbd_co_truncate, .bdrv_getlength = nbd_getlength, .bdrv_detach_aio_context = nbd_client_detach_aio_context, .bdrv_attach_aio_context = nbd_client_attach_aio_context, @@ -2074,6 +2463,7 @@ static BlockDriver bdrv_nbd_tcp = { .bdrv_co_flush_to_os = nbd_co_flush, .bdrv_co_pdiscard = nbd_client_co_pdiscard, .bdrv_refresh_limits = nbd_refresh_limits, + .bdrv_co_truncate = nbd_co_truncate, .bdrv_getlength = nbd_getlength, .bdrv_detach_aio_context = nbd_client_detach_aio_context, .bdrv_attach_aio_context = nbd_client_attach_aio_context, @@ -2101,6 +2491,7 @@ static BlockDriver bdrv_nbd_unix = { .bdrv_co_flush_to_os = nbd_co_flush, .bdrv_co_pdiscard = nbd_client_co_pdiscard, .bdrv_refresh_limits = nbd_refresh_limits, + .bdrv_co_truncate = nbd_co_truncate, .bdrv_getlength = nbd_getlength, .bdrv_detach_aio_context = nbd_client_detach_aio_context, .bdrv_attach_aio_context = nbd_client_attach_aio_context, diff --git a/block/nfs.c b/block/nfs.c index b1718d125a479f2bd0ff80c06791898c452fe5c4..77905f516d203d03012cdf362daf8d08d2a7397c 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -24,7 +24,9 @@ #include "qemu/osdep.h" +#if !defined(_WIN32) #include +#endif #include "qemu/config-file.h" #include "qemu/error-report.h" #include "qapi/error.h" @@ -58,7 +60,7 @@ typedef struct NFSClient { bool has_zero_init; AioContext *aio_context; QemuMutex mutex; - blkcnt_t st_blocks; + uint64_t st_blocks; bool cache_used; NFSServer *server; char *path; @@ -545,7 +547,9 @@ static int64_t nfs_client_open(NFSClient *client, BlockdevOptionsNfs *opts, } ret = DIV_ROUND_UP(st.st_size, BDRV_SECTOR_SIZE); +#if !defined(_WIN32) client->st_blocks = st.st_blocks; +#endif client->has_zero_init = S_ISREG(st.st_mode); *strp = '/'; goto out; @@ -563,18 +567,15 @@ static BlockdevOptionsNfs *nfs_options_qdict_to_qapi(QDict *options, BlockdevOptionsNfs *opts = NULL; Visitor *v; const QDictEntry *e; - Error *local_err = NULL; v = qobject_input_visitor_new_flat_confused(options, errp); if (!v) { return NULL; } - visit_type_BlockdevOptionsNfs(v, NULL, &opts, &local_err); + visit_type_BlockdevOptionsNfs(v, NULL, &opts, errp); visit_free(v); - - if (local_err) { - error_propagate(errp, local_err); + if (!opts) { return NULL; } @@ -709,6 +710,7 @@ static int nfs_has_zero_init(BlockDriverState *bs) return client->has_zero_init; } +#if !defined(_WIN32) /* Called (via nfs_service) with QemuMutex held. */ static void nfs_get_allocated_file_size_cb(int ret, struct nfs_context *nfs, void *data, @@ -724,7 +726,7 @@ nfs_get_allocated_file_size_cb(int ret, struct nfs_context *nfs, void *data, } /* Set task->complete before reading bs->wakeup. */ - atomic_mb_set(&task->complete, 1); + qatomic_mb_set(&task->complete, 1); bdrv_wakeup(task->bs); } @@ -751,6 +753,7 @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs) return (task.ret < 0 ? task.ret : st.st_blocks * 512); } +#endif static int coroutine_fn nfs_file_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, @@ -803,7 +806,9 @@ static int nfs_reopen_prepare(BDRVReopenState *state, nfs_get_error(client->context)); return ret; } +#if !defined(_WIN32) client->st_blocks = st.st_blocks; +#endif } return 0; @@ -872,7 +877,10 @@ static BlockDriver bdrv_nfs = { .create_opts = &nfs_create_opts, .bdrv_has_zero_init = nfs_has_zero_init, +/* libnfs does not provide the allocated filesize of a file on win32. */ +#if !defined(_WIN32) .bdrv_get_allocated_file_size = nfs_get_allocated_file_size, +#endif .bdrv_co_truncate = nfs_file_co_truncate, .bdrv_file_open = nfs_file_open, diff --git a/block/null.c b/block/null.c index 15e1d5674643df4f6f8cedf3fc88419b9f44150e..cc9b1d4ea720f5bb1992e3929223987f0befd87e 100644 --- a/block/null.c +++ b/block/null.c @@ -262,6 +262,11 @@ static void null_refresh_filename(BlockDriverState *bs) bs->drv->format_name); } +static int64_t null_allocated_file_size(BlockDriverState *bs) +{ + return 0; +} + static const char *const null_strong_runtime_opts[] = { BLOCK_OPT_SIZE, NULL_OPT_ZEROES, @@ -277,6 +282,7 @@ static BlockDriver bdrv_null_co = { .bdrv_file_open = null_file_open, .bdrv_parse_filename = null_co_parse_filename, .bdrv_getlength = null_getlength, + .bdrv_get_allocated_file_size = null_allocated_file_size, .bdrv_co_preadv = null_co_preadv, .bdrv_co_pwritev = null_co_pwritev, @@ -297,6 +303,7 @@ static BlockDriver bdrv_null_aio = { .bdrv_file_open = null_file_open, .bdrv_parse_filename = null_aio_parse_filename, .bdrv_getlength = null_getlength, + .bdrv_get_allocated_file_size = null_allocated_file_size, .bdrv_aio_preadv = null_aio_preadv, .bdrv_aio_pwritev = null_aio_pwritev, diff --git a/block/nvme.c b/block/nvme.c index eb2f54dd9dc95138e2bfe60acf1353551264fa63..a06a188d530063d02fbacae29e0512f053ba15ef 100644 --- a/block/nvme.c +++ b/block/nvme.c @@ -31,7 +31,25 @@ #define NVME_SQ_ENTRY_BYTES 64 #define NVME_CQ_ENTRY_BYTES 16 #define NVME_QUEUE_SIZE 128 -#define NVME_BAR_SIZE 8192 +#define NVME_DOORBELL_SIZE 4096 + +/* + * We have to leave one slot empty as that is the full queue case where + * head == tail + 1. + */ +#define NVME_NUM_REQS (NVME_QUEUE_SIZE - 1) + +typedef struct BDRVNVMeState BDRVNVMeState; + +/* Same index is used for queues and IRQs */ +#define INDEX_ADMIN 0 +#define INDEX_IO(n) (1 + n) + +/* This driver shares a single MSIX IRQ for the admin and I/O queues */ +enum { + MSIX_SHARED_IRQ_IDX = 0, + MSIX_IRQ_COUNT = 1 +}; typedef struct { int32_t head, tail; @@ -47,63 +65,52 @@ typedef struct { int cid; void *prp_list_page; uint64_t prp_list_iova; - bool busy; + int free_req_next; /* q->reqs[] index of next free req */ } NVMeRequest; typedef struct { - CoQueue free_req_queue; QemuMutex lock; + /* Read from I/O code path, initialized under BQL */ + BDRVNVMeState *s; + int index; + /* Fields protected by BQL */ - int index; uint8_t *prp_list_pages; /* Fields protected by @lock */ + CoQueue free_req_queue; NVMeQueue sq, cq; int cq_phase; - NVMeRequest reqs[NVME_QUEUE_SIZE]; - bool busy; + int free_req_head; + NVMeRequest reqs[NVME_NUM_REQS]; int need_kick; int inflight; -} NVMeQueuePair; -/* Memory mapped registers */ -typedef volatile struct { - uint64_t cap; - uint32_t vs; - uint32_t intms; - uint32_t intmc; - uint32_t cc; - uint32_t reserved0; - uint32_t csts; - uint32_t nssr; - uint32_t aqa; - uint64_t asq; - uint64_t acq; - uint32_t cmbloc; - uint32_t cmbsz; - uint8_t reserved1[0xec0]; - uint8_t cmd_set_specfic[0x100]; - uint32_t doorbells[]; -} NVMeRegs; - -QEMU_BUILD_BUG_ON(offsetof(NVMeRegs, doorbells) != 0x1000); + /* Thread-safe, no lock necessary */ + QEMUBH *completion_bh; +} NVMeQueuePair; -typedef struct { +struct BDRVNVMeState { AioContext *aio_context; QEMUVFIOState *vfio; - NVMeRegs *regs; + void *bar0_wo_map; + /* Memory mapped registers */ + volatile struct { + uint32_t sq_tail; + uint32_t cq_head; + } *doorbells; /* The submission/completion queue pairs. * [0]: admin queue. * [1..]: io queues. */ NVMeQueuePair **queues; - int nr_queues; + unsigned queue_count; size_t page_size; /* How many uint32_t elements does each doorbell entry take. */ size_t doorbell_scale; bool write_cache_supported; - EventNotifier irq_notifier; + EventNotifier irq_notifier[MSIX_IRQ_COUNT]; uint64_t nsze; /* Namespace size reported by identify command */ int nsid; /* The namespace id to read/write data. */ @@ -123,11 +130,19 @@ typedef struct { /* PCI address (required for nvme_refresh_filename()) */ char *device; -} BDRVNVMeState; + + struct { + uint64_t completion_errors; + uint64_t aligned_accesses; + uint64_t unaligned_accesses; + } stats; +}; #define NVME_BLOCK_OPT_DEVICE "device" #define NVME_BLOCK_OPT_NAMESPACE "namespace" +static void nvme_process_completion_bh(void *opaque); + static QemuOptsList runtime_opts = { .name = "nvme", .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), @@ -146,29 +161,35 @@ static QemuOptsList runtime_opts = { }, }; -static void nvme_init_queue(BlockDriverState *bs, NVMeQueue *q, - int nentries, int entry_bytes, Error **errp) +/* Returns true on success, false on failure. */ +static bool nvme_init_queue(BDRVNVMeState *s, NVMeQueue *q, + unsigned nentries, size_t entry_bytes, Error **errp) { - BDRVNVMeState *s = bs->opaque; size_t bytes; int r; - bytes = ROUND_UP(nentries * entry_bytes, s->page_size); + bytes = ROUND_UP(nentries * entry_bytes, qemu_real_host_page_size); q->head = q->tail = 0; - q->queue = qemu_try_blockalign0(bs, bytes); - + q->queue = qemu_try_memalign(qemu_real_host_page_size, bytes); if (!q->queue) { error_setg(errp, "Cannot allocate queue"); - return; + return false; } + memset(q->queue, 0, bytes); r = qemu_vfio_dma_map(s->vfio, q->queue, bytes, false, &q->iova); if (r) { error_setg(errp, "Cannot map queue"); + return false; } + return true; } -static void nvme_free_queue_pair(BlockDriverState *bs, NVMeQueuePair *q) +static void nvme_free_queue_pair(NVMeQueuePair *q) { + trace_nvme_free_queue_pair(q->index, q); + if (q->completion_bh) { + qemu_bh_delete(q->completion_bh); + } qemu_vfree(q->prp_list_pages); qemu_vfree(q->sq.queue); qemu_vfree(q->cq.queue); @@ -187,55 +208,70 @@ static void nvme_free_req_queue_cb(void *opaque) qemu_mutex_unlock(&q->lock); } -static NVMeQueuePair *nvme_create_queue_pair(BlockDriverState *bs, - int idx, int size, +static NVMeQueuePair *nvme_create_queue_pair(BDRVNVMeState *s, + AioContext *aio_context, + unsigned idx, size_t size, Error **errp) { int i, r; - BDRVNVMeState *s = bs->opaque; - Error *local_err = NULL; - NVMeQueuePair *q = g_new0(NVMeQueuePair, 1); + NVMeQueuePair *q; uint64_t prp_list_iova; + size_t bytes; + q = g_try_new0(NVMeQueuePair, 1); + if (!q) { + return NULL; + } + trace_nvme_create_queue_pair(idx, q, size, aio_context, + event_notifier_get_fd(s->irq_notifier)); + bytes = QEMU_ALIGN_UP(s->page_size * NVME_NUM_REQS, + qemu_real_host_page_size); + q->prp_list_pages = qemu_try_memalign(qemu_real_host_page_size, bytes); + if (!q->prp_list_pages) { + goto fail; + } + memset(q->prp_list_pages, 0, bytes); qemu_mutex_init(&q->lock); + q->s = s; q->index = idx; qemu_co_queue_init(&q->free_req_queue); - q->prp_list_pages = qemu_blockalign0(bs, s->page_size * NVME_QUEUE_SIZE); - r = qemu_vfio_dma_map(s->vfio, q->prp_list_pages, - s->page_size * NVME_QUEUE_SIZE, + q->completion_bh = aio_bh_new(aio_context, nvme_process_completion_bh, q); + r = qemu_vfio_dma_map(s->vfio, q->prp_list_pages, bytes, false, &prp_list_iova); if (r) { goto fail; } - for (i = 0; i < NVME_QUEUE_SIZE; i++) { + q->free_req_head = -1; + for (i = 0; i < NVME_NUM_REQS; i++) { NVMeRequest *req = &q->reqs[i]; req->cid = i + 1; + req->free_req_next = q->free_req_head; + q->free_req_head = i; req->prp_list_page = q->prp_list_pages + i * s->page_size; req->prp_list_iova = prp_list_iova + i * s->page_size; } - nvme_init_queue(bs, &q->sq, size, NVME_SQ_ENTRY_BYTES, &local_err); - if (local_err) { - error_propagate(errp, local_err); + + if (!nvme_init_queue(s, &q->sq, size, NVME_SQ_ENTRY_BYTES, errp)) { goto fail; } - q->sq.doorbell = &s->regs->doorbells[idx * 2 * s->doorbell_scale]; + q->sq.doorbell = &s->doorbells[idx * s->doorbell_scale].sq_tail; - nvme_init_queue(bs, &q->cq, size, NVME_CQ_ENTRY_BYTES, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!nvme_init_queue(s, &q->cq, size, NVME_CQ_ENTRY_BYTES, errp)) { goto fail; } - q->cq.doorbell = &s->regs->doorbells[(idx * 2 + 1) * s->doorbell_scale]; + q->cq.doorbell = &s->doorbells[idx * s->doorbell_scale].cq_head; return q; fail: - nvme_free_queue_pair(bs, q); + nvme_free_queue_pair(q); return NULL; } /* With q->lock */ -static void nvme_kick(BDRVNVMeState *s, NVMeQueuePair *q) +static void nvme_kick(NVMeQueuePair *q) { + BDRVNVMeState *s = q->s; + if (s->plugged || !q->need_kick) { return; } @@ -254,35 +290,53 @@ static void nvme_kick(BDRVNVMeState *s, NVMeQueuePair *q) */ static NVMeRequest *nvme_get_free_req(NVMeQueuePair *q) { - int i; - NVMeRequest *req = NULL; + NVMeRequest *req; qemu_mutex_lock(&q->lock); - while (q->inflight + q->need_kick > NVME_QUEUE_SIZE - 2) { - /* We have to leave one slot empty as that is the full queue case (head - * == tail + 1). */ + + while (q->free_req_head == -1) { if (qemu_in_coroutine()) { - trace_nvme_free_req_queue_wait(q); + trace_nvme_free_req_queue_wait(q->s, q->index); qemu_co_queue_wait(&q->free_req_queue, &q->lock); } else { qemu_mutex_unlock(&q->lock); return NULL; } } - for (i = 0; i < NVME_QUEUE_SIZE; i++) { - if (!q->reqs[i].busy) { - q->reqs[i].busy = true; - req = &q->reqs[i]; - break; - } - } - /* We have checked inflight and need_kick while holding q->lock, so one - * free req must be available. */ - assert(req); + + req = &q->reqs[q->free_req_head]; + q->free_req_head = req->free_req_next; + req->free_req_next = -1; + qemu_mutex_unlock(&q->lock); return req; } +/* With q->lock */ +static void nvme_put_free_req_locked(NVMeQueuePair *q, NVMeRequest *req) +{ + req->free_req_next = q->free_req_head; + q->free_req_head = req - q->reqs; +} + +/* With q->lock */ +static void nvme_wake_free_req_locked(NVMeQueuePair *q) +{ + if (!qemu_co_queue_empty(&q->free_req_queue)) { + replay_bh_schedule_oneshot_event(q->s->aio_context, + nvme_free_req_queue_cb, q); + } +} + +/* Insert a request in the freelist and wake waiters */ +static void nvme_put_free_req_and_wake(NVMeQueuePair *q, NVMeRequest *req) +{ + qemu_mutex_lock(&q->lock); + nvme_put_free_req_locked(q, req); + nvme_wake_free_req_locked(q); + qemu_mutex_unlock(&q->lock); +} + static inline int nvme_translate_error(const NvmeCqe *c) { uint16_t status = (le16_to_cpu(c->status) >> 1) & 0xFF; @@ -306,67 +360,101 @@ static inline int nvme_translate_error(const NvmeCqe *c) } /* With q->lock */ -static bool nvme_process_completion(BDRVNVMeState *s, NVMeQueuePair *q) +static bool nvme_process_completion(NVMeQueuePair *q) { + BDRVNVMeState *s = q->s; bool progress = false; NVMeRequest *preq; NVMeRequest req; NvmeCqe *c; trace_nvme_process_completion(s, q->index, q->inflight); - if (q->busy || s->plugged) { - trace_nvme_process_completion_queue_busy(s, q->index); + if (s->plugged) { + trace_nvme_process_completion_queue_plugged(s, q->index); return false; } - q->busy = true; + + /* + * Support re-entrancy when a request cb() function invokes aio_poll(). + * Pending completions must be visible to aio_poll() so that a cb() + * function can wait for the completion of another request. + * + * The aio_poll() loop will execute our BH and we'll resume completion + * processing there. + */ + qemu_bh_schedule(q->completion_bh); + assert(q->inflight >= 0); while (q->inflight) { + int ret; int16_t cid; + c = (NvmeCqe *)&q->cq.queue[q->cq.head * NVME_CQ_ENTRY_BYTES]; if ((le16_to_cpu(c->status) & 0x1) == q->cq_phase) { break; } + ret = nvme_translate_error(c); + if (ret) { + s->stats.completion_errors++; + } q->cq.head = (q->cq.head + 1) % NVME_QUEUE_SIZE; if (!q->cq.head) { q->cq_phase = !q->cq_phase; } cid = le16_to_cpu(c->cid); if (cid == 0 || cid > NVME_QUEUE_SIZE) { - fprintf(stderr, "Unexpected CID in completion queue: %" PRIu32 "\n", - cid); + warn_report("NVMe: Unexpected CID in completion queue: %"PRIu32", " + "queue size: %u", cid, NVME_QUEUE_SIZE); continue; } - assert(cid <= NVME_QUEUE_SIZE); trace_nvme_complete_command(s, q->index, cid); preq = &q->reqs[cid - 1]; req = *preq; assert(req.cid == cid); assert(req.cb); - preq->busy = false; + nvme_put_free_req_locked(q, preq); preq->cb = preq->opaque = NULL; + q->inflight--; qemu_mutex_unlock(&q->lock); - req.cb(req.opaque, nvme_translate_error(c)); + req.cb(req.opaque, ret); qemu_mutex_lock(&q->lock); - q->inflight--; progress = true; } if (progress) { /* Notify the device so it can post more completions. */ smp_mb_release(); *q->cq.doorbell = cpu_to_le32(q->cq.head); - if (!qemu_co_queue_empty(&q->free_req_queue)) { - replay_bh_schedule_oneshot_event(s->aio_context, - nvme_free_req_queue_cb, q); - } + nvme_wake_free_req_locked(q); } - q->busy = false; + + qemu_bh_cancel(q->completion_bh); + return progress; } +static void nvme_process_completion_bh(void *opaque) +{ + NVMeQueuePair *q = opaque; + + /* + * We're being invoked because a nvme_process_completion() cb() function + * called aio_poll(). The callback may be waiting for further completions + * so notify the device that it has space to fill in more completions now. + */ + smp_mb_release(); + *q->cq.doorbell = cpu_to_le32(q->cq.head); + nvme_wake_free_req_locked(q); + + nvme_process_completion(q); +} + static void nvme_trace_command(const NvmeCmd *cmd) { int i; + if (!trace_event_get_state_backends(TRACE_NVME_SUBMIT_COMMAND_RAW)) { + return; + } for (i = 0; i < 8; ++i) { uint8_t *cmdp = (uint8_t *)cmd + i * 8; trace_nvme_submit_command_raw(cmdp[0], cmdp[1], cmdp[2], cmdp[3], @@ -374,58 +462,61 @@ static void nvme_trace_command(const NvmeCmd *cmd) } } -static void nvme_submit_command(BDRVNVMeState *s, NVMeQueuePair *q, - NVMeRequest *req, +static void nvme_submit_command(NVMeQueuePair *q, NVMeRequest *req, NvmeCmd *cmd, BlockCompletionFunc cb, void *opaque) { assert(!req->cb); req->cb = cb; req->opaque = opaque; - cmd->cid = cpu_to_le32(req->cid); + cmd->cid = cpu_to_le16(req->cid); - trace_nvme_submit_command(s, q->index, req->cid); + trace_nvme_submit_command(q->s, q->index, req->cid); nvme_trace_command(cmd); qemu_mutex_lock(&q->lock); memcpy((uint8_t *)q->sq.queue + q->sq.tail * NVME_SQ_ENTRY_BYTES, cmd, sizeof(*cmd)); q->sq.tail = (q->sq.tail + 1) % NVME_QUEUE_SIZE; q->need_kick++; - nvme_kick(s, q); - nvme_process_completion(s, q); + nvme_kick(q); + nvme_process_completion(q); qemu_mutex_unlock(&q->lock); } -static void nvme_cmd_sync_cb(void *opaque, int ret) +static void nvme_admin_cmd_sync_cb(void *opaque, int ret) { int *pret = opaque; *pret = ret; aio_wait_kick(); } -static int nvme_cmd_sync(BlockDriverState *bs, NVMeQueuePair *q, - NvmeCmd *cmd) +static int nvme_admin_cmd_sync(BlockDriverState *bs, NvmeCmd *cmd) { - NVMeRequest *req; BDRVNVMeState *s = bs->opaque; + NVMeQueuePair *q = s->queues[INDEX_ADMIN]; + AioContext *aio_context = bdrv_get_aio_context(bs); + NVMeRequest *req; int ret = -EINPROGRESS; req = nvme_get_free_req(q); if (!req) { return -EBUSY; } - nvme_submit_command(s, q, req, cmd, nvme_cmd_sync_cb, &ret); + nvme_submit_command(q, req, cmd, nvme_admin_cmd_sync_cb, &ret); - BDRV_POLL_WHILE(bs, ret == -EINPROGRESS); + AIO_WAIT_WHILE(aio_context, ret == -EINPROGRESS); return ret; } -static void nvme_identify(BlockDriverState *bs, int namespace, Error **errp) +/* Returns true on success, false on failure. */ +static bool nvme_identify(BlockDriverState *bs, int namespace, Error **errp) { BDRVNVMeState *s = bs->opaque; - NvmeIdCtrl *idctrl; - NvmeIdNs *idns; + bool ret = false; + union { + NvmeIdCtrl ctrl; + NvmeIdNs ns; + } *id; NvmeLBAF *lbaf; - uint8_t *resp; uint16_t oncs; int r; uint64_t iova; @@ -433,55 +524,54 @@ static void nvme_identify(BlockDriverState *bs, int namespace, Error **errp) .opcode = NVME_ADM_CMD_IDENTIFY, .cdw10 = cpu_to_le32(0x1), }; + size_t id_size = QEMU_ALIGN_UP(sizeof(*id), qemu_real_host_page_size); - resp = qemu_try_blockalign0(bs, sizeof(NvmeIdCtrl)); - if (!resp) { + id = qemu_try_memalign(qemu_real_host_page_size, id_size); + if (!id) { error_setg(errp, "Cannot allocate buffer for identify response"); goto out; } - idctrl = (NvmeIdCtrl *)resp; - idns = (NvmeIdNs *)resp; - r = qemu_vfio_dma_map(s->vfio, resp, sizeof(NvmeIdCtrl), true, &iova); + r = qemu_vfio_dma_map(s->vfio, id, id_size, true, &iova); if (r) { error_setg(errp, "Cannot map buffer for DMA"); goto out; } - cmd.prp1 = cpu_to_le64(iova); - if (nvme_cmd_sync(bs, s->queues[0], &cmd)) { + memset(id, 0, id_size); + cmd.dptr.prp1 = cpu_to_le64(iova); + if (nvme_admin_cmd_sync(bs, &cmd)) { error_setg(errp, "Failed to identify controller"); goto out; } - if (le32_to_cpu(idctrl->nn) < namespace) { + if (le32_to_cpu(id->ctrl.nn) < namespace) { error_setg(errp, "Invalid namespace"); goto out; } - s->write_cache_supported = le32_to_cpu(idctrl->vwc) & 0x1; - s->max_transfer = (idctrl->mdts ? 1 << idctrl->mdts : 0) * s->page_size; + s->write_cache_supported = le32_to_cpu(id->ctrl.vwc) & 0x1; + s->max_transfer = (id->ctrl.mdts ? 1 << id->ctrl.mdts : 0) * s->page_size; /* For now the page list buffer per command is one page, to hold at most * s->page_size / sizeof(uint64_t) entries. */ s->max_transfer = MIN_NON_ZERO(s->max_transfer, s->page_size / sizeof(uint64_t) * s->page_size); - oncs = le16_to_cpu(idctrl->oncs); - s->supports_write_zeroes = !!(oncs & NVME_ONCS_WRITE_ZEROS); + oncs = le16_to_cpu(id->ctrl.oncs); + s->supports_write_zeroes = !!(oncs & NVME_ONCS_WRITE_ZEROES); s->supports_discard = !!(oncs & NVME_ONCS_DSM); - memset(resp, 0, 4096); - + memset(id, 0, id_size); cmd.cdw10 = 0; cmd.nsid = cpu_to_le32(namespace); - if (nvme_cmd_sync(bs, s->queues[0], &cmd)) { + if (nvme_admin_cmd_sync(bs, &cmd)) { error_setg(errp, "Failed to identify namespace"); goto out; } - s->nsze = le64_to_cpu(idns->nsze); - lbaf = &idns->lbaf[NVME_ID_NS_FLBAS_INDEX(idns->flbas)]; + s->nsze = le64_to_cpu(id->ns.nsze); + lbaf = &id->ns.lbaf[NVME_ID_NS_FLBAS_INDEX(id->ns.flbas)]; - if (NVME_ID_NS_DLFEAT_WRITE_ZEROES(idns->dlfeat) && - NVME_ID_NS_DLFEAT_READ_BEHAVIOR(idns->dlfeat) == + if (NVME_ID_NS_DLFEAT_WRITE_ZEROES(id->ns.dlfeat) && + NVME_ID_NS_DLFEAT_READ_BEHAVIOR(id->ns.dlfeat) == NVME_ID_NS_DLFEAT_READ_BEHAVIOR_ZEROES) { bs->supported_write_flags |= BDRV_REQ_MAY_UNMAP; } @@ -499,10 +589,40 @@ static void nvme_identify(BlockDriverState *bs, int namespace, Error **errp) goto out; } + ret = true; s->blkshift = lbaf->ds; out: - qemu_vfio_dma_unmap(s->vfio, resp); - qemu_vfree(resp); + qemu_vfio_dma_unmap(s->vfio, id); + qemu_vfree(id); + + return ret; +} + +static bool nvme_poll_queue(NVMeQueuePair *q) +{ + bool progress = false; + + const size_t cqe_offset = q->cq.head * NVME_CQ_ENTRY_BYTES; + NvmeCqe *cqe = (NvmeCqe *)&q->cq.queue[cqe_offset]; + + trace_nvme_poll_queue(q->s, q->index); + /* + * Do an early check for completions. q->lock isn't needed because + * nvme_process_completion() only runs in the event loop thread and + * cannot race with itself. + */ + if ((le16_to_cpu(cqe->status) & 0x1) == q->cq_phase) { + return false; + } + + qemu_mutex_lock(&q->lock); + while (nvme_process_completion(q)) { + /* Keep polling */ + progress = true; + } + qemu_mutex_unlock(&q->lock); + + return progress; } static bool nvme_poll_queues(BDRVNVMeState *s) @@ -510,21 +630,18 @@ static bool nvme_poll_queues(BDRVNVMeState *s) bool progress = false; int i; - for (i = 0; i < s->nr_queues; i++) { - NVMeQueuePair *q = s->queues[i]; - qemu_mutex_lock(&q->lock); - while (nvme_process_completion(s, q)) { - /* Keep polling */ + for (i = 0; i < s->queue_count; i++) { + if (nvme_poll_queue(s->queues[i])) { progress = true; } - qemu_mutex_unlock(&q->lock); } return progress; } static void nvme_handle_event(EventNotifier *n) { - BDRVNVMeState *s = container_of(n, BDRVNVMeState, irq_notifier); + BDRVNVMeState *s = container_of(n, BDRVNVMeState, + irq_notifier[MSIX_SHARED_IRQ_IDX]); trace_nvme_handle_event(s); event_notifier_test_and_clear(n); @@ -534,49 +651,52 @@ static void nvme_handle_event(EventNotifier *n) static bool nvme_add_io_queue(BlockDriverState *bs, Error **errp) { BDRVNVMeState *s = bs->opaque; - int n = s->nr_queues; + unsigned n = s->queue_count; NVMeQueuePair *q; NvmeCmd cmd; - int queue_size = NVME_QUEUE_SIZE; + unsigned queue_size = NVME_QUEUE_SIZE; - q = nvme_create_queue_pair(bs, n, queue_size, errp); + assert(n <= UINT16_MAX); + q = nvme_create_queue_pair(s, bdrv_get_aio_context(bs), + n, queue_size, errp); if (!q) { return false; } cmd = (NvmeCmd) { .opcode = NVME_ADM_CMD_CREATE_CQ, - .prp1 = cpu_to_le64(q->cq.iova), - .cdw10 = cpu_to_le32(((queue_size - 1) << 16) | (n & 0xFFFF)), - .cdw11 = cpu_to_le32(0x3), + .dptr.prp1 = cpu_to_le64(q->cq.iova), + .cdw10 = cpu_to_le32(((queue_size - 1) << 16) | n), + .cdw11 = cpu_to_le32(NVME_CQ_IEN | NVME_CQ_PC), }; - if (nvme_cmd_sync(bs, s->queues[0], &cmd)) { - error_setg(errp, "Failed to create io queue [%d]", n); - nvme_free_queue_pair(bs, q); - return false; + if (nvme_admin_cmd_sync(bs, &cmd)) { + error_setg(errp, "Failed to create CQ io queue [%u]", n); + goto out_error; } cmd = (NvmeCmd) { .opcode = NVME_ADM_CMD_CREATE_SQ, - .prp1 = cpu_to_le64(q->sq.iova), - .cdw10 = cpu_to_le32(((queue_size - 1) << 16) | (n & 0xFFFF)), - .cdw11 = cpu_to_le32(0x1 | (n << 16)), + .dptr.prp1 = cpu_to_le64(q->sq.iova), + .cdw10 = cpu_to_le32(((queue_size - 1) << 16) | n), + .cdw11 = cpu_to_le32(NVME_SQ_PC | (n << 16)), }; - if (nvme_cmd_sync(bs, s->queues[0], &cmd)) { - error_setg(errp, "Failed to create io queue [%d]", n); - nvme_free_queue_pair(bs, q); - return false; + if (nvme_admin_cmd_sync(bs, &cmd)) { + error_setg(errp, "Failed to create SQ io queue [%u]", n); + goto out_error; } s->queues = g_renew(NVMeQueuePair *, s->queues, n + 1); s->queues[n] = q; - s->nr_queues++; + s->queue_count++; return true; +out_error: + nvme_free_queue_pair(q); + return false; } static bool nvme_poll_cb(void *opaque) { EventNotifier *e = opaque; - BDRVNVMeState *s = container_of(e, BDRVNVMeState, irq_notifier); + BDRVNVMeState *s = container_of(e, BDRVNVMeState, + irq_notifier[MSIX_SHARED_IRQ_IDX]); - trace_nvme_poll_cb(s); return nvme_poll_queues(s); } @@ -584,18 +704,20 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace, Error **errp) { BDRVNVMeState *s = bs->opaque; + NVMeQueuePair *q; + AioContext *aio_context = bdrv_get_aio_context(bs); int ret; uint64_t cap; uint64_t timeout_ms; uint64_t deadline, now; - Error *local_err = NULL; + volatile NvmeBar *regs = NULL; qemu_co_mutex_init(&s->dma_map_lock); qemu_co_queue_init(&s->dma_flush_queue); s->device = g_strdup(device); s->nsid = namespace; s->aio_context = bdrv_get_aio_context(bs); - ret = event_notifier_init(&s->irq_notifier, 0); + ret = event_notifier_init(&s->irq_notifier[MSIX_SHARED_IRQ_IDX], 0); if (ret) { error_setg(errp, "Failed to init event notifier"); return ret; @@ -607,32 +729,46 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace, goto out; } - s->regs = qemu_vfio_pci_map_bar(s->vfio, 0, 0, NVME_BAR_SIZE, errp); - if (!s->regs) { + regs = qemu_vfio_pci_map_bar(s->vfio, 0, 0, sizeof(NvmeBar), + PROT_READ | PROT_WRITE, errp); + if (!regs) { ret = -EINVAL; goto out; } - /* Perform initialize sequence as described in NVMe spec "7.6.1 * Initialization". */ - cap = le64_to_cpu(s->regs->cap); - if (!(cap & (1ULL << 37))) { + cap = le64_to_cpu(regs->cap); + trace_nvme_controller_capability_raw(cap); + trace_nvme_controller_capability("Maximum Queue Entries Supported", + 1 + NVME_CAP_MQES(cap)); + trace_nvme_controller_capability("Contiguous Queues Required", + NVME_CAP_CQR(cap)); + trace_nvme_controller_capability("Doorbell Stride", + 2 << (2 + NVME_CAP_DSTRD(cap))); + trace_nvme_controller_capability("Subsystem Reset Supported", + NVME_CAP_NSSRS(cap)); + trace_nvme_controller_capability("Memory Page Size Minimum", + 1 << (12 + NVME_CAP_MPSMIN(cap))); + trace_nvme_controller_capability("Memory Page Size Maximum", + 1 << (12 + NVME_CAP_MPSMAX(cap))); + if (!NVME_CAP_CSS(cap)) { error_setg(errp, "Device doesn't support NVMe command set"); ret = -EINVAL; goto out; } - s->page_size = MAX(4096, 1 << (12 + ((cap >> 48) & 0xF))); - s->doorbell_scale = (4 << (((cap >> 32) & 0xF))) / sizeof(uint32_t); + s->page_size = 1u << (12 + NVME_CAP_MPSMIN(cap)); + s->doorbell_scale = (4 << NVME_CAP_DSTRD(cap)) / sizeof(uint32_t); bs->bl.opt_mem_alignment = s->page_size; - timeout_ms = MIN(500 * ((cap >> 24) & 0xFF), 30000); + bs->bl.request_alignment = s->page_size; + timeout_ms = MIN(500 * NVME_CAP_TO(cap), 30000); /* Reset device to get a clean state. */ - s->regs->cc = cpu_to_le32(le32_to_cpu(s->regs->cc) & 0xFE); + regs->cc = cpu_to_le32(le32_to_cpu(regs->cc) & 0xFE); /* Wait for CSTS.RDY = 0. */ - deadline = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + timeout_ms * 1000000ULL; - while (le32_to_cpu(s->regs->csts) & 0x1) { + deadline = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + timeout_ms * SCALE_MS; + while (NVME_CSTS_RDY(le32_to_cpu(regs->csts))) { if (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) > deadline) { error_setg(errp, "Timeout while waiting for device to reset (%" PRId64 " ms)", @@ -642,27 +778,38 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace, } } + s->bar0_wo_map = qemu_vfio_pci_map_bar(s->vfio, 0, 0, + sizeof(NvmeBar) + NVME_DOORBELL_SIZE, + PROT_WRITE, errp); + s->doorbells = (void *)((uintptr_t)s->bar0_wo_map + sizeof(NvmeBar)); + if (!s->doorbells) { + ret = -EINVAL; + goto out; + } + /* Set up admin queue. */ s->queues = g_new(NVMeQueuePair *, 1); - s->queues[0] = nvme_create_queue_pair(bs, 0, NVME_QUEUE_SIZE, errp); - if (!s->queues[0]) { + q = nvme_create_queue_pair(s, aio_context, 0, NVME_QUEUE_SIZE, errp); + if (!q) { ret = -EINVAL; goto out; } - s->nr_queues = 1; - QEMU_BUILD_BUG_ON(NVME_QUEUE_SIZE & 0xF000); - s->regs->aqa = cpu_to_le32((NVME_QUEUE_SIZE << 16) | NVME_QUEUE_SIZE); - s->regs->asq = cpu_to_le64(s->queues[0]->sq.iova); - s->regs->acq = cpu_to_le64(s->queues[0]->cq.iova); + s->queues[INDEX_ADMIN] = q; + s->queue_count = 1; + QEMU_BUILD_BUG_ON((NVME_QUEUE_SIZE - 1) & 0xF000); + regs->aqa = cpu_to_le32(((NVME_QUEUE_SIZE - 1) << AQA_ACQS_SHIFT) | + ((NVME_QUEUE_SIZE - 1) << AQA_ASQS_SHIFT)); + regs->asq = cpu_to_le64(q->sq.iova); + regs->acq = cpu_to_le64(q->cq.iova); /* After setting up all control registers we can enable device now. */ - s->regs->cc = cpu_to_le32((ctz32(NVME_CQ_ENTRY_BYTES) << 20) | - (ctz32(NVME_SQ_ENTRY_BYTES) << 16) | - 0x1); + regs->cc = cpu_to_le32((ctz32(NVME_CQ_ENTRY_BYTES) << CC_IOCQES_SHIFT) | + (ctz32(NVME_SQ_ENTRY_BYTES) << CC_IOSQES_SHIFT) | + CC_EN_MASK); /* Wait for CSTS.RDY = 1. */ now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); - deadline = now + timeout_ms * 1000000; - while (!(le32_to_cpu(s->regs->csts) & 0x1)) { + deadline = now + timeout_ms * SCALE_MS; + while (!NVME_CSTS_RDY(le32_to_cpu(regs->csts))) { if (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) > deadline) { error_setg(errp, "Timeout while waiting for device to start (%" PRId64 " ms)", @@ -672,17 +819,16 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace, } } - ret = qemu_vfio_pci_init_irq(s->vfio, &s->irq_notifier, + ret = qemu_vfio_pci_init_irq(s->vfio, s->irq_notifier, VFIO_PCI_MSIX_IRQ_INDEX, errp); if (ret) { goto out; } - aio_set_event_notifier(bdrv_get_aio_context(bs), &s->irq_notifier, + aio_set_event_notifier(bdrv_get_aio_context(bs), + &s->irq_notifier[MSIX_SHARED_IRQ_IDX], false, nvme_handle_event, nvme_poll_cb); - nvme_identify(bs, namespace, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!nvme_identify(bs, namespace, errp)) { ret = -EIO; goto out; } @@ -692,6 +838,10 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace, ret = -EIO; } out: + if (regs) { + qemu_vfio_pci_unmap_bar(s->vfio, 0, (void *)regs, 0, sizeof(NvmeBar)); + } + /* Cleaning up is done in nvme_file_open() upon error. */ return ret; } @@ -744,7 +894,7 @@ static int nvme_enable_disable_write_cache(BlockDriverState *bs, bool enable, .cdw11 = cpu_to_le32(enable ? 0x01 : 0x00), }; - ret = nvme_cmd_sync(bs, s->queues[0], &cmd); + ret = nvme_admin_cmd_sync(bs, &cmd); if (ret) { error_setg(errp, "Failed to configure NVMe write cache"); } @@ -753,17 +903,18 @@ static int nvme_enable_disable_write_cache(BlockDriverState *bs, bool enable, static void nvme_close(BlockDriverState *bs) { - int i; BDRVNVMeState *s = bs->opaque; - for (i = 0; i < s->nr_queues; ++i) { - nvme_free_queue_pair(bs, s->queues[i]); + for (unsigned i = 0; i < s->queue_count; ++i) { + nvme_free_queue_pair(s->queues[i]); } g_free(s->queues); - aio_set_event_notifier(bdrv_get_aio_context(bs), &s->irq_notifier, + aio_set_event_notifier(bdrv_get_aio_context(bs), + &s->irq_notifier[MSIX_SHARED_IRQ_IDX], false, NULL, NULL); - event_notifier_cleanup(&s->irq_notifier); - qemu_vfio_pci_unmap_bar(s->vfio, 0, (void *)s->regs, 0, NVME_BAR_SIZE); + event_notifier_cleanup(&s->irq_notifier[MSIX_SHARED_IRQ_IDX]); + qemu_vfio_pci_unmap_bar(s->vfio, 0, s->bar0_wo_map, + 0, sizeof(NvmeBar) + NVME_DOORBELL_SIZE); qemu_vfio_close(s->vfio); g_free(s->device); @@ -867,11 +1018,12 @@ static coroutine_fn int nvme_cmd_map_qiov(BlockDriverState *bs, NvmeCmd *cmd, for (i = 0; i < qiov->niov; ++i) { bool retry = true; uint64_t iova; + size_t len = QEMU_ALIGN_UP(qiov->iov[i].iov_len, + qemu_real_host_page_size); try_map: r = qemu_vfio_dma_map(s->vfio, qiov->iov[i].iov_base, - qiov->iov[i].iov_len, - true, &iova); + len, true, &iova); if (r == -ENOMEM && retry) { retry = false; trace_nvme_dma_flush_queue_wait(s); @@ -904,16 +1056,16 @@ try_map: case 0: abort(); case 1: - cmd->prp1 = pagelist[0]; - cmd->prp2 = 0; + cmd->dptr.prp1 = pagelist[0]; + cmd->dptr.prp2 = 0; break; case 2: - cmd->prp1 = pagelist[0]; - cmd->prp2 = pagelist[1]; + cmd->dptr.prp1 = pagelist[0]; + cmd->dptr.prp2 = pagelist[1]; break; default: - cmd->prp1 = pagelist[0]; - cmd->prp2 = cpu_to_le64(req->prp_list_iova + sizeof(uint64_t)); + cmd->dptr.prp1 = pagelist[0]; + cmd->dptr.prp2 = cpu_to_le64(req->prp_list_iova + sizeof(uint64_t)); break; } trace_nvme_cmd_map_qiov(s, cmd, req, qiov, entries); @@ -961,7 +1113,7 @@ static coroutine_fn int nvme_co_prw_aligned(BlockDriverState *bs, { int r; BDRVNVMeState *s = bs->opaque; - NVMeQueuePair *ioq = s->queues[1]; + NVMeQueuePair *ioq = s->queues[INDEX_IO(0)]; NVMeRequest *req; uint32_t cdw12 = (((bytes >> s->blkshift) - 1) & 0xFFFF) | @@ -979,7 +1131,7 @@ static coroutine_fn int nvme_co_prw_aligned(BlockDriverState *bs, }; trace_nvme_prw_aligned(s, is_write, offset, bytes, flags, qiov->niov); - assert(s->nr_queues > 1); + assert(s->queue_count > 1); req = nvme_get_free_req(ioq); assert(req); @@ -987,10 +1139,10 @@ static coroutine_fn int nvme_co_prw_aligned(BlockDriverState *bs, r = nvme_cmd_map_qiov(bs, &cmd, req, qiov); qemu_co_mutex_unlock(&s->dma_map_lock); if (r) { - req->busy = false; + nvme_put_free_req_and_wake(ioq, req); return r; } - nvme_submit_command(s, ioq, req, &cmd, nvme_rw_cb, &data); + nvme_submit_command(ioq, req, &cmd, nvme_rw_cb, &data); data.co = qemu_coroutine_self(); while (data.ret == -EINPROGRESS) { @@ -1015,8 +1167,9 @@ static inline bool nvme_qiov_aligned(BlockDriverState *bs, BDRVNVMeState *s = bs->opaque; for (i = 0; i < qiov->niov; ++i) { - if (!QEMU_PTR_IS_ALIGNED(qiov->iov[i].iov_base, s->page_size) || - !QEMU_IS_ALIGNED(qiov->iov[i].iov_len, s->page_size)) { + if (!QEMU_PTR_IS_ALIGNED(qiov->iov[i].iov_base, + qemu_real_host_page_size) || + !QEMU_IS_ALIGNED(qiov->iov[i].iov_len, qemu_real_host_page_size)) { trace_nvme_qiov_unaligned(qiov, i, qiov->iov[i].iov_base, qiov->iov[i].iov_len, s->page_size); return false; @@ -1032,15 +1185,17 @@ static int nvme_co_prw(BlockDriverState *bs, uint64_t offset, uint64_t bytes, int r; uint8_t *buf = NULL; QEMUIOVector local_qiov; - + size_t len = QEMU_ALIGN_UP(bytes, qemu_real_host_page_size); assert(QEMU_IS_ALIGNED(offset, s->page_size)); assert(QEMU_IS_ALIGNED(bytes, s->page_size)); assert(bytes <= s->max_transfer); if (nvme_qiov_aligned(bs, qiov)) { + s->stats.aligned_accesses++; return nvme_co_prw_aligned(bs, offset, bytes, qiov, is_write, flags); } + s->stats.unaligned_accesses++; trace_nvme_prw_buffered(s, offset, bytes, qiov->niov, is_write); - buf = qemu_try_blockalign(bs, bytes); + buf = qemu_try_memalign(qemu_real_host_page_size, len); if (!buf) { return -ENOMEM; @@ -1076,7 +1231,7 @@ static coroutine_fn int nvme_co_pwritev(BlockDriverState *bs, static coroutine_fn int nvme_co_flush(BlockDriverState *bs) { BDRVNVMeState *s = bs->opaque; - NVMeQueuePair *ioq = s->queues[1]; + NVMeQueuePair *ioq = s->queues[INDEX_IO(0)]; NVMeRequest *req; NvmeCmd cmd = { .opcode = NVME_CMD_FLUSH, @@ -1087,10 +1242,10 @@ static coroutine_fn int nvme_co_flush(BlockDriverState *bs) .ret = -EINPROGRESS, }; - assert(s->nr_queues > 1); + assert(s->queue_count > 1); req = nvme_get_free_req(ioq); assert(req); - nvme_submit_command(s, ioq, req, &cmd, nvme_rw_cb, &data); + nvme_submit_command(ioq, req, &cmd, nvme_rw_cb, &data); data.co = qemu_coroutine_self(); if (data.ret == -EINPROGRESS) { @@ -1107,7 +1262,7 @@ static coroutine_fn int nvme_co_pwrite_zeroes(BlockDriverState *bs, BdrvRequestFlags flags) { BDRVNVMeState *s = bs->opaque; - NVMeQueuePair *ioq = s->queues[1]; + NVMeQueuePair *ioq = s->queues[INDEX_IO(0)]; NVMeRequest *req; uint32_t cdw12 = ((bytes >> s->blkshift) - 1) & 0xFFFF; @@ -1117,7 +1272,7 @@ static coroutine_fn int nvme_co_pwrite_zeroes(BlockDriverState *bs, } NvmeCmd cmd = { - .opcode = NVME_CMD_WRITE_ZEROS, + .opcode = NVME_CMD_WRITE_ZEROES, .nsid = cpu_to_le32(s->nsid), .cdw10 = cpu_to_le32((offset >> s->blkshift) & 0xFFFFFFFF), .cdw11 = cpu_to_le32(((offset >> s->blkshift) >> 32) & 0xFFFFFFFF), @@ -1139,11 +1294,11 @@ static coroutine_fn int nvme_co_pwrite_zeroes(BlockDriverState *bs, cmd.cdw12 = cpu_to_le32(cdw12); trace_nvme_write_zeroes(s, offset, bytes, flags); - assert(s->nr_queues > 1); + assert(s->queue_count > 1); req = nvme_get_free_req(ioq); assert(req); - nvme_submit_command(s, ioq, req, &cmd, nvme_rw_cb, &data); + nvme_submit_command(ioq, req, &cmd, nvme_rw_cb, &data); data.co = qemu_coroutine_self(); while (data.ret == -EINPROGRESS) { @@ -1160,7 +1315,7 @@ static int coroutine_fn nvme_co_pdiscard(BlockDriverState *bs, int bytes) { BDRVNVMeState *s = bs->opaque; - NVMeQueuePair *ioq = s->queues[1]; + NVMeQueuePair *ioq = s->queues[INDEX_IO(0)]; NVMeRequest *req; NvmeDsmRange *buf; QEMUIOVector local_qiov; @@ -1182,13 +1337,13 @@ static int coroutine_fn nvme_co_pdiscard(BlockDriverState *bs, return -ENOTSUP; } - assert(s->nr_queues > 1); + assert(s->queue_count > 1); - buf = qemu_try_blockalign0(bs, s->page_size); + buf = qemu_try_memalign(s->page_size, s->page_size); if (!buf) { return -ENOMEM; } - + memset(buf, 0, s->page_size); buf->nlb = cpu_to_le32(bytes >> s->blkshift); buf->slba = cpu_to_le64(offset >> s->blkshift); buf->cattr = 0; @@ -1204,13 +1359,13 @@ static int coroutine_fn nvme_co_pdiscard(BlockDriverState *bs, qemu_co_mutex_unlock(&s->dma_map_lock); if (ret) { - req->busy = false; + nvme_put_free_req_and_wake(ioq, req); goto out; } trace_nvme_dsm(s, offset, bytes); - nvme_submit_command(s, ioq, req, &cmd, nvme_rw_cb, &data); + nvme_submit_command(ioq, req, &cmd, nvme_rw_cb, &data); data.co = qemu_coroutine_self(); while (data.ret == -EINPROGRESS) { @@ -1262,7 +1417,15 @@ static void nvme_detach_aio_context(BlockDriverState *bs) { BDRVNVMeState *s = bs->opaque; - aio_set_event_notifier(bdrv_get_aio_context(bs), &s->irq_notifier, + for (unsigned i = 0; i < s->queue_count; i++) { + NVMeQueuePair *q = s->queues[i]; + + qemu_bh_delete(q->completion_bh); + q->completion_bh = NULL; + } + + aio_set_event_notifier(bdrv_get_aio_context(bs), + &s->irq_notifier[MSIX_SHARED_IRQ_IDX], false, NULL, NULL); } @@ -1272,8 +1435,15 @@ static void nvme_attach_aio_context(BlockDriverState *bs, BDRVNVMeState *s = bs->opaque; s->aio_context = new_context; - aio_set_event_notifier(new_context, &s->irq_notifier, + aio_set_event_notifier(new_context, &s->irq_notifier[MSIX_SHARED_IRQ_IDX], false, nvme_handle_event, nvme_poll_cb); + + for (unsigned i = 0; i < s->queue_count; i++) { + NVMeQueuePair *q = s->queues[i]; + + q->completion_bh = + aio_bh_new(new_context, nvme_process_completion_bh, q); + } } static void nvme_aio_plug(BlockDriverState *bs) @@ -1285,15 +1455,14 @@ static void nvme_aio_plug(BlockDriverState *bs) static void nvme_aio_unplug(BlockDriverState *bs) { - int i; BDRVNVMeState *s = bs->opaque; assert(s->plugged); s->plugged = false; - for (i = 1; i < s->nr_queues; i++) { + for (unsigned i = INDEX_IO(0); i < s->queue_count; i++) { NVMeQueuePair *q = s->queues[i]; qemu_mutex_lock(&q->lock); - nvme_kick(s, q); - nvme_process_completion(s, q); + nvme_kick(q); + nvme_process_completion(q); qemu_mutex_unlock(&q->lock); } } @@ -1319,6 +1488,21 @@ static void nvme_unregister_buf(BlockDriverState *bs, void *host) qemu_vfio_dma_unmap(s->vfio, host); } +static BlockStatsSpecific *nvme_get_specific_stats(BlockDriverState *bs) +{ + BlockStatsSpecific *stats = g_new(BlockStatsSpecific, 1); + BDRVNVMeState *s = bs->opaque; + + stats->driver = BLOCKDEV_DRIVER_NVME; + stats->u.nvme = (BlockStatsSpecificNvme) { + .completion_errors = s->stats.completion_errors, + .aligned_accesses = s->stats.aligned_accesses, + .unaligned_accesses = s->stats.unaligned_accesses, + }; + + return stats; +} + static const char *const nvme_strong_runtime_opts[] = { NVME_BLOCK_OPT_DEVICE, NVME_BLOCK_OPT_NAMESPACE, @@ -1352,6 +1536,7 @@ static BlockDriver bdrv_nvme = { .bdrv_refresh_filename = nvme_refresh_filename, .bdrv_refresh_limits = nvme_refresh_limits, .strong_runtime_opts = nvme_strong_runtime_opts, + .bdrv_get_specific_stats = nvme_get_specific_stats, .bdrv_detach_aio_context = nvme_detach_aio_context, .bdrv_attach_aio_context = nvme_attach_aio_context, diff --git a/block/parallels.c b/block/parallels.c index 63a1cde8af828a596a42278ff30425de4b83f43d..3c22dfdc9daa432a3c2ccf4b6910011207f54bae 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -625,7 +625,6 @@ static int coroutine_fn parallels_co_create_opts(BlockDriver *drv, Error **errp) { BlockdevCreateOptions *create_options = NULL; - Error *local_err = NULL; BlockDriverState *bs = NULL; QDict *qdict; Visitor *v; @@ -646,9 +645,8 @@ static int coroutine_fn parallels_co_create_opts(BlockDriver *drv, } /* Create and open the file (protocol layer) */ - ret = bdrv_create_file(filename, opts, &local_err); + ret = bdrv_create_file(filename, opts, errp); if (ret < 0) { - error_propagate(errp, local_err); goto done; } @@ -669,11 +667,9 @@ static int coroutine_fn parallels_co_create_opts(BlockDriver *drv, goto done; } - visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); + visit_type_BlockdevCreateOptions(v, NULL, &create_options, errp); visit_free(v); - - if (local_err) { - error_propagate(errp, local_err); + if (!create_options) { ret = -EINVAL; goto done; } @@ -824,13 +820,12 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags, } } - opts = qemu_opts_create(¶llels_runtime_opts, NULL, 0, &local_err); - if (local_err != NULL) { + opts = qemu_opts_create(¶llels_runtime_opts, NULL, 0, errp); + if (!opts) { goto fail_options; } - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err != NULL) { + if (!qemu_opts_absorb_qdict(opts, options, errp)) { goto fail_options; } @@ -844,6 +839,7 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags, &local_err); g_free(buf); if (local_err != NULL) { + error_propagate(errp, local_err); goto fail_options; } @@ -863,9 +859,8 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags, error_setg(&s->migration_blocker, "The Parallels format used by node '%s' " "does not support live migration", bdrv_get_device_or_node_name(bs)); - ret = migrate_add_blocker(s->migration_blocker, &local_err); - if (local_err) { - error_propagate(errp, local_err); + ret = migrate_add_blocker(s->migration_blocker, errp); + if (ret < 0) { error_free(s->migration_blocker); goto fail; } @@ -874,15 +869,11 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags, fail_format: error_setg(errp, "Image not in Parallels format"); +fail_options: ret = -EINVAL; fail: qemu_vfree(s->header); return ret; - -fail_options: - error_propagate(errp, local_err); - ret = -EINVAL; - goto fail; } diff --git a/block/qapi.c b/block/qapi.c index afd9f3b4a7c13d4061ec87462c0985bd07393fe8..036da085eea66bd1ad866f5be06f22330297437c 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -47,7 +47,7 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk, Error **errp) { ImageInfo **p_image_info; - BlockDriverState *bs0; + BlockDriverState *bs0, *backing; BlockDeviceInfo *info; if (!bs->drv) { @@ -76,9 +76,10 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk, info->node_name = g_strdup(bs->node_name); } - if (bs->backing_file[0]) { + backing = bdrv_cow_bs(bs); + if (backing) { info->has_backing_file = true; - info->backing_file = g_strdup(bs->backing_file); + info->backing_file = g_strdup(backing->filename); } if (!QLIST_EMPTY(&bs->dirty_bitmaps)) { @@ -163,9 +164,13 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk, break; } - if (bs0->drv && bs0->backing) { + if (bs0->drv && bdrv_filter_or_cow_child(bs0)) { + /* + * Put any filtered child here (for backwards compatibility to when + * we put bs0->backing here, which might be any filtered child). + */ info->backing_file_depth++; - bs0 = bs0->backing->bs; + bs0 = bdrv_filter_or_cow_bs(bs0); (*p_image_info)->has_backing_image = true; p_image_info = &((*p_image_info)->backing_image); } else { @@ -174,9 +179,8 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk, /* Skip automatically inserted nodes that the user isn't aware of for * query-block (blk != NULL), but not for query-named-block-nodes */ - while (blk && bs0->drv && bs0->implicit) { - bs0 = backing_bs(bs0); - assert(bs0); + if (blk) { + bs0 = bdrv_skip_implicit_filters(bs0); } } @@ -226,6 +230,8 @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs, info->date_nsec = sn_tab[i].date_nsec; info->vm_clock_sec = sn_tab[i].vm_clock_nsec / 1000000000; info->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000; + info->icount = sn_tab[i].icount; + info->has_icount = sn_tab[i].icount != -1ULL; info_list = g_new0(SnapshotInfoList, 1); info_list->value = info; @@ -288,7 +294,7 @@ void bdrv_query_image_info(BlockDriverState *bs, info->virtual_size = size; info->actual_size = bdrv_get_allocated_file_size(bs); info->has_actual_size = info->actual_size >= 0; - if (bdrv_is_encrypted(bs)) { + if (bs->encrypted) { info->encrypted = true; info->has_encrypted = true; } @@ -311,6 +317,7 @@ void bdrv_query_image_info(BlockDriverState *bs, backing_filename = bs->backing_file; if (backing_filename[0] != '\0') { char *backing_filename2; + info->backing_filename = g_strdup(backing_filename); info->has_backing_filename = true; backing_filename2 = bdrv_get_full_backing_filename(bs, NULL); @@ -362,9 +369,7 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info, char *qdev; /* Skip automatically inserted nodes that the user isn't aware of */ - while (bs && bs->drv && bs->implicit) { - bs = backing_bs(bs); - } + bs = bdrv_skip_implicit_filters(bs); info->device = g_strdup(blk_name(blk)); info->type = g_strdup("unknown"); @@ -526,6 +531,8 @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk) static BlockStats *bdrv_query_bds_stats(BlockDriverState *bs, bool blk_level) { + BdrvChild *parent_child; + BlockDriverState *filter_or_cow_bs; BlockStats *s = NULL; s = g_malloc0(sizeof(*s)); @@ -538,9 +545,8 @@ static BlockStats *bdrv_query_bds_stats(BlockDriverState *bs, /* Skip automatically inserted nodes that the user isn't aware of in * a BlockBackend-level command. Stay at the exact node for a node-level * command. */ - while (blk_level && bs->drv && bs->implicit) { - bs = backing_bs(bs); - assert(bs); + if (blk_level) { + bs = bdrv_skip_implicit_filters(bs); } if (bdrv_get_node_name(bs)[0]) { @@ -555,14 +561,46 @@ static BlockStats *bdrv_query_bds_stats(BlockDriverState *bs, s->has_driver_specific = true; } - if (bs->file) { + parent_child = bdrv_primary_child(bs); + if (!parent_child || + !(parent_child->role & (BDRV_CHILD_DATA | BDRV_CHILD_FILTERED))) + { + BdrvChild *c; + + /* + * Look for a unique data-storing child. We do not need to look for + * filtered children, as there would be only one and it would have been + * the primary child. + */ + parent_child = NULL; + QLIST_FOREACH(c, &bs->children, next) { + if (c->role & BDRV_CHILD_DATA) { + if (parent_child) { + /* + * There are multiple data-storing children and we cannot + * choose between them. + */ + parent_child = NULL; + break; + } + parent_child = c; + } + } + } + if (parent_child) { s->has_parent = true; - s->parent = bdrv_query_bds_stats(bs->file->bs, blk_level); + s->parent = bdrv_query_bds_stats(parent_child->bs, blk_level); } - if (blk_level && bs->backing) { + filter_or_cow_bs = bdrv_filter_or_cow_bs(bs); + if (blk_level && filter_or_cow_bs) { + /* + * Put any filtered or COW child here (for backwards + * compatibility to when we put bs0->backing here, which might + * be either) + */ s->has_backing = true; - s->backing = bdrv_query_bds_stats(bs->backing->bs, blk_level); + s->backing = bdrv_query_bds_stats(filter_or_cow_bs, blk_level); } return s; @@ -658,14 +696,15 @@ BlockStatsList *qmp_query_blockstats(bool has_query_nodes, void bdrv_snapshot_dump(QEMUSnapshotInfo *sn) { char date_buf[128], clock_buf[128]; + char icount_buf[128] = {0}; struct tm tm; time_t ti; int64_t secs; char *sizing = NULL; if (!sn) { - qemu_printf("%-10s%-20s%11s%20s%15s", - "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK"); + qemu_printf("%-10s%-18s%7s%20s%13s%11s", + "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK", "ICOUNT"); } else { ti = sn->date_sec; localtime_r(&ti, &tm); @@ -679,11 +718,16 @@ void bdrv_snapshot_dump(QEMUSnapshotInfo *sn) (int)(secs % 60), (int)((sn->vm_clock_nsec / 1000000) % 1000)); sizing = size_to_str(sn->vm_state_size); - qemu_printf("%-10s%-20s%11s%20s%15s", + if (sn->icount != -1ULL) { + snprintf(icount_buf, sizeof(icount_buf), + "%"PRId64, sn->icount); + } + qemu_printf("%-9s %-17s %7s%20s%13s%11s", sn->id_str, sn->name, sizing, date_buf, - clock_buf); + clock_buf, + icount_buf); } g_free(sizing); } @@ -845,6 +889,8 @@ void bdrv_image_info_dump(ImageInfo *info) .date_nsec = elem->value->date_nsec, .vm_clock_nsec = elem->value->vm_clock_sec * 1000000000ULL + elem->value->vm_clock_nsec, + .icount = elem->value->has_icount ? + elem->value->icount : -1ULL, }; pstrcpy(sn.id_str, sizeof(sn.id_str), elem->value->id); diff --git a/block/qcow.c b/block/qcow.c index ee5d35fe20ed5781de7907d2cba9bec71a109717..f8919a44d1935b18b545bbd8bbf4a007d000d75a 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -105,15 +105,6 @@ static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename) return 0; } -static QemuOptsList qcow_runtime_opts = { - .name = "qcow", - .head = QTAILQ_HEAD_INITIALIZER(qcow_runtime_opts.head), - .desc = { - BLOCK_CRYPTO_OPT_DEF_QCOW_KEY_SECRET("encrypt."), - { /* end of list */ } - }, -}; - static int qcow_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { @@ -121,7 +112,6 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, unsigned int len, i, shift; int ret; QCowHeader header; - Error *local_err = NULL; QCryptoBlockOpenOptions *crypto_opts = NULL; unsigned int cflags = 0; QDict *encryptopts = NULL; @@ -314,9 +304,8 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, error_setg(&s->migration_blocker, "The qcow format used by node '%s' " "does not support live migration", bdrv_get_device_or_node_name(bs)); - ret = migrate_add_blocker(s->migration_blocker, &local_err); - if (local_err) { - error_propagate(errp, local_err); + ret = migrate_add_blocker(s->migration_blocker, errp); + if (ret < 0) { error_free(s->migration_blocker); goto fail; } @@ -940,11 +929,11 @@ static int coroutine_fn qcow_co_create_opts(BlockDriver *drv, { BlockdevCreateOptions *create_options = NULL; BlockDriverState *bs = NULL; - QDict *qdict; + QDict *qdict = NULL; Visitor *v; const char *val; - Error *local_err = NULL; int ret; + char *backing_fmt; static const QDictRenames opt_renames[] = { { BLOCK_OPT_BACKING_FILE, "backing-file" }, @@ -952,6 +941,17 @@ static int coroutine_fn qcow_co_create_opts(BlockDriver *drv, { NULL, NULL }, }; + /* + * We can't actually store a backing format, but can check that + * the user's request made sense. + */ + backing_fmt = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FMT); + if (backing_fmt && !bdrv_find_format(backing_fmt)) { + error_setg(errp, "unrecognized backing format '%s'", backing_fmt); + ret = -EINVAL; + goto fail; + } + /* Parse options and convert legacy syntax */ qdict = qemu_opts_to_qdict_filtered(opts, NULL, &qcow_create_opts, true); @@ -973,9 +973,8 @@ static int coroutine_fn qcow_co_create_opts(BlockDriver *drv, } /* Create and open the file (protocol layer) */ - ret = bdrv_create_file(filename, opts, &local_err); + ret = bdrv_create_file(filename, opts, errp); if (ret < 0) { - error_propagate(errp, local_err); goto fail; } @@ -996,11 +995,9 @@ static int coroutine_fn qcow_co_create_opts(BlockDriver *drv, goto fail; } - visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); + visit_type_BlockdevCreateOptions(v, NULL, &create_options, errp); visit_free(v); - - if (local_err) { - error_propagate(errp, local_err); + if (!create_options) { ret = -EINVAL; goto fail; } @@ -1018,6 +1015,7 @@ static int coroutine_fn qcow_co_create_opts(BlockDriver *drv, ret = 0; fail: + g_free(backing_fmt); qobject_unref(qdict); bdrv_unref(bs); qapi_free_BlockdevCreateOptions(create_options); @@ -1152,6 +1150,11 @@ static QemuOptsList qcow_create_opts = { .type = QEMU_OPT_STRING, .help = "File name of a base image" }, + { + .name = BLOCK_OPT_BACKING_FMT, + .type = QEMU_OPT_STRING, + .help = "Format of the backing image", + }, { .name = BLOCK_OPT_ENCRYPT, .type = QEMU_OPT_BOOL, diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c index 1cf6d2ab77a3f4f3da87d9772aa445a98039ce94..d7a31a8ddcdbe123489456fbf31a5abba73b28ac 100644 --- a/block/qcow2-bitmap.c +++ b/block/qcow2-bitmap.c @@ -42,6 +42,9 @@ #define BME_MIN_GRANULARITY_BITS 9 #define BME_MAX_NAME_SIZE 1023 +/* Size of bitmap table entries */ +#define BME_TABLE_ENTRY_SIZE (sizeof(uint64_t)) + QEMU_BUILD_BUG_ON(BME_MAX_NAME_SIZE != BDRV_BITMAP_MAX_NAME_SIZE); #if BME_MAX_TABLE_SIZE * 8ULL > INT_MAX @@ -232,7 +235,7 @@ static int bitmap_table_load(BlockDriverState *bs, Qcow2BitmapTable *tb, assert(tb->size <= BME_MAX_TABLE_SIZE); ret = bdrv_pread(bs->file, tb->offset, - table, tb->size * sizeof(uint64_t)); + table, tb->size * BME_TABLE_ENTRY_SIZE); if (ret < 0) { goto fail; } @@ -265,7 +268,7 @@ static int free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb) } clear_bitmap_table(bs, bitmap_table, tb->size); - qcow2_free_clusters(bs, tb->offset, tb->size * sizeof(uint64_t), + qcow2_free_clusters(bs, tb->offset, tb->size * BME_TABLE_ENTRY_SIZE, QCOW2_DISCARD_OTHER); g_free(bitmap_table); @@ -690,7 +693,7 @@ int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res, ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, refcount_table_size, bm->table.offset, - bm->table.size * sizeof(uint64_t)); + bm->table.size * BME_TABLE_ENTRY_SIZE); if (ret < 0) { goto out; } @@ -1562,11 +1565,22 @@ void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Qcow2Bitmap *bm; if (!bdrv_dirty_bitmap_get_persistence(bitmap) || - bdrv_dirty_bitmap_readonly(bitmap) || bdrv_dirty_bitmap_inconsistent(bitmap)) { continue; } + if (bdrv_dirty_bitmap_readonly(bitmap)) { + /* + * Store the bitmap in the associated Qcow2Bitmap so it + * can be released later + */ + bm = find_bitmap_by_name(bm_list, name); + if (bm) { + bm->dirty_bitmap = bitmap; + } + continue; + } + need_write = true; if (check_constraints_on_bitmap(bs, name, granularity, errp) < 0) { @@ -1618,7 +1632,9 @@ void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, /* allocate clusters and store bitmaps */ QSIMPLEQ_FOREACH(bm, bm_list, entry) { - if (bm->dirty_bitmap == NULL) { + BdrvDirtyBitmap *bitmap = bm->dirty_bitmap; + + if (bitmap == NULL || bdrv_dirty_bitmap_readonly(bitmap)) { continue; } @@ -1641,6 +1657,7 @@ void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, g_free(tb); } +success: if (release_stored) { QSIMPLEQ_FOREACH(bm, bm_list, entry) { if (bm->dirty_bitmap == NULL) { @@ -1651,13 +1668,14 @@ void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, } } -success: bitmap_list_free(bm_list); return; fail: QSIMPLEQ_FOREACH(bm, bm_list, entry) { - if (bm->dirty_bitmap == NULL || bm->table.offset == 0) { + if (bm->dirty_bitmap == NULL || bm->table.offset == 0 || + bdrv_dirty_bitmap_readonly(bm->dirty_bitmap)) + { continue; } @@ -1755,3 +1773,40 @@ bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs) return s->qcow_version >= 3; } + +/* + * Compute the space required to copy bitmaps from @in_bs. + * + * The computation is based as if copying to a new image with the + * given @cluster_size, which may differ from the cluster size in + * @in_bs; in fact, @in_bs might be something other than qcow2. + */ +uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *in_bs, + uint32_t cluster_size) +{ + uint64_t bitmaps_size = 0; + BdrvDirtyBitmap *bm; + size_t bitmap_dir_size = 0; + + FOR_EACH_DIRTY_BITMAP(in_bs, bm) { + if (bdrv_dirty_bitmap_get_persistence(bm)) { + const char *name = bdrv_dirty_bitmap_name(bm); + uint32_t granularity = bdrv_dirty_bitmap_granularity(bm); + uint64_t bmbytes = + get_bitmap_bytes_needed(bdrv_dirty_bitmap_size(bm), + granularity); + uint64_t bmclusters = DIV_ROUND_UP(bmbytes, cluster_size); + + /* Assume the entire bitmap is allocated */ + bitmaps_size += bmclusters * cluster_size; + /* Also reserve space for the bitmap table entries */ + bitmaps_size += ROUND_UP(bmclusters * BME_TABLE_ENTRY_SIZE, + cluster_size); + /* And space for contribution to bitmap directory size */ + bitmap_dir_size += calc_dir_entry_size(strlen(name), 0); + } + } + bitmaps_size += ROUND_UP(bitmap_dir_size, cluster_size); + + return bitmaps_size; +} diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 4b5fc8c4a78aba5af451726c5e40a1f1670310cb..bd0597842f320e7bc635fa67a3ed92e9c2c08621 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -47,8 +47,8 @@ int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t exact_size) BLKDBG_EVENT(bs->file, BLKDBG_L1_SHRINK_WRITE_TABLE); ret = bdrv_pwrite_zeroes(bs->file, s->l1_table_offset + - new_l1_size * sizeof(uint64_t), - (s->l1_size - new_l1_size) * sizeof(uint64_t), 0); + new_l1_size * L1E_SIZE, + (s->l1_size - new_l1_size) * L1E_SIZE, 0); if (ret < 0) { goto fail; } @@ -76,7 +76,7 @@ fail: * l1_table in memory to avoid possible image corruption. */ memset(s->l1_table + new_l1_size, 0, - (s->l1_size - new_l1_size) * sizeof(uint64_t)); + (s->l1_size - new_l1_size) * L1E_SIZE); return ret; } @@ -96,7 +96,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, /* Do a sanity check on min_size before trying to calculate new_l1_size * (this prevents overflows during the while loop for the calculation of * new_l1_size) */ - if (min_size > INT_MAX / sizeof(uint64_t)) { + if (min_size > INT_MAX / L1E_SIZE) { return -EFBIG; } @@ -114,7 +114,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, } QEMU_BUILD_BUG_ON(QCOW_MAX_L1_SIZE > INT_MAX); - if (new_l1_size > QCOW_MAX_L1_SIZE / sizeof(uint64_t)) { + if (new_l1_size > QCOW_MAX_L1_SIZE / L1E_SIZE) { return -EFBIG; } @@ -123,7 +123,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, s->l1_size, new_l1_size); #endif - new_l1_size2 = sizeof(uint64_t) * new_l1_size; + new_l1_size2 = L1E_SIZE * new_l1_size; new_l1_table = qemu_try_blockalign(bs->file->bs, new_l1_size2); if (new_l1_table == NULL) { return -ENOMEM; @@ -131,7 +131,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, memset(new_l1_table, 0, new_l1_size2); if (s->l1_size) { - memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t)); + memcpy(new_l1_table, s->l1_table, s->l1_size * L1E_SIZE); } /* write new table (align to cluster) */ @@ -180,7 +180,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, s->l1_table = new_l1_table; old_l1_size = s->l1_size; s->l1_size = new_l1_size; - qcow2_free_clusters(bs, old_l1_table_offset, old_l1_size * sizeof(uint64_t), + qcow2_free_clusters(bs, old_l1_table_offset, old_l1_size * L1E_SIZE, QCOW2_DISCARD_OTHER); return 0; fail: @@ -208,7 +208,7 @@ static int l2_load(BlockDriverState *bs, uint64_t offset, uint64_t l2_offset, uint64_t **l2_slice) { BDRVQcow2State *s = bs->opaque; - int start_of_slice = sizeof(uint64_t) * + int start_of_slice = l2_entry_size(s) * (offset_to_l2_index(s, offset) - offset_to_l2_slice_index(s, offset)); return qcow2_cache_get(bs, s->l2_table_cache, l2_offset + start_of_slice, @@ -225,9 +225,9 @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index) BDRVQcow2State *s = bs->opaque; int l1_start_index; int i, ret; - int bufsize = MAX(sizeof(uint64_t), + int bufsize = MAX(L1E_SIZE, MIN(bs->file->bs->bl.request_alignment, s->cluster_size)); - int nentries = bufsize / sizeof(uint64_t); + int nentries = bufsize / L1E_SIZE; g_autofree uint64_t *buf = g_try_new0(uint64_t, nentries); if (buf == NULL) { @@ -240,14 +240,14 @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index) } ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L1, - s->l1_table_offset + 8 * l1_start_index, bufsize, false); + s->l1_table_offset + L1E_SIZE * l1_start_index, bufsize, false); if (ret < 0) { return ret; } BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE); ret = bdrv_pwrite_sync(bs->file, - s->l1_table_offset + 8 * l1_start_index, + s->l1_table_offset + L1E_SIZE * l1_start_index, buf, bufsize); if (ret < 0) { return ret; @@ -281,7 +281,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index) /* allocate a new l2 entry */ - l2_offset = qcow2_alloc_clusters(bs, s->l2_size * sizeof(uint64_t)); + l2_offset = qcow2_alloc_clusters(bs, s->l2_size * l2_entry_size(s)); if (l2_offset < 0) { ret = l2_offset; goto fail; @@ -305,7 +305,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index) /* allocate a new entry in the l2 cache */ - slice_size2 = s->l2_slice_size * sizeof(uint64_t); + slice_size2 = s->l2_slice_size * l2_entry_size(s); n_slices = s->cluster_size / slice_size2; trace_qcow2_l2_allocate_get_empty(bs, l1_index); @@ -369,70 +369,123 @@ fail: } s->l1_table[l1_index] = old_l2_offset; if (l2_offset > 0) { - qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t), + qcow2_free_clusters(bs, l2_offset, s->l2_size * l2_entry_size(s), QCOW2_DISCARD_ALWAYS); } return ret; } /* - * Checks how many clusters in a given L2 slice are contiguous in the image - * file. As soon as one of the flags in the bitmask stop_flags changes compared - * to the first cluster, the search is stopped and the cluster is not counted - * as contiguous. (This allows it, for example, to stop at the first compressed - * cluster which may require a different handling) + * For a given L2 entry, count the number of contiguous subclusters of + * the same type starting from @sc_from. Compressed clusters are + * treated as if they were divided into subclusters of size + * s->subcluster_size. + * + * Return the number of contiguous subclusters and set @type to the + * subcluster type. + * + * If the L2 entry is invalid return -errno and set @type to + * QCOW2_SUBCLUSTER_INVALID. */ -static int count_contiguous_clusters(BlockDriverState *bs, int nb_clusters, - int cluster_size, uint64_t *l2_slice, uint64_t stop_flags) +static int qcow2_get_subcluster_range_type(BlockDriverState *bs, + uint64_t l2_entry, + uint64_t l2_bitmap, + unsigned sc_from, + QCow2SubclusterType *type) { - int i; - QCow2ClusterType first_cluster_type; - uint64_t mask = stop_flags | L2E_OFFSET_MASK | QCOW_OFLAG_COMPRESSED; - uint64_t first_entry = be64_to_cpu(l2_slice[0]); - uint64_t offset = first_entry & mask; + BDRVQcow2State *s = bs->opaque; + uint32_t val; - first_cluster_type = qcow2_get_cluster_type(bs, first_entry); - if (first_cluster_type == QCOW2_CLUSTER_UNALLOCATED) { - return 0; + *type = qcow2_get_subcluster_type(bs, l2_entry, l2_bitmap, sc_from); + + if (*type == QCOW2_SUBCLUSTER_INVALID) { + return -EINVAL; + } else if (!has_subclusters(s) || *type == QCOW2_SUBCLUSTER_COMPRESSED) { + return s->subclusters_per_cluster - sc_from; } - /* must be allocated */ - assert(first_cluster_type == QCOW2_CLUSTER_NORMAL || - first_cluster_type == QCOW2_CLUSTER_ZERO_ALLOC); + switch (*type) { + case QCOW2_SUBCLUSTER_NORMAL: + val = l2_bitmap | QCOW_OFLAG_SUB_ALLOC_RANGE(0, sc_from); + return cto32(val) - sc_from; - for (i = 0; i < nb_clusters; i++) { - uint64_t l2_entry = be64_to_cpu(l2_slice[i]) & mask; - if (offset + (uint64_t) i * cluster_size != l2_entry) { - break; - } - } + case QCOW2_SUBCLUSTER_ZERO_PLAIN: + case QCOW2_SUBCLUSTER_ZERO_ALLOC: + val = (l2_bitmap | QCOW_OFLAG_SUB_ZERO_RANGE(0, sc_from)) >> 32; + return cto32(val) - sc_from; + + case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN: + case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC: + val = ((l2_bitmap >> 32) | l2_bitmap) + & ~QCOW_OFLAG_SUB_ALLOC_RANGE(0, sc_from); + return ctz32(val) - sc_from; - return i; + default: + g_assert_not_reached(); + } } /* - * Checks how many consecutive unallocated clusters in a given L2 - * slice have the same cluster type. + * Return the number of contiguous subclusters of the exact same type + * in a given L2 slice, starting from cluster @l2_index, subcluster + * @sc_index. Allocated subclusters are required to be contiguous in + * the image file. + * At most @nb_clusters are checked (note that this means clusters, + * not subclusters). + * Compressed clusters are always processed one by one but for the + * purpose of this count they are treated as if they were divided into + * subclusters of size s->subcluster_size. + * On failure return -errno and update @l2_index to point to the + * invalid entry. */ -static int count_contiguous_clusters_unallocated(BlockDriverState *bs, - int nb_clusters, - uint64_t *l2_slice, - QCow2ClusterType wanted_type) +static int count_contiguous_subclusters(BlockDriverState *bs, int nb_clusters, + unsigned sc_index, uint64_t *l2_slice, + unsigned *l2_index) { - int i; + BDRVQcow2State *s = bs->opaque; + int i, count = 0; + bool check_offset = false; + uint64_t expected_offset = 0; + QCow2SubclusterType expected_type = QCOW2_SUBCLUSTER_NORMAL, type; - assert(wanted_type == QCOW2_CLUSTER_ZERO_PLAIN || - wanted_type == QCOW2_CLUSTER_UNALLOCATED); - for (i = 0; i < nb_clusters; i++) { - uint64_t entry = be64_to_cpu(l2_slice[i]); - QCow2ClusterType type = qcow2_get_cluster_type(bs, entry); + assert(*l2_index + nb_clusters <= s->l2_slice_size); - if (type != wanted_type) { + for (i = 0; i < nb_clusters; i++) { + unsigned first_sc = (i == 0) ? sc_index : 0; + uint64_t l2_entry = get_l2_entry(s, l2_slice, *l2_index + i); + uint64_t l2_bitmap = get_l2_bitmap(s, l2_slice, *l2_index + i); + int ret = qcow2_get_subcluster_range_type(bs, l2_entry, l2_bitmap, + first_sc, &type); + if (ret < 0) { + *l2_index += i; /* Point to the invalid entry */ + return -EIO; + } + if (i == 0) { + if (type == QCOW2_SUBCLUSTER_COMPRESSED) { + /* Compressed clusters are always processed one by one */ + return ret; + } + expected_type = type; + expected_offset = l2_entry & L2E_OFFSET_MASK; + check_offset = (type == QCOW2_SUBCLUSTER_NORMAL || + type == QCOW2_SUBCLUSTER_ZERO_ALLOC || + type == QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC); + } else if (type != expected_type) { + break; + } else if (check_offset) { + expected_offset += s->cluster_size; + if (expected_offset != (l2_entry & L2E_OFFSET_MASK)) { + break; + } + } + count += ret; + /* Stop if there are type changes before the end of the cluster */ + if (first_sc + ret < s->subclusters_per_cluster) { break; } } - return i; + return count; } static int coroutine_fn do_perform_cow_read(BlockDriverState *bs, @@ -496,31 +549,37 @@ static int coroutine_fn do_perform_cow_write(BlockDriverState *bs, /* - * get_cluster_offset + * get_host_offset + * + * For a given offset of the virtual disk find the equivalent host + * offset in the qcow2 file and store it in *host_offset. Neither + * offset needs to be aligned to a cluster boundary. * - * For a given offset of the virtual disk, find the cluster type and offset in - * the qcow2 file. The offset is stored in *cluster_offset. + * If the cluster is unallocated then *host_offset will be 0. + * If the cluster is compressed then *host_offset will contain the + * complete compressed cluster descriptor. * * On entry, *bytes is the maximum number of contiguous bytes starting at * offset that we are interested in. * * On exit, *bytes is the number of bytes starting at offset that have the same - * cluster type and (if applicable) are stored contiguously in the image file. - * Compressed clusters are always returned one by one. + * subcluster type and (if applicable) are stored contiguously in the image + * file. The subcluster type is stored in *subcluster_type. + * Compressed clusters are always processed one by one. * - * Returns the cluster type (QCOW2_CLUSTER_*) on success, -errno in error - * cases. + * Returns 0 on success, -errno in error cases. */ -int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, - unsigned int *bytes, uint64_t *cluster_offset) +int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset, + unsigned int *bytes, uint64_t *host_offset, + QCow2SubclusterType *subcluster_type) { BDRVQcow2State *s = bs->opaque; - unsigned int l2_index; - uint64_t l1_index, l2_offset, *l2_slice; - int c; + unsigned int l2_index, sc_index; + uint64_t l1_index, l2_offset, *l2_slice, l2_entry, l2_bitmap; + int sc; unsigned int offset_in_cluster; uint64_t bytes_available, bytes_needed, nb_clusters; - QCow2ClusterType type; + QCow2SubclusterType type; int ret; offset_in_cluster = offset_into_cluster(s, offset); @@ -537,19 +596,19 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, bytes_needed = bytes_available; } - *cluster_offset = 0; + *host_offset = 0; /* seek to the l2 offset in the l1 table */ l1_index = offset_to_l1_index(s, offset); if (l1_index >= s->l1_size) { - type = QCOW2_CLUSTER_UNALLOCATED; + type = QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN; goto out; } l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK; if (!l2_offset) { - type = QCOW2_CLUSTER_UNALLOCATED; + type = QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN; goto out; } @@ -570,7 +629,9 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, /* find the cluster offset for the given disk offset */ l2_index = offset_to_l2_slice_index(s, offset); - *cluster_offset = be64_to_cpu(l2_slice[l2_index]); + sc_index = offset_to_sc_index(s, offset); + l2_entry = get_l2_entry(s, l2_slice, l2_index); + l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index); nb_clusters = size_to_clusters(s, bytes_needed); /* bytes_needed <= *bytes + offset_in_cluster, both of which are unsigned @@ -578,9 +639,9 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, * true */ assert(nb_clusters <= INT_MAX); - type = qcow2_get_cluster_type(bs, *cluster_offset); - if (s->qcow_version < 3 && (type == QCOW2_CLUSTER_ZERO_PLAIN || - type == QCOW2_CLUSTER_ZERO_ALLOC)) { + type = qcow2_get_subcluster_type(bs, l2_entry, l2_bitmap, sc_index); + if (s->qcow_version < 3 && (type == QCOW2_SUBCLUSTER_ZERO_PLAIN || + type == QCOW2_SUBCLUSTER_ZERO_ALLOC)) { qcow2_signal_corruption(bs, true, -1, -1, "Zero cluster entry found" " in pre-v3 image (L2 offset: %#" PRIx64 ", L2 index: %#x)", l2_offset, l2_index); @@ -588,7 +649,9 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, goto fail; } switch (type) { - case QCOW2_CLUSTER_COMPRESSED: + case QCOW2_SUBCLUSTER_INVALID: + break; /* This is handled by count_contiguous_subclusters() below */ + case QCOW2_SUBCLUSTER_COMPRESSED: if (has_data_file(bs)) { qcow2_signal_corruption(bs, true, -1, -1, "Compressed cluster " "entry found in image with external data " @@ -597,51 +660,53 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, ret = -EIO; goto fail; } - /* Compressed clusters can only be processed one by one */ - c = 1; - *cluster_offset &= L2E_COMPRESSED_OFFSET_SIZE_MASK; + *host_offset = l2_entry & L2E_COMPRESSED_OFFSET_SIZE_MASK; break; - case QCOW2_CLUSTER_ZERO_PLAIN: - case QCOW2_CLUSTER_UNALLOCATED: - /* how many empty clusters ? */ - c = count_contiguous_clusters_unallocated(bs, nb_clusters, - &l2_slice[l2_index], type); - *cluster_offset = 0; + case QCOW2_SUBCLUSTER_ZERO_PLAIN: + case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN: break; - case QCOW2_CLUSTER_ZERO_ALLOC: - case QCOW2_CLUSTER_NORMAL: - /* how many allocated clusters ? */ - c = count_contiguous_clusters(bs, nb_clusters, s->cluster_size, - &l2_slice[l2_index], QCOW_OFLAG_ZERO); - *cluster_offset &= L2E_OFFSET_MASK; - if (offset_into_cluster(s, *cluster_offset)) { + case QCOW2_SUBCLUSTER_ZERO_ALLOC: + case QCOW2_SUBCLUSTER_NORMAL: + case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC: { + uint64_t host_cluster_offset = l2_entry & L2E_OFFSET_MASK; + *host_offset = host_cluster_offset + offset_in_cluster; + if (offset_into_cluster(s, host_cluster_offset)) { qcow2_signal_corruption(bs, true, -1, -1, "Cluster allocation offset %#" PRIx64 " unaligned (L2 offset: %#" PRIx64 - ", L2 index: %#x)", *cluster_offset, + ", L2 index: %#x)", host_cluster_offset, l2_offset, l2_index); ret = -EIO; goto fail; } - if (has_data_file(bs) && *cluster_offset != offset - offset_in_cluster) - { + if (has_data_file(bs) && *host_offset != offset) { qcow2_signal_corruption(bs, true, -1, -1, "External data file host cluster offset %#" PRIx64 " does not match guest cluster " "offset: %#" PRIx64 - ", L2 index: %#x)", *cluster_offset, + ", L2 index: %#x)", host_cluster_offset, offset - offset_in_cluster, l2_index); ret = -EIO; goto fail; } break; + } default: abort(); } + sc = count_contiguous_subclusters(bs, nb_clusters, sc_index, + l2_slice, &l2_index); + if (sc < 0) { + qcow2_signal_corruption(bs, true, -1, -1, "Invalid cluster entry found " + " (L2 offset: %#" PRIx64 ", L2 index: %#x)", + l2_offset, l2_index); + ret = -EIO; + goto fail; + } qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice); - bytes_available = (int64_t)c * s->cluster_size; + bytes_available = ((int64_t)sc + sc_index) << s->subcluster_bits; out: if (bytes_available > bytes_needed) { @@ -654,7 +719,9 @@ out: assert(bytes_available - offset_in_cluster <= UINT_MAX); *bytes = bytes_available - offset_in_cluster; - return type; + *subcluster_type = type; + + return 0; fail: qcow2_cache_put(s->l2_table_cache, (void **)&l2_slice); @@ -709,7 +776,7 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset, /* Then decrease the refcount of the old table */ if (l2_offset) { - qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t), + qcow2_free_clusters(bs, l2_offset, s->l2_size * l2_entry_size(s), QCOW2_DISCARD_OTHER); } @@ -765,7 +832,7 @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, /* Compression can't overwrite anything. Fail if the cluster was already * allocated. */ - cluster_offset = be64_to_cpu(l2_slice[l2_index]); + cluster_offset = get_l2_entry(s, l2_slice, l2_index); if (cluster_offset & L2E_OFFSET_MASK) { qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice); return -EIO; @@ -794,7 +861,10 @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED); qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice); - l2_slice[l2_index] = cpu_to_be64(cluster_offset); + set_l2_entry(s, l2_slice, l2_index, cluster_offset); + if (has_subclusters(s)) { + set_l2_bitmap(s, l2_slice, l2_index, 0); + } qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice); *host_offset = cluster_offset & s->cluster_offset_mask; @@ -979,22 +1049,41 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice); assert(l2_index + m->nb_clusters <= s->l2_slice_size); + assert(m->cow_end.offset + m->cow_end.nb_bytes <= + m->nb_clusters << s->cluster_bits); for (i = 0; i < m->nb_clusters; i++) { - uint64_t offset = cluster_offset + (i << s->cluster_bits); + uint64_t offset = cluster_offset + ((uint64_t)i << s->cluster_bits); /* if two concurrent writes happen to the same unallocated cluster * each write allocates separate cluster and writes data concurrently. * The first one to complete updates l2 table with pointer to its * cluster the second one has to do RMW (which is done above by * perform_cow()), update l2 table with its cluster pointer and free * old cluster. This is what this loop does */ - if (l2_slice[l2_index + i] != 0) { - old_cluster[j++] = l2_slice[l2_index + i]; + if (get_l2_entry(s, l2_slice, l2_index + i) != 0) { + old_cluster[j++] = get_l2_entry(s, l2_slice, l2_index + i); } /* The offset must fit in the offset field of the L2 table entry */ assert((offset & L2E_OFFSET_MASK) == offset); - l2_slice[l2_index + i] = cpu_to_be64(offset | QCOW_OFLAG_COPIED); + set_l2_entry(s, l2_slice, l2_index + i, offset | QCOW_OFLAG_COPIED); + + /* Update bitmap with the subclusters that were just written */ + if (has_subclusters(s) && !m->prealloc) { + uint64_t l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + i); + unsigned written_from = m->cow_start.offset; + unsigned written_to = m->cow_end.offset + m->cow_end.nb_bytes; + int first_sc, last_sc; + /* Narrow written_from and written_to down to the current cluster */ + written_from = MAX(written_from, i << s->cluster_bits); + written_to = MIN(written_to, (i + 1) << s->cluster_bits); + assert(written_from < written_to); + first_sc = offset_to_sc_index(s, written_from); + last_sc = offset_to_sc_index(s, written_to - 1); + l2_bitmap |= QCOW_OFLAG_SUB_ALLOC_RANGE(first_sc, last_sc + 1); + l2_bitmap &= ~QCOW_OFLAG_SUB_ZERO_RANGE(first_sc, last_sc + 1); + set_l2_bitmap(s, l2_slice, l2_index + i, l2_bitmap); + } } @@ -1008,8 +1097,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) */ if (!m->keep_old_clusters && j != 0) { for (i = 0; i < j; i++) { - qcow2_free_any_clusters(bs, be64_to_cpu(old_cluster[i]), 1, - QCOW2_DISCARD_NEVER); + qcow2_free_any_cluster(bs, old_cluster[i], QCOW2_DISCARD_NEVER); } } @@ -1034,36 +1122,250 @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m) } /* - * Returns the number of contiguous clusters that can be used for an allocating - * write, but require COW to be performed (this includes yet unallocated space, - * which must copy from the backing file) + * For a given write request, create a new QCowL2Meta structure, add + * it to @m and the BDRVQcow2State.cluster_allocs list. If the write + * request does not need copy-on-write or changes to the L2 metadata + * then this function does nothing. + * + * @host_cluster_offset points to the beginning of the first cluster. + * + * @guest_offset and @bytes indicate the offset and length of the + * request. + * + * @l2_slice contains the L2 entries of all clusters involved in this + * write request. + * + * If @keep_old is true it means that the clusters were already + * allocated and will be overwritten. If false then the clusters are + * new and we have to decrease the reference count of the old ones. + * + * Returns 0 on success, -errno on failure. */ -static int count_cow_clusters(BlockDriverState *bs, int nb_clusters, - uint64_t *l2_slice, int l2_index) +static int calculate_l2_meta(BlockDriverState *bs, uint64_t host_cluster_offset, + uint64_t guest_offset, unsigned bytes, + uint64_t *l2_slice, QCowL2Meta **m, bool keep_old) { + BDRVQcow2State *s = bs->opaque; + int sc_index, l2_index = offset_to_l2_slice_index(s, guest_offset); + uint64_t l2_entry, l2_bitmap; + unsigned cow_start_from, cow_end_to; + unsigned cow_start_to = offset_into_cluster(s, guest_offset); + unsigned cow_end_from = cow_start_to + bytes; + unsigned nb_clusters = size_to_clusters(s, cow_end_from); + QCowL2Meta *old_m = *m; + QCow2SubclusterType type; int i; + bool skip_cow = keep_old; + + assert(nb_clusters <= s->l2_slice_size - l2_index); + /* Check the type of all affected subclusters */ for (i = 0; i < nb_clusters; i++) { - uint64_t l2_entry = be64_to_cpu(l2_slice[l2_index + i]); - QCow2ClusterType cluster_type = qcow2_get_cluster_type(bs, l2_entry); + l2_entry = get_l2_entry(s, l2_slice, l2_index + i); + l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + i); + if (skip_cow) { + unsigned write_from = MAX(cow_start_to, i << s->cluster_bits); + unsigned write_to = MIN(cow_end_from, (i + 1) << s->cluster_bits); + int first_sc = offset_to_sc_index(s, write_from); + int last_sc = offset_to_sc_index(s, write_to - 1); + int cnt = qcow2_get_subcluster_range_type(bs, l2_entry, l2_bitmap, + first_sc, &type); + /* Is any of the subclusters of type != QCOW2_SUBCLUSTER_NORMAL ? */ + if (type != QCOW2_SUBCLUSTER_NORMAL || first_sc + cnt <= last_sc) { + skip_cow = false; + } + } else { + /* If we can't skip the cow we can still look for invalid entries */ + type = qcow2_get_subcluster_type(bs, l2_entry, l2_bitmap, 0); + } + if (type == QCOW2_SUBCLUSTER_INVALID) { + int l1_index = offset_to_l1_index(s, guest_offset); + uint64_t l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK; + qcow2_signal_corruption(bs, true, -1, -1, "Invalid cluster " + "entry found (L2 offset: %#" PRIx64 + ", L2 index: %#x)", + l2_offset, l2_index + i); + return -EIO; + } + } + + if (skip_cow) { + return 0; + } - switch(cluster_type) { - case QCOW2_CLUSTER_NORMAL: - if (l2_entry & QCOW_OFLAG_COPIED) { - goto out; + /* Get the L2 entry of the first cluster */ + l2_entry = get_l2_entry(s, l2_slice, l2_index); + l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index); + sc_index = offset_to_sc_index(s, guest_offset); + type = qcow2_get_subcluster_type(bs, l2_entry, l2_bitmap, sc_index); + + if (!keep_old) { + switch (type) { + case QCOW2_SUBCLUSTER_COMPRESSED: + cow_start_from = 0; + break; + case QCOW2_SUBCLUSTER_NORMAL: + case QCOW2_SUBCLUSTER_ZERO_ALLOC: + case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC: + if (has_subclusters(s)) { + /* Skip all leading zero and unallocated subclusters */ + uint32_t alloc_bitmap = l2_bitmap & QCOW_L2_BITMAP_ALL_ALLOC; + cow_start_from = + MIN(sc_index, ctz32(alloc_bitmap)) << s->subcluster_bits; + } else { + cow_start_from = 0; } break; - case QCOW2_CLUSTER_UNALLOCATED: - case QCOW2_CLUSTER_COMPRESSED: - case QCOW2_CLUSTER_ZERO_PLAIN: - case QCOW2_CLUSTER_ZERO_ALLOC: + case QCOW2_SUBCLUSTER_ZERO_PLAIN: + case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN: + cow_start_from = sc_index << s->subcluster_bits; + break; + default: + g_assert_not_reached(); + } + } else { + switch (type) { + case QCOW2_SUBCLUSTER_NORMAL: + cow_start_from = cow_start_to; + break; + case QCOW2_SUBCLUSTER_ZERO_ALLOC: + case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC: + cow_start_from = sc_index << s->subcluster_bits; break; default: - abort(); + g_assert_not_reached(); + } + } + + /* Get the L2 entry of the last cluster */ + l2_index += nb_clusters - 1; + l2_entry = get_l2_entry(s, l2_slice, l2_index); + l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index); + sc_index = offset_to_sc_index(s, guest_offset + bytes - 1); + type = qcow2_get_subcluster_type(bs, l2_entry, l2_bitmap, sc_index); + + if (!keep_old) { + switch (type) { + case QCOW2_SUBCLUSTER_COMPRESSED: + cow_end_to = ROUND_UP(cow_end_from, s->cluster_size); + break; + case QCOW2_SUBCLUSTER_NORMAL: + case QCOW2_SUBCLUSTER_ZERO_ALLOC: + case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC: + cow_end_to = ROUND_UP(cow_end_from, s->cluster_size); + if (has_subclusters(s)) { + /* Skip all trailing zero and unallocated subclusters */ + uint32_t alloc_bitmap = l2_bitmap & QCOW_L2_BITMAP_ALL_ALLOC; + cow_end_to -= + MIN(s->subclusters_per_cluster - sc_index - 1, + clz32(alloc_bitmap)) << s->subcluster_bits; + } + break; + case QCOW2_SUBCLUSTER_ZERO_PLAIN: + case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN: + cow_end_to = ROUND_UP(cow_end_from, s->subcluster_size); + break; + default: + g_assert_not_reached(); + } + } else { + switch (type) { + case QCOW2_SUBCLUSTER_NORMAL: + cow_end_to = cow_end_from; + break; + case QCOW2_SUBCLUSTER_ZERO_ALLOC: + case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC: + cow_end_to = ROUND_UP(cow_end_from, s->subcluster_size); + break; + default: + g_assert_not_reached(); + } + } + + *m = g_malloc0(sizeof(**m)); + **m = (QCowL2Meta) { + .next = old_m, + + .alloc_offset = host_cluster_offset, + .offset = start_of_cluster(s, guest_offset), + .nb_clusters = nb_clusters, + + .keep_old_clusters = keep_old, + + .cow_start = { + .offset = cow_start_from, + .nb_bytes = cow_start_to - cow_start_from, + }, + .cow_end = { + .offset = cow_end_from, + .nb_bytes = cow_end_to - cow_end_from, + }, + }; + + qemu_co_queue_init(&(*m)->dependent_requests); + QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight); + + return 0; +} + +/* + * Returns true if writing to the cluster pointed to by @l2_entry + * requires a new allocation (that is, if the cluster is unallocated + * or has refcount > 1 and therefore cannot be written in-place). + */ +static bool cluster_needs_new_alloc(BlockDriverState *bs, uint64_t l2_entry) +{ + switch (qcow2_get_cluster_type(bs, l2_entry)) { + case QCOW2_CLUSTER_NORMAL: + case QCOW2_CLUSTER_ZERO_ALLOC: + if (l2_entry & QCOW_OFLAG_COPIED) { + return false; + } + /* fallthrough */ + case QCOW2_CLUSTER_UNALLOCATED: + case QCOW2_CLUSTER_COMPRESSED: + case QCOW2_CLUSTER_ZERO_PLAIN: + return true; + default: + abort(); + } +} + +/* + * Returns the number of contiguous clusters that can be written to + * using one single write request, starting from @l2_index. + * At most @nb_clusters are checked. + * + * If @new_alloc is true this counts clusters that are either + * unallocated, or allocated but with refcount > 1 (so they need to be + * newly allocated and COWed). + * + * If @new_alloc is false this counts clusters that are already + * allocated and can be overwritten in-place (this includes clusters + * of type QCOW2_CLUSTER_ZERO_ALLOC). + */ +static int count_single_write_clusters(BlockDriverState *bs, int nb_clusters, + uint64_t *l2_slice, int l2_index, + bool new_alloc) +{ + BDRVQcow2State *s = bs->opaque; + uint64_t l2_entry = get_l2_entry(s, l2_slice, l2_index); + uint64_t expected_offset = l2_entry & L2E_OFFSET_MASK; + int i; + + for (i = 0; i < nb_clusters; i++) { + l2_entry = get_l2_entry(s, l2_slice, l2_index + i); + if (cluster_needs_new_alloc(bs, l2_entry) != new_alloc) { + break; + } + if (!new_alloc) { + if (expected_offset != (l2_entry & L2E_OFFSET_MASK)) { + break; + } + expected_offset += s->cluster_size; } } -out: assert(i <= nb_clusters); return i; } @@ -1093,8 +1395,8 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset, uint64_t start = guest_offset; uint64_t end = start + bytes; - uint64_t old_start = l2meta_cow_start(old_alloc); - uint64_t old_end = l2meta_cow_end(old_alloc); + uint64_t old_start = start_of_cluster(s, l2meta_cow_start(old_alloc)); + uint64_t old_end = ROUND_UP(l2meta_cow_end(old_alloc), s->cluster_size); if (end <= old_start || start >= old_end) { /* No intersection */ @@ -1132,10 +1434,10 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset, } /* - * Checks how many already allocated clusters that don't require a copy on - * write there are at the given guest_offset (up to *bytes). If *host_offset is - * not INV_OFFSET, only physically contiguous clusters beginning at this host - * offset are counted. + * Checks how many already allocated clusters that don't require a new + * allocation there are at the given guest_offset (up to *bytes). + * If *host_offset is not INV_OFFSET, only physically contiguous clusters + * beginning at this host offset are counted. * * Note that guest_offset may not be cluster aligned. In this case, the * returned *host_offset points to exact byte referenced by guest_offset and @@ -1144,12 +1446,12 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset, * Returns: * 0: if no allocated clusters are available at the given offset. * *bytes is normally unchanged. It is set to 0 if the cluster - * is allocated and doesn't need COW, but doesn't have the right - * physical offset. + * is allocated and can be overwritten in-place but doesn't have + * the right physical offset. * - * 1: if allocated clusters that don't require a COW are available at - * the requested offset. *bytes may have decreased and describes - * the length of the area that can be written to. + * 1: if allocated clusters that can be overwritten in place are + * available at the requested offset. *bytes may have decreased + * and describes the length of the area that can be written to. * * -errno: in error cases */ @@ -1158,7 +1460,7 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset, { BDRVQcow2State *s = bs->opaque; int l2_index; - uint64_t cluster_offset; + uint64_t l2_entry, cluster_offset; uint64_t *l2_slice; uint64_t nb_clusters; unsigned int keep_clusters; @@ -1179,7 +1481,8 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset, l2_index = offset_to_l2_slice_index(s, guest_offset); nb_clusters = MIN(nb_clusters, s->l2_slice_size - l2_index); - assert(nb_clusters <= INT_MAX); + /* Limit total byte count to BDRV_REQUEST_MAX_BYTES */ + nb_clusters = MIN(nb_clusters, BDRV_REQUEST_MAX_BYTES >> s->cluster_bits); /* Find L2 entry for the first involved cluster */ ret = get_cluster_table(bs, guest_offset, &l2_slice, &l2_index); @@ -1187,41 +1490,42 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset, return ret; } - cluster_offset = be64_to_cpu(l2_slice[l2_index]); + l2_entry = get_l2_entry(s, l2_slice, l2_index); + cluster_offset = l2_entry & L2E_OFFSET_MASK; - /* Check how many clusters are already allocated and don't need COW */ - if (qcow2_get_cluster_type(bs, cluster_offset) == QCOW2_CLUSTER_NORMAL - && (cluster_offset & QCOW_OFLAG_COPIED)) - { - /* If a specific host_offset is required, check it */ - bool offset_matches = - (cluster_offset & L2E_OFFSET_MASK) == *host_offset; - - if (offset_into_cluster(s, cluster_offset & L2E_OFFSET_MASK)) { - qcow2_signal_corruption(bs, true, -1, -1, "Data cluster offset " - "%#llx unaligned (guest offset: %#" PRIx64 - ")", cluster_offset & L2E_OFFSET_MASK, - guest_offset); + if (!cluster_needs_new_alloc(bs, l2_entry)) { + if (offset_into_cluster(s, cluster_offset)) { + qcow2_signal_corruption(bs, true, -1, -1, "%s cluster offset " + "%#" PRIx64 " unaligned (guest offset: %#" + PRIx64 ")", l2_entry & QCOW_OFLAG_ZERO ? + "Preallocated zero" : "Data", + cluster_offset, guest_offset); ret = -EIO; goto out; } - if (*host_offset != INV_OFFSET && !offset_matches) { + /* If a specific host_offset is required, check it */ + if (*host_offset != INV_OFFSET && cluster_offset != *host_offset) { *bytes = 0; ret = 0; goto out; } /* We keep all QCOW_OFLAG_COPIED clusters */ - keep_clusters = - count_contiguous_clusters(bs, nb_clusters, s->cluster_size, - &l2_slice[l2_index], - QCOW_OFLAG_COPIED | QCOW_OFLAG_ZERO); + keep_clusters = count_single_write_clusters(bs, nb_clusters, l2_slice, + l2_index, false); assert(keep_clusters <= nb_clusters); *bytes = MIN(*bytes, keep_clusters * s->cluster_size - offset_into_cluster(s, guest_offset)); + assert(*bytes != 0); + + ret = calculate_l2_meta(bs, cluster_offset, guest_offset, + *bytes, l2_slice, m, true); + if (ret < 0) { + goto out; + } ret = 1; } else { @@ -1235,8 +1539,7 @@ out: /* Only return a host offset if we actually made progress. Otherwise we * would make requirements for handle_alloc() that it can't fulfill */ if (ret > 0) { - *host_offset = (cluster_offset & L2E_OFFSET_MASK) - + offset_into_cluster(s, guest_offset); + *host_offset = cluster_offset + offset_into_cluster(s, guest_offset); } return ret; @@ -1297,9 +1600,10 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset, } /* - * Allocates new clusters for an area that either is yet unallocated or needs a - * copy on write. If *host_offset is not INV_OFFSET, clusters are only - * allocated if the new allocation can match the specified host offset. + * Allocates new clusters for an area that is either still unallocated or + * cannot be overwritten in-place. If *host_offset is not INV_OFFSET, + * clusters are only allocated if the new allocation can match the specified + * host offset. * * Note that guest_offset may not be cluster aligned. In this case, the * returned *host_offset points to exact byte referenced by guest_offset and @@ -1322,12 +1626,10 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset, BDRVQcow2State *s = bs->opaque; int l2_index; uint64_t *l2_slice; - uint64_t entry; uint64_t nb_clusters; int ret; - bool keep_old_clusters = false; - uint64_t alloc_cluster_offset = INV_OFFSET; + uint64_t alloc_cluster_offset; trace_qcow2_handle_alloc(qemu_coroutine_self(), guest_offset, *host_offset, *bytes); @@ -1342,10 +1644,8 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset, l2_index = offset_to_l2_slice_index(s, guest_offset); nb_clusters = MIN(nb_clusters, s->l2_slice_size - l2_index); - assert(nb_clusters <= INT_MAX); - - /* Limit total allocation byte count to INT_MAX */ - nb_clusters = MIN(nb_clusters, INT_MAX >> s->cluster_bits); + /* Limit total allocation byte count to BDRV_REQUEST_MAX_BYTES */ + nb_clusters = MIN(nb_clusters, BDRV_REQUEST_MAX_BYTES >> s->cluster_bits); /* Find L2 entry for the first involved cluster */ ret = get_cluster_table(bs, guest_offset, &l2_slice, &l2_index); @@ -1353,67 +1653,32 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset, return ret; } - entry = be64_to_cpu(l2_slice[l2_index]); - nb_clusters = count_cow_clusters(bs, nb_clusters, l2_slice, l2_index); + nb_clusters = count_single_write_clusters(bs, nb_clusters, + l2_slice, l2_index, true); /* This function is only called when there were no non-COW clusters, so if * we can't find any unallocated or COW clusters either, something is * wrong with our code. */ assert(nb_clusters > 0); - if (qcow2_get_cluster_type(bs, entry) == QCOW2_CLUSTER_ZERO_ALLOC && - (entry & QCOW_OFLAG_COPIED) && - (*host_offset == INV_OFFSET || - start_of_cluster(s, *host_offset) == (entry & L2E_OFFSET_MASK))) - { - int preallocated_nb_clusters; - - if (offset_into_cluster(s, entry & L2E_OFFSET_MASK)) { - qcow2_signal_corruption(bs, true, -1, -1, "Preallocated zero " - "cluster offset %#llx unaligned (guest " - "offset: %#" PRIx64 ")", - entry & L2E_OFFSET_MASK, guest_offset); - ret = -EIO; - goto fail; - } - - /* Try to reuse preallocated zero clusters; contiguous normal clusters - * would be fine, too, but count_cow_clusters() above has limited - * nb_clusters already to a range of COW clusters */ - preallocated_nb_clusters = - count_contiguous_clusters(bs, nb_clusters, s->cluster_size, - &l2_slice[l2_index], QCOW_OFLAG_COPIED); - assert(preallocated_nb_clusters > 0); - - nb_clusters = preallocated_nb_clusters; - alloc_cluster_offset = entry & L2E_OFFSET_MASK; - - /* We want to reuse these clusters, so qcow2_alloc_cluster_link_l2() - * should not free them. */ - keep_old_clusters = true; + /* Allocate at a given offset in the image file */ + alloc_cluster_offset = *host_offset == INV_OFFSET ? INV_OFFSET : + start_of_cluster(s, *host_offset); + ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset, + &nb_clusters); + if (ret < 0) { + goto out; } - qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice); - - if (alloc_cluster_offset == INV_OFFSET) { - /* Allocate, if necessary at a given offset in the image file */ - alloc_cluster_offset = *host_offset == INV_OFFSET ? INV_OFFSET : - start_of_cluster(s, *host_offset); - ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset, - &nb_clusters); - if (ret < 0) { - goto fail; - } - - /* Can't extend contiguous allocation */ - if (nb_clusters == 0) { - *bytes = 0; - return 0; - } - - assert(alloc_cluster_offset != INV_OFFSET); + /* Can't extend contiguous allocation */ + if (nb_clusters == 0) { + *bytes = 0; + ret = 0; + goto out; } + assert(alloc_cluster_offset != INV_OFFSET); + /* * Save info needed for meta data update. * @@ -1431,66 +1696,54 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset, uint64_t requested_bytes = *bytes + offset_into_cluster(s, guest_offset); int avail_bytes = nb_clusters << s->cluster_bits; int nb_bytes = MIN(requested_bytes, avail_bytes); - QCowL2Meta *old_m = *m; - - *m = g_malloc0(sizeof(**m)); - - **m = (QCowL2Meta) { - .next = old_m, - - .alloc_offset = alloc_cluster_offset, - .offset = start_of_cluster(s, guest_offset), - .nb_clusters = nb_clusters, - - .keep_old_clusters = keep_old_clusters, - - .cow_start = { - .offset = 0, - .nb_bytes = offset_into_cluster(s, guest_offset), - }, - .cow_end = { - .offset = nb_bytes, - .nb_bytes = avail_bytes - nb_bytes, - }, - }; - qemu_co_queue_init(&(*m)->dependent_requests); - QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight); *host_offset = alloc_cluster_offset + offset_into_cluster(s, guest_offset); *bytes = MIN(*bytes, nb_bytes - offset_into_cluster(s, guest_offset)); assert(*bytes != 0); - return 1; - -fail: - if (*m && (*m)->nb_clusters > 0) { - QLIST_REMOVE(*m, next_in_flight); + ret = calculate_l2_meta(bs, alloc_cluster_offset, guest_offset, *bytes, + l2_slice, m, false); + if (ret < 0) { + goto out; } + + ret = 1; + +out: + qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice); return ret; } /* - * alloc_cluster_offset + * For a given area on the virtual disk defined by @offset and @bytes, + * find the corresponding area on the qcow2 image, allocating new + * clusters (or subclusters) if necessary. The result can span a + * combination of allocated and previously unallocated clusters. * - * For a given offset on the virtual disk, find the cluster offset in qcow2 - * file. If the offset is not found, allocate a new cluster. + * Note that offset may not be cluster aligned. In this case, the returned + * *host_offset points to exact byte referenced by offset and therefore + * isn't cluster aligned as well. * - * If the cluster was already allocated, m->nb_clusters is set to 0 and - * other fields in m are meaningless. + * On return, @host_offset is set to the beginning of the requested + * area. This area is guaranteed to be contiguous on the qcow2 file + * but it can be smaller than initially requested. In this case @bytes + * is updated with the actual size. * - * If the cluster is newly allocated, m->nb_clusters is set to the number of - * contiguous clusters that have been allocated. In this case, the other - * fields of m are valid and contain information about the first allocated - * cluster. + * If any clusters or subclusters were allocated then @m contains a + * list with the information of all the affected regions. Note that + * this can happen regardless of whether this function succeeds or + * not. The caller is responsible for updating the L2 metadata of the + * allocated clusters (on success) or freeing them (on failure), and + * for clearing the contents of @m afterwards in both cases. * * If the request conflicts with another write request in flight, the coroutine * is queued and will be reentered when the dependency has completed. * * Return 0 on success and -errno in error cases */ -int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, - unsigned int *bytes, uint64_t *host_offset, - QCowL2Meta **m) +int qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset, + unsigned int *bytes, uint64_t *host_offset, + QCowL2Meta **m) { BDRVQcow2State *s = bs->opaque; uint64_t start, remaining; @@ -1511,7 +1764,7 @@ again: while (true) { if (*host_offset == INV_OFFSET && cluster_offset != INV_OFFSET) { - *host_offset = start_of_cluster(s, cluster_offset); + *host_offset = cluster_offset; } assert(remaining >= cur_bytes); @@ -1594,6 +1847,8 @@ again: *bytes -= remaining; assert(*bytes > 0); assert(*host_offset != INV_OFFSET); + assert(offset_into_cluster(s, *host_offset) == + offset_into_cluster(s, offset)); return 0; } @@ -1623,11 +1878,17 @@ static int discard_in_l2_slice(BlockDriverState *bs, uint64_t offset, assert(nb_clusters <= INT_MAX); for (i = 0; i < nb_clusters; i++) { - uint64_t old_l2_entry; - - old_l2_entry = be64_to_cpu(l2_slice[l2_index + i]); + uint64_t old_l2_entry = get_l2_entry(s, l2_slice, l2_index + i); + uint64_t old_l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + i); + uint64_t new_l2_entry = old_l2_entry; + uint64_t new_l2_bitmap = old_l2_bitmap; + QCow2ClusterType cluster_type = + qcow2_get_cluster_type(bs, old_l2_entry); /* + * If full_discard is true, the cluster should not read back as zeroes, + * but rather fall through to the backing file. + * * If full_discard is false, make sure that a discarded area reads back * as zeroes for v3 images (we cannot do it for v2 without actually * writing a zero-filled buffer). We can skip the operation if the @@ -1636,42 +1897,30 @@ static int discard_in_l2_slice(BlockDriverState *bs, uint64_t offset, * * TODO We might want to use bdrv_block_status(bs) here, but we're * holding s->lock, so that doesn't work today. - * - * If full_discard is true, the sector should not read back as zeroes, - * but rather fall through to the backing file. */ - switch (qcow2_get_cluster_type(bs, old_l2_entry)) { - case QCOW2_CLUSTER_UNALLOCATED: - if (full_discard || !bs->backing) { - continue; - } - break; - - case QCOW2_CLUSTER_ZERO_PLAIN: - if (!full_discard) { - continue; + if (full_discard) { + new_l2_entry = new_l2_bitmap = 0; + } else if (bs->backing || qcow2_cluster_is_allocated(cluster_type)) { + if (has_subclusters(s)) { + new_l2_entry = 0; + new_l2_bitmap = QCOW_L2_BITMAP_ALL_ZEROES; + } else { + new_l2_entry = s->qcow_version >= 3 ? QCOW_OFLAG_ZERO : 0; } - break; - - case QCOW2_CLUSTER_ZERO_ALLOC: - case QCOW2_CLUSTER_NORMAL: - case QCOW2_CLUSTER_COMPRESSED: - break; + } - default: - abort(); + if (old_l2_entry == new_l2_entry && old_l2_bitmap == new_l2_bitmap) { + continue; } /* First remove L2 entries */ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice); - if (!full_discard && s->qcow_version >= 3) { - l2_slice[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO); - } else { - l2_slice[l2_index + i] = cpu_to_be64(0); + set_l2_entry(s, l2_slice, l2_index + i, new_l2_entry); + if (has_subclusters(s)) { + set_l2_bitmap(s, l2_slice, l2_index + i, new_l2_bitmap); } - /* Then decrease the refcount */ - qcow2_free_any_clusters(bs, old_l2_entry, 1, type); + qcow2_free_any_cluster(bs, old_l2_entry, type); } qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice); @@ -1732,7 +1981,6 @@ static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset, int l2_index; int ret; int i; - bool unmap = !!(flags & BDRV_REQ_MAY_UNMAP); ret = get_cluster_table(bs, offset, &l2_slice, &l2_index); if (ret < 0) { @@ -1744,27 +1992,34 @@ static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset, assert(nb_clusters <= INT_MAX); for (i = 0; i < nb_clusters; i++) { - uint64_t old_offset; - QCow2ClusterType cluster_type; - - old_offset = be64_to_cpu(l2_slice[l2_index + i]); + uint64_t old_l2_entry = get_l2_entry(s, l2_slice, l2_index + i); + uint64_t old_l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + i); + QCow2ClusterType type = qcow2_get_cluster_type(bs, old_l2_entry); + bool unmap = (type == QCOW2_CLUSTER_COMPRESSED) || + ((flags & BDRV_REQ_MAY_UNMAP) && qcow2_cluster_is_allocated(type)); + uint64_t new_l2_entry = unmap ? 0 : old_l2_entry; + uint64_t new_l2_bitmap = old_l2_bitmap; + + if (has_subclusters(s)) { + new_l2_bitmap = QCOW_L2_BITMAP_ALL_ZEROES; + } else { + new_l2_entry |= QCOW_OFLAG_ZERO; + } - /* - * Minimize L2 changes if the cluster already reads back as - * zeroes with correct allocation. - */ - cluster_type = qcow2_get_cluster_type(bs, old_offset); - if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN || - (cluster_type == QCOW2_CLUSTER_ZERO_ALLOC && !unmap)) { + if (old_l2_entry == new_l2_entry && old_l2_bitmap == new_l2_bitmap) { continue; } + /* First update L2 entries */ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice); - if (cluster_type == QCOW2_CLUSTER_COMPRESSED || unmap) { - l2_slice[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO); - qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST); - } else { - l2_slice[l2_index + i] |= cpu_to_be64(QCOW_OFLAG_ZERO); + set_l2_entry(s, l2_slice, l2_index + i, new_l2_entry); + if (has_subclusters(s)) { + set_l2_bitmap(s, l2_slice, l2_index + i, new_l2_bitmap); + } + + /* Then decrease the refcount */ + if (unmap) { + qcow2_free_any_cluster(bs, old_l2_entry, QCOW2_DISCARD_REQUEST); } } @@ -1773,12 +2028,59 @@ static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset, return nb_clusters; } -int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset, - uint64_t bytes, int flags) +static int zero_l2_subclusters(BlockDriverState *bs, uint64_t offset, + unsigned nb_subclusters) +{ + BDRVQcow2State *s = bs->opaque; + uint64_t *l2_slice; + uint64_t old_l2_bitmap, l2_bitmap; + int l2_index, ret, sc = offset_to_sc_index(s, offset); + + /* For full clusters use zero_in_l2_slice() instead */ + assert(nb_subclusters > 0 && nb_subclusters < s->subclusters_per_cluster); + assert(sc + nb_subclusters <= s->subclusters_per_cluster); + assert(offset_into_subcluster(s, offset) == 0); + + ret = get_cluster_table(bs, offset, &l2_slice, &l2_index); + if (ret < 0) { + return ret; + } + + switch (qcow2_get_cluster_type(bs, get_l2_entry(s, l2_slice, l2_index))) { + case QCOW2_CLUSTER_COMPRESSED: + ret = -ENOTSUP; /* We cannot partially zeroize compressed clusters */ + goto out; + case QCOW2_CLUSTER_NORMAL: + case QCOW2_CLUSTER_UNALLOCATED: + break; + default: + g_assert_not_reached(); + } + + old_l2_bitmap = l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index); + + l2_bitmap |= QCOW_OFLAG_SUB_ZERO_RANGE(sc, sc + nb_subclusters); + l2_bitmap &= ~QCOW_OFLAG_SUB_ALLOC_RANGE(sc, sc + nb_subclusters); + + if (old_l2_bitmap != l2_bitmap) { + set_l2_bitmap(s, l2_slice, l2_index, l2_bitmap); + qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice); + } + + ret = 0; +out: + qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice); + + return ret; +} + +int qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, + uint64_t bytes, int flags) { BDRVQcow2State *s = bs->opaque; uint64_t end_offset = offset + bytes; uint64_t nb_clusters; + unsigned head, tail; int64_t cleared; int ret; @@ -1793,20 +2095,42 @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset, } /* Caller must pass aligned values, except at image end */ - assert(QEMU_IS_ALIGNED(offset, s->cluster_size)); - assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) || + assert(offset_into_subcluster(s, offset) == 0); + assert(offset_into_subcluster(s, end_offset) == 0 || end_offset >= bs->total_sectors << BDRV_SECTOR_BITS); - /* The zero flag is only supported by version 3 and newer */ + /* + * The zero flag is only supported by version 3 and newer. However, if we + * have no backing file, we can resort to discard in version 2. + */ if (s->qcow_version < 3) { + if (!bs->backing) { + return qcow2_cluster_discard(bs, offset, bytes, + QCOW2_DISCARD_REQUEST, false); + } return -ENOTSUP; } - /* Each L2 slice is handled by its own loop iteration */ - nb_clusters = size_to_clusters(s, bytes); + head = MIN(end_offset, ROUND_UP(offset, s->cluster_size)) - offset; + offset += head; + + tail = (end_offset >= bs->total_sectors << BDRV_SECTOR_BITS) ? 0 : + end_offset - MAX(offset, start_of_cluster(s, end_offset)); + end_offset -= tail; s->cache_discards = true; + if (head) { + ret = zero_l2_subclusters(bs, offset - head, + size_to_subclusters(s, head)); + if (ret < 0) { + goto fail; + } + } + + /* Each L2 slice is handled by its own loop iteration */ + nb_clusters = size_to_clusters(s, end_offset - offset); + while (nb_clusters > 0) { cleared = zero_in_l2_slice(bs, offset, nb_clusters, flags); if (cleared < 0) { @@ -1818,6 +2142,13 @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset, offset += (cleared * s->cluster_size); } + if (tail) { + ret = zero_l2_subclusters(bs, end_offset, size_to_subclusters(s, tail)); + if (ret < 0) { + goto fail; + } + } + ret = 0; fail: s->cache_discards = false; @@ -1847,7 +2178,10 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, int ret; int i, j; - slice_size2 = s->l2_slice_size * sizeof(uint64_t); + /* qcow2_downgrade() is not allowed in images with subclusters */ + assert(!has_subclusters(s)); + + slice_size2 = s->l2_slice_size * l2_entry_size(s); n_slices = s->cluster_size / slice_size2; if (!is_active_l1) { @@ -1902,7 +2236,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, } for (j = 0; j < s->l2_slice_size; j++) { - uint64_t l2_entry = be64_to_cpu(l2_slice[j]); + uint64_t l2_entry = get_l2_entry(s, l2_slice, j); int64_t offset = l2_entry & L2E_OFFSET_MASK; QCow2ClusterType cluster_type = qcow2_get_cluster_type(bs, l2_entry); @@ -1914,9 +2248,12 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN) { if (!bs->backing) { - /* not backed; therefore we can simply deallocate the - * cluster */ - l2_slice[j] = 0; + /* + * not backed; therefore we can simply deallocate the + * cluster. No need to call set_l2_bitmap(), this + * function doesn't support images with subclusters. + */ + set_l2_entry(s, l2_slice, j, 0); l2_dirty = true; continue; } @@ -1982,10 +2319,14 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, } if (l2_refcount == 1) { - l2_slice[j] = cpu_to_be64(offset | QCOW_OFLAG_COPIED); + set_l2_entry(s, l2_slice, j, offset | QCOW_OFLAG_COPIED); } else { - l2_slice[j] = cpu_to_be64(offset); + set_l2_entry(s, l2_slice, j, offset); } + /* + * No need to call set_l2_bitmap() after set_l2_entry() because + * this function doesn't support images with subclusters. + */ l2_dirty = true; } @@ -2080,7 +2421,7 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs, Error *local_err = NULL; ret = qcow2_validate_table(bs, s->snapshots[i].l1_table_offset, - s->snapshots[i].l1_size, sizeof(uint64_t), + s->snapshots[i].l1_size, L1E_SIZE, QCOW_MAX_L1_SIZE, "Snapshot L1 table", &local_err); if (ret < 0) { @@ -2088,7 +2429,7 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs, goto fail; } - l1_size2 = s->snapshots[i].l1_size * sizeof(uint64_t); + l1_size2 = s->snapshots[i].l1_size * L1E_SIZE; new_l1_table = g_try_realloc(l1_table, l1_size2); if (!new_l1_table) { diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 0457a6060d111e82e14fa7d7dbc183a43763dda6..8e649b008e8cd6b5f36f35e156e8d4a63e0b09b6 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -105,8 +105,8 @@ int qcow2_refcount_init(BlockDriverState *bs) s->get_refcount = get_refcount_funcs[s->refcount_order]; s->set_refcount = set_refcount_funcs[s->refcount_order]; - assert(s->refcount_table_size <= INT_MAX / sizeof(uint64_t)); - refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t); + assert(s->refcount_table_size <= INT_MAX / REFTABLE_ENTRY_SIZE); + refcount_table_size2 = s->refcount_table_size * REFTABLE_ENTRY_SIZE; s->refcount_table = g_try_malloc(refcount_table_size2); if (s->refcount_table_size > 0) { @@ -434,8 +434,8 @@ static int alloc_refcount_block(BlockDriverState *bs, if (refcount_table_index < s->refcount_table_size) { uint64_t data64 = cpu_to_be64(new_block); BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_HOOKUP); - ret = bdrv_pwrite_sync(bs->file, - s->refcount_table_offset + refcount_table_index * sizeof(uint64_t), + ret = bdrv_pwrite_sync(bs->file, s->refcount_table_offset + + refcount_table_index * REFTABLE_ENTRY_SIZE, &data64, sizeof(data64)); if (ret < 0) { goto fail; @@ -562,8 +562,8 @@ int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t start_offset, DIV_ROUND_UP(total_refblock_count, 2); } /* The qcow2 file can only store the reftable size in number of clusters */ - table_size = ROUND_UP(table_size, s->cluster_size / sizeof(uint64_t)); - table_clusters = (table_size * sizeof(uint64_t)) / s->cluster_size; + table_size = ROUND_UP(table_size, s->cluster_size / REFTABLE_ENTRY_SIZE); + table_clusters = (table_size * REFTABLE_ENTRY_SIZE) / s->cluster_size; if (table_size > QCOW_MAX_REFTABLE_SIZE) { return -EFBIG; @@ -581,13 +581,13 @@ int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t start_offset, if (table_size > s->max_refcount_table_index) { /* We're actually growing the reftable */ memcpy(new_table, s->refcount_table, - (s->max_refcount_table_index + 1) * sizeof(uint64_t)); + (s->max_refcount_table_index + 1) * REFTABLE_ENTRY_SIZE); } else { /* Improbable case: We're shrinking the reftable. However, the caller * has assured us that there is only empty space beyond @start_offset, * so we can simply drop all of the refblocks that won't fit into the * new reftable. */ - memcpy(new_table, s->refcount_table, table_size * sizeof(uint64_t)); + memcpy(new_table, s->refcount_table, table_size * REFTABLE_ENTRY_SIZE); } if (new_refblock_offset) { @@ -682,7 +682,7 @@ int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t start_offset, BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE); ret = bdrv_pwrite_sync(bs->file, table_offset, new_table, - table_size * sizeof(uint64_t)); + table_size * REFTABLE_ENTRY_SIZE); if (ret < 0) { goto fail; } @@ -717,7 +717,8 @@ int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t start_offset, update_max_refcount_table_index(s); /* Free old table. */ - qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t), + qcow2_free_clusters(bs, old_table_offset, + old_table_size * REFTABLE_ENTRY_SIZE, QCOW2_DISCARD_OTHER); return end_offset; @@ -1156,8 +1157,8 @@ void qcow2_free_clusters(BlockDriverState *bs, * Free a cluster using its L2 entry (handles clusters of all types, e.g. * normal cluster, compressed cluster, etc.) */ -void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry, - int nb_clusters, enum qcow2_discard_type type) +void qcow2_free_any_cluster(BlockDriverState *bs, uint64_t l2_entry, + enum qcow2_discard_type type) { BDRVQcow2State *s = bs->opaque; QCow2ClusterType ctype = qcow2_get_cluster_type(bs, l2_entry); @@ -1168,7 +1169,7 @@ void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry, ctype == QCOW2_CLUSTER_ZERO_ALLOC)) { bdrv_pdiscard(s->data_file, l2_entry & L2E_OFFSET_MASK, - nb_clusters << s->cluster_bits); + s->cluster_size); } return; } @@ -1191,7 +1192,7 @@ void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry, l2_entry & L2E_OFFSET_MASK); } else { qcow2_free_clusters(bs, l2_entry & L2E_OFFSET_MASK, - nb_clusters << s->cluster_bits, type); + s->cluster_size, type); } break; case QCOW2_CLUSTER_ZERO_PLAIN: @@ -1253,8 +1254,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, l2_slice = NULL; l1_table = NULL; - l1_size2 = l1_size * sizeof(uint64_t); - slice_size2 = s->l2_slice_size * sizeof(uint64_t); + l1_size2 = l1_size * L1E_SIZE; + slice_size2 = s->l2_slice_size * l2_entry_size(s); n_slices = s->cluster_size / slice_size2; s->cache_discards = true; @@ -1310,7 +1311,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, uint64_t cluster_index; uint64_t offset; - entry = be64_to_cpu(l2_slice[j]); + entry = get_l2_entry(s, l2_slice, j); old_entry = entry; entry &= ~QCOW_OFLAG_COPIED; offset = entry & L2E_OFFSET_MASK; @@ -1384,7 +1385,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, qcow2_cache_set_dependency(bs, s->l2_table_cache, s->refcount_block_cache); } - l2_slice[j] = cpu_to_be64(entry); + set_l2_entry(s, l2_slice, j, entry); qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice); } @@ -1605,7 +1606,7 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, int i, l2_size, nb_csectors, ret; /* Read L2 table from disk */ - l2_size = s->l2_size * sizeof(uint64_t); + l2_size = s->l2_size * l2_entry_size(s); l2_table = g_malloc(l2_size); ret = bdrv_pread(bs->file, l2_offset, l2_table, l2_size); @@ -1617,7 +1618,7 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, /* Do the actual checks */ for(i = 0; i < s->l2_size; i++) { - l2_entry = be64_to_cpu(l2_table[i]); + l2_entry = get_l2_entry(s, l2_table, i); switch (qcow2_get_cluster_type(bs, l2_entry)) { case QCOW2_CLUSTER_COMPRESSED: @@ -1669,26 +1670,33 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, /* Correct offsets are cluster aligned */ if (offset_into_cluster(s, offset)) { + bool contains_data; res->corruptions++; - if (qcow2_get_cluster_type(bs, l2_entry) == - QCOW2_CLUSTER_ZERO_ALLOC) - { - fprintf(stderr, "%s offset=%" PRIx64 ": Preallocated zero " + if (has_subclusters(s)) { + uint64_t l2_bitmap = get_l2_bitmap(s, l2_table, i); + contains_data = (l2_bitmap & QCOW_L2_BITMAP_ALL_ALLOC); + } else { + contains_data = !(l2_entry & QCOW_OFLAG_ZERO); + } + + if (!contains_data) { + fprintf(stderr, "%s offset=%" PRIx64 ": Preallocated " "cluster is not properly aligned; L2 entry " "corrupted.\n", fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR", offset); if (fix & BDRV_FIX_ERRORS) { + int idx = i * (l2_entry_size(s) / sizeof(uint64_t)); uint64_t l2e_offset = - l2_offset + (uint64_t)i * sizeof(uint64_t); + l2_offset + (uint64_t)i * l2_entry_size(s); int ign = active ? QCOW2_OL_ACTIVE_L2 : QCOW2_OL_INACTIVE_L2; - l2_entry = QCOW_OFLAG_ZERO; - l2_table[i] = cpu_to_be64(l2_entry); + l2_entry = has_subclusters(s) ? 0 : QCOW_OFLAG_ZERO; + set_l2_entry(s, l2_table, i, l2_entry); ret = qcow2_pre_write_overlap_check(bs, ign, - l2e_offset, sizeof(uint64_t), false); + l2e_offset, l2_entry_size(s), false); if (ret < 0) { fprintf(stderr, "ERROR: Overlap check failed\n"); res->check_errors++; @@ -1698,7 +1706,8 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, } ret = bdrv_pwrite_sync(bs->file, l2e_offset, - &l2_table[i], sizeof(uint64_t)); + &l2_table[idx], + l2_entry_size(s)); if (ret < 0) { fprintf(stderr, "ERROR: Failed to overwrite L2 " "table entry: %s\n", strerror(-ret)); @@ -1776,7 +1785,7 @@ static int check_refcounts_l1(BlockDriverState *bs, uint64_t *l1_table = NULL, l2_offset, l1_size2; int i, ret; - l1_size2 = l1_size * sizeof(uint64_t); + l1_size2 = l1_size * L1E_SIZE; /* Mark L1 table as used */ ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, refcount_table_size, @@ -1905,7 +1914,7 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res, } ret = bdrv_pread(bs->file, l2_offset, l2_table, - s->l2_size * sizeof(uint64_t)); + s->l2_size * l2_entry_size(s)); if (ret < 0) { fprintf(stderr, "ERROR: Could not read L2 table: %s\n", strerror(-ret)); @@ -1914,7 +1923,7 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res, } for (j = 0; j < s->l2_size; j++) { - uint64_t l2_entry = be64_to_cpu(l2_table[j]); + uint64_t l2_entry = get_l2_entry(s, l2_table, j); uint64_t data_offset = l2_entry & L2E_OFFSET_MASK; QCow2ClusterType cluster_type = qcow2_get_cluster_type(bs, l2_entry); @@ -1937,9 +1946,10 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res, "l2_entry=%" PRIx64 " refcount=%" PRIu64 "\n", repair ? "Repairing" : "ERROR", l2_entry, refcount); if (repair) { - l2_table[j] = cpu_to_be64(refcount == 1 - ? l2_entry | QCOW_OFLAG_COPIED - : l2_entry & ~QCOW_OFLAG_COPIED); + set_l2_entry(s, l2_table, j, + refcount == 1 ? + l2_entry | QCOW_OFLAG_COPIED : + l2_entry & ~QCOW_OFLAG_COPIED); l2_dirty++; } } @@ -2137,7 +2147,7 @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, res->corruptions++; continue; } - if (sn->l1_size > QCOW_MAX_L1_SIZE / sizeof(uint64_t)) { + if (sn->l1_size > QCOW_MAX_L1_SIZE / L1E_SIZE) { fprintf(stderr, "ERROR snapshot %s (%s) l1_size=%#" PRIx32 ": " "L1 table is too large; snapshot table entry corrupted\n", sn->id_str, sn->name, sn->l1_size); @@ -2160,7 +2170,8 @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, /* refcount data */ ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, nb_clusters, s->refcount_table_offset, - s->refcount_table_size * sizeof(uint64_t)); + s->refcount_table_size * + REFTABLE_ENTRY_SIZE); if (ret < 0) { return ret; } @@ -2381,11 +2392,11 @@ write_refblocks: uint32_t old_reftable_size = reftable_size; uint64_t *new_on_disk_reftable; - reftable_size = ROUND_UP((refblock_index + 1) * sizeof(uint64_t), - s->cluster_size) / sizeof(uint64_t); + reftable_size = ROUND_UP((refblock_index + 1) * REFTABLE_ENTRY_SIZE, + s->cluster_size) / REFTABLE_ENTRY_SIZE; new_on_disk_reftable = g_try_realloc(on_disk_reftable, reftable_size * - sizeof(uint64_t)); + REFTABLE_ENTRY_SIZE); if (!new_on_disk_reftable) { res->check_errors++; ret = -ENOMEM; @@ -2394,7 +2405,7 @@ write_refblocks: on_disk_reftable = new_on_disk_reftable; memset(on_disk_reftable + old_reftable_size, 0, - (reftable_size - old_reftable_size) * sizeof(uint64_t)); + (reftable_size - old_reftable_size) * REFTABLE_ENTRY_SIZE); /* The offset we have for the reftable is now no longer valid; * this will leak that range, but we can easily fix that by running @@ -2411,7 +2422,7 @@ write_refblocks: reftable_offset < 0) { uint64_t reftable_clusters = size_to_clusters(s, reftable_size * - sizeof(uint64_t)); + REFTABLE_ENTRY_SIZE); reftable_offset = alloc_clusters_imrt(bs, reftable_clusters, refcount_table, nb_clusters, &first_free_cluster); @@ -2451,8 +2462,8 @@ write_refblocks: uint64_t post_refblock_start, reftable_clusters; post_refblock_start = ROUND_UP(*nb_clusters, s->refcount_block_size); - reftable_clusters = size_to_clusters(s, - reftable_size * sizeof(uint64_t)); + reftable_clusters = + size_to_clusters(s, reftable_size * REFTABLE_ENTRY_SIZE); /* Not pretty but simple */ if (first_free_cluster < post_refblock_start) { first_free_cluster = post_refblock_start; @@ -2476,16 +2487,16 @@ write_refblocks: } ret = qcow2_pre_write_overlap_check(bs, 0, reftable_offset, - reftable_size * sizeof(uint64_t), + reftable_size * REFTABLE_ENTRY_SIZE, false); if (ret < 0) { fprintf(stderr, "ERROR writing reftable: %s\n", strerror(-ret)); goto fail; } - assert(reftable_size < INT_MAX / sizeof(uint64_t)); + assert(reftable_size < INT_MAX / REFTABLE_ENTRY_SIZE); ret = bdrv_pwrite(bs->file, reftable_offset, on_disk_reftable, - reftable_size * sizeof(uint64_t)); + reftable_size * REFTABLE_ENTRY_SIZE); if (ret < 0) { fprintf(stderr, "ERROR writing reftable: %s\n", strerror(-ret)); goto fail; @@ -2494,7 +2505,7 @@ write_refblocks: /* Enter new reftable into the image header */ reftable_offset_and_clusters.reftable_offset = cpu_to_be64(reftable_offset); reftable_offset_and_clusters.reftable_clusters = - cpu_to_be32(size_to_clusters(s, reftable_size * sizeof(uint64_t))); + cpu_to_be32(size_to_clusters(s, reftable_size * REFTABLE_ENTRY_SIZE)); ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, refcount_table_offset), &reftable_offset_and_clusters, @@ -2684,14 +2695,14 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset, offset = start_of_cluster(s, offset); if ((chk & QCOW2_OL_ACTIVE_L1) && s->l1_size) { - if (overlaps_with(s->l1_table_offset, s->l1_size * sizeof(uint64_t))) { + if (overlaps_with(s->l1_table_offset, s->l1_size * L1E_SIZE)) { return QCOW2_OL_ACTIVE_L1; } } if ((chk & QCOW2_OL_REFCOUNT_TABLE) && s->refcount_table_size) { if (overlaps_with(s->refcount_table_offset, - s->refcount_table_size * sizeof(uint64_t))) { + s->refcount_table_size * REFTABLE_ENTRY_SIZE)) { return QCOW2_OL_REFCOUNT_TABLE; } } @@ -2706,7 +2717,7 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset, for (i = 0; i < s->nb_snapshots; i++) { if (s->snapshots[i].l1_size && overlaps_with(s->snapshots[i].l1_table_offset, - s->snapshots[i].l1_size * sizeof(uint64_t))) { + s->snapshots[i].l1_size * L1E_SIZE)) { return QCOW2_OL_INACTIVE_L1; } } @@ -2740,11 +2751,11 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset, for (i = 0; i < s->nb_snapshots; i++) { uint64_t l1_ofs = s->snapshots[i].l1_table_offset; uint32_t l1_sz = s->snapshots[i].l1_size; - uint64_t l1_sz2 = l1_sz * sizeof(uint64_t); + uint64_t l1_sz2 = l1_sz * L1E_SIZE; uint64_t *l1; int ret; - ret = qcow2_validate_table(bs, l1_ofs, l1_sz, sizeof(uint64_t), + ret = qcow2_validate_table(bs, l1_ofs, l1_sz, L1E_SIZE, QCOW_MAX_L1_SIZE, "", NULL); if (ret < 0) { return ret; @@ -2868,8 +2879,8 @@ static int alloc_refblock(BlockDriverState *bs, uint64_t **reftable, uint64_t new_reftable_size; new_reftable_size = ROUND_UP(reftable_index + 1, - s->cluster_size / sizeof(uint64_t)); - if (new_reftable_size > QCOW_MAX_REFTABLE_SIZE / sizeof(uint64_t)) { + s->cluster_size / REFTABLE_ENTRY_SIZE); + if (new_reftable_size > QCOW_MAX_REFTABLE_SIZE / REFTABLE_ENTRY_SIZE) { error_setg(errp, "This operation would make the refcount table grow " "beyond the maximum size supported by QEMU, aborting"); @@ -2877,14 +2888,14 @@ static int alloc_refblock(BlockDriverState *bs, uint64_t **reftable, } new_reftable = g_try_realloc(*reftable, new_reftable_size * - sizeof(uint64_t)); + REFTABLE_ENTRY_SIZE); if (!new_reftable) { error_setg(errp, "Failed to increase reftable buffer size"); return -ENOMEM; } memset(new_reftable + *reftable_size, 0, - (new_reftable_size - *reftable_size) * sizeof(uint64_t)); + (new_reftable_size - *reftable_size) * REFTABLE_ENTRY_SIZE); *reftable = new_reftable; *reftable_size = new_reftable_size; @@ -3155,13 +3166,14 @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order, if (new_allocation) { if (new_reftable_offset) { - qcow2_free_clusters(bs, new_reftable_offset, - allocated_reftable_size * sizeof(uint64_t), - QCOW2_DISCARD_NEVER); + qcow2_free_clusters( + bs, new_reftable_offset, + allocated_reftable_size * REFTABLE_ENTRY_SIZE, + QCOW2_DISCARD_NEVER); } new_reftable_offset = qcow2_alloc_clusters(bs, new_reftable_size * - sizeof(uint64_t)); + REFTABLE_ENTRY_SIZE); if (new_reftable_offset < 0) { error_setg_errno(errp, -new_reftable_offset, "Failed to allocate the new reftable"); @@ -3187,7 +3199,7 @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order, /* Write the new reftable */ ret = qcow2_pre_write_overlap_check(bs, 0, new_reftable_offset, - new_reftable_size * sizeof(uint64_t), + new_reftable_size * REFTABLE_ENTRY_SIZE, false); if (ret < 0) { error_setg_errno(errp, -ret, "Overlap check failed"); @@ -3199,7 +3211,7 @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order, } ret = bdrv_pwrite(bs->file, new_reftable_offset, new_reftable, - new_reftable_size * sizeof(uint64_t)); + new_reftable_size * REFTABLE_ENTRY_SIZE); for (i = 0; i < new_reftable_size; i++) { be64_to_cpus(&new_reftable[i]); @@ -3276,7 +3288,7 @@ done: if (new_reftable_offset > 0) { qcow2_free_clusters(bs, new_reftable_offset, - new_reftable_size * sizeof(uint64_t), + new_reftable_size * REFTABLE_ENTRY_SIZE, QCOW2_DISCARD_OTHER); } } @@ -3365,7 +3377,7 @@ int qcow2_shrink_reftable(BlockDriverState *bs) { BDRVQcow2State *s = bs->opaque; uint64_t *reftable_tmp = - g_malloc(s->refcount_table_size * sizeof(uint64_t)); + g_malloc(s->refcount_table_size * REFTABLE_ENTRY_SIZE); int i, ret; for (i = 0; i < s->refcount_table_size; i++) { @@ -3403,7 +3415,7 @@ int qcow2_shrink_reftable(BlockDriverState *bs) } ret = bdrv_pwrite_sync(bs->file, s->refcount_table_offset, reftable_tmp, - s->refcount_table_size * sizeof(uint64_t)); + s->refcount_table_size * REFTABLE_ENTRY_SIZE); /* * If the write in the reftable failed the image may contain a partially * overwritten reftable. In this case it would be better to clear the diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index 2756b37d24275bfb0235f5885537d7688f4a398f..2e98c7f4b620ffadc10f6f181c75c45e1f3f86b2 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -164,6 +164,12 @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair, sn->disk_size = bs->total_sectors * BDRV_SECTOR_SIZE; } + if (sn->extra_data_size >= endof(QCowSnapshotExtraData, icount)) { + sn->icount = be64_to_cpu(extra.icount); + } else { + sn->icount = -1ULL; + } + if (sn->extra_data_size > sizeof(extra)) { uint64_t extra_data_end; size_t unknown_extra_data_size; @@ -333,6 +339,7 @@ int qcow2_write_snapshots(BlockDriverState *bs) memset(&extra, 0, sizeof(extra)); extra.vm_state_size_large = cpu_to_be64(sn->vm_state_size); extra.disk_size = cpu_to_be64(sn->disk_size); + extra.icount = cpu_to_be64(sn->icount); id_str_size = strlen(sn->id_str); name_size = strlen(sn->name); @@ -656,10 +663,11 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) sn->date_sec = sn_info->date_sec; sn->date_nsec = sn_info->date_nsec; sn->vm_clock_nsec = sn_info->vm_clock_nsec; + sn->icount = sn_info->icount; sn->extra_data_size = sizeof(QCowSnapshotExtraData); /* Allocate the L1 table of the snapshot and copy the current one there. */ - l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * sizeof(uint64_t)); + l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * L1E_SIZE); if (l1_table_offset < 0) { ret = l1_table_offset; goto fail; @@ -679,13 +687,13 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) } ret = qcow2_pre_write_overlap_check(bs, 0, sn->l1_table_offset, - s->l1_size * sizeof(uint64_t), false); + s->l1_size * L1E_SIZE, false); if (ret < 0) { goto fail; } ret = bdrv_pwrite(bs->file, sn->l1_table_offset, l1_table, - s->l1_size * sizeof(uint64_t)); + s->l1_size * L1E_SIZE); if (ret < 0) { goto fail; } @@ -768,7 +776,7 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) sn = &s->snapshots[snapshot_index]; ret = qcow2_validate_table(bs, sn->l1_table_offset, sn->l1_size, - sizeof(uint64_t), QCOW_MAX_L1_SIZE, + L1E_SIZE, QCOW_MAX_L1_SIZE, "Snapshot L1 table", &local_err); if (ret < 0) { error_report_err(local_err); @@ -803,8 +811,8 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) goto fail; } - cur_l1_bytes = s->l1_size * sizeof(uint64_t); - sn_l1_bytes = sn->l1_size * sizeof(uint64_t); + cur_l1_bytes = s->l1_size * L1E_SIZE; + sn_l1_bytes = sn->l1_size * L1E_SIZE; /* * Copy the snapshot L1 table to the current L1 table. @@ -917,7 +925,7 @@ int qcow2_snapshot_delete(BlockDriverState *bs, sn = s->snapshots[snapshot_index]; ret = qcow2_validate_table(bs, sn.l1_table_offset, sn.l1_size, - sizeof(uint64_t), QCOW_MAX_L1_SIZE, + L1E_SIZE, QCOW_MAX_L1_SIZE, "Snapshot L1 table", errp); if (ret < 0) { return ret; @@ -953,7 +961,7 @@ int qcow2_snapshot_delete(BlockDriverState *bs, error_setg_errno(errp, -ret, "Failed to free the cluster and L1 table"); return ret; } - qcow2_free_clusters(bs, sn.l1_table_offset, sn.l1_size * sizeof(uint64_t), + qcow2_free_clusters(bs, sn.l1_table_offset, sn.l1_size * L1E_SIZE, QCOW2_DISCARD_SNAPSHOT); /* must update the copied flag on the current cluster offsets */ @@ -1000,6 +1008,7 @@ int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) sn_info->date_sec = sn->date_sec; sn_info->date_nsec = sn->date_nsec; sn_info->vm_clock_nsec = sn->vm_clock_nsec; + sn_info->icount = sn->icount; } *psn_tab = sn_tab; return s->nb_snapshots; @@ -1030,12 +1039,12 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs, /* Allocate and read in the snapshot's L1 table */ ret = qcow2_validate_table(bs, sn->l1_table_offset, sn->l1_size, - sizeof(uint64_t), QCOW_MAX_L1_SIZE, + L1E_SIZE, QCOW_MAX_L1_SIZE, "Snapshot L1 table", errp); if (ret < 0) { return ret; } - new_l1_bytes = sn->l1_size * sizeof(uint64_t); + new_l1_bytes = sn->l1_size * L1E_SIZE; new_l1_table = qemu_try_blockalign(bs->file->bs, new_l1_bytes); if (new_l1_table == NULL) { return -ENOMEM; diff --git a/block/qcow2.c b/block/qcow2.c index dfab8d2f6cd85c3f4d363404b246fab4d608ed43..3a90ef27868ad7e4bd9eb2e7fa0ff363c23db8f1 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -66,7 +66,7 @@ typedef struct { } QEMU_PACKED QCowExtension; #define QCOW2_EXT_MAGIC_END 0 -#define QCOW2_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA +#define QCOW2_EXT_MAGIC_BACKING_FORMAT 0xe2792aca #define QCOW2_EXT_MAGIC_FEATURE_TABLE 0x6803f857 #define QCOW2_EXT_MAGIC_CRYPTO_HEADER 0x0537be77 #define QCOW2_EXT_MAGIC_BITMAPS 0x23852875 @@ -74,7 +74,7 @@ typedef struct { static int coroutine_fn qcow2_co_preadv_compressed(BlockDriverState *bs, - uint64_t file_cluster_offset, + uint64_t cluster_descriptor, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, @@ -176,6 +176,19 @@ static ssize_t qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset, return ret; } +static QDict* +qcow2_extract_crypto_opts(QemuOpts *opts, const char *fmt, Error **errp) +{ + QDict *cryptoopts_qdict; + QDict *opts_qdict; + + /* Extract "encrypt." options into a qdict */ + opts_qdict = qemu_opts_to_qdict(opts, NULL); + qdict_extract_subqdict(opts_qdict, &cryptoopts_qdict, "encrypt."); + qobject_unref(opts_qdict); + qdict_put_str(cryptoopts_qdict, "format", fmt); + return cryptoopts_qdict; +} /* * read qcow2 extension and fill bs @@ -256,7 +269,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, case QCOW2_EXT_MAGIC_FEATURE_TABLE: if (p_feature_table != NULL) { - void* feature_table = g_malloc0(ext.len + 2 * sizeof(Qcow2Feature)); + void *feature_table = g_malloc0(ext.len + 2 * sizeof(Qcow2Feature)); ret = bdrv_pread(bs->file, offset , feature_table, ext.len); if (ret < 0) { error_setg_errno(errp, -ret, "ERROR: ext_feature_table: " @@ -870,7 +883,7 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts, uint64_t max_l2_entries = DIV_ROUND_UP(virtual_disk_size, s->cluster_size); /* An L2 table is always one cluster in size so the max cache size * should be a multiple of the cluster size. */ - uint64_t max_l2_cache = ROUND_UP(max_l2_entries * sizeof(uint64_t), + uint64_t max_l2_cache = ROUND_UP(max_l2_entries * l2_entry_size(s), s->cluster_size); combined_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_CACHE_SIZE); @@ -977,9 +990,7 @@ static int qcow2_update_options_prepare(BlockDriverState *bs, encryptfmt = qdict_get_try_str(encryptopts, "format"); opts = qemu_opts_create(&qcow2_runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { ret = -EINVAL; goto fail; } @@ -1031,7 +1042,7 @@ static int qcow2_update_options_prepare(BlockDriverState *bs, } } - r->l2_slice_size = l2_cache_entry_size / sizeof(uint64_t); + r->l2_slice_size = l2_cache_entry_size / l2_entry_size(s); r->l2_table_cache = qcow2_cache_create(bs, l2_cache_size, l2_cache_entry_size); r->refcount_block_cache = qcow2_cache_create(bs, refcount_cache_size, @@ -1433,6 +1444,17 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, } } + s->subclusters_per_cluster = + has_subclusters(s) ? QCOW_EXTL2_SUBCLUSTERS_PER_CLUSTER : 1; + s->subcluster_size = s->cluster_size / s->subclusters_per_cluster; + s->subcluster_bits = ctz32(s->subcluster_size); + + if (s->subcluster_size < (1 << MIN_CLUSTER_BITS)) { + error_setg(errp, "Unsupported subcluster size: %d", s->subcluster_size); + ret = -EINVAL; + goto fail; + } + /* Check support for various header values */ if (header.refcount_order > 6) { error_setg(errp, "Reference count entry width too large; may not " @@ -1473,7 +1495,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, bs->encrypted = true; } - s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */ + s->l2_bits = s->cluster_bits - ctz32(l2_entry_size(s)); s->l2_size = 1 << s->l2_bits; /* 2^(s->refcount_order - 3) is the refcount width in bytes */ s->refcount_block_bits = s->cluster_bits - (s->refcount_order - 3); @@ -1521,7 +1543,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, /* read the level 1 table */ ret = qcow2_validate_table(bs, header.l1_table_offset, - header.l1_size, sizeof(uint64_t), + header.l1_size, L1E_SIZE, QCOW_MAX_L1_SIZE, "Active L1 table", errp); if (ret < 0) { goto fail; @@ -1546,15 +1568,14 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, } if (s->l1_size > 0) { - s->l1_table = qemu_try_blockalign(bs->file->bs, - s->l1_size * sizeof(uint64_t)); + s->l1_table = qemu_try_blockalign(bs->file->bs, s->l1_size * L1E_SIZE); if (s->l1_table == NULL) { error_setg(errp, "Could not allocate L1 table"); ret = -ENOMEM; goto fail; } ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_table, - s->l1_size * sizeof(uint64_t)); + s->l1_size * L1E_SIZE); if (ret < 0) { error_setg_errno(errp, -ret, "Could not read L1 table"); goto fail; @@ -1583,8 +1604,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, /* read qcow2 extensions */ if (qcow2_read_extensions(bs, header.header_length, ext_end, NULL, - flags, &update_header, &local_err)) { - error_propagate(errp, local_err); + flags, &update_header, errp)) { ret = -EINVAL; goto fail; } @@ -1898,7 +1918,7 @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp) /* Encryption works on a sector granularity */ bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto); } - bs->bl.pwrite_zeroes_alignment = s->cluster_size; + bs->bl.pwrite_zeroes_alignment = s->subcluster_size; bs->bl.pdiscard_alignment = s->cluster_size; } @@ -2026,8 +2046,9 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs, BlockDriverState **file) { BDRVQcow2State *s = bs->opaque; - uint64_t cluster_offset; + uint64_t host_offset; unsigned int bytes; + QCow2SubclusterType type; int ret, status = 0; qemu_co_mutex_lock(&s->lock); @@ -2039,7 +2060,7 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs, } bytes = MIN(INT_MAX, count); - ret = qcow2_get_cluster_offset(bs, offset, &bytes, &cluster_offset); + ret = qcow2_get_host_offset(bs, offset, &bytes, &host_offset, &type); qemu_co_mutex_unlock(&s->lock); if (ret < 0) { return ret; @@ -2047,15 +2068,18 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs, *pnum = bytes; - if ((ret == QCOW2_CLUSTER_NORMAL || ret == QCOW2_CLUSTER_ZERO_ALLOC) && - !s->crypto) { - *map = cluster_offset | offset_into_cluster(s, offset); + if ((type == QCOW2_SUBCLUSTER_NORMAL || + type == QCOW2_SUBCLUSTER_ZERO_ALLOC || + type == QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC) && !s->crypto) { + *map = host_offset; *file = s->data_file->bs; status |= BDRV_BLOCK_OFFSET_VALID; } - if (ret == QCOW2_CLUSTER_ZERO_PLAIN || ret == QCOW2_CLUSTER_ZERO_ALLOC) { + if (type == QCOW2_SUBCLUSTER_ZERO_PLAIN || + type == QCOW2_SUBCLUSTER_ZERO_ALLOC) { status |= BDRV_BLOCK_ZERO; - } else if (ret != QCOW2_CLUSTER_UNALLOCATED) { + } else if (type != QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN && + type != QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC) { status |= BDRV_BLOCK_DATA; } if (s->metadata_preallocation && (status & BDRV_BLOCK_DATA) && @@ -2086,9 +2110,7 @@ static coroutine_fn int qcow2_handle_l2meta(BlockDriverState *bs, } /* Take the request off the list of running requests */ - if (l2meta->nb_clusters != 0) { - QLIST_REMOVE(l2meta, next_in_flight); - } + QLIST_REMOVE(l2meta, next_in_flight); qemu_co_queue_restart_all(&l2meta->dependent_requests); @@ -2103,7 +2125,7 @@ out: static coroutine_fn int qcow2_co_preadv_encrypted(BlockDriverState *bs, - uint64_t file_cluster_offset, + uint64_t host_offset, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, @@ -2130,16 +2152,12 @@ qcow2_co_preadv_encrypted(BlockDriverState *bs, } BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); - ret = bdrv_co_pread(s->data_file, - file_cluster_offset + offset_into_cluster(s, offset), - bytes, buf, 0); + ret = bdrv_co_pread(s->data_file, host_offset, bytes, buf, 0); if (ret < 0) { goto fail; } - if (qcow2_co_decrypt(bs, - file_cluster_offset + offset_into_cluster(s, offset), - offset, buf, bytes) < 0) + if (qcow2_co_decrypt(bs, host_offset, offset, buf, bytes) < 0) { ret = -EIO; goto fail; @@ -2156,8 +2174,8 @@ typedef struct Qcow2AioTask { AioTask task; BlockDriverState *bs; - QCow2ClusterType cluster_type; /* only for read */ - uint64_t file_cluster_offset; + QCow2SubclusterType subcluster_type; /* only for read */ + uint64_t host_offset; /* or full descriptor in compressed clusters */ uint64_t offset; uint64_t bytes; QEMUIOVector *qiov; @@ -2169,8 +2187,8 @@ static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task); static coroutine_fn int qcow2_add_task(BlockDriverState *bs, AioTaskPool *pool, AioTaskFunc func, - QCow2ClusterType cluster_type, - uint64_t file_cluster_offset, + QCow2SubclusterType subcluster_type, + uint64_t host_offset, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, @@ -2183,9 +2201,9 @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs, *task = (Qcow2AioTask) { .task.func = func, .bs = bs, - .cluster_type = cluster_type, + .subcluster_type = subcluster_type, .qiov = qiov, - .file_cluster_offset = file_cluster_offset, + .host_offset = host_offset, .offset = offset, .bytes = bytes, .qiov_offset = qiov_offset, @@ -2194,7 +2212,7 @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs, trace_qcow2_add_task(qemu_coroutine_self(), bs, pool, func == qcow2_co_preadv_task_entry ? "read" : "write", - cluster_type, file_cluster_offset, offset, bytes, + subcluster_type, host_offset, offset, bytes, qiov, qiov_offset); if (!pool) { @@ -2207,42 +2225,40 @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs, } static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs, - QCow2ClusterType cluster_type, - uint64_t file_cluster_offset, + QCow2SubclusterType subc_type, + uint64_t host_offset, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, size_t qiov_offset) { BDRVQcow2State *s = bs->opaque; - int offset_in_cluster = offset_into_cluster(s, offset); - switch (cluster_type) { - case QCOW2_CLUSTER_ZERO_PLAIN: - case QCOW2_CLUSTER_ZERO_ALLOC: + switch (subc_type) { + case QCOW2_SUBCLUSTER_ZERO_PLAIN: + case QCOW2_SUBCLUSTER_ZERO_ALLOC: /* Both zero types are handled in qcow2_co_preadv_part */ g_assert_not_reached(); - case QCOW2_CLUSTER_UNALLOCATED: + case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN: + case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC: assert(bs->backing); /* otherwise handled in qcow2_co_preadv_part */ BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO); return bdrv_co_preadv_part(bs->backing, offset, bytes, qiov, qiov_offset, 0); - case QCOW2_CLUSTER_COMPRESSED: - return qcow2_co_preadv_compressed(bs, file_cluster_offset, + case QCOW2_SUBCLUSTER_COMPRESSED: + return qcow2_co_preadv_compressed(bs, host_offset, offset, bytes, qiov, qiov_offset); - case QCOW2_CLUSTER_NORMAL: - assert(offset_into_cluster(s, file_cluster_offset) == 0); + case QCOW2_SUBCLUSTER_NORMAL: if (bs->encrypted) { - return qcow2_co_preadv_encrypted(bs, file_cluster_offset, + return qcow2_co_preadv_encrypted(bs, host_offset, offset, bytes, qiov, qiov_offset); } BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); - return bdrv_co_preadv_part(s->data_file, - file_cluster_offset + offset_in_cluster, + return bdrv_co_preadv_part(s->data_file, host_offset, bytes, qiov, qiov_offset, 0); default: @@ -2258,8 +2274,9 @@ static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task) assert(!t->l2meta); - return qcow2_co_preadv_task(t->bs, t->cluster_type, t->file_cluster_offset, - t->offset, t->bytes, t->qiov, t->qiov_offset); + return qcow2_co_preadv_task(t->bs, t->subcluster_type, + t->host_offset, t->offset, t->bytes, + t->qiov, t->qiov_offset); } static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs, @@ -2270,7 +2287,8 @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs, BDRVQcow2State *s = bs->opaque; int ret = 0; unsigned int cur_bytes; /* number of bytes in current iteration */ - uint64_t cluster_offset = 0; + uint64_t host_offset = 0; + QCow2SubclusterType type; AioTaskPool *aio = NULL; while (bytes != 0 && aio_task_pool_status(aio) == 0) { @@ -2282,23 +2300,25 @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs, } qemu_co_mutex_lock(&s->lock); - ret = qcow2_get_cluster_offset(bs, offset, &cur_bytes, &cluster_offset); + ret = qcow2_get_host_offset(bs, offset, &cur_bytes, + &host_offset, &type); qemu_co_mutex_unlock(&s->lock); if (ret < 0) { goto out; } - if (ret == QCOW2_CLUSTER_ZERO_PLAIN || - ret == QCOW2_CLUSTER_ZERO_ALLOC || - (ret == QCOW2_CLUSTER_UNALLOCATED && !bs->backing)) + if (type == QCOW2_SUBCLUSTER_ZERO_PLAIN || + type == QCOW2_SUBCLUSTER_ZERO_ALLOC || + (type == QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN && !bs->backing) || + (type == QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC && !bs->backing)) { qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes); } else { if (!aio && cur_bytes != bytes) { aio = aio_task_pool_new(QCOW2_MAX_WORKERS); } - ret = qcow2_add_task(bs, aio, qcow2_co_preadv_task_entry, ret, - cluster_offset, offset, cur_bytes, + ret = qcow2_add_task(bs, aio, qcow2_co_preadv_task_entry, type, + host_offset, offset, cur_bytes, qiov, qiov_offset, NULL); if (ret < 0) { goto out; @@ -2341,15 +2361,26 @@ static bool merge_cow(uint64_t offset, unsigned bytes, continue; } - /* The data (middle) region must be immediately after the - * start region */ + /* + * The write request should start immediately after the first + * COW region. This does not always happen because the area + * touched by the request can be larger than the one defined + * by @m (a single request can span an area consisting of a + * mix of previously unallocated and allocated clusters, that + * is why @l2meta is a list). + */ if (l2meta_cow_start(m) + m->cow_start.nb_bytes != offset) { + /* In this case the request starts before this region */ + assert(offset < l2meta_cow_start(m)); + assert(m->cow_start.nb_bytes == 0); continue; } - /* The end region must be immediately after the data (middle) - * region */ + /* The write request should end immediately before the second + * COW region (see above for why it does not always happen) */ if (m->offset + m->cow_end.offset != offset + bytes) { + assert(offset + bytes > m->offset + m->cow_end.offset); + assert(m->cow_end.nb_bytes == 0); continue; } @@ -2367,26 +2398,26 @@ static bool merge_cow(uint64_t offset, unsigned bytes, return false; } -static bool is_unallocated(BlockDriverState *bs, int64_t offset, int64_t bytes) -{ - int64_t nr; - return !bytes || - (!bdrv_is_allocated_above(bs, NULL, false, offset, bytes, &nr) && - nr == bytes); -} - -static bool is_zero_cow(BlockDriverState *bs, QCowL2Meta *m) +/* + * Return 1 if the COW regions read as zeroes, 0 if not, < 0 on error. + * Note that returning 0 does not guarantee non-zero data. + */ +static int is_zero_cow(BlockDriverState *bs, QCowL2Meta *m) { /* * This check is designed for optimization shortcut so it must be * efficient. - * Instead of is_zero(), use is_unallocated() as it is faster (but not - * as accurate and can result in false negatives). + * Instead of is_zero(), use bdrv_co_is_zero_fast() as it is + * faster (but not as accurate and can result in false negatives). */ - return is_unallocated(bs, m->offset + m->cow_start.offset, - m->cow_start.nb_bytes) && - is_unallocated(bs, m->offset + m->cow_end.offset, - m->cow_end.nb_bytes); + int ret = bdrv_co_is_zero_fast(bs, m->offset + m->cow_start.offset, + m->cow_start.nb_bytes); + if (ret <= 0) { + return ret; + } + + return bdrv_co_is_zero_fast(bs, m->offset + m->cow_end.offset, + m->cow_end.nb_bytes); } static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta) @@ -2404,12 +2435,18 @@ static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta) for (m = l2meta; m != NULL; m = m->next) { int ret; + uint64_t start_offset = m->alloc_offset + m->cow_start.offset; + unsigned nb_bytes = m->cow_end.offset + m->cow_end.nb_bytes - + m->cow_start.offset; if (!m->cow_start.nb_bytes && !m->cow_end.nb_bytes) { continue; } - if (!is_zero_cow(bs, m)) { + ret = is_zero_cow(bs, m); + if (ret < 0) { + return ret; + } else if (ret == 0) { continue; } @@ -2418,16 +2455,14 @@ static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta) * efficiently zero out the whole clusters */ - ret = qcow2_pre_write_overlap_check(bs, 0, m->alloc_offset, - m->nb_clusters * s->cluster_size, + ret = qcow2_pre_write_overlap_check(bs, 0, start_offset, nb_bytes, true); if (ret < 0) { return ret; } BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC_SPACE); - ret = bdrv_co_pwrite_zeroes(s->data_file, m->alloc_offset, - m->nb_clusters * s->cluster_size, + ret = bdrv_co_pwrite_zeroes(s->data_file, start_offset, nb_bytes, BDRV_REQ_NO_FALLBACK); if (ret < 0) { if (ret != -ENOTSUP && ret != -EAGAIN) { @@ -2449,7 +2484,7 @@ static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta) * not use it somehow after qcow2_co_pwritev_task() call */ static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs, - uint64_t file_cluster_offset, + uint64_t host_offset, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, uint64_t qiov_offset, @@ -2458,7 +2493,6 @@ static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs, int ret; BDRVQcow2State *s = bs->opaque; void *crypt_buf = NULL; - int offset_in_cluster = offset_into_cluster(s, offset); QEMUIOVector encrypted_qiov; if (bs->encrypted) { @@ -2471,9 +2505,7 @@ static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs, } qemu_iovec_to_buf(qiov, qiov_offset, crypt_buf, bytes); - if (qcow2_co_encrypt(bs, file_cluster_offset + offset_in_cluster, - offset, crypt_buf, bytes) < 0) - { + if (qcow2_co_encrypt(bs, host_offset, offset, crypt_buf, bytes) < 0) { ret = -EIO; goto out_unlocked; } @@ -2497,10 +2529,8 @@ static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs, */ if (!merge_cow(offset, bytes, qiov, qiov_offset, l2meta)) { BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); - trace_qcow2_writev_data(qemu_coroutine_self(), - file_cluster_offset + offset_in_cluster); - ret = bdrv_co_pwritev_part(s->data_file, - file_cluster_offset + offset_in_cluster, + trace_qcow2_writev_data(qemu_coroutine_self(), host_offset); + ret = bdrv_co_pwritev_part(s->data_file, host_offset, bytes, qiov, qiov_offset, 0); if (ret < 0) { goto out_unlocked; @@ -2528,9 +2558,9 @@ static coroutine_fn int qcow2_co_pwritev_task_entry(AioTask *task) { Qcow2AioTask *t = container_of(task, Qcow2AioTask, task); - assert(!t->cluster_type); + assert(!t->subcluster_type); - return qcow2_co_pwritev_task(t->bs, t->file_cluster_offset, + return qcow2_co_pwritev_task(t->bs, t->host_offset, t->offset, t->bytes, t->qiov, t->qiov_offset, t->l2meta); } @@ -2543,7 +2573,7 @@ static coroutine_fn int qcow2_co_pwritev_part( int offset_in_cluster; int ret; unsigned int cur_bytes; /* number of sectors in current iteration */ - uint64_t cluster_offset; + uint64_t host_offset; QCowL2Meta *l2meta = NULL; AioTaskPool *aio = NULL; @@ -2564,16 +2594,13 @@ static coroutine_fn int qcow2_co_pwritev_part( qemu_co_mutex_lock(&s->lock); - ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes, - &cluster_offset, &l2meta); + ret = qcow2_alloc_host_offset(bs, offset, &cur_bytes, + &host_offset, &l2meta); if (ret < 0) { goto out_locked; } - assert(offset_into_cluster(s, cluster_offset) == 0); - - ret = qcow2_pre_write_overlap_check(bs, 0, - cluster_offset + offset_in_cluster, + ret = qcow2_pre_write_overlap_check(bs, 0, host_offset, cur_bytes, true); if (ret < 0) { goto out_locked; @@ -2585,8 +2612,8 @@ static coroutine_fn int qcow2_co_pwritev_part( aio = aio_task_pool_new(QCOW2_MAX_WORKERS); } ret = qcow2_add_task(bs, aio, qcow2_co_pwritev_task_entry, 0, - cluster_offset, offset, cur_bytes, - qiov, qiov_offset, l2meta); + host_offset, offset, + cur_bytes, qiov, qiov_offset, l2meta); l2meta = NULL; /* l2meta is consumed by qcow2_co_pwritev_task() */ if (ret < 0) { goto fail_nometa; @@ -2920,6 +2947,11 @@ int qcow2_update_header(BlockDriverState *bs) .bit = QCOW2_INCOMPAT_COMPRESSION_BITNR, .name = "compression type", }, + { + .type = QCOW2_FEAT_TYPE_INCOMPATIBLE, + .bit = QCOW2_INCOMPAT_EXTL2_BITNR, + .name = "extended L2 entries", + }, { .type = QCOW2_FEAT_TYPE_COMPATIBLE, .bit = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR, @@ -3042,17 +3074,6 @@ static int qcow2_change_backing_file(BlockDriverState *bs, return qcow2_update_header(bs); } -static int qcow2_crypt_method_from_format(const char *encryptfmt) -{ - if (g_str_equal(encryptfmt, "luks")) { - return QCOW_CRYPT_LUKS; - } else if (g_str_equal(encryptfmt, "aes")) { - return QCOW_CRYPT_AES; - } else { - return -EINVAL; - } -} - static int qcow2_set_up_encryption(BlockDriverState *bs, QCryptoBlockCreateOptions *cryptoopts, Error **errp) @@ -3112,37 +3133,28 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, int64_t file_length; unsigned int cur_bytes; int ret; - QCowL2Meta *meta; + QCowL2Meta *meta = NULL, *m; assert(offset <= new_length); bytes = new_length - offset; while (bytes) { cur_bytes = MIN(bytes, QEMU_ALIGN_DOWN(INT_MAX, s->cluster_size)); - ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes, - &host_offset, &meta); + ret = qcow2_alloc_host_offset(bs, offset, &cur_bytes, + &host_offset, &meta); if (ret < 0) { error_setg_errno(errp, -ret, "Allocating clusters failed"); - return ret; + goto out; } - while (meta) { - QCowL2Meta *next = meta->next; - - ret = qcow2_alloc_cluster_link_l2(bs, meta); - if (ret < 0) { - error_setg_errno(errp, -ret, "Mapping clusters failed"); - qcow2_free_any_clusters(bs, meta->alloc_offset, - meta->nb_clusters, QCOW2_DISCARD_NEVER); - return ret; - } - - /* There are no dependent requests, but we need to remove our - * request from the list of in-flight requests */ - QLIST_REMOVE(meta, next_in_flight); + for (m = meta; m != NULL; m = m->next) { + m->prealloc = true; + } - g_free(meta); - meta = next; + ret = qcow2_handle_l2meta(bs, &meta, true); + if (ret < 0) { + error_setg_errno(errp, -ret, "Mapping clusters failed"); + goto out; } /* TODO Preallocate data if requested */ @@ -3159,7 +3171,8 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, file_length = bdrv_getlength(s->data_file->bs); if (file_length < 0) { error_setg_errno(errp, -file_length, "Could not get file size"); - return file_length; + ret = file_length; + goto out; } if (host_offset + cur_bytes > file_length) { @@ -3169,11 +3182,15 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, ret = bdrv_co_truncate(s->data_file, host_offset + cur_bytes, false, mode, 0, errp); if (ret < 0) { - return ret; + goto out; } } - return 0; + ret = 0; + +out: + qcow2_handle_l2meta(bs, &meta, false); + return ret; } /* qcow2_refcount_metadata_size: @@ -3198,7 +3215,7 @@ int64_t qcow2_refcount_metadata_size(int64_t clusters, size_t cluster_size, * where no further refcount blocks or table clusters are required to * reference count every cluster. */ - int64_t blocks_per_table_cluster = cluster_size / sizeof(uint64_t); + int64_t blocks_per_table_cluster = cluster_size / REFTABLE_ENTRY_SIZE; int64_t refcounts_per_block = cluster_size * 8 / (1 << refcount_order); int64_t table = 0; /* number of refcount table clusters */ int64_t blocks = 0; /* number of refcount block clusters */ @@ -3230,30 +3247,33 @@ int64_t qcow2_refcount_metadata_size(int64_t clusters, size_t cluster_size, * @total_size: virtual disk size in bytes * @cluster_size: cluster size in bytes * @refcount_order: refcount bits power-of-2 exponent + * @extended_l2: true if the image has extended L2 entries * * Returns: Total number of bytes required for the fully allocated image * (including metadata). */ static int64_t qcow2_calc_prealloc_size(int64_t total_size, size_t cluster_size, - int refcount_order) + int refcount_order, + bool extended_l2) { int64_t meta_size = 0; uint64_t nl1e, nl2e; int64_t aligned_total_size = ROUND_UP(total_size, cluster_size); + size_t l2e_size = extended_l2 ? L2E_SIZE_EXTENDED : L2E_SIZE_NORMAL; /* header: 1 cluster */ meta_size += cluster_size; /* total size of L2 tables */ nl2e = aligned_total_size / cluster_size; - nl2e = ROUND_UP(nl2e, cluster_size / sizeof(uint64_t)); - meta_size += nl2e * sizeof(uint64_t); + nl2e = ROUND_UP(nl2e, cluster_size / l2e_size); + meta_size += nl2e * l2e_size; /* total size of L1 tables */ - nl1e = nl2e * sizeof(uint64_t) / cluster_size; - nl1e = ROUND_UP(nl1e, cluster_size / sizeof(uint64_t)); - meta_size += nl1e * sizeof(uint64_t); + nl1e = nl2e * l2e_size / cluster_size; + nl1e = ROUND_UP(nl1e, cluster_size / L1E_SIZE); + meta_size += nl1e * L1E_SIZE; /* total size of refcount table and blocks */ meta_size += qcow2_refcount_metadata_size( @@ -3263,7 +3283,8 @@ static int64_t qcow2_calc_prealloc_size(int64_t total_size, return meta_size + aligned_total_size; } -static bool validate_cluster_size(size_t cluster_size, Error **errp) +static bool validate_cluster_size(size_t cluster_size, bool extended_l2, + Error **errp) { int cluster_bits = ctz32(cluster_size); if (cluster_bits < MIN_CLUSTER_BITS || cluster_bits > MAX_CLUSTER_BITS || @@ -3273,16 +3294,28 @@ static bool validate_cluster_size(size_t cluster_size, Error **errp) "%dk", 1 << MIN_CLUSTER_BITS, 1 << (MAX_CLUSTER_BITS - 10)); return false; } + + if (extended_l2) { + unsigned min_cluster_size = + (1 << MIN_CLUSTER_BITS) * QCOW_EXTL2_SUBCLUSTERS_PER_CLUSTER; + if (cluster_size < min_cluster_size) { + error_setg(errp, "Extended L2 entries are only supported with " + "cluster sizes of at least %u bytes", min_cluster_size); + return false; + } + } + return true; } -static size_t qcow2_opt_get_cluster_size_del(QemuOpts *opts, Error **errp) +static size_t qcow2_opt_get_cluster_size_del(QemuOpts *opts, bool extended_l2, + Error **errp) { size_t cluster_size; cluster_size = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, DEFAULT_CLUSTER_SIZE); - if (!validate_cluster_size(cluster_size, errp)) { + if (!validate_cluster_size(cluster_size, extended_l2, errp)) { return 0; } return cluster_size; @@ -3355,8 +3388,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) size_t cluster_size; int version; int refcount_order; - uint64_t* refcount_table; - Error *local_err = NULL; + uint64_t *refcount_table; int ret; uint8_t compression_type = QCOW2_COMPRESSION_TYPE_ZLIB; @@ -3397,7 +3429,20 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) cluster_size = DEFAULT_CLUSTER_SIZE; } - if (!validate_cluster_size(cluster_size, errp)) { + if (!qcow2_opts->has_extended_l2) { + qcow2_opts->extended_l2 = false; + } + if (qcow2_opts->extended_l2) { + if (version < 3) { + error_setg(errp, "Extended L2 entries are only supported with " + "compatibility level 1.1 and above (use version=v3 or " + "greater)"); + ret = -EINVAL; + goto out; + } + } + + if (!validate_cluster_size(cluster_size, qcow2_opts->extended_l2, errp)) { ret = -EINVAL; goto out; } @@ -3406,10 +3451,11 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) qcow2_opts->preallocation = PREALLOC_MODE_OFF; } if (qcow2_opts->has_backing_file && - qcow2_opts->preallocation != PREALLOC_MODE_OFF) + qcow2_opts->preallocation != PREALLOC_MODE_OFF && + !qcow2_opts->extended_l2) { - error_setg(errp, "Backing file and preallocation cannot be used at " - "the same time"); + error_setg(errp, "Backing file and preallocation can only be used at " + "the same time if extended_l2 is on"); ret = -EINVAL; goto out; } @@ -3548,6 +3594,11 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) cpu_to_be64(QCOW2_INCOMPAT_COMPRESSION); } + if (qcow2_opts->extended_l2) { + header->incompatible_features |= + cpu_to_be64(QCOW2_INCOMPAT_EXTL2); + } + ret = blk_pwrite(blk, 0, header, cluster_size, 0); g_free(header); if (ret < 0) { @@ -3582,9 +3633,8 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) } blk = blk_new_open(NULL, NULL, options, BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_NO_FLUSH, - &local_err); + errp); if (blk == NULL) { - error_propagate(errp, local_err); ret = -EIO; goto out; } @@ -3630,7 +3680,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) } ret = bdrv_change_backing_file(blk_bs(blk), qcow2_opts->backing_file, - backing_format); + backing_format, false); if (ret < 0) { error_setg_errno(errp, -ret, "Could not assign backing file '%s' " "with format '%s'", qcow2_opts->backing_file, @@ -3664,9 +3714,8 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) } blk = blk_new_open(NULL, NULL, options, BDRV_O_RDWR | BDRV_O_NO_BACKING | BDRV_O_NO_IO, - &local_err); + errp); if (blk == NULL) { - error_propagate(errp, local_err); ret = -EIO; goto out; } @@ -3689,7 +3738,6 @@ static int coroutine_fn qcow2_co_create_opts(BlockDriver *drv, Visitor *v; BlockDriverState *bs = NULL; BlockDriverState *data_bs = NULL; - Error *local_err = NULL; const char *val; int ret; @@ -3728,6 +3776,7 @@ static int coroutine_fn qcow2_co_create_opts(BlockDriver *drv, { BLOCK_OPT_BACKING_FMT, "backing-fmt" }, { BLOCK_OPT_CLUSTER_SIZE, "cluster-size" }, { BLOCK_OPT_LAZY_REFCOUNTS, "lazy-refcounts" }, + { BLOCK_OPT_EXTL2, "extended-l2" }, { BLOCK_OPT_REFCOUNT_BITS, "refcount-bits" }, { BLOCK_OPT_ENCRYPT, BLOCK_OPT_ENCRYPT_FORMAT }, { BLOCK_OPT_COMPAT_LEVEL, "version" }, @@ -3785,11 +3834,9 @@ static int coroutine_fn qcow2_co_create_opts(BlockDriver *drv, goto finish; } - visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); + visit_type_BlockdevCreateOptions(v, NULL, &create_options, errp); visit_free(v); - - if (local_err) { - error_propagate(errp, local_err); + if (!create_options) { ret = -EINVAL; goto finish; } @@ -3827,8 +3874,20 @@ static bool is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes) if (!bytes) { return true; } - res = bdrv_block_status_above(bs, NULL, offset, bytes, &nr, NULL, NULL); - return res >= 0 && (res & BDRV_BLOCK_ZERO) && nr == bytes; + + /* + * bdrv_block_status_above doesn't merge different types of zeros, for + * example, zeros which come from the region which is unallocated in + * the whole backing chain, and zeros which come because of a short + * backing file. So, we need a loop. + */ + do { + res = bdrv_block_status_above(bs, NULL, offset, bytes, &nr, NULL, NULL); + offset += nr; + bytes -= nr; + } while (res >= 0 && (res & BDRV_BLOCK_ZERO) && nr && bytes); + + return res >= 0 && (res & BDRV_BLOCK_ZERO) && bytes == 0; } static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs, @@ -3837,8 +3896,9 @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs, int ret; BDRVQcow2State *s = bs->opaque; - uint32_t head = offset % s->cluster_size; - uint32_t tail = (offset + bytes) % s->cluster_size; + uint32_t head = offset_into_subcluster(s, offset); + uint32_t tail = ROUND_UP(offset + bytes, s->subcluster_size) - + (offset + bytes); trace_qcow2_pwrite_zeroes_start_req(qemu_coroutine_self(), offset, bytes); if (offset + bytes == bs->total_sectors * BDRV_SECTOR_SIZE) { @@ -3848,27 +3908,29 @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs, if (head || tail) { uint64_t off; unsigned int nr; + QCow2SubclusterType type; - assert(head + bytes <= s->cluster_size); + assert(head + bytes + tail <= s->subcluster_size); /* check whether remainder of cluster already reads as zero */ if (!(is_zero(bs, offset - head, head) && - is_zero(bs, offset + bytes, - tail ? s->cluster_size - tail : 0))) { + is_zero(bs, offset + bytes, tail))) { return -ENOTSUP; } qemu_co_mutex_lock(&s->lock); /* We can have new write after previous check */ - offset = QEMU_ALIGN_DOWN(offset, s->cluster_size); - bytes = s->cluster_size; - nr = s->cluster_size; - ret = qcow2_get_cluster_offset(bs, offset, &nr, &off); - if (ret != QCOW2_CLUSTER_UNALLOCATED && - ret != QCOW2_CLUSTER_ZERO_PLAIN && - ret != QCOW2_CLUSTER_ZERO_ALLOC) { + offset -= head; + bytes = s->subcluster_size; + nr = s->subcluster_size; + ret = qcow2_get_host_offset(bs, offset, &nr, &off, &type); + if (ret < 0 || + (type != QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN && + type != QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC && + type != QCOW2_SUBCLUSTER_ZERO_PLAIN && + type != QCOW2_SUBCLUSTER_ZERO_ALLOC)) { qemu_co_mutex_unlock(&s->lock); - return -ENOTSUP; + return ret < 0 ? ret : -ENOTSUP; } } else { qemu_co_mutex_lock(&s->lock); @@ -3876,8 +3938,8 @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs, trace_qcow2_pwrite_zeroes(qemu_coroutine_self(), offset, bytes); - /* Whatever is left can use real zero clusters */ - ret = qcow2_cluster_zeroize(bs, offset, bytes, flags); + /* Whatever is left can use real zero subclusters */ + ret = qcow2_subcluster_zeroize(bs, offset, bytes, flags); qemu_co_mutex_unlock(&s->lock); return ret; @@ -3930,17 +3992,20 @@ qcow2_co_copy_range_from(BlockDriverState *bs, while (bytes != 0) { uint64_t copy_offset = 0; + QCow2SubclusterType type; /* prepare next request */ cur_bytes = MIN(bytes, INT_MAX); cur_write_flags = write_flags; - ret = qcow2_get_cluster_offset(bs, src_offset, &cur_bytes, ©_offset); + ret = qcow2_get_host_offset(bs, src_offset, &cur_bytes, + ©_offset, &type); if (ret < 0) { goto out; } - switch (ret) { - case QCOW2_CLUSTER_UNALLOCATED: + switch (type) { + case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN: + case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC: if (bs->backing && bs->backing->bs) { int64_t backing_length = bdrv_getlength(bs->backing->bs); if (src_offset >= backing_length) { @@ -3955,18 +4020,17 @@ qcow2_co_copy_range_from(BlockDriverState *bs, } break; - case QCOW2_CLUSTER_ZERO_PLAIN: - case QCOW2_CLUSTER_ZERO_ALLOC: + case QCOW2_SUBCLUSTER_ZERO_PLAIN: + case QCOW2_SUBCLUSTER_ZERO_ALLOC: cur_write_flags |= BDRV_REQ_ZERO_WRITE; break; - case QCOW2_CLUSTER_COMPRESSED: + case QCOW2_SUBCLUSTER_COMPRESSED: ret = -ENOTSUP; goto out; - case QCOW2_CLUSTER_NORMAL: + case QCOW2_SUBCLUSTER_NORMAL: child = s->data_file; - copy_offset += offset_into_cluster(s, src_offset); break; default: @@ -4001,10 +4065,9 @@ qcow2_co_copy_range_to(BlockDriverState *bs, BdrvRequestFlags write_flags) { BDRVQcow2State *s = bs->opaque; - int offset_in_cluster; int ret; unsigned int cur_bytes; /* number of sectors in current iteration */ - uint64_t cluster_offset; + uint64_t host_offset; QCowL2Meta *l2meta = NULL; assert(!bs->encrypted); @@ -4015,31 +4078,26 @@ qcow2_co_copy_range_to(BlockDriverState *bs, l2meta = NULL; - offset_in_cluster = offset_into_cluster(s, dst_offset); cur_bytes = MIN(bytes, INT_MAX); /* TODO: * If src->bs == dst->bs, we could simply copy by incrementing * the refcnt, without copying user data. * Or if src->bs == dst->bs->backing->bs, we could copy by discarding. */ - ret = qcow2_alloc_cluster_offset(bs, dst_offset, &cur_bytes, - &cluster_offset, &l2meta); + ret = qcow2_alloc_host_offset(bs, dst_offset, &cur_bytes, + &host_offset, &l2meta); if (ret < 0) { goto fail; } - assert(offset_into_cluster(s, cluster_offset) == 0); - - ret = qcow2_pre_write_overlap_check(bs, 0, - cluster_offset + offset_in_cluster, cur_bytes, true); + ret = qcow2_pre_write_overlap_check(bs, 0, host_offset, cur_bytes, + true); if (ret < 0) { goto fail; } qemu_co_mutex_unlock(&s->lock); - ret = bdrv_co_copy_range_to(src, src_offset, - s->data_file, - cluster_offset + offset_in_cluster, + ret = bdrv_co_copy_range_to(src, src_offset, s->data_file, host_offset, cur_bytes, read_flags, write_flags); qemu_co_mutex_lock(&s->lock); if (ret < 0) { @@ -4213,6 +4271,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, int64_t clusters_allocated; int64_t old_file_size, last_cluster, new_file_size; uint64_t nb_new_data_clusters, nb_new_l2_tables; + bool subclusters_need_allocation = false; /* With a data file, preallocation means just allocating the metadata * and forwarding the truncate request to the data file */ @@ -4239,8 +4298,8 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, old_file_size = ROUND_UP(old_file_size, s->cluster_size); } - nb_new_data_clusters = DIV_ROUND_UP(offset - old_length, - s->cluster_size); + nb_new_data_clusters = (ROUND_UP(offset, s->cluster_size) - + start_of_cluster(s, old_length)) >> s->cluster_bits; /* This is an overestimation; we will not actually allocate space for * these in the file but just make sure the new refcount structures are @@ -4253,7 +4312,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, * preallocation. All that matters is that we will not have to allocate * new refcount structures for them.) */ nb_new_l2_tables = DIV_ROUND_UP(nb_new_data_clusters, - s->cluster_size / sizeof(uint64_t)); + s->cluster_size / l2_entry_size(s)); /* The cluster range may not be aligned to L2 boundaries, so add one L2 * table for a potential head/tail */ nb_new_l2_tables++; @@ -4294,6 +4353,8 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, BDRV_REQ_ZERO_WRITE, NULL); if (ret >= 0) { flags &= ~BDRV_REQ_ZERO_WRITE; + /* Ensure that we read zeroes and not backing file data */ + subclusters_need_allocation = true; } } else { ret = -1; @@ -4317,10 +4378,22 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, int64_t nb_clusters = MIN( nb_new_data_clusters, s->l2_slice_size - offset_to_l2_slice_index(s, guest_offset)); - QCowL2Meta allocation = { + unsigned cow_start_length = offset_into_cluster(s, guest_offset); + QCowL2Meta allocation; + guest_offset = start_of_cluster(s, guest_offset); + allocation = (QCowL2Meta) { .offset = guest_offset, .alloc_offset = host_offset, .nb_clusters = nb_clusters, + .cow_start = { + .offset = 0, + .nb_bytes = cow_start_length, + }, + .cow_end = { + .offset = nb_clusters << s->cluster_bits, + .nb_bytes = 0, + }, + .prealloc = !subclusters_need_allocation, }; qemu_co_queue_init(&allocation.dependent_requests); @@ -4345,15 +4418,16 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, } if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) { - uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->cluster_size); + uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->subcluster_size); /* - * Use zero clusters as much as we can. qcow2_cluster_zeroize() - * requires a cluster-aligned start. The end may be unaligned if it is - * at the end of the image (which it is here). + * Use zero clusters as much as we can. qcow2_subcluster_zeroize() + * requires a subcluster-aligned start. The end may be unaligned if + * it is at the end of the image (which it is here). */ if (offset > zero_start) { - ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0); + ret = qcow2_subcluster_zeroize(bs, zero_start, offset - zero_start, + 0); if (ret < 0) { error_setg_errno(errp, -ret, "Failed to zero out new clusters"); goto fail; @@ -4394,7 +4468,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, /* write updated header.size */ offset = cpu_to_be64(offset); ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size), - &offset, sizeof(uint64_t)); + &offset, sizeof(offset)); if (ret < 0) { error_setg_errno(errp, -ret, "Failed to update the image size"); goto fail; @@ -4483,7 +4557,7 @@ static coroutine_fn int qcow2_co_pwritev_compressed_task_entry(AioTask *task) { Qcow2AioTask *t = container_of(task, Qcow2AioTask, task); - assert(!t->cluster_type && !t->l2meta); + assert(!t->subcluster_type && !t->l2meta); return qcow2_co_pwritev_compressed_task(t->bs, t->offset, t->bytes, t->qiov, t->qiov_offset); @@ -4558,7 +4632,7 @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs, static int coroutine_fn qcow2_co_preadv_compressed(BlockDriverState *bs, - uint64_t file_cluster_offset, + uint64_t cluster_descriptor, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, @@ -4570,8 +4644,8 @@ qcow2_co_preadv_compressed(BlockDriverState *bs, uint8_t *buf, *out_buf; int offset_in_cluster = offset_into_cluster(s, offset); - coffset = file_cluster_offset & s->cluster_offset_mask; - nb_csectors = ((file_cluster_offset >> s->csize_shift) & s->csize_mask) + 1; + coffset = cluster_descriptor & s->cluster_offset_mask; + nb_csectors = ((cluster_descriptor >> s->csize_shift) & s->csize_mask) + 1; csize = nb_csectors * QCOW2_COMPRESSED_SECTOR_SIZE - (coffset & ~QCOW2_COMPRESSED_SECTOR_MASK); @@ -4634,8 +4708,8 @@ static int make_completely_empty(BlockDriverState *bs) BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE); - l1_clusters = DIV_ROUND_UP(s->l1_size, s->cluster_size / sizeof(uint64_t)); - l1_size2 = (uint64_t)s->l1_size * sizeof(uint64_t); + l1_clusters = DIV_ROUND_UP(s->l1_size, s->cluster_size / L1E_SIZE); + l1_size2 = (uint64_t)s->l1_size * L1E_SIZE; /* After this call, neither the in-memory nor the on-disk refcount * information accurately describe the actual references */ @@ -4681,14 +4755,14 @@ static int make_completely_empty(BlockDriverState *bs) s->l1_table_offset = 3 * s->cluster_size; - new_reftable = g_try_new0(uint64_t, s->cluster_size / sizeof(uint64_t)); + new_reftable = g_try_new0(uint64_t, s->cluster_size / REFTABLE_ENTRY_SIZE); if (!new_reftable) { ret = -ENOMEM; goto fail_broken_refcounts; } s->refcount_table_offset = s->cluster_size; - s->refcount_table_size = s->cluster_size / sizeof(uint64_t); + s->refcount_table_size = s->cluster_size / REFTABLE_ENTRY_SIZE; s->max_refcount_table_index = 0; g_free(s->refcount_table); @@ -4760,7 +4834,7 @@ static int qcow2_make_empty(BlockDriverState *bs) int step = QEMU_ALIGN_DOWN(INT_MAX, s->cluster_size); int l1_clusters, ret = 0; - l1_clusters = DIV_ROUND_UP(s->l1_size, s->cluster_size / sizeof(uint64_t)); + l1_clusters = DIV_ROUND_UP(s->l1_size, s->cluster_size / L1E_SIZE); if (s->qcow_version >= 3 && !s->snapshots && !s->nb_bitmaps && 3 + l1_clusters <= s->refcount_block_size && @@ -4825,9 +4899,14 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs, PreallocMode prealloc; bool has_backing_file; bool has_luks; + bool extended_l2; + size_t l2e_size; /* Parse image creation options */ - cluster_size = qcow2_opt_get_cluster_size_del(opts, &local_err); + extended_l2 = qemu_opt_get_bool_del(opts, BLOCK_OPT_EXTL2, false); + + cluster_size = qcow2_opt_get_cluster_size_del(opts, extended_l2, + &local_err); if (local_err) { goto err; } @@ -4860,16 +4939,9 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs, if (has_luks) { g_autoptr(QCryptoBlockCreateOptions) create_opts = NULL; - QDict *opts_qdict; - QDict *cryptoopts; + QDict *cryptoopts = qcow2_extract_crypto_opts(opts, "luks", errp); size_t headerlen; - opts_qdict = qemu_opts_to_qdict(opts, NULL); - qdict_extract_subqdict(opts_qdict, &cryptoopts, "encrypt."); - qobject_unref(opts_qdict); - - qdict_put_str(cryptoopts, "format", "luks"); - create_opts = block_crypto_create_opts_init(cryptoopts, errp); qobject_unref(cryptoopts); if (!create_opts) { @@ -4890,9 +4962,10 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs, virtual_size = ROUND_UP(virtual_size, cluster_size); /* Check that virtual disk size is valid */ + l2e_size = extended_l2 ? L2E_SIZE_EXTENDED : L2E_SIZE_NORMAL; l2_tables = DIV_ROUND_UP(virtual_size / cluster_size, - cluster_size / sizeof(uint64_t)); - if (l2_tables * sizeof(uint64_t) > QCOW_MAX_L1_SIZE) { + cluster_size / l2e_size); + if (l2_tables * L1E_SIZE > QCOW_MAX_L1_SIZE) { error_setg(&local_err, "The image size is too large " "(try using a larger cluster size)"); goto err; @@ -4953,16 +5026,24 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs, required = virtual_size; } - info = g_new(BlockMeasureInfo, 1); - info->fully_allocated = + info = g_new0(BlockMeasureInfo, 1); + info->fully_allocated = luks_payload_size + qcow2_calc_prealloc_size(virtual_size, cluster_size, - ctz32(refcount_bits)) + luks_payload_size; + ctz32(refcount_bits), extended_l2); - /* Remove data clusters that are not required. This overestimates the + /* + * Remove data clusters that are not required. This overestimates the * required size because metadata needed for the fully allocated file is - * still counted. + * still counted. Show bitmaps only if both source and destination + * would support them. */ info->required = info->fully_allocated - virtual_size + required; + info->has_bitmaps = version >= 3 && in_bs && + bdrv_supports_persistent_dirty_bitmap(in_bs); + if (info->has_bitmaps) { + info->bitmaps = qcow2_get_persistent_dirty_bitmap_size(in_bs, + cluster_size); + } return info; err: @@ -4973,7 +5054,6 @@ err: static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { BDRVQcow2State *s = bs->opaque; - bdi->unallocated_blocks_are_zero = true; bdi->cluster_size = s->cluster_size; bdi->vm_state_offset = qcow2_vm_state_offset(s); return 0; @@ -5022,6 +5102,8 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs, .corrupt = s->incompatible_features & QCOW2_INCOMPAT_CORRUPT, .has_corrupt = true, + .has_extended_l2 = true, + .extended_l2 = has_subclusters(s), .refcount_bits = s->refcount_bits, .has_bitmaps = !!bitmaps, .bitmaps = bitmaps, @@ -5265,6 +5347,7 @@ typedef enum Qcow2AmendOperation { QCOW2_NO_OPERATION = 0, QCOW2_UPGRADING, + QCOW2_UPDATING_ENCRYPTION, QCOW2_CHANGING_REFCOUNT_ORDER, QCOW2_DOWNGRADING, } Qcow2AmendOperation; @@ -5332,6 +5415,7 @@ static void qcow2_amend_helper_cb(BlockDriverState *bs, static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, BlockDriverAmendStatusCB *status_cb, void *cb_opaque, + bool force, Error **errp) { BDRVQcow2State *s = bs->opaque; @@ -5341,13 +5425,11 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, bool lazy_refcounts = s->use_lazy_refcounts; bool data_file_raw = data_file_is_raw(bs); const char *compat = NULL; - uint64_t cluster_size = s->cluster_size; - bool encrypt; - int encformat; int refcount_bits = s->refcount_bits; int ret; QemuOptDesc *desc = opts->list->desc; Qcow2AmendHelperCBInfo helper_cb_info; + bool encryption_update = false; while (desc && desc->name) { if (!qemu_opt_find(opts, desc->name)) { @@ -5368,44 +5450,24 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, error_setg(errp, "Unknown compatibility level %s", compat); return -EINVAL; } - } else if (!strcmp(desc->name, BLOCK_OPT_PREALLOC)) { - error_setg(errp, "Cannot change preallocation mode"); - return -ENOTSUP; } else if (!strcmp(desc->name, BLOCK_OPT_SIZE)) { new_size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0); } else if (!strcmp(desc->name, BLOCK_OPT_BACKING_FILE)) { backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE); } else if (!strcmp(desc->name, BLOCK_OPT_BACKING_FMT)) { backing_format = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT); - } else if (!strcmp(desc->name, BLOCK_OPT_ENCRYPT)) { - encrypt = qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT, - !!s->crypto); - - if (encrypt != !!s->crypto) { + } else if (g_str_has_prefix(desc->name, "encrypt.")) { + if (!s->crypto) { error_setg(errp, - "Changing the encryption flag is not supported"); - return -ENOTSUP; + "Can't amend encryption options - encryption not present"); + return -EINVAL; } - } else if (!strcmp(desc->name, BLOCK_OPT_ENCRYPT_FORMAT)) { - encformat = qcow2_crypt_method_from_format( - qemu_opt_get(opts, BLOCK_OPT_ENCRYPT_FORMAT)); - - if (encformat != s->crypt_method_header) { + if (s->crypt_method_header != QCOW_CRYPT_LUKS) { error_setg(errp, - "Changing the encryption format is not supported"); - return -ENOTSUP; - } - } else if (g_str_has_prefix(desc->name, "encrypt.")) { - error_setg(errp, - "Changing the encryption parameters is not supported"); - return -ENOTSUP; - } else if (!strcmp(desc->name, BLOCK_OPT_CLUSTER_SIZE)) { - cluster_size = qemu_opt_get_size(opts, BLOCK_OPT_CLUSTER_SIZE, - cluster_size); - if (cluster_size != s->cluster_size) { - error_setg(errp, "Changing the cluster size is not supported"); + "Only LUKS encryption options can be amended"); return -ENOTSUP; } + encryption_update = true; } else if (!strcmp(desc->name, BLOCK_OPT_LAZY_REFCOUNTS)) { lazy_refcounts = qemu_opt_get_bool(opts, BLOCK_OPT_LAZY_REFCOUNTS, lazy_refcounts); @@ -5435,22 +5497,6 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, "images"); return -EINVAL; } - } else if (!strcmp(desc->name, BLOCK_OPT_COMPRESSION_TYPE)) { - const char *ct_name = - qemu_opt_get(opts, BLOCK_OPT_COMPRESSION_TYPE); - int compression_type = - qapi_enum_parse(&Qcow2CompressionType_lookup, ct_name, -1, - NULL); - if (compression_type == -1) { - error_setg(errp, "Unknown compression type: %s", ct_name); - return -ENOTSUP; - } - - if (compression_type != s->compression_type) { - error_setg(errp, "Changing the compression type " - "is not supported"); - return -ENOTSUP; - } } else { /* if this point is reached, this probably means a new option was * added without having it covered here */ @@ -5464,7 +5510,8 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, .original_status_cb = status_cb, .original_cb_opaque = cb_opaque, .total_operations = (new_version != old_version) - + (s->refcount_bits != refcount_bits) + + (s->refcount_bits != refcount_bits) + + (encryption_update == true) }; /* Upgrade first (some features may require compat=1.1) */ @@ -5477,6 +5524,33 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, } } + if (encryption_update) { + QDict *amend_opts_dict; + QCryptoBlockAmendOptions *amend_opts; + + helper_cb_info.current_operation = QCOW2_UPDATING_ENCRYPTION; + amend_opts_dict = qcow2_extract_crypto_opts(opts, "luks", errp); + if (!amend_opts_dict) { + return -EINVAL; + } + amend_opts = block_crypto_amend_opts_init(amend_opts_dict, errp); + qobject_unref(amend_opts_dict); + if (!amend_opts) { + return -EINVAL; + } + ret = qcrypto_block_amend_options(s->crypto, + qcow2_crypto_hdr_read_func, + qcow2_crypto_hdr_write_func, + bs, + amend_opts, + force, + errp); + qapi_free_QCryptoBlockAmendOptions(amend_opts); + if (ret < 0) { + return ret; + } + } + if (s->refcount_bits != refcount_bits) { int refcount_order = ctz32(refcount_bits); @@ -5515,6 +5589,11 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, } if (backing_file || backing_format) { + if (g_strcmp0(backing_file, s->image_backing_file) || + g_strcmp0(backing_format, s->image_backing_format)) { + warn_report("Deprecated use of amend to alter the backing file; " + "use qemu-img rebase instead"); + } ret = qcow2_change_backing_file(bs, backing_file ?: s->image_backing_file, backing_format ?: s->image_backing_format); @@ -5590,6 +5669,44 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, return 0; } +static int coroutine_fn qcow2_co_amend(BlockDriverState *bs, + BlockdevAmendOptions *opts, + bool force, + Error **errp) +{ + BlockdevAmendOptionsQcow2 *qopts = &opts->u.qcow2; + BDRVQcow2State *s = bs->opaque; + int ret = 0; + + if (qopts->has_encrypt) { + if (!s->crypto) { + error_setg(errp, "image is not encrypted, can't amend"); + return -EOPNOTSUPP; + } + + if (qopts->encrypt->format != Q_CRYPTO_BLOCK_FORMAT_LUKS) { + error_setg(errp, + "Amend can't be used to change the qcow2 encryption format"); + return -EOPNOTSUPP; + } + + if (s->crypt_method_header != QCOW_CRYPT_LUKS) { + error_setg(errp, + "Only LUKS encryption options can be amended for qcow2 with blockdev-amend"); + return -EOPNOTSUPP; + } + + ret = qcrypto_block_amend_options(s->crypto, + qcow2_crypto_hdr_read_func, + qcow2_crypto_hdr_write_func, + bs, + qopts->encrypt, + force, + errp); + } + return ret; +} + /* * If offset or size are negative, respectively, they will not be included in * the BLOCK_IMAGE_CORRUPTED event emitted. @@ -5640,89 +5757,114 @@ void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset, s->signaled_corruption = true; } +#define QCOW_COMMON_OPTIONS \ + { \ + .name = BLOCK_OPT_SIZE, \ + .type = QEMU_OPT_SIZE, \ + .help = "Virtual disk size" \ + }, \ + { \ + .name = BLOCK_OPT_COMPAT_LEVEL, \ + .type = QEMU_OPT_STRING, \ + .help = "Compatibility level (v2 [0.10] or v3 [1.1])" \ + }, \ + { \ + .name = BLOCK_OPT_BACKING_FILE, \ + .type = QEMU_OPT_STRING, \ + .help = "File name of a base image" \ + }, \ + { \ + .name = BLOCK_OPT_BACKING_FMT, \ + .type = QEMU_OPT_STRING, \ + .help = "Image format of the base image" \ + }, \ + { \ + .name = BLOCK_OPT_DATA_FILE, \ + .type = QEMU_OPT_STRING, \ + .help = "File name of an external data file" \ + }, \ + { \ + .name = BLOCK_OPT_DATA_FILE_RAW, \ + .type = QEMU_OPT_BOOL, \ + .help = "The external data file must stay valid " \ + "as a raw image" \ + }, \ + { \ + .name = BLOCK_OPT_LAZY_REFCOUNTS, \ + .type = QEMU_OPT_BOOL, \ + .help = "Postpone refcount updates", \ + .def_value_str = "off" \ + }, \ + { \ + .name = BLOCK_OPT_REFCOUNT_BITS, \ + .type = QEMU_OPT_NUMBER, \ + .help = "Width of a reference count entry in bits", \ + .def_value_str = "16" \ + } + static QemuOptsList qcow2_create_opts = { .name = "qcow2-create-opts", .head = QTAILQ_HEAD_INITIALIZER(qcow2_create_opts.head), .desc = { - { - .name = BLOCK_OPT_SIZE, - .type = QEMU_OPT_SIZE, - .help = "Virtual disk size" - }, - { - .name = BLOCK_OPT_COMPAT_LEVEL, - .type = QEMU_OPT_STRING, - .help = "Compatibility level (v2 [0.10] or v3 [1.1])" - }, - { - .name = BLOCK_OPT_BACKING_FILE, - .type = QEMU_OPT_STRING, - .help = "File name of a base image" - }, - { - .name = BLOCK_OPT_BACKING_FMT, - .type = QEMU_OPT_STRING, - .help = "Image format of the base image" - }, - { - .name = BLOCK_OPT_DATA_FILE, - .type = QEMU_OPT_STRING, - .help = "File name of an external data file" - }, - { - .name = BLOCK_OPT_DATA_FILE_RAW, - .type = QEMU_OPT_BOOL, - .help = "The external data file must stay valid as a raw image" - }, - { - .name = BLOCK_OPT_ENCRYPT, - .type = QEMU_OPT_BOOL, - .help = "Encrypt the image with format 'aes'. (Deprecated " - "in favor of " BLOCK_OPT_ENCRYPT_FORMAT "=aes)", - }, - { - .name = BLOCK_OPT_ENCRYPT_FORMAT, - .type = QEMU_OPT_STRING, - .help = "Encrypt the image, format choices: 'aes', 'luks'", + { \ + .name = BLOCK_OPT_ENCRYPT, \ + .type = QEMU_OPT_BOOL, \ + .help = "Encrypt the image with format 'aes'. (Deprecated " \ + "in favor of " BLOCK_OPT_ENCRYPT_FORMAT "=aes)", \ + }, \ + { \ + .name = BLOCK_OPT_ENCRYPT_FORMAT, \ + .type = QEMU_OPT_STRING, \ + .help = "Encrypt the image, format choices: 'aes', 'luks'", \ + }, \ + BLOCK_CRYPTO_OPT_DEF_KEY_SECRET("encrypt.", \ + "ID of secret providing qcow AES key or LUKS passphrase"), \ + BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG("encrypt."), \ + BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE("encrypt."), \ + BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG("encrypt."), \ + BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG("encrypt."), \ + BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG("encrypt."), \ + BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME("encrypt."), \ + { \ + .name = BLOCK_OPT_CLUSTER_SIZE, \ + .type = QEMU_OPT_SIZE, \ + .help = "qcow2 cluster size", \ + .def_value_str = stringify(DEFAULT_CLUSTER_SIZE) \ + }, \ + { \ + .name = BLOCK_OPT_EXTL2, \ + .type = QEMU_OPT_BOOL, \ + .help = "Extended L2 tables", \ + .def_value_str = "off" \ + }, \ + { \ + .name = BLOCK_OPT_PREALLOC, \ + .type = QEMU_OPT_STRING, \ + .help = "Preallocation mode (allowed values: off, " \ + "metadata, falloc, full)" \ + }, \ + { \ + .name = BLOCK_OPT_COMPRESSION_TYPE, \ + .type = QEMU_OPT_STRING, \ + .help = "Compression method used for image cluster " \ + "compression", \ + .def_value_str = "zlib" \ }, - BLOCK_CRYPTO_OPT_DEF_KEY_SECRET("encrypt.", - "ID of secret providing qcow AES key or LUKS passphrase"), - BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG("encrypt."), - BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE("encrypt."), - BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG("encrypt."), - BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG("encrypt."), - BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG("encrypt."), + QCOW_COMMON_OPTIONS, + { /* end of list */ } + } +}; + +static QemuOptsList qcow2_amend_opts = { + .name = "qcow2-amend-opts", + .head = QTAILQ_HEAD_INITIALIZER(qcow2_amend_opts.head), + .desc = { + BLOCK_CRYPTO_OPT_DEF_LUKS_STATE("encrypt."), + BLOCK_CRYPTO_OPT_DEF_LUKS_KEYSLOT("encrypt."), + BLOCK_CRYPTO_OPT_DEF_LUKS_OLD_SECRET("encrypt."), + BLOCK_CRYPTO_OPT_DEF_LUKS_NEW_SECRET("encrypt."), BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME("encrypt."), - { - .name = BLOCK_OPT_CLUSTER_SIZE, - .type = QEMU_OPT_SIZE, - .help = "qcow2 cluster size", - .def_value_str = stringify(DEFAULT_CLUSTER_SIZE) - }, - { - .name = BLOCK_OPT_PREALLOC, - .type = QEMU_OPT_STRING, - .help = "Preallocation mode (allowed values: off, metadata, " - "falloc, full)" - }, - { - .name = BLOCK_OPT_LAZY_REFCOUNTS, - .type = QEMU_OPT_BOOL, - .help = "Postpone refcount updates", - .def_value_str = "off" - }, - { - .name = BLOCK_OPT_REFCOUNT_BITS, - .type = QEMU_OPT_NUMBER, - .help = "Width of a reference count entry in bits", - .def_value_str = "16" - }, - { - .name = BLOCK_OPT_COMPRESSION_TYPE, - .type = QEMU_OPT_STRING, - .help = "Compression method used for image cluster compression", - .def_value_str = "zlib" - }, + QCOW_COMMON_OPTIONS, { /* end of list */ } } }; @@ -5783,10 +5925,12 @@ BlockDriver bdrv_qcow2 = { .bdrv_inactivate = qcow2_inactivate, .create_opts = &qcow2_create_opts, + .amend_opts = &qcow2_amend_opts, .strong_runtime_opts = qcow2_strong_runtime_opts, .mutable_opts = mutable_opts, .bdrv_co_check = qcow2_co_check, .bdrv_amend_options = qcow2_amend_options, + .bdrv_co_amend = qcow2_co_amend, .bdrv_detach_aio_context = qcow2_detach_aio_context, .bdrv_attach_aio_context = qcow2_attach_aio_context, diff --git a/block/qcow2.h b/block/qcow2.h index 402e8acb1cb7dd691ad4a8781ec7c301a5dcad71..0678073b742f1b6ae2f1e5fcd3daf430fba05b5d 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -78,6 +78,33 @@ /* The cluster reads as all zeros */ #define QCOW_OFLAG_ZERO (1ULL << 0) +#define QCOW_EXTL2_SUBCLUSTERS_PER_CLUSTER 32 + +/* The subcluster X [0..31] is allocated */ +#define QCOW_OFLAG_SUB_ALLOC(X) (1ULL << (X)) +/* The subcluster X [0..31] reads as zeroes */ +#define QCOW_OFLAG_SUB_ZERO(X) (QCOW_OFLAG_SUB_ALLOC(X) << 32) +/* Subclusters [X, Y) (0 <= X <= Y <= 32) are allocated */ +#define QCOW_OFLAG_SUB_ALLOC_RANGE(X, Y) \ + (QCOW_OFLAG_SUB_ALLOC(Y) - QCOW_OFLAG_SUB_ALLOC(X)) +/* Subclusters [X, Y) (0 <= X <= Y <= 32) read as zeroes */ +#define QCOW_OFLAG_SUB_ZERO_RANGE(X, Y) \ + (QCOW_OFLAG_SUB_ALLOC_RANGE(X, Y) << 32) +/* L2 entry bitmap with all allocation bits set */ +#define QCOW_L2_BITMAP_ALL_ALLOC (QCOW_OFLAG_SUB_ALLOC_RANGE(0, 32)) +/* L2 entry bitmap with all "read as zeroes" bits set */ +#define QCOW_L2_BITMAP_ALL_ZEROES (QCOW_OFLAG_SUB_ZERO_RANGE(0, 32)) + +/* Size of normal and extended L2 entries */ +#define L2E_SIZE_NORMAL (sizeof(uint64_t)) +#define L2E_SIZE_EXTENDED (sizeof(uint64_t) * 2) + +/* Size of L1 table entries */ +#define L1E_SIZE (sizeof(uint64_t)) + +/* Size of reftable entries */ +#define REFTABLE_ENTRY_SIZE (sizeof(uint64_t)) + #define MIN_CLUSTER_BITS 9 #define MAX_CLUSTER_BITS 21 @@ -179,6 +206,7 @@ typedef struct QEMU_PACKED QCowSnapshotHeader { typedef struct QEMU_PACKED QCowSnapshotExtraData { uint64_t vm_state_size_large; uint64_t disk_size; + uint64_t icount; } QCowSnapshotExtraData; @@ -192,6 +220,8 @@ typedef struct QCowSnapshot { uint32_t date_sec; uint32_t date_nsec; uint64_t vm_clock_nsec; + /* icount value for the moment when snapshot was taken */ + uint64_t icount; /* Size of all extra data, including QCowSnapshotExtraData if available */ uint32_t extra_data_size; /* Data beyond QCowSnapshotExtraData, if any */ @@ -225,15 +255,18 @@ enum { QCOW2_INCOMPAT_CORRUPT_BITNR = 1, QCOW2_INCOMPAT_DATA_FILE_BITNR = 2, QCOW2_INCOMPAT_COMPRESSION_BITNR = 3, + QCOW2_INCOMPAT_EXTL2_BITNR = 4, QCOW2_INCOMPAT_DIRTY = 1 << QCOW2_INCOMPAT_DIRTY_BITNR, QCOW2_INCOMPAT_CORRUPT = 1 << QCOW2_INCOMPAT_CORRUPT_BITNR, QCOW2_INCOMPAT_DATA_FILE = 1 << QCOW2_INCOMPAT_DATA_FILE_BITNR, QCOW2_INCOMPAT_COMPRESSION = 1 << QCOW2_INCOMPAT_COMPRESSION_BITNR, + QCOW2_INCOMPAT_EXTL2 = 1 << QCOW2_INCOMPAT_EXTL2_BITNR, QCOW2_INCOMPAT_MASK = QCOW2_INCOMPAT_DIRTY | QCOW2_INCOMPAT_CORRUPT | QCOW2_INCOMPAT_DATA_FILE - | QCOW2_INCOMPAT_COMPRESSION, + | QCOW2_INCOMPAT_COMPRESSION + | QCOW2_INCOMPAT_EXTL2, }; /* Compatible feature bits */ @@ -295,6 +328,9 @@ typedef struct BDRVQcow2State { int cluster_bits; int cluster_size; int l2_slice_size; + int subcluster_bits; + int subcluster_size; + int subclusters_per_cluster; int l2_bits; int l2_size; int l1_size; @@ -307,8 +343,8 @@ typedef struct BDRVQcow2State { uint64_t l1_table_offset; uint64_t *l1_table; - Qcow2Cache* l2_table_cache; - Qcow2Cache* refcount_block_cache; + Qcow2Cache *l2_table_cache; + Qcow2Cache *refcount_block_cache; QEMUTimer *cache_clean_timer; unsigned cache_clean_interval; @@ -358,7 +394,7 @@ typedef struct BDRVQcow2State { uint64_t autoclear_features; size_t unknown_header_fields_size; - void* unknown_header_fields; + void *unknown_header_fields; QLIST_HEAD(, Qcow2UnknownHeaderExtension) unknown_header_ext; QTAILQ_HEAD (, Qcow2DiscardRegion) discards; bool cache_discards; @@ -399,17 +435,18 @@ typedef struct Qcow2COWRegion { /** * Describes an in-flight (part of a) write request that writes to clusters - * that are not referenced in their L2 table yet. + * that need to have their L2 table entries updated (because they are + * newly allocated or need changes in their L2 bitmaps) */ typedef struct QCowL2Meta { - /** Guest offset of the first newly allocated cluster */ + /** Guest offset of the first updated cluster */ uint64_t offset; - /** Host offset of the first newly allocated cluster */ + /** Host offset of the first updated cluster */ uint64_t alloc_offset; - /** Number of newly allocated clusters */ + /** Number of updated clusters */ int nb_clusters; /** Do not free the old clusters */ @@ -422,14 +459,16 @@ typedef struct QCowL2Meta CoQueue dependent_requests; /** - * The COW Region between the start of the first allocated cluster and the - * area the guest actually writes to. + * The COW Region immediately before the area the guest actually + * writes to. This (part of the) write request starts at + * cow_start.offset + cow_start.nb_bytes. */ Qcow2COWRegion cow_start; /** - * The COW Region between the area the guest actually writes to and the - * end of the last allocated cluster. + * The COW Region immediately after the area the guest actually + * writes to. This (part of the) write request ends at cow_end.offset + * (which must always be set even when cow_end.nb_bytes is 0). */ Qcow2COWRegion cow_end; @@ -439,6 +478,14 @@ typedef struct QCowL2Meta */ bool skip_cow; + /** + * Indicates that this is not a normal write request but a preallocation. + * If the image has extended L2 entries this means that no new individual + * subclusters will be marked as allocated in the L2 bitmap (but any + * existing contents of that bitmap will be kept). + */ + bool prealloc; + /** * The I/O vector with the data from the actual guest write request. * If non-NULL, this is meant to be merged together with the data @@ -453,6 +500,33 @@ typedef struct QCowL2Meta QLIST_ENTRY(QCowL2Meta) next_in_flight; } QCowL2Meta; +/* + * In images with standard L2 entries all clusters are treated as if + * they had one subcluster so QCow2ClusterType and QCow2SubclusterType + * can be mapped to each other and have the exact same meaning + * (QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC cannot happen in these images). + * + * In images with extended L2 entries QCow2ClusterType refers to the + * complete cluster and QCow2SubclusterType to each of the individual + * subclusters, so there are several possible combinations: + * + * |--------------+---------------------------| + * | Cluster type | Possible subcluster types | + * |--------------+---------------------------| + * | UNALLOCATED | UNALLOCATED_PLAIN | + * | | ZERO_PLAIN | + * |--------------+---------------------------| + * | NORMAL | UNALLOCATED_ALLOC | + * | | ZERO_ALLOC | + * | | NORMAL | + * |--------------+---------------------------| + * | COMPRESSED | COMPRESSED | + * |--------------+---------------------------| + * + * QCOW2_SUBCLUSTER_INVALID means that the L2 entry is incorrect and + * the image should be marked corrupt. + */ + typedef enum QCow2ClusterType { QCOW2_CLUSTER_UNALLOCATED, QCOW2_CLUSTER_ZERO_PLAIN, @@ -461,6 +535,16 @@ typedef enum QCow2ClusterType { QCOW2_CLUSTER_COMPRESSED, } QCow2ClusterType; +typedef enum QCow2SubclusterType { + QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN, + QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC, + QCOW2_SUBCLUSTER_ZERO_PLAIN, + QCOW2_SUBCLUSTER_ZERO_ALLOC, + QCOW2_SUBCLUSTER_NORMAL, + QCOW2_SUBCLUSTER_COMPRESSED, + QCOW2_SUBCLUSTER_INVALID, +} QCow2SubclusterType; + typedef enum QCow2MetadataOverlap { QCOW2_OL_MAIN_HEADER_BITNR = 0, QCOW2_OL_ACTIVE_L1_BITNR = 1, @@ -510,6 +594,49 @@ typedef enum QCow2MetadataOverlap { #define INV_OFFSET (-1ULL) +static inline bool has_subclusters(BDRVQcow2State *s) +{ + return s->incompatible_features & QCOW2_INCOMPAT_EXTL2; +} + +static inline size_t l2_entry_size(BDRVQcow2State *s) +{ + return has_subclusters(s) ? L2E_SIZE_EXTENDED : L2E_SIZE_NORMAL; +} + +static inline uint64_t get_l2_entry(BDRVQcow2State *s, uint64_t *l2_slice, + int idx) +{ + idx *= l2_entry_size(s) / sizeof(uint64_t); + return be64_to_cpu(l2_slice[idx]); +} + +static inline uint64_t get_l2_bitmap(BDRVQcow2State *s, uint64_t *l2_slice, + int idx) +{ + if (has_subclusters(s)) { + idx *= l2_entry_size(s) / sizeof(uint64_t); + return be64_to_cpu(l2_slice[idx + 1]); + } else { + return 0; /* For convenience only; this value has no meaning. */ + } +} + +static inline void set_l2_entry(BDRVQcow2State *s, uint64_t *l2_slice, + int idx, uint64_t entry) +{ + idx *= l2_entry_size(s) / sizeof(uint64_t); + l2_slice[idx] = cpu_to_be64(entry); +} + +static inline void set_l2_bitmap(BDRVQcow2State *s, uint64_t *l2_slice, + int idx, uint64_t bitmap) +{ + assert(has_subclusters(s)); + idx *= l2_entry_size(s) / sizeof(uint64_t); + l2_slice[idx + 1] = cpu_to_be64(bitmap); +} + static inline bool has_data_file(BlockDriverState *bs) { BDRVQcow2State *s = bs->opaque; @@ -532,11 +659,21 @@ static inline int64_t offset_into_cluster(BDRVQcow2State *s, int64_t offset) return offset & (s->cluster_size - 1); } +static inline int64_t offset_into_subcluster(BDRVQcow2State *s, int64_t offset) +{ + return offset & (s->subcluster_size - 1); +} + static inline uint64_t size_to_clusters(BDRVQcow2State *s, uint64_t size) { return (size + (s->cluster_size - 1)) >> s->cluster_bits; } +static inline uint64_t size_to_subclusters(BDRVQcow2State *s, uint64_t size) +{ + return (size + (s->subcluster_size - 1)) >> s->subcluster_bits; +} + static inline int64_t size_to_l1(BDRVQcow2State *s, int64_t size) { int shift = s->cluster_bits + s->l2_bits; @@ -558,6 +695,11 @@ static inline int offset_to_l2_slice_index(BDRVQcow2State *s, int64_t offset) return (offset >> s->cluster_bits) & (s->l2_slice_size - 1); } +static inline int offset_to_sc_index(BDRVQcow2State *s, int64_t offset) +{ + return (offset >> s->subcluster_bits) & (s->subclusters_per_cluster - 1); +} + static inline int64_t qcow2_vm_state_offset(BDRVQcow2State *s) { return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits); @@ -566,9 +708,11 @@ static inline int64_t qcow2_vm_state_offset(BDRVQcow2State *s) static inline QCow2ClusterType qcow2_get_cluster_type(BlockDriverState *bs, uint64_t l2_entry) { + BDRVQcow2State *s = bs->opaque; + if (l2_entry & QCOW_OFLAG_COMPRESSED) { return QCOW2_CLUSTER_COMPRESSED; - } else if (l2_entry & QCOW_OFLAG_ZERO) { + } else if ((l2_entry & QCOW_OFLAG_ZERO) && !has_subclusters(s)) { if (l2_entry & L2E_OFFSET_MASK) { return QCOW2_CLUSTER_ZERO_ALLOC; } @@ -588,6 +732,72 @@ static inline QCow2ClusterType qcow2_get_cluster_type(BlockDriverState *bs, } } +/* + * In an image without subsclusters @l2_bitmap is ignored and + * @sc_index must be 0. + * Return QCOW2_SUBCLUSTER_INVALID if an invalid l2 entry is detected + * (this checks the whole entry and bitmap, not only the bits related + * to subcluster @sc_index). + */ +static inline +QCow2SubclusterType qcow2_get_subcluster_type(BlockDriverState *bs, + uint64_t l2_entry, + uint64_t l2_bitmap, + unsigned sc_index) +{ + BDRVQcow2State *s = bs->opaque; + QCow2ClusterType type = qcow2_get_cluster_type(bs, l2_entry); + assert(sc_index < s->subclusters_per_cluster); + + if (has_subclusters(s)) { + switch (type) { + case QCOW2_CLUSTER_COMPRESSED: + return QCOW2_SUBCLUSTER_COMPRESSED; + case QCOW2_CLUSTER_NORMAL: + if ((l2_bitmap >> 32) & l2_bitmap) { + return QCOW2_SUBCLUSTER_INVALID; + } else if (l2_bitmap & QCOW_OFLAG_SUB_ZERO(sc_index)) { + return QCOW2_SUBCLUSTER_ZERO_ALLOC; + } else if (l2_bitmap & QCOW_OFLAG_SUB_ALLOC(sc_index)) { + return QCOW2_SUBCLUSTER_NORMAL; + } else { + return QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC; + } + case QCOW2_CLUSTER_UNALLOCATED: + if (l2_bitmap & QCOW_L2_BITMAP_ALL_ALLOC) { + return QCOW2_SUBCLUSTER_INVALID; + } else if (l2_bitmap & QCOW_OFLAG_SUB_ZERO(sc_index)) { + return QCOW2_SUBCLUSTER_ZERO_PLAIN; + } else { + return QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN; + } + default: + g_assert_not_reached(); + } + } else { + switch (type) { + case QCOW2_CLUSTER_COMPRESSED: + return QCOW2_SUBCLUSTER_COMPRESSED; + case QCOW2_CLUSTER_ZERO_PLAIN: + return QCOW2_SUBCLUSTER_ZERO_PLAIN; + case QCOW2_CLUSTER_ZERO_ALLOC: + return QCOW2_SUBCLUSTER_ZERO_ALLOC; + case QCOW2_CLUSTER_NORMAL: + return QCOW2_SUBCLUSTER_NORMAL; + case QCOW2_CLUSTER_UNALLOCATED: + return QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN; + default: + g_assert_not_reached(); + } + } +} + +static inline bool qcow2_cluster_is_allocated(QCow2ClusterType type) +{ + return (type == QCOW2_CLUSTER_COMPRESSED || type == QCOW2_CLUSTER_NORMAL || + type == QCOW2_CLUSTER_ZERO_ALLOC); +} + /* Check whether refcounts are eager or lazy */ static inline bool qcow2_need_accurate_refcounts(BDRVQcow2State *s) { @@ -657,8 +867,8 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size); void qcow2_free_clusters(BlockDriverState *bs, int64_t offset, int64_t size, enum qcow2_discard_type type); -void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry, - int nb_clusters, enum qcow2_discard_type type); +void qcow2_free_any_cluster(BlockDriverState *bs, uint64_t l2_entry, + enum qcow2_discard_type type); int qcow2_update_snapshot_refcount(BlockDriverState *bs, int64_t l1_table_offset, int l1_size, int addend); @@ -694,11 +904,12 @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index); int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num, uint8_t *buf, int nb_sectors, bool enc, Error **errp); -int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, - unsigned int *bytes, uint64_t *cluster_offset); -int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, - unsigned int *bytes, uint64_t *host_offset, - QCowL2Meta **m); +int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset, + unsigned int *bytes, uint64_t *host_offset, + QCow2SubclusterType *subcluster_type); +int qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset, + unsigned int *bytes, uint64_t *host_offset, + QCowL2Meta **m); int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, uint64_t offset, int compressed_size, @@ -709,8 +920,8 @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m); int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset, uint64_t bytes, enum qcow2_discard_type type, bool full_discard); -int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset, - uint64_t bytes, int flags); +int qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, + uint64_t bytes, int flags); int qcow2_expand_zero_clusters(BlockDriverState *bs, BlockDriverAmendStatusCB *status_cb, @@ -783,6 +994,8 @@ int qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name, Error **errp); bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs); +uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *bs, + uint32_t cluster_size); ssize_t coroutine_fn qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size, diff --git a/block/qed.c b/block/qed.c index c0c65015c76b1e9fde2ffcb649afb409220b9631..b27e7546cabd292aa51b1d315ec02b2851b8a18f 100644 --- a/block/qed.c +++ b/block/qed.c @@ -729,7 +729,6 @@ static int coroutine_fn bdrv_qed_co_create_opts(BlockDriver *drv, QDict *qdict; Visitor *v; BlockDriverState *bs = NULL; - Error *local_err = NULL; int ret; static const QDictRenames opt_renames[] = { @@ -749,9 +748,8 @@ static int coroutine_fn bdrv_qed_co_create_opts(BlockDriver *drv, } /* Create and open the file (protocol layer) */ - ret = bdrv_create_file(filename, opts, &local_err); + ret = bdrv_create_file(filename, opts, errp); if (ret < 0) { - error_propagate(errp, local_err); goto fail; } @@ -772,11 +770,9 @@ static int coroutine_fn bdrv_qed_co_create_opts(BlockDriver *drv, goto fail; } - visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); + visit_type_BlockdevCreateOptions(v, NULL, &create_options, errp); visit_free(v); - - if (local_err) { - error_propagate(errp, local_err); + if (!create_options) { ret = -EINVAL; goto fail; } @@ -849,56 +845,18 @@ static BDRVQEDState *acb_to_s(QEDAIOCB *acb) * @s: QED state * @pos: Byte position in device * @qiov: Destination I/O vector - * @backing_qiov: Possibly shortened copy of qiov, to be allocated here - * @cb: Completion function - * @opaque: User data for completion function * * This function reads qiov->size bytes starting at pos from the backing file. * If there is no backing file then zeroes are read. */ static int coroutine_fn qed_read_backing_file(BDRVQEDState *s, uint64_t pos, - QEMUIOVector *qiov, - QEMUIOVector **backing_qiov) + QEMUIOVector *qiov) { - uint64_t backing_length = 0; - size_t size; - int ret; - - /* If there is a backing file, get its length. Treat the absence of a - * backing file like a zero length backing file. - */ if (s->bs->backing) { - int64_t l = bdrv_getlength(s->bs->backing->bs); - if (l < 0) { - return l; - } - backing_length = l; - } - - /* Zero all sectors if reading beyond the end of the backing file */ - if (pos >= backing_length || - pos + qiov->size > backing_length) { - qemu_iovec_memset(qiov, 0, 0, qiov->size); - } - - /* Complete now if there are no backing file sectors to read */ - if (pos >= backing_length) { - return 0; - } - - /* If the read straddles the end of the backing file, shorten it */ - size = MIN((uint64_t)backing_length - pos, qiov->size); - - assert(*backing_qiov == NULL); - *backing_qiov = g_new(QEMUIOVector, 1); - qemu_iovec_init(*backing_qiov, qiov->niov); - qemu_iovec_concat(*backing_qiov, qiov, 0, size); - - BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO); - ret = bdrv_co_preadv(s->bs->backing, pos, size, *backing_qiov, 0); - if (ret < 0) { - return ret; + BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO); + return bdrv_co_preadv(s->bs->backing, pos, qiov->size, qiov, 0); } + qemu_iovec_memset(qiov, 0, 0, qiov->size); return 0; } @@ -915,7 +873,6 @@ static int coroutine_fn qed_copy_from_backing_file(BDRVQEDState *s, uint64_t offset) { QEMUIOVector qiov; - QEMUIOVector *backing_qiov = NULL; int ret; /* Skip copy entirely if there is no work to do */ @@ -925,13 +882,7 @@ static int coroutine_fn qed_copy_from_backing_file(BDRVQEDState *s, qemu_iovec_init_buf(&qiov, qemu_blockalign(s->bs, len), len); - ret = qed_read_backing_file(s, pos, &qiov, &backing_qiov); - - if (backing_qiov) { - qemu_iovec_destroy(backing_qiov); - g_free(backing_qiov); - backing_qiov = NULL; - } + ret = qed_read_backing_file(s, pos, &qiov); if (ret) { goto out; @@ -1339,8 +1290,7 @@ static int coroutine_fn qed_aio_read_data(void *opaque, int ret, qemu_iovec_memset(&acb->cur_qiov, 0, 0, acb->cur_qiov.size); r = 0; } else if (ret != QED_CLUSTER_FOUND) { - r = qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov, - &acb->backing_qiov); + r = qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov); } else { BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); r = bdrv_co_preadv(bs->file, offset, acb->cur_qiov.size, @@ -1365,12 +1315,6 @@ static int coroutine_fn qed_aio_next_io(QEDAIOCB *acb) while (1) { trace_qed_aio_next_io(s, acb, 0, acb->cur_pos + acb->cur_qiov.size); - if (acb->backing_qiov) { - qemu_iovec_destroy(acb->backing_qiov); - g_free(acb->backing_qiov); - acb->backing_qiov = NULL; - } - acb->qiov_offset += acb->cur_qiov.size; acb->cur_pos += acb->cur_qiov.size; qemu_iovec_reset(&acb->cur_qiov); @@ -1514,7 +1458,6 @@ static int bdrv_qed_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) memset(bdi, 0, sizeof(*bdi)); bdi->cluster_size = s->header.cluster_size; bdi->is_dirty = s->header.features & QED_F_NEED_CHECK; - bdi->unallocated_blocks_are_zero = true; return 0; } diff --git a/block/qed.h b/block/qed.h index 42c115d8220cc61a74ff50dede211ea033d421da..3d12bf78d4128356e62b9772ab8695f41f997d9b 100644 --- a/block/qed.h +++ b/block/qed.h @@ -140,7 +140,6 @@ typedef struct QEDAIOCB { /* Current cluster scatter-gather list */ QEMUIOVector cur_qiov; - QEMUIOVector *backing_qiov; uint64_t cur_pos; /* position on block device, in bytes */ uint64_t cur_cluster; /* cluster offset in image file */ unsigned int cur_nclusters; /* number of clusters being accessed */ diff --git a/block/quorum.c b/block/quorum.c index 7cf7ab15467441708e7b04e7bcba353afa26c671..b10fc2089e5e9e2d9dabd379e398d1b8aa9862fb 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -29,6 +29,8 @@ #define HASH_LENGTH 32 +#define INDEXSTR_LEN 32 + #define QUORUM_OPT_VOTE_THRESHOLD "vote-threshold" #define QUORUM_OPT_BLKVERIFY "blkverify" #define QUORUM_OPT_REWRITE "rewrite-corrupted" @@ -910,27 +912,25 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags, /* count how many different children are present */ s->num_children = qdict_array_entries(options, "children."); if (s->num_children < 0) { - error_setg(&local_err, "Option children is not a valid array"); + error_setg(errp, "Option children is not a valid array"); ret = -EINVAL; goto exit; } if (s->num_children < 1) { - error_setg(&local_err, - "Number of provided children must be 1 or more"); + error_setg(errp, "Number of provided children must be 1 or more"); ret = -EINVAL; goto exit; } opts = qemu_opts_create(&quorum_runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { + if (!qemu_opts_absorb_qdict(opts, options, errp)) { ret = -EINVAL; goto exit; } s->threshold = qemu_opt_get_number(opts, QUORUM_OPT_VOTE_THRESHOLD, 0); /* and validate it against s->num_children */ - ret = quorum_valid_threshold(s->threshold, s->num_children, &local_err); + ret = quorum_valid_threshold(s->threshold, s->num_children, errp); if (ret < 0) { goto exit; } @@ -943,7 +943,7 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags, -EINVAL, NULL); } if (ret < 0) { - error_setg(&local_err, "Please set read-pattern as fifo or quorum"); + error_setg(errp, "Please set read-pattern as fifo or quorum"); goto exit; } s->read_pattern = ret; @@ -951,7 +951,7 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags, if (s->read_pattern == QUORUM_READ_PATTERN_QUORUM) { s->is_blkverify = qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false); if (s->is_blkverify && (s->num_children != 2 || s->threshold != 2)) { - error_setg(&local_err, "blkverify=on can only be set if there are " + error_setg(errp, "blkverify=on can only be set if there are " "exactly two files and vote-threshold is 2"); ret = -EINVAL; goto exit; @@ -960,7 +960,7 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags, s->rewrite_corrupted = qemu_opt_get_bool(opts, QUORUM_OPT_REWRITE, false); if (s->rewrite_corrupted && s->is_blkverify) { - error_setg(&local_err, + error_setg(errp, "rewrite-corrupted=on cannot be used with blkverify=on"); ret = -EINVAL; goto exit; @@ -972,14 +972,15 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags, opened = g_new0(bool, s->num_children); for (i = 0; i < s->num_children; i++) { - char indexstr[32]; - ret = snprintf(indexstr, 32, "children.%d", i); - assert(ret < 32); + char indexstr[INDEXSTR_LEN]; + ret = snprintf(indexstr, INDEXSTR_LEN, "children.%d", i); + assert(ret < INDEXSTR_LEN); s->children[i] = bdrv_open_child(NULL, options, indexstr, bs, &child_of_bds, BDRV_CHILD_DATA, false, &local_err); if (local_err) { + error_propagate(errp, local_err); ret = -EINVAL; goto close_exit; } @@ -1005,8 +1006,6 @@ close_exit: g_free(opened); exit: qemu_opts_del(opts); - /* propagate error */ - error_propagate(errp, local_err); return ret; } @@ -1027,7 +1026,7 @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs, { BDRVQuorumState *s = bs->opaque; BdrvChild *child; - char indexstr[32]; + char indexstr[INDEXSTR_LEN]; int ret; if (s->is_blkverify) { @@ -1042,8 +1041,8 @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs, return; } - ret = snprintf(indexstr, 32, "children.%u", s->next_child_index); - if (ret < 0 || ret >= 32) { + ret = snprintf(indexstr, INDEXSTR_LEN, "children.%u", s->next_child_index); + if (ret < 0 || ret >= INDEXSTR_LEN) { error_setg(errp, "cannot generate child name"); return; } @@ -1071,6 +1070,7 @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child, Error **errp) { BDRVQuorumState *s = bs->opaque; + char indexstr[INDEXSTR_LEN]; int i; for (i = 0; i < s->num_children; i++) { @@ -1092,6 +1092,11 @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child, /* We know now that num_children > threshold, so blkverify must be false */ assert(!s->is_blkverify); + snprintf(indexstr, INDEXSTR_LEN, "children.%u", s->next_child_index - 1); + if (!strncmp(child->name, indexstr, INDEXSTR_LEN)) { + s->next_child_index--; + } + bdrv_drained_begin(bs); /* We can safely remove this child now */ @@ -1158,7 +1163,12 @@ static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c, uint64_t perm, uint64_t shared, uint64_t *nperm, uint64_t *nshared) { + BDRVQuorumState *s = bs->opaque; + *nperm = perm & DEFAULT_PERM_PASSTHROUGH; + if (s->rewrite_corrupted) { + *nperm |= BLK_PERM_WRITE; + } /* * We cannot share RESIZE or WRITE, as this would make the diff --git a/block/raw-format.c b/block/raw-format.c index 018441bddf2795df66b378f24e5478092ae84051..42ec50802bcdbbec43e9a8997956f7c7d13c8faf 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -74,14 +74,11 @@ static QemuOptsList raw_create_opts = { static int raw_read_options(QDict *options, uint64_t *offset, bool *has_size, uint64_t *size, Error **errp) { - Error *local_err = NULL; QemuOpts *opts = NULL; int ret; opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { ret = -EINVAL; goto end; } @@ -359,7 +356,7 @@ static BlockMeasureInfo *raw_measure(QemuOpts *opts, BlockDriverState *in_bs, BDRV_SECTOR_SIZE); } - info = g_new(BlockMeasureInfo, 1); + info = g_new0(BlockMeasureInfo, 1); info->required = required; /* Unallocated sectors count towards the file size in raw images */ diff --git a/block/rbd.c b/block/rbd.c index 617553b022c73728b98bfb694b2ffab9e05e4554..9bd2bce71651b8612e37c5dc040da04f7ae1a520 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -341,48 +341,6 @@ static void qemu_rbd_memset(RADOSCB *rcb, int64_t offs) } } -static QemuOptsList runtime_opts = { - .name = "rbd", - .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), - .desc = { - { - .name = "pool", - .type = QEMU_OPT_STRING, - .help = "Rados pool name", - }, - { - .name = "namespace", - .type = QEMU_OPT_STRING, - .help = "Rados namespace name in the pool", - }, - { - .name = "image", - .type = QEMU_OPT_STRING, - .help = "Image name in the pool", - }, - { - .name = "conf", - .type = QEMU_OPT_STRING, - .help = "Rados config file location", - }, - { - .name = "snapshot", - .type = QEMU_OPT_STRING, - .help = "Ceph snapshot name", - }, - { - /* maps to 'id' in rados_create() */ - .name = "user", - .type = QEMU_OPT_STRING, - .help = "Rados id name", - }, - /* - * server.* extracted manually, see qemu_rbd_mon_host() - */ - { /* end of list */ } - }, -}; - /* FIXME Deprecate and remove keypairs or make it available in QMP. */ static int qemu_rbd_do_create(BlockdevCreateOptions *options, const char *keypairs, const char *password_secret, @@ -681,7 +639,6 @@ static int qemu_rbd_convert_options(QDict *options, BlockdevOptionsRbd **opts, Error **errp) { Visitor *v; - Error *local_err = NULL; /* Convert the remaining options into a QAPI object */ v = qobject_input_visitor_new_flat_confused(options, errp); @@ -689,11 +646,9 @@ static int qemu_rbd_convert_options(QDict *options, BlockdevOptionsRbd **opts, return -EINVAL; } - visit_type_BlockdevOptionsRbd(v, NULL, opts, &local_err); + visit_type_BlockdevOptionsRbd(v, NULL, opts, errp); visit_free(v); - - if (local_err) { - error_propagate(errp, local_err); + if (!opts) { return -EINVAL; } @@ -1292,6 +1247,7 @@ static QemuOptsList qemu_rbd_create_opts = { static const char *const qemu_rbd_strong_runtime_opts[] = { "pool", + "namespace", "image", "conf", "snapshot", diff --git a/block/replication.c b/block/replication.c index ccf7b781607e793953da0c1a0ad21c247bf8b491..0c70215784da9cd4516919f25928f55a06679c41 100644 --- a/block/replication.c +++ b/block/replication.c @@ -85,7 +85,6 @@ static int replication_open(BlockDriverState *bs, QDict *options, { int ret; BDRVReplicationState *s = bs->opaque; - Error *local_err = NULL; QemuOpts *opts = NULL; const char *mode; const char *top_id; @@ -99,14 +98,13 @@ static int replication_open(BlockDriverState *bs, QDict *options, ret = -EINVAL; opts = qemu_opts_create(&replication_runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { + if (!qemu_opts_absorb_qdict(opts, options, errp)) { goto fail; } mode = qemu_opt_get(opts, REPLICATION_MODE); if (!mode) { - error_setg(&local_err, "Missing the option mode"); + error_setg(errp, "Missing the option mode"); goto fail; } @@ -114,7 +112,8 @@ static int replication_open(BlockDriverState *bs, QDict *options, s->mode = REPLICATION_MODE_PRIMARY; top_id = qemu_opt_get(opts, REPLICATION_TOP_ID); if (top_id) { - error_setg(&local_err, "The primary side does not support option top-id"); + error_setg(errp, + "The primary side does not support option top-id"); goto fail; } } else if (!strcmp(mode, "secondary")) { @@ -122,11 +121,11 @@ static int replication_open(BlockDriverState *bs, QDict *options, top_id = qemu_opt_get(opts, REPLICATION_TOP_ID); s->top_id = g_strdup(top_id); if (!s->top_id) { - error_setg(&local_err, "Missing the option top-id"); + error_setg(errp, "Missing the option top-id"); goto fail; } } else { - error_setg(&local_err, + error_setg(errp, "The option mode's value should be primary or secondary"); goto fail; } @@ -137,8 +136,6 @@ static int replication_open(BlockDriverState *bs, QDict *options, fail: qemu_opts_del(opts); - error_propagate(errp, local_err); - return ret; } @@ -369,7 +366,6 @@ static void reopen_backing_file(BlockDriverState *bs, bool writable, { BDRVReplicationState *s = bs->opaque; BlockReopenQueue *reopen_queue = NULL; - Error *local_err = NULL; if (writable) { s->orig_hidden_read_only = bdrv_is_read_only(s->hidden_disk->bs); @@ -394,8 +390,7 @@ static void reopen_backing_file(BlockDriverState *bs, bool writable, } if (reopen_queue) { - bdrv_reopen_multiple(reopen_queue, &local_err); - error_propagate(errp, local_err); + bdrv_reopen_multiple(reopen_queue, errp); } bdrv_subtree_drained_end(s->hidden_disk->bs); diff --git a/block/sheepdog.c b/block/sheepdog.c index 27a30d17f4c9d3103a74b8c4145d600bb070f2f0..a45c73826d4da92646e65a672acd968eb8a1df3f 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -242,6 +242,16 @@ typedef struct SheepdogInode { */ #define FNV1A_64_INIT ((uint64_t)0xcbf29ce484222325ULL) +static void deprecation_warning(void) +{ + static bool warned; + + if (!warned) { + warn_report("the sheepdog block driver is deprecated"); + warned = true; + } +} + /* * 64 bit Fowler/Noll/Vo FNV-1a hash code */ @@ -532,7 +542,6 @@ static SocketAddress *sd_server_config(QDict *options, Error **errp) QDict *server = NULL; Visitor *iv = NULL; SocketAddress *saddr = NULL; - Error *local_err = NULL; qdict_extract_subqdict(options, &server, "server."); @@ -541,9 +550,7 @@ static SocketAddress *sd_server_config(QDict *options, Error **errp) goto done; } - visit_type_SocketAddress(iv, NULL, &saddr, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_SocketAddress(iv, NULL, &saddr, errp)) { goto done; } @@ -668,7 +675,7 @@ out: srco->co = NULL; srco->ret = ret; /* Set srco->finished before reading bs->wakeup. */ - atomic_mb_set(&srco->finished, true); + qatomic_mb_set(&srco->finished, true); if (srco->bs) { bdrv_wakeup(srco->bs); } @@ -743,7 +750,7 @@ static coroutine_fn void reconnect_to_sdog(void *opaque) if (s->fd < 0) { trace_sheepdog_reconnect_to_sdog(); error_report_err(local_err); - qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 1000000000ULL); + qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, NANOSECONDS_PER_SECOND); } }; @@ -1550,15 +1557,14 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags, uint64_t snap_id; char *buf = NULL; QemuOpts *opts; - Error *local_err = NULL; + + deprecation_warning(); s->bs = bs; s->aio_context = bdrv_get_aio_context(bs); opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { ret = -EINVAL; goto err_no_fd; } @@ -2013,6 +2019,8 @@ static int sd_co_create(BlockdevCreateOptions *options, Error **errp) assert(options->driver == BLOCKDEV_DRIVER_SHEEPDOG); + deprecation_warning(); + s = g_new0(BDRVSheepdogState, 1); /* Steal SocketAddress from QAPI, set NULL to prevent double free */ @@ -2157,13 +2165,21 @@ static int coroutine_fn sd_co_create_opts(BlockDriver *drv, Error **errp) { BlockdevCreateOptions *create_options = NULL; - QDict *qdict, *location_qdict; + QDict *qdict = NULL, *location_qdict; Visitor *v; - char *redundancy; + char *redundancy = NULL; Error *local_err = NULL; int ret; + char *backing_fmt = NULL; redundancy = qemu_opt_get_del(opts, BLOCK_OPT_REDUNDANCY); + backing_fmt = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FMT); + + if (backing_fmt && strcmp(backing_fmt, "sheepdog") != 0) { + error_setg(errp, "backing_file must be a sheepdog image"); + ret = -EINVAL; + goto fail; + } qdict = qemu_opts_to_qdict(opts, NULL); qdict_put_str(qdict, "driver", "sheepdog"); @@ -2199,11 +2215,9 @@ static int coroutine_fn sd_co_create_opts(BlockDriver *drv, goto fail; } - visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); + visit_type_BlockdevCreateOptions(v, NULL, &create_options, errp); visit_free(v); - - if (local_err) { - error_propagate(errp, local_err); + if (!create_options) { ret = -EINVAL; goto fail; } @@ -2228,6 +2242,7 @@ fail: qapi_free_BlockdevCreateOptions(create_options); qobject_unref(qdict); g_free(redundancy); + g_free(backing_fmt); return ret; } @@ -3185,6 +3200,11 @@ static QemuOptsList sd_create_opts = { .type = QEMU_OPT_STRING, .help = "File name of a base image" }, + { + .name = BLOCK_OPT_BACKING_FMT, + .type = QEMU_OPT_STRING, + .help = "Must be 'sheepdog' if present", + }, { .name = BLOCK_OPT_PREALLOC, .type = QEMU_OPT_STRING, diff --git a/block/snapshot.c b/block/snapshot.c index bd9fb01817d86ed15cd4c6d7f37fcd07e35849d8..a2bf3a54eb08f09e2c0fa837b1282906bae410d2 100644 --- a/block/snapshot.c +++ b/block/snapshot.c @@ -147,6 +147,56 @@ bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs, return ret; } +/** + * Return a pointer to the child BDS pointer to which we can fall + * back if the given BDS does not support snapshots. + * Return NULL if there is no BDS to (safely) fall back to. + * + * We need to return an indirect pointer because bdrv_snapshot_goto() + * has to modify the BdrvChild pointer. + */ +static BdrvChild **bdrv_snapshot_fallback_ptr(BlockDriverState *bs) +{ + BdrvChild **fallback; + BdrvChild *child; + + /* + * The only BdrvChild pointers that are safe to modify (and which + * we can thus return a reference to) are bs->file and + * bs->backing. + */ + fallback = &bs->file; + if (!*fallback && bs->drv && bs->drv->is_filter) { + fallback = &bs->backing; + } + + if (!*fallback) { + return NULL; + } + + /* + * Check that there are no other children that would need to be + * snapshotted. If there are, it is not safe to fall back to + * *fallback. + */ + QLIST_FOREACH(child, &bs->children, next) { + if (child->role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA | + BDRV_CHILD_FILTERED) && + child != *fallback) + { + return NULL; + } + } + + return fallback; +} + +static BlockDriverState *bdrv_snapshot_fallback(BlockDriverState *bs) +{ + BdrvChild **child_ptr = bdrv_snapshot_fallback_ptr(bs); + return child_ptr ? (*child_ptr)->bs : NULL; +} + int bdrv_can_snapshot(BlockDriverState *bs) { BlockDriver *drv = bs->drv; @@ -155,8 +205,9 @@ int bdrv_can_snapshot(BlockDriverState *bs) } if (!drv->bdrv_snapshot_create) { - if (bs->file != NULL) { - return bdrv_can_snapshot(bs->file->bs); + BlockDriverState *fallback_bs = bdrv_snapshot_fallback(bs); + if (fallback_bs) { + return bdrv_can_snapshot(fallback_bs); } return 0; } @@ -168,14 +219,15 @@ int bdrv_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) { BlockDriver *drv = bs->drv; + BlockDriverState *fallback_bs = bdrv_snapshot_fallback(bs); if (!drv) { return -ENOMEDIUM; } if (drv->bdrv_snapshot_create) { return drv->bdrv_snapshot_create(bs, sn_info); } - if (bs->file) { - return bdrv_snapshot_create(bs->file->bs, sn_info); + if (fallback_bs) { + return bdrv_snapshot_create(fallback_bs, sn_info); } return -ENOTSUP; } @@ -185,6 +237,7 @@ int bdrv_snapshot_goto(BlockDriverState *bs, Error **errp) { BlockDriver *drv = bs->drv; + BdrvChild **fallback_ptr; int ret, open_ret; if (!drv) { @@ -205,39 +258,46 @@ int bdrv_snapshot_goto(BlockDriverState *bs, return ret; } - if (bs->file) { - BlockDriverState *file; - QDict *options = qdict_clone_shallow(bs->options); + fallback_ptr = bdrv_snapshot_fallback_ptr(bs); + if (fallback_ptr) { + QDict *options; QDict *file_options; Error *local_err = NULL; + BlockDriverState *fallback_bs = (*fallback_ptr)->bs; + char *subqdict_prefix = g_strdup_printf("%s.", (*fallback_ptr)->name); + + options = qdict_clone_shallow(bs->options); - file = bs->file->bs; /* Prevent it from getting deleted when detached from bs */ - bdrv_ref(file); + bdrv_ref(fallback_bs); - qdict_extract_subqdict(options, &file_options, "file."); + qdict_extract_subqdict(options, &file_options, subqdict_prefix); qobject_unref(file_options); - qdict_put_str(options, "file", bdrv_get_node_name(file)); + g_free(subqdict_prefix); + + qdict_put_str(options, (*fallback_ptr)->name, + bdrv_get_node_name(fallback_bs)); if (drv->bdrv_close) { drv->bdrv_close(bs); } - bdrv_unref_child(bs, bs->file); - bs->file = NULL; - ret = bdrv_snapshot_goto(file, snapshot_id, errp); + bdrv_unref_child(bs, *fallback_ptr); + *fallback_ptr = NULL; + + ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp); open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err); qobject_unref(options); if (open_ret < 0) { - bdrv_unref(file); + bdrv_unref(fallback_bs); bs->drv = NULL; /* A bdrv_snapshot_goto() error takes precedence */ error_propagate(errp, local_err); return ret < 0 ? ret : open_ret; } - assert(bs->file->bs == file); - bdrv_unref(file); + assert(fallback_bs == (*fallback_ptr)->bs); + bdrv_unref(fallback_bs); return ret; } @@ -273,6 +333,7 @@ int bdrv_snapshot_delete(BlockDriverState *bs, Error **errp) { BlockDriver *drv = bs->drv; + BlockDriverState *fallback_bs = bdrv_snapshot_fallback(bs); int ret; if (!drv) { @@ -289,8 +350,8 @@ int bdrv_snapshot_delete(BlockDriverState *bs, if (drv->bdrv_snapshot_delete) { ret = drv->bdrv_snapshot_delete(bs, snapshot_id, name, errp); - } else if (bs->file) { - ret = bdrv_snapshot_delete(bs->file->bs, snapshot_id, name, errp); + } else if (fallback_bs) { + ret = bdrv_snapshot_delete(fallback_bs, snapshot_id, name, errp); } else { error_setg(errp, "Block format '%s' used by device '%s' " "does not support internal snapshot deletion", @@ -306,14 +367,15 @@ int bdrv_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_info) { BlockDriver *drv = bs->drv; + BlockDriverState *fallback_bs = bdrv_snapshot_fallback(bs); if (!drv) { return -ENOMEDIUM; } if (drv->bdrv_snapshot_list) { return drv->bdrv_snapshot_list(bs, psn_info); } - if (bs->file) { - return bdrv_snapshot_list(bs->file->bs, psn_info); + if (fallback_bs) { + return bdrv_snapshot_list(fallback_bs, psn_info); } return -ENOTSUP; } diff --git a/block/ssh.c b/block/ssh.c index 098dbe03c15b8bf81246ad1a5cde1589eb4f275b..ebe3d8b631ffc91eeaf66e2627301597db83d23e 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -616,15 +616,12 @@ static BlockdevOptionsSsh *ssh_parse_options(QDict *options, Error **errp) { BlockdevOptionsSsh *result = NULL; QemuOpts *opts = NULL; - Error *local_err = NULL; const QDictEntry *e; Visitor *v; /* Translate legacy options */ opts = qemu_opts_create(&ssh_runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { goto fail; } @@ -638,11 +635,9 @@ static BlockdevOptionsSsh *ssh_parse_options(QDict *options, Error **errp) goto fail; } - visit_type_BlockdevOptionsSsh(v, NULL, &result, &local_err); + visit_type_BlockdevOptionsSsh(v, NULL, &result, errp); visit_free(v); - - if (local_err) { - error_propagate(errp, local_err); + if (!result) { goto fail; } diff --git a/block/stream.c b/block/stream.c index aa2e7af98e37747526efbba6ef1120294e6abc55..236384f2f739125b8e1f2a4632fa1c99699a78ca 100644 --- a/block/stream.c +++ b/block/stream.c @@ -31,7 +31,8 @@ enum { typedef struct StreamBlockJob { BlockJob common; - BlockDriverState *bottom; + BlockDriverState *base_overlay; /* COW overlay (stream from this) */ + BlockDriverState *above_base; /* Node directly above the base */ BlockdevOnError on_error; char *backing_file_str; bool bs_read_only; @@ -53,7 +54,7 @@ static void stream_abort(Job *job) if (s->chain_frozen) { BlockJob *bjob = &s->common; - bdrv_unfreeze_backing_chain(blk_bs(bjob->blk), s->bottom); + bdrv_unfreeze_backing_chain(blk_bs(bjob->blk), s->above_base); } } @@ -62,14 +63,15 @@ static int stream_prepare(Job *job) StreamBlockJob *s = container_of(job, StreamBlockJob, common.job); BlockJob *bjob = &s->common; BlockDriverState *bs = blk_bs(bjob->blk); - BlockDriverState *base = backing_bs(s->bottom); + BlockDriverState *unfiltered_bs = bdrv_skip_filters(bs); + BlockDriverState *base = bdrv_filter_or_cow_bs(s->above_base); Error *local_err = NULL; int ret = 0; - bdrv_unfreeze_backing_chain(bs, s->bottom); + bdrv_unfreeze_backing_chain(bs, s->above_base); s->chain_frozen = false; - if (bs->backing) { + if (bdrv_cow_child(unfiltered_bs)) { const char *base_id = NULL, *base_fmt = NULL; if (base) { base_id = s->backing_file_str; @@ -77,8 +79,8 @@ static int stream_prepare(Job *job) base_fmt = base->drv->format_name; } } - bdrv_set_backing_hd(bs, base, &local_err); - ret = bdrv_change_backing_file(bs, base_id, base_fmt); + bdrv_set_backing_hd(unfiltered_bs, base, &local_err); + ret = bdrv_change_backing_file(unfiltered_bs, base_id, base_fmt, false); if (local_err) { error_report_err(local_err); return -EPERM; @@ -109,14 +111,15 @@ static int coroutine_fn stream_run(Job *job, Error **errp) StreamBlockJob *s = container_of(job, StreamBlockJob, common.job); BlockBackend *blk = s->common.blk; BlockDriverState *bs = blk_bs(blk); - bool enable_cor = !backing_bs(s->bottom); + BlockDriverState *unfiltered_bs = bdrv_skip_filters(bs); + bool enable_cor = !bdrv_cow_child(s->base_overlay); int64_t len; int64_t offset = 0; uint64_t delay_ns = 0; int error = 0; int64_t n = 0; /* bytes */ - if (bs == s->bottom) { + if (unfiltered_bs == s->base_overlay) { /* Nothing to stream */ return 0; } @@ -150,20 +153,21 @@ static int coroutine_fn stream_run(Job *job, Error **errp) copy = false; - ret = bdrv_is_allocated(bs, offset, STREAM_CHUNK, &n); + ret = bdrv_is_allocated(unfiltered_bs, offset, STREAM_CHUNK, &n); if (ret == 1) { /* Allocated in the top, no need to copy. */ } else if (ret >= 0) { /* Copy if allocated in the intermediate images. Limit to the * known-unallocated area [offset, offset+n*BDRV_SECTOR_SIZE). */ - ret = bdrv_is_allocated_above(backing_bs(bs), s->bottom, true, + ret = bdrv_is_allocated_above(bdrv_cow_bs(unfiltered_bs), + s->base_overlay, true, offset, n, &n); /* Finish early if end of backing file has been reached */ if (ret == 0 && n == 0) { n = len - offset; } - copy = (ret == 1); + copy = (ret > 0); } trace_stream_one_iteration(s, offset, n, ret); if (copy) { @@ -223,9 +227,29 @@ void stream_start(const char *job_id, BlockDriverState *bs, BlockDriverState *iter; bool bs_read_only; int basic_flags = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED; - BlockDriverState *bottom = bdrv_find_overlay(bs, base); + BlockDriverState *base_overlay = bdrv_find_overlay(bs, base); + BlockDriverState *above_base; - if (bdrv_freeze_backing_chain(bs, bottom, errp) < 0) { + if (!base_overlay) { + error_setg(errp, "'%s' is not in the backing chain of '%s'", + base->node_name, bs->node_name); + return; + } + + /* + * Find the node directly above @base. @base_overlay is a COW overlay, so + * it must have a bdrv_cow_child(), but it is the immediate overlay of + * @base, so between the two there can only be filters. + */ + above_base = base_overlay; + if (bdrv_cow_bs(above_base) != base) { + above_base = bdrv_cow_bs(above_base); + while (bdrv_filter_bs(above_base) != base) { + above_base = bdrv_filter_bs(above_base); + } + } + + if (bdrv_freeze_backing_chain(bs, above_base, errp) < 0) { return; } @@ -255,14 +279,19 @@ void stream_start(const char *job_id, BlockDriverState *bs, * and resizes. Reassign the base node pointer because the backing BS of the * bottom node might change after the call to bdrv_reopen_set_read_only() * due to parallel block jobs running. + * above_base node might change after the call to + * bdrv_reopen_set_read_only() due to parallel block jobs running. */ - base = backing_bs(bottom); - for (iter = backing_bs(bs); iter && iter != base; iter = backing_bs(iter)) { + base = bdrv_filter_or_cow_bs(above_base); + for (iter = bdrv_filter_or_cow_bs(bs); iter != base; + iter = bdrv_filter_or_cow_bs(iter)) + { block_job_add_bdrv(&s->common, "intermediate node", iter, 0, basic_flags, &error_abort); } - s->bottom = bottom; + s->base_overlay = base_overlay; + s->above_base = above_base; s->backing_file_str = g_strdup(backing_file_str); s->bs_read_only = bs_read_only; s->chain_frozen = true; @@ -276,5 +305,5 @@ fail: if (bs_read_only) { bdrv_reopen_set_read_only(bs, true, NULL); } - bdrv_unfreeze_backing_chain(bs, bottom); + bdrv_unfreeze_backing_chain(bs, above_base); } diff --git a/block/throttle-groups.c b/block/throttle-groups.c index 784fa4a16c39e58e6a1eab7dc6934d1c6573a526..e2f2813c0fcda64a6ec8a2d7e20f2652651d645a 100644 --- a/block/throttle-groups.c +++ b/block/throttle-groups.c @@ -63,7 +63,7 @@ static void timer_cb(ThrottleGroupMember *tgm, bool is_write); * access some other ThrottleGroupMember's timers only after verifying that * that ThrottleGroupMember has throttled requests in the queue. */ -typedef struct ThrottleGroup { +struct ThrottleGroup { Object parent_obj; /* refuse individual property change if initialization is complete */ @@ -79,7 +79,7 @@ typedef struct ThrottleGroup { /* This field is protected by the global QEMU mutex */ QTAILQ_ENTRY(ThrottleGroup) list; -} ThrottleGroup; +}; /* This is protected by the global QEMU mutex */ static QTAILQ_HEAD(, ThrottleGroup) throttle_groups = @@ -228,7 +228,7 @@ static ThrottleGroupMember *next_throttle_token(ThrottleGroupMember *tgm, * immediately if it has pending requests. Otherwise we could be * forcing it to wait for other member's throttled requests. */ if (tgm_has_pending_reqs(tgm, is_write) && - atomic_read(&tgm->io_limits_disabled)) { + qatomic_read(&tgm->io_limits_disabled)) { return tgm; } @@ -272,7 +272,7 @@ static bool throttle_group_schedule_timer(ThrottleGroupMember *tgm, ThrottleTimers *tt = &tgm->throttle_timers; bool must_wait; - if (atomic_read(&tgm->io_limits_disabled)) { + if (qatomic_read(&tgm->io_limits_disabled)) { return false; } @@ -417,7 +417,7 @@ static void coroutine_fn throttle_group_restart_queue_entry(void *opaque) g_free(data); - atomic_dec(&tgm->restart_pending); + qatomic_dec(&tgm->restart_pending); aio_wait_kick(); } @@ -434,7 +434,7 @@ static void throttle_group_restart_queue(ThrottleGroupMember *tgm, bool is_write * be no timer pending on this tgm at this point */ assert(!timer_pending(tgm->throttle_timers.timers[is_write])); - atomic_inc(&tgm->restart_pending); + qatomic_inc(&tgm->restart_pending); co = qemu_coroutine_create(throttle_group_restart_queue_entry, rd); aio_co_enter(tgm->aio_context, co); @@ -544,7 +544,7 @@ void throttle_group_register_tgm(ThrottleGroupMember *tgm, tgm->throttle_state = ts; tgm->aio_context = ctx; - atomic_set(&tgm->restart_pending, 0); + qatomic_set(&tgm->restart_pending, 0); qemu_mutex_lock(&tg->lock); /* If the ThrottleGroup is new set this ThrottleGroupMember as the token */ @@ -592,7 +592,7 @@ void throttle_group_unregister_tgm(ThrottleGroupMember *tgm) } /* Wait for throttle_group_restart_queue_entry() coroutines to finish */ - AIO_WAIT_WHILE(tgm->aio_context, atomic_read(&tgm->restart_pending) > 0); + AIO_WAIT_WHILE(tgm->aio_context, qatomic_read(&tgm->restart_pending) > 0); qemu_mutex_lock(&tg->lock); for (i = 0; i < 2; i++) { @@ -771,7 +771,7 @@ static void throttle_group_obj_complete(UserCreatable *obj, Error **errp) /* set group name to object id if it exists */ if (!tg->name && tg->parent_obj.parent) { - tg->name = object_get_canonical_path_component(OBJECT(obj)); + tg->name = g_strdup(object_get_canonical_path_component(OBJECT(obj))); } /* We must have a group name at this point */ assert(tg->name); @@ -811,7 +811,6 @@ static void throttle_group_set(Object *obj, Visitor *v, const char * name, ThrottleGroup *tg = THROTTLE_GROUP(obj); ThrottleConfig *cfg; ThrottleParamInfo *info = opaque; - Error *local_err = NULL; int64_t value; /* If we have finished initialization, don't accept individual property @@ -819,17 +818,16 @@ static void throttle_group_set(Object *obj, Visitor *v, const char * name, * transaction, as certain combinations are invalid. */ if (tg->is_initialized) { - error_setg(&local_err, "Property cannot be set after initialization"); - goto ret; + error_setg(errp, "Property cannot be set after initialization"); + return; } - visit_type_int64(v, name, &value, &local_err); - if (local_err) { - goto ret; + if (!visit_type_int64(v, name, &value, errp)) { + return; } if (value < 0) { - error_setg(&local_err, "Property values cannot be negative"); - goto ret; + error_setg(errp, "Property values cannot be negative"); + return; } cfg = &tg->ts.cfg; @@ -842,9 +840,9 @@ static void throttle_group_set(Object *obj, Visitor *v, const char * name, break; case BURST_LENGTH: if (value > UINT_MAX) { - error_setg(&local_err, "%s value must be in the" - "range [0, %u]", info->name, UINT_MAX); - goto ret; + error_setg(errp, "%s value must be in the" "range [0, %u]", + info->name, UINT_MAX); + return; } cfg->buckets[info->type].burst_length = value; break; @@ -852,11 +850,6 @@ static void throttle_group_set(Object *obj, Visitor *v, const char * name, cfg->op_size = value; break; } - -ret: - error_propagate(errp, local_err); - return; - } static void throttle_group_get(Object *obj, Visitor *v, const char *name, @@ -896,9 +889,8 @@ static void throttle_group_set_limits(Object *obj, Visitor *v, ThrottleLimits *argp; Error *local_err = NULL; - visit_type_ThrottleLimits(v, name, &argp, &local_err); - if (local_err) { - goto ret; + if (!visit_type_ThrottleLimits(v, name, &argp, errp)) { + return; } qemu_mutex_lock(&tg->lock); throttle_get_config(&tg->ts, &cfg); @@ -910,7 +902,6 @@ static void throttle_group_set_limits(Object *obj, Visitor *v, unlock: qemu_mutex_unlock(&tg->lock); -ret: qapi_free_ThrottleLimits(argp); error_propagate(errp, local_err); return; diff --git a/block/throttle.c b/block/throttle.c index 0ebbad074392b2c8a089a9b8ffb8f8db5b14a46a..b685166ad4a940a059f06269daddd726b08038ad 100644 --- a/block/throttle.c +++ b/block/throttle.c @@ -46,12 +46,9 @@ static int throttle_parse_options(QDict *options, char **group, Error **errp) { int ret; const char *group_name; - Error *local_err = NULL; QemuOpts *opts = qemu_opts_create(&throttle_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { ret = -EINVAL; goto fin; } @@ -154,6 +151,15 @@ static int coroutine_fn throttle_co_pdiscard(BlockDriverState *bs, return bdrv_co_pdiscard(bs->file, offset, bytes); } +static int coroutine_fn throttle_co_pwritev_compressed(BlockDriverState *bs, + uint64_t offset, + uint64_t bytes, + QEMUIOVector *qiov) +{ + return throttle_co_pwritev(bs, offset, bytes, qiov, + BDRV_REQ_WRITE_COMPRESSED); +} + static int throttle_co_flush(BlockDriverState *bs) { return bdrv_co_flush(bs->file->bs); @@ -211,7 +217,7 @@ static void throttle_reopen_abort(BDRVReopenState *reopen_state) static void coroutine_fn throttle_co_drain_begin(BlockDriverState *bs) { ThrottleGroupMember *tgm = bs->opaque; - if (atomic_fetch_inc(&tgm->io_limits_disabled) == 0) { + if (qatomic_fetch_inc(&tgm->io_limits_disabled) == 0) { throttle_group_restart_tgm(tgm); } } @@ -220,7 +226,7 @@ static void coroutine_fn throttle_co_drain_end(BlockDriverState *bs) { ThrottleGroupMember *tgm = bs->opaque; assert(tgm->io_limits_disabled); - atomic_dec(&tgm->io_limits_disabled); + qatomic_dec(&tgm->io_limits_disabled); } static const char *const throttle_strong_runtime_opts[] = { @@ -246,6 +252,7 @@ static BlockDriver bdrv_throttle = { .bdrv_co_pwrite_zeroes = throttle_co_pwrite_zeroes, .bdrv_co_pdiscard = throttle_co_pdiscard, + .bdrv_co_pwritev_compressed = throttle_co_pwritev_compressed, .bdrv_attach_aio_context = throttle_attach_aio_context, .bdrv_detach_aio_context = throttle_detach_aio_context, @@ -253,7 +260,6 @@ static BlockDriver bdrv_throttle = { .bdrv_reopen_prepare = throttle_reopen_prepare, .bdrv_reopen_commit = throttle_reopen_commit, .bdrv_reopen_abort = throttle_reopen_abort, - .bdrv_co_block_status = bdrv_co_block_status_from_file, .bdrv_co_drain_begin = throttle_co_drain_begin, .bdrv_co_drain_end = throttle_co_drain_end, diff --git a/block/trace-events b/block/trace-events index 29dff8881cca9f89cb00d4c773fae042b284880b..8368f4acb0bba73b1b407c722483d36adba89549 100644 --- a/block/trace-events +++ b/block/trace-events @@ -42,7 +42,6 @@ backup_do_cow_enter(void *job, int64_t start, int64_t offset, uint64_t bytes) "j backup_do_cow_return(void *job, int64_t offset, uint64_t bytes, int ret) "job %p offset %" PRId64 " bytes %" PRIu64 " ret %d" # block-copy.c -block_copy_skip(void *bcs, int64_t start) "bcs %p start %"PRId64 block_copy_skip_range(void *bcs, int64_t start, uint64_t bytes) "bcs %p start %"PRId64" bytes %"PRId64 block_copy_process(void *bcs, int64_t start) "bcs %p start %"PRId64 block_copy_copy_range_fail(void *bcs, int64_t start, int ret) "bcs %p start %"PRId64" ret %d" @@ -59,12 +58,10 @@ qmp_block_job_finalize(void *job) "job %p" qmp_block_job_dismiss(void *job) "job %p" qmp_block_stream(void *bs) "bs %p" -# file-posix.c # file-win32.c file_paio_submit(void *acb, void *opaque, int64_t offset, int count, int type) "acb %p opaque %p offset %"PRId64" count %d type %d" -file_copy_file_range(void *bs, int src, int64_t src_off, int dst, int64_t dst_off, int64_t bytes, int flags, int64_t ret) "bs %p src_fd %d offset %"PRIu64" dst_fd %d offset %"PRIu64" bytes %"PRIu64" flags %d ret %"PRId64 -#io_uring.c +# io_uring.c luring_init_state(void *s, size_t size) "s %p size %zu" luring_cleanup_state(void *s) "%p freed" luring_io_plug(void *s) "LuringState %p plug" @@ -77,7 +74,7 @@ luring_io_uring_submit(void *s, int ret) "LuringState %p ret %d" luring_resubmit_short_read(void *s, void *luringcb, int nread) "LuringState %p luringcb %p nread %d" # qcow2.c -qcow2_add_task(void *co, void *bs, void *pool, const char *action, int cluster_type, uint64_t file_cluster_offset, uint64_t offset, uint64_t bytes, void *qiov, size_t qiov_offset) "co %p bs %p pool %p: %s: cluster_type %d file_cluster_offset %" PRIu64 " offset %" PRIu64 " bytes %" PRIu64 " qiov %p qiov_offset %zu" +qcow2_add_task(void *co, void *bs, void *pool, const char *action, int cluster_type, uint64_t host_offset, uint64_t offset, uint64_t bytes, void *qiov, size_t qiov_offset) "co %p bs %p pool %p: %s: cluster_type %d file_cluster_offset %" PRIu64 " offset %" PRIu64 " bytes %" PRIu64 " qiov %p qiov_offset %zu" qcow2_writev_start_req(void *co, int64_t offset, int bytes) "co %p offset 0x%" PRIx64 " bytes %d" qcow2_writev_done_req(void *co, int ret) "co %p ret %d" qcow2_writev_start_part(void *co) "co %p" @@ -136,43 +133,30 @@ qed_aio_write_prefill(void *s, void *acb, uint64_t start, size_t len, uint64_t o qed_aio_write_postfill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64 qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu" -# vxhs.c -vxhs_iio_callback(int error) "ctx is NULL: error %d" -vxhs_iio_callback_chnfail(int err, int error) "QNIO channel failed, no i/o %d, %d" -vxhs_iio_callback_unknwn(int opcode, int err) "unexpected opcode %d, errno %d" -vxhs_aio_rw_invalid(int req) "Invalid I/O request iodir %d" -vxhs_aio_rw_ioerr(char *guid, int iodir, uint64_t size, uint64_t off, void *acb, int ret, int err) "IO ERROR (vDisk %s) FOR : Read/Write = %d size = %"PRIu64" offset = %"PRIu64" ACB = %p. Error = %d, errno = %d" -vxhs_get_vdisk_stat_err(char *guid, int ret, int err) "vDisk (%s) stat ioctl failed, ret = %d, errno = %d" -vxhs_get_vdisk_stat(char *vdisk_guid, uint64_t vdisk_size) "vDisk %s stat ioctl returned size %"PRIu64 -vxhs_complete_aio(void *acb, uint64_t ret) "aio failed acb %p ret %"PRIu64 -vxhs_parse_uri_filename(const char *filename) "URI passed via bdrv_parse_filename %s" -vxhs_open_vdiskid(const char *vdisk_id) "Opening vdisk-id %s" -vxhs_open_hostinfo(char *of_vsa_addr, int port) "Adding host %s:%d to BDRVVXHSState" -vxhs_open_iio_open(const char *host) "Failed to connect to storage agent on host %s" -vxhs_parse_uri_hostinfo(char *host, int port) "Host: IP %s, Port %d" -vxhs_close(char *vdisk_guid) "Closing vdisk %s" -vxhs_get_creds(const char *cacert, const char *client_key, const char *client_cert) "cacert %s, client_key %s, client_cert %s" - # nvme.c -nvme_kick(void *s, int queue) "s %p queue %d" +nvme_controller_capability_raw(uint64_t value) "0x%08"PRIx64 +nvme_controller_capability(const char *desc, uint64_t value) "%s: %"PRIu64 +nvme_kick(void *s, unsigned q_index) "s %p q #%u" nvme_dma_flush_queue_wait(void *s) "s %p" nvme_error(int cmd_specific, int sq_head, int sqid, int cid, int status) "cmd_specific %d sq_head %d sqid %d cid %d status 0x%x" -nvme_process_completion(void *s, int index, int inflight) "s %p queue %d inflight %d" -nvme_process_completion_queue_busy(void *s, int index) "s %p queue %d" -nvme_complete_command(void *s, int index, int cid) "s %p queue %d cid %d" -nvme_submit_command(void *s, int index, int cid) "s %p queue %d cid %d" +nvme_process_completion(void *s, unsigned q_index, int inflight) "s %p q #%u inflight %d" +nvme_process_completion_queue_plugged(void *s, unsigned q_index) "s %p q #%u" +nvme_complete_command(void *s, unsigned q_index, int cid) "s %p q #%u cid %d" +nvme_submit_command(void *s, unsigned q_index, int cid) "s %p q #%u cid %d" nvme_submit_command_raw(int c0, int c1, int c2, int c3, int c4, int c5, int c6, int c7) "%02x %02x %02x %02x %02x %02x %02x %02x" nvme_handle_event(void *s) "s %p" -nvme_poll_cb(void *s) "s %p" -nvme_prw_aligned(void *s, int is_write, uint64_t offset, uint64_t bytes, int flags, int niov) "s %p is_write %d offset %"PRId64" bytes %"PRId64" flags %d niov %d" -nvme_write_zeroes(void *s, uint64_t offset, uint64_t bytes, int flags) "s %p offset %"PRId64" bytes %"PRId64" flags %d" +nvme_poll_queue(void *s, unsigned q_index) "s %p q #%u" +nvme_prw_aligned(void *s, int is_write, uint64_t offset, uint64_t bytes, int flags, int niov) "s %p is_write %d offset 0x%"PRIx64" bytes %"PRId64" flags %d niov %d" +nvme_write_zeroes(void *s, uint64_t offset, uint64_t bytes, int flags) "s %p offset 0x%"PRIx64" bytes %"PRId64" flags %d" nvme_qiov_unaligned(const void *qiov, int n, void *base, size_t size, int align) "qiov %p n %d base %p size 0x%zx align 0x%x" -nvme_prw_buffered(void *s, uint64_t offset, uint64_t bytes, int niov, int is_write) "s %p offset %"PRId64" bytes %"PRId64" niov %d is_write %d" -nvme_rw_done(void *s, int is_write, uint64_t offset, uint64_t bytes, int ret) "s %p is_write %d offset %"PRId64" bytes %"PRId64" ret %d" -nvme_dsm(void *s, uint64_t offset, uint64_t bytes) "s %p offset %"PRId64" bytes %"PRId64"" -nvme_dsm_done(void *s, uint64_t offset, uint64_t bytes, int ret) "s %p offset %"PRId64" bytes %"PRId64" ret %d" +nvme_prw_buffered(void *s, uint64_t offset, uint64_t bytes, int niov, int is_write) "s %p offset 0x%"PRIx64" bytes %"PRId64" niov %d is_write %d" +nvme_rw_done(void *s, int is_write, uint64_t offset, uint64_t bytes, int ret) "s %p is_write %d offset 0x%"PRIx64" bytes %"PRId64" ret %d" +nvme_dsm(void *s, uint64_t offset, uint64_t bytes) "s %p offset 0x%"PRIx64" bytes %"PRId64"" +nvme_dsm_done(void *s, uint64_t offset, uint64_t bytes, int ret) "s %p offset 0x%"PRIx64" bytes %"PRId64" ret %d" nvme_dma_map_flush(void *s) "s %p" -nvme_free_req_queue_wait(void *q) "q %p" +nvme_free_req_queue_wait(void *s, unsigned q_index) "s %p q #%u" +nvme_create_queue_pair(unsigned q_index, void *q, unsigned size, void *aio_context, int fd) "index %u q %p size %u aioctx %p fd %d" +nvme_free_queue_pair(unsigned q_index, void *q) "index %u q %p" nvme_cmd_map_qiov(void *s, void *cmd, void *req, void *qiov, int entries) "s %p cmd %p req %p qiov %p entries %d" nvme_cmd_map_qiov_pages(void *s, int i, uint64_t page) "s %p page[%d] 0x%"PRIx64 nvme_cmd_map_qiov_iov(void *s, int i, void *page, int pages) "s %p iov[%d] %p pages %d" @@ -185,8 +169,8 @@ nbd_parse_blockstatus_compliance(const char *err) "ignoring extra data from non- nbd_structured_read_compliance(const char *type) "server sent non-compliant unaligned read %s chunk" nbd_read_reply_entry_fail(int ret, const char *err) "ret = %d, err: %s" nbd_co_request_fail(uint64_t from, uint32_t len, uint64_t handle, uint16_t flags, uint16_t type, const char *name, int ret, const char *err) "Request failed { .from = %" PRIu64", .len = %" PRIu32 ", .handle = %" PRIu64 ", .flags = 0x%" PRIx16 ", .type = %" PRIu16 " (%s) } ret = %d, err: %s" -nbd_client_connect(const char *export_name) "export '%s'" -nbd_client_connect_success(const char *export_name) "export '%s'" +nbd_client_handshake(const char *export_name) "export '%s'" +nbd_client_handshake_success(const char *export_name) "export '%s'" # ssh.c ssh_restart_coroutine(void *co) "co=%p" @@ -217,8 +201,7 @@ curl_setup_preadv(uint64_t bytes, uint64_t start, const char *range) "reading %" curl_close(void) "close" # file-posix.c -file_xfs_write_zeroes(const char *error) "cannot write zero range (%s)" -file_xfs_discard(const char *error) "cannot punch hole (%s)" +file_copy_file_range(void *bs, int src, int64_t src_off, int dst, int64_t dst_off, int64_t bytes, int flags, int64_t ret) "bs %p src_fd %d offset %"PRIu64" dst_fd %d offset %"PRIu64" bytes %"PRIu64" flags %d ret %"PRId64 file_FindEjectableOpticalMedia(const char *media) "Matching using %s" file_setup_cdrom(const char *partition) "Using %s as optical disc" file_hdev_is_sg(int type, int version) "SG device found: type=%d, version=%d" diff --git a/block/trace.h b/block/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..3a436e6c7fda3e263c10ee4d15627365c4c5054f --- /dev/null +++ b/block/trace.h @@ -0,0 +1 @@ +#include "trace/trace-block.h" diff --git a/block/vdi.c b/block/vdi.c index 2f506a01ba45f78c793990ad2752832e1fd5aa23..5627e7d764aeeccba87e569f8209caf82dccaa35 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -334,7 +334,6 @@ static int vdi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) logout("\n"); bdi->cluster_size = s->block_size; bdi->vm_state_offset = 0; - bdi->unallocated_blocks_are_zero = true; return 0; } @@ -375,7 +374,6 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags, VdiHeader header; size_t bmap_size; int ret; - Error *local_err = NULL; QemuUUID uuid_link, uuid_parent; bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, @@ -496,9 +494,8 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags, error_setg(&s->migration_blocker, "The vdi format used by node '%s' " "does not support live migration", bdrv_get_device_or_node_name(bs)); - ret = migrate_add_blocker(s->migration_blocker, &local_err); - if (local_err) { - error_propagate(errp, local_err); + ret = migrate_add_blocker(s->migration_blocker, errp); + if (ret < 0) { error_free(s->migration_blocker); goto fail_free_bmap; } @@ -536,7 +533,7 @@ static int coroutine_fn vdi_co_block_status(BlockDriverState *bs, *pnum = MIN(s->block_size - index_in_block, bytes); result = VDI_IS_ALLOCATED(bmap_entry); if (!result) { - return 0; + return BDRV_BLOCK_ZERO; } *map = s->header.offset_data + (uint64_t)bmap_entry * s->block_size + @@ -907,7 +904,6 @@ static int coroutine_fn vdi_co_create_opts(BlockDriver *drv, uint64_t block_size = DEFAULT_CLUSTER_SIZE; bool is_static = false; Visitor *v; - Error *local_err = NULL; int ret; /* Parse options and convert legacy syntax. @@ -958,11 +954,9 @@ static int coroutine_fn vdi_co_create_opts(BlockDriver *drv, ret = -EINVAL; goto done; } - visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); + visit_type_BlockdevCreateOptions(v, NULL, &create_options, errp); visit_free(v); - - if (local_err) { - error_propagate(errp, local_err); + if (!create_options) { ret = -EINVAL; goto done; } diff --git a/block/vhdx.c b/block/vhdx.c index fa9e544a5e22c428af8a11c5a869b2c9dfd1987e..356ec4c455a42be6e5f68b62c712536e9f2f6310 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -816,9 +816,9 @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s) goto exit; } - /* only 2 supported sector sizes */ - if (s->logical_sector_size != 512 && s->logical_sector_size != 4096) { - ret = -EINVAL; + /* Currently we only support 512 */ + if (s->logical_sector_size != 512) { + ret = -ENOTSUP; goto exit; } @@ -1089,9 +1089,8 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags, error_setg(&s->migration_blocker, "The vhdx format used by node '%s' " "does not support live migration", bdrv_get_device_or_node_name(bs)); - ret = migrate_add_blocker(s->migration_blocker, &local_err); - if (local_err) { - error_propagate(errp, local_err); + ret = migrate_add_blocker(s->migration_blocker, errp); + if (ret < 0) { error_free(s->migration_blocker); goto fail; } @@ -1164,9 +1163,6 @@ static int vhdx_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) bdi->cluster_size = s->block_size; - bdi->unallocated_blocks_are_zero = - (s->params.data_bits & VHDX_PARAMS_HAS_PARENT) == 0; - return 0; } @@ -2067,7 +2063,6 @@ static int coroutine_fn vhdx_co_create_opts(BlockDriver *drv, QDict *qdict; Visitor *v; BlockDriverState *bs = NULL; - Error *local_err = NULL; int ret; static const QDictRenames opt_renames[] = { @@ -2086,9 +2081,8 @@ static int coroutine_fn vhdx_co_create_opts(BlockDriver *drv, } /* Create and open the file (protocol layer) */ - ret = bdrv_create_file(filename, opts, &local_err); + ret = bdrv_create_file(filename, opts, errp); if (ret < 0) { - error_propagate(errp, local_err); goto fail; } @@ -2109,11 +2103,9 @@ static int coroutine_fn vhdx_co_create_opts(BlockDriver *drv, goto fail; } - visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); + visit_type_BlockdevCreateOptions(v, NULL, &create_options, errp); visit_free(v); - - if (local_err) { - error_propagate(errp, local_err); + if (!create_options) { ret = -EINVAL; goto fail; } diff --git a/block/vmdk.c b/block/vmdk.c index 62da4651263bab7fbce5ad0e298b7e192db3297b..a00dc00eb47a1d478e8c56a644bed04931fe12cb 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -595,7 +595,7 @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs, int ret; uint32_t magic; VMDK3Header header; - VmdkExtent *extent; + VmdkExtent *extent = NULL; ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header)); if (ret < 0) { @@ -751,7 +751,7 @@ static int vmdk_open_se_sparse(BlockDriverState *bs, int ret; VMDKSESparseConstHeader const_header; VMDKSESparseVolatileHeader volatile_header; - VmdkExtent *extent; + VmdkExtent *extent = NULL; ret = bdrv_apply_auto_read_only(bs, "No write support for seSparse images available", errp); @@ -869,7 +869,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, uint32_t magic; uint32_t l1_size, l1_entry_sectors; VMDK4Header header; - VmdkExtent *extent; + VmdkExtent *extent = NULL; BDRVVmdkState *s = bs->opaque; int64_t l1_backup_offset = 0; bool compressed; @@ -1053,14 +1053,11 @@ static int vmdk_open_sparse(BlockDriverState *bs, BdrvChild *file, int flags, switch (magic) { case VMDK3_MAGIC: return vmdk_open_vmfs_sparse(bs, file, flags, errp); - break; case VMDK4_MAGIC: return vmdk_open_vmdk4(bs, file, flags, options, errp); - break; default: error_setg(errp, "Image not in VMDK format"); return -EINVAL; - break; } } @@ -1091,7 +1088,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, BdrvChild *extent_file; BdrvChildRole extent_role; BDRVVmdkState *s = bs->opaque; - VmdkExtent *extent; + VmdkExtent *extent = NULL; char extent_opt_prefix[32]; Error *local_err = NULL; @@ -1263,7 +1260,6 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags, int ret; BDRVVmdkState *s = bs->opaque; uint32_t magic; - Error *local_err = NULL; bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, BDRV_CHILD_IMAGE, false, errp); @@ -1317,9 +1313,8 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags, error_setg(&s->migration_blocker, "The vmdk format used by node '%s' " "does not support live migration", bdrv_get_device_or_node_name(bs)); - ret = migrate_add_blocker(s->migration_blocker, &local_err); - if (local_err) { - error_propagate(errp, local_err); + ret = migrate_add_blocker(s->migration_blocker, errp); + if (ret < 0) { error_free(s->migration_blocker); goto fail; } @@ -2250,19 +2245,16 @@ static int vmdk_create_extent(const char *filename, int64_t filesize, { int ret; BlockBackend *blk = NULL; - Error *local_err = NULL; - ret = bdrv_create_file(filename, opts, &local_err); + ret = bdrv_create_file(filename, opts, errp); if (ret < 0) { - error_propagate(errp, local_err); goto exit; } blk = blk_new_open(filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, - &local_err); + errp); if (blk == NULL) { - error_propagate(errp, local_err); ret = -EIO; goto exit; } @@ -2638,6 +2630,14 @@ static int coroutine_fn vmdk_co_create_opts(BlockDriver *drv, bool zeroed_grain; bool compat6; VMDKCreateOptsData data; + char *backing_fmt = NULL; + + backing_fmt = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FMT); + if (backing_fmt && strcmp(backing_fmt, "vmdk") != 0) { + error_setg(errp, "backing_file must be a vmdk image"); + ret = -EINVAL; + goto exit; + } if (filename_decompose(filename, path, prefix, postfix, PATH_MAX, errp)) { ret = -EINVAL; @@ -2696,6 +2696,7 @@ static int coroutine_fn vmdk_co_create_opts(BlockDriver *drv, vmdk_co_create_opts_cb, &data, errp); exit: + g_free(backing_fmt); g_free(adapter_type); g_free(backing_file); g_free(hw_version); @@ -2802,21 +2803,6 @@ static void vmdk_close(BlockDriverState *bs) error_free(s->migration_blocker); } -static coroutine_fn int vmdk_co_flush(BlockDriverState *bs) -{ - BDRVVmdkState *s = bs->opaque; - int i, err; - int ret = 0; - - for (i = 0; i < s->num_extents; i++) { - err = bdrv_co_flush(s->extents[i].file->bs); - if (err < 0) { - ret = err; - } - } - return ret; -} - static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs) { int i; @@ -3031,6 +3017,11 @@ static QemuOptsList vmdk_create_opts = { .type = QEMU_OPT_STRING, .help = "File name of a base image" }, + { + .name = BLOCK_OPT_BACKING_FMT, + .type = QEMU_OPT_STRING, + .help = "Must be 'vmdk' if present", + }, { .name = BLOCK_OPT_COMPAT6, .type = QEMU_OPT_BOOL, @@ -3075,7 +3066,6 @@ static BlockDriver bdrv_vmdk = { .bdrv_close = vmdk_close, .bdrv_co_create_opts = vmdk_co_create_opts, .bdrv_co_create = vmdk_co_create, - .bdrv_co_flush_to_disk = vmdk_co_flush, .bdrv_co_block_status = vmdk_co_block_status, .bdrv_get_allocated_file_size = vmdk_get_allocated_file_size, .bdrv_has_zero_init = vmdk_has_zero_init, diff --git a/block/vpc.c b/block/vpc.c index c0555916418758d571247042a598dd111e073ad5..1ab55f92877f864cfea5a9fe537df086d954bd00 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -172,7 +172,7 @@ static QemuOptsList vpc_runtime_opts = { static QemuOptsList vpc_create_opts; -static uint32_t vpc_checksum(uint8_t* buf, size_t size) +static uint32_t vpc_checksum(uint8_t *buf, size_t size) { uint32_t res = 0; int i; @@ -235,9 +235,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, } opts = qemu_opts_create(&vpc_runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { ret = -EINVAL; goto fail; } @@ -448,9 +446,8 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, error_setg(&s->migration_blocker, "The vpc format used by node '%s' " "does not support live migration", bdrv_get_device_or_node_name(bs)); - ret = migrate_add_blocker(s->migration_blocker, &local_err); - if (local_err) { - error_propagate(errp, local_err); + ret = migrate_add_blocker(s->migration_blocker, errp); + if (ret < 0) { error_free(s->migration_blocker); goto fail; } @@ -531,7 +528,7 @@ static inline int64_t get_image_offset(BlockDriverState *bs, uint64_t offset, * * Returns 0 on success and < 0 on error */ -static int rewrite_footer(BlockDriverState* bs) +static int rewrite_footer(BlockDriverState *bs) { int ret; BDRVVPCState *s = bs->opaque; @@ -551,7 +548,7 @@ static int rewrite_footer(BlockDriverState* bs) * * Returns the sectors' offset in the image file on success and < 0 on error */ -static int64_t alloc_block(BlockDriverState* bs, int64_t offset) +static int64_t alloc_block(BlockDriverState *bs, int64_t offset) { BDRVVPCState *s = bs->opaque; int64_t bat_offset; @@ -606,7 +603,6 @@ static int vpc_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) bdi->cluster_size = s->block_size; } - bdi->unallocated_blocks_are_zero = true; return 0; } @@ -745,7 +741,7 @@ static int coroutine_fn vpc_co_block_status(BlockDriverState *bs, image_offset = get_image_offset(bs, offset, false, NULL); allocated = (image_offset != -1); *pnum = 0; - ret = 0; + ret = BDRV_BLOCK_ZERO; do { /* All sectors in a block are contiguous (without using the bitmap) */ @@ -785,8 +781,8 @@ static int coroutine_fn vpc_co_block_status(BlockDriverState *bs, * the hardware EIDE and ATA-2 limit of 16 heads (max disk size of 127 GB) * and instead allow up to 255 heads. */ -static int calculate_geometry(int64_t total_sectors, uint16_t* cyls, - uint8_t* heads, uint8_t* secs_per_cyl) +static int calculate_geometry(int64_t total_sectors, uint16_t *cyls, + uint8_t *heads, uint8_t *secs_per_cyl) { uint32_t cyls_times_heads; @@ -1098,7 +1094,6 @@ static int coroutine_fn vpc_co_create_opts(BlockDriver *drv, QDict *qdict; Visitor *v; BlockDriverState *bs = NULL; - Error *local_err = NULL; int ret; static const QDictRenames opt_renames[] = { @@ -1115,9 +1110,8 @@ static int coroutine_fn vpc_co_create_opts(BlockDriver *drv, } /* Create and open the file (protocol layer) */ - ret = bdrv_create_file(filename, opts, &local_err); + ret = bdrv_create_file(filename, opts, errp); if (ret < 0) { - error_propagate(errp, local_err); goto fail; } @@ -1138,11 +1132,9 @@ static int coroutine_fn vpc_co_create_opts(BlockDriver *drv, goto fail; } - visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); + visit_type_BlockdevCreateOptions(v, NULL, &create_options, errp); visit_free(v); - - if (local_err) { - error_propagate(errp, local_err); + if (!create_options) { ret = -EINVAL; goto fail; } diff --git a/block/vvfat.c b/block/vvfat.c index c65a98e3ee1caae6aff4234bd75c3c5258249677..54807f82ca1f362e956cccddae85cb73362fc5b7 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -140,48 +140,16 @@ static inline void* array_insert(array_t* array,unsigned int index,unsigned int return array->pointer+index*array->item_size; } -/* this performs a "roll", so that the element which was at index_from becomes - * index_to, but the order of all other elements is preserved. */ -static inline int array_roll(array_t* array,int index_to,int index_from,int count) -{ - char* buf; - char* from; - char* to; - int is; - - if(!array || - index_to<0 || index_to>=array->next || - index_from<0 || index_from>=array->next) - return -1; - - if(index_to==index_from) - return 0; - - is=array->item_size; - from=array->pointer+index_from*is; - to=array->pointer+index_to*is; - buf=g_malloc(is*count); - memcpy(buf,from,is*count); - - if(index_to=0); assert(count > 0); assert(index + count <= array->next); - if(array_roll(array,array->next-1,index,count)) - return -1; + + memmove(array->pointer + index * array->item_size, + array->pointer + (index + count) * array->item_size, + (array->next - index - count) * array->item_size); + array->next -= count; return 0; } @@ -520,12 +488,31 @@ static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin) direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff); } +static bool valid_filename(const unsigned char *name) +{ + unsigned char c; + if (!strcmp((const char*)name, ".") || !strcmp((const char*)name, "..")) { + return false; + } + for (; (c = *name); name++) { + if (!((c >= '0' && c <= '9') || + (c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z') || + c > 127 || + strchr("$%'-_@~`!(){}^#&.+,;=[]", c) != NULL)) + { + return false; + } + } + return true; +} + static uint8_t to_valid_short_char(gunichar c) { c = g_unichar_toupper(c); if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || - strchr("$%'-_@~`!(){}^#&", c) != 0) { + strchr("$%'-_@~`!(){}^#&", c) != NULL) { return c; } else { return 0; @@ -1154,7 +1141,6 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags, bool floppy; const char *dirname, *label; QemuOpts *opts; - Error *local_err = NULL; int ret; #ifdef DEBUG @@ -1162,9 +1148,7 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags, #endif opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { ret = -EINVAL; goto fail; } @@ -1282,9 +1266,8 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags, "The vvfat (rw) format used by node '%s' " "does not support live migration", bdrv_get_device_or_node_name(bs)); - ret = migrate_add_blocker(s->migration_blocker, &local_err); - if (local_err) { - error_propagate(errp, local_err); + ret = migrate_add_blocker(s->migration_blocker, errp); + if (ret < 0) { error_free(s->migration_blocker); goto fail; } @@ -1369,7 +1352,8 @@ static int open_file(BDRVVVFATState* s,mapping_t* mapping) if(!s->current_mapping || strcmp(s->current_mapping->path,mapping->path)) { /* open file */ - int fd = qemu_open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE); + int fd = qemu_open_old(mapping->path, + O_RDONLY | O_BINARY | O_LARGEFILE); if(fd<0) return -1; vvfat_close_current_file(s); @@ -1453,7 +1437,7 @@ static void print_direntry(const direntry_t* direntry) for(i=0;i<11;i++) ADD_CHAR(direntry->name[i]); buffer[j] = 0; - fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n", + fprintf(stderr, "%s attributes=0x%02x begin=%u size=%u\n", buffer, direntry->attributes, begin_of_direntry(direntry),le32_to_cpu(direntry->size)); @@ -1462,7 +1446,7 @@ static void print_direntry(const direntry_t* direntry) static void print_mapping(const mapping_t* mapping) { - fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, " + fprintf(stderr, "mapping (%p): begin, end = %u, %u, dir_index = %u, " "first_mapping_index = %d, name = %s, mode = 0x%x, " , mapping, mapping->begin, mapping->end, mapping->dir_index, mapping->first_mapping_index, mapping->path, mapping->mode); @@ -1470,7 +1454,7 @@ static void print_mapping(const mapping_t* mapping) if (mapping->mode & MODE_DIRECTORY) fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index); else - fprintf(stderr, "offset = %d\n", mapping->info.file.offset); + fprintf(stderr, "offset = %u\n", mapping->info.file.offset); } #endif @@ -1604,7 +1588,7 @@ typedef struct commit_t { static void clear_commits(BDRVVVFATState* s) { int i; -DLOG(fprintf(stderr, "clear_commits (%d commits)\n", s->commits.next)); +DLOG(fprintf(stderr, "clear_commits (%u commits)\n", s->commits.next)); for (i = 0; i < s->commits.next; i++) { commit_t* commit = array_get(&(s->commits), i); assert(commit->path || commit->action == ACTION_WRITEOUT); @@ -2098,6 +2082,10 @@ DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i)) } lfn.checksum = 0x100; /* cannot use long name twice */ + if (!valid_filename(lfn.name)) { + fprintf(stderr, "Invalid file name\n"); + goto fail; + } if (path_len + 1 + lfn.len >= PATH_MAX) { fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name); goto fail; @@ -2526,7 +2514,7 @@ static int commit_one_file(BDRVVVFATState* s, for (i = s->cluster_size; i < offset; i += s->cluster_size) c = modified_fat_get(s, c); - fd = qemu_open(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666); + fd = qemu_open_old(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666); if (fd < 0) { fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path, strerror(errno), errno); @@ -2660,7 +2648,9 @@ static int handle_renames_and_mkdirs(BDRVVVFATState* s) fprintf(stderr, "handle_renames\n"); for (i = 0; i < s->commits.next; i++) { commit_t* commit = array_get(&(s->commits), i); - fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action); + fprintf(stderr, "%d, %s (%u, %d)\n", i, + commit->path ? commit->path : "(null)", + commit->param.rename.cluster, commit->action); } #endif diff --git a/block/vxhs.c b/block/vxhs.c deleted file mode 100644 index d79fc97df66a13a07e06fac06a8383e91be025bc..0000000000000000000000000000000000000000 --- a/block/vxhs.c +++ /dev/null @@ -1,590 +0,0 @@ -/* - * QEMU Block driver for Veritas HyperScale (VxHS) - * - * Copyright (c) 2017 Veritas Technologies LLC. - * - * 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 -#include -#include "block/block_int.h" -#include "block/qdict.h" -#include "qapi/qmp/qerror.h" -#include "qapi/qmp/qdict.h" -#include "qapi/qmp/qstring.h" -#include "trace.h" -#include "qemu/module.h" -#include "qemu/uri.h" -#include "qapi/error.h" -#include "qemu/uuid.h" -#include "crypto/tlscredsx509.h" -#include "sysemu/replay.h" - -#define VXHS_OPT_FILENAME "filename" -#define VXHS_OPT_VDISK_ID "vdisk-id" -#define VXHS_OPT_SERVER "server" -#define VXHS_OPT_HOST "host" -#define VXHS_OPT_PORT "port" - -/* Only accessed under QEMU global mutex */ -static uint32_t vxhs_ref; - -typedef enum { - VDISK_AIO_READ, - VDISK_AIO_WRITE, -} VDISKAIOCmd; - -/* - * HyperScale AIO callbacks structure - */ -typedef struct VXHSAIOCB { - BlockAIOCB common; - int err; -} VXHSAIOCB; - -typedef struct VXHSvDiskHostsInfo { - void *dev_handle; /* Device handle */ - char *host; /* Host name or IP */ - int port; /* Host's port number */ -} VXHSvDiskHostsInfo; - -/* - * Structure per vDisk maintained for state - */ -typedef struct BDRVVXHSState { - VXHSvDiskHostsInfo vdisk_hostinfo; /* Per host info */ - char *vdisk_guid; - char *tlscredsid; /* tlscredsid */ -} BDRVVXHSState; - -static void vxhs_complete_aio_bh(void *opaque) -{ - VXHSAIOCB *acb = opaque; - BlockCompletionFunc *cb = acb->common.cb; - void *cb_opaque = acb->common.opaque; - int ret = 0; - - if (acb->err != 0) { - trace_vxhs_complete_aio(acb, acb->err); - ret = (-EIO); - } - - qemu_aio_unref(acb); - cb(cb_opaque, ret); -} - -/* - * Called from a libqnio thread - */ -static void vxhs_iio_callback(void *ctx, uint32_t opcode, uint32_t error) -{ - VXHSAIOCB *acb = NULL; - - switch (opcode) { - case IRP_READ_REQUEST: - case IRP_WRITE_REQUEST: - - /* - * ctx is VXHSAIOCB* - * ctx is NULL if error is QNIOERROR_CHANNEL_HUP - */ - if (ctx) { - acb = ctx; - } else { - trace_vxhs_iio_callback(error); - goto out; - } - - if (error) { - if (!acb->err) { - acb->err = error; - } - trace_vxhs_iio_callback(error); - } - - replay_bh_schedule_oneshot_event(bdrv_get_aio_context(acb->common.bs), - vxhs_complete_aio_bh, acb); - break; - - default: - if (error == QNIOERROR_HUP) { - /* - * Channel failed, spontaneous notification, - * not in response to I/O - */ - trace_vxhs_iio_callback_chnfail(error, errno); - } else { - trace_vxhs_iio_callback_unknwn(opcode, error); - } - break; - } -out: - return; -} - -static QemuOptsList runtime_opts = { - .name = "vxhs", - .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), - .desc = { - { - .name = VXHS_OPT_FILENAME, - .type = QEMU_OPT_STRING, - .help = "URI to the Veritas HyperScale image", - }, - { - .name = VXHS_OPT_VDISK_ID, - .type = QEMU_OPT_STRING, - .help = "UUID of the VxHS vdisk", - }, - { - .name = "tls-creds", - .type = QEMU_OPT_STRING, - .help = "ID of the TLS/SSL credentials to use", - }, - { /* end of list */ } - }, -}; - -static QemuOptsList runtime_tcp_opts = { - .name = "vxhs_tcp", - .head = QTAILQ_HEAD_INITIALIZER(runtime_tcp_opts.head), - .desc = { - { - .name = VXHS_OPT_HOST, - .type = QEMU_OPT_STRING, - .help = "host address (ipv4 addresses)", - }, - { - .name = VXHS_OPT_PORT, - .type = QEMU_OPT_NUMBER, - .help = "port number on which VxHSD is listening (default 9999)", - .def_value_str = "9999" - }, - { /* end of list */ } - }, -}; - -/* - * Parse incoming URI and populate *options with the host - * and device information - */ -static int vxhs_parse_uri(const char *filename, QDict *options) -{ - URI *uri = NULL; - char *port; - int ret = 0; - - trace_vxhs_parse_uri_filename(filename); - uri = uri_parse(filename); - if (!uri || !uri->server || !uri->path) { - uri_free(uri); - return -EINVAL; - } - - qdict_put_str(options, VXHS_OPT_SERVER ".host", uri->server); - - if (uri->port) { - port = g_strdup_printf("%d", uri->port); - qdict_put_str(options, VXHS_OPT_SERVER ".port", port); - g_free(port); - } - - qdict_put_str(options, "vdisk-id", uri->path); - - trace_vxhs_parse_uri_hostinfo(uri->server, uri->port); - uri_free(uri); - - return ret; -} - -static void vxhs_parse_filename(const char *filename, QDict *options, - Error **errp) -{ - if (qdict_haskey(options, "vdisk-id") || qdict_haskey(options, "server")) { - error_setg(errp, "vdisk-id/server and a file name may not be specified " - "at the same time"); - return; - } - - if (strstr(filename, "://")) { - int ret = vxhs_parse_uri(filename, options); - if (ret < 0) { - error_setg(errp, "Invalid URI. URI should be of the form " - " vxhs://:/"); - } - } -} - -static void vxhs_refresh_limits(BlockDriverState *bs, Error **errp) -{ - /* XXX Does VXHS support AIO on less than 512-byte alignment? */ - bs->bl.request_alignment = 512; -} - -static int vxhs_init_and_ref(void) -{ - if (vxhs_ref++ == 0) { - if (iio_init(QNIO_VERSION, vxhs_iio_callback)) { - return -ENODEV; - } - } - return 0; -} - -static void vxhs_unref(void) -{ - if (--vxhs_ref == 0) { - iio_fini(); - } -} - -static void vxhs_get_tls_creds(const char *id, char **cacert, - char **key, char **cert, Error **errp) -{ - Object *obj; - QCryptoTLSCreds *creds; - QCryptoTLSCredsX509 *creds_x509; - - obj = object_resolve_path_component( - object_get_objects_root(), id); - - if (!obj) { - error_setg(errp, "No TLS credentials with id '%s'", - id); - return; - } - - creds_x509 = (QCryptoTLSCredsX509 *) - object_dynamic_cast(obj, TYPE_QCRYPTO_TLS_CREDS_X509); - - if (!creds_x509) { - error_setg(errp, "Object with id '%s' is not TLS credentials", - id); - return; - } - - creds = &creds_x509->parent_obj; - - if (creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) { - error_setg(errp, - "Expecting TLS credentials with a client endpoint"); - return; - } - - /* - * Get the cacert, client_cert and client_key file names. - */ - if (!creds->dir) { - error_setg(errp, "TLS object missing 'dir' property value"); - return; - } - - *cacert = g_strdup_printf("%s/%s", creds->dir, - QCRYPTO_TLS_CREDS_X509_CA_CERT); - *cert = g_strdup_printf("%s/%s", creds->dir, - QCRYPTO_TLS_CREDS_X509_CLIENT_CERT); - *key = g_strdup_printf("%s/%s", creds->dir, - QCRYPTO_TLS_CREDS_X509_CLIENT_KEY); -} - -static int vxhs_open(BlockDriverState *bs, QDict *options, - int bdrv_flags, Error **errp) -{ - BDRVVXHSState *s = bs->opaque; - void *dev_handlep; - QDict *backing_options = NULL; - QemuOpts *opts = NULL; - QemuOpts *tcp_opts = NULL; - char *of_vsa_addr = NULL; - Error *local_err = NULL; - const char *vdisk_id_opt; - const char *server_host_opt; - int ret = 0; - char *cacert = NULL; - char *client_key = NULL; - char *client_cert = NULL; - - ret = vxhs_init_and_ref(); - if (ret < 0) { - ret = -EINVAL; - goto out; - } - - /* Create opts info from runtime_opts and runtime_tcp_opts list */ - opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); - tcp_opts = qemu_opts_create(&runtime_tcp_opts, NULL, 0, &error_abort); - - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - ret = -EINVAL; - goto out; - } - - /* vdisk-id is the disk UUID */ - vdisk_id_opt = qemu_opt_get(opts, VXHS_OPT_VDISK_ID); - if (!vdisk_id_opt) { - error_setg(&local_err, QERR_MISSING_PARAMETER, VXHS_OPT_VDISK_ID); - ret = -EINVAL; - goto out; - } - - /* vdisk-id may contain a leading '/' */ - if (strlen(vdisk_id_opt) > UUID_FMT_LEN + 1) { - error_setg(&local_err, "vdisk-id cannot be more than %d characters", - UUID_FMT_LEN); - ret = -EINVAL; - goto out; - } - - s->vdisk_guid = g_strdup(vdisk_id_opt); - trace_vxhs_open_vdiskid(vdisk_id_opt); - - /* get the 'server.' arguments */ - qdict_extract_subqdict(options, &backing_options, VXHS_OPT_SERVER"."); - - qemu_opts_absorb_qdict(tcp_opts, backing_options, &local_err); - if (local_err != NULL) { - ret = -EINVAL; - goto out; - } - - server_host_opt = qemu_opt_get(tcp_opts, VXHS_OPT_HOST); - if (!server_host_opt) { - error_setg(&local_err, QERR_MISSING_PARAMETER, - VXHS_OPT_SERVER"."VXHS_OPT_HOST); - ret = -EINVAL; - goto out; - } - - if (strlen(server_host_opt) > MAXHOSTNAMELEN) { - error_setg(&local_err, "server.host cannot be more than %d characters", - MAXHOSTNAMELEN); - ret = -EINVAL; - goto out; - } - - /* check if we got tls-creds via the --object argument */ - s->tlscredsid = g_strdup(qemu_opt_get(opts, "tls-creds")); - if (s->tlscredsid) { - vxhs_get_tls_creds(s->tlscredsid, &cacert, &client_key, - &client_cert, &local_err); - if (local_err != NULL) { - ret = -EINVAL; - goto out; - } - trace_vxhs_get_creds(cacert, client_key, client_cert); - } - - s->vdisk_hostinfo.host = g_strdup(server_host_opt); - s->vdisk_hostinfo.port = g_ascii_strtoll(qemu_opt_get(tcp_opts, - VXHS_OPT_PORT), - NULL, 0); - - trace_vxhs_open_hostinfo(s->vdisk_hostinfo.host, - s->vdisk_hostinfo.port); - - of_vsa_addr = g_strdup_printf("of://%s:%d", - s->vdisk_hostinfo.host, - s->vdisk_hostinfo.port); - - /* - * Open qnio channel to storage agent if not opened before - */ - dev_handlep = iio_open(of_vsa_addr, s->vdisk_guid, 0, - cacert, client_key, client_cert); - if (dev_handlep == NULL) { - trace_vxhs_open_iio_open(of_vsa_addr); - ret = -ENODEV; - goto out; - } - s->vdisk_hostinfo.dev_handle = dev_handlep; - -out: - g_free(of_vsa_addr); - qobject_unref(backing_options); - qemu_opts_del(tcp_opts); - qemu_opts_del(opts); - g_free(cacert); - g_free(client_key); - g_free(client_cert); - - if (ret < 0) { - vxhs_unref(); - error_propagate(errp, local_err); - g_free(s->vdisk_hostinfo.host); - g_free(s->vdisk_guid); - g_free(s->tlscredsid); - s->vdisk_guid = NULL; - } - - return ret; -} - -static const AIOCBInfo vxhs_aiocb_info = { - .aiocb_size = sizeof(VXHSAIOCB) -}; - -/* - * This allocates QEMU-VXHS callback for each IO - * and is passed to QNIO. When QNIO completes the work, - * it will be passed back through the callback. - */ -static BlockAIOCB *vxhs_aio_rw(BlockDriverState *bs, uint64_t offset, - QEMUIOVector *qiov, uint64_t size, - BlockCompletionFunc *cb, void *opaque, - VDISKAIOCmd iodir) -{ - VXHSAIOCB *acb = NULL; - BDRVVXHSState *s = bs->opaque; - int iio_flags = 0; - int ret = 0; - void *dev_handle = s->vdisk_hostinfo.dev_handle; - - acb = qemu_aio_get(&vxhs_aiocb_info, bs, cb, opaque); - - /* - * Initialize VXHSAIOCB. - */ - acb->err = 0; - - iio_flags = IIO_FLAG_ASYNC; - - switch (iodir) { - case VDISK_AIO_WRITE: - ret = iio_writev(dev_handle, acb, qiov->iov, qiov->niov, - offset, size, iio_flags); - break; - case VDISK_AIO_READ: - ret = iio_readv(dev_handle, acb, qiov->iov, qiov->niov, - offset, size, iio_flags); - break; - default: - trace_vxhs_aio_rw_invalid(iodir); - goto errout; - } - - if (ret != 0) { - trace_vxhs_aio_rw_ioerr(s->vdisk_guid, iodir, size, offset, - acb, ret, errno); - goto errout; - } - return &acb->common; - -errout: - qemu_aio_unref(acb); - return NULL; -} - -static BlockAIOCB *vxhs_aio_preadv(BlockDriverState *bs, - uint64_t offset, uint64_t bytes, - QEMUIOVector *qiov, int flags, - BlockCompletionFunc *cb, void *opaque) -{ - return vxhs_aio_rw(bs, offset, qiov, bytes, cb, opaque, VDISK_AIO_READ); -} - -static BlockAIOCB *vxhs_aio_pwritev(BlockDriverState *bs, - uint64_t offset, uint64_t bytes, - QEMUIOVector *qiov, int flags, - BlockCompletionFunc *cb, void *opaque) -{ - return vxhs_aio_rw(bs, offset, qiov, bytes, cb, opaque, VDISK_AIO_WRITE); -} - -static void vxhs_close(BlockDriverState *bs) -{ - BDRVVXHSState *s = bs->opaque; - - trace_vxhs_close(s->vdisk_guid); - - g_free(s->vdisk_guid); - s->vdisk_guid = NULL; - - /* - * Close vDisk device - */ - if (s->vdisk_hostinfo.dev_handle) { - iio_close(s->vdisk_hostinfo.dev_handle); - s->vdisk_hostinfo.dev_handle = NULL; - } - - vxhs_unref(); - - /* - * Free the dynamically allocated host string etc - */ - g_free(s->vdisk_hostinfo.host); - g_free(s->tlscredsid); - s->tlscredsid = NULL; - s->vdisk_hostinfo.host = NULL; - s->vdisk_hostinfo.port = 0; -} - -static int64_t vxhs_get_vdisk_stat(BDRVVXHSState *s) -{ - int64_t vdisk_size = -1; - int ret = 0; - void *dev_handle = s->vdisk_hostinfo.dev_handle; - - ret = iio_ioctl(dev_handle, IOR_VDISK_STAT, &vdisk_size, 0); - if (ret < 0) { - trace_vxhs_get_vdisk_stat_err(s->vdisk_guid, ret, errno); - return -EIO; - } - - trace_vxhs_get_vdisk_stat(s->vdisk_guid, vdisk_size); - return vdisk_size; -} - -/* - * Returns the size of vDisk in bytes. This is required - * by QEMU block upper block layer so that it is visible - * to guest. - */ -static int64_t vxhs_getlength(BlockDriverState *bs) -{ - BDRVVXHSState *s = bs->opaque; - int64_t vdisk_size; - - vdisk_size = vxhs_get_vdisk_stat(s); - if (vdisk_size < 0) { - return -EIO; - } - - return vdisk_size; -} - -static const char *const vxhs_strong_runtime_opts[] = { - VXHS_OPT_VDISK_ID, - "tls-creds", - VXHS_OPT_HOST, - VXHS_OPT_PORT, - VXHS_OPT_SERVER".", - - NULL -}; - -static BlockDriver bdrv_vxhs = { - .format_name = "vxhs", - .protocol_name = "vxhs", - .instance_size = sizeof(BDRVVXHSState), - .bdrv_file_open = vxhs_open, - .bdrv_parse_filename = vxhs_parse_filename, - .bdrv_refresh_limits = vxhs_refresh_limits, - .bdrv_close = vxhs_close, - .bdrv_getlength = vxhs_getlength, - .bdrv_aio_preadv = vxhs_aio_preadv, - .bdrv_aio_pwritev = vxhs_aio_pwritev, - .strong_runtime_opts = vxhs_strong_runtime_opts, -}; - -static void bdrv_vxhs_init(void) -{ - bdrv_register(&bdrv_vxhs); -} - -block_init(bdrv_vxhs_init); diff --git a/blockdev-nbd.c b/blockdev-nbd.c index 1a95d89f0096a848eab3d2a1d13daade6b0d2227..d8443d235b7338949a4e6e10dec5a8cc88fa9f32 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -14,7 +14,9 @@ #include "sysemu/block-backend.h" #include "hw/block/block.h" #include "qapi/error.h" -#include "qapi/qapi-commands-block.h" +#include "qapi/clone-visitor.h" +#include "qapi/qapi-visit-block-export.h" +#include "qapi/qapi-commands-block-export.h" #include "block/nbd.h" #include "io/channel-socket.h" #include "io/net-listener.h" @@ -23,23 +25,52 @@ typedef struct NBDServerData { QIONetListener *listener; QCryptoTLSCreds *tlscreds; char *tlsauthz; + uint32_t max_connections; + uint32_t connections; } NBDServerData; static NBDServerData *nbd_server; +static bool is_qemu_nbd; + +static void nbd_update_server_watch(NBDServerData *s); + +void nbd_server_is_qemu_nbd(bool value) +{ + is_qemu_nbd = value; +} + +bool nbd_server_is_running(void) +{ + return nbd_server || is_qemu_nbd; +} static void nbd_blockdev_client_closed(NBDClient *client, bool ignored) { nbd_client_put(client); + assert(nbd_server->connections > 0); + nbd_server->connections--; + nbd_update_server_watch(nbd_server); } static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc, gpointer opaque) { + nbd_server->connections++; + nbd_update_server_watch(nbd_server); + qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server"); nbd_client_new(cioc, nbd_server->tlscreds, nbd_server->tlsauthz, nbd_blockdev_client_closed); } +static void nbd_update_server_watch(NBDServerData *s) +{ + if (!s->max_connections || s->connections < s->max_connections) { + qio_net_listener_set_client_func(s->listener, nbd_accept, NULL, NULL); + } else { + qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL); + } +} static void nbd_server_free(NBDServerData *server) { @@ -88,7 +119,8 @@ static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, Error **errp) void nbd_server_start(SocketAddress *addr, const char *tls_creds, - const char *tls_authz, Error **errp) + const char *tls_authz, uint32_t max_connections, + Error **errp) { if (nbd_server) { error_setg(errp, "NBD server already running"); @@ -96,6 +128,7 @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds, } nbd_server = g_new0(NBDServerData, 1); + nbd_server->max_connections = max_connections; nbd_server->listener = qio_net_listener_new(); qio_net_listener_set_name(nbd_server->listener, @@ -120,10 +153,7 @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds, nbd_server->tlsauthz = g_strdup(tls_authz); - qio_net_listener_set_client_func(nbd_server->listener, - nbd_accept, - NULL, - NULL); + nbd_update_server_watch(nbd_server); return; @@ -134,117 +164,99 @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds, void nbd_server_start_options(NbdServerOptions *arg, Error **errp) { - nbd_server_start(arg->addr, arg->tls_creds, arg->tls_authz, errp); + nbd_server_start(arg->addr, arg->tls_creds, arg->tls_authz, + arg->max_connections, errp); } void qmp_nbd_server_start(SocketAddressLegacy *addr, bool has_tls_creds, const char *tls_creds, bool has_tls_authz, const char *tls_authz, + bool has_max_connections, uint32_t max_connections, Error **errp) { SocketAddress *addr_flat = socket_address_flatten(addr); - nbd_server_start(addr_flat, tls_creds, tls_authz, errp); + nbd_server_start(addr_flat, tls_creds, tls_authz, max_connections, errp); qapi_free_SocketAddress(addr_flat); } -void qmp_nbd_server_add(BlockExportNbd *arg, Error **errp) +void qmp_nbd_server_add(NbdServerAddOptions *arg, Error **errp) { - BlockDriverState *bs = NULL; + BlockExport *export; + BlockDriverState *bs; BlockBackend *on_eject_blk; - NBDExport *exp; - int64_t len; - AioContext *aio_context; + BlockExportOptions *export_opts; - if (!nbd_server) { - error_setg(errp, "NBD server not running"); + bs = bdrv_lookup_bs(arg->device, arg->device, errp); + if (!bs) { return; } + /* + * block-export-add would default to the node-name, but we may have to use + * the device name as a default here for compatibility. + */ if (!arg->has_name) { - arg->name = arg->device; + arg->has_name = true; + arg->name = g_strdup(arg->device); } - if (strlen(arg->name) > NBD_MAX_STRING_SIZE) { - error_setg(errp, "export name '%s' too long", arg->name); - return; + export_opts = g_new(BlockExportOptions, 1); + *export_opts = (BlockExportOptions) { + .type = BLOCK_EXPORT_TYPE_NBD, + .id = g_strdup(arg->name), + .node_name = g_strdup(bdrv_get_node_name(bs)), + .has_writable = arg->has_writable, + .writable = arg->writable, + }; + QAPI_CLONE_MEMBERS(BlockExportOptionsNbdBase, &export_opts->u.nbd, + qapi_NbdServerAddOptions_base(arg)); + if (arg->has_bitmap) { + export_opts->u.nbd.has_bitmaps = true; + QAPI_LIST_PREPEND(export_opts->u.nbd.bitmaps, g_strdup(arg->bitmap)); } - if (arg->description && strlen(arg->description) > NBD_MAX_STRING_SIZE) { - error_setg(errp, "description '%s' too long", arg->description); - return; + /* + * nbd-server-add doesn't complain when a read-only device should be + * exported as writable, but simply downgrades it. This is an error with + * block-export-add. + */ + if (bdrv_is_read_only(bs)) { + export_opts->has_writable = true; + export_opts->writable = false; } - if (nbd_export_find(arg->name)) { - error_setg(errp, "NBD server already has export named '%s'", arg->name); - return; + export = blk_exp_add(export_opts, errp); + if (!export) { + goto fail; } + /* + * nbd-server-add removes the export when the named BlockBackend used for + * @device goes away. + */ on_eject_blk = blk_by_name(arg->device); - - bs = bdrv_lookup_bs(arg->device, arg->device, errp); - if (!bs) { - return; - } - - aio_context = bdrv_get_aio_context(bs); - aio_context_acquire(aio_context); - len = bdrv_getlength(bs); - if (len < 0) { - error_setg_errno(errp, -len, - "Failed to determine the NBD export's length"); - goto out; + if (on_eject_blk) { + nbd_export_set_on_eject_blk(export, on_eject_blk); } - if (!arg->has_writable) { - arg->writable = false; - } - if (bdrv_is_read_only(bs)) { - arg->writable = false; - } - - exp = nbd_export_new(bs, 0, len, arg->name, arg->description, arg->bitmap, - !arg->writable, !arg->writable, - NULL, false, on_eject_blk, errp); - if (!exp) { - goto out; - } - - /* The list of named exports has a strong reference to this export now and - * our only way of accessing it is through nbd_export_find(), so we can drop - * the strong reference that is @exp. */ - nbd_export_put(exp); - - out: - aio_context_release(aio_context); +fail: + qapi_free_BlockExportOptions(export_opts); } void qmp_nbd_server_remove(const char *name, - bool has_mode, NbdServerRemoveMode mode, + bool has_mode, BlockExportRemoveMode mode, Error **errp) { - NBDExport *exp; - AioContext *aio_context; + BlockExport *exp; - if (!nbd_server) { - error_setg(errp, "NBD server not running"); + exp = blk_exp_find(name); + if (exp && exp->drv->type != BLOCK_EXPORT_TYPE_NBD) { + error_setg(errp, "Block export '%s' is not an NBD export", name); return; } - exp = nbd_export_find(name); - if (exp == NULL) { - error_setg(errp, "Export '%s' is not found", name); - return; - } - - if (!has_mode) { - mode = NBD_SERVER_REMOVE_MODE_SAFE; - } - - aio_context = nbd_export_aio_context(exp); - aio_context_acquire(aio_context); - nbd_export_remove(exp, mode, errp); - aio_context_release(aio_context); + qmp_block_export_del(name, has_mode, mode, errp); } void qmp_nbd_server_stop(Error **errp) @@ -254,7 +266,7 @@ void qmp_nbd_server_stop(Error **errp) return; } - nbd_export_close_all(); + blk_exp_close_all_type(BLOCK_EXPORT_TYPE_NBD); nbd_server_free(nbd_server); nbd_server = NULL; diff --git a/blockdev.c b/blockdev.c index 72df193ca73b30d1722a130fbddf12823ad3556c..fe6fb5dc1d19716fba52e8b900e2763aad25f601 100644 --- a/blockdev.c +++ b/blockdev.c @@ -59,6 +59,7 @@ #include "sysemu/arch_init.h" #include "sysemu/qtest.h" #include "sysemu/runstate.h" +#include "sysemu/replay.h" #include "qemu/cutils.h" #include "qemu/help_option.h" #include "qemu/main-loop.h" @@ -239,6 +240,19 @@ DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit) return NULL; } +void drive_mark_claimed_by_board(void) +{ + BlockBackend *blk; + DriveInfo *dinfo; + + for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { + dinfo = blk_legacy_dinfo(blk); + if (dinfo && blk_get_attached_dev(blk)) { + dinfo->claimed_by_board = true; + } + } +} + void drive_check_orphaned(void) { BlockBackend *blk; @@ -248,8 +262,10 @@ void drive_check_orphaned(void) for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { dinfo = blk_legacy_dinfo(blk); - if (!blk_get_attached_dev(blk) && !dinfo->is_default && - dinfo->type != IF_NONE) { + if (dinfo->is_default || dinfo->type == IF_NONE) { + continue; + } + if (!blk_get_attached_dev(blk)) { loc_push_none(&loc); qemu_opts_loc_restore(dinfo->opts); error_report("machine type does not support" @@ -257,6 +273,14 @@ void drive_check_orphaned(void) if_name[dinfo->type], dinfo->bus, dinfo->unit); loc_pop(&loc); orphans = true; + continue; + } + if (!dinfo->claimed_by_board && dinfo->type != IF_VIRTIO) { + loc_push_none(&loc); + qemu_opts_loc_restore(dinfo->opts); + warn_report("bogus if=%s is deprecated, use if=none", + if_name[dinfo->type]); + loc_pop(&loc); } } @@ -481,15 +505,12 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, /* Check common options by copying from bs_opts to opts, all other options * stay in bs_opts for processing by bdrv_open(). */ id = qdict_get_try_str(bs_opts, "id"); - opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error); - if (error) { - error_propagate(errp, error); + opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, errp); + if (!opts) { goto err_no_opts; } - qemu_opts_absorb_qdict(opts, bs_opts, &error); - if (error) { - error_propagate(errp, error); + if (!qemu_opts_absorb_qdict(opts, bs_opts, errp)) { goto early_err; } @@ -683,7 +704,7 @@ BlockDriverState *bdrv_next_monitor_owned(BlockDriverState *bs) : QTAILQ_FIRST(&monitor_bdrv_states); } -static void qemu_opt_rename(QemuOpts *opts, const char *from, const char *to, +static bool qemu_opt_rename(QemuOpts *opts, const char *from, const char *to, Error **errp) { const char *value; @@ -693,7 +714,7 @@ static void qemu_opt_rename(QemuOpts *opts, const char *from, const char *to, if (qemu_opt_find(opts, to)) { error_setg(errp, "'%s' and its alias '%s' can't be used at the " "same time", to, from); - return; + return false; } } @@ -702,6 +723,7 @@ static void qemu_opt_rename(QemuOpts *opts, const char *from, const char *to, qemu_opt_set(opts, to, value, &error_abort); qemu_opt_unset(opts, from); } + return true; } QemuOptsList qemu_legacy_drive_opts = { @@ -772,7 +794,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type, bool read_only = false; bool copy_on_read; const char *filename; - Error *local_err = NULL; int i; /* Change legacy command line options into QMP ones */ @@ -804,10 +825,8 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type, }; for (i = 0; i < ARRAY_SIZE(opt_renames); i++) { - qemu_opt_rename(all_opts, opt_renames[i].from, opt_renames[i].to, - &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opt_rename(all_opts, opt_renames[i].from, + opt_renames[i].to, errp)) { return NULL; } } @@ -844,9 +863,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type, legacy_opts = qemu_opts_create(&qemu_legacy_drive_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(legacy_opts, bs_opts, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(legacy_opts, bs_opts, errp)) { goto fail; } @@ -986,13 +1003,10 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type, } /* Actual block device init: Functionality shared with blockdev-add */ - blk = blockdev_init(filename, bs_opts, &local_err); + blk = blockdev_init(filename, bs_opts, errp); bs_opts = NULL; if (!blk) { - error_propagate(errp, local_err); goto fail; - } else { - assert(!local_err); } /* Create legacy DriveInfo */ @@ -1177,6 +1191,10 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device, info->vm_state_size = sn.vm_state_size; info->vm_clock_nsec = sn.vm_clock_nsec % 1000000000; info->vm_clock_sec = sn.vm_clock_nsec / 1000000000; + if (sn.icount != -1ULL) { + info->icount = sn.icount; + info->has_icount = true; + } return info; @@ -1337,6 +1355,11 @@ static void internal_snapshot_prepare(BlkActionState *common, sn->date_sec = tv.tv_sec; sn->date_nsec = tv.tv_usec * 1000; sn->vm_clock_nsec = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + if (replay_mode != REPLAY_MODE_NONE) { + sn->icount = replay_get_current_icount(); + } else { + sn->icount = -1ULL; + } ret1 = bdrv_snapshot_create(bs, sn); if (ret1 < 0) { @@ -1549,7 +1572,12 @@ static void external_snapshot_prepare(BlkActionState *common, goto out; } - if (state->new_bs->backing != NULL) { + if (state->new_bs->drv->is_filter) { + error_setg(errp, "Filters cannot be used as overlays"); + goto out; + } + + if (bdrv_cow_child(state->new_bs)) { error_setg(errp, "The overlay already has a backing image"); goto out; } @@ -1586,7 +1614,7 @@ static void external_snapshot_commit(BlkActionState *common) /* We don't need (or want) to use the transactional * bdrv_reopen_multiple() across all the entries at once, because we * don't want to abort all of them if one of them fails the reopen */ - if (!atomic_read(&state->old_bs->copy_on_read)) { + if (!qatomic_read(&state->old_bs->copy_on_read)) { bdrv_reopen_set_read_only(state->old_bs, true, NULL); } @@ -1723,7 +1751,13 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp) * on top of. */ if (backup->sync == MIRROR_SYNC_MODE_TOP) { - source = backing_bs(bs); + /* + * Backup will not replace the source by the target, so none + * of the filters skipped here will be removed (in contrast to + * mirror). Therefore, we can skip all of them when looking + * for the first COW relationship. + */ + source = bdrv_cow_bs(bdrv_skip_filters(bs)); if (!source) { backup->sync = MIRROR_SYNC_MODE_FULL; } @@ -1743,9 +1777,14 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp) if (backup->mode != NEW_IMAGE_MODE_EXISTING) { assert(backup->format); if (source) { - bdrv_refresh_filename(source); - bdrv_img_create(backup->target, backup->format, source->filename, - source->drv->format_name, NULL, + /* Implicit filters should not appear in the filename */ + BlockDriverState *explicit_backing = + bdrv_skip_implicit_filters(source); + + bdrv_refresh_filename(explicit_backing); + bdrv_img_create(backup->target, backup->format, + explicit_backing->filename, + explicit_backing->drv->format_name, NULL, size, flags, false, &local_err); } else { bdrv_img_create(backup->target, backup->format, NULL, NULL, NULL, @@ -2410,14 +2449,14 @@ BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *node, return ret; } -void qmp_block_resize(bool has_device, const char *device, - bool has_node_name, const char *node_name, - int64_t size, Error **errp) +void coroutine_fn qmp_block_resize(bool has_device, const char *device, + bool has_node_name, const char *node_name, + int64_t size, Error **errp) { Error *local_err = NULL; BlockBackend *blk = NULL; BlockDriverState *bs; - AioContext *aio_context; + AioContext *old_ctx; bs = bdrv_lookup_bs(has_device ? device : NULL, has_node_name ? node_name : NULL, @@ -2427,9 +2466,6 @@ void qmp_block_resize(bool has_device, const char *device, return; } - aio_context = bdrv_get_aio_context(bs); - aio_context_acquire(aio_context); - if (size < 0) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "size", "a >0 size"); goto out; @@ -2446,12 +2482,15 @@ void qmp_block_resize(bool has_device, const char *device, } bdrv_drained_begin(bs); + old_ctx = bdrv_co_enter(bs); blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp); + bdrv_co_leave(bs, old_ctx); bdrv_drained_end(bs); out: + bdrv_co_lock(bs); blk_unref(blk); - aio_context_release(aio_context); + bdrv_co_unlock(bs); } void qmp_block_stream(bool has_job_id, const char *job_id, const char *device, @@ -2515,7 +2554,9 @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device, } /* Check for op blockers in the whole chain between bs and base */ - for (iter = bs; iter && iter != base_bs; iter = backing_bs(iter)) { + for (iter = bs; iter && iter != base_bs; + iter = bdrv_filter_or_cow_bs(iter)) + { if (bdrv_op_is_blocked(iter, BLOCK_OP_TYPE_STREAM, errp)) { goto out; } @@ -2571,6 +2612,7 @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device, AioContext *aio_context; Error *local_err = NULL; int job_flags = JOB_DEFAULT; + uint64_t top_perm, top_shared; if (!has_speed) { speed = 0; @@ -2672,7 +2714,9 @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device, assert(bdrv_get_aio_context(base_bs) == aio_context); - for (iter = top_bs; iter != backing_bs(base_bs); iter = backing_bs(iter)) { + for (iter = top_bs; iter != bdrv_filter_or_cow_bs(base_bs); + iter = bdrv_filter_or_cow_bs(iter)) + { if (bdrv_op_is_blocked(iter, BLOCK_OP_TYPE_COMMIT_TARGET, errp)) { goto out; } @@ -2684,14 +2728,38 @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device, goto out; } - if (top_bs == bs) { + /* + * Active commit is required if and only if someone has taken a + * WRITE permission on the top node. Historically, we have always + * used active commit for top nodes, so continue that practice + * lest we possibly break clients that rely on this behavior, e.g. + * to later attach this node to a writing parent. + * (Active commit is never really wrong.) + */ + bdrv_get_cumulative_perm(top_bs, &top_perm, &top_shared); + if (top_perm & BLK_PERM_WRITE || + bdrv_skip_filters(top_bs) == bdrv_skip_filters(bs)) + { if (has_backing_file) { - error_setg(errp, "'backing-file' specified," - " but 'top' is the active layer"); + if (bdrv_skip_filters(top_bs) == bdrv_skip_filters(bs)) { + error_setg(errp, "'backing-file' specified," + " but 'top' is the active layer"); + } else { + error_setg(errp, "'backing-file' specified, but 'top' has a " + "writer on it"); + } goto out; } - commit_active_start(has_job_id ? job_id : NULL, bs, base_bs, - job_flags, speed, on_error, + if (!has_job_id) { + /* + * Emulate here what block_job_create() does, because it + * is possible that @bs != @top_bs (the block job should + * be named after @bs, even if @top_bs is the actual + * source) + */ + job_id = bdrv_get_device_name(bs); + } + commit_active_start(job_id, top_bs, base_bs, job_flags, speed, on_error, filter_node_name, NULL, NULL, false, &local_err); } else { BlockDriverState *overlay_bs = bdrv_find_overlay(bs, top_bs); @@ -2879,6 +2947,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs, bool has_auto_dismiss, bool auto_dismiss, Error **errp) { + BlockDriverState *unfiltered_bs; int job_flags = JOB_DEFAULT; if (!has_speed) { @@ -2930,10 +2999,19 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs, return; } - if (!bs->backing && sync == MIRROR_SYNC_MODE_TOP) { + if (!bdrv_backing_chain_next(bs) && sync == MIRROR_SYNC_MODE_TOP) { sync = MIRROR_SYNC_MODE_FULL; } + if (!has_replaces) { + /* We want to mirror from @bs, but keep implicit filters on top */ + unfiltered_bs = bdrv_skip_implicit_filters(bs); + if (unfiltered_bs != bs) { + replaces = unfiltered_bs->node_name; + has_replaces = true; + } + } + if (has_replaces) { BlockDriverState *to_replace_bs; AioContext *replace_aio_context; @@ -2980,7 +3058,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs, void qmp_drive_mirror(DriveMirror *arg, Error **errp) { BlockDriverState *bs; - BlockDriverState *source, *target_bs; + BlockDriverState *target_backing_bs, *target_bs; AioContext *aio_context; AioContext *old_context; BlockMirrorBackingMode backing_mode; @@ -3015,12 +3093,12 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) } flags = bs->open_flags | BDRV_O_RDWR; - source = backing_bs(bs); - if (!source && arg->sync == MIRROR_SYNC_MODE_TOP) { + target_backing_bs = bdrv_cow_bs(bdrv_skip_filters(bs)); + if (!target_backing_bs && arg->sync == MIRROR_SYNC_MODE_TOP) { arg->sync = MIRROR_SYNC_MODE_FULL; } if (arg->sync == MIRROR_SYNC_MODE_NONE) { - source = bs; + target_backing_bs = bs; } size = bdrv_getlength(bs); @@ -3046,7 +3124,7 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) /* Don't open backing image in create() */ flags |= BDRV_O_NO_BACKING; - if ((arg->sync == MIRROR_SYNC_MODE_FULL || !source) + if ((arg->sync == MIRROR_SYNC_MODE_FULL || !target_backing_bs) && arg->mode != NEW_IMAGE_MODE_EXISTING) { /* create new image w/o backing file */ @@ -3054,15 +3132,19 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) bdrv_img_create(arg->target, format, NULL, NULL, NULL, size, flags, false, &local_err); } else { + /* Implicit filters should not appear in the filename */ + BlockDriverState *explicit_backing = + bdrv_skip_implicit_filters(target_backing_bs); + switch (arg->mode) { case NEW_IMAGE_MODE_EXISTING: break; case NEW_IMAGE_MODE_ABSOLUTE_PATHS: /* create new image with backing file */ - bdrv_refresh_filename(source); + bdrv_refresh_filename(explicit_backing); bdrv_img_create(arg->target, format, - source->filename, - source->drv->format_name, + explicit_backing->filename, + explicit_backing->drv->format_name, NULL, size, flags, false, &local_err); break; default: @@ -3124,9 +3206,8 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) arg->has_copy_mode, arg->copy_mode, arg->has_auto_finalize, arg->auto_finalize, arg->has_auto_dismiss, arg->auto_dismiss, - &local_err); + errp); bdrv_unref(target_bs); - error_propagate(errp, local_err); out: aio_context_release(aio_context); } @@ -3154,7 +3235,6 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id, AioContext *aio_context; AioContext *old_context; BlockMirrorBackingMode backing_mode = MIRROR_LEAVE_BACKING_CHAIN; - Error *local_err = NULL; bool zero_target; int ret; @@ -3196,8 +3276,7 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id, has_copy_mode, copy_mode, has_auto_finalize, auto_finalize, has_auto_dismiss, auto_dismiss, - &local_err); - error_propagate(errp, local_err); + errp); out: aio_context_release(aio_context); } @@ -3406,7 +3485,8 @@ void qmp_change_backing_file(const char *device, } ret = bdrv_change_backing_file(image_bs, backing_file, - image_bs->drv ? image_bs->drv->format_name : ""); + image_bs->drv ? image_bs->drv->format_name : "", + false); if (ret < 0) { error_setg_errno(errp, -ret, "Could not change backing file to '%s'", @@ -3416,8 +3496,7 @@ void qmp_change_backing_file(const char *device, } if (ro) { - bdrv_reopen_set_read_only(image_bs, true, &local_err); - error_propagate(errp, local_err); + bdrv_reopen_set_read_only(image_bs, true, errp); } out: diff --git a/blockjob.c b/blockjob.c index 470facfd47a08b3c084796cc64e7521774a3175b..98ac8af98299ac26c50ce5e4c5bb82f39e1a54c6 100644 --- a/blockjob.c +++ b/blockjob.c @@ -298,7 +298,7 @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp) info = g_new0(BlockJobInfo, 1); info->type = g_strdup(job_type_str(&job->job)); info->device = g_strdup(job->job.id); - info->busy = atomic_read(&job->job.busy); + info->busy = qatomic_read(&job->job.busy); info->paused = job->job.pause_count > 0; info->offset = job->job.progress.current; info->len = job->job.progress.total; diff --git a/bsd-user/Makefile.objs b/bsd-user/Makefile.objs deleted file mode 100644 index 5e77f57782a152b2ee96e7b197ed12fb21be7d9f..0000000000000000000000000000000000000000 --- a/bsd-user/Makefile.objs +++ /dev/null @@ -1,2 +0,0 @@ -obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \ - uaccess.o diff --git a/bsd-user/main.c b/bsd-user/main.c index 0bfe46cff93e723fd1f135528eb65bb35a3c8a91..0a918e8f746e7997ffd0b40e8d5010a8de73e009 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -413,7 +413,11 @@ static void save_window(CPUSPARCState *env) save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); env->wim = new_wim; #else - save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); + /* + * cansave is zero if the spill trap handler is triggered by `save` and + * nonzero if triggered by a `flushw` + */ + save_window_offset(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2)); env->cansave++; env->canrestore--; #endif @@ -741,7 +745,6 @@ int main(int argc, char **argv) const char *gdbstub = NULL; char **target_environ, **wrk; envlist_t *envlist = NULL; - char *trace_file = NULL; bsd_type = target_openbsd; if (argc <= 1) @@ -847,8 +850,7 @@ int main(int argc, char **argv) } else if (!strcmp(r, "strace")) { do_strace = 1; } else if (!strcmp(r, "trace")) { - g_free(trace_file); - trace_file = trace_opt_parse(optarg); + trace_opt_parse(optarg); } else { usage(); } @@ -876,7 +878,7 @@ int main(int argc, char **argv) if (!trace_init_backends()) { exit(1); } - trace_init_file(trace_file); + trace_init_file(); /* Zero out regs */ memset(regs, 0, sizeof(struct target_pt_regs)); diff --git a/bsd-user/meson.build b/bsd-user/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..0369549340844d6c7b79ac4b570624fda774c47c --- /dev/null +++ b/bsd-user/meson.build @@ -0,0 +1,10 @@ +bsd_user_ss.add(files( + 'bsdload.c', + 'elfload.c', + 'main.c', + 'mmap.c', + 'signal.c', + 'strace.c', + 'syscall.c', + 'uaccess.c', +)) diff --git a/capstone b/capstone index 22ead3e0bfdb87516656453336160e0a37b066bf..f8b1b833015a4ae47110ed068e0deb7106ced66d 160000 --- a/capstone +++ b/capstone @@ -1 +1 @@ -Subproject commit 22ead3e0bfdb87516656453336160e0a37b066bf +Subproject commit f8b1b833015a4ae47110ed068e0deb7106ced66d diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs deleted file mode 100644 index d68e1347f9afb5dffd4eec63831832fafac8ddf3..0000000000000000000000000000000000000000 --- a/chardev/Makefile.objs +++ /dev/null @@ -1,25 +0,0 @@ -chardev-obj-y += char.o -chardev-obj-$(CONFIG_WIN32) += char-console.o -chardev-obj-$(CONFIG_POSIX) += char-fd.o -chardev-obj-y += char-fe.o -chardev-obj-y += char-file.o -chardev-obj-y += char-io.o -chardev-obj-y += char-mux.o -chardev-obj-y += char-null.o -chardev-obj-$(CONFIG_POSIX) += char-parallel.o -chardev-obj-y += char-pipe.o -chardev-obj-$(CONFIG_POSIX) += char-pty.o -chardev-obj-y += char-ringbuf.o -chardev-obj-y += char-serial.o -chardev-obj-y += char-socket.o -chardev-obj-y += char-stdio.o -chardev-obj-y += char-udp.o -chardev-obj-$(CONFIG_WIN32) += char-win.o -chardev-obj-$(CONFIG_WIN32) += char-win-stdio.o - -common-obj-y += msmouse.o wctablet.o testdev.o -common-obj-$(CONFIG_BRLAPI) += baum.o -baum.o-cflags := $(SDL_CFLAGS) -baum.o-libs := $(BRLAPI_LIBS) - -common-obj-$(CONFIG_SPICE) += spice.o diff --git a/chardev/baum.c b/chardev/baum.c index 9c95e7bc7985e0932ab5ec623fe294d364ed858c..5deca778bc447af946b75def9691eae1b0e613a3 100644 --- a/chardev/baum.c +++ b/chardev/baum.c @@ -33,6 +33,7 @@ #include #include #include +#include "qom/object.h" #if 0 #define DPRINTF(fmt, ...) \ @@ -86,7 +87,7 @@ #define BUF_SIZE 256 -typedef struct { +struct BaumChardev { Chardev parent; brlapi_handle_t *brlapi; @@ -100,10 +101,12 @@ typedef struct { uint8_t out_buf_used, out_buf_ptr; QEMUTimer *cellCount_timer; -} BaumChardev; +}; +typedef struct BaumChardev BaumChardev; #define TYPE_CHARDEV_BRAILLE "chardev-braille" -#define BAUM_CHARDEV(obj) OBJECT_CHECK(BaumChardev, (obj), TYPE_CHARDEV_BRAILLE) +DECLARE_INSTANCE_CHECKER(BaumChardev, BAUM_CHARDEV, + TYPE_CHARDEV_BRAILLE) /* Let's assume NABCC by default */ enum way { diff --git a/chardev/char-fd.c b/chardev/char-fd.c index c2d81011063387a6fb0243a337dbdd1f7e31c95a..1cd62f2779b2b69e3ce6a1d073cd0da5fead571f 100644 --- a/chardev/char-fd.c +++ b/chardev/char-fd.c @@ -119,7 +119,7 @@ int qmp_chardev_open_file_source(char *src, int flags, Error **errp) { int fd = -1; - TFR(fd = qemu_open(src, flags, 0666)); + TFR(fd = qemu_open_old(src, flags, 0666)); if (fd == -1) { error_setg_file_open(errp, errno, src); } diff --git a/chardev/char-fe.c b/chardev/char-fe.c index f3530a90e6364d813097105b611326afd7903b41..474715c5a9257ae9e9e286d2e02dacb8a6fcbfe6 100644 --- a/chardev/char-fe.c +++ b/chardev/char-fe.c @@ -29,7 +29,7 @@ #include "chardev/char-fe.h" #include "chardev/char-io.h" -#include "chardev/char-mux.h" +#include "chardev-internal.h" int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len) { diff --git a/chardev/char-mux.c b/chardev/char-mux.c index 46c44af67c4ea5348eb1b6db637f62b8107c46be..6f980bb83647da13c62f514391b33fbabe13aac7 100644 --- a/chardev/char-mux.c +++ b/chardev/char-mux.c @@ -29,7 +29,7 @@ #include "chardev/char.h" #include "sysemu/block-backend.h" #include "sysemu/sysemu.h" -#include "chardev/char-mux.h" +#include "chardev-internal.h" /* MUX driver for serial I/O splitting */ diff --git a/chardev/char-pipe.c b/chardev/char-pipe.c index fd12c9e63b5313cdfd972aa815b7db4ae659dff7..7eca5d9a56aeeb00a6948e62c2f1c78975fe2339 100644 --- a/chardev/char-pipe.c +++ b/chardev/char-pipe.c @@ -132,8 +132,8 @@ static void qemu_chr_open_pipe(Chardev *chr, filename_in = g_strdup_printf("%s.in", filename); filename_out = g_strdup_printf("%s.out", filename); - TFR(fd_in = qemu_open(filename_in, O_RDWR | O_BINARY)); - TFR(fd_out = qemu_open(filename_out, O_RDWR | O_BINARY)); + TFR(fd_in = qemu_open_old(filename_in, O_RDWR | O_BINARY)); + TFR(fd_out = qemu_open_old(filename_out, O_RDWR | O_BINARY)); g_free(filename_in); g_free(filename_out); if (fd_in < 0 || fd_out < 0) { @@ -143,7 +143,7 @@ static void qemu_chr_open_pipe(Chardev *chr, if (fd_out >= 0) { close(fd_out); } - TFR(fd_in = fd_out = qemu_open(filename, O_RDWR | O_BINARY)); + TFR(fd_in = fd_out = qemu_open_old(filename, O_RDWR | O_BINARY)); if (fd_in < 0) { error_setg_file_open(errp, errno, filename); return; diff --git a/chardev/char-pty.c b/chardev/char-pty.c index 1cc501a481edeb94023e9300c0632ed59a867691..a2d1e7c985bc49a76b27abb44998332df4f3da47 100644 --- a/chardev/char-pty.c +++ b/chardev/char-pty.c @@ -33,17 +33,20 @@ #include "qemu/qemu-print.h" #include "chardev/char-io.h" +#include "qom/object.h" -typedef struct { +struct PtyChardev { Chardev parent; QIOChannel *ioc; int read_bytes; int connected; GSource *timer_src; -} PtyChardev; +}; +typedef struct PtyChardev PtyChardev; -#define PTY_CHARDEV(obj) OBJECT_CHECK(PtyChardev, (obj), TYPE_CHARDEV_PTY) +DECLARE_INSTANCE_CHECKER(PtyChardev, PTY_CHARDEV, + TYPE_CHARDEV_PTY) static void pty_chr_state(Chardev *chr, int connected); diff --git a/chardev/char-ringbuf.c b/chardev/char-ringbuf.c index 67397a8ce944b47379c0139984f96d8e649ddcd0..d40d21d3cf78cb0ab5ac997909c6009b313ca41b 100644 --- a/chardev/char-ringbuf.c +++ b/chardev/char-ringbuf.c @@ -29,19 +29,21 @@ #include "qemu/base64.h" #include "qemu/module.h" #include "qemu/option.h" +#include "qom/object.h" /* Ring buffer chardev */ -typedef struct { +struct RingBufChardev { Chardev parent; size_t size; size_t prod; size_t cons; uint8_t *cbuf; -} RingBufChardev; +}; +typedef struct RingBufChardev RingBufChardev; -#define RINGBUF_CHARDEV(obj) \ - OBJECT_CHECK(RingBufChardev, (obj), TYPE_CHARDEV_RINGBUF) +DECLARE_INSTANCE_CHECKER(RingBufChardev, RINGBUF_CHARDEV, + TYPE_CHARDEV_RINGBUF) static size_t ringbuf_count(const Chardev *chr) { diff --git a/chardev/char-socket.c b/chardev/char-socket.c index e77699db4848788f4adda908d1ca58d232aa2e42..213a4c8dd0d9b50087e630121555fbff9374d3bd 100644 --- a/chardev/char-socket.c +++ b/chardev/char-socket.c @@ -36,6 +36,7 @@ #include "qapi/qapi-visit-sockets.h" #include "chardev/char-io.h" +#include "qom/object.h" /***********************************************************/ /* TCP Net console */ @@ -53,7 +54,7 @@ typedef enum { TCP_CHARDEV_STATE_CONNECTED, } TCPChardevState; -typedef struct { +struct SocketChardev { Chardev parent; QIOChannel *ioc; /* Client I/O channel */ QIOChannelSocket *sioc; /* Client master channel */ @@ -84,10 +85,11 @@ typedef struct { bool connect_err_reported; QIOTask *connect_task; -} SocketChardev; +}; +typedef struct SocketChardev SocketChardev; -#define SOCKET_CHARDEV(obj) \ - OBJECT_CHECK(SocketChardev, (obj), TYPE_CHARDEV_SOCKET) +DECLARE_INSTANCE_CHECKER(SocketChardev, SOCKET_CHARDEV, + TYPE_CHARDEV_SOCKET) static gboolean socket_reconnect_timeout(gpointer opaque); static void tcp_chr_telnet_init(Chardev *chr); @@ -138,9 +140,12 @@ static void check_report_connect_error(Chardev *chr, SocketChardev *s = SOCKET_CHARDEV(chr); if (!s->connect_err_reported) { - error_report("Unable to connect character device %s: %s", - chr->label, error_get_pretty(err)); + error_reportf_err(err, + "Unable to connect character device %s: ", + chr->label); s->connect_err_reported = true; + } else { + error_free(err); } qemu_chr_socket_restart_timer(chr); } @@ -174,15 +179,16 @@ static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len) if (ret < 0 && errno != EAGAIN) { if (tcp_chr_read_poll(chr) <= 0) { + /* Perform disconnect and return error. */ tcp_chr_disconnect_locked(chr); - return len; } /* else let the read handler finish it properly */ } return ret; } else { - /* XXX: indicate an error ? */ - return len; + /* Indicate an error. */ + errno = EIO; + return -1; } } @@ -437,10 +443,24 @@ static char *qemu_chr_socket_address(SocketChardev *s, const char *prefix) s->is_listen ? ",server" : ""); break; case SOCKET_ADDRESS_TYPE_UNIX: - return g_strdup_printf("%sunix:%s%s", prefix, - s->addr->u.q_unix.path, + { + const char *tight = "", *abstract = ""; + UnixSocketAddress *sa = &s->addr->u.q_unix; + +#ifdef CONFIG_LINUX + if (sa->has_abstract && sa->abstract) { + abstract = ",abstract"; + if (sa->has_tight && sa->tight) { + tight = ",tight"; + } + } +#endif + + return g_strdup_printf("%sunix:%s%s%s%s", prefix, sa->path, + abstract, tight, s->is_listen ? ",server" : ""); break; + } case SOCKET_ADDRESS_TYPE_FD: return g_strdup_printf("%sfd:%s%s", prefix, s->addr->u.fd.str, s->is_listen ? ",server" : ""); @@ -486,7 +506,7 @@ static void tcp_chr_disconnect_locked(Chardev *chr) if (emit_close) { qemu_chr_be_event(chr, CHR_EVENT_CLOSED); } - if (s->reconnect_time) { + if (s->reconnect_time && !s->reconnect_timer) { qemu_chr_socket_restart_timer(chr); } } @@ -549,7 +569,9 @@ static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len) qio_channel_set_blocking(s->ioc, true, NULL); size = tcp_chr_recv(chr, (void *) buf, len); - qio_channel_set_blocking(s->ioc, false, NULL); + if (s->state != TCP_CHARDEV_STATE_DISCONNECTED) { + qio_channel_set_blocking(s->ioc, false, NULL); + } if (size == 0) { /* connection closed */ tcp_chr_disconnect(chr); @@ -811,22 +833,20 @@ static void tcp_chr_tls_init(Chardev *chr) { SocketChardev *s = SOCKET_CHARDEV(chr); QIOChannelTLS *tioc; - Error *err = NULL; gchar *name; if (s->is_listen) { tioc = qio_channel_tls_new_server( s->ioc, s->tls_creds, s->tls_authz, - &err); + NULL); } else { tioc = qio_channel_tls_new_client( s->ioc, s->tls_creds, s->addr->u.inet.host, - &err); + NULL); } if (tioc == NULL) { - error_free(err); tcp_chr_disconnect(chr); return; } @@ -1082,7 +1102,6 @@ static void qemu_chr_socket_connected(QIOTask *task, void *opaque) if (qio_task_propagate_error(task, &err)) { tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED); check_report_connect_error(chr, err); - error_free(err); goto cleanup; } @@ -1126,7 +1145,8 @@ static void tcp_chr_connect_client_async(Chardev *chr) */ s->connect_task = qio_task_new(OBJECT(sioc), qemu_chr_socket_connected, - chr, NULL); + object_ref(OBJECT(chr)), + (GDestroyNotify)object_unref); qio_task_run_in_thread(s->connect_task, tcp_chr_connect_client_task, s->addr, @@ -1380,8 +1400,10 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend, const char *host = qemu_opt_get(opts, "host"); const char *port = qemu_opt_get(opts, "port"); const char *fd = qemu_opt_get(opts, "fd"); +#ifdef CONFIG_LINUX bool tight = qemu_opt_get_bool(opts, "tight", true); bool abstract = qemu_opt_get_bool(opts, "abstract", false); +#endif SocketAddressLegacy *addr; ChardevSocket *sock; @@ -1433,8 +1455,12 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend, addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX; q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1); q_unix->path = g_strdup(path); +#ifdef CONFIG_LINUX + q_unix->has_tight = true; q_unix->tight = tight; + q_unix->has_abstract = true; q_unix->abstract = abstract; +#endif } else if (host) { addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET; addr->u.inet.data = g_new(InetSocketAddress, 1); diff --git a/chardev/char-stdio.c b/chardev/char-stdio.c index 82eaebc1db6528b9238455d0ae3710134abaebee..403da308c980ebf24eaacb61cc2e77c6ffb5ad03 100644 --- a/chardev/char-stdio.c +++ b/chardev/char-stdio.c @@ -112,9 +112,7 @@ static void qemu_chr_open_stdio(Chardev *chr, qemu_chr_open_fd(chr, 0, 1); - if (opts->has_signal) { - stdio_allow_signal = opts->signal; - } + stdio_allow_signal = !opts->has_signal || opts->signal; qemu_chr_set_echo_stdio(chr, false); } #endif diff --git a/chardev/char-udp.c b/chardev/char-udp.c index bba4145f96e88e17dd9f10d142efe15b8c7bfcb6..16b5dbce5824327f649fd2a7a9890a93d3bf7402 100644 --- a/chardev/char-udp.c +++ b/chardev/char-udp.c @@ -30,20 +30,23 @@ #include "qemu/option.h" #include "chardev/char-io.h" +#include "qom/object.h" /***********************************************************/ /* UDP Net console */ -typedef struct { +struct UdpChardev { Chardev parent; QIOChannel *ioc; uint8_t buf[CHR_READ_BUF_LEN]; int bufcnt; int bufptr; int max_size; -} UdpChardev; +}; +typedef struct UdpChardev UdpChardev; -#define UDP_CHARDEV(obj) OBJECT_CHECK(UdpChardev, (obj), TYPE_CHARDEV_UDP) +DECLARE_INSTANCE_CHECKER(UdpChardev, UDP_CHARDEV, + TYPE_CHARDEV_UDP) /* Called with chr_write_lock held. */ static int udp_chr_write(Chardev *chr, const uint8_t *buf, int len) diff --git a/chardev/char-win-stdio.c b/chardev/char-win-stdio.c index 99afda353c57b2d67fe26bb832122d72d7462509..a4771ab82e64d69bd2baee76e4c8ac4179b4a009 100644 --- a/chardev/char-win-stdio.c +++ b/chardev/char-win-stdio.c @@ -28,18 +28,20 @@ #include "qemu/module.h" #include "chardev/char-win.h" #include "chardev/char-win-stdio.h" +#include "qom/object.h" -typedef struct { +struct WinStdioChardev { Chardev parent; HANDLE hStdIn; HANDLE hInputReadyEvent; HANDLE hInputDoneEvent; HANDLE hInputThread; uint8_t win_stdio_buf; -} WinStdioChardev; +}; +typedef struct WinStdioChardev WinStdioChardev; -#define WIN_STDIO_CHARDEV(obj) \ - OBJECT_CHECK(WinStdioChardev, (obj), TYPE_CHARDEV_WIN_STDIO) +DECLARE_INSTANCE_CHECKER(WinStdioChardev, WIN_STDIO_CHARDEV, + TYPE_CHARDEV_WIN_STDIO) static void win_stdio_wait_func(void *opaque) { diff --git a/chardev/char.c b/chardev/char.c index ea06c5ff4d9b667d8caf757ed0250946326405a1..aa4282164acabbba58a6eea76b8cabf346b79ad5 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -38,13 +38,14 @@ #include "qemu/module.h" #include "qemu/option.h" #include "qemu/id.h" +#include "qemu/coroutine.h" -#include "chardev/char-mux.h" +#include "chardev-internal.h" /***********************************************************/ /* character device */ -static Object *get_chardevs_root(void) +Object *get_chardevs_root(void) { return container_get(object_get_root(), "/chardevs"); } @@ -119,7 +120,11 @@ static int qemu_chr_write_buffer(Chardev *s, retry: res = cc->chr_write(s, buf + *offset, len - *offset); if (res < 0 && errno == EAGAIN && write_all) { - g_usleep(100); + if (qemu_in_coroutine()) { + qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 100000); + } else { + g_usleep(100); + } goto retry; } @@ -133,7 +138,20 @@ static int qemu_chr_write_buffer(Chardev *s, } } if (*offset > 0) { + /* + * If some data was written by backend, we should + * only log what was actually written. This method + * may be invoked again to write the remaining + * method, thus we'll log the remainder at that time. + */ qemu_chr_write_log(s, buf, *offset); + } else if (res < 0) { + /* + * If a fatal error was reported by the backend, + * assume this method won't be invoked again with + * this buffer, so log it all right away. + */ + qemu_chr_write_log(s, buf, len); } qemu_mutex_unlock(&s->chr_write_lock); @@ -230,7 +248,7 @@ static void qemu_char_open(Chardev *chr, ChardevBackend *backend, } else { flags |= O_TRUNC; } - chr->logfd = qemu_open(common->logfile, flags, 0666); + chr->logfd = qemu_open_old(common->logfile, flags, 0666); if (chr->logfd < 0) { error_setg_errno(errp, errno, "Unable to open logfile %s", @@ -300,33 +318,6 @@ static const TypeInfo char_type_info = { .class_init = char_class_init, }; -static int chardev_machine_done_notify_one(Object *child, void *opaque) -{ - Chardev *chr = (Chardev *)child; - ChardevClass *class = CHARDEV_GET_CLASS(chr); - - if (class->chr_machine_done) { - return class->chr_machine_done(chr); - } - - return 0; -} - -static void chardev_machine_done_hook(Notifier *notifier, void *unused) -{ - int ret = object_child_foreach(get_chardevs_root(), - chardev_machine_done_notify_one, NULL); - - if (ret) { - error_report("Failed to call chardev machine_done hooks"); - exit(1); - } -} - -static Notifier chardev_machine_done_notify = { - .notify = chardev_machine_done_hook, -}; - static bool qemu_chr_is_busy(Chardev *s) { if (CHARDEV_IS_MUX(s)) { @@ -439,8 +430,7 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename, qemu_opt_set(opts, "host", host, &error_abort); qemu_opt_set(opts, "port", port, &error_abort); if (p[pos] == ',') { - qemu_opts_do_parse(opts, p+pos+1, NULL, &local_err); - if (local_err) { + if (!qemu_opts_do_parse(opts, p + pos + 1, NULL, &local_err)) { error_report_err(local_err); goto fail; } @@ -479,8 +469,7 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename, } if (strstart(filename, "unix:", &p)) { qemu_opt_set(opts, "backend", "socket", &error_abort); - qemu_opts_do_parse(opts, p, "path", &local_err); - if (local_err) { + if (!qemu_opts_do_parse(opts, p, "path", &local_err)) { error_report_err(local_err); goto fail; } @@ -522,7 +511,7 @@ static const ChardevClass *char_get_class(const char *driver, Error **errp) const ChardevClass *cc; char *typename = g_strdup_printf("chardev-%s", driver); - oc = object_class_by_name(typename); + oc = module_object_class_by_name(typename); g_free(typename); if (!object_class_dynamic_cast(oc, TYPE_CHARDEV)) { @@ -939,6 +928,7 @@ QemuOptsList qemu_chardev_opts = { },{ .name = "logappend", .type = QEMU_OPT_BOOL, +#ifdef CONFIG_LINUX },{ .name = "tight", .type = QEMU_OPT_BOOL, @@ -946,6 +936,7 @@ QemuOptsList qemu_chardev_opts = { },{ .name = "abstract", .type = QEMU_OPT_BOOL, +#endif }, { /* end of list */ } }, @@ -993,7 +984,11 @@ static Chardev *chardev_new(const char *id, const char *typename, } if (id) { - object_property_add_child(get_chardevs_root(), id, obj); + object_property_try_add_child(get_chardevs_root(), id, obj, + &local_err); + if (local_err) { + goto end; + } object_unref(obj); } @@ -1191,12 +1186,6 @@ void qemu_chr_cleanup(void) static void register_types(void) { type_register_static(&char_type_info); - - /* this must be done after machine init, since we register FEs with muxes - * as part of realize functions like serial_isa_realizefn when -nographic - * is specified - */ - qemu_add_machine_init_done_notifier(&chardev_machine_done_notify); } type_init(register_types); diff --git a/include/chardev/char-mux.h b/chardev/chardev-internal.h similarity index 87% rename from include/chardev/char-mux.h rename to chardev/chardev-internal.h index 417fe32eedf29b206c4c7a20f8ef2de0ee584c6f..aba0240759ebf938cf391d89edb88f84f94fa641 100644 --- a/include/chardev/char-mux.h +++ b/chardev/chardev-internal.h @@ -1,5 +1,5 @@ /* - * QEMU System Emulator + * QEMU Character device internals * * Copyright (c) 2003-2008 Fabrice Bellard * @@ -21,16 +21,18 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef CHAR_MUX_H -#define CHAR_MUX_H +#ifndef CHARDEV_INTERNAL_H +#define CHARDEV_INTERNAL_H #include "chardev/char.h" #include "chardev/char-fe.h" +#include "qom/object.h" #define MAX_MUX 4 #define MUX_BUFFER_SIZE 32 /* Must be a power of 2. */ #define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1) -typedef struct MuxChardev { + +struct MuxChardev { Chardev parent; CharBackend *backends[MAX_MUX]; CharBackend chr; @@ -49,13 +51,17 @@ typedef struct MuxChardev { /* Protected by the Chardev chr_write_lock. */ int linestart; int64_t timestamps_start; -} MuxChardev; +}; +typedef struct MuxChardev MuxChardev; -#define MUX_CHARDEV(obj) OBJECT_CHECK(MuxChardev, (obj), TYPE_CHARDEV_MUX) +DECLARE_INSTANCE_CHECKER(MuxChardev, MUX_CHARDEV, + TYPE_CHARDEV_MUX) #define CHARDEV_IS_MUX(chr) \ object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_MUX) void mux_set_focus(Chardev *chr, int focus); void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event); +Object *get_chardevs_root(void); + #endif /* CHAR_MUX_H */ diff --git a/chardev/chardev-sysemu.c b/chardev/chardev-sysemu.c new file mode 100644 index 0000000000000000000000000000000000000000..eecdc615ee1c6c64060452ac837d129fb83b12f0 --- /dev/null +++ b/chardev/chardev-sysemu.c @@ -0,0 +1,69 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "sysemu/sysemu.h" +#include "chardev/char.h" +#include "qemu/error-report.h" +#include "chardev-internal.h" + +static int chardev_machine_done_notify_one(Object *child, void *opaque) +{ + Chardev *chr = (Chardev *)child; + ChardevClass *class = CHARDEV_GET_CLASS(chr); + + if (class->chr_machine_done) { + return class->chr_machine_done(chr); + } + + return 0; +} + +static void chardev_machine_done_hook(Notifier *notifier, void *unused) +{ + int ret = object_child_foreach(get_chardevs_root(), + chardev_machine_done_notify_one, NULL); + + if (ret) { + error_report("Failed to call chardev machine_done hooks"); + exit(1); + } +} + + +static Notifier chardev_machine_done_notify = { + .notify = chardev_machine_done_hook, +}; + +static void register_types(void) +{ + /* + * This must be done after machine init, since we register FEs with muxes + * as part of realize functions like serial_isa_realizefn when -nographic + * is specified. + */ + qemu_add_machine_init_done_notifier(&chardev_machine_done_notify); +} + +type_init(register_types); diff --git a/chardev/meson.build b/chardev/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..859d8b04d480bb69a0f2b9ef95ceee476e4f653e --- /dev/null +++ b/chardev/meson.build @@ -0,0 +1,44 @@ +chardev_ss.add(files( + 'char-fe.c', + 'char-file.c', + 'char-io.c', + 'char-mux.c', + 'char-null.c', + 'char-pipe.c', + 'char-ringbuf.c', + 'char-serial.c', + 'char-socket.c', + 'char-stdio.c', + 'char-udp.c', + 'char.c', +)) +chardev_ss.add(when: 'CONFIG_POSIX', if_true: files( + 'char-fd.c', + 'char-parallel.c', + 'char-pty.c', +)) +chardev_ss.add(when: 'CONFIG_WIN32', if_true: files( + 'char-console.c', + 'char-win-stdio.c', + 'char-win.c', +)) + +chardev_ss = chardev_ss.apply(config_host, strict: false) + +softmmu_ss.add(files('chardev-sysemu.c', 'msmouse.c', 'wctablet.c', 'testdev.c')) + +chardev_modules = {} + +if config_host.has_key('CONFIG_BRLAPI') + module_ss = ss.source_set() + module_ss.add(when: [brlapi], if_true: [files('baum.c'), pixman]) + chardev_modules += { 'baum': module_ss } +endif + +if config_host.has_key('CONFIG_SPICE') + module_ss = ss.source_set() + module_ss.add(when: [spice], if_true: files('spice.c')) + chardev_modules += { 'spice': module_ss } +endif + +modules += { 'chardev': chardev_modules } diff --git a/chardev/msmouse.c b/chardev/msmouse.c index 6d8f06fed44c9c6a0f25099d7d5c0d45aeb97d57..eb9231dcdb988fa9c0ca2d61f2ae5ebfd932ab43 100644 --- a/chardev/msmouse.c +++ b/chardev/msmouse.c @@ -27,11 +27,12 @@ #include "chardev/char.h" #include "ui/console.h" #include "ui/input.h" +#include "qom/object.h" #define MSMOUSE_LO6(n) ((n) & 0x3f) #define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6) -typedef struct { +struct MouseChardev { Chardev parent; QemuInputHandlerState *hs; @@ -40,11 +41,12 @@ typedef struct { bool btnc[INPUT_BUTTON__MAX]; uint8_t outbuf[32]; int outlen; -} MouseChardev; +}; +typedef struct MouseChardev MouseChardev; #define TYPE_CHARDEV_MSMOUSE "chardev-msmouse" -#define MOUSE_CHARDEV(obj) \ - OBJECT_CHECK(MouseChardev, (obj), TYPE_CHARDEV_MSMOUSE) +DECLARE_INSTANCE_CHECKER(MouseChardev, MOUSE_CHARDEV, + TYPE_CHARDEV_MSMOUSE) static void msmouse_chr_accept_input(Chardev *chr) { diff --git a/chardev/spice.c b/chardev/spice.c index bf7ea1e2940d13eb5e78252da0a4ff93736ad8da..1104426e3a11bb39227dc68d0f81fb902b9fd27e 100644 --- a/chardev/spice.c +++ b/chardev/spice.c @@ -14,9 +14,6 @@ typedef struct SpiceCharSource { SpiceChardev *scd; } SpiceCharSource; -static QLIST_HEAD(, SpiceChardev) spice_chars = - QLIST_HEAD_INITIALIZER(spice_chars); - static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) { SpiceChardev *scd = container_of(sin, SpiceChardev, sin); @@ -113,7 +110,7 @@ static void vmc_register_interface(SpiceChardev *scd) return; } scd->sin.base.sif = &vmc_interface.base; - qemu_spice_add_interface(&scd->sin.base); + qemu_spice.add_interface(&scd->sin.base); scd->active = true; trace_spice_vmc_register_interface(scd); } @@ -216,8 +213,6 @@ static void char_spice_finalize(Object *obj) vmc_unregister_interface(s); - QLIST_SAFE_REMOVE(s, next); - g_free((char *)s->sin.subtype); g_free((char *)s->sin.portname); } @@ -256,8 +251,6 @@ static void chr_open(Chardev *chr, const char *subtype) s->active = false; s->sin.subtype = g_strdup(subtype); - - QLIST_INSERT_HEAD(&spice_chars, s, next); } static void qemu_chr_open_spice_vmc(Chardev *chr, @@ -296,10 +289,10 @@ static void qemu_chr_open_spice_vmc(Chardev *chr, chr_open(chr, type); } -void qemu_chr_open_spice_port(Chardev *chr, - ChardevBackend *backend, - bool *be_opened, - Error **errp) +static void qemu_chr_open_spice_port(Chardev *chr, + ChardevBackend *backend, + bool *be_opened, + Error **errp) { ChardevSpicePort *spiceport = backend->u.spiceport.data; const char *name = spiceport->fqdn; @@ -310,28 +303,18 @@ void qemu_chr_open_spice_port(Chardev *chr, return; } + if (!using_spice) { + error_setg(errp, "spice not enabled"); + return; + } + chr_open(chr, "port"); *be_opened = false; s = SPICE_CHARDEV(chr); s->sin.portname = g_strdup(name); - if (using_spice) { - /* spice server already created */ - vmc_register_interface(s); - } -} - -void qemu_spice_register_ports(void) -{ - SpiceChardev *s; - - QLIST_FOREACH(s, &spice_chars, next) { - if (s->sin.portname == NULL) { - continue; - } - vmc_register_interface(s); - } + vmc_register_interface(s); } static void qemu_chr_parse_spice_vmc(QemuOpts *opts, ChardevBackend *backend, diff --git a/chardev/testdev.c b/chardev/testdev.c index 368a8c041e55f4b87d651bf9b4d9cab81a914d38..a92caca3c3392ca7faae224fb62f0c397d1c0516 100644 --- a/chardev/testdev.c +++ b/chardev/testdev.c @@ -27,19 +27,21 @@ #include "qemu/osdep.h" #include "qemu/module.h" #include "chardev/char.h" +#include "qom/object.h" #define BUF_SIZE 32 -typedef struct { +struct TestdevChardev { Chardev parent; uint8_t in_buf[32]; int in_buf_used; -} TestdevChardev; +}; +typedef struct TestdevChardev TestdevChardev; #define TYPE_CHARDEV_TESTDEV "chardev-testdev" -#define TESTDEV_CHARDEV(obj) \ - OBJECT_CHECK(TestdevChardev, (obj), TYPE_CHARDEV_TESTDEV) +DECLARE_INSTANCE_CHECKER(TestdevChardev, TESTDEV_CHARDEV, + TYPE_CHARDEV_TESTDEV) /* Try to interpret a whole incoming packet */ static int testdev_eat_packet(TestdevChardev *testdev) diff --git a/chardev/trace.h b/chardev/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..eb4f9027a112e06c593279ed3d3fc4c3dc889f03 --- /dev/null +++ b/chardev/trace.h @@ -0,0 +1 @@ +#include "trace/trace-chardev.h" diff --git a/chardev/wctablet.c b/chardev/wctablet.c index e9cb7ca71069e80b0924a16840f5146fad658f11..95e005f5a5639f055070456e418c0a83363badf2 100644 --- a/chardev/wctablet.c +++ b/chardev/wctablet.c @@ -32,6 +32,7 @@ #include "ui/console.h" #include "ui/input.h" #include "trace.h" +#include "qom/object.h" #define WC_OUTPUT_BUF_MAX_LEN 512 @@ -64,7 +65,7 @@ uint8_t WC_FULL_CONFIG_STRING[WC_FULL_CONFIG_STRING_LENGTH + 1] = { }; /* This structure is used to save private info for Wacom Tablet. */ -typedef struct { +struct TabletChardev { Chardev parent; QemuInputHandlerState *hs; @@ -81,11 +82,12 @@ typedef struct { int axis[INPUT_AXIS__MAX]; bool btns[INPUT_BUTTON__MAX]; -} TabletChardev; +}; +typedef struct TabletChardev TabletChardev; #define TYPE_CHARDEV_WCTABLET "chardev-wctablet" -#define WCTABLET_CHARDEV(obj) \ - OBJECT_CHECK(TabletChardev, (obj), TYPE_CHARDEV_WCTABLET) +DECLARE_INSTANCE_CHECKER(TabletChardev, WCTABLET_CHARDEV, + TYPE_CHARDEV_WCTABLET) static void wctablet_chr_accept_input(Chardev *chr); diff --git a/configure b/configure index 10565e588affb4c35bb7d27abf42fa244c276a48..18c26e0389741643748c70ac7788a996ef006834 100755 --- a/configure +++ b/configure @@ -11,6 +11,55 @@ unset CLICOLOR_FORCE GREP_OPTIONS # Don't allow CCACHE, if present, to use cached results of compile tests! export CCACHE_RECACHE=yes +# make source path absolute +source_path=$(cd "$(dirname -- "$0")"; pwd) + +if test "$PWD" = "$source_path" +then + echo "Using './build' as the directory for build output" + + MARKER=build/auto-created-by-configure + + if test -e build + then + if test -f $MARKER + then + rm -rf build + else + echo "ERROR: ./build dir already exists and was not previously created by configure" + exit 1 + fi + fi + + mkdir build + touch $MARKER + + cat > GNUmakefile <<'EOF' +# This file is auto-generated by configure to support in-source tree +# 'make' command invocation + +ifeq ($(MAKECMDGOALS),) +recurse: all +endif + +.NOTPARALLEL: % +%: force + @echo 'changing dir to build for $(MAKE) "$(MAKECMDGOALS)"...' + @$(MAKE) -C build -f Makefile $(MAKECMDGOALS) + @if test "$(MAKECMDGOALS)" = "distclean" && \ + test -e build/auto-created-by-configure ; \ + then \ + rm -rf build GNUmakefile ; \ + fi +force: ; +.PHONY: force +GNUmakefile: ; + +EOF + cd build + exec $source_path/configure "$@" +fi + # Temporary directory used for files created while # configure runs. Since it is in the build directory # we can safely blow away any previous version of it @@ -29,7 +78,6 @@ TMPC="${TMPDIR1}/${TMPB}.c" TMPO="${TMPDIR1}/${TMPB}.o" TMPCXX="${TMPDIR1}/${TMPB}.cxx" TMPE="${TMPDIR1}/${TMPB}.exe" -TMPMO="${TMPDIR1}/${TMPB}.mo" TMPTXT="${TMPDIR1}/${TMPB}.txt" rm -f config.log @@ -97,20 +145,22 @@ do_cxx() { do_compiler "$cxx" "$@" } +# Append $2 to the variable named $1, with space separation +add_to() { + eval $1=\${$1:+\"\$$1 \"}\$2 +} + update_cxxflags() { # Set QEMU_CXXFLAGS from QEMU_CFLAGS by filtering out those # options which some versions of GCC's C++ compiler complain about # because they only make sense for C programs. QEMU_CXXFLAGS="$QEMU_CXXFLAGS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS" - + CONFIGURE_CXXFLAGS=$(echo "$CONFIGURE_CFLAGS" | sed s/-std=gnu99/-std=gnu++11/) for arg in $QEMU_CFLAGS; do case $arg in -Wstrict-prototypes|-Wmissing-prototypes|-Wnested-externs|\ -Wold-style-declaration|-Wold-style-definition|-Wredundant-decls) ;; - -std=gnu99) - QEMU_CXXFLAGS=${QEMU_CXXFLAGS:+$QEMU_CXXFLAGS }"-std=gnu++98" - ;; *) QEMU_CXXFLAGS=${QEMU_CXXFLAGS:+$QEMU_CXXFLAGS }$arg ;; @@ -120,13 +170,14 @@ update_cxxflags() { compile_object() { local_cflags="$1" - do_cc $QEMU_CFLAGS $local_cflags -c -o $TMPO $TMPC + do_cc $CFLAGS $CONFIGURE_CFLAGS $QEMU_CFLAGS $local_cflags -c -o $TMPO $TMPC } compile_prog() { local_cflags="$1" local_ldflags="$2" - do_cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $QEMU_LDFLAGS $local_ldflags + do_cc $CFLAGS $CONFIGURE_CFLAGS $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC \ + $LDFLAGS $CONFIGURE_LDFLAGS $QEMU_LDFLAGS $local_ldflags } # symbolically link $1 to $2. Portable version of "ln -sf". @@ -142,34 +193,23 @@ has() { type "$1" >/dev/null 2>&1 } -# search for an executable in PATH -path_of() { - local_command="$1" - local_ifs="$IFS" - local_dir="" - - # pathname has a dir component? - if [ "${local_command#*/}" != "$local_command" ]; then - if [ -x "$local_command" ] && [ ! -d "$local_command" ]; then - echo "$local_command" - return 0 - fi - fi - if [ -z "$local_command" ]; then - return 1 - fi - - IFS=: - for local_dir in $PATH; do - if [ -x "$local_dir/$local_command" ] && [ ! -d "$local_dir/$local_command" ]; then - echo "$local_dir/$local_command" - IFS="${local_ifs:-$(printf ' \t\n')}" - return 0 - fi +version_ge () { + local_ver1=`echo $1 | tr . ' '` + local_ver2=`echo $2 | tr . ' '` + while true; do + set x $local_ver1 + local_first=${2-0} + # 'shift 2' if $2 is set, or 'shift' if $2 is not set + shift ${2:+2} + local_ver1=$* + set x $local_ver2 + # the second argument finished, the first must be greater or equal + test $# = 1 && return 0 + test $local_first -lt $2 && return 1 + test $local_first -gt $2 && return 0 + shift ${2:+2} + local_ver2=$* done - # not found - IFS="${local_ifs:-$(printf ' \t\n')}" - return 1 } have_backend () { @@ -180,107 +220,10 @@ glob() { eval test -z '"${1#'"$2"'}"' } -supported_hax_target() { - test "$hax" = "yes" || return 1 - glob "$1" "*-softmmu" || return 1 - case "${1%-softmmu}" in - i386|x86_64) - return 0 - ;; - esac - return 1 -} - -supported_kvm_target() { - test "$kvm" = "yes" || return 1 - glob "$1" "*-softmmu" || return 1 - case "${1%-softmmu}:$cpu" in - arm:arm | aarch64:aarch64 | \ - i386:i386 | i386:x86_64 | i386:x32 | \ - x86_64:i386 | x86_64:x86_64 | x86_64:x32 | \ - mips:mips | mipsel:mips | \ - ppc:ppc | ppc64:ppc | ppc:ppc64 | ppc64:ppc64 | ppc64:ppc64le | \ - riscv32:riscv32 | riscv64:riscv64 | \ - s390x:s390x) - return 0 - ;; - esac - return 1 -} - -supported_xen_target() { - test "$xen" = "yes" || return 1 - glob "$1" "*-softmmu" || return 1 - # Only i386 and x86_64 provide the xenpv machine. - case "${1%-softmmu}" in - i386|x86_64) - return 0 - ;; - esac - return 1 -} - -supported_hvf_target() { - test "$hvf" = "yes" || return 1 - glob "$1" "*-softmmu" || return 1 - case "${1%-softmmu}" in - x86_64) - return 0 - ;; - esac - return 1 -} - -supported_whpx_target() { - test "$whpx" = "yes" || return 1 - glob "$1" "*-softmmu" || return 1 - case "${1%-softmmu}" in - i386|x86_64) - return 0 - ;; - esac - return 1 -} - -supported_target() { - case "$1" in - *-softmmu) - ;; - *-linux-user) - if test "$linux" != "yes"; then - print_error "Target '$target' is only available on a Linux host" - return 1 - fi - ;; - *-bsd-user) - if test "$bsd" != "yes"; then - print_error "Target '$target' is only available on a BSD host" - return 1 - fi - ;; - *) - print_error "Invalid target name '$target'" - return 1 - ;; - esac - test "$tcg" = "yes" && return 0 - supported_kvm_target "$1" && return 0 - supported_xen_target "$1" && return 0 - supported_hax_target "$1" && return 0 - supported_hvf_target "$1" && return 0 - supported_whpx_target "$1" && return 0 - print_error "TCG disabled, but hardware accelerator not available for '$target'" - return 1 -} - - ld_has() { $ld --help 2>/dev/null | grep ".$1" >/dev/null 2>&1 } -# make source path absolute -source_path=$(cd "$(dirname -- "$0")"; pwd) - if printf %s\\n "$source_path" "$PWD" | grep -q "[[:space:]:]"; then error_exit "main directory cannot contain spaces nor colons" @@ -296,13 +239,11 @@ audio_drv_list="" block_drv_rw_whitelist="" block_drv_ro_whitelist="" host_cc="cc" -libs_cpu="" -libs_softmmu="" -libs_tools="" audio_win_int="" libs_qga="" debug_info="yes" stack_protector="" +safe_stack="" use_containers="yes" gdb_bin=$(command -v "gdb-multiarch" || command -v "gdb") @@ -354,84 +295,76 @@ unset target_list_exclude brlapi="" curl="" -curses="" -docs="" -fdt="" +iconv="auto" +curses="auto" +docs="auto" +fdt="auto" netmap="no" -sdl="" -sdl_image="" +sdl="auto" +sdl_image="auto" +virtiofsd="auto" virtfs="" -mpath="" -vnc="yes" -sparse="no" +libudev="auto" +mpath="auto" +vnc="enabled" +sparse="auto" vde="" -vnc_sasl="" -vnc_jpeg="" -vnc_png="" -xkbcommon="" +vnc_sasl="auto" +vnc_jpeg="auto" +vnc_png="auto" +xkbcommon="auto" xen="" xen_ctrl_version="" -xen_pci_passthrough="" +xen_pci_passthrough="auto" linux_aio="" linux_io_uring="" cap_ng="" attr="" libattr="" xfs="" -tcg="yes" +tcg="enabled" membarrier="" vhost_net="" vhost_crypto="" vhost_scsi="" vhost_vsock="" -vhost_user="" +vhost_user="no" +vhost_user_blk_server="auto" vhost_user_fs="" -kvm="no" -hax="no" -hvf="no" -whpx="no" +kvm="auto" +hax="auto" +hvf="auto" +whpx="auto" rdma="" pvrdma="" gprof="no" debug_tcg="no" debug="no" sanitizers="no" +tsan="no" fortify_source="" strip_opt="yes" tcg_interpreter="no" bigendian="no" mingw32="no" gcov="no" -gcov_tool="gcov" EXESUF="" -DSOSUF=".so" -LDFLAGS_SHARED="-shared" +HOST_DSOSUF=".so" modules="no" module_upgrades="no" prefix="/usr/local" -mandir="\${prefix}/share/man" -datadir="\${prefix}/share" -firmwarepath="\${prefix}/share/qemu-firmware" -qemu_docdir="\${prefix}/share/doc/qemu" -bindir="\${prefix}/bin" -libdir="\${prefix}/lib" -libexecdir="\${prefix}/libexec" -includedir="\${prefix}/include" -sysconfdir="\${prefix}/etc" -local_statedir="\${prefix}/var" -confsuffix="/qemu" -slirp="" +qemu_suffix="qemu" +slirp="auto" oss_lib="" bsd="no" linux="no" solaris="no" profiler="no" -cocoa="no" +cocoa="auto" softmmu="yes" linux_user="no" bsd_user="no" -blobs="yes" -edk2_blobs="no" +blobs="true" pkgversion="" pie="" qom_cast_debug="yes" @@ -440,14 +373,14 @@ trace_file="trace" spice="" rbd="" smartcard="" +u2f="auto" libusb="" usb_redir="" opengl="" opengl_dmabuf="no" cpuid_h="no" avx2_opt="" -zlib="yes" -capstone="" +capstone="auto" lzo="" snappy="" bzip2="" @@ -494,7 +427,6 @@ numa="" tcmalloc="no" jemalloc="no" replication="yes" -vxhs="" bochs="yes" cloop="yes" dmg="yes" @@ -503,18 +435,23 @@ vdi="yes" vvfat="yes" qed="yes" parallels="yes" -sheepdog="yes" +sheepdog="no" libxml2="" debug_mutex="no" libpmem="" default_devices="yes" plugins="no" fuzzing="no" +rng_none="no" +secret_keyring="" +libdaxctl="" +meson="" +ninja="" +skip_meson=no +gettext="" -supported_cpu="no" -supported_os="no" bogus_os="no" -malloc_trim="" +malloc_trim="auto" # parse CC options first for opt do @@ -598,23 +535,15 @@ ARFLAGS="${ARFLAGS-rv}" # left shift of signed integers is well defined and has the expected # 2s-complement style results. (Both clang and gcc agree that it # provides these semantics.) -QEMU_CFLAGS="-fno-strict-aliasing -fno-common -fwrapv -std=gnu99 $QEMU_CFLAGS" -QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS" +QEMU_CFLAGS="-fno-strict-aliasing -fno-common -fwrapv $QEMU_CFLAGS" +QEMU_CFLAGS="-Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS" QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS" QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS" -QEMU_INCLUDES="-iquote . -iquote \$(SRC_PATH) -iquote \$(SRC_PATH)/accel/tcg -iquote \$(SRC_PATH)/include" -QEMU_INCLUDES="$QEMU_INCLUDES -iquote \$(SRC_PATH)/disas/libvixl" -if test "$debug_info" = "yes"; then - CFLAGS="-g $CFLAGS" -fi -# running configure in the source tree? -# we know that's the case if configure is there. -if test -f "./configure"; then - pwd_is_source_path="y" -else - pwd_is_source_path="n" -fi +# Flags that are needed during configure but later taken care of by Meson +CONFIGURE_CFLAGS="-std=gnu99 -Wall" +CONFIGURE_LDFLAGS= + check_define() { cat > $TMPC <= 3.7 and requires coroutine backend ucontext. gnutls GNUTLS cryptography support nettle nettle cryptography support @@ -1822,6 +1771,8 @@ disabled with --disable-FEATURE, default is enabled if available: vnc-png PNG compression for VNC server cocoa Cocoa UI (Mac OS X only) virtfs VirtFS + virtiofsd build virtiofs daemon (virtiofsd) + libudev Use libudev to enumerate host devices mpath Multipath persistent reservation passthrough xen xen backend driver support xen-pci-passthrough PCI passthrough support for Xen @@ -1847,11 +1798,14 @@ disabled with --disable-FEATURE, default is enabled if available: vhost-crypto vhost-user-crypto backend support vhost-kernel vhost kernel backend support vhost-user vhost-user backend support + vhost-user-blk-server vhost-user-blk server support + vhost-vdpa vhost-vdpa kernel backend support spice spice rbd rados block device (rbd) libiscsi iscsi support libnfs nfs support smartcard smartcard support (libcacard) + u2f U2F support (u2f-emu) libusb libusb (for usb passthrough) live-block-migration Block migration in the main migration stream usb-redir usb network redirection support @@ -1880,7 +1834,6 @@ disabled with --disable-FEATURE, default is enabled if available: xfsctl xfsctl support qom-cast-debug cast debugging support tools build qemu-io, qemu-nbd and qemu-img tools - vxhs Veritas HyperScale vDisk backend support bochs bochs image format support cloop cloop image format support dmg dmg image format support @@ -1889,12 +1842,14 @@ disabled with --disable-FEATURE, default is enabled if available: vvfat vvfat image format support qed qed image format support parallels parallels image format support - sheepdog sheepdog block driver support + sheepdog sheepdog block driver support (deprecated) crypto-afalg Linux AF_ALG crypto backend driver capstone capstone disassembler support debug-mutex mutex debugging support libpmem libpmem support xkbcommon xkbcommon support + rng-none dummy RNG, avoid using /dev/(u)random and getrandom() + libdaxctl libdaxctl support NOTE: The object files are built at the place where configure is launched EOF @@ -1904,20 +1859,6 @@ fi # Remove old dependency files to make sure that they get properly regenerated rm -f */config-devices.mak.d -# Remove syscall_nr.h to be sure they will be regenerated in the build -# directory, not in the source directory -for arch in alpha hppa m68k xtensa sh4 microblaze arm ppc s390x sparc sparc64 \ - i386 x86_64 mips mips64 ; do - # remove the file if it has been generated in the source directory - rm -f "${source_path}/linux-user/${arch}/syscall_nr.h" - # remove the dependency files - for target in ${arch}*-linux-user ; do - test -d "${target}" && find "${target}" -type f -name "*.d" \ - -exec grep -q "${source_path}/linux-user/${arch}/syscall_nr.h" {} \; \ - -print | while read file ; do rm "${file}" "${file%.d}.o" ; done - done -done - if test -z "$python" then error_exit "Python not found. Use --python=/path/to/python" @@ -1925,8 +1866,8 @@ fi # Note that if the Python conditional here evaluates True we will exit # with status 1 which is a shell 'false' value. -if ! $python -c 'import sys; sys.exit(sys.version_info < (3,5))'; then - error_exit "Cannot use '$python', Python >= 3.5 is required." \ +if ! $python -c 'import sys; sys.exit(sys.version_info < (3,6))'; then + error_exit "Cannot use '$python', Python >= 3.6 is required." \ "Use --python=/path/to/python to specify a supported Python." fi @@ -1936,6 +1877,60 @@ python_version=$($python -c 'import sys; print("%d.%d.%d" % (sys.version_info[0] # Suppress writing compiled files python="$python -B" +if test -z "$meson"; then + if test "$explicit_python" = no && has meson && version_ge "$(meson --version)" 0.55.3; then + meson=meson + elif test -e "${source_path}/.git" && test $git_update = 'yes' ; then + meson=git + elif test -e "${source_path}/meson/meson.py" ; then + meson=internal + else + if test "$explicit_python" = yes; then + error_exit "--python requires using QEMU's embedded Meson distribution, but it was not found." + else + error_exit "Meson not found. Use --meson=/path/to/meson" + fi + fi +else + # Meson uses its own Python interpreter to invoke other Python scripts, + # but the user wants to use the one they specified with --python. + # + # We do not want to override the distro Python interpreter (and sometimes + # cannot: for example in Homebrew /usr/bin/meson is a bash script), so + # just require --meson=git|internal together with --python. + if test "$explicit_python" = yes; then + case "$meson" in + git | internal) ;; + *) error_exit "--python requires using QEMU's embedded Meson distribution." ;; + esac + fi +fi + +if test "$meson" = git; then + git_submodules="${git_submodules} meson" +fi + +case "$meson" in + git | internal) + meson="$python ${source_path}/meson/meson.py" + ;; + *) meson=$(command -v "$meson") ;; +esac + +# Probe for ninja + +if test -z "$ninja"; then + for c in ninja ninja-build samu; do + if has $c; then + ninja=$(command -v "$c") + break + fi + done + if test -z "$ninja"; then + error_exit "Cannot find Ninja" + fi +fi + # Check that the C compiler works. Doing this here before testing # the host CPU ensures that we had a valid CC to autodetect the # $cpu var (and we should bail right here if that's not the case). @@ -1950,16 +1945,6 @@ if ! compile_prog ; then error_exit "\"$cc\" cannot build an executable (is your linker broken?)" fi -# Now we have handled --enable-tcg-interpreter and know we're not just -# printing the help message, bail out if the host CPU isn't supported. -if test "$ARCH" = "unknown"; then - if test "$tcg_interpreter" = "yes" ; then - echo "Unsupported CPU = $cpu, will use TCG with TCI (experimental)" - else - error_exit "Unsupported CPU = $cpu, try --enable-tcg-interpreter" - fi -fi - # Consult white-list to determine whether to enable werror # by default. Only enable by default for git builds if test -z "$werror" ; then @@ -2004,16 +1989,35 @@ if ! compile_prog "" "" ; then error_exit "You need at least GCC v4.8 or Clang v3.4 (or XCode Clang v5.1)" fi -gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits" -gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags" -gcc_flags="-Wno-missing-include-dirs -Wempty-body -Wnested-externs $gcc_flags" -gcc_flags="-Wendif-labels -Wno-shift-negative-value $gcc_flags" -gcc_flags="-Wno-initializer-overrides -Wexpansion-to-defined $gcc_flags" -gcc_flags="-Wno-string-plus-int -Wno-typedef-redefinition $gcc_flags" -# Note that we do not add -Werror to gcc_flags here, because that would -# enable it for all configure tests. If a configure test failed due -# to -Werror this would just silently disable some features, -# so it's too error prone. +# Accumulate -Wfoo and -Wno-bar separately. +# We will list all of the enable flags first, and the disable flags second. +# Note that we do not add -Werror, because that would enable it for all +# configure tests. If a configure test failed due to -Werror this would +# just silently disable some features, so it's too error prone. + +warn_flags= +add_to warn_flags -Wold-style-declaration +add_to warn_flags -Wold-style-definition +add_to warn_flags -Wtype-limits +add_to warn_flags -Wformat-security +add_to warn_flags -Wformat-y2k +add_to warn_flags -Winit-self +add_to warn_flags -Wignored-qualifiers +add_to warn_flags -Wempty-body +add_to warn_flags -Wnested-externs +add_to warn_flags -Wendif-labels +add_to warn_flags -Wexpansion-to-defined + +nowarn_flags= +add_to nowarn_flags -Wno-initializer-overrides +add_to nowarn_flags -Wno-missing-include-dirs +add_to nowarn_flags -Wno-shift-negative-value +add_to nowarn_flags -Wno-string-plus-int +add_to nowarn_flags -Wno-typedef-redefinition +add_to nowarn_flags -Wno-tautological-type-limit-compare +add_to nowarn_flags -Wno-psabi + +gcc_flags="$warn_flags $nowarn_flags" cc_has_warning_flag() { write_c_skeleton; @@ -2047,7 +2051,7 @@ EOF for flag in $gcc_flags; do # We need to check both a compile and a link, since some compiler # setups fail only on a .c->.o compile and some only at link time - if do_cc $QEMU_CFLAGS -Werror $flag -c -o $TMPO $TMPC && + if compile_object "-Werror $flag" && compile_prog "-Werror $flag" ""; then QEMU_CFLAGS="$QEMU_CFLAGS $flag" QEMU_LDFLAGS="$QEMU_LDFLAGS $flag" @@ -2122,7 +2126,7 @@ fi if test "$static" = "yes"; then if test "$pie" != "no" && compile_prog "-Werror -fPIE -DPIE" "-static-pie"; then - QEMU_CFLAGS="-fPIE -DPIE $QEMU_CFLAGS" + CONFIGURE_CFLAGS="-fPIE -DPIE $CONFIGURE_CFLAGS" QEMU_LDFLAGS="-static-pie $QEMU_LDFLAGS" pie="yes" elif test "$pie" = "yes"; then @@ -2132,11 +2136,11 @@ if test "$static" = "yes"; then pie="no" fi elif test "$pie" = "no"; then - QEMU_CFLAGS="$CFLAGS_NOPIE $QEMU_CFLAGS" - QEMU_LDFLAGS="$LDFLAGS_NOPIE $QEMU_LDFLAGS" + CONFIGURE_CFLAGS="$CFLAGS_NOPIE $CONFIGURE_CFLAGS" + CONFIGURE_LDFLAGS="$LDFLAGS_NOPIE $CONFIGURE_LDFLAGS" elif compile_prog "-Werror -fPIE -DPIE" "-pie"; then - QEMU_CFLAGS="-fPIE -DPIE $QEMU_CFLAGS" - QEMU_LDFLAGS="-pie $QEMU_LDFLAGS" + CONFIGURE_CFLAGS="-fPIE -DPIE $CONFIGURE_CFLAGS" + CONFIGURE_LDFLAGS="-pie $CONFIGURE_LDFLAGS" pie="yes" elif test "$pie" = "yes"; then error_exit "PIE not available due to missing toolchain support" @@ -2180,18 +2184,6 @@ fi # Solaris specific configure tool chain decisions if test "$solaris" = "yes" ; then - if has $install; then - : - else - error_exit "Solaris install program not found. Use --install=/usr/ucb/install or" \ - "install fileutils from www.blastwave.org using pkg-get -i fileutils" \ - "to get ginstall which is used by default (which lives in /opt/csw/bin)" - fi - if test "$(path_of $install)" = "/usr/sbin/install" ; then - error_exit "Solaris /usr/sbin/install is not an appropriate install program." \ - "try ginstall from the GNU fileutils available from www.blastwave.org" \ - "using pkg-get -i fileutils, or use --install=/usr/ucb/install" - fi if has ar; then : else @@ -2204,12 +2196,13 @@ if test "$solaris" = "yes" ; then fi if test -z "${target_list+xxx}" ; then + default_targets=yes for target in $default_target_list; do - supported_target $target 2>/dev/null && \ - target_list="$target_list $target" + target_list="$target_list $target" done target_list="${target_list# }" else + default_targets=no target_list=$(echo "$target_list" | sed -e 's/,/ /g') for target in $target_list; do # Check that we recognised the target name; this allows a more @@ -2221,10 +2214,16 @@ else error_exit "Unknown target name '$target'" ;; esac - supported_target $target || exit 1 done fi +for target in $target_list; do + # if a deprecated target is enabled we note it here + if echo "$deprecated_targets_list" | grep -q "$target"; then + add_to deprecated_features $target + fi +done + # see if system emulation was really requested case " $target_list " in *"-softmmu "*) softmmu=yes @@ -2233,18 +2232,6 @@ case " $target_list " in ;; esac -for target in $target_list; do - case "$target" in - arm-softmmu | aarch64-softmmu | i386-softmmu | x86_64-softmmu) - edk2_blobs="yes" - ;; - esac -done -# The EDK2 binaries are compressed with bzip2 -if test "$edk2_blobs" = "yes" && ! has bzip2; then - error_exit "The bzip2 program is required for building QEMU" -fi - feature_not_found() { feature=$1 remedy=$2 @@ -2291,15 +2278,15 @@ fi # cocoa implies not SDL or GTK # (the cocoa UI code currently assumes it is always the active UI # and doesn't interact well with other UI frontend code) -if test "$cocoa" = "yes"; then - if test "$sdl" = "yes"; then +if test "$cocoa" = "enabled"; then + if test "$sdl" = "enabled"; then error_exit "Cocoa and SDL UIs cannot both be enabled at once" fi if test "$gtk" = "yes"; then error_exit "Cocoa and GTK UIs cannot both be enabled at once" fi gtk=no - sdl=no + sdl=disabled fi # Some versions of Mac OS X incorrectly define SIZE_MAX @@ -2329,13 +2316,34 @@ else l2tpv3=no fi +if check_include "pty.h" ; then + pty_h=yes +else + pty_h=no +fi + +cat > $TMPC < +int main(int argc, char *argv[]) { + return mlockall(MCL_FUTURE); +} +EOF +if compile_prog "" "" ; then + have_mlockall=yes +else + have_mlockall=no +fi + ######################################### # vhost interdependencies and host support # vhost backends -test "$vhost_user" = "" && vhost_user=yes -if test "$vhost_user" = "yes" && test "$mingw32" = "yes"; then - error_exit "vhost-user isn't available on win32" +if test "$vhost_user" = "yes" && test "$linux" != "yes"; then + error_exit "vhost-user is only available on Linux" +fi +test "$vhost_vdpa" = "" && vhost_vdpa=$linux +if test "$vhost_vdpa" = "yes" && test "$linux" != "yes"; then + error_exit "vhost-vdpa is only available on Linux" fi test "$vhost_kernel" = "" && vhost_kernel=$linux if test "$vhost_kernel" = "yes" && test "$linux" != "yes"; then @@ -2365,44 +2373,19 @@ test "$vhost_user_fs" = "" && vhost_user_fs=$vhost_user if test "$vhost_user_fs" = "yes" && test "$vhost_user" = "no"; then error_exit "--enable-vhost-user-fs requires --enable-vhost-user" fi +#vhost-vdpa backends +test "$vhost_net_vdpa" = "" && vhost_net_vdpa=$vhost_vdpa +if test "$vhost_net_vdpa" = "yes" && test "$vhost_vdpa" = "no"; then + error_exit "--enable-vhost-net-vdpa requires --enable-vhost-vdpa" +fi -# OR the vhost-kernel and vhost-user values for simplicity +# OR the vhost-kernel, vhost-vdpa and vhost-user values for simplicity if test "$vhost_net" = ""; then test "$vhost_net_user" = "yes" && vhost_net=yes + test "$vhost_net_vdpa" = "yes" && vhost_net=yes test "$vhost_kernel" = "yes" && vhost_net=yes fi -########################################## -# MinGW / Mingw-w64 localtime_r/gmtime_r check - -if test "$mingw32" = "yes"; then - # Some versions of MinGW / Mingw-w64 lack localtime_r - # and gmtime_r entirely. - # - # Some versions of Mingw-w64 define a macro for - # localtime_r/gmtime_r. - # - # Some versions of Mingw-w64 will define functions - # for localtime_r/gmtime_r, but only if you have - # _POSIX_THREAD_SAFE_FUNCTIONS defined. For fun - # though, unistd.h and pthread.h both define - # that for you. - # - # So this #undef localtime_r and #include - # are not in fact redundant. -cat > $TMPC << EOF -#include -#include -#undef localtime_r -int main(void) { localtime_r(NULL, NULL); return 0; } -EOF - if compile_prog "" "" ; then - localtime_r="yes" - else - localtime_r="no" - fi -fi - ########################################## # pkg-config probe @@ -2438,7 +2421,7 @@ if test "$lzo" != "no" ; then int main(void) { lzo_version(); return 0; } EOF if compile_prog "" "-llzo2" ; then - libs_softmmu="$libs_softmmu -llzo2" + lzo_libs="-llzo2" lzo="yes" else if test "$lzo" = "yes"; then @@ -2457,7 +2440,7 @@ if test "$snappy" != "no" ; then int main(void) { snappy_max_compressed_length(4096); return 0; } EOF if compile_prog "" "-lsnappy" ; then - libs_softmmu="$libs_softmmu -lsnappy" + snappy_libs='-lsnappy' snappy="yes" else if test "$snappy" = "yes"; then @@ -2511,8 +2494,6 @@ if test "$zstd" != "no" ; then if $pkg_config --atleast-version=$libzstd_minver libzstd ; then zstd_cflags="$($pkg_config --cflags libzstd)" zstd_libs="$($pkg_config --libs libzstd)" - LIBS="$zstd_libs $LIBS" - QEMU_CFLAGS="$QEMU_CFLAGS $zstd_cflags" zstd="yes" else if test "$zstd" = "yes" ; then @@ -2539,10 +2520,11 @@ if test "$seccomp" != "no" ; then seccomp="no" fi fi + ########################################## # xen probe -if test "$xen" != "no" ; then +if test "$xen" != "disabled" ; then # Check whether Xen library path is specified via --extra-ldflags to avoid # overriding this setting with pkg-config output. If not, try pkg-config # to obtain all needed flags. @@ -2551,17 +2533,17 @@ if test "$xen" != "no" ; then $pkg_config --exists xencontrol ; then xen_ctrl_version="$(printf '%d%02d%02d' \ $($pkg_config --modversion xencontrol | sed 's/\./ /g') )" - xen=yes - xen_pc="xencontrol xenstore xenguest xenforeignmemory xengnttab" + xen=enabled + xen_pc="xencontrol xenstore xenforeignmemory xengnttab" xen_pc="$xen_pc xenevtchn xendevicemodel" if $pkg_config --exists xentoolcore; then xen_pc="$xen_pc xentoolcore" fi - QEMU_CFLAGS="$QEMU_CFLAGS $($pkg_config --cflags $xen_pc)" - libs_softmmu="$($pkg_config --libs $xen_pc) $libs_softmmu" + xen_cflags="$($pkg_config --cflags $xen_pc)" + xen_libs="$($pkg_config --libs $xen_pc)" else - xen_libs="-lxenstore -lxenctrl -lxenguest" + xen_libs="-lxenstore -lxenctrl" xen_stable_libs="-lxenforeignmemory -lxengnttab -lxenevtchn" # First we test whether Xen headers and libraries are available. @@ -2577,10 +2559,10 @@ int main(void) { EOF if ! compile_prog "" "$xen_libs" ; then # Xen not found - if test "$xen" = "yes" ; then + if test "$xen" = "enabled" ; then feature_not_found "xen" "Install xen devel" fi - xen=no + xen=disabled # Xen unstable elif @@ -2606,7 +2588,7 @@ EOF then xen_stable_libs="-lxendevicemodel $xen_stable_libs -lxentoolcore" xen_ctrl_version=41100 - xen=yes + xen=enabled elif cat > $TMPC < $TMPC < $TMPC < $TMPC < $TMPC </dev/null) - elif has "$sdl2_config"; then - sdlconfig="$sdl2_config" - sdlversion=$($sdlconfig --version) +# RDMA needs OpenFabrics libraries +if test "$rdma" != "no" ; then + cat > $TMPC < +int main(void) { return 0; } +EOF + rdma_libs="-lrdmacm -libverbs -libumad" + if compile_prog "" "$rdma_libs" ; then + rdma="yes" else - if test "$sdl" = "yes" ; then - feature_not_found "sdl" "Install SDL2-devel" + if test "$rdma" = "yes" ; then + error_exit \ + " OpenFabrics librdmacm/libibverbs/libibumad not present." \ + " Your options:" \ + " (1) Fast: Install infiniband packages (devel) from your distro." \ + " (2) Cleanest: Install libraries from www.openfabrics.org" \ + " (3) Also: Install softiwarp if you don't have RDMA hardware" fi - sdl=no - # no need to do the rest - return - fi - if test -n "$cross_prefix" && test "$(basename "$sdlconfig")" = sdl2-config; then - echo warning: using "\"$sdlconfig\"" to detect cross-compiled sdl >&2 + rdma="no" fi +fi - cat > $TMPC << EOF -#include -#undef main /* We don't want SDL to override our main() */ -int main( void ) { return SDL_Init (SDL_INIT_VIDEO); } -EOF - sdl_cflags=$($sdlconfig --cflags 2>/dev/null) - sdl_cflags="$sdl_cflags -Wno-undef" # workaround 2.0.8 bug - if test "$static" = "yes" ; then - if $pkg_config sdl2 --exists; then - sdl_libs=$($pkg_config sdl2 --static --libs 2>/dev/null) - else - sdl_libs=$($sdlconfig --static-libs 2>/dev/null) - fi - else - sdl_libs=$($sdlconfig --libs 2>/dev/null) - fi - if compile_prog "$sdl_cflags" "$sdl_libs" ; then - sdl=yes - - # static link with sdl ? (note: sdl.pc's --static --libs is broken) - if test "$sdl" = "yes" && test "$static" = "yes" ; then - if test $? = 0 && echo $sdl_libs | grep -- -laa > /dev/null; then - sdl_libs="$sdl_libs $(aalib-config --static-libs 2>/dev/null)" - sdl_cflags="$sdl_cflags $(aalib-config --cflags 2>/dev/null)" - fi - if compile_prog "$sdl_cflags" "$sdl_libs" ; then - : - else - sdl=no - fi - fi # static link - else # sdl not found - if test "$sdl" = "yes" ; then - feature_not_found "sdl" "Install SDL2 devel" - fi - sdl=no - fi # sdl compile test -} +########################################## +# PVRDMA detection -sdl_image_probe () -{ - if test "$sdl_image" != "no" ; then - if $pkg_config SDL2_image --exists; then - if test "$static" = "yes"; then - sdl_image_libs=$($pkg_config SDL2_image --libs --static 2>/dev/null) - else - sdl_image_libs=$($pkg_config SDL2_image --libs 2>/dev/null) - fi - sdl_image_cflags=$($pkg_config SDL2_image --cflags 2>/dev/null) - sdl_image=yes - - sdl_cflags="$sdl_cflags $sdl_image_cflags" - sdl_libs="$sdl_libs $sdl_image_libs" - else - if test "$sdl_image" = "yes" ; then - feature_not_found "sdl_image" "Install SDL Image devel" - else - sdl_image=no - fi - fi - fi -} - -if test "$sdl" != "no" ; then - sdl_probe -fi - -if test "$sdl" = "yes" ; then - sdl_image_probe -else - if test "$sdl_image" = "yes"; then - echo "warning: SDL Image requested, but SDL is not available, disabling" - fi - sdl_image=no -fi - -if test "$sdl" = "yes" ; then - cat > $TMPC < -#if defined(SDL_VIDEO_DRIVER_X11) -#include -#else -#error No x11 support -#endif -int main(void) { return 0; } -EOF - if compile_prog "$sdl_cflags $x11_cflags" "$sdl_libs $x11_libs" ; then - need_x11=yes - sdl_cflags="$sdl_cflags $x11_cflags" - sdl_libs="$sdl_libs $x11_libs" - fi -fi - -########################################## -# RDMA needs OpenFabrics libraries -if test "$rdma" != "no" ; then - cat > $TMPC < -int main(void) { return 0; } -EOF - rdma_libs="-lrdmacm -libverbs -libumad" - if compile_prog "" "$rdma_libs" ; then - rdma="yes" - libs_softmmu="$libs_softmmu $rdma_libs" - else - if test "$rdma" = "yes" ; then - error_exit \ - " OpenFabrics librdmacm/libibverbs/libibumad not present." \ - " Your options:" \ - " (1) Fast: Install infiniband packages (devel) from your distro." \ - " (2) Cleanest: Install libraries from www.openfabrics.org" \ - " (3) Also: Install softiwarp if you don't have RDMA hardware" - fi - rdma="no" - fi -fi - -########################################## -# PVRDMA detection - -cat > $TMPC < +cat > $TMPC < int main(void) @@ -3373,101 +3229,6 @@ EOF fi fi -########################################## -# VNC SASL detection -if test "$vnc" = "yes" && test "$vnc_sasl" != "no" ; then - cat > $TMPC < -#include -int main(void) { sasl_server_init(NULL, "qemu"); return 0; } -EOF - # Assuming Cyrus-SASL installed in /usr prefix - # QEMU defines struct iovec in "qemu/osdep.h", - # we don't want libsasl to redefine it in . - vnc_sasl_cflags="-DSTRUCT_IOVEC_DEFINED" - vnc_sasl_libs="-lsasl2" - if compile_prog "$vnc_sasl_cflags" "$vnc_sasl_libs" ; then - vnc_sasl=yes - libs_softmmu="$vnc_sasl_libs $libs_softmmu" - QEMU_CFLAGS="$QEMU_CFLAGS $vnc_sasl_cflags" - else - if test "$vnc_sasl" = "yes" ; then - feature_not_found "vnc-sasl" "Install Cyrus SASL devel" - fi - vnc_sasl=no - fi -fi - -########################################## -# VNC JPEG detection -if test "$vnc" = "yes" && test "$vnc_jpeg" != "no" ; then -cat > $TMPC < -#include -int main(void) { struct jpeg_compress_struct s; jpeg_create_compress(&s); return 0; } -EOF - vnc_jpeg_cflags="" - vnc_jpeg_libs="-ljpeg" - if compile_prog "$vnc_jpeg_cflags" "$vnc_jpeg_libs" ; then - vnc_jpeg=yes - libs_softmmu="$vnc_jpeg_libs $libs_softmmu" - QEMU_CFLAGS="$QEMU_CFLAGS $vnc_jpeg_cflags" - else - if test "$vnc_jpeg" = "yes" ; then - feature_not_found "vnc-jpeg" "Install libjpeg-turbo devel" - fi - vnc_jpeg=no - fi -fi - -########################################## -# VNC PNG detection -if test "$vnc" = "yes" && test "$vnc_png" != "no" ; then -cat > $TMPC < -#include -#include -int main(void) { - png_structp png_ptr; - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - return png_ptr != 0; -} -EOF - if $pkg_config libpng --exists; then - vnc_png_cflags=$($pkg_config libpng --cflags) - vnc_png_libs=$($pkg_config libpng --libs) - else - vnc_png_cflags="" - vnc_png_libs="-lpng" - fi - if compile_prog "$vnc_png_cflags" "$vnc_png_libs" ; then - vnc_png=yes - libs_softmmu="$vnc_png_libs $libs_softmmu" - QEMU_CFLAGS="$QEMU_CFLAGS $vnc_png_cflags" - else - if test "$vnc_png" = "yes" ; then - feature_not_found "vnc-png" "Install libpng devel" - fi - vnc_png=no - fi -fi - -########################################## -# xkbcommon probe -if test "$xkbcommon" != "no" ; then - if $pkg_config xkbcommon --exists; then - xkbcommon_cflags=$($pkg_config xkbcommon --cflags) - xkbcommon_libs=$($pkg_config xkbcommon --libs) - xkbcommon=yes - else - if test "$xkbcommon" = "yes" ; then - feature_not_found "xkbcommon" "Install libxkbcommon-devel" - fi - xkbcommon=no - fi -fi - - ########################################## # xfsctl() probe, used for file-posix.c if test "$xfs" != "no" ; then @@ -3484,7 +3245,7 @@ EOF xfs="yes" else if test "$xfs" = "yes" ; then - feature_not_found "xfs" "Instal xfsprogs/xfslibs devel" + feature_not_found "xfs" "Install xfsprogs/xfslibs devel" fi xfs=no fi @@ -3556,7 +3317,6 @@ int main(void) EOF if compile_prog "" "$cap_libs" ; then cap_ng=yes - libs_tools="$cap_libs $libs_tools" else if test "$cap_ng" = "yes" ; then feature_not_found "cap_ng" "Install libcap-ng devel" @@ -3574,6 +3334,8 @@ for drv in $audio_drv_list; do alsa | try-alsa) if $pkg_config alsa --exists; then alsa_libs=$($pkg_config alsa --libs) + alsa_cflags=$($pkg_config alsa --cflags) + alsa=yes if test "$drv" = "try-alsa"; then audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-alsa/alsa/') fi @@ -3589,7 +3351,9 @@ for drv in $audio_drv_list; do pa | try-pa) if $pkg_config libpulse --exists; then + libpulse=yes pulse_libs=$($pkg_config libpulse --libs) + pulse_cflags=$($pkg_config libpulse --cflags) if test "$drv" = "try-pa"; then audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-pa/pa/') fi @@ -3632,6 +3396,7 @@ for drv in $audio_drv_list; do jack | try-jack) if $pkg_config jack --exists; then + libjack=yes jack_libs=$($pkg_config jack --libs) if test "$drv" = "try-jack"; then audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-jack/jack/') @@ -3675,105 +3440,6 @@ EOF fi fi -########################################## -# iconv probe -if test "$iconv" != "no" ; then - cat > $TMPC << EOF -#include -int main(void) { - iconv_t conv = iconv_open("WCHAR_T", "UCS-2"); - return conv != (iconv_t) -1; -} -EOF - iconv_prefix_list="/usr/local:/usr" - iconv_lib_list=":-liconv" - IFS=: - for iconv_prefix in $iconv_prefix_list; do - IFS=: - iconv_cflags="-I$iconv_prefix/include" - iconv_ldflags="-L$iconv_prefix/lib" - for iconv_link in $iconv_lib_list; do - unset IFS - iconv_lib="$iconv_ldflags $iconv_link" - echo "looking at iconv in '$iconv_cflags' '$iconv_lib'" >> config.log - if compile_prog "$iconv_cflags" "$iconv_lib" ; then - iconv_found=yes - break - fi - done - if test "$iconv_found" = yes ; then - break - fi - done - if test "$iconv_found" = "yes" ; then - iconv=yes - else - if test "$iconv" = "yes" ; then - feature_not_found "iconv" "Install iconv devel" - fi - iconv=no - fi -fi - -########################################## -# curses probe -if test "$iconv" = "no" ; then - # curses will need iconv - curses=no -fi -if test "$curses" != "no" ; then - if test "$mingw32" = "yes" ; then - curses_inc_list="$($pkg_config --cflags ncurses 2>/dev/null):" - curses_lib_list="$($pkg_config --libs ncurses 2>/dev/null):-lpdcurses" - else - curses_inc_list="$($pkg_config --cflags ncursesw 2>/dev/null):-I/usr/include/ncursesw:" - curses_lib_list="$($pkg_config --libs ncursesw 2>/dev/null):-lncursesw:-lcursesw" - fi - curses_found=no - cat > $TMPC << EOF -#include -#include -#include -#include -int main(void) { - const char *codeset; - wchar_t wch = L'w'; - setlocale(LC_ALL, ""); - resize_term(0, 0); - addwstr(L"wide chars\n"); - addnwstr(&wch, 1); - add_wch(WACS_DEGREE); - codeset = nl_langinfo(CODESET); - return codeset != 0; -} -EOF - IFS=: - for curses_inc in $curses_inc_list; do - # Make sure we get the wide character prototypes - curses_inc="-DNCURSES_WIDECHAR $curses_inc" - IFS=: - for curses_lib in $curses_lib_list; do - unset IFS - if compile_prog "$curses_inc" "$curses_lib" ; then - curses_found=yes - break - fi - done - if test "$curses_found" = yes ; then - break - fi - done - unset IFS - if test "$curses_found" = "yes" ; then - curses=yes - else - if test "$curses" = "yes" ; then - feature_not_found "curses" "Install ncurses devel" - fi - curses=no - fi -fi - ########################################## # curl probe if test "$curl" != "no" ; then @@ -3810,33 +3476,45 @@ if test "$plugins" = yes; then glib_modules="$glib_modules gmodule-2.0" fi -# This workaround is required due to a bug in pkg-config file for glib as it -# doesn't define GLIB_STATIC_COMPILATION for pkg-config --static - -if test "$static" = yes && test "$mingw32" = yes; then - QEMU_CFLAGS="-DGLIB_STATIC_COMPILATION $QEMU_CFLAGS" -fi - for i in $glib_modules; do if $pkg_config --atleast-version=$glib_req_ver $i; then glib_cflags=$($pkg_config --cflags $i) glib_libs=$($pkg_config --libs $i) - QEMU_CFLAGS="$glib_cflags $QEMU_CFLAGS" - LIBS="$glib_libs $LIBS" - libs_qga="$glib_libs $libs_qga" else error_exit "glib-$glib_req_ver $i is required to compile QEMU" fi done +# This workaround is required due to a bug in pkg-config file for glib as it +# doesn't define GLIB_STATIC_COMPILATION for pkg-config --static + +if test "$static" = yes && test "$mingw32" = yes; then + glib_cflags="-DGLIB_STATIC_COMPILATION $glib_cflags" +fi + if $pkg_config --atleast-version=$glib_req_ver gio-2.0; then - gio=yes gio_cflags=$($pkg_config --cflags gio-2.0) gio_libs=$($pkg_config --libs gio-2.0) gdbus_codegen=$($pkg_config --variable=gdbus_codegen gio-2.0) if [ ! -x "$gdbus_codegen" ]; then gdbus_codegen= fi + # Check that the libraries actually work -- Ubuntu 18.04 ships + # with pkg-config --static --libs data for gio-2.0 that is missing + # -lblkid and will give a link error. + cat > $TMPC < +int main(void) +{ + g_dbus_proxy_new_sync(0, 0, 0, 0, 0, 0, 0, 0); + return 0; +} +EOF + if compile_prog "$gio_cflags" "$gio_libs" ; then + gio=yes + else + gio=no + fi else gio=no fi @@ -3863,7 +3541,7 @@ int main(void) { } EOF -if ! compile_prog "$CFLAGS" "$LIBS" ; then +if ! compile_prog "$glib_cflags" "$glib_libs" ; then error_exit "sizeof(size_t) doesn't match GLIB_SIZEOF_SIZE_T."\ "You probably need to set PKG_CONFIG_LIBDIR"\ "to point to the right pkg-config files for your"\ @@ -3878,7 +3556,7 @@ EOF if ! compile_prog "$glib_cflags -Werror" "$glib_libs" ; then if cc_has_warning_flag "-Wno-unknown-attributes"; then glib_cflags="-Wno-unknown-attributes $glib_cflags" - CFLAGS="-Wno-unknown-attributes $CFLAGS" + CONFIGURE_CFLAGS="-Wno-unknown-attributes $CONFIGURE_CFLAGS" fi fi @@ -3898,30 +3576,7 @@ EOF if ! compile_prog "$glib_cflags -Werror" "$glib_libs" ; then if cc_has_warning_flag "-Wno-unused-function"; then glib_cflags="$glib_cflags -Wno-unused-function" - CFLAGS="$CFLAGS -Wno-unused-function" - fi -fi - -######################################### -# zlib check - -if test "$zlib" != "no" ; then - if $pkg_config --exists zlib; then - zlib_cflags=$($pkg_config --cflags zlib) - zlib_libs=$($pkg_config --libs zlib) - QEMU_CFLAGS="$zlib_cflags $QEMU_CFLAGS" - LIBS="$zlib_libs $LIBS" - else - cat > $TMPC << EOF -#include -int main(void) { zlibVersion(); return 0; } -EOF - if compile_prog "" "-lz" ; then - LIBS="$LIBS -lz" - else - error_exit "zlib check failed" \ - "Make sure to have the zlib libs and headers installed." - fi + CONFIGURE_CFLAGS="$CONFIGURE_CFLAGS -Wno-unused-function" fi fi @@ -3940,71 +3595,6 @@ if test "$modules" = yes; then fi fi -########################################## -# pixman support probe - -if test "$want_tools" = "no" && test "$softmmu" = "no"; then - pixman_cflags= - pixman_libs= -elif $pkg_config --atleast-version=0.21.8 pixman-1 > /dev/null 2>&1; then - pixman_cflags=$($pkg_config --cflags pixman-1) - pixman_libs=$($pkg_config --libs pixman-1) -else - error_exit "pixman >= 0.21.8 not present." \ - "Please install the pixman devel package." -fi - -########################################## -# libmpathpersist probe - -if test "$mpath" != "no" ; then - # probe for the new API - cat > $TMPC < -#include -unsigned mpath_mx_alloc_len = 1024; -int logsink; -static struct config *multipath_conf; -extern struct udev *udev; -extern struct config *get_multipath_config(void); -extern void put_multipath_config(struct config *conf); -struct udev *udev; -struct config *get_multipath_config(void) { return multipath_conf; } -void put_multipath_config(struct config *conf) { } - -int main(void) { - udev = udev_new(); - multipath_conf = mpath_lib_init(); - return 0; -} -EOF - if compile_prog "" "-ludev -lmultipath -lmpathpersist" ; then - mpathpersist=yes - mpathpersist_new_api=yes - else - # probe for the old API - cat > $TMPC < -#include -unsigned mpath_mx_alloc_len = 1024; -int logsink; -int main(void) { - struct udev *udev = udev_new(); - mpath_lib_init(udev); - return 0; -} -EOF - if compile_prog "" "-ludev -lmultipath -lmpathpersist" ; then - mpathpersist=yes - mpathpersist_new_api=no - else - mpathpersist=no - fi - fi -else - mpathpersist=no -fi - ########################################## # pthread probe PTHREADLIBS_LIST="-pthread -lpthread -lpthreadGC2" @@ -4034,9 +3624,7 @@ else done if test "$found" = "no"; then LIBS="$pthread_lib $LIBS" - libs_qga="$pthread_lib $libs_qga" fi - PTHREAD_LIB="$pthread_lib" break fi done @@ -4070,7 +3658,7 @@ pthread_setname_np_wo_tid=no cat > $TMPC << EOF #include -static void *f(void *p) { pthread_setname_np("QEMU"); } +static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; } int main(void) { pthread_t thread; @@ -4164,11 +3752,6 @@ if test "$linux_io_uring" != "no" ; then linux_io_uring_cflags=$($pkg_config --cflags liburing) linux_io_uring_libs=$($pkg_config --libs liburing) linux_io_uring=yes - - # io_uring is used in libqemuutil.a where per-file -libs variables are not - # seen by programs linking the archive. It's not ideal, but just add the - # library dependency globally. - LIBS="$linux_io_uring_libs $LIBS" else if test "$linux_io_uring" = "yes" ; then feature_not_found "linux io_uring" "Install liburing devel" @@ -4195,6 +3778,7 @@ fi ########################################## # attr probe +libattr_libs= if test "$attr" != "no" ; then cat > $TMPC < @@ -4211,7 +3795,7 @@ EOF # Older distros have , and need -lattr: elif compile_prog "-DCONFIG_LIBATTR" "-lattr" ; then attr=yes - LIBS="-lattr $LIBS" + libattr_libs="-lattr" libattr=yes else if test "$attr" = "yes" ; then @@ -4249,73 +3833,15 @@ fi ########################################## # fdt probe -# fdt support is mandatory for at least some target architectures, -# so insist on it if we're building those system emulators. -fdt_required=no -for target in $target_list; do - case $target in - aarch64*-softmmu|arm*-softmmu|ppc*-softmmu|microblaze*-softmmu|mips64el-softmmu|riscv*-softmmu|rx-softmmu) - fdt_required=yes - ;; - esac -done -if test "$fdt_required" = "yes"; then - if test "$fdt" = "no"; then - error_exit "fdt disabled but some requested targets require it." \ - "You can turn off fdt only if you also disable all the system emulation" \ - "targets which need it (by specifying a cut down --target-list)." - fi - fdt=yes -elif test "$fdt" != "yes" ; then - fdt=no -fi - -# fdt is only required when building softmmu targets -if test -z "$fdt" -a "$softmmu" != "yes" ; then - fdt="no" -fi - -if test "$fdt" != "no" ; then - fdt_libs="-lfdt" - # explicitly check for libfdt_env.h as it is missing in some stable installs - # and test for required functions to make sure we are on a version >= 1.4.2 - cat > $TMPC << EOF -#include -#include -int main(void) { fdt_check_full(NULL, 0); return 0; } -EOF - if compile_prog "" "$fdt_libs" ; then - # system DTC is good - use it - fdt=system - else - # have GIT checkout, so activate dtc submodule - if test -e "${source_path}/.git" ; then - git_submodules="${git_submodules} dtc" - fi - if test -d "${source_path}/dtc/libfdt" || test -e "${source_path}/.git" ; then - fdt=git - mkdir -p dtc - if [ "$pwd_is_source_path" != "y" ] ; then - symlink "$source_path/dtc/Makefile" "dtc/Makefile" - symlink "$source_path/dtc/scripts" "dtc/scripts" - fi - fdt_cflags="-I\$(SRC_PATH)/dtc/libfdt" - fdt_ldflags="-L\$(BUILD_DIR)/dtc/libfdt" - fdt_libs="$fdt_libs" - elif test "$fdt" = "yes" ; then - # Not a git build & no libfdt found, prompt for system install - error_exit "DTC (libfdt) version >= 1.4.2 not present." \ - "Please install the DTC (libfdt) devel package" - else - # don't have and don't want - fdt_libs= - fdt=no - fi - fi -fi - -libs_softmmu="$libs_softmmu $fdt_libs" +case "$fdt" in + auto | enabled | internal) + # Simpler to always update submodule, even if not needed. + if test -e "${source_path}/.git" && test $git_update = 'yes' ; then + git_submodules="${git_submodules} dtc" + fi + ;; +esac ########################################## # opengl probe (for sdl2, gtk, milkymist-tmu2) @@ -4336,7 +3862,6 @@ if test "$opengl" != "no" ; then if test "$gtk" = "yes" && $pkg_config --exists "$gtkpackage >= 3.16"; then gtk_gl="yes" fi - QEMU_CFLAGS="$QEMU_CFLAGS $opengl_cflags" else if test "$opengl" = "yes" ; then feature_not_found "opengl" "Please install opengl (mesa) devel pkgs: $opengl_pkgs" @@ -4540,7 +4065,7 @@ EOF if compile_prog "" "-lnuma" ; then numa=yes - libs_softmmu="-lnuma $libs_softmmu" + numa_libs="-lnuma" else if test "$numa" = "yes" ; then feature_not_found "numa" "install numactl devel" @@ -4549,65 +4074,14 @@ EOF fi fi +malloc=system if test "$tcmalloc" = "yes" && test "$jemalloc" = "yes" ; then echo "ERROR: tcmalloc && jemalloc can't be used at the same time" exit 1 -fi - -# Even if malloc_trim() is available, these non-libc memory allocators -# do not support it. -if test "$tcmalloc" = "yes" || test "$jemalloc" = "yes" ; then - if test "$malloc_trim" = "yes" ; then - echo "Disabling malloc_trim with non-libc memory allocator" - fi - malloc_trim="no" -fi - -####################################### -# malloc_trim - -if test "$malloc_trim" != "no" ; then - cat > $TMPC << EOF -#include -int main(void) { malloc_trim(0); return 0; } -EOF - if compile_prog "" "" ; then - malloc_trim="yes" - else - malloc_trim="no" - fi -fi - -########################################## -# tcmalloc probe - -if test "$tcmalloc" = "yes" ; then - cat > $TMPC << EOF -#include -int main(void) { malloc(1); return 0; } -EOF - - if compile_prog "" "-ltcmalloc" ; then - LIBS="-ltcmalloc $LIBS" - else - feature_not_found "tcmalloc" "install gperftools devel" - fi -fi - -########################################## -# jemalloc probe - -if test "$jemalloc" = "yes" ; then - cat > $TMPC << EOF -#include -int main(void) { malloc(1); return 0; } -EOF - - if compile_prog "" "-ljemalloc" ; then - LIBS="-ljemalloc $LIBS" - else - feature_not_found "jemalloc" "install jemalloc devel" - fi +elif test "$tcmalloc" = "yes" ; then + malloc=tcmalloc +elif test "$jemalloc" = "yes" ; then + malloc=jemalloc fi ########################################## @@ -4946,43 +4420,10 @@ if check_include sys/kcov.h ; then kcov=yes fi -# If we're making warnings fatal, apply this to Sphinx runs as well -sphinx_werror="" -if test "$werror" = "yes"; then - sphinx_werror="-W" -fi - -# Check we have a new enough version of sphinx-build -has_sphinx_build() { - # This is a bit awkward but works: create a trivial document and - # try to run it with our configuration file (which enforces a - # version requirement). This will fail if either - # sphinx-build doesn't exist at all or if it is too old. - mkdir -p "$TMPDIR1/sphinx" - touch "$TMPDIR1/sphinx/index.rst" - "$sphinx_build" $sphinx_werror -c "$source_path/docs" \ - -b html "$TMPDIR1/sphinx" \ - "$TMPDIR1/sphinx/out" >> config.log 2>&1 -} - -# Check if tools are available to build documentation. -if test "$docs" != "no" ; then - if has_sphinx_build; then - sphinx_ok=yes - else - sphinx_ok=no - fi - if has makeinfo && has pod2man && test "$sphinx_ok" = "yes"; then - docs=yes - else - if test "$docs" = "yes" ; then - if has $sphinx_build && test "$sphinx_ok" != "yes"; then - echo "Warning: $sphinx_build exists but it is either too old or uses too old a Python version" >&2 - fi - feature_not_found "docs" "Install texinfo, Perl/perl-podlators and a Python 3 version of python-sphinx" - fi - docs=no - fi +# check for btrfs filesystem support (kernel must be 3.9+) +btrfs=no +if check_include linux/btrfs.h ; then + btrfs=yes fi # Search for bswap_32 function @@ -5022,21 +4463,6 @@ if test "$libiscsi" != "no" ; then fi fi -########################################## -# Do we need libm -cat > $TMPC << EOF -#include -int main(int argc, char **argv) { return isnan(sin((double)argc)); } -EOF -if compile_prog "" "" ; then - : -elif compile_prog "" "-lm" ; then - LIBS="-lm $LIBS" - libs_qga="-lm $libs_qga" -else - error_exit "libm check failed" -fi - ########################################## # Do we need librt # uClibc provides 2 versions of clock_gettime(), one with realtime @@ -5057,19 +4483,20 @@ if compile_prog "" "" ; then # we need pthread for static linking. use previous pthread test result elif compile_prog "" "$pthread_lib -lrt" ; then LIBS="$LIBS -lrt" - libs_qga="$libs_qga -lrt" fi -# Check whether we need to link libutil for openpty() +# Check whether we have openpty() in either libc or libutil cat > $TMPC << EOF extern int openpty(int *am, int *as, char *name, void *termp, void *winp); int main(void) { return openpty(0, 0, 0, 0, 0); } EOF -if ! compile_prog "" "" ; then +have_openpty="no" +if compile_prog "" "" ; then + have_openpty="yes" +else if compile_prog "" "-lutil" ; then - libs_softmmu="-lutil $libs_softmmu" - libs_tools="-lutil $libs_tools" + have_openpty="yes" fi fi @@ -5086,10 +4513,6 @@ EOF $pkg_config --atleast-version=0.12.3 spice-protocol && \ compile_prog "$spice_cflags" "$spice_libs" ; then spice="yes" - libs_softmmu="$libs_softmmu $spice_libs" - QEMU_CFLAGS="$QEMU_CFLAGS $spice_cflags" - spice_protocol_version=$($pkg_config --modversion spice-protocol) - spice_server_version=$($pkg_config --modversion spice-server) else if test "$spice" = "yes" ; then feature_not_found "spice" \ @@ -5245,54 +4668,14 @@ fi # capstone case "$capstone" in - "" | yes) - if $pkg_config capstone; then - capstone=system - elif test -e "${source_path}/.git" && test $git_update = 'yes' ; then - capstone=git - elif test -e "${source_path}/capstone/Makefile" ; then - capstone=internal - elif test -z "$capstone" ; then - capstone=no - else - feature_not_found "capstone" "Install capstone devel or git submodule" - fi - ;; - - system) - if ! $pkg_config capstone; then - feature_not_found "capstone" "Install capstone devel" + auto | enabled | internal) + # Simpler to always update submodule, even if not needed. + if test -e "${source_path}/.git" && test $git_update = 'yes' ; then + git_submodules="${git_submodules} capstone" fi ;; esac -case "$capstone" in - git | internal) - if test "$capstone" = git; then - git_submodules="${git_submodules} capstone" - fi - mkdir -p capstone - QEMU_CFLAGS="$QEMU_CFLAGS -I\$(SRC_PATH)/capstone/include" - if test "$mingw32" = "yes"; then - LIBCAPSTONE=capstone.lib - else - LIBCAPSTONE=libcapstone.a - fi - libs_cpu="-L\$(BUILD_DIR)/capstone -lcapstone $libs_cpu" - ;; - - system) - QEMU_CFLAGS="$QEMU_CFLAGS $($pkg_config --cflags capstone)" - libs_cpu="$($pkg_config --libs capstone) $libs_cpu" - ;; - - no) - ;; - *) - error_exit "Unknown state for capstone: $capstone" - ;; -esac - ########################################## # check if we have fdatasync @@ -5432,9 +4815,6 @@ EOF else urcu_bp_libs="-lurcu-bp" fi - - LIBS="$lttng_ust_libs $urcu_bp_libs $LIBS" - libs_qga="$lttng_ust_libs $urcu_bp_libs $libs_qga" else error_exit "Trace backend 'ust' missing lttng-ust header files" fi @@ -5449,6 +4829,13 @@ if have_backend "dtrace"; then trace_backend_stap="no" if has 'stap' ; then trace_backend_stap="yes" + + # Workaround to avoid dtrace(1) producing a file with 'hidden' symbol + # visibility. Define STAP_SDT_V2 to produce 'default' symbol visibility + # instead. QEMU --enable-modules depends on this because the SystemTap + # semaphores are linked into the main binary and not the module's shared + # object. + QEMU_CFLAGS="$QEMU_CFLAGS -DSTAP_SDT_V2" fi fi @@ -5518,6 +4905,67 @@ if test "$debug_stack_usage" = "yes"; then fi fi +################################################## +# SafeStack + + +if test "$safe_stack" = "yes"; then +cat > $TMPC << EOF +int main(int argc, char *argv[]) +{ +#if ! __has_feature(safe_stack) +#error SafeStack Disabled +#endif + return 0; +} +EOF + flag="-fsanitize=safe-stack" + # Check that safe-stack is supported and enabled. + if compile_prog "-Werror $flag" "$flag"; then + # Flag needed both at compilation and at linking + QEMU_CFLAGS="$QEMU_CFLAGS $flag" + QEMU_LDFLAGS="$QEMU_LDFLAGS $flag" + else + error_exit "SafeStack not supported by your compiler" + fi + if test "$coroutine" != "ucontext"; then + error_exit "SafeStack is only supported by the coroutine backend ucontext" + fi +else +cat > $TMPC << EOF +int main(int argc, char *argv[]) +{ +#if defined(__has_feature) +#if __has_feature(safe_stack) +#error SafeStack Enabled +#endif +#endif + return 0; +} +EOF +if test "$safe_stack" = "no"; then + # Make sure that safe-stack is disabled + if ! compile_prog "-Werror" ""; then + # SafeStack was already enabled, try to explicitly remove the feature + flag="-fno-sanitize=safe-stack" + if ! compile_prog "-Werror $flag" "$flag"; then + error_exit "Configure cannot disable SafeStack" + fi + QEMU_CFLAGS="$QEMU_CFLAGS $flag" + QEMU_LDFLAGS="$QEMU_LDFLAGS $flag" + fi +else # "$safe_stack" = "" + # Set safe_stack to yes or no based on pre-existing flags + if compile_prog "-Werror" ""; then + safe_stack="no" + else + safe_stack="yes" + if test "$coroutine" != "ucontext"; then + error_exit "SafeStack is only supported by the coroutine backend ucontext" + fi + fi +fi +fi ########################################## # check if we have open_by_handle_at @@ -5549,31 +4997,6 @@ if compile_prog "" "" ; then linux_magic_h=yes fi -######################################## -# check whether we can disable warning option with a pragma (this is needed -# to silence warnings in the headers of some versions of external libraries). -# This test has to be compiled with -Werror as otherwise an unknown pragma is -# only a warning. -# -# If we can't selectively disable warning in the code, disable -Werror so that -# the build doesn't fail anyway. - -pragma_disable_unused_but_set=no -cat > $TMPC << EOF -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-prototypes" -#pragma GCC diagnostic pop - -int main(void) { - return 0; -} -EOF -if compile_prog "-Werror" "" ; then - pragma_diagnostic_available=yes -else - werror=no -fi - ######################################## # check if we have valgrind/valgrind.h @@ -5746,11 +5169,11 @@ int main(void) { uint64_t x = 0, y = 0; #ifdef __ATOMIC_RELAXED - y = __atomic_load_8(&x, 0); - __atomic_store_8(&x, y, 0); - __atomic_compare_exchange_8(&x, &y, x, 0, 0, 0); - __atomic_exchange_8(&x, y, 0); - __atomic_fetch_add_8(&x, y, 0); + y = __atomic_load_n(&x, __ATOMIC_RELAXED); + __atomic_store_n(&x, y, __ATOMIC_RELAXED); + __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED); + __atomic_exchange_n(&x, y, __ATOMIC_RELAXED); + __atomic_fetch_add(&x, y, __ATOMIC_RELAXED); #else typedef char is_host64[sizeof(void *) >= sizeof(uint64_t) ? 1 : -1]; __sync_lock_test_and_set(&x, y); @@ -6017,46 +5440,6 @@ fi ################################################# -# Check to see if we have the Hypervisor framework -if [ "$darwin" = "yes" ] ; then - cat > $TMPC << EOF -#include -int main() { return 0;} -EOF - if ! compile_object ""; then - hvf='no' - else - hvf='yes' - QEMU_LDFLAGS="-framework Hypervisor $QEMU_LDFLAGS" - fi -fi - -################################################# -# Sparc implicitly links with --relax, which is -# incompatible with -r, so --no-relax should be -# given. It does no harm to give it on other -# platforms too. - -# Note: the prototype is needed since QEMU_CFLAGS -# contains -Wmissing-prototypes -cat > $TMPC << EOF -extern int foo(void); -int foo(void) { return 0; } -EOF -if ! compile_object ""; then - error_exit "Failed to compile object file for LD_REL_FLAGS test" -fi -for i in '-Wl,-r -Wl,--no-relax' -Wl,-r -r; do - if do_cc -nostdlib $i -o $TMPMO $TMPO; then - LD_REL_FLAGS=$i - break - fi -done -if test "$modules" = "yes" && test "$LD_REL_FLAGS" = ""; then - feature_not_found "modules" "Cannot find how to build relocatable objects" -fi - -########################################## # check for sysmacros.h have_sysmacros=no @@ -6070,33 +5453,6 @@ if compile_prog "" "" ; then have_sysmacros=yes fi -########################################## -# Veritas HyperScale block driver VxHS -# Check if libvxhs is installed - -if test "$vxhs" != "no" ; then - cat > $TMPC < -#include - -void *vxhs_callback; - -int main(void) { - iio_init(QNIO_VERSION, vxhs_callback); - return 0; -} -EOF - vxhs_libs="-lvxhs -lssl" - if compile_prog "" "$vxhs_libs" ; then - vxhs=yes - else - if test "$vxhs" = "yes" ; then - feature_not_found "vxhs block device" "Install libvxhs See github" - fi - vxhs=no - fi -fi - ########################################## # check for _Static_assert() @@ -6161,7 +5517,10 @@ if test "$sanitizers" = "yes" ; then #include int main(void) { void *tmp = malloc(10); - return *(int *)(tmp + 2); + if (tmp != NULL) { + return *(int *)(tmp + 2); + } + return 1; } EOF if compile_prog "$CPU_CFLAGS -Werror -fsanitize=undefined" ""; then @@ -6186,10 +5545,37 @@ fi ########################################## # checks for fuzzer -if test "$fuzzing" = "yes" ; then +if test "$fuzzing" = "yes" && test -z "${LIB_FUZZING_ENGINE+xxx}"; then write_c_fuzzer_skeleton - if compile_prog "$CPU_CFLAGS -Werror -fsanitize=address,fuzzer" ""; then - have_fuzzer=yes + if compile_prog "$CPU_CFLAGS -Werror -fsanitize=fuzzer" ""; then + have_fuzzer=yes + else + error_exit "Your compiler doesn't support -fsanitize=fuzzer" + exit 1 + fi +fi + +# Thread sanitizer is, for now, much noisier than the other sanitizers; +# keep it separate until that is not the case. +if test "$tsan" = "yes" && test "$sanitizers" = "yes"; then + error_exit "TSAN is not supported with other sanitiziers." +fi +have_tsan=no +have_tsan_iface_fiber=no +if test "$tsan" = "yes" ; then + write_c_skeleton + if compile_prog "$CPU_CFLAGS -Werror -fsanitize=thread" "" ; then + have_tsan=yes + fi + cat > $TMPC << EOF +#include +int main(void) { + __tsan_create_fiber(0); + return 0; +} +EOF + if compile_prog "$CPU_CFLAGS -Werror -fsanitize=thread" "" ; then + have_tsan_iface_fiber=yes fi fi @@ -6201,8 +5587,6 @@ if test "$libpmem" != "no"; then libpmem="yes" libpmem_libs=$($pkg_config --libs libpmem) libpmem_cflags=$($pkg_config --cflags libpmem) - libs_softmmu="$libs_softmmu $libpmem_libs" - QEMU_CFLAGS="$QEMU_CFLAGS $libpmem_cflags" else if test "$libpmem" = "yes" ; then feature_not_found "libpmem" "Install nvml or pmdk" @@ -6212,61 +5596,67 @@ if test "$libpmem" != "no"; then fi ########################################## -# check for slirp +# check for libdaxctl -# slirp is only required when building softmmu targets -if test -z "$slirp" -a "$softmmu" != "yes" ; then - slirp="no" +if test "$libdaxctl" != "no"; then + if $pkg_config --atleast-version=57 "libdaxctl"; then + libdaxctl="yes" + libdaxctl_libs=$($pkg_config --libs libdaxctl) + libdaxctl_cflags=$($pkg_config --cflags libdaxctl) + else + if test "$libdaxctl" = "yes" ; then + feature_not_found "libdaxctl" "Install libdaxctl" + fi + libdaxctl="no" + fi fi -case "$slirp" in - "" | yes) - if $pkg_config slirp; then - slirp=system - elif test -e "${source_path}/.git" && test $git_update = 'yes' ; then - slirp=git - elif test -e "${source_path}/slirp/Makefile" ; then - slirp=internal - elif test -z "$slirp" ; then - slirp=no - else - feature_not_found "slirp" "Install slirp devel or git submodule" - fi - ;; - - system) - if ! $pkg_config slirp; then - feature_not_found "slirp" "Install slirp devel" - fi - ;; -esac +########################################## +# check for slirp case "$slirp" in - git | internal) - if test "$slirp" = git; then + auto | enabled | internal) + # Simpler to always update submodule, even if not needed. + if test -e "${source_path}/.git" && test $git_update = 'yes' ; then git_submodules="${git_submodules} slirp" fi - mkdir -p slirp - slirp_cflags="-I\$(SRC_PATH)/slirp/src -I\$(BUILD_DIR)/slirp/src" - slirp_libs="-L\$(BUILD_DIR)/slirp -lslirp" - if test "$mingw32" = "yes" ; then - slirp_libs="$slirp_libs -lws2_32 -liphlpapi" - fi ;; +esac - system) - slirp_version=$($pkg_config --modversion slirp 2>/dev/null) - slirp_cflags=$($pkg_config --cflags slirp 2>/dev/null) - slirp_libs=$($pkg_config --libs slirp 2>/dev/null) - ;; +########################################## +# check for usable __NR_keyctl syscall - no) - ;; - *) - error_exit "Unknown state for slirp: $slirp" - ;; -esac +if test "$linux" = "yes" ; then + have_keyring=no + cat > $TMPC << EOF +#include +#include +#include +#include +int main(void) { + return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0); +} +EOF + if compile_prog "" "" ; then + have_keyring=yes + fi +fi +if test "$secret_keyring" != "no" +then + if test "$have_keyring" = "yes" + then + secret_keyring=yes + else + if test "$secret_keyring" = "yes" + then + error_exit "syscall __NR_keyctl requested, \ +but not implemented on your system" + else + secret_keyring=no + fi + fi +fi ########################################## # End of CC checks @@ -6275,12 +5665,22 @@ esac write_c_skeleton if test "$gcov" = "yes" ; then - QEMU_CFLAGS="-fprofile-arcs -ftest-coverage -g $QEMU_CFLAGS" - QEMU_LDFLAGS="-fprofile-arcs -ftest-coverage $QEMU_LDFLAGS" + : elif test "$fortify_source" = "yes" ; then - CFLAGS="-O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $CFLAGS" -elif test "$debug" = "no"; then - CFLAGS="-O2 $CFLAGS" + QEMU_CFLAGS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $QEMU_CFLAGS" + debug=no +fi + +case "$ARCH" in +alpha) + # Ensure there's only a single GP + QEMU_CFLAGS="-msmall-data $QEMU_CFLAGS" +;; +esac + +if test "$gprof" = "yes" ; then + QEMU_CFLAGS="-p $QEMU_CFLAGS" + QEMU_LDFLAGS="-p $QEMU_LDFLAGS" fi if test "$have_asan" = "yes"; then @@ -6294,6 +5694,16 @@ if test "$have_asan" = "yes"; then "Without code annotation, the report may be inferior." fi fi +if test "$have_tsan" = "yes" ; then + if test "$have_tsan_iface_fiber" = "yes" ; then + QEMU_CFLAGS="-fsanitize=thread $QEMU_CFLAGS" + QEMU_LDFLAGS="-fsanitize=thread $QEMU_LDFLAGS" + else + error_exit "Cannot enable TSAN due to missing fiber annotation interface." + fi +elif test "$tsan" = "yes" ; then + error_exit "Cannot enable TSAN due to missing sanitize thread interface." +fi if test "$have_ubsan" = "yes"; then QEMU_CFLAGS="-fsanitize=undefined $QEMU_CFLAGS" QEMU_LDFLAGS="-fsanitize=undefined $QEMU_LDFLAGS" @@ -6314,111 +5724,50 @@ if test "$libnfs" != "no" ; then fi ########################################## -# Do we have libudev -if test "$libudev" != "no" ; then - if $pkg_config libudev && test "$static" != "yes"; then - libudev="yes" - libudev_libs=$($pkg_config --libs libudev) - else - libudev="no" - fi -fi - -# Now we've finished running tests it's OK to add -Werror to the compiler flags -if test "$werror" = "yes"; then - QEMU_CFLAGS="-Werror $QEMU_CFLAGS" -fi -if test "$solaris" = "no" ; then +# Exclude --warn-common with TSan to suppress warnings from the TSan libraries. +if test "$solaris" = "no" && test "$tsan" = "no"; then if $ld --version 2>/dev/null | grep "GNU ld" >/dev/null 2>/dev/null ; then QEMU_LDFLAGS="-Wl,--warn-common $QEMU_LDFLAGS" fi fi -# test if pod2man has --utf8 option -if pod2man --help | grep -q utf8; then - POD2MAN="pod2man --utf8" -else - POD2MAN="pod2man" -fi - # Use ASLR, no-SEH and DEP if available if test "$mingw32" = "yes" ; then - for flag in --dynamicbase --no-seh --nxcompat; do + flags="--no-seh --nxcompat" + + # Disable ASLR for debug builds to allow debugging with gdb + if test "$debug" = "no" ; then + flags="--dynamicbase $flags" + fi + + for flag in $flags; do if ld_has $flag ; then QEMU_LDFLAGS="-Wl,$flag $QEMU_LDFLAGS" fi done fi -# Disable OpenBSD W^X if available -if test "$tcg" = "yes" && test "$targetos" = "OpenBSD"; then - cat > $TMPC <" -fi -echo "spice support $spice $(echo_version $spice $spice_protocol_version/$spice_server_version)" -echo "rbd support $rbd" -echo "xfsctl support $xfs" -echo "smartcard support $smartcard" -echo "libusb $libusb" -echo "usb net redir $usb_redir" -echo "OpenGL support $opengl" -echo "OpenGL dmabufs $opengl_dmabuf" -echo "libiscsi support $libiscsi" -echo "libnfs support $libnfs" -echo "build guest agent $guest_agent" -echo "QGA VSS support $guest_agent_with_vss" -echo "QGA w32 disk info $guest_agent_ntddscsi" -echo "QGA MSI support $guest_agent_msi" -echo "seccomp support $seccomp" -echo "coroutine backend $coroutine" -echo "coroutine pool $coroutine_pool" -echo "debug stack usage $debug_stack_usage" -echo "mutex debugging $debug_mutex" -echo "crypto afalg $crypto_afalg" -echo "GlusterFS support $glusterfs" -echo "gcov $gcov_tool" -echo "gcov enabled $gcov" -echo "TPM support $tpm" -echo "libssh support $libssh" -echo "QOM debugging $qom_cast_debug" -echo "Live block migration $live_block_migration" -echo "lzo support $lzo" -echo "snappy support $snappy" -echo "bzip2 support $bzip2" -echo "lzfse support $lzfse" -echo "zstd support $zstd" -echo "NUMA host support $numa" -echo "libxml2 $libxml2" -echo "tcmalloc support $tcmalloc" -echo "jemalloc support $jemalloc" -echo "avx2 optimization $avx2_opt" -echo "avx512f optimization $avx512f_opt" -echo "replication support $replication" -echo "VxHS block device $vxhs" -echo "bochs support $bochs" -echo "cloop support $cloop" -echo "dmg support $dmg" -echo "qcow v1 support $qcow1" -echo "vdi support $vdi" -echo "vvfat support $vvfat" -echo "qed support $qed" -echo "parallels support $parallels" -echo "sheepdog support $sheepdog" -echo "capstone $capstone" -echo "libpmem support $libpmem" -echo "libudev $libudev" -echo "default devices $default_devices" -echo "plugin support $plugins" -echo "fuzzing support $fuzzing" -echo "gdb $gdb_bin" - -if test "$supported_cpu" = "no"; then - echo - echo "WARNING: SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!" - echo - echo "CPU host architecture $cpu support is not currently maintained." - echo "The QEMU project intends to remove support for this host CPU in" - echo "a future release if nobody volunteers to maintain it and to" - echo "provide a build host for our continuous integration setup." - echo "configure has succeeded and you can continue to build, but" - echo "if you care about QEMU on this platform you should contact" - echo "us upstream at qemu-devel@nongnu.org." -fi - -if test "$supported_os" = "no"; then - echo - echo "WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!" - echo - echo "Host OS $targetos support is not currently maintained." - echo "The QEMU project intends to remove support for this host OS in" - echo "a future release if nobody volunteers to maintain it and to" - echo "provide a build host for our continuous integration setup." - echo "configure has succeeded and you can continue to build, but" - echo "if you care about QEMU on this platform you should contact" - echo "us upstream at qemu-devel@nongnu.org." +if test $git_update = 'yes' ; then + (cd "${source_path}" && GIT="$git" "./scripts/git-submodule.sh" update "$git_submodules") fi config_host_mak="config-host.mak" -echo "# Automatically generated by configure - do not modify" >config-all-disas.mak - echo "# Automatically generated by configure - do not modify" > $config_host_mak echo >> $config_host_mak echo all: >> $config_host_mak -echo "prefix=$prefix" >> $config_host_mak -echo "bindir=$bindir" >> $config_host_mak -echo "libdir=$libdir" >> $config_host_mak -echo "libexecdir=$libexecdir" >> $config_host_mak -echo "includedir=$includedir" >> $config_host_mak -echo "mandir=$mandir" >> $config_host_mak -echo "sysconfdir=$sysconfdir" >> $config_host_mak -echo "qemu_confdir=$qemu_confdir" >> $config_host_mak -echo "qemu_datadir=$qemu_datadir" >> $config_host_mak -echo "qemu_firmwarepath=$firmwarepath" >> $config_host_mak -echo "qemu_docdir=$qemu_docdir" >> $config_host_mak -echo "qemu_moddir=$qemu_moddir" >> $config_host_mak -if test "$mingw32" = "no" ; then - echo "qemu_localstatedir=$local_statedir" >> $config_host_mak -fi -echo "qemu_helperdir=$libexecdir" >> $config_host_mak -echo "qemu_localedir=$qemu_localedir" >> $config_host_mak -echo "qemu_icondir=$qemu_icondir" >> $config_host_mak -echo "qemu_desktopdir=$qemu_desktopdir" >> $config_host_mak -echo "libs_cpu=$libs_cpu" >> $config_host_mak -echo "libs_softmmu=$libs_softmmu" >> $config_host_mak echo "GIT=$git" >> $config_host_mak echo "GIT_SUBMODULES=$git_submodules" >> $config_host_mak echo "GIT_UPDATE=$git_update" >> $config_host_mak @@ -6846,7 +5954,7 @@ if test "$mingw32" = "yes" ; then echo "CONFIG_QGA_NTDDSCSI=y" >> $config_host_mak fi if test "$guest_agent_msi" = "yes"; then - echo "QEMU_GA_MSI_ENABLED=yes" >> $config_host_mak + echo "CONFIG_QGA_MSI=y" >> $config_host_mak echo "QEMU_GA_MSI_MINGW_DLL_PATH=${QEMU_GA_MSI_MINGW_DLL_PATH}" >> $config_host_mak echo "QEMU_GA_MSI_WITH_VSS=${QEMU_GA_MSI_WITH_VSS}" >> $config_host_mak echo "QEMU_GA_MSI_ARCH=${QEMU_GA_MSI_ARCH}" >> $config_host_mak @@ -6881,15 +5989,10 @@ fi if test "$want_tools" = "yes" ; then echo "CONFIG_TOOLS=y" >> $config_host_mak fi -if test "$slirp" != "no"; then - echo "CONFIG_SLIRP=y" >> $config_host_mak - echo "CONFIG_SMBD_COMMAND=\"$smbd\"" >> $config_host_mak - echo "SLIRP_CFLAGS=$slirp_cflags" >> $config_host_mak - echo "SLIRP_LIBS=$slirp_libs" >> $config_host_mak -fi -if [ "$slirp" = "git" -o "$slirp" = "internal" ]; then - echo "config-host.h: slirp/all" >> $config_host_mak +if test "$guest_agent" = "yes" ; then + echo "CONFIG_GUEST_AGENT=y" >> $config_host_mak fi +echo "CONFIG_SMBD_COMMAND=\"$smbd\"" >> $config_host_mak if test "$vde" = "yes" ; then echo "CONFIG_VDE=y" >> $config_host_mak echo "VDE_LIBS=$vde_libs" >> $config_host_mak @@ -6905,55 +6008,42 @@ if test "$gprof" = "yes" ; then fi if test "$cap_ng" = "yes" ; then echo "CONFIG_LIBCAP_NG=y" >> $config_host_mak + echo "LIBCAP_NG_LIBS=$cap_libs" >> $config_host_mak fi echo "CONFIG_AUDIO_DRIVERS=$audio_drv_list" >> $config_host_mak for drv in $audio_drv_list; do def=CONFIG_AUDIO_$(echo $drv | LC_ALL=C tr '[a-z]' '[A-Z]') - case "$drv" in - alsa | oss | pa | sdl) - echo "$def=m" >> $config_host_mak ;; - *) - echo "$def=y" >> $config_host_mak ;; - esac + echo "$def=y" >> $config_host_mak done +if test "$alsa" = "yes" ; then + echo "CONFIG_ALSA=y" >> $config_host_mak +fi echo "ALSA_LIBS=$alsa_libs" >> $config_host_mak +echo "ALSA_CFLAGS=$alsa_cflags" >> $config_host_mak +if test "$libpulse" = "yes" ; then + echo "CONFIG_LIBPULSE=y" >> $config_host_mak +fi echo "PULSE_LIBS=$pulse_libs" >> $config_host_mak +echo "PULSE_CFLAGS=$pulse_cflags" >> $config_host_mak echo "COREAUDIO_LIBS=$coreaudio_libs" >> $config_host_mak echo "DSOUND_LIBS=$dsound_libs" >> $config_host_mak echo "OSS_LIBS=$oss_libs" >> $config_host_mak +if test "$libjack" = "yes" ; then + echo "CONFIG_LIBJACK=y" >> $config_host_mak +fi echo "JACK_LIBS=$jack_libs" >> $config_host_mak if test "$audio_win_int" = "yes" ; then echo "CONFIG_AUDIO_WIN_INT=y" >> $config_host_mak fi echo "CONFIG_BDRV_RW_WHITELIST=$block_drv_rw_whitelist" >> $config_host_mak echo "CONFIG_BDRV_RO_WHITELIST=$block_drv_ro_whitelist" >> $config_host_mak -if test "$vnc" = "yes" ; then - echo "CONFIG_VNC=y" >> $config_host_mak -fi -if test "$vnc_sasl" = "yes" ; then - echo "CONFIG_VNC_SASL=y" >> $config_host_mak -fi -if test "$vnc_jpeg" = "yes" ; then - echo "CONFIG_VNC_JPEG=y" >> $config_host_mak -fi -if test "$vnc_png" = "yes" ; then - echo "CONFIG_VNC_PNG=y" >> $config_host_mak -fi -if test "$xkbcommon" = "yes" ; then - echo "XKBCOMMON_CFLAGS=$xkbcommon_cflags" >> $config_host_mak - echo "XKBCOMMON_LIBS=$xkbcommon_libs" >> $config_host_mak -fi if test "$xfs" = "yes" ; then echo "CONFIG_XFS=y" >> $config_host_mak fi qemu_version=$(head $source_path/VERSION) -echo "VERSION=$qemu_version" >>$config_host_mak echo "PKGVERSION=$pkgversion" >>$config_host_mak echo "SRC_PATH=$source_path" >> $config_host_mak echo "TARGET_DIRS=$target_list" >> $config_host_mak -if [ "$docs" = "yes" ] ; then - echo "BUILD_DOCS=yes" >> $config_host_mak -fi if test "$modules" = "yes"; then # $shacmd can generate a hash started with digit, which the compiler doesn't # like as an symbol. So prefix it with an underscore @@ -6968,27 +6058,6 @@ if test "$have_x11" = "yes" && test "$need_x11" = "yes"; then echo "X11_CFLAGS=$x11_cflags" >> $config_host_mak echo "X11_LIBS=$x11_libs" >> $config_host_mak fi -if test "$sdl" = "yes" ; then - echo "CONFIG_SDL=m" >> $config_host_mak - echo "SDL_CFLAGS=$sdl_cflags" >> $config_host_mak - echo "SDL_LIBS=$sdl_libs" >> $config_host_mak - if test "$sdl_image" = "yes" ; then - echo "CONFIG_SDL_IMAGE=y" >> $config_host_mak - fi -fi -if test "$cocoa" = "yes" ; then - echo "CONFIG_COCOA=y" >> $config_host_mak -fi -if test "$iconv" = "yes" ; then - echo "CONFIG_ICONV=y" >> $config_host_mak - echo "ICONV_CFLAGS=$iconv_cflags" >> $config_host_mak - echo "ICONV_LIBS=$iconv_lib" >> $config_host_mak -fi -if test "$curses" = "yes" ; then - echo "CONFIG_CURSES=m" >> $config_host_mak - echo "CURSES_CFLAGS=$curses_inc" >> $config_host_mak - echo "CURSES_LIBS=$curses_lib" >> $config_host_mak -fi if test "$pipe2" = "yes" ; then echo "CONFIG_PIPE2=y" >> $config_host_mak fi @@ -7058,6 +6127,9 @@ fi if test "$kcov" = "yes" ; then echo "CONFIG_KCOV=y" >> $config_host_mak fi +if test "$btrfs" = "yes" ; then + echo "CONFIG_BTRFS=y" >> $config_host_mak +fi if test "$inotify" = "yes" ; then echo "CONFIG_INOTIFY=y" >> $config_host_mak fi @@ -7080,7 +6152,7 @@ if test "$bswap_h" = "yes" ; then echo "CONFIG_MACHINE_BSWAP_H=y" >> $config_host_mak fi if test "$curl" = "yes" ; then - echo "CONFIG_CURL=m" >> $config_host_mak + echo "CONFIG_CURL=y" >> $config_host_mak echo "CURL_CFLAGS=$curl_cflags" >> $config_host_mak echo "CURL_LIBS=$curl_libs" >> $config_host_mak fi @@ -7089,7 +6161,7 @@ if test "$brlapi" = "yes" ; then echo "BRLAPI_LIBS=$brlapi_libs" >> $config_host_mak fi if test "$gtk" = "yes" ; then - echo "CONFIG_GTK=m" >> $config_host_mak + echo "CONFIG_GTK=y" >> $config_host_mak echo "GTK_CFLAGS=$gtk_cflags" >> $config_host_mak echo "GTK_LIBS=$gtk_libs" >> $config_host_mak if test "$gtk_gl" = "yes" ; then @@ -7105,16 +6177,22 @@ fi echo "CONFIG_TLS_PRIORITY=\"$tls_priority\"" >> $config_host_mak if test "$gnutls" = "yes" ; then echo "CONFIG_GNUTLS=y" >> $config_host_mak + echo "GNUTLS_CFLAGS=$gnutls_cflags" >> $config_host_mak + echo "GNUTLS_LIBS=$gnutls_libs" >> $config_host_mak fi if test "$gcrypt" = "yes" ; then echo "CONFIG_GCRYPT=y" >> $config_host_mak if test "$gcrypt_hmac" = "yes" ; then echo "CONFIG_GCRYPT_HMAC=y" >> $config_host_mak fi + echo "GCRYPT_CFLAGS=$gcrypt_cflags" >> $config_host_mak + echo "GCRYPT_LIBS=$gcrypt_libs" >> $config_host_mak fi if test "$nettle" = "yes" ; then echo "CONFIG_NETTLE=y" >> $config_host_mak echo "CONFIG_NETTLE_VERSION_MAJOR=${nettle_version%%.*}" >> $config_host_mak + echo "NETTLE_CFLAGS=$nettle_cflags" >> $config_host_mak + echo "NETTLE_LIBS=$nettle_libs" >> $config_host_mak fi if test "$qemu_private_xts" = "yes" ; then echo "CONFIG_QEMU_PRIVATE_XTS=y" >> $config_host_mak @@ -7128,9 +6206,18 @@ fi if test "$have_ifaddrs_h" = "yes" ; then echo "HAVE_IFADDRS_H=y" >> $config_host_mak fi +if test "$have_drm_h" = "yes" ; then + echo "HAVE_DRM_H=y" >> $config_host_mak +fi if test "$have_broken_size_max" = "yes" ; then echo "HAVE_BROKEN_SIZE_MAX=y" >> $config_host_mak fi +if test "$have_openpty" = "yes" ; then + echo "HAVE_OPENPTY=y" >> $config_host_mak +fi +if test "$have_sys_signal_h" = "yes" ; then + echo "HAVE_SYS_SIGNAL_H=y" >> $config_host_mak +fi # Work around a system header bug with some kernel/XFS header # versions where they both try to define 'struct fsxattr': @@ -7152,9 +6239,11 @@ if test "$virglrenderer" = "yes" ; then echo "VIRGL_CFLAGS=$virgl_cflags" >> $config_host_mak echo "VIRGL_LIBS=$virgl_libs" >> $config_host_mak fi -if test "$xen" = "yes" ; then +if test "$xen" = "enabled" ; then echo "CONFIG_XEN_BACKEND=y" >> $config_host_mak echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version" >> $config_host_mak + echo "XEN_CFLAGS=$xen_cflags" >> $config_host_mak + echo "XEN_LIBS=$xen_libs" >> $config_host_mak fi if test "$linux_aio" = "yes" ; then echo "CONFIG_LINUX_AIO=y" >> $config_host_mak @@ -7166,6 +6255,7 @@ if test "$linux_io_uring" = "yes" ; then fi if test "$attr" = "yes" ; then echo "CONFIG_ATTR=y" >> $config_host_mak + echo "LIBATTR_LIBS=$libattr_libs" >> $config_host_mak fi if test "$libattr" = "yes" ; then echo "CONFIG_LIBATTR=y" >> $config_host_mak @@ -7173,12 +6263,6 @@ fi if test "$virtfs" = "yes" ; then echo "CONFIG_VIRTFS=y" >> $config_host_mak fi -if test "$mpath" = "yes" ; then - echo "CONFIG_MPATH=y" >> $config_host_mak - if test "$mpathpersist_new_api" = "yes"; then - echo "CONFIG_MPATH_NEW_API=y" >> $config_host_mak - fi -fi if test "$vhost_scsi" = "yes" ; then echo "CONFIG_VHOST_SCSI=y" >> $config_host_mak fi @@ -7188,11 +6272,17 @@ fi if test "$vhost_net_user" = "yes" ; then echo "CONFIG_VHOST_NET_USER=y" >> $config_host_mak fi +if test "$vhost_net_vdpa" = "yes" ; then + echo "CONFIG_VHOST_NET_VDPA=y" >> $config_host_mak +fi if test "$vhost_crypto" = "yes" ; then echo "CONFIG_VHOST_CRYPTO=y" >> $config_host_mak fi if test "$vhost_vsock" = "yes" ; then echo "CONFIG_VHOST_VSOCK=y" >> $config_host_mak + if test "$vhost_user" = "yes" ; then + echo "CONFIG_VHOST_USER_VSOCK=y" >> $config_host_mak + fi fi if test "$vhost_kernel" = "yes" ; then echo "CONFIG_VHOST_KERNEL=y" >> $config_host_mak @@ -7200,21 +6290,18 @@ fi if test "$vhost_user" = "yes" ; then echo "CONFIG_VHOST_USER=y" >> $config_host_mak fi +if test "$vhost_vdpa" = "yes" ; then + echo "CONFIG_VHOST_VDPA=y" >> $config_host_mak +fi if test "$vhost_user_fs" = "yes" ; then echo "CONFIG_VHOST_USER_FS=y" >> $config_host_mak fi -if test "$blobs" = "yes" ; then - echo "INSTALL_BLOBS=yes" >> $config_host_mak -fi if test "$iovec" = "yes" ; then echo "CONFIG_IOVEC=y" >> $config_host_mak fi if test "$preadv" = "yes" ; then echo "CONFIG_PREADV=y" >> $config_host_mak fi -if test "$fdt" != "no" ; then - echo "CONFIG_FDT=y" >> $config_host_mak -fi if test "$membarrier" = "yes" ; then echo "CONFIG_MEMBARRIER=y" >> $config_host_mak fi @@ -7224,8 +6311,7 @@ fi if test "$optreset" = "yes" ; then echo "HAVE_OPTRESET=y" >> $config_host_mak fi -if test "$tcg" = "yes"; then - echo "CONFIG_TCG=y" >> $config_host_mak +if test "$tcg" = "enabled"; then if test "$tcg_interpreter" = "yes" ; then echo "CONFIG_TCG_INTERPRETER=y" >> $config_host_mak fi @@ -7242,9 +6328,10 @@ fi if test "$posix_memalign" = "yes" ; then echo "CONFIG_POSIX_MEMALIGN=y" >> $config_host_mak fi - if test "$spice" = "yes" ; then echo "CONFIG_SPICE=y" >> $config_host_mak + echo "SPICE_CFLAGS=$spice_cflags" >> $config_host_mak + echo "SPICE_LIBS=$spice_libs" >> $config_host_mak fi if test "$smartcard" = "yes" ; then @@ -7267,6 +6354,7 @@ fi if test "$opengl" = "yes" ; then echo "CONFIG_OPENGL=y" >> $config_host_mak + echo "OPENGL_CFLAGS=$opengl_cflags" >> $config_host_mak echo "OPENGL_LIBS=$opengl_libs" >> $config_host_mak if test "$opengl_dmabuf" = "yes" ; then echo "CONFIG_OPENGL_DMABUF=y" >> $config_host_mak @@ -7280,10 +6368,6 @@ if test "$gbm" = "yes" ; then fi -if test "$malloc_trim" = "yes" ; then - echo "CONFIG_MALLOC_TRIM=y" >> $config_host_mak -fi - if test "$avx2_opt" = "yes" ; then echo "CONFIG_AVX2_OPT=y" >> $config_host_mak fi @@ -7294,10 +6378,12 @@ fi if test "$lzo" = "yes" ; then echo "CONFIG_LZO=y" >> $config_host_mak + echo "LZO_LIBS=$lzo_libs" >> $config_host_mak fi if test "$snappy" = "yes" ; then echo "CONFIG_SNAPPY=y" >> $config_host_mak + echo "SNAPPY_LIBS=$snappy_libs" >> $config_host_mak fi if test "$bzip2" = "yes" ; then @@ -7312,16 +6398,18 @@ fi if test "$zstd" = "yes" ; then echo "CONFIG_ZSTD=y" >> $config_host_mak + echo "ZSTD_CFLAGS=$zstd_cflags" >> $config_host_mak + echo "ZSTD_LIBS=$zstd_libs" >> $config_host_mak fi if test "$libiscsi" = "yes" ; then - echo "CONFIG_LIBISCSI=m" >> $config_host_mak + echo "CONFIG_LIBISCSI=y" >> $config_host_mak echo "LIBISCSI_CFLAGS=$libiscsi_cflags" >> $config_host_mak echo "LIBISCSI_LIBS=$libiscsi_libs" >> $config_host_mak fi if test "$libnfs" = "yes" ; then - echo "CONFIG_LIBNFS=m" >> $config_host_mak + echo "CONFIG_LIBNFS=y" >> $config_host_mak echo "LIBNFS_LIBS=$libnfs_libs" >> $config_host_mak fi @@ -7336,15 +6424,11 @@ if [ "$bsd" = "yes" ] ; then echo "CONFIG_BSD=y" >> $config_host_mak fi -if test "$localtime_r" = "yes" ; then - echo "CONFIG_LOCALTIME_R=y" >> $config_host_mak -fi if test "$qom_cast_debug" = "yes" ; then echo "CONFIG_QOM_CAST_DEBUG=y" >> $config_host_mak fi if test "$rbd" = "yes" ; then - echo "CONFIG_RBD=m" >> $config_host_mak - echo "RBD_CFLAGS=$rbd_cflags" >> $config_host_mak + echo "CONFIG_RBD=y" >> $config_host_mak echo "RBD_LIBS=$rbd_libs" >> $config_host_mak fi @@ -7371,10 +6455,6 @@ if test "$linux_magic_h" = "yes" ; then echo "CONFIG_LINUX_MAGIC_H=y" >> $config_host_mak fi -if test "$pragma_diagnostic_available" = "yes" ; then - echo "CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE=y" >> $config_host_mak -fi - if test "$valgrind_h" = "yes" ; then echo "CONFIG_VALGRIND_H=y" >> $config_host_mak fi @@ -7383,6 +6463,10 @@ if test "$have_asan_iface_fiber" = "yes" ; then echo "CONFIG_ASAN_IFACE_FIBER=y" >> $config_host_mak fi +if test "$have_tsan" = "yes" && test "$have_tsan_iface_fiber" = "yes" ; then + echo "CONFIG_TSAN=y" >> $config_host_mak +fi + if test "$has_environ" = "yes" ; then echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak fi @@ -7416,7 +6500,7 @@ if test "$getauxval" = "yes" ; then fi if test "$glusterfs" = "yes" ; then - echo "CONFIG_GLUSTERFS=m" >> $config_host_mak + echo "CONFIG_GLUSTERFS=y" >> $config_host_mak echo "GLUSTERFS_CFLAGS=$glusterfs_cflags" >> $config_host_mak echo "GLUSTERFS_LIBS=$glusterfs_libs" >> $config_host_mak fi @@ -7446,7 +6530,7 @@ if test "$glusterfs_iocb_has_stat" = "yes" ; then fi if test "$libssh" = "yes" ; then - echo "CONFIG_LIBSSH=m" >> $config_host_mak + echo "CONFIG_LIBSSH=y" >> $config_host_mak echo "LIBSSH_CFLAGS=$libssh_cflags" >> $config_host_mak echo "LIBSSH_LIBS=$libssh_libs" >> $config_host_mak fi @@ -7473,6 +6557,8 @@ if have_backend "log"; then fi if have_backend "ust"; then echo "CONFIG_TRACE_UST=y" >> $config_host_mak + echo "LTTNG_UST_LIBS=$lttng_ust_libs" >> $config_host_mak + echo "URCU_BP_LIBS=$urcu_bp_libs" >> $config_host_mak fi if have_backend "dtrace"; then echo "CONFIG_TRACE_DTRACE=y" >> $config_host_mak @@ -7540,9 +6626,6 @@ fi if test "$ivshmem" = "yes" ; then echo "CONFIG_IVSHMEM=y" >> $config_host_mak fi -if test "$capstone" != "no" ; then - echo "CONFIG_CAPSTONE=y" >> $config_host_mak -fi if test "$debug_mutex" = "yes" ; then echo "CONFIG_DEBUG_MUTEX=y" >> $config_host_mak fi @@ -7560,13 +6643,15 @@ elif test "$pthread_setname_np_wo_tid" = "yes" ; then echo "CONFIG_PTHREAD_SETNAME_NP_WO_TID=y" >> $config_host_mak fi -if test "$vxhs" = "yes" ; then - echo "CONFIG_VXHS=y" >> $config_host_mak - echo "VXHS_LIBS=$vxhs_libs" >> $config_host_mak -fi - if test "$libpmem" = "yes" ; then echo "CONFIG_LIBPMEM=y" >> $config_host_mak + echo "LIBPMEM_LIBS=$libpmem_libs" >> $config_host_mak + echo "LIBPMEM_CFLAGS=$libpmem_cflags" >> $config_host_mak +fi + +if test "$libdaxctl" = "yes" ; then + echo "CONFIG_LIBDAXCTL=y" >> $config_host_mak + echo "LIBDAXCTL_LIBS=$libdaxctl_libs" >> $config_host_mak fi if test "$bochs" = "yes" ; then @@ -7594,22 +6679,28 @@ if test "$parallels" = "yes" ; then echo "CONFIG_PARALLELS=y" >> $config_host_mak fi if test "$sheepdog" = "yes" ; then + add_to deprecated_features "sheepdog" echo "CONFIG_SHEEPDOG=y" >> $config_host_mak fi +if test "$pty_h" = "yes" ; then + echo "HAVE_PTY_H=y" >> $config_host_mak +fi +if test "$have_mlockall" = "yes" ; then + echo "HAVE_MLOCKALL=y" >> $config_host_mak +fi if test "$fuzzing" = "yes" ; then - if test "$have_fuzzer" = "yes"; then - FUZZ_LDFLAGS=" -fsanitize=address,fuzzer" - FUZZ_CFLAGS=" -fsanitize=address,fuzzer" - CFLAGS=" -fsanitize=address,fuzzer-no-link" + # If LIB_FUZZING_ENGINE is set, assume we are running on OSS-Fuzz, and the + # needed CFLAGS have already been provided + if test -z "${LIB_FUZZING_ENGINE+xxx}" ; then + QEMU_CFLAGS="$QEMU_CFLAGS -fsanitize=fuzzer-no-link" + FUZZ_EXE_LDFLAGS="-fsanitize=fuzzer" else - error_exit "Your compiler doesn't support -fsanitize=address,fuzzer" - exit 1 + FUZZ_EXE_LDFLAGS="$LIB_FUZZING_ENGINE" fi fi if test "$plugins" = "yes" ; then echo "CONFIG_PLUGIN=y" >> $config_host_mak - LIBS="-ldl $LIBS" # Copy the export object list to the build dir if test "$ld_dynamic_list" = "yes" ; then echo "CONFIG_HAS_LD_DYNAMIC_LIST=yes" >> $config_host_mak @@ -7632,39 +6723,20 @@ if test -n "$gdb_bin" ; then echo "HAVE_GDB_BIN=$gdb_bin" >> $config_host_mak fi -if test "$tcg_interpreter" = "yes"; then - QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/tci $QEMU_INCLUDES" -elif test "$ARCH" = "sparc64" ; then - QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/sparc $QEMU_INCLUDES" -elif test "$ARCH" = "s390x" ; then - QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/s390 $QEMU_INCLUDES" -elif test "$ARCH" = "x86_64" || test "$ARCH" = "x32" ; then - QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/i386 $QEMU_INCLUDES" -elif test "$ARCH" = "ppc64" ; then - QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/ppc $QEMU_INCLUDES" -elif test "$ARCH" = "riscv32" || test "$ARCH" = "riscv64" ; then - QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/riscv $QEMU_INCLUDES" -else - QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/\$(ARCH) $QEMU_INCLUDES" +if test "$secret_keyring" = "yes" ; then + echo "CONFIG_SECRET_KEYRING=y" >> $config_host_mak fi -echo "TOOLS=$tools" >> $config_host_mak echo "ROMS=$roms" >> $config_host_mak echo "MAKE=$make" >> $config_host_mak -echo "INSTALL=$install" >> $config_host_mak -echo "INSTALL_DIR=$install -d -m 0755" >> $config_host_mak -echo "INSTALL_DATA=$install -c -m 0644" >> $config_host_mak -echo "INSTALL_PROG=$install -c -m 0755" >> $config_host_mak -echo "INSTALL_LIB=$install -c -m 0644" >> $config_host_mak echo "PYTHON=$python" >> $config_host_mak -echo "SPHINX_BUILD=$sphinx_build" >> $config_host_mak -echo "SPHINX_WERROR=$sphinx_werror" >> $config_host_mak echo "GENISOIMAGE=$genisoimage" >> $config_host_mak +echo "MESON=$meson" >> $config_host_mak +echo "NINJA=$ninja" >> $config_host_mak echo "CC=$cc" >> $config_host_mak if $iasl -h > /dev/null 2>&1; then - echo "IASL=$iasl" >> $config_host_mak + echo "CONFIG_IASL=$iasl" >> $config_host_mak fi -echo "HOST_CC=$host_cc" >> $config_host_mak echo "CXX=$cxx" >> $config_host_mak echo "OBJCC=$objcc" >> $config_host_mak echo "AR=$ar" >> $config_host_mak @@ -7678,49 +6750,30 @@ echo "RANLIB=$ranlib" >> $config_host_mak echo "NM=$nm" >> $config_host_mak echo "PKG_CONFIG=$pkg_config_exe" >> $config_host_mak echo "WINDRES=$windres" >> $config_host_mak -echo "CFLAGS=$CFLAGS" >> $config_host_mak echo "CFLAGS_NOPIE=$CFLAGS_NOPIE" >> $config_host_mak echo "QEMU_CFLAGS=$QEMU_CFLAGS" >> $config_host_mak echo "QEMU_CXXFLAGS=$QEMU_CXXFLAGS" >> $config_host_mak -echo "QEMU_INCLUDES=$QEMU_INCLUDES" >> $config_host_mak -if test "$sparse" = "yes" ; then - echo "CC := REAL_CC=\"\$(CC)\" cgcc" >> $config_host_mak - echo "CPP := REAL_CC=\"\$(CPP)\" cgcc" >> $config_host_mak - echo "CXX := REAL_CC=\"\$(CXX)\" cgcc" >> $config_host_mak - echo "HOST_CC := REAL_CC=\"\$(HOST_CC)\" cgcc" >> $config_host_mak - echo "QEMU_CFLAGS += -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-non-pointer-null" >> $config_host_mak -fi +echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak +echo "GLIB_LIBS=$glib_libs" >> $config_host_mak echo "QEMU_LDFLAGS=$QEMU_LDFLAGS" >> $config_host_mak echo "LDFLAGS_NOPIE=$LDFLAGS_NOPIE" >> $config_host_mak -echo "LD_REL_FLAGS=$LD_REL_FLAGS" >> $config_host_mak echo "LD_I386_EMULATION=$ld_i386_emulation" >> $config_host_mak -echo "LIBS+=$LIBS" >> $config_host_mak -echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak -echo "PTHREAD_LIB=$PTHREAD_LIB" >> $config_host_mak echo "EXESUF=$EXESUF" >> $config_host_mak -echo "DSOSUF=$DSOSUF" >> $config_host_mak -echo "LDFLAGS_SHARED=$LDFLAGS_SHARED" >> $config_host_mak -echo "LIBS_QGA+=$libs_qga" >> $config_host_mak +echo "HOST_DSOSUF=$HOST_DSOSUF" >> $config_host_mak +echo "LIBS_QGA=$libs_qga" >> $config_host_mak echo "TASN1_LIBS=$tasn1_libs" >> $config_host_mak echo "TASN1_CFLAGS=$tasn1_cflags" >> $config_host_mak -echo "POD2MAN=$POD2MAN" >> $config_host_mak if test "$gcov" = "yes" ; then echo "CONFIG_GCOV=y" >> $config_host_mak - echo "GCOV=$gcov_tool" >> $config_host_mak fi -if test "$libudev" != "no"; then - echo "CONFIG_LIBUDEV=y" >> $config_host_mak - echo "LIBUDEV_LIBS=$libudev_libs" >> $config_host_mak -fi if test "$fuzzing" != "no"; then echo "CONFIG_FUZZ=y" >> $config_host_mak - echo "FUZZ_CFLAGS=$FUZZ_CFLAGS" >> $config_host_mak - echo "FUZZ_LDFLAGS=$FUZZ_LDFLAGS" >> $config_host_mak fi +echo "FUZZ_EXE_LDFLAGS=$FUZZ_EXE_LDFLAGS" >> $config_host_mak -if test "$edk2_blobs" = "yes" ; then - echo "DECOMPRESS_EDK2_BLOBS=y" >> $config_host_mak +if test "$rng_none" = "yes"; then + echo "CONFIG_RNG_NONE=y" >> $config_host_mak fi # use included Linux headers @@ -7754,448 +6807,33 @@ if test "$linux" = "yes" ; then fi for target in $target_list; do -target_dir="$target" -config_target_mak=$target_dir/config-target.mak -target_name=$(echo $target | cut -d '-' -f 1) -target_aligned_only="no" -case "$target_name" in - alpha|hppa|mips64el|mips64|mipsel|mips|mipsn32|mipsn32el|sh4|sh4eb|sparc|sparc64|sparc32plus|xtensa|xtensaeb) - target_aligned_only="yes" - ;; -esac -target_bigendian="no" -case "$target_name" in - armeb|aarch64_be|hppa|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or1k|ppc|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb) - target_bigendian="yes" - ;; -esac -target_softmmu="no" -target_user_only="no" -target_linux_user="no" -target_bsd_user="no" -case "$target" in - ${target_name}-softmmu) - target_softmmu="yes" - ;; - ${target_name}-linux-user) - target_user_only="yes" - target_linux_user="yes" - ;; - ${target_name}-bsd-user) - target_user_only="yes" - target_bsd_user="yes" - ;; - *) - error_exit "Target '$target' not recognised" - exit 1 - ;; -esac - -mkdir -p $target_dir -echo "# Automatically generated by configure - do not modify" > $config_target_mak - -bflt="no" -mttcg="no" -interp_prefix1=$(echo "$interp_prefix" | sed "s/%M/$target_name/g") -gdb_xml_files="" - -TARGET_ARCH="$target_name" -TARGET_BASE_ARCH="" -TARGET_ABI_DIR="" - -case "$target_name" in - i386) - mttcg="yes" - gdb_xml_files="i386-32bit.xml" - TARGET_SYSTBL_ABI=i386 - ;; - x86_64) - TARGET_BASE_ARCH=i386 - TARGET_SYSTBL_ABI=common,64 - mttcg="yes" - gdb_xml_files="i386-64bit.xml" - ;; - alpha) - mttcg="yes" - TARGET_SYSTBL_ABI=common - ;; - arm|armeb) - TARGET_ARCH=arm - TARGET_SYSTBL_ABI=common,oabi - bflt="yes" - mttcg="yes" - gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml arm-m-profile.xml" - ;; - aarch64|aarch64_be) - TARGET_ARCH=aarch64 - TARGET_BASE_ARCH=arm - bflt="yes" - mttcg="yes" - gdb_xml_files="aarch64-core.xml aarch64-fpu.xml arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml arm-m-profile.xml" - ;; - cris) - ;; - hppa) - mttcg="yes" - TARGET_SYSTBL_ABI=common,32 - ;; - lm32) - ;; - m68k) - bflt="yes" - gdb_xml_files="cf-core.xml cf-fp.xml m68k-core.xml m68k-fp.xml" - TARGET_SYSTBL_ABI=common - ;; - microblaze|microblazeel) - TARGET_ARCH=microblaze - TARGET_SYSTBL_ABI=common - bflt="yes" - echo "TARGET_ABI32=y" >> $config_target_mak - ;; - mips|mipsel) - mttcg="yes" - TARGET_ARCH=mips - echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak - TARGET_SYSTBL_ABI=o32 - ;; - mipsn32|mipsn32el) - mttcg="yes" - TARGET_ARCH=mips64 - TARGET_BASE_ARCH=mips - echo "TARGET_ABI_MIPSN32=y" >> $config_target_mak - echo "TARGET_ABI32=y" >> $config_target_mak - TARGET_SYSTBL_ABI=n32 - ;; - mips64|mips64el) - mttcg="no" - TARGET_ARCH=mips64 - TARGET_BASE_ARCH=mips - echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak - TARGET_SYSTBL_ABI=n64 - ;; - moxie) - ;; - nios2) - ;; - or1k) - TARGET_ARCH=openrisc - TARGET_BASE_ARCH=openrisc - ;; - ppc) - gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml" - TARGET_SYSTBL_ABI=common,nospu,32 - ;; - ppc64) - TARGET_BASE_ARCH=ppc - TARGET_ABI_DIR=ppc - TARGET_SYSTBL_ABI=common,nospu,64 - mttcg=yes - gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml" - ;; - ppc64le) - TARGET_ARCH=ppc64 - TARGET_BASE_ARCH=ppc - TARGET_ABI_DIR=ppc - TARGET_SYSTBL_ABI=common,nospu,64 - mttcg=yes - gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml" - ;; - ppc64abi32) - TARGET_ARCH=ppc64 - TARGET_BASE_ARCH=ppc - TARGET_ABI_DIR=ppc - TARGET_SYSTBL_ABI=common,nospu,32 - echo "TARGET_ABI32=y" >> $config_target_mak - gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml" - ;; - riscv32) - TARGET_BASE_ARCH=riscv - TARGET_ABI_DIR=riscv - mttcg=yes - gdb_xml_files="riscv-32bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-32bit-csr.xml riscv-32bit-virtual.xml" - ;; - riscv64) - TARGET_BASE_ARCH=riscv - TARGET_ABI_DIR=riscv - mttcg=yes - gdb_xml_files="riscv-64bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-64bit-csr.xml riscv-64bit-virtual.xml" - ;; - rx) - TARGET_ARCH=rx - bflt="yes" - target_compiler=$cross_cc_rx - gdb_xml_files="rx-core.xml" - ;; - sh4|sh4eb) - TARGET_ARCH=sh4 - TARGET_SYSTBL_ABI=common - bflt="yes" - ;; - sparc) - TARGET_SYSTBL_ABI=common,32 - ;; - sparc64) - TARGET_BASE_ARCH=sparc - TARGET_SYSTBL_ABI=common,64 - ;; - sparc32plus) - TARGET_ARCH=sparc64 - TARGET_BASE_ARCH=sparc - TARGET_ABI_DIR=sparc - TARGET_SYSTBL_ABI=common,32 - echo "TARGET_ABI32=y" >> $config_target_mak - ;; - s390x) - TARGET_SYSTBL_ABI=common,64 - mttcg=yes - gdb_xml_files="s390x-core64.xml s390-acr.xml s390-fpr.xml s390-vx.xml s390-cr.xml s390-virt.xml s390-gs.xml" - ;; - tilegx) - ;; - tricore) - ;; - unicore32) - ;; - xtensa|xtensaeb) - TARGET_ARCH=xtensa - TARGET_SYSTBL_ABI=common - bflt="yes" - mttcg="yes" - ;; - *) - error_exit "Unsupported target CPU" - ;; -esac -# TARGET_BASE_ARCH needs to be defined after TARGET_ARCH -if [ "$TARGET_BASE_ARCH" = "" ]; then - TARGET_BASE_ARCH=$TARGET_ARCH -fi - -symlink "$source_path/Makefile.target" "$target_dir/Makefile" - -upper() { - echo "$@"| LC_ALL=C tr '[a-z]' '[A-Z]' -} - -target_arch_name="$(upper $TARGET_ARCH)" -echo "TARGET_$target_arch_name=y" >> $config_target_mak -echo "TARGET_NAME=$target_name" >> $config_target_mak -echo "TARGET_BASE_ARCH=$TARGET_BASE_ARCH" >> $config_target_mak -if [ "$TARGET_ABI_DIR" = "" ]; then - TARGET_ABI_DIR=$TARGET_ARCH -fi -echo "TARGET_ABI_DIR=$TARGET_ABI_DIR" >> $config_target_mak -if [ "$HOST_VARIANT_DIR" != "" ]; then - echo "HOST_VARIANT_DIR=$HOST_VARIANT_DIR" >> $config_target_mak -fi -if [ "$TARGET_SYSTBL_ABI" != "" ]; then - echo "TARGET_SYSTBL_ABI=$TARGET_SYSTBL_ABI" >> $config_target_mak -fi - -if supported_xen_target $target; then - echo "CONFIG_XEN=y" >> $config_target_mak - echo "$target/config-devices.mak: CONFIG_XEN=y" >> $config_host_mak - if test "$xen_pci_passthrough" = yes; then - echo "CONFIG_XEN_PCI_PASSTHROUGH=y" >> "$config_target_mak" - fi -else - echo "$target/config-devices.mak: CONFIG_XEN=n" >> $config_host_mak -fi -if supported_kvm_target $target; then - echo "CONFIG_KVM=y" >> $config_target_mak - echo "$target/config-devices.mak: CONFIG_KVM=y" >> $config_host_mak -else - echo "$target/config-devices.mak: CONFIG_KVM=n" >> $config_host_mak -fi -if supported_hax_target $target; then - echo "CONFIG_HAX=y" >> $config_target_mak -fi -if supported_hvf_target $target; then - echo "CONFIG_HVF=y" >> $config_target_mak -fi -if supported_whpx_target $target; then - echo "CONFIG_WHPX=y" >> $config_target_mak -fi -if test "$target_aligned_only" = "yes" ; then - echo "TARGET_ALIGNED_ONLY=y" >> $config_target_mak -fi -if test "$target_bigendian" = "yes" ; then - echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak -fi -if test "$target_softmmu" = "yes" ; then - echo "CONFIG_SOFTMMU=y" >> $config_target_mak - if test "$mttcg" = "yes" ; then - echo "TARGET_SUPPORTS_MTTCG=y" >> $config_target_mak - fi -fi -if test "$target_user_only" = "yes" ; then - echo "CONFIG_USER_ONLY=y" >> $config_target_mak - echo "CONFIG_QEMU_INTERP_PREFIX=\"$interp_prefix1\"" >> $config_target_mak -fi -if test "$target_linux_user" = "yes" ; then - echo "CONFIG_LINUX_USER=y" >> $config_target_mak -fi -list="" -if test ! -z "$gdb_xml_files" ; then - for x in $gdb_xml_files; do - list="$list $source_path/gdb-xml/$x" - done - echo "TARGET_XML_FILES=$list" >> $config_target_mak -fi - -if test "$target_user_only" = "yes" && test "$bflt" = "yes"; then - echo "TARGET_HAS_BFLT=y" >> $config_target_mak -fi -if test "$target_bsd_user" = "yes" ; then - echo "CONFIG_BSD_USER=y" >> $config_target_mak -fi - - -# generate QEMU_CFLAGS/QEMU_LDFLAGS for targets - -cflags="" -ldflags="" - -disas_config() { - echo "CONFIG_${1}_DIS=y" >> $config_target_mak - echo "CONFIG_${1}_DIS=y" >> config-all-disas.mak -} - -for i in $ARCH $TARGET_BASE_ARCH ; do - case "$i" in - alpha) - disas_config "ALPHA" - ;; - aarch64) - if test -n "${cxx}"; then - disas_config "ARM_A64" - fi - ;; - arm) - disas_config "ARM" - if test -n "${cxx}"; then - disas_config "ARM_A64" - fi - ;; - cris) - disas_config "CRIS" - ;; - hppa) - disas_config "HPPA" - ;; - i386|x86_64|x32) - disas_config "I386" - ;; - lm32) - disas_config "LM32" - ;; - m68k) - disas_config "M68K" - ;; - microblaze*) - disas_config "MICROBLAZE" - ;; - mips*) - disas_config "MIPS" - if test -n "${cxx}"; then - disas_config "NANOMIPS" - fi - ;; - moxie*) - disas_config "MOXIE" - ;; - nios2) - disas_config "NIOS2" - ;; - or1k) - disas_config "OPENRISC" - ;; - ppc*) - disas_config "PPC" - ;; - riscv*) - disas_config "RISCV" - ;; - rx) - disas_config "RX" - ;; - s390*) - disas_config "S390" - ;; - sh4) - disas_config "SH4" - ;; - sparc*) - disas_config "SPARC" - ;; - xtensa*) - disas_config "XTENSA" - ;; - esac + target_dir="$target" + target_name=$(echo $target | cut -d '-' -f 1) + mkdir -p $target_dir + case $target in + *-user) symlink "../qemu-$target_name" "$target_dir/qemu-$target_name" ;; + *) symlink "../qemu-system-$target_name" "$target_dir/qemu-system-$target_name" ;; + esac done -if test "$tcg_interpreter" = "yes" ; then - disas_config "TCI" -fi - -case "$ARCH" in -alpha) - # Ensure there's only a single GP - cflags="-msmall-data $cflags" -;; -esac -if test "$gprof" = "yes" ; then - if test "$target_linux_user" = "yes" ; then - cflags="-p $cflags" - ldflags="-p $ldflags" - fi - if test "$target_softmmu" = "yes" ; then - ldflags="-p $ldflags" - echo "GPROF_CFLAGS=-p" >> $config_target_mak - fi -fi - -# Newer kernels on s390 check for an S390_PGSTE program header and -# enable the pgste page table extensions in that case. This makes -# the vm.allocate_pgste sysctl unnecessary. We enable this program -# header if -# - we build on s390x -# - we build the system emulation for s390x (qemu-system-s390x) -# - KVM is enabled -# - the linker supports --s390-pgste -if test "$TARGET_ARCH" = "s390x" && test "$target_softmmu" = "yes" && \ - test "$ARCH" = "s390x" && test "$kvm" = "yes"; then - if ld_has --s390-pgste ; then - ldflags="-Wl,--s390-pgste $ldflags" - fi -fi - -echo "QEMU_LDFLAGS+=$ldflags" >> $config_target_mak -echo "QEMU_CFLAGS+=$cflags" >> $config_target_mak - -done # for target in $targets - -echo "PIXMAN_CFLAGS=$pixman_cflags" >> $config_host_mak -echo "PIXMAN_LIBS=$pixman_libs" >> $config_host_mak - -if [ "$fdt" = "git" ]; then - echo "config-host.h: dtc/all" >> $config_host_mak -fi -if [ "$capstone" = "git" -o "$capstone" = "internal" ]; then - echo "config-host.h: capstone/all" >> $config_host_mak -fi -if test -n "$LIBCAPSTONE"; then - echo "LIBCAPSTONE=$LIBCAPSTONE" >> $config_host_mak +echo "CONFIG_QEMU_INTERP_PREFIX=$interp_prefix" | sed 's/%M/@0@/' >> $config_host_mak +if test "$default_targets" = "yes"; then + echo "CONFIG_DEFAULT_TARGETS=y" >> $config_host_mak fi if test "$numa" = "yes"; then echo "CONFIG_NUMA=y" >> $config_host_mak + echo "NUMA_LIBS=$numa_libs" >> $config_host_mak fi if test "$ccache_cpp2" = "yes"; then echo "export CCACHE_CPP2=y" >> $config_host_mak fi +if test "$safe_stack" = "yes"; then + echo "CONFIG_SAFESTACK=y" >> $config_host_mak +fi + # If we're using a separate build tree, set it up now. # DIRS are directories which we simply mkdir in the build tree; # LINKS are things to symlink back into the source tree @@ -8206,25 +6844,31 @@ fi # so the build tree will be missing the link back to the new file, and # tests might fail. Prefer to keep the relevant files in their own # directory and symlink the directory instead. +# UNLINK is used to remove symlinks from older development versions +# that might get into the way when doing "git update" without doing +# a "make distclean" in between. DIRS="tests tests/tcg tests/tcg/lm32 tests/qapi-schema tests/qtest/libqos" DIRS="$DIRS tests/qtest tests/qemu-iotests tests/vm tests/fp tests/qgraph" DIRS="$DIRS docs docs/interop fsdev scsi" DIRS="$DIRS pc-bios/optionrom pc-bios/s390-ccw" -DIRS="$DIRS roms/seabios roms/vgabios" +DIRS="$DIRS roms/seabios" +DIRS="$DIRS contrib/plugins/" LINKS="Makefile" -LINKS="$LINKS tests/tcg/lm32/Makefile po/Makefile" -LINKS="$LINKS tests/tcg/Makefile.target tests/fp/Makefile" -LINKS="$LINKS tests/plugin/Makefile" -LINKS="$LINKS pc-bios/optionrom/Makefile pc-bios/keymaps" +LINKS="$LINKS tests/tcg/lm32/Makefile" +LINKS="$LINKS tests/tcg/Makefile.target" +LINKS="$LINKS pc-bios/optionrom/Makefile" LINKS="$LINKS pc-bios/s390-ccw/Makefile" -LINKS="$LINKS roms/seabios/Makefile roms/vgabios/Makefile" +LINKS="$LINKS roms/seabios/Makefile" LINKS="$LINKS pc-bios/qemu-icon.bmp" LINKS="$LINKS .gdbinit scripts" # scripts needed by relative path in .gdbinit LINKS="$LINKS tests/acceptance tests/data" LINKS="$LINKS tests/qemu-iotests/check" LINKS="$LINKS python" +LINKS="$LINKS contrib/plugins/Makefile " +UNLINK="pc-bios/keymaps" for bios_file in \ $source_path/pc-bios/*.bin \ + $source_path/pc-bios/*.elf \ $source_path/pc-bios/*.lid \ $source_path/pc-bios/*.rom \ $source_path/pc-bios/*.dtb \ @@ -8238,10 +6882,15 @@ do done mkdir -p $DIRS for f in $LINKS ; do - if [ -e "$source_path/$f" ] && [ "$pwd_is_source_path" != "y" ]; then + if [ -e "$source_path/$f" ]; then symlink "$source_path/$f" "$f" fi done +for f in $UNLINK ; do + if [ -L "$f" ]; then + rm -f "$f" + fi +done (for i in $cross_cc_vars; do export $i @@ -8250,7 +6899,7 @@ export target_list source_path use_containers $source_path/tests/tcg/configure.sh) # temporary config to build submodules -for rom in seabios vgabios ; do +for rom in seabios; do config_mak=roms/$rom/config.mak echo "# Automatically generated by configure - do not modify" > $config_mak echo "SRC_PATH=$source_path/roms/$rom" >> $config_mak @@ -8272,6 +6921,113 @@ echo "# Automatically generated by configure - do not modify" > "$iotests_common echo >> "$iotests_common_env" echo "export PYTHON='$python'" >> "$iotests_common_env" +if test "$skip_meson" = no; then +cross="config-meson.cross.new" +meson_quote() { + echo "'$(echo $* | sed "s/ /','/g")'" +} + +echo "# Automatically generated by configure - do not modify" > $cross +echo "[properties]" >> $cross +test -z "$cxx" && echo "link_language = 'c'" >> $cross +echo "[built-in options]" >> $cross +echo "c_args = [${CFLAGS:+$(meson_quote $CFLAGS)}]" >> $cross +echo "cpp_args = [${CXXFLAGS:+$(meson_quote $CXXFLAGS)}]" >> $cross +echo "c_link_args = [${LDFLAGS:+$(meson_quote $LDFLAGS)}]" >> $cross +echo "cpp_link_args = [${LDFLAGS:+$(meson_quote $LDFLAGS)}]" >> $cross +echo "[binaries]" >> $cross +echo "c = [$(meson_quote $cc)]" >> $cross +test -n "$cxx" && echo "cpp = [$(meson_quote $cxx)]" >> $cross +echo "ar = [$(meson_quote $ar)]" >> $cross +echo "nm = [$(meson_quote $nm)]" >> $cross +echo "pkgconfig = [$(meson_quote $pkg_config_exe)]" >> $cross +echo "ranlib = [$(meson_quote $ranlib)]" >> $cross +if has $sdl2_config; then + echo "sdl2-config = [$(meson_quote $sdl2_config)]" >> $cross +fi +echo "strip = [$(meson_quote $strip)]" >> $cross +echo "windres = [$(meson_quote $windres)]" >> $cross +if test -n "$cross_prefix"; then + cross_arg="--cross-file config-meson.cross" + echo "[host_machine]" >> $cross + if test "$mingw32" = "yes" ; then + echo "system = 'windows'" >> $cross + fi + if test "$linux" = "yes" ; then + echo "system = 'linux'" >> $cross + fi + case "$ARCH" in + i386|x86_64) + echo "cpu_family = 'x86'" >> $cross + ;; + ppc64le) + echo "cpu_family = 'ppc64'" >> $cross + ;; + *) + echo "cpu_family = '$ARCH'" >> $cross + ;; + esac + echo "cpu = '$cpu'" >> $cross + if test "$bigendian" = "yes" ; then + echo "endian = 'big'" >> $cross + else + echo "endian = 'little'" >> $cross + fi +else + cross_arg="--native-file config-meson.cross" +fi +mv $cross config-meson.cross + +rm -rf meson-private meson-info meson-logs +unset staticpic +if ! version_ge "$($meson --version)" 0.56.0; then + staticpic=$(if test "$pie" = yes; then echo true; else echo false; fi) +fi +NINJA=$ninja $meson setup \ + --prefix "$prefix" \ + --libdir "$libdir" \ + --libexecdir "$libexecdir" \ + --bindir "$bindir" \ + --includedir "$includedir" \ + --datadir "$datadir" \ + --mandir "$mandir" \ + --sysconfdir "$sysconfdir" \ + --localedir "$localedir" \ + --localstatedir "$local_statedir" \ + -Ddocdir="$docdir" \ + -Dqemu_firmwarepath="$firmwarepath" \ + -Dqemu_suffix="$qemu_suffix" \ + -Doptimization=$(if test "$debug" = yes; then echo 0; else echo 2; fi) \ + -Ddebug=$(if test "$debug_info" = yes; then echo true; else echo false; fi) \ + -Dwerror=$(if test "$werror" = yes; then echo true; else echo false; fi) \ + -Dstrip=$(if test "$strip_opt" = yes; then echo true; else echo false; fi) \ + -Db_pie=$(if test "$pie" = yes; then echo true; else echo false; fi) \ + ${staticpic:+-Db_staticpic=$staticpic} \ + -Db_coverage=$(if test "$gcov" = yes; then echo true; else echo false; fi) \ + -Dmalloc=$malloc -Dmalloc_trim=$malloc_trim -Dsparse=$sparse \ + -Dkvm=$kvm -Dhax=$hax -Dwhpx=$whpx -Dhvf=$hvf \ + -Dxen=$xen -Dxen_pci_passthrough=$xen_pci_passthrough -Dtcg=$tcg \ + -Dcocoa=$cocoa -Dmpath=$mpath -Dsdl=$sdl -Dsdl_image=$sdl_image \ + -Dvnc=$vnc -Dvnc_sasl=$vnc_sasl -Dvnc_jpeg=$vnc_jpeg -Dvnc_png=$vnc_png \ + -Dgettext=$gettext -Dxkbcommon=$xkbcommon -Du2f=$u2f -Dvirtiofsd=$virtiofsd \ + -Dcapstone=$capstone -Dslirp=$slirp -Dfdt=$fdt \ + -Diconv=$iconv -Dcurses=$curses -Dlibudev=$libudev\ + -Ddocs=$docs -Dsphinx_build=$sphinx_build -Dinstall_blobs=$blobs \ + -Dvhost_user_blk_server=$vhost_user_blk_server \ + $cross_arg \ + "$PWD" "$source_path" + +if test "$?" -ne 0 ; then + error_exit "meson setup failed" +fi +fi + +if test -n "${deprecated_features}"; then + echo "Warning, deprecated features enabled." + echo "Please see docs/system/deprecated.rst" + echo " features: ${deprecated_features}" +fi + # Save the configure command line for later reuse. cat <config.status #!/bin/sh @@ -8320,7 +7076,9 @@ preserve_env STRIP preserve_env WINDRES printf "exec" >>config.status -printf " '%s'" "$0" "$@" >>config.status +for i in "$0" "$@"; do + test "$i" = --skip-meson || printf " '%s'" "$i" >>config.status +done echo ' "$@"' >>config.status chmod +x config.status diff --git a/contrib/elf2dmp/Makefile.objs b/contrib/elf2dmp/Makefile.objs deleted file mode 100644 index 1505716916067c044760b89f3da3a768578dd724..0000000000000000000000000000000000000000 --- a/contrib/elf2dmp/Makefile.objs +++ /dev/null @@ -1,4 +0,0 @@ -elf2dmp-obj-y = main.o addrspace.o download.o pdb.o qemu_elf.o - -download.o-cflags := $(CURL_CFLAGS) -download.o-libs := $(CURL_LIBS) diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c index 9a2dbc290214bc56fa02b077f3afdaed8216fc54..ac746e49e097c2e11f5a9c1eb715ed91d00deb8f 100644 --- a/contrib/elf2dmp/main.c +++ b/contrib/elf2dmp/main.c @@ -568,12 +568,12 @@ int main(int argc, char *argv[]) if (fill_header(&header, &ps, &vs, KdDebuggerDataBlock, kdbg, KdVersionBlock, qemu_elf.state_nr)) { err = 1; - goto out_pdb; + goto out_kdbg; } if (fill_context(kdbg, &vs, &qemu_elf)) { err = 1; - goto out_pdb; + goto out_kdbg; } if (write_dump(&ps, &header, argv[2])) { diff --git a/contrib/elf2dmp/meson.build b/contrib/elf2dmp/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..b3de173316a3542e58e700bec72039b60d7d0330 --- /dev/null +++ b/contrib/elf2dmp/meson.build @@ -0,0 +1,5 @@ +if 'CONFIG_CURL' in config_host + executable('elf2dmp', files('main.c', 'addrspace.c', 'download.c', 'pdb.c', 'qemu_elf.c'), + dependencies: [glib, curl], + install: true) +endif diff --git a/contrib/gitdm/domain-map b/contrib/gitdm/domain-map index dd79147c769787565d7320e88daab2f978f2434a..0074da618f5d44c3e5a5b579f0f2069a8c124543 100644 --- a/contrib/gitdm/domain-map +++ b/contrib/gitdm/domain-map @@ -5,10 +5,13 @@ # amd.com AMD +baidu.com Baidu +bytedance.com ByteDance cmss.chinamobile.com China Mobile citrix.com Citrix -greensocs.com GreenSocs fujitsu.com Fujitsu +google.com Google +greensocs.com GreenSocs huawei.com Huawei ibm.com IBM igalia.com Igalia @@ -16,13 +19,18 @@ intel.com Intel linaro.org Linaro microsoft.com Microsoft nokia.com Nokia +nuviainc.com NUVIA oracle.com Oracle proxmox.com Proxmox +quicinc.com Qualcomm Innovation Center redhat.com Red Hat rt-rk.com RT-RK siemens.com Siemens sifive.com SiFive +suse.com SUSE suse.de SUSE virtuozzo.com Virtuozzo wdc.com Western Digital xilinx.com Xilinx +yadro.com YADRO +yandex-team.ru Yandex diff --git a/contrib/gitdm/filetypes.txt b/contrib/gitdm/filetypes.txt index 2d5002fea0c926fb4f10e5ef3401528272f635ee..d2d6f6db8d5e7ba991bee380bf8f0e5e995ae5da 100644 --- a/contrib/gitdm/filetypes.txt +++ b/contrib/gitdm/filetypes.txt @@ -22,7 +22,7 @@ # in the gitdm sample-config directory. # # This file contains associations parameters regarding filetypes -# (documentation, develompent, multimedia, images...) +# (documentation, development, multimedia, images...) # # format: # filetype [] @@ -42,7 +42,7 @@ order build,interface,tests,code,documentation,devel-doc,blobs # (most common languages first # filetype code \.c$ # C -filetype code \.inc.c$ # C +filetype code \.c.inc$ # C filetype code \.C$ # C++ filetype code \.cpp$ # C++ filetype code \.c\+\+$ # C++ @@ -59,8 +59,8 @@ filetype code \.s$ # Assembly filetype code \.S$ # Assembly filetype code \.asm$ # Assembly filetype code \.awk$ # awk -filetype code ^common$ # script fragements -filetype code ^common.*$ # script fragements +filetype code ^common$ # script fragments +filetype code ^common.*$ # script fragments filetype code (qom|qmp)-\w+$ # python script fragments # diff --git a/contrib/gitdm/group-map-academics b/contrib/gitdm/group-map-academics index 08f9d81d13e7be642eb2d0bc288b785731379cdb..bf3c894821b8cfdd0d2262c63a04955a6fcf91d9 100644 --- a/contrib/gitdm/group-map-academics +++ b/contrib/gitdm/group-map-academics @@ -12,3 +12,7 @@ ispras.ru # Columbia University cs.columbia.edu cota@braap.org + +uni-paderborn.de +edu +edu.cn diff --git a/contrib/gitdm/group-map-individuals b/contrib/gitdm/group-map-individuals index cf8a2ce3671b108c6cbefaff26b861282e545f7d..36bbb77c39a1cc09a07e1c09705bba228014bf99 100644 --- a/contrib/gitdm/group-map-individuals +++ b/contrib/gitdm/group-map-individuals @@ -16,3 +16,16 @@ aurelien@aurel32.net balaton@eik.bme.hu e.emanuelegiuseppe@gmail.com andrew.smirnov@gmail.com +sw@weilnetz.de +deller@gmx.de +fthain@telegraphics.com.au +vr_qemu@t-online.de +nieklinnenbank@gmail.com +devnexen@gmail.com +pauldzim@gmail.com +ani@anisinha.ca +sundeep.lkml@gmail.com +mrolnik@gmail.com +huth@tuxfamily.org +jhogan@kernel.org +atar4qemu@gmail.com diff --git a/contrib/gitdm/group-map-redhat b/contrib/gitdm/group-map-redhat index d15db2d35e166ca963ea6e72611b323273b4a983..02507b7b53345e1caf90c39ed9e42f79b818d33f 100644 --- a/contrib/gitdm/group-map-redhat +++ b/contrib/gitdm/group-map-redhat @@ -6,3 +6,4 @@ david@gibson.dropbear.id.au laurent@vivier.eu pjp@fedoraproject.org armbru@pond.sub.org +nirsof@gmail.com diff --git a/contrib/ivshmem-client/Makefile.objs b/contrib/ivshmem-client/Makefile.objs deleted file mode 100644 index bfab2d20dd53f92da3b1e913035afe3886410a89..0000000000000000000000000000000000000000 --- a/contrib/ivshmem-client/Makefile.objs +++ /dev/null @@ -1 +0,0 @@ -ivshmem-client-obj-y = ivshmem-client.o main.o diff --git a/contrib/ivshmem-client/ivshmem-client.h b/contrib/ivshmem-client/ivshmem-client.h index fe3cc4a03d3358a1b256c3ef944d9c50fabd602c..fc45a38060f03ab9d71a519aa8ac06a142c5cb47 100644 --- a/contrib/ivshmem-client/ivshmem-client.h +++ b/contrib/ivshmem-client/ivshmem-client.h @@ -174,7 +174,7 @@ int ivshmem_client_notify_all_vects(const IvshmemClient *client, const IvshmemClientPeer *peer); /** - * Broadcat a notification to all vectors of all peers + * Broadcast a notification to all vectors of all peers * * @client: The ivshmem client * diff --git a/contrib/ivshmem-client/meson.build b/contrib/ivshmem-client/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..1b171efb4f536f608191cd4cba1bd11cc4bbb280 --- /dev/null +++ b/contrib/ivshmem-client/meson.build @@ -0,0 +1,4 @@ +executable('ivshmem-client', files('ivshmem-client.c', 'main.c'), + dependencies: glib, + build_by_default: targetos == 'linux', + install: false) diff --git a/contrib/ivshmem-server/Makefile.objs b/contrib/ivshmem-server/Makefile.objs deleted file mode 100644 index c060dd36983cb33561b5ab993db4eae284fc0c52..0000000000000000000000000000000000000000 --- a/contrib/ivshmem-server/Makefile.objs +++ /dev/null @@ -1 +0,0 @@ -ivshmem-server-obj-y = ivshmem-server.o main.o diff --git a/contrib/ivshmem-server/main.c b/contrib/ivshmem-server/main.c index e4cd35f74c61b638648fdefb17cbaac1a152c4ed..ee08c4ced0bd9a4e02b64b2df28ee2dd4c8ab4f5 100644 --- a/contrib/ivshmem-server/main.c +++ b/contrib/ivshmem-server/main.c @@ -103,8 +103,8 @@ ivshmem_server_parse_args(IvshmemServerArgs *args, int argc, char *argv[]) break; case 'l': /* shm size */ - parse_option_size("shm_size", optarg, &args->shm_size, &err); - if (err) { + if (!parse_option_size("shm_size", optarg, &args->shm_size, + &err)) { error_report_err(err); ivshmem_server_help(argv[0]); exit(1); diff --git a/contrib/ivshmem-server/meson.build b/contrib/ivshmem-server/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..3a539422017e6dc342e098c3e9c8dde4be97c563 --- /dev/null +++ b/contrib/ivshmem-server/meson.build @@ -0,0 +1,4 @@ +executable('ivshmem-server', files('ivshmem-server.c', 'main.c'), + dependencies: [qemuutil, rt], + build_by_default: targetos == 'linux', + install: false) diff --git a/contrib/libvhost-user/Makefile.objs b/contrib/libvhost-user/Makefile.objs deleted file mode 100644 index ef3778edd42feb700e1b0bb82ca30fe70b61d5ec..0000000000000000000000000000000000000000 --- a/contrib/libvhost-user/Makefile.objs +++ /dev/null @@ -1 +0,0 @@ -libvhost-user-obj-y += libvhost-user.o libvhost-user-glib.o diff --git a/contrib/libvhost-user/libvhost-user-glib.c b/contrib/libvhost-user/libvhost-user-glib.c index 53f1ca4cdd7395b7f65617d733ba04b43aeb3902..0df2ec927135c6e7ab70d02515ebdf3eea4fe22d 100644 --- a/contrib/libvhost-user/libvhost-user-glib.c +++ b/contrib/libvhost-user/libvhost-user-glib.c @@ -147,7 +147,7 @@ vug_init(VugDev *dev, uint16_t max_queues, int socket, g_assert(dev); g_assert(iface); - if (!vu_init(&dev->parent, max_queues, socket, panic, set_watch, + if (!vu_init(&dev->parent, max_queues, socket, panic, NULL, set_watch, remove_watch, iface)) { return false; } diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost-user.c index 3bca996c6289c8f37efd67e919cc1b0464723fe1..5c73ffdd6b4589b07c13593d070bcfd5d6dd48c4 100644 --- a/contrib/libvhost-user/libvhost-user.c +++ b/contrib/libvhost-user/libvhost-user.c @@ -42,6 +42,7 @@ #include "qemu/atomic.h" #include "qemu/osdep.h" +#include "qemu/bswap.h" #include "qemu/memfd.h" #include "libvhost-user.h" @@ -67,8 +68,6 @@ /* The version of inflight buffer */ #define INFLIGHT_VERSION 1 -#define VHOST_USER_HDR_SIZE offsetof(VhostUserMsg, payload.u64) - /* The version of the protocol we support */ #define VHOST_USER_VERSION 1 #define LIBVHOST_USER_DEBUG 0 @@ -137,6 +136,9 @@ vu_request_to_string(unsigned int req) REQ(VHOST_USER_SET_INFLIGHT_FD), REQ(VHOST_USER_GPU_SET_SOCKET), REQ(VHOST_USER_VRING_KICK), + REQ(VHOST_USER_GET_MAX_MEM_SLOTS), + REQ(VHOST_USER_ADD_MEM_REG), + REQ(VHOST_USER_REM_MEM_REG), REQ(VHOST_USER_MAX), }; #undef REQ @@ -264,9 +266,9 @@ have_userfault(void) } static bool -vu_message_read(VuDev *dev, int conn_fd, VhostUserMsg *vmsg) +vu_message_read_default(VuDev *dev, int conn_fd, VhostUserMsg *vmsg) { - char control[CMSG_SPACE(VHOST_MEMORY_MAX_NREGIONS * sizeof(int))] = { }; + char control[CMSG_SPACE(VHOST_MEMORY_BASELINE_NREGIONS * sizeof(int))] = {}; struct iovec iov = { .iov_base = (char *)vmsg, .iov_len = VHOST_USER_HDR_SIZE, @@ -337,7 +339,7 @@ vu_message_write(VuDev *dev, int conn_fd, VhostUserMsg *vmsg) { int rc; uint8_t *p = (uint8_t *)vmsg; - char control[CMSG_SPACE(VHOST_MEMORY_MAX_NREGIONS * sizeof(int))] = { }; + char control[CMSG_SPACE(VHOST_MEMORY_BASELINE_NREGIONS * sizeof(int))] = {}; struct iovec iov = { .iov_base = (char *)vmsg, .iov_len = VHOST_USER_HDR_SIZE, @@ -350,7 +352,7 @@ vu_message_write(VuDev *dev, int conn_fd, VhostUserMsg *vmsg) struct cmsghdr *cmsg; memset(control, 0, sizeof(control)); - assert(vmsg->fd_num <= VHOST_MEMORY_MAX_NREGIONS); + assert(vmsg->fd_num <= VHOST_MEMORY_BASELINE_NREGIONS); if (vmsg->fd_num > 0) { size_t fdsize = vmsg->fd_num * sizeof(int); msg.msg_controllen = CMSG_SPACE(fdsize); @@ -412,7 +414,7 @@ vu_process_message_reply(VuDev *dev, const VhostUserMsg *vmsg) goto out; } - if (!vu_message_read(dev, dev->slave_fd, &msg_reply)) { + if (!vu_message_read_default(dev, dev->slave_fd, &msg_reply)) { goto out; } @@ -445,7 +447,7 @@ static void vu_log_page(uint8_t *log_table, uint64_t page) { DPRINT("Logged dirty guest page: %"PRId64"\n", page); - atomic_or(&log_table[page / 8], 1 << (page % 8)); + qatomic_or(&log_table[page / 8], 1 << (page % 8)); } static void @@ -495,6 +497,16 @@ static bool vu_get_features_exec(VuDev *dev, VhostUserMsg *vmsg) { vmsg->payload.u64 = + /* + * The following VIRTIO feature bits are supported by our virtqueue + * implementation: + */ + 1ULL << VIRTIO_F_NOTIFY_ON_EMPTY | + 1ULL << VIRTIO_RING_F_INDIRECT_DESC | + 1ULL << VIRTIO_RING_F_EVENT_IDX | + 1ULL << VIRTIO_F_VERSION_1 | + + /* vhost-user feature bits */ 1ULL << VHOST_F_LOG_ALL | 1ULL << VHOST_USER_F_PROTOCOL_FEATURES; @@ -526,6 +538,14 @@ vu_set_features_exec(VuDev *dev, VhostUserMsg *vmsg) DPRINT("u64: 0x%016"PRIx64"\n", vmsg->payload.u64); dev->features = vmsg->payload.u64; + if (!vu_has_feature(dev, VIRTIO_F_VERSION_1)) { + /* + * We only support devices conforming to VIRTIO 1.0 or + * later + */ + vu_panic(dev, "virtio legacy devices aren't supported by libvhost-user"); + return false; + } if (!(dev->features & VHOST_USER_F_PROTOCOL_FEATURES)) { vu_set_enable_all_rings(dev, true); @@ -583,6 +603,244 @@ map_ring(VuDev *dev, VuVirtq *vq) return !(vq->vring.desc && vq->vring.used && vq->vring.avail); } +static bool +generate_faults(VuDev *dev) { + int i; + for (i = 0; i < dev->nregions; i++) { + VuDevRegion *dev_region = &dev->regions[i]; + int ret; +#ifdef UFFDIO_REGISTER + /* + * We should already have an open ufd. Mark each memory + * range as ufd. + * Discard any mapping we have here; note I can't use MADV_REMOVE + * or fallocate to make the hole since I don't want to lose + * data that's already arrived in the shared process. + * TODO: How to do hugepage + */ + ret = madvise((void *)(uintptr_t)dev_region->mmap_addr, + dev_region->size + dev_region->mmap_offset, + MADV_DONTNEED); + if (ret) { + fprintf(stderr, + "%s: Failed to madvise(DONTNEED) region %d: %s\n", + __func__, i, strerror(errno)); + } + /* + * Turn off transparent hugepages so we dont get lose wakeups + * in neighbouring pages. + * TODO: Turn this backon later. + */ + ret = madvise((void *)(uintptr_t)dev_region->mmap_addr, + dev_region->size + dev_region->mmap_offset, + MADV_NOHUGEPAGE); + if (ret) { + /* + * Note: This can happen legally on kernels that are configured + * without madvise'able hugepages + */ + fprintf(stderr, + "%s: Failed to madvise(NOHUGEPAGE) region %d: %s\n", + __func__, i, strerror(errno)); + } + struct uffdio_register reg_struct; + reg_struct.range.start = (uintptr_t)dev_region->mmap_addr; + reg_struct.range.len = dev_region->size + dev_region->mmap_offset; + reg_struct.mode = UFFDIO_REGISTER_MODE_MISSING; + + if (ioctl(dev->postcopy_ufd, UFFDIO_REGISTER, ®_struct)) { + vu_panic(dev, "%s: Failed to userfault region %d " + "@%p + size:%zx offset: %zx: (ufd=%d)%s\n", + __func__, i, + dev_region->mmap_addr, + dev_region->size, dev_region->mmap_offset, + dev->postcopy_ufd, strerror(errno)); + return false; + } + if (!(reg_struct.ioctls & ((__u64)1 << _UFFDIO_COPY))) { + vu_panic(dev, "%s Region (%d) doesn't support COPY", + __func__, i); + return false; + } + DPRINT("%s: region %d: Registered userfault for %" + PRIx64 " + %" PRIx64 "\n", __func__, i, + (uint64_t)reg_struct.range.start, + (uint64_t)reg_struct.range.len); + /* Now it's registered we can let the client at it */ + if (mprotect((void *)(uintptr_t)dev_region->mmap_addr, + dev_region->size + dev_region->mmap_offset, + PROT_READ | PROT_WRITE)) { + vu_panic(dev, "failed to mprotect region %d for postcopy (%s)", + i, strerror(errno)); + return false; + } + /* TODO: Stash 'zero' support flags somewhere */ +#endif + } + + return true; +} + +static bool +vu_add_mem_reg(VuDev *dev, VhostUserMsg *vmsg) { + int i; + bool track_ramblocks = dev->postcopy_listening; + VhostUserMemoryRegion m = vmsg->payload.memreg.region, *msg_region = &m; + VuDevRegion *dev_region = &dev->regions[dev->nregions]; + void *mmap_addr; + + /* + * If we are in postcopy mode and we receive a u64 payload with a 0 value + * we know all the postcopy client bases have been received, and we + * should start generating faults. + */ + if (track_ramblocks && + vmsg->size == sizeof(vmsg->payload.u64) && + vmsg->payload.u64 == 0) { + (void)generate_faults(dev); + return false; + } + + DPRINT("Adding region: %u\n", dev->nregions); + DPRINT(" guest_phys_addr: 0x%016"PRIx64"\n", + msg_region->guest_phys_addr); + DPRINT(" memory_size: 0x%016"PRIx64"\n", + msg_region->memory_size); + DPRINT(" userspace_addr 0x%016"PRIx64"\n", + msg_region->userspace_addr); + DPRINT(" mmap_offset 0x%016"PRIx64"\n", + msg_region->mmap_offset); + + dev_region->gpa = msg_region->guest_phys_addr; + dev_region->size = msg_region->memory_size; + dev_region->qva = msg_region->userspace_addr; + dev_region->mmap_offset = msg_region->mmap_offset; + + /* + * We don't use offset argument of mmap() since the + * mapped address has to be page aligned, and we use huge + * pages. + */ + if (track_ramblocks) { + /* + * In postcopy we're using PROT_NONE here to catch anyone + * accessing it before we userfault. + */ + mmap_addr = mmap(0, dev_region->size + dev_region->mmap_offset, + PROT_NONE, MAP_SHARED, + vmsg->fds[0], 0); + } else { + mmap_addr = mmap(0, dev_region->size + dev_region->mmap_offset, + PROT_READ | PROT_WRITE, MAP_SHARED, vmsg->fds[0], + 0); + } + + if (mmap_addr == MAP_FAILED) { + vu_panic(dev, "region mmap error: %s", strerror(errno)); + } else { + dev_region->mmap_addr = (uint64_t)(uintptr_t)mmap_addr; + DPRINT(" mmap_addr: 0x%016"PRIx64"\n", + dev_region->mmap_addr); + } + + close(vmsg->fds[0]); + + if (track_ramblocks) { + /* + * Return the address to QEMU so that it can translate the ufd + * fault addresses back. + */ + msg_region->userspace_addr = (uintptr_t)(mmap_addr + + dev_region->mmap_offset); + + /* Send the message back to qemu with the addresses filled in. */ + vmsg->fd_num = 0; + if (!vu_send_reply(dev, dev->sock, vmsg)) { + vu_panic(dev, "failed to respond to add-mem-region for postcopy"); + return false; + } + + DPRINT("Successfully added new region in postcopy\n"); + dev->nregions++; + return false; + + } else { + for (i = 0; i < dev->max_queues; i++) { + if (dev->vq[i].vring.desc) { + if (map_ring(dev, &dev->vq[i])) { + vu_panic(dev, "remapping queue %d for new memory region", + i); + } + } + } + + DPRINT("Successfully added new region\n"); + dev->nregions++; + vmsg_set_reply_u64(vmsg, 0); + return true; + } +} + +static inline bool reg_equal(VuDevRegion *vudev_reg, + VhostUserMemoryRegion *msg_reg) +{ + if (vudev_reg->gpa == msg_reg->guest_phys_addr && + vudev_reg->qva == msg_reg->userspace_addr && + vudev_reg->size == msg_reg->memory_size) { + return true; + } + + return false; +} + +static bool +vu_rem_mem_reg(VuDev *dev, VhostUserMsg *vmsg) { + int i, j; + bool found = false; + VuDevRegion shadow_regions[VHOST_USER_MAX_RAM_SLOTS] = {}; + VhostUserMemoryRegion m = vmsg->payload.memreg.region, *msg_region = &m; + + DPRINT("Removing region:\n"); + DPRINT(" guest_phys_addr: 0x%016"PRIx64"\n", + msg_region->guest_phys_addr); + DPRINT(" memory_size: 0x%016"PRIx64"\n", + msg_region->memory_size); + DPRINT(" userspace_addr 0x%016"PRIx64"\n", + msg_region->userspace_addr); + DPRINT(" mmap_offset 0x%016"PRIx64"\n", + msg_region->mmap_offset); + + for (i = 0, j = 0; i < dev->nregions; i++) { + if (!reg_equal(&dev->regions[i], msg_region)) { + shadow_regions[j].gpa = dev->regions[i].gpa; + shadow_regions[j].size = dev->regions[i].size; + shadow_regions[j].qva = dev->regions[i].qva; + shadow_regions[j].mmap_offset = dev->regions[i].mmap_offset; + j++; + } else { + found = true; + VuDevRegion *r = &dev->regions[i]; + void *m = (void *) (uintptr_t) r->mmap_addr; + + if (m) { + munmap(m, r->size + r->mmap_offset); + } + } + } + + if (found) { + memcpy(dev->regions, shadow_regions, + sizeof(VuDevRegion) * VHOST_USER_MAX_RAM_SLOTS); + DPRINT("Successfully removed a region\n"); + dev->nregions--; + vmsg_set_reply_u64(vmsg, 0); + } else { + vu_panic(dev, "Specified region not found\n"); + } + + return true; +} + static bool vu_set_mem_table_exec_postcopy(VuDev *dev, VhostUserMsg *vmsg) { @@ -590,7 +848,7 @@ vu_set_mem_table_exec_postcopy(VuDev *dev, VhostUserMsg *vmsg) VhostUserMemory m = vmsg->payload.memory, *memory = &m; dev->nregions = memory->nregions; - DPRINT("Nregions: %d\n", memory->nregions); + DPRINT("Nregions: %u\n", memory->nregions); for (i = 0; i < dev->nregions; i++) { void *mmap_addr; VhostUserMemoryRegion *msg_region = &memory->regions[i]; @@ -647,7 +905,7 @@ vu_set_mem_table_exec_postcopy(VuDev *dev, VhostUserMsg *vmsg) /* Wait for QEMU to confirm that it's registered the handler for the * faults. */ - if (!vu_message_read(dev, dev->sock, vmsg) || + if (!dev->read_msg(dev, dev->sock, vmsg) || vmsg->size != sizeof(vmsg->payload.u64) || vmsg->payload.u64 != 0) { vu_panic(dev, "failed to receive valid ack for postcopy set-mem-table"); @@ -655,74 +913,7 @@ vu_set_mem_table_exec_postcopy(VuDev *dev, VhostUserMsg *vmsg) } /* OK, now we can go and register the memory and generate faults */ - for (i = 0; i < dev->nregions; i++) { - VuDevRegion *dev_region = &dev->regions[i]; - int ret; -#ifdef UFFDIO_REGISTER - /* We should already have an open ufd. Mark each memory - * range as ufd. - * Discard any mapping we have here; note I can't use MADV_REMOVE - * or fallocate to make the hole since I don't want to lose - * data that's already arrived in the shared process. - * TODO: How to do hugepage - */ - ret = madvise((void *)(uintptr_t)dev_region->mmap_addr, - dev_region->size + dev_region->mmap_offset, - MADV_DONTNEED); - if (ret) { - fprintf(stderr, - "%s: Failed to madvise(DONTNEED) region %d: %s\n", - __func__, i, strerror(errno)); - } - /* Turn off transparent hugepages so we dont get lose wakeups - * in neighbouring pages. - * TODO: Turn this backon later. - */ - ret = madvise((void *)(uintptr_t)dev_region->mmap_addr, - dev_region->size + dev_region->mmap_offset, - MADV_NOHUGEPAGE); - if (ret) { - /* Note: This can happen legally on kernels that are configured - * without madvise'able hugepages - */ - fprintf(stderr, - "%s: Failed to madvise(NOHUGEPAGE) region %d: %s\n", - __func__, i, strerror(errno)); - } - struct uffdio_register reg_struct; - reg_struct.range.start = (uintptr_t)dev_region->mmap_addr; - reg_struct.range.len = dev_region->size + dev_region->mmap_offset; - reg_struct.mode = UFFDIO_REGISTER_MODE_MISSING; - - if (ioctl(dev->postcopy_ufd, UFFDIO_REGISTER, ®_struct)) { - vu_panic(dev, "%s: Failed to userfault region %d " - "@%p + size:%zx offset: %zx: (ufd=%d)%s\n", - __func__, i, - dev_region->mmap_addr, - dev_region->size, dev_region->mmap_offset, - dev->postcopy_ufd, strerror(errno)); - return false; - } - if (!(reg_struct.ioctls & ((__u64)1 << _UFFDIO_COPY))) { - vu_panic(dev, "%s Region (%d) doesn't support COPY", - __func__, i); - return false; - } - DPRINT("%s: region %d: Registered userfault for %" - PRIx64 " + %" PRIx64 "\n", __func__, i, - (uint64_t)reg_struct.range.start, - (uint64_t)reg_struct.range.len); - /* Now it's registered we can let the client at it */ - if (mprotect((void *)(uintptr_t)dev_region->mmap_addr, - dev_region->size + dev_region->mmap_offset, - PROT_READ | PROT_WRITE)) { - vu_panic(dev, "failed to mprotect region %d for postcopy (%s)", - i, strerror(errno)); - return false; - } - /* TODO: Stash 'zero' support flags somewhere */ -#endif - } + (void)generate_faults(dev); return false; } @@ -747,7 +938,7 @@ vu_set_mem_table_exec(VuDev *dev, VhostUserMsg *vmsg) return vu_set_mem_table_exec_postcopy(dev, vmsg); } - DPRINT("Nregions: %d\n", memory->nregions); + DPRINT("Nregions: %u\n", memory->nregions); for (i = 0; i < dev->nregions; i++) { void *mmap_addr; VhostUserMemoryRegion *msg_region = &memory->regions[i]; @@ -789,7 +980,7 @@ vu_set_mem_table_exec(VuDev *dev, VhostUserMsg *vmsg) for (i = 0; i < dev->max_queues; i++) { if (dev->vq[i].vring.desc) { if (map_ring(dev, &dev->vq[i])) { - vu_panic(dev, "remaping queue %d during setmemtable", i); + vu_panic(dev, "remapping queue %d during setmemtable", i); } } } @@ -858,8 +1049,8 @@ vu_set_vring_num_exec(VuDev *dev, VhostUserMsg *vmsg) unsigned int index = vmsg->payload.state.index; unsigned int num = vmsg->payload.state.num; - DPRINT("State.index: %d\n", index); - DPRINT("State.num: %d\n", num); + DPRINT("State.index: %u\n", index); + DPRINT("State.num: %u\n", num); dev->vq[index].vring.num = num; return false; @@ -890,7 +1081,7 @@ vu_set_vring_addr_exec(VuDev *dev, VhostUserMsg *vmsg) return false; } - vq->used_idx = vq->vring.used->idx; + vq->used_idx = lduw_le_p(&vq->vring.used->idx); if (vq->last_avail_idx != vq->used_idx) { bool resume = dev->iface->queue_is_processed_in_order && @@ -914,8 +1105,8 @@ vu_set_vring_base_exec(VuDev *dev, VhostUserMsg *vmsg) unsigned int index = vmsg->payload.state.index; unsigned int num = vmsg->payload.state.num; - DPRINT("State.index: %d\n", index); - DPRINT("State.num: %d\n", num); + DPRINT("State.index: %u\n", index); + DPRINT("State.num: %u\n", num); dev->vq[index].shadow_avail_idx = dev->vq[index].last_avail_idx = num; return false; @@ -926,7 +1117,7 @@ vu_get_vring_base_exec(VuDev *dev, VhostUserMsg *vmsg) { unsigned int index = vmsg->payload.state.index; - DPRINT("State.index: %d\n", index); + DPRINT("State.index: %u\n", index); vmsg->payload.state.num = dev->vq[index].last_avail_idx; vmsg->size = sizeof(vmsg->payload.state); @@ -1007,7 +1198,7 @@ vu_check_queue_inflights(VuDev *dev, VuVirtq *vq) return 0; } - vq->used_idx = vq->vring.used->idx; + vq->used_idx = lduw_le_p(&vq->vring.used->idx); vq->resubmit_num = 0; vq->resubmit_list = NULL; vq->counter = 0; @@ -1220,7 +1411,8 @@ vu_get_protocol_features_exec(VuDev *dev, VhostUserMsg *vmsg) 1ULL << VHOST_USER_PROTOCOL_F_SLAVE_REQ | 1ULL << VHOST_USER_PROTOCOL_F_HOST_NOTIFIER | 1ULL << VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD | - 1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK; + 1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK | + 1ULL << VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS; if (have_userfault()) { features |= 1ULL << VHOST_USER_PROTOCOL_F_PAGEFAULT; @@ -1286,8 +1478,8 @@ vu_set_vring_enable_exec(VuDev *dev, VhostUserMsg *vmsg) unsigned int index = vmsg->payload.state.index; unsigned int enable = vmsg->payload.state.num; - DPRINT("State.index: %d\n", index); - DPRINT("State.enable: %d\n", enable); + DPRINT("State.index: %u\n", index); + DPRINT("State.enable: %u\n", enable); if (index >= dev->max_queues) { vu_panic(dev, "Invalid vring_enable index: %u", index); @@ -1536,7 +1728,7 @@ vu_handle_vring_kick(VuDev *dev, VhostUserMsg *vmsg) return false; } - DPRINT("Got kick message: handler:%p idx:%d\n", + DPRINT("Got kick message: handler:%p idx:%u\n", dev->vq[index].handler, index); if (!dev->vq[index].started) { @@ -1554,6 +1746,22 @@ vu_handle_vring_kick(VuDev *dev, VhostUserMsg *vmsg) return false; } +static bool vu_handle_get_max_memslots(VuDev *dev, VhostUserMsg *vmsg) +{ + vmsg->flags = VHOST_USER_REPLY_MASK | VHOST_USER_VERSION; + vmsg->size = sizeof(vmsg->payload.u64); + vmsg->payload.u64 = VHOST_USER_MAX_RAM_SLOTS; + vmsg->fd_num = 0; + + if (!vu_message_write(dev, dev->sock, vmsg)) { + vu_panic(dev, "Failed to send max ram slots: %s\n", strerror(errno)); + } + + DPRINT("u64: 0x%016"PRIx64"\n", (uint64_t) VHOST_USER_MAX_RAM_SLOTS); + + return false; +} + static bool vu_process_message(VuDev *dev, VhostUserMsg *vmsg) { @@ -1564,7 +1772,7 @@ vu_process_message(VuDev *dev, VhostUserMsg *vmsg) DPRINT("Request: %s (%d)\n", vu_request_to_string(vmsg->request), vmsg->request); DPRINT("Flags: 0x%x\n", vmsg->flags); - DPRINT("Size: %d\n", vmsg->size); + DPRINT("Size: %u\n", vmsg->size); if (vmsg->fd_num) { int i; @@ -1638,6 +1846,12 @@ vu_process_message(VuDev *dev, VhostUserMsg *vmsg) return vu_set_inflight_fd(dev, vmsg); case VHOST_USER_VRING_KICK: return vu_handle_vring_kick(dev, vmsg); + case VHOST_USER_GET_MAX_MEM_SLOTS: + return vu_handle_get_max_memslots(dev, vmsg); + case VHOST_USER_ADD_MEM_REG: + return vu_add_mem_reg(dev, vmsg); + case VHOST_USER_REM_MEM_REG: + return vu_rem_mem_reg(dev, vmsg); default: vmsg_close_fds(vmsg); vu_panic(dev, "Unhandled request: %d", vmsg->request); @@ -1653,7 +1867,7 @@ vu_dispatch(VuDev *dev) int reply_requested; bool need_reply, success = false; - if (!vu_message_read(dev, dev->sock, &vmsg)) { + if (!dev->read_msg(dev, dev->sock, &vmsg)) { goto end; } @@ -1704,6 +1918,7 @@ vu_deinit(VuDev *dev) } if (vq->kick_fd != -1) { + dev->remove_watch(dev, vq->kick_fd); close(vq->kick_fd); vq->kick_fd = -1; } @@ -1751,6 +1966,7 @@ vu_init(VuDev *dev, uint16_t max_queues, int socket, vu_panic_cb panic, + vu_read_msg_cb read_msg, vu_set_watch_cb set_watch, vu_remove_watch_cb remove_watch, const VuDevIface *iface) @@ -1768,6 +1984,7 @@ vu_init(VuDev *dev, dev->sock = socket; dev->panic = panic; + dev->read_msg = read_msg ? read_msg : vu_message_read_default; dev->set_watch = set_watch; dev->remove_watch = remove_watch; dev->iface = iface; @@ -1814,13 +2031,13 @@ vu_queue_started(const VuDev *dev, const VuVirtq *vq) static inline uint16_t vring_avail_flags(VuVirtq *vq) { - return vq->vring.avail->flags; + return lduw_le_p(&vq->vring.avail->flags); } static inline uint16_t vring_avail_idx(VuVirtq *vq) { - vq->shadow_avail_idx = vq->vring.avail->idx; + vq->shadow_avail_idx = lduw_le_p(&vq->vring.avail->idx); return vq->shadow_avail_idx; } @@ -1828,7 +2045,7 @@ vring_avail_idx(VuVirtq *vq) static inline uint16_t vring_avail_ring(VuVirtq *vq, int i) { - return vq->vring.avail->ring[i]; + return lduw_le_p(&vq->vring.avail->ring[i]); } static inline uint16_t @@ -1867,7 +2084,7 @@ virtqueue_get_head(VuDev *dev, VuVirtq *vq, /* If their number is silly, that's a fatal mistake. */ if (*head >= vq->vring.num) { - vu_panic(dev, "Guest says index %u is available", head); + vu_panic(dev, "Guest says index %u is available", *head); return false; } @@ -1916,17 +2133,17 @@ virtqueue_read_next_desc(VuDev *dev, struct vring_desc *desc, int i, unsigned int max, unsigned int *next) { /* If this descriptor says it doesn't chain, we're done. */ - if (!(desc[i].flags & VRING_DESC_F_NEXT)) { + if (!(lduw_le_p(&desc[i].flags) & VRING_DESC_F_NEXT)) { return VIRTQUEUE_READ_DESC_DONE; } /* Check they're not leading us off end of descriptors. */ - *next = desc[i].next; + *next = lduw_le_p(&desc[i].next); /* Make sure compiler knows to grab that: we don't want it changing! */ smp_wmb(); if (*next >= max) { - vu_panic(dev, "Desc next is %u", next); + vu_panic(dev, "Desc next is %u", *next); return VIRTQUEUE_READ_DESC_ERROR; } @@ -1964,8 +2181,8 @@ vu_queue_get_avail_bytes(VuDev *dev, VuVirtq *vq, unsigned int *in_bytes, } desc = vq->vring.desc; - if (desc[i].flags & VRING_DESC_F_INDIRECT) { - if (desc[i].len % sizeof(struct vring_desc)) { + if (lduw_le_p(&desc[i].flags) & VRING_DESC_F_INDIRECT) { + if (ldl_le_p(&desc[i].len) % sizeof(struct vring_desc)) { vu_panic(dev, "Invalid size for indirect buffer table"); goto err; } @@ -1978,8 +2195,8 @@ vu_queue_get_avail_bytes(VuDev *dev, VuVirtq *vq, unsigned int *in_bytes, /* loop over the indirect descriptor table */ indirect = 1; - desc_addr = desc[i].addr; - desc_len = desc[i].len; + desc_addr = ldq_le_p(&desc[i].addr); + desc_len = ldl_le_p(&desc[i].len); max = desc_len / sizeof(struct vring_desc); read_len = desc_len; desc = vu_gpa_to_va(dev, &read_len, desc_addr); @@ -2006,10 +2223,10 @@ vu_queue_get_avail_bytes(VuDev *dev, VuVirtq *vq, unsigned int *in_bytes, goto err; } - if (desc[i].flags & VRING_DESC_F_WRITE) { - in_total += desc[i].len; + if (lduw_le_p(&desc[i].flags) & VRING_DESC_F_WRITE) { + in_total += ldl_le_p(&desc[i].len); } else { - out_total += desc[i].len; + out_total += ldl_le_p(&desc[i].len); } if (in_total >= max_in_bytes && out_total >= max_out_bytes) { goto done; @@ -2133,7 +2350,7 @@ static void _vu_queue_notify(VuDev *dev, VuVirtq *vq, bool sync) vu_message_write(dev, dev->slave_fd, &vmsg); if (ack) { - vu_message_read(dev, dev->slave_fd, &vmsg); + vu_message_read_default(dev, dev->slave_fd, &vmsg); } return; } @@ -2160,7 +2377,7 @@ vring_used_flags_set_bit(VuVirtq *vq, int mask) flags = (uint16_t *)((char*)vq->vring.used + offsetof(struct vring_used, flags)); - *flags |= mask; + stw_le_p(flags, lduw_le_p(flags) | mask); } static inline void @@ -2170,7 +2387,7 @@ vring_used_flags_unset_bit(VuVirtq *vq, int mask) flags = (uint16_t *)((char*)vq->vring.used + offsetof(struct vring_used, flags)); - *flags &= ~mask; + stw_le_p(flags, lduw_le_p(flags) & ~mask); } static inline void @@ -2180,7 +2397,7 @@ vring_set_avail_event(VuVirtq *vq, uint16_t val) return; } - *((uint16_t *) &vq->vring.used->ring[vq->vring.num]) = val; + stw_le_p(&vq->vring.used->ring[vq->vring.num], val); } void @@ -2200,7 +2417,7 @@ vu_queue_set_notification(VuDev *dev, VuVirtq *vq, int enable) } } -static void +static bool virtqueue_map_desc(VuDev *dev, unsigned int *p_num_sg, struct iovec *iov, unsigned int max_num_sg, bool is_write, @@ -2212,7 +2429,7 @@ virtqueue_map_desc(VuDev *dev, if (!sz) { vu_panic(dev, "virtio: zero sized buffers are not allowed"); - return; + return false; } while (sz) { @@ -2220,13 +2437,13 @@ virtqueue_map_desc(VuDev *dev, if (num_sg == max_num_sg) { vu_panic(dev, "virtio: too many descriptors in indirect table"); - return; + return false; } iov[num_sg].iov_base = vu_gpa_to_va(dev, &len, pa); if (iov[num_sg].iov_base == NULL) { vu_panic(dev, "virtio: invalid address for buffers"); - return; + return false; } iov[num_sg].iov_len = len; num_sg++; @@ -2235,6 +2452,7 @@ virtqueue_map_desc(VuDev *dev, } *p_num_sg = num_sg; + return true; } static void * @@ -2269,14 +2487,15 @@ vu_queue_map_desc(VuDev *dev, VuVirtq *vq, unsigned int idx, size_t sz) struct vring_desc desc_buf[VIRTQUEUE_MAX_SIZE]; int rc; - if (desc[i].flags & VRING_DESC_F_INDIRECT) { - if (desc[i].len % sizeof(struct vring_desc)) { + if (lduw_le_p(&desc[i].flags) & VRING_DESC_F_INDIRECT) { + if (ldl_le_p(&desc[i].len) % sizeof(struct vring_desc)) { vu_panic(dev, "Invalid size for indirect buffer table"); + return NULL; } /* loop over the indirect descriptor table */ - desc_addr = desc[i].addr; - desc_len = desc[i].len; + desc_addr = ldq_le_p(&desc[i].addr); + desc_len = ldl_le_p(&desc[i].len); max = desc_len / sizeof(struct vring_desc); read_len = desc_len; desc = vu_gpa_to_va(dev, &read_len, desc_addr); @@ -2298,23 +2517,30 @@ vu_queue_map_desc(VuDev *dev, VuVirtq *vq, unsigned int idx, size_t sz) /* Collect all the descriptors */ do { - if (desc[i].flags & VRING_DESC_F_WRITE) { - virtqueue_map_desc(dev, &in_num, iov + out_num, + if (lduw_le_p(&desc[i].flags) & VRING_DESC_F_WRITE) { + if (!virtqueue_map_desc(dev, &in_num, iov + out_num, VIRTQUEUE_MAX_SIZE - out_num, true, - desc[i].addr, desc[i].len); + ldq_le_p(&desc[i].addr), + ldl_le_p(&desc[i].len))) { + return NULL; + } } else { if (in_num) { vu_panic(dev, "Incorrect order for descriptors"); return NULL; } - virtqueue_map_desc(dev, &out_num, iov, + if (!virtqueue_map_desc(dev, &out_num, iov, VIRTQUEUE_MAX_SIZE, false, - desc[i].addr, desc[i].len); + ldq_le_p(&desc[i].addr), + ldl_le_p(&desc[i].len))) { + return NULL; + } } /* If we've got too many, that implies a descriptor loop. */ if ((in_num + out_num) > max) { vu_panic(dev, "Looped descriptor"); + return NULL; } rc = virtqueue_read_next_desc(dev, desc, i, max, &i); } while (rc == VIRTQUEUE_READ_DESC_MORE); @@ -2505,14 +2731,15 @@ vu_log_queue_fill(VuDev *dev, VuVirtq *vq, max = vq->vring.num; i = elem->index; - if (desc[i].flags & VRING_DESC_F_INDIRECT) { - if (desc[i].len % sizeof(struct vring_desc)) { + if (lduw_le_p(&desc[i].flags) & VRING_DESC_F_INDIRECT) { + if (ldl_le_p(&desc[i].len) % sizeof(struct vring_desc)) { vu_panic(dev, "Invalid size for indirect buffer table"); + return; } /* loop over the indirect descriptor table */ - desc_addr = desc[i].addr; - desc_len = desc[i].len; + desc_addr = ldq_le_p(&desc[i].addr); + desc_len = ldl_le_p(&desc[i].len); max = desc_len / sizeof(struct vring_desc); read_len = desc_len; desc = vu_gpa_to_va(dev, &read_len, desc_addr); @@ -2538,9 +2765,9 @@ vu_log_queue_fill(VuDev *dev, VuVirtq *vq, return; } - if (desc[i].flags & VRING_DESC_F_WRITE) { - min = MIN(desc[i].len, len); - vu_log_write(dev, desc[i].addr, min); + if (lduw_le_p(&desc[i].flags) & VRING_DESC_F_WRITE) { + min = MIN(ldl_le_p(&desc[i].len), len); + vu_log_write(dev, ldq_le_p(&desc[i].addr), min); len -= min; } @@ -2565,15 +2792,15 @@ vu_queue_fill(VuDev *dev, VuVirtq *vq, idx = (idx + vq->used_idx) % vq->vring.num; - uelem.id = elem->index; - uelem.len = len; + stl_le_p(&uelem.id, elem->index); + stl_le_p(&uelem.len, len); vring_used_write(dev, vq, &uelem, idx); } static inline void vring_used_idx_set(VuDev *dev, VuVirtq *vq, uint16_t val) { - vq->vring.used->idx = val; + stw_le_p(&vq->vring.used->idx, val); vu_log_write(dev, vq->vring.log_guest_addr + offsetof(struct vring_used, idx), sizeof(vq->vring.used->idx)); diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/libvhost-user.h index f30394fab66c2d0363489e6249fa10c10faea56d..7d47f1364a5703b3437c1cc8e60e5072dbecb107 100644 --- a/contrib/libvhost-user/libvhost-user.h +++ b/contrib/libvhost-user/libvhost-user.h @@ -28,7 +28,15 @@ #define VIRTQUEUE_MAX_SIZE 1024 -#define VHOST_MEMORY_MAX_NREGIONS 8 +#define VHOST_MEMORY_BASELINE_NREGIONS 8 + +/* + * Set a reasonable maximum number of ram slots, which will be supported by + * any architecture. + */ +#define VHOST_USER_MAX_RAM_SLOTS 32 + +#define VHOST_USER_HDR_SIZE offsetof(VhostUserMsg, payload.u64) typedef enum VhostSetConfigType { VHOST_SET_CONFIG_TYPE_MASTER = 0, @@ -55,6 +63,7 @@ enum VhostUserProtocolFeature { VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11, VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD = 12, VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS = 14, + VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS = 15, VHOST_USER_PROTOCOL_F_MAX }; @@ -97,6 +106,9 @@ typedef enum VhostUserRequest { VHOST_USER_SET_INFLIGHT_FD = 32, VHOST_USER_GPU_SET_SOCKET = 33, VHOST_USER_VRING_KICK = 35, + VHOST_USER_GET_MAX_MEM_SLOTS = 36, + VHOST_USER_ADD_MEM_REG = 37, + VHOST_USER_REM_MEM_REG = 38, VHOST_USER_MAX } VhostUserRequest; @@ -120,9 +132,14 @@ typedef struct VhostUserMemoryRegion { typedef struct VhostUserMemory { uint32_t nregions; uint32_t padding; - VhostUserMemoryRegion regions[VHOST_MEMORY_MAX_NREGIONS]; + VhostUserMemoryRegion regions[VHOST_MEMORY_BASELINE_NREGIONS]; } VhostUserMemory; +typedef struct VhostUserMemRegMsg { + uint64_t padding; + VhostUserMemoryRegion region; +} VhostUserMemRegMsg; + typedef struct VhostUserLog { uint64_t mmap_size; uint64_t mmap_offset; @@ -175,13 +192,14 @@ typedef struct VhostUserMsg { struct vhost_vring_state state; struct vhost_vring_addr addr; VhostUserMemory memory; + VhostUserMemRegMsg memreg; VhostUserLog log; VhostUserConfig config; VhostUserVringArea area; VhostUserInflight inflight; } payload; - int fds[VHOST_MEMORY_MAX_NREGIONS]; + int fds[VHOST_MEMORY_BASELINE_NREGIONS]; int fd_num; uint8_t *data; } VU_PACKED VhostUserMsg; @@ -205,6 +223,7 @@ typedef uint64_t (*vu_get_features_cb) (VuDev *dev); typedef void (*vu_set_features_cb) (VuDev *dev, uint64_t features); typedef int (*vu_process_msg_cb) (VuDev *dev, VhostUserMsg *vmsg, int *do_reply); +typedef bool (*vu_read_msg_cb) (VuDev *dev, int sock, VhostUserMsg *vmsg); typedef void (*vu_queue_set_started_cb) (VuDev *dev, int qidx, bool started); typedef bool (*vu_queue_is_processed_in_order_cb) (VuDev *dev, int qidx); typedef int (*vu_get_config_cb) (VuDev *dev, uint8_t *config, uint32_t len); @@ -359,7 +378,7 @@ typedef struct VuDevInflightInfo { struct VuDev { int sock; uint32_t nregions; - VuDevRegion regions[VHOST_MEMORY_MAX_NREGIONS]; + VuDevRegion regions[VHOST_USER_MAX_RAM_SLOTS]; VuVirtq *vq; VuDevInflightInfo inflight_info; int log_call_fd; @@ -373,15 +392,37 @@ struct VuDev { bool broken; uint16_t max_queues; - /* @set_watch: add or update the given fd to the watch set, - * call cb when condition is met */ + /* + * @read_msg: custom method to read vhost-user message + * + * Read data from vhost_user socket fd and fill up + * the passed VhostUserMsg *vmsg struct. + * + * If reading fails, it should close the received set of file + * descriptors as socket message's auxiliary data. + * + * For the details, please refer to vu_message_read in libvhost-user.c + * which will be used by default if not custom method is provided when + * calling vu_init + * + * Returns: true if vhost-user message successfully received, + * otherwise return false. + * + */ + vu_read_msg_cb read_msg; + + /* + * @set_watch: add or update the given fd to the watch set, + * call cb when condition is met. + */ vu_set_watch_cb set_watch; /* @remove_watch: remove the given fd from the watch set */ vu_remove_watch_cb remove_watch; - /* @panic: encountered an unrecoverable error, you may try to - * re-initialize */ + /* + * @panic: encountered an unrecoverable error, you may try to re-initialize + */ vu_panic_cb panic; const VuDevIface *iface; @@ -408,7 +449,7 @@ typedef struct VuVirtqElement { * @remove_watch: a remove_watch callback * @iface: a VuDevIface structure with vhost-user device callbacks * - * Intializes a VuDev vhost-user context. + * Initializes a VuDev vhost-user context. * * Returns: true on success, false on failure. **/ @@ -416,6 +457,7 @@ bool vu_init(VuDev *dev, uint16_t max_queues, int socket, vu_panic_cb panic, + vu_read_msg_cb read_msg, vu_set_watch_cb set_watch, vu_remove_watch_cb remove_watch, const VuDevIface *iface); diff --git a/contrib/libvhost-user/meson.build b/contrib/libvhost-user/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..a261e7665f79cb88cfaa5f6b127afaa1b49e719b --- /dev/null +++ b/contrib/libvhost-user/meson.build @@ -0,0 +1,4 @@ +libvhost_user = static_library('vhost-user', + files('libvhost-user.c', 'libvhost-user-glib.c'), + build_by_default: false) +vhost_user = declare_dependency(link_with: libvhost_user) diff --git a/tests/plugin/Makefile b/contrib/plugins/Makefile similarity index 34% rename from tests/plugin/Makefile rename to contrib/plugins/Makefile index 75467b6db8599a7be2063a0a1a53df8bceaed28d..7801b08b0d6e1e2ee17ca0e481da7c120eb84aae 100644 --- a/tests/plugin/Makefile +++ b/contrib/plugins/Makefile @@ -1,26 +1,37 @@ +# -*- Mode: makefile -*- +# +# This Makefile example is fairly independent from the main makefile +# so users can take and adapt it for their build. We only really +# include config-host.mak so we don't have to repeat probing for +# cflags that the main configure has already done for us. +# + BUILD_DIR := $(CURDIR)/../.. include $(BUILD_DIR)/config-host.mak -include $(SRC_PATH)/rules.mak -$(call set-vpath, $(SRC_PATH)/tests/plugin) +VPATH += $(SRC_PATH)/contrib/plugins NAMES := -NAMES += bb -NAMES += empty -NAMES += insn -NAMES += mem NAMES += hotblocks -NAMES += howvec NAMES += hotpages +NAMES += howvec +NAMES += lockstep SONAMES := $(addsuffix .so,$(addprefix lib,$(NAMES))) -QEMU_CFLAGS += -fPIC -QEMU_CFLAGS += -I$(SRC_PATH)/include/qemu +# 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 += $(if $(findstring no-psabi,$(QEMU_CFLAGS)),-Wpsabi) +CFLAGS += -I$(SRC_PATH)/include/qemu all: $(SONAMES) +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + lib%.so: %.o $(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDLIBS) diff --git a/tests/plugin/hotblocks.c b/contrib/plugins/hotblocks.c similarity index 98% rename from tests/plugin/hotblocks.c rename to contrib/plugins/hotblocks.c index 3942a2ca544cc2cebeb8e788f03ccabd8f3f98a7..37435a3fc7c6e08aa3615731b8b3d4012b648678 100644 --- a/tests/plugin/hotblocks.c +++ b/contrib/plugins/hotblocks.c @@ -102,7 +102,7 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) { ExecCount *cnt; uint64_t pc = qemu_plugin_tb_vaddr(tb); - unsigned long insns = qemu_plugin_tb_n_insns(tb); + size_t insns = qemu_plugin_tb_n_insns(tb); uint64_t hash = pc ^ insns; g_mutex_lock(&lock); diff --git a/tests/plugin/hotpages.c b/contrib/plugins/hotpages.c similarity index 100% rename from tests/plugin/hotpages.c rename to contrib/plugins/hotpages.c diff --git a/tests/plugin/howvec.c b/contrib/plugins/howvec.c similarity index 100% rename from tests/plugin/howvec.c rename to contrib/plugins/howvec.c diff --git a/contrib/plugins/lockstep.c b/contrib/plugins/lockstep.c new file mode 100644 index 0000000000000000000000000000000000000000..5aad50869d50c2cbd7e339f47f644cddccdb68ca --- /dev/null +++ b/contrib/plugins/lockstep.c @@ -0,0 +1,343 @@ +/* + * Lockstep Execution Plugin + * + * Allows you to execute two QEMU instances in lockstep and report + * when their execution diverges. This is mainly useful for developers + * who want to see where a change to TCG code generation has + * introduced a subtle and hard to find bug. + * + * Caveats: + * - single-threaded linux-user apps only with non-deterministic syscalls + * - no MTTCG enabled system emulation (icount may help) + * + * While icount makes things more deterministic it doesn't mean a + * particular run may execute the exact same sequence of blocks. An + * asynchronous event (for example X11 graphics update) may cause a + * block to end early and a new partial block to start. This means + * serial only test cases are a better bet. -d nochain may also help. + * + * This code is not thread safe! + * + * Copyright (c) 2020 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; + +/* saved so we can uninstall later */ +static qemu_plugin_id_t our_id; + +static unsigned long bb_count; +static unsigned long insn_count; + +/* Information about a translated block */ +typedef struct { + uint64_t pc; + uint64_t insns; +} BlockInfo; + +/* Information about an execution state in the log */ +typedef struct { + BlockInfo *block; + unsigned long insn_count; + unsigned long block_count; +} ExecInfo; + +/* The execution state we compare */ +typedef struct { + uint64_t pc; + unsigned long insn_count; +} ExecState; + +typedef struct { + GSList *log_pos; + int distance; +} DivergeState; + +/* list of translated block info */ +static GSList *blocks; + +/* execution log and points of divergence */ +static GSList *log, *divergence_log; + +static int socket_fd; +static char *path_to_unlink; + +static bool verbose; + +static void plugin_cleanup(qemu_plugin_id_t id) +{ + /* Free our block data */ + g_slist_free_full(blocks, &g_free); + g_slist_free_full(log, &g_free); + g_slist_free(divergence_log); + + close(socket_fd); + if (path_to_unlink) { + unlink(path_to_unlink); + } +} + +static void plugin_exit(qemu_plugin_id_t id, void *p) +{ + g_autoptr(GString) out = g_string_new("No divergence :-)\n"); + g_string_append_printf(out, "Executed %ld/%d blocks\n", + bb_count, g_slist_length(log)); + g_string_append_printf(out, "Executed ~%ld instructions\n", insn_count); + qemu_plugin_outs(out->str); + + plugin_cleanup(id); +} + +static void report_divergance(ExecState *us, ExecState *them) +{ + DivergeState divrec = { log, 0 }; + g_autoptr(GString) out = g_string_new(""); + bool diverged = false; + + /* + * If we have diverged before did we get back on track or are we + * totally loosing it? + */ + if (divergence_log) { + DivergeState *last = (DivergeState *) divergence_log->data; + GSList *entry; + + for (entry = log; g_slist_next(entry); entry = g_slist_next(entry)) { + if (entry == last->log_pos) { + break; + } + divrec.distance++; + } + + /* + * If the last two records are so close it is likely we will + * not recover synchronisation with the other end. + */ + if (divrec.distance == 1 && last->distance == 1) { + diverged = true; + } + } + divergence_log = g_slist_prepend(divergence_log, + g_memdup(&divrec, sizeof(divrec))); + + /* Output short log entry of going out of sync... */ + if (verbose || divrec.distance == 1 || diverged) { + g_string_printf(out, "@ %#016lx vs %#016lx (%d/%d since last)\n", + us->pc, them->pc, g_slist_length(divergence_log), + divrec.distance); + qemu_plugin_outs(out->str); + } + + if (diverged) { + int i; + GSList *entry; + + g_string_printf(out, "Δ insn_count @ %#016lx (%ld) vs %#016lx (%ld)\n", + us->pc, us->insn_count, them->pc, them->insn_count); + + for (entry = log, i = 0; + g_slist_next(entry) && i < 5; + entry = g_slist_next(entry), i++) { + ExecInfo *prev = (ExecInfo *) entry->data; + g_string_append_printf(out, + " previously @ %#016lx/%ld (%ld insns)\n", + prev->block->pc, prev->block->insns, + prev->insn_count); + } + qemu_plugin_outs(out->str); + qemu_plugin_outs("too much divergence... giving up."); + qemu_plugin_uninstall(our_id, plugin_cleanup); + } +} + +static void vcpu_tb_exec(unsigned int cpu_index, void *udata) +{ + BlockInfo *bi = (BlockInfo *) udata; + ExecState us, them; + ssize_t bytes; + ExecInfo *exec; + + us.pc = bi->pc; + us.insn_count = insn_count; + + /* + * Write our current position to the other end. If we fail the + * other end has probably died and we should shut down gracefully. + */ + bytes = write(socket_fd, &us, sizeof(ExecState)); + if (bytes < sizeof(ExecState)) { + qemu_plugin_outs(bytes < 0 ? + "problem writing to socket" : + "wrote less than expected to socket"); + qemu_plugin_uninstall(our_id, plugin_cleanup); + return; + } + + /* + * Now read where our peer has reached. Again a failure probably + * indicates the other end died and we should close down cleanly. + */ + bytes = read(socket_fd, &them, sizeof(ExecState)); + if (bytes < sizeof(ExecState)) { + qemu_plugin_outs(bytes < 0 ? + "problem reading from socket" : + "read less than expected"); + qemu_plugin_uninstall(our_id, plugin_cleanup); + return; + } + + /* + * Compare and report if we have diverged. + */ + if (us.pc != them.pc) { + report_divergance(&us, &them); + } + + /* + * Assume this block will execute fully and record it + * in the execution log. + */ + insn_count += bi->insns; + bb_count++; + exec = g_new0(ExecInfo, 1); + exec->block = bi; + exec->insn_count = insn_count; + exec->block_count = bb_count; + log = g_slist_prepend(log, exec); +} + +static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) +{ + BlockInfo *bi = g_new0(BlockInfo, 1); + bi->pc = qemu_plugin_tb_vaddr(tb); + bi->insns = qemu_plugin_tb_n_insns(tb); + + /* save a reference so we can free later */ + blocks = g_slist_prepend(blocks, bi); + qemu_plugin_register_vcpu_tb_exec_cb(tb, vcpu_tb_exec, + QEMU_PLUGIN_CB_NO_REGS, (void *)bi); +} + + +/* + * Instead of encoding master/slave status into what is essentially + * two peers we shall just take the simple approach of checking for + * the existence of the pipe and assuming if it's not there we are the + * first process. + */ +static bool setup_socket(const char *path) +{ + struct sockaddr_un sockaddr; + int fd; + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + perror("create socket"); + return false; + } + + sockaddr.sun_family = AF_UNIX; + g_strlcpy(sockaddr.sun_path, path, sizeof(sockaddr.sun_path) - 1); + if (bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) { + perror("bind socket"); + close(fd); + return false; + } + + /* remember to clean-up */ + path_to_unlink = g_strdup(path); + + if (listen(fd, 1) < 0) { + perror("listen socket"); + close(fd); + return false; + } + + socket_fd = accept(fd, NULL, NULL); + if (socket_fd < 0 && errno != EINTR) { + perror("accept socket"); + close(fd); + return false; + } + + qemu_plugin_outs("setup_socket::ready\n"); + + close(fd); + return true; +} + +static bool connect_socket(const char *path) +{ + int fd; + struct sockaddr_un sockaddr; + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + perror("create socket"); + return false; + } + + sockaddr.sun_family = AF_UNIX; + g_strlcpy(sockaddr.sun_path, path, sizeof(sockaddr.sun_path) - 1); + + if (connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) { + perror("failed to connect"); + close(fd); + return false; + } + + qemu_plugin_outs("connect_socket::ready\n"); + + socket_fd = fd; + return true; +} + +static bool setup_unix_socket(const char *path) +{ + if (g_file_test(path, G_FILE_TEST_EXISTS)) { + return connect_socket(path); + } else { + return setup_socket(path); + } +} + + +QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, + const qemu_info_t *info, + int argc, char **argv) +{ + int i; + + if (!argc || !argv[0]) { + qemu_plugin_outs("Need a socket path to talk to other instance."); + return -1; + } + + for (i = 0; i < argc; i++) { + char *p = argv[i]; + if (strcmp(p, "verbose") == 0) { + verbose = true; + } else if (!setup_unix_socket(argv[0])) { + qemu_plugin_outs("Failed to setup socket for communications."); + return -1; + } + } + + our_id = id; + + 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/contrib/rdmacm-mux/Makefile.objs b/contrib/rdmacm-mux/Makefile.objs deleted file mode 100644 index 3df744af89a3a86f9ea8d3b4af2bfa7dbaaeb47d..0000000000000000000000000000000000000000 --- a/contrib/rdmacm-mux/Makefile.objs +++ /dev/null @@ -1,3 +0,0 @@ -ifdef CONFIG_PVRDMA -rdmacm-mux-obj-y = main.o -endif diff --git a/contrib/rdmacm-mux/meson.build b/contrib/rdmacm-mux/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..6cc5016747684fd5e144d31f257b7547c8b06154 --- /dev/null +++ b/contrib/rdmacm-mux/meson.build @@ -0,0 +1,9 @@ +if 'CONFIG_PVRDMA' in config_host + # if not found, CONFIG_PVRDMA should not be set + # FIXME: broken on big endian architectures + libumad = cc.find_library('ibumad', required: true) + executable('rdmacm-mux', files('main.c'), + dependencies: [glib, libumad], + build_by_default: false, + install: false) +endif diff --git a/contrib/vhost-user-blk/Makefile.objs b/contrib/vhost-user-blk/Makefile.objs deleted file mode 100644 index 72e2cdc3addb6b583a0824bf4a6eedc140b91a14..0000000000000000000000000000000000000000 --- a/contrib/vhost-user-blk/Makefile.objs +++ /dev/null @@ -1 +0,0 @@ -vhost-user-blk-obj-y = vhost-user-blk.o diff --git a/contrib/vhost-user-blk/meson.build b/contrib/vhost-user-blk/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..5db8cc3fe2b3de5a67ab5cc8a81cad046d8e84fd --- /dev/null +++ b/contrib/vhost-user-blk/meson.build @@ -0,0 +1,6 @@ +# FIXME: broken on 32-bit architectures +executable('vhost-user-blk', files('vhost-user-blk.c'), + link_with: libvhost_user, + dependencies: qemuutil, + build_by_default: false, + install: false) diff --git a/contrib/vhost-user-blk/vhost-user-blk.c b/contrib/vhost-user-blk/vhost-user-blk.c index 6fd91c7e9940bbac9b429b61a9eef1107da7e16c..dc981bf945342090233f4f9d8768938dbc6efe6c 100644 --- a/contrib/vhost-user-blk/vhost-user-blk.c +++ b/contrib/vhost-user-blk/vhost-user-blk.c @@ -382,9 +382,7 @@ vub_get_features(VuDev *dev) 1ull << VIRTIO_BLK_F_DISCARD | 1ull << VIRTIO_BLK_F_WRITE_ZEROES | #endif - 1ull << VIRTIO_BLK_F_CONFIG_WCE | - 1ull << VIRTIO_F_VERSION_1 | - 1ull << VHOST_USER_F_PROTOCOL_FEATURES; + 1ull << VIRTIO_BLK_F_CONFIG_WCE; if (vdev_blk->enable_ro) { features |= 1ull << VIRTIO_BLK_F_RO; @@ -406,6 +404,8 @@ vub_get_config(VuDev *vu_dev, uint8_t *config, uint32_t len) VugDev *gdev; VubDev *vdev_blk; + g_return_val_if_fail(len <= sizeof(struct virtio_blk_config), -1); + gdev = container_of(vu_dev, VugDev, parent); vdev_blk = container_of(gdev, VubDev, parent); memcpy(config, &vdev_blk->blkcfg, len); @@ -476,7 +476,7 @@ static int unix_sock_new(char *unix_fn) assert(unix_fn); sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock <= 0) { + if (sock < 0) { perror("socket"); return -1; } diff --git a/contrib/vhost-user-gpu/Makefile.objs b/contrib/vhost-user-gpu/Makefile.objs deleted file mode 100644 index 09296091be405518e8ac42bed9abfb118cee559e..0000000000000000000000000000000000000000 --- a/contrib/vhost-user-gpu/Makefile.objs +++ /dev/null @@ -1,10 +0,0 @@ -vhost-user-gpu-obj-y = vhost-user-gpu.o virgl.o vugbm.o - -vhost-user-gpu.o-cflags := $(PIXMAN_CFLAGS) $(GBM_CFLAGS) -vhost-user-gpu.o-libs := $(PIXMAN_LIBS) - -virgl.o-cflags := $(VIRGL_CFLAGS) $(GBM_CFLAGS) -virgl.o-libs := $(VIRGL_LIBS) - -vugbm.o-cflags := $(GBM_CFLAGS) -vugbm.o-libs := $(GBM_LIBS) diff --git a/contrib/vhost-user-gpu/meson.build b/contrib/vhost-user-gpu/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..c487ca72c1ff325ca476b93c519621d6ba5b1fd9 --- /dev/null +++ b/contrib/vhost-user-gpu/meson.build @@ -0,0 +1,14 @@ +if 'CONFIG_TOOLS' in config_host and 'CONFIG_VIRGL' in config_host \ + and 'CONFIG_GBM' in config_host and 'CONFIG_LINUX' in config_host \ + and pixman.found() + executable('vhost-user-gpu', files('vhost-user-gpu.c', 'virgl.c', 'vugbm.c'), + link_with: libvhost_user, + dependencies: [qemuutil, pixman, gbm, virgl], + install: true, + install_dir: get_option('libexecdir')) + + configure_file(input: '50-qemu-gpu.json.in', + output: '50-qemu-gpu.json', + configuration: { 'libexecdir' : get_option('prefix') / get_option('libexecdir') }, + install_dir: qemu_datadir / 'vhost-user') +endif diff --git a/contrib/vhost-user-input/Makefile.objs b/contrib/vhost-user-input/Makefile.objs deleted file mode 100644 index b1fad90d51b6a2b0d71ed105168170969b160919..0000000000000000000000000000000000000000 --- a/contrib/vhost-user-input/Makefile.objs +++ /dev/null @@ -1 +0,0 @@ -vhost-user-input-obj-y = main.o diff --git a/contrib/vhost-user-input/meson.build b/contrib/vhost-user-input/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..1eeb1329d9e220c4caf87d38526650dac08a7a89 --- /dev/null +++ b/contrib/vhost-user-input/meson.build @@ -0,0 +1,5 @@ +executable('vhost-user-input', files('main.c'), + link_with: libvhost_user, + dependencies: qemuutil, + build_by_default: targetos == 'linux', + install: false) diff --git a/contrib/vhost-user-scsi/Makefile.objs b/contrib/vhost-user-scsi/Makefile.objs deleted file mode 100644 index e83a38a85bc2adb7a63ded2d75d92e7fc19e9bf7..0000000000000000000000000000000000000000 --- a/contrib/vhost-user-scsi/Makefile.objs +++ /dev/null @@ -1 +0,0 @@ -vhost-user-scsi-obj-y = vhost-user-scsi.o diff --git a/contrib/vhost-user-scsi/meson.build b/contrib/vhost-user-scsi/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..257cbffc8e5b1972de1bbb8bf28765d37cf7420e --- /dev/null +++ b/contrib/vhost-user-scsi/meson.build @@ -0,0 +1,7 @@ +if 'CONFIG_LIBISCSI' in config_host + executable('vhost-user-scsi', files('vhost-user-scsi.c'), + link_with: libvhost_user, + dependencies: [qemuutil, libiscsi], + build_by_default: targetos == 'linux', + install: false) +endif diff --git a/contrib/vhost-user-scsi/vhost-user-scsi.c b/contrib/vhost-user-scsi/vhost-user-scsi.c index 7a1db164c84b2052356ed4fdc86127f355fec7c0..0f9ba4b2a22d3254ec1cf8ddc6d961be4d48ec62 100644 --- a/contrib/vhost-user-scsi/vhost-user-scsi.c +++ b/contrib/vhost-user-scsi/vhost-user-scsi.c @@ -12,7 +12,9 @@ #include "qemu/osdep.h" #include +#define inline __attribute__((gnu_inline)) /* required for libiscsi v1.9.0 */ #include +#undef inline #include "contrib/libvhost-user/libvhost-user-glib.h" #include "standard-headers/linux/virtio_scsi.h" @@ -318,7 +320,7 @@ static int unix_sock_new(char *unix_fn) assert(unix_fn); sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock <= 0) { + if (sock < 0) { perror("socket"); return -1; } diff --git a/cpu.c b/cpu.c new file mode 100644 index 0000000000000000000000000000000000000000..0be5dcb6f3e18fcc5d8c262feca5ac394b04a13f --- /dev/null +++ b/cpu.c @@ -0,0 +1,452 @@ +/* + * Target-specific parts of the CPU object + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qapi/error.h" + +#include "exec/target_page.h" +#include "hw/qdev-core.h" +#include "hw/qdev-properties.h" +#include "qemu/error-report.h" +#include "migration/vmstate.h" +#ifdef CONFIG_USER_ONLY +#include "qemu.h" +#else +#include "exec/address-spaces.h" +#endif +#include "sysemu/tcg.h" +#include "sysemu/kvm.h" +#include "sysemu/replay.h" +#include "translate-all.h" +#include "exec/log.h" + +uintptr_t qemu_host_page_size; +intptr_t qemu_host_page_mask; + +#ifndef CONFIG_USER_ONLY +static int cpu_common_post_load(void *opaque, int version_id) +{ + CPUState *cpu = opaque; + + /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the + version_id is increased. */ + cpu->interrupt_request &= ~0x01; + tlb_flush(cpu); + + /* loadvm has just updated the content of RAM, bypassing the + * usual mechanisms that ensure we flush TBs for writes to + * memory we've translated code from. So we must flush all TBs, + * which will now be stale. + */ + tb_flush(cpu); + + return 0; +} + +static int cpu_common_pre_load(void *opaque) +{ + CPUState *cpu = opaque; + + cpu->exception_index = -1; + + return 0; +} + +static bool cpu_common_exception_index_needed(void *opaque) +{ + CPUState *cpu = opaque; + + return tcg_enabled() && cpu->exception_index != -1; +} + +static const VMStateDescription vmstate_cpu_common_exception_index = { + .name = "cpu_common/exception_index", + .version_id = 1, + .minimum_version_id = 1, + .needed = cpu_common_exception_index_needed, + .fields = (VMStateField[]) { + VMSTATE_INT32(exception_index, CPUState), + VMSTATE_END_OF_LIST() + } +}; + +static bool cpu_common_crash_occurred_needed(void *opaque) +{ + CPUState *cpu = opaque; + + return cpu->crash_occurred; +} + +static const VMStateDescription vmstate_cpu_common_crash_occurred = { + .name = "cpu_common/crash_occurred", + .version_id = 1, + .minimum_version_id = 1, + .needed = cpu_common_crash_occurred_needed, + .fields = (VMStateField[]) { + VMSTATE_BOOL(crash_occurred, CPUState), + VMSTATE_END_OF_LIST() + } +}; + +const VMStateDescription vmstate_cpu_common = { + .name = "cpu_common", + .version_id = 1, + .minimum_version_id = 1, + .pre_load = cpu_common_pre_load, + .post_load = cpu_common_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT32(halted, CPUState), + VMSTATE_UINT32(interrupt_request, CPUState), + VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription*[]) { + &vmstate_cpu_common_exception_index, + &vmstate_cpu_common_crash_occurred, + NULL + } +}; +#endif + +void cpu_exec_unrealizefn(CPUState *cpu) +{ + CPUClass *cc = CPU_GET_CLASS(cpu); + + tlb_destroy(cpu); + cpu_list_remove(cpu); + +#ifdef CONFIG_USER_ONLY + assert(cc->vmsd == NULL); +#else + if (cc->vmsd != NULL) { + vmstate_unregister(NULL, cc->vmsd, cpu); + } + if (qdev_get_vmsd(DEVICE(cpu)) == NULL) { + vmstate_unregister(NULL, &vmstate_cpu_common, cpu); + } + tcg_iommu_free_notifier_list(cpu); +#endif +} + +Property cpu_common_props[] = { +#ifndef CONFIG_USER_ONLY + /* Create a memory property for softmmu CPU object, + * so users can wire up its memory. (This can't go in hw/core/cpu.c + * because that file is compiled only once for both user-mode + * and system builds.) The default if no link is set up is to use + * the system address space. + */ + DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION, + MemoryRegion *), +#endif + DEFINE_PROP_BOOL("start-powered-off", CPUState, start_powered_off, false), + DEFINE_PROP_END_OF_LIST(), +}; + +void cpu_exec_initfn(CPUState *cpu) +{ + cpu->as = NULL; + cpu->num_ases = 0; + +#ifndef CONFIG_USER_ONLY + cpu->thread_id = qemu_get_thread_id(); + cpu->memory = get_system_memory(); + object_ref(OBJECT(cpu->memory)); +#endif +} + +void cpu_exec_realizefn(CPUState *cpu, Error **errp) +{ + CPUClass *cc = CPU_GET_CLASS(cpu); + static bool tcg_target_initialized; + + cpu_list_add(cpu); + + if (tcg_enabled() && !tcg_target_initialized) { + tcg_target_initialized = true; + cc->tcg_initialize(); + } + tlb_init(cpu); + + qemu_plugin_vcpu_init_hook(cpu); + +#ifdef CONFIG_USER_ONLY + assert(cc->vmsd == NULL); +#else /* !CONFIG_USER_ONLY */ + if (qdev_get_vmsd(DEVICE(cpu)) == NULL) { + vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu); + } + if (cc->vmsd != NULL) { + vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu); + } + + tcg_iommu_init_notifier_list(cpu); +#endif +} + +const char *parse_cpu_option(const char *cpu_option) +{ + ObjectClass *oc; + CPUClass *cc; + gchar **model_pieces; + const char *cpu_type; + + model_pieces = g_strsplit(cpu_option, ",", 2); + if (!model_pieces[0]) { + error_report("-cpu option cannot be empty"); + exit(1); + } + + oc = cpu_class_by_name(CPU_RESOLVING_TYPE, model_pieces[0]); + if (oc == NULL) { + error_report("unable to find CPU model '%s'", model_pieces[0]); + g_strfreev(model_pieces); + exit(EXIT_FAILURE); + } + + cpu_type = object_class_get_name(oc); + cc = CPU_CLASS(oc); + cc->parse_features(cpu_type, model_pieces[1], &error_fatal); + g_strfreev(model_pieces); + return cpu_type; +} + +#if defined(CONFIG_USER_ONLY) +void tb_invalidate_phys_addr(target_ulong addr) +{ + mmap_lock(); + tb_invalidate_phys_page_range(addr, addr + 1); + mmap_unlock(); +} + +static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) +{ + tb_invalidate_phys_addr(pc); +} +#else +void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs) +{ + ram_addr_t ram_addr; + MemoryRegion *mr; + hwaddr l = 1; + + if (!tcg_enabled()) { + return; + } + + RCU_READ_LOCK_GUARD(); + mr = address_space_translate(as, addr, &addr, &l, false, attrs); + if (!(memory_region_is_ram(mr) + || memory_region_is_romd(mr))) { + return; + } + ram_addr = memory_region_get_ram_addr(mr) + addr; + tb_invalidate_phys_page_range(ram_addr, ram_addr + 1); +} + +static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) +{ + /* + * There may not be a virtual to physical translation for the pc + * right now, but there may exist cached TB for this pc. + * Flush the whole TB cache to force re-translation of such TBs. + * This is heavyweight, but we're debugging anyway. + */ + tb_flush(cpu); +} +#endif + +/* Add a breakpoint. */ +int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, + CPUBreakpoint **breakpoint) +{ + CPUBreakpoint *bp; + + bp = g_malloc(sizeof(*bp)); + + bp->pc = pc; + bp->flags = flags; + + /* keep all GDB-injected breakpoints in front */ + if (flags & BP_GDB) { + QTAILQ_INSERT_HEAD(&cpu->breakpoints, bp, entry); + } else { + QTAILQ_INSERT_TAIL(&cpu->breakpoints, bp, entry); + } + + breakpoint_invalidate(cpu, pc); + + if (breakpoint) { + *breakpoint = bp; + } + return 0; +} + +/* Remove a specific breakpoint. */ +int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags) +{ + CPUBreakpoint *bp; + + QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { + if (bp->pc == pc && bp->flags == flags) { + cpu_breakpoint_remove_by_ref(cpu, bp); + return 0; + } + } + return -ENOENT; +} + +/* Remove a specific breakpoint by reference. */ +void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint) +{ + QTAILQ_REMOVE(&cpu->breakpoints, breakpoint, entry); + + breakpoint_invalidate(cpu, breakpoint->pc); + + g_free(breakpoint); +} + +/* Remove all matching breakpoints. */ +void cpu_breakpoint_remove_all(CPUState *cpu, int mask) +{ + CPUBreakpoint *bp, *next; + + QTAILQ_FOREACH_SAFE(bp, &cpu->breakpoints, entry, next) { + if (bp->flags & mask) { + cpu_breakpoint_remove_by_ref(cpu, bp); + } + } +} + +/* enable or disable single step mode. EXCP_DEBUG is returned by the + CPU loop after each instruction */ +void cpu_single_step(CPUState *cpu, int enabled) +{ + if (cpu->singlestep_enabled != enabled) { + cpu->singlestep_enabled = enabled; + if (kvm_enabled()) { + kvm_update_guest_debug(cpu, 0); + } else { + /* must flush all the translated code to avoid inconsistencies */ + /* XXX: only flush what is necessary */ + tb_flush(cpu); + } + } +} + +void cpu_abort(CPUState *cpu, const char *fmt, ...) +{ + va_list ap; + va_list ap2; + + va_start(ap, fmt); + va_copy(ap2, ap); + fprintf(stderr, "qemu: fatal: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + cpu_dump_state(cpu, stderr, CPU_DUMP_FPU | CPU_DUMP_CCOP); + if (qemu_log_separate()) { + FILE *logfile = qemu_log_lock(); + qemu_log("qemu: fatal: "); + qemu_log_vprintf(fmt, ap2); + qemu_log("\n"); + log_cpu_state(cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP); + qemu_log_flush(); + qemu_log_unlock(logfile); + qemu_log_close(); + } + va_end(ap2); + va_end(ap); + replay_finish(); +#if defined(CONFIG_USER_ONLY) + { + struct sigaction act; + sigfillset(&act.sa_mask); + act.sa_handler = SIG_DFL; + act.sa_flags = 0; + sigaction(SIGABRT, &act, NULL); + } +#endif + abort(); +} + +/* physical memory access (slow version, mainly for debug) */ +#if defined(CONFIG_USER_ONLY) +int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr, + void *ptr, target_ulong len, bool is_write) +{ + int flags; + target_ulong l, page; + void * p; + uint8_t *buf = ptr; + + while (len > 0) { + page = addr & TARGET_PAGE_MASK; + l = (page + TARGET_PAGE_SIZE) - addr; + if (l > len) + l = len; + flags = page_get_flags(page); + if (!(flags & PAGE_VALID)) + return -1; + if (is_write) { + if (!(flags & PAGE_WRITE)) + return -1; + /* XXX: this code should not depend on lock_user */ + if (!(p = lock_user(VERIFY_WRITE, addr, l, 0))) + return -1; + memcpy(p, buf, l); + unlock_user(p, addr, l); + } else { + if (!(flags & PAGE_READ)) + return -1; + /* XXX: this code should not depend on lock_user */ + if (!(p = lock_user(VERIFY_READ, addr, l, 1))) + return -1; + memcpy(buf, p, l); + unlock_user(p, addr, 0); + } + len -= l; + buf += l; + addr += l; + } + return 0; +} +#endif + +bool target_words_bigendian(void) +{ +#if defined(TARGET_WORDS_BIGENDIAN) + return true; +#else + return false; +#endif +} + +void page_size_init(void) +{ + /* NOTE: we can always suppose that qemu_host_page_size >= + TARGET_PAGE_SIZE */ + if (qemu_host_page_size == 0) { + qemu_host_page_size = qemu_real_host_page_size; + } + if (qemu_host_page_size < TARGET_PAGE_SIZE) { + qemu_host_page_size = TARGET_PAGE_SIZE; + } + qemu_host_page_mask = -(intptr_t)qemu_host_page_size; +} diff --git a/cpus-common.c b/cpus-common.c index 55d5df89237ff625ec75d2048f7f04a6664d76ad..6e73d3e58dac6b6f4e117d56f5020d8496f17439 100644 --- a/cpus-common.c +++ b/cpus-common.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -61,15 +61,19 @@ static bool cpu_index_auto_assigned; static int cpu_get_free_index(void) { CPUState *some_cpu; - int cpu_index = 0; + int max_cpu_index = 0; cpu_index_auto_assigned = true; CPU_FOREACH(some_cpu) { - cpu_index++; + if (some_cpu->cpu_index >= max_cpu_index) { + max_cpu_index = some_cpu->cpu_index + 1; + } } - return cpu_index; + return max_cpu_index; } +CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus); + void cpu_list_add(CPUState *cpu) { QEMU_LOCK_GUARD(&qemu_cpu_list_lock); @@ -90,14 +94,28 @@ void cpu_list_remove(CPUState *cpu) return; } - assert(!(cpu_index_auto_assigned && cpu != QTAILQ_LAST(&cpus))); - QTAILQ_REMOVE_RCU(&cpus, cpu, node); cpu->cpu_index = UNASSIGNED_CPU_INDEX; } +CPUState *qemu_get_cpu(int index) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + if (cpu->cpu_index == index) { + return cpu; + } + } + + return NULL; +} + +/* current CPU in the current thread. It is only valid inside cpu_exec() */ +__thread CPUState *current_cpu; + struct qemu_work_item { - struct qemu_work_item *next; + QSIMPLEQ_ENTRY(qemu_work_item) node; run_on_cpu_func func; run_on_cpu_data data; bool free, exclusive, done; @@ -106,13 +124,7 @@ struct qemu_work_item { static void queue_work_on_cpu(CPUState *cpu, struct qemu_work_item *wi) { qemu_mutex_lock(&cpu->work_mutex); - if (cpu->queued_work_first == NULL) { - cpu->queued_work_first = wi; - } else { - cpu->queued_work_last->next = wi; - } - cpu->queued_work_last = wi; - wi->next = NULL; + QSIMPLEQ_INSERT_TAIL(&cpu->work_list, wi, node); wi->done = false; qemu_mutex_unlock(&cpu->work_mutex); @@ -136,7 +148,7 @@ void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data, wi.exclusive = false; queue_work_on_cpu(cpu, &wi); - while (!atomic_mb_read(&wi.done)) { + while (!qatomic_mb_read(&wi.done)) { CPUState *self_cpu = current_cpu; qemu_cond_wait(&qemu_work_cond, mutex); @@ -176,20 +188,20 @@ void start_exclusive(void) exclusive_idle(); /* Make all other cpus stop executing. */ - atomic_set(&pending_cpus, 1); + qatomic_set(&pending_cpus, 1); /* Write pending_cpus before reading other_cpu->running. */ smp_mb(); running_cpus = 0; CPU_FOREACH(other_cpu) { - if (atomic_read(&other_cpu->running)) { + if (qatomic_read(&other_cpu->running)) { other_cpu->has_waiter = true; running_cpus++; qemu_cpu_kick(other_cpu); } } - atomic_set(&pending_cpus, running_cpus + 1); + qatomic_set(&pending_cpus, running_cpus + 1); while (pending_cpus > 1) { qemu_cond_wait(&exclusive_cond, &qemu_cpu_list_lock); } @@ -208,7 +220,7 @@ void end_exclusive(void) current_cpu->in_exclusive_context = false; qemu_mutex_lock(&qemu_cpu_list_lock); - atomic_set(&pending_cpus, 0); + qatomic_set(&pending_cpus, 0); qemu_cond_broadcast(&exclusive_resume); qemu_mutex_unlock(&qemu_cpu_list_lock); } @@ -216,7 +228,7 @@ void end_exclusive(void) /* Wait for exclusive ops to finish, and begin cpu execution. */ void cpu_exec_start(CPUState *cpu) { - atomic_set(&cpu->running, true); + qatomic_set(&cpu->running, true); /* Write cpu->running before reading pending_cpus. */ smp_mb(); @@ -234,17 +246,17 @@ void cpu_exec_start(CPUState *cpu) * 3. pending_cpus == 0. Then start_exclusive is definitely going to * see cpu->running == true, and it will kick the CPU. */ - if (unlikely(atomic_read(&pending_cpus))) { + if (unlikely(qatomic_read(&pending_cpus))) { QEMU_LOCK_GUARD(&qemu_cpu_list_lock); if (!cpu->has_waiter) { /* Not counted in pending_cpus, let the exclusive item * run. Since we have the lock, just set cpu->running to true * while holding it; no need to check pending_cpus again. */ - atomic_set(&cpu->running, false); + qatomic_set(&cpu->running, false); exclusive_idle(); /* Now pending_cpus is zero. */ - atomic_set(&cpu->running, true); + qatomic_set(&cpu->running, true); } else { /* Counted in pending_cpus, go ahead and release the * waiter at cpu_exec_end. @@ -256,7 +268,7 @@ void cpu_exec_start(CPUState *cpu) /* Mark cpu as not executing, and release pending exclusive ops. */ void cpu_exec_end(CPUState *cpu) { - atomic_set(&cpu->running, false); + qatomic_set(&cpu->running, false); /* Write cpu->running before reading pending_cpus. */ smp_mb(); @@ -276,11 +288,11 @@ void cpu_exec_end(CPUState *cpu) * see cpu->running == false, and it can ignore this CPU until the * next cpu_exec_start. */ - if (unlikely(atomic_read(&pending_cpus))) { + if (unlikely(qatomic_read(&pending_cpus))) { QEMU_LOCK_GUARD(&qemu_cpu_list_lock); if (cpu->has_waiter) { cpu->has_waiter = false; - atomic_set(&pending_cpus, pending_cpus - 1); + qatomic_set(&pending_cpus, pending_cpus - 1); if (pending_cpus == 1) { qemu_cond_signal(&exclusive_cond); } @@ -306,17 +318,14 @@ void process_queued_cpu_work(CPUState *cpu) { struct qemu_work_item *wi; - if (cpu->queued_work_first == NULL) { + qemu_mutex_lock(&cpu->work_mutex); + if (QSIMPLEQ_EMPTY(&cpu->work_list)) { + qemu_mutex_unlock(&cpu->work_mutex); return; } - - qemu_mutex_lock(&cpu->work_mutex); - while (cpu->queued_work_first != NULL) { - wi = cpu->queued_work_first; - cpu->queued_work_first = wi->next; - if (!cpu->queued_work_first) { - cpu->queued_work_last = NULL; - } + while (!QSIMPLEQ_EMPTY(&cpu->work_list)) { + wi = QSIMPLEQ_FIRST(&cpu->work_list); + QSIMPLEQ_REMOVE_HEAD(&cpu->work_list, node); qemu_mutex_unlock(&cpu->work_mutex); if (wi->exclusive) { /* Running work items outside the BQL avoids the following deadlock: @@ -337,7 +346,7 @@ void process_queued_cpu_work(CPUState *cpu) if (wi->free) { g_free(wi); } else { - atomic_mb_set(&wi->done, true); + qatomic_mb_set(&wi->done, true); } } qemu_mutex_unlock(&cpu->work_mutex); diff --git a/cpus.c b/cpus.c deleted file mode 100644 index 5670c96bcfa62713c97164f88f998f5f7421cf98..0000000000000000000000000000000000000000 --- a/cpus.c +++ /dev/null @@ -1,2290 +0,0 @@ -/* - * QEMU System Emulator - * - * Copyright (c) 2003-2008 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "qemu/config-file.h" -#include "qemu/cutils.h" -#include "migration/vmstate.h" -#include "monitor/monitor.h" -#include "qapi/error.h" -#include "qapi/qapi-commands-misc.h" -#include "qapi/qapi-events-run-state.h" -#include "qapi/qmp/qerror.h" -#include "qemu/error-report.h" -#include "qemu/qemu-print.h" -#include "sysemu/tcg.h" -#include "sysemu/block-backend.h" -#include "exec/gdbstub.h" -#include "sysemu/dma.h" -#include "sysemu/hw_accel.h" -#include "sysemu/kvm.h" -#include "sysemu/hax.h" -#include "sysemu/hvf.h" -#include "sysemu/whpx.h" -#include "exec/exec-all.h" - -#include "qemu/thread.h" -#include "qemu/plugin.h" -#include "sysemu/cpus.h" -#include "sysemu/qtest.h" -#include "qemu/main-loop.h" -#include "qemu/option.h" -#include "qemu/bitmap.h" -#include "qemu/seqlock.h" -#include "qemu/guest-random.h" -#include "tcg/tcg.h" -#include "hw/nmi.h" -#include "sysemu/replay.h" -#include "sysemu/runstate.h" -#include "hw/boards.h" -#include "hw/hw.h" - -#ifdef CONFIG_LINUX - -#include - -#ifndef PR_MCE_KILL -#define PR_MCE_KILL 33 -#endif - -#ifndef PR_MCE_KILL_SET -#define PR_MCE_KILL_SET 1 -#endif - -#ifndef PR_MCE_KILL_EARLY -#define PR_MCE_KILL_EARLY 1 -#endif - -#endif /* CONFIG_LINUX */ - -static QemuMutex qemu_global_mutex; - -int64_t max_delay; -int64_t max_advance; - -/* vcpu throttling controls */ -static QEMUTimer *throttle_timer; -static unsigned int throttle_percentage; - -#define CPU_THROTTLE_PCT_MIN 1 -#define CPU_THROTTLE_PCT_MAX 99 -#define CPU_THROTTLE_TIMESLICE_NS 10000000 - -bool cpu_is_stopped(CPUState *cpu) -{ - return cpu->stopped || !runstate_is_running(); -} - -static bool cpu_thread_is_idle(CPUState *cpu) -{ - if (cpu->stop || cpu->queued_work_first) { - return false; - } - if (cpu_is_stopped(cpu)) { - return true; - } - if (!cpu->halted || cpu_has_work(cpu) || - kvm_halt_in_kernel()) { - return false; - } - return true; -} - -static bool all_cpu_threads_idle(void) -{ - CPUState *cpu; - - CPU_FOREACH(cpu) { - if (!cpu_thread_is_idle(cpu)) { - return false; - } - } - return true; -} - -/***********************************************************/ -/* guest cycle counter */ - -/* Protected by TimersState seqlock */ - -static bool icount_sleep = true; -/* Arbitrarily pick 1MIPS as the minimum allowable speed. */ -#define MAX_ICOUNT_SHIFT 10 - -typedef struct TimersState { - /* Protected by BQL. */ - int64_t cpu_ticks_prev; - int64_t cpu_ticks_offset; - - /* Protect fields that can be respectively read outside the - * BQL, and written from multiple threads. - */ - QemuSeqLock vm_clock_seqlock; - QemuSpin vm_clock_lock; - - int16_t cpu_ticks_enabled; - - /* Conversion factor from emulated instructions to virtual clock ticks. */ - int16_t icount_time_shift; - - /* Compensate for varying guest execution speed. */ - int64_t qemu_icount_bias; - - int64_t vm_clock_warp_start; - int64_t cpu_clock_offset; - - /* Only written by TCG thread */ - int64_t qemu_icount; - - /* for adjusting icount */ - QEMUTimer *icount_rt_timer; - QEMUTimer *icount_vm_timer; - QEMUTimer *icount_warp_timer; -} TimersState; - -static TimersState timers_state; -bool mttcg_enabled; - - -/* The current number of executed instructions is based on what we - * originally budgeted minus the current state of the decrementing - * icount counters in extra/u16.low. - */ -static int64_t cpu_get_icount_executed(CPUState *cpu) -{ - return (cpu->icount_budget - - (cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra)); -} - -/* - * Update the global shared timer_state.qemu_icount to take into - * account executed instructions. This is done by the TCG vCPU - * thread so the main-loop can see time has moved forward. - */ -static void cpu_update_icount_locked(CPUState *cpu) -{ - int64_t executed = cpu_get_icount_executed(cpu); - cpu->icount_budget -= executed; - - atomic_set_i64(&timers_state.qemu_icount, - timers_state.qemu_icount + executed); -} - -/* - * Update the global shared timer_state.qemu_icount to take into - * account executed instructions. This is done by the TCG vCPU - * thread so the main-loop can see time has moved forward. - */ -void cpu_update_icount(CPUState *cpu) -{ - seqlock_write_lock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - cpu_update_icount_locked(cpu); - seqlock_write_unlock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); -} - -static int64_t cpu_get_icount_raw_locked(void) -{ - CPUState *cpu = current_cpu; - - if (cpu && cpu->running) { - if (!cpu->can_do_io) { - error_report("Bad icount read"); - exit(1); - } - /* Take into account what has run */ - cpu_update_icount_locked(cpu); - } - /* The read is protected by the seqlock, but needs atomic64 to avoid UB */ - return atomic_read_i64(&timers_state.qemu_icount); -} - -static int64_t cpu_get_icount_locked(void) -{ - int64_t icount = cpu_get_icount_raw_locked(); - return atomic_read_i64(&timers_state.qemu_icount_bias) + - cpu_icount_to_ns(icount); -} - -int64_t cpu_get_icount_raw(void) -{ - int64_t icount; - unsigned start; - - do { - start = seqlock_read_begin(&timers_state.vm_clock_seqlock); - icount = cpu_get_icount_raw_locked(); - } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start)); - - return icount; -} - -/* Return the virtual CPU time, based on the instruction counter. */ -int64_t cpu_get_icount(void) -{ - int64_t icount; - unsigned start; - - do { - start = seqlock_read_begin(&timers_state.vm_clock_seqlock); - icount = cpu_get_icount_locked(); - } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start)); - - return icount; -} - -int64_t cpu_icount_to_ns(int64_t icount) -{ - return icount << atomic_read(&timers_state.icount_time_shift); -} - -static int64_t cpu_get_ticks_locked(void) -{ - int64_t ticks = timers_state.cpu_ticks_offset; - if (timers_state.cpu_ticks_enabled) { - ticks += cpu_get_host_ticks(); - } - - if (timers_state.cpu_ticks_prev > ticks) { - /* Non increasing ticks may happen if the host uses software suspend. */ - timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks; - ticks = timers_state.cpu_ticks_prev; - } - - timers_state.cpu_ticks_prev = ticks; - return ticks; -} - -/* return the time elapsed in VM between vm_start and vm_stop. Unless - * icount is active, cpu_get_ticks() uses units of the host CPU cycle - * counter. - */ -int64_t cpu_get_ticks(void) -{ - int64_t ticks; - - if (use_icount) { - return cpu_get_icount(); - } - - qemu_spin_lock(&timers_state.vm_clock_lock); - ticks = cpu_get_ticks_locked(); - qemu_spin_unlock(&timers_state.vm_clock_lock); - return ticks; -} - -static int64_t cpu_get_clock_locked(void) -{ - int64_t time; - - time = timers_state.cpu_clock_offset; - if (timers_state.cpu_ticks_enabled) { - time += get_clock(); - } - - return time; -} - -/* Return the monotonic time elapsed in VM, i.e., - * the time between vm_start and vm_stop - */ -int64_t cpu_get_clock(void) -{ - int64_t ti; - unsigned start; - - do { - start = seqlock_read_begin(&timers_state.vm_clock_seqlock); - ti = cpu_get_clock_locked(); - } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start)); - - return ti; -} - -/* enable cpu_get_ticks() - * Caller must hold BQL which serves as mutex for vm_clock_seqlock. - */ -void cpu_enable_ticks(void) -{ - seqlock_write_lock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - if (!timers_state.cpu_ticks_enabled) { - timers_state.cpu_ticks_offset -= cpu_get_host_ticks(); - timers_state.cpu_clock_offset -= get_clock(); - timers_state.cpu_ticks_enabled = 1; - } - seqlock_write_unlock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); -} - -/* disable cpu_get_ticks() : the clock is stopped. You must not call - * cpu_get_ticks() after that. - * Caller must hold BQL which serves as mutex for vm_clock_seqlock. - */ -void cpu_disable_ticks(void) -{ - seqlock_write_lock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - if (timers_state.cpu_ticks_enabled) { - timers_state.cpu_ticks_offset += cpu_get_host_ticks(); - timers_state.cpu_clock_offset = cpu_get_clock_locked(); - timers_state.cpu_ticks_enabled = 0; - } - seqlock_write_unlock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); -} - -/* Correlation between real and virtual time is always going to be - fairly approximate, so ignore small variation. - When the guest is idle real and virtual time will be aligned in - the IO wait loop. */ -#define ICOUNT_WOBBLE (NANOSECONDS_PER_SECOND / 10) - -static void icount_adjust(void) -{ - int64_t cur_time; - int64_t cur_icount; - int64_t delta; - - /* Protected by TimersState mutex. */ - static int64_t last_delta; - - /* If the VM is not running, then do nothing. */ - if (!runstate_is_running()) { - return; - } - - seqlock_write_lock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - cur_time = cpu_get_clock_locked(); - cur_icount = cpu_get_icount_locked(); - - delta = cur_icount - cur_time; - /* FIXME: This is a very crude algorithm, somewhat prone to oscillation. */ - if (delta > 0 - && last_delta + ICOUNT_WOBBLE < delta * 2 - && timers_state.icount_time_shift > 0) { - /* The guest is getting too far ahead. Slow time down. */ - atomic_set(&timers_state.icount_time_shift, - timers_state.icount_time_shift - 1); - } - if (delta < 0 - && last_delta - ICOUNT_WOBBLE > delta * 2 - && timers_state.icount_time_shift < MAX_ICOUNT_SHIFT) { - /* The guest is getting too far behind. Speed time up. */ - atomic_set(&timers_state.icount_time_shift, - timers_state.icount_time_shift + 1); - } - last_delta = delta; - atomic_set_i64(&timers_state.qemu_icount_bias, - cur_icount - (timers_state.qemu_icount - << timers_state.icount_time_shift)); - seqlock_write_unlock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); -} - -static void icount_adjust_rt(void *opaque) -{ - timer_mod(timers_state.icount_rt_timer, - qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) + 1000); - icount_adjust(); -} - -static void icount_adjust_vm(void *opaque) -{ - timer_mod(timers_state.icount_vm_timer, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - NANOSECONDS_PER_SECOND / 10); - icount_adjust(); -} - -static int64_t qemu_icount_round(int64_t count) -{ - int shift = atomic_read(&timers_state.icount_time_shift); - return (count + (1 << shift) - 1) >> shift; -} - -static void icount_warp_rt(void) -{ - unsigned seq; - int64_t warp_start; - - /* The icount_warp_timer is rescheduled soon after vm_clock_warp_start - * changes from -1 to another value, so the race here is okay. - */ - do { - seq = seqlock_read_begin(&timers_state.vm_clock_seqlock); - warp_start = timers_state.vm_clock_warp_start; - } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, seq)); - - if (warp_start == -1) { - return; - } - - seqlock_write_lock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - if (runstate_is_running()) { - int64_t clock = REPLAY_CLOCK_LOCKED(REPLAY_CLOCK_VIRTUAL_RT, - cpu_get_clock_locked()); - int64_t warp_delta; - - warp_delta = clock - timers_state.vm_clock_warp_start; - if (use_icount == 2) { - /* - * In adaptive mode, do not let QEMU_CLOCK_VIRTUAL run too - * far ahead of real time. - */ - int64_t cur_icount = cpu_get_icount_locked(); - int64_t delta = clock - cur_icount; - warp_delta = MIN(warp_delta, delta); - } - atomic_set_i64(&timers_state.qemu_icount_bias, - timers_state.qemu_icount_bias + warp_delta); - } - timers_state.vm_clock_warp_start = -1; - seqlock_write_unlock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - - if (qemu_clock_expired(QEMU_CLOCK_VIRTUAL)) { - qemu_clock_notify(QEMU_CLOCK_VIRTUAL); - } -} - -static void icount_timer_cb(void *opaque) -{ - /* No need for a checkpoint because the timer already synchronizes - * with CHECKPOINT_CLOCK_VIRTUAL_RT. - */ - icount_warp_rt(); -} - -void qtest_clock_warp(int64_t dest) -{ - int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - AioContext *aio_context; - assert(qtest_enabled()); - aio_context = qemu_get_aio_context(); - while (clock < dest) { - int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, - QEMU_TIMER_ATTR_ALL); - int64_t warp = qemu_soonest_timeout(dest - clock, deadline); - - seqlock_write_lock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - atomic_set_i64(&timers_state.qemu_icount_bias, - timers_state.qemu_icount_bias + warp); - seqlock_write_unlock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - - qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL); - timerlist_run_timers(aio_context->tlg.tl[QEMU_CLOCK_VIRTUAL]); - clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - } - qemu_clock_notify(QEMU_CLOCK_VIRTUAL); -} - -void qemu_start_warp_timer(void) -{ - int64_t clock; - int64_t deadline; - - if (!use_icount) { - return; - } - - /* Nothing to do if the VM is stopped: QEMU_CLOCK_VIRTUAL timers - * do not fire, so computing the deadline does not make sense. - */ - if (!runstate_is_running()) { - return; - } - - if (replay_mode != REPLAY_MODE_PLAY) { - if (!all_cpu_threads_idle()) { - return; - } - - if (qtest_enabled()) { - /* When testing, qtest commands advance icount. */ - return; - } - - replay_checkpoint(CHECKPOINT_CLOCK_WARP_START); - } else { - /* warp clock deterministically in record/replay mode */ - if (!replay_checkpoint(CHECKPOINT_CLOCK_WARP_START)) { - /* vCPU is sleeping and warp can't be started. - It is probably a race condition: notification sent - to vCPU was processed in advance and vCPU went to sleep. - Therefore we have to wake it up for doing someting. */ - if (replay_has_checkpoint()) { - qemu_clock_notify(QEMU_CLOCK_VIRTUAL); - } - return; - } - } - - /* We want to use the earliest deadline from ALL vm_clocks */ - clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT); - deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, - ~QEMU_TIMER_ATTR_EXTERNAL); - if (deadline < 0) { - static bool notified; - if (!icount_sleep && !notified) { - warn_report("icount sleep disabled and no active timers"); - notified = true; - } - return; - } - - if (deadline > 0) { - /* - * Ensure QEMU_CLOCK_VIRTUAL proceeds even when the virtual CPU goes to - * sleep. Otherwise, the CPU might be waiting for a future timer - * interrupt to wake it up, but the interrupt never comes because - * the vCPU isn't running any insns and thus doesn't advance the - * QEMU_CLOCK_VIRTUAL. - */ - if (!icount_sleep) { - /* - * We never let VCPUs sleep in no sleep icount mode. - * If there is a pending QEMU_CLOCK_VIRTUAL timer we just advance - * to the next QEMU_CLOCK_VIRTUAL event and notify it. - * It is useful when we want a deterministic execution time, - * isolated from host latencies. - */ - seqlock_write_lock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - atomic_set_i64(&timers_state.qemu_icount_bias, - timers_state.qemu_icount_bias + deadline); - seqlock_write_unlock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - qemu_clock_notify(QEMU_CLOCK_VIRTUAL); - } else { - /* - * We do stop VCPUs and only advance QEMU_CLOCK_VIRTUAL after some - * "real" time, (related to the time left until the next event) has - * passed. The QEMU_CLOCK_VIRTUAL_RT clock will do this. - * This avoids that the warps are visible externally; for example, - * you will not be sending network packets continuously instead of - * every 100ms. - */ - seqlock_write_lock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - if (timers_state.vm_clock_warp_start == -1 - || timers_state.vm_clock_warp_start > clock) { - timers_state.vm_clock_warp_start = clock; - } - seqlock_write_unlock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - timer_mod_anticipate(timers_state.icount_warp_timer, - clock + deadline); - } - } else if (deadline == 0) { - qemu_clock_notify(QEMU_CLOCK_VIRTUAL); - } -} - -static void qemu_account_warp_timer(void) -{ - if (!use_icount || !icount_sleep) { - return; - } - - /* Nothing to do if the VM is stopped: QEMU_CLOCK_VIRTUAL timers - * do not fire, so computing the deadline does not make sense. - */ - if (!runstate_is_running()) { - return; - } - - /* warp clock deterministically in record/replay mode */ - if (!replay_checkpoint(CHECKPOINT_CLOCK_WARP_ACCOUNT)) { - return; - } - - timer_del(timers_state.icount_warp_timer); - icount_warp_rt(); -} - -static bool icount_state_needed(void *opaque) -{ - return use_icount; -} - -static bool warp_timer_state_needed(void *opaque) -{ - TimersState *s = opaque; - return s->icount_warp_timer != NULL; -} - -static bool adjust_timers_state_needed(void *opaque) -{ - TimersState *s = opaque; - return s->icount_rt_timer != NULL; -} - -/* - * Subsection for warp timer migration is optional, because may not be created - */ -static const VMStateDescription icount_vmstate_warp_timer = { - .name = "timer/icount/warp_timer", - .version_id = 1, - .minimum_version_id = 1, - .needed = warp_timer_state_needed, - .fields = (VMStateField[]) { - VMSTATE_INT64(vm_clock_warp_start, TimersState), - VMSTATE_TIMER_PTR(icount_warp_timer, TimersState), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription icount_vmstate_adjust_timers = { - .name = "timer/icount/timers", - .version_id = 1, - .minimum_version_id = 1, - .needed = adjust_timers_state_needed, - .fields = (VMStateField[]) { - VMSTATE_TIMER_PTR(icount_rt_timer, TimersState), - VMSTATE_TIMER_PTR(icount_vm_timer, TimersState), - VMSTATE_END_OF_LIST() - } -}; - -/* - * This is a subsection for icount migration. - */ -static const VMStateDescription icount_vmstate_timers = { - .name = "timer/icount", - .version_id = 1, - .minimum_version_id = 1, - .needed = icount_state_needed, - .fields = (VMStateField[]) { - VMSTATE_INT64(qemu_icount_bias, TimersState), - VMSTATE_INT64(qemu_icount, TimersState), - VMSTATE_END_OF_LIST() - }, - .subsections = (const VMStateDescription*[]) { - &icount_vmstate_warp_timer, - &icount_vmstate_adjust_timers, - NULL - } -}; - -static const VMStateDescription vmstate_timers = { - .name = "timer", - .version_id = 2, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_INT64(cpu_ticks_offset, TimersState), - VMSTATE_UNUSED(8), - VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2), - VMSTATE_END_OF_LIST() - }, - .subsections = (const VMStateDescription*[]) { - &icount_vmstate_timers, - NULL - } -}; - -static void cpu_throttle_thread(CPUState *cpu, run_on_cpu_data opaque) -{ - double pct; - double throttle_ratio; - int64_t sleeptime_ns, endtime_ns; - - if (!cpu_throttle_get_percentage()) { - return; - } - - pct = (double)cpu_throttle_get_percentage()/100; - throttle_ratio = pct / (1 - pct); - /* Add 1ns to fix double's rounding error (like 0.9999999...) */ - sleeptime_ns = (int64_t)(throttle_ratio * CPU_THROTTLE_TIMESLICE_NS + 1); - endtime_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + sleeptime_ns; - while (sleeptime_ns > 0 && !cpu->stop) { - if (sleeptime_ns > SCALE_MS) { - qemu_cond_timedwait(cpu->halt_cond, &qemu_global_mutex, - sleeptime_ns / SCALE_MS); - } else { - qemu_mutex_unlock_iothread(); - g_usleep(sleeptime_ns / SCALE_US); - qemu_mutex_lock_iothread(); - } - sleeptime_ns = endtime_ns - qemu_clock_get_ns(QEMU_CLOCK_REALTIME); - } - atomic_set(&cpu->throttle_thread_scheduled, 0); -} - -static void cpu_throttle_timer_tick(void *opaque) -{ - CPUState *cpu; - double pct; - - /* Stop the timer if needed */ - if (!cpu_throttle_get_percentage()) { - return; - } - CPU_FOREACH(cpu) { - if (!atomic_xchg(&cpu->throttle_thread_scheduled, 1)) { - async_run_on_cpu(cpu, cpu_throttle_thread, - RUN_ON_CPU_NULL); - } - } - - pct = (double)cpu_throttle_get_percentage()/100; - timer_mod(throttle_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT) + - CPU_THROTTLE_TIMESLICE_NS / (1-pct)); -} - -void cpu_throttle_set(int new_throttle_pct) -{ - /* Ensure throttle percentage is within valid range */ - new_throttle_pct = MIN(new_throttle_pct, CPU_THROTTLE_PCT_MAX); - new_throttle_pct = MAX(new_throttle_pct, CPU_THROTTLE_PCT_MIN); - - atomic_set(&throttle_percentage, new_throttle_pct); - - timer_mod(throttle_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT) + - CPU_THROTTLE_TIMESLICE_NS); -} - -void cpu_throttle_stop(void) -{ - atomic_set(&throttle_percentage, 0); -} - -bool cpu_throttle_active(void) -{ - return (cpu_throttle_get_percentage() != 0); -} - -int cpu_throttle_get_percentage(void) -{ - return atomic_read(&throttle_percentage); -} - -void cpu_ticks_init(void) -{ - seqlock_init(&timers_state.vm_clock_seqlock); - qemu_spin_init(&timers_state.vm_clock_lock); - vmstate_register(NULL, 0, &vmstate_timers, &timers_state); - throttle_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT, - cpu_throttle_timer_tick, NULL); -} - -void configure_icount(QemuOpts *opts, Error **errp) -{ - const char *option = qemu_opt_get(opts, "shift"); - bool sleep = qemu_opt_get_bool(opts, "sleep", true); - bool align = qemu_opt_get_bool(opts, "align", false); - long time_shift = -1; - - if (!option && qemu_opt_get(opts, "align")) { - error_setg(errp, "Please specify shift option when using align"); - return; - } - - if (align && !sleep) { - error_setg(errp, "align=on and sleep=off are incompatible"); - return; - } - - if (strcmp(option, "auto") != 0) { - if (qemu_strtol(option, NULL, 0, &time_shift) < 0 - || time_shift < 0 || time_shift > MAX_ICOUNT_SHIFT) { - error_setg(errp, "icount: Invalid shift value"); - return; - } - } else if (icount_align_option) { - error_setg(errp, "shift=auto and align=on are incompatible"); - return; - } else if (!icount_sleep) { - error_setg(errp, "shift=auto and sleep=off are incompatible"); - return; - } - - icount_sleep = sleep; - if (icount_sleep) { - timers_state.icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT, - icount_timer_cb, NULL); - } - - icount_align_option = align; - - if (time_shift >= 0) { - timers_state.icount_time_shift = time_shift; - use_icount = 1; - return; - } - - use_icount = 2; - - /* 125MIPS seems a reasonable initial guess at the guest speed. - It will be corrected fairly quickly anyway. */ - timers_state.icount_time_shift = 3; - - /* Have both realtime and virtual time triggers for speed adjustment. - The realtime trigger catches emulated time passing too slowly, - the virtual time trigger catches emulated time passing too fast. - Realtime triggers occur even when idle, so use them less frequently - than VM triggers. */ - timers_state.vm_clock_warp_start = -1; - timers_state.icount_rt_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL_RT, - icount_adjust_rt, NULL); - timer_mod(timers_state.icount_rt_timer, - qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) + 1000); - timers_state.icount_vm_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, - icount_adjust_vm, NULL); - timer_mod(timers_state.icount_vm_timer, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - NANOSECONDS_PER_SECOND / 10); -} - -/***********************************************************/ -/* TCG vCPU kick timer - * - * The kick timer is responsible for moving single threaded vCPU - * emulation on to the next vCPU. If more than one vCPU is running a - * timer event with force a cpu->exit so the next vCPU can get - * scheduled. - * - * The timer is removed if all vCPUs are idle and restarted again once - * idleness is complete. - */ - -static QEMUTimer *tcg_kick_vcpu_timer; -static CPUState *tcg_current_rr_cpu; - -#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10) - -static inline int64_t qemu_tcg_next_kick(void) -{ - return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + TCG_KICK_PERIOD; -} - -/* Kick the currently round-robin scheduled vCPU to next */ -static void qemu_cpu_kick_rr_next_cpu(void) -{ - CPUState *cpu; - do { - cpu = atomic_mb_read(&tcg_current_rr_cpu); - if (cpu) { - cpu_exit(cpu); - } - } while (cpu != atomic_mb_read(&tcg_current_rr_cpu)); -} - -/* Kick all RR vCPUs */ -static void qemu_cpu_kick_rr_cpus(void) -{ - CPUState *cpu; - - CPU_FOREACH(cpu) { - cpu_exit(cpu); - }; -} - -static void do_nothing(CPUState *cpu, run_on_cpu_data unused) -{ -} - -void qemu_timer_notify_cb(void *opaque, QEMUClockType type) -{ - if (!use_icount || type != QEMU_CLOCK_VIRTUAL) { - qemu_notify_event(); - return; - } - - if (qemu_in_vcpu_thread()) { - /* A CPU is currently running; kick it back out to the - * tcg_cpu_exec() loop so it will recalculate its - * icount deadline immediately. - */ - qemu_cpu_kick(current_cpu); - } else if (first_cpu) { - /* qemu_cpu_kick is not enough to kick a halted CPU out of - * qemu_tcg_wait_io_event. async_run_on_cpu, instead, - * causes cpu_thread_is_idle to return false. This way, - * handle_icount_deadline can run. - * If we have no CPUs at all for some reason, we don't - * need to do anything. - */ - async_run_on_cpu(first_cpu, do_nothing, RUN_ON_CPU_NULL); - } -} - -static void kick_tcg_thread(void *opaque) -{ - timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick()); - qemu_cpu_kick_rr_next_cpu(); -} - -static void start_tcg_kick_timer(void) -{ - assert(!mttcg_enabled); - if (!tcg_kick_vcpu_timer && CPU_NEXT(first_cpu)) { - tcg_kick_vcpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, - kick_tcg_thread, NULL); - } - if (tcg_kick_vcpu_timer && !timer_pending(tcg_kick_vcpu_timer)) { - timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick()); - } -} - -static void stop_tcg_kick_timer(void) -{ - assert(!mttcg_enabled); - if (tcg_kick_vcpu_timer && timer_pending(tcg_kick_vcpu_timer)) { - timer_del(tcg_kick_vcpu_timer); - } -} - -/***********************************************************/ -void hw_error(const char *fmt, ...) -{ - va_list ap; - CPUState *cpu; - - va_start(ap, fmt); - fprintf(stderr, "qemu: hardware error: "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - CPU_FOREACH(cpu) { - fprintf(stderr, "CPU #%d:\n", cpu->cpu_index); - cpu_dump_state(cpu, stderr, CPU_DUMP_FPU); - } - va_end(ap); - abort(); -} - -void cpu_synchronize_all_states(void) -{ - CPUState *cpu; - - CPU_FOREACH(cpu) { - cpu_synchronize_state(cpu); - /* TODO: move to cpu_synchronize_state() */ - if (hvf_enabled()) { - hvf_cpu_synchronize_state(cpu); - } - } -} - -void cpu_synchronize_all_post_reset(void) -{ - CPUState *cpu; - - CPU_FOREACH(cpu) { - cpu_synchronize_post_reset(cpu); - /* TODO: move to cpu_synchronize_post_reset() */ - if (hvf_enabled()) { - hvf_cpu_synchronize_post_reset(cpu); - } - } -} - -void cpu_synchronize_all_post_init(void) -{ - CPUState *cpu; - - CPU_FOREACH(cpu) { - cpu_synchronize_post_init(cpu); - /* TODO: move to cpu_synchronize_post_init() */ - if (hvf_enabled()) { - hvf_cpu_synchronize_post_init(cpu); - } - } -} - -void cpu_synchronize_all_pre_loadvm(void) -{ - CPUState *cpu; - - CPU_FOREACH(cpu) { - cpu_synchronize_pre_loadvm(cpu); - } -} - -static int do_vm_stop(RunState state, bool send_stop) -{ - int ret = 0; - - if (runstate_is_running()) { - runstate_set(state); - cpu_disable_ticks(); - pause_all_vcpus(); - vm_state_notify(0, state); - if (send_stop) { - qapi_event_send_stop(); - } - } - - bdrv_drain_all(); - ret = bdrv_flush_all(); - - return ret; -} - -/* Special vm_stop() variant for terminating the process. Historically clients - * did not expect a QMP STOP event and so we need to retain compatibility. - */ -int vm_shutdown(void) -{ - return do_vm_stop(RUN_STATE_SHUTDOWN, false); -} - -static bool cpu_can_run(CPUState *cpu) -{ - if (cpu->stop) { - return false; - } - if (cpu_is_stopped(cpu)) { - return false; - } - return true; -} - -static void cpu_handle_guest_debug(CPUState *cpu) -{ - gdb_set_stop_cpu(cpu); - qemu_system_debug_request(); - cpu->stopped = true; -} - -#ifdef CONFIG_LINUX -static void sigbus_reraise(void) -{ - sigset_t set; - struct sigaction action; - - memset(&action, 0, sizeof(action)); - action.sa_handler = SIG_DFL; - if (!sigaction(SIGBUS, &action, NULL)) { - raise(SIGBUS); - sigemptyset(&set); - sigaddset(&set, SIGBUS); - pthread_sigmask(SIG_UNBLOCK, &set, NULL); - } - perror("Failed to re-raise SIGBUS!\n"); - abort(); -} - -static void sigbus_handler(int n, siginfo_t *siginfo, void *ctx) -{ - if (siginfo->si_code != BUS_MCEERR_AO && siginfo->si_code != BUS_MCEERR_AR) { - sigbus_reraise(); - } - - if (current_cpu) { - /* Called asynchronously in VCPU thread. */ - if (kvm_on_sigbus_vcpu(current_cpu, siginfo->si_code, siginfo->si_addr)) { - sigbus_reraise(); - } - } else { - /* Called synchronously (via signalfd) in main thread. */ - if (kvm_on_sigbus(siginfo->si_code, siginfo->si_addr)) { - sigbus_reraise(); - } - } -} - -static void qemu_init_sigbus(void) -{ - struct sigaction action; - - memset(&action, 0, sizeof(action)); - action.sa_flags = SA_SIGINFO; - action.sa_sigaction = sigbus_handler; - sigaction(SIGBUS, &action, NULL); - - prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0); -} -#else /* !CONFIG_LINUX */ -static void qemu_init_sigbus(void) -{ -} -#endif /* !CONFIG_LINUX */ - -static QemuThread io_thread; - -/* cpu creation */ -static QemuCond qemu_cpu_cond; -/* system init */ -static QemuCond qemu_pause_cond; - -void qemu_init_cpu_loop(void) -{ - qemu_init_sigbus(); - qemu_cond_init(&qemu_cpu_cond); - qemu_cond_init(&qemu_pause_cond); - qemu_mutex_init(&qemu_global_mutex); - - qemu_thread_get_self(&io_thread); -} - -void run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data) -{ - do_run_on_cpu(cpu, func, data, &qemu_global_mutex); -} - -static void qemu_kvm_destroy_vcpu(CPUState *cpu) -{ - if (kvm_destroy_vcpu(cpu) < 0) { - error_report("kvm_destroy_vcpu failed"); - exit(EXIT_FAILURE); - } -} - -static void qemu_tcg_destroy_vcpu(CPUState *cpu) -{ -} - -static void qemu_cpu_stop(CPUState *cpu, bool exit) -{ - g_assert(qemu_cpu_is_self(cpu)); - cpu->stop = false; - cpu->stopped = true; - if (exit) { - cpu_exit(cpu); - } - qemu_cond_broadcast(&qemu_pause_cond); -} - -static void qemu_wait_io_event_common(CPUState *cpu) -{ - atomic_mb_set(&cpu->thread_kicked, false); - if (cpu->stop) { - qemu_cpu_stop(cpu, false); - } - process_queued_cpu_work(cpu); -} - -static void qemu_tcg_rr_wait_io_event(void) -{ - CPUState *cpu; - - while (all_cpu_threads_idle()) { - stop_tcg_kick_timer(); - qemu_cond_wait(first_cpu->halt_cond, &qemu_global_mutex); - } - - start_tcg_kick_timer(); - - CPU_FOREACH(cpu) { - qemu_wait_io_event_common(cpu); - } -} - -static void qemu_wait_io_event(CPUState *cpu) -{ - bool slept = false; - - while (cpu_thread_is_idle(cpu)) { - if (!slept) { - slept = true; - qemu_plugin_vcpu_idle_cb(cpu); - } - qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex); - } - if (slept) { - qemu_plugin_vcpu_resume_cb(cpu); - } - -#ifdef _WIN32 - /* Eat dummy APC queued by qemu_cpu_kick_thread. */ - if (!tcg_enabled()) { - SleepEx(0, TRUE); - } -#endif - qemu_wait_io_event_common(cpu); -} - -static void *qemu_kvm_cpu_thread_fn(void *arg) -{ - CPUState *cpu = arg; - int r; - - rcu_register_thread(); - - qemu_mutex_lock_iothread(); - qemu_thread_get_self(cpu->thread); - cpu->thread_id = qemu_get_thread_id(); - cpu->can_do_io = 1; - current_cpu = cpu; - - r = kvm_init_vcpu(cpu); - if (r < 0) { - error_report("kvm_init_vcpu failed: %s", strerror(-r)); - exit(1); - } - - kvm_init_cpu_signals(cpu); - - /* signal CPU creation */ - cpu->created = true; - qemu_cond_signal(&qemu_cpu_cond); - qemu_guest_random_seed_thread_part2(cpu->random_seed); - - do { - if (cpu_can_run(cpu)) { - r = kvm_cpu_exec(cpu); - if (r == EXCP_DEBUG) { - cpu_handle_guest_debug(cpu); - } - } - qemu_wait_io_event(cpu); - } while (!cpu->unplug || cpu_can_run(cpu)); - - qemu_kvm_destroy_vcpu(cpu); - cpu->created = false; - qemu_cond_signal(&qemu_cpu_cond); - qemu_mutex_unlock_iothread(); - rcu_unregister_thread(); - return NULL; -} - -static void *qemu_dummy_cpu_thread_fn(void *arg) -{ -#ifdef _WIN32 - error_report("qtest is not supported under Windows"); - exit(1); -#else - CPUState *cpu = arg; - sigset_t waitset; - int r; - - rcu_register_thread(); - - qemu_mutex_lock_iothread(); - qemu_thread_get_self(cpu->thread); - cpu->thread_id = qemu_get_thread_id(); - cpu->can_do_io = 1; - current_cpu = cpu; - - sigemptyset(&waitset); - sigaddset(&waitset, SIG_IPI); - - /* signal CPU creation */ - cpu->created = true; - qemu_cond_signal(&qemu_cpu_cond); - qemu_guest_random_seed_thread_part2(cpu->random_seed); - - do { - qemu_mutex_unlock_iothread(); - do { - int sig; - r = sigwait(&waitset, &sig); - } while (r == -1 && (errno == EAGAIN || errno == EINTR)); - if (r == -1) { - perror("sigwait"); - exit(1); - } - qemu_mutex_lock_iothread(); - qemu_wait_io_event(cpu); - } while (!cpu->unplug); - - qemu_mutex_unlock_iothread(); - rcu_unregister_thread(); - return NULL; -#endif -} - -static int64_t tcg_get_icount_limit(void) -{ - int64_t deadline; - - if (replay_mode != REPLAY_MODE_PLAY) { - /* - * Include all the timers, because they may need an attention. - * Too long CPU execution may create unnecessary delay in UI. - */ - deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, - QEMU_TIMER_ATTR_ALL); - /* Check realtime timers, because they help with input processing */ - deadline = qemu_soonest_timeout(deadline, - qemu_clock_deadline_ns_all(QEMU_CLOCK_REALTIME, - QEMU_TIMER_ATTR_ALL)); - - /* Maintain prior (possibly buggy) behaviour where if no deadline - * was set (as there is no QEMU_CLOCK_VIRTUAL timer) or it is more than - * INT32_MAX nanoseconds ahead, we still use INT32_MAX - * nanoseconds. - */ - if ((deadline < 0) || (deadline > INT32_MAX)) { - deadline = INT32_MAX; - } - - return qemu_icount_round(deadline); - } else { - return replay_get_instructions(); - } -} - -static void handle_icount_deadline(void) -{ - assert(qemu_in_vcpu_thread()); - if (use_icount) { - int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, - QEMU_TIMER_ATTR_ALL); - - if (deadline == 0) { - /* Wake up other AioContexts. */ - qemu_clock_notify(QEMU_CLOCK_VIRTUAL); - qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL); - } - } -} - -static void prepare_icount_for_run(CPUState *cpu) -{ - if (use_icount) { - int insns_left; - - /* These should always be cleared by process_icount_data after - * each vCPU execution. However u16.high can be raised - * asynchronously by cpu_exit/cpu_interrupt/tcg_handle_interrupt - */ - g_assert(cpu_neg(cpu)->icount_decr.u16.low == 0); - g_assert(cpu->icount_extra == 0); - - cpu->icount_budget = tcg_get_icount_limit(); - insns_left = MIN(0xffff, cpu->icount_budget); - cpu_neg(cpu)->icount_decr.u16.low = insns_left; - cpu->icount_extra = cpu->icount_budget - insns_left; - - replay_mutex_lock(); - } -} - -static void process_icount_data(CPUState *cpu) -{ - if (use_icount) { - /* Account for executed instructions */ - cpu_update_icount(cpu); - - /* Reset the counters */ - cpu_neg(cpu)->icount_decr.u16.low = 0; - cpu->icount_extra = 0; - cpu->icount_budget = 0; - - replay_account_executed_instructions(); - - replay_mutex_unlock(); - } -} - - -static int tcg_cpu_exec(CPUState *cpu) -{ - int ret; -#ifdef CONFIG_PROFILER - int64_t ti; -#endif - - assert(tcg_enabled()); -#ifdef CONFIG_PROFILER - ti = profile_getclock(); -#endif - cpu_exec_start(cpu); - ret = cpu_exec(cpu); - cpu_exec_end(cpu); -#ifdef CONFIG_PROFILER - atomic_set(&tcg_ctx->prof.cpu_exec_time, - tcg_ctx->prof.cpu_exec_time + profile_getclock() - ti); -#endif - return ret; -} - -/* Destroy any remaining vCPUs which have been unplugged and have - * finished running - */ -static void deal_with_unplugged_cpus(void) -{ - CPUState *cpu; - - CPU_FOREACH(cpu) { - if (cpu->unplug && !cpu_can_run(cpu)) { - qemu_tcg_destroy_vcpu(cpu); - cpu->created = false; - qemu_cond_signal(&qemu_cpu_cond); - break; - } - } -} - -/* Single-threaded TCG - * - * In the single-threaded case each vCPU is simulated in turn. If - * there is more than a single vCPU we create a simple timer to kick - * the vCPU and ensure we don't get stuck in a tight loop in one vCPU. - * This is done explicitly rather than relying on side-effects - * elsewhere. - */ - -static void *qemu_tcg_rr_cpu_thread_fn(void *arg) -{ - CPUState *cpu = arg; - - assert(tcg_enabled()); - rcu_register_thread(); - tcg_register_thread(); - - qemu_mutex_lock_iothread(); - qemu_thread_get_self(cpu->thread); - - cpu->thread_id = qemu_get_thread_id(); - cpu->created = true; - cpu->can_do_io = 1; - qemu_cond_signal(&qemu_cpu_cond); - qemu_guest_random_seed_thread_part2(cpu->random_seed); - - /* wait for initial kick-off after machine start */ - while (first_cpu->stopped) { - qemu_cond_wait(first_cpu->halt_cond, &qemu_global_mutex); - - /* process any pending work */ - CPU_FOREACH(cpu) { - current_cpu = cpu; - qemu_wait_io_event_common(cpu); - } - } - - start_tcg_kick_timer(); - - cpu = first_cpu; - - /* process any pending work */ - cpu->exit_request = 1; - - while (1) { - qemu_mutex_unlock_iothread(); - replay_mutex_lock(); - qemu_mutex_lock_iothread(); - /* Account partial waits to QEMU_CLOCK_VIRTUAL. */ - qemu_account_warp_timer(); - - /* Run the timers here. This is much more efficient than - * waking up the I/O thread and waiting for completion. - */ - handle_icount_deadline(); - - replay_mutex_unlock(); - - if (!cpu) { - cpu = first_cpu; - } - - while (cpu && !cpu->queued_work_first && !cpu->exit_request) { - - atomic_mb_set(&tcg_current_rr_cpu, cpu); - current_cpu = cpu; - - qemu_clock_enable(QEMU_CLOCK_VIRTUAL, - (cpu->singlestep_enabled & SSTEP_NOTIMER) == 0); - - if (cpu_can_run(cpu)) { - int r; - - qemu_mutex_unlock_iothread(); - prepare_icount_for_run(cpu); - - r = tcg_cpu_exec(cpu); - - process_icount_data(cpu); - qemu_mutex_lock_iothread(); - - if (r == EXCP_DEBUG) { - cpu_handle_guest_debug(cpu); - break; - } else if (r == EXCP_ATOMIC) { - qemu_mutex_unlock_iothread(); - cpu_exec_step_atomic(cpu); - qemu_mutex_lock_iothread(); - break; - } - } else if (cpu->stop) { - if (cpu->unplug) { - cpu = CPU_NEXT(cpu); - } - break; - } - - cpu = CPU_NEXT(cpu); - } /* while (cpu && !cpu->exit_request).. */ - - /* Does not need atomic_mb_set because a spurious wakeup is okay. */ - atomic_set(&tcg_current_rr_cpu, NULL); - - if (cpu && cpu->exit_request) { - atomic_mb_set(&cpu->exit_request, 0); - } - - if (use_icount && all_cpu_threads_idle()) { - /* - * When all cpus are sleeping (e.g in WFI), to avoid a deadlock - * in the main_loop, wake it up in order to start the warp timer. - */ - qemu_notify_event(); - } - - qemu_tcg_rr_wait_io_event(); - deal_with_unplugged_cpus(); - } - - rcu_unregister_thread(); - return NULL; -} - -static void *qemu_hax_cpu_thread_fn(void *arg) -{ - CPUState *cpu = arg; - int r; - - rcu_register_thread(); - qemu_mutex_lock_iothread(); - qemu_thread_get_self(cpu->thread); - - cpu->thread_id = qemu_get_thread_id(); - cpu->created = true; - current_cpu = cpu; - - hax_init_vcpu(cpu); - qemu_cond_signal(&qemu_cpu_cond); - qemu_guest_random_seed_thread_part2(cpu->random_seed); - - do { - if (cpu_can_run(cpu)) { - r = hax_smp_cpu_exec(cpu); - if (r == EXCP_DEBUG) { - cpu_handle_guest_debug(cpu); - } - } - - qemu_wait_io_event(cpu); - } while (!cpu->unplug || cpu_can_run(cpu)); - rcu_unregister_thread(); - return NULL; -} - -/* The HVF-specific vCPU thread function. This one should only run when the host - * CPU supports the VMX "unrestricted guest" feature. */ -static void *qemu_hvf_cpu_thread_fn(void *arg) -{ - CPUState *cpu = arg; - - int r; - - assert(hvf_enabled()); - - rcu_register_thread(); - - qemu_mutex_lock_iothread(); - qemu_thread_get_self(cpu->thread); - - cpu->thread_id = qemu_get_thread_id(); - cpu->can_do_io = 1; - current_cpu = cpu; - - hvf_init_vcpu(cpu); - - /* signal CPU creation */ - cpu->created = true; - qemu_cond_signal(&qemu_cpu_cond); - qemu_guest_random_seed_thread_part2(cpu->random_seed); - - do { - if (cpu_can_run(cpu)) { - r = hvf_vcpu_exec(cpu); - if (r == EXCP_DEBUG) { - cpu_handle_guest_debug(cpu); - } - } - qemu_wait_io_event(cpu); - } while (!cpu->unplug || cpu_can_run(cpu)); - - hvf_vcpu_destroy(cpu); - cpu->created = false; - qemu_cond_signal(&qemu_cpu_cond); - qemu_mutex_unlock_iothread(); - rcu_unregister_thread(); - return NULL; -} - -static void *qemu_whpx_cpu_thread_fn(void *arg) -{ - CPUState *cpu = arg; - int r; - - rcu_register_thread(); - - qemu_mutex_lock_iothread(); - qemu_thread_get_self(cpu->thread); - cpu->thread_id = qemu_get_thread_id(); - current_cpu = cpu; - - r = whpx_init_vcpu(cpu); - if (r < 0) { - fprintf(stderr, "whpx_init_vcpu failed: %s\n", strerror(-r)); - exit(1); - } - - /* signal CPU creation */ - cpu->created = true; - qemu_cond_signal(&qemu_cpu_cond); - qemu_guest_random_seed_thread_part2(cpu->random_seed); - - do { - if (cpu_can_run(cpu)) { - r = whpx_vcpu_exec(cpu); - if (r == EXCP_DEBUG) { - cpu_handle_guest_debug(cpu); - } - } - while (cpu_thread_is_idle(cpu)) { - qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex); - } - qemu_wait_io_event_common(cpu); - } while (!cpu->unplug || cpu_can_run(cpu)); - - whpx_destroy_vcpu(cpu); - cpu->created = false; - qemu_cond_signal(&qemu_cpu_cond); - qemu_mutex_unlock_iothread(); - rcu_unregister_thread(); - return NULL; -} - -#ifdef _WIN32 -static void CALLBACK dummy_apc_func(ULONG_PTR unused) -{ -} -#endif - -/* Multi-threaded TCG - * - * In the multi-threaded case each vCPU has its own thread. The TLS - * variable current_cpu can be used deep in the code to find the - * current CPUState for a given thread. - */ - -static void *qemu_tcg_cpu_thread_fn(void *arg) -{ - CPUState *cpu = arg; - - assert(tcg_enabled()); - g_assert(!use_icount); - - rcu_register_thread(); - tcg_register_thread(); - - qemu_mutex_lock_iothread(); - qemu_thread_get_self(cpu->thread); - - cpu->thread_id = qemu_get_thread_id(); - cpu->created = true; - cpu->can_do_io = 1; - current_cpu = cpu; - qemu_cond_signal(&qemu_cpu_cond); - qemu_guest_random_seed_thread_part2(cpu->random_seed); - - /* process any pending work */ - cpu->exit_request = 1; - - do { - if (cpu_can_run(cpu)) { - int r; - qemu_mutex_unlock_iothread(); - r = tcg_cpu_exec(cpu); - qemu_mutex_lock_iothread(); - switch (r) { - case EXCP_DEBUG: - cpu_handle_guest_debug(cpu); - break; - case EXCP_HALTED: - /* during start-up the vCPU is reset and the thread is - * kicked several times. If we don't ensure we go back - * to sleep in the halted state we won't cleanly - * start-up when the vCPU is enabled. - * - * cpu->halted should ensure we sleep in wait_io_event - */ - g_assert(cpu->halted); - break; - case EXCP_ATOMIC: - qemu_mutex_unlock_iothread(); - cpu_exec_step_atomic(cpu); - qemu_mutex_lock_iothread(); - default: - /* Ignore everything else? */ - break; - } - } - - atomic_mb_set(&cpu->exit_request, 0); - qemu_wait_io_event(cpu); - } while (!cpu->unplug || cpu_can_run(cpu)); - - qemu_tcg_destroy_vcpu(cpu); - cpu->created = false; - qemu_cond_signal(&qemu_cpu_cond); - qemu_mutex_unlock_iothread(); - rcu_unregister_thread(); - return NULL; -} - -static void qemu_cpu_kick_thread(CPUState *cpu) -{ -#ifndef _WIN32 - int err; - - if (cpu->thread_kicked) { - return; - } - cpu->thread_kicked = true; - err = pthread_kill(cpu->thread->thread, SIG_IPI); - if (err && err != ESRCH) { - fprintf(stderr, "qemu:%s: %s", __func__, strerror(err)); - exit(1); - } -#else /* _WIN32 */ - if (!qemu_cpu_is_self(cpu)) { - if (whpx_enabled()) { - whpx_vcpu_kick(cpu); - } else if (!QueueUserAPC(dummy_apc_func, cpu->hThread, 0)) { - fprintf(stderr, "%s: QueueUserAPC failed with error %lu\n", - __func__, GetLastError()); - exit(1); - } - } -#endif -} - -void qemu_cpu_kick(CPUState *cpu) -{ - qemu_cond_broadcast(cpu->halt_cond); - if (tcg_enabled()) { - if (qemu_tcg_mttcg_enabled()) { - cpu_exit(cpu); - } else { - qemu_cpu_kick_rr_cpus(); - } - } else { - if (hax_enabled()) { - /* - * FIXME: race condition with the exit_request check in - * hax_vcpu_hax_exec - */ - cpu->exit_request = 1; - } - qemu_cpu_kick_thread(cpu); - } -} - -void qemu_cpu_kick_self(void) -{ - assert(current_cpu); - qemu_cpu_kick_thread(current_cpu); -} - -bool qemu_cpu_is_self(CPUState *cpu) -{ - return qemu_thread_is_self(cpu->thread); -} - -bool qemu_in_vcpu_thread(void) -{ - return current_cpu && qemu_cpu_is_self(current_cpu); -} - -static __thread bool iothread_locked = false; - -bool qemu_mutex_iothread_locked(void) -{ - return iothread_locked; -} - -/* - * The BQL is taken from so many places that it is worth profiling the - * callers directly, instead of funneling them all through a single function. - */ -void qemu_mutex_lock_iothread_impl(const char *file, int line) -{ - QemuMutexLockFunc bql_lock = atomic_read(&qemu_bql_mutex_lock_func); - - g_assert(!qemu_mutex_iothread_locked()); - bql_lock(&qemu_global_mutex, file, line); - iothread_locked = true; -} - -void qemu_mutex_unlock_iothread(void) -{ - g_assert(qemu_mutex_iothread_locked()); - iothread_locked = false; - qemu_mutex_unlock(&qemu_global_mutex); -} - -void qemu_cond_wait_iothread(QemuCond *cond) -{ - qemu_cond_wait(cond, &qemu_global_mutex); -} - -static bool all_vcpus_paused(void) -{ - CPUState *cpu; - - CPU_FOREACH(cpu) { - if (!cpu->stopped) { - return false; - } - } - - return true; -} - -void pause_all_vcpus(void) -{ - CPUState *cpu; - - qemu_clock_enable(QEMU_CLOCK_VIRTUAL, false); - CPU_FOREACH(cpu) { - if (qemu_cpu_is_self(cpu)) { - qemu_cpu_stop(cpu, true); - } else { - cpu->stop = true; - qemu_cpu_kick(cpu); - } - } - - /* We need to drop the replay_lock so any vCPU threads woken up - * can finish their replay tasks - */ - replay_mutex_unlock(); - - while (!all_vcpus_paused()) { - qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex); - CPU_FOREACH(cpu) { - qemu_cpu_kick(cpu); - } - } - - qemu_mutex_unlock_iothread(); - replay_mutex_lock(); - qemu_mutex_lock_iothread(); -} - -void cpu_resume(CPUState *cpu) -{ - cpu->stop = false; - cpu->stopped = false; - qemu_cpu_kick(cpu); -} - -void resume_all_vcpus(void) -{ - CPUState *cpu; - - if (!runstate_is_running()) { - return; - } - - qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true); - CPU_FOREACH(cpu) { - cpu_resume(cpu); - } -} - -void cpu_remove_sync(CPUState *cpu) -{ - cpu->stop = true; - cpu->unplug = true; - qemu_cpu_kick(cpu); - qemu_mutex_unlock_iothread(); - qemu_thread_join(cpu->thread); - qemu_mutex_lock_iothread(); -} - -/* For temporary buffers for forming a name */ -#define VCPU_THREAD_NAME_SIZE 16 - -static void qemu_tcg_init_vcpu(CPUState *cpu) -{ - char thread_name[VCPU_THREAD_NAME_SIZE]; - static QemuCond *single_tcg_halt_cond; - static QemuThread *single_tcg_cpu_thread; - static int tcg_region_inited; - - assert(tcg_enabled()); - /* - * Initialize TCG regions--once. Now is a good time, because: - * (1) TCG's init context, prologue and target globals have been set up. - * (2) qemu_tcg_mttcg_enabled() works now (TCG init code runs before the - * -accel flag is processed, so the check doesn't work then). - */ - if (!tcg_region_inited) { - tcg_region_inited = 1; - tcg_region_init(); - } - - if (qemu_tcg_mttcg_enabled() || !single_tcg_cpu_thread) { - cpu->thread = g_malloc0(sizeof(QemuThread)); - cpu->halt_cond = g_malloc0(sizeof(QemuCond)); - qemu_cond_init(cpu->halt_cond); - - if (qemu_tcg_mttcg_enabled()) { - /* create a thread per vCPU with TCG (MTTCG) */ - parallel_cpus = true; - snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/TCG", - cpu->cpu_index); - - qemu_thread_create(cpu->thread, thread_name, qemu_tcg_cpu_thread_fn, - cpu, QEMU_THREAD_JOINABLE); - - } else { - /* share a single thread for all cpus with TCG */ - snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "ALL CPUs/TCG"); - qemu_thread_create(cpu->thread, thread_name, - qemu_tcg_rr_cpu_thread_fn, - cpu, QEMU_THREAD_JOINABLE); - - single_tcg_halt_cond = cpu->halt_cond; - single_tcg_cpu_thread = cpu->thread; - } -#ifdef _WIN32 - cpu->hThread = qemu_thread_get_handle(cpu->thread); -#endif - } else { - /* For non-MTTCG cases we share the thread */ - cpu->thread = single_tcg_cpu_thread; - cpu->halt_cond = single_tcg_halt_cond; - cpu->thread_id = first_cpu->thread_id; - cpu->can_do_io = 1; - cpu->created = true; - } -} - -static void qemu_hax_start_vcpu(CPUState *cpu) -{ - char thread_name[VCPU_THREAD_NAME_SIZE]; - - cpu->thread = g_malloc0(sizeof(QemuThread)); - cpu->halt_cond = g_malloc0(sizeof(QemuCond)); - qemu_cond_init(cpu->halt_cond); - - snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HAX", - cpu->cpu_index); - qemu_thread_create(cpu->thread, thread_name, qemu_hax_cpu_thread_fn, - cpu, QEMU_THREAD_JOINABLE); -#ifdef _WIN32 - cpu->hThread = qemu_thread_get_handle(cpu->thread); -#endif -} - -static void qemu_kvm_start_vcpu(CPUState *cpu) -{ - char thread_name[VCPU_THREAD_NAME_SIZE]; - - cpu->thread = g_malloc0(sizeof(QemuThread)); - cpu->halt_cond = g_malloc0(sizeof(QemuCond)); - qemu_cond_init(cpu->halt_cond); - snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/KVM", - cpu->cpu_index); - qemu_thread_create(cpu->thread, thread_name, qemu_kvm_cpu_thread_fn, - cpu, QEMU_THREAD_JOINABLE); -} - -static void qemu_hvf_start_vcpu(CPUState *cpu) -{ - char thread_name[VCPU_THREAD_NAME_SIZE]; - - /* HVF currently does not support TCG, and only runs in - * unrestricted-guest mode. */ - assert(hvf_enabled()); - - cpu->thread = g_malloc0(sizeof(QemuThread)); - cpu->halt_cond = g_malloc0(sizeof(QemuCond)); - qemu_cond_init(cpu->halt_cond); - - snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HVF", - cpu->cpu_index); - qemu_thread_create(cpu->thread, thread_name, qemu_hvf_cpu_thread_fn, - cpu, QEMU_THREAD_JOINABLE); -} - -static void qemu_whpx_start_vcpu(CPUState *cpu) -{ - char thread_name[VCPU_THREAD_NAME_SIZE]; - - cpu->thread = g_malloc0(sizeof(QemuThread)); - cpu->halt_cond = g_malloc0(sizeof(QemuCond)); - qemu_cond_init(cpu->halt_cond); - snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/WHPX", - cpu->cpu_index); - qemu_thread_create(cpu->thread, thread_name, qemu_whpx_cpu_thread_fn, - cpu, QEMU_THREAD_JOINABLE); -#ifdef _WIN32 - cpu->hThread = qemu_thread_get_handle(cpu->thread); -#endif -} - -static void qemu_dummy_start_vcpu(CPUState *cpu) -{ - char thread_name[VCPU_THREAD_NAME_SIZE]; - - cpu->thread = g_malloc0(sizeof(QemuThread)); - cpu->halt_cond = g_malloc0(sizeof(QemuCond)); - qemu_cond_init(cpu->halt_cond); - snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/DUMMY", - cpu->cpu_index); - qemu_thread_create(cpu->thread, thread_name, qemu_dummy_cpu_thread_fn, cpu, - QEMU_THREAD_JOINABLE); -} - -void qemu_init_vcpu(CPUState *cpu) -{ - MachineState *ms = MACHINE(qdev_get_machine()); - - cpu->nr_cores = ms->smp.cores; - cpu->nr_threads = ms->smp.threads; - cpu->stopped = true; - cpu->random_seed = qemu_guest_random_seed_thread_part1(); - - if (!cpu->as) { - /* If the target cpu hasn't set up any address spaces itself, - * give it the default one. - */ - cpu->num_ases = 1; - cpu_address_space_init(cpu, 0, "cpu-memory", cpu->memory); - } - - if (kvm_enabled()) { - qemu_kvm_start_vcpu(cpu); - } else if (hax_enabled()) { - qemu_hax_start_vcpu(cpu); - } else if (hvf_enabled()) { - qemu_hvf_start_vcpu(cpu); - } else if (tcg_enabled()) { - qemu_tcg_init_vcpu(cpu); - } else if (whpx_enabled()) { - qemu_whpx_start_vcpu(cpu); - } else { - qemu_dummy_start_vcpu(cpu); - } - - while (!cpu->created) { - qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex); - } -} - -void cpu_stop_current(void) -{ - if (current_cpu) { - current_cpu->stop = true; - cpu_exit(current_cpu); - } -} - -int vm_stop(RunState state) -{ - if (qemu_in_vcpu_thread()) { - qemu_system_vmstop_request_prepare(); - qemu_system_vmstop_request(state); - /* - * FIXME: should not return to device code in case - * vm_stop() has been requested. - */ - cpu_stop_current(); - return 0; - } - - return do_vm_stop(state, true); -} - -/** - * Prepare for (re)starting the VM. - * Returns -1 if the vCPUs are not to be restarted (e.g. if they are already - * running or in case of an error condition), 0 otherwise. - */ -int vm_prepare_start(void) -{ - RunState requested; - - qemu_vmstop_requested(&requested); - if (runstate_is_running() && requested == RUN_STATE__MAX) { - return -1; - } - - /* Ensure that a STOP/RESUME pair of events is emitted if a - * vmstop request was pending. The BLOCK_IO_ERROR event, for - * example, according to documentation is always followed by - * the STOP event. - */ - if (runstate_is_running()) { - qapi_event_send_stop(); - qapi_event_send_resume(); - return -1; - } - - /* We are sending this now, but the CPUs will be resumed shortly later */ - qapi_event_send_resume(); - - cpu_enable_ticks(); - runstate_set(RUN_STATE_RUNNING); - vm_state_notify(1, RUN_STATE_RUNNING); - return 0; -} - -void vm_start(void) -{ - if (!vm_prepare_start()) { - resume_all_vcpus(); - } -} - -/* does a state transition even if the VM is already stopped, - current state is forgotten forever */ -int vm_stop_force_state(RunState state) -{ - if (runstate_is_running()) { - return vm_stop(state); - } else { - runstate_set(state); - - bdrv_drain_all(); - /* Make sure to return an error if the flush in a previous vm_stop() - * failed. */ - return bdrv_flush_all(); - } -} - -void list_cpus(const char *optarg) -{ - /* XXX: implement xxx_cpu_list for targets that still miss it */ -#if defined(cpu_list) - cpu_list(); -#endif -} - -void qmp_memsave(int64_t addr, int64_t size, const char *filename, - bool has_cpu, int64_t cpu_index, Error **errp) -{ - FILE *f; - uint32_t l; - CPUState *cpu; - uint8_t buf[1024]; - int64_t orig_addr = addr, orig_size = size; - - if (!has_cpu) { - cpu_index = 0; - } - - cpu = qemu_get_cpu(cpu_index); - if (cpu == NULL) { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index", - "a CPU number"); - return; - } - - f = fopen(filename, "wb"); - if (!f) { - error_setg_file_open(errp, errno, filename); - return; - } - - while (size != 0) { - l = sizeof(buf); - if (l > size) - l = size; - if (cpu_memory_rw_debug(cpu, addr, buf, l, 0) != 0) { - error_setg(errp, "Invalid addr 0x%016" PRIx64 "/size %" PRId64 - " specified", orig_addr, orig_size); - goto exit; - } - if (fwrite(buf, 1, l, f) != l) { - error_setg(errp, QERR_IO_ERROR); - goto exit; - } - addr += l; - size -= l; - } - -exit: - fclose(f); -} - -void qmp_pmemsave(int64_t addr, int64_t size, const char *filename, - Error **errp) -{ - FILE *f; - uint32_t l; - uint8_t buf[1024]; - - f = fopen(filename, "wb"); - if (!f) { - error_setg_file_open(errp, errno, filename); - return; - } - - while (size != 0) { - l = sizeof(buf); - if (l > size) - l = size; - cpu_physical_memory_read(addr, buf, l); - if (fwrite(buf, 1, l, f) != l) { - error_setg(errp, QERR_IO_ERROR); - goto exit; - } - addr += l; - size -= l; - } - -exit: - fclose(f); -} - -void qmp_inject_nmi(Error **errp) -{ - nmi_monitor_handle(monitor_get_cpu_index(), errp); -} - -void dump_drift_info(void) -{ - if (!use_icount) { - return; - } - - qemu_printf("Host - Guest clock %"PRIi64" ms\n", - (cpu_get_clock() - cpu_get_icount())/SCALE_MS); - if (icount_align_option) { - qemu_printf("Max guest delay %"PRIi64" ms\n", - -max_delay / SCALE_MS); - qemu_printf("Max guest advance %"PRIi64" ms\n", - max_advance / SCALE_MS); - } else { - qemu_printf("Max guest delay NA\n"); - qemu_printf("Max guest advance NA\n"); - } -} diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs deleted file mode 100644 index c2a371b0b43c75b48c4f09c50fae230707be6b57..0000000000000000000000000000000000000000 --- a/crypto/Makefile.objs +++ /dev/null @@ -1,39 +0,0 @@ -crypto-obj-y = init.o -crypto-obj-y += hash.o -crypto-obj-$(CONFIG_NETTLE) += hash-nettle.o -crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += hash-gcrypt.o -crypto-obj-$(if $(CONFIG_NETTLE),n,$(if $(CONFIG_GCRYPT),n,y)) += hash-glib.o -crypto-obj-y += hmac.o -crypto-obj-$(CONFIG_NETTLE) += hmac-nettle.o -crypto-obj-$(CONFIG_GCRYPT_HMAC) += hmac-gcrypt.o -crypto-obj-$(if $(CONFIG_NETTLE),n,$(if $(CONFIG_GCRYPT_HMAC),n,y)) += hmac-glib.o -crypto-obj-y += aes.o -crypto-obj-y += desrfb.o -crypto-obj-y += cipher.o -crypto-obj-$(CONFIG_AF_ALG) += afalg.o -crypto-obj-$(CONFIG_AF_ALG) += cipher-afalg.o -crypto-obj-$(CONFIG_AF_ALG) += hash-afalg.o -crypto-obj-y += tlscreds.o -crypto-obj-y += tlscredsanon.o -crypto-obj-y += tlscredspsk.o -crypto-obj-y += tlscredsx509.o -crypto-obj-y += tlssession.o -crypto-obj-y += secret.o -crypto-obj-y += pbkdf.o -crypto-obj-$(CONFIG_NETTLE) += pbkdf-nettle.o -crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += pbkdf-gcrypt.o -crypto-obj-$(if $(CONFIG_NETTLE),n,$(if $(CONFIG_GCRYPT),n,y)) += pbkdf-stub.o -crypto-obj-y += ivgen.o -crypto-obj-y += ivgen-essiv.o -crypto-obj-y += ivgen-plain.o -crypto-obj-y += ivgen-plain64.o -crypto-obj-y += afsplit.o -crypto-obj-$(CONFIG_QEMU_PRIVATE_XTS) += xts.o -crypto-obj-y += block.o -crypto-obj-y += block-qcow.o -crypto-obj-y += block-luks.o - -util-obj-$(CONFIG_GCRYPT) += random-gcrypt.o -util-obj-$(if $(CONFIG_GCRYPT),n,$(CONFIG_GNUTLS)) += random-gnutls.o -util-obj-$(if $(CONFIG_GCRYPT),n,$(if $(CONFIG_GNUTLS),n,y)) += random-platform.o -util-obj-y += aes.o init.o diff --git a/crypto/aes.c b/crypto/aes.c index 0f6a195af8226c4667a7a7b8a58bb84079562449..159800df652d14d30f8ccbb3f66ae524c6f623b7 100644 --- a/crypto/aes.c +++ b/crypto/aes.c @@ -1599,54 +1599,3 @@ void AES_decrypt(const unsigned char *in, unsigned char *out, } #endif /* AES_ASM */ - -void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, - const unsigned long length, const AES_KEY *key, - unsigned char *ivec, const int enc) -{ - - unsigned long n; - unsigned long len = length; - unsigned char tmp[AES_BLOCK_SIZE]; - - assert(in && out && key && ivec); - - if (enc) { - while (len >= AES_BLOCK_SIZE) { - for(n=0; n < AES_BLOCK_SIZE; ++n) - tmp[n] = in[n] ^ ivec[n]; - AES_encrypt(tmp, out, key); - memcpy(ivec, out, AES_BLOCK_SIZE); - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - if (len) { - for(n=0; n < len; ++n) - tmp[n] = in[n] ^ ivec[n]; - for(n=len; n < AES_BLOCK_SIZE; ++n) - tmp[n] = ivec[n]; - AES_encrypt(tmp, tmp, key); - memcpy(out, tmp, AES_BLOCK_SIZE); - memcpy(ivec, tmp, AES_BLOCK_SIZE); - } - } else { - while (len >= AES_BLOCK_SIZE) { - memcpy(tmp, in, AES_BLOCK_SIZE); - AES_decrypt(in, out, key); - for(n=0; n < AES_BLOCK_SIZE; ++n) - out[n] ^= ivec[n]; - memcpy(ivec, tmp, AES_BLOCK_SIZE); - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - if (len) { - memcpy(tmp, in, AES_BLOCK_SIZE); - AES_decrypt(tmp, tmp, key); - for(n=0; n < len; ++n) - out[n] = tmp[n] ^ ivec[n]; - memcpy(ivec, tmp, AES_BLOCK_SIZE); - } - } -} diff --git a/crypto/afalgpriv.h b/crypto/afalgpriv.h index f6550b5c51752da4169e02655debe391092c5f7b..5a2393f1b7ee2c4a4986eb576e2085a84b023af5 100644 --- a/crypto/afalgpriv.h +++ b/crypto/afalgpriv.h @@ -15,6 +15,7 @@ #define QCRYPTO_AFALGPRIV_H #include +#include "crypto/cipher.h" #define SALG_TYPE_LEN_MAX 14 #define SALG_NAME_LEN_MAX 64 @@ -32,6 +33,8 @@ typedef struct QCryptoAFAlg QCryptoAFAlg; struct QCryptoAFAlg { + QCryptoCipher base; + int tfmfd; int opfd; struct msghdr *msg; diff --git a/crypto/block-luks.c b/crypto/block-luks.c index 4861db810c5cb95f2ce89e608b9f12cd4254a587..564caa10949bcbbf7de8f2cc04f81fc636372969 100644 --- a/crypto/block-luks.c +++ b/crypto/block-luks.c @@ -32,6 +32,7 @@ #include "qemu/uuid.h" #include "qemu/coroutine.h" +#include "qemu/bitmap.h" /* * Reference for the LUKS format implemented here is @@ -70,6 +71,9 @@ typedef struct QCryptoBlockLUKSKeySlot QCryptoBlockLUKSKeySlot; #define QCRYPTO_BLOCK_LUKS_SECTOR_SIZE 512LL +#define QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS 2000 +#define QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS 40 + static const char qcrypto_block_luks_magic[QCRYPTO_BLOCK_LUKS_MAGIC_LEN] = { 'L', 'U', 'K', 'S', 0xBA, 0xBE }; @@ -219,6 +223,9 @@ struct QCryptoBlockLUKS { /* Hash algorithm used in pbkdf2 function */ QCryptoHashAlgorithm hash_alg; + + /* Name of the secret that was used to open the image */ + char *secret; }; @@ -720,7 +727,7 @@ qcrypto_block_luks_store_key(QCryptoBlock *block, Error **errp) { QCryptoBlockLUKS *luks = block->opaque; - QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[slot_idx]; + QCryptoBlockLUKSKeySlot *slot; g_autofree uint8_t *splitkey = NULL; size_t splitkeylen; g_autofree uint8_t *slotkey = NULL; @@ -730,6 +737,8 @@ qcrypto_block_luks_store_key(QCryptoBlock *block, uint64_t iters; int ret = -1; + assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); + slot = &luks->header.key_slots[slot_idx]; if (qcrypto_random_bytes(slot->salt, QCRYPTO_BLOCK_LUKS_SALT_LEN, errp) < 0) { @@ -890,7 +899,7 @@ qcrypto_block_luks_load_key(QCryptoBlock *block, Error **errp) { QCryptoBlockLUKS *luks = block->opaque; - const QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[slot_idx]; + const QCryptoBlockLUKSKeySlot *slot; g_autofree uint8_t *splitkey = NULL; size_t splitkeylen; g_autofree uint8_t *possiblekey = NULL; @@ -900,6 +909,8 @@ qcrypto_block_luks_load_key(QCryptoBlock *block, g_autoptr(QCryptoIVGen) ivgen = NULL; size_t niv; + assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); + slot = &luks->header.key_slots[slot_idx]; if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) { return 0; } @@ -1069,6 +1080,126 @@ qcrypto_block_luks_find_key(QCryptoBlock *block, return -1; } +/* + * Returns true if a slot i is marked as active + * (contains encrypted copy of the master key) + */ +static bool +qcrypto_block_luks_slot_active(const QCryptoBlockLUKS *luks, + unsigned int slot_idx) +{ + uint32_t val; + + assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); + val = luks->header.key_slots[slot_idx].active; + return val == QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; +} + +/* + * Returns the number of slots that are marked as active + * (slots that contain encrypted copy of the master key) + */ +static unsigned int +qcrypto_block_luks_count_active_slots(const QCryptoBlockLUKS *luks) +{ + size_t i = 0; + unsigned int ret = 0; + + for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { + if (qcrypto_block_luks_slot_active(luks, i)) { + ret++; + } + } + return ret; +} + +/* + * Finds first key slot which is not active + * Returns the key slot index, or -1 if it doesn't exist + */ +static int +qcrypto_block_luks_find_free_keyslot(const QCryptoBlockLUKS *luks) +{ + size_t i; + + for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { + if (!qcrypto_block_luks_slot_active(luks, i)) { + return i; + } + } + return -1; +} + +/* + * Erases an keyslot given its index + * Returns: + * 0 if the keyslot was erased successfully + * -1 if a error occurred while erasing the keyslot + * + */ +static int +qcrypto_block_luks_erase_key(QCryptoBlock *block, + unsigned int slot_idx, + QCryptoBlockWriteFunc writefunc, + void *opaque, + Error **errp) +{ + QCryptoBlockLUKS *luks = block->opaque; + QCryptoBlockLUKSKeySlot *slot; + g_autofree uint8_t *garbagesplitkey = NULL; + size_t splitkeylen; + size_t i; + Error *local_err = NULL; + int ret; + + assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); + slot = &luks->header.key_slots[slot_idx]; + + splitkeylen = luks->header.master_key_len * slot->stripes; + assert(splitkeylen > 0); + + garbagesplitkey = g_new0(uint8_t, splitkeylen); + + /* Reset the key slot header */ + memset(slot->salt, 0, QCRYPTO_BLOCK_LUKS_SALT_LEN); + slot->iterations = 0; + slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED; + + ret = qcrypto_block_luks_store_header(block, writefunc, + opaque, &local_err); + + if (ret < 0) { + error_propagate(errp, local_err); + } + /* + * Now try to erase the key material, even if the header + * update failed + */ + for (i = 0; i < QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS; i++) { + if (qcrypto_random_bytes(garbagesplitkey, + splitkeylen, &local_err) < 0) { + /* + * If we failed to get the random data, still write + * at least zeros to the key slot at least once + */ + error_propagate(errp, local_err); + + if (i > 0) { + return -1; + } + } + if (writefunc(block, + slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, + garbagesplitkey, + splitkeylen, + opaque, + &local_err) != splitkeylen) { + error_propagate(errp, local_err); + return -1; + } + } + return ret; +} static int qcrypto_block_luks_open(QCryptoBlock *block, @@ -1099,6 +1230,7 @@ qcrypto_block_luks_open(QCryptoBlock *block, luks = g_new0(QCryptoBlockLUKS, 1); block->opaque = luks; + luks->secret = g_strdup(options->u.luks.key_secret); if (qcrypto_block_luks_load_header(block, readfunc, opaque, errp) < 0) { goto fail; @@ -1164,6 +1296,7 @@ qcrypto_block_luks_open(QCryptoBlock *block, fail: qcrypto_block_free_cipher(block); qcrypto_ivgen_free(block->ivgen); + g_free(luks->secret); g_free(luks); return -1; } @@ -1204,7 +1337,7 @@ qcrypto_block_luks_create(QCryptoBlock *block, memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts)); if (!luks_opts.has_iter_time) { - luks_opts.iter_time = 2000; + luks_opts.iter_time = QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS; } if (!luks_opts.has_cipher_alg) { luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256; @@ -1244,6 +1377,8 @@ qcrypto_block_luks_create(QCryptoBlock *block, optprefix ? optprefix : ""); goto error; } + luks->secret = g_strdup(options->u.luks.key_secret); + password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp); if (!password) { goto error; @@ -1471,10 +1606,278 @@ qcrypto_block_luks_create(QCryptoBlock *block, qcrypto_block_free_cipher(block); qcrypto_ivgen_free(block->ivgen); + g_free(luks->secret); g_free(luks); return -1; } +static int +qcrypto_block_luks_amend_add_keyslot(QCryptoBlock *block, + QCryptoBlockReadFunc readfunc, + QCryptoBlockWriteFunc writefunc, + void *opaque, + QCryptoBlockAmendOptionsLUKS *opts_luks, + bool force, + Error **errp) +{ + QCryptoBlockLUKS *luks = block->opaque; + uint64_t iter_time = opts_luks->has_iter_time ? + opts_luks->iter_time : + QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS; + int keyslot; + g_autofree char *old_password = NULL; + g_autofree char *new_password = NULL; + g_autofree uint8_t *master_key = NULL; + + char *secret = opts_luks->has_secret ? opts_luks->secret : luks->secret; + + if (!opts_luks->has_new_secret) { + error_setg(errp, "'new-secret' is required to activate a keyslot"); + return -1; + } + if (opts_luks->has_old_secret) { + error_setg(errp, + "'old-secret' must not be given when activating keyslots"); + return -1; + } + + if (opts_luks->has_keyslot) { + keyslot = opts_luks->keyslot; + if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) { + error_setg(errp, + "Invalid keyslot %u specified, must be between 0 and %u", + keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1); + return -1; + } + } else { + keyslot = qcrypto_block_luks_find_free_keyslot(luks); + if (keyslot == -1) { + error_setg(errp, + "Can't add a keyslot - all keyslots are in use"); + return -1; + } + } + + if (!force && qcrypto_block_luks_slot_active(luks, keyslot)) { + error_setg(errp, + "Refusing to overwrite active keyslot %i - " + "please erase it first", + keyslot); + return -1; + } + + /* Locate the password that will be used to retrieve the master key */ + old_password = qcrypto_secret_lookup_as_utf8(secret, errp); + if (!old_password) { + return -1; + } + + /* Retrieve the master key */ + master_key = g_new0(uint8_t, luks->header.master_key_len); + + if (qcrypto_block_luks_find_key(block, old_password, master_key, + readfunc, opaque, errp) < 0) { + error_append_hint(errp, "Failed to retrieve the master key"); + return -1; + } + + /* Locate the new password*/ + new_password = qcrypto_secret_lookup_as_utf8(opts_luks->new_secret, errp); + if (!new_password) { + return -1; + } + + /* Now set the new keyslots */ + if (qcrypto_block_luks_store_key(block, keyslot, new_password, master_key, + iter_time, writefunc, opaque, errp)) { + error_append_hint(errp, "Failed to write to keyslot %i", keyslot); + return -1; + } + return 0; +} + +static int +qcrypto_block_luks_amend_erase_keyslots(QCryptoBlock *block, + QCryptoBlockReadFunc readfunc, + QCryptoBlockWriteFunc writefunc, + void *opaque, + QCryptoBlockAmendOptionsLUKS *opts_luks, + bool force, + Error **errp) +{ + QCryptoBlockLUKS *luks = block->opaque; + g_autofree uint8_t *tmpkey = NULL; + g_autofree char *old_password = NULL; + + if (opts_luks->has_new_secret) { + error_setg(errp, + "'new-secret' must not be given when erasing keyslots"); + return -1; + } + if (opts_luks->has_iter_time) { + error_setg(errp, + "'iter-time' must not be given when erasing keyslots"); + return -1; + } + if (opts_luks->has_secret) { + error_setg(errp, + "'secret' must not be given when erasing keyslots"); + return -1; + } + + /* Load the old password if given */ + if (opts_luks->has_old_secret) { + old_password = qcrypto_secret_lookup_as_utf8(opts_luks->old_secret, + errp); + if (!old_password) { + return -1; + } + + /* + * Allocate a temporary key buffer that we will need when + * checking if slot matches the given old password + */ + tmpkey = g_new0(uint8_t, luks->header.master_key_len); + } + + /* Erase an explicitly given keyslot */ + if (opts_luks->has_keyslot) { + int keyslot = opts_luks->keyslot; + + if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) { + error_setg(errp, + "Invalid keyslot %i specified, must be between 0 and %i", + keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1); + return -1; + } + + if (opts_luks->has_old_secret) { + int rv = qcrypto_block_luks_load_key(block, + keyslot, + old_password, + tmpkey, + readfunc, + opaque, + errp); + if (rv == -1) { + return -1; + } else if (rv == 0) { + error_setg(errp, + "Given keyslot %i doesn't contain the given " + "old password for erase operation", + keyslot); + return -1; + } + } + + if (!force && !qcrypto_block_luks_slot_active(luks, keyslot)) { + error_setg(errp, + "Given keyslot %i is already erased (inactive) ", + keyslot); + return -1; + } + + if (!force && qcrypto_block_luks_count_active_slots(luks) == 1) { + error_setg(errp, + "Attempt to erase the only active keyslot %i " + "which will erase all the data in the image " + "irreversibly - refusing operation", + keyslot); + return -1; + } + + if (qcrypto_block_luks_erase_key(block, keyslot, + writefunc, opaque, errp)) { + error_append_hint(errp, "Failed to erase keyslot %i", keyslot); + return -1; + } + + /* Erase all keyslots that match the given old password */ + } else if (opts_luks->has_old_secret) { + + unsigned long slots_to_erase_bitmap = 0; + size_t i; + int slot_count; + + assert(QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS <= + sizeof(slots_to_erase_bitmap) * 8); + + for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { + int rv = qcrypto_block_luks_load_key(block, + i, + old_password, + tmpkey, + readfunc, + opaque, + errp); + if (rv == -1) { + return -1; + } else if (rv == 1) { + bitmap_set(&slots_to_erase_bitmap, i, 1); + } + } + + slot_count = bitmap_count_one(&slots_to_erase_bitmap, + QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); + if (slot_count == 0) { + error_setg(errp, + "No keyslots match given (old) password for erase operation"); + return -1; + } + + if (!force && + slot_count == qcrypto_block_luks_count_active_slots(luks)) { + error_setg(errp, + "All the active keyslots match the (old) password that " + "was given and erasing them will erase all the data in " + "the image irreversibly - refusing operation"); + return -1; + } + + /* Now apply the update */ + for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { + if (!test_bit(i, &slots_to_erase_bitmap)) { + continue; + } + if (qcrypto_block_luks_erase_key(block, i, writefunc, + opaque, errp)) { + error_append_hint(errp, "Failed to erase keyslot %zu", i); + return -1; + } + } + } else { + error_setg(errp, + "To erase keyslot(s), either explicit keyslot index " + "or the password currently contained in them must be given"); + return -1; + } + return 0; +} + +static int +qcrypto_block_luks_amend_options(QCryptoBlock *block, + QCryptoBlockReadFunc readfunc, + QCryptoBlockWriteFunc writefunc, + void *opaque, + QCryptoBlockAmendOptions *options, + bool force, + Error **errp) +{ + QCryptoBlockAmendOptionsLUKS *opts_luks = &options->u.luks; + + switch (opts_luks->state) { + case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_ACTIVE: + return qcrypto_block_luks_amend_add_keyslot(block, readfunc, + writefunc, opaque, + opts_luks, force, errp); + case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_INACTIVE: + return qcrypto_block_luks_amend_erase_keyslots(block, readfunc, + writefunc, opaque, + opts_luks, force, errp); + default: + g_assert_not_reached(); + } +} static int qcrypto_block_luks_get_info(QCryptoBlock *block, QCryptoBlockInfo *info, @@ -1523,7 +1926,11 @@ static int qcrypto_block_luks_get_info(QCryptoBlock *block, static void qcrypto_block_luks_cleanup(QCryptoBlock *block) { - g_free(block->opaque); + QCryptoBlockLUKS *luks = block->opaque; + if (luks) { + g_free(luks->secret); + g_free(luks); + } } @@ -1560,6 +1967,7 @@ qcrypto_block_luks_encrypt(QCryptoBlock *block, const QCryptoBlockDriver qcrypto_block_driver_luks = { .open = qcrypto_block_luks_open, .create = qcrypto_block_luks_create, + .amend = qcrypto_block_luks_amend_options, .get_info = qcrypto_block_luks_get_info, .cleanup = qcrypto_block_luks_cleanup, .decrypt = qcrypto_block_luks_decrypt, diff --git a/crypto/block.c b/crypto/block.c index 6f42b32f1edbcbd4d40f7433b7af1e5588805b03..eb057948b591626bb7a84fdc60006d4eebb2a176 100644 --- a/crypto/block.c +++ b/crypto/block.c @@ -150,6 +150,35 @@ qcrypto_block_calculate_payload_offset(QCryptoBlockCreateOptions *create_opts, return crypto != NULL; } +int qcrypto_block_amend_options(QCryptoBlock *block, + QCryptoBlockReadFunc readfunc, + QCryptoBlockWriteFunc writefunc, + void *opaque, + QCryptoBlockAmendOptions *options, + bool force, + Error **errp) +{ + if (options->format != block->format) { + error_setg(errp, + "Cannot amend encryption format"); + return -1; + } + + if (!block->driver->amend) { + error_setg(errp, + "Crypto format %s doesn't support format options amendment", + QCryptoBlockFormat_str(block->format)); + return -1; + } + + return block->driver->amend(block, + readfunc, + writefunc, + opaque, + options, + force, + errp); +} QCryptoBlockInfo *qcrypto_block_get_info(QCryptoBlock *block, Error **errp) diff --git a/crypto/blockpriv.h b/crypto/blockpriv.h index 71c59cb542631042efd44aa2de91d9a1c67be938..3c7ccea50401a2bda8a1a501eb3c8b30d0b40811 100644 --- a/crypto/blockpriv.h +++ b/crypto/blockpriv.h @@ -62,6 +62,14 @@ struct QCryptoBlockDriver { void *opaque, Error **errp); + int (*amend)(QCryptoBlock *block, + QCryptoBlockReadFunc readfunc, + QCryptoBlockWriteFunc writefunc, + void *opaque, + QCryptoBlockAmendOptions *options, + bool force, + Error **errp); + int (*get_info)(QCryptoBlock *block, QCryptoBlockInfo *info, Error **errp); diff --git a/crypto/cipher-afalg.c b/crypto/cipher-afalg.c index cd7228469014ec3d413926c4d7ae6e467d769351..052355a8a9219be6bca07ce10ee5b282af7665a6 100644 --- a/crypto/cipher-afalg.c +++ b/crypto/cipher-afalg.c @@ -58,7 +58,9 @@ qcrypto_afalg_cipher_format_name(QCryptoCipherAlgorithm alg, return name; } -QCryptoAFAlg * +static const struct QCryptoCipherDriver qcrypto_cipher_afalg_driver; + +QCryptoCipher * qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg, QCryptoCipherMode mode, const uint8_t *key, @@ -109,7 +111,8 @@ qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg, } afalg->cmsg = CMSG_FIRSTHDR(afalg->msg); - return afalg; + afalg->base.driver = &qcrypto_cipher_afalg_driver; + return &afalg->base; } static int @@ -117,9 +120,9 @@ qcrypto_afalg_cipher_setiv(QCryptoCipher *cipher, const uint8_t *iv, size_t niv, Error **errp) { + QCryptoAFAlg *afalg = container_of(cipher, QCryptoAFAlg, base); struct af_alg_iv *alg_iv; size_t expect_niv; - QCryptoAFAlg *afalg = cipher->opaque; expect_niv = qcrypto_cipher_get_iv_len(cipher->alg, cipher->mode); if (niv != expect_niv) { @@ -200,8 +203,9 @@ qcrypto_afalg_cipher_encrypt(QCryptoCipher *cipher, const void *in, void *out, size_t len, Error **errp) { - return qcrypto_afalg_cipher_op(cipher->opaque, in, out, - len, true, errp); + QCryptoAFAlg *afalg = container_of(cipher, QCryptoAFAlg, base); + + return qcrypto_afalg_cipher_op(afalg, in, out, len, true, errp); } static int @@ -209,16 +213,19 @@ qcrypto_afalg_cipher_decrypt(QCryptoCipher *cipher, const void *in, void *out, size_t len, Error **errp) { - return qcrypto_afalg_cipher_op(cipher->opaque, in, out, - len, false, errp); + QCryptoAFAlg *afalg = container_of(cipher, QCryptoAFAlg, base); + + return qcrypto_afalg_cipher_op(afalg, in, out, len, false, errp); } static void qcrypto_afalg_comm_ctx_free(QCryptoCipher *cipher) { - qcrypto_afalg_comm_free(cipher->opaque); + QCryptoAFAlg *afalg = container_of(cipher, QCryptoAFAlg, base); + + qcrypto_afalg_comm_free(afalg); } -struct QCryptoCipherDriver qcrypto_cipher_afalg_driver = { +static const struct QCryptoCipherDriver qcrypto_cipher_afalg_driver = { .cipher_encrypt = qcrypto_afalg_cipher_encrypt, .cipher_decrypt = qcrypto_afalg_cipher_decrypt, .cipher_setiv = qcrypto_afalg_cipher_setiv, diff --git a/crypto/cipher-builtin.c b/crypto/cipher-builtin.c deleted file mode 100644 index 35cf7820d9b3ca260aff16c17624785a2cd4ddce..0000000000000000000000000000000000000000 --- a/crypto/cipher-builtin.c +++ /dev/null @@ -1,532 +0,0 @@ -/* - * QEMU Crypto cipher built-in algorithms - * - * Copyright (c) 2015 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - * - */ - -#include "qemu/osdep.h" -#include "crypto/aes.h" -#include "crypto/desrfb.h" -#include "crypto/xts.h" -#include "cipherpriv.h" - -typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext; -struct QCryptoCipherBuiltinAESContext { - AES_KEY enc; - AES_KEY dec; -}; -typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES; -struct QCryptoCipherBuiltinAES { - QCryptoCipherBuiltinAESContext key; - QCryptoCipherBuiltinAESContext key_tweak; - uint8_t iv[AES_BLOCK_SIZE]; -}; -typedef struct QCryptoCipherBuiltinDESRFB QCryptoCipherBuiltinDESRFB; -struct QCryptoCipherBuiltinDESRFB { - uint8_t *key; - size_t nkey; -}; - -typedef struct QCryptoCipherBuiltin QCryptoCipherBuiltin; -struct QCryptoCipherBuiltin { - union { - QCryptoCipherBuiltinAES aes; - QCryptoCipherBuiltinDESRFB desrfb; - } state; - size_t blocksize; - void (*free)(QCryptoCipher *cipher); - int (*setiv)(QCryptoCipher *cipher, - const uint8_t *iv, size_t niv, - Error **errp); - int (*encrypt)(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp); - int (*decrypt)(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp); -}; - - -static void qcrypto_cipher_free_aes(QCryptoCipher *cipher) -{ - QCryptoCipherBuiltin *ctxt = cipher->opaque; - - g_free(ctxt); - cipher->opaque = NULL; -} - - -static void qcrypto_cipher_aes_ecb_encrypt(const AES_KEY *key, - const void *in, - void *out, - size_t len) -{ - const uint8_t *inptr = in; - uint8_t *outptr = out; - while (len) { - if (len > AES_BLOCK_SIZE) { - AES_encrypt(inptr, outptr, key); - inptr += AES_BLOCK_SIZE; - outptr += AES_BLOCK_SIZE; - len -= AES_BLOCK_SIZE; - } else { - uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE]; - memcpy(tmp1, inptr, len); - /* Fill with 0 to avoid valgrind uninitialized reads */ - memset(tmp1 + len, 0, sizeof(tmp1) - len); - AES_encrypt(tmp1, tmp2, key); - memcpy(outptr, tmp2, len); - len = 0; - } - } -} - - -static void qcrypto_cipher_aes_ecb_decrypt(const AES_KEY *key, - const void *in, - void *out, - size_t len) -{ - const uint8_t *inptr = in; - uint8_t *outptr = out; - while (len) { - if (len > AES_BLOCK_SIZE) { - AES_decrypt(inptr, outptr, key); - inptr += AES_BLOCK_SIZE; - outptr += AES_BLOCK_SIZE; - len -= AES_BLOCK_SIZE; - } else { - uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE]; - memcpy(tmp1, inptr, len); - /* Fill with 0 to avoid valgrind uninitialized reads */ - memset(tmp1 + len, 0, sizeof(tmp1) - len); - AES_decrypt(tmp1, tmp2, key); - memcpy(outptr, tmp2, len); - len = 0; - } - } -} - - -static void qcrypto_cipher_aes_xts_encrypt(const void *ctx, - size_t length, - uint8_t *dst, - const uint8_t *src) -{ - const QCryptoCipherBuiltinAESContext *aesctx = ctx; - - qcrypto_cipher_aes_ecb_encrypt(&aesctx->enc, src, dst, length); -} - - -static void qcrypto_cipher_aes_xts_decrypt(const void *ctx, - size_t length, - uint8_t *dst, - const uint8_t *src) -{ - const QCryptoCipherBuiltinAESContext *aesctx = ctx; - - qcrypto_cipher_aes_ecb_decrypt(&aesctx->dec, src, dst, length); -} - - -static int qcrypto_cipher_encrypt_aes(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt = cipher->opaque; - - switch (cipher->mode) { - case QCRYPTO_CIPHER_MODE_ECB: - qcrypto_cipher_aes_ecb_encrypt(&ctxt->state.aes.key.enc, - in, out, len); - break; - case QCRYPTO_CIPHER_MODE_CBC: - AES_cbc_encrypt(in, out, len, - &ctxt->state.aes.key.enc, - ctxt->state.aes.iv, 1); - break; - case QCRYPTO_CIPHER_MODE_XTS: - xts_encrypt(&ctxt->state.aes.key, - &ctxt->state.aes.key_tweak, - qcrypto_cipher_aes_xts_encrypt, - qcrypto_cipher_aes_xts_decrypt, - ctxt->state.aes.iv, - len, out, in); - break; - default: - g_assert_not_reached(); - } - - return 0; -} - - -static int qcrypto_cipher_decrypt_aes(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt = cipher->opaque; - - switch (cipher->mode) { - case QCRYPTO_CIPHER_MODE_ECB: - qcrypto_cipher_aes_ecb_decrypt(&ctxt->state.aes.key.dec, - in, out, len); - break; - case QCRYPTO_CIPHER_MODE_CBC: - AES_cbc_encrypt(in, out, len, - &ctxt->state.aes.key.dec, - ctxt->state.aes.iv, 0); - break; - case QCRYPTO_CIPHER_MODE_XTS: - xts_decrypt(&ctxt->state.aes.key, - &ctxt->state.aes.key_tweak, - qcrypto_cipher_aes_xts_encrypt, - qcrypto_cipher_aes_xts_decrypt, - ctxt->state.aes.iv, - len, out, in); - break; - default: - g_assert_not_reached(); - } - - return 0; -} - -static int qcrypto_cipher_setiv_aes(QCryptoCipher *cipher, - const uint8_t *iv, size_t niv, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt = cipher->opaque; - if (niv != AES_BLOCK_SIZE) { - error_setg(errp, "IV must be %d bytes not %zu", - AES_BLOCK_SIZE, niv); - return -1; - } - - memcpy(ctxt->state.aes.iv, iv, AES_BLOCK_SIZE); - - return 0; -} - - - - -static QCryptoCipherBuiltin * -qcrypto_cipher_init_aes(QCryptoCipherMode mode, - const uint8_t *key, size_t nkey, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt; - - if (mode != QCRYPTO_CIPHER_MODE_CBC && - mode != QCRYPTO_CIPHER_MODE_ECB && - mode != QCRYPTO_CIPHER_MODE_XTS) { - error_setg(errp, "Unsupported cipher mode %s", - QCryptoCipherMode_str(mode)); - return NULL; - } - - ctxt = g_new0(QCryptoCipherBuiltin, 1); - - if (mode == QCRYPTO_CIPHER_MODE_XTS) { - if (AES_set_encrypt_key(key, nkey * 4, &ctxt->state.aes.key.enc) != 0) { - error_setg(errp, "Failed to set encryption key"); - goto error; - } - - if (AES_set_decrypt_key(key, nkey * 4, &ctxt->state.aes.key.dec) != 0) { - error_setg(errp, "Failed to set decryption key"); - goto error; - } - - if (AES_set_encrypt_key(key + (nkey / 2), nkey * 4, - &ctxt->state.aes.key_tweak.enc) != 0) { - error_setg(errp, "Failed to set encryption key"); - goto error; - } - - if (AES_set_decrypt_key(key + (nkey / 2), nkey * 4, - &ctxt->state.aes.key_tweak.dec) != 0) { - error_setg(errp, "Failed to set decryption key"); - goto error; - } - } else { - if (AES_set_encrypt_key(key, nkey * 8, &ctxt->state.aes.key.enc) != 0) { - error_setg(errp, "Failed to set encryption key"); - goto error; - } - - if (AES_set_decrypt_key(key, nkey * 8, &ctxt->state.aes.key.dec) != 0) { - error_setg(errp, "Failed to set decryption key"); - goto error; - } - } - - ctxt->blocksize = AES_BLOCK_SIZE; - ctxt->free = qcrypto_cipher_free_aes; - ctxt->setiv = qcrypto_cipher_setiv_aes; - ctxt->encrypt = qcrypto_cipher_encrypt_aes; - ctxt->decrypt = qcrypto_cipher_decrypt_aes; - - return ctxt; - - error: - g_free(ctxt); - return NULL; -} - - -static void qcrypto_cipher_free_des_rfb(QCryptoCipher *cipher) -{ - QCryptoCipherBuiltin *ctxt = cipher->opaque; - - g_free(ctxt->state.desrfb.key); - g_free(ctxt); - cipher->opaque = NULL; -} - - -static int qcrypto_cipher_encrypt_des_rfb(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt = cipher->opaque; - size_t i; - - if (len % 8) { - error_setg(errp, "Buffer size must be multiple of 8 not %zu", - len); - return -1; - } - - deskey(ctxt->state.desrfb.key, EN0); - - for (i = 0; i < len; i += 8) { - des((void *)in + i, out + i); - } - - return 0; -} - - -static int qcrypto_cipher_decrypt_des_rfb(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt = cipher->opaque; - size_t i; - - if (len % 8) { - error_setg(errp, "Buffer size must be multiple of 8 not %zu", - len); - return -1; - } - - deskey(ctxt->state.desrfb.key, DE1); - - for (i = 0; i < len; i += 8) { - des((void *)in + i, out + i); - } - - return 0; -} - - -static int qcrypto_cipher_setiv_des_rfb(QCryptoCipher *cipher, - const uint8_t *iv, size_t niv, - Error **errp) -{ - error_setg(errp, "Setting IV is not supported"); - return -1; -} - - -static QCryptoCipherBuiltin * -qcrypto_cipher_init_des_rfb(QCryptoCipherMode mode, - const uint8_t *key, size_t nkey, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt; - - if (mode != QCRYPTO_CIPHER_MODE_ECB) { - error_setg(errp, "Unsupported cipher mode %s", - QCryptoCipherMode_str(mode)); - return NULL; - } - - ctxt = g_new0(QCryptoCipherBuiltin, 1); - - ctxt->state.desrfb.key = g_new0(uint8_t, nkey); - memcpy(ctxt->state.desrfb.key, key, nkey); - ctxt->state.desrfb.nkey = nkey; - - ctxt->blocksize = 8; - ctxt->free = qcrypto_cipher_free_des_rfb; - ctxt->setiv = qcrypto_cipher_setiv_des_rfb; - ctxt->encrypt = qcrypto_cipher_encrypt_des_rfb; - ctxt->decrypt = qcrypto_cipher_decrypt_des_rfb; - - return ctxt; -} - - -bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, - QCryptoCipherMode mode) -{ - switch (alg) { - case QCRYPTO_CIPHER_ALG_DES_RFB: - case QCRYPTO_CIPHER_ALG_AES_128: - case QCRYPTO_CIPHER_ALG_AES_192: - case QCRYPTO_CIPHER_ALG_AES_256: - break; - default: - return false; - } - - switch (mode) { - case QCRYPTO_CIPHER_MODE_ECB: - case QCRYPTO_CIPHER_MODE_CBC: - case QCRYPTO_CIPHER_MODE_XTS: - return true; - case QCRYPTO_CIPHER_MODE_CTR: - return false; - default: - return false; - } -} - - -static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, - QCryptoCipherMode mode, - const uint8_t *key, - size_t nkey, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt; - - switch (mode) { - case QCRYPTO_CIPHER_MODE_ECB: - case QCRYPTO_CIPHER_MODE_CBC: - case QCRYPTO_CIPHER_MODE_XTS: - break; - default: - error_setg(errp, "Unsupported cipher mode %s", - QCryptoCipherMode_str(mode)); - return NULL; - } - - if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) { - return NULL; - } - - switch (alg) { - case QCRYPTO_CIPHER_ALG_DES_RFB: - ctxt = qcrypto_cipher_init_des_rfb(mode, key, nkey, errp); - break; - case QCRYPTO_CIPHER_ALG_AES_128: - case QCRYPTO_CIPHER_ALG_AES_192: - case QCRYPTO_CIPHER_ALG_AES_256: - ctxt = qcrypto_cipher_init_aes(mode, key, nkey, errp); - break; - default: - error_setg(errp, - "Unsupported cipher algorithm %s", - QCryptoCipherAlgorithm_str(alg)); - return NULL; - } - - return ctxt; -} - -static void -qcrypto_builtin_cipher_ctx_free(QCryptoCipher *cipher) -{ - QCryptoCipherBuiltin *ctxt; - - ctxt = cipher->opaque; - ctxt->free(cipher); -} - - -static int -qcrypto_builtin_cipher_encrypt(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt = cipher->opaque; - - if (len % ctxt->blocksize) { - error_setg(errp, "Length %zu must be a multiple of block size %zu", - len, ctxt->blocksize); - return -1; - } - - return ctxt->encrypt(cipher, in, out, len, errp); -} - - -static int -qcrypto_builtin_cipher_decrypt(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt = cipher->opaque; - - if (len % ctxt->blocksize) { - error_setg(errp, "Length %zu must be a multiple of block size %zu", - len, ctxt->blocksize); - return -1; - } - - return ctxt->decrypt(cipher, in, out, len, errp); -} - - -static int -qcrypto_builtin_cipher_setiv(QCryptoCipher *cipher, - const uint8_t *iv, size_t niv, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt = cipher->opaque; - - return ctxt->setiv(cipher, iv, niv, errp); -} - - -static struct QCryptoCipherDriver qcrypto_cipher_lib_driver = { - .cipher_encrypt = qcrypto_builtin_cipher_encrypt, - .cipher_decrypt = qcrypto_builtin_cipher_decrypt, - .cipher_setiv = qcrypto_builtin_cipher_setiv, - .cipher_free = qcrypto_builtin_cipher_ctx_free, -}; diff --git a/crypto/cipher-builtin.c.inc b/crypto/cipher-builtin.c.inc new file mode 100644 index 0000000000000000000000000000000000000000..7597cf4a10fd208664c7082240bba49f4fc38a0d --- /dev/null +++ b/crypto/cipher-builtin.c.inc @@ -0,0 +1,435 @@ +/* + * QEMU Crypto cipher built-in algorithms + * + * Copyright (c) 2015 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + */ + +#include "crypto/aes.h" +#include "crypto/desrfb.h" +#include "crypto/xts.h" + +typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext; +struct QCryptoCipherBuiltinAESContext { + AES_KEY enc; + AES_KEY dec; +}; + +typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES; +struct QCryptoCipherBuiltinAES { + QCryptoCipher base; + QCryptoCipherBuiltinAESContext key; + QCryptoCipherBuiltinAESContext key_tweak; + uint8_t iv[AES_BLOCK_SIZE]; +}; + + +static inline bool qcrypto_length_check(size_t len, size_t blocksize, + Error **errp) +{ + if (unlikely(len & (blocksize - 1))) { + error_setg(errp, "Length %zu must be a multiple of block size %zu", + len, blocksize); + return false; + } + return true; +} + +static void qcrypto_cipher_ctx_free(QCryptoCipher *cipher) +{ + g_free(cipher); +} + +static int qcrypto_cipher_no_setiv(QCryptoCipher *cipher, + const uint8_t *iv, size_t niv, + Error **errp) +{ + error_setg(errp, "Setting IV is not supported"); + return -1; +} + +static void do_aes_encrypt_ecb(const void *vctx, + size_t len, + uint8_t *out, + const uint8_t *in) +{ + const QCryptoCipherBuiltinAESContext *ctx = vctx; + + /* We have already verified that len % AES_BLOCK_SIZE == 0. */ + while (len) { + AES_encrypt(in, out, &ctx->enc); + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + len -= AES_BLOCK_SIZE; + } +} + +static void do_aes_decrypt_ecb(const void *vctx, + size_t len, + uint8_t *out, + const uint8_t *in) +{ + const QCryptoCipherBuiltinAESContext *ctx = vctx; + + /* We have already verified that len % AES_BLOCK_SIZE == 0. */ + while (len) { + AES_decrypt(in, out, &ctx->dec); + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + len -= AES_BLOCK_SIZE; + } +} + +static void do_aes_encrypt_cbc(const AES_KEY *key, + size_t len, + uint8_t *out, + const uint8_t *in, + uint8_t *ivec) +{ + uint8_t tmp[AES_BLOCK_SIZE]; + size_t n; + + /* We have already verified that len % AES_BLOCK_SIZE == 0. */ + while (len) { + for (n = 0; n < AES_BLOCK_SIZE; ++n) { + tmp[n] = in[n] ^ ivec[n]; + } + AES_encrypt(tmp, out, key); + memcpy(ivec, out, AES_BLOCK_SIZE); + len -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } +} + +static void do_aes_decrypt_cbc(const AES_KEY *key, + size_t len, + uint8_t *out, + const uint8_t *in, + uint8_t *ivec) +{ + uint8_t tmp[AES_BLOCK_SIZE]; + size_t n; + + /* We have already verified that len % AES_BLOCK_SIZE == 0. */ + while (len) { + memcpy(tmp, in, AES_BLOCK_SIZE); + AES_decrypt(in, out, key); + for (n = 0; n < AES_BLOCK_SIZE; ++n) { + out[n] ^= ivec[n]; + } + memcpy(ivec, tmp, AES_BLOCK_SIZE); + len -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } +} + +static int qcrypto_cipher_aes_encrypt_ecb(QCryptoCipher *cipher, + const void *in, void *out, + size_t len, Error **errp) +{ + QCryptoCipherBuiltinAES *ctx + = container_of(cipher, QCryptoCipherBuiltinAES, base); + + if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) { + return -1; + } + do_aes_encrypt_ecb(&ctx->key, len, out, in); + return 0; +} + +static int qcrypto_cipher_aes_decrypt_ecb(QCryptoCipher *cipher, + const void *in, void *out, + size_t len, Error **errp) +{ + QCryptoCipherBuiltinAES *ctx + = container_of(cipher, QCryptoCipherBuiltinAES, base); + + if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) { + return -1; + } + do_aes_decrypt_ecb(&ctx->key, len, out, in); + return 0; +} + +static int qcrypto_cipher_aes_encrypt_cbc(QCryptoCipher *cipher, + const void *in, void *out, + size_t len, Error **errp) +{ + QCryptoCipherBuiltinAES *ctx + = container_of(cipher, QCryptoCipherBuiltinAES, base); + + if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) { + return -1; + } + do_aes_encrypt_cbc(&ctx->key.enc, len, out, in, ctx->iv); + return 0; +} + +static int qcrypto_cipher_aes_decrypt_cbc(QCryptoCipher *cipher, + const void *in, void *out, + size_t len, Error **errp) +{ + QCryptoCipherBuiltinAES *ctx + = container_of(cipher, QCryptoCipherBuiltinAES, base); + + if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) { + return -1; + } + do_aes_decrypt_cbc(&ctx->key.dec, len, out, in, ctx->iv); + return 0; +} + +static int qcrypto_cipher_aes_encrypt_xts(QCryptoCipher *cipher, + const void *in, void *out, + size_t len, Error **errp) +{ + QCryptoCipherBuiltinAES *ctx + = container_of(cipher, QCryptoCipherBuiltinAES, base); + + if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) { + return -1; + } + xts_encrypt(&ctx->key, &ctx->key_tweak, + do_aes_encrypt_ecb, do_aes_decrypt_ecb, + ctx->iv, len, out, in); + return 0; +} + +static int qcrypto_cipher_aes_decrypt_xts(QCryptoCipher *cipher, + const void *in, void *out, + size_t len, Error **errp) +{ + QCryptoCipherBuiltinAES *ctx + = container_of(cipher, QCryptoCipherBuiltinAES, base); + + if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) { + return -1; + } + xts_decrypt(&ctx->key, &ctx->key_tweak, + do_aes_encrypt_ecb, do_aes_decrypt_ecb, + ctx->iv, len, out, in); + return 0; +} + + +static int qcrypto_cipher_aes_setiv(QCryptoCipher *cipher, const uint8_t *iv, + size_t niv, Error **errp) +{ + QCryptoCipherBuiltinAES *ctx + = container_of(cipher, QCryptoCipherBuiltinAES, base); + + if (niv != AES_BLOCK_SIZE) { + error_setg(errp, "IV must be %d bytes not %zu", + AES_BLOCK_SIZE, niv); + return -1; + } + + memcpy(ctx->iv, iv, AES_BLOCK_SIZE); + return 0; +} + +static const struct QCryptoCipherDriver qcrypto_cipher_aes_driver_ecb = { + .cipher_encrypt = qcrypto_cipher_aes_encrypt_ecb, + .cipher_decrypt = qcrypto_cipher_aes_decrypt_ecb, + .cipher_setiv = qcrypto_cipher_no_setiv, + .cipher_free = qcrypto_cipher_ctx_free, +}; + +static const struct QCryptoCipherDriver qcrypto_cipher_aes_driver_cbc = { + .cipher_encrypt = qcrypto_cipher_aes_encrypt_cbc, + .cipher_decrypt = qcrypto_cipher_aes_decrypt_cbc, + .cipher_setiv = qcrypto_cipher_aes_setiv, + .cipher_free = qcrypto_cipher_ctx_free, +}; + +static const struct QCryptoCipherDriver qcrypto_cipher_aes_driver_xts = { + .cipher_encrypt = qcrypto_cipher_aes_encrypt_xts, + .cipher_decrypt = qcrypto_cipher_aes_decrypt_xts, + .cipher_setiv = qcrypto_cipher_aes_setiv, + .cipher_free = qcrypto_cipher_ctx_free, +}; + + +typedef struct QCryptoCipherBuiltinDESRFB QCryptoCipherBuiltinDESRFB; +struct QCryptoCipherBuiltinDESRFB { + QCryptoCipher base; + + /* C.f. alg_key_len[QCRYPTO_CIPHER_ALG_DES_RFB] */ + uint8_t key[8]; +}; + +static int qcrypto_cipher_encrypt_des_rfb(QCryptoCipher *cipher, + const void *in, void *out, + size_t len, Error **errp) +{ + QCryptoCipherBuiltinDESRFB *ctx + = container_of(cipher, QCryptoCipherBuiltinDESRFB, base); + size_t i; + + if (!qcrypto_length_check(len, 8, errp)) { + return -1; + } + + deskey(ctx->key, EN0); + + for (i = 0; i < len; i += 8) { + des((void *)in + i, out + i); + } + + return 0; +} + +static int qcrypto_cipher_decrypt_des_rfb(QCryptoCipher *cipher, + const void *in, void *out, + size_t len, Error **errp) +{ + QCryptoCipherBuiltinDESRFB *ctx + = container_of(cipher, QCryptoCipherBuiltinDESRFB, base); + size_t i; + + if (!qcrypto_length_check(len, 8, errp)) { + return -1; + } + + deskey(ctx->key, DE1); + + for (i = 0; i < len; i += 8) { + des((void *)in + i, out + i); + } + + return 0; +} + +static const struct QCryptoCipherDriver qcrypto_cipher_des_rfb_driver = { + .cipher_encrypt = qcrypto_cipher_encrypt_des_rfb, + .cipher_decrypt = qcrypto_cipher_decrypt_des_rfb, + .cipher_setiv = qcrypto_cipher_no_setiv, + .cipher_free = qcrypto_cipher_ctx_free, +}; + +bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode) +{ + switch (alg) { + case QCRYPTO_CIPHER_ALG_DES_RFB: + return mode == QCRYPTO_CIPHER_MODE_ECB; + case QCRYPTO_CIPHER_ALG_AES_128: + case QCRYPTO_CIPHER_ALG_AES_192: + case QCRYPTO_CIPHER_ALG_AES_256: + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + case QCRYPTO_CIPHER_MODE_CBC: + case QCRYPTO_CIPHER_MODE_XTS: + return true; + default: + return false; + } + break; + default: + return false; + } +} + +static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode, + const uint8_t *key, + size_t nkey, + Error **errp) +{ + if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) { + return NULL; + } + + switch (alg) { + case QCRYPTO_CIPHER_ALG_DES_RFB: + if (mode == QCRYPTO_CIPHER_MODE_ECB) { + QCryptoCipherBuiltinDESRFB *ctx; + + ctx = g_new0(QCryptoCipherBuiltinDESRFB, 1); + ctx->base.driver = &qcrypto_cipher_des_rfb_driver; + memcpy(ctx->key, key, sizeof(ctx->key)); + + return &ctx->base; + } + goto bad_mode; + + case QCRYPTO_CIPHER_ALG_AES_128: + case QCRYPTO_CIPHER_ALG_AES_192: + case QCRYPTO_CIPHER_ALG_AES_256: + { + QCryptoCipherBuiltinAES *ctx; + const QCryptoCipherDriver *drv; + + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + drv = &qcrypto_cipher_aes_driver_ecb; + break; + case QCRYPTO_CIPHER_MODE_CBC: + drv = &qcrypto_cipher_aes_driver_cbc; + break; + case QCRYPTO_CIPHER_MODE_XTS: + drv = &qcrypto_cipher_aes_driver_xts; + break; + default: + goto bad_mode; + } + + ctx = g_new0(QCryptoCipherBuiltinAES, 1); + ctx->base.driver = drv; + + if (mode == QCRYPTO_CIPHER_MODE_XTS) { + nkey /= 2; + if (AES_set_encrypt_key(key + nkey, nkey * 8, + &ctx->key_tweak.enc)) { + error_setg(errp, "Failed to set encryption key"); + goto error; + } + if (AES_set_decrypt_key(key + nkey, nkey * 8, + &ctx->key_tweak.dec)) { + error_setg(errp, "Failed to set decryption key"); + goto error; + } + } + if (AES_set_encrypt_key(key, nkey * 8, &ctx->key.enc)) { + error_setg(errp, "Failed to set encryption key"); + goto error; + } + if (AES_set_decrypt_key(key, nkey * 8, &ctx->key.dec)) { + error_setg(errp, "Failed to set decryption key"); + goto error; + } + + return &ctx->base; + + error: + g_free(ctx); + return NULL; + } + + default: + error_setg(errp, + "Unsupported cipher algorithm %s", + QCryptoCipherAlgorithm_str(alg)); + return NULL; + } + + bad_mode: + error_setg(errp, "Unsupported cipher mode %s", + QCryptoCipherMode_str(mode)); + return NULL; +} diff --git a/crypto/cipher-gcrypt.c b/crypto/cipher-gcrypt.c.inc similarity index 52% rename from crypto/cipher-gcrypt.c rename to crypto/cipher-gcrypt.c.inc index 2864099527e473c9aa86d5a23629e3f8cb8acaf5..42d4137534f271147b4cd0cec8e556ef5904676a 100644 --- a/crypto/cipher-gcrypt.c +++ b/crypto/cipher-gcrypt.c.inc @@ -18,15 +18,12 @@ * */ -#include "qemu/osdep.h" #ifdef CONFIG_QEMU_PRIVATE_XTS #include "crypto/xts.h" #endif -#include "cipherpriv.h" #include - bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, QCryptoCipherMode mode) { @@ -58,69 +55,224 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, } } -typedef struct QCryptoCipherGcrypt QCryptoCipherGcrypt; -struct QCryptoCipherGcrypt { +typedef struct QCryptoCipherGcrypt { + QCryptoCipher base; gcry_cipher_hd_t handle; size_t blocksize; #ifdef CONFIG_QEMU_PRIVATE_XTS gcry_cipher_hd_t tweakhandle; - /* Initialization vector or Counter */ - uint8_t *iv; + uint8_t iv[XTS_BLOCK_SIZE]; #endif -}; +} QCryptoCipherGcrypt; + -static void -qcrypto_gcrypt_cipher_free_ctx(QCryptoCipherGcrypt *ctx, - QCryptoCipherMode mode) +static void qcrypto_gcrypt_ctx_free(QCryptoCipher *cipher) { - if (!ctx) { - return; - } + QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); gcry_cipher_close(ctx->handle); -#ifdef CONFIG_QEMU_PRIVATE_XTS - if (mode == QCRYPTO_CIPHER_MODE_XTS) { - gcry_cipher_close(ctx->tweakhandle); - } - g_free(ctx->iv); -#endif g_free(ctx); } +static int qcrypto_gcrypt_encrypt(QCryptoCipher *cipher, const void *in, + void *out, size_t len, Error **errp) +{ + QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); + gcry_error_t err; + + if (len & (ctx->blocksize - 1)) { + error_setg(errp, "Length %zu must be a multiple of block size %zu", + len, ctx->blocksize); + return -1; + } + + err = gcry_cipher_encrypt(ctx->handle, out, len, in, len); + if (err != 0) { + error_setg(errp, "Cannot encrypt data: %s", gcry_strerror(err)); + return -1; + } + + return 0; +} + -static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, - QCryptoCipherMode mode, - const uint8_t *key, - size_t nkey, - Error **errp) +static int qcrypto_gcrypt_decrypt(QCryptoCipher *cipher, const void *in, + void *out, size_t len, Error **errp) { - QCryptoCipherGcrypt *ctx; + QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); gcry_error_t err; - int gcryalg, gcrymode; - switch (mode) { - case QCRYPTO_CIPHER_MODE_ECB: - gcrymode = GCRY_CIPHER_MODE_ECB; - break; - case QCRYPTO_CIPHER_MODE_XTS: + if (len & (ctx->blocksize - 1)) { + error_setg(errp, "Length %zu must be a multiple of block size %zu", + len, ctx->blocksize); + return -1; + } + + err = gcry_cipher_decrypt(ctx->handle, out, len, in, len); + if (err != 0) { + error_setg(errp, "Cannot decrypt data: %s", + gcry_strerror(err)); + return -1; + } + + return 0; +} + +static int qcrypto_gcrypt_setiv(QCryptoCipher *cipher, + const uint8_t *iv, size_t niv, + Error **errp) +{ + QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); + gcry_error_t err; + + if (niv != ctx->blocksize) { + error_setg(errp, "Expected IV size %zu not %zu", + ctx->blocksize, niv); + return -1; + } + + gcry_cipher_reset(ctx->handle); + err = gcry_cipher_setiv(ctx->handle, iv, niv); + if (err != 0) { + error_setg(errp, "Cannot set IV: %s", gcry_strerror(err)); + return -1; + } + + return 0; +} + +static int qcrypto_gcrypt_ctr_setiv(QCryptoCipher *cipher, + const uint8_t *iv, size_t niv, + Error **errp) +{ + QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); + gcry_error_t err; + + if (niv != ctx->blocksize) { + error_setg(errp, "Expected IV size %zu not %zu", + ctx->blocksize, niv); + return -1; + } + + err = gcry_cipher_setctr(ctx->handle, iv, niv); + if (err != 0) { + error_setg(errp, "Cannot set Counter: %s", gcry_strerror(err)); + return -1; + } + + return 0; +} + + +static const struct QCryptoCipherDriver qcrypto_gcrypt_driver = { + .cipher_encrypt = qcrypto_gcrypt_encrypt, + .cipher_decrypt = qcrypto_gcrypt_decrypt, + .cipher_setiv = qcrypto_gcrypt_setiv, + .cipher_free = qcrypto_gcrypt_ctx_free, +}; + +static const struct QCryptoCipherDriver qcrypto_gcrypt_ctr_driver = { + .cipher_encrypt = qcrypto_gcrypt_encrypt, + .cipher_decrypt = qcrypto_gcrypt_decrypt, + .cipher_setiv = qcrypto_gcrypt_ctr_setiv, + .cipher_free = qcrypto_gcrypt_ctx_free, +}; + #ifdef CONFIG_QEMU_PRIVATE_XTS - gcrymode = GCRY_CIPHER_MODE_ECB; -#else - gcrymode = GCRY_CIPHER_MODE_XTS; -#endif - break; - case QCRYPTO_CIPHER_MODE_CBC: - gcrymode = GCRY_CIPHER_MODE_CBC; - break; - case QCRYPTO_CIPHER_MODE_CTR: - gcrymode = GCRY_CIPHER_MODE_CTR; - break; - default: - error_setg(errp, "Unsupported cipher mode %s", - QCryptoCipherMode_str(mode)); - return NULL; +static void qcrypto_gcrypt_xts_ctx_free(QCryptoCipher *cipher) +{ + QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); + + gcry_cipher_close(ctx->tweakhandle); + qcrypto_gcrypt_ctx_free(cipher); +} + +static void qcrypto_gcrypt_xts_wrape(const void *ctx, size_t length, + uint8_t *dst, const uint8_t *src) +{ + gcry_error_t err; + err = gcry_cipher_encrypt((gcry_cipher_hd_t)ctx, dst, length, src, length); + g_assert(err == 0); +} + +static void qcrypto_gcrypt_xts_wrapd(const void *ctx, size_t length, + uint8_t *dst, const uint8_t *src) +{ + gcry_error_t err; + err = gcry_cipher_decrypt((gcry_cipher_hd_t)ctx, dst, length, src, length); + g_assert(err == 0); +} + +static int qcrypto_gcrypt_xts_encrypt(QCryptoCipher *cipher, const void *in, + void *out, size_t len, Error **errp) +{ + QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); + + if (len & (ctx->blocksize - 1)) { + error_setg(errp, "Length %zu must be a multiple of block size %zu", + len, ctx->blocksize); + return -1; } + xts_encrypt(ctx->handle, ctx->tweakhandle, + qcrypto_gcrypt_xts_wrape, qcrypto_gcrypt_xts_wrapd, + ctx->iv, len, out, in); + return 0; +} + +static int qcrypto_gcrypt_xts_decrypt(QCryptoCipher *cipher, const void *in, + void *out, size_t len, Error **errp) +{ + QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); + + if (len & (ctx->blocksize - 1)) { + error_setg(errp, "Length %zu must be a multiple of block size %zu", + len, ctx->blocksize); + return -1; + } + + xts_decrypt(ctx->handle, ctx->tweakhandle, + qcrypto_gcrypt_xts_wrape, qcrypto_gcrypt_xts_wrapd, + ctx->iv, len, out, in); + return 0; +} + +static int qcrypto_gcrypt_xts_setiv(QCryptoCipher *cipher, + const uint8_t *iv, size_t niv, + Error **errp) +{ + QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); + + if (niv != ctx->blocksize) { + error_setg(errp, "Expected IV size %zu not %zu", + ctx->blocksize, niv); + return -1; + } + + memcpy(ctx->iv, iv, niv); + return 0; +} + +static const struct QCryptoCipherDriver qcrypto_gcrypt_xts_driver = { + .cipher_encrypt = qcrypto_gcrypt_xts_encrypt, + .cipher_decrypt = qcrypto_gcrypt_xts_decrypt, + .cipher_setiv = qcrypto_gcrypt_xts_setiv, + .cipher_free = qcrypto_gcrypt_xts_ctx_free, +}; +#endif /* CONFIG_QEMU_PRIVATE_XTS */ + + +static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode, + const uint8_t *key, + size_t nkey, + Error **errp) +{ + QCryptoCipherGcrypt *ctx; + const QCryptoCipherDriver *drv; + gcry_error_t err; + int gcryalg, gcrymode; + if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) { return NULL; } @@ -129,54 +281,70 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, case QCRYPTO_CIPHER_ALG_DES_RFB: gcryalg = GCRY_CIPHER_DES; break; - case QCRYPTO_CIPHER_ALG_3DES: gcryalg = GCRY_CIPHER_3DES; break; - case QCRYPTO_CIPHER_ALG_AES_128: gcryalg = GCRY_CIPHER_AES128; break; - case QCRYPTO_CIPHER_ALG_AES_192: gcryalg = GCRY_CIPHER_AES192; break; - case QCRYPTO_CIPHER_ALG_AES_256: gcryalg = GCRY_CIPHER_AES256; break; - case QCRYPTO_CIPHER_ALG_CAST5_128: gcryalg = GCRY_CIPHER_CAST5; break; - case QCRYPTO_CIPHER_ALG_SERPENT_128: gcryalg = GCRY_CIPHER_SERPENT128; break; - case QCRYPTO_CIPHER_ALG_SERPENT_192: gcryalg = GCRY_CIPHER_SERPENT192; break; - case QCRYPTO_CIPHER_ALG_SERPENT_256: gcryalg = GCRY_CIPHER_SERPENT256; break; - case QCRYPTO_CIPHER_ALG_TWOFISH_128: gcryalg = GCRY_CIPHER_TWOFISH128; break; - case QCRYPTO_CIPHER_ALG_TWOFISH_256: gcryalg = GCRY_CIPHER_TWOFISH; break; - default: error_setg(errp, "Unsupported cipher algorithm %s", QCryptoCipherAlgorithm_str(alg)); return NULL; } + drv = &qcrypto_gcrypt_driver; + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + gcrymode = GCRY_CIPHER_MODE_ECB; + break; + case QCRYPTO_CIPHER_MODE_XTS: +#ifdef CONFIG_QEMU_PRIVATE_XTS + drv = &qcrypto_gcrypt_xts_driver; + gcrymode = GCRY_CIPHER_MODE_ECB; +#else + gcrymode = GCRY_CIPHER_MODE_XTS; +#endif + break; + case QCRYPTO_CIPHER_MODE_CBC: + gcrymode = GCRY_CIPHER_MODE_CBC; + break; + case QCRYPTO_CIPHER_MODE_CTR: + drv = &qcrypto_gcrypt_ctr_driver; + gcrymode = GCRY_CIPHER_MODE_CTR; + break; + default: + error_setg(errp, "Unsupported cipher mode %s", + QCryptoCipherMode_str(mode)); + return NULL; + } + ctx = g_new0(QCryptoCipherGcrypt, 1); + ctx->base.driver = drv; err = gcry_cipher_open(&ctx->handle, gcryalg, gcrymode, 0); if (err != 0) { @@ -184,8 +352,16 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, gcry_strerror(err)); goto error; } + ctx->blocksize = gcry_cipher_get_algo_blklen(gcryalg); + #ifdef CONFIG_QEMU_PRIVATE_XTS if (mode == QCRYPTO_CIPHER_MODE_XTS) { + if (ctx->blocksize != XTS_BLOCK_SIZE) { + error_setg(errp, + "Cipher block size %zu must equal XTS block size %d", + ctx->blocksize, XTS_BLOCK_SIZE); + goto error; + } err = gcry_cipher_open(&ctx->tweakhandle, gcryalg, gcrymode, 0); if (err != 0) { error_setg(errp, "Cannot initialize cipher: %s", @@ -203,220 +379,31 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, uint8_t *rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey); err = gcry_cipher_setkey(ctx->handle, rfbkey, nkey); g_free(rfbkey); - ctx->blocksize = 8; } else { #ifdef CONFIG_QEMU_PRIVATE_XTS if (mode == QCRYPTO_CIPHER_MODE_XTS) { nkey /= 2; - err = gcry_cipher_setkey(ctx->handle, key, nkey); + err = gcry_cipher_setkey(ctx->tweakhandle, key + nkey, nkey); if (err != 0) { - error_setg(errp, "Cannot set key: %s", - gcry_strerror(err)); + error_setg(errp, "Cannot set key: %s", gcry_strerror(err)); goto error; } - err = gcry_cipher_setkey(ctx->tweakhandle, key + nkey, nkey); - } else { -#endif - err = gcry_cipher_setkey(ctx->handle, key, nkey); -#ifdef CONFIG_QEMU_PRIVATE_XTS - } -#endif - if (err != 0) { - error_setg(errp, "Cannot set key: %s", - gcry_strerror(err)); - goto error; } - switch (alg) { - case QCRYPTO_CIPHER_ALG_AES_128: - case QCRYPTO_CIPHER_ALG_AES_192: - case QCRYPTO_CIPHER_ALG_AES_256: - case QCRYPTO_CIPHER_ALG_SERPENT_128: - case QCRYPTO_CIPHER_ALG_SERPENT_192: - case QCRYPTO_CIPHER_ALG_SERPENT_256: - case QCRYPTO_CIPHER_ALG_TWOFISH_128: - case QCRYPTO_CIPHER_ALG_TWOFISH_256: - ctx->blocksize = 16; - break; - case QCRYPTO_CIPHER_ALG_3DES: - case QCRYPTO_CIPHER_ALG_CAST5_128: - ctx->blocksize = 8; - break; - default: - g_assert_not_reached(); - } - } - -#ifdef CONFIG_QEMU_PRIVATE_XTS - if (mode == QCRYPTO_CIPHER_MODE_XTS) { - if (ctx->blocksize != XTS_BLOCK_SIZE) { - error_setg(errp, - "Cipher block size %zu must equal XTS block size %d", - ctx->blocksize, XTS_BLOCK_SIZE); - goto error; - } - ctx->iv = g_new0(uint8_t, ctx->blocksize); - } -#endif - - return ctx; - - error: - qcrypto_gcrypt_cipher_free_ctx(ctx, mode); - return NULL; -} - - -static void -qcrypto_gcrypt_cipher_ctx_free(QCryptoCipher *cipher) -{ - qcrypto_gcrypt_cipher_free_ctx(cipher->opaque, cipher->mode); -} - - -#ifdef CONFIG_QEMU_PRIVATE_XTS -static void qcrypto_gcrypt_xts_encrypt(const void *ctx, - size_t length, - uint8_t *dst, - const uint8_t *src) -{ - gcry_error_t err; - err = gcry_cipher_encrypt((gcry_cipher_hd_t)ctx, dst, length, src, length); - g_assert(err == 0); -} - -static void qcrypto_gcrypt_xts_decrypt(const void *ctx, - size_t length, - uint8_t *dst, - const uint8_t *src) -{ - gcry_error_t err; - err = gcry_cipher_decrypt((gcry_cipher_hd_t)ctx, dst, length, src, length); - g_assert(err == 0); -} #endif - -static int -qcrypto_gcrypt_cipher_encrypt(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) -{ - QCryptoCipherGcrypt *ctx = cipher->opaque; - gcry_error_t err; - - if (len % ctx->blocksize) { - error_setg(errp, "Length %zu must be a multiple of block size %zu", - len, ctx->blocksize); - return -1; + err = gcry_cipher_setkey(ctx->handle, key, nkey); } - -#ifdef CONFIG_QEMU_PRIVATE_XTS - if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) { - xts_encrypt(ctx->handle, ctx->tweakhandle, - qcrypto_gcrypt_xts_encrypt, - qcrypto_gcrypt_xts_decrypt, - ctx->iv, len, out, in); - return 0; - } -#endif - - err = gcry_cipher_encrypt(ctx->handle, - out, len, - in, len); if (err != 0) { - error_setg(errp, "Cannot encrypt data: %s", - gcry_strerror(err)); - return -1; - } - - return 0; -} - - -static int -qcrypto_gcrypt_cipher_decrypt(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) -{ - QCryptoCipherGcrypt *ctx = cipher->opaque; - gcry_error_t err; - - if (len % ctx->blocksize) { - error_setg(errp, "Length %zu must be a multiple of block size %zu", - len, ctx->blocksize); - return -1; - } - -#ifdef CONFIG_QEMU_PRIVATE_XTS - if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) { - xts_decrypt(ctx->handle, ctx->tweakhandle, - qcrypto_gcrypt_xts_encrypt, - qcrypto_gcrypt_xts_decrypt, - ctx->iv, len, out, in); - return 0; - } -#endif - - err = gcry_cipher_decrypt(ctx->handle, - out, len, - in, len); - if (err != 0) { - error_setg(errp, "Cannot decrypt data: %s", - gcry_strerror(err)); - return -1; + error_setg(errp, "Cannot set key: %s", gcry_strerror(err)); + goto error; } - return 0; -} - -static int -qcrypto_gcrypt_cipher_setiv(QCryptoCipher *cipher, - const uint8_t *iv, size_t niv, - Error **errp) -{ - QCryptoCipherGcrypt *ctx = cipher->opaque; - gcry_error_t err; - - if (niv != ctx->blocksize) { - error_setg(errp, "Expected IV size %zu not %zu", - ctx->blocksize, niv); - return -1; - } + return &ctx->base; + error: #ifdef CONFIG_QEMU_PRIVATE_XTS - if (ctx->iv) { - memcpy(ctx->iv, iv, niv); - return 0; - } + gcry_cipher_close(ctx->tweakhandle); #endif - - if (cipher->mode == QCRYPTO_CIPHER_MODE_CTR) { - err = gcry_cipher_setctr(ctx->handle, iv, niv); - if (err != 0) { - error_setg(errp, "Cannot set Counter: %s", - gcry_strerror(err)); - return -1; - } - } else { - gcry_cipher_reset(ctx->handle); - err = gcry_cipher_setiv(ctx->handle, iv, niv); - if (err != 0) { - error_setg(errp, "Cannot set IV: %s", - gcry_strerror(err)); - return -1; - } - } - - return 0; + gcry_cipher_close(ctx->handle); + g_free(ctx); + return NULL; } - - -static struct QCryptoCipherDriver qcrypto_cipher_lib_driver = { - .cipher_encrypt = qcrypto_gcrypt_cipher_encrypt, - .cipher_decrypt = qcrypto_gcrypt_cipher_decrypt, - .cipher_setiv = qcrypto_gcrypt_cipher_setiv, - .cipher_free = qcrypto_gcrypt_cipher_ctx_free, -}; diff --git a/crypto/cipher-nettle.c b/crypto/cipher-nettle.c deleted file mode 100644 index 7e9a4cc19993a1bccdf48c4e9e90aca162880f18..0000000000000000000000000000000000000000 --- a/crypto/cipher-nettle.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - * QEMU Crypto cipher nettle algorithms - * - * Copyright (c) 2015 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - * - */ - -#include "qemu/osdep.h" -#ifdef CONFIG_QEMU_PRIVATE_XTS -#include "crypto/xts.h" -#endif -#include "cipherpriv.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef CONFIG_QEMU_PRIVATE_XTS -#include -#endif - -typedef void (*QCryptoCipherNettleFuncWrapper)(const void *ctx, - size_t length, - uint8_t *dst, - const uint8_t *src); - -#if CONFIG_NETTLE_VERSION_MAJOR < 3 -typedef nettle_crypt_func * QCryptoCipherNettleFuncNative; -typedef void * cipher_ctx_t; -typedef unsigned cipher_length_t; - -#define cast5_set_key cast128_set_key - -#define aes128_ctx aes_ctx -#define aes192_ctx aes_ctx -#define aes256_ctx aes_ctx -#define aes128_set_encrypt_key(c, k) \ - aes_set_encrypt_key(c, 16, k) -#define aes192_set_encrypt_key(c, k) \ - aes_set_encrypt_key(c, 24, k) -#define aes256_set_encrypt_key(c, k) \ - aes_set_encrypt_key(c, 32, k) -#define aes128_set_decrypt_key(c, k) \ - aes_set_decrypt_key(c, 16, k) -#define aes192_set_decrypt_key(c, k) \ - aes_set_decrypt_key(c, 24, k) -#define aes256_set_decrypt_key(c, k) \ - aes_set_decrypt_key(c, 32, k) -#define aes128_encrypt aes_encrypt -#define aes192_encrypt aes_encrypt -#define aes256_encrypt aes_encrypt -#define aes128_decrypt aes_decrypt -#define aes192_decrypt aes_decrypt -#define aes256_decrypt aes_decrypt -#else -typedef nettle_cipher_func * QCryptoCipherNettleFuncNative; -typedef const void * cipher_ctx_t; -typedef size_t cipher_length_t; -#endif - -typedef struct QCryptoNettleAES128 { - struct aes128_ctx enc; - struct aes128_ctx dec; -} QCryptoNettleAES128; - -typedef struct QCryptoNettleAES192 { - struct aes192_ctx enc; - struct aes192_ctx dec; -} QCryptoNettleAES192; - -typedef struct QCryptoNettleAES256 { - struct aes256_ctx enc; - struct aes256_ctx dec; -} QCryptoNettleAES256; - -static void aes128_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, - uint8_t *dst, const uint8_t *src) -{ - const QCryptoNettleAES128 *aesctx = ctx; - aes128_encrypt(&aesctx->enc, length, dst, src); -} - -static void aes128_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, - uint8_t *dst, const uint8_t *src) -{ - const QCryptoNettleAES128 *aesctx = ctx; - aes128_decrypt(&aesctx->dec, length, dst, src); -} - -static void aes192_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, - uint8_t *dst, const uint8_t *src) -{ - const QCryptoNettleAES192 *aesctx = ctx; - aes192_encrypt(&aesctx->enc, length, dst, src); -} - -static void aes192_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, - uint8_t *dst, const uint8_t *src) -{ - const QCryptoNettleAES192 *aesctx = ctx; - aes192_decrypt(&aesctx->dec, length, dst, src); -} - -static void aes256_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, - uint8_t *dst, const uint8_t *src) -{ - const QCryptoNettleAES256 *aesctx = ctx; - aes256_encrypt(&aesctx->enc, length, dst, src); -} - -static void aes256_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, - uint8_t *dst, const uint8_t *src) -{ - const QCryptoNettleAES256 *aesctx = ctx; - aes256_decrypt(&aesctx->dec, length, dst, src); -} - -static void des_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, - uint8_t *dst, const uint8_t *src) -{ - des_encrypt(ctx, length, dst, src); -} - -static void des_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, - uint8_t *dst, const uint8_t *src) -{ - des_decrypt(ctx, length, dst, src); -} - -static void des3_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, - uint8_t *dst, const uint8_t *src) -{ - des3_encrypt(ctx, length, dst, src); -} - -static void des3_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, - uint8_t *dst, const uint8_t *src) -{ - des3_decrypt(ctx, length, dst, src); -} - -static void cast128_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, - uint8_t *dst, const uint8_t *src) -{ - cast128_encrypt(ctx, length, dst, src); -} - -static void cast128_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, - uint8_t *dst, const uint8_t *src) -{ - cast128_decrypt(ctx, length, dst, src); -} - -static void serpent_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, - uint8_t *dst, const uint8_t *src) -{ - serpent_encrypt(ctx, length, dst, src); -} - -static void serpent_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, - uint8_t *dst, const uint8_t *src) -{ - serpent_decrypt(ctx, length, dst, src); -} - -static void twofish_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, - uint8_t *dst, const uint8_t *src) -{ - twofish_encrypt(ctx, length, dst, src); -} - -static void twofish_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, - uint8_t *dst, const uint8_t *src) -{ - twofish_decrypt(ctx, length, dst, src); -} - -static void aes128_encrypt_wrapper(const void *ctx, size_t length, - uint8_t *dst, const uint8_t *src) -{ - const QCryptoNettleAES128 *aesctx = ctx; - aes128_encrypt(&aesctx->enc, length, dst, src); -} - -static void aes128_decrypt_wrapper(const void *ctx, size_t length, - uint8_t *dst, const uint8_t *src) -{ - const QCryptoNettleAES128 *aesctx = ctx; - aes128_decrypt(&aesctx->dec, length, dst, src); -} - -static void aes192_encrypt_wrapper(const void *ctx, size_t length, - uint8_t *dst, const uint8_t *src) -{ - const QCryptoNettleAES192 *aesctx = ctx; - aes192_encrypt(&aesctx->enc, length, dst, src); -} - -static void aes192_decrypt_wrapper(const void *ctx, size_t length, - uint8_t *dst, const uint8_t *src) -{ - const QCryptoNettleAES192 *aesctx = ctx; - aes192_decrypt(&aesctx->dec, length, dst, src); -} - -static void aes256_encrypt_wrapper(const void *ctx, size_t length, - uint8_t *dst, const uint8_t *src) -{ - const QCryptoNettleAES256 *aesctx = ctx; - aes256_encrypt(&aesctx->enc, length, dst, src); -} - -static void aes256_decrypt_wrapper(const void *ctx, size_t length, - uint8_t *dst, const uint8_t *src) -{ - const QCryptoNettleAES256 *aesctx = ctx; - aes256_decrypt(&aesctx->dec, length, dst, src); -} - -static void des_encrypt_wrapper(const void *ctx, size_t length, - uint8_t *dst, const uint8_t *src) -{ - des_encrypt(ctx, length, dst, src); -} - -static void des_decrypt_wrapper(const void *ctx, size_t length, - uint8_t *dst, const uint8_t *src) -{ - des_decrypt(ctx, length, dst, src); -} - -static void des3_encrypt_wrapper(const void *ctx, size_t length, - uint8_t *dst, const uint8_t *src) -{ - des3_encrypt(ctx, length, dst, src); -} - -static void des3_decrypt_wrapper(const void *ctx, size_t length, - uint8_t *dst, const uint8_t *src) -{ - des3_decrypt(ctx, length, dst, src); -} - -static void cast128_encrypt_wrapper(const void *ctx, size_t length, - uint8_t *dst, const uint8_t *src) -{ - cast128_encrypt(ctx, length, dst, src); -} - -static void cast128_decrypt_wrapper(const void *ctx, size_t length, - uint8_t *dst, const uint8_t *src) -{ - cast128_decrypt(ctx, length, dst, src); -} - -static void serpent_encrypt_wrapper(const void *ctx, size_t length, - uint8_t *dst, const uint8_t *src) -{ - serpent_encrypt(ctx, length, dst, src); -} - -static void serpent_decrypt_wrapper(const void *ctx, size_t length, - uint8_t *dst, const uint8_t *src) -{ - serpent_decrypt(ctx, length, dst, src); -} - -static void twofish_encrypt_wrapper(const void *ctx, size_t length, - uint8_t *dst, const uint8_t *src) -{ - twofish_encrypt(ctx, length, dst, src); -} - -static void twofish_decrypt_wrapper(const void *ctx, size_t length, - uint8_t *dst, const uint8_t *src) -{ - twofish_decrypt(ctx, length, dst, src); -} - -typedef struct QCryptoCipherNettle QCryptoCipherNettle; -struct QCryptoCipherNettle { - /* Primary cipher context for all modes */ - void *ctx; - /* Second cipher context for XTS mode only */ - void *ctx_tweak; - /* Cipher callbacks for both contexts */ - QCryptoCipherNettleFuncNative alg_encrypt_native; - QCryptoCipherNettleFuncNative alg_decrypt_native; - QCryptoCipherNettleFuncWrapper alg_encrypt_wrapper; - QCryptoCipherNettleFuncWrapper alg_decrypt_wrapper; - /* Initialization vector or Counter */ - uint8_t *iv; - size_t blocksize; -}; - -bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, - QCryptoCipherMode mode) -{ - switch (alg) { - case QCRYPTO_CIPHER_ALG_DES_RFB: - case QCRYPTO_CIPHER_ALG_3DES: - case QCRYPTO_CIPHER_ALG_AES_128: - case QCRYPTO_CIPHER_ALG_AES_192: - case QCRYPTO_CIPHER_ALG_AES_256: - case QCRYPTO_CIPHER_ALG_CAST5_128: - case QCRYPTO_CIPHER_ALG_SERPENT_128: - case QCRYPTO_CIPHER_ALG_SERPENT_192: - case QCRYPTO_CIPHER_ALG_SERPENT_256: - case QCRYPTO_CIPHER_ALG_TWOFISH_128: - case QCRYPTO_CIPHER_ALG_TWOFISH_192: - case QCRYPTO_CIPHER_ALG_TWOFISH_256: - break; - default: - return false; - } - - switch (mode) { - case QCRYPTO_CIPHER_MODE_ECB: - case QCRYPTO_CIPHER_MODE_CBC: - case QCRYPTO_CIPHER_MODE_XTS: - case QCRYPTO_CIPHER_MODE_CTR: - return true; - default: - return false; - } -} - - -static void -qcrypto_nettle_cipher_free_ctx(QCryptoCipherNettle *ctx) -{ - if (!ctx) { - return; - } - - g_free(ctx->iv); - g_free(ctx->ctx); - g_free(ctx->ctx_tweak); - g_free(ctx); -} - - -static QCryptoCipherNettle *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, - QCryptoCipherMode mode, - const uint8_t *key, - size_t nkey, - Error **errp) -{ - QCryptoCipherNettle *ctx; - uint8_t *rfbkey; - - switch (mode) { - case QCRYPTO_CIPHER_MODE_ECB: - case QCRYPTO_CIPHER_MODE_CBC: - case QCRYPTO_CIPHER_MODE_XTS: - case QCRYPTO_CIPHER_MODE_CTR: - break; - default: - error_setg(errp, "Unsupported cipher mode %s", - QCryptoCipherMode_str(mode)); - return NULL; - } - - if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) { - return NULL; - } - - ctx = g_new0(QCryptoCipherNettle, 1); - - switch (alg) { - case QCRYPTO_CIPHER_ALG_DES_RFB: - ctx->ctx = g_new0(struct des_ctx, 1); - rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey); - des_set_key(ctx->ctx, rfbkey); - g_free(rfbkey); - - ctx->alg_encrypt_native = des_encrypt_native; - ctx->alg_decrypt_native = des_decrypt_native; - ctx->alg_encrypt_wrapper = des_encrypt_wrapper; - ctx->alg_decrypt_wrapper = des_decrypt_wrapper; - - ctx->blocksize = DES_BLOCK_SIZE; - break; - - case QCRYPTO_CIPHER_ALG_3DES: - ctx->ctx = g_new0(struct des3_ctx, 1); - des3_set_key(ctx->ctx, key); - - ctx->alg_encrypt_native = des3_encrypt_native; - ctx->alg_decrypt_native = des3_decrypt_native; - ctx->alg_encrypt_wrapper = des3_encrypt_wrapper; - ctx->alg_decrypt_wrapper = des3_decrypt_wrapper; - - ctx->blocksize = DES3_BLOCK_SIZE; - break; - - case QCRYPTO_CIPHER_ALG_AES_128: - ctx->ctx = g_new0(QCryptoNettleAES128, 1); - - if (mode == QCRYPTO_CIPHER_MODE_XTS) { - ctx->ctx_tweak = g_new0(QCryptoNettleAES128, 1); - - nkey /= 2; - aes128_set_encrypt_key(&((QCryptoNettleAES128 *)ctx->ctx)->enc, - key); - aes128_set_decrypt_key(&((QCryptoNettleAES128 *)ctx->ctx)->dec, - key); - - aes128_set_encrypt_key(&((QCryptoNettleAES128 *)ctx->ctx_tweak)-> - enc, key + nkey); - aes128_set_decrypt_key(&((QCryptoNettleAES128 *)ctx->ctx_tweak)-> - dec, key + nkey); - } else { - aes128_set_encrypt_key(&((QCryptoNettleAES128 *)ctx->ctx)->enc, - key); - aes128_set_decrypt_key(&((QCryptoNettleAES128 *)ctx->ctx)->dec, - key); - } - - ctx->alg_encrypt_native = aes128_encrypt_native; - ctx->alg_decrypt_native = aes128_decrypt_native; - ctx->alg_encrypt_wrapper = aes128_encrypt_wrapper; - ctx->alg_decrypt_wrapper = aes128_decrypt_wrapper; - - ctx->blocksize = AES_BLOCK_SIZE; - break; - - case QCRYPTO_CIPHER_ALG_AES_192: - ctx->ctx = g_new0(QCryptoNettleAES192, 1); - - if (mode == QCRYPTO_CIPHER_MODE_XTS) { - ctx->ctx_tweak = g_new0(QCryptoNettleAES192, 1); - - nkey /= 2; - aes192_set_encrypt_key(&((QCryptoNettleAES192 *)ctx->ctx)->enc, - key); - aes192_set_decrypt_key(&((QCryptoNettleAES192 *)ctx->ctx)->dec, - key); - - aes192_set_encrypt_key(&((QCryptoNettleAES192 *)ctx->ctx_tweak)-> - enc, key + nkey); - aes192_set_decrypt_key(&((QCryptoNettleAES192 *)ctx->ctx_tweak)-> - dec, key + nkey); - } else { - aes192_set_encrypt_key(&((QCryptoNettleAES192 *)ctx->ctx)->enc, - key); - aes192_set_decrypt_key(&((QCryptoNettleAES192 *)ctx->ctx)->dec, - key); - } - - ctx->alg_encrypt_native = aes192_encrypt_native; - ctx->alg_decrypt_native = aes192_decrypt_native; - ctx->alg_encrypt_wrapper = aes192_encrypt_wrapper; - ctx->alg_decrypt_wrapper = aes192_decrypt_wrapper; - - ctx->blocksize = AES_BLOCK_SIZE; - break; - - case QCRYPTO_CIPHER_ALG_AES_256: - ctx->ctx = g_new0(QCryptoNettleAES256, 1); - - if (mode == QCRYPTO_CIPHER_MODE_XTS) { - ctx->ctx_tweak = g_new0(QCryptoNettleAES256, 1); - - nkey /= 2; - aes256_set_encrypt_key(&((QCryptoNettleAES256 *)ctx->ctx)->enc, - key); - aes256_set_decrypt_key(&((QCryptoNettleAES256 *)ctx->ctx)->dec, - key); - - aes256_set_encrypt_key(&((QCryptoNettleAES256 *)ctx->ctx_tweak)-> - enc, key + nkey); - aes256_set_decrypt_key(&((QCryptoNettleAES256 *)ctx->ctx_tweak)-> - dec, key + nkey); - } else { - aes256_set_encrypt_key(&((QCryptoNettleAES256 *)ctx->ctx)->enc, - key); - aes256_set_decrypt_key(&((QCryptoNettleAES256 *)ctx->ctx)->dec, - key); - } - - ctx->alg_encrypt_native = aes256_encrypt_native; - ctx->alg_decrypt_native = aes256_decrypt_native; - ctx->alg_encrypt_wrapper = aes256_encrypt_wrapper; - ctx->alg_decrypt_wrapper = aes256_decrypt_wrapper; - - ctx->blocksize = AES_BLOCK_SIZE; - break; - - case QCRYPTO_CIPHER_ALG_CAST5_128: - ctx->ctx = g_new0(struct cast128_ctx, 1); - - if (mode == QCRYPTO_CIPHER_MODE_XTS) { - ctx->ctx_tweak = g_new0(struct cast128_ctx, 1); - - nkey /= 2; - cast5_set_key(ctx->ctx, nkey, key); - cast5_set_key(ctx->ctx_tweak, nkey, key + nkey); - } else { - cast5_set_key(ctx->ctx, nkey, key); - } - - ctx->alg_encrypt_native = cast128_encrypt_native; - ctx->alg_decrypt_native = cast128_decrypt_native; - ctx->alg_encrypt_wrapper = cast128_encrypt_wrapper; - ctx->alg_decrypt_wrapper = cast128_decrypt_wrapper; - - ctx->blocksize = CAST128_BLOCK_SIZE; - break; - - case QCRYPTO_CIPHER_ALG_SERPENT_128: - case QCRYPTO_CIPHER_ALG_SERPENT_192: - case QCRYPTO_CIPHER_ALG_SERPENT_256: - ctx->ctx = g_new0(struct serpent_ctx, 1); - - if (mode == QCRYPTO_CIPHER_MODE_XTS) { - ctx->ctx_tweak = g_new0(struct serpent_ctx, 1); - - nkey /= 2; - serpent_set_key(ctx->ctx, nkey, key); - serpent_set_key(ctx->ctx_tweak, nkey, key + nkey); - } else { - serpent_set_key(ctx->ctx, nkey, key); - } - - ctx->alg_encrypt_native = serpent_encrypt_native; - ctx->alg_decrypt_native = serpent_decrypt_native; - ctx->alg_encrypt_wrapper = serpent_encrypt_wrapper; - ctx->alg_decrypt_wrapper = serpent_decrypt_wrapper; - - ctx->blocksize = SERPENT_BLOCK_SIZE; - break; - - case QCRYPTO_CIPHER_ALG_TWOFISH_128: - case QCRYPTO_CIPHER_ALG_TWOFISH_192: - case QCRYPTO_CIPHER_ALG_TWOFISH_256: - ctx->ctx = g_new0(struct twofish_ctx, 1); - - if (mode == QCRYPTO_CIPHER_MODE_XTS) { - ctx->ctx_tweak = g_new0(struct twofish_ctx, 1); - - nkey /= 2; - twofish_set_key(ctx->ctx, nkey, key); - twofish_set_key(ctx->ctx_tweak, nkey, key + nkey); - } else { - twofish_set_key(ctx->ctx, nkey, key); - } - - ctx->alg_encrypt_native = twofish_encrypt_native; - ctx->alg_decrypt_native = twofish_decrypt_native; - ctx->alg_encrypt_wrapper = twofish_encrypt_wrapper; - ctx->alg_decrypt_wrapper = twofish_decrypt_wrapper; - - ctx->blocksize = TWOFISH_BLOCK_SIZE; - break; - - default: - error_setg(errp, "Unsupported cipher algorithm %s", - QCryptoCipherAlgorithm_str(alg)); - goto error; - } - - if (mode == QCRYPTO_CIPHER_MODE_XTS && - ctx->blocksize != XTS_BLOCK_SIZE) { - error_setg(errp, "Cipher block size %zu must equal XTS block size %d", - ctx->blocksize, XTS_BLOCK_SIZE); - goto error; - } - - ctx->iv = g_new0(uint8_t, ctx->blocksize); - - return ctx; - - error: - qcrypto_nettle_cipher_free_ctx(ctx); - return NULL; -} - - -static void -qcrypto_nettle_cipher_ctx_free(QCryptoCipher *cipher) -{ - QCryptoCipherNettle *ctx; - - ctx = cipher->opaque; - qcrypto_nettle_cipher_free_ctx(ctx); -} - - -static int -qcrypto_nettle_cipher_encrypt(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) -{ - QCryptoCipherNettle *ctx = cipher->opaque; - - if (len % ctx->blocksize) { - error_setg(errp, "Length %zu must be a multiple of block size %zu", - len, ctx->blocksize); - return -1; - } - - switch (cipher->mode) { - case QCRYPTO_CIPHER_MODE_ECB: - ctx->alg_encrypt_wrapper(ctx->ctx, len, out, in); - break; - - case QCRYPTO_CIPHER_MODE_CBC: - cbc_encrypt(ctx->ctx, ctx->alg_encrypt_native, - ctx->blocksize, ctx->iv, - len, out, in); - break; - - case QCRYPTO_CIPHER_MODE_XTS: -#ifdef CONFIG_QEMU_PRIVATE_XTS - xts_encrypt(ctx->ctx, ctx->ctx_tweak, - ctx->alg_encrypt_wrapper, ctx->alg_encrypt_wrapper, - ctx->iv, len, out, in); -#else - xts_encrypt_message(ctx->ctx, ctx->ctx_tweak, - ctx->alg_encrypt_native, - ctx->iv, len, out, in); -#endif - break; - - case QCRYPTO_CIPHER_MODE_CTR: - ctr_crypt(ctx->ctx, ctx->alg_encrypt_native, - ctx->blocksize, ctx->iv, - len, out, in); - break; - - default: - error_setg(errp, "Unsupported cipher mode %s", - QCryptoCipherMode_str(cipher->mode)); - return -1; - } - return 0; -} - - -static int -qcrypto_nettle_cipher_decrypt(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) -{ - QCryptoCipherNettle *ctx = cipher->opaque; - - if (len % ctx->blocksize) { - error_setg(errp, "Length %zu must be a multiple of block size %zu", - len, ctx->blocksize); - return -1; - } - - switch (cipher->mode) { - case QCRYPTO_CIPHER_MODE_ECB: - ctx->alg_decrypt_wrapper(ctx->ctx, len, out, in); - break; - - case QCRYPTO_CIPHER_MODE_CBC: - cbc_decrypt(ctx->ctx, ctx->alg_decrypt_native, - ctx->blocksize, ctx->iv, - len, out, in); - break; - - case QCRYPTO_CIPHER_MODE_XTS: -#ifdef CONFIG_QEMU_PRIVATE_XTS - xts_decrypt(ctx->ctx, ctx->ctx_tweak, - ctx->alg_encrypt_wrapper, ctx->alg_decrypt_wrapper, - ctx->iv, len, out, in); -#else - xts_decrypt_message(ctx->ctx, ctx->ctx_tweak, - ctx->alg_decrypt_native, - ctx->alg_encrypt_native, - ctx->iv, len, out, in); -#endif - break; - case QCRYPTO_CIPHER_MODE_CTR: - ctr_crypt(ctx->ctx, ctx->alg_encrypt_native, - ctx->blocksize, ctx->iv, - len, out, in); - break; - - default: - error_setg(errp, "Unsupported cipher mode %s", - QCryptoCipherMode_str(cipher->mode)); - return -1; - } - return 0; -} - -static int -qcrypto_nettle_cipher_setiv(QCryptoCipher *cipher, - const uint8_t *iv, size_t niv, - Error **errp) -{ - QCryptoCipherNettle *ctx = cipher->opaque; - if (niv != ctx->blocksize) { - error_setg(errp, "Expected IV size %zu not %zu", - ctx->blocksize, niv); - return -1; - } - memcpy(ctx->iv, iv, niv); - return 0; -} - - -static struct QCryptoCipherDriver qcrypto_cipher_lib_driver = { - .cipher_encrypt = qcrypto_nettle_cipher_encrypt, - .cipher_decrypt = qcrypto_nettle_cipher_decrypt, - .cipher_setiv = qcrypto_nettle_cipher_setiv, - .cipher_free = qcrypto_nettle_cipher_ctx_free, -}; diff --git a/crypto/cipher-nettle.c.inc b/crypto/cipher-nettle.c.inc new file mode 100644 index 0000000000000000000000000000000000000000..cac771e4ff7bd93a055a968aa5ad4cd0750ec9b5 --- /dev/null +++ b/crypto/cipher-nettle.c.inc @@ -0,0 +1,760 @@ +/* + * QEMU Crypto cipher nettle algorithms + * + * Copyright (c) 2015 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + */ + +#ifdef CONFIG_QEMU_PRIVATE_XTS +#include "crypto/xts.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef CONFIG_QEMU_PRIVATE_XTS +#include +#endif + +typedef void (*QCryptoCipherNettleFuncWrapper)(const void *ctx, + size_t length, + uint8_t *dst, + const uint8_t *src); + +#if CONFIG_NETTLE_VERSION_MAJOR < 3 +typedef nettle_crypt_func * QCryptoCipherNettleFuncNative; +typedef void * cipher_ctx_t; +typedef unsigned cipher_length_t; +#define CONST_CTX + +#define cast5_set_key cast128_set_key + +#define aes128_ctx aes_ctx +#define aes192_ctx aes_ctx +#define aes256_ctx aes_ctx +#define aes128_set_encrypt_key(c, k) \ + aes_set_encrypt_key(c, 16, k) +#define aes192_set_encrypt_key(c, k) \ + aes_set_encrypt_key(c, 24, k) +#define aes256_set_encrypt_key(c, k) \ + aes_set_encrypt_key(c, 32, k) +#define aes128_set_decrypt_key(c, k) \ + aes_set_decrypt_key(c, 16, k) +#define aes192_set_decrypt_key(c, k) \ + aes_set_decrypt_key(c, 24, k) +#define aes256_set_decrypt_key(c, k) \ + aes_set_decrypt_key(c, 32, k) +#define aes128_encrypt aes_encrypt +#define aes192_encrypt aes_encrypt +#define aes256_encrypt aes_encrypt +#define aes128_decrypt aes_decrypt +#define aes192_decrypt aes_decrypt +#define aes256_decrypt aes_decrypt +#else +typedef nettle_cipher_func * QCryptoCipherNettleFuncNative; +typedef const void * cipher_ctx_t; +typedef size_t cipher_length_t; +#define CONST_CTX const +#endif + +static inline bool qcrypto_length_check(size_t len, size_t blocksize, + Error **errp) +{ + if (unlikely(len & (blocksize - 1))) { + error_setg(errp, "Length %zu must be a multiple of block size %zu", + len, blocksize); + return false; + } + return true; +} + + +static void qcrypto_cipher_ctx_free(QCryptoCipher *ctx) +{ + g_free(ctx); +} + +static int qcrypto_cipher_no_setiv(QCryptoCipher *cipher, + const uint8_t *iv, size_t niv, + Error **errp) +{ + error_setg(errp, "Setting IV is not supported"); + return -1; +} + + +#define DEFINE_SETIV(NAME, TYPE, BLEN) \ +static int NAME##_setiv(QCryptoCipher *cipher, const uint8_t *iv, \ + size_t niv, Error **errp) \ +{ \ + TYPE *ctx = container_of(cipher, TYPE, base); \ + if (niv != BLEN) { \ + error_setg(errp, "Expected IV size %d not %zu", BLEN, niv); \ + return -1; \ + } \ + memcpy(ctx->iv, iv, niv); \ + return 0; \ +} + + +#define DEFINE_ECB(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \ +static int NAME##_encrypt_ecb(QCryptoCipher *cipher, const void *in, \ + void *out, size_t len, Error **errp) \ +{ \ + TYPE *ctx = container_of(cipher, TYPE, base); \ + if (!qcrypto_length_check(len, BLEN, errp)) { \ + return -1; \ + } \ + ENCRYPT(&ctx->key, len, out, in); \ + return 0; \ +} \ +static int NAME##_decrypt_ecb(QCryptoCipher *cipher, const void *in, \ + void *out, size_t len, Error **errp) \ +{ \ + TYPE *ctx = container_of(cipher, TYPE, base); \ + if (!qcrypto_length_check(len, BLEN, errp)) { \ + return -1; \ + } \ + DECRYPT(&ctx->key, len, out, in); \ + return 0; \ +} \ +static const struct QCryptoCipherDriver NAME##_driver_ecb = { \ + .cipher_encrypt = NAME##_encrypt_ecb, \ + .cipher_decrypt = NAME##_decrypt_ecb, \ + .cipher_setiv = qcrypto_cipher_no_setiv, \ + .cipher_free = qcrypto_cipher_ctx_free, \ +}; + + +#define DEFINE_CBC(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \ +static int NAME##_encrypt_cbc(QCryptoCipher *cipher, const void *in, \ + void *out, size_t len, Error **errp) \ +{ \ + TYPE *ctx = container_of(cipher, TYPE, base); \ + if (!qcrypto_length_check(len, BLEN, errp)) { \ + return -1; \ + } \ + cbc_encrypt(&ctx->key, ENCRYPT, BLEN, ctx->iv, len, out, in); \ + return 0; \ +} \ +static int NAME##_decrypt_cbc(QCryptoCipher *cipher, const void *in, \ + void *out, size_t len, Error **errp) \ +{ \ + TYPE *ctx = container_of(cipher, TYPE, base); \ + if (!qcrypto_length_check(len, BLEN, errp)) { \ + return -1; \ + } \ + cbc_decrypt(&ctx->key, DECRYPT, BLEN, ctx->iv, len, out, in); \ + return 0; \ +} \ +static const struct QCryptoCipherDriver NAME##_driver_cbc = { \ + .cipher_encrypt = NAME##_encrypt_cbc, \ + .cipher_decrypt = NAME##_decrypt_cbc, \ + .cipher_setiv = NAME##_setiv, \ + .cipher_free = qcrypto_cipher_ctx_free, \ +}; + + +#define DEFINE_CTR(NAME, TYPE, BLEN, ENCRYPT) \ +static int NAME##_encrypt_ctr(QCryptoCipher *cipher, const void *in, \ + void *out, size_t len, Error **errp) \ +{ \ + TYPE *ctx = container_of(cipher, TYPE, base); \ + if (!qcrypto_length_check(len, BLEN, errp)) { \ + return -1; \ + } \ + ctr_crypt(&ctx->key, ENCRYPT, BLEN, ctx->iv, len, out, in); \ + return 0; \ +} \ +static const struct QCryptoCipherDriver NAME##_driver_ctr = { \ + .cipher_encrypt = NAME##_encrypt_ctr, \ + .cipher_decrypt = NAME##_encrypt_ctr, \ + .cipher_setiv = NAME##_setiv, \ + .cipher_free = qcrypto_cipher_ctx_free, \ +}; + + +#ifdef CONFIG_QEMU_PRIVATE_XTS +#define DEFINE__XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \ +static void NAME##_xts_wrape(const void *ctx, size_t length, \ + uint8_t *dst, const uint8_t *src) \ +{ \ + ENCRYPT((cipher_ctx_t)ctx, length, dst, src); \ +} \ +static void NAME##_xts_wrapd(const void *ctx, size_t length, \ + uint8_t *dst, const uint8_t *src) \ +{ \ + DECRYPT((cipher_ctx_t)ctx, length, dst, src); \ +} \ +static int NAME##_encrypt_xts(QCryptoCipher *cipher, const void *in, \ + void *out, size_t len, Error **errp) \ +{ \ + TYPE *ctx = container_of(cipher, TYPE, base); \ + if (!qcrypto_length_check(len, BLEN, errp)) { \ + return -1; \ + } \ + xts_encrypt(&ctx->key, &ctx->key_xts, \ + NAME##_xts_wrape, NAME##_xts_wrapd, \ + ctx->iv, len, out, in); \ + return 0; \ +} \ +static int NAME##_decrypt_xts(QCryptoCipher *cipher, const void *in, \ + void *out, size_t len, Error **errp) \ +{ \ + TYPE *ctx = container_of(cipher, TYPE, base); \ + if (!qcrypto_length_check(len, BLEN, errp)) { \ + return -1; \ + } \ + xts_decrypt(&ctx->key, &ctx->key_xts, \ + NAME##_xts_wrape, NAME##_xts_wrapd, \ + ctx->iv, len, out, in); \ + return 0; \ +} +#else +#define DEFINE__XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \ +static int NAME##_encrypt_xts(QCryptoCipher *cipher, const void *in, \ + void *out, size_t len, Error **errp) \ +{ \ + TYPE *ctx = container_of(cipher, TYPE, base); \ + if (!qcrypto_length_check(len, BLEN, errp)) { \ + return -1; \ + } \ + xts_encrypt_message(&ctx->key, &ctx->key_xts, ENCRYPT, \ + ctx->iv, len, out, in); \ + return 0; \ +} \ +static int NAME##_decrypt_xts(QCryptoCipher *cipher, const void *in, \ + void *out, size_t len, Error **errp) \ +{ \ + TYPE *ctx = container_of(cipher, TYPE, base); \ + if (!qcrypto_length_check(len, BLEN, errp)) { \ + return -1; \ + } \ + xts_decrypt_message(&ctx->key, &ctx->key_xts, DECRYPT, ENCRYPT, \ + ctx->iv, len, out, in); \ + return 0; \ +} +#endif + +#define DEFINE_XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \ + QEMU_BUILD_BUG_ON(BLEN != XTS_BLOCK_SIZE); \ + DEFINE__XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \ +static const struct QCryptoCipherDriver NAME##_driver_xts = { \ + .cipher_encrypt = NAME##_encrypt_xts, \ + .cipher_decrypt = NAME##_decrypt_xts, \ + .cipher_setiv = NAME##_setiv, \ + .cipher_free = qcrypto_cipher_ctx_free, \ +}; + + +#define DEFINE_ECB_CBC_CTR(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \ + DEFINE_SETIV(NAME, TYPE, BLEN) \ + DEFINE_ECB(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \ + DEFINE_CBC(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \ + DEFINE_CTR(NAME, TYPE, BLEN, ENCRYPT) + +#define DEFINE_ECB_CBC_CTR_XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \ + DEFINE_ECB_CBC_CTR(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \ + DEFINE_XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) + + +typedef struct QCryptoNettleDESRFB { + QCryptoCipher base; + struct des_ctx key; + uint8_t iv[DES_BLOCK_SIZE]; +} QCryptoNettleDESRFB; + +static void des_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, + uint8_t *dst, const uint8_t *src) +{ + des_encrypt(ctx, length, dst, src); +} + +static void des_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, + uint8_t *dst, const uint8_t *src) +{ + des_decrypt(ctx, length, dst, src); +} + +DEFINE_ECB_CBC_CTR(qcrypto_nettle_des_rfb, QCryptoNettleDESRFB, + DES_BLOCK_SIZE, des_encrypt_native, des_decrypt_native) + + +typedef struct QCryptoNettleDES3 { + QCryptoCipher base; + struct des3_ctx key; + uint8_t iv[DES3_BLOCK_SIZE]; +} QCryptoNettleDES3; + +static void des3_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, + uint8_t *dst, const uint8_t *src) +{ + des3_encrypt(ctx, length, dst, src); +} + +static void des3_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, + uint8_t *dst, const uint8_t *src) +{ + des3_decrypt(ctx, length, dst, src); +} + +DEFINE_ECB_CBC_CTR(qcrypto_nettle_des3, QCryptoNettleDES3, DES3_BLOCK_SIZE, + des3_encrypt_native, des3_decrypt_native) + + +typedef struct QCryptoNettleAES128 { + QCryptoCipher base; + uint8_t iv[AES_BLOCK_SIZE]; + /* First key from pair is encode, second key is decode. */ + struct aes128_ctx key[2], key_xts[2]; +} QCryptoNettleAES128; + +static void aes128_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, + uint8_t *dst, const uint8_t *src) +{ + CONST_CTX struct aes128_ctx *keys = ctx; + aes128_encrypt(&keys[0], length, dst, src); +} + +static void aes128_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, + uint8_t *dst, const uint8_t *src) +{ + CONST_CTX struct aes128_ctx *keys = ctx; + aes128_decrypt(&keys[1], length, dst, src); +} + +DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_aes128, + QCryptoNettleAES128, AES_BLOCK_SIZE, + aes128_encrypt_native, aes128_decrypt_native) + + +typedef struct QCryptoNettleAES192 { + QCryptoCipher base; + uint8_t iv[AES_BLOCK_SIZE]; + /* First key from pair is encode, second key is decode. */ + struct aes192_ctx key[2], key_xts[2]; +} QCryptoNettleAES192; + +static void aes192_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, + uint8_t *dst, const uint8_t *src) +{ + CONST_CTX struct aes192_ctx *keys = ctx; + aes192_encrypt(&keys[0], length, dst, src); +} + +static void aes192_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, + uint8_t *dst, const uint8_t *src) +{ + CONST_CTX struct aes192_ctx *keys = ctx; + aes192_decrypt(&keys[1], length, dst, src); +} + +DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_aes192, + QCryptoNettleAES192, AES_BLOCK_SIZE, + aes192_encrypt_native, aes192_decrypt_native) + + +typedef struct QCryptoNettleAES256 { + QCryptoCipher base; + uint8_t iv[AES_BLOCK_SIZE]; + /* First key from pair is encode, second key is decode. */ + struct aes256_ctx key[2], key_xts[2]; +} QCryptoNettleAES256; + +static void aes256_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, + uint8_t *dst, const uint8_t *src) +{ + CONST_CTX struct aes256_ctx *keys = ctx; + aes256_encrypt(&keys[0], length, dst, src); +} + +static void aes256_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, + uint8_t *dst, const uint8_t *src) +{ + CONST_CTX struct aes256_ctx *keys = ctx; + aes256_decrypt(&keys[1], length, dst, src); +} + +DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_aes256, + QCryptoNettleAES256, AES_BLOCK_SIZE, + aes256_encrypt_native, aes256_decrypt_native) + + +typedef struct QCryptoNettleCAST128 { + QCryptoCipher base; + uint8_t iv[CAST128_BLOCK_SIZE]; + struct cast128_ctx key, key_xts; +} QCryptoNettleCAST128; + +static void cast128_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, + uint8_t *dst, const uint8_t *src) +{ + cast128_encrypt(ctx, length, dst, src); +} + +static void cast128_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, + uint8_t *dst, const uint8_t *src) +{ + cast128_decrypt(ctx, length, dst, src); +} + +DEFINE_ECB_CBC_CTR(qcrypto_nettle_cast128, + QCryptoNettleCAST128, CAST128_BLOCK_SIZE, + cast128_encrypt_native, cast128_decrypt_native) + + +typedef struct QCryptoNettleSerpent { + QCryptoCipher base; + uint8_t iv[SERPENT_BLOCK_SIZE]; + struct serpent_ctx key, key_xts; +} QCryptoNettleSerpent; + + +static void serpent_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, + uint8_t *dst, const uint8_t *src) +{ + serpent_encrypt(ctx, length, dst, src); +} + +static void serpent_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, + uint8_t *dst, const uint8_t *src) +{ + serpent_decrypt(ctx, length, dst, src); +} + +DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_serpent, + QCryptoNettleSerpent, SERPENT_BLOCK_SIZE, + serpent_encrypt_native, serpent_decrypt_native) + + +typedef struct QCryptoNettleTwofish { + QCryptoCipher base; + uint8_t iv[TWOFISH_BLOCK_SIZE]; + struct twofish_ctx key, key_xts; +} QCryptoNettleTwofish; + +static void twofish_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, + uint8_t *dst, const uint8_t *src) +{ + twofish_encrypt(ctx, length, dst, src); +} + +static void twofish_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, + uint8_t *dst, const uint8_t *src) +{ + twofish_decrypt(ctx, length, dst, src); +} + +DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_twofish, + QCryptoNettleTwofish, TWOFISH_BLOCK_SIZE, + twofish_encrypt_native, twofish_decrypt_native) + + +bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode) +{ + switch (alg) { + case QCRYPTO_CIPHER_ALG_DES_RFB: + case QCRYPTO_CIPHER_ALG_3DES: + case QCRYPTO_CIPHER_ALG_AES_128: + case QCRYPTO_CIPHER_ALG_AES_192: + case QCRYPTO_CIPHER_ALG_AES_256: + case QCRYPTO_CIPHER_ALG_CAST5_128: + case QCRYPTO_CIPHER_ALG_SERPENT_128: + case QCRYPTO_CIPHER_ALG_SERPENT_192: + case QCRYPTO_CIPHER_ALG_SERPENT_256: + case QCRYPTO_CIPHER_ALG_TWOFISH_128: + case QCRYPTO_CIPHER_ALG_TWOFISH_192: + case QCRYPTO_CIPHER_ALG_TWOFISH_256: + break; + default: + return false; + } + + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + case QCRYPTO_CIPHER_MODE_CBC: + case QCRYPTO_CIPHER_MODE_XTS: + case QCRYPTO_CIPHER_MODE_CTR: + return true; + default: + return false; + } +} + +static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode, + const uint8_t *key, + size_t nkey, + Error **errp) +{ + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + case QCRYPTO_CIPHER_MODE_CBC: + case QCRYPTO_CIPHER_MODE_XTS: + case QCRYPTO_CIPHER_MODE_CTR: + break; + default: + goto bad_cipher_mode; + } + + if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) { + return NULL; + } + + switch (alg) { + case QCRYPTO_CIPHER_ALG_DES_RFB: + { + QCryptoNettleDESRFB *ctx; + const QCryptoCipherDriver *drv; + uint8_t *rfbkey; + + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + drv = &qcrypto_nettle_des_rfb_driver_ecb; + break; + case QCRYPTO_CIPHER_MODE_CBC: + drv = &qcrypto_nettle_des_rfb_driver_cbc; + break; + case QCRYPTO_CIPHER_MODE_CTR: + drv = &qcrypto_nettle_des_rfb_driver_ctr; + break; + default: + goto bad_cipher_mode; + } + + ctx = g_new0(QCryptoNettleDESRFB, 1); + ctx->base.driver = drv; + + rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey); + des_set_key(&ctx->key, rfbkey); + g_free(rfbkey); + + return &ctx->base; + } + + case QCRYPTO_CIPHER_ALG_3DES: + { + QCryptoNettleDES3 *ctx; + const QCryptoCipherDriver *drv; + + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + drv = &qcrypto_nettle_des3_driver_ecb; + break; + case QCRYPTO_CIPHER_MODE_CBC: + drv = &qcrypto_nettle_des3_driver_cbc; + break; + case QCRYPTO_CIPHER_MODE_CTR: + drv = &qcrypto_nettle_des3_driver_ctr; + break; + default: + goto bad_cipher_mode; + } + + ctx = g_new0(QCryptoNettleDES3, 1); + ctx->base.driver = drv; + des3_set_key(&ctx->key, key); + return &ctx->base; + } + + case QCRYPTO_CIPHER_ALG_AES_128: + { + QCryptoNettleAES128 *ctx = g_new0(QCryptoNettleAES128, 1); + + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + ctx->base.driver = &qcrypto_nettle_aes128_driver_ecb; + break; + case QCRYPTO_CIPHER_MODE_CBC: + ctx->base.driver = &qcrypto_nettle_aes128_driver_cbc; + break; + case QCRYPTO_CIPHER_MODE_CTR: + ctx->base.driver = &qcrypto_nettle_aes128_driver_ctr; + break; + case QCRYPTO_CIPHER_MODE_XTS: + ctx->base.driver = &qcrypto_nettle_aes128_driver_xts; + nkey /= 2; + aes128_set_encrypt_key(&ctx->key_xts[0], key + nkey); + aes128_set_decrypt_key(&ctx->key_xts[1], key + nkey); + break; + default: + g_assert_not_reached(); + } + aes128_set_encrypt_key(&ctx->key[0], key); + aes128_set_decrypt_key(&ctx->key[1], key); + + return &ctx->base; + } + + case QCRYPTO_CIPHER_ALG_AES_192: + { + QCryptoNettleAES192 *ctx = g_new0(QCryptoNettleAES192, 1); + + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + ctx->base.driver = &qcrypto_nettle_aes192_driver_ecb; + break; + case QCRYPTO_CIPHER_MODE_CBC: + ctx->base.driver = &qcrypto_nettle_aes192_driver_cbc; + break; + case QCRYPTO_CIPHER_MODE_CTR: + ctx->base.driver = &qcrypto_nettle_aes192_driver_ctr; + break; + case QCRYPTO_CIPHER_MODE_XTS: + ctx->base.driver = &qcrypto_nettle_aes192_driver_xts; + nkey /= 2; + aes192_set_encrypt_key(&ctx->key_xts[0], key + nkey); + aes192_set_decrypt_key(&ctx->key_xts[1], key + nkey); + break; + default: + g_assert_not_reached(); + } + aes192_set_encrypt_key(&ctx->key[0], key); + aes192_set_decrypt_key(&ctx->key[1], key); + + return &ctx->base; + } + + case QCRYPTO_CIPHER_ALG_AES_256: + { + QCryptoNettleAES256 *ctx = g_new0(QCryptoNettleAES256, 1); + + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + ctx->base.driver = &qcrypto_nettle_aes256_driver_ecb; + break; + case QCRYPTO_CIPHER_MODE_CBC: + ctx->base.driver = &qcrypto_nettle_aes256_driver_cbc; + break; + case QCRYPTO_CIPHER_MODE_CTR: + ctx->base.driver = &qcrypto_nettle_aes256_driver_ctr; + break; + case QCRYPTO_CIPHER_MODE_XTS: + ctx->base.driver = &qcrypto_nettle_aes256_driver_xts; + nkey /= 2; + aes256_set_encrypt_key(&ctx->key_xts[0], key + nkey); + aes256_set_decrypt_key(&ctx->key_xts[1], key + nkey); + break; + default: + g_assert_not_reached(); + } + aes256_set_encrypt_key(&ctx->key[0], key); + aes256_set_decrypt_key(&ctx->key[1], key); + + return &ctx->base; + } + + case QCRYPTO_CIPHER_ALG_CAST5_128: + { + QCryptoNettleCAST128 *ctx; + const QCryptoCipherDriver *drv; + + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + drv = &qcrypto_nettle_cast128_driver_ecb; + break; + case QCRYPTO_CIPHER_MODE_CBC: + drv = &qcrypto_nettle_cast128_driver_cbc; + break; + case QCRYPTO_CIPHER_MODE_CTR: + drv = &qcrypto_nettle_cast128_driver_ctr; + break; + default: + goto bad_cipher_mode; + } + + ctx = g_new0(QCryptoNettleCAST128, 1); + ctx->base.driver = drv; + cast5_set_key(&ctx->key, nkey, key); + + return &ctx->base; + } + + case QCRYPTO_CIPHER_ALG_SERPENT_128: + case QCRYPTO_CIPHER_ALG_SERPENT_192: + case QCRYPTO_CIPHER_ALG_SERPENT_256: + { + QCryptoNettleSerpent *ctx = g_new0(QCryptoNettleSerpent, 1); + + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + ctx->base.driver = &qcrypto_nettle_serpent_driver_ecb; + break; + case QCRYPTO_CIPHER_MODE_CBC: + ctx->base.driver = &qcrypto_nettle_serpent_driver_cbc; + break; + case QCRYPTO_CIPHER_MODE_CTR: + ctx->base.driver = &qcrypto_nettle_serpent_driver_ctr; + break; + case QCRYPTO_CIPHER_MODE_XTS: + ctx->base.driver = &qcrypto_nettle_serpent_driver_xts; + nkey /= 2; + serpent_set_key(&ctx->key_xts, nkey, key + nkey); + break; + default: + g_assert_not_reached(); + } + serpent_set_key(&ctx->key, nkey, key); + + return &ctx->base; + } + + case QCRYPTO_CIPHER_ALG_TWOFISH_128: + case QCRYPTO_CIPHER_ALG_TWOFISH_192: + case QCRYPTO_CIPHER_ALG_TWOFISH_256: + { + QCryptoNettleTwofish *ctx = g_new0(QCryptoNettleTwofish, 1); + + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + ctx->base.driver = &qcrypto_nettle_twofish_driver_ecb; + break; + case QCRYPTO_CIPHER_MODE_CBC: + ctx->base.driver = &qcrypto_nettle_twofish_driver_cbc; + break; + case QCRYPTO_CIPHER_MODE_CTR: + ctx->base.driver = &qcrypto_nettle_twofish_driver_ctr; + break; + case QCRYPTO_CIPHER_MODE_XTS: + ctx->base.driver = &qcrypto_nettle_twofish_driver_xts; + nkey /= 2; + twofish_set_key(&ctx->key_xts, nkey, key + nkey); + break; + default: + g_assert_not_reached(); + } + twofish_set_key(&ctx->key, nkey, key); + + return &ctx->base; + } + + default: + error_setg(errp, "Unsupported cipher algorithm %s", + QCryptoCipherAlgorithm_str(alg)); + return NULL; + } + + bad_cipher_mode: + error_setg(errp, "Unsupported cipher mode %s", + QCryptoCipherMode_str(mode)); + return NULL; +} diff --git a/crypto/cipher.c b/crypto/cipher.c index e5adb56271e0612a6b62eb87abcb108be04980fc..068b2fb867c626e446d1016c136226764044bd62 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -19,12 +19,13 @@ */ #include "qemu/osdep.h" +#include "qemu/host-utils.h" #include "qapi/error.h" #include "crypto/cipher.h" #include "cipherpriv.h" -static size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = { +static const size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = { [QCRYPTO_CIPHER_ALG_AES_128] = 16, [QCRYPTO_CIPHER_ALG_AES_192] = 24, [QCRYPTO_CIPHER_ALG_AES_256] = 32, @@ -39,7 +40,7 @@ static size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = { [QCRYPTO_CIPHER_ALG_TWOFISH_256] = 32, }; -static size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = { +static const size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = { [QCRYPTO_CIPHER_ALG_AES_128] = 16, [QCRYPTO_CIPHER_ALG_AES_192] = 16, [QCRYPTO_CIPHER_ALG_AES_256] = 16, @@ -54,7 +55,7 @@ static size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = { [QCRYPTO_CIPHER_ALG_TWOFISH_256] = 16, }; -static bool mode_need_iv[QCRYPTO_CIPHER_MODE__MAX] = { +static const bool mode_need_iv[QCRYPTO_CIPHER_MODE__MAX] = { [QCRYPTO_CIPHER_MODE_ECB] = false, [QCRYPTO_CIPHER_MODE_CBC] = true, [QCRYPTO_CIPHER_MODE_XTS] = true, @@ -150,11 +151,11 @@ qcrypto_cipher_munge_des_rfb_key(const uint8_t *key, #endif /* CONFIG_GCRYPT || CONFIG_NETTLE */ #ifdef CONFIG_GCRYPT -#include "cipher-gcrypt.c" +#include "cipher-gcrypt.c.inc" #elif defined CONFIG_NETTLE -#include "cipher-nettle.c" +#include "cipher-nettle.c.inc" #else -#include "cipher-builtin.c" +#include "cipher-builtin.c.inc" #endif QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg, @@ -162,31 +163,21 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg, const uint8_t *key, size_t nkey, Error **errp) { - QCryptoCipher *cipher; - void *ctx = NULL; - QCryptoCipherDriver *drv = NULL; + QCryptoCipher *cipher = NULL; #ifdef CONFIG_AF_ALG - ctx = qcrypto_afalg_cipher_ctx_new(alg, mode, key, nkey, NULL); - if (ctx) { - drv = &qcrypto_cipher_afalg_driver; - } + cipher = qcrypto_afalg_cipher_ctx_new(alg, mode, key, nkey, NULL); #endif - if (!ctx) { - ctx = qcrypto_cipher_ctx_new(alg, mode, key, nkey, errp); - if (!ctx) { + if (!cipher) { + cipher = qcrypto_cipher_ctx_new(alg, mode, key, nkey, errp); + if (!cipher) { return NULL; } - - drv = &qcrypto_cipher_lib_driver; } - cipher = g_new0(QCryptoCipher, 1); cipher->alg = alg; cipher->mode = mode; - cipher->opaque = ctx; - cipher->driver = (void *)drv; return cipher; } @@ -198,7 +189,7 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher, size_t len, Error **errp) { - QCryptoCipherDriver *drv = cipher->driver; + const QCryptoCipherDriver *drv = cipher->driver; return drv->cipher_encrypt(cipher, in, out, len, errp); } @@ -209,7 +200,7 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher, size_t len, Error **errp) { - QCryptoCipherDriver *drv = cipher->driver; + const QCryptoCipherDriver *drv = cipher->driver; return drv->cipher_decrypt(cipher, in, out, len, errp); } @@ -218,17 +209,14 @@ int qcrypto_cipher_setiv(QCryptoCipher *cipher, const uint8_t *iv, size_t niv, Error **errp) { - QCryptoCipherDriver *drv = cipher->driver; + const QCryptoCipherDriver *drv = cipher->driver; return drv->cipher_setiv(cipher, iv, niv, errp); } void qcrypto_cipher_free(QCryptoCipher *cipher) { - QCryptoCipherDriver *drv; if (cipher) { - drv = cipher->driver; - drv->cipher_free(cipher); - g_free(cipher); + cipher->driver->cipher_free(cipher); } } diff --git a/crypto/cipherpriv.h b/crypto/cipherpriv.h index 0823239f4136802ef908adda9ca39f08dbf71ffb..396527857d686ba0225547f5fa6bffaa673f7f95 100644 --- a/crypto/cipherpriv.h +++ b/crypto/cipherpriv.h @@ -17,8 +17,6 @@ #include "qapi/qapi-types-crypto.h" -typedef struct QCryptoCipherDriver QCryptoCipherDriver; - struct QCryptoCipherDriver { int (*cipher_encrypt)(QCryptoCipher *cipher, const void *in, @@ -43,14 +41,12 @@ struct QCryptoCipherDriver { #include "afalgpriv.h" -extern QCryptoAFAlg * +extern QCryptoCipher * qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg, QCryptoCipherMode mode, const uint8_t *key, size_t nkey, Error **errp); -extern struct QCryptoCipherDriver qcrypto_cipher_afalg_driver; - #endif #endif diff --git a/crypto/init.c b/crypto/init.c index b305381ec540ebe79903632ddc9bc1eb65274f58..ea233b9192ab070a208c8786c931f5b7036d4376 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -122,7 +122,7 @@ int qcrypto_init(Error **errp) #endif #ifdef CONFIG_GCRYPT - if (!gcry_check_version(GCRYPT_VERSION)) { + if (!gcry_check_version(NULL)) { error_setg(errp, "Unable to initialize gcrypt"); return -1; } diff --git a/crypto/meson.build b/crypto/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..7f37b5d33546902208b20cf32d7e85371d3ccbf6 --- /dev/null +++ b/crypto/meson.build @@ -0,0 +1,73 @@ +crypto_ss.add(genh) +crypto_ss.add(files( + 'afsplit.c', + 'block-luks.c', + 'block-qcow.c', + 'block.c', + 'cipher.c', + 'desrfb.c', + 'hash.c', + 'hmac.c', + 'ivgen-essiv.c', + 'ivgen-plain.c', + 'ivgen-plain64.c', + 'ivgen.c', + 'pbkdf.c', + 'secret_common.c', + 'secret.c', + 'tlscreds.c', + 'tlscredsanon.c', + 'tlscredspsk.c', + 'tlscredsx509.c', + 'tlssession.c', +)) + +if 'CONFIG_NETTLE' in config_host + crypto_ss.add(files('hash-nettle.c', 'hmac-nettle.c', 'pbkdf-nettle.c')) +elif 'CONFIG_GCRYPT' in config_host + crypto_ss.add(files('hash-gcrypt.c', 'pbkdf-gcrypt.c')) + if 'CONFIG_GCRYPT_HMAC' in config_host + crypto_ss.add(files('hmac-gcrypt.c')) + else + crypto_ss.add(files('hmac-glib.c')) + endif +else + crypto_ss.add(files('hash-glib.c', 'hmac-glib.c', 'pbkdf-stub.c')) +endif + +crypto_ss.add(when: 'CONFIG_SECRET_KEYRING', if_true: files('secret_keyring.c')) +crypto_ss.add(when: 'CONFIG_QEMU_PRIVATE_XTS', if_true: files('xts.c')) +crypto_ss.add(when: 'CONFIG_AF_ALG', if_true: files('afalg.c', 'cipher-afalg.c', 'hash-afalg.c')) +crypto_ss.add(when: 'CONFIG_GNUTLS', if_true: files('tls-cipher-suites.c')) + +if 'CONFIG_NETTLE' in config_host + crypto_ss.add(nettle) +elif 'CONFIG_GCRYPT' in config_host + crypto_ss.add(gcrypt) +endif + +if 'CONFIG_GNUTLS' in config_host + crypto_ss.add(gnutls) +endif + + +util_ss.add(files('aes.c')) +util_ss.add(files('init.c')) + +if 'CONFIG_GCRYPT' in config_host + util_ss.add(files('random-gcrypt.c')) +elif 'CONFIG_GNUTLS' in config_host + util_ss.add(files('random-gnutls.c')) +elif 'CONFIG_RNG_NONE' in config_host + util_ss.add(files('random-none.c')) +else + util_ss.add(files('random-platform.c')) +endif + +if 'CONFIG_GCRYPT' in config_host + util_ss.add(gcrypt) +endif + +if 'CONFIG_GNUTLS' in config_host + util_ss.add(gnutls) +endif diff --git a/crypto/random-none.c b/crypto/random-none.c new file mode 100644 index 0000000000000000000000000000000000000000..102f8a4dce053fe4ea27ff29585e76f5748683c2 --- /dev/null +++ b/crypto/random-none.c @@ -0,0 +1,38 @@ +/* + * QEMU Crypto "none" random number provider + * + * Copyright (c) 2020 Marek Marczykowski-GĂłrecki + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + */ + +#include "qemu/osdep.h" + +#include "crypto/random.h" +#include "qapi/error.h" + +int qcrypto_random_init(Error **errp) +{ + return 0; +} + +int qcrypto_random_bytes(void *buf, + size_t buflen, + Error **errp) +{ + error_setg(errp, "Random bytes not available with \"none\" rng"); + return -1; +} diff --git a/crypto/secret.c b/crypto/secret.c index 3107aecb474f3728badafbb6bf3acd6ded4996ac..281cb81f0f082bcfc3883ab0c6fc03e94cf2875d 100644 --- a/crypto/secret.c +++ b/crypto/secret.c @@ -20,16 +20,14 @@ #include "qemu/osdep.h" #include "crypto/secret.h" -#include "crypto/cipher.h" #include "qapi/error.h" #include "qom/object_interfaces.h" -#include "qemu/base64.h" #include "qemu/module.h" #include "trace.h" static void -qcrypto_secret_load_data(QCryptoSecret *secret, +qcrypto_secret_load_data(QCryptoSecretCommon *sec_common, uint8_t **output, size_t *outputlen, Error **errp) @@ -38,6 +36,8 @@ qcrypto_secret_load_data(QCryptoSecret *secret, size_t length = 0; GError *gerr = NULL; + QCryptoSecret *secret = QCRYPTO_SECRET(sec_common); + *output = NULL; *outputlen = 0; @@ -65,198 +65,6 @@ qcrypto_secret_load_data(QCryptoSecret *secret, } -static void qcrypto_secret_decrypt(QCryptoSecret *secret, - const uint8_t *input, - size_t inputlen, - uint8_t **output, - size_t *outputlen, - Error **errp) -{ - g_autofree uint8_t *key = NULL; - g_autofree uint8_t *ciphertext = NULL; - g_autofree uint8_t *iv = NULL; - size_t keylen, ciphertextlen, ivlen; - g_autoptr(QCryptoCipher) aes = NULL; - g_autofree uint8_t *plaintext = NULL; - - *output = NULL; - *outputlen = 0; - - if (qcrypto_secret_lookup(secret->keyid, - &key, &keylen, - errp) < 0) { - return; - } - - if (keylen != 32) { - error_setg(errp, "Key should be 32 bytes in length"); - return; - } - - if (!secret->iv) { - error_setg(errp, "IV is required to decrypt secret"); - return; - } - - iv = qbase64_decode(secret->iv, -1, &ivlen, errp); - if (!iv) { - return; - } - if (ivlen != 16) { - error_setg(errp, "IV should be 16 bytes in length not %zu", - ivlen); - return; - } - - aes = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_256, - QCRYPTO_CIPHER_MODE_CBC, - key, keylen, - errp); - if (!aes) { - return; - } - - if (qcrypto_cipher_setiv(aes, iv, ivlen, errp) < 0) { - return; - } - - if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) { - ciphertext = qbase64_decode((const gchar*)input, - inputlen, - &ciphertextlen, - errp); - if (!ciphertext) { - return; - } - plaintext = g_new0(uint8_t, ciphertextlen + 1); - } else { - ciphertextlen = inputlen; - plaintext = g_new0(uint8_t, inputlen + 1); - } - if (qcrypto_cipher_decrypt(aes, - ciphertext ? ciphertext : input, - plaintext, - ciphertextlen, - errp) < 0) { - return; - } - - if (plaintext[ciphertextlen - 1] > 16 || - plaintext[ciphertextlen - 1] > ciphertextlen) { - error_setg(errp, "Incorrect number of padding bytes (%d) " - "found on decrypted data", - (int)plaintext[ciphertextlen - 1]); - return; - } - - /* Even though plaintext may contain arbitrary NUL - * ensure it is explicitly NUL terminated. - */ - ciphertextlen -= plaintext[ciphertextlen - 1]; - plaintext[ciphertextlen] = '\0'; - - *output = g_steal_pointer(&plaintext); - *outputlen = ciphertextlen; -} - - -static void qcrypto_secret_decode(const uint8_t *input, - size_t inputlen, - uint8_t **output, - size_t *outputlen, - Error **errp) -{ - *output = qbase64_decode((const gchar*)input, - inputlen, - outputlen, - errp); -} - - -static void -qcrypto_secret_prop_set_loaded(Object *obj, - bool value, - Error **errp) -{ - QCryptoSecret *secret = QCRYPTO_SECRET(obj); - - if (value) { - Error *local_err = NULL; - uint8_t *input = NULL; - size_t inputlen = 0; - uint8_t *output = NULL; - size_t outputlen = 0; - - qcrypto_secret_load_data(secret, &input, &inputlen, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - - if (secret->keyid) { - qcrypto_secret_decrypt(secret, input, inputlen, - &output, &outputlen, &local_err); - g_free(input); - if (local_err) { - error_propagate(errp, local_err); - return; - } - input = output; - inputlen = outputlen; - } else { - if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) { - qcrypto_secret_decode(input, inputlen, - &output, &outputlen, &local_err); - g_free(input); - if (local_err) { - error_propagate(errp, local_err); - return; - } - input = output; - inputlen = outputlen; - } - } - - secret->rawdata = input; - secret->rawlen = inputlen; - } else { - g_free(secret->rawdata); - secret->rawdata = NULL; - secret->rawlen = 0; - } -} - - -static bool -qcrypto_secret_prop_get_loaded(Object *obj, - Error **errp G_GNUC_UNUSED) -{ - QCryptoSecret *secret = QCRYPTO_SECRET(obj); - return secret->rawdata != NULL; -} - - -static void -qcrypto_secret_prop_set_format(Object *obj, - int value, - Error **errp G_GNUC_UNUSED) -{ - QCryptoSecret *creds = QCRYPTO_SECRET(obj); - - creds->format = value; -} - - -static int -qcrypto_secret_prop_get_format(Object *obj, - Error **errp G_GNUC_UNUSED) -{ - QCryptoSecret *creds = QCRYPTO_SECRET(obj); - - return creds->format; -} - - static void qcrypto_secret_prop_set_data(Object *obj, const char *value, @@ -299,52 +107,10 @@ qcrypto_secret_prop_get_file(Object *obj, } -static void -qcrypto_secret_prop_set_iv(Object *obj, - const char *value, - Error **errp) -{ - QCryptoSecret *secret = QCRYPTO_SECRET(obj); - - g_free(secret->iv); - secret->iv = g_strdup(value); -} - - -static char * -qcrypto_secret_prop_get_iv(Object *obj, - Error **errp) -{ - QCryptoSecret *secret = QCRYPTO_SECRET(obj); - return g_strdup(secret->iv); -} - - -static void -qcrypto_secret_prop_set_keyid(Object *obj, - const char *value, - Error **errp) -{ - QCryptoSecret *secret = QCRYPTO_SECRET(obj); - - g_free(secret->keyid); - secret->keyid = g_strdup(value); -} - - -static char * -qcrypto_secret_prop_get_keyid(Object *obj, - Error **errp) -{ - QCryptoSecret *secret = QCRYPTO_SECRET(obj); - return g_strdup(secret->keyid); -} - - static void qcrypto_secret_complete(UserCreatable *uc, Error **errp) { - object_property_set_bool(OBJECT(uc), true, "loaded", errp); + object_property_set_bool(OBJECT(uc), "loaded", true, errp); } @@ -353,129 +119,30 @@ qcrypto_secret_finalize(Object *obj) { QCryptoSecret *secret = QCRYPTO_SECRET(obj); - g_free(secret->iv); g_free(secret->file); - g_free(secret->keyid); - g_free(secret->rawdata); g_free(secret->data); } static void qcrypto_secret_class_init(ObjectClass *oc, void *data) { - UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); + QCryptoSecretCommonClass *sic = QCRYPTO_SECRET_COMMON_CLASS(oc); + sic->load_data = qcrypto_secret_load_data; + UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); ucc->complete = qcrypto_secret_complete; - object_class_property_add_bool(oc, "loaded", - qcrypto_secret_prop_get_loaded, - qcrypto_secret_prop_set_loaded); - object_class_property_add_enum(oc, "format", - "QCryptoSecretFormat", - &QCryptoSecretFormat_lookup, - qcrypto_secret_prop_get_format, - qcrypto_secret_prop_set_format); object_class_property_add_str(oc, "data", qcrypto_secret_prop_get_data, qcrypto_secret_prop_set_data); object_class_property_add_str(oc, "file", qcrypto_secret_prop_get_file, qcrypto_secret_prop_set_file); - object_class_property_add_str(oc, "keyid", - qcrypto_secret_prop_get_keyid, - qcrypto_secret_prop_set_keyid); - object_class_property_add_str(oc, "iv", - qcrypto_secret_prop_get_iv, - qcrypto_secret_prop_set_iv); -} - - -int qcrypto_secret_lookup(const char *secretid, - uint8_t **data, - size_t *datalen, - Error **errp) -{ - Object *obj; - QCryptoSecret *secret; - - obj = object_resolve_path_component( - object_get_objects_root(), secretid); - if (!obj) { - error_setg(errp, "No secret with id '%s'", secretid); - return -1; - } - - secret = (QCryptoSecret *) - object_dynamic_cast(obj, - TYPE_QCRYPTO_SECRET); - if (!secret) { - error_setg(errp, "Object with id '%s' is not a secret", - secretid); - return -1; - } - - if (!secret->rawdata) { - error_setg(errp, "Secret with id '%s' has no data", - secretid); - return -1; - } - - *data = g_new0(uint8_t, secret->rawlen + 1); - memcpy(*data, secret->rawdata, secret->rawlen); - (*data)[secret->rawlen] = '\0'; - *datalen = secret->rawlen; - - return 0; -} - - -char *qcrypto_secret_lookup_as_utf8(const char *secretid, - Error **errp) -{ - uint8_t *data; - size_t datalen; - - if (qcrypto_secret_lookup(secretid, - &data, - &datalen, - errp) < 0) { - return NULL; - } - - if (!g_utf8_validate((const gchar*)data, datalen, NULL)) { - error_setg(errp, - "Data from secret %s is not valid UTF-8", - secretid); - g_free(data); - return NULL; - } - - return (char *)data; -} - - -char *qcrypto_secret_lookup_as_base64(const char *secretid, - Error **errp) -{ - uint8_t *data; - size_t datalen; - char *ret; - - if (qcrypto_secret_lookup(secretid, - &data, - &datalen, - errp) < 0) { - return NULL; - } - - ret = g_base64_encode(data, datalen); - g_free(data); - return ret; } static const TypeInfo qcrypto_secret_info = { - .parent = TYPE_OBJECT, + .parent = TYPE_QCRYPTO_SECRET_COMMON, .name = TYPE_QCRYPTO_SECRET, .instance_size = sizeof(QCryptoSecret), .instance_finalize = qcrypto_secret_finalize, diff --git a/crypto/secret_common.c b/crypto/secret_common.c new file mode 100644 index 0000000000000000000000000000000000000000..b03d530867ebc8e00918193870d7615b6bfd7c80 --- /dev/null +++ b/crypto/secret_common.c @@ -0,0 +1,403 @@ +/* + * QEMU crypto secret support + * + * Copyright (c) 2015 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + */ + +#include "qemu/osdep.h" +#include "crypto/secret_common.h" +#include "crypto/cipher.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "qemu/base64.h" +#include "qemu/module.h" +#include "trace.h" + + +static void qcrypto_secret_decrypt(QCryptoSecretCommon *secret, + const uint8_t *input, + size_t inputlen, + uint8_t **output, + size_t *outputlen, + Error **errp) +{ + g_autofree uint8_t *iv = NULL; + g_autofree uint8_t *key = NULL; + g_autofree uint8_t *ciphertext = NULL; + size_t keylen, ciphertextlen, ivlen; + g_autoptr(QCryptoCipher) aes = NULL; + g_autofree uint8_t *plaintext = NULL; + + *output = NULL; + *outputlen = 0; + + if (qcrypto_secret_lookup(secret->keyid, + &key, &keylen, + errp) < 0) { + return; + } + + if (keylen != 32) { + error_setg(errp, "Key should be 32 bytes in length"); + return; + } + + if (!secret->iv) { + error_setg(errp, "IV is required to decrypt secret"); + return; + } + + iv = qbase64_decode(secret->iv, -1, &ivlen, errp); + if (!iv) { + return; + } + if (ivlen != 16) { + error_setg(errp, "IV should be 16 bytes in length not %zu", + ivlen); + return; + } + + aes = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_256, + QCRYPTO_CIPHER_MODE_CBC, + key, keylen, + errp); + if (!aes) { + return; + } + + if (qcrypto_cipher_setiv(aes, iv, ivlen, errp) < 0) { + return; + } + + if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) { + ciphertext = qbase64_decode((const gchar *)input, + inputlen, + &ciphertextlen, + errp); + if (!ciphertext) { + return; + } + plaintext = g_new0(uint8_t, ciphertextlen + 1); + } else { + ciphertextlen = inputlen; + plaintext = g_new0(uint8_t, inputlen + 1); + } + if (qcrypto_cipher_decrypt(aes, + ciphertext ? ciphertext : input, + plaintext, + ciphertextlen, + errp) < 0) { + return; + } + + if (plaintext[ciphertextlen - 1] > 16 || + plaintext[ciphertextlen - 1] > ciphertextlen) { + error_setg(errp, "Incorrect number of padding bytes (%d) " + "found on decrypted data", + (int)plaintext[ciphertextlen - 1]); + return; + } + + /* + * Even though plaintext may contain arbitrary NUL + * ensure it is explicitly NUL terminated. + */ + ciphertextlen -= plaintext[ciphertextlen - 1]; + plaintext[ciphertextlen] = '\0'; + + *output = g_steal_pointer(&plaintext); + *outputlen = ciphertextlen; +} + + +static void qcrypto_secret_decode(const uint8_t *input, + size_t inputlen, + uint8_t **output, + size_t *outputlen, + Error **errp) +{ + *output = qbase64_decode((const gchar *)input, + inputlen, + outputlen, + errp); +} + + +static void +qcrypto_secret_prop_set_loaded(Object *obj, + bool value, + Error **errp) +{ + QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(obj); + QCryptoSecretCommonClass *sec_class + = QCRYPTO_SECRET_COMMON_GET_CLASS(obj); + + if (value) { + Error *local_err = NULL; + uint8_t *input = NULL; + size_t inputlen = 0; + uint8_t *output = NULL; + size_t outputlen = 0; + + if (sec_class->load_data) { + sec_class->load_data(secret, &input, &inputlen, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + } else { + error_setg(errp, "%s provides no 'load_data' method'", + object_get_typename(obj)); + return; + } + + if (secret->keyid) { + qcrypto_secret_decrypt(secret, input, inputlen, + &output, &outputlen, &local_err); + g_free(input); + if (local_err) { + error_propagate(errp, local_err); + return; + } + input = output; + inputlen = outputlen; + } else { + if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) { + qcrypto_secret_decode(input, inputlen, + &output, &outputlen, &local_err); + g_free(input); + if (local_err) { + error_propagate(errp, local_err); + return; + } + input = output; + inputlen = outputlen; + } + } + + secret->rawdata = input; + secret->rawlen = inputlen; + } else { + g_free(secret->rawdata); + secret->rawlen = 0; + } +} + + +static bool +qcrypto_secret_prop_get_loaded(Object *obj, + Error **errp G_GNUC_UNUSED) +{ + QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(obj); + return secret->rawdata != NULL; +} + + +static void +qcrypto_secret_prop_set_format(Object *obj, + int value, + Error **errp G_GNUC_UNUSED) +{ + QCryptoSecretCommon *creds = QCRYPTO_SECRET_COMMON(obj); + creds->format = value; +} + + +static int +qcrypto_secret_prop_get_format(Object *obj, + Error **errp G_GNUC_UNUSED) +{ + QCryptoSecretCommon *creds = QCRYPTO_SECRET_COMMON(obj); + return creds->format; +} + + +static void +qcrypto_secret_prop_set_iv(Object *obj, + const char *value, + Error **errp) +{ + QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(obj); + + g_free(secret->iv); + secret->iv = g_strdup(value); +} + + +static char * +qcrypto_secret_prop_get_iv(Object *obj, + Error **errp) +{ + QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(obj); + return g_strdup(secret->iv); +} + + +static void +qcrypto_secret_prop_set_keyid(Object *obj, + const char *value, + Error **errp) +{ + QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(obj); + + g_free(secret->keyid); + secret->keyid = g_strdup(value); +} + + +static char * +qcrypto_secret_prop_get_keyid(Object *obj, + Error **errp) +{ + QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(obj); + return g_strdup(secret->keyid); +} + + +static void +qcrypto_secret_finalize(Object *obj) +{ + QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(obj); + + g_free(secret->iv); + g_free(secret->keyid); + g_free(secret->rawdata); +} + +static void +qcrypto_secret_class_init(ObjectClass *oc, void *data) +{ + object_class_property_add_bool(oc, "loaded", + qcrypto_secret_prop_get_loaded, + qcrypto_secret_prop_set_loaded); + object_class_property_add_enum(oc, "format", + "QCryptoSecretFormat", + &QCryptoSecretFormat_lookup, + qcrypto_secret_prop_get_format, + qcrypto_secret_prop_set_format); + object_class_property_add_str(oc, "keyid", + qcrypto_secret_prop_get_keyid, + qcrypto_secret_prop_set_keyid); + object_class_property_add_str(oc, "iv", + qcrypto_secret_prop_get_iv, + qcrypto_secret_prop_set_iv); +} + + +int qcrypto_secret_lookup(const char *secretid, + uint8_t **data, + size_t *datalen, + Error **errp) +{ + Object *obj; + QCryptoSecretCommon *secret; + + obj = object_resolve_path_component( + object_get_objects_root(), secretid); + if (!obj) { + error_setg(errp, "No secret with id '%s'", secretid); + return -1; + } + + secret = (QCryptoSecretCommon *) + object_dynamic_cast(obj, + TYPE_QCRYPTO_SECRET_COMMON); + if (!secret) { + error_setg(errp, "Object with id '%s' is not a secret", + secretid); + return -1; + } + + if (!secret->rawdata) { + error_setg(errp, "Secret with id '%s' has no data", + secretid); + return -1; + } + + *data = g_new0(uint8_t, secret->rawlen + 1); + memcpy(*data, secret->rawdata, secret->rawlen); + (*data)[secret->rawlen] = '\0'; + *datalen = secret->rawlen; + + return 0; +} + + +char *qcrypto_secret_lookup_as_utf8(const char *secretid, + Error **errp) +{ + uint8_t *data; + size_t datalen; + + if (qcrypto_secret_lookup(secretid, + &data, + &datalen, + errp) < 0) { + return NULL; + } + + if (!g_utf8_validate((const gchar *)data, datalen, NULL)) { + error_setg(errp, + "Data from secret %s is not valid UTF-8", + secretid); + g_free(data); + return NULL; + } + + return (char *)data; +} + + +char *qcrypto_secret_lookup_as_base64(const char *secretid, + Error **errp) +{ + uint8_t *data; + size_t datalen; + char *ret; + + if (qcrypto_secret_lookup(secretid, + &data, + &datalen, + errp) < 0) { + return NULL; + } + + ret = g_base64_encode(data, datalen); + g_free(data); + return ret; +} + + +static const TypeInfo qcrypto_secret_info = { + .parent = TYPE_OBJECT, + .name = TYPE_QCRYPTO_SECRET_COMMON, + .instance_size = sizeof(QCryptoSecretCommon), + .instance_finalize = qcrypto_secret_finalize, + .class_size = sizeof(QCryptoSecretCommonClass), + .class_init = qcrypto_secret_class_init, + .abstract = true, +}; + + +static void +qcrypto_secret_register_types(void) +{ + type_register_static(&qcrypto_secret_info); +} + + +type_init(qcrypto_secret_register_types); diff --git a/crypto/secret_keyring.c b/crypto/secret_keyring.c new file mode 100644 index 0000000000000000000000000000000000000000..10d8bc48a0f551d320a7101d92d5fe7ac2e759f0 --- /dev/null +++ b/crypto/secret_keyring.c @@ -0,0 +1,147 @@ +/* + * QEMU crypto secret support + * + * Copyright 2020 Yandex N.V. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + */ + +#include "qemu/osdep.h" +#include +#include +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "trace.h" +#include "crypto/secret_keyring.h" + + +static inline +long keyctl_read(int32_t key, uint8_t *buffer, size_t buflen) +{ + return syscall(__NR_keyctl, KEYCTL_READ, key, buffer, buflen, 0); +} + + +static void +qcrypto_secret_keyring_load_data(QCryptoSecretCommon *sec_common, + uint8_t **output, + size_t *outputlen, + Error **errp) +{ + QCryptoSecretKeyring *secret = QCRYPTO_SECRET_KEYRING(sec_common); + uint8_t *buffer = NULL; + long retcode; + + *output = NULL; + *outputlen = 0; + + if (!secret->serial) { + error_setg(errp, "'serial' parameter must be provided"); + return; + } + + retcode = keyctl_read(secret->serial, NULL, 0); + if (retcode <= 0) { + goto keyctl_error; + } + + buffer = g_new0(uint8_t, retcode); + + retcode = keyctl_read(secret->serial, buffer, retcode); + if (retcode < 0) { + g_free(buffer); + goto keyctl_error; + } + + *outputlen = retcode; + *output = buffer; + return; + +keyctl_error: + error_setg_errno(errp, errno, + "Unable to read serial key %08x", + secret->serial); +} + + +static void +qcrypto_secret_prop_set_key(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + QCryptoSecretKeyring *secret = QCRYPTO_SECRET_KEYRING(obj); + int32_t value; + visit_type_int32(v, name, &value, errp); + if (!value) { + error_setg(errp, "'serial' should not be equal to 0"); + } + secret->serial = value; +} + + +static void +qcrypto_secret_prop_get_key(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + QCryptoSecretKeyring *secret = QCRYPTO_SECRET_KEYRING(obj); + int32_t value = secret->serial; + visit_type_int32(v, name, &value, errp); +} + + +static void +qcrypto_secret_keyring_complete(UserCreatable *uc, Error **errp) +{ + object_property_set_bool(OBJECT(uc), "loaded", true, errp); +} + + +static void +qcrypto_secret_keyring_class_init(ObjectClass *oc, void *data) +{ + QCryptoSecretCommonClass *sic = QCRYPTO_SECRET_COMMON_CLASS(oc); + sic->load_data = qcrypto_secret_keyring_load_data; + + UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); + ucc->complete = qcrypto_secret_keyring_complete; + + object_class_property_add(oc, "serial", "int32_t", + qcrypto_secret_prop_get_key, + qcrypto_secret_prop_set_key, + NULL, NULL); +} + + +static const TypeInfo qcrypto_secret_info = { + .parent = TYPE_QCRYPTO_SECRET_COMMON, + .name = TYPE_QCRYPTO_SECRET_KEYRING, + .instance_size = sizeof(QCryptoSecretKeyring), + .class_init = qcrypto_secret_keyring_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_USER_CREATABLE }, + { } + } +}; + + +static void +qcrypto_secret_register_types(void) +{ + type_register_static(&qcrypto_secret_info); +} + + +type_init(qcrypto_secret_register_types); diff --git a/crypto/tls-cipher-suites.c b/crypto/tls-cipher-suites.c new file mode 100644 index 0000000000000000000000000000000000000000..55fb5f7c19d107a152039a0d90f22474c4a11567 --- /dev/null +++ b/crypto/tls-cipher-suites.c @@ -0,0 +1,126 @@ +/* + * QEMU TLS Cipher Suites + * + * Copyright (c) 2018-2020 Red Hat, Inc. + * + * Author: Philippe Mathieu-DaudĂ© + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "crypto/tlscreds.h" +#include "crypto/tls-cipher-suites.h" +#include "hw/nvram/fw_cfg.h" +#include "trace.h" + +/* + * IANA registered TLS ciphers: + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4 + */ +typedef struct { + uint8_t data[2]; +} QEMU_PACKED IANA_TLS_CIPHER; + +GByteArray *qcrypto_tls_cipher_suites_get_data(QCryptoTLSCipherSuites *obj, + Error **errp) +{ + QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj); + gnutls_priority_t pcache; + GByteArray *byte_array; + const char *err; + size_t i; + int ret; + + trace_qcrypto_tls_cipher_suite_priority(creds->priority); + ret = gnutls_priority_init(&pcache, creds->priority, &err); + if (ret < 0) { + error_setg(errp, "Syntax error using priority '%s': %s", + creds->priority, gnutls_strerror(ret)); + return NULL; + } + + byte_array = g_byte_array_new(); + + for (i = 0;; i++) { + int ret; + unsigned idx; + const char *name; + IANA_TLS_CIPHER cipher; + gnutls_protocol_t protocol; + const char *version; + + ret = gnutls_priority_get_cipher_suite_index(pcache, i, &idx); + if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { + break; + } + if (ret == GNUTLS_E_UNKNOWN_CIPHER_SUITE) { + continue; + } + + name = gnutls_cipher_suite_info(idx, (unsigned char *)&cipher, + NULL, NULL, NULL, &protocol); + if (name == NULL) { + continue; + } + + version = gnutls_protocol_get_name(protocol); + g_byte_array_append(byte_array, cipher.data, 2); + trace_qcrypto_tls_cipher_suite_info(cipher.data[0], + cipher.data[1], + version, name); + } + trace_qcrypto_tls_cipher_suite_count(byte_array->len); + gnutls_priority_deinit(pcache); + + return byte_array; +} + +static void qcrypto_tls_cipher_suites_complete(UserCreatable *uc, + Error **errp) +{ + QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(uc); + + if (!creds->priority) { + error_setg(errp, "'priority' property is not set"); + return; + } +} + +static GByteArray *qcrypto_tls_cipher_suites_fw_cfg_gen_data(Object *obj, + Error **errp) +{ + return qcrypto_tls_cipher_suites_get_data(QCRYPTO_TLS_CIPHER_SUITES(obj), + errp); +} + +static void qcrypto_tls_cipher_suites_class_init(ObjectClass *oc, void *data) +{ + UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); + FWCfgDataGeneratorClass *fwgc = FW_CFG_DATA_GENERATOR_CLASS(oc); + + ucc->complete = qcrypto_tls_cipher_suites_complete; + fwgc->get_data = qcrypto_tls_cipher_suites_fw_cfg_gen_data; +} + +static const TypeInfo qcrypto_tls_cipher_suites_info = { + .parent = TYPE_QCRYPTO_TLS_CREDS, + .name = TYPE_QCRYPTO_TLS_CIPHER_SUITES, + .instance_size = sizeof(QCryptoTLSCipherSuites), + .class_size = sizeof(QCryptoTLSCredsClass), + .class_init = qcrypto_tls_cipher_suites_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_USER_CREATABLE }, + { TYPE_FW_CFG_DATA_GENERATOR_INTERFACE }, + { } + } +}; + +static void qcrypto_tls_cipher_suites_register_types(void) +{ + type_register_static(&qcrypto_tls_cipher_suites_info); +} + +type_init(qcrypto_tls_cipher_suites_register_types); diff --git a/crypto/tlscredsanon.c b/crypto/tlscredsanon.c index fc078d5b97e2a681416807cbdcb7c65622f7481f..30275b684772ef6436a7d5c01ab25b6145c4bf29 100644 --- a/crypto/tlscredsanon.c +++ b/crypto/tlscredsanon.c @@ -165,7 +165,7 @@ qcrypto_tls_creds_anon_prop_get_loaded(Object *obj G_GNUC_UNUSED, static void qcrypto_tls_creds_anon_complete(UserCreatable *uc, Error **errp) { - object_property_set_bool(OBJECT(uc), true, "loaded", errp); + object_property_set_bool(OBJECT(uc), "loaded", true, errp); } diff --git a/crypto/tlscredspsk.c b/crypto/tlscredspsk.c index f01b64d8bc0f48f5e9976847fd8e697ed3880bdd..e26807b899e9f2723be43b0144a5e81d887dad1e 100644 --- a/crypto/tlscredspsk.c +++ b/crypto/tlscredspsk.c @@ -234,7 +234,7 @@ qcrypto_tls_creds_psk_prop_get_loaded(Object *obj G_GNUC_UNUSED, static void qcrypto_tls_creds_psk_complete(UserCreatable *uc, Error **errp) { - object_property_set_bool(OBJECT(uc), true, "loaded", errp); + object_property_set_bool(OBJECT(uc), "loaded", true, errp); } diff --git a/crypto/tlscredsx509.c b/crypto/tlscredsx509.c index e337d68c4f8bfbb680cacf1978481e031e459afd..dd7267ccdb0c5e686f53552a5732ca6c7d3ae0d6 100644 --- a/crypto/tlscredsx509.c +++ b/crypto/tlscredsx509.c @@ -774,7 +774,7 @@ qcrypto_tls_creds_x509_prop_get_sanity(Object *obj, static void qcrypto_tls_creds_x509_complete(UserCreatable *uc, Error **errp) { - object_property_set_bool(OBJECT(uc), true, "loaded", errp); + object_property_set_bool(OBJECT(uc), "loaded", true, errp); } diff --git a/crypto/trace-events b/crypto/trace-events index 9e594d30e8b0d3a948343e3c7c0cf4a11dfd1891..798b6067ab0f3a3be76f1a670da3deca00aa833b 100644 --- a/crypto/trace-events +++ b/crypto/trace-events @@ -21,3 +21,8 @@ qcrypto_tls_creds_x509_load_cert_list(void *creds, const char *file) "TLS creds # tlssession.c qcrypto_tls_session_new(void *session, void *creds, const char *hostname, const char *authzid, int endpoint) "TLS session new session=%p creds=%p hostname=%s authzid=%s endpoint=%d" qcrypto_tls_session_check_creds(void *session, const char *status) "TLS session check creds session=%p status=%s" + +# tls-cipher-suites.c +qcrypto_tls_cipher_suite_priority(const char *name) "priority: %s" +qcrypto_tls_cipher_suite_info(uint8_t data0, uint8_t data1, const char *version, const char *name) "data=[0x%02x,0x%02x] version=%s name=%s" +qcrypto_tls_cipher_suite_count(unsigned count) "count: %u" diff --git a/crypto/trace.h b/crypto/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..a9af0f315cb08a6b6a361edb4280b2e29d150d75 --- /dev/null +++ b/crypto/trace.h @@ -0,0 +1 @@ +#include "trace/trace-crypto.h" diff --git a/default-configs/aarch64-linux-user.mak b/default-configs/aarch64-linux-user.mak deleted file mode 100644 index 0a5b08a007423bfdaf8f9187b7f2ec44ef17c88d..0000000000000000000000000000000000000000 --- a/default-configs/aarch64-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for aarch64-linux-user diff --git a/default-configs/aarch64_be-linux-user.mak b/default-configs/aarch64_be-linux-user.mak deleted file mode 100644 index a69d9d2e41a8e49b9306eef3980fc8371f45a6cc..0000000000000000000000000000000000000000 --- a/default-configs/aarch64_be-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for aarch64_be-linux-user diff --git a/default-configs/alpha-linux-user.mak b/default-configs/alpha-linux-user.mak deleted file mode 100644 index 7956e29898a3badc2156fa983ffdea8fde76a69f..0000000000000000000000000000000000000000 --- a/default-configs/alpha-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for alpha-linux-user diff --git a/default-configs/arm-linux-user.mak b/default-configs/arm-linux-user.mak deleted file mode 100644 index 413361a022e72d5833ec105c4010ae76512745b7..0000000000000000000000000000000000000000 --- a/default-configs/arm-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for arm-linux-user diff --git a/default-configs/armeb-linux-user.mak b/default-configs/armeb-linux-user.mak deleted file mode 100644 index bf2ffe703851835722ac7a3e669f54453d6c7cfd..0000000000000000000000000000000000000000 --- a/default-configs/armeb-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for armeb-linux-user diff --git a/default-configs/cris-linux-user.mak b/default-configs/cris-linux-user.mak deleted file mode 100644 index e3aec7b864f4ce867ba8684223a863517ef275c4..0000000000000000000000000000000000000000 --- a/default-configs/cris-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for cris-linux-user diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/devices/aarch64-softmmu.mak similarity index 100% rename from default-configs/aarch64-softmmu.mak rename to default-configs/devices/aarch64-softmmu.mak diff --git a/default-configs/alpha-softmmu.mak b/default-configs/devices/alpha-softmmu.mak similarity index 100% rename from default-configs/alpha-softmmu.mak rename to default-configs/devices/alpha-softmmu.mak diff --git a/default-configs/arm-softmmu.mak b/default-configs/devices/arm-softmmu.mak similarity index 97% rename from default-configs/arm-softmmu.mak rename to default-configs/devices/arm-softmmu.mak index 8fc09a4a510370b87c0703375dd10455cca077dd..08a32123b4c9b71f5e149b684c3662835def4c42 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/devices/arm-softmmu.mak @@ -27,6 +27,7 @@ CONFIG_GUMSTIX=y CONFIG_SPITZ=y CONFIG_TOSA=y CONFIG_Z2=y +CONFIG_NPCM7XX=y CONFIG_COLLIE=y CONFIG_ASPEED_SOC=y CONFIG_NETDUINO2=y @@ -42,4 +43,3 @@ CONFIG_FSL_IMX7=y CONFIG_FSL_IMX6UL=y CONFIG_SEMIHOSTING=y CONFIG_ALLWINNER_H3=y -CONFIG_ACPI_APEI=y diff --git a/default-configs/devices/avr-softmmu.mak b/default-configs/devices/avr-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..80218add98cf1d012f6907570bdbe45d1055b333 --- /dev/null +++ b/default-configs/devices/avr-softmmu.mak @@ -0,0 +1,5 @@ +# Default configuration for avr-softmmu + +# Boards: +# +CONFIG_ARDUINO=y diff --git a/default-configs/cris-softmmu.mak b/default-configs/devices/cris-softmmu.mak similarity index 100% rename from default-configs/cris-softmmu.mak rename to default-configs/devices/cris-softmmu.mak diff --git a/default-configs/hppa-softmmu.mak b/default-configs/devices/hppa-softmmu.mak similarity index 100% rename from default-configs/hppa-softmmu.mak rename to default-configs/devices/hppa-softmmu.mak diff --git a/default-configs/i386-softmmu.mak b/default-configs/devices/i386-softmmu.mak similarity index 100% rename from default-configs/i386-softmmu.mak rename to default-configs/devices/i386-softmmu.mak diff --git a/default-configs/lm32-softmmu.mak b/default-configs/devices/lm32-softmmu.mak similarity index 100% rename from default-configs/lm32-softmmu.mak rename to default-configs/devices/lm32-softmmu.mak diff --git a/default-configs/m68k-softmmu.mak b/default-configs/devices/m68k-softmmu.mak similarity index 100% rename from default-configs/m68k-softmmu.mak rename to default-configs/devices/m68k-softmmu.mak diff --git a/default-configs/microblaze-softmmu.mak b/default-configs/devices/microblaze-softmmu.mak similarity index 100% rename from default-configs/microblaze-softmmu.mak rename to default-configs/devices/microblaze-softmmu.mak diff --git a/default-configs/microblazeel-softmmu.mak b/default-configs/devices/microblazeel-softmmu.mak similarity index 100% rename from default-configs/microblazeel-softmmu.mak rename to default-configs/devices/microblazeel-softmmu.mak diff --git a/default-configs/mips-softmmu-common.mak b/default-configs/devices/mips-softmmu-common.mak similarity index 98% rename from default-configs/mips-softmmu-common.mak rename to default-configs/devices/mips-softmmu-common.mak index da29c6c0b2446e523f46769638749a74b69b30f1..ea78fe727597a1fd120dd6341f6034a4f82077e4 100644 --- a/default-configs/mips-softmmu-common.mak +++ b/default-configs/devices/mips-softmmu-common.mak @@ -33,7 +33,6 @@ CONFIG_MC146818RTC=y CONFIG_EMPTY_SLOT=y CONFIG_MIPS_CPS=y CONFIG_MIPS_ITU=y -CONFIG_R4K=y CONFIG_MALTA=y CONFIG_PCNET_PCI=y CONFIG_MIPSSIM=y diff --git a/default-configs/mips-softmmu.mak b/default-configs/devices/mips-softmmu.mak similarity index 100% rename from default-configs/mips-softmmu.mak rename to default-configs/devices/mips-softmmu.mak diff --git a/default-configs/mips64-softmmu.mak b/default-configs/devices/mips64-softmmu.mak similarity index 100% rename from default-configs/mips64-softmmu.mak rename to default-configs/devices/mips64-softmmu.mak diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/devices/mips64el-softmmu.mak similarity index 100% rename from default-configs/mips64el-softmmu.mak rename to default-configs/devices/mips64el-softmmu.mak diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/devices/mipsel-softmmu.mak similarity index 100% rename from default-configs/mipsel-softmmu.mak rename to default-configs/devices/mipsel-softmmu.mak diff --git a/default-configs/moxie-softmmu.mak b/default-configs/devices/moxie-softmmu.mak similarity index 100% rename from default-configs/moxie-softmmu.mak rename to default-configs/devices/moxie-softmmu.mak diff --git a/default-configs/nios2-softmmu.mak b/default-configs/devices/nios2-softmmu.mak similarity index 100% rename from default-configs/nios2-softmmu.mak rename to default-configs/devices/nios2-softmmu.mak diff --git a/default-configs/or1k-softmmu.mak b/default-configs/devices/or1k-softmmu.mak similarity index 100% rename from default-configs/or1k-softmmu.mak rename to default-configs/devices/or1k-softmmu.mak diff --git a/default-configs/ppc-softmmu.mak b/default-configs/devices/ppc-softmmu.mak similarity index 100% rename from default-configs/ppc-softmmu.mak rename to default-configs/devices/ppc-softmmu.mak diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/devices/ppc64-softmmu.mak similarity index 100% rename from default-configs/ppc64-softmmu.mak rename to default-configs/devices/ppc64-softmmu.mak diff --git a/default-configs/riscv32-softmmu.mak b/default-configs/devices/riscv32-softmmu.mak similarity index 92% rename from default-configs/riscv32-softmmu.mak rename to default-configs/devices/riscv32-softmmu.mak index 1ae077ed877e64057b676afbbb20fe0c187f8f1c..94a236c9c25b23ae1c28aeb49a554f546cb4d35c 100644 --- a/default-configs/riscv32-softmmu.mak +++ b/default-configs/devices/riscv32-softmmu.mak @@ -10,3 +10,4 @@ CONFIG_SPIKE=y CONFIG_SIFIVE_E=y CONFIG_SIFIVE_U=y CONFIG_RISCV_VIRT=y +CONFIG_OPENTITAN=y diff --git a/default-configs/devices/riscv64-softmmu.mak b/default-configs/devices/riscv64-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..76b619564898cd0dab8df7878f544ed00b26e6cc --- /dev/null +++ b/default-configs/devices/riscv64-softmmu.mak @@ -0,0 +1,13 @@ +# Default configuration for riscv64-softmmu + +# Uncomment the following lines to disable these optional devices: +# +#CONFIG_PCI_DEVICES=n + +# Boards: +# +CONFIG_SPIKE=y +CONFIG_SIFIVE_E=y +CONFIG_SIFIVE_U=y +CONFIG_RISCV_VIRT=y +CONFIG_MICROCHIP_PFSOC=y diff --git a/default-configs/rx-softmmu.mak b/default-configs/devices/rx-softmmu.mak similarity index 67% rename from default-configs/rx-softmmu.mak rename to default-configs/devices/rx-softmmu.mak index 7c4eb2c1a03bd28dd133e165118b9cc6dfb38aac..df2b4e4f426186e9909ea4d7f95b0987f0d3835b 100644 --- a/default-configs/rx-softmmu.mak +++ b/default-configs/devices/rx-softmmu.mak @@ -1,2 +1,3 @@ # Default configuration for rx-softmmu +CONFIG_RX_GDBSIM=y diff --git a/default-configs/s390x-softmmu.mak b/default-configs/devices/s390x-softmmu.mak similarity index 100% rename from default-configs/s390x-softmmu.mak rename to default-configs/devices/s390x-softmmu.mak diff --git a/default-configs/sh4-softmmu.mak b/default-configs/devices/sh4-softmmu.mak similarity index 100% rename from default-configs/sh4-softmmu.mak rename to default-configs/devices/sh4-softmmu.mak diff --git a/default-configs/sh4eb-softmmu.mak b/default-configs/devices/sh4eb-softmmu.mak similarity index 100% rename from default-configs/sh4eb-softmmu.mak rename to default-configs/devices/sh4eb-softmmu.mak diff --git a/default-configs/sparc-softmmu.mak b/default-configs/devices/sparc-softmmu.mak similarity index 100% rename from default-configs/sparc-softmmu.mak rename to default-configs/devices/sparc-softmmu.mak diff --git a/default-configs/sparc64-softmmu.mak b/default-configs/devices/sparc64-softmmu.mak similarity index 100% rename from default-configs/sparc64-softmmu.mak rename to default-configs/devices/sparc64-softmmu.mak diff --git a/default-configs/tricore-softmmu.mak b/default-configs/devices/tricore-softmmu.mak similarity index 100% rename from default-configs/tricore-softmmu.mak rename to default-configs/devices/tricore-softmmu.mak diff --git a/default-configs/unicore32-softmmu.mak b/default-configs/devices/unicore32-softmmu.mak similarity index 77% rename from default-configs/unicore32-softmmu.mak rename to default-configs/devices/unicore32-softmmu.mak index 0bfce48c6da75ffd94ae44b6b1a9348269b8b9ff..899288e3d715486cbf8021cd23d76451a4c1c1c0 100644 --- a/default-configs/unicore32-softmmu.mak +++ b/default-configs/devices/unicore32-softmmu.mak @@ -3,3 +3,4 @@ # Boards: # CONFIG_PUV3=y +CONFIG_SEMIHOSTING=y diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/devices/x86_64-softmmu.mak similarity index 100% rename from default-configs/x86_64-softmmu.mak rename to default-configs/devices/x86_64-softmmu.mak diff --git a/default-configs/xtensa-softmmu.mak b/default-configs/devices/xtensa-softmmu.mak similarity index 100% rename from default-configs/xtensa-softmmu.mak rename to default-configs/devices/xtensa-softmmu.mak diff --git a/default-configs/xtensaeb-softmmu.mak b/default-configs/devices/xtensaeb-softmmu.mak similarity index 100% rename from default-configs/xtensaeb-softmmu.mak rename to default-configs/devices/xtensaeb-softmmu.mak diff --git a/default-configs/hppa-linux-user.mak b/default-configs/hppa-linux-user.mak deleted file mode 100644 index 796393940b202365e99c65ee7b2c8c3e56256ae9..0000000000000000000000000000000000000000 --- a/default-configs/hppa-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for hppa-linux-user diff --git a/default-configs/i386-bsd-user.mak b/default-configs/i386-bsd-user.mak deleted file mode 100644 index af1b31a59a744a4749f9756e930ba2cb7570b117..0000000000000000000000000000000000000000 --- a/default-configs/i386-bsd-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for i386-bsd-user diff --git a/default-configs/i386-linux-user.mak b/default-configs/i386-linux-user.mak deleted file mode 100644 index 8657e68627769a4ab76eb41e244477ca08d034a2..0000000000000000000000000000000000000000 --- a/default-configs/i386-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for i386-linux-user diff --git a/default-configs/m68k-linux-user.mak b/default-configs/m68k-linux-user.mak deleted file mode 100644 index 06cd5ed7ed87e1409d1730854015e270cd9649db..0000000000000000000000000000000000000000 --- a/default-configs/m68k-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for m68k-linux-user diff --git a/default-configs/microblaze-linux-user.mak b/default-configs/microblaze-linux-user.mak deleted file mode 100644 index 566fdc01c4d4fe4654a8ac9458dd660db404e403..0000000000000000000000000000000000000000 --- a/default-configs/microblaze-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for microblaze-linux-user diff --git a/default-configs/microblazeel-linux-user.mak b/default-configs/microblazeel-linux-user.mak deleted file mode 100644 index 378c6ddcb0546b250a64b88069e758e1a6de0814..0000000000000000000000000000000000000000 --- a/default-configs/microblazeel-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for microblazeel-linux-user diff --git a/default-configs/mips-linux-user.mak b/default-configs/mips-linux-user.mak deleted file mode 100644 index 31df57021eb07d4180f2ef55d948121b63c9b77a..0000000000000000000000000000000000000000 --- a/default-configs/mips-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for mips-linux-user diff --git a/default-configs/mips64-linux-user.mak b/default-configs/mips64-linux-user.mak deleted file mode 100644 index 1598bfcf7dade9a243cf788176a42535e5e35b87..0000000000000000000000000000000000000000 --- a/default-configs/mips64-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for mips64-linux-user diff --git a/default-configs/mips64el-linux-user.mak b/default-configs/mips64el-linux-user.mak deleted file mode 100644 index 629f084086340bc3543c384daf63924eb929be0c..0000000000000000000000000000000000000000 --- a/default-configs/mips64el-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for mips64el-linux-user diff --git a/default-configs/mipsel-linux-user.mak b/default-configs/mipsel-linux-user.mak deleted file mode 100644 index 4d0e4afb69bf5ae4c380352fa17c25d65801d019..0000000000000000000000000000000000000000 --- a/default-configs/mipsel-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for mipsel-linux-user diff --git a/default-configs/mipsn32-linux-user.mak b/default-configs/mipsn32-linux-user.mak deleted file mode 100644 index 5b979197944df4b897381014d33bb06763c4cc7b..0000000000000000000000000000000000000000 --- a/default-configs/mipsn32-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for mipsn32-linux-user diff --git a/default-configs/mipsn32el-linux-user.mak b/default-configs/mipsn32el-linux-user.mak deleted file mode 100644 index d6367ff9875347ae86fc299c599bf448354716c9..0000000000000000000000000000000000000000 --- a/default-configs/mipsn32el-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for mipsn32el-linux-user diff --git a/default-configs/nios2-linux-user.mak b/default-configs/nios2-linux-user.mak deleted file mode 100644 index 5be3eb795d0b3ad97ae2577c30502d1daeb242f8..0000000000000000000000000000000000000000 --- a/default-configs/nios2-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for nios2-linux-user diff --git a/default-configs/or1k-linux-user.mak b/default-configs/or1k-linux-user.mak deleted file mode 100644 index 20e03c131779bc56afe2a68435b1806069d224b6..0000000000000000000000000000000000000000 --- a/default-configs/or1k-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for or1k-linux-user diff --git a/default-configs/ppc-linux-user.mak b/default-configs/ppc-linux-user.mak deleted file mode 100644 index 6273df2930250e4921fac15f6efc81f757d91882..0000000000000000000000000000000000000000 --- a/default-configs/ppc-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for ppc-linux-user diff --git a/default-configs/ppc64-linux-user.mak b/default-configs/ppc64-linux-user.mak deleted file mode 100644 index 422d3fbaeb87fd477c093a06ba7b810b56e0e392..0000000000000000000000000000000000000000 --- a/default-configs/ppc64-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for ppc64-linux-user diff --git a/default-configs/ppc64abi32-linux-user.mak b/default-configs/ppc64abi32-linux-user.mak deleted file mode 100644 index 1c657ec9bb29d0723d30f1e7583f381d21d29f97..0000000000000000000000000000000000000000 --- a/default-configs/ppc64abi32-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for ppc64abi32-linux-user diff --git a/default-configs/ppc64le-linux-user.mak b/default-configs/ppc64le-linux-user.mak deleted file mode 100644 index 63f4269023044f48fa881ccb434692ae2d8981dc..0000000000000000000000000000000000000000 --- a/default-configs/ppc64le-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for ppc64le-linux-user diff --git a/default-configs/riscv32-linux-user.mak b/default-configs/riscv32-linux-user.mak deleted file mode 100644 index 865b362f5a01a377c731c7712e20f2b33ef057a4..0000000000000000000000000000000000000000 --- a/default-configs/riscv32-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for riscv-linux-user diff --git a/default-configs/riscv64-linux-user.mak b/default-configs/riscv64-linux-user.mak deleted file mode 100644 index 865b362f5a01a377c731c7712e20f2b33ef057a4..0000000000000000000000000000000000000000 --- a/default-configs/riscv64-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for riscv-linux-user diff --git a/default-configs/riscv64-softmmu.mak b/default-configs/riscv64-softmmu.mak deleted file mode 100644 index 235c6f473f7cf3b9c4b349fceed3ea6f882bd6e8..0000000000000000000000000000000000000000 --- a/default-configs/riscv64-softmmu.mak +++ /dev/null @@ -1,3 +0,0 @@ -# Default configuration for riscv64-softmmu - -include riscv32-softmmu.mak diff --git a/default-configs/s390x-linux-user.mak b/default-configs/s390x-linux-user.mak deleted file mode 100644 index a243c998740f655bdce35b0e27027202c02ea472..0000000000000000000000000000000000000000 --- a/default-configs/s390x-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for s390x-linux-user diff --git a/default-configs/sh4-linux-user.mak b/default-configs/sh4-linux-user.mak deleted file mode 100644 index a469e19ac6b9eaaacffd1d6d5f7f1be31552df85..0000000000000000000000000000000000000000 --- a/default-configs/sh4-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for sh4-linux-user diff --git a/default-configs/sh4eb-linux-user.mak b/default-configs/sh4eb-linux-user.mak deleted file mode 100644 index be08ca1002744b27dee5e61c1699894c6f7221fd..0000000000000000000000000000000000000000 --- a/default-configs/sh4eb-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for sh4eb-linux-user diff --git a/default-configs/sparc-bsd-user.mak b/default-configs/sparc-bsd-user.mak deleted file mode 100644 index 21e09508d889c14df8c8ce5f125b7e0284b009d8..0000000000000000000000000000000000000000 --- a/default-configs/sparc-bsd-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for sparc-bsd-user diff --git a/default-configs/sparc-linux-user.mak b/default-configs/sparc-linux-user.mak deleted file mode 100644 index 9c716d1f923657c6d6a3441f1048c44be051de6a..0000000000000000000000000000000000000000 --- a/default-configs/sparc-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for sparc-linux-user diff --git a/default-configs/sparc32plus-linux-user.mak b/default-configs/sparc32plus-linux-user.mak deleted file mode 100644 index 432e88011ea3b2c2d2d9bae6c5bff0ab8c9ad6e6..0000000000000000000000000000000000000000 --- a/default-configs/sparc32plus-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for sparc32plus-linux-user diff --git a/default-configs/sparc64-bsd-user.mak b/default-configs/sparc64-bsd-user.mak deleted file mode 100644 index b8b9eea7f67bb550e6528b152fa4fcfc18e1007f..0000000000000000000000000000000000000000 --- a/default-configs/sparc64-bsd-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for sparc64-bsd-user diff --git a/default-configs/sparc64-linux-user.mak b/default-configs/sparc64-linux-user.mak deleted file mode 100644 index bf1bdd6aa484705b1c187a3de909d2efadf94b16..0000000000000000000000000000000000000000 --- a/default-configs/sparc64-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for sparc64-linux-user diff --git a/default-configs/targets/aarch64-linux-user.mak b/default-configs/targets/aarch64-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..163c9209f45d6731c24f24198c99c08dc4d0ab85 --- /dev/null +++ b/default-configs/targets/aarch64-linux-user.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=aarch64 +TARGET_BASE_ARCH=arm +TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml +TARGET_HAS_BFLT=y diff --git a/default-configs/targets/aarch64-softmmu.mak b/default-configs/targets/aarch64-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..7703127674e82c832eaaadc8b8bd7ccf210c6980 --- /dev/null +++ b/default-configs/targets/aarch64-softmmu.mak @@ -0,0 +1,5 @@ +TARGET_ARCH=aarch64 +TARGET_BASE_ARCH=arm +TARGET_SUPPORTS_MTTCG=y +TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml +TARGET_NEED_FDT=y diff --git a/default-configs/targets/aarch64_be-linux-user.mak b/default-configs/targets/aarch64_be-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..4c953cf8c5939d581957523246e6cdcecda9de1e --- /dev/null +++ b/default-configs/targets/aarch64_be-linux-user.mak @@ -0,0 +1,5 @@ +TARGET_ARCH=aarch64 +TARGET_BASE_ARCH=arm +TARGET_WORDS_BIGENDIAN=y +TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml +TARGET_HAS_BFLT=y diff --git a/default-configs/targets/alpha-linux-user.mak b/default-configs/targets/alpha-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..7e62fd796a2da66620067e0e7a9aa9560879a794 --- /dev/null +++ b/default-configs/targets/alpha-linux-user.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=alpha +TARGET_SYSTBL_ABI=common +TARGET_SYSTBL=syscall.tbl +TARGET_ALIGNED_ONLY=y diff --git a/default-configs/targets/alpha-softmmu.mak b/default-configs/targets/alpha-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..e4b874a19e316710fd8fdeea45ad51e3a701ebf9 --- /dev/null +++ b/default-configs/targets/alpha-softmmu.mak @@ -0,0 +1,3 @@ +TARGET_ARCH=alpha +TARGET_ALIGNED_ONLY=y +TARGET_SUPPORTS_MTTCG=y diff --git a/default-configs/targets/arm-linux-user.mak b/default-configs/targets/arm-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..c7cd872e8600efbae4656789ebce283ad49d2ecd --- /dev/null +++ b/default-configs/targets/arm-linux-user.mak @@ -0,0 +1,5 @@ +TARGET_ARCH=arm +TARGET_SYSTBL_ABI=common,oabi +TARGET_SYSTBL=syscall.tbl +TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml +TARGET_HAS_BFLT=y diff --git a/default-configs/targets/arm-softmmu.mak b/default-configs/targets/arm-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..84a98f48186de29498c128e164be5f47bbed71e1 --- /dev/null +++ b/default-configs/targets/arm-softmmu.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=arm +TARGET_SUPPORTS_MTTCG=y +TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml +TARGET_NEED_FDT=y diff --git a/default-configs/targets/armeb-linux-user.mak b/default-configs/targets/armeb-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..79bf10e99b46e1227c821518da53b973dac02f5c --- /dev/null +++ b/default-configs/targets/armeb-linux-user.mak @@ -0,0 +1,6 @@ +TARGET_ARCH=arm +TARGET_SYSTBL_ABI=common,oabi +TARGET_SYSTBL=syscall.tbl +TARGET_WORDS_BIGENDIAN=y +TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml +TARGET_HAS_BFLT=y diff --git a/default-configs/targets/avr-softmmu.mak b/default-configs/targets/avr-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..e3f921c019902280230198c31dfe5b77ad45646f --- /dev/null +++ b/default-configs/targets/avr-softmmu.mak @@ -0,0 +1,2 @@ +TARGET_ARCH=avr +TARGET_XML_FILES= gdb-xml/avr-cpu.xml diff --git a/default-configs/targets/cris-linux-user.mak b/default-configs/targets/cris-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..e483c4206690e04bc89dd91e59fd9a0acd33c543 --- /dev/null +++ b/default-configs/targets/cris-linux-user.mak @@ -0,0 +1 @@ +TARGET_ARCH=cris diff --git a/default-configs/targets/cris-softmmu.mak b/default-configs/targets/cris-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..e483c4206690e04bc89dd91e59fd9a0acd33c543 --- /dev/null +++ b/default-configs/targets/cris-softmmu.mak @@ -0,0 +1 @@ +TARGET_ARCH=cris diff --git a/default-configs/targets/hppa-linux-user.mak b/default-configs/targets/hppa-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..f01e0a7b9ed87679619c96a9b9361fb5862d3007 --- /dev/null +++ b/default-configs/targets/hppa-linux-user.mak @@ -0,0 +1,5 @@ +TARGET_ARCH=hppa +TARGET_SYSTBL_ABI=common,32 +TARGET_SYSTBL=syscall.tbl +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/hppa-softmmu.mak b/default-configs/targets/hppa-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..e3e71eb21b9adbb7fb15d977073e6033fe79e98f --- /dev/null +++ b/default-configs/targets/hppa-softmmu.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=hppa +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y +TARGET_SUPPORTS_MTTCG=y diff --git a/default-configs/targets/i386-bsd-user.mak b/default-configs/targets/i386-bsd-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..0283bb62a070aa402497e0b5592391eb3ea8f2f7 --- /dev/null +++ b/default-configs/targets/i386-bsd-user.mak @@ -0,0 +1,2 @@ +TARGET_ARCH=i386 +TARGET_XML_FILES= gdb-xml/i386-32bit.xml diff --git a/default-configs/targets/i386-linux-user.mak b/default-configs/targets/i386-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..5b2546a43098b61e2d826e47cd81ffe92b833b13 --- /dev/null +++ b/default-configs/targets/i386-linux-user.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=i386 +TARGET_SYSTBL_ABI=i386 +TARGET_SYSTBL=syscall_32.tbl +TARGET_XML_FILES= gdb-xml/i386-32bit.xml diff --git a/default-configs/targets/i386-softmmu.mak b/default-configs/targets/i386-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..5babf71895dbe69e6f908c0db52b17119031c8b7 --- /dev/null +++ b/default-configs/targets/i386-softmmu.mak @@ -0,0 +1,3 @@ +TARGET_ARCH=i386 +TARGET_SUPPORTS_MTTCG=y +TARGET_XML_FILES= gdb-xml/i386-32bit.xml diff --git a/default-configs/targets/lm32-softmmu.mak b/default-configs/targets/lm32-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..55e7184a3db4ad40f992cdd81391a5d5025662b5 --- /dev/null +++ b/default-configs/targets/lm32-softmmu.mak @@ -0,0 +1,2 @@ +TARGET_ARCH=lm32 +TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/m68k-linux-user.mak b/default-configs/targets/m68k-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..805d16c6ab2d0b45333b24c08d5f6f904c236f63 --- /dev/null +++ b/default-configs/targets/m68k-linux-user.mak @@ -0,0 +1,6 @@ +TARGET_ARCH=m68k +TARGET_SYSTBL_ABI=common +TARGET_SYSTBL=syscall.tbl +TARGET_WORDS_BIGENDIAN=y +TARGET_XML_FILES= gdb-xml/cf-core.xml gdb-xml/cf-fp.xml gdb-xml/m68k-core.xml gdb-xml/m68k-fp.xml +TARGET_HAS_BFLT=y diff --git a/default-configs/targets/m68k-softmmu.mak b/default-configs/targets/m68k-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..5df1a2b7d76ceee7f539610aa55e6c1fa7ee71cc --- /dev/null +++ b/default-configs/targets/m68k-softmmu.mak @@ -0,0 +1,3 @@ +TARGET_ARCH=m68k +TARGET_WORDS_BIGENDIAN=y +TARGET_XML_FILES= gdb-xml/cf-core.xml gdb-xml/cf-fp.xml gdb-xml/m68k-core.xml gdb-xml/m68k-fp.xml diff --git a/default-configs/targets/microblaze-linux-user.mak b/default-configs/targets/microblaze-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..2a25bf2fa39ae93064674107ffb5ebe3ec81aaac --- /dev/null +++ b/default-configs/targets/microblaze-linux-user.mak @@ -0,0 +1,5 @@ +TARGET_ARCH=microblaze +TARGET_SYSTBL_ABI=common +TARGET_SYSTBL=syscall.tbl +TARGET_WORDS_BIGENDIAN=y +TARGET_HAS_BFLT=y diff --git a/default-configs/targets/microblaze-softmmu.mak b/default-configs/targets/microblaze-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..33f2a004029f48b6e1d11ea4e504c52c91883594 --- /dev/null +++ b/default-configs/targets/microblaze-softmmu.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=microblaze +TARGET_WORDS_BIGENDIAN=y +TARGET_SUPPORTS_MTTCG=y +TARGET_NEED_FDT=y diff --git a/default-configs/targets/microblazeel-linux-user.mak b/default-configs/targets/microblazeel-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..d0e775d8402bf6bbb98ecff1c93815b2df18bda5 --- /dev/null +++ b/default-configs/targets/microblazeel-linux-user.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=microblaze +TARGET_SYSTBL_ABI=common +TARGET_SYSTBL=syscall.tbl +TARGET_HAS_BFLT=y diff --git a/default-configs/targets/microblazeel-softmmu.mak b/default-configs/targets/microblazeel-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..af40391f2f3d2d829aa1a53893335ab85b117975 --- /dev/null +++ b/default-configs/targets/microblazeel-softmmu.mak @@ -0,0 +1,3 @@ +TARGET_ARCH=microblaze +TARGET_SUPPORTS_MTTCG=y +TARGET_NEED_FDT=y diff --git a/default-configs/targets/mips-linux-user.mak b/default-configs/targets/mips-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..19f5779831ae723d67a92771ff2d32a267176fff --- /dev/null +++ b/default-configs/targets/mips-linux-user.mak @@ -0,0 +1,6 @@ +TARGET_ARCH=mips +TARGET_ABI_MIPSO32=y +TARGET_SYSTBL_ABI=o32 +TARGET_SYSTBL=syscall_o32.tbl +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/mips-softmmu.mak b/default-configs/targets/mips-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..8a49999a47ddac78eb2c66daa2ce15f85d50da9c --- /dev/null +++ b/default-configs/targets/mips-softmmu.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=mips +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y +TARGET_SUPPORTS_MTTCG=y diff --git a/default-configs/targets/mips64-linux-user.mak b/default-configs/targets/mips64-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..32fd1acdf2548638a606e26bf255e1c733366772 --- /dev/null +++ b/default-configs/targets/mips64-linux-user.mak @@ -0,0 +1,7 @@ +TARGET_ARCH=mips64 +TARGET_ABI_MIPSN64=y +TARGET_BASE_ARCH=mips +TARGET_SYSTBL_ABI=n64 +TARGET_SYSTBL=syscall_n64.tbl +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/mips64-softmmu.mak b/default-configs/targets/mips64-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..ece25b96242e560ecbfe24a3d74cc2b67954c18a --- /dev/null +++ b/default-configs/targets/mips64-softmmu.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=mips64 +TARGET_BASE_ARCH=mips +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/mips64el-linux-user.mak b/default-configs/targets/mips64el-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..f348f35997f9d1503245b1c0b947c15a9adc0a78 --- /dev/null +++ b/default-configs/targets/mips64el-linux-user.mak @@ -0,0 +1,6 @@ +TARGET_ARCH=mips64 +TARGET_ABI_MIPSN64=y +TARGET_BASE_ARCH=mips +TARGET_SYSTBL_ABI=n64 +TARGET_SYSTBL=syscall_n64.tbl +TARGET_ALIGNED_ONLY=y diff --git a/default-configs/targets/mips64el-softmmu.mak b/default-configs/targets/mips64el-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..5a52aa4b64c8deee24255cfd1b82f63a80ccfad6 --- /dev/null +++ b/default-configs/targets/mips64el-softmmu.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=mips64 +TARGET_BASE_ARCH=mips +TARGET_ALIGNED_ONLY=y +TARGET_NEED_FDT=y diff --git a/default-configs/targets/mipsel-linux-user.mak b/default-configs/targets/mipsel-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..e23793070cfeaff270dc2ebe63cb02fa1e310c77 --- /dev/null +++ b/default-configs/targets/mipsel-linux-user.mak @@ -0,0 +1,5 @@ +TARGET_ARCH=mips +TARGET_ABI_MIPSO32=y +TARGET_SYSTBL_ABI=o32 +TARGET_SYSTBL=syscall_o32.tbl +TARGET_ALIGNED_ONLY=y diff --git a/default-configs/targets/mipsel-softmmu.mak b/default-configs/targets/mipsel-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..c7c41f4fb79aab2dd1f72c64d2b48f53eccabd07 --- /dev/null +++ b/default-configs/targets/mipsel-softmmu.mak @@ -0,0 +1,3 @@ +TARGET_ARCH=mips +TARGET_ALIGNED_ONLY=y +TARGET_SUPPORTS_MTTCG=y diff --git a/default-configs/targets/mipsn32-linux-user.mak b/default-configs/targets/mipsn32-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..b8c2441ad0763a382b502b71e4859c273e023b71 --- /dev/null +++ b/default-configs/targets/mipsn32-linux-user.mak @@ -0,0 +1,8 @@ +TARGET_ARCH=mips64 +TARGET_ABI_MIPSN32=y +TARGET_ABI32=y +TARGET_BASE_ARCH=mips +TARGET_SYSTBL_ABI=n32 +TARGET_SYSTBL=syscall_n32.tbl +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/mipsn32el-linux-user.mak b/default-configs/targets/mipsn32el-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..f31a9c394be75c4364597c91f390d03dc1fa2c77 --- /dev/null +++ b/default-configs/targets/mipsn32el-linux-user.mak @@ -0,0 +1,7 @@ +TARGET_ARCH=mips64 +TARGET_ABI_MIPSN32=y +TARGET_ABI32=y +TARGET_BASE_ARCH=mips +TARGET_SYSTBL_ABI=n32 +TARGET_SYSTBL=syscall_n32.tbl +TARGET_ALIGNED_ONLY=y diff --git a/default-configs/targets/moxie-softmmu.mak b/default-configs/targets/moxie-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..183e6b0ebda5d5329d5a84c294310d3fad38bfdb --- /dev/null +++ b/default-configs/targets/moxie-softmmu.mak @@ -0,0 +1,2 @@ +TARGET_ARCH=moxie +TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/nios2-linux-user.mak b/default-configs/targets/nios2-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..9a372f071772032ae5d568f4322530e5704e5711 --- /dev/null +++ b/default-configs/targets/nios2-linux-user.mak @@ -0,0 +1 @@ +TARGET_ARCH=nios2 diff --git a/default-configs/targets/nios2-softmmu.mak b/default-configs/targets/nios2-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..9a372f071772032ae5d568f4322530e5704e5711 --- /dev/null +++ b/default-configs/targets/nios2-softmmu.mak @@ -0,0 +1 @@ +TARGET_ARCH=nios2 diff --git a/default-configs/targets/or1k-linux-user.mak b/default-configs/targets/or1k-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..1dfb93e46dc8601d8509aae1579eb0f9c0aa20fb --- /dev/null +++ b/default-configs/targets/or1k-linux-user.mak @@ -0,0 +1,2 @@ +TARGET_ARCH=openrisc +TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/or1k-softmmu.mak b/default-configs/targets/or1k-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..1dfb93e46dc8601d8509aae1579eb0f9c0aa20fb --- /dev/null +++ b/default-configs/targets/or1k-softmmu.mak @@ -0,0 +1,2 @@ +TARGET_ARCH=openrisc +TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/ppc-linux-user.mak b/default-configs/targets/ppc-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..ca4187e4aaca6b091601991108a2a94931471812 --- /dev/null +++ b/default-configs/targets/ppc-linux-user.mak @@ -0,0 +1,5 @@ +TARGET_ARCH=ppc +TARGET_SYSTBL_ABI=common,nospu,32 +TARGET_SYSTBL=syscall.tbl +TARGET_WORDS_BIGENDIAN=y +TARGET_XML_FILES= gdb-xml/power-core.xml gdb-xml/power-fpu.xml gdb-xml/power-altivec.xml gdb-xml/power-spe.xml diff --git a/default-configs/targets/ppc-softmmu.mak b/default-configs/targets/ppc-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..f4eef1819a664e39d6ca1dbae6e5b9bbfdadd2f5 --- /dev/null +++ b/default-configs/targets/ppc-softmmu.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=ppc +TARGET_WORDS_BIGENDIAN=y +TARGET_XML_FILES= gdb-xml/power-core.xml gdb-xml/power-fpu.xml gdb-xml/power-altivec.xml gdb-xml/power-spe.xml +TARGET_NEED_FDT=y diff --git a/default-configs/targets/ppc64-linux-user.mak b/default-configs/targets/ppc64-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..3133346676cfacfa603a1576b9680882f8de9da3 --- /dev/null +++ b/default-configs/targets/ppc64-linux-user.mak @@ -0,0 +1,7 @@ +TARGET_ARCH=ppc64 +TARGET_BASE_ARCH=ppc +TARGET_ABI_DIR=ppc +TARGET_SYSTBL_ABI=common,nospu,64 +TARGET_SYSTBL=syscall.tbl +TARGET_WORDS_BIGENDIAN=y +TARGET_XML_FILES= gdb-xml/power64-core.xml gdb-xml/power-fpu.xml gdb-xml/power-altivec.xml gdb-xml/power-spe.xml gdb-xml/power-vsx.xml diff --git a/default-configs/targets/ppc64-softmmu.mak b/default-configs/targets/ppc64-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..84fbf46be9e043c0e162f6552449d576e41d549c --- /dev/null +++ b/default-configs/targets/ppc64-softmmu.mak @@ -0,0 +1,6 @@ +TARGET_ARCH=ppc64 +TARGET_BASE_ARCH=ppc +TARGET_WORDS_BIGENDIAN=y +TARGET_SUPPORTS_MTTCG=y +TARGET_XML_FILES= gdb-xml/power64-core.xml gdb-xml/power-fpu.xml gdb-xml/power-altivec.xml gdb-xml/power-spe.xml gdb-xml/power-vsx.xml +TARGET_NEED_FDT=y diff --git a/default-configs/targets/ppc64abi32-linux-user.mak b/default-configs/targets/ppc64abi32-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..0945451081b63df3094ec525e34add0e13a6daf6 --- /dev/null +++ b/default-configs/targets/ppc64abi32-linux-user.mak @@ -0,0 +1,8 @@ +TARGET_ARCH=ppc64 +TARGET_ABI32=y +TARGET_BASE_ARCH=ppc +TARGET_ABI_DIR=ppc +TARGET_SYSTBL_ABI=common,nospu,32 +TARGET_SYSTBL=syscall.tbl +TARGET_WORDS_BIGENDIAN=y +TARGET_XML_FILES= gdb-xml/power64-core.xml gdb-xml/power-fpu.xml gdb-xml/power-altivec.xml gdb-xml/power-spe.xml gdb-xml/power-vsx.xml diff --git a/default-configs/targets/ppc64le-linux-user.mak b/default-configs/targets/ppc64le-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..426d5a28d6696d436f4026ec3cff06f929fbbb65 --- /dev/null +++ b/default-configs/targets/ppc64le-linux-user.mak @@ -0,0 +1,6 @@ +TARGET_ARCH=ppc64 +TARGET_BASE_ARCH=ppc +TARGET_ABI_DIR=ppc +TARGET_SYSTBL_ABI=common,nospu,64 +TARGET_SYSTBL=syscall.tbl +TARGET_XML_FILES= gdb-xml/power64-core.xml gdb-xml/power-fpu.xml gdb-xml/power-altivec.xml gdb-xml/power-spe.xml gdb-xml/power-vsx.xml diff --git a/default-configs/targets/riscv32-linux-user.mak b/default-configs/targets/riscv32-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..dfb259e8aa87c27893acafc31833912eb56ba501 --- /dev/null +++ b/default-configs/targets/riscv32-linux-user.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=riscv32 +TARGET_BASE_ARCH=riscv +TARGET_ABI_DIR=riscv +TARGET_XML_FILES= gdb-xml/riscv-32bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-32bit-csr.xml gdb-xml/riscv-32bit-virtual.xml diff --git a/default-configs/targets/riscv32-softmmu.mak b/default-configs/targets/riscv32-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..9446d96d1345b47fc7acbcf7901f28ee55475703 --- /dev/null +++ b/default-configs/targets/riscv32-softmmu.mak @@ -0,0 +1,5 @@ +TARGET_ARCH=riscv32 +TARGET_BASE_ARCH=riscv +TARGET_SUPPORTS_MTTCG=y +TARGET_XML_FILES= gdb-xml/riscv-32bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-32bit-csr.xml gdb-xml/riscv-32bit-virtual.xml +TARGET_NEED_FDT=y diff --git a/default-configs/targets/riscv64-linux-user.mak b/default-configs/targets/riscv64-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..b13895f3b0ad75a93d5f40488968709bca14e1b8 --- /dev/null +++ b/default-configs/targets/riscv64-linux-user.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=riscv64 +TARGET_BASE_ARCH=riscv +TARGET_ABI_DIR=riscv +TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-csr.xml gdb-xml/riscv-64bit-virtual.xml diff --git a/default-configs/targets/riscv64-softmmu.mak b/default-configs/targets/riscv64-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..d809bd666a79caafe0cdf3b3ad6b9bd0bdcba88c --- /dev/null +++ b/default-configs/targets/riscv64-softmmu.mak @@ -0,0 +1,5 @@ +TARGET_ARCH=riscv64 +TARGET_BASE_ARCH=riscv +TARGET_SUPPORTS_MTTCG=y +TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-csr.xml gdb-xml/riscv-64bit-virtual.xml +TARGET_NEED_FDT=y diff --git a/default-configs/targets/rx-softmmu.mak b/default-configs/targets/rx-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..0c458b2d07c74ff8ac95ed7c1de548124ba8e3a0 --- /dev/null +++ b/default-configs/targets/rx-softmmu.mak @@ -0,0 +1,3 @@ +TARGET_ARCH=rx +TARGET_XML_FILES= gdb-xml/rx-core.xml +TARGET_NEED_FDT=y diff --git a/default-configs/targets/s390x-linux-user.mak b/default-configs/targets/s390x-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..9e31ce6457e9d532845129dce7da03f941a015eb --- /dev/null +++ b/default-configs/targets/s390x-linux-user.mak @@ -0,0 +1,5 @@ +TARGET_ARCH=s390x +TARGET_SYSTBL_ABI=common,64 +TARGET_SYSTBL=syscall.tbl +TARGET_WORDS_BIGENDIAN=y +TARGET_XML_FILES= gdb-xml/s390x-core64.xml gdb-xml/s390-acr.xml gdb-xml/s390-fpr.xml gdb-xml/s390-vx.xml gdb-xml/s390-cr.xml gdb-xml/s390-virt.xml gdb-xml/s390-gs.xml diff --git a/default-configs/targets/s390x-softmmu.mak b/default-configs/targets/s390x-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..fd9fbd870d3205f1b1b761e023a325c37237fedc --- /dev/null +++ b/default-configs/targets/s390x-softmmu.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=s390x +TARGET_WORDS_BIGENDIAN=y +TARGET_SUPPORTS_MTTCG=y +TARGET_XML_FILES= gdb-xml/s390x-core64.xml gdb-xml/s390-acr.xml gdb-xml/s390-fpr.xml gdb-xml/s390-vx.xml gdb-xml/s390-cr.xml gdb-xml/s390-virt.xml gdb-xml/s390-gs.xml diff --git a/default-configs/targets/sh4-linux-user.mak b/default-configs/targets/sh4-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..0152d6621ea5e1266563a50cd1f4aac0e1ceee96 --- /dev/null +++ b/default-configs/targets/sh4-linux-user.mak @@ -0,0 +1,5 @@ +TARGET_ARCH=sh4 +TARGET_SYSTBL_ABI=common +TARGET_SYSTBL=syscall.tbl +TARGET_ALIGNED_ONLY=y +TARGET_HAS_BFLT=y diff --git a/default-configs/targets/sh4-softmmu.mak b/default-configs/targets/sh4-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..95896376c4ff9c329060d5b47b190c2738df9b4e --- /dev/null +++ b/default-configs/targets/sh4-softmmu.mak @@ -0,0 +1,2 @@ +TARGET_ARCH=sh4 +TARGET_ALIGNED_ONLY=y diff --git a/default-configs/targets/sh4eb-linux-user.mak b/default-configs/targets/sh4eb-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..9b6fb4c1bbed42552636e5ce7cdbe3a7a39df942 --- /dev/null +++ b/default-configs/targets/sh4eb-linux-user.mak @@ -0,0 +1,6 @@ +TARGET_ARCH=sh4 +TARGET_SYSTBL_ABI=common +TARGET_SYSTBL=syscall.tbl +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y +TARGET_HAS_BFLT=y diff --git a/default-configs/targets/sh4eb-softmmu.mak b/default-configs/targets/sh4eb-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..382e9a80f8d230cec092223e5244c0032db1a818 --- /dev/null +++ b/default-configs/targets/sh4eb-softmmu.mak @@ -0,0 +1,3 @@ +TARGET_ARCH=sh4 +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/sparc-bsd-user.mak b/default-configs/targets/sparc-bsd-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..9ba3d7b07f19011f77fa470f32fed4cf5e521d47 --- /dev/null +++ b/default-configs/targets/sparc-bsd-user.mak @@ -0,0 +1,3 @@ +TARGET_ARCH=sparc +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/sparc-linux-user.mak b/default-configs/targets/sparc-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..53dc7aaed5a66d7e1298b089a11a307eb99839c2 --- /dev/null +++ b/default-configs/targets/sparc-linux-user.mak @@ -0,0 +1,5 @@ +TARGET_ARCH=sparc +TARGET_SYSTBL_ABI=common,32 +TARGET_SYSTBL=syscall.tbl +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/sparc-softmmu.mak b/default-configs/targets/sparc-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..9ba3d7b07f19011f77fa470f32fed4cf5e521d47 --- /dev/null +++ b/default-configs/targets/sparc-softmmu.mak @@ -0,0 +1,3 @@ +TARGET_ARCH=sparc +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/sparc32plus-linux-user.mak b/default-configs/targets/sparc32plus-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..e4c51df3dcad7974abef51d8197507f045b61945 --- /dev/null +++ b/default-configs/targets/sparc32plus-linux-user.mak @@ -0,0 +1,8 @@ +TARGET_ARCH=sparc64 +TARGET_ABI32=y +TARGET_BASE_ARCH=sparc +TARGET_ABI_DIR=sparc +TARGET_SYSTBL_ABI=common,32 +TARGET_SYSTBL=syscall.tbl +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/sparc64-bsd-user.mak b/default-configs/targets/sparc64-bsd-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..8dd32178004250ba43ccf74063f20538b08fe849 --- /dev/null +++ b/default-configs/targets/sparc64-bsd-user.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=sparc64 +TARGET_BASE_ARCH=sparc +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/sparc64-linux-user.mak b/default-configs/targets/sparc64-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..846924201ae17c922b91875cac341523fa8d80fe --- /dev/null +++ b/default-configs/targets/sparc64-linux-user.mak @@ -0,0 +1,6 @@ +TARGET_ARCH=sparc64 +TARGET_BASE_ARCH=sparc +TARGET_SYSTBL_ABI=common,64 +TARGET_SYSTBL=syscall.tbl +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/sparc64-softmmu.mak b/default-configs/targets/sparc64-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..8dd32178004250ba43ccf74063f20538b08fe849 --- /dev/null +++ b/default-configs/targets/sparc64-softmmu.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=sparc64 +TARGET_BASE_ARCH=sparc +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/tilegx-linux-user.mak b/default-configs/targets/tilegx-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..10480e74c9915f7396ac67f18d7c64d1b086d52e --- /dev/null +++ b/default-configs/targets/tilegx-linux-user.mak @@ -0,0 +1 @@ +TARGET_ARCH=tilegx diff --git a/default-configs/targets/tricore-softmmu.mak b/default-configs/targets/tricore-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..96b10af85336662d76a8b9c82cfbd851b5c37dd1 --- /dev/null +++ b/default-configs/targets/tricore-softmmu.mak @@ -0,0 +1 @@ +TARGET_ARCH=tricore diff --git a/default-configs/targets/unicore32-softmmu.mak b/default-configs/targets/unicore32-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..57331e94fe28174c88b1509472cbc3d720e85667 --- /dev/null +++ b/default-configs/targets/unicore32-softmmu.mak @@ -0,0 +1 @@ +TARGET_ARCH=unicore32 diff --git a/default-configs/targets/x86_64-bsd-user.mak b/default-configs/targets/x86_64-bsd-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..799cd4acd41c9c03b3a2be5c75a42a560ce99666 --- /dev/null +++ b/default-configs/targets/x86_64-bsd-user.mak @@ -0,0 +1,3 @@ +TARGET_ARCH=x86_64 +TARGET_BASE_ARCH=i386 +TARGET_XML_FILES= gdb-xml/i386-64bit.xml diff --git a/default-configs/targets/x86_64-linux-user.mak b/default-configs/targets/x86_64-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..9ceefbb615a6d172e656028a49c1bad6ef554746 --- /dev/null +++ b/default-configs/targets/x86_64-linux-user.mak @@ -0,0 +1,5 @@ +TARGET_ARCH=x86_64 +TARGET_BASE_ARCH=i386 +TARGET_SYSTBL_ABI=common,64 +TARGET_SYSTBL=syscall_64.tbl +TARGET_XML_FILES= gdb-xml/i386-64bit.xml diff --git a/default-configs/targets/x86_64-softmmu.mak b/default-configs/targets/x86_64-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..75e42bc84047efe61f0ff1f1e1123ab711bd4599 --- /dev/null +++ b/default-configs/targets/x86_64-softmmu.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=x86_64 +TARGET_BASE_ARCH=i386 +TARGET_SUPPORTS_MTTCG=y +TARGET_XML_FILES= gdb-xml/i386-64bit.xml diff --git a/default-configs/targets/xtensa-linux-user.mak b/default-configs/targets/xtensa-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..fc95cc60f5858aa8bb87e22804fcb04ec2f8f97c --- /dev/null +++ b/default-configs/targets/xtensa-linux-user.mak @@ -0,0 +1,5 @@ +TARGET_ARCH=xtensa +TARGET_SYSTBL_ABI=common +TARGET_SYSTBL=syscall.tbl +TARGET_ALIGNED_ONLY=y +TARGET_HAS_BFLT=y diff --git a/default-configs/targets/xtensa-softmmu.mak b/default-configs/targets/xtensa-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..26c0285655cd7b9208c5614c11946e3a4c8fab1f --- /dev/null +++ b/default-configs/targets/xtensa-softmmu.mak @@ -0,0 +1,3 @@ +TARGET_ARCH=xtensa +TARGET_ALIGNED_ONLY=y +TARGET_SUPPORTS_MTTCG=y diff --git a/default-configs/targets/xtensaeb-linux-user.mak b/default-configs/targets/xtensaeb-linux-user.mak new file mode 100644 index 0000000000000000000000000000000000000000..cfc3518118c9fb80fa07c8fe73ca1fce559b70f3 --- /dev/null +++ b/default-configs/targets/xtensaeb-linux-user.mak @@ -0,0 +1,6 @@ +TARGET_ARCH=xtensa +TARGET_SYSTBL_ABI=common +TARGET_SYSTBL=syscall.tbl +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y +TARGET_HAS_BFLT=y diff --git a/default-configs/targets/xtensaeb-softmmu.mak b/default-configs/targets/xtensaeb-softmmu.mak new file mode 100644 index 0000000000000000000000000000000000000000..14cb9289a62050ec7fdc379ac272e0d993027a5e --- /dev/null +++ b/default-configs/targets/xtensaeb-softmmu.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=xtensa +TARGET_ALIGNED_ONLY=y +TARGET_WORDS_BIGENDIAN=y +TARGET_SUPPORTS_MTTCG=y diff --git a/default-configs/tilegx-linux-user.mak b/default-configs/tilegx-linux-user.mak deleted file mode 100644 index 3e47493af0b092c47af9e48a6d5cc4e8427383c1..0000000000000000000000000000000000000000 --- a/default-configs/tilegx-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for tilegx-linux-user diff --git a/default-configs/x86_64-bsd-user.mak b/default-configs/x86_64-bsd-user.mak deleted file mode 100644 index 73e5d34ec5ee9d114ec6d6a764044f48690f2383..0000000000000000000000000000000000000000 --- a/default-configs/x86_64-bsd-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for x86_64-bsd-user diff --git a/default-configs/x86_64-linux-user.mak b/default-configs/x86_64-linux-user.mak deleted file mode 100644 index bec1d9e7c6bc2cbbc2e0586ea3a2ad2cfcf7df49..0000000000000000000000000000000000000000 --- a/default-configs/x86_64-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for x86_64-linux-user diff --git a/default-configs/xtensa-linux-user.mak b/default-configs/xtensa-linux-user.mak deleted file mode 100644 index fd1d350ee94433f7ecc244d8b132fde34c6602c4..0000000000000000000000000000000000000000 --- a/default-configs/xtensa-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for xtensa-linux-user diff --git a/default-configs/xtensaeb-linux-user.mak b/default-configs/xtensaeb-linux-user.mak deleted file mode 100644 index fd1d350ee94433f7ecc244d8b132fde34c6602c4..0000000000000000000000000000000000000000 --- a/default-configs/xtensaeb-linux-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for xtensa-linux-user diff --git a/disas.c b/disas.c index 45285d3f63fd62d68baf681d99c54887b6d6057c..7c18d7d2a78a736f9c375e27cc954b59dabaa81c 100644 --- a/disas.c +++ b/disas.c @@ -16,131 +16,68 @@ typedef struct CPUDebug { /* Filled in by elfload.c. Simplistic, but will do for now. */ struct syminfo *syminfos = NULL; -/* Get LENGTH bytes from info's buffer, at target address memaddr. - Transfer them to myaddr. */ -int -buffer_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length, - struct disassemble_info *info) +/* + * Get LENGTH bytes from info's buffer, at host address memaddr. + * Transfer them to myaddr. + */ +static int host_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length, + struct disassemble_info *info) { if (memaddr < info->buffer_vma - || memaddr + length > info->buffer_vma + info->buffer_length) + || memaddr + length > info->buffer_vma + info->buffer_length) { /* Out of bounds. Use EIO because GDB uses it. */ return EIO; + } memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length); return 0; } -/* Get LENGTH bytes from info's buffer, at target address memaddr. - Transfer them to myaddr. */ -static int -target_read_memory (bfd_vma memaddr, - bfd_byte *myaddr, - int length, - struct disassemble_info *info) +/* + * Get LENGTH bytes from info's buffer, at target address memaddr. + * Transfer them to myaddr. + */ +static int target_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length, + struct disassemble_info *info) { CPUDebug *s = container_of(info, CPUDebug, info); - - cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0); - return 0; + int r = cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0); + return r ? EIO : 0; } -/* Print an error message. We can assume that this is in response to - an error return from buffer_read_memory. */ -void -perror_memory (int status, bfd_vma memaddr, struct disassemble_info *info) +/* + * Print an error message. We can assume that this is in response to + * an error return from {host,target}_read_memory. + */ +static void perror_memory(int status, bfd_vma memaddr, + struct disassemble_info *info) { - if (status != EIO) - /* Can't happen. */ - (*info->fprintf_func) (info->stream, "Unknown error %d\n", status); - else - /* Actually, address between memaddr and memaddr + len was - out of bounds. */ - (*info->fprintf_func) (info->stream, - "Address 0x%" PRIx64 " is out of bounds.\n", memaddr); + if (status != EIO) { + /* Can't happen. */ + info->fprintf_func(info->stream, "Unknown error %d\n", status); + } else { + /* Address between memaddr and memaddr + len was out of bounds. */ + info->fprintf_func(info->stream, + "Address 0x%" PRIx64 " is out of bounds.\n", + memaddr); + } } -/* This could be in a separate file, to save minuscule amounts of space - in statically linked executables. */ - -/* Just print the address is hex. This is included for completeness even - though both GDB and objdump provide their own (to print symbolic - addresses). */ - -void -generic_print_address (bfd_vma addr, struct disassemble_info *info) +/* Print address in hex. */ +static void print_address(bfd_vma addr, struct disassemble_info *info) { - (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr); + info->fprintf_func(info->stream, "0x%" PRIx64, addr); } /* Print address in hex, truncated to the width of a host virtual address. */ -static void -generic_print_host_address(bfd_vma addr, struct disassemble_info *info) +static void host_print_address(bfd_vma addr, struct disassemble_info *info) { - uint64_t mask = ~0ULL >> (64 - (sizeof(void *) * 8)); - generic_print_address(addr & mask, info); + print_address((uintptr_t)addr, info); } -/* Just return the given address. */ - -int -generic_symbol_at_address (bfd_vma addr, struct disassemble_info *info) +/* Stub prevents some fruitless earching in optabs disassemblers. */ +static int symbol_at_address(bfd_vma addr, struct disassemble_info *info) { - return 1; -} - -bfd_vma bfd_getl64 (const bfd_byte *addr) -{ - unsigned long long v; - - v = (unsigned long long) addr[0]; - v |= (unsigned long long) addr[1] << 8; - v |= (unsigned long long) addr[2] << 16; - v |= (unsigned long long) addr[3] << 24; - v |= (unsigned long long) addr[4] << 32; - v |= (unsigned long long) addr[5] << 40; - v |= (unsigned long long) addr[6] << 48; - v |= (unsigned long long) addr[7] << 56; - return (bfd_vma) v; -} - -bfd_vma bfd_getl32 (const bfd_byte *addr) -{ - unsigned long v; - - v = (unsigned long) addr[0]; - v |= (unsigned long) addr[1] << 8; - v |= (unsigned long) addr[2] << 16; - v |= (unsigned long) addr[3] << 24; - return (bfd_vma) v; -} - -bfd_vma bfd_getb32 (const bfd_byte *addr) -{ - unsigned long v; - - v = (unsigned long) addr[0] << 24; - v |= (unsigned long) addr[1] << 16; - v |= (unsigned long) addr[2] << 8; - v |= (unsigned long) addr[3]; - return (bfd_vma) v; -} - -bfd_vma bfd_getl16 (const bfd_byte *addr) -{ - unsigned long v; - - v = (unsigned long) addr[0]; - v |= (unsigned long) addr[1] << 8; - return (bfd_vma) v; -} - -bfd_vma bfd_getb16 (const bfd_byte *addr) -{ - unsigned long v; - - v = (unsigned long) addr[0] << 24; - v |= (unsigned long) addr[1] << 16; - return (bfd_vma) v; + return 1; } static int print_insn_objdump(bfd_vma pc, disassemble_info *info, @@ -172,292 +109,121 @@ static int print_insn_od_target(bfd_vma pc, disassemble_info *info) return print_insn_objdump(pc, info, "OBJD-T"); } -#ifdef CONFIG_CAPSTONE -/* Temporary storage for the capstone library. This will be alloced via - malloc with a size private to the library; thus there's no reason not - to share this across calls and across host vs target disassembly. */ -static __thread cs_insn *cap_insn; - -/* Initialize the Capstone library. */ -/* ??? It would be nice to cache this. We would need one handle for the - host and one for the target. For most targets we can reset specific - parameters via cs_option(CS_OPT_MODE, new_mode), but we cannot change - CS_ARCH_* in this way. Thus we would need to be able to close and - re-open the target handle with a different arch for the target in order - to handle AArch64 vs AArch32 mode switching. */ -static cs_err cap_disas_start(disassemble_info *info, csh *handle) -{ - cs_mode cap_mode = info->cap_mode; - cs_err err; - - cap_mode += (info->endian == BFD_ENDIAN_BIG ? CS_MODE_BIG_ENDIAN - : CS_MODE_LITTLE_ENDIAN); - - err = cs_open(info->cap_arch, cap_mode, handle); - if (err != CS_ERR_OK) { - return err; - } - - /* ??? There probably ought to be a better place to put this. */ - if (info->cap_arch == CS_ARCH_X86) { - /* We don't care about errors (if for some reason the library - is compiled without AT&T syntax); the user will just have - to deal with the Intel syntax. */ - cs_option(*handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); - } - - /* "Disassemble" unknown insns as ".byte W,X,Y,Z". */ - cs_option(*handle, CS_OPT_SKIPDATA, CS_OPT_ON); - - /* Allocate temp space for cs_disasm_iter. */ - if (cap_insn == NULL) { - cap_insn = cs_malloc(*handle); - if (cap_insn == NULL) { - cs_close(handle); - return CS_ERR_MEM; - } - } - return CS_ERR_OK; -} - -static void cap_dump_insn_units(disassemble_info *info, cs_insn *insn, - int i, int n) -{ - fprintf_function print = info->fprintf_func; - FILE *stream = info->stream; - - switch (info->cap_insn_unit) { - case 4: - if (info->endian == BFD_ENDIAN_BIG) { - for (; i < n; i += 4) { - print(stream, " %08x", ldl_be_p(insn->bytes + i)); - - } - } else { - for (; i < n; i += 4) { - print(stream, " %08x", ldl_le_p(insn->bytes + i)); - } - } - break; - - case 2: - if (info->endian == BFD_ENDIAN_BIG) { - for (; i < n; i += 2) { - print(stream, " %04x", lduw_be_p(insn->bytes + i)); - } - } else { - for (; i < n; i += 2) { - print(stream, " %04x", lduw_le_p(insn->bytes + i)); - } - } - break; - - default: - for (; i < n; i++) { - print(stream, " %02x", insn->bytes[i]); - } - break; - } -} - -static void cap_dump_insn(disassemble_info *info, cs_insn *insn, - const char *note) +static void initialize_debug(CPUDebug *s) { - fprintf_function print = info->fprintf_func; - int i, n, split; - - print(info->stream, "0x%08" PRIx64 ": ", insn->address); - - n = insn->size; - split = info->cap_insn_split; - - /* Dump the first SPLIT bytes of the instruction. */ - cap_dump_insn_units(info, insn, 0, MIN(n, split)); - - /* Add padding up to SPLIT so that mnemonics line up. */ - if (n < split) { - int width = (split - n) / info->cap_insn_unit; - width *= (2 * info->cap_insn_unit + 1); - print(info->stream, "%*s", width, ""); - } - - /* Print the actual instruction. */ - print(info->stream, " %-8s %s", insn->mnemonic, insn->op_str); - if (note) { - print(info->stream, "\t\t%s", note); - } - print(info->stream, "\n"); - - /* Dump any remaining part of the insn on subsequent lines. */ - for (i = split; i < n; i += split) { - print(info->stream, "0x%08" PRIx64 ": ", insn->address + i); - cap_dump_insn_units(info, insn, i, MIN(n, i + split)); - print(info->stream, "\n"); - } + memset(s, 0, sizeof(*s)); + s->info.arch = bfd_arch_unknown; + s->info.cap_arch = -1; + s->info.cap_insn_unit = 4; + s->info.cap_insn_split = 4; + s->info.memory_error_func = perror_memory; + s->info.symbol_at_address_func = symbol_at_address; } -/* Disassemble SIZE bytes at PC for the target. */ -static bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size) +static void initialize_debug_target(CPUDebug *s, CPUState *cpu) { - uint8_t cap_buf[1024]; - csh handle; - cs_insn *insn; - size_t csize = 0; - - if (cap_disas_start(info, &handle) != CS_ERR_OK) { - return false; - } - insn = cap_insn; - - while (1) { - size_t tsize = MIN(sizeof(cap_buf) - csize, size); - const uint8_t *cbuf = cap_buf; - - target_read_memory(pc + csize, cap_buf + csize, tsize, info); - csize += tsize; - size -= tsize; - - while (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) { - cap_dump_insn(info, insn, NULL); - } - - /* If the target memory is not consumed, go back for more... */ - if (size != 0) { - /* ... taking care to move any remaining fractional insn - to the beginning of the buffer. */ - if (csize != 0) { - memmove(cap_buf, cbuf, csize); - } - continue; - } + initialize_debug(s); - /* Since the target memory is consumed, we should not have - a remaining fractional insn. */ - if (csize != 0) { - (*info->fprintf_func)(info->stream, - "Disassembler disagrees with translator " - "over instruction decoding\n" - "Please report this to qemu-devel@nongnu.org\n"); - } - break; - } - - cs_close(&handle); - return true; -} - -/* Disassemble SIZE bytes at CODE for the host. */ -static bool cap_disas_host(disassemble_info *info, void *code, size_t size, - const char *note) -{ - csh handle; - const uint8_t *cbuf; - cs_insn *insn; - uint64_t pc; - - if (cap_disas_start(info, &handle) != CS_ERR_OK) { - return false; - } - insn = cap_insn; - - cbuf = code; - pc = (uintptr_t)code; + s->cpu = cpu; + s->info.read_memory_func = target_read_memory; + s->info.print_address_func = print_address; +#ifdef TARGET_WORDS_BIGENDIAN + s->info.endian = BFD_ENDIAN_BIG; +#else + s->info.endian = BFD_ENDIAN_LITTLE; +#endif - while (cs_disasm_iter(handle, &cbuf, &size, &pc, insn)) { - cap_dump_insn(info, insn, note); - note = NULL; - } - if (size != 0) { - (*info->fprintf_func)(info->stream, - "Disassembler disagrees with TCG over instruction encoding\n" - "Please report this to qemu-devel@nongnu.org\n"); + CPUClass *cc = CPU_GET_CLASS(cpu); + if (cc->disas_set_info) { + cc->disas_set_info(cpu, &s->info); } - - cs_close(&handle); - return true; } -#if !defined(CONFIG_USER_ONLY) -/* Disassemble COUNT insns at PC for the target. */ -static bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count) +static void initialize_debug_host(CPUDebug *s) { - uint8_t cap_buf[32]; - csh handle; - cs_insn *insn; - size_t csize = 0; + initialize_debug(s); - if (cap_disas_start(info, &handle) != CS_ERR_OK) { - return false; - } - insn = cap_insn; - - while (1) { - /* We want to read memory for one insn, but generically we do not - know how much memory that is. We have a small buffer which is - known to be sufficient for all supported targets. Try to not - read beyond the page, Just In Case. For even more simplicity, - ignore the actual target page size and use a 1k boundary. If - that turns out to be insufficient, we'll come back around the - loop and read more. */ - uint64_t epc = QEMU_ALIGN_UP(pc + csize + 1, 1024); - size_t tsize = MIN(sizeof(cap_buf) - csize, epc - pc); - const uint8_t *cbuf = cap_buf; - - /* Make certain that we can make progress. */ - assert(tsize != 0); - info->read_memory_func(pc, cap_buf + csize, tsize, info); - csize += tsize; - - if (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) { - cap_dump_insn(info, insn, NULL); - if (--count <= 0) { - break; - } - } - memmove(cap_buf, cbuf, csize); - } - - cs_close(&handle); - return true; -} -#endif /* !CONFIG_USER_ONLY */ + s->info.read_memory_func = host_read_memory; + s->info.print_address_func = host_print_address; +#ifdef HOST_WORDS_BIGENDIAN + s->info.endian = BFD_ENDIAN_BIG; +#else + s->info.endian = BFD_ENDIAN_LITTLE; +#endif +#if defined(CONFIG_TCG_INTERPRETER) + s->info.print_insn = print_insn_tci; +#elif defined(__i386__) + s->info.mach = bfd_mach_i386_i386; + s->info.print_insn = print_insn_i386; + s->info.cap_arch = CS_ARCH_X86; + s->info.cap_mode = CS_MODE_32; + s->info.cap_insn_unit = 1; + s->info.cap_insn_split = 8; +#elif defined(__x86_64__) + s->info.mach = bfd_mach_x86_64; + s->info.print_insn = print_insn_i386; + s->info.cap_arch = CS_ARCH_X86; + s->info.cap_mode = CS_MODE_64; + s->info.cap_insn_unit = 1; + s->info.cap_insn_split = 8; +#elif defined(_ARCH_PPC) + s->info.disassembler_options = (char *)"any"; + s->info.print_insn = print_insn_ppc; + s->info.cap_arch = CS_ARCH_PPC; +# ifdef _ARCH_PPC64 + s->info.cap_mode = CS_MODE_64; +# endif +#elif defined(__riscv) && defined(CONFIG_RISCV_DIS) +#if defined(_ILP32) || (__riscv_xlen == 32) + s->info.print_insn = print_insn_riscv32; +#elif defined(_LP64) + s->info.print_insn = print_insn_riscv64; #else -# define cap_disas_target(i, p, s) false -# define cap_disas_host(i, p, s, n) false -# define cap_disas_monitor(i, p, c) false -# define cap_disas_plugin(i, p, c) false -#endif /* CONFIG_CAPSTONE */ +#error unsupported RISC-V ABI +#endif +#elif defined(__aarch64__) + s->info.cap_arch = CS_ARCH_ARM64; +# ifdef CONFIG_ARM_A64_DIS + s->info.print_insn = print_insn_arm_a64; +# endif +#elif defined(__alpha__) + s->info.print_insn = print_insn_alpha; +#elif defined(__sparc__) + s->info.print_insn = print_insn_sparc; + s->info.mach = bfd_mach_sparc_v9b; +#elif defined(__arm__) + /* TCG only generates code for arm mode. */ + s->info.print_insn = print_insn_arm; + s->info.cap_arch = CS_ARCH_ARM; +#elif defined(__MIPSEB__) + s->info.print_insn = print_insn_big_mips; +#elif defined(__MIPSEL__) + s->info.print_insn = print_insn_little_mips; +#elif defined(__m68k__) + s->info.print_insn = print_insn_m68k; +#elif defined(__s390__) + s->info.print_insn = print_insn_s390; + s->info.cap_arch = CS_ARCH_SYSZ; + s->info.cap_insn_unit = 2; + s->info.cap_insn_split = 6; +#elif defined(__hppa__) + s->info.print_insn = print_insn_hppa; +#endif +} /* Disassemble this for me please... (debugging). */ void target_disas(FILE *out, CPUState *cpu, target_ulong code, target_ulong size) { - CPUClass *cc = CPU_GET_CLASS(cpu); target_ulong pc; int count; CPUDebug s; - INIT_DISASSEMBLE_INFO(s.info, out, fprintf); - - s.cpu = cpu; - s.info.read_memory_func = target_read_memory; + initialize_debug_target(&s, cpu); + s.info.fprintf_func = fprintf; + s.info.stream = out; s.info.buffer_vma = code; s.info.buffer_length = size; - s.info.print_address_func = generic_print_address; - s.info.cap_arch = -1; - s.info.cap_mode = 0; - s.info.cap_insn_unit = 4; - s.info.cap_insn_split = 4; - -#ifdef TARGET_WORDS_BIGENDIAN - s.info.endian = BFD_ENDIAN_BIG; -#else - s.info.endian = BFD_ENDIAN_LITTLE; -#endif - - if (cc->disas_set_info) { - cc->disas_set_info(cpu, &s.info); - } if (s.info.cap_arch >= 0 && cap_disas_target(&s.info, code, size)) { return; @@ -483,13 +249,12 @@ void target_disas(FILE *out, CPUState *cpu, target_ulong code, } } -static __thread GString plugin_disas_output; - static int plugin_printf(FILE *stream, const char *fmt, ...) { - va_list va; - GString *s = &plugin_disas_output; + /* We abuse the FILE parameter to pass a GString. */ + GString *s = (GString *)stream; int initial_len = s->len; + va_list va; va_start(va, fmt); g_string_append_vprintf(s, fmt, va); @@ -504,40 +269,6 @@ static void plugin_print_address(bfd_vma addr, struct disassemble_info *info) } -#ifdef CONFIG_CAPSTONE -/* Disassemble a single instruction directly into plugin output */ -static -bool cap_disas_plugin(disassemble_info *info, uint64_t pc, size_t size) -{ - uint8_t cap_buf[1024]; - csh handle; - cs_insn *insn; - size_t csize = 0; - int count; - GString *s = &plugin_disas_output; - - if (cap_disas_start(info, &handle) != CS_ERR_OK) { - return false; - } - insn = cap_insn; - - size_t tsize = MIN(sizeof(cap_buf) - csize, size); - const uint8_t *cbuf = cap_buf; - target_read_memory(pc, cap_buf, tsize, info); - - count = cs_disasm(handle, cbuf, size, 0, 1, &insn); - - if (count) { - g_string_printf(s, "%s %s", insn->mnemonic, insn->op_str); - } else { - g_string_printf(s, "cs_disasm failed"); - } - - cs_close(&handle); - return true; -} -#endif - /* * We should only be dissembling one instruction at a time here. If * there is left over it usually indicates the front end has read more @@ -545,146 +276,52 @@ bool cap_disas_plugin(disassemble_info *info, uint64_t pc, size_t size) */ char *plugin_disas(CPUState *cpu, uint64_t addr, size_t size) { - CPUClass *cc = CPU_GET_CLASS(cpu); - int count; CPUDebug s; - GString *ds = g_string_set_size(&plugin_disas_output, 0); - - g_assert(ds == &plugin_disas_output); + GString *ds = g_string_new(NULL); - INIT_DISASSEMBLE_INFO(s.info, NULL, plugin_printf); - - s.cpu = cpu; - s.info.read_memory_func = target_read_memory; + initialize_debug_target(&s, cpu); + s.info.fprintf_func = plugin_printf; + s.info.stream = (FILE *)ds; /* abuse this slot */ s.info.buffer_vma = addr; s.info.buffer_length = size; s.info.print_address_func = plugin_print_address; - s.info.cap_arch = -1; - s.info.cap_mode = 0; - s.info.cap_insn_unit = 4; - s.info.cap_insn_split = 4; - -#ifdef TARGET_WORDS_BIGENDIAN - s.info.endian = BFD_ENDIAN_BIG; -#else - s.info.endian = BFD_ENDIAN_LITTLE; -#endif - - if (cc->disas_set_info) { - cc->disas_set_info(cpu, &s.info); - } if (s.info.cap_arch >= 0 && cap_disas_plugin(&s.info, addr, size)) { - return g_strdup(ds->str); - } - - if (s.info.print_insn == NULL) { - s.info.print_insn = print_insn_od_target; - } - - count = s.info.print_insn(addr, &s.info); - - /* The decoder probably read more than it needed it's not critical */ - if (count < size) { - warn_report("%s: %zu bytes left over", __func__, size - count); + ; /* done */ + } else if (s.info.print_insn) { + s.info.print_insn(addr, &s.info); + } else { + ; /* cannot disassemble -- return empty string */ } - return g_strdup(ds->str); + /* Return the buffer, freeing the GString container. */ + return g_string_free(ds, false); } /* Disassemble this for me please... (debugging). */ -void disas(FILE *out, void *code, unsigned long size, const char *note) +void disas(FILE *out, void *code, unsigned long size) { uintptr_t pc; int count; CPUDebug s; - int (*print_insn)(bfd_vma pc, disassemble_info *info) = NULL; - - INIT_DISASSEMBLE_INFO(s.info, out, fprintf); - s.info.print_address_func = generic_print_host_address; + initialize_debug_host(&s); + s.info.fprintf_func = fprintf; + s.info.stream = out; s.info.buffer = code; s.info.buffer_vma = (uintptr_t)code; s.info.buffer_length = size; - s.info.cap_arch = -1; - s.info.cap_mode = 0; - s.info.cap_insn_unit = 4; - s.info.cap_insn_split = 4; -#ifdef HOST_WORDS_BIGENDIAN - s.info.endian = BFD_ENDIAN_BIG; -#else - s.info.endian = BFD_ENDIAN_LITTLE; -#endif -#if defined(CONFIG_TCG_INTERPRETER) - print_insn = print_insn_tci; -#elif defined(__i386__) - s.info.mach = bfd_mach_i386_i386; - print_insn = print_insn_i386; - s.info.cap_arch = CS_ARCH_X86; - s.info.cap_mode = CS_MODE_32; - s.info.cap_insn_unit = 1; - s.info.cap_insn_split = 8; -#elif defined(__x86_64__) - s.info.mach = bfd_mach_x86_64; - print_insn = print_insn_i386; - s.info.cap_arch = CS_ARCH_X86; - s.info.cap_mode = CS_MODE_64; - s.info.cap_insn_unit = 1; - s.info.cap_insn_split = 8; -#elif defined(_ARCH_PPC) - s.info.disassembler_options = (char *)"any"; - print_insn = print_insn_ppc; - s.info.cap_arch = CS_ARCH_PPC; -# ifdef _ARCH_PPC64 - s.info.cap_mode = CS_MODE_64; -# endif -#elif defined(__riscv) && defined(CONFIG_RISCV_DIS) -#if defined(_ILP32) || (__riscv_xlen == 32) - print_insn = print_insn_riscv32; -#elif defined(_LP64) - print_insn = print_insn_riscv64; -#else -#error unsupported RISC-V ABI -#endif -#elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS) - print_insn = print_insn_arm_a64; - s.info.cap_arch = CS_ARCH_ARM64; -#elif defined(__alpha__) - print_insn = print_insn_alpha; -#elif defined(__sparc__) - print_insn = print_insn_sparc; - s.info.mach = bfd_mach_sparc_v9b; -#elif defined(__arm__) - print_insn = print_insn_arm; - s.info.cap_arch = CS_ARCH_ARM; - /* TCG only generates code for arm mode. */ -#elif defined(__MIPSEB__) - print_insn = print_insn_big_mips; -#elif defined(__MIPSEL__) - print_insn = print_insn_little_mips; -#elif defined(__m68k__) - print_insn = print_insn_m68k; -#elif defined(__s390__) - print_insn = print_insn_s390; -#elif defined(__hppa__) - print_insn = print_insn_hppa; -#endif - - if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size, note)) { + if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size)) { return; } - if (print_insn == NULL) { - print_insn = print_insn_od_host; + if (s.info.print_insn == NULL) { + s.info.print_insn = print_insn_od_host; } for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) { fprintf(out, "0x%08" PRIxPTR ": ", pc); - count = print_insn(pc, &s.info); - if (note) { - fprintf(out, "\t\t%s", note); - note = NULL; - } + count = s.info.print_insn(pc, &s.info); fprintf(out, "\n"); if (count < 0) { break; @@ -718,41 +355,26 @@ physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length, struct disassemble_info *info) { CPUDebug *s = container_of(info, CPUDebug, info); + MemTxResult res; - address_space_read(s->cpu->as, memaddr, MEMTXATTRS_UNSPECIFIED, - myaddr, length); - return 0; + res = address_space_read(s->cpu->as, memaddr, MEMTXATTRS_UNSPECIFIED, + myaddr, length); + return res == MEMTX_OK ? 0 : EIO; } /* Disassembler for the monitor. */ void monitor_disas(Monitor *mon, CPUState *cpu, target_ulong pc, int nb_insn, int is_physical) { - CPUClass *cc = CPU_GET_CLASS(cpu); int count, i; CPUDebug s; - INIT_DISASSEMBLE_INFO(s.info, NULL, qemu_fprintf); - - s.cpu = cpu; - s.info.read_memory_func - = (is_physical ? physical_read_memory : target_read_memory); - s.info.print_address_func = generic_print_address; - s.info.buffer_vma = pc; - s.info.cap_arch = -1; - s.info.cap_mode = 0; - s.info.cap_insn_unit = 4; - s.info.cap_insn_split = 4; - -#ifdef TARGET_WORDS_BIGENDIAN - s.info.endian = BFD_ENDIAN_BIG; -#else - s.info.endian = BFD_ENDIAN_LITTLE; -#endif - - if (cc->disas_set_info) { - cc->disas_set_info(cpu, &s.info); + initialize_debug_target(&s, cpu); + s.info.fprintf_func = qemu_fprintf; + if (is_physical) { + s.info.read_memory_func = physical_read_memory; } + s.info.buffer_vma = pc; if (s.info.cap_arch >= 0 && cap_disas_monitor(&s.info, pc, nb_insn)) { return; diff --git a/disas/Makefile.objs b/disas/Makefile.objs deleted file mode 100644 index 3c1cdce02694e65e41d67d8b101ae88c9156c7f7..0000000000000000000000000000000000000000 --- a/disas/Makefile.objs +++ /dev/null @@ -1,30 +0,0 @@ - -common-obj-$(CONFIG_ALPHA_DIS) += alpha.o -common-obj-$(CONFIG_ARM_DIS) += arm.o -common-obj-$(CONFIG_ARM_A64_DIS) += arm-a64.o -common-obj-$(CONFIG_ARM_A64_DIS) += libvixl/ -libvixldir = $(SRC_PATH)/disas/libvixl -# The -Wno-sign-compare is needed only for gcc 4.6, which complains about -# some signed-unsigned equality comparisons in libvixl which later gcc -# versions do not. -arm-a64.o-cflags := -I$(libvixldir) -Wno-sign-compare -common-obj-$(CONFIG_CRIS_DIS) += cris.o -common-obj-$(CONFIG_HPPA_DIS) += hppa.o -common-obj-$(CONFIG_I386_DIS) += i386.o -common-obj-$(CONFIG_M68K_DIS) += m68k.o -common-obj-$(CONFIG_MICROBLAZE_DIS) += microblaze.o -common-obj-$(CONFIG_MIPS_DIS) += mips.o -common-obj-$(CONFIG_NANOMIPS_DIS) += nanomips.o -common-obj-$(CONFIG_NIOS2_DIS) += nios2.o -common-obj-$(CONFIG_MOXIE_DIS) += moxie.o -common-obj-$(CONFIG_PPC_DIS) += ppc.o -common-obj-$(CONFIG_RISCV_DIS) += riscv.o -common-obj-$(CONFIG_S390_DIS) += s390.o -common-obj-$(CONFIG_SH4_DIS) += sh4.o -common-obj-$(CONFIG_SPARC_DIS) += sparc.o -common-obj-$(CONFIG_LM32_DIS) += lm32.o -common-obj-$(CONFIG_XTENSA_DIS) += xtensa.o - -# TODO: As long as the TCG interpreter and its generated code depend -# on the QEMU target, we cannot compile the disassembler here. -#common-obj-$(CONFIG_TCI_DIS) += tci.o diff --git a/disas/capstone.c b/disas/capstone.c new file mode 100644 index 0000000000000000000000000000000000000000..7462c0e3053f445e5a8461e029c3ed196b844d44 --- /dev/null +++ b/disas/capstone.c @@ -0,0 +1,326 @@ +/* + * Interface to the capstone disassembler. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/bswap.h" +#include "disas/dis-asm.h" +#include "disas/capstone.h" + + +/* + * Temporary storage for the capstone library. This will be alloced via + * malloc with a size private to the library; thus there's no reason not + * to share this across calls and across host vs target disassembly. + */ +static __thread cs_insn *cap_insn; + +/* + * The capstone library always skips 2 bytes for S390X. + * This is less than ideal, since we can tell from the first two bits + * the size of the insn and thus stay in sync with the insn stream. + */ +static size_t CAPSTONE_API +cap_skipdata_s390x_cb(const uint8_t *code, size_t code_size, + size_t offset, void *user_data) +{ + size_t ilen; + + /* See get_ilen() in target/s390x/internal.h. */ + switch (code[offset] >> 6) { + case 0: + ilen = 2; + break; + case 1: + case 2: + ilen = 4; + break; + default: + ilen = 6; + break; + } + + return ilen; +} + +static const cs_opt_skipdata cap_skipdata_s390x = { + .mnemonic = ".byte", + .callback = cap_skipdata_s390x_cb +}; + +/* + * Initialize the Capstone library. + * + * ??? It would be nice to cache this. We would need one handle for the + * host and one for the target. For most targets we can reset specific + * parameters via cs_option(CS_OPT_MODE, new_mode), but we cannot change + * CS_ARCH_* in this way. Thus we would need to be able to close and + * re-open the target handle with a different arch for the target in order + * to handle AArch64 vs AArch32 mode switching. + */ +static cs_err cap_disas_start(disassemble_info *info, csh *handle) +{ + cs_mode cap_mode = info->cap_mode; + cs_err err; + + cap_mode += (info->endian == BFD_ENDIAN_BIG ? CS_MODE_BIG_ENDIAN + : CS_MODE_LITTLE_ENDIAN); + + err = cs_open(info->cap_arch, cap_mode, handle); + if (err != CS_ERR_OK) { + return err; + } + + /* "Disassemble" unknown insns as ".byte W,X,Y,Z". */ + cs_option(*handle, CS_OPT_SKIPDATA, CS_OPT_ON); + + switch (info->cap_arch) { + case CS_ARCH_SYSZ: + cs_option(*handle, CS_OPT_SKIPDATA_SETUP, + (uintptr_t)&cap_skipdata_s390x); + break; + + case CS_ARCH_X86: + /* + * We don't care about errors (if for some reason the library + * is compiled without AT&T syntax); the user will just have + * to deal with the Intel syntax. + */ + cs_option(*handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); + break; + } + + /* Allocate temp space for cs_disasm_iter. */ + if (cap_insn == NULL) { + cap_insn = cs_malloc(*handle); + if (cap_insn == NULL) { + cs_close(handle); + return CS_ERR_MEM; + } + } + return CS_ERR_OK; +} + +static void cap_dump_insn_units(disassemble_info *info, cs_insn *insn, + int i, int n) +{ + fprintf_function print = info->fprintf_func; + FILE *stream = info->stream; + + switch (info->cap_insn_unit) { + case 4: + if (info->endian == BFD_ENDIAN_BIG) { + for (; i < n; i += 4) { + print(stream, " %08x", ldl_be_p(insn->bytes + i)); + + } + } else { + for (; i < n; i += 4) { + print(stream, " %08x", ldl_le_p(insn->bytes + i)); + } + } + break; + + case 2: + if (info->endian == BFD_ENDIAN_BIG) { + for (; i < n; i += 2) { + print(stream, " %04x", lduw_be_p(insn->bytes + i)); + } + } else { + for (; i < n; i += 2) { + print(stream, " %04x", lduw_le_p(insn->bytes + i)); + } + } + break; + + default: + for (; i < n; i++) { + print(stream, " %02x", insn->bytes[i]); + } + break; + } +} + +static void cap_dump_insn(disassemble_info *info, cs_insn *insn) +{ + fprintf_function print = info->fprintf_func; + FILE *stream = info->stream; + int i, n, split; + + print(stream, "0x%08" PRIx64 ": ", insn->address); + + n = insn->size; + split = info->cap_insn_split; + + /* Dump the first SPLIT bytes of the instruction. */ + cap_dump_insn_units(info, insn, 0, MIN(n, split)); + + /* Add padding up to SPLIT so that mnemonics line up. */ + if (n < split) { + int width = (split - n) / info->cap_insn_unit; + width *= (2 * info->cap_insn_unit + 1); + print(stream, "%*s", width, ""); + } + + /* Print the actual instruction. */ + print(stream, " %-8s %s\n", insn->mnemonic, insn->op_str); + + /* Dump any remaining part of the insn on subsequent lines. */ + for (i = split; i < n; i += split) { + print(stream, "0x%08" PRIx64 ": ", insn->address + i); + cap_dump_insn_units(info, insn, i, MIN(n, i + split)); + print(stream, "\n"); + } +} + +/* Disassemble SIZE bytes at PC for the target. */ +bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size) +{ + uint8_t cap_buf[1024]; + csh handle; + cs_insn *insn; + size_t csize = 0; + + if (cap_disas_start(info, &handle) != CS_ERR_OK) { + return false; + } + insn = cap_insn; + + while (1) { + size_t tsize = MIN(sizeof(cap_buf) - csize, size); + const uint8_t *cbuf = cap_buf; + + info->read_memory_func(pc + csize, cap_buf + csize, tsize, info); + csize += tsize; + size -= tsize; + + while (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) { + cap_dump_insn(info, insn); + } + + /* If the target memory is not consumed, go back for more... */ + if (size != 0) { + /* + * ... taking care to move any remaining fractional insn + * to the beginning of the buffer. + */ + if (csize != 0) { + memmove(cap_buf, cbuf, csize); + } + continue; + } + + /* + * Since the target memory is consumed, we should not have + * a remaining fractional insn. + */ + if (csize != 0) { + info->fprintf_func(info->stream, + "Disassembler disagrees with translator " + "over instruction decoding\n" + "Please report this to qemu-devel@nongnu.org\n"); + } + break; + } + + cs_close(&handle); + return true; +} + +/* Disassemble SIZE bytes at CODE for the host. */ +bool cap_disas_host(disassemble_info *info, void *code, size_t size) +{ + csh handle; + const uint8_t *cbuf; + cs_insn *insn; + uint64_t pc; + + if (cap_disas_start(info, &handle) != CS_ERR_OK) { + return false; + } + insn = cap_insn; + + cbuf = code; + pc = (uintptr_t)code; + + while (cs_disasm_iter(handle, &cbuf, &size, &pc, insn)) { + cap_dump_insn(info, insn); + } + if (size != 0) { + info->fprintf_func(info->stream, + "Disassembler disagrees with TCG over instruction encoding\n" + "Please report this to qemu-devel@nongnu.org\n"); + } + + cs_close(&handle); + return true; +} + +/* Disassemble COUNT insns at PC for the target. */ +bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count) +{ + uint8_t cap_buf[32]; + csh handle; + cs_insn *insn; + size_t csize = 0; + + if (cap_disas_start(info, &handle) != CS_ERR_OK) { + return false; + } + insn = cap_insn; + + while (1) { + /* + * We want to read memory for one insn, but generically we do not + * know how much memory that is. We have a small buffer which is + * known to be sufficient for all supported targets. Try to not + * read beyond the page, Just In Case. For even more simplicity, + * ignore the actual target page size and use a 1k boundary. If + * that turns out to be insufficient, we'll come back around the + * loop and read more. + */ + uint64_t epc = QEMU_ALIGN_UP(pc + csize + 1, 1024); + size_t tsize = MIN(sizeof(cap_buf) - csize, epc - pc); + const uint8_t *cbuf = cap_buf; + + /* Make certain that we can make progress. */ + assert(tsize != 0); + info->read_memory_func(pc + csize, cap_buf + csize, tsize, info); + csize += tsize; + + if (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) { + cap_dump_insn(info, insn); + if (--count <= 0) { + break; + } + } + memmove(cap_buf, cbuf, csize); + } + + cs_close(&handle); + return true; +} + +/* Disassemble a single instruction directly into plugin output */ +bool cap_disas_plugin(disassemble_info *info, uint64_t pc, size_t size) +{ + uint8_t cap_buf[32]; + const uint8_t *cbuf = cap_buf; + csh handle; + + if (cap_disas_start(info, &handle) != CS_ERR_OK) { + return false; + } + + assert(size < sizeof(cap_buf)); + info->read_memory_func(pc, cap_buf, size, info); + + if (cs_disasm_iter(handle, &cbuf, &size, &pc, cap_insn)) { + info->fprintf_func(info->stream, "%s %s", + cap_insn->mnemonic, cap_insn->op_str); + } + + cs_close(&handle); + return true; +} diff --git a/disas/hppa.c b/disas/hppa.c index 2dbd1fc4454ef79454fadc855ce3fe00c7cc47ff..dcf9a47f348932ea7ddaafe810f2e1d04c146583 100644 --- a/disas/hppa.c +++ b/disas/hppa.c @@ -2021,7 +2021,7 @@ print_insn_hppa (bfd_vma memaddr, disassemble_info *info) fput_fp_reg (GET_FIELD (insn, 6, 10), info); break; - /* 'fA' will not generate a space before the regsiter + /* 'fA' will not generate a space before the register name. Normally that is fine. Except that it causes problems with xmpyu which has no FP format completer. */ diff --git a/disas/libvixl/Makefile.objs b/disas/libvixl/Makefile.objs deleted file mode 100644 index 99a637f6a0a721d4c02f171c92baa69b56ef17f1..0000000000000000000000000000000000000000 --- a/disas/libvixl/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -common-obj-$(CONFIG_ARM_A64_DIS) = vixl/utils.o \ - vixl/compiler-intrinsics.o \ - vixl/a64/instructions-a64.o \ - vixl/a64/decoder-a64.o \ - vixl/a64/disasm-a64.o diff --git a/disas/libvixl/meson.build b/disas/libvixl/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..5e2eb33e8ef5dc0f63b7a134ca8346023773f076 --- /dev/null +++ b/disas/libvixl/meson.build @@ -0,0 +1,7 @@ +libvixl_ss.add(files( + 'vixl/a64/decoder-a64.cc', + 'vixl/a64/disasm-a64.cc', + 'vixl/a64/instructions-a64.cc', + 'vixl/compiler-intrinsics.cc', + 'vixl/utils.cc', +)) diff --git a/disas/lm32.c b/disas/lm32.c index c0ef8160fe690aeb32c83f008f6d9dbdab041afe..4fbb1245348824bcc92776b7d9001902dd57da17 100644 --- a/disas/lm32.c +++ b/disas/lm32.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/disas/m68k.c b/disas/m68k.c index 863409c67ccb3132e83ed09c835ff2618972bc0d..aefaecfbd6cbed736a437ebeea9987b44c86e7dd 100644 --- a/disas/m68k.c +++ b/disas/m68k.c @@ -70,7 +70,7 @@ struct floatformat unsigned int exp_start; unsigned int exp_len; /* Bias added to a "true" exponent to form the biased exponent. It - is intentionally signed as, otherwize, -exp_bias can turn into a + is intentionally signed as, otherwise, -exp_bias can turn into a very large number (e.g., given the exp_bias of 0x3fff and a 64 bit long, the equation (long)(1 - exp_bias) evaluates to 4294950914) instead of -16382). */ @@ -479,7 +479,7 @@ struct m68k_opcode_alias and remaining 3 bits of register shifted 9 bits in first word. Indicate upper/lower in 1 bit shifted 7 bits in second word. Use with `R' or `u' format. - n `m' withouth upper/lower indication. (For M[S]ACx; 4 bits split + n `m' without upper/lower indication. (For M[S]ACx; 4 bits split with MSB shifted 6 bits in first word and remaining 3 bits of register shifted 9 bits in first word. No upper/lower indication is done.) Use with `R' or `u' format. @@ -854,7 +854,7 @@ fetch_arg (unsigned char *buffer, /* Check if an EA is valid for a particular code. This is required for the EMAC instructions since the type of source address determines - if it is a EMAC-load instruciton if the EA is mode 2-5, otherwise it + if it is a EMAC-load instruction if the EA is mode 2-5, otherwise it is a non-load EMAC instruction and the bits mean register Ry. A similar case exists for the movem instructions where the register mask is interpreted differently for different EAs. */ @@ -1080,7 +1080,7 @@ print_indexed (int basereg, /* Returns number of bytes "eaten" by the operand, or return -1 if an invalid operand was found, or -2 if - an opcode tabe error was found. + an opcode table error was found. ADDR is the pc for this arg to be relative to. */ static int diff --git a/disas/meson.build b/disas/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..09a852742e2592a4622e2bcfa0c913874364e853 --- /dev/null +++ b/disas/meson.build @@ -0,0 +1,26 @@ +libvixl_ss = ss.source_set() +subdir('libvixl') + +common_ss.add(when: 'CONFIG_ALPHA_DIS', if_true: files('alpha.c')) +common_ss.add(when: 'CONFIG_ARM_A64_DIS', if_true: files('arm-a64.cc')) +common_ss.add_all(when: 'CONFIG_ARM_A64_DIS', if_true: libvixl_ss) +common_ss.add(when: 'CONFIG_ARM_DIS', if_true: files('arm.c')) +common_ss.add(when: 'CONFIG_CRIS_DIS', if_true: files('cris.c')) +common_ss.add(when: 'CONFIG_HPPA_DIS', if_true: files('hppa.c')) +common_ss.add(when: 'CONFIG_I386_DIS', if_true: files('i386.c')) +common_ss.add(when: 'CONFIG_LM32_DIS', if_true: files('lm32.c')) +common_ss.add(when: 'CONFIG_M68K_DIS', if_true: files('m68k.c')) +common_ss.add(when: 'CONFIG_MICROBLAZE_DIS', if_true: files('microblaze.c')) +common_ss.add(when: 'CONFIG_MIPS_DIS', if_true: files('mips.c')) +common_ss.add(when: 'CONFIG_MOXIE_DIS', if_true: files('moxie.c')) +common_ss.add(when: 'CONFIG_NANOMIPS_DIS', if_true: files('nanomips.cpp')) +common_ss.add(when: 'CONFIG_NIOS2_DIS', if_true: files('nios2.c')) +common_ss.add(when: 'CONFIG_PPC_DIS', if_true: files('ppc.c')) +common_ss.add(when: 'CONFIG_RISCV_DIS', if_true: files('riscv.c')) +common_ss.add(when: 'CONFIG_S390_DIS', if_true: files('s390.c')) +common_ss.add(when: 'CONFIG_SH4_DIS', if_true: files('sh4.c')) +common_ss.add(when: 'CONFIG_SPARC_DIS', if_true: files('sparc.c')) +common_ss.add(when: 'CONFIG_XTENSA_DIS', if_true: files('xtensa.c')) +common_ss.add(when: capstone, if_true: files('capstone.c')) + +specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('tci.c')) diff --git a/disas/ppc.c b/disas/ppc.c index 63e97cfe1da27de94983987e820c5cbedd32df51..02be8781983270f1ce05d766d6a76e82d90bf700 100644 --- a/disas/ppc.c +++ b/disas/ppc.c @@ -5226,7 +5226,7 @@ operand_value_powerpc (const struct powerpc_operand *operand, if ((operand->flags & PPC_OPERAND_SIGNED) != 0) { /* BITM is always some number of zeros followed by some - number of ones, followed by some numer of zeros. */ + number of ones, followed by some number of zeros. */ unsigned long top = operand->bitm; /* top & -top gives the rightmost 1 bit, so this fills in any trailing zeros. */ diff --git a/disas/sh4.c b/disas/sh4.c index 55ef865a36af0e3e44ad051983ac6781c610dcdb..dcdbdf26d8e2175befdc37030c06998848d1ab78 100644 --- a/disas/sh4.c +++ b/disas/sh4.c @@ -1963,6 +1963,7 @@ print_insn_sh (bfd_vma memaddr, struct disassemble_info *info) fprintf_fn (stream, "xd%d", rn & ~1); break; } + /* fallthrough */ case D_REG_N: fprintf_fn (stream, "dr%d", rn); break; @@ -1972,6 +1973,7 @@ print_insn_sh (bfd_vma memaddr, struct disassemble_info *info) fprintf_fn (stream, "xd%d", rm & ~1); break; } + /* fallthrough */ case D_REG_M: fprintf_fn (stream, "dr%d", rm); break; diff --git a/docs/COLO-FT.txt b/docs/COLO-FT.txt index c8e17409356645dd2feea19623e8cfe1b2e5f9e0..bc5fb2a1bb5f4ff76f389d37c433a33d1538a2ba 100644 --- a/docs/COLO-FT.txt +++ b/docs/COLO-FT.txt @@ -91,7 +91,7 @@ the heartbeat stops responding, the secondary node will trigger a failover as soon as it determines the absence. COLO disk Manager: -When primary VM writes data into image, the colo disk manger captures this data +When primary VM writes data into image, the colo disk manager captures this data and sends it to secondary VM's which makes sure the context of secondary VM's image is consistent with the context of primary VM 's image. For more details, please refer to docs/block-replication.txt. @@ -146,12 +146,12 @@ in test procedure. == Test procedure == Note: Here we are running both instances on the same host for testing, -change the IP Addresses if you want to run it on two hosts. Initally +change the IP Addresses if you want to run it on two hosts. Initially 127.0.0.1 is the Primary Host and 127.0.0.2 is the Secondary Host. == Startup qemu == 1. Primary: -Note: Initally, $imagefolder/primary.qcow2 needs to be copied to all hosts. +Note: Initially, $imagefolder/primary.qcow2 needs to be copied to all hosts. You don't need to change any IP's here, because 0.0.0.0 listens on any interface. The chardev's with 127.0.0.1 IP's loopback to the local qemu instance. diff --git a/docs/_templates/editpage.html b/docs/_templates/editpage.html new file mode 100644 index 0000000000000000000000000000000000000000..4319b0f5ac895a4c0b772dc6145cad50d4316f23 --- /dev/null +++ b/docs/_templates/editpage.html @@ -0,0 +1,5 @@ +
+ +
diff --git a/docs/amd-memory-encryption.txt b/docs/amd-memory-encryption.txt index 43bf3ee6a5a9fdd671376505aa9aa1c49557df79..80b8eb00e98093bfe4c758ba32fc75c36505deb6 100644 --- a/docs/amd-memory-encryption.txt +++ b/docs/amd-memory-encryption.txt @@ -95,10 +95,10 @@ References ----------------- AMD Memory Encryption whitepaper: -http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf +https://developer.amd.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf Secure Encrypted Virtualization Key Management: -[1] http://support.amd.com/TechDocs/55766_SEV-KM API_Specification.pdf +[1] http://developer.amd.com/wordpress/media/2017/11/55766_SEV-KM-API_Specification.pdf KVM Forum slides: http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf diff --git a/docs/can.txt b/docs/can.txt index 11ed8f2d68b1c1bc11534ce0cc9eeb64ea6bafa7..0d310237dfaadaed4e69f01295e98b6c9dda527c 100644 --- a/docs/can.txt +++ b/docs/can.txt @@ -8,13 +8,22 @@ can be connected to host system CAN API (at this time only Linux SocketCAN is supported). The concept of busses is generic and different CAN controllers -can be implemented for it but at this time only SJA1000 chip -controller is implemented. +can be implemented. + +The initial submission implemented SJA1000 controller which +is common and well supported by by drivers for the most operating +systems. The PCI addon card hardware has been selected as the first CAN interface to implement because such device can be easily connected to systems with different CPU architectures (x86, PowerPC, Arm, etc.). +In 2020, CTU CAN FD controller model has been added as part +of the bachelor thesis of Jan Charvat. This controller is complete +open-source/design/hardware solution. The core designer +of the project is Ondrej Ille, the financial support has been +provided by CTU, and more companies including Volkswagen subsidiaries. + The project has been initially started in frame of RTEMS GSoC 2013 slot by Jin Yang under our mentoring The initial idea was to provide generic CAN subsystem for RTEMS. But lack of common environment for code and RTEMS @@ -22,8 +31,8 @@ testing lead to goal change to provide environment which provides complete emulated environment for testing and RTEMS GSoC slot has been donated to work on CAN hardware emulation on QEMU. -Examples how to use CAN emulation -================================= +Examples how to use CAN emulation for SJA1000 based boards +========================================================== When QEMU with CAN PCI support is compiled then one of the next CAN boards can be selected @@ -90,18 +99,100 @@ traffic with "candump" command which is included in "can-utils". candump can0 +CTU CAN FD support examples +=========================== + +This open-source core provides CAN FD support. CAN FD drames are +delivered even to the host systems when SocketCAN interface is found +CAN FD capable. + +The PCIe board emulation is provided for now (the device identifier is +ctucan_pci). The default build defines two CTU CAN FD cores +on the board. + +Example how to connect the canbus0-bus (virtual wire) to the host +Linux system (SocketCAN used) and to both CTU CAN FD cores emulated +on the corresponding PCI card expects that host system CAN bus +is setup according to the previous SJA1000 section. + + qemu-system-x86_64 -enable-kvm -kernel /boot/vmlinuz-4.19.52+ \ + -initrd ramdisk.cpio \ + -virtfs local,path=shareddir,security_model=none,mount_tag=shareddir \ + -vga cirrus \ + -append "console=ttyS0" \ + -object can-bus,id=canbus0-bus \ + -object can-host-socketcan,if=can0,canbus=canbus0-bus,id=canbus0-socketcan \ + -device ctucan_pci,canbus0=canbus0-bus,canbus1=canbus0-bus \ + -nographic + +Setup of CTU CAN FD controller in a guest Linux system + + insmod ctucanfd.ko || modprobe ctucanfd + insmod ctucanfd_pci.ko || modprobe ctucanfd_pci + + for ifc in /sys/class/net/can* ; do + if [ -e $ifc/device/vendor ] ; then + if ! grep -q 0x1760 $ifc/device/vendor ; then + continue; + fi + else + continue; + fi + if [ -e $ifc/device/device ] ; then + if ! grep -q 0xff00 $ifc/device/device ; then + continue; + fi + else + continue; + fi + ifc=$(basename $ifc) + /bin/ip link set $ifc type can bitrate 1000000 dbitrate 10000000 fd on + /bin/ip link set $ifc up + done + +The test can run for example + + candump can1 + +in the guest system and next commands in the host system for basic CAN + + cangen can0 + +for CAN FD without bitrate switch + + cangen can0 -f + +and with bitrate switch + + cangen can0 -b + +The test can be run viceversa, generate messages in the guest system and capture them +in the host one and much more combinations. + Links to other resources ======================== - (1) Repository with development branch can-pci at Czech Technical University - https://gitlab.fel.cvut.cz/canbus/qemu-canbus - (2) GitHub repository with can-pci and our other changes included + (1) CAN related projects at Czech Technical University, Faculty of Electrical Engineering + http://canbus.pages.fel.cvut.cz/ + (2) Repository with development can-pci branch at Czech Technical University https://gitlab.fel.cvut.cz/canbus/qemu-canbus (3) RTEMS page describing project https://devel.rtems.org/wiki/Developer/Simulators/QEMU/CANEmulation (4) RTLWS 2015 article about the project and its use with CANopen emulation - http://rtime.felk.cvut.cz/publications/public/rtlws2015-qemu-can.pdf - Slides - http://rtime.felk.cvut.cz/publications/public/rtlws2015-qemu-can-slides.pdf - (5) Linux SocketCAN utilities + http://cmp.felk.cvut.cz/~pisa/can/doc/rtlws-17-pisa-qemu-can.pdf + (5) GNU/Linux, CAN and CANopen in Real-time Control Applications + Slides from LinuxDays 2017 (include updated RTLWS 2015 content) + https://www.linuxdays.cz/2017/video/Pavel_Pisa-CAN_canopen.pdf + (6) Linux SocketCAN utilities https://github.com/linux-can/can-utils/ + (7) CTU CAN FD project including core VHDL design, Linux driver, + test utilities etc. + https://gitlab.fel.cvut.cz/canbus/ctucanfd_ip_core + (8) CTU CAN FD Core Datasheet Documentation + http://canbus.pages.fel.cvut.cz/ctucanfd_ip_core/Progdokum.pdf + (9) CTU CAN FD Core System Architecture Documentation + http://canbus.pages.fel.cvut.cz/ctucanfd_ip_core/ctu_can_fd_architecture.pdf + (10) CTU CAN FD Driver Documentation + http://canbus.pages.fel.cvut.cz/ctucanfd_ip_core/driver_doc/ctucanfd-driver.html + (11) Integration with PCIe interfacing for Intel/Altera Cyclone IV based board + https://gitlab.fel.cvut.cz/canbus/pcie-ctu_can_fd diff --git a/docs/conf.py b/docs/conf.py index d6e173ef77bfb47a4dc7ba3ed55b2074ce317977..d40d8ff37bab430c211a6c7dbfea6b1f3a6cf446 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -36,9 +36,9 @@ # In newer versions of Sphinx this will display nicely; in older versions # Sphinx will also produce a Python backtrace but at least the information # gets printed... -if sys.version_info < (3,5): +if sys.version_info < (3,6): raise ConfigError( - "QEMU requires a Sphinx that uses Python 3.5 or better\n") + "QEMU requires a Sphinx that uses Python 3.6 or better\n") # The per-manual conf.py will set qemu_docdir for a single-manual build; # otherwise set it here if this is an entire-manual-set build. @@ -52,7 +52,10 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use an absolute path starting from qemu_docdir. # +# Our extensions are in docs/sphinx; the qapidoc extension requires +# the QAPI modules from scripts/. sys.path.insert(0, os.path.join(qemu_docdir, "sphinx")) +sys.path.insert(0, os.path.join(qemu_docdir, "../scripts")) # -- General configuration ------------------------------------------------ @@ -67,7 +70,7 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['kerneldoc', 'qmp_lexer', 'hxtool'] +extensions = ['kerneldoc', 'qmp_lexer', 'hxtool', 'depfile', 'qapidoc'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -174,6 +177,7 @@ html_sidebars = { '**': [ 'about.html', + 'editpage.html', 'navigation.html', 'searchbox.html', ] @@ -238,6 +242,7 @@ # We use paths starting from qemu_docdir here so that you can run # sphinx-build from anywhere and the kerneldoc extension can still # find everything. -kerneldoc_bin = os.path.join(qemu_docdir, '../scripts/kernel-doc') +kerneldoc_bin = ['perl', os.path.join(qemu_docdir, '../scripts/kernel-doc')] kerneldoc_srctree = os.path.join(qemu_docdir, '..') hxtool_srctree = os.path.join(qemu_docdir, '..') +qapidoc_srctree = os.path.join(qemu_docdir, '..') diff --git a/docs/devel/_templates/editpage.html b/docs/devel/_templates/editpage.html new file mode 100644 index 0000000000000000000000000000000000000000..a86d22bca8635c2bb8354dc05ce4fbd984589175 --- /dev/null +++ b/docs/devel/_templates/editpage.html @@ -0,0 +1,5 @@ +
+ +
diff --git a/docs/devel/atomics.rst b/docs/devel/atomics.rst index 445c3b35036fcab4c6154f2c65466890ce06476a..52baa0736d2fa0a3358f409e000365366fb97793 100644 --- a/docs/devel/atomics.rst +++ b/docs/devel/atomics.rst @@ -23,9 +23,9 @@ provides macros that fall in three camps: - compiler barriers: ``barrier()``; -- weak atomic access and manual memory barriers: ``atomic_read()``, - ``atomic_set()``, ``smp_rmb()``, ``smp_wmb()``, ``smp_mb()``, ``smp_mb_acquire()``, - ``smp_mb_release()``, ``smp_read_barrier_depends()``; +- weak atomic access and manual memory barriers: ``qatomic_read()``, + ``qatomic_set()``, ``smp_rmb()``, ``smp_wmb()``, ``smp_mb()``, + ``smp_mb_acquire()``, ``smp_mb_release()``, ``smp_read_barrier_depends()``; - sequentially consistent atomic access: everything else. @@ -67,23 +67,23 @@ in the order specified by its program". ``qemu/atomic.h`` provides the following set of atomic read-modify-write operations:: - void atomic_inc(ptr) - void atomic_dec(ptr) - void atomic_add(ptr, val) - void atomic_sub(ptr, val) - void atomic_and(ptr, val) - void atomic_or(ptr, val) - - typeof(*ptr) atomic_fetch_inc(ptr) - typeof(*ptr) atomic_fetch_dec(ptr) - typeof(*ptr) atomic_fetch_add(ptr, val) - typeof(*ptr) atomic_fetch_sub(ptr, val) - typeof(*ptr) atomic_fetch_and(ptr, val) - typeof(*ptr) atomic_fetch_or(ptr, val) - typeof(*ptr) atomic_fetch_xor(ptr, val) - typeof(*ptr) atomic_fetch_inc_nonzero(ptr) - typeof(*ptr) atomic_xchg(ptr, val) - typeof(*ptr) atomic_cmpxchg(ptr, old, new) + void qatomic_inc(ptr) + void qatomic_dec(ptr) + void qatomic_add(ptr, val) + void qatomic_sub(ptr, val) + void qatomic_and(ptr, val) + void qatomic_or(ptr, val) + + typeof(*ptr) qatomic_fetch_inc(ptr) + typeof(*ptr) qatomic_fetch_dec(ptr) + typeof(*ptr) qatomic_fetch_add(ptr, val) + typeof(*ptr) qatomic_fetch_sub(ptr, val) + typeof(*ptr) qatomic_fetch_and(ptr, val) + typeof(*ptr) qatomic_fetch_or(ptr, val) + typeof(*ptr) qatomic_fetch_xor(ptr, val) + typeof(*ptr) qatomic_fetch_inc_nonzero(ptr) + typeof(*ptr) qatomic_xchg(ptr, val) + typeof(*ptr) qatomic_cmpxchg(ptr, old, new) all of which return the old value of ``*ptr``. These operations are polymorphic; they operate on any type that is as wide as a pointer or @@ -91,19 +91,19 @@ smaller. Similar operations return the new value of ``*ptr``:: - typeof(*ptr) atomic_inc_fetch(ptr) - typeof(*ptr) atomic_dec_fetch(ptr) - typeof(*ptr) atomic_add_fetch(ptr, val) - typeof(*ptr) atomic_sub_fetch(ptr, val) - typeof(*ptr) atomic_and_fetch(ptr, val) - typeof(*ptr) atomic_or_fetch(ptr, val) - typeof(*ptr) atomic_xor_fetch(ptr, val) + typeof(*ptr) qatomic_inc_fetch(ptr) + typeof(*ptr) qatomic_dec_fetch(ptr) + typeof(*ptr) qatomic_add_fetch(ptr, val) + typeof(*ptr) qatomic_sub_fetch(ptr, val) + typeof(*ptr) qatomic_and_fetch(ptr, val) + typeof(*ptr) qatomic_or_fetch(ptr, val) + typeof(*ptr) qatomic_xor_fetch(ptr, val) ``qemu/atomic.h`` also provides loads and stores that cannot be reordered with each other:: - typeof(*ptr) atomic_mb_read(ptr) - void atomic_mb_set(ptr, val) + typeof(*ptr) qatomic_mb_read(ptr) + void qatomic_mb_set(ptr, val) However these do not provide sequential consistency and, in particular, they do not participate in the total ordering enforced by @@ -115,11 +115,11 @@ easiest to hardest): - lightweight synchronization primitives such as ``QemuEvent`` -- RCU operations (``atomic_rcu_read``, ``atomic_rcu_set``) when publishing +- RCU operations (``qatomic_rcu_read``, ``qatomic_rcu_set``) when publishing or accessing a new version of a data structure -- other atomic accesses: ``atomic_read`` and ``atomic_load_acquire`` for - loads, ``atomic_set`` and ``atomic_store_release`` for stores, ``smp_mb`` +- other atomic accesses: ``qatomic_read`` and ``qatomic_load_acquire`` for + loads, ``qatomic_set`` and ``qatomic_store_release`` for stores, ``smp_mb`` to forbid reordering subsequent loads before a store. @@ -149,22 +149,22 @@ The only guarantees that you can rely upon in this case are: When using this model, variables are accessed with: -- ``atomic_read()`` and ``atomic_set()``; these prevent the compiler from +- ``qatomic_read()`` and ``qatomic_set()``; these prevent the compiler from optimizing accesses out of existence and creating unsolicited accesses, but do not otherwise impose any ordering on loads and stores: both the compiler and the processor are free to reorder them. -- ``atomic_load_acquire()``, which guarantees the LOAD to appear to +- ``qatomic_load_acquire()``, which guarantees the LOAD to appear to happen, with respect to the other components of the system, before all the LOAD or STORE operations specified afterwards. - Operations coming before ``atomic_load_acquire()`` can still be + Operations coming before ``qatomic_load_acquire()`` can still be reordered after it. -- ``atomic_store_release()``, which guarantees the STORE to appear to +- ``qatomic_store_release()``, which guarantees the STORE to appear to happen, with respect to the other components of the system, after all the LOAD or STORE operations specified before. - Operations coming after ``atomic_store_release()`` can still be + Operations coming after ``qatomic_store_release()`` can still be reordered before it. Restrictions to the ordering of accesses can also be specified @@ -229,7 +229,7 @@ They come in six kinds: dependency and a full read barrier or better is required. -Memory barriers and ``atomic_load_acquire``/``atomic_store_release`` are +Memory barriers and ``qatomic_load_acquire``/``qatomic_store_release`` are mostly used when a data structure has one thread that is always a writer and one thread that is always a reader: @@ -238,8 +238,8 @@ and one thread that is always a reader: +==================================+==================================+ | :: | :: | | | | - | atomic_store_release(&a, x); | y = atomic_load_acquire(&b); | - | atomic_store_release(&b, y); | x = atomic_load_acquire(&a); | + | qatomic_store_release(&a, x); | y = qatomic_load_acquire(&b); | + | qatomic_store_release(&b, y); | x = qatomic_load_acquire(&a); | +----------------------------------+----------------------------------+ In this case, correctness is easy to check for using the "pairing" @@ -258,14 +258,14 @@ outside a loop. For example: | | | | n = 0; | n = 0; | | for (i = 0; i < 10; i++) | for (i = 0; i < 10; i++) | - | n += atomic_load_acquire(&a[i]); | n += atomic_read(&a[i]); | + | n += qatomic_load_acquire(&a[i]); | n += qatomic_read(&a[i]); | | | smp_mb_acquire(); | +------------------------------------------+----------------------------------+ | :: | :: | | | | | | smp_mb_release(); | | for (i = 0; i < 10; i++) | for (i = 0; i < 10; i++) | - | atomic_store_release(&a[i], false); | atomic_set(&a[i], false); | + | qatomic_store_release(&a[i], false); | qatomic_set(&a[i], false); | +------------------------------------------+----------------------------------+ Splitting a loop can also be useful to reduce the number of barriers: @@ -277,11 +277,11 @@ Splitting a loop can also be useful to reduce the number of barriers: | | | | n = 0; | smp_mb_release(); | | for (i = 0; i < 10; i++) { | for (i = 0; i < 10; i++) | - | atomic_store_release(&a[i], false); | atomic_set(&a[i], false); | + | qatomic_store_release(&a[i], false); | qatomic_set(&a[i], false); | | smp_mb(); | smb_mb(); | - | n += atomic_read(&b[i]); | n = 0; | + | n += qatomic_read(&b[i]); | n = 0; | | } | for (i = 0; i < 10; i++) | - | | n += atomic_read(&b[i]); | + | | n += qatomic_read(&b[i]); | +------------------------------------------+----------------------------------+ In this case, a ``smp_mb_release()`` is also replaced with a (possibly cheaper, and clearer @@ -294,10 +294,10 @@ as well) ``smp_wmb()``: | | | | | smp_mb_release(); | | for (i = 0; i < 10; i++) { | for (i = 0; i < 10; i++) | - | atomic_store_release(&a[i], false); | atomic_set(&a[i], false); | - | atomic_store_release(&b[i], false); | smb_wmb(); | + | qatomic_store_release(&a[i], false); | qatomic_set(&a[i], false); | + | qatomic_store_release(&b[i], false); | smb_wmb(); | | } | for (i = 0; i < 10; i++) | - | | atomic_set(&b[i], false); | + | | qatomic_set(&b[i], false); | +------------------------------------------+----------------------------------+ @@ -306,7 +306,7 @@ as well) ``smp_wmb()``: Acquire/release pairing and the *synchronizes-with* relation ------------------------------------------------------------ -Atomic operations other than ``atomic_set()`` and ``atomic_read()`` have +Atomic operations other than ``qatomic_set()`` and ``qatomic_read()`` have either *acquire* or *release* semantics [#rmw]_. This has two effects: .. [#rmw] Read-modify-write operations can have both---acquire applies to the @@ -357,16 +357,16 @@ thread 2 is relying on the *synchronizes-with* relation between ``pthread_exit`` Synchronization between threads basically descends from this pairing of a release operation and an acquire operation. Therefore, atomic operations -other than ``atomic_set()`` and ``atomic_read()`` will almost always be +other than ``qatomic_set()`` and ``qatomic_read()`` will almost always be paired with another operation of the opposite kind: an acquire operation will pair with a release operation and vice versa. This rule of thumb is extremely useful; in the case of QEMU, however, note that the other operation may actually be in a driver that runs in the guest! ``smp_read_barrier_depends()``, ``smp_rmb()``, ``smp_mb_acquire()``, -``atomic_load_acquire()`` and ``atomic_rcu_read()`` all count +``qatomic_load_acquire()`` and ``qatomic_rcu_read()`` all count as acquire operations. ``smp_wmb()``, ``smp_mb_release()``, -``atomic_store_release()`` and ``atomic_rcu_set()`` all count as release +``qatomic_store_release()`` and ``qatomic_rcu_set()`` all count as release operations. ``smp_mb()`` counts as both acquire and release, therefore it can pair with any other atomic operation. Here is an example: @@ -375,11 +375,11 @@ it can pair with any other atomic operation. Here is an example: +======================+==============================+ | :: | :: | | | | - | atomic_set(&a, 1); | | + | qatomic_set(&a, 1);| | | smp_wmb(); | | - | atomic_set(&b, 2); | x = atomic_read(&b); | + | qatomic_set(&b, 2);| x = qatomic_read(&b); | | | smp_rmb(); | - | | y = atomic_read(&a); | + | | y = qatomic_read(&a); | +----------------------+------------------------------+ Note that a load-store pair only counts if the two operations access the @@ -393,9 +393,9 @@ correct synchronization: +================================+================================+ | :: | :: | | | | - | atomic_set(&a, 1); | | - | atomic_store_release(&b, 2); | x = atomic_load_acquire(&b); | - | | y = atomic_read(&a); | + | qatomic_set(&a, 1); | | + | qatomic_store_release(&b, 2);| x = qatomic_load_acquire(&b);| + | | y = qatomic_read(&a); | +--------------------------------+--------------------------------+ Acquire and release semantics of higher-level primitives can also be @@ -421,7 +421,7 @@ cannot be a data race: | smp_wmb(); | | | x->i = 2; | | | smp_wmb(); | | - | atomic_set(&a, x); | x = atomic_read(&a); | + | qatomic_set(&a, x);| x = qatomic_read(&a); | | | smp_read_barrier_depends(); | | | y = x->i; | | | smp_read_barrier_depends(); | @@ -442,7 +442,7 @@ and memory barriers, and the equivalents in QEMU: at all. Linux 4.1 updated them to implement volatile semantics via ``ACCESS_ONCE`` (or the more recent ``READ``/``WRITE_ONCE``). - QEMU's ``atomic_read`` and ``atomic_set`` implement C11 atomic relaxed + QEMU's ``qatomic_read`` and ``qatomic_set`` implement C11 atomic relaxed semantics if the compiler supports it, and volatile semantics otherwise. Both semantics prevent the compiler from doing certain transformations; the difference is that atomic accesses are guaranteed to be atomic, @@ -451,8 +451,8 @@ and memory barriers, and the equivalents in QEMU: since we assume the variables passed are machine-word sized and properly aligned. - No barriers are implied by ``atomic_read`` and ``atomic_set`` in either Linux - or QEMU. + No barriers are implied by ``qatomic_read`` and ``qatomic_set`` in either + Linux or QEMU. - atomic read-modify-write operations in Linux are of three kinds: @@ -469,7 +469,7 @@ and memory barriers, and the equivalents in QEMU: a different set of memory barriers; in QEMU, all of them enforce sequential consistency. -- in QEMU, ``atomic_read()`` and ``atomic_set()`` do not participate in +- in QEMU, ``qatomic_read()`` and ``qatomic_set()`` do not participate in the total ordering enforced by sequentially-consistent operations. This is because QEMU uses the C11 memory model. The following example is correct in Linux but not in QEMU: @@ -479,8 +479,8 @@ and memory barriers, and the equivalents in QEMU: +==================================+================================+ | :: | :: | | | | - | a = atomic_fetch_add(&x, 2); | a = atomic_fetch_add(&x, 2); | - | b = READ_ONCE(&y); | b = atomic_read(&y); | + | a = atomic_fetch_add(&x, 2); | a = qatomic_fetch_add(&x, 2);| + | b = READ_ONCE(&y); | b = qatomic_read(&y); | +----------------------------------+--------------------------------+ because the read of ``y`` can be moved (by either the processor or the @@ -495,10 +495,10 @@ and memory barriers, and the equivalents in QEMU: +================================+ | :: | | | - | a = atomic_read(&x); | - | atomic_set(&x, a + 2); | + | a = qatomic_read(&x); | + | qatomic_set(&x, a + 2); | | smp_mb(); | - | b = atomic_read(&y); | + | b = qatomic_read(&y); | +--------------------------------+ Sources diff --git a/docs/devel/blkdebug.txt b/docs/devel/blkdebug.txt index 43d8e8f9c63ba32d9a44fc25135d22790e607f2c..0b0c128d356bec222f05e73ccfb3f58dc1d18a71 100644 --- a/docs/devel/blkdebug.txt +++ b/docs/devel/blkdebug.txt @@ -62,7 +62,7 @@ Rules support the following attributes: errno - the numeric errno value to return when a request matches this rule. The errno values depend on the host since the numeric values are not - standarized in the POSIX specification. + standardized in the POSIX specification. sector - (optional) a sector number that the request must overlap in order to match this rule diff --git a/docs/devel/blkverify.txt b/docs/devel/blkverify.txt index d556dc4e6d09f7aef059e568f1987a0ca762f30f..aca826c51cc98fda2323875f5f54a279f9b26902 100644 --- a/docs/devel/blkverify.txt +++ b/docs/devel/blkverify.txt @@ -62,8 +62,8 @@ A more realistic scenario is verifying the installation of a guest OS: $ ./qemu-img create raw.img 16G $ ./qemu-img create -f qcow2 test.qcow2 16G - $ x86_64-softmmu/qemu-system-x86_64 -cdrom debian.iso \ - -drive file=blkverify:raw.img:test.qcow2 + $ ./qemu-system-x86_64 -cdrom debian.iso \ + -drive file=blkverify:raw.img:test.qcow2 If the installation is aborted when blkverify detects corruption, use qemu-io to explore the contents of the disk image at the sector in question. diff --git a/docs/devel/block-coroutine-wrapper.rst b/docs/devel/block-coroutine-wrapper.rst new file mode 100644 index 0000000000000000000000000000000000000000..412851986b1a045453ab864afd5a84d647cac944 --- /dev/null +++ b/docs/devel/block-coroutine-wrapper.rst @@ -0,0 +1,54 @@ +======================= +block-coroutine-wrapper +======================= + +A lot of functions in QEMU block layer (see ``block/*``) can only be +called in coroutine context. Such functions are normally marked by the +coroutine_fn specifier. Still, sometimes we need to call them from +non-coroutine context; for this we need to start a coroutine, run the +needed function from it and wait for the coroutine to finish in a +BDRV_POLL_WHILE() loop. To run a coroutine we need a function with one +void* argument. So for each coroutine_fn function which needs a +non-coroutine interface, we should define a structure to pack the +parameters, define a separate function to unpack the parameters and +call the original function and finally define a new interface function +with same list of arguments as original one, which will pack the +parameters into a struct, create a coroutine, run it and wait in +BDRV_POLL_WHILE() loop. It's boring to create such wrappers by hand, +so we have a script to generate them. + +Usage +===== + +Assume we have defined the ``coroutine_fn`` function +``bdrv_co_foo()`` and need a non-coroutine interface for it, +called ``bdrv_foo()``. In this case the script can help. To +trigger the generation: + +1. You need ``bdrv_foo`` declaration somewhere (for example, in + ``block/coroutines.h``) with the ``generated_co_wrapper`` mark, + like this: + +.. code-block:: c + + int generated_co_wrapper bdrv_foo(); + +2. You need to feed this declaration to block-coroutine-wrapper script. + For this, add the .h (or .c) file with the declaration to the + ``input: files(...)`` list of ``block_gen_c`` target declaration in + ``block/meson.build`` + +You are done. During the build, coroutine wrappers will be generated in +``/block/block-gen.c``. + +Links +===== + +1. The script location is ``scripts/block-coroutine-wrapper.py``. + +2. Generic place for private ``generated_co_wrapper`` declarations is + ``block/coroutines.h``, for public declarations: + ``include/block/block.h`` + +3. The core API of generated coroutine wrappers is placed in + (not generated) ``block/block-gen.h`` diff --git a/docs/devel/build-system.rst b/docs/devel/build-system.rst new file mode 100644 index 0000000000000000000000000000000000000000..31f4dced2a080322b5fdf268371840e492b298c1 --- /dev/null +++ b/docs/devel/build-system.rst @@ -0,0 +1,477 @@ +================================== +The QEMU build system architecture +================================== + +This document aims to help developers understand the architecture of the +QEMU build system. As with projects using GNU autotools, the QEMU build +system has two stages, first the developer runs the "configure" script +to determine the local build environment characteristics, then they run +"make" to build the project. There is about where the similarities with +GNU autotools end, so try to forget what you know about them. + + +Stage 1: configure +================== + +The QEMU configure script is written directly in shell, and should be +compatible with any POSIX shell, hence it uses #!/bin/sh. An important +implication of this is that it is important to avoid using bash-isms on +development platforms where bash is the primary host. + +In contrast to autoconf scripts, QEMU's configure is expected to be +silent while it is checking for features. It will only display output +when an error occurs, or to show the final feature enablement summary +on completion. + +Because QEMU uses the Meson build system under the hood, only VPATH +builds are supported. There are two general ways to invoke configure & +perform a build: + + - VPATH, build artifacts outside of QEMU source tree entirely:: + + cd ../ + mkdir build + cd build + ../qemu/configure + make + + - VPATH, build artifacts in a subdir of QEMU source tree:: + + mkdir build + cd build + ../configure + make + +For now, checks on the compilation environment are found in configure +rather than meson.build, though this is expected to change. The command +line is parsed in the configure script and, whenever needed, converted +into the appropriate options to Meson. + +New checks should be added to Meson, which usually comprises the +following tasks: + + - Add a Meson build option to meson_options.txt. + + - Add support to the command line arg parser to handle any new + `--enable-XXX`/`--disable-XXX` flags required by the feature. + + - Add information to the help output message to report on the new + feature flag. + + - Add code to perform the actual feature check. + + - Add code to include the feature status in `config-host.h` + + - Add code to print out the feature status in the configure summary + upon completion. + + +Taking the probe for SDL2_Image as an example, we have the following pieces +in configure:: + + # Initial variable state + sdl_image=auto + + ..snip.. + + # Configure flag processing + --disable-sdl-image) sdl_image=disabled + ;; + --enable-sdl-image) sdl_image=enabled + ;; + + ..snip.. + + # Help output feature message + sdl-image SDL Image support for icons + + ..snip.. + + # Meson invocation + -Dsdl_image=$sdl_image + +In meson_options.txt:: + + option('sdl', type : 'feature', value : 'auto', + description: 'SDL Image support for icons') + +In meson.build:: + + # Detect dependency + sdl_image = dependency('SDL2_image', required: get_option('sdl_image'), + method: 'pkg-config', + static: enable_static) + + # Create config-host.h (if applicable) + config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found()) + + # Summary + summary_info += {'SDL image support': sdl_image.found()} + + + +Helper functions +---------------- + +The configure script provides a variety of helper functions to assist +developers in checking for system features: + +`do_cc $ARGS...` + Attempt to run the system C compiler passing it $ARGS... + +`do_cxx $ARGS...` + Attempt to run the system C++ compiler passing it $ARGS... + +`compile_object $CFLAGS` + Attempt to compile a test program with the system C compiler using + $CFLAGS. The test program must have been previously written to a file + called $TMPC. The replacement in Meson is the compiler object `cc`, + which has methods such as `cc.compiles()`, + `cc.check_header()`, `cc.has_function()`. + +`compile_prog $CFLAGS $LDFLAGS` + Attempt to compile a test program with the system C compiler using + $CFLAGS and link it with the system linker using $LDFLAGS. The test + program must have been previously written to a file called $TMPC. + The replacement in Meson is `cc.find_library()` and `cc.links()`. + +`has $COMMAND` + Determine if $COMMAND exists in the current environment, either as a + shell builtin, or executable binary, returning 0 on success. The + replacement in Meson is `find_program()`. + +`check_define $NAME` + Determine if the macro $NAME is defined by the system C compiler + +`check_include $NAME` + Determine if the include $NAME file is available to the system C + compiler. The replacement in Meson is `cc.has_header()`. + +`write_c_skeleton` + Write a minimal C program main() function to the temporary file + indicated by $TMPC + +`feature_not_found $NAME $REMEDY` + Print a message to stderr that the feature $NAME was not available + on the system, suggesting the user try $REMEDY to address the + problem. + +`error_exit $MESSAGE $MORE...` + Print $MESSAGE to stderr, followed by $MORE... and then exit from the + configure script with non-zero status + +`query_pkg_config $ARGS...` + Run pkg-config passing it $ARGS. If QEMU is doing a static build, + then --static will be automatically added to $ARGS + + +Stage 2: Meson +============== + +The Meson build system is currently used to describe the build +process for: + +1) executables, which include: + + - Tools - qemu-img, qemu-nbd, qga (guest agent), etc + + - System emulators - qemu-system-$ARCH + + - Userspace emulators - qemu-$ARCH + + - Unit tests + +2) documentation + +3) ROMs, which can be either installed as binary blobs or compiled + +4) other data files, such as icons or desktop files + +All executables are built by default, except for some `contrib/` +binaries that are known to fail to build on some platforms (for example +32-bit or big-endian platforms). Tests are also built by default, +though that might change in the future. + +The source code is highly modularized, split across many files to +facilitate building of all of these components with as little duplicated +compilation as possible. Using the Meson "sourceset" functionality, +`meson.build` files group the source files in rules that are +enabled according to the available system libraries and to various +configuration symbols. Sourcesets belong to one of four groups: + +Subsystem sourcesets: + Various subsystems that are common to both tools and emulators have + their own sourceset, for example `block_ss` for the block device subsystem, + `chardev_ss` for the character device subsystem, etc. These sourcesets + are then turned into static libraries as follows:: + + libchardev = static_library('chardev', chardev_ss.sources(), + name_suffix: 'fa', + build_by_default: false) + + chardev = declare_dependency(link_whole: libchardev) + + As of Meson 0.55.1, the special `.fa` suffix should be used for everything + that is used with `link_whole`, to ensure that the link flags are placed + correctly in the command line. + +Target-independent emulator sourcesets: + Various general purpose helper code is compiled only once and + the .o files are linked into all output binaries that need it. + This includes error handling infrastructure, standard data structures, + platform portability wrapper functions, etc. + + Target-independent code lives in the `common_ss`, `softmmu_ss` and + `user_ss` sourcesets. `common_ss` is linked into all emulators, + `softmmu_ss` only in system emulators, `user_ss` only in user-mode + emulators. + + Target-independent sourcesets must exercise particular care when using + `if_false` rules. The `if_false` rule will be used correctly when linking + emulator binaries; however, when *compiling* target-independent files + into .o files, Meson may need to pick *both* the `if_true` and + `if_false` sides to cater for targets that want either side. To + achieve that, you can add a special rule using the ``CONFIG_ALL`` + symbol:: + + # Some targets have CONFIG_ACPI, some don't, so this is not enough + softmmu_ss.add(when: 'CONFIG_ACPI`, if_true: files('acpi.c'), + if_false: files('acpi-stub.c')) + + # This is required as well: + softmmu_ss.add(when: 'CONFIG_ALL`, if_true: files('acpi-stub.c')) + +Target-dependent emulator sourcesets: + In the target-dependent set lives CPU emulation, some device emulation and + much glue code. This sometimes also has to be compiled multiple times, + once for each target being built. Target-dependent files are included + in the `specific_ss` sourceset. + + Each emulator also includes sources for files in the `hw/` and `target/` + subdirectories. The subdirectory used for each emulator comes + from the target's definition of ``TARGET_BASE_ARCH`` or (if missing) + ``TARGET_ARCH``, as found in `default-configs/targets/*.mak`. + + Each subdirectory in `hw/` adds one sourceset to the `hw_arch` dictionary, + for example:: + + arm_ss = ss.source_set() + arm_ss.add(files('boot.c'), fdt) + ... + hw_arch += {'arm': arm_ss} + + The sourceset is only used for system emulators. + + Each subdirectory in `target/` instead should add one sourceset to each + of the `target_arch` and `target_softmmu_arch`, which are used respectively + for all emulators and for system emulators only. For example:: + + arm_ss = ss.source_set() + arm_softmmu_ss = ss.source_set() + ... + target_arch += {'arm': arm_ss} + target_softmmu_arch += {'arm': arm_softmmu_ss} + +Utility sourcesets: + All binaries link with a static library `libqemuutil.a`. This library + is built from several sourcesets; most of them however host generated + code, and the only two of general interest are `util_ss` and `stub_ss`. + + The separation between these two is purely for documentation purposes. + `util_ss` contains generic utility files. Even though this code is only + linked in some binaries, sometimes it requires hooks only in some of + these and depend on other functions that are not fully implemented by + all QEMU binaries. `stub_ss` links dummy stubs that will only be linked + into the binary if the real implementation is not present. In a way, + the stubs can be thought of as a portable implementation of the weak + symbols concept. + + +The following files concur in the definition of which files are linked +into each emulator: + +`default-configs/devices/*.mak` + The files under `default-configs/devices/` control the boards and devices + that are built into each QEMU system emulation targets. They merely contain + a list of config variable definitions such as:: + + include arm-softmmu.mak + CONFIG_XLNX_ZYNQMP_ARM=y + CONFIG_XLNX_VERSAL=y + +`*/Kconfig` + These files are processed together with `default-configs/devices/*.mak` and + describe the dependencies between various features, subsystems and + device models. They are described in :ref:`kconfig` + +`default-configs/targets/*.mak` + These files mostly define symbols that appear in the `*-config-target.h` + file for each emulator [#cfgtarget]_. However, the ``TARGET_ARCH`` + and ``TARGET_BASE_ARCH`` will also be used to select the `hw/` and + `target/` subdirectories that are compiled into each target. + +.. [#cfgtarget] This header is included by `qemu/osdep.h` when + compiling files from the target-specific sourcesets. + +These files rarely need changing unless you are adding a completely +new target, or enabling new devices or hardware for a particular +system/userspace emulation target + + +Support scripts +--------------- + +Meson has a special convention for invoking Python scripts: if their +first line is `#! /usr/bin/env python3` and the file is *not* executable, +find_program() arranges to invoke the script under the same Python +interpreter that was used to invoke Meson. This is the most common +and preferred way to invoke support scripts from Meson build files, +because it automatically uses the value of configure's --python= option. + +In case the script is not written in Python, use a `#! /usr/bin/env ...` +line and make the script executable. + +Scripts written in Python, where it is desirable to make the script +executable (for example for test scripts that developers may want to +invoke from the command line, such as tests/qapi-schema/test-qapi.py), +should be invoked through the `python` variable in meson.build. For +example:: + + test('QAPI schema regression tests', python, + args: files('test-qapi.py'), + env: test_env, suite: ['qapi-schema', 'qapi-frontend']) + +This is needed to obey the --python= option passed to the configure +script, which may point to something other than the first python3 +binary on the path. + + +Stage 3: makefiles +================== + +The use of GNU make is required with the QEMU build system. + +The output of Meson is a build.ninja file, which is used with the Ninja +build system. QEMU uses a different approach, where Makefile rules are +synthesized from the build.ninja file. The main Makefile includes these +rules and wraps them so that e.g. submodules are built before QEMU. +The resulting build system is largely non-recursive in nature, in +contrast to common practices seen with automake. + +Tests are also ran by the Makefile with the traditional `make check` +phony target, while benchmarks are run with `make bench`. Meson test +suites such as `unit` can be ran with `make check-unit` too. It is also +possible to run tests defined in meson.build with `meson test`. + +Important files for the build system +==================================== + +Statically defined files +------------------------ + +The following key files are statically defined in the source tree, with +the rules needed to build QEMU. Their behaviour is influenced by a +number of dynamically created files listed later. + +`Makefile` + The main entry point used when invoking make to build all the components + of QEMU. The default 'all' target will naturally result in the build of + every component. Makefile takes care of recursively building submodules + directly via a non-recursive set of rules. + +`*/meson.build` + The meson.build file in the root directory is the main entry point for the + Meson build system, and it coordinates the configuration and build of all + executables. Build rules for various subdirectories are included in + other meson.build files spread throughout the QEMU source tree. + +`tests/Makefile.include` + Rules for external test harnesses. These include the TCG tests, + `qemu-iotests` and the Avocado-based acceptance tests. + +`tests/docker/Makefile.include` + Rules for Docker tests. Like tests/Makefile, this file is included + directly by the top level Makefile, anything defined in this file will + influence the entire build system. + +`tests/vm/Makefile.include` + Rules for VM-based tests. Like tests/Makefile, this file is included + directly by the top level Makefile, anything defined in this file will + influence the entire build system. + +Dynamically created files +------------------------- + +The following files are generated dynamically by configure in order to +control the behaviour of the statically defined makefiles. This avoids +the need for QEMU makefiles to go through any pre-processing as seen +with autotools, where Makefile.am generates Makefile.in which generates +Makefile. + +Built by configure: + +`config-host.mak` + When configure has determined the characteristics of the build host it + will write a long list of variables to config-host.mak file. This + provides the various install directories, compiler / linker flags and a + variety of `CONFIG_*` variables related to optionally enabled features. + This is imported by the top level Makefile and meson.build in order to + tailor the build output. + + config-host.mak is also used as a dependency checking mechanism. If make + sees that the modification timestamp on configure is newer than that on + config-host.mak, then configure will be re-run. + + The variables defined here are those which are applicable to all QEMU + build outputs. Variables which are potentially different for each + emulator target are defined by the next file... + +`$TARGET-NAME/config-target.mak` + TARGET-NAME is the name of a system or userspace emulator, for example, + x86_64-softmmu denotes the system emulator for the x86_64 architecture. + This file contains the variables which need to vary on a per-target + basis. For example, it will indicate whether KVM or Xen are enabled for + the target and any other potential custom libraries needed for linking + the target. + + +Built by Meson: + +`${TARGET-NAME}-config-devices.mak` + TARGET-NAME is again the name of a system or userspace emulator. The + config-devices.mak file is automatically generated by make using the + scripts/make_device_config.sh program, feeding it the + default-configs/$TARGET-NAME file as input. + +`config-host.h`, `$TARGET-NAME/config-target.h`, `$TARGET-NAME/config-devices.h` + These files are used by source code to determine what features + are enabled. They are generated from the contents of the corresponding + `*.h` files using the scripts/create_config program. This extracts + relevant variables and formats them as C preprocessor macros. + +`build.ninja` + The build rules. + + +Built by Makefile: + +`Makefile.ninja` + A Makefile include that bridges to ninja for the actual build. The + Makefile is mostly a list of targets that Meson included in build.ninja. + +`Makefile.mtest` + The Makefile definitions that let "make check" run tests defined in + meson.build. The rules are produced from Meson's JSON description of + tests (obtained with "meson introspect --tests") through the script + scripts/mtest2make.py. + + +Useful make targets +------------------- + +`help` + Print a help message for the most common build targets. + +`print-VAR` + Print the value of the variable VAR. Useful for debugging the build + system. diff --git a/docs/devel/build-system.txt b/docs/devel/build-system.txt deleted file mode 100644 index 41bd08ea3ab381d1671da7c0c3dd50ff766cab16..0000000000000000000000000000000000000000 --- a/docs/devel/build-system.txt +++ /dev/null @@ -1,519 +0,0 @@ - The QEMU build system architecture - ================================== - -This document aims to help developers understand the architecture of the -QEMU build system. As with projects using GNU autotools, the QEMU build -system has two stages, first the developer runs the "configure" script -to determine the local build environment characteristics, then they run -"make" to build the project. There is about where the similarities with -GNU autotools end, so try to forget what you know about them. - - -Stage 1: configure -================== - -The QEMU configure script is written directly in shell, and should be -compatible with any POSIX shell, hence it uses #!/bin/sh. An important -implication of this is that it is important to avoid using bash-isms on -development platforms where bash is the primary host. - -In contrast to autoconf scripts, QEMU's configure is expected to be -silent while it is checking for features. It will only display output -when an error occurs, or to show the final feature enablement summary -on completion. - -Adding new checks to the configure script usually comprises the -following tasks: - - - Initialize one or more variables with the default feature state. - - Ideally features should auto-detect whether they are present, - so try to avoid hardcoding the initial state to either enabled - or disabled, as that forces the user to pass a --enable-XXX - / --disable-XXX flag on every invocation of configure. - - - Add support to the command line arg parser to handle any new - --enable-XXX / --disable-XXX flags required by the feature XXX. - - - Add information to the help output message to report on the new - feature flag. - - - Add code to perform the actual feature check. As noted above, try to - be fully dynamic in checking enablement/disablement. - - - Add code to print out the feature status in the configure summary - upon completion. - - - Add any new makefile variables to $config_host_mak on completion. - - -Taking (a simplified version of) the probe for gnutls from configure, -we have the following pieces: - - # Initial variable state - gnutls="" - - ..snip.. - - # Configure flag processing - --disable-gnutls) gnutls="no" - ;; - --enable-gnutls) gnutls="yes" - ;; - - ..snip.. - - # Help output feature message - gnutls GNUTLS cryptography support - - ..snip.. - - # Test for gnutls - if test "$gnutls" != "no"; then - if ! $pkg_config --exists "gnutls"; then - gnutls_cflags=`$pkg_config --cflags gnutls` - gnutls_libs=`$pkg_config --libs gnutls` - libs_softmmu="$gnutls_libs $libs_softmmu" - libs_tools="$gnutls_libs $libs_tools" - QEMU_CFLAGS="$QEMU_CFLAGS $gnutls_cflags" - gnutls="yes" - elif test "$gnutls" = "yes"; then - feature_not_found "gnutls" "Install gnutls devel" - else - gnutls="no" - fi - fi - - ..snip.. - - # Completion feature summary - echo "GNUTLS support $gnutls" - - ..snip.. - - # Define make variables - if test "$gnutls" = "yes" ; then - echo "CONFIG_GNUTLS=y" >> $config_host_mak - fi - - -Helper functions ----------------- - -The configure script provides a variety of helper functions to assist -developers in checking for system features: - - - do_cc $ARGS... - - Attempt to run the system C compiler passing it $ARGS... - - - do_cxx $ARGS... - - Attempt to run the system C++ compiler passing it $ARGS... - - - compile_object $CFLAGS - - Attempt to compile a test program with the system C compiler using - $CFLAGS. The test program must have been previously written to a file - called $TMPC. - - - compile_prog $CFLAGS $LDFLAGS - - Attempt to compile a test program with the system C compiler using - $CFLAGS and link it with the system linker using $LDFLAGS. The test - program must have been previously written to a file called $TMPC. - - - has $COMMAND - - Determine if $COMMAND exists in the current environment, either as a - shell builtin, or executable binary, returning 0 on success. - - - path_of $COMMAND - - Return the fully qualified path of $COMMAND, printing it to stdout, - and returning 0 on success. - - - check_define $NAME - - Determine if the macro $NAME is defined by the system C compiler - - - check_include $NAME - - Determine if the include $NAME file is available to the system C - compiler - - - write_c_skeleton - - Write a minimal C program main() function to the temporary file - indicated by $TMPC - - - feature_not_found $NAME $REMEDY - - Print a message to stderr that the feature $NAME was not available - on the system, suggesting the user try $REMEDY to address the - problem. - - - error_exit $MESSAGE $MORE... - - Print $MESSAGE to stderr, followed by $MORE... and then exit from the - configure script with non-zero status - - - query_pkg_config $ARGS... - - Run pkg-config passing it $ARGS. If QEMU is doing a static build, - then --static will be automatically added to $ARGS - - -Stage 2: makefiles -================== - -The use of GNU make is required with the QEMU build system. - -Although the source code is spread across multiple subdirectories, the -build system should be considered largely non-recursive in nature, in -contrast to common practices seen with automake. There is some recursive -invocation of make, but this is related to the things being built, -rather than the source directory structure. - -QEMU currently supports both VPATH and non-VPATH builds, so there are -three general ways to invoke configure & perform a build. - - - VPATH, build artifacts outside of QEMU source tree entirely - - cd ../ - mkdir build - cd build - ../qemu/configure - make - - - VPATH, build artifacts in a subdir of QEMU source tree - - mkdir build - cd build - ../configure - make - - - non-VPATH, build artifacts everywhere - - ./configure - make - -The QEMU maintainers generally recommend that a VPATH build is used by -developers. Patches to QEMU are expected to ensure VPATH build still -works. - - -Module structure ----------------- - -There are a number of key outputs of the QEMU build system: - - - Tools - qemu-img, qemu-nbd, qga (guest agent), etc - - System emulators - qemu-system-$ARCH - - Userspace emulators - qemu-$ARCH - - Unit tests - -The source code is highly modularized, split across many files to -facilitate building of all of these components with as little duplicated -compilation as possible. There can be considered to be two distinct -groups of files, those which are independent of the QEMU emulation -target and those which are dependent on the QEMU emulation target. - -In the target-independent set lives various general purpose helper code, -such as error handling infrastructure, standard data structures, -platform portability wrapper functions, etc. This code can be compiled -once only and the .o files linked into all output binaries. - -In the target-dependent set lives CPU emulation, device emulation and -much glue code. This sometimes also has to be compiled multiple times, -once for each target being built. - -The utility code that is used by all binaries is built into a -static archive called libqemuutil.a, which is then linked to all the -binaries. In order to provide hooks that are only needed by some of the -binaries, code in libqemuutil.a may depend on other functions that are -not fully implemented by all QEMU binaries. Dummy stubs for all these -functions are also provided by this library, and will only be linked -into the binary if the real implementation is not present. In a way, -the stubs can be thought of as a portable implementation of the weak -symbols concept. - -All binaries should link to libqemuutil.a, e.g.: - - qemu-img$(EXESUF): qemu-img.o ..snip.. libqemuutil.a - - -Windows platform portability ----------------------------- - -On Windows, all binaries have the suffix '.exe', so all Makefile rules -which create binaries must include the $(EXESUF) variable on the binary -name. e.g. - - qemu-img$(EXESUF): qemu-img.o ..snip.. - -This expands to '.exe' on Windows, or '' on other platforms. - -A further complication for the system emulator binaries is that -two separate binaries need to be generated. - -The main binary (e.g. qemu-system-x86_64.exe) is linked against the -Windows console runtime subsystem. These are expected to be run from a -command prompt window, and so will print stderr to the console that -launched them. - -The second binary generated has a 'w' on the end of its name (e.g. -qemu-system-x86_64w.exe) and is linked against the Windows graphical -runtime subsystem. These are expected to be run directly from the -desktop and will open up a dedicated console window for stderr output. - -The Makefile.target will generate the binary for the graphical subsystem -first, and then use objcopy to relink it against the console subsystem -to generate the second binary. - - -Object variable naming ----------------------- - -The QEMU convention is to define variables to list different groups of -object files. These are named with the convention $PREFIX-obj-y. For -example the libqemuutil.a file will be linked with all objects listed -in a variable 'util-obj-y'. So, for example, util/Makefile.obj will -contain a set of definitions looking like - - util-obj-y += bitmap.o bitops.o hbitmap.o - util-obj-y += fifo8.o - util-obj-y += acl.o - util-obj-y += error.o qemu-error.o - -When there is an object file which needs to be conditionally built based -on some characteristic of the host system, the configure script will -define a variable for the conditional. For example, on Windows it will -define $(CONFIG_POSIX) with a value of 'n' and $(CONFIG_WIN32) with a -value of 'y'. It is now possible to use the config variables when -listing object files. For example, - - util-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o - util-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o - -On Windows this expands to - - util-obj-y += oslib-win32.o qemu-thread-win32.o - util-obj-n += oslib-posix.o qemu-thread-posix.o - -Since libqemutil.a links in $(util-obj-y), the POSIX specific files -listed against $(util-obj-n) are ignored on the Windows platform builds. - - -CFLAGS / LDFLAGS / LIBS handling --------------------------------- - -There are many different binaries being built with differing purposes, -and some of them might even be 3rd party libraries pulled in via git -submodules. As such the use of the global CFLAGS variable is generally -avoided in QEMU, since it would apply to too many build targets. - -Flags that are needed by any QEMU code (i.e. everything *except* GIT -submodule projects) are put in $(QEMU_CFLAGS) variable. For linker -flags the $(LIBS) variable is sometimes used, but a couple of more -targeted variables are preferred. $(libs_softmmu) is used for -libraries that must be linked to system emulator targets, $(LIBS_TOOLS) -is used for tools like qemu-img, qemu-nbd, etc and $(LIBS_QGA) is used -for the QEMU guest agent. There is currently no specific variable for -the userspace emulator targets as the global $(LIBS), or more targeted -variables shown below, are sufficient. - -In addition to these variables, it is possible to provide cflags and -libs against individual source code files, by defining variables of the -form $FILENAME-cflags and $FILENAME-libs. For example, the curl block -driver needs to link to the libcurl library, so block/Makefile defines -some variables: - - curl.o-cflags := $(CURL_CFLAGS) - curl.o-libs := $(CURL_LIBS) - -The scope is a little different between the two variables. The libs get -used when linking any target binary that includes the curl.o object -file, while the cflags get used when compiling the curl.c file only. - - -Statically defined files ------------------------- - -The following key files are statically defined in the source tree, with -the rules needed to build QEMU. Their behaviour is influenced by a -number of dynamically created files listed later. - -- Makefile - -The main entry point used when invoking make to build all the components -of QEMU. The default 'all' target will naturally result in the build of -every component. The various tools and helper binaries are built -directly via a non-recursive set of rules. - -Each system/userspace emulation target needs to have a slightly -different set of make rules / variables. Thus, make will be recursively -invoked for each of the emulation targets. - -The recursive invocation will end up processing the toplevel -Makefile.target file (more on that later). - - -- */Makefile.objs - -Since the source code is spread across multiple directories, the rules -for each file are similarly modularized. Thus each subdirectory -containing .c files will usually also contain a Makefile.objs file. -These files are not directly invoked by a recursive make, but instead -they are imported by the top level Makefile and/or Makefile.target - -Each Makefile.objs usually just declares a set of variables listing the -.o files that need building from the source files in the directory. They -will also define any custom linker or compiler flags. For example in -block/Makefile.objs - - block-obj-$(CONFIG_LIBISCSI) += iscsi.o - block-obj-$(CONFIG_CURL) += curl.o - - ..snip... - - iscsi.o-cflags := $(LIBISCSI_CFLAGS) - iscsi.o-libs := $(LIBISCSI_LIBS) - curl.o-cflags := $(CURL_CFLAGS) - curl.o-libs := $(CURL_LIBS) - -If there are any rules defined in the Makefile.objs file, they should -all use $(obj) as a prefix to the target, e.g. - - $(obj)/generated-tcg-tracers.h: $(obj)/generated-tcg-tracers.h-timestamp - - -- Makefile.target - -This file provides the entry point used to build each individual system -or userspace emulator target. Each enabled target has its own -subdirectory. For example if configure is run with the argument -'--target-list=x86_64-softmmu', then a sub-directory 'x86_64-softmmu' -will be created, containing a 'Makefile' which symlinks back to -Makefile.target - -So when the recursive '$(MAKE) -C x86_64-softmmu' is invoked, it ends up -using Makefile.target for the build rules. - - -- rules.mak - -This file provides the generic helper rules for invoking build tools, in -particular the compiler and linker. This also contains the magic (hairy) -'unnest-vars' function which is used to merge the variable definitions -from all Makefile.objs in the source tree down into the main Makefile -context. - - -- default-configs/*.mak - -The files under default-configs/ control what emulated hardware is built -into each QEMU system and userspace emulator targets. They merely contain -a list of config variable definitions like the machines that should be -included. For example, default-configs/aarch64-softmmu.mak has: - - include arm-softmmu.mak - CONFIG_XLNX_ZYNQMP_ARM=y - CONFIG_XLNX_VERSAL=y - -These files rarely need changing unless new devices / hardware need to -be enabled for a particular system/userspace emulation target - - -- tests/Makefile - -Rules for building the unit tests. This file is included directly by the -top level Makefile, so anything defined in this file will influence the -entire build system. Care needs to be taken when writing rules for tests -to ensure they only apply to the unit test execution / build. - -- tests/docker/Makefile.include - -Rules for Docker tests. Like tests/Makefile, this file is included -directly by the top level Makefile, anything defined in this file will -influence the entire build system. - -- po/Makefile - -Rules for building and installing the binary message catalogs from the -text .po file sources. This almost never needs changing for any reason. - - -Dynamically created files -------------------------- - -The following files are generated dynamically by configure in order to -control the behaviour of the statically defined makefiles. This avoids -the need for QEMU makefiles to go through any pre-processing as seen -with autotools, where Makefile.am generates Makefile.in which generates -Makefile. - - -- config-host.mak - -When configure has determined the characteristics of the build host it -will write a long list of variables to config-host.mak file. This -provides the various install directories, compiler / linker flags and a -variety of CONFIG_* variables related to optionally enabled features. -This is imported by the top level Makefile in order to tailor the build -output. - -The variables defined here are those which are applicable to all QEMU -build outputs. Variables which are potentially different for each -emulator target are defined by the next file... - -It is also used as a dependency checking mechanism. If make sees that -the modification timestamp on configure is newer than that on -config-host.mak, then configure will be re-run. - - -- config-host.h - -The config-host.h file is used by source code to determine what features -are enabled. It is generated from the contents of config-host.mak using -the scripts/create_config program. This extracts all the CONFIG_* variables, -most of the HOST_* variables and a few other misc variables from -config-host.mak, formatting them as C preprocessor macros. - - -- $TARGET-NAME/config-target.mak - -TARGET-NAME is the name of a system or userspace emulator, for example, -x86_64-softmmu denotes the system emulator for the x86_64 architecture. -This file contains the variables which need to vary on a per-target -basis. For example, it will indicate whether KVM or Xen are enabled for -the target and any other potential custom libraries needed for linking -the target. - - -- $TARGET-NAME/config-devices.mak - -TARGET-NAME is again the name of a system or userspace emulator. The -config-devices.mak file is automatically generated by make using the -scripts/make_device_config.sh program, feeding it the -default-configs/$TARGET-NAME file as input. - - -- $TARGET-NAME/Makefile - -This is the entrypoint used when make recurses to build a single system -or userspace emulator target. It is merely a symlink back to the -Makefile.target in the top level. - - -Useful make targets -=================== - -- help - - Print a help message for the most common build targets. - -- print-VAR - - Print the value of the variable VAR. Useful for debugging the build - system. diff --git a/docs/devel/decodetree.rst b/docs/devel/decodetree.rst index ce7f52308ffecce95508869d267eb9e6fa06c35a..74f66bf46e20959d99d69e13ba22e3b081dd200d 100644 --- a/docs/devel/decodetree.rst +++ b/docs/devel/decodetree.rst @@ -173,18 +173,25 @@ Pattern Groups Syntax:: - group := '{' ( pat_def | group )+ '}' - -A *group* begins with a lone open-brace, with all subsequent lines -indented two spaces, and ending with a lone close-brace. Groups -may be nested, increasing the required indentation of the lines -within the nested group to two spaces per nesting level. - -Unlike ungrouped patterns, grouped patterns are allowed to overlap. -Conflicts are resolved by selecting the patterns in order. If all -of the fixedbits for a pattern match, its translate function will -be called. If the translate function returns false, then subsequent -patterns within the group will be matched. + group := overlap_group | no_overlap_group + overlap_group := '{' ( pat_def | group )+ '}' + no_overlap_group := '[' ( pat_def | group )+ ']' + +A *group* begins with a lone open-brace or open-bracket, with all +subsequent lines indented two spaces, and ending with a lone +close-brace or close-bracket. Groups may be nested, increasing the +required indentation of the lines within the nested group to two +spaces per nesting level. + +Patterns within overlap groups are allowed to overlap. Conflicts are +resolved by selecting the patterns in order. If all of the fixedbits +for a pattern match, its translate function will be called. If the +translate function returns false, then subsequent patterns within the +group will be matched. + +Patterns within no-overlap groups are not allowed to overlap, just +the same as ungrouped patterns. Thus no-overlap groups are intended +to be nested inside overlap groups. The following example from PA-RISC shows specialization of the *or* instruction:: @@ -200,7 +207,7 @@ instruction:: When the *cf* field is zero, the instruction has no side effects, and may be specialized. When the *rt* field is zero, the output is discarded and so the instruction has no effect. When the *rt2* -field is zero, the operation is ``reg[rt] | 0`` and so encodes +field is zero, the operation is ``reg[r1] | 0`` and so encodes the canonical register copy operation. The output from the generator might look like:: diff --git a/docs/devel/fuzzing.rst b/docs/devel/fuzzing.rst new file mode 100644 index 0000000000000000000000000000000000000000..6096242d991829806738f352b9fa1d520cb50ef6 --- /dev/null +++ b/docs/devel/fuzzing.rst @@ -0,0 +1,236 @@ +======== +Fuzzing +======== + +This document describes the virtual-device fuzzing infrastructure in QEMU and +how to use it to implement additional fuzzers. + +Basics +------ + +Fuzzing operates by passing inputs to an entry point/target function. The +fuzzer tracks the code coverage triggered by the input. Based on these +findings, the fuzzer mutates the input and repeats the fuzzing. + +To fuzz QEMU, we rely on libfuzzer. Unlike other fuzzers such as AFL, libfuzzer +is an *in-process* fuzzer. For the developer, this means that it is their +responsibility to ensure that state is reset between fuzzing-runs. + +Building the fuzzers +-------------------- + +*NOTE*: If possible, build a 32-bit binary. When forking, the 32-bit fuzzer is +much faster, since the page-map has a smaller size. This is due to the fact that +AddressSanitizer maps ~20TB of memory, as part of its detection. This results +in a large page-map, and a much slower ``fork()``. + +To build the fuzzers, install a recent version of clang: +Configure with (substitute the clang binaries with the version you installed). +Here, enable-sanitizers, is optional but it allows us to reliably detect bugs +such as out-of-bounds accesses, use-after-frees, double-frees etc.:: + + CC=clang-8 CXX=clang++-8 /path/to/configure --enable-fuzzing \ + --enable-sanitizers + +Fuzz targets are built similarly to system targets:: + + make qemu-fuzz-i386 + +This builds ``./qemu-fuzz-i386`` + +The first option to this command is: ``--fuzz-target=FUZZ_NAME`` +To list all of the available fuzzers run ``qemu-fuzz-i386`` with no arguments. + +For example:: + + ./qemu-fuzz-i386 --fuzz-target=virtio-scsi-fuzz + +Internally, libfuzzer parses all arguments that do not begin with ``"--"``. +Information about these is available by passing ``-help=1`` + +Now the only thing left to do is wait for the fuzzer to trigger potential +crashes. + +Useful libFuzzer flags +---------------------- + +As mentioned above, libFuzzer accepts some arguments. Passing ``-help=1`` will +list the available arguments. In particular, these arguments might be helpful: + +* ``CORPUS_DIR/`` : Specify a directory as the last argument to libFuzzer. + libFuzzer stores each "interesting" input in this corpus directory. The next + time you run libFuzzer, it will read all of the inputs from the corpus, and + continue fuzzing from there. You can also specify multiple directories. + libFuzzer loads existing inputs from all specified directories, but will only + write new ones to the first one specified. + +* ``-max_len=4096`` : specify the maximum byte-length of the inputs libFuzzer + will generate. + +* ``-close_fd_mask={1,2,3}`` : close, stderr, or both. Useful for targets that + trigger many debug/error messages, or create output on the serial console. + +* ``-jobs=4 -workers=4`` : These arguments configure libFuzzer to run 4 fuzzers in + parallel (4 fuzzing jobs in 4 worker processes). Alternatively, with only + ``-jobs=N``, libFuzzer automatically spawns a number of workers less than or equal + to half the available CPU cores. Replace 4 with a number appropriate for your + machine. Make sure to specify a ``CORPUS_DIR``, which will allow the parallel + fuzzers to share information about the interesting inputs they find. + +* ``-use_value_profile=1`` : For each comparison operation, libFuzzer computes + ``(caller_pc&4095) | (popcnt(Arg1 ^ Arg2) << 12)`` and places this in the + coverage table. Useful for targets with "magic" constants. If Arg1 came from + the fuzzer's input and Arg2 is a magic constant, then each time the Hamming + distance between Arg1 and Arg2 decreases, libFuzzer adds the input to the + corpus. + +* ``-shrink=1`` : Tries to make elements of the corpus "smaller". Might lead to + better coverage performance, depending on the target. + +Note that libFuzzer's exact behavior will depend on the version of +clang and libFuzzer used to build the device fuzzers. + +Generating Coverage Reports +--------------------------- + +Code coverage is a crucial metric for evaluating a fuzzer's performance. +libFuzzer's output provides a "cov: " column that provides a total number of +unique blocks/edges covered. To examine coverage on a line-by-line basis we +can use Clang coverage: + + 1. Configure libFuzzer to store a corpus of all interesting inputs (see + CORPUS_DIR above) + 2. ``./configure`` the QEMU build with :: + + --enable-fuzzing \ + --extra-cflags="-fprofile-instr-generate -fcoverage-mapping" + + 3. Re-run the fuzzer. Specify $CORPUS_DIR/* as an argument, telling libfuzzer + to execute all of the inputs in $CORPUS_DIR and exit. Once the process + exits, you should find a file, "default.profraw" in the working directory. + 4. Execute these commands to generate a detailed HTML coverage-report:: + + llvm-profdata merge -output=default.profdata default.profraw + llvm-cov show ./path/to/qemu-fuzz-i386 -instr-profile=default.profdata \ + --format html -output-dir=/path/to/output/report + +Adding a new fuzzer +------------------- + +Coverage over virtual devices can be improved by adding additional fuzzers. +Fuzzers are kept in ``tests/qtest/fuzz/`` and should be added to +``tests/qtest/fuzz/Makefile.include`` + +Fuzzers can rely on both qtest and libqos to communicate with virtual devices. + +1. Create a new source file. For example ``tests/qtest/fuzz/foo-device-fuzz.c``. + +2. Write the fuzzing code using the libqtest/libqos API. See existing fuzzers + for reference. + +3. Register the fuzzer in ``tests/fuzz/Makefile.include`` by appending the + corresponding object to fuzz-obj-y + +Fuzzers can be more-or-less thought of as special qtest programs which can +modify the qtest commands and/or qtest command arguments based on inputs +provided by libfuzzer. Libfuzzer passes a byte array and length. Commonly the +fuzzer loops over the byte-array interpreting it as a list of qtest commands, +addresses, or values. + +The Generic Fuzzer +------------------ + +Writing a fuzz target can be a lot of effort (especially if a device driver has +not be built-out within libqos). Many devices can be fuzzed to some degree, +without any device-specific code, using the generic-fuzz target. + +The generic-fuzz target is capable of fuzzing devices over their PIO, MMIO, +and DMA input-spaces. To apply the generic-fuzz to a device, we need to define +two env-variables, at minimum: + +* ``QEMU_FUZZ_ARGS=`` is the set of QEMU arguments used to configure a machine, with + the device attached. For example, if we want to fuzz the virtio-net device + attached to a pc-i440fx machine, we can specify:: + + QEMU_FUZZ_ARGS="-M pc -nodefaults -netdev user,id=user0 \ + -device virtio-net,netdev=user0" + +* ``QEMU_FUZZ_OBJECTS=`` is a set of space-delimited strings used to identify + the MemoryRegions that will be fuzzed. These strings are compared against + MemoryRegion names and MemoryRegion owner names, to decide whether each + MemoryRegion should be fuzzed. These strings support globbing. For the + virtio-net example, we could use one of :: + + QEMU_FUZZ_OBJECTS='virtio-net' + QEMU_FUZZ_OBJECTS='virtio*' + QEMU_FUZZ_OBJECTS='virtio* pcspk' # Fuzz the virtio devices and the speaker + QEMU_FUZZ_OBJECTS='*' # Fuzz the whole machine`` + +The ``"info mtree"`` and ``"info qom-tree"`` monitor commands can be especially +useful for identifying the ``MemoryRegion`` and ``Object`` names used for +matching. + +As a generic rule-of-thumb, the more ``MemoryRegions``/Devices we match, the +greater the input-space, and the smaller the probability of finding crashing +inputs for individual devices. As such, it is usually a good idea to limit the +fuzzer to only a few ``MemoryRegions``. + +To ensure that these env variables have been configured correctly, we can use:: + + ./qemu-fuzz-i386 --fuzz-target=generic-fuzz -runs=0 + +The output should contain a complete list of matched MemoryRegions. + +Implementation Details / Fuzzer Lifecycle +----------------------------------------- + +The fuzzer has two entrypoints that libfuzzer calls. libfuzzer provides it's +own ``main()``, which performs some setup, and calls the entrypoints: + +``LLVMFuzzerInitialize``: called prior to fuzzing. Used to initialize all of the +necessary state + +``LLVMFuzzerTestOneInput``: called for each fuzzing run. Processes the input and +resets the state at the end of each run. + +In more detail: + +``LLVMFuzzerInitialize`` parses the arguments to the fuzzer (must start with two +dashes, so they are ignored by libfuzzer ``main()``). Currently, the arguments +select the fuzz target. Then, the qtest client is initialized. If the target +requires qos, qgraph is set up and the QOM/LIBQOS modules are initialized. +Then the QGraph is walked and the QEMU cmd_line is determined and saved. + +After this, the ``vl.c:qemu_main`` is called to set up the guest. There are +target-specific hooks that can be called before and after qemu_main, for +additional setup(e.g. PCI setup, or VM snapshotting). + +``LLVMFuzzerTestOneInput``: Uses qtest/qos functions to act based on the fuzz +input. It is also responsible for manually calling ``main_loop_wait`` to ensure +that bottom halves are executed and any cleanup required before the next input. + +Since the same process is reused for many fuzzing runs, QEMU state needs to +be reset at the end of each run. There are currently two implemented +options for resetting state: + +- Reboot the guest between runs. + - *Pros*: Straightforward and fast for simple fuzz targets. + + - *Cons*: Depending on the device, does not reset all device state. If the + device requires some initialization prior to being ready for fuzzing (common + for QOS-based targets), this initialization needs to be done after each + reboot. + + - *Example target*: ``i440fx-qtest-reboot-fuzz`` + +- Run each test case in a separate forked process and copy the coverage + information back to the parent. This is fairly similar to AFL's "deferred" + fork-server mode [3] + + - *Pros*: Relatively fast. Devices only need to be initialized once. No need to + do slow reboots or vmloads. + + - *Cons*: Not officially supported by libfuzzer. Does not work well for + devices that rely on dedicated threads. + + - *Example target*: ``virtio-net-fork-fuzz`` diff --git a/docs/devel/fuzzing.txt b/docs/devel/fuzzing.txt deleted file mode 100644 index 324d2cd92be063938bc33adfb1eced593c50bb56..0000000000000000000000000000000000000000 --- a/docs/devel/fuzzing.txt +++ /dev/null @@ -1,116 +0,0 @@ -= Fuzzing = - -== Introduction == - -This document describes the virtual-device fuzzing infrastructure in QEMU and -how to use it to implement additional fuzzers. - -== Basics == - -Fuzzing operates by passing inputs to an entry point/target function. The -fuzzer tracks the code coverage triggered by the input. Based on these -findings, the fuzzer mutates the input and repeats the fuzzing. - -To fuzz QEMU, we rely on libfuzzer. Unlike other fuzzers such as AFL, libfuzzer -is an _in-process_ fuzzer. For the developer, this means that it is their -responsibility to ensure that state is reset between fuzzing-runs. - -== Building the fuzzers == - -NOTE: If possible, build a 32-bit binary. When forking, the 32-bit fuzzer is -much faster, since the page-map has a smaller size. This is due to the fact that -AddressSanitizer mmaps ~20TB of memory, as part of its detection. This results -in a large page-map, and a much slower fork(). - -To build the fuzzers, install a recent version of clang: -Configure with (substitute the clang binaries with the version you installed): - - CC=clang-8 CXX=clang++-8 /path/to/configure --enable-fuzzing - -Fuzz targets are built similarly to system/softmmu: - - make i386-softmmu/fuzz - -This builds ./i386-softmmu/qemu-fuzz-i386 - -The first option to this command is: --fuzz_taget=FUZZ_NAME -To list all of the available fuzzers run qemu-fuzz-i386 with no arguments. - -eg: - ./i386-softmmu/qemu-fuzz-i386 --fuzz-target=virtio-net-fork-fuzz - -Internally, libfuzzer parses all arguments that do not begin with "--". -Information about these is available by passing -help=1 - -Now the only thing left to do is wait for the fuzzer to trigger potential -crashes. - -== Adding a new fuzzer == -Coverage over virtual devices can be improved by adding additional fuzzers. -Fuzzers are kept in tests/qtest/fuzz/ and should be added to -tests/qtest/fuzz/Makefile.include - -Fuzzers can rely on both qtest and libqos to communicate with virtual devices. - -1. Create a new source file. For example ``tests/qtest/fuzz/foo-device-fuzz.c``. - -2. Write the fuzzing code using the libqtest/libqos API. See existing fuzzers -for reference. - -3. Register the fuzzer in ``tests/fuzz/Makefile.include`` by appending the -corresponding object to fuzz-obj-y - -Fuzzers can be more-or-less thought of as special qtest programs which can -modify the qtest commands and/or qtest command arguments based on inputs -provided by libfuzzer. Libfuzzer passes a byte array and length. Commonly the -fuzzer loops over the byte-array interpreting it as a list of qtest commands, -addresses, or values. - -= Implementation Details = - -== The Fuzzer's Lifecycle == - -The fuzzer has two entrypoints that libfuzzer calls. libfuzzer provides it's -own main(), which performs some setup, and calls the entrypoints: - -LLVMFuzzerInitialize: called prior to fuzzing. Used to initialize all of the -necessary state - -LLVMFuzzerTestOneInput: called for each fuzzing run. Processes the input and -resets the state at the end of each run. - -In more detail: - -LLVMFuzzerInitialize parses the arguments to the fuzzer (must start with two -dashes, so they are ignored by libfuzzer main()). Currently, the arguments -select the fuzz target. Then, the qtest client is initialized. If the target -requires qos, qgraph is set up and the QOM/LIBQOS modules are initialized. -Then the QGraph is walked and the QEMU cmd_line is determined and saved. - -After this, the vl.c:qemu__main is called to set up the guest. There are -target-specific hooks that can be called before and after qemu_main, for -additional setup(e.g. PCI setup, or VM snapshotting). - -LLVMFuzzerTestOneInput: Uses qtest/qos functions to act based on the fuzz -input. It is also responsible for manually calling the main loop/main_loop_wait -to ensure that bottom halves are executed and any cleanup required before the -next input. - -Since the same process is reused for many fuzzing runs, QEMU state needs to -be reset at the end of each run. There are currently two implemented -options for resetting state: -1. Reboot the guest between runs. - Pros: Straightforward and fast for simple fuzz targets. - Cons: Depending on the device, does not reset all device state. If the - device requires some initialization prior to being ready for fuzzing - (common for QOS-based targets), this initialization needs to be done after - each reboot. - Example target: i440fx-qtest-reboot-fuzz -2. Run each test case in a separate forked process and copy the coverage - information back to the parent. This is fairly similar to AFL's "deferred" - fork-server mode [3] - Pros: Relatively fast. Devices only need to be initialized once. No need - to do slow reboots or vmloads. - Cons: Not officially supported by libfuzzer. Does not work well for devices - that rely on dedicated threads. - Example target: virtio-net-fork-fuzz diff --git a/docs/devel/index.rst b/docs/devel/index.rst index bb8238c5d6de55fae3bf14a01b4946c47a432a0b..f10ed77e4c09e42c51d58de8e4b934f8f04edaa7 100644 --- a/docs/devel/index.rst +++ b/docs/devel/index.rst @@ -13,6 +13,7 @@ Contents: .. toctree:: :maxdepth: 2 + build-system kconfig loads-stores memory @@ -20,11 +21,17 @@ Contents: atomics stable-process testing + qtest + fuzzing decodetree secure-coding-practices tcg + tcg-icount + multi-thread-tcg tcg-plugins bitops reset s390-dasd-ipl clocks + qom + block-coroutine-wrapper diff --git a/docs/devel/kconfig.rst b/docs/devel/kconfig.rst index e5df72b34228ffb38a937d53a157f413e6aa8c5c..336ba0e8e5a7ed594cfc204087e3583e1f5e75f0 100644 --- a/docs/devel/kconfig.rst +++ b/docs/devel/kconfig.rst @@ -1,3 +1,5 @@ +.. _kconfig: + ================ QEMU and Kconfig ================ diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst index 9a944ef1af6fc4bdbb114450c87444c8e79c9fd4..59c1225391cebb53077a9c2243d73befd1b8d336 100644 --- a/docs/devel/loads-stores.rst +++ b/docs/devel/loads-stores.rst @@ -93,7 +93,13 @@ guest CPU state in case of a guest CPU exception. This is passed to ``cpu_restore_state()``. Therefore the value should either be 0, to indicate that the guest CPU state is already synchronized, or the result of ``GETPC()`` from the top level ``HELPER(foo)`` -function, which is a return address into the generated code. +function, which is a return address into the generated code [#gpc]_. + +.. [#gpc] Note that ``GETPC()`` should be used with great care: calling + it in other functions that are *not* the top level + ``HELPER(foo)`` will cause unexpected behavior. Instead, the + value of ``GETPC()`` should be read from the helper and passed + if needed to the functions that the helper calls. Function names follow the pattern: diff --git a/docs/devel/lockcnt.txt b/docs/devel/lockcnt.txt index 7c099bc6c8b5b473c2feff25532d28c97ae06d81..2d85462fe3749e802ef7473d485604bd8059272c 100644 --- a/docs/devel/lockcnt.txt +++ b/docs/devel/lockcnt.txt @@ -95,7 +95,7 @@ not just frees, though there could be cases where this is not necessary. Reads, instead, can be done without taking the mutex, as long as the readers and writers use the same macros that are used for RCU, for -example atomic_rcu_read, atomic_rcu_set, QLIST_FOREACH_RCU, etc. This is +example qatomic_rcu_read, qatomic_rcu_set, QLIST_FOREACH_RCU, etc. This is because the reads are done outside a lock and a set or QLIST_INSERT_HEAD can happen concurrently with the read. The RCU API ensures that the processor and the compiler see all required memory barriers. @@ -189,7 +189,7 @@ qemu_lockcnt_lock and qemu_lockcnt_unlock: if (!xyz) { new_xyz = g_new(XYZ, 1); ... - atomic_rcu_set(&xyz, new_xyz); + qatomic_rcu_set(&xyz, new_xyz); } qemu_lockcnt_unlock(&xyz_lockcnt); @@ -198,7 +198,7 @@ qemu_lockcnt_dec: qemu_lockcnt_inc(&xyz_lockcnt); if (xyz) { - XYZ *p = atomic_rcu_read(&xyz); + XYZ *p = qatomic_rcu_read(&xyz); ... /* Accesses can now be done through "p". */ } @@ -222,7 +222,7 @@ the decrement, the locking and the check on count as follows: qemu_lockcnt_inc(&xyz_lockcnt); if (xyz) { - XYZ *p = atomic_rcu_read(&xyz); + XYZ *p = qatomic_rcu_read(&xyz); ... /* Accesses can now be done through "p". */ } diff --git a/docs/devel/migration.rst b/docs/devel/migration.rst index 2eb08624fc369ccf8852604b1ebbf83eb9ac3f39..49112bb27aab2886e1c952239ad3071ef700ebc7 100644 --- a/docs/devel/migration.rst +++ b/docs/devel/migration.rst @@ -625,7 +625,7 @@ It can be issued immediately after migration is started or any time later on. Issuing it after the end of a migration is harmless. Blocktime is a postcopy live migration metric, intended to show how -long the vCPU was in state of interruptable sleep due to pagefault. +long the vCPU was in state of interruptible sleep due to pagefault. That metric is calculated both for all vCPUs as overlapped value, and separately for each vCPU. These values are calculated on destination side. To enable postcopy blocktime calculation, enter following diff --git a/docs/devel/multi-thread-tcg.txt b/docs/devel/multi-thread-tcg.rst similarity index 90% rename from docs/devel/multi-thread-tcg.txt rename to docs/devel/multi-thread-tcg.rst index 3c85ac0eab9b8febfa420c83e04df5bbf74dd779..92a9eba13c91862b881181de38d4031a6d339be0 100644 --- a/docs/devel/multi-thread-tcg.txt +++ b/docs/devel/multi-thread-tcg.rst @@ -1,15 +1,17 @@ -Copyright (c) 2015-2016 Linaro Ltd. +.. + Copyright (c) 2015-2020 Linaro Ltd. -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 work is licensed under the terms of the GNU GPL, version 2 or + later. See the COPYING file in the top-level directory. Introduction ============ -This document outlines the design for multi-threaded TCG system-mode -emulation. The current user-mode emulation mirrors the thread -structure of the translated executable. Some of the work will be -applicable to both system and linux-user emulation. +This document outlines the design for multi-threaded TCG (a.k.a MTTCG) +system-mode emulation. user-mode emulation has always mirrored the +thread structure of the translated executable although some of the +changes done for MTTCG system emulation have improved the stability of +linux-user emulation. The original system-mode TCG implementation was single threaded and dealt with multiple CPUs with simple round-robin scheduling. This @@ -21,9 +23,18 @@ vCPU Scheduling =============== We introduce a new running mode where each vCPU will run on its own -user-space thread. This will be enabled by default for all FE/BE -combinations that have had the required work done to support this -safely. +user-space thread. This is enabled by default for all FE/BE +combinations where the host memory model is able to accommodate the +guest (TCG_GUEST_DEFAULT_MO & ~TCG_TARGET_DEFAULT_MO is zero) and the +guest has had the required work done to support this safely +(TARGET_SUPPORTS_MTTCG). + +System emulation will fall back to the original round robin approach +if: + +* forced by --accel tcg,thread=single +* enabling --icount mode +* 64 bit guests on 32 bit hosts (TCG_OVERSIZED_GUEST) In the general case of running translated code there should be no inter-vCPU dependencies and all vCPUs should be able to run at full @@ -61,7 +72,9 @@ have their block-to-block jumps patched. Global TCG State ---------------- -### User-mode emulation +User-mode emulation +~~~~~~~~~~~~~~~~~~~ + We need to protect the entire code generation cycle including any post generation patching of the translated code. This also implies a shared translation buffer which contains code running on all cores. Any @@ -78,9 +91,11 @@ patching. Code generation is serialised with mmap_lock(). -### !User-mode emulation +!User-mode emulation +~~~~~~~~~~~~~~~~~~~~ + Each vCPU has its own TCG context and associated TCG region, thereby -requiring no locking. +requiring no locking during translation. Translation Blocks ------------------ @@ -92,6 +107,7 @@ including: - debugging operations (breakpoint insertion/removal) - some CPU helper functions + - linux-user spawning its first thread This is done with the async_safe_run_on_cpu() mechanism to ensure all vCPUs are quiescent when changes are being made to shared global @@ -250,8 +266,10 @@ to enforce a particular ordering of memory operations from the point of view of external observers (e.g. another processor core). They can apply to any memory operations as well as just loads or stores. -The Linux kernel has an excellent write-up on the various forms of -memory barrier and the guarantees they can provide [1]. +The Linux kernel has an excellent `write-up +`_ +on the various forms of memory barrier and the guarantees they can +provide. Barriers are often wrapped around synchronisation primitives to provide explicit memory ordering semantics. However they can be used @@ -352,7 +370,3 @@ an exclusive lock which ensures all emulation is serialised. While the atomic helpers look good enough for now there may be a need to look at solutions that can more closely model the guest architectures semantics. - -========== - -[1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/Documentation/memory-barriers.txt diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt index a7794ef658c613e6c69b0deb7c7ea5874e765c7a..6906a06ad23681b1307096c405fbb9c3f1c439d4 100644 --- a/docs/devel/qapi-code-gen.txt +++ b/docs/devel/qapi-code-gen.txt @@ -393,7 +393,7 @@ is identical on the wire to: { 'enum': 'Enum', 'data': ['one', 'two'] } { 'struct': 'Branch1', 'data': { 'data': 'str' } } { 'struct': 'Branch2', 'data': { 'data': 'int' } } - { 'union': 'Flat': 'base': { 'type': 'Enum' }, 'discriminator': 'type', + { 'union': 'Flat', 'base': { 'type': 'Enum' }, 'discriminator': 'type', 'data': { 'one': 'Branch1', 'two': 'Branch2' } } The optional 'if' member specifies a conditional. See "Configuring @@ -472,6 +472,7 @@ Syntax: '*gen': false, '*allow-oob': true, '*allow-preconfig': true, + '*coroutine': true, '*if': COND, '*features': FEATURES } @@ -589,6 +590,8 @@ When in doubt, do not implement OOB execution support. Member 'allow-preconfig' declares whether the command is available before the machine is built. It defaults to false. For example: + { 'enum': 'QMPCapability', + 'data': [ 'oob' ] } { 'command': 'qmp_capabilities', 'data': { '*enable': [ 'QMPCapability' ] }, 'allow-preconfig': true } @@ -596,6 +599,34 @@ before the machine is built. It defaults to false. For example: QMP is available before the machine is built only when QEMU was started with --preconfig. +Member 'coroutine' tells the QMP dispatcher whether the command handler +is safe to be run in a coroutine. It defaults to false. If it is true, +the command handler is called from coroutine context and may yield while +waiting for an external event (such as I/O completion) in order to avoid +blocking the guest and other background operations. + +Coroutine safety can be hard to prove, similar to thread safety. Common +pitfalls are: + +- The global mutex isn't held across qemu_coroutine_yield(), so + operations that used to assume that they execute atomically may have + to be more careful to protect against changes in the global state. + +- Nested event loops (AIO_WAIT_WHILE() etc.) are problematic in + coroutine context and can easily lead to deadlocks. They should be + replaced by yielding and reentering the coroutine when the condition + becomes false. + +Since the command handler may assume coroutine context, any callers +other than the QMP dispatcher must also call it in coroutine context. +In particular, HMP commands calling such a QMP command handler must be +marked .coroutine = true in hmp-commands.hx. + +It is an error to specify both 'coroutine': true and 'allow-oob': true +for a command. We don't currently have a use case for both together and +without a use case, it's not entirely clear what the semantics should +be. + The optional 'if' member specifies a conditional. See "Configuring the schema" below for more on this. @@ -795,7 +826,7 @@ Example: a struct with conditional feature 'allow-negative-numbers' { 'struct': 'TestType', 'data': { 'number': 'int' }, 'features': [ { 'name': 'allow-negative-numbers', - 'if' 'defined(IFCOND)' } ] } + 'if': 'defined(IFCOND)' } ] } Please note that you are responsible to ensure that the C code will compile with an arbitrary combination of conditions, since the @@ -824,21 +855,37 @@ See below for more on definition documentation. Free-form documentation may be used to provide additional text and structuring content. +==== Headings and subheadings ==== -==== Documentation markup ==== +A free-form documentation comment containing a line which starts with +some '=' symbols and then a space defines a section heading: -Comment text starting with '=' is a section title: + ## + # = This is a top level heading + # + # This is a free-form comment which will go under the + # top level heading. + ## - # = Section title + ## + # == This is a second level heading + ## -Double the '=' for a subsection title: +A heading line must be the first line of the documentation +comment block. - # == Subsection title +Section headings must always be correctly nested, so you can only +define a third-level heading inside a second-level heading, and so on. -'|' denotes examples: +==== Documentation markup ==== - # | Text of the example, may span - # | multiple lines +Documentation comments can use most rST markup. In particular, +a '::' literal block can be used for examples: + + # :: + # + # Text of the example, may span + # multiple lines '*' starts an itemized list: @@ -854,34 +901,33 @@ A decimal number followed by '.' starts a numbered list: # multiple lines # 2. Second item -The actual number doesn't matter. You could even use '*' instead of -'2.' for the second item. - -Lists can't be nested. Blank lines are currently not supported within -lists. +The actual number doesn't matter. -Additional whitespace between the initial '#' and the comment text is -permitted. +Lists of either kind must be preceded and followed by a blank line. +If a list item's text spans multiple lines, then the second and +subsequent lines must be correctly indented to line up with the +first character of the first line. -*foo* and _foo_ are for strong and emphasis styles respectively (they -do not work over multiple lines). @foo is used to reference a name in -the schema. +The usual '**strong**', '*emphasised*' and '``literal``' markup should +be used. If you need a single literal '*' you will need to +backslash-escape it. As an extension beyond the usual rST syntax, you +can also use '@foo' to reference a name in the schema; this is +rendered the same way as '``foo``'. Example: ## -# = Section -# == Subsection -# -# Some text foo with *strong* and _emphasis_ +# Some text foo with **bold** and *emphasis* # 1. with a list # 2. like that # # And some code: -# | $ echo foo -# | -> do this -# | <- get that # +# :: +# +# $ echo foo +# -> do this +# <- get that ## @@ -899,6 +945,22 @@ commands and events), member (for structs and unions), branch (for alternates), or value (for enums), and finally optional tagged sections. +Descriptions of arguments can span multiple lines. The description +text can start on the line following the '@argname:', in which case it +must not be indented at all. It can also start on the same line as +the '@argname:'. In this case if it spans multiple lines then second +and subsequent lines must be indented to line up with the first +character of the first line of the description: + +# @argone: +# This is a two line description +# in the first style. +# +# @argtwo: This is a two line description +# in the second style. + +The number of spaces between the ':' and the text is not significant. + FIXME: the parser accepts these things in almost any order. FIXME: union branches should be described, too. @@ -909,9 +971,26 @@ A tagged section starts with one of the following words: "Note:"/"Notes:", "Since:", "Example"/"Examples", "Returns:", "TODO:". The section ends with the start of a new section. +The text of a section can start on a new line, in +which case it must not be indented at all. It can also start +on the same line as the 'Note:', 'Returns:', etc tag. In this +case if it spans multiple lines then second and subsequent +lines must be indented to match the first, in the same way as +multiline argument descriptions. + A 'Since: x.y.z' tagged section lists the release that introduced the definition. +The text of a section can start on a new line, in +which case it must not be indented at all. It can also start +on the same line as the 'Note:', 'Returns:', etc tag. In this +case if it spans multiple lines then second and subsequent +lines must be indented to match the first. + +An 'Example' or 'Examples' section is automatically rendered +entirely as literal fixed-width text. In other sections, +the text is formatted, and rST markup can be used. + For example: ## @@ -1321,6 +1400,7 @@ Example: }; void qapi_free_UserDefOne(UserDefOne *obj); + G_DEFINE_AUTOPTR_CLEANUP_FUNC(UserDefOne, qapi_free_UserDefOne) struct UserDefOneList { UserDefOneList *next; @@ -1328,6 +1408,7 @@ Example: }; void qapi_free_UserDefOneList(UserDefOneList *obj); + G_DEFINE_AUTOPTR_CLEANUP_FUNC(UserDefOneList, qapi_free_UserDefOneList) struct q_obj_my_command_arg { UserDefOneList *arg1; @@ -1408,105 +1489,87 @@ Example: #include "example-qapi-types.h" - void visit_type_UserDefOne_members(Visitor *v, UserDefOne *obj, Error **errp); - void visit_type_UserDefOne(Visitor *v, const char *name, UserDefOne **obj, Error **errp); - void visit_type_UserDefOneList(Visitor *v, const char *name, UserDefOneList **obj, Error **errp); + bool visit_type_UserDefOne_members(Visitor *v, UserDefOne *obj, Error **errp); + bool visit_type_UserDefOne(Visitor *v, const char *name, UserDefOne **obj, Error **errp); + bool visit_type_UserDefOneList(Visitor *v, const char *name, UserDefOneList **obj, Error **errp); - void visit_type_q_obj_my_command_arg_members(Visitor *v, q_obj_my_command_arg *obj, Error **errp); + bool visit_type_q_obj_my_command_arg_members(Visitor *v, q_obj_my_command_arg *obj, Error **errp); #endif /* EXAMPLE_QAPI_VISIT_H */ $ cat qapi-generated/example-qapi-visit.c [Uninteresting stuff omitted...] - void visit_type_UserDefOne_members(Visitor *v, UserDefOne *obj, Error **errp) + bool visit_type_UserDefOne_members(Visitor *v, UserDefOne *obj, Error **errp) { - Error *err = NULL; - - visit_type_int(v, "integer", &obj->integer, &err); - if (err) { - goto out; + if (!visit_type_int(v, "integer", &obj->integer, errp)) { + return false; } if (visit_optional(v, "string", &obj->has_string)) { - visit_type_str(v, "string", &obj->string, &err); - if (err) { - goto out; + if (!visit_type_str(v, "string", &obj->string, errp)) { + return false; } } - - out: - error_propagate(errp, err); + return true; } - void visit_type_UserDefOne(Visitor *v, const char *name, UserDefOne **obj, Error **errp) + bool visit_type_UserDefOne(Visitor *v, const char *name, UserDefOne **obj, Error **errp) { - Error *err = NULL; + bool ok = false; - visit_start_struct(v, name, (void **)obj, sizeof(UserDefOne), &err); - if (err) { - goto out; + if (!visit_start_struct(v, name, (void **)obj, sizeof(UserDefOne), errp)) { + return false; } if (!*obj) { /* incomplete */ assert(visit_is_dealloc(v)); goto out_obj; } - visit_type_UserDefOne_members(v, *obj, &err); - if (err) { + if (!visit_type_UserDefOne_members(v, *obj, errp)) { goto out_obj; } - visit_check_struct(v, &err); + ok = visit_check_struct(v, errp); out_obj: visit_end_struct(v, (void **)obj); - if (err && visit_is_input(v)) { + if (!ok && visit_is_input(v)) { qapi_free_UserDefOne(*obj); *obj = NULL; } - out: - error_propagate(errp, err); + return ok; } - void visit_type_UserDefOneList(Visitor *v, const char *name, UserDefOneList **obj, Error **errp) + bool visit_type_UserDefOneList(Visitor *v, const char *name, UserDefOneList **obj, Error **errp) { - Error *err = NULL; + bool ok = false; UserDefOneList *tail; size_t size = sizeof(**obj); - visit_start_list(v, name, (GenericList **)obj, size, &err); - if (err) { - goto out; + if (!visit_start_list(v, name, (GenericList **)obj, size, errp)) { + return false; } for (tail = *obj; tail; tail = (UserDefOneList *)visit_next_list(v, (GenericList *)tail, size)) { - visit_type_UserDefOne(v, NULL, &tail->value, &err); - if (err) { - break; + if (!visit_type_UserDefOne(v, NULL, &tail->value, errp)) { + goto out_obj; } } - if (!err) { - visit_check_list(v, &err); - } + ok = visit_check_list(v, errp); + out_obj: visit_end_list(v, (void **)obj); - if (err && visit_is_input(v)) { + if (!ok && visit_is_input(v)) { qapi_free_UserDefOneList(*obj); *obj = NULL; } - out: - error_propagate(errp, err); + return ok; } - void visit_type_q_obj_my_command_arg_members(Visitor *v, q_obj_my_command_arg *obj, Error **errp) + bool visit_type_q_obj_my_command_arg_members(Visitor *v, q_obj_my_command_arg *obj, Error **errp) { - Error *err = NULL; - - visit_type_UserDefOneList(v, "arg1", &obj->arg1, &err); - if (err) { - goto out; + if (!visit_type_UserDefOneList(v, "arg1", &obj->arg1, errp)) { + return false; } - - out: - error_propagate(errp, err); + return true; } [Uninteresting stuff omitted...] @@ -1561,15 +1624,12 @@ Example: static void qmp_marshal_output_UserDefOne(UserDefOne *ret_in, QObject **ret_out, Error **errp) { - Error *err = NULL; Visitor *v; v = qobject_output_visitor_new(ret_out); - visit_type_UserDefOne(v, "unused", &ret_in, &err); - if (!err) { + if (visit_type_UserDefOne(v, "unused", &ret_in, errp)) { visit_complete(v, ret_out); } - error_propagate(errp, err); visit_free(v); v = qapi_dealloc_visitor_new(); visit_type_UserDefOne(v, "unused", &ret_in, NULL); @@ -1579,33 +1639,32 @@ Example: void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp) { Error *err = NULL; + bool ok = false; Visitor *v; UserDefOne *retval; q_obj_my_command_arg arg = {0}; v = qobject_input_visitor_new(QOBJECT(args)); - visit_start_struct(v, NULL, NULL, 0, &err); - if (err) { + if (!visit_start_struct(v, NULL, NULL, 0, errp)) { goto out; } - visit_type_q_obj_my_command_arg_members(v, &arg, &err); - if (!err) { - visit_check_struct(v, &err); + if (visit_type_q_obj_my_command_arg_members(v, &arg, errp)) { + ok = visit_check_struct(v, errp); } visit_end_struct(v, NULL); - if (err) { + if (!ok) { goto out; } retval = qmp_my_command(arg.arg1, &err); + error_propagate(errp, err); if (err) { goto out; } - qmp_marshal_output_UserDefOne(retval, ret, &err); + qmp_marshal_output_UserDefOne(retval, ret, errp); out: - error_propagate(errp, err); visit_free(v); v = qapi_dealloc_visitor_new(); visit_start_struct(v, NULL, NULL, 0, NULL); @@ -1613,6 +1672,7 @@ Example: visit_end_struct(v, NULL); visit_free(v); } + [Uninteresting stuff omitted...] $ cat qapi-generated/example-qapi-init-commands.h [Uninteresting stuff omitted...] diff --git a/docs/devel/qom.rst b/docs/devel/qom.rst new file mode 100644 index 0000000000000000000000000000000000000000..42d0dc4f4da801e6c8f73a634bf15a88bf090f3e --- /dev/null +++ b/docs/devel/qom.rst @@ -0,0 +1,381 @@ +=========================== +The QEMU Object Model (QOM) +=========================== + +.. highlight:: c + +The QEMU Object Model provides a framework for registering user creatable +types and instantiating objects from those types. QOM provides the following +features: + +- System for dynamically registering types +- Support for single-inheritance of types +- Multiple inheritance of stateless interfaces + +.. code-block:: c + :caption: Creating a minimal type + + #include "qdev.h" + + #define TYPE_MY_DEVICE "my-device" + + // No new virtual functions: we can reuse the typedef for the + // superclass. + typedef DeviceClass MyDeviceClass; + typedef struct MyDevice + { + DeviceState parent; + + int reg0, reg1, reg2; + } MyDevice; + + static const TypeInfo my_device_info = { + .name = TYPE_MY_DEVICE, + .parent = TYPE_DEVICE, + .instance_size = sizeof(MyDevice), + }; + + static void my_device_register_types(void) + { + type_register_static(&my_device_info); + } + + type_init(my_device_register_types) + +In the above example, we create a simple type that is described by #TypeInfo. +#TypeInfo describes information about the type including what it inherits +from, the instance and class size, and constructor/destructor hooks. + +Alternatively several static types could be registered using helper macro +DEFINE_TYPES() + +.. code-block:: c + + static const TypeInfo device_types_info[] = { + { + .name = TYPE_MY_DEVICE_A, + .parent = TYPE_DEVICE, + .instance_size = sizeof(MyDeviceA), + }, + { + .name = TYPE_MY_DEVICE_B, + .parent = TYPE_DEVICE, + .instance_size = sizeof(MyDeviceB), + }, + }; + + DEFINE_TYPES(device_types_info) + +Every type has an #ObjectClass associated with it. #ObjectClass derivatives +are instantiated dynamically but there is only ever one instance for any +given type. The #ObjectClass typically holds a table of function pointers +for the virtual methods implemented by this type. + +Using object_new(), a new #Object derivative will be instantiated. You can +cast an #Object to a subclass (or base-class) type using +object_dynamic_cast(). You typically want to define macro wrappers around +OBJECT_CHECK() and OBJECT_CLASS_CHECK() to make it easier to convert to a +specific type: + +.. code-block:: c + :caption: Typecasting macros + + #define MY_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(MyDeviceClass, obj, TYPE_MY_DEVICE) + #define MY_DEVICE_CLASS(klass) \ + OBJECT_CLASS_CHECK(MyDeviceClass, klass, TYPE_MY_DEVICE) + #define MY_DEVICE(obj) \ + OBJECT_CHECK(MyDevice, obj, TYPE_MY_DEVICE) + +Class Initialization +==================== + +Before an object is initialized, the class for the object must be +initialized. There is only one class object for all instance objects +that is created lazily. + +Classes are initialized by first initializing any parent classes (if +necessary). After the parent class object has initialized, it will be +copied into the current class object and any additional storage in the +class object is zero filled. + +The effect of this is that classes automatically inherit any virtual +function pointers that the parent class has already initialized. All +other fields will be zero filled. + +Once all of the parent classes have been initialized, #TypeInfo::class_init +is called to let the class being instantiated provide default initialize for +its virtual functions. Here is how the above example might be modified +to introduce an overridden virtual function: + +.. code-block:: c + :caption: Overriding a virtual function + + #include "qdev.h" + + void my_device_class_init(ObjectClass *klass, void *class_data) + { + DeviceClass *dc = DEVICE_CLASS(klass); + dc->reset = my_device_reset; + } + + static const TypeInfo my_device_info = { + .name = TYPE_MY_DEVICE, + .parent = TYPE_DEVICE, + .instance_size = sizeof(MyDevice), + .class_init = my_device_class_init, + }; + +Introducing new virtual methods requires a class to define its own +struct and to add a .class_size member to the #TypeInfo. Each method +will also have a wrapper function to call it easily: + +.. code-block:: c + :caption: Defining an abstract class + + #include "qdev.h" + + typedef struct MyDeviceClass + { + DeviceClass parent; + + void (*frobnicate) (MyDevice *obj); + } MyDeviceClass; + + static const TypeInfo my_device_info = { + .name = TYPE_MY_DEVICE, + .parent = TYPE_DEVICE, + .instance_size = sizeof(MyDevice), + .abstract = true, // or set a default in my_device_class_init + .class_size = sizeof(MyDeviceClass), + }; + + void my_device_frobnicate(MyDevice *obj) + { + MyDeviceClass *klass = MY_DEVICE_GET_CLASS(obj); + + klass->frobnicate(obj); + } + +Interfaces +========== + +Interfaces allow a limited form of multiple inheritance. Instances are +similar to normal types except for the fact that are only defined by +their classes and never carry any state. As a consequence, a pointer to +an interface instance should always be of incomplete type in order to be +sure it cannot be dereferenced. That is, you should define the +'typedef struct SomethingIf SomethingIf' so that you can pass around +``SomethingIf *si`` arguments, but not define a ``struct SomethingIf { ... }``. +The only things you can validly do with a ``SomethingIf *`` are to pass it as +an argument to a method on its corresponding SomethingIfClass, or to +dynamically cast it to an object that implements the interface. + +Methods +======= + +A *method* is a function within the namespace scope of +a class. It usually operates on the object instance by passing it as a +strongly-typed first argument. +If it does not operate on an object instance, it is dubbed +*class method*. + +Methods cannot be overloaded. That is, the #ObjectClass and method name +uniquely identity the function to be called; the signature does not vary +except for trailing varargs. + +Methods are always *virtual*. Overriding a method in +#TypeInfo.class_init of a subclass leads to any user of the class obtained +via OBJECT_GET_CLASS() accessing the overridden function. +The original function is not automatically invoked. It is the responsibility +of the overriding class to determine whether and when to invoke the method +being overridden. + +To invoke the method being overridden, the preferred solution is to store +the original value in the overriding class before overriding the method. +This corresponds to ``{super,base}.method(...)`` in Java and C# +respectively; this frees the overriding class from hardcoding its parent +class, which someone might choose to change at some point. + +.. code-block:: c + :caption: Overriding a virtual method + + typedef struct MyState MyState; + + typedef void (*MyDoSomething)(MyState *obj); + + typedef struct MyClass { + ObjectClass parent_class; + + MyDoSomething do_something; + } MyClass; + + static void my_do_something(MyState *obj) + { + // do something + } + + static void my_class_init(ObjectClass *oc, void *data) + { + MyClass *mc = MY_CLASS(oc); + + mc->do_something = my_do_something; + } + + static const TypeInfo my_type_info = { + .name = TYPE_MY, + .parent = TYPE_OBJECT, + .instance_size = sizeof(MyState), + .class_size = sizeof(MyClass), + .class_init = my_class_init, + }; + + typedef struct DerivedClass { + MyClass parent_class; + + MyDoSomething parent_do_something; + } DerivedClass; + + static void derived_do_something(MyState *obj) + { + DerivedClass *dc = DERIVED_GET_CLASS(obj); + + // do something here + dc->parent_do_something(obj); + // do something else here + } + + static void derived_class_init(ObjectClass *oc, void *data) + { + MyClass *mc = MY_CLASS(oc); + DerivedClass *dc = DERIVED_CLASS(oc); + + dc->parent_do_something = mc->do_something; + mc->do_something = derived_do_something; + } + + static const TypeInfo derived_type_info = { + .name = TYPE_DERIVED, + .parent = TYPE_MY, + .class_size = sizeof(DerivedClass), + .class_init = derived_class_init, + }; + +Alternatively, object_class_by_name() can be used to obtain the class and +its non-overridden methods for a specific type. This would correspond to +``MyClass::method(...)`` in C++. + +The first example of such a QOM method was #CPUClass.reset, +another example is #DeviceClass.realize. + +Standard type declaration and definition macros +=============================================== + +A lot of the code outlined above follows a standard pattern and naming +convention. To reduce the amount of boilerplate code that needs to be +written for a new type there are two sets of macros to generate the +common parts in a standard format. + +A type is declared using the OBJECT_DECLARE macro family. In types +which do not require any virtual functions in the class, the +OBJECT_DECLARE_SIMPLE_TYPE macro is suitable, and is commonly placed +in the header file: + +.. code-block:: c + :caption: Declaring a simple type + + OBJECT_DECLARE_SIMPLE_TYPE(MyDevice, my_device, + MY_DEVICE, DEVICE) + +This is equivalent to the following: + +.. code-block:: c + :caption: Expansion from declaring a simple type + + typedef struct MyDevice MyDevice; + typedef struct MyDeviceClass MyDeviceClass; + + G_DEFINE_AUTOPTR_CLEANUP_FUNC(MyDeviceClass, object_unref) + + #define MY_DEVICE_GET_CLASS(void *obj) \ + OBJECT_GET_CLASS(MyDeviceClass, obj, TYPE_MY_DEVICE) + #define MY_DEVICE_CLASS(void *klass) \ + OBJECT_CLASS_CHECK(MyDeviceClass, klass, TYPE_MY_DEVICE) + #define MY_DEVICE(void *obj) + OBJECT_CHECK(MyDevice, obj, TYPE_MY_DEVICE) + + struct MyDeviceClass { + DeviceClass parent_class; + }; + +The 'struct MyDevice' needs to be declared separately. +If the type requires virtual functions to be declared in the class +struct, then the alternative OBJECT_DECLARE_TYPE() macro can be +used. This does the same as OBJECT_DECLARE_SIMPLE_TYPE(), but without +the 'struct MyDeviceClass' definition. + +To implement the type, the OBJECT_DEFINE macro family is available. +In the simple case the OBJECT_DEFINE_TYPE macro is suitable: + +.. code-block:: c + :caption: Defining a simple type + + OBJECT_DEFINE_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE) + +This is equivalent to the following: + +.. code-block:: c + :caption: Expansion from defining a simple type + + static void my_device_finalize(Object *obj); + static void my_device_class_init(ObjectClass *oc, void *data); + static void my_device_init(Object *obj); + + static const TypeInfo my_device_info = { + .parent = TYPE_DEVICE, + .name = TYPE_MY_DEVICE, + .instance_size = sizeof(MyDevice), + .instance_init = my_device_init, + .instance_finalize = my_device_finalize, + .class_size = sizeof(MyDeviceClass), + .class_init = my_device_class_init, + }; + + static void + my_device_register_types(void) + { + type_register_static(&my_device_info); + } + type_init(my_device_register_types); + +This is sufficient to get the type registered with the type +system, and the three standard methods now need to be implemented +along with any other logic required for the type. + +If the type needs to implement one or more interfaces, then the +OBJECT_DEFINE_TYPE_WITH_INTERFACES() macro can be used instead. +This accepts an array of interface type names. + +.. code-block:: c + :caption: Defining a simple type implementing interfaces + + OBJECT_DEFINE_TYPE_WITH_INTERFACES(MyDevice, my_device, + MY_DEVICE, DEVICE, + { TYPE_USER_CREATABLE }, + { NULL }) + +If the type is not intended to be instantiated, then then +the OBJECT_DEFINE_ABSTRACT_TYPE() macro can be used instead: + +.. code-block:: c + :caption: Defining a simple abstract type + + OBJECT_DEFINE_ABSTRACT_TYPE(MyDevice, my_device, + MY_DEVICE, DEVICE) + + + +API Reference +------------- + +.. kernel-doc:: include/qom/object.h diff --git a/docs/devel/qtest.rst b/docs/devel/qtest.rst new file mode 100644 index 0000000000000000000000000000000000000000..97c5a756260766a20aa66183ce4e4388e98ba2be --- /dev/null +++ b/docs/devel/qtest.rst @@ -0,0 +1,84 @@ +======================================== +QTest Device Emulation Testing Framework +======================================== + +QTest is a device emulation testing framework. It can be very useful to test +device models; it could also control certain aspects of QEMU (such as virtual +clock stepping), with a special purpose "qtest" protocol. Refer to +:ref:`qtest-protocol` for more details of the protocol. + +QTest cases can be executed with + +.. code:: + + make check-qtest + +The QTest library is implemented by ``tests/qtest/libqtest.c`` and the API is +defined in ``tests/qtest/libqtest.h``. + +Consider adding a new QTest case when you are introducing a new virtual +hardware, or extending one if you are adding functionalities to an existing +virtual device. + +On top of libqtest, a higher level library, ``libqos``, was created to +encapsulate common tasks of device drivers, such as memory management and +communicating with system buses or devices. Many virtual device tests use +libqos instead of directly calling into libqtest. + +Steps to add a new QTest case are: + +1. Create a new source file for the test. (More than one file can be added as + necessary.) For example, ``tests/qtest/foo-test.c``. + +2. Write the test code with the glib and libqtest/libqos API. See also existing + tests and the library headers for reference. + +3. Register the new test in ``tests/qtest/meson.build``. Add the test + executable name to an appropriate ``qtests_*`` variable. There is + one variable per architecture, plus ``qtests_generic`` for tests + that can be run for all architectures. For example:: + + qtests_generic = [ + ... + 'foo-test', + ... + ] + +4. If the test has more than one source file or needs to be linked with any + dependency other than ``qemuutil`` and ``qos``, list them in the ``qtests`` + dictionary. For example a test that needs to use the ``QIO`` library + will have an entry like:: + + { + ... + 'foo-test': [io], + ... + } + +Debugging a QTest failure is slightly harder than the unit test because the +tests look up QEMU program names in the environment variables, such as +``QTEST_QEMU_BINARY`` and ``QTEST_QEMU_IMG``, and also because it is not easy +to attach gdb to the QEMU process spawned from the test. But manual invoking +and using gdb on the test is still simple to do: find out the actual command +from the output of + +.. code:: + + make check-qtest V=1 + +which you can run manually. + + +.. _qtest-protocol: + +QTest Protocol +-------------- + +.. kernel-doc:: softmmu/qtest.c + :doc: QTest Protocol + + +libqtest API reference +---------------------- + +.. kernel-doc:: tests/qtest/libqos/libqtest.h diff --git a/docs/devel/rcu.txt b/docs/devel/rcu.txt index 0ce15ba198ac00ce0052c7c860b151b84c210e90..cdf002edd82625c2a322cdab797c1b521c24d311 100644 --- a/docs/devel/rcu.txt +++ b/docs/devel/rcu.txt @@ -130,13 +130,13 @@ The core RCU API is small: g_free_rcu(&foo, rcu); - typeof(*p) atomic_rcu_read(p); + typeof(*p) qatomic_rcu_read(p); - atomic_rcu_read() is similar to atomic_load_acquire(), but it makes + qatomic_rcu_read() is similar to qatomic_load_acquire(), but it makes some assumptions on the code that calls it. This allows a more optimized implementation. - atomic_rcu_read assumes that whenever a single RCU critical + qatomic_rcu_read assumes that whenever a single RCU critical section reads multiple shared data, these reads are either data-dependent or need no ordering. This is almost always the case when using RCU, because read-side critical sections typically @@ -144,7 +144,7 @@ The core RCU API is small: every update) until reaching a data structure of interest, and then read from there. - RCU read-side critical sections must use atomic_rcu_read() to + RCU read-side critical sections must use qatomic_rcu_read() to read data, unless concurrent writes are prevented by another synchronization mechanism. @@ -152,18 +152,18 @@ The core RCU API is small: data structure in a single direction, opposite to the direction in which the updater initializes it. - void atomic_rcu_set(p, typeof(*p) v); + void qatomic_rcu_set(p, typeof(*p) v); - atomic_rcu_set() is similar to atomic_store_release(), though it also + qatomic_rcu_set() is similar to qatomic_store_release(), though it also makes assumptions on the code that calls it in order to allow a more optimized implementation. - In particular, atomic_rcu_set() suffices for synchronization + In particular, qatomic_rcu_set() suffices for synchronization with readers, if the updater never mutates a field within a data item that is already accessible to readers. This is the case when initializing a new copy of the RCU-protected data structure; just ensure that initialization of *p is carried out - before atomic_rcu_set() makes the data item visible to readers. + before qatomic_rcu_set() makes the data item visible to readers. If this rule is observed, writes will happen in the opposite order as reads in the RCU read-side critical sections (or if there is just one update), and there will be no need for other @@ -212,7 +212,7 @@ DIFFERENCES WITH LINUX programming; not allowing this would prevent upgrading an RCU read-side critical section to become an updater. -- atomic_rcu_read and atomic_rcu_set replace rcu_dereference and +- qatomic_rcu_read and qatomic_rcu_set replace rcu_dereference and rcu_assign_pointer. They take a _pointer_ to the variable being accessed. - call_rcu is a macro that has an extra argument (the name of the first @@ -257,7 +257,7 @@ may be used as a restricted reference-counting mechanism. For example, consider the following code fragment: rcu_read_lock(); - p = atomic_rcu_read(&foo); + p = qatomic_rcu_read(&foo); /* do something with p. */ rcu_read_unlock(); @@ -268,7 +268,7 @@ The write side looks simply like this (with appropriate locking): qemu_mutex_lock(&foo_mutex); old = foo; - atomic_rcu_set(&foo, new); + qatomic_rcu_set(&foo, new); qemu_mutex_unlock(&foo_mutex); synchronize_rcu(); free(old); @@ -277,7 +277,7 @@ If the processing cannot be done purely within the critical section, it is possible to combine this idiom with a "real" reference count: rcu_read_lock(); - p = atomic_rcu_read(&foo); + p = qatomic_rcu_read(&foo); foo_ref(p); rcu_read_unlock(); /* do something with p. */ @@ -287,7 +287,7 @@ The write side can be like this: qemu_mutex_lock(&foo_mutex); old = foo; - atomic_rcu_set(&foo, new); + qatomic_rcu_set(&foo, new); qemu_mutex_unlock(&foo_mutex); synchronize_rcu(); foo_unref(old); @@ -296,7 +296,7 @@ or with call_rcu: qemu_mutex_lock(&foo_mutex); old = foo; - atomic_rcu_set(&foo, new); + qatomic_rcu_set(&foo, new); qemu_mutex_unlock(&foo_mutex); call_rcu(foo_unref, old, rcu); @@ -307,7 +307,7 @@ last reference may be dropped on the read side. Hence you can use call_rcu() instead: foo_unref(struct foo *p) { - if (atomic_fetch_dec(&p->refcount) == 1) { + if (qatomic_fetch_dec(&p->refcount) == 1) { call_rcu(foo_destroy, p, rcu); } } @@ -375,7 +375,7 @@ Instead, we store the size of the array with the array itself: read side: rcu_read_lock(); - struct arr *array = atomic_rcu_read(&global_array); + struct arr *array = qatomic_rcu_read(&global_array); x = i < array->size ? array->data[i] : -1; rcu_read_unlock(); return x; @@ -392,7 +392,7 @@ Instead, we store the size of the array with the array itself: /* Removal phase. */ old_array = global_array; - atomic_rcu_set(&new_array->data, new_array); + qatomic_rcu_set(&new_array->data, new_array); synchronize_rcu(); /* Reclamation phase. */ diff --git a/docs/devel/tcg-icount.rst b/docs/devel/tcg-icount.rst new file mode 100644 index 0000000000000000000000000000000000000000..8d67b6c076a754cd6f826829dbc95416b9e89289 --- /dev/null +++ b/docs/devel/tcg-icount.rst @@ -0,0 +1,97 @@ +.. + Copyright (c) 2020, Linaro Limited + Written by Alex BennĂ©e + + +======================== +TCG Instruction Counting +======================== + +TCG has long supported a feature known as icount which allows for +instruction counting during execution. This should not be confused +with cycle accurate emulation - QEMU does not attempt to emulate how +long an instruction would take on real hardware. That is a job for +other more detailed (and slower) tools that simulate the rest of a +micro-architecture. + +This feature is only available for system emulation and is +incompatible with multi-threaded TCG. It can be used to better align +execution time with wall-clock time so a "slow" device doesn't run too +fast on modern hardware. It can also provides for a degree of +deterministic execution and is an essential part of the record/replay +support in QEMU. + +Core Concepts +============= + +At its heart icount is simply a count of executed instructions which +is stored in the TimersState of QEMU's timer sub-system. The number of +executed instructions can then be used to calculate QEMU_CLOCK_VIRTUAL +which represents the amount of elapsed time in the system since +execution started. Depending on the icount mode this may either be a +fixed number of ns per instruction or adjusted as execution continues +to keep wall clock time and virtual time in sync. + +To be able to calculate the number of executed instructions the +translator starts by allocating a budget of instructions to be +executed. The budget of instructions is limited by how long it will be +until the next timer will expire. We store this budget as part of a +vCPU icount_decr field which shared with the machinery for handling +cpu_exit(). The whole field is checked at the start of every +translated block and will cause a return to the outer loop to deal +with whatever caused the exit. + +In the case of icount, before the flag is checked we subtract the +number of instructions the translation block would execute. If this +would cause the instruction budget to go negative we exit the main +loop and regenerate a new translation block with exactly the right +number of instructions to take the budget to 0 meaning whatever timer +was due to expire will expire exactly when we exit the main run loop. + +Dealing with MMIO +----------------- + +While we can adjust the instruction budget for known events like timer +expiry we cannot do the same for MMIO. Every load/store we execute +might potentially trigger an I/O event, at which point we will need an +up to date and accurate reading of the icount number. + +To deal with this case, when an I/O access is made we: + + - restore un-executed instructions to the icount budget + - re-compile a single [1]_ instruction block for the current PC + - exit the cpu loop and execute the re-compiled block + +The new block is created with the CF_LAST_IO compile flag which +ensures the final instruction translation starts with a call to +gen_io_start() so we don't enter a perpetual loop constantly +recompiling a single instruction block. For translators using the +common translator_loop this is done automatically. + +.. [1] sometimes two instructions if dealing with delay slots + +Other I/O operations +-------------------- + +MMIO isn't the only type of operation for which we might need a +correct and accurate clock. IO port instructions and accesses to +system registers are the common examples here. These instructions have +to be handled by the individual translators which have the knowledge +of which operations are I/O operations. + +When the translator is handling an instruction of this kind: + +* it must call gen_io_start() if icount is enabled, at some + point before the generation of the code which actually does + the I/O, using a code fragment similar to: + +.. code:: c + + if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { + gen_io_start(); + } + +* it must end the TB immediately after this instruction + +Note that some older front-ends call a "gen_io_end()" function: +this is obsolete and should not be used. diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst index a05990906cc09b9b764858dc0fa0fbf9d50b373f..0568dfa6a49d9c18132b9ba27a5ecb3f84544b53 100644 --- a/docs/devel/tcg-plugins.rst +++ b/docs/devel/tcg-plugins.rst @@ -134,3 +134,149 @@ longer want to instrument the code. This operation is asynchronous which means callbacks may still occur after the uninstall operation is requested. The plugin isn't completely uninstalled until the safe work has executed while all vCPUs are quiescent. + +Example Plugins +=============== + +There are a number of plugins included with QEMU and you are +encouraged to contribute your own plugins plugins upstream. There is a +`contrib/plugins` directory where they can go. + +- tests/plugins + +These are some basic plugins that are used to test and exercise the +API during the `make check-tcg` target. + +- contrib/plugins/hotblocks.c + +The hotblocks plugin allows you to examine the where hot paths of +execution are in your program. Once the program has finished you will +get a sorted list of blocks reporting the starting PC, translation +count, number of instructions and execution count. This will work best +with linux-user execution as system emulation tends to generate +re-translations as blocks from different programs get swapped in and +out of system memory. + +If your program is single-threaded you can use the `inline` option for +slightly faster (but not thread safe) counters. + +Example:: + + ./aarch64-linux-user/qemu-aarch64 \ + -plugin contrib/plugins/libhotblocks.so -d plugin \ + ./tests/tcg/aarch64-linux-user/sha1 + SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6 + collected 903 entries in the hash table + pc, tcount, icount, ecount + 0x0000000041ed10, 1, 5, 66087 + 0x000000004002b0, 1, 4, 66087 + ... + +- contrib/plugins/hotpages.c + +Similar to hotblocks but this time tracks memory accesses:: + + ./aarch64-linux-user/qemu-aarch64 \ + -plugin contrib/plugins/libhotpages.so -d plugin \ + ./tests/tcg/aarch64-linux-user/sha1 + SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6 + Addr, RCPUs, Reads, WCPUs, Writes + 0x000055007fe000, 0x0001, 31747952, 0x0001, 8835161 + 0x000055007ff000, 0x0001, 29001054, 0x0001, 8780625 + 0x00005500800000, 0x0001, 687465, 0x0001, 335857 + 0x0000000048b000, 0x0001, 130594, 0x0001, 355 + 0x0000000048a000, 0x0001, 1826, 0x0001, 11 + +- contrib/plugins/howvec.c + +This is an instruction classifier so can be used to count different +types of instructions. It has a number of options to refine which get +counted. You can give an argument for a class of instructions to break +it down fully, so for example to see all the system registers +accesses:: + + ./aarch64-softmmu/qemu-system-aarch64 $(QEMU_ARGS) \ + -append "root=/dev/sda2 systemd.unit=benchmark.service" \ + -smp 4 -plugin ./contrib/plugins/libhowvec.so,arg=sreg -d plugin + +which will lead to a sorted list after the class breakdown:: + + Instruction Classes: + Class: UDEF not counted + Class: SVE (68 hits) + Class: PCrel addr (47789483 hits) + Class: Add/Sub (imm) (192817388 hits) + Class: Logical (imm) (93852565 hits) + Class: Move Wide (imm) (76398116 hits) + Class: Bitfield (44706084 hits) + Class: Extract (5499257 hits) + Class: Cond Branch (imm) (147202932 hits) + Class: Exception Gen (193581 hits) + Class: NOP not counted + Class: Hints (6652291 hits) + Class: Barriers (8001661 hits) + Class: PSTATE (1801695 hits) + Class: System Insn (6385349 hits) + Class: System Reg counted individually + Class: Branch (reg) (69497127 hits) + Class: Branch (imm) (84393665 hits) + Class: Cmp & Branch (110929659 hits) + Class: Tst & Branch (44681442 hits) + Class: AdvSimd ldstmult (736 hits) + Class: ldst excl (9098783 hits) + Class: Load Reg (lit) (87189424 hits) + Class: ldst noalloc pair (3264433 hits) + Class: ldst pair (412526434 hits) + Class: ldst reg (imm) (314734576 hits) + Class: Loads & Stores (2117774 hits) + Class: Data Proc Reg (223519077 hits) + Class: Scalar FP (31657954 hits) + Individual Instructions: + Instr: mrs x0, sp_el0 (2682661 hits) (op=0xd5384100/ System Reg) + Instr: mrs x1, tpidr_el2 (1789339 hits) (op=0xd53cd041/ System Reg) + Instr: mrs x2, tpidr_el2 (1513494 hits) (op=0xd53cd042/ System Reg) + Instr: mrs x0, tpidr_el2 (1490823 hits) (op=0xd53cd040/ System Reg) + Instr: mrs x1, sp_el0 (933793 hits) (op=0xd5384101/ System Reg) + Instr: mrs x2, sp_el0 (699516 hits) (op=0xd5384102/ System Reg) + Instr: mrs x4, tpidr_el2 (528437 hits) (op=0xd53cd044/ System Reg) + Instr: mrs x30, ttbr1_el1 (480776 hits) (op=0xd538203e/ System Reg) + Instr: msr ttbr1_el1, x30 (480713 hits) (op=0xd518203e/ System Reg) + Instr: msr vbar_el1, x30 (480671 hits) (op=0xd518c01e/ System Reg) + ... + +To find the argument shorthand for the class you need to examine the +source code of the plugin at the moment, specifically the `*opt` +argument in the InsnClassExecCount tables. + +- contrib/plugins/lockstep.c + +This is a debugging tool for developers who want to find out when and +where execution diverges after a subtle change to TCG code generation. +It is not an exact science and results are likely to be mixed once +asynchronous events are introduced. While the use of -icount can +introduce determinism to the execution flow it doesn't always follow +the translation sequence will be exactly the same. Typically this is +caused by a timer firing to service the GUI causing a block to end +early. However in some cases it has proved to be useful in pointing +people at roughly where execution diverges. The only argument you need +for the plugin is a path for the socket the two instances will +communicate over:: + + + ./sparc-softmmu/qemu-system-sparc -monitor none -parallel none \ + -net none -M SS-20 -m 256 -kernel day11/zImage.elf \ + -plugin ./contrib/plugins/liblockstep.so,arg=lockstep-sparc.sock \ + -d plugin,nochain + +which will eventually report:: + + qemu-system-sparc: warning: nic lance.0 has no peer + @ 0x000000ffd06678 vs 0x000000ffd001e0 (2/1 since last) + @ 0x000000ffd07d9c vs 0x000000ffd06678 (3/1 since last) + Δ insn_count @ 0x000000ffd07d9c (809900609) vs 0x000000ffd06678 (809900612) + previously @ 0x000000ffd06678/10 (809900609 insns) + previously @ 0x000000ffd001e0/4 (809900599 insns) + previously @ 0x000000ffd080ac/2 (809900595 insns) + previously @ 0x000000ffd08098/5 (809900593 insns) + previously @ 0x000000ffd080c0/1 (809900588 insns) + diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst index 770a987ea421db362de0fff5bb45621dd0bcfb89..0aa7a13bbad3f64c9c44119d17bc201feef01a81 100644 --- a/docs/devel/testing.rst +++ b/docs/devel/testing.rst @@ -41,15 +41,16 @@ add a new unit test: test. The test code should be organized with the glib testing framework. Copying and modifying an existing test is usually a good idea. -3. Add the test to ``tests/Makefile.include``. First, name the unit test - program and add it to ``$(check-unit-y)``; then add a rule to build the - executable. For example: +3. Add the test to ``tests/meson.build``. The unit tests are listed in a + dictionary called ``tests``. The values are any additional sources and + dependencies to be linked with the test. For a simple test whose source + is in ``tests/foo-test.c``, it is enough to add an entry like:: -.. code:: - - check-unit-y += tests/foo-test$(EXESUF) - tests/foo-test$(EXESUF): tests/foo-test.o $(test-util-obj-y) - ... + { + ... + 'foo-test': [], + ... + } Since unit tests don't require environment variables, the simplest way to debug a unit test failure is often directly invoking it or even running it under @@ -70,8 +71,8 @@ QTest QTest is a device emulation testing framework. It can be very useful to test device models; it could also control certain aspects of QEMU (such as virtual -clock stepping), with a special purpose "qtest" protocol. Refer to the -documentation in ``qtest.c`` for more details of the protocol. +clock stepping), with a special purpose "qtest" protocol. Refer to +:doc:`qtest` for more details. QTest cases can be executed with @@ -79,49 +80,6 @@ QTest cases can be executed with make check-qtest -The QTest library is implemented by ``tests/qtest/libqtest.c`` and the API is -defined in ``tests/qtest/libqtest.h``. - -Consider adding a new QTest case when you are introducing a new virtual -hardware, or extending one if you are adding functionalities to an existing -virtual device. - -On top of libqtest, a higher level library, ``libqos``, was created to -encapsulate common tasks of device drivers, such as memory management and -communicating with system buses or devices. Many virtual device tests use -libqos instead of directly calling into libqtest. - -Steps to add a new QTest case are: - -1. Create a new source file for the test. (More than one file can be added as - necessary.) For example, ``tests/qtest/foo-test.c``. - -2. Write the test code with the glib and libqtest/libqos API. See also existing - tests and the library headers for reference. - -3. Register the new test in ``tests/qtest/Makefile.include``. Add the test - executable name to an appropriate ``check-qtest-*-y`` variable. For example: - - ``check-qtest-generic-y = tests/qtest/foo-test$(EXESUF)`` - -4. Add object dependencies of the executable in the Makefile, including the - test source file(s) and other interesting objects. For example: - - ``tests/qtest/foo-test$(EXESUF): tests/qtest/foo-test.o $(libqos-obj-y)`` - -Debugging a QTest failure is slightly harder than the unit test because the -tests look up QEMU program names in the environment variables, such as -``QTEST_QEMU_BINARY`` and ``QTEST_QEMU_IMG``, and also because it is not easy -to attach gdb to the QEMU process spawned from the test. But manual invoking -and using gdb on the test is still simple to do: find out the actual command -from the output of - -.. code:: - - make check-qtest V=1 - -which you can run manually. - QAPI schema tests ----------------- @@ -164,13 +122,12 @@ instrumenting the tested code. To use it, configure QEMU with ``--enable-gcov`` option and build. Then run ``make check`` as usual. If you want to gather coverage information on a single test the ``make -clean-coverage`` target can be used to delete any existing coverage +clean-gcda`` target can be used to delete any existing coverage information before running a single test. You can generate a HTML coverage report by executing ``make -coverage-report`` which will create -./reports/coverage/coverage-report.html. If you want to create it -elsewhere simply execute ``make /foo/bar/baz/coverage-report.html``. +coverage-html`` which will create +``meson-logs/coveragereport/index.html``. Further analysis can be conducted by running the ``gcov`` command directly on the various .gcda output files. Please read the ``gcov`` @@ -397,6 +354,113 @@ list is in the ``make docker`` help text. The frequently used ones are: * ``DEBUG=1``: enables debug. See the previous "Debugging a Docker test failure" section. +Thread Sanitizer +================ + +Thread Sanitizer (TSan) is a tool which can detect data races. QEMU supports +building and testing with this tool. + +For more information on TSan: + +https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual + +Thread Sanitizer in Docker +--------------------------- +TSan is currently supported in the ubuntu2004 docker. + +The test-tsan test will build using TSan and then run make check. + +.. code:: + + make docker-test-tsan@ubuntu2004 + +TSan warnings under docker are placed in files located at build/tsan/. + +We recommend using DEBUG=1 to allow launching the test from inside the docker, +and to allow review of the warnings generated by TSan. + +Building and Testing with TSan +------------------------------ + +It is possible to build and test with TSan, with a few additional steps. +These steps are normally done automatically in the docker. + +There is a one time patch needed in clang-9 or clang-10 at this time: + +.. code:: + + sed -i 's/^const/static const/g' \ + /usr/lib/llvm-10/lib/clang/10.0.0/include/sanitizer/tsan_interface.h + +To configure the build for TSan: + +.. code:: + + ../configure --enable-tsan --cc=clang-10 --cxx=clang++-10 \ + --disable-werror --extra-cflags="-O0" + +The runtime behavior of TSAN is controlled by the TSAN_OPTIONS environment +variable. + +More information on the TSAN_OPTIONS can be found here: + +https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags + +For example: + +.. code:: + + export TSAN_OPTIONS=suppressions=/tests/tsan/suppressions.tsan \ + detect_deadlocks=false history_size=7 exitcode=0 \ + log_path=/tsan/tsan_warning + +The above exitcode=0 has TSan continue without error if any warnings are found. +This allows for running the test and then checking the warnings afterwards. +If you want TSan to stop and exit with error on warnings, use exitcode=66. + +TSan Suppressions +----------------- +Keep in mind that for any data race warning, although there might be a data race +detected by TSan, there might be no actual bug here. TSan provides several +different mechanisms for suppressing warnings. In general it is recommended +to fix the code if possible to eliminate the data race rather than suppress +the warning. + +A few important files for suppressing warnings are: + +tests/tsan/suppressions.tsan - Has TSan warnings we wish to suppress at runtime. +The comment on each suppression will typically indicate why we are +suppressing it. More information on the file format can be found here: + +https://github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions + +tests/tsan/blacklist.tsan - Has TSan warnings we wish to disable +at compile time for test or debug. +Add flags to configure to enable: + +"--extra-cflags=-fsanitize-blacklist=/tests/tsan/blacklist.tsan" + +More information on the file format can be found here under "Blacklist Format": + +https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags + +TSan Annotations +---------------- +include/qemu/tsan.h defines annotations. See this file for more descriptions +of the annotations themselves. Annotations can be used to suppress +TSan warnings or give TSan more information so that it can detect proper +relationships between accesses of data. + +Annotation examples can be found here: + +https://github.com/llvm/llvm-project/tree/master/compiler-rt/test/tsan/ + +Good files to start with are: annotate_happens_before.cpp and ignore_race.cpp + +The full set of annotations can be found here: + +https://github.com/llvm/llvm-project/blob/master/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp + VM testing ========== @@ -590,7 +654,7 @@ To manually install Avocado and its dependencies, run: Alternatively, follow the instructions on this link: - http://avocado-framework.readthedocs.io/en/latest/GetStartedGuide.html#installing-avocado + https://avocado-framework.readthedocs.io/en/latest/guides/user/chapters/installing.html Overview -------- @@ -713,7 +777,7 @@ the following approaches: 1) Set ``qemu_bin``, and use the given binary 2) Do not set ``qemu_bin``, and use a QEMU binary named like - "${arch}-softmmu/qemu-system-${arch}", either in the current + "qemu-system-${arch}", either in the current working directory, or in the current source tree. The resulting ``qemu_bin`` value will be preserved in the @@ -773,14 +837,14 @@ Parameter reference To understand how Avocado parameters are accessed by tests, and how they can be passed to tests, please refer to:: - http://avocado-framework.readthedocs.io/en/latest/WritingTests.html#accessing-test-parameters + https://avocado-framework.readthedocs.io/en/latest/guides/writer/chapters/writing.html#accessing-test-parameters Parameter values can be easily seen in the log files, and will look like the following: .. code:: - PARAMS (key=qemu_bin, path=*, default=x86_64-softmmu/qemu-system-x86_64) => 'x86_64-softmmu/qemu-system-x86_64 + PARAMS (key=qemu_bin, path=*, default=./qemu-system-x86_64) => './qemu-system-x86_64 arch ~~~~ @@ -847,7 +911,7 @@ compiler flags are needed to build for a given target. If you have the ability to run containers as the user you can also take advantage of the build systems "Docker" support. It will then use containers to build any test case for an enabled guest where there is -no system compiler available. See :ref: `_docker-ref` for details. +no system compiler available. See :ref:`docker-ref` for details. Running subset of tests ----------------------- diff --git a/docs/devel/tracing.txt b/docs/devel/tracing.txt index cb5f685de9f6f4a0c32ecfb5091392d77d44644a..d2160655b4e3041509a5d87216846e85292393c1 100644 --- a/docs/devel/tracing.txt +++ b/docs/devel/tracing.txt @@ -55,12 +55,12 @@ without any sub-directory path prefix. eg io/channel-buffer.c would do #include "trace.h" To access the 'io/trace.h' file. While it is possible to include a trace.h -file from outside a source files' own sub-directory, this is discouraged in +file from outside a source file's own sub-directory, this is discouraged in general. It is strongly preferred that all events be declared directly in the sub-directory that uses them. The only exception is where there are some shared trace events defined in the top level directory trace-events file. The top level directory generates trace files with a filename prefix of -"trace-root" instead of just "trace". This is to avoid ambiguity between +"trace/trace-root" instead of just "trace". This is to avoid ambiguity between a trace.h in the current directory, vs the top level directory. === Using trace events === diff --git a/docs/hyperv.txt b/docs/hyperv.txt index 6518b716a9585c995a7beb21c87384b33eb71390..5df00da54fc48fffc56a882b2133ad0043598a4f 100644 --- a/docs/hyperv.txt +++ b/docs/hyperv.txt @@ -49,7 +49,7 @@ more efficiently. In particular, this enlightenment allows paravirtualized ====================== Enables paravirtualized spinlocks. The parameter indicates how many times spinlock acquisition should be attempted before indicating the situation to the -hypervisor. A special value 0xffffffff indicates "never to retry". +hypervisor. A special value 0xffffffff indicates "never notify". 3.4. hv-vpindex ================ diff --git a/docs/index.html.in b/docs/index.html.in index e9a160384cfe939a3bccc51e5da9052130e381a8..33db4396ac83b95b60ef16580d3176453b64293a 100644 --- a/docs/index.html.in +++ b/docs/index.html.in @@ -2,18 +2,16 @@ - QEMU @@VERSION@@ Documentation + QEMU @VERSION@ Documentation -

QEMU @@VERSION@@ Documentation

+

QEMU @VERSION@ Documentation

diff --git a/docs/interop/_templates/editpage.html b/docs/interop/_templates/editpage.html new file mode 100644 index 0000000000000000000000000000000000000000..215e5626812c748f290d370cb07ea90460931976 --- /dev/null +++ b/docs/interop/_templates/editpage.html @@ -0,0 +1,5 @@ +
+ +
diff --git a/docs/interop/bitmaps.rst b/docs/interop/bitmaps.rst index c20bd37a7971e68803d67932217949e30de232ee..059ad67929407526c00e3aa49257674c275742d1 100644 --- a/docs/interop/bitmaps.rst +++ b/docs/interop/bitmaps.rst @@ -484,7 +484,7 @@ Bitmaps can generally be modified at any time, but certain operations often only make sense when paired directly with other commands. When a VM is paused, it's easy to ensure that no guest writes occur between individual QMP commands. When a VM is running, this is difficult to accomplish with -individual QMP commands that may allow guest writes to occur inbetween each +individual QMP commands that may allow guest writes to occur between each command. For example, using only individual QMP commands, we could: diff --git a/docs/interop/conf.py b/docs/interop/conf.py index 42ce7e3d365f303b34eb8a16c822da7564b6fa58..2634ca3410a59242c134be6c4a14e399e88c9c4c 100644 --- a/docs/interop/conf.py +++ b/docs/interop/conf.py @@ -19,4 +19,8 @@ man_pages = [ ('qemu-ga', 'qemu-ga', u'QEMU Guest Agent', ['Michael Roth '], 8), + ('qemu-ga-ref', 'qemu-ga-ref', 'QEMU Guest Agent Protocol Reference', + [], 7), + ('qemu-qmp-ref', 'qemu-qmp-ref', 'QEMU QMP Reference Manual', + [], 7), ] diff --git a/docs/interop/dbus.rst b/docs/interop/dbus.rst index 76a5bde625348b062067061bee9a5f44bbd94d97..be596d3f418c14ff5744943b6266195d0560adac 100644 --- a/docs/interop/dbus.rst +++ b/docs/interop/dbus.rst @@ -57,7 +57,7 @@ Depending on the use case, you may choose different scenarios: - Everything the same UID - Convenient for developers - - Improved reliability - crash of one part doens't take + - Improved reliability - crash of one part doesn't take out entire VM - No security benefit over traditional QEMU, unless additional unless additional controls such as SELinux or AppArmor are @@ -87,7 +87,7 @@ For example, to allow only ``qemu`` user to talk to ``qemu-helper`` -dbus-daemon can also perfom SELinux checks based on the security +dbus-daemon can also perform SELinux checks based on the security context of the source and the target. For example, ``virtiofs_t`` could be allowed to send a message to ``svirt_t``, but ``virtiofs_t`` wouldn't be allowed to send a message to ``virtiofs_t``. diff --git a/docs/interop/firmware.json b/docs/interop/firmware.json index 240f565397ae0e754e85976f2d4b5e3873ae8211..989f10b626d223d9bbbcdcc2036ca49c473cb700 100644 --- a/docs/interop/firmware.json +++ b/docs/interop/firmware.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # # Copyright (C) 2018 Red Hat, Inc. # diff --git a/docs/interop/index.rst b/docs/interop/index.rst index 049387ac6deaeb4f6227fc6fd01a97dc0c8a572b..cd78d679d8249977aed44dd64fd1905f8a997536 100644 --- a/docs/interop/index.rst +++ b/docs/interop/index.rst @@ -18,5 +18,8 @@ Contents: live-block-operations pr-helper qemu-ga + qemu-ga-ref + qemu-qmp-ref vhost-user vhost-user-gpu + vhost-vdpa diff --git a/docs/interop/live-block-operations.rst b/docs/interop/live-block-operations.rst index 48afdc7927f64846d3d0dbb39511506c274b9b6e..e13f5a21f8d9cbc8490b05824f4ebd41d0a3fb65 100644 --- a/docs/interop/live-block-operations.rst +++ b/docs/interop/live-block-operations.rst @@ -129,7 +129,7 @@ To show some example invocations of command-line, we will use the following invocation of QEMU, with a QMP server running over UNIX socket:: - $ ./x86_64-softmmu/qemu-system-x86_64 -display none -no-user-config \ + $ ./qemu-system-x86_64 -display none -no-user-config \ -M q35 -nodefaults -m 512 \ -blockdev node-name=node-A,driver=qcow2,file.driver=file,file.node-name=file,file.filename=./a.qcow2 \ -device virtio-blk,drive=node-A,id=virtio0 \ @@ -694,7 +694,7 @@ instance, with the following invocation. (As noted earlier, for simplicity's sake, the destination QEMU is started on the same host, but it could be located elsewhere):: - $ ./x86_64-softmmu/qemu-system-x86_64 -display none -no-user-config \ + $ ./qemu-system-x86_64 -display none -no-user-config \ -M q35 -nodefaults -m 512 \ -blockdev node-name=node-TargetDisk,driver=qcow2,file.driver=file,file.node-name=file,file.filename=./target-disk.qcow2 \ -device virtio-blk,drive=node-TargetDisk,id=virtio0 \ diff --git a/docs/interop/nbd.txt b/docs/interop/nbd.txt index 45118809618e296ac9d2f7cf81957ebdcf04add3..10ce098a29bff89a805392831c90c7230ddb72cd 100644 --- a/docs/interop/nbd.txt +++ b/docs/interop/nbd.txt @@ -17,19 +17,31 @@ namespace "qemu". == "qemu" namespace == -The "qemu" namespace currently contains only one type of context, -related to exposing the contents of a dirty bitmap alongside the -associated disk contents. That context has the following form: +The "qemu" namespace currently contains two available metadata context +types. The first is related to exposing the contents of a dirty +bitmap alongside the associated disk contents. That metadata context +is named with the following form: qemu:dirty-bitmap: Each dirty-bitmap metadata context defines only one flag for extents in reply for NBD_CMD_BLOCK_STATUS: - bit 0: NBD_STATE_DIRTY, means that the extent is "dirty" + bit 0: NBD_STATE_DIRTY, set when the extent is "dirty" + +The second is related to exposing the source of various extents within +the image, with a single metadata context named: + + qemu:allocation-depth + +In the allocation depth context, the entire 32-bit value represents a +depth of which layer in a thin-provisioned backing chain provided the +data (0 for unallocated, 1 for the active layer, 2 for the first +backing layer, and so forth). For NBD_OPT_LIST_META_CONTEXT the following queries are supported -in addition to "qemu:dirty-bitmap:": +in addition to the specific "qemu:allocation-depth" and +"qemu:dirty-bitmap:": * "qemu:" - returns list of all available metadata contexts in the namespace. @@ -53,5 +65,6 @@ the operation of that feature. * 2.12: NBD_CMD_BLOCK_STATUS for "base:allocation" * 3.0: NBD_OPT_STARTTLS with TLS Pre-Shared Keys (PSK), NBD_CMD_BLOCK_STATUS for "qemu:dirty-bitmap:", NBD_CMD_CACHE -* 4.2: NBD_FLAG_CAN_MULTI_CONN for sharable read-only exports, +* 4.2: NBD_FLAG_CAN_MULTI_CONN for shareable read-only exports, NBD_CMD_FLAG_FAST_ZERO +* 5.2: NBD_CMD_BLOCK_STATUS for "qemu:allocation-depth" diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt index cb723463f241bc94cd97a490b235f4a48ac5ead6..0463f761efbb8deadc3e9f429c20bf37dcb4c756 100644 --- a/docs/interop/qcow2.txt +++ b/docs/interop/qcow2.txt @@ -42,6 +42,9 @@ The first cluster of a qcow2 image contains the file header: as the maximum cluster size and won't be able to open images with larger cluster sizes. + Note: if the image has Extended L2 Entries then cluster_bits + must be at least 14 (i.e. 16384 byte clusters). + 24 - 31: size Virtual disk size in bytes. @@ -117,7 +120,12 @@ the next fields through header_length. clusters. The compression_type field must be present and not zero. - Bits 4-63: Reserved (set to 0) + Bit 4: Extended L2 Entries. If this bit is set then + L2 table entries use an extended format that + allows subcluster-based allocation. See the + Extended L2 Entries section for more details. + + Bits 5-63: Reserved (set to 0) 80 - 87: compatible_features Bitmask of compatible features. An implementation can @@ -231,7 +239,7 @@ be stored. Each extension has a structure like the following: Byte 0 - 3: Header extension type: 0x00000000 - End of the header extension area - 0xE2792ACA - Backing file format name string + 0xe2792aca - Backing file format name string 0x6803f857 - Feature name table 0x23852875 - Bitmaps extension 0x0537be77 - Full disk encryption header pointer @@ -498,7 +506,7 @@ cannot be relaxed without an incompatible layout change). Given an offset into the virtual disk, the offset into the image file can be obtained as follows: - l2_entries = (cluster_size / sizeof(uint64_t)) + l2_entries = (cluster_size / sizeof(uint64_t)) [*] l2_index = (offset / cluster_size) % l2_entries l1_index = (offset / cluster_size) / l2_entries @@ -508,6 +516,8 @@ obtained as follows: return cluster_offset + (offset % cluster_size) + [*] this changes if Extended L2 Entries are enabled, see next section + L1 table entry: Bit 0 - 8: Reserved (set to 0) @@ -548,7 +558,8 @@ Standard Cluster Descriptor: nor is data read from the backing file if the cluster is unallocated. - With version 2, this is always 0. + With version 2 or with extended L2 entries (see the next + section), this is always 0. 1 - 8: Reserved (set to 0) @@ -585,6 +596,57 @@ file (except if bit 0 in the Standard Cluster Descriptor is set). If there is no backing file or the backing file is smaller than the image, they shall read zeros for all parts that are not covered by the backing file. +== Extended L2 Entries == + +An image uses Extended L2 Entries if bit 4 is set on the incompatible_features +field of the header. + +In these images standard data clusters are divided into 32 subclusters of the +same size. They are contiguous and start from the beginning of the cluster. +Subclusters can be allocated independently and the L2 entry contains information +indicating the status of each one of them. Compressed data clusters don't have +subclusters so they are treated the same as in images without this feature. + +The size of an extended L2 entry is 128 bits so the number of entries per table +is calculated using this formula: + + l2_entries = (cluster_size / (2 * sizeof(uint64_t))) + +The first 64 bits have the same format as the standard L2 table entry described +in the previous section, with the exception of bit 0 of the standard cluster +descriptor. + +The last 64 bits contain a subcluster allocation bitmap with this format: + +Subcluster Allocation Bitmap (for standard clusters): + + Bit 0 - 31: Allocation status (one bit per subcluster) + + 1: the subcluster is allocated. In this case the + host cluster offset field must contain a valid + offset. + 0: the subcluster is not allocated. In this case + read requests shall go to the backing file or + return zeros if there is no backing file data. + + Bits are assigned starting from the least significant + one (i.e. bit x is used for subcluster x). + + 32 - 63 Subcluster reads as zeros (one bit per subcluster) + + 1: the subcluster reads as zeros. In this case the + allocation status bit must be unset. The host + cluster offset field may or may not be set. + 0: no effect. + + Bits are assigned starting from the least significant + one (i.e. bit x is used for subcluster x - 32). + +Subcluster Allocation Bitmap (for compressed clusters): + + Bit 0 - 63: Reserved (set to 0) + Compressed clusters don't have subclusters, + so this field is not used. == Snapshots == @@ -645,6 +707,11 @@ Snapshot table entry: Byte 48 - 55: Virtual disk size of the snapshot in bytes + Byte 56 - 63: icount value which corresponds to + the record/replay instruction count + when the snapshot was taken. Set to -1 + if icount was disabled + Version 3 images must include extra data at least up to byte 55. diff --git a/docs/interop/qemu-ga-ref.rst b/docs/interop/qemu-ga-ref.rst new file mode 100644 index 0000000000000000000000000000000000000000..3f1c4f908fa85850afe996ba07c48430da8f7ed4 --- /dev/null +++ b/docs/interop/qemu-ga-ref.rst @@ -0,0 +1,13 @@ +QEMU Guest Agent Protocol Reference +=================================== + +.. + TODO: the old Texinfo manual used to note that this manual + is GPL-v2-or-later. We should make that reader-visible + both here and in our Sphinx manuals more generally. + +.. + TODO: display the QEMU version, both here and in our Sphinx manuals + more generally. + +.. qapi-doc:: qga/qapi-schema.json diff --git a/docs/interop/qemu-ga-ref.texi b/docs/interop/qemu-ga-ref.texi deleted file mode 100644 index ddb76ce1c2a1c05ab22a3c666028d3dd55a75a47..0000000000000000000000000000000000000000 --- a/docs/interop/qemu-ga-ref.texi +++ /dev/null @@ -1,80 +0,0 @@ -\input texinfo -@setfilename qemu-ga-ref.info - -@include version.texi - -@exampleindent 0 -@paragraphindent 0 - -@settitle QEMU Guest Agent Protocol Reference - -@iftex -@center @image{docs/qemu_logo} -@end iftex - -@copying -This is the QEMU Guest Agent Protocol reference manual. - -Copyright @copyright{} 2016 The QEMU Project developers - -@quotation -This manual is free documentation: 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 manual 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 manual. If not, see http://www.gnu.org/licenses/. -@end quotation -@end copying - -@dircategory QEMU -@direntry -* QEMU-GA-Ref: (qemu-ga-ref). QEMU Guest Agent Protocol Reference -@end direntry - -@titlepage -@title Guest Agent Protocol Reference Manual -@subtitle QEMU version @value{VERSION} -@page -@vskip 0pt plus 1filll -@insertcopying -@end titlepage - -@contents - -@ifnottex -@node Top -@top QEMU Guest Agent protocol reference -@end ifnottex - -@menu -* API Reference:: -* Commands and Events Index:: -* Data Types Index:: -@end menu - -@node API Reference -@chapter API Reference - -@c for texi2pod: -@c man begin DESCRIPTION - -@include qemu-ga-qapi.texi - -@c man end - -@node Commands and Events Index -@unnumbered Commands and Events Index -@printindex fn - -@node Data Types Index -@unnumbered Data Types Index -@printindex tp - -@bye diff --git a/docs/interop/qemu-qmp-ref.rst b/docs/interop/qemu-qmp-ref.rst new file mode 100644 index 0000000000000000000000000000000000000000..c8abaaf8e3ecb98707355eacfcaa0ea19dd6ed17 --- /dev/null +++ b/docs/interop/qemu-qmp-ref.rst @@ -0,0 +1,13 @@ +QEMU QMP Reference Manual +========================= + +.. + TODO: the old Texinfo manual used to note that this manual + is GPL-v2-or-later. We should make that reader-visible + both here and in our Sphinx manuals more generally. + +.. + TODO: display the QEMU version, both here and in our Sphinx manuals + more generally. + +.. qapi-doc:: qapi/qapi-schema.json diff --git a/docs/interop/qemu-qmp-ref.texi b/docs/interop/qemu-qmp-ref.texi deleted file mode 100644 index bb25758bd0297d47af80be20ac6b9850f41cd2c0..0000000000000000000000000000000000000000 --- a/docs/interop/qemu-qmp-ref.texi +++ /dev/null @@ -1,80 +0,0 @@ -\input texinfo -@setfilename qemu-qmp-ref.info - -@include version.texi - -@exampleindent 0 -@paragraphindent 0 - -@settitle QEMU QMP Reference Manual - -@iftex -@center @image{docs/qemu_logo} -@end iftex - -@copying -This is the QEMU QMP reference manual. - -Copyright @copyright{} 2016 The QEMU Project developers - -@quotation -This manual is free documentation: 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 manual 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 manual. If not, see http://www.gnu.org/licenses/. -@end quotation -@end copying - -@dircategory QEMU -@direntry -* QEMU-QMP-Ref: (qemu-qmp-ref). QEMU QMP Reference Manual -@end direntry - -@titlepage -@title QMP Reference Manual -@subtitle QEMU version @value{VERSION} -@page -@vskip 0pt plus 1filll -@insertcopying -@end titlepage - -@contents - -@ifnottex -@node Top -@top QEMU QMP reference -@end ifnottex - -@menu -* API Reference:: -* Commands and Events Index:: -* Data Types Index:: -@end menu - -@node API Reference -@chapter API Reference - -@c for texi2pod: -@c man begin DESCRIPTION - -@include qemu-qmp-qapi.texi - -@c man end - -@node Commands and Events Index -@unnumbered Commands and Events Index -@printindex fn - -@node Data Types Index -@unnumbered Data Types Index -@printindex tp - -@bye diff --git a/docs/interop/qmp-spec.txt b/docs/interop/qmp-spec.txt index adcf86754d91770d4dbfba8acc15bdb318ebac15..cdf584255568d080325c8614f33c6ffce8625f98 100644 --- a/docs/interop/qmp-spec.txt +++ b/docs/interop/qmp-spec.txt @@ -110,6 +110,9 @@ or if provided. The "id" member can be any json-value. A json-number incremented for each successive command works fine. +The actual commands are documented in the QEMU QMP reference manual +docs/interop/qemu-qmp-ref.{7,html,info,pdf,txt}. + 2.3.1 Out-of-band execution --------------------------- @@ -207,13 +210,13 @@ The format of asynchronous events is: there is a failure to retrieve host time, both members of the timestamp will be set to -1. -For a listing of supported asynchronous events, please, refer to the -qmp-events.txt file. +The actual asynchronous events are documented in the QEMU QMP +reference manual docs/interop/qemu-qmp-ref.{7,html,info,pdf,txt}. Some events are rate-limited to at most one per second. If additional "similar" events arrive within one second, all but the last one are dropped, and the last one is delayed. "Similar" normally means same -event type. See qmp-events.txt for details. +event type. 2.6 Forcing the JSON parser into known-good state ------------------------------------------------- diff --git a/docs/interop/vhost-user-gpu.rst b/docs/interop/vhost-user-gpu.rst index 688f8b425999c6528660c187c3e69becc6cb1d7a..3268bf405ce30726f229e20861535e2a87e6ffb5 100644 --- a/docs/interop/vhost-user-gpu.rst +++ b/docs/interop/vhost-user-gpu.rst @@ -66,7 +66,7 @@ VhostUserGpuCursorPos :scanout-id: ``u32``, the scanout where the cursor is located -:x/y: ``u32``, the cursor postion +:x/y: ``u32``, the cursor position VhostUserGpuCursorUpdate ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/interop/vhost-user.json b/docs/interop/vhost-user.json index ef8ac5941f5c8d14402566a984a0a0876d768c19..feb5fe58cad2b3f8bd3f6be57cac13358feec8ff 100644 --- a/docs/interop/vhost-user.json +++ b/docs/interop/vhost-user.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # # Copyright (C) 2018 Red Hat, Inc. # diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst index 3b1b6602c77932101e1e3b098e35c2497f5b0260..d6085f7045222193c930a2779fe5215047856675 100644 --- a/docs/interop/vhost-user.rst +++ b/docs/interop/vhost-user.rst @@ -131,6 +131,23 @@ A region is: :mmap offset: 64-bit offset where region starts in the mapped memory +Single memory region description +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ++---------+---------------+------+--------------+-------------+ +| padding | guest address | size | user address | mmap offset | ++---------+---------------+------+--------------+-------------+ + +:padding: 64-bit + +:guest address: a 64-bit guest address of the region + +:size: a 64-bit size + +:user address: a 64-bit user address + +:mmap offset: 64-bit offset where region starts in the mapped memory + Log description ^^^^^^^^^^^^^^^ @@ -464,7 +481,7 @@ the ``VHOST_USER_SET_MEM_TABLE`` request. For invalidation events, the (3), the I/O virtual address and the size. On success, the slave is expected to reply with a zero payload, non-zero otherwise. -The slave relies on the slave communcation channel (see :ref:`Slave +The slave relies on the slave communication channel (see :ref:`Slave communication ` section below) to send IOTLB miss and access failure events, by sending ``VHOST_USER_SLAVE_IOTLB_MSG`` requests to the master with a ``struct vhost_iotlb_msg`` as @@ -513,7 +530,7 @@ descriptor table (split virtqueue) or descriptor ring (packed virtqueue). However, it can't work when we process descriptors out-of-order because some entries which store the information of inflight descriptors in available ring (split virtqueue) or descriptor -ring (packed virtqueue) might be overrided by new entries. To solve +ring (packed virtqueue) might be overridden by new entries. To solve this problem, slave need to allocate an extra buffer to store this information of inflight descriptors and share it with master for persistent. ``VHOST_USER_GET_INFLIGHT_FD`` and @@ -815,6 +832,8 @@ Protocol features #define VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD 12 #define VHOST_USER_PROTOCOL_F_RESET_DEVICE 13 #define VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS 14 + #define VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS 15 + #define VHOST_USER_PROTOCOL_F_STATUS 16 Master message types -------------------- @@ -1263,6 +1282,72 @@ Master message types The state.num field is currently reserved and must be set to 0. +``VHOST_USER_GET_MAX_MEM_SLOTS`` + :id: 36 + :equivalent ioctl: N/A + :slave payload: u64 + + When the ``VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS`` protocol + feature has been successfully negotiated, this message is submitted + by master to the slave. The slave should return the message with a + u64 payload containing the maximum number of memory slots for + QEMU to expose to the guest. The value returned by the backend + will be capped at the maximum number of ram slots which can be + supported by the target platform. + +``VHOST_USER_ADD_MEM_REG`` + :id: 37 + :equivalent ioctl: N/A + :slave payload: single memory region description + + When the ``VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS`` protocol + feature has been successfully negotiated, this message is submitted + by the master to the slave. The message payload contains a memory + region descriptor struct, describing a region of guest memory which + the slave device must map in. When the + ``VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS`` protocol feature has + been successfully negotiated, along with the + ``VHOST_USER_REM_MEM_REG`` message, this message is used to set and + update the memory tables of the slave device. + +``VHOST_USER_REM_MEM_REG`` + :id: 38 + :equivalent ioctl: N/A + :slave payload: single memory region description + + When the ``VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS`` protocol + feature has been successfully negotiated, this message is submitted + by the master to the slave. The message payload contains a memory + region descriptor struct, describing a region of guest memory which + the slave device must unmap. When the + ``VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS`` protocol feature has + been successfully negotiated, along with the + ``VHOST_USER_ADD_MEM_REG`` message, this message is used to set and + update the memory tables of the slave device. + +``VHOST_USER_SET_STATUS`` + :id: 39 + :equivalent ioctl: VHOST_VDPA_SET_STATUS + :slave payload: N/A + :master payload: ``u64`` + + When the ``VHOST_USER_PROTOCOL_F_STATUS`` protocol feature has been + successfully negotiated, this message is submitted by the master to + notify the backend with updated device status as defined in the Virtio + specification. + +``VHOST_USER_GET_STATUS`` + :id: 40 + :equivalent ioctl: VHOST_VDPA_GET_STATUS + :slave payload: ``u64`` + :master payload: N/A + + When the ``VHOST_USER_PROTOCOL_F_STATUS`` protocol feature has been + successfully negotiated, this message is submitted by the master to + query the backend for its device status as defined in the Virtio + specification. + + Slave message types ------------------- @@ -1382,7 +1467,7 @@ vhost-user backends can provide various devices & services and may need to be configured manually depending on the use case. However, it is a good idea to follow the conventions listed here when possible. Users, QEMU or libvirt, can then rely on some common -behaviour to avoid heterogenous configuration and management of the +behaviour to avoid heterogeneous configuration and management of the backend programs and facilitate interoperability. Each backend installed on a host system should come with at least one diff --git a/docs/interop/vhost-vdpa.rst b/docs/interop/vhost-vdpa.rst new file mode 100644 index 0000000000000000000000000000000000000000..0c70ba01bc32c8a64aa8de1ab406731125cf9d0c --- /dev/null +++ b/docs/interop/vhost-vdpa.rst @@ -0,0 +1,17 @@ +===================== +Vhost-vdpa Protocol +===================== + +Introduction +============= +vDPA(Virtual data path acceleration) device is a device that uses +a datapath which complies with the virtio specifications with vendor +specific control path. vDPA devices can be both physically located on +the hardware or emulated by software. + +This document describes the vDPA support in qemu + +Here is the kernel commit here +https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4c8cf31885f69e86be0b5b9e6677a26797365e1d + +TODO : More information will add later diff --git a/docs/meson.build b/docs/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..ebd85d59f98625e14ccb4e5b9d3a442243a043eb --- /dev/null +++ b/docs/meson.build @@ -0,0 +1,117 @@ +if get_option('sphinx_build') == '' + sphinx_build = find_program(['sphinx-build-3', 'sphinx-build'], + required: get_option('docs')) +else + sphinx_build = find_program(get_option('sphinx_build'), + required: get_option('docs')) +endif + +# Check if tools are available to build documentation. +build_docs = false +if sphinx_build.found() + SPHINX_ARGS = [sphinx_build] + # If we're making warnings fatal, apply this to Sphinx runs as well + if get_option('werror') + SPHINX_ARGS += [ '-W' ] + endif + + # This is a bit awkward but works: create a trivial document and + # try to run it with our configuration file (which enforces a + # version requirement). This will fail if sphinx-build is too old. + run_command('mkdir', ['-p', tmpdir / 'sphinx']) + run_command('touch', [tmpdir / 'sphinx/index.rst']) + sphinx_build_test_out = run_command(SPHINX_ARGS + [ + '-c', meson.current_source_dir(), + '-b', 'html', tmpdir / 'sphinx', + tmpdir / 'sphinx/out']) + build_docs = (sphinx_build_test_out.returncode() == 0) + + if not build_docs + warning('@0@ is either too old or uses too old a Python version' + .format(sphinx_build.full_path())) + if get_option('docs').enabled() + error('Install a Python 3 version of python-sphinx') + endif + endif +endif + +if build_docs + SPHINX_ARGS += ['-Dversion=' + meson.project_version(), '-Drelease=' + config_host['PKGVERSION']] + + sphinx_extn_depends = [ meson.source_root() / 'docs/sphinx/depfile.py', + meson.source_root() / 'docs/sphinx/hxtool.py', + meson.source_root() / 'docs/sphinx/kerneldoc.py', + meson.source_root() / 'docs/sphinx/kernellog.py', + meson.source_root() / 'docs/sphinx/qapidoc.py', + meson.source_root() / 'docs/sphinx/qmp_lexer.py', + qapi_gen_depends ] + + configure_file(output: 'index.html', + input: files('index.html.in'), + configuration: {'VERSION': meson.project_version()}, + install_dir: qemu_docdir) + manuals = [ 'devel', 'interop', 'tools', 'specs', 'system', 'user' ] + man_pages = { + 'interop' : { + 'qemu-ga.8': (have_tools ? 'man8' : ''), + 'qemu-ga-ref.7': 'man7', + 'qemu-qmp-ref.7': 'man7', + }, + 'tools': { + 'qemu-img.1': (have_tools ? 'man1' : ''), + 'qemu-nbd.8': (have_tools ? 'man8' : ''), + 'qemu-pr-helper.8': (have_tools ? 'man8' : ''), + 'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''), + 'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''), + 'virtiofsd.1': (have_virtiofsd ? 'man1' : ''), + }, + 'system': { + 'qemu.1': 'man1', + 'qemu-block-drivers.7': 'man7', + 'qemu-cpu-models.7': 'man7' + }, + } + + sphinxdocs = [] + sphinxmans = [] + foreach manual : manuals + private_dir = meson.current_build_dir() / (manual + '.p') + output_dir = meson.current_build_dir() / manual + input_dir = meson.current_source_dir() / manual + + this_manual = custom_target(manual + ' manual', + build_by_default: build_docs, + output: [manual + '.stamp'], + input: [files('conf.py'), files(manual / 'conf.py')], + depfile: manual + '.d', + depend_files: sphinx_extn_depends, + command: [SPHINX_ARGS, '-Ddepfile=@DEPFILE@', + '-Ddepfile_stamp=@OUTPUT0@', + '-b', 'html', '-d', private_dir, + input_dir, output_dir]) + sphinxdocs += this_manual + if build_docs and manual != 'devel' + install_subdir(output_dir, install_dir: qemu_docdir) + endif + + these_man_pages = [] + install_dirs = [] + foreach page, section : man_pages.get(manual, {}) + these_man_pages += page + install_dirs += section == '' ? false : get_option('mandir') / section + endforeach + if these_man_pages.length() > 0 + sphinxmans += custom_target(manual + ' man pages', + build_by_default: build_docs, + output: these_man_pages, + input: this_manual, + install: build_docs, + install_dir: install_dirs, + command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir, + input_dir, meson.current_build_dir()]) + endif + endforeach + alias_target('sphinxdocs', sphinxdocs) + alias_target('html', sphinxdocs) + alias_target('man', sphinxmans) +endif diff --git a/docs/nvdimm.txt b/docs/nvdimm.txt index 362e99109e7b8458fcfee4d52194f1a26e1167aa..c2c6e441b34e6141717793a82898e5f60e8daf68 100644 --- a/docs/nvdimm.txt +++ b/docs/nvdimm.txt @@ -132,6 +132,16 @@ address to the page size (getpagesize(2)) by default. However, some types of backends may require an alignment different than the page size. In that case, QEMU v2.12.0 and later provide 'align' option to memory-backend-file to allow users to specify the proper alignment. +For device dax (e.g., /dev/dax0.0), this alignment needs to match the +alignment requirement of the device dax. The NUM of 'align=NUM' option +must be larger than or equal to the 'align' of device dax. +We can use one of the following commands to show the 'align' of device dax. + + ndctl list -X + daxctl list -R + +In order to get the proper 'align' of device dax, you need to install +the library 'libdaxctl'. For example, device dax require the 2 MB alignment, so we can use following QEMU command line options to use it (/dev/dax0.0) as the diff --git a/docs/pvrdma.txt b/docs/pvrdma.txt index 0f0dd8a7e562293961f9747f9ed80a091d393148..5c122fe81813e793e395d834d7b1c2321086102f 100644 --- a/docs/pvrdma.txt +++ b/docs/pvrdma.txt @@ -18,7 +18,7 @@ over-commit and, even if not implemented yet, migration support will be possible with some HW assistance. A project presentation accompany this document: -- http://events.linuxfoundation.org/sites/events/files/slides/lpc-2017-pvrdma-marcel-apfelbaum-yuval-shaia.pdf +- https://blog.linuxplumbersconf.org/2017/ocw/system/presentations/4730/original/lpc-2017-pvrdma-marcel-apfelbaum-yuval-shaia.pdf diff --git a/docs/qcow2-cache.txt b/docs/qcow2-cache.txt index d57f40986139ba167e2372cb90c3381606daf0c7..5f763aa6bbfe3700ba1324d04064589c7a2a447b 100644 --- a/docs/qcow2-cache.txt +++ b/docs/qcow2-cache.txt @@ -1,6 +1,6 @@ qcow2 L2/refcount cache configuration ===================================== -Copyright (C) 2015, 2018 Igalia, S.L. +Copyright (C) 2015, 2018-2020 Igalia, S.L. Author: Alberto Garcia This work is licensed under the terms of the GNU GPL, version 2 or @@ -222,3 +222,20 @@ support this functionality, and is 0 (disabled) on other platforms. This functionality currently relies on the MADV_DONTNEED argument for madvise() to actually free the memory. This is a Linux-specific feature, so cache-clean-interval is not supported on other systems. + + +Extended L2 Entries +------------------- +All numbers shown in this document are valid for qcow2 images with normal +64-bit L2 entries. + +Images with extended L2 entries need twice as much L2 metadata, so the L2 +cache size must be twice as large for the same disk space. + + disk_size = l2_cache_size * cluster_size / 16 + +i.e. + + l2_cache_size = disk_size * 16 / cluster_size + +Refcount blocks are not affected by this. diff --git a/docs/qdev-device-use.txt b/docs/qdev-device-use.txt index cc53e97dcdaa0d02850f242b6047d6cf32ab9a99..245cdf29c7635084fd55b5425afb9411285b7368 100644 --- a/docs/qdev-device-use.txt +++ b/docs/qdev-device-use.txt @@ -104,15 +104,10 @@ The -device argument differs in detail for each type of drive: * if=floppy - -global isa-fdc.driveA=DRIVE-ID - -global isa-fdc.driveB=DRIVE-ID + -device floppy,unit=UNIT,drive=DRIVE-ID - This is -global instead of -device, because the floppy controller is - created automatically, and we want to configure that one, not create - a second one (which isn't possible anyway). - - Without any -global isa-fdc,... you get an empty driveA and no - driveB. You can use -nodefaults to suppress the default driveA, see + Without any -device floppy,... you get an empty unit 0 and no unit + 1. You can use -nodefaults to suppress the default unit 0, see "Default Devices". * if=virtio @@ -130,12 +125,14 @@ The -device argument differs in detail for each type of drive: * if=pflash, if=mtd, if=sd, if=xen are not yet available with -device -For USB devices, the old way is actually different: +For USB devices, the old way was actually different: -usbdevice disk:format=FMT:FILENAME -Provides much less control than -drive's OPTS... The new way fixes -that: +"Was" because "disk:" is gone since v2.12.0. + +The old way provided much less control than -drive's OPTS... The new +way fixes that: -device usb-storage,drive=DRIVE-ID,removable=RMB @@ -182,14 +179,15 @@ The appropriate DEVNAME depends on the machine type. For type "pc": This lets you control I/O ports and IRQs. -* -usbdevice serial::chardev becomes -device usb-serial,chardev=dev. - * -usbdevice braille doesn't support LEGACY-CHARDEV syntax. It always uses "braille". With -device, this useful default is gone, so you have to use something like -device usb-braille,chardev=braille -chardev braille,id=braille +* -usbdevice serial::chardev is gone since v2.12.0. It became + -device usb-serial,chardev=dev. + LEGACY-CHARDEV translates to -chardev HOST-OPTS... as follows: * null becomes -chardev null @@ -243,10 +241,12 @@ The old way to define the guest part looks like this: -net nic,netdev=NET-ID,macaddr=MACADDR,model=MODEL,name=ID,addr=STR,vectors=V -Except for USB it looks like this: +Except for USB it looked like this: -usbdevice net:netdev=NET-ID,macaddr=MACADDR,name=ID +"Looked" because "net:" is gone since v2.12.0. + The new way is -device: -device DEVNAME,netdev=NET-ID,mac=MACADDR,DEV-OPTS... @@ -341,12 +341,15 @@ The new way is -device DEVNAME,DEV-OPTS... Details depend on DRIVER: * mouse -device usb-mouse * tablet -device usb-tablet * wacom-tablet -device usb-wacom-tablet +* u2f -device u2f-{emulated,passthru} +* braille See "Character Devices" + +Until v2.12.0, we additionally had + * host:... See "Host Device Assignment" * disk:... See "Block Devices" * serial:... See "Character Devices" -* braille See "Character Devices" * net:... See "Network Devices" -* bt:... not yet available with -device === Watchdog Devices === @@ -363,17 +366,18 @@ and host USB devices. PCI devices can only be assigned with -device: -device vfio-pci,host=ADDR,id=ID -The old way to assign a host USB device is +The old way to assign a USB host device -usbdevice host:auto:BUS.ADDR:VID:PRID -where any of BUS, ADDR, VID, PRID can be the wildcard *. +was removed in v2.12.0. Any of BUS, ADDR, VID, PRID could be the +wildcard *. The new way is -device usb-host,hostbus=BUS,hostaddr=ADDR,vendorid=VID,productid=PRID -Omitted options match anything, just like the old way's wildcard. +Omitted options match anything. === Default Devices === @@ -385,12 +389,12 @@ some DEVNAMEs: default device suppressing DEVNAMEs CD-ROM ide-cd, ide-drive, ide-hd, scsi-cd, scsi-hd - isa-fdc's driveA floppy, isa-fdc + floppy floppy, isa-fdc parallel isa-parallel serial isa-serial VGA VGA, cirrus-vga, isa-vga, isa-cirrus-vga, - vmware-svga, qxl-vga, virtio-vga - virtioconsole virtio-serial-pci, virtio-serial + vmware-svga, qxl-vga, virtio-vga, ati-vga, + vhost-user-vga The default NIC is connected to a default part created along with it. It is *not* suppressed by configuring a NIC with -device (you may call diff --git a/docs/qemu-option-trace.rst.inc b/docs/qemu-option-trace.rst.inc index 7e09773a9c518f6a47e9262b66c6016b21a61762..d7acbe67f737a0f86aad06a732b6edca2735b8e3 100644 --- a/docs/qemu-option-trace.rst.inc +++ b/docs/qemu-option-trace.rst.inc @@ -1,7 +1,7 @@ Specify tracing options. -.. option:: [enable=]PATTERN +``[enable=]PATTERN`` Immediately enable events matching *PATTERN* (either event name or a globbing pattern). This option is only @@ -11,7 +11,7 @@ Specify tracing options. Use :option:`-trace help` to print a list of names of trace points. -.. option:: events=FILE +``events=FILE`` Immediately enable events listed in *FILE*. The file must contain one event name (as listed in the ``trace-events-all`` @@ -19,7 +19,7 @@ Specify tracing options. available if QEMU has been compiled with the ``simple``, ``log`` or ``ftrace`` tracing backend. -.. option:: file=FILE +``file=FILE`` Log output traces to *FILE*. This option is only available if QEMU has been compiled with diff --git a/docs/rdma.txt b/docs/rdma.txt index a86e992c84538609876baf26291fb5c3edbd4c9d..49dc9f8bcab4059a7b133603ae0dbae6ac24d1fb 100644 --- a/docs/rdma.txt +++ b/docs/rdma.txt @@ -261,7 +261,7 @@ qemu_rdma_exchange_send(header, data, optional response header & data): of the connection (described below). All of the remaining command types (not including 'ready') -described above all use the aformentioned two functions to do the hard work: +described above all use the aforementioned two functions to do the hard work: 1. After connection setup, RAMBlock information is exchanged using this protocol before the actual migration begins. This information includes diff --git a/docs/replay.txt b/docs/replay.txt index 70c27edb362105cf5886141d048f6b885763c244..5b008ca4911f72204ec84e393dd5cbddded4bce2 100644 --- a/docs/replay.txt +++ b/docs/replay.txt @@ -184,11 +184,11 @@ is then incremented (which is called "warping" the virtual clock) as soon as the timer fires or the CPUs need to go out of the idle state. Two functions are used for this purpose; because these actions change virtual machine state and must be deterministic, each of them creates a -checkpoint. qemu_start_warp_timer checks if the CPUs are idle and if so -starts accounting real time to virtual clock. qemu_account_warp_timer +checkpoint. icount_start_warp_timer checks if the CPUs are idle and if so +starts accounting real time to virtual clock. icount_account_warp_timer is called when the CPUs get an interrupt or when the warp timer fires, and it warps the virtual clock by the amount of real time that has passed -since qemu_start_warp_timer. +since icount_start_warp_timer. Bottom halves ------------- @@ -265,6 +265,16 @@ of the original disk image, use overlay files linked to the original images. Therefore all new snapshots (including the starting one) will be saved in overlays and the original image remains unchanged. +When you need to use snapshots with diskless virtual machine, +it must be started with 'orphan' qcow2 image. This image will be used +for storing VM snapshots. Here is the example of the command line for this: + + qemu-system-i386 -icount shift=3,rr=replay,rrfile=record.bin,rrsnapshot=init \ + -net none -drive file=empty.qcow2,if=none,id=rr + +empty.qcow2 drive does not connected to any virtual block device and used +for VM snapshots only. + Network devices --------------- @@ -294,6 +304,42 @@ for recording and replaying must contain identical number of ports in record and replay modes, but their backends may differ. E.g., '-serial stdio' in record mode, and '-serial null' in replay mode. +Reverse debugging +----------------- + +Reverse debugging allows "executing" the program in reverse direction. +GDB remote protocol supports "reverse step" and "reverse continue" +commands. The first one steps single instruction backwards in time, +and the second one finds the last breakpoint in the past. + +Recorded executions may be used to enable reverse debugging. QEMU can't +execute the code in backwards direction, but can load a snapshot and +replay forward to find the desired position or breakpoint. + +The following GDB commands are supported: + - reverse-stepi (or rsi) - step one instruction backwards + - reverse-continue (or rc) - find last breakpoint in the past + +Reverse step loads the nearest snapshot and replays the execution until +the required instruction is met. + +Reverse continue may include several passes of examining the execution +between the snapshots. Each of the passes include the following steps: + 1. loading the snapshot + 2. replaying to examine the breakpoints + 3. if breakpoint or watchpoint was met + - loading the snapshot again + - replaying to the required breakpoint + 4. else + - proceeding to the p.1 with the earlier snapshot + +Therefore usage of the reverse debugging requires at least one snapshot +created in advance. This can be done by omitting 'snapshot' option +for the block drives and adding 'rrsnapshot' for both record and replay +command lines. +See the "Snapshotting" section to learn more about running record/replay +and creating the snapshot in these modes. + Replay log format ----------------- diff --git a/docs/specs/_templates/editpage.html b/docs/specs/_templates/editpage.html new file mode 100644 index 0000000000000000000000000000000000000000..aaa468aa98df19cc1bf8012bd06899103fe559a5 --- /dev/null +++ b/docs/specs/_templates/editpage.html @@ -0,0 +1,5 @@ +
+ +
diff --git a/docs/specs/fw_cfg.txt b/docs/specs/fw_cfg.txt index 8f1ebc66fa4a3fe04f898597a58f1c96576d9d30..3e6d586f66bfb7a54025c24902b9ea9fe3ee5795 100644 --- a/docs/specs/fw_cfg.txt +++ b/docs/specs/fw_cfg.txt @@ -219,7 +219,7 @@ To check the result, read the "control" field: = Externally Provided Items = -As of v2.4, "file" fw_cfg items (i.e., items with selector keys above +Since v2.4, "file" fw_cfg items (i.e., items with selector keys above FW_CFG_FILE_FIRST, and with a corresponding entry in the fw_cfg file directory structure) may be inserted via the QEMU command line, using the following syntax: @@ -230,6 +230,13 @@ Or -fw_cfg [name=],string= +Since v5.1, QEMU allows some objects to generate fw_cfg-specific content, +the content is then associated with a "file" item using the 'gen_id' option +in the command line, using the following syntax: + + -object ,id=,[generator-specific-options] \ + -fw_cfg [name=],gen_id= + See QEMU man page for more documentation. Using item_name with plain ASCII characters only is recommended. @@ -251,4 +258,8 @@ Prefix "opt/org.qemu/" is reserved for QEMU itself. Use of names not beginning with "opt/" is potentially dangerous and entirely unsupported. QEMU will warn if you try. +Use of names not beginning with "opt/" is tolerated with 'gen_id' (that +is, the warning is suppressed), but you must know exactly what you're +doing. + All externally provided fw_cfg items are read-only to the guest. diff --git a/docs/specs/index.rst b/docs/specs/index.rst index 426632a4755e3269e57e449b264f1cf3abd03b2a..1b0eb979d581531f307c6b6f15dd1552342ad8e3 100644 --- a/docs/specs/index.rst +++ b/docs/specs/index.rst @@ -12,6 +12,7 @@ Contents: ppc-xive ppc-spapr-xive + ppc-spapr-numa acpi_hw_reduced_hotplug tpm acpi_hest_ghes diff --git a/docs/specs/nvme.txt b/docs/specs/nvme.txt new file mode 100644 index 0000000000000000000000000000000000000000..56d393884e7a1407d4656fc8cc34898986c5fa36 --- /dev/null +++ b/docs/specs/nvme.txt @@ -0,0 +1,23 @@ +NVM Express Controller +====================== + +The nvme device (-device nvme) emulates an NVM Express Controller. + + +Reference Specifications +------------------------ + +The device currently implements most mandatory features of NVMe v1.3d, see + + https://nvmexpress.org/resources/specifications/ + +for the specification. + + +Known issues +------------ + +* The accounting numbers in the SMART/Health are reset across power cycles + +* Interrupt Coalescing is not supported and is disabled by default in volation + of the specification. diff --git a/docs/specs/pci-ids.txt b/docs/specs/pci-ids.txt index 4d53e5c7d9d527df0369ec02265ce84382be3b86..abbdbca6be382afc6cc2f3e30fcc0023e06329ce 100644 --- a/docs/specs/pci-ids.txt +++ b/docs/specs/pci-ids.txt @@ -63,6 +63,7 @@ PCI devices (other than virtio): 1b36:000b PCIe Expander Bridge (-device pxb-pcie) 1b36:000d PCI xhci usb host adapter 1b36:000f mdpy (mdev sample device), linux/samples/vfio-mdev/mdpy.c +1b36:0010 PCIe NVMe device (-device nvme) All these devices are documented in docs/specs. diff --git a/docs/specs/ppc-spapr-hotplug.txt b/docs/specs/ppc-spapr-hotplug.txt index 859d52cce6c80dafff69a3e892faf13de968f72e..d4fb2d46d950bc7df71e2bbc0cfe0c2469a21de3 100644 --- a/docs/specs/ppc-spapr-hotplug.txt +++ b/docs/specs/ppc-spapr-hotplug.txt @@ -371,7 +371,7 @@ ibm,dynamic-memory This property describes the dynamically reconfigurable memory. It is a property encoded array that has an integer N, the number of LMBs followed -by N LMB list entires. +by N LMB list entries. Each LMB list entry consists of the following elements: @@ -390,7 +390,7 @@ Each LMB list entry consists of the following elements: ibm,dynamic-memory-v2 This property describes the dynamically reconfigurable memory. This is -an alternate and newer way to describe dyanamically reconfigurable memory. +an alternate and newer way to describe dynamically reconfigurable memory. It is a property encoded array that has an integer N (the number of LMB set entries) followed by N LMB set entries. There is an LMB set entry for each sequential group of LMBs that share common attributes. diff --git a/docs/specs/ppc-spapr-numa.rst b/docs/specs/ppc-spapr-numa.rst new file mode 100644 index 0000000000000000000000000000000000000000..ffa687dc89da79e2e01ecad6f3beb85b2266db67 --- /dev/null +++ b/docs/specs/ppc-spapr-numa.rst @@ -0,0 +1,410 @@ + +NUMA mechanics for sPAPR (pseries machines) +============================================ + +NUMA in sPAPR works different than the System Locality Distance +Information Table (SLIT) in ACPI. The logic is explained in the LOPAPR +1.1 chapter 15, "Non Uniform Memory Access (NUMA) Option". This +document aims to complement this specification, providing details +of the elements that impacts how QEMU views NUMA in pseries. + +Associativity and ibm,associativity property +-------------------------------------------- + +Associativity is defined as a group of platform resources that has +similar mean performance (or in our context here, distance) relative to +everyone else outside of the group. + +The format of the ibm,associativity property varies with the value of +bit 0 of byte 5 of the ibm,architecture-vec-5 property. The format with +bit 0 equal to zero is deprecated. The current format, with the bit 0 +with the value of one, makes ibm,associativity property represent the +physical hierarchy of the platform, as one or more lists that starts +with the highest level grouping up to the smallest. Considering the +following topology: + +:: + + Mem M1 ---- Proc P1 | + ----------------- | Socket S1 ---| + chip C1 | | + | HW module 1 (MOD1) + Mem M2 ---- Proc P2 | | + ----------------- | Socket S2 ---| + chip C2 | + +The ibm,associativity property for the processors would be: + +* P1: {MOD1, S1, C1, P1} +* P2: {MOD1, S2, C2, P2} + +Each allocable resource has an ibm,associativity property. The LOPAPR +specification allows multiple lists to be present in this property, +considering that the same resource can have multiple connections to the +platform. + +Relative Performance Distance and ibm,associativity-reference-points +-------------------------------------------------------------------- + +The ibm,associativity-reference-points property is an array that is used +to define the relevant performance/distance related boundaries, defining +the NUMA levels for the platform. + +The definition of its elements also varies with the value of bit 0 of byte 5 +of the ibm,architecture-vec-5 property. The format with bit 0 equal to zero +is also deprecated. With the current format, each integer of the +ibm,associativity-reference-points represents an 1 based ordinal index (i.e. +the first element is 1) of the ibm,associativity array. The first +boundary is the most significant to application performance, followed by +less significant boundaries. Allocated resources that belongs to the +same performance boundaries are expected to have relative NUMA distance +that matches the relevancy of the boundary itself. Resources that belongs +to the same first boundary will have the shortest distance from each +other. Subsequent boundaries represents greater distances and degraded +performance. + +Using the previous example, the following setting reference points defines +three NUMA levels: + +* ibm,associativity-reference-points = {0x3, 0x2, 0x1} + +The first NUMA level (0x3) is interpreted as the third element of each +ibm,associativity array, the second level is the second element and +the third level is the first element. Let's also consider that elements +belonging to the first NUMA level have distance equal to 10 from each +other, and each NUMA level doubles the distance from the previous. This +means that the second would be 20 and the third level 40. For the P1 and +P2 processors, we would have the following NUMA levels: + +:: + + * ibm,associativity-reference-points = {0x3, 0x2, 0x1} + + * P1: associativity{MOD1, S1, C1, P1} + + First NUMA level (0x3) => associativity[2] = C1 + Second NUMA level (0x2) => associativity[1] = S1 + Third NUMA level (0x1) => associativity[0] = MOD1 + + * P2: associativity{MOD1, S2, C2, P2} + + First NUMA level (0x3) => associativity[2] = C2 + Second NUMA level (0x2) => associativity[1] = S2 + Third NUMA level (0x1) => associativity[0] = MOD1 + + P1 and P2 have the same third NUMA level, MOD1: Distance between them = 40 + +Changing the ibm,associativity-reference-points array changes the performance +distance attributes for the same associativity arrays, as the following +example illustrates: + +:: + + * ibm,associativity-reference-points = {0x2} + + * P1: associativity{MOD1, S1, C1, P1} + + First NUMA level (0x2) => associativity[1] = S1 + + * P2: associativity{MOD1, S2, C2, P2} + + First NUMA level (0x2) => associativity[1] = S2 + + P1 and P2 does not have a common performance boundary. Since this is a one level + NUMA configuration, distance between them is one boundary above the first + level, 20. + + +In a hypothetical platform where all resources inside the same hardware module +is considered to be on the same performance boundary: + +:: + + * ibm,associativity-reference-points = {0x1} + + * P1: associativity{MOD1, S1, C1, P1} + + First NUMA level (0x1) => associativity[0] = MOD0 + + * P2: associativity{MOD1, S2, C2, P2} + + First NUMA level (0x1) => associativity[0] = MOD0 + + P1 and P2 belongs to the same first order boundary. The distance between then + is 10. + + +How the pseries Linux guest calculates NUMA distances +===================================================== + +Another key difference between ACPI SLIT and the LOPAPR regarding NUMA is +how the distances are expressed. The SLIT table provides the NUMA distance +value between the relevant resources. LOPAPR does not provide a standard +way to calculate it. We have the ibm,associativity for each resource, which +provides a common-performance hierarchy, and the ibm,associativity-reference-points +array that tells which level of associativity is considered to be relevant +or not. + +The result is that each OS is free to implement and to interpret the distance +as it sees fit. For the pseries Linux guest, each level of NUMA duplicates +the distance of the previous level, and the maximum amount of levels is +limited to MAX_DISTANCE_REF_POINTS = 4 (from arch/powerpc/mm/numa.c in the +kernel tree). This results in the following distances: + +* both resources in the first NUMA level: 10 +* resources one NUMA level apart: 20 +* resources two NUMA levels apart: 40 +* resources three NUMA levels apart: 80 +* resources four NUMA levels apart: 160 + + +pseries NUMA mechanics +====================== + +Starting in QEMU 5.2, the pseries machine considers user input when setting NUMA +topology of the guest. The overall design is: + +* ibm,associativity-reference-points is set to {0x4, 0x3, 0x2, 0x1}, allowing + for 4 distinct NUMA distance values based on the NUMA levels + +* ibm,max-associativity-domains supports multiple associativity domains in all + NUMA levels, granting user flexibility + +* ibm,associativity for all resources varies with user input + +These changes are only effective for pseries-5.2 and newer machines that are +created with more than one NUMA node (disconsidering NUMA nodes created by +the machine itself, e.g. NVLink 2 GPUs). The now legacy support has been +around for such a long time, with users seeing NUMA distances 10 and 40 +(and 80 if using NVLink2 GPUs), and there is no need to disrupt the +existing experience of those guests. + +To bring the user experience x86 users have when tuning up NUMA, we had +to operate under the current pseries Linux kernel logic described in +`How the pseries Linux guest calculates NUMA distances`_. The result +is that we needed to translate NUMA distance user input to pseries +Linux kernel input. + +Translating user distance to kernel distance +-------------------------------------------- + +User input for NUMA distance can vary from 10 to 254. We need to translate +that to the values that the Linux kernel operates on (10, 20, 40, 80, 160). +This is how it is being done: + +* user distance 11 to 30 will be interpreted as 20 +* user distance 31 to 60 will be interpreted as 40 +* user distance 61 to 120 will be interpreted as 80 +* user distance 121 and beyond will be interpreted as 160 +* user distance 10 stays 10 + +The reasoning behind this approximation is to avoid any round up to the local +distance (10), keeping it exclusive to the 4th NUMA level (which is still +exclusive to the node_id). All other ranges were chosen under the developer +discretion of what would be (somewhat) sensible considering the user input. +Any other strategy can be used here, but in the end the reality is that we'll +have to accept that a large array of values will be translated to the same +NUMA topology in the guest, e.g. this user input: + +:: + + 0 1 2 + 0 10 31 120 + 1 31 10 30 + 2 120 30 10 + +And this other user input: + +:: + + 0 1 2 + 0 10 60 61 + 1 60 10 11 + 2 61 11 10 + +Will both be translated to the same values internally: + +:: + + 0 1 2 + 0 10 40 80 + 1 40 10 20 + 2 80 20 10 + +Users are encouraged to use only the kernel values in the NUMA definition to +avoid being taken by surprise with that the guest is actually seeing in the +topology. There are enough potential surprises that are inherent to the +associativity domain assignment process, discussed below. + + +How associativity domains are assigned +-------------------------------------- + +LOPAPR allows more than one associativity array (or 'string') per allocated +resource. This would be used to represent that the resource has multiple +connections with the board, and then the operational system, when deciding +NUMA distancing, should consider the associativity information that provides +the shortest distance. + +The spapr implementation does not support multiple associativity arrays per +resource, neither does the pseries Linux kernel. We'll have to represent the +NUMA topology using one associativity per resource, which means that choices +and compromises are going to be made. + +Consider the following NUMA topology entered by user input: + +:: + + 0 1 2 3 + 0 10 40 20 40 + 1 40 10 80 40 + 2 20 80 10 20 + 3 40 40 20 10 + +All the associativity arrays are initialized with NUMA id in all associativity +domains: + +* node 0: 0 0 0 0 +* node 1: 1 1 1 1 +* node 2: 2 2 2 2 +* node 3: 3 3 3 3 + + +Honoring just the relative distances of node 0 to every other node, we find the +NUMA level matches (considering the reference points {0x4, 0x3, 0x2, 0x1}) for +each distance: + +* distance from 0 to 1 is 40 (no match at 0x4 and 0x3, will match + at 0x2) +* distance from 0 to 2 is 20 (no match at 0x4, will match at 0x3) +* distance from 0 to 3 is 40 (no match at 0x4 and 0x3, will match + at 0x2) + +We'll copy the associativity domains of node 0 to all other nodes, based on +the NUMA level matches. Between 0 and 1, a match in 0x2, we'll also copy +the domains 0x2 and 0x1 from 0 to 1 as well. This will give us: + +* node 0: 0 0 0 0 +* node 1: 0 0 1 1 + +Doing the same to node 2 and node 3, these are the associativity arrays +after considering all matches with node 0: + +* node 0: 0 0 0 0 +* node 1: 0 0 1 1 +* node 2: 0 0 0 2 +* node 3: 0 0 3 3 + +The distances related to node 0 are accounted for. For node 1, and keeping +in mind that we don't need to revisit node 0 again, the distance from +node 1 to 2 is 80, matching at 0x1, and distance from 1 to 3 is 40, +match in 0x2. Repeating the same logic of copying all domains up to +the NUMA level match: + +* node 0: 0 0 0 0 +* node 1: 1 0 1 1 +* node 2: 1 0 0 2 +* node 3: 1 0 3 3 + +In the last step we will analyze just nodes 2 and 3. The desired distance +between 2 and 3 is 20, i.e. a match in 0x3: + +* node 0: 0 0 0 0 +* node 1: 1 0 1 1 +* node 2: 1 0 0 2 +* node 3: 1 0 0 3 + + +The kernel will read these arrays and will calculate the following NUMA topology for +the guest: + +:: + + 0 1 2 3 + 0 10 40 20 20 + 1 40 10 40 40 + 2 20 40 10 20 + 3 20 40 20 10 + +Note that this is not what the user wanted - the desired distance between +0 and 3 is 40, we calculated it as 20. This is what the current logic and +implementation constraints of the kernel and QEMU will provide inside the +LOPAPR specification. + +Users are welcome to use this knowledge and experiment with the input to get +the NUMA topology they want, or as closer as they want. The important thing +is to keep expectations up to par with what we are capable of provide at this +moment: an approximation. + +Limitations of the implementation +--------------------------------- + +As mentioned above, the pSeries NUMA distance logic is, in fact, a way to approximate +user choice. The Linux kernel, and PAPR itself, does not provide QEMU with the ways +to fully map user input to actual NUMA distance the guest will use. These limitations +creates two notable limitations in our support: + +* Asymmetrical topologies aren't supported. We only support NUMA topologies where + the distance from node A to B is always the same as B to A. We do not support + any A-B pair where the distance back and forth is asymmetric. For example, the + following topology isn't supported and the pSeries guest will not boot with this + user input: + +:: + + 0 1 + 0 10 40 + 1 20 10 + + +* 'non-transitive' topologies will be poorly translated to the guest. This is the + kind of topology where the distance from a node A to B is X, B to C is X, but + the distance A to C is not X. E.g.: + +:: + + 0 1 2 3 + 0 10 20 20 40 + 1 20 10 80 40 + 2 20 80 10 20 + 3 40 40 20 10 + + In the example above, distance 0 to 2 is 20, 2 to 3 is 20, but 0 to 3 is 40. + The kernel will always match with the shortest associativity domain possible, + and we're attempting to retain the previous established relations between the + nodes. This means that a distance equal to 20 between nodes 0 and 2 and the + same distance 20 between nodes 2 and 3 will cause the distance between 0 and 3 + to also be 20. + + +Legacy (5.1 and older) pseries NUMA mechanics +============================================= + +In short, we can summarize the NUMA distances seem in pseries Linux guests, using +QEMU up to 5.1, as follows: + +* local distance, i.e. the distance of the resource to its own NUMA node: 10 +* if it's a NVLink GPU device, distance: 80 +* every other resource, distance: 40 + +The way the pseries Linux guest calculates NUMA distances has a direct effect +on what QEMU users can expect when doing NUMA tuning. As of QEMU 5.1, this is +the default ibm,associativity-reference-points being used in the pseries +machine: + +ibm,associativity-reference-points = {0x4, 0x4, 0x2} + +The first and second level are equal, 0x4, and a third one was added in +commit a6030d7e0b35 exclusively for NVLink GPUs support. This means that +regardless of how the ibm,associativity properties are being created in +the device tree, the pseries Linux guest will only recognize three scenarios +as far as NUMA distance goes: + +* if the resources belongs to the same first NUMA level = 10 +* second level is skipped since it's equal to the first +* all resources that aren't a NVLink GPU, it is guaranteed that they will belong + to the same third NUMA level, having distance = 40 +* for NVLink GPUs, distance = 80 from everything else + +This also means that user input in QEMU command line does not change the +NUMA distancing inside the guest for the pseries machine. diff --git a/docs/specs/ppc-spapr-xive.rst b/docs/specs/ppc-spapr-xive.rst index 6159bc6eed6205a3d5c6621ebc4fb71081c2b583..f47f739e0190fbf70ac49b5f0d83edf7829747dd 100644 --- a/docs/specs/ppc-spapr-xive.rst +++ b/docs/specs/ppc-spapr-xive.rst @@ -46,7 +46,7 @@ default mode. ``dual`` means that both modes XICS **and** XIVE are supported and if the guest OS supports XIVE, this mode will be selected. -The choosen interrupt mode is activated after a reconfiguration done +The chosen interrupt mode is activated after a reconfiguration done in a machine reset. KVM negotiation @@ -61,6 +61,11 @@ depend on the XIVE KVM capability of the host. On older kernels without XIVE KVM support, QEMU will use the emulated XIVE device as a fallback and on newer kernels (>=5.2), the KVM XIVE device. +XIVE native exploitation mode is not supported for KVM nested guests, +VMs running under a L1 hypervisor (KVM on pSeries). In that case, the +hypervisor will not advertise the KVM capability and QEMU will use the +emulated XIVE device, same as for older versions of KVM. + As a final refinement, the user can also switch the use of the KVM device with the machine option ``kernel_irqchip``. @@ -121,6 +126,9 @@ xics XICS KVM XICS emul. XICS KVM (1) QEMU warns with ``warning: kernel_irqchip requested but unavailable: IRQ_XIVE capability must be present for KVM`` + In some cases (old host kernels or KVM nested guests), one may hit a + QEMU/KVM incompatibility due to device destruction in reset. QEMU fails + with ``KVM is incompatible with ic-mode=dual,kernel-irqchip=on`` (2) QEMU fails with ``kernel_irqchip requested but unavailable: IRQ_XIVE capability must be present for KVM`` @@ -143,14 +151,14 @@ xics XICS KVM XICS emul. XICS KVM mode (XICS), either don't set the ic-mode machine property or try ic-mode=xics or ic-mode=dual`` (4) QEMU/KVM incompatibility due to device destruction in reset. QEMU fails - with ``KVM is too old to support ic-mode=dual,kernel-irqchip=on`` + with ``KVM is incompatible with ic-mode=dual,kernel-irqchip=on`` XIVE Device tree properties --------------------------- The properties for the PAPR interrupt controller node when the *XIVE -native exploitation mode* is selected shoud contain: +native exploitation mode* is selected should contain: - ``device_type`` diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst index 5e61238bc5fe3c74a11ecd8b0202ef13d7fb83b9..5e9aef4db312038aa794399618b7c0a777101fd6 100644 --- a/docs/specs/tpm.rst +++ b/docs/specs/tpm.rst @@ -199,8 +199,8 @@ to be used with the passthrough backend or the swtpm backend. QEMU files related to TPM backends: - ``backends/tpm.c`` + - ``include/sysemu/tpm.h`` - ``include/sysemu/tpm_backend.h`` - - ``include/sysemu/tpm_backend_int.h`` The QEMU TPM passthrough device ------------------------------- @@ -232,9 +232,9 @@ Integrity Measurement Architecture (IMA), are not expecting to share PCRs. QEMU files related to the TPM passthrough device: - - ``hw/tpm/tpm_passthrough.c`` - - ``hw/tpm/tpm_util.c`` - - ``hw/tpm/tpm_util.h`` + - ``backends/tpm/tpm_passthrough.c`` + - ``backends/tpm/tpm_util.c`` + - ``include/sysemu/tpm_util.h`` Command line to start QEMU with the TPM passthrough device using the host's @@ -292,9 +292,9 @@ instrumented to initialize a TPM 1.2 or TPM 2 device using this command. QEMU files related to the TPM emulator device: - - ``hw/tpm/tpm_emulator.c`` - - ``hw/tpm/tpm_util.c`` - - ``hw/tpm/tpm_util.h`` + - ``backends/tpm/tpm_emulator.c`` + - ``backends/tpm/tpm_util.c`` + - ``include/sysemu/tpm_util.h`` The following commands start the swtpm with a UnixIO control channel over a socket interface. They do not need to be run as root. @@ -346,8 +346,6 @@ In case an Arm virt machine is emulated, use the following command line: -drive if=pflash,format=raw,file=flash0.img,readonly \ -drive if=pflash,format=raw,file=flash1.img - On Arm, ACPI boot with TPM is not yet supported. - In case SeaBIOS is used as firmware, it should show the TPM menu item after entering the menu with 'ESC'. diff --git a/docs/sphinx/depfile.py b/docs/sphinx/depfile.py new file mode 100644 index 0000000000000000000000000000000000000000..277fdf0f56806d2fc58dbdf65200bdbb29c11194 --- /dev/null +++ b/docs/sphinx/depfile.py @@ -0,0 +1,51 @@ +# coding=utf-8 +# +# QEMU depfile generation extension +# +# Copyright (c) 2020 Red Hat, Inc. +# +# This work is licensed under the terms of the GNU GPLv2 or later. +# See the COPYING file in the top-level directory. + +"""depfile is a Sphinx extension that writes a dependency file for + an external build system""" + +import os +import sphinx + +__version__ = '1.0' + +def get_infiles(env): + for x in env.found_docs: + yield env.doc2path(x) + yield from ((os.path.join(env.srcdir, dep) + for dep in env.dependencies[x])) + +def write_depfile(app, env): + if not env.config.depfile: + return + + # Using a directory as the output file does not work great because + # its timestamp does not necessarily change when the contents change. + # So create a timestamp file. + if env.config.depfile_stamp: + with open(env.config.depfile_stamp, 'w') as f: + pass + + with open(env.config.depfile, 'w') as f: + print((env.config.depfile_stamp or app.outdir) + ": \\", file=f) + print(*get_infiles(env), file=f) + for x in get_infiles(env): + print(x + ":", file=f) + + +def setup(app): + app.add_config_value('depfile', None, 'env') + app.add_config_value('depfile_stamp', None, 'env') + app.connect('env-updated', write_depfile) + + return dict( + version = __version__, + parallel_read_safe = True, + parallel_write_safe = True + ) diff --git a/docs/sphinx/kerneldoc.py b/docs/sphinx/kerneldoc.py index 3e879402064603ee6a2f95263ef07d4c12461a21..3ac277d1622464cc4a4bd6a274839692342e3873 100644 --- a/docs/sphinx/kerneldoc.py +++ b/docs/sphinx/kerneldoc.py @@ -67,7 +67,7 @@ class KernelDocDirective(Directive): def run(self): env = self.state.document.settings.env - cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno'] + cmd = env.config.kerneldoc_bin + ['-rst', '-enable-lineno'] filename = env.config.kerneldoc_srctree + '/' + self.arguments[0] export_file_patterns = [] diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py new file mode 100644 index 0000000000000000000000000000000000000000..e03abcbb9597d77bdc64d8166921fa4c22cc6819 --- /dev/null +++ b/docs/sphinx/qapidoc.py @@ -0,0 +1,549 @@ +# coding=utf-8 +# +# QEMU qapidoc QAPI file parsing extension +# +# Copyright (c) 2020 Linaro +# +# This work is licensed under the terms of the GNU GPLv2 or later. +# See the COPYING file in the top-level directory. + +""" +qapidoc is a Sphinx extension that implements the qapi-doc directive + +The purpose of this extension is to read the documentation comments +in QAPI schema files, and insert them all into the current document. + +It implements one new rST directive, "qapi-doc::". +Each qapi-doc:: directive takes one argument, which is the +pathname of the schema file to process, relative to the source tree. + +The docs/conf.py file must set the qapidoc_srctree config value to +the root of the QEMU source tree. + +The Sphinx documentation on writing extensions is at: +https://www.sphinx-doc.org/en/master/development/index.html +""" + +import os +import re + +from docutils import nodes +from docutils.statemachine import ViewList +from docutils.parsers.rst import directives, Directive +from sphinx.errors import ExtensionError +from sphinx.util.nodes import nested_parse_with_titles +import sphinx +from qapi.gen import QAPISchemaVisitor +from qapi.schema import QAPIError, QAPISemError, QAPISchema + + +# Sphinx up to 1.6 uses AutodocReporter; 1.7 and later +# use switch_source_input. Check borrowed from kerneldoc.py. +Use_SSI = sphinx.__version__[:3] >= '1.7' +if Use_SSI: + from sphinx.util.docutils import switch_source_input +else: + from sphinx.ext.autodoc import AutodocReporter + + +__version__ = '1.0' + + +# Function borrowed from pydash, which is under the MIT license +def intersperse(iterable, separator): + """Yield the members of *iterable* interspersed with *separator*.""" + iterable = iter(iterable) + yield next(iterable) + for item in iterable: + yield separator + yield item + + +class QAPISchemaGenRSTVisitor(QAPISchemaVisitor): + """A QAPI schema visitor which generates docutils/Sphinx nodes + + This class builds up a tree of docutils/Sphinx nodes corresponding + to documentation for the various QAPI objects. To use it, first + create a QAPISchemaGenRSTVisitor object, and call its + visit_begin() method. Then you can call one of the two methods + 'freeform' (to add documentation for a freeform documentation + chunk) or 'symbol' (to add documentation for a QAPI symbol). These + will cause the visitor to build up the tree of document + nodes. Once you've added all the documentation via 'freeform' and + 'symbol' method calls, you can call 'get_document_nodes' to get + the final list of document nodes (in a form suitable for returning + from a Sphinx directive's 'run' method). + """ + def __init__(self, sphinx_directive): + self._cur_doc = None + self._sphinx_directive = sphinx_directive + self._top_node = nodes.section() + self._active_headings = [self._top_node] + + def _make_dlitem(self, term, defn): + """Return a dlitem node with the specified term and definition. + + term should be a list of Text and literal nodes. + defn should be one of: + - a string, which will be handed to _parse_text_into_node + - a list of Text and literal nodes, which will be put into + a paragraph node + """ + dlitem = nodes.definition_list_item() + dlterm = nodes.term('', '', *term) + dlitem += dlterm + if defn: + dldef = nodes.definition() + if isinstance(defn, list): + dldef += nodes.paragraph('', '', *defn) + else: + self._parse_text_into_node(defn, dldef) + dlitem += dldef + return dlitem + + def _make_section(self, title): + """Return a section node with optional title""" + section = nodes.section(ids=[self._sphinx_directive.new_serialno()]) + if title: + section += nodes.title(title, title) + return section + + def _nodes_for_ifcond(self, ifcond, with_if=True): + """Return list of Text, literal nodes for the ifcond + + Return a list which gives text like ' (If: cond1, cond2, cond3)', where + the conditions are in literal-text and the commas are not. + If with_if is False, we don't return the "(If: " and ")". + """ + condlist = intersperse([nodes.literal('', c) for c in ifcond], + nodes.Text(', ')) + if not with_if: + return condlist + + nodelist = [nodes.Text(' ('), nodes.strong('', 'If: ')] + nodelist.extend(condlist) + nodelist.append(nodes.Text(')')) + return nodelist + + def _nodes_for_one_member(self, member): + """Return list of Text, literal nodes for this member + + Return a list of doctree nodes which give text like + 'name: type (optional) (If: ...)' suitable for use as the + 'term' part of a definition list item. + """ + term = [nodes.literal('', member.name)] + if member.type.doc_type(): + term.append(nodes.Text(': ')) + term.append(nodes.literal('', member.type.doc_type())) + if member.optional: + term.append(nodes.Text(' (optional)')) + if member.ifcond: + term.extend(self._nodes_for_ifcond(member.ifcond)) + return term + + def _nodes_for_variant_when(self, variants, variant): + """Return list of Text, literal nodes for variant 'when' clause + + Return a list of doctree nodes which give text like + 'when tagname is variant (If: ...)' suitable for use in + the 'variants' part of a definition list. + """ + term = [nodes.Text(' when '), + nodes.literal('', variants.tag_member.name), + nodes.Text(' is '), + nodes.literal('', '"%s"' % variant.name)] + if variant.ifcond: + term.extend(self._nodes_for_ifcond(variant.ifcond)) + return term + + def _nodes_for_members(self, doc, what, base=None, variants=None): + """Return list of doctree nodes for the table of members""" + dlnode = nodes.definition_list() + for section in doc.args.values(): + term = self._nodes_for_one_member(section.member) + # TODO drop fallbacks when undocumented members are outlawed + if section.text: + defn = section.text + elif (variants and variants.tag_member == section.member + and not section.member.type.doc_type()): + values = section.member.type.member_names() + defn = [nodes.Text('One of ')] + defn.extend(intersperse([nodes.literal('', v) for v in values], + nodes.Text(', '))) + else: + defn = [nodes.Text('Not documented')] + + dlnode += self._make_dlitem(term, defn) + + if base: + dlnode += self._make_dlitem([nodes.Text('The members of '), + nodes.literal('', base.doc_type())], + None) + + if variants: + for v in variants.variants: + if v.type.is_implicit(): + assert not v.type.base and not v.type.variants + for m in v.type.local_members: + term = self._nodes_for_one_member(m) + term.extend(self._nodes_for_variant_when(variants, v)) + dlnode += self._make_dlitem(term, None) + else: + term = [nodes.Text('The members of '), + nodes.literal('', v.type.doc_type())] + term.extend(self._nodes_for_variant_when(variants, v)) + dlnode += self._make_dlitem(term, None) + + if not dlnode.children: + return [] + + section = self._make_section(what) + section += dlnode + return [section] + + def _nodes_for_enum_values(self, doc): + """Return list of doctree nodes for the table of enum values""" + seen_item = False + dlnode = nodes.definition_list() + for section in doc.args.values(): + termtext = [nodes.literal('', section.member.name)] + if section.member.ifcond: + termtext.extend(self._nodes_for_ifcond(section.member.ifcond)) + # TODO drop fallbacks when undocumented members are outlawed + if section.text: + defn = section.text + else: + defn = [nodes.Text('Not documented')] + + dlnode += self._make_dlitem(termtext, defn) + seen_item = True + + if not seen_item: + return [] + + section = self._make_section('Values') + section += dlnode + return [section] + + def _nodes_for_arguments(self, doc, boxed_arg_type): + """Return list of doctree nodes for the arguments section""" + if boxed_arg_type: + assert not doc.args + section = self._make_section('Arguments') + dlnode = nodes.definition_list() + dlnode += self._make_dlitem( + [nodes.Text('The members of '), + nodes.literal('', boxed_arg_type.name)], + None) + section += dlnode + return [section] + + return self._nodes_for_members(doc, 'Arguments') + + def _nodes_for_features(self, doc): + """Return list of doctree nodes for the table of features""" + seen_item = False + dlnode = nodes.definition_list() + for section in doc.features.values(): + dlnode += self._make_dlitem([nodes.literal('', section.name)], + section.text) + seen_item = True + + if not seen_item: + return [] + + section = self._make_section('Features') + section += dlnode + return [section] + + def _nodes_for_example(self, exampletext): + """Return list of doctree nodes for a code example snippet""" + return [nodes.literal_block(exampletext, exampletext)] + + def _nodes_for_sections(self, doc): + """Return list of doctree nodes for additional sections""" + nodelist = [] + for section in doc.sections: + snode = self._make_section(section.name) + if section.name and section.name.startswith('Example'): + snode += self._nodes_for_example(section.text) + else: + self._parse_text_into_node(section.text, snode) + nodelist.append(snode) + return nodelist + + def _nodes_for_if_section(self, ifcond): + """Return list of doctree nodes for the "If" section""" + nodelist = [] + if ifcond: + snode = self._make_section('If') + snode += self._nodes_for_ifcond(ifcond, with_if=False) + nodelist.append(snode) + return nodelist + + def _add_doc(self, typ, sections): + """Add documentation for a command/object/enum... + + We assume we're documenting the thing defined in self._cur_doc. + typ is the type of thing being added ("Command", "Object", etc) + + sections is a list of nodes for sections to add to the definition. + """ + + doc = self._cur_doc + snode = nodes.section(ids=[self._sphinx_directive.new_serialno()]) + snode += nodes.title('', '', *[nodes.literal(doc.symbol, doc.symbol), + nodes.Text(' (' + typ + ')')]) + self._parse_text_into_node(doc.body.text, snode) + for s in sections: + if s is not None: + snode += s + self._add_node_to_current_heading(snode) + + def visit_enum_type(self, name, info, ifcond, features, members, prefix): + doc = self._cur_doc + self._add_doc('Enum', + self._nodes_for_enum_values(doc) + + self._nodes_for_features(doc) + + self._nodes_for_sections(doc) + + self._nodes_for_if_section(ifcond)) + + def visit_object_type(self, name, info, ifcond, features, + base, members, variants): + doc = self._cur_doc + if base and base.is_implicit(): + base = None + self._add_doc('Object', + self._nodes_for_members(doc, 'Members', base, variants) + + self._nodes_for_features(doc) + + self._nodes_for_sections(doc) + + self._nodes_for_if_section(ifcond)) + + def visit_alternate_type(self, name, info, ifcond, features, variants): + doc = self._cur_doc + self._add_doc('Alternate', + self._nodes_for_members(doc, 'Members') + + self._nodes_for_features(doc) + + self._nodes_for_sections(doc) + + self._nodes_for_if_section(ifcond)) + + def visit_command(self, name, info, ifcond, features, arg_type, + ret_type, gen, success_response, boxed, allow_oob, + allow_preconfig, coroutine): + doc = self._cur_doc + self._add_doc('Command', + self._nodes_for_arguments(doc, + arg_type if boxed else None) + + self._nodes_for_features(doc) + + self._nodes_for_sections(doc) + + self._nodes_for_if_section(ifcond)) + + def visit_event(self, name, info, ifcond, features, arg_type, boxed): + doc = self._cur_doc + self._add_doc('Event', + self._nodes_for_arguments(doc, + arg_type if boxed else None) + + self._nodes_for_features(doc) + + self._nodes_for_sections(doc) + + self._nodes_for_if_section(ifcond)) + + def symbol(self, doc, entity): + """Add documentation for one symbol to the document tree + + This is the main entry point which causes us to add documentation + nodes for a symbol (which could be a 'command', 'object', 'event', + etc). We do this by calling 'visit' on the schema entity, which + will then call back into one of our visit_* methods, depending + on what kind of thing this symbol is. + """ + self._cur_doc = doc + entity.visit(self) + self._cur_doc = None + + def _start_new_heading(self, heading, level): + """Start a new heading at the specified heading level + + Create a new section whose title is 'heading' and which is placed + in the docutils node tree as a child of the most recent level-1 + heading. Subsequent document sections (commands, freeform doc chunks, + etc) will be placed as children of this new heading section. + """ + if len(self._active_headings) < level: + raise QAPISemError(self._cur_doc.info, + 'Level %d subheading found outside a ' + 'level %d heading' + % (level, level - 1)) + snode = self._make_section(heading) + self._active_headings[level - 1] += snode + self._active_headings = self._active_headings[:level] + self._active_headings.append(snode) + + def _add_node_to_current_heading(self, node): + """Add the node to whatever the current active heading is""" + self._active_headings[-1] += node + + def freeform(self, doc): + """Add a piece of 'freeform' documentation to the document tree + + A 'freeform' document chunk doesn't relate to any particular + symbol (for instance, it could be an introduction). + + If the freeform document starts with a line of the form + '= Heading text', this is a section or subsection heading, with + the heading level indicated by the number of '=' signs. + """ + + # QAPIDoc documentation says free-form documentation blocks + # must have only a body section, nothing else. + assert not doc.sections + assert not doc.args + assert not doc.features + self._cur_doc = doc + + text = doc.body.text + if re.match(r'=+ ', text): + # Section/subsection heading (if present, will always be + # the first line of the block) + (heading, _, text) = text.partition('\n') + (leader, _, heading) = heading.partition(' ') + self._start_new_heading(heading, len(leader)) + if text == '': + return + + node = self._make_section(None) + self._parse_text_into_node(text, node) + self._add_node_to_current_heading(node) + self._cur_doc = None + + def _parse_text_into_node(self, doctext, node): + """Parse a chunk of QAPI-doc-format text into the node + + The doc comment can contain most inline rST markup, including + bulleted and enumerated lists. + As an extra permitted piece of markup, @var will be turned + into ``var``. + """ + + # Handle the "@var means ``var`` case + doctext = re.sub(r'@([\w-]+)', r'``\1``', doctext) + + rstlist = ViewList() + for line in doctext.splitlines(): + # The reported line number will always be that of the start line + # of the doc comment, rather than the actual location of the error. + # Being more precise would require overhaul of the QAPIDoc class + # to track lines more exactly within all the sub-parts of the doc + # comment, as well as counting lines here. + rstlist.append(line, self._cur_doc.info.fname, + self._cur_doc.info.line) + # Append a blank line -- in some cases rST syntax errors get + # attributed to the line after one with actual text, and if there + # isn't anything in the ViewList corresponding to that then Sphinx + # 1.6's AutodocReporter will then misidentify the source/line location + # in the error message (usually attributing it to the top-level + # .rst file rather than the offending .json file). The extra blank + # line won't affect the rendered output. + rstlist.append("", self._cur_doc.info.fname, self._cur_doc.info.line) + self._sphinx_directive.do_parse(rstlist, node) + + def get_document_nodes(self): + """Return the list of docutils nodes which make up the document""" + return self._top_node.children + + +class QAPISchemaGenDepVisitor(QAPISchemaVisitor): + """A QAPI schema visitor which adds Sphinx dependencies each module + + This class calls the Sphinx note_dependency() function to tell Sphinx + that the generated documentation output depends on the input + schema file associated with each module in the QAPI input. + """ + def __init__(self, env, qapidir): + self._env = env + self._qapidir = qapidir + + def visit_module(self, name): + if name is not None: + qapifile = self._qapidir + '/' + name + self._env.note_dependency(os.path.abspath(qapifile)) + super().visit_module(name) + + +class QAPIDocDirective(Directive): + """Extract documentation from the specified QAPI .json file""" + required_argument = 1 + optional_arguments = 1 + option_spec = { + 'qapifile': directives.unchanged_required + } + has_content = False + + def new_serialno(self): + """Return a unique new ID string suitable for use as a node's ID""" + env = self.state.document.settings.env + return 'qapidoc-%d' % env.new_serialno('qapidoc') + + def run(self): + env = self.state.document.settings.env + qapifile = env.config.qapidoc_srctree + '/' + self.arguments[0] + qapidir = os.path.dirname(qapifile) + + try: + schema = QAPISchema(qapifile) + + # First tell Sphinx about all the schema files that the + # output documentation depends on (including 'qapifile' itself) + schema.visit(QAPISchemaGenDepVisitor(env, qapidir)) + + vis = QAPISchemaGenRSTVisitor(self) + vis.visit_begin(schema) + for doc in schema.docs: + if doc.symbol: + vis.symbol(doc, schema.lookup_entity(doc.symbol)) + else: + vis.freeform(doc) + return vis.get_document_nodes() + except QAPIError as err: + # Launder QAPI parse errors into Sphinx extension errors + # so they are displayed nicely to the user + raise ExtensionError(str(err)) + + def do_parse(self, rstlist, node): + """Parse rST source lines and add them to the specified node + + Take the list of rST source lines rstlist, parse them as + rST, and add the resulting docutils nodes as children of node. + The nodes are parsed in a way that allows them to include + subheadings (titles) without confusing the rendering of + anything else. + """ + # This is from kerneldoc.py -- it works around an API change in + # Sphinx between 1.6 and 1.7. Unlike kerneldoc.py, we use + # sphinx.util.nodes.nested_parse_with_titles() rather than the + # plain self.state.nested_parse(), and so we can drop the saving + # of title_styles and section_level that kerneldoc.py does, + # because nested_parse_with_titles() does that for us. + if Use_SSI: + with switch_source_input(self.state, rstlist): + nested_parse_with_titles(self.state, rstlist, node) + else: + save = self.state.memo.reporter + self.state.memo.reporter = AutodocReporter( + rstlist, self.state.memo.reporter) + try: + nested_parse_with_titles(self.state, rstlist, node) + finally: + self.state.memo.reporter = save + + +def setup(app): + """ Register qapi-doc directive with Sphinx""" + app.add_config_value('qapidoc_srctree', None, 'env') + app.add_directive('qapi-doc', QAPIDocDirective) + + return dict( + version=__version__, + parallel_read_safe=True, + parallel_write_safe=True + ) diff --git a/docs/system/_templates/editpage.html b/docs/system/_templates/editpage.html new file mode 100644 index 0000000000000000000000000000000000000000..6586b2e2579874af379ad289f40959dc087ced93 --- /dev/null +++ b/docs/system/_templates/editpage.html @@ -0,0 +1,5 @@ +
+ +
diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst new file mode 100644 index 0000000000000000000000000000000000000000..690bada7842be2f054035e345fbd2def5463349e --- /dev/null +++ b/docs/system/arm/aspeed.rst @@ -0,0 +1,104 @@ +Aspeed family boards (``*-bmc``, ``ast2500-evb``, ``ast2600-evb``) +================================================================== + +The QEMU Aspeed machines model BMCs of various OpenPOWER systems and +Aspeed evaluation boards. They are based on different releases of the +Aspeed SoC : the AST2400 integrating an ARM926EJ-S CPU (400MHz), the +AST2500 with an ARM1176JZS CPU (800MHz) and more recently the AST2600 +with dual cores ARM Cortex A7 CPUs (1.2GHz). + +The SoC comes with RAM, Gigabit ethernet, USB, SD/MMC, USB, SPI, I2C, +etc. + +AST2400 SoC based machines : + +- ``palmetto-bmc`` OpenPOWER Palmetto POWER8 BMC + +AST2500 SoC based machines : + +- ``ast2500-evb`` Aspeed AST2500 Evaluation board +- ``romulus-bmc`` OpenPOWER Romulus POWER9 BMC +- ``witherspoon-bmc`` OpenPOWER Witherspoon POWER9 BMC +- ``sonorapass-bmc`` OCP SonoraPass BMC +- ``swift-bmc`` OpenPOWER Swift BMC POWER9 + +AST2600 SoC based machines : + +- ``ast2600-evb`` Aspeed AST2600 Evaluation board (Cortex A7) +- ``tacoma-bmc`` OpenPOWER Witherspoon POWER9 AST2600 BMC + +Supported devices +----------------- + + * SMP (for the AST2600 Cortex-A7) + * Interrupt Controller (VIC) + * Timer Controller + * RTC Controller + * I2C Controller + * System Control Unit (SCU) + * SRAM mapping + * X-DMA Controller (basic interface) + * Static Memory Controller (SMC or FMC) - Only SPI Flash support + * SPI Memory Controller + * USB 2.0 Controller + * SD/MMC storage controllers + * SDRAM controller (dummy interface for basic settings and training) + * Watchdog Controller + * GPIO Controller (Master only) + * UART + * Ethernet controllers + * Front LEDs (PCA9552 on I2C bus) + + +Missing devices +--------------- + + * Coprocessor support + * ADC (out of tree implementation) + * PWM and Fan Controller + * LPC Bus Controller + * Slave GPIO Controller + * Super I/O Controller + * Hash/Crypto Engine + * PCI-Express 1 Controller + * Graphic Display Controller + * PECI Controller + * MCTP Controller + * Mailbox Controller + * Virtual UART + * eSPI Controller + * I3C Controller + +Boot options +------------ + +The Aspeed machines can be started using the -kernel option to load a +Linux kernel or from a firmware image which can be downloaded from the +OpenPOWER jenkins : + + https://openpower.xyz/ + +The image should be attached as an MTD drive. Run : + +.. code-block:: bash + + $ qemu-system-arm -M romulus-bmc -nic user \ + -drive file=flash-romulus,format=raw,if=mtd -nographic + +Options specific to Aspeed machines are : + + * ``execute-in-place`` which emulates the boot from the CE0 flash + device by using the FMC controller to load the instructions, and + not simply from RAM. This takes a little longer. + + * ``fmc-model`` to change the FMC Flash model. FW needs support for + the chip model to boot. + + * ``spi-model`` to change the SPI Flash model. + +For instance, to start the ``ast2500-evb`` machine with a different +FMC chip and a bigger (64M) SPI chip, use : + +.. code-block:: bash + + -M ast2500-evb,fmc-model=mx25l25635e,spi-model=mx66u51235f diff --git a/docs/system/arm/collie.rst b/docs/system/arm/collie.rst new file mode 100644 index 0000000000000000000000000000000000000000..5cc67b6d1b50e76a865a3f8abf912973551aaaad --- /dev/null +++ b/docs/system/arm/collie.rst @@ -0,0 +1,16 @@ +Sharp Zaurus SL-5500 (``collie``) +================================= + +This machine is a model of the Sharp Zaurus SL-5500, which was +a 1990s PDA based on the StrongARM SA1110. + +Implemented devices: + + * NOR flash + * Interrupt controller + * Timer + * RTC + * GPIO + * Peripheral Pin Controller (PPC) + * UARTs + * Synchronous Serial Ports (SSP) diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst index 2d5c06cd016bea36ff7b5ea7ed2711346349173f..35196a6b759d0ea39708c32f3fa0384a7f031fc7 100644 --- a/docs/system/arm/cpu-features.rst +++ b/docs/system/arm/cpu-features.rst @@ -200,6 +200,17 @@ the list of KVM VCPU features and their descriptions. adjustment, also restoring the legacy (pre-5.0) behavior. + kvm-steal-time Since v5.2, kvm-steal-time is enabled by + default when KVM is enabled, the feature is + supported, and the guest is 64-bit. + + When kvm-steal-time is enabled a 64-bit guest + can account for time its CPUs were not running + due to the host not scheduling the corresponding + VCPU threads. The accounting statistics may + influence the guest scheduler behavior and/or be + exposed to the guest userspace. + SVE CPU Properties ================== diff --git a/docs/system/arm/digic.rst b/docs/system/arm/digic.rst new file mode 100644 index 0000000000000000000000000000000000000000..2b3520ff5e19a0e57baf246ece4949e2dd908a0b --- /dev/null +++ b/docs/system/arm/digic.rst @@ -0,0 +1,11 @@ +Canon A1100 (``canon-a1100``) +============================= + +This machine is a model of the Canon PowerShot A1100 camera, which +uses the DIGIC SoC. This model is based on reverse engineering efforts +by the contributors to the `CHDK `_ and +`Magic Lantern `_ projects. + +The emulation is incomplete. In particular it can't be used +to run the original camera firmware, but it can successfully run +an experimental version of the `barebox bootloader `_. diff --git a/docs/system/arm/gumstix.rst b/docs/system/arm/gumstix.rst new file mode 100644 index 0000000000000000000000000000000000000000..cb373139dcb64c0196c3815c8ca475e4c5c4bbe6 --- /dev/null +++ b/docs/system/arm/gumstix.rst @@ -0,0 +1,21 @@ +Gumstix Connex and Verdex (``connex``, ``verdex``) +================================================== + +These machines model the Gumstix Connex and Verdex boards. +The Connex has a PXA255 CPU and the Verdex has a PXA270. + +Implemented devices: + + * NOR flash + * SMC91C111 ethernet + * Interrupt controller + * DMA + * Timer + * GPIO + * MMC/SD card + * Fast infra-red communications port (FIR) + * LCD controller + * Synchronous serial ports (SPI) + * PCMCIA interface + * I2C + * I2S diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst index 3a98cb59b0d6f155300104dc02f135354093a4b1..8c5b5f1fe07709cf183469a81f70fd105d033732 100644 --- a/docs/system/arm/mps2.rst +++ b/docs/system/arm/mps2.rst @@ -1,5 +1,5 @@ -Arm MPS2 boards (``mps2-an385``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``) -================================================================================ +Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``) +================================================================================================================ These board models all use Arm M-profile CPUs. @@ -11,17 +11,21 @@ as seen by the guest depend significantly on the FPGA image. QEMU models the following FPGA images: ``mps2-an385`` - Cortex-M3 as documented in ARM Application Note AN385 -``mps2-an511`` - Cortex-M3 'DesignStart' as documented in AN511 + Cortex-M3 as documented in Arm Application Note AN385 +``mps2-an386`` + Cortex-M4 as documented in Arm Application Note AN386 +``mps2-an500`` + Cortex-M7 as documented in Arm Application Note AN500 ``mps2-an505`` - Cortex-M33 as documented in ARM Application Note AN505 + Cortex-M33 as documented in Arm Application Note AN505 +``mps2-an511`` + Cortex-M3 'DesignStart' as documented in Arm Application Note AN511 ``mps2-an521`` - Dual Cortex-M33 as documented in Application Note AN521 + Dual Cortex-M33 as documented in Arm Application Note AN521 Differences between QEMU and real hardware: -- AN385 remapping of low 16K of memory to either ZBT SSRAM1 or to +- AN385/AN386 remapping of low 16K of memory to either ZBT SSRAM1 or to block RAM is unimplemented (QEMU always maps this to ZBT SSRAM1, as if zbt_boot_ctrl is always zero) - QEMU provides a LAN9118 ethernet rather than LAN9220; the only guest diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst new file mode 100644 index 0000000000000000000000000000000000000000..b00d405d52e906883a050a5ab48244fa6d17f075 --- /dev/null +++ b/docs/system/arm/nuvoton.rst @@ -0,0 +1,92 @@ +Nuvoton iBMC boards (``npcm750-evb``, ``quanta-gsj``) +===================================================== + +The `Nuvoton iBMC`_ chips (NPCM7xx) are a family of ARM-based SoCs that are +designed to be used as Baseboard Management Controllers (BMCs) in various +servers. They all feature one or two ARM Cortex A9 CPU cores, as well as an +assortment of peripherals targeted for either Enterprise or Data Center / +Hyperscale applications. The former is a superset of the latter, so NPCM750 has +all the peripherals of NPCM730 and more. + +.. _Nuvoton iBMC: https://www.nuvoton.com/products/cloud-computing/ibmc/ + +The NPCM750 SoC has two Cortex A9 cores and is targeted for the Enterprise +segment. The following machines are based on this chip : + +- ``npcm750-evb`` Nuvoton NPCM750 Evaluation board + +The NPCM730 SoC has two Cortex A9 cores and is targeted for Data Center and +Hyperscale applications. The following machines are based on this chip : + +- ``quanta-gsj`` Quanta GSJ server BMC + +There are also two more SoCs, NPCM710 and NPCM705, which are single-core +variants of NPCM750 and NPCM730, respectively. These are currently not +supported by QEMU. + +Supported devices +----------------- + + * SMP (Dual Core Cortex-A9) + * Cortex-A9MPCore built-in peripherals: SCU, GIC, Global Timer, Private Timer + and Watchdog. + * SRAM, ROM and DRAM mappings + * System Global Control Registers (GCR) + * Clock and reset controller (CLK) + * Timer controller (TIM) + * Serial ports (16550-based) + * DDR4 memory controller (dummy interface indicating memory training is done) + * OTP controllers (no protection features) + * Flash Interface Unit (FIU; no protection features) + * Random Number Generator (RNG) + * USB host (USBH) + * GPIO controller + +Missing devices +--------------- + + * LPC/eSPI host-to-BMC interface, including + + * Keyboard and mouse controller interface (KBCI) + * Keyboard Controller Style (KCS) channels + * BIOS POST code FIFO + * System Wake-up Control (SWC) + * Shared memory (SHM) + * eSPI slave interface + + * Ethernet controllers (GMAC and EMC) + * USB device (USBD) + * SMBus controller (SMBF) + * Peripheral SPI controller (PSPI) + * Analog to Digital Converter (ADC) + * SD/MMC host + * PECI interface + * Pulse Width Modulation (PWM) + * Tachometer + * PCI and PCIe root complex and bridges + * VDM and MCTP support + * Serial I/O expansion + * LPC/eSPI host + * Coprocessor + * Graphics + * Video capture + * Encoding compression engine + * Security features + +Boot options +------------ + +The Nuvoton machines can boot from an OpenBMC firmware image, or directly into +a kernel using the ``-kernel`` option. OpenBMC images for `quanta-gsj` and +possibly others can be downloaded from the OpenPOWER jenkins : + + https://openpower.xyz/ + +The firmware image should be attached as an MTD drive. Example : + +.. code-block:: bash + + $ qemu-system-arm -machine quanta-gsj -nographic \ + -drive file=image-bmc,if=mtd,bus=0,unit=0,format=raw + +The default root password for test images is usually ``0penBmc``. diff --git a/docs/system/arm/orangepi.rst b/docs/system/arm/orangepi.rst index c41adad4883c855c49abc571bcde596ca7d44ef3..6f23907fb69d2208dd19ec57b7b09996fcba2f60 100644 --- a/docs/system/arm/orangepi.rst +++ b/docs/system/arm/orangepi.rst @@ -127,6 +127,16 @@ can be downloaded from: Alternatively, you can also choose to build you own image with buildroot using the orangepi_pc_defconfig. Also see https://buildroot.org for more information. +When using an image as an SD card, it must be resized to a power of two. This can be +done with the qemu-img command. It is recommended to only increase the image size +instead of shrinking it to a power of two, to avoid loss of data. For example, +to prepare a downloaded Armbian image, first extract it and then increase +its size to one gigabyte as follows: + +.. code-block:: bash + + $ qemu-img resize Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.img 1G + You can choose to attach the selected image either as an SD card or as USB mass storage. For example, to boot using the Orange Pi PC Debian image on SD card, simply add the -sd argument and provide the proper root= kernel parameter: @@ -213,12 +223,12 @@ Next, unzip the NetBSD image and write the U-Boot binary including SPL using: $ dd if=/path/to/u-boot-sunxi-with-spl.bin of=armv7.img bs=1024 seek=8 conv=notrunc Finally, before starting the machine the SD image must be extended such -that the NetBSD kernel will not conclude the NetBSD partition is larger than -the emulated SD card: +that the size of the SD image is a power of two and that the NetBSD kernel +will not conclude the NetBSD partition is larger than the emulated SD card: .. code-block:: bash - $ dd if=/dev/zero bs=1M count=64 >> armv7.img + $ qemu-img resize armv7.img 2G Start the machine using the following command: diff --git a/docs/system/arm/raspi.rst b/docs/system/arm/raspi.rst new file mode 100644 index 0000000000000000000000000000000000000000..922fe375a672ca970d3b0f71d39061cd58862002 --- /dev/null +++ b/docs/system/arm/raspi.rst @@ -0,0 +1,43 @@ +Raspberry Pi boards (``raspi0``, ``raspi1ap``, ``raspi2b``, ``raspi3ap``, ``raspi3b``) +====================================================================================== + + +QEMU provides models of the following Raspberry Pi boards: + +``raspi0`` and ``raspi1ap`` + ARM1176JZF-S core, 512 MiB of RAM +``raspi2b`` + Cortex-A7 (4 cores), 1 GiB of RAM +``raspi3ap`` + Cortex-A53 (4 cores), 512 MiB of RAM +``raspi3b`` + Cortex-A53 (4 cores), 1 GiB of RAM + + +Implemented devices +------------------- + + * ARM1176JZF-S, Cortex-A7 or Cortex-A53 CPU + * Interrupt controller + * DMA controller + * Clock and reset controller (CPRMAN) + * System Timer + * GPIO controller + * Serial ports (BCM2835 AUX - 16550 based - and PL011) + * Random Number Generator (RNG) + * Frame Buffer + * USB host (USBH) + * GPIO controller + * SD/MMC host controller + * SoC thermal sensor + * USB2 host controller (DWC2 and MPHI) + * MailBox controller (MBOX) + * VideoCore firmware (property) + + +Missing devices +--------------- + + * Peripheral SPI controller (SPI) + * Analog to Digital Converter (ADC) + * Pulse Width Modulation (PWM) diff --git a/docs/system/arm/sbsa.rst b/docs/system/arm/sbsa.rst new file mode 100644 index 0000000000000000000000000000000000000000..b8ecfdb62fde4943f57a0901b3b5acc2a012dbe0 --- /dev/null +++ b/docs/system/arm/sbsa.rst @@ -0,0 +1,32 @@ +Arm Server Base System Architecture Reference board (``sbsa-ref``) +================================================================== + +While the `virt` board is a generic board platform that doesn't match +any real hardware the `sbsa-ref` board intends to look like real +hardware. The `Server Base System Architecture +` defines a +minimum base line of hardware support and importantly how the firmware +reports that to any operating system. It is a static system that +reports a very minimal DT to the firmware for non-discoverable +information about components affected by the qemu command line (i.e. +cpus and memory). As a result it must have a firmware specifically +built to expect a certain hardware layout (as you would in a real +machine). + +It is intended to be a machine for developing firmware and testing +standards compliance with operating systems. + +Supported devices +""""""""""""""""" + +The sbsa-ref board supports: + + - A configurable number of AArch64 CPUs + - GIC version 3 + - System bus AHCI controller + - System bus EHCI controller + - CDROM and hard disc on AHCI bus + - E1000E ethernet card on PCIe bus + - VGA display adaptor on PCIe bus + - A generic SBSA watchdog device + diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst new file mode 100644 index 0000000000000000000000000000000000000000..32dc5eb22ee38d6b5c67995735a357070aa151ed --- /dev/null +++ b/docs/system/arm/virt.rst @@ -0,0 +1,165 @@ +'virt' generic virtual platform (``virt``) +========================================== + +The `virt` board is a platform which does not correspond to any +real hardware; it is designed for use in virtual machines. +It is the recommended board type if you simply want to run +a guest such as Linux and do not care about reproducing the +idiosyncrasies and limitations of a particular bit of real-world +hardware. + +This is a "versioned" board model, so as well as the ``virt`` machine +type itself (which may have improvements, bugfixes and other minor +changes between QEMU versions) a version is provided that guarantees +to have the same behaviour as that of previous QEMU releases, so +that VM migration will work between QEMU versions. For instance the +``virt-5.0`` machine type will behave like the ``virt`` machine from +the QEMU 5.0 release, and migration should work between ``virt-5.0`` +of the 5.0 release and ``virt-5.0`` of the 5.1 release. Migration +is not guaranteed to work between different QEMU releases for +the non-versioned ``virt`` machine type. + +Supported devices +""""""""""""""""" + +The virt board supports: + +- PCI/PCIe devices +- Flash memory +- One PL011 UART +- An RTC +- The fw_cfg device that allows a guest to obtain data from QEMU +- A PL061 GPIO controller +- An optional SMMUv3 IOMMU +- hotpluggable DIMMs +- hotpluggable NVDIMMs +- An MSI controller (GICv2M or ITS). GICv2M is selected by default along + with GICv2. ITS is selected by default with GICv3 (>= virt-2.7). Note + that ITS is not modeled in TCG mode. +- 32 virtio-mmio transport devices +- running guests using the KVM accelerator on aarch64 hardware +- large amounts of RAM (at least 255GB, and more if using highmem) +- many CPUs (up to 512 if using a GICv3 and highmem) +- Secure-World-only devices if the CPU has TrustZone: + + - A second PL011 UART + - A secure flash memory + - 16MB of secure RAM + +Supported guest CPU types: + +- ``cortex-a7`` (32-bit) +- ``cortex-a15`` (32-bit; the default) +- ``cortex-a53`` (64-bit) +- ``cortex-a57`` (64-bit) +- ``cortex-a72`` (64-bit) +- ``host`` (with KVM only) +- ``max`` (same as ``host`` for KVM; best possible emulation with TCG) + +Note that the default is ``cortex-a15``, so for an AArch64 guest you must +specify a CPU type. + +Graphics output is available, but unlike the x86 PC machine types +there is no default display device enabled: you should select one from +the Display devices section of "-device help". The recommended option +is ``virtio-gpu-pci``; this is the only one which will work correctly +with KVM. You may also need to ensure your guest kernel is configured +with support for this; see below. + +Machine-specific options +"""""""""""""""""""""""" + +The following machine-specific options are supported: + +secure + Set ``on``/``off`` to enable/disable emulating a guest CPU which implements the + Arm Security Extensions (TrustZone). The default is ``off``. + +virtualization + Set ``on``/``off`` to enable/disable emulating a guest CPU which implements the + Arm Virtualization Extensions. The default is ``off``. + +mte + Set ``on``/``off`` to enable/disable emulating a guest CPU which implements the + Arm Memory Tagging Extensions. The default is ``off``. + +highmem + Set ``on``/``off`` to enable/disable placing devices and RAM in physical + address space above 32 bits. The default is ``on`` for machine types + later than ``virt-2.12``. + +gic-version + Specify the version of the Generic Interrupt Controller (GIC) to provide. + Valid values are: + + ``2`` + GICv2 + ``3`` + GICv3 + ``host`` + Use the same GIC version the host provides, when using KVM + ``max`` + Use the best GIC version possible (same as host when using KVM; + currently same as ``3``` for TCG, but this may change in future) + +its + Set ``on``/``off`` to enable/disable ITS instantiation. The default is ``on`` + for machine types later than ``virt-2.7``. + +iommu + Set the IOMMU type to create for the guest. Valid values are: + + ``none`` + Don't create an IOMMU (the default) + ``smmuv3`` + Create an SMMUv3 + +ras + Set ``on``/``off`` to enable/disable reporting host memory errors to a guest + using ACPI and guest external abort exceptions. The default is off. + +Linux guest kernel configuration +"""""""""""""""""""""""""""""""" + +The 'defconfig' for Linux arm and arm64 kernels should include the +right device drivers for virtio and the PCI controller; however some older +kernel versions, especially for 32-bit Arm, did not have everything +enabled by default. If you're not seeing PCI devices that you expect, +then check that your guest config has:: + + CONFIG_PCI=y + CONFIG_VIRTIO_PCI=y + CONFIG_PCI_HOST_GENERIC=y + +If you want to use the ``virtio-gpu-pci`` graphics device you will also +need:: + + CONFIG_DRM=y + CONFIG_DRM_VIRTIO_GPU=y + +Hardware configuration information for bare-metal programming +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +The ``virt`` board automatically generates a device tree blob ("dtb") +which it passes to the guest. This provides information about the +addresses, interrupt lines and other configuration of the various devices +in the system. Guest code can rely on and hard-code the following +addresses: + +- Flash memory starts at address 0x0000_0000 + +- RAM starts at 0x4000_0000 + +All other information about device locations may change between +QEMU versions, so guest code must look in the DTB. + +QEMU supports two types of guest image boot for ``virt``, and +the way for the guest code to locate the dtb binary differs: + +- For guests using the Linux kernel boot protocol (this means any + non-ELF file passed to the QEMU ``-kernel`` option) the address + of the DTB is passed in a register (``r2`` for 32-bit guests, + or ``x0`` for 64-bit guests) + +- For guests booting as "bare-metal" (any other kind of boot), + the DTB is at the start of RAM (0x4000_0000) diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst new file mode 100644 index 0000000000000000000000000000000000000000..2602d0f99530ed4d373f2a8b7766769c286e6c2d --- /dev/null +++ b/docs/system/arm/xlnx-versal-virt.rst @@ -0,0 +1,176 @@ +Xilinx Versal Virt (``xlnx-versal-virt``) +========================================= + +Xilinx Versal is a family of heterogeneous multi-core SoCs +(System on Chip) that combine traditional hardened CPUs and I/O +peripherals in a Processing System (PS) with runtime programmable +FPGA logic (PL) and an Artificial Intelligence Engine (AIE). + +More details here: +https://www.xilinx.com/products/silicon-devices/acap/versal.html + +The family of Versal SoCs share a single architecture but come in +different parts with different speed grades, amounts of PL and +other differences. + +The Xilinx Versal Virt board in QEMU is a model of a virtual board +(does not exist in reality) with a virtual Versal SoC without I/O +limitations. Currently, we support the following cores and devices: + +Implemented CPU cores: + +- 2 ACPUs (ARM Cortex-A72) + +Implemented devices: + +- Interrupt controller (ARM GICv3) +- 2 UARTs (ARM PL011) +- An RTC (Versal built-in) +- 2 GEMs (Cadence MACB Ethernet MACs) +- 8 ADMA (Xilinx zDMA) channels +- 2 SD Controllers +- OCM (256KB of On Chip Memory) +- DDR memory + +QEMU does not yet model any other devices, including the PL and the AI Engine. + +Other differences between the hardware and the QEMU model: + +- QEMU allows the amount of DDR memory provided to be specified with the + ``-m`` argument. If a DTB is provided on the command line then QEMU will + edit it to include suitable entries describing the Versal DDR memory ranges. + +- QEMU provides 8 virtio-mmio virtio transports; these start at + address ``0xa0000000`` and have IRQs from 111 and upwards. + +Running +""""""" +If the user provides an Operating System to be loaded, we expect users +to use the ``-kernel`` command line option. + +Users can load firmware or boot-loaders with the ``-device loader`` options. + +When loading an OS, QEMU generates a DTB and selects an appropriate address +where it gets loaded. This DTB will be passed to the kernel in register x0. + +If there's no ``-kernel`` option, we generate a DTB and place it at 0x1000 +for boot-loaders or firmware to pick it up. + +If users want to provide their own DTB, they can use the ``-dtb`` option. +These DTBs will have their memory nodes modified to match QEMU's +selected ram_size option before they get passed to the kernel or FW. + +When loading an OS, we turn on QEMU's PSCI implementation with SMC +as the PSCI conduit. When there's no ``-kernel`` option, we assume the user +provides EL3 firmware to handle PSCI. + +A few examples: + +Direct Linux boot of a generic ARM64 upstream Linux kernel: + +.. code-block:: bash + + $ qemu-system-aarch64 -M xlnx-versal-virt -m 2G \ + -serial mon:stdio -display none \ + -kernel arch/arm64/boot/Image \ + -nic user -nic user \ + -device virtio-rng-device,bus=virtio-mmio-bus.0 \ + -drive if=none,index=0,file=hd0.qcow2,id=hd0,snapshot \ + -drive file=qemu_sd.qcow2,if=sd,index=0,snapshot \ + -device virtio-blk-device,drive=hd0 -append root=/dev/vda + +Direct Linux boot of PetaLinux 2019.2: + +.. code-block:: bash + + $ qemu-system-aarch64 -M xlnx-versal-virt -m 2G \ + -serial mon:stdio -display none \ + -kernel petalinux-v2019.2/Image \ + -append "rdinit=/sbin/init console=ttyAMA0,115200n8 earlycon=pl011,mmio,0xFF000000,115200n8" \ + -net nic,model=cadence_gem,netdev=net0 -netdev user,id=net0 \ + -device virtio-rng-device,bus=virtio-mmio-bus.0,rng=rng0 \ + -object rng-random,filename=/dev/urandom,id=rng0 + +Boot PetaLinux 2019.2 via ARM Trusted Firmware (2018.3 because the 2019.2 +version of ATF tries to configure the CCI which we don't model) and U-boot: + +.. code-block:: bash + + $ qemu-system-aarch64 -M xlnx-versal-virt -m 2G \ + -serial stdio -display none \ + -device loader,file=petalinux-v2018.3/bl31.elf,cpu-num=0 \ + -device loader,file=petalinux-v2019.2/u-boot.elf \ + -device loader,addr=0x20000000,file=petalinux-v2019.2/Image \ + -nic user -nic user \ + -device virtio-rng-device,bus=virtio-mmio-bus.0,rng=rng0 \ + -object rng-random,filename=/dev/urandom,id=rng0 + +Run the following at the U-Boot prompt: + +.. code-block:: bash + + Versal> + fdt addr $fdtcontroladdr + fdt move $fdtcontroladdr 0x40000000 + fdt set /timer clock-frequency <0x3dfd240> + setenv bootargs "rdinit=/sbin/init maxcpus=1 console=ttyAMA0,115200n8 earlycon=pl011,mmio,0xFF000000,115200n8" + booti 20000000 - 40000000 + fdt addr $fdtcontroladdr + +Boot Linux as DOM0 on Xen via U-Boot: + +.. code-block:: bash + + $ qemu-system-aarch64 -M xlnx-versal-virt -m 4G \ + -serial stdio -display none \ + -device loader,file=petalinux-v2019.2/u-boot.elf,cpu-num=0 \ + -device loader,addr=0x30000000,file=linux/2018-04-24/xen \ + -device loader,addr=0x40000000,file=petalinux-v2019.2/Image \ + -nic user -nic user \ + -device virtio-rng-device,bus=virtio-mmio-bus.0,rng=rng0 \ + -object rng-random,filename=/dev/urandom,id=rng0 + +Run the following at the U-Boot prompt: + +.. code-block:: bash + + Versal> + fdt addr $fdtcontroladdr + fdt move $fdtcontroladdr 0x20000000 + fdt set /timer clock-frequency <0x3dfd240> + fdt set /chosen xen,xen-bootargs "console=dtuart dtuart=/uart@ff000000 dom0_mem=640M bootscrub=0 maxcpus=1 timer_slop=0" + fdt set /chosen xen,dom0-bootargs "rdinit=/sbin/init clk_ignore_unused console=hvc0 maxcpus=1" + fdt mknode /chosen dom0 + fdt set /chosen/dom0 compatible "xen,multiboot-module" + fdt set /chosen/dom0 reg <0x00000000 0x40000000 0x0 0x03100000> + booti 30000000 - 20000000 + +Boot Linux as Dom0 on Xen via ARM Trusted Firmware and U-Boot: + +.. code-block:: bash + + $ qemu-system-aarch64 -M xlnx-versal-virt -m 4G \ + -serial stdio -display none \ + -device loader,file=petalinux-v2018.3/bl31.elf,cpu-num=0 \ + -device loader,file=petalinux-v2019.2/u-boot.elf \ + -device loader,addr=0x30000000,file=linux/2018-04-24/xen \ + -device loader,addr=0x40000000,file=petalinux-v2019.2/Image \ + -nic user -nic user \ + -device virtio-rng-device,bus=virtio-mmio-bus.0,rng=rng0 \ + -object rng-random,filename=/dev/urandom,id=rng0 + +Run the following at the U-Boot prompt: + +.. code-block:: bash + + Versal> + fdt addr $fdtcontroladdr + fdt move $fdtcontroladdr 0x20000000 + fdt set /timer clock-frequency <0x3dfd240> + fdt set /chosen xen,xen-bootargs "console=dtuart dtuart=/uart@ff000000 dom0_mem=640M bootscrub=0 maxcpus=1 timer_slop=0" + fdt set /chosen xen,dom0-bootargs "rdinit=/sbin/init clk_ignore_unused console=hvc0 maxcpus=1" + fdt mknode /chosen dom0 + fdt set /chosen/dom0 compatible "xen,multiboot-module" + fdt set /chosen/dom0 reg <0x00000000 0x40000000 0x0 0x03100000> + booti 30000000 - 20000000 + diff --git a/docs/system/arm/xscale.rst b/docs/system/arm/xscale.rst index 89ec93e904e194bf7459161843c2ba4cb8d0377d..d2d5949e1026e3f6d868ad5aea13369ef20d329f 100644 --- a/docs/system/arm/xscale.rst +++ b/docs/system/arm/xscale.rst @@ -1,16 +1,22 @@ -Sharp XScale-based PDA models (``akita``, ``borzoi``, ``spitz``, ``terrier``) -============================================================================= +Sharp XScale-based PDA models (``akita``, ``borzoi``, ``spitz``, ``terrier``, ``tosa``) +======================================================================================= -The XScale-based clamshell PDA models (\"Spitz\", \"Akita\", \"Borzoi\" -and \"Terrier\") emulation includes the following peripherals: +The Sharp Zaurus are PDAs based on XScale, able to run Linux ('SL series'). -- Intel PXA270 System-on-chip (ARMv5TE core) +The SL-6000 (\"Tosa\"), released in 2005, uses a PXA255 System-on-chip. -- NAND Flash memory +The SL-C3000 (\"Spitz\"), SL-C1000 (\"Akita\"), SL-C3100 (\"Borzoi\") and +SL-C3200 (\"Terrier\") use a PXA270. + +The clamshell PDA models emulation includes the following peripherals: + +- Intel PXA255/PXA270 System-on-chip (ARMv5TE core) + +- NAND Flash memory - not in \"Tosa\" - IBM/Hitachi DSCM microdrive in a PXA PCMCIA slot - not in \"Akita\" -- On-chip OHCI USB controller +- On-chip OHCI USB controller - not in \"Tosa\" - On-chip LCD controller diff --git a/docs/system/build-platforms.rst b/docs/system/build-platforms.rst index c2b92a96987c187ce0a980a09cecce59599f3897..9734eba2f180b16a5d3f3875bbaea8a0c10744c4 100644 --- a/docs/system/build-platforms.rst +++ b/docs/system/build-platforms.rst @@ -57,12 +57,12 @@ macOS ----- The project supports building with the two most recent versions of -macOS, with the current homebrew package set available. +macOS, with the current Homebrew package set available. FreeBSD ------- -The project aims to support the all the versions which are not end of +The project aims to support all versions which are not end of life. NetBSD @@ -75,5 +75,5 @@ new major version is released. OpenBSD ------- -The project aims to support the all the versions which are not end of +The project aims to support all versions which are not end of life. diff --git a/docs/cpu-hotplug.rst b/docs/system/cpu-hotplug.rst similarity index 100% rename from docs/cpu-hotplug.rst rename to docs/system/cpu-hotplug.rst diff --git a/docs/system/cpu-models-mips.rst.inc b/docs/system/cpu-models-mips.rst.inc index 499b5b6fedb5782cae8b127a60b76dbad69d0b7c..02cc4bb884c105a7cfa57c5fe87db8b51617dad4 100644 --- a/docs/system/cpu-models-mips.rst.inc +++ b/docs/system/cpu-models-mips.rst.inc @@ -48,11 +48,17 @@ across all desired hosts. ``I6400`` MIPS64 Processor (Release 6, 2014) +``Loongson-2E`` + MIPS64 Processor (Loongson 2, 2006) + ``Loongson-2F`` MIPS64 Processor (Loongson 2, 2008) -``Loongson-2E`` - MIPS64 Processor (Loongson 2, 2006) +``Loongson-3A1000`` + MIPS64 Processor (Loongson 3, 2010) + +``Loongson-3A4000`` + MIPS64 Processor (Loongson 3, 2018) ``mips64dspr2`` MIPS64 Processor (Release 2, 2006) diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst index f0061f94aa10c47285b1b93fe17cf7549b3991dd..565389697e84277e8d638dc1b5f133bf603c318c 100644 --- a/docs/system/deprecated.rst +++ b/docs/system/deprecated.rst @@ -3,10 +3,11 @@ Deprecated features In general features are intended to be supported indefinitely once introduced into QEMU. In the event that a feature needs to be removed, -it will be listed in this section. The feature will remain functional -for 2 releases prior to actual removal. Deprecated features may also -generate warnings on the console when QEMU starts up, or if activated -via a monitor command, however, this is not a mandatory requirement. +it will be listed in this section. The feature will remain functional for the +release in which it was deprecated and one further release. After these two +releases, the feature is liable to be removed. Deprecated features may also +generate warnings on the console when QEMU starts up, or if activated via a +monitor command, however, this is not a mandatory requirement. Prior to the 2.10.0 release there was no official policy on how long features would be deprecated prior to their removal, nor @@ -20,17 +21,6 @@ deprecated. System emulator command line arguments -------------------------------------- -``-machine enforce-config-section=on|off`` (since 3.1) -'''''''''''''''''''''''''''''''''''''''''''''''''''''' - -The ``enforce-config-section`` parameter is replaced by the -``-global migration.send-configuration={on|off}`` option. - -``-no-kvm`` (since 1.3.0) -''''''''''''''''''''''''' - -The ``-no-kvm`` argument is now a synonym for setting ``-accel tcg``. - ``-usbdevice`` (since 2.10.0) ''''''''''''''''''''''''''''' @@ -47,25 +37,6 @@ The 'file' driver for drives is no longer appropriate for character or host devices and will only accept regular files (S_IFREG). The correct driver for these file types is 'host_cdrom' or 'host_device' as appropriate. -``-net ...,name=``\ *name* (since 3.1) -'''''''''''''''''''''''''''''''''''''' - -The ``name`` parameter of the ``-net`` option is a synonym -for the ``id`` parameter, which should now be used instead. - -``-smp`` (invalid topologies) (since 3.1) -''''''''''''''''''''''''''''''''''''''''' - -CPU topology properties should describe whole machine topology including -possible CPUs. - -However, historically it was possible to start QEMU with an incorrect topology -where *n* <= *sockets* * *cores* * *threads* < *maxcpus*, -which could lead to an incorrect topology enumeration by the guest. -Support for invalid topologies will be removed, the user must ensure -topologies described with -smp include all possible cpus, i.e. -*sockets* * *cores* * *threads* = *maxcpus*. - ``-vnc acl`` (since 4.0.0) '''''''''''''''''''''''''' @@ -85,9 +56,18 @@ Creating sound card devices and vnc without ``audiodev=`` property (since 4.2) When not using the deprecated legacy audio config, each sound card should specify an ``audiodev=`` property. Additionally, when using -vnc, you should specify an ``audiodev=`` propery if you plan to +vnc, you should specify an ``audiodev=`` property if you plan to transmit audio through the VNC protocol. +Creating sound card devices using ``-soundhw`` (since 5.1) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +Sound card devices should be created using ``-device`` instead. The +names are the same for most devices. The exceptions are ``hda`` which +needs two devices (``-device intel-hda -device hda-duplex``) and +``pcspk`` which can be activated using ``-machine +pcspk-audiodev=``. + ``-mon ...,control=readline,pretty=on|off`` (since 4.1) ''''''''''''''''''''''''''''''''''''''''''''''''''''''' @@ -101,62 +81,23 @@ error in the future. The ``-realtime mlock=on|off`` argument has been replaced by the ``-overcommit mem-lock=on|off`` argument. -``-numa node,mem=``\ *size* (since 4.1) -''''''''''''''''''''''''''''''''''''''' - -The parameter ``mem`` of ``-numa node`` is used to assign a part of -guest RAM to a NUMA node. But when using it, it's impossible to manage specified -RAM chunk on the host side (like bind it to a host node, setting bind policy, ...), -so guest end-ups with the fake NUMA configuration with suboptiomal performance. -However since 2014 there is an alternative way to assign RAM to a NUMA node -using parameter ``memdev``, which does the same as ``mem`` and adds -means to actualy manage node RAM on the host side. Use parameter ``memdev`` -with *memory-backend-ram* backend as an replacement for parameter ``mem`` -to achieve the same fake NUMA effect or a properly configured -*memory-backend-file* backend to actually benefit from NUMA configuration. -In future new machine versions will not accept the option but it will still -work with old machine types. User can check QAPI schema to see if the legacy -option is supported by looking at MachineInfo::numa-mem-supported property. - -``-numa`` node (without memory specified) (since 4.1) -''''''''''''''''''''''''''''''''''''''''''''''''''''' - -Splitting RAM by default between NUMA nodes has the same issues as ``mem`` -parameter described above with the difference that the role of the user plays -QEMU using implicit generic or board specific splitting rule. -Use ``memdev`` with *memory-backend-ram* backend or ``mem`` (if -it's supported by used machine type) to define mapping explictly instead. - -``-mem-path`` fallback to RAM (since 4.1) -''''''''''''''''''''''''''''''''''''''''' - -Currently if guest RAM allocation from file pointed by ``mem-path`` -fails, QEMU falls back to allocating from RAM, which might result -in unpredictable behavior since the backing file specified by the user -is ignored. In the future, users will be responsible for making sure -the backing storage specified with ``-mem-path`` can actually provide -the guest RAM configured with ``-m`` and QEMU will fail to start up if -RAM allocation is unsuccessful. - -RISC-V ``-bios`` (since 4.1) +RISC-V ``-bios`` (since 5.1) '''''''''''''''''''''''''''' QEMU 4.1 introduced support for the -bios option in QEMU for RISC-V for the -RISC-V virt machine and sifive_u machine. - -QEMU 4.1 has no changes to the default behaviour to avoid breakages. This -default will change in a future QEMU release, so please prepare now. All users -of the virt or sifive_u machine must change their command line usage. - -QEMU 4.1 has three options, please migrate to one of these three: - 1. ``-bios none`` - This is the current default behavior if no -bios option - is included. QEMU will not automatically load any firmware. It is up +RISC-V virt machine and sifive_u machine. QEMU 4.1 had no changes to the +default behaviour to avoid breakages. + +QEMU 5.1 changes the default behaviour from ``-bios none`` to ``-bios default``. + +QEMU 5.1 has three options: + 1. ``-bios default`` - This is the current default behavior if no -bios option + is included. This option will load the default OpenSBI firmware automatically. + The firmware is included with the QEMU release and no user interaction is + required. All a user needs to do is specify the kernel they want to boot + with the -kernel option + 2. ``-bios none`` - QEMU will not automatically load any firmware. It is up to the user to load all the images they need. - 2. ``-bios default`` - In a future QEMU release this will become the default - behaviour if no -bios option is specified. This option will load the - default OpenSBI firmware automatically. The firmware is included with - the QEMU release and no user interaction is required. All a user needs - to do is specify the kernel they want to boot with the -kernel option 3. ``-bios `` - Tells QEMU to load the specified file as the firmwrae. ``-tb-size`` option (since 5.0) @@ -172,6 +113,40 @@ previously available ``-tb-size`` option. Use ``-display sdl,show-cursor=on`` or ``-display gtk,show-cursor=on`` instead. +``Configuring floppies with ``-global`` +''''''''''''''''''''''''''''''''''''''' + +Use ``-device floppy,...`` instead: +:: + + -global isa-fdc.driveA=... + -global sysbus-fdc.driveA=... + -global SUNW,fdtwo.drive=... + +become +:: + + -device floppy,unit=0,drive=... + +and +:: + + -global isa-fdc.driveB=... + -global sysbus-fdc.driveB=... + +become +:: + + -device floppy,unit=1,drive=... + +``-drive`` with bogus interface type +'''''''''''''''''''''''''''''''''''' + +Drives with interface types other than ``if=none`` are for onboard +devices. It is possible to use drives the board doesn't pick up with +-device. This usage is now deprecated. Use ``if=none`` instead. + + QEMU Machine Protocol (QMP) commands ------------------------------------ @@ -266,13 +241,6 @@ The ``query-cpus`` command is replaced by the ``query-cpus-fast`` command. The ``arch`` output member of the ``query-cpus-fast`` command is replaced by the ``target`` output member. -``cpu-add`` (since 4.0) -''''''''''''''''''''''' - -Use ``device_add`` for hotplugging vCPUs instead of ``cpu-add``. See -documentation of ``query-hotpluggable-cpus`` for additional -details. - ``query-events`` (since 4.0) '''''''''''''''''''''''''''' @@ -285,14 +253,15 @@ chardev client socket with ``wait`` option (since 4.0) Character devices creating sockets in client mode should not specify the 'wait' field, which is only applicable to sockets in server mode -Human Monitor Protocol (HMP) commands -------------------------------------- +``nbd-server-add`` and ``nbd-server-remove`` (since 5.2) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''' -``cpu-add`` (since 4.0) -''''''''''''''''''''''' +Use the more generic commands ``block-export-add`` and ``block-export-del`` +instead. As part of this deprecation, where ``nbd-server-add`` used a +single ``bitmap``, the new ``block-export-add`` uses a list of ``bitmaps``. -Use ``device_add`` for hotplugging vCPUs instead of ``cpu-add``. See -documentation of ``query-hotpluggable-cpus`` for additional details. +Human Monitor Protocol (HMP) commands +------------------------------------- ``acl_show``, ``acl_reset``, ``acl_policy``, ``acl_add``, ``acl_remove`` (since 4.0.0) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' @@ -301,33 +270,16 @@ The ``acl_show``, ``acl_reset``, ``acl_policy``, ``acl_add``, and ``acl_remove`` commands are deprecated with no replacement. Authorization for VNC should be performed using the pluggable QAuthZ objects. -Guest Emulator ISAs -------------------- - -RISC-V ISA privledge specification version 1.09.1 (since 4.1) -''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -The RISC-V ISA privledge specification version 1.09.1 has been deprecated. -QEMU supports both the newer version 1.10.0 and the ratified version 1.11.0, these -should be used instead of the 1.09.1 version. - System emulator CPUS -------------------- -RISC-V ISA CPUs (since 4.1) +``moxie`` CPU (since 5.2.0) ''''''''''''''''''''''''''' -The RISC-V cpus with the ISA version in the CPU name have been depcreated. The -four CPUs are: ``rv32gcsu-v1.9.1``, ``rv32gcsu-v1.10.0``, ``rv64gcsu-v1.9.1`` and -``rv64gcsu-v1.10.0``. Instead the version can be specified via the CPU ``priv_spec`` -option when using the ``rv32`` or ``rv64`` CPUs. - -RISC-V ISA CPUs (since 4.1) -''''''''''''''''''''''''''' - -The RISC-V no MMU cpus have been depcreated. The two CPUs: ``rv32imacu-nommu`` and -``rv64imacu-nommu`` should no longer be used. Instead the MMU status can be specified -via the CPU ``mmu`` option when using the ``rv32`` or ``rv64`` CPUs. +The ``moxie`` guest CPU support is deprecated and will be removed in +a future version of QEMU. It's unclear whether anybody is still using +CPU emulation in QEMU, and there are no test images available to make +sure that the code is still working. ``compat`` property of server class POWER CPUs (since 5.0) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''' @@ -336,13 +288,34 @@ The ``compat`` property used to set backwards compatibility modes for the processor has been deprecated. The ``max-cpu-compat`` property of the ``pseries`` machine type should be used instead. -KVM guest support on 32-bit Arm hosts (since 5.0) -''''''''''''''''''''''''''''''''''''''''''''''''' +``lm32`` CPUs (since 5.2.0) +''''''''''''''''''''''''''' -The Linux kernel has dropped support for allowing 32-bit Arm systems -to host KVM guests as of the 5.7 kernel. Accordingly, QEMU is deprecating -its support for this configuration and will remove it in a future version. -Running 32-bit guests on a 64-bit Arm host remains supported. +The ``lm32`` guest CPU support is deprecated and will be removed in +a future version of QEMU. The only public user of this architecture +was the milkymist project, which has been dead for years; there was +never an upstream Linux port. + +``unicore32`` CPUs (since 5.2.0) +'''''''''''''''''''''''''''''''' + +The ``unicore32`` guest CPU support is deprecated and will be removed in +a future version of QEMU. Support for this CPU was removed from the +upstream Linux kernel, and there is no available upstream toolchain +to build binaries for it. + +``Icelake-Client`` CPU Model (since 5.2.0) +'''''''''''''''''''''''''''''''''''''''''' + +``Icelake-Client`` CPU Models are deprecated. Use ``Icelake-Server`` CPU +Models instead. + +MIPS ``I7200`` CPU Model (since 5.2) +'''''''''''''''''''''''''''''''''''' + +The ``I7200`` guest CPU relies on the nanoMIPS ISA, which is deprecated +(the ISA has never been upstreamed to a compiler toolchain). Therefore +this CPU is also deprecated. System emulator devices ----------------------- @@ -362,12 +335,6 @@ The 'scsi-disk' device is deprecated. Users should use 'scsi-hd' or System emulator machines ------------------------ -mips ``r4k`` platform (since 5.0) -''''''''''''''''''''''''''''''''' - -This machine type is very old and unmaintained. Users should use the ``malta`` -machine type instead. - mips ``fulong2e`` machine (since 5.1) ''''''''''''''''''''''''''''''''''''' @@ -379,12 +346,12 @@ This machine has been renamed ``fuloong2e``. These machine types are very old and likely can not be used for live migration from old QEMU versions anymore. A newer machine type should be used instead. -``spike_v1.9.1`` and ``spike_v1.10`` (since 4.1) -'''''''''''''''''''''''''''''''''''''''''''''''' +Raspberry Pi ``raspi2`` and ``raspi3`` machines (since 5.2) +''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' -The version specific Spike machines have been deprecated in favour of the -generic ``spike`` machine. If you need to specify an older version of the RISC-V -spec you can use the ``-cpu rv64gcsu,priv_spec=v1.9.1`` command line argument. +The Raspberry Pi machines come in various models (A, A+, B, B+). To be able +to distinguish which model QEMU is implementing, the ``raspi2`` and ``raspi3`` +machines have been renamed ``raspi2b`` and ``raspi3b``. Device options -------------- @@ -427,16 +394,74 @@ The above, converted to the current supported format:: json:{"file.driver":"rbd", "file.pool":"rbd", "file.image":"name"} +``sheepdog`` driver (since 5.2.0) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``sheepdog`` block device driver is deprecated. The corresponding upstream +server project is no longer actively maintained. Users are recommended to switch +to an alternative distributed block device driver such as RBD. The +``qemu-img convert`` command can be used to liberate existing data by moving +it out of sheepdog volumes into an alternative storage backend. + +linux-user mode CPUs +-------------------- + +``tilegx`` CPUs (since 5.1.0) +''''''''''''''''''''''''''''' + +The ``tilegx`` guest CPU support (which was only implemented in +linux-user mode) is deprecated and will be removed in a future version +of QEMU. Support for this CPU was removed from the upstream Linux +kernel in 2018, and has also been dropped from glibc. + +``ppc64abi32`` CPUs (since 5.2.0) +''''''''''''''''''''''''''''''''' + +The ``ppc64abi32`` architecture has a number of issues which regularly +trip up our CI testing and is suspected to be quite broken. For that +reason the maintainers strongly suspect no one actually uses it. + +MIPS ``I7200`` CPU (since 5.2) +'''''''''''''''''''''''''''''' + +The ``I7200`` guest CPU relies on the nanoMIPS ISA, which is deprecated +(the ISA has never been upstreamed to a compiler toolchain). Therefore +this CPU is also deprecated. + Related binaries ---------------- -``qemu-img convert -n -o`` (since 4.2.0) -'''''''''''''''''''''''''''''''''''''''' +qemu-img amend to adjust backing file (since 5.1) +''''''''''''''''''''''''''''''''''''''''''''''''' -All options specified in ``-o`` are image creation options, so -they have no effect when used with ``-n`` to skip image creation. -Silently ignored options can be confusing, so this combination of -options will be made an error in future versions. +The use of ``qemu-img amend`` to modify the name or format of a qcow2 +backing image is deprecated; this functionality was never fully +documented or tested, and interferes with other amend operations that +need access to the original backing image (such as deciding whether a +v3 zero cluster may be left unallocated when converting to a v2 +image). Rather, any changes to the backing chain should be performed +with ``qemu-img rebase -u`` either before or after the remaining +changes being performed by amend, as appropriate. + +qemu-img backing file without format (since 5.1) +'''''''''''''''''''''''''''''''''''''''''''''''' + +The use of ``qemu-img create``, ``qemu-img rebase``, or ``qemu-img +convert`` to create or modify an image that depends on a backing file +now recommends that an explicit backing format be provided. This is +for safety: if QEMU probes a different format than what you thought, +the data presented to the guest will be corrupt; similarly, presenting +a raw image to a guest allows a potential security exploit if a future +probe sees a non-raw image based on guest writes. + +To avoid the warning message, or even future refusal to create an +unsafe image, you must pass ``-o backing_fmt=`` (or the shorthand +``-F`` during create) to specify the intended backing format. You may +use ``qemu-img rebase -u`` to retroactively add a backing format to an +existing image. However, be aware that there are already potential +security risks to blindly using ``qemu-img info`` to probe the format +of an untrusted backing image, when deciding what format to add into +an existing image. Backwards compatibility ----------------------- @@ -455,7 +480,7 @@ default configuration. The CPU model runnability guarantee won't apply anymore to existing CPU models. Management software that needs runnability -guarantees must resolve the CPU model aliases using te +guarantees must resolve the CPU model aliases using the ``alias-of`` field returned by the ``query-cpu-definitions`` QMP command. @@ -467,6 +492,15 @@ versions, aliases will point to newer CPU model versions depending on the machine type, so management software must resolve CPU model aliases before starting a virtual machine. +Guest Emulator ISAs +------------------- + +nanoMIPS ISA +'''''''''''' + +The ``nanoMIPS`` ISA has never been upstreamed to any compiler toolchain. +As it is hard to generate binaries for it, declare it deprecated. + Recently removed features ========================= @@ -475,6 +509,21 @@ What follows is a record of recently removed, formerly deprecated features that serves as a record for users who have encountered trouble after a recent upgrade. +System emulator command line arguments +-------------------------------------- + +``-net ...,name=``\ *name* (removed in 5.1) +''''''''''''''''''''''''''''''''''''''''''' + +The ``name`` parameter of the ``-net`` option was a synonym +for the ``id`` parameter, which should now be used instead. + +``-no-kvm`` (removed in 5.2) +'''''''''''''''''''''''''''' + +The ``-no-kvm`` argument was a synonym for setting ``-machine accel=tcg``. + + QEMU Machine Protocol (QMP) commands ------------------------------------ @@ -484,6 +533,12 @@ QEMU Machine Protocol (QMP) commands The "autoload" parameter has been ignored since 2.12.0. All bitmaps are automatically loaded from qcow2 images. +``cpu-add`` (removed in 5.2) +'''''''''''''''''''''''''''' + +Use ``device_add`` for hotplugging vCPUs instead of ``cpu-add``. See +documentation of ``query-hotpluggable-cpus`` for additional details. + Human Monitor Protocol (HMP) commands ------------------------------------- @@ -493,11 +548,69 @@ The ``hub_id`` parameter of ``hostfwd_add`` / ``hostfwd_remove`` (removed in 5.0 The ``[hub_id name]`` parameter tuple of the 'hostfwd_add' and 'hostfwd_remove' HMP commands has been replaced by ``netdev_id``. +``cpu-add`` (removed in 5.2) +'''''''''''''''''''''''''''' + +Use ``device_add`` for hotplugging vCPUs instead of ``cpu-add``. See +documentation of ``query-hotpluggable-cpus`` for additional details. + +Guest Emulator ISAs +------------------- + +RISC-V ISA privilege specification version 1.09.1 (removed in 5.1) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The RISC-V ISA privilege specification version 1.09.1 has been removed. +QEMU supports both the newer version 1.10.0 and the ratified version 1.11.0, these +should be used instead of the 1.09.1 version. + +System emulator CPUS +-------------------- + +KVM guest support on 32-bit Arm hosts (removed in 5.2) +'''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The Linux kernel has dropped support for allowing 32-bit Arm systems +to host KVM guests as of the 5.7 kernel. Accordingly, QEMU is deprecating +its support for this configuration and will remove it in a future version. +Running 32-bit guests on a 64-bit Arm host remains supported. + +RISC-V ISA Specific CPUs (removed in 5.1) +''''''''''''''''''''''''''''''''''''''''' + +The RISC-V cpus with the ISA version in the CPU name have been removed. The +four CPUs are: ``rv32gcsu-v1.9.1``, ``rv32gcsu-v1.10.0``, ``rv64gcsu-v1.9.1`` and +``rv64gcsu-v1.10.0``. Instead the version can be specified via the CPU ``priv_spec`` +option when using the ``rv32`` or ``rv64`` CPUs. + +RISC-V no MMU CPUs (removed in 5.1) +''''''''''''''''''''''''''''''''''' + +The RISC-V no MMU cpus have been removed. The two CPUs: ``rv32imacu-nommu`` and +``rv64imacu-nommu`` can no longer be used. Instead the MMU status can be specified +via the CPU ``mmu`` option when using the ``rv32`` or ``rv64`` CPUs. + +System emulator machines +------------------------ + +``spike_v1.9.1`` and ``spike_v1.10`` (removed in 5.1) +''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The version specific Spike machines have been removed in favour of the +generic ``spike`` machine. If you need to specify an older version of the RISC-V +spec you can use the ``-cpu rv64gcsu,priv_spec=v1.10.0`` command line argument. + +mips ``r4k`` platform (removed in 5.2) +'''''''''''''''''''''''''''''''''''''' + +This machine type was very old and unmaintained. Users should use the ``malta`` +machine type instead. + Related binaries ---------------- -``qemu-nbd --partition`` (removed in 5.0.0) -''''''''''''''''''''''''''''''''''''''''''' +``qemu-nbd --partition`` (removed in 5.0) +''''''''''''''''''''''''''''''''''''''''' The ``qemu-nbd --partition $digit`` code (also spelled ``-P``) could only handle MBR partitions, and never correctly handled logical @@ -512,3 +625,105 @@ long starting at 1MiB, the old command:: can be rewritten as:: qemu-nbd -t --image-opts driver=raw,offset=1M,size=100M,file.driver=qcow2,file.file.driver=file,file.file.filename=file.qcow2 + +``qemu-img convert -n -o`` (removed in 5.1) +''''''''''''''''''''''''''''''''''''''''''' + +All options specified in ``-o`` are image creation options, so +they are now rejected when used with ``-n`` to skip image creation. + + +``qemu-img create -b bad file $size`` (removed in 5.1) +'''''''''''''''''''''''''''''''''''''''''''''''''''''' + +When creating an image with a backing file that could not be opened, +``qemu-img create`` used to issue a warning about the failure but +proceed with the image creation if an explicit size was provided. +However, as the ``-u`` option exists for this purpose, it is safer to +enforce that any failure to open the backing image (including if the +backing file is missing or an incorrect format was specified) is an +error when ``-u`` is not used. + +Command line options +-------------------- + +``-smp`` (invalid topologies) (removed 5.2) +''''''''''''''''''''''''''''''''''''''''''' + +CPU topology properties should describe whole machine topology including +possible CPUs. + +However, historically it was possible to start QEMU with an incorrect topology +where *n* <= *sockets* * *cores* * *threads* < *maxcpus*, +which could lead to an incorrect topology enumeration by the guest. +Support for invalid topologies is removed, the user must ensure +topologies described with -smp include all possible cpus, i.e. +*sockets* * *cores* * *threads* = *maxcpus*. + +``-numa`` node (without memory specified) (removed 5.2) +''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +Splitting RAM by default between NUMA nodes had the same issues as ``mem`` +parameter with the difference that the role of the user plays QEMU using +implicit generic or board specific splitting rule. +Use ``memdev`` with *memory-backend-ram* backend or ``mem`` (if +it's supported by used machine type) to define mapping explicitly instead. +Users of existing VMs, wishing to preserve the same RAM distribution, should +configure it explicitly using ``-numa node,memdev`` options. Current RAM +distribution can be retrieved using HMP command ``info numa`` and if separate +memory devices (pc|nv-dimm) are present use ``info memory-device`` and subtract +device memory from output of ``info numa``. + +``-numa node,mem=``\ *size* (removed in 5.1) +'''''''''''''''''''''''''''''''''''''''''''' + +The parameter ``mem`` of ``-numa node`` was used to assign a part of +guest RAM to a NUMA node. But when using it, it's impossible to manage a specified +RAM chunk on the host side (like bind it to a host node, setting bind policy, ...), +so the guest ends up with the fake NUMA configuration with suboptiomal performance. +However since 2014 there is an alternative way to assign RAM to a NUMA node +using parameter ``memdev``, which does the same as ``mem`` and adds +means to actually manage node RAM on the host side. Use parameter ``memdev`` +with *memory-backend-ram* backend as replacement for parameter ``mem`` +to achieve the same fake NUMA effect or a properly configured +*memory-backend-file* backend to actually benefit from NUMA configuration. +New machine versions (since 5.1) will not accept the option but it will still +work with old machine types. User can check the QAPI schema to see if the legacy +option is supported by looking at MachineInfo::numa-mem-supported property. + +``-mem-path`` fallback to RAM (removed in 5.0) +'''''''''''''''''''''''''''''''''''''''''''''' + +If guest RAM allocation from file pointed by ``mem-path`` failed, +QEMU was falling back to allocating from RAM, which might have resulted +in unpredictable behavior since the backing file specified by the user +as ignored. Currently, users are responsible for making sure the backing storage +specified with ``-mem-path`` can actually provide the guest RAM configured with +``-m`` and QEMU fails to start up if RAM allocation is unsuccessful. + +``-smp`` (invalid topologies) (removed 5.2) +''''''''''''''''''''''''''''''''''''''''''' + +CPU topology properties should describe whole machine topology including +possible CPUs. + +However, historically it was possible to start QEMU with an incorrect topology +where *n* <= *sockets* * *cores* * *threads* < *maxcpus*, +which could lead to an incorrect topology enumeration by the guest. +Support for invalid topologies is removed, the user must ensure +topologies described with -smp include all possible cpus, i.e. +*sockets* * *cores* * *threads* = *maxcpus*. + +``-machine enforce-config-section=on|off`` (removed 5.2) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The ``enforce-config-section`` property was replaced by the +``-global migration.send-configuration={on|off}`` option. + +Block devices +------------- + +VXHS backend (removed in 5.1) +''''''''''''''''''''''''''''' + +The VXHS code does not compile since v2.12.0. It was removed in 5.1. diff --git a/docs/system/device-url-syntax.rst.inc b/docs/system/device-url-syntax.rst.inc index 88d7a372a748540cb8915abc92734c34018c9870..6f6ec8366b7a3bfd5879363452324b4af6123d10 100644 --- a/docs/system/device-url-syntax.rst.inc +++ b/docs/system/device-url-syntax.rst.inc @@ -25,8 +25,8 @@ These are specified using a special URL syntax. .. parsed-literal:: - |qemu_system| -iscsi initiator-name=iqn.2001-04.com.example:my-initiator \ - -cdrom iscsi://192.0.2.1/iqn.2001-04.com.example/2 \ + |qemu_system| -iscsi initiator-name=iqn.2001-04.com.example:my-initiator \\ + -cdrom iscsi://192.0.2.1/iqn.2001-04.com.example/2 \\ -drive file=iscsi://192.0.2.1/iqn.2001-04.com.example/1 Example (CHAP username/password via URL): @@ -39,8 +39,8 @@ These are specified using a special URL syntax. .. parsed-literal:: - LIBISCSI_CHAP_USERNAME="user" \ - LIBISCSI_CHAP_PASSWORD="password" \ + LIBISCSI_CHAP_USERNAME="user" \\ + LIBISCSI_CHAP_PASSWORD="password" \\ |qemu_system| -drive file=iscsi://192.0.2.1/iqn.2001-04.com.example/1 ``NBD`` diff --git a/docs/system/gdb.rst b/docs/system/gdb.rst index a40145fcf849bf4ee42197d25bbcabe1dec75914..72b1e68f4ef3d82d29419696d69746a2b224fb0f 100644 --- a/docs/system/gdb.rst +++ b/docs/system/gdb.rst @@ -1,4 +1,4 @@ -.. _gdb_005fusage: +.. _GDB usage: GDB usage --------- @@ -87,3 +87,23 @@ three commands you can query and set the single step behavior: (gdb) maintenance packet Qqemu.sstep=0x5 sending: "qemu.sstep=0x5" received: "OK" + + +Another feature that QEMU gdbstub provides is to toggle the memory GDB +works with, by default GDB will show the current process memory respecting +the virtual address translation. + +If you want to examine/change the physical memory you can set the gdbstub +to work with the physical memory rather with the virtual one. + +The memory mode can be checked by sending the following command: + +``maintenance packet qqemu.PhyMemMode`` + This will return either 0 or 1, 1 indicates you are currently in the + physical memory mode. + +``maintenance packet Qqemu.PhyMemMode:1`` + This will change the memory mode to physical memory. + +``maintenance packet Qqemu.PhyMemMode:0`` + This will change it back to normal memory mode. diff --git a/docs/microvm.rst b/docs/system/i386/microvm.rst similarity index 98% rename from docs/microvm.rst rename to docs/system/i386/microvm.rst index fcf41fc1f6f67e713eb71b6f196598d6afc14e8c..1675e37d3e73f04649332f311f2f0368a13a2ca7 100644 --- a/docs/microvm.rst +++ b/docs/system/i386/microvm.rst @@ -1,6 +1,5 @@ -==================== -microvm Machine Type -==================== +'microvm' virtual platform (``microvm``) +======================================== ``microvm`` is a machine type inspired by ``Firecracker`` and constructed after its machine model. diff --git a/docs/system/i386/pc.rst b/docs/system/i386/pc.rst new file mode 100644 index 0000000000000000000000000000000000000000..d543c11a5cd31ed1c8683948555d23091632c952 --- /dev/null +++ b/docs/system/i386/pc.rst @@ -0,0 +1,7 @@ +i440fx PC (``pc-i440fx``, ``pc``) +================================= + +Peripherals +~~~~~~~~~~~ + +.. include:: ../target-i386-desc.rst.inc diff --git a/docs/system/images.rst b/docs/system/images.rst index ff26bf9587502fc87e5b0a2bbb138524e44bec19..3d9144e6258b7e30bb3bd3a9a14e1498b8412e5b 100644 --- a/docs/system/images.rst +++ b/docs/system/images.rst @@ -1,4 +1,4 @@ -.. _disk_005fimages: +.. _disk images: Disk Images ----------- diff --git a/docs/system/index.rst b/docs/system/index.rst index c0f685b818e5b71b1306c8609037e55f00db3552..e5a35817a24a2ba84cab30040b01ccdd26dd9996 100644 --- a/docs/system/index.rst +++ b/docs/system/index.rst @@ -21,6 +21,7 @@ Contents: monitor images net + virtio-net-failover usb ivshmem linuxboot @@ -28,6 +29,9 @@ Contents: tls gdb managed-startup + cpu-hotplug + virtio-pmem + pr-manager targets security deprecated diff --git a/docs/system/monitor.rst b/docs/system/monitor.rst index 0bcd5da21644fd4423507bcc7b7c1fb6b79862e8..ff5c434612237fbb48d8bb5d53e3837b85f3b5b2 100644 --- a/docs/system/monitor.rst +++ b/docs/system/monitor.rst @@ -1,4 +1,4 @@ -.. _pcsys_005fmonitor: +.. _QEMU monitor: QEMU Monitor ------------ diff --git a/docs/system/mux-chardev.rst b/docs/system/mux-chardev.rst index 413a6b3446053c3292fa1f88dc038a9c305e62b4..05064068aa02c37c65821deb9d6fbe514e9bae4d 100644 --- a/docs/system/mux-chardev.rst +++ b/docs/system/mux-chardev.rst @@ -1,4 +1,4 @@ -.. _mux_005fkeys: +.. _keys in the character backend multiplexer: Keys in the character backend multiplexer ----------------------------------------- diff --git a/docs/pr-manager.rst b/docs/system/pr-manager.rst similarity index 68% rename from docs/pr-manager.rst rename to docs/system/pr-manager.rst index 9b1de198b1b8700da61652df39e7b139f087ede5..b19a0c15e662f84f3b230ff3aabdfeab22453833 100644 --- a/docs/pr-manager.rst +++ b/docs/system/pr-manager.rst @@ -1,8 +1,8 @@ -====================================== +=============================== Persistent reservation managers -====================================== +=============================== -SCSI persistent Reservations allow restricting access to block devices +SCSI persistent reservations allow restricting access to block devices to specific initiators in a shared storage setup. When implementing clustering of virtual machines, it is a common requirement for virtual machines to send persistent reservation SCSI commands. However, @@ -50,39 +50,11 @@ Alternatively, using ``-blockdev``:: -blockdev node-name=hd,driver=raw,file.driver=host_device,file.filename=/dev/sdb,file.pr-manager=helper0 -device scsi-block,drive=hd ----------------------------------- -Invoking :program:`qemu-pr-helper` ----------------------------------- - -QEMU provides an implementation of the persistent reservation helper, -called :program:`qemu-pr-helper`. The helper should be started as a -system service and supports the following option: - --d, --daemon run in the background --q, --quiet decrease verbosity --v, --verbose increase verbosity --f, --pidfile=path PID file when running as a daemon --k, --socket=path path to the socket --T, --trace=trace-opts tracing options - -By default, the socket and PID file are placed in the runtime state -directory, for example :file:`/var/run/qemu-pr-helper.sock` and -:file:`/var/run/qemu-pr-helper.pid`. The PID file is not created -unless :option:`-d` is passed too. - -:program:`qemu-pr-helper` can also use the systemd socket activation -protocol. In this case, the systemd socket unit should specify a -Unix stream socket, like this:: - - [Socket] - ListenStream=/var/run/qemu-pr-helper.sock - -After connecting to the socket, :program:`qemu-pr-helper`` can optionally drop -root privileges, except for those capabilities that are needed for -its operation. To do this, add the following options: - --u, --user=user user to drop privileges to --g, --group=group group to drop privileges to +You will also need to ensure that the helper program +:command:`qemu-pr-helper` is running, and that it has been +set up to use the same socket filename as your QEMU commandline +specifies. See the qemu-pr-helper documentation or manpage for +further details. --------------------------------------------- Multipath devices and persistent reservations diff --git a/docs/system/s390x/3270.rst b/docs/system/s390x/3270.rst new file mode 100644 index 0000000000000000000000000000000000000000..0554a70a9ff00046d9a56b9c9fb613091144d298 --- /dev/null +++ b/docs/system/s390x/3270.rst @@ -0,0 +1,63 @@ +3270 devices +============ + +The 3270 is the classic 'green-screen' console of the mainframes (see the +`IBM 3270 Wikipedia article `__). + +The 3270 data stream is not implemented within QEMU; the device only provides +TN3270 (a telnet extension; see `RFC 854 `__ +and `RFC 1576 `__) and leaves the heavy +lifting to an external 3270 terminal emulator (such as ``x3270``) to make a +single 3270 device available to a guest. Note that this supports basic +features only. + +To provide a 3270 device to a guest, create a ``x-terminal3270`` linked to +a ``tn3270`` chardev. The guest will see a 3270 channel device. In order +to actually be able to use it, attach the ``x3270`` emulator to the chardev. + +Example configuration +--------------------- + +* Make sure that 3270 support is enabled in the guest's Linux kernel. You need + ``CONFIG_TN3270`` and at least one of ``CONFIG_TN3270_TTY`` (for additional + ttys) or ``CONFIG_TN3270_CONSOLE`` (for a 3270 console). + +* Add a ``tn3270`` chardev and a ``x-terminal3270`` to the QEMU command line:: + + -chardev socket,id=ch0,host=0.0.0.0,port=2300,nowait,server,tn3270 + -device x-terminal3270,chardev=ch0,devno=fe.0.000a,id=terminal0 + +* Start the guest. In the guest, use ``chccwdev -e 0.0.000a`` to enable + the device. + +* On the host, start the ``x3270`` emulator:: + + x3270 :2300 + +* In the guest, locate the 3270 device node under ``/dev/3270/`` (say, + ``tty1``) and start a getty on it:: + + systemctl start serial-getty@3270-tty1.service + + This should get you an additional tty for logging into the guest. + +* If you want to use the 3270 device as the Linux kernel console instead of + an additional tty, you can also append ``conmode=3270 condev=000a`` to + the guest's kernel command line. The kernel then should use the 3270 as + console after the next boot. + +Restrictions +------------ + +3270 support is very basic. In particular: + +* Only one 3270 device is supported. + +* It has only been tested with Linux guests and the x3270 emulator. + +* TLS/SSL is not supported. + +* Resizing on reattach is not supported. + +* Multiple commands in one inbound buffer (for example, when the reset key + is pressed while the network is slow) are not supported. diff --git a/docs/system/s390x/bootdevices.rst b/docs/system/s390x/bootdevices.rst new file mode 100644 index 0000000000000000000000000000000000000000..9e591cb9dc36a5a8f04e1ee415ee1a0d4b890a3e --- /dev/null +++ b/docs/system/s390x/bootdevices.rst @@ -0,0 +1,82 @@ +Boot devices on s390x +===================== + +Booting with bootindex parameter +-------------------------------- + +For classical mainframe guests (i.e. LPAR or z/VM installations), you always +have to explicitly specify the disk where you want to boot from (or "IPL" from, +in s390x-speak -- IPL means "Initial Program Load"). In particular, there can +also be only one boot device according to the architecture specification, thus +specifying multiple boot devices is not possible (yet). + +So for booting an s390x guest in QEMU, you should always mark the +device where you want to boot from with the ``bootindex`` property, for +example:: + + qemu-system-s390x -drive if=none,id=dr1,file=guest.qcow2 \ + -device virtio-blk,drive=dr1,bootindex=1 + +For booting from a CD-ROM ISO image (which needs to include El-Torito boot +information in order to be bootable), it is recommended to specify a ``scsi-cd`` +device, for example like this:: + + qemu-system-s390x -blockdev file,node-name=c1,filename=... \ + -device virtio-scsi \ + -device scsi-cd,drive=c1,bootindex=1 + +Note that you really have to use the ``bootindex`` property to select the +boot device. The old-fashioned ``-boot order=...`` command of QEMU (and +also ``-boot once=...``) is not supported on s390x. + + +Booting without bootindex parameter +----------------------------------- + +The QEMU guest firmware (the so-called s390-ccw bios) has also some rudimentary +support for scanning through the available block devices. So in case you did +not specify a boot device with the ``bootindex`` property, there is still a +chance that it finds a bootable device on its own and starts a guest operating +system from it. However, this scanning algorithm is still very rough and may +be incomplete, so that it might fail to detect a bootable device in many cases. +It is really recommended to always specify the boot device with the +``bootindex`` property instead. + +This also means that you should avoid the classical short-cut commands like +``-hda``, ``-cdrom`` or ``-drive if=virtio``, since it is not possible to +specify the ``bootindex`` with these commands. Note that the convenience +``-cdrom`` option even does not give you a real (virtio-scsi) CD-ROM device on +s390x. Due to technical limitations in the QEMU code base, you will get a +virtio-blk device with this parameter instead, which might not be the right +device type for installing a Linux distribution via ISO image. It is +recommended to specify a CD-ROM device via ``-device scsi-cd`` (as mentioned +above) instead. + + +Booting from a network device +----------------------------- + +Beside the normal guest firmware (which is loaded from the file ``s390-ccw.img`` +in the data directory of QEMU, or via the ``-bios`` option), QEMU ships with +a small TFTP network bootloader firmware for virtio-net-ccw devices, too. This +firmware is loaded from a file called ``s390-netboot.img`` in the QEMU data +directory. In case you want to load it from a different filename instead, +you can specify it via the ``-global s390-ipl.netboot_fw=filename`` +command line option. + +The ``bootindex`` property is especially important for booting via the network. +If you don't specify the the ``bootindex`` property here, the network bootloader +firmware code won't get loaded into the guest memory so that the network boot +will fail. For a successful network boot, try something like this:: + + qemu-system-s390x -netdev user,id=n1,tftp=...,bootfile=... \ + -device virtio-net-ccw,netdev=n1,bootindex=1 + +The network bootloader firmware also has basic support for pxelinux.cfg-style +configuration files. See the `PXELINUX Configuration page +`__ +for details how to set up the configuration file on your TFTP server. +The supported configuration file entries are ``DEFAULT``, ``LABEL``, +``KERNEL``, ``INITRD`` and ``APPEND`` (see the `Syslinux Config file syntax +`__ for more +information). diff --git a/docs/system/s390x/css.rst b/docs/system/s390x/css.rst new file mode 100644 index 0000000000000000000000000000000000000000..3b4016118423ac3beb6cd08b27dff00b38021b33 --- /dev/null +++ b/docs/system/s390x/css.rst @@ -0,0 +1,86 @@ +The virtual channel subsystem +============================= + +QEMU implements a virtual channel subsystem with subchannels, (mostly +functionless) channel paths, and channel devices (virtio-ccw, 3270, and +devices passed via vfio-ccw). It supports multiple subchannel sets (MSS) and +multiple channel subsystems extended (MCSS-E). + +All channel devices support the ``devno`` property, which takes a parameter +in the form ``..``. + +The default channel subsystem image id (````) is ``0xfe``. Devices in +there will show up in channel subsystem image ``0`` to guests that do not +enable MCSS-E. Note that devices with a different cssid will not be visible +if the guest OS does not enable MCSS-E (which is true for all supported guest +operating systems today). + +Supported values for the subchannel set id (````) range from ``0-3``. +Devices with a ssid that is not ``0`` will not be visible if the guest OS +does not enable MSS (any Linux version that supports virtio also enables MSS). +Any device may be put into any subchannel set, there is no restriction by +device type. + +The device number can range from ``0-0xffff``. + +If the ``devno`` property is not specified for a device, QEMU will choose the +next free device number in subchannel set 0, skipping to the next subchannel +set if no more device numbers are free. + +QEMU places a device at the first free subchannel in the specified subchannel +set. If a device is hotunplugged and later replugged, it may appear at a +different subchannel. (This is similar to how z/VM works.) + + +Examples +-------- + +* a virtio-net device, cssid/ssid/devno automatically assigned:: + + -device virtio-net-ccw + + In a Linux guest (without default devices and no other devices specified + prior to this one), this will show up as ``0.0.0000`` under subchannel + ``0.0.0000``. + + The auto-assigned-properties in QEMU (as seen via e.g. ``info qtree``) + would be ``dev_id = "fe.0.0000"`` and ``subch_id = "fe.0.0000"``. + +* a virtio-rng device in subchannel set ``0``:: + + -device virtio-rng-ccw,devno=fe.0.0042 + + If added to the same Linux guest as above, it would show up as ``0.0.0042`` + under subchannel ``0.0.0001``. + + The properties for the device would be ``dev_id = "fe.0.0042"`` and + ``subch_id = "fe.0.0001"``. + +* a virtio-gpu device in subchannel set ``2``:: + + -device virtio-gpu-ccw,devno=fe.2.1111 + + If added to the same Linux guest as above, it would show up as ``0.2.1111`` + under subchannel ``0.2.0000``. + + The properties for the device would be ``dev_id = "fe.2.1111"`` and + ``subch_id = "fe.2.0000"``. + +* a virtio-mouse device in a non-standard channel subsystem image:: + + -device virtio-mouse-ccw,devno=2.0.2222 + + This would not show up in a standard Linux guest. + + The properties for the device would be ``dev_id = "2.0.2222"`` and + ``subch_id = "2.0.0000"``. + +* a virtio-keyboard device in another non-standard channel subsystem image:: + + -device virtio-keyboard-ccw,devno=0.0.1234 + + This would not show up in a standard Linux guest, either, as ``0`` is not + the standard channel subsystem image id. + + The properties for the device would be ``dev_id = "0.0.1234"`` and + ``subch_id = "0.0.0000"``. diff --git a/docs/system/s390x/vfio-ap.rst b/docs/system/s390x/vfio-ap.rst index 3cd84179a2dfa331328ee4d3131233cfac7aec5b..084ba9c4e3b0f18405942ab1d26710cec11c54f0 100644 --- a/docs/system/s390x/vfio-ap.rst +++ b/docs/system/s390x/vfio-ap.rst @@ -606,10 +606,11 @@ action. To hot plug a vfio-ap device, use the QEMU ``device_add`` command:: - (qemu) device_add vfio-ap,sysfsdev="$path-to-mdev" + (qemu) device_add vfio-ap,sysfsdev="$path-to-mdev",id="$id" Where the ``$path-to-mdev`` value specifies the absolute path to a mediated device to which AP resources to be used by the guest have been assigned. +``$id`` is the name value for the optional id parameter. Note that on Linux guests, the AP devices will be created in the ``/sys/bus/ap/devices`` directory when the AP bus subsequently performs its periodic @@ -632,10 +633,9 @@ or a prior hot plug action. To hot unplug a vfio-ap device, use the QEMU ``device_del`` command:: - (qemu) device_del vfio-ap,sysfsdev="$path-to-mdev" + (qemu) device_del "$id" -Where ``$path-to-mdev`` is the same as the path specified when the vfio-ap -device was attached to the virtual machine's ap-bus. +Where ``$id`` is the same id that was specified at device creation. On a Linux guest, the AP devices will be removed from the ``/sys/bus/ap/devices`` directory on the guest when the AP bus subsequently performs its periodic scan, diff --git a/docs/system/s390x/vfio-ccw.rst b/docs/system/s390x/vfio-ccw.rst new file mode 100644 index 0000000000000000000000000000000000000000..41e0bad5b4891aa77a431245992e7ff10aea03cd --- /dev/null +++ b/docs/system/s390x/vfio-ccw.rst @@ -0,0 +1,77 @@ +Subchannel passthrough via vfio-ccw +=================================== + +vfio-ccw (based upon the mediated vfio device infrastructure) allows to +make certain I/O subchannels and their devices available to a guest. The +host will not interact with those subchannels/devices any more. + +Note that while vfio-ccw should work with most non-QDIO devices, only ECKD +DASDs have really been tested. + +Example configuration +--------------------- + +Step 1: configure the host device +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As every mdev is identified by a uuid, the first step is to obtain one:: + + [root@host ~]# uuidgen + 7e270a25-e163-4922-af60-757fc8ed48c6 + +Note: it is recommended to use the ``mdevctl`` tool for actually configuring +the host device. + +To define the same device as configured below to be started +automatically, use + +:: + + [root@host ~]# driverctl -b css set-override 0.0.0313 vfio_ccw + [root@host ~]# mdevctl define -u 7e270a25-e163-4922-af60-757fc8ed48c6 \ + -p 0.0.0313 -t vfio_ccw-io -a + +If using ``mdevctl`` is not possible or wanted, follow the manual procedure +below. + +* Locate the subchannel for the device (in this example, ``0.0.2b09``):: + + [root@host ~]# lscss | grep 0.0.2b09 | awk '{print $2}' + 0.0.0313 + +* Unbind the subchannel (in this example, ``0.0.0313``) from the standard + I/O subchannel driver and bind it to the vfio-ccw driver:: + + [root@host ~]# echo 0.0.0313 > /sys/bus/css/devices/0.0.0313/driver/unbind + [root@host ~]# echo 0.0.0313 > /sys/bus/css/drivers/vfio_ccw/bind + +* Create the mediated device (identified by the uuid):: + + [root@host ~]# echo "7e270a25-e163-4922-af60-757fc8ed48c6" > \ + /sys/bus/css/devices/0.0.0313/mdev_supported_types/vfio_ccw-io/create + +Step 2: configure QEMU +~~~~~~~~~~~~~~~~~~~~~~ + +* Reference the created mediated device and (optionally) pick a device id to + be presented in the guest (here, ``fe.0.1234``, which will end up visible + in the guest as ``0.0.1234``:: + + -device vfio-ccw,devno=fe.0.1234,sysfsdev=\ + /sys/bus/mdev/devices/7e270a25-e163-4922-af60-757fc8ed48c6 + +* Start the guest. The device (here, ``0.0.1234``) should now be usable:: + + [root@guest ~]# lscss -d 0.0.1234 + Device Subchan. DevType CU Type Use PIM PAM POM CHPID + ---------------------------------------------------------------------- + 0.0.1234 0.0.0007 3390/0e 3990/e9 f0 f0 ff 1a2a3a0a 00000000 + [root@guest ~]# chccwdev -e 0.0.1234 + Setting device 0.0.1234 online + Done + [root@guest ~]# dmesg -t + (...) + dasd-eckd 0.0.1234: A channel path to the device has become operational + dasd-eckd 0.0.1234: New DASD 3390/0E (CU 3990/01) with 10017 cylinders, 15 heads, 224 sectors + dasd-eckd 0.0.1234: DASD with 4 KB/block, 7212240 KB total size, 48 KB/track, compatible disk layout + dasda:VOL1/ 0X2B09: dasda1 diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst index dce384cb0e3edfb5590e05f759526429c262863d..bde4b8e044e54f3e4e8b0a51eb4bfd7de02099f2 100644 --- a/docs/system/target-arm.rst +++ b/docs/system/target-arm.rst @@ -79,15 +79,24 @@ undocumented; you can get a complete list by running arm/mps2 arm/musca arm/realview + arm/sbsa arm/versatile arm/vexpress + arm/aspeed + arm/digic arm/musicpal + arm/gumstix arm/nseries + arm/nuvoton arm/orangepi arm/palm + arm/raspi arm/xscale + arm/collie arm/sx1 arm/stellaris + arm/virt + arm/xlnx-versal-virt Arm CPU features ================ diff --git a/docs/system/target-avr.rst b/docs/system/target-avr.rst new file mode 100644 index 0000000000000000000000000000000000000000..25ab46ef05ccd0ade33354638d1e4894973bd08f --- /dev/null +++ b/docs/system/target-avr.rst @@ -0,0 +1,48 @@ +.. _AVR-System-emulator: + +AVR System emulator +------------------- + +Use the executable ``qemu-system-avr`` to emulate a AVR 8 bit based machine. +These can have one of the following cores: avr1, avr2, avr25, avr3, avr31, +avr35, avr4, avr5, avr51, avr6, avrtiny, xmega2, xmega3, xmega4, xmega5, +xmega6 and xmega7. + +As for now it supports few Arduino boards for educational and testing purposes. +These boards use a ATmega controller, which model is limited to USART & 16-bit +timer devices, enough to run FreeRTOS based applications (like +https://github.com/seharris/qemu-avr-tests/blob/master/free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf +). + +Following are examples of possible usages, assuming demo.elf is compiled for +AVR cpu + +- Continuous non interrupted execution:: + + qemu-system-avr -machine mega2560 -bios demo.elf + +- Continuous non interrupted execution with serial output into telnet window:: + + qemu-system-avr -M mega2560 -bios demo.elf -nographic \ + -serial tcp::5678,server,nowait + + and then in another shell:: + + telnet localhost 5678 + +- Debugging with GDB debugger:: + + qemu-system-avr -machine mega2560 -bios demo.elf -s -S + + and then in another shell:: + + avr-gdb demo.elf + + and then within GDB shell:: + + target remote :1234 + +- Print out executed instructions (that have not been translated by the JIT + compiler yet):: + + qemu-system-avr -machine mega2560 -bios demo.elf -d in_asm diff --git a/docs/system/target-i386-desc.rst.inc b/docs/system/target-i386-desc.rst.inc index 47a169e0ae2a85eddabb5d48f35df45885ec3ca8..7d1fffacbea37ab1f6f165d1c269e5c423a09064 100644 --- a/docs/system/target-i386-desc.rst.inc +++ b/docs/system/target-i386-desc.rst.inc @@ -31,6 +31,8 @@ The QEMU PC System emulator simulates the following peripherals: - CS4231A compatible sound card +- PC speaker + - PCI UHCI, OHCI, EHCI or XHCI USB controller and a virtual USB-1.1 hub. @@ -49,7 +51,7 @@ must be told to not have parallel ports to have working GUS. .. parsed-literal:: - |qemu_system_x86| dos.img -soundhw gus -parallel none + |qemu_system_x86| dos.img -device gus -parallel none Alternatively: @@ -60,3 +62,12 @@ Alternatively: Or some other unclaimed IRQ. CS4231A is the chip used in Windows Sound System and GUSMAX products + +The PC speaker audio device can be configured using the pcspk-audiodev +machine property, i.e. + +.. parsed-literal:: + + |qemu_system_x86| some.img \ + -audiodev ,id= \ + -machine pcspk-audiodev= diff --git a/docs/system/target-i386.rst b/docs/system/target-i386.rst index 51be03d881f862ea928dad011a1bf48a4ae422f5..22ba5ce2c0f292f1fbeea9526bad42aca98fa51e 100644 --- a/docs/system/target-i386.rst +++ b/docs/system/target-i386.rst @@ -1,14 +1,23 @@ .. _QEMU-PC-System-emulator: -x86 (PC) System emulator ------------------------- +x86 System emulator +------------------- .. _pcsys_005fdevices: -Peripherals -~~~~~~~~~~~ +Board-specific documentation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. include:: target-i386-desc.rst.inc +.. + This table of contents should be kept sorted alphabetically + by the title text of each file, which isn't the same ordering + as an alphabetical sort by filename. + +.. toctree:: + :maxdepth: 1 + + i386/microvm + i386/pc .. include:: cpu-models-x86.rst.inc diff --git a/docs/system/target-rx.rst b/docs/system/target-rx.rst new file mode 100644 index 0000000000000000000000000000000000000000..4a20a89a064ce3c3316f934281779634edae6612 --- /dev/null +++ b/docs/system/target-rx.rst @@ -0,0 +1,36 @@ +.. _RX-System-emulator: + +RX System emulator +-------------------- + +Use the executable ``qemu-system-rx`` to simulate RX target (GDB simulator). +This target emulated following devices. + +- R5F562N8 MCU + + - On-chip memory (ROM 512KB, RAM 96KB) + - Interrupt Control Unit (ICUa) + - 8Bit Timer x 1CH (TMR0,1) + - Compare Match Timer x 2CH (CMT0,1) + - Serial Communication Interface x 1CH (SCI0) + +- External memory 16MByte + +Example of ``qemu-system-rx`` usage for RX is shown below: + +Download ```` from +https://osdn.net/users/ysato/pf/qemu/dl/u-boot.bin.gz + +Start emulation of rx-virt:: + qemu-system-rx -M gdbsim-r5f562n8 -bios + +Download ``kernel_image_file`` from +https://osdn.net/users/ysato/pf/qemu/dl/zImage + +Download ``device_tree_blob`` from +https://osdn.net/users/ysato/pf/qemu/dl/rx-virt.dtb + +Start emulation of rx-virt:: + qemu-system-rx -M gdbsim-r5f562n8 \ + -kernel -dtb \ + -append "earlycon" diff --git a/docs/system/target-s390x.rst b/docs/system/target-s390x.rst index 7d76ae97b4018ae618af598cb2154d4db92e9f4b..c636f64113d7a7ed357cb4fae062905189d0c62c 100644 --- a/docs/system/target-s390x.rst +++ b/docs/system/target-s390x.rst @@ -23,9 +23,13 @@ or vfio-ap is also available. .. toctree:: s390x/vfio-ap + s390x/css + s390x/3270 + s390x/vfio-ccw Architectural features ====================== .. toctree:: + s390x/bootdevices s390x/protvirt diff --git a/docs/system/targets.rst b/docs/system/targets.rst index 0d8f91580aa5c6f2a2c59d478171331720fd9e86..560783644dbffb78a5c8601733c13b06b97a9e77 100644 --- a/docs/system/targets.rst +++ b/docs/system/targets.rst @@ -18,3 +18,5 @@ Contents: target-m68k target-xtensa target-s390x + target-rx + target-avr diff --git a/docs/system/usb.rst b/docs/system/usb.rst index ddfa828d74ae232cf56ac590222b52771eba07eb..eeab78dcfbeeed86221e6bef85682f9fc51b7bee 100644 --- a/docs/system/usb.rst +++ b/docs/system/usb.rst @@ -8,7 +8,7 @@ plug virtual USB devices or real host USB devices (only works with certain host operating systems). QEMU will automatically create and connect virtual USB hubs as necessary to connect multiple USB devices. -.. _usb_005fdevices: +.. _Connecting USB devices: Connecting USB devices ~~~~~~~~~~~~~~~~~~~~~~ @@ -27,8 +27,8 @@ option or the ``device_add`` monitor command. Available devices are: activated. ``usb-storage,drive=drive_id`` - Mass storage device backed by drive_id (see - :ref:`disk_005fimages`) + Mass storage device backed by drive_id (see the :ref:`disk images` + chapter in the System Emulation Users Guide) ``usb-uas`` USB attached SCSI device, see @@ -81,6 +81,9 @@ option or the ``device_add`` monitor command. Available devices are: ``usb-audio`` USB audio device +``u2f-{emulated,passthru}`` + Universal Second Factor device + .. _host_005fusb_005fdevices: Using host USB devices on a Linux host diff --git a/docs/virtio-net-failover.rst b/docs/system/virtio-net-failover.rst similarity index 100% rename from docs/virtio-net-failover.rst rename to docs/system/virtio-net-failover.rst diff --git a/docs/virtio-pmem.rst b/docs/system/virtio-pmem.rst similarity index 42% rename from docs/virtio-pmem.rst rename to docs/system/virtio-pmem.rst index 4bf5d0044323cdddd2b4fd2131b80736b2ad526a..c82ac0673153bd942d89ccf56a994c8a10c35b0a 100644 --- a/docs/virtio-pmem.rst +++ b/docs/system/virtio-pmem.rst @@ -1,38 +1,37 @@ -======================== -QEMU virtio pmem -======================== +=========== +virtio pmem +=========== - This document explains the setup and usage of the virtio pmem device - which is available since QEMU v4.1.0. - - The virtio pmem device is a paravirtualized persistent memory device - on regular (i.e non-NVDIMM) storage. +This document explains the setup and usage of the virtio pmem device. +The virtio pmem device is a paravirtualized persistent memory device +on regular (i.e non-NVDIMM) storage. Usecase --------- +------- - Virtio pmem allows to bypass the guest page cache and directly use - host page cache. This reduces guest memory footprint as the host can - make efficient memory reclaim decisions under memory pressure. +Virtio pmem allows to bypass the guest page cache and directly use +host page cache. This reduces guest memory footprint as the host can +make efficient memory reclaim decisions under memory pressure. -o How does virtio-pmem compare to the nvdimm emulation supported by QEMU? +How does virtio-pmem compare to the nvdimm emulation? +----------------------------------------------------- - NVDIMM emulation on regular (i.e. non-NVDIMM) host storage does not - persist the guest writes as there are no defined semantics in the device - specification. The virtio pmem device provides guest write persistence - on non-NVDIMM host storage. +NVDIMM emulation on regular (i.e. non-NVDIMM) host storage does not +persist the guest writes as there are no defined semantics in the device +specification. The virtio pmem device provides guest write persistence +on non-NVDIMM host storage. virtio pmem usage ----------------- - A virtio pmem device backed by a memory-backend-file can be created on - the QEMU command line as in the following example:: +A virtio pmem device backed by a memory-backend-file can be created on +the QEMU command line as in the following example:: -object memory-backend-file,id=mem1,share,mem-path=./virtio_pmem.img,size=4G -device virtio-pmem-pci,memdev=mem1,id=nv1 - where: +where: - "object memory-backend-file,id=mem1,share,mem-path=, size=" creates a backend file with the specified size. @@ -40,8 +39,8 @@ virtio pmem usage - "device virtio-pmem-pci,id=nvdimm1,memdev=mem1" creates a virtio pmem pci device whose storage is provided by above memory backend device. - Multiple virtio pmem devices can be created if multiple pairs of "-object" - and "-device" are provided. +Multiple virtio pmem devices can be created if multiple pairs of "-object" +and "-device" are provided. Hotplug ------- @@ -59,17 +58,18 @@ the guest:: Guest Data Persistence ---------------------- - Guest data persistence on non-NVDIMM requires guest userspace applications - to perform fsync/msync. This is different from a real nvdimm backend where - no additional fsync/msync is required. This is to persist guest writes in - host backing file which otherwise remains in host page cache and there is - risk of losing the data in case of power failure. +Guest data persistence on non-NVDIMM requires guest userspace applications +to perform fsync/msync. This is different from a real nvdimm backend where +no additional fsync/msync is required. This is to persist guest writes in +host backing file which otherwise remains in host page cache and there is +risk of losing the data in case of power failure. - With virtio pmem device, MAP_SYNC mmap flag is not supported. This provides - a hint to application to perform fsync for write persistence. +With virtio pmem device, MAP_SYNC mmap flag is not supported. This provides +a hint to application to perform fsync for write persistence. Limitations ------------- +----------- + - Real nvdimm device backend is not supported. - virtio pmem hotunplug is not supported. - ACPI NVDIMM features like regions/namespaces are not supported. diff --git a/docs/system/vnc-security.rst b/docs/system/vnc-security.rst index b237b07330df9e0316df02c6104a94f95141baea..558e4faffc9da4789aa3c891ff45908e4685c5ce 100644 --- a/docs/system/vnc-security.rst +++ b/docs/system/vnc-security.rst @@ -1,4 +1,4 @@ -.. _vnc_005fsecurity: +.. _VNC security: VNC security ------------ diff --git a/docs/throttle.txt b/docs/throttle.txt index cd4e109d393245459ca5aa0a56b8d396ed624040..b5b78b7326d822cac7e0b7e5466e2009e80318e9 100644 --- a/docs/throttle.txt +++ b/docs/throttle.txt @@ -1,6 +1,6 @@ The QEMU throttling infrastructure ================================== -Copyright (C) 2016 Igalia, S.L. +Copyright (C) 2016,2020 Igalia, S.L. Author: Alberto Garcia This work is licensed under the terms of the GNU GPL, version 2 or @@ -253,3 +253,109 @@ up. After those 60 seconds the bucket will have leaked 60 x 100 = Also, due to the way the algorithm works, longer burst can be done at a lower I/O rate, e.g. 1000 IOPS during 120 seconds. + + +The 'throttle' block filter +--------------------------- +Since QEMU 2.11 it is possible to configure the I/O limits using a +'throttle' block filter. This filter uses the exact same throttling +infrastructure described above but can be used anywhere in the node +graph, allowing for more flexibility. + +The user can create an arbitrary number of filters and each one of +them must be assigned to a group that contains the actual I/O limits. +Different filters can use the same group so the limits are shared as +described earlier in "Applying I/O limits to groups of disks". + +A group can be created using the object-add QMP function: + + { "execute": "object-add", + "arguments": { + "qom-type": "throttle-group", + "id": "group0", + "props": { + "limits" : { + "iops-total": 1000 + "bps-write": 2097152 + } + } + } + } + +throttle-group has a 'limits' property (of type ThrottleLimits as +defined in qapi/block-core.json) which can be set on creation or later +with 'qom-set'. + +A throttle-group can also be created with the -object command line +option but at the moment there is no way to pass a 'limits' parameter +that contains a ThrottleLimits structure. The solution is to set the +individual values directly, like in this example: + + -object throttle-group,id=group0,x-iops-total=1000,x-bps-write=2097152 + +Note however that this is not a stable API (hence the 'x-' prefixes) and +will disappear when -object gains support for structured options and +enables use of 'limits'. + +Once we have a throttle-group we can use the throttle block filter, +where the 'file' property must be set to the block device that we want +to filter: + + { "execute": "blockdev-add", + "arguments": { + "options": { + "driver": "qcow2", + "node-name": "disk0", + "file": { + "driver": "file", + "filename": "/path/to/disk.qcow2" + } + } + } + } + + { "execute": "blockdev-add", + "arguments": { + "driver": "throttle", + "node-name": "throttle0", + "throttle-group": "group0", + "file": "disk0" + } + } + +A similar setup can also be done with the command line, for example: + + -drive driver=throttle,throttle-group=group0, + file.driver=qcow2,file.file.filename=/path/to/disk.qcow2 + +The scenario described so far is very simple but the throttle block +filter allows for more complex configurations. For example, let's say +that we have three different drives and we want to set I/O limits for +each one of them and an additional set of limits for the combined I/O +of all three drives. + +First we would define all throttle groups, one for each one of the +drives and one that would apply to all of them: + + -object throttle-group,id=limits0,x-iops-total=2000 + -object throttle-group,id=limits1,x-iops-total=2500 + -object throttle-group,id=limits2,x-iops-total=3000 + -object throttle-group,id=limits012,x-iops-total=4000 + +Now we can define the drives, and for each one of them we use two +chained throttle filters: the drive's own filter and the combined +filter. + + -drive driver=throttle,throttle-group=limits012, + file.driver=throttle,file.throttle-group=limits0 + file.file.driver=qcow2,file.file.file.filename=/path/to/disk0.qcow2 + -drive driver=throttle,throttle-group=limits012, + file.driver=throttle,file.throttle-group=limits1 + file.file.driver=qcow2,file.file.file.filename=/path/to/disk1.qcow2 + -drive driver=throttle,throttle-group=limits012, + file.driver=throttle,file.throttle-group=limits2 + file.file.driver=qcow2,file.file.file.filename=/path/to/disk2.qcow2 + +In this example the individual drives have IOPS limits of 2000, 2500 +and 3000 respectively but the total combined I/O can never exceed 4000 +IOPS. diff --git a/docs/tools/_templates/editpage.html b/docs/tools/_templates/editpage.html new file mode 100644 index 0000000000000000000000000000000000000000..2a9c8fc92b375ee15c6d0f2dac510c8c61e25810 --- /dev/null +++ b/docs/tools/_templates/editpage.html @@ -0,0 +1,5 @@ +
+ +
diff --git a/docs/tools/conf.py b/docs/tools/conf.py index 9052d17d6d476a5c7df51b64dfb9f23c3313fc0d..4760d36ff2a6fd0a1f04ce2b3fd3b78b482bf82c 100644 --- a/docs/tools/conf.py +++ b/docs/tools/conf.py @@ -22,6 +22,8 @@ ['Fabrice Bellard'], 1), ('qemu-nbd', 'qemu-nbd', u'QEMU Disk Network Block Device Server', ['Anthony Liguori '], 8), + ('qemu-pr-helper', 'qemu-pr-helper', 'QEMU persistent reservation helper', + [], 8), ('qemu-trace-stap', 'qemu-trace-stap', u'QEMU SystemTap trace tool', [], 1), ('virtfs-proxy-helper', 'virtfs-proxy-helper', diff --git a/docs/tools/index.rst b/docs/tools/index.rst index 232ce9f3e463b70da3394b1eef8aec4f9cff69e8..b99f86c7c6613f358d2dbef047d771dd18ceb1a0 100644 --- a/docs/tools/index.rst +++ b/docs/tools/index.rst @@ -12,6 +12,7 @@ Contents: qemu-img qemu-nbd + qemu-pr-helper qemu-trace-stap virtfs-proxy-helper virtiofsd diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst index 38d464ea3f23111fb5b0ac8fdff70580d554b32d..b615aa84191dc0723ec0c5ee282a82989ccc25fd 100644 --- a/docs/tools/qemu-img.rst +++ b/docs/tools/qemu-img.rst @@ -162,6 +162,10 @@ Parameters to convert subcommand: .. program:: qemu-img-convert +.. option:: --bitmaps + + Additionally copy all persistent bitmaps from the top layer of the source + .. option:: -n Skip the creation of the target volume @@ -184,6 +188,10 @@ Parameters to convert subcommand: allocated target image depending on the host support for getting allocation information. +.. option:: -r + + Rate limit for the convert process + .. option:: --salvage Try to ignore I/O errors when reading. Unless in quiet mode (``-q``), errors @@ -249,11 +257,18 @@ Command description: .. program:: qemu-img-commands -.. option:: amend [--object OBJECTDEF] [--image-opts] [-p] [-q] [-f FMT] [-t CACHE] -o OPTIONS FILENAME +.. option:: amend [--object OBJECTDEF] [--image-opts] [-p] [-q] [-f FMT] [-t CACHE] [--force] -o OPTIONS FILENAME Amends the image format specific *OPTIONS* for the image file *FILENAME*. Not all file formats support this operation. + The set of options that can be amended are dependent on the image + format, but note that amending the backing chain relationship should + instead be performed with ``qemu-img rebase``. + + --force allows some unsafe operations. Currently for -f luks, it allows to + erase the last encryption key, and to overwrite an active encryption key. + .. option:: bench [-c COUNT] [-d DEPTH] [-f FMT] [--flush-interval=FLUSH_INTERVAL] [-i AIO] [-n] [--no-drain] [-o OFFSET] [--pattern=PATTERN] [-q] [-s BUFFER_SIZE] [-S STEP_SIZE] [-t CACHE] [-w] [-U] FILENAME Run a simple sequential I/O benchmark on the specified image. If ``-w`` is @@ -296,7 +311,7 @@ Command description: ``--disable`` to change *BITMAP* to stop recording future edits. - ``--merge`` to merge the contents of *SOURCE_BITMAP* into *BITMAP*. + ``--merge`` to merge the contents of the *SOURCE* bitmap into *BITMAP*. Additional options include ``-g`` which sets a non-default *GRANULARITY* for ``--add``, and ``-b`` and ``-F`` which select an @@ -338,7 +353,7 @@ Command description: state after (the attempt at) repairing it. That is, a successful ``-r all`` will yield the exit code 0, independently of the image state before. -.. option:: commit [--object OBJECTDEF] [--image-opts] [-q] [-f FMT] [-t CACHE] [-b BASE] [-d] [-p] FILENAME +.. option:: commit [--object OBJECTDEF] [--image-opts] [-q] [-f FMT] [-t CACHE] [-b BASE] [-r RATE_LIMIT] [-d] [-p] FILENAME Commit the changes recorded in *FILENAME* in its base image or backing file. If the backing file is smaller than the snapshot, then the backing file will be @@ -360,6 +375,8 @@ Command description: garbage data when read. For this reason, ``-b`` implies ``-d`` (so that the top image stays valid). + The rate limit for the commit process is specified by ``-r``. + .. option:: compare [--object OBJECTDEF] [--image-opts] [-f FMT] [-F FMT] [-T SRC_CACHE] [-p] [-q] [-s] [-U] FILENAME1 FILENAME2 Check if two images have the same content. You can compare images with @@ -397,7 +414,7 @@ Command description: 4 Error on reading data -.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-m NUM_COROUTINES] [-W] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME +.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [--bitmaps] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-r RATE_LIMIT] [-m NUM_COROUTINES] [-W] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME Convert the disk image *FILENAME* or a snapshot *SNAPSHOT_PARAM* to disk image *OUTPUT_FILENAME* using format *OUTPUT_FMT*. It can @@ -616,6 +633,7 @@ Command description: required size: 524288 fully allocated size: 1074069504 + bitmaps size: 0 The ``required size`` is the file size of the new image. It may be smaller than the virtual disk size if the image format supports compact representation. @@ -625,6 +643,12 @@ Command description: occupy with the exception of internal snapshots, dirty bitmaps, vmstate data, and other advanced image format features. + The ``bitmaps size`` is the additional size required in order to + copy bitmaps from a source image in addition to the guest-visible + data; the line is omitted if either source or destination lacks + bitmap support, or 0 if bitmaps are supported but there is nothing + to copy. + .. option:: snapshot [--object OBJECTDEF] [--image-opts] [-U] [-q] [-l | -a SNAPSHOT | -c SNAPSHOT | -d SNAPSHOT] FILENAME List, apply, create or delete snapshots in image *FILENAME*. diff --git a/docs/tools/qemu-nbd.rst b/docs/tools/qemu-nbd.rst index 667861cb22e970d87b4a551818da6c291896abb4..fe41336dc5508570680e5fa4ee661ccba0cd59a8 100644 --- a/docs/tools/qemu-nbd.rst +++ b/docs/tools/qemu-nbd.rst @@ -72,10 +72,16 @@ driver options if ``--image-opts`` is specified. Export the disk as read-only. +.. option:: -A, --allocation-depth + + Expose allocation depth information via the + ``qemu:allocation-depth`` metadata context accessible through + NBD_OPT_SET_META_CONTEXT. + .. option:: -B, --bitmap=NAME If *filename* has a qcow2 persistent bitmap *NAME*, expose - that bitmap via the ``qemu:dirty-bitmap:NAME`` context + that bitmap via the ``qemu:dirty-bitmap:NAME`` metadata context accessible through NBD_OPT_SET_META_CONTEXT. .. option:: -s, --snapshot diff --git a/docs/tools/qemu-pr-helper.rst b/docs/tools/qemu-pr-helper.rst new file mode 100644 index 0000000000000000000000000000000000000000..ac036180ac1e22bc82d3928b1a2796916b031e4e --- /dev/null +++ b/docs/tools/qemu-pr-helper.rst @@ -0,0 +1,90 @@ +QEMU persistent reservation helper +================================== + +Synopsis +-------- + +**qemu-pr-helper** [*OPTION*] + +Description +----------- + +Implements the persistent reservation helper for QEMU. + +SCSI persistent reservations allow restricting access to block devices +to specific initiators in a shared storage setup. When implementing +clustering of virtual machines, it is a common requirement for virtual +machines to send persistent reservation SCSI commands. However, +the operating system restricts sending these commands to unprivileged +programs because incorrect usage can disrupt regular operation of the +storage fabric. QEMU's SCSI passthrough devices ``scsi-block`` +and ``scsi-generic`` support passing guest persistent reservation +requests to a privileged external helper program. :program:`qemu-pr-helper` +is that external helper; it creates a socket which QEMU can +connect to to communicate with it. + +If you want to run VMs in a setup like this, this helper should be +started as a system service, and you should read the QEMU manual +section on "persistent reservation managers" to find out how to +configure QEMU to connect to the socket created by +:program:`qemu-pr-helper`. + +After connecting to the socket, :program:`qemu-pr-helper` can +optionally drop root privileges, except for those capabilities that +are needed for its operation. + +:program:`qemu-pr-helper` can also use the systemd socket activation +protocol. In this case, the systemd socket unit should specify a +Unix stream socket, like this:: + + [Socket] + ListenStream=/var/run/qemu-pr-helper.sock + +Options +------- + +.. program:: qemu-pr-helper + +.. option:: -d, --daemon + + run in the background (and create a PID file) + +.. option:: -q, --quiet + + decrease verbosity + +.. option:: -v, --verbose + + increase verbosity + +.. option:: -f, --pidfile=PATH + + PID file when running as a daemon. By default the PID file + is created in the system runtime state directory, for example + :file:`/var/run/qemu-pr-helper.pid`. + +.. option:: -k, --socket=PATH + + path to the socket. By default the socket is created in + the system runtime state directory, for example + :file:`/var/run/qemu-pr-helper.sock`. + +.. option:: -T, --trace [[enable=]PATTERN][,events=FILE][,file=FILE] + + .. include:: ../qemu-option-trace.rst.inc + +.. option:: -u, --user=USER + + user to drop privileges to + +.. option:: -g, --group=GROUP + + group to drop privileges to + +.. option:: -h, --help + + Display a help message and exit. + +.. option:: -V, --version + + Display version information and exit. diff --git a/docs/tools/virtiofsd.rst b/docs/tools/virtiofsd.rst index 378594c422a216d40593b27aae893b9813d651f2..866b7db3eed36302bc96bbef8184e87fdc9df9b9 100644 --- a/docs/tools/virtiofsd.rst +++ b/docs/tools/virtiofsd.rst @@ -17,13 +17,24 @@ This program is designed to work with QEMU's ``--device vhost-user-fs-pci`` but should work with any virtual machine monitor (VMM) that supports vhost-user. See the Examples section below. -This program must be run as the root user. Upon startup the program will -switch into a new file system namespace with the shared directory tree as its -root. This prevents "file system escapes" due to symlinks and other file -system objects that might lead to files outside the shared directory. The -program also sandboxes itself using seccomp(2) to prevent ptrace(2) and other -vectors that could allow an attacker to compromise the system after gaining -control of the virtiofsd process. +This program must be run as the root user. The program drops privileges where +possible during startup although it must be able to create and access files +with any uid/gid: + +* The ability to invoke syscalls is limited using seccomp(2). +* Linux capabilities(7) are dropped. + +In "namespace" sandbox mode the program switches into a new file system +namespace and invokes pivot_root(2) to make the shared directory tree its root. +A new pid and net namespace is also created to isolate the process. + +In "chroot" sandbox mode the program invokes chroot(2) to make the shared +directory tree its root. This mode is intended for container environments where +the container runtime has already set up the namespaces and the program does +not have permission to create namespaces itself. + +Both sandbox modes prevent "file system escapes" due to symlinks and other file +system objects that might lead to files outside the shared directory. Options ------- @@ -54,19 +65,28 @@ Options * flock|no_flock - Enable/disable flock. The default is ``no_flock``. + * modcaps=CAPLIST + Modify the list of capabilities allowed; CAPLIST is a colon separated + list of capabilities, each preceded by either + or -, e.g. + ''+sys_admin:-chown''. + * log_level=LEVEL - Print only log messages matching LEVEL or more severe. LEVEL is one of ``err``, ``warn``, ``info``, or ``debug``. The default is ``info``. - * norace - - Disable racy fallback. The default is false. - * posix_lock|no_posix_lock - - Enable/disable remote POSIX locks. The default is ``posix_lock``. + Enable/disable remote POSIX locks. The default is ``no_posix_lock``. * readdirplus|no_readdirplus - Enable/disable readdirplus. The default is ``readdirplus``. + * sandbox=namespace|chroot - + Sandbox mode: + - namespace: Create mount, pid, and net namespaces and pivot_root(2) into + the shared directory. + - chroot: chroot(2) into shared directory (use in containers). + The default is "namespace". + * source=PATH - Share host directory tree located at PATH. This option is required. @@ -74,7 +94,7 @@ Options I/O timeout in seconds. The default depends on cache= option. * writeback|no_writeback - - Enable/disable writeback cache. The cache alows the FUSE client to buffer + Enable/disable writeback cache. The cache allows the FUSE client to buffer and merge write requests. The default is ``no_writeback``. * xattr|no_xattr - @@ -85,6 +105,10 @@ Options Listen on vhost-user UNIX domain socket at PATH. +.. option:: --socket-group=GROUP + + Set the vhost-user UNIX domain socket gid to GROUP. + .. option:: --fd=FDNUM Accept connections from vhost-user UNIX domain socket file descriptor FDNUM. @@ -101,6 +125,168 @@ Options forbids the FUSE client from caching to achieve best coherency at the cost of performance. ``auto`` acts similar to NFS with a 1 second metadata cache timeout. ``always`` sets a long cache lifetime at the expense of coherency. + The default is ``auto``. + +xattr-mapping +------------- + +By default the name of xattr's used by the client are passed through to the server +file system. This can be a problem where either those xattr names are used +by something on the server (e.g. selinux client/server confusion) or if the +virtiofsd is running in a container with restricted privileges where it cannot +access some attributes. + +A mapping of xattr names can be made using -o xattrmap=mapping where the ``mapping`` +string consists of a series of rules. + +The first matching rule terminates the mapping. +The set of rules must include a terminating rule to match any remaining attributes +at the end. + +Each rule consists of a number of fields separated with a separator that is the +first non-white space character in the rule. This separator must then be used +for the whole rule. +White space may be added before and after each rule. + +Using ':' as the separator a rule is of the form: + +``:type:scope:key:prepend:`` + +**scope** is: + +- 'client' - match 'key' against a xattr name from the client for + setxattr/getxattr/removexattr +- 'server' - match 'prepend' against a xattr name from the server + for listxattr +- 'all' - can be used to make a single rule where both the server + and client matches are triggered. + +**type** is one of: + +- 'prefix' - is designed to prepend and strip a prefix; the modified + attributes then being passed on to the client/server. + +- 'ok' - Causes the rule set to be terminated when a match is found + while allowing matching xattr's through unchanged. + It is intended both as a way of explicitly terminating + the list of rules, and to allow some xattr's to skip following rules. + +- 'bad' - If a client tries to use a name matching 'key' it's + denied using EPERM; when the server passes an attribute + name matching 'prepend' it's hidden. In many ways it's use is very like + 'ok' as either an explicit terminator or for special handling of certain + patterns. + +**key** is a string tested as a prefix on an attribute name originating +on the client. It maybe empty in which case a 'client' rule +will always match on client names. + +**prepend** is a string tested as a prefix on an attribute name originating +on the server, and used as a new prefix. It may be empty +in which case a 'server' rule will always match on all names from +the server. + +e.g.: + + ``:prefix:client:trusted.:user.virtiofs.:`` + + will match 'trusted.' attributes in client calls and prefix them before + passing them to the server. + + ``:prefix:server::user.virtiofs.:`` + + will strip 'user.virtiofs.' from all server replies. + + ``:prefix:all:trusted.:user.virtiofs.:`` + + combines the previous two cases into a single rule. + + ``:ok:client:user.::`` + + will allow get/set xattr for 'user.' xattr's and ignore + following rules. + + ``:ok:server::security.:`` + + will pass 'securty.' xattr's in listxattr from the server + and ignore following rules. + + ``:ok:all:::`` + + will terminate the rule search passing any remaining attributes + in both directions. + + ``:bad:server::security.:`` + + would hide 'security.' xattr's in listxattr from the server. + +A simpler 'map' type provides a shorter syntax for the common case: + +``:map:key:prepend:`` + +The 'map' type adds a number of separate rules to add **prepend** as a prefix +to the matched **key** (or all attributes if **key** is empty). +There may be at most one 'map' rule and it must be the last rule in the set. + +xattr-mapping Examples +---------------------- + +1) Prefix all attributes with 'user.virtiofs.' + +:: + +-o xattrmap=":prefix:all::user.virtiofs.::bad:all:::" + + +This uses two rules, using : as the field separator; +the first rule prefixes and strips 'user.virtiofs.', +the second rule hides any non-prefixed attributes that +the host set. + +This is equivalent to the 'map' rule: + +:: +-o xattrmap=":map::user.virtiofs.:" + +2) Prefix 'trusted.' attributes, allow others through + +:: + + "/prefix/all/trusted./user.virtiofs./ + /bad/server//trusted./ + /bad/client/user.virtiofs.// + /ok/all///" + + +Here there are four rules, using / as the field +separator, and also demonstrating that new lines can +be included between rules. +The first rule is the prefixing of 'trusted.' and +stripping of 'user.virtiofs.'. +The second rule hides unprefixed 'trusted.' attributes +on the host. +The third rule stops a guest from explicitly setting +the 'user.virtiofs.' path directly. +Finally, the fourth rule lets all remaining attributes +through. + +This is equivalent to the 'map' rule: + +:: +-o xattrmap="/map/trusted./user.virtiofs./" + +3) Hide 'security.' attributes, and allow everything else + +:: + + "/bad/all/security./security./ + /ok/all///' + +The first rule combines what could be separate client and server +rules into a single 'all' rule, matching 'security.' in either +client arguments or lists returned from the host. This stops +the client seeing any 'security.' attributes on the server and +stops it setting any. Examples -------- diff --git a/docs/u2f.txt b/docs/u2f.txt new file mode 100644 index 0000000000000000000000000000000000000000..8f44994818a23de44482d7ca2ad099b332598ade --- /dev/null +++ b/docs/u2f.txt @@ -0,0 +1,110 @@ +QEMU U2F Key Device Documentation. + +Contents +1. USB U2F key device +2. Building +3. Using u2f-emulated +4. Using u2f-passthru +5. Libu2f-emu + +1. USB U2F key device + +U2F is an open authentication standard that enables relying parties +exposed to the internet to offer a strong second factor option for end +user authentication. + +The standard brings many advantages to both parties, client and server, +allowing to reduce over-reliance on passwords, it increases authentication +security and simplifies passwords. + +The second factor is materialized by a device implementing the U2F +protocol. In case of a USB U2F security key, it is a USB HID device +that implements the U2F protocol. + +In Qemu, the USB U2F key device offers a dedicated support of U2F, allowing +guest USB FIDO/U2F security keys operating in two possible modes: +pass-through and emulated. + +The pass-through mode consists of passing all requests made from the guest +to the physical security key connected to the host machine and vice versa. +In addition, the dedicated pass-through allows to have a U2F security key +shared on several guests which is not possible with a simple host device +assignment pass-through. + +The emulated mode consists of completely emulating the behavior of an +U2F device through software part. Libu2f-emu is used for that. + + +2. Building + +To ensure the build of the u2f-emulated device variant which depends +on libu2f-emu: configuring and building: + + ./configure --enable-u2f && make + +The pass-through mode is built by default on Linux. To take advantage +of the autoscan option it provides, make sure you have a working libudev +installed on the host. + + +3. Using u2f-emulated + +To work, an emulated U2F device must have four elements: + * ec x509 certificate + * ec private key + * counter (four bytes value) + * 48 bytes of entropy (random bits) + +To use this type of device, this one has to be configured, and these +four elements must be passed one way or another. + +Assuming that you have a working libu2f-emu installed on the host. +There are three possible ways of configurations: + * ephemeral + * setup directory + * manual + +Ephemeral is the simplest way to configure, it lets the device generate +all the elements it needs for a single use of the lifetime of the device. + + qemu -usb -device u2f-emulated + +Setup directory allows to configure the device from a directory containing +four files: + * certificate.pem: ec x509 certificate + * private-key.pem: ec private key + * counter: counter value + * entropy: 48 bytes of entropy + + qemu -usb -device u2f-emulated,dir=$dir + +Manual allows to configure the device more finely by specifying each +of the elements necessary for the device: + * cert + * priv + * counter + * entropy + + qemu -usb -device u2f-emulated,cert=$DIR1/$FILE1,priv=$DIR2/$FILE2,counter=$DIR3/$FILE3,entropy=$DIR4/$FILE4 + + +4. Using u2f-passthru + +On the host specify the u2f-passthru device with a suitable hidraw: + + qemu -usb -device u2f-passthru,hidraw=/dev/hidraw0 + +Alternately, the u2f-passthru device can autoscan to take the first +U2F device it finds on the host (this requires a working libudev): + + qemu -usb -device u2f-passthru + + +5. Libu2f-emu + +The u2f-emulated device uses libu2f-emu for the U2F key emulation. Libu2f-emu +implements completely the U2F protocol device part for all specified +transport given by the FIDO Alliance. + +For more information about libu2f-emu see this page: +https://github.com/MattGorko/libu2f-emu. diff --git a/docs/user/_templates/editpage.html b/docs/user/_templates/editpage.html new file mode 100644 index 0000000000000000000000000000000000000000..1f5ee01e606e3769658ecc47d8a2cd2023228f88 --- /dev/null +++ b/docs/user/_templates/editpage.html @@ -0,0 +1,5 @@ +
+ +
diff --git a/docs/xbzrle.txt b/docs/xbzrle.txt index b431bdaf0f9066ad56fb9791ccf3b9436bd4e603..6bd1828f3428de686d8dfee38b027c7edc07f2ef 100644 --- a/docs/xbzrle.txt +++ b/docs/xbzrle.txt @@ -112,10 +112,12 @@ is recommended. cache size: H bytes xbzrle transferred: I kbytes xbzrle pages: J pages - xbzrle cache miss: K - xbzrle overflow: L + xbzrle cache miss: K pages + xbzrle cache miss rate: L + xbzrle encoding rate: M + xbzrle overflow: N -xbzrle cache-miss: the number of cache misses to date - high cache-miss rate +xbzrle cache miss: the number of cache misses to date - high cache-miss rate indicates that the cache size is set too low. xbzrle overflow: the number of overflows in the decoding which where the delta could not be compressed. This can happen if the changes in the pages are too diff --git a/dtc b/dtc index 88f18909db731a627456f26d779445f84e449536..85e5d839847af54efab170f2b1331b2a6421e647 160000 --- a/dtc +++ b/dtc @@ -1 +1 @@ -Subproject commit 88f18909db731a627456f26d779445f84e449536 +Subproject commit 85e5d839847af54efab170f2b1331b2a6421e647 diff --git a/dump/Makefile.objs b/dump/Makefile.objs deleted file mode 100644 index d2a5db3b815132e72d1bf130acbe93e718872ce3..0000000000000000000000000000000000000000 --- a/dump/Makefile.objs +++ /dev/null @@ -1,3 +0,0 @@ -obj-y += dump.o -common-obj-y += dump-hmp-cmds.o -obj-$(TARGET_X86_64) += win_dump.o diff --git a/dump/dump.c b/dump/dump.c index 248ea06370b4c0773da297cdf5365b10d12f610e..dec32468d98c1bee3d0cfc6e302e3932fff93199 100644 --- a/dump/dump.c +++ b/dump/dump.c @@ -1031,14 +1031,11 @@ out: static void write_dump_header(DumpState *s, Error **errp) { - Error *local_err = NULL; - if (s->dump_info.d_class == ELFCLASS32) { - create_header32(s, &local_err); + create_header32(s, errp); } else { - create_header64(s, &local_err); + create_header64(s, errp); } - error_propagate(errp, local_err); } static size_t dump_bitmap_get_bufsize(DumpState *s) @@ -1575,7 +1572,7 @@ static void dump_state_prepare(DumpState *s) bool dump_in_progress(void) { DumpState *state = &dump_state_global; - return (atomic_read(&state->status) == DUMP_STATUS_ACTIVE); + return (qatomic_read(&state->status) == DUMP_STATUS_ACTIVE); } /* calculate total size of memory to be dumped (taking filter into @@ -1885,7 +1882,7 @@ static void dump_process(DumpState *s, Error **errp) /* make sure status is written after written_size updates */ smp_wmb(); - atomic_set(&s->status, + qatomic_set(&s->status, (local_err ? DUMP_STATUS_FAILED : DUMP_STATUS_COMPLETED)); /* send DUMP_COMPLETED message (unconditionally) */ @@ -1911,7 +1908,7 @@ DumpQueryResult *qmp_query_dump(Error **errp) { DumpQueryResult *result = g_new(DumpQueryResult, 1); DumpState *state = &dump_state_global; - result->status = atomic_read(&state->status); + result->status = qatomic_read(&state->status); /* make sure we are reading status and written_size in order */ smp_rmb(); result->completed = state->written_size; @@ -1989,7 +1986,7 @@ void qmp_dump_guest_memory(bool paging, const char *file, #if !defined(WIN32) if (strstart(file, "fd:", &p)) { - fd = monitor_get_fd(cur_mon, p, errp); + fd = monitor_get_fd(monitor_cur(), p, errp); if (fd == -1) { return; } @@ -1997,7 +1994,7 @@ void qmp_dump_guest_memory(bool paging, const char *file, #endif if (strstart(file, "file:", &p)) { - fd = qemu_open(p, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR); + fd = qemu_open_old(p, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR); if (fd < 0) { error_setg_file_open(errp, errno, p); return; @@ -2016,7 +2013,7 @@ void qmp_dump_guest_memory(bool paging, const char *file, begin, length, &local_err); if (local_err) { error_propagate(errp, local_err); - atomic_set(&s->status, DUMP_STATUS_FAILED); + qatomic_set(&s->status, DUMP_STATUS_FAILED); return; } diff --git a/dump/meson.build b/dump/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..2eff29c3eaba8a85c91c3842bbac047fa21d3d4b --- /dev/null +++ b/dump/meson.build @@ -0,0 +1,4 @@ +softmmu_ss.add(files('dump-hmp-cmds.c')) + +specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files('dump.c'), snappy, lzo]) +specific_ss.add(when: ['CONFIG_SOFTMMU', 'TARGET_X86_64'], if_true: files('win_dump.c')) diff --git a/exec-vary.c b/exec-vary.c index ff905f2a8fb254bfc6017ef94539d496d83d0e9c..a603b1b4336cb004f3c68fc98994d90c1e7811f8 100644 --- a/exec-vary.c +++ b/exec-vary.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/fpu/softfloat-specialize.inc.c b/fpu/softfloat-specialize.c.inc similarity index 83% rename from fpu/softfloat-specialize.inc.c rename to fpu/softfloat-specialize.c.inc index 44f5b661f8312e4ed4382144db02f1e85dc1e026..c2f87addb254900b43bde6705119e274fe2642e0 100644 --- a/fpu/softfloat-specialize.inc.c +++ b/fpu/softfloat-specialize.c.inc @@ -79,12 +79,18 @@ this code that are retained. * version 2 or later. See the COPYING file in the top-level directory. */ -/* Define for architectures which deviate from IEEE in not supporting +/* + * Define whether architecture deviates from IEEE in not supporting * signaling NaNs (so all NaNs are treated as quiet). */ +static inline bool no_signaling_nans(float_status *status) +{ #if defined(TARGET_XTENSA) -#define NO_SIGNALING_NANS 1 + return status->no_signaling_nans; +#else + return false; #endif +} /* Define how the architecture discriminates signaling NaNs. * This done with the most significant bit of the fraction. @@ -111,12 +117,12 @@ static inline bool snan_bit_is_one(float_status *status) static bool parts_is_snan_frac(uint64_t frac, float_status *status) { -#ifdef NO_SIGNALING_NANS - return false; -#else - bool msb = extract64(frac, DECOMPOSED_BINARY_POINT - 1, 1); - return msb == snan_bit_is_one(status); -#endif + if (no_signaling_nans(status)) { + return false; + } else { + bool msb = extract64(frac, DECOMPOSED_BINARY_POINT - 1, 1); + return msb == snan_bit_is_one(status); + } } /*---------------------------------------------------------------------------- @@ -170,9 +176,8 @@ static FloatParts parts_default_nan(float_status *status) static FloatParts parts_silence_nan(FloatParts a, float_status *status) { -#ifdef NO_SIGNALING_NANS - g_assert_not_reached(); -#elif defined(TARGET_HPPA) + g_assert(!no_signaling_nans(status)); +#if defined(TARGET_HPPA) a.frac &= ~(1ULL << (DECOMPOSED_BINARY_POINT - 1)); a.frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 2); #else @@ -247,16 +252,36 @@ typedef struct { bool float16_is_quiet_nan(float16 a_, float_status *status) { -#ifdef NO_SIGNALING_NANS - return float16_is_any_nan(a_); -#else - uint16_t a = float16_val(a_); - if (snan_bit_is_one(status)) { - return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF); + if (no_signaling_nans(status)) { + return float16_is_any_nan(a_); } else { - return ((a & ~0x8000) >= 0x7C80); + uint16_t a = float16_val(a_); + if (snan_bit_is_one(status)) { + return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF); + } else { + + return ((a >> 9) & 0x3F) == 0x3F; + } + } +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the bfloat16 value `a' is a quiet +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +bool bfloat16_is_quiet_nan(bfloat16 a_, float_status *status) +{ + if (no_signaling_nans(status)) { + return bfloat16_is_any_nan(a_); + } else { + uint16_t a = a_; + if (snan_bit_is_one(status)) { + return (((a >> 6) & 0x1FF) == 0x1FE) && (a & 0x3F); + } else { + return ((a >> 6) & 0x1FF) == 0x1FF; + } } -#endif } /*---------------------------------------------------------------------------- @@ -266,16 +291,35 @@ bool float16_is_quiet_nan(float16 a_, float_status *status) bool float16_is_signaling_nan(float16 a_, float_status *status) { -#ifdef NO_SIGNALING_NANS - return 0; -#else - uint16_t a = float16_val(a_); - if (snan_bit_is_one(status)) { - return ((a & ~0x8000) >= 0x7C80); + if (no_signaling_nans(status)) { + return 0; + } else { + uint16_t a = float16_val(a_); + if (snan_bit_is_one(status)) { + return ((a >> 9) & 0x3F) == 0x3F; + } else { + return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF); + } + } +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the bfloat16 value `a' is a signaling +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +bool bfloat16_is_signaling_nan(bfloat16 a_, float_status *status) +{ + if (no_signaling_nans(status)) { + return 0; } else { - return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF); + uint16_t a = a_; + if (snan_bit_is_one(status)) { + return ((a >> 6) & 0x1FF) == 0x1FF; + } else { + return (((a >> 6) & 0x1FF) == 0x1FE) && (a & 0x3F); + } } -#endif } /*---------------------------------------------------------------------------- @@ -285,16 +329,16 @@ bool float16_is_signaling_nan(float16 a_, float_status *status) bool float32_is_quiet_nan(float32 a_, float_status *status) { -#ifdef NO_SIGNALING_NANS - return float32_is_any_nan(a_); -#else - uint32_t a = float32_val(a_); - if (snan_bit_is_one(status)) { - return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF); + if (no_signaling_nans(status)) { + return float32_is_any_nan(a_); } else { - return ((uint32_t)(a << 1) >= 0xFF800000); + uint32_t a = float32_val(a_); + if (snan_bit_is_one(status)) { + return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF); + } else { + return ((uint32_t)(a << 1) >= 0xFF800000); + } } -#endif } /*---------------------------------------------------------------------------- @@ -304,16 +348,16 @@ bool float32_is_quiet_nan(float32 a_, float_status *status) bool float32_is_signaling_nan(float32 a_, float_status *status) { -#ifdef NO_SIGNALING_NANS - return 0; -#else - uint32_t a = float32_val(a_); - if (snan_bit_is_one(status)) { - return ((uint32_t)(a << 1) >= 0xFF800000); + if (no_signaling_nans(status)) { + return 0; } else { - return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF); + uint32_t a = float32_val(a_); + if (snan_bit_is_one(status)) { + return ((uint32_t)(a << 1) >= 0xFF800000); + } else { + return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF); + } } -#endif } /*---------------------------------------------------------------------------- @@ -374,7 +418,7 @@ static float32 commonNaNToFloat32(commonNaNT a, float_status *status) *----------------------------------------------------------------------------*/ static int pickNaN(FloatClass a_cls, FloatClass b_cls, - bool aIsLargerSignificand) + bool aIsLargerSignificand, float_status *status) { #if defined(TARGET_ARM) || defined(TARGET_MIPS) || defined(TARGET_HPPA) /* ARM mandated NaN propagation rules (see FPProcessNaNs()), take @@ -407,7 +451,7 @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls, } else { return 1; } -#elif defined(TARGET_PPC) || defined(TARGET_XTENSA) || defined(TARGET_M68K) +#elif defined(TARGET_PPC) || defined(TARGET_M68K) /* PowerPC propagation rules: * 1. A if it sNaN or qNaN * 2. B if it sNaN or qNaN @@ -432,6 +476,24 @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls, } else { return 1; } +#elif defined(TARGET_XTENSA) + /* + * Xtensa has two NaN propagation modes. + * Which one is active is controlled by float_status::use_first_nan. + */ + if (status->use_first_nan) { + if (is_nan(a_cls)) { + return 0; + } else { + return 1; + } + } else { + if (is_nan(b_cls)) { + return 1; + } else { + return 0; + } + } #else /* This implements x87 NaN propagation rules: * SNaN + QNaN => return the QNaN @@ -562,6 +624,32 @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls, } else { return 1; } +#elif defined(TARGET_XTENSA) + /* + * For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns + * an input NaN if we have one (ie c). + */ + if (infzero) { + float_raise(float_flag_invalid, status); + return 2; + } + if (status->use_first_nan) { + if (is_nan(a_cls)) { + return 0; + } else if (is_nan(b_cls)) { + return 1; + } else { + return 2; + } + } else { + if (is_nan(c_cls)) { + return 2; + } else if (is_nan(b_cls)) { + return 1; + } else { + return 0; + } + } #else /* A default implementation: prefer a to b to c. * This is unlikely to actually match any real implementation. @@ -619,7 +707,7 @@ static float32 propagateFloat32NaN(float32 a, float32 b, float_status *status) aIsLargerSignificand = (av < bv) ? 1 : 0; } - if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) { + if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) { if (is_snan(b_cls)) { return float32_silence_nan(b, status); } @@ -639,17 +727,17 @@ static float32 propagateFloat32NaN(float32 a, float32 b, float_status *status) bool float64_is_quiet_nan(float64 a_, float_status *status) { -#ifdef NO_SIGNALING_NANS - return float64_is_any_nan(a_); -#else - uint64_t a = float64_val(a_); - if (snan_bit_is_one(status)) { - return (((a >> 51) & 0xFFF) == 0xFFE) - && (a & 0x0007FFFFFFFFFFFFULL); + if (no_signaling_nans(status)) { + return float64_is_any_nan(a_); } else { - return ((a << 1) >= 0xFFF0000000000000ULL); + uint64_t a = float64_val(a_); + if (snan_bit_is_one(status)) { + return (((a >> 51) & 0xFFF) == 0xFFE) + && (a & 0x0007FFFFFFFFFFFFULL); + } else { + return ((a << 1) >= 0xFFF0000000000000ULL); + } } -#endif } /*---------------------------------------------------------------------------- @@ -659,17 +747,17 @@ bool float64_is_quiet_nan(float64 a_, float_status *status) bool float64_is_signaling_nan(float64 a_, float_status *status) { -#ifdef NO_SIGNALING_NANS - return 0; -#else - uint64_t a = float64_val(a_); - if (snan_bit_is_one(status)) { - return ((a << 1) >= 0xFFF0000000000000ULL); + if (no_signaling_nans(status)) { + return 0; } else { - return (((a >> 51) & 0xFFF) == 0xFFE) - && (a & UINT64_C(0x0007FFFFFFFFFFFF)); + uint64_t a = float64_val(a_); + if (snan_bit_is_one(status)) { + return ((a << 1) >= 0xFFF0000000000000ULL); + } else { + return (((a >> 51) & 0xFFF) == 0xFFE) + && (a & UINT64_C(0x0007FFFFFFFFFFFF)); + } } -#endif } /*---------------------------------------------------------------------------- @@ -757,7 +845,7 @@ static float64 propagateFloat64NaN(float64 a, float64 b, float_status *status) aIsLargerSignificand = (av < bv) ? 1 : 0; } - if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) { + if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) { if (is_snan(b_cls)) { return float64_silence_nan(b, status); } @@ -778,21 +866,21 @@ static float64 propagateFloat64NaN(float64 a, float64 b, float_status *status) int floatx80_is_quiet_nan(floatx80 a, float_status *status) { -#ifdef NO_SIGNALING_NANS - return floatx80_is_any_nan(a); -#else - if (snan_bit_is_one(status)) { - uint64_t aLow; - - aLow = a.low & ~0x4000000000000000ULL; - return ((a.high & 0x7FFF) == 0x7FFF) - && (aLow << 1) - && (a.low == aLow); + if (no_signaling_nans(status)) { + return floatx80_is_any_nan(a); } else { - return ((a.high & 0x7FFF) == 0x7FFF) - && (UINT64_C(0x8000000000000000) <= ((uint64_t)(a.low << 1))); + if (snan_bit_is_one(status)) { + uint64_t aLow; + + aLow = a.low & ~0x4000000000000000ULL; + return ((a.high & 0x7FFF) == 0x7FFF) + && (aLow << 1) + && (a.low == aLow); + } else { + return ((a.high & 0x7FFF) == 0x7FFF) + && (UINT64_C(0x8000000000000000) <= ((uint64_t)(a.low << 1))); + } } -#endif } /*---------------------------------------------------------------------------- @@ -803,21 +891,21 @@ int floatx80_is_quiet_nan(floatx80 a, float_status *status) int floatx80_is_signaling_nan(floatx80 a, float_status *status) { -#ifdef NO_SIGNALING_NANS - return 0; -#else - if (snan_bit_is_one(status)) { - return ((a.high & 0x7FFF) == 0x7FFF) - && ((a.low << 1) >= 0x8000000000000000ULL); + if (no_signaling_nans(status)) { + return 0; } else { - uint64_t aLow; + if (snan_bit_is_one(status)) { + return ((a.high & 0x7FFF) == 0x7FFF) + && ((a.low << 1) >= 0x8000000000000000ULL); + } else { + uint64_t aLow; - aLow = a.low & ~UINT64_C(0x4000000000000000); - return ((a.high & 0x7FFF) == 0x7FFF) - && (uint64_t)(aLow << 1) - && (a.low == aLow); + aLow = a.low & ~UINT64_C(0x4000000000000000); + return ((a.high & 0x7FFF) == 0x7FFF) + && (uint64_t)(aLow << 1) + && (a.low == aLow); + } } -#endif } /*---------------------------------------------------------------------------- @@ -921,7 +1009,7 @@ floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status) aIsLargerSignificand = (a.high < b.high) ? 1 : 0; } - if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) { + if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) { if (is_snan(b_cls)) { return floatx80_silence_nan(b, status); } @@ -941,17 +1029,17 @@ floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status) bool float128_is_quiet_nan(float128 a, float_status *status) { -#ifdef NO_SIGNALING_NANS - return float128_is_any_nan(a); -#else - if (snan_bit_is_one(status)) { - return (((a.high >> 47) & 0xFFFF) == 0xFFFE) - && (a.low || (a.high & 0x00007FFFFFFFFFFFULL)); + if (no_signaling_nans(status)) { + return float128_is_any_nan(a); } else { - return ((a.high << 1) >= 0xFFFF000000000000ULL) - && (a.low || (a.high & 0x0000FFFFFFFFFFFFULL)); + if (snan_bit_is_one(status)) { + return (((a.high >> 47) & 0xFFFF) == 0xFFFE) + && (a.low || (a.high & 0x00007FFFFFFFFFFFULL)); + } else { + return ((a.high << 1) >= 0xFFFF000000000000ULL) + && (a.low || (a.high & 0x0000FFFFFFFFFFFFULL)); + } } -#endif } /*---------------------------------------------------------------------------- @@ -961,17 +1049,17 @@ bool float128_is_quiet_nan(float128 a, float_status *status) bool float128_is_signaling_nan(float128 a, float_status *status) { -#ifdef NO_SIGNALING_NANS - return 0; -#else - if (snan_bit_is_one(status)) { - return ((a.high << 1) >= 0xFFFF000000000000ULL) - && (a.low || (a.high & 0x0000FFFFFFFFFFFFULL)); + if (no_signaling_nans(status)) { + return 0; } else { - return (((a.high >> 47) & 0xFFFF) == 0xFFFE) - && (a.low || (a.high & UINT64_C(0x00007FFFFFFFFFFF))); + if (snan_bit_is_one(status)) { + return ((a.high << 1) >= 0xFFFF000000000000ULL) + && (a.low || (a.high & 0x0000FFFFFFFFFFFFULL)); + } else { + return (((a.high >> 47) & 0xFFFF) == 0xFFFE) + && (a.low || (a.high & UINT64_C(0x00007FFFFFFFFFFF))); + } } -#endif } /*---------------------------------------------------------------------------- @@ -981,16 +1069,16 @@ bool float128_is_signaling_nan(float128 a, float_status *status) float128 float128_silence_nan(float128 a, float_status *status) { -#ifdef NO_SIGNALING_NANS - g_assert_not_reached(); -#else - if (snan_bit_is_one(status)) { - return float128_default_nan(status); + if (no_signaling_nans(status)) { + g_assert_not_reached(); } else { - a.high |= UINT64_C(0x0000800000000000); - return a; + if (snan_bit_is_one(status)) { + return float128_default_nan(status); + } else { + a.high |= UINT64_C(0x0000800000000000); + return a; + } } -#endif } /*---------------------------------------------------------------------------- @@ -1069,7 +1157,7 @@ static float128 propagateFloat128NaN(float128 a, float128 b, aIsLargerSignificand = (a.high < b.high) ? 1 : 0; } - if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) { + if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) { if (is_snan(b_cls)) { return float128_silence_nan(b, status); } diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 6c8f2d597a4b15e3c27b69a71a10c7d1492077c1..67cfa0fd82ccd5e4f640b4e2ee8d552ab380c472 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -554,6 +554,10 @@ static const FloatFmt float16_params_ahp = { .arm_althp = true }; +static const FloatFmt bfloat16_params = { + FLOAT_PARAMS(8, 7) +}; + static const FloatFmt float32_params = { FLOAT_PARAMS(8, 23) }; @@ -580,6 +584,11 @@ static inline FloatParts float16_unpack_raw(float16 f) return unpack_raw(float16_params, f); } +static inline FloatParts bfloat16_unpack_raw(bfloat16 f) +{ + return unpack_raw(bfloat16_params, f); +} + static inline FloatParts float32_unpack_raw(float32 f) { return unpack_raw(float32_params, f); @@ -603,6 +612,11 @@ static inline float16 float16_pack_raw(FloatParts p) return make_float16(pack_raw(float16_params, p)); } +static inline bfloat16 bfloat16_pack_raw(FloatParts p) +{ + return pack_raw(bfloat16_params, p); +} + static inline float32 float32_pack_raw(FloatParts p) { return make_float32(pack_raw(float32_params, p)); @@ -621,7 +635,7 @@ static inline float64 float64_pack_raw(FloatParts p) | are propagated from function inputs to output. These details are target- | specific. *----------------------------------------------------------------------------*/ -#include "softfloat-specialize.inc.c" +#include "softfloat-specialize.c.inc" /* Canonicalize EXP and FRAC, setting CLS. */ static FloatParts sf_canonicalize(FloatParts part, const FloatFmt *parm, @@ -820,6 +834,11 @@ static FloatParts float16_unpack_canonical(float16 f, float_status *s) return float16a_unpack_canonical(f, s, &float16_params); } +static FloatParts bfloat16_unpack_canonical(bfloat16 f, float_status *s) +{ + return sf_canonicalize(bfloat16_unpack_raw(f), &bfloat16_params, s); +} + static float16 float16a_round_pack_canonical(FloatParts p, float_status *s, const FloatFmt *params) { @@ -831,6 +850,11 @@ static float16 float16_round_pack_canonical(FloatParts p, float_status *s) return float16a_round_pack_canonical(p, s, &float16_params); } +static bfloat16 bfloat16_round_pack_canonical(FloatParts p, float_status *s) +{ + return bfloat16_pack_raw(round_canonical(p, s, &bfloat16_params)); +} + static FloatParts float32_unpack_canonical(float32 f, float_status *s) { return sf_canonicalize(float32_unpack_raw(f), &float32_params, s); @@ -881,7 +905,7 @@ static FloatParts pick_nan(FloatParts a, FloatParts b, float_status *s) } else { if (pickNaN(a.cls, b.cls, a.frac > b.frac || - (a.frac == b.frac && a.sign < b.sign))) { + (a.frac == b.frac && a.sign < b.sign), s)) { a = b; } if (is_snan(a.cls)) { @@ -1158,6 +1182,28 @@ float64_sub(float64 a, float64 b, float_status *s) return float64_addsub(a, b, s, hard_f64_sub, soft_f64_sub); } +/* + * Returns the result of adding or subtracting the bfloat16 + * values `a' and `b'. + */ +bfloat16 QEMU_FLATTEN bfloat16_add(bfloat16 a, bfloat16 b, float_status *status) +{ + FloatParts pa = bfloat16_unpack_canonical(a, status); + FloatParts pb = bfloat16_unpack_canonical(b, status); + FloatParts pr = addsub_floats(pa, pb, false, status); + + return bfloat16_round_pack_canonical(pr, status); +} + +bfloat16 QEMU_FLATTEN bfloat16_sub(bfloat16 a, bfloat16 b, float_status *status) +{ + FloatParts pa = bfloat16_unpack_canonical(a, status); + FloatParts pb = bfloat16_unpack_canonical(b, status); + FloatParts pr = addsub_floats(pa, pb, true, status); + + return bfloat16_round_pack_canonical(pr, status); +} + /* * Returns the result of multiplying the floating-point values `a' and * `b'. The operation is performed according to the IEC/IEEE Standard @@ -1260,6 +1306,20 @@ float64_mul(float64 a, float64 b, float_status *s) f64_is_zon2, f64_addsubmul_post); } +/* + * Returns the result of multiplying the bfloat16 + * values `a' and `b'. + */ + +bfloat16 QEMU_FLATTEN bfloat16_mul(bfloat16 a, bfloat16 b, float_status *status) +{ + FloatParts pa = bfloat16_unpack_canonical(a, status); + FloatParts pb = bfloat16_unpack_canonical(b, status); + FloatParts pr = mul_floats(pa, pb, status); + + return bfloat16_round_pack_canonical(pr, status); +} + /* * Returns the result of multiplying the floating-point values `a' and * `b' then adding 'c', with no intermediate rounding step after the @@ -1642,6 +1702,23 @@ float64_muladd(float64 xa, float64 xb, float64 xc, int flags, float_status *s) return soft_f64_muladd(ua.s, ub.s, uc.s, flags, s); } +/* + * Returns the result of multiplying the bfloat16 values `a' + * and `b' then adding 'c', with no intermediate rounding step after the + * multiplication. + */ + +bfloat16 QEMU_FLATTEN bfloat16_muladd(bfloat16 a, bfloat16 b, bfloat16 c, + int flags, float_status *status) +{ + FloatParts pa = bfloat16_unpack_canonical(a, status); + FloatParts pb = bfloat16_unpack_canonical(b, status); + FloatParts pc = bfloat16_unpack_canonical(c, status); + FloatParts pr = muladd_floats(pa, pb, pc, flags, status); + + return bfloat16_round_pack_canonical(pr, status); +} + /* * Returns the result of dividing the floating-point value `a' by the * corresponding value `b'. The operation is performed according to @@ -1808,6 +1885,20 @@ float64_div(float64 a, float64 b, float_status *s) f64_div_pre, f64_div_post); } +/* + * Returns the result of dividing the bfloat16 + * value `a' by the corresponding value `b'. + */ + +bfloat16 bfloat16_div(bfloat16 a, bfloat16 b, float_status *status) +{ + FloatParts pa = bfloat16_unpack_canonical(a, status); + FloatParts pb = bfloat16_unpack_canonical(b, status); + FloatParts pr = div_floats(pa, pb, status); + + return bfloat16_round_pack_canonical(pr, status); +} + /* * Float to Float conversions * @@ -1923,6 +2014,34 @@ float32 float64_to_float32(float64 a, float_status *s) return float32_round_pack_canonical(pr, s); } +float32 bfloat16_to_float32(bfloat16 a, float_status *s) +{ + FloatParts p = bfloat16_unpack_canonical(a, s); + FloatParts pr = float_to_float(p, &float32_params, s); + return float32_round_pack_canonical(pr, s); +} + +float64 bfloat16_to_float64(bfloat16 a, float_status *s) +{ + FloatParts p = bfloat16_unpack_canonical(a, s); + FloatParts pr = float_to_float(p, &float64_params, s); + return float64_round_pack_canonical(pr, s); +} + +bfloat16 float32_to_bfloat16(float32 a, float_status *s) +{ + FloatParts p = float32_unpack_canonical(a, s); + FloatParts pr = float_to_float(p, &bfloat16_params, s); + return bfloat16_round_pack_canonical(pr, s); +} + +bfloat16 float64_to_bfloat16(float64 a, float_status *s) +{ + FloatParts p = float64_unpack_canonical(a, s); + FloatParts pr = float_to_float(p, &bfloat16_params, s); + return bfloat16_round_pack_canonical(pr, s); +} + /* * Rounds the floating-point value `a' to an integer, and returns the * result as a floating-point value. The operation is performed @@ -2052,6 +2171,18 @@ float64 float64_round_to_int(float64 a, float_status *s) return float64_round_pack_canonical(pr, s); } +/* + * Rounds the bfloat16 value `a' to an integer, and returns the + * result as a bfloat16 value. + */ + +bfloat16 bfloat16_round_to_int(bfloat16 a, float_status *s) +{ + FloatParts pa = bfloat16_unpack_canonical(a, s); + FloatParts pr = round_to_int(pa, s->float_rounding_mode, 0, s); + return bfloat16_round_pack_canonical(pr, s); +} + /* * Returns the result of converting the floating-point value `a' to * the two's complement integer format. The conversion is performed @@ -2109,6 +2240,13 @@ static int64_t round_to_int_and_pack(FloatParts in, FloatRoundMode rmode, } } +int8_t float16_to_int8_scalbn(float16 a, FloatRoundMode rmode, int scale, + float_status *s) +{ + return round_to_int_and_pack(float16_unpack_canonical(a, s), + rmode, scale, INT8_MIN, INT8_MAX, s); +} + int16_t float16_to_int16_scalbn(float16 a, FloatRoundMode rmode, int scale, float_status *s) { @@ -2172,6 +2310,11 @@ int64_t float64_to_int64_scalbn(float64 a, FloatRoundMode rmode, int scale, rmode, scale, INT64_MIN, INT64_MAX, s); } +int8_t float16_to_int8(float16 a, float_status *s) +{ + return float16_to_int8_scalbn(a, s->float_rounding_mode, 0, s); +} + int16_t float16_to_int16(float16 a, float_status *s) { return float16_to_int16_scalbn(a, s->float_rounding_mode, 0, s); @@ -2262,6 +2405,62 @@ int64_t float64_to_int64_round_to_zero(float64 a, float_status *s) return float64_to_int64_scalbn(a, float_round_to_zero, 0, s); } +/* + * Returns the result of converting the floating-point value `a' to + * the two's complement integer format. + */ + +int16_t bfloat16_to_int16_scalbn(bfloat16 a, FloatRoundMode rmode, int scale, + float_status *s) +{ + return round_to_int_and_pack(bfloat16_unpack_canonical(a, s), + rmode, scale, INT16_MIN, INT16_MAX, s); +} + +int32_t bfloat16_to_int32_scalbn(bfloat16 a, FloatRoundMode rmode, int scale, + float_status *s) +{ + return round_to_int_and_pack(bfloat16_unpack_canonical(a, s), + rmode, scale, INT32_MIN, INT32_MAX, s); +} + +int64_t bfloat16_to_int64_scalbn(bfloat16 a, FloatRoundMode rmode, int scale, + float_status *s) +{ + return round_to_int_and_pack(bfloat16_unpack_canonical(a, s), + rmode, scale, INT64_MIN, INT64_MAX, s); +} + +int16_t bfloat16_to_int16(bfloat16 a, float_status *s) +{ + return bfloat16_to_int16_scalbn(a, s->float_rounding_mode, 0, s); +} + +int32_t bfloat16_to_int32(bfloat16 a, float_status *s) +{ + return bfloat16_to_int32_scalbn(a, s->float_rounding_mode, 0, s); +} + +int64_t bfloat16_to_int64(bfloat16 a, float_status *s) +{ + return bfloat16_to_int64_scalbn(a, s->float_rounding_mode, 0, s); +} + +int16_t bfloat16_to_int16_round_to_zero(bfloat16 a, float_status *s) +{ + return bfloat16_to_int16_scalbn(a, float_round_to_zero, 0, s); +} + +int32_t bfloat16_to_int32_round_to_zero(bfloat16 a, float_status *s) +{ + return bfloat16_to_int32_scalbn(a, float_round_to_zero, 0, s); +} + +int64_t bfloat16_to_int64_round_to_zero(bfloat16 a, float_status *s) +{ + return bfloat16_to_int64_scalbn(a, float_round_to_zero, 0, s); +} + /* * Returns the result of converting the floating-point value `a' to * the unsigned integer format. The conversion is performed according @@ -2322,6 +2521,13 @@ static uint64_t round_to_uint_and_pack(FloatParts in, FloatRoundMode rmode, } } +uint8_t float16_to_uint8_scalbn(float16 a, FloatRoundMode rmode, int scale, + float_status *s) +{ + return round_to_uint_and_pack(float16_unpack_canonical(a, s), + rmode, scale, UINT8_MAX, s); +} + uint16_t float16_to_uint16_scalbn(float16 a, FloatRoundMode rmode, int scale, float_status *s) { @@ -2385,6 +2591,11 @@ uint64_t float64_to_uint64_scalbn(float64 a, FloatRoundMode rmode, int scale, rmode, scale, UINT64_MAX, s); } +uint8_t float16_to_uint8(float16 a, float_status *s) +{ + return float16_to_uint8_scalbn(a, s->float_rounding_mode, 0, s); +} + uint16_t float16_to_uint16(float16 a, float_status *s) { return float16_to_uint16_scalbn(a, s->float_rounding_mode, 0, s); @@ -2475,6 +2686,62 @@ uint64_t float64_to_uint64_round_to_zero(float64 a, float_status *s) return float64_to_uint64_scalbn(a, float_round_to_zero, 0, s); } +/* + * Returns the result of converting the bfloat16 value `a' to + * the unsigned integer format. + */ + +uint16_t bfloat16_to_uint16_scalbn(bfloat16 a, FloatRoundMode rmode, + int scale, float_status *s) +{ + return round_to_uint_and_pack(bfloat16_unpack_canonical(a, s), + rmode, scale, UINT16_MAX, s); +} + +uint32_t bfloat16_to_uint32_scalbn(bfloat16 a, FloatRoundMode rmode, + int scale, float_status *s) +{ + return round_to_uint_and_pack(bfloat16_unpack_canonical(a, s), + rmode, scale, UINT32_MAX, s); +} + +uint64_t bfloat16_to_uint64_scalbn(bfloat16 a, FloatRoundMode rmode, + int scale, float_status *s) +{ + return round_to_uint_and_pack(bfloat16_unpack_canonical(a, s), + rmode, scale, UINT64_MAX, s); +} + +uint16_t bfloat16_to_uint16(bfloat16 a, float_status *s) +{ + return bfloat16_to_uint16_scalbn(a, s->float_rounding_mode, 0, s); +} + +uint32_t bfloat16_to_uint32(bfloat16 a, float_status *s) +{ + return bfloat16_to_uint32_scalbn(a, s->float_rounding_mode, 0, s); +} + +uint64_t bfloat16_to_uint64(bfloat16 a, float_status *s) +{ + return bfloat16_to_uint64_scalbn(a, s->float_rounding_mode, 0, s); +} + +uint16_t bfloat16_to_uint16_round_to_zero(bfloat16 a, float_status *s) +{ + return bfloat16_to_uint16_scalbn(a, float_round_to_zero, 0, s); +} + +uint32_t bfloat16_to_uint32_round_to_zero(bfloat16 a, float_status *s) +{ + return bfloat16_to_uint32_scalbn(a, float_round_to_zero, 0, s); +} + +uint64_t bfloat16_to_uint64_round_to_zero(bfloat16 a, float_status *s) +{ + return bfloat16_to_uint64_scalbn(a, float_round_to_zero, 0, s); +} + /* * Integer to float conversions * @@ -2539,6 +2806,11 @@ float16 int16_to_float16(int16_t a, float_status *status) return int64_to_float16_scalbn(a, 0, status); } +float16 int8_to_float16(int8_t a, float_status *status) +{ + return int64_to_float16_scalbn(a, 0, status); +} + float32 int64_to_float32_scalbn(int64_t a, int scale, float_status *status) { FloatParts pa = int_to_float(a, scale, status); @@ -2601,6 +2873,41 @@ float64 int16_to_float64(int16_t a, float_status *status) return int64_to_float64_scalbn(a, 0, status); } +/* + * Returns the result of converting the two's complement integer `a' + * to the bfloat16 format. + */ + +bfloat16 int64_to_bfloat16_scalbn(int64_t a, int scale, float_status *status) +{ + FloatParts pa = int_to_float(a, scale, status); + return bfloat16_round_pack_canonical(pa, status); +} + +bfloat16 int32_to_bfloat16_scalbn(int32_t a, int scale, float_status *status) +{ + return int64_to_bfloat16_scalbn(a, scale, status); +} + +bfloat16 int16_to_bfloat16_scalbn(int16_t a, int scale, float_status *status) +{ + return int64_to_bfloat16_scalbn(a, scale, status); +} + +bfloat16 int64_to_bfloat16(int64_t a, float_status *status) +{ + return int64_to_bfloat16_scalbn(a, 0, status); +} + +bfloat16 int32_to_bfloat16(int32_t a, float_status *status) +{ + return int64_to_bfloat16_scalbn(a, 0, status); +} + +bfloat16 int16_to_bfloat16(int16_t a, float_status *status) +{ + return int64_to_bfloat16_scalbn(a, 0, status); +} /* * Unsigned Integer to float conversions @@ -2664,6 +2971,11 @@ float16 uint16_to_float16(uint16_t a, float_status *status) return uint64_to_float16_scalbn(a, 0, status); } +float16 uint8_to_float16(uint8_t a, float_status *status) +{ + return uint64_to_float16_scalbn(a, 0, status); +} + float32 uint64_to_float32_scalbn(uint64_t a, int scale, float_status *status) { FloatParts pa = uint_to_float(a, scale, status); @@ -2726,6 +3038,42 @@ float64 uint16_to_float64(uint16_t a, float_status *status) return uint64_to_float64_scalbn(a, 0, status); } +/* + * Returns the result of converting the unsigned integer `a' to the + * bfloat16 format. + */ + +bfloat16 uint64_to_bfloat16_scalbn(uint64_t a, int scale, float_status *status) +{ + FloatParts pa = uint_to_float(a, scale, status); + return bfloat16_round_pack_canonical(pa, status); +} + +bfloat16 uint32_to_bfloat16_scalbn(uint32_t a, int scale, float_status *status) +{ + return uint64_to_bfloat16_scalbn(a, scale, status); +} + +bfloat16 uint16_to_bfloat16_scalbn(uint16_t a, int scale, float_status *status) +{ + return uint64_to_bfloat16_scalbn(a, scale, status); +} + +bfloat16 uint64_to_bfloat16(uint64_t a, float_status *status) +{ + return uint64_to_bfloat16_scalbn(a, 0, status); +} + +bfloat16 uint32_to_bfloat16(uint32_t a, float_status *status) +{ + return uint64_to_bfloat16_scalbn(a, 0, status); +} + +bfloat16 uint16_to_bfloat16(uint16_t a, float_status *status) +{ + return uint64_to_bfloat16_scalbn(a, 0, status); +} + /* Float Min/Max */ /* min() and max() functions. These can't be implemented as * 'compare and pick one input' because that would mishandle @@ -2847,6 +3195,25 @@ MINMAX(64, maxnummag, false, true, true) #undef MINMAX +#define BF16_MINMAX(name, ismin, isiee, ismag) \ +bfloat16 bfloat16_ ## name(bfloat16 a, bfloat16 b, float_status *s) \ +{ \ + FloatParts pa = bfloat16_unpack_canonical(a, s); \ + FloatParts pb = bfloat16_unpack_canonical(b, s); \ + FloatParts pr = minmax_floats(pa, pb, ismin, isiee, ismag, s); \ + \ + return bfloat16_round_pack_canonical(pr, s); \ +} + +BF16_MINMAX(min, true, false, false) +BF16_MINMAX(minnum, true, true, false) +BF16_MINMAX(minnummag, true, true, true) +BF16_MINMAX(max, false, false, false) +BF16_MINMAX(maxnum, false, true, false) +BF16_MINMAX(maxnummag, false, true, true) + +#undef BF16_MINMAX + /* Floating point compare */ static FloatRelation compare_floats(FloatParts a, FloatParts b, bool is_quiet, float_status *s) @@ -3008,6 +3375,24 @@ FloatRelation float64_compare_quiet(float64 a, float64 b, float_status *s) return f64_compare(a, b, true, s); } +static FloatRelation QEMU_FLATTEN +soft_bf16_compare(bfloat16 a, bfloat16 b, bool is_quiet, float_status *s) +{ + FloatParts pa = bfloat16_unpack_canonical(a, s); + FloatParts pb = bfloat16_unpack_canonical(b, s); + return compare_floats(pa, pb, is_quiet, s); +} + +FloatRelation bfloat16_compare(bfloat16 a, bfloat16 b, float_status *s) +{ + return soft_bf16_compare(a, b, false, s); +} + +FloatRelation bfloat16_compare_quiet(bfloat16 a, bfloat16 b, float_status *s) +{ + return soft_bf16_compare(a, b, true, s); +} + /* Multiply A by 2 raised to the power N. */ static FloatParts scalbn_decomposed(FloatParts a, int n, float_status *s) { @@ -3047,6 +3432,13 @@ float64 float64_scalbn(float64 a, int n, float_status *status) return float64_round_pack_canonical(pr, status); } +bfloat16 bfloat16_scalbn(bfloat16 a, int n, float_status *status) +{ + FloatParts pa = bfloat16_unpack_canonical(a, status); + FloatParts pr = scalbn_decomposed(pa, n, status); + return bfloat16_round_pack_canonical(pr, status); +} + /* * Square Root * @@ -3197,6 +3589,13 @@ float64 QEMU_FLATTEN float64_sqrt(float64 xa, float_status *s) return soft_f64_sqrt(ua.s, s); } +bfloat16 QEMU_FLATTEN bfloat16_sqrt(bfloat16 a, float_status *status) +{ + FloatParts pa = bfloat16_unpack_canonical(a, status); + FloatParts pr = sqrt_float(pa, status, &bfloat16_params); + return bfloat16_round_pack_canonical(pr, status); +} + /*---------------------------------------------------------------------------- | The pattern for a default generated NaN. *----------------------------------------------------------------------------*/ @@ -3239,6 +3638,13 @@ float128 float128_default_nan(float_status *status) return r; } +bfloat16 bfloat16_default_nan(float_status *status) +{ + FloatParts p = parts_default_nan(status); + p.frac >>= bfloat16_params.frac_shift; + return bfloat16_pack_raw(p); +} + /*---------------------------------------------------------------------------- | Returns a quiet NaN from a signalling NaN for the floating point value `a'. *----------------------------------------------------------------------------*/ @@ -3270,6 +3676,14 @@ float64 float64_silence_nan(float64 a, float_status *status) return float64_pack_raw(p); } +bfloat16 bfloat16_silence_nan(bfloat16 a, float_status *status) +{ + FloatParts p = bfloat16_unpack_raw(a); + p.frac <<= bfloat16_params.frac_shift; + p = parts_silence_nan(p, status); + p.frac >>= bfloat16_params.frac_shift; + return bfloat16_pack_raw(p); +} /*---------------------------------------------------------------------------- | If `a' is denormal and we are in flush-to-zero mode then set the @@ -3319,6 +3733,17 @@ float64 float64_squash_input_denormal(float64 a, float_status *status) return a; } +bfloat16 bfloat16_squash_input_denormal(bfloat16 a, float_status *status) +{ + if (status->flush_inputs_to_zero) { + FloatParts p = bfloat16_unpack_raw(a); + if (parts_squash_denormal(p, status)) { + return bfloat16_set_sign(bfloat16_zero, p.sign); + } + } + return a; +} + /*---------------------------------------------------------------------------- | Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 | and 7, and returns the properly rounded 32-bit integer corresponding to the @@ -3362,7 +3787,9 @@ static int32_t roundAndPackInt32(bool zSign, uint64_t absZ, } roundBits = absZ & 0x7F; absZ = ( absZ + roundIncrement )>>7; - absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); + if (!(roundBits ^ 0x40) && roundNearestEven) { + absZ &= ~1; + } z = absZ; if ( zSign ) z = - z; if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { @@ -3420,7 +3847,9 @@ static int64_t roundAndPackInt64(bool zSign, uint64_t absZ0, uint64_t absZ1, if ( increment ) { ++absZ0; if ( absZ0 == 0 ) goto overflow; - absZ0 &= ~ ( ( (uint64_t) ( absZ1<<1 ) == 0 ) & roundNearestEven ); + if (!(absZ1 << 1) && roundNearestEven) { + absZ0 &= ~1; + } } z = absZ0; if ( zSign ) z = - z; @@ -3480,7 +3909,9 @@ static int64_t roundAndPackUint64(bool zSign, uint64_t absZ0, float_raise(float_flag_invalid, status); return UINT64_MAX; } - absZ0 &= ~(((uint64_t)(absZ1<<1) == 0) & roundNearestEven); + if (!(absZ1 << 1) && roundNearestEven) { + absZ0 &= ~1; + } } if (zSign && absZ0) { @@ -3603,7 +4034,9 @@ static float32 roundAndPackFloat32(bool zSign, int zExp, uint32_t zSig, status->float_exception_flags |= float_flag_inexact; } zSig = ( zSig + roundIncrement )>>7; - zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); + if (!(roundBits ^ 0x40) && roundNearestEven) { + zSig &= ~1; + } if ( zSig == 0 ) zExp = 0; return packFloat32( zSign, zExp, zSig ); @@ -3757,7 +4190,9 @@ static float64 roundAndPackFloat64(bool zSign, int zExp, uint64_t zSig, status->float_exception_flags |= float_flag_inexact; } zSig = ( zSig + roundIncrement )>>10; - zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); + if (!(roundBits ^ 0x200) && roundNearestEven) { + zSig &= ~1; + } if ( zSig == 0 ) zExp = 0; return packFloat64( zSign, zExp, zSig ); @@ -3983,8 +4418,9 @@ floatx80 roundAndPackFloatx80(int8_t roundingPrecision, bool zSign, } if ( increment ) { ++zSig0; - zSig0 &= - ~ ( ( (uint64_t) ( zSig1<<1 ) == 0 ) & roundNearestEven ); + if (!(zSig1 << 1) && roundNearestEven) { + zSig0 &= ~1; + } if ( (int64_t) zSig0 < 0 ) zExp = 1; } return packFloatx80( zSign, zExp, zSig0 ); @@ -4000,7 +4436,9 @@ floatx80 roundAndPackFloatx80(int8_t roundingPrecision, bool zSign, zSig0 = UINT64_C(0x8000000000000000); } else { - zSig0 &= ~ ( ( (uint64_t) ( zSig1<<1 ) == 0 ) & roundNearestEven ); + if (!(zSig1 << 1) && roundNearestEven) { + zSig0 &= ~1; + } } } else { @@ -4270,7 +4708,9 @@ static float128 roundAndPackFloat128(bool zSign, int32_t zExp, } if ( increment ) { add128( zSig0, zSig1, 0, 1, &zSig0, &zSig1 ); - zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven ); + if ((zSig2 + zSig2 == 0) && roundNearestEven) { + zSig1 &= ~1; + } } else { if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0; @@ -5682,22 +6122,27 @@ floatx80 floatx80_div(floatx80 a, floatx80 b, float_status *status) /*---------------------------------------------------------------------------- | Returns the remainder of the extended double-precision floating-point value | `a' with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic, +| if 'mod' is false; if 'mod' is true, return the remainder based on truncating +| the quotient toward zero instead. '*quotient' is set to the low 64 bits of +| the absolute value of the integer quotient. *----------------------------------------------------------------------------*/ -floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status) +floatx80 floatx80_modrem(floatx80 a, floatx80 b, bool mod, uint64_t *quotient, + float_status *status) { bool aSign, zSign; - int32_t aExp, bExp, expDiff; + int32_t aExp, bExp, expDiff, aExpOrig; uint64_t aSig0, aSig1, bSig; uint64_t q, term0, term1, alternateASig0, alternateASig1; + *quotient = 0; if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) { float_raise(float_flag_invalid, status); return floatx80_default_nan(status); } aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); + aExpOrig = aExp = extractFloatx80Exp( a ); aSign = extractFloatx80Sign( a ); bSig = extractFloatx80Frac( b ); bExp = extractFloatx80Exp( b ); @@ -5712,6 +6157,13 @@ floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status) if ((uint64_t)(bSig << 1)) { return propagateFloatx80NaN(a, b, status); } + if (aExp == 0 && aSig0 >> 63) { + /* + * Pseudo-denormal argument must be returned in normalized + * form. + */ + return packFloatx80(aSign, 1, aSig0); + } return a; } if ( bExp == 0 ) { @@ -5723,19 +6175,27 @@ floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status) normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); } if ( aExp == 0 ) { - if ( (uint64_t) ( aSig0<<1 ) == 0 ) return a; + if ( aSig0 == 0 ) return a; normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); } - bSig |= UINT64_C(0x8000000000000000); zSign = aSign; expDiff = aExp - bExp; aSig1 = 0; if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; + if ( mod || expDiff < -1 ) { + if (aExp == 1 && aExpOrig == 0) { + /* + * Pseudo-denormal argument must be returned in + * normalized form. + */ + return packFloatx80(aSign, aExp, aSig0); + } + return a; + } shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); expDiff = 0; } - q = ( bSig <= aSig0 ); + *quotient = q = ( bSig <= aSig0 ); if ( q ) aSig0 -= bSig; expDiff -= 64; while ( 0 < expDiff ) { @@ -5745,6 +6205,8 @@ floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status) sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 ); expDiff -= 62; + *quotient <<= 62; + *quotient += q; } expDiff += 64; if ( 0 < expDiff ) { @@ -5758,19 +6220,28 @@ floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status) ++q; sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); } + if (expDiff < 64) { + *quotient <<= expDiff; + } else { + *quotient = 0; + } + *quotient += q; } else { term1 = 0; term0 = bSig; } - sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); - if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) - || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) - && ( q & 1 ) ) - ) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - zSign = ! zSign; + if (!mod) { + sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); + if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) + || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) + && ( q & 1 ) ) + ) { + aSig0 = alternateASig0; + aSig1 = alternateASig1; + zSign = ! zSign; + ++*quotient; + } } return normalizeRoundAndPackFloatx80( @@ -5778,6 +6249,30 @@ floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status) } +/*---------------------------------------------------------------------------- +| Returns the remainder of the extended double-precision floating-point value +| `a' with respect to the corresponding value `b'. The operation is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status) +{ + uint64_t quotient; + return floatx80_modrem(a, b, false, "ient, status); +} + +/*---------------------------------------------------------------------------- +| Returns the remainder of the extended double-precision floating-point value +| `a' with respect to the corresponding value `b', with the quotient truncated +| toward zero. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status) +{ + uint64_t quotient; + return floatx80_modrem(a, b, true, "ient, status); +} + /*---------------------------------------------------------------------------- | Returns the square root of the extended double-precision floating-point | value `a'. The operation is performed according to the IEC/IEEE Standard diff --git a/fsdev/Makefile.objs b/fsdev/Makefile.objs deleted file mode 100644 index 42cd70c367fd1b4d002a98b7c87d707ed6448f8a..0000000000000000000000000000000000000000 --- a/fsdev/Makefile.objs +++ /dev/null @@ -1,12 +0,0 @@ -# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add. -# only pull in the actual 9p backend if we also enabled virtio or xen. -ifeq ($(CONFIG_FSDEV_9P),y) -common-obj-y = qemu-fsdev.o 9p-marshal.o 9p-iov-marshal.o -else -common-obj-y = qemu-fsdev-dummy.o -endif -common-obj-y += qemu-fsdev-opts.o qemu-fsdev-throttle.o - -# Toplevel always builds this; targets without virtio will put it in -# common-obj-y -common-obj-$(CONFIG_ALL) += qemu-fsdev-dummy.o diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h index f2f7772c86d5ae45d1a8bb539a9a023ae8379b3f..d51cec2f3be0b6efc5e756cb5ee6fe03782cccfa 100644 --- a/fsdev/file-op-9p.h +++ b/fsdev/file-op-9p.h @@ -64,6 +64,10 @@ typedef struct ExtendedOps { */ #define V9FS_REMAP_INODES 0x00000200 #define V9FS_FORBID_MULTIDEVS 0x00000400 +/* + * Disables certain performance warnings from being logged on host side. + */ +#define V9FS_NO_PERF_WARN 0x00000800 #define V9FS_SEC_MASK 0x0000003C diff --git a/fsdev/meson.build b/fsdev/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..7dd1cc9bfb991fa0d567d2ac0bf221503356f278 --- /dev/null +++ b/fsdev/meson.build @@ -0,0 +1,18 @@ +fsdev_ss = ss.source_set() +fsdev_ss.add(files('qemu-fsdev-opts.c', 'qemu-fsdev-throttle.c')) +fsdev_ss.add(when: 'CONFIG_ALL', if_true: files('qemu-fsdev-dummy.c')) +fsdev_ss.add(when: ['CONFIG_FSDEV_9P'], if_true: files( + '9p-iov-marshal.c', + '9p-marshal.c', + 'qemu-fsdev.c', +), if_false: files('qemu-fsdev-dummy.c')) +softmmu_ss.add_all(when: 'CONFIG_LINUX', if_true: fsdev_ss) + +have_virtfs_proxy_helper = have_tools and libattr.found() and libcap_ng.found() and 'CONFIG_VIRTFS' in config_host +if have_virtfs_proxy_helper + executable('virtfs-proxy-helper', + files('virtfs-proxy-helper.c', '9p-marshal.c', '9p-iov-marshal.c'), + dependencies: [qemuutil, libattr, libcap_ng], + install: true, + install_dir: get_option('libexecdir')) +endif diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c index a9e069c0c78d8075caea939a8664be34442120f0..3da64e9f72b4a7cd44b8ad1cdba288cb6db41667 100644 --- a/fsdev/qemu-fsdev.c +++ b/fsdev/qemu-fsdev.c @@ -78,6 +78,7 @@ static FsDriverTable FsDrivers[] = { "throttling.iops-read-max-length", "throttling.iops-write-max-length", "throttling.iops-size", + NULL }, }, { @@ -85,6 +86,7 @@ static FsDriverTable FsDrivers[] = { .ops = &synth_ops, .opts = (const char * []) { COMMON_FS_DRIVER_OPTIONS, + NULL }, }, { @@ -95,6 +97,7 @@ static FsDriverTable FsDrivers[] = { "socket", "sock_fd", "writeout", + NULL }, }, }; diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c index de061a8a0eaaa496ce70ec859a0d36f66793fcbc..15c0e79b067b89a6253a680dbf0126c89d74ce47 100644 --- a/fsdev/virtfs-proxy-helper.c +++ b/fsdev/virtfs-proxy-helper.c @@ -518,7 +518,7 @@ static void statfs_to_prstatfs(ProxyStatFS *pr_stfs, struct statfs *stfs) /* * Gets stat/statfs information and packs in out_iovec structure - * on success returns number of bytes packed in out_iovec struture + * on success returns number of bytes packed in out_iovec structure * otherwise returns -errno */ static int do_stat(int type, struct iovec *iovec, struct iovec *out_iovec) diff --git a/gdb-xml/avr-cpu.xml b/gdb-xml/avr-cpu.xml new file mode 100644 index 0000000000000000000000000000000000000000..c4747f5b40e92f755d42651b549e9d88f80d483a --- /dev/null +++ b/gdb-xml/avr-cpu.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdbstub.c b/gdbstub.c index 6950fd243f34154ddd270d823502a1fce815db2b..f19f98ab1ab7d36c53a715bf885c77cfe01675d7 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -30,7 +30,7 @@ #include "qemu/ctype.h" #include "qemu/cutils.h" #include "qemu/module.h" -#include "trace-root.h" +#include "trace/trace-root.h" #ifdef CONFIG_USER_ONLY #include "qemu.h" #else @@ -51,6 +51,7 @@ #include "sysemu/runstate.h" #include "hw/semihosting/semihost.h" #include "exec/exec-all.h" +#include "sysemu/replay.h" #ifdef CONFIG_USER_ONLY #define GDB_ATTACHED "0" @@ -375,6 +376,20 @@ typedef struct GDBState { */ static int sstep_flags = SSTEP_ENABLE|SSTEP_NOIRQ|SSTEP_NOTIMER; +/* Retrieves flags for single step mode. */ +static int get_sstep_flags(void) +{ + /* + * In replay mode all events written into the log should be replayed. + * That is why NOIRQ flag is removed in this mode. + */ + if (replay_mode != REPLAY_MODE_NONE) { + return SSTEP_ENABLE; + } else { + return sstep_flags; + } +} + static GDBState gdbserver_state; static void init_gdbserver_state(void) @@ -501,7 +516,7 @@ static int gdb_continue_partial(char *newstates) break; /* nothing to do here */ case 's': trace_gdbstub_op_stepping(cpu->cpu_index); - cpu_single_step(cpu, sstep_flags); + cpu_single_step(cpu, get_sstep_flags()); cpu_resume(cpu); flag = 1; break; @@ -1874,10 +1889,38 @@ static void handle_step(GdbCmdContext *gdb_ctx, void *user_ctx) gdb_set_cpu_pc((target_ulong)gdb_ctx->params[0].val_ull); } - cpu_single_step(gdbserver_state.c_cpu, sstep_flags); + cpu_single_step(gdbserver_state.c_cpu, get_sstep_flags()); gdb_continue(); } +static void handle_backward(GdbCmdContext *gdb_ctx, void *user_ctx) +{ + if (replay_mode != REPLAY_MODE_PLAY) { + put_packet("E22"); + } + if (gdb_ctx->num_params == 1) { + switch (gdb_ctx->params[0].opcode) { + case 's': + if (replay_reverse_step()) { + gdb_continue(); + } else { + put_packet("E14"); + } + return; + case 'c': + if (replay_reverse_continue()) { + gdb_continue(); + } else { + put_packet("E14"); + } + return; + } + } + + /* Default invalid command */ + put_packet(""); +} + static void handle_v_cont_query(GdbCmdContext *gdb_ctx, void *user_ctx) { put_packet("vCont;c;C;s;S"); @@ -2059,7 +2102,7 @@ static void handle_query_thread_extra(GdbCmdContext *gdb_ctx, void *user_ctx) /* Print the CPU model and name in multiprocess mode */ ObjectClass *oc = object_get_class(OBJECT(cpu)); const char *cpu_model = object_class_get_name(oc); - g_autofree char *cpu_name = + const char *cpu_name = object_get_canonical_path_component(OBJECT(cpu)); g_string_printf(rs, "%s %s [%s]", cpu_model, cpu_name, cpu->halted ? "halted " : "running"); @@ -2124,6 +2167,11 @@ static void handle_query_supported(GdbCmdContext *gdb_ctx, void *user_ctx) g_string_append(gdbserver_state.str_buf, ";qXfer:features:read+"); } + if (replay_mode == REPLAY_MODE_PLAY) { + g_string_append(gdbserver_state.str_buf, + ";ReverseStep+;ReverseContinue+"); + } + if (gdb_ctx->num_params && strstr(gdb_ctx->params[0].data, "multiprocess+")) { gdbserver_state.multiprocess = true; @@ -2460,6 +2508,17 @@ static int gdb_handle_packet(const char *line_buf) cmd_parser = &step_cmd_desc; } break; + case 'b': + { + static const GdbCmdParseEntry backward_cmd_desc = { + .handler = handle_backward, + .cmd = "b", + .cmd_startswith = 1, + .schema = "o0" + }; + cmd_parser = &backward_cmd_desc; + } + break; case 'F': { static const GdbCmdParseEntry file_io_cmd_desc = { @@ -3262,6 +3321,7 @@ static void gdb_chr_event(void *opaque, QEMUChrEvent event) s->g_cpu = s->c_cpu; vm_stop(RUN_STATE_PAUSED); + replay_gdb_attached(); gdb_has_xml = false; break; default: diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index ca5198438deccd2b9e9e8350fe913435c0ba34e0..117ba25f91dbd8879558279b8b384b9a4e640884 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -254,11 +254,12 @@ ERST { .name = "mtree", - .args_type = "flatview:-f,dispatch_tree:-d,owner:-o", - .params = "[-f][-d][-o]", + .args_type = "flatview:-f,dispatch_tree:-d,owner:-o,disabled:-D", + .params = "[-f][-d][-o][-D]", .help = "show memory tree (-f: dump flat view for address spaces;" "-d: dump dispatch tree, valid with -f only);" - "-o: dump region owners/parents", + "-o: dump region owners/parents;" + "-D: dump disabled regions", .cmd = hmp_info_mtree, }, @@ -880,4 +881,15 @@ SRST Show SEV information. ERST + { + .name = "replay", + .args_type = "", + .params = "", + .help = "show record/replay information", + .cmd = hmp_info_replay, + }, +SRST + ``info replay`` + Display the record/replay information: mode and the current icount. +ERST diff --git a/hmp-commands.hx b/hmp-commands.hx index 7f0f3974ad908fb8e2bb965b3c85146330ab73f5..ff2d7aa8f3e39a179ee2b340ac01ec30af3a3b91 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -76,6 +76,7 @@ ERST .params = "device size", .help = "resize a block image", .cmd = hmp_block_resize, + .coroutine = true, }, SRST @@ -253,6 +254,7 @@ ERST .help = "save screen from head 'head' of display device 'device' " "into PPM image 'filename'", .cmd = hmp_screendump, + .coroutine = true, }, SRST @@ -1267,7 +1269,7 @@ ERST }, SRST ``drive_backup`` - Start a point-in-time copy of a block device to a specificed target. + Start a point-in-time copy of a block device to a specified target. ERST { @@ -1761,21 +1763,6 @@ SRST Executes a qemu-io command on the given block device. ERST - { - .name = "cpu-add", - .args_type = "id:i", - .params = "id", - .help = "add cpu (deprecated, use device_add instead)", - .cmd = hmp_cpu_add, - }, - -SRST -``cpu-add`` *id* - Add CPU with id *id*. This command is deprecated, please - +use ``device_add`` instead. For details, refer to - 'docs/cpu-hotplug.rst'. -ERST - { .name = "qom-list", .args_type = "path:s?", @@ -1790,11 +1777,26 @@ SRST Print QOM properties of object at location *path* ERST + { + .name = "qom-get", + .args_type = "path:s,property:s", + .params = "path property", + .help = "print QOM property", + .cmd = hmp_qom_get, + .flags = "p", + }, + +SRST +``qom-get`` *path* *property* + Print QOM property *property* of object at location *path* +ERST + { .name = "qom-set", - .args_type = "path:s,property:s,value:s", - .params = "path property value", - .help = "set QOM property", + .args_type = "json:-j,path:s,property:s,value:S", + .params = "[-j] path property value", + .help = "set QOM property.\n\t\t\t" + "-j: the value is specified in json format.", .cmd = hmp_qom_set, .flags = "p", }, @@ -1804,6 +1806,56 @@ SRST Set QOM property *property* of object at location *path* to value *value* ERST + { + .name = "replay_break", + .args_type = "icount:i", + .params = "icount", + .help = "set breakpoint at the specified instruction count", + .cmd = hmp_replay_break, + }, + +SRST +``replay_break`` *icount* + Set replay breakpoint at instruction count *icount*. + Execution stops when the specified instruction is reached. + There can be at most one breakpoint. When breakpoint is set, any prior + one is removed. The breakpoint may be set only in replay mode and only + "in the future", i.e. at instruction counts greater than the current one. + The current instruction count can be observed with ``info replay``. +ERST + + { + .name = "replay_delete_break", + .args_type = "", + .params = "", + .help = "remove replay breakpoint", + .cmd = hmp_replay_delete_break, + }, + +SRST +``replay_delete_break`` + Remove replay breakpoint which was previously set with ``replay_break``. + The command is ignored when there are no replay breakpoints. +ERST + + { + .name = "replay_seek", + .args_type = "icount:i", + .params = "icount", + .help = "replay execution to the specified instruction count", + .cmd = hmp_replay_seek, + }, + +SRST +``replay_seek`` *icount* + Automatically proceed to the instruction count *icount*, when + replaying the execution. The command automatically loads nearest + snapshot and replays the execution to find the desired instruction. + When there is no preceding snapshot or the execution is not replayed, + then the command fails. + *icount* for the reference may be observed with ``info replay`` command. +ERST + { .name = "info", .args_type = "item:s?", diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c index 54e012e5b442c7b0e7027d0ccf6f2c09057534d5..af52c1daac8523105dd43184efd48c8f9842fbb0 100644 --- a/hw/9pfs/9p-local.c +++ b/hw/9pfs/9p-local.c @@ -162,13 +162,13 @@ static void local_mapped_file_attr(int dirfd, const char *name, memset(buf, 0, ATTR_MAX); while (fgets(buf, ATTR_MAX, fp)) { if (!strncmp(buf, "virtfs.uid", 10)) { - stbuf->st_uid = atoi(buf+11); + stbuf->st_uid = atoi(buf + 11); } else if (!strncmp(buf, "virtfs.gid", 10)) { - stbuf->st_gid = atoi(buf+11); + stbuf->st_gid = atoi(buf + 11); } else if (!strncmp(buf, "virtfs.mode", 11)) { - stbuf->st_mode = atoi(buf+12); + stbuf->st_mode = atoi(buf + 12); } else if (!strncmp(buf, "virtfs.rdev", 11)) { - stbuf->st_rdev = atoi(buf+12); + stbuf->st_rdev = atoi(buf + 12); } memset(buf, 0, ATTR_MAX); } @@ -823,7 +823,7 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, if (fd == -1) { goto out; } - credp->fc_mode = credp->fc_mode|S_IFREG; + credp->fc_mode = credp->fc_mode | S_IFREG; if (fs_ctx->export_flags & V9FS_SM_MAPPED) { /* Set cleint credentials in xattr */ err = local_set_xattrat(dirfd, name, credp); @@ -1479,10 +1479,10 @@ static void error_append_security_model_hint(Error *const *errp) static int local_parse_opts(QemuOpts *opts, FsDriverEntry *fse, Error **errp) { + ERRP_GUARD(); const char *sec_model = qemu_opt_get(opts, "security_model"); const char *path = qemu_opt_get(opts, "path"); const char *multidevs = qemu_opt_get(opts, "multidevs"); - Error *local_err = NULL; if (!sec_model) { error_setg(errp, "security_model property not set"); @@ -1516,11 +1516,10 @@ static int local_parse_opts(QemuOpts *opts, FsDriverEntry *fse, Error **errp) fse->export_flags &= ~V9FS_FORBID_MULTIDEVS; fse->export_flags &= ~V9FS_REMAP_INODES; } else { - error_setg(&local_err, "invalid multidevs property '%s'", + error_setg(errp, "invalid multidevs property '%s'", multidevs); - error_append_hint(&local_err, "Valid options are: multidevs=" + error_append_hint(errp, "Valid options are: multidevs=" "[remap|forbid|warn]\n"); - error_propagate(errp, local_err); return -1; } } @@ -1530,9 +1529,8 @@ static int local_parse_opts(QemuOpts *opts, FsDriverEntry *fse, Error **errp) return -1; } - if (fsdev_throttle_parse_opts(opts, &fse->fst, &local_err)) { - error_propagate_prepend(errp, local_err, - "invalid throttle configuration: "); + if (fsdev_throttle_parse_opts(opts, &fse->fst, errp)) { + error_prepend(errp, "invalid throttle configuration: "); return -1; } diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 45a788f6e67566fbb5f32887c564d1b4b3c5960e..94df440fc74004bfa45b3fe305405434de551f92 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -314,8 +314,8 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid) f->next = s->fid_list; s->fid_list = f; - v9fs_readdir_init(&f->fs.dir); - v9fs_readdir_init(&f->fs_reclaim.dir); + v9fs_readdir_init(s->proto_version, &f->fs.dir); + v9fs_readdir_init(s->proto_version, &f->fs_reclaim.dir); return f; } @@ -972,30 +972,6 @@ static int coroutine_fn fid_to_qid(V9fsPDU *pdu, V9fsFidState *fidp, return 0; } -static int coroutine_fn dirent_to_qid(V9fsPDU *pdu, V9fsFidState *fidp, - struct dirent *dent, V9fsQID *qidp) -{ - struct stat stbuf; - V9fsPath path; - int err; - - v9fs_path_init(&path); - - err = v9fs_co_name_to_path(pdu, &fidp->path, dent->d_name, &path); - if (err < 0) { - goto out; - } - err = v9fs_co_lstat(pdu, &path, &stbuf); - if (err < 0) { - goto out; - } - err = stat_to_qid(pdu, &stbuf, qidp); - -out: - v9fs_path_free(&path); - return err; -} - V9fsPDU *pdu_alloc(V9fsState *s) { V9fsPDU *pdu = NULL; @@ -1115,7 +1091,7 @@ static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension) } } - if (!(ret&~0777)) { + if (!(ret & ~0777)) { ret |= S_IFREG; } @@ -1377,6 +1353,15 @@ static void coroutine_fn v9fs_version(void *opaque) goto out; } + /* 8192 is the default msize of Linux clients */ + if (s->msize <= 8192 && !(s->ctx.export_flags & V9FS_NO_PERF_WARN)) { + warn_report_once( + "9p: degraded performance: a reasonable high msize should be " + "chosen on client/guest side (chosen msize is <= 8192). See " + "https://wiki.qemu.org/Documentation/9psetup#msize for details." + ); + } + marshal: err = pdu_marshal(pdu, offset, "ds", s->msize, &version); if (err < 0) { @@ -1399,7 +1384,6 @@ static void coroutine_fn v9fs_attach(void *opaque) size_t offset = 7; V9fsQID qid; ssize_t err; - Error *local_err = NULL; v9fs_string_init(&uname); v9fs_string_init(&aname); @@ -1437,9 +1421,8 @@ static void coroutine_fn v9fs_attach(void *opaque) error_setg(&s->migration_blocker, "Migration is disabled when VirtFS export path '%s' is mounted in the guest using mount_tag '%s'", s->ctx.fs_root ? s->ctx.fs_root : "NULL", s->tag); - err = migrate_add_blocker(s->migration_blocker, &local_err); - if (local_err) { - error_free(local_err); + err = migrate_add_blocker(s->migration_blocker, NULL); + if (err < 0) { error_free(s->migration_blocker); s->migration_blocker = NULL; clunk_fid(s, fid); @@ -2254,7 +2237,14 @@ static void coroutine_fn v9fs_read(void *opaque) goto out_nofid; } if (fidp->fid_type == P9_FID_DIR) { - + if (s->proto_version != V9FS_PROTO_2000U) { + warn_report_once( + "9p: bad client: T_read request on directory only expected " + "with 9P2000.u protocol version" + ); + err = -EOPNOTSUPP; + goto out; + } if (off == 0) { v9fs_co_rewinddir(pdu, fidp); } @@ -2315,7 +2305,13 @@ out_nofid: pdu_complete(pdu, err); } -static size_t v9fs_readdir_data_size(V9fsString *name) +/** + * Returns size required in Rreaddir response for the passed dirent @p name. + * + * @param name - directory entry's name (i.e. file name, directory name) + * @returns required size in bytes + */ +size_t v9fs_readdir_response_size(V9fsString *name) { /* * Size of each dirent on the wire: size of qid (13) + size of offset (8) @@ -2324,62 +2320,74 @@ static size_t v9fs_readdir_data_size(V9fsString *name) return 24 + v9fs_string_size(name); } +static void v9fs_free_dirents(struct V9fsDirEnt *e) +{ + struct V9fsDirEnt *next = NULL; + + for (; e; e = next) { + next = e->next; + g_free(e->dent); + g_free(e->st); + g_free(e); + } +} + static int coroutine_fn v9fs_do_readdir(V9fsPDU *pdu, V9fsFidState *fidp, - int32_t max_count) + off_t offset, int32_t max_count) { size_t size; V9fsQID qid; V9fsString name; int len, err = 0; int32_t count = 0; - off_t saved_dir_pos; struct dirent *dent; + struct stat *st; + struct V9fsDirEnt *entries = NULL; - /* save the directory position */ - saved_dir_pos = v9fs_co_telldir(pdu, fidp); - if (saved_dir_pos < 0) { - return saved_dir_pos; - } - - while (1) { - v9fs_readdir_lock(&fidp->fs.dir); + /* + * inode remapping requires the device id, which in turn might be + * different for different directory entries, so if inode remapping is + * enabled we have to make a full stat for each directory entry + */ + const bool dostat = pdu->s->ctx.export_flags & V9FS_REMAP_INODES; - err = v9fs_co_readdir(pdu, fidp, &dent); - if (err || !dent) { - break; - } - v9fs_string_init(&name); - v9fs_string_sprintf(&name, "%s", dent->d_name); - if ((count + v9fs_readdir_data_size(&name)) > max_count) { - v9fs_readdir_unlock(&fidp->fs.dir); + /* + * Fetch all required directory entries altogether on a background IO + * thread from fs driver. We don't want to do that for each entry + * individually, because hopping between threads (this main IO thread + * and background IO driver thread) would sum up to huge latencies. + */ + count = v9fs_co_readdir_many(pdu, fidp, &entries, offset, max_count, + dostat); + if (count < 0) { + err = count; + count = 0; + goto out; + } + count = 0; - /* Ran out of buffer. Set dir back to old position and return */ - v9fs_co_seekdir(pdu, fidp, saved_dir_pos); - v9fs_string_free(&name); - return count; - } + for (struct V9fsDirEnt *e = entries; e; e = e->next) { + dent = e->dent; if (pdu->s->ctx.export_flags & V9FS_REMAP_INODES) { - /* - * dirent_to_qid() implies expensive stat call for each entry, - * we must do that here though since inode remapping requires - * the device id, which in turn might be different for - * different entries; we cannot make any assumption to avoid - * that here. - */ - err = dirent_to_qid(pdu, fidp, dent, &qid); + st = e->st; + /* e->st should never be NULL, but just to be sure */ + if (!st) { + err = -1; + break; + } + + /* remap inode */ + err = stat_to_qid(pdu, st, &qid); if (err < 0) { - v9fs_readdir_unlock(&fidp->fs.dir); - v9fs_co_seekdir(pdu, fidp, saved_dir_pos); - v9fs_string_free(&name); - return err; + break; } } else { /* * Fill up just the path field of qid because the client uses * only that. To fill the entire qid structure we will have * to stat each dirent found, which is expensive. For the - * latter reason we don't call dirent_to_qid() here. Only drawback + * latter reason we don't call stat_to_qid() here. Only drawback * is that no multi-device export detection of stat_to_qid() * would be done and provided as error to the user here. But * user would get that error anyway when accessing those @@ -2392,25 +2400,26 @@ static int coroutine_fn v9fs_do_readdir(V9fsPDU *pdu, V9fsFidState *fidp, qid.version = 0; } + v9fs_string_init(&name); + v9fs_string_sprintf(&name, "%s", dent->d_name); + /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */ len = pdu_marshal(pdu, 11 + count, "Qqbs", &qid, dent->d_off, dent->d_type, &name); - v9fs_readdir_unlock(&fidp->fs.dir); + v9fs_string_free(&name); if (len < 0) { - v9fs_co_seekdir(pdu, fidp, saved_dir_pos); - v9fs_string_free(&name); - return len; + err = len; + break; } + count += len; - v9fs_string_free(&name); - saved_dir_pos = dent->d_off; } - v9fs_readdir_unlock(&fidp->fs.dir); - +out: + v9fs_free_dirents(entries); if (err < 0) { return err; } @@ -2453,12 +2462,15 @@ static void coroutine_fn v9fs_readdir(void *opaque) retval = -EINVAL; goto out; } - if (initial_offset == 0) { - v9fs_co_rewinddir(pdu, fidp); - } else { - v9fs_co_seekdir(pdu, fidp, initial_offset); + if (s->proto_version != V9FS_PROTO_2000L) { + warn_report_once( + "9p: bad client: T_readdir request only expected with 9P2000.L " + "protocol version" + ); + retval = -EOPNOTSUPP; + goto out; } - count = v9fs_do_readdir(pdu, fidp, max_count); + count = v9fs_do_readdir(pdu, fidp, (off_t) initial_offset, max_count); if (count < 0) { retval = count; goto out; @@ -2764,7 +2776,7 @@ static void coroutine_fn v9fs_create(void *opaque) v9fs_path_unlock(s); } else { err = v9fs_co_open2(pdu, fidp, &name, -1, - omode_to_uflags(mode)|O_CREAT, perm, &stbuf); + omode_to_uflags(mode) | O_CREAT, perm, &stbuf); if (err < 0) { goto out; } @@ -3416,7 +3428,7 @@ static int v9fs_fill_statfs(V9fsState *s, V9fsPDU *pdu, struct statfs *stbuf) * compute bsize factor based on host file system block size * and client msize */ - bsize_factor = (s->msize - P9_IOHDRSZ)/stbuf->f_bsize; + bsize_factor = (s->msize - P9_IOHDRSZ) / stbuf->f_bsize; if (!bsize_factor) { bsize_factor = 1; } @@ -3428,9 +3440,9 @@ static int v9fs_fill_statfs(V9fsState *s, V9fsPDU *pdu, struct statfs *stbuf) * adjust(divide) the number of blocks, free blocks and available * blocks by bsize factor */ - f_blocks = stbuf->f_blocks/bsize_factor; - f_bfree = stbuf->f_bfree/bsize_factor; - f_bavail = stbuf->f_bavail/bsize_factor; + f_blocks = stbuf->f_blocks / bsize_factor; + f_bfree = stbuf->f_bfree / bsize_factor; + f_bavail = stbuf->f_bavail / bsize_factor; f_files = stbuf->f_files; f_ffree = stbuf->f_ffree; fsid_val = (unsigned int) stbuf->f_fsid.__val[0] | @@ -4013,6 +4025,7 @@ void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr) int v9fs_device_realize_common(V9fsState *s, const V9fsTransport *t, Error **errp) { + ERRP_GUARD(); int i, len; struct stat stat; FsDriverEntry *fse; @@ -4172,6 +4185,6 @@ static void __attribute__((__constructor__)) v9fs_set_fd_limit(void) error_report("Failed to get the resource limit"); exit(1); } - open_fd_hw = rlim.rlim_cur - MIN(400, rlim.rlim_cur/3); - open_fd_rc = rlim.rlim_cur/2; + open_fd_hw = rlim.rlim_cur - MIN(400, rlim.rlim_cur / 3); + open_fd_rc = rlim.rlim_cur / 2; } diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h index ee2271663c508ee83cc59cc758146204e96ed7df..32df81f360ea7ba1d3f30ef530470a8d24725a3c 100644 --- a/hw/9pfs/9p.h +++ b/hw/9pfs/9p.h @@ -143,8 +143,7 @@ typedef struct { */ QEMU_BUILD_BUG_ON(sizeof(P9MsgHeader) != 7); -struct V9fsPDU -{ +struct V9fsPDU { uint32_t size; uint16_t tag; uint8_t id; @@ -197,24 +196,63 @@ typedef struct V9fsXattr typedef struct V9fsDir { DIR *stream; - CoMutex readdir_mutex; + P9ProtoVersion proto_version; + /* readdir mutex type used for 9P2000.u protocol variant */ + CoMutex readdir_mutex_u; + /* readdir mutex type used for 9P2000.L protocol variant */ + QemuMutex readdir_mutex_L; } V9fsDir; static inline void v9fs_readdir_lock(V9fsDir *dir) { - qemu_co_mutex_lock(&dir->readdir_mutex); + if (dir->proto_version == V9FS_PROTO_2000U) { + qemu_co_mutex_lock(&dir->readdir_mutex_u); + } else { + qemu_mutex_lock(&dir->readdir_mutex_L); + } } static inline void v9fs_readdir_unlock(V9fsDir *dir) { - qemu_co_mutex_unlock(&dir->readdir_mutex); + if (dir->proto_version == V9FS_PROTO_2000U) { + qemu_co_mutex_unlock(&dir->readdir_mutex_u); + } else { + qemu_mutex_unlock(&dir->readdir_mutex_L); + } } -static inline void v9fs_readdir_init(V9fsDir *dir) +static inline void v9fs_readdir_init(P9ProtoVersion proto_version, V9fsDir *dir) { - qemu_co_mutex_init(&dir->readdir_mutex); + dir->proto_version = proto_version; + if (proto_version == V9FS_PROTO_2000U) { + qemu_co_mutex_init(&dir->readdir_mutex_u); + } else { + qemu_mutex_init(&dir->readdir_mutex_L); + } } +/** + * Type for 9p fs drivers' (a.k.a. 9p backends) result of readdir requests, + * which is a chained list of directory entries. + */ +typedef struct V9fsDirEnt { + /* mandatory (must not be NULL) information for all readdir requests */ + struct dirent *dent; + /* + * optional (may be NULL): A full stat of each directory entry is just + * done if explicitly told to fs driver. + */ + struct stat *st; + /* + * instead of an array, directory entries are always returned as + * chained list, that's because the amount of entries retrieved by fs + * drivers is dependent on the individual entries' name (since response + * messages are size limited), so the final amount cannot be estimated + * before hand + */ + struct V9fsDirEnt *next; +} V9fsDirEnt; + /* * Filled by fs driver on open and other * calls. @@ -231,8 +269,7 @@ union V9fsFidOpenState { void *private; }; -struct V9fsFidState -{ +struct V9fsFidState { int fid_type; int32_t fid; V9fsPath path; @@ -299,8 +336,7 @@ typedef struct { uint64_t path; } QpfEntry; -struct V9fsState -{ +struct V9fsState { QLIST_HEAD(, V9fsPDU) free_list; QLIST_HEAD(, V9fsPDU) active_list; V9fsFidState *fid_list; @@ -419,6 +455,7 @@ void v9fs_path_init(V9fsPath *path); void v9fs_path_free(V9fsPath *path); void v9fs_path_sprintf(V9fsPath *path, const char *fmt, ...); void v9fs_path_copy(V9fsPath *dst, const V9fsPath *src); +size_t v9fs_readdir_response_size(V9fsString *name); int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath, const char *name, V9fsPath *path); int v9fs_device_realize_common(V9fsState *s, const V9fsTransport *t, diff --git a/hw/9pfs/Makefile.objs b/hw/9pfs/Makefile.objs deleted file mode 100644 index 70ded6fd8fbf4e490124e00321544a614674e8fb..0000000000000000000000000000000000000000 --- a/hw/9pfs/Makefile.objs +++ /dev/null @@ -1,9 +0,0 @@ -common-obj-y = 9p.o 9p-util.o -common-obj-y += 9p-local.o 9p-xattr.o -common-obj-y += 9p-xattr-user.o 9p-posix-acl.o -common-obj-y += coth.o cofs.o codir.o cofile.o -common-obj-y += coxattr.o 9p-synth.o -common-obj-y += 9p-proxy.o - -common-obj-$(CONFIG_XEN) += xen-9p-backend.o -obj-$(CONFIG_VIRTIO_9P) += virtio-9p-device.o diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c index 73f9a751e178341745143bc9d2f697f4102d87a3..1f70a58df5eff4f07a1962dbb9e647a6aa944bdf 100644 --- a/hw/9pfs/codir.c +++ b/hw/9pfs/codir.c @@ -18,28 +18,209 @@ #include "qemu/main-loop.h" #include "coth.h" +/* + * Intended to be called from bottom-half (e.g. background I/O thread) + * context. + */ +static int do_readdir(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent **dent) +{ + int err = 0; + V9fsState *s = pdu->s; + struct dirent *entry; + + errno = 0; + entry = s->ops->readdir(&s->ctx, &fidp->fs); + if (!entry && errno) { + *dent = NULL; + err = -errno; + } else { + *dent = entry; + } + return err; +} + +/* + * TODO: This will be removed for performance reasons. + * Use v9fs_co_readdir_many() instead. + */ int coroutine_fn v9fs_co_readdir(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent **dent) { int err; - V9fsState *s = pdu->s; if (v9fs_request_cancelled(pdu)) { return -EINTR; } - v9fs_co_run_in_worker( - { - struct dirent *entry; + v9fs_co_run_in_worker({ + err = do_readdir(pdu, fidp, dent); + }); + return err; +} + +/* + * This is solely executed on a background IO thread. + * + * See v9fs_co_readdir_many() (as its only user) below for details. + */ +static int do_readdir_many(V9fsPDU *pdu, V9fsFidState *fidp, + struct V9fsDirEnt **entries, off_t offset, + int32_t maxsize, bool dostat) +{ + V9fsState *s = pdu->s; + V9fsString name; + int len, err = 0; + int32_t size = 0; + off_t saved_dir_pos; + struct dirent *dent; + struct V9fsDirEnt *e = NULL; + V9fsPath path; + struct stat stbuf; + + *entries = NULL; + v9fs_path_init(&path); + + /* + * TODO: Here should be a warn_report_once() if lock failed. + * + * With a good 9p client we should not get into concurrency here, + * because a good client would not use the same fid for concurrent + * requests. We do the lock here for safety reasons though. However + * the client would then suffer performance issues, so better log that + * issue here. + */ + v9fs_readdir_lock(&fidp->fs.dir); + + /* seek directory to requested initial position */ + if (offset == 0) { + s->ops->rewinddir(&s->ctx, &fidp->fs); + } else { + s->ops->seekdir(&s->ctx, &fidp->fs, offset); + } + + /* save the directory position */ + saved_dir_pos = s->ops->telldir(&s->ctx, &fidp->fs); + if (saved_dir_pos < 0) { + err = saved_dir_pos; + goto out; + } + + while (true) { + /* interrupt loop if request was cancelled by a Tflush request */ + if (v9fs_request_cancelled(pdu)) { + err = -EINTR; + break; + } + + /* get directory entry from fs driver */ + err = do_readdir(pdu, fidp, &dent); + if (err || !dent) { + break; + } + + /* + * stop this loop as soon as it would exceed the allowed maximum + * response message size for the directory entries collected so far, + * because anything beyond that size would need to be discarded by + * 9p controller (main thread / top half) anyway + */ + v9fs_string_init(&name); + v9fs_string_sprintf(&name, "%s", dent->d_name); + len = v9fs_readdir_response_size(&name); + v9fs_string_free(&name); + if (size + len > maxsize) { + /* this is not an error case actually */ + break; + } + + /* append next node to result chain */ + if (!e) { + *entries = e = g_malloc0(sizeof(V9fsDirEnt)); + } else { + e = e->next = g_malloc0(sizeof(V9fsDirEnt)); + } + e->dent = g_malloc0(sizeof(struct dirent)); + memcpy(e->dent, dent, sizeof(struct dirent)); - errno = 0; - entry = s->ops->readdir(&s->ctx, &fidp->fs); - if (!entry && errno) { + /* perform a full stat() for directory entry if requested by caller */ + if (dostat) { + err = s->ops->name_to_path( + &s->ctx, &fidp->path, dent->d_name, &path + ); + if (err < 0) { err = -errno; - } else { - *dent = entry; - err = 0; + break; } - }); + + err = s->ops->lstat(&s->ctx, &path, &stbuf); + if (err < 0) { + err = -errno; + break; + } + + e->st = g_malloc0(sizeof(struct stat)); + memcpy(e->st, &stbuf, sizeof(struct stat)); + } + + size += len; + saved_dir_pos = dent->d_off; + } + + /* restore (last) saved position */ + s->ops->seekdir(&s->ctx, &fidp->fs, saved_dir_pos); + +out: + v9fs_readdir_unlock(&fidp->fs.dir); + v9fs_path_free(&path); + if (err < 0) { + return err; + } + return size; +} + +/** + * @brief Reads multiple directory entries in one rush. + * + * Retrieves the requested (max. amount of) directory entries from the fs + * driver. This function must only be called by the main IO thread (top half). + * Internally this function call will be dispatched to a background IO thread + * (bottom half) where it is eventually executed by the fs driver. + * + * @discussion Acquiring multiple directory entries in one rush from the fs + * driver, instead of retrieving each directory entry individually, is very + * beneficial from performance point of view. Because for every fs driver + * request latency is added, which in practice could lead to overall + * latencies of several hundred ms for reading all entries (of just a single + * directory) if every directory entry was individually requested from fs + * driver. + * + * @note You must @b ALWAYS call @c v9fs_free_dirents(entries) after calling + * v9fs_co_readdir_many(), both on success and on error cases of this + * function, to avoid memory leaks once @p entries are no longer needed. + * + * @param pdu - the causing 9p (T_readdir) client request + * @param fidp - already opened directory where readdir shall be performed on + * @param entries - output for directory entries (must not be NULL) + * @param offset - initial position inside the directory the function shall + * seek to before retrieving the directory entries + * @param maxsize - maximum result message body size (in bytes) + * @param dostat - whether a stat() should be performed and returned for + * each directory entry + * @returns resulting response message body size (in bytes) on success, + * negative error code otherwise + */ +int coroutine_fn v9fs_co_readdir_many(V9fsPDU *pdu, V9fsFidState *fidp, + struct V9fsDirEnt **entries, + off_t offset, int32_t maxsize, + bool dostat) +{ + int err = 0; + + if (v9fs_request_cancelled(pdu)) { + return -EINTR; + } + v9fs_co_run_in_worker({ + err = do_readdir_many(pdu, fidp, entries, offset, maxsize, dostat); + }); return err; } diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c index 55991916ec2a61ff69093d5205db3c86f000a741..0b321b456e3eb21a7b620d74233173230cb15ec3 100644 --- a/hw/9pfs/cofs.c +++ b/hw/9pfs/cofs.c @@ -23,7 +23,7 @@ static ssize_t __readlink(V9fsState *s, V9fsPath *path, V9fsString *buf) ssize_t len, maxlen = PATH_MAX; buf->data = g_malloc(PATH_MAX); - for(;;) { + for (;;) { len = s->ops->readlink(&s->ctx, path, buf->data, maxlen); if (len < 0) { g_free(buf->data); diff --git a/hw/9pfs/coth.h b/hw/9pfs/coth.h index c2cdc7a9eaac4aeb7d849d9086e9d97124dc98f5..c51289903d0df0ff65f9d3f2649bbe78b490fee9 100644 --- a/hw/9pfs/coth.h +++ b/hw/9pfs/coth.h @@ -19,7 +19,7 @@ #include "qemu/coroutine.h" #include "9p.h" -/* +/** * we want to use bottom half because we want to make sure the below * sequence of events. * @@ -28,6 +28,16 @@ * 3. Enter the coroutine in the worker thread. * we cannot swap step 1 and 2, because that would imply worker thread * can enter coroutine while step1 is still running + * + * @b PERFORMANCE @b CONSIDERATIONS: As a rule of thumb, keep in mind + * that hopping between threads adds @b latency! So when handling a + * 9pfs request, avoid calling v9fs_co_run_in_worker() too often, because + * this might otherwise sum up to a significant, huge overall latency for + * providing the response for just a single request. For that reason it + * is highly recommended to fetch all data from fs driver with a single + * fs driver request on a background I/O thread (bottom half) in one rush + * first and then eventually assembling the final response from that data + * on main I/O thread (top half). */ #define v9fs_co_run_in_worker(code_block) \ do { \ @@ -49,6 +59,9 @@ void co_run_in_worker_bh(void *); int coroutine_fn v9fs_co_readlink(V9fsPDU *, V9fsPath *, V9fsString *); int coroutine_fn v9fs_co_readdir(V9fsPDU *, V9fsFidState *, struct dirent **); +int coroutine_fn v9fs_co_readdir_many(V9fsPDU *, V9fsFidState *, + struct V9fsDirEnt **, off_t, int32_t, + bool); off_t coroutine_fn v9fs_co_telldir(V9fsPDU *, V9fsFidState *); void coroutine_fn v9fs_co_seekdir(V9fsPDU *, V9fsFidState *, off_t); void coroutine_fn v9fs_co_rewinddir(V9fsPDU *, V9fsFidState *); diff --git a/hw/9pfs/meson.build b/hw/9pfs/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..99be5d9119680315ce536f297747a2069c499e3e --- /dev/null +++ b/hw/9pfs/meson.build @@ -0,0 +1,20 @@ +fs_ss = ss.source_set() +fs_ss.add(files( + '9p-local.c', + '9p-posix-acl.c', + '9p-proxy.c', + '9p-synth.c', + '9p-util.c', + '9p-xattr-user.c', + '9p-xattr.c', + '9p.c', + 'codir.c', + 'cofile.c', + 'cofs.c', + 'coth.c', + 'coxattr.c', +)) +fs_ss.add(when: 'CONFIG_XEN', if_true: files('xen-9p-backend.c')) +softmmu_ss.add_all(when: 'CONFIG_FSDEV_9P', if_true: fs_ss) + +specific_ss.add(when: 'CONFIG_VIRTIO_9P', if_true: files('virtio-9p-device.c')) diff --git a/hw/9pfs/trace.h b/hw/9pfs/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..6104fe2a77ba5cddf6b8584d0d544bb9e46a6ac6 --- /dev/null +++ b/hw/9pfs/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_9pfs.h" diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index 36f3aa9352f28cef3f84e9906c614ceb580017bf..14371a78efd8312a26a6f60cbba2f25ed9543a4d 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -21,6 +21,7 @@ #include "hw/virtio/virtio-access.h" #include "qemu/iov.h" #include "qemu/module.h" +#include "sysemu/qtest.h" static void virtio_9p_push_and_notify(V9fsPDU *pdu) { @@ -199,6 +200,11 @@ static void virtio_9p_device_realize(DeviceState *dev, Error **errp) VirtIODevice *vdev = VIRTIO_DEVICE(dev); V9fsVirtioState *v = VIRTIO_9P(dev); V9fsState *s = &v->state; + FsDriverEntry *fse = get_fsdev_fsentry(s->fsconf.fsdev_id); + + if (qtest_enabled() && fse) { + fse->export_flags |= V9FS_NO_PERF_WARN; + } if (v9fs_device_realize_common(s, &virtio_9p_transport, errp)) { return; diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index e763da2c02bfa824be1f6f6a5b44b02afcfb28bc..20fa118f3a666bd01cb7fd4e5004a6bac23d1830 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -4,18 +4,17 @@ #include "standard-headers/linux/virtio_9p.h" #include "hw/virtio/virtio.h" #include "9p.h" +#include "qom/object.h" -typedef struct V9fsVirtioState -{ +struct V9fsVirtioState { VirtIODevice parent_obj; VirtQueue *vq; size_t config_size; VirtQueueElement *elems[MAX_REQ]; V9fsState state; -} V9fsVirtioState; +}; #define TYPE_VIRTIO_9P "virtio-9p-device" -#define VIRTIO_9P(obj) \ - OBJECT_CHECK(V9fsVirtioState, (obj), TYPE_VIRTIO_9P) +OBJECT_DECLARE_SIMPLE_TYPE(V9fsVirtioState, VIRTIO_9P) #endif diff --git a/hw/Kconfig b/hw/Kconfig index ecf491bf046d915e6beba03719a2c64f8e156357..4de1797ffdabc8d2adb5f3358b149470da1b6139 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -43,6 +43,7 @@ source watchdog/Kconfig # arch Kconfig source arm/Kconfig source alpha/Kconfig +source avr/Kconfig source cris/Kconfig source hppa/Kconfig source i386/Kconfig @@ -55,6 +56,7 @@ source nios2/Kconfig source openrisc/Kconfig source ppc/Kconfig source riscv/Kconfig +source rx/Kconfig source s390x/Kconfig source sh4/Kconfig source sparc/Kconfig diff --git a/hw/Makefile.objs b/hw/Makefile.objs deleted file mode 100644 index 660e2b43734817910a836a1279514554616cdc89..0000000000000000000000000000000000000000 --- a/hw/Makefile.objs +++ /dev/null @@ -1,46 +0,0 @@ -devices-dirs-y = core/ -ifeq ($(CONFIG_SOFTMMU), y) -devices-dirs-$(call lor,$(CONFIG_VIRTIO_9P),$(call land,$(CONFIG_VIRTFS),$(CONFIG_XEN))) += 9pfs/ -devices-dirs-y += acpi/ -devices-dirs-y += adc/ -devices-dirs-y += audio/ -devices-dirs-y += block/ -devices-dirs-y += char/ -devices-dirs-y += cpu/ -devices-dirs-y += display/ -devices-dirs-y += dma/ -devices-dirs-y += gpio/ -devices-dirs-$(CONFIG_HYPERV) += hyperv/ -devices-dirs-$(CONFIG_I2C) += i2c/ -devices-dirs-y += ide/ -devices-dirs-y += input/ -devices-dirs-y += intc/ -devices-dirs-$(CONFIG_IPACK) += ipack/ -devices-dirs-$(CONFIG_IPMI) += ipmi/ -devices-dirs-y += isa/ -devices-dirs-y += misc/ -devices-dirs-y += net/ -devices-dirs-y += rdma/ -devices-dirs-y += nvram/ -devices-dirs-y += pci/ -devices-dirs-$(CONFIG_PCI) += pci-bridge/ pci-host/ -devices-dirs-y += pcmcia/ -devices-dirs-y += rtc/ -devices-dirs-$(CONFIG_SCSI) += scsi/ -devices-dirs-y += sd/ -devices-dirs-y += ssi/ -devices-dirs-y += timer/ -devices-dirs-$(CONFIG_TPM) += tpm/ -devices-dirs-y += usb/ -devices-dirs-$(CONFIG_VFIO) += vfio/ -devices-dirs-y += virtio/ -devices-dirs-y += watchdog/ -devices-dirs-y += xen/ -devices-dirs-$(CONFIG_MEM_DEVICE) += mem/ -devices-dirs-$(CONFIG_NUBUS) += nubus/ -devices-dirs-y += semihosting/ -devices-dirs-y += smbios/ -endif - -common-obj-y += $(devices-dirs-y) -obj-y += $(devices-dirs-y) diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs deleted file mode 100644 index 72886c7965749eac110e8c1efb2f60480a128329..0000000000000000000000000000000000000000 --- a/hw/acpi/Makefile.objs +++ /dev/null @@ -1,26 +0,0 @@ -ifeq ($(CONFIG_ACPI),y) -common-obj-$(CONFIG_ACPI_X86) += core.o piix4.o pcihp.o -common-obj-$(CONFIG_ACPI_X86_ICH) += ich9.o tco.o -common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu_hotplug.o -common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o -common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o -common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o -common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o -common-obj-$(CONFIG_ACPI_HW_REDUCED) += generic_event_device.o -common-obj-$(CONFIG_ACPI_HMAT) += hmat.o -common-obj-$(CONFIG_ACPI_APEI) += ghes.o -common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o -common-obj-$(call lnot,$(CONFIG_PC)) += acpi-x86-stub.o - -common-obj-y += acpi_interface.o -common-obj-y += bios-linker-loader.o -common-obj-y += aml-build.o utils.o -common-obj-$(CONFIG_ACPI_PCI) += pci.o -common-obj-$(CONFIG_TPM) += tpm.o - -common-obj-$(CONFIG_IPMI) += ipmi.o -common-obj-$(call lnot,$(CONFIG_IPMI)) += ipmi-stub.o -else -common-obj-y += acpi-stub.o aml-build-stub.o -endif -common-obj-$(CONFIG_ALL) += acpi-stub.o aml-build-stub.o acpi-x86-stub.o ipmi-stub.o diff --git a/hw/acpi/aml-build-stub.c b/hw/acpi/aml-build-stub.c index 58b2e162277f54fc335c9d96bfcf5e337cfb7ff1..8d8ad1a314976368c2748e015ca9252eca021f5c 100644 --- a/hw/acpi/aml-build-stub.c +++ b/hw/acpi/aml-build-stub.c @@ -57,6 +57,20 @@ Aml *aml_irq_no_flags(uint8_t irq) return NULL; } +Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro, + AmlLevelAndEdge level_and_edge, + AmlActiveHighAndLow high_and_low, AmlShared shared, + uint32_t *irq_list, uint8_t irq_count) +{ + return NULL; +} + +Aml *aml_memory32_fixed(uint32_t addr, uint32_t size, + AmlReadAndWrite read_and_write) +{ + return NULL; +} + Aml *aml_int(const uint64_t val) { return NULL; diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index 3681ec6e3d88fd8a11617ba659e12e0f44229112..3792ba96ce05b789698df44f5b39c032adbd13fb 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -26,6 +26,7 @@ #include "qemu/bitops.h" #include "sysemu/numa.h" #include "hw/boards.h" +#include "hw/acpi/tpm.h" static GArray *build_alloc_array(void) { @@ -555,6 +556,15 @@ Aml *aml_or(Aml *arg1, Aml *arg2, Aml *dst) return build_opcode_2arg_dst(0x7D /* OrOp */, arg1, arg2, dst); } +/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLAnd */ +Aml *aml_land(Aml *arg1, Aml *arg2) +{ + Aml *var = aml_opcode(0x90 /* LAndOp */); + aml_append(var, arg1); + aml_append(var, arg2); + return var; +} + /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLOr */ Aml *aml_lor(Aml *arg1, Aml *arg2) { @@ -628,6 +638,13 @@ Aml *aml_notify(Aml *arg1, Aml *arg2) return var; } +/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefBreak */ +Aml *aml_break(void) +{ + Aml *var = aml_opcode(0xa5 /* BreakOp */); + return var; +} + /* helper to call method without argument */ Aml *aml_call0(const char *method) { @@ -1865,9 +1882,9 @@ void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f, } /* SLEEP_CONTROL_REG */ - build_append_gas(tbl, AML_AS_SYSTEM_MEMORY, 0 , 0, 0, 0); + build_append_gas_from_struct(tbl, &f->sleep_ctl); /* SLEEP_STATUS_REG */ - build_append_gas(tbl, AML_AS_SYSTEM_MEMORY, 0 , 0, 0, 0); + build_append_gas_from_struct(tbl, &f->sleep_sts); /* TODO: extra fields need to be added to support revisions above rev5 */ assert(f->rev == 5); @@ -1877,6 +1894,63 @@ build_hdr: "FACP", tbl->len - fadt_start, f->rev, oem_id, oem_table_id); } +/* + * build_tpm2 - Build the TPM2 table as specified in + * table 7: TCG Hardware Interface Description Table Format for TPM 2.0 + * of TCG ACPI Specification, Family “1.2” and “2.0”, Version 1.2, Rev 8 + */ +void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog) +{ + uint8_t start_method_params[12] = {}; + unsigned log_addr_offset, tpm2_start; + uint64_t control_area_start_address; + TPMIf *tpmif = tpm_find(); + uint32_t start_method; + void *tpm2_ptr; + + tpm2_start = table_data->len; + tpm2_ptr = acpi_data_push(table_data, sizeof(AcpiTableHeader)); + + /* Platform Class */ + build_append_int_noprefix(table_data, TPM2_ACPI_CLASS_CLIENT, 2); + /* Reserved */ + build_append_int_noprefix(table_data, 0, 2); + if (TPM_IS_TIS_ISA(tpmif) || TPM_IS_TIS_SYSBUS(tpmif)) { + control_area_start_address = 0; + start_method = TPM2_START_METHOD_MMIO; + } else if (TPM_IS_CRB(tpmif)) { + control_area_start_address = TPM_CRB_ADDR_CTRL; + start_method = TPM2_START_METHOD_CRB; + } else { + g_assert_not_reached(); + } + /* Address of Control Area */ + build_append_int_noprefix(table_data, control_area_start_address, 8); + /* Start Method */ + build_append_int_noprefix(table_data, start_method, 4); + + /* Platform Specific Parameters */ + g_array_append_vals(table_data, &start_method_params, + ARRAY_SIZE(start_method_params)); + + /* Log Area Minimum Length */ + build_append_int_noprefix(table_data, TPM_LOG_AREA_MINIMUM_SIZE, 4); + + acpi_data_push(tcpalog, TPM_LOG_AREA_MINIMUM_SIZE); + bios_linker_loader_alloc(linker, ACPI_BUILD_TPMLOG_FILE, tcpalog, 1, + false); + + log_addr_offset = table_data->len; + + /* Log Area Start Address to be filled by Guest linker */ + build_append_int_noprefix(table_data, 0, 8); + bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, + log_addr_offset, 8, + ACPI_BUILD_TPMLOG_FILE, 0); + build_header(linker, table_data, + tpm2_ptr, "TPM2", table_data->len - tpm2_start, 4, NULL, NULL); +} + /* ACPI 5.0: 6.4.3.8.2 Serial Bus Connection Descriptors */ static Aml *aml_serial_bus_device(uint8_t serial_bus_type, uint8_t flags, uint16_t type_flags, diff --git a/hw/acpi/core.c b/hw/acpi/core.c index 45cbed49abddecb61f57ff0c6dc384a7291c580b..7170bff6572cdc7a5f93fb595c951aeaeff122c3 100644 --- a/hw/acpi/core.c +++ b/hw/acpi/core.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -27,7 +27,7 @@ #include "qapi/error.h" #include "qapi/opts-visitor.h" #include "qapi/qapi-events-run-state.h" -#include "qapi/qapi-visit-misc.h" +#include "qapi/qapi-visit-acpi.h" #include "qemu/error-report.h" #include "qemu/module.h" #include "qemu/option.h" @@ -239,7 +239,6 @@ static void acpi_table_install(const char unsigned *blob, size_t bloblen, void acpi_table_add(const QemuOpts *opts, Error **errp) { AcpiTableOptions *hdrs = NULL; - Error *err = NULL; char **pathnames = NULL; char **cur; size_t bloblen = 0; @@ -249,21 +248,21 @@ void acpi_table_add(const QemuOpts *opts, Error **errp) Visitor *v; v = opts_visitor_new(opts); - visit_type_AcpiTableOptions(v, NULL, &hdrs, &err); + visit_type_AcpiTableOptions(v, NULL, &hdrs, errp); visit_free(v); } - if (err) { + if (!hdrs) { goto out; } if (hdrs->has_file == hdrs->has_data) { - error_setg(&err, "'-acpitable' requires one of 'data' or 'file'"); + error_setg(errp, "'-acpitable' requires one of 'data' or 'file'"); goto out; } pathnames = g_strsplit(hdrs->has_file ? hdrs->file : hdrs->data, ":", 0); if (pathnames == NULL || pathnames[0] == NULL) { - error_setg(&err, "'-acpitable' requires at least one pathname"); + error_setg(errp, "'-acpitable' requires at least one pathname"); goto out; } @@ -272,7 +271,7 @@ void acpi_table_add(const QemuOpts *opts, Error **errp) int fd = open(*cur, O_RDONLY | O_BINARY); if (fd < 0) { - error_setg(&err, "can't open file %s: %s", *cur, strerror(errno)); + error_setg(errp, "can't open file %s: %s", *cur, strerror(errno)); goto out; } @@ -288,8 +287,8 @@ void acpi_table_add(const QemuOpts *opts, Error **errp) memcpy(blob + bloblen, data, r); bloblen += r; } else if (errno != EINTR) { - error_setg(&err, "can't read file %s: %s", - *cur, strerror(errno)); + error_setg(errp, "can't read file %s: %s", *cur, + strerror(errno)); close(fd); goto out; } @@ -298,14 +297,12 @@ void acpi_table_add(const QemuOpts *opts, Error **errp) close(fd); } - acpi_table_install(blob, bloblen, hdrs->has_file, hdrs, &err); + acpi_table_install(blob, bloblen, hdrs->has_file, hdrs, errp); out: g_free(blob); g_strfreev(pathnames); qapi_free_AcpiTableOptions(hdrs); - - error_propagate(errp, err); } unsigned acpi_table_len(void *current) @@ -461,7 +458,8 @@ static void acpi_pm_evt_write(void *opaque, hwaddr addr, uint64_t val, static const MemoryRegionOps acpi_pm_evt_ops = { .read = acpi_pm_evt_read, .write = acpi_pm_evt_write, - .valid.min_access_size = 2, + .impl.min_access_size = 2, + .valid.min_access_size = 1, .valid.max_access_size = 2, .endianness = DEVICE_LITTLE_ENDIAN, }; @@ -530,7 +528,8 @@ static void acpi_pm_tmr_write(void *opaque, hwaddr addr, uint64_t val, static const MemoryRegionOps acpi_pm_tmr_ops = { .read = acpi_pm_tmr_read, .write = acpi_pm_tmr_write, - .valid.min_access_size = 4, + .impl.min_access_size = 4, + .valid.min_access_size = 1, .valid.max_access_size = 4, .endianness = DEVICE_LITTLE_ENDIAN, }; @@ -559,7 +558,7 @@ static void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val) if (val & ACPI_BITMASK_SLEEP_ENABLE) { /* change suspend type */ uint16_t sus_typ = (val >> 10) & 7; - switch(sus_typ) { + switch (sus_typ) { case 0: /* soft power off */ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); break; @@ -602,7 +601,8 @@ static void acpi_pm_cnt_write(void *opaque, hwaddr addr, uint64_t val, static const MemoryRegionOps acpi_pm_cnt_ops = { .read = acpi_pm_cnt_read, .write = acpi_pm_cnt_write, - .valid.min_access_size = 2, + .impl.min_access_size = 2, + .valid.min_access_size = 1, .valid.max_access_size = 2, .endianness = DEVICE_LITTLE_ENDIAN, }; diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c index 3d6a500fb7e56df4114b5d68c8f8fcceb1b790d1..f099b5092730cd4067e882062f3be33ef143a625 100644 --- a/hw/acpi/cpu.c +++ b/hw/acpi/cpu.c @@ -3,7 +3,7 @@ #include "migration/vmstate.h" #include "hw/acpi/cpu.h" #include "qapi/error.h" -#include "qapi/qapi-events-misc.h" +#include "qapi/qapi-events-acpi.h" #include "trace.h" #include "sysemu/numa.h" @@ -14,6 +14,8 @@ #define ACPI_CPU_CMD_DATA_OFFSET_RW 8 #define ACPI_CPU_CMD_DATA2_OFFSET_R 0 +#define OVMF_CPUHP_SMI_CMD 4 + enum { CPHP_GET_NEXT_CPU_WITH_EVENT_CMD = 0, CPHP_OST_EVENT_CMD = 1, @@ -321,6 +323,7 @@ const VMStateDescription vmstate_cpu_hotplug = { #define CPU_NOTIFY_METHOD "CTFY" #define CPU_EJECT_METHOD "CEJ0" #define CPU_OST_METHOD "COST" +#define CPU_ADDED_LIST "CNEW" #define CPU_ENABLED "CPEN" #define CPU_SELECTOR "CSEL" @@ -465,42 +468,150 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, method = aml_method(CPU_SCAN_METHOD, 0, AML_SERIALIZED); { + const uint8_t max_cpus_per_pass = 255; Aml *else_ctx; - Aml *while_ctx; + Aml *while_ctx, *while_ctx2; Aml *has_event = aml_local(0); Aml *dev_chk = aml_int(1); Aml *eject_req = aml_int(3); Aml *next_cpu_cmd = aml_int(CPHP_GET_NEXT_CPU_WITH_EVENT_CMD); + Aml *num_added_cpus = aml_local(1); + Aml *cpu_idx = aml_local(2); + Aml *uid = aml_local(3); + Aml *has_job = aml_local(4); + Aml *new_cpus = aml_name(CPU_ADDED_LIST); aml_append(method, aml_acquire(ctrl_lock, 0xFFFF)); - aml_append(method, aml_store(one, has_event)); - while_ctx = aml_while(aml_equal(has_event, one)); + + /* + * Windows versions newer than XP (including Windows 10/Windows + * Server 2019), do support* VarPackageOp but, it is cripled to hold + * the same elements number as old PackageOp. + * For compatibility with Windows XP (so it won't crash) use ACPI1.0 + * PackageOp which can hold max 255 elements. + * + * use named package as old Windows don't support it in local var + */ + aml_append(method, aml_name_decl(CPU_ADDED_LIST, + aml_package(max_cpus_per_pass))); + + aml_append(method, aml_store(zero, uid)); + aml_append(method, aml_store(one, has_job)); + /* + * CPU_ADDED_LIST can hold limited number of elements, outer loop + * allows to process CPUs in batches which let us to handle more + * CPUs than CPU_ADDED_LIST can hold. + */ + while_ctx2 = aml_while(aml_equal(has_job, one)); { - /* clear loop exit condition, ins_evt/rm_evt checks - * will set it to 1 while next_cpu_cmd returns a CPU - * with events */ - aml_append(while_ctx, aml_store(zero, has_event)); - aml_append(while_ctx, aml_store(next_cpu_cmd, cpu_cmd)); - ifctx = aml_if(aml_equal(ins_evt, one)); - { - aml_append(ifctx, - aml_call2(CPU_NOTIFY_METHOD, cpu_data, dev_chk)); - aml_append(ifctx, aml_store(one, ins_evt)); - aml_append(ifctx, aml_store(one, has_event)); - } - aml_append(while_ctx, ifctx); - else_ctx = aml_else(); - ifctx = aml_if(aml_equal(rm_evt, one)); - { - aml_append(ifctx, - aml_call2(CPU_NOTIFY_METHOD, cpu_data, eject_req)); - aml_append(ifctx, aml_store(one, rm_evt)); - aml_append(ifctx, aml_store(one, has_event)); - } - aml_append(else_ctx, ifctx); - aml_append(while_ctx, else_ctx); + aml_append(while_ctx2, aml_store(zero, has_job)); + + aml_append(while_ctx2, aml_store(one, has_event)); + aml_append(while_ctx2, aml_store(zero, num_added_cpus)); + + /* + * Scan CPUs, till there are CPUs with events or + * CPU_ADDED_LIST capacity is exhausted + */ + while_ctx = aml_while(aml_land(aml_equal(has_event, one), + aml_lless(uid, aml_int(arch_ids->len)))); + { + /* + * clear loop exit condition, ins_evt/rm_evt checks will + * set it to 1 while next_cpu_cmd returns a CPU with events + */ + aml_append(while_ctx, aml_store(zero, has_event)); + + aml_append(while_ctx, aml_store(uid, cpu_selector)); + aml_append(while_ctx, aml_store(next_cpu_cmd, cpu_cmd)); + + /* + * wrap around case, scan is complete, exit loop. + * It happens since events are not cleared in scan loop, + * so next_cpu_cmd continues to find already processed CPUs + */ + ifctx = aml_if(aml_lless(cpu_data, uid)); + { + aml_append(ifctx, aml_break()); + } + aml_append(while_ctx, ifctx); + + /* + * if CPU_ADDED_LIST is full, exit inner loop and process + * collected CPUs + */ + ifctx = aml_if( + aml_equal(num_added_cpus, aml_int(max_cpus_per_pass))); + { + aml_append(ifctx, aml_store(one, has_job)); + aml_append(ifctx, aml_break()); + } + aml_append(while_ctx, ifctx); + + aml_append(while_ctx, aml_store(cpu_data, uid)); + ifctx = aml_if(aml_equal(ins_evt, one)); + { + /* cache added CPUs to Notify/Wakeup later */ + aml_append(ifctx, aml_store(uid, + aml_index(new_cpus, num_added_cpus))); + aml_append(ifctx, aml_increment(num_added_cpus)); + aml_append(ifctx, aml_store(one, has_event)); + } + aml_append(while_ctx, ifctx); + else_ctx = aml_else(); + ifctx = aml_if(aml_equal(rm_evt, one)); + { + aml_append(ifctx, + aml_call2(CPU_NOTIFY_METHOD, uid, eject_req)); + aml_append(ifctx, aml_store(one, rm_evt)); + aml_append(ifctx, aml_store(one, has_event)); + } + aml_append(else_ctx, ifctx); + aml_append(while_ctx, else_ctx); + aml_append(while_ctx, aml_increment(uid)); + } + aml_append(while_ctx2, while_ctx); + + /* + * in case FW negotiated ICH9_LPC_SMI_F_CPU_HOTPLUG_BIT, + * make upcall to FW, so it can pull in new CPUs before + * OS is notified and wakes them up + */ + if (opts.smi_path) { + ifctx = aml_if(aml_lgreater(num_added_cpus, zero)); + { + aml_append(ifctx, aml_store(aml_int(OVMF_CPUHP_SMI_CMD), + aml_name("%s", opts.smi_path))); + } + aml_append(while_ctx2, ifctx); + } + + /* Notify OSPM about new CPUs and clear insert events */ + aml_append(while_ctx2, aml_store(zero, cpu_idx)); + while_ctx = aml_while(aml_lless(cpu_idx, num_added_cpus)); + { + aml_append(while_ctx, + aml_store(aml_derefof(aml_index(new_cpus, cpu_idx)), + uid)); + aml_append(while_ctx, + aml_call2(CPU_NOTIFY_METHOD, uid, dev_chk)); + aml_append(while_ctx, aml_store(uid, aml_debug())); + aml_append(while_ctx, aml_store(uid, cpu_selector)); + aml_append(while_ctx, aml_store(one, ins_evt)); + aml_append(while_ctx, aml_increment(cpu_idx)); + } + aml_append(while_ctx2, while_ctx); + /* + * If another batch is needed, then it will resume scanning + * exactly at -- and not after -- the last CPU that's currently + * in CPU_ADDED_LIST. In other words, the last CPU in + * CPU_ADDED_LIST is going to be re-checked. That's OK: we've + * just cleared the insert event for *all* CPUs in + * CPU_ADDED_LIST, including the last one. So the scan will + * simply seek past it. + */ } - aml_append(method, while_ctx); + aml_append(method, while_ctx2); aml_append(method, aml_release(ctrl_lock)); } aml_append(cpus_dev, method); diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c index 3e687d227a65ddc207230b05985956ce172cfb84..53654f8638306bda80874a5e7d850f5c70f99c47 100644 --- a/hw/acpi/cpu_hotplug.c +++ b/hw/acpi/cpu_hotplug.c @@ -41,7 +41,7 @@ static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data, */ if (addr == 0 && data == 0) { AcpiCpuHotplug *cpus = opaque; - object_property_set_bool(cpus->device, false, "cpu-hotplug-legacy", + object_property_set_bool(cpus->device, "cpu-hotplug-legacy", false, &error_abort); } } @@ -63,7 +63,7 @@ static void acpi_set_cpu_present_bit(AcpiCpuHotplug *g, CPUState *cpu) cpu_id = k->get_arch_id(cpu); if ((cpu_id / 8) >= ACPI_GPE_PROC_LEN) { - object_property_set_bool(g->device, false, "cpu-hotplug-legacy", + object_property_set_bool(g->device, "cpu-hotplug-legacy", false, &error_abort); return; } diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c index b1cbdd86b66c4de4d5bdb245f3841fde9aeaac74..5454be67d5f09e0c69ba345368c82bf4a9f37aa5 100644 --- a/hw/acpi/generic_event_device.c +++ b/hw/acpi/generic_event_device.c @@ -20,6 +20,7 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "qemu/error-report.h" +#include "sysemu/runstate.h" static const uint32_t ged_supported_events[] = { ACPI_GED_MEM_HOTPLUG_EVT, @@ -141,8 +142,16 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, aml_append(table, dev); } +void acpi_dsdt_add_power_button(Aml *scope) +{ + Aml *dev = aml_device(ACPI_POWER_BUTTON_DEVICE); + aml_append(dev, aml_name_decl("_HID", aml_string("PNP0C0C"))); + aml_append(dev, aml_name_decl("_UID", aml_int(0))); + aml_append(scope, dev); +} + /* Memory read by the GED _EVT AML dynamic method */ -static uint64_t ged_read(void *opaque, hwaddr addr, unsigned size) +static uint64_t ged_evt_read(void *opaque, hwaddr addr, unsigned size) { uint64_t val = 0; GEDState *ged_st = opaque; @@ -161,14 +170,14 @@ static uint64_t ged_read(void *opaque, hwaddr addr, unsigned size) } /* Nothing is expected to be written to the GED memory region */ -static void ged_write(void *opaque, hwaddr addr, uint64_t data, - unsigned int size) +static void ged_evt_write(void *opaque, hwaddr addr, uint64_t data, + unsigned int size) { } -static const MemoryRegionOps ged_ops = { - .read = ged_read, - .write = ged_write, +static const MemoryRegionOps ged_evt_ops = { + .read = ged_evt_read, + .write = ged_evt_write, .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 4, @@ -176,6 +185,45 @@ static const MemoryRegionOps ged_ops = { }, }; +static uint64_t ged_regs_read(void *opaque, hwaddr addr, unsigned size) +{ + return 0; +} + +static void ged_regs_write(void *opaque, hwaddr addr, uint64_t data, + unsigned int size) +{ + bool slp_en; + int slp_typ; + + switch (addr) { + case ACPI_GED_REG_SLEEP_CTL: + slp_typ = (data >> 2) & 0x07; + slp_en = (data >> 5) & 0x01; + if (slp_en && slp_typ == 5) { + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + } + return; + case ACPI_GED_REG_SLEEP_STS: + return; + case ACPI_GED_REG_RESET: + if (data == ACPI_GED_RESET_VALUE) { + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + } + return; + } +} + +static const MemoryRegionOps ged_regs_ops = { + .read = ged_regs_read, + .write = ged_regs_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 1, + }, +}; + static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -193,6 +241,33 @@ static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev, } } +static void acpi_ged_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + AcpiGedState *s = ACPI_GED(hotplug_dev); + + if ((object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) && + !(object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)))) { + acpi_memory_unplug_request_cb(hotplug_dev, &s->memhp_state, dev, errp); + } else { + error_setg(errp, "acpi: device unplug request for unsupported device" + " type: %s", object_get_typename(OBJECT(dev))); + } +} + +static void acpi_ged_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + AcpiGedState *s = ACPI_GED(hotplug_dev); + + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + acpi_memory_unplug_cb(&s->memhp_state, dev, errp); + } else { + error_setg(errp, "acpi: device unplug for unsupported device" + " type: %s", object_get_typename(OBJECT(dev))); + } +} + static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) { AcpiGedState *s = ACPI_GED(adev); @@ -247,6 +322,16 @@ static const VMStateDescription vmstate_ged_state = { } }; +static const VMStateDescription vmstate_ghes = { + .name = "acpi-ghes", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT64(ghes_addr_le, AcpiGhesState), + VMSTATE_END_OF_LIST() + }, +}; + static bool ghes_needed(void *opaque) { AcpiGedState *s = opaque; @@ -260,7 +345,7 @@ static const VMStateDescription vmstate_ghes_state = { .needed = ghes_needed, .fields = (VMStateField[]) { VMSTATE_STRUCT(ghes_state, AcpiGedState, 1, - vmstate_ghes_state, AcpiGhesState), + vmstate_ghes, AcpiGhesState), VMSTATE_END_OF_LIST() } }; @@ -287,9 +372,9 @@ static void acpi_ged_initfn(Object *obj) SysBusDevice *sbd = SYS_BUS_DEVICE(obj); GEDState *ged_st = &s->ged_state; - memory_region_init_io(&ged_st->io, obj, &ged_ops, ged_st, + memory_region_init_io(&ged_st->evt, obj, &ged_evt_ops, ged_st, TYPE_ACPI_GED, ACPI_GED_EVT_SEL_LEN); - sysbus_init_mmio(sbd, &ged_st->io); + sysbus_init_mmio(sbd, &ged_st->evt); sysbus_init_irq(sbd, &s->irq); @@ -305,6 +390,10 @@ static void acpi_ged_initfn(Object *obj) sysbus_init_mmio(sbd, &s->container_memhp); acpi_memory_hotplug_init(&s->container_memhp, OBJECT(dev), &s->memhp_state, 0); + + memory_region_init_io(&ged_st->regs, obj, &ged_regs_ops, ged_st, + TYPE_ACPI_GED "-regs", ACPI_GED_REG_COUNT); + sysbus_init_mmio(sbd, &ged_st->regs); } static void acpi_ged_class_init(ObjectClass *class, void *data) @@ -318,6 +407,8 @@ static void acpi_ged_class_init(ObjectClass *class, void *data) dc->vmsd = &vmstate_acpi_ged; hc->plug = acpi_ged_device_plug_cb; + hc->unplug_request = acpi_ged_unplug_request_cb; + hc->unplug = acpi_ged_unplug_cb; adevc->send_event = acpi_ged_send_event; } diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c index b363bc331d0468092814667630bf0822f4b01c0d..f0ee9f51caa969921cbfc7dbcda26608f5dfd278 100644 --- a/hw/acpi/ghes.c +++ b/hw/acpi/ghes.c @@ -204,16 +204,12 @@ static int acpi_ghes_record_mem_error(uint64_t error_block_address, /* This is the length if adding a new generic error data entry*/ data_length = ACPI_GHES_DATA_LENGTH + ACPI_GHES_MEM_CPER_LENGTH; - /* - * Check whether it will run out of the preallocated memory if adding a new - * generic error data entry + * It should not run out of the preallocated memory if adding a new generic + * error data entry */ - if ((data_length + ACPI_GHES_GESB_SIZE) > ACPI_GHES_MAX_RAW_DATA_LENGTH) { - error_report("Not enough memory to record new CPER!!!"); - g_array_free(block, true); - return -1; - } + assert((data_length + ACPI_GHES_GESB_SIZE) <= + ACPI_GHES_MAX_RAW_DATA_LENGTH); /* Build the new generic error status block header */ acpi_ghes_generic_error_status(block, ACPI_GEBS_UNCORRECTABLE, diff --git a/hw/acpi/hmat.c b/hw/acpi/hmat.c index 7c24bb53719e497d5cc6cf3f262e1c187e0bca7f..37806f7a06488a57773762852de73dcd1178a14d 100644 --- a/hw/acpi/hmat.c +++ b/hw/acpi/hmat.c @@ -13,7 +13,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/acpi/hmat.h b/hw/acpi/hmat.h index 437dbc6872e82e4c1ae42a9ff16299465eec052f..e9031cac01e943cf90c9ae5ce48eb3df1145b3cf 100644 --- a/hw/acpi/hmat.h +++ b/hw/acpi/hmat.h @@ -13,7 +13,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c index 2d204babc6e71bd2953bc8399681fad7e72bb388..5ff4e01c36905fa86582291cc08dd48bc1bf464e 100644 --- a/hw/acpi/ich9.c +++ b/hw/acpi/ich9.c @@ -10,7 +10,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -201,7 +201,7 @@ static int vmstate_cpuhp_pre_load(void *opaque) { ICH9LPCPMRegs *s = opaque; Object *obj = OBJECT(s->gpe_cpu.device); - object_property_set_bool(obj, false, "cpu-hotplug-legacy", &error_abort); + object_property_set_bool(obj, "cpu-hotplug-legacy", false, &error_abort); return 0; } @@ -408,10 +408,20 @@ void ich9_pm_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev); if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) && - !lpc->pm.acpi_memory_hotplug.is_enabled) + !lpc->pm.acpi_memory_hotplug.is_enabled) { error_setg(errp, "memory hotplug is not enabled: %s.memory-hotplug-support " "is not set", object_get_typename(OBJECT(lpc))); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + uint64_t negotiated = lpc->smi_negotiated_features; + + if (negotiated & BIT_ULL(ICH9_LPC_SMI_F_BROADCAST_BIT) && + !(negotiated & BIT_ULL(ICH9_LPC_SMI_F_CPU_HOTPLUG_BIT))) { + error_setg(errp, "cpu hotplug with SMI wasn't enabled by firmware"); + error_append_hint(errp, "update machine type to newer than 5.1 " + "and firmware that suppors CPU hotplug with SMM"); + } + } } void ich9_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, @@ -450,6 +460,18 @@ void ich9_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU) && !lpc->pm.cpu_hotplug_legacy) { + uint64_t negotiated = lpc->smi_negotiated_features; + + if (negotiated & BIT_ULL(ICH9_LPC_SMI_F_BROADCAST_BIT) && + !(negotiated & BIT_ULL(ICH9_LPC_SMI_F_CPU_HOT_UNPLUG_BIT))) { + error_setg(errp, "cpu hot-unplug with SMI wasn't enabled " + "by firmware"); + error_append_hint(errp, "update machine type to a version having " + "x-smi-cpu-hotunplug=on and firmware that " + "supports CPU hot-unplug with SMM"); + return; + } + acpi_cpu_unplug_request_cb(hotplug_dev, &lpc->pm.cpuhp_state, dev, errp); } else { diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c index 8d2e82240fff18f0013163d4f18f8a6720d7131b..f2552b2a46242e46b3157f0dede9ac34af63b9c3 100644 --- a/hw/acpi/memory_hotplug.c +++ b/hw/acpi/memory_hotplug.c @@ -7,7 +7,8 @@ #include "migration/vmstate.h" #include "trace.h" #include "qapi/error.h" -#include "qapi/qapi-events-misc.h" +#include "qapi/qapi-events-acpi.h" +#include "qapi/qapi-events-machine.h" #define MEMORY_SLOTS_NUMBER "MDNR" #define MEMORY_HOTPLUG_IO_REGION "HPMR" diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..dd69577212ac3b20a13025e06d9aa49d20011d63 --- /dev/null +++ b/hw/acpi/meson.build @@ -0,0 +1,25 @@ +acpi_ss = ss.source_set() +acpi_ss.add(files( + 'acpi_interface.c', + 'aml-build.c', + 'bios-linker-loader.c', + 'utils.c', +)) +acpi_ss.add(when: 'CONFIG_ACPI_CPU_HOTPLUG', if_true: files('cpu.c')) +acpi_ss.add(when: 'CONFIG_ACPI_CPU_HOTPLUG', if_true: files('cpu_hotplug.c')) +acpi_ss.add(when: 'CONFIG_ACPI_MEMORY_HOTPLUG', if_true: files('memory_hotplug.c')) +acpi_ss.add(when: 'CONFIG_ACPI_NVDIMM', if_true: files('nvdimm.c')) +acpi_ss.add(when: 'CONFIG_ACPI_PCI', if_true: files('pci.c')) +acpi_ss.add(when: 'CONFIG_ACPI_VMGENID', if_true: files('vmgenid.c')) +acpi_ss.add(when: 'CONFIG_ACPI_HW_REDUCED', if_true: files('generic_event_device.c')) +acpi_ss.add(when: 'CONFIG_ACPI_HMAT', if_true: files('hmat.c')) +acpi_ss.add(when: 'CONFIG_ACPI_APEI', if_true: files('ghes.c')) +acpi_ss.add(when: 'CONFIG_ACPI_X86', if_true: files('core.c', 'piix4.c', 'pcihp.c'), if_false: files('acpi-stub.c')) +acpi_ss.add(when: 'CONFIG_ACPI_X86_ICH', if_true: files('ich9.c', 'tco.c')) +acpi_ss.add(when: 'CONFIG_IPMI', if_true: files('ipmi.c'), if_false: files('ipmi-stub.c')) +acpi_ss.add(when: 'CONFIG_PC', if_false: files('acpi-x86-stub.c')) +acpi_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c')) +softmmu_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c')) +softmmu_ss.add_all(when: 'CONFIG_ACPI', if_true: acpi_ss) +softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('acpi-stub.c', 'aml-build-stub.c', + 'acpi-x86-stub.c', 'ipmi-stub.c')) diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c index 9316d12b7026978285cd492ae40aa6b5c3a3e0f5..aa95b0cbafd97822511c271604561b10f7124b89 100644 --- a/hw/acpi/nvdimm.c +++ b/hw/acpi/nvdimm.c @@ -15,7 +15,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -28,6 +28,7 @@ #include "qemu/osdep.h" #include "qemu/uuid.h" +#include "qapi/error.h" #include "hw/acpi/acpi.h" #include "hw/acpi/aml-build.h" #include "hw/acpi/bios-linker-loader.h" @@ -555,7 +556,7 @@ static void nvdimm_dsm_func_read_fit(NVDIMMState *state, NvdimmDsmIn *in, fit = fit_buf->fit; - nvdimm_debug("Read FIT: offset %#x FIT size %#x Dirty %s.\n", + nvdimm_debug("Read FIT: offset 0x%x FIT size 0x%x Dirty %s.\n", read_fit->offset, fit->len, fit_buf->dirty ? "Yes" : "No"); if (read_fit->offset > fit->len) { @@ -663,7 +664,7 @@ static void nvdimm_dsm_label_size(NVDIMMDevice *nvdimm, hwaddr dsm_mem_addr) label_size = nvdimm->label_size; mxfer = nvdimm_get_max_xfer_label_size(); - nvdimm_debug("label_size %#x, max_xfer %#x.\n", label_size, mxfer); + nvdimm_debug("label_size 0x%x, max_xfer 0x%x.\n", label_size, mxfer); label_size_out.func_ret_status = cpu_to_le32(NVDIMM_DSM_RET_STATUS_SUCCESS); label_size_out.label_size = cpu_to_le32(label_size); @@ -679,19 +680,19 @@ static uint32_t nvdimm_rw_label_data_check(NVDIMMDevice *nvdimm, uint32_t ret = NVDIMM_DSM_RET_STATUS_INVALID; if (offset + length < offset) { - nvdimm_debug("offset %#x + length %#x is overflow.\n", offset, + nvdimm_debug("offset 0x%x + length 0x%x is overflow.\n", offset, length); return ret; } if (nvdimm->label_size < offset + length) { - nvdimm_debug("position %#x is beyond label data (len = %" PRIx64 ").\n", + nvdimm_debug("position 0x%x is beyond label data (len = %" PRIx64 ").\n", offset + length, nvdimm->label_size); return ret; } if (length > nvdimm_get_max_xfer_label_size()) { - nvdimm_debug("length (%#x) is larger than max_xfer (%#x).\n", + nvdimm_debug("length (0x%x) is larger than max_xfer (0x%x).\n", length, nvdimm_get_max_xfer_label_size()); return ret; } @@ -715,7 +716,7 @@ static void nvdimm_dsm_get_label_data(NVDIMMDevice *nvdimm, NvdimmDsmIn *in, get_label_data->offset = le32_to_cpu(get_label_data->offset); get_label_data->length = le32_to_cpu(get_label_data->length); - nvdimm_debug("Read Label Data: offset %#x length %#x.\n", + nvdimm_debug("Read Label Data: offset 0x%x length 0x%x.\n", get_label_data->offset, get_label_data->length); status = nvdimm_rw_label_data_check(nvdimm, get_label_data->offset, @@ -754,7 +755,7 @@ static void nvdimm_dsm_set_label_data(NVDIMMDevice *nvdimm, NvdimmDsmIn *in, set_label_data->offset = le32_to_cpu(set_label_data->offset); set_label_data->length = le32_to_cpu(set_label_data->length); - nvdimm_debug("Write Label Data: offset %#x length %#x.\n", + nvdimm_debug("Write Label Data: offset 0x%x length 0x%x.\n", set_label_data->offset, set_label_data->length); status = nvdimm_rw_label_data_check(nvdimm, set_label_data->offset, @@ -837,7 +838,7 @@ nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) NvdimmDsmIn *in; hwaddr dsm_mem_addr = val; - nvdimm_debug("dsm memory address %#" HWADDR_PRIx ".\n", dsm_mem_addr); + nvdimm_debug("dsm memory address 0x%" HWADDR_PRIx ".\n", dsm_mem_addr); /* * The DSM memory is mapped to guest address space so an evil guest @@ -851,11 +852,11 @@ nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) in->function = le32_to_cpu(in->function); in->handle = le32_to_cpu(in->handle); - nvdimm_debug("Revision %#x Handler %#x Function %#x.\n", in->revision, + nvdimm_debug("Revision 0x%x Handler 0x%x Function 0x%x.\n", in->revision, in->handle, in->function); if (in->revision != 0x1 /* Currently we only support DSM Spec Rev1. */) { - nvdimm_debug("Revision %#x is not supported, expect %#x.\n", + nvdimm_debug("Revision 0x%x is not supported, expect 0x%x.\n", in->revision, 0x1); nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_UNSUPPORT, dsm_mem_addr); goto exit; @@ -1334,6 +1335,28 @@ static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data, free_aml_allocator(); } +void nvdimm_build_srat(GArray *table_data) +{ + GSList *device_list = nvdimm_get_device_list(); + + for (; device_list; device_list = device_list->next) { + AcpiSratMemoryAffinity *numamem = NULL; + DeviceState *dev = device_list->data; + Object *obj = OBJECT(dev); + uint64_t addr, size; + int node; + + node = object_property_get_int(obj, PC_DIMM_NODE_PROP, &error_abort); + addr = object_property_get_uint(obj, PC_DIMM_ADDR_PROP, &error_abort); + size = object_property_get_uint(obj, PC_DIMM_SIZE_PROP, &error_abort); + + numamem = acpi_data_push(table_data, sizeof *numamem); + build_srat_memory(numamem, addr, size, node, + MEM_AFFINITY_ENABLED | MEM_AFFINITY_NON_VOLATILE); + } + g_slist_free(device_list); +} + void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data, BIOSLinker *linker, NVDIMMState *state, uint32_t ram_slots) diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c index d42906ea1942e3fbdea2ac0bb517ebfd8884d296..9dc4d3e2dbeda7660d1395bf9e9d5f14378690f4 100644 --- a/hw/acpi/pcihp.c +++ b/hw/acpi/pcihp.c @@ -10,7 +10,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -104,6 +104,24 @@ static void acpi_set_pci_info(void) } } +static void acpi_pcihp_disable_root_bus(void) +{ + static bool root_hp_disabled; + PCIBus *bus; + + if (root_hp_disabled) { + return; + } + + bus = find_i440fx(); + if (bus) { + /* setting the hotplug handler to NULL makes the bus non-hotpluggable */ + qbus_set_hotplug_handler(BUS(bus), NULL); + } + root_hp_disabled = true; + return; +} + static void acpi_pcihp_test_hotplug_bus(PCIBus *bus, void *opaque) { AcpiPciHpFind *find = opaque; @@ -129,6 +147,21 @@ static PCIBus *acpi_pcihp_find_hotplug_bus(AcpiPciHpState *s, int bsel) if (!bsel && !find.bus) { find.bus = s->root; } + + /* + * Check if find.bus is actually hotpluggable. If bsel is set to + * NULL for example on the root bus in order to make it + * non-hotpluggable, find.bus will match the root bus when bsel + * is 0. See acpi_pcihp_test_hotplug_bus() above. Since the + * bus is not hotpluggable however, we should not select the bus. + * Instead, we should set find.bus to NULL in that case. In the check + * below, we generalize this case for all buses, not just the root bus. + * The callers of this function check for a null return value and + * handle them appropriately. + */ + if (find.bus && !qbus_is_hotpluggable(BUS(find.bus))) { + find.bus = NULL; + } return find.bus; } @@ -209,8 +242,11 @@ static void acpi_pcihp_update(AcpiPciHpState *s) } } -void acpi_pcihp_reset(AcpiPciHpState *s) +void acpi_pcihp_reset(AcpiPciHpState *s, bool acpihp_root_off) { + if (acpihp_root_off) { + acpi_pcihp_disable_root_bus(); + } acpi_set_pci_info(); acpi_pcihp_update(s); } @@ -246,8 +282,7 @@ void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s, object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) { PCIBus *sec = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev)); - qbus_set_hotplug_handler(BUS(sec), OBJECT(hotplug_dev), - &error_abort); + qbus_set_hotplug_handler(BUS(sec), OBJECT(hotplug_dev)); /* We don't have to overwrite any other hotplug handler yet */ assert(QLIST_EMPTY(&sec->child)); } @@ -266,7 +301,7 @@ void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s, { trace_acpi_pci_unplug(PCI_SLOT(PCI_DEVICE(dev)->devfn), acpi_pcihp_get_bsel(pci_get_bus(PCI_DEVICE(dev)))); - object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + qdev_unrealize(dev); } void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev, @@ -365,7 +400,7 @@ void acpi_pcihp_init(Object *owner, AcpiPciHpState *s, PCIBus *root_bus, s->io_len = ACPI_PCIHP_SIZE; s->io_base = ACPI_PCIHP_ADDR; - s->root= root_bus; + s->root = root_bus; s->legacy_piix = !bridges_enabled; memory_region_init_io(&s->io, owner, &acpi_pcihp_io_ops, s, diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 85c199b30d8d98f7b9674c08e22e9fd42ec73b9b..669be5bbf61ecc9308bb4b25e2b8bc78d5360874 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -30,6 +30,7 @@ #include "hw/acpi/acpi.h" #include "sysemu/runstate.h" #include "sysemu/sysemu.h" +#include "sysemu/xen.h" #include "qapi/error.h" #include "qemu/range.h" #include "exec/address-spaces.h" @@ -41,10 +42,10 @@ #include "hw/mem/nvdimm.h" #include "hw/acpi/memory_hotplug.h" #include "hw/acpi/acpi_dev_interface.h" -#include "hw/xen/xen.h" #include "migration/vmstate.h" #include "hw/core/cpu.h" #include "trace.h" +#include "qom/object.h" #define GPE_BASE 0xafe0 #define GPE_LEN 4 @@ -54,7 +55,7 @@ struct pci_status { uint32_t down; }; -typedef struct PIIX4PMState { +struct PIIX4PMState { /*< private >*/ PCIDevice parent_obj; /*< public >*/ @@ -77,7 +78,8 @@ typedef struct PIIX4PMState { Notifier powerdown_notifier; AcpiPciHpState acpi_pci_hotplug; - bool use_acpi_pci_hotplug; + bool use_acpi_hotplug_bridge; + bool use_acpi_root_pci_hotplug; uint8_t disable_s3; uint8_t disable_s4; @@ -88,10 +90,9 @@ typedef struct PIIX4PMState { CPUHotplugState cpuhp_state; MemHotplugState acpi_memory_hotplug; -} PIIX4PMState; +}; -#define PIIX4_PM(obj) \ - OBJECT_CHECK(PIIX4PMState, (obj), TYPE_PIIX4_PM) +OBJECT_DECLARE_SIMPLE_TYPE(PIIX4PMState, PIIX4_PM) static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, PCIBus *bus, PIIX4PMState *s); @@ -204,16 +205,17 @@ static const VMStateDescription vmstate_pci_status = { } }; -static bool vmstate_test_use_acpi_pci_hotplug(void *opaque, int version_id) +static bool vmstate_test_use_acpi_hotplug_bridge(void *opaque, int version_id) { PIIX4PMState *s = opaque; - return s->use_acpi_pci_hotplug; + return s->use_acpi_hotplug_bridge; } -static bool vmstate_test_no_use_acpi_pci_hotplug(void *opaque, int version_id) +static bool vmstate_test_no_use_acpi_hotplug_bridge(void *opaque, + int version_id) { PIIX4PMState *s = opaque; - return !s->use_acpi_pci_hotplug; + return !s->use_acpi_hotplug_bridge; } static bool vmstate_test_use_memhp(void *opaque) @@ -243,7 +245,7 @@ static bool vmstate_test_use_cpuhp(void *opaque) static int vmstate_cpuhp_pre_load(void *opaque) { Object *obj = OBJECT(opaque); - object_property_set_bool(obj, false, "cpu-hotplug-legacy", &error_abort); + object_property_set_bool(obj, "cpu-hotplug-legacy", false, &error_abort); return 0; } @@ -290,11 +292,11 @@ static const VMStateDescription vmstate_acpi = { VMSTATE_STRUCT_TEST( acpi_pci_hotplug.acpi_pcihp_pci_status[ACPI_PCIHP_BSEL_DEFAULT], PIIX4PMState, - vmstate_test_no_use_acpi_pci_hotplug, + vmstate_test_no_use_acpi_hotplug_bridge, 2, vmstate_pci_status, struct AcpiPciHpPciStatus), VMSTATE_PCI_HOTPLUG(acpi_pci_hotplug, PIIX4PMState, - vmstate_test_use_acpi_pci_hotplug), + vmstate_test_use_acpi_hotplug_bridge), VMSTATE_END_OF_LIST() }, .subsections = (const VMStateDescription*[]) { @@ -323,7 +325,7 @@ static void piix4_pm_reset(DeviceState *dev) pci_conf[0x5B] = 0x02; } pm_io_space_update(s); - acpi_pcihp_reset(&s->acpi_pci_hotplug); + acpi_pcihp_reset(&s->acpi_pci_hotplug, !s->use_acpi_root_pci_hotplug); } static void piix4_pm_powerdown_req(Notifier *n, void *opaque) @@ -435,7 +437,7 @@ static void piix4_pm_machine_ready(Notifier *n, void *opaque) (memory_region_present(io_as, 0x2f8) ? 0x90 : 0); } -static void piix4_pm_add_propeties(PIIX4PMState *s) +static void piix4_pm_add_properties(PIIX4PMState *s) { static const uint8_t acpi_enable_cmd = ACPI_ENABLE; static const uint8_t acpi_disable_cmd = ACPI_DISABLE; @@ -505,19 +507,21 @@ static void piix4_pm_realize(PCIDevice *dev, Error **errp) piix4_acpi_system_hot_add_init(pci_address_space_io(dev), pci_get_bus(dev), s); - qbus_set_hotplug_handler(BUS(pci_get_bus(dev)), OBJECT(s), &error_abort); + qbus_set_hotplug_handler(BUS(pci_get_bus(dev)), OBJECT(s)); - piix4_pm_add_propeties(s); + piix4_pm_add_properties(s); } I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq, qemu_irq smi_irq, int smm_enabled, DeviceState **piix4_pm) { + PCIDevice *pci_dev; DeviceState *dev; PIIX4PMState *s; - dev = DEVICE(pci_create(bus, devfn, TYPE_PIIX4_PM)); + pci_dev = pci_new(devfn, TYPE_PIIX4_PM); + dev = DEVICE(pci_dev); qdev_prop_set_uint32(dev, "smb_io_base", smb_io_base); if (piix4_pm) { *piix4_pm = dev; @@ -528,10 +532,10 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, s->smi_irq = smi_irq; s->smm_enabled = smm_enabled; if (xen_enabled()) { - s->use_acpi_pci_hotplug = false; + s->use_acpi_hotplug_bridge = false; } - qdev_init_nofail(dev); + pci_realize_and_unref(pci_dev, bus, &error_fatal); return s->smb.smbus; } @@ -592,8 +596,10 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, "acpi-gpe0", GPE_LEN); memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe); - acpi_pcihp_init(OBJECT(s), &s->acpi_pci_hotplug, bus, parent, - s->use_acpi_pci_hotplug); + if (s->use_acpi_hotplug_bridge || s->use_acpi_root_pci_hotplug) { + acpi_pcihp_init(OBJECT(s), &s->acpi_pci_hotplug, bus, parent, + s->use_acpi_hotplug_bridge); + } s->cpu_hotplug_legacy = true; object_property_add_bool(OBJECT(s), "cpu-hotplug-legacy", @@ -631,7 +637,9 @@ static Property piix4_pm_properties[] = { DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, 0), DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2), DEFINE_PROP_BOOL("acpi-pci-hotplug-with-bridge-support", PIIX4PMState, - use_acpi_pci_hotplug, true), + use_acpi_hotplug_bridge, true), + DEFINE_PROP_BOOL("acpi-root-pci-hotplug", PIIX4PMState, + use_acpi_root_pci_hotplug, true), DEFINE_PROP_BOOL("memory-hotplug-support", PIIX4PMState, acpi_memory_hotplug.is_enabled, true), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/acpi/tco.c b/hw/acpi/tco.c index fb9052dbca2a0495bf1a72abcf198bee5fa1e83b..cf1e68a5393b732fcdf2c9e4e4ab7ee780ebc26e 100644 --- a/hw/acpi/tco.c +++ b/hw/acpi/tco.c @@ -15,17 +15,6 @@ #include "hw/acpi/tco.h" #include "trace.h" -//#define DEBUG - -#ifdef DEBUG -#define TCO_DEBUG(fmt, ...) \ - do { \ - fprintf(stderr, "%s "fmt, __func__, ## __VA_ARGS__); \ - } while (0) -#else -#define TCO_DEBUG(fmt, ...) do { } while (0) -#endif - enum { TCO_RLD_DEFAULT = 0x0000, TCO_DAT_IN_DEFAULT = 0x00, diff --git a/hw/acpi/trace.h b/hw/acpi/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..a7f7da7009d199103d5895d199947ddca2953a8b --- /dev/null +++ b/hw/acpi/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_acpi.h" diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c index 2df7623d74d96e1e33d6d36a33d05f42d775337c..2c8152d5088e5f7ec7a005bab65cc1772ae43965 100644 --- a/hw/acpi/vmgenid.c +++ b/hw/acpi/vmgenid.c @@ -12,7 +12,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "qapi/qapi-commands-misc.h" +#include "qapi/qapi-commands-machine.h" #include "qemu/module.h" #include "hw/acpi/acpi.h" #include "hw/acpi/aml-build.h" @@ -198,7 +198,7 @@ static void vmgenid_realize(DeviceState *dev, Error **errp) if (!bios_linker_loader_can_write_pointer()) { error_setg(errp, "%s requires DMA write support in fw_cfg, " - "which this machine type does not provide", VMGENID_DEVICE); + "which this machine type does not provide", TYPE_VMGENID); return; } @@ -206,7 +206,7 @@ static void vmgenid_realize(DeviceState *dev, Error **errp) * device. Check if there are several. */ if (!find_vmgenid_dev()) { - error_setg(errp, "at most one %s device is permitted", VMGENID_DEVICE); + error_setg(errp, "at most one %s device is permitted", TYPE_VMGENID); return; } @@ -232,7 +232,7 @@ static void vmgenid_device_class_init(ObjectClass *klass, void *data) } static const TypeInfo vmgenid_device_info = { - .name = VMGENID_DEVICE, + .name = TYPE_VMGENID, .parent = TYPE_DEVICE, .instance_size = sizeof(VmGenIdState), .class_init = vmgenid_device_class_init, diff --git a/hw/adc/Makefile.objs b/hw/adc/Makefile.objs deleted file mode 100644 index 2b9dc36c7f9427ecfcf0192118e9db520599751d..0000000000000000000000000000000000000000 --- a/hw/adc/Makefile.objs +++ /dev/null @@ -1 +0,0 @@ -common-obj-$(CONFIG_STM32F2XX_ADC) += stm32f2xx_adc.o diff --git a/hw/adc/meson.build b/hw/adc/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..0d62ae96ae93f5e45a275206538e6acf01121c35 --- /dev/null +++ b/hw/adc/meson.build @@ -0,0 +1 @@ +softmmu_ss.add(when: 'CONFIG_STM32F2XX_ADC', if_true: files('stm32f2xx_adc.c')) diff --git a/hw/adc/stm32f2xx_adc.c b/hw/adc/stm32f2xx_adc.c index 4f9d485ecf29786508dbca58e1427c3bc9e104e3..01a0b14e69d6c7de7112036ebc4143af582300e9 100644 --- a/hw/adc/stm32f2xx_adc.c +++ b/hw/adc/stm32f2xx_adc.c @@ -246,6 +246,8 @@ static const MemoryRegionOps stm32f2xx_adc_ops = { .read = stm32f2xx_adc_read, .write = stm32f2xx_adc_write, .endianness = DEVICE_NATIVE_ENDIAN, + .impl.min_access_size = 4, + .impl.max_access_size = 4, }; static const VMStateDescription vmstate_stm32f2xx_adc = { @@ -278,7 +280,7 @@ static void stm32f2xx_adc_init(Object *obj) sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); memory_region_init_io(&s->mmio, obj, &stm32f2xx_adc_ops, s, - TYPE_STM32F2XX_ADC, 0xFF); + TYPE_STM32F2XX_ADC, 0x100); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); } diff --git a/hw/alpha/Makefile.objs b/hw/alpha/Makefile.objs deleted file mode 100644 index 62fdf3edec90f95deb9d40a067a02694e318e75d..0000000000000000000000000000000000000000 --- a/hw/alpha/Makefile.objs +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_DP264) += dp264.o pci.o typhoon.o diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c index f7751b18f691327396a6c9c7305b0929b5dc8bd4..4d24518d1d9246bedb3496b112ce188f172244e9 100644 --- a/hw/alpha/dp264.c +++ b/hw/alpha/dp264.c @@ -62,8 +62,8 @@ static void clipper_init(MachineState *machine) qemu_irq rtc_irq; long size, i; char *palcode_filename; - uint64_t palcode_entry, palcode_low, palcode_high; - uint64_t kernel_entry, kernel_low, kernel_high; + uint64_t palcode_entry; + uint64_t kernel_entry, kernel_low; unsigned int smp_cpus = machine->smp.cpus; /* Create up to 4 cpus. */ @@ -113,7 +113,7 @@ static void clipper_init(MachineState *machine) exit(1); } size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys, - NULL, &palcode_entry, &palcode_low, &palcode_high, NULL, + NULL, &palcode_entry, NULL, NULL, NULL, 0, EM_ALPHA, 0, 0); if (size < 0) { error_report("could not load palcode '%s'", palcode_filename); @@ -132,7 +132,7 @@ static void clipper_init(MachineState *machine) uint64_t param_offset; size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys, - NULL, &kernel_entry, &kernel_low, &kernel_high, NULL, + NULL, &kernel_entry, &kernel_low, NULL, NULL, 0, EM_ALPHA, 0, 0); if (size < 0) { error_report("could not load kernel '%s'", kernel_filename); diff --git a/hw/alpha/meson.build b/hw/alpha/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..81ca2157772f748568a7a4ba8dc4f15756723723 --- /dev/null +++ b/hw/alpha/meson.build @@ -0,0 +1,8 @@ +alpha_ss = ss.source_set() +alpha_ss.add(when: 'CONFIG_DP264', if_true: files( + 'dp264.c', + 'pci.c', + 'typhoon.c', +)) + +hw_arch += {'alpha': alpha_ss} diff --git a/hw/alpha/trace.h b/hw/alpha/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..20fe698191a2d82ff4e0b6167babeaca98c23a72 --- /dev/null +++ b/hw/alpha/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_alpha.h" diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c index 1795e2f29d9a25b456728ef6d7d24508d800d471..a42b31981216964c2634bcb93cd42e4cc18b8b72 100644 --- a/hw/alpha/typhoon.c +++ b/hw/alpha/typhoon.c @@ -15,6 +15,7 @@ #include "hw/irq.h" #include "alpha_sys.h" #include "exec/address-spaces.h" +#include "qom/object.h" #define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost" @@ -49,16 +50,15 @@ typedef struct TyphoonPchip { TyphoonWindow win[4]; } TyphoonPchip; -#define TYPHOON_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(TyphoonState, (obj), TYPE_TYPHOON_PCI_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(TyphoonState, TYPHOON_PCI_HOST_BRIDGE) -typedef struct TyphoonState { +struct TyphoonState { PCIHostState parent_obj; TyphoonCchip cchip; TyphoonPchip pchip; MemoryRegion dchip_region; -} TyphoonState; +}; /* Called when one of DRIR or DIM changes. */ static void cpu_irq_change(AlphaCPU *cpu, uint64_t req) @@ -826,7 +826,7 @@ PCIBus *typhoon_init(MemoryRegion *ram, ISABus **isa_bus, qemu_irq *p_rtc_irq, PCIBus *b; int i; - dev = qdev_create(NULL, TYPE_TYPHOON_PCI_HOST_BRIDGE); + dev = qdev_new(TYPE_TYPHOON_PCI_HOST_BRIDGE); s = TYPHOON_PCI_HOST_BRIDGE(dev); phb = PCI_HOST_BRIDGE(dev); @@ -889,7 +889,7 @@ PCIBus *typhoon_init(MemoryRegion *ram, ISABus **isa_bus, qemu_irq *p_rtc_irq, &s->pchip.reg_mem, &s->pchip.reg_io, 0, 64, TYPE_PCI_BUS); phb->bus = b; - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); /* Host memory as seen from the PCI side, via the IOMMU. */ memory_region_init_iommu(&s->pchip.iommu, sizeof(s->pchip.iommu), diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 9afa6eee7991c31ee6e4b644f0c1378e29214405..e69a9009cf0ab55ebada6eba9a170a65008aba76 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -6,7 +6,7 @@ config ARM_VIRT imply VFIO_PLATFORM imply VFIO_XGMAC imply TPM_TIS_SYSBUS - select A15MPCORE + select ARM_GIC select ACPI select ARM_SMMUV3 select GPIO_KEY @@ -26,6 +26,7 @@ config ARM_VIRT select ACPI_MEMORY_HOTPLUG select ACPI_HW_REDUCED select ACPI_NVDIMM + select ACPI_APEI config CHEETAH bool @@ -59,7 +60,7 @@ config HIGHBANK select ARM_TIMER # sp804 select ARM_V7M select PL011 # UART - select PL022 # Serial port + select PL022 # SPI select PL031 # RTC select PL061 # GPIO select PL310 # cache controller @@ -93,6 +94,7 @@ config MUSCA config MUSICPAL bool + select OR_IRQ select BITBANG_I2C select MARVELL_88W8618 select PTIMER @@ -150,6 +152,7 @@ config TOSA select ZAURUS # scoop select MICRODRIVE select PXA2XX + select LED config SPITZ bool @@ -210,6 +213,7 @@ config SBSA_REF select PL031 # RTC select PL061 # GPIO select USB_EHCI_SYSBUS + select WDT_SBSA config SABRELITE bool @@ -222,7 +226,7 @@ config STELLARIS select CMSDK_APB_WATCHDOG select I2C select PL011 # UART - select PL022 # Serial port + select PL022 # SPI select PL061 # GPIO select SSD0303 # OLED display select SSD0323 # OLED display @@ -288,6 +292,7 @@ config ZYNQ config ARM_V7M bool + select PTIMER config ALLWINNER_A10 bool @@ -315,6 +320,7 @@ config RASPI select FRAMEBUFFER select PL011 # UART select SDHCI + select USB_DWC2 config STM32F205_SOC bool @@ -354,6 +360,15 @@ config XLNX_VERSAL select VIRTIO_MMIO select UNIMP +config NPCM7XX + bool + select A9MPCORE + select ARM_GIC + select PL310 # cache controller + select SERIAL + select SSI + select UNIMP + config FSL_IMX25 bool select IMX @@ -393,6 +408,7 @@ config ASPEED_SOC select TMP105 select TMP421 select UNIMP + select LED config MPS2 bool @@ -401,10 +417,12 @@ config MPS2 select MPS2_FPGAIO select MPS2_SCC select OR_IRQ - select PL022 # Serial port + select PL022 # SPI select PL080 # DMA controller select SPLIT_IRQ select UNIMP + select CMSDK_APB_WATCHDOG + select VERSATILE_I2C config FSL_IMX7 bool diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs deleted file mode 100644 index 534a6a119e5d799e49d5312c33e92df2a4f1a2ea..0000000000000000000000000000000000000000 --- a/hw/arm/Makefile.objs +++ /dev/null @@ -1,56 +0,0 @@ -obj-y += boot.o -obj-$(CONFIG_PLATFORM_BUS) += sysbus-fdt.o -obj-$(CONFIG_ARM_VIRT) += virt.o -obj-$(CONFIG_ACPI) += virt-acpi-build.o -obj-$(CONFIG_DIGIC) += digic_boards.o -obj-$(CONFIG_EXYNOS4) += exynos4_boards.o -obj-$(CONFIG_EMCRAFT_SF2) += msf2-som.o -obj-$(CONFIG_HIGHBANK) += highbank.o -obj-$(CONFIG_INTEGRATOR) += integratorcp.o -obj-$(CONFIG_MAINSTONE) += mainstone.o -obj-$(CONFIG_MICROBIT) += microbit.o -obj-$(CONFIG_MUSICPAL) += musicpal.o -obj-$(CONFIG_NETDUINO2) += netduino2.o -obj-$(CONFIG_NETDUINOPLUS2) += netduinoplus2.o -obj-$(CONFIG_NSERIES) += nseries.o -obj-$(CONFIG_SX1) += omap_sx1.o -obj-$(CONFIG_CHEETAH) += palm.o -obj-$(CONFIG_GUMSTIX) += gumstix.o -obj-$(CONFIG_SPITZ) += spitz.o -obj-$(CONFIG_TOSA) += tosa.o -obj-$(CONFIG_Z2) += z2.o -obj-$(CONFIG_REALVIEW) += realview.o -obj-$(CONFIG_SBSA_REF) += sbsa-ref.o -obj-$(CONFIG_STELLARIS) += stellaris.o -obj-$(CONFIG_COLLIE) += collie.o -obj-$(CONFIG_VERSATILE) += versatilepb.o -obj-$(CONFIG_VEXPRESS) += vexpress.o -obj-$(CONFIG_ZYNQ) += xilinx_zynq.o -obj-$(CONFIG_SABRELITE) += sabrelite.o - -obj-$(CONFIG_ARM_V7M) += armv7m.o -obj-$(CONFIG_EXYNOS4) += exynos4210.o -obj-$(CONFIG_PXA2XX) += pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o -obj-$(CONFIG_DIGIC) += digic.o -obj-$(CONFIG_OMAP) += omap1.o omap2.o -obj-$(CONFIG_STRONGARM) += strongarm.o -obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o -obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3.o orangepi.o -obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o -obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o -obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o -obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o -obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o -obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o -obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o -obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o -obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o aspeed_ast2600.o -obj-$(CONFIG_MPS2) += mps2.o -obj-$(CONFIG_MPS2) += mps2-tz.o -obj-$(CONFIG_MSF2) += msf2-soc.o -obj-$(CONFIG_MUSCA) += musca.o -obj-$(CONFIG_ARMSSE) += armsse.o -obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o -obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o -obj-$(CONFIG_FSL_IMX6UL) += fsl-imx6ul.o mcimx6ul-evk.o -obj-$(CONFIG_NRF51_SOC) += nrf51_soc.o diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c index 6e1329a4a256daa38163529b453829e266f4b552..d404f31e02f1dcb0047e2fd024015e5c9b7cea75 100644 --- a/hw/arm/allwinner-a10.c +++ b/hw/arm/allwinner-a10.c @@ -41,54 +41,43 @@ static void aw_a10_init(Object *obj) { AwA10State *s = AW_A10(obj); - object_initialize_child(obj, "cpu", &s->cpu, sizeof(s->cpu), - ARM_CPU_TYPE_NAME("cortex-a8"), - &error_abort, NULL); + object_initialize_child(obj, "cpu", &s->cpu, + ARM_CPU_TYPE_NAME("cortex-a8")); - sysbus_init_child_obj(obj, "intc", &s->intc, sizeof(s->intc), - TYPE_AW_A10_PIC); + object_initialize_child(obj, "intc", &s->intc, TYPE_AW_A10_PIC); - sysbus_init_child_obj(obj, "timer", &s->timer, sizeof(s->timer), - TYPE_AW_A10_PIT); + object_initialize_child(obj, "timer", &s->timer, TYPE_AW_A10_PIT); - sysbus_init_child_obj(obj, "emac", &s->emac, sizeof(s->emac), TYPE_AW_EMAC); + object_initialize_child(obj, "emac", &s->emac, TYPE_AW_EMAC); - sysbus_init_child_obj(obj, "sata", &s->sata, sizeof(s->sata), - TYPE_ALLWINNER_AHCI); + object_initialize_child(obj, "sata", &s->sata, TYPE_ALLWINNER_AHCI); if (machine_usb(current_machine)) { int i; for (i = 0; i < AW_A10_NUM_USB; i++) { - sysbus_init_child_obj(obj, "ehci[*]", OBJECT(&s->ehci[i]), - sizeof(s->ehci[i]), TYPE_PLATFORM_EHCI); - sysbus_init_child_obj(obj, "ohci[*]", OBJECT(&s->ohci[i]), - sizeof(s->ohci[i]), TYPE_SYSBUS_OHCI); + object_initialize_child(obj, "ehci[*]", &s->ehci[i], + TYPE_PLATFORM_EHCI); + object_initialize_child(obj, "ohci[*]", &s->ohci[i], + TYPE_SYSBUS_OHCI); } } - sysbus_init_child_obj(obj, "mmc0", &s->mmc0, sizeof(s->mmc0), - TYPE_AW_SDHOST_SUN4I); + object_initialize_child(obj, "mmc0", &s->mmc0, TYPE_AW_SDHOST_SUN4I); - sysbus_init_child_obj(obj, "rtc", &s->rtc, sizeof(s->rtc), - TYPE_AW_RTC_SUN4I); + object_initialize_child(obj, "rtc", &s->rtc, TYPE_AW_RTC_SUN4I); } static void aw_a10_realize(DeviceState *dev, Error **errp) { AwA10State *s = AW_A10(dev); SysBusDevice *sysbusdev; - Error *err = NULL; - object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->cpu), NULL, errp)) { return; } - object_property_set_bool(OBJECT(&s->intc), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->intc), errp)) { return; } sysbusdev = SYS_BUS_DEVICE(&s->intc); @@ -99,9 +88,7 @@ static void aw_a10_realize(DeviceState *dev, Error **errp) qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ)); qdev_pass_gpios(DEVICE(&s->intc), dev, NULL); - object_property_set_bool(OBJECT(&s->timer), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer), errp)) { return; } sysbusdev = SYS_BUS_DEVICE(&s->timer); @@ -123,18 +110,14 @@ static void aw_a10_realize(DeviceState *dev, Error **errp) qemu_check_nic_model(&nd_table[0], TYPE_AW_EMAC); qdev_set_nic_properties(DEVICE(&s->emac), &nd_table[0]); } - object_property_set_bool(OBJECT(&s->emac), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->emac), errp)) { return; } sysbusdev = SYS_BUS_DEVICE(&s->emac); sysbus_mmio_map(sysbusdev, 0, AW_A10_EMAC_BASE); sysbus_connect_irq(sysbusdev, 0, qdev_get_gpio_in(dev, 55)); - object_property_set_bool(OBJECT(&s->sata), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sata), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->sata), 0, AW_A10_SATA_BASE); @@ -153,19 +136,17 @@ static void aw_a10_realize(DeviceState *dev, Error **errp) sprintf(bus, "usb-bus.%d", i); - object_property_set_bool(OBJECT(&s->ehci[i]), true, - "companion-enable", &error_fatal); - object_property_set_bool(OBJECT(&s->ehci[i]), true, "realized", - &error_fatal); + object_property_set_bool(OBJECT(&s->ehci[i]), "companion-enable", + true, &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(&s->ehci[i]), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(&s->ehci[i]), 0, AW_A10_EHCI_BASE + i * 0x8000); sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci[i]), 0, qdev_get_gpio_in(dev, 39 + i)); - object_property_set_str(OBJECT(&s->ohci[i]), bus, "masterbus", + object_property_set_str(OBJECT(&s->ohci[i]), "masterbus", bus, &error_fatal); - object_property_set_bool(OBJECT(&s->ohci[i]), true, "realized", - &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(&s->ohci[i]), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(&s->ohci[i]), 0, AW_A10_OHCI_BASE + i * 0x8000); sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci[i]), 0, @@ -174,14 +155,16 @@ static void aw_a10_realize(DeviceState *dev, Error **errp) } /* SD/MMC */ - qdev_init_nofail(DEVICE(&s->mmc0)); + object_property_set_link(OBJECT(&s->mmc0), "dma-memory", + OBJECT(get_system_memory()), &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(&s->mmc0), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc0), 0, AW_A10_MMC0_BASE); sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc0), 0, qdev_get_gpio_in(dev, 32)); object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0), "sd-bus"); /* RTC */ - qdev_init_nofail(DEVICE(&s->rtc)); + sysbus_realize(SYS_BUS_DEVICE(&s->rtc), &error_fatal); sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->rtc), 0, AW_A10_RTC_BASE, 10); } diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c index f10674da5a8afc9c2ec4064ee9577334742e5098..88259a9c0d1f9dfe2ba60794a1570450f1fa73f4 100644 --- a/hw/arm/allwinner-h3.c +++ b/hw/arm/allwinner-h3.c @@ -35,37 +35,37 @@ /* Memory map */ const hwaddr allwinner_h3_memmap[] = { - [AW_H3_SRAM_A1] = 0x00000000, - [AW_H3_SRAM_A2] = 0x00044000, - [AW_H3_SRAM_C] = 0x00010000, - [AW_H3_SYSCTRL] = 0x01c00000, - [AW_H3_MMC0] = 0x01c0f000, - [AW_H3_SID] = 0x01c14000, - [AW_H3_EHCI0] = 0x01c1a000, - [AW_H3_OHCI0] = 0x01c1a400, - [AW_H3_EHCI1] = 0x01c1b000, - [AW_H3_OHCI1] = 0x01c1b400, - [AW_H3_EHCI2] = 0x01c1c000, - [AW_H3_OHCI2] = 0x01c1c400, - [AW_H3_EHCI3] = 0x01c1d000, - [AW_H3_OHCI3] = 0x01c1d400, - [AW_H3_CCU] = 0x01c20000, - [AW_H3_PIT] = 0x01c20c00, - [AW_H3_UART0] = 0x01c28000, - [AW_H3_UART1] = 0x01c28400, - [AW_H3_UART2] = 0x01c28800, - [AW_H3_UART3] = 0x01c28c00, - [AW_H3_EMAC] = 0x01c30000, - [AW_H3_DRAMCOM] = 0x01c62000, - [AW_H3_DRAMCTL] = 0x01c63000, - [AW_H3_DRAMPHY] = 0x01c65000, - [AW_H3_GIC_DIST] = 0x01c81000, - [AW_H3_GIC_CPU] = 0x01c82000, - [AW_H3_GIC_HYP] = 0x01c84000, - [AW_H3_GIC_VCPU] = 0x01c86000, - [AW_H3_RTC] = 0x01f00000, - [AW_H3_CPUCFG] = 0x01f01c00, - [AW_H3_SDRAM] = 0x40000000 + [AW_H3_DEV_SRAM_A1] = 0x00000000, + [AW_H3_DEV_SRAM_A2] = 0x00044000, + [AW_H3_DEV_SRAM_C] = 0x00010000, + [AW_H3_DEV_SYSCTRL] = 0x01c00000, + [AW_H3_DEV_MMC0] = 0x01c0f000, + [AW_H3_DEV_SID] = 0x01c14000, + [AW_H3_DEV_EHCI0] = 0x01c1a000, + [AW_H3_DEV_OHCI0] = 0x01c1a400, + [AW_H3_DEV_EHCI1] = 0x01c1b000, + [AW_H3_DEV_OHCI1] = 0x01c1b400, + [AW_H3_DEV_EHCI2] = 0x01c1c000, + [AW_H3_DEV_OHCI2] = 0x01c1c400, + [AW_H3_DEV_EHCI3] = 0x01c1d000, + [AW_H3_DEV_OHCI3] = 0x01c1d400, + [AW_H3_DEV_CCU] = 0x01c20000, + [AW_H3_DEV_PIT] = 0x01c20c00, + [AW_H3_DEV_UART0] = 0x01c28000, + [AW_H3_DEV_UART1] = 0x01c28400, + [AW_H3_DEV_UART2] = 0x01c28800, + [AW_H3_DEV_UART3] = 0x01c28c00, + [AW_H3_DEV_EMAC] = 0x01c30000, + [AW_H3_DEV_DRAMCOM] = 0x01c62000, + [AW_H3_DEV_DRAMCTL] = 0x01c63000, + [AW_H3_DEV_DRAMPHY] = 0x01c65000, + [AW_H3_DEV_GIC_DIST] = 0x01c81000, + [AW_H3_DEV_GIC_CPU] = 0x01c82000, + [AW_H3_DEV_GIC_HYP] = 0x01c84000, + [AW_H3_DEV_GIC_VCPU] = 0x01c86000, + [AW_H3_DEV_RTC] = 0x01f00000, + [AW_H3_DEV_CPUCFG] = 0x01f01c00, + [AW_H3_DEV_SDRAM] = 0x40000000 }; /* List of unimplemented devices */ @@ -183,7 +183,7 @@ void allwinner_h3_bootrom_setup(AwH3State *s, BlockBackend *blk) } rom_add_blob("allwinner-h3.bootrom", buffer, rom_size, - rom_size, s->memmap[AW_H3_SRAM_A1], + rom_size, s->memmap[AW_H3_DEV_SRAM_A1], NULL, NULL, NULL, NULL, false); } @@ -194,50 +194,39 @@ static void allwinner_h3_init(Object *obj) s->memmap = allwinner_h3_memmap; for (int i = 0; i < AW_H3_NUM_CPUS; i++) { - object_initialize_child(obj, "cpu[*]", &s->cpus[i], sizeof(s->cpus[i]), - ARM_CPU_TYPE_NAME("cortex-a7"), - &error_abort, NULL); + object_initialize_child(obj, "cpu[*]", &s->cpus[i], + ARM_CPU_TYPE_NAME("cortex-a7")); } - sysbus_init_child_obj(obj, "gic", &s->gic, sizeof(s->gic), - TYPE_ARM_GIC); + object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GIC); - sysbus_init_child_obj(obj, "timer", &s->timer, sizeof(s->timer), - TYPE_AW_A10_PIT); + object_initialize_child(obj, "timer", &s->timer, TYPE_AW_A10_PIT); object_property_add_alias(obj, "clk0-freq", OBJECT(&s->timer), "clk0-freq"); object_property_add_alias(obj, "clk1-freq", OBJECT(&s->timer), "clk1-freq"); - sysbus_init_child_obj(obj, "ccu", &s->ccu, sizeof(s->ccu), - TYPE_AW_H3_CCU); + object_initialize_child(obj, "ccu", &s->ccu, TYPE_AW_H3_CCU); - sysbus_init_child_obj(obj, "sysctrl", &s->sysctrl, sizeof(s->sysctrl), - TYPE_AW_H3_SYSCTRL); + object_initialize_child(obj, "sysctrl", &s->sysctrl, TYPE_AW_H3_SYSCTRL); - sysbus_init_child_obj(obj, "cpucfg", &s->cpucfg, sizeof(s->cpucfg), - TYPE_AW_CPUCFG); + object_initialize_child(obj, "cpucfg", &s->cpucfg, TYPE_AW_CPUCFG); - sysbus_init_child_obj(obj, "sid", &s->sid, sizeof(s->sid), - TYPE_AW_SID); + object_initialize_child(obj, "sid", &s->sid, TYPE_AW_SID); object_property_add_alias(obj, "identifier", OBJECT(&s->sid), "identifier"); - sysbus_init_child_obj(obj, "mmc0", &s->mmc0, sizeof(s->mmc0), - TYPE_AW_SDHOST_SUN5I); + object_initialize_child(obj, "mmc0", &s->mmc0, TYPE_AW_SDHOST_SUN5I); - sysbus_init_child_obj(obj, "emac", &s->emac, sizeof(s->emac), - TYPE_AW_SUN8I_EMAC); + object_initialize_child(obj, "emac", &s->emac, TYPE_AW_SUN8I_EMAC); - sysbus_init_child_obj(obj, "dramc", &s->dramc, sizeof(s->dramc), - TYPE_AW_H3_DRAMC); + object_initialize_child(obj, "dramc", &s->dramc, TYPE_AW_H3_DRAMC); object_property_add_alias(obj, "ram-addr", OBJECT(&s->dramc), "ram-addr"); object_property_add_alias(obj, "ram-size", OBJECT(&s->dramc), "ram-size"); - sysbus_init_child_obj(obj, "rtc", &s->rtc, sizeof(s->rtc), - TYPE_AW_RTC_SUN6I); + object_initialize_child(obj, "rtc", &s->rtc, TYPE_AW_RTC_SUN6I); } static void allwinner_h3_realize(DeviceState *dev, Error **errp) @@ -261,7 +250,7 @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp) qdev_prop_set_bit(DEVICE(&s->cpus[i]), "has_el2", true); /* Mark realized */ - qdev_init_nofail(DEVICE(&s->cpus[i])); + qdev_realize(DEVICE(&s->cpus[i]), NULL, &error_fatal); } /* Generic Interrupt Controller */ @@ -271,12 +260,12 @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp) qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", AW_H3_NUM_CPUS); qdev_prop_set_bit(DEVICE(&s->gic), "has-security-extensions", false); qdev_prop_set_bit(DEVICE(&s->gic), "has-virtualization-extensions", true); - qdev_init_nofail(DEVICE(&s->gic)); + sysbus_realize(SYS_BUS_DEVICE(&s->gic), &error_fatal); - sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 0, s->memmap[AW_H3_GIC_DIST]); - sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 1, s->memmap[AW_H3_GIC_CPU]); - sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 2, s->memmap[AW_H3_GIC_HYP]); - sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 3, s->memmap[AW_H3_GIC_VCPU]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 0, s->memmap[AW_H3_DEV_GIC_DIST]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 1, s->memmap[AW_H3_DEV_GIC_CPU]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 2, s->memmap[AW_H3_DEV_GIC_HYP]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 3, s->memmap[AW_H3_DEV_GIC_VCPU]); /* * Wire the outputs from each CPU's generic timer and the GICv3 @@ -322,8 +311,8 @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp) } /* Timer */ - qdev_init_nofail(DEVICE(&s->timer)); - sysbus_mmio_map(SYS_BUS_DEVICE(&s->timer), 0, s->memmap[AW_H3_PIT]); + sysbus_realize(SYS_BUS_DEVICE(&s->timer), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->timer), 0, s->memmap[AW_H3_DEV_PIT]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), 0, qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_TIMER0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), 1, @@ -336,32 +325,34 @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp) 32 * KiB, &error_abort); memory_region_init_ram(&s->sram_c, OBJECT(dev), "sram C", 44 * KiB, &error_abort); - memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_SRAM_A1], + memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_DEV_SRAM_A1], &s->sram_a1); - memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_SRAM_A2], + memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_DEV_SRAM_A2], &s->sram_a2); - memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_SRAM_C], + memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_DEV_SRAM_C], &s->sram_c); /* Clock Control Unit */ - qdev_init_nofail(DEVICE(&s->ccu)); - sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_H3_CCU]); + sysbus_realize(SYS_BUS_DEVICE(&s->ccu), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_H3_DEV_CCU]); /* System Control */ - qdev_init_nofail(DEVICE(&s->sysctrl)); - sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctrl), 0, s->memmap[AW_H3_SYSCTRL]); + sysbus_realize(SYS_BUS_DEVICE(&s->sysctrl), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctrl), 0, s->memmap[AW_H3_DEV_SYSCTRL]); /* CPU Configuration */ - qdev_init_nofail(DEVICE(&s->cpucfg)); - sysbus_mmio_map(SYS_BUS_DEVICE(&s->cpucfg), 0, s->memmap[AW_H3_CPUCFG]); + sysbus_realize(SYS_BUS_DEVICE(&s->cpucfg), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->cpucfg), 0, s->memmap[AW_H3_DEV_CPUCFG]); /* Security Identifier */ - qdev_init_nofail(DEVICE(&s->sid)); - sysbus_mmio_map(SYS_BUS_DEVICE(&s->sid), 0, s->memmap[AW_H3_SID]); + sysbus_realize(SYS_BUS_DEVICE(&s->sid), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->sid), 0, s->memmap[AW_H3_DEV_SID]); /* SD/MMC */ - qdev_init_nofail(DEVICE(&s->mmc0)); - sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc0), 0, s->memmap[AW_H3_MMC0]); + object_property_set_link(OBJECT(&s->mmc0), "dma-memory", + OBJECT(get_system_memory()), &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(&s->mmc0), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc0), 0, s->memmap[AW_H3_DEV_MMC0]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc0), 0, qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_MMC0)); @@ -369,68 +360,71 @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp) "sd-bus"); /* EMAC */ + /* FIXME use qdev NIC properties instead of nd_table[] */ if (nd_table[0].used) { qemu_check_nic_model(&nd_table[0], TYPE_AW_SUN8I_EMAC); qdev_set_nic_properties(DEVICE(&s->emac), &nd_table[0]); } - qdev_init_nofail(DEVICE(&s->emac)); - sysbus_mmio_map(SYS_BUS_DEVICE(&s->emac), 0, s->memmap[AW_H3_EMAC]); + object_property_set_link(OBJECT(&s->emac), "dma-memory", + OBJECT(get_system_memory()), &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(&s->emac), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->emac), 0, s->memmap[AW_H3_DEV_EMAC]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->emac), 0, qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_EMAC)); /* Universal Serial Bus */ - sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0], + sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_DEV_EHCI0], qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_EHCI0)); - sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI1], + sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_DEV_EHCI1], qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_EHCI1)); - sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI2], + sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_DEV_EHCI2], qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_EHCI2)); - sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI3], + sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_DEV_EHCI3], qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_EHCI3)); - sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI0], + sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_DEV_OHCI0], qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_OHCI0)); - sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI1], + sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_DEV_OHCI1], qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_OHCI1)); - sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI2], + sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_DEV_OHCI2], qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_OHCI2)); - sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI3], + sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_DEV_OHCI3], qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_OHCI3)); /* UART0. For future clocktree API: All UARTS are connected to APB2_CLK. */ - serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART0], 2, + serial_mm_init(get_system_memory(), s->memmap[AW_H3_DEV_UART0], 2, qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART0), 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN); /* UART1 */ - serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART1], 2, + serial_mm_init(get_system_memory(), s->memmap[AW_H3_DEV_UART1], 2, qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART1), 115200, serial_hd(1), DEVICE_NATIVE_ENDIAN); /* UART2 */ - serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART2], 2, + serial_mm_init(get_system_memory(), s->memmap[AW_H3_DEV_UART2], 2, qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART2), 115200, serial_hd(2), DEVICE_NATIVE_ENDIAN); /* UART3 */ - serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART3], 2, + serial_mm_init(get_system_memory(), s->memmap[AW_H3_DEV_UART3], 2, qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART3), 115200, serial_hd(3), DEVICE_NATIVE_ENDIAN); /* DRAMC */ - qdev_init_nofail(DEVICE(&s->dramc)); - sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 0, s->memmap[AW_H3_DRAMCOM]); - sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 1, s->memmap[AW_H3_DRAMCTL]); - sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 2, s->memmap[AW_H3_DRAMPHY]); + sysbus_realize(SYS_BUS_DEVICE(&s->dramc), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 0, s->memmap[AW_H3_DEV_DRAMCOM]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 1, s->memmap[AW_H3_DEV_DRAMCTL]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 2, s->memmap[AW_H3_DEV_DRAMPHY]); /* RTC */ - qdev_init_nofail(DEVICE(&s->rtc)); - sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, s->memmap[AW_H3_RTC]); + sysbus_realize(SYS_BUS_DEVICE(&s->rtc), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, s->memmap[AW_H3_DEV_RTC]); /* Unimplemented devices */ for (i = 0; i < ARRAY_SIZE(unimplemented); i++) { diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c index 174ca7effc18c49db94e6961c6aee32212ca93ee..baac027659d5bbe414a67f68b57a7077aab12c6c 100644 --- a/hw/arm/armsse.c +++ b/hw/arm/armsse.c @@ -167,7 +167,7 @@ static void irq_status_forwarder(void *opaque, int n, int level) static void nsccfg_handler(void *opaque, int n, int level) { - ARMSSE *s = ARMSSE(opaque); + ARMSSE *s = ARM_SSE(opaque); s->nsccfg = level; } @@ -233,8 +233,8 @@ static void armsse_forward_sec_resp_cfg(ARMSSE *s) static void armsse_init(Object *obj) { - ARMSSE *s = ARMSSE(obj); - ARMSSEClass *asc = ARMSSE_GET_CLASS(obj); + ARMSSE *s = ARM_SSE(obj); + ARMSSEClass *asc = ARM_SSE_GET_CLASS(obj); const ARMSSEInfo *info = asc->info; int i; @@ -251,15 +251,13 @@ static void armsse_init(Object *obj) char *name; name = g_strdup_printf("cluster%d", i); - object_initialize_child(obj, name, &s->cluster[i], - sizeof(s->cluster[i]), TYPE_CPU_CLUSTER, - &error_abort, NULL); + object_initialize_child(obj, name, &s->cluster[i], TYPE_CPU_CLUSTER); qdev_prop_set_uint32(DEVICE(&s->cluster[i]), "cluster-id", i); g_free(name); name = g_strdup_printf("armv7m%d", i); - sysbus_init_child_obj(OBJECT(&s->cluster[i]), name, - &s->armv7m[i], sizeof(s->armv7m), TYPE_ARMV7M); + object_initialize_child(OBJECT(&s->cluster[i]), name, &s->armv7m[i], + TYPE_ARMV7M); qdev_prop_set_string(DEVICE(&s->armv7m[i]), "cpu-type", ARM_CPU_TYPE_NAME("cortex-m33")); g_free(name); @@ -274,74 +272,61 @@ static void armsse_init(Object *obj) } } - sysbus_init_child_obj(obj, "secctl", &s->secctl, sizeof(s->secctl), - TYPE_IOTKIT_SECCTL); - sysbus_init_child_obj(obj, "apb-ppc0", &s->apb_ppc0, sizeof(s->apb_ppc0), - TYPE_TZ_PPC); - sysbus_init_child_obj(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1), - TYPE_TZ_PPC); + object_initialize_child(obj, "secctl", &s->secctl, TYPE_IOTKIT_SECCTL); + object_initialize_child(obj, "apb-ppc0", &s->apb_ppc0, TYPE_TZ_PPC); + object_initialize_child(obj, "apb-ppc1", &s->apb_ppc1, TYPE_TZ_PPC); for (i = 0; i < info->sram_banks; i++) { char *name = g_strdup_printf("mpc%d", i); - sysbus_init_child_obj(obj, name, &s->mpc[i], - sizeof(s->mpc[i]), TYPE_TZ_MPC); + object_initialize_child(obj, name, &s->mpc[i], TYPE_TZ_MPC); g_free(name); } object_initialize_child(obj, "mpc-irq-orgate", &s->mpc_irq_orgate, - sizeof(s->mpc_irq_orgate), TYPE_OR_IRQ, - &error_abort, NULL); + TYPE_OR_IRQ); for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) { char *name = g_strdup_printf("mpc-irq-splitter-%d", i); SplitIRQ *splitter = &s->mpc_irq_splitter[i]; - object_initialize_child(obj, name, splitter, sizeof(*splitter), - TYPE_SPLIT_IRQ, &error_abort, NULL); + object_initialize_child(obj, name, splitter, TYPE_SPLIT_IRQ); g_free(name); } - sysbus_init_child_obj(obj, "timer0", &s->timer0, sizeof(s->timer0), - TYPE_CMSDK_APB_TIMER); - sysbus_init_child_obj(obj, "timer1", &s->timer1, sizeof(s->timer1), - TYPE_CMSDK_APB_TIMER); - sysbus_init_child_obj(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32ktimer), - TYPE_CMSDK_APB_TIMER); - sysbus_init_child_obj(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer), - TYPE_CMSDK_APB_DUALTIMER); - sysbus_init_child_obj(obj, "s32kwatchdog", &s->s32kwatchdog, - sizeof(s->s32kwatchdog), TYPE_CMSDK_APB_WATCHDOG); - sysbus_init_child_obj(obj, "nswatchdog", &s->nswatchdog, - sizeof(s->nswatchdog), TYPE_CMSDK_APB_WATCHDOG); - sysbus_init_child_obj(obj, "swatchdog", &s->swatchdog, - sizeof(s->swatchdog), TYPE_CMSDK_APB_WATCHDOG); - sysbus_init_child_obj(obj, "armsse-sysctl", &s->sysctl, - sizeof(s->sysctl), TYPE_IOTKIT_SYSCTL); - sysbus_init_child_obj(obj, "armsse-sysinfo", &s->sysinfo, - sizeof(s->sysinfo), TYPE_IOTKIT_SYSINFO); + object_initialize_child(obj, "timer0", &s->timer0, TYPE_CMSDK_APB_TIMER); + object_initialize_child(obj, "timer1", &s->timer1, TYPE_CMSDK_APB_TIMER); + object_initialize_child(obj, "s32ktimer", &s->s32ktimer, + TYPE_CMSDK_APB_TIMER); + object_initialize_child(obj, "dualtimer", &s->dualtimer, + TYPE_CMSDK_APB_DUALTIMER); + object_initialize_child(obj, "s32kwatchdog", &s->s32kwatchdog, + TYPE_CMSDK_APB_WATCHDOG); + object_initialize_child(obj, "nswatchdog", &s->nswatchdog, + TYPE_CMSDK_APB_WATCHDOG); + object_initialize_child(obj, "swatchdog", &s->swatchdog, + TYPE_CMSDK_APB_WATCHDOG); + object_initialize_child(obj, "armsse-sysctl", &s->sysctl, + TYPE_IOTKIT_SYSCTL); + object_initialize_child(obj, "armsse-sysinfo", &s->sysinfo, + TYPE_IOTKIT_SYSINFO); if (info->has_mhus) { - sysbus_init_child_obj(obj, "mhu0", &s->mhu[0], sizeof(s->mhu[0]), - TYPE_ARMSSE_MHU); - sysbus_init_child_obj(obj, "mhu1", &s->mhu[1], sizeof(s->mhu[1]), - TYPE_ARMSSE_MHU); + object_initialize_child(obj, "mhu0", &s->mhu[0], TYPE_ARMSSE_MHU); + object_initialize_child(obj, "mhu1", &s->mhu[1], TYPE_ARMSSE_MHU); } if (info->has_ppus) { for (i = 0; i < info->num_cpus; i++) { char *name = g_strdup_printf("CPU%dCORE_PPU", i); int ppuidx = CPU0CORE_PPU + i; - sysbus_init_child_obj(obj, name, &s->ppu[ppuidx], - sizeof(s->ppu[ppuidx]), - TYPE_UNIMPLEMENTED_DEVICE); + object_initialize_child(obj, name, &s->ppu[ppuidx], + TYPE_UNIMPLEMENTED_DEVICE); g_free(name); } - sysbus_init_child_obj(obj, "DBG_PPU", &s->ppu[DBG_PPU], - sizeof(s->ppu[DBG_PPU]), - TYPE_UNIMPLEMENTED_DEVICE); + object_initialize_child(obj, "DBG_PPU", &s->ppu[DBG_PPU], + TYPE_UNIMPLEMENTED_DEVICE); for (i = 0; i < info->sram_banks; i++) { char *name = g_strdup_printf("RAM%d_PPU", i); int ppuidx = RAM0_PPU + i; - sysbus_init_child_obj(obj, name, &s->ppu[ppuidx], - sizeof(s->ppu[ppuidx]), - TYPE_UNIMPLEMENTED_DEVICE); + object_initialize_child(obj, name, &s->ppu[ppuidx], + TYPE_UNIMPLEMENTED_DEVICE); g_free(name); } } @@ -349,9 +334,8 @@ static void armsse_init(Object *obj) for (i = 0; i < info->num_cpus; i++) { char *name = g_strdup_printf("cachectrl%d", i); - sysbus_init_child_obj(obj, name, &s->cachectrl[i], - sizeof(s->cachectrl[i]), - TYPE_UNIMPLEMENTED_DEVICE); + object_initialize_child(obj, name, &s->cachectrl[i], + TYPE_UNIMPLEMENTED_DEVICE); g_free(name); } } @@ -359,9 +343,8 @@ static void armsse_init(Object *obj) for (i = 0; i < info->num_cpus; i++) { char *name = g_strdup_printf("cpusecctrl%d", i); - sysbus_init_child_obj(obj, name, &s->cpusecctrl[i], - sizeof(s->cpusecctrl[i]), - TYPE_UNIMPLEMENTED_DEVICE); + object_initialize_child(obj, name, &s->cpusecctrl[i], + TYPE_UNIMPLEMENTED_DEVICE); g_free(name); } } @@ -369,27 +352,21 @@ static void armsse_init(Object *obj) for (i = 0; i < info->num_cpus; i++) { char *name = g_strdup_printf("cpuid%d", i); - sysbus_init_child_obj(obj, name, &s->cpuid[i], - sizeof(s->cpuid[i]), - TYPE_ARMSSE_CPUID); + object_initialize_child(obj, name, &s->cpuid[i], + TYPE_ARMSSE_CPUID); g_free(name); } } - object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate, - sizeof(s->nmi_orgate), TYPE_OR_IRQ, - &error_abort, NULL); + object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate, TYPE_OR_IRQ); object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate, - sizeof(s->ppc_irq_orgate), TYPE_OR_IRQ, - &error_abort, NULL); + TYPE_OR_IRQ); object_initialize_child(obj, "sec-resp-splitter", &s->sec_resp_splitter, - sizeof(s->sec_resp_splitter), TYPE_SPLIT_IRQ, - &error_abort, NULL); + TYPE_SPLIT_IRQ); for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) { char *name = g_strdup_printf("ppc-irq-splitter-%d", i); SplitIRQ *splitter = &s->ppc_irq_splitter[i]; - object_initialize_child(obj, name, splitter, sizeof(*splitter), - TYPE_SPLIT_IRQ, &error_abort, NULL); + object_initialize_child(obj, name, splitter, TYPE_SPLIT_IRQ); g_free(name); } if (info->num_cpus > 1) { @@ -398,8 +375,7 @@ static void armsse_init(Object *obj) char *name = g_strdup_printf("cpu-irq-splitter%d", i); SplitIRQ *splitter = &s->cpu_irq_splitter[i]; - object_initialize_child(obj, name, splitter, sizeof(*splitter), - TYPE_SPLIT_IRQ, &error_abort, NULL); + object_initialize_child(obj, name, splitter, TYPE_SPLIT_IRQ); g_free(name); } } @@ -415,7 +391,7 @@ static void armsse_exp_irq(void *opaque, int n, int level) static void armsse_mpcexp_status(void *opaque, int n, int level) { - ARMSSE *s = ARMSSE(opaque); + ARMSSE *s = ARM_SSE(opaque); qemu_set_irq(s->mpcexp_status_in[n], level); } @@ -425,7 +401,7 @@ static qemu_irq armsse_get_common_irq_in(ARMSSE *s, int irqno) * Return a qemu_irq which can be used to signal IRQ n to * all CPUs in the SSE. */ - ARMSSEClass *asc = ARMSSE_GET_CLASS(s); + ARMSSEClass *asc = ARM_SSE_GET_CLASS(s); const ARMSSEInfo *info = asc->info; assert(irq_is_common[irqno]); @@ -446,14 +422,14 @@ static void map_ppu(ARMSSE *s, int ppuidx, const char *name, hwaddr addr) qdev_prop_set_string(dev, "name", name); qdev_prop_set_uint64(dev, "size", 0x1000); - qdev_init_nofail(dev); + sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(&s->ppu[ppuidx]), 0, addr); } static void armsse_realize(DeviceState *dev, Error **errp) { - ARMSSE *s = ARMSSE(dev); - ARMSSEClass *asc = ARMSSE_GET_CLASS(dev); + ARMSSE *s = ARM_SSE(dev); + ARMSSEClass *asc = ARM_SSE_GET_CLASS(dev); const ARMSSEInfo *info = asc->info; int i; MemoryRegion *mr; @@ -476,6 +452,8 @@ static void armsse_realize(DeviceState *dev, Error **errp) return; } + assert(info->num_cpus <= SSE_MAX_CPUS); + /* max SRAM_ADDR_WIDTH: 24 - log2(SRAM_NUM_BANK) */ assert(is_power_of_2(info->sram_banks)); addr_width_max = 24 - ctz32(info->sram_banks); @@ -558,23 +536,18 @@ static void armsse_realize(DeviceState *dev, Error **errp) * later if necessary. */ if (extract32(info->cpuwait_rst, i, 1)) { - object_property_set_bool(cpuobj, true, "start-powered-off", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_bool(cpuobj, "start-powered-off", true, + errp)) { return; } } if (!s->cpu_fpu[i]) { - object_property_set_bool(cpuobj, false, "vfp", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_bool(cpuobj, "vfp", false, errp)) { return; } } if (!s->cpu_dsp[i]) { - object_property_set_bool(cpuobj, false, "dsp", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_bool(cpuobj, "dsp", false, errp)) { return; } } @@ -586,20 +559,10 @@ static void armsse_realize(DeviceState *dev, Error **errp) memory_region_add_subregion_overlap(&s->cpu_container[i], 0, &s->container, -1); } - object_property_set_link(cpuobj, OBJECT(&s->cpu_container[i]), - "memory", &err); - if (err) { - error_propagate(errp, err); - return; - } - object_property_set_link(cpuobj, OBJECT(s), "idau", &err); - if (err) { - error_propagate(errp, err); - return; - } - object_property_set_bool(cpuobj, true, "realized", &err); - if (err) { - error_propagate(errp, err); + object_property_set_link(cpuobj, "memory", + OBJECT(&s->cpu_container[i]), &error_abort); + object_property_set_link(cpuobj, "idau", OBJECT(s), &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(cpuobj), errp)) { return; } /* @@ -608,10 +571,7 @@ static void armsse_realize(DeviceState *dev, Error **errp) * CPU must exist and have been parented into the cluster before * the cluster is realized. */ - object_property_set_bool(OBJECT(&s->cluster[i]), - true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->cluster[i]), NULL, errp)) { return; } @@ -639,15 +599,11 @@ static void armsse_realize(DeviceState *dev, Error **errp) DeviceState *devs = DEVICE(splitter); int cpunum; - object_property_set_int(splitter, info->num_cpus, - "num-lines", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_int(splitter, "num-lines", + info->num_cpus, errp)) { return; } - object_property_set_bool(splitter, true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(splitter), NULL, errp)) { return; } for (cpunum = 0; cpunum < info->num_cpus; cpunum++) { @@ -678,9 +634,7 @@ static void armsse_realize(DeviceState *dev, Error **errp) } /* Security controller */ - object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->secctl), errp)) { return; } sbd_secctl = SYS_BUS_DEVICE(&s->secctl); @@ -695,16 +649,11 @@ static void armsse_realize(DeviceState *dev, Error **errp) * multiple lines, one for each of the PPCs within the ARMSSE and one * that will be an output from the ARMSSE to the system. */ - object_property_set_int(OBJECT(&s->sec_resp_splitter), 3, - "num-lines", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_int(OBJECT(&s->sec_resp_splitter), + "num-lines", 3, errp)) { return; } - object_property_set_bool(OBJECT(&s->sec_resp_splitter), true, - "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->sec_resp_splitter), NULL, errp)) { return; } dev_splitter = DEVICE(&s->sec_resp_splitter); @@ -724,15 +673,9 @@ static void armsse_realize(DeviceState *dev, Error **errp) error_propagate(errp, err); return; } - object_property_set_link(OBJECT(&s->mpc[i]), OBJECT(&s->sram[i]), - "downstream", &err); - if (err) { - error_propagate(errp, err); - return; - } - object_property_set_bool(OBJECT(&s->mpc[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + object_property_set_link(OBJECT(&s->mpc[i]), "downstream", + OBJECT(&s->sram[i]), &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->mpc[i]), errp)) { return; } /* Map the upstream end of the MPC into the right place... */ @@ -746,17 +689,12 @@ static void armsse_realize(DeviceState *dev, Error **errp) } /* We must OR together lines from the MPC splitters to go to the NVIC */ - object_property_set_int(OBJECT(&s->mpc_irq_orgate), - IOTS_NUM_EXP_MPC + info->sram_banks, - "num-lines", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_int(OBJECT(&s->mpc_irq_orgate), "num-lines", + IOTS_NUM_EXP_MPC + info->sram_banks, + errp)) { return; } - object_property_set_bool(OBJECT(&s->mpc_irq_orgate), true, - "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->mpc_irq_orgate), NULL, errp)) { return; } qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0, @@ -773,50 +711,34 @@ static void armsse_realize(DeviceState *dev, Error **errp) * map its upstream ends to the right place in the container. */ qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq); - object_property_set_bool(OBJECT(&s->timer0), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer0), errp)) { return; } sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0, armsse_get_common_irq_in(s, 3)); mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0); - object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[0]", &err); - if (err) { - error_propagate(errp, err); - return; - } + object_property_set_link(OBJECT(&s->apb_ppc0), "port[0]", OBJECT(mr), + &error_abort); qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq); - object_property_set_bool(OBJECT(&s->timer1), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer1), errp)) { return; } sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0, armsse_get_common_irq_in(s, 4)); mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0); - object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[1]", &err); - if (err) { - error_propagate(errp, err); - return; - } - + object_property_set_link(OBJECT(&s->apb_ppc0), "port[1]", OBJECT(mr), + &error_abort); qdev_prop_set_uint32(DEVICE(&s->dualtimer), "pclk-frq", s->mainclk_frq); - object_property_set_bool(OBJECT(&s->dualtimer), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->dualtimer), errp)) { return; } sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0, armsse_get_common_irq_in(s, 5)); mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0); - object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err); - if (err) { - error_propagate(errp, err); - return; - } + object_property_set_link(OBJECT(&s->apb_ppc0), "port[2]", OBJECT(mr), + &error_abort); if (info->has_mhus) { /* @@ -833,21 +755,14 @@ static void armsse_realize(DeviceState *dev, Error **errp) int cpunum; SysBusDevice *mhu_sbd = SYS_BUS_DEVICE(&s->mhu[i]); - object_property_set_bool(OBJECT(&s->mhu[i]), true, - "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->mhu[i]), errp)) { return; } port = g_strdup_printf("port[%d]", i + 3); mr = sysbus_mmio_get_region(mhu_sbd, 0); - object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), - port, &err); + object_property_set_link(OBJECT(&s->apb_ppc0), port, OBJECT(mr), + &error_abort); g_free(port); - if (err) { - error_propagate(errp, err); - return; - } /* * Each MHU has an irq line for each CPU: @@ -865,9 +780,7 @@ static void armsse_realize(DeviceState *dev, Error **errp) } } - object_property_set_bool(OBJECT(&s->apb_ppc0), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc0), errp)) { return; } @@ -908,16 +821,11 @@ static void armsse_realize(DeviceState *dev, Error **errp) * ones) are sent individually to the security controller, and also * ORed together to give a single combined PPC interrupt to the NVIC. */ - object_property_set_int(OBJECT(&s->ppc_irq_orgate), - NUM_PPCS, "num-lines", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_int(OBJECT(&s->ppc_irq_orgate), + "num-lines", NUM_PPCS, errp)) { return; } - object_property_set_bool(OBJECT(&s->ppc_irq_orgate), true, - "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->ppc_irq_orgate), NULL, errp)) { return; } qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0, @@ -938,10 +846,7 @@ static void armsse_realize(DeviceState *dev, Error **errp) qdev_prop_set_string(DEVICE(&s->cachectrl[i]), "name", name); g_free(name); qdev_prop_set_uint64(DEVICE(&s->cachectrl[i]), "size", 0x1000); - object_property_set_bool(OBJECT(&s->cachectrl[i]), true, - "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->cachectrl[i]), errp)) { return; } @@ -957,10 +862,7 @@ static void armsse_realize(DeviceState *dev, Error **errp) qdev_prop_set_string(DEVICE(&s->cpusecctrl[i]), "name", name); g_free(name); qdev_prop_set_uint64(DEVICE(&s->cpusecctrl[i]), "size", 0x1000); - object_property_set_bool(OBJECT(&s->cpusecctrl[i]), true, - "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpusecctrl[i]), errp)) { return; } @@ -973,10 +875,7 @@ static void armsse_realize(DeviceState *dev, Error **errp) MemoryRegion *mr; qdev_prop_set_uint32(DEVICE(&s->cpuid[i]), "CPUID", i); - object_property_set_bool(OBJECT(&s->cpuid[i]), true, - "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpuid[i]), errp)) { return; } @@ -990,23 +889,16 @@ static void armsse_realize(DeviceState *dev, Error **errp) * 0x4002f000: S32K timer */ qdev_prop_set_uint32(DEVICE(&s->s32ktimer), "pclk-frq", S32KCLK); - object_property_set_bool(OBJECT(&s->s32ktimer), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32ktimer), errp)) { return; } sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0, armsse_get_common_irq_in(s, 2)); mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0); - object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err); - if (err) { - error_propagate(errp, err); - return; - } + object_property_set_link(OBJECT(&s->apb_ppc1), "port[0]", OBJECT(mr), + &error_abort); - object_property_set_bool(OBJECT(&s->apb_ppc1), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc1), errp)) { return; } mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc1), 0); @@ -1029,38 +921,29 @@ static void armsse_realize(DeviceState *dev, Error **errp) qdev_get_gpio_in_named(dev_apb_ppc1, "cfg_sec_resp", 0)); - object_property_set_int(OBJECT(&s->sysinfo), info->sys_version, - "SYS_VERSION", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_int(OBJECT(&s->sysinfo), "SYS_VERSION", + info->sys_version, errp)) { return; } - object_property_set_int(OBJECT(&s->sysinfo), - armsse_sys_config_value(s, info), - "SYS_CONFIG", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_int(OBJECT(&s->sysinfo), "SYS_CONFIG", + armsse_sys_config_value(s, info), errp)) { return; } - object_property_set_bool(OBJECT(&s->sysinfo), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysinfo), errp)) { return; } /* System information registers */ sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, 0x40020000); /* System control registers */ - object_property_set_int(OBJECT(&s->sysctl), info->sys_version, - "SYS_VERSION", &err); - object_property_set_int(OBJECT(&s->sysctl), info->cpuwait_rst, - "CPUWAIT_RST", &err); - object_property_set_int(OBJECT(&s->sysctl), s->init_svtor, - "INITSVTOR0_RST", &err); - object_property_set_int(OBJECT(&s->sysctl), s->init_svtor, - "INITSVTOR1_RST", &err); - object_property_set_bool(OBJECT(&s->sysctl), true, "realized", &err); - if (err) { - error_propagate(errp, err); + object_property_set_int(OBJECT(&s->sysctl), "SYS_VERSION", + info->sys_version, &error_abort); + object_property_set_int(OBJECT(&s->sysctl), "CPUWAIT_RST", + info->cpuwait_rst, &error_abort); + object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR0_RST", + s->init_svtor, &error_abort); + object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR1_RST", + s->init_svtor, &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysctl), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctl), 0, 0x50021000); @@ -1088,23 +971,18 @@ static void armsse_realize(DeviceState *dev, Error **errp) } /* This OR gate wires together outputs from the secure watchdogs to NMI */ - object_property_set_int(OBJECT(&s->nmi_orgate), 2, "num-lines", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_int(OBJECT(&s->nmi_orgate), "num-lines", 2, + errp)) { return; } - object_property_set_bool(OBJECT(&s->nmi_orgate), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->nmi_orgate), NULL, errp)) { return; } qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0, qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0)); qdev_prop_set_uint32(DEVICE(&s->s32kwatchdog), "wdogclk-frq", S32KCLK); - object_property_set_bool(OBJECT(&s->s32kwatchdog), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32kwatchdog), errp)) { return; } sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, @@ -1114,9 +992,7 @@ static void armsse_realize(DeviceState *dev, Error **errp) /* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */ qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq); - object_property_set_bool(OBJECT(&s->nswatchdog), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->nswatchdog), errp)) { return; } sysbus_connect_irq(SYS_BUS_DEVICE(&s->nswatchdog), 0, @@ -1124,9 +1000,7 @@ static void armsse_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000); qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq); - object_property_set_bool(OBJECT(&s->swatchdog), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->swatchdog), errp)) { return; } sysbus_connect_irq(SYS_BUS_DEVICE(&s->swatchdog), 0, @@ -1136,14 +1010,10 @@ static void armsse_realize(DeviceState *dev, Error **errp) for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) { Object *splitter = OBJECT(&s->ppc_irq_splitter[i]); - object_property_set_int(splitter, 2, "num-lines", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_int(splitter, "num-lines", 2, errp)) { return; } - object_property_set_bool(splitter, true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(splitter), NULL, errp)) { return; } } @@ -1183,14 +1053,11 @@ static void armsse_realize(DeviceState *dev, Error **errp) SplitIRQ *splitter = &s->mpc_irq_splitter[i]; DeviceState *dev_splitter = DEVICE(splitter); - object_property_set_int(OBJECT(splitter), 2, "num-lines", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_int(OBJECT(splitter), "num-lines", 2, + errp)) { return; } - object_property_set_bool(OBJECT(splitter), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(splitter), NULL, errp)) { return; } @@ -1207,7 +1074,8 @@ static void armsse_realize(DeviceState *dev, Error **errp) qdev_get_gpio_in(dev_splitter, 0)); qdev_connect_gpio_out(dev_splitter, 0, qdev_get_gpio_in_named(dev_secctl, - "mpc_status", 0)); + "mpc_status", + i - IOTS_NUM_EXP_MPC)); } qdev_connect_gpio_out(dev_splitter, 1, @@ -1247,7 +1115,7 @@ static void armsse_idau_check(IDAUInterface *ii, uint32_t address, * of the address bits. The NSC attribute is guest-adjustable via the * NSCCFG register in the security controller. */ - ARMSSE *s = ARMSSE(ii); + ARMSSE *s = ARM_SSE(ii); int region = extract32(address, 28, 4); *ns = !(region & 1); @@ -1269,7 +1137,7 @@ static const VMStateDescription armsse_vmstate = { static void armsse_reset(DeviceState *dev) { - ARMSSE *s = ARMSSE(dev); + ARMSSE *s = ARM_SSE(dev); s->nsccfg = 0; } @@ -1278,7 +1146,7 @@ static void armsse_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass); - ARMSSEClass *asc = ARMSSE_CLASS(klass); + ARMSSEClass *asc = ARM_SSE_CLASS(klass); const ARMSSEInfo *info = data; dc->realize = armsse_realize; @@ -1290,9 +1158,10 @@ static void armsse_class_init(ObjectClass *klass, void *data) } static const TypeInfo armsse_info = { - .name = TYPE_ARMSSE, + .name = TYPE_ARM_SSE, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(ARMSSE), + .class_size = sizeof(ARMSSEClass), .instance_init = armsse_init, .abstract = true, .interfaces = (InterfaceInfo[]) { @@ -1310,7 +1179,7 @@ static void armsse_register_types(void) for (i = 0; i < ARRAY_SIZE(armsse_variants); i++) { TypeInfo ti = { .name = armsse_variants[i].name, - .parent = TYPE_ARMSSE, + .parent = TYPE_ARM_SSE, .class_init = armsse_class_init, .class_data = (void *)&armsse_variants[i], }; diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c index 7da57f56d308933fcb8c9a15ae2413192527eafd..8113b29f1fdcb67505265c02db16aad97b57ee34 100644 --- a/hw/arm/armv7m.c +++ b/hw/arm/armv7m.c @@ -136,13 +136,13 @@ static void armv7m_instance_init(Object *obj) memory_region_init(&s->container, obj, "armv7m-container", UINT64_MAX); - sysbus_init_child_obj(obj, "nvnic", &s->nvic, sizeof(s->nvic), TYPE_NVIC); + object_initialize_child(obj, "nvnic", &s->nvic, TYPE_NVIC); object_property_add_alias(obj, "num-irq", OBJECT(&s->nvic), "num-irq"); for (i = 0; i < ARRAY_SIZE(s->bitband); i++) { - sysbus_init_child_obj(obj, "bitband[*]", &s->bitband[i], - sizeof(s->bitband[i]), TYPE_BITBAND); + object_initialize_child(obj, "bitband[*]", &s->bitband[i], + TYPE_BITBAND); } } @@ -167,44 +167,31 @@ static void armv7m_realize(DeviceState *dev, Error **errp) return; } - object_property_set_link(OBJECT(s->cpu), OBJECT(&s->container), "memory", + object_property_set_link(OBJECT(s->cpu), "memory", OBJECT(&s->container), &error_abort); - if (object_property_find(OBJECT(s->cpu), "idau", NULL)) { - object_property_set_link(OBJECT(s->cpu), s->idau, "idau", &err); - if (err != NULL) { - error_propagate(errp, err); - return; - } + if (object_property_find(OBJECT(s->cpu), "idau")) { + object_property_set_link(OBJECT(s->cpu), "idau", s->idau, + &error_abort); } - if (object_property_find(OBJECT(s->cpu), "init-svtor", NULL)) { - object_property_set_uint(OBJECT(s->cpu), s->init_svtor, - "init-svtor", &err); - if (err != NULL) { - error_propagate(errp, err); + if (object_property_find(OBJECT(s->cpu), "init-svtor")) { + if (!object_property_set_uint(OBJECT(s->cpu), "init-svtor", + s->init_svtor, errp)) { return; } } - if (object_property_find(OBJECT(s->cpu), "start-powered-off", NULL)) { - object_property_set_bool(OBJECT(s->cpu), s->start_powered_off, - "start-powered-off", &err); - if (err != NULL) { - error_propagate(errp, err); + if (object_property_find(OBJECT(s->cpu), "start-powered-off")) { + if (!object_property_set_bool(OBJECT(s->cpu), "start-powered-off", + s->start_powered_off, errp)) { return; } } - if (object_property_find(OBJECT(s->cpu), "vfp", NULL)) { - object_property_set_bool(OBJECT(s->cpu), s->vfp, - "vfp", &err); - if (err != NULL) { - error_propagate(errp, err); + if (object_property_find(OBJECT(s->cpu), "vfp")) { + if (!object_property_set_bool(OBJECT(s->cpu), "vfp", s->vfp, errp)) { return; } } - if (object_property_find(OBJECT(s->cpu), "dsp", NULL)) { - object_property_set_bool(OBJECT(s->cpu), s->dsp, - "dsp", &err); - if (err != NULL) { - error_propagate(errp, err); + if (object_property_find(OBJECT(s->cpu), "dsp")) { + if (!object_property_set_bool(OBJECT(s->cpu), "dsp", s->dsp, errp)) { return; } } @@ -216,16 +203,12 @@ static void armv7m_realize(DeviceState *dev, Error **errp) s->cpu->env.nvic = &s->nvic; s->nvic.cpu = s->cpu; - object_property_set_bool(OBJECT(s->cpu), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(s->cpu), NULL, errp)) { return; } /* Note that we must realize the NVIC after the CPU */ - object_property_set_bool(OBJECT(&s->nvic), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->nvic), errp)) { return; } @@ -245,26 +228,25 @@ static void armv7m_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(&s->container, 0xe000e000, sysbus_mmio_get_region(sbd, 0)); - if (s->enable_bitband) { - for (i = 0; i < ARRAY_SIZE(s->bitband); i++) { + for (i = 0; i < ARRAY_SIZE(s->bitband); i++) { + if (s->enable_bitband) { Object *obj = OBJECT(&s->bitband[i]); SysBusDevice *sbd = SYS_BUS_DEVICE(&s->bitband[i]); - object_property_set_int(obj, bitband_input_addr[i], "base", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!object_property_set_int(obj, "base", + bitband_input_addr[i], errp)) { return; } - object_property_set_link(obj, OBJECT(s->board_memory), - "source-memory", &error_abort); - object_property_set_bool(obj, true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + object_property_set_link(obj, "source-memory", + OBJECT(s->board_memory), &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(obj), errp)) { return; } memory_region_add_subregion(&s->container, bitband_output_addr[i], sysbus_mmio_get_region(sbd, 0)); + } else { + object_unparent(OBJECT(&s->bitband[i])); } } } @@ -310,7 +292,6 @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size) { int image_size; uint64_t entry; - uint64_t lowaddr; int big_endian; AddressSpace *as; int asidx; @@ -331,12 +312,11 @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size) if (kernel_filename) { image_size = load_elf_as(kernel_filename, NULL, NULL, NULL, - &entry, &lowaddr, NULL, + &entry, NULL, NULL, NULL, big_endian, EM_ARM, 1, 0, as); if (image_size < 0) { image_size = load_image_targphys_as(kernel_filename, 0, mem_size, as); - lowaddr = 0; } if (image_size < 0) { error_report("Could not load kernel '%s'", kernel_filename); diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 2c23297edf07126d98891363633b11d12cd6455e..0ef3f6b412fe3035215061d650338e8d046b534f 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -20,6 +20,7 @@ #include "hw/i2c/smbus_eeprom.h" #include "hw/misc/pca9552.h" #include "hw/misc/tmp105.h" +#include "hw/misc/led.h" #include "hw/qdev-properties.h" #include "qemu/log.h" #include "sysemu/block-backend.h" @@ -32,10 +33,17 @@ static struct arm_boot_info aspeed_board_binfo = { .board_id = -1, /* device-tree-only board */ }; -struct AspeedBoardState { +struct AspeedMachineState { + /* Private */ + MachineState parent_obj; + /* Public */ + AspeedSoCState soc; MemoryRegion ram_container; MemoryRegion max_ram; + bool mmio_exec; + char *fmc_model; + char *spi_model; }; /* Palmetto hardware value: 0x120CE416 */ @@ -52,6 +60,20 @@ struct AspeedBoardState { SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \ SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT)) +/* TODO: Find the actual hardware value */ +#define SUPERMICROX11_BMC_HW_STRAP1 ( \ + SCU_AST2400_HW_STRAP_DRAM_SIZE(DRAM_SIZE_128MB) | \ + SCU_AST2400_HW_STRAP_DRAM_CONFIG(2) | \ + SCU_AST2400_HW_STRAP_ACPI_DIS | \ + SCU_AST2400_HW_STRAP_SET_CLK_SOURCE(AST2400_CLK_48M_IN) | \ + SCU_HW_STRAP_VGA_CLASS_CODE | \ + SCU_HW_STRAP_LPC_RESET_PIN | \ + SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_M_S_EN) | \ + SCU_AST2400_HW_STRAP_SET_CPU_AHB_RATIO(AST2400_CPU_AHB_RATIO_2_1) | \ + SCU_HW_STRAP_SPI_WIDTH | \ + SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \ + SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT)) + /* AST2500 evb hardware value: 0xF100C2E6 */ #define AST2500_EVB_HW_STRAP1 (( \ AST2500_HW_STRAP1_DEFAULTS | \ @@ -215,8 +237,8 @@ static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size, g_free(storage); } -static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype, - Error **errp) +static void aspeed_board_init_flashes(AspeedSMCState *s, + const char *flashtype) { int i ; @@ -225,12 +247,12 @@ static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype, DriveInfo *dinfo = drive_get_next(IF_MTD); qemu_irq cs_line; - fl->flash = ssi_create_slave_no_init(s->spi, flashtype); + fl->flash = qdev_new(flashtype); if (dinfo) { - qdev_prop_set_drive(fl->flash, "drive", blk_by_legacy_dinfo(dinfo), - errp); + qdev_prop_set_drive(fl->flash, "drive", + blk_by_legacy_dinfo(dinfo)); } - qdev_init_nofail(fl->flash); + qdev_realize_and_unref(fl->flash, BUS(s->spi), &error_fatal); cs_line = qdev_get_gpio_in_named(fl->flash, SSI_GPIO_CS, 0); sysbus_connect_irq(SYS_BUS_DEVICE(s), i + 1, cs_line); @@ -241,66 +263,70 @@ static void sdhci_attach_drive(SDHCIState *sdhci, DriveInfo *dinfo) { DeviceState *card; - card = qdev_create(qdev_get_child_bus(DEVICE(sdhci), "sd-bus"), - TYPE_SD_CARD); - if (dinfo) { - qdev_prop_set_drive(card, "drive", blk_by_legacy_dinfo(dinfo), - &error_fatal); + if (!dinfo) { + return; } - object_property_set_bool(OBJECT(card), true, "realized", &error_fatal); + card = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo), + &error_fatal); + qdev_realize_and_unref(card, + qdev_get_child_bus(DEVICE(sdhci), "sd-bus"), + &error_fatal); } static void aspeed_machine_init(MachineState *machine) { - AspeedBoardState *bmc; + AspeedMachineState *bmc = ASPEED_MACHINE(machine); AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(machine); AspeedSoCClass *sc; DriveInfo *drive0 = drive_get(IF_MTD, 0, 0); ram_addr_t max_ram_size; int i; - - bmc = g_new0(AspeedBoardState, 1); + NICInfo *nd = &nd_table[0]; memory_region_init(&bmc->ram_container, NULL, "aspeed-ram-container", - UINT32_MAX); + 4 * GiB); memory_region_add_subregion(&bmc->ram_container, 0, machine->ram); - object_initialize_child(OBJECT(machine), "soc", &bmc->soc, - (sizeof(bmc->soc)), amc->soc_name, &error_abort, - NULL); + object_initialize_child(OBJECT(machine), "soc", &bmc->soc, amc->soc_name); sc = ASPEED_SOC_GET_CLASS(&bmc->soc); /* * This will error out if isize is not supported by memory controller. */ - object_property_set_uint(OBJECT(&bmc->soc), ram_size, "ram-size", + object_property_set_uint(OBJECT(&bmc->soc), "ram-size", ram_size, &error_fatal); - object_property_set_int(OBJECT(&bmc->soc), amc->hw_strap1, "hw-strap1", - &error_abort); - object_property_set_int(OBJECT(&bmc->soc), amc->hw_strap2, "hw-strap2", + for (i = 0; i < sc->macs_num; i++) { + if ((amc->macs_mask & (1 << i)) && nd->used) { + qemu_check_nic_model(nd, TYPE_FTGMAC100); + qdev_set_nic_properties(DEVICE(&bmc->soc.ftgmac100[i]), nd); + nd++; + } + } + + object_property_set_int(OBJECT(&bmc->soc), "hw-strap1", amc->hw_strap1, &error_abort); - object_property_set_int(OBJECT(&bmc->soc), amc->num_cs, "num-cs", + object_property_set_int(OBJECT(&bmc->soc), "hw-strap2", amc->hw_strap2, &error_abort); - object_property_set_int(OBJECT(&bmc->soc), machine->smp.cpus, "num-cpus", + object_property_set_int(OBJECT(&bmc->soc), "num-cs", amc->num_cs, &error_abort); - object_property_set_link(OBJECT(&bmc->soc), OBJECT(&bmc->ram_container), - "dram", &error_abort); + object_property_set_link(OBJECT(&bmc->soc), "dram", + OBJECT(&bmc->ram_container), &error_abort); if (machine->kernel_filename) { /* * When booting with a -kernel command line there is no u-boot * that runs to unlock the SCU. In this case set the default to * be unlocked as the kernel expects */ - object_property_set_int(OBJECT(&bmc->soc), ASPEED_SCU_PROT_KEY, - "hw-prot-key", &error_abort); + object_property_set_int(OBJECT(&bmc->soc), "hw-prot-key", + ASPEED_SCU_PROT_KEY, &error_abort); } - object_property_set_bool(OBJECT(&bmc->soc), true, "realized", - &error_abort); + qdev_realize(DEVICE(&bmc->soc), NULL, &error_abort); memory_region_add_subregion(get_system_memory(), - sc->memmap[ASPEED_SDRAM], + sc->memmap[ASPEED_DEV_SDRAM], &bmc->ram_container); max_ram_size = object_property_get_uint(OBJECT(&bmc->soc), "max-ram-size", @@ -309,8 +335,10 @@ static void aspeed_machine_init(MachineState *machine) "max_ram", max_ram_size - ram_size); memory_region_add_subregion(&bmc->ram_container, ram_size, &bmc->max_ram); - aspeed_board_init_flashes(&bmc->soc.fmc, amc->fmc_model, &error_abort); - aspeed_board_init_flashes(&bmc->soc.spi[0], amc->spi_model, &error_abort); + aspeed_board_init_flashes(&bmc->soc.fmc, bmc->fmc_model ? + bmc->fmc_model : amc->fmc_model); + aspeed_board_init_flashes(&bmc->soc.spi[0], bmc->spi_model ? + bmc->spi_model : amc->spi_model); /* Install first FMC flash content as a boot rom. */ if (drive0) { @@ -324,12 +352,12 @@ static void aspeed_machine_init(MachineState *machine) * needed by the flash modules of the Aspeed machines. */ if (ASPEED_MACHINE(machine)->mmio_exec) { - memory_region_init_alias(boot_rom, OBJECT(bmc), "aspeed.boot_rom", + memory_region_init_alias(boot_rom, NULL, "aspeed.boot_rom", &fl->mmio, 0, fl->size); memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR, boot_rom); } else { - memory_region_init_rom(boot_rom, OBJECT(bmc), "aspeed.boot_rom", + memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom", fl->size, &error_abort); memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR, boot_rom); @@ -337,10 +365,10 @@ static void aspeed_machine_init(MachineState *machine) } } - if (machine->kernel_filename && bmc->soc.num_cpus > 1) { + if (machine->kernel_filename && sc->num_cpus > 1) { /* With no u-boot we must set up a boot stub for the secondary CPU */ MemoryRegion *smpboot = g_new(MemoryRegion, 1); - memory_region_init_ram(smpboot, OBJECT(bmc), "aspeed.smpboot", + memory_region_init_ram(smpboot, NULL, "aspeed.smpboot", 0x80, &error_abort); memory_region_add_subregion(get_system_memory(), AST_SMP_MAILBOX_BASE, smpboot); @@ -351,8 +379,8 @@ static void aspeed_machine_init(MachineState *machine) } aspeed_board_binfo.ram_size = ram_size; - aspeed_board_binfo.loader_start = sc->memmap[ASPEED_SDRAM]; - aspeed_board_binfo.nb_cpus = bmc->soc.num_cpus; + aspeed_board_binfo.loader_start = sc->memmap[ASPEED_DEV_SDRAM]; + aspeed_board_binfo.nb_cpus = sc->num_cpus; if (amc->i2c_init) { amc->i2c_init(bmc); @@ -369,7 +397,7 @@ static void aspeed_machine_init(MachineState *machine) arm_load_kernel(ARM_CPU(first_cpu), machine, &aspeed_board_binfo); } -static void palmetto_bmc_i2c_init(AspeedBoardState *bmc) +static void palmetto_bmc_i2c_init(AspeedMachineState *bmc) { AspeedSoCState *soc = &bmc->soc; DeviceState *dev; @@ -377,112 +405,112 @@ static void palmetto_bmc_i2c_init(AspeedBoardState *bmc) /* The palmetto platform expects a ds3231 RTC but a ds1338 is * enough to provide basic RTC features. Alarms will be missing */ - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 0), "ds1338", 0x68); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 0), "ds1338", 0x68); - smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 0), 0x50, + smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 0), 0x50, eeprom_buf); /* add a TMP423 temperature sensor */ - dev = i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2), - "tmp423", 0x4c); - object_property_set_int(OBJECT(dev), 31000, "temperature0", &error_abort); - object_property_set_int(OBJECT(dev), 28000, "temperature1", &error_abort); - object_property_set_int(OBJECT(dev), 20000, "temperature2", &error_abort); - object_property_set_int(OBJECT(dev), 110000, "temperature3", &error_abort); + dev = DEVICE(i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 2), + "tmp423", 0x4c)); + object_property_set_int(OBJECT(dev), "temperature0", 31000, &error_abort); + object_property_set_int(OBJECT(dev), "temperature1", 28000, &error_abort); + object_property_set_int(OBJECT(dev), "temperature2", 20000, &error_abort); + object_property_set_int(OBJECT(dev), "temperature3", 110000, &error_abort); } -static void ast2500_evb_i2c_init(AspeedBoardState *bmc) +static void ast2500_evb_i2c_init(AspeedMachineState *bmc) { AspeedSoCState *soc = &bmc->soc; uint8_t *eeprom_buf = g_malloc0(8 * 1024); - smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), 0x50, + smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 3), 0x50, eeprom_buf); /* The AST2500 EVB expects a LM75 but a TMP105 is compatible */ - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7), + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), TYPE_TMP105, 0x4d); /* The AST2500 EVB does not have an RTC. Let's pretend that one is * plugged on the I2C bus header */ - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 0x32); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), "ds1338", 0x32); } -static void ast2600_evb_i2c_init(AspeedBoardState *bmc) +static void ast2600_evb_i2c_init(AspeedMachineState *bmc) { /* Start with some devices on our I2C busses */ ast2500_evb_i2c_init(bmc); } -static void romulus_bmc_i2c_init(AspeedBoardState *bmc) +static void romulus_bmc_i2c_init(AspeedMachineState *bmc) { AspeedSoCState *soc = &bmc->soc; /* The romulus board expects Epson RX8900 I2C RTC but a ds1338 is * good enough */ - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 0x32); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), "ds1338", 0x32); } -static void swift_bmc_i2c_init(AspeedBoardState *bmc) +static void swift_bmc_i2c_init(AspeedMachineState *bmc) { AspeedSoCState *soc = &bmc->soc; - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), "pca9552", 0x60); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 3), "pca9552", 0x60); /* The swift board expects a TMP275 but a TMP105 is compatible */ - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7), "tmp105", 0x48); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), "tmp105", 0x48); /* The swift board expects a pca9551 but a pca9552 is compatible */ - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7), "pca9552", 0x60); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), "pca9552", 0x60); /* The swift board expects an Epson RX8900 RTC but a ds1338 is compatible */ - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "ds1338", 0x32); - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "pca9552", 0x60); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), "ds1338", 0x32); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), "pca9552", 0x60); - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 9), "tmp423", 0x4c); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp423", 0x4c); /* The swift board expects a pca9539 but a pca9552 is compatible */ - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 9), "pca9552", 0x74); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "pca9552", 0x74); - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 10), "tmp423", 0x4c); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), "tmp423", 0x4c); /* The swift board expects a pca9539 but a pca9552 is compatible */ - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 10), "pca9552", + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), "pca9552", 0x74); /* The swift board expects a TMP275 but a TMP105 is compatible */ - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 12), "tmp105", 0x48); - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 12), "tmp105", 0x4a); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 12), "tmp105", 0x48); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 12), "tmp105", 0x4a); } -static void sonorapass_bmc_i2c_init(AspeedBoardState *bmc) +static void sonorapass_bmc_i2c_init(AspeedMachineState *bmc) { AspeedSoCState *soc = &bmc->soc; /* bus 2 : */ - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2), "tmp105", 0x48); - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2), "tmp105", 0x49); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 2), "tmp105", 0x48); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 2), "tmp105", 0x49); /* bus 2 : pca9546 @ 0x73 */ /* bus 3 : pca9548 @ 0x70 */ /* bus 4 : */ uint8_t *eeprom4_54 = g_malloc0(8 * 1024); - smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), 0x54, + smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 4), 0x54, eeprom4_54); /* PCA9539 @ 0x76, but PCA9552 is compatible */ - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "pca9552", 0x76); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), "pca9552", 0x76); /* PCA9539 @ 0x77, but PCA9552 is compatible */ - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "pca9552", 0x77); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), "pca9552", 0x77); /* bus 6 : */ - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 6), "tmp105", 0x48); - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 6), "tmp105", 0x49); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), "tmp105", 0x48); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), "tmp105", 0x49); /* bus 6 : pca9546 @ 0x73 */ /* bus 8 : */ uint8_t *eeprom8_56 = g_malloc0(8 * 1024); - smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), 0x56, + smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 8), 0x56, eeprom8_56); - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "pca9552", 0x60); - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "pca9552", 0x61); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), "pca9552", 0x60); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), "pca9552", 0x61); /* bus 8 : adc128d818 @ 0x1d */ /* bus 8 : adc128d818 @ 0x1f */ @@ -496,32 +524,58 @@ static void sonorapass_bmc_i2c_init(AspeedBoardState *bmc) } -static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc) +static void witherspoon_bmc_i2c_init(AspeedMachineState *bmc) { + static const struct { + unsigned gpio_id; + LEDColor color; + const char *description; + bool gpio_polarity; + } pca1_leds[] = { + {13, LED_COLOR_GREEN, "front-fault-4", GPIO_POLARITY_ACTIVE_LOW}, + {14, LED_COLOR_GREEN, "front-power-3", GPIO_POLARITY_ACTIVE_LOW}, + {15, LED_COLOR_GREEN, "front-id-5", GPIO_POLARITY_ACTIVE_LOW}, + }; AspeedSoCState *soc = &bmc->soc; uint8_t *eeprom_buf = g_malloc0(8 * 1024); + DeviceState *dev; + LEDState *led; /* Bus 3: TODO bmp280@77 */ /* Bus 3: TODO max31785@52 */ /* Bus 3: TODO dps310@76 */ - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), TYPE_PCA9552, - 0x60); + dev = DEVICE(i2c_slave_new(TYPE_PCA9552, 0x60)); + qdev_prop_set_string(dev, "description", "pca1"); + i2c_slave_realize_and_unref(I2C_SLAVE(dev), + aspeed_i2c_get_bus(&soc->i2c, 3), + &error_fatal); - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "tmp423", 0x4c); - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 5), "tmp423", 0x4c); + for (size_t i = 0; i < ARRAY_SIZE(pca1_leds); i++) { + led = led_create_simple(OBJECT(bmc), + pca1_leds[i].gpio_polarity, + pca1_leds[i].color, + pca1_leds[i].description); + qdev_connect_gpio_out(dev, pca1_leds[i].gpio_id, + qdev_get_gpio_in(DEVICE(led), 0)); + } + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), "tmp423", 0x4c); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), "tmp423", 0x4c); /* The Witherspoon expects a TMP275 but a TMP105 is compatible */ - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 9), TYPE_TMP105, + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), TYPE_TMP105, 0x4a); /* The witherspoon board expects Epson RX8900 I2C RTC but a ds1338 is * good enough */ - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 0x32); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), "ds1338", 0x32); - smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), 0x51, + smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 11), 0x51, eeprom_buf); - i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), TYPE_PCA9552, - 0x60); + dev = DEVICE(i2c_slave_new(TYPE_PCA9552, 0x60)); + qdev_prop_set_string(dev, "description", "pca0"); + i2c_slave_realize_and_unref(I2C_SLAVE(dev), + aspeed_i2c_get_bus(&soc->i2c, 11), + &error_fatal); /* Bus 11: TODO ucd90160@64 */ } @@ -540,6 +594,34 @@ static void aspeed_machine_instance_init(Object *obj) ASPEED_MACHINE(obj)->mmio_exec = false; } +static char *aspeed_get_fmc_model(Object *obj, Error **errp) +{ + AspeedMachineState *bmc = ASPEED_MACHINE(obj); + return g_strdup(bmc->fmc_model); +} + +static void aspeed_set_fmc_model(Object *obj, const char *value, Error **errp) +{ + AspeedMachineState *bmc = ASPEED_MACHINE(obj); + + g_free(bmc->fmc_model); + bmc->fmc_model = g_strdup(value); +} + +static char *aspeed_get_spi_model(Object *obj, Error **errp) +{ + AspeedMachineState *bmc = ASPEED_MACHINE(obj); + return g_strdup(bmc->spi_model); +} + +static void aspeed_set_spi_model(Object *obj, const char *value, Error **errp) +{ + AspeedMachineState *bmc = ASPEED_MACHINE(obj); + + g_free(bmc->spi_model); + bmc->spi_model = g_strdup(value); +} + static void aspeed_machine_class_props_init(ObjectClass *oc) { object_class_property_add_bool(oc, "execute-in-place", @@ -547,18 +629,34 @@ static void aspeed_machine_class_props_init(ObjectClass *oc) aspeed_set_mmio_exec); object_class_property_set_description(oc, "execute-in-place", "boot directly from CE0 flash device"); + + object_class_property_add_str(oc, "fmc-model", aspeed_get_fmc_model, + aspeed_set_fmc_model); + object_class_property_set_description(oc, "fmc-model", + "Change the FMC Flash model"); + object_class_property_add_str(oc, "spi-model", aspeed_get_spi_model, + aspeed_set_spi_model); + object_class_property_set_description(oc, "spi-model", + "Change the SPI Flash model"); +} + +static int aspeed_soc_num_cpus(const char *soc_name) +{ + AspeedSoCClass *sc = ASPEED_SOC_CLASS(object_class_by_name(soc_name)); + return sc->num_cpus; } static void aspeed_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); + AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); mc->init = aspeed_machine_init; - mc->max_cpus = ASPEED_CPUS_NUM; mc->no_floppy = 1; mc->no_cdrom = 1; mc->no_parallel = 1; mc->default_ram_id = "ram"; + amc->macs_mask = ASPEED_MAC0_ON; aspeed_machine_class_props_init(oc); } @@ -576,8 +674,27 @@ static void aspeed_machine_palmetto_class_init(ObjectClass *oc, void *data) amc->num_cs = 1; amc->i2c_init = palmetto_bmc_i2c_init; mc->default_ram_size = 256 * MiB; + mc->default_cpus = mc->min_cpus = mc->max_cpus = + aspeed_soc_num_cpus(amc->soc_name); }; +static void aspeed_machine_supermicrox11_bmc_class_init(ObjectClass *oc, + void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); + + mc->desc = "Supermicro X11 BMC (ARM926EJ-S)"; + amc->soc_name = "ast2400-a1"; + amc->hw_strap1 = SUPERMICROX11_BMC_HW_STRAP1; + amc->fmc_model = "mx25l25635e"; + amc->spi_model = "mx25l25635e"; + amc->num_cs = 1; + amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON; + amc->i2c_init = palmetto_bmc_i2c_init; + mc->default_ram_size = 256 * MiB; +} + static void aspeed_machine_ast2500_evb_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -591,6 +708,8 @@ static void aspeed_machine_ast2500_evb_class_init(ObjectClass *oc, void *data) amc->num_cs = 1; amc->i2c_init = ast2500_evb_i2c_init; mc->default_ram_size = 512 * MiB; + mc->default_cpus = mc->min_cpus = mc->max_cpus = + aspeed_soc_num_cpus(amc->soc_name); }; static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data) @@ -606,6 +725,8 @@ static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data) amc->num_cs = 2; amc->i2c_init = romulus_bmc_i2c_init; mc->default_ram_size = 512 * MiB; + mc->default_cpus = mc->min_cpus = mc->max_cpus = + aspeed_soc_num_cpus(amc->soc_name); }; static void aspeed_machine_sonorapass_class_init(ObjectClass *oc, void *data) @@ -621,6 +742,8 @@ static void aspeed_machine_sonorapass_class_init(ObjectClass *oc, void *data) amc->num_cs = 2; amc->i2c_init = sonorapass_bmc_i2c_init; mc->default_ram_size = 512 * MiB; + mc->default_cpus = mc->min_cpus = mc->max_cpus = + aspeed_soc_num_cpus(amc->soc_name); }; static void aspeed_machine_swift_class_init(ObjectClass *oc, void *data) @@ -636,6 +759,8 @@ static void aspeed_machine_swift_class_init(ObjectClass *oc, void *data) amc->num_cs = 2; amc->i2c_init = swift_bmc_i2c_init; mc->default_ram_size = 512 * MiB; + mc->default_cpus = mc->min_cpus = mc->max_cpus = + aspeed_soc_num_cpus(amc->soc_name); }; static void aspeed_machine_witherspoon_class_init(ObjectClass *oc, void *data) @@ -651,6 +776,8 @@ static void aspeed_machine_witherspoon_class_init(ObjectClass *oc, void *data) amc->num_cs = 2; amc->i2c_init = witherspoon_bmc_i2c_init; mc->default_ram_size = 512 * MiB; + mc->default_cpus = mc->min_cpus = mc->max_cpus = + aspeed_soc_num_cpus(amc->soc_name); }; static void aspeed_machine_ast2600_evb_class_init(ObjectClass *oc, void *data) @@ -665,8 +792,11 @@ static void aspeed_machine_ast2600_evb_class_init(ObjectClass *oc, void *data) amc->fmc_model = "w25q512jv"; amc->spi_model = "mx66u51235f"; amc->num_cs = 1; + amc->macs_mask = ASPEED_MAC1_ON | ASPEED_MAC2_ON | ASPEED_MAC3_ON; amc->i2c_init = ast2600_evb_i2c_init; mc->default_ram_size = 1 * GiB; + mc->default_cpus = mc->min_cpus = mc->max_cpus = + aspeed_soc_num_cpus(amc->soc_name); }; static void aspeed_machine_tacoma_class_init(ObjectClass *oc, void *data) @@ -681,8 +811,11 @@ static void aspeed_machine_tacoma_class_init(ObjectClass *oc, void *data) amc->fmc_model = "mx66l1g45g"; amc->spi_model = "mx66l1g45g"; amc->num_cs = 2; + amc->macs_mask = ASPEED_MAC2_ON; amc->i2c_init = witherspoon_bmc_i2c_init; /* Same board layout */ mc->default_ram_size = 1 * GiB; + mc->default_cpus = mc->min_cpus = mc->max_cpus = + aspeed_soc_num_cpus(amc->soc_name); }; static const TypeInfo aspeed_machine_types[] = { @@ -690,6 +823,10 @@ static const TypeInfo aspeed_machine_types[] = { .name = MACHINE_TYPE_NAME("palmetto-bmc"), .parent = TYPE_ASPEED_MACHINE, .class_init = aspeed_machine_palmetto_class_init, + }, { + .name = MACHINE_TYPE_NAME("supermicrox11-bmc"), + .parent = TYPE_ASPEED_MACHINE, + .class_init = aspeed_machine_supermicrox11_bmc_class_init, }, { .name = MACHINE_TYPE_NAME("ast2500-evb"), .parent = TYPE_ASPEED_MACHINE, @@ -721,7 +858,7 @@ static const TypeInfo aspeed_machine_types[] = { }, { .name = TYPE_ASPEED_MACHINE, .parent = TYPE_MACHINE, - .instance_size = sizeof(AspeedMachine), + .instance_size = sizeof(AspeedMachineState), .instance_init = aspeed_machine_instance_init, .class_size = sizeof(AspeedMachineClass), .class_init = aspeed_machine_class_init, diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index 71a0acfe267d553611225aeac9ccb279da511d7b..1450bde7cf26e0bd999e000d40f7d0db4e111248 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -24,43 +24,43 @@ #define ASPEED_SOC_IOMEM_SIZE 0x00200000 static const hwaddr aspeed_soc_ast2600_memmap[] = { - [ASPEED_SRAM] = 0x10000000, + [ASPEED_DEV_SRAM] = 0x10000000, /* 0x16000000 0x17FFFFFF : AHB BUS do LPC Bus bridge */ - [ASPEED_IOMEM] = 0x1E600000, - [ASPEED_PWM] = 0x1E610000, - [ASPEED_FMC] = 0x1E620000, - [ASPEED_SPI1] = 0x1E630000, - [ASPEED_SPI2] = 0x1E641000, - [ASPEED_EHCI1] = 0x1E6A1000, - [ASPEED_EHCI2] = 0x1E6A3000, - [ASPEED_MII1] = 0x1E650000, - [ASPEED_MII2] = 0x1E650008, - [ASPEED_MII3] = 0x1E650010, - [ASPEED_MII4] = 0x1E650018, - [ASPEED_ETH1] = 0x1E660000, - [ASPEED_ETH3] = 0x1E670000, - [ASPEED_ETH2] = 0x1E680000, - [ASPEED_ETH4] = 0x1E690000, - [ASPEED_VIC] = 0x1E6C0000, - [ASPEED_SDMC] = 0x1E6E0000, - [ASPEED_SCU] = 0x1E6E2000, - [ASPEED_XDMA] = 0x1E6E7000, - [ASPEED_ADC] = 0x1E6E9000, - [ASPEED_VIDEO] = 0x1E700000, - [ASPEED_SDHCI] = 0x1E740000, - [ASPEED_EMMC] = 0x1E750000, - [ASPEED_GPIO] = 0x1E780000, - [ASPEED_GPIO_1_8V] = 0x1E780800, - [ASPEED_RTC] = 0x1E781000, - [ASPEED_TIMER1] = 0x1E782000, - [ASPEED_WDT] = 0x1E785000, - [ASPEED_LPC] = 0x1E789000, - [ASPEED_IBT] = 0x1E789140, - [ASPEED_I2C] = 0x1E78A000, - [ASPEED_UART1] = 0x1E783000, - [ASPEED_UART5] = 0x1E784000, - [ASPEED_VUART] = 0x1E787000, - [ASPEED_SDRAM] = 0x80000000, + [ASPEED_DEV_IOMEM] = 0x1E600000, + [ASPEED_DEV_PWM] = 0x1E610000, + [ASPEED_DEV_FMC] = 0x1E620000, + [ASPEED_DEV_SPI1] = 0x1E630000, + [ASPEED_DEV_SPI2] = 0x1E641000, + [ASPEED_DEV_EHCI1] = 0x1E6A1000, + [ASPEED_DEV_EHCI2] = 0x1E6A3000, + [ASPEED_DEV_MII1] = 0x1E650000, + [ASPEED_DEV_MII2] = 0x1E650008, + [ASPEED_DEV_MII3] = 0x1E650010, + [ASPEED_DEV_MII4] = 0x1E650018, + [ASPEED_DEV_ETH1] = 0x1E660000, + [ASPEED_DEV_ETH3] = 0x1E670000, + [ASPEED_DEV_ETH2] = 0x1E680000, + [ASPEED_DEV_ETH4] = 0x1E690000, + [ASPEED_DEV_VIC] = 0x1E6C0000, + [ASPEED_DEV_SDMC] = 0x1E6E0000, + [ASPEED_DEV_SCU] = 0x1E6E2000, + [ASPEED_DEV_XDMA] = 0x1E6E7000, + [ASPEED_DEV_ADC] = 0x1E6E9000, + [ASPEED_DEV_VIDEO] = 0x1E700000, + [ASPEED_DEV_SDHCI] = 0x1E740000, + [ASPEED_DEV_EMMC] = 0x1E750000, + [ASPEED_DEV_GPIO] = 0x1E780000, + [ASPEED_DEV_GPIO_1_8V] = 0x1E780800, + [ASPEED_DEV_RTC] = 0x1E781000, + [ASPEED_DEV_TIMER1] = 0x1E782000, + [ASPEED_DEV_WDT] = 0x1E785000, + [ASPEED_DEV_LPC] = 0x1E789000, + [ASPEED_DEV_IBT] = 0x1E789140, + [ASPEED_DEV_I2C] = 0x1E78A000, + [ASPEED_DEV_UART1] = 0x1E783000, + [ASPEED_DEV_UART5] = 0x1E784000, + [ASPEED_DEV_VUART] = 0x1E787000, + [ASPEED_DEV_SDRAM] = 0x80000000, }; #define ASPEED_A7MPCORE_ADDR 0x40460000 @@ -69,41 +69,41 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { /* Shared Peripheral Interrupt values below are offset by -32 from datasheet */ static const int aspeed_soc_ast2600_irqmap[] = { - [ASPEED_UART1] = 47, - [ASPEED_UART2] = 48, - [ASPEED_UART3] = 49, - [ASPEED_UART4] = 50, - [ASPEED_UART5] = 8, - [ASPEED_VUART] = 8, - [ASPEED_FMC] = 39, - [ASPEED_SDMC] = 0, - [ASPEED_SCU] = 12, - [ASPEED_ADC] = 78, - [ASPEED_XDMA] = 6, - [ASPEED_SDHCI] = 43, - [ASPEED_EHCI1] = 5, - [ASPEED_EHCI2] = 9, - [ASPEED_EMMC] = 15, - [ASPEED_GPIO] = 40, - [ASPEED_GPIO_1_8V] = 11, - [ASPEED_RTC] = 13, - [ASPEED_TIMER1] = 16, - [ASPEED_TIMER2] = 17, - [ASPEED_TIMER3] = 18, - [ASPEED_TIMER4] = 19, - [ASPEED_TIMER5] = 20, - [ASPEED_TIMER6] = 21, - [ASPEED_TIMER7] = 22, - [ASPEED_TIMER8] = 23, - [ASPEED_WDT] = 24, - [ASPEED_PWM] = 44, - [ASPEED_LPC] = 35, - [ASPEED_IBT] = 35, /* LPC */ - [ASPEED_I2C] = 110, /* 110 -> 125 */ - [ASPEED_ETH1] = 2, - [ASPEED_ETH2] = 3, - [ASPEED_ETH3] = 32, - [ASPEED_ETH4] = 33, + [ASPEED_DEV_UART1] = 47, + [ASPEED_DEV_UART2] = 48, + [ASPEED_DEV_UART3] = 49, + [ASPEED_DEV_UART4] = 50, + [ASPEED_DEV_UART5] = 8, + [ASPEED_DEV_VUART] = 8, + [ASPEED_DEV_FMC] = 39, + [ASPEED_DEV_SDMC] = 0, + [ASPEED_DEV_SCU] = 12, + [ASPEED_DEV_ADC] = 78, + [ASPEED_DEV_XDMA] = 6, + [ASPEED_DEV_SDHCI] = 43, + [ASPEED_DEV_EHCI1] = 5, + [ASPEED_DEV_EHCI2] = 9, + [ASPEED_DEV_EMMC] = 15, + [ASPEED_DEV_GPIO] = 40, + [ASPEED_DEV_GPIO_1_8V] = 11, + [ASPEED_DEV_RTC] = 13, + [ASPEED_DEV_TIMER1] = 16, + [ASPEED_DEV_TIMER2] = 17, + [ASPEED_DEV_TIMER3] = 18, + [ASPEED_DEV_TIMER4] = 19, + [ASPEED_DEV_TIMER5] = 20, + [ASPEED_DEV_TIMER6] = 21, + [ASPEED_DEV_TIMER7] = 22, + [ASPEED_DEV_TIMER8] = 23, + [ASPEED_DEV_WDT] = 24, + [ASPEED_DEV_PWM] = 44, + [ASPEED_DEV_LPC] = 35, + [ASPEED_DEV_IBT] = 35, /* LPC */ + [ASPEED_DEV_I2C] = 110, /* 110 -> 125 */ + [ASPEED_DEV_ETH1] = 2, + [ASPEED_DEV_ETH2] = 3, + [ASPEED_DEV_ETH3] = 32, + [ASPEED_DEV_ETH4] = 33, }; @@ -127,14 +127,11 @@ static void aspeed_soc_ast2600_init(Object *obj) } for (i = 0; i < sc->num_cpus; i++) { - object_initialize_child(obj, "cpu[*]", OBJECT(&s->cpu[i]), - sizeof(s->cpu[i]), sc->cpu_type, - &error_abort, NULL); + object_initialize_child(obj, "cpu[*]", &s->cpu[i], sc->cpu_type); } snprintf(typename, sizeof(typename), "aspeed.scu-%s", socname); - sysbus_init_child_obj(obj, "scu", OBJECT(&s->scu), sizeof(s->scu), - typename); + object_initialize_child(obj, "scu", &s->scu, typename); qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev", sc->silicon_rev); object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu), @@ -144,39 +141,33 @@ static void aspeed_soc_ast2600_init(Object *obj) object_property_add_alias(obj, "hw-prot-key", OBJECT(&s->scu), "hw-prot-key"); - sysbus_init_child_obj(obj, "a7mpcore", &s->a7mpcore, - sizeof(s->a7mpcore), TYPE_A15MPCORE_PRIV); + object_initialize_child(obj, "a7mpcore", &s->a7mpcore, + TYPE_A15MPCORE_PRIV); - sysbus_init_child_obj(obj, "rtc", OBJECT(&s->rtc), sizeof(s->rtc), - TYPE_ASPEED_RTC); + object_initialize_child(obj, "rtc", &s->rtc, TYPE_ASPEED_RTC); snprintf(typename, sizeof(typename), "aspeed.timer-%s", socname); - sysbus_init_child_obj(obj, "timerctrl", OBJECT(&s->timerctrl), - sizeof(s->timerctrl), typename); + object_initialize_child(obj, "timerctrl", &s->timerctrl, typename); snprintf(typename, sizeof(typename), "aspeed.i2c-%s", socname); - sysbus_init_child_obj(obj, "i2c", OBJECT(&s->i2c), sizeof(s->i2c), - typename); + object_initialize_child(obj, "i2c", &s->i2c, typename); snprintf(typename, sizeof(typename), "aspeed.fmc-%s", socname); - sysbus_init_child_obj(obj, "fmc", OBJECT(&s->fmc), sizeof(s->fmc), - typename); + object_initialize_child(obj, "fmc", &s->fmc, typename); object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs"); for (i = 0; i < sc->spis_num; i++) { snprintf(typename, sizeof(typename), "aspeed.spi%d-%s", i + 1, socname); - sysbus_init_child_obj(obj, "spi[*]", OBJECT(&s->spi[i]), - sizeof(s->spi[i]), typename); + object_initialize_child(obj, "spi[*]", &s->spi[i], typename); } for (i = 0; i < sc->ehcis_num; i++) { - sysbus_init_child_obj(obj, "ehci[*]", OBJECT(&s->ehci[i]), - sizeof(s->ehci[i]), TYPE_PLATFORM_EHCI); + object_initialize_child(obj, "ehci[*]", &s->ehci[i], + TYPE_PLATFORM_EHCI); } snprintf(typename, sizeof(typename), "aspeed.sdmc-%s", socname); - sysbus_init_child_obj(obj, "sdmc", OBJECT(&s->sdmc), sizeof(s->sdmc), - typename); + object_initialize_child(obj, "sdmc", &s->sdmc, typename); object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc), "ram-size"); object_property_add_alias(obj, "max-ram-size", OBJECT(&s->sdmc), @@ -184,49 +175,42 @@ static void aspeed_soc_ast2600_init(Object *obj) for (i = 0; i < sc->wdts_num; i++) { snprintf(typename, sizeof(typename), "aspeed.wdt-%s", socname); - sysbus_init_child_obj(obj, "wdt[*]", OBJECT(&s->wdt[i]), - sizeof(s->wdt[i]), typename); + object_initialize_child(obj, "wdt[*]", &s->wdt[i], typename); } for (i = 0; i < sc->macs_num; i++) { - sysbus_init_child_obj(obj, "ftgmac100[*]", OBJECT(&s->ftgmac100[i]), - sizeof(s->ftgmac100[i]), TYPE_FTGMAC100); + object_initialize_child(obj, "ftgmac100[*]", &s->ftgmac100[i], + TYPE_FTGMAC100); - sysbus_init_child_obj(obj, "mii[*]", &s->mii[i], sizeof(s->mii[i]), - TYPE_ASPEED_MII); + object_initialize_child(obj, "mii[*]", &s->mii[i], TYPE_ASPEED_MII); } - sysbus_init_child_obj(obj, "xdma", OBJECT(&s->xdma), sizeof(s->xdma), - TYPE_ASPEED_XDMA); + object_initialize_child(obj, "xdma", &s->xdma, TYPE_ASPEED_XDMA); snprintf(typename, sizeof(typename), "aspeed.gpio-%s", socname); - sysbus_init_child_obj(obj, "gpio", OBJECT(&s->gpio), sizeof(s->gpio), - typename); + object_initialize_child(obj, "gpio", &s->gpio, typename); snprintf(typename, sizeof(typename), "aspeed.gpio-%s-1_8v", socname); - sysbus_init_child_obj(obj, "gpio_1_8v", OBJECT(&s->gpio_1_8v), - sizeof(s->gpio_1_8v), typename); + object_initialize_child(obj, "gpio_1_8v", &s->gpio_1_8v, typename); - sysbus_init_child_obj(obj, "sd-controller", OBJECT(&s->sdhci), - sizeof(s->sdhci), TYPE_ASPEED_SDHCI); + object_initialize_child(obj, "sd-controller", &s->sdhci, + TYPE_ASPEED_SDHCI); - object_property_set_int(OBJECT(&s->sdhci), 2, "num-slots", &error_abort); + object_property_set_int(OBJECT(&s->sdhci), "num-slots", 2, &error_abort); /* Init sd card slot class here so that they're under the correct parent */ for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) { - sysbus_init_child_obj(obj, "sd-controller.sdhci[*]", - OBJECT(&s->sdhci.slots[i]), - sizeof(s->sdhci.slots[i]), TYPE_SYSBUS_SDHCI); + object_initialize_child(obj, "sd-controller.sdhci[*]", + &s->sdhci.slots[i], TYPE_SYSBUS_SDHCI); } - sysbus_init_child_obj(obj, "emmc-controller", OBJECT(&s->emmc), - sizeof(s->emmc), TYPE_ASPEED_SDHCI); + object_initialize_child(obj, "emmc-controller", &s->emmc, + TYPE_ASPEED_SDHCI); - object_property_set_int(OBJECT(&s->emmc), 1, "num-slots", &error_abort); + object_property_set_int(OBJECT(&s->emmc), "num-slots", 1, &error_abort); - sysbus_init_child_obj(obj, "emmc-controller.sdhci", - OBJECT(&s->emmc.slots[0]), sizeof(s->emmc.slots[0]), - TYPE_SYSBUS_SDHCI); + object_initialize_child(obj, "emmc-controller.sdhci", &s->emmc.slots[0], + TYPE_SYSBUS_SDHCI); } /* @@ -244,36 +228,29 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) int i; AspeedSoCState *s = ASPEED_SOC(dev); AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); - Error *err = NULL, *local_err = NULL; + Error *err = NULL; qemu_irq irq; /* IO space */ - create_unimplemented_device("aspeed_soc.io", sc->memmap[ASPEED_IOMEM], + create_unimplemented_device("aspeed_soc.io", sc->memmap[ASPEED_DEV_IOMEM], ASPEED_SOC_IOMEM_SIZE); /* Video engine stub */ - create_unimplemented_device("aspeed.video", sc->memmap[ASPEED_VIDEO], + create_unimplemented_device("aspeed.video", sc->memmap[ASPEED_DEV_VIDEO], 0x1000); - if (s->num_cpus > sc->num_cpus) { - warn_report("%s: invalid number of CPUs %d, using default %d", - sc->name, s->num_cpus, sc->num_cpus); - s->num_cpus = sc->num_cpus; - } - /* CPU */ - for (i = 0; i < s->num_cpus; i++) { - object_property_set_int(OBJECT(&s->cpu[i]), QEMU_PSCI_CONDUIT_SMC, - "psci-conduit", &error_abort); - if (s->num_cpus > 1) { - object_property_set_int(OBJECT(&s->cpu[i]), - ASPEED_A7MPCORE_ADDR, - "reset-cbar", &error_abort); + for (i = 0; i < sc->num_cpus; i++) { + object_property_set_int(OBJECT(&s->cpu[i]), "psci-conduit", + QEMU_PSCI_CONDUIT_SMC, &error_abort); + if (sc->num_cpus > 1) { + object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar", + ASPEED_A7MPCORE_ADDR, &error_abort); } - object_property_set_int(OBJECT(&s->cpu[i]), aspeed_calc_affinity(i), - "mp-affinity", &error_abort); + object_property_set_int(OBJECT(&s->cpu[i]), "mp-affinity", + aspeed_calc_affinity(i), &error_abort); - object_property_set_int(OBJECT(&s->cpu[i]), 1125000000, "cntfrq", + object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 1125000000, &error_abort); /* @@ -281,36 +258,33 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) * is needed when using -kernel */ - object_property_set_bool(OBJECT(&s->cpu[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) { return; } } /* A7MPCORE */ - object_property_set_int(OBJECT(&s->a7mpcore), s->num_cpus, "num-cpu", + object_property_set_int(OBJECT(&s->a7mpcore), "num-cpu", sc->num_cpus, &error_abort); - object_property_set_int(OBJECT(&s->a7mpcore), + object_property_set_int(OBJECT(&s->a7mpcore), "num-irq", ASPEED_SOC_AST2600_MAX_IRQ + GIC_INTERNAL, - "num-irq", &error_abort); + &error_abort); - object_property_set_bool(OBJECT(&s->a7mpcore), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->a7mpcore), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->a7mpcore), 0, ASPEED_A7MPCORE_ADDR); - for (i = 0; i < s->num_cpus; i++) { + for (i = 0; i < sc->num_cpus; i++) { SysBusDevice *sbd = SYS_BUS_DEVICE(&s->a7mpcore); DeviceState *d = DEVICE(qemu_get_cpu(i)); irq = qdev_get_gpio_in(d, ARM_CPU_IRQ); sysbus_connect_irq(sbd, i, irq); irq = qdev_get_gpio_in(d, ARM_CPU_FIQ); - sysbus_connect_irq(sbd, i + s->num_cpus, irq); + sysbus_connect_irq(sbd, i + sc->num_cpus, irq); irq = qdev_get_gpio_in(d, ARM_CPU_VIRQ); - sysbus_connect_irq(sbd, i + 2 * s->num_cpus, irq); + sysbus_connect_irq(sbd, i + 2 * sc->num_cpus, irq); irq = qdev_get_gpio_in(d, ARM_CPU_VFIQ); - sysbus_connect_irq(sbd, i + 3 * s->num_cpus, irq); + sysbus_connect_irq(sbd, i + 3 * sc->num_cpus, irq); } /* SRAM */ @@ -321,63 +295,50 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) return; } memory_region_add_subregion(get_system_memory(), - sc->memmap[ASPEED_SRAM], &s->sram); + sc->memmap[ASPEED_DEV_SRAM], &s->sram); /* SCU */ - object_property_set_bool(OBJECT(&s->scu), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) { return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, sc->memmap[ASPEED_SCU]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, sc->memmap[ASPEED_DEV_SCU]); /* RTC */ - object_property_set_bool(OBJECT(&s->rtc), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->rtc), errp)) { return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, sc->memmap[ASPEED_RTC]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, sc->memmap[ASPEED_DEV_RTC]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0, - aspeed_soc_get_irq(s, ASPEED_RTC)); + aspeed_soc_get_irq(s, ASPEED_DEV_RTC)); /* Timer */ - object_property_set_link(OBJECT(&s->timerctrl), - OBJECT(&s->scu), "scu", &error_abort); - object_property_set_bool(OBJECT(&s->timerctrl), true, "realized", &err); - if (err) { - error_propagate(errp, err); + object_property_set_link(OBJECT(&s->timerctrl), "scu", OBJECT(&s->scu), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->timerctrl), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->timerctrl), 0, - sc->memmap[ASPEED_TIMER1]); + sc->memmap[ASPEED_DEV_TIMER1]); for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) { - qemu_irq irq = aspeed_soc_get_irq(s, ASPEED_TIMER1 + i); + qemu_irq irq = aspeed_soc_get_irq(s, ASPEED_DEV_TIMER1 + i); sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq); } /* UART - attach an 8250 to the IO space as our UART5 */ - if (serial_hd(0)) { - qemu_irq uart5 = aspeed_soc_get_irq(s, ASPEED_UART5); - serial_mm_init(get_system_memory(), sc->memmap[ASPEED_UART5], 2, - uart5, 38400, serial_hd(0), DEVICE_LITTLE_ENDIAN); - } + serial_mm_init(get_system_memory(), sc->memmap[ASPEED_DEV_UART5], 2, + aspeed_soc_get_irq(s, ASPEED_DEV_UART5), + 38400, serial_hd(0), DEVICE_LITTLE_ENDIAN); /* I2C */ - object_property_set_link(OBJECT(&s->i2c), OBJECT(s->dram_mr), "dram", &err); - if (err) { - error_propagate(errp, err); - return; - } - object_property_set_bool(OBJECT(&s->i2c), true, "realized", &err); - if (err) { - error_propagate(errp, err); + object_property_set_link(OBJECT(&s->i2c), "dram", OBJECT(s->dram_mr), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c), errp)) { return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, sc->memmap[ASPEED_I2C]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, sc->memmap[ASPEED_DEV_I2C]); for (i = 0; i < ASPEED_I2C_GET_CLASS(&s->i2c)->num_busses; i++) { qemu_irq irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), - sc->irqmap[ASPEED_I2C] + i); + sc->irqmap[ASPEED_DEV_I2C] + i); /* * The AST2600 SoC has one IRQ per I2C bus. Skip the common * IRQ (AST2400 and AST2500) and connect all bussses. @@ -386,167 +347,128 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) } /* FMC, The number of CS is set at the board level */ - object_property_set_link(OBJECT(&s->fmc), OBJECT(s->dram_mr), "dram", &err); - if (err) { - error_propagate(errp, err); - return; - } - object_property_set_int(OBJECT(&s->fmc), sc->memmap[ASPEED_SDRAM], - "sdram-base", &err); - if (err) { - error_propagate(errp, err); + object_property_set_link(OBJECT(&s->fmc), "dram", OBJECT(s->dram_mr), + &error_abort); + if (!object_property_set_int(OBJECT(&s->fmc), "sdram-base", + sc->memmap[ASPEED_DEV_SDRAM], errp)) { return; } - object_property_set_bool(OBJECT(&s->fmc), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->fmc), errp)) { return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 0, sc->memmap[ASPEED_FMC]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 0, sc->memmap[ASPEED_DEV_FMC]); sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 1, s->fmc.ctrl->flash_window_base); sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0, - aspeed_soc_get_irq(s, ASPEED_FMC)); + aspeed_soc_get_irq(s, ASPEED_DEV_FMC)); /* SPI */ for (i = 0; i < sc->spis_num; i++) { - object_property_set_link(OBJECT(&s->spi[i]), OBJECT(s->dram_mr), - "dram", &err); - if (err) { - error_propagate(errp, err); - return; - } - object_property_set_int(OBJECT(&s->spi[i]), 1, "num-cs", &err); - object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", - &local_err); - error_propagate(&err, local_err); - if (err) { - error_propagate(errp, err); + object_property_set_link(OBJECT(&s->spi[i]), "dram", + OBJECT(s->dram_mr), &error_abort); + object_property_set_int(OBJECT(&s->spi[i]), "num-cs", 1, &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, - sc->memmap[ASPEED_SPI1 + i]); + sc->memmap[ASPEED_DEV_SPI1 + i]); sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 1, s->spi[i].ctrl->flash_window_base); } /* EHCI */ for (i = 0; i < sc->ehcis_num; i++) { - object_property_set_bool(OBJECT(&s->ehci[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->ehci[i]), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->ehci[i]), 0, - sc->memmap[ASPEED_EHCI1 + i]); + sc->memmap[ASPEED_DEV_EHCI1 + i]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci[i]), 0, - aspeed_soc_get_irq(s, ASPEED_EHCI1 + i)); + aspeed_soc_get_irq(s, ASPEED_DEV_EHCI1 + i)); } /* SDMC - SDRAM Memory Controller */ - object_property_set_bool(OBJECT(&s->sdmc), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdmc), errp)) { return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, sc->memmap[ASPEED_SDMC]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, sc->memmap[ASPEED_DEV_SDMC]); /* Watch dog */ for (i = 0; i < sc->wdts_num; i++) { AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(&s->wdt[i]); - object_property_set_link(OBJECT(&s->wdt[i]), - OBJECT(&s->scu), "scu", &error_abort); - object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + object_property_set_link(OBJECT(&s->wdt[i]), "scu", OBJECT(&s->scu), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, - sc->memmap[ASPEED_WDT] + i * awc->offset); + sc->memmap[ASPEED_DEV_WDT] + i * awc->offset); } /* Net */ - for (i = 0; i < nb_nics && i < sc->macs_num; i++) { - qdev_set_nic_properties(DEVICE(&s->ftgmac100[i]), &nd_table[i]); - object_property_set_bool(OBJECT(&s->ftgmac100[i]), true, "aspeed", - &err); - object_property_set_bool(OBJECT(&s->ftgmac100[i]), true, "realized", - &local_err); - error_propagate(&err, local_err); - if (err) { - error_propagate(errp, err); - return; + for (i = 0; i < sc->macs_num; i++) { + object_property_set_bool(OBJECT(&s->ftgmac100[i]), "aspeed", true, + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->ftgmac100[i]), errp)) { + return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->ftgmac100[i]), 0, - sc->memmap[ASPEED_ETH1 + i]); + sc->memmap[ASPEED_DEV_ETH1 + i]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->ftgmac100[i]), 0, - aspeed_soc_get_irq(s, ASPEED_ETH1 + i)); - - object_property_set_link(OBJECT(&s->mii[i]), OBJECT(&s->ftgmac100[i]), - "nic", &error_abort); - object_property_set_bool(OBJECT(&s->mii[i]), true, "realized", - &err); - if (err) { - error_propagate(errp, err); + aspeed_soc_get_irq(s, ASPEED_DEV_ETH1 + i)); + + object_property_set_link(OBJECT(&s->mii[i]), "nic", + OBJECT(&s->ftgmac100[i]), &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->mii[i]), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->mii[i]), 0, - sc->memmap[ASPEED_MII1 + i]); + sc->memmap[ASPEED_DEV_MII1 + i]); } /* XDMA */ - object_property_set_bool(OBJECT(&s->xdma), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->xdma), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->xdma), 0, - sc->memmap[ASPEED_XDMA]); + sc->memmap[ASPEED_DEV_XDMA]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->xdma), 0, - aspeed_soc_get_irq(s, ASPEED_XDMA)); + aspeed_soc_get_irq(s, ASPEED_DEV_XDMA)); /* GPIO */ - object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) { return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio), 0, sc->memmap[ASPEED_GPIO]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio), 0, sc->memmap[ASPEED_DEV_GPIO]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0, - aspeed_soc_get_irq(s, ASPEED_GPIO)); + aspeed_soc_get_irq(s, ASPEED_DEV_GPIO)); - object_property_set_bool(OBJECT(&s->gpio_1_8v), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio_1_8v), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio_1_8v), 0, - sc->memmap[ASPEED_GPIO_1_8V]); + sc->memmap[ASPEED_DEV_GPIO_1_8V]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio_1_8v), 0, - aspeed_soc_get_irq(s, ASPEED_GPIO_1_8V)); + aspeed_soc_get_irq(s, ASPEED_DEV_GPIO_1_8V)); /* SDHCI */ - object_property_set_bool(OBJECT(&s->sdhci), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdhci), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci), 0, - sc->memmap[ASPEED_SDHCI]); + sc->memmap[ASPEED_DEV_SDHCI]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0, - aspeed_soc_get_irq(s, ASPEED_SDHCI)); + aspeed_soc_get_irq(s, ASPEED_DEV_SDHCI)); /* eMMC */ - object_property_set_bool(OBJECT(&s->emmc), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->emmc), errp)) { return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->emmc), 0, sc->memmap[ASPEED_EMMC]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->emmc), 0, sc->memmap[ASPEED_DEV_EMMC]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->emmc), 0, - aspeed_soc_get_irq(s, ASPEED_EMMC)); + aspeed_soc_get_irq(s, ASPEED_DEV_EMMC)); } static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data) diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index cf6b6dd116a41ae3148f38fb4cbad089eabe1ab8..7eefd54ac07a7a41f48466848386455dad62064d 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -27,97 +27,97 @@ #define ASPEED_SOC_IOMEM_SIZE 0x00200000 static const hwaddr aspeed_soc_ast2400_memmap[] = { - [ASPEED_IOMEM] = 0x1E600000, - [ASPEED_FMC] = 0x1E620000, - [ASPEED_SPI1] = 0x1E630000, - [ASPEED_EHCI1] = 0x1E6A1000, - [ASPEED_VIC] = 0x1E6C0000, - [ASPEED_SDMC] = 0x1E6E0000, - [ASPEED_SCU] = 0x1E6E2000, - [ASPEED_XDMA] = 0x1E6E7000, - [ASPEED_VIDEO] = 0x1E700000, - [ASPEED_ADC] = 0x1E6E9000, - [ASPEED_SRAM] = 0x1E720000, - [ASPEED_SDHCI] = 0x1E740000, - [ASPEED_GPIO] = 0x1E780000, - [ASPEED_RTC] = 0x1E781000, - [ASPEED_TIMER1] = 0x1E782000, - [ASPEED_WDT] = 0x1E785000, - [ASPEED_PWM] = 0x1E786000, - [ASPEED_LPC] = 0x1E789000, - [ASPEED_IBT] = 0x1E789140, - [ASPEED_I2C] = 0x1E78A000, - [ASPEED_ETH1] = 0x1E660000, - [ASPEED_ETH2] = 0x1E680000, - [ASPEED_UART1] = 0x1E783000, - [ASPEED_UART5] = 0x1E784000, - [ASPEED_VUART] = 0x1E787000, - [ASPEED_SDRAM] = 0x40000000, + [ASPEED_DEV_IOMEM] = 0x1E600000, + [ASPEED_DEV_FMC] = 0x1E620000, + [ASPEED_DEV_SPI1] = 0x1E630000, + [ASPEED_DEV_EHCI1] = 0x1E6A1000, + [ASPEED_DEV_VIC] = 0x1E6C0000, + [ASPEED_DEV_SDMC] = 0x1E6E0000, + [ASPEED_DEV_SCU] = 0x1E6E2000, + [ASPEED_DEV_XDMA] = 0x1E6E7000, + [ASPEED_DEV_VIDEO] = 0x1E700000, + [ASPEED_DEV_ADC] = 0x1E6E9000, + [ASPEED_DEV_SRAM] = 0x1E720000, + [ASPEED_DEV_SDHCI] = 0x1E740000, + [ASPEED_DEV_GPIO] = 0x1E780000, + [ASPEED_DEV_RTC] = 0x1E781000, + [ASPEED_DEV_TIMER1] = 0x1E782000, + [ASPEED_DEV_WDT] = 0x1E785000, + [ASPEED_DEV_PWM] = 0x1E786000, + [ASPEED_DEV_LPC] = 0x1E789000, + [ASPEED_DEV_IBT] = 0x1E789140, + [ASPEED_DEV_I2C] = 0x1E78A000, + [ASPEED_DEV_ETH1] = 0x1E660000, + [ASPEED_DEV_ETH2] = 0x1E680000, + [ASPEED_DEV_UART1] = 0x1E783000, + [ASPEED_DEV_UART5] = 0x1E784000, + [ASPEED_DEV_VUART] = 0x1E787000, + [ASPEED_DEV_SDRAM] = 0x40000000, }; static const hwaddr aspeed_soc_ast2500_memmap[] = { - [ASPEED_IOMEM] = 0x1E600000, - [ASPEED_FMC] = 0x1E620000, - [ASPEED_SPI1] = 0x1E630000, - [ASPEED_SPI2] = 0x1E631000, - [ASPEED_EHCI1] = 0x1E6A1000, - [ASPEED_EHCI2] = 0x1E6A3000, - [ASPEED_VIC] = 0x1E6C0000, - [ASPEED_SDMC] = 0x1E6E0000, - [ASPEED_SCU] = 0x1E6E2000, - [ASPEED_XDMA] = 0x1E6E7000, - [ASPEED_ADC] = 0x1E6E9000, - [ASPEED_VIDEO] = 0x1E700000, - [ASPEED_SRAM] = 0x1E720000, - [ASPEED_SDHCI] = 0x1E740000, - [ASPEED_GPIO] = 0x1E780000, - [ASPEED_RTC] = 0x1E781000, - [ASPEED_TIMER1] = 0x1E782000, - [ASPEED_WDT] = 0x1E785000, - [ASPEED_PWM] = 0x1E786000, - [ASPEED_LPC] = 0x1E789000, - [ASPEED_IBT] = 0x1E789140, - [ASPEED_I2C] = 0x1E78A000, - [ASPEED_ETH1] = 0x1E660000, - [ASPEED_ETH2] = 0x1E680000, - [ASPEED_UART1] = 0x1E783000, - [ASPEED_UART5] = 0x1E784000, - [ASPEED_VUART] = 0x1E787000, - [ASPEED_SDRAM] = 0x80000000, + [ASPEED_DEV_IOMEM] = 0x1E600000, + [ASPEED_DEV_FMC] = 0x1E620000, + [ASPEED_DEV_SPI1] = 0x1E630000, + [ASPEED_DEV_SPI2] = 0x1E631000, + [ASPEED_DEV_EHCI1] = 0x1E6A1000, + [ASPEED_DEV_EHCI2] = 0x1E6A3000, + [ASPEED_DEV_VIC] = 0x1E6C0000, + [ASPEED_DEV_SDMC] = 0x1E6E0000, + [ASPEED_DEV_SCU] = 0x1E6E2000, + [ASPEED_DEV_XDMA] = 0x1E6E7000, + [ASPEED_DEV_ADC] = 0x1E6E9000, + [ASPEED_DEV_VIDEO] = 0x1E700000, + [ASPEED_DEV_SRAM] = 0x1E720000, + [ASPEED_DEV_SDHCI] = 0x1E740000, + [ASPEED_DEV_GPIO] = 0x1E780000, + [ASPEED_DEV_RTC] = 0x1E781000, + [ASPEED_DEV_TIMER1] = 0x1E782000, + [ASPEED_DEV_WDT] = 0x1E785000, + [ASPEED_DEV_PWM] = 0x1E786000, + [ASPEED_DEV_LPC] = 0x1E789000, + [ASPEED_DEV_IBT] = 0x1E789140, + [ASPEED_DEV_I2C] = 0x1E78A000, + [ASPEED_DEV_ETH1] = 0x1E660000, + [ASPEED_DEV_ETH2] = 0x1E680000, + [ASPEED_DEV_UART1] = 0x1E783000, + [ASPEED_DEV_UART5] = 0x1E784000, + [ASPEED_DEV_VUART] = 0x1E787000, + [ASPEED_DEV_SDRAM] = 0x80000000, }; static const int aspeed_soc_ast2400_irqmap[] = { - [ASPEED_UART1] = 9, - [ASPEED_UART2] = 32, - [ASPEED_UART3] = 33, - [ASPEED_UART4] = 34, - [ASPEED_UART5] = 10, - [ASPEED_VUART] = 8, - [ASPEED_FMC] = 19, - [ASPEED_EHCI1] = 5, - [ASPEED_EHCI2] = 13, - [ASPEED_SDMC] = 0, - [ASPEED_SCU] = 21, - [ASPEED_ADC] = 31, - [ASPEED_GPIO] = 20, - [ASPEED_RTC] = 22, - [ASPEED_TIMER1] = 16, - [ASPEED_TIMER2] = 17, - [ASPEED_TIMER3] = 18, - [ASPEED_TIMER4] = 35, - [ASPEED_TIMER5] = 36, - [ASPEED_TIMER6] = 37, - [ASPEED_TIMER7] = 38, - [ASPEED_TIMER8] = 39, - [ASPEED_WDT] = 27, - [ASPEED_PWM] = 28, - [ASPEED_LPC] = 8, - [ASPEED_IBT] = 8, /* LPC */ - [ASPEED_I2C] = 12, - [ASPEED_ETH1] = 2, - [ASPEED_ETH2] = 3, - [ASPEED_XDMA] = 6, - [ASPEED_SDHCI] = 26, + [ASPEED_DEV_UART1] = 9, + [ASPEED_DEV_UART2] = 32, + [ASPEED_DEV_UART3] = 33, + [ASPEED_DEV_UART4] = 34, + [ASPEED_DEV_UART5] = 10, + [ASPEED_DEV_VUART] = 8, + [ASPEED_DEV_FMC] = 19, + [ASPEED_DEV_EHCI1] = 5, + [ASPEED_DEV_EHCI2] = 13, + [ASPEED_DEV_SDMC] = 0, + [ASPEED_DEV_SCU] = 21, + [ASPEED_DEV_ADC] = 31, + [ASPEED_DEV_GPIO] = 20, + [ASPEED_DEV_RTC] = 22, + [ASPEED_DEV_TIMER1] = 16, + [ASPEED_DEV_TIMER2] = 17, + [ASPEED_DEV_TIMER3] = 18, + [ASPEED_DEV_TIMER4] = 35, + [ASPEED_DEV_TIMER5] = 36, + [ASPEED_DEV_TIMER6] = 37, + [ASPEED_DEV_TIMER7] = 38, + [ASPEED_DEV_TIMER8] = 39, + [ASPEED_DEV_WDT] = 27, + [ASPEED_DEV_PWM] = 28, + [ASPEED_DEV_LPC] = 8, + [ASPEED_DEV_IBT] = 8, /* LPC */ + [ASPEED_DEV_I2C] = 12, + [ASPEED_DEV_ETH1] = 2, + [ASPEED_DEV_ETH2] = 3, + [ASPEED_DEV_XDMA] = 6, + [ASPEED_DEV_SDHCI] = 26, }; #define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap @@ -142,14 +142,11 @@ static void aspeed_soc_init(Object *obj) } for (i = 0; i < sc->num_cpus; i++) { - object_initialize_child(obj, "cpu[*]", OBJECT(&s->cpu[i]), - sizeof(s->cpu[i]), sc->cpu_type, - &error_abort, NULL); + object_initialize_child(obj, "cpu[*]", &s->cpu[i], sc->cpu_type); } snprintf(typename, sizeof(typename), "aspeed.scu-%s", socname); - sysbus_init_child_obj(obj, "scu", OBJECT(&s->scu), sizeof(s->scu), - typename); + object_initialize_child(obj, "scu", &s->scu, typename); qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev", sc->silicon_rev); object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu), @@ -159,39 +156,32 @@ static void aspeed_soc_init(Object *obj) object_property_add_alias(obj, "hw-prot-key", OBJECT(&s->scu), "hw-prot-key"); - sysbus_init_child_obj(obj, "vic", OBJECT(&s->vic), sizeof(s->vic), - TYPE_ASPEED_VIC); + object_initialize_child(obj, "vic", &s->vic, TYPE_ASPEED_VIC); - sysbus_init_child_obj(obj, "rtc", OBJECT(&s->rtc), sizeof(s->rtc), - TYPE_ASPEED_RTC); + object_initialize_child(obj, "rtc", &s->rtc, TYPE_ASPEED_RTC); snprintf(typename, sizeof(typename), "aspeed.timer-%s", socname); - sysbus_init_child_obj(obj, "timerctrl", OBJECT(&s->timerctrl), - sizeof(s->timerctrl), typename); + object_initialize_child(obj, "timerctrl", &s->timerctrl, typename); snprintf(typename, sizeof(typename), "aspeed.i2c-%s", socname); - sysbus_init_child_obj(obj, "i2c", OBJECT(&s->i2c), sizeof(s->i2c), - typename); + object_initialize_child(obj, "i2c", &s->i2c, typename); snprintf(typename, sizeof(typename), "aspeed.fmc-%s", socname); - sysbus_init_child_obj(obj, "fmc", OBJECT(&s->fmc), sizeof(s->fmc), - typename); + object_initialize_child(obj, "fmc", &s->fmc, typename); object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs"); for (i = 0; i < sc->spis_num; i++) { snprintf(typename, sizeof(typename), "aspeed.spi%d-%s", i + 1, socname); - sysbus_init_child_obj(obj, "spi[*]", OBJECT(&s->spi[i]), - sizeof(s->spi[i]), typename); + object_initialize_child(obj, "spi[*]", &s->spi[i], typename); } for (i = 0; i < sc->ehcis_num; i++) { - sysbus_init_child_obj(obj, "ehci[*]", OBJECT(&s->ehci[i]), - sizeof(s->ehci[i]), TYPE_PLATFORM_EHCI); + object_initialize_child(obj, "ehci[*]", &s->ehci[i], + TYPE_PLATFORM_EHCI); } snprintf(typename, sizeof(typename), "aspeed.sdmc-%s", socname); - sysbus_init_child_obj(obj, "sdmc", OBJECT(&s->sdmc), sizeof(s->sdmc), - typename); + object_initialize_child(obj, "sdmc", &s->sdmc, typename); object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc), "ram-size"); object_property_add_alias(obj, "max-ram-size", OBJECT(&s->sdmc), @@ -199,31 +189,27 @@ static void aspeed_soc_init(Object *obj) for (i = 0; i < sc->wdts_num; i++) { snprintf(typename, sizeof(typename), "aspeed.wdt-%s", socname); - sysbus_init_child_obj(obj, "wdt[*]", OBJECT(&s->wdt[i]), - sizeof(s->wdt[i]), typename); + object_initialize_child(obj, "wdt[*]", &s->wdt[i], typename); } for (i = 0; i < sc->macs_num; i++) { - sysbus_init_child_obj(obj, "ftgmac100[*]", OBJECT(&s->ftgmac100[i]), - sizeof(s->ftgmac100[i]), TYPE_FTGMAC100); + object_initialize_child(obj, "ftgmac100[*]", &s->ftgmac100[i], + TYPE_FTGMAC100); } - sysbus_init_child_obj(obj, "xdma", OBJECT(&s->xdma), sizeof(s->xdma), - TYPE_ASPEED_XDMA); + object_initialize_child(obj, "xdma", &s->xdma, TYPE_ASPEED_XDMA); snprintf(typename, sizeof(typename), "aspeed.gpio-%s", socname); - sysbus_init_child_obj(obj, "gpio", OBJECT(&s->gpio), sizeof(s->gpio), - typename); + object_initialize_child(obj, "gpio", &s->gpio, typename); - sysbus_init_child_obj(obj, "sdc", OBJECT(&s->sdhci), sizeof(s->sdhci), - TYPE_ASPEED_SDHCI); + object_initialize_child(obj, "sdc", &s->sdhci, TYPE_ASPEED_SDHCI); - object_property_set_int(OBJECT(&s->sdhci), 2, "num-slots", &error_abort); + object_property_set_int(OBJECT(&s->sdhci), "num-slots", 2, &error_abort); /* Init sd card slot class here so that they're under the correct parent */ for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) { - sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(&s->sdhci.slots[i]), - sizeof(s->sdhci.slots[i]), TYPE_SYSBUS_SDHCI); + object_initialize_child(obj, "sdhci[*]", &s->sdhci.slots[i], + TYPE_SYSBUS_SDHCI); } } @@ -232,27 +218,19 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) int i; AspeedSoCState *s = ASPEED_SOC(dev); AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); - Error *err = NULL, *local_err = NULL; + Error *err = NULL; /* IO space */ - create_unimplemented_device("aspeed_soc.io", sc->memmap[ASPEED_IOMEM], + create_unimplemented_device("aspeed_soc.io", sc->memmap[ASPEED_DEV_IOMEM], ASPEED_SOC_IOMEM_SIZE); /* Video engine stub */ - create_unimplemented_device("aspeed.video", sc->memmap[ASPEED_VIDEO], + create_unimplemented_device("aspeed.video", sc->memmap[ASPEED_DEV_VIDEO], 0x1000); - if (s->num_cpus > sc->num_cpus) { - warn_report("%s: invalid number of CPUs %d, using default %d", - sc->name, s->num_cpus, sc->num_cpus); - s->num_cpus = sc->num_cpus; - } - /* CPU */ - for (i = 0; i < s->num_cpus; i++) { - object_property_set_bool(OBJECT(&s->cpu[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + for (i = 0; i < sc->num_cpus; i++) { + if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) { return; } } @@ -265,202 +243,158 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) return; } memory_region_add_subregion(get_system_memory(), - sc->memmap[ASPEED_SRAM], &s->sram); + sc->memmap[ASPEED_DEV_SRAM], &s->sram); /* SCU */ - object_property_set_bool(OBJECT(&s->scu), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) { return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, sc->memmap[ASPEED_SCU]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, sc->memmap[ASPEED_DEV_SCU]); /* VIC */ - object_property_set_bool(OBJECT(&s->vic), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->vic), errp)) { return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, sc->memmap[ASPEED_VIC]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, sc->memmap[ASPEED_DEV_VIC]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 0, qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 1, qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ)); /* RTC */ - object_property_set_bool(OBJECT(&s->rtc), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->rtc), errp)) { return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, sc->memmap[ASPEED_RTC]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, sc->memmap[ASPEED_DEV_RTC]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0, - aspeed_soc_get_irq(s, ASPEED_RTC)); + aspeed_soc_get_irq(s, ASPEED_DEV_RTC)); /* Timer */ - object_property_set_link(OBJECT(&s->timerctrl), - OBJECT(&s->scu), "scu", &error_abort); - object_property_set_bool(OBJECT(&s->timerctrl), true, "realized", &err); - if (err) { - error_propagate(errp, err); + object_property_set_link(OBJECT(&s->timerctrl), "scu", OBJECT(&s->scu), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->timerctrl), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->timerctrl), 0, - sc->memmap[ASPEED_TIMER1]); + sc->memmap[ASPEED_DEV_TIMER1]); for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) { - qemu_irq irq = aspeed_soc_get_irq(s, ASPEED_TIMER1 + i); + qemu_irq irq = aspeed_soc_get_irq(s, ASPEED_DEV_TIMER1 + i); sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq); } /* UART - attach an 8250 to the IO space as our UART5 */ - if (serial_hd(0)) { - qemu_irq uart5 = aspeed_soc_get_irq(s, ASPEED_UART5); - serial_mm_init(get_system_memory(), sc->memmap[ASPEED_UART5], 2, - uart5, 38400, serial_hd(0), DEVICE_LITTLE_ENDIAN); - } + serial_mm_init(get_system_memory(), sc->memmap[ASPEED_DEV_UART5], 2, + aspeed_soc_get_irq(s, ASPEED_DEV_UART5), 38400, + serial_hd(0), DEVICE_LITTLE_ENDIAN); /* I2C */ - object_property_set_link(OBJECT(&s->i2c), OBJECT(s->dram_mr), "dram", &err); - if (err) { - error_propagate(errp, err); - return; - } - object_property_set_bool(OBJECT(&s->i2c), true, "realized", &err); - if (err) { - error_propagate(errp, err); + object_property_set_link(OBJECT(&s->i2c), "dram", OBJECT(s->dram_mr), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c), errp)) { return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, sc->memmap[ASPEED_I2C]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, sc->memmap[ASPEED_DEV_I2C]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0, - aspeed_soc_get_irq(s, ASPEED_I2C)); + aspeed_soc_get_irq(s, ASPEED_DEV_I2C)); /* FMC, The number of CS is set at the board level */ - object_property_set_link(OBJECT(&s->fmc), OBJECT(s->dram_mr), "dram", &err); - if (err) { - error_propagate(errp, err); + object_property_set_link(OBJECT(&s->fmc), "dram", OBJECT(s->dram_mr), + &error_abort); + if (!object_property_set_int(OBJECT(&s->fmc), "sdram-base", + sc->memmap[ASPEED_DEV_SDRAM], errp)) { return; } - object_property_set_int(OBJECT(&s->fmc), sc->memmap[ASPEED_SDRAM], - "sdram-base", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->fmc), errp)) { return; } - object_property_set_bool(OBJECT(&s->fmc), true, "realized", &err); - if (err) { - error_propagate(errp, err); - return; - } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 0, sc->memmap[ASPEED_FMC]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 0, sc->memmap[ASPEED_DEV_FMC]); sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 1, s->fmc.ctrl->flash_window_base); sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0, - aspeed_soc_get_irq(s, ASPEED_FMC)); + aspeed_soc_get_irq(s, ASPEED_DEV_FMC)); /* SPI */ for (i = 0; i < sc->spis_num; i++) { - object_property_set_int(OBJECT(&s->spi[i]), 1, "num-cs", &err); - object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", - &local_err); - error_propagate(&err, local_err); - if (err) { - error_propagate(errp, err); + object_property_set_int(OBJECT(&s->spi[i]), "num-cs", 1, &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, - sc->memmap[ASPEED_SPI1 + i]); + sc->memmap[ASPEED_DEV_SPI1 + i]); sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 1, s->spi[i].ctrl->flash_window_base); } /* EHCI */ for (i = 0; i < sc->ehcis_num; i++) { - object_property_set_bool(OBJECT(&s->ehci[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->ehci[i]), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->ehci[i]), 0, - sc->memmap[ASPEED_EHCI1 + i]); + sc->memmap[ASPEED_DEV_EHCI1 + i]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci[i]), 0, - aspeed_soc_get_irq(s, ASPEED_EHCI1 + i)); + aspeed_soc_get_irq(s, ASPEED_DEV_EHCI1 + i)); } /* SDMC - SDRAM Memory Controller */ - object_property_set_bool(OBJECT(&s->sdmc), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdmc), errp)) { return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, sc->memmap[ASPEED_SDMC]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, sc->memmap[ASPEED_DEV_SDMC]); /* Watch dog */ for (i = 0; i < sc->wdts_num; i++) { AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(&s->wdt[i]); - object_property_set_link(OBJECT(&s->wdt[i]), - OBJECT(&s->scu), "scu", &error_abort); - object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + object_property_set_link(OBJECT(&s->wdt[i]), "scu", OBJECT(&s->scu), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, - sc->memmap[ASPEED_WDT] + i * awc->offset); + sc->memmap[ASPEED_DEV_WDT] + i * awc->offset); } /* Net */ - for (i = 0; i < nb_nics && i < sc->macs_num; i++) { - qdev_set_nic_properties(DEVICE(&s->ftgmac100[i]), &nd_table[i]); - object_property_set_bool(OBJECT(&s->ftgmac100[i]), true, "aspeed", - &err); - object_property_set_bool(OBJECT(&s->ftgmac100[i]), true, "realized", - &local_err); - error_propagate(&err, local_err); - if (err) { - error_propagate(errp, err); - return; + for (i = 0; i < sc->macs_num; i++) { + object_property_set_bool(OBJECT(&s->ftgmac100[i]), "aspeed", true, + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->ftgmac100[i]), errp)) { + return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->ftgmac100[i]), 0, - sc->memmap[ASPEED_ETH1 + i]); + sc->memmap[ASPEED_DEV_ETH1 + i]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->ftgmac100[i]), 0, - aspeed_soc_get_irq(s, ASPEED_ETH1 + i)); + aspeed_soc_get_irq(s, ASPEED_DEV_ETH1 + i)); } /* XDMA */ - object_property_set_bool(OBJECT(&s->xdma), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->xdma), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->xdma), 0, - sc->memmap[ASPEED_XDMA]); + sc->memmap[ASPEED_DEV_XDMA]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->xdma), 0, - aspeed_soc_get_irq(s, ASPEED_XDMA)); + aspeed_soc_get_irq(s, ASPEED_DEV_XDMA)); /* GPIO */ - object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) { return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio), 0, sc->memmap[ASPEED_GPIO]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio), 0, sc->memmap[ASPEED_DEV_GPIO]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0, - aspeed_soc_get_irq(s, ASPEED_GPIO)); + aspeed_soc_get_irq(s, ASPEED_DEV_GPIO)); /* SDHCI */ - object_property_set_bool(OBJECT(&s->sdhci), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdhci), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci), 0, - sc->memmap[ASPEED_SDHCI]); + sc->memmap[ASPEED_DEV_SDHCI]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0, - aspeed_soc_get_irq(s, ASPEED_SDHCI)); + aspeed_soc_get_irq(s, ASPEED_DEV_SDHCI)); } static Property aspeed_soc_properties[] = { - DEFINE_PROP_UINT32("num-cpus", AspeedSoCState, num_cpus, 0), DEFINE_PROP_LINK("dram", AspeedSoCState, dram_mr, TYPE_MEMORY_REGION, MemoryRegion *), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c index f1bcc14f553e2d679b124dc8bf8461ed1bf854d7..dcff13433e562d4e2cd47887fa94e7a9959e639a 100644 --- a/hw/arm/bcm2835_peripherals.c +++ b/hw/arm/bcm2835_peripherals.c @@ -27,12 +27,10 @@ static void create_unimp(BCM2835PeripheralState *ps, UnimplementedDeviceState *uds, const char *name, hwaddr ofs, hwaddr size) { - sysbus_init_child_obj(OBJECT(ps), name, uds, - sizeof(UnimplementedDeviceState), - TYPE_UNIMPLEMENTED_DEVICE); + object_initialize_child(OBJECT(ps), name, uds, TYPE_UNIMPLEMENTED_DEVICE); qdev_prop_set_string(DEVICE(uds), "name", name); qdev_prop_set_uint64(DEVICE(uds), "size", size); - object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(uds), &error_fatal); memory_region_add_subregion_overlap(&ps->peri_mr, ofs, sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0), -1000); } @@ -55,37 +53,34 @@ static void bcm2835_peripherals_init(Object *obj) MBOX_CHAN_COUNT << MBOX_AS_CHAN_SHIFT); /* Interrupt Controller */ - sysbus_init_child_obj(obj, "ic", &s->ic, sizeof(s->ic), TYPE_BCM2835_IC); + object_initialize_child(obj, "ic", &s->ic, TYPE_BCM2835_IC); /* SYS Timer */ - sysbus_init_child_obj(obj, "systimer", &s->systmr, sizeof(s->systmr), - TYPE_BCM2835_SYSTIMER); + object_initialize_child(obj, "systimer", &s->systmr, + TYPE_BCM2835_SYSTIMER); /* UART0 */ - sysbus_init_child_obj(obj, "uart0", &s->uart0, sizeof(s->uart0), - TYPE_PL011); + object_initialize_child(obj, "uart0", &s->uart0, TYPE_PL011); /* AUX / UART1 */ - sysbus_init_child_obj(obj, "aux", &s->aux, sizeof(s->aux), - TYPE_BCM2835_AUX); + object_initialize_child(obj, "aux", &s->aux, TYPE_BCM2835_AUX); /* Mailboxes */ - sysbus_init_child_obj(obj, "mbox", &s->mboxes, sizeof(s->mboxes), - TYPE_BCM2835_MBOX); + object_initialize_child(obj, "mbox", &s->mboxes, TYPE_BCM2835_MBOX); object_property_add_const_link(OBJECT(&s->mboxes), "mbox-mr", OBJECT(&s->mbox_mr)); /* Framebuffer */ - sysbus_init_child_obj(obj, "fb", &s->fb, sizeof(s->fb), TYPE_BCM2835_FB); + object_initialize_child(obj, "fb", &s->fb, TYPE_BCM2835_FB); object_property_add_alias(obj, "vcram-size", OBJECT(&s->fb), "vcram-size"); object_property_add_const_link(OBJECT(&s->fb), "dma-mr", OBJECT(&s->gpu_bus_mr)); /* Property channel */ - sysbus_init_child_obj(obj, "property", &s->property, sizeof(s->property), - TYPE_BCM2835_PROPERTY); + object_initialize_child(obj, "property", &s->property, + TYPE_BCM2835_PROPERTY); object_property_add_alias(obj, "board-rev", OBJECT(&s->property), "board-rev"); @@ -95,36 +90,42 @@ static void bcm2835_peripherals_init(Object *obj) OBJECT(&s->gpu_bus_mr)); /* Random Number Generator */ - sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng), - TYPE_BCM2835_RNG); + object_initialize_child(obj, "rng", &s->rng, TYPE_BCM2835_RNG); /* Extended Mass Media Controller */ - sysbus_init_child_obj(obj, "sdhci", &s->sdhci, sizeof(s->sdhci), - TYPE_SYSBUS_SDHCI); + object_initialize_child(obj, "sdhci", &s->sdhci, TYPE_SYSBUS_SDHCI); /* SDHOST */ - sysbus_init_child_obj(obj, "sdhost", &s->sdhost, sizeof(s->sdhost), - TYPE_BCM2835_SDHOST); + object_initialize_child(obj, "sdhost", &s->sdhost, TYPE_BCM2835_SDHOST); /* DMA Channels */ - sysbus_init_child_obj(obj, "dma", &s->dma, sizeof(s->dma), - TYPE_BCM2835_DMA); + object_initialize_child(obj, "dma", &s->dma, TYPE_BCM2835_DMA); object_property_add_const_link(OBJECT(&s->dma), "dma-mr", OBJECT(&s->gpu_bus_mr)); /* Thermal */ - sysbus_init_child_obj(obj, "thermal", &s->thermal, sizeof(s->thermal), - TYPE_BCM2835_THERMAL); + object_initialize_child(obj, "thermal", &s->thermal, TYPE_BCM2835_THERMAL); /* GPIO */ - sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio), - TYPE_BCM2835_GPIO); + object_initialize_child(obj, "gpio", &s->gpio, TYPE_BCM2835_GPIO); object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhci", OBJECT(&s->sdhci.sdbus)); object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhost", OBJECT(&s->sdhost.sdbus)); + + /* Mphi */ + object_initialize_child(obj, "mphi", &s->mphi, TYPE_BCM2835_MPHI); + + /* DWC2 */ + object_initialize_child(obj, "dwc2", &s->dwc2, TYPE_DWC2_USB); + + /* CPRMAN clock manager */ + object_initialize_child(obj, "cprman", &s->cprman, TYPE_BCM2835_CPRMAN); + + object_property_add_const_link(OBJECT(&s->dwc2), "dma-mr", + OBJECT(&s->gpu_bus_mr)); } static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) @@ -136,12 +137,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) uint64_t ram_size, vcram_size; int n; - obj = object_property_get_link(OBJECT(dev), "ram", &err); - if (obj == NULL) { - error_setg(errp, "%s: required ram link not found: %s", - __func__, error_get_pretty(err)); - return; - } + obj = object_property_get_link(OBJECT(dev), "ram", &error_abort); ram = MEMORY_REGION(obj); ram_size = memory_region_size(ram); @@ -163,33 +159,45 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) } /* Interrupt Controller */ - object_property_set_bool(OBJECT(&s->ic), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->ic), errp)) { + return; + } + + /* CPRMAN clock manager */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->cprman), errp)) { return; } + memory_region_add_subregion(&s->peri_mr, CPRMAN_OFFSET, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cprman), 0)); + qdev_connect_clock_in(DEVICE(&s->uart0), "clk", + qdev_get_clock_out(DEVICE(&s->cprman), "uart-out")); memory_region_add_subregion(&s->peri_mr, ARMCTRL_IC_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ic), 0)); sysbus_pass_irq(SYS_BUS_DEVICE(s), SYS_BUS_DEVICE(&s->ic)); /* Sys Timer */ - object_property_set_bool(OBJECT(&s->systmr), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->systmr), errp)) { return; } memory_region_add_subregion(&s->peri_mr, ST_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systmr), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 0, - qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ, - INTERRUPT_ARM_TIMER)); + qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, + INTERRUPT_TIMER0)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 1, + qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, + INTERRUPT_TIMER1)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 2, + qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, + INTERRUPT_TIMER2)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 3, + qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, + INTERRUPT_TIMER3)); /* UART0 */ qdev_prop_set_chr(DEVICE(&s->uart0), "chardev", serial_hd(0)); - object_property_set_bool(OBJECT(&s->uart0), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart0), errp)) { return; } @@ -202,9 +210,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) /* AUX / UART1 */ qdev_prop_set_chr(DEVICE(&s->aux), "chardev", serial_hd(1)); - object_property_set_bool(OBJECT(&s->aux), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->aux), errp)) { return; } @@ -215,9 +221,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) INTERRUPT_AUX)); /* Mailboxes */ - object_property_set_bool(OBJECT(&s->mboxes), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->mboxes), errp)) { return; } @@ -234,16 +238,12 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) return; } - object_property_set_uint(OBJECT(&s->fb), ram_size - vcram_size, - "vcram-base", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_uint(OBJECT(&s->fb), "vcram-base", + ram_size - vcram_size, errp)) { return; } - object_property_set_bool(OBJECT(&s->fb), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->fb), errp)) { return; } @@ -253,9 +253,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_FB)); /* Property channel */ - object_property_set_bool(OBJECT(&s->property), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->property), errp)) { return; } @@ -266,9 +264,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_PROPERTY)); /* Random Number Generator */ - object_property_set_bool(OBJECT(&s->rng), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->rng), errp)) { return; } @@ -285,19 +281,13 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) * For the exact details please refer to the Arasan documentation: * SD3.0_Host_AHB_eMMC4.4_Usersguide_ver5.9_jan11_10.pdf */ - object_property_set_uint(OBJECT(&s->sdhci), 3, "sd-spec-version", &err); - object_property_set_uint(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capareg", - &err); - object_property_set_bool(OBJECT(&s->sdhci), true, "pending-insert-quirk", - &err); - if (err) { - error_propagate(errp, err); - return; - } - - object_property_set_bool(OBJECT(&s->sdhci), true, "realized", &err); - if (err) { - error_propagate(errp, err); + object_property_set_uint(OBJECT(&s->sdhci), "sd-spec-version", 3, + &error_abort); + object_property_set_uint(OBJECT(&s->sdhci), "capareg", + BCM2835_SDHC_CAPAREG, &error_abort); + object_property_set_bool(OBJECT(&s->sdhci), "pending-insert-quirk", true, + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdhci), errp)) { return; } @@ -308,9 +298,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) INTERRUPT_ARASANSDIO)); /* SDHOST */ - object_property_set_bool(OBJECT(&s->sdhost), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdhost), errp)) { return; } @@ -321,9 +309,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) INTERRUPT_SDIO)); /* DMA Channels */ - object_property_set_bool(OBJECT(&s->dma), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->dma), errp)) { return; } @@ -340,18 +326,14 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) } /* THERMAL */ - object_property_set_bool(OBJECT(&s->thermal), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->thermal), errp)) { return; } memory_region_add_subregion(&s->peri_mr, THERMAL_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->thermal), 0)); /* GPIO */ - object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) { return; } @@ -360,9 +342,31 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus"); + /* Mphi */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->mphi), errp)) { + return; + } + + memory_region_add_subregion(&s->peri_mr, MPHI_OFFSET, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mphi), 0)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->mphi), 0, + qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, + INTERRUPT_HOSTPORT)); + + /* DWC2 */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->dwc2), errp)) { + return; + } + + memory_region_add_subregion(&s->peri_mr, USB_OTG_OFFSET, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dwc2), 0)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->dwc2), 0, + qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, + INTERRUPT_USB)); + + create_unimp(s, &s->txp, "bcm2835-txp", TXP_OFFSET, 0x1000); create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40); - create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x1000); - create_unimp(s, &s->a2w, "bcm2835-a2w", A2W_OFFSET, 0x1000); + create_unimp(s, &s->powermgt, "bcm2835-powermgt", PM_OFFSET, 0x114); create_unimp(s, &s->i2s, "bcm2835-i2s", I2S_OFFSET, 0x100); create_unimp(s, &s->smi, "bcm2835-smi", SMI_OFFSET, 0x100); create_unimp(s, &s->spi[0], "bcm2835-spi0", SPI0_OFFSET, 0x20); @@ -373,7 +377,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) create_unimp(s, &s->otp, "bcm2835-otp", OTP_OFFSET, 0x80); create_unimp(s, &s->dbus, "bcm2835-dbus", DBUS_OFFSET, 0x8000); create_unimp(s, &s->ave0, "bcm2835-ave0", AVE0_OFFSET, 0x8000); - create_unimp(s, &s->dwc2, "dwc-usb2", USB_OTG_OFFSET, 0x1000); + create_unimp(s, &s->v3d, "bcm2835-v3d", V3D_OFFSET, 0x1000); create_unimp(s, &s->sdramc, "bcm2835-sdramc", SDRAMC_OFFSET, 0x100); } diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c index e51b4e0c43643c6edd8843f61d9158cbd969c985..de7ade2878e4172f45582d89bc36ba79cdf4f76a 100644 --- a/hw/arm/bcm2836.c +++ b/hw/arm/bcm2836.c @@ -17,97 +17,113 @@ #include "hw/arm/raspi_platform.h" #include "hw/sysbus.h" -struct BCM283XInfo { +typedef struct BCM283XClass { + /*< private >*/ + DeviceClass parent_class; + /*< public >*/ const char *name; const char *cpu_type; + unsigned core_count; hwaddr peri_base; /* Peripheral base address seen by the CPU */ hwaddr ctrl_base; /* Interrupt controller and mailboxes etc. */ int clusterid; -}; +} BCM283XClass; -static const BCM283XInfo bcm283x_socs[] = { - { - .name = TYPE_BCM2836, - .cpu_type = ARM_CPU_TYPE_NAME("cortex-a7"), - .peri_base = 0x3f000000, - .ctrl_base = 0x40000000, - .clusterid = 0xf, - }, -#ifdef TARGET_AARCH64 - { - .name = TYPE_BCM2837, - .cpu_type = ARM_CPU_TYPE_NAME("cortex-a53"), - .peri_base = 0x3f000000, - .ctrl_base = 0x40000000, - .clusterid = 0x0, - }, -#endif -}; +#define BCM283X_CLASS(klass) \ + OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X) +#define BCM283X_GET_CLASS(obj) \ + OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X) + +static Property bcm2836_enabled_cores_property = + DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus, 0); static void bcm2836_init(Object *obj) { BCM283XState *s = BCM283X(obj); BCM283XClass *bc = BCM283X_GET_CLASS(obj); - const BCM283XInfo *info = bc->info; int n; - for (n = 0; n < BCM283X_NCPUS; n++) { + for (n = 0; n < bc->core_count; n++) { object_initialize_child(obj, "cpu[*]", &s->cpu[n].core, - sizeof(s->cpu[n].core), info->cpu_type, - &error_abort, NULL); + bc->cpu_type); + } + if (bc->core_count > 1) { + qdev_property_add_static(DEVICE(obj), &bcm2836_enabled_cores_property); + qdev_prop_set_uint32(DEVICE(obj), "enabled-cpus", bc->core_count); } - sysbus_init_child_obj(obj, "control", &s->control, sizeof(s->control), - TYPE_BCM2836_CONTROL); + if (bc->ctrl_base) { + object_initialize_child(obj, "control", &s->control, + TYPE_BCM2836_CONTROL); + } - sysbus_init_child_obj(obj, "peripherals", &s->peripherals, - sizeof(s->peripherals), TYPE_BCM2835_PERIPHERALS); + object_initialize_child(obj, "peripherals", &s->peripherals, + TYPE_BCM2835_PERIPHERALS); object_property_add_alias(obj, "board-rev", OBJECT(&s->peripherals), "board-rev"); object_property_add_alias(obj, "vcram-size", OBJECT(&s->peripherals), "vcram-size"); } -static void bcm2836_realize(DeviceState *dev, Error **errp) +static bool bcm283x_common_realize(DeviceState *dev, Error **errp) { BCM283XState *s = BCM283X(dev); BCM283XClass *bc = BCM283X_GET_CLASS(dev); - const BCM283XInfo *info = bc->info; Object *obj; - Error *err = NULL; - int n; /* common peripherals from bcm2835 */ - obj = object_property_get_link(OBJECT(dev), "ram", &err); - if (obj == NULL) { - error_setg(errp, "%s: required ram link not found: %s", - __func__, error_get_pretty(err)); - return; - } + obj = object_property_get_link(OBJECT(dev), "ram", &error_abort); object_property_add_const_link(OBJECT(&s->peripherals), "ram", obj); - object_property_set_bool(OBJECT(&s->peripherals), true, "realized", &err); - if (err) { - error_propagate(errp, err); - return; + if (!sysbus_realize(SYS_BUS_DEVICE(&s->peripherals), errp)) { + return false; } object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->peripherals), "sd-bus"); sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0, - info->peri_base, 1); + bc->peri_base, 1); + return true; +} + +static void bcm2835_realize(DeviceState *dev, Error **errp) +{ + BCM283XState *s = BCM283X(dev); + + if (!bcm283x_common_realize(dev, errp)) { + return; + } + + if (!qdev_realize(DEVICE(&s->cpu[0].core), NULL, errp)) { + return; + } + + /* Connect irq/fiq outputs from the interrupt controller. */ + sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0, + qdev_get_gpio_in(DEVICE(&s->cpu[0].core), ARM_CPU_IRQ)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1, + qdev_get_gpio_in(DEVICE(&s->cpu[0].core), ARM_CPU_FIQ)); +} + +static void bcm2836_realize(DeviceState *dev, Error **errp) +{ + BCM283XState *s = BCM283X(dev); + BCM283XClass *bc = BCM283X_GET_CLASS(dev); + int n; + + if (!bcm283x_common_realize(dev, errp)) { + return; + } /* bcm2836 interrupt controller (and mailboxes, etc.) */ - object_property_set_bool(OBJECT(&s->control), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->control), errp)) { return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, info->ctrl_base); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, bc->ctrl_base); sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0, qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-irq", 0)); @@ -116,29 +132,23 @@ static void bcm2836_realize(DeviceState *dev, Error **errp) for (n = 0; n < BCM283X_NCPUS; n++) { /* TODO: this should be converted to a property of ARM_CPU */ - s->cpu[n].core.mp_affinity = (info->clusterid << 8) | n; + s->cpu[n].core.mp_affinity = (bc->clusterid << 8) | n; /* set periphbase/CBAR value for CPU-local registers */ - object_property_set_int(OBJECT(&s->cpu[n].core), - info->peri_base, - "reset-cbar", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_int(OBJECT(&s->cpu[n].core), "reset-cbar", + bc->peri_base, errp)) { return; } /* start powered off if not enabled */ - object_property_set_bool(OBJECT(&s->cpu[n].core), n >= s->enabled_cpus, - "start-powered-off", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_bool(OBJECT(&s->cpu[n].core), + "start-powered-off", + n >= s->enabled_cpus, + errp)) { return; } - object_property_set_bool(OBJECT(&s->cpu[n].core), true, - "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->cpu[n].core), NULL, errp)) { return; } @@ -160,47 +170,77 @@ static void bcm2836_realize(DeviceState *dev, Error **errp) } } -static Property bcm2836_props[] = { - DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus, - BCM283X_NCPUS), - DEFINE_PROP_END_OF_LIST() -}; - static void bcm283x_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); - BCM283XClass *bc = BCM283X_CLASS(oc); - bc->info = data; - dc->realize = bcm2836_realize; - device_class_set_props(dc, bcm2836_props); /* Reason: Must be wired up in code (see raspi_init() function) */ dc->user_creatable = false; } -static const TypeInfo bcm283x_type_info = { - .name = TYPE_BCM283X, - .parent = TYPE_DEVICE, - .instance_size = sizeof(BCM283XState), - .instance_init = bcm2836_init, - .class_size = sizeof(BCM283XClass), - .abstract = true, +static void bcm2835_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + BCM283XClass *bc = BCM283X_CLASS(oc); + + bc->cpu_type = ARM_CPU_TYPE_NAME("arm1176"); + bc->core_count = 1; + bc->peri_base = 0x20000000; + dc->realize = bcm2835_realize; }; -static void bcm2836_register_types(void) +static void bcm2836_class_init(ObjectClass *oc, void *data) { - int i; - - type_register_static(&bcm283x_type_info); - for (i = 0; i < ARRAY_SIZE(bcm283x_socs); i++) { - TypeInfo ti = { - .name = bcm283x_socs[i].name, - .parent = TYPE_BCM283X, - .class_init = bcm283x_class_init, - .class_data = (void *) &bcm283x_socs[i], - }; - type_register(&ti); + DeviceClass *dc = DEVICE_CLASS(oc); + BCM283XClass *bc = BCM283X_CLASS(oc); + + bc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a7"); + bc->core_count = BCM283X_NCPUS; + bc->peri_base = 0x3f000000; + bc->ctrl_base = 0x40000000; + bc->clusterid = 0xf; + dc->realize = bcm2836_realize; +}; + +#ifdef TARGET_AARCH64 +static void bcm2837_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + BCM283XClass *bc = BCM283X_CLASS(oc); + + bc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a53"); + bc->core_count = BCM283X_NCPUS; + bc->peri_base = 0x3f000000; + bc->ctrl_base = 0x40000000; + bc->clusterid = 0x0; + dc->realize = bcm2836_realize; +}; +#endif + +static const TypeInfo bcm283x_types[] = { + { + .name = TYPE_BCM2835, + .parent = TYPE_BCM283X, + .class_init = bcm2835_class_init, + }, { + .name = TYPE_BCM2836, + .parent = TYPE_BCM283X, + .class_init = bcm2836_class_init, +#ifdef TARGET_AARCH64 + }, { + .name = TYPE_BCM2837, + .parent = TYPE_BCM283X, + .class_init = bcm2837_class_init, +#endif + }, { + .name = TYPE_BCM283X, + .parent = TYPE_DEVICE, + .instance_size = sizeof(BCM283XState), + .instance_init = bcm2836_init, + .class_size = sizeof(BCM283XClass), + .class_init = bcm283x_class_init, + .abstract = true, } -} +}; -type_init(bcm2836_register_types) +DEFINE_TYPES(bcm283x_types) diff --git a/hw/arm/boot.c b/hw/arm/boot.c index fef4072db169e6c8dfb2b94abf475c2f3db66f16..cf97600a9158999a6cbad43c55fd5425015e0a07 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -736,6 +736,15 @@ static void do_cpu_reset(void *opaque) } else { env->pstate = PSTATE_MODE_EL1h; } + if (cpu_isar_feature(aa64_pauth, cpu)) { + env->cp15.scr_el3 |= SCR_API | SCR_APK; + } + if (cpu_isar_feature(aa64_mte, cpu)) { + env->cp15.scr_el3 |= SCR_ATA; + } + if (cpu_isar_feature(aa64_sve, cpu)) { + env->cp15.cptr_el[3] |= CPTR_EZ; + } /* AArch64 kernels never boot in secure mode */ assert(!info->secure_boot); /* This hook is only supported for AArch32 currently: diff --git a/hw/arm/collie.c b/hw/arm/collie.c index 4b35ef4bed65e061371165a3c145a1a90e27c103..8df31e27932af0c23fdc13dd5aca1dc63f8af9ce 100644 --- a/hw/arm/collie.c +++ b/hw/arm/collie.c @@ -18,16 +18,16 @@ #include "hw/block/flash.h" #include "exec/address-spaces.h" #include "cpu.h" +#include "qom/object.h" -typedef struct { +struct CollieMachineState { MachineState parent; StrongARMState *sa1110; -} CollieMachineState; +}; #define TYPE_COLLIE_MACHINE MACHINE_TYPE_NAME("collie") -#define COLLIE_MACHINE(obj) \ - OBJECT_CHECK(CollieMachineState, obj, TYPE_COLLIE_MACHINE) +OBJECT_DECLARE_SIMPLE_TYPE(CollieMachineState, COLLIE_MACHINE) static struct arm_boot_info collie_binfo = { .loader_start = SA_SDCS0, diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c index cd1b6d3e19b816cf49e949be5b5dde52651263f2..1c6c792eb673ebecd75fbb6cb57773534a9711c6 100644 --- a/hw/arm/cubieboard.c +++ b/hw/arm/cubieboard.c @@ -62,26 +62,24 @@ static void cubieboard_init(MachineState *machine) object_property_add_child(OBJECT(machine), "soc", OBJECT(a10)); object_unref(OBJECT(a10)); - object_property_set_int(OBJECT(&a10->emac), 1, "phy-addr", &err); - if (err != NULL) { + if (!object_property_set_int(OBJECT(&a10->emac), "phy-addr", 1, &err)) { error_reportf_err(err, "Couldn't set phy address: "); exit(1); } - object_property_set_int(OBJECT(&a10->timer), 32768, "clk0-freq", &err); - if (err != NULL) { + if (!object_property_set_int(OBJECT(&a10->timer), "clk0-freq", 32768, + &err)) { error_reportf_err(err, "Couldn't set clk0 frequency: "); exit(1); } - object_property_set_int(OBJECT(&a10->timer), 24000000, "clk1-freq", &err); - if (err != NULL) { + if (!object_property_set_int(OBJECT(&a10->timer), "clk1-freq", 24000000, + &err)) { error_reportf_err(err, "Couldn't set clk1 frequency: "); exit(1); } - object_property_set_bool(OBJECT(a10), true, "realized", &err); - if (err != NULL) { + if (!qdev_realize(DEVICE(a10), NULL, &err)) { error_reportf_err(err, "Couldn't realize Allwinner A10: "); exit(1); } @@ -92,9 +90,9 @@ static void cubieboard_init(MachineState *machine) bus = qdev_get_child_bus(DEVICE(a10), "sd-bus"); /* Plug in SD card */ - carddev = qdev_create(bus, TYPE_SD_CARD); - qdev_prop_set_drive(carddev, "drive", blk, &error_fatal); - object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal); + carddev = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal); + qdev_realize_and_unref(carddev, bus, &error_fatal); memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE, machine->ram); diff --git a/hw/arm/digic.c b/hw/arm/digic.c index 22434a65a28778b4fc6d32ff4c174752cf6a424a..614232165cdca5f6786beffadb363a5dc1562391 100644 --- a/hw/arm/digic.c +++ b/hw/arm/digic.c @@ -36,46 +36,36 @@ static void digic_init(Object *obj) DigicState *s = DIGIC(obj); int i; - object_initialize_child(obj, "cpu", &s->cpu, sizeof(s->cpu), - ARM_CPU_TYPE_NAME("arm946"), - &error_abort, NULL); + object_initialize_child(obj, "cpu", &s->cpu, ARM_CPU_TYPE_NAME("arm946")); for (i = 0; i < DIGIC4_NB_TIMERS; i++) { #define DIGIC_TIMER_NAME_MLEN 11 char name[DIGIC_TIMER_NAME_MLEN]; snprintf(name, DIGIC_TIMER_NAME_MLEN, "timer[%d]", i); - sysbus_init_child_obj(obj, name, &s->timer[i], sizeof(s->timer[i]), - TYPE_DIGIC_TIMER); + object_initialize_child(obj, name, &s->timer[i], TYPE_DIGIC_TIMER); } - sysbus_init_child_obj(obj, "uart", &s->uart, sizeof(s->uart), - TYPE_DIGIC_UART); + object_initialize_child(obj, "uart", &s->uart, TYPE_DIGIC_UART); } static void digic_realize(DeviceState *dev, Error **errp) { DigicState *s = DIGIC(dev); - Error *err = NULL; SysBusDevice *sbd; int i; - object_property_set_bool(OBJECT(&s->cpu), true, "reset-hivecs", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!object_property_set_bool(OBJECT(&s->cpu), "reset-hivecs", true, + errp)) { return; } - object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->cpu), NULL, errp)) { return; } for (i = 0; i < DIGIC4_NB_TIMERS; i++) { - object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer[i]), errp)) { return; } @@ -84,9 +74,7 @@ static void digic_realize(DeviceState *dev, Error **errp) } qdev_prop_set_chr(DEVICE(&s->uart), "chardev", serial_hd(0)); - object_property_set_bool(OBJECT(&s->uart), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart), errp)) { return; } diff --git a/hw/arm/digic_boards.c b/hw/arm/digic_boards.c index 518a63e61dec070b376b39e73836ec67bf35cde5..d5524d3e725ae81ff7d525ab0ae83e9d83de455c 100644 --- a/hw/arm/digic_boards.c +++ b/hw/arm/digic_boards.c @@ -62,8 +62,7 @@ static void digic4_board_init(MachineState *machine, DigicBoard *board) exit(EXIT_FAILURE); } - object_property_set_bool(OBJECT(s), true, "realized", &err); - if (err != NULL) { + if (!qdev_realize(DEVICE(s), NULL, &err)) { error_reportf_err(err, "Couldn't realize DIGIC SoC: "); exit(1); } diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c index 1f7253ef6f6ecf4f1dc9cd1c02fd166cb59dfa23..ced2769b102ad89b5fd1ad4ab286b67a01d33f7a 100644 --- a/hw/arm/exynos4210.c +++ b/hw/arm/exynos4210.c @@ -173,7 +173,7 @@ static DeviceState *pl330_create(uint32_t base, qemu_or_irq *orgate, DeviceState *dev; int i; - dev = qdev_create(NULL, "pl330"); + dev = qdev_new("pl330"); qdev_prop_set_uint8(dev, "num_events", nevents); qdev_prop_set_uint8(dev, "num_chnls", 8); qdev_prop_set_uint8(dev, "num_periph_req", nreq); @@ -184,13 +184,13 @@ static DeviceState *pl330_create(uint32_t base, qemu_or_irq *orgate, qdev_prop_set_uint8(dev, "rd_q_dep", 8); qdev_prop_set_uint8(dev, "data_width", width); qdev_prop_set_uint16(dev, "data_buffer_dep", width); - qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, base); - object_property_set_int(OBJECT(orgate), nevents + 1, "num-lines", + object_property_set_int(OBJECT(orgate), "num-lines", nevents + 1, &error_abort); - object_property_set_bool(OBJECT(orgate), true, "realized", &error_abort); + qdev_realize(DEVICE(orgate), NULL, &error_abort); for (i = 0; i < nevents + 1; i++) { sysbus_connect_irq(busdev, i, qdev_get_gpio_in(DEVICE(orgate), i)); @@ -214,16 +214,17 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp) /* By default A9 CPUs have EL3 enabled. This board does not currently * support EL3 so the CPU EL3 property is disabled before realization. */ - if (object_property_find(cpuobj, "has_el3", NULL)) { - object_property_set_bool(cpuobj, false, "has_el3", &error_fatal); + if (object_property_find(cpuobj, "has_el3")) { + object_property_set_bool(cpuobj, "has_el3", false, &error_fatal); } s->cpu[n] = ARM_CPU(cpuobj); - object_property_set_int(cpuobj, exynos4210_calc_affinity(n), - "mp-affinity", &error_abort); - object_property_set_int(cpuobj, EXYNOS4210_SMP_PRIVATE_BASE_ADDR, - "reset-cbar", &error_abort); - object_property_set_bool(cpuobj, true, "realized", &error_fatal); + object_property_set_int(cpuobj, "mp-affinity", + exynos4210_calc_affinity(n), &error_abort); + object_property_set_int(cpuobj, "reset-cbar", + EXYNOS4210_SMP_PRIVATE_BASE_ADDR, + &error_abort); + qdev_realize(DEVICE(cpuobj), NULL, &error_fatal); } /*** IRQs ***/ @@ -232,9 +233,9 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp) /* IRQ Gate */ for (i = 0; i < EXYNOS4210_NCPUS; i++) { - dev = qdev_create(NULL, "exynos4210.irq_gate"); + dev = qdev_new("exynos4210.irq_gate"); qdev_prop_set_uint32(dev, "n_in", EXYNOS4210_IRQ_GATE_NINPUTS); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); /* Get IRQ Gate input in gate_irq */ for (n = 0; n < EXYNOS4210_IRQ_GATE_NINPUTS; n++) { gate_irq[i][n] = qdev_get_gpio_in(dev, n); @@ -247,10 +248,10 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp) } /* Private memory region and Internal GIC */ - dev = qdev_create(NULL, TYPE_A9MPCORE_PRIV); + dev = qdev_new(TYPE_A9MPCORE_PRIV); qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS); - qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR); for (n = 0; n < EXYNOS4210_NCPUS; n++) { sysbus_connect_irq(busdev, n, gate_irq[n][0]); @@ -263,10 +264,10 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp) sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL); /* External GIC */ - dev = qdev_create(NULL, "exynos4210.gic"); + dev = qdev_new("exynos4210.gic"); qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS); - qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); /* Map CPU interface */ sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_GIC_CPU_BASE_ADDR); /* Map Distributer interface */ @@ -279,9 +280,9 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp) } /* Internal Interrupt Combiner */ - dev = qdev_create(NULL, "exynos4210.combiner"); - qdev_init_nofail(dev); + dev = qdev_new("exynos4210.combiner"); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) { sysbus_connect_irq(busdev, n, s->irqs.int_gic_irq[n]); } @@ -289,10 +290,10 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp) sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR); /* External Interrupt Combiner */ - dev = qdev_create(NULL, "exynos4210.combiner"); + dev = qdev_new("exynos4210.combiner"); qdev_prop_set_uint32(dev, "external", 1); - qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) { sysbus_connect_irq(busdev, n, s->irqs.ext_gic_irq[n]); } @@ -353,9 +354,9 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp) NULL); /* Multi Core Timer */ - dev = qdev_create(NULL, "exynos4210.mct"); - qdev_init_nofail(dev); + dev = qdev_new("exynos4210.mct"); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); for (n = 0; n < 4; n++) { /* Connect global timer interrupts to Combiner gpio_in */ sysbus_connect_irq(busdev, n, @@ -379,9 +380,9 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp) i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_HDMI_INTG, 1)]; } - dev = qdev_create(NULL, "exynos4210.i2c"); - qdev_init_nofail(dev); + dev = qdev_new("exynos4210.i2c"); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_connect_irq(busdev, 0, i2c_irq); sysbus_mmio_map(busdev, 0, addr); s->i2c_if[n] = (I2CBus *)qdev_get_child_bus(dev, "i2c"); @@ -423,19 +424,20 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp) * public datasheet which is very similar (implementing * MMC Specification Version 4.0 being the only difference noted) */ - dev = qdev_create(NULL, TYPE_S3C_SDHCI); + dev = qdev_new(TYPE_S3C_SDHCI); qdev_prop_set_uint64(dev, "capareg", EXYNOS4210_SDHCI_CAPABILITIES); - qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, EXYNOS4210_SDHCI_ADDR(n)); sysbus_connect_irq(busdev, 0, s->irq_table[exynos4210_get_irq(29, n)]); di = drive_get(IF_SD, 0, n); blk = di ? blk_by_legacy_dinfo(di) : NULL; - carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD); - qdev_prop_set_drive(carddev, "drive", blk, &error_abort); - qdev_init_nofail(carddev); + carddev = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive(carddev, "drive", blk); + qdev_realize_and_unref(carddev, qdev_get_child_bus(dev, "sd-bus"), + &error_fatal); } /*** Display controller (FIMD) ***/ @@ -481,8 +483,7 @@ static void exynos4210_init(Object *obj) char *name = g_strdup_printf("pl330-irq-orgate%d", i); qemu_or_irq *orgate = &s->pl330_irq_orgate[i]; - object_initialize_child(obj, name, orgate, sizeof(*orgate), - TYPE_OR_IRQ, &error_abort, NULL); + object_initialize_child(obj, name, orgate, TYPE_OR_IRQ); g_free(name); } } diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c index 09da52876d6ee9688abf9c54a2f070fd09ce2101..56b729141b51c5f00d97dc9505bc76afece081da 100644 --- a/hw/arm/exynos4_boards.c +++ b/hw/arm/exynos4_boards.c @@ -81,11 +81,11 @@ static void lan9215_init(uint32_t base, qemu_irq irq) /* This should be a 9215 but the 9118 is close enough */ if (nd_table[0].used) { qemu_check_nic_model(&nd_table[0], "lan9118"); - dev = qdev_create(NULL, TYPE_LAN9118); + dev = qdev_new(TYPE_LAN9118); qdev_set_nic_properties(dev, &nd_table[0]); qdev_prop_set_uint32(dev, "mode_16bit", 1); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, base); sysbus_connect_irq(s, 0, irq); } @@ -128,10 +128,9 @@ exynos4_boards_init_common(MachineState *machine, exynos4_boards_init_ram(s, get_system_memory(), exynos4_board_ram_size[board_type]); - sysbus_init_child_obj(OBJECT(machine), "soc", - &s->soc, sizeof(s->soc), TYPE_EXYNOS4210_SOC); - object_property_set_bool(OBJECT(&s->soc), true, "realized", - &error_fatal); + object_initialize_child(OBJECT(machine), "soc", &s->soc, + TYPE_EXYNOS4210_SOC); + sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal); return s; } diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c index cdaa79c26bd074b8874f6a053773657556b56c1a..08a98f828fc8b7b411d971323d97be1a73109387 100644 --- a/hw/arm/fsl-imx25.c +++ b/hw/arm/fsl-imx25.c @@ -38,56 +38,45 @@ static void fsl_imx25_init(Object *obj) FslIMX25State *s = FSL_IMX25(obj); int i; - object_initialize_child(obj, "cpu", &s->cpu, sizeof(s->cpu), - ARM_CPU_TYPE_NAME("arm926"), - &error_abort, NULL); + object_initialize_child(obj, "cpu", &s->cpu, ARM_CPU_TYPE_NAME("arm926")); - sysbus_init_child_obj(obj, "avic", &s->avic, sizeof(s->avic), - TYPE_IMX_AVIC); + object_initialize_child(obj, "avic", &s->avic, TYPE_IMX_AVIC); - sysbus_init_child_obj(obj, "ccm", &s->ccm, sizeof(s->ccm), TYPE_IMX25_CCM); + object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX25_CCM); for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) { - sysbus_init_child_obj(obj, "uart[*]", &s->uart[i], sizeof(s->uart[i]), - TYPE_IMX_SERIAL); + object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_IMX_SERIAL); } for (i = 0; i < FSL_IMX25_NUM_GPTS; i++) { - sysbus_init_child_obj(obj, "gpt[*]", &s->gpt[i], sizeof(s->gpt[i]), - TYPE_IMX25_GPT); + object_initialize_child(obj, "gpt[*]", &s->gpt[i], TYPE_IMX25_GPT); } for (i = 0; i < FSL_IMX25_NUM_EPITS; i++) { - sysbus_init_child_obj(obj, "epit[*]", &s->epit[i], sizeof(s->epit[i]), - TYPE_IMX_EPIT); + object_initialize_child(obj, "epit[*]", &s->epit[i], TYPE_IMX_EPIT); } - sysbus_init_child_obj(obj, "fec", &s->fec, sizeof(s->fec), TYPE_IMX_FEC); + object_initialize_child(obj, "fec", &s->fec, TYPE_IMX_FEC); - sysbus_init_child_obj(obj, "rngc", &s->rngc, sizeof(s->rngc), - TYPE_IMX_RNGC); + object_initialize_child(obj, "rngc", &s->rngc, TYPE_IMX_RNGC); for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) { - sysbus_init_child_obj(obj, "i2c[*]", &s->i2c[i], sizeof(s->i2c[i]), - TYPE_IMX_I2C); + object_initialize_child(obj, "i2c[*]", &s->i2c[i], TYPE_IMX_I2C); } for (i = 0; i < FSL_IMX25_NUM_GPIOS; i++) { - sysbus_init_child_obj(obj, "gpio[*]", &s->gpio[i], sizeof(s->gpio[i]), - TYPE_IMX_GPIO); + object_initialize_child(obj, "gpio[*]", &s->gpio[i], TYPE_IMX_GPIO); } for (i = 0; i < FSL_IMX25_NUM_ESDHCS; i++) { - sysbus_init_child_obj(obj, "sdhc[*]", &s->esdhc[i], sizeof(s->esdhc[i]), - TYPE_IMX_USDHC); + object_initialize_child(obj, "sdhc[*]", &s->esdhc[i], TYPE_IMX_USDHC); } for (i = 0; i < FSL_IMX25_NUM_USBS; i++) { - sysbus_init_child_obj(obj, "usb[*]", &s->usb[i], sizeof(s->usb[i]), - TYPE_CHIPIDEA); + object_initialize_child(obj, "usb[*]", &s->usb[i], TYPE_CHIPIDEA); } - sysbus_init_child_obj(obj, "wdt", &s->wdt, sizeof(s->wdt), TYPE_IMX2_WDT); + object_initialize_child(obj, "wdt", &s->wdt, TYPE_IMX2_WDT); } static void fsl_imx25_realize(DeviceState *dev, Error **errp) @@ -96,15 +85,11 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) uint8_t i; Error *err = NULL; - object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->cpu), NULL, errp)) { return; } - object_property_set_bool(OBJECT(&s->avic), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->avic), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->avic), 0, FSL_IMX25_AVIC_ADDR); @@ -113,9 +98,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 1, qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ)); - object_property_set_bool(OBJECT(&s->ccm), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->ccm), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX25_CCM_ADDR); @@ -135,9 +118,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i)); - object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr); @@ -160,9 +141,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) s->gpt[i].ccm = IMX_CCM(&s->ccm); - object_property_set_bool(OBJECT(&s->gpt[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpt[i]), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, gpt_table[i].addr); @@ -183,9 +162,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) s->epit[i].ccm = IMX_CCM(&s->ccm); - object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->epit[i]), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->epit[i]), 0, epit_table[i].addr); @@ -194,20 +171,17 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) epit_table[i].irq)); } + object_property_set_uint(OBJECT(&s->fec), "phy-num", s->phy_num, &err); qdev_set_nic_properties(DEVICE(&s->fec), &nd_table[0]); - object_property_set_bool(OBJECT(&s->fec), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->fec), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->fec), 0, FSL_IMX25_FEC_ADDR); sysbus_connect_irq(SYS_BUS_DEVICE(&s->fec), 0, qdev_get_gpio_in(DEVICE(&s->avic), FSL_IMX25_FEC_IRQ)); - object_property_set_bool(OBJECT(&s->rngc), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->rngc), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->rngc), 0, FSL_IMX25_RNGC_ADDR); @@ -225,9 +199,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) { FSL_IMX25_I2C3_ADDR, FSL_IMX25_I2C3_IRQ } }; - object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c[i]), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr); @@ -248,9 +220,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) { FSL_IMX25_GPIO4_ADDR, FSL_IMX25_GPIO4_IRQ } }; - object_property_set_bool(OBJECT(&s->gpio[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr); @@ -270,13 +240,13 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) { FSL_IMX25_ESDHC2_ADDR, FSL_IMX25_ESDHC2_IRQ }, }; - object_property_set_uint(OBJECT(&s->esdhc[i]), 2, "sd-spec-version", - &err); - object_property_set_uint(OBJECT(&s->esdhc[i]), IMX25_ESDHC_CAPABILITIES, - "capareg", &err); - object_property_set_bool(OBJECT(&s->esdhc[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + object_property_set_uint(OBJECT(&s->esdhc[i]), "sd-spec-version", 2, + &error_abort); + object_property_set_uint(OBJECT(&s->esdhc[i]), "capareg", + IMX25_ESDHC_CAPABILITIES, &error_abort); + object_property_set_uint(OBJECT(&s->esdhc[i]), "vendor", + SDHCI_VENDOR_IMX, &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->esdhc[i]), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->esdhc[i]), 0, esdhc_table[i].addr); @@ -295,8 +265,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) { FSL_IMX25_USB2_ADDR, FSL_IMX25_USB2_IRQ }, }; - object_property_set_bool(OBJECT(&s->usb[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->usb[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, usb_table[i].addr); sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i]), 0, qdev_get_gpio_in(DEVICE(&s->avic), @@ -304,9 +273,9 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) } /* Watchdog */ - object_property_set_bool(OBJECT(&s->wdt), true, "pretimeout-support", + object_property_set_bool(OBJECT(&s->wdt), "pretimeout-support", true, &error_abort); - object_property_set_bool(OBJECT(&s->wdt), true, "realized", &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->wdt), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0, FSL_IMX25_WDT_ADDR); sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt), 0, qdev_get_gpio_in(DEVICE(&s->avic), @@ -347,10 +316,16 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) &s->iram_alias); } +static Property fsl_imx25_properties[] = { + DEFINE_PROP_UINT32("fec-phy-num", FslIMX25State, phy_num, 0), + DEFINE_PROP_END_OF_LIST(), +}; + static void fsl_imx25_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); + device_class_set_props(dc, fsl_imx25_properties); dc->realize = fsl_imx25_realize; dc->desc = "i.MX25 SOC"; /* diff --git a/hw/arm/fsl-imx31.c b/hw/arm/fsl-imx31.c index 1e7959863dd049d5a5f12db4cbde7fcbc6f60ed1..0983998bb4b08393ab0c9fb87727b0e45bc70609 100644 --- a/hw/arm/fsl-imx31.c +++ b/hw/arm/fsl-imx31.c @@ -33,38 +33,31 @@ static void fsl_imx31_init(Object *obj) FslIMX31State *s = FSL_IMX31(obj); int i; - object_initialize_child(obj, "cpu", &s->cpu, sizeof(s->cpu), - ARM_CPU_TYPE_NAME("arm1136"), - &error_abort, NULL); + object_initialize_child(obj, "cpu", &s->cpu, ARM_CPU_TYPE_NAME("arm1136")); - sysbus_init_child_obj(obj, "avic", &s->avic, sizeof(s->avic), - TYPE_IMX_AVIC); + object_initialize_child(obj, "avic", &s->avic, TYPE_IMX_AVIC); - sysbus_init_child_obj(obj, "ccm", &s->ccm, sizeof(s->ccm), TYPE_IMX31_CCM); + object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX31_CCM); for (i = 0; i < FSL_IMX31_NUM_UARTS; i++) { - sysbus_init_child_obj(obj, "uart[*]", &s->uart[i], sizeof(s->uart[i]), - TYPE_IMX_SERIAL); + object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_IMX_SERIAL); } - sysbus_init_child_obj(obj, "gpt", &s->gpt, sizeof(s->gpt), TYPE_IMX31_GPT); + object_initialize_child(obj, "gpt", &s->gpt, TYPE_IMX31_GPT); for (i = 0; i < FSL_IMX31_NUM_EPITS; i++) { - sysbus_init_child_obj(obj, "epit[*]", &s->epit[i], sizeof(s->epit[i]), - TYPE_IMX_EPIT); + object_initialize_child(obj, "epit[*]", &s->epit[i], TYPE_IMX_EPIT); } for (i = 0; i < FSL_IMX31_NUM_I2CS; i++) { - sysbus_init_child_obj(obj, "i2c[*]", &s->i2c[i], sizeof(s->i2c[i]), - TYPE_IMX_I2C); + object_initialize_child(obj, "i2c[*]", &s->i2c[i], TYPE_IMX_I2C); } for (i = 0; i < FSL_IMX31_NUM_GPIOS; i++) { - sysbus_init_child_obj(obj, "gpio[*]", &s->gpio[i], sizeof(s->gpio[i]), - TYPE_IMX_GPIO); + object_initialize_child(obj, "gpio[*]", &s->gpio[i], TYPE_IMX_GPIO); } - sysbus_init_child_obj(obj, "wdt", &s->wdt, sizeof(s->wdt), TYPE_IMX2_WDT); + object_initialize_child(obj, "wdt", &s->wdt, TYPE_IMX2_WDT); } static void fsl_imx31_realize(DeviceState *dev, Error **errp) @@ -73,15 +66,11 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp) uint16_t i; Error *err = NULL; - object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->cpu), NULL, errp)) { return; } - object_property_set_bool(OBJECT(&s->avic), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->avic), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->avic), 0, FSL_IMX31_AVIC_ADDR); @@ -90,9 +79,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 1, qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ)); - object_property_set_bool(OBJECT(&s->ccm), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->ccm), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX31_CCM_ADDR); @@ -109,9 +96,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp) qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i)); - object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) { return; } @@ -123,9 +108,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp) s->gpt.ccm = IMX_CCM(&s->ccm); - object_property_set_bool(OBJECT(&s->gpt), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpt), errp)) { return; } @@ -145,9 +128,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp) s->epit[i].ccm = IMX_CCM(&s->ccm); - object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->epit[i]), errp)) { return; } @@ -169,9 +150,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp) }; /* Initialize the I2C */ - object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c[i]), errp)) { return; } /* Map I2C memory */ @@ -193,11 +172,9 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp) { FSL_IMX31_GPIO3_ADDR, FSL_IMX31_GPIO3_IRQ } }; - object_property_set_bool(OBJECT(&s->gpio[i]), false, "has-edge-sel", + object_property_set_bool(OBJECT(&s->gpio[i]), "has-edge-sel", false, &error_abort); - object_property_set_bool(OBJECT(&s->gpio[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr); @@ -208,7 +185,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp) } /* Watchdog */ - object_property_set_bool(OBJECT(&s->wdt), true, "realized", &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->wdt), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0, FSL_IMX31_WDT_ADDR); /* On a real system, the first 16k is a `secure boot rom' */ diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c index f58c85aa8ce70d077eb08b49a9f4ad8b5f967dad..00dafe3f62dee011c9249807ae1894082728c97e 100644 --- a/hw/arm/fsl-imx6.c +++ b/hw/arm/fsl-imx6.c @@ -43,74 +43,63 @@ static void fsl_imx6_init(Object *obj) for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX6_NUM_CPUS); i++) { snprintf(name, NAME_SIZE, "cpu%d", i); - object_initialize_child(obj, name, &s->cpu[i], sizeof(s->cpu[i]), - ARM_CPU_TYPE_NAME("cortex-a9"), - &error_abort, NULL); + object_initialize_child(obj, name, &s->cpu[i], + ARM_CPU_TYPE_NAME("cortex-a9")); } - sysbus_init_child_obj(obj, "a9mpcore", &s->a9mpcore, sizeof(s->a9mpcore), - TYPE_A9MPCORE_PRIV); + object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV); - sysbus_init_child_obj(obj, "ccm", &s->ccm, sizeof(s->ccm), TYPE_IMX6_CCM); + object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX6_CCM); - sysbus_init_child_obj(obj, "src", &s->src, sizeof(s->src), TYPE_IMX6_SRC); + object_initialize_child(obj, "src", &s->src, TYPE_IMX6_SRC); for (i = 0; i < FSL_IMX6_NUM_UARTS; i++) { snprintf(name, NAME_SIZE, "uart%d", i + 1); - sysbus_init_child_obj(obj, name, &s->uart[i], sizeof(s->uart[i]), - TYPE_IMX_SERIAL); + object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL); } - sysbus_init_child_obj(obj, "gpt", &s->gpt, sizeof(s->gpt), TYPE_IMX6_GPT); + object_initialize_child(obj, "gpt", &s->gpt, TYPE_IMX6_GPT); for (i = 0; i < FSL_IMX6_NUM_EPITS; i++) { snprintf(name, NAME_SIZE, "epit%d", i + 1); - sysbus_init_child_obj(obj, name, &s->epit[i], sizeof(s->epit[i]), - TYPE_IMX_EPIT); + object_initialize_child(obj, name, &s->epit[i], TYPE_IMX_EPIT); } for (i = 0; i < FSL_IMX6_NUM_I2CS; i++) { snprintf(name, NAME_SIZE, "i2c%d", i + 1); - sysbus_init_child_obj(obj, name, &s->i2c[i], sizeof(s->i2c[i]), - TYPE_IMX_I2C); + object_initialize_child(obj, name, &s->i2c[i], TYPE_IMX_I2C); } for (i = 0; i < FSL_IMX6_NUM_GPIOS; i++) { snprintf(name, NAME_SIZE, "gpio%d", i + 1); - sysbus_init_child_obj(obj, name, &s->gpio[i], sizeof(s->gpio[i]), - TYPE_IMX_GPIO); + object_initialize_child(obj, name, &s->gpio[i], TYPE_IMX_GPIO); } for (i = 0; i < FSL_IMX6_NUM_ESDHCS; i++) { snprintf(name, NAME_SIZE, "sdhc%d", i + 1); - sysbus_init_child_obj(obj, name, &s->esdhc[i], sizeof(s->esdhc[i]), - TYPE_IMX_USDHC); + object_initialize_child(obj, name, &s->esdhc[i], TYPE_IMX_USDHC); } for (i = 0; i < FSL_IMX6_NUM_USB_PHYS; i++) { snprintf(name, NAME_SIZE, "usbphy%d", i); - sysbus_init_child_obj(obj, name, &s->usbphy[i], sizeof(s->usbphy[i]), - TYPE_IMX_USBPHY); + object_initialize_child(obj, name, &s->usbphy[i], TYPE_IMX_USBPHY); } for (i = 0; i < FSL_IMX6_NUM_USBS; i++) { snprintf(name, NAME_SIZE, "usb%d", i); - sysbus_init_child_obj(obj, name, &s->usb[i], sizeof(s->usb[i]), - TYPE_CHIPIDEA); + object_initialize_child(obj, name, &s->usb[i], TYPE_CHIPIDEA); } for (i = 0; i < FSL_IMX6_NUM_ECSPIS; i++) { snprintf(name, NAME_SIZE, "spi%d", i + 1); - sysbus_init_child_obj(obj, name, &s->spi[i], sizeof(s->spi[i]), - TYPE_IMX_SPI); + object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI); } for (i = 0; i < FSL_IMX6_NUM_WDTS; i++) { snprintf(name, NAME_SIZE, "wdt%d", i); - sysbus_init_child_obj(obj, name, &s->wdt[i], sizeof(s->wdt[i]), - TYPE_IMX2_WDT); + object_initialize_child(obj, name, &s->wdt[i], TYPE_IMX2_WDT); } - sysbus_init_child_obj(obj, "eth", &s->eth, sizeof(s->eth), TYPE_IMX_ENET); + object_initialize_child(obj, "eth", &s->eth, TYPE_IMX_ENET); } static void fsl_imx6_realize(DeviceState *dev, Error **errp) @@ -131,33 +120,28 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) /* On uniprocessor, the CBAR is set to 0 */ if (smp_cpus > 1) { - object_property_set_int(OBJECT(&s->cpu[i]), FSL_IMX6_A9MPCORE_ADDR, - "reset-cbar", &error_abort); + object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar", + FSL_IMX6_A9MPCORE_ADDR, &error_abort); } /* All CPU but CPU 0 start in power off mode */ if (i) { - object_property_set_bool(OBJECT(&s->cpu[i]), true, - "start-powered-off", &error_abort); + object_property_set_bool(OBJECT(&s->cpu[i]), "start-powered-off", + true, &error_abort); } - object_property_set_bool(OBJECT(&s->cpu[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) { return; } } - object_property_set_int(OBJECT(&s->a9mpcore), smp_cpus, "num-cpu", + object_property_set_int(OBJECT(&s->a9mpcore), "num-cpu", smp_cpus, &error_abort); - object_property_set_int(OBJECT(&s->a9mpcore), - FSL_IMX6_MAX_IRQ + GIC_INTERNAL, "num-irq", - &error_abort); + object_property_set_int(OBJECT(&s->a9mpcore), "num-irq", + FSL_IMX6_MAX_IRQ + GIC_INTERNAL, &error_abort); - object_property_set_bool(OBJECT(&s->a9mpcore), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->a9mpcore), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->a9mpcore), 0, FSL_IMX6_A9MPCORE_ADDR); @@ -169,16 +153,12 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_FIQ)); } - object_property_set_bool(OBJECT(&s->ccm), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->ccm), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX6_CCM_ADDR); - object_property_set_bool(OBJECT(&s->src), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->src), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->src), 0, FSL_IMX6_SRC_ADDR); @@ -198,9 +178,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i)); - object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) { return; } @@ -212,9 +190,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) s->gpt.ccm = IMX_CCM(&s->ccm); - object_property_set_bool(OBJECT(&s->gpt), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpt), errp)) { return; } @@ -235,9 +211,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) s->epit[i].ccm = IMX_CCM(&s->ccm); - object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->epit[i]), errp)) { return; } @@ -258,9 +232,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) { FSL_IMX6_I2C3_ADDR, FSL_IMX6_I2C3_IRQ } }; - object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c[i]), errp)) { return; } @@ -314,13 +286,11 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) }, }; - object_property_set_bool(OBJECT(&s->gpio[i]), true, "has-edge-sel", - &error_abort); - object_property_set_bool(OBJECT(&s->gpio[i]), true, "has-upper-pin-irq", + object_property_set_bool(OBJECT(&s->gpio[i]), "has-edge-sel", true, &error_abort); - object_property_set_bool(OBJECT(&s->gpio[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + object_property_set_bool(OBJECT(&s->gpio[i]), "has-upper-pin-irq", + true, &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), errp)) { return; } @@ -346,13 +316,13 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) }; /* UHS-I SDIO3.0 SDR104 1.8V ADMA */ - object_property_set_uint(OBJECT(&s->esdhc[i]), 3, "sd-spec-version", - &err); - object_property_set_uint(OBJECT(&s->esdhc[i]), IMX6_ESDHC_CAPABILITIES, - "capareg", &err); - object_property_set_bool(OBJECT(&s->esdhc[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + object_property_set_uint(OBJECT(&s->esdhc[i]), "sd-spec-version", 3, + &error_abort); + object_property_set_uint(OBJECT(&s->esdhc[i]), "capareg", + IMX6_ESDHC_CAPABILITIES, &error_abort); + object_property_set_uint(OBJECT(&s->esdhc[i]), "vendor", + SDHCI_VENDOR_IMX, &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->esdhc[i]), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->esdhc[i]), 0, esdhc_table[i].addr); @@ -363,8 +333,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) /* USB */ for (i = 0; i < FSL_IMX6_NUM_USB_PHYS; i++) { - object_property_set_bool(OBJECT(&s->usbphy[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->usbphy[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->usbphy[i]), 0, FSL_IMX6_USBPHY1_ADDR + i * 0x1000); } @@ -376,8 +345,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) FSL_IMX6_USB_HOST3_IRQ, }; - object_property_set_bool(OBJECT(&s->usb[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->usb[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, FSL_IMX6_USBOH3_USB_ADDR + i * 0x200); sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i]), 0, @@ -399,9 +367,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) }; /* Initialize the SPI */ - object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) { return; } @@ -411,10 +377,9 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) spi_table[i].irq)); } + object_property_set_uint(OBJECT(&s->eth), "phy-num", s->phy_num, &err); qdev_set_nic_properties(DEVICE(&s->eth), &nd_table[0]); - object_property_set_bool(OBJECT(&s->eth), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->eth), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->eth), 0, FSL_IMX6_ENET_ADDR); @@ -438,10 +403,9 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) FSL_IMX6_WDOG2_IRQ, }; - object_property_set_bool(OBJECT(&s->wdt[i]), true, "pretimeout-support", - &error_abort); - object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized", - &error_abort); + object_property_set_bool(OBJECT(&s->wdt[i]), "pretimeout-support", + true, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, FSL_IMX6_WDOGn_ADDR[i]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0, @@ -486,10 +450,16 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) &s->ocram_alias); } +static Property fsl_imx6_properties[] = { + DEFINE_PROP_UINT32("fec-phy-num", FslIMX6State, phy_num, 0), + DEFINE_PROP_END_OF_LIST(), +}; + static void fsl_imx6_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); + device_class_set_props(dc, fsl_imx6_properties); dc->realize = fsl_imx6_realize; dc->desc = "i.MX6 SOC"; /* Reason: Uses serial_hd() in the realize() function */ diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c index 3ecb212da6ffefe32d932c95e278666615f8a6e3..e0128d7316112bb61d50b39d0c1e79d61b19fbef 100644 --- a/hw/arm/fsl-imx6ul.c +++ b/hw/arm/fsl-imx6ul.c @@ -34,50 +34,46 @@ static void fsl_imx6ul_init(Object *obj) char name[NAME_SIZE]; int i; - object_initialize_child(obj, "cpu0", &s->cpu, sizeof(s->cpu), - ARM_CPU_TYPE_NAME("cortex-a7"), &error_abort, NULL); + object_initialize_child(obj, "cpu0", &s->cpu, + ARM_CPU_TYPE_NAME("cortex-a7")); /* * A7MPCORE */ - sysbus_init_child_obj(obj, "a7mpcore", &s->a7mpcore, sizeof(s->a7mpcore), - TYPE_A15MPCORE_PRIV); + object_initialize_child(obj, "a7mpcore", &s->a7mpcore, + TYPE_A15MPCORE_PRIV); /* * CCM */ - sysbus_init_child_obj(obj, "ccm", &s->ccm, sizeof(s->ccm), TYPE_IMX6UL_CCM); + object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX6UL_CCM); /* * SRC */ - sysbus_init_child_obj(obj, "src", &s->src, sizeof(s->src), TYPE_IMX6_SRC); + object_initialize_child(obj, "src", &s->src, TYPE_IMX6_SRC); /* * GPCv2 */ - sysbus_init_child_obj(obj, "gpcv2", &s->gpcv2, sizeof(s->gpcv2), - TYPE_IMX_GPCV2); + object_initialize_child(obj, "gpcv2", &s->gpcv2, TYPE_IMX_GPCV2); /* * SNVS */ - sysbus_init_child_obj(obj, "snvs", &s->snvs, sizeof(s->snvs), - TYPE_IMX7_SNVS); + object_initialize_child(obj, "snvs", &s->snvs, TYPE_IMX7_SNVS); /* * GPR */ - sysbus_init_child_obj(obj, "gpr", &s->gpr, sizeof(s->gpr), - TYPE_IMX7_GPR); + object_initialize_child(obj, "gpr", &s->gpr, TYPE_IMX7_GPR); /* * GPIOs 1 to 5 */ for (i = 0; i < FSL_IMX6UL_NUM_GPIOS; i++) { snprintf(name, NAME_SIZE, "gpio%d", i); - sysbus_init_child_obj(obj, name, &s->gpio[i], sizeof(s->gpio[i]), - TYPE_IMX_GPIO); + object_initialize_child(obj, name, &s->gpio[i], TYPE_IMX_GPIO); } /* @@ -85,8 +81,7 @@ static void fsl_imx6ul_init(Object *obj) */ for (i = 0; i < FSL_IMX6UL_NUM_GPTS; i++) { snprintf(name, NAME_SIZE, "gpt%d", i); - sysbus_init_child_obj(obj, name, &s->gpt[i], sizeof(s->gpt[i]), - TYPE_IMX7_GPT); + object_initialize_child(obj, name, &s->gpt[i], TYPE_IMX7_GPT); } /* @@ -94,8 +89,7 @@ static void fsl_imx6ul_init(Object *obj) */ for (i = 0; i < FSL_IMX6UL_NUM_EPITS; i++) { snprintf(name, NAME_SIZE, "epit%d", i + 1); - sysbus_init_child_obj(obj, name, &s->epit[i], sizeof(s->epit[i]), - TYPE_IMX_EPIT); + object_initialize_child(obj, name, &s->epit[i], TYPE_IMX_EPIT); } /* @@ -103,8 +97,7 @@ static void fsl_imx6ul_init(Object *obj) */ for (i = 0; i < FSL_IMX6UL_NUM_ECSPIS; i++) { snprintf(name, NAME_SIZE, "spi%d", i + 1); - sysbus_init_child_obj(obj, name, &s->spi[i], sizeof(s->spi[i]), - TYPE_IMX_SPI); + object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI); } /* @@ -112,8 +105,7 @@ static void fsl_imx6ul_init(Object *obj) */ for (i = 0; i < FSL_IMX6UL_NUM_I2CS; i++) { snprintf(name, NAME_SIZE, "i2c%d", i + 1); - sysbus_init_child_obj(obj, name, &s->i2c[i], sizeof(s->i2c[i]), - TYPE_IMX_I2C); + object_initialize_child(obj, name, &s->i2c[i], TYPE_IMX_I2C); } /* @@ -121,8 +113,7 @@ static void fsl_imx6ul_init(Object *obj) */ for (i = 0; i < FSL_IMX6UL_NUM_UARTS; i++) { snprintf(name, NAME_SIZE, "uart%d", i); - sysbus_init_child_obj(obj, name, &s->uart[i], sizeof(s->uart[i]), - TYPE_IMX_SERIAL); + object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL); } /* @@ -130,20 +121,17 @@ static void fsl_imx6ul_init(Object *obj) */ for (i = 0; i < FSL_IMX6UL_NUM_ETHS; i++) { snprintf(name, NAME_SIZE, "eth%d", i); - sysbus_init_child_obj(obj, name, &s->eth[i], sizeof(s->eth[i]), - TYPE_IMX_ENET); + object_initialize_child(obj, name, &s->eth[i], TYPE_IMX_ENET); } /* USB */ for (i = 0; i < FSL_IMX6UL_NUM_USB_PHYS; i++) { snprintf(name, NAME_SIZE, "usbphy%d", i); - sysbus_init_child_obj(obj, name, &s->usbphy[i], sizeof(s->usbphy[i]), - TYPE_IMX_USBPHY); + object_initialize_child(obj, name, &s->usbphy[i], TYPE_IMX_USBPHY); } for (i = 0; i < FSL_IMX6UL_NUM_USBS; i++) { snprintf(name, NAME_SIZE, "usb%d", i); - sysbus_init_child_obj(obj, name, &s->usb[i], sizeof(s->usb[i]), - TYPE_CHIPIDEA); + object_initialize_child(obj, name, &s->usb[i], TYPE_CHIPIDEA); } /* @@ -151,8 +139,7 @@ static void fsl_imx6ul_init(Object *obj) */ for (i = 0; i < FSL_IMX6UL_NUM_USDHCS; i++) { snprintf(name, NAME_SIZE, "usdhc%d", i); - sysbus_init_child_obj(obj, name, &s->usdhc[i], sizeof(s->usdhc[i]), - TYPE_IMX_USDHC); + object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC); } /* @@ -160,8 +147,7 @@ static void fsl_imx6ul_init(Object *obj) */ for (i = 0; i < FSL_IMX6UL_NUM_WDTS; i++) { snprintf(name, NAME_SIZE, "wdt%d", i); - sysbus_init_child_obj(obj, name, &s->wdt[i], sizeof(s->wdt[i]), - TYPE_IMX2_WDT); + object_initialize_child(obj, name, &s->wdt[i], TYPE_IMX2_WDT); } } @@ -180,20 +166,17 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) return; } - object_property_set_int(OBJECT(&s->cpu), QEMU_PSCI_CONDUIT_SMC, - "psci-conduit", &error_abort); - object_property_set_bool(OBJECT(&s->cpu), true, - "realized", &error_abort); + object_property_set_int(OBJECT(&s->cpu), "psci-conduit", + QEMU_PSCI_CONDUIT_SMC, &error_abort); + qdev_realize(DEVICE(&s->cpu), NULL, &error_abort); /* * A7MPCORE */ - object_property_set_int(OBJECT(&s->a7mpcore), 1, "num-cpu", &error_abort); - object_property_set_int(OBJECT(&s->a7mpcore), - FSL_IMX6UL_MAX_IRQ + GIC_INTERNAL, - "num-irq", &error_abort); - object_property_set_bool(OBJECT(&s->a7mpcore), true, "realized", - &error_abort); + object_property_set_int(OBJECT(&s->a7mpcore), "num-cpu", 1, &error_abort); + object_property_set_int(OBJECT(&s->a7mpcore), "num-irq", + FSL_IMX6UL_MAX_IRQ + GIC_INTERNAL, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->a7mpcore), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->a7mpcore), 0, FSL_IMX6UL_A7MPCORE_ADDR); sbd = SYS_BUS_DEVICE(&s->a7mpcore); @@ -225,8 +208,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) }; s->gpt[i].ccm = IMX_CCM(&s->ccm); - object_property_set_bool(OBJECT(&s->gpt[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->gpt[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, FSL_IMX6UL_GPTn_ADDR[i]); @@ -251,8 +233,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) }; s->epit[i].ccm = IMX_CCM(&s->ccm); - object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->epit[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->epit[i]), 0, FSL_IMX6UL_EPITn_ADDR[i]); @@ -290,8 +271,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) FSL_IMX6UL_GPIO5_HIGH_IRQ, }; - object_property_set_bool(OBJECT(&s->gpio[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, FSL_IMX6UL_GPIOn_ADDR[i]); @@ -321,20 +301,19 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) /* * CCM */ - object_property_set_bool(OBJECT(&s->ccm), true, "realized", &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->ccm), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX6UL_CCM_ADDR); /* * SRC */ - object_property_set_bool(OBJECT(&s->src), true, "realized", &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->src), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->src), 0, FSL_IMX6UL_SRC_ADDR); /* * GPCv2 */ - object_property_set_bool(OBJECT(&s->gpcv2), true, - "realized", &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->gpcv2), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpcv2), 0, FSL_IMX6UL_GPC_ADDR); /* Initialize all ECSPI */ @@ -354,8 +333,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) }; /* Initialize the SPI */ - object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, FSL_IMX6UL_SPIn_ADDR[i]); @@ -383,8 +361,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) FSL_IMX6UL_I2C4_IRQ, }; - object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->i2c[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, FSL_IMX6UL_I2Cn_ADDR[i]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0, @@ -420,8 +397,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i)); - object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, FSL_IMX6UL_UARTn_ADDR[i]); @@ -450,12 +426,12 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) FSL_IMX6UL_ENET2_TIMER_IRQ, }; - object_property_set_uint(OBJECT(&s->eth[i]), - FSL_IMX6UL_ETH_NUM_TX_RINGS, - "tx-ring-num", &error_abort); + object_property_set_uint(OBJECT(&s->eth[i]), "phy-num", + s->phy_num[i], &error_abort); + object_property_set_uint(OBJECT(&s->eth[i]), "tx-ring-num", + FSL_IMX6UL_ETH_NUM_TX_RINGS, &error_abort); qdev_set_nic_properties(DEVICE(&s->eth[i]), &nd_table[i]); - object_property_set_bool(OBJECT(&s->eth[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->eth[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->eth[i]), 0, FSL_IMX6UL_ENETn_ADDR[i]); @@ -471,8 +447,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) /* USB */ for (i = 0; i < FSL_IMX6UL_NUM_USB_PHYS; i++) { - object_property_set_bool(OBJECT(&s->usbphy[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->usbphy[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->usbphy[i]), 0, FSL_IMX6UL_USBPHY1_ADDR + i * 0x1000); } @@ -482,8 +457,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) FSL_IMX6UL_USB1_IRQ, FSL_IMX6UL_USB2_IRQ, }; - object_property_set_bool(OBJECT(&s->usb[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->usb[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, FSL_IMX6UL_USBO2_USB_ADDR + i * 0x200); sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i]), 0, @@ -505,8 +479,9 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) FSL_IMX6UL_USDHC2_IRQ, }; - object_property_set_bool(OBJECT(&s->usdhc[i]), true, "realized", - &error_abort); + object_property_set_uint(OBJECT(&s->usdhc[i]), "vendor", + SDHCI_VENDOR_IMX, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->usdhc[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0, FSL_IMX6UL_USDHCn_ADDR[i]); @@ -519,7 +494,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) /* * SNVS */ - object_property_set_bool(OBJECT(&s->snvs), true, "realized", &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->snvs), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0, FSL_IMX6UL_SNVS_HP_ADDR); /* @@ -537,10 +512,9 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) FSL_IMX6UL_WDOG3_IRQ, }; - object_property_set_bool(OBJECT(&s->wdt[i]), true, "pretimeout-support", - &error_abort); - object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized", - &error_abort); + object_property_set_bool(OBJECT(&s->wdt[i]), "pretimeout-support", + true, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, FSL_IMX6UL_WDOGn_ADDR[i]); @@ -552,8 +526,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) /* * GPR */ - object_property_set_bool(OBJECT(&s->gpr), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->gpr), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0, FSL_IMX6UL_IOMUXC_GPR_ADDR); /* @@ -634,10 +607,17 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) FSL_IMX6UL_OCRAM_ALIAS_ADDR, &s->ocram_alias); } +static Property fsl_imx6ul_properties[] = { + DEFINE_PROP_UINT32("fec1-phy-num", FslIMX6ULState, phy_num[0], 0), + DEFINE_PROP_UINT32("fec2-phy-num", FslIMX6ULState, phy_num[1], 1), + DEFINE_PROP_END_OF_LIST(), +}; + static void fsl_imx6ul_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); + device_class_set_props(dc, fsl_imx6ul_properties); dc->realize = fsl_imx6ul_realize; dc->desc = "i.MX6UL SOC"; /* Reason: Uses serial_hds and nd_table in realize() directly */ diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c index 89c3b64c06668d4f7fcf6b1730b9b931df87df2b..2ff2cab9246cc60096e243ea2d83c636d61a115b 100644 --- a/hw/arm/fsl-imx7.c +++ b/hw/arm/fsl-imx7.c @@ -38,24 +38,22 @@ static void fsl_imx7_init(Object *obj) for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX7_NUM_CPUS); i++) { snprintf(name, NAME_SIZE, "cpu%d", i); - object_initialize_child(obj, name, &s->cpu[i], sizeof(s->cpu[i]), - ARM_CPU_TYPE_NAME("cortex-a7"), &error_abort, - NULL); + object_initialize_child(obj, name, &s->cpu[i], + ARM_CPU_TYPE_NAME("cortex-a7")); } /* * A7MPCORE */ - sysbus_init_child_obj(obj, "a7mpcore", &s->a7mpcore, sizeof(s->a7mpcore), - TYPE_A15MPCORE_PRIV); + object_initialize_child(obj, "a7mpcore", &s->a7mpcore, + TYPE_A15MPCORE_PRIV); /* * GPIOs 1 to 7 */ for (i = 0; i < FSL_IMX7_NUM_GPIOS; i++) { snprintf(name, NAME_SIZE, "gpio%d", i); - sysbus_init_child_obj(obj, name, &s->gpio[i], sizeof(s->gpio[i]), - TYPE_IMX_GPIO); + object_initialize_child(obj, name, &s->gpio[i], TYPE_IMX_GPIO); } /* @@ -63,38 +61,33 @@ static void fsl_imx7_init(Object *obj) */ for (i = 0; i < FSL_IMX7_NUM_GPTS; i++) { snprintf(name, NAME_SIZE, "gpt%d", i); - sysbus_init_child_obj(obj, name, &s->gpt[i], sizeof(s->gpt[i]), - TYPE_IMX7_GPT); + object_initialize_child(obj, name, &s->gpt[i], TYPE_IMX7_GPT); } /* * CCM */ - sysbus_init_child_obj(obj, "ccm", &s->ccm, sizeof(s->ccm), TYPE_IMX7_CCM); + object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX7_CCM); /* * Analog */ - sysbus_init_child_obj(obj, "analog", &s->analog, sizeof(s->analog), - TYPE_IMX7_ANALOG); + object_initialize_child(obj, "analog", &s->analog, TYPE_IMX7_ANALOG); /* * GPCv2 */ - sysbus_init_child_obj(obj, "gpcv2", &s->gpcv2, sizeof(s->gpcv2), - TYPE_IMX_GPCV2); + object_initialize_child(obj, "gpcv2", &s->gpcv2, TYPE_IMX_GPCV2); for (i = 0; i < FSL_IMX7_NUM_ECSPIS; i++) { snprintf(name, NAME_SIZE, "spi%d", i + 1); - sysbus_init_child_obj(obj, name, &s->spi[i], sizeof(s->spi[i]), - TYPE_IMX_SPI); + object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI); } for (i = 0; i < FSL_IMX7_NUM_I2CS; i++) { snprintf(name, NAME_SIZE, "i2c%d", i + 1); - sysbus_init_child_obj(obj, name, &s->i2c[i], sizeof(s->i2c[i]), - TYPE_IMX_I2C); + object_initialize_child(obj, name, &s->i2c[i], TYPE_IMX_I2C); } /* @@ -102,8 +95,7 @@ static void fsl_imx7_init(Object *obj) */ for (i = 0; i < FSL_IMX7_NUM_UARTS; i++) { snprintf(name, NAME_SIZE, "uart%d", i); - sysbus_init_child_obj(obj, name, &s->uart[i], sizeof(s->uart[i]), - TYPE_IMX_SERIAL); + object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL); } /* @@ -111,8 +103,7 @@ static void fsl_imx7_init(Object *obj) */ for (i = 0; i < FSL_IMX7_NUM_ETHS; i++) { snprintf(name, NAME_SIZE, "eth%d", i); - sysbus_init_child_obj(obj, name, &s->eth[i], sizeof(s->eth[i]), - TYPE_IMX_ENET); + object_initialize_child(obj, name, &s->eth[i], TYPE_IMX_ENET); } /* @@ -120,37 +111,32 @@ static void fsl_imx7_init(Object *obj) */ for (i = 0; i < FSL_IMX7_NUM_USDHCS; i++) { snprintf(name, NAME_SIZE, "usdhc%d", i); - sysbus_init_child_obj(obj, name, &s->usdhc[i], sizeof(s->usdhc[i]), - TYPE_IMX_USDHC); + object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC); } /* * SNVS */ - sysbus_init_child_obj(obj, "snvs", &s->snvs, sizeof(s->snvs), - TYPE_IMX7_SNVS); + object_initialize_child(obj, "snvs", &s->snvs, TYPE_IMX7_SNVS); /* * Watchdog */ for (i = 0; i < FSL_IMX7_NUM_WDTS; i++) { snprintf(name, NAME_SIZE, "wdt%d", i); - sysbus_init_child_obj(obj, name, &s->wdt[i], sizeof(s->wdt[i]), - TYPE_IMX2_WDT); + object_initialize_child(obj, name, &s->wdt[i], TYPE_IMX2_WDT); } /* * GPR */ - sysbus_init_child_obj(obj, "gpr", &s->gpr, sizeof(s->gpr), TYPE_IMX7_GPR); + object_initialize_child(obj, "gpr", &s->gpr, TYPE_IMX7_GPR); - sysbus_init_child_obj(obj, "pcie", &s->pcie, sizeof(s->pcie), - TYPE_DESIGNWARE_PCIE_HOST); + object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST); for (i = 0; i < FSL_IMX7_NUM_USBS; i++) { snprintf(name, NAME_SIZE, "usb%d", i); - sysbus_init_child_obj(obj, name, &s->usb[i], sizeof(s->usb[i]), - TYPE_CHIPIDEA); + object_initialize_child(obj, name, &s->usb[i], TYPE_CHIPIDEA); } } @@ -173,35 +159,33 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) for (i = 0; i < smp_cpus; i++) { o = OBJECT(&s->cpu[i]); - object_property_set_int(o, QEMU_PSCI_CONDUIT_SMC, - "psci-conduit", &error_abort); + object_property_set_int(o, "psci-conduit", QEMU_PSCI_CONDUIT_SMC, + &error_abort); /* On uniprocessor, the CBAR is set to 0 */ if (smp_cpus > 1) { - object_property_set_int(o, FSL_IMX7_A7MPCORE_ADDR, - "reset-cbar", &error_abort); + object_property_set_int(o, "reset-cbar", FSL_IMX7_A7MPCORE_ADDR, + &error_abort); } if (i) { /* Secondary CPUs start in PSCI powered-down state */ - object_property_set_bool(o, true, - "start-powered-off", &error_abort); + object_property_set_bool(o, "start-powered-off", true, + &error_abort); } - object_property_set_bool(o, true, "realized", &error_abort); + qdev_realize(DEVICE(o), NULL, &error_abort); } /* * A7MPCORE */ - object_property_set_int(OBJECT(&s->a7mpcore), smp_cpus, "num-cpu", + object_property_set_int(OBJECT(&s->a7mpcore), "num-cpu", smp_cpus, &error_abort); - object_property_set_int(OBJECT(&s->a7mpcore), - FSL_IMX7_MAX_IRQ + GIC_INTERNAL, - "num-irq", &error_abort); + object_property_set_int(OBJECT(&s->a7mpcore), "num-irq", + FSL_IMX7_MAX_IRQ + GIC_INTERNAL, &error_abort); - object_property_set_bool(OBJECT(&s->a7mpcore), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->a7mpcore), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->a7mpcore), 0, FSL_IMX7_A7MPCORE_ADDR); for (i = 0; i < smp_cpus; i++) { @@ -236,8 +220,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) }; s->gpt[i].ccm = IMX_CCM(&s->ccm); - object_property_set_bool(OBJECT(&s->gpt[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->gpt[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, FSL_IMX7_GPTn_ADDR[i]); } @@ -252,8 +235,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) FSL_IMX7_GPIO7_ADDR, }; - object_property_set_bool(OBJECT(&s->gpio[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, FSL_IMX7_GPIOn_ADDR[i]); } @@ -274,21 +256,19 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) /* * CCM */ - object_property_set_bool(OBJECT(&s->ccm), true, "realized", &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->ccm), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX7_CCM_ADDR); /* * Analog */ - object_property_set_bool(OBJECT(&s->analog), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->analog), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->analog), 0, FSL_IMX7_ANALOG_ADDR); /* * GPCv2 */ - object_property_set_bool(OBJECT(&s->gpcv2), true, - "realized", &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->gpcv2), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpcv2), 0, FSL_IMX7_GPC_ADDR); /* Initialize all ECSPI */ @@ -308,8 +288,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) }; /* Initialize the SPI */ - object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, FSL_IMX7_SPIn_ADDR[i]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0, @@ -332,8 +311,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) FSL_IMX7_I2C4_IRQ, }; - object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->i2c[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, FSL_IMX7_I2Cn_ADDR[i]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0, @@ -368,8 +346,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i)); - object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, FSL_IMX7_UARTn_ADDR[i]); @@ -386,11 +363,12 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) FSL_IMX7_ENET2_ADDR, }; - object_property_set_uint(OBJECT(&s->eth[i]), FSL_IMX7_ETH_NUM_TX_RINGS, - "tx-ring-num", &error_abort); + object_property_set_uint(OBJECT(&s->eth[i]), "phy-num", + s->phy_num[i], &error_abort); + object_property_set_uint(OBJECT(&s->eth[i]), "tx-ring-num", + FSL_IMX7_ETH_NUM_TX_RINGS, &error_abort); qdev_set_nic_properties(DEVICE(&s->eth[i]), &nd_table[i]); - object_property_set_bool(OBJECT(&s->eth[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->eth[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->eth[i]), 0, FSL_IMX7_ENETn_ADDR[i]); @@ -416,8 +394,9 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) FSL_IMX7_USDHC3_IRQ, }; - object_property_set_bool(OBJECT(&s->usdhc[i]), true, "realized", - &error_abort); + object_property_set_uint(OBJECT(&s->usdhc[i]), "vendor", + SDHCI_VENDOR_IMX, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->usdhc[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0, FSL_IMX7_USDHCn_ADDR[i]); @@ -429,7 +408,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) /* * SNVS */ - object_property_set_bool(OBJECT(&s->snvs), true, "realized", &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->snvs), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0, FSL_IMX7_SNVS_ADDR); /* @@ -454,10 +433,9 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) FSL_IMX7_WDOG4_IRQ, }; - object_property_set_bool(OBJECT(&s->wdt[i]), true, "pretimeout-support", - &error_abort); - object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized", - &error_abort); + object_property_set_bool(OBJECT(&s->wdt[i]), "pretimeout-support", + true, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, FSL_IMX7_WDOGn_ADDR[i]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0, @@ -495,12 +473,10 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) create_unimplemented_device("ocotp", FSL_IMX7_OCOTP_ADDR, FSL_IMX7_OCOTP_SIZE); - object_property_set_bool(OBJECT(&s->gpr), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->gpr), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0, FSL_IMX7_GPR_ADDR); - object_property_set_bool(OBJECT(&s->pcie), true, - "realized", &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->pcie), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie), 0, FSL_IMX7_PCIE_REG_ADDR); irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTA_IRQ); @@ -532,8 +508,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) FSL_IMX7_USB3_IRQ, }; - object_property_set_bool(OBJECT(&s->usb[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->usb[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, FSL_IMX7_USBn_ADDR[i]); @@ -577,10 +552,17 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) FSL_IMX7_PCIE_PHY_SIZE); } +static Property fsl_imx7_properties[] = { + DEFINE_PROP_UINT32("fec1-phy-num", FslIMX7State, phy_num[0], 0), + DEFINE_PROP_UINT32("fec2-phy-num", FslIMX7State, phy_num[1], 1), + DEFINE_PROP_END_OF_LIST(), +}; + static void fsl_imx7_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); + device_class_set_props(dc, fsl_imx7_properties); dc->realize = fsl_imx7_realize; /* Reason: Uses serial_hds and nd_table in realize() directly */ diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index ac9de9411ebaa75cca203ed9208a2dd6b784b4e3..f71087860d06416d148d4344d5007389e2b6b48c 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -36,6 +36,7 @@ #include "hw/cpu/a9mpcore.h" #include "hw/cpu/a15mpcore.h" #include "qemu/log.h" +#include "qom/object.h" #define SMP_BOOT_ADDR 0x100 #define SMP_BOOT_REG 0x40 @@ -91,10 +92,12 @@ static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info) address_space_stl_notdirty(&address_space_memory, SMP_BOOT_REG + 0x30, 0, MEMTXATTRS_UNSPECIFIED, NULL); + /* fallthrough */ case 3: address_space_stl_notdirty(&address_space_memory, SMP_BOOT_REG + 0x20, 0, MEMTXATTRS_UNSPECIFIED, NULL); + /* fallthrough */ case 2: address_space_stl_notdirty(&address_space_memory, SMP_BOOT_REG + 0x10, 0, @@ -155,17 +158,16 @@ static const MemoryRegionOps hb_mem_ops = { }; #define TYPE_HIGHBANK_REGISTERS "highbank-regs" -#define HIGHBANK_REGISTERS(obj) \ - OBJECT_CHECK(HighbankRegsState, (obj), TYPE_HIGHBANK_REGISTERS) +OBJECT_DECLARE_SIMPLE_TYPE(HighbankRegsState, HIGHBANK_REGISTERS) -typedef struct { +struct HighbankRegsState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ MemoryRegion iomem; uint32_t regs[NUM_REGS]; -} HighbankRegsState; +}; static VMStateDescription vmstate_highbank_regs = { .name = "highbank-regs", @@ -267,20 +269,20 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id) cpuobj = object_new(machine->cpu_type); cpu = ARM_CPU(cpuobj); - object_property_set_int(cpuobj, QEMU_PSCI_CONDUIT_SMC, - "psci-conduit", &error_abort); + object_property_set_int(cpuobj, "psci-conduit", QEMU_PSCI_CONDUIT_SMC, + &error_abort); if (n) { /* Secondary CPUs start in PSCI powered-down state */ - object_property_set_bool(cpuobj, true, - "start-powered-off", &error_abort); + object_property_set_bool(cpuobj, "start-powered-off", true, + &error_abort); } - if (object_property_find(cpuobj, "reset-cbar", NULL)) { - object_property_set_int(cpuobj, MPCORE_PERIPHBASE, - "reset-cbar", &error_abort); + if (object_property_find(cpuobj, "reset-cbar")) { + object_property_set_int(cpuobj, "reset-cbar", MPCORE_PERIPHBASE, + &error_abort); } - object_property_set_bool(cpuobj, true, "realized", &error_fatal); + qdev_realize(DEVICE(cpuobj), NULL, &error_fatal); cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ); cpu_fiq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ); cpu_virq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_VIRQ); @@ -311,21 +313,21 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id) switch (machine_id) { case CALXEDA_HIGHBANK: - dev = qdev_create(NULL, "l2x0"); - qdev_init_nofail(dev); + dev = qdev_new("l2x0"); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, 0xfff12000); - dev = qdev_create(NULL, TYPE_A9MPCORE_PRIV); + dev = qdev_new(TYPE_A9MPCORE_PRIV); break; case CALXEDA_MIDWAY: - dev = qdev_create(NULL, TYPE_A15MPCORE_PRIV); + dev = qdev_new(TYPE_A15MPCORE_PRIV); break; } qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC); - qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, MPCORE_PERIPHBASE); for (n = 0; n < smp_cpus; n++) { sysbus_connect_irq(busdev, n, cpu_irq[n]); @@ -338,18 +340,18 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id) pic[n] = qdev_get_gpio_in(dev, n); } - dev = qdev_create(NULL, "sp804"); + dev = qdev_new("sp804"); qdev_prop_set_uint32(dev, "freq0", 150000000); qdev_prop_set_uint32(dev, "freq1", 150000000); - qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, 0xfff34000); sysbus_connect_irq(busdev, 0, pic[18]); pl011_create(0xfff36000, pic[20], serial_hd(0)); - dev = qdev_create(NULL, TYPE_HIGHBANK_REGISTERS); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_HIGHBANK_REGISTERS); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, 0xfff3c000); sysbus_create_simple("pl061", 0xfff30000, pic[14]); @@ -363,18 +365,18 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id) if (nd_table[0].used) { qemu_check_nic_model(&nd_table[0], "xgmac"); - dev = qdev_create(NULL, "xgmac"); + dev = qdev_new("xgmac"); qdev_set_nic_properties(dev, &nd_table[0]); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff50000); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[77]); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[78]); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[79]); qemu_check_nic_model(&nd_table[1], "xgmac"); - dev = qdev_create(NULL, "xgmac"); + dev = qdev_new("xgmac"); qdev_set_nic_properties(dev, &nd_table[1]); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff51000); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[80]); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[81]); diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c index b3ca82bafa742f0a3b31d44f0bda429b173eb229..1c201d0d8ed91f827d4355c38661d24bebc051a0 100644 --- a/hw/arm/imx25_pdk.c +++ b/hw/arm/imx25_pdk.c @@ -73,10 +73,9 @@ static void imx25_pdk_init(MachineState *machine) unsigned int alias_offset; int i; - object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), - TYPE_FSL_IMX25, &error_abort, NULL); + object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_FSL_IMX25); - object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal); + qdev_realize(DEVICE(&s->soc), NULL, &error_fatal); /* We need to initialize our memory */ if (machine->ram_size > (FSL_IMX25_SDRAM0_SIZE + FSL_IMX25_SDRAM1_SIZE)) { @@ -130,10 +129,9 @@ static void imx25_pdk_init(MachineState *machine) di = drive_get_next(IF_SD); blk = di ? blk_by_legacy_dinfo(di) : NULL; bus = qdev_get_child_bus(DEVICE(&s->soc.esdhc[i]), "sd-bus"); - carddev = qdev_create(bus, TYPE_SD_CARD); - qdev_prop_set_drive(carddev, "drive", blk, &error_fatal); - object_property_set_bool(OBJECT(carddev), true, - "realized", &error_fatal); + carddev = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal); + qdev_realize_and_unref(carddev, bus, &error_fatal); } /* diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c index 5fb54e5aa75b8fc9ae5a35758f1aeefa88739f44..16e8985953987cd918550141bf4fd4382ff23529 100644 --- a/hw/arm/integratorcp.c +++ b/hw/arm/integratorcp.c @@ -25,12 +25,13 @@ #include "hw/char/pl011.h" #include "hw/hw.h" #include "hw/irq.h" +#include "hw/sd/sd.h" +#include "qom/object.h" #define TYPE_INTEGRATOR_CM "integrator_core" -#define INTEGRATOR_CM(obj) \ - OBJECT_CHECK(IntegratorCMState, (obj), TYPE_INTEGRATOR_CM) +OBJECT_DECLARE_SIMPLE_TYPE(IntegratorCMState, INTEGRATOR_CM) -typedef struct IntegratorCMState { +struct IntegratorCMState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -50,7 +51,7 @@ typedef struct IntegratorCMState { uint32_t int_level; uint32_t irq_enabled; uint32_t fiq_enabled; -} IntegratorCMState; +}; static uint8_t integrator_spd[128] = { 128, 8, 4, 11, 9, 1, 64, 0, 2, 0xa0, 0xa0, 0, 0, 8, 0, 1, @@ -325,10 +326,9 @@ static void integratorcm_realize(DeviceState *d, Error **errp) /* Primary interrupt controller. */ #define TYPE_INTEGRATOR_PIC "integrator_pic" -#define INTEGRATOR_PIC(obj) \ - OBJECT_CHECK(icp_pic_state, (obj), TYPE_INTEGRATOR_PIC) +OBJECT_DECLARE_SIMPLE_TYPE(icp_pic_state, INTEGRATOR_PIC) -typedef struct icp_pic_state { +struct icp_pic_state { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -339,7 +339,7 @@ typedef struct icp_pic_state { uint32_t fiq_enabled; qemu_irq parent_irq; qemu_irq parent_fiq; -} icp_pic_state; +}; static const VMStateDescription vmstate_icp_pic = { .name = "icp_pic", @@ -464,10 +464,9 @@ static void icp_pic_init(Object *obj) /* CP control registers. */ #define TYPE_ICP_CONTROL_REGS "icp-ctrl-regs" -#define ICP_CONTROL_REGS(obj) \ - OBJECT_CHECK(ICPCtrlRegsState, (obj), TYPE_ICP_CONTROL_REGS) +OBJECT_DECLARE_SIMPLE_TYPE(ICPCtrlRegsState, ICP_CONTROL_REGS) -typedef struct ICPCtrlRegsState { +struct ICPCtrlRegsState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -476,7 +475,7 @@ typedef struct ICPCtrlRegsState { qemu_irq mmc_irq; uint32_t intreg_state; -} ICPCtrlRegsState; +}; #define ICP_GPIO_MMC_WPROT "mmc-wprot" #define ICP_GPIO_MMC_CARDIN "mmc-cardin" @@ -595,6 +594,7 @@ static void integratorcp_init(MachineState *machine) MemoryRegion *ram_alias = g_new(MemoryRegion, 1); qemu_irq pic[32]; DeviceState *dev, *sic, *icp; + DriveInfo *dinfo; int i; cpuobj = object_new(machine->cpu_type); @@ -603,11 +603,11 @@ static void integratorcp_init(MachineState *machine) * currently support EL3 so the CPU EL3 property is disabled before * realization. */ - if (object_property_find(cpuobj, "has_el3", NULL)) { - object_property_set_bool(cpuobj, false, "has_el3", &error_fatal); + if (object_property_find(cpuobj, "has_el3")) { + object_property_set_bool(cpuobj, "has_el3", false, &error_fatal); } - object_property_set_bool(cpuobj, true, "realized", &error_fatal); + qdev_realize(DEVICE(cpuobj), NULL, &error_fatal); cpu = ARM_CPU(cpuobj); @@ -620,9 +620,9 @@ static void integratorcp_init(MachineState *machine) 0, ram_size); memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias); - dev = qdev_create(NULL, TYPE_INTEGRATOR_CM); + dev = qdev_new(TYPE_INTEGRATOR_CM); qdev_prop_set_uint32(dev, "memsz", ram_size >> 20); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000); dev = sysbus_create_varargs(TYPE_INTEGRATOR_PIC, 0x14000000, @@ -645,10 +645,21 @@ static void integratorcp_init(MachineState *machine) sysbus_create_simple(TYPE_INTEGRATOR_DEBUG, 0x1a000000, 0); dev = sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL); - qdev_connect_gpio_out(dev, 0, + qdev_connect_gpio_out_named(dev, "card-read-only", 0, qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_WPROT, 0)); - qdev_connect_gpio_out(dev, 1, + qdev_connect_gpio_out_named(dev, "card-inserted", 0, qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_CARDIN, 0)); + dinfo = drive_get_next(IF_SD); + if (dinfo) { + DeviceState *card; + + card = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo), + &error_fatal); + qdev_realize_and_unref(card, qdev_get_child_bus(dev, "sd-bus"), + &error_fatal); + } + sysbus_create_varargs("pl041", 0x1d000000, pic[25], NULL); if (nd_table[0].used) diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c index 34f6bcb4911d2221b696e11e6abb243f83513835..e3f7d4ead2324ebd211317a3e39d18b0d817abc3 100644 --- a/hw/arm/kzm.c +++ b/hw/arm/kzm.c @@ -71,10 +71,9 @@ static void kzm_init(MachineState *machine) unsigned int alias_offset; unsigned int i; - object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), - TYPE_FSL_IMX31, &error_abort, NULL); + object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_FSL_IMX31); - object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal); + qdev_realize(DEVICE(&s->soc), NULL, &error_fatal); /* Check the amount of memory is compatible with the SOC */ if (machine->ram_size > (FSL_IMX31_SDRAM0_SIZE + FSL_IMX31_SDRAM1_SIZE)) { diff --git a/hw/arm/mcimx6ul-evk.c b/hw/arm/mcimx6ul-evk.c index 5b5f23a6d418399b57a5330ff60ddd149d41e1d9..ed69a7b037ad6e056ed3f06da9d0ed07e29550ed 100644 --- a/hw/arm/mcimx6ul-evk.c +++ b/hw/arm/mcimx6ul-evk.c @@ -40,7 +40,9 @@ static void mcimx6ul_evk_init(MachineState *machine) s = FSL_IMX6UL(object_new(TYPE_FSL_IMX6UL)); object_property_add_child(OBJECT(machine), "soc", OBJECT(s)); - object_property_set_bool(OBJECT(s), true, "realized", &error_fatal); + object_property_set_uint(OBJECT(s), "fec1-phy-num", 2, &error_fatal); + object_property_set_uint(OBJECT(s), "fec2-phy-num", 1, &error_fatal); + qdev_realize(DEVICE(s), NULL, &error_fatal); memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_MMDC_ADDR, machine->ram); @@ -54,10 +56,9 @@ static void mcimx6ul_evk_init(MachineState *machine) di = drive_get_next(IF_SD); blk = di ? blk_by_legacy_dinfo(di) : NULL; bus = qdev_get_child_bus(DEVICE(&s->usdhc[i]), "sd-bus"); - carddev = qdev_create(bus, TYPE_SD_CARD); - qdev_prop_set_drive(carddev, "drive", blk, &error_fatal); - object_property_set_bool(OBJECT(carddev), true, - "realized", &error_fatal); + carddev = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal); + qdev_realize_and_unref(carddev, bus, &error_fatal); } if (!qtest_enabled()) { diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c index 3851cd9e3ed537ca12cb81d8a63faf441216e532..e57d52b3441c2ce3f7f1b5747f9784c62c155580 100644 --- a/hw/arm/mcimx7d-sabre.c +++ b/hw/arm/mcimx7d-sabre.c @@ -42,7 +42,7 @@ static void mcimx7d_sabre_init(MachineState *machine) s = FSL_IMX7(object_new(TYPE_FSL_IMX7)); object_property_add_child(OBJECT(machine), "soc", OBJECT(s)); - object_property_set_bool(OBJECT(s), true, "realized", &error_fatal); + qdev_realize(DEVICE(s), NULL, &error_fatal); memory_region_add_subregion(get_system_memory(), FSL_IMX7_MMDC_ADDR, machine->ram); @@ -56,10 +56,9 @@ static void mcimx7d_sabre_init(MachineState *machine) di = drive_get_next(IF_SD); blk = di ? blk_by_legacy_dinfo(di) : NULL; bus = qdev_get_child_bus(DEVICE(&s->usdhc[i]), "sd-bus"); - carddev = qdev_create(bus, TYPE_SD_CARD); - qdev_prop_set_drive(carddev, "drive", blk, &error_fatal); - object_property_set_bool(OBJECT(carddev), true, - "realized", &error_fatal); + carddev = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal); + qdev_realize_and_unref(carddev, bus, &error_fatal); } if (!qtest_enabled()) { diff --git a/hw/arm/meson.build b/hw/arm/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..be39117b9b6f32626ccb07dd42186e5cca383e4b --- /dev/null +++ b/hw/arm/meson.build @@ -0,0 +1,60 @@ +arm_ss = ss.source_set() +arm_ss.add(files('boot.c'), fdt) +arm_ss.add(when: 'CONFIG_PLATFORM_BUS', if_true: files('sysbus-fdt.c')) +arm_ss.add(when: 'CONFIG_ARM_VIRT', if_true: files('virt.c')) +arm_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c')) +arm_ss.add(when: 'CONFIG_DIGIC', if_true: files('digic_boards.c')) +arm_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4_boards.c')) +arm_ss.add(when: 'CONFIG_EMCRAFT_SF2', if_true: files('msf2-som.c')) +arm_ss.add(when: 'CONFIG_HIGHBANK', if_true: files('highbank.c')) +arm_ss.add(when: 'CONFIG_INTEGRATOR', if_true: files('integratorcp.c')) +arm_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mainstone.c')) +arm_ss.add(when: 'CONFIG_MICROBIT', if_true: files('microbit.c')) +arm_ss.add(when: 'CONFIG_MUSICPAL', if_true: files('musicpal.c')) +arm_ss.add(when: 'CONFIG_NETDUINO2', if_true: files('netduino2.c')) +arm_ss.add(when: 'CONFIG_NETDUINOPLUS2', if_true: files('netduinoplus2.c')) +arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c', 'npcm7xx_boards.c')) +arm_ss.add(when: 'CONFIG_NSERIES', if_true: files('nseries.c')) +arm_ss.add(when: 'CONFIG_SX1', if_true: files('omap_sx1.c')) +arm_ss.add(when: 'CONFIG_CHEETAH', if_true: files('palm.c')) +arm_ss.add(when: 'CONFIG_GUMSTIX', if_true: files('gumstix.c')) +arm_ss.add(when: 'CONFIG_SPITZ', if_true: files('spitz.c')) +arm_ss.add(when: 'CONFIG_TOSA', if_true: files('tosa.c')) +arm_ss.add(when: 'CONFIG_Z2', if_true: files('z2.c')) +arm_ss.add(when: 'CONFIG_REALVIEW', if_true: files('realview.c')) +arm_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa-ref.c')) +arm_ss.add(when: 'CONFIG_STELLARIS', if_true: files('stellaris.c')) +arm_ss.add(when: 'CONFIG_COLLIE', if_true: files('collie.c')) +arm_ss.add(when: 'CONFIG_VERSATILE', if_true: files('versatilepb.c')) +arm_ss.add(when: 'CONFIG_VEXPRESS', if_true: files('vexpress.c')) +arm_ss.add(when: 'CONFIG_ZYNQ', if_true: files('xilinx_zynq.c')) +arm_ss.add(when: 'CONFIG_SABRELITE', if_true: files('sabrelite.c')) + +arm_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m.c')) +arm_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210.c')) +arm_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx.c', 'pxa2xx_gpio.c', 'pxa2xx_pic.c')) +arm_ss.add(when: 'CONFIG_DIGIC', if_true: files('digic.c')) +arm_ss.add(when: 'CONFIG_OMAP', if_true: files('omap1.c', 'omap2.c')) +arm_ss.add(when: 'CONFIG_STRONGARM', if_true: files('strongarm.c')) +arm_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: files('allwinner-a10.c', 'cubieboard.c')) +arm_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3.c', 'orangepi.c')) +arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_peripherals.c', 'bcm2836.c', 'raspi.c')) +arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c')) +arm_ss.add(when: 'CONFIG_STM32F405_SOC', if_true: files('stm32f405_soc.c')) +arm_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp.c', 'xlnx-zcu102.c')) +arm_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal.c', 'xlnx-versal-virt.c')) +arm_ss.add(when: 'CONFIG_FSL_IMX25', if_true: files('fsl-imx25.c', 'imx25_pdk.c')) +arm_ss.add(when: 'CONFIG_FSL_IMX31', if_true: files('fsl-imx31.c', 'kzm.c')) +arm_ss.add(when: 'CONFIG_FSL_IMX6', if_true: files('fsl-imx6.c')) +arm_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_soc.c', 'aspeed.c', 'aspeed_ast2600.c')) +arm_ss.add(when: 'CONFIG_MPS2', if_true: files('mps2.c')) +arm_ss.add(when: 'CONFIG_MPS2', if_true: files('mps2-tz.c')) +arm_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-soc.c')) +arm_ss.add(when: 'CONFIG_MUSCA', if_true: files('musca.c')) +arm_ss.add(when: 'CONFIG_ARMSSE', if_true: files('armsse.c')) +arm_ss.add(when: 'CONFIG_FSL_IMX7', if_true: files('fsl-imx7.c', 'mcimx7d-sabre.c')) +arm_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmu-common.c', 'smmuv3.c')) +arm_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true: files('fsl-imx6ul.c', 'mcimx6ul-evk.c')) +arm_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_soc.c')) + +hw_arch += {'arm': arm_ss} diff --git a/hw/arm/microbit.c b/hw/arm/microbit.c index ef213695bdbd4bbc1eab70b9afeeac22d9206a5d..0947491cb97cba444decddab9720f28f4f26706e 100644 --- a/hw/arm/microbit.c +++ b/hw/arm/microbit.c @@ -18,48 +18,46 @@ #include "hw/arm/nrf51_soc.h" #include "hw/i2c/microbit_i2c.h" #include "hw/qdev-properties.h" +#include "qom/object.h" -typedef struct { +struct MicrobitMachineState { MachineState parent; NRF51State nrf51; MicrobitI2CState i2c; -} MicrobitMachineState; +}; #define TYPE_MICROBIT_MACHINE MACHINE_TYPE_NAME("microbit") -#define MICROBIT_MACHINE(obj) \ - OBJECT_CHECK(MicrobitMachineState, obj, TYPE_MICROBIT_MACHINE) +OBJECT_DECLARE_SIMPLE_TYPE(MicrobitMachineState, MICROBIT_MACHINE) static void microbit_init(MachineState *machine) { MicrobitMachineState *s = MICROBIT_MACHINE(machine); MemoryRegion *system_memory = get_system_memory(); MemoryRegion *mr; - Object *soc = OBJECT(&s->nrf51); - Object *i2c = OBJECT(&s->i2c); - sysbus_init_child_obj(OBJECT(machine), "nrf51", soc, sizeof(s->nrf51), - TYPE_NRF51_SOC); + object_initialize_child(OBJECT(machine), "nrf51", &s->nrf51, + TYPE_NRF51_SOC); qdev_prop_set_chr(DEVICE(&s->nrf51), "serial0", serial_hd(0)); - object_property_set_link(soc, OBJECT(system_memory), "memory", - &error_fatal); - object_property_set_bool(soc, true, "realized", &error_fatal); + object_property_set_link(OBJECT(&s->nrf51), "memory", + OBJECT(system_memory), &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(&s->nrf51), &error_fatal); /* * Overlap the TWI stub device into the SoC. This is a microbit-specific * hack until we implement the nRF51 TWI controller properly and the * magnetometer/accelerometer devices. */ - sysbus_init_child_obj(OBJECT(machine), "microbit.twi", i2c, - sizeof(s->i2c), TYPE_MICROBIT_I2C); - object_property_set_bool(i2c, true, "realized", &error_fatal); - mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(i2c), 0); + object_initialize_child(OBJECT(machine), "microbit.twi", &s->i2c, + TYPE_MICROBIT_I2C); + sysbus_realize(SYS_BUS_DEVICE(&s->i2c), &error_fatal); + mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->i2c), 0); memory_region_add_subregion_overlap(&s->nrf51.container, NRF51_TWI_BASE, mr, -1); armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, - NRF51_SOC(soc)->flash_size); + s->nrf51.flash_size); } static void microbit_machine_class_init(ObjectClass *oc, void *data) diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c index 2c43041564c22f1cfeab36258ca7760c45e92736..3707876d6d487680754d5a360e62f8d403f0d1b4 100644 --- a/hw/arm/mps2-tz.c +++ b/hw/arm/mps2-tz.c @@ -58,9 +58,11 @@ #include "hw/arm/armsse.h" #include "hw/dma/pl080.h" #include "hw/ssi/pl022.h" +#include "hw/i2c/arm_sbcon_i2c.h" #include "hw/net/lan9118.h" #include "net/net.h" #include "hw/core/split-irq.h" +#include "qom/object.h" #define MPS2TZ_NUMIRQ 92 @@ -69,14 +71,14 @@ typedef enum MPS2TZFPGAType { FPGA_AN521, } MPS2TZFPGAType; -typedef struct { +struct MPS2TZMachineClass { MachineClass parent; MPS2TZFPGAType fpga_type; uint32_t scc_id; const char *armsse_type; -} MPS2TZMachineClass; +}; -typedef struct { +struct MPS2TZMachineState { MachineState parent; ARMSSE iotkit; @@ -87,7 +89,7 @@ typedef struct { TZPPC ppc[5]; TZMPC ssram_mpc[3]; PL022State spi[5]; - UnimplementedDeviceState i2c[4]; + ArmSbconI2CState i2c[4]; UnimplementedDeviceState i2s_audio; UnimplementedDeviceState gpio[4]; UnimplementedDeviceState gfx; @@ -98,18 +100,13 @@ typedef struct { qemu_or_irq uart_irq_orgate; DeviceState *lan9118; SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ]; -} MPS2TZMachineState; +}; #define TYPE_MPS2TZ_MACHINE "mps2tz" #define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505") #define TYPE_MPS2TZ_AN521_MACHINE MACHINE_TYPE_NAME("mps2-an521") -#define MPS2TZ_MACHINE(obj) \ - OBJECT_CHECK(MPS2TZMachineState, obj, TYPE_MPS2TZ_MACHINE) -#define MPS2TZ_MACHINE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(MPS2TZMachineClass, obj, TYPE_MPS2TZ_MACHINE) -#define MPS2TZ_MACHINE_CLASS(klass) \ - OBJECT_CLASS_CHECK(MPS2TZMachineClass, klass, TYPE_MPS2TZ_MACHINE) +OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE) /* Main SYSCLK frequency in Hz */ #define SYSCLK_FRQ 20000000 @@ -174,12 +171,10 @@ static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms, */ UnimplementedDeviceState *uds = opaque; - sysbus_init_child_obj(OBJECT(mms), name, uds, - sizeof(UnimplementedDeviceState), - TYPE_UNIMPLEMENTED_DEVICE); + object_initialize_child(OBJECT(mms), name, uds, TYPE_UNIMPLEMENTED_DEVICE); qdev_prop_set_string(DEVICE(uds), "name", name); qdev_prop_set_uint64(DEVICE(uds), "size", size); - object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(uds), &error_fatal); return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0); } @@ -194,11 +189,10 @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque, SysBusDevice *s; DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate); - sysbus_init_child_obj(OBJECT(mms), name, uart, sizeof(mms->uart[0]), - TYPE_CMSDK_APB_UART); + object_initialize_child(OBJECT(mms), name, uart, TYPE_CMSDK_APB_UART); qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i)); qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ); - object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal); s = SYS_BUS_DEVICE(uart); sysbus_connect_irq(s, 0, get_sse_irq_in(mms, txirqno)); sysbus_connect_irq(s, 1, get_sse_irq_in(mms, rxirqno)); @@ -215,13 +209,12 @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque, DeviceState *sccdev; MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms); - sysbus_init_child_obj(OBJECT(mms), "scc", scc, - sizeof(mms->scc), TYPE_MPS2_SCC); + object_initialize_child(OBJECT(mms), "scc", scc, TYPE_MPS2_SCC); sccdev = DEVICE(scc); qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2); qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008); qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id); - object_property_set_bool(OBJECT(scc), true, "realized", &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(scc), &error_fatal); return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0); } @@ -230,9 +223,8 @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque, { MPS2FPGAIO *fpgaio = opaque; - sysbus_init_child_obj(OBJECT(mms), "fpgaio", fpgaio, - sizeof(mms->fpgaio), TYPE_MPS2_FPGAIO); - object_property_set_bool(OBJECT(fpgaio), true, "realized", &error_fatal); + object_initialize_child(OBJECT(mms), "fpgaio", fpgaio, TYPE_MPS2_FPGAIO); + sysbus_realize(SYS_BUS_DEVICE(fpgaio), &error_fatal); return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0); } @@ -246,11 +238,11 @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque, * except that it doesn't support the checksum-offload feature. */ qemu_check_nic_model(nd, "lan9118"); - mms->lan9118 = qdev_create(NULL, TYPE_LAN9118); + mms->lan9118 = qdev_new(TYPE_LAN9118); qdev_set_nic_properties(mms->lan9118, nd); - qdev_init_nofail(mms->lan9118); s = SYS_BUS_DEVICE(mms->lan9118); + sysbus_realize_and_unref(s, &error_fatal); sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 16)); return sysbus_mmio_get_region(s, 0); } @@ -268,11 +260,10 @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque, memory_region_init_ram(ssram, NULL, name, ramsize[i], &error_fatal); - sysbus_init_child_obj(OBJECT(mms), mpcname, mpc, sizeof(mms->ssram_mpc[0]), - TYPE_TZ_MPC); - object_property_set_link(OBJECT(mpc), OBJECT(ssram), - "downstream", &error_fatal); - object_property_set_bool(OBJECT(mpc), true, "realized", &error_fatal); + object_initialize_child(OBJECT(mms), mpcname, mpc, TYPE_TZ_MPC); + object_property_set_link(OBJECT(mpc), "downstream", OBJECT(ssram), + &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(mpc), &error_fatal); /* Map the upstream end of the MPC into system memory */ upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1); memory_region_add_subregion(get_system_memory(), rambase[i], upstream); @@ -311,13 +302,12 @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque, * the MSC connects to the IoTKit AHB Slave Expansion port, so the * DMA devices can see all devices and memory that the CPU does. */ - sysbus_init_child_obj(OBJECT(mms), mscname, msc, sizeof(*msc), TYPE_TZ_MSC); + object_initialize_child(OBJECT(mms), mscname, msc, TYPE_TZ_MSC); msc_downstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(&mms->iotkit), 0); - object_property_set_link(OBJECT(msc), OBJECT(msc_downstream), - "downstream", &error_fatal); - object_property_set_link(OBJECT(msc), OBJECT(mms), - "idau", &error_fatal); - object_property_set_bool(OBJECT(msc), true, "realized", &error_fatal); + object_property_set_link(OBJECT(msc), "downstream", + OBJECT(msc_downstream), &error_fatal); + object_property_set_link(OBJECT(msc), "idau", OBJECT(mms), &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(msc), &error_fatal); qdev_connect_gpio_out_named(DEVICE(msc), "irq", 0, qdev_get_gpio_in_named(iotkitdev, @@ -334,10 +324,10 @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque, "cfg_sec_resp", 0)); msc_upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(msc), 0); - sysbus_init_child_obj(OBJECT(mms), name, dma, sizeof(*dma), TYPE_PL081); - object_property_set_link(OBJECT(dma), OBJECT(msc_upstream), - "downstream", &error_fatal); - object_property_set_bool(OBJECT(dma), true, "realized", &error_fatal); + object_initialize_child(OBJECT(mms), name, dma, TYPE_PL081); + object_property_set_link(OBJECT(dma), "downstream", OBJECT(msc_upstream), + &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(dma), &error_fatal); s = SYS_BUS_DEVICE(dma); /* Wire up DMACINTR, DMACINTERR, DMACINTTC */ @@ -364,14 +354,25 @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque, int i = spi - &mms->spi[0]; SysBusDevice *s; - sysbus_init_child_obj(OBJECT(mms), name, spi, sizeof(mms->spi[0]), - TYPE_PL022); - object_property_set_bool(OBJECT(spi), true, "realized", &error_fatal); + object_initialize_child(OBJECT(mms), name, spi, TYPE_PL022); + sysbus_realize(SYS_BUS_DEVICE(spi), &error_fatal); s = SYS_BUS_DEVICE(spi); sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 51 + i)); return sysbus_mmio_get_region(s, 0); } +static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque, + const char *name, hwaddr size) +{ + ArmSbconI2CState *i2c = opaque; + SysBusDevice *s; + + object_initialize_child(OBJECT(mms), name, i2c, TYPE_ARM_SBCON_I2C); + s = SYS_BUS_DEVICE(i2c); + sysbus_realize(s, &error_fatal); + return sysbus_mmio_get_region(s, 0); +} + static void mps2tz_common_init(MachineState *machine) { MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine); @@ -395,15 +396,14 @@ static void mps2tz_common_init(MachineState *machine) exit(EXIT_FAILURE); } - sysbus_init_child_obj(OBJECT(machine), TYPE_IOTKIT, &mms->iotkit, - sizeof(mms->iotkit), mmc->armsse_type); + object_initialize_child(OBJECT(machine), TYPE_IOTKIT, &mms->iotkit, + mmc->armsse_type); iotkitdev = DEVICE(&mms->iotkit); - object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory), - "memory", &error_abort); + object_property_set_link(OBJECT(&mms->iotkit), "memory", + OBJECT(system_memory), &error_abort); qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ); qdev_prop_set_uint32(iotkitdev, "MAINCLK", SYSCLK_FRQ); - object_property_set_bool(OBJECT(&mms->iotkit), true, "realized", - &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal); /* * The AN521 needs us to create splitters to feed the IRQ inputs @@ -414,15 +414,15 @@ static void mps2tz_common_init(MachineState *machine) char *name = g_strdup_printf("mps2-irq-splitter%d", i); SplitIRQ *splitter = &mms->cpu_irq_splitter[i]; - object_initialize_child(OBJECT(machine), name, - splitter, sizeof(*splitter), - TYPE_SPLIT_IRQ, &error_fatal, NULL); + object_initialize_child_with_props(OBJECT(machine), name, + splitter, sizeof(*splitter), + TYPE_SPLIT_IRQ, &error_fatal, + NULL); g_free(name); - object_property_set_int(OBJECT(splitter), 2, "num-lines", + object_property_set_int(OBJECT(splitter), "num-lines", 2, &error_fatal); - object_property_set_bool(OBJECT(splitter), true, "realized", - &error_fatal); + qdev_realize(DEVICE(splitter), NULL, &error_fatal); qdev_connect_gpio_out(DEVICE(splitter), 0, qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "EXP_IRQ", i)); @@ -436,14 +436,11 @@ static void mps2tz_common_init(MachineState *machine) * lines, one for each of the PPCs we create here, plus one per MSC. */ object_initialize_child(OBJECT(machine), "sec-resp-splitter", - &mms->sec_resp_splitter, - sizeof(mms->sec_resp_splitter), - TYPE_SPLIT_IRQ, &error_abort, NULL); - object_property_set_int(OBJECT(&mms->sec_resp_splitter), + &mms->sec_resp_splitter, TYPE_SPLIT_IRQ); + object_property_set_int(OBJECT(&mms->sec_resp_splitter), "num-lines", ARRAY_SIZE(mms->ppc) + ARRAY_SIZE(mms->msc), - "num-lines", &error_fatal); - object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true, - "realized", &error_fatal); + &error_fatal); + qdev_realize(DEVICE(&mms->sec_resp_splitter), NULL, &error_fatal); dev_splitter = DEVICE(&mms->sec_resp_splitter); qdev_connect_gpio_out_named(iotkitdev, "sec_resp_cfg", 0, qdev_get_gpio_in(dev_splitter, 0)); @@ -472,12 +469,10 @@ static void mps2tz_common_init(MachineState *machine) * Create the OR gate for this. */ object_initialize_child(OBJECT(mms), "uart-irq-orgate", - &mms->uart_irq_orgate, sizeof(mms->uart_irq_orgate), - TYPE_OR_IRQ, &error_abort, NULL); - object_property_set_int(OBJECT(&mms->uart_irq_orgate), 10, "num-lines", + &mms->uart_irq_orgate, TYPE_OR_IRQ); + object_property_set_int(OBJECT(&mms->uart_irq_orgate), "num-lines", 10, &error_fatal); - object_property_set_bool(OBJECT(&mms->uart_irq_orgate), true, - "realized", &error_fatal); + qdev_realize(DEVICE(&mms->uart_irq_orgate), NULL, &error_fatal); qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0, get_sse_irq_in(mms, 15)); @@ -512,10 +507,10 @@ static void mps2tz_common_init(MachineState *machine) { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000 }, { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000 }, { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000 }, - { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40207000, 0x1000 }, - { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40208000, 0x1000 }, - { "i2c2", make_unimp_dev, &mms->i2c[2], 0x4020c000, 0x1000 }, - { "i2c3", make_unimp_dev, &mms->i2c[3], 0x4020d000, 0x1000 }, + { "i2c0", make_i2c, &mms->i2c[0], 0x40207000, 0x1000 }, + { "i2c1", make_i2c, &mms->i2c[1], 0x40208000, 0x1000 }, + { "i2c2", make_i2c, &mms->i2c[2], 0x4020c000, 0x1000 }, + { "i2c3", make_i2c, &mms->i2c[3], 0x4020d000, 0x1000 }, }, }, { .name = "apb_ppcexp2", @@ -553,8 +548,8 @@ static void mps2tz_common_init(MachineState *machine) int port; char *gpioname; - sysbus_init_child_obj(OBJECT(machine), ppcinfo->name, ppc, - sizeof(TZPPC), TYPE_TZ_PPC); + object_initialize_child(OBJECT(machine), ppcinfo->name, ppc, + TYPE_TZ_PPC); ppcdev = DEVICE(ppc); for (port = 0; port < TZ_NUM_PORTS; port++) { @@ -568,12 +563,12 @@ static void mps2tz_common_init(MachineState *machine) mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size); portname = g_strdup_printf("port[%d]", port); - object_property_set_link(OBJECT(ppc), OBJECT(mr), - portname, &error_fatal); + object_property_set_link(OBJECT(ppc), portname, OBJECT(mr), + &error_fatal); g_free(portname); } - object_property_set_bool(OBJECT(ppc), true, "realized", &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(ppc), &error_fatal); for (port = 0; port < TZ_NUM_PORTS; port++) { const PPCPortInfo *pinfo = &ppcinfo->ports[port]; diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c index f246213206e28b5d55a8601075dbcb93224fd15b..9a8b23c64ce70f7eac5ca1b4ae8ca778aa09a9ba 100644 --- a/hw/arm/mps2.c +++ b/hw/arm/mps2.c @@ -15,6 +15,8 @@ * as seen by the guest depend significantly on the FPGA image. * We model the following FPGA images: * "mps2-an385" -- Cortex-M3 as documented in ARM Application Note AN385 + * "mps2-an386" -- Cortex-M4 as documented in ARM Application Note AN386 + * "mps2-an500" -- Cortex-M7 as documented in ARM Application Note AN500 * "mps2-an511" -- Cortex-M3 'DesignStart' as documented in AN511 * * Links to the TRM for the board itself and to the various Application @@ -38,21 +40,31 @@ #include "hw/timer/cmsdk-apb-timer.h" #include "hw/timer/cmsdk-apb-dualtimer.h" #include "hw/misc/mps2-scc.h" +#include "hw/misc/mps2-fpgaio.h" +#include "hw/ssi/pl022.h" +#include "hw/i2c/arm_sbcon_i2c.h" #include "hw/net/lan9118.h" #include "net/net.h" +#include "hw/watchdog/cmsdk-apb-watchdog.h" +#include "qom/object.h" typedef enum MPS2FPGAType { FPGA_AN385, + FPGA_AN386, + FPGA_AN500, FPGA_AN511, } MPS2FPGAType; -typedef struct { +struct MPS2MachineClass { MachineClass parent; MPS2FPGAType fpga_type; uint32_t scc_id; -} MPS2MachineClass; + bool has_block_ram; + hwaddr ethernet_base; + hwaddr psram_base; +}; -typedef struct { +struct MPS2MachineState { MachineState parent; ARMv7MState armv7m; @@ -65,20 +77,21 @@ typedef struct { MemoryRegion blockram_m2; MemoryRegion blockram_m3; MemoryRegion sram; + /* FPGA APB subsystem */ MPS2SCC scc; + MPS2FPGAIO fpgaio; + /* CMSDK APB subsystem */ CMSDKAPBDualTimer dualtimer; -} MPS2MachineState; + CMSDKAPBWatchdog watchdog; +}; #define TYPE_MPS2_MACHINE "mps2" #define TYPE_MPS2_AN385_MACHINE MACHINE_TYPE_NAME("mps2-an385") +#define TYPE_MPS2_AN386_MACHINE MACHINE_TYPE_NAME("mps2-an386") +#define TYPE_MPS2_AN500_MACHINE MACHINE_TYPE_NAME("mps2-an500") #define TYPE_MPS2_AN511_MACHINE MACHINE_TYPE_NAME("mps2-an511") -#define MPS2_MACHINE(obj) \ - OBJECT_CHECK(MPS2MachineState, obj, TYPE_MPS2_MACHINE) -#define MPS2_MACHINE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(MPS2MachineClass, obj, TYPE_MPS2_MACHINE) -#define MPS2_MACHINE_CLASS(klass) \ - OBJECT_CLASS_CHECK(MPS2MachineClass, klass, TYPE_MPS2_MACHINE) +OBJECT_DECLARE_TYPE(MPS2MachineState, MPS2MachineClass, MPS2_MACHINE) /* Main SYSCLK frequency in Hz */ #define SYSCLK_FRQ 25000000 @@ -111,6 +124,7 @@ static void mps2_common_init(MachineState *machine) MemoryRegion *system_memory = get_system_memory(); MachineClass *mc = MACHINE_GET_CLASS(machine); DeviceState *armv7m, *sccdev; + int i; if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) { error_report("This board can only be used with CPU %s", @@ -131,13 +145,14 @@ static void mps2_common_init(MachineState *machine) * tradeoffs. For QEMU they're all just RAM, though. We arbitrarily * call the 16MB our "system memory", as it's the largest lump. * - * Common to both boards: - * 0x21000000..0x21ffffff : PSRAM (16MB) - * AN385 only: + * AN385/AN386/AN511: + * 0x21000000 .. 0x21ffffff : PSRAM (16MB) + * AN385/AN386/AN500: * 0x00000000 .. 0x003fffff : ZBT SSRAM1 * 0x00400000 .. 0x007fffff : mirror of ZBT SSRAM1 * 0x20000000 .. 0x203fffff : ZBT SSRAM 2&3 * 0x20400000 .. 0x207fffff : mirror of ZBT SSRAM 2&3 + * AN385/AN386 only: * 0x01000000 .. 0x01003fff : block RAM (16K) * 0x01004000 .. 0x01007fff : mirror of above * 0x01008000 .. 0x0100bfff : mirror of above @@ -147,21 +162,17 @@ static void mps2_common_init(MachineState *machine) * 0x00400000 .. 0x007fffff : ZBT SSRAM1 * 0x20000000 .. 0x2001ffff : SRAM * 0x20400000 .. 0x207fffff : ZBT SSRAM 2&3 + * AN500 only: + * 0x60000000 .. 0x60ffffff : PSRAM (16MB) * - * The AN385 has a feature where the lowest 16K can be mapped + * The AN385/AN386 has a feature where the lowest 16K can be mapped * either to the bottom of the ZBT SSRAM1 or to the block RAM. * This is of no use for QEMU so we don't implement it (as if * zbt_boot_ctrl is always zero). */ - memory_region_add_subregion(system_memory, 0x21000000, machine->ram); + memory_region_add_subregion(system_memory, mmc->psram_base, machine->ram); - switch (mmc->fpga_type) { - case FPGA_AN385: - make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000); - make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000); - make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000); - make_ram_alias(&mms->ssram23_m, "mps.ssram23_m", - &mms->ssram23, 0x20400000); + if (mmc->has_block_ram) { make_ram(&mms->blockram, "mps.blockram", 0x01000000, 0x4000); make_ram_alias(&mms->blockram_m1, "mps.blockram_m1", &mms->blockram, 0x01004000); @@ -169,6 +180,17 @@ static void mps2_common_init(MachineState *machine) &mms->blockram, 0x01008000); make_ram_alias(&mms->blockram_m3, "mps.blockram_m3", &mms->blockram, 0x0100c000); + } + + switch (mmc->fpga_type) { + case FPGA_AN385: + case FPGA_AN386: + case FPGA_AN500: + make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000); + make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000); + make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000); + make_ram_alias(&mms->ssram23_m, "mps.ssram23_m", + &mms->ssram23, 0x20400000); break; case FPGA_AN511: make_ram(&mms->blockram, "mps.blockram", 0x0, 0x40000); @@ -180,11 +202,12 @@ static void mps2_common_init(MachineState *machine) g_assert_not_reached(); } - sysbus_init_child_obj(OBJECT(mms), "armv7m", &mms->armv7m, - sizeof(mms->armv7m), TYPE_ARMV7M); + object_initialize_child(OBJECT(mms), "armv7m", &mms->armv7m, TYPE_ARMV7M); armv7m = DEVICE(&mms->armv7m); switch (mmc->fpga_type) { case FPGA_AN385: + case FPGA_AN386: + case FPGA_AN500: qdev_prop_set_uint32(armv7m, "num-irq", 32); break; case FPGA_AN511: @@ -195,10 +218,9 @@ static void mps2_common_init(MachineState *machine) } qdev_prop_set_string(armv7m, "cpu-type", machine->cpu_type); qdev_prop_set_bit(armv7m, "enable-bitband", true); - object_property_set_link(OBJECT(&mms->armv7m), OBJECT(system_memory), - "memory", &error_abort); - object_property_set_bool(OBJECT(&mms->armv7m), true, "realized", - &error_fatal); + object_property_set_link(OBJECT(&mms->armv7m), "memory", + OBJECT(system_memory), &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&mms->armv7m), &error_fatal); create_unimplemented_device("zbtsmram mirror", 0x00400000, 0x00400000); create_unimplemented_device("RESERVED 1", 0x00800000, 0x00800000); @@ -212,26 +234,28 @@ static void mps2_common_init(MachineState *machine) */ create_unimplemented_device("CMSDK APB peripheral region @0x40000000", 0x40000000, 0x00010000); - create_unimplemented_device("CMSDK peripheral region @0x40010000", + create_unimplemented_device("CMSDK AHB peripheral region @0x40010000", 0x40010000, 0x00010000); create_unimplemented_device("Extra peripheral region @0x40020000", 0x40020000, 0x00010000); + create_unimplemented_device("RESERVED 4", 0x40030000, 0x001D0000); create_unimplemented_device("VGA", 0x41000000, 0x0200000); switch (mmc->fpga_type) { case FPGA_AN385: + case FPGA_AN386: + case FPGA_AN500: { /* The overflow IRQs for UARTs 0, 1 and 2 are ORed together. * Overflow for UARTs 4 and 5 doesn't trigger any interrupt. */ Object *orgate; DeviceState *orgate_dev; - int i; orgate = object_new(TYPE_OR_IRQ); - object_property_set_int(orgate, 6, "num-lines", &error_fatal); - object_property_set_bool(orgate, true, "realized", &error_fatal); + object_property_set_int(orgate, "num-lines", 6, &error_fatal); + qdev_realize(DEVICE(orgate), NULL, &error_fatal); orgate_dev = DEVICE(orgate); qdev_connect_gpio_out(orgate_dev, 0, qdev_get_gpio_in(armv7m, 12)); @@ -264,11 +288,10 @@ static void mps2_common_init(MachineState *machine) */ Object *orgate; DeviceState *orgate_dev; - int i; orgate = object_new(TYPE_OR_IRQ); - object_property_set_int(orgate, 10, "num-lines", &error_fatal); - object_property_set_bool(orgate, true, "realized", &error_fatal); + object_property_set_int(orgate, "num-lines", 10, &error_fatal); + qdev_realize(DEVICE(orgate), NULL, &error_fatal); orgate_dev = DEVICE(orgate); qdev_connect_gpio_out(orgate_dev, 0, qdev_get_gpio_in(armv7m, 12)); @@ -282,9 +305,8 @@ static void mps2_common_init(MachineState *machine) DeviceState *txrx_orgate_dev; txrx_orgate = object_new(TYPE_OR_IRQ); - object_property_set_int(txrx_orgate, 2, "num-lines", &error_fatal); - object_property_set_bool(txrx_orgate, true, "realized", - &error_fatal); + object_property_set_int(txrx_orgate, "num-lines", 2, &error_fatal); + qdev_realize(DEVICE(txrx_orgate), NULL, &error_fatal); txrx_orgate_dev = DEVICE(txrx_orgate); qdev_connect_gpio_out(txrx_orgate_dev, 0, qdev_get_gpio_in(armv7m, uart_txrx_irqno[i])); @@ -301,35 +323,81 @@ static void mps2_common_init(MachineState *machine) default: g_assert_not_reached(); } + for (i = 0; i < 4; i++) { + static const hwaddr gpiobase[] = {0x40010000, 0x40011000, + 0x40012000, 0x40013000}; + create_unimplemented_device("cmsdk-ahb-gpio", gpiobase[i], 0x1000); + } + /* CMSDK APB subsystem */ cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ); cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ); - - sysbus_init_child_obj(OBJECT(mms), "dualtimer", &mms->dualtimer, - sizeof(mms->dualtimer), TYPE_CMSDK_APB_DUALTIMER); + object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer, + TYPE_CMSDK_APB_DUALTIMER); qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ); - object_property_set_bool(OBJECT(&mms->dualtimer), true, "realized", - &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(&mms->dualtimer), &error_fatal); sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0, qdev_get_gpio_in(armv7m, 10)); sysbus_mmio_map(SYS_BUS_DEVICE(&mms->dualtimer), 0, 0x40002000); - - sysbus_init_child_obj(OBJECT(mms), "scc", &mms->scc, - sizeof(mms->scc), TYPE_MPS2_SCC); + object_initialize_child(OBJECT(mms), "watchdog", &mms->watchdog, + TYPE_CMSDK_APB_WATCHDOG); + qdev_prop_set_uint32(DEVICE(&mms->watchdog), "wdogclk-frq", SYSCLK_FRQ); + sysbus_realize(SYS_BUS_DEVICE(&mms->watchdog), &error_fatal); + sysbus_connect_irq(SYS_BUS_DEVICE(&mms->watchdog), 0, + qdev_get_gpio_in_named(armv7m, "NMI", 0)); + sysbus_mmio_map(SYS_BUS_DEVICE(&mms->watchdog), 0, 0x40008000); + + /* FPGA APB subsystem */ + object_initialize_child(OBJECT(mms), "scc", &mms->scc, TYPE_MPS2_SCC); sccdev = DEVICE(&mms->scc); qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2); qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008); qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id); - object_property_set_bool(OBJECT(&mms->scc), true, "realized", - &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(&mms->scc), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(sccdev), 0, 0x4002f000); + object_initialize_child(OBJECT(mms), "fpgaio", + &mms->fpgaio, TYPE_MPS2_FPGAIO); + qdev_prop_set_uint32(DEVICE(&mms->fpgaio), "prescale-clk", 25000000); + sysbus_realize(SYS_BUS_DEVICE(&mms->fpgaio), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(&mms->fpgaio), 0, 0x40028000); + sysbus_create_simple(TYPE_PL022, 0x40025000, /* External ADC */ + qdev_get_gpio_in(armv7m, 22)); + for (i = 0; i < 2; i++) { + static const int spi_irqno[] = {11, 24}; + static const hwaddr spibase[] = {0x40020000, /* APB */ + 0x40021000, /* LCD */ + 0x40026000, /* Shield0 */ + 0x40027000}; /* Shield1 */ + DeviceState *orgate_dev; + Object *orgate; + int j; + + orgate = object_new(TYPE_OR_IRQ); + object_property_set_int(orgate, "num-lines", 2, &error_fatal); + orgate_dev = DEVICE(orgate); + qdev_realize(orgate_dev, NULL, &error_fatal); + qdev_connect_gpio_out(orgate_dev, 0, + qdev_get_gpio_in(armv7m, spi_irqno[i])); + for (j = 0; j < 2; j++) { + sysbus_create_simple(TYPE_PL022, spibase[2 * i + j], + qdev_get_gpio_in(orgate_dev, j)); + } + } + for (i = 0; i < 4; i++) { + static const hwaddr i2cbase[] = {0x40022000, /* Touch */ + 0x40023000, /* Audio */ + 0x40029000, /* Shield0 */ + 0x4002a000}; /* Shield1 */ + sysbus_create_simple(TYPE_ARM_SBCON_I2C, i2cbase[i], NULL); + } + create_unimplemented_device("i2s", 0x40024000, 0x400); /* In hardware this is a LAN9220; the LAN9118 is software compatible * except that it doesn't support the checksum-offload feature. */ - lan9118_init(&nd_table[0], 0x40200000, + lan9118_init(&nd_table[0], mmc->ethernet_base, qdev_get_gpio_in(armv7m, - mmc->fpga_type == FPGA_AN385 ? 13 : 47)); + mmc->fpga_type == FPGA_AN511 ? 47 : 13)); system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ; @@ -356,6 +424,37 @@ static void mps2_an385_class_init(ObjectClass *oc, void *data) mmc->fpga_type = FPGA_AN385; mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3"); mmc->scc_id = 0x41043850; + mmc->psram_base = 0x21000000; + mmc->ethernet_base = 0x40200000; + mmc->has_block_ram = true; +} + +static void mps2_an386_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc); + + mc->desc = "ARM MPS2 with AN386 FPGA image for Cortex-M4"; + mmc->fpga_type = FPGA_AN386; + mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4"); + mmc->scc_id = 0x41043860; + mmc->psram_base = 0x21000000; + mmc->ethernet_base = 0x40200000; + mmc->has_block_ram = true; +} + +static void mps2_an500_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc); + + mc->desc = "ARM MPS2 with AN500 FPGA image for Cortex-M7"; + mmc->fpga_type = FPGA_AN500; + mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m7"); + mmc->scc_id = 0x41045000; + mmc->psram_base = 0x60000000; + mmc->ethernet_base = 0xa0000000; + mmc->has_block_ram = false; } static void mps2_an511_class_init(ObjectClass *oc, void *data) @@ -367,6 +466,9 @@ static void mps2_an511_class_init(ObjectClass *oc, void *data) mmc->fpga_type = FPGA_AN511; mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3"); mmc->scc_id = 0x41045110; + mmc->psram_base = 0x21000000; + mmc->ethernet_base = 0x40200000; + mmc->has_block_ram = false; } static const TypeInfo mps2_info = { @@ -384,6 +486,18 @@ static const TypeInfo mps2_an385_info = { .class_init = mps2_an385_class_init, }; +static const TypeInfo mps2_an386_info = { + .name = TYPE_MPS2_AN386_MACHINE, + .parent = TYPE_MPS2_MACHINE, + .class_init = mps2_an386_class_init, +}; + +static const TypeInfo mps2_an500_info = { + .name = TYPE_MPS2_AN500_MACHINE, + .parent = TYPE_MPS2_MACHINE, + .class_init = mps2_an500_class_init, +}; + static const TypeInfo mps2_an511_info = { .name = TYPE_MPS2_AN511_MACHINE, .parent = TYPE_MPS2_MACHINE, @@ -394,6 +508,8 @@ static void mps2_machine_init(void) { type_register_static(&mps2_info); type_register_static(&mps2_an385_info); + type_register_static(&mps2_an386_info); + type_register_static(&mps2_an500_info); type_register_static(&mps2_an511_info); } diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c index f4579e5a085b3948e504c948bb9ab7da7a6e001b..d2c29e82d13a83dad32c8fea61afb25ed1d3aa0e 100644 --- a/hw/arm/msf2-soc.c +++ b/hw/arm/msf2-soc.c @@ -30,7 +30,6 @@ #include "hw/irq.h" #include "hw/arm/msf2-soc.h" #include "hw/misc/unimp.h" -#include "sysemu/runstate.h" #include "sysemu/sysemu.h" #define MSF2_TIMER_BASE 0x40004000 @@ -59,38 +58,22 @@ static const int spi_irq[MSF2_NUM_SPIS] = { 2, 3 }; static const int uart_irq[MSF2_NUM_UARTS] = { 10, 11 }; static const int timer_irq[MSF2_NUM_TIMERS] = { 14, 15 }; -static void do_sys_reset(void *opaque, int n, int level) -{ - if (level) { - qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); - } -} - static void m2sxxx_soc_initfn(Object *obj) { MSF2State *s = MSF2_SOC(obj); int i; - sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m), - TYPE_ARMV7M); + object_initialize_child(obj, "armv7m", &s->armv7m, TYPE_ARMV7M); - sysbus_init_child_obj(obj, "sysreg", &s->sysreg, sizeof(s->sysreg), - TYPE_MSF2_SYSREG); + object_initialize_child(obj, "sysreg", &s->sysreg, TYPE_MSF2_SYSREG); - sysbus_init_child_obj(obj, "timer", &s->timer, sizeof(s->timer), - TYPE_MSS_TIMER); + object_initialize_child(obj, "timer", &s->timer, TYPE_MSS_TIMER); for (i = 0; i < MSF2_NUM_SPIS; i++) { - sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]), - TYPE_MSS_SPI); + object_initialize_child(obj, "spi[*]", &s->spi[i], TYPE_MSS_SPI); } - sysbus_init_child_obj(obj, "emac", &s->emac, sizeof(s->emac), - TYPE_MSS_EMAC); - if (nd_table[0].used) { - qemu_check_nic_model(&nd_table[0], TYPE_MSS_EMAC); - qdev_set_nic_properties(DEVICE(&s->emac), &nd_table[0]); - } + object_initialize_child(obj, "emac", &s->emac, TYPE_MSS_EMAC); } static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp) @@ -98,7 +81,6 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp) MSF2State *s = MSF2_SOC(dev_soc); DeviceState *dev, *armv7m; SysBusDevice *busdev; - Error *err = NULL; int i; MemoryRegion *system_memory = get_system_memory(); @@ -128,11 +110,9 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp) qdev_prop_set_uint32(armv7m, "num-irq", 81); qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type); qdev_prop_set_bit(armv7m, "enable-bitband", true); - object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()), - "memory", &error_abort); - object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + object_property_set_link(OBJECT(&s->armv7m), "memory", + OBJECT(get_system_memory()), &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) { return; } @@ -142,9 +122,6 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp) return; } - qdev_connect_gpio_out_named(DEVICE(&s->armv7m.nvic), "SYSRESETREQ", 0, - qemu_allocate_irq(&do_sys_reset, NULL, 0)); - system_clock_scale = NANOSECONDS_PER_SECOND / s->m3clk; for (i = 0; i < MSF2_NUM_UARTS; i++) { @@ -158,9 +135,7 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp) dev = DEVICE(&s->timer); /* APB0 clock is the timer input clock */ qdev_prop_set_uint32(dev, "clock-frequency", s->m3clk / s->apb0div); - object_property_set_bool(OBJECT(&s->timer), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer), errp)) { return; } busdev = SYS_BUS_DEVICE(dev); @@ -173,9 +148,7 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp) dev = DEVICE(&s->sysreg); qdev_prop_set_uint32(dev, "apb0divisor", s->apb0div); qdev_prop_set_uint32(dev, "apb1divisor", s->apb1div); - object_property_set_bool(OBJECT(&s->sysreg), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysreg), errp)) { return; } busdev = SYS_BUS_DEVICE(dev); @@ -184,9 +157,7 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp) for (i = 0; i < MSF2_NUM_SPIS; i++) { gchar *bus_name; - object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) { return; } @@ -201,12 +172,15 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp) g_free(bus_name); } + /* FIXME use qdev NIC properties instead of nd_table[] */ + if (nd_table[0].used) { + qemu_check_nic_model(&nd_table[0], TYPE_MSS_EMAC); + qdev_set_nic_properties(DEVICE(&s->emac), &nd_table[0]); + } dev = DEVICE(&s->emac); - object_property_set_link(OBJECT(&s->emac), OBJECT(get_system_memory()), - "ahb-bus", &error_abort); - object_property_set_bool(OBJECT(&s->emac), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + object_property_set_link(OBJECT(&s->emac), "ahb-bus", + OBJECT(get_system_memory()), &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->emac), errp)) { return; } busdev = SYS_BUS_DEVICE(dev); diff --git a/hw/arm/msf2-som.c b/hw/arm/msf2-som.c index dbd35b6defe05aca2e1f1fae54c6b42a4ebe2d5c..f9b61c36ddbaa7452d12147a86bc2f46eda1fea8 100644 --- a/hw/arm/msf2-som.c +++ b/hw/arm/msf2-som.c @@ -47,7 +47,7 @@ static void emcraft_sf2_s2s010_init(MachineState *machine) MachineClass *mc = MACHINE_GET_CLASS(machine); DriveInfo *dinfo = drive_get_next(IF_MTD); qemu_irq cs_line; - SSIBus *spi_bus; + BusState *spi_bus; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ddr = g_new(MemoryRegion, 1); @@ -61,7 +61,7 @@ static void emcraft_sf2_s2s010_init(MachineState *machine) &error_fatal); memory_region_add_subregion(sysmem, DDR_BASE_ADDRESS, ddr); - dev = qdev_create(NULL, TYPE_MSF2_SOC); + dev = qdev_new(TYPE_MSF2_SOC); qdev_prop_set_string(dev, "part-name", "M2S010"); qdev_prop_set_string(dev, "cpu-type", mc->default_cpu_type); @@ -77,19 +77,19 @@ static void emcraft_sf2_s2s010_init(MachineState *machine) qdev_prop_set_uint32(dev, "apb0div", 2); qdev_prop_set_uint32(dev, "apb1div", 2); - object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); soc = MSF2_SOC(dev); /* Attach SPI flash to SPI0 controller */ - spi_bus = (SSIBus *)qdev_get_child_bus(dev, "spi0"); - spi_flash = ssi_create_slave_no_init(spi_bus, "s25sl12801"); + spi_bus = qdev_get_child_bus(dev, "spi0"); + spi_flash = qdev_new("s25sl12801"); qdev_prop_set_uint8(spi_flash, "spansion-cr2nv", 1); if (dinfo) { - qdev_prop_set_drive(spi_flash, "drive", blk_by_legacy_dinfo(dinfo), - &error_fatal); + qdev_prop_set_drive_err(spi_flash, "drive", + blk_by_legacy_dinfo(dinfo), &error_fatal); } - qdev_init_nofail(spi_flash); + qdev_realize_and_unref(spi_flash, spi_bus, &error_fatal); cs_line = qdev_get_gpio_in_named(spi_flash, SSI_GPIO_CS, 0); sysbus_connect_irq(SYS_BUS_DEVICE(&soc->spi[0]), 1, cs_line); diff --git a/hw/arm/musca.c b/hw/arm/musca.c index ba99dd19413dacab2b37c0b07d007c55a0a1ae6d..b50157f63a684c65be319b3f864cb57c15abdfae 100644 --- a/hw/arm/musca.c +++ b/hw/arm/musca.c @@ -33,6 +33,7 @@ #include "hw/misc/tz-ppc.h" #include "hw/misc/unimp.h" #include "hw/rtc/pl031.h" +#include "qom/object.h" #define MUSCA_NUMIRQ_MAX 96 #define MUSCA_PPC_MAX 3 @@ -45,7 +46,7 @@ typedef enum MuscaType { MUSCA_B1, } MuscaType; -typedef struct { +struct MuscaMachineClass { MachineClass parent; MuscaType type; uint32_t init_svtor; @@ -53,9 +54,9 @@ typedef struct { int num_irqs; const MPCInfo *mpc_info; int num_mpcs; -} MuscaMachineClass; +}; -typedef struct { +struct MuscaMachineState { MachineState parent; ARMSSE sse; @@ -81,18 +82,13 @@ typedef struct { UnimplementedDeviceState sdio; UnimplementedDeviceState gpio; UnimplementedDeviceState cryptoisland; -} MuscaMachineState; +}; #define TYPE_MUSCA_MACHINE "musca" #define TYPE_MUSCA_A_MACHINE MACHINE_TYPE_NAME("musca-a") #define TYPE_MUSCA_B1_MACHINE MACHINE_TYPE_NAME("musca-b1") -#define MUSCA_MACHINE(obj) \ - OBJECT_CHECK(MuscaMachineState, obj, TYPE_MUSCA_MACHINE) -#define MUSCA_MACHINE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(MuscaMachineClass, obj, TYPE_MUSCA_MACHINE) -#define MUSCA_MACHINE_CLASS(klass) \ - OBJECT_CLASS_CHECK(MuscaMachineClass, klass, TYPE_MUSCA_MACHINE) +OBJECT_DECLARE_TYPE(MuscaMachineState, MuscaMachineClass, MUSCA_MACHINE) /* * Main SYSCLK frequency in Hz @@ -142,12 +138,10 @@ static MemoryRegion *make_unimp_dev(MuscaMachineState *mms, */ UnimplementedDeviceState *uds = opaque; - sysbus_init_child_obj(OBJECT(mms), name, uds, - sizeof(UnimplementedDeviceState), - TYPE_UNIMPLEMENTED_DEVICE); + object_initialize_child(OBJECT(mms), name, uds, TYPE_UNIMPLEMENTED_DEVICE); qdev_prop_set_string(DEVICE(uds), "name", name); qdev_prop_set_uint64(DEVICE(uds), "size", size); - object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(uds), &error_fatal); return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0); } @@ -246,23 +240,21 @@ static MemoryRegion *make_mpc(MuscaMachineState *mms, void *opaque, case MPC_CRYPTOISLAND: /* We don't implement the CryptoIsland yet */ uds = &mms->cryptoisland; - sysbus_init_child_obj(OBJECT(mms), name, uds, - sizeof(UnimplementedDeviceState), - TYPE_UNIMPLEMENTED_DEVICE); + object_initialize_child(OBJECT(mms), name, uds, + TYPE_UNIMPLEMENTED_DEVICE); qdev_prop_set_string(DEVICE(uds), "name", mpcinfo[i].name); qdev_prop_set_uint64(DEVICE(uds), "size", mpcinfo[i].size); - object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(uds), &error_fatal); downstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0); break; default: g_assert_not_reached(); } - sysbus_init_child_obj(OBJECT(mms), mpcname, mpc, sizeof(mms->mpc[0]), - TYPE_TZ_MPC); - object_property_set_link(OBJECT(mpc), OBJECT(downstream), - "downstream", &error_fatal); - object_property_set_bool(OBJECT(mpc), true, "realized", &error_fatal); + object_initialize_child(OBJECT(mms), mpcname, mpc, TYPE_TZ_MPC); + object_property_set_link(OBJECT(mpc), "downstream", OBJECT(downstream), + &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(mpc), &error_fatal); /* Map the upstream end of the MPC into system memory */ upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1); memory_region_add_subregion(get_system_memory(), mpcinfo[i].addr, upstream); @@ -281,8 +273,8 @@ static MemoryRegion *make_rtc(MuscaMachineState *mms, void *opaque, { PL031State *rtc = opaque; - sysbus_init_child_obj(OBJECT(mms), name, rtc, sizeof(mms->rtc), TYPE_PL031); - object_property_set_bool(OBJECT(rtc), true, "realized", &error_fatal); + object_initialize_child(OBJECT(mms), name, rtc, TYPE_PL031); + sysbus_realize(SYS_BUS_DEVICE(rtc), &error_fatal); sysbus_connect_irq(SYS_BUS_DEVICE(rtc), 0, get_sse_irq_in(mms, 39)); return sysbus_mmio_get_region(SYS_BUS_DEVICE(rtc), 0); } @@ -295,10 +287,9 @@ static MemoryRegion *make_uart(MuscaMachineState *mms, void *opaque, int irqbase = 7 + i * 6; SysBusDevice *s; - sysbus_init_child_obj(OBJECT(mms), name, uart, sizeof(mms->uart[0]), - TYPE_PL011); + object_initialize_child(OBJECT(mms), name, uart, TYPE_PL011); qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i)); - object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal); s = SYS_BUS_DEVICE(uart); sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqbase + 5)); /* combined */ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqbase + 0)); /* RX */ @@ -376,11 +367,11 @@ static void musca_init(MachineState *machine) exit(1); } - sysbus_init_child_obj(OBJECT(machine), "sse-200", &mms->sse, - sizeof(mms->sse), TYPE_SSE200); + object_initialize_child(OBJECT(machine), "sse-200", &mms->sse, + TYPE_SSE200); ssedev = DEVICE(&mms->sse); - object_property_set_link(OBJECT(&mms->sse), OBJECT(system_memory), - "memory", &error_fatal); + object_property_set_link(OBJECT(&mms->sse), "memory", + OBJECT(system_memory), &error_fatal); qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs); qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor); qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width); @@ -393,8 +384,7 @@ static void musca_init(MachineState *machine) qdev_prop_set_bit(ssedev, "CPU0_FPU", true); qdev_prop_set_bit(ssedev, "CPU0_DSP", true); } - object_property_set_bool(OBJECT(&mms->sse), true, "realized", - &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(&mms->sse), &error_fatal); /* * We need to create splitters to feed the IRQ inputs @@ -404,15 +394,14 @@ static void musca_init(MachineState *machine) char *name = g_strdup_printf("musca-irq-splitter%d", i); SplitIRQ *splitter = &mms->cpu_irq_splitter[i]; - object_initialize_child(OBJECT(machine), name, - splitter, sizeof(*splitter), - TYPE_SPLIT_IRQ, &error_fatal, NULL); + object_initialize_child_with_props(OBJECT(machine), name, splitter, + sizeof(*splitter), TYPE_SPLIT_IRQ, + &error_fatal, NULL); g_free(name); - object_property_set_int(OBJECT(splitter), 2, "num-lines", + object_property_set_int(OBJECT(splitter), "num-lines", 2, &error_fatal); - object_property_set_bool(OBJECT(splitter), true, "realized", - &error_fatal); + qdev_realize(DEVICE(splitter), NULL, &error_fatal); qdev_connect_gpio_out(DEVICE(splitter), 0, qdev_get_gpio_in_named(ssedev, "EXP_IRQ", i)); qdev_connect_gpio_out(DEVICE(splitter), 1, @@ -424,15 +413,14 @@ static void musca_init(MachineState *machine) * The sec_resp_cfg output from the SSE-200 must be split into multiple * lines, one for each of the PPCs we create here. */ - object_initialize_child(OBJECT(machine), "sec-resp-splitter", - &mms->sec_resp_splitter, - sizeof(mms->sec_resp_splitter), - TYPE_SPLIT_IRQ, &error_fatal, NULL); - - object_property_set_int(OBJECT(&mms->sec_resp_splitter), - ARRAY_SIZE(mms->ppc), "num-lines", &error_fatal); - object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true, - "realized", &error_fatal); + object_initialize_child_with_props(OBJECT(machine), "sec-resp-splitter", + &mms->sec_resp_splitter, + sizeof(mms->sec_resp_splitter), + TYPE_SPLIT_IRQ, &error_fatal, NULL); + + object_property_set_int(OBJECT(&mms->sec_resp_splitter), "num-lines", + ARRAY_SIZE(mms->ppc), &error_fatal); + qdev_realize(DEVICE(&mms->sec_resp_splitter), NULL, &error_fatal); dev_splitter = DEVICE(&mms->sec_resp_splitter); qdev_connect_gpio_out_named(ssedev, "sec_resp_cfg", 0, qdev_get_gpio_in(dev_splitter, 0)); @@ -534,8 +522,8 @@ static void musca_init(MachineState *machine) int port; char *gpioname; - sysbus_init_child_obj(OBJECT(machine), ppcinfo->name, ppc, - sizeof(TZPPC), TYPE_TZ_PPC); + object_initialize_child(OBJECT(machine), ppcinfo->name, ppc, + TYPE_TZ_PPC); ppcdev = DEVICE(ppc); for (port = 0; port < TZ_NUM_PORTS; port++) { @@ -549,12 +537,12 @@ static void musca_init(MachineState *machine) mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size); portname = g_strdup_printf("port[%d]", port); - object_property_set_link(OBJECT(ppc), OBJECT(mr), - portname, &error_fatal); + object_property_set_link(OBJECT(ppc), portname, OBJECT(mr), + &error_fatal); g_free(portname); } - object_property_set_bool(OBJECT(ppc), true, "realized", &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(ppc), &error_fatal); for (port = 0; port < TZ_NUM_PORTS; port++) { const PPCPortInfo *pinfo = &ppcinfo->ports[port]; diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index 92f33ed87edc3c4dfd0a9dfeef4d8a72d0389704..458b1cbeb76393ce15010fb741f5373524f77906 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -27,12 +27,15 @@ #include "ui/console.h" #include "hw/i2c/i2c.h" #include "hw/irq.h" +#include "hw/or-irq.h" #include "hw/audio/wm8750.h" #include "sysemu/block-backend.h" #include "sysemu/runstate.h" +#include "sysemu/dma.h" #include "exec/address-spaces.h" #include "ui/pixel_ops.h" #include "qemu/cutils.h" +#include "qom/object.h" #define MP_MISC_BASE 0x80002000 #define MP_MISC_SIZE 0x00001000 @@ -75,8 +78,7 @@ #define MP_TIMER4_IRQ 7 #define MP_EHCI_IRQ 8 #define MP_ETH_IRQ 9 -#define MP_UART1_IRQ 11 -#define MP_UART2_IRQ 11 +#define MP_UART_SHARED_IRQ 11 #define MP_GPIO_IRQ 12 #define MP_RTC_IRQ 28 #define MP_AUDIO_IRQ 30 @@ -153,16 +155,17 @@ typedef struct mv88w8618_rx_desc { } mv88w8618_rx_desc; #define TYPE_MV88W8618_ETH "mv88w8618_eth" -#define MV88W8618_ETH(obj) \ - OBJECT_CHECK(mv88w8618_eth_state, (obj), TYPE_MV88W8618_ETH) +OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_eth_state, MV88W8618_ETH) -typedef struct mv88w8618_eth_state { +struct mv88w8618_eth_state { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ MemoryRegion iomem; qemu_irq irq; + MemoryRegion *dma_mr; + AddressSpace dma_as; uint32_t smir; uint32_t icr; uint32_t imr; @@ -174,21 +177,23 @@ typedef struct mv88w8618_eth_state { uint32_t cur_rx[4]; NICState *nic; NICConf conf; -} mv88w8618_eth_state; +}; -static void eth_rx_desc_put(uint32_t addr, mv88w8618_rx_desc *desc) +static void eth_rx_desc_put(AddressSpace *dma_as, uint32_t addr, + mv88w8618_rx_desc *desc) { cpu_to_le32s(&desc->cmdstat); cpu_to_le16s(&desc->bytes); cpu_to_le16s(&desc->buffer_size); cpu_to_le32s(&desc->buffer); cpu_to_le32s(&desc->next); - cpu_physical_memory_write(addr, desc, sizeof(*desc)); + dma_memory_write(dma_as, addr, desc, sizeof(*desc)); } -static void eth_rx_desc_get(uint32_t addr, mv88w8618_rx_desc *desc) +static void eth_rx_desc_get(AddressSpace *dma_as, uint32_t addr, + mv88w8618_rx_desc *desc) { - cpu_physical_memory_read(addr, desc, sizeof(*desc)); + dma_memory_read(dma_as, addr, desc, sizeof(*desc)); le32_to_cpus(&desc->cmdstat); le16_to_cpus(&desc->bytes); le16_to_cpus(&desc->buffer_size); @@ -209,9 +214,9 @@ static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size) continue; } do { - eth_rx_desc_get(desc_addr, &desc); + eth_rx_desc_get(&s->dma_as, desc_addr, &desc); if ((desc.cmdstat & MP_ETH_RX_OWN) && desc.buffer_size >= size) { - cpu_physical_memory_write(desc.buffer + s->vlan_header, + dma_memory_write(&s->dma_as, desc.buffer + s->vlan_header, buf, size); desc.bytes = size + s->vlan_header; desc.cmdstat &= ~MP_ETH_RX_OWN; @@ -221,7 +226,7 @@ static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size) if (s->icr & s->imr) { qemu_irq_raise(s->irq); } - eth_rx_desc_put(desc_addr, &desc); + eth_rx_desc_put(&s->dma_as, desc_addr, &desc); return size; } desc_addr = desc.next; @@ -230,19 +235,21 @@ static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size) return size; } -static void eth_tx_desc_put(uint32_t addr, mv88w8618_tx_desc *desc) +static void eth_tx_desc_put(AddressSpace *dma_as, uint32_t addr, + mv88w8618_tx_desc *desc) { cpu_to_le32s(&desc->cmdstat); cpu_to_le16s(&desc->res); cpu_to_le16s(&desc->bytes); cpu_to_le32s(&desc->buffer); cpu_to_le32s(&desc->next); - cpu_physical_memory_write(addr, desc, sizeof(*desc)); + dma_memory_write(dma_as, addr, desc, sizeof(*desc)); } -static void eth_tx_desc_get(uint32_t addr, mv88w8618_tx_desc *desc) +static void eth_tx_desc_get(AddressSpace *dma_as, uint32_t addr, + mv88w8618_tx_desc *desc) { - cpu_physical_memory_read(addr, desc, sizeof(*desc)); + dma_memory_read(dma_as, addr, desc, sizeof(*desc)); le32_to_cpus(&desc->cmdstat); le16_to_cpus(&desc->res); le16_to_cpus(&desc->bytes); @@ -259,17 +266,17 @@ static void eth_send(mv88w8618_eth_state *s, int queue_index) int len; do { - eth_tx_desc_get(desc_addr, &desc); + eth_tx_desc_get(&s->dma_as, desc_addr, &desc); next_desc = desc.next; if (desc.cmdstat & MP_ETH_TX_OWN) { len = desc.bytes; if (len < 2048) { - cpu_physical_memory_read(desc.buffer, buf, len); + dma_memory_read(&s->dma_as, desc.buffer, buf, len); qemu_send_packet(qemu_get_queue(s->nic), buf, len); } desc.cmdstat &= ~MP_ETH_TX_OWN; s->icr |= 1 << (MP_ETH_IRQ_TXLO_BIT - queue_index); - eth_tx_desc_put(desc_addr, &desc); + eth_tx_desc_put(&s->dma_as, desc_addr, &desc); } desc_addr = next_desc; } while (desc_addr != s->tx_queue[queue_index]); @@ -405,6 +412,12 @@ static void mv88w8618_eth_realize(DeviceState *dev, Error **errp) { mv88w8618_eth_state *s = MV88W8618_ETH(dev); + if (!s->dma_mr) { + error_setg(errp, TYPE_MV88W8618_ETH " 'dma-memory' link not set"); + return; + } + + address_space_init(&s->dma_as, s->dma_mr, "emac-dma"); s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s); } @@ -428,6 +441,8 @@ static const VMStateDescription mv88w8618_eth_vmsd = { static Property mv88w8618_eth_properties[] = { DEFINE_NIC_PROPERTIES(mv88w8618_eth_state, conf), + DEFINE_PROP_LINK("dma-memory", mv88w8618_eth_state, dma_mr, + TYPE_MEMORY_REGION, MemoryRegion *), DEFINE_PROP_END_OF_LIST(), }; @@ -468,10 +483,9 @@ static const TypeInfo mv88w8618_eth_info = { #define MP_LCD_TEXTCOLOR 0xe0e0ff /* RRGGBB */ #define TYPE_MUSICPAL_LCD "musicpal_lcd" -#define MUSICPAL_LCD(obj) \ - OBJECT_CHECK(musicpal_lcd_state, (obj), TYPE_MUSICPAL_LCD) +OBJECT_DECLARE_SIMPLE_TYPE(musicpal_lcd_state, MUSICPAL_LCD) -typedef struct musicpal_lcd_state { +struct musicpal_lcd_state { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -484,7 +498,7 @@ typedef struct musicpal_lcd_state { uint32_t page_off; QemuConsole *con; uint8_t video_ram[128*64/8]; -} musicpal_lcd_state; +}; static uint8_t scale_lcd_color(musicpal_lcd_state *s, uint8_t col) { @@ -685,10 +699,9 @@ static const TypeInfo musicpal_lcd_info = { #define MP_PIC_ENABLE_CLR 0x0C #define TYPE_MV88W8618_PIC "mv88w8618_pic" -#define MV88W8618_PIC(obj) \ - OBJECT_CHECK(mv88w8618_pic_state, (obj), TYPE_MV88W8618_PIC) +OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_pic_state, MV88W8618_PIC) -typedef struct mv88w8618_pic_state { +struct mv88w8618_pic_state { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -697,7 +710,7 @@ typedef struct mv88w8618_pic_state { uint32_t level; uint32_t enabled; qemu_irq parent_irq; -} mv88w8618_pic_state; +}; static void mv88w8618_pic_update(mv88w8618_pic_state *s) { @@ -822,17 +835,16 @@ typedef struct mv88w8618_timer_state { } mv88w8618_timer_state; #define TYPE_MV88W8618_PIT "mv88w8618_pit" -#define MV88W8618_PIT(obj) \ - OBJECT_CHECK(mv88w8618_pit_state, (obj), TYPE_MV88W8618_PIT) +OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_pit_state, MV88W8618_PIT) -typedef struct mv88w8618_pit_state { +struct mv88w8618_pit_state { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ MemoryRegion iomem; mv88w8618_timer_state timer[4]; -} mv88w8618_pit_state; +}; static void mv88w8618_timer_tick(void *opaque) { @@ -989,17 +1001,16 @@ static const TypeInfo mv88w8618_pit_info = { #define MP_FLASHCFG_CFGR0 0x04 #define TYPE_MV88W8618_FLASHCFG "mv88w8618_flashcfg" -#define MV88W8618_FLASHCFG(obj) \ - OBJECT_CHECK(mv88w8618_flashcfg_state, (obj), TYPE_MV88W8618_FLASHCFG) +OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_flashcfg_state, MV88W8618_FLASHCFG) -typedef struct mv88w8618_flashcfg_state { +struct mv88w8618_flashcfg_state { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ MemoryRegion iomem; uint32_t cfgr0; -} mv88w8618_flashcfg_state; +}; static uint64_t mv88w8618_flashcfg_read(void *opaque, hwaddr offset, @@ -1075,14 +1086,13 @@ static const TypeInfo mv88w8618_flashcfg_info = { #define MP_BOARD_REVISION 0x31 -typedef struct { +struct MusicPalMiscState { SysBusDevice parent_obj; MemoryRegion iomem; -} MusicPalMiscState; +}; #define TYPE_MUSICPAL_MISC "musicpal-misc" -#define MUSICPAL_MISC(obj) \ - OBJECT_CHECK(MusicPalMiscState, (obj), TYPE_MUSICPAL_MISC) +OBJECT_DECLARE_SIMPLE_TYPE(MusicPalMiscState, MUSICPAL_MISC) static uint64_t musicpal_misc_read(void *opaque, hwaddr offset, unsigned size) @@ -1187,10 +1197,9 @@ static void mv88w8618_wlan_realize(DeviceState *dev, Error **errp) #define MP_OE_LCD_BRIGHTNESS 0x0007 #define TYPE_MUSICPAL_GPIO "musicpal_gpio" -#define MUSICPAL_GPIO(obj) \ - OBJECT_CHECK(musicpal_gpio_state, (obj), TYPE_MUSICPAL_GPIO) +OBJECT_DECLARE_SIMPLE_TYPE(musicpal_gpio_state, MUSICPAL_GPIO) -typedef struct musicpal_gpio_state { +struct musicpal_gpio_state { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -1204,7 +1213,7 @@ typedef struct musicpal_gpio_state { uint32_t isr; qemu_irq irq; qemu_irq out[5]; /* 3 brightness out + 2 lcd (data and clock ) */ -} musicpal_gpio_state; +}; static void musicpal_gpio_brightness_update(musicpal_gpio_state *s) { int i; @@ -1437,10 +1446,9 @@ static const TypeInfo musicpal_gpio_info = { #define MP_KEY_BTN_NAVIGATION (1 << 7) #define TYPE_MUSICPAL_KEY "musicpal_key" -#define MUSICPAL_KEY(obj) \ - OBJECT_CHECK(musicpal_key_state, (obj), TYPE_MUSICPAL_KEY) +OBJECT_DECLARE_SIMPLE_TYPE(musicpal_key_state, MUSICPAL_KEY) -typedef struct musicpal_key_state { +struct musicpal_key_state { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -1449,7 +1457,7 @@ typedef struct musicpal_key_state { uint32_t kbd_extended; uint32_t pressed_keys; qemu_irq out[8]; -} musicpal_key_state; +}; static void musicpal_key_event(void *opaque, int keycode) { @@ -1579,12 +1587,13 @@ static struct arm_boot_info musicpal_binfo = { static void musicpal_init(MachineState *machine) { ARMCPU *cpu; - qemu_irq pic[32]; DeviceState *dev; + DeviceState *pic; + DeviceState *uart_orgate; DeviceState *i2c_dev; DeviceState *lcd_dev; DeviceState *key_dev; - DeviceState *wm8750_dev; + I2CSlave *wm8750_dev; SysBusDevice *s; I2CBus *i2c; int i; @@ -1610,18 +1619,26 @@ static void musicpal_init(MachineState *machine) &error_fatal); memory_region_add_subregion(address_space_mem, MP_SRAM_BASE, sram); - dev = sysbus_create_simple(TYPE_MV88W8618_PIC, MP_PIC_BASE, + pic = sysbus_create_simple(TYPE_MV88W8618_PIC, MP_PIC_BASE, qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ)); - for (i = 0; i < 32; i++) { - pic[i] = qdev_get_gpio_in(dev, i); - } - sysbus_create_varargs(TYPE_MV88W8618_PIT, MP_PIT_BASE, pic[MP_TIMER1_IRQ], - pic[MP_TIMER2_IRQ], pic[MP_TIMER3_IRQ], - pic[MP_TIMER4_IRQ], NULL); - - serial_mm_init(address_space_mem, MP_UART1_BASE, 2, pic[MP_UART1_IRQ], + sysbus_create_varargs(TYPE_MV88W8618_PIT, MP_PIT_BASE, + qdev_get_gpio_in(pic, MP_TIMER1_IRQ), + qdev_get_gpio_in(pic, MP_TIMER2_IRQ), + qdev_get_gpio_in(pic, MP_TIMER3_IRQ), + qdev_get_gpio_in(pic, MP_TIMER4_IRQ), NULL); + + /* Logically OR both UART IRQs together */ + uart_orgate = DEVICE(object_new(TYPE_OR_IRQ)); + object_property_set_int(OBJECT(uart_orgate), "num-lines", 2, &error_fatal); + qdev_realize_and_unref(uart_orgate, NULL, &error_fatal); + qdev_connect_gpio_out(DEVICE(uart_orgate), 0, + qdev_get_gpio_in(pic, MP_UART_SHARED_IRQ)); + + serial_mm_init(address_space_mem, MP_UART1_BASE, 2, + qdev_get_gpio_in(uart_orgate, 0), 1825000, serial_hd(0), DEVICE_NATIVE_ENDIAN); - serial_mm_init(address_space_mem, MP_UART2_BASE, 2, pic[MP_UART2_IRQ], + serial_mm_init(address_space_mem, MP_UART2_BASE, 2, + qdev_get_gpio_in(uart_orgate, 1), 1825000, serial_hd(1), DEVICE_NATIVE_ENDIAN); /* Register flash */ @@ -1651,18 +1668,21 @@ static void musicpal_init(MachineState *machine) sysbus_create_simple(TYPE_MV88W8618_FLASHCFG, MP_FLASHCFG_BASE, NULL); qemu_check_nic_model(&nd_table[0], "mv88w8618"); - dev = qdev_create(NULL, TYPE_MV88W8618_ETH); + dev = qdev_new(TYPE_MV88W8618_ETH); qdev_set_nic_properties(dev, &nd_table[0]); - qdev_init_nofail(dev); + object_property_set_link(OBJECT(dev), "dma-memory", + OBJECT(get_system_memory()), &error_fatal); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, MP_ETH_BASE); - sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[MP_ETH_IRQ]); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, + qdev_get_gpio_in(pic, MP_ETH_IRQ)); sysbus_create_simple("mv88w8618_wlan", MP_WLAN_BASE, NULL); sysbus_create_simple(TYPE_MUSICPAL_MISC, MP_MISC_BASE, NULL); dev = sysbus_create_simple(TYPE_MUSICPAL_GPIO, MP_GPIO_BASE, - pic[MP_GPIO_IRQ]); + qdev_get_gpio_in(pic, MP_GPIO_IRQ)); i2c_dev = sysbus_create_simple("gpio_i2c", -1, NULL); i2c = (I2CBus *)qdev_get_child_bus(i2c_dev, "i2c"); @@ -1687,14 +1707,14 @@ static void musicpal_init(MachineState *machine) qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15)); } - wm8750_dev = i2c_create_slave(i2c, TYPE_WM8750, MP_WM_ADDR); - dev = qdev_create(NULL, TYPE_MV88W8618_AUDIO); + wm8750_dev = i2c_slave_create_simple(i2c, TYPE_WM8750, MP_WM_ADDR); + dev = qdev_new(TYPE_MV88W8618_AUDIO); s = SYS_BUS_DEVICE(dev); - object_property_set_link(OBJECT(dev), OBJECT(wm8750_dev), - "wm8750", NULL); - qdev_init_nofail(dev); + object_property_set_link(OBJECT(dev), "wm8750", OBJECT(wm8750_dev), + NULL); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, MP_AUDIO_BASE); - sysbus_connect_irq(s, 0, pic[MP_AUDIO_IRQ]); + sysbus_connect_irq(s, 0, qdev_get_gpio_in(pic, MP_AUDIO_IRQ)); musicpal_binfo.ram_size = MP_RAM_DEFAULT_SIZE; arm_load_kernel(cpu, machine, &musicpal_binfo); diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c index e770d9cac8b6117b15f7da35d9ae28a2d9a9d2e2..8f103341443755537f9b683203a123f4340695e6 100644 --- a/hw/arm/netduino2.c +++ b/hw/arm/netduino2.c @@ -30,13 +30,23 @@ #include "hw/arm/stm32f205_soc.h" #include "hw/arm/boot.h" +/* Main SYSCLK frequency in Hz (120MHz) */ +#define SYSCLK_FRQ 120000000ULL + static void netduino2_init(MachineState *machine) { DeviceState *dev; - dev = qdev_create(NULL, TYPE_STM32F205_SOC); + /* + * TODO: ideally we would model the SoC RCC and let it handle + * system_clock_scale, including its ability to define different + * possible SYSCLK sources. + */ + system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ; + + dev = qdev_new(TYPE_STM32F205_SOC); qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3")); - object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, FLASH_SIZE); diff --git a/hw/arm/netduinoplus2.c b/hw/arm/netduinoplus2.c index e5e247edbed68b0df9554ef3f859e259360b20ed..68abd3ec69d9435f020c17f5ddf63f28d7312c13 100644 --- a/hw/arm/netduinoplus2.c +++ b/hw/arm/netduinoplus2.c @@ -30,13 +30,23 @@ #include "hw/arm/stm32f405_soc.h" #include "hw/arm/boot.h" +/* Main SYSCLK frequency in Hz (168MHz) */ +#define SYSCLK_FRQ 168000000ULL + static void netduinoplus2_init(MachineState *machine) { DeviceState *dev; - dev = qdev_create(NULL, TYPE_STM32F405_SOC); + /* + * TODO: ideally we would model the SoC RCC and let it handle + * system_clock_scale, including its ability to define different + * possible SYSCLK sources. + */ + system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ; + + dev = qdev_new(TYPE_STM32F405_SOC); qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4")); - object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c new file mode 100644 index 0000000000000000000000000000000000000000..47e2b6fc400de2c7355203728d8a02bccac22505 --- /dev/null +++ b/hw/arm/npcm7xx.c @@ -0,0 +1,652 @@ +/* + * Nuvoton NPCM7xx SoC family. + * + * Copyright 2020 Google LLC + * + * 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. + */ + +#include "qemu/osdep.h" + +#include "exec/address-spaces.h" +#include "hw/arm/boot.h" +#include "hw/arm/npcm7xx.h" +#include "hw/char/serial.h" +#include "hw/loader.h" +#include "hw/misc/unimp.h" +#include "hw/qdev-properties.h" +#include "qapi/error.h" +#include "qemu/units.h" +#include "sysemu/sysemu.h" + +/* + * This covers the whole MMIO space. We'll use this to catch any MMIO accesses + * that aren't handled by any device. + */ +#define NPCM7XX_MMIO_BA (0x80000000) +#define NPCM7XX_MMIO_SZ (0x7ffd0000) + +/* OTP key storage and fuse strap array */ +#define NPCM7XX_OTP1_BA (0xf0189000) +#define NPCM7XX_OTP2_BA (0xf018a000) + +/* Core system modules. */ +#define NPCM7XX_L2C_BA (0xf03fc000) +#define NPCM7XX_CPUP_BA (0xf03fe000) +#define NPCM7XX_GCR_BA (0xf0800000) +#define NPCM7XX_CLK_BA (0xf0801000) +#define NPCM7XX_MC_BA (0xf0824000) +#define NPCM7XX_RNG_BA (0xf000b000) + +/* USB Host modules */ +#define NPCM7XX_EHCI_BA (0xf0806000) +#define NPCM7XX_OHCI_BA (0xf0807000) + +/* Internal AHB SRAM */ +#define NPCM7XX_RAM3_BA (0xc0008000) +#define NPCM7XX_RAM3_SZ (4 * KiB) + +/* Memory blocks at the end of the address space */ +#define NPCM7XX_RAM2_BA (0xfffd0000) +#define NPCM7XX_RAM2_SZ (128 * KiB) +#define NPCM7XX_ROM_BA (0xffff0000) +#define NPCM7XX_ROM_SZ (64 * KiB) + +/* Clock configuration values to be fixed up when bypassing bootloader */ + +/* Run PLL1 at 1600 MHz */ +#define NPCM7XX_PLLCON1_FIXUP_VAL (0x00402101) +/* Run the CPU from PLL1 and UART from PLL2 */ +#define NPCM7XX_CLKSEL_FIXUP_VAL (0x004aaba9) + +/* + * Interrupt lines going into the GIC. This does not include internal Cortex-A9 + * interrupts. + */ +enum NPCM7xxInterrupt { + NPCM7XX_UART0_IRQ = 2, + NPCM7XX_UART1_IRQ, + NPCM7XX_UART2_IRQ, + NPCM7XX_UART3_IRQ, + NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */ + NPCM7XX_TIMER1_IRQ, + NPCM7XX_TIMER2_IRQ, + NPCM7XX_TIMER3_IRQ, + NPCM7XX_TIMER4_IRQ, + NPCM7XX_TIMER5_IRQ, /* Timer Module 1 */ + NPCM7XX_TIMER6_IRQ, + NPCM7XX_TIMER7_IRQ, + NPCM7XX_TIMER8_IRQ, + NPCM7XX_TIMER9_IRQ, + NPCM7XX_TIMER10_IRQ, /* Timer Module 2 */ + NPCM7XX_TIMER11_IRQ, + NPCM7XX_TIMER12_IRQ, + NPCM7XX_TIMER13_IRQ, + NPCM7XX_TIMER14_IRQ, + NPCM7XX_WDG0_IRQ = 47, /* Timer Module 0 Watchdog */ + NPCM7XX_WDG1_IRQ, /* Timer Module 1 Watchdog */ + NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */ + NPCM7XX_EHCI_IRQ = 61, + NPCM7XX_OHCI_IRQ = 62, + NPCM7XX_GPIO0_IRQ = 116, + NPCM7XX_GPIO1_IRQ, + NPCM7XX_GPIO2_IRQ, + NPCM7XX_GPIO3_IRQ, + NPCM7XX_GPIO4_IRQ, + NPCM7XX_GPIO5_IRQ, + NPCM7XX_GPIO6_IRQ, + NPCM7XX_GPIO7_IRQ, +}; + +/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */ +#define NPCM7XX_NUM_IRQ (160) + +/* Register base address for each Timer Module */ +static const hwaddr npcm7xx_tim_addr[] = { + 0xf0008000, + 0xf0009000, + 0xf000a000, +}; + +/* Register base address for each 16550 UART */ +static const hwaddr npcm7xx_uart_addr[] = { + 0xf0001000, + 0xf0002000, + 0xf0003000, + 0xf0004000, +}; + +/* Direct memory-mapped access to SPI0 CS0-1. */ +static const hwaddr npcm7xx_fiu0_flash_addr[] = { + 0x80000000, /* CS0 */ + 0x88000000, /* CS1 */ +}; + +/* Direct memory-mapped access to SPI3 CS0-3. */ +static const hwaddr npcm7xx_fiu3_flash_addr[] = { + 0xa0000000, /* CS0 */ + 0xa8000000, /* CS1 */ + 0xb0000000, /* CS2 */ + 0xb8000000, /* CS3 */ +}; + +static const struct { + hwaddr regs_addr; + uint32_t unconnected_pins; + uint32_t reset_pu; + uint32_t reset_pd; + uint32_t reset_osrc; + uint32_t reset_odsc; +} npcm7xx_gpio[] = { + { + .regs_addr = 0xf0010000, + .reset_pu = 0xff03ffff, + .reset_pd = 0x00fc0000, + }, { + .regs_addr = 0xf0011000, + .unconnected_pins = 0x0000001e, + .reset_pu = 0xfefffe07, + .reset_pd = 0x010001e0, + }, { + .regs_addr = 0xf0012000, + .reset_pu = 0x780fffff, + .reset_pd = 0x07f00000, + .reset_odsc = 0x00700000, + }, { + .regs_addr = 0xf0013000, + .reset_pu = 0x00fc0000, + .reset_pd = 0xff000000, + }, { + .regs_addr = 0xf0014000, + .reset_pu = 0xffffffff, + }, { + .regs_addr = 0xf0015000, + .reset_pu = 0xbf83f801, + .reset_pd = 0x007c0000, + .reset_osrc = 0x000000f1, + .reset_odsc = 0x3f9f80f1, + }, { + .regs_addr = 0xf0016000, + .reset_pu = 0xfc00f801, + .reset_pd = 0x000007fe, + .reset_odsc = 0x00000800, + }, { + .regs_addr = 0xf0017000, + .unconnected_pins = 0xffffff00, + .reset_pu = 0x0000007f, + .reset_osrc = 0x0000007f, + .reset_odsc = 0x0000007f, + }, +}; + +static const struct { + const char *name; + hwaddr regs_addr; + int cs_count; + const hwaddr *flash_addr; +} npcm7xx_fiu[] = { + { + .name = "fiu0", + .regs_addr = 0xfb000000, + .cs_count = ARRAY_SIZE(npcm7xx_fiu0_flash_addr), + .flash_addr = npcm7xx_fiu0_flash_addr, + }, { + .name = "fiu3", + .regs_addr = 0xc0000000, + .cs_count = ARRAY_SIZE(npcm7xx_fiu3_flash_addr), + .flash_addr = npcm7xx_fiu3_flash_addr, + }, +}; + +static void npcm7xx_write_board_setup(ARMCPU *cpu, + const struct arm_boot_info *info) +{ + uint32_t board_setup[] = { + 0xe59f0010, /* ldr r0, clk_base_addr */ + 0xe59f1010, /* ldr r1, pllcon1_value */ + 0xe5801010, /* str r1, [r0, #16] */ + 0xe59f100c, /* ldr r1, clksel_value */ + 0xe5801004, /* str r1, [r0, #4] */ + 0xe12fff1e, /* bx lr */ + NPCM7XX_CLK_BA, + NPCM7XX_PLLCON1_FIXUP_VAL, + NPCM7XX_CLKSEL_FIXUP_VAL, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(board_setup); i++) { + board_setup[i] = tswap32(board_setup[i]); + } + rom_add_blob_fixed("board-setup", board_setup, sizeof(board_setup), + info->board_setup_addr); +} + +static void npcm7xx_write_secondary_boot(ARMCPU *cpu, + const struct arm_boot_info *info) +{ + /* + * The default smpboot stub halts the secondary CPU with a 'wfi' + * instruction, but the arch/arm/mach-npcm/platsmp.c in the Linux kernel + * does not send an IPI to wake it up, so the second CPU fails to boot. So + * we need to provide our own smpboot stub that can not use 'wfi', it has + * to spin the secondary CPU until the first CPU writes to the SCRPAD reg. + */ + uint32_t smpboot[] = { + 0xe59f2018, /* ldr r2, bootreg_addr */ + 0xe3a00000, /* mov r0, #0 */ + 0xe5820000, /* str r0, [r2] */ + 0xe320f002, /* wfe */ + 0xe5921000, /* ldr r1, [r2] */ + 0xe1110001, /* tst r1, r1 */ + 0x0afffffb, /* beq */ + 0xe12fff11, /* bx r1 */ + NPCM7XX_SMP_BOOTREG_ADDR, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(smpboot); i++) { + smpboot[i] = tswap32(smpboot[i]); + } + + rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), + NPCM7XX_SMP_LOADER_START); +} + +static struct arm_boot_info npcm7xx_binfo = { + .loader_start = NPCM7XX_LOADER_START, + .smp_loader_start = NPCM7XX_SMP_LOADER_START, + .smp_bootreg_addr = NPCM7XX_SMP_BOOTREG_ADDR, + .gic_cpu_if_addr = NPCM7XX_GIC_CPU_IF_ADDR, + .write_secondary_boot = npcm7xx_write_secondary_boot, + .board_id = -1, + .board_setup_addr = NPCM7XX_BOARD_SETUP_ADDR, + .write_board_setup = npcm7xx_write_board_setup, +}; + +void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc) +{ + NPCM7xxClass *sc = NPCM7XX_GET_CLASS(soc); + + npcm7xx_binfo.ram_size = machine->ram_size; + npcm7xx_binfo.nb_cpus = sc->num_cpus; + + arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo); +} + +static void npcm7xx_init_fuses(NPCM7xxState *s) +{ + NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s); + uint32_t value; + + /* + * The initial mask of disabled modules indicates the chip derivative (e.g. + * NPCM750 or NPCM730). + */ + value = tswap32(nc->disabled_modules); + npcm7xx_otp_array_write(&s->fuse_array, &value, NPCM7XX_FUSE_DERIVATIVE, + sizeof(value)); +} + +static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n) +{ + return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n); +} + +static void npcm7xx_init(Object *obj) +{ + NPCM7xxState *s = NPCM7XX(obj); + int i; + + for (i = 0; i < NPCM7XX_MAX_NUM_CPUS; i++) { + object_initialize_child(obj, "cpu[*]", &s->cpu[i], + ARM_CPU_TYPE_NAME("cortex-a9")); + } + + object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV); + object_initialize_child(obj, "gcr", &s->gcr, TYPE_NPCM7XX_GCR); + object_property_add_alias(obj, "power-on-straps", OBJECT(&s->gcr), + "power-on-straps"); + object_initialize_child(obj, "clk", &s->clk, TYPE_NPCM7XX_CLK); + object_initialize_child(obj, "otp1", &s->key_storage, + TYPE_NPCM7XX_KEY_STORAGE); + object_initialize_child(obj, "otp2", &s->fuse_array, + TYPE_NPCM7XX_FUSE_ARRAY); + object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC); + object_initialize_child(obj, "rng", &s->rng, TYPE_NPCM7XX_RNG); + + for (i = 0; i < ARRAY_SIZE(s->tim); i++) { + object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER); + } + + for (i = 0; i < ARRAY_SIZE(s->gpio); i++) { + object_initialize_child(obj, "gpio[*]", &s->gpio[i], TYPE_NPCM7XX_GPIO); + } + + object_initialize_child(obj, "ehci", &s->ehci, TYPE_NPCM7XX_EHCI); + object_initialize_child(obj, "ohci", &s->ohci, TYPE_SYSBUS_OHCI); + + QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu)); + for (i = 0; i < ARRAY_SIZE(s->fiu); i++) { + object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i], + TYPE_NPCM7XX_FIU); + } +} + +static void npcm7xx_realize(DeviceState *dev, Error **errp) +{ + NPCM7xxState *s = NPCM7XX(dev); + NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s); + int i; + + if (memory_region_size(s->dram) > NPCM7XX_DRAM_SZ) { + error_setg(errp, "%s: NPCM7xx cannot address more than %" PRIu64 + " MiB of DRAM", __func__, NPCM7XX_DRAM_SZ / MiB); + return; + } + + /* CPUs */ + for (i = 0; i < nc->num_cpus; i++) { + object_property_set_int(OBJECT(&s->cpu[i]), "mp-affinity", + arm_cpu_mp_affinity(i, NPCM7XX_MAX_NUM_CPUS), + &error_abort); + object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar", + NPCM7XX_GIC_CPU_IF_ADDR, &error_abort); + object_property_set_bool(OBJECT(&s->cpu[i]), "reset-hivecs", true, + &error_abort); + + /* Disable security extensions. */ + object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3", false, + &error_abort); + + if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) { + return; + } + } + + /* A9MPCORE peripherals. Can only fail if we pass bad parameters here. */ + object_property_set_int(OBJECT(&s->a9mpcore), "num-cpu", nc->num_cpus, + &error_abort); + object_property_set_int(OBJECT(&s->a9mpcore), "num-irq", NPCM7XX_NUM_IRQ, + &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->a9mpcore), &error_abort); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->a9mpcore), 0, NPCM7XX_CPUP_BA); + + for (i = 0; i < nc->num_cpus; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i, + qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_IRQ)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i + nc->num_cpus, + qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_FIQ)); + } + + /* L2 cache controller */ + sysbus_create_simple("l2x0", NPCM7XX_L2C_BA, NULL); + + /* System Global Control Registers (GCR). Can fail due to user input. */ + object_property_set_int(OBJECT(&s->gcr), "disabled-modules", + nc->disabled_modules, &error_abort); + object_property_add_const_link(OBJECT(&s->gcr), "dram-mr", OBJECT(s->dram)); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gcr), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gcr), 0, NPCM7XX_GCR_BA); + + /* Clock Control Registers (CLK). Cannot fail. */ + sysbus_realize(SYS_BUS_DEVICE(&s->clk), &error_abort); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->clk), 0, NPCM7XX_CLK_BA); + + /* OTP key storage and fuse strap array. Cannot fail. */ + sysbus_realize(SYS_BUS_DEVICE(&s->key_storage), &error_abort); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->key_storage), 0, NPCM7XX_OTP1_BA); + sysbus_realize(SYS_BUS_DEVICE(&s->fuse_array), &error_abort); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->fuse_array), 0, NPCM7XX_OTP2_BA); + npcm7xx_init_fuses(s); + + /* Fake Memory Controller (MC). Cannot fail. */ + sysbus_realize(SYS_BUS_DEVICE(&s->mc), &error_abort); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->mc), 0, NPCM7XX_MC_BA); + + /* Timer Modules (TIM). Cannot fail. */ + QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim)); + for (i = 0; i < ARRAY_SIZE(s->tim); i++) { + SysBusDevice *sbd = SYS_BUS_DEVICE(&s->tim[i]); + int first_irq; + int j; + + sysbus_realize(sbd, &error_abort); + sysbus_mmio_map(sbd, 0, npcm7xx_tim_addr[i]); + + first_irq = NPCM7XX_TIMER0_IRQ + i * NPCM7XX_TIMERS_PER_CTRL; + for (j = 0; j < NPCM7XX_TIMERS_PER_CTRL; j++) { + qemu_irq irq = npcm7xx_irq(s, first_irq + j); + sysbus_connect_irq(sbd, j, irq); + } + + /* IRQ for watchdogs */ + sysbus_connect_irq(sbd, NPCM7XX_TIMERS_PER_CTRL, + npcm7xx_irq(s, NPCM7XX_WDG0_IRQ + i)); + /* GPIO that connects clk module with watchdog */ + qdev_connect_gpio_out_named(DEVICE(&s->tim[i]), + NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 0, + qdev_get_gpio_in_named(DEVICE(&s->clk), + NPCM7XX_WATCHDOG_RESET_GPIO_IN, i)); + } + + /* UART0..3 (16550 compatible) */ + for (i = 0; i < ARRAY_SIZE(npcm7xx_uart_addr); i++) { + serial_mm_init(get_system_memory(), npcm7xx_uart_addr[i], 2, + npcm7xx_irq(s, NPCM7XX_UART0_IRQ + i), 115200, + serial_hd(i), DEVICE_LITTLE_ENDIAN); + } + + /* Random Number Generator. Cannot fail. */ + sysbus_realize(SYS_BUS_DEVICE(&s->rng), &error_abort); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->rng), 0, NPCM7XX_RNG_BA); + + /* GPIO modules. Cannot fail. */ + QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_gpio) != ARRAY_SIZE(s->gpio)); + for (i = 0; i < ARRAY_SIZE(s->gpio); i++) { + Object *obj = OBJECT(&s->gpio[i]); + + object_property_set_uint(obj, "reset-pullup", + npcm7xx_gpio[i].reset_pu, &error_abort); + object_property_set_uint(obj, "reset-pulldown", + npcm7xx_gpio[i].reset_pd, &error_abort); + object_property_set_uint(obj, "reset-osrc", + npcm7xx_gpio[i].reset_osrc, &error_abort); + object_property_set_uint(obj, "reset-odsc", + npcm7xx_gpio[i].reset_odsc, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(obj), &error_abort); + sysbus_mmio_map(SYS_BUS_DEVICE(obj), 0, npcm7xx_gpio[i].regs_addr); + sysbus_connect_irq(SYS_BUS_DEVICE(obj), 0, + npcm7xx_irq(s, NPCM7XX_GPIO0_IRQ + i)); + } + + /* USB Host */ + object_property_set_bool(OBJECT(&s->ehci), "companion-enable", true, + &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->ehci), &error_abort); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->ehci), 0, NPCM7XX_EHCI_BA); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci), 0, + npcm7xx_irq(s, NPCM7XX_EHCI_IRQ)); + + object_property_set_str(OBJECT(&s->ohci), "masterbus", "usb-bus.0", + &error_abort); + object_property_set_uint(OBJECT(&s->ohci), "num-ports", 1, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->ohci), &error_abort); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->ohci), 0, NPCM7XX_OHCI_BA); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci), 0, + npcm7xx_irq(s, NPCM7XX_OHCI_IRQ)); + + /* + * Flash Interface Unit (FIU). Can fail if incorrect number of chip selects + * specified, but this is a programming error. + */ + QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu)); + for (i = 0; i < ARRAY_SIZE(s->fiu); i++) { + SysBusDevice *sbd = SYS_BUS_DEVICE(&s->fiu[i]); + int j; + + object_property_set_int(OBJECT(sbd), "cs-count", + npcm7xx_fiu[i].cs_count, &error_abort); + sysbus_realize(sbd, &error_abort); + + sysbus_mmio_map(sbd, 0, npcm7xx_fiu[i].regs_addr); + for (j = 0; j < npcm7xx_fiu[i].cs_count; j++) { + sysbus_mmio_map(sbd, j + 1, npcm7xx_fiu[i].flash_addr[j]); + } + } + + /* RAM2 (SRAM) */ + memory_region_init_ram(&s->sram, OBJECT(dev), "ram2", + NPCM7XX_RAM2_SZ, &error_abort); + memory_region_add_subregion(get_system_memory(), NPCM7XX_RAM2_BA, &s->sram); + + /* RAM3 (SRAM) */ + memory_region_init_ram(&s->ram3, OBJECT(dev), "ram3", + NPCM7XX_RAM3_SZ, &error_abort); + memory_region_add_subregion(get_system_memory(), NPCM7XX_RAM3_BA, &s->ram3); + + /* Internal ROM */ + memory_region_init_rom(&s->irom, OBJECT(dev), "irom", NPCM7XX_ROM_SZ, + &error_abort); + memory_region_add_subregion(get_system_memory(), NPCM7XX_ROM_BA, &s->irom); + + create_unimplemented_device("npcm7xx.shm", 0xc0001000, 4 * KiB); + create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB); + create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB); + create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * KiB); + create_unimplemented_device("npcm7xx.adc", 0xf000c000, 4 * KiB); + create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * KiB); + create_unimplemented_device("npcm7xx.gpio[0]", 0xf0010000, 4 * KiB); + create_unimplemented_device("npcm7xx.gpio[1]", 0xf0011000, 4 * KiB); + create_unimplemented_device("npcm7xx.gpio[2]", 0xf0012000, 4 * KiB); + create_unimplemented_device("npcm7xx.gpio[3]", 0xf0013000, 4 * KiB); + create_unimplemented_device("npcm7xx.gpio[4]", 0xf0014000, 4 * KiB); + create_unimplemented_device("npcm7xx.gpio[5]", 0xf0015000, 4 * KiB); + create_unimplemented_device("npcm7xx.gpio[6]", 0xf0016000, 4 * KiB); + create_unimplemented_device("npcm7xx.gpio[7]", 0xf0017000, 4 * KiB); + create_unimplemented_device("npcm7xx.smbus[0]", 0xf0080000, 4 * KiB); + create_unimplemented_device("npcm7xx.smbus[1]", 0xf0081000, 4 * KiB); + create_unimplemented_device("npcm7xx.smbus[2]", 0xf0082000, 4 * KiB); + create_unimplemented_device("npcm7xx.smbus[3]", 0xf0083000, 4 * KiB); + create_unimplemented_device("npcm7xx.smbus[4]", 0xf0084000, 4 * KiB); + create_unimplemented_device("npcm7xx.smbus[5]", 0xf0085000, 4 * KiB); + create_unimplemented_device("npcm7xx.smbus[6]", 0xf0086000, 4 * KiB); + create_unimplemented_device("npcm7xx.smbus[7]", 0xf0087000, 4 * KiB); + create_unimplemented_device("npcm7xx.smbus[8]", 0xf0088000, 4 * KiB); + create_unimplemented_device("npcm7xx.smbus[9]", 0xf0089000, 4 * KiB); + create_unimplemented_device("npcm7xx.smbus[10]", 0xf008a000, 4 * KiB); + create_unimplemented_device("npcm7xx.smbus[11]", 0xf008b000, 4 * KiB); + create_unimplemented_device("npcm7xx.smbus[12]", 0xf008c000, 4 * KiB); + create_unimplemented_device("npcm7xx.smbus[13]", 0xf008d000, 4 * KiB); + create_unimplemented_device("npcm7xx.smbus[14]", 0xf008e000, 4 * KiB); + create_unimplemented_device("npcm7xx.smbus[15]", 0xf008f000, 4 * KiB); + create_unimplemented_device("npcm7xx.espi", 0xf009f000, 4 * KiB); + create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB); + create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB); + create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB); + create_unimplemented_device("npcm7xx.pwm[0]", 0xf0103000, 4 * KiB); + create_unimplemented_device("npcm7xx.pwm[1]", 0xf0104000, 4 * KiB); + create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB); + create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB); + create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB); + create_unimplemented_device("npcm7xx.mft[3]", 0xf0183000, 4 * KiB); + create_unimplemented_device("npcm7xx.mft[4]", 0xf0184000, 4 * KiB); + create_unimplemented_device("npcm7xx.mft[5]", 0xf0185000, 4 * KiB); + create_unimplemented_device("npcm7xx.mft[6]", 0xf0186000, 4 * KiB); + create_unimplemented_device("npcm7xx.mft[7]", 0xf0187000, 4 * KiB); + create_unimplemented_device("npcm7xx.pspi1", 0xf0200000, 4 * KiB); + create_unimplemented_device("npcm7xx.pspi2", 0xf0201000, 4 * KiB); + create_unimplemented_device("npcm7xx.ahbpci", 0xf0400000, 1 * MiB); + create_unimplemented_device("npcm7xx.mcphy", 0xf05f0000, 64 * KiB); + create_unimplemented_device("npcm7xx.gmac1", 0xf0802000, 8 * KiB); + create_unimplemented_device("npcm7xx.gmac2", 0xf0804000, 8 * KiB); + create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB); + create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB); + create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB); + create_unimplemented_device("npcm7xx.emc1", 0xf0825000, 4 * KiB); + create_unimplemented_device("npcm7xx.emc2", 0xf0826000, 4 * KiB); + create_unimplemented_device("npcm7xx.usbd[0]", 0xf0830000, 4 * KiB); + create_unimplemented_device("npcm7xx.usbd[1]", 0xf0831000, 4 * KiB); + create_unimplemented_device("npcm7xx.usbd[2]", 0xf0832000, 4 * KiB); + create_unimplemented_device("npcm7xx.usbd[3]", 0xf0833000, 4 * KiB); + create_unimplemented_device("npcm7xx.usbd[4]", 0xf0834000, 4 * KiB); + create_unimplemented_device("npcm7xx.usbd[5]", 0xf0835000, 4 * KiB); + create_unimplemented_device("npcm7xx.usbd[6]", 0xf0836000, 4 * KiB); + create_unimplemented_device("npcm7xx.usbd[7]", 0xf0837000, 4 * KiB); + create_unimplemented_device("npcm7xx.usbd[8]", 0xf0838000, 4 * KiB); + create_unimplemented_device("npcm7xx.usbd[9]", 0xf0839000, 4 * KiB); + create_unimplemented_device("npcm7xx.sd", 0xf0840000, 8 * KiB); + create_unimplemented_device("npcm7xx.mmc", 0xf0842000, 8 * KiB); + create_unimplemented_device("npcm7xx.pcimbx", 0xf0848000, 512 * KiB); + create_unimplemented_device("npcm7xx.aes", 0xf0858000, 4 * KiB); + create_unimplemented_device("npcm7xx.des", 0xf0859000, 4 * KiB); + create_unimplemented_device("npcm7xx.sha", 0xf085a000, 4 * KiB); + create_unimplemented_device("npcm7xx.secacc", 0xf085b000, 4 * KiB); + create_unimplemented_device("npcm7xx.spixcs0", 0xf8000000, 16 * MiB); + create_unimplemented_device("npcm7xx.spixcs1", 0xf9000000, 16 * MiB); + create_unimplemented_device("npcm7xx.spix", 0xfb001000, 4 * KiB); +} + +static Property npcm7xx_properties[] = { + DEFINE_PROP_LINK("dram-mr", NPCM7xxState, dram, TYPE_MEMORY_REGION, + MemoryRegion *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void npcm7xx_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = npcm7xx_realize; + dc->user_creatable = false; + device_class_set_props(dc, npcm7xx_properties); +} + +static void npcm730_class_init(ObjectClass *oc, void *data) +{ + NPCM7xxClass *nc = NPCM7XX_CLASS(oc); + + /* NPCM730 is optimized for data center use, so no graphics, etc. */ + nc->disabled_modules = 0x00300395; + nc->num_cpus = 2; +} + +static void npcm750_class_init(ObjectClass *oc, void *data) +{ + NPCM7xxClass *nc = NPCM7XX_CLASS(oc); + + /* NPCM750 has 2 cores and a full set of peripherals */ + nc->disabled_modules = 0x00000000; + nc->num_cpus = 2; +} + +static const TypeInfo npcm7xx_soc_types[] = { + { + .name = TYPE_NPCM7XX, + .parent = TYPE_DEVICE, + .instance_size = sizeof(NPCM7xxState), + .instance_init = npcm7xx_init, + .class_size = sizeof(NPCM7xxClass), + .class_init = npcm7xx_class_init, + .abstract = true, + }, { + .name = TYPE_NPCM730, + .parent = TYPE_NPCM7XX, + .class_init = npcm730_class_init, + }, { + .name = TYPE_NPCM750, + .parent = TYPE_NPCM7XX, + .class_init = npcm750_class_init, + }, +}; + +DEFINE_TYPES(npcm7xx_soc_types); diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c new file mode 100644 index 0000000000000000000000000000000000000000..79e2e2744cac6f5fa31e5f45cf7afa9e29ae9df0 --- /dev/null +++ b/hw/arm/npcm7xx_boards.c @@ -0,0 +1,197 @@ +/* + * Machine definitions for boards featuring an NPCM7xx SoC. + * + * Copyright 2020 Google LLC + * + * 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. + */ + +#include "qemu/osdep.h" + +#include "exec/address-spaces.h" +#include "hw/arm/npcm7xx.h" +#include "hw/core/cpu.h" +#include "hw/loader.h" +#include "hw/qdev-properties.h" +#include "qapi/error.h" +#include "qemu-common.h" +#include "qemu/units.h" +#include "sysemu/sysemu.h" + +#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7 +#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff + +static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin"; + +static void npcm7xx_load_bootrom(MachineState *machine, NPCM7xxState *soc) +{ + g_autofree char *filename = NULL; + int ret; + + if (!bios_name) { + bios_name = npcm7xx_default_bootrom; + } + + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + if (!filename) { + error_report("Could not find ROM image '%s'", bios_name); + if (!machine->kernel_filename) { + /* We can't boot without a bootrom or a kernel image. */ + exit(1); + } + return; + } + ret = load_image_mr(filename, &soc->irom); + if (ret < 0) { + error_report("Failed to load ROM image '%s'", filename); + exit(1); + } +} + +static void npcm7xx_connect_flash(NPCM7xxFIUState *fiu, int cs_no, + const char *flash_type, DriveInfo *dinfo) +{ + DeviceState *flash; + qemu_irq flash_cs; + + flash = qdev_new(flash_type); + if (dinfo) { + qdev_prop_set_drive(flash, "drive", blk_by_legacy_dinfo(dinfo)); + } + qdev_realize_and_unref(flash, BUS(fiu->spi), &error_fatal); + + flash_cs = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0); + qdev_connect_gpio_out_named(DEVICE(fiu), "cs", cs_no, flash_cs); +} + +static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram) +{ + memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram); + + object_property_set_link(OBJECT(soc), "dram-mr", OBJECT(dram), + &error_abort); +} + +static NPCM7xxState *npcm7xx_create_soc(MachineState *machine, + uint32_t hw_straps) +{ + NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine); + MachineClass *mc = &nmc->parent; + Object *obj; + + if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) { + error_report("This board can only be used with %s", + mc->default_cpu_type); + exit(1); + } + + obj = object_new_with_props(nmc->soc_type, OBJECT(machine), "soc", + &error_abort, NULL); + object_property_set_uint(obj, "power-on-straps", hw_straps, &error_abort); + + return NPCM7XX(obj); +} + +static void npcm750_evb_init(MachineState *machine) +{ + NPCM7xxState *soc; + + soc = npcm7xx_create_soc(machine, NPCM750_EVB_POWER_ON_STRAPS); + npcm7xx_connect_dram(soc, machine->ram); + qdev_realize(DEVICE(soc), NULL, &error_fatal); + + npcm7xx_load_bootrom(machine, soc); + npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", drive_get(IF_MTD, 0, 0)); + npcm7xx_load_kernel(machine, soc); +} + +static void quanta_gsj_init(MachineState *machine) +{ + NPCM7xxState *soc; + + soc = npcm7xx_create_soc(machine, QUANTA_GSJ_POWER_ON_STRAPS); + npcm7xx_connect_dram(soc, machine->ram); + qdev_realize(DEVICE(soc), NULL, &error_fatal); + + npcm7xx_load_bootrom(machine, soc); + npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e", + drive_get(IF_MTD, 0, 0)); + npcm7xx_load_kernel(machine, soc); +} + +static void npcm7xx_set_soc_type(NPCM7xxMachineClass *nmc, const char *type) +{ + NPCM7xxClass *sc = NPCM7XX_CLASS(object_class_by_name(type)); + MachineClass *mc = MACHINE_CLASS(nmc); + + nmc->soc_type = type; + mc->default_cpus = mc->min_cpus = mc->max_cpus = sc->num_cpus; +} + +static void npcm7xx_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->no_floppy = 1; + mc->no_cdrom = 1; + mc->no_parallel = 1; + mc->default_ram_id = "ram"; + mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a9"); +} + +/* + * Schematics: + * https://github.com/Nuvoton-Israel/nuvoton-info/blob/master/npcm7xx-poleg/evaluation-board/board_deliverables/NPCM750x_EB_ver.A1.1_COMPLETE.pdf + */ +static void npcm750_evb_machine_class_init(ObjectClass *oc, void *data) +{ + NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc); + MachineClass *mc = MACHINE_CLASS(oc); + + npcm7xx_set_soc_type(nmc, TYPE_NPCM750); + + mc->desc = "Nuvoton NPCM750 Evaluation Board (Cortex A9)"; + mc->init = npcm750_evb_init; + mc->default_ram_size = 512 * MiB; +}; + +static void gsj_machine_class_init(ObjectClass *oc, void *data) +{ + NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc); + MachineClass *mc = MACHINE_CLASS(oc); + + npcm7xx_set_soc_type(nmc, TYPE_NPCM730); + + mc->desc = "Quanta GSJ (Cortex A9)"; + mc->init = quanta_gsj_init; + mc->default_ram_size = 512 * MiB; +}; + +static const TypeInfo npcm7xx_machine_types[] = { + { + .name = TYPE_NPCM7XX_MACHINE, + .parent = TYPE_MACHINE, + .instance_size = sizeof(NPCM7xxMachine), + .class_size = sizeof(NPCM7xxMachineClass), + .class_init = npcm7xx_machine_class_init, + .abstract = true, + }, { + .name = MACHINE_TYPE_NAME("npcm750-evb"), + .parent = TYPE_NPCM7XX_MACHINE, + .class_init = npcm750_evb_machine_class_init, + }, { + .name = MACHINE_TYPE_NAME("quanta-gsj"), + .parent = TYPE_NPCM7XX_MACHINE, + .class_init = gsj_machine_class_init, + }, +}; + +DEFINE_TYPES(npcm7xx_machine_types) diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c index fe126581e4b1d27421c8260ad806f57dbb8f2128..e15981e019f44ef2430e34bb0651081f6933aa06 100644 --- a/hw/arm/nrf51_soc.c +++ b/hw/arm/nrf51_soc.c @@ -32,6 +32,9 @@ #define BASE_TO_IRQ(base) ((base >> 12) & 0x1F) +/* HCLK (the main CPU clock) on this SoC is always 16MHz */ +#define HCLK_FRQ 16000000 + static uint64_t clock_read(void *opaque, hwaddr addr, unsigned int size) { qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n", @@ -65,15 +68,11 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) return; } - object_property_set_link(OBJECT(&s->cpu), OBJECT(&s->container), "memory", - &err); - if (err) { - error_propagate(errp, err); - return; - } - object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err); - if (err) { - error_propagate(errp, err); + system_clock_scale = NANOSECONDS_PER_SECOND / HCLK_FRQ; + + object_property_set_link(OBJECT(&s->cpu), "memory", OBJECT(&s->container), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpu), errp)) { return; } @@ -88,9 +87,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) memory_region_add_subregion(&s->container, NRF51_SRAM_BASE, &s->sram); /* UART */ - object_property_set_bool(OBJECT(&s->uart), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart), errp)) { return; } mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0); @@ -100,9 +97,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) BASE_TO_IRQ(NRF51_UART_BASE))); /* RNG */ - object_property_set_bool(OBJECT(&s->rng), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->rng), errp)) { return; } @@ -113,16 +108,12 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) BASE_TO_IRQ(NRF51_RNG_BASE))); /* UICR, FICR, NVMC, FLASH */ - object_property_set_uint(OBJECT(&s->nvm), s->flash_size, "flash-size", - &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_uint(OBJECT(&s->nvm), "flash-size", + s->flash_size, errp)) { return; } - object_property_set_bool(OBJECT(&s->nvm), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->nvm), errp)) { return; } @@ -136,9 +127,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) memory_region_add_subregion_overlap(&s->container, NRF51_FLASH_BASE, mr, 0); /* GPIO */ - object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) { return; } @@ -150,14 +139,10 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) /* TIMER */ for (i = 0; i < NRF51_NUM_TIMERS; i++) { - object_property_set_uint(OBJECT(&s->timer[i]), i, "id", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_uint(OBJECT(&s->timer[i]), "id", i, errp)) { return; } - object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer[i]), errp)) { return; } @@ -189,27 +174,23 @@ static void nrf51_soc_init(Object *obj) memory_region_init(&s->container, obj, "nrf51-container", UINT64_MAX); - sysbus_init_child_obj(OBJECT(s), "armv6m", OBJECT(&s->cpu), sizeof(s->cpu), - TYPE_ARMV7M); + object_initialize_child(OBJECT(s), "armv6m", &s->cpu, TYPE_ARMV7M); qdev_prop_set_string(DEVICE(&s->cpu), "cpu-type", ARM_CPU_TYPE_NAME("cortex-m0")); qdev_prop_set_uint32(DEVICE(&s->cpu), "num-irq", 32); - sysbus_init_child_obj(obj, "uart", &s->uart, sizeof(s->uart), - TYPE_NRF51_UART); + object_initialize_child(obj, "uart", &s->uart, TYPE_NRF51_UART); object_property_add_alias(obj, "serial0", OBJECT(&s->uart), "chardev"); - sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng), - TYPE_NRF51_RNG); + object_initialize_child(obj, "rng", &s->rng, TYPE_NRF51_RNG); - sysbus_init_child_obj(obj, "nvm", &s->nvm, sizeof(s->nvm), TYPE_NRF51_NVM); + object_initialize_child(obj, "nvm", &s->nvm, TYPE_NRF51_NVM); - sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio), - TYPE_NRF51_GPIO); + object_initialize_child(obj, "gpio", &s->gpio, TYPE_NRF51_GPIO); for (i = 0; i < NRF51_NUM_TIMERS; i++) { - sysbus_init_child_obj(obj, "timer[*]", &s->timer[i], - sizeof(s->timer[i]), TYPE_NRF51_TIMER); + object_initialize_child(obj, "timer[*]", &s->timer[i], + TYPE_NRF51_TIMER); } } diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c index eae800b5c1338949f0d516dcdd9d8ef54bc06866..387eea4d44c5b3e531d147921cdb9702b9f9f754 100644 --- a/hw/arm/nseries.c +++ b/hw/arm/nseries.c @@ -174,7 +174,7 @@ static void n8x0_nand_setup(struct n800_s *s) char *otp_region; DriveInfo *dinfo; - s->nand = qdev_create(NULL, "onenand"); + s->nand = qdev_new("onenand"); qdev_prop_set_uint16(s->nand, "manufacturer_id", NAND_MFR_SAMSUNG); /* Either 0x40 or 0x48 are OK for the device ID */ qdev_prop_set_uint16(s->nand, "device_id", 0x48); @@ -182,10 +182,10 @@ static void n8x0_nand_setup(struct n800_s *s) qdev_prop_set_int32(s->nand, "shift", 1); dinfo = drive_get(IF_MTD, 0, 0); if (dinfo) { - qdev_prop_set_drive(s->nand, "drive", blk_by_legacy_dinfo(dinfo), - &error_fatal); + qdev_prop_set_drive_err(s->nand, "drive", blk_by_legacy_dinfo(dinfo), + &error_fatal); } - qdev_init_nofail(s->nand); + sysbus_realize_and_unref(SYS_BUS_DEVICE(s->nand), &error_fatal); sysbus_connect_irq(SYS_BUS_DEVICE(s->nand), 0, qdev_get_gpio_in(s->mpu->gpio, N8X0_ONENAND_GPIO)); omap_gpmc_attach(s->mpu->gpmc, N8X0_ONENAND_CS, @@ -215,7 +215,7 @@ static void n8x0_i2c_setup(struct n800_s *s) I2CBus *i2c = omap_i2c_bus(s->mpu->i2c[0]); /* Attach a menelaus PM chip */ - dev = i2c_create_slave(i2c, "twl92230", N8X0_MENELAUS_ADDR); + dev = DEVICE(i2c_slave_create_simple(i2c, "twl92230", N8X0_MENELAUS_ADDR)); qdev_connect_gpio_out(dev, 3, qdev_get_gpio_in(s->mpu->ih[0], OMAP_INT_24XX_SYS_NIRQ)); @@ -224,7 +224,7 @@ static void n8x0_i2c_setup(struct n800_s *s) qemu_register_powerdown_notifier(&n8x0_system_powerdown_notifier); /* Attach a TMP105 PM chip (A0 wired to ground) */ - dev = i2c_create_slave(i2c, TYPE_TMP105, N8X0_TMP105_ADDR); + dev = DEVICE(i2c_slave_create_simple(i2c, TYPE_TMP105, N8X0_TMP105_ADDR)); qdev_connect_gpio_out(dev, 0, tmp_irq); } @@ -416,8 +416,8 @@ static void n810_kbd_setup(struct n800_s *s) /* Attach the LM8322 keyboard to the I2C bus, * should happen in n8x0_i2c_setup and s->kbd be initialised here. */ - s->kbd = i2c_create_slave(omap_i2c_bus(s->mpu->i2c[0]), - "lm8323", N810_LM8323_ADDR); + s->kbd = DEVICE(i2c_slave_create_simple(omap_i2c_bus(s->mpu->i2c[0]), + "lm8323", N810_LM8323_ADDR)); qdev_connect_gpio_out(s->kbd, 0, kbd_irq); } @@ -789,22 +789,12 @@ static void n8x0_cbus_setup(struct n800_s *s) cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1)); } -static void n8x0_uart_setup(struct n800_s *s) -{ - Chardev *radio = qemu_chr_new("bt-dummy-uart", "null", NULL); - /* - * Note: We used to connect N8X0_BT_RESET_GPIO and N8X0_BT_WKUP_GPIO - * here, but this code has been removed with the bluetooth backend. - */ - omap_uart_attach(s->mpu->uart[BT_UART], radio); -} - static void n8x0_usb_setup(struct n800_s *s) { SysBusDevice *dev; - s->usb = qdev_create(NULL, "tusb6010"); + s->usb = qdev_new("tusb6010"); dev = SYS_BUS_DEVICE(s->usb); - qdev_init_nofail(s->usb); + sysbus_realize_and_unref(dev, &error_fatal); sysbus_connect_irq(dev, 0, qdev_get_gpio_in(s->mpu->gpio, N8X0_TUSB_INT_GPIO)); /* Using the NOR interface */ @@ -1318,6 +1308,7 @@ static void n8x0_init(MachineState *machine, g_free(sz); exit(EXIT_FAILURE); } + binfo->ram_size = machine->ram_size; memory_region_add_subregion(get_system_memory(), OMAP2_Q2_BASE, machine->ram); @@ -1361,7 +1352,6 @@ static void n8x0_init(MachineState *machine, n8x0_spi_setup(s); n8x0_dss_setup(s); n8x0_cbus_setup(s); - n8x0_uart_setup(s); if (machine_usb(machine)) { n8x0_usb_setup(s); } @@ -1379,7 +1369,8 @@ static void n8x0_init(MachineState *machine, /* No, wait, better start at the ROM. */ s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000; - /* This is intended for loading the `secondary.bin' program from + /* + * This is intended for loading the `secondary.bin' program from * Nokia images (the NOLO bootloader). The entry point seems * to be at OMAP2_Q2_BASE + 0x400000. * @@ -1387,9 +1378,15 @@ static void n8x0_init(MachineState *machine, * for them the entry point needs to be set to OMAP2_SRAM_BASE. * * The code above is for loading the `zImage' file from Nokia - * images. */ - load_image_targphys(option_rom[0].name, OMAP2_Q2_BASE + 0x400000, - machine->ram_size - 0x400000); + * images. + */ + if (load_image_targphys(option_rom[0].name, + OMAP2_Q2_BASE + 0x400000, + machine->ram_size - 0x400000) < 0) { + error_report("Failed to load secondary bootloader %s", + option_rom[0].name); + exit(EXIT_FAILURE); + } n800_setup_nolo_tags(nolo_tags); cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000); diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c index 761cc17ea95f6bfd9e982d6d5feb9b992ba226c0..02c0f66431b98747813c9f5591b893d13f44fc00 100644 --- a/hw/arm/omap1.c +++ b/hw/arm/omap1.c @@ -1774,7 +1774,6 @@ static uint64_t omap_clkdsp_read(void *opaque, hwaddr addr, return s->clkm.dsp_rstct2; case 0x18: /* DSP_SYSST */ - cpu = CPU(s->cpu); return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start | (cpu->halted << 6); /* Quite useless... */ } @@ -3887,21 +3886,21 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *dram, omap_clkm_init(system_memory, 0xfffece00, 0xe1008000, s); - s->ih[0] = qdev_create(NULL, "omap-intc"); + s->ih[0] = qdev_new("omap-intc"); qdev_prop_set_uint32(s->ih[0], "size", 0x100); omap_intc_set_iclk(OMAP_INTC(s->ih[0]), omap_findclk(s, "arminth_ck")); - qdev_init_nofail(s->ih[0]); busdev = SYS_BUS_DEVICE(s->ih[0]); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ)); sysbus_connect_irq(busdev, 1, qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ)); sysbus_mmio_map(busdev, 0, 0xfffecb00); - s->ih[1] = qdev_create(NULL, "omap-intc"); + s->ih[1] = qdev_new("omap-intc"); qdev_prop_set_uint32(s->ih[1], "size", 0x800); omap_intc_set_iclk(OMAP_INTC(s->ih[1]), omap_findclk(s, "arminth_ck")); - qdev_init_nofail(s->ih[1]); busdev = SYS_BUS_DEVICE(s->ih[1]); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[0], OMAP_INT_15XX_IH2_IRQ)); /* The second interrupt controller's FIQ output is not wired up */ @@ -4010,10 +4009,10 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *dram, qdev_get_gpio_in(s->ih[1], OMAP_INT_MPUIO), s->wakeup, omap_findclk(s, "clk32-kHz")); - s->gpio = qdev_create(NULL, "omap-gpio"); + s->gpio = qdev_new("omap-gpio"); qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model); omap_gpio_set_clk(OMAP1_GPIO(s->gpio), omap_findclk(s, "arm_gpio_ck")); - qdev_init_nofail(s->gpio); + sysbus_realize_and_unref(SYS_BUS_DEVICE(s->gpio), &error_fatal); sysbus_connect_irq(SYS_BUS_DEVICE(s->gpio), 0, qdev_get_gpio_in(s->ih[0], OMAP_INT_GPIO_BANK1)); sysbus_mmio_map(SYS_BUS_DEVICE(s->gpio), 0, 0xfffce000); @@ -4028,11 +4027,11 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *dram, s->pwt = omap_pwt_init(system_memory, 0xfffb6000, omap_findclk(s, "armxor_ck")); - s->i2c[0] = qdev_create(NULL, "omap_i2c"); + s->i2c[0] = qdev_new("omap_i2c"); qdev_prop_set_uint8(s->i2c[0], "revision", 0x11); omap_i2c_set_fclk(OMAP_I2C(s->i2c[0]), omap_findclk(s, "mpuper_ck")); - qdev_init_nofail(s->i2c[0]); busdev = SYS_BUS_DEVICE(s->i2c[0]); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C)); sysbus_connect_irq(busdev, 1, s->drq[OMAP_DMA_I2C_TX]); sysbus_connect_irq(busdev, 2, s->drq[OMAP_DMA_I2C_RX]); diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c index e1c11de5ce0898c6780392aca33fa0732eaf443e..16d388fc79d5e8a680fd86a08a78bf6ec7ecd09c 100644 --- a/hw/arm/omap2.c +++ b/hw/arm/omap2.c @@ -2306,12 +2306,12 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sdram, s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54); /* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */ - s->ih[0] = qdev_create(NULL, "omap2-intc"); + s->ih[0] = qdev_new("omap2-intc"); qdev_prop_set_uint8(s->ih[0], "revision", 0x21); omap_intc_set_fclk(OMAP_INTC(s->ih[0]), omap_findclk(s, "mpu_intc_fclk")); omap_intc_set_iclk(OMAP_INTC(s->ih[0]), omap_findclk(s, "mpu_intc_iclk")); - qdev_init_nofail(s->ih[0]); busdev = SYS_BUS_DEVICE(s->ih[0]); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ)); sysbus_connect_irq(busdev, 1, @@ -2423,31 +2423,31 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sdram, omap_findclk(s, "clk32-kHz"), omap_findclk(s, "core_l4_iclk")); - s->i2c[0] = qdev_create(NULL, "omap_i2c"); + s->i2c[0] = qdev_new("omap_i2c"); qdev_prop_set_uint8(s->i2c[0], "revision", 0x34); omap_i2c_set_iclk(OMAP_I2C(s->i2c[0]), omap_findclk(s, "i2c1.iclk")); omap_i2c_set_fclk(OMAP_I2C(s->i2c[0]), omap_findclk(s, "i2c1.fclk")); - qdev_init_nofail(s->i2c[0]); busdev = SYS_BUS_DEVICE(s->i2c[0]); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C1_IRQ)); sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C1_TX]); sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C1_RX]); sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 5), 0)); - s->i2c[1] = qdev_create(NULL, "omap_i2c"); + s->i2c[1] = qdev_new("omap_i2c"); qdev_prop_set_uint8(s->i2c[1], "revision", 0x34); omap_i2c_set_iclk(OMAP_I2C(s->i2c[1]), omap_findclk(s, "i2c2.iclk")); omap_i2c_set_fclk(OMAP_I2C(s->i2c[1]), omap_findclk(s, "i2c2.fclk")); - qdev_init_nofail(s->i2c[1]); busdev = SYS_BUS_DEVICE(s->i2c[1]); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C2_IRQ)); sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C2_TX]); sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C2_RX]); sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 6), 0)); - s->gpio = qdev_create(NULL, "omap2-gpio"); + s->gpio = qdev_new("omap2-gpio"); qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model); omap2_gpio_set_iclk(OMAP2_GPIO(s->gpio), omap_findclk(s, "gpio_iclk")); omap2_gpio_set_fclk(OMAP2_GPIO(s->gpio), 0, omap_findclk(s, "gpio1_dbclk")); @@ -2458,8 +2458,8 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sdram, omap2_gpio_set_fclk(OMAP2_GPIO(s->gpio), 4, omap_findclk(s, "gpio5_dbclk")); } - qdev_init_nofail(s->gpio); busdev = SYS_BUS_DEVICE(s->gpio); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK1)); sysbus_connect_irq(busdev, 3, diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c index b291715f27bb5c9acdd9749fb4b0731ff4391aae..17a568a2b45cdfd8527a7ceb976277867adb3f97 100644 --- a/hw/arm/orangepi.c +++ b/hw/arm/orangepi.c @@ -63,9 +63,8 @@ static void orangepi_init(MachineState *machine) object_unref(OBJECT(h3)); /* Setup timer properties */ - object_property_set_int(OBJECT(h3), 32768, "clk0-freq", - &error_abort); - object_property_set_int(OBJECT(h3), 24 * 1000 * 1000, "clk1-freq", + object_property_set_int(OBJECT(h3), "clk0-freq", 32768, &error_abort); + object_property_set_int(OBJECT(h3), "clk1-freq", 24 * 1000 * 1000, &error_abort); /* Setup SID properties. Currently using a default fixed SID identifier. */ @@ -77,16 +76,16 @@ static void orangepi_init(MachineState *machine) } /* Setup EMAC properties */ - object_property_set_int(OBJECT(&h3->emac), 1, "phy-addr", &error_abort); + object_property_set_int(OBJECT(&h3->emac), "phy-addr", 1, &error_abort); /* DRAMC */ - object_property_set_uint(OBJECT(h3), h3->memmap[AW_H3_SDRAM], - "ram-addr", &error_abort); - object_property_set_int(OBJECT(h3), machine->ram_size / MiB, "ram-size", + object_property_set_uint(OBJECT(h3), "ram-addr", h3->memmap[AW_H3_DEV_SDRAM], + &error_abort); + object_property_set_int(OBJECT(h3), "ram-size", machine->ram_size / MiB, &error_abort); /* Mark H3 object realized */ - object_property_set_bool(OBJECT(h3), true, "realized", &error_abort); + qdev_realize(DEVICE(h3), NULL, &error_abort); /* Retrieve SD bus */ di = drive_get_next(IF_SD); @@ -94,12 +93,12 @@ static void orangepi_init(MachineState *machine) bus = qdev_get_child_bus(DEVICE(h3), "sd-bus"); /* Plug in SD card */ - carddev = qdev_create(bus, TYPE_SD_CARD); - qdev_prop_set_drive(carddev, "drive", blk, &error_fatal); - object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal); + carddev = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal); + qdev_realize_and_unref(carddev, bus, &error_fatal); /* SDRAM */ - memory_region_add_subregion(get_system_memory(), h3->memmap[AW_H3_SDRAM], + memory_region_add_subregion(get_system_memory(), h3->memmap[AW_H3_DEV_SDRAM], machine->ram); /* Load target kernel or start using BootROM */ @@ -107,7 +106,7 @@ static void orangepi_init(MachineState *machine) /* Use Boot ROM to copy data from SD card to SRAM */ allwinner_h3_bootrom_setup(h3, blk); } - orangepi_binfo.loader_start = h3->memmap[AW_H3_SDRAM]; + orangepi_binfo.loader_start = h3->memmap[AW_H3_DEV_SDRAM]; orangepi_binfo.ram_size = machine->ram_size; arm_load_kernel(ARM_CPU(first_cpu), machine, &orangepi_binfo); } diff --git a/hw/arm/palm.c b/hw/arm/palm.c index 97ca105d297513b784cd88e22e793a1c8789c381..4e3dc5fbbf2e4d7adeb3f45d5cdac212be6a1f8f 100644 --- a/hw/arm/palm.c +++ b/hw/arm/palm.c @@ -32,6 +32,7 @@ #include "exec/address-spaces.h" #include "cpu.h" #include "qemu/cutils.h" +#include "qom/object.h" static uint64_t static_read(void *opaque, hwaddr offset, unsigned size) { @@ -61,21 +62,21 @@ static const MemoryRegionOps static_ops = { /* Palm Tunsgten|E support */ /* Shared GPIOs */ -#define PALMTE_USBDETECT_GPIO 0 -#define PALMTE_USB_OR_DC_GPIO 1 -#define PALMTE_TSC_GPIO 4 -#define PALMTE_PINTDAV_GPIO 6 -#define PALMTE_MMC_WP_GPIO 8 -#define PALMTE_MMC_POWER_GPIO 9 -#define PALMTE_HDQ_GPIO 11 -#define PALMTE_HEADPHONES_GPIO 14 -#define PALMTE_SPEAKER_GPIO 15 +#define PALMTE_USBDETECT_GPIO 0 +#define PALMTE_USB_OR_DC_GPIO 1 +#define PALMTE_TSC_GPIO 4 +#define PALMTE_PINTDAV_GPIO 6 +#define PALMTE_MMC_WP_GPIO 8 +#define PALMTE_MMC_POWER_GPIO 9 +#define PALMTE_HDQ_GPIO 11 +#define PALMTE_HEADPHONES_GPIO 14 +#define PALMTE_SPEAKER_GPIO 15 /* MPU private GPIOs */ -#define PALMTE_DC_GPIO 2 -#define PALMTE_MMC_SWITCH_GPIO 4 -#define PALMTE_MMC1_GPIO 6 -#define PALMTE_MMC2_GPIO 7 -#define PALMTE_MMC3_GPIO 11 +#define PALMTE_DC_GPIO 2 +#define PALMTE_MMC_SWITCH_GPIO 4 +#define PALMTE_MMC1_GPIO 6 +#define PALMTE_MMC2_GPIO 7 +#define PALMTE_MMC3_GPIO 11 static MouseTransformInfo palmte_pointercal = { .x = 320, @@ -100,17 +101,17 @@ static struct { int column; } palmte_keymap[0x80] = { [0 ... 0x7f] = { -1, -1 }, - [0x3b] = { 0, 0 }, /* F1 -> Calendar */ - [0x3c] = { 1, 0 }, /* F2 -> Contacts */ - [0x3d] = { 2, 0 }, /* F3 -> Tasks List */ - [0x3e] = { 3, 0 }, /* F4 -> Note Pad */ - [0x01] = { 4, 0 }, /* Esc -> Power */ - [0x4b] = { 0, 1 }, /* Left */ - [0x50] = { 1, 1 }, /* Down */ - [0x48] = { 2, 1 }, /* Up */ - [0x4d] = { 3, 1 }, /* Right */ - [0x4c] = { 4, 1 }, /* Centre */ - [0x39] = { 4, 1 }, /* Spc -> Centre */ + [0x3b] = { 0, 0 }, /* F1 -> Calendar */ + [0x3c] = { 1, 0 }, /* F2 -> Contacts */ + [0x3d] = { 2, 0 }, /* F3 -> Tasks List */ + [0x3e] = { 3, 0 }, /* F4 -> Note Pad */ + [0x01] = { 4, 0 }, /* Esc -> Power */ + [0x4b] = { 0, 1 }, /* Left */ + [0x50] = { 1, 1 }, /* Down */ + [0x48] = { 2, 1 }, /* Up */ + [0x4d] = { 3, 1 }, /* Right */ + [0x4c] = { 4, 1 }, /* Centre */ + [0x39] = { 4, 1 }, /* Spc -> Centre */ }; static void palmte_button_event(void *opaque, int keycode) @@ -124,6 +125,20 @@ static void palmte_button_event(void *opaque, int keycode) !(keycode & 0x80)); } +/* + * Encapsulation of some GPIO line behaviour for the Palm board + * + * QEMU interface: + * + unnamed GPIO inputs 0..6: for the various miscellaneous input lines + */ + +#define TYPE_PALM_MISC_GPIO "palm-misc-gpio" +OBJECT_DECLARE_SIMPLE_TYPE(PalmMiscGPIOState, PALM_MISC_GPIO) + +struct PalmMiscGPIOState { + SysBusDevice parent_obj; +}; + static void palmte_onoff_gpios(void *opaque, int line, int level) { switch (line) { @@ -151,23 +166,44 @@ static void palmte_onoff_gpios(void *opaque, int line, int level) } } +static void palm_misc_gpio_init(Object *obj) +{ + DeviceState *dev = DEVICE(obj); + + qdev_init_gpio_in(dev, palmte_onoff_gpios, 7); +} + +static const TypeInfo palm_misc_gpio_info = { + .name = TYPE_PALM_MISC_GPIO, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(PalmMiscGPIOState), + .instance_init = palm_misc_gpio_init, + /* + * No class init required: device has no internal state so does not + * need to set up reset or vmstate, and has no realize method. + */ +}; + static void palmte_gpio_setup(struct omap_mpu_state_s *cpu) { - qemu_irq *misc_gpio; + DeviceState *misc_gpio; + + misc_gpio = sysbus_create_simple(TYPE_PALM_MISC_GPIO, -1, NULL); omap_mmc_handlers(cpu->mmc, qdev_get_gpio_in(cpu->gpio, PALMTE_MMC_WP_GPIO), qemu_irq_invert(omap_mpuio_in_get(cpu->mpuio) [PALMTE_MMC_SWITCH_GPIO])); - misc_gpio = qemu_allocate_irqs(palmte_onoff_gpios, cpu, 7); - qdev_connect_gpio_out(cpu->gpio, PALMTE_MMC_POWER_GPIO, misc_gpio[0]); - qdev_connect_gpio_out(cpu->gpio, PALMTE_SPEAKER_GPIO, misc_gpio[1]); - qdev_connect_gpio_out(cpu->gpio, 11, misc_gpio[2]); - qdev_connect_gpio_out(cpu->gpio, 12, misc_gpio[3]); - qdev_connect_gpio_out(cpu->gpio, 13, misc_gpio[4]); - omap_mpuio_out_set(cpu->mpuio, 1, misc_gpio[5]); - omap_mpuio_out_set(cpu->mpuio, 3, misc_gpio[6]); + qdev_connect_gpio_out(cpu->gpio, PALMTE_MMC_POWER_GPIO, + qdev_get_gpio_in(misc_gpio, 0)); + qdev_connect_gpio_out(cpu->gpio, PALMTE_SPEAKER_GPIO, + qdev_get_gpio_in(misc_gpio, 1)); + qdev_connect_gpio_out(cpu->gpio, 11, qdev_get_gpio_in(misc_gpio, 2)); + qdev_connect_gpio_out(cpu->gpio, 12, qdev_get_gpio_in(misc_gpio, 3)); + qdev_connect_gpio_out(cpu->gpio, 13, qdev_get_gpio_in(misc_gpio, 4)); + omap_mpuio_out_set(cpu->mpuio, 1, qdev_get_gpio_in(misc_gpio, 5)); + omap_mpuio_out_set(cpu->mpuio, 3, qdev_get_gpio_in(misc_gpio, 6)); /* Reset some inputs to initial state. */ qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USBDETECT_GPIO)); @@ -276,3 +312,10 @@ static void palmte_machine_init(MachineClass *mc) } DEFINE_MACHINE("cheetah", palmte_machine_init) + +static void palm_register_types(void) +{ + type_register_static(&palm_misc_gpio_info); +} + +type_init(palm_register_types) diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index 336c9bad4aec4feb1077cffd7686cc1036c27444..1a98f3bd5cdc589537d0c48ee1eadaca13cb9a24 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -22,10 +22,13 @@ #include "hw/irq.h" #include "hw/qdev-properties.h" #include "hw/ssi/ssi.h" +#include "hw/sd/sd.h" #include "chardev/char-fe.h" #include "sysemu/blockdev.h" #include "sysemu/qtest.h" #include "qemu/cutils.h" +#include "qemu/log.h" +#include "qom/object.h" static struct { hwaddr io_base; @@ -112,7 +115,9 @@ static uint64_t pxa2xx_pm_read(void *opaque, hwaddr addr, return s->pm_regs[addr >> 2]; default: fail: - printf("%s: Bad register " REG_FMT "\n", __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad read offset 0x%"HWADDR_PRIx"\n", + __func__, addr); break; } return 0; @@ -143,8 +148,9 @@ static void pxa2xx_pm_write(void *opaque, hwaddr addr, s->pm_regs[addr >> 2] = value; break; } - - printf("%s: Bad register " REG_FMT "\n", __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad write offset 0x%"HWADDR_PRIx"\n", + __func__, addr); break; } } @@ -185,7 +191,9 @@ static uint64_t pxa2xx_cm_read(void *opaque, hwaddr addr, return s->cm_regs[CCCR >> 2] | (3 << 28); default: - printf("%s: Bad register " REG_FMT "\n", __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad read offset 0x%"HWADDR_PRIx"\n", + __func__, addr); break; } return 0; @@ -210,7 +218,9 @@ static void pxa2xx_cm_write(void *opaque, hwaddr addr, break; default: - printf("%s: Bad register " REG_FMT "\n", __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad write offset 0x%"HWADDR_PRIx"\n", + __func__, addr); break; } } @@ -415,7 +425,9 @@ static uint64_t pxa2xx_mm_read(void *opaque, hwaddr addr, return s->mm_regs[addr >> 2]; /* fall through */ default: - printf("%s: Bad register " REG_FMT "\n", __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad read offset 0x%"HWADDR_PRIx"\n", + __func__, addr); break; } return 0; @@ -432,9 +444,11 @@ static void pxa2xx_mm_write(void *opaque, hwaddr addr, s->mm_regs[addr >> 2] = value; break; } - + /* fallthrough */ default: - printf("%s: Bad register " REG_FMT "\n", __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad write offset 0x%"HWADDR_PRIx"\n", + __func__, addr); break; } } @@ -456,11 +470,10 @@ static const VMStateDescription vmstate_pxa2xx_mm = { }; #define TYPE_PXA2XX_SSP "pxa2xx-ssp" -#define PXA2XX_SSP(obj) \ - OBJECT_CHECK(PXA2xxSSPState, (obj), TYPE_PXA2XX_SSP) +OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxSSPState, PXA2XX_SSP) /* Synchronous Serial Ports */ -typedef struct { +struct PXA2xxSSPState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -482,7 +495,7 @@ typedef struct { uint32_t rx_fifo[16]; uint32_t rx_level; uint32_t rx_start; -} PXA2xxSSPState; +}; static bool pxa2xx_ssp_vmstate_validate(void *opaque, int version_id) { @@ -641,7 +654,9 @@ static uint64_t pxa2xx_ssp_read(void *opaque, hwaddr addr, case SSACD: return s->ssacd; default: - printf("%s: Bad register " REG_FMT "\n", __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad read offset 0x%"HWADDR_PRIx"\n", + __func__, addr); break; } return 0; @@ -660,7 +675,7 @@ static void pxa2xx_ssp_write(void *opaque, hwaddr addr, if (value & SSCR0_MOD) printf("%s: Attempt to use network mode\n", __func__); if (s->enable && SSCR0_DSS(value) < 4) - printf("%s: Wrong data size: %i bits\n", __func__, + printf("%s: Wrong data size: %u bits\n", __func__, SSCR0_DSS(value)); if (!(value & SSCR0_SSE)) { s->sssr = 0; @@ -733,7 +748,9 @@ static void pxa2xx_ssp_write(void *opaque, hwaddr addr, break; default: - printf("%s: Bad register " REG_FMT "\n", __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad write offset 0x%"HWADDR_PRIx"\n", + __func__, addr); break; } } @@ -792,10 +809,9 @@ static void pxa2xx_ssp_init(Object *obj) #define PIAR 0x38 /* RTC Periodic Interrupt Alarm register */ #define TYPE_PXA2XX_RTC "pxa2xx_rtc" -#define PXA2XX_RTC(obj) \ - OBJECT_CHECK(PXA2xxRTCState, (obj), TYPE_PXA2XX_RTC) +OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxRTCState, PXA2XX_RTC) -typedef struct { +struct PXA2xxRTCState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -826,7 +842,7 @@ typedef struct { QEMUTimer *rtc_swal2; QEMUTimer *rtc_pi; qemu_irq rtc_irq; -} PXA2xxRTCState; +}; static inline void pxa2xx_rtc_int_update(PXA2xxRTCState *s) { @@ -995,7 +1011,9 @@ static uint64_t pxa2xx_rtc_read(void *opaque, hwaddr addr, else return s->last_swcr; default: - printf("%s: Bad register " REG_FMT "\n", __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad read offset 0x%"HWADDR_PRIx"\n", + __func__, addr); break; } return 0; @@ -1101,7 +1119,9 @@ static void pxa2xx_rtc_write(void *opaque, hwaddr addr, break; default: - printf("%s: Bad register " REG_FMT "\n", __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad write offset 0x%"HWADDR_PRIx"\n", + __func__, addr); } } @@ -1221,18 +1241,13 @@ static const TypeInfo pxa2xx_rtc_sysbus_info = { /* I2C Interface */ #define TYPE_PXA2XX_I2C_SLAVE "pxa2xx-i2c-slave" -#define PXA2XX_I2C_SLAVE(obj) \ - OBJECT_CHECK(PXA2xxI2CSlaveState, (obj), TYPE_PXA2XX_I2C_SLAVE) +OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxI2CSlaveState, PXA2XX_I2C_SLAVE) -typedef struct PXA2xxI2CSlaveState { +struct PXA2xxI2CSlaveState { I2CSlave parent_obj; PXA2xxI2CState *host; -} PXA2xxI2CSlaveState; - -#define TYPE_PXA2XX_I2C "pxa2xx_i2c" -#define PXA2XX_I2C(obj) \ - OBJECT_CHECK(PXA2xxI2CState, (obj), TYPE_PXA2XX_I2C) +}; struct PXA2xxI2CState { /*< private >*/ @@ -1354,7 +1369,9 @@ static uint64_t pxa2xx_i2c_read(void *opaque, hwaddr addr, s->ibmr = 0; return s->ibmr; default: - printf("%s: Bad register " REG_FMT "\n", __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad read offset 0x%"HWADDR_PRIx"\n", + __func__, addr); break; } return 0; @@ -1427,7 +1444,9 @@ static void pxa2xx_i2c_write(void *opaque, hwaddr addr, break; default: - printf("%s: Bad register " REG_FMT "\n", __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad write offset 0x%"HWADDR_PRIx"\n", + __func__, addr); } } @@ -1486,20 +1505,21 @@ PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base, PXA2xxI2CState *s; I2CBus *i2cbus; - dev = qdev_create(NULL, TYPE_PXA2XX_I2C); + dev = qdev_new(TYPE_PXA2XX_I2C); qdev_prop_set_uint32(dev, "size", region_size + 1); qdev_prop_set_uint32(dev, "offset", base & region_size); - qdev_init_nofail(dev); i2c_dev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(i2c_dev, &error_fatal); sysbus_mmio_map(i2c_dev, 0, base & ~region_size); sysbus_connect_irq(i2c_dev, 0, irq); s = PXA2XX_I2C(i2c_dev); /* FIXME: Should the slave device really be on a separate bus? */ i2cbus = i2c_init_bus(dev, "dummy"); - dev = i2c_create_slave(i2cbus, TYPE_PXA2XX_I2C_SLAVE, 0); - s->slave = PXA2XX_I2C_SLAVE(dev); + s->slave = PXA2XX_I2C_SLAVE(i2c_slave_create_simple(i2cbus, + TYPE_PXA2XX_I2C_SLAVE, + 0)); s->slave->host = s; return s; @@ -1628,7 +1648,9 @@ static uint64_t pxa2xx_i2s_read(void *opaque, hwaddr addr, } return 0; default: - printf("%s: Bad register " REG_FMT "\n", __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad read offset 0x%"HWADDR_PRIx"\n", + __func__, addr); break; } return 0; @@ -1685,7 +1707,9 @@ static void pxa2xx_i2s_write(void *opaque, hwaddr addr, } break; default: - printf("%s: Bad register " REG_FMT "\n", __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad write offset 0x%"HWADDR_PRIx"\n", + __func__, addr); } } @@ -1757,9 +1781,6 @@ static PXA2xxI2SState *pxa2xx_i2s_init(MemoryRegion *sysmem, } /* PXA Fast Infra-red Communications Port */ -#define TYPE_PXA2XX_FIR "pxa2xx-fir" -#define PXA2XX_FIR(obj) OBJECT_CHECK(PXA2xxFIrState, (obj), TYPE_PXA2XX_FIR) - struct PXA2xxFIrState { /*< private >*/ SysBusDevice parent_obj; @@ -1870,7 +1891,9 @@ static uint64_t pxa2xx_fir_read(void *opaque, hwaddr addr, case ICFOR: return s->rx_len; default: - printf("%s: Bad register " REG_FMT "\n", __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad read offset 0x%"HWADDR_PRIx"\n", + __func__, addr); break; } return 0; @@ -1922,7 +1945,9 @@ static void pxa2xx_fir_write(void *opaque, hwaddr addr, case ICFOR: break; default: - printf("%s: Bad register " REG_FMT "\n", __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad write offset 0x%"HWADDR_PRIx"\n", + __func__, addr); } } @@ -2041,10 +2066,10 @@ static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem, DeviceState *dev; SysBusDevice *sbd; - dev = qdev_create(NULL, TYPE_PXA2XX_FIR); + dev = qdev_new(TYPE_PXA2XX_FIR); qdev_prop_set_chr(dev, "chardev", chr); - qdev_init_nofail(dev); sbd = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sbd, &error_fatal); sysbus_mmio_map(sbd, 0, base); sysbus_connect_irq(sbd, 0, irq); sysbus_connect_irq(sbd, 1, rx_dma); @@ -2103,15 +2128,24 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space, s->gpio = pxa2xx_gpio_init(0x40e00000, s->cpu, s->pic, 121); - dinfo = drive_get(IF_SD, 0, 0); - if (!dinfo && !qtest_enabled()) { - warn_report("missing SecureDigital device"); - } s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, - dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC), qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI), qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI)); + dinfo = drive_get(IF_SD, 0, 0); + if (dinfo) { + DeviceState *carddev; + + /* Create and plug in the sd card */ + carddev = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(carddev, "drive", + blk_by_legacy_dinfo(dinfo), &error_fatal); + qdev_realize_and_unref(carddev, qdev_get_child_bus(DEVICE(s->mmc), + "sd-bus"), + &error_fatal); + } else if (!qtest_enabled()) { + warn_report("missing SecureDigital device"); + } for (i = 0; pxa270_serial[i].io_base; i++) { if (serial_hd(i)) { @@ -2227,15 +2261,24 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size) s->gpio = pxa2xx_gpio_init(0x40e00000, s->cpu, s->pic, 85); - dinfo = drive_get(IF_SD, 0, 0); - if (!dinfo && !qtest_enabled()) { - warn_report("missing SecureDigital device"); - } s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, - dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC), qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI), qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI)); + dinfo = drive_get(IF_SD, 0, 0); + if (dinfo) { + DeviceState *carddev; + + /* Create and plug in the sd card */ + carddev = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(carddev, "drive", + blk_by_legacy_dinfo(dinfo), &error_fatal); + qdev_realize_and_unref(carddev, qdev_get_child_bus(DEVICE(s->mmc), + "sd-bus"), + &error_fatal); + } else if (!qtest_enabled()) { + warn_report("missing SecureDigital device"); + } for (i = 0; pxa255_serial[i].io_base; i++) { if (serial_hd(i)) { diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c index a01db54a518d5e391eb501ad4b29ca40bcd60861..e7c3d99224a653948de24b8355f9209e28499e6a 100644 --- a/hw/arm/pxa2xx_gpio.c +++ b/hw/arm/pxa2xx_gpio.c @@ -14,16 +14,16 @@ #include "hw/sysbus.h" #include "migration/vmstate.h" #include "hw/arm/pxa.h" +#include "qapi/error.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" #define PXA2XX_GPIO_BANKS 4 #define TYPE_PXA2XX_GPIO "pxa2xx-gpio" -#define PXA2XX_GPIO(obj) \ - OBJECT_CHECK(PXA2xxGPIOInfo, (obj), TYPE_PXA2XX_GPIO) +OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxGPIOInfo, PXA2XX_GPIO) -typedef struct PXA2xxGPIOInfo PXA2xxGPIOInfo; struct PXA2xxGPIOInfo { /*< private >*/ SysBusDevice parent_obj; @@ -269,10 +269,10 @@ DeviceState *pxa2xx_gpio_init(hwaddr base, CPUState *cs = CPU(cpu); DeviceState *dev; - dev = qdev_create(NULL, TYPE_PXA2XX_GPIO); + dev = qdev_new(TYPE_PXA2XX_GPIO); qdev_prop_set_int32(dev, "lines", lines); qdev_prop_set_int32(dev, "ncpu", cs->cpu_index); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c index 203d4d28aff26ea1a8efa9b3202585c2efa5bea4..cf6cb2a373ac972a02d67f83ba34ab2eed4cde87 100644 --- a/hw/arm/pxa2xx_pic.c +++ b/hw/arm/pxa2xx_pic.c @@ -9,11 +9,14 @@ */ #include "qemu/osdep.h" +#include "qapi/error.h" #include "qemu/module.h" +#include "qemu/log.h" #include "cpu.h" #include "hw/arm/pxa.h" #include "hw/sysbus.h" #include "migration/vmstate.h" +#include "qom/object.h" #define ICIP 0x00 /* Interrupt Controller IRQ Pending register */ #define ICMR 0x04 /* Interrupt Controller Mask register */ @@ -35,10 +38,9 @@ #define PXA2XX_PIC_SRCS 40 #define TYPE_PXA2XX_PIC "pxa2xx_pic" -#define PXA2XX_PIC(obj) \ - OBJECT_CHECK(PXA2xxPICState, (obj), TYPE_PXA2XX_PIC) +OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxPICState, PXA2XX_PIC) -typedef struct { +struct PXA2xxPICState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -50,7 +52,7 @@ typedef struct { uint32_t is_fiq[2]; uint32_t int_idle; uint32_t priority[PXA2XX_PIC_SRCS]; -} PXA2xxPICState; +}; static void pxa2xx_pic_update(void *opaque) { @@ -165,7 +167,9 @@ static uint64_t pxa2xx_pic_mem_read(void *opaque, hwaddr offset, case ICHP: /* Highest Priority register */ return pxa2xx_pic_highest(s); default: - printf("%s: Bad register offset " REG_FMT "\n", __func__, offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pxa2xx_pic_mem_read: bad register offset 0x%" HWADDR_PRIx + "\n", offset); return 0; } } @@ -198,7 +202,9 @@ static void pxa2xx_pic_mem_write(void *opaque, hwaddr offset, s->priority[32 + ((offset - IPR32) >> 2)] = value & 0x8000003f; break; default: - printf("%s: Bad register offset " REG_FMT "\n", __func__, offset); + qemu_log_mask(LOG_GUEST_ERROR, + "pxa2xx_pic_mem_write: bad register offset 0x%" + HWADDR_PRIx "\n", offset); return; } pxa2xx_pic_update(opaque); @@ -267,7 +273,7 @@ static int pxa2xx_pic_post_load(void *opaque, int version_id) DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu) { - DeviceState *dev = qdev_create(NULL, TYPE_PXA2XX_PIC); + DeviceState *dev = qdev_new(TYPE_PXA2XX_PIC); PXA2xxPICState *s = PXA2XX_PIC(dev); s->cpu = cpu; @@ -279,7 +285,7 @@ DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu) s->is_fiq[0] = 0; s->is_fiq[1] = 0; - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); qdev_init_gpio_in(dev, pxa2xx_pic_set_irq, PXA2XX_PIC_SRCS); diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c index a2efe0b94d51cc252a8686fe0c5adccbfa8a8f54..990509d38521937bc8f6e1828d69cba784cb84b8 100644 --- a/hw/arm/raspi.c +++ b/hw/arm/raspi.c @@ -24,6 +24,7 @@ #include "hw/loader.h" #include "hw/arm/boot.h" #include "sysemu/sysemu.h" +#include "qom/object.h" #define SMPBOOT_ADDR 0x300 /* this should leave enough space for ATAGS */ #define MVBAR_ADDR 0x400 /* secure vectors */ @@ -35,28 +36,27 @@ /* Registered machine type (matches RPi Foundation bootloader and U-Boot) */ #define MACH_TYPE_BCM2708 3138 -typedef struct RaspiMachineState { +struct RaspiMachineState { /*< private >*/ MachineState parent_obj; /*< public >*/ BCM283XState soc; -} RaspiMachineState; + struct arm_boot_info binfo; +}; +typedef struct RaspiMachineState RaspiMachineState; -typedef struct RaspiMachineClass { +struct RaspiMachineClass { /*< private >*/ MachineClass parent_obj; /*< public >*/ uint32_t board_rev; -} RaspiMachineClass; +}; +typedef struct RaspiMachineClass RaspiMachineClass; #define TYPE_RASPI_MACHINE MACHINE_TYPE_NAME("raspi-common") -#define RASPI_MACHINE(obj) \ - OBJECT_CHECK(RaspiMachineState, (obj), TYPE_RASPI_MACHINE) +DECLARE_OBJ_CHECKERS(RaspiMachineState, RaspiMachineClass, + RASPI_MACHINE, TYPE_RASPI_MACHINE) -#define RASPI_MACHINE_CLASS(klass) \ - OBJECT_CLASS_CHECK(RaspiMachineClass, (klass), TYPE_RASPI_MACHINE) -#define RASPI_MACHINE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(RaspiMachineClass, (obj), TYPE_RASPI_MACHINE) /* * Board revision codes: @@ -69,51 +69,45 @@ FIELD(REV_CODE, MANUFACTURER, 16, 4); FIELD(REV_CODE, MEMORY_SIZE, 20, 3); FIELD(REV_CODE, STYLE, 23, 1); +typedef enum RaspiProcessorId { + PROCESSOR_ID_BCM2835 = 0, + PROCESSOR_ID_BCM2836 = 1, + PROCESSOR_ID_BCM2837 = 2, +} RaspiProcessorId; + +static const struct { + const char *type; + int cores_count; +} soc_property[] = { + [PROCESSOR_ID_BCM2835] = {TYPE_BCM2835, 1}, + [PROCESSOR_ID_BCM2836] = {TYPE_BCM2836, BCM283X_NCPUS}, + [PROCESSOR_ID_BCM2837] = {TYPE_BCM2837, BCM283X_NCPUS}, +}; + static uint64_t board_ram_size(uint32_t board_rev) { assert(FIELD_EX32(board_rev, REV_CODE, STYLE)); /* Only new style */ return 256 * MiB << FIELD_EX32(board_rev, REV_CODE, MEMORY_SIZE); } -static int board_processor_id(uint32_t board_rev) +static RaspiProcessorId board_processor_id(uint32_t board_rev) { + int proc_id = FIELD_EX32(board_rev, REV_CODE, PROCESSOR); + assert(FIELD_EX32(board_rev, REV_CODE, STYLE)); /* Only new style */ - return FIELD_EX32(board_rev, REV_CODE, PROCESSOR); -} + assert(proc_id < ARRAY_SIZE(soc_property) && soc_property[proc_id].type); -static int board_version(uint32_t board_rev) -{ - return board_processor_id(board_rev) + 1; + return proc_id; } static const char *board_soc_type(uint32_t board_rev) { - static const char *soc_types[] = { - NULL, TYPE_BCM2836, TYPE_BCM2837, - }; - int proc_id = board_processor_id(board_rev); - - if (proc_id >= ARRAY_SIZE(soc_types) || !soc_types[proc_id]) { - error_report("Unsupported processor id '%d' (board revision: 0x%x)", - proc_id, board_rev); - exit(1); - } - return soc_types[proc_id]; + return soc_property[board_processor_id(board_rev)].type; } static int cores_count(uint32_t board_rev) { - static const int soc_cores_count[] = { - 0, BCM283X_NCPUS, BCM283X_NCPUS, - }; - int proc_id = board_processor_id(board_rev); - - if (proc_id >= ARRAY_SIZE(soc_cores_count) || !soc_cores_count[proc_id]) { - error_report("Unsupported processor id '%d' (board revision: 0x%x)", - proc_id, board_rev); - exit(1); - } - return soc_cores_count[proc_id]; + return soc_property[board_processor_id(board_rev)].cores_count; } static const char *board_type(uint32_t board_rev) @@ -204,44 +198,47 @@ static void reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info) cpu_set_pc(cs, info->smp_loader_start); } -static void setup_boot(MachineState *machine, int version, size_t ram_size) +static void setup_boot(MachineState *machine, RaspiProcessorId processor_id, + size_t ram_size) { - static struct arm_boot_info binfo; + RaspiMachineState *s = RASPI_MACHINE(machine); int r; - binfo.board_id = MACH_TYPE_BCM2708; - binfo.ram_size = ram_size; - binfo.nb_cpus = machine->smp.cpus; + s->binfo.board_id = MACH_TYPE_BCM2708; + s->binfo.ram_size = ram_size; + s->binfo.nb_cpus = machine->smp.cpus; - if (version <= 2) { - /* The rpi1 and 2 require some custom setup code to run in Secure - * mode before booting a kernel (to set up the SMC vectors so - * that we get a no-op SMC; this is used by Linux to call the + if (processor_id <= PROCESSOR_ID_BCM2836) { + /* + * The BCM2835 and BCM2836 require some custom setup code to run + * in Secure mode before booting a kernel (to set up the SMC vectors + * so that we get a no-op SMC; this is used by Linux to call the * firmware for some cache maintenance operations. - * The rpi3 doesn't need this. + * The BCM2837 doesn't need this. */ - binfo.board_setup_addr = BOARDSETUP_ADDR; - binfo.write_board_setup = write_board_setup; - binfo.secure_board_setup = true; - binfo.secure_boot = true; + s->binfo.board_setup_addr = BOARDSETUP_ADDR; + s->binfo.write_board_setup = write_board_setup; + s->binfo.secure_board_setup = true; + s->binfo.secure_boot = true; } - /* Pi2 and Pi3 requires SMP setup */ - if (version >= 2) { - binfo.smp_loader_start = SMPBOOT_ADDR; - if (version == 2) { - binfo.write_secondary_boot = write_smpboot; + /* BCM2836 and BCM2837 requires SMP setup */ + if (processor_id >= PROCESSOR_ID_BCM2836) { + s->binfo.smp_loader_start = SMPBOOT_ADDR; + if (processor_id == PROCESSOR_ID_BCM2836) { + s->binfo.write_secondary_boot = write_smpboot; } else { - binfo.write_secondary_boot = write_smpboot64; + s->binfo.write_secondary_boot = write_smpboot64; } - binfo.secondary_cpu_reset_hook = reset_secondary; + s->binfo.secondary_cpu_reset_hook = reset_secondary; } /* If the user specified a "firmware" image (e.g. UEFI), we bypass * the normal Linux boot process */ if (machine->firmware) { - hwaddr firmware_addr = version == 3 ? FIRMWARE_ADDR_3 : FIRMWARE_ADDR_2; + hwaddr firmware_addr = processor_id <= PROCESSOR_ID_BCM2836 + ? FIRMWARE_ADDR_2 : FIRMWARE_ADDR_3; /* load the firmware image (typically kernel.img) */ r = load_image_targphys(machine->firmware, firmware_addr, ram_size - firmware_addr); @@ -250,11 +247,11 @@ static void setup_boot(MachineState *machine, int version, size_t ram_size) exit(1); } - binfo.entry = firmware_addr; - binfo.firmware_loaded = true; + s->binfo.entry = firmware_addr; + s->binfo.firmware_loaded = true; } - arm_load_kernel(ARM_CPU(first_cpu), machine, &binfo); + arm_load_kernel(&s->soc.cpu[0].core, machine, &s->binfo); } static void raspi_machine_init(MachineState *machine) @@ -262,7 +259,6 @@ static void raspi_machine_init(MachineState *machine) RaspiMachineClass *mc = RASPI_MACHINE_GET_CLASS(machine); RaspiMachineState *s = RASPI_MACHINE(machine); uint32_t board_rev = mc->board_rev; - int version = board_version(board_rev); uint64_t ram_size = board_ram_size(board_rev); uint32_t vcram_size; DriveInfo *di; @@ -282,12 +278,12 @@ static void raspi_machine_init(MachineState *machine) machine->ram, 0); /* Setup the SOC */ - object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), - board_soc_type(board_rev), &error_abort, NULL); + object_initialize_child(OBJECT(machine), "soc", &s->soc, + board_soc_type(board_rev)); object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(machine->ram)); - object_property_set_int(OBJECT(&s->soc), board_rev, "board-rev", + object_property_set_int(OBJECT(&s->soc), "board-rev", board_rev, &error_abort); - object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_abort); + qdev_realize(DEVICE(&s->soc), NULL, &error_abort); /* Create and plug in the SD cards */ di = drive_get_next(IF_SD); @@ -297,23 +293,22 @@ static void raspi_machine_init(MachineState *machine) error_report("No SD bus found in SOC object"); exit(1); } - carddev = qdev_create(bus, TYPE_SD_CARD); - qdev_prop_set_drive(carddev, "drive", blk, &error_fatal); - object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal); + carddev = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal); + qdev_realize_and_unref(carddev, bus, &error_fatal); vcram_size = object_property_get_uint(OBJECT(&s->soc), "vcram-size", &error_abort); - setup_boot(machine, version, machine->ram_size - vcram_size); + setup_boot(machine, board_processor_id(mc->board_rev), + machine->ram_size - vcram_size); } -static void raspi_machine_class_init(ObjectClass *oc, void *data) +static void raspi_machine_class_common_init(MachineClass *mc, + uint32_t board_rev) { - MachineClass *mc = MACHINE_CLASS(oc); - RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc); - uint32_t board_rev = (uint32_t)(uintptr_t)data; - - rmc->board_rev = board_rev; - mc->desc = g_strdup_printf("Raspberry Pi %s", board_type(board_rev)); + mc->desc = g_strdup_printf("Raspberry Pi %s (revision 1.%u)", + board_type(board_rev), + FIELD_EX32(board_rev, REV_CODE, REVISION)); mc->init = raspi_machine_init; mc->block_default_type = IF_SD; mc->no_parallel = 1; @@ -322,23 +317,79 @@ static void raspi_machine_class_init(ObjectClass *oc, void *data) mc->default_cpus = mc->min_cpus = mc->max_cpus = cores_count(board_rev); mc->default_ram_size = board_ram_size(board_rev); mc->default_ram_id = "ram"; - if (board_version(board_rev) == 2) { - mc->ignore_memory_transaction_failures = true; - } }; +static void raspi0_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc); + + rmc->board_rev = 0x920092; /* Revision 1.2 */ + raspi_machine_class_common_init(mc, rmc->board_rev); +}; + +static void raspi1ap_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc); + + rmc->board_rev = 0x900021; /* Revision 1.1 */ + raspi_machine_class_common_init(mc, rmc->board_rev); +}; + +static void raspi2b_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc); + + mc->alias = "raspi2"; + rmc->board_rev = 0xa21041; + raspi_machine_class_common_init(mc, rmc->board_rev); +}; + +#ifdef TARGET_AARCH64 +static void raspi3ap_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc); + + rmc->board_rev = 0x9020e0; /* Revision 1.0 */ + raspi_machine_class_common_init(mc, rmc->board_rev); +}; + +static void raspi3b_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc); + + mc->alias = "raspi3"; + rmc->board_rev = 0xa02082; + raspi_machine_class_common_init(mc, rmc->board_rev); +}; +#endif /* TARGET_AARCH64 */ + static const TypeInfo raspi_machine_types[] = { { - .name = MACHINE_TYPE_NAME("raspi2"), + .name = MACHINE_TYPE_NAME("raspi0"), + .parent = TYPE_RASPI_MACHINE, + .class_init = raspi0_machine_class_init, + }, { + .name = MACHINE_TYPE_NAME("raspi1ap"), .parent = TYPE_RASPI_MACHINE, - .class_init = raspi_machine_class_init, - .class_data = (void *)0xa21041, + .class_init = raspi1ap_machine_class_init, + }, { + .name = MACHINE_TYPE_NAME("raspi2b"), + .parent = TYPE_RASPI_MACHINE, + .class_init = raspi2b_machine_class_init, #ifdef TARGET_AARCH64 }, { - .name = MACHINE_TYPE_NAME("raspi3"), + .name = MACHINE_TYPE_NAME("raspi3ap"), + .parent = TYPE_RASPI_MACHINE, + .class_init = raspi3ap_machine_class_init, + }, { + .name = MACHINE_TYPE_NAME("raspi3b"), .parent = TYPE_RASPI_MACHINE, - .class_init = raspi_machine_class_init, - .class_data = (void *)0xa02082, + .class_init = raspi3b_machine_class_init, #endif }, { .name = TYPE_RASPI_MACHINE, diff --git a/hw/arm/realview.c b/hw/arm/realview.c index 8fcdf75a2b29f6f9255293bb3ecfc8213869332d..0831159d1587a2c7d9700d7dc1e309a9d7e50d7a 100644 --- a/hw/arm/realview.c +++ b/hw/arm/realview.c @@ -26,6 +26,8 @@ #include "hw/cpu/a9mpcore.h" #include "hw/intc/realview_gic.h" #include "hw/irq.h" +#include "hw/i2c/arm_sbcon_i2c.h" +#include "hw/sd/sd.h" #define SMP_BOOT_ADDR 0xe0000000 #define SMP_BOOTREG_ADDR 0x10000030 @@ -68,6 +70,7 @@ static void realview_init(MachineState *machine, qemu_irq mmc_irq[2]; PCIBus *pci_bus = NULL; NICInfo *nd; + DriveInfo *dinfo; I2CBus *i2c; int n; unsigned int smp_cpus = machine->smp.cpus; @@ -105,16 +108,16 @@ static void realview_init(MachineState *machine, * does not currently support EL3 so the CPU EL3 property is disabled * before realization. */ - if (object_property_find(cpuobj, "has_el3", NULL)) { - object_property_set_bool(cpuobj, false, "has_el3", &error_fatal); + if (object_property_find(cpuobj, "has_el3")) { + object_property_set_bool(cpuobj, "has_el3", false, &error_fatal); } if (is_pb && is_mpcore) { - object_property_set_int(cpuobj, periphbase, "reset-cbar", + object_property_set_int(cpuobj, "reset-cbar", periphbase, &error_fatal); } - object_property_set_bool(cpuobj, true, "realized", &error_fatal); + qdev_realize(DEVICE(cpuobj), NULL, &error_fatal); cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpuobj), ARM_CPU_IRQ); } @@ -161,17 +164,17 @@ static void realview_init(MachineState *machine, } sys_id = is_pb ? 0x01780500 : 0xc1400400; - sysctl = qdev_create(NULL, "realview_sysctl"); + sysctl = qdev_new("realview_sysctl"); qdev_prop_set_uint32(sysctl, "sys_id", sys_id); qdev_prop_set_uint32(sysctl, "proc_id", proc_id); - qdev_init_nofail(sysctl); + sysbus_realize_and_unref(SYS_BUS_DEVICE(sysctl), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000); if (is_mpcore) { - dev = qdev_create(NULL, is_pb ? TYPE_A9MPCORE_PRIV : "realview_mpcore"); + dev = qdev_new(is_pb ? TYPE_A9MPCORE_PRIV : "realview_mpcore"); qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); - qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, periphbase); for (n = 0; n < smp_cpus; n++) { sysbus_connect_irq(busdev, n, cpu_irq[n]); @@ -188,9 +191,9 @@ static void realview_init(MachineState *machine, pic[n] = qdev_get_gpio_in(dev, n); } - pl041 = qdev_create(NULL, "pl041"); + pl041 = qdev_new("pl041"); qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512); - qdev_init_nofail(pl041); + sysbus_realize_and_unref(SYS_BUS_DEVICE(pl041), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000); sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, pic[19]); @@ -203,11 +206,11 @@ static void realview_init(MachineState *machine, pl011_create(0x1000c000, pic[15], serial_hd(3)); /* DMA controller is optional, apparently. */ - dev = qdev_create(NULL, "pl081"); - object_property_set_link(OBJECT(dev), OBJECT(sysmem), "downstream", + dev = qdev_new("pl081"); + object_property_set_link(OBJECT(dev), "downstream", OBJECT(sysmem), &error_fatal); - qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, 0x10030000); sysbus_connect_irq(busdev, 0, pic[24]); @@ -233,15 +236,25 @@ static void realview_init(MachineState *machine, mmc_irq[1] = qemu_irq_split( qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN), qemu_irq_invert(qdev_get_gpio_in(gpio2, 0))); - qdev_connect_gpio_out(dev, 0, mmc_irq[0]); - qdev_connect_gpio_out(dev, 1, mmc_irq[1]); + qdev_connect_gpio_out_named(dev, "card-read-only", 0, mmc_irq[0]); + qdev_connect_gpio_out_named(dev, "card-inserted", 0, mmc_irq[1]); + dinfo = drive_get_next(IF_SD); + if (dinfo) { + DeviceState *card; + + card = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo), + &error_fatal); + qdev_realize_and_unref(card, qdev_get_child_bus(dev, "sd-bus"), + &error_fatal); + } sysbus_create_simple("pl031", 0x10017000, pic[10]); if (!is_pb) { - dev = qdev_create(NULL, "realview_pci"); + dev = qdev_new("realview_pci"); busdev = SYS_BUS_DEVICE(dev); - qdev_init_nofail(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, 0x10019000); /* PCI controller registers */ sysbus_mmio_map(busdev, 1, 0x60000000); /* PCI self-config */ sysbus_mmio_map(busdev, 2, 0x61000000); /* PCI config */ @@ -282,9 +295,9 @@ static void realview_init(MachineState *machine, } } - dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL); + dev = sysbus_create_simple(TYPE_VERSATILE_I2C, 0x10002000, NULL); i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c"); - i2c_create_slave(i2c, "ds1338", 0x68); + i2c_slave_create_simple(i2c, "ds1338", 0x68); /* Memory map for RealView Emulation Baseboard: */ /* 0x10000000 System registers. */ diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c index 6f0e233d77f469e58f13161ff35f05f86b88c84d..91d8c43a7eb129bc052fdfd4be95ef641d9cf633 100644 --- a/hw/arm/sabrelite.c +++ b/hw/arm/sabrelite.c @@ -41,7 +41,6 @@ static void sabrelite_reset_secondary(ARMCPU *cpu, static void sabrelite_init(MachineState *machine) { FslIMX6State *s; - Error *err = NULL; /* Check the amount of memory is compatible with the SOC */ if (machine->ram_size > FSL_IMX6_MMDC_SIZE) { @@ -52,11 +51,7 @@ static void sabrelite_init(MachineState *machine) s = FSL_IMX6(object_new(TYPE_FSL_IMX6)); object_property_add_child(OBJECT(machine), "soc", OBJECT(s)); - object_property_set_bool(OBJECT(s), true, "realized", &err); - if (err != NULL) { - error_report("%s", error_get_pretty(err)); - exit(1); - } + qdev_realize(DEVICE(s), NULL, &error_fatal); memory_region_add_subregion(get_system_memory(), FSL_IMX6_MMDC_ADDR, machine->ram); @@ -80,13 +75,13 @@ static void sabrelite_init(MachineState *machine) qemu_irq cs_line; DriveInfo *dinfo = drive_get_next(IF_MTD); - flash_dev = ssi_create_slave_no_init(spi_bus, "sst25vf016b"); + flash_dev = qdev_new("sst25vf016b"); if (dinfo) { - qdev_prop_set_drive(flash_dev, "drive", - blk_by_legacy_dinfo(dinfo), - &error_fatal); + qdev_prop_set_drive_err(flash_dev, "drive", + blk_by_legacy_dinfo(dinfo), + &error_fatal); } - qdev_init_nofail(flash_dev); + qdev_realize_and_unref(flash_dev, BUS(spi_bus), &error_fatal); cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0); sysbus_connect_irq(SYS_BUS_DEVICE(spi_dev), 1, cs_line); diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c index 6a0221a681cff557bb801a41b6032359b18ad6fc..7d9e180c0db04547590d2866b3104f3121818629 100644 --- a/hw/arm/sbsa-ref.c +++ b/hw/arm/sbsa-ref.c @@ -40,7 +40,9 @@ #include "hw/qdev-properties.h" #include "hw/usb.h" #include "hw/char/pl011.h" +#include "hw/watchdog/sbsa_gwdt.h" #include "net/net.h" +#include "qom/object.h" #define RAMLIMIT_GB 8192 #define RAMLIMIT_BYTES (RAMLIMIT_GB * GiB) @@ -62,6 +64,10 @@ enum { SBSA_CPUPERIPHS, SBSA_GIC_DIST, SBSA_GIC_REDIST, + SBSA_SECURE_EC, + SBSA_GWDT, + SBSA_GWDT_REFRESH, + SBSA_GWDT_CONTROL, SBSA_SMMU, SBSA_UART, SBSA_RTC, @@ -78,12 +84,7 @@ enum { SBSA_EHCI, }; -typedef struct MemMapEntry { - hwaddr base; - hwaddr size; -} MemMapEntry; - -typedef struct { +struct SBSAMachineState { MachineState parent; struct arm_boot_info bootinfo; int smp_cpus; @@ -92,11 +93,10 @@ typedef struct { int psci_conduit; DeviceState *gic; PFlashCFI01 *flash[2]; -} SBSAMachineState; +}; #define TYPE_SBSA_MACHINE MACHINE_TYPE_NAME("sbsa-ref") -#define SBSA_MACHINE(obj) \ - OBJECT_CHECK(SBSAMachineState, (obj), TYPE_SBSA_MACHINE) +OBJECT_DECLARE_SIMPLE_TYPE(SBSAMachineState, SBSA_MACHINE) static const MemMapEntry sbsa_ref_memmap[] = { /* 512M boot ROM */ @@ -107,6 +107,9 @@ static const MemMapEntry sbsa_ref_memmap[] = { [SBSA_CPUPERIPHS] = { 0x40000000, 0x00040000 }, [SBSA_GIC_DIST] = { 0x40060000, 0x00010000 }, [SBSA_GIC_REDIST] = { 0x40080000, 0x04000000 }, + [SBSA_SECURE_EC] = { 0x50000000, 0x00001000 }, + [SBSA_GWDT_REFRESH] = { 0x50010000, 0x00001000 }, + [SBSA_GWDT_CONTROL] = { 0x50011000, 0x00001000 }, [SBSA_UART] = { 0x60000000, 0x00001000 }, [SBSA_RTC] = { 0x60010000, 0x00001000 }, [SBSA_GPIO] = { 0x60020000, 0x00001000 }, @@ -136,8 +139,16 @@ static const int sbsa_ref_irqmap[] = { [SBSA_SECURE_UART_MM] = 9, [SBSA_AHCI] = 10, [SBSA_EHCI] = 11, + [SBSA_SMMU] = 12, /* ... to 15 */ + [SBSA_GWDT] = 16, }; +static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx) +{ + uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER; + return arm_cpu_mp_affinity(idx, clustersz); +} + /* * Firmware on this machine only uses ACPI table to load OS, these limited * device tree nodes are just to let firmware know the info which varies from @@ -183,14 +194,31 @@ static void create_fdt(SBSAMachineState *sms) g_free(matrix); } + /* + * From Documentation/devicetree/bindings/arm/cpus.yaml + * On ARM v8 64-bit systems this property is required + * and matches the MPIDR_EL1 register affinity bits. + * + * * If cpus node's #address-cells property is set to 2 + * + * The first reg cell bits [7:0] must be set to + * bits [39:32] of MPIDR_EL1. + * + * The second reg cell bits [23:0] must be set to + * bits [23:0] of MPIDR_EL1. + */ qemu_fdt_add_subnode(sms->fdt, "/cpus"); + qemu_fdt_setprop_cell(sms->fdt, "/cpus", "#address-cells", 2); + qemu_fdt_setprop_cell(sms->fdt, "/cpus", "#size-cells", 0x0); for (cpu = sms->smp_cpus - 1; cpu >= 0; cpu--) { char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu); ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu)); CPUState *cs = CPU(armcpu); + uint64_t mpidr = sbsa_ref_cpu_mp_affinity(sms, cpu); qemu_fdt_add_subnode(sms->fdt, nodename); + qemu_fdt_setprop_u64(sms->fdt, nodename, "reg", mpidr); if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) { qemu_fdt_setprop_cell(sms->fdt, nodename, "numa-node-id", @@ -211,7 +239,7 @@ static PFlashCFI01 *sbsa_flash_create1(SBSAMachineState *sms, * Create a single flash device. We use the same parameters as * the flash devices on the Versatile Express board. */ - DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01); + DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01); qdev_prop_set_uint64(dev, "sector-length", SBSA_FLASH_SECTOR_SIZE); qdev_prop_set_uint8(dev, "width", 4); @@ -243,7 +271,7 @@ static void sbsa_flash_map1(PFlashCFI01 *flash, assert(QEMU_IS_ALIGNED(size, SBSA_FLASH_SECTOR_SIZE)); assert(size / SBSA_FLASH_SECTOR_SIZE <= UINT32_MAX); qdev_prop_set_uint32(dev, "num-blocks", size / SBSA_FLASH_SECTOR_SIZE); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); memory_region_add_subregion(sysmem, base, sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), @@ -339,7 +367,7 @@ static void create_gic(SBSAMachineState *sms) gictype = gicv3_class_name(); - sms->gic = qdev_create(NULL, gictype); + sms->gic = qdev_new(gictype); qdev_prop_set_uint32(sms->gic, "revision", 3); qdev_prop_set_uint32(sms->gic, "num-cpu", smp_cpus); /* @@ -356,8 +384,8 @@ static void create_gic(SBSAMachineState *sms) qdev_prop_set_uint32(sms->gic, "len-redist-region-count", 1); qdev_prop_set_uint32(sms->gic, "redist-region-count[0]", redist0_count); - qdev_init_nofail(sms->gic); gicbusdev = SYS_BUS_DEVICE(sms->gic); + sysbus_realize_and_unref(gicbusdev, &error_fatal); sysbus_mmio_map(gicbusdev, 0, sbsa_ref_memmap[SBSA_GIC_DIST].base); sysbus_mmio_map(gicbusdev, 1, sbsa_ref_memmap[SBSA_GIC_REDIST].base); @@ -409,11 +437,11 @@ static void create_uart(const SBSAMachineState *sms, int uart, { hwaddr base = sbsa_ref_memmap[uart].base; int irq = sbsa_ref_irqmap[uart]; - DeviceState *dev = qdev_create(NULL, TYPE_PL011); + DeviceState *dev = qdev_new(TYPE_PL011); SysBusDevice *s = SYS_BUS_DEVICE(dev); qdev_prop_set_chr(dev, "chardev", chr); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0)); sysbus_connect_irq(s, 0, qdev_get_gpio_in(sms->gic, irq)); @@ -427,6 +455,20 @@ static void create_rtc(const SBSAMachineState *sms) sysbus_create_simple("pl031", base, qdev_get_gpio_in(sms->gic, irq)); } +static void create_wdt(const SBSAMachineState *sms) +{ + hwaddr rbase = sbsa_ref_memmap[SBSA_GWDT_REFRESH].base; + hwaddr cbase = sbsa_ref_memmap[SBSA_GWDT_CONTROL].base; + DeviceState *dev = qdev_new(TYPE_WDT_SBSA); + SysBusDevice *s = SYS_BUS_DEVICE(dev); + int irq = sbsa_ref_irqmap[SBSA_GWDT]; + + sysbus_realize_and_unref(s, &error_fatal); + sysbus_mmio_map(s, 0, rbase); + sysbus_mmio_map(s, 1, cbase); + sysbus_connect_irq(s, 0, qdev_get_gpio_in(sms->gic, irq)); +} + static DeviceState *gpio_key_dev; static void sbsa_ref_powerdown_req(Notifier *n, void *opaque) { @@ -464,9 +506,9 @@ static void create_ahci(const SBSAMachineState *sms) AHCIState *ahci; int i; - dev = qdev_create(NULL, "sysbus-ahci"); + dev = qdev_new("sysbus-ahci"); qdev_prop_set_uint32(dev, "num-ports", NUM_SATA_PORTS); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(sms->gic, irq)); @@ -497,15 +539,15 @@ static void create_smmu(const SBSAMachineState *sms, PCIBus *bus) DeviceState *dev; int i; - dev = qdev_create(NULL, "arm-smmuv3"); + dev = qdev_new("arm-smmuv3"); - object_property_set_link(OBJECT(dev), OBJECT(bus), "primary-bus", + object_property_set_link(OBJECT(dev), "primary-bus", OBJECT(bus), &error_abort); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); for (i = 0; i < NUM_SMMU_IRQS; i++) { sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, - qdev_get_gpio_in(sms->gic, irq + 1)); + qdev_get_gpio_in(sms->gic, irq + i)); } } @@ -525,8 +567,8 @@ static void create_pcie(SBSAMachineState *sms) PCIHostState *pci; int i; - dev = qdev_create(NULL, TYPE_GPEX_HOST); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_GPEX_HOST); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); /* Map ECAM space */ ecam_alias = g_new0(MemoryRegion, 1); @@ -554,7 +596,7 @@ static void create_pcie(SBSAMachineState *sms) for (i = 0; i < GPEX_NUM_IRQS; i++) { sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, - qdev_get_gpio_in(sms->gic, irq + 1)); + qdev_get_gpio_in(sms->gic, irq + i)); gpex_set_irq_num(GPEX_HOST(dev), i, irq + i); } @@ -585,6 +627,16 @@ static void *sbsa_ref_dtb(const struct arm_boot_info *binfo, int *fdt_size) return board->fdt; } +static void create_secure_ec(MemoryRegion *mem) +{ + hwaddr base = sbsa_ref_memmap[SBSA_SECURE_EC].base; + DeviceState *dev = qdev_new("sbsa-ec"); + SysBusDevice *s = SYS_BUS_DEVICE(dev); + + memory_region_add_subregion(mem, base, + sysbus_mmio_get_region(s, 0)); +} + static void sbsa_ref_init(MachineState *machine) { unsigned int smp_cpus = machine->smp.cpus; @@ -659,8 +711,8 @@ static void sbsa_ref_init(MachineState *machine) } cpuobj = object_new(possible_cpus->cpus[n].type); - object_property_set_int(cpuobj, possible_cpus->cpus[n].arch_id, - "mp-affinity", NULL); + object_property_set_int(cpuobj, "mp-affinity", + possible_cpus->cpus[n].arch_id, NULL); cs = CPU(cpuobj); cs->cpu_index = n; @@ -668,19 +720,19 @@ static void sbsa_ref_init(MachineState *machine) numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj), &error_fatal); - if (object_property_find(cpuobj, "reset-cbar", NULL)) { - object_property_set_int(cpuobj, + if (object_property_find(cpuobj, "reset-cbar")) { + object_property_set_int(cpuobj, "reset-cbar", sbsa_ref_memmap[SBSA_CPUPERIPHS].base, - "reset-cbar", &error_abort); + &error_abort); } - object_property_set_link(cpuobj, OBJECT(sysmem), "memory", + object_property_set_link(cpuobj, "memory", OBJECT(sysmem), &error_abort); - object_property_set_link(cpuobj, OBJECT(secure_sysmem), - "secure-memory", &error_abort); + object_property_set_link(cpuobj, "secure-memory", + OBJECT(secure_sysmem), &error_abort); - object_property_set_bool(cpuobj, true, "realized", &error_fatal); + qdev_realize(DEVICE(cpuobj), NULL, &error_fatal); object_unref(cpuobj); } @@ -700,6 +752,8 @@ static void sbsa_ref_init(MachineState *machine) create_rtc(sms); + create_wdt(sms); + create_gpio(sms); create_ahci(sms); @@ -708,6 +762,8 @@ static void sbsa_ref_init(MachineState *machine) create_pcie(sms); + create_secure_ec(secure_sysmem); + sms->bootinfo.ram_size = machine->ram_size; sms->bootinfo.nb_cpus = smp_cpus; sms->bootinfo.board_id = -1; @@ -717,12 +773,6 @@ static void sbsa_ref_init(MachineState *machine) arm_load_kernel(ARM_CPU(first_cpu), machine, &sms->bootinfo); } -static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx) -{ - uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER; - return arm_cpu_mp_affinity(idx, clustersz); -} - static const CPUArchIdList *sbsa_ref_possible_cpu_arch_ids(MachineState *ms) { unsigned int max_cpus = ms->smp.max_cpus; diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index e13a5f4a7cb3ef298549300dd1daf3ebc901f8d5..3838db13952ef193f5e985c97168c6f814cf3c5a 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -32,6 +32,91 @@ /* IOTLB Management */ +static guint smmu_iotlb_key_hash(gconstpointer v) +{ + SMMUIOTLBKey *key = (SMMUIOTLBKey *)v; + uint32_t a, b, c; + + /* Jenkins hash */ + a = b = c = JHASH_INITVAL + sizeof(*key); + a += key->asid + key->level + key->tg; + b += extract64(key->iova, 0, 32); + c += extract64(key->iova, 32, 32); + + __jhash_mix(a, b, c); + __jhash_final(a, b, c); + + return c; +} + +static gboolean smmu_iotlb_key_equal(gconstpointer v1, gconstpointer v2) +{ + SMMUIOTLBKey *k1 = (SMMUIOTLBKey *)v1, *k2 = (SMMUIOTLBKey *)v2; + + return (k1->asid == k2->asid) && (k1->iova == k2->iova) && + (k1->level == k2->level) && (k1->tg == k2->tg); +} + +SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova, + uint8_t tg, uint8_t level) +{ + SMMUIOTLBKey key = {.asid = asid, .iova = iova, .tg = tg, .level = level}; + + return key; +} + +SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, + SMMUTransTableInfo *tt, hwaddr iova) +{ + uint8_t tg = (tt->granule_sz - 10) / 2; + uint8_t inputsize = 64 - tt->tsz; + uint8_t stride = tt->granule_sz - 3; + uint8_t level = 4 - (inputsize - 4) / stride; + SMMUTLBEntry *entry = NULL; + + while (level <= 3) { + uint64_t subpage_size = 1ULL << level_shift(level, tt->granule_sz); + uint64_t mask = subpage_size - 1; + SMMUIOTLBKey key; + + key = smmu_get_iotlb_key(cfg->asid, iova & ~mask, tg, level); + entry = g_hash_table_lookup(bs->iotlb, &key); + if (entry) { + break; + } + level++; + } + + if (entry) { + cfg->iotlb_hits++; + trace_smmu_iotlb_lookup_hit(cfg->asid, iova, + cfg->iotlb_hits, cfg->iotlb_misses, + 100 * cfg->iotlb_hits / + (cfg->iotlb_hits + cfg->iotlb_misses)); + } else { + cfg->iotlb_misses++; + trace_smmu_iotlb_lookup_miss(cfg->asid, iova, + cfg->iotlb_hits, cfg->iotlb_misses, + 100 * cfg->iotlb_hits / + (cfg->iotlb_hits + cfg->iotlb_misses)); + } + return entry; +} + +void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *new) +{ + SMMUIOTLBKey *key = g_new0(SMMUIOTLBKey, 1); + uint8_t tg = (new->granule - 10) / 2; + + if (g_hash_table_size(bs->iotlb) >= SMMU_IOTLB_MAX_SIZE) { + smmu_iotlb_inv_all(bs); + } + + *key = smmu_get_iotlb_key(cfg->asid, new->entry.iova, tg, new->level); + trace_smmu_iotlb_insert(cfg->asid, new->entry.iova, tg, new->level); + g_hash_table_insert(bs->iotlb, key, new); +} + inline void smmu_iotlb_inv_all(SMMUState *s) { trace_smmu_iotlb_inv_all(); @@ -44,15 +129,44 @@ static gboolean smmu_hash_remove_by_asid(gpointer key, gpointer value, uint16_t asid = *(uint16_t *)user_data; SMMUIOTLBKey *iotlb_key = (SMMUIOTLBKey *)key; - return iotlb_key->asid == asid; + return SMMU_IOTLB_ASID(*iotlb_key) == asid; } -inline void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova) +static gboolean smmu_hash_remove_by_asid_iova(gpointer key, gpointer value, + gpointer user_data) { - SMMUIOTLBKey key = {.asid = asid, .iova = iova}; + SMMUTLBEntry *iter = (SMMUTLBEntry *)value; + IOMMUTLBEntry *entry = &iter->entry; + SMMUIOTLBPageInvInfo *info = (SMMUIOTLBPageInvInfo *)user_data; + SMMUIOTLBKey iotlb_key = *(SMMUIOTLBKey *)key; - trace_smmu_iotlb_inv_iova(asid, iova); - g_hash_table_remove(s->iotlb, &key); + if (info->asid >= 0 && info->asid != SMMU_IOTLB_ASID(iotlb_key)) { + return false; + } + return ((info->iova & ~entry->addr_mask) == entry->iova) || + ((entry->iova & ~info->mask) == info->iova); +} + +inline void +smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova, + uint8_t tg, uint64_t num_pages, uint8_t ttl) +{ + if (ttl && (num_pages == 1)) { + SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova, tg, ttl); + + g_hash_table_remove(s->iotlb, &key); + } else { + /* if tg is not set we use 4KB range invalidation */ + uint8_t granule = tg ? tg * 2 + 10 : 12; + + SMMUIOTLBPageInvInfo info = { + .asid = asid, .iova = iova, + .mask = (num_pages * 1 << granule) - 1}; + + g_hash_table_foreach_remove(s->iotlb, + smmu_hash_remove_by_asid_iova, + &info); + } } inline void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid) @@ -149,7 +263,7 @@ SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova) * @cfg: translation config * @iova: iova to translate * @perm: access type - * @tlbe: IOMMUTLBEntry (out) + * @tlbe: SMMUTLBEntry (out) * @info: handle to an error info * * Return 0 on success, < 0 on error. In case of error, @info is filled @@ -159,7 +273,7 @@ SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova) */ static int smmu_ptw_64(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm, - IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info) + SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info) { dma_addr_t baseaddr, indexmask; int stage = cfg->stage; @@ -179,14 +293,11 @@ static int smmu_ptw_64(SMMUTransCfg *cfg, baseaddr = extract64(tt->ttb, 0, 48); baseaddr &= ~indexmask; - tlbe->iova = iova; - tlbe->addr_mask = (1 << granule_sz) - 1; - while (level <= 3) { uint64_t subpage_size = 1ULL << level_shift(level, granule_sz); uint64_t mask = subpage_size - 1; uint32_t offset = iova_level_offset(iova, inputsize, level, granule_sz); - uint64_t pte; + uint64_t pte, gpa; dma_addr_t pte_addr = baseaddr + offset * sizeof(pte); uint8_t ap; @@ -199,60 +310,50 @@ static int smmu_ptw_64(SMMUTransCfg *cfg, if (is_invalid_pte(pte) || is_reserved_pte(pte, level)) { trace_smmu_ptw_invalid_pte(stage, level, baseaddr, pte_addr, offset, pte); - info->type = SMMU_PTW_ERR_TRANSLATION; - goto error; + break; } - if (is_page_pte(pte, level)) { - uint64_t gpa = get_page_pte_address(pte, granule_sz); + if (is_table_pte(pte, level)) { + ap = PTE_APTABLE(pte); - ap = PTE_AP(pte); - if (is_permission_fault(ap, perm)) { + if (is_permission_fault(ap, perm) && !tt->had) { info->type = SMMU_PTW_ERR_PERMISSION; goto error; } - - tlbe->translated_addr = gpa + (iova & mask); - tlbe->perm = PTE_AP_TO_PERM(ap); + baseaddr = get_table_pte_address(pte, granule_sz); + level++; + continue; + } else if (is_page_pte(pte, level)) { + gpa = get_page_pte_address(pte, granule_sz); trace_smmu_ptw_page_pte(stage, level, iova, baseaddr, pte_addr, pte, gpa); - return 0; - } - if (is_block_pte(pte, level)) { + } else { uint64_t block_size; - hwaddr gpa = get_block_pte_address(pte, level, granule_sz, - &block_size); - - ap = PTE_AP(pte); - if (is_permission_fault(ap, perm)) { - info->type = SMMU_PTW_ERR_PERMISSION; - goto error; - } + gpa = get_block_pte_address(pte, level, granule_sz, + &block_size); trace_smmu_ptw_block_pte(stage, level, baseaddr, pte_addr, pte, iova, gpa, block_size >> 20); - - tlbe->translated_addr = gpa + (iova & mask); - tlbe->perm = PTE_AP_TO_PERM(ap); - return 0; } - - /* table pte */ - ap = PTE_APTABLE(pte); - + ap = PTE_AP(pte); if (is_permission_fault(ap, perm)) { info->type = SMMU_PTW_ERR_PERMISSION; goto error; } - baseaddr = get_table_pte_address(pte, granule_sz); - level++; - } + tlbe->entry.translated_addr = gpa; + tlbe->entry.iova = iova & ~mask; + tlbe->entry.addr_mask = mask; + tlbe->entry.perm = PTE_AP_TO_PERM(ap); + tlbe->level = level; + tlbe->granule = granule_sz; + return 0; + } info->type = SMMU_PTW_ERR_TRANSLATION; error: - tlbe->perm = IOMMU_NONE; + tlbe->entry.perm = IOMMU_NONE; return -EINVAL; } @@ -268,7 +369,7 @@ error: * return 0 on success */ inline int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm, - IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info) + SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info) { if (!cfg->aa64) { /* @@ -361,31 +462,6 @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid) return NULL; } -static guint smmu_iotlb_key_hash(gconstpointer v) -{ - SMMUIOTLBKey *key = (SMMUIOTLBKey *)v; - uint32_t a, b, c; - - /* Jenkins hash */ - a = b = c = JHASH_INITVAL + sizeof(*key); - a += key->asid; - b += extract64(key->iova, 0, 32); - c += extract64(key->iova, 32, 32); - - __jhash_mix(a, b, c); - __jhash_final(a, b, c); - - return c; -} - -static gboolean smmu_iotlb_key_equal(gconstpointer v1, gconstpointer v2) -{ - const SMMUIOTLBKey *k1 = v1; - const SMMUIOTLBKey *k2 = v2; - - return (k1->asid == k2->asid) && (k1->iova == k2->iova); -} - /* Unmap the whole notifier's range */ static void smmu_unmap_notifier_range(IOMMUNotifier *n) { diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h index 7794d6d3947f2fc581a4961e6f1a821efa432f43..55147f29be44ced03e00e45aa76fd1de1030203f 100644 --- a/hw/arm/smmu-internal.h +++ b/hw/arm/smmu-internal.h @@ -96,4 +96,12 @@ uint64_t iova_level_offset(uint64_t iova, int inputsize, MAKE_64BIT_MASK(0, gsz - 3); } +#define SMMU_IOTLB_ASID(key) ((key).asid) + +typedef struct SMMUIOTLBPageInvInfo { + int asid; + uint64_t iova; + uint64_t mask; +} SMMUIOTLBPageInvInfo; + #endif diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index 4112394129e0069018a5967cb6851b4e4cc96f93..fa3c088972e83dc08f0c123e1b4c05b15e1cbda7 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -54,6 +54,8 @@ REG32(IDR1, 0x4) REG32(IDR2, 0x8) REG32(IDR3, 0xc) + FIELD(IDR3, HAD, 2, 1); + FIELD(IDR3, RIL, 10, 1); REG32(IDR4, 0x10) REG32(IDR5, 0x14) FIELD(IDR5, OAS, 0, 3); @@ -63,7 +65,8 @@ REG32(IDR5, 0x14) #define SMMU_IDR5_OAS 4 -REG32(IIDR, 0x1c) +REG32(IIDR, 0x18) +REG32(AIDR, 0x1c) REG32(CR0, 0x20) FIELD(CR0, SMMU_ENABLE, 0, 1) FIELD(CR0, EVENTQEN, 2, 1) @@ -298,6 +301,8 @@ enum { /* Command completion notification */ }; #define CMD_TYPE(x) extract32((x)->word[0], 0 , 8) +#define CMD_NUM(x) extract32((x)->word[0], 12 , 5) +#define CMD_SCALE(x) extract32((x)->word[0], 20 , 5) #define CMD_SSEC(x) extract32((x)->word[0], 10, 1) #define CMD_SSV(x) extract32((x)->word[0], 11, 1) #define CMD_RESUME_AC(x) extract32((x)->word[0], 12, 1) @@ -310,6 +315,8 @@ enum { /* Command completion notification */ #define CMD_RESUME_STAG(x) extract32((x)->word[2], 0 , 16) #define CMD_RESP(x) extract32((x)->word[2], 11, 2) #define CMD_LEAF(x) extract32((x)->word[2], 0 , 1) +#define CMD_TTL(x) extract32((x)->word[2], 8 , 2) +#define CMD_TG(x) extract32((x)->word[2], 10, 2) #define CMD_STE_RANGE(x) extract32((x)->word[2], 0 , 5) #define CMD_ADDR(x) ({ \ uint64_t high = (uint64_t)(x)->word[3]; \ @@ -573,6 +580,7 @@ static inline int pa_range(STE *ste) lo = (x)->word[(sel) * 2 + 2] & ~0xfULL; \ hi | lo; \ }) +#define CD_HAD(x, sel) extract32((x)->word[(sel) * 2 + 2], 1, 1) #define CD_TSZ(x, sel) extract32((x)->word[0], (16 * (sel)) + 0, 6) #define CD_TG(x, sel) extract32((x)->word[0], (16 * (sel)) + 6, 2) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 57a79df55b5610b9febc49d646275a0c51721ef5..22607c378413ea047847cadb23760a73745a4111 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -17,6 +17,7 @@ */ #include "qemu/osdep.h" +#include "qemu/bitops.h" #include "hw/irq.h" #include "hw/sysbus.h" #include "migration/vmstate.h" @@ -254,6 +255,9 @@ static void smmuv3_init_regs(SMMUv3State *s) s->idr[1] = FIELD_DP32(s->idr[1], IDR1, EVENTQS, SMMU_EVENTQS); s->idr[1] = FIELD_DP32(s->idr[1], IDR1, CMDQS, SMMU_CMDQS); + s->idr[3] = FIELD_DP32(s->idr[3], IDR3, RIL, 1); + s->idr[3] = FIELD_DP32(s->idr[3], IDR3, HAD, 1); + /* 4K and 64K granule support */ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN4K, 1); s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN64K, 1); @@ -270,6 +274,7 @@ static void smmuv3_init_regs(SMMUv3State *s) s->features = 0; s->sid_split = 0; + s->aidr = 0x1; } static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf, @@ -506,7 +511,8 @@ static int decode_cd(SMMUTransCfg *cfg, CD *cd, SMMUEventInfo *event) if (tt->ttb & ~(MAKE_64BIT_MASK(0, cfg->oas))) { goto bad_cd; } - trace_smmuv3_decode_cd_tt(i, tt->tsz, tt->ttb, tt->granule_sz); + tt->had = CD_HAD(cd, i); + trace_smmuv3_decode_cd_tt(i, tt->tsz, tt->ttb, tt->granule_sz, tt->had); } event->record_trans_faults = CD_R(cd); @@ -626,7 +632,7 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr, SMMUTranslationStatus status; SMMUState *bs = ARM_SMMU(s); uint64_t page_mask, aligned_addr; - IOMMUTLBEntry *cached_entry = NULL; + SMMUTLBEntry *cached_entry = NULL; SMMUTransTableInfo *tt; SMMUTransCfg *cfg = NULL; IOMMUTLBEntry entry = { @@ -636,7 +642,6 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr, .addr_mask = ~(hwaddr)0, .perm = IOMMU_NONE, }; - SMMUIOTLBKey key, *new_key; qemu_mutex_lock(&s->mutex); @@ -675,17 +680,9 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr, page_mask = (1ULL << (tt->granule_sz)) - 1; aligned_addr = addr & ~page_mask; - key.asid = cfg->asid; - key.iova = aligned_addr; - - cached_entry = g_hash_table_lookup(bs->iotlb, &key); + cached_entry = smmu_iotlb_lookup(bs, cfg, tt, aligned_addr); if (cached_entry) { - cfg->iotlb_hits++; - trace_smmu_iotlb_cache_hit(cfg->asid, aligned_addr, - cfg->iotlb_hits, cfg->iotlb_misses, - 100 * cfg->iotlb_hits / - (cfg->iotlb_hits + cfg->iotlb_misses)); - if ((flag & IOMMU_WO) && !(cached_entry->perm & IOMMU_WO)) { + if ((flag & IOMMU_WO) && !(cached_entry->entry.perm & IOMMU_WO)) { status = SMMU_TRANS_ERROR; if (event.record_trans_faults) { event.type = SMMU_EVT_F_PERMISSION; @@ -698,17 +695,7 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr, goto epilogue; } - cfg->iotlb_misses++; - trace_smmu_iotlb_cache_miss(cfg->asid, addr & ~page_mask, - cfg->iotlb_hits, cfg->iotlb_misses, - 100 * cfg->iotlb_hits / - (cfg->iotlb_hits + cfg->iotlb_misses)); - - if (g_hash_table_size(bs->iotlb) >= SMMU_IOTLB_MAX_SIZE) { - smmu_iotlb_inv_all(bs); - } - - cached_entry = g_new0(IOMMUTLBEntry, 1); + cached_entry = g_new0(SMMUTLBEntry, 1); if (smmu_ptw(cfg, aligned_addr, flag, cached_entry, &ptw_info)) { g_free(cached_entry); @@ -753,10 +740,7 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr, } status = SMMU_TRANS_ERROR; } else { - new_key = g_new0(SMMUIOTLBKey, 1); - new_key->asid = cfg->asid; - new_key->iova = aligned_addr; - g_hash_table_insert(bs->iotlb, new_key, cached_entry); + smmu_iotlb_insert(bs, cfg, cached_entry); status = SMMU_TRANS_SUCCESS; } @@ -765,9 +749,9 @@ epilogue: switch (status) { case SMMU_TRANS_SUCCESS: entry.perm = flag; - entry.translated_addr = cached_entry->translated_addr + - (addr & page_mask); - entry.addr_mask = cached_entry->addr_mask; + entry.translated_addr = cached_entry->entry.translated_addr + + (addr & cached_entry->entry.addr_mask); + entry.addr_mask = cached_entry->entry.addr_mask; trace_smmuv3_translate_success(mr->parent_obj.name, sid, addr, entry.translated_addr, entry.perm); break; @@ -807,42 +791,49 @@ epilogue: * @n: notifier to be called * @asid: address space ID or negative value if we don't care * @iova: iova + * @tg: translation granule (if communicated through range invalidation) + * @num_pages: number of @granule sized pages (if tg != 0), otherwise 1 */ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, IOMMUNotifier *n, - int asid, - dma_addr_t iova) + int asid, dma_addr_t iova, + uint8_t tg, uint64_t num_pages) { SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu); - SMMUEventInfo event = {.inval_ste_allowed = true}; - SMMUTransTableInfo *tt; - SMMUTransCfg *cfg; IOMMUTLBEntry entry; + uint8_t granule = tg; - cfg = smmuv3_get_config(sdev, &event); - if (!cfg) { - return; - } + if (!tg) { + SMMUEventInfo event = {.inval_ste_allowed = true}; + SMMUTransCfg *cfg = smmuv3_get_config(sdev, &event); + SMMUTransTableInfo *tt; - if (asid >= 0 && cfg->asid != asid) { - return; - } + if (!cfg) { + return; + } - tt = select_tt(cfg, iova); - if (!tt) { - return; + if (asid >= 0 && cfg->asid != asid) { + return; + } + + tt = select_tt(cfg, iova); + if (!tt) { + return; + } + granule = tt->granule_sz; } entry.target_as = &address_space_memory; entry.iova = iova; - entry.addr_mask = (1 << tt->granule_sz) - 1; + entry.addr_mask = num_pages * (1 << granule) - 1; entry.perm = IOMMU_NONE; memory_region_notify_one(n, &entry); } -/* invalidate an asid/iova tuple in all mr's */ -static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova) +/* invalidate an asid/iova range tuple in all mr's */ +static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova, + uint8_t tg, uint64_t num_pages) { SMMUDevice *sdev; @@ -850,14 +841,41 @@ static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova) IOMMUMemoryRegion *mr = &sdev->iommu; IOMMUNotifier *n; - trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, iova); + trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, iova, + tg, num_pages); IOMMU_NOTIFIER_FOREACH(n, mr) { - smmuv3_notify_iova(mr, n, asid, iova); + smmuv3_notify_iova(mr, n, asid, iova, tg, num_pages); } } } +static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd) +{ + uint8_t scale = 0, num = 0, ttl = 0; + dma_addr_t addr = CMD_ADDR(cmd); + uint8_t type = CMD_TYPE(cmd); + uint16_t vmid = CMD_VMID(cmd); + bool leaf = CMD_LEAF(cmd); + uint8_t tg = CMD_TG(cmd); + hwaddr num_pages = 1; + int asid = -1; + + if (tg) { + scale = CMD_SCALE(cmd); + num = CMD_NUM(cmd); + ttl = CMD_TTL(cmd); + num_pages = (num + 1) * BIT_ULL(scale); + } + + if (type == SMMU_CMD_TLBI_NH_VA) { + asid = CMD_ASID(cmd); + } + trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, num_pages, ttl, leaf); + smmuv3_inv_notifiers_iova(s, asid, addr, tg, num_pages); + smmu_iotlb_inv_iova(s, asid, addr, tg, num_pages, ttl); +} + static int smmuv3_cmdq_consume(SMMUv3State *s) { SMMUState *bs = ARM_SMMU(s); @@ -988,27 +1006,9 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) smmu_iotlb_inv_all(bs); break; case SMMU_CMD_TLBI_NH_VAA: - { - dma_addr_t addr = CMD_ADDR(&cmd); - uint16_t vmid = CMD_VMID(&cmd); - - trace_smmuv3_cmdq_tlbi_nh_vaa(vmid, addr); - smmuv3_inv_notifiers_iova(bs, -1, addr); - smmu_iotlb_inv_all(bs); - break; - } case SMMU_CMD_TLBI_NH_VA: - { - uint16_t asid = CMD_ASID(&cmd); - uint16_t vmid = CMD_VMID(&cmd); - dma_addr_t addr = CMD_ADDR(&cmd); - bool leaf = CMD_LEAF(&cmd); - - trace_smmuv3_cmdq_tlbi_nh_va(vmid, asid, addr, leaf); - smmuv3_inv_notifiers_iova(bs, asid, addr); - smmu_iotlb_inv_iova(bs, asid, addr); + smmuv3_s1_range_inval(bs, &cmd); break; - } case SMMU_CMD_TLBI_EL3_ALL: case SMMU_CMD_TLBI_EL3_VA: case SMMU_CMD_TLBI_EL2_ALL: @@ -1257,6 +1257,9 @@ static MemTxResult smmu_readl(SMMUv3State *s, hwaddr offset, case A_IIDR: *data = s->iidr; return MEMTX_OK; + case A_AIDR: + *data = s->aidr; + return MEMTX_OK; case A_CR0: *data = s->cr[0]; return MEMTX_OK; @@ -1438,6 +1441,7 @@ static const VMStateDescription vmstate_smmuv3 = { .name = "smmuv3", .version_id = 1, .minimum_version_id = 1, + .priority = MIG_PRI_IOMMU, .fields = (VMStateField[]) { VMSTATE_UINT32(features, SMMUv3State), VMSTATE_UINT8(sid_size, SMMUv3State), diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c index c28d9b5ed71d65b5ef1d6c3e90e2ef02e1215b7e..772662f149401a1db31dec540f8362b8f8889b8e 100644 --- a/hw/arm/spitz.c +++ b/hw/arm/spitz.c @@ -23,41 +23,67 @@ #include "hw/ssi/ssi.h" #include "hw/block/flash.h" #include "qemu/timer.h" +#include "qemu/log.h" #include "hw/arm/sharpsl.h" #include "ui/console.h" #include "hw/audio/wm8750.h" #include "audio/audio.h" #include "hw/boards.h" #include "hw/sysbus.h" +#include "hw/misc/max111x.h" #include "migration/vmstate.h" #include "exec/address-spaces.h" #include "cpu.h" +#include "qom/object.h" -#undef REG_FMT -#define REG_FMT "0x%02lx" +enum spitz_model_e { spitz, akita, borzoi, terrier }; + +struct SpitzMachineClass { + MachineClass parent; + enum spitz_model_e model; + int arm_id; +}; + +struct SpitzMachineState { + MachineState parent; + PXA2xxState *mpu; + DeviceState *mux; + DeviceState *lcdtg; + DeviceState *ads7846; + DeviceState *max1111; + DeviceState *scp0; + DeviceState *scp1; + DeviceState *misc_gpio; +}; + +#define TYPE_SPITZ_MACHINE "spitz-common" +OBJECT_DECLARE_TYPE(SpitzMachineState, SpitzMachineClass, SPITZ_MACHINE) + +#define zaurus_printf(format, ...) \ + fprintf(stderr, "%s: " format, __func__, ##__VA_ARGS__) /* Spitz Flash */ -#define FLASH_BASE 0x0c000000 -#define FLASH_ECCLPLB 0x00 /* Line parity 7 - 0 bit */ -#define FLASH_ECCLPUB 0x04 /* Line parity 15 - 8 bit */ -#define FLASH_ECCCP 0x08 /* Column parity 5 - 0 bit */ -#define FLASH_ECCCNTR 0x0c /* ECC byte counter */ -#define FLASH_ECCCLRR 0x10 /* Clear ECC */ -#define FLASH_FLASHIO 0x14 /* Flash I/O */ -#define FLASH_FLASHCTL 0x18 /* Flash Control */ - -#define FLASHCTL_CE0 (1 << 0) -#define FLASHCTL_CLE (1 << 1) -#define FLASHCTL_ALE (1 << 2) -#define FLASHCTL_WP (1 << 3) -#define FLASHCTL_CE1 (1 << 4) -#define FLASHCTL_RYBY (1 << 5) -#define FLASHCTL_NCE (FLASHCTL_CE0 | FLASHCTL_CE1) +#define FLASH_BASE 0x0c000000 +#define FLASH_ECCLPLB 0x00 /* Line parity 7 - 0 bit */ +#define FLASH_ECCLPUB 0x04 /* Line parity 15 - 8 bit */ +#define FLASH_ECCCP 0x08 /* Column parity 5 - 0 bit */ +#define FLASH_ECCCNTR 0x0c /* ECC byte counter */ +#define FLASH_ECCCLRR 0x10 /* Clear ECC */ +#define FLASH_FLASHIO 0x14 /* Flash I/O */ +#define FLASH_FLASHCTL 0x18 /* Flash Control */ + +#define FLASHCTL_CE0 (1 << 0) +#define FLASHCTL_CLE (1 << 1) +#define FLASHCTL_ALE (1 << 2) +#define FLASHCTL_WP (1 << 3) +#define FLASHCTL_CE1 (1 << 4) +#define FLASHCTL_RYBY (1 << 5) +#define FLASHCTL_NCE (FLASHCTL_CE0 | FLASHCTL_CE1) #define TYPE_SL_NAND "sl-nand" -#define SL_NAND(obj) OBJECT_CHECK(SLNANDState, (obj), TYPE_SL_NAND) +OBJECT_DECLARE_SIMPLE_TYPE(SLNANDState, SL_NAND) -typedef struct { +struct SLNANDState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -66,7 +92,7 @@ typedef struct { uint8_t manf_id; uint8_t chip_id; ECCState ecc; -} SLNANDState; +}; static uint64_t sl_read(void *opaque, hwaddr addr, unsigned size) { @@ -74,12 +100,12 @@ static uint64_t sl_read(void *opaque, hwaddr addr, unsigned size) int ryby; switch (addr) { -#define BSHR(byte, from, to) ((s->ecc.lp[byte] >> (from - to)) & (1 << to)) +#define BSHR(byte, from, to) ((s->ecc.lp[byte] >> (from - to)) & (1 << to)) case FLASH_ECCLPLB: return BSHR(0, 4, 0) | BSHR(0, 5, 2) | BSHR(0, 6, 4) | BSHR(0, 7, 6) | BSHR(1, 4, 1) | BSHR(1, 5, 3) | BSHR(1, 6, 5) | BSHR(1, 7, 7); -#define BSHL(byte, from, to) ((s->ecc.lp[byte] << (to - from)) & (1 << to)) +#define BSHL(byte, from, to) ((s->ecc.lp[byte] << (to - from)) & (1 << to)) case FLASH_ECCLPUB: return BSHL(0, 0, 0) | BSHL(0, 1, 2) | BSHL(0, 2, 4) | BSHL(0, 3, 6) | BSHL(1, 0, 1) | BSHL(1, 1, 3) | BSHL(1, 2, 5) | BSHL(1, 3, 7); @@ -105,7 +131,9 @@ static uint64_t sl_read(void *opaque, hwaddr addr, unsigned size) return ecc_digest(&s->ecc, nand_getio(s->nand)); default: - zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr); + qemu_log_mask(LOG_GUEST_ERROR, + "sl_read: bad register offset 0x%02" HWADDR_PRIx "\n", + addr); } return 0; } @@ -136,7 +164,9 @@ static void sl_write(void *opaque, hwaddr addr, break; default: - zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr); + qemu_log_mask(LOG_GUEST_ERROR, + "sl_write: bad register offset 0x%02" HWADDR_PRIx "\n", + addr); } } @@ -155,7 +185,7 @@ static void sl_flash_register(PXA2xxState *cpu, int size) { DeviceState *dev; - dev = qdev_create(NULL, TYPE_SL_NAND); + dev = qdev_new(TYPE_SL_NAND); qdev_prop_set_uint8(dev, "manf_id", NAND_MFR_SAMSUNG); if (size == FLASH_128M) @@ -163,7 +193,7 @@ static void sl_flash_register(PXA2xxState *cpu, int size) else if (size == FLASH_1024M) qdev_prop_set_uint8(dev, "chip_id", 0xf1); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, FLASH_BASE); } @@ -191,8 +221,8 @@ static void sl_nand_realize(DeviceState *dev, Error **errp) /* Spitz Keyboard */ -#define SPITZ_KEY_STROBE_NUM 11 -#define SPITZ_KEY_SENSE_NUM 7 +#define SPITZ_KEY_STROBE_NUM 11 +#define SPITZ_KEY_SENSE_NUM 7 static const int spitz_gpio_key_sense[SPITZ_KEY_SENSE_NUM] = { 12, 17, 91, 34, 36, 38, 39 @@ -214,11 +244,11 @@ static int spitz_keymap[SPITZ_KEY_SENSE_NUM + 1][SPITZ_KEY_STROBE_NUM] = { { 0x52, 0x43, 0x01, 0x47, 0x49, -1 , -1 , -1 , -1 , -1 , -1 }, }; -#define SPITZ_GPIO_AK_INT 13 /* Remote control */ -#define SPITZ_GPIO_SYNC 16 /* Sync button */ -#define SPITZ_GPIO_ON_KEY 95 /* Power button */ -#define SPITZ_GPIO_SWA 97 /* Lid */ -#define SPITZ_GPIO_SWB 96 /* Tablet mode */ +#define SPITZ_GPIO_AK_INT 13 /* Remote control */ +#define SPITZ_GPIO_SYNC 16 /* Sync button */ +#define SPITZ_GPIO_ON_KEY 95 /* Power button */ +#define SPITZ_GPIO_SWA 97 /* Lid */ +#define SPITZ_GPIO_SWB 96 /* Tablet mode */ /* The special buttons are mapped to unused keys */ static const int spitz_gpiomap[5] = { @@ -227,10 +257,9 @@ static const int spitz_gpiomap[5] = { }; #define TYPE_SPITZ_KEYBOARD "spitz-keyboard" -#define SPITZ_KEYBOARD(obj) \ - OBJECT_CHECK(SpitzKeyboardState, (obj), TYPE_SPITZ_KEYBOARD) +OBJECT_DECLARE_SIMPLE_TYPE(SpitzKeyboardState, SPITZ_KEYBOARD) -typedef struct { +struct SpitzKeyboardState { SysBusDevice parent_obj; qemu_irq sense[SPITZ_KEY_SENSE_NUM]; @@ -246,7 +275,7 @@ typedef struct { uint8_t fifo[16]; int fifopos, fifolen; QEMUTimer *kbdtimer; -} SpitzKeyboardState; +}; static void spitz_keyboard_sense_update(SpitzKeyboardState *s) { @@ -300,7 +329,7 @@ static void spitz_keyboard_keydown(SpitzKeyboardState *s, int keycode) #define SPITZ_MOD_CTRL (1 << 8) #define SPITZ_MOD_FN (1 << 9) -#define QUEUE_KEY(c) s->fifo[(s->fifopos + s->fifolen ++) & 0xf] = c +#define QUEUE_KEY(c) s->fifo[(s->fifopos + s->fifolen ++) & 0xf] = c static void spitz_keyboard_handler(void *opaque, int keycode) { @@ -308,25 +337,25 @@ static void spitz_keyboard_handler(void *opaque, int keycode) uint16_t code; int mapcode; switch (keycode) { - case 0x2a: /* Left Shift */ + case 0x2a: /* Left Shift */ s->modifiers |= 1; break; case 0xaa: s->modifiers &= ~1; break; - case 0x36: /* Right Shift */ + case 0x36: /* Right Shift */ s->modifiers |= 2; break; case 0xb6: s->modifiers &= ~2; break; - case 0x1d: /* Control */ + case 0x1d: /* Control */ s->modifiers |= 4; break; case 0x9d: s->modifiers &= ~4; break; - case 0x38: /* Alt */ + case 0x38: /* Alt */ s->modifiers |= 8; break; case 0xb8: @@ -536,35 +565,35 @@ static void spitz_keyboard_realize(DeviceState *dev, Error **errp) /* LCD backlight controller */ -#define LCDTG_RESCTL 0x00 -#define LCDTG_PHACTRL 0x01 -#define LCDTG_DUTYCTRL 0x02 -#define LCDTG_POWERREG0 0x03 -#define LCDTG_POWERREG1 0x04 -#define LCDTG_GPOR3 0x05 -#define LCDTG_PICTRL 0x06 -#define LCDTG_POLCTRL 0x07 +#define LCDTG_RESCTL 0x00 +#define LCDTG_PHACTRL 0x01 +#define LCDTG_DUTYCTRL 0x02 +#define LCDTG_POWERREG0 0x03 +#define LCDTG_POWERREG1 0x04 +#define LCDTG_GPOR3 0x05 +#define LCDTG_PICTRL 0x06 +#define LCDTG_POLCTRL 0x07 + +#define TYPE_SPITZ_LCDTG "spitz-lcdtg" +OBJECT_DECLARE_SIMPLE_TYPE(SpitzLCDTG, SPITZ_LCDTG) -typedef struct { +struct SpitzLCDTG { SSISlave ssidev; uint32_t bl_intensity; uint32_t bl_power; -} SpitzLCDTG; +}; static void spitz_bl_update(SpitzLCDTG *s) { if (s->bl_power && s->bl_intensity) - zaurus_printf("LCD Backlight now at %i/63\n", s->bl_intensity); + zaurus_printf("LCD Backlight now at %u/63\n", s->bl_intensity); else zaurus_printf("LCD Backlight now off\n"); } -/* FIXME: Implement GPIO properly and remove this hack. */ -static SpitzLCDTG *spitz_lcdtg; - static inline void spitz_bl_bit5(void *opaque, int line, int level) { - SpitzLCDTG *s = spitz_lcdtg; + SpitzLCDTG *s = opaque; int prev = s->bl_intensity; if (level) @@ -578,14 +607,14 @@ static inline void spitz_bl_bit5(void *opaque, int line, int level) static inline void spitz_bl_power(void *opaque, int line, int level) { - SpitzLCDTG *s = spitz_lcdtg; + SpitzLCDTG *s = opaque; s->bl_power = !!level; spitz_bl_update(s); } static uint32_t spitz_lcdtg_transfer(SSISlave *dev, uint32_t value) { - SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev); + SpitzLCDTG *s = SPITZ_LCDTG(dev); int addr; addr = value >> 5; value &= 0x1f; @@ -612,36 +641,40 @@ static uint32_t spitz_lcdtg_transfer(SSISlave *dev, uint32_t value) return 0; } -static void spitz_lcdtg_realize(SSISlave *dev, Error **errp) +static void spitz_lcdtg_realize(SSISlave *ssi, Error **errp) { - SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev); + SpitzLCDTG *s = SPITZ_LCDTG(ssi); + DeviceState *dev = DEVICE(s); - spitz_lcdtg = s; s->bl_power = 0; s->bl_intensity = 0x20; + + qdev_init_gpio_in_named(dev, spitz_bl_bit5, "bl_bit5", 1); + qdev_init_gpio_in_named(dev, spitz_bl_power, "bl_power", 1); } /* SSP devices */ -#define CORGI_SSP_PORT 2 +#define CORGI_SSP_PORT 2 -#define SPITZ_GPIO_LCDCON_CS 53 -#define SPITZ_GPIO_ADS7846_CS 14 -#define SPITZ_GPIO_MAX1111_CS 20 -#define SPITZ_GPIO_TP_INT 11 +#define SPITZ_GPIO_LCDCON_CS 53 +#define SPITZ_GPIO_ADS7846_CS 14 +#define SPITZ_GPIO_MAX1111_CS 20 +#define SPITZ_GPIO_TP_INT 11 -static DeviceState *max1111; +#define TYPE_CORGI_SSP "corgi-ssp" +OBJECT_DECLARE_SIMPLE_TYPE(CorgiSSPState, CORGI_SSP) /* "Demux" the signal based on current chipselect */ -typedef struct { +struct CorgiSSPState { SSISlave ssidev; SSIBus *bus[3]; uint32_t enable[3]; -} CorgiSSPState; +}; static uint32_t corgi_ssp_transfer(SSISlave *dev, uint32_t value) { - CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev); + CorgiSSPState *s = CORGI_SSP(dev); int i; for (i = 0; i < 3; i++) { @@ -659,29 +692,18 @@ static void corgi_ssp_gpio_cs(void *opaque, int line, int level) s->enable[line] = !level; } -#define MAX1111_BATT_VOLT 1 -#define MAX1111_BATT_TEMP 2 -#define MAX1111_ACIN_VOLT 3 - -#define SPITZ_BATTERY_TEMP 0xe0 /* About 2.9V */ -#define SPITZ_BATTERY_VOLT 0xd0 /* About 4.0V */ -#define SPITZ_CHARGEON_ACIN 0x80 /* About 5.0V */ +#define MAX1111_BATT_VOLT 1 +#define MAX1111_BATT_TEMP 2 +#define MAX1111_ACIN_VOLT 3 -static void spitz_adc_temp_on(void *opaque, int line, int level) -{ - if (!max1111) - return; - - if (level) - max111x_set_input(max1111, MAX1111_BATT_TEMP, SPITZ_BATTERY_TEMP); - else - max111x_set_input(max1111, MAX1111_BATT_TEMP, 0); -} +#define SPITZ_BATTERY_TEMP 0xe0 /* About 2.9V */ +#define SPITZ_BATTERY_VOLT 0xd0 /* About 4.0V */ +#define SPITZ_CHARGEON_ACIN 0x80 /* About 5.0V */ static void corgi_ssp_realize(SSISlave *d, Error **errp) { DeviceState *dev = DEVICE(d); - CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, d); + CorgiSSPState *s = CORGI_SSP(d); qdev_init_gpio_in(dev, corgi_ssp_gpio_cs, 3); s->bus[0] = ssi_create_bus(dev, "ssi0"); @@ -689,34 +711,36 @@ static void corgi_ssp_realize(SSISlave *d, Error **errp) s->bus[2] = ssi_create_bus(dev, "ssi2"); } -static void spitz_ssp_attach(PXA2xxState *cpu) +static void spitz_ssp_attach(SpitzMachineState *sms) { - DeviceState *mux; - DeviceState *dev; void *bus; - mux = ssi_create_slave(cpu->ssp[CORGI_SSP_PORT - 1], "corgi-ssp"); - - bus = qdev_get_child_bus(mux, "ssi0"); - ssi_create_slave(bus, "spitz-lcdtg"); - - bus = qdev_get_child_bus(mux, "ssi1"); - dev = ssi_create_slave(bus, "ads7846"); - qdev_connect_gpio_out(dev, 0, - qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_TP_INT)); - - bus = qdev_get_child_bus(mux, "ssi2"); - max1111 = ssi_create_slave(bus, "max1111"); - max111x_set_input(max1111, MAX1111_BATT_VOLT, SPITZ_BATTERY_VOLT); - max111x_set_input(max1111, MAX1111_BATT_TEMP, 0); - max111x_set_input(max1111, MAX1111_ACIN_VOLT, SPITZ_CHARGEON_ACIN); - - qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_LCDCON_CS, - qdev_get_gpio_in(mux, 0)); - qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_ADS7846_CS, - qdev_get_gpio_in(mux, 1)); - qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_MAX1111_CS, - qdev_get_gpio_in(mux, 2)); + sms->mux = ssi_create_slave(sms->mpu->ssp[CORGI_SSP_PORT - 1], + TYPE_CORGI_SSP); + + bus = qdev_get_child_bus(sms->mux, "ssi0"); + sms->lcdtg = ssi_create_slave(bus, TYPE_SPITZ_LCDTG); + + bus = qdev_get_child_bus(sms->mux, "ssi1"); + sms->ads7846 = ssi_create_slave(bus, "ads7846"); + qdev_connect_gpio_out(sms->ads7846, 0, + qdev_get_gpio_in(sms->mpu->gpio, SPITZ_GPIO_TP_INT)); + + bus = qdev_get_child_bus(sms->mux, "ssi2"); + sms->max1111 = qdev_new(TYPE_MAX_1111); + qdev_prop_set_uint8(sms->max1111, "input1" /* BATT_VOLT */, + SPITZ_BATTERY_VOLT); + qdev_prop_set_uint8(sms->max1111, "input2" /* BATT_TEMP */, 0); + qdev_prop_set_uint8(sms->max1111, "input3" /* ACIN_VOLT */, + SPITZ_CHARGEON_ACIN); + ssi_realize_and_unref(sms->max1111, bus, &error_fatal); + + qdev_connect_gpio_out(sms->mpu->gpio, SPITZ_GPIO_LCDCON_CS, + qdev_get_gpio_in(sms->mux, 0)); + qdev_connect_gpio_out(sms->mpu->gpio, SPITZ_GPIO_ADS7846_CS, + qdev_get_gpio_in(sms->mux, 1)); + qdev_connect_gpio_out(sms->mpu->gpio, SPITZ_GPIO_MAX1111_CS, + qdev_get_gpio_in(sms->mux, 2)); } /* CF Microdrive */ @@ -735,11 +759,11 @@ static void spitz_microdrive_attach(PXA2xxState *cpu, int slot) /* Wm8750 and Max7310 on I2C */ -#define AKITA_MAX_ADDR 0x18 -#define SPITZ_WM_ADDRL 0x1b -#define SPITZ_WM_ADDRH 0x1a +#define AKITA_MAX_ADDR 0x18 +#define SPITZ_WM_ADDRL 0x1b +#define SPITZ_WM_ADDRH 0x1a -#define SPITZ_GPIO_WM 5 +#define SPITZ_GPIO_WM 5 static void spitz_wm8750_addr(void *opaque, int line, int level) { @@ -758,7 +782,7 @@ static void spitz_i2c_setup(PXA2xxState *cpu) DeviceState *wm; /* Attach a WM8750 to the bus */ - wm = i2c_create_slave(bus, TYPE_WM8750, 0); + wm = DEVICE(i2c_slave_create_simple(bus, TYPE_WM8750, 0)); spitz_wm8750_addr(wm, 0, 0); qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_WM, @@ -773,81 +797,124 @@ static void spitz_i2c_setup(PXA2xxState *cpu) static void spitz_akita_i2c_setup(PXA2xxState *cpu) { /* Attach a Max7310 to Akita I2C bus. */ - i2c_create_slave(pxa2xx_i2c_bus(cpu->i2c[0]), "max7310", + i2c_slave_create_simple(pxa2xx_i2c_bus(cpu->i2c[0]), "max7310", AKITA_MAX_ADDR); } /* Other peripherals */ -static void spitz_out_switch(void *opaque, int line, int level) +/* + * Encapsulation of some miscellaneous GPIO line behaviour for the Spitz boards. + * + * QEMU interface: + * + named GPIO inputs "green-led", "orange-led", "charging", "discharging": + * these currently just print messages that the line has been signalled + * + named GPIO input "adc-temp-on": set to cause the battery-temperature + * value to be passed to the max111x ADC + * + named GPIO output "adc-temp": the ADC value, to be wired up to the max111x + */ +#define TYPE_SPITZ_MISC_GPIO "spitz-misc-gpio" +OBJECT_DECLARE_SIMPLE_TYPE(SpitzMiscGPIOState, SPITZ_MISC_GPIO) + +struct SpitzMiscGPIOState { + SysBusDevice parent_obj; + + qemu_irq adc_value; +}; + +static void spitz_misc_charging(void *opaque, int n, int level) { - switch (line) { - case 0: - zaurus_printf("Charging %s.\n", level ? "off" : "on"); - break; - case 1: - zaurus_printf("Discharging %s.\n", level ? "on" : "off"); - break; - case 2: - zaurus_printf("Green LED %s.\n", level ? "on" : "off"); - break; - case 3: - zaurus_printf("Orange LED %s.\n", level ? "on" : "off"); - break; - case 4: - spitz_bl_bit5(opaque, line, level); - break; - case 5: - spitz_bl_power(opaque, line, level); - break; - case 6: - spitz_adc_temp_on(opaque, line, level); - break; - } + zaurus_printf("Charging %s.\n", level ? "off" : "on"); +} + +static void spitz_misc_discharging(void *opaque, int n, int level) +{ + zaurus_printf("Discharging %s.\n", level ? "off" : "on"); } -#define SPITZ_SCP_LED_GREEN 1 -#define SPITZ_SCP_JK_B 2 -#define SPITZ_SCP_CHRG_ON 3 -#define SPITZ_SCP_MUTE_L 4 -#define SPITZ_SCP_MUTE_R 5 -#define SPITZ_SCP_CF_POWER 6 -#define SPITZ_SCP_LED_ORANGE 7 -#define SPITZ_SCP_JK_A 8 -#define SPITZ_SCP_ADC_TEMP_ON 9 -#define SPITZ_SCP2_IR_ON 1 -#define SPITZ_SCP2_AKIN_PULLUP 2 -#define SPITZ_SCP2_BACKLIGHT_CONT 7 -#define SPITZ_SCP2_BACKLIGHT_ON 8 -#define SPITZ_SCP2_MIC_BIAS 9 - -static void spitz_scoop_gpio_setup(PXA2xxState *cpu, - DeviceState *scp0, DeviceState *scp1) +static void spitz_misc_green_led(void *opaque, int n, int level) { - qemu_irq *outsignals = qemu_allocate_irqs(spitz_out_switch, cpu, 8); + zaurus_printf("Green LED %s.\n", level ? "off" : "on"); +} - qdev_connect_gpio_out(scp0, SPITZ_SCP_CHRG_ON, outsignals[0]); - qdev_connect_gpio_out(scp0, SPITZ_SCP_JK_B, outsignals[1]); - qdev_connect_gpio_out(scp0, SPITZ_SCP_LED_GREEN, outsignals[2]); - qdev_connect_gpio_out(scp0, SPITZ_SCP_LED_ORANGE, outsignals[3]); +static void spitz_misc_orange_led(void *opaque, int n, int level) +{ + zaurus_printf("Orange LED %s.\n", level ? "off" : "on"); +} - if (scp1) { - qdev_connect_gpio_out(scp1, SPITZ_SCP2_BACKLIGHT_CONT, outsignals[4]); - qdev_connect_gpio_out(scp1, SPITZ_SCP2_BACKLIGHT_ON, outsignals[5]); - } +static void spitz_misc_adc_temp(void *opaque, int n, int level) +{ + SpitzMiscGPIOState *s = SPITZ_MISC_GPIO(opaque); + int batt_temp = level ? SPITZ_BATTERY_TEMP : 0; - qdev_connect_gpio_out(scp0, SPITZ_SCP_ADC_TEMP_ON, outsignals[6]); + qemu_set_irq(s->adc_value, batt_temp); } -#define SPITZ_GPIO_HSYNC 22 -#define SPITZ_GPIO_SD_DETECT 9 -#define SPITZ_GPIO_SD_WP 81 -#define SPITZ_GPIO_ON_RESET 89 -#define SPITZ_GPIO_BAT_COVER 90 -#define SPITZ_GPIO_CF1_IRQ 105 -#define SPITZ_GPIO_CF1_CD 94 -#define SPITZ_GPIO_CF2_IRQ 106 -#define SPITZ_GPIO_CF2_CD 93 +static void spitz_misc_gpio_init(Object *obj) +{ + SpitzMiscGPIOState *s = SPITZ_MISC_GPIO(obj); + DeviceState *dev = DEVICE(obj); + + qdev_init_gpio_in_named(dev, spitz_misc_charging, "charging", 1); + qdev_init_gpio_in_named(dev, spitz_misc_discharging, "discharging", 1); + qdev_init_gpio_in_named(dev, spitz_misc_green_led, "green-led", 1); + qdev_init_gpio_in_named(dev, spitz_misc_orange_led, "orange-led", 1); + qdev_init_gpio_in_named(dev, spitz_misc_adc_temp, "adc-temp-on", 1); + + qdev_init_gpio_out_named(dev, &s->adc_value, "adc-temp", 1); +} + +#define SPITZ_SCP_LED_GREEN 1 +#define SPITZ_SCP_JK_B 2 +#define SPITZ_SCP_CHRG_ON 3 +#define SPITZ_SCP_MUTE_L 4 +#define SPITZ_SCP_MUTE_R 5 +#define SPITZ_SCP_CF_POWER 6 +#define SPITZ_SCP_LED_ORANGE 7 +#define SPITZ_SCP_JK_A 8 +#define SPITZ_SCP_ADC_TEMP_ON 9 +#define SPITZ_SCP2_IR_ON 1 +#define SPITZ_SCP2_AKIN_PULLUP 2 +#define SPITZ_SCP2_BACKLIGHT_CONT 7 +#define SPITZ_SCP2_BACKLIGHT_ON 8 +#define SPITZ_SCP2_MIC_BIAS 9 + +static void spitz_scoop_gpio_setup(SpitzMachineState *sms) +{ + DeviceState *miscdev = sysbus_create_simple(TYPE_SPITZ_MISC_GPIO, -1, NULL); + + sms->misc_gpio = miscdev; + + qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_CHRG_ON, + qdev_get_gpio_in_named(miscdev, "charging", 0)); + qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_JK_B, + qdev_get_gpio_in_named(miscdev, "discharging", 0)); + qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_LED_GREEN, + qdev_get_gpio_in_named(miscdev, "green-led", 0)); + qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_LED_ORANGE, + qdev_get_gpio_in_named(miscdev, "orange-led", 0)); + qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_ADC_TEMP_ON, + qdev_get_gpio_in_named(miscdev, "adc-temp-on", 0)); + qdev_connect_gpio_out_named(miscdev, "adc-temp", 0, + qdev_get_gpio_in(sms->max1111, MAX1111_BATT_TEMP)); + + if (sms->scp1) { + qdev_connect_gpio_out(sms->scp1, SPITZ_SCP2_BACKLIGHT_CONT, + qdev_get_gpio_in_named(sms->lcdtg, "bl_bit5", 0)); + qdev_connect_gpio_out(sms->scp1, SPITZ_SCP2_BACKLIGHT_ON, + qdev_get_gpio_in_named(sms->lcdtg, "bl_power", 0)); + } +} + +#define SPITZ_GPIO_HSYNC 22 +#define SPITZ_GPIO_SD_DETECT 9 +#define SPITZ_GPIO_SD_WP 81 +#define SPITZ_GPIO_ON_RESET 89 +#define SPITZ_GPIO_BAT_COVER 90 +#define SPITZ_GPIO_CF1_IRQ 105 +#define SPITZ_GPIO_CF1_CD 94 +#define SPITZ_GPIO_CF2_IRQ 106 +#define SPITZ_GPIO_CF2_CD 93 static int spitz_hsync; @@ -905,27 +972,27 @@ static void spitz_gpio_setup(PXA2xxState *cpu, int slots) } /* Board init. */ -enum spitz_model_e { spitz, akita, borzoi, terrier }; - -#define SPITZ_RAM 0x04000000 -#define SPITZ_ROM 0x00800000 +#define SPITZ_RAM 0x04000000 +#define SPITZ_ROM 0x00800000 static struct arm_boot_info spitz_binfo = { .loader_start = PXA2XX_SDRAM_BASE, .ram_size = 0x04000000, }; -static void spitz_common_init(MachineState *machine, - enum spitz_model_e model, int arm_id) +static void spitz_common_init(MachineState *machine) { + SpitzMachineClass *smc = SPITZ_MACHINE_GET_CLASS(machine); + SpitzMachineState *sms = SPITZ_MACHINE(machine); + enum spitz_model_e model = smc->model; PXA2xxState *mpu; - DeviceState *scp0, *scp1 = NULL; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *rom = g_new(MemoryRegion, 1); /* Setup CPU & memory */ mpu = pxa270_init(address_space_mem, spitz_binfo.ram_size, machine->cpu_type); + sms->mpu = mpu; sl_flash_register(mpu, (model == spitz) ? FLASH_128M : FLASH_1024M); @@ -935,14 +1002,16 @@ static void spitz_common_init(MachineState *machine, /* Setup peripherals */ spitz_keyboard_register(mpu); - spitz_ssp_attach(mpu); + spitz_ssp_attach(sms); - scp0 = sysbus_create_simple("scoop", 0x10800000, NULL); + sms->scp0 = sysbus_create_simple("scoop", 0x10800000, NULL); if (model != akita) { - scp1 = sysbus_create_simple("scoop", 0x08800040, NULL); + sms->scp1 = sysbus_create_simple("scoop", 0x08800040, NULL); + } else { + sms->scp1 = NULL; } - spitz_scoop_gpio_setup(mpu, scp0, scp1); + spitz_scoop_gpio_setup(sms); spitz_gpio_setup(mpu, (model == akita) ? 1 : 2); @@ -958,100 +1027,100 @@ static void spitz_common_init(MachineState *machine, /* A 4.0 GB microdrive is permanently sitting in CF slot 0. */ spitz_microdrive_attach(mpu, 0); - spitz_binfo.board_id = arm_id; + spitz_binfo.board_id = smc->arm_id; arm_load_kernel(mpu->cpu, machine, &spitz_binfo); sl_bootparam_write(SL_PXA_PARAM_BASE); } -static void spitz_init(MachineState *machine) +static void spitz_common_class_init(ObjectClass *oc, void *data) { - spitz_common_init(machine, spitz, 0x2c9); -} - -static void borzoi_init(MachineState *machine) -{ - spitz_common_init(machine, borzoi, 0x33f); -} + MachineClass *mc = MACHINE_CLASS(oc); -static void akita_init(MachineState *machine) -{ - spitz_common_init(machine, akita, 0x2e8); + mc->block_default_type = IF_IDE; + mc->ignore_memory_transaction_failures = true; + mc->init = spitz_common_init; } -static void terrier_init(MachineState *machine) -{ - spitz_common_init(machine, terrier, 0x33f); -} +static const TypeInfo spitz_common_info = { + .name = TYPE_SPITZ_MACHINE, + .parent = TYPE_MACHINE, + .abstract = true, + .instance_size = sizeof(SpitzMachineState), + .class_size = sizeof(SpitzMachineClass), + .class_init = spitz_common_class_init, +}; static void akitapda_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); + SpitzMachineClass *smc = SPITZ_MACHINE_CLASS(oc); mc->desc = "Sharp SL-C1000 (Akita) PDA (PXA270)"; - mc->init = akita_init; - mc->ignore_memory_transaction_failures = true; mc->default_cpu_type = ARM_CPU_TYPE_NAME("pxa270-c0"); + smc->model = akita; + smc->arm_id = 0x2e8; } static const TypeInfo akitapda_type = { .name = MACHINE_TYPE_NAME("akita"), - .parent = TYPE_MACHINE, + .parent = TYPE_SPITZ_MACHINE, .class_init = akitapda_class_init, }; static void spitzpda_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); + SpitzMachineClass *smc = SPITZ_MACHINE_CLASS(oc); mc->desc = "Sharp SL-C3000 (Spitz) PDA (PXA270)"; - mc->init = spitz_init; - mc->block_default_type = IF_IDE; - mc->ignore_memory_transaction_failures = true; mc->default_cpu_type = ARM_CPU_TYPE_NAME("pxa270-c0"); + smc->model = spitz; + smc->arm_id = 0x2c9; } static const TypeInfo spitzpda_type = { .name = MACHINE_TYPE_NAME("spitz"), - .parent = TYPE_MACHINE, + .parent = TYPE_SPITZ_MACHINE, .class_init = spitzpda_class_init, }; static void borzoipda_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); + SpitzMachineClass *smc = SPITZ_MACHINE_CLASS(oc); mc->desc = "Sharp SL-C3100 (Borzoi) PDA (PXA270)"; - mc->init = borzoi_init; - mc->block_default_type = IF_IDE; - mc->ignore_memory_transaction_failures = true; mc->default_cpu_type = ARM_CPU_TYPE_NAME("pxa270-c0"); + smc->model = borzoi; + smc->arm_id = 0x33f; } static const TypeInfo borzoipda_type = { .name = MACHINE_TYPE_NAME("borzoi"), - .parent = TYPE_MACHINE, + .parent = TYPE_SPITZ_MACHINE, .class_init = borzoipda_class_init, }; static void terrierpda_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); + SpitzMachineClass *smc = SPITZ_MACHINE_CLASS(oc); mc->desc = "Sharp SL-C3200 (Terrier) PDA (PXA270)"; - mc->init = terrier_init; - mc->block_default_type = IF_IDE; - mc->ignore_memory_transaction_failures = true; mc->default_cpu_type = ARM_CPU_TYPE_NAME("pxa270-c5"); + smc->model = terrier; + smc->arm_id = 0x33f; } static const TypeInfo terrierpda_type = { .name = MACHINE_TYPE_NAME("terrier"), - .parent = TYPE_MACHINE, + .parent = TYPE_SPITZ_MACHINE, .class_init = terrierpda_class_init, }; static void spitz_machine_init(void) { + type_register_static(&spitz_common_info); type_register_static(&akitapda_type); type_register_static(&spitzpda_type); type_register_static(&borzoipda_type); @@ -1152,7 +1221,7 @@ static void corgi_ssp_class_init(ObjectClass *klass, void *data) } static const TypeInfo corgi_ssp_info = { - .name = "corgi-ssp", + .name = TYPE_CORGI_SSP, .parent = TYPE_SSI_SLAVE, .instance_size = sizeof(CorgiSSPState), .class_init = corgi_ssp_class_init, @@ -1181,18 +1250,30 @@ static void spitz_lcdtg_class_init(ObjectClass *klass, void *data) } static const TypeInfo spitz_lcdtg_info = { - .name = "spitz-lcdtg", + .name = TYPE_SPITZ_LCDTG, .parent = TYPE_SSI_SLAVE, .instance_size = sizeof(SpitzLCDTG), .class_init = spitz_lcdtg_class_init, }; +static const TypeInfo spitz_misc_gpio_info = { + .name = TYPE_SPITZ_MISC_GPIO, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SpitzMiscGPIOState), + .instance_init = spitz_misc_gpio_init, + /* + * No class_init required: device has no internal state so does not + * need to set up reset or vmstate, and does not have a realize method. + */ +}; + static void spitz_register_types(void) { type_register_static(&corgi_ssp_info); type_register_static(&spitz_lcdtg_info); type_register_static(&spitz_keyboard_info); type_register_static(&sl_nand_info); + type_register_static(&spitz_misc_gpio_info); } type_init(spitz_register_types) diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index d136ba1a92adf2d65822d42660b229ed6f841ec7..1237f5af021cc457261c989aa7e2368d11487170 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -18,7 +18,6 @@ #include "hw/boards.h" #include "qemu/log.h" #include "exec/address-spaces.h" -#include "sysemu/runstate.h" #include "sysemu/sysemu.h" #include "hw/arm/armv7m.h" #include "hw/char/pl011.h" @@ -28,6 +27,7 @@ #include "migration/vmstate.h" #include "hw/misc/unimp.h" #include "cpu.h" +#include "qom/object.h" #define GPIO_A 0 #define GPIO_B 1 @@ -58,10 +58,9 @@ typedef const struct { /* General purpose timer module. */ #define TYPE_STELLARIS_GPTM "stellaris-gptm" -#define STELLARIS_GPTM(obj) \ - OBJECT_CHECK(gptm_state, (obj), TYPE_STELLARIS_GPTM) +OBJECT_DECLARE_SIMPLE_TYPE(gptm_state, STELLARIS_GPTM) -typedef struct gptm_state { +struct gptm_state { SysBusDevice parent_obj; MemoryRegion iomem; @@ -81,7 +80,7 @@ typedef struct gptm_state { /* The timers have an alternate output used to trigger the ADC. */ qemu_irq trigger; qemu_irq irq; -} gptm_state; +}; static void gptm_update_irq(gptm_state *s) { @@ -720,10 +719,9 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq, /* I2C controller. */ #define TYPE_STELLARIS_I2C "stellaris-i2c" -#define STELLARIS_I2C(obj) \ - OBJECT_CHECK(stellaris_i2c_state, (obj), TYPE_STELLARIS_I2C) +OBJECT_DECLARE_SIMPLE_TYPE(stellaris_i2c_state, STELLARIS_I2C) -typedef struct { +struct stellaris_i2c_state { SysBusDevice parent_obj; I2CBus *bus; @@ -736,7 +734,7 @@ typedef struct { uint32_t mimr; uint32_t mris; uint32_t mcr; -} stellaris_i2c_state; +}; #define STELLARIS_I2C_MCS_BUSY 0x01 #define STELLARIS_I2C_MCS_ERROR 0x02 @@ -933,10 +931,11 @@ static void stellaris_i2c_init(Object *obj) #define STELLARIS_ADC_FIFO_FULL 0x1000 #define TYPE_STELLARIS_ADC "stellaris-adc" -#define STELLARIS_ADC(obj) \ - OBJECT_CHECK(stellaris_adc_state, (obj), TYPE_STELLARIS_ADC) +typedef struct StellarisADCState stellaris_adc_state; +DECLARE_INSTANCE_CHECKER(stellaris_adc_state, STELLARIS_ADC, + TYPE_STELLARIS_ADC) -typedef struct StellarisADCState { +struct StellarisADCState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -956,7 +955,7 @@ typedef struct StellarisADCState { uint32_t ssctl[4]; uint32_t noise; qemu_irq irq[4]; -} stellaris_adc_state; +}; static uint32_t stellaris_adc_fifo_read(stellaris_adc_state *s, int n) { @@ -1206,14 +1205,6 @@ static void stellaris_adc_init(Object *obj) qdev_init_gpio_in(dev, stellaris_adc_trigger, 1); } -static -void do_sys_reset(void *opaque, int n, int level) -{ - if (level) { - qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); - } -} - /* Board init. */ static stellaris_board_info stellaris_boards[] = { { "LM3S811EVB", @@ -1308,17 +1299,14 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) &error_fatal); memory_region_add_subregion(system_memory, 0x20000000, sram); - nvic = qdev_create(NULL, TYPE_ARMV7M); + nvic = qdev_new(TYPE_ARMV7M); qdev_prop_set_uint32(nvic, "num-irq", NUM_IRQ_LINES); qdev_prop_set_string(nvic, "cpu-type", ms->cpu_type); qdev_prop_set_bit(nvic, "enable-bitband", true); - object_property_set_link(OBJECT(nvic), OBJECT(get_system_memory()), - "memory", &error_abort); + object_property_set_link(OBJECT(nvic), "memory", + OBJECT(get_system_memory()), &error_abort); /* This will exit with an error if the user passed us a bad cpu_type */ - qdev_init_nofail(nvic); - - qdev_connect_gpio_out_named(nvic, "SYSRESETREQ", 0, - qemu_allocate_irq(&do_sys_reset, NULL, 0)); + sysbus_realize_and_unref(SYS_BUS_DEVICE(nvic), &error_fatal); if (board->dc1 & (1 << 16)) { dev = sysbus_create_varargs(TYPE_STELLARIS_ADC, 0x40038000, @@ -1347,13 +1335,13 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) if (board->dc1 & (1 << 3)) { /* watchdog present */ - dev = qdev_create(NULL, TYPE_LUMINARY_WATCHDOG); + dev = qdev_new(TYPE_LUMINARY_WATCHDOG); /* system_clock_scale is valid now */ uint32_t mainclk = NANOSECONDS_PER_SECOND / system_clock_scale; qdev_prop_set_uint32(dev, "wdogclk-frq", mainclk); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x40000000u); @@ -1380,7 +1368,7 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) qdev_get_gpio_in(nvic, 8)); i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c"); if (board->peripherals & BP_OLED_I2C) { - i2c_create_slave(i2c, "ssd0303", 0x3d); + i2c_slave_create_simple(i2c, "ssd0303", 0x3d); } } @@ -1425,9 +1413,9 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) qemu_check_nic_model(&nd_table[0], "stellaris"); - enet = qdev_create(NULL, "stellaris_enet"); + enet = qdev_new("stellaris_enet"); qdev_set_nic_properties(enet, &nd_table[0]); - qdev_init_nofail(enet); + sysbus_realize_and_unref(SYS_BUS_DEVICE(enet), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(enet), 0, 0x40048000); sysbus_connect_irq(SYS_BUS_DEVICE(enet), 0, qdev_get_gpio_in(nvic, 42)); } diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c index 118c3425591cc89221fa8889e19d5b4c8204f7f4..9cd41bf56da5a6fa4d78bc2fe487cda6403b8a0e 100644 --- a/hw/arm/stm32f205_soc.c +++ b/hw/arm/stm32f205_soc.c @@ -51,32 +51,28 @@ static void stm32f205_soc_initfn(Object *obj) STM32F205State *s = STM32F205_SOC(obj); int i; - sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m), - TYPE_ARMV7M); + object_initialize_child(obj, "armv7m", &s->armv7m, TYPE_ARMV7M); - sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg), - TYPE_STM32F2XX_SYSCFG); + object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32F2XX_SYSCFG); for (i = 0; i < STM_NUM_USARTS; i++) { - sysbus_init_child_obj(obj, "usart[*]", &s->usart[i], - sizeof(s->usart[i]), TYPE_STM32F2XX_USART); + object_initialize_child(obj, "usart[*]", &s->usart[i], + TYPE_STM32F2XX_USART); } for (i = 0; i < STM_NUM_TIMERS; i++) { - sysbus_init_child_obj(obj, "timer[*]", &s->timer[i], - sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER); + object_initialize_child(obj, "timer[*]", &s->timer[i], + TYPE_STM32F2XX_TIMER); } s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ)); for (i = 0; i < STM_NUM_ADCS; i++) { - sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]), - TYPE_STM32F2XX_ADC); + object_initialize_child(obj, "adc[*]", &s->adc[i], TYPE_STM32F2XX_ADC); } for (i = 0; i < STM_NUM_SPIS; i++) { - sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]), - TYPE_STM32F2XX_SPI); + object_initialize_child(obj, "spi[*]", &s->spi[i], TYPE_STM32F2XX_SPI); } } @@ -85,7 +81,6 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) STM32F205State *s = STM32F205_SOC(dev_soc); DeviceState *dev, *armv7m; SysBusDevice *busdev; - Error *err = NULL; int i; MemoryRegion *system_memory = get_system_memory(); @@ -109,32 +104,25 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) qdev_prop_set_uint32(armv7m, "num-irq", 96); qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type); qdev_prop_set_bit(armv7m, "enable-bitband", true); - object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()), - "memory", &error_abort); - object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + object_property_set_link(OBJECT(&s->armv7m), "memory", + OBJECT(get_system_memory()), &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) { return; } /* System configuration controller */ dev = DEVICE(&s->syscfg); - object_property_set_bool(OBJECT(&s->syscfg), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->syscfg), errp)) { return; } busdev = SYS_BUS_DEVICE(dev); sysbus_mmio_map(busdev, 0, 0x40013800); - sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, 71)); /* Attach UART (uses USART registers) and USART controllers */ for (i = 0; i < STM_NUM_USARTS; i++) { dev = DEVICE(&(s->usart[i])); qdev_prop_set_chr(dev, "chardev", serial_hd(i)); - object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->usart[i]), errp)) { return; } busdev = SYS_BUS_DEVICE(dev); @@ -146,9 +134,7 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) for (i = 0; i < STM_NUM_TIMERS; i++) { dev = DEVICE(&(s->timer[i])); qdev_prop_set_uint64(dev, "clock-frequency", 1000000000); - object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer[i]), errp)) { return; } busdev = SYS_BUS_DEVICE(dev); @@ -157,11 +143,9 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) } /* ADC 1 to 3 */ - object_property_set_int(OBJECT(s->adc_irqs), STM_NUM_ADCS, - "num-lines", &err); - object_property_set_bool(OBJECT(s->adc_irqs), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + object_property_set_int(OBJECT(s->adc_irqs), "num-lines", STM_NUM_ADCS, + &error_abort); + if (!qdev_realize(DEVICE(s->adc_irqs), NULL, errp)) { return; } qdev_connect_gpio_out(DEVICE(s->adc_irqs), 0, @@ -169,9 +153,7 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) for (i = 0; i < STM_NUM_ADCS; i++) { dev = DEVICE(&(s->adc[i])); - object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->adc[i]), errp)) { return; } busdev = SYS_BUS_DEVICE(dev); @@ -183,9 +165,7 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) /* SPI 1 and 2 */ for (i = 0; i < STM_NUM_SPIS; i++) { dev = DEVICE(&(s->spi[i])); - object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) { return; } busdev = SYS_BUS_DEVICE(dev); diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c index 4f10ce61763dc40cc3159e2908796462cf37969a..cb04c111987b95dd69e194c3d2b106ddff971400 100644 --- a/hw/arm/stm32f405_soc.c +++ b/hw/arm/stm32f405_soc.c @@ -37,7 +37,8 @@ static const uint32_t usart_addr[] = { 0x40011000, 0x40004400, 0x40004800, /* At the moment only Timer 2 to 5 are modelled */ static const uint32_t timer_addr[] = { 0x40000000, 0x40000400, 0x40000800, 0x40000C00 }; -#define ADC_ADDR 0x40012000 +static const uint32_t adc_addr[] = { 0x40012000, 0x40012100, 0x40012200, + 0x40012300, 0x40012400, 0x40012500 }; static const uint32_t spi_addr[] = { 0x40013000, 0x40003800, 0x40003C00, 0x40013400, 0x40015000, 0x40015400 }; #define EXTI_ADDR 0x40013C00 @@ -56,34 +57,29 @@ static void stm32f405_soc_initfn(Object *obj) STM32F405State *s = STM32F405_SOC(obj); int i; - sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m), - TYPE_ARMV7M); + object_initialize_child(obj, "armv7m", &s->armv7m, TYPE_ARMV7M); - sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg), - TYPE_STM32F4XX_SYSCFG); + object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32F4XX_SYSCFG); for (i = 0; i < STM_NUM_USARTS; i++) { - sysbus_init_child_obj(obj, "usart[*]", &s->usart[i], - sizeof(s->usart[i]), TYPE_STM32F2XX_USART); + object_initialize_child(obj, "usart[*]", &s->usart[i], + TYPE_STM32F2XX_USART); } for (i = 0; i < STM_NUM_TIMERS; i++) { - sysbus_init_child_obj(obj, "timer[*]", &s->timer[i], - sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER); + object_initialize_child(obj, "timer[*]", &s->timer[i], + TYPE_STM32F2XX_TIMER); } for (i = 0; i < STM_NUM_ADCS; i++) { - sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]), - TYPE_STM32F2XX_ADC); + object_initialize_child(obj, "adc[*]", &s->adc[i], TYPE_STM32F2XX_ADC); } for (i = 0; i < STM_NUM_SPIS; i++) { - sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]), - TYPE_STM32F2XX_SPI); + object_initialize_child(obj, "spi[*]", &s->spi[i], TYPE_STM32F2XX_SPI); } - sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti), - TYPE_STM32F4XX_EXTI); + object_initialize_child(obj, "exti", &s->exti, TYPE_STM32F4XX_EXTI); } static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp) @@ -120,19 +116,15 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp) qdev_prop_set_uint32(armv7m, "num-irq", 96); qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type); qdev_prop_set_bit(armv7m, "enable-bitband", true); - object_property_set_link(OBJECT(&s->armv7m), OBJECT(system_memory), - "memory", &error_abort); - object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + object_property_set_link(OBJECT(&s->armv7m), "memory", + OBJECT(system_memory), &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) { return; } /* System configuration controller */ dev = DEVICE(&s->syscfg); - object_property_set_bool(OBJECT(&s->syscfg), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->syscfg), errp)) { return; } busdev = SYS_BUS_DEVICE(dev); @@ -143,9 +135,7 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp) for (i = 0; i < STM_NUM_USARTS; i++) { dev = DEVICE(&(s->usart[i])); qdev_prop_set_chr(dev, "chardev", serial_hd(i)); - object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->usart[i]), errp)) { return; } busdev = SYS_BUS_DEVICE(dev); @@ -157,9 +147,7 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp) for (i = 0; i < STM_NUM_TIMERS; i++) { dev = DEVICE(&(s->timer[i])); qdev_prop_set_uint64(dev, "clock-frequency", 1000000000); - object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer[i]), errp)) { return; } busdev = SYS_BUS_DEVICE(dev); @@ -168,40 +156,34 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp) } /* ADC device, the IRQs are ORed together */ - object_initialize_child(OBJECT(s), "adc-orirq", &s->adc_irqs, - sizeof(s->adc_irqs), TYPE_OR_IRQ, - &err, NULL); - if (err != NULL) { - error_propagate(errp, err); + if (!object_initialize_child_with_props(OBJECT(s), "adc-orirq", + &s->adc_irqs, sizeof(s->adc_irqs), + TYPE_OR_IRQ, errp, NULL)) { return; } - object_property_set_int(OBJECT(&s->adc_irqs), STM_NUM_ADCS, - "num-lines", &err); - object_property_set_bool(OBJECT(&s->adc_irqs), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + object_property_set_int(OBJECT(&s->adc_irqs), "num-lines", STM_NUM_ADCS, + &error_abort); + if (!qdev_realize(DEVICE(&s->adc_irqs), NULL, errp)) { return; } qdev_connect_gpio_out(DEVICE(&s->adc_irqs), 0, qdev_get_gpio_in(armv7m, ADC_IRQ)); - dev = DEVICE(&(s->adc[i])); - object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); - return; + for (i = 0; i < STM_NUM_ADCS; i++) { + dev = DEVICE(&(s->adc[i])); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->adc[i]), errp)) { + return; + } + busdev = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(busdev, 0, adc_addr[i]); + sysbus_connect_irq(busdev, 0, + qdev_get_gpio_in(DEVICE(&s->adc_irqs), i)); } - busdev = SYS_BUS_DEVICE(dev); - sysbus_mmio_map(busdev, 0, ADC_ADDR); - sysbus_connect_irq(busdev, 0, - qdev_get_gpio_in(DEVICE(&s->adc_irqs), i)); /* SPI devices */ for (i = 0; i < STM_NUM_SPIS; i++) { dev = DEVICE(&(s->spi[i])); - object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) { return; } busdev = SYS_BUS_DEVICE(dev); @@ -211,9 +193,7 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp) /* EXTI device */ dev = DEVICE(&s->exti); - object_property_set_bool(OBJECT(&s->exti), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->exti), errp)) { return; } busdev = SYS_BUS_DEVICE(dev); diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c index 3010d765bb7d393fba78cda3d1b2cf61c49eeb3d..ca7c385f313c477acdb308fd73fcfa3ef07a855c 100644 --- a/hw/arm/strongarm.c +++ b/hw/arm/strongarm.c @@ -42,8 +42,10 @@ #include "chardev/char-serial.h" #include "sysemu/sysemu.h" #include "hw/ssi/ssi.h" +#include "qapi/error.h" #include "qemu/cutils.h" #include "qemu/log.h" +#include "qom/object.h" //#define DEBUG @@ -83,10 +85,9 @@ static struct { /* Interrupt Controller */ #define TYPE_STRONGARM_PIC "strongarm_pic" -#define STRONGARM_PIC(obj) \ - OBJECT_CHECK(StrongARMPICState, (obj), TYPE_STRONGARM_PIC) +OBJECT_DECLARE_SIMPLE_TYPE(StrongARMPICState, STRONGARM_PIC) -typedef struct StrongARMPICState { +struct StrongARMPICState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -97,7 +98,7 @@ typedef struct StrongARMPICState { uint32_t enabled; uint32_t is_fiq; uint32_t int_idle; -} StrongARMPICState; +}; #define ICIP 0x00 #define ICMR 0x04 @@ -251,10 +252,9 @@ static const TypeInfo strongarm_pic_info = { * f = 32 768 / (RTTR_trim + 1) */ #define TYPE_STRONGARM_RTC "strongarm-rtc" -#define STRONGARM_RTC(obj) \ - OBJECT_CHECK(StrongARMRTCState, (obj), TYPE_STRONGARM_RTC) +OBJECT_DECLARE_SIMPLE_TYPE(StrongARMRTCState, STRONGARM_RTC) -typedef struct StrongARMRTCState { +struct StrongARMRTCState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -267,7 +267,7 @@ typedef struct StrongARMRTCState { QEMUTimer *rtc_hz; qemu_irq rtc_irq; qemu_irq rtc_hz_irq; -} StrongARMRTCState; +}; static inline void strongarm_rtc_int_update(StrongARMRTCState *s) { @@ -477,10 +477,8 @@ static const TypeInfo strongarm_rtc_sysbus_info = { #define GAFR 0x1c #define TYPE_STRONGARM_GPIO "strongarm-gpio" -#define STRONGARM_GPIO(obj) \ - OBJECT_CHECK(StrongARMGPIOInfo, (obj), TYPE_STRONGARM_GPIO) +OBJECT_DECLARE_SIMPLE_TYPE(StrongARMGPIOInfo, STRONGARM_GPIO) -typedef struct StrongARMGPIOInfo StrongARMGPIOInfo; struct StrongARMGPIOInfo { SysBusDevice busdev; MemoryRegion iomem; @@ -644,8 +642,8 @@ static DeviceState *strongarm_gpio_init(hwaddr base, DeviceState *dev; int i; - dev = qdev_create(NULL, TYPE_STRONGARM_GPIO); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_STRONGARM_GPIO); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); for (i = 0; i < 12; i++) @@ -716,10 +714,8 @@ static const TypeInfo strongarm_gpio_info = { #define PPFR 0x10 #define TYPE_STRONGARM_PPC "strongarm-ppc" -#define STRONGARM_PPC(obj) \ - OBJECT_CHECK(StrongARMPPCInfo, (obj), TYPE_STRONGARM_PPC) +OBJECT_DECLARE_SIMPLE_TYPE(StrongARMPPCInfo, STRONGARM_PPC) -typedef struct StrongARMPPCInfo StrongARMPPCInfo; struct StrongARMPPCInfo { SysBusDevice parent_obj; @@ -917,10 +913,9 @@ static const TypeInfo strongarm_ppc_info = { #define RX_FIFO_ROR (1 << 10) #define TYPE_STRONGARM_UART "strongarm-uart" -#define STRONGARM_UART(obj) \ - OBJECT_CHECK(StrongARMUARTState, (obj), TYPE_STRONGARM_UART) +OBJECT_DECLARE_SIMPLE_TYPE(StrongARMUARTState, STRONGARM_UART) -typedef struct StrongARMUARTState { +struct StrongARMUARTState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -940,11 +935,11 @@ typedef struct StrongARMUARTState { uint8_t rx_start; uint8_t rx_len; - uint64_t char_transmit_time; /* time to transmit a char in ticks*/ + uint64_t char_transmit_time; /* time to transmit a char in nanoseconds */ bool wait_break_end; QEMUTimer *rx_timeout_timer; QEMUTimer *tx_timer; -} StrongARMUARTState; +}; static void strongarm_uart_update_status(StrongARMUARTState *s) { @@ -1348,10 +1343,9 @@ static const TypeInfo strongarm_uart_info = { /* Synchronous Serial Ports */ #define TYPE_STRONGARM_SSP "strongarm-ssp" -#define STRONGARM_SSP(obj) \ - OBJECT_CHECK(StrongARMSSPState, (obj), TYPE_STRONGARM_SSP) +OBJECT_DECLARE_SIMPLE_TYPE(StrongARMSSPState, STRONGARM_SSP) -typedef struct StrongARMSSPState { +struct StrongARMSSPState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -1364,7 +1358,7 @@ typedef struct StrongARMSSPState { uint16_t rx_fifo[8]; uint8_t rx_level; uint8_t rx_start; -} StrongARMSSPState; +}; #define SSCR0 0x60 /* SSP Control register 0 */ #define SSCR1 0x64 /* SSP Control register 1 */ @@ -1626,9 +1620,9 @@ StrongARMState *sa1110_init(const char *cpu_type) s->ppc = sysbus_create_varargs(TYPE_STRONGARM_PPC, 0x90060000, NULL); for (i = 0; sa_serial[i].io_base; i++) { - DeviceState *dev = qdev_create(NULL, TYPE_STRONGARM_UART); + DeviceState *dev = qdev_new(TYPE_STRONGARM_UART); qdev_prop_set_chr(dev, "chardev", serial_hd(i)); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, sa_serial[i].io_base); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c index 5dee2d76c6152b72f31266053af1e1348ad02041..66b244aeffd30755fb9a1e5ea867207a2d90492f 100644 --- a/hw/arm/tosa.c +++ b/hw/arm/tosa.c @@ -24,34 +24,36 @@ #include "hw/irq.h" #include "hw/ssi/ssi.h" #include "hw/sysbus.h" +#include "hw/misc/led.h" #include "exec/address-spaces.h" - -#define TOSA_RAM 0x04000000 -#define TOSA_ROM 0x00800000 - -#define TOSA_GPIO_USB_IN (5) -#define TOSA_GPIO_nSD_DETECT (9) -#define TOSA_GPIO_ON_RESET (19) -#define TOSA_GPIO_CF_IRQ (21) /* CF slot0 Ready */ -#define TOSA_GPIO_CF_CD (13) -#define TOSA_GPIO_TC6393XB_INT (15) -#define TOSA_GPIO_JC_CF_IRQ (36) /* CF slot1 Ready */ - -#define TOSA_SCOOP_GPIO_BASE 1 -#define TOSA_GPIO_IR_POWERDWN (TOSA_SCOOP_GPIO_BASE + 2) -#define TOSA_GPIO_SD_WP (TOSA_SCOOP_GPIO_BASE + 3) -#define TOSA_GPIO_PWR_ON (TOSA_SCOOP_GPIO_BASE + 4) - -#define TOSA_SCOOP_JC_GPIO_BASE 1 -#define TOSA_GPIO_BT_LED (TOSA_SCOOP_JC_GPIO_BASE + 0) -#define TOSA_GPIO_NOTE_LED (TOSA_SCOOP_JC_GPIO_BASE + 1) -#define TOSA_GPIO_CHRG_ERR_LED (TOSA_SCOOP_JC_GPIO_BASE + 2) -#define TOSA_GPIO_TC6393XB_L3V_ON (TOSA_SCOOP_JC_GPIO_BASE + 5) -#define TOSA_GPIO_WLAN_LED (TOSA_SCOOP_JC_GPIO_BASE + 7) - -#define DAC_BASE 0x4e -#define DAC_CH1 0 -#define DAC_CH2 1 +#include "qom/object.h" + +#define TOSA_RAM 0x04000000 +#define TOSA_ROM 0x00800000 + +#define TOSA_GPIO_USB_IN (5) +#define TOSA_GPIO_nSD_DETECT (9) +#define TOSA_GPIO_ON_RESET (19) +#define TOSA_GPIO_CF_IRQ (21) /* CF slot0 Ready */ +#define TOSA_GPIO_CF_CD (13) +#define TOSA_GPIO_TC6393XB_INT (15) +#define TOSA_GPIO_JC_CF_IRQ (36) /* CF slot1 Ready */ + +#define TOSA_SCOOP_GPIO_BASE 1 +#define TOSA_GPIO_IR_POWERDWN (TOSA_SCOOP_GPIO_BASE + 2) +#define TOSA_GPIO_SD_WP (TOSA_SCOOP_GPIO_BASE + 3) +#define TOSA_GPIO_PWR_ON (TOSA_SCOOP_GPIO_BASE + 4) + +#define TOSA_SCOOP_JC_GPIO_BASE 1 +#define TOSA_GPIO_BT_LED (TOSA_SCOOP_JC_GPIO_BASE + 0) +#define TOSA_GPIO_NOTE_LED (TOSA_SCOOP_JC_GPIO_BASE + 1) +#define TOSA_GPIO_CHRG_ERR_LED (TOSA_SCOOP_JC_GPIO_BASE + 2) +#define TOSA_GPIO_TC6393XB_L3V_ON (TOSA_SCOOP_JC_GPIO_BASE + 5) +#define TOSA_GPIO_WLAN_LED (TOSA_SCOOP_JC_GPIO_BASE + 7) + +#define DAC_BASE 0x4e +#define DAC_CH1 0 +#define DAC_CH2 1 static void tosa_microdrive_attach(PXA2xxState *cpu) { @@ -65,26 +67,20 @@ static void tosa_microdrive_attach(PXA2xxState *cpu) pxa2xx_pcmcia_attach(cpu->pcmcia[0], md); } -static void tosa_out_switch(void *opaque, int line, int level) -{ - switch (line) { - case 0: - fprintf(stderr, "blue LED %s.\n", level ? "on" : "off"); - break; - case 1: - fprintf(stderr, "green LED %s.\n", level ? "on" : "off"); - break; - case 2: - fprintf(stderr, "amber LED %s.\n", level ? "on" : "off"); - break; - case 3: - fprintf(stderr, "wlan LED %s.\n", level ? "on" : "off"); - break; - default: - fprintf(stderr, "Uhandled out event: %d = %d\n", line, level); - break; - } -} +/* + * Encapsulation of some GPIO line behaviour for the Tosa board + * + * QEMU interface: + * + named GPIO inputs "leds[0..3]": assert to light LEDs + * + named GPIO input "reset": when asserted, resets the system + */ + +#define TYPE_TOSA_MISC_GPIO "tosa-misc-gpio" +OBJECT_DECLARE_SIMPLE_TYPE(TosaMiscGPIOState, TOSA_MISC_GPIO) + +struct TosaMiscGPIOState { + SysBusDevice parent_obj; +}; static void tosa_reset(void *opaque, int line, int level) { @@ -93,13 +89,22 @@ static void tosa_reset(void *opaque, int line, int level) } } +static void tosa_misc_gpio_init(Object *obj) +{ + DeviceState *dev = DEVICE(obj); + + qdev_init_gpio_in_named(dev, tosa_reset, "reset", 1); +} + static void tosa_gpio_setup(PXA2xxState *cpu, DeviceState *scp0, DeviceState *scp1, TC6393xbState *tmio) { - qemu_irq *outsignals = qemu_allocate_irqs(tosa_out_switch, cpu, 4); - qemu_irq reset; + DeviceState *misc_gpio; + LEDState *led[4]; + + misc_gpio = sysbus_create_simple(TYPE_TOSA_MISC_GPIO, -1, NULL); /* MMC/SD host */ pxa2xx_mmci_handlers(cpu->mmc, @@ -107,8 +112,8 @@ static void tosa_gpio_setup(PXA2xxState *cpu, qemu_irq_invert(qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_nSD_DETECT))); /* Handle reset */ - reset = qemu_allocate_irq(tosa_reset, cpu, 0); - qdev_connect_gpio_out(cpu->gpio, TOSA_GPIO_ON_RESET, reset); + qdev_connect_gpio_out(cpu->gpio, TOSA_GPIO_ON_RESET, + qdev_get_gpio_in_named(misc_gpio, "reset", 0)); /* PCMCIA signals: card's IRQ and Card-Detect */ pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0], @@ -119,10 +124,23 @@ static void tosa_gpio_setup(PXA2xxState *cpu, qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_JC_CF_IRQ), NULL); - qdev_connect_gpio_out(scp1, TOSA_GPIO_BT_LED, outsignals[0]); - qdev_connect_gpio_out(scp1, TOSA_GPIO_NOTE_LED, outsignals[1]); - qdev_connect_gpio_out(scp1, TOSA_GPIO_CHRG_ERR_LED, outsignals[2]); - qdev_connect_gpio_out(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]); + led[0] = led_create_simple(OBJECT(misc_gpio), GPIO_POLARITY_ACTIVE_HIGH, + LED_COLOR_BLUE, "bluetooth"); + led[1] = led_create_simple(OBJECT(misc_gpio), GPIO_POLARITY_ACTIVE_HIGH, + LED_COLOR_GREEN, "note"); + led[2] = led_create_simple(OBJECT(misc_gpio), GPIO_POLARITY_ACTIVE_HIGH, + LED_COLOR_AMBER, "charger-error"); + led[3] = led_create_simple(OBJECT(misc_gpio), GPIO_POLARITY_ACTIVE_HIGH, + LED_COLOR_GREEN, "wlan"); + + qdev_connect_gpio_out(scp1, TOSA_GPIO_BT_LED, + qdev_get_gpio_in(DEVICE(led[0]), 0)); + qdev_connect_gpio_out(scp1, TOSA_GPIO_NOTE_LED, + qdev_get_gpio_in(DEVICE(led[1]), 0)); + qdev_connect_gpio_out(scp1, TOSA_GPIO_CHRG_ERR_LED, + qdev_get_gpio_in(DEVICE(led[2]), 0)); + qdev_connect_gpio_out(scp1, TOSA_GPIO_WLAN_LED, + qdev_get_gpio_in(DEVICE(led[3]), 0)); qdev_connect_gpio_out(scp1, TOSA_GPIO_TC6393XB_L3V_ON, tc6393xb_l3v_get(tmio)); @@ -132,7 +150,7 @@ static void tosa_gpio_setup(PXA2xxState *cpu, static uint32_t tosa_ssp_tansfer(SSISlave *dev, uint32_t value) { - fprintf(stderr, "TG: %d %02x\n", value >> 5, value & 0x1f); + fprintf(stderr, "TG: %u %02x\n", value >> 5, value & 0x1f); return 0; } @@ -142,14 +160,14 @@ static void tosa_ssp_realize(SSISlave *dev, Error **errp) } #define TYPE_TOSA_DAC "tosa_dac" -#define TOSA_DAC(obj) OBJECT_CHECK(TosaDACState, (obj), TYPE_TOSA_DAC) +OBJECT_DECLARE_SIMPLE_TYPE(TosaDACState, TOSA_DAC) -typedef struct { +struct TosaDACState { I2CSlave parent_obj; int len; char buf[3]; -} TosaDACState; +}; static int tosa_dac_send(I2CSlave *i2c, uint8_t data) { @@ -206,7 +224,7 @@ static uint8_t tosa_dac_recv(I2CSlave *s) static void tosa_tg_init(PXA2xxState *cpu) { I2CBus *bus = pxa2xx_i2c_bus(cpu->i2c[0]); - i2c_create_slave(bus, TYPE_TOSA_DAC, DAC_BASE); + i2c_slave_create_simple(bus, TYPE_TOSA_DAC, DAC_BASE); ssi_create_slave(cpu->ssp[1], "tosa-ssp"); } @@ -287,10 +305,22 @@ static const TypeInfo tosa_ssp_info = { .class_init = tosa_ssp_class_init, }; +static const TypeInfo tosa_misc_gpio_info = { + .name = TYPE_TOSA_MISC_GPIO, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(TosaMiscGPIOState), + .instance_init = tosa_misc_gpio_init, + /* + * No class init required: device has no internal state so does not + * need to set up reset or vmstate, and has no realize method. + */ +}; + static void tosa_register_types(void) { type_register_static(&tosa_dac_info); type_register_static(&tosa_ssp_info); + type_register_static(&tosa_misc_gpio_info); } type_init(tosa_register_types) diff --git a/hw/arm/trace-events b/hw/arm/trace-events index 0acedcedc6f3e6f573dea16ee4414e27afb1cee9..a335ee891db3330bf378ea6ad4212e98c137aa07 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -14,6 +14,9 @@ smmu_iotlb_inv_all(void) "IOTLB invalidate all" smmu_iotlb_inv_asid(uint16_t asid) "IOTLB invalidate asid=%d" smmu_iotlb_inv_iova(uint16_t asid, uint64_t addr) "IOTLB invalidate asid=%d addr=0x%"PRIx64 smmu_inv_notifiers_mr(const char *name) "iommu mr=%s" +smmu_iotlb_lookup_hit(uint16_t asid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache HIT asid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d" +smmu_iotlb_lookup_miss(uint16_t asid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache MISS asid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d" +smmu_iotlb_insert(uint16_t asid, uint64_t addr, uint8_t tg, uint8_t level) "IOTLB ++ asid=%d addr=0x%"PRIx64" tg=%d level=%d" # smmuv3.c smmuv3_read_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)" @@ -36,20 +39,17 @@ smmuv3_translate_abort(const char *n, uint16_t sid, uint64_t addr, bool is_write smmuv3_translate_success(const char *n, uint16_t sid, uint64_t iova, uint64_t translated, int perm) "%s sid=%d iova=0x%"PRIx64" translated=0x%"PRIx64" perm=0x%x" smmuv3_get_cd(uint64_t addr) "CD addr: 0x%"PRIx64 smmuv3_decode_cd(uint32_t oas) "oas=%d" -smmuv3_decode_cd_tt(int i, uint32_t tsz, uint64_t ttb, uint32_t granule_sz) "TT[%d]:tsz:%d ttb:0x%"PRIx64" granule_sz:%d" +smmuv3_decode_cd_tt(int i, uint32_t tsz, uint64_t ttb, uint32_t granule_sz, bool had) "TT[%d]:tsz:%d ttb:0x%"PRIx64" granule_sz:%d had:%d" smmuv3_cmdq_cfgi_ste(int streamid) "streamid =%d" -smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%d - end=0x%d" +smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%x - end=0x%x" smmuv3_cmdq_cfgi_cd(uint32_t sid) "streamid = %d" smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid %d (hits=%d, misses=%d, hit rate=%d)" smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid %d (hits=%d, misses=%d, hit rate=%d)" -smmuv3_cmdq_tlbi_nh_va(int vmid, int asid, uint64_t addr, bool leaf) "vmid =%d asid =%d addr=0x%"PRIx64" leaf=%d" -smmuv3_cmdq_tlbi_nh_vaa(int vmid, uint64_t addr) "vmid =%d addr=0x%"PRIx64 +smmuv3_s1_range_inval(int vmid, int asid, uint64_t addr, uint8_t tg, uint64_t num_pages, uint8_t ttl, bool leaf) "vmid =%d asid =%d addr=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" ttl=%d leaf=%d" smmuv3_cmdq_tlbi_nh(void) "" smmuv3_cmdq_tlbi_nh_asid(uint16_t asid) "asid=%d" -smmu_iotlb_cache_hit(uint16_t asid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache HIT asid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d" -smmu_iotlb_cache_miss(uint16_t asid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache MISS asid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d" smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid %d" smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s" smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s" -smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint64_t iova) "iommu mr=%s asid=%d iova=0x%"PRIx64 +smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint64_t iova, uint8_t tg, uint64_t num_pages) "iommu mr=%s asid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64 diff --git a/hw/arm/trace.h b/hw/arm/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..91337aa6b041b2a712986abe0737aaa0cb1b2416 --- /dev/null +++ b/hw/arm/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_arm.h" diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c index f3c4a50b19fafb4865a7e21b3cb9c6def64fc6e6..1ea5534626477754725bc1aa49bbe73b3d2e291e 100644 --- a/hw/arm/versatilepb.c +++ b/hw/arm/versatilepb.c @@ -18,12 +18,15 @@ #include "sysemu/sysemu.h" #include "hw/pci/pci.h" #include "hw/i2c/i2c.h" +#include "hw/i2c/arm_sbcon_i2c.h" #include "hw/irq.h" #include "hw/boards.h" #include "exec/address-spaces.h" #include "hw/block/flash.h" #include "qemu/error-report.h" #include "hw/char/pl011.h" +#include "hw/sd/sd.h" +#include "qom/object.h" #define VERSATILE_FLASH_ADDR 0x34000000 #define VERSATILE_FLASH_SIZE (64 * 1024 * 1024) @@ -32,10 +35,9 @@ /* Primary interrupt controller. */ #define TYPE_VERSATILE_PB_SIC "versatilepb_sic" -#define VERSATILE_PB_SIC(obj) \ - OBJECT_CHECK(vpb_sic_state, (obj), TYPE_VERSATILE_PB_SIC) +OBJECT_DECLARE_SIMPLE_TYPE(vpb_sic_state, VERSATILE_PB_SIC) -typedef struct vpb_sic_state { +struct vpb_sic_state { SysBusDevice parent_obj; MemoryRegion iomem; @@ -44,7 +46,7 @@ typedef struct vpb_sic_state { uint32_t pic_enable; qemu_irq parent[32]; int irq; -} vpb_sic_state; +}; static const VMStateDescription vmstate_vpb_sic = { .name = "versatilepb_sic", @@ -211,11 +213,11 @@ static void versatile_init(MachineState *machine, int board_id) * currently support EL3 so the CPU EL3 property is disabled before * realization. */ - if (object_property_find(cpuobj, "has_el3", NULL)) { - object_property_set_bool(cpuobj, false, "has_el3", &error_fatal); + if (object_property_find(cpuobj, "has_el3")) { + object_property_set_bool(cpuobj, "has_el3", false, &error_fatal); } - object_property_set_bool(cpuobj, true, "realized", &error_fatal); + qdev_realize(DEVICE(cpuobj), NULL, &error_fatal); cpu = ARM_CPU(cpuobj); @@ -223,10 +225,10 @@ static void versatile_init(MachineState *machine, int board_id) /* SDRAM at address zero. */ memory_region_add_subregion(sysmem, 0, machine->ram); - sysctl = qdev_create(NULL, "realview_sysctl"); + sysctl = qdev_new("realview_sysctl"); qdev_prop_set_uint32(sysctl, "sys_id", 0x41007004); qdev_prop_set_uint32(sysctl, "proc_id", 0x02000000); - qdev_init_nofail(sysctl); + sysbus_realize_and_unref(SYS_BUS_DEVICE(sysctl), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000); dev = sysbus_create_varargs("pl190", 0x10140000, @@ -245,9 +247,9 @@ static void versatile_init(MachineState *machine, int board_id) sysbus_create_simple("pl050_keyboard", 0x10006000, sic[3]); sysbus_create_simple("pl050_mouse", 0x10007000, sic[4]); - dev = qdev_create(NULL, "versatile_pci"); + dev = qdev_new("versatile_pci"); busdev = SYS_BUS_DEVICE(dev); - qdev_init_nofail(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, 0x10001000); /* PCI controller regs */ sysbus_mmio_map(busdev, 1, 0x41000000); /* PCI self-config */ sysbus_mmio_map(busdev, 2, 0x42000000); /* PCI config */ @@ -286,11 +288,11 @@ static void versatile_init(MachineState *machine, int board_id) pl011_create(0x101f3000, pic[14], serial_hd(2)); pl011_create(0x10009000, sic[6], serial_hd(3)); - dev = qdev_create(NULL, "pl080"); - object_property_set_link(OBJECT(dev), OBJECT(sysmem), "downstream", + dev = qdev_new("pl080"); + object_property_set_link(OBJECT(dev), "downstream", OBJECT(sysmem), &error_fatal); - qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, 0x10130000); sysbus_connect_irq(busdev, 0, pic[17]); @@ -308,20 +310,41 @@ static void versatile_init(MachineState *machine, int board_id) /* Wire up the mux control signals from the SYS_CLCD register */ qdev_connect_gpio_out(sysctl, 0, qdev_get_gpio_in(dev, 0)); - sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL); - sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL); + dev = sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL); + dinfo = drive_get_next(IF_SD); + if (dinfo) { + DeviceState *card; + + card = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo), + &error_fatal); + qdev_realize_and_unref(card, qdev_get_child_bus(dev, "sd-bus"), + &error_fatal); + } + + dev = sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL); + dinfo = drive_get_next(IF_SD); + if (dinfo) { + DeviceState *card; + + card = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo), + &error_fatal); + qdev_realize_and_unref(card, qdev_get_child_bus(dev, "sd-bus"), + &error_fatal); + } /* Add PL031 Real Time Clock. */ sysbus_create_simple("pl031", 0x101e8000, pic[10]); - dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL); + dev = sysbus_create_simple(TYPE_VERSATILE_I2C, 0x10002000, NULL); i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c"); - i2c_create_slave(i2c, "ds1338", 0x68); + i2c_slave_create_simple(i2c, "ds1338", 0x68); /* Add PL041 AACI Interface to the LM4549 codec */ - pl041 = qdev_create(NULL, "pl041"); + pl041 = qdev_new("pl041"); qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512); - qdev_init_nofail(pl041); + sysbus_realize_and_unref(SYS_BUS_DEVICE(pl041), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000); sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, sic[24]); diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c index 69ee4988f9029b45a387425bb2b721561e258bc9..531f3a122ad5f2354a68d1673e1d1256402e17cc 100644 --- a/hw/arm/vexpress.c +++ b/hw/arm/vexpress.c @@ -42,6 +42,9 @@ #include "hw/char/pl011.h" #include "hw/cpu/a9mpcore.h" #include "hw/cpu/a15mpcore.h" +#include "hw/i2c/arm_sbcon_i2c.h" +#include "hw/sd/sd.h" +#include "qom/object.h" #define VEXPRESS_BOARD_ID 0x8e0 #define VEXPRESS_FLASH_SIZE (64 * 1024 * 1024) @@ -164,26 +167,21 @@ static hwaddr motherboard_aseries_map[] = { typedef struct VEDBoardInfo VEDBoardInfo; -typedef struct { +struct VexpressMachineClass { MachineClass parent; VEDBoardInfo *daughterboard; -} VexpressMachineClass; +}; -typedef struct { +struct VexpressMachineState { MachineState parent; bool secure; bool virt; -} VexpressMachineState; +}; #define TYPE_VEXPRESS_MACHINE "vexpress" #define TYPE_VEXPRESS_A9_MACHINE MACHINE_TYPE_NAME("vexpress-a9") #define TYPE_VEXPRESS_A15_MACHINE MACHINE_TYPE_NAME("vexpress-a15") -#define VEXPRESS_MACHINE(obj) \ - OBJECT_CHECK(VexpressMachineState, (obj), TYPE_VEXPRESS_MACHINE) -#define VEXPRESS_MACHINE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VexpressMachineClass, obj, TYPE_VEXPRESS_MACHINE) -#define VEXPRESS_MACHINE_CLASS(klass) \ - OBJECT_CLASS_CHECK(VexpressMachineClass, klass, TYPE_VEXPRESS_MACHINE) +OBJECT_DECLARE_TYPE(VexpressMachineState, VexpressMachineClass, VEXPRESS_MACHINE) typedef void DBoardInitFn(const VexpressMachineState *machine, ram_addr_t ram_size, @@ -217,29 +215,29 @@ static void init_cpus(MachineState *ms, const char *cpu_type, Object *cpuobj = object_new(cpu_type); if (!secure) { - object_property_set_bool(cpuobj, false, "has_el3", NULL); + object_property_set_bool(cpuobj, "has_el3", false, NULL); } if (!virt) { - if (object_property_find(cpuobj, "has_el2", NULL)) { - object_property_set_bool(cpuobj, false, "has_el2", NULL); + if (object_property_find(cpuobj, "has_el2")) { + object_property_set_bool(cpuobj, "has_el2", false, NULL); } } - if (object_property_find(cpuobj, "reset-cbar", NULL)) { - object_property_set_int(cpuobj, periphbase, - "reset-cbar", &error_abort); + if (object_property_find(cpuobj, "reset-cbar")) { + object_property_set_int(cpuobj, "reset-cbar", periphbase, + &error_abort); } - object_property_set_bool(cpuobj, true, "realized", &error_fatal); + qdev_realize(DEVICE(cpuobj), NULL, &error_fatal); } /* Create the private peripheral devices (including the GIC); * this must happen after the CPUs are created because a15mpcore_priv * wires itself up to the CPU's generic_timer gpio out lines. */ - dev = qdev_create(NULL, privdev); + dev = qdev_new(privdev); qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); - qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, periphbase); /* Interrupts [42:0] are from the motherboard; @@ -514,11 +512,10 @@ static void vexpress_modify_dtb(const struct arm_boot_info *info, void *fdt) static PFlashCFI01 *ve_pflash_cfi01_register(hwaddr base, const char *name, DriveInfo *di) { - DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01); + DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01); if (di) { - qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(di), - &error_abort); + qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(di)); } qdev_prop_set_uint32(dev, "num-blocks", @@ -532,7 +529,7 @@ static PFlashCFI01 *ve_pflash_cfi01_register(hwaddr base, const char *name, qdev_prop_set_uint16(dev, "id2", 0x00); qdev_prop_set_uint16(dev, "id3", 0x00); qdev_prop_set_string(dev, "name", name); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); return PFLASH_CFI01(dev); @@ -593,7 +590,7 @@ static void vexpress_common_init(MachineState *machine) sys_id = 0x1190f500; - sysctl = qdev_create(NULL, "realview_sysctl"); + sysctl = qdev_new("realview_sysctl"); qdev_prop_set_uint32(sysctl, "sys_id", sys_id); qdev_prop_set_uint32(sysctl, "proc_id", daughterboard->proc_id); qdev_prop_set_uint32(sysctl, "len-db-voltage", @@ -610,24 +607,34 @@ static void vexpress_common_init(MachineState *machine) qdev_prop_set_uint32(sysctl, propname, daughterboard->clocks[i]); g_free(propname); } - qdev_init_nofail(sysctl); + sysbus_realize_and_unref(SYS_BUS_DEVICE(sysctl), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, map[VE_SYSREGS]); /* VE_SP810: not modelled */ /* VE_SERIALPCI: not modelled */ - pl041 = qdev_create(NULL, "pl041"); + pl041 = qdev_new("pl041"); qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512); - qdev_init_nofail(pl041); + sysbus_realize_and_unref(SYS_BUS_DEVICE(pl041), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, map[VE_PL041]); sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, pic[11]); dev = sysbus_create_varargs("pl181", map[VE_MMCI], pic[9], pic[10], NULL); /* Wire up MMC card detect and read-only signals */ - qdev_connect_gpio_out(dev, 0, + qdev_connect_gpio_out_named(dev, "card-read-only", 0, qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT)); - qdev_connect_gpio_out(dev, 1, + qdev_connect_gpio_out_named(dev, "card-inserted", 0, qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN)); + dinfo = drive_get_next(IF_SD); + if (dinfo) { + DeviceState *card; + + card = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo), + &error_fatal); + qdev_realize_and_unref(card, qdev_get_child_bus(dev, "sd-bus"), + &error_fatal); + } sysbus_create_simple("pl050_keyboard", map[VE_KMI0], pic[12]); sysbus_create_simple("pl050_mouse", map[VE_KMI1], pic[13]); @@ -640,9 +647,9 @@ static void vexpress_common_init(MachineState *machine) sysbus_create_simple("sp804", map[VE_TIMER01], pic[2]); sysbus_create_simple("sp804", map[VE_TIMER23], pic[3]); - dev = sysbus_create_simple("versatile_i2c", map[VE_SERIALDVI], NULL); + dev = sysbus_create_simple(TYPE_VERSATILE_I2C, map[VE_SERIALDVI], NULL); i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c"); - i2c_create_slave(i2c, "sii9022", 0x39); + i2c_slave_create_simple(i2c, "sii9022", 0x39); sysbus_create_simple("pl031", map[VE_RTC], pic[4]); /* RTC */ diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 1b0a584c7b623d295fa53ce5a9b3958c84337267..9747a6458f0bfd34a3c2b3fda96aab99f7f72872 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -41,12 +41,16 @@ #include "hw/acpi/pci.h" #include "hw/acpi/memory_hotplug.h" #include "hw/acpi/generic_event_device.h" +#include "hw/acpi/tpm.h" #include "hw/pci/pcie_host.h" #include "hw/pci/pci.h" +#include "hw/pci-host/gpex.h" #include "hw/arm/virt.h" #include "hw/mem/nvdimm.h" +#include "hw/platform-bus.h" #include "sysemu/numa.h" #include "sysemu/reset.h" +#include "sysemu/tpm.h" #include "kvm_arm.h" #include "migration/vmstate.h" #include "hw/acpi/ghes.h" @@ -152,176 +156,18 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, uint32_t irq, bool use_highmem, bool highmem_ecam) { int ecam_id = VIRT_ECAM_ID(highmem_ecam); - Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf; - int i, slot_no; - hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base; - hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size; - hwaddr base_pio = memmap[VIRT_PCIE_PIO].base; - hwaddr size_pio = memmap[VIRT_PCIE_PIO].size; - hwaddr base_ecam = memmap[ecam_id].base; - hwaddr size_ecam = memmap[ecam_id].size; - int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN; - - Aml *dev = aml_device("%s", "PCI0"); - aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08"))); - aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03"))); - aml_append(dev, aml_name_decl("_SEG", aml_int(0))); - aml_append(dev, aml_name_decl("_BBN", aml_int(0))); - aml_append(dev, aml_name_decl("_UID", aml_string("PCI0"))); - aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device"))); - aml_append(dev, aml_name_decl("_CCA", aml_int(1))); - - /* Declare the PCI Routing Table. */ - Aml *rt_pkg = aml_varpackage(PCI_SLOT_MAX * PCI_NUM_PINS); - for (slot_no = 0; slot_no < PCI_SLOT_MAX; slot_no++) { - for (i = 0; i < PCI_NUM_PINS; i++) { - int gsi = (i + slot_no) % PCI_NUM_PINS; - Aml *pkg = aml_package(4); - aml_append(pkg, aml_int((slot_no << 16) | 0xFFFF)); - aml_append(pkg, aml_int(i)); - aml_append(pkg, aml_name("GSI%d", gsi)); - aml_append(pkg, aml_int(0)); - aml_append(rt_pkg, pkg); - } - } - aml_append(dev, aml_name_decl("_PRT", rt_pkg)); - - /* Create GSI link device */ - for (i = 0; i < PCI_NUM_PINS; i++) { - uint32_t irqs = irq + i; - Aml *dev_gsi = aml_device("GSI%d", i); - aml_append(dev_gsi, aml_name_decl("_HID", aml_string("PNP0C0F"))); - aml_append(dev_gsi, aml_name_decl("_UID", aml_int(i))); - crs = aml_resource_template(); - aml_append(crs, - aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, - AML_EXCLUSIVE, &irqs, 1)); - aml_append(dev_gsi, aml_name_decl("_PRS", crs)); - crs = aml_resource_template(); - aml_append(crs, - aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, - AML_EXCLUSIVE, &irqs, 1)); - aml_append(dev_gsi, aml_name_decl("_CRS", crs)); - method = aml_method("_SRS", 1, AML_NOTSERIALIZED); - aml_append(dev_gsi, method); - aml_append(dev, dev_gsi); - } - - method = aml_method("_CBA", 0, AML_NOTSERIALIZED); - aml_append(method, aml_return(aml_int(base_ecam))); - aml_append(dev, method); - - method = aml_method("_CRS", 0, AML_NOTSERIALIZED); - Aml *rbuf = aml_resource_template(); - aml_append(rbuf, - aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, - 0x0000, 0x0000, nr_pcie_buses - 1, 0x0000, - nr_pcie_buses)); - aml_append(rbuf, - aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, - AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, base_mmio, - base_mmio + size_mmio - 1, 0x0000, size_mmio)); - aml_append(rbuf, - aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, - AML_ENTIRE_RANGE, 0x0000, 0x0000, size_pio - 1, base_pio, - size_pio)); + struct GPEXConfig cfg = { + .mmio32 = memmap[VIRT_PCIE_MMIO], + .pio = memmap[VIRT_PCIE_PIO], + .ecam = memmap[ecam_id], + .irq = irq, + }; if (use_highmem) { - hwaddr base_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].base; - hwaddr size_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].size; - - aml_append(rbuf, - aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, - AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, - base_mmio_high, - base_mmio_high + size_mmio_high - 1, 0x0000, - size_mmio_high)); + cfg.mmio64 = memmap[VIRT_HIGH_PCIE_MMIO]; } - aml_append(method, aml_return(rbuf)); - aml_append(dev, method); - - /* Declare an _OSC (OS Control Handoff) method */ - aml_append(dev, aml_name_decl("SUPP", aml_int(0))); - aml_append(dev, aml_name_decl("CTRL", aml_int(0))); - method = aml_method("_OSC", 4, AML_NOTSERIALIZED); - aml_append(method, - aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1")); - - /* PCI Firmware Specification 3.0 - * 4.5.1. _OSC Interface for PCI Host Bridge Devices - * The _OSC interface for a PCI/PCI-X/PCI Express hierarchy is - * identified by the Universal Unique IDentifier (UUID) - * 33DB4D5B-1FF7-401C-9657-7441C03DD766 - */ - UUID = aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766"); - ifctx = aml_if(aml_equal(aml_arg(0), UUID)); - aml_append(ifctx, - aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2")); - aml_append(ifctx, - aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3")); - aml_append(ifctx, aml_store(aml_name("CDW2"), aml_name("SUPP"))); - aml_append(ifctx, aml_store(aml_name("CDW3"), aml_name("CTRL"))); - - /* - * Allow OS control for all 5 features: - * PCIeHotplug SHPCHotplug PME AER PCIeCapability. - */ - aml_append(ifctx, aml_and(aml_name("CTRL"), aml_int(0x1F), - aml_name("CTRL"))); - - ifctx1 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(0x1)))); - aml_append(ifctx1, aml_or(aml_name("CDW1"), aml_int(0x08), - aml_name("CDW1"))); - aml_append(ifctx, ifctx1); - - ifctx1 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), aml_name("CTRL")))); - aml_append(ifctx1, aml_or(aml_name("CDW1"), aml_int(0x10), - aml_name("CDW1"))); - aml_append(ifctx, ifctx1); - - aml_append(ifctx, aml_store(aml_name("CTRL"), aml_name("CDW3"))); - aml_append(ifctx, aml_return(aml_arg(3))); - aml_append(method, ifctx); - - elsectx = aml_else(); - aml_append(elsectx, aml_or(aml_name("CDW1"), aml_int(4), - aml_name("CDW1"))); - aml_append(elsectx, aml_return(aml_arg(3))); - aml_append(method, elsectx); - aml_append(dev, method); - - method = aml_method("_DSM", 4, AML_NOTSERIALIZED); - - /* PCI Firmware Specification 3.0 - * 4.6.1. _DSM for PCI Express Slot Information - * The UUID in _DSM in this context is - * {E5C937D0-3553-4D7A-9117-EA4D19C3434D} - */ - UUID = aml_touuid("E5C937D0-3553-4D7A-9117-EA4D19C3434D"); - ifctx = aml_if(aml_equal(aml_arg(0), UUID)); - ifctx1 = aml_if(aml_equal(aml_arg(2), aml_int(0))); - uint8_t byte_list[1] = {1}; - buf = aml_buffer(1, byte_list); - aml_append(ifctx1, aml_return(buf)); - aml_append(ifctx, ifctx1); - aml_append(method, ifctx); - - byte_list[0] = 0; - buf = aml_buffer(1, byte_list); - aml_append(method, aml_return(buf)); - aml_append(dev, method); - - Aml *dev_res0 = aml_device("%s", "RES0"); - aml_append(dev_res0, aml_name_decl("_HID", aml_string("PNP0C02"))); - crs = aml_resource_template(); - aml_append(crs, - aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, - AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, base_ecam, - base_ecam + size_ecam - 1, 0x0000, size_ecam)); - aml_append(dev_res0, aml_name_decl("_CRS", crs)); - aml_append(dev, dev_res0); - aml_append(scope, dev); + acpi_dsdt_add_gpex(scope, &cfg); } static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap, @@ -354,11 +200,35 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap, aml_append(scope, dev); } -static void acpi_dsdt_add_power_button(Aml *scope) +static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms) { - Aml *dev = aml_device(ACPI_POWER_BUTTON_DEVICE); - aml_append(dev, aml_name_decl("_HID", aml_string("PNP0C0C"))); + PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev); + hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base; + SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find()); + MemoryRegion *sbdev_mr; + hwaddr tpm_base; + + if (!sbdev) { + return; + } + + tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0); + assert(tpm_base != -1); + + tpm_base += pbus_base; + + sbdev_mr = sysbus_mmio_get_region(sbdev, 0); + + Aml *dev = aml_device("TPM0"); + aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101"))); aml_append(dev, aml_name_decl("_UID", aml_int(0))); + + Aml *crs = aml_resource_template(); + aml_append(crs, + aml_memory32_fixed(tpm_base, + (uint32_t)memory_region_size(sbdev_mr), + AML_READ_WRITE)); + aml_append(dev, aml_name_decl("_CRS", crs)); aml_append(scope, dev); } @@ -539,6 +409,10 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) } } + if (ms->nvdimms_state->is_enabled) { + nvdimm_build_srat(table_data); + } + if (ms->device_memory) { numamem = acpi_data_push(table_data, sizeof *numamem); build_srat_memory(numamem, ms->device_memory->base, @@ -594,12 +468,11 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) int madt_start = table_data->len; const MemMapEntry *memmap = vms->memmap; const int *irqmap = vms->irqmap; - AcpiMultipleApicTable *madt; AcpiMadtGenericDistributor *gicd; AcpiMadtGenericMsiFrame *gic_msi; int i; - madt = acpi_data_push(table_data, sizeof *madt); + acpi_data_push(table_data, sizeof(AcpiMultipleApicTable)); gicd = acpi_data_push(table_data, sizeof *gicd); gicd->type = ACPI_APIC_GENERIC_DISTRIBUTOR; @@ -710,6 +583,7 @@ static void build_fadt_rev5(GArray *table_data, BIOSLinker *linker, static void build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) { + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); Aml *scope, *dsdt; MachineState *ms = MACHINE(vms); const MemMapEntry *memmap = vms->memmap; @@ -728,7 +602,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) acpi_dsdt_add_cpus(scope, vms->smp_cpus); acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], (irqmap[VIRT_UART] + ARM_SPI_BASE)); - acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); + if (vmc->acpi_expose_flash) { + acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); + } acpi_dsdt_add_fw_cfg(scope, &memmap[VIRT_FW_CFG]); acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO], (irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS); @@ -756,6 +632,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) } acpi_dsdt_add_power_button(scope); + acpi_dsdt_add_tpm(scope, vms); aml_append(dsdt, scope); @@ -844,6 +721,11 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) build_iort(tables_blob, tables->linker, vms); } + if (tpm_get_version(tpm_find()) == TPM_VERSION_2_0) { + acpi_add_table(table_offsets, tables_blob); + build_tpm2(tables_blob, tables->linker, tables->tcpalog); + } + /* XSDT is pointed to by RSDP */ xsdt = tables_blob->len; build_xsdt(tables_blob, tables->linker, table_offsets, NULL, NULL); diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 37462a6f78fc3a949c09bd41a3444a296dcb4523..d18df5be1692f50001fd78995fddf24a72d47e73 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -151,6 +151,7 @@ static const MemMapEntry base_memmap[] = { [VIRT_PCDIMM_ACPI] = { 0x09070000, MEMORY_HOTPLUG_IO_LEN }, [VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN }, [VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN}, + [VIRT_PVTIME] = { 0x090a0000, 0x00010000 }, [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, @@ -217,11 +218,9 @@ static bool cpu_type_valid(const char *cpu) static void create_kaslr_seed(VirtMachineState *vms, const char *node) { - Error *err = NULL; uint64_t seed; - if (qemu_guest_getrandom(&seed, sizeof(seed), &err)) { - error_free(err); + if (qemu_guest_getrandom(&seed, sizeof(seed), NULL)) { return; } qemu_fdt_setprop_u64(vms->fdt, node, "kaslr-seed", seed); @@ -523,21 +522,12 @@ static void fdt_add_gic_node(VirtMachineState *vms) static void fdt_add_pmu_nodes(const VirtMachineState *vms) { - CPUState *cpu; - ARMCPU *armcpu; + ARMCPU *armcpu = ARM_CPU(first_cpu); uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI; - CPU_FOREACH(cpu) { - armcpu = ARM_CPU(cpu); - if (!arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { - return; - } - if (kvm_enabled()) { - if (kvm_irqchip_in_kernel()) { - kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ)); - } - kvm_arm_pmu_init(cpu); - } + if (!arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { + assert(!object_property_get_bool(OBJECT(armcpu), "pmu", NULL)); + return; } if (vms->gic_version == VIRT_GIC_VERSION_2) { @@ -546,7 +536,6 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms) (1 << vms->smp_cpus) - 1); } - armcpu = ARM_CPU(qemu_get_cpu(0)); qemu_fdt_add_subnode(vms->fdt, "/pmu"); if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) { const char compat[] = "arm,armv8-pmuv3"; @@ -572,14 +561,14 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) event |= ACPI_GED_NVDIMM_HOTPLUG_EVT; } - dev = qdev_create(NULL, TYPE_ACPI_GED); + dev = qdev_new(TYPE_ACPI_GED); qdev_prop_set_uint32(dev, "ged-event", event); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, irq)); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); return dev; } @@ -594,14 +583,15 @@ static void create_its(VirtMachineState *vms) return; } - dev = qdev_create(NULL, itsclass); + dev = qdev_new(itsclass); - object_property_set_link(OBJECT(dev), OBJECT(vms->gic), "parent-gicv3", + object_property_set_link(OBJECT(dev), "parent-gicv3", OBJECT(vms->gic), &error_abort); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_GIC_ITS].base); fdt_add_its_gic_node(vms); + vms->msi_controller = VIRT_MSI_CTRL_ITS; } static void create_v2m(VirtMachineState *vms) @@ -610,11 +600,11 @@ static void create_v2m(VirtMachineState *vms) int irq = vms->irqmap[VIRT_GIC_V2M]; DeviceState *dev; - dev = qdev_create(NULL, "arm-gicv2m"); + dev = qdev_new("arm-gicv2m"); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_GIC_V2M].base); qdev_prop_set_uint32(dev, "base-spi", irq); qdev_prop_set_uint32(dev, "num-spi", NUM_GICV2M_SPIS); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); for (i = 0; i < NUM_GICV2M_SPIS; i++) { sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, @@ -622,6 +612,7 @@ static void create_v2m(VirtMachineState *vms) } fdt_add_v2m_gic_node(vms); + vms->msi_controller = VIRT_MSI_CTRL_GICV2M; } static void create_gic(VirtMachineState *vms) @@ -636,7 +627,7 @@ static void create_gic(VirtMachineState *vms) gictype = (type == 3) ? gicv3_class_name() : gic_class_name(); - vms->gic = qdev_create(NULL, gictype); + vms->gic = qdev_new(gictype); qdev_prop_set_uint32(vms->gic, "revision", type); qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus); /* Note that the num-irq property counts both internal and external @@ -671,8 +662,8 @@ static void create_gic(VirtMachineState *vms) vms->virt); } } - qdev_init_nofail(vms->gic); gicbusdev = SYS_BUS_DEVICE(vms->gic); + sysbus_realize_and_unref(gicbusdev, &error_fatal); sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base); if (type == 3) { sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base); @@ -754,11 +745,11 @@ static void create_uart(const VirtMachineState *vms, int uart, int irq = vms->irqmap[uart]; const char compat[] = "arm,pl011\0arm,primecell"; const char clocknames[] = "uartclk\0apb_pclk"; - DeviceState *dev = qdev_create(NULL, TYPE_PL011); + DeviceState *dev = qdev_new(TYPE_PL011); SysBusDevice *s = SYS_BUS_DEVICE(dev); qdev_prop_set_chr(dev, "chardev", chr); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0)); sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq)); @@ -948,7 +939,7 @@ static PFlashCFI01 *virt_flash_create1(VirtMachineState *vms, * Create a single flash device. We use the same parameters as * the flash devices on the Versatile Express board. */ - DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01); + DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01); qdev_prop_set_uint64(dev, "sector-length", VIRT_FLASH_SECTOR_SIZE); qdev_prop_set_uint8(dev, "width", 4); @@ -980,7 +971,7 @@ static void virt_flash_map1(PFlashCFI01 *flash, assert(QEMU_IS_ALIGNED(size, VIRT_FLASH_SECTOR_SIZE)); assert(size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX); qdev_prop_set_uint32(dev, "num-blocks", size / VIRT_FLASH_SECTOR_SIZE); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); memory_region_add_subregion(sysmem, base, sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), @@ -1173,11 +1164,11 @@ static void create_smmu(const VirtMachineState *vms, return; } - dev = qdev_create(NULL, "arm-smmuv3"); + dev = qdev_new("arm-smmuv3"); - object_property_set_link(OBJECT(dev), OBJECT(bus), "primary-bus", + object_property_set_link(OBJECT(dev), "primary-bus", OBJECT(bus), &error_abort); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); for (i = 0; i < NUM_SMMU_IRQS; i++) { sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, @@ -1253,8 +1244,8 @@ static void create_pcie(VirtMachineState *vms) int i, ecam_id; PCIHostState *pci; - dev = qdev_create(NULL, TYPE_GPEX_HOST); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_GPEX_HOST); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); ecam_id = VIRT_ECAM_ID(vms->highmem_ecam); base_ecam = vms->memmap[ecam_id].base; @@ -1372,11 +1363,11 @@ static void create_platform_bus(VirtMachineState *vms) int i; MemoryRegion *sysmem = get_system_memory(); - dev = qdev_create(NULL, TYPE_PLATFORM_BUS_DEVICE); + dev = qdev_new(TYPE_PLATFORM_BUS_DEVICE); dev->id = TYPE_PLATFORM_BUS_DEVICE; qdev_prop_set_uint32(dev, "num_irqs", PLATFORM_BUS_NUM_IRQS); qdev_prop_set_uint32(dev, "mmio_size", vms->memmap[VIRT_PLATFORM_BUS].size); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); vms->platform_bus_dev = dev; s = SYS_BUS_DEVICE(dev); @@ -1390,8 +1381,19 @@ static void create_platform_bus(VirtMachineState *vms) sysbus_mmio_get_region(s, 0)); } +static void create_tag_ram(MemoryRegion *tag_sysmem, + hwaddr base, hwaddr size, + const char *name) +{ + MemoryRegion *tagram = g_new(MemoryRegion, 1); + + memory_region_init_ram(tagram, NULL, name, size / 32, &error_fatal); + memory_region_add_subregion(tag_sysmem, base / 32, tagram); +} + static void create_secure_ram(VirtMachineState *vms, - MemoryRegion *secure_sysmem) + MemoryRegion *secure_sysmem, + MemoryRegion *secure_tag_sysmem) { MemoryRegion *secram = g_new(MemoryRegion, 1); char *nodename; @@ -1409,6 +1411,10 @@ static void create_secure_ram(VirtMachineState *vms, qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled"); qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay"); + if (secure_tag_sysmem) { + create_tag_ram(secure_tag_sysmem, base, size, "mach-virt.secure-tag"); + } + g_free(nodename); } @@ -1657,6 +1663,72 @@ static void finalize_gic_version(VirtMachineState *vms) } } +/* + * virt_cpu_post_init() must be called after the CPUs have + * been realized and the GIC has been created. + */ +static void virt_cpu_post_init(VirtMachineState *vms, int max_cpus, + MemoryRegion *sysmem) +{ + bool aarch64, pmu, steal_time; + CPUState *cpu; + + aarch64 = object_property_get_bool(OBJECT(first_cpu), "aarch64", NULL); + pmu = object_property_get_bool(OBJECT(first_cpu), "pmu", NULL); + steal_time = object_property_get_bool(OBJECT(first_cpu), + "kvm-steal-time", NULL); + + if (kvm_enabled()) { + hwaddr pvtime_reg_base = vms->memmap[VIRT_PVTIME].base; + hwaddr pvtime_reg_size = vms->memmap[VIRT_PVTIME].size; + + if (steal_time) { + MemoryRegion *pvtime = g_new(MemoryRegion, 1); + hwaddr pvtime_size = max_cpus * PVTIME_SIZE_PER_CPU; + + /* The memory region size must be a multiple of host page size. */ + pvtime_size = REAL_HOST_PAGE_ALIGN(pvtime_size); + + if (pvtime_size > pvtime_reg_size) { + error_report("pvtime requires a %" HWADDR_PRId + " byte memory region for %d CPUs," + " but only %" HWADDR_PRId " has been reserved", + pvtime_size, max_cpus, pvtime_reg_size); + exit(1); + } + + memory_region_init_ram(pvtime, NULL, "pvtime", pvtime_size, NULL); + memory_region_add_subregion(sysmem, pvtime_reg_base, pvtime); + } + + CPU_FOREACH(cpu) { + if (pmu) { + assert(arm_feature(&ARM_CPU(cpu)->env, ARM_FEATURE_PMU)); + if (kvm_irqchip_in_kernel()) { + kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ)); + } + kvm_arm_pmu_init(cpu); + } + if (steal_time) { + kvm_arm_pvtime_init(cpu, pvtime_reg_base + + cpu->cpu_index * PVTIME_SIZE_PER_CPU); + } + } + } else { + if (aarch64 && vms->highmem) { + int requested_pa_size = 64 - clz64(vms->highest_gpa); + int pamax = arm_pamax(ARM_CPU(first_cpu)); + + if (pamax < requested_pa_size) { + error_report("VCPU supports less PA bits (%d) than " + "requested by the memory map (%d)", + pamax, requested_pa_size); + exit(1); + } + } + } +} + static void machvirt_init(MachineState *machine) { VirtMachineState *vms = VIRT_MACHINE(machine); @@ -1665,6 +1737,8 @@ static void machvirt_init(MachineState *machine) const CPUArchIdList *possible_cpus; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *secure_sysmem = NULL; + MemoryRegion *tag_sysmem = NULL; + MemoryRegion *secure_tag_sysmem = NULL; int n, virt_max_cpus; bool firmware_loaded; bool aarch64 = true; @@ -1756,6 +1830,12 @@ static void machvirt_init(MachineState *machine) exit(1); } + if (vms->mte && kvm_enabled()) { + error_report("mach-virt: KVM does not support providing " + "MTE to the guest CPU"); + exit(1); + } + create_fdt(vms); possible_cpus = mc->possible_cpu_arch_ids(machine); @@ -1768,8 +1848,8 @@ static void machvirt_init(MachineState *machine) } cpuobj = object_new(possible_cpus->cpus[n].type); - object_property_set_int(cpuobj, possible_cpus->cpus[n].arch_id, - "mp-affinity", NULL); + object_property_set_int(cpuobj, "mp-affinity", + possible_cpus->cpus[n].arch_id, NULL); cs = CPU(cpuobj); cs->cpu_index = n; @@ -1780,66 +1860,93 @@ static void machvirt_init(MachineState *machine) aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL); if (!vms->secure) { - object_property_set_bool(cpuobj, false, "has_el3", NULL); + object_property_set_bool(cpuobj, "has_el3", false, NULL); } - if (!vms->virt && object_property_find(cpuobj, "has_el2", NULL)) { - object_property_set_bool(cpuobj, false, "has_el2", NULL); + if (!vms->virt && object_property_find(cpuobj, "has_el2")) { + object_property_set_bool(cpuobj, "has_el2", false, NULL); } if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) { - object_property_set_int(cpuobj, vms->psci_conduit, - "psci-conduit", NULL); + object_property_set_int(cpuobj, "psci-conduit", vms->psci_conduit, + NULL); /* Secondary CPUs start in PSCI powered-down state */ if (n > 0) { - object_property_set_bool(cpuobj, true, - "start-powered-off", NULL); + object_property_set_bool(cpuobj, "start-powered-off", true, + NULL); } } if (vmc->kvm_no_adjvtime && - object_property_find(cpuobj, "kvm-no-adjvtime", NULL)) { - object_property_set_bool(cpuobj, true, "kvm-no-adjvtime", NULL); + object_property_find(cpuobj, "kvm-no-adjvtime")) { + object_property_set_bool(cpuobj, "kvm-no-adjvtime", true, NULL); } - if (vmc->no_pmu && object_property_find(cpuobj, "pmu", NULL)) { - object_property_set_bool(cpuobj, false, "pmu", NULL); + if (vmc->no_kvm_steal_time && + object_property_find(cpuobj, "kvm-steal-time")) { + object_property_set_bool(cpuobj, "kvm-steal-time", false, NULL); } - if (object_property_find(cpuobj, "reset-cbar", NULL)) { - object_property_set_int(cpuobj, vms->memmap[VIRT_CPUPERIPHS].base, - "reset-cbar", &error_abort); + if (vmc->no_pmu && object_property_find(cpuobj, "pmu")) { + object_property_set_bool(cpuobj, "pmu", false, NULL); } - object_property_set_link(cpuobj, OBJECT(sysmem), "memory", + if (object_property_find(cpuobj, "reset-cbar")) { + object_property_set_int(cpuobj, "reset-cbar", + vms->memmap[VIRT_CPUPERIPHS].base, + &error_abort); + } + + object_property_set_link(cpuobj, "memory", OBJECT(sysmem), &error_abort); if (vms->secure) { - object_property_set_link(cpuobj, OBJECT(secure_sysmem), - "secure-memory", &error_abort); + object_property_set_link(cpuobj, "secure-memory", + OBJECT(secure_sysmem), &error_abort); } - object_property_set_bool(cpuobj, true, "realized", &error_fatal); - object_unref(cpuobj); - } - fdt_add_timer_nodes(vms); - fdt_add_cpu_nodes(vms); - - if (!kvm_enabled()) { - ARMCPU *cpu = ARM_CPU(first_cpu); - bool aarch64 = object_property_get_bool(OBJECT(cpu), "aarch64", NULL); - - if (aarch64 && vms->highmem) { - int requested_pa_size, pamax = arm_pamax(cpu); + if (vms->mte) { + /* Create the memory region only once, but link to all cpus. */ + if (!tag_sysmem) { + /* + * The property exists only if MemTag is supported. + * If it is, we must allocate the ram to back that up. + */ + if (!object_property_find(cpuobj, "tag-memory")) { + error_report("MTE requested, but not supported " + "by the guest CPU"); + exit(1); + } + + tag_sysmem = g_new(MemoryRegion, 1); + memory_region_init(tag_sysmem, OBJECT(machine), + "tag-memory", UINT64_MAX / 32); + + if (vms->secure) { + secure_tag_sysmem = g_new(MemoryRegion, 1); + memory_region_init(secure_tag_sysmem, OBJECT(machine), + "secure-tag-memory", UINT64_MAX / 32); + + /* As with ram, secure-tag takes precedence over tag. */ + memory_region_add_subregion_overlap(secure_tag_sysmem, 0, + tag_sysmem, -1); + } + } - requested_pa_size = 64 - clz64(vms->highest_gpa); - if (pamax < requested_pa_size) { - error_report("VCPU supports less PA bits (%d) than requested " - "by the memory map (%d)", pamax, requested_pa_size); - exit(1); + object_property_set_link(cpuobj, "tag-memory", OBJECT(tag_sysmem), + &error_abort); + if (vms->secure) { + object_property_set_link(cpuobj, "secure-tag-memory", + OBJECT(secure_tag_sysmem), + &error_abort); } } + + qdev_realize(DEVICE(cpuobj), NULL, &error_fatal); + object_unref(cpuobj); } + fdt_add_timer_nodes(vms); + fdt_add_cpu_nodes(vms); memory_region_add_subregion(sysmem, vms->memmap[VIRT_MEM].base, machine->ram); @@ -1852,15 +1959,22 @@ static void machvirt_init(MachineState *machine) create_gic(vms); + virt_cpu_post_init(vms, possible_cpus->len, sysmem); + fdt_add_pmu_nodes(vms); create_uart(vms, VIRT_UART, sysmem, serial_hd(0)); if (vms->secure) { - create_secure_ram(vms, secure_sysmem); + create_secure_ram(vms, secure_sysmem, secure_tag_sysmem); create_uart(vms, VIRT_SECURE_UART, secure_sysmem, serial_hd(1)); } + if (tag_sysmem) { + create_tag_ram(tag_sysmem, vms->memmap[VIRT_MEM].base, + machine->ram_size, "mach-virt.tag"); + } + vms->highmem_ecam &= vms->highmem && (!firmware_loaded || aarch64); create_rtc(vms); @@ -2008,6 +2122,20 @@ static void virt_set_ras(Object *obj, bool value, Error **errp) vms->ras = value; } +static bool virt_get_mte(Object *obj, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(obj); + + return vms->mte; +} + +static void virt_set_mte(Object *obj, bool value, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(obj); + + vms->mte = value; +} + static char *virt_get_gic_version(Object *obj, Error **errp) { VirtMachineState *vms = VIRT_MACHINE(obj); @@ -2114,6 +2242,11 @@ static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, return; } + if (vms->mte) { + error_setg(errp, "memory hotplug is not enabled: MTE is enabled"); + return; + } + if (is_nvdimm && !ms->nvdimms_state->is_enabled) { error_setg(errp, "nvdimm is not enabled: add 'nvdimm=on' to '-M'"); return; @@ -2128,12 +2261,8 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev, VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); MachineState *ms = MACHINE(hotplug_dev); bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); - Error *local_err = NULL; - pc_dimm_plug(PC_DIMM(dev), MACHINE(vms), &local_err); - if (local_err) { - goto out; - } + pc_dimm_plug(PC_DIMM(dev), MACHINE(vms)); if (is_nvdimm) { nvdimm_plug(ms->nvdimms_state); @@ -2141,16 +2270,41 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev, hotplug_handler_plug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &error_abort); - -out: - error_propagate(errp, local_err); } static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { + VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { virt_memory_pre_plug(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { + hwaddr db_start = 0, db_end = 0; + char *resv_prop_str; + + switch (vms->msi_controller) { + case VIRT_MSI_CTRL_NONE: + return; + case VIRT_MSI_CTRL_ITS: + /* GITS_TRANSLATER page */ + db_start = base_memmap[VIRT_GIC_ITS].base + 0x10000; + db_end = base_memmap[VIRT_GIC_ITS].base + + base_memmap[VIRT_GIC_ITS].size - 1; + break; + case VIRT_MSI_CTRL_GICV2M: + /* MSI_SETSPI_NS page */ + db_start = base_memmap[VIRT_GIC_V2M].base; + db_end = db_start + base_memmap[VIRT_GIC_V2M].size - 1; + break; + } + resv_prop_str = g_strdup_printf("0x%"PRIx64":0x%"PRIx64":%u", + db_start, db_end, + VIRTIO_IOMMU_RESV_MEM_T_MSI); + + qdev_prop_set_uint32(dev, "len-reserved-regions", 1); + qdev_prop_set_string(dev, "reserved-regions[0]", resv_prop_str); + g_free(resv_prop_str); } } @@ -2177,11 +2331,68 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, } } +static void virt_dimm_unplug_request(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); + Error *local_err = NULL; + + if (!vms->acpi_dev) { + error_setg(&local_err, + "memory hotplug is not enabled: missing acpi-ged device"); + goto out; + } + + if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { + error_setg(&local_err, + "nvdimm device hot unplug is not supported yet."); + goto out; + } + + hotplug_handler_unplug_request(HOTPLUG_HANDLER(vms->acpi_dev), dev, + &local_err); +out: + error_propagate(errp, local_err); +} + +static void virt_dimm_unplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); + Error *local_err = NULL; + + hotplug_handler_unplug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &local_err); + if (local_err) { + goto out; + } + + pc_dimm_unplug(PC_DIMM(dev), MACHINE(vms)); + qdev_unrealize(dev); + +out: + error_propagate(errp, local_err); +} + static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - error_setg(errp, "device unplug request for unsupported device" - " type: %s", object_get_typename(OBJECT(dev))); + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + virt_dimm_unplug_request(hotplug_dev, dev, errp); + } else { + error_setg(errp, "device unplug request for unsupported device" + " type: %s", object_get_typename(OBJECT(dev))); + } +} + +static void virt_machine_device_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + virt_dimm_unplug(hotplug_dev, dev, errp); + } else { + error_setg(errp, "virt: device unplug for unsupported device" + " type: %s", object_get_typename(OBJECT(dev))); + } } static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, @@ -2262,9 +2473,10 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) hc->pre_plug = virt_machine_device_pre_plug_cb; hc->plug = virt_machine_device_plug_cb; hc->unplug_request = virt_machine_device_unplug_request_cb; - mc->numa_mem_supported = true; + hc->unplug = virt_machine_device_unplug_cb; mc->nvdimm_supported = true; mc->auto_enable_numa_with_memhp = true; + mc->auto_enable_numa_with_memdev = true; mc->default_ram_id = "mach-virt.ram"; object_class_property_add(oc, "acpi", "OnOffAuto", @@ -2342,6 +2554,14 @@ static void virt_instance_init(Object *obj) "Set on/off to enable/disable reporting host memory errors " "to a KVM guest using ACPI and guest external abort exceptions"); + /* MTE is disabled by default. */ + vms->mte = false; + object_property_add_bool(obj, "mte", virt_get_mte, virt_set_mte); + object_property_set_description(obj, "mte", + "Set on/off to enable/disable emulating a " + "guest CPU which implements the ARM " + "Memory Tagging Extension"); + vms->irqmap = a15irqmap; virt_flash_create(vms); @@ -2367,14 +2587,31 @@ static void machvirt_machine_init(void) } type_init(machvirt_machine_init); +static void virt_machine_5_2_options(MachineClass *mc) +{ +} +DEFINE_VIRT_MACHINE_AS_LATEST(5, 2) + static void virt_machine_5_1_options(MachineClass *mc) { + VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); + + virt_machine_5_2_options(mc); + compat_props_add(mc->compat_props, hw_compat_5_1, hw_compat_5_1_len); + vmc->no_kvm_steal_time = true; } -DEFINE_VIRT_MACHINE_AS_LATEST(5, 1) +DEFINE_VIRT_MACHINE(5, 1) static void virt_machine_5_0_options(MachineClass *mc) { + VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); + virt_machine_5_1_options(mc); + compat_props_add(mc->compat_props, hw_compat_5_0, hw_compat_5_0_len); + mc->numa_mem_supported = true; + mc->auto_enable_numa_with_memdev = false; + vmc->acpi_expose_flash = true; + mc->auto_enable_numa_with_memdev = false; } DEFINE_VIRT_MACHINE(5, 0) diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c index cb933efb49ad0927186f12d25ac071e6f6507ef3..b72772bc8245e6b3971f91dbbea6c7bc90772cc9 100644 --- a/hw/arm/xilinx_zynq.c +++ b/hw/arm/xilinx_zynq.c @@ -37,10 +37,10 @@ #include "hw/cpu/a9mpcore.h" #include "hw/qdev-clock.h" #include "sysemu/reset.h" +#include "qom/object.h" #define TYPE_ZYNQ_MACHINE MACHINE_TYPE_NAME("xilinx-zynq-a9") -#define ZYNQ_MACHINE(obj) \ - OBJECT_CHECK(ZynqMachineState, (obj), TYPE_ZYNQ_MACHINE) +OBJECT_DECLARE_SIMPLE_TYPE(ZynqMachineState, ZYNQ_MACHINE) /* board base frequency: 33.333333 MHz */ #define PS_CLK_FREQUENCY (100 * 1000 * 1000 / 3) @@ -84,10 +84,10 @@ static const int dma_irqs[8] = { 0xe3401000 + ARMV7_IMM16(extract32((val), 16, 16)), /* movt r1 ... */ \ 0xe5801000 + (addr) -typedef struct ZynqMachineState { +struct ZynqMachineState { MachineState parent; Clock *ps_clk; -} ZynqMachineState; +}; static void zynq_write_board_setup(ARMCPU *cpu, const struct arm_boot_info *info) @@ -114,13 +114,14 @@ static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq) DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, TYPE_CADENCE_GEM); + dev = qdev_new(TYPE_CADENCE_GEM); if (nd->used) { qemu_check_nic_model(nd, TYPE_CADENCE_GEM); qdev_set_nic_properties(dev, nd); } - qdev_init_nofail(dev); + object_property_set_int(OBJECT(dev), "phy-addr", 23, &error_abort); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, base); sysbus_connect_irq(s, 0, irq); } @@ -136,12 +137,12 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq, int num_busses = is_qspi ? NUM_QSPI_BUSSES : 1; int num_ss = is_qspi ? NUM_QSPI_FLASHES : NUM_SPI_FLASHES; - dev = qdev_create(NULL, is_qspi ? "xlnx.ps7-qspi" : "xlnx.ps7-spi"); + dev = qdev_new(is_qspi ? "xlnx.ps7-qspi" : "xlnx.ps7-spi"); qdev_prop_set_uint8(dev, "num-txrx-bytes", is_qspi ? 4 : 1); qdev_prop_set_uint8(dev, "num-ss-bits", num_ss); qdev_prop_set_uint8(dev, "num-busses", num_busses); - qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, base_addr); if (is_qspi) { sysbus_mmio_map(busdev, 1, 0xFC000000); @@ -157,12 +158,13 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq, for (j = 0; j < num_ss; ++j) { DriveInfo *dinfo = drive_get_next(IF_MTD); - flash_dev = ssi_create_slave_no_init(spi, "n25q128"); + flash_dev = qdev_new("n25q128"); if (dinfo) { - qdev_prop_set_drive(flash_dev, "drive", - blk_by_legacy_dinfo(dinfo), &error_fatal); + qdev_prop_set_drive_err(flash_dev, "drive", + blk_by_legacy_dinfo(dinfo), + &error_fatal); } - qdev_init_nofail(flash_dev); + qdev_realize_and_unref(flash_dev, BUS(spi), &error_fatal); cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0); sysbus_connect_irq(busdev, i * num_ss + j + 1, cs_line); @@ -194,15 +196,15 @@ static void zynq_init(MachineState *machine) * currently support EL3 so the CPU EL3 property is disabled before * realization. */ - if (object_property_find(OBJECT(cpu), "has_el3", NULL)) { - object_property_set_bool(OBJECT(cpu), false, "has_el3", &error_fatal); + if (object_property_find(OBJECT(cpu), "has_el3")) { + object_property_set_bool(OBJECT(cpu), "has_el3", false, &error_fatal); } - object_property_set_int(OBJECT(cpu), ZYNQ_BOARD_MIDR, "midr", + object_property_set_int(OBJECT(cpu), "midr", ZYNQ_BOARD_MIDR, &error_fatal); - object_property_set_int(OBJECT(cpu), MPCORE_PERIPHBASE, "reset-cbar", + object_property_set_int(OBJECT(cpu), "reset-cbar", MPCORE_PERIPHBASE, &error_fatal); - object_property_set_bool(OBJECT(cpu), true, "realized", &error_fatal); + qdev_realize(DEVICE(cpu), NULL, &error_fatal); /* DDR remapped to address zero. */ memory_region_add_subregion(address_space_mem, 0, machine->ram); @@ -221,23 +223,23 @@ static void zynq_init(MachineState *machine) 1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa, 0); - /* Create slcr, keep a pointer to connect clocks */ - slcr = qdev_create(NULL, "xilinx,zynq_slcr"); - qdev_init_nofail(slcr); - sysbus_mmio_map(SYS_BUS_DEVICE(slcr), 0, 0xF8000000); - /* Create the main clock source, and feed slcr with it */ zynq_machine->ps_clk = CLOCK(object_new(TYPE_CLOCK)); object_property_add_child(OBJECT(zynq_machine), "ps_clk", OBJECT(zynq_machine->ps_clk)); object_unref(OBJECT(zynq_machine->ps_clk)); clock_set_hz(zynq_machine->ps_clk, PS_CLK_FREQUENCY); + + /* Create slcr, keep a pointer to connect clocks */ + slcr = qdev_new("xilinx,zynq_slcr"); qdev_connect_clock_in(slcr, "ps_clk", zynq_machine->ps_clk); + sysbus_realize_and_unref(SYS_BUS_DEVICE(slcr), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(slcr), 0, 0xF8000000); - dev = qdev_create(NULL, TYPE_A9MPCORE_PRIV); + dev = qdev_new(TYPE_A9MPCORE_PRIV); qdev_prop_set_uint32(dev, "num-cpu", 1); - qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, MPCORE_PERIPHBASE); sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ)); @@ -253,12 +255,22 @@ static void zynq_init(MachineState *machine) sysbus_create_simple(TYPE_CHIPIDEA, 0xE0002000, pic[53 - IRQ_OFFSET]); sysbus_create_simple(TYPE_CHIPIDEA, 0xE0003000, pic[76 - IRQ_OFFSET]); - dev = cadence_uart_create(0xE0000000, pic[59 - IRQ_OFFSET], serial_hd(0)); + dev = qdev_new(TYPE_CADENCE_UART); + busdev = SYS_BUS_DEVICE(dev); + qdev_prop_set_chr(dev, "chardev", serial_hd(0)); qdev_connect_clock_in(dev, "refclk", qdev_get_clock_out(slcr, "uart0_ref_clk")); - dev = cadence_uart_create(0xE0001000, pic[82 - IRQ_OFFSET], serial_hd(1)); + sysbus_realize_and_unref(busdev, &error_fatal); + sysbus_mmio_map(busdev, 0, 0xE0000000); + sysbus_connect_irq(busdev, 0, pic[59 - IRQ_OFFSET]); + dev = qdev_new(TYPE_CADENCE_UART); + busdev = SYS_BUS_DEVICE(dev); + qdev_prop_set_chr(dev, "chardev", serial_hd(1)); qdev_connect_clock_in(dev, "refclk", qdev_get_clock_out(slcr, "uart1_ref_clk")); + sysbus_realize_and_unref(busdev, &error_fatal); + sysbus_mmio_map(busdev, 0, 0xE0001000); + sysbus_connect_irq(busdev, 0, pic[82 - IRQ_OFFSET]); sysbus_create_varargs("cadence_ttc", 0xF8001000, pic[42-IRQ_OFFSET], pic[43-IRQ_OFFSET], pic[44-IRQ_OFFSET], NULL); @@ -280,27 +292,27 @@ static void zynq_init(MachineState *machine) * - SDIO Specification Version 2.0 * - MMC Specification Version 3.31 */ - dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI); + dev = qdev_new(TYPE_SYSBUS_SDHCI); qdev_prop_set_uint8(dev, "sd-spec-version", 2); qdev_prop_set_uint64(dev, "capareg", ZYNQ_SDHCI_CAPABILITIES); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, hci_addr); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[hci_irq - IRQ_OFFSET]); di = drive_get_next(IF_SD); blk = di ? blk_by_legacy_dinfo(di) : NULL; - carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD); - qdev_prop_set_drive(carddev, "drive", blk, &error_fatal); - object_property_set_bool(OBJECT(carddev), true, "realized", - &error_fatal); + carddev = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal); + qdev_realize_and_unref(carddev, qdev_get_child_bus(dev, "sd-bus"), + &error_fatal); } - dev = qdev_create(NULL, TYPE_ZYNQ_XADC); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_ZYNQ_XADC); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xF8007100); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[39-IRQ_OFFSET]); - dev = qdev_create(NULL, "pl330"); + dev = qdev_new("pl330"); qdev_prop_set_uint8(dev, "num_chnls", 8); qdev_prop_set_uint8(dev, "num_periph_req", 4); qdev_prop_set_uint8(dev, "num_events", 16); @@ -312,17 +324,17 @@ static void zynq_init(MachineState *machine) qdev_prop_set_uint8(dev, "rd_q_dep", 16); qdev_prop_set_uint16(dev, "data_buffer_dep", 256); - qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, 0xF8003000); sysbus_connect_irq(busdev, 0, pic[45-IRQ_OFFSET]); /* abort irq line */ for (n = 0; n < ARRAY_SIZE(dma_irqs); ++n) { /* event irqs */ sysbus_connect_irq(busdev, n + 1, pic[dma_irqs[n] - IRQ_OFFSET]); } - dev = qdev_create(NULL, "xlnx.ps7-dev-cfg"); - qdev_init_nofail(dev); + dev = qdev_new("xlnx.ps7-dev-cfg"); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_connect_irq(busdev, 0, pic[40 - IRQ_OFFSET]); sysbus_mmio_map(busdev, 0, 0xF8007000); diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 43a71e2eea36e3692ec54209f47f5c5eddad9d93..ee1282241e37b363ae27188cce8c4dbfc00149bd 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -22,12 +22,12 @@ #include "cpu.h" #include "hw/qdev-properties.h" #include "hw/arm/xlnx-versal.h" +#include "qom/object.h" #define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt") -#define XLNX_VERSAL_VIRT_MACHINE(obj) \ - OBJECT_CHECK(VersalVirt, (obj), TYPE_XLNX_VERSAL_VIRT_MACHINE) +OBJECT_DECLARE_SIMPLE_TYPE(VersalVirt, XLNX_VERSAL_VIRT_MACHINE) -typedef struct VersalVirt { +struct VersalVirt { MachineState parent_obj; Versal soc; @@ -45,7 +45,7 @@ typedef struct VersalVirt { struct { bool secure; } cfg; -} VersalVirt; +}; static void fdt_create(VersalVirt *s) { @@ -212,7 +212,7 @@ static void fdt_add_gem_nodes(VersalVirt *s) s->phandle.ethernet_phy[i]); qemu_fdt_setprop_cells(s->fdt, name, "clocks", s->phandle.clk_25Mhz, s->phandle.clk_25Mhz, - s->phandle.clk_25Mhz, s->phandle.clk_25Mhz); + s->phandle.clk_125Mhz, s->phandle.clk_125Mhz); qemu_fdt_setprop(s->fdt, name, "clock-names", clocknames, sizeof(clocknames)); qemu_fdt_setprop_cells(s->fdt, name, "interrupts", @@ -432,9 +432,9 @@ static void create_virtio_regions(VersalVirt *s) qemu_irq pic_irq; pic_irq = qdev_get_gpio_in(DEVICE(&s->soc.fpd.apu.gic), irq); - dev = qdev_create(NULL, "virtio-mmio"); + dev = qdev_new("virtio-mmio"); object_property_add_child(OBJECT(&s->soc), name, OBJECT(dev)); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic_irq); mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); memory_region_add_subregion(&s->soc.mr_ps, base, mr); @@ -463,10 +463,11 @@ static void sd_plugin_card(SDHCIState *sd, DriveInfo *di) BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL; DeviceState *card; - card = qdev_create(qdev_get_child_bus(DEVICE(sd), "sd-bus"), TYPE_SD_CARD); + card = qdev_new(TYPE_SD_CARD); object_property_add_child(OBJECT(sd), "card[*]", OBJECT(card)); - qdev_prop_set_drive(card, "drive", blk, &error_fatal); - object_property_set_bool(OBJECT(card), true, "realized", &error_fatal); + qdev_prop_set_drive_err(card, "drive", blk, &error_fatal); + qdev_realize_and_unref(card, qdev_get_child_bus(DEVICE(sd), "sd-bus"), + &error_fatal); } static void versal_virt_init(MachineState *machine) @@ -499,13 +500,13 @@ static void versal_virt_init(MachineState *machine) psci_conduit = QEMU_PSCI_CONDUIT_SMC; } - sysbus_init_child_obj(OBJECT(machine), "xlnx-versal", &s->soc, - sizeof(s->soc), TYPE_XLNX_VERSAL); - object_property_set_link(OBJECT(&s->soc), OBJECT(machine->ram), - "ddr", &error_abort); - object_property_set_int(OBJECT(&s->soc), psci_conduit, - "psci-conduit", &error_abort); - object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal); + object_initialize_child(OBJECT(machine), "xlnx-versal", &s->soc, + TYPE_XLNX_VERSAL); + object_property_set_link(OBJECT(&s->soc), "ddr", OBJECT(machine->ram), + &error_abort); + object_property_set_int(OBJECT(&s->soc), "psci-conduit", psci_conduit, + &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal); fdt_create(s); create_virtio_regions(s); @@ -560,6 +561,7 @@ static void versal_virt_machine_class_init(ObjectClass *oc, void *data) mc->desc = "Xilinx Versal Virtual development board"; mc->init = versal_virt_init; + mc->min_cpus = XLNX_VERSAL_NR_ACPUS; mc->max_cpus = XLNX_VERSAL_NR_ACPUS; mc->default_cpus = XLNX_VERSAL_NR_ACPUS; mc->no_cdrom = true; diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 809a31390f794ff1297ed366cc0d2f8980d84af3..12ba6c4ebaea4b9a13732221206ba31a93abd339 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -32,23 +32,22 @@ static void versal_create_apu_cpus(Versal *s) for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) { Object *obj; - object_initialize_child(OBJECT(s), "apu-cpu[*]", - &s->fpd.apu.cpu[i], sizeof(s->fpd.apu.cpu[i]), - XLNX_VERSAL_ACPU_TYPE, &error_abort, NULL); + object_initialize_child(OBJECT(s), "apu-cpu[*]", &s->fpd.apu.cpu[i], + XLNX_VERSAL_ACPU_TYPE); obj = OBJECT(&s->fpd.apu.cpu[i]); - object_property_set_int(obj, s->cfg.psci_conduit, - "psci-conduit", &error_abort); + object_property_set_int(obj, "psci-conduit", s->cfg.psci_conduit, + &error_abort); if (i) { /* Secondary CPUs start in PSCI powered-down state */ - object_property_set_bool(obj, true, - "start-powered-off", &error_abort); + object_property_set_bool(obj, "start-powered-off", true, + &error_abort); } - object_property_set_int(obj, ARRAY_SIZE(s->fpd.apu.cpu), - "core-count", &error_abort); - object_property_set_link(obj, OBJECT(&s->fpd.apu.mr), "memory", + object_property_set_int(obj, "core-count", ARRAY_SIZE(s->fpd.apu.cpu), + &error_abort); + object_property_set_link(obj, "memory", OBJECT(&s->fpd.apu.mr), &error_abort); - object_property_set_bool(obj, true, "realized", &error_fatal); + qdev_realize(DEVICE(obj), NULL, &error_fatal); } } @@ -63,9 +62,8 @@ static void versal_create_apu_gic(Versal *s, qemu_irq *pic) int nr_apu_cpus = ARRAY_SIZE(s->fpd.apu.cpu); int i; - sysbus_init_child_obj(OBJECT(s), "apu-gic", - &s->fpd.apu.gic, sizeof(s->fpd.apu.gic), - gicv3_class_name()); + object_initialize_child(OBJECT(s), "apu-gic", &s->fpd.apu.gic, + gicv3_class_name()); gicbusdev = SYS_BUS_DEVICE(&s->fpd.apu.gic); gicdev = DEVICE(&s->fpd.apu.gic); qdev_prop_set_uint32(gicdev, "revision", 3); @@ -75,8 +73,7 @@ static void versal_create_apu_gic(Versal *s, qemu_irq *pic) qdev_prop_set_uint32(gicdev, "redist-region-count[0]", 2); qdev_prop_set_bit(gicdev, "has-security-extensions", true); - object_property_set_bool(OBJECT(&s->fpd.apu.gic), true, "realized", - &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(&s->fpd.apu.gic), &error_fatal); for (i = 0; i < ARRAY_SIZE(addrs); i++) { MemoryRegion *mr; @@ -134,12 +131,11 @@ static void versal_create_uarts(Versal *s, qemu_irq *pic) DeviceState *dev; MemoryRegion *mr; - sysbus_init_child_obj(OBJECT(s), name, - &s->lpd.iou.uart[i], sizeof(s->lpd.iou.uart[i]), - TYPE_PL011); + object_initialize_child(OBJECT(s), name, &s->lpd.iou.uart[i], + TYPE_PL011); dev = DEVICE(&s->lpd.iou.uart[i]); qdev_prop_set_chr(dev, "chardev", serial_hd(i)); - qdev_init_nofail(dev); + sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal); mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); memory_region_add_subregion(&s->mr_ps, addrs[i], mr); @@ -161,21 +157,20 @@ static void versal_create_gems(Versal *s, qemu_irq *pic) DeviceState *dev; MemoryRegion *mr; - sysbus_init_child_obj(OBJECT(s), name, - &s->lpd.iou.gem[i], sizeof(s->lpd.iou.gem[i]), - TYPE_CADENCE_GEM); + object_initialize_child(OBJECT(s), name, &s->lpd.iou.gem[i], + TYPE_CADENCE_GEM); dev = DEVICE(&s->lpd.iou.gem[i]); + /* FIXME use qdev NIC properties instead of nd_table[] */ if (nd->used) { qemu_check_nic_model(nd, "cadence_gem"); qdev_set_nic_properties(dev, nd); } - object_property_set_int(OBJECT(dev), - 2, "num-priority-queues", + object_property_set_int(OBJECT(dev), "phy-addr", 23, &error_abort); + object_property_set_int(OBJECT(dev), "num-priority-queues", 2, &error_abort); - object_property_set_link(OBJECT(dev), - OBJECT(&s->mr_ps), "dma", + object_property_set_link(OBJECT(dev), "dma", OBJECT(&s->mr_ps), &error_abort); - qdev_init_nofail(dev); + sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal); mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); memory_region_add_subregion(&s->mr_ps, addrs[i], mr); @@ -194,12 +189,11 @@ static void versal_create_admas(Versal *s, qemu_irq *pic) DeviceState *dev; MemoryRegion *mr; - sysbus_init_child_obj(OBJECT(s), name, - &s->lpd.iou.adma[i], sizeof(s->lpd.iou.adma[i]), - TYPE_XLNX_ZDMA); + object_initialize_child(OBJECT(s), name, &s->lpd.iou.adma[i], + TYPE_XLNX_ZDMA); dev = DEVICE(&s->lpd.iou.adma[i]); - object_property_set_int(OBJECT(dev), 128, "bus-width", &error_abort); - qdev_init_nofail(dev); + object_property_set_int(OBJECT(dev), "bus-width", 128, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal); mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); memory_region_add_subregion(&s->mr_ps, @@ -219,17 +213,16 @@ static void versal_create_sds(Versal *s, qemu_irq *pic) DeviceState *dev; MemoryRegion *mr; - sysbus_init_child_obj(OBJECT(s), "sd[*]", - &s->pmc.iou.sd[i], sizeof(s->pmc.iou.sd[i]), - TYPE_SYSBUS_SDHCI); + object_initialize_child(OBJECT(s), "sd[*]", &s->pmc.iou.sd[i], + TYPE_SYSBUS_SDHCI); dev = DEVICE(&s->pmc.iou.sd[i]); - object_property_set_uint(OBJECT(dev), - 3, "sd-spec-version", &error_fatal); - object_property_set_uint(OBJECT(dev), SDHCI_CAPABILITIES, "capareg", + object_property_set_uint(OBJECT(dev), "sd-spec-version", 3, + &error_fatal); + object_property_set_uint(OBJECT(dev), "capareg", SDHCI_CAPABILITIES, &error_fatal); - object_property_set_uint(OBJECT(dev), UHS_I, "uhs", &error_fatal); - qdev_init_nofail(dev); + object_property_set_uint(OBJECT(dev), "uhs", UHS_I, &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal); mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); memory_region_add_subregion(&s->mr_ps, @@ -245,10 +238,10 @@ static void versal_create_rtc(Versal *s, qemu_irq *pic) SysBusDevice *sbd; MemoryRegion *mr; - sysbus_init_child_obj(OBJECT(s), "rtc", &s->pmc.rtc, sizeof(s->pmc.rtc), - TYPE_XLNX_ZYNQMP_RTC); + object_initialize_child(OBJECT(s), "rtc", &s->pmc.rtc, + TYPE_XLNX_ZYNQMP_RTC); sbd = SYS_BUS_DEVICE(&s->pmc.rtc); - qdev_init_nofail(DEVICE(sbd)); + sysbus_realize(SYS_BUS_DEVICE(sbd), &error_fatal); mr = sysbus_mmio_get_region(sbd, 0); memory_region_add_subregion(&s->mr_ps, MM_PMC_RTC, mr); @@ -304,13 +297,13 @@ static void versal_unimp_area(Versal *s, const char *name, MemoryRegion *mr, hwaddr base, hwaddr size) { - DeviceState *dev = qdev_create(NULL, TYPE_UNIMPLEMENTED_DEVICE); + DeviceState *dev = qdev_new(TYPE_UNIMPLEMENTED_DEVICE); MemoryRegion *mr_dev; qdev_prop_set_string(dev, "name", name); qdev_prop_set_uint64(dev, "size", size); object_property_add_child(OBJECT(s), name, OBJECT(dev)); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); mr_dev = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); memory_region_add_subregion(mr, base, mr_dev); diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c index b01e575b588beab1da5e887a7da5f2b9cf1fb2f4..ad7fff9697b4bedd09adab206eed635ad1957e24 100644 --- a/hw/arm/xlnx-zcu102.c +++ b/hw/arm/xlnx-zcu102.c @@ -24,8 +24,9 @@ #include "qemu/log.h" #include "sysemu/qtest.h" #include "sysemu/device_tree.h" +#include "qom/object.h" -typedef struct XlnxZCU102 { +struct XlnxZCU102 { MachineState parent_obj; XlnxZynqMPState soc; @@ -34,11 +35,10 @@ typedef struct XlnxZCU102 { bool virt; struct arm_boot_info binfo; -} XlnxZCU102; +}; #define TYPE_ZCU102_MACHINE MACHINE_TYPE_NAME("xlnx-zcu102") -#define ZCU102_MACHINE(obj) \ - OBJECT_CHECK(XlnxZCU102, (obj), TYPE_ZCU102_MACHINE) +OBJECT_DECLARE_SIMPLE_TYPE(XlnxZCU102, ZCU102_MACHINE) static bool zcu102_get_secure(Object *obj, Error **errp) @@ -116,17 +116,16 @@ static void xlnx_zcu102_init(MachineState *machine) ram_size); } - object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), - TYPE_XLNX_ZYNQMP, &error_abort, NULL); + object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_XLNX_ZYNQMP); - object_property_set_link(OBJECT(&s->soc), OBJECT(machine->ram), - "ddr-ram", &error_abort); - object_property_set_bool(OBJECT(&s->soc), s->secure, "secure", + object_property_set_link(OBJECT(&s->soc), "ddr-ram", OBJECT(machine->ram), + &error_abort); + object_property_set_bool(OBJECT(&s->soc), "secure", s->secure, &error_fatal); - object_property_set_bool(OBJECT(&s->soc), s->virt, "virtualization", + object_property_set_bool(OBJECT(&s->soc), "virtualization", s->virt, &error_fatal); - object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal); + qdev_realize(DEVICE(&s->soc), NULL, &error_fatal); /* Create and plug in the SD cards */ for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) { @@ -143,28 +142,27 @@ static void xlnx_zcu102_init(MachineState *machine) error_report("No SD bus found for SD card %d", i); exit(1); } - carddev = qdev_create(bus, TYPE_SD_CARD); - qdev_prop_set_drive(carddev, "drive", blk, &error_fatal); - object_property_set_bool(OBJECT(carddev), true, "realized", - &error_fatal); + carddev = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal); + qdev_realize_and_unref(carddev, bus, &error_fatal); } for (i = 0; i < XLNX_ZYNQMP_NUM_SPIS; i++) { - SSIBus *spi_bus; + BusState *spi_bus; DeviceState *flash_dev; qemu_irq cs_line; DriveInfo *dinfo = drive_get_next(IF_MTD); gchar *bus_name = g_strdup_printf("spi%d", i); - spi_bus = (SSIBus *)qdev_get_child_bus(DEVICE(&s->soc), bus_name); + spi_bus = qdev_get_child_bus(DEVICE(&s->soc), bus_name); g_free(bus_name); - flash_dev = ssi_create_slave_no_init(spi_bus, "sst25wf080"); + flash_dev = qdev_new("sst25wf080"); if (dinfo) { - qdev_prop_set_drive(flash_dev, "drive", blk_by_legacy_dinfo(dinfo), - &error_fatal); + qdev_prop_set_drive_err(flash_dev, "drive", + blk_by_legacy_dinfo(dinfo), &error_fatal); } - qdev_init_nofail(flash_dev); + qdev_realize_and_unref(flash_dev, spi_bus, &error_fatal); cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0); @@ -172,22 +170,22 @@ static void xlnx_zcu102_init(MachineState *machine) } for (i = 0; i < XLNX_ZYNQMP_NUM_QSPI_FLASH; i++) { - SSIBus *spi_bus; + BusState *spi_bus; DeviceState *flash_dev; qemu_irq cs_line; DriveInfo *dinfo = drive_get_next(IF_MTD); int bus = i / XLNX_ZYNQMP_NUM_QSPI_BUS_CS; gchar *bus_name = g_strdup_printf("qspi%d", bus); - spi_bus = (SSIBus *)qdev_get_child_bus(DEVICE(&s->soc), bus_name); + spi_bus = qdev_get_child_bus(DEVICE(&s->soc), bus_name); g_free(bus_name); - flash_dev = ssi_create_slave_no_init(spi_bus, "n25q512a11"); + flash_dev = qdev_new("n25q512a11"); if (dinfo) { - qdev_prop_set_drive(flash_dev, "drive", blk_by_legacy_dinfo(dinfo), - &error_fatal); + qdev_prop_set_drive_err(flash_dev, "drive", + blk_by_legacy_dinfo(dinfo), &error_fatal); } - qdev_init_nofail(flash_dev); + qdev_realize_and_unref(flash_dev, spi_bus, &error_fatal); cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0); @@ -208,20 +206,8 @@ static void xlnx_zcu102_machine_instance_init(Object *obj) /* Default to secure mode being disabled */ s->secure = false; - object_property_add_bool(obj, "secure", zcu102_get_secure, - zcu102_set_secure); - object_property_set_description(obj, "secure", - "Set on/off to enable/disable the ARM " - "Security Extensions (TrustZone)"); - /* Default to virt (EL2) being disabled */ s->virt = false; - object_property_add_bool(obj, "virtualization", zcu102_get_virt, - zcu102_set_virt); - object_property_set_description(obj, "virtualization", - "Set on/off to enable/disable emulating a " - "guest CPU which implements the ARM " - "Virtualization Extensions"); } static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data) @@ -237,10 +223,23 @@ static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data) mc->max_cpus = XLNX_ZYNQMP_NUM_APU_CPUS + XLNX_ZYNQMP_NUM_RPU_CPUS; mc->default_cpus = XLNX_ZYNQMP_NUM_APU_CPUS; mc->default_ram_id = "ddr-ram"; + + object_class_property_add_bool(oc, "secure", zcu102_get_secure, + zcu102_set_secure); + object_class_property_set_description(oc, "secure", + "Set on/off to enable/disable the ARM " + "Security Extensions (TrustZone)"); + + object_class_property_add_bool(oc, "virtualization", zcu102_get_virt, + zcu102_set_virt); + object_class_property_set_description(oc, "virtualization", + "Set on/off to enable/disable emulating a " + "guest CPU which implements the ARM " + "Virtualization Extensions"); } static const TypeInfo xlnx_zcu102_machine_init_typeinfo = { - .name = MACHINE_TYPE_NAME("xlnx-zcu102"), + .name = TYPE_ZCU102_MACHINE, .parent = TYPE_MACHINE, .class_init = xlnx_zcu102_machine_class_init, .instance_init = xlnx_zcu102_machine_instance_init, diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index f08abf60d7329e71714a393e8456c52ae28dd083..7885bb1774538ccfdc55a695cfca0aa6915b30ba 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -176,7 +176,6 @@ static inline int arm_gic_ppi_index(int cpu_nr, int ppi_index) static void xlnx_zynqmp_create_rpu(MachineState *ms, XlnxZynqMPState *s, const char *boot_cpu, Error **errp) { - Error *err = NULL; int i; int num_rpus = MIN(ms->smp.cpus - XLNX_ZYNQMP_NUM_APU_CPUS, XLNX_ZYNQMP_NUM_RPU_CPUS); @@ -187,39 +186,33 @@ static void xlnx_zynqmp_create_rpu(MachineState *ms, XlnxZynqMPState *s, } object_initialize_child(OBJECT(s), "rpu-cluster", &s->rpu_cluster, - sizeof(s->rpu_cluster), TYPE_CPU_CLUSTER, - &error_abort, NULL); + TYPE_CPU_CLUSTER); qdev_prop_set_uint32(DEVICE(&s->rpu_cluster), "cluster-id", 1); for (i = 0; i < num_rpus; i++) { - char *name; + const char *name; object_initialize_child(OBJECT(&s->rpu_cluster), "rpu-cpu[*]", - &s->rpu_cpu[i], sizeof(s->rpu_cpu[i]), - ARM_CPU_TYPE_NAME("cortex-r5f"), - &error_abort, NULL); + &s->rpu_cpu[i], + ARM_CPU_TYPE_NAME("cortex-r5f")); name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i])); if (strcmp(name, boot_cpu)) { /* Secondary CPUs start in PSCI powered-down state */ - object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, - "start-powered-off", &error_abort); + object_property_set_bool(OBJECT(&s->rpu_cpu[i]), + "start-powered-off", true, &error_abort); } else { s->boot_cpu_ptr = &s->rpu_cpu[i]; } - g_free(name); - object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "reset-hivecs", + object_property_set_bool(OBJECT(&s->rpu_cpu[i]), "reset-hivecs", true, &error_abort); - object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "realized", - &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->rpu_cpu[i]), NULL, errp)) { return; } } - qdev_init_nofail(DEVICE(&s->rpu_cluster)); + qdev_realize(DEVICE(&s->rpu_cluster), NULL, &error_fatal); } static void xlnx_zynqmp_init(Object *obj) @@ -230,65 +223,53 @@ static void xlnx_zynqmp_init(Object *obj) int num_apus = MIN(ms->smp.cpus, XLNX_ZYNQMP_NUM_APU_CPUS); object_initialize_child(obj, "apu-cluster", &s->apu_cluster, - sizeof(s->apu_cluster), TYPE_CPU_CLUSTER, - &error_abort, NULL); + TYPE_CPU_CLUSTER); qdev_prop_set_uint32(DEVICE(&s->apu_cluster), "cluster-id", 0); for (i = 0; i < num_apus; i++) { object_initialize_child(OBJECT(&s->apu_cluster), "apu-cpu[*]", - &s->apu_cpu[i], sizeof(s->apu_cpu[i]), - ARM_CPU_TYPE_NAME("cortex-a53"), - &error_abort, NULL); + &s->apu_cpu[i], + ARM_CPU_TYPE_NAME("cortex-a53")); } - sysbus_init_child_obj(obj, "gic", &s->gic, sizeof(s->gic), - gic_class_name()); + object_initialize_child(obj, "gic", &s->gic, gic_class_name()); for (i = 0; i < XLNX_ZYNQMP_NUM_GEMS; i++) { - sysbus_init_child_obj(obj, "gem[*]", &s->gem[i], sizeof(s->gem[i]), - TYPE_CADENCE_GEM); + object_initialize_child(obj, "gem[*]", &s->gem[i], TYPE_CADENCE_GEM); } for (i = 0; i < XLNX_ZYNQMP_NUM_UARTS; i++) { - sysbus_init_child_obj(obj, "uart[*]", &s->uart[i], sizeof(s->uart[i]), - TYPE_CADENCE_UART); + object_initialize_child(obj, "uart[*]", &s->uart[i], + TYPE_CADENCE_UART); } - sysbus_init_child_obj(obj, "sata", &s->sata, sizeof(s->sata), - TYPE_SYSBUS_AHCI); + object_initialize_child(obj, "sata", &s->sata, TYPE_SYSBUS_AHCI); for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) { - sysbus_init_child_obj(obj, "sdhci[*]", &s->sdhci[i], - sizeof(s->sdhci[i]), TYPE_SYSBUS_SDHCI); + object_initialize_child(obj, "sdhci[*]", &s->sdhci[i], + TYPE_SYSBUS_SDHCI); } for (i = 0; i < XLNX_ZYNQMP_NUM_SPIS; i++) { - sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]), - TYPE_XILINX_SPIPS); + object_initialize_child(obj, "spi[*]", &s->spi[i], TYPE_XILINX_SPIPS); } - sysbus_init_child_obj(obj, "qspi", &s->qspi, sizeof(s->qspi), - TYPE_XLNX_ZYNQMP_QSPIPS); + object_initialize_child(obj, "qspi", &s->qspi, TYPE_XLNX_ZYNQMP_QSPIPS); - sysbus_init_child_obj(obj, "xxxdp", &s->dp, sizeof(s->dp), TYPE_XLNX_DP); + object_initialize_child(obj, "xxxdp", &s->dp, TYPE_XLNX_DP); - sysbus_init_child_obj(obj, "dp-dma", &s->dpdma, sizeof(s->dpdma), - TYPE_XLNX_DPDMA); + object_initialize_child(obj, "dp-dma", &s->dpdma, TYPE_XLNX_DPDMA); - sysbus_init_child_obj(obj, "ipi", &s->ipi, sizeof(s->ipi), - TYPE_XLNX_ZYNQMP_IPI); + object_initialize_child(obj, "ipi", &s->ipi, TYPE_XLNX_ZYNQMP_IPI); - sysbus_init_child_obj(obj, "rtc", &s->rtc, sizeof(s->rtc), - TYPE_XLNX_ZYNQMP_RTC); + object_initialize_child(obj, "rtc", &s->rtc, TYPE_XLNX_ZYNQMP_RTC); for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) { - sysbus_init_child_obj(obj, "gdma[*]", &s->gdma[i], sizeof(s->gdma[i]), - TYPE_XLNX_ZDMA); + object_initialize_child(obj, "gdma[*]", &s->gdma[i], TYPE_XLNX_ZDMA); } for (i = 0; i < XLNX_ZYNQMP_NUM_ADMA_CH; i++) { - sysbus_init_child_obj(obj, "adma[*]", &s->adma[i], sizeof(s->adma[i]), - TYPE_XLNX_ZDMA); + object_initialize_child(obj, "adma[*]", &s->adma[i], TYPE_XLNX_ZDMA); } } @@ -355,44 +336,38 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) qdev_prop_set_bit(DEVICE(&s->gic), "has-virtualization-extensions", s->virt); - qdev_init_nofail(DEVICE(&s->apu_cluster)); + qdev_realize(DEVICE(&s->apu_cluster), NULL, &error_fatal); /* Realize APUs before realizing the GIC. KVM requires this. */ for (i = 0; i < num_apus; i++) { - char *name; + const char *name; - object_property_set_int(OBJECT(&s->apu_cpu[i]), QEMU_PSCI_CONDUIT_SMC, - "psci-conduit", &error_abort); + object_property_set_int(OBJECT(&s->apu_cpu[i]), "psci-conduit", + QEMU_PSCI_CONDUIT_SMC, &error_abort); name = object_get_canonical_path_component(OBJECT(&s->apu_cpu[i])); if (strcmp(name, boot_cpu)) { /* Secondary CPUs start in PSCI powered-down state */ - object_property_set_bool(OBJECT(&s->apu_cpu[i]), true, - "start-powered-off", &error_abort); + object_property_set_bool(OBJECT(&s->apu_cpu[i]), + "start-powered-off", true, &error_abort); } else { s->boot_cpu_ptr = &s->apu_cpu[i]; } - g_free(name); - - object_property_set_bool(OBJECT(&s->apu_cpu[i]), - s->secure, "has_el3", NULL); - object_property_set_bool(OBJECT(&s->apu_cpu[i]), - s->virt, "has_el2", NULL); - object_property_set_int(OBJECT(&s->apu_cpu[i]), GIC_BASE_ADDR, - "reset-cbar", &error_abort); - object_property_set_int(OBJECT(&s->apu_cpu[i]), num_apus, - "core-count", &error_abort); - object_property_set_bool(OBJECT(&s->apu_cpu[i]), true, "realized", - &err); - if (err) { - error_propagate(errp, err); + + object_property_set_bool(OBJECT(&s->apu_cpu[i]), "has_el3", s->secure, + NULL); + object_property_set_bool(OBJECT(&s->apu_cpu[i]), "has_el2", s->virt, + NULL); + object_property_set_int(OBJECT(&s->apu_cpu[i]), "reset-cbar", + GIC_BASE_ADDR, &error_abort); + object_property_set_int(OBJECT(&s->apu_cpu[i]), "core-count", + num_apus, &error_abort); + if (!qdev_realize(DEVICE(&s->apu_cpu[i]), NULL, errp)) { return; } } - object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gic), errp)) { return; } @@ -478,17 +453,18 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) for (i = 0; i < XLNX_ZYNQMP_NUM_GEMS; i++) { NICInfo *nd = &nd_table[i]; + /* FIXME use qdev NIC properties instead of nd_table[] */ if (nd->used) { qemu_check_nic_model(nd, TYPE_CADENCE_GEM); qdev_set_nic_properties(DEVICE(&s->gem[i]), nd); } - object_property_set_int(OBJECT(&s->gem[i]), GEM_REVISION, "revision", + object_property_set_int(OBJECT(&s->gem[i]), "revision", GEM_REVISION, + &error_abort); + object_property_set_int(OBJECT(&s->gem[i]), "phy-addr", 23, &error_abort); - object_property_set_int(OBJECT(&s->gem[i]), 2, "num-priority-queues", + object_property_set_int(OBJECT(&s->gem[i]), "num-priority-queues", 2, &error_abort); - object_property_set_bool(OBJECT(&s->gem[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gem[i]), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->gem[i]), 0, gem_addr[i]); @@ -498,9 +474,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) for (i = 0; i < XLNX_ZYNQMP_NUM_UARTS; i++) { qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i)); - object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, uart_addr[i]); @@ -508,11 +482,9 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) gic_spi[uart_intr[i]]); } - object_property_set_int(OBJECT(&s->sata), SATA_NUM_PORTS, "num-ports", + object_property_set_int(OBJECT(&s->sata), "num-ports", SATA_NUM_PORTS, &error_abort); - object_property_set_bool(OBJECT(&s->sata), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sata), errp)) { return; } @@ -529,24 +501,17 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) * - SDIO Specification Version 3.0 * - eMMC Specification Version 4.51 */ - object_property_set_uint(sdhci, 3, "sd-spec-version", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_uint(sdhci, "sd-spec-version", 3, errp)) { return; } - object_property_set_uint(sdhci, SDHCI_CAPABILITIES, "capareg", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_uint(sdhci, "capareg", SDHCI_CAPABILITIES, + errp)) { return; } - object_property_set_uint(sdhci, UHS_I, "uhs", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_uint(sdhci, "uhs", UHS_I, errp)) { return; } - object_property_set_bool(sdhci, true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(sdhci), errp)) { return; } sysbus_mmio_map(sbd, 0, sdhci_addr[i]); @@ -561,9 +526,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) for (i = 0; i < XLNX_ZYNQMP_NUM_SPIS; i++) { gchar *bus_name; - object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) { return; } @@ -578,9 +541,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) g_free(bus_name); } - object_property_set_bool(OBJECT(&s->qspi), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->qspi), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi), 0, QSPI_ADDR); @@ -600,49 +561,38 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) g_free(target_bus); } - object_property_set_bool(OBJECT(&s->dp), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->dp), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->dp), 0, DP_ADDR); sysbus_connect_irq(SYS_BUS_DEVICE(&s->dp), 0, gic_spi[DP_IRQ]); - object_property_set_bool(OBJECT(&s->dpdma), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->dpdma), errp)) { return; } - object_property_set_link(OBJECT(&s->dp), OBJECT(&s->dpdma), "dpdma", + object_property_set_link(OBJECT(&s->dp), "dpdma", OBJECT(&s->dpdma), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->dpdma), 0, DPDMA_ADDR); sysbus_connect_irq(SYS_BUS_DEVICE(&s->dpdma), 0, gic_spi[DPDMA_IRQ]); - object_property_set_bool(OBJECT(&s->ipi), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->ipi), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->ipi), 0, IPI_ADDR); sysbus_connect_irq(SYS_BUS_DEVICE(&s->ipi), 0, gic_spi[IPI_IRQ]); - object_property_set_bool(OBJECT(&s->rtc), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->rtc), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, RTC_ADDR); sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0, gic_spi[RTC_IRQ]); for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) { - object_property_set_uint(OBJECT(&s->gdma[i]), 128, "bus-width", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_uint(OBJECT(&s->gdma[i]), "bus-width", 128, + errp)) { return; } - object_property_set_bool(OBJECT(&s->gdma[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gdma[i]), errp)) { return; } @@ -652,9 +602,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) } for (i = 0; i < XLNX_ZYNQMP_NUM_ADMA_CH; i++) { - object_property_set_bool(OBJECT(&s->adma[i]), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->adma[i]), errp)) { return; } diff --git a/hw/arm/z2.c b/hw/arm/z2.c index a0f4095990450c1808848d420848ac7fd355cd85..4fc5699daef9b966e12b12ffd5000c6df8b171ac 100644 --- a/hw/arm/z2.c +++ b/hw/arm/z2.c @@ -26,6 +26,7 @@ #include "exec/address-spaces.h" #include "sysemu/qtest.h" #include "cpu.h" +#include "qom/object.h" #ifdef DEBUG_Z2 #define DPRINTF(fmt, ...) \ @@ -102,18 +103,21 @@ static struct arm_boot_info z2_binfo = { #define Z2_GPIO_KEY_ON 1 #define Z2_GPIO_LCD_CS 88 -typedef struct { +struct ZipitLCD { SSISlave ssidev; int32_t selected; int32_t enabled; uint8_t buf[3]; uint32_t cur_reg; int pos; -} ZipitLCD; +}; + +#define TYPE_ZIPIT_LCD "zipit-lcd" +OBJECT_DECLARE_SIMPLE_TYPE(ZipitLCD, ZIPIT_LCD) static uint32_t zipit_lcd_transfer(SSISlave *dev, uint32_t value) { - ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev); + ZipitLCD *z = ZIPIT_LCD(dev); uint16_t val; if (z->selected) { z->buf[z->pos] = value & 0xff; @@ -153,7 +157,7 @@ static void z2_lcd_cs(void *opaque, int line, int level) static void zipit_lcd_realize(SSISlave *dev, Error **errp) { - ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev); + ZipitLCD *z = ZIPIT_LCD(dev); z->selected = 0; z->enabled = 0; z->pos = 0; @@ -185,21 +189,21 @@ static void zipit_lcd_class_init(ObjectClass *klass, void *data) } static const TypeInfo zipit_lcd_info = { - .name = "zipit-lcd", + .name = TYPE_ZIPIT_LCD, .parent = TYPE_SSI_SLAVE, .instance_size = sizeof(ZipitLCD), .class_init = zipit_lcd_class_init, }; #define TYPE_AER915 "aer915" -#define AER915(obj) OBJECT_CHECK(AER915State, (obj), TYPE_AER915) +OBJECT_DECLARE_SIMPLE_TYPE(AER915State, AER915) -typedef struct AER915State { +struct AER915State { I2CSlave parent_obj; int len; uint8_t buf[3]; -} AER915State; +}; static int aer915_send(I2CSlave *i2c, uint8_t data) { @@ -325,10 +329,10 @@ static void z2_init(MachineState *machine) type_register_static(&zipit_lcd_info); type_register_static(&aer915_info); - z2_lcd = ssi_create_slave(mpu->ssp[1], "zipit-lcd"); + z2_lcd = ssi_create_slave(mpu->ssp[1], TYPE_ZIPIT_LCD); bus = pxa2xx_i2c_bus(mpu->i2c[0]); - i2c_create_slave(bus, TYPE_AER915, 0x55); - wm = i2c_create_slave(bus, TYPE_WM8750, 0x1b); + i2c_slave_create_simple(bus, TYPE_AER915, 0x55); + wm = DEVICE(i2c_slave_create_simple(bus, TYPE_WM8750, 0x1b)); mpu->i2s->opaque = wm; mpu->i2s->codec_out = wm8750_dac_dat; mpu->i2s->codec_in = wm8750_adc_dat; diff --git a/hw/audio/Makefile.objs b/hw/audio/Makefile.objs deleted file mode 100644 index 63db383709a160ab03b290fef0784110d56b4fab..0000000000000000000000000000000000000000 --- a/hw/audio/Makefile.objs +++ /dev/null @@ -1,18 +0,0 @@ -# Sound -common-obj-$(CONFIG_SB16) += sb16.o -common-obj-$(CONFIG_ES1370) += es1370.o -common-obj-$(CONFIG_AC97) += ac97.o -common-obj-$(CONFIG_ADLIB) += fmopl.o adlib.o -common-obj-$(CONFIG_GUS) += gus.o gusemu_hal.o gusemu_mixer.o -common-obj-$(CONFIG_CS4231A) += cs4231a.o -common-obj-$(CONFIG_HDA) += intel-hda.o hda-codec.o - -common-obj-$(CONFIG_PCSPK) += pcspk.o -common-obj-$(CONFIG_WM8750) += wm8750.o -common-obj-$(CONFIG_PL041) += pl041.o lm4549.o - -common-obj-$(CONFIG_CS4231) += cs4231.o -common-obj-$(CONFIG_MARVELL_88W8618) += marvell_88w8618.o -common-obj-$(CONFIG_MILKYMIST) += milkymist-ac97.o - -common-obj-y += soundhw.o diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index 8a9b9924c49593078b509d8f8694fac0f6cffbb0..3cb81310607fe64d4b1fb58834e2b3f57ad19cb3 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -25,6 +25,7 @@ #include "migration/vmstate.h" #include "qemu/module.h" #include "sysemu/dma.h" +#include "qom/object.h" enum { AC97_Reset = 0x00, @@ -126,8 +127,7 @@ enum { #define MUTE_SHIFT 15 #define TYPE_AC97 "AC97" -#define AC97(obj) \ - OBJECT_CHECK(AC97LinkState, (obj), TYPE_AC97) +OBJECT_DECLARE_SIMPLE_TYPE(AC97LinkState, AC97) #define REC_MASK 7 enum { @@ -158,7 +158,7 @@ typedef struct AC97BusMasterRegs { BD bd; } AC97BusMasterRegs; -typedef struct AC97LinkState { +struct AC97LinkState { PCIDevice dev; QEMUSoundCard card; uint32_t glob_cnt; @@ -175,7 +175,7 @@ typedef struct AC97LinkState { int bup_flag; MemoryRegion io_nam; MemoryRegion io_nabm; -} AC97LinkState; +}; enum { BUP_SET = 1, @@ -1393,12 +1393,6 @@ static void ac97_exit(PCIDevice *dev) AUD_remove_card(&s->card); } -static int ac97_init (PCIBus *bus) -{ - pci_create_simple(bus, -1, TYPE_AC97); - return 0; -} - static Property ac97_properties[] = { DEFINE_AUDIO_PROPERTIES(AC97LinkState, card), DEFINE_PROP_END_OF_LIST (), @@ -1436,7 +1430,8 @@ static const TypeInfo ac97_info = { static void ac97_register_types (void) { type_register_static (&ac97_info); - pci_register_soundhw("ac97", "Intel 82801AA AC97 Audio", ac97_init); + deprecated_register_soundhw("ac97", "Intel 82801AA AC97 Audio", + 0, TYPE_AC97); } type_init (ac97_register_types) diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c index 7c3b67dcfb8cd9a0a59749c43a013198cf7c69a2..42d50d2fdc46138275adcfe6b26fb9a4439f5c00 100644 --- a/hw/audio/adlib.c +++ b/hw/audio/adlib.c @@ -29,6 +29,7 @@ #include "audio/audio.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" +#include "qom/object.h" //#define DEBUG @@ -51,9 +52,9 @@ #define SHIFT 1 #define TYPE_ADLIB "adlib" -#define ADLIB(obj) OBJECT_CHECK(AdlibState, (obj), TYPE_ADLIB) +OBJECT_DECLARE_SIMPLE_TYPE(AdlibState, ADLIB) -typedef struct { +struct AdlibState { ISADevice parent_obj; QEMUSoundCard card; @@ -73,7 +74,7 @@ typedef struct { QEMUAudioTimeStamp ats; FM_OPL *opl; PortioList port_list; -} AdlibState; +}; static void adlib_stop_opl_timer (AdlibState *s, size_t n) { @@ -319,16 +320,10 @@ static const TypeInfo adlib_info = { .class_init = adlib_class_initfn, }; -static int Adlib_init (ISABus *bus) -{ - isa_create_simple (bus, TYPE_ADLIB); - return 0; -} - static void adlib_register_types (void) { type_register_static (&adlib_info); - isa_register_soundhw("adlib", ADLIB_DESC, Adlib_init); + deprecated_register_soundhw("adlib", ADLIB_DESC, 1, TYPE_ADLIB); } type_init (adlib_register_types) diff --git a/hw/audio/cs4231.c b/hw/audio/cs4231.c index 11a6328fc24f47456fb9bf3d613e50abaa77c15c..8e9554ce9bcd4f9f0cdb8ffec0c2a8865c2b1fa5 100644 --- a/hw/audio/cs4231.c +++ b/hw/audio/cs4231.c @@ -27,6 +27,7 @@ #include "migration/vmstate.h" #include "qemu/module.h" #include "trace.h" +#include "qom/object.h" /* * In addition to Crystal CS4231 there is a DMA controller on Sparc. @@ -37,17 +38,18 @@ #define CS_MAXDREG (CS_DREGS - 1) #define TYPE_CS4231 "SUNW,CS4231" -#define CS4231(obj) \ - OBJECT_CHECK(CSState, (obj), TYPE_CS4231) +typedef struct CSState CSState; +DECLARE_INSTANCE_CHECKER(CSState, CS4231, + TYPE_CS4231) -typedef struct CSState { +struct CSState { SysBusDevice parent_obj; MemoryRegion iomem; qemu_irq irq; uint32_t regs[CS_REGS]; uint8_t dregs[CS_DREGS]; -} CSState; +}; #define CS_RAP(s) ((s)->regs[0] & CS_MAXDREG) #define CS_VER 0xa0 diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c index ffdbb58d6a1198f7bf96d9b846c81a89a02bbd36..7d60ce6f0ef34e919b5adfbfcac3ed288bfe50ef 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -32,6 +32,7 @@ #include "qemu/module.h" #include "qemu/timer.h" #include "qapi/error.h" +#include "qom/object.h" /* Missing features: @@ -62,9 +63,11 @@ static struct { #define CS_DREGS 32 #define TYPE_CS4231A "cs4231a" -#define CS4231A(obj) OBJECT_CHECK (CSState, (obj), TYPE_CS4231A) +typedef struct CSState CSState; +DECLARE_INSTANCE_CHECKER(CSState, CS4231A, + TYPE_CS4231A) -typedef struct CSState { +struct CSState { ISADevice dev; QEMUSoundCard card; MemoryRegion ioports; @@ -82,7 +85,7 @@ typedef struct CSState { int aci_counter; SWVoiceOut *voice; int16_t *tab; -} CSState; +}; #define MODE2 (1 << 6) #define MCE (1 << 6) @@ -683,12 +686,6 @@ static void cs4231a_realizefn (DeviceState *dev, Error **errp) AUD_register_card ("cs4231a", &s->card); } -static int cs4231a_init (ISABus *bus) -{ - isa_create_simple (bus, TYPE_CS4231A); - return 0; -} - static Property cs4231a_properties[] = { DEFINE_AUDIO_PROPERTIES(CSState, card), DEFINE_PROP_UINT32 ("iobase", CSState, port, 0x534), @@ -720,7 +717,7 @@ static const TypeInfo cs4231a_info = { static void cs4231a_register_types (void) { type_register_static (&cs4231a_info); - isa_register_soundhw("cs4231a", "CS4231A", cs4231a_init); + deprecated_register_soundhw("cs4231a", "CS4231A", 1, TYPE_CS4231A); } type_init (cs4231a_register_types) diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c index 5f8a83ff56241d94347c1e51419ea71fa839e30b..690458981471bd5ff7847ee8ca3cb3c0c8f6a212 100644 --- a/hw/audio/es1370.c +++ b/hw/audio/es1370.c @@ -33,6 +33,7 @@ #include "migration/vmstate.h" #include "qemu/module.h" #include "sysemu/dma.h" +#include "qom/object.h" /* Missing stuff: SCTRL_P[12](END|ST)INC @@ -263,7 +264,7 @@ struct chan { uint32_t frame_cnt; }; -typedef struct ES1370State { +struct ES1370State { PCIDevice dev; QEMUSoundCard card; MemoryRegion io; @@ -276,7 +277,8 @@ typedef struct ES1370State { uint32_t mempage; uint32_t codec; uint32_t sctl; -} ES1370State; +}; +typedef struct ES1370State ES1370State; struct chan_bits { uint32_t ctl_en; @@ -291,8 +293,7 @@ struct chan_bits { }; #define TYPE_ES1370 "ES1370" -#define ES1370(obj) \ - OBJECT_CHECK(ES1370State, (obj), TYPE_ES1370) +OBJECT_DECLARE_SIMPLE_TYPE(ES1370State, ES1370) static void es1370_dac1_calc_freq (ES1370State *s, uint32_t ctl, uint32_t *old_freq, uint32_t *new_freq); @@ -884,12 +885,6 @@ static void es1370_exit(PCIDevice *dev) AUD_remove_card(&s->card); } -static int es1370_init (PCIBus *bus) -{ - pci_create_simple (bus, -1, TYPE_ES1370); - return 0; -} - static Property es1370_properties[] = { DEFINE_AUDIO_PROPERTIES(ES1370State, card), DEFINE_PROP_END_OF_LIST(), @@ -928,7 +923,8 @@ static const TypeInfo es1370_info = { static void es1370_register_types (void) { type_register_static (&es1370_info); - pci_register_soundhw("es1370", "ENSONIQ AudioPCI ES1370", es1370_init); + deprecated_register_soundhw("es1370", "ENSONIQ AudioPCI ES1370", + 0, TYPE_ES1370); } type_init (es1370_register_types) diff --git a/hw/audio/gus.c b/hw/audio/gus.c index c8df2bde6b3230397c7ab2349ab3fe96f6418750..e8719ee117fe65e6c71c2b5f2ac646c0cb2eb9af 100644 --- a/hw/audio/gus.c +++ b/hw/audio/gus.c @@ -33,6 +33,7 @@ #include "migration/vmstate.h" #include "gusemu.h" #include "gustate.h" +#include "qom/object.h" #define dolog(...) AUD_log ("audio", __VA_ARGS__) #ifdef DEBUG @@ -42,9 +43,9 @@ #endif #define TYPE_GUS "gus" -#define GUS(obj) OBJECT_CHECK (GUSState, (obj), TYPE_GUS) +OBJECT_DECLARE_SIMPLE_TYPE(GUSState, GUS) -typedef struct GUSState { +struct GUSState { ISADevice dev; GUSEmuState emu; QEMUSoundCard card; @@ -60,7 +61,7 @@ typedef struct GUSState { IsaDma *isa_dma; PortioList portio_list1; PortioList portio_list2; -} GUSState; +}; static uint32_t gus_readb(void *opaque, uint32_t nport) { @@ -286,12 +287,6 @@ static void gus_realizefn (DeviceState *dev, Error **errp) AUD_set_active_out (s->voice, 1); } -static int GUS_init (ISABus *bus) -{ - isa_create_simple (bus, TYPE_GUS); - return 0; -} - static Property gus_properties[] = { DEFINE_AUDIO_PROPERTIES(GUSState, card), DEFINE_PROP_UINT32 ("freq", GUSState, freq, 44100), @@ -322,7 +317,7 @@ static const TypeInfo gus_info = { static void gus_register_types (void) { type_register_static (&gus_info); - isa_register_soundhw("gus", "Gravis Ultrasound GF1", GUS_init); + deprecated_register_soundhw("gus", "Gravis Ultrasound GF1", 1, TYPE_GUS); } type_init (gus_register_types) diff --git a/hw/audio/gusemu_hal.c b/hw/audio/gusemu_hal.c index ae40ca341cc4ef43b2c430d84dfac465378398f7..5b9a14ee21b668a3627aa2bfd2c6eca14ba0ea11 100644 --- a/hw/audio/gusemu_hal.c +++ b/hw/audio/gusemu_hal.c @@ -32,7 +32,7 @@ #define GUSregb(position) (* (gusptr+(position))) #define GUSregw(position) (*(uint16_t *) (gusptr+(position))) -#define GUSregd(position) (*(uint16_t *)(gusptr+(position))) +#define GUSregd(position) (*(uint32_t *)(gusptr + (position))) /* size given in bytes */ unsigned int gus_read(GUSEmuState * state, int port, int size) diff --git a/hw/audio/gusemu_mixer.c b/hw/audio/gusemu_mixer.c index 00b9861b92b222b48a9d7a484a8f4a70a4217a24..56300de77e4429b5c02d4d2b00dfc6f87d4b348c 100644 --- a/hw/audio/gusemu_mixer.c +++ b/hw/audio/gusemu_mixer.c @@ -28,7 +28,7 @@ #define GUSregb(position) (* (gusptr+(position))) #define GUSregw(position) (*(uint16_t *) (gusptr+(position))) -#define GUSregd(position) (*(uint16_t *)(gusptr+(position))) +#define GUSregd(position) (*(uint32_t *)(gusptr + (position))) #define GUSvoice(position) (*(uint16_t *)(voiceptr+(position))) diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c index cbd92b72f27cd8f5debf98a30dc6096caad91be1..feb8f9e2bb7aa553e855693ab0130ce71cf8e138 100644 --- a/hw/audio/hda-codec.c +++ b/hw/audio/hda-codec.c @@ -26,6 +26,7 @@ #include "intel-hda-defs.h" #include "audio/audio.h" #include "trace.h" +#include "qom/object.h" /* -------------------------------------------------------------------------- */ @@ -171,7 +172,7 @@ struct HDAAudioStream { }; #define TYPE_HDA_AUDIO "hda-audio" -#define HDA_AUDIO(obj) OBJECT_CHECK(HDAAudioState, (obj), TYPE_HDA_AUDIO) +OBJECT_DECLARE_SIMPLE_TYPE(HDAAudioState, HDA_AUDIO) struct HDAAudioState { HDACodecDevice hda; @@ -898,6 +899,7 @@ static void hda_audio_base_class_init(ObjectClass *klass, void *data) static const TypeInfo hda_audio_info = { .name = TYPE_HDA_AUDIO, .parent = TYPE_HDA_CODEC_DEVICE, + .instance_size = sizeof(HDAAudioState), .class_init = hda_audio_base_class_init, .abstract = true, }; @@ -914,7 +916,6 @@ static void hda_audio_output_class_init(ObjectClass *klass, void *data) static const TypeInfo hda_audio_output_info = { .name = "hda-output", .parent = TYPE_HDA_AUDIO, - .instance_size = sizeof(HDAAudioState), .class_init = hda_audio_output_class_init, }; @@ -930,7 +931,6 @@ static void hda_audio_duplex_class_init(ObjectClass *klass, void *data) static const TypeInfo hda_audio_duplex_info = { .name = "hda-duplex", .parent = TYPE_HDA_AUDIO, - .instance_size = sizeof(HDAAudioState), .class_init = hda_audio_duplex_class_init, }; @@ -946,7 +946,6 @@ static void hda_audio_micro_class_init(ObjectClass *klass, void *data) static const TypeInfo hda_audio_micro_info = { .name = "hda-micro", .parent = TYPE_HDA_AUDIO, - .instance_size = sizeof(HDAAudioState), .class_init = hda_audio_micro_class_init, }; diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index 4696ae0d9a61539fe02fd2f1183f9baf924d12f1..4330213fff167071800216c49607c5f18022cc20 100644 --- a/hw/audio/intel-hda.c +++ b/hw/audio/intel-hda.c @@ -25,12 +25,14 @@ #include "qemu/bitops.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qemu/error-report.h" #include "hw/audio/soundhw.h" #include "intel-hda.h" #include "migration/vmstate.h" #include "intel-hda-defs.h" #include "sysemu/dma.h" #include "qapi/error.h" +#include "qom/object.h" /* --------------------------------------------------------------------- */ /* hda bus */ @@ -202,8 +204,8 @@ struct IntelHDAState { #define TYPE_INTEL_HDA_GENERIC "intel-hda-generic" -#define INTEL_HDA(obj) \ - OBJECT_CHECK(IntelHDAState, (obj), TYPE_INTEL_HDA_GENERIC) +DECLARE_INSTANCE_CHECKER(IntelHDAState, INTEL_HDA, + TYPE_INTEL_HDA_GENERIC) struct IntelHDAReg { const char *name; /* register name */ @@ -1307,10 +1309,12 @@ static int intel_hda_and_codec_init(PCIBus *bus) BusState *hdabus; DeviceState *codec; + warn_report("'-soundhw hda' is deprecated, " + "please use '-device intel-hda -device hda-duplex' instead"); controller = DEVICE(pci_create_simple(bus, -1, "intel-hda")); hdabus = QLIST_FIRST(&controller->child_bus); - codec = qdev_create(hdabus, "hda-duplex"); - qdev_init_nofail(codec); + codec = qdev_new("hda-duplex"); + qdev_realize_and_unref(codec, hdabus, &error_fatal); return 0; } diff --git a/hw/audio/intel-hda.h b/hw/audio/intel-hda.h index eee6fee5af3fc057289f1f5489ac638b273c85af..f78c1833e34141c5ad5561292c8cf097500b7d12 100644 --- a/hw/audio/intel-hda.h +++ b/hw/audio/intel-hda.h @@ -2,23 +2,18 @@ #define HW_INTEL_HDA_H #include "hw/qdev-core.h" +#include "qom/object.h" /* --------------------------------------------------------------------- */ /* hda bus */ #define TYPE_HDA_CODEC_DEVICE "hda-codec" -#define HDA_CODEC_DEVICE(obj) \ - OBJECT_CHECK(HDACodecDevice, (obj), TYPE_HDA_CODEC_DEVICE) -#define HDA_CODEC_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(HDACodecDeviceClass, (klass), TYPE_HDA_CODEC_DEVICE) -#define HDA_CODEC_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(HDACodecDeviceClass, (obj), TYPE_HDA_CODEC_DEVICE) +OBJECT_DECLARE_TYPE(HDACodecDevice, HDACodecDeviceClass, + HDA_CODEC_DEVICE) #define TYPE_HDA_BUS "HDA" -#define HDA_BUS(obj) OBJECT_CHECK(HDACodecBus, (obj), TYPE_HDA_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(HDACodecBus, HDA_BUS) -typedef struct HDACodecBus HDACodecBus; -typedef struct HDACodecDevice HDACodecDevice; typedef void (*hda_codec_response_func)(HDACodecDevice *dev, bool solicited, uint32_t response); @@ -33,15 +28,14 @@ struct HDACodecBus { hda_codec_xfer_func xfer; }; -typedef struct HDACodecDeviceClass -{ +struct HDACodecDeviceClass { DeviceClass parent_class; int (*init)(HDACodecDevice *dev); void (*exit)(HDACodecDevice *dev); void (*command)(HDACodecDevice *dev, uint32_t nid, uint32_t data); void (*stream)(HDACodecDevice *dev, uint32_t stnr, bool running, bool output); -} HDACodecDeviceClass; +}; struct HDACodecDevice { DeviceState qdev; diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c index 8dfacec693f1b58b7852fe4c7e499a359b566025..e6c09bdb8e3eb33bcffd22fe0fd3df81b48584a3 100644 --- a/hw/audio/marvell_88w8618.c +++ b/hw/audio/marvell_88w8618.c @@ -19,6 +19,7 @@ #include "audio/audio.h" #include "qapi/error.h" #include "qemu/module.h" +#include "qom/object.h" #define MP_AUDIO_SIZE 0x00001000 @@ -42,10 +43,9 @@ #define MP_AUDIO_CLOCK_24MHZ (1 << 9) #define MP_AUDIO_MONO (1 << 14) -#define MV88W8618_AUDIO(obj) \ - OBJECT_CHECK(mv88w8618_audio_state, (obj), TYPE_MV88W8618_AUDIO) +OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_audio_state, MV88W8618_AUDIO) -typedef struct mv88w8618_audio_state { +struct mv88w8618_audio_state { SysBusDevice parent_obj; MemoryRegion iomem; @@ -60,7 +60,7 @@ typedef struct mv88w8618_audio_state { uint32_t last_free; uint32_t clock_div; void *wm; -} mv88w8618_audio_state; +}; static void mv88w8618_audio_callback(void *opaque, int free_out, int free_in) { diff --git a/hw/audio/meson.build b/hw/audio/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..549e9a0396a2b895138c4926b81ebae10c600998 --- /dev/null +++ b/hw/audio/meson.build @@ -0,0 +1,14 @@ +softmmu_ss.add(files('soundhw.c')) +softmmu_ss.add(when: 'CONFIG_AC97', if_true: files('ac97.c')) +softmmu_ss.add(when: 'CONFIG_ADLIB', if_true: files('fmopl.c', 'adlib.c')) +softmmu_ss.add(when: 'CONFIG_CS4231', if_true: files('cs4231.c')) +softmmu_ss.add(when: 'CONFIG_CS4231A', if_true: files('cs4231a.c')) +softmmu_ss.add(when: 'CONFIG_ES1370', if_true: files('es1370.c')) +softmmu_ss.add(when: 'CONFIG_GUS', if_true: files('gus.c', 'gusemu_hal.c', 'gusemu_mixer.c')) +softmmu_ss.add(when: 'CONFIG_HDA', if_true: files('intel-hda.c', 'hda-codec.c')) +softmmu_ss.add(when: 'CONFIG_MARVELL_88W8618', if_true: files('marvell_88w8618.c')) +softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-ac97.c')) +softmmu_ss.add(when: 'CONFIG_PCSPK', if_true: files('pcspk.c')) +softmmu_ss.add(when: 'CONFIG_PL041', if_true: files('pl041.c', 'lm4549.c')) +softmmu_ss.add(when: 'CONFIG_SB16', if_true: files('sb16.c')) +softmmu_ss.add(when: 'CONFIG_WM8750', if_true: files('wm8750.c')) diff --git a/hw/audio/milkymist-ac97.c b/hw/audio/milkymist-ac97.c index 0fa38adbe24b8624c4eece38ad748fe7f4fecb1d..7d2e0570380ea86b6662fe4cabf699eb3fb30d2a 100644 --- a/hw/audio/milkymist-ac97.c +++ b/hw/audio/milkymist-ac97.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -29,6 +29,7 @@ #include "audio/audio.h" #include "qemu/error-report.h" #include "qemu/module.h" +#include "qom/object.h" enum { R_AC97_CTRL = 0, @@ -55,8 +56,7 @@ enum { }; #define TYPE_MILKYMIST_AC97 "milkymist-ac97" -#define MILKYMIST_AC97(obj) \ - OBJECT_CHECK(MilkymistAC97State, (obj), TYPE_MILKYMIST_AC97) +OBJECT_DECLARE_SIMPLE_TYPE(MilkymistAC97State, MILKYMIST_AC97) struct MilkymistAC97State { SysBusDevice parent_obj; @@ -74,7 +74,6 @@ struct MilkymistAC97State { qemu_irq dmar_irq; qemu_irq dmaw_irq; }; -typedef struct MilkymistAC97State MilkymistAC97State; static void update_voices(MilkymistAC97State *s) { diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index c37a3878612e25947f436984447f4817f20c0819..b056c05387c8c9a6bea5b9f098820ae197e2c652 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -28,19 +28,21 @@ #include "audio/audio.h" #include "qemu/module.h" #include "qemu/timer.h" +#include "qemu/error-report.h" #include "hw/timer/i8254.h" #include "migration/vmstate.h" #include "hw/audio/pcspk.h" #include "qapi/error.h" +#include "qom/object.h" #define PCSPK_BUF_LEN 1792 #define PCSPK_SAMPLE_RATE 32000 #define PCSPK_MAX_FREQ (PCSPK_SAMPLE_RATE >> 1) #define PCSPK_MIN_COUNT DIV_ROUND_UP(PIT_FREQ, PCSPK_MAX_FREQ) -#define PC_SPEAKER(obj) OBJECT_CHECK(PCSpkState, (obj), TYPE_PC_SPEAKER) +OBJECT_DECLARE_SIMPLE_TYPE(PCSpkState, PC_SPEAKER) -typedef struct { +struct PCSpkState { ISADevice parent_obj; MemoryRegion ioport; @@ -55,7 +57,7 @@ typedef struct { uint8_t data_on; uint8_t dummy_refresh_clock; bool migrate; -} PCSpkState; +}; static const char *s_spk = "pcspk"; static PCSpkState *pcspk_state; @@ -112,11 +114,15 @@ static void pcspk_callback(void *opaque, int free) } } -static int pcspk_audio_init(ISABus *bus) +static int pcspk_audio_init(PCSpkState *s) { - PCSpkState *s = pcspk_state; struct audsettings as = {PCSPK_SAMPLE_RATE, 1, AUDIO_FORMAT_U8, 0}; + if (s->voice) { + /* already initialized */ + return 0; + } + AUD_register_card(s_spk, &s->card); s->voice = AUD_open_out(&s->card, s->voice, s_spk, s, pcspk_callback, &as); @@ -185,6 +191,10 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp) isa_register_ioport(isadev, &s->ioport, s->iobase); + if (s->card.state) { + pcspk_audio_init(s); + } + pcspk_state = s; } @@ -210,7 +220,7 @@ static const VMStateDescription vmstate_spk = { static Property pcspk_properties[] = { DEFINE_AUDIO_PROPERTIES(PCSpkState, card), - DEFINE_PROP_UINT32("iobase", PCSpkState, iobase, -1), + DEFINE_PROP_UINT32("iobase", PCSpkState, iobase, 0x61), DEFINE_PROP_BOOL("migrate", PCSpkState, migrate, true), DEFINE_PROP_END_OF_LIST(), }; @@ -236,9 +246,18 @@ static const TypeInfo pcspk_info = { .class_init = pcspk_class_initfn, }; +static int pcspk_audio_init_soundhw(ISABus *bus) +{ + PCSpkState *s = pcspk_state; + + warn_report("'-soundhw pcspk' is deprecated, " + "please set a backend using '-machine pcspk-audiodev=' instead"); + return pcspk_audio_init(s); +} + static void pcspk_register(void) { type_register_static(&pcspk_info); - isa_register_soundhw("pcspk", "PC speaker", pcspk_audio_init); + isa_register_soundhw("pcspk", "PC speaker", pcspk_audio_init_soundhw); } type_init(pcspk_register) diff --git a/hw/audio/pl041.c b/hw/audio/pl041.c index c3d3eab6ed3ea3edd919b1c812813acd0be1529f..03acd4fe344b95655cc9bf752d87251b486817d8 100644 --- a/hw/audio/pl041.c +++ b/hw/audio/pl041.c @@ -30,6 +30,7 @@ #include "pl041.h" #include "lm4549.h" #include "migration/vmstate.h" +#include "qom/object.h" #if 0 #define PL041_DEBUG_LEVEL 1 @@ -77,9 +78,9 @@ typedef struct { } pl041_channel; #define TYPE_PL041 "pl041" -#define PL041(obj) OBJECT_CHECK(PL041State, (obj), TYPE_PL041) +OBJECT_DECLARE_SIMPLE_TYPE(PL041State, PL041) -typedef struct PL041State { +struct PL041State { SysBusDevice parent_obj; MemoryRegion iomem; @@ -90,7 +91,7 @@ typedef struct PL041State { pl041_regfile regs; pl041_channel fifo1; lm4549_state codec; -} PL041State; +}; static const unsigned char pl041_default_id[8] = { diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c index df6f755a37f88cc9778da013667d9ce100f8270a..8b207004102548cd2f9e29bf840ad0c24ce9e740 100644 --- a/hw/audio/sb16.c +++ b/hw/audio/sb16.c @@ -34,6 +34,7 @@ #include "qemu/log.h" #include "qemu/module.h" #include "qapi/error.h" +#include "qom/object.h" #define dolog(...) AUD_log ("sb16", __VA_ARGS__) @@ -49,9 +50,9 @@ static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; #define TYPE_SB16 "sb16" -#define SB16(obj) OBJECT_CHECK (SB16State, (obj), TYPE_SB16) +OBJECT_DECLARE_SIMPLE_TYPE(SB16State, SB16) -typedef struct SB16State { +struct SB16State { ISADevice parent_obj; QEMUSoundCard card; @@ -112,7 +113,7 @@ typedef struct SB16State { int mixer_nreg; uint8_t mixer_regs[256]; PortioList portio_list; -} SB16State; +}; static void SB_audio_callback (void *opaque, int free); @@ -1415,12 +1416,6 @@ static void sb16_realizefn (DeviceState *dev, Error **errp) AUD_register_card ("sb16", &s->card); } -static int SB16_init (ISABus *bus) -{ - isa_create_simple (bus, TYPE_SB16); - return 0; -} - static Property sb16_properties[] = { DEFINE_AUDIO_PROPERTIES(SB16State, card), DEFINE_PROP_UINT32 ("version", SB16State, ver, 0x0405), /* 4.5 */ @@ -1453,7 +1448,8 @@ static const TypeInfo sb16_info = { static void sb16_register_types (void) { type_register_static (&sb16_info); - isa_register_soundhw("sb16", "Creative Sound Blaster 16", SB16_init); + deprecated_register_soundhw("sb16", "Creative Sound Blaster 16", + 1, TYPE_SB16); } type_init (sb16_register_types) diff --git a/hw/audio/soundhw.c b/hw/audio/soundhw.c index c750473c8f0c48d7b9a25ea440964c9a2ba9cd76..173b674ff53aea0bcaef70f3880edcc792fc89a6 100644 --- a/hw/audio/soundhw.c +++ b/hw/audio/soundhw.c @@ -22,6 +22,7 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" +#include "qemu/option.h" #include "qemu/help_option.h" #include "qemu/error-report.h" #include "qom/object.h" @@ -32,6 +33,7 @@ struct soundhw { const char *name; const char *descr; + const char *typename; int enabled; int isa; union { @@ -65,6 +67,17 @@ void pci_register_soundhw(const char *name, const char *descr, soundhw_count++; } +void deprecated_register_soundhw(const char *name, const char *descr, + int isa, const char *typename) +{ + assert(soundhw_count < ARRAY_SIZE(soundhw) - 1); + soundhw[soundhw_count].name = name; + soundhw[soundhw_count].descr = descr; + soundhw[soundhw_count].isa = isa; + soundhw[soundhw_count].typename = typename; + soundhw_count++; +} + void select_soundhw(const char *optarg) { struct soundhw *c; @@ -136,7 +149,16 @@ void soundhw_init(void) for (c = soundhw; c->name; ++c) { if (c->enabled) { - if (c->isa) { + if (c->typename) { + warn_report("'-soundhw %s' is deprecated, " + "please use '-device %s' instead", + c->name, c->typename); + if (c->isa) { + isa_create_simple(isa_bus, c->typename); + } else { + pci_create_simple(pci_bus, -1, c->typename); + } + } else if (c->isa) { if (!isa_bus) { error_report("ISA bus not available for %s", c->name); exit(1); diff --git a/hw/audio/trace.h b/hw/audio/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..5c7516a4d104fdbda2873f58ad0a76d05f93114e --- /dev/null +++ b/hw/audio/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_audio.h" diff --git a/hw/audio/wm8750.c b/hw/audio/wm8750.c index 92b2902a10297de8f7a90fd4c66b5c0db639d106..b5722b37c36be6e3f2fc036908cbe01331062a3b 100644 --- a/hw/audio/wm8750.c +++ b/hw/audio/wm8750.c @@ -13,6 +13,7 @@ #include "qemu/module.h" #include "hw/audio/wm8750.h" #include "audio/audio.h" +#include "qom/object.h" #define IN_PORT_N 3 #define OUT_PORT_N 3 @@ -26,9 +27,9 @@ typedef struct { int dac_hz; } WMRate; -#define WM8750(obj) OBJECT_CHECK(WM8750State, (obj), TYPE_WM8750) +OBJECT_DECLARE_SIMPLE_TYPE(WM8750State, WM8750) -typedef struct WM8750State { +struct WM8750State { I2CSlave parent_obj; uint8_t i2c_data[2]; @@ -54,7 +55,7 @@ typedef struct WM8750State { const WMRate *rate; uint8_t rate_vmstate; int adc_hz, dac_hz, ext_adc_hz, ext_dac_hz, master; -} WM8750State; +}; /* pow(10.0, -i / 20.0) * 255, i = 0..42 */ static const uint8_t wm8750_vol_db_table[] = { diff --git a/hw/avr/Kconfig b/hw/avr/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..d31298c3cce111dc6e8aba107bbbda7744419c26 --- /dev/null +++ b/hw/avr/Kconfig @@ -0,0 +1,9 @@ +config AVR_ATMEGA_MCU + bool + select AVR_TIMER16 + select AVR_USART + select AVR_POWER + +config ARDUINO + select AVR_ATMEGA_MCU + select UNIMP diff --git a/hw/avr/arduino.c b/hw/avr/arduino.c new file mode 100644 index 0000000000000000000000000000000000000000..3c8388490d668b4d7f7c980a10ade9b71926e481 --- /dev/null +++ b/hw/avr/arduino.c @@ -0,0 +1,148 @@ +/* + * QEMU Arduino boards + * + * Copyright (c) 2019-2020 Philippe Mathieu-DaudĂ© + * + * This work is licensed under the terms of the GNU GPLv2 or later. + * See the COPYING file in the top-level directory. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* TODO: Implement the use of EXTRAM */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/boards.h" +#include "atmega.h" +#include "boot.h" +#include "qom/object.h" + +struct ArduinoMachineState { + /*< private >*/ + MachineState parent_obj; + /*< public >*/ + AtmegaMcuState mcu; +}; +typedef struct ArduinoMachineState ArduinoMachineState; + +struct ArduinoMachineClass { + /*< private >*/ + MachineClass parent_class; + /*< public >*/ + const char *mcu_type; + uint64_t xtal_hz; +}; +typedef struct ArduinoMachineClass ArduinoMachineClass; + +#define TYPE_ARDUINO_MACHINE \ + MACHINE_TYPE_NAME("arduino") +DECLARE_OBJ_CHECKERS(ArduinoMachineState, ArduinoMachineClass, + ARDUINO_MACHINE, TYPE_ARDUINO_MACHINE) + +static void arduino_machine_init(MachineState *machine) +{ + ArduinoMachineClass *amc = ARDUINO_MACHINE_GET_CLASS(machine); + ArduinoMachineState *ams = ARDUINO_MACHINE(machine); + + object_initialize_child(OBJECT(machine), "mcu", &ams->mcu, amc->mcu_type); + object_property_set_uint(OBJECT(&ams->mcu), "xtal-frequency-hz", + amc->xtal_hz, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&ams->mcu), &error_abort); + + if (machine->firmware) { + if (!avr_load_firmware(&ams->mcu.cpu, machine, + &ams->mcu.flash, machine->firmware)) { + exit(1); + } + } +} + +static void arduino_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->init = arduino_machine_init; + mc->default_cpus = 1; + mc->min_cpus = mc->default_cpus; + mc->max_cpus = mc->default_cpus; + mc->no_floppy = 1; + mc->no_cdrom = 1; + mc->no_parallel = 1; +} + +static void arduino_duemilanove_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + ArduinoMachineClass *amc = ARDUINO_MACHINE_CLASS(oc); + + /* https://www.arduino.cc/en/Main/ArduinoBoardDuemilanove */ + mc->desc = "Arduino Duemilanove (ATmega168)", + mc->alias = "2009"; + amc->mcu_type = TYPE_ATMEGA168_MCU; + amc->xtal_hz = 16 * 1000 * 1000; +}; + +static void arduino_uno_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + ArduinoMachineClass *amc = ARDUINO_MACHINE_CLASS(oc); + + /* https://store.arduino.cc/arduino-uno-rev3 */ + mc->desc = "Arduino UNO (ATmega328P)"; + mc->alias = "uno"; + amc->mcu_type = TYPE_ATMEGA328_MCU; + amc->xtal_hz = 16 * 1000 * 1000; +}; + +static void arduino_mega_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + ArduinoMachineClass *amc = ARDUINO_MACHINE_CLASS(oc); + + /* https://www.arduino.cc/en/Main/ArduinoBoardMega */ + mc->desc = "Arduino Mega (ATmega1280)"; + mc->alias = "mega"; + amc->mcu_type = TYPE_ATMEGA1280_MCU; + amc->xtal_hz = 16 * 1000 * 1000; +}; + +static void arduino_mega2560_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + ArduinoMachineClass *amc = ARDUINO_MACHINE_CLASS(oc); + + /* https://store.arduino.cc/arduino-mega-2560-rev3 */ + mc->desc = "Arduino Mega 2560 (ATmega2560)"; + mc->alias = "mega2560"; + amc->mcu_type = TYPE_ATMEGA2560_MCU; + amc->xtal_hz = 16 * 1000 * 1000; /* CSTCE16M0V53-R0 */ +}; + +static const TypeInfo arduino_machine_types[] = { + { + .name = MACHINE_TYPE_NAME("arduino-duemilanove"), + .parent = TYPE_ARDUINO_MACHINE, + .class_init = arduino_duemilanove_class_init, + }, { + .name = MACHINE_TYPE_NAME("arduino-uno"), + .parent = TYPE_ARDUINO_MACHINE, + .class_init = arduino_uno_class_init, + }, { + .name = MACHINE_TYPE_NAME("arduino-mega"), + .parent = TYPE_ARDUINO_MACHINE, + .class_init = arduino_mega_class_init, + }, { + .name = MACHINE_TYPE_NAME("arduino-mega-2560-v3"), + .parent = TYPE_ARDUINO_MACHINE, + .class_init = arduino_mega2560_class_init, + }, { + .name = TYPE_ARDUINO_MACHINE, + .parent = TYPE_MACHINE, + .instance_size = sizeof(ArduinoMachineState), + .class_size = sizeof(ArduinoMachineClass), + .class_init = arduino_machine_class_init, + .abstract = true, + } +}; + +DEFINE_TYPES(arduino_machine_types) diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c new file mode 100644 index 0000000000000000000000000000000000000000..44c6afebbb66f2aa0d7248f7f4666a493bedacc5 --- /dev/null +++ b/hw/avr/atmega.c @@ -0,0 +1,458 @@ +/* + * QEMU ATmega MCU + * + * Copyright (c) 2019-2020 Philippe Mathieu-DaudĂ© + * + * This work is licensed under the terms of the GNU GPLv2 or later. + * See the COPYING file in the top-level directory. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/module.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "exec/memory.h" +#include "exec/address-spaces.h" +#include "sysemu/sysemu.h" +#include "hw/qdev-properties.h" +#include "hw/sysbus.h" +#include "qom/object.h" +#include "hw/boards.h" /* FIXME memory_region_allocate_system_memory for sram */ +#include "hw/misc/unimp.h" +#include "atmega.h" + +enum AtmegaPeripheral { + POWER0, POWER1, + GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, + GPIOG, GPIOH, GPIOI, GPIOJ, GPIOK, GPIOL, + USART0, USART1, USART2, USART3, + TIMER0, TIMER1, TIMER2, TIMER3, TIMER4, TIMER5, + PERIFMAX +}; + +#define GPIO(n) (n + GPIOA) +#define USART(n) (n + USART0) +#define TIMER(n) (n + TIMER0) +#define POWER(n) (n + POWER0) + +typedef struct { + uint16_t addr; + enum AtmegaPeripheral power_index; + uint8_t power_bit; + /* timer specific */ + uint16_t intmask_addr; + uint16_t intflag_addr; + bool is_timer16; +} peripheral_cfg; + +struct AtmegaMcuClass { + /*< private >*/ + SysBusDeviceClass parent_class; + /*< public >*/ + const char *uc_name; + const char *cpu_type; + size_t flash_size; + size_t eeprom_size; + size_t sram_size; + size_t io_size; + size_t gpio_count; + size_t adc_count; + const uint8_t *irq; + const peripheral_cfg *dev; +}; +typedef struct AtmegaMcuClass AtmegaMcuClass; + +DECLARE_CLASS_CHECKERS(AtmegaMcuClass, ATMEGA_MCU, + TYPE_ATMEGA_MCU) + +static const peripheral_cfg dev168_328[PERIFMAX] = { + [USART0] = { 0xc0, POWER0, 1 }, + [TIMER2] = { 0xb0, POWER0, 6, 0x70, 0x37, false }, + [TIMER1] = { 0x80, POWER0, 3, 0x6f, 0x36, true }, + [POWER0] = { 0x64 }, + [TIMER0] = { 0x44, POWER0, 5, 0x6e, 0x35, false }, + [GPIOD] = { 0x29 }, + [GPIOC] = { 0x26 }, + [GPIOB] = { 0x23 }, +}, dev1280_2560[PERIFMAX] = { + [USART3] = { 0x130, POWER1, 2 }, + [TIMER5] = { 0x120, POWER1, 5, 0x73, 0x3a, true }, + [GPIOL] = { 0x109 }, + [GPIOK] = { 0x106 }, + [GPIOJ] = { 0x103 }, + [GPIOH] = { 0x100 }, + [USART2] = { 0xd0, POWER1, 1 }, + [USART1] = { 0xc8, POWER1, 0 }, + [USART0] = { 0xc0, POWER0, 1 }, + [TIMER2] = { 0xb0, POWER0, 6, 0x70, 0x37, false }, /* TODO async */ + [TIMER4] = { 0xa0, POWER1, 4, 0x72, 0x39, true }, + [TIMER3] = { 0x90, POWER1, 3, 0x71, 0x38, true }, + [TIMER1] = { 0x80, POWER0, 3, 0x6f, 0x36, true }, + [POWER1] = { 0x65 }, + [POWER0] = { 0x64 }, + [TIMER0] = { 0x44, POWER0, 5, 0x6e, 0x35, false }, + [GPIOG] = { 0x32 }, + [GPIOF] = { 0x2f }, + [GPIOE] = { 0x2c }, + [GPIOD] = { 0x29 }, + [GPIOC] = { 0x26 }, + [GPIOB] = { 0x23 }, + [GPIOA] = { 0x20 }, +}; + +enum AtmegaIrq { + USART0_RXC_IRQ, USART0_DRE_IRQ, USART0_TXC_IRQ, + USART1_RXC_IRQ, USART1_DRE_IRQ, USART1_TXC_IRQ, + USART2_RXC_IRQ, USART2_DRE_IRQ, USART2_TXC_IRQ, + USART3_RXC_IRQ, USART3_DRE_IRQ, USART3_TXC_IRQ, + TIMER0_CAPT_IRQ, TIMER0_COMPA_IRQ, TIMER0_COMPB_IRQ, + TIMER0_COMPC_IRQ, TIMER0_OVF_IRQ, + TIMER1_CAPT_IRQ, TIMER1_COMPA_IRQ, TIMER1_COMPB_IRQ, + TIMER1_COMPC_IRQ, TIMER1_OVF_IRQ, + TIMER2_CAPT_IRQ, TIMER2_COMPA_IRQ, TIMER2_COMPB_IRQ, + TIMER2_COMPC_IRQ, TIMER2_OVF_IRQ, + TIMER3_CAPT_IRQ, TIMER3_COMPA_IRQ, TIMER3_COMPB_IRQ, + TIMER3_COMPC_IRQ, TIMER3_OVF_IRQ, + TIMER4_CAPT_IRQ, TIMER4_COMPA_IRQ, TIMER4_COMPB_IRQ, + TIMER4_COMPC_IRQ, TIMER4_OVF_IRQ, + TIMER5_CAPT_IRQ, TIMER5_COMPA_IRQ, TIMER5_COMPB_IRQ, + TIMER5_COMPC_IRQ, TIMER5_OVF_IRQ, + IRQ_COUNT +}; + +#define USART_IRQ_COUNT 3 +#define USART_RXC_IRQ(n) (n * USART_IRQ_COUNT + USART0_RXC_IRQ) +#define USART_DRE_IRQ(n) (n * USART_IRQ_COUNT + USART0_DRE_IRQ) +#define USART_TXC_IRQ(n) (n * USART_IRQ_COUNT + USART0_TXC_IRQ) +#define TIMER_IRQ_COUNT 5 +#define TIMER_CAPT_IRQ(n) (n * TIMER_IRQ_COUNT + TIMER0_CAPT_IRQ) +#define TIMER_COMPA_IRQ(n) (n * TIMER_IRQ_COUNT + TIMER0_COMPA_IRQ) +#define TIMER_COMPB_IRQ(n) (n * TIMER_IRQ_COUNT + TIMER0_COMPB_IRQ) +#define TIMER_COMPC_IRQ(n) (n * TIMER_IRQ_COUNT + TIMER0_COMPC_IRQ) +#define TIMER_OVF_IRQ(n) (n * TIMER_IRQ_COUNT + TIMER0_OVF_IRQ) + +static const uint8_t irq168_328[IRQ_COUNT] = { + [TIMER2_COMPA_IRQ] = 8, + [TIMER2_COMPB_IRQ] = 9, + [TIMER2_OVF_IRQ] = 10, + [TIMER1_CAPT_IRQ] = 11, + [TIMER1_COMPA_IRQ] = 12, + [TIMER1_COMPB_IRQ] = 13, + [TIMER1_OVF_IRQ] = 14, + [TIMER0_COMPA_IRQ] = 15, + [TIMER0_COMPB_IRQ] = 16, + [TIMER0_OVF_IRQ] = 17, + [USART0_RXC_IRQ] = 19, + [USART0_DRE_IRQ] = 20, + [USART0_TXC_IRQ] = 21, +}, irq1280_2560[IRQ_COUNT] = { + [TIMER2_COMPA_IRQ] = 14, + [TIMER2_COMPB_IRQ] = 15, + [TIMER2_OVF_IRQ] = 16, + [TIMER1_CAPT_IRQ] = 17, + [TIMER1_COMPA_IRQ] = 18, + [TIMER1_COMPB_IRQ] = 19, + [TIMER1_COMPC_IRQ] = 20, + [TIMER1_OVF_IRQ] = 21, + [TIMER0_COMPA_IRQ] = 22, + [TIMER0_COMPB_IRQ] = 23, + [TIMER0_OVF_IRQ] = 24, + [USART0_RXC_IRQ] = 26, + [USART0_DRE_IRQ] = 27, + [USART0_TXC_IRQ] = 28, + [TIMER3_CAPT_IRQ] = 32, + [TIMER3_COMPA_IRQ] = 33, + [TIMER3_COMPB_IRQ] = 34, + [TIMER3_COMPC_IRQ] = 35, + [TIMER3_OVF_IRQ] = 36, + [USART1_RXC_IRQ] = 37, + [USART1_DRE_IRQ] = 38, + [USART1_TXC_IRQ] = 39, + [TIMER4_CAPT_IRQ] = 42, + [TIMER4_COMPA_IRQ] = 43, + [TIMER4_COMPB_IRQ] = 44, + [TIMER4_COMPC_IRQ] = 45, + [TIMER4_OVF_IRQ] = 46, + [TIMER5_CAPT_IRQ] = 47, + [TIMER5_COMPA_IRQ] = 48, + [TIMER5_COMPB_IRQ] = 49, + [TIMER5_COMPC_IRQ] = 50, + [TIMER5_OVF_IRQ] = 51, + [USART2_RXC_IRQ] = 52, + [USART2_DRE_IRQ] = 53, + [USART2_TXC_IRQ] = 54, + [USART3_RXC_IRQ] = 55, + [USART3_DRE_IRQ] = 56, + [USART3_TXC_IRQ] = 57, +}; + +static void connect_peripheral_irq(const AtmegaMcuClass *k, + SysBusDevice *dev, int dev_irqn, + DeviceState *cpu, + unsigned peripheral_index) +{ + int cpu_irq = k->irq[peripheral_index]; + + if (!cpu_irq) { + return; + } + /* FIXME move that to avr_cpu_set_int() once 'sample' board is removed */ + assert(cpu_irq >= 2); + cpu_irq -= 2; + + sysbus_connect_irq(dev, dev_irqn, qdev_get_gpio_in(cpu, cpu_irq)); +} + +static void connect_power_reduction_gpio(AtmegaMcuState *s, + const AtmegaMcuClass *k, + DeviceState *cpu, + unsigned peripheral_index) +{ + unsigned power_index = k->dev[peripheral_index].power_index; + assert(k->dev[power_index].addr); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->pwr[power_index - POWER0]), + k->dev[peripheral_index].power_bit, + qdev_get_gpio_in(cpu, 0)); +} + +static void atmega_realize(DeviceState *dev, Error **errp) +{ + AtmegaMcuState *s = ATMEGA_MCU(dev); + const AtmegaMcuClass *mc = ATMEGA_MCU_GET_CLASS(dev); + DeviceState *cpudev; + SysBusDevice *sbd; + char *devname; + size_t i; + + assert(mc->io_size <= 0x200); + + if (!s->xtal_freq_hz) { + error_setg(errp, "\"xtal-frequency-hz\" property must be provided."); + return; + } + + /* CPU */ + object_initialize_child(OBJECT(dev), "cpu", &s->cpu, mc->cpu_type); + object_property_set_bool(OBJECT(&s->cpu), "realized", true, &error_abort); + cpudev = DEVICE(&s->cpu); + + /* SRAM */ + memory_region_init_ram(&s->sram, OBJECT(dev), "sram", mc->sram_size, + &error_abort); + memory_region_add_subregion(get_system_memory(), + OFFSET_DATA + mc->io_size, &s->sram); + + /* Flash */ + memory_region_init_rom(&s->flash, OBJECT(dev), + "flash", mc->flash_size, &error_fatal); + memory_region_add_subregion(get_system_memory(), OFFSET_CODE, &s->flash); + + /* + * I/O + * + * 0x00 - 0x1f: Registers + * 0x20 - 0x5f: I/O memory + * 0x60 - 0xff: Extended I/O + */ + s->io = qdev_new(TYPE_UNIMPLEMENTED_DEVICE); + qdev_prop_set_string(s->io, "name", "I/O"); + qdev_prop_set_uint64(s->io, "size", mc->io_size); + sysbus_realize_and_unref(SYS_BUS_DEVICE(s->io), &error_fatal); + sysbus_mmio_map_overlap(SYS_BUS_DEVICE(s->io), 0, OFFSET_DATA, -1234); + + /* Power Reduction */ + for (i = 0; i < POWER_MAX; i++) { + int idx = POWER(i); + if (!mc->dev[idx].addr) { + continue; + } + devname = g_strdup_printf("power%zu", i); + object_initialize_child(OBJECT(dev), devname, &s->pwr[i], + TYPE_AVR_MASK); + sysbus_realize(SYS_BUS_DEVICE(&s->pwr[i]), &error_abort); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->pwr[i]), 0, + OFFSET_DATA + mc->dev[idx].addr); + g_free(devname); + } + + /* GPIO */ + for (i = 0; i < GPIO_MAX; i++) { + int idx = GPIO(i); + if (!mc->dev[idx].addr) { + continue; + } + devname = g_strdup_printf("atmega-gpio-%c", 'a' + (char)i); + create_unimplemented_device(devname, + OFFSET_DATA + mc->dev[idx].addr, 3); + g_free(devname); + } + + /* USART */ + for (i = 0; i < USART_MAX; i++) { + int idx = USART(i); + if (!mc->dev[idx].addr) { + continue; + } + devname = g_strdup_printf("usart%zu", i); + object_initialize_child(OBJECT(dev), devname, &s->usart[i], + TYPE_AVR_USART); + qdev_prop_set_chr(DEVICE(&s->usart[i]), "chardev", serial_hd(i)); + sbd = SYS_BUS_DEVICE(&s->usart[i]); + sysbus_realize(sbd, &error_abort); + sysbus_mmio_map(sbd, 0, OFFSET_DATA + mc->dev[USART(i)].addr); + connect_peripheral_irq(mc, sbd, 0, cpudev, USART_RXC_IRQ(i)); + connect_peripheral_irq(mc, sbd, 1, cpudev, USART_DRE_IRQ(i)); + connect_peripheral_irq(mc, sbd, 2, cpudev, USART_TXC_IRQ(i)); + connect_power_reduction_gpio(s, mc, DEVICE(&s->usart[i]), idx); + g_free(devname); + } + + /* Timer */ + for (i = 0; i < TIMER_MAX; i++) { + int idx = TIMER(i); + if (!mc->dev[idx].addr) { + continue; + } + if (!mc->dev[idx].is_timer16) { + create_unimplemented_device("avr-timer8", + OFFSET_DATA + mc->dev[idx].addr, 5); + create_unimplemented_device("avr-timer8-intmask", + OFFSET_DATA + + mc->dev[idx].intmask_addr, 1); + create_unimplemented_device("avr-timer8-intflag", + OFFSET_DATA + + mc->dev[idx].intflag_addr, 1); + continue; + } + devname = g_strdup_printf("timer%zu", i); + object_initialize_child(OBJECT(dev), devname, &s->timer[i], + TYPE_AVR_TIMER16); + object_property_set_uint(OBJECT(&s->timer[i]), "cpu-frequency-hz", + s->xtal_freq_hz, &error_abort); + sbd = SYS_BUS_DEVICE(&s->timer[i]); + sysbus_realize(sbd, &error_abort); + sysbus_mmio_map(sbd, 0, OFFSET_DATA + mc->dev[idx].addr); + sysbus_mmio_map(sbd, 1, OFFSET_DATA + mc->dev[idx].intmask_addr); + sysbus_mmio_map(sbd, 2, OFFSET_DATA + mc->dev[idx].intflag_addr); + connect_peripheral_irq(mc, sbd, 0, cpudev, TIMER_CAPT_IRQ(i)); + connect_peripheral_irq(mc, sbd, 1, cpudev, TIMER_COMPA_IRQ(i)); + connect_peripheral_irq(mc, sbd, 2, cpudev, TIMER_COMPB_IRQ(i)); + connect_peripheral_irq(mc, sbd, 3, cpudev, TIMER_COMPC_IRQ(i)); + connect_peripheral_irq(mc, sbd, 4, cpudev, TIMER_OVF_IRQ(i)); + connect_power_reduction_gpio(s, mc, DEVICE(&s->timer[i]), idx); + g_free(devname); + } + + create_unimplemented_device("avr-twi", OFFSET_DATA + 0x0b8, 6); + create_unimplemented_device("avr-adc", OFFSET_DATA + 0x078, 8); + create_unimplemented_device("avr-ext-mem-ctrl", OFFSET_DATA + 0x074, 2); + create_unimplemented_device("avr-watchdog", OFFSET_DATA + 0x060, 1); + create_unimplemented_device("avr-spi", OFFSET_DATA + 0x04c, 3); + create_unimplemented_device("avr-eeprom", OFFSET_DATA + 0x03f, 3); +} + +static Property atmega_props[] = { + DEFINE_PROP_UINT64("xtal-frequency-hz", AtmegaMcuState, + xtal_freq_hz, 0), + DEFINE_PROP_END_OF_LIST() +}; + +static void atmega_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = atmega_realize; + device_class_set_props(dc, atmega_props); + /* Reason: Mapped at fixed location on the system bus */ + dc->user_creatable = false; +} + +static void atmega168_class_init(ObjectClass *oc, void *data) +{ + AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc); + + amc->cpu_type = AVR_CPU_TYPE_NAME("avr5"); + amc->flash_size = 16 * KiB; + amc->eeprom_size = 512; + amc->sram_size = 1 * KiB; + amc->io_size = 256; + amc->gpio_count = 23; + amc->adc_count = 6; + amc->irq = irq168_328; + amc->dev = dev168_328; +}; + +static void atmega328_class_init(ObjectClass *oc, void *data) +{ + AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc); + + amc->cpu_type = AVR_CPU_TYPE_NAME("avr5"); + amc->flash_size = 32 * KiB; + amc->eeprom_size = 1 * KiB; + amc->sram_size = 2 * KiB; + amc->io_size = 256; + amc->gpio_count = 23; + amc->adc_count = 6; + amc->irq = irq168_328; + amc->dev = dev168_328; +}; + +static void atmega1280_class_init(ObjectClass *oc, void *data) +{ + AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc); + + amc->cpu_type = AVR_CPU_TYPE_NAME("avr6"); + amc->flash_size = 128 * KiB; + amc->eeprom_size = 4 * KiB; + amc->sram_size = 8 * KiB; + amc->io_size = 512; + amc->gpio_count = 86; + amc->adc_count = 16; + amc->irq = irq1280_2560; + amc->dev = dev1280_2560; +}; + +static void atmega2560_class_init(ObjectClass *oc, void *data) +{ + AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc); + + amc->cpu_type = AVR_CPU_TYPE_NAME("avr6"); + amc->flash_size = 256 * KiB; + amc->eeprom_size = 4 * KiB; + amc->sram_size = 8 * KiB; + amc->io_size = 512; + amc->gpio_count = 54; + amc->adc_count = 16; + amc->irq = irq1280_2560; + amc->dev = dev1280_2560; +}; + +static const TypeInfo atmega_mcu_types[] = { + { + .name = TYPE_ATMEGA168_MCU, + .parent = TYPE_ATMEGA_MCU, + .class_init = atmega168_class_init, + }, { + .name = TYPE_ATMEGA328_MCU, + .parent = TYPE_ATMEGA_MCU, + .class_init = atmega328_class_init, + }, { + .name = TYPE_ATMEGA1280_MCU, + .parent = TYPE_ATMEGA_MCU, + .class_init = atmega1280_class_init, + }, { + .name = TYPE_ATMEGA2560_MCU, + .parent = TYPE_ATMEGA_MCU, + .class_init = atmega2560_class_init, + }, { + .name = TYPE_ATMEGA_MCU, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AtmegaMcuState), + .class_size = sizeof(AtmegaMcuClass), + .class_init = atmega_class_init, + .abstract = true, + } +}; + +DEFINE_TYPES(atmega_mcu_types) diff --git a/hw/avr/atmega.h b/hw/avr/atmega.h new file mode 100644 index 0000000000000000000000000000000000000000..a99ee15c7e18c601d99614813af13eb55d6681d8 --- /dev/null +++ b/hw/avr/atmega.h @@ -0,0 +1,51 @@ +/* + * QEMU ATmega MCU + * + * Copyright (c) 2019-2020 Philippe Mathieu-DaudĂ© + * + * This work is licensed under the terms of the GNU GPLv2 or later. + * See the COPYING file in the top-level directory. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_AVR_ATMEGA_H +#define HW_AVR_ATMEGA_H + +#include "hw/char/avr_usart.h" +#include "hw/timer/avr_timer16.h" +#include "hw/misc/avr_power.h" +#include "target/avr/cpu.h" +#include "qom/object.h" + +#define TYPE_ATMEGA_MCU "ATmega" +#define TYPE_ATMEGA168_MCU "ATmega168" +#define TYPE_ATMEGA328_MCU "ATmega328" +#define TYPE_ATMEGA1280_MCU "ATmega1280" +#define TYPE_ATMEGA2560_MCU "ATmega2560" + +typedef struct AtmegaMcuState AtmegaMcuState; +DECLARE_INSTANCE_CHECKER(AtmegaMcuState, ATMEGA_MCU, + TYPE_ATMEGA_MCU) + +#define POWER_MAX 2 +#define USART_MAX 4 +#define TIMER_MAX 6 +#define GPIO_MAX 12 + +struct AtmegaMcuState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + AVRCPU cpu; + MemoryRegion flash; + MemoryRegion eeprom; + MemoryRegion sram; + DeviceState *io; + AVRMaskState pwr[POWER_MAX]; + AVRUsartState usart[USART_MAX]; + AVRTimer16State timer[TIMER_MAX]; + uint64_t xtal_freq_hz; +}; + +#endif /* HW_AVR_ATMEGA_H */ diff --git a/hw/avr/boot.c b/hw/avr/boot.c new file mode 100644 index 0000000000000000000000000000000000000000..d16bb3dbe1bcc18f15b70725b55e40ee2797942e --- /dev/null +++ b/hw/avr/boot.c @@ -0,0 +1,115 @@ +/* + * AVR loader helpers + * + * Copyright (c) 2019-2020 Philippe Mathieu-DaudĂ© + * + * This work is licensed under the terms of the GNU GPLv2 or later. + * See the COPYING file in the top-level directory. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "hw/loader.h" +#include "elf.h" +#include "boot.h" +#include "qemu/error-report.h" + +static const char *avr_elf_e_flags_to_cpu_type(uint32_t flags) +{ + switch (flags & EF_AVR_MACH) { + case bfd_mach_avr1: + return AVR_CPU_TYPE_NAME("avr1"); + case bfd_mach_avr2: + return AVR_CPU_TYPE_NAME("avr2"); + case bfd_mach_avr25: + return AVR_CPU_TYPE_NAME("avr25"); + case bfd_mach_avr3: + return AVR_CPU_TYPE_NAME("avr3"); + case bfd_mach_avr31: + return AVR_CPU_TYPE_NAME("avr31"); + case bfd_mach_avr35: + return AVR_CPU_TYPE_NAME("avr35"); + case bfd_mach_avr4: + return AVR_CPU_TYPE_NAME("avr4"); + case bfd_mach_avr5: + return AVR_CPU_TYPE_NAME("avr5"); + case bfd_mach_avr51: + return AVR_CPU_TYPE_NAME("avr51"); + case bfd_mach_avr6: + return AVR_CPU_TYPE_NAME("avr6"); + case bfd_mach_avrtiny: + return AVR_CPU_TYPE_NAME("avrtiny"); + case bfd_mach_avrxmega2: + return AVR_CPU_TYPE_NAME("xmega2"); + case bfd_mach_avrxmega3: + return AVR_CPU_TYPE_NAME("xmega3"); + case bfd_mach_avrxmega4: + return AVR_CPU_TYPE_NAME("xmega4"); + case bfd_mach_avrxmega5: + return AVR_CPU_TYPE_NAME("xmega5"); + case bfd_mach_avrxmega6: + return AVR_CPU_TYPE_NAME("xmega6"); + case bfd_mach_avrxmega7: + return AVR_CPU_TYPE_NAME("xmega7"); + default: + return NULL; + } +} + +bool avr_load_firmware(AVRCPU *cpu, MachineState *ms, + MemoryRegion *program_mr, const char *firmware) +{ + g_autofree char *filename = NULL; + int bytes_loaded; + uint64_t entry; + uint32_t e_flags; + + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, firmware); + if (filename == NULL) { + error_report("Unable to find %s", firmware); + return false; + } + + bytes_loaded = load_elf_ram_sym(filename, + NULL, NULL, NULL, + &entry, NULL, NULL, + &e_flags, 0, EM_AVR, 0, 0, + NULL, true, NULL); + if (bytes_loaded >= 0) { + /* If ELF file is provided, determine CPU type reading ELF e_flags. */ + const char *elf_cpu = avr_elf_e_flags_to_cpu_type(e_flags); + const char *mcu_cpu_type = object_get_typename(OBJECT(cpu)); + int cpu_len = strlen(mcu_cpu_type) - strlen(AVR_CPU_TYPE_SUFFIX); + + if (entry) { + error_report("BIOS entry_point must be 0x0000 " + "(ELF image '%s' has entry_point 0x%04" PRIx64 ")", + firmware, entry); + return false; + } + if (!elf_cpu) { + warn_report("Could not determine CPU type for ELF image '%s', " + "assuming '%.*s' CPU", + firmware, cpu_len, mcu_cpu_type); + return true; + } + if (strcmp(elf_cpu, mcu_cpu_type)) { + error_report("Current machine: %s with '%.*s' CPU", + MACHINE_GET_CLASS(ms)->desc, cpu_len, mcu_cpu_type); + error_report("ELF image '%s' is for '%.*s' CPU", + firmware, + (int)(strlen(elf_cpu) - strlen(AVR_CPU_TYPE_SUFFIX)), + elf_cpu); + return false; + } + } else { + bytes_loaded = load_image_mr(filename, program_mr); + } + if (bytes_loaded < 0) { + error_report("Unable to load firmware image %s as ELF or raw binary", + firmware); + return false; + } + return true; +} diff --git a/hw/avr/boot.h b/hw/avr/boot.h new file mode 100644 index 0000000000000000000000000000000000000000..684d553322bfb8b58bd2a9982eacc181517f865c --- /dev/null +++ b/hw/avr/boot.h @@ -0,0 +1,33 @@ +/* + * AVR loader helpers + * + * Copyright (c) 2019-2020 Philippe Mathieu-DaudĂ© + * + * This work is licensed under the terms of the GNU GPLv2 or later. + * See the COPYING file in the top-level directory. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_AVR_BOOT_H +#define HW_AVR_BOOT_H + +#include "hw/boards.h" +#include "cpu.h" + +/** + * avr_load_firmware: load an image into a memory region + * + * @cpu: Handle a AVR CPU object + * @ms: A MachineState + * @mr: Memory Region to load into + * @firmware: Path to the firmware file (raw binary or ELF format) + * + * Load a firmware supplied by the machine or by the user with the + * '-bios' command line option, and put it in target memory. + * + * Returns: true on success, false on error. + */ +bool avr_load_firmware(AVRCPU *cpu, MachineState *ms, + MemoryRegion *mr, const char *firmware); + +#endif diff --git a/hw/avr/meson.build b/hw/avr/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..46d53fb17e3487eca39e52ea61d41f8c7d4645ce --- /dev/null +++ b/hw/avr/meson.build @@ -0,0 +1,6 @@ +avr_ss = ss.source_set() +avr_ss.add(files('boot.c')) +avr_ss.add(when: 'CONFIG_AVR_ATMEGA_MCU', if_true: files('atmega.c')) +avr_ss.add(when: 'CONFIG_ARDUINO', if_true: files('arduino.c')) + +hw_arch += {'avr': avr_ss} diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs deleted file mode 100644 index 47960b5f0d3e453f7e8fcd741cf236c588c4f92f..0000000000000000000000000000000000000000 --- a/hw/block/Makefile.objs +++ /dev/null @@ -1,18 +0,0 @@ -common-obj-y += block.o cdrom.o hd-geometry.o -common-obj-$(CONFIG_FDC) += fdc.o -common-obj-$(CONFIG_SSI_M25P80) += m25p80.o -common-obj-$(CONFIG_NAND) += nand.o -common-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o -common-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o -common-obj-$(CONFIG_XEN) += xen-block.o -common-obj-$(CONFIG_ECC) += ecc.o -common-obj-$(CONFIG_ONENAND) += onenand.o -common-obj-$(CONFIG_SWIM) += swim.o - -common-obj-$(CONFIG_SH4) += tc58128.o - -obj-$(CONFIG_VIRTIO_BLK) += virtio-blk.o -obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk.o -obj-$(CONFIG_NVME_PCI) += nvme.o - -obj-y += dataplane/ diff --git a/hw/block/block.c b/hw/block/block.c index bf56c7612bc0ee33b57275218169992536a7749e..1e34573da71b9ee5acfbd9f1f9e010563d3740e9 100644 --- a/hw/block/block.c +++ b/hw/block/block.c @@ -61,7 +61,7 @@ bool blk_check_size_and_read_all(BlockBackend *blk, void *buf, hwaddr size, return true; } -void blkconf_blocksizes(BlockConf *conf) +bool blkconf_blocksizes(BlockConf *conf, Error **errp) { BlockBackend *blk = conf->blk; BlockSizes blocksizes; @@ -83,6 +83,44 @@ void blkconf_blocksizes(BlockConf *conf) conf->logical_block_size = BDRV_SECTOR_SIZE; } } + + if (conf->logical_block_size > conf->physical_block_size) { + error_setg(errp, + "logical_block_size > physical_block_size not supported"); + return false; + } + + if (!QEMU_IS_ALIGNED(conf->min_io_size, conf->logical_block_size)) { + error_setg(errp, + "min_io_size must be a multiple of logical_block_size"); + return false; + } + + /* + * all devices which support min_io_size (scsi and virtio-blk) expose it to + * the guest as a uint16_t in units of logical blocks + */ + if (conf->min_io_size / conf->logical_block_size > UINT16_MAX) { + error_setg(errp, "min_io_size must not exceed %u logical blocks", + UINT16_MAX); + return false; + } + + if (!QEMU_IS_ALIGNED(conf->opt_io_size, conf->logical_block_size)) { + error_setg(errp, + "opt_io_size must be a multiple of logical_block_size"); + return false; + } + + if (conf->discard_granularity != -1 && + !QEMU_IS_ALIGNED(conf->discard_granularity, + conf->logical_block_size)) { + error_setg(errp, "discard_granularity must be " + "a multiple of logical_block_size"); + return false; + } + + return true; } bool blkconf_apply_backend_options(BlockConf *conf, bool readonly, diff --git a/hw/block/dataplane/Makefile.objs b/hw/block/dataplane/Makefile.objs deleted file mode 100644 index 0c5270268e8a92515dca7958feb3650be80c9b99..0000000000000000000000000000000000000000 --- a/hw/block/dataplane/Makefile.objs +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_VIRTIO_BLK) += virtio-blk.o -obj-$(CONFIG_XEN) += xen-block.o diff --git a/hw/block/dataplane/meson.build b/hw/block/dataplane/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..12c6a264f10f647899551c179a7acdc0cca38372 --- /dev/null +++ b/hw/block/dataplane/meson.build @@ -0,0 +1,2 @@ +specific_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-blk.c')) +specific_ss.add(when: 'CONFIG_XEN', if_true: files('xen-block.c')) diff --git a/hw/block/dataplane/trace.h b/hw/block/dataplane/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..240cc598348eb704bffb3d57957593773f7d25d5 --- /dev/null +++ b/hw/block/dataplane/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_block_dataplane.h" diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 1b52e8159c8d1056f56bd5f7c22ff1bbf43a2966..37499c5564822521a7168ff913862189c8a0e90e 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -220,6 +220,9 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev) goto fail_guest_notifiers; } + /* Process queued requests before the ones in vring */ + virtio_blk_process_queued_requests(vblk, false); + /* Kick right away to begin processing requests already in vring */ for (i = 0; i < nvqs; i++) { VirtQueue *vq = virtio_get_queue(s->vdev, i); @@ -239,6 +242,11 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev) return 0; fail_guest_notifiers: + /* + * If we failed to set up the guest notifiers queued requests will be + * processed on the main context. + */ + virtio_blk_process_queued_requests(vblk, false); vblk->dataplane_disabled = true; s->starting = false; vblk->dataplane_started = true; diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c index 5f8f15778ba5ff87d718b6159974d41fb35b88c2..71c337c7b7e74085532754bb28b2f343e55416b5 100644 --- a/hw/block/dataplane/xen-block.c +++ b/hw/block/dataplane/xen-block.c @@ -723,8 +723,8 @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane, unsigned int protocol, Error **errp) { + ERRP_GUARD(); XenDevice *xendev = dataplane->xendev; - Error *local_err = NULL; unsigned int ring_size; unsigned int i; @@ -760,9 +760,8 @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane, } xen_device_set_max_grant_refs(xendev, dataplane->nr_ring_ref, - &local_err); - if (local_err) { - error_propagate(errp, local_err); + errp); + if (*errp) { goto stop; } @@ -770,9 +769,8 @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane, dataplane->ring_ref, dataplane->nr_ring_ref, PROT_READ | PROT_WRITE, - &local_err); - if (local_err) { - error_propagate(errp, local_err); + errp); + if (*errp) { goto stop; } @@ -805,9 +803,8 @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane, dataplane->event_channel = xen_device_bind_event_channel(xendev, event_channel, xen_block_dataplane_event, dataplane, - &local_err); - if (local_err) { - error_propagate(errp, local_err); + errp); + if (*errp) { goto stop; } diff --git a/hw/block/fdc.c b/hw/block/fdc.c index c5fb9d6ece772dbdd1290387db1d1a2416c7ae41..4c2c35e223aa5fccb6b855b1aa9e1d2cbe29e4e7 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -32,6 +32,7 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/timer.h" +#include "hw/acpi/aml-build.h" #include "hw/irq.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" @@ -45,6 +46,7 @@ #include "qemu/main-loop.h" #include "qemu/module.h" #include "trace.h" +#include "qom/object.h" /********************************************************/ /* debug Floppy devices */ @@ -63,16 +65,16 @@ /* qdev floppy bus */ #define TYPE_FLOPPY_BUS "floppy-bus" -#define FLOPPY_BUS(obj) OBJECT_CHECK(FloppyBus, (obj), TYPE_FLOPPY_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(FloppyBus, FLOPPY_BUS) typedef struct FDCtrl FDCtrl; typedef struct FDrive FDrive; static FDrive *get_drv(FDCtrl *fdctrl, int unit); -typedef struct FloppyBus { +struct FloppyBus { BusState bus; FDCtrl *fdc; -} FloppyBus; +}; static const TypeInfo floppy_bus_info = { .name = TYPE_FLOPPY_BUS, @@ -493,15 +495,14 @@ static const BlockDevOps fd_block_ops = { #define TYPE_FLOPPY_DRIVE "floppy" -#define FLOPPY_DRIVE(obj) \ - OBJECT_CHECK(FloppyDrive, (obj), TYPE_FLOPPY_DRIVE) +OBJECT_DECLARE_SIMPLE_TYPE(FloppyDrive, FLOPPY_DRIVE) -typedef struct FloppyDrive { +struct FloppyDrive { DeviceState qdev; uint32_t unit; BlockConf conf; FloppyDriveType type; -} FloppyDrive; +}; static Property floppy_drive_properties[] = { DEFINE_PROP_UINT32("unit", FloppyDrive, unit, -1), @@ -554,7 +555,10 @@ static void floppy_drive_realize(DeviceState *qdev, Error **errp) read_only = !blk_bs(dev->conf.blk) || blk_is_read_only(dev->conf.blk); } - blkconf_blocksizes(&dev->conf); + if (!blkconf_blocksizes(&dev->conf, errp)) { + return; + } + if (dev->conf.logical_block_size != 512 || dev->conf.physical_block_size != 512) { @@ -882,19 +886,19 @@ static FloppyDriveType get_fallback_drive_type(FDrive *drv) } #define TYPE_SYSBUS_FDC "base-sysbus-fdc" -#define SYSBUS_FDC(obj) OBJECT_CHECK(FDCtrlSysBus, (obj), TYPE_SYSBUS_FDC) +OBJECT_DECLARE_SIMPLE_TYPE(FDCtrlSysBus, SYSBUS_FDC) -typedef struct FDCtrlSysBus { +struct FDCtrlSysBus { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ struct FDCtrl state; -} FDCtrlSysBus; +}; -#define ISA_FDC(obj) OBJECT_CHECK(FDCtrlISABus, (obj), TYPE_ISA_FDC) +OBJECT_DECLARE_SIMPLE_TYPE(FDCtrlISABus, ISA_FDC) -typedef struct FDCtrlISABus { +struct FDCtrlISABus { ISADevice parent_obj; uint32_t iobase; @@ -903,7 +907,7 @@ typedef struct FDCtrlISABus { struct FDCtrl state; int32_t bootindexA; int32_t bootindexB; -} FDCtrlISABus; +}; static uint32_t fdctrl_read (void *opaque, uint32_t reg) { @@ -2494,6 +2498,29 @@ static void fdctrl_result_timer(void *opaque) } /* Init functions */ + +static void fdctrl_init_drives(FloppyBus *bus, DriveInfo **fds) +{ + DeviceState *dev; + int i; + + for (i = 0; i < MAX_FD; i++) { + if (fds[i]) { + dev = qdev_new("floppy"); + qdev_prop_set_uint32(dev, "unit", i); + qdev_prop_set_enum(dev, "drive-type", FLOPPY_DRIVE_TYPE_AUTO); + qdev_prop_set_drive_err(dev, "drive", blk_by_legacy_dinfo(fds[i]), + &error_fatal); + qdev_realize_and_unref(dev, &bus->bus, &error_fatal); + } + } +} + +void isa_fdc_init_drives(ISADevice *fdc, DriveInfo **fds) +{ + fdctrl_init_drives(&ISA_FDC(fdc)->state.bus, fds); +} + static void fdctrl_connect_drives(FDCtrl *fdctrl, DeviceState *fdc_dev, Error **errp) { @@ -2501,7 +2528,8 @@ static void fdctrl_connect_drives(FDCtrl *fdctrl, DeviceState *fdc_dev, FDrive *drive; DeviceState *dev; BlockBackend *blk; - Error *local_err = NULL; + bool ok; + const char *fdc_name, *drive_suffix; for (i = 0; i < MAX_FD; i++) { drive = &fdctrl->drives[i]; @@ -2516,53 +2544,41 @@ static void fdctrl_connect_drives(FDCtrl *fdctrl, DeviceState *fdc_dev, continue; } - dev = qdev_create(&fdctrl->bus.bus, "floppy"); + fdc_name = object_get_typename(OBJECT(fdc_dev)); + drive_suffix = !strcmp(fdc_name, "SUNW,fdtwo") ? "" : i ? "B" : "A"; + warn_report("warning: property %s.drive%s is deprecated", + fdc_name, drive_suffix); + error_printf("Use -device floppy,unit=%d,drive=... instead.\n", i); + + dev = qdev_new("floppy"); qdev_prop_set_uint32(dev, "unit", i); qdev_prop_set_enum(dev, "drive-type", fdctrl->qdev_for_drives[i].type); + /* + * Hack alert: we move the backend from the floppy controller + * device to the floppy device. We first need to detach the + * controller, or else floppy_create()'s qdev_prop_set_drive() + * will die when it attaches floppy device. We also need to + * take another reference so that blk_detach_dev() doesn't + * free blk while we still need it. + * + * The hack is probably a bad idea. + */ blk_ref(blk); blk_detach_dev(blk, fdc_dev); fdctrl->qdev_for_drives[i].blk = NULL; - qdev_prop_set_drive(dev, "drive", blk, &local_err); + ok = qdev_prop_set_drive_err(dev, "drive", blk, errp); blk_unref(blk); - - if (local_err) { - error_propagate(errp, local_err); + if (!ok) { return; } - object_property_set_bool(OBJECT(dev), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qdev_realize_and_unref(dev, &fdctrl->bus.bus, errp)) { return; } } } -ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds) -{ - DeviceState *dev; - ISADevice *isadev; - - isadev = isa_try_create(bus, TYPE_ISA_FDC); - if (!isadev) { - return NULL; - } - dev = DEVICE(isadev); - - if (fds[0]) { - qdev_prop_set_drive(dev, "driveA", blk_by_legacy_dinfo(fds[0]), - &error_fatal); - } - if (fds[1]) { - qdev_prop_set_drive(dev, "driveB", blk_by_legacy_dinfo(fds[1]), - &error_fatal); - } - qdev_init_nofail(dev); - - return isadev; -} - void fdctrl_init_sysbus(qemu_irq irq, int dma_chann, hwaddr mmio_base, DriveInfo **fds) { @@ -2571,22 +2587,16 @@ void fdctrl_init_sysbus(qemu_irq irq, int dma_chann, SysBusDevice *sbd; FDCtrlSysBus *sys; - dev = qdev_create(NULL, "sysbus-fdc"); + dev = qdev_new("sysbus-fdc"); sys = SYSBUS_FDC(dev); fdctrl = &sys->state; fdctrl->dma_chann = dma_chann; /* FIXME */ - if (fds[0]) { - qdev_prop_set_drive(dev, "driveA", blk_by_legacy_dinfo(fds[0]), - &error_fatal); - } - if (fds[1]) { - qdev_prop_set_drive(dev, "driveB", blk_by_legacy_dinfo(fds[1]), - &error_fatal); - } - qdev_init_nofail(dev); sbd = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sbd, &error_fatal); sysbus_connect_irq(sbd, 0, irq); sysbus_mmio_map(sbd, 0, mmio_base); + + fdctrl_init_drives(&sys->state.bus, fds); } void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base, @@ -2595,16 +2605,14 @@ void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base, DeviceState *dev; FDCtrlSysBus *sys; - dev = qdev_create(NULL, "SUNW,fdtwo"); - if (fds[0]) { - qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(fds[0]), - &error_fatal); - } - qdev_init_nofail(dev); + dev = qdev_new("SUNW,fdtwo"); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sys = SYSBUS_FDC(dev); sysbus_connect_irq(SYS_BUS_DEVICE(sys), 0, irq); sysbus_mmio_map(SYS_BUS_DEVICE(sys), 0, io_base); *fdc_tc = qdev_get_gpio_in(dev, 0); + + fdctrl_init_drives(&sys->state.bus, fds); } static void fdctrl_realize_common(DeviceState *dev, FDCtrl *fdctrl, @@ -2742,8 +2750,8 @@ FloppyDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i) return isa->state.drives[i].drive; } -void isa_fdc_get_drive_max_chs(FloppyDriveType type, - uint8_t *maxc, uint8_t *maxh, uint8_t *maxs) +static void isa_fdc_get_drive_max_chs(FloppyDriveType type, uint8_t *maxc, + uint8_t *maxh, uint8_t *maxs) { const FDFormat *fdf; @@ -2765,6 +2773,110 @@ void isa_fdc_get_drive_max_chs(FloppyDriveType type, (*maxc)--; } +static Aml *build_fdinfo_aml(int idx, FloppyDriveType type) +{ + Aml *dev, *fdi; + uint8_t maxc, maxh, maxs; + + isa_fdc_get_drive_max_chs(type, &maxc, &maxh, &maxs); + + dev = aml_device("FLP%c", 'A' + idx); + + aml_append(dev, aml_name_decl("_ADR", aml_int(idx))); + + fdi = aml_package(16); + aml_append(fdi, aml_int(idx)); /* Drive Number */ + aml_append(fdi, + aml_int(cmos_get_fd_drive_type(type))); /* Device Type */ + /* + * the values below are the limits of the drive, and are thus independent + * of the inserted media + */ + aml_append(fdi, aml_int(maxc)); /* Maximum Cylinder Number */ + aml_append(fdi, aml_int(maxs)); /* Maximum Sector Number */ + aml_append(fdi, aml_int(maxh)); /* Maximum Head Number */ + /* + * SeaBIOS returns the below values for int 0x13 func 0x08 regardless of + * the drive type, so shall we + */ + aml_append(fdi, aml_int(0xAF)); /* disk_specify_1 */ + aml_append(fdi, aml_int(0x02)); /* disk_specify_2 */ + aml_append(fdi, aml_int(0x25)); /* disk_motor_wait */ + aml_append(fdi, aml_int(0x02)); /* disk_sector_siz */ + aml_append(fdi, aml_int(0x12)); /* disk_eot */ + aml_append(fdi, aml_int(0x1B)); /* disk_rw_gap */ + aml_append(fdi, aml_int(0xFF)); /* disk_dtl */ + aml_append(fdi, aml_int(0x6C)); /* disk_formt_gap */ + aml_append(fdi, aml_int(0xF6)); /* disk_fill */ + aml_append(fdi, aml_int(0x0F)); /* disk_head_sttl */ + aml_append(fdi, aml_int(0x08)); /* disk_motor_strt */ + + aml_append(dev, aml_name_decl("_FDI", fdi)); + return dev; +} + +int cmos_get_fd_drive_type(FloppyDriveType fd0) +{ + int val; + + switch (fd0) { + case FLOPPY_DRIVE_TYPE_144: + /* 1.44 Mb 3"5 drive */ + val = 4; + break; + case FLOPPY_DRIVE_TYPE_288: + /* 2.88 Mb 3"5 drive */ + val = 5; + break; + case FLOPPY_DRIVE_TYPE_120: + /* 1.2 Mb 5"5 drive */ + val = 2; + break; + case FLOPPY_DRIVE_TYPE_NONE: + default: + val = 0; + break; + } + return val; +} + +static void fdc_isa_build_aml(ISADevice *isadev, Aml *scope) +{ + Aml *dev; + Aml *crs; + int i; + +#define ACPI_FDE_MAX_FD 4 + uint32_t fde_buf[5] = { + 0, 0, 0, 0, /* presence of floppy drives #0 - #3 */ + cpu_to_le32(2) /* tape presence (2 == never present) */ + }; + + crs = aml_resource_template(); + aml_append(crs, aml_io(AML_DECODE16, 0x03F2, 0x03F2, 0x00, 0x04)); + aml_append(crs, aml_io(AML_DECODE16, 0x03F7, 0x03F7, 0x00, 0x01)); + aml_append(crs, aml_irq_no_flags(6)); + aml_append(crs, + aml_dma(AML_COMPATIBILITY, AML_NOTBUSMASTER, AML_TRANSFER8, 2)); + + dev = aml_device("FDC0"); + aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0700"))); + aml_append(dev, aml_name_decl("_CRS", crs)); + + for (i = 0; i < MIN(MAX_FD, ACPI_FDE_MAX_FD); i++) { + FloppyDriveType type = isa_fdc_get_drive_type(isadev, i); + + if (type < FLOPPY_DRIVE_TYPE_NONE) { + fde_buf[i] = cpu_to_le32(1); /* drive present */ + aml_append(dev, build_fdinfo_aml(i, type)); + } + } + aml_append(dev, aml_name_decl("_FDE", + aml_buffer(sizeof(fde_buf), (uint8_t *)fde_buf))); + + aml_append(scope, dev); +} + static const VMStateDescription vmstate_isa_fdc ={ .name = "fdc", .version_id = 2, @@ -2798,11 +2910,13 @@ static Property isa_fdc_properties[] = { static void isabus_fdc_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *isa = ISA_DEVICE_CLASS(klass); dc->realize = isabus_fdc_realize; dc->fw_name = "fdc"; dc->reset = fdctrl_external_reset_isa; dc->vmsd = &vmstate_isa_fdc; + isa->build_aml = fdc_isa_build_aml; device_class_set_props(dc, isa_fdc_properties); set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); } diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index 82270884416e337221833bc543404e2749ff2f85..483925f57a9023f349bd70e8db9af24a9b54d3ac 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -33,6 +33,7 @@ #include "qemu/error-report.h" #include "qapi/error.h" #include "trace.h" +#include "qom/object.h" /* Fields for FlashPartInfo->flags */ @@ -217,8 +218,9 @@ static const FlashPartInfo known_devices[] = { { INFO("mx25l6405d", 0xc22017, 0, 64 << 10, 128, 0) }, { INFO("mx25l12805d", 0xc22018, 0, 64 << 10, 256, 0) }, { INFO("mx25l12855e", 0xc22618, 0, 64 << 10, 256, 0) }, - { INFO("mx25l25635e", 0xc22019, 0, 64 << 10, 512, 0) }, + { INFO6("mx25l25635e", 0xc22019, 0xc22019, 64 << 10, 512, 0) }, { INFO("mx25l25655e", 0xc22619, 0, 64 << 10, 512, 0) }, + { INFO("mx66l51235f", 0xc2201a, 0, 64 << 10, 1024, ER_4K | ER_32K) }, { INFO("mx66u51235f", 0xc2253a, 0, 64 << 10, 1024, ER_4K | ER_32K) }, { INFO("mx66u1g45g", 0xc2253b, 0, 64 << 10, 2048, ER_4K | ER_32K) }, { INFO("mx66l1g45g", 0xc2201b, 0, 64 << 10, 2048, ER_4K | ER_32K) }, @@ -237,6 +239,8 @@ static const FlashPartInfo known_devices[] = { { INFO("n25q128", 0x20ba18, 0, 64 << 10, 256, 0) }, { INFO("n25q256a", 0x20ba19, 0, 64 << 10, 512, ER_4K) }, { INFO("n25q512a", 0x20ba20, 0, 64 << 10, 1024, ER_4K) }, + { INFO("n25q512ax3", 0x20ba20, 0x1000, 64 << 10, 1024, ER_4K) }, + { INFO("mt25ql512ab", 0x20ba20, 0x1044, 64 << 10, 1024, ER_4K | ER_32K) }, { INFO_STACKED("n25q00", 0x20ba21, 0x1000, 64 << 10, 2048, ER_4K, 4) }, { INFO_STACKED("n25q00a", 0x20bb21, 0x1000, 64 << 10, 2048, ER_4K, 4) }, { INFO_STACKED("mt25ql01g", 0x20ba21, 0x1040, 64 << 10, 2048, ER_4K, 2) }, @@ -411,7 +415,7 @@ typedef enum { #define M25P80_INTERNAL_DATA_BUFFER_SZ 16 -typedef struct Flash { +struct Flash { SSISlave parent_obj; BlockBackend *blk; @@ -451,20 +455,15 @@ typedef struct Flash { const FlashPartInfo *pi; -} Flash; +}; -typedef struct M25P80Class { +struct M25P80Class { SSISlaveClass parent_class; FlashPartInfo *pi; -} M25P80Class; +}; #define TYPE_M25P80 "m25p80-generic" -#define M25P80(obj) \ - OBJECT_CHECK(Flash, (obj), TYPE_M25P80) -#define M25P80_CLASS(klass) \ - OBJECT_CLASS_CHECK(M25P80Class, (klass), TYPE_M25P80) -#define M25P80_GET_CLASS(obj) \ - OBJECT_GET_CLASS(M25P80Class, (obj), TYPE_M25P80) +OBJECT_DECLARE_TYPE(Flash, M25P80Class, M25P80) static inline Manufacturer get_man(Flash *s) { diff --git a/hw/block/meson.build b/hw/block/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..602ca6c8541dd48a900704927247d884e30ea0b5 --- /dev/null +++ b/hw/block/meson.build @@ -0,0 +1,21 @@ +softmmu_ss.add(files( + 'block.c', + 'cdrom.c', + 'hd-geometry.c' +)) +softmmu_ss.add(when: 'CONFIG_ECC', if_true: files('ecc.c')) +softmmu_ss.add(when: 'CONFIG_FDC', if_true: files('fdc.c')) +softmmu_ss.add(when: 'CONFIG_NAND', if_true: files('nand.c')) +softmmu_ss.add(when: 'CONFIG_ONENAND', if_true: files('onenand.c')) +softmmu_ss.add(when: 'CONFIG_PFLASH_CFI01', if_true: files('pflash_cfi01.c')) +softmmu_ss.add(when: 'CONFIG_PFLASH_CFI02', if_true: files('pflash_cfi02.c')) +softmmu_ss.add(when: 'CONFIG_SSI_M25P80', if_true: files('m25p80.c')) +softmmu_ss.add(when: 'CONFIG_SWIM', if_true: files('swim.c')) +softmmu_ss.add(when: 'CONFIG_XEN', if_true: files('xen-block.c')) +softmmu_ss.add(when: 'CONFIG_SH4', if_true: files('tc58128.c')) +softmmu_ss.add(when: 'CONFIG_NVME_PCI', if_true: files('nvme.c', 'nvme-ns.c')) + +specific_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-blk.c')) +specific_ss.add(when: 'CONFIG_VHOST_USER_BLK', if_true: files('vhost-user-blk.c')) + +subdir('dataplane') diff --git a/hw/block/nand.c b/hw/block/nand.c index bba89688ba0eb30737af3903d611329b657779ca..1d7a48a2ec2ad7ac77dc4b28f6779fd127428a6c 100644 --- a/hw/block/nand.c +++ b/hw/block/nand.c @@ -27,6 +27,7 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/module.h" +#include "qom/object.h" # define NAND_CMD_READ0 0x00 # define NAND_CMD_READ1 0x01 @@ -89,8 +90,7 @@ struct NANDFlashState { #define TYPE_NAND "nand" -#define NAND(obj) \ - OBJECT_CHECK(NANDFlashState, (obj), TYPE_NAND) +OBJECT_DECLARE_SIMPLE_TYPE(NANDFlashState, NAND) static void mem_and(uint8_t *dest, const uint8_t *src, size_t n) { @@ -449,6 +449,7 @@ static void nand_class_init(ObjectClass *klass, void *data) dc->reset = nand_reset; dc->vmsd = &vmstate_nand; device_class_set_props(dc, nand_properties); + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); } static const TypeInfo nand_info = { @@ -644,14 +645,14 @@ DeviceState *nand_init(BlockBackend *blk, int manf_id, int chip_id) if (nand_flash_ids[chip_id].size == 0) { hw_error("%s: Unsupported NAND chip ID.\n", __func__); } - dev = DEVICE(object_new(TYPE_NAND)); + dev = qdev_new(TYPE_NAND); qdev_prop_set_uint8(dev, "manufacturer_id", manf_id); qdev_prop_set_uint8(dev, "chip_id", chip_id); if (blk) { - qdev_prop_set_drive(dev, "drive", blk, &error_fatal); + qdev_prop_set_drive_err(dev, "drive", blk, &error_fatal); } - qdev_init_nofail(dev); + qdev_realize(dev, NULL, &error_fatal); return dev; } diff --git a/hw/block/nvme-ns.c b/hw/block/nvme-ns.c new file mode 100644 index 0000000000000000000000000000000000000000..31c80cdf5b5ff302052383cbada1b053336ea40f --- /dev/null +++ b/hw/block/nvme-ns.c @@ -0,0 +1,168 @@ +/* + * QEMU NVM Express Virtual Namespace + * + * Copyright (c) 2019 CNEX Labs + * Copyright (c) 2020 Samsung Electronics + * + * Authors: + * Klaus Jensen + * + * This work is licensed under the terms of the GNU GPL, version 2. See the + * COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qemu/cutils.h" +#include "qemu/log.h" +#include "hw/block/block.h" +#include "hw/pci/pci.h" +#include "sysemu/sysemu.h" +#include "sysemu/block-backend.h" +#include "qapi/error.h" + +#include "hw/qdev-properties.h" +#include "hw/qdev-core.h" + +#include "nvme.h" +#include "nvme-ns.h" + +static void nvme_ns_init(NvmeNamespace *ns) +{ + NvmeIdNs *id_ns = &ns->id_ns; + int lba_index = NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas); + + if (blk_get_flags(ns->blkconf.blk) & BDRV_O_UNMAP) { + ns->id_ns.dlfeat = 0x9; + } + + id_ns->lbaf[lba_index].ds = 31 - clz32(ns->blkconf.logical_block_size); + + id_ns->nsze = cpu_to_le64(nvme_ns_nlbas(ns)); + + /* no thin provisioning */ + id_ns->ncap = id_ns->nsze; + id_ns->nuse = id_ns->ncap; +} + +static int nvme_ns_init_blk(NvmeCtrl *n, NvmeNamespace *ns, Error **errp) +{ + if (!blkconf_blocksizes(&ns->blkconf, errp)) { + return -1; + } + + if (!blkconf_apply_backend_options(&ns->blkconf, + blk_is_read_only(ns->blkconf.blk), + false, errp)) { + return -1; + } + + ns->size = blk_getlength(ns->blkconf.blk); + if (ns->size < 0) { + error_setg_errno(errp, -ns->size, "could not get blockdev size"); + return -1; + } + + if (blk_enable_write_cache(ns->blkconf.blk)) { + n->features.vwc = 0x1; + } + + return 0; +} + +static int nvme_ns_check_constraints(NvmeNamespace *ns, Error **errp) +{ + if (!ns->blkconf.blk) { + error_setg(errp, "block backend not configured"); + return -1; + } + + return 0; +} + +int nvme_ns_setup(NvmeCtrl *n, NvmeNamespace *ns, Error **errp) +{ + if (nvme_ns_check_constraints(ns, errp)) { + return -1; + } + + if (nvme_ns_init_blk(n, ns, errp)) { + return -1; + } + + nvme_ns_init(ns); + if (nvme_register_namespace(n, ns, errp)) { + return -1; + } + + return 0; +} + +void nvme_ns_drain(NvmeNamespace *ns) +{ + blk_drain(ns->blkconf.blk); +} + +void nvme_ns_flush(NvmeNamespace *ns) +{ + blk_flush(ns->blkconf.blk); +} + +static void nvme_ns_realize(DeviceState *dev, Error **errp) +{ + NvmeNamespace *ns = NVME_NS(dev); + BusState *s = qdev_get_parent_bus(dev); + NvmeCtrl *n = NVME(s->parent); + Error *local_err = NULL; + + if (nvme_ns_setup(n, ns, &local_err)) { + error_propagate_prepend(errp, local_err, + "could not setup namespace: "); + return; + } +} + +static Property nvme_ns_props[] = { + DEFINE_BLOCK_PROPERTIES(NvmeNamespace, blkconf), + DEFINE_PROP_UINT32("nsid", NvmeNamespace, params.nsid, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void nvme_ns_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + + dc->bus_type = TYPE_NVME_BUS; + dc->realize = nvme_ns_realize; + device_class_set_props(dc, nvme_ns_props); + dc->desc = "Virtual NVMe namespace"; +} + +static void nvme_ns_instance_init(Object *obj) +{ + NvmeNamespace *ns = NVME_NS(obj); + char *bootindex = g_strdup_printf("/namespace@%d,0", ns->params.nsid); + + device_add_bootindex_property(obj, &ns->bootindex, "bootindex", + bootindex, DEVICE(obj)); + + g_free(bootindex); +} + +static const TypeInfo nvme_ns_info = { + .name = TYPE_NVME_NS, + .parent = TYPE_DEVICE, + .class_init = nvme_ns_class_init, + .instance_size = sizeof(NvmeNamespace), + .instance_init = nvme_ns_instance_init, +}; + +static void nvme_ns_register_types(void) +{ + type_register_static(&nvme_ns_info); +} + +type_init(nvme_ns_register_types) diff --git a/hw/block/nvme-ns.h b/hw/block/nvme-ns.h new file mode 100644 index 0000000000000000000000000000000000000000..83734f4606e16312e2e975858c0ed0d35356c13c --- /dev/null +++ b/hw/block/nvme-ns.h @@ -0,0 +1,74 @@ +/* + * QEMU NVM Express Virtual Namespace + * + * Copyright (c) 2019 CNEX Labs + * Copyright (c) 2020 Samsung Electronics + * + * Authors: + * Klaus Jensen + * + * This work is licensed under the terms of the GNU GPL, version 2. See the + * COPYING file in the top-level directory. + * + */ + +#ifndef NVME_NS_H +#define NVME_NS_H + +#define TYPE_NVME_NS "nvme-ns" +#define NVME_NS(obj) \ + OBJECT_CHECK(NvmeNamespace, (obj), TYPE_NVME_NS) + +typedef struct NvmeNamespaceParams { + uint32_t nsid; +} NvmeNamespaceParams; + +typedef struct NvmeNamespace { + DeviceState parent_obj; + BlockConf blkconf; + int32_t bootindex; + int64_t size; + NvmeIdNs id_ns; + + NvmeNamespaceParams params; +} NvmeNamespace; + +static inline uint32_t nvme_nsid(NvmeNamespace *ns) +{ + if (ns) { + return ns->params.nsid; + } + + return -1; +} + +static inline NvmeLBAF *nvme_ns_lbaf(NvmeNamespace *ns) +{ + NvmeIdNs *id_ns = &ns->id_ns; + return &id_ns->lbaf[NVME_ID_NS_FLBAS_INDEX(id_ns->flbas)]; +} + +static inline uint8_t nvme_ns_lbads(NvmeNamespace *ns) +{ + return nvme_ns_lbaf(ns)->ds; +} + +/* calculate the number of LBAs that the namespace can accomodate */ +static inline uint64_t nvme_ns_nlbas(NvmeNamespace *ns) +{ + return ns->size >> nvme_ns_lbads(ns); +} + +/* convert an LBA to the equivalent in bytes */ +static inline size_t nvme_l2b(NvmeNamespace *ns, uint64_t lba) +{ + return lba << nvme_ns_lbads(ns); +} + +typedef struct NvmeCtrl NvmeCtrl; + +int nvme_ns_setup(NvmeCtrl *n, NvmeNamespace *ns, Error **errp); +void nvme_ns_drain(NvmeNamespace *ns); +void nvme_ns_flush(NvmeNamespace *ns); + +#endif /* NVME_NS_H */ diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 2f3100e56c1bbfdbbe431793519c5d05f627ac0d..01b657b1c5e27fad73627834e1d082f5493dadb4 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -11,16 +11,19 @@ /** * Reference Specs: http://www.nvmexpress.org, 1.2, 1.1, 1.0e * - * http://www.nvmexpress.org/resources/ + * https://nvmexpress.org/developers/nvme-specification/ */ /** * Usage: add options: * -drive file=,if=none,id= - * -device nvme,drive=,serial=,id=, \ + * -device nvme,serial=,id=, \ * cmb_size_mb=, \ * [pmrdev=,] \ - * num_queues= + * max_ioqpairs=, \ + * aerl=, aer_max_queued=, \ + * mdts= + * -device nvme-ns,drive=,bus=bus_name,nsid= * * Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at * offset 0 in BAR2 and supports only WDS, RDS and SQS for now. @@ -32,10 +35,25 @@ * For example: * -object memory-backend-file,id=,share=on,mem-path=, \ * size= .... -device nvme,...,pmrdev= + * + * + * nvme device parameters + * ~~~~~~~~~~~~~~~~~~~~~~ + * - `aerl` + * The Asynchronous Event Request Limit (AERL). Indicates the maximum number + * of concurrently outstanding Asynchronous Event Request commands suppoert + * by the controller. This is a 0's based value. + * + * - `aer_max_queued` + * This is the maximum number of events that the device will enqueue for + * completion when there are no oustanding AERs. When the maximum number of + * enqueued events are reached, subsequent events will be dropped. + * */ #include "qemu/osdep.h" #include "qemu/units.h" +#include "qemu/error-report.h" #include "hw/block/block.h" #include "hw/pci/msix.h" #include "hw/pci/pci.h" @@ -46,13 +64,23 @@ #include "qapi/visitor.h" #include "sysemu/hostmem.h" #include "sysemu/block-backend.h" -#include "exec/ram_addr.h" - +#include "exec/memory.h" #include "qemu/log.h" #include "qemu/module.h" #include "qemu/cutils.h" #include "trace.h" #include "nvme.h" +#include "nvme-ns.h" + +#define NVME_MAX_IOQPAIRS 0xffff +#define NVME_DB_SIZE 4 +#define NVME_SPEC_VER 0x00010300 +#define NVME_CMB_BIR 2 +#define NVME_PMR_BIR 2 +#define NVME_TEMPERATURE 0x143 +#define NVME_TEMPERATURE_WARNING 0x157 +#define NVME_TEMPERATURE_CRITICAL 0x175 +#define NVME_NUM_FW_SLOTS 1 #define NVME_GUEST_ERR(trace, fmt, ...) \ do { \ @@ -61,26 +89,87 @@ " in %s: " fmt "\n", __func__, ## __VA_ARGS__); \ } while (0) +static const bool nvme_feature_support[NVME_FID_MAX] = { + [NVME_ARBITRATION] = true, + [NVME_POWER_MANAGEMENT] = true, + [NVME_TEMPERATURE_THRESHOLD] = true, + [NVME_ERROR_RECOVERY] = true, + [NVME_VOLATILE_WRITE_CACHE] = true, + [NVME_NUMBER_OF_QUEUES] = true, + [NVME_INTERRUPT_COALESCING] = true, + [NVME_INTERRUPT_VECTOR_CONF] = true, + [NVME_WRITE_ATOMICITY] = true, + [NVME_ASYNCHRONOUS_EVENT_CONF] = true, + [NVME_TIMESTAMP] = true, +}; + +static const uint32_t nvme_feature_cap[NVME_FID_MAX] = { + [NVME_TEMPERATURE_THRESHOLD] = NVME_FEAT_CAP_CHANGE, + [NVME_VOLATILE_WRITE_CACHE] = NVME_FEAT_CAP_CHANGE, + [NVME_NUMBER_OF_QUEUES] = NVME_FEAT_CAP_CHANGE, + [NVME_ASYNCHRONOUS_EVENT_CONF] = NVME_FEAT_CAP_CHANGE, + [NVME_TIMESTAMP] = NVME_FEAT_CAP_CHANGE, +}; + static void nvme_process_sq(void *opaque); -static void nvme_addr_read(NvmeCtrl *n, hwaddr addr, void *buf, int size) +static uint16_t nvme_cid(NvmeRequest *req) { - if (n->cmbsz && addr >= n->ctrl_mem.addr && - addr < (n->ctrl_mem.addr + int128_get64(n->ctrl_mem.size))) { - memcpy(buf, (void *)&n->cmbuf[addr - n->ctrl_mem.addr], size); - } else { - pci_dma_read(&n->parent_obj, addr, buf, size); + if (!req) { + return 0xffff; + } + + return le16_to_cpu(req->cqe.cid); +} + +static uint16_t nvme_sqid(NvmeRequest *req) +{ + return le16_to_cpu(req->sq->sqid); +} + +static bool nvme_addr_is_cmb(NvmeCtrl *n, hwaddr addr) +{ + hwaddr low = n->ctrl_mem.addr; + hwaddr hi = n->ctrl_mem.addr + int128_get64(n->ctrl_mem.size); + + return addr >= low && addr < hi; +} + +static inline void *nvme_addr_to_cmb(NvmeCtrl *n, hwaddr addr) +{ + assert(nvme_addr_is_cmb(n, addr)); + + return &n->cmbuf[addr - n->ctrl_mem.addr]; +} + +static int nvme_addr_read(NvmeCtrl *n, hwaddr addr, void *buf, int size) +{ + hwaddr hi = addr + size - 1; + if (hi < addr) { + return 1; + } + + if (n->bar.cmbsz && nvme_addr_is_cmb(n, addr) && nvme_addr_is_cmb(n, hi)) { + memcpy(buf, nvme_addr_to_cmb(n, addr), size); + return 0; } + + return pci_dma_read(&n->parent_obj, addr, buf, size); +} + +static bool nvme_nsid_valid(NvmeCtrl *n, uint32_t nsid) +{ + return nsid && (nsid == NVME_NSID_BROADCAST || nsid <= n->num_namespaces); } static int nvme_check_sqid(NvmeCtrl *n, uint16_t sqid) { - return sqid < n->num_queues && n->sq[sqid] != NULL ? 0 : -1; + return sqid < n->params.max_ioqpairs + 1 && n->sq[sqid] != NULL ? 0 : -1; } static int nvme_check_cqid(NvmeCtrl *n, uint16_t cqid) { - return cqid < n->num_queues && n->cq[cqid] != NULL ? 0 : -1; + return cqid < n->params.max_ioqpairs + 1 && n->cq[cqid] != NULL ? 0 : -1; } static void nvme_inc_cq_tail(NvmeCQueue *cq) @@ -123,16 +212,16 @@ static void nvme_irq_assert(NvmeCtrl *n, NvmeCQueue *cq) { if (cq->irq_enabled) { if (msix_enabled(&(n->parent_obj))) { - trace_nvme_irq_msix(cq->vector); + trace_pci_nvme_irq_msix(cq->vector); msix_notify(&(n->parent_obj), cq->vector); } else { - trace_nvme_irq_pin(); - assert(cq->cqid < 64); - n->irq_status |= 1 << cq->cqid; + trace_pci_nvme_irq_pin(); + assert(cq->vector < 32); + n->irq_status |= 1 << cq->vector; nvme_irq_check(n); } } else { - trace_nvme_irq_masked(); + trace_pci_nvme_irq_masked(); } } @@ -142,145 +231,496 @@ static void nvme_irq_deassert(NvmeCtrl *n, NvmeCQueue *cq) if (msix_enabled(&(n->parent_obj))) { return; } else { - assert(cq->cqid < 64); - n->irq_status &= ~(1 << cq->cqid); + assert(cq->vector < 32); + n->irq_status &= ~(1 << cq->vector); nvme_irq_check(n); } } } -static uint16_t nvme_map_prp(QEMUSGList *qsg, QEMUIOVector *iov, uint64_t prp1, - uint64_t prp2, uint32_t len, NvmeCtrl *n) +static void nvme_req_clear(NvmeRequest *req) +{ + req->ns = NULL; + memset(&req->cqe, 0x0, sizeof(req->cqe)); + req->status = NVME_SUCCESS; +} + +static void nvme_req_exit(NvmeRequest *req) +{ + if (req->qsg.sg) { + qemu_sglist_destroy(&req->qsg); + } + + if (req->iov.iov) { + qemu_iovec_destroy(&req->iov); + } +} + +static uint16_t nvme_map_addr_cmb(NvmeCtrl *n, QEMUIOVector *iov, hwaddr addr, + size_t len) +{ + if (!len) { + return NVME_SUCCESS; + } + + trace_pci_nvme_map_addr_cmb(addr, len); + + if (!nvme_addr_is_cmb(n, addr) || !nvme_addr_is_cmb(n, addr + len - 1)) { + return NVME_DATA_TRAS_ERROR; + } + + qemu_iovec_add(iov, nvme_addr_to_cmb(n, addr), len); + + return NVME_SUCCESS; +} + +static uint16_t nvme_map_addr(NvmeCtrl *n, QEMUSGList *qsg, QEMUIOVector *iov, + hwaddr addr, size_t len) +{ + if (!len) { + return NVME_SUCCESS; + } + + trace_pci_nvme_map_addr(addr, len); + + if (nvme_addr_is_cmb(n, addr)) { + if (qsg && qsg->sg) { + return NVME_INVALID_USE_OF_CMB | NVME_DNR; + } + + assert(iov); + + if (!iov->iov) { + qemu_iovec_init(iov, 1); + } + + return nvme_map_addr_cmb(n, iov, addr, len); + } + + if (iov && iov->iov) { + return NVME_INVALID_USE_OF_CMB | NVME_DNR; + } + + assert(qsg); + + if (!qsg->sg) { + pci_dma_sglist_init(qsg, &n->parent_obj, 1); + } + + qemu_sglist_add(qsg, addr, len); + + return NVME_SUCCESS; +} + +static uint16_t nvme_map_prp(NvmeCtrl *n, uint64_t prp1, uint64_t prp2, + uint32_t len, NvmeRequest *req) { hwaddr trans_len = n->page_size - (prp1 % n->page_size); trans_len = MIN(len, trans_len); int num_prps = (len >> n->page_bits) + 1; + uint16_t status; + bool prp_list_in_cmb = false; + int ret; - if (unlikely(!prp1)) { - trace_nvme_err_invalid_prp(); - return NVME_INVALID_FIELD | NVME_DNR; - } else if (n->cmbsz && prp1 >= n->ctrl_mem.addr && - prp1 < n->ctrl_mem.addr + int128_get64(n->ctrl_mem.size)) { - qsg->nsg = 0; + QEMUSGList *qsg = &req->qsg; + QEMUIOVector *iov = &req->iov; + + trace_pci_nvme_map_prp(trans_len, len, prp1, prp2, num_prps); + + if (nvme_addr_is_cmb(n, prp1)) { qemu_iovec_init(iov, num_prps); - qemu_iovec_add(iov, (void *)&n->cmbuf[prp1 - n->ctrl_mem.addr], trans_len); } else { pci_dma_sglist_init(qsg, &n->parent_obj, num_prps); - qemu_sglist_add(qsg, prp1, trans_len); } + + status = nvme_map_addr(n, qsg, iov, prp1, trans_len); + if (status) { + return status; + } + len -= trans_len; if (len) { - if (unlikely(!prp2)) { - trace_nvme_err_invalid_prp2_missing(); - goto unmap; - } if (len > n->page_size) { uint64_t prp_list[n->max_prp_ents]; uint32_t nents, prp_trans; int i = 0; + if (nvme_addr_is_cmb(n, prp2)) { + prp_list_in_cmb = true; + } + nents = (len + n->page_size - 1) >> n->page_bits; prp_trans = MIN(n->max_prp_ents, nents) * sizeof(uint64_t); - nvme_addr_read(n, prp2, (void *)prp_list, prp_trans); + ret = nvme_addr_read(n, prp2, (void *)prp_list, prp_trans); + if (ret) { + trace_pci_nvme_err_addr_read(prp2); + return NVME_DATA_TRAS_ERROR; + } while (len != 0) { uint64_t prp_ent = le64_to_cpu(prp_list[i]); if (i == n->max_prp_ents - 1 && len > n->page_size) { - if (unlikely(!prp_ent || prp_ent & (n->page_size - 1))) { - trace_nvme_err_invalid_prplist_ent(prp_ent); - goto unmap; + if (unlikely(prp_ent & (n->page_size - 1))) { + trace_pci_nvme_err_invalid_prplist_ent(prp_ent); + return NVME_INVALID_PRP_OFFSET | NVME_DNR; + } + + if (prp_list_in_cmb != nvme_addr_is_cmb(n, prp_ent)) { + return NVME_INVALID_USE_OF_CMB | NVME_DNR; } i = 0; nents = (len + n->page_size - 1) >> n->page_bits; prp_trans = MIN(n->max_prp_ents, nents) * sizeof(uint64_t); - nvme_addr_read(n, prp_ent, (void *)prp_list, - prp_trans); + ret = nvme_addr_read(n, prp_ent, (void *)prp_list, + prp_trans); + if (ret) { + trace_pci_nvme_err_addr_read(prp_ent); + return NVME_DATA_TRAS_ERROR; + } prp_ent = le64_to_cpu(prp_list[i]); } - if (unlikely(!prp_ent || prp_ent & (n->page_size - 1))) { - trace_nvme_err_invalid_prplist_ent(prp_ent); - goto unmap; + if (unlikely(prp_ent & (n->page_size - 1))) { + trace_pci_nvme_err_invalid_prplist_ent(prp_ent); + return NVME_INVALID_PRP_OFFSET | NVME_DNR; } trans_len = MIN(len, n->page_size); - if (qsg->nsg){ - qemu_sglist_add(qsg, prp_ent, trans_len); - } else { - qemu_iovec_add(iov, (void *)&n->cmbuf[prp_ent - n->ctrl_mem.addr], trans_len); + status = nvme_map_addr(n, qsg, iov, prp_ent, trans_len); + if (status) { + return status; } + len -= trans_len; i++; } } else { if (unlikely(prp2 & (n->page_size - 1))) { - trace_nvme_err_invalid_prp2_align(prp2); - goto unmap; + trace_pci_nvme_err_invalid_prp2_align(prp2); + return NVME_INVALID_PRP_OFFSET | NVME_DNR; } - if (qsg->nsg) { - qemu_sglist_add(qsg, prp2, len); - } else { - qemu_iovec_add(iov, (void *)&n->cmbuf[prp2 - n->ctrl_mem.addr], trans_len); + status = nvme_map_addr(n, qsg, iov, prp2, len); + if (status) { + return status; } } } + return NVME_SUCCESS; +} + +/* + * Map 'nsgld' data descriptors from 'segment'. The function will subtract the + * number of bytes mapped in len. + */ +static uint16_t nvme_map_sgl_data(NvmeCtrl *n, QEMUSGList *qsg, + QEMUIOVector *iov, + NvmeSglDescriptor *segment, uint64_t nsgld, + size_t *len, NvmeRequest *req) +{ + dma_addr_t addr, trans_len; + uint32_t dlen; + uint16_t status; + + for (int i = 0; i < nsgld; i++) { + uint8_t type = NVME_SGL_TYPE(segment[i].type); + + switch (type) { + case NVME_SGL_DESCR_TYPE_BIT_BUCKET: + if (req->cmd.opcode == NVME_CMD_WRITE) { + continue; + } + case NVME_SGL_DESCR_TYPE_DATA_BLOCK: + break; + case NVME_SGL_DESCR_TYPE_SEGMENT: + case NVME_SGL_DESCR_TYPE_LAST_SEGMENT: + return NVME_INVALID_NUM_SGL_DESCRS | NVME_DNR; + default: + return NVME_SGL_DESCR_TYPE_INVALID | NVME_DNR; + } + + dlen = le32_to_cpu(segment[i].len); + + if (!dlen) { + continue; + } - unmap: - qemu_sglist_destroy(qsg); - return NVME_INVALID_FIELD | NVME_DNR; + if (*len == 0) { + /* + * All data has been mapped, but the SGL contains additional + * segments and/or descriptors. The controller might accept + * ignoring the rest of the SGL. + */ + uint32_t sgls = le32_to_cpu(n->id_ctrl.sgls); + if (sgls & NVME_CTRL_SGLS_EXCESS_LENGTH) { + break; + } + + trace_pci_nvme_err_invalid_sgl_excess_length(nvme_cid(req)); + return NVME_DATA_SGL_LEN_INVALID | NVME_DNR; + } + + trans_len = MIN(*len, dlen); + + if (type == NVME_SGL_DESCR_TYPE_BIT_BUCKET) { + goto next; + } + + addr = le64_to_cpu(segment[i].addr); + + if (UINT64_MAX - addr < dlen) { + return NVME_DATA_SGL_LEN_INVALID | NVME_DNR; + } + + status = nvme_map_addr(n, qsg, iov, addr, trans_len); + if (status) { + return status; + } + +next: + *len -= trans_len; + } + + return NVME_SUCCESS; } -static uint16_t nvme_dma_write_prp(NvmeCtrl *n, uint8_t *ptr, uint32_t len, - uint64_t prp1, uint64_t prp2) +static uint16_t nvme_map_sgl(NvmeCtrl *n, QEMUSGList *qsg, QEMUIOVector *iov, + NvmeSglDescriptor sgl, size_t len, + NvmeRequest *req) { - QEMUSGList qsg; - QEMUIOVector iov; - uint16_t status = NVME_SUCCESS; + /* + * Read the segment in chunks of 256 descriptors (one 4k page) to avoid + * dynamically allocating a potentially huge SGL. The spec allows the SGL + * to be larger (as in number of bytes required to describe the SGL + * descriptors and segment chain) than the command transfer size, so it is + * not bounded by MDTS. + */ + const int SEG_CHUNK_SIZE = 256; - if (nvme_map_prp(&qsg, &iov, prp1, prp2, len, n)) { - return NVME_INVALID_FIELD | NVME_DNR; + NvmeSglDescriptor segment[SEG_CHUNK_SIZE], *sgld, *last_sgld; + uint64_t nsgld; + uint32_t seg_len; + uint16_t status; + bool sgl_in_cmb = false; + hwaddr addr; + int ret; + + sgld = &sgl; + addr = le64_to_cpu(sgl.addr); + + trace_pci_nvme_map_sgl(nvme_cid(req), NVME_SGL_TYPE(sgl.type), len); + + /* + * If the entire transfer can be described with a single data block it can + * be mapped directly. + */ + if (NVME_SGL_TYPE(sgl.type) == NVME_SGL_DESCR_TYPE_DATA_BLOCK) { + status = nvme_map_sgl_data(n, qsg, iov, sgld, 1, &len, req); + if (status) { + goto unmap; + } + + goto out; } - if (qsg.nsg > 0) { - if (dma_buf_write(ptr, len, &qsg)) { - status = NVME_INVALID_FIELD | NVME_DNR; + + /* + * If the segment is located in the CMB, the submission queue of the + * request must also reside there. + */ + if (nvme_addr_is_cmb(n, addr)) { + if (!nvme_addr_is_cmb(n, req->sq->dma_addr)) { + return NVME_INVALID_USE_OF_CMB | NVME_DNR; } - qemu_sglist_destroy(&qsg); - } else { - if (qemu_iovec_to_buf(&iov, 0, ptr, len) != len) { - status = NVME_INVALID_FIELD | NVME_DNR; + + sgl_in_cmb = true; + } + + for (;;) { + switch (NVME_SGL_TYPE(sgld->type)) { + case NVME_SGL_DESCR_TYPE_SEGMENT: + case NVME_SGL_DESCR_TYPE_LAST_SEGMENT: + break; + default: + return NVME_INVALID_SGL_SEG_DESCR | NVME_DNR; + } + + seg_len = le32_to_cpu(sgld->len); + + /* check the length of the (Last) Segment descriptor */ + if ((!seg_len || seg_len & 0xf) && + (NVME_SGL_TYPE(sgld->type) != NVME_SGL_DESCR_TYPE_BIT_BUCKET)) { + return NVME_INVALID_SGL_SEG_DESCR | NVME_DNR; } - qemu_iovec_destroy(&iov); + + if (UINT64_MAX - addr < seg_len) { + return NVME_DATA_SGL_LEN_INVALID | NVME_DNR; + } + + nsgld = seg_len / sizeof(NvmeSglDescriptor); + + while (nsgld > SEG_CHUNK_SIZE) { + if (nvme_addr_read(n, addr, segment, sizeof(segment))) { + trace_pci_nvme_err_addr_read(addr); + status = NVME_DATA_TRAS_ERROR; + goto unmap; + } + + status = nvme_map_sgl_data(n, qsg, iov, segment, SEG_CHUNK_SIZE, + &len, req); + if (status) { + goto unmap; + } + + nsgld -= SEG_CHUNK_SIZE; + addr += SEG_CHUNK_SIZE * sizeof(NvmeSglDescriptor); + } + + ret = nvme_addr_read(n, addr, segment, nsgld * + sizeof(NvmeSglDescriptor)); + if (ret) { + trace_pci_nvme_err_addr_read(addr); + status = NVME_DATA_TRAS_ERROR; + goto unmap; + } + + last_sgld = &segment[nsgld - 1]; + + /* + * If the segment ends with a Data Block or Bit Bucket Descriptor Type, + * then we are done. + */ + switch (NVME_SGL_TYPE(last_sgld->type)) { + case NVME_SGL_DESCR_TYPE_DATA_BLOCK: + case NVME_SGL_DESCR_TYPE_BIT_BUCKET: + status = nvme_map_sgl_data(n, qsg, iov, segment, nsgld, &len, req); + if (status) { + goto unmap; + } + + goto out; + + default: + break; + } + + /* + * If the last descriptor was not a Data Block or Bit Bucket, then the + * current segment must not be a Last Segment. + */ + if (NVME_SGL_TYPE(sgld->type) == NVME_SGL_DESCR_TYPE_LAST_SEGMENT) { + status = NVME_INVALID_SGL_SEG_DESCR | NVME_DNR; + goto unmap; + } + + sgld = last_sgld; + addr = le64_to_cpu(sgld->addr); + + /* + * Do not map the last descriptor; it will be a Segment or Last Segment + * descriptor and is handled by the next iteration. + */ + status = nvme_map_sgl_data(n, qsg, iov, segment, nsgld - 1, &len, req); + if (status) { + goto unmap; + } + + /* + * If the next segment is in the CMB, make sure that the sgl was + * already located there. + */ + if (sgl_in_cmb != nvme_addr_is_cmb(n, addr)) { + status = NVME_INVALID_USE_OF_CMB | NVME_DNR; + goto unmap; + } + } + +out: + /* if there is any residual left in len, the SGL was too short */ + if (len) { + status = NVME_DATA_SGL_LEN_INVALID | NVME_DNR; + goto unmap; + } + + return NVME_SUCCESS; + +unmap: + if (iov->iov) { + qemu_iovec_destroy(iov); } + + if (qsg->sg) { + qemu_sglist_destroy(qsg); + } + return status; } -static uint16_t nvme_dma_read_prp(NvmeCtrl *n, uint8_t *ptr, uint32_t len, - uint64_t prp1, uint64_t prp2) +static uint16_t nvme_map_dptr(NvmeCtrl *n, size_t len, NvmeRequest *req) { - QEMUSGList qsg; - QEMUIOVector iov; - uint16_t status = NVME_SUCCESS; + uint64_t prp1, prp2; + + switch (NVME_CMD_FLAGS_PSDT(req->cmd.flags)) { + case NVME_PSDT_PRP: + prp1 = le64_to_cpu(req->cmd.dptr.prp1); + prp2 = le64_to_cpu(req->cmd.dptr.prp2); + + return nvme_map_prp(n, prp1, prp2, len, req); + case NVME_PSDT_SGL_MPTR_CONTIGUOUS: + case NVME_PSDT_SGL_MPTR_SGL: + /* SGLs shall not be used for Admin commands in NVMe over PCIe */ + if (!req->sq->sqid) { + return NVME_INVALID_FIELD | NVME_DNR; + } - trace_nvme_dma_read(prp1, prp2); + return nvme_map_sgl(n, &req->qsg, &req->iov, req->cmd.dptr.sgl, len, + req); + default: + return NVME_INVALID_FIELD; + } +} - if (nvme_map_prp(&qsg, &iov, prp1, prp2, len, n)) { - return NVME_INVALID_FIELD | NVME_DNR; +static uint16_t nvme_dma(NvmeCtrl *n, uint8_t *ptr, uint32_t len, + DMADirection dir, NvmeRequest *req) +{ + uint16_t status = NVME_SUCCESS; + + status = nvme_map_dptr(n, len, req); + if (status) { + return status; } - if (qsg.nsg > 0) { - if (unlikely(dma_buf_read(ptr, len, &qsg))) { - trace_nvme_err_invalid_dma(); + + /* assert that only one of qsg and iov carries data */ + assert((req->qsg.nsg > 0) != (req->iov.niov > 0)); + + if (req->qsg.nsg > 0) { + uint64_t residual; + + if (dir == DMA_DIRECTION_TO_DEVICE) { + residual = dma_buf_write(ptr, len, &req->qsg); + } else { + residual = dma_buf_read(ptr, len, &req->qsg); + } + + if (unlikely(residual)) { + trace_pci_nvme_err_invalid_dma(); status = NVME_INVALID_FIELD | NVME_DNR; } - qemu_sglist_destroy(&qsg); } else { - if (unlikely(qemu_iovec_from_buf(&iov, 0, ptr, len) != len)) { - trace_nvme_err_invalid_dma(); + size_t bytes; + + if (dir == DMA_DIRECTION_TO_DEVICE) { + bytes = qemu_iovec_to_buf(&req->iov, 0, ptr, len); + } else { + bytes = qemu_iovec_from_buf(&req->iov, 0, ptr, len); + } + + if (unlikely(bytes != len)) { + trace_pci_nvme_err_invalid_dma(); status = NVME_INVALID_FIELD | NVME_DNR; } - qemu_iovec_destroy(&iov); } + return status; } @@ -289,6 +729,7 @@ static void nvme_post_cqes(void *opaque) NvmeCQueue *cq = opaque; NvmeCtrl *n = cq->ctrl; NvmeRequest *req, *next; + int ret; QTAILQ_FOREACH_SAFE(req, &cq->req_list, entry, next) { NvmeSQueue *sq; @@ -298,15 +739,22 @@ static void nvme_post_cqes(void *opaque) break; } - QTAILQ_REMOVE(&cq->req_list, req, entry); sq = req->sq; req->cqe.status = cpu_to_le16((req->status << 1) | cq->phase); req->cqe.sq_id = cpu_to_le16(sq->sqid); req->cqe.sq_head = cpu_to_le16(sq->head); addr = cq->dma_addr + cq->tail * n->cqe_size; + ret = pci_dma_write(&n->parent_obj, addr, (void *)&req->cqe, + sizeof(req->cqe)); + if (ret) { + trace_pci_nvme_err_addr_write(addr); + trace_pci_nvme_err_cfs(); + n->bar.csts = NVME_CSTS_FAILED; + break; + } + QTAILQ_REMOVE(&cq->req_list, req, entry); nvme_inc_cq_tail(cq); - pci_dma_write(&n->parent_obj, addr, (void *)&req->cqe, - sizeof(req->cqe)); + nvme_req_exit(req); QTAILQ_INSERT_TAIL(&sq->req_list, req, entry); } if (cq->tail != cq->head) { @@ -317,136 +765,286 @@ static void nvme_post_cqes(void *opaque) static void nvme_enqueue_req_completion(NvmeCQueue *cq, NvmeRequest *req) { assert(cq->cqid == req->sq->cqid); + trace_pci_nvme_enqueue_req_completion(nvme_cid(req), cq->cqid, + req->status); + + if (req->status) { + trace_pci_nvme_err_req_status(nvme_cid(req), nvme_nsid(req->ns), + req->status, req->cmd.opcode); + } + QTAILQ_REMOVE(&req->sq->out_req_list, req, entry); QTAILQ_INSERT_TAIL(&cq->req_list, req, entry); timer_mod(cq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500); } +static void nvme_process_aers(void *opaque) +{ + NvmeCtrl *n = opaque; + NvmeAsyncEvent *event, *next; + + trace_pci_nvme_process_aers(n->aer_queued); + + QTAILQ_FOREACH_SAFE(event, &n->aer_queue, entry, next) { + NvmeRequest *req; + NvmeAerResult *result; + + /* can't post cqe if there is nothing to complete */ + if (!n->outstanding_aers) { + trace_pci_nvme_no_outstanding_aers(); + break; + } + + /* ignore if masked (cqe posted, but event not cleared) */ + if (n->aer_mask & (1 << event->result.event_type)) { + trace_pci_nvme_aer_masked(event->result.event_type, n->aer_mask); + continue; + } + + QTAILQ_REMOVE(&n->aer_queue, event, entry); + n->aer_queued--; + + n->aer_mask |= 1 << event->result.event_type; + n->outstanding_aers--; + + req = n->aer_reqs[n->outstanding_aers]; + + result = (NvmeAerResult *) &req->cqe.result; + result->event_type = event->result.event_type; + result->event_info = event->result.event_info; + result->log_page = event->result.log_page; + g_free(event); + + trace_pci_nvme_aer_post_cqe(result->event_type, result->event_info, + result->log_page); + + nvme_enqueue_req_completion(&n->admin_cq, req); + } +} + +static void nvme_enqueue_event(NvmeCtrl *n, uint8_t event_type, + uint8_t event_info, uint8_t log_page) +{ + NvmeAsyncEvent *event; + + trace_pci_nvme_enqueue_event(event_type, event_info, log_page); + + if (n->aer_queued == n->params.aer_max_queued) { + trace_pci_nvme_enqueue_event_noqueue(n->aer_queued); + return; + } + + event = g_new(NvmeAsyncEvent, 1); + event->result = (NvmeAerResult) { + .event_type = event_type, + .event_info = event_info, + .log_page = log_page, + }; + + QTAILQ_INSERT_TAIL(&n->aer_queue, event, entry); + n->aer_queued++; + + nvme_process_aers(n); +} + +static void nvme_clear_events(NvmeCtrl *n, uint8_t event_type) +{ + n->aer_mask &= ~(1 << event_type); + if (!QTAILQ_EMPTY(&n->aer_queue)) { + nvme_process_aers(n); + } +} + +static inline uint16_t nvme_check_mdts(NvmeCtrl *n, size_t len) +{ + uint8_t mdts = n->params.mdts; + + if (mdts && len > n->page_size << mdts) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + return NVME_SUCCESS; +} + +static inline uint16_t nvme_check_bounds(NvmeCtrl *n, NvmeNamespace *ns, + uint64_t slba, uint32_t nlb) +{ + uint64_t nsze = le64_to_cpu(ns->id_ns.nsze); + + if (unlikely(UINT64_MAX - slba < nlb || slba + nlb > nsze)) { + return NVME_LBA_RANGE | NVME_DNR; + } + + return NVME_SUCCESS; +} + static void nvme_rw_cb(void *opaque, int ret) { NvmeRequest *req = opaque; - NvmeSQueue *sq = req->sq; - NvmeCtrl *n = sq->ctrl; - NvmeCQueue *cq = n->cq[sq->cqid]; + NvmeNamespace *ns = req->ns; + + BlockBackend *blk = ns->blkconf.blk; + BlockAcctCookie *acct = &req->acct; + BlockAcctStats *stats = blk_get_stats(blk); + + Error *local_err = NULL; + + trace_pci_nvme_rw_cb(nvme_cid(req), blk_name(blk)); if (!ret) { - block_acct_done(blk_get_stats(n->conf.blk), &req->acct); - req->status = NVME_SUCCESS; + block_acct_done(stats, acct); } else { - block_acct_failed(blk_get_stats(n->conf.blk), &req->acct); - req->status = NVME_INTERNAL_DEV_ERROR; - } - if (req->has_sg) { - qemu_sglist_destroy(&req->qsg); + uint16_t status; + + block_acct_failed(stats, acct); + + switch (req->cmd.opcode) { + case NVME_CMD_READ: + status = NVME_UNRECOVERED_READ; + break; + case NVME_CMD_FLUSH: + case NVME_CMD_WRITE: + case NVME_CMD_WRITE_ZEROES: + status = NVME_WRITE_FAULT; + break; + default: + status = NVME_INTERNAL_DEV_ERROR; + break; + } + + trace_pci_nvme_err_aio(nvme_cid(req), strerror(ret), status); + + error_setg_errno(&local_err, -ret, "aio failed"); + error_report_err(local_err); + + req->status = status; } - nvme_enqueue_req_completion(cq, req); + + nvme_enqueue_req_completion(nvme_cq(req), req); } -static uint16_t nvme_flush(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd, - NvmeRequest *req) +static uint16_t nvme_flush(NvmeCtrl *n, NvmeRequest *req) { - req->has_sg = false; - block_acct_start(blk_get_stats(n->conf.blk), &req->acct, 0, - BLOCK_ACCT_FLUSH); - req->aiocb = blk_aio_flush(n->conf.blk, nvme_rw_cb, req); - + block_acct_start(blk_get_stats(req->ns->blkconf.blk), &req->acct, 0, + BLOCK_ACCT_FLUSH); + req->aiocb = blk_aio_flush(req->ns->blkconf.blk, nvme_rw_cb, req); return NVME_NO_COMPLETE; } -static uint16_t nvme_write_zeros(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd, - NvmeRequest *req) +static uint16_t nvme_write_zeroes(NvmeCtrl *n, NvmeRequest *req) { - NvmeRwCmd *rw = (NvmeRwCmd *)cmd; - const uint8_t lba_index = NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas); - const uint8_t data_shift = ns->id_ns.lbaf[lba_index].ds; + NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; + NvmeNamespace *ns = req->ns; uint64_t slba = le64_to_cpu(rw->slba); - uint32_t nlb = le16_to_cpu(rw->nlb) + 1; - uint64_t offset = slba << data_shift; - uint32_t count = nlb << data_shift; + uint32_t nlb = (uint32_t)le16_to_cpu(rw->nlb) + 1; + uint64_t offset = nvme_l2b(ns, slba); + uint32_t count = nvme_l2b(ns, nlb); + uint16_t status; - if (unlikely(slba + nlb > ns->id_ns.nsze)) { - trace_nvme_err_invalid_lba_range(slba, nlb, ns->id_ns.nsze); - return NVME_LBA_RANGE | NVME_DNR; + trace_pci_nvme_write_zeroes(nvme_cid(req), nvme_nsid(ns), slba, nlb); + + status = nvme_check_bounds(n, ns, slba, nlb); + if (status) { + trace_pci_nvme_err_invalid_lba_range(slba, nlb, ns->id_ns.nsze); + return status; } - req->has_sg = false; - block_acct_start(blk_get_stats(n->conf.blk), &req->acct, 0, + block_acct_start(blk_get_stats(req->ns->blkconf.blk), &req->acct, 0, BLOCK_ACCT_WRITE); - req->aiocb = blk_aio_pwrite_zeroes(n->conf.blk, offset, count, - BDRV_REQ_MAY_UNMAP, nvme_rw_cb, req); + req->aiocb = blk_aio_pwrite_zeroes(req->ns->blkconf.blk, offset, count, + BDRV_REQ_MAY_UNMAP, nvme_rw_cb, req); return NVME_NO_COMPLETE; } -static uint16_t nvme_rw(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd, - NvmeRequest *req) +static uint16_t nvme_rw(NvmeCtrl *n, NvmeRequest *req) { - NvmeRwCmd *rw = (NvmeRwCmd *)cmd; - uint32_t nlb = le32_to_cpu(rw->nlb) + 1; + NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; + NvmeNamespace *ns = req->ns; + uint32_t nlb = (uint32_t)le16_to_cpu(rw->nlb) + 1; uint64_t slba = le64_to_cpu(rw->slba); - uint64_t prp1 = le64_to_cpu(rw->prp1); - uint64_t prp2 = le64_to_cpu(rw->prp2); - uint8_t lba_index = NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas); - uint8_t data_shift = ns->id_ns.lbaf[lba_index].ds; - uint64_t data_size = (uint64_t)nlb << data_shift; - uint64_t data_offset = slba << data_shift; - int is_write = rw->opcode == NVME_CMD_WRITE ? 1 : 0; - enum BlockAcctType acct = is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ; + uint64_t data_size = nvme_l2b(ns, nlb); + uint64_t data_offset = nvme_l2b(ns, slba); + enum BlockAcctType acct = req->cmd.opcode == NVME_CMD_WRITE ? + BLOCK_ACCT_WRITE : BLOCK_ACCT_READ; + BlockBackend *blk = ns->blkconf.blk; + uint16_t status; - trace_nvme_rw(is_write ? "write" : "read", nlb, data_size, slba); + trace_pci_nvme_rw(nvme_cid(req), nvme_io_opc_str(rw->opcode), + nvme_nsid(ns), nlb, data_size, slba); - if (unlikely((slba + nlb) > ns->id_ns.nsze)) { - block_acct_invalid(blk_get_stats(n->conf.blk), acct); - trace_nvme_err_invalid_lba_range(slba, nlb, ns->id_ns.nsze); - return NVME_LBA_RANGE | NVME_DNR; + status = nvme_check_mdts(n, data_size); + if (status) { + trace_pci_nvme_err_mdts(nvme_cid(req), data_size); + goto invalid; } - if (nvme_map_prp(&req->qsg, &req->iov, prp1, prp2, data_size, n)) { - block_acct_invalid(blk_get_stats(n->conf.blk), acct); - return NVME_INVALID_FIELD | NVME_DNR; + status = nvme_check_bounds(n, ns, slba, nlb); + if (status) { + trace_pci_nvme_err_invalid_lba_range(slba, nlb, ns->id_ns.nsze); + goto invalid; } - dma_acct_start(n->conf.blk, &req->acct, &req->qsg, acct); - if (req->qsg.nsg > 0) { - req->has_sg = true; - req->aiocb = is_write ? - dma_blk_write(n->conf.blk, &req->qsg, data_offset, BDRV_SECTOR_SIZE, - nvme_rw_cb, req) : - dma_blk_read(n->conf.blk, &req->qsg, data_offset, BDRV_SECTOR_SIZE, - nvme_rw_cb, req); - } else { - req->has_sg = false; - req->aiocb = is_write ? - blk_aio_pwritev(n->conf.blk, data_offset, &req->iov, 0, nvme_rw_cb, - req) : - blk_aio_preadv(n->conf.blk, data_offset, &req->iov, 0, nvme_rw_cb, - req); + status = nvme_map_dptr(n, data_size, req); + if (status) { + goto invalid; } + block_acct_start(blk_get_stats(blk), &req->acct, data_size, acct); + if (req->qsg.sg) { + if (acct == BLOCK_ACCT_WRITE) { + req->aiocb = dma_blk_write(blk, &req->qsg, data_offset, + BDRV_SECTOR_SIZE, nvme_rw_cb, req); + } else { + req->aiocb = dma_blk_read(blk, &req->qsg, data_offset, + BDRV_SECTOR_SIZE, nvme_rw_cb, req); + } + } else { + if (acct == BLOCK_ACCT_WRITE) { + req->aiocb = blk_aio_pwritev(blk, data_offset, &req->iov, 0, + nvme_rw_cb, req); + } else { + req->aiocb = blk_aio_preadv(blk, data_offset, &req->iov, 0, + nvme_rw_cb, req); + } + } return NVME_NO_COMPLETE; + +invalid: + block_acct_invalid(blk_get_stats(ns->blkconf.blk), acct); + return status; } -static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) +static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeRequest *req) { - NvmeNamespace *ns; - uint32_t nsid = le32_to_cpu(cmd->nsid); + uint32_t nsid = le32_to_cpu(req->cmd.nsid); + + trace_pci_nvme_io_cmd(nvme_cid(req), nsid, nvme_sqid(req), + req->cmd.opcode, nvme_io_opc_str(req->cmd.opcode)); + + if (NVME_CC_CSS(n->bar.cc) == NVME_CC_CSS_ADMIN_ONLY) { + return NVME_INVALID_OPCODE | NVME_DNR; + } - if (unlikely(nsid == 0 || nsid > n->num_namespaces)) { - trace_nvme_err_invalid_ns(nsid, n->num_namespaces); + if (!nvme_nsid_valid(n, nsid)) { return NVME_INVALID_NSID | NVME_DNR; } - ns = &n->namespaces[nsid - 1]; - switch (cmd->opcode) { + req->ns = nvme_ns(n, nsid); + if (unlikely(!req->ns)) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + switch (req->cmd.opcode) { case NVME_CMD_FLUSH: - return nvme_flush(n, ns, cmd, req); - case NVME_CMD_WRITE_ZEROS: - return nvme_write_zeros(n, ns, cmd, req); + return nvme_flush(n, req); + case NVME_CMD_WRITE_ZEROES: + return nvme_write_zeroes(n, req); case NVME_CMD_WRITE: case NVME_CMD_READ: - return nvme_rw(n, ns, cmd, req); + return nvme_rw(n, req); default: - trace_nvme_err_invalid_opc(cmd->opcode); + trace_pci_nvme_err_invalid_opc(req->cmd.opcode); return NVME_INVALID_OPCODE | NVME_DNR; } } @@ -462,36 +1060,36 @@ static void nvme_free_sq(NvmeSQueue *sq, NvmeCtrl *n) } } -static uint16_t nvme_del_sq(NvmeCtrl *n, NvmeCmd *cmd) +static uint16_t nvme_del_sq(NvmeCtrl *n, NvmeRequest *req) { - NvmeDeleteQ *c = (NvmeDeleteQ *)cmd; - NvmeRequest *req, *next; + NvmeDeleteQ *c = (NvmeDeleteQ *)&req->cmd; + NvmeRequest *r, *next; NvmeSQueue *sq; NvmeCQueue *cq; uint16_t qid = le16_to_cpu(c->qid); if (unlikely(!qid || nvme_check_sqid(n, qid))) { - trace_nvme_err_invalid_del_sq(qid); + trace_pci_nvme_err_invalid_del_sq(qid); return NVME_INVALID_QID | NVME_DNR; } - trace_nvme_del_sq(qid); + trace_pci_nvme_del_sq(qid); sq = n->sq[qid]; while (!QTAILQ_EMPTY(&sq->out_req_list)) { - req = QTAILQ_FIRST(&sq->out_req_list); - assert(req->aiocb); - blk_aio_cancel(req->aiocb); + r = QTAILQ_FIRST(&sq->out_req_list); + assert(r->aiocb); + blk_aio_cancel(r->aiocb); } if (!nvme_check_cqid(n, sq->cqid)) { cq = n->cq[sq->cqid]; QTAILQ_REMOVE(&cq->sq_list, sq, entry); nvme_post_cqes(cq); - QTAILQ_FOREACH_SAFE(req, &cq->req_list, entry, next) { - if (req->sq == sq) { - QTAILQ_REMOVE(&cq->req_list, req, entry); - QTAILQ_INSERT_TAIL(&sq->req_list, req, entry); + QTAILQ_FOREACH_SAFE(r, &cq->req_list, entry, next) { + if (r->sq == sq) { + QTAILQ_REMOVE(&cq->req_list, r, entry); + QTAILQ_INSERT_TAIL(&sq->req_list, r, entry); } } } @@ -501,7 +1099,7 @@ static uint16_t nvme_del_sq(NvmeCtrl *n, NvmeCmd *cmd) } static void nvme_init_sq(NvmeSQueue *sq, NvmeCtrl *n, uint64_t dma_addr, - uint16_t sqid, uint16_t cqid, uint16_t size) + uint16_t sqid, uint16_t cqid, uint16_t size) { int i; NvmeCQueue *cq; @@ -512,7 +1110,7 @@ static void nvme_init_sq(NvmeSQueue *sq, NvmeCtrl *n, uint64_t dma_addr, sq->size = size; sq->cqid = cqid; sq->head = sq->tail = 0; - sq->io_req = g_new(NvmeRequest, sq->size); + sq->io_req = g_new0(NvmeRequest, sq->size); QTAILQ_INIT(&sq->req_list); QTAILQ_INIT(&sq->out_req_list); @@ -528,10 +1126,10 @@ static void nvme_init_sq(NvmeSQueue *sq, NvmeCtrl *n, uint64_t dma_addr, n->sq[sqid] = sq; } -static uint16_t nvme_create_sq(NvmeCtrl *n, NvmeCmd *cmd) +static uint16_t nvme_create_sq(NvmeCtrl *n, NvmeRequest *req) { NvmeSQueue *sq; - NvmeCreateSq *c = (NvmeCreateSq *)cmd; + NvmeCreateSq *c = (NvmeCreateSq *)&req->cmd; uint16_t cqid = le16_to_cpu(c->cqid); uint16_t sqid = le16_to_cpu(c->sqid); @@ -539,26 +1137,27 @@ static uint16_t nvme_create_sq(NvmeCtrl *n, NvmeCmd *cmd) uint16_t qflags = le16_to_cpu(c->sq_flags); uint64_t prp1 = le64_to_cpu(c->prp1); - trace_nvme_create_sq(prp1, sqid, cqid, qsize, qflags); + trace_pci_nvme_create_sq(prp1, sqid, cqid, qsize, qflags); if (unlikely(!cqid || nvme_check_cqid(n, cqid))) { - trace_nvme_err_invalid_create_sq_cqid(cqid); + trace_pci_nvme_err_invalid_create_sq_cqid(cqid); return NVME_INVALID_CQID | NVME_DNR; } - if (unlikely(!sqid || !nvme_check_sqid(n, sqid))) { - trace_nvme_err_invalid_create_sq_sqid(sqid); + if (unlikely(!sqid || sqid > n->params.max_ioqpairs || + n->sq[sqid] != NULL)) { + trace_pci_nvme_err_invalid_create_sq_sqid(sqid); return NVME_INVALID_QID | NVME_DNR; } if (unlikely(!qsize || qsize > NVME_CAP_MQES(n->bar.cap))) { - trace_nvme_err_invalid_create_sq_size(qsize); + trace_pci_nvme_err_invalid_create_sq_size(qsize); return NVME_MAX_QSIZE_EXCEEDED | NVME_DNR; } - if (unlikely(!prp1 || prp1 & (n->page_size - 1))) { - trace_nvme_err_invalid_create_sq_addr(prp1); - return NVME_INVALID_FIELD | NVME_DNR; + if (unlikely(prp1 & (n->page_size - 1))) { + trace_pci_nvme_err_invalid_create_sq_addr(prp1); + return NVME_INVALID_PRP_OFFSET | NVME_DNR; } if (unlikely(!(NVME_SQ_FLAGS_PC(qflags)))) { - trace_nvme_err_invalid_create_sq_qflags(NVME_SQ_FLAGS_PC(qflags)); + trace_pci_nvme_err_invalid_create_sq_qflags(NVME_SQ_FLAGS_PC(qflags)); return NVME_INVALID_FIELD | NVME_DNR; } sq = g_malloc0(sizeof(*sq)); @@ -566,6 +1165,172 @@ static uint16_t nvme_create_sq(NvmeCtrl *n, NvmeCmd *cmd) return NVME_SUCCESS; } +struct nvme_stats { + uint64_t units_read; + uint64_t units_written; + uint64_t read_commands; + uint64_t write_commands; +}; + +static void nvme_set_blk_stats(NvmeNamespace *ns, struct nvme_stats *stats) +{ + BlockAcctStats *s = blk_get_stats(ns->blkconf.blk); + + stats->units_read += s->nr_bytes[BLOCK_ACCT_READ] >> BDRV_SECTOR_BITS; + stats->units_written += s->nr_bytes[BLOCK_ACCT_WRITE] >> BDRV_SECTOR_BITS; + stats->read_commands += s->nr_ops[BLOCK_ACCT_READ]; + stats->write_commands += s->nr_ops[BLOCK_ACCT_WRITE]; +} + +static uint16_t nvme_smart_info(NvmeCtrl *n, uint8_t rae, uint32_t buf_len, + uint64_t off, NvmeRequest *req) +{ + uint32_t nsid = le32_to_cpu(req->cmd.nsid); + struct nvme_stats stats = { 0 }; + NvmeSmartLog smart = { 0 }; + uint32_t trans_len; + NvmeNamespace *ns; + time_t current_ms; + + if (off >= sizeof(smart)) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + if (nsid != 0xffffffff) { + ns = nvme_ns(n, nsid); + if (!ns) { + return NVME_INVALID_NSID | NVME_DNR; + } + nvme_set_blk_stats(ns, &stats); + } else { + int i; + + for (i = 1; i <= n->num_namespaces; i++) { + ns = nvme_ns(n, i); + if (!ns) { + continue; + } + nvme_set_blk_stats(ns, &stats); + } + } + + trans_len = MIN(sizeof(smart) - off, buf_len); + + smart.data_units_read[0] = cpu_to_le64(DIV_ROUND_UP(stats.units_read, + 1000)); + smart.data_units_written[0] = cpu_to_le64(DIV_ROUND_UP(stats.units_written, + 1000)); + smart.host_read_commands[0] = cpu_to_le64(stats.read_commands); + smart.host_write_commands[0] = cpu_to_le64(stats.write_commands); + + smart.temperature = cpu_to_le16(n->temperature); + + if ((n->temperature >= n->features.temp_thresh_hi) || + (n->temperature <= n->features.temp_thresh_low)) { + smart.critical_warning |= NVME_SMART_TEMPERATURE; + } + + current_ms = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); + smart.power_on_hours[0] = + cpu_to_le64((((current_ms - n->starttime_ms) / 1000) / 60) / 60); + + if (!rae) { + nvme_clear_events(n, NVME_AER_TYPE_SMART); + } + + return nvme_dma(n, (uint8_t *) &smart + off, trans_len, + DMA_DIRECTION_FROM_DEVICE, req); +} + +static uint16_t nvme_fw_log_info(NvmeCtrl *n, uint32_t buf_len, uint64_t off, + NvmeRequest *req) +{ + uint32_t trans_len; + NvmeFwSlotInfoLog fw_log = { + .afi = 0x1, + }; + + if (off >= sizeof(fw_log)) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + strpadcpy((char *)&fw_log.frs1, sizeof(fw_log.frs1), "1.0", ' '); + trans_len = MIN(sizeof(fw_log) - off, buf_len); + + return nvme_dma(n, (uint8_t *) &fw_log + off, trans_len, + DMA_DIRECTION_FROM_DEVICE, req); +} + +static uint16_t nvme_error_info(NvmeCtrl *n, uint8_t rae, uint32_t buf_len, + uint64_t off, NvmeRequest *req) +{ + uint32_t trans_len; + NvmeErrorLog errlog; + + if (off >= sizeof(errlog)) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + if (!rae) { + nvme_clear_events(n, NVME_AER_TYPE_ERROR); + } + + memset(&errlog, 0x0, sizeof(errlog)); + trans_len = MIN(sizeof(errlog) - off, buf_len); + + return nvme_dma(n, (uint8_t *)&errlog, trans_len, + DMA_DIRECTION_FROM_DEVICE, req); +} + +static uint16_t nvme_get_log(NvmeCtrl *n, NvmeRequest *req) +{ + NvmeCmd *cmd = &req->cmd; + + uint32_t dw10 = le32_to_cpu(cmd->cdw10); + uint32_t dw11 = le32_to_cpu(cmd->cdw11); + uint32_t dw12 = le32_to_cpu(cmd->cdw12); + uint32_t dw13 = le32_to_cpu(cmd->cdw13); + uint8_t lid = dw10 & 0xff; + uint8_t lsp = (dw10 >> 8) & 0xf; + uint8_t rae = (dw10 >> 15) & 0x1; + uint32_t numdl, numdu; + uint64_t off, lpol, lpou; + size_t len; + uint16_t status; + + numdl = (dw10 >> 16); + numdu = (dw11 & 0xffff); + lpol = dw12; + lpou = dw13; + + len = (((numdu << 16) | numdl) + 1) << 2; + off = (lpou << 32ULL) | lpol; + + if (off & 0x3) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + trace_pci_nvme_get_log(nvme_cid(req), lid, lsp, rae, len, off); + + status = nvme_check_mdts(n, len); + if (status) { + trace_pci_nvme_err_mdts(nvme_cid(req), len); + return status; + } + + switch (lid) { + case NVME_LOG_ERROR_INFO: + return nvme_error_info(n, rae, len, off, req); + case NVME_LOG_SMART_INFO: + return nvme_smart_info(n, rae, len, off, req); + case NVME_LOG_FW_SLOT_INFO: + return nvme_fw_log_info(n, len, off, req); + default: + trace_pci_nvme_err_invalid_log_page(nvme_cid(req), lid); + return NVME_INVALID_FIELD | NVME_DNR; + } +} + static void nvme_free_cq(NvmeCQueue *cq, NvmeCtrl *n) { n->cq[cq->cqid] = NULL; @@ -577,31 +1342,36 @@ static void nvme_free_cq(NvmeCQueue *cq, NvmeCtrl *n) } } -static uint16_t nvme_del_cq(NvmeCtrl *n, NvmeCmd *cmd) +static uint16_t nvme_del_cq(NvmeCtrl *n, NvmeRequest *req) { - NvmeDeleteQ *c = (NvmeDeleteQ *)cmd; + NvmeDeleteQ *c = (NvmeDeleteQ *)&req->cmd; NvmeCQueue *cq; uint16_t qid = le16_to_cpu(c->qid); if (unlikely(!qid || nvme_check_cqid(n, qid))) { - trace_nvme_err_invalid_del_cq_cqid(qid); + trace_pci_nvme_err_invalid_del_cq_cqid(qid); return NVME_INVALID_CQID | NVME_DNR; } cq = n->cq[qid]; if (unlikely(!QTAILQ_EMPTY(&cq->sq_list))) { - trace_nvme_err_invalid_del_cq_notempty(qid); + trace_pci_nvme_err_invalid_del_cq_notempty(qid); return NVME_INVALID_QUEUE_DEL; } nvme_irq_deassert(n, cq); - trace_nvme_del_cq(qid); + trace_pci_nvme_del_cq(qid); nvme_free_cq(cq, n); return NVME_SUCCESS; } static void nvme_init_cq(NvmeCQueue *cq, NvmeCtrl *n, uint64_t dma_addr, - uint16_t cqid, uint16_t vector, uint16_t size, uint16_t irq_enabled) + uint16_t cqid, uint16_t vector, uint16_t size, + uint16_t irq_enabled) { + int ret; + + ret = msix_vector_use(&n->parent_obj, vector); + assert(ret == 0); cq->ctrl = n; cq->cqid = cqid; cq->size = size; @@ -612,129 +1382,206 @@ static void nvme_init_cq(NvmeCQueue *cq, NvmeCtrl *n, uint64_t dma_addr, cq->head = cq->tail = 0; QTAILQ_INIT(&cq->req_list); QTAILQ_INIT(&cq->sq_list); - msix_vector_use(&n->parent_obj, cq->vector); n->cq[cqid] = cq; cq->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, nvme_post_cqes, cq); } -static uint16_t nvme_create_cq(NvmeCtrl *n, NvmeCmd *cmd) +static uint16_t nvme_create_cq(NvmeCtrl *n, NvmeRequest *req) { NvmeCQueue *cq; - NvmeCreateCq *c = (NvmeCreateCq *)cmd; + NvmeCreateCq *c = (NvmeCreateCq *)&req->cmd; uint16_t cqid = le16_to_cpu(c->cqid); uint16_t vector = le16_to_cpu(c->irq_vector); uint16_t qsize = le16_to_cpu(c->qsize); uint16_t qflags = le16_to_cpu(c->cq_flags); uint64_t prp1 = le64_to_cpu(c->prp1); - trace_nvme_create_cq(prp1, cqid, vector, qsize, qflags, - NVME_CQ_FLAGS_IEN(qflags) != 0); + trace_pci_nvme_create_cq(prp1, cqid, vector, qsize, qflags, + NVME_CQ_FLAGS_IEN(qflags) != 0); - if (unlikely(!cqid || !nvme_check_cqid(n, cqid))) { - trace_nvme_err_invalid_create_cq_cqid(cqid); - return NVME_INVALID_CQID | NVME_DNR; + if (unlikely(!cqid || cqid > n->params.max_ioqpairs || + n->cq[cqid] != NULL)) { + trace_pci_nvme_err_invalid_create_cq_cqid(cqid); + return NVME_INVALID_QID | NVME_DNR; } if (unlikely(!qsize || qsize > NVME_CAP_MQES(n->bar.cap))) { - trace_nvme_err_invalid_create_cq_size(qsize); + trace_pci_nvme_err_invalid_create_cq_size(qsize); return NVME_MAX_QSIZE_EXCEEDED | NVME_DNR; } - if (unlikely(!prp1)) { - trace_nvme_err_invalid_create_cq_addr(prp1); - return NVME_INVALID_FIELD | NVME_DNR; + if (unlikely(prp1 & (n->page_size - 1))) { + trace_pci_nvme_err_invalid_create_cq_addr(prp1); + return NVME_INVALID_PRP_OFFSET | NVME_DNR; + } + if (unlikely(!msix_enabled(&n->parent_obj) && vector)) { + trace_pci_nvme_err_invalid_create_cq_vector(vector); + return NVME_INVALID_IRQ_VECTOR | NVME_DNR; } - if (unlikely(vector > n->num_queues)) { - trace_nvme_err_invalid_create_cq_vector(vector); + if (unlikely(vector >= n->params.msix_qsize)) { + trace_pci_nvme_err_invalid_create_cq_vector(vector); return NVME_INVALID_IRQ_VECTOR | NVME_DNR; } if (unlikely(!(NVME_CQ_FLAGS_PC(qflags)))) { - trace_nvme_err_invalid_create_cq_qflags(NVME_CQ_FLAGS_PC(qflags)); + trace_pci_nvme_err_invalid_create_cq_qflags(NVME_CQ_FLAGS_PC(qflags)); return NVME_INVALID_FIELD | NVME_DNR; } cq = g_malloc0(sizeof(*cq)); nvme_init_cq(cq, n, prp1, cqid, vector, qsize + 1, - NVME_CQ_FLAGS_IEN(qflags)); + NVME_CQ_FLAGS_IEN(qflags)); + + /* + * It is only required to set qs_created when creating a completion queue; + * creating a submission queue without a matching completion queue will + * fail. + */ + n->qs_created = true; return NVME_SUCCESS; } -static uint16_t nvme_identify_ctrl(NvmeCtrl *n, NvmeIdentify *c) +static uint16_t nvme_identify_ctrl(NvmeCtrl *n, NvmeRequest *req) { - uint64_t prp1 = le64_to_cpu(c->prp1); - uint64_t prp2 = le64_to_cpu(c->prp2); + trace_pci_nvme_identify_ctrl(); - trace_nvme_identify_ctrl(); - - return nvme_dma_read_prp(n, (uint8_t *)&n->id_ctrl, sizeof(n->id_ctrl), - prp1, prp2); + return nvme_dma(n, (uint8_t *)&n->id_ctrl, sizeof(n->id_ctrl), + DMA_DIRECTION_FROM_DEVICE, req); } -static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeIdentify *c) +static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeRequest *req) { NvmeNamespace *ns; + NvmeIdentify *c = (NvmeIdentify *)&req->cmd; + NvmeIdNs *id_ns, inactive = { 0 }; uint32_t nsid = le32_to_cpu(c->nsid); - uint64_t prp1 = le64_to_cpu(c->prp1); - uint64_t prp2 = le64_to_cpu(c->prp2); - trace_nvme_identify_ns(nsid); + trace_pci_nvme_identify_ns(nsid); - if (unlikely(nsid == 0 || nsid > n->num_namespaces)) { - trace_nvme_err_invalid_ns(nsid, n->num_namespaces); + if (!nvme_nsid_valid(n, nsid) || nsid == NVME_NSID_BROADCAST) { return NVME_INVALID_NSID | NVME_DNR; } - ns = &n->namespaces[nsid - 1]; + ns = nvme_ns(n, nsid); + if (unlikely(!ns)) { + id_ns = &inactive; + } else { + id_ns = &ns->id_ns; + } - return nvme_dma_read_prp(n, (uint8_t *)&ns->id_ns, sizeof(ns->id_ns), - prp1, prp2); + return nvme_dma(n, (uint8_t *)id_ns, sizeof(NvmeIdNs), + DMA_DIRECTION_FROM_DEVICE, req); } -static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeIdentify *c) +static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeRequest *req) { - static const int data_len = 4 * KiB; + NvmeIdentify *c = (NvmeIdentify *)&req->cmd; + static const int data_len = NVME_IDENTIFY_DATA_SIZE; uint32_t min_nsid = le32_to_cpu(c->nsid); - uint64_t prp1 = le64_to_cpu(c->prp1); - uint64_t prp2 = le64_to_cpu(c->prp2); uint32_t *list; uint16_t ret; - int i, j = 0; + int j = 0; + + trace_pci_nvme_identify_nslist(min_nsid); - trace_nvme_identify_nslist(min_nsid); + /* + * Both 0xffffffff (NVME_NSID_BROADCAST) and 0xfffffffe are invalid values + * since the Active Namespace ID List should return namespaces with ids + * *higher* than the NSID specified in the command. This is also specified + * in the spec (NVM Express v1.3d, Section 5.15.4). + */ + if (min_nsid >= NVME_NSID_BROADCAST - 1) { + return NVME_INVALID_NSID | NVME_DNR; + } list = g_malloc0(data_len); - for (i = 0; i < n->num_namespaces; i++) { - if (i < min_nsid) { + for (int i = 1; i <= n->num_namespaces; i++) { + if (i <= min_nsid || !nvme_ns(n, i)) { continue; } - list[j++] = cpu_to_le32(i + 1); + list[j++] = cpu_to_le32(i); if (j == data_len / sizeof(uint32_t)) { break; } } - ret = nvme_dma_read_prp(n, (uint8_t *)list, data_len, prp1, prp2); + ret = nvme_dma(n, (uint8_t *)list, data_len, DMA_DIRECTION_FROM_DEVICE, + req); g_free(list); return ret; } -static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *cmd) +static uint16_t nvme_identify_ns_descr_list(NvmeCtrl *n, NvmeRequest *req) +{ + NvmeIdentify *c = (NvmeIdentify *)&req->cmd; + uint32_t nsid = le32_to_cpu(c->nsid); + uint8_t list[NVME_IDENTIFY_DATA_SIZE]; + + struct data { + struct { + NvmeIdNsDescr hdr; + uint8_t v[16]; + } uuid; + }; + + struct data *ns_descrs = (struct data *)list; + + trace_pci_nvme_identify_ns_descr_list(nsid); + + if (!nvme_nsid_valid(n, nsid) || nsid == NVME_NSID_BROADCAST) { + return NVME_INVALID_NSID | NVME_DNR; + } + + if (unlikely(!nvme_ns(n, nsid))) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + memset(list, 0x0, sizeof(list)); + + /* + * Because the NGUID and EUI64 fields are 0 in the Identify Namespace data + * structure, a Namespace UUID (nidt = 0x3) must be reported in the + * Namespace Identification Descriptor. Add a very basic Namespace UUID + * here. + */ + ns_descrs->uuid.hdr.nidt = NVME_NIDT_UUID; + ns_descrs->uuid.hdr.nidl = NVME_NIDT_UUID_LEN; + stl_be_p(&ns_descrs->uuid.v, nsid); + + return nvme_dma(n, list, NVME_IDENTIFY_DATA_SIZE, + DMA_DIRECTION_FROM_DEVICE, req); +} + +static uint16_t nvme_identify(NvmeCtrl *n, NvmeRequest *req) { - NvmeIdentify *c = (NvmeIdentify *)cmd; + NvmeIdentify *c = (NvmeIdentify *)&req->cmd; switch (le32_to_cpu(c->cns)) { - case 0x00: - return nvme_identify_ns(n, c); - case 0x01: - return nvme_identify_ctrl(n, c); - case 0x02: - return nvme_identify_nslist(n, c); + case NVME_ID_CNS_NS: + return nvme_identify_ns(n, req); + case NVME_ID_CNS_CTRL: + return nvme_identify_ctrl(n, req); + case NVME_ID_CNS_NS_ACTIVE_LIST: + return nvme_identify_nslist(n, req); + case NVME_ID_CNS_NS_DESCR_LIST: + return nvme_identify_ns_descr_list(n, req); default: - trace_nvme_err_invalid_identify_cns(le32_to_cpu(c->cns)); + trace_pci_nvme_err_invalid_identify_cns(le32_to_cpu(c->cns)); return NVME_INVALID_FIELD | NVME_DNR; } } +static uint16_t nvme_abort(NvmeCtrl *n, NvmeRequest *req) +{ + uint16_t sqid = le32_to_cpu(req->cmd.cdw10) & 0xffff; + + req->cqe.result = 1; + if (nvme_check_sqid(n, sqid)) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + return NVME_SUCCESS; +} + static inline void nvme_set_timestamp(NvmeCtrl *n, uint64_t ts) { - trace_nvme_setfeat_timestamp(ts); + trace_pci_nvme_setfeat_timestamp(ts); n->host_timestamp = le64_to_cpu(ts); n->timestamp_set_qemu_clock_ms = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); @@ -757,67 +1604,157 @@ static inline uint64_t nvme_get_timestamp(const NvmeCtrl *n) union nvme_timestamp ts; ts.all = 0; - - /* - * If the sum of the Timestamp value set by the host and the elapsed - * time exceeds 2^48, the value returned should be reduced modulo 2^48. - */ - ts.timestamp = (n->host_timestamp + elapsed_time) & 0xffffffffffff; + ts.timestamp = n->host_timestamp + elapsed_time; /* If the host timestamp is non-zero, set the timestamp origin */ ts.origin = n->host_timestamp ? 0x01 : 0x00; - trace_nvme_getfeat_timestamp(ts.all); + trace_pci_nvme_getfeat_timestamp(ts.all); return cpu_to_le64(ts.all); } -static uint16_t nvme_get_feature_timestamp(NvmeCtrl *n, NvmeCmd *cmd) +static uint16_t nvme_get_feature_timestamp(NvmeCtrl *n, NvmeRequest *req) { - uint64_t prp1 = le64_to_cpu(cmd->prp1); - uint64_t prp2 = le64_to_cpu(cmd->prp2); - uint64_t timestamp = nvme_get_timestamp(n); - return nvme_dma_read_prp(n, (uint8_t *)×tamp, - sizeof(timestamp), prp1, prp2); + return nvme_dma(n, (uint8_t *)×tamp, sizeof(timestamp), + DMA_DIRECTION_FROM_DEVICE, req); } -static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) +static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeRequest *req) { + NvmeCmd *cmd = &req->cmd; uint32_t dw10 = le32_to_cpu(cmd->cdw10); + uint32_t dw11 = le32_to_cpu(cmd->cdw11); + uint32_t nsid = le32_to_cpu(cmd->nsid); uint32_t result; + uint8_t fid = NVME_GETSETFEAT_FID(dw10); + NvmeGetFeatureSelect sel = NVME_GETFEAT_SELECT(dw10); + uint16_t iv; + + static const uint32_t nvme_feature_default[NVME_FID_MAX] = { + [NVME_ARBITRATION] = NVME_ARB_AB_NOLIMIT, + }; + + trace_pci_nvme_getfeat(nvme_cid(req), nsid, fid, sel, dw11); + + if (!nvme_feature_support[fid]) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + if (nvme_feature_cap[fid] & NVME_FEAT_CAP_NS) { + if (!nvme_nsid_valid(n, nsid) || nsid == NVME_NSID_BROADCAST) { + /* + * The Reservation Notification Mask and Reservation Persistence + * features require a status code of Invalid Field in Command when + * NSID is 0xFFFFFFFF. Since the device does not support those + * features we can always return Invalid Namespace or Format as we + * should do for all other features. + */ + return NVME_INVALID_NSID | NVME_DNR; + } + + if (!nvme_ns(n, nsid)) { + return NVME_INVALID_FIELD | NVME_DNR; + } + } + + switch (sel) { + case NVME_GETFEAT_SELECT_CURRENT: + break; + case NVME_GETFEAT_SELECT_SAVED: + /* no features are saveable by the controller; fallthrough */ + case NVME_GETFEAT_SELECT_DEFAULT: + goto defaults; + case NVME_GETFEAT_SELECT_CAP: + result = nvme_feature_cap[fid]; + goto out; + } + + switch (fid) { + case NVME_TEMPERATURE_THRESHOLD: + result = 0; + + /* + * The controller only implements the Composite Temperature sensor, so + * return 0 for all other sensors. + */ + if (NVME_TEMP_TMPSEL(dw11) != NVME_TEMP_TMPSEL_COMPOSITE) { + goto out; + } + + switch (NVME_TEMP_THSEL(dw11)) { + case NVME_TEMP_THSEL_OVER: + result = n->features.temp_thresh_hi; + goto out; + case NVME_TEMP_THSEL_UNDER: + result = n->features.temp_thresh_low; + goto out; + } - switch (dw10) { + return NVME_INVALID_FIELD | NVME_DNR; case NVME_VOLATILE_WRITE_CACHE: - result = blk_enable_write_cache(n->conf.blk); - trace_nvme_getfeat_vwcache(result ? "enabled" : "disabled"); + result = n->features.vwc; + trace_pci_nvme_getfeat_vwcache(result ? "enabled" : "disabled"); + goto out; + case NVME_ASYNCHRONOUS_EVENT_CONF: + result = n->features.async_config; + goto out; + case NVME_TIMESTAMP: + return nvme_get_feature_timestamp(n, req); + default: + break; + } + +defaults: + switch (fid) { + case NVME_TEMPERATURE_THRESHOLD: + result = 0; + + if (NVME_TEMP_TMPSEL(dw11) != NVME_TEMP_TMPSEL_COMPOSITE) { + break; + } + + if (NVME_TEMP_THSEL(dw11) == NVME_TEMP_THSEL_OVER) { + result = NVME_TEMPERATURE_WARNING; + } + break; case NVME_NUMBER_OF_QUEUES: - result = cpu_to_le32((n->num_queues - 2) | ((n->num_queues - 2) << 16)); - trace_nvme_getfeat_numq(result); + result = (n->params.max_ioqpairs - 1) | + ((n->params.max_ioqpairs - 1) << 16); + trace_pci_nvme_getfeat_numq(result); break; - case NVME_TIMESTAMP: - return nvme_get_feature_timestamp(n, cmd); + case NVME_INTERRUPT_VECTOR_CONF: + iv = dw11 & 0xffff; + if (iv >= n->params.max_ioqpairs + 1) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + result = iv; + if (iv == n->admin_cq.vector) { + result |= NVME_INTVC_NOCOALESCING; + } + break; default: - trace_nvme_err_invalid_getfeat(dw10); - return NVME_INVALID_FIELD | NVME_DNR; + result = nvme_feature_default[fid]; + break; } - req->cqe.result = result; +out: + req->cqe.result = cpu_to_le32(result); return NVME_SUCCESS; } -static uint16_t nvme_set_feature_timestamp(NvmeCtrl *n, NvmeCmd *cmd) +static uint16_t nvme_set_feature_timestamp(NvmeCtrl *n, NvmeRequest *req) { uint16_t ret; uint64_t timestamp; - uint64_t prp1 = le64_to_cpu(cmd->prp1); - uint64_t prp2 = le64_to_cpu(cmd->prp2); - ret = nvme_dma_write_prp(n, (uint8_t *)×tamp, - sizeof(timestamp), prp1, prp2); + ret = nvme_dma(n, (uint8_t *)×tamp, sizeof(timestamp), + DMA_DIRECTION_TO_DEVICE, req); if (ret != NVME_SUCCESS) { return ret; } @@ -827,53 +1764,172 @@ static uint16_t nvme_set_feature_timestamp(NvmeCtrl *n, NvmeCmd *cmd) return NVME_SUCCESS; } -static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) +static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeRequest *req) { + NvmeNamespace *ns; + + NvmeCmd *cmd = &req->cmd; uint32_t dw10 = le32_to_cpu(cmd->cdw10); uint32_t dw11 = le32_to_cpu(cmd->cdw11); + uint32_t nsid = le32_to_cpu(cmd->nsid); + uint8_t fid = NVME_GETSETFEAT_FID(dw10); + uint8_t save = NVME_SETFEAT_SAVE(dw10); + + trace_pci_nvme_setfeat(nvme_cid(req), nsid, fid, save, dw11); + + if (save) { + return NVME_FID_NOT_SAVEABLE | NVME_DNR; + } + + if (!nvme_feature_support[fid]) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + if (nvme_feature_cap[fid] & NVME_FEAT_CAP_NS) { + if (nsid != NVME_NSID_BROADCAST) { + if (!nvme_nsid_valid(n, nsid)) { + return NVME_INVALID_NSID | NVME_DNR; + } + + ns = nvme_ns(n, nsid); + if (unlikely(!ns)) { + return NVME_INVALID_FIELD | NVME_DNR; + } + } + } else if (nsid && nsid != NVME_NSID_BROADCAST) { + if (!nvme_nsid_valid(n, nsid)) { + return NVME_INVALID_NSID | NVME_DNR; + } + + return NVME_FEAT_NOT_NS_SPEC | NVME_DNR; + } + + if (!(nvme_feature_cap[fid] & NVME_FEAT_CAP_CHANGE)) { + return NVME_FEAT_NOT_CHANGEABLE | NVME_DNR; + } + + switch (fid) { + case NVME_TEMPERATURE_THRESHOLD: + if (NVME_TEMP_TMPSEL(dw11) != NVME_TEMP_TMPSEL_COMPOSITE) { + break; + } + + switch (NVME_TEMP_THSEL(dw11)) { + case NVME_TEMP_THSEL_OVER: + n->features.temp_thresh_hi = NVME_TEMP_TMPTH(dw11); + break; + case NVME_TEMP_THSEL_UNDER: + n->features.temp_thresh_low = NVME_TEMP_TMPTH(dw11); + break; + default: + return NVME_INVALID_FIELD | NVME_DNR; + } - switch (dw10) { + if (((n->temperature >= n->features.temp_thresh_hi) || + (n->temperature <= n->features.temp_thresh_low)) && + NVME_AEC_SMART(n->features.async_config) & NVME_SMART_TEMPERATURE) { + nvme_enqueue_event(n, NVME_AER_TYPE_SMART, + NVME_AER_INFO_SMART_TEMP_THRESH, + NVME_LOG_SMART_INFO); + } + + break; case NVME_VOLATILE_WRITE_CACHE: - blk_set_enable_write_cache(n->conf.blk, dw11 & 1); + n->features.vwc = dw11 & 0x1; + + for (int i = 1; i <= n->num_namespaces; i++) { + ns = nvme_ns(n, i); + if (!ns) { + continue; + } + + if (!(dw11 & 0x1) && blk_enable_write_cache(ns->blkconf.blk)) { + blk_flush(ns->blkconf.blk); + } + + blk_set_enable_write_cache(ns->blkconf.blk, dw11 & 1); + } + break; + case NVME_NUMBER_OF_QUEUES: - trace_nvme_setfeat_numq((dw11 & 0xFFFF) + 1, - ((dw11 >> 16) & 0xFFFF) + 1, - n->num_queues - 1, n->num_queues - 1); - req->cqe.result = - cpu_to_le32((n->num_queues - 2) | ((n->num_queues - 2) << 16)); - break; + if (n->qs_created) { + return NVME_CMD_SEQ_ERROR | NVME_DNR; + } - case NVME_TIMESTAMP: - return nvme_set_feature_timestamp(n, cmd); - break; + /* + * NVMe v1.3, Section 5.21.1.7: 0xffff is not an allowed value for NCQR + * and NSQR. + */ + if ((dw11 & 0xffff) == 0xffff || ((dw11 >> 16) & 0xffff) == 0xffff) { + return NVME_INVALID_FIELD | NVME_DNR; + } + trace_pci_nvme_setfeat_numq((dw11 & 0xFFFF) + 1, + ((dw11 >> 16) & 0xFFFF) + 1, + n->params.max_ioqpairs, + n->params.max_ioqpairs); + req->cqe.result = cpu_to_le32((n->params.max_ioqpairs - 1) | + ((n->params.max_ioqpairs - 1) << 16)); + break; + case NVME_ASYNCHRONOUS_EVENT_CONF: + n->features.async_config = dw11; + break; + case NVME_TIMESTAMP: + return nvme_set_feature_timestamp(n, req); default: - trace_nvme_err_invalid_setfeat(dw10); - return NVME_INVALID_FIELD | NVME_DNR; + return NVME_FEAT_NOT_CHANGEABLE | NVME_DNR; } return NVME_SUCCESS; } -static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) +static uint16_t nvme_aer(NvmeCtrl *n, NvmeRequest *req) +{ + trace_pci_nvme_aer(nvme_cid(req)); + + if (n->outstanding_aers > n->params.aerl) { + trace_pci_nvme_aer_aerl_exceeded(); + return NVME_AER_LIMIT_EXCEEDED; + } + + n->aer_reqs[n->outstanding_aers] = req; + n->outstanding_aers++; + + if (!QTAILQ_EMPTY(&n->aer_queue)) { + nvme_process_aers(n); + } + + return NVME_NO_COMPLETE; +} + +static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeRequest *req) { - switch (cmd->opcode) { + trace_pci_nvme_admin_cmd(nvme_cid(req), nvme_sqid(req), req->cmd.opcode, + nvme_adm_opc_str(req->cmd.opcode)); + + switch (req->cmd.opcode) { case NVME_ADM_CMD_DELETE_SQ: - return nvme_del_sq(n, cmd); + return nvme_del_sq(n, req); case NVME_ADM_CMD_CREATE_SQ: - return nvme_create_sq(n, cmd); + return nvme_create_sq(n, req); + case NVME_ADM_CMD_GET_LOG_PAGE: + return nvme_get_log(n, req); case NVME_ADM_CMD_DELETE_CQ: - return nvme_del_cq(n, cmd); + return nvme_del_cq(n, req); case NVME_ADM_CMD_CREATE_CQ: - return nvme_create_cq(n, cmd); + return nvme_create_cq(n, req); case NVME_ADM_CMD_IDENTIFY: - return nvme_identify(n, cmd); + return nvme_identify(n, req); + case NVME_ADM_CMD_ABORT: + return nvme_abort(n, req); case NVME_ADM_CMD_SET_FEATURES: - return nvme_set_feature(n, cmd, req); + return nvme_set_feature(n, req); case NVME_ADM_CMD_GET_FEATURES: - return nvme_get_feature(n, cmd, req); + return nvme_get_feature(n, req); + case NVME_ADM_CMD_ASYNC_EV_REQ: + return nvme_aer(n, req); default: - trace_nvme_err_invalid_admin_opc(cmd->opcode); + trace_pci_nvme_err_invalid_admin_opc(req->cmd.opcode); return NVME_INVALID_OPCODE | NVME_DNR; } } @@ -891,17 +1947,23 @@ static void nvme_process_sq(void *opaque) while (!(nvme_sq_empty(sq) || QTAILQ_EMPTY(&sq->req_list))) { addr = sq->dma_addr + sq->head * n->sqe_size; - nvme_addr_read(n, addr, (void *)&cmd, sizeof(cmd)); + if (nvme_addr_read(n, addr, (void *)&cmd, sizeof(cmd))) { + trace_pci_nvme_err_addr_read(addr); + trace_pci_nvme_err_cfs(); + n->bar.csts = NVME_CSTS_FAILED; + break; + } nvme_inc_sq_head(sq); req = QTAILQ_FIRST(&sq->req_list); QTAILQ_REMOVE(&sq->req_list, req, entry); QTAILQ_INSERT_TAIL(&sq->out_req_list, req, entry); - memset(&req->cqe, 0, sizeof(req->cqe)); + nvme_req_clear(req); req->cqe.cid = cmd.cid; + memcpy(&req->cmd, &cmd, sizeof(NvmeCmd)); - status = sq->sqid ? nvme_io_cmd(n, &cmd, req) : - nvme_admin_cmd(n, &cmd, req); + status = sq->sqid ? nvme_io_cmd(n, req) : + nvme_admin_cmd(n, req); if (status != NVME_NO_COMPLETE) { req->status = status; nvme_enqueue_req_completion(cq, req); @@ -911,22 +1973,48 @@ static void nvme_process_sq(void *opaque) static void nvme_clear_ctrl(NvmeCtrl *n) { + NvmeNamespace *ns; int i; - blk_drain(n->conf.blk); + for (i = 1; i <= n->num_namespaces; i++) { + ns = nvme_ns(n, i); + if (!ns) { + continue; + } + + nvme_ns_drain(ns); + } - for (i = 0; i < n->num_queues; i++) { + for (i = 0; i < n->params.max_ioqpairs + 1; i++) { if (n->sq[i] != NULL) { nvme_free_sq(n->sq[i], n); } } - for (i = 0; i < n->num_queues; i++) { + for (i = 0; i < n->params.max_ioqpairs + 1; i++) { if (n->cq[i] != NULL) { nvme_free_cq(n->cq[i], n); } } - blk_flush(n->conf.blk); + while (!QTAILQ_EMPTY(&n->aer_queue)) { + NvmeAsyncEvent *event = QTAILQ_FIRST(&n->aer_queue); + QTAILQ_REMOVE(&n->aer_queue, event, entry); + g_free(event); + } + + n->aer_queued = 0; + n->outstanding_aers = 0; + n->qs_created = false; + + for (i = 1; i <= n->num_namespaces; i++) { + ns = nvme_ns(n, i); + if (!ns) { + continue; + } + + nvme_ns_flush(ns); + } + n->bar.cc = 0; } @@ -936,77 +2024,81 @@ static int nvme_start_ctrl(NvmeCtrl *n) uint32_t page_size = 1 << page_bits; if (unlikely(n->cq[0])) { - trace_nvme_err_startfail_cq(); + trace_pci_nvme_err_startfail_cq(); return -1; } if (unlikely(n->sq[0])) { - trace_nvme_err_startfail_sq(); + trace_pci_nvme_err_startfail_sq(); return -1; } if (unlikely(!n->bar.asq)) { - trace_nvme_err_startfail_nbarasq(); + trace_pci_nvme_err_startfail_nbarasq(); return -1; } if (unlikely(!n->bar.acq)) { - trace_nvme_err_startfail_nbaracq(); + trace_pci_nvme_err_startfail_nbaracq(); return -1; } if (unlikely(n->bar.asq & (page_size - 1))) { - trace_nvme_err_startfail_asq_misaligned(n->bar.asq); + trace_pci_nvme_err_startfail_asq_misaligned(n->bar.asq); return -1; } if (unlikely(n->bar.acq & (page_size - 1))) { - trace_nvme_err_startfail_acq_misaligned(n->bar.acq); + trace_pci_nvme_err_startfail_acq_misaligned(n->bar.acq); + return -1; + } + if (unlikely(!(NVME_CAP_CSS(n->bar.cap) & (1 << NVME_CC_CSS(n->bar.cc))))) { + trace_pci_nvme_err_startfail_css(NVME_CC_CSS(n->bar.cc)); return -1; } if (unlikely(NVME_CC_MPS(n->bar.cc) < NVME_CAP_MPSMIN(n->bar.cap))) { - trace_nvme_err_startfail_page_too_small( + trace_pci_nvme_err_startfail_page_too_small( NVME_CC_MPS(n->bar.cc), NVME_CAP_MPSMIN(n->bar.cap)); return -1; } if (unlikely(NVME_CC_MPS(n->bar.cc) > NVME_CAP_MPSMAX(n->bar.cap))) { - trace_nvme_err_startfail_page_too_large( + trace_pci_nvme_err_startfail_page_too_large( NVME_CC_MPS(n->bar.cc), NVME_CAP_MPSMAX(n->bar.cap)); return -1; } if (unlikely(NVME_CC_IOCQES(n->bar.cc) < NVME_CTRL_CQES_MIN(n->id_ctrl.cqes))) { - trace_nvme_err_startfail_cqent_too_small( + trace_pci_nvme_err_startfail_cqent_too_small( NVME_CC_IOCQES(n->bar.cc), NVME_CTRL_CQES_MIN(n->bar.cap)); return -1; } if (unlikely(NVME_CC_IOCQES(n->bar.cc) > NVME_CTRL_CQES_MAX(n->id_ctrl.cqes))) { - trace_nvme_err_startfail_cqent_too_large( + trace_pci_nvme_err_startfail_cqent_too_large( NVME_CC_IOCQES(n->bar.cc), NVME_CTRL_CQES_MAX(n->bar.cap)); return -1; } if (unlikely(NVME_CC_IOSQES(n->bar.cc) < NVME_CTRL_SQES_MIN(n->id_ctrl.sqes))) { - trace_nvme_err_startfail_sqent_too_small( + trace_pci_nvme_err_startfail_sqent_too_small( NVME_CC_IOSQES(n->bar.cc), NVME_CTRL_SQES_MIN(n->bar.cap)); return -1; } if (unlikely(NVME_CC_IOSQES(n->bar.cc) > NVME_CTRL_SQES_MAX(n->id_ctrl.sqes))) { - trace_nvme_err_startfail_sqent_too_large( + trace_pci_nvme_err_startfail_sqent_too_large( NVME_CC_IOSQES(n->bar.cc), NVME_CTRL_SQES_MAX(n->bar.cap)); return -1; } if (unlikely(!NVME_AQA_ASQS(n->bar.aqa))) { - trace_nvme_err_startfail_asqent_sz_zero(); + trace_pci_nvme_err_startfail_asqent_sz_zero(); return -1; } if (unlikely(!NVME_AQA_ACQS(n->bar.aqa))) { - trace_nvme_err_startfail_acqent_sz_zero(); + trace_pci_nvme_err_startfail_acqent_sz_zero(); return -1; } @@ -1016,27 +2108,29 @@ static int nvme_start_ctrl(NvmeCtrl *n) n->cqe_size = 1 << NVME_CC_IOCQES(n->bar.cc); n->sqe_size = 1 << NVME_CC_IOSQES(n->bar.cc); nvme_init_cq(&n->admin_cq, n, n->bar.acq, 0, 0, - NVME_AQA_ACQS(n->bar.aqa) + 1, 1); + NVME_AQA_ACQS(n->bar.aqa) + 1, 1); nvme_init_sq(&n->admin_sq, n, n->bar.asq, 0, 0, - NVME_AQA_ASQS(n->bar.aqa) + 1); + NVME_AQA_ASQS(n->bar.aqa) + 1); nvme_set_timestamp(n, 0ULL); + QTAILQ_INIT(&n->aer_queue); + return 0; } static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data, - unsigned size) + unsigned size) { if (unlikely(offset & (sizeof(uint32_t) - 1))) { - NVME_GUEST_ERR(nvme_ub_mmiowr_misaligned32, + NVME_GUEST_ERR(pci_nvme_ub_mmiowr_misaligned32, "MMIO write not 32-bit aligned," " offset=0x%"PRIx64"", offset); /* should be ignored, fall through for now */ } if (unlikely(size < sizeof(uint32_t))) { - NVME_GUEST_ERR(nvme_ub_mmiowr_toosmall, + NVME_GUEST_ERR(pci_nvme_ub_mmiowr_toosmall, "MMIO write smaller than 32-bits," " offset=0x%"PRIx64", size=%u", offset, size); @@ -1046,32 +2140,30 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data, switch (offset) { case 0xc: /* INTMS */ if (unlikely(msix_enabled(&(n->parent_obj)))) { - NVME_GUEST_ERR(nvme_ub_mmiowr_intmask_with_msix, + NVME_GUEST_ERR(pci_nvme_ub_mmiowr_intmask_with_msix, "undefined access to interrupt mask set" " when MSI-X is enabled"); /* should be ignored, fall through for now */ } n->bar.intms |= data & 0xffffffff; n->bar.intmc = n->bar.intms; - trace_nvme_mmio_intm_set(data & 0xffffffff, - n->bar.intmc); + trace_pci_nvme_mmio_intm_set(data & 0xffffffff, n->bar.intmc); nvme_irq_check(n); break; case 0x10: /* INTMC */ if (unlikely(msix_enabled(&(n->parent_obj)))) { - NVME_GUEST_ERR(nvme_ub_mmiowr_intmask_with_msix, + NVME_GUEST_ERR(pci_nvme_ub_mmiowr_intmask_with_msix, "undefined access to interrupt mask clr" " when MSI-X is enabled"); /* should be ignored, fall through for now */ } n->bar.intms &= ~(data & 0xffffffff); n->bar.intmc = n->bar.intms; - trace_nvme_mmio_intm_clr(data & 0xffffffff, - n->bar.intmc); + trace_pci_nvme_mmio_intm_clr(data & 0xffffffff, n->bar.intmc); nvme_irq_check(n); break; case 0x14: /* CC */ - trace_nvme_mmio_cfg(data & 0xffffffff); + trace_pci_nvme_mmio_cfg(data & 0xffffffff); /* Windows first sends data, then sends enable bit */ if (!NVME_CC_EN(data) && !NVME_CC_EN(n->bar.cc) && !NVME_CC_SHN(data) && !NVME_CC_SHN(n->bar.cc)) @@ -1082,42 +2174,42 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data, if (NVME_CC_EN(data) && !NVME_CC_EN(n->bar.cc)) { n->bar.cc = data; if (unlikely(nvme_start_ctrl(n))) { - trace_nvme_err_startfail(); + trace_pci_nvme_err_startfail(); n->bar.csts = NVME_CSTS_FAILED; } else { - trace_nvme_mmio_start_success(); + trace_pci_nvme_mmio_start_success(); n->bar.csts = NVME_CSTS_READY; } } else if (!NVME_CC_EN(data) && NVME_CC_EN(n->bar.cc)) { - trace_nvme_mmio_stopped(); + trace_pci_nvme_mmio_stopped(); nvme_clear_ctrl(n); n->bar.csts &= ~NVME_CSTS_READY; } if (NVME_CC_SHN(data) && !(NVME_CC_SHN(n->bar.cc))) { - trace_nvme_mmio_shutdown_set(); + trace_pci_nvme_mmio_shutdown_set(); nvme_clear_ctrl(n); n->bar.cc = data; n->bar.csts |= NVME_CSTS_SHST_COMPLETE; } else if (!NVME_CC_SHN(data) && NVME_CC_SHN(n->bar.cc)) { - trace_nvme_mmio_shutdown_cleared(); + trace_pci_nvme_mmio_shutdown_cleared(); n->bar.csts &= ~NVME_CSTS_SHST_COMPLETE; n->bar.cc = data; } break; case 0x1C: /* CSTS */ if (data & (1 << 4)) { - NVME_GUEST_ERR(nvme_ub_mmiowr_ssreset_w1c_unsupported, + NVME_GUEST_ERR(pci_nvme_ub_mmiowr_ssreset_w1c_unsupported, "attempted to W1C CSTS.NSSRO" " but CAP.NSSRS is zero (not supported)"); } else if (data != 0) { - NVME_GUEST_ERR(nvme_ub_mmiowr_ro_csts, + NVME_GUEST_ERR(pci_nvme_ub_mmiowr_ro_csts, "attempted to set a read only bit" " of controller status"); } break; case 0x20: /* NSSR */ if (data == 0x4E564D65) { - trace_nvme_ub_mmiowr_ssreset_unsupported(); + trace_pci_nvme_ub_mmiowr_ssreset_unsupported(); } else { /* The spec says that writes of other values have no effect */ return; @@ -1125,55 +2217,55 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data, break; case 0x24: /* AQA */ n->bar.aqa = data & 0xffffffff; - trace_nvme_mmio_aqattr(data & 0xffffffff); + trace_pci_nvme_mmio_aqattr(data & 0xffffffff); break; case 0x28: /* ASQ */ n->bar.asq = data; - trace_nvme_mmio_asqaddr(data); + trace_pci_nvme_mmio_asqaddr(data); break; case 0x2c: /* ASQ hi */ n->bar.asq |= data << 32; - trace_nvme_mmio_asqaddr_hi(data, n->bar.asq); + trace_pci_nvme_mmio_asqaddr_hi(data, n->bar.asq); break; case 0x30: /* ACQ */ - trace_nvme_mmio_acqaddr(data); + trace_pci_nvme_mmio_acqaddr(data); n->bar.acq = data; break; case 0x34: /* ACQ hi */ n->bar.acq |= data << 32; - trace_nvme_mmio_acqaddr_hi(data, n->bar.acq); + trace_pci_nvme_mmio_acqaddr_hi(data, n->bar.acq); break; case 0x38: /* CMBLOC */ - NVME_GUEST_ERR(nvme_ub_mmiowr_cmbloc_reserved, + NVME_GUEST_ERR(pci_nvme_ub_mmiowr_cmbloc_reserved, "invalid write to reserved CMBLOC" " when CMBSZ is zero, ignored"); return; case 0x3C: /* CMBSZ */ - NVME_GUEST_ERR(nvme_ub_mmiowr_cmbsz_readonly, + NVME_GUEST_ERR(pci_nvme_ub_mmiowr_cmbsz_readonly, "invalid write to read only CMBSZ, ignored"); return; case 0xE00: /* PMRCAP */ - NVME_GUEST_ERR(nvme_ub_mmiowr_pmrcap_readonly, + NVME_GUEST_ERR(pci_nvme_ub_mmiowr_pmrcap_readonly, "invalid write to PMRCAP register, ignored"); return; case 0xE04: /* TODO PMRCTL */ break; case 0xE08: /* PMRSTS */ - NVME_GUEST_ERR(nvme_ub_mmiowr_pmrsts_readonly, + NVME_GUEST_ERR(pci_nvme_ub_mmiowr_pmrsts_readonly, "invalid write to PMRSTS register, ignored"); return; case 0xE0C: /* PMREBS */ - NVME_GUEST_ERR(nvme_ub_mmiowr_pmrebs_readonly, + NVME_GUEST_ERR(pci_nvme_ub_mmiowr_pmrebs_readonly, "invalid write to PMREBS register, ignored"); return; case 0xE10: /* PMRSWTP */ - NVME_GUEST_ERR(nvme_ub_mmiowr_pmrswtp_readonly, + NVME_GUEST_ERR(pci_nvme_ub_mmiowr_pmrswtp_readonly, "invalid write to PMRSWTP register, ignored"); return; case 0xE14: /* TODO PMRMSC */ - break; + break; default: - NVME_GUEST_ERR(nvme_ub_mmiowr_invalid, + NVME_GUEST_ERR(pci_nvme_ub_mmiowr_invalid, "invalid MMIO write," " offset=0x%"PRIx64", data=%"PRIx64"", offset, data); @@ -1187,13 +2279,15 @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size) uint8_t *ptr = (uint8_t *)&n->bar; uint64_t val = 0; + trace_pci_nvme_mmio_read(addr); + if (unlikely(addr & (sizeof(uint32_t) - 1))) { - NVME_GUEST_ERR(nvme_ub_mmiord_misaligned32, + NVME_GUEST_ERR(pci_nvme_ub_mmiord_misaligned32, "MMIO read not 32-bit aligned," " offset=0x%"PRIx64"", addr); /* should RAZ, fall through for now */ } else if (unlikely(size < sizeof(uint32_t))) { - NVME_GUEST_ERR(nvme_ub_mmiord_toosmall, + NVME_GUEST_ERR(pci_nvme_ub_mmiord_toosmall, "MMIO read smaller than 32-bits," " offset=0x%"PRIx64"", addr); /* should RAZ, fall through for now */ @@ -1207,12 +2301,11 @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size) */ if (addr == 0xE08 && (NVME_PMRCAP_PMRWBM(n->bar.pmrcap) & 0x02)) { - qemu_ram_writeback(n->pmrdev->mr.ram_block, - 0, n->pmrdev->size); + memory_region_msync(&n->pmrdev->mr, 0, n->pmrdev->size); } memcpy(&val, ptr + addr, size); } else { - NVME_GUEST_ERR(nvme_ub_mmiord_invalid_ofs, + NVME_GUEST_ERR(pci_nvme_ub_mmiord_invalid_ofs, "MMIO read beyond last register," " offset=0x%"PRIx64", returning 0", addr); } @@ -1225,7 +2318,7 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) uint32_t qid; if (unlikely(addr & ((1 << 2) - 1))) { - NVME_GUEST_ERR(nvme_ub_db_wr_misaligned, + NVME_GUEST_ERR(pci_nvme_ub_db_wr_misaligned, "doorbell write not 32-bit aligned," " offset=0x%"PRIx64", ignoring", addr); return; @@ -1240,23 +2333,52 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) qid = (addr - (0x1000 + (1 << 2))) >> 3; if (unlikely(nvme_check_cqid(n, qid))) { - NVME_GUEST_ERR(nvme_ub_db_wr_invalid_cq, + NVME_GUEST_ERR(pci_nvme_ub_db_wr_invalid_cq, "completion queue doorbell write" " for nonexistent queue," " sqid=%"PRIu32", ignoring", qid); + + /* + * NVM Express v1.3d, Section 4.1 state: "If host software writes + * an invalid value to the Submission Queue Tail Doorbell or + * Completion Queue Head Doorbell regiter and an Asynchronous Event + * Request command is outstanding, then an asynchronous event is + * posted to the Admin Completion Queue with a status code of + * Invalid Doorbell Write Value." + * + * Also note that the spec includes the "Invalid Doorbell Register" + * status code, but nowhere does it specify when to use it. + * However, it seems reasonable to use it here in a similar + * fashion. + */ + if (n->outstanding_aers) { + nvme_enqueue_event(n, NVME_AER_TYPE_ERROR, + NVME_AER_INFO_ERR_INVALID_DB_REGISTER, + NVME_LOG_ERROR_INFO); + } + return; } cq = n->cq[qid]; if (unlikely(new_head >= cq->size)) { - NVME_GUEST_ERR(nvme_ub_db_wr_invalid_cqhead, + NVME_GUEST_ERR(pci_nvme_ub_db_wr_invalid_cqhead, "completion queue doorbell write value" " beyond queue size, sqid=%"PRIu32"," " new_head=%"PRIu16", ignoring", qid, new_head); + + if (n->outstanding_aers) { + nvme_enqueue_event(n, NVME_AER_TYPE_ERROR, + NVME_AER_INFO_ERR_INVALID_DB_VALUE, + NVME_LOG_ERROR_INFO); + } + return; } + trace_pci_nvme_mmio_doorbell_cq(cq->cqid, new_head); + start_sqs = nvme_cq_full(cq) ? 1 : 0; cq->head = new_head; if (start_sqs) { @@ -1278,35 +2400,54 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) qid = (addr - 0x1000) >> 3; if (unlikely(nvme_check_sqid(n, qid))) { - NVME_GUEST_ERR(nvme_ub_db_wr_invalid_sq, + NVME_GUEST_ERR(pci_nvme_ub_db_wr_invalid_sq, "submission queue doorbell write" " for nonexistent queue," " sqid=%"PRIu32", ignoring", qid); + + if (n->outstanding_aers) { + nvme_enqueue_event(n, NVME_AER_TYPE_ERROR, + NVME_AER_INFO_ERR_INVALID_DB_REGISTER, + NVME_LOG_ERROR_INFO); + } + return; } sq = n->sq[qid]; if (unlikely(new_tail >= sq->size)) { - NVME_GUEST_ERR(nvme_ub_db_wr_invalid_sqtail, + NVME_GUEST_ERR(pci_nvme_ub_db_wr_invalid_sqtail, "submission queue doorbell write value" " beyond queue size, sqid=%"PRIu32"," " new_tail=%"PRIu16", ignoring", qid, new_tail); + + if (n->outstanding_aers) { + nvme_enqueue_event(n, NVME_AER_TYPE_ERROR, + NVME_AER_INFO_ERR_INVALID_DB_VALUE, + NVME_LOG_ERROR_INFO); + } + return; } + trace_pci_nvme_mmio_doorbell_sq(sq->sqid, new_tail); + sq->tail = new_tail; timer_mod(sq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500); } } static void nvme_mmio_write(void *opaque, hwaddr addr, uint64_t data, - unsigned size) + unsigned size) { NvmeCtrl *n = (NvmeCtrl *)opaque; + + trace_pci_nvme_mmio_write(addr, data); + if (addr < sizeof(n->bar)) { nvme_write_bar(n, addr, data, size); - } else if (addr >= 0x1000) { + } else { nvme_process_db(n, addr, data); } } @@ -1322,7 +2463,7 @@ static const MemoryRegionOps nvme_mmio_ops = { }; static void nvme_cmb_write(void *opaque, hwaddr addr, uint64_t data, - unsigned size) + unsigned size) { NvmeCtrl *n = (NvmeCtrl *)opaque; stn_le_p(&n->cmbuf[addr], size, data); @@ -1344,41 +2485,45 @@ static const MemoryRegionOps nvme_cmb_ops = { }, }; -static void nvme_realize(PCIDevice *pci_dev, Error **errp) +static void nvme_check_constraints(NvmeCtrl *n, Error **errp) { - NvmeCtrl *n = NVME(pci_dev); - NvmeIdCtrl *id = &n->id_ctrl; + NvmeParams *params = &n->params; - int i; - int64_t bs_size; - uint8_t *pci_conf; + if (params->num_queues) { + warn_report("num_queues is deprecated; please use max_ioqpairs " + "instead"); - if (!n->num_queues) { - error_setg(errp, "num_queues can't be zero"); - return; + params->max_ioqpairs = params->num_queues - 1; + } + + if (n->conf.blk) { + warn_report("drive property is deprecated; " + "please use an nvme-ns device instead"); } - if (!n->conf.blk) { - error_setg(errp, "drive property not set"); + if (params->max_ioqpairs < 1 || + params->max_ioqpairs > NVME_MAX_IOQPAIRS) { + error_setg(errp, "max_ioqpairs must be between 1 and %d", + NVME_MAX_IOQPAIRS); return; } - bs_size = blk_getlength(n->conf.blk); - if (bs_size < 0) { - error_setg(errp, "could not get backing file size"); + if (params->msix_qsize < 1 || + params->msix_qsize > PCI_MSIX_FLAGS_QSIZE + 1) { + error_setg(errp, "msix_qsize must be between 1 and %d", + PCI_MSIX_FLAGS_QSIZE + 1); return; } - if (!n->serial) { + if (!params->serial) { error_setg(errp, "serial property not set"); return; } - if (!n->cmb_size_mb && n->pmrdev) { + if (!n->params.cmb_size_mb && n->pmrdev) { if (host_memory_backend_is_mapped(n->pmrdev)) { - char *path = object_get_canonical_path_component(OBJECT(n->pmrdev)); - error_setg(errp, "can't use already busy memdev: %s", path); - g_free(path); + error_setg(errp, "can't use already busy memdev: %s", + object_get_canonical_path_component(OBJECT(n->pmrdev))); return; } @@ -1389,150 +2534,263 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp) host_memory_backend_set_mapped(n->pmrdev, true); } +} - blkconf_blocksizes(&n->conf); - if (!blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk), - false, errp)) { - return; +static void nvme_init_state(NvmeCtrl *n) +{ + n->num_namespaces = NVME_MAX_NAMESPACES; + /* add one to max_ioqpairs to account for the admin queue pair */ + n->reg_size = pow2ceil(sizeof(NvmeBar) + + 2 * (n->params.max_ioqpairs + 1) * NVME_DB_SIZE); + n->sq = g_new0(NvmeSQueue *, n->params.max_ioqpairs + 1); + n->cq = g_new0(NvmeCQueue *, n->params.max_ioqpairs + 1); + n->temperature = NVME_TEMPERATURE; + n->features.temp_thresh_hi = NVME_TEMPERATURE_WARNING; + n->starttime_ms = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); + n->aer_reqs = g_new0(NvmeRequest *, n->params.aerl + 1); +} + +int nvme_register_namespace(NvmeCtrl *n, NvmeNamespace *ns, Error **errp) +{ + uint32_t nsid = nvme_nsid(ns); + + if (nsid > NVME_MAX_NAMESPACES) { + error_setg(errp, "invalid namespace id (must be between 0 and %d)", + NVME_MAX_NAMESPACES); + return -1; + } + + if (!nsid) { + for (int i = 1; i <= n->num_namespaces; i++) { + if (!nvme_ns(n, i)) { + nsid = ns->params.nsid = i; + break; + } + } + + if (!nsid) { + error_setg(errp, "no free namespace id"); + return -1; + } + } else { + if (n->namespaces[nsid - 1]) { + error_setg(errp, "namespace id '%d' is already in use", nsid); + return -1; + } } - pci_conf = pci_dev->config; + trace_pci_nvme_register_namespace(nsid); + + n->namespaces[nsid - 1] = ns; + + return 0; +} + +static void nvme_init_cmb(NvmeCtrl *n, PCIDevice *pci_dev) +{ + NVME_CMBLOC_SET_BIR(n->bar.cmbloc, NVME_CMB_BIR); + NVME_CMBLOC_SET_OFST(n->bar.cmbloc, 0); + + NVME_CMBSZ_SET_SQS(n->bar.cmbsz, 1); + NVME_CMBSZ_SET_CQS(n->bar.cmbsz, 0); + NVME_CMBSZ_SET_LISTS(n->bar.cmbsz, 1); + NVME_CMBSZ_SET_RDS(n->bar.cmbsz, 1); + NVME_CMBSZ_SET_WDS(n->bar.cmbsz, 1); + NVME_CMBSZ_SET_SZU(n->bar.cmbsz, 2); /* MBs */ + NVME_CMBSZ_SET_SZ(n->bar.cmbsz, n->params.cmb_size_mb); + + n->cmbuf = g_malloc0(NVME_CMBSZ_GETSIZE(n->bar.cmbsz)); + memory_region_init_io(&n->ctrl_mem, OBJECT(n), &nvme_cmb_ops, n, + "nvme-cmb", NVME_CMBSZ_GETSIZE(n->bar.cmbsz)); + pci_register_bar(pci_dev, NVME_CMBLOC_BIR(n->bar.cmbloc), + PCI_BASE_ADDRESS_SPACE_MEMORY | + PCI_BASE_ADDRESS_MEM_TYPE_64 | + PCI_BASE_ADDRESS_MEM_PREFETCH, &n->ctrl_mem); +} + +static void nvme_init_pmr(NvmeCtrl *n, PCIDevice *pci_dev) +{ + /* Controller Capabilities register */ + NVME_CAP_SET_PMRS(n->bar.cap, 1); + + /* PMR Capabities register */ + n->bar.pmrcap = 0; + NVME_PMRCAP_SET_RDS(n->bar.pmrcap, 0); + NVME_PMRCAP_SET_WDS(n->bar.pmrcap, 0); + NVME_PMRCAP_SET_BIR(n->bar.pmrcap, NVME_PMR_BIR); + NVME_PMRCAP_SET_PMRTU(n->bar.pmrcap, 0); + /* Turn on bit 1 support */ + NVME_PMRCAP_SET_PMRWBM(n->bar.pmrcap, 0x02); + NVME_PMRCAP_SET_PMRTO(n->bar.pmrcap, 0); + NVME_PMRCAP_SET_CMSS(n->bar.pmrcap, 0); + + /* PMR Control register */ + n->bar.pmrctl = 0; + NVME_PMRCTL_SET_EN(n->bar.pmrctl, 0); + + /* PMR Status register */ + n->bar.pmrsts = 0; + NVME_PMRSTS_SET_ERR(n->bar.pmrsts, 0); + NVME_PMRSTS_SET_NRDY(n->bar.pmrsts, 0); + NVME_PMRSTS_SET_HSTS(n->bar.pmrsts, 0); + NVME_PMRSTS_SET_CBAI(n->bar.pmrsts, 0); + + /* PMR Elasticity Buffer Size register */ + n->bar.pmrebs = 0; + NVME_PMREBS_SET_PMRSZU(n->bar.pmrebs, 0); + NVME_PMREBS_SET_RBB(n->bar.pmrebs, 0); + NVME_PMREBS_SET_PMRWBZ(n->bar.pmrebs, 0); + + /* PMR Sustained Write Throughput register */ + n->bar.pmrswtp = 0; + NVME_PMRSWTP_SET_PMRSWTU(n->bar.pmrswtp, 0); + NVME_PMRSWTP_SET_PMRSWTV(n->bar.pmrswtp, 0); + + /* PMR Memory Space Control register */ + n->bar.pmrmsc = 0; + NVME_PMRMSC_SET_CMSE(n->bar.pmrmsc, 0); + NVME_PMRMSC_SET_CBA(n->bar.pmrmsc, 0); + + pci_register_bar(pci_dev, NVME_PMRCAP_BIR(n->bar.pmrcap), + PCI_BASE_ADDRESS_SPACE_MEMORY | + PCI_BASE_ADDRESS_MEM_TYPE_64 | + PCI_BASE_ADDRESS_MEM_PREFETCH, &n->pmrdev->mr); +} + +static void nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp) +{ + uint8_t *pci_conf = pci_dev->config; + pci_conf[PCI_INTERRUPT_PIN] = 1; - pci_config_set_prog_interface(pci_dev->config, 0x2); - pci_config_set_class(pci_dev->config, PCI_CLASS_STORAGE_EXPRESS); + pci_config_set_prog_interface(pci_conf, 0x2); + + if (n->params.use_intel_id) { + pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL); + pci_config_set_device_id(pci_conf, 0x5845); + } else { + pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_REDHAT); + pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_REDHAT_NVME); + } + + pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_EXPRESS); pcie_endpoint_cap_init(pci_dev, 0x80); - n->num_namespaces = 1; - n->reg_size = pow2ceil(0x1004 + 2 * (n->num_queues + 1) * 4); - n->ns_size = bs_size / (uint64_t)n->num_namespaces; + memory_region_init_io(&n->iomem, OBJECT(n), &nvme_mmio_ops, n, "nvme", + n->reg_size); + pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY | + PCI_BASE_ADDRESS_MEM_TYPE_64, &n->iomem); + if (msix_init_exclusive_bar(pci_dev, n->params.msix_qsize, 4, errp)) { + return; + } - n->namespaces = g_new0(NvmeNamespace, n->num_namespaces); - n->sq = g_new0(NvmeSQueue *, n->num_queues); - n->cq = g_new0(NvmeCQueue *, n->num_queues); + if (n->params.cmb_size_mb) { + nvme_init_cmb(n, pci_dev); + } else if (n->pmrdev) { + nvme_init_pmr(n, pci_dev); + } +} - memory_region_init_io(&n->iomem, OBJECT(n), &nvme_mmio_ops, n, - "nvme", n->reg_size); - pci_register_bar(pci_dev, 0, - PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64, - &n->iomem); - msix_init_exclusive_bar(pci_dev, n->num_queues, 4, NULL); +static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev) +{ + NvmeIdCtrl *id = &n->id_ctrl; + uint8_t *pci_conf = pci_dev->config; + char *subnqn; id->vid = cpu_to_le16(pci_get_word(pci_conf + PCI_VENDOR_ID)); id->ssvid = cpu_to_le16(pci_get_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID)); strpadcpy((char *)id->mn, sizeof(id->mn), "QEMU NVMe Ctrl", ' '); strpadcpy((char *)id->fr, sizeof(id->fr), "1.0", ' '); - strpadcpy((char *)id->sn, sizeof(id->sn), n->serial, ' '); + strpadcpy((char *)id->sn, sizeof(id->sn), n->params.serial, ' '); id->rab = 6; id->ieee[0] = 0x00; id->ieee[1] = 0x02; id->ieee[2] = 0xb3; + id->mdts = n->params.mdts; + id->ver = cpu_to_le32(NVME_SPEC_VER); id->oacs = cpu_to_le16(0); - id->frmw = 7 << 1; - id->lpa = 1 << 0; + + /* + * Because the controller always completes the Abort command immediately, + * there can never be more than one concurrently executing Abort command, + * so this value is never used for anything. Note that there can easily be + * many Abort commands in the queues, but they are not considered + * "executing" until processed by nvme_abort. + * + * The specification recommends a value of 3 for Abort Command Limit (four + * concurrently outstanding Abort commands), so lets use that though it is + * inconsequential. + */ + id->acl = 3; + id->aerl = n->params.aerl; + id->frmw = (NVME_NUM_FW_SLOTS << 1) | NVME_FRMW_SLOT1_RO; + id->lpa = NVME_LPA_NS_SMART | NVME_LPA_EXTENDED; + + /* recommended default value (~70 C) */ + id->wctemp = cpu_to_le16(NVME_TEMPERATURE_WARNING); + id->cctemp = cpu_to_le16(NVME_TEMPERATURE_CRITICAL); + id->sqes = (0x6 << 4) | 0x6; id->cqes = (0x4 << 4) | 0x4; id->nn = cpu_to_le32(n->num_namespaces); - id->oncs = cpu_to_le16(NVME_ONCS_WRITE_ZEROS | NVME_ONCS_TIMESTAMP); + id->oncs = cpu_to_le16(NVME_ONCS_WRITE_ZEROES | NVME_ONCS_TIMESTAMP | + NVME_ONCS_FEATURES); + + id->vwc = 0x1; + id->sgls = cpu_to_le32(NVME_CTRL_SGLS_SUPPORT_NO_ALIGN | + NVME_CTRL_SGLS_BITBUCKET); + + subnqn = g_strdup_printf("nqn.2019-08.org.qemu:%s", n->params.serial); + strpadcpy((char *)id->subnqn, sizeof(id->subnqn), subnqn, '\0'); + g_free(subnqn); + id->psd[0].mp = cpu_to_le16(0x9c4); id->psd[0].enlat = cpu_to_le32(0x10); id->psd[0].exlat = cpu_to_le32(0x4); - if (blk_enable_write_cache(n->conf.blk)) { - id->vwc = 1; - } n->bar.cap = 0; NVME_CAP_SET_MQES(n->bar.cap, 0x7ff); NVME_CAP_SET_CQR(n->bar.cap, 1); NVME_CAP_SET_TO(n->bar.cap, 0xf); - NVME_CAP_SET_CSS(n->bar.cap, 1); + NVME_CAP_SET_CSS(n->bar.cap, NVME_CAP_CSS_NVM); + NVME_CAP_SET_CSS(n->bar.cap, NVME_CAP_CSS_ADMIN_ONLY); NVME_CAP_SET_MPSMAX(n->bar.cap, 4); - n->bar.vs = 0x00010200; + n->bar.vs = NVME_SPEC_VER; n->bar.intmc = n->bar.intms = 0; +} + +static void nvme_realize(PCIDevice *pci_dev, Error **errp) +{ + NvmeCtrl *n = NVME(pci_dev); + NvmeNamespace *ns; + Error *local_err = NULL; - if (n->cmb_size_mb) { + nvme_check_constraints(n, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } - NVME_CMBLOC_SET_BIR(n->bar.cmbloc, 2); - NVME_CMBLOC_SET_OFST(n->bar.cmbloc, 0); + qbus_create_inplace(&n->bus, sizeof(NvmeBus), TYPE_NVME_BUS, + &pci_dev->qdev, n->parent_obj.qdev.id); - NVME_CMBSZ_SET_SQS(n->bar.cmbsz, 1); - NVME_CMBSZ_SET_CQS(n->bar.cmbsz, 0); - NVME_CMBSZ_SET_LISTS(n->bar.cmbsz, 0); - NVME_CMBSZ_SET_RDS(n->bar.cmbsz, 1); - NVME_CMBSZ_SET_WDS(n->bar.cmbsz, 1); - NVME_CMBSZ_SET_SZU(n->bar.cmbsz, 2); /* MBs */ - NVME_CMBSZ_SET_SZ(n->bar.cmbsz, n->cmb_size_mb); + nvme_init_state(n); + nvme_init_pci(n, pci_dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } - n->cmbloc = n->bar.cmbloc; - n->cmbsz = n->bar.cmbsz; + nvme_init_ctrl(n, pci_dev); - n->cmbuf = g_malloc0(NVME_CMBSZ_GETSIZE(n->bar.cmbsz)); - memory_region_init_io(&n->ctrl_mem, OBJECT(n), &nvme_cmb_ops, n, - "nvme-cmb", NVME_CMBSZ_GETSIZE(n->bar.cmbsz)); - pci_register_bar(pci_dev, NVME_CMBLOC_BIR(n->bar.cmbloc), - PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 | - PCI_BASE_ADDRESS_MEM_PREFETCH, &n->ctrl_mem); + /* setup a namespace if the controller drive property was given */ + if (n->namespace.blkconf.blk) { + ns = &n->namespace; + ns->params.nsid = 1; - } else if (n->pmrdev) { - /* Controller Capabilities register */ - NVME_CAP_SET_PMRS(n->bar.cap, 1); - - /* PMR Capabities register */ - n->bar.pmrcap = 0; - NVME_PMRCAP_SET_RDS(n->bar.pmrcap, 0); - NVME_PMRCAP_SET_WDS(n->bar.pmrcap, 0); - NVME_PMRCAP_SET_BIR(n->bar.pmrcap, 2); - NVME_PMRCAP_SET_PMRTU(n->bar.pmrcap, 0); - /* Turn on bit 1 support */ - NVME_PMRCAP_SET_PMRWBM(n->bar.pmrcap, 0x02); - NVME_PMRCAP_SET_PMRTO(n->bar.pmrcap, 0); - NVME_PMRCAP_SET_CMSS(n->bar.pmrcap, 0); - - /* PMR Control register */ - n->bar.pmrctl = 0; - NVME_PMRCTL_SET_EN(n->bar.pmrctl, 0); - - /* PMR Status register */ - n->bar.pmrsts = 0; - NVME_PMRSTS_SET_ERR(n->bar.pmrsts, 0); - NVME_PMRSTS_SET_NRDY(n->bar.pmrsts, 0); - NVME_PMRSTS_SET_HSTS(n->bar.pmrsts, 0); - NVME_PMRSTS_SET_CBAI(n->bar.pmrsts, 0); - - /* PMR Elasticity Buffer Size register */ - n->bar.pmrebs = 0; - NVME_PMREBS_SET_PMRSZU(n->bar.pmrebs, 0); - NVME_PMREBS_SET_RBB(n->bar.pmrebs, 0); - NVME_PMREBS_SET_PMRWBZ(n->bar.pmrebs, 0); - - /* PMR Sustained Write Throughput register */ - n->bar.pmrswtp = 0; - NVME_PMRSWTP_SET_PMRSWTU(n->bar.pmrswtp, 0); - NVME_PMRSWTP_SET_PMRSWTV(n->bar.pmrswtp, 0); - - /* PMR Memory Space Control register */ - n->bar.pmrmsc = 0; - NVME_PMRMSC_SET_CMSE(n->bar.pmrmsc, 0); - NVME_PMRMSC_SET_CBA(n->bar.pmrmsc, 0); - - pci_register_bar(pci_dev, NVME_PMRCAP_BIR(n->bar.pmrcap), - PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 | - PCI_BASE_ADDRESS_MEM_PREFETCH, &n->pmrdev->mr); - } - - for (i = 0; i < n->num_namespaces; i++) { - NvmeNamespace *ns = &n->namespaces[i]; - NvmeIdNs *id_ns = &ns->id_ns; - id_ns->nsfeat = 0; - id_ns->nlbaf = 0; - id_ns->flbas = 0; - id_ns->mc = 0; - id_ns->dpc = 0; - id_ns->dps = 0; - id_ns->lbaf[0].ds = BDRV_SECTOR_BITS; - id_ns->ncap = id_ns->nuse = id_ns->nsze = - cpu_to_le64(n->ns_size >> - id_ns->lbaf[NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas)].ds); + if (nvme_ns_setup(n, ns, errp)) { + return; + } } } @@ -1541,11 +2799,11 @@ static void nvme_exit(PCIDevice *pci_dev) NvmeCtrl *n = NVME(pci_dev); nvme_clear_ctrl(n); - g_free(n->namespaces); g_free(n->cq); g_free(n->sq); + g_free(n->aer_reqs); - if (n->cmb_size_mb) { + if (n->params.cmb_size_mb) { g_free(n->cmbuf); } @@ -1556,12 +2814,18 @@ static void nvme_exit(PCIDevice *pci_dev) } static Property nvme_props[] = { - DEFINE_BLOCK_PROPERTIES(NvmeCtrl, conf), + DEFINE_BLOCK_PROPERTIES(NvmeCtrl, namespace.blkconf), DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmrdev, TYPE_MEMORY_BACKEND, HostMemoryBackend *), - DEFINE_PROP_STRING("serial", NvmeCtrl, serial), - DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, cmb_size_mb, 0), - DEFINE_PROP_UINT32("num_queues", NvmeCtrl, num_queues, 64), + DEFINE_PROP_STRING("serial", NvmeCtrl, params.serial), + DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, params.cmb_size_mb, 0), + DEFINE_PROP_UINT32("num_queues", NvmeCtrl, params.num_queues, 0), + DEFINE_PROP_UINT32("max_ioqpairs", NvmeCtrl, params.max_ioqpairs, 64), + DEFINE_PROP_UINT16("msix_qsize", NvmeCtrl, params.msix_qsize, 65), + DEFINE_PROP_UINT8("aerl", NvmeCtrl, params.aerl, 3), + DEFINE_PROP_UINT32("aer_max_queued", NvmeCtrl, params.aer_max_queued, 64), + DEFINE_PROP_UINT8("mdts", NvmeCtrl, params.mdts, 7), + DEFINE_PROP_BOOL("use-intel-id", NvmeCtrl, params.use_intel_id, false), DEFINE_PROP_END_OF_LIST(), }; @@ -1578,8 +2842,6 @@ static void nvme_class_init(ObjectClass *oc, void *data) pc->realize = nvme_realize; pc->exit = nvme_exit; pc->class_id = PCI_CLASS_STORAGE_EXPRESS; - pc->vendor_id = PCI_VENDOR_ID_INTEL; - pc->device_id = 0x5845; pc->revision = 2; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); @@ -1592,26 +2854,35 @@ static void nvme_instance_init(Object *obj) { NvmeCtrl *s = NVME(obj); - device_add_bootindex_property(obj, &s->conf.bootindex, - "bootindex", "/namespace@1,0", - DEVICE(obj)); + if (s->namespace.blkconf.blk) { + device_add_bootindex_property(obj, &s->namespace.blkconf.bootindex, + "bootindex", "/namespace@1,0", + DEVICE(obj)); + } } static const TypeInfo nvme_info = { .name = TYPE_NVME, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(NvmeCtrl), - .class_init = nvme_class_init, .instance_init = nvme_instance_init, + .class_init = nvme_class_init, .interfaces = (InterfaceInfo[]) { { INTERFACE_PCIE_DEVICE }, { } }, }; +static const TypeInfo nvme_bus_info = { + .name = TYPE_NVME_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(NvmeBus), +}; + static void nvme_register_types(void) { type_register_static(&nvme_info); + type_register_static(&nvme_bus_info); } type_init(nvme_register_types) diff --git a/hw/block/nvme.h b/hw/block/nvme.h index 6520a9f0bead46082738267434675a2b86771e65..e080a2318a50689eb8c6c94c15f32e56dcb29ebd 100644 --- a/hw/block/nvme.h +++ b/hw/block/nvme.h @@ -1,24 +1,69 @@ #ifndef HW_NVME_H #define HW_NVME_H + #include "block/nvme.h" +#include "nvme-ns.h" + +#define NVME_MAX_NAMESPACES 256 + +typedef struct NvmeParams { + char *serial; + uint32_t num_queues; /* deprecated since 5.1 */ + uint32_t max_ioqpairs; + uint16_t msix_qsize; + uint32_t cmb_size_mb; + uint8_t aerl; + uint32_t aer_max_queued; + uint8_t mdts; + bool use_intel_id; +} NvmeParams; typedef struct NvmeAsyncEvent { - QSIMPLEQ_ENTRY(NvmeAsyncEvent) entry; + QTAILQ_ENTRY(NvmeAsyncEvent) entry; NvmeAerResult result; } NvmeAsyncEvent; typedef struct NvmeRequest { struct NvmeSQueue *sq; + struct NvmeNamespace *ns; BlockAIOCB *aiocb; uint16_t status; - bool has_sg; NvmeCqe cqe; + NvmeCmd cmd; BlockAcctCookie acct; QEMUSGList qsg; QEMUIOVector iov; QTAILQ_ENTRY(NvmeRequest)entry; } NvmeRequest; +static inline const char *nvme_adm_opc_str(uint8_t opc) +{ + switch (opc) { + case NVME_ADM_CMD_DELETE_SQ: return "NVME_ADM_CMD_DELETE_SQ"; + case NVME_ADM_CMD_CREATE_SQ: return "NVME_ADM_CMD_CREATE_SQ"; + case NVME_ADM_CMD_GET_LOG_PAGE: return "NVME_ADM_CMD_GET_LOG_PAGE"; + case NVME_ADM_CMD_DELETE_CQ: return "NVME_ADM_CMD_DELETE_CQ"; + case NVME_ADM_CMD_CREATE_CQ: return "NVME_ADM_CMD_CREATE_CQ"; + case NVME_ADM_CMD_IDENTIFY: return "NVME_ADM_CMD_IDENTIFY"; + case NVME_ADM_CMD_ABORT: return "NVME_ADM_CMD_ABORT"; + case NVME_ADM_CMD_SET_FEATURES: return "NVME_ADM_CMD_SET_FEATURES"; + case NVME_ADM_CMD_GET_FEATURES: return "NVME_ADM_CMD_GET_FEATURES"; + case NVME_ADM_CMD_ASYNC_EV_REQ: return "NVME_ADM_CMD_ASYNC_EV_REQ"; + default: return "NVME_ADM_CMD_UNKNOWN"; + } +} + +static inline const char *nvme_io_opc_str(uint8_t opc) +{ + switch (opc) { + case NVME_CMD_FLUSH: return "NVME_NVM_CMD_FLUSH"; + case NVME_CMD_WRITE: return "NVME_NVM_CMD_WRITE"; + case NVME_CMD_READ: return "NVME_NVM_CMD_READ"; + case NVME_CMD_WRITE_ZEROES: return "NVME_NVM_CMD_WRITE_ZEROES"; + default: return "NVME_NVM_CMD_UNKNOWN"; + } +} + typedef struct NvmeSQueue { struct NvmeCtrl *ctrl; uint16_t sqid; @@ -49,21 +94,36 @@ typedef struct NvmeCQueue { QTAILQ_HEAD(, NvmeRequest) req_list; } NvmeCQueue; -typedef struct NvmeNamespace { - NvmeIdNs id_ns; -} NvmeNamespace; +#define TYPE_NVME_BUS "nvme-bus" +#define NVME_BUS(obj) OBJECT_CHECK(NvmeBus, (obj), TYPE_NVME_BUS) + +typedef struct NvmeBus { + BusState parent_bus; +} NvmeBus; #define TYPE_NVME "nvme" #define NVME(obj) \ OBJECT_CHECK(NvmeCtrl, (obj), TYPE_NVME) +typedef struct NvmeFeatureVal { + struct { + uint16_t temp_thresh_hi; + uint16_t temp_thresh_low; + }; + uint32_t async_config; + uint32_t vwc; +} NvmeFeatureVal; + typedef struct NvmeCtrl { PCIDevice parent_obj; MemoryRegion iomem; MemoryRegion ctrl_mem; NvmeBar bar; + NvmeParams params; + NvmeBus bus; BlockConf conf; + bool qs_created; uint32_t page_size; uint16_t page_bits; uint16_t max_prp_ents; @@ -71,26 +131,55 @@ typedef struct NvmeCtrl { uint16_t sqe_size; uint32_t reg_size; uint32_t num_namespaces; - uint32_t num_queues; uint32_t max_q_ents; - uint64_t ns_size; - uint32_t cmb_size_mb; - uint32_t cmbsz; - uint32_t cmbloc; + uint8_t outstanding_aers; uint8_t *cmbuf; - uint64_t irq_status; + uint32_t irq_status; uint64_t host_timestamp; /* Timestamp sent by the host */ uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */ + uint64_t starttime_ms; + uint16_t temperature; - char *serial; HostMemoryBackend *pmrdev; - NvmeNamespace *namespaces; + uint8_t aer_mask; + NvmeRequest **aer_reqs; + QTAILQ_HEAD(, NvmeAsyncEvent) aer_queue; + int aer_queued; + + NvmeNamespace namespace; + NvmeNamespace *namespaces[NVME_MAX_NAMESPACES]; NvmeSQueue **sq; NvmeCQueue **cq; NvmeSQueue admin_sq; NvmeCQueue admin_cq; NvmeIdCtrl id_ctrl; + NvmeFeatureVal features; } NvmeCtrl; +static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid) +{ + if (!nsid || nsid > n->num_namespaces) { + return NULL; + } + + return n->namespaces[nsid - 1]; +} + +static inline NvmeCQueue *nvme_cq(NvmeRequest *req) +{ + NvmeSQueue *sq = req->sq; + NvmeCtrl *n = sq->ctrl; + + return n->cq[sq->cqid]; +} + +static inline NvmeCtrl *nvme_ctrl(NvmeRequest *req) +{ + NvmeSQueue *sq = req->sq; + return sq->ctrl; +} + +int nvme_register_namespace(NvmeCtrl *n, NvmeNamespace *ns, Error **errp); + #endif /* HW_NVME_H */ diff --git a/hw/block/onenand.c b/hw/block/onenand.c index 898ac563a3890c9af5f43316d75aa4921155d68a..5ff7be86bb798190b976779d76032067dc5f0d66 100644 --- a/hw/block/onenand.c +++ b/hw/block/onenand.c @@ -31,6 +31,7 @@ #include "qemu/error-report.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" /* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */ #define PAGE_SHIFT 11 @@ -39,9 +40,9 @@ #define BLOCK_SHIFT (PAGE_SHIFT + 6) #define TYPE_ONE_NAND "onenand" -#define ONE_NAND(obj) OBJECT_CHECK(OneNANDState, (obj), TYPE_ONE_NAND) +OBJECT_DECLARE_SIMPLE_TYPE(OneNANDState, ONE_NAND) -typedef struct OneNANDState { +struct OneNANDState { SysBusDevice parent_obj; struct { @@ -85,7 +86,7 @@ typedef struct OneNANDState { int secs_cur; int blocks; uint8_t *blockwp; -} OneNANDState; +}; enum { ONEN_BUF_BLOCK = 0, diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c index 11922c0f96b5b8ba59f940308ef174e3d27f7ea7..daae9658605f4a348d6e91c84b31da554464aee7 100644 --- a/hw/block/pflash_cfi01.c +++ b/hw/block/pflash_cfi01.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -213,7 +213,6 @@ static uint32_t pflash_devid_query(PFlashCFI01 *pfl, hwaddr offset) default: trace_pflash_device_info(offset); return 0; - break; } /* Replicate responses for each device in bank. */ if (pfl->device_width < pfl->bank_width) { @@ -696,12 +695,12 @@ static const MemoryRegionOps pflash_cfi01_ops = { static void pflash_cfi01_realize(DeviceState *dev, Error **errp) { + ERRP_GUARD(); PFlashCFI01 *pfl = PFLASH_CFI01(dev); uint64_t total_len; int ret; uint64_t blocks_per_device, sector_len_per_device, device_len; int num_devices; - Error *local_err = NULL; if (pfl->sector_len == 0) { error_setg(errp, "attribute \"sector-length\" not specified or zero."); @@ -735,9 +734,8 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) &pfl->mem, OBJECT(dev), &pflash_cfi01_ops, pfl, - pfl->name, total_len, &local_err); - if (local_err) { - error_propagate(errp, local_err); + pfl->name, total_len, errp); + if (*errp) { return; } @@ -959,10 +957,10 @@ PFlashCFI01 *pflash_cfi01_register(hwaddr base, uint16_t id2, uint16_t id3, int be) { - DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01); + DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01); if (blk) { - qdev_prop_set_drive(dev, "drive", blk, &error_abort); + qdev_prop_set_drive(dev, "drive", blk); } assert(QEMU_IS_ALIGNED(size, sector_len)); qdev_prop_set_uint32(dev, "num-blocks", size / sector_len); @@ -974,7 +972,7 @@ PFlashCFI01 *pflash_cfi01_register(hwaddr base, qdev_prop_set_uint16(dev, "id2", id2); qdev_prop_set_uint16(dev, "id3", id3); qdev_prop_set_string(dev, "name", name); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); return PFLASH_CFI01(dev); @@ -1010,8 +1008,8 @@ void pflash_cfi01_legacy_drive(PFlashCFI01 *fl, DriveInfo *dinfo) error_report("clashes with -machine"); exit(1); } - qdev_prop_set_drive(DEVICE(fl), "drive", - blk_by_legacy_dinfo(dinfo), &error_fatal); + qdev_prop_set_drive_err(DEVICE(fl), "drive", blk_by_legacy_dinfo(dinfo), + &error_fatal); loc_pop(&loc); } diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c index ac7e34ecbf144d26f100d8e72a847fa375711116..1b3d94e0473bd4490b7c97d7c7e7d7cc9bbe490d 100644 --- a/hw/block/pflash_cfi02.c +++ b/hw/block/pflash_cfi02.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -724,9 +724,9 @@ static const MemoryRegionOps pflash_cfi02_ops = { static void pflash_cfi02_realize(DeviceState *dev, Error **errp) { + ERRP_GUARD(); PFlashCFI02 *pfl = PFLASH_CFI02(dev); int ret; - Error *local_err = NULL; if (pfl->uniform_sector_len == 0 && pfl->sector_len[0] == 0) { error_setg(errp, "attribute \"sector-length\" not specified or zero."); @@ -792,9 +792,8 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) memory_region_init_rom_device(&pfl->orig_mem, OBJECT(pfl), &pflash_cfi02_ops, pfl, pfl->name, - pfl->chip_len, &local_err); - if (local_err) { - error_propagate(errp, local_err); + pfl->chip_len, errp); + if (*errp) { return; } @@ -998,10 +997,10 @@ PFlashCFI02 *pflash_cfi02_register(hwaddr base, uint16_t unlock_addr1, int be) { - DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI02); + DeviceState *dev = qdev_new(TYPE_PFLASH_CFI02); if (blk) { - qdev_prop_set_drive(dev, "drive", blk, &error_abort); + qdev_prop_set_drive(dev, "drive", blk); } assert(QEMU_IS_ALIGNED(size, sector_len)); qdev_prop_set_uint32(dev, "num-blocks", size / sector_len); @@ -1016,7 +1015,7 @@ PFlashCFI02 *pflash_cfi02_register(hwaddr base, qdev_prop_set_uint16(dev, "unlock-addr0", unlock_addr0); qdev_prop_set_uint16(dev, "unlock-addr1", unlock_addr1); qdev_prop_set_string(dev, "name", name); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); return PFLASH_CFI02(dev); diff --git a/hw/block/swim.c b/hw/block/swim.c index 8f124782f41a3c5aa834b81ef9c4eeb16d53ace9..20133a814c44095028ea0efe7d53b31c11dc6fb2 100644 --- a/hw/block/swim.c +++ b/hw/block/swim.c @@ -189,7 +189,10 @@ static void swim_drive_realize(DeviceState *qdev, Error **errp) assert(ret == 0); } - blkconf_blocksizes(&dev->conf); + if (!blkconf_blocksizes(&dev->conf, errp)) { + return; + } + if (dev->conf.logical_block_size != 512 || dev->conf.physical_block_size != 512) { @@ -384,7 +387,7 @@ static const MemoryRegionOps swimctrl_mem_ops = { static void sysbus_swim_reset(DeviceState *d) { - SWIM *sys = SWIM(d); + Swim *sys = SWIM(d); SWIMCtrl *ctrl = &sys->ctrl; int i; @@ -405,7 +408,7 @@ static void sysbus_swim_reset(DeviceState *d) static void sysbus_swim_init(Object *obj) { SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - SWIM *sbs = SWIM(obj); + Swim *sbs = SWIM(obj); SWIMCtrl *swimctrl = &sbs->ctrl; memory_region_init_io(&swimctrl->iomem, obj, &swimctrl_mem_ops, swimctrl, @@ -415,7 +418,7 @@ static void sysbus_swim_init(Object *obj) static void sysbus_swim_realize(DeviceState *dev, Error **errp) { - SWIM *sys = SWIM(dev); + Swim *sys = SWIM(dev); SWIMCtrl *swimctrl = &sys->ctrl; qbus_create_inplace(&swimctrl->bus, sizeof(SWIMBus), TYPE_SWIM_BUS, dev, @@ -457,7 +460,7 @@ static const VMStateDescription vmstate_sysbus_swim = { .name = "SWIM", .version_id = 1, .fields = (VMStateField[]) { - VMSTATE_STRUCT(ctrl, SWIM, 0, vmstate_swim, SWIMCtrl), + VMSTATE_STRUCT(ctrl, Swim, 0, vmstate_swim, SWIMCtrl), VMSTATE_END_OF_LIST() } }; @@ -474,7 +477,7 @@ static void sysbus_swim_class_init(ObjectClass *oc, void *data) static const TypeInfo sysbus_swim_info = { .name = TYPE_SWIM, .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SWIM), + .instance_size = sizeof(Swim), .instance_init = sysbus_swim_init, .class_init = sysbus_swim_class_init, }; diff --git a/hw/block/trace-events b/hw/block/trace-events index aca54bda1423cb2b1be1a63315064be3dbd83943..c1537e3ac0b0f6beed67c47040d4326786fdf4c2 100644 --- a/hw/block/trace-events +++ b/hw/block/trace-events @@ -4,8 +4,8 @@ fdc_ioport_read(uint8_t reg, uint8_t value) "read reg 0x%02x val 0x%02x" fdc_ioport_write(uint8_t reg, uint8_t value) "write reg 0x%02x val 0x%02x" -# pflash_cfi02.c # pflash_cfi01.c +# pflash_cfi02.c pflash_reset(void) "reset" pflash_timer_expired(uint8_t cmd) "command 0x%02x done" pflash_io_read(uint64_t offset, unsigned size, uint32_t value, uint8_t cmd, uint8_t wcycle) "offset:0x%04"PRIx64" size:%u value:0x%04x cmd:0x%02x wcycle:%u" @@ -29,100 +29,135 @@ hd_geometry_guess(void *blk, uint32_t cyls, uint32_t heads, uint32_t secs, int t # nvme.c # nvme traces for successful events -nvme_irq_msix(uint32_t vector) "raising MSI-X IRQ vector %u" -nvme_irq_pin(void) "pulsing IRQ pin" -nvme_irq_masked(void) "IRQ is masked" -nvme_dma_read(uint64_t prp1, uint64_t prp2) "DMA read, prp1=0x%"PRIx64" prp2=0x%"PRIx64"" -nvme_rw(const char *verb, uint32_t blk_count, uint64_t byte_count, uint64_t lba) "%s %"PRIu32" blocks (%"PRIu64" bytes) from LBA %"PRIu64"" -nvme_create_sq(uint64_t addr, uint16_t sqid, uint16_t cqid, uint16_t qsize, uint16_t qflags) "create submission queue, addr=0x%"PRIx64", sqid=%"PRIu16", cqid=%"PRIu16", qsize=%"PRIu16", qflags=%"PRIu16"" -nvme_create_cq(uint64_t addr, uint16_t cqid, uint16_t vector, uint16_t size, uint16_t qflags, int ien) "create completion queue, addr=0x%"PRIx64", cqid=%"PRIu16", vector=%"PRIu16", qsize=%"PRIu16", qflags=%"PRIu16", ien=%d" -nvme_del_sq(uint16_t qid) "deleting submission queue sqid=%"PRIu16"" -nvme_del_cq(uint16_t cqid) "deleted completion queue, cqid=%"PRIu16"" -nvme_identify_ctrl(void) "identify controller" -nvme_identify_ns(uint16_t ns) "identify namespace, nsid=%"PRIu16"" -nvme_identify_nslist(uint16_t ns) "identify namespace list, nsid=%"PRIu16"" -nvme_getfeat_vwcache(const char* result) "get feature volatile write cache, result=%s" -nvme_getfeat_numq(int result) "get feature number of queues, result=%d" -nvme_setfeat_numq(int reqcq, int reqsq, int gotcq, int gotsq) "requested cq_count=%d sq_count=%d, responding with cq_count=%d sq_count=%d" -nvme_setfeat_timestamp(uint64_t ts) "set feature timestamp = 0x%"PRIx64"" -nvme_getfeat_timestamp(uint64_t ts) "get feature timestamp = 0x%"PRIx64"" -nvme_mmio_intm_set(uint64_t data, uint64_t new_mask) "wrote MMIO, interrupt mask set, data=0x%"PRIx64", new_mask=0x%"PRIx64"" -nvme_mmio_intm_clr(uint64_t data, uint64_t new_mask) "wrote MMIO, interrupt mask clr, data=0x%"PRIx64", new_mask=0x%"PRIx64"" -nvme_mmio_cfg(uint64_t data) "wrote MMIO, config controller config=0x%"PRIx64"" -nvme_mmio_aqattr(uint64_t data) "wrote MMIO, admin queue attributes=0x%"PRIx64"" -nvme_mmio_asqaddr(uint64_t data) "wrote MMIO, admin submission queue address=0x%"PRIx64"" -nvme_mmio_acqaddr(uint64_t data) "wrote MMIO, admin completion queue address=0x%"PRIx64"" -nvme_mmio_asqaddr_hi(uint64_t data, uint64_t new_addr) "wrote MMIO, admin submission queue high half=0x%"PRIx64", new_address=0x%"PRIx64"" -nvme_mmio_acqaddr_hi(uint64_t data, uint64_t new_addr) "wrote MMIO, admin completion queue high half=0x%"PRIx64", new_address=0x%"PRIx64"" -nvme_mmio_start_success(void) "setting controller enable bit succeeded" -nvme_mmio_stopped(void) "cleared controller enable bit" -nvme_mmio_shutdown_set(void) "shutdown bit set" -nvme_mmio_shutdown_cleared(void) "shutdown bit cleared" +pci_nvme_register_namespace(uint32_t nsid) "nsid %"PRIu32"" +pci_nvme_irq_msix(uint32_t vector) "raising MSI-X IRQ vector %u" +pci_nvme_irq_pin(void) "pulsing IRQ pin" +pci_nvme_irq_masked(void) "IRQ is masked" +pci_nvme_dma_read(uint64_t prp1, uint64_t prp2) "DMA read, prp1=0x%"PRIx64" prp2=0x%"PRIx64"" +pci_nvme_map_addr(uint64_t addr, uint64_t len) "addr 0x%"PRIx64" len %"PRIu64"" +pci_nvme_map_addr_cmb(uint64_t addr, uint64_t len) "addr 0x%"PRIx64" len %"PRIu64"" +pci_nvme_map_prp(uint64_t trans_len, uint32_t len, uint64_t prp1, uint64_t prp2, int num_prps) "trans_len %"PRIu64" len %"PRIu32" prp1 0x%"PRIx64" prp2 0x%"PRIx64" num_prps %d" +pci_nvme_map_sgl(uint16_t cid, uint8_t typ, uint64_t len) "cid %"PRIu16" type 0x%"PRIx8" len %"PRIu64"" +pci_nvme_io_cmd(uint16_t cid, uint32_t nsid, uint16_t sqid, uint8_t opcode, const char *opname) "cid %"PRIu16" nsid %"PRIu32" sqid %"PRIu16" opc 0x%"PRIx8" opname '%s'" +pci_nvme_admin_cmd(uint16_t cid, uint16_t sqid, uint8_t opcode, const char *opname) "cid %"PRIu16" sqid %"PRIu16" opc 0x%"PRIx8" opname '%s'" +pci_nvme_rw(uint16_t cid, const char *verb, uint32_t nsid, uint32_t nlb, uint64_t count, uint64_t lba) "cid %"PRIu16" opname '%s' nsid %"PRIu32" nlb %"PRIu32" count %"PRIu64" lba 0x%"PRIx64"" +pci_nvme_rw_cb(uint16_t cid, const char *blkname) "cid %"PRIu16" blk '%s'" +pci_nvme_write_zeroes(uint16_t cid, uint32_t nsid, uint64_t slba, uint32_t nlb) "cid %"PRIu16" nsid %"PRIu32" slba %"PRIu64" nlb %"PRIu32"" +pci_nvme_create_sq(uint64_t addr, uint16_t sqid, uint16_t cqid, uint16_t qsize, uint16_t qflags) "create submission queue, addr=0x%"PRIx64", sqid=%"PRIu16", cqid=%"PRIu16", qsize=%"PRIu16", qflags=%"PRIu16"" +pci_nvme_create_cq(uint64_t addr, uint16_t cqid, uint16_t vector, uint16_t size, uint16_t qflags, int ien) "create completion queue, addr=0x%"PRIx64", cqid=%"PRIu16", vector=%"PRIu16", qsize=%"PRIu16", qflags=%"PRIu16", ien=%d" +pci_nvme_del_sq(uint16_t qid) "deleting submission queue sqid=%"PRIu16"" +pci_nvme_del_cq(uint16_t cqid) "deleted completion queue, cqid=%"PRIu16"" +pci_nvme_identify_ctrl(void) "identify controller" +pci_nvme_identify_ns(uint32_t ns) "nsid %"PRIu32"" +pci_nvme_identify_nslist(uint32_t ns) "nsid %"PRIu32"" +pci_nvme_identify_ns_descr_list(uint32_t ns) "nsid %"PRIu32"" +pci_nvme_get_log(uint16_t cid, uint8_t lid, uint8_t lsp, uint8_t rae, uint32_t len, uint64_t off) "cid %"PRIu16" lid 0x%"PRIx8" lsp 0x%"PRIx8" rae 0x%"PRIx8" len %"PRIu32" off %"PRIu64"" +pci_nvme_getfeat(uint16_t cid, uint32_t nsid, uint8_t fid, uint8_t sel, uint32_t cdw11) "cid %"PRIu16" nsid 0x%"PRIx32" fid 0x%"PRIx8" sel 0x%"PRIx8" cdw11 0x%"PRIx32"" +pci_nvme_setfeat(uint16_t cid, uint32_t nsid, uint8_t fid, uint8_t save, uint32_t cdw11) "cid %"PRIu16" nsid 0x%"PRIx32" fid 0x%"PRIx8" save 0x%"PRIx8" cdw11 0x%"PRIx32"" +pci_nvme_getfeat_vwcache(const char* result) "get feature volatile write cache, result=%s" +pci_nvme_getfeat_numq(int result) "get feature number of queues, result=%d" +pci_nvme_setfeat_numq(int reqcq, int reqsq, int gotcq, int gotsq) "requested cq_count=%d sq_count=%d, responding with cq_count=%d sq_count=%d" +pci_nvme_setfeat_timestamp(uint64_t ts) "set feature timestamp = 0x%"PRIx64"" +pci_nvme_getfeat_timestamp(uint64_t ts) "get feature timestamp = 0x%"PRIx64"" +pci_nvme_process_aers(int queued) "queued %d" +pci_nvme_aer(uint16_t cid) "cid %"PRIu16"" +pci_nvme_aer_aerl_exceeded(void) "aerl exceeded" +pci_nvme_aer_masked(uint8_t type, uint8_t mask) "type 0x%"PRIx8" mask 0x%"PRIx8"" +pci_nvme_aer_post_cqe(uint8_t typ, uint8_t info, uint8_t log_page) "type 0x%"PRIx8" info 0x%"PRIx8" lid 0x%"PRIx8"" +pci_nvme_enqueue_event(uint8_t typ, uint8_t info, uint8_t log_page) "type 0x%"PRIx8" info 0x%"PRIx8" lid 0x%"PRIx8"" +pci_nvme_enqueue_event_noqueue(int queued) "queued %d" +pci_nvme_enqueue_event_masked(uint8_t typ) "type 0x%"PRIx8"" +pci_nvme_no_outstanding_aers(void) "ignoring event; no outstanding AERs" +pci_nvme_enqueue_req_completion(uint16_t cid, uint16_t cqid, uint16_t status) "cid %"PRIu16" cqid %"PRIu16" status 0x%"PRIx16"" +pci_nvme_mmio_read(uint64_t addr) "addr 0x%"PRIx64"" +pci_nvme_mmio_write(uint64_t addr, uint64_t data) "addr 0x%"PRIx64" data 0x%"PRIx64"" +pci_nvme_mmio_doorbell_cq(uint16_t cqid, uint16_t new_head) "cqid %"PRIu16" new_head %"PRIu16"" +pci_nvme_mmio_doorbell_sq(uint16_t sqid, uint16_t new_tail) "sqid %"PRIu16" new_tail %"PRIu16"" +pci_nvme_mmio_intm_set(uint64_t data, uint64_t new_mask) "wrote MMIO, interrupt mask set, data=0x%"PRIx64", new_mask=0x%"PRIx64"" +pci_nvme_mmio_intm_clr(uint64_t data, uint64_t new_mask) "wrote MMIO, interrupt mask clr, data=0x%"PRIx64", new_mask=0x%"PRIx64"" +pci_nvme_mmio_cfg(uint64_t data) "wrote MMIO, config controller config=0x%"PRIx64"" +pci_nvme_mmio_aqattr(uint64_t data) "wrote MMIO, admin queue attributes=0x%"PRIx64"" +pci_nvme_mmio_asqaddr(uint64_t data) "wrote MMIO, admin submission queue address=0x%"PRIx64"" +pci_nvme_mmio_acqaddr(uint64_t data) "wrote MMIO, admin completion queue address=0x%"PRIx64"" +pci_nvme_mmio_asqaddr_hi(uint64_t data, uint64_t new_addr) "wrote MMIO, admin submission queue high half=0x%"PRIx64", new_address=0x%"PRIx64"" +pci_nvme_mmio_acqaddr_hi(uint64_t data, uint64_t new_addr) "wrote MMIO, admin completion queue high half=0x%"PRIx64", new_address=0x%"PRIx64"" +pci_nvme_mmio_start_success(void) "setting controller enable bit succeeded" +pci_nvme_mmio_stopped(void) "cleared controller enable bit" +pci_nvme_mmio_shutdown_set(void) "shutdown bit set" +pci_nvme_mmio_shutdown_cleared(void) "shutdown bit cleared" # nvme traces for error conditions -nvme_err_invalid_dma(void) "PRP/SGL is too small for transfer size" -nvme_err_invalid_prplist_ent(uint64_t prplist) "PRP list entry is null or not page aligned: 0x%"PRIx64"" -nvme_err_invalid_prp2_align(uint64_t prp2) "PRP2 is not page aligned: 0x%"PRIx64"" -nvme_err_invalid_prp2_missing(void) "PRP2 is null and more data to be transferred" -nvme_err_invalid_prp(void) "invalid PRP" -nvme_err_invalid_ns(uint32_t ns, uint32_t limit) "invalid namespace %u not within 1-%u" -nvme_err_invalid_opc(uint8_t opc) "invalid opcode 0x%"PRIx8"" -nvme_err_invalid_admin_opc(uint8_t opc) "invalid admin opcode 0x%"PRIx8"" -nvme_err_invalid_lba_range(uint64_t start, uint64_t len, uint64_t limit) "Invalid LBA start=%"PRIu64" len=%"PRIu64" limit=%"PRIu64"" -nvme_err_invalid_del_sq(uint16_t qid) "invalid submission queue deletion, sid=%"PRIu16"" -nvme_err_invalid_create_sq_cqid(uint16_t cqid) "failed creating submission queue, invalid cqid=%"PRIu16"" -nvme_err_invalid_create_sq_sqid(uint16_t sqid) "failed creating submission queue, invalid sqid=%"PRIu16"" -nvme_err_invalid_create_sq_size(uint16_t qsize) "failed creating submission queue, invalid qsize=%"PRIu16"" -nvme_err_invalid_create_sq_addr(uint64_t addr) "failed creating submission queue, addr=0x%"PRIx64"" -nvme_err_invalid_create_sq_qflags(uint16_t qflags) "failed creating submission queue, qflags=%"PRIu16"" -nvme_err_invalid_del_cq_cqid(uint16_t cqid) "failed deleting completion queue, cqid=%"PRIu16"" -nvme_err_invalid_del_cq_notempty(uint16_t cqid) "failed deleting completion queue, it is not empty, cqid=%"PRIu16"" -nvme_err_invalid_create_cq_cqid(uint16_t cqid) "failed creating completion queue, cqid=%"PRIu16"" -nvme_err_invalid_create_cq_size(uint16_t size) "failed creating completion queue, size=%"PRIu16"" -nvme_err_invalid_create_cq_addr(uint64_t addr) "failed creating completion queue, addr=0x%"PRIx64"" -nvme_err_invalid_create_cq_vector(uint16_t vector) "failed creating completion queue, vector=%"PRIu16"" -nvme_err_invalid_create_cq_qflags(uint16_t qflags) "failed creating completion queue, qflags=%"PRIu16"" -nvme_err_invalid_identify_cns(uint16_t cns) "identify, invalid cns=0x%"PRIx16"" -nvme_err_invalid_getfeat(int dw10) "invalid get features, dw10=0x%"PRIx32"" -nvme_err_invalid_setfeat(uint32_t dw10) "invalid set features, dw10=0x%"PRIx32"" -nvme_err_startfail_cq(void) "nvme_start_ctrl failed because there are non-admin completion queues" -nvme_err_startfail_sq(void) "nvme_start_ctrl failed because there are non-admin submission queues" -nvme_err_startfail_nbarasq(void) "nvme_start_ctrl failed because the admin submission queue address is null" -nvme_err_startfail_nbaracq(void) "nvme_start_ctrl failed because the admin completion queue address is null" -nvme_err_startfail_asq_misaligned(uint64_t addr) "nvme_start_ctrl failed because the admin submission queue address is misaligned: 0x%"PRIx64"" -nvme_err_startfail_acq_misaligned(uint64_t addr) "nvme_start_ctrl failed because the admin completion queue address is misaligned: 0x%"PRIx64"" -nvme_err_startfail_page_too_small(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the page size is too small: log2size=%u, min=%u" -nvme_err_startfail_page_too_large(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the page size is too large: log2size=%u, max=%u" -nvme_err_startfail_cqent_too_small(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the completion queue entry size is too small: log2size=%u, min=%u" -nvme_err_startfail_cqent_too_large(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the completion queue entry size is too large: log2size=%u, max=%u" -nvme_err_startfail_sqent_too_small(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the submission queue entry size is too small: log2size=%u, min=%u" -nvme_err_startfail_sqent_too_large(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the submission queue entry size is too large: log2size=%u, max=%u" -nvme_err_startfail_asqent_sz_zero(void) "nvme_start_ctrl failed because the admin submission queue size is zero" -nvme_err_startfail_acqent_sz_zero(void) "nvme_start_ctrl failed because the admin completion queue size is zero" -nvme_err_startfail(void) "setting controller enable bit failed" +pci_nvme_err_mdts(uint16_t cid, size_t len) "cid %"PRIu16" len %zu" +pci_nvme_err_req_status(uint16_t cid, uint32_t nsid, uint16_t status, uint8_t opc) "cid %"PRIu16" nsid %"PRIu32" status 0x%"PRIx16" opc 0x%"PRIx8"" +pci_nvme_err_addr_read(uint64_t addr) "addr 0x%"PRIx64"" +pci_nvme_err_addr_write(uint64_t addr) "addr 0x%"PRIx64"" +pci_nvme_err_cfs(void) "controller fatal status" +pci_nvme_err_aio(uint16_t cid, const char *errname, uint16_t status) "cid %"PRIu16" err '%s' status 0x%"PRIx16"" +pci_nvme_err_invalid_sgld(uint16_t cid, uint8_t typ) "cid %"PRIu16" type 0x%"PRIx8"" +pci_nvme_err_invalid_num_sgld(uint16_t cid, uint8_t typ) "cid %"PRIu16" type 0x%"PRIx8"" +pci_nvme_err_invalid_sgl_excess_length(uint16_t cid) "cid %"PRIu16"" +pci_nvme_err_invalid_dma(void) "PRP/SGL is too small for transfer size" +pci_nvme_err_invalid_prplist_ent(uint64_t prplist) "PRP list entry is not page aligned: 0x%"PRIx64"" +pci_nvme_err_invalid_prp2_align(uint64_t prp2) "PRP2 is not page aligned: 0x%"PRIx64"" +pci_nvme_err_invalid_opc(uint8_t opc) "invalid opcode 0x%"PRIx8"" +pci_nvme_err_invalid_admin_opc(uint8_t opc) "invalid admin opcode 0x%"PRIx8"" +pci_nvme_err_invalid_lba_range(uint64_t start, uint64_t len, uint64_t limit) "Invalid LBA start=%"PRIu64" len=%"PRIu64" limit=%"PRIu64"" +pci_nvme_err_invalid_del_sq(uint16_t qid) "invalid submission queue deletion, sid=%"PRIu16"" +pci_nvme_err_invalid_create_sq_cqid(uint16_t cqid) "failed creating submission queue, invalid cqid=%"PRIu16"" +pci_nvme_err_invalid_create_sq_sqid(uint16_t sqid) "failed creating submission queue, invalid sqid=%"PRIu16"" +pci_nvme_err_invalid_create_sq_size(uint16_t qsize) "failed creating submission queue, invalid qsize=%"PRIu16"" +pci_nvme_err_invalid_create_sq_addr(uint64_t addr) "failed creating submission queue, addr=0x%"PRIx64"" +pci_nvme_err_invalid_create_sq_qflags(uint16_t qflags) "failed creating submission queue, qflags=%"PRIu16"" +pci_nvme_err_invalid_del_cq_cqid(uint16_t cqid) "failed deleting completion queue, cqid=%"PRIu16"" +pci_nvme_err_invalid_del_cq_notempty(uint16_t cqid) "failed deleting completion queue, it is not empty, cqid=%"PRIu16"" +pci_nvme_err_invalid_create_cq_cqid(uint16_t cqid) "failed creating completion queue, cqid=%"PRIu16"" +pci_nvme_err_invalid_create_cq_size(uint16_t size) "failed creating completion queue, size=%"PRIu16"" +pci_nvme_err_invalid_create_cq_addr(uint64_t addr) "failed creating completion queue, addr=0x%"PRIx64"" +pci_nvme_err_invalid_create_cq_vector(uint16_t vector) "failed creating completion queue, vector=%"PRIu16"" +pci_nvme_err_invalid_create_cq_qflags(uint16_t qflags) "failed creating completion queue, qflags=%"PRIu16"" +pci_nvme_err_invalid_identify_cns(uint16_t cns) "identify, invalid cns=0x%"PRIx16"" +pci_nvme_err_invalid_getfeat(int dw10) "invalid get features, dw10=0x%"PRIx32"" +pci_nvme_err_invalid_setfeat(uint32_t dw10) "invalid set features, dw10=0x%"PRIx32"" +pci_nvme_err_invalid_log_page(uint16_t cid, uint16_t lid) "cid %"PRIu16" lid 0x%"PRIx16"" +pci_nvme_err_startfail_cq(void) "nvme_start_ctrl failed because there are non-admin completion queues" +pci_nvme_err_startfail_sq(void) "nvme_start_ctrl failed because there are non-admin submission queues" +pci_nvme_err_startfail_nbarasq(void) "nvme_start_ctrl failed because the admin submission queue address is null" +pci_nvme_err_startfail_nbaracq(void) "nvme_start_ctrl failed because the admin completion queue address is null" +pci_nvme_err_startfail_asq_misaligned(uint64_t addr) "nvme_start_ctrl failed because the admin submission queue address is misaligned: 0x%"PRIx64"" +pci_nvme_err_startfail_acq_misaligned(uint64_t addr) "nvme_start_ctrl failed because the admin completion queue address is misaligned: 0x%"PRIx64"" +pci_nvme_err_startfail_page_too_small(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the page size is too small: log2size=%u, min=%u" +pci_nvme_err_startfail_page_too_large(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the page size is too large: log2size=%u, max=%u" +pci_nvme_err_startfail_cqent_too_small(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the completion queue entry size is too small: log2size=%u, min=%u" +pci_nvme_err_startfail_cqent_too_large(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the completion queue entry size is too large: log2size=%u, max=%u" +pci_nvme_err_startfail_sqent_too_small(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the submission queue entry size is too small: log2size=%u, min=%u" +pci_nvme_err_startfail_sqent_too_large(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the submission queue entry size is too large: log2size=%u, max=%u" +pci_nvme_err_startfail_css(uint8_t css) "nvme_start_ctrl failed because invalid command set selected:%u" +pci_nvme_err_startfail_asqent_sz_zero(void) "nvme_start_ctrl failed because the admin submission queue size is zero" +pci_nvme_err_startfail_acqent_sz_zero(void) "nvme_start_ctrl failed because the admin completion queue size is zero" +pci_nvme_err_startfail(void) "setting controller enable bit failed" # Traces for undefined behavior -nvme_ub_mmiowr_misaligned32(uint64_t offset) "MMIO write not 32-bit aligned, offset=0x%"PRIx64"" -nvme_ub_mmiowr_toosmall(uint64_t offset, unsigned size) "MMIO write smaller than 32 bits, offset=0x%"PRIx64", size=%u" -nvme_ub_mmiowr_intmask_with_msix(void) "undefined access to interrupt mask set when MSI-X is enabled" -nvme_ub_mmiowr_ro_csts(void) "attempted to set a read only bit of controller status" -nvme_ub_mmiowr_ssreset_w1c_unsupported(void) "attempted to W1C CSTS.NSSRO but CAP.NSSRS is zero (not supported)" -nvme_ub_mmiowr_ssreset_unsupported(void) "attempted NVM subsystem reset but CAP.NSSRS is zero (not supported)" -nvme_ub_mmiowr_cmbloc_reserved(void) "invalid write to reserved CMBLOC when CMBSZ is zero, ignored" -nvme_ub_mmiowr_cmbsz_readonly(void) "invalid write to read only CMBSZ, ignored" -nvme_ub_mmiowr_pmrcap_readonly(void) "invalid write to read only PMRCAP, ignored" -nvme_ub_mmiowr_pmrsts_readonly(void) "invalid write to read only PMRSTS, ignored" -nvme_ub_mmiowr_pmrebs_readonly(void) "invalid write to read only PMREBS, ignored" -nvme_ub_mmiowr_pmrswtp_readonly(void) "invalid write to read only PMRSWTP, ignored" -nvme_ub_mmiowr_invalid(uint64_t offset, uint64_t data) "invalid MMIO write, offset=0x%"PRIx64", data=0x%"PRIx64"" -nvme_ub_mmiord_misaligned32(uint64_t offset) "MMIO read not 32-bit aligned, offset=0x%"PRIx64"" -nvme_ub_mmiord_toosmall(uint64_t offset) "MMIO read smaller than 32-bits, offset=0x%"PRIx64"" -nvme_ub_mmiord_invalid_ofs(uint64_t offset) "MMIO read beyond last register, offset=0x%"PRIx64", returning 0" -nvme_ub_db_wr_misaligned(uint64_t offset) "doorbell write not 32-bit aligned, offset=0x%"PRIx64", ignoring" -nvme_ub_db_wr_invalid_cq(uint32_t qid) "completion queue doorbell write for nonexistent queue, cqid=%"PRIu32", ignoring" -nvme_ub_db_wr_invalid_cqhead(uint32_t qid, uint16_t new_head) "completion queue doorbell write value beyond queue size, cqid=%"PRIu32", new_head=%"PRIu16", ignoring" -nvme_ub_db_wr_invalid_sq(uint32_t qid) "submission queue doorbell write for nonexistent queue, sqid=%"PRIu32", ignoring" -nvme_ub_db_wr_invalid_sqtail(uint32_t qid, uint16_t new_tail) "submission queue doorbell write value beyond queue size, sqid=%"PRIu32", new_head=%"PRIu16", ignoring" +pci_nvme_ub_mmiowr_misaligned32(uint64_t offset) "MMIO write not 32-bit aligned, offset=0x%"PRIx64"" +pci_nvme_ub_mmiowr_toosmall(uint64_t offset, unsigned size) "MMIO write smaller than 32 bits, offset=0x%"PRIx64", size=%u" +pci_nvme_ub_mmiowr_intmask_with_msix(void) "undefined access to interrupt mask set when MSI-X is enabled" +pci_nvme_ub_mmiowr_ro_csts(void) "attempted to set a read only bit of controller status" +pci_nvme_ub_mmiowr_ssreset_w1c_unsupported(void) "attempted to W1C CSTS.NSSRO but CAP.NSSRS is zero (not supported)" +pci_nvme_ub_mmiowr_ssreset_unsupported(void) "attempted NVM subsystem reset but CAP.NSSRS is zero (not supported)" +pci_nvme_ub_mmiowr_cmbloc_reserved(void) "invalid write to reserved CMBLOC when CMBSZ is zero, ignored" +pci_nvme_ub_mmiowr_cmbsz_readonly(void) "invalid write to read only CMBSZ, ignored" +pci_nvme_ub_mmiowr_pmrcap_readonly(void) "invalid write to read only PMRCAP, ignored" +pci_nvme_ub_mmiowr_pmrsts_readonly(void) "invalid write to read only PMRSTS, ignored" +pci_nvme_ub_mmiowr_pmrebs_readonly(void) "invalid write to read only PMREBS, ignored" +pci_nvme_ub_mmiowr_pmrswtp_readonly(void) "invalid write to read only PMRSWTP, ignored" +pci_nvme_ub_mmiowr_invalid(uint64_t offset, uint64_t data) "invalid MMIO write, offset=0x%"PRIx64", data=0x%"PRIx64"" +pci_nvme_ub_mmiord_misaligned32(uint64_t offset) "MMIO read not 32-bit aligned, offset=0x%"PRIx64"" +pci_nvme_ub_mmiord_toosmall(uint64_t offset) "MMIO read smaller than 32-bits, offset=0x%"PRIx64"" +pci_nvme_ub_mmiord_invalid_ofs(uint64_t offset) "MMIO read beyond last register, offset=0x%"PRIx64", returning 0" +pci_nvme_ub_db_wr_misaligned(uint64_t offset) "doorbell write not 32-bit aligned, offset=0x%"PRIx64", ignoring" +pci_nvme_ub_db_wr_invalid_cq(uint32_t qid) "completion queue doorbell write for nonexistent queue, cqid=%"PRIu32", ignoring" +pci_nvme_ub_db_wr_invalid_cqhead(uint32_t qid, uint16_t new_head) "completion queue doorbell write value beyond queue size, cqid=%"PRIu32", new_head=%"PRIu16", ignoring" +pci_nvme_ub_db_wr_invalid_sq(uint32_t qid) "submission queue doorbell write for nonexistent queue, sqid=%"PRIu32", ignoring" +pci_nvme_ub_db_wr_invalid_sqtail(uint32_t qid, uint16_t new_tail) "submission queue doorbell write value beyond queue size, sqid=%"PRIu32", new_head=%"PRIu16", ignoring" # xen-block.c xen_block_realize(const char *type, uint32_t disk, uint32_t partition) "%s d%up%u" diff --git a/hw/block/trace.h b/hw/block/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..cde210ae692e436b65faf19256c1ace56a5ebde5 --- /dev/null +++ b/hw/block/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_block.h" diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index 9d8c0b3909c51da072a69e52db5da9274a01eb24..2dd3d93ca02f077b9fe8aaaa4d14d97a1f0b33bd 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -20,7 +20,6 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/cutils.h" -#include "qom/object.h" #include "hw/qdev-core.h" #include "hw/qdev-properties.h" #include "hw/virtio/vhost.h" @@ -132,6 +131,12 @@ static int vhost_user_blk_start(VirtIODevice *vdev) s->dev.acked_features = vdev->guest_features; + ret = vhost_dev_prepare_inflight(&s->dev, vdev); + if (ret < 0) { + error_report("Error set inflight format: %d", -ret); + goto err_guest_notifiers; + } + if (!s->inflight->addr) { ret = vhost_dev_get_inflight(&s->dev, s->queue_size, s->inflight); if (ret < 0) { @@ -151,6 +156,7 @@ static int vhost_user_blk_start(VirtIODevice *vdev) error_report("Error starting vhost: %d", -ret); goto err_guest_notifiers; } + s->started_vu = true; /* guest_notifier_mask/pending not used yet, so just unmask * everything here. virtio-pci will do the right thing by @@ -176,6 +182,11 @@ static void vhost_user_blk_stop(VirtIODevice *vdev) VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); int ret; + if (!s->started_vu) { + return; + } + s->started_vu = false; + if (!k->set_guest_notifiers) { return; } @@ -342,13 +353,24 @@ static void vhost_user_blk_disconnect(DeviceState *dev) } s->connected = false; - if (s->dev.started) { - vhost_user_blk_stop(vdev); - } + vhost_user_blk_stop(vdev); vhost_dev_cleanup(&s->dev); } +static void vhost_user_blk_event(void *opaque, QEMUChrEvent event); + +static void vhost_user_blk_chr_closed_bh(void *opaque) +{ + DeviceState *dev = opaque; + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VHostUserBlk *s = VHOST_USER_BLK(vdev); + + vhost_user_blk_disconnect(dev); + qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, vhost_user_blk_event, + NULL, opaque, NULL, true); +} + static void vhost_user_blk_event(void *opaque, QEMUChrEvent event) { DeviceState *dev = opaque; @@ -363,7 +385,39 @@ static void vhost_user_blk_event(void *opaque, QEMUChrEvent event) } break; case CHR_EVENT_CLOSED: - vhost_user_blk_disconnect(dev); + /* + * A close event may happen during a read/write, but vhost + * code assumes the vhost_dev remains setup, so delay the + * stop & clear. There are two possible paths to hit this + * disconnect event: + * 1. When VM is in the RUN_STATE_PRELAUNCH state. The + * vhost_user_blk_device_realize() is a caller. + * 2. In tha main loop phase after VM start. + * + * For p2 the disconnect event will be delayed. We can't + * do the same for p1, because we are not running the loop + * at this moment. So just skip this step and perform + * disconnect in the caller function. + * + * TODO: maybe it is a good idea to make the same fix + * for other vhost-user devices. + */ + if (runstate_is_running()) { + AioContext *ctx = qemu_get_current_aio_context(); + + qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, NULL, NULL, + NULL, NULL, false); + aio_bh_schedule_oneshot(ctx, vhost_user_blk_chr_closed_bh, opaque); + } + + /* + * Move vhost device to the stopped state. The vhost-user device + * will be clean up and disconnected in BH. This can be useful in + * the vhost migration code. If disconnect was caught there is an + * option for the general vhost code to get the dev state without + * knowing its type (in this case vhost-user). + */ + s->dev.started = false; break; case CHR_EVENT_BREAK: case CHR_EVENT_MUX_IN: @@ -385,6 +439,9 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp) return; } + if (s->num_queues == VHOST_USER_BLK_AUTO_NUM_QUEUES) { + s->num_queues = 1; + } if (!s->num_queues || s->num_queues > VIRTIO_QUEUE_MAX) { error_setg(errp, "vhost-user-blk: invalid number of IO queues"); return; @@ -496,7 +553,8 @@ static const VMStateDescription vmstate_vhost_user_blk = { static Property vhost_user_blk_properties[] = { DEFINE_PROP_CHR("chardev", VHostUserBlk, chardev), - DEFINE_PROP_UINT16("num-queues", VHostUserBlk, num_queues, 1), + DEFINE_PROP_UINT16("num-queues", VHostUserBlk, num_queues, + VHOST_USER_BLK_AUTO_NUM_QUEUES), DEFINE_PROP_UINT32("queue-size", VHostUserBlk, queue_size, 128), DEFINE_PROP_BIT("config-wce", VHostUserBlk, config_wce, 0, true), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index f5f6fc925e8bfc6501ccfec209de481e5efc7ef8..bac2d6fa2b283854b21f225bea1c144ed531e99e 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -80,6 +80,8 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status) trace_virtio_blk_req_complete(vdev, req, status); stb_p(&req->in->status, status); + iov_discard_undo(&req->inhdr_undo); + iov_discard_undo(&req->outhdr_undo); virtqueue_push(req->vq, &req->elem, req->in_len); if (s->dataplane_started && !s->dataplane_disabled) { virtio_blk_data_plane_notify(s->dataplane, req->vq); @@ -632,10 +634,12 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb) return -1; } - iov_discard_front(&out_iov, &out_num, sizeof(req->out)); + iov_discard_front_undoable(&out_iov, &out_num, sizeof(req->out), + &req->outhdr_undo); if (in_iov[in_num - 1].iov_len < sizeof(struct virtio_blk_inhdr)) { virtio_error(vdev, "virtio-blk request inhdr too short"); + iov_discard_undo(&req->outhdr_undo); return -1; } @@ -644,7 +648,8 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb) req->in = (void *)in_iov[in_num - 1].iov_base + in_iov[in_num - 1].iov_len - sizeof(struct virtio_blk_inhdr); - iov_discard_back(in_iov, &in_num, sizeof(struct virtio_blk_inhdr)); + iov_discard_back_undoable(in_iov, &in_num, sizeof(struct virtio_blk_inhdr), + &req->inhdr_undo); type = virtio_ldl_p(vdev, &req->out.type); @@ -739,6 +744,8 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb) if (unlikely(iov_to_buf(out_iov, out_num, 0, &dwz_hdr, sizeof(dwz_hdr)) != sizeof(dwz_hdr))) { + iov_discard_undo(&req->inhdr_undo); + iov_discard_undo(&req->outhdr_undo); virtio_error(vdev, "virtio-blk discard/write_zeroes header" " too short"); return -1; @@ -819,15 +826,11 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) virtio_blk_handle_output_do(s, vq); } -static void virtio_blk_dma_restart_bh(void *opaque) +void virtio_blk_process_queued_requests(VirtIOBlock *s, bool is_bh) { - VirtIOBlock *s = opaque; VirtIOBlockReq *req = s->rq; MultiReqBuffer mrb = {}; - qemu_bh_delete(s->bh); - s->bh = NULL; - s->rq = NULL; aio_context_acquire(blk_get_aio_context(s->conf.conf.blk)); @@ -851,22 +854,38 @@ static void virtio_blk_dma_restart_bh(void *opaque) if (mrb.num_reqs) { virtio_blk_submit_multireq(s->blk, &mrb); } - blk_dec_in_flight(s->conf.conf.blk); + if (is_bh) { + blk_dec_in_flight(s->conf.conf.blk); + } aio_context_release(blk_get_aio_context(s->conf.conf.blk)); } +static void virtio_blk_dma_restart_bh(void *opaque) +{ + VirtIOBlock *s = opaque; + + qemu_bh_delete(s->bh); + s->bh = NULL; + + virtio_blk_process_queued_requests(s, true); +} + static void virtio_blk_dma_restart_cb(void *opaque, int running, RunState state) { VirtIOBlock *s = opaque; + BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s))); + VirtioBusState *bus = VIRTIO_BUS(qbus); if (!running) { return; } - if (!s->bh) { - /* FIXME The data plane is not started yet, so these requests are - * processed in the main thread. */ + /* + * If ioeventfd is enabled, don't schedule the BH here as queued + * requests will be processed while starting the data plane. + */ + if (!s->bh && !virtio_bus_ioeventfd_enabled(bus)) { s->bh = aio_bh_new(blk_get_aio_context(s->conf.conf.blk), virtio_blk_dma_restart_bh, s); blk_inc_in_flight(s->conf.conf.blk); @@ -918,7 +937,7 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config) virtio_stw_p(vdev, &blkcfg.geometry.cylinders, conf->cyls); virtio_stl_p(vdev, &blkcfg.blk_size, blk_size); virtio_stw_p(vdev, &blkcfg.min_io_size, conf->min_io_size / blk_size); - virtio_stw_p(vdev, &blkcfg.opt_io_size, conf->opt_io_size / blk_size); + virtio_stl_p(vdev, &blkcfg.opt_io_size, conf->opt_io_size / blk_size); blkcfg.geometry.heads = conf->heads; /* * We must ensure that the block device capacity is a multiple of @@ -1135,6 +1154,9 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) error_setg(errp, "Device needs media, but drive is empty"); return; } + if (conf->num_queues == VIRTIO_BLK_AUTO_NUM_QUEUES) { + conf->num_queues = 1; + } if (!conf->num_queues) { error_setg(errp, "num-queues property must be larger than 0"); return; @@ -1162,12 +1184,7 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) return; } - blkconf_blocksizes(&conf->conf); - - if (conf->conf.logical_block_size > - conf->conf.physical_block_size) { - error_setg(errp, - "logical_block_size > physical_block_size not supported"); + if (!blkconf_blocksizes(&conf->conf, errp)) { return; } @@ -1274,7 +1291,8 @@ static Property virtio_blk_properties[] = { #endif DEFINE_PROP_BIT("request-merging", VirtIOBlock, conf.request_merging, 0, true), - DEFINE_PROP_UINT16("num-queues", VirtIOBlock, conf.num_queues, 1), + DEFINE_PROP_UINT16("num-queues", VirtIOBlock, conf.num_queues, + VIRTIO_BLK_AUTO_NUM_QUEUES), DEFINE_PROP_UINT16("queue-size", VirtIOBlock, conf.queue_size, 256), DEFINE_PROP_BOOL("seg-max-adjust", VirtIOBlock, conf.seg_max_adjust, true), DEFINE_PROP_LINK("iothread", VirtIOBlock, conf.iothread, TYPE_IOTHREAD, diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c index 570489d6d9ad1e941739602dc16b74271ccda649..8a7a3f54523ed050587c3e2047defda073561653 100644 --- a/hw/block/xen-block.c +++ b/hw/block/xen-block.c @@ -195,6 +195,7 @@ static const BlockDevOps xen_block_dev_ops = { static void xen_block_realize(XenDevice *xendev, Error **errp) { + ERRP_GUARD(); XenBlockDevice *blockdev = XEN_BLOCK_DEVICE(xendev); XenBlockDeviceClass *blockdev_class = XEN_BLOCK_DEVICE_GET_CLASS(xendev); @@ -202,7 +203,6 @@ static void xen_block_realize(XenDevice *xendev, Error **errp) XenBlockVdev *vdev = &blockdev->props.vdev; BlockConf *conf = &blockdev->props.conf; BlockBackend *blk = conf->blk; - Error *local_err = NULL; if (vdev->type == XEN_BLOCK_VDEV_TYPE_INVALID) { error_setg(errp, "vdev property not set"); @@ -212,9 +212,8 @@ static void xen_block_realize(XenDevice *xendev, Error **errp) trace_xen_block_realize(type, vdev->disk, vdev->partition); if (blockdev_class->realize) { - blockdev_class->realize(blockdev, &local_err); - if (local_err) { - error_propagate(errp, local_err); + blockdev_class->realize(blockdev, errp); + if (*errp) { return; } } @@ -239,11 +238,7 @@ static void xen_block_realize(XenDevice *xendev, Error **errp) return; } - blkconf_blocksizes(conf); - - if (conf->logical_block_size > conf->physical_block_size) { - error_setg( - errp, "logical_block_size > physical_block_size not supported"); + if (!blkconf_blocksizes(conf, errp)) { return; } @@ -284,8 +279,8 @@ static void xen_block_frontend_changed(XenDevice *xendev, enum xenbus_state frontend_state, Error **errp) { + ERRP_GUARD(); enum xenbus_state backend_state = xen_device_backend_get_state(xendev); - Error *local_err = NULL; switch (frontend_state) { case XenbusStateInitialised: @@ -294,15 +289,13 @@ static void xen_block_frontend_changed(XenDevice *xendev, break; } - xen_block_disconnect(xendev, &local_err); - if (local_err) { - error_propagate(errp, local_err); + xen_block_disconnect(xendev, errp); + if (*errp) { break; } - xen_block_connect(xendev, &local_err); - if (local_err) { - error_propagate(errp, local_err); + xen_block_connect(xendev, errp); + if (*errp) { break; } @@ -315,9 +308,8 @@ static void xen_block_frontend_changed(XenDevice *xendev, case XenbusStateClosed: case XenbusStateUnknown: - xen_block_disconnect(xendev, &local_err); - if (local_err) { - error_propagate(errp, local_err); + xen_block_disconnect(xendev, errp); + if (*errp) { break; } @@ -407,7 +399,6 @@ static void xen_block_set_vdev(Object *obj, Visitor *v, const char *name, DeviceState *dev = DEVICE(obj); Property *prop = opaque; XenBlockVdev *vdev = qdev_get_prop_ptr(dev, prop); - Error *local_err = NULL; char *str, *p; const char *end; @@ -416,9 +407,7 @@ static void xen_block_set_vdev(Object *obj, Visitor *v, const char *name, return; } - visit_type_str(v, name, &str, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_str(v, name, &str, errp)) { return; } @@ -672,9 +661,9 @@ static void xen_block_blockdev_del(const char *node_name, Error **errp) static char *xen_block_blockdev_add(const char *id, QDict *qdict, Error **errp) { + ERRP_GUARD(); const char *driver = qdict_get_try_str(qdict, "driver"); BlockdevOptions *options = NULL; - Error *local_err = NULL; char *node_name; Visitor *v; @@ -689,18 +678,15 @@ static char *xen_block_blockdev_add(const char *id, QDict *qdict, trace_xen_block_blockdev_add(node_name); v = qobject_input_visitor_new(QOBJECT(qdict)); - visit_type_BlockdevOptions(v, NULL, &options, &local_err); + visit_type_BlockdevOptions(v, NULL, &options, errp); visit_free(v); - - if (local_err) { - error_propagate(errp, local_err); + if (!options) { goto fail; } - qmp_blockdev_add(options, &local_err); + qmp_blockdev_add(options, errp); - if (local_err) { - error_propagate(errp, local_err); + if (*errp) { goto fail; } @@ -719,14 +705,12 @@ fail: static void xen_block_drive_destroy(XenBlockDrive *drive, Error **errp) { + ERRP_GUARD(); char *node_name = drive->node_name; if (node_name) { - Error *local_err = NULL; - - xen_block_blockdev_del(node_name, &local_err); - if (local_err) { - error_propagate(errp, local_err); + xen_block_blockdev_del(node_name, errp); + if (*errp) { return; } g_free(node_name); @@ -740,6 +724,7 @@ static XenBlockDrive *xen_block_drive_create(const char *id, const char *device_type, QDict *opts, Error **errp) { + ERRP_GUARD(); const char *params = qdict_get_try_str(opts, "params"); const char *mode = qdict_get_try_str(opts, "mode"); const char *direct_io_safe = qdict_get_try_str(opts, "direct-io-safe"); @@ -747,7 +732,6 @@ static XenBlockDrive *xen_block_drive_create(const char *id, char *driver = NULL; char *filename = NULL; XenBlockDrive *drive = NULL; - Error *local_err = NULL; QDict *file_layer; QDict *driver_layer; @@ -826,13 +810,12 @@ static XenBlockDrive *xen_block_drive_create(const char *id, g_assert(!drive->node_name); drive->node_name = xen_block_blockdev_add(drive->id, driver_layer, - &local_err); + errp); qobject_unref(driver_layer); done: - if (local_err) { - error_propagate(errp, local_err); + if (*errp) { xen_block_drive_destroy(drive, NULL); return NULL; } @@ -857,8 +840,8 @@ static void xen_block_iothread_destroy(XenBlockIOThread *iothread, static XenBlockIOThread *xen_block_iothread_create(const char *id, Error **errp) { + ERRP_GUARD(); XenBlockIOThread *iothread = g_new(XenBlockIOThread, 1); - Error *local_err = NULL; QDict *opts; QObject *ret_data = NULL; @@ -867,13 +850,11 @@ static XenBlockIOThread *xen_block_iothread_create(const char *id, opts = qdict_new(); qdict_put_str(opts, "qom-type", TYPE_IOTHREAD); qdict_put_str(opts, "id", id); - qmp_object_add(opts, &ret_data, &local_err); + qmp_object_add(opts, &ret_data, errp); qobject_unref(opts); qobject_unref(ret_data); - if (local_err) { - error_propagate(errp, local_err); - + if (*errp) { g_free(iothread->id); g_free(iothread); return NULL; @@ -885,6 +866,7 @@ static XenBlockIOThread *xen_block_iothread_create(const char *id, static void xen_block_device_create(XenBackendInstance *backend, QDict *opts, Error **errp) { + ERRP_GUARD(); XenBus *xenbus = xen_backend_get_bus(backend); const char *name = xen_backend_get_name(backend); unsigned long number; @@ -892,7 +874,6 @@ static void xen_block_device_create(XenBackendInstance *backend, XenBlockDrive *drive = NULL; XenBlockIOThread *iothread = NULL; XenDevice *xendev = NULL; - Error *local_err = NULL; const char *type; XenBlockDevice *blockdev; @@ -924,52 +905,45 @@ static void xen_block_device_create(XenBackendInstance *backend, goto fail; } - drive = xen_block_drive_create(vdev, device_type, opts, &local_err); + drive = xen_block_drive_create(vdev, device_type, opts, errp); if (!drive) { - error_propagate_prepend(errp, local_err, "failed to create drive: "); + error_prepend(errp, "failed to create drive: "); goto fail; } - iothread = xen_block_iothread_create(vdev, &local_err); - if (local_err) { - error_propagate_prepend(errp, local_err, - "failed to create iothread: "); + iothread = xen_block_iothread_create(vdev, errp); + if (*errp) { + error_prepend(errp, "failed to create iothread: "); goto fail; } - xendev = XEN_DEVICE(qdev_create(BUS(xenbus), type)); + xendev = XEN_DEVICE(qdev_new(type)); blockdev = XEN_BLOCK_DEVICE(xendev); - object_property_set_str(OBJECT(xendev), vdev, "vdev", &local_err); - if (local_err) { - error_propagate_prepend(errp, local_err, "failed to set 'vdev': "); + if (!object_property_set_str(OBJECT(xendev), "vdev", vdev, + errp)) { + error_prepend(errp, "failed to set 'vdev': "); goto fail; } - object_property_set_str(OBJECT(xendev), - xen_block_drive_get_node_name(drive), "drive", - &local_err); - if (local_err) { - error_propagate_prepend(errp, local_err, "failed to set 'drive': "); + if (!object_property_set_str(OBJECT(xendev), "drive", + xen_block_drive_get_node_name(drive), + errp)) { + error_prepend(errp, "failed to set 'drive': "); goto fail; } - object_property_set_str(OBJECT(xendev), iothread->id, "iothread", - &local_err); - if (local_err) { - error_propagate_prepend(errp, local_err, - "failed to set 'iothread': "); + if (!object_property_set_str(OBJECT(xendev), "iothread", iothread->id, + errp)) { + error_prepend(errp, "failed to set 'iothread': "); goto fail; } blockdev->iothread = iothread; blockdev->drive = drive; - object_property_set_bool(OBJECT(xendev), true, "realized", &local_err); - if (local_err) { - error_propagate_prepend(errp, local_err, - "realization of device %s failed: ", - type); + if (!qdev_realize_and_unref(DEVICE(xendev), BUS(xenbus), errp)) { + error_prepend(errp, "realization of device %s failed: ", type); goto fail; } @@ -993,31 +967,29 @@ fail: static void xen_block_device_destroy(XenBackendInstance *backend, Error **errp) { + ERRP_GUARD(); XenDevice *xendev = xen_backend_get_device(backend); XenBlockDevice *blockdev = XEN_BLOCK_DEVICE(xendev); XenBlockVdev *vdev = &blockdev->props.vdev; XenBlockDrive *drive = blockdev->drive; XenBlockIOThread *iothread = blockdev->iothread; - Error *local_err = NULL; trace_xen_block_device_destroy(vdev->number); object_unparent(OBJECT(xendev)); if (iothread) { - xen_block_iothread_destroy(iothread, &local_err); - if (local_err) { - error_propagate_prepend(errp, local_err, - "failed to destroy iothread: "); + xen_block_iothread_destroy(iothread, errp); + if (*errp) { + error_prepend(errp, "failed to destroy iothread: "); return; } } if (drive) { - xen_block_drive_destroy(drive, &local_err); - if (local_err) { - error_propagate_prepend(errp, local_err, - "failed to destroy drive: "); + xen_block_drive_destroy(drive, errp); + if (*errp) { + error_prepend(errp, "failed to destroy drive: "); return; } } diff --git a/hw/char/Kconfig b/hw/char/Kconfig index 40e7a8b8bb122776dd5dc992eaec9f8a00a9852f..939bc4475883a5efe9b12cd5b1c73869694366af 100644 --- a/hw/char/Kconfig +++ b/hw/char/Kconfig @@ -1,6 +1,9 @@ config ESCC bool +config HTIF + bool + config PARALLEL bool default y @@ -46,3 +49,15 @@ config SCLPCONSOLE config TERMINAL3270 bool + +config RENESAS_SCI + bool + +config AVR_USART + bool + +config MCHP_PFSOC_MMUART + bool + +config SIFIVE_UART + bool diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs deleted file mode 100644 index 9e9a6c1affb6b68838a2d98b065f73db93cb3b7f..0000000000000000000000000000000000000000 --- a/hw/char/Makefile.objs +++ /dev/null @@ -1,36 +0,0 @@ -common-obj-$(CONFIG_IPACK) += ipoctal232.o -common-obj-$(CONFIG_ESCC) += escc.o -common-obj-$(CONFIG_NRF51_SOC) += nrf51_uart.o -common-obj-$(CONFIG_PARALLEL) += parallel.o -common-obj-$(CONFIG_ISA_BUS) += parallel-isa.o -common-obj-$(CONFIG_PL011) += pl011.o -common-obj-$(CONFIG_SERIAL) += serial.o -common-obj-$(CONFIG_SERIAL_ISA) += serial-isa.o -common-obj-$(CONFIG_SERIAL_PCI) += serial-pci.o -common-obj-$(CONFIG_SERIAL_PCI_MULTI) += serial-pci-multi.o -common-obj-$(CONFIG_VIRTIO_SERIAL) += virtio-console.o -common-obj-$(CONFIG_XILINX) += xilinx_uartlite.o -common-obj-$(CONFIG_XEN) += xen_console.o -common-obj-$(CONFIG_CADENCE) += cadence_uart.o - -common-obj-$(CONFIG_EXYNOS4) += exynos4210_uart.o -common-obj-$(CONFIG_COLDFIRE) += mcf_uart.o -common-obj-$(CONFIG_OMAP) += omap_uart.o -common-obj-$(CONFIG_SH4) += sh_serial.o -common-obj-$(CONFIG_DIGIC) += digic-uart.o -common-obj-$(CONFIG_STM32F2XX_USART) += stm32f2xx_usart.o -common-obj-$(CONFIG_RASPI) += bcm2835_aux.o - -common-obj-$(CONFIG_CMSDK_APB_UART) += cmsdk-apb-uart.o -common-obj-$(CONFIG_ETRAXFS) += etraxfs_ser.o -common-obj-$(CONFIG_ISA_DEBUG) += debugcon.o -common-obj-$(CONFIG_GRLIB) += grlib_apbuart.o -common-obj-$(CONFIG_IMX) += imx_serial.o -common-obj-$(CONFIG_LM32) += lm32_juart.o -common-obj-$(CONFIG_LM32) += lm32_uart.o -common-obj-$(CONFIG_MILKYMIST) += milkymist-uart.o -common-obj-$(CONFIG_SCLPCONSOLE) += sclpconsole.o sclpconsole-lm.o - -obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o -obj-$(CONFIG_PSERIES) += spapr_vty.o -obj-$(CONFIG_TERMINAL3270) += terminal3270.o diff --git a/hw/char/avr_usart.c b/hw/char/avr_usart.c new file mode 100644 index 0000000000000000000000000000000000000000..fbe2a112b7027b59421ab63e3cb563df61779d56 --- /dev/null +++ b/hw/char/avr_usart.c @@ -0,0 +1,320 @@ +/* + * AVR USART + * + * Copyright (c) 2018 University of Kent + * Author: Sarah Harris + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * + */ + +#include "qemu/osdep.h" +#include "hw/char/avr_usart.h" +#include "qemu/log.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" + +static int avr_usart_can_receive(void *opaque) +{ + AVRUsartState *usart = opaque; + + if (usart->data_valid || !(usart->csrb & USART_CSRB_RXEN)) { + return 0; + } + return 1; +} + +static void avr_usart_receive(void *opaque, const uint8_t *buffer, int size) +{ + AVRUsartState *usart = opaque; + assert(size == 1); + assert(!usart->data_valid); + usart->data = buffer[0]; + usart->data_valid = true; + usart->csra |= USART_CSRA_RXC; + if (usart->csrb & USART_CSRB_RXCIE) { + qemu_set_irq(usart->rxc_irq, 1); + } +} + +static void update_char_mask(AVRUsartState *usart) +{ + uint8_t mode = ((usart->csrc & USART_CSRC_CSZ0) ? 1 : 0) | + ((usart->csrc & USART_CSRC_CSZ1) ? 2 : 0) | + ((usart->csrb & USART_CSRB_CSZ2) ? 4 : 0); + switch (mode) { + case 0: + usart->char_mask = 0b11111; + break; + case 1: + usart->char_mask = 0b111111; + break; + case 2: + usart->char_mask = 0b1111111; + break; + case 3: + usart->char_mask = 0b11111111; + break; + case 4: + /* Fallthrough. */ + case 5: + /* Fallthrough. */ + case 6: + qemu_log_mask( + LOG_GUEST_ERROR, + "%s: Reserved character size 0x%x\n", + __func__, + mode); + break; + case 7: + qemu_log_mask( + LOG_GUEST_ERROR, + "%s: Nine bit character size not supported (forcing eight)\n", + __func__); + usart->char_mask = 0b11111111; + break; + default: + assert(0); + } +} + +static void avr_usart_reset(DeviceState *dev) +{ + AVRUsartState *usart = AVR_USART(dev); + usart->data_valid = false; + usart->csra = 0b00100000; + usart->csrb = 0b00000000; + usart->csrc = 0b00000110; + usart->brrl = 0; + usart->brrh = 0; + update_char_mask(usart); + qemu_set_irq(usart->rxc_irq, 0); + qemu_set_irq(usart->txc_irq, 0); + qemu_set_irq(usart->dre_irq, 0); +} + +static uint64_t avr_usart_read(void *opaque, hwaddr addr, unsigned int size) +{ + AVRUsartState *usart = opaque; + uint8_t data; + assert(size == 1); + + if (!usart->enabled) { + return 0; + } + + switch (addr) { + case USART_DR: + if (!(usart->csrb & USART_CSRB_RXEN)) { + /* Receiver disabled, ignore. */ + return 0; + } + if (usart->data_valid) { + data = usart->data & usart->char_mask; + usart->data_valid = false; + } else { + data = 0; + } + usart->csra &= 0xff ^ USART_CSRA_RXC; + qemu_set_irq(usart->rxc_irq, 0); + qemu_chr_fe_accept_input(&usart->chr); + return data; + case USART_CSRA: + return usart->csra; + case USART_CSRB: + return usart->csrb; + case USART_CSRC: + return usart->csrc; + case USART_BRRL: + return usart->brrl; + case USART_BRRH: + return usart->brrh; + default: + qemu_log_mask( + LOG_GUEST_ERROR, + "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, + addr); + } + return 0; +} + +static void avr_usart_write(void *opaque, hwaddr addr, uint64_t value, + unsigned int size) +{ + AVRUsartState *usart = opaque; + uint8_t mask; + uint8_t data; + assert((value & 0xff) == value); + assert(size == 1); + + if (!usart->enabled) { + return; + } + + switch (addr) { + case USART_DR: + if (!(usart->csrb & USART_CSRB_TXEN)) { + /* Transmitter disabled, ignore. */ + return; + } + usart->csra |= USART_CSRA_TXC; + usart->csra |= USART_CSRA_DRE; + if (usart->csrb & USART_CSRB_TXCIE) { + qemu_set_irq(usart->txc_irq, 1); + usart->csra &= 0xff ^ USART_CSRA_TXC; + } + if (usart->csrb & USART_CSRB_DREIE) { + qemu_set_irq(usart->dre_irq, 1); + } + data = value; + qemu_chr_fe_write_all(&usart->chr, &data, 1); + break; + case USART_CSRA: + mask = 0b01000011; + /* Mask read-only bits. */ + value = (value & mask) | (usart->csra & (0xff ^ mask)); + usart->csra = value; + if (value & USART_CSRA_TXC) { + usart->csra ^= USART_CSRA_TXC; + qemu_set_irq(usart->txc_irq, 0); + } + if (value & USART_CSRA_MPCM) { + qemu_log_mask( + LOG_GUEST_ERROR, + "%s: MPCM not supported by USART\n", + __func__); + } + break; + case USART_CSRB: + mask = 0b11111101; + /* Mask read-only bits. */ + value = (value & mask) | (usart->csrb & (0xff ^ mask)); + usart->csrb = value; + if (!(value & USART_CSRB_RXEN)) { + /* Receiver disabled, flush input buffer. */ + usart->data_valid = false; + } + qemu_set_irq(usart->rxc_irq, + ((value & USART_CSRB_RXCIE) && + (usart->csra & USART_CSRA_RXC)) ? 1 : 0); + qemu_set_irq(usart->txc_irq, + ((value & USART_CSRB_TXCIE) && + (usart->csra & USART_CSRA_TXC)) ? 1 : 0); + qemu_set_irq(usart->dre_irq, + ((value & USART_CSRB_DREIE) && + (usart->csra & USART_CSRA_DRE)) ? 1 : 0); + update_char_mask(usart); + break; + case USART_CSRC: + usart->csrc = value; + if ((value & USART_CSRC_MSEL1) && (value & USART_CSRC_MSEL0)) { + qemu_log_mask( + LOG_GUEST_ERROR, + "%s: SPI mode not supported by USART\n", + __func__); + } + if ((value & USART_CSRC_MSEL1) && !(value & USART_CSRC_MSEL0)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad USART mode\n", __func__); + } + if (!(value & USART_CSRC_PM1) && (value & USART_CSRC_PM0)) { + qemu_log_mask( + LOG_GUEST_ERROR, + "%s: Bad USART parity mode\n", + __func__); + } + update_char_mask(usart); + break; + case USART_BRRL: + usart->brrl = value; + break; + case USART_BRRH: + usart->brrh = value & 0b00001111; + break; + default: + qemu_log_mask( + LOG_GUEST_ERROR, + "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, + addr); + } +} + +static const MemoryRegionOps avr_usart_ops = { + .read = avr_usart_read, + .write = avr_usart_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = {.min_access_size = 1, .max_access_size = 1} +}; + +static Property avr_usart_properties[] = { + DEFINE_PROP_CHR("chardev", AVRUsartState, chr), + DEFINE_PROP_END_OF_LIST(), +}; + +static void avr_usart_pr(void *opaque, int irq, int level) +{ + AVRUsartState *s = AVR_USART(opaque); + + s->enabled = !level; + + if (!s->enabled) { + avr_usart_reset(DEVICE(s)); + } +} + +static void avr_usart_init(Object *obj) +{ + AVRUsartState *s = AVR_USART(obj); + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->rxc_irq); + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->dre_irq); + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->txc_irq); + memory_region_init_io(&s->mmio, obj, &avr_usart_ops, s, TYPE_AVR_USART, 7); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); + qdev_init_gpio_in(DEVICE(s), avr_usart_pr, 1); + s->enabled = true; +} + +static void avr_usart_realize(DeviceState *dev, Error **errp) +{ + AVRUsartState *s = AVR_USART(dev); + qemu_chr_fe_set_handlers(&s->chr, avr_usart_can_receive, + avr_usart_receive, NULL, NULL, + s, NULL, true); + avr_usart_reset(dev); +} + +static void avr_usart_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = avr_usart_reset; + device_class_set_props(dc, avr_usart_properties); + dc->realize = avr_usart_realize; +} + +static const TypeInfo avr_usart_info = { + .name = TYPE_AVR_USART, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AVRUsartState), + .instance_init = avr_usart_init, + .class_init = avr_usart_class_init, +}; + +static void avr_usart_register_types(void) +{ + type_register_static(&avr_usart_info); +} + +type_init(avr_usart_register_types) diff --git a/hw/char/bcm2835_aux.c b/hw/char/bcm2835_aux.c index ee3dd40e3c7bebf434a5f96cb1502524c419eca6..dade2ab5fd5036eb5adab9f3da5385238ae85b7f 100644 --- a/hw/char/bcm2835_aux.c +++ b/hw/char/bcm2835_aux.c @@ -249,7 +249,9 @@ static const MemoryRegionOps bcm2835_aux_ops = { .read = bcm2835_aux_read, .write = bcm2835_aux_write, .endianness = DEVICE_NATIVE_ENDIAN, - .valid.min_access_size = 4, + .impl.min_access_size = 4, + .impl.max_access_size = 4, + .valid.min_access_size = 1, .valid.max_access_size = 4, }; diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c index c8d938efb5bb363ae33845b750b29bffb830acbf..2a063ad72c5eb2b4e7dc7d12f76b0f5ab84ca882 100644 --- a/hw/char/debugcon.c +++ b/hw/char/debugcon.c @@ -30,10 +30,10 @@ #include "chardev/char-fe.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" +#include "qom/object.h" #define TYPE_ISA_DEBUGCON_DEVICE "isa-debugcon" -#define ISA_DEBUGCON_DEVICE(obj) \ - OBJECT_CHECK(ISADebugconState, (obj), TYPE_ISA_DEBUGCON_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(ISADebugconState, ISA_DEBUGCON_DEVICE) //#define DEBUG_DEBUGCON @@ -43,12 +43,12 @@ typedef struct DebugconState { uint32_t readback; } DebugconState; -typedef struct ISADebugconState { +struct ISADebugconState { ISADevice parent_obj; uint32_t iobase; DebugconState state; -} ISADebugconState; +}; static void debugcon_ioport_write(void *opaque, hwaddr addr, uint64_t val, unsigned width) diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c index 947bdb649a5257fcfb6a03f49699f30fd583b1e5..d9fba2ae6cb5dbe1844bb2b6a24b6ca607f1b8f9 100644 --- a/hw/char/etraxfs_ser.c +++ b/hw/char/etraxfs_ser.c @@ -29,6 +29,7 @@ #include "chardev/char-fe.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" #define D(x) @@ -49,10 +50,11 @@ #define STAT_TR_RDY 24 #define TYPE_ETRAX_FS_SERIAL "etraxfs,serial" -#define ETRAX_SERIAL(obj) \ - OBJECT_CHECK(ETRAXSerial, (obj), TYPE_ETRAX_FS_SERIAL) +typedef struct ETRAXSerial ETRAXSerial; +DECLARE_INSTANCE_CHECKER(ETRAXSerial, ETRAX_SERIAL, + TYPE_ETRAX_FS_SERIAL) -typedef struct ETRAXSerial { +struct ETRAXSerial { SysBusDevice parent_obj; MemoryRegion mmio; @@ -67,7 +69,7 @@ typedef struct ETRAXSerial { /* Control registers. */ uint32_t regs[R_MAX]; -} ETRAXSerial; +}; static void ser_update_irq(ETRAXSerial *s) { diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c index 96d5180e3e27d1f2c23b02a69dddc077f431945c..96afe3580f937f3f085fcf816586de599ac7abd3 100644 --- a/hw/char/exynos4210_uart.c +++ b/hw/char/exynos4210_uart.c @@ -22,6 +22,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" #include "migration/vmstate.h" +#include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/module.h" #include "qemu/timer.h" @@ -33,6 +34,7 @@ #include "hw/qdev-properties.h" #include "trace.h" +#include "qom/object.h" /* * Offsets for UART registers relative to SFR base address @@ -137,10 +139,9 @@ typedef struct { } Exynos4210UartFIFO; #define TYPE_EXYNOS4210_UART "exynos4210.uart" -#define EXYNOS4210_UART(obj) \ - OBJECT_CHECK(Exynos4210UartState, (obj), TYPE_EXYNOS4210_UART) +OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210UartState, EXYNOS4210_UART) -typedef struct Exynos4210UartState { +struct Exynos4210UartState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -158,7 +159,7 @@ typedef struct Exynos4210UartState { uint32_t channel; -} Exynos4210UartState; +}; /* Used only for tracing */ @@ -652,7 +653,7 @@ DeviceState *exynos4210_uart_create(hwaddr addr, DeviceState *dev; SysBusDevice *bus; - dev = qdev_create(NULL, TYPE_EXYNOS4210_UART); + dev = qdev_new(TYPE_EXYNOS4210_UART); qdev_prop_set_chr(dev, "chardev", chr); qdev_prop_set_uint32(dev, "channel", channel); @@ -660,7 +661,7 @@ DeviceState *exynos4210_uart_create(hwaddr addr, qdev_prop_set_uint32(dev, "tx-size", fifo_size); bus = SYS_BUS_DEVICE(dev); - qdev_init_nofail(dev); + sysbus_realize_and_unref(bus, &error_fatal); if (addr != (hwaddr)-1) { sysbus_mmio_map(bus, 0, addr); } diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c index 16d0feac594e0633a1ddf243b280fe874e178a44..3f80f6824e060899a4d5499543318829a7a56f8a 100644 --- a/hw/char/grlib_apbuart.c +++ b/hw/char/grlib_apbuart.c @@ -31,6 +31,7 @@ #include "chardev/char-fe.h" #include "trace.h" +#include "qom/object.h" #define UART_REG_SIZE 20 /* Size of memory mapped registers */ @@ -72,10 +73,9 @@ #define FIFO_LENGTH 1024 -#define GRLIB_APB_UART(obj) \ - OBJECT_CHECK(UART, (obj), TYPE_GRLIB_APB_UART) +OBJECT_DECLARE_SIMPLE_TYPE(UART, GRLIB_APB_UART) -typedef struct UART { +struct UART { SysBusDevice parent_obj; MemoryRegion iomem; @@ -91,7 +91,7 @@ typedef struct UART { char buffer[FIFO_LENGTH]; int len; int current; -} UART; +}; static int uart_data_to_read(UART *uart) { diff --git a/hw/char/ibex_uart.c b/hw/char/ibex_uart.c new file mode 100644 index 0000000000000000000000000000000000000000..cc49a3501326aaecc8fda079850e7231f63032b2 --- /dev/null +++ b/hw/char/ibex_uart.c @@ -0,0 +1,516 @@ +/* + * QEMU lowRISC Ibex UART device + * + * Copyright (c) 2020 Western Digital + * + * For details check the documentation here: + * https://docs.opentitan.org/hw/ip/uart/doc/ + * + * 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/char/ibex_uart.h" +#include "hw/irq.h" +#include "hw/qdev-clock.h" +#include "hw/qdev-properties.h" +#include "migration/vmstate.h" +#include "qemu/log.h" +#include "qemu/module.h" + +static void ibex_uart_update_irqs(IbexUartState *s) +{ + if (s->uart_intr_state & s->uart_intr_enable & R_INTR_STATE_TX_WATERMARK_MASK) { + qemu_set_irq(s->tx_watermark, 1); + } else { + qemu_set_irq(s->tx_watermark, 0); + } + + if (s->uart_intr_state & s->uart_intr_enable & R_INTR_STATE_RX_WATERMARK_MASK) { + qemu_set_irq(s->rx_watermark, 1); + } else { + qemu_set_irq(s->rx_watermark, 0); + } + + if (s->uart_intr_state & s->uart_intr_enable & R_INTR_STATE_TX_EMPTY_MASK) { + qemu_set_irq(s->tx_empty, 1); + } else { + qemu_set_irq(s->tx_empty, 0); + } + + if (s->uart_intr_state & s->uart_intr_enable & R_INTR_STATE_RX_OVERFLOW_MASK) { + qemu_set_irq(s->rx_overflow, 1); + } else { + qemu_set_irq(s->rx_overflow, 0); + } +} + +static int ibex_uart_can_receive(void *opaque) +{ + IbexUartState *s = opaque; + + if (s->uart_ctrl & R_CTRL_RX_ENABLE_MASK) { + return 1; + } + + return 0; +} + +static void ibex_uart_receive(void *opaque, const uint8_t *buf, int size) +{ + IbexUartState *s = opaque; + uint8_t rx_fifo_level = (s->uart_fifo_ctrl & R_FIFO_CTRL_RXILVL_MASK) + >> R_FIFO_CTRL_RXILVL_SHIFT; + + s->uart_rdata = *buf; + + s->uart_status &= ~R_STATUS_RXIDLE_MASK; + s->uart_status &= ~R_STATUS_RXEMPTY_MASK; + + if (size > rx_fifo_level) { + s->uart_intr_state |= R_INTR_STATE_RX_WATERMARK_MASK; + } + + ibex_uart_update_irqs(s); +} + +static gboolean ibex_uart_xmit(GIOChannel *chan, GIOCondition cond, + void *opaque) +{ + IbexUartState *s = opaque; + uint8_t tx_fifo_level = (s->uart_fifo_ctrl & R_FIFO_CTRL_TXILVL_MASK) + >> R_FIFO_CTRL_TXILVL_SHIFT; + int ret; + + /* instant drain the fifo when there's no back-end */ + if (!qemu_chr_fe_backend_connected(&s->chr)) { + s->tx_level = 0; + return FALSE; + } + + if (!s->tx_level) { + s->uart_status &= ~R_STATUS_TXFULL_MASK; + s->uart_status |= R_STATUS_TXEMPTY_MASK; + s->uart_intr_state |= R_INTR_STATE_TX_EMPTY_MASK; + s->uart_intr_state &= ~R_INTR_STATE_TX_WATERMARK_MASK; + ibex_uart_update_irqs(s); + return FALSE; + } + + ret = qemu_chr_fe_write(&s->chr, s->tx_fifo, s->tx_level); + + if (ret >= 0) { + s->tx_level -= ret; + memmove(s->tx_fifo, s->tx_fifo + ret, s->tx_level); + } + + if (s->tx_level) { + guint r = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP, + ibex_uart_xmit, s); + if (!r) { + s->tx_level = 0; + return FALSE; + } + } + + /* Clear the TX Full bit */ + if (s->tx_level != IBEX_UART_TX_FIFO_SIZE) { + s->uart_status &= ~R_STATUS_TXFULL_MASK; + } + + /* Disable the TX_WATERMARK IRQ */ + if (s->tx_level < tx_fifo_level) { + s->uart_intr_state &= ~R_INTR_STATE_TX_WATERMARK_MASK; + } + + /* Set TX empty */ + if (s->tx_level == 0) { + s->uart_status |= R_STATUS_TXEMPTY_MASK; + s->uart_intr_state |= R_INTR_STATE_TX_EMPTY_MASK; + } + + ibex_uart_update_irqs(s); + return FALSE; +} + +static void uart_write_tx_fifo(IbexUartState *s, const uint8_t *buf, + int size) +{ + uint64_t current_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint8_t tx_fifo_level = (s->uart_fifo_ctrl & R_FIFO_CTRL_TXILVL_MASK) + >> R_FIFO_CTRL_TXILVL_SHIFT; + + if (size > IBEX_UART_TX_FIFO_SIZE - s->tx_level) { + size = IBEX_UART_TX_FIFO_SIZE - s->tx_level; + qemu_log_mask(LOG_GUEST_ERROR, "ibex_uart: TX FIFO overflow"); + } + + memcpy(s->tx_fifo + s->tx_level, buf, size); + s->tx_level += size; + + if (s->tx_level > 0) { + s->uart_status &= ~R_STATUS_TXEMPTY_MASK; + } + + if (s->tx_level >= tx_fifo_level) { + s->uart_intr_state |= R_INTR_STATE_TX_WATERMARK_MASK; + ibex_uart_update_irqs(s); + } + + if (s->tx_level == IBEX_UART_TX_FIFO_SIZE) { + s->uart_status |= R_STATUS_TXFULL_MASK; + } + + timer_mod(s->fifo_trigger_handle, current_time + + (s->char_tx_time * 4)); +} + +static void ibex_uart_reset(DeviceState *dev) +{ + IbexUartState *s = IBEX_UART(dev); + + s->uart_intr_state = 0x00000000; + s->uart_intr_state = 0x00000000; + s->uart_intr_enable = 0x00000000; + s->uart_ctrl = 0x00000000; + s->uart_status = 0x0000003c; + s->uart_rdata = 0x00000000; + s->uart_fifo_ctrl = 0x00000000; + s->uart_fifo_status = 0x00000000; + s->uart_ovrd = 0x00000000; + s->uart_val = 0x00000000; + s->uart_timeout_ctrl = 0x00000000; + + s->tx_level = 0; + + s->char_tx_time = (NANOSECONDS_PER_SECOND / 230400) * 10; + + ibex_uart_update_irqs(s); +} + +static uint64_t ibex_uart_get_baud(IbexUartState *s) +{ + uint64_t baud; + + baud = ((s->uart_ctrl & R_CTRL_NCO_MASK) >> 16); + baud *= clock_get_hz(s->f_clk); + baud >>= 20; + + return baud; +} + +static uint64_t ibex_uart_read(void *opaque, hwaddr addr, + unsigned int size) +{ + IbexUartState *s = opaque; + uint64_t retvalue = 0; + + switch (addr >> 2) { + case R_INTR_STATE: + retvalue = s->uart_intr_state; + break; + case R_INTR_ENABLE: + retvalue = s->uart_intr_enable; + break; + case R_INTR_TEST: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: wdata is write only\n", __func__); + break; + + case R_CTRL: + retvalue = s->uart_ctrl; + break; + case R_STATUS: + retvalue = s->uart_status; + break; + + case R_RDATA: + retvalue = s->uart_rdata; + if (s->uart_ctrl & R_CTRL_RX_ENABLE_MASK) { + qemu_chr_fe_accept_input(&s->chr); + + s->uart_status |= R_STATUS_RXIDLE_MASK; + s->uart_status |= R_STATUS_RXEMPTY_MASK; + } + break; + case R_WDATA: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: wdata is write only\n", __func__); + break; + + case R_FIFO_CTRL: + retvalue = s->uart_fifo_ctrl; + break; + case R_FIFO_STATUS: + retvalue = s->uart_fifo_status; + + retvalue |= s->tx_level & 0x1F; + + qemu_log_mask(LOG_UNIMP, + "%s: RX fifos are not supported\n", __func__); + break; + + case R_OVRD: + retvalue = s->uart_ovrd; + qemu_log_mask(LOG_UNIMP, + "%s: ovrd is not supported\n", __func__); + break; + case R_VAL: + retvalue = s->uart_val; + qemu_log_mask(LOG_UNIMP, + "%s: val is not supported\n", __func__); + break; + case R_TIMEOUT_CTRL: + retvalue = s->uart_timeout_ctrl; + qemu_log_mask(LOG_UNIMP, + "%s: timeout_ctrl is not supported\n", __func__); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); + return 0; + } + + return retvalue; +} + +static void ibex_uart_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned int size) +{ + IbexUartState *s = opaque; + uint32_t value = val64; + + switch (addr >> 2) { + case R_INTR_STATE: + /* Write 1 clear */ + s->uart_intr_state &= ~value; + ibex_uart_update_irqs(s); + break; + case R_INTR_ENABLE: + s->uart_intr_enable = value; + ibex_uart_update_irqs(s); + break; + case R_INTR_TEST: + s->uart_intr_state |= value; + ibex_uart_update_irqs(s); + break; + + case R_CTRL: + s->uart_ctrl = value; + + if (value & R_CTRL_NF_MASK) { + qemu_log_mask(LOG_UNIMP, + "%s: UART_CTRL_NF is not supported\n", __func__); + } + if (value & R_CTRL_SLPBK_MASK) { + qemu_log_mask(LOG_UNIMP, + "%s: UART_CTRL_SLPBK is not supported\n", __func__); + } + if (value & R_CTRL_LLPBK_MASK) { + qemu_log_mask(LOG_UNIMP, + "%s: UART_CTRL_LLPBK is not supported\n", __func__); + } + if (value & R_CTRL_PARITY_EN_MASK) { + qemu_log_mask(LOG_UNIMP, + "%s: UART_CTRL_PARITY_EN is not supported\n", + __func__); + } + if (value & R_CTRL_PARITY_ODD_MASK) { + qemu_log_mask(LOG_UNIMP, + "%s: UART_CTRL_PARITY_ODD is not supported\n", + __func__); + } + if (value & R_CTRL_RXBLVL_MASK) { + qemu_log_mask(LOG_UNIMP, + "%s: UART_CTRL_RXBLVL is not supported\n", __func__); + } + if (value & R_CTRL_NCO_MASK) { + uint64_t baud = ibex_uart_get_baud(s); + + s->char_tx_time = (NANOSECONDS_PER_SECOND / baud) * 10; + } + break; + case R_STATUS: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: status is read only\n", __func__); + break; + + case R_RDATA: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: rdata is read only\n", __func__); + break; + case R_WDATA: + uart_write_tx_fifo(s, (uint8_t *) &value, 1); + break; + + case R_FIFO_CTRL: + s->uart_fifo_ctrl = value; + + if (value & R_FIFO_CTRL_RXRST_MASK) { + qemu_log_mask(LOG_UNIMP, + "%s: RX fifos are not supported\n", __func__); + } + if (value & R_FIFO_CTRL_TXRST_MASK) { + s->tx_level = 0; + } + break; + case R_FIFO_STATUS: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: fifo_status is read only\n", __func__); + break; + + case R_OVRD: + s->uart_ovrd = value; + qemu_log_mask(LOG_UNIMP, + "%s: ovrd is not supported\n", __func__); + break; + case R_VAL: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: val is read only\n", __func__); + break; + case R_TIMEOUT_CTRL: + s->uart_timeout_ctrl = value; + qemu_log_mask(LOG_UNIMP, + "%s: timeout_ctrl is not supported\n", __func__); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); + } +} + +static void ibex_uart_clk_update(void *opaque) +{ + IbexUartState *s = opaque; + + /* recompute uart's speed on clock change */ + uint64_t baud = ibex_uart_get_baud(s); + + s->char_tx_time = (NANOSECONDS_PER_SECOND / baud) * 10; +} + +static void fifo_trigger_update(void *opaque) +{ + IbexUartState *s = opaque; + + if (s->uart_ctrl & R_CTRL_TX_ENABLE_MASK) { + ibex_uart_xmit(NULL, G_IO_OUT, s); + } +} + +static const MemoryRegionOps ibex_uart_ops = { + .read = ibex_uart_read, + .write = ibex_uart_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl.min_access_size = 4, + .impl.max_access_size = 4, +}; + +static int ibex_uart_post_load(void *opaque, int version_id) +{ + IbexUartState *s = opaque; + + ibex_uart_update_irqs(s); + return 0; +} + +static const VMStateDescription vmstate_ibex_uart = { + .name = TYPE_IBEX_UART, + .version_id = 1, + .minimum_version_id = 1, + .post_load = ibex_uart_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT8_ARRAY(tx_fifo, IbexUartState, + IBEX_UART_TX_FIFO_SIZE), + VMSTATE_UINT32(tx_level, IbexUartState), + VMSTATE_UINT64(char_tx_time, IbexUartState), + VMSTATE_TIMER_PTR(fifo_trigger_handle, IbexUartState), + VMSTATE_UINT32(uart_intr_state, IbexUartState), + VMSTATE_UINT32(uart_intr_enable, IbexUartState), + VMSTATE_UINT32(uart_ctrl, IbexUartState), + VMSTATE_UINT32(uart_status, IbexUartState), + VMSTATE_UINT32(uart_rdata, IbexUartState), + VMSTATE_UINT32(uart_fifo_ctrl, IbexUartState), + VMSTATE_UINT32(uart_fifo_status, IbexUartState), + VMSTATE_UINT32(uart_ovrd, IbexUartState), + VMSTATE_UINT32(uart_val, IbexUartState), + VMSTATE_UINT32(uart_timeout_ctrl, IbexUartState), + VMSTATE_END_OF_LIST() + } +}; + +static Property ibex_uart_properties[] = { + DEFINE_PROP_CHR("chardev", IbexUartState, chr), + DEFINE_PROP_END_OF_LIST(), +}; + +static void ibex_uart_init(Object *obj) +{ + IbexUartState *s = IBEX_UART(obj); + + s->f_clk = qdev_init_clock_in(DEVICE(obj), "f_clock", + ibex_uart_clk_update, s); + clock_set_hz(s->f_clk, IBEX_UART_CLOCK); + + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->tx_watermark); + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->rx_watermark); + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->tx_empty); + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->rx_overflow); + + memory_region_init_io(&s->mmio, obj, &ibex_uart_ops, s, + TYPE_IBEX_UART, 0x400); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); +} + +static void ibex_uart_realize(DeviceState *dev, Error **errp) +{ + IbexUartState *s = IBEX_UART(dev); + + s->fifo_trigger_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL, + fifo_trigger_update, s); + + qemu_chr_fe_set_handlers(&s->chr, ibex_uart_can_receive, + ibex_uart_receive, NULL, NULL, + s, NULL, true); +} + +static void ibex_uart_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = ibex_uart_reset; + dc->realize = ibex_uart_realize; + dc->vmsd = &vmstate_ibex_uart; + device_class_set_props(dc, ibex_uart_properties); +} + +static const TypeInfo ibex_uart_info = { + .name = TYPE_IBEX_UART, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(IbexUartState), + .instance_init = ibex_uart_init, + .class_init = ibex_uart_class_init, +}; + +static void ibex_uart_register_types(void) +{ + type_register_static(&ibex_uart_info); +} + +type_init(ibex_uart_register_types) diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c index d7c497b93992b111ab86f97b058f9942d3021a27..ad000a39b9b3ba0cb3b6448389cf5b121f52bb21 100644 --- a/hw/char/ipoctal232.c +++ b/hw/char/ipoctal232.c @@ -16,6 +16,7 @@ #include "qemu/bitops.h" #include "qemu/module.h" #include "chardev/char-fe.h" +#include "qom/object.h" /* #define DEBUG_IPOCTAL */ @@ -122,8 +123,7 @@ struct IPOctalState { #define TYPE_IPOCTAL "ipoctal232" -#define IPOCTAL(obj) \ - OBJECT_CHECK(IPOctalState, (obj), TYPE_IPOCTAL) +OBJECT_DECLARE_SIMPLE_TYPE(IPOctalState, IPOCTAL) static const VMStateDescription vmstate_scc2698_channel = { .name = "scc2698_channel", diff --git a/hw/char/lm32_juart.c b/hw/char/lm32_juart.c index 3f348612334aabfc3911d85667e1c2fbb4390264..aced357011683d5f6fc01ec659c6b314e45a936d 100644 --- a/hw/char/lm32_juart.c +++ b/hw/char/lm32_juart.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -26,6 +26,7 @@ #include "hw/char/lm32_juart.h" #include "hw/qdev-properties.h" +#include "qom/object.h" enum { LM32_JUART_MIN_SAVE_VERSION = 0, @@ -41,7 +42,7 @@ enum { JRX_FULL = (1<<8), }; -#define LM32_JUART(obj) OBJECT_CHECK(LM32JuartState, (obj), TYPE_LM32_JUART) +OBJECT_DECLARE_SIMPLE_TYPE(LM32JuartState, LM32_JUART) struct LM32JuartState { SysBusDevice parent_obj; @@ -51,7 +52,6 @@ struct LM32JuartState { uint32_t jtx; uint32_t jrx; }; -typedef struct LM32JuartState LM32JuartState; uint32_t lm32_juart_get_jtx(DeviceState *d) { diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c index b0b10928891210cd5ca4b1aaa96feb1bea98917c..2f58e2943bf96ef0fef02b8c4d3fe42a28da1cb4 100644 --- a/hw/char/lm32_uart.c +++ b/hw/char/lm32_uart.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,6 +31,7 @@ #include "chardev/char-fe.h" #include "qemu/error-report.h" #include "qemu/module.h" +#include "qom/object.h" enum { R_RXTX = 0, @@ -94,7 +95,7 @@ enum { }; #define TYPE_LM32_UART "lm32-uart" -#define LM32_UART(obj) OBJECT_CHECK(LM32UartState, (obj), TYPE_LM32_UART) +OBJECT_DECLARE_SIMPLE_TYPE(LM32UartState, LM32_UART) struct LM32UartState { SysBusDevice parent_obj; @@ -105,7 +106,6 @@ struct LM32UartState { uint32_t regs[R_MAX]; }; -typedef struct LM32UartState LM32UartState; static void uart_update_irq(LM32UartState *s) { diff --git a/hw/char/mcf_uart.c b/hw/char/mcf_uart.c index 97e4bbc31adcc7c423be39aaa557793d550b2a6a..e6814faffb2a899a3921176370981b23ac07ccf4 100644 --- a/hw/char/mcf_uart.c +++ b/hw/char/mcf_uart.c @@ -10,11 +10,13 @@ #include "hw/irq.h" #include "hw/sysbus.h" #include "qemu/module.h" +#include "qapi/error.h" #include "hw/m68k/mcf.h" #include "hw/qdev-properties.h" #include "chardev/char-fe.h" +#include "qom/object.h" -typedef struct { +struct mcf_uart_state { SysBusDevice parent_obj; MemoryRegion iomem; @@ -32,10 +34,10 @@ typedef struct { int rx_enabled; qemu_irq irq; CharBackend chr; -} mcf_uart_state; +}; #define TYPE_MCF_UART "mcf-uart" -#define MCF_UART(obj) OBJECT_CHECK(mcf_uart_state, (obj), TYPE_MCF_UART) +OBJECT_DECLARE_SIMPLE_TYPE(mcf_uart_state, MCF_UART) /* UART Status Register bits. */ #define MCF_UART_RxRDY 0x01 @@ -343,11 +345,11 @@ void *mcf_uart_init(qemu_irq irq, Chardev *chrdrv) { DeviceState *dev; - dev = qdev_create(NULL, TYPE_MCF_UART); + dev = qdev_new(TYPE_MCF_UART); if (chrdrv) { qdev_prop_set_chr(dev, "chardev", chrdrv); } - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq); diff --git a/hw/char/mchp_pfsoc_mmuart.c b/hw/char/mchp_pfsoc_mmuart.c new file mode 100644 index 0000000000000000000000000000000000000000..8a002b0a19f5b74c6ad32d829ff9df9c0e1314c4 --- /dev/null +++ b/hw/char/mchp_pfsoc_mmuart.c @@ -0,0 +1,86 @@ +/* + * Microchip PolarFire SoC MMUART emulation + * + * Copyright (c) 2020 Wind River Systems, Inc. + * + * Author: + * Bin Meng + * + * 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 or + * (at your option) version 3 of the License. + * + * 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "chardev/char.h" +#include "exec/address-spaces.h" +#include "hw/char/mchp_pfsoc_mmuart.h" + +static uint64_t mchp_pfsoc_mmuart_read(void *opaque, hwaddr addr, unsigned size) +{ + MchpPfSoCMMUartState *s = opaque; + + if (addr >= MCHP_PFSOC_MMUART_REG_SIZE) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%" HWADDR_PRIx "\n", + __func__, addr); + return 0; + } + + return s->reg[addr / sizeof(uint32_t)]; +} + +static void mchp_pfsoc_mmuart_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + MchpPfSoCMMUartState *s = opaque; + uint32_t val32 = (uint32_t)value; + + if (addr >= MCHP_PFSOC_MMUART_REG_SIZE) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx + " v=0x%x\n", __func__, addr, val32); + return; + } + + s->reg[addr / sizeof(uint32_t)] = val32; +} + +static const MemoryRegionOps mchp_pfsoc_mmuart_ops = { + .read = mchp_pfsoc_mmuart_read, + .write = mchp_pfsoc_mmuart_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + +MchpPfSoCMMUartState *mchp_pfsoc_mmuart_create(MemoryRegion *sysmem, + hwaddr base, qemu_irq irq, Chardev *chr) +{ + MchpPfSoCMMUartState *s; + + s = g_new0(MchpPfSoCMMUartState, 1); + + memory_region_init_io(&s->iomem, NULL, &mchp_pfsoc_mmuart_ops, s, + "mchp.pfsoc.mmuart", 0x1000); + + s->base = base; + s->irq = irq; + + s->serial = serial_mm_init(sysmem, base, 2, irq, 399193, chr, + DEVICE_LITTLE_ENDIAN); + + memory_region_add_subregion(sysmem, base + 0x20, &s->iomem); + + return s; +} diff --git a/hw/char/meson.build b/hw/char/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..196ac91fa29ac93dc140b283fab70a150c498147 --- /dev/null +++ b/hw/char/meson.build @@ -0,0 +1,41 @@ +softmmu_ss.add(when: 'CONFIG_CADENCE', if_true: files('cadence_uart.c')) +softmmu_ss.add(when: 'CONFIG_CMSDK_APB_UART', if_true: files('cmsdk-apb-uart.c')) +softmmu_ss.add(when: 'CONFIG_ESCC', if_true: files('escc.c')) +softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_ser.c')) +softmmu_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_apbuart.c')) +softmmu_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_uart.c')) +softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_serial.c')) +softmmu_ss.add(when: 'CONFIG_IPACK', if_true: files('ipoctal232.c')) +softmmu_ss.add(when: 'CONFIG_ISA_BUS', if_true: files('parallel-isa.c')) +softmmu_ss.add(when: 'CONFIG_ISA_DEBUG', if_true: files('debugcon.c')) +softmmu_ss.add(when: 'CONFIG_LM32', if_true: files('lm32_juart.c')) +softmmu_ss.add(when: 'CONFIG_LM32', if_true: files('lm32_uart.c')) +softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-uart.c')) +softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_uart.c')) +softmmu_ss.add(when: 'CONFIG_PARALLEL', if_true: files('parallel.c')) +softmmu_ss.add(when: 'CONFIG_PL011', if_true: files('pl011.c')) +softmmu_ss.add(when: 'CONFIG_SCLPCONSOLE', if_true: files('sclpconsole.c', 'sclpconsole-lm.c')) +softmmu_ss.add(when: 'CONFIG_SERIAL', if_true: files('serial.c')) +softmmu_ss.add(when: 'CONFIG_SERIAL_ISA', if_true: files('serial-isa.c')) +softmmu_ss.add(when: 'CONFIG_SERIAL_PCI', if_true: files('serial-pci.c')) +softmmu_ss.add(when: 'CONFIG_SERIAL_PCI_MULTI', if_true: files('serial-pci-multi.c')) +softmmu_ss.add(when: 'CONFIG_VIRTIO_SERIAL', if_true: files('virtio-console.c')) +softmmu_ss.add(when: 'CONFIG_XEN', if_true: files('xen_console.c')) +softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_uartlite.c')) + +softmmu_ss.add(when: 'CONFIG_AVR_USART', if_true: files('avr_usart.c')) +softmmu_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_uart.c')) +softmmu_ss.add(when: 'CONFIG_DIGIC', if_true: files('digic-uart.c')) +softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_uart.c')) +softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_uart.c')) +softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_aux.c')) +softmmu_ss.add(when: 'CONFIG_RENESAS_SCI', if_true: files('renesas_sci.c')) +softmmu_ss.add(when: 'CONFIG_SIFIVE_UART', if_true: files('sifive_uart.c')) +softmmu_ss.add(when: 'CONFIG_SH4', if_true: files('sh_serial.c')) +softmmu_ss.add(when: 'CONFIG_STM32F2XX_USART', if_true: files('stm32f2xx_usart.c')) +softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_MMUART', if_true: files('mchp_pfsoc_mmuart.c')) + +specific_ss.add(when: 'CONFIG_HTIF', if_true: files('riscv_htif.c')) +specific_ss.add(when: 'CONFIG_TERMINAL3270', if_true: files('terminal3270.c')) +specific_ss.add(when: 'CONFIG_VIRTIO', if_true: files('virtio-serial-bus.c')) +specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_vty.c')) diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c index 1439efb42a852cbe9d3d38eaf980d13d084699cf..a817c51eb5db73c3a475d5478838ae45014496d8 100644 --- a/hw/char/milkymist-uart.c +++ b/hw/char/milkymist-uart.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -30,6 +30,7 @@ #include "chardev/char-fe.h" #include "qemu/error-report.h" #include "qemu/module.h" +#include "qom/object.h" enum { R_RXTX = 0, @@ -57,8 +58,7 @@ enum { }; #define TYPE_MILKYMIST_UART "milkymist-uart" -#define MILKYMIST_UART(obj) \ - OBJECT_CHECK(MilkymistUartState, (obj), TYPE_MILKYMIST_UART) +OBJECT_DECLARE_SIMPLE_TYPE(MilkymistUartState, MILKYMIST_UART) struct MilkymistUartState { SysBusDevice parent_obj; @@ -69,7 +69,6 @@ struct MilkymistUartState { uint32_t regs[R_MAX]; }; -typedef struct MilkymistUartState MilkymistUartState; static void uart_update_irq(MilkymistUartState *s) { diff --git a/hw/char/parallel-isa.c b/hw/char/parallel-isa.c index bcc577f61ccfc8c0b0881e6703c202169119326d..1ccbb96e7080c57dbfe8462c6e4a493bd2255bfc 100644 --- a/hw/char/parallel-isa.c +++ b/hw/char/parallel-isa.c @@ -14,17 +14,18 @@ #include "hw/isa/isa.h" #include "hw/qdev-properties.h" #include "hw/char/parallel.h" +#include "qapi/error.h" static void parallel_init(ISABus *bus, int index, Chardev *chr) { DeviceState *dev; ISADevice *isadev; - isadev = isa_create(bus, "isa-parallel"); + isadev = isa_new("isa-parallel"); dev = DEVICE(isadev); qdev_prop_set_uint32(dev, "index", index); qdev_prop_set_chr(dev, "chardev", chr); - qdev_init_nofail(dev); + isa_realize_and_unref(isadev, bus, &error_fatal); } void parallel_hds_isa_init(ISABus *bus, int n) diff --git a/hw/char/parallel.c b/hw/char/parallel.c index 8dd67d13759b03e0eab8cbb9224567ad223963da..8b418abf7199121a4f2c93e4c84367ffdea5d496 100644 --- a/hw/char/parallel.c +++ b/hw/char/parallel.c @@ -28,6 +28,7 @@ #include "qemu/module.h" #include "chardev/char-parallel.h" #include "chardev/char-fe.h" +#include "hw/acpi/aml-build.h" #include "hw/irq.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" @@ -36,6 +37,7 @@ #include "sysemu/reset.h" #include "sysemu/sysemu.h" #include "trace.h" +#include "qom/object.h" //#define DEBUG_PARALLEL @@ -91,17 +93,16 @@ typedef struct ParallelState { } ParallelState; #define TYPE_ISA_PARALLEL "isa-parallel" -#define ISA_PARALLEL(obj) \ - OBJECT_CHECK(ISAParallelState, (obj), TYPE_ISA_PARALLEL) +OBJECT_DECLARE_SIMPLE_TYPE(ISAParallelState, ISA_PARALLEL) -typedef struct ISAParallelState { +struct ISAParallelState { ISADevice parent_obj; uint32_t index; uint32_t iobase; uint32_t isairq; ParallelState state; -} ISAParallelState; +}; static void parallel_update_irq(ParallelState *s) { @@ -568,6 +569,25 @@ static void parallel_isa_realizefn(DeviceState *dev, Error **errp) s, "parallel"); } +static void parallel_isa_build_aml(ISADevice *isadev, Aml *scope) +{ + ISAParallelState *isa = ISA_PARALLEL(isadev); + Aml *dev; + Aml *crs; + + crs = aml_resource_template(); + aml_append(crs, aml_io(AML_DECODE16, isa->iobase, isa->iobase, 0x08, 0x08)); + aml_append(crs, aml_irq_no_flags(isa->isairq)); + + dev = aml_device("LPT%d", isa->index + 1); + aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0400"))); + aml_append(dev, aml_name_decl("_UID", aml_int(isa->index + 1))); + aml_append(dev, aml_name_decl("_STA", aml_int(0xf))); + aml_append(dev, aml_name_decl("_CRS", crs)); + + aml_append(scope, dev); +} + /* Memory mapped interface */ static uint64_t parallel_mm_readfn(void *opaque, hwaddr addr, unsigned size) { @@ -624,9 +644,11 @@ static Property parallel_isa_properties[] = { static void parallel_isa_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *isa = ISA_DEVICE_CLASS(klass); dc->realize = parallel_isa_realizefn; dc->vmsd = &vmstate_parallel_isa; + isa->build_aml = parallel_isa_build_aml; device_class_set_props(dc, parallel_isa_properties); set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } diff --git a/hw/char/pl011.c b/hw/char/pl011.c index 13e784f9d90b5fd55057ff95046aee116aff36ca..ede16c781c9abcbeaf3ffb8f5c73ca0d2b5d8e9d 100644 --- a/hw/char/pl011.c +++ b/hw/char/pl011.c @@ -22,6 +22,7 @@ #include "hw/char/pl011.h" #include "hw/irq.h" #include "hw/sysbus.h" +#include "hw/qdev-clock.h" #include "migration/vmstate.h" #include "chardev/char-fe.h" #include "qemu/log.h" @@ -169,6 +170,25 @@ static void pl011_set_read_trigger(PL011State *s) s->read_trigger = 1; } +static unsigned int pl011_get_baudrate(const PL011State *s) +{ + uint64_t clk; + + if (s->fbrd == 0) { + return 0; + } + + clk = clock_get_hz(s->clk); + return (clk / ((s->ibrd << 6) + s->fbrd)) << 2; +} + +static void pl011_trace_baudrate_change(const PL011State *s) +{ + trace_pl011_baudrate_change(pl011_get_baudrate(s), + clock_get_hz(s->clk), + s->ibrd, s->fbrd); +} + static void pl011_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { @@ -198,9 +218,11 @@ static void pl011_write(void *opaque, hwaddr offset, break; case 9: /* UARTIBRD */ s->ibrd = value; + pl011_trace_baudrate_change(s); break; case 10: /* UARTFBRD */ s->fbrd = value; + pl011_trace_baudrate_change(s); break; case 11: /* UARTLCR_H */ /* Reset the FIFO state on FIFO enable or disable */ @@ -286,12 +308,29 @@ static void pl011_event(void *opaque, QEMUChrEvent event) pl011_put_fifo(opaque, 0x400); } +static void pl011_clock_update(void *opaque) +{ + PL011State *s = PL011(opaque); + + pl011_trace_baudrate_change(s); +} + static const MemoryRegionOps pl011_ops = { .read = pl011_read, .write = pl011_write, .endianness = DEVICE_NATIVE_ENDIAN, }; +static const VMStateDescription vmstate_pl011_clock = { + .name = "pl011/clock", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_CLOCK(clk, PL011State), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_pl011 = { .name = "pl011", .version_id = 2, @@ -314,6 +353,10 @@ static const VMStateDescription vmstate_pl011 = { VMSTATE_INT32(read_count, PL011State), VMSTATE_INT32(read_trigger, PL011State), VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription * []) { + &vmstate_pl011_clock, + NULL } }; @@ -334,6 +377,8 @@ static void pl011_init(Object *obj) sysbus_init_irq(sbd, &s->irq[i]); } + s->clk = qdev_init_clock_in(DEVICE(obj), "clk", pl011_clock_update, s); + s->read_trigger = 1; s->ifl = 0x12; s->cr = 0x300; diff --git a/hw/char/renesas_sci.c b/hw/char/renesas_sci.c new file mode 100644 index 0000000000000000000000000000000000000000..5d7c6e6523cd371e27968a8f380aaa99e35fd631 --- /dev/null +++ b/hw/char/renesas_sci.c @@ -0,0 +1,350 @@ +/* + * Renesas Serial Communication Interface + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * + * Copyright (c) 2019 Yoshinori Sato + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "hw/irq.h" +#include "hw/registerfields.h" +#include "hw/qdev-properties.h" +#include "hw/char/renesas_sci.h" +#include "migration/vmstate.h" + +/* SCI register map */ +REG8(SMR, 0) + FIELD(SMR, CKS, 0, 2) + FIELD(SMR, MP, 2, 1) + FIELD(SMR, STOP, 3, 1) + FIELD(SMR, PM, 4, 1) + FIELD(SMR, PE, 5, 1) + FIELD(SMR, CHR, 6, 1) + FIELD(SMR, CM, 7, 1) +REG8(BRR, 1) +REG8(SCR, 2) + FIELD(SCR, CKE, 0, 2) + FIELD(SCR, TEIE, 2, 1) + FIELD(SCR, MPIE, 3, 1) + FIELD(SCR, RE, 4, 1) + FIELD(SCR, TE, 5, 1) + FIELD(SCR, RIE, 6, 1) + FIELD(SCR, TIE, 7, 1) +REG8(TDR, 3) +REG8(SSR, 4) + FIELD(SSR, MPBT, 0, 1) + FIELD(SSR, MPB, 1, 1) + FIELD(SSR, TEND, 2, 1) + FIELD(SSR, ERR, 3, 3) + FIELD(SSR, PER, 3, 1) + FIELD(SSR, FER, 4, 1) + FIELD(SSR, ORER, 5, 1) + FIELD(SSR, RDRF, 6, 1) + FIELD(SSR, TDRE, 7, 1) +REG8(RDR, 5) +REG8(SCMR, 6) + FIELD(SCMR, SMIF, 0, 1) + FIELD(SCMR, SINV, 2, 1) + FIELD(SCMR, SDIR, 3, 1) + FIELD(SCMR, BCP2, 7, 1) +REG8(SEMR, 7) + FIELD(SEMR, ACS0, 0, 1) + FIELD(SEMR, ABCS, 4, 1) + +static int can_receive(void *opaque) +{ + RSCIState *sci = RSCI(opaque); + if (sci->rx_next > qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) { + return 0; + } else { + return FIELD_EX8(sci->scr, SCR, RE); + } +} + +static void receive(void *opaque, const uint8_t *buf, int size) +{ + RSCIState *sci = RSCI(opaque); + sci->rx_next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + sci->trtime; + if (FIELD_EX8(sci->ssr, SSR, RDRF) || size > 1) { + sci->ssr = FIELD_DP8(sci->ssr, SSR, ORER, 1); + if (FIELD_EX8(sci->scr, SCR, RIE)) { + qemu_set_irq(sci->irq[ERI], 1); + } + } else { + sci->rdr = buf[0]; + sci->ssr = FIELD_DP8(sci->ssr, SSR, RDRF, 1); + if (FIELD_EX8(sci->scr, SCR, RIE)) { + qemu_irq_pulse(sci->irq[RXI]); + } + } +} + +static void send_byte(RSCIState *sci) +{ + if (qemu_chr_fe_backend_connected(&sci->chr)) { + qemu_chr_fe_write_all(&sci->chr, &sci->tdr, 1); + } + timer_mod(&sci->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + sci->trtime); + sci->ssr = FIELD_DP8(sci->ssr, SSR, TEND, 0); + sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 1); + qemu_set_irq(sci->irq[TEI], 0); + if (FIELD_EX8(sci->scr, SCR, TIE)) { + qemu_irq_pulse(sci->irq[TXI]); + } +} + +static void txend(void *opaque) +{ + RSCIState *sci = RSCI(opaque); + if (!FIELD_EX8(sci->ssr, SSR, TDRE)) { + send_byte(sci); + } else { + sci->ssr = FIELD_DP8(sci->ssr, SSR, TEND, 1); + if (FIELD_EX8(sci->scr, SCR, TEIE)) { + qemu_set_irq(sci->irq[TEI], 1); + } + } +} + +static void update_trtime(RSCIState *sci) +{ + /* char per bits */ + sci->trtime = 8 - FIELD_EX8(sci->smr, SMR, CHR); + sci->trtime += FIELD_EX8(sci->smr, SMR, PE); + sci->trtime += FIELD_EX8(sci->smr, SMR, STOP) + 1; + /* x bit transmit time (32 * divrate * brr) / base freq */ + sci->trtime *= 32 * sci->brr; + sci->trtime *= 1 << (2 * FIELD_EX8(sci->smr, SMR, CKS)); + sci->trtime *= NANOSECONDS_PER_SECOND; + sci->trtime /= sci->input_freq; +} + +static bool sci_is_tr_enabled(RSCIState *sci) +{ + return FIELD_EX8(sci->scr, SCR, TE) || FIELD_EX8(sci->scr, SCR, RE); +} + +static void sci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) +{ + RSCIState *sci = RSCI(opaque); + + switch (offset) { + case A_SMR: + if (!sci_is_tr_enabled(sci)) { + sci->smr = val; + update_trtime(sci); + } + break; + case A_BRR: + if (!sci_is_tr_enabled(sci)) { + sci->brr = val; + update_trtime(sci); + } + break; + case A_SCR: + sci->scr = val; + if (FIELD_EX8(sci->scr, SCR, TE)) { + sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 1); + sci->ssr = FIELD_DP8(sci->ssr, SSR, TEND, 1); + if (FIELD_EX8(sci->scr, SCR, TIE)) { + qemu_irq_pulse(sci->irq[TXI]); + } + } + if (!FIELD_EX8(sci->scr, SCR, TEIE)) { + qemu_set_irq(sci->irq[TEI], 0); + } + if (!FIELD_EX8(sci->scr, SCR, RIE)) { + qemu_set_irq(sci->irq[ERI], 0); + } + break; + case A_TDR: + sci->tdr = val; + if (FIELD_EX8(sci->ssr, SSR, TEND)) { + send_byte(sci); + } else { + sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 0); + } + break; + case A_SSR: + sci->ssr = FIELD_DP8(sci->ssr, SSR, MPBT, + FIELD_EX8(val, SSR, MPBT)); + sci->ssr = FIELD_DP8(sci->ssr, SSR, ERR, + FIELD_EX8(val, SSR, ERR) & 0x07); + if (FIELD_EX8(sci->read_ssr, SSR, ERR) && + FIELD_EX8(sci->ssr, SSR, ERR) == 0) { + qemu_set_irq(sci->irq[ERI], 0); + } + break; + case A_RDR: + qemu_log_mask(LOG_GUEST_ERROR, "reneas_sci: RDR is read only.\n"); + break; + case A_SCMR: + sci->scmr = val; break; + case A_SEMR: /* SEMR */ + sci->semr = val; break; + default: + qemu_log_mask(LOG_UNIMP, "renesas_sci: Register 0x%" HWADDR_PRIX " " + "not implemented\n", + offset); + } +} + +static uint64_t sci_read(void *opaque, hwaddr offset, unsigned size) +{ + RSCIState *sci = RSCI(opaque); + + switch (offset) { + case A_SMR: + return sci->smr; + case A_BRR: + return sci->brr; + case A_SCR: + return sci->scr; + case A_TDR: + return sci->tdr; + case A_SSR: + sci->read_ssr = sci->ssr; + return sci->ssr; + case A_RDR: + sci->ssr = FIELD_DP8(sci->ssr, SSR, RDRF, 0); + return sci->rdr; + case A_SCMR: + return sci->scmr; + case A_SEMR: + return sci->semr; + default: + qemu_log_mask(LOG_UNIMP, "renesas_sci: Register 0x%" HWADDR_PRIX + " not implemented.\n", offset); + } + return UINT64_MAX; +} + +static const MemoryRegionOps sci_ops = { + .write = sci_write, + .read = sci_read, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl.max_access_size = 1, + .valid.max_access_size = 1, +}; + +static void rsci_reset(DeviceState *dev) +{ + RSCIState *sci = RSCI(dev); + sci->smr = sci->scr = 0x00; + sci->brr = 0xff; + sci->tdr = 0xff; + sci->rdr = 0x00; + sci->ssr = 0x84; + sci->scmr = 0x00; + sci->semr = 0x00; + sci->rx_next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +} + +static void sci_event(void *opaque, QEMUChrEvent event) +{ + RSCIState *sci = RSCI(opaque); + if (event == CHR_EVENT_BREAK) { + sci->ssr = FIELD_DP8(sci->ssr, SSR, FER, 1); + if (FIELD_EX8(sci->scr, SCR, RIE)) { + qemu_set_irq(sci->irq[ERI], 1); + } + } +} + +static void rsci_realize(DeviceState *dev, Error **errp) +{ + RSCIState *sci = RSCI(dev); + + if (sci->input_freq == 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "renesas_sci: input-freq property must be set."); + return; + } + qemu_chr_fe_set_handlers(&sci->chr, can_receive, receive, + sci_event, NULL, sci, NULL, true); +} + +static void rsci_init(Object *obj) +{ + SysBusDevice *d = SYS_BUS_DEVICE(obj); + RSCIState *sci = RSCI(obj); + int i; + + memory_region_init_io(&sci->memory, OBJECT(sci), &sci_ops, + sci, "renesas-sci", 0x8); + sysbus_init_mmio(d, &sci->memory); + + for (i = 0; i < SCI_NR_IRQ; i++) { + sysbus_init_irq(d, &sci->irq[i]); + } + timer_init_ns(&sci->timer, QEMU_CLOCK_VIRTUAL, txend, sci); +} + +static const VMStateDescription vmstate_rsci = { + .name = "renesas-sci", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_INT64(trtime, RSCIState), + VMSTATE_INT64(rx_next, RSCIState), + VMSTATE_UINT8(smr, RSCIState), + VMSTATE_UINT8(brr, RSCIState), + VMSTATE_UINT8(scr, RSCIState), + VMSTATE_UINT8(tdr, RSCIState), + VMSTATE_UINT8(ssr, RSCIState), + VMSTATE_UINT8(rdr, RSCIState), + VMSTATE_UINT8(scmr, RSCIState), + VMSTATE_UINT8(semr, RSCIState), + VMSTATE_UINT8(read_ssr, RSCIState), + VMSTATE_TIMER(timer, RSCIState), + VMSTATE_END_OF_LIST() + } +}; + +static Property rsci_properties[] = { + DEFINE_PROP_UINT64("input-freq", RSCIState, input_freq, 0), + DEFINE_PROP_CHR("chardev", RSCIState, chr), + DEFINE_PROP_END_OF_LIST(), +}; + +static void rsci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = rsci_realize; + dc->vmsd = &vmstate_rsci; + dc->reset = rsci_reset; + device_class_set_props(dc, rsci_properties); +} + +static const TypeInfo rsci_info = { + .name = TYPE_RENESAS_SCI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(RSCIState), + .instance_init = rsci_init, + .class_init = rsci_class_init, +}; + +static void rsci_register_types(void) +{ + type_register_static(&rsci_info); +} + +type_init(rsci_register_types) diff --git a/hw/riscv/riscv_htif.c b/hw/char/riscv_htif.c similarity index 99% rename from hw/riscv/riscv_htif.c rename to hw/char/riscv_htif.c index ca87a5cf9f86b210446456c30ef30de2418e7f7f..ba1af1cfc450891ffcad2b684d61a26da1807dc8 100644 --- a/hw/riscv/riscv_htif.c +++ b/hw/char/riscv_htif.c @@ -24,10 +24,10 @@ #include "qapi/error.h" #include "qemu/log.h" #include "hw/sysbus.h" +#include "hw/char/riscv_htif.h" #include "hw/char/serial.h" #include "chardev/char.h" #include "chardev/char-fe.h" -#include "hw/riscv/riscv_htif.h" #include "qemu/timer.h" #include "qemu/error-report.h" diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c index 2b5f37b6a2a12e8c80e7f2f5289efc2e6cf3889f..81f6d0ed4f903ec4203f5b691bbb88a028d5d249 100644 --- a/hw/char/sclpconsole-lm.c +++ b/hw/char/sclpconsole-lm.c @@ -24,6 +24,7 @@ #include "hw/s390x/event-facility.h" #include "hw/qdev-properties.h" #include "hw/s390x/ebcdic.h" +#include "qom/object.h" #define SIZE_BUFFER 4096 #define NEWLINE "\n" @@ -37,18 +38,19 @@ typedef struct OprtnsCommand { /* max size for line-mode data in 4K SCCB page */ #define SIZE_CONSOLE_BUFFER (SCCB_DATA_LEN - sizeof(OprtnsCommand)) -typedef struct SCLPConsoleLM { +struct SCLPConsoleLM { SCLPEvent event; CharBackend chr; bool echo; /* immediate echo of input if true */ uint32_t write_errors; /* errors writing to char layer */ uint32_t length; /* length of byte stream in buffer */ uint8_t buf[SIZE_CONSOLE_BUFFER]; -} SCLPConsoleLM; +}; +typedef struct SCLPConsoleLM SCLPConsoleLM; #define TYPE_SCLPLM_CONSOLE "sclplmconsole" -#define SCLPLM_CONSOLE(obj) \ - OBJECT_CHECK(SCLPConsoleLM, (obj), TYPE_SCLPLM_CONSOLE) +DECLARE_INSTANCE_CHECKER(SCLPConsoleLM, SCLPLM_CONSOLE, + TYPE_SCLPLM_CONSOLE) /* * Character layer call-back functions @@ -355,7 +357,7 @@ static void console_class_init(ObjectClass *klass, void *data) } static const TypeInfo sclp_console_info = { - .name = "sclplmconsole", + .name = TYPE_SCLPLM_CONSOLE, .parent = TYPE_SCLP_EVENT, .instance_size = sizeof(SCLPConsoleLM), .class_init = console_class_init, diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c index 5c7664905e479f159ffe384f0e59135f106da801..aa72ab40b92cc74c4c6464426bc698f846cf6aed 100644 --- a/hw/char/sclpconsole.c +++ b/hw/char/sclpconsole.c @@ -22,6 +22,7 @@ #include "hw/qdev-properties.h" #include "hw/s390x/event-facility.h" #include "chardev/char-fe.h" +#include "qom/object.h" typedef struct ASCIIConsoleData { EventBufferHeader ebh; @@ -31,7 +32,7 @@ typedef struct ASCIIConsoleData { /* max size for ASCII data in 4K SCCB page */ #define SIZE_BUFFER_VT220 4080 -typedef struct SCLPConsole { +struct SCLPConsole { SCLPEvent event; CharBackend chr; uint8_t iov[SIZE_BUFFER_VT220]; @@ -40,11 +41,12 @@ typedef struct SCLPConsole { uint32_t iov_data_len; /* length of byte stream in buffer */ uint32_t iov_sclp_rest; /* length of byte stream not read via SCLP */ bool notify; /* qemu_notify_event() req'd if true */ -} SCLPConsole; +}; +typedef struct SCLPConsole SCLPConsole; #define TYPE_SCLP_CONSOLE "sclpconsole" -#define SCLP_CONSOLE(obj) \ - OBJECT_CHECK(SCLPConsole, (obj), TYPE_SCLP_CONSOLE) +DECLARE_INSTANCE_CHECKER(SCLPConsole, SCLP_CONSOLE, + TYPE_SCLP_CONSOLE) /* character layer call-back functions */ @@ -271,7 +273,7 @@ static void console_class_init(ObjectClass *klass, void *data) } static const TypeInfo sclp_console_info = { - .name = "sclpconsole", + .name = TYPE_SCLP_CONSOLE, .parent = TYPE_SCLP_EVENT, .instance_size = sizeof(SCLPConsole), .class_init = console_class_init, diff --git a/hw/char/serial-isa.c b/hw/char/serial-isa.c index f9b6eed7833d688919ca3c6f77a81518a0e7a0b7..1b8b303079611fedd2517ffab95be42daaa64079 100644 --- a/hw/char/serial-isa.c +++ b/hw/char/serial-isa.c @@ -27,21 +27,23 @@ #include "qapi/error.h" #include "qemu/module.h" #include "sysemu/sysemu.h" +#include "hw/acpi/aml-build.h" #include "hw/char/serial.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" +#include "qom/object.h" -#define ISA_SERIAL(obj) OBJECT_CHECK(ISASerialState, (obj), TYPE_ISA_SERIAL) +OBJECT_DECLARE_SIMPLE_TYPE(ISASerialState, ISA_SERIAL) -typedef struct ISASerialState { +struct ISASerialState { ISADevice parent_obj; uint32_t index; uint32_t iobase; uint32_t isairq; SerialState state; -} ISASerialState; +}; static const int isa_serial_io[MAX_ISA_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 @@ -74,13 +76,32 @@ static void serial_isa_realizefn(DeviceState *dev, Error **errp) index++; isa_init_irq(isadev, &s->irq, isa->isairq); - object_property_set_bool(OBJECT(s), true, "realized", errp); + qdev_realize(DEVICE(s), NULL, errp); qdev_set_legacy_instance_id(dev, isa->iobase, 3); memory_region_init_io(&s->io, OBJECT(isa), &serial_io_ops, s, "serial", 8); isa_register_ioport(isadev, &s->io, isa->iobase); } +static void serial_isa_build_aml(ISADevice *isadev, Aml *scope) +{ + ISASerialState *isa = ISA_SERIAL(isadev); + Aml *dev; + Aml *crs; + + crs = aml_resource_template(); + aml_append(crs, aml_io(AML_DECODE16, isa->iobase, isa->iobase, 0x00, 0x08)); + aml_append(crs, aml_irq_no_flags(isa->isairq)); + + dev = aml_device("COM%d", isa->index + 1); + aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0501"))); + aml_append(dev, aml_name_decl("_UID", aml_int(isa->index + 1))); + aml_append(dev, aml_name_decl("_STA", aml_int(0xf))); + aml_append(dev, aml_name_decl("_CRS", crs)); + + aml_append(scope, dev); +} + static const VMStateDescription vmstate_isa_serial = { .name = "serial", .version_id = 3, @@ -95,17 +116,17 @@ static Property serial_isa_properties[] = { DEFINE_PROP_UINT32("index", ISASerialState, index, -1), DEFINE_PROP_UINT32("iobase", ISASerialState, iobase, -1), DEFINE_PROP_UINT32("irq", ISASerialState, isairq, -1), - DEFINE_PROP_CHR("chardev", ISASerialState, state.chr), - DEFINE_PROP_UINT32("wakeup", ISASerialState, state.wakeup, 0), DEFINE_PROP_END_OF_LIST(), }; static void serial_isa_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *isa = ISA_DEVICE_CLASS(klass); dc->realize = serial_isa_realizefn; dc->vmsd = &vmstate_isa_serial; + isa->build_aml = serial_isa_build_aml; device_class_set_props(dc, serial_isa_properties); set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } @@ -114,8 +135,9 @@ static void serial_isa_initfn(Object *o) { ISASerialState *self = ISA_SERIAL(o); - object_initialize_child(o, "serial", &self->state, sizeof(self->state), - TYPE_SERIAL, &error_abort, NULL); + object_initialize_child(o, "serial", &self->state, TYPE_SERIAL); + + qdev_alias_all_properties(DEVICE(&self->state), o); } static const TypeInfo serial_isa_info = { @@ -138,11 +160,11 @@ static void serial_isa_init(ISABus *bus, int index, Chardev *chr) DeviceState *dev; ISADevice *isadev; - isadev = isa_create(bus, TYPE_ISA_SERIAL); + isadev = isa_new(TYPE_ISA_SERIAL); dev = DEVICE(isadev); qdev_prop_set_uint32(dev, "index", index); qdev_prop_set_chr(dev, "chardev", chr); - qdev_init_nofail(dev); + isa_realize_and_unref(isadev, bus, &error_fatal); } void serial_hds_isa_init(ISABus *bus, int from, int to) diff --git a/hw/char/serial-pci-multi.c b/hw/char/serial-pci-multi.c index 5f9ccfcc935b4294a6bed09b92e4a7e68bdc0412..2cf3e441773401d0233e56ddb52092b63b448855 100644 --- a/hw/char/serial-pci-multi.c +++ b/hw/char/serial-pci-multi.c @@ -56,7 +56,7 @@ static void multi_serial_pci_exit(PCIDevice *dev) for (i = 0; i < pci->ports; i++) { s = pci->state + i; - object_property_set_bool(OBJECT(s), false, "realized", &error_abort); + qdev_unrealize(DEVICE(s)); memory_region_del_subregion(&pci->iobar, &s->io); g_free(pci->name[i]); } @@ -95,7 +95,6 @@ static void multi_serial_pci_realize(PCIDevice *dev, Error **errp) PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); PCIMultiSerialState *pci = DO_UPCAST(PCIMultiSerialState, dev, dev); SerialState *s; - Error *err = NULL; size_t i, nports = multi_serial_get_port_count(pc); pci->dev.config[PCI_CLASS_PROG] = pci->prog_if; @@ -106,9 +105,7 @@ static void multi_serial_pci_realize(PCIDevice *dev, Error **errp) for (i = 0; i < nports; i++) { s = pci->state + i; - object_property_set_bool(OBJECT(s), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(s), NULL, errp)) { multi_serial_pci_exit(dev); return; } @@ -187,9 +184,7 @@ static void multi_serial_init(Object *o) size_t i, nports = multi_serial_get_port_count(PCI_DEVICE_GET_CLASS(dev)); for (i = 0; i < nports; i++) { - object_initialize_child(o, "serial[*]", &pms->state[i], - sizeof(pms->state[i]), - TYPE_SERIAL, &error_abort, NULL); + object_initialize_child(o, "serial[*]", &pms->state[i], TYPE_SERIAL); } } diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c index 37818db156c01fbe43dbd0512ab6f35f35e91669..93d6f9924425cb18ab08615ad2641ad759ac6e4e 100644 --- a/hw/char/serial-pci.c +++ b/hw/char/serial-pci.c @@ -33,25 +33,23 @@ #include "hw/pci/pci.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" +#include "qom/object.h" -typedef struct PCISerialState { +struct PCISerialState { PCIDevice dev; SerialState state; uint8_t prog_if; -} PCISerialState; +}; #define TYPE_PCI_SERIAL "pci-serial" -#define PCI_SERIAL(s) OBJECT_CHECK(PCISerialState, (s), TYPE_PCI_SERIAL) +OBJECT_DECLARE_SIMPLE_TYPE(PCISerialState, PCI_SERIAL) static void serial_pci_realize(PCIDevice *dev, Error **errp) { PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev); SerialState *s = &pci->state; - Error *err = NULL; - object_property_set_bool(OBJECT(s), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(s), NULL, errp)) { return; } @@ -68,7 +66,7 @@ static void serial_pci_exit(PCIDevice *dev) PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev); SerialState *s = &pci->state; - object_property_set_bool(OBJECT(s), false, "realized", &error_abort); + qdev_unrealize(DEVICE(s)); qemu_free_irq(s->irq); } @@ -84,7 +82,6 @@ static const VMStateDescription vmstate_pci_serial = { }; static Property serial_pci_properties[] = { - DEFINE_PROP_CHR("chardev", PCISerialState, state.chr), DEFINE_PROP_UINT8("prog_if", PCISerialState, prog_if, 0x02), DEFINE_PROP_END_OF_LIST(), }; @@ -108,8 +105,9 @@ static void serial_pci_init(Object *o) { PCISerialState *ps = PCI_SERIAL(o); - object_initialize_child(o, "serial", &ps->state, sizeof(ps->state), - TYPE_SERIAL, &error_abort, NULL); + object_initialize_child(o, "serial", &ps->state, TYPE_SERIAL); + + qdev_alias_all_properties(DEVICE(&ps->state), o); } static const TypeInfo serial_pci_info = { diff --git a/hw/char/serial.c b/hw/char/serial.c index 7d746945877697b7807acc95fe132c53755c9d6e..97f71879ff2ac89225f74f3d594f2bcfd9f0dc60 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -36,8 +36,6 @@ #include "trace.h" #include "hw/qdev-properties.h" -//#define DEBUG_SERIAL - #define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ #define UART_IER_MSI 0x08 /* Enable Modem status interrupt */ @@ -102,14 +100,6 @@ #define MAX_XMIT_RETRY 4 -#ifdef DEBUG_SERIAL -#define DPRINTF(fmt, ...) \ -do { fprintf(stderr, "serial: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) \ -do {} while (0) -#endif - static void serial_receive1(void *opaque, const uint8_t *buf, int size); static void serial_xmit(SerialState *s); @@ -187,9 +177,7 @@ static void serial_update_parameters(SerialState *s) ssp.stop_bits = stop_bits; s->char_transmit_time = (NANOSECONDS_PER_SECOND / speed) * frame_size; qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp); - - DPRINTF("speed=%.2f parity=%c data=%d stop=%d\n", - speed, parity, data_bits, stop_bits); + trace_serial_update_parameters(speed, parity, data_bits, stop_bits); } static void serial_update_msl(SerialState *s) @@ -344,8 +332,8 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, { SerialState *s = opaque; - addr &= 7; - trace_serial_ioport_write(addr, val); + assert(size == 1 && addr < 8); + trace_serial_write(addr, val); switch(addr) { default: case 0: @@ -485,7 +473,7 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size) SerialState *s = opaque; uint32_t ret; - addr &= 7; + assert(size == 1 && addr < 8); switch(addr) { default: case 0: @@ -562,7 +550,7 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size) ret = s->scr; break; } - trace_serial_ioport_read(addr, ret); + trace_serial_read(addr, ret); return ret; } @@ -638,7 +626,6 @@ static void serial_receive1(void *opaque, const uint8_t *buf, int size) static void serial_event(void *opaque, QEMUChrEvent event) { SerialState *s = opaque; - DPRINTF("event %x\n", event); if (event == CHR_EVENT_BREAK) serial_receive_break(s); } @@ -985,53 +972,10 @@ const MemoryRegionOps serial_io_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static void serial_io_realize(DeviceState *dev, Error **errp) -{ - SerialIO *sio = SERIAL_IO(dev); - SerialState *s = &sio->serial; - Error *local_err = NULL; - - object_property_set_bool(OBJECT(s), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - - memory_region_init_io(&s->io, OBJECT(dev), &serial_io_ops, s, "serial", 8); - sysbus_init_mmio(SYS_BUS_DEVICE(sio), &s->io); - sysbus_init_irq(SYS_BUS_DEVICE(sio), &s->irq); -} - -static void serial_io_class_init(ObjectClass *klass, void* data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = serial_io_realize; - /* No dc->vmsd: class has no migratable state */ -} - -static void serial_io_instance_init(Object *o) -{ - SerialIO *sio = SERIAL_IO(o); - - object_initialize_child(o, "serial", &sio->serial, sizeof(sio->serial), - TYPE_SERIAL, &error_abort, NULL); - - qdev_alias_all_properties(DEVICE(&sio->serial), o); -} - - -static const TypeInfo serial_io_info = { - .name = TYPE_SERIAL_IO, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SerialIO), - .instance_init = serial_io_instance_init, - .class_init = serial_io_class_init, -}; - static Property serial_properties[] = { DEFINE_PROP_CHR("chardev", SerialState, chr), DEFINE_PROP_UINT32("baudbase", SerialState, baudbase, 115200), + DEFINE_PROP_BOOL("wakeup", SerialState, wakeup, false), DEFINE_PROP_END_OF_LIST(), }; @@ -1097,11 +1041,8 @@ static void serial_mm_realize(DeviceState *dev, Error **errp) { SerialMM *smm = SERIAL_MM(dev); SerialState *s = &smm->serial; - Error *local_err = NULL; - object_property_set_bool(OBJECT(s), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qdev_realize(DEVICE(s), NULL, errp)) { return; } @@ -1127,7 +1068,7 @@ SerialMM *serial_mm_init(MemoryRegion *address_space, qemu_irq irq, int baudbase, Chardev *chr, enum device_endian end) { - SerialMM *smm = SERIAL_MM(qdev_create(NULL, TYPE_SERIAL_MM)); + SerialMM *smm = SERIAL_MM(qdev_new(TYPE_SERIAL_MM)); MemoryRegion *mr; qdev_prop_set_uint8(DEVICE(smm), "regshift", regshift); @@ -1135,7 +1076,7 @@ SerialMM *serial_mm_init(MemoryRegion *address_space, qdev_prop_set_chr(DEVICE(smm), "chardev", chr); qdev_set_legacy_instance_id(DEVICE(smm), base, 2); qdev_prop_set_uint8(DEVICE(smm), "endianness", end); - qdev_init_nofail(DEVICE(smm)); + sysbus_realize_and_unref(SYS_BUS_DEVICE(smm), &error_fatal); sysbus_connect_irq(SYS_BUS_DEVICE(smm), 0, irq); mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(smm), 0); @@ -1148,8 +1089,7 @@ static void serial_mm_instance_init(Object *o) { SerialMM *smm = SERIAL_MM(o); - object_initialize_child(o, "serial", &smm->serial, sizeof(smm->serial), - TYPE_SERIAL, &error_abort, NULL); + object_initialize_child(o, "serial", &smm->serial, TYPE_SERIAL); qdev_alias_all_properties(DEVICE(&smm->serial), o); } @@ -1180,13 +1120,11 @@ static const TypeInfo serial_mm_info = { .class_init = serial_mm_class_init, .instance_init = serial_mm_instance_init, .instance_size = sizeof(SerialMM), - .class_init = serial_mm_class_init, }; static void serial_register_types(void) { type_register_static(&serial_info); - type_register_static(&serial_io_info); type_register_static(&serial_mm_info); } diff --git a/hw/riscv/sifive_uart.c b/hw/char/sifive_uart.c similarity index 99% rename from hw/riscv/sifive_uart.c rename to hw/char/sifive_uart.c index 93504826626ecaced1496263e9aa44a0b8efd642..3a00ba7f006cadb3b1520c257cc425be18afd82e 100644 --- a/hw/riscv/sifive_uart.c +++ b/hw/char/sifive_uart.c @@ -24,7 +24,7 @@ #include "chardev/char-fe.h" #include "hw/hw.h" #include "hw/irq.h" -#include "hw/riscv/sifive_uart.h" +#include "hw/char/sifive_uart.h" /* * Not yet implemented: diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c index ecb94f5673ca978f38f093f2b53e8315fd46d9aa..e726d4d91557ee37aeaab9a73554f1119baf97bd 100644 --- a/hw/char/spapr_vty.c +++ b/hw/char/spapr_vty.c @@ -8,19 +8,19 @@ #include "hw/ppc/spapr.h" #include "hw/ppc/spapr_vio.h" #include "hw/qdev-properties.h" +#include "qom/object.h" #define VTERM_BUFSIZE 16 -typedef struct SpaprVioVty { +struct SpaprVioVty { SpaprVioDevice sdev; CharBackend chardev; uint32_t in, out; uint8_t buf[VTERM_BUFSIZE]; -} SpaprVioVty; +}; #define TYPE_VIO_SPAPR_VTY_DEVICE "spapr-vty" -#define VIO_SPAPR_VTY_DEVICE(obj) \ - OBJECT_CHECK(SpaprVioVty, (obj), TYPE_VIO_SPAPR_VTY_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(SpaprVioVty, VIO_SPAPR_VTY_DEVICE) static int vty_can_receive(void *opaque) { @@ -158,9 +158,9 @@ void spapr_vty_create(SpaprVioBus *bus, Chardev *chardev) { DeviceState *dev; - dev = qdev_create(&bus->bus, "spapr-vty"); + dev = qdev_new("spapr-vty"); qdev_prop_set_chr(dev, "chardev", chardev); - qdev_init_nofail(dev); + qdev_realize_and_unref(dev, &bus->bus, &error_fatal); } static Property spapr_vty_properties[] = { diff --git a/hw/char/terminal3270.c b/hw/char/terminal3270.c index 2c47ebf0076d0c36e0b167c523d099d5260e7284..d77981bb6d52a2af651bfa2b6ecbd454cf76a085 100644 --- a/hw/char/terminal3270.c +++ b/hw/char/terminal3270.c @@ -17,6 +17,7 @@ #include "chardev/char-fe.h" #include "hw/qdev-properties.h" #include "hw/s390x/3270-ccw.h" +#include "qom/object.h" /* Enough spaces for different window sizes. */ #define INPUT_BUFFER_SIZE 1000 @@ -26,7 +27,7 @@ */ #define OUTPUT_BUFFER_SIZE 2051 -typedef struct Terminal3270 { +struct Terminal3270 { EmulatedCcw3270Device cdev; CharBackend chr; uint8_t inv[INPUT_BUFFER_SIZE]; @@ -34,11 +35,12 @@ typedef struct Terminal3270 { int in_len; bool handshake_done; guint timer_tag; -} Terminal3270; +}; +typedef struct Terminal3270 Terminal3270; #define TYPE_TERMINAL_3270 "x-terminal3270" -#define TERMINAL_3270(obj) \ - OBJECT_CHECK(Terminal3270, (obj), TYPE_TERMINAL_3270) +DECLARE_INSTANCE_CHECKER(Terminal3270, TERMINAL_3270, + TYPE_TERMINAL_3270) static int terminal_can_read(void *opaque) { diff --git a/hw/char/trace-events b/hw/char/trace-events index d20eafd56f8cfbb7f1f91bf625cd4850dc75b302..81026f6612771e55e4351b1d148ef53e54f4c4d7 100644 --- a/hw/char/trace-events +++ b/hw/char/trace-events @@ -5,8 +5,9 @@ parallel_ioport_read(const char *desc, uint16_t addr, uint8_t value) "read [%s] parallel_ioport_write(const char *desc, uint16_t addr, uint8_t value) "write [%s] addr 0x%02x val 0x%02x" # serial.c -serial_ioport_read(uint16_t addr, uint8_t value) "read addr 0x%02x val 0x%02x" -serial_ioport_write(uint16_t addr, uint8_t value) "write addr 0x%02x val 0x%02x" +serial_read(uint16_t addr, uint8_t value) "read addr 0x%02x val 0x%02x" +serial_write(uint16_t addr, uint8_t value) "write addr 0x%02x val 0x%02x" +serial_update_parameters(uint64_t baudrate, char parity, int data_bits, int stop_bits) "baudrate=%"PRIu64" parity='%c' data=%d stop=%d" # virtio-serial-bus.c virtio_serial_send_control_event(unsigned int port, uint16_t event, uint16_t value) "port %u, event %u, value %u" @@ -64,6 +65,7 @@ pl011_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" pl011_can_receive(uint32_t lcr, int read_count, int r) "LCR 0x%08x read_count %d returning %d" pl011_put_fifo(uint32_t c, int read_count) "new char 0x%x read_count now %d" pl011_put_fifo_full(void) "FIFO now full, RXFF set" +pl011_baudrate_change(unsigned int baudrate, uint64_t clock, uint32_t ibrd, uint32_t fbrd) "new baudrate %u (clk: %" PRIu64 "hz, ibrd: %" PRIu32 ", fbrd: %" PRIu32 ")" # cmsdk-apb-uart.c cmsdk_apb_uart_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB UART read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" @@ -98,5 +100,5 @@ exynos_uart_rxsize(uint32_t channel, uint32_t size) "UART%d: Rx FIFO size: %d" exynos_uart_channel_error(uint32_t channel) "Wrong UART channel number: %d" exynos_uart_rx_timeout(uint32_t channel, uint32_t stat, uint32_t intsp) "UART%d: Rx timeout stat=0x%x intsp=0x%x" -# hw/char/cadence_uart.c +# cadence_uart.c cadence_uart_baudrate(unsigned baudrate) "baudrate %u" diff --git a/hw/char/trace.h b/hw/char/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..c2df66af2e8eaf8bf7f31cf85d3fea5824495c31 --- /dev/null +++ b/hw/char/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_char.h" diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c index 4f46753ea3086f5cf2aa4820059252bc2494c23d..bc752cf90f36fb4a1196c28c5e316c11ff7cdda8 100644 --- a/hw/char/virtio-console.c +++ b/hw/char/virtio-console.c @@ -19,17 +19,19 @@ #include "hw/virtio/virtio-serial.h" #include "qapi/error.h" #include "qapi/qapi-events-char.h" +#include "qom/object.h" #define TYPE_VIRTIO_CONSOLE_SERIAL_PORT "virtserialport" -#define VIRTIO_CONSOLE(obj) \ - OBJECT_CHECK(VirtConsole, (obj), TYPE_VIRTIO_CONSOLE_SERIAL_PORT) +typedef struct VirtConsole VirtConsole; +DECLARE_INSTANCE_CHECKER(VirtConsole, VIRTIO_CONSOLE, + TYPE_VIRTIO_CONSOLE_SERIAL_PORT) -typedef struct VirtConsole { +struct VirtConsole { VirtIOSerialPort parent_obj; CharBackend chr; guint watch; -} VirtConsole; +}; /* * Callback function that's called from chardevs when backend becomes diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index 262089c0c95a7390a89e2432a5b989d3f9af4e9a..cf08ef972812044fc1f801ade08832cc7bccebfb 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -843,10 +843,6 @@ static Property virtser_props[] = { DEFINE_PROP_END_OF_LIST() }; -#define TYPE_VIRTIO_SERIAL_BUS "virtio-serial-bus" -#define VIRTIO_SERIAL_BUS(obj) \ - OBJECT_CHECK(VirtIOSerialBus, (obj), TYPE_VIRTIO_SERIAL_BUS) - static void virtser_bus_class_init(ObjectClass *klass, void *data) { BusClass *k = BUS_CLASS(klass); @@ -1056,7 +1052,7 @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp) /* Spawn a new virtio-serial bus on which the ports will ride as devices */ qbus_create_inplace(&vser->bus, sizeof(vser->bus), TYPE_VIRTIO_SERIAL_BUS, dev, vdev->bus_name); - qbus_set_hotplug_handler(BUS(&vser->bus), OBJECT(vser), errp); + qbus_set_hotplug_handler(BUS(&vser->bus), OBJECT(vser)); vser->bus.vser = vser; QTAILQ_INIT(&vser->ports); @@ -1147,7 +1143,7 @@ static void virtio_serial_device_unrealize(DeviceState *dev) g_free(vser->post_load); } - qbus_set_hotplug_handler(BUS(&vser->bus), NULL, &error_abort); + qbus_set_hotplug_handler(BUS(&vser->bus), NULL); virtio_cleanup(vdev); } diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c index ae4ccd00c70e5bd194ff2e55907d3ec23b0a2fee..2e773ec4c430e9f3971a7fa3009b2c00e788a705 100644 --- a/hw/char/xilinx_uartlite.c +++ b/hw/char/xilinx_uartlite.c @@ -29,6 +29,7 @@ #include "hw/sysbus.h" #include "qemu/module.h" #include "chardev/char-fe.h" +#include "qom/object.h" #define DUART(x) @@ -52,10 +53,9 @@ #define CONTROL_IE 0x10 #define TYPE_XILINX_UARTLITE "xlnx.xps-uartlite" -#define XILINX_UARTLITE(obj) \ - OBJECT_CHECK(XilinxUARTLite, (obj), TYPE_XILINX_UARTLITE) +OBJECT_DECLARE_SIMPLE_TYPE(XilinxUARTLite, XILINX_UARTLITE) -typedef struct XilinxUARTLite { +struct XilinxUARTLite { SysBusDevice parent_obj; MemoryRegion mmio; @@ -67,7 +67,7 @@ typedef struct XilinxUARTLite { unsigned int rx_fifo_len; uint32_t regs[R_MAX]; -} XilinxUARTLite; +}; static void uart_update_irq(XilinxUARTLite *s) { diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs deleted file mode 100644 index 1d540ed6e783f17525f8ef2db0d4c11005dd17ce..0000000000000000000000000000000000000000 --- a/hw/core/Makefile.objs +++ /dev/null @@ -1,35 +0,0 @@ -# core qdev-related obj files, also used by *-user: -common-obj-y += qdev.o qdev-properties.o -common-obj-y += bus.o -common-obj-y += cpu.o -common-obj-y += resettable.o -common-obj-y += hotplug.o -common-obj-y += vmstate-if.o -# irq.o needed for qdev GPIO handling: -common-obj-y += irq.o -common-obj-y += clock.o qdev-clock.o - -common-obj-$(CONFIG_SOFTMMU) += reset.o -common-obj-$(CONFIG_SOFTMMU) += qdev-fw.o -common-obj-$(CONFIG_SOFTMMU) += fw-path-provider.o -common-obj-$(CONFIG_SOFTMMU) += nmi.o -common-obj-$(CONFIG_SOFTMMU) += vm-change-state-handler.o -common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o -common-obj-$(CONFIG_SOFTMMU) += sysbus.o -common-obj-$(CONFIG_SOFTMMU) += machine.o -common-obj-$(CONFIG_SOFTMMU) += null-machine.o -common-obj-$(CONFIG_SOFTMMU) += loader.o -common-obj-$(CONFIG_SOFTMMU) += machine-hmp-cmds.o -common-obj-$(CONFIG_SOFTMMU) += numa.o -common-obj-$(CONFIG_SOFTMMU) += clock-vmstate.o -obj-$(CONFIG_SOFTMMU) += machine-qmp-cmds.o - -common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o -common-obj-$(CONFIG_XILINX_AXI) += stream.o -common-obj-$(CONFIG_PTIMER) += ptimer.o -common-obj-$(CONFIG_FITLOADER) += loader-fit.o -common-obj-$(CONFIG_REGISTER) += register.o -common-obj-$(CONFIG_OR_IRQ) += or-irq.o -common-obj-$(CONFIG_SPLIT_IRQ) += split-irq.o -common-obj-$(CONFIG_PLATFORM_BUS) += platform-bus.o -common-obj-$(CONFIG_GENERIC_LOADER) += generic-loader.o diff --git a/hw/core/bus.c b/hw/core/bus.c index 50924793ac8db8aac1136c64676b9cd8839d3151..9cfbc3a6877c3d332df57ee067bef8f9d36209ac 100644 --- a/hw/core/bus.c +++ b/hw/core/bus.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -23,15 +23,15 @@ #include "qemu/module.h" #include "qapi/error.h" -void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp) +void qbus_set_hotplug_handler(BusState *bus, Object *handler) { - object_property_set_link(OBJECT(bus), handler, - QDEV_HOTPLUG_HANDLER_PROPERTY, errp); + object_property_set_link(OBJECT(bus), QDEV_HOTPLUG_HANDLER_PROPERTY, + handler, &error_abort); } -void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp) +void qbus_set_bus_hotplug_handler(BusState *bus) { - qbus_set_hotplug_handler(bus, OBJECT(bus), errp); + qbus_set_hotplug_handler(bus, OBJECT(bus)); } int qbus_walk_children(BusState *bus, @@ -49,12 +49,14 @@ int qbus_walk_children(BusState *bus, } } - QTAILQ_FOREACH(kid, &bus->children, sibling) { - err = qdev_walk_children(kid->child, - pre_devfn, pre_busfn, - post_devfn, post_busfn, opaque); - if (err < 0) { - return err; + WITH_RCU_READ_LOCK_GUARD() { + QTAILQ_FOREACH_RCU(kid, &bus->children, sibling) { + err = qdev_walk_children(kid->child, + pre_devfn, pre_busfn, + post_devfn, post_busfn, opaque); + if (err < 0) { + return err; + } } } @@ -90,12 +92,14 @@ static void bus_reset_child_foreach(Object *obj, ResettableChildCallback cb, BusState *bus = BUS(obj); BusChild *kid; - QTAILQ_FOREACH(kid, &bus->children, sibling) { - cb(OBJECT(kid->child), opaque, type); + WITH_RCU_READ_LOCK_GUARD() { + QTAILQ_FOREACH_RCU(kid, &bus->children, sibling) { + cb(OBJECT(kid->child), opaque, type); + } } } -static void qbus_realize(BusState *bus, DeviceState *parent, const char *name) +static void qbus_init(BusState *bus, DeviceState *parent, const char *name) { const char *typename = object_get_typename(OBJECT(bus)); BusClass *bc; @@ -151,7 +155,7 @@ void qbus_create_inplace(void *bus, size_t size, const char *typename, DeviceState *parent, const char *name) { object_initialize(bus, size, typename); - qbus_realize(bus, parent, name); + qbus_init(bus, parent, name); } BusState *qbus_create(const char *typename, DeviceState *parent, const char *name) @@ -159,11 +163,21 @@ BusState *qbus_create(const char *typename, DeviceState *parent, const char *nam BusState *bus; bus = BUS(object_new(typename)); - qbus_realize(bus, parent, name); + qbus_init(bus, parent, name); return bus; } +bool qbus_realize(BusState *bus, Error **errp) +{ + return object_property_set_bool(OBJECT(bus), "realized", true, errp); +} + +void qbus_unrealize(BusState *bus) +{ + object_property_set_bool(OBJECT(bus), "realized", false, &error_abort); +} + static bool bus_get_realized(Object *obj, Error **errp) { BusState *bus = BUS(obj); @@ -184,10 +198,11 @@ static void bus_set_realized(Object *obj, bool value, Error **errp) /* TODO: recursive realization */ } else if (!value && bus->realized) { - QTAILQ_FOREACH(kid, &bus->children, sibling) { - DeviceState *dev = kid->child; - object_property_set_bool(OBJECT(dev), false, "realized", - &error_abort); + WITH_RCU_READ_LOCK_GUARD() { + QTAILQ_FOREACH_RCU(kid, &bus->children, sibling) { + DeviceState *dev = kid->child; + qdev_unrealize(dev); + } } if (bc->unrealize) { bc->unrealize(bus); diff --git a/hw/core/clock.c b/hw/core/clock.c index 3c0daf7d4cffb572f98a40a0d1927a1e2026f96e..8c6af223e7c05d6e18d48822021ad8aba88db7b3 100644 --- a/hw/core/clock.c +++ b/hw/core/clock.c @@ -23,6 +23,21 @@ void clock_setup_canonical_path(Clock *clk) clk->canonical_path = object_get_canonical_path(OBJECT(clk)); } +Clock *clock_new(Object *parent, const char *name) +{ + Object *obj; + Clock *clk; + + obj = object_new(TYPE_CLOCK); + object_property_add_child(parent, name, obj); + object_unref(obj); + + clk = CLOCK(obj); + clock_setup_canonical_path(clk); + + return clk; +} + void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque) { clk->callback = cb; @@ -34,11 +49,16 @@ void clock_clear_callback(Clock *clk) clock_set_callback(clk, NULL, NULL); } -void clock_set(Clock *clk, uint64_t period) +bool clock_set(Clock *clk, uint64_t period) { - trace_clock_set(CLOCK_PATH(clk), CLOCK_PERIOD_TO_NS(clk->period), - CLOCK_PERIOD_TO_NS(period)); + if (clk->period == period) { + return false; + } + trace_clock_set(CLOCK_PATH(clk), CLOCK_PERIOD_TO_HZ(clk->period), + CLOCK_PERIOD_TO_HZ(period)); clk->period = period; + + return true; } static void clock_propagate_period(Clock *clk, bool call_callbacks) @@ -49,7 +69,7 @@ static void clock_propagate_period(Clock *clk, bool call_callbacks) if (child->period != clk->period) { child->period = clk->period; trace_clock_update(CLOCK_PATH(child), CLOCK_PATH(clk), - CLOCK_PERIOD_TO_NS(clk->period), + CLOCK_PERIOD_TO_HZ(clk->period), call_callbacks); if (call_callbacks && child->callback) { child->callback(child->callback_opaque); diff --git a/hw/core/cpu.c b/hw/core/cpu.c index 5284d384fb6b4f8618a1efd5390df525d8ed2130..576fa1d7ba02eb07118fd6391c9ffa3ef13ae356 100644 --- a/hw/core/cpu.c +++ b/hw/core/cpu.c @@ -26,15 +26,15 @@ #include "qemu/log.h" #include "qemu/main-loop.h" #include "exec/log.h" +#include "exec/cpu-common.h" #include "qemu/error-report.h" #include "qemu/qemu-print.h" #include "sysemu/tcg.h" #include "hw/boards.h" #include "hw/qdev-properties.h" -#include "trace-root.h" +#include "trace/trace-root.h" #include "qemu/plugin.h" - -CPUInterruptHandler cpu_interrupt_handler; +#include "sysemu/hw_accel.h" CPUState *cpu_by_arch_id(int64_t id) { @@ -59,8 +59,7 @@ CPUState *cpu_create(const char *typename) { Error *err = NULL; CPUState *cpu = CPU(object_new(typename)); - object_property_set_bool(OBJECT(cpu), true, "realized", &err); - if (err != NULL) { + if (!qdev_realize(DEVICE(cpu), NULL, &err)) { error_report_err(err); object_unref(OBJECT(cpu)); exit(EXIT_FAILURE); @@ -112,10 +111,10 @@ void cpu_reset_interrupt(CPUState *cpu, int mask) void cpu_exit(CPUState *cpu) { - atomic_set(&cpu->exit_request, 1); + qatomic_set(&cpu->exit_request, 1); /* Ensure cpu_exec will see the exit request after TCG has exited. */ smp_wmb(); - atomic_set(&cpu->icount_decr_ptr->u16.high, -1); + qatomic_set(&cpu->icount_decr_ptr->u16.high, -1); } int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu, @@ -209,6 +208,7 @@ static bool cpu_common_exec_interrupt(CPUState *cpu, int int_req) return false; } +#if !defined(CONFIG_USER_ONLY) GuestPanicInformation *cpu_get_crash_info(CPUState *cpu) { CPUClass *cc = CPU_GET_CLASS(cpu); @@ -219,6 +219,7 @@ GuestPanicInformation *cpu_get_crash_info(CPUState *cpu) } return res; } +#endif void cpu_dump_state(CPUState *cpu, FILE *f, int flags) { @@ -257,10 +258,10 @@ static void cpu_common_reset(DeviceState *dev) } cpu->interrupt_request = 0; - cpu->halted = 0; + cpu->halted = cpu->start_powered_off; cpu->mem_io_pc = 0; cpu->icount_extra = 0; - atomic_set(&cpu->icount_decr_ptr->u32, 0); + qatomic_set(&cpu->icount_decr_ptr->u32, 0); cpu->can_do_io = 1; cpu->exception_index = -1; cpu->crash_occurred = false; @@ -368,6 +369,7 @@ static void cpu_common_initfn(Object *obj) cpu->nr_threads = 1; qemu_mutex_init(&cpu->work_mutex); + QSIMPLEQ_INIT(&cpu->work_list); QTAILQ_INIT(&cpu->breakpoints); QTAILQ_INIT(&cpu->watchpoints); @@ -391,17 +393,6 @@ static vaddr cpu_adjust_watchpoint_address(CPUState *cpu, vaddr addr, int len) return addr; } -static void generic_handle_interrupt(CPUState *cpu, int mask) -{ - cpu->interrupt_request |= mask; - - if (!qemu_cpu_is_self(cpu)) { - qemu_cpu_kick(cpu); - } -} - -CPUInterruptHandler cpu_interrupt_handler = generic_handle_interrupt; - static void cpu_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); diff --git a/hw/core/irq.c b/hw/core/irq.c index fb3045b912e9b6af659a602aeff3bba8244339ee..8a9cbdd5561a0d0c35b5139df51ec980ac4c9d21 100644 --- a/hw/core/irq.c +++ b/hw/core/irq.c @@ -26,7 +26,8 @@ #include "hw/irq.h" #include "qom/object.h" -#define IRQ(obj) OBJECT_CHECK(struct IRQState, (obj), TYPE_IRQ) +DECLARE_INSTANCE_CHECKER(struct IRQState, IRQ, + TYPE_IRQ) struct IRQState { Object parent_obj; diff --git a/hw/core/loader-fit.c b/hw/core/loader-fit.c index c465921b8f777f4924fc2c1b4b7115d69434b472..b7c7b3ba94d47c877dc9711b8384e139bcaea3d1 100644 --- a/hw/core/loader-fit.c +++ b/hw/core/loader-fit.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/core/machine-hmp-cmds.c b/hw/core/machine-hmp-cmds.c index 39999c47c5c3a93efaa9011c38d83903aa8993ab..6357be9c6b18b595ff88b08518868b39977e7d20 100644 --- a/hw/core/machine-hmp-cmds.c +++ b/hw/core/machine-hmp-cmds.c @@ -34,7 +34,7 @@ void hmp_info_cpus(Monitor *mon, const QDict *qdict) for (cpu = cpu_list; cpu; cpu = cpu->next) { int active = ' '; - if (cpu->value->cpu_index == monitor_get_cpu_index()) { + if (cpu->value->cpu_index == monitor_get_cpu_index(mon)) { active = '*'; } @@ -46,18 +46,6 @@ void hmp_info_cpus(Monitor *mon, const QDict *qdict) qapi_free_CpuInfoFastList(cpu_list); } -void hmp_cpu_add(Monitor *mon, const QDict *qdict) -{ - int cpuid; - Error *err = NULL; - - error_report("cpu_add is deprecated, please use device_add instead"); - - cpuid = qdict_get_int(qdict, "id"); - qmp_cpu_add(cpuid, &err); - hmp_handle_error(mon, err); -} - void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict) { Error *err = NULL; diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c index 2c5da8413d662c1ccf8740fe0f913aa5b4f1e466..5362c80a1873742e320acd3cc1402578a04c2781 100644 --- a/hw/core/machine-qmp-cmds.c +++ b/hw/core/machine-qmp-cmds.c @@ -238,6 +238,10 @@ MachineInfoList *qmp_query_machines(Error **errp) info->default_cpu_type = g_strdup(mc->default_cpu_type); info->has_default_cpu_type = true; } + if (mc->default_ram_id) { + info->default_ram_id = g_strdup(mc->default_ram_id); + info->has_default_ram_id = true; + } entry = g_malloc0(sizeof(*entry)); entry->value = info; @@ -280,18 +284,6 @@ HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp) return machine_query_hotpluggable_cpus(ms); } -void qmp_cpu_add(int64_t id, Error **errp) -{ - MachineClass *mc; - - mc = MACHINE_GET_CLASS(current_machine); - if (mc->hot_add_cpu) { - mc->hot_add_cpu(current_machine, id, errp); - } else { - error_setg(errp, "Not supported"); - } -} - void qmp_set_numa_node(NumaOptions *cmd, Error **errp) { if (!runstate_check(RUN_STATE_PRECONFIG)) { @@ -315,7 +307,7 @@ static int query_memdev(Object *obj, void *opaque) m->value = g_malloc0(sizeof(*m->value)); - m->value->id = object_get_canonical_path_component(obj); + m->value->id = g_strdup(object_get_canonical_path_component(obj)); m->value->has_id = !!m->value->id; m->value->size = object_property_get_uint(obj, "size", diff --git a/hw/core/machine.c b/hw/core/machine.c index bb3a7b18b193db5c9c328580000fc0e257744995..d0408049b53c795d095ca7ec8c28068f74d47162 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -28,7 +28,26 @@ #include "hw/mem/nvdimm.h" #include "migration/vmstate.h" -GlobalProperty hw_compat_5_0[] = {}; +GlobalProperty hw_compat_5_1[] = { + { "vhost-scsi", "num_queues", "1"}, + { "vhost-user-blk", "num-queues", "1"}, + { "vhost-user-scsi", "num_queues", "1"}, + { "virtio-blk-device", "num-queues", "1"}, + { "virtio-scsi-device", "num_queues", "1"}, + { "nvme", "use-intel-id", "on"}, + { "pvpanic", "events", "1"}, /* PVPANIC_PANICKED */ +}; +const size_t hw_compat_5_1_len = G_N_ELEMENTS(hw_compat_5_1); + +GlobalProperty hw_compat_5_0[] = { + { "pci-host-bridge", "x-config-reg-migration-enabled", "off" }, + { "virtio-balloon-device", "page-poison", "false" }, + { "vmport", "x-read-set-eax", "off" }, + { "vmport", "x-signal-unsupported-cmd", "off" }, + { "vmport", "x-report-vmx-type", "off" }, + { "vmport", "x-cmds-v2", "off" }, + { "virtio-device", "x-disable-legacy-check", "true" }, +}; const size_t hw_compat_5_0_len = G_N_ELEMENTS(hw_compat_5_0); GlobalProperty hw_compat_4_2[] = { @@ -284,12 +303,9 @@ static void machine_set_phandle_start(Object *obj, Visitor *v, Error **errp) { MachineState *ms = MACHINE(obj); - Error *error = NULL; int64_t value; - visit_type_int(v, name, &value, &error); - if (error) { - error_propagate(errp, error); + if (!visit_type_int(v, name, &value, errp)) { return; } @@ -397,24 +413,6 @@ static bool machine_get_suppress_vmdesc(Object *obj, Error **errp) return ms->suppress_vmdesc; } -static void machine_set_enforce_config_section(Object *obj, bool value, - Error **errp) -{ - MachineState *ms = MACHINE(obj); - - warn_report("enforce-config-section is deprecated, please use " - "-global migration.send-configuration=on|off instead"); - - ms->enforce_config_section = value; -} - -static bool machine_get_enforce_config_section(Object *obj, Error **errp) -{ - MachineState *ms = MACHINE(obj); - - return ms->enforce_config_section; -} - static char *machine_get_memory_encryption(Object *obj, Error **errp) { MachineState *ms = MACHINE(obj); @@ -741,23 +739,15 @@ static void smp_parse(MachineState *ms, QemuOpts *opts) exit(1); } - if (sockets * cores * threads > ms->smp.max_cpus) { - error_report("cpu topology: " - "sockets (%u) * cores (%u) * threads (%u) > " - "maxcpus (%u)", + if (sockets * cores * threads != ms->smp.max_cpus) { + error_report("Invalid CPU topology: " + "sockets (%u) * cores (%u) * threads (%u) " + "!= maxcpus (%u)", sockets, cores, threads, ms->smp.max_cpus); exit(1); } - if (sockets * cores * threads != ms->smp.max_cpus) { - warn_report("Invalid CPU topology deprecated: " - "sockets (%u) * cores (%u) * threads (%u) " - "!= maxcpus (%u)", - sockets, cores, threads, - ms->smp.max_cpus); - } - ms->smp.cpus = cpus; ms->smp.cores = cores; ms->smp.threads = threads; @@ -784,7 +774,6 @@ static void machine_class_init(ObjectClass *oc, void *data) * On Linux, each node's border has to be 8MB aligned */ mc->numa_mem_align_shift = 23; - mc->numa_auto_assign_ram = numa_default_auto_assign_ram; object_class_property_add_str(oc, "kernel", machine_get_kernel, machine_set_kernel); @@ -852,21 +841,26 @@ static void machine_class_init(ObjectClass *oc, void *data) object_class_property_set_description(oc, "suppress-vmdesc", "Set on to disable self-describing migration"); - object_class_property_add_bool(oc, "enforce-config-section", - machine_get_enforce_config_section, machine_set_enforce_config_section); - object_class_property_set_description(oc, "enforce-config-section", - "Set on to enforce configuration section migration"); - object_class_property_add_str(oc, "memory-encryption", machine_get_memory_encryption, machine_set_memory_encryption); object_class_property_set_description(oc, "memory-encryption", "Set memory encryption object to use"); + + object_class_property_add_str(oc, "memory-backend", + machine_get_memdev, machine_set_memdev); + object_class_property_set_description(oc, "memory-backend", + "Set RAM backend" + "Valid value is ID of hostmem based backend"); } static void machine_class_base_init(ObjectClass *oc, void *data) { + MachineClass *mc = MACHINE_CLASS(oc); + mc->max_cpus = mc->max_cpus ?: 1; + mc->min_cpus = mc->min_cpus ?: 1; + mc->default_cpus = mc->default_cpus ?: 1; + if (!object_class_is_abstract(oc)) { - MachineClass *mc = MACHINE_CLASS(oc); const char *cname = object_class_get_name(oc); assert(g_str_has_suffix(cname, TYPE_MACHINE_SUFFIX)); mc->name = g_strndup(cname, @@ -912,15 +906,16 @@ static void machine_initfn(Object *obj) "Table (HMAT)"); } - object_property_add_str(obj, "memory-backend", - machine_get_memdev, machine_set_memdev); - object_property_set_description(obj, "memory-backend", - "Set RAM backend" - "Valid value is ID of hostmem based backend"); - /* Register notifier when init is done for sysbus sanity checks */ ms->sysbus_notifier.notify = machine_init_notify; qemu_add_machine_init_done_notifier(&ms->sysbus_notifier); + + /* default to mc->default_cpus */ + ms->smp.cpus = mc->default_cpus; + ms->smp.max_cpus = mc->default_cpus; + ms->smp.cores = 1; + ms->smp.threads = 1; + ms->smp.sockets = 1; } static void machine_finalize(Object *obj) @@ -1070,9 +1065,8 @@ MemoryRegion *machine_consume_memdev(MachineState *machine, MemoryRegion *ret = host_memory_backend_get_memory(backend); if (memory_region_is_mapped(ret)) { - char *path = object_get_canonical_path_component(OBJECT(backend)); - error_report("memory backend %s can't be used multiple times.", path); - g_free(path); + error_report("memory backend %s can't be used multiple times.", + object_get_canonical_path_component(OBJECT(backend))); exit(EXIT_FAILURE); } host_memory_backend_set_mapped(backend, true); @@ -1083,6 +1077,8 @@ MemoryRegion *machine_consume_memdev(MachineState *machine, void machine_run_board_init(MachineState *machine) { MachineClass *machine_class = MACHINE_GET_CLASS(machine); + ObjectClass *oc = object_class_by_name(machine->cpu_type); + CPUClass *cc; if (machine->ram_memdev_id) { Object *o; @@ -1102,11 +1098,10 @@ void machine_run_board_init(MachineState *machine) * specified a CPU with -cpu check here that the user CPU is supported. */ if (machine_class->valid_cpu_types && machine->cpu_type) { - ObjectClass *class = object_class_by_name(machine->cpu_type); int i; for (i = 0; machine_class->valid_cpu_types[i]; i++) { - if (object_class_dynamic_cast(class, + if (object_class_dynamic_cast(oc, machine_class->valid_cpu_types[i])) { /* The user specificed CPU is in the valid field, we are * good to go. @@ -1129,6 +1124,13 @@ void machine_run_board_init(MachineState *machine) } } + /* Check if CPU type is deprecated and warn if so */ + cc = CPU_CLASS(oc); + if (cc && cc->deprecation_note) { + warn_report("CPU model %s is deprecated -- %s", machine->cpu_type, + cc->deprecation_note); + } + machine_class->init(machine); } diff --git a/hw/core/meson.build b/hw/core/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..4a744f3b5e7f90901ed4b508a2cc869ccd85b581 --- /dev/null +++ b/hw/core/meson.build @@ -0,0 +1,43 @@ +# core qdev-related obj files, also used by *-user and unit tests +hwcore_files = files( + 'bus.c', + 'fw-path-provider.c', + 'hotplug.c', + 'qdev-properties.c', + 'qdev.c', + 'reset.c', + 'resettable.c', + 'vmstate-if.c', + # irq.c needed for qdev GPIO handling: + 'irq.c', + 'clock.c', + 'qdev-clock.c', +) + +common_ss.add(files('cpu.c')) +common_ss.add(when: 'CONFIG_FITLOADER', if_true: files('loader-fit.c')) +common_ss.add(when: 'CONFIG_GENERIC_LOADER', if_true: files('generic-loader.c')) +common_ss.add(when: 'CONFIG_OR_IRQ', if_true: files('or-irq.c')) +common_ss.add(when: 'CONFIG_PLATFORM_BUS', if_true: files('platform-bus.c')) +common_ss.add(when: 'CONFIG_PTIMER', if_true: files('ptimer.c')) +common_ss.add(when: 'CONFIG_REGISTER', if_true: files('register.c')) +common_ss.add(when: 'CONFIG_SPLIT_IRQ', if_true: files('split-irq.c')) +common_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('stream.c')) + +softmmu_ss.add(files( + 'loader.c', + 'machine-hmp-cmds.c', + 'machine.c', + 'nmi.c', + 'null-machine.c', + 'qdev-fw.c', + 'qdev-properties-system.c', + 'sysbus.c', + 'vm-change-state-handler.c', + 'clock-vmstate.c', +)) + +specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: files( + 'machine-qmp-cmds.c', + 'numa.c', +)) diff --git a/hw/core/null-machine.c b/hw/core/null-machine.c index cb47d9d4f8054a3dd5d02c372a78a0a13793c752..7e693523d75292915f1a311cdb3137c63053a3a5 100644 --- a/hw/core/null-machine.c +++ b/hw/core/null-machine.c @@ -50,6 +50,11 @@ static void machine_none_machine_init(MachineClass *mc) mc->max_cpus = 1; mc->default_ram_size = 0; mc->default_ram_id = "ram"; + mc->no_serial = 1; + mc->no_parallel = 1; + mc->no_floppy = 1; + mc->no_cdrom = 1; + mc->no_sdcard = 1; } DEFINE_MACHINE("none", machine_none_machine_init) diff --git a/hw/core/numa.c b/hw/core/numa.c index 316bc50d75b0787fd91316d5155a1d915e610831..7c4dd4e68e3c0304edfbab66903d56651a6dfde7 100644 --- a/hw/core/numa.c +++ b/hw/core/numa.c @@ -117,6 +117,13 @@ static void parse_numa_node(MachineState *ms, NumaNodeOptions *node, } if (node->has_mem) { + if (!mc->numa_mem_supported) { + error_setg(errp, "Parameter -numa node,mem is not supported by this" + " machine type"); + error_append_hint(errp, "Use -numa node,memdev instead\n"); + return; + } + numa_info[nodenr].node_mem = node->mem; if (!qtest_enabled()) { warn_report("Parameter -numa node,mem is deprecated," @@ -417,11 +424,17 @@ void parse_numa_hmat_cache(MachineState *ms, NumaHmatCacheOptions *node, } if ((node->level > 1) && - ms->numa_state->hmat_cache[node->node_id][node->level - 1] && - (node->size >= + ms->numa_state->hmat_cache[node->node_id][node->level - 1] == NULL) { + error_setg(errp, "Cache level=%u shall be defined first", + node->level - 1); + return; + } + + if ((node->level > 1) && + (node->size <= ms->numa_state->hmat_cache[node->node_id][node->level - 1]->size)) { error_setg(errp, "Invalid size=%" PRIu64 ", the size of level=%" PRIu8 - " should be less than the size(%" PRIu64 ") of " + " should be larger than the size(%" PRIu64 ") of " "level=%u", node->size, node->level, ms->numa_state->hmat_cache[node->node_id] [node->level - 1]->size, @@ -431,10 +444,10 @@ void parse_numa_hmat_cache(MachineState *ms, NumaHmatCacheOptions *node, if ((node->level < HMAT_LB_LEVELS - 1) && ms->numa_state->hmat_cache[node->node_id][node->level + 1] && - (node->size <= + (node->size >= ms->numa_state->hmat_cache[node->node_id][node->level + 1]->size)) { error_setg(errp, "Invalid size=%" PRIu64 ", the size of level=%" PRIu8 - " should be larger than the size(%" PRIu64 ") of " + " should be less than the size(%" PRIu64 ") of " "level=%u", node->size, node->level, ms->numa_state->hmat_cache[node->node_id] [node->level + 1]->size, @@ -449,40 +462,33 @@ void parse_numa_hmat_cache(MachineState *ms, NumaHmatCacheOptions *node, void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp) { - Error *err = NULL; - if (!ms->numa_state) { error_setg(errp, "NUMA is not supported by this machine-type"); - goto end; + return; } switch (object->type) { case NUMA_OPTIONS_TYPE_NODE: - parse_numa_node(ms, &object->u.node, &err); - if (err) { - goto end; - } + parse_numa_node(ms, &object->u.node, errp); break; case NUMA_OPTIONS_TYPE_DIST: - parse_numa_distance(ms, &object->u.dist, &err); - if (err) { - goto end; - } + parse_numa_distance(ms, &object->u.dist, errp); break; case NUMA_OPTIONS_TYPE_CPU: if (!object->u.cpu.has_node_id) { - error_setg(&err, "Missing mandatory node-id property"); - goto end; + error_setg(errp, "Missing mandatory node-id property"); + return; } if (!ms->numa_state->nodes[object->u.cpu.node_id].present) { - error_setg(&err, "Invalid node-id=%" PRId64 ", NUMA node must be " - "defined with -numa node,nodeid=ID before it's used with " - "-numa cpu,node-id=ID", object->u.cpu.node_id); - goto end; + error_setg(errp, "Invalid node-id=%" PRId64 ", NUMA node must be " + "defined with -numa node,nodeid=ID before it's used with " + "-numa cpu,node-id=ID", object->u.cpu.node_id); + return; } - machine_set_cpu_numa_node(ms, qapi_NumaCpuOptions_base(&object->u.cpu), - &err); + machine_set_cpu_numa_node(ms, + qapi_NumaCpuOptions_base(&object->u.cpu), + errp); break; case NUMA_OPTIONS_TYPE_HMAT_LB: if (!ms->numa_state->hmat_enabled) { @@ -492,10 +498,7 @@ void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp) return; } - parse_numa_hmat_lb(ms->numa_state, &object->u.hmat_lb, &err); - if (err) { - goto end; - } + parse_numa_hmat_lb(ms->numa_state, &object->u.hmat_lb, errp); break; case NUMA_OPTIONS_TYPE_HMAT_CACHE: if (!ms->numa_state->hmat_enabled) { @@ -505,17 +508,11 @@ void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp) return; } - parse_numa_hmat_cache(ms, &object->u.hmat_cache, &err); - if (err) { - goto end; - } + parse_numa_hmat_cache(ms, &object->u.hmat_cache, errp); break; default: abort(); } - -end: - error_propagate(errp, err); } static int parse_numa(void *opaque, QemuOpts *opts, Error **errp) @@ -525,10 +522,10 @@ static int parse_numa(void *opaque, QemuOpts *opts, Error **errp) Error *err = NULL; Visitor *v = opts_visitor_new(opts); - visit_type_NumaOptions(v, NULL, &object, &err); + visit_type_NumaOptions(v, NULL, &object, errp); visit_free(v); - if (err) { - goto end; + if (!object) { + return -1; } /* Fix up legacy suffix-less format */ @@ -539,7 +536,6 @@ static int parse_numa(void *opaque, QemuOpts *opts, Error **errp) set_numa_options(ms, object, &err); -end: qapi_free_NumaOptions(object); if (err) { error_propagate(errp, err); @@ -621,42 +617,6 @@ static void complete_init_numa_distance(MachineState *ms) } } -void numa_legacy_auto_assign_ram(MachineClass *mc, NodeInfo *nodes, - int nb_nodes, ram_addr_t size) -{ - int i; - uint64_t usedmem = 0; - - /* Align each node according to the alignment - * requirements of the machine class - */ - - for (i = 0; i < nb_nodes - 1; i++) { - nodes[i].node_mem = (size / nb_nodes) & - ~((1 << mc->numa_mem_align_shift) - 1); - usedmem += nodes[i].node_mem; - } - nodes[i].node_mem = size - usedmem; -} - -void numa_default_auto_assign_ram(MachineClass *mc, NodeInfo *nodes, - int nb_nodes, ram_addr_t size) -{ - int i; - uint64_t usedmem = 0, node_mem; - uint64_t granularity = size / nb_nodes; - uint64_t propagate = 0; - - for (i = 0; i < nb_nodes - 1; i++) { - node_mem = (granularity + propagate) & - ~((1 << mc->numa_mem_align_shift) - 1); - propagate = granularity + propagate - node_mem; - nodes[i].node_mem = node_mem; - usedmem += node_mem; - } - nodes[i].node_mem = size - usedmem; -} - static void numa_init_memdev_container(MachineState *ms, MemoryRegion *ram) { int i; @@ -681,8 +641,9 @@ void numa_complete_configuration(MachineState *ms) NodeInfo *numa_info = ms->numa_state->nodes; /* - * If memory hotplug is enabled (slots > 0) but without '-numa' - * options explicitly on CLI, guestes will break. + * If memory hotplug is enabled (slot > 0) or memory devices are enabled + * (ms->maxram_size > ram_size) but without '-numa' options explicitly on + * CLI, guests will break. * * Windows: won't enable memory hotplug without SRAT table at all * @@ -697,9 +658,9 @@ void numa_complete_configuration(MachineState *ms) * assume there is just one node with whole RAM. */ if (ms->numa_state->num_nodes == 0 && - ((ms->ram_slots > 0 && - mc->auto_enable_numa_with_memhp) || - mc->auto_enable_numa)) { + ((ms->ram_slots && mc->auto_enable_numa_with_memhp) || + (ms->maxram_size > ms->ram_size && mc->auto_enable_numa_with_memdev) || + mc->auto_enable_numa)) { NumaNodeOptions node = { }; parse_numa_node(ms, &node, &error_abort); numa_info[0].node_mem = ram_size; @@ -722,29 +683,6 @@ void numa_complete_configuration(MachineState *ms) if (ms->numa_state->num_nodes > 0) { uint64_t numa_total; - if (ms->numa_state->num_nodes > MAX_NODES) { - ms->numa_state->num_nodes = MAX_NODES; - } - - /* If no memory size is given for any node, assume the default case - * and distribute the available memory equally across all nodes - */ - for (i = 0; i < ms->numa_state->num_nodes; i++) { - if (numa_info[i].node_mem != 0) { - break; - } - } - if (i == ms->numa_state->num_nodes) { - assert(mc->numa_auto_assign_ram); - mc->numa_auto_assign_ram(mc, numa_info, - ms->numa_state->num_nodes, ram_size); - if (!qtest_enabled()) { - warn_report("Default splitting of RAM between nodes is deprecated," - " Use '-numa node,memdev' to explictly define RAM" - " allocation per node"); - } - } - numa_total = 0; for (i = 0; i < ms->numa_state->num_nodes; i++) { numa_total += numa_info[i].node_mem; @@ -757,6 +695,11 @@ void numa_complete_configuration(MachineState *ms) } if (!numa_uses_legacy_mem() && mc->default_ram_id) { + if (ms->ram_memdev_id) { + error_report("'-machine memory-backend' and '-numa memdev'" + " properties are mutually exclusive"); + exit(1); + } ms->ram = g_new(MemoryRegion, 1); memory_region_init(ms->ram, OBJECT(ms), mc->default_ram_id, ram_size); @@ -797,8 +740,8 @@ void numa_cpu_pre_plug(const CPUArchId *slot, DeviceState *dev, Error **errp) /* due to bug in libvirt, it doesn't pass node-id from props on * device_add as expected, so we have to fix it up here */ if (slot->props.has_node_id) { - object_property_set_int(OBJECT(dev), slot->props.node_id, - "node-id", errp); + object_property_set_int(OBJECT(dev), "node-id", + slot->props.node_id, errp); } } else if (node_id != slot->props.node_id) { error_setg(errp, "invalid node-id, must be %"PRId64, @@ -812,6 +755,7 @@ static void numa_stat_memory_devices(NumaNodeMem node_mem[]) MemoryDeviceInfoList *info; PCDIMMDeviceInfo *pcdimm_info; VirtioPMEMDeviceInfo *vpi; + VirtioMEMDeviceInfo *vmi; for (info = info_list; info; info = info->next) { MemoryDeviceInfo *value = info->value; @@ -832,6 +776,11 @@ static void numa_stat_memory_devices(NumaNodeMem node_mem[]) node_mem[0].node_mem += vpi->size; node_mem[0].node_plugged_mem += vpi->size; break; + case MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM: + vmi = value->u.virtio_mem.data; + node_mem[vmi->node].node_mem += vmi->size; + node_mem[vmi->node].node_plugged_mem += vmi->size; + break; default: g_assert_not_reached(); } diff --git a/hw/core/platform-bus.c b/hw/core/platform-bus.c index d494e5cec1434e9226a0b506ea39ba736a52fe93..b8487b26b674e46e445749118abc7b2cc6918f0f 100644 --- a/hw/core/platform-bus.c +++ b/hw/core/platform-bus.c @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -22,6 +22,7 @@ #include "qemu/osdep.h" #include "hw/platform-bus.h" #include "hw/qdev-properties.h" +#include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/module.h" @@ -63,9 +64,8 @@ hwaddr platform_bus_get_mmio_addr(PlatformBusDevice *pbus, SysBusDevice *sbdev, return -1; } - parent_mr = object_property_get_link(OBJECT(sbdev_mr), "container", NULL); - - assert(parent_mr); + parent_mr = object_property_get_link(OBJECT(sbdev_mr), "container", + &error_abort); if (parent_mr != pbus_mr_obj) { /* MMIO region is not mapped on platform bus */ return -1; diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c index b5a54e25369a5c9f2fbdd323410baafeed7ea325..2aa97cb665c55562798bd39bdd558435c01b135c 100644 --- a/hw/core/ptimer.c +++ b/hw/core/ptimer.c @@ -7,11 +7,11 @@ */ #include "qemu/osdep.h" -#include "qemu/timer.h" #include "hw/ptimer.h" #include "migration/vmstate.h" #include "qemu/host-utils.h" #include "sysemu/replay.h" +#include "sysemu/cpu-timers.h" #include "sysemu/qtest.h" #include "block/aio.h" #include "sysemu/cpus.h" @@ -117,6 +117,10 @@ static void ptimer_reload(ptimer_state *s, int delta_adjust) } if (delta == 0) { + if (s->enabled == 0) { + /* trigger callback disabled the timer already */ + return; + } if (!qtest_enabled()) { fprintf(stderr, "Timer with delta zero, disabling\n"); } @@ -134,7 +138,8 @@ static void ptimer_reload(ptimer_state *s, int delta_adjust) * on the current generation of host machines. */ - if (s->enabled == 1 && (delta * period < 10000) && !use_icount) { + if (s->enabled == 1 && (delta * period < 10000) && + !icount_enabled() && !qtest_enabled()) { period = 10000 / delta; period_frac = 0; } @@ -217,7 +222,8 @@ uint64_t ptimer_get_count(ptimer_state *s) uint32_t period_frac = s->period_frac; uint64_t period = s->period; - if (!oneshot && (s->delta * period < 10000) && !use_icount) { + if (!oneshot && (s->delta * period < 10000) && + !icount_enabled() && !qtest_enabled()) { period = 10000 / s->delta; period_frac = 0; } diff --git a/hw/core/qdev-clock.c b/hw/core/qdev-clock.c index 5cc1e82e510405957e68b169fd5140bbc91c7143..eb05f2a13ca255c801776f9abd9894f0813740ba 100644 --- a/hw/core/qdev-clock.c +++ b/hw/core/qdev-clock.c @@ -12,6 +12,7 @@ */ #include "qemu/osdep.h" +#include "qemu/error-report.h" #include "hw/qdev-clock.h" #include "hw/qdev-core.h" #include "qapi/error.h" @@ -60,6 +61,14 @@ static NamedClockList *qdev_init_clocklist(DeviceState *dev, const char *name, object_get_typename(OBJECT(clk)), (Object **) &ncl->clock, NULL, OBJ_PROP_LINK_STRONG); + /* + * Since the link property has the OBJ_PROP_LINK_STRONG flag, the clk + * object reference count gets decremented on property deletion. + * However object_property_add_link does not increment it since it + * doesn't know the linked object. Increment it here to ensure the + * aliased clock stays alive during this device life-time. + */ + object_ref(OBJECT(clk)); } ncl->clock = clk; @@ -153,6 +162,11 @@ Clock *qdev_get_clock_in(DeviceState *dev, const char *name) assert(name); ncl = qdev_get_clocklist(dev, name); + if (!ncl) { + error_report("Can not find clock-in '%s' for device type '%s'", + name, object_get_typename(OBJECT(dev))); + abort(); + } assert(!ncl->output); return ncl->clock; @@ -165,6 +179,11 @@ Clock *qdev_get_clock_out(DeviceState *dev, const char *name) assert(name); ncl = qdev_get_clocklist(dev, name); + if (!ncl) { + error_report("Can not find clock-out '%s' for device type '%s'", + name, object_get_typename(OBJECT(dev))); + abort(); + } assert(ncl->output); return ncl->clock; @@ -183,3 +202,9 @@ Clock *qdev_alias_clock(DeviceState *dev, const char *name, return ncl->clock; } + +void qdev_connect_clock_in(DeviceState *dev, const char *name, Clock *source) +{ + assert(!dev->realized); + clock_set_source(qdev_get_clock_in(dev, name), source); +} diff --git a/hw/core/qdev-prop-internal.h b/hw/core/qdev-prop-internal.h new file mode 100644 index 0000000000000000000000000000000000000000..9cf5cc1d519cbd007b2e649a149abd569a57d3aa --- /dev/null +++ b/hw/core/qdev-prop-internal.h @@ -0,0 +1,30 @@ +/* + * qdev property parsing + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_CORE_QDEV_PROP_INTERNAL_H +#define HW_CORE_QDEV_PROP_INTERNAL_H + +void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp); +void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp); + +void qdev_propinfo_set_default_value_enum(ObjectProperty *op, + const Property *prop); +void qdev_propinfo_set_default_value_int(ObjectProperty *op, + const Property *prop); +void qdev_propinfo_set_default_value_uint(ObjectProperty *op, + const Property *prop); + +void qdev_propinfo_get_uint16(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp); +void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp); +void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp); + +#endif diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 70bfd4809b1713db25eb7491d7dff13c63a5fe03..9d80a07d26f82edc11cb7cb6782f1943b141e024 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -11,71 +11,110 @@ */ #include "qemu/osdep.h" -#include "audio/audio.h" -#include "net/net.h" #include "hw/qdev-properties.h" #include "qapi/error.h" +#include "qapi/visitor.h" +#include "qapi/qapi-types-block.h" +#include "qapi/qapi-types-machine.h" +#include "qapi/qapi-types-migration.h" #include "qapi/qmp/qerror.h" +#include "qemu/ctype.h" +#include "qemu/cutils.h" +#include "qemu/units.h" +#include "qemu/error-report.h" +#include "qdev-prop-internal.h" + +#include "audio/audio.h" +#include "chardev/char-fe.h" #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" -#include "hw/block/block.h" -#include "net/hub.h" -#include "qapi/visitor.h" -#include "chardev/char-fe.h" -#include "sysemu/iothread.h" -#include "sysemu/tpm_backend.h" +#include "net/net.h" +#include "hw/pci/pci.h" +#include "util/block-helpers.h" -static void get_pointer(Object *obj, Visitor *v, Property *prop, - char *(*print)(void *ptr), - const char *name, Error **errp) +static bool check_prop_still_unset(DeviceState *dev, const char *name, + const void *old_val, const char *new_val, + Error **errp) +{ + const GlobalProperty *prop = qdev_find_global_prop(dev, name); + + if (!old_val) { + return true; + } + + if (prop) { + error_setg(errp, "-global %s.%s=... conflicts with %s=%s", + prop->driver, prop->property, name, new_val); + } else { + /* Error message is vague, but a better one would be hard */ + error_setg(errp, "%s=%s conflicts, and override is not implemented", + name, new_val); + } + return false; +} + + +/* --- drive --- */ + +static void get_drive(Object *obj, Visitor *v, const char *name, void *opaque, + Error **errp) { DeviceState *dev = DEVICE(obj); + Property *prop = opaque; void **ptr = qdev_get_prop_ptr(dev, prop); + const char *value; char *p; - p = *ptr ? print(*ptr) : g_strdup(""); + if (*ptr) { + value = blk_name(*ptr); + if (!*value) { + BlockDriverState *bs = blk_bs(*ptr); + if (bs) { + value = bdrv_get_node_name(bs); + } + } + } else { + value = ""; + } + + p = g_strdup(value); visit_type_str(v, name, &p, errp); g_free(p); } -static void set_pointer(Object *obj, Visitor *v, Property *prop, - void (*parse)(DeviceState *dev, const char *str, - void **ptr, const char *propname, - Error **errp), - const char *name, Error **errp) +static void set_drive_helper(Object *obj, Visitor *v, const char *name, + void *opaque, bool iothread, Error **errp) { DeviceState *dev = DEVICE(obj); - Error *local_err = NULL; + Property *prop = opaque; void **ptr = qdev_get_prop_ptr(dev, prop); char *str; + BlockBackend *blk; + bool blk_created = false; + int ret; if (dev->realized) { qdev_prop_set_after_realize(dev, name, errp); return; } - visit_type_str(v, name, &str, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_str(v, name, &str, errp)) { + return; + } + + /* + * TODO Should this really be an error? If no, the old value + * needs to be released before we store the new one. + */ + if (!check_prop_still_unset(dev, name, *ptr, str, errp)) { return; } + if (!*str) { g_free(str); *ptr = NULL; return; } - parse(dev, str, ptr, prop->name, errp); - g_free(str); -} - -/* --- drive --- */ - -static void do_parse_drive(DeviceState *dev, const char *str, void **ptr, - const char *propname, bool iothread, Error **errp) -{ - BlockBackend *blk; - bool blk_created = false; - int ret; blk = blk_by_name(str); if (!blk) { @@ -101,7 +140,7 @@ static void do_parse_drive(DeviceState *dev, const char *str, void **ptr, } if (!blk) { error_setg(errp, "Property '%s.%s' can't find value '%s'", - object_get_typename(OBJECT(dev)), propname, str); + object_get_typename(OBJECT(dev)), prop->name, str); goto fail; } if (blk_attach_dev(blk, dev) < 0) { @@ -126,18 +165,20 @@ fail: /* If we need to keep a reference, blk_attach_dev() took it */ blk_unref(blk); } + + g_free(str); } -static void parse_drive(DeviceState *dev, const char *str, void **ptr, - const char *propname, Error **errp) +static void set_drive(Object *obj, Visitor *v, const char *name, void *opaque, + Error **errp) { - do_parse_drive(dev, str, ptr, propname, false, errp); + set_drive_helper(obj, v, name, opaque, false, errp); } -static void parse_drive_iothread(DeviceState *dev, const char *str, void **ptr, - const char *propname, Error **errp) +static void set_drive_iothread(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { - do_parse_drive(dev, str, ptr, propname, true, errp); + set_drive_helper(obj, v, name, opaque, true, errp); } static void release_drive(Object *obj, const char *name, void *opaque) @@ -156,38 +197,6 @@ static void release_drive(Object *obj, const char *name, void *opaque) } } -static char *print_drive(void *ptr) -{ - const char *name; - - name = blk_name(ptr); - if (!*name) { - BlockDriverState *bs = blk_bs(ptr); - if (bs) { - name = bdrv_get_node_name(bs); - } - } - return g_strdup(name); -} - -static void get_drive(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) -{ - get_pointer(obj, v, opaque, print_drive, name, errp); -} - -static void set_drive(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) -{ - set_pointer(obj, v, opaque, parse_drive, name, errp); -} - -static void set_drive_iothread(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - set_pointer(obj, v, opaque, parse_drive_iothread, name, errp); -} - const PropertyInfo qdev_prop_drive = { .name = "str", .description = "Node name or ID of a block device to use as a backend", @@ -222,7 +231,6 @@ static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { DeviceState *dev = DEVICE(obj); - Error *local_err = NULL; Property *prop = opaque; CharBackend *be = qdev_get_prop_ptr(dev, prop); Chardev *s; @@ -233,9 +241,15 @@ static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque, return; } - visit_type_str(v, name, &str, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_str(v, name, &str, errp)) { + return; + } + + /* + * TODO Should this really be an error? If no, the old value + * needs to be released before we store the new one. + */ + if (!check_prop_still_unset(dev, name, be->chr, str, errp)) { return; } @@ -273,6 +287,96 @@ const PropertyInfo qdev_prop_chr = { .release = release_chr, }; +/* --- mac address --- */ + +/* + * accepted syntax versions: + * 01:02:03:04:05:06 + * 01-02-03-04-05-06 + */ +static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque, + Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + MACAddr *mac = qdev_get_prop_ptr(dev, prop); + char buffer[2 * 6 + 5 + 1]; + char *p = buffer; + + snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x", + mac->a[0], mac->a[1], mac->a[2], + mac->a[3], mac->a[4], mac->a[5]); + + visit_type_str(v, name, &p, errp); +} + +static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque, + Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + MACAddr *mac = qdev_get_prop_ptr(dev, prop); + int i, pos; + char *str; + const char *p; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + if (!visit_type_str(v, name, &str, errp)) { + return; + } + + for (i = 0, pos = 0; i < 6; i++, pos += 3) { + long val; + + if (!qemu_isxdigit(str[pos])) { + goto inval; + } + if (!qemu_isxdigit(str[pos + 1])) { + goto inval; + } + if (i == 5) { + if (str[pos + 2] != '\0') { + goto inval; + } + } else { + if (str[pos + 2] != ':' && str[pos + 2] != '-') { + goto inval; + } + } + if (qemu_strtol(str + pos, &p, 16, &val) < 0 || val > 0xff) { + goto inval; + } + mac->a[i] = val; + } + g_free(str); + return; + +inval: + error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); + g_free(str); +} + +const PropertyInfo qdev_prop_macaddr = { + .name = "str", + .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56", + .get = get_mac, + .set = set_mac, +}; + +void qdev_prop_set_macaddr(DeviceState *dev, const char *name, + const uint8_t *value) +{ + char str[2 * 6 + 5 + 1]; + snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x", + value[0], value[1], value[2], value[3], value[4], value[5]); + + object_property_set_str(OBJECT(dev), name, str, &error_abort); +} + /* --- netdev device --- */ static void get_netdev(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) @@ -294,7 +398,6 @@ static void set_netdev(Object *obj, Visitor *v, const char *name, NICPeers *peers_ptr = qdev_get_prop_ptr(dev, prop); NetClientState **ncs = peers_ptr->ncs; NetClientState *peers[MAX_QUEUE_NUM]; - Error *local_err = NULL; int queues, err = 0, i = 0; char *str; @@ -303,9 +406,7 @@ static void set_netdev(Object *obj, Visitor *v, const char *name, return; } - visit_type_str(v, name, &str, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_str(v, name, &str, errp)) { return; } @@ -324,14 +425,16 @@ static void set_netdev(Object *obj, Visitor *v, const char *name, } for (i = 0; i < queues; i++) { - if (peers[i]->peer) { err = -EEXIST; goto out; } - if (ncs[i]) { - err = -EINVAL; + /* + * TODO Should this really be an error? If no, the old value + * needs to be released before we store the new one. + */ + if (!check_prop_still_unset(dev, name, ncs[i], str, errp)) { goto out; } @@ -374,7 +477,6 @@ static void set_audiodev(Object *obj, Visitor *v, const char* name, Property *prop = opaque; QEMUSoundCard *card = qdev_get_prop_ptr(dev, prop); AudioState *state; - Error *local_err = NULL; int err = 0; char *str; @@ -383,9 +485,7 @@ static void set_audiodev(Object *obj, Visitor *v, const char* name, return; } - visit_type_str(v, name, &str, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_str(v, name, &str, errp)) { return; } @@ -410,8 +510,8 @@ const PropertyInfo qdev_prop_audiodev = { .set = set_audiodev, }; -void qdev_prop_set_drive(DeviceState *dev, const char *name, - BlockBackend *value, Error **errp) +bool qdev_prop_set_drive_err(DeviceState *dev, const char *name, + BlockBackend *value, Error **errp) { const char *ref = ""; @@ -425,23 +525,29 @@ void qdev_prop_set_drive(DeviceState *dev, const char *name, } } - object_property_set_str(OBJECT(dev), ref, name, errp); + return object_property_set_str(OBJECT(dev), name, ref, errp); +} + +void qdev_prop_set_drive(DeviceState *dev, const char *name, + BlockBackend *value) +{ + qdev_prop_set_drive_err(dev, name, value, &error_abort); } void qdev_prop_set_chr(DeviceState *dev, const char *name, Chardev *value) { assert(!value || value->label); - object_property_set_str(OBJECT(dev), - value ? value->label : "", name, &error_abort); + object_property_set_str(OBJECT(dev), name, value ? value->label : "", + &error_abort); } void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value) { assert(!value || value->name); - object_property_set_str(OBJECT(dev), - value ? value->name : "", name, &error_abort); + object_property_set_str(OBJECT(dev), name, value ? value->name : "", + &error_abort); } void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) @@ -451,8 +557,562 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) qdev_prop_set_netdev(dev, "netdev", nd->netdev); } if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED && - object_property_find(OBJECT(dev), "vectors", NULL)) { + object_property_find(OBJECT(dev), "vectors")) { qdev_prop_set_uint32(dev, "vectors", nd->nvectors); } nd->instantiated = 1; } + +/* --- lost tick policy --- */ + +QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int)); + +const PropertyInfo qdev_prop_losttickpolicy = { + .name = "LostTickPolicy", + .enum_table = &LostTickPolicy_lookup, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; + +/* --- blocksize --- */ + +static void set_blocksize(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + uint32_t *ptr = qdev_get_prop_ptr(dev, prop); + uint64_t value; + Error *local_err = NULL; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + if (!visit_type_size(v, name, &value, errp)) { + return; + } + check_block_size(dev->id ? : "", name, value, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + *ptr = value; +} + +const PropertyInfo qdev_prop_blocksize = { + .name = "size", + .description = "A power of two between " MIN_BLOCK_SIZE_STR + " and " MAX_BLOCK_SIZE_STR, + .get = qdev_propinfo_get_size32, + .set = set_blocksize, + .set_default_value = qdev_propinfo_set_default_value_uint, +}; + +/* --- Block device error handling policy --- */ + +QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int)); + +const PropertyInfo qdev_prop_blockdev_on_error = { + .name = "BlockdevOnError", + .description = "Error handling policy, " + "report/ignore/enospc/stop/auto", + .enum_table = &BlockdevOnError_lookup, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; + +/* --- BIOS CHS translation */ + +QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int)); + +const PropertyInfo qdev_prop_bios_chs_trans = { + .name = "BiosAtaTranslation", + .description = "Logical CHS translation algorithm, " + "auto/none/lba/large/rechs", + .enum_table = &BiosAtaTranslation_lookup, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; + +/* --- FDC default drive types */ + +const PropertyInfo qdev_prop_fdc_drive_type = { + .name = "FdcDriveType", + .description = "FDC drive type, " + "144/288/120/none/auto", + .enum_table = &FloppyDriveType_lookup, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; + +/* --- MultiFDCompression --- */ + +const PropertyInfo qdev_prop_multifd_compression = { + .name = "MultiFDCompression", + .description = "multifd_compression values, " + "none/zlib/zstd", + .enum_table = &MultiFDCompression_lookup, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; + +/* --- Reserved Region --- */ + +/* + * Accepted syntax: + * :: + * where low/high addresses are uint64_t in hexadecimal + * and type is a non-negative decimal integer + */ +static void get_reserved_region(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + ReservedRegion *rr = qdev_get_prop_ptr(dev, prop); + char buffer[64]; + char *p = buffer; + int rc; + + rc = snprintf(buffer, sizeof(buffer), "0x%"PRIx64":0x%"PRIx64":%u", + rr->low, rr->high, rr->type); + assert(rc < sizeof(buffer)); + + visit_type_str(v, name, &p, errp); +} + +static void set_reserved_region(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + ReservedRegion *rr = qdev_get_prop_ptr(dev, prop); + Error *local_err = NULL; + const char *endptr; + char *str; + int ret; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + visit_type_str(v, name, &str, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + ret = qemu_strtou64(str, &endptr, 16, &rr->low); + if (ret) { + error_setg(errp, "start address of '%s'" + " must be a hexadecimal integer", name); + goto out; + } + if (*endptr != ':') { + goto separator_error; + } + + ret = qemu_strtou64(endptr + 1, &endptr, 16, &rr->high); + if (ret) { + error_setg(errp, "end address of '%s'" + " must be a hexadecimal integer", name); + goto out; + } + if (*endptr != ':') { + goto separator_error; + } + + ret = qemu_strtoui(endptr + 1, &endptr, 10, &rr->type); + if (ret) { + error_setg(errp, "type of '%s'" + " must be a non-negative decimal integer", name); + } + goto out; + +separator_error: + error_setg(errp, "reserved region fields must be separated with ':'"); +out: + g_free(str); + return; +} + +const PropertyInfo qdev_prop_reserved_region = { + .name = "reserved_region", + .description = "Reserved Region, example: 0xFEE00000:0xFEEFFFFF:0", + .get = get_reserved_region, + .set = set_reserved_region, +}; + +/* --- pci address --- */ + +/* + * bus-local address, i.e. "$slot" or "$slot.$fn" + */ +static void set_pci_devfn(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + int32_t value, *ptr = qdev_get_prop_ptr(dev, prop); + unsigned int slot, fn, n; + char *str; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + if (!visit_type_str(v, name, &str, NULL)) { + if (!visit_type_int32(v, name, &value, errp)) { + return; + } + if (value < -1 || value > 255) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + name ? name : "null", "pci_devfn"); + return; + } + *ptr = value; + return; + } + + if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) { + fn = 0; + if (sscanf(str, "%x%n", &slot, &n) != 1) { + goto invalid; + } + } + if (str[n] != '\0' || fn > 7 || slot > 31) { + goto invalid; + } + *ptr = slot << 3 | fn; + g_free(str); + return; + +invalid: + error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); + g_free(str); +} + +static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, + size_t len) +{ + int32_t *ptr = qdev_get_prop_ptr(dev, prop); + + if (*ptr == -1) { + return snprintf(dest, len, ""); + } else { + return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7); + } +} + +const PropertyInfo qdev_prop_pci_devfn = { + .name = "int32", + .description = "Slot and optional function number, example: 06.0 or 06", + .print = print_pci_devfn, + .get = qdev_propinfo_get_int32, + .set = set_pci_devfn, + .set_default_value = qdev_propinfo_set_default_value_int, +}; + +/* --- pci host address --- */ + +static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop); + char buffer[] = "ffff:ff:ff.f"; + char *p = buffer; + int rc = 0; + + /* + * Catch "invalid" device reference from vfio-pci and allow the + * default buffer representing the non-existent device to be used. + */ + if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) { + rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d", + addr->domain, addr->bus, addr->slot, addr->function); + assert(rc == sizeof(buffer) - 1); + } + + visit_type_str(v, name, &p, errp); +} + +/* + * Parse [:]:. + * if is not supplied, it's assumed to be 0. + */ +static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop); + char *str, *p; + char *e; + unsigned long val; + unsigned long dom = 0, bus = 0; + unsigned int slot = 0, func = 0; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + if (!visit_type_str(v, name, &str, errp)) { + return; + } + + p = str; + val = strtoul(p, &e, 16); + if (e == p || *e != ':') { + goto inval; + } + bus = val; + + p = e + 1; + val = strtoul(p, &e, 16); + if (e == p) { + goto inval; + } + if (*e == ':') { + dom = bus; + bus = val; + p = e + 1; + val = strtoul(p, &e, 16); + if (e == p) { + goto inval; + } + } + slot = val; + + if (*e != '.') { + goto inval; + } + p = e + 1; + val = strtoul(p, &e, 10); + if (e == p) { + goto inval; + } + func = val; + + if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) { + goto inval; + } + + if (*e) { + goto inval; + } + + addr->domain = dom; + addr->bus = bus; + addr->slot = slot; + addr->function = func; + + g_free(str); + return; + +inval: + error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); + g_free(str); +} + +const PropertyInfo qdev_prop_pci_host_devaddr = { + .name = "str", + .description = "Address (bus/device/function) of " + "the host device, example: 04:10.0", + .get = get_pci_host_devaddr, + .set = set_pci_host_devaddr, +}; + +/* --- OffAutoPCIBAR off/auto/bar0/bar1/bar2/bar3/bar4/bar5 --- */ + +const PropertyInfo qdev_prop_off_auto_pcibar = { + .name = "OffAutoPCIBAR", + .description = "off/auto/bar0/bar1/bar2/bar3/bar4/bar5", + .enum_table = &OffAutoPCIBAR_lookup, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; + +/* --- PCIELinkSpeed 2_5/5/8/16 -- */ + +static void get_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop); + int speed; + + switch (*p) { + case QEMU_PCI_EXP_LNK_2_5GT: + speed = PCIE_LINK_SPEED_2_5; + break; + case QEMU_PCI_EXP_LNK_5GT: + speed = PCIE_LINK_SPEED_5; + break; + case QEMU_PCI_EXP_LNK_8GT: + speed = PCIE_LINK_SPEED_8; + break; + case QEMU_PCI_EXP_LNK_16GT: + speed = PCIE_LINK_SPEED_16; + break; + default: + /* Unreachable */ + abort(); + } + + visit_type_enum(v, prop->name, &speed, prop->info->enum_table, errp); +} + +static void set_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop); + int speed; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + if (!visit_type_enum(v, prop->name, &speed, prop->info->enum_table, + errp)) { + return; + } + + switch (speed) { + case PCIE_LINK_SPEED_2_5: + *p = QEMU_PCI_EXP_LNK_2_5GT; + break; + case PCIE_LINK_SPEED_5: + *p = QEMU_PCI_EXP_LNK_5GT; + break; + case PCIE_LINK_SPEED_8: + *p = QEMU_PCI_EXP_LNK_8GT; + break; + case PCIE_LINK_SPEED_16: + *p = QEMU_PCI_EXP_LNK_16GT; + break; + default: + /* Unreachable */ + abort(); + } +} + +const PropertyInfo qdev_prop_pcie_link_speed = { + .name = "PCIELinkSpeed", + .description = "2_5/5/8/16", + .enum_table = &PCIELinkSpeed_lookup, + .get = get_prop_pcielinkspeed, + .set = set_prop_pcielinkspeed, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; + +/* --- PCIELinkWidth 1/2/4/8/12/16/32 -- */ + +static void get_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop); + int width; + + switch (*p) { + case QEMU_PCI_EXP_LNK_X1: + width = PCIE_LINK_WIDTH_1; + break; + case QEMU_PCI_EXP_LNK_X2: + width = PCIE_LINK_WIDTH_2; + break; + case QEMU_PCI_EXP_LNK_X4: + width = PCIE_LINK_WIDTH_4; + break; + case QEMU_PCI_EXP_LNK_X8: + width = PCIE_LINK_WIDTH_8; + break; + case QEMU_PCI_EXP_LNK_X12: + width = PCIE_LINK_WIDTH_12; + break; + case QEMU_PCI_EXP_LNK_X16: + width = PCIE_LINK_WIDTH_16; + break; + case QEMU_PCI_EXP_LNK_X32: + width = PCIE_LINK_WIDTH_32; + break; + default: + /* Unreachable */ + abort(); + } + + visit_type_enum(v, prop->name, &width, prop->info->enum_table, errp); +} + +static void set_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop); + int width; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + if (!visit_type_enum(v, prop->name, &width, prop->info->enum_table, + errp)) { + return; + } + + switch (width) { + case PCIE_LINK_WIDTH_1: + *p = QEMU_PCI_EXP_LNK_X1; + break; + case PCIE_LINK_WIDTH_2: + *p = QEMU_PCI_EXP_LNK_X2; + break; + case PCIE_LINK_WIDTH_4: + *p = QEMU_PCI_EXP_LNK_X4; + break; + case PCIE_LINK_WIDTH_8: + *p = QEMU_PCI_EXP_LNK_X8; + break; + case PCIE_LINK_WIDTH_12: + *p = QEMU_PCI_EXP_LNK_X12; + break; + case PCIE_LINK_WIDTH_16: + *p = QEMU_PCI_EXP_LNK_X16; + break; + case PCIE_LINK_WIDTH_32: + *p = QEMU_PCI_EXP_LNK_X32; + break; + default: + /* Unreachable */ + abort(); + } +} + +const PropertyInfo qdev_prop_pcie_link_width = { + .name = "PCIELinkWidth", + .description = "1/2/4/8/12/16/32", + .enum_table = &PCIELinkWidth_lookup, + .get = get_prop_pcielinkwidth, + .set = set_prop_pcielinkwidth, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index cc924815da5460035df5992ce2fb2c1062440021..509cbf155d2acc06e0627a1b612cb18b51378f2a 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -1,19 +1,15 @@ #include "qemu/osdep.h" -#include "net/net.h" #include "hw/qdev-properties.h" #include "qapi/error.h" -#include "hw/pci/pci.h" -#include "qapi/qapi-types-block.h" #include "qapi/qapi-types-misc.h" #include "qapi/qmp/qerror.h" #include "qemu/ctype.h" #include "qemu/error-report.h" -#include "qapi/qapi-types-migration.h" -#include "hw/block/block.h" -#include "net/hub.h" #include "qapi/visitor.h" -#include "chardev/char.h" #include "qemu/uuid.h" +#include "qemu/units.h" +#include "qemu/cutils.h" +#include "qdev-prop-internal.h" void qdev_prop_set_after_realize(DeviceState *dev, const char *name, Error **errp) @@ -49,8 +45,8 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) return ptr; } -static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) +void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { DeviceState *dev = DEVICE(obj); Property *prop = opaque; @@ -59,8 +55,8 @@ static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque, visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp); } -static void set_enum(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) +void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { DeviceState *dev = DEVICE(obj); Property *prop = opaque; @@ -74,12 +70,20 @@ static void set_enum(Object *obj, Visitor *v, const char *name, void *opaque, visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp); } -static void set_default_value_enum(ObjectProperty *op, const Property *prop) +void qdev_propinfo_set_default_value_enum(ObjectProperty *op, + const Property *prop) { object_property_set_default_str(op, qapi_enum_lookup(prop->info->enum_table, prop->defval.i)); } +const PropertyInfo qdev_prop_enum = { + .name = "enum", + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; + /* Bit */ static uint32_t qdev_get_prop_mask(Property *prop) @@ -115,7 +119,6 @@ static void prop_set_bit(Object *obj, Visitor *v, const char *name, { DeviceState *dev = DEVICE(obj); Property *prop = opaque; - Error *local_err = NULL; bool value; if (dev->realized) { @@ -123,9 +126,7 @@ static void prop_set_bit(Object *obj, Visitor *v, const char *name, return; } - visit_type_bool(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_bool(v, name, &value, errp)) { return; } bit_prop_set(dev, prop, value); @@ -179,7 +180,6 @@ static void prop_set_bit64(Object *obj, Visitor *v, const char *name, { DeviceState *dev = DEVICE(obj); Property *prop = opaque; - Error *local_err = NULL; bool value; if (dev->realized) { @@ -187,9 +187,7 @@ static void prop_set_bit64(Object *obj, Visitor *v, const char *name, return; } - visit_type_bool(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_bool(v, name, &value, errp)) { return; } bit64_prop_set(dev, prop, value); @@ -264,12 +262,14 @@ static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque, visit_type_uint8(v, name, ptr, errp); } -static void set_default_value_int(ObjectProperty *op, const Property *prop) +void qdev_propinfo_set_default_value_int(ObjectProperty *op, + const Property *prop) { object_property_set_default_int(op, prop->defval.i); } -static void set_default_value_uint(ObjectProperty *op, const Property *prop) +void qdev_propinfo_set_default_value_uint(ObjectProperty *op, + const Property *prop) { object_property_set_default_uint(op, prop->defval.u); } @@ -278,13 +278,13 @@ const PropertyInfo qdev_prop_uint8 = { .name = "uint8", .get = get_uint8, .set = set_uint8, - .set_default_value = set_default_value_uint, + .set_default_value = qdev_propinfo_set_default_value_uint, }; /* --- 16bit integer --- */ -static void get_uint16(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) +void qdev_propinfo_get_uint16(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { DeviceState *dev = DEVICE(obj); Property *prop = opaque; @@ -310,9 +310,9 @@ static void set_uint16(Object *obj, Visitor *v, const char *name, const PropertyInfo qdev_prop_uint16 = { .name = "uint16", - .get = get_uint16, + .get = qdev_propinfo_get_uint16, .set = set_uint16, - .set_default_value = set_default_value_uint, + .set_default_value = qdev_propinfo_set_default_value_uint, }; /* --- 32bit integer --- */ @@ -342,8 +342,8 @@ static void set_uint32(Object *obj, Visitor *v, const char *name, visit_type_uint32(v, name, ptr, errp); } -static void get_int32(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) +void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { DeviceState *dev = DEVICE(obj); Property *prop = opaque; @@ -371,14 +371,14 @@ const PropertyInfo qdev_prop_uint32 = { .name = "uint32", .get = get_uint32, .set = set_uint32, - .set_default_value = set_default_value_uint, + .set_default_value = qdev_propinfo_set_default_value_uint, }; const PropertyInfo qdev_prop_int32 = { .name = "int32", - .get = get_int32, + .get = qdev_propinfo_get_int32, .set = set_int32, - .set_default_value = set_default_value_int, + .set_default_value = qdev_propinfo_set_default_value_int, }; /* --- 64bit integer --- */ @@ -437,14 +437,14 @@ const PropertyInfo qdev_prop_uint64 = { .name = "uint64", .get = get_uint64, .set = set_uint64, - .set_default_value = set_default_value_uint, + .set_default_value = qdev_propinfo_set_default_value_uint, }; const PropertyInfo qdev_prop_int64 = { .name = "int64", .get = get_int64, .set = set_int64, - .set_default_value = set_default_value_int, + .set_default_value = qdev_propinfo_set_default_value_int, }; /* --- string --- */ @@ -476,7 +476,6 @@ static void set_string(Object *obj, Visitor *v, const char *name, DeviceState *dev = DEVICE(obj); Property *prop = opaque; char **ptr = qdev_get_prop_ptr(dev, prop); - Error *local_err = NULL; char *str; if (dev->realized) { @@ -484,9 +483,7 @@ static void set_string(Object *obj, Visitor *v, const char *name, return; } - visit_type_str(v, name, &str, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_str(v, name, &str, errp)) { return; } g_free(*ptr); @@ -500,394 +497,63 @@ const PropertyInfo qdev_prop_string = { .set = set_string, }; -/* --- mac address --- */ - -/* - * accepted syntax versions: - * 01:02:03:04:05:06 - * 01-02-03-04-05-06 - */ -static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - MACAddr *mac = qdev_get_prop_ptr(dev, prop); - char buffer[2 * 6 + 5 + 1]; - char *p = buffer; - - snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x", - mac->a[0], mac->a[1], mac->a[2], - mac->a[3], mac->a[4], mac->a[5]); - - visit_type_str(v, name, &p, errp); -} - -static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - MACAddr *mac = qdev_get_prop_ptr(dev, prop); - Error *local_err = NULL; - int i, pos; - char *str, *p; - - if (dev->realized) { - qdev_prop_set_after_realize(dev, name, errp); - return; - } - - visit_type_str(v, name, &str, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - - for (i = 0, pos = 0; i < 6; i++, pos += 3) { - if (!qemu_isxdigit(str[pos])) { - goto inval; - } - if (!qemu_isxdigit(str[pos+1])) { - goto inval; - } - if (i == 5) { - if (str[pos+2] != '\0') { - goto inval; - } - } else { - if (str[pos+2] != ':' && str[pos+2] != '-') { - goto inval; - } - } - mac->a[i] = strtol(str+pos, &p, 16); - } - g_free(str); - return; - -inval: - error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); - g_free(str); -} - -const PropertyInfo qdev_prop_macaddr = { - .name = "str", - .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56", - .get = get_mac, - .set = set_mac, -}; - /* --- on/off/auto --- */ const PropertyInfo qdev_prop_on_off_auto = { .name = "OnOffAuto", .description = "on/off/auto", .enum_table = &OnOffAuto_lookup, - .get = get_enum, - .set = set_enum, - .set_default_value = set_default_value_enum, -}; - -/* --- lost tick policy --- */ - -QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int)); - -const PropertyInfo qdev_prop_losttickpolicy = { - .name = "LostTickPolicy", - .enum_table = &LostTickPolicy_lookup, - .get = get_enum, - .set = set_enum, - .set_default_value = set_default_value_enum, -}; - -/* --- Block device error handling policy --- */ - -QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int)); - -const PropertyInfo qdev_prop_blockdev_on_error = { - .name = "BlockdevOnError", - .description = "Error handling policy, " - "report/ignore/enospc/stop/auto", - .enum_table = &BlockdevOnError_lookup, - .get = get_enum, - .set = set_enum, - .set_default_value = set_default_value_enum, -}; - -/* --- BIOS CHS translation */ - -QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int)); - -const PropertyInfo qdev_prop_bios_chs_trans = { - .name = "BiosAtaTranslation", - .description = "Logical CHS translation algorithm, " - "auto/none/lba/large/rechs", - .enum_table = &BiosAtaTranslation_lookup, - .get = get_enum, - .set = set_enum, - .set_default_value = set_default_value_enum, -}; - -/* --- FDC default drive types */ - -const PropertyInfo qdev_prop_fdc_drive_type = { - .name = "FdcDriveType", - .description = "FDC drive type, " - "144/288/120/none/auto", - .enum_table = &FloppyDriveType_lookup, - .get = get_enum, - .set = set_enum, - .set_default_value = set_default_value_enum, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, }; -/* --- MultiFDCompression --- */ +/* --- 32bit unsigned int 'size' type --- */ -const PropertyInfo qdev_prop_multifd_compression = { - .name = "MultiFDCompression", - .description = "multifd_compression values, " - "none/zlib/zstd", - .enum_table = &MultiFDCompression_lookup, - .get = get_enum, - .set = set_enum, - .set_default_value = set_default_value_enum, -}; - -/* --- pci address --- */ - -/* - * bus-local address, i.e. "$slot" or "$slot.$fn" - */ -static void set_pci_devfn(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) +void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { DeviceState *dev = DEVICE(obj); Property *prop = opaque; - int32_t value, *ptr = qdev_get_prop_ptr(dev, prop); - unsigned int slot, fn, n; - Error *local_err = NULL; - char *str; - - if (dev->realized) { - qdev_prop_set_after_realize(dev, name, errp); - return; - } - - visit_type_str(v, name, &str, &local_err); - if (local_err) { - error_free(local_err); - local_err = NULL; - visit_type_int32(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); - } else if (value < -1 || value > 255) { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, - name ? name : "null", "pci_devfn"); - } else { - *ptr = value; - } - return; - } - - if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) { - fn = 0; - if (sscanf(str, "%x%n", &slot, &n) != 1) { - goto invalid; - } - } - if (str[n] != '\0' || fn > 7 || slot > 31) { - goto invalid; - } - *ptr = slot << 3 | fn; - g_free(str); - return; + uint32_t *ptr = qdev_get_prop_ptr(dev, prop); + uint64_t value = *ptr; -invalid: - error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); - g_free(str); + visit_type_size(v, name, &value, errp); } -static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, - size_t len) -{ - int32_t *ptr = qdev_get_prop_ptr(dev, prop); - - if (*ptr == -1) { - return snprintf(dest, len, ""); - } else { - return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7); - } -} - -const PropertyInfo qdev_prop_pci_devfn = { - .name = "int32", - .description = "Slot and optional function number, example: 06.0 or 06", - .print = print_pci_devfn, - .get = get_int32, - .set = set_pci_devfn, - .set_default_value = set_default_value_int, -}; - -/* --- blocksize --- */ - -static void set_blocksize(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) +static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque, + Error **errp) { DeviceState *dev = DEVICE(obj); Property *prop = opaque; - uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop); - Error *local_err = NULL; - const int64_t min = 512; - const int64_t max = 32768; + uint32_t *ptr = qdev_get_prop_ptr(dev, prop); + uint64_t value; if (dev->realized) { qdev_prop_set_after_realize(dev, name, errp); return; } - visit_type_uint16(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - /* value of 0 means "unset" */ - if (value && (value < min || value > max)) { - error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, - dev->id ? : "", name, (int64_t)value, min, max); + if (!visit_type_size(v, name, &value, errp)) { return; } - /* We rely on power-of-2 blocksizes for bitmasks */ - if ((value & (value - 1)) != 0) { + if (value > UINT32_MAX) { error_setg(errp, - "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2", - dev->id ?: "", name, (int64_t)value); + "Property %s.%s doesn't take value %" PRIu64 + " (maximum: %u)", + dev->id ? : "", name, value, UINT32_MAX); return; } *ptr = value; } -const PropertyInfo qdev_prop_blocksize = { - .name = "uint16", - .description = "A power of two between 512 and 32768", - .get = get_uint16, - .set = set_blocksize, - .set_default_value = set_default_value_uint, -}; - -/* --- pci host address --- */ - -static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop); - char buffer[] = "ffff:ff:ff.f"; - char *p = buffer; - int rc = 0; - - /* - * Catch "invalid" device reference from vfio-pci and allow the - * default buffer representing the non-existent device to be used. - */ - if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) { - rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d", - addr->domain, addr->bus, addr->slot, addr->function); - assert(rc == sizeof(buffer) - 1); - } - - visit_type_str(v, name, &p, errp); -} - -/* - * Parse [:]:. - * if is not supplied, it's assumed to be 0. - */ -static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop); - Error *local_err = NULL; - char *str, *p; - char *e; - unsigned long val; - unsigned long dom = 0, bus = 0; - unsigned int slot = 0, func = 0; - - if (dev->realized) { - qdev_prop_set_after_realize(dev, name, errp); - return; - } - - visit_type_str(v, name, &str, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - - p = str; - val = strtoul(p, &e, 16); - if (e == p || *e != ':') { - goto inval; - } - bus = val; - - p = e + 1; - val = strtoul(p, &e, 16); - if (e == p) { - goto inval; - } - if (*e == ':') { - dom = bus; - bus = val; - p = e + 1; - val = strtoul(p, &e, 16); - if (e == p) { - goto inval; - } - } - slot = val; - - if (*e != '.') { - goto inval; - } - p = e + 1; - val = strtoul(p, &e, 10); - if (e == p) { - goto inval; - } - func = val; - - if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) { - goto inval; - } - - if (*e) { - goto inval; - } - - addr->domain = dom; - addr->bus = bus; - addr->slot = slot; - addr->function = func; - - g_free(str); - return; - -inval: - error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); - g_free(str); -} - -const PropertyInfo qdev_prop_pci_host_devaddr = { - .name = "str", - .description = "Address (bus/device/function) of " - "the host device, example: 04:10.0", - .get = get_pci_host_devaddr, - .set = set_pci_host_devaddr, +const PropertyInfo qdev_prop_size32 = { + .name = "size", + .get = qdev_propinfo_get_size32, + .set = set_size32, + .set_default_value = qdev_propinfo_set_default_value_uint, }; /* --- UUID --- */ @@ -914,7 +580,6 @@ static void set_uuid(Object *obj, Visitor *v, const char *name, void *opaque, DeviceState *dev = DEVICE(obj); Property *prop = opaque; QemuUUID *uuid = qdev_get_prop_ptr(dev, prop); - Error *local_err = NULL; char *str; if (dev->realized) { @@ -922,9 +587,7 @@ static void set_uuid(Object *obj, Visitor *v, const char *name, void *opaque, return; } - visit_type_str(v, name, &str, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_str(v, name, &str, errp)) { return; } @@ -990,7 +653,6 @@ static void set_prop_arraylen(Object *obj, Visitor *v, const char *name, Property *prop = opaque; uint32_t *alenptr = qdev_get_prop_ptr(dev, prop); void **arrayptr = (void *)dev + prop->arrayoffset; - Error *local_err = NULL; void *eltptr; const char *arrayname; int i; @@ -1004,9 +666,7 @@ static void set_prop_arraylen(Object *obj, Visitor *v, const char *name, name); return; } - visit_type_uint32(v, name, alenptr, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_uint32(v, name, alenptr, errp)) { return; } if (!*alenptr) { @@ -1051,7 +711,7 @@ const PropertyInfo qdev_prop_arraylen = { .name = "uint32", .get = get_uint32, .set = set_prop_arraylen, - .set_default_value = set_default_value_uint, + .set_default_value = qdev_propinfo_set_default_value_uint, }; /* --- public helpers --- */ @@ -1112,47 +772,37 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value) { - object_property_set_bool(OBJECT(dev), value, name, &error_abort); + object_property_set_bool(OBJECT(dev), name, value, &error_abort); } void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value) { - object_property_set_int(OBJECT(dev), value, name, &error_abort); + object_property_set_int(OBJECT(dev), name, value, &error_abort); } void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value) { - object_property_set_int(OBJECT(dev), value, name, &error_abort); + object_property_set_int(OBJECT(dev), name, value, &error_abort); } void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value) { - object_property_set_int(OBJECT(dev), value, name, &error_abort); + object_property_set_int(OBJECT(dev), name, value, &error_abort); } void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value) { - object_property_set_int(OBJECT(dev), value, name, &error_abort); + object_property_set_int(OBJECT(dev), name, value, &error_abort); } void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value) { - object_property_set_int(OBJECT(dev), value, name, &error_abort); + object_property_set_int(OBJECT(dev), name, value, &error_abort); } void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value) { - object_property_set_str(OBJECT(dev), value, name, &error_abort); -} - -void qdev_prop_set_macaddr(DeviceState *dev, const char *name, - const uint8_t *value) -{ - char str[2 * 6 + 5 + 1]; - snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x", - value[0], value[1], value[2], value[3], value[4], value[5]); - - object_property_set_str(OBJECT(dev), str, name, &error_abort); + object_property_set_str(OBJECT(dev), name, value, &error_abort); } void qdev_prop_set_enum(DeviceState *dev, const char *name, int value) @@ -1160,9 +810,9 @@ void qdev_prop_set_enum(DeviceState *dev, const char *name, int value) Property *prop; prop = qdev_prop_find(dev, name); - object_property_set_str(OBJECT(dev), + object_property_set_str(OBJECT(dev), name, qapi_enum_lookup(prop->info->enum_table, value), - name, &error_abort); + &error_abort); } static GPtrArray *global_props(void) @@ -1181,6 +831,23 @@ void qdev_prop_register_global(GlobalProperty *prop) g_ptr_array_add(global_props(), prop); } +const GlobalProperty *qdev_find_global_prop(DeviceState *dev, + const char *name) +{ + GPtrArray *props = global_props(); + const GlobalProperty *p; + int i; + + for (i = 0; i < props->len; i++) { + p = g_ptr_array_index(props, i); + if (object_dynamic_cast(OBJECT(dev), p->driver) + && !strcmp(p->property, name)) { + return p; + } + } + return NULL; +} + int qdev_prop_check_globals(void) { int i, ret = 0; @@ -1245,7 +912,7 @@ const PropertyInfo qdev_prop_size = { .name = "size", .get = get_size, .set = set_size, - .set_default_value = set_default_value_uint, + .set_default_value = qdev_propinfo_set_default_value_uint, }; /* --- object link property --- */ @@ -1262,190 +929,3 @@ const PropertyInfo qdev_prop_link = { .name = "link", .create = create_link_property, }; - -/* --- OffAutoPCIBAR off/auto/bar0/bar1/bar2/bar3/bar4/bar5 --- */ - -const PropertyInfo qdev_prop_off_auto_pcibar = { - .name = "OffAutoPCIBAR", - .description = "off/auto/bar0/bar1/bar2/bar3/bar4/bar5", - .enum_table = &OffAutoPCIBAR_lookup, - .get = get_enum, - .set = set_enum, - .set_default_value = set_default_value_enum, -}; - -/* --- PCIELinkSpeed 2_5/5/8/16 -- */ - -static void get_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop); - int speed; - - switch (*p) { - case QEMU_PCI_EXP_LNK_2_5GT: - speed = PCIE_LINK_SPEED_2_5; - break; - case QEMU_PCI_EXP_LNK_5GT: - speed = PCIE_LINK_SPEED_5; - break; - case QEMU_PCI_EXP_LNK_8GT: - speed = PCIE_LINK_SPEED_8; - break; - case QEMU_PCI_EXP_LNK_16GT: - speed = PCIE_LINK_SPEED_16; - break; - default: - /* Unreachable */ - abort(); - } - - visit_type_enum(v, prop->name, &speed, prop->info->enum_table, errp); -} - -static void set_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop); - int speed; - Error *local_err = NULL; - - if (dev->realized) { - qdev_prop_set_after_realize(dev, name, errp); - return; - } - - visit_type_enum(v, prop->name, &speed, prop->info->enum_table, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - - switch (speed) { - case PCIE_LINK_SPEED_2_5: - *p = QEMU_PCI_EXP_LNK_2_5GT; - break; - case PCIE_LINK_SPEED_5: - *p = QEMU_PCI_EXP_LNK_5GT; - break; - case PCIE_LINK_SPEED_8: - *p = QEMU_PCI_EXP_LNK_8GT; - break; - case PCIE_LINK_SPEED_16: - *p = QEMU_PCI_EXP_LNK_16GT; - break; - default: - /* Unreachable */ - abort(); - } -} - -const PropertyInfo qdev_prop_pcie_link_speed = { - .name = "PCIELinkSpeed", - .description = "2_5/5/8/16", - .enum_table = &PCIELinkSpeed_lookup, - .get = get_prop_pcielinkspeed, - .set = set_prop_pcielinkspeed, - .set_default_value = set_default_value_enum, -}; - -/* --- PCIELinkWidth 1/2/4/8/12/16/32 -- */ - -static void get_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop); - int width; - - switch (*p) { - case QEMU_PCI_EXP_LNK_X1: - width = PCIE_LINK_WIDTH_1; - break; - case QEMU_PCI_EXP_LNK_X2: - width = PCIE_LINK_WIDTH_2; - break; - case QEMU_PCI_EXP_LNK_X4: - width = PCIE_LINK_WIDTH_4; - break; - case QEMU_PCI_EXP_LNK_X8: - width = PCIE_LINK_WIDTH_8; - break; - case QEMU_PCI_EXP_LNK_X12: - width = PCIE_LINK_WIDTH_12; - break; - case QEMU_PCI_EXP_LNK_X16: - width = PCIE_LINK_WIDTH_16; - break; - case QEMU_PCI_EXP_LNK_X32: - width = PCIE_LINK_WIDTH_32; - break; - default: - /* Unreachable */ - abort(); - } - - visit_type_enum(v, prop->name, &width, prop->info->enum_table, errp); -} - -static void set_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop); - int width; - Error *local_err = NULL; - - if (dev->realized) { - qdev_prop_set_after_realize(dev, name, errp); - return; - } - - visit_type_enum(v, prop->name, &width, prop->info->enum_table, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - - switch (width) { - case PCIE_LINK_WIDTH_1: - *p = QEMU_PCI_EXP_LNK_X1; - break; - case PCIE_LINK_WIDTH_2: - *p = QEMU_PCI_EXP_LNK_X2; - break; - case PCIE_LINK_WIDTH_4: - *p = QEMU_PCI_EXP_LNK_X4; - break; - case PCIE_LINK_WIDTH_8: - *p = QEMU_PCI_EXP_LNK_X8; - break; - case PCIE_LINK_WIDTH_12: - *p = QEMU_PCI_EXP_LNK_X12; - break; - case PCIE_LINK_WIDTH_16: - *p = QEMU_PCI_EXP_LNK_X16; - break; - case PCIE_LINK_WIDTH_32: - *p = QEMU_PCI_EXP_LNK_X32; - break; - default: - /* Unreachable */ - abort(); - } -} - -const PropertyInfo qdev_prop_pcie_link_width = { - .name = "PCIELinkWidth", - .description = "1/2/4/8/12/16/32", - .enum_table = &PCIELinkWidth_lookup, - .get = get_prop_pcielinkwidth, - .set = set_prop_pcielinkwidth, - .set_default_value = set_default_value_enum, -}; diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 9e5538aeaebd999407f54ac2cebc7a12f7acb374..262bca716f5e56c0ef8dce24c1c0b5cc49ef679c 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -51,6 +51,12 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev) return dc->vmsd; } +static void bus_free_bus_child(BusChild *kid) +{ + object_unref(OBJECT(kid->child)); + g_free(kid); +} + static void bus_remove_child(BusState *bus, DeviceState *child) { BusChild *kid; @@ -60,15 +66,16 @@ static void bus_remove_child(BusState *bus, DeviceState *child) char name[32]; snprintf(name, sizeof(name), "child[%d]", kid->index); - QTAILQ_REMOVE(&bus->children, kid, sibling); + QTAILQ_REMOVE_RCU(&bus->children, kid, sibling); bus->num_children--; /* This gives back ownership of kid->child back to us. */ object_property_del(OBJECT(bus), name); - object_unref(OBJECT(kid->child)); - g_free(kid); - return; + + /* free the bus kid, when it is safe to do so*/ + call_rcu(kid, bus_free_bus_child, rcu); + break; } } } @@ -83,7 +90,7 @@ static void bus_add_child(BusState *bus, DeviceState *child) kid->child = child; object_ref(OBJECT(kid->child)); - QTAILQ_INSERT_HEAD(&bus->children, kid, sibling); + QTAILQ_INSERT_HEAD_RCU(&bus->children, kid, sibling); /* This transfers ownership of kid->child to the property. */ snprintf(name, sizeof(name), "child[%d]", kid->index); @@ -94,9 +101,22 @@ static void bus_add_child(BusState *bus, DeviceState *child) 0); } -void qdev_set_parent_bus(DeviceState *dev, BusState *bus) +static bool bus_check_address(BusState *bus, DeviceState *child, Error **errp) +{ + BusClass *bc = BUS_GET_CLASS(bus); + return !bc->check_address || bc->check_address(bus, child, errp); +} + +bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp) { BusState *old_parent_bus = dev->parent_bus; + DeviceClass *dc = DEVICE_GET_CLASS(dev); + + assert(dc->bus_type && object_dynamic_cast(OBJECT(bus), dc->bus_type)); + + if (!bus_check_address(bus, dev, errp)) { + return false; + } if (old_parent_bus) { trace_qdev_update_parent_bus(dev, object_get_typename(OBJECT(dev)), @@ -123,54 +143,23 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus) object_unref(OBJECT(old_parent_bus)); object_unref(OBJECT(dev)); } + return true; } -/* Create a new device. This only initializes the device state - structure and allows properties to be set. The device still needs - to be realized. See qdev-core.h. */ -DeviceState *qdev_create(BusState *bus, const char *name) +DeviceState *qdev_new(const char *name) { - DeviceState *dev; - - dev = qdev_try_create(bus, name); - if (!dev) { - if (bus) { - error_report("Unknown device '%s' for bus '%s'", name, - object_get_typename(OBJECT(bus))); - } else { - error_report("Unknown device '%s' for default sysbus", name); - } - abort(); + if (!object_class_by_name(name)) { + module_load_qom_one(name); } - - return dev; + return DEVICE(object_new(name)); } -DeviceState *qdev_try_create(BusState *bus, const char *type) +DeviceState *qdev_try_new(const char *name) { - DeviceState *dev; - - if (object_class_by_name(type) == NULL) { - return NULL; - } - dev = DEVICE(object_new(type)); - if (!dev) { + if (!module_object_class_by_name(name)) { return NULL; } - - if (!bus) { - /* Assert that the device really is a SysBusDevice before - * we put it onto the sysbus. Non-sysbus devices which aren't - * being put onto a bus should be created with object_new(TYPE_FOO), - * not qdev_create(NULL, TYPE_FOO). - */ - g_assert(object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE)); - bus = sysbus_get_default(); - } - - qdev_set_parent_bus(dev, bus); - object_unref(OBJECT(dev)); - return dev; + return DEVICE(object_new(name)); } static QTAILQ_HEAD(, DeviceListener) device_listeners @@ -392,36 +381,49 @@ static void device_reset_child_foreach(Object *obj, ResettableChildCallback cb, void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + qdev_unrealize(dev); } -/* - * Realize @dev. - * Device properties should be set before calling this function. IRQs - * and MMIO regions should be connected/mapped after calling this - * function. - * On failure, report an error with error_report() and terminate the - * program. This is okay during machine creation. Don't use for - * hotplug, because there callers need to recover from failure. - * Exception: if you know the device's init() callback can't fail, - * then qdev_init_nofail() can't fail either, and is therefore usable - * even then. But relying on the device implementation that way is - * somewhat unclean, and best avoided. - */ -void qdev_init_nofail(DeviceState *dev) +bool qdev_realize(DeviceState *dev, BusState *bus, Error **errp) { - Error *err = NULL; - - assert(!dev->realized); + assert(!dev->realized && !dev->parent_bus); - object_ref(OBJECT(dev)); - object_property_set_bool(OBJECT(dev), true, "realized", &err); - if (err) { - error_reportf_err(err, "Initialization of device %s failed: ", - object_get_typename(OBJECT(dev))); - exit(1); + if (bus) { + if (!qdev_set_parent_bus(dev, bus, errp)) { + return false; + } + } else { + assert(!DEVICE_GET_CLASS(dev)->bus_type); } + + return object_property_set_bool(OBJECT(dev), "realized", true, errp); +} + +bool qdev_realize_and_unref(DeviceState *dev, BusState *bus, Error **errp) +{ + bool ret; + + ret = qdev_realize(dev, bus, errp); object_unref(OBJECT(dev)); + return ret; +} + +void qdev_unrealize(DeviceState *dev) +{ + object_property_set_bool(OBJECT(dev), "realized", false, &error_abort); +} + +static int qdev_assert_realized_properly(Object *obj, void *opaque) +{ + DeviceState *dev = DEVICE(object_dynamic_cast(obj, TYPE_DEVICE)); + DeviceClass *dc; + + if (dev) { + dc = DEVICE_GET_CLASS(dev); + assert(dev->realized); + assert(dev->parent_bus || !dc->bus_type); + } + return 0; } void qdev_machine_creation_done(void) @@ -431,6 +433,9 @@ void qdev_machine_creation_done(void) * only create hotpluggable devices */ qdev_hotplug = true; + + object_child_foreach_recursive(object_get_root(), + qdev_assert_realized_properly, NULL); } bool qdev_machine_modified(void) @@ -546,7 +551,7 @@ void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, "/unattached"), "non-qdev-gpio[*]", OBJECT(pin)); } - object_property_set_link(OBJECT(dev), OBJECT(pin), propname, &error_abort); + object_property_set_link(OBJECT(dev), propname, OBJECT(pin), &error_abort); g_free(propname); } @@ -572,7 +577,7 @@ static qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev, qemu_irq ret = (qemu_irq)object_property_get_link(OBJECT(dev), propname, NULL); if (ret) { - object_property_set_link(OBJECT(dev), NULL, propname, NULL); + object_property_set_link(OBJECT(dev), propname, NULL, NULL); } g_free(propname); return ret; @@ -674,17 +679,19 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id) DeviceState *ret; BusState *child; - QTAILQ_FOREACH(kid, &bus->children, sibling) { - DeviceState *dev = kid->child; + WITH_RCU_READ_LOCK_GUARD() { + QTAILQ_FOREACH_RCU(kid, &bus->children, sibling) { + DeviceState *dev = kid->child; - if (dev->id && strcmp(dev->id, id) == 0) { - return dev; - } + if (dev->id && strcmp(dev->id, id) == 0) { + return dev; + } - QLIST_FOREACH(child, &dev->child_bus, sibling) { - ret = qdev_find_recursive(child, id); - if (ret) { - return ret; + QLIST_FOREACH(child, &dev->child_bus, sibling) { + ret = qdev_find_recursive(child, id); + if (ret) { + return ret; + } } } } @@ -799,9 +806,6 @@ static void qdev_class_add_property(DeviceClass *klass, Property *prop) prop->info->description); } -/* @qdev_alias_all_properties - Add alias properties to the source object for - * all qdev properties on the target DeviceState. - */ void qdev_alias_all_properties(DeviceState *target, Object *source) { ObjectClass *class; @@ -856,7 +860,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp) } if (value && !dev->realized) { - if (!check_only_migratable(obj, &local_err)) { + if (!check_only_migratable(obj, errp)) { goto fail; } @@ -919,9 +923,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp) resettable_state_clear(&dev->reset); QLIST_FOREACH(bus, &dev->child_bus, sibling) { - object_property_set_bool(OBJECT(bus), true, "realized", - &local_err); - if (local_err != NULL) { + if (!qbus_realize(bus, errp)) { goto child_realize_fail; } } @@ -944,10 +946,27 @@ static void device_set_realized(Object *obj, bool value, Error **errp) } } + qatomic_store_release(&dev->realized, value); + } else if (!value && dev->realized) { + + /* + * Change the value so that any concurrent users are aware + * that the device is going to be unrealized + * + * TODO: change .realized property to enum that states + * each phase of the device realization/unrealization + */ + + qatomic_set(&dev->realized, value); + /* + * Ensure that concurrent users see this update prior to + * any other changes done by unrealize. + */ + smp_wmb(); + QLIST_FOREACH(bus, &dev->child_bus, sibling) { - object_property_set_bool(OBJECT(bus), false, "realized", - &error_abort); + qbus_unrealize(bus); } if (qdev_get_vmsd(dev)) { vmstate_unregister(VMSTATE_IF(dev), qdev_get_vmsd(dev), dev); @@ -960,13 +979,11 @@ static void device_set_realized(Object *obj, bool value, Error **errp) } assert(local_err == NULL); - dev->realized = value; return; child_realize_fail: QLIST_FOREACH(bus, &dev->child_bus, sibling) { - object_property_set_bool(OBJECT(bus), false, "realized", - &error_abort); + qbus_unrealize(bus); } if (qdev_get_vmsd(dev)) { @@ -983,6 +1000,10 @@ post_realize_fail: fail: error_propagate(errp, local_err); if (unattached_parent) { + /* + * Beware, this doesn't just revert + * object_property_add_child(), it also runs bus_remove()! + */ object_unparent(OBJECT(dev)); unattached_count--; } @@ -1078,7 +1099,7 @@ static void device_unparent(Object *obj) BusState *bus; if (dev->realized) { - object_property_set_bool(obj, false, "realized", &error_abort); + qdev_unrealize(dev); } while (dev->num_child_bus) { bus = QLIST_FIRST(&dev->child_bus); diff --git a/hw/core/register.c b/hw/core/register.c index ddf91eb445e169b9e7b91f4240e6a9b6ff30c7fc..3600ef5bde7d408b33a972c7b7ad38139cd84e64 100644 --- a/hw/core/register.c +++ b/hw/core/register.c @@ -176,17 +176,6 @@ void register_reset(RegisterInfo *reg) } } -void register_init(RegisterInfo *reg) -{ - assert(reg); - - if (!reg->data || !reg->access) { - return; - } - - object_initialize((void *)reg, sizeof(*reg), TYPE_REGISTER); -} - void register_write_memory(void *opaque, hwaddr addr, uint64_t value, unsigned size) { @@ -269,13 +258,14 @@ static RegisterInfoArray *register_init_block(DeviceState *owner, int index = rae[i].addr / data_size; RegisterInfo *r = &ri[index]; - *r = (RegisterInfo) { - .data = data + data_size * index, - .data_size = data_size, - .access = &rae[i], - .opaque = owner, - }; - register_init(r); + /* Init the register, this will zero it. */ + object_initialize((void *)r, sizeof(*r), TYPE_REGISTER); + + /* Set the properties of the register */ + r->data = data + data_size * index; + r->data_size = data_size; + r->access = &rae[i]; + r->opaque = owner; r_array->r[i] = r; } @@ -329,6 +319,7 @@ static const TypeInfo register_info = { .name = TYPE_REGISTER, .parent = TYPE_DEVICE, .class_init = register_class_init, + .instance_size = sizeof(RegisterInfo), }; static void register_register_types(void) diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c index 08b0311c5f0137ce69bd2049d6b929752960844b..aaae8e23cc4ad693bffd3614d56fa7dab76191d6 100644 --- a/hw/core/sysbus.c +++ b/hw/core/sysbus.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -64,7 +64,7 @@ void foreach_dynamic_sysbus_device(FindSysbusDeviceFunc *func, void *opaque) .opaque = opaque, }; - /* Loop through all sysbus devices that were spawened outside the machine */ + /* Loop through all sysbus devices that were spawned outside the machine */ container = container_get(qdev_get_machine(), "/peripheral"); find_sysbus_device(container, &find); container = container_get(qdev_get_machine(), "/peripheral-anon"); @@ -93,7 +93,7 @@ bool sysbus_has_irq(SysBusDevice *dev, int n) char *prop = g_strdup_printf("%s[%d]", SYSBUS_DEVICE_GPIO_IRQ, n); ObjectProperty *r; - r = object_property_find(OBJECT(dev), prop, NULL); + r = object_property_find(OBJECT(dev), prop); g_free(prop); return (r != NULL); @@ -199,6 +199,7 @@ void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory) MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n) { + assert(n >= 0 && n < QDEV_MAX_MMIO); return dev->mmio[n].memory; } @@ -217,7 +218,7 @@ void sysbus_init_ioports(SysBusDevice *dev, uint32_t ioport, uint32_t size) * from being set to NULL to break the normal init/realize * of some devices. */ -static void sysbus_realize(DeviceState *dev, Error **errp) +static void sysbus_device_realize(DeviceState *dev, Error **errp) { } @@ -230,9 +231,9 @@ DeviceState *sysbus_create_varargs(const char *name, qemu_irq irq; int n; - dev = qdev_create(NULL, name); + dev = qdev_new(name); s = SYS_BUS_DEVICE(dev); - qdev_init_nofail(dev); + sysbus_realize_and_unref(s, &error_fatal); if (addr != (hwaddr)-1) { sysbus_mmio_map(s, 0, addr); } @@ -250,6 +251,16 @@ DeviceState *sysbus_create_varargs(const char *name, return dev; } +bool sysbus_realize(SysBusDevice *dev, Error **errp) +{ + return qdev_realize(DEVICE(dev), sysbus_get_default(), errp); +} + +bool sysbus_realize_and_unref(SysBusDevice *dev, Error **errp) +{ + return qdev_realize_and_unref(DEVICE(dev), sysbus_get_default(), errp); +} + static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent) { SysBusDevice *s = SYS_BUS_DEVICE(dev); @@ -301,7 +312,7 @@ MemoryRegion *sysbus_address_space(SysBusDevice *dev) static void sysbus_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); - k->realize = sysbus_realize; + k->realize = sysbus_device_realize; k->bus_type = TYPE_SYSTEM_BUS; /* * device_add plugs devices into a suitable bus. For "real" buses, @@ -325,7 +336,6 @@ static const TypeInfo sysbus_device_type_info = { .class_init = sysbus_device_class_init, }; -/* This is a nasty hack to allow passing a NULL bus to qdev_create. */ static BusState *main_system_bus; static void main_system_bus_create(void) @@ -346,14 +356,6 @@ BusState *sysbus_get_default(void) return main_system_bus; } -void sysbus_init_child_obj(Object *parent, const char *childname, void *child, - size_t childsize, const char *childtype) -{ - object_initialize_child(parent, childname, child, childsize, childtype, - &error_abort, NULL); - qdev_set_parent_bus(DEVICE(child), sysbus_get_default()); -} - static void sysbus_register_types(void) { type_register_static(&system_bus_info); diff --git a/hw/core/trace-events b/hw/core/trace-events index 1ac60ede6b7e9873f029bcbb9f9216b23a0ec41b..360ddeb2c875e616e46b6fe05ab0ba5dd34cd9fe 100644 --- a/hw/core/trace-events +++ b/hw/core/trace-events @@ -31,6 +31,6 @@ resettable_transitional_function(void *obj, const char *objtype) "obj=%p(%s)" # clock.c clock_set_source(const char *clk, const char *src) "'%s', src='%s'" clock_disconnect(const char *clk) "'%s'" -clock_set(const char *clk, uint64_t old, uint64_t new) "'%s', ns=%"PRIu64"->%"PRIu64 +clock_set(const char *clk, uint64_t old, uint64_t new) "'%s', %"PRIu64"Hz->%"PRIu64"Hz" clock_propagate(const char *clk) "'%s'" -clock_update(const char *clk, const char *src, uint64_t val, int cb) "'%s', src='%s', ns=%"PRIu64", cb=%d" +clock_update(const char *clk, const char *src, uint64_t hz, int cb) "'%s', src='%s', val=%"PRIu64"Hz cb=%d" diff --git a/hw/core/trace.h b/hw/core/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..23dfd61c497fb12c83b3b9353f8a775a2d4cbcd8 --- /dev/null +++ b/hw/core/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_core.h" diff --git a/hw/cpu/Makefile.objs b/hw/cpu/Makefile.objs deleted file mode 100644 index 8db9e8a7b3c49db6b46710f331f408b260efb1a9..0000000000000000000000000000000000000000 --- a/hw/cpu/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o -obj-$(CONFIG_REALVIEW) += realview_mpcore.o -obj-$(CONFIG_A9MPCORE) += a9mpcore.o -obj-$(CONFIG_A15MPCORE) += a15mpcore.o -common-obj-y += core.o cluster.o diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c index 4f659115b68722ee750992f9f6f339b99c00b73a..774ca9987a18bd855852d13da9f7fcb94e17a8b1 100644 --- a/hw/cpu/a15mpcore.c +++ b/hw/cpu/a15mpcore.c @@ -42,8 +42,7 @@ static void a15mp_priv_initfn(Object *obj) memory_region_init(&s->container, obj, "a15mp-priv-container", 0x8000); sysbus_init_mmio(sbd, &s->container); - sysbus_init_child_obj(obj, "gic", &s->gic, sizeof(s->gic), - gic_class_name()); + object_initialize_child(obj, "gic", &s->gic, gic_class_name()); qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2); } @@ -54,7 +53,6 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp) DeviceState *gicdev; SysBusDevice *busdev; int i; - Error *err = NULL; bool has_el3; bool has_el2 = false; Object *cpuobj; @@ -68,18 +66,16 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp) * either all the CPUs have TZ, or none do. */ cpuobj = OBJECT(qemu_get_cpu(0)); - has_el3 = object_property_find(cpuobj, "has_el3", NULL) && + has_el3 = object_property_find(cpuobj, "has_el3") && object_property_get_bool(cpuobj, "has_el3", &error_abort); qdev_prop_set_bit(gicdev, "has-security-extensions", has_el3); /* Similarly for virtualization support */ - has_el2 = object_property_find(cpuobj, "has_el2", NULL) && + has_el2 = object_property_find(cpuobj, "has_el2") && object_property_get_bool(cpuobj, "has_el2", &error_abort); qdev_prop_set_bit(gicdev, "has-virtualization-extensions", has_el2); } - object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gic), errp)) { return; } busdev = SYS_BUS_DEVICE(&s->gic); diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c index b4f6a7e8a5493a1cd73807682d29c85d8c938a9c..d03f57e579b35ae80da011c49b428759de4268ef 100644 --- a/hw/cpu/a9mpcore.c +++ b/hw/cpu/a9mpcore.c @@ -15,6 +15,7 @@ #include "hw/irq.h" #include "hw/qdev-properties.h" #include "hw/core/cpu.h" +#include "cpu.h" #define A9_GIC_NUM_PRIORITY_BITS 5 @@ -32,18 +33,15 @@ static void a9mp_priv_initfn(Object *obj) memory_region_init(&s->container, obj, "a9mp-priv-container", 0x2000); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->container); - sysbus_init_child_obj(obj, "scu", &s->scu, sizeof(s->scu), TYPE_A9_SCU); + object_initialize_child(obj, "scu", &s->scu, TYPE_A9_SCU); - sysbus_init_child_obj(obj, "gic", &s->gic, sizeof(s->gic), TYPE_ARM_GIC); + object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GIC); - sysbus_init_child_obj(obj, "gtimer", &s->gtimer, sizeof(s->gtimer), - TYPE_A9_GTIMER); + object_initialize_child(obj, "gtimer", &s->gtimer, TYPE_A9_GTIMER); - sysbus_init_child_obj(obj, "mptimer", &s->mptimer, sizeof(s->mptimer), - TYPE_ARM_MPTIMER); + object_initialize_child(obj, "mptimer", &s->mptimer, TYPE_ARM_MPTIMER); - sysbus_init_child_obj(obj, "wdt", &s->wdt, sizeof(s->wdt), - TYPE_ARM_MPTIMER); + object_initialize_child(obj, "wdt", &s->wdt, TYPE_ARM_MPTIMER); } static void a9mp_priv_realize(DeviceState *dev, Error **errp) @@ -53,16 +51,23 @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp) DeviceState *scudev, *gicdev, *gtimerdev, *mptimerdev, *wdtdev; SysBusDevice *scubusdev, *gicbusdev, *gtimerbusdev, *mptimerbusdev, *wdtbusdev; - Error *err = NULL; int i; bool has_el3; + CPUState *cpu0; Object *cpuobj; + cpu0 = qemu_get_cpu(0); + cpuobj = OBJECT(cpu0); + if (strcmp(object_get_typename(cpuobj), ARM_CPU_TYPE_NAME("cortex-a9"))) { + /* We might allow Cortex-A5 once we model it */ + error_setg(errp, + "Cortex-A9MPCore peripheral can only use Cortex-A9 CPU"); + return; + } + scudev = DEVICE(&s->scu); qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu); - object_property_set_bool(OBJECT(&s->scu), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) { return; } scubusdev = SYS_BUS_DEVICE(&s->scu); @@ -76,14 +81,11 @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp) /* Make the GIC's TZ support match the CPUs. We assume that * either all the CPUs have TZ, or none do. */ - cpuobj = OBJECT(qemu_get_cpu(0)); - has_el3 = object_property_find(cpuobj, "has_el3", NULL) && + has_el3 = object_property_find(cpuobj, "has_el3") && object_property_get_bool(cpuobj, "has_el3", &error_abort); qdev_prop_set_bit(gicdev, "has-security-extensions", has_el3); - object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gic), errp)) { return; } gicbusdev = SYS_BUS_DEVICE(&s->gic); @@ -96,27 +98,21 @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp) gtimerdev = DEVICE(&s->gtimer); qdev_prop_set_uint32(gtimerdev, "num-cpu", s->num_cpu); - object_property_set_bool(OBJECT(&s->gtimer), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gtimer), errp)) { return; } gtimerbusdev = SYS_BUS_DEVICE(&s->gtimer); mptimerdev = DEVICE(&s->mptimer); qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu); - object_property_set_bool(OBJECT(&s->mptimer), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->mptimer), errp)) { return; } mptimerbusdev = SYS_BUS_DEVICE(&s->mptimer); wdtdev = DEVICE(&s->wdt); qdev_prop_set_uint32(wdtdev, "num-cpu", s->num_cpu); - object_property_set_bool(OBJECT(&s->wdt), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt), errp)) { return; } wdtbusdev = SYS_BUS_DEVICE(&s->wdt); diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c index ab9fadb67cbc57d67e70dc0c8e673d199043bc56..89c4e35143a57f9adc4f470ca105d72e6177a8b1 100644 --- a/hw/cpu/arm11mpcore.c +++ b/hw/cpu/arm11mpcore.c @@ -76,12 +76,9 @@ static void mpcore_priv_realize(DeviceState *dev, Error **errp) DeviceState *gicdev = DEVICE(&s->gic); DeviceState *mptimerdev = DEVICE(&s->mptimer); DeviceState *wdtimerdev = DEVICE(&s->wdtimer); - Error *err = NULL; qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu); - object_property_set_bool(OBJECT(&s->scu), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) { return; } @@ -91,9 +88,7 @@ static void mpcore_priv_realize(DeviceState *dev, Error **errp) ARM11MPCORE_NUM_GIC_PRIORITY_BITS); - object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gic), errp)) { return; } @@ -104,16 +99,12 @@ static void mpcore_priv_realize(DeviceState *dev, Error **errp) qdev_init_gpio_in(dev, mpcore_priv_set_irq, s->num_irq - 32); qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu); - object_property_set_bool(OBJECT(&s->mptimer), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->mptimer), errp)) { return; } qdev_prop_set_uint32(wdtimerdev, "num-cpu", s->num_cpu); - object_property_set_bool(OBJECT(&s->wdtimer), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdtimer), errp)) { return; } @@ -129,17 +120,15 @@ static void mpcore_priv_initfn(Object *obj) "mpcore-priv-container", 0x2000); sysbus_init_mmio(sbd, &s->container); - sysbus_init_child_obj(obj, "scu", &s->scu, sizeof(s->scu), TYPE_ARM11_SCU); + object_initialize_child(obj, "scu", &s->scu, TYPE_ARM11_SCU); - sysbus_init_child_obj(obj, "gic", &s->gic, sizeof(s->gic), TYPE_ARM_GIC); + object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GIC); /* Request the legacy 11MPCore GIC behaviour: */ qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 0); - sysbus_init_child_obj(obj, "mptimer", &s->mptimer, sizeof(s->mptimer), - TYPE_ARM_MPTIMER); + object_initialize_child(obj, "mptimer", &s->mptimer, TYPE_ARM_MPTIMER); - sysbus_init_child_obj(obj, "wdtimer", &s->wdtimer, sizeof(s->wdtimer), - TYPE_ARM_MPTIMER); + object_initialize_child(obj, "wdtimer", &s->wdtimer, TYPE_ARM_MPTIMER); } static Property mpcore_priv_properties[] = { diff --git a/hw/cpu/core.c b/hw/cpu/core.c index a92ac597ca3585225a724b7b1b0aecb14a291747..92d3b2fbad62cc3dd7656f148bfdbbc685275275 100644 --- a/hw/cpu/core.c +++ b/hw/cpu/core.c @@ -28,12 +28,9 @@ static void core_prop_set_core_id(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { CPUCore *core = CPU_CORE(obj); - Error *local_err = NULL; int64_t value; - visit_type_int(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_int(v, name, &value, errp)) { return; } @@ -58,12 +55,9 @@ static void core_prop_set_nr_threads(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { CPUCore *core = CPU_CORE(obj); - Error *local_err = NULL; int64_t value; - visit_type_int(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_int(v, name, &value, errp)) { return; } @@ -75,10 +69,6 @@ static void cpu_core_instance_init(Object *obj) MachineState *ms = MACHINE(qdev_get_machine()); CPUCore *core = CPU_CORE(obj); - object_property_add(obj, "core-id", "int", core_prop_get_core_id, - core_prop_set_core_id, NULL, NULL); - object_property_add(obj, "nr-threads", "int", core_prop_get_nr_threads, - core_prop_set_nr_threads, NULL, NULL); core->nr_threads = ms->smp.threads; } @@ -87,6 +77,10 @@ static void cpu_core_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); set_bit(DEVICE_CATEGORY_CPU, dc->categories); + object_class_property_add(oc, "core-id", "int", core_prop_get_core_id, + core_prop_set_core_id, NULL, NULL); + object_class_property_add(oc, "nr-threads", "int", core_prop_get_nr_threads, + core_prop_set_nr_threads, NULL, NULL); } static const TypeInfo cpu_core_type_info = { diff --git a/hw/cpu/meson.build b/hw/cpu/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..9e52fee9e778c0d92586cd83ecba8bbc54f4bc45 --- /dev/null +++ b/hw/cpu/meson.build @@ -0,0 +1,6 @@ +softmmu_ss.add(files('core.c', 'cluster.c')) + +specific_ss.add(when: 'CONFIG_ARM11MPCORE', if_true: files('arm11mpcore.c')) +specific_ss.add(when: 'CONFIG_REALVIEW', if_true: files('realview_mpcore.c')) +specific_ss.add(when: 'CONFIG_A9MPCORE', if_true: files('a9mpcore.c')) +specific_ss.add(when: 'CONFIG_A15MPCORE', if_true: files('a15mpcore.c')) diff --git a/hw/cpu/realview_mpcore.c b/hw/cpu/realview_mpcore.c index cc2767c71657cab28a4d7ae9c496ba6b6e66ad3b..72c792eef1a5e88ef4644a3f159040ce5daa698f 100644 --- a/hw/cpu/realview_mpcore.c +++ b/hw/cpu/realview_mpcore.c @@ -15,15 +15,15 @@ #include "hw/intc/realview_gic.h" #include "hw/irq.h" #include "hw/qdev-properties.h" +#include "qom/object.h" #define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore" -#define REALVIEW_MPCORE_RIRQ(obj) \ - OBJECT_CHECK(mpcore_rirq_state, (obj), TYPE_REALVIEW_MPCORE_RIRQ) +OBJECT_DECLARE_SIMPLE_TYPE(mpcore_rirq_state, REALVIEW_MPCORE_RIRQ) /* Dummy PIC to route IRQ lines. The baseboard has 4 independent IRQ controllers. The output of these, plus some of the raw input lines are fed into a single SMP-aware interrupt controller on the CPU. */ -typedef struct { +struct mpcore_rirq_state { SysBusDevice parent_obj; qemu_irq cpuic[32]; @@ -32,7 +32,7 @@ typedef struct { ARM11MPCorePriveState priv; RealViewGICState gic[4]; -} mpcore_rirq_state; +}; /* Map baseboard IRQs onto CPU IRQ lines. */ static const int mpcore_irq_map[32] = { @@ -65,14 +65,11 @@ static void realview_mpcore_realize(DeviceState *dev, Error **errp) DeviceState *priv = DEVICE(&s->priv); DeviceState *gic; SysBusDevice *gicbusdev; - Error *err = NULL; int n; int i; qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu); - object_property_set_bool(OBJECT(&s->priv), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->priv), errp)) { return; } sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->priv)); @@ -81,9 +78,7 @@ static void realview_mpcore_realize(DeviceState *dev, Error **errp) } /* ??? IRQ routing is hardcoded to "normal" mode. */ for (n = 0; n < 4; n++) { - object_property_set_bool(OBJECT(&s->gic[n]), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gic[n]), errp)) { return; } gic = DEVICE(&s->gic[n]); @@ -104,14 +99,12 @@ static void mpcore_rirq_init(Object *obj) SysBusDevice *privbusdev; int i; - sysbus_init_child_obj(obj, "a11priv", &s->priv, sizeof(s->priv), - TYPE_ARM11MPCORE_PRIV); + object_initialize_child(obj, "a11priv", &s->priv, TYPE_ARM11MPCORE_PRIV); privbusdev = SYS_BUS_DEVICE(&s->priv); sysbus_init_mmio(sbd, sysbus_mmio_get_region(privbusdev, 0)); for (i = 0; i < 4; i++) { - sysbus_init_child_obj(obj, "gic[*]", &s->gic[i], sizeof(s->gic[i]), - TYPE_REALVIEW_GIC); + object_initialize_child(obj, "gic[*]", &s->gic[i], TYPE_REALVIEW_GIC); } } diff --git a/hw/cris/Makefile.objs b/hw/cris/Makefile.objs deleted file mode 100644 index a4a27b3a138d1ccbaa7374b159c604920ce98e78..0000000000000000000000000000000000000000 --- a/hw/cris/Makefile.objs +++ /dev/null @@ -1,2 +0,0 @@ -obj-y += boot.o -obj-$(CONFIG_AXIS) += axis_dev88.o diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c index 75e5c993b5d4a7927c09e0ea4de00cc7d4483bb1..dab7423c7378525c3fcf3977e12c84425f795a3f 100644 --- a/hw/cris/axis_dev88.c +++ b/hw/cris/axis_dev88.c @@ -289,9 +289,9 @@ void axisdev88_init(MachineState *machine) &gpio_state.iomem); - dev = qdev_create(NULL, "etraxfs,pic"); - qdev_init_nofail(dev); + dev = qdev_new("etraxfs,pic"); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, 0x3001c000); sysbus_connect_irq(s, 0, qdev_get_gpio_in(DEVICE(cpu), CRIS_CPU_IRQ)); sysbus_connect_irq(s, 1, qdev_get_gpio_in(DEVICE(cpu), CRIS_CPU_NMI)); diff --git a/hw/cris/boot.c b/hw/cris/boot.c index b8947bc6607870a8993c62679e9b1d6300e31c4a..aa8d2756d6cebad30d3d1865579916e33526a115 100644 --- a/hw/cris/boot.c +++ b/hw/cris/boot.c @@ -67,7 +67,7 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr) void cris_load_image(CRISCPU *cpu, struct cris_load_info *li) { CPUCRISState *env = &cpu->env; - uint64_t entry, high; + uint64_t entry; int kcmdline_len; int image_size; @@ -76,7 +76,7 @@ void cris_load_image(CRISCPU *cpu, struct cris_load_info *li) devboard SDK. */ image_size = load_elf(li->image_filename, NULL, translate_kernel_address, NULL, - &entry, NULL, &high, NULL, 0, EM_CRIS, 0, 0); + &entry, NULL, NULL, NULL, 0, EM_CRIS, 0, 0); li->entry = entry; if (image_size < 0) { /* Takes a kimage from the axis devboard SDK. */ diff --git a/hw/cris/meson.build b/hw/cris/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..dc808a4e0f1cfc916517ae16fe88f07b15493bbe --- /dev/null +++ b/hw/cris/meson.build @@ -0,0 +1,5 @@ +cris_ss = ss.source_set() +cris_ss.add(files('boot.c')) +cris_ss.add(when: 'CONFIG_AXIS', if_true: files('axis_dev88.c')) + +hw_arch += {'cris': cris_ss} diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs deleted file mode 100644 index 77a7d622bd2da8e911213e487bf9f155c9b955f3..0000000000000000000000000000000000000000 --- a/hw/display/Makefile.objs +++ /dev/null @@ -1,62 +0,0 @@ -common-obj-$(CONFIG_DDC) += i2c-ddc.o -common-obj-$(CONFIG_EDID) += edid-generate.o edid-region.o - -common-obj-$(CONFIG_FW_CFG_DMA) += ramfb.o -common-obj-$(CONFIG_FW_CFG_DMA) += ramfb-standalone.o - -common-obj-$(CONFIG_ADS7846) += ads7846.o -common-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o -common-obj-$(call land,$(CONFIG_VGA_CIRRUS),$(CONFIG_VGA_ISA))+=cirrus_vga_isa.o -common-obj-$(CONFIG_G364FB) += g364fb.o -common-obj-$(CONFIG_JAZZ_LED) += jazz_led.o -common-obj-$(CONFIG_PL110) += pl110.o -common-obj-$(CONFIG_SII9022) += sii9022.o -common-obj-$(CONFIG_SSD0303) += ssd0303.o -common-obj-$(CONFIG_SSD0323) += ssd0323.o -common-obj-$(CONFIG_XEN) += xenfb.o - -common-obj-$(CONFIG_VGA_PCI) += vga-pci.o -common-obj-$(CONFIG_VGA_ISA) += vga-isa.o -common-obj-$(CONFIG_VGA_ISA_MM) += vga-isa-mm.o -common-obj-$(CONFIG_VMWARE_VGA) += vmware_vga.o -common-obj-$(CONFIG_BOCHS_DISPLAY) += bochs-display.o - -common-obj-$(CONFIG_BLIZZARD) += blizzard.o -common-obj-$(CONFIG_EXYNOS4) += exynos4210_fimd.o -common-obj-$(CONFIG_FRAMEBUFFER) += framebuffer.o -common-obj-$(CONFIG_MILKYMIST) += milkymist-vgafb.o -common-obj-$(CONFIG_ZAURUS) += tc6393xb.o -common-obj-$(CONFIG_MACFB) += macfb.o - -obj-$(CONFIG_MILKYMIST_TMU2) += milkymist-tmu2.o -milkymist-tmu2.o-cflags := $(X11_CFLAGS) $(OPENGL_CFLAGS) -milkymist-tmu2.o-libs := $(X11_LIBS) $(OPENGL_LIBS) - -common-obj-$(CONFIG_OMAP) += omap_dss.o -obj-$(CONFIG_OMAP) += omap_lcdc.o -common-obj-$(CONFIG_PXA2XX) += pxa2xx_lcd.o -common-obj-$(CONFIG_RASPI) += bcm2835_fb.o -common-obj-$(CONFIG_SM501) += sm501.o -common-obj-$(CONFIG_TCX) += tcx.o -common-obj-$(CONFIG_CG3) += cg3.o -common-obj-$(CONFIG_NEXTCUBE) += next-fb.o -common-obj-$(CONFIG_ARTIST) += artist.o - -obj-$(CONFIG_VGA) += vga.o - -common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o - -obj-$(CONFIG_VIRTIO_GPU) += virtio-gpu-base.o virtio-gpu.o virtio-gpu-3d.o -obj-$(CONFIG_VHOST_USER_GPU) += vhost-user-gpu.o -obj-$(call land,$(CONFIG_VIRTIO_GPU),$(CONFIG_VIRTIO_PCI)) += virtio-gpu-pci.o -obj-$(call land,$(CONFIG_VHOST_USER_GPU),$(CONFIG_VIRTIO_PCI)) += vhost-user-gpu-pci.o -obj-$(CONFIG_VIRTIO_VGA) += virtio-vga.o -obj-$(CONFIG_VHOST_USER_VGA) += vhost-user-vga.o -virtio-gpu.o-cflags := $(VIRGL_CFLAGS) -virtio-gpu.o-libs += $(VIRGL_LIBS) -virtio-gpu-3d.o-cflags := $(VIRGL_CFLAGS) -virtio-gpu-3d.o-libs += $(VIRGL_LIBS) -common-obj-$(CONFIG_DPCD) += dpcd.o -common-obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx_dp.o - -common-obj-$(CONFIG_ATI_VGA) += ati.o ati_2d.o ati_dbg.o diff --git a/hw/display/ads7846.c b/hw/display/ads7846.c index 9228b40b1af2419c91eb7c2465a984dff14675c2..cb3a431cfd006475f83a8df2a769258e2f0b0966 100644 --- a/hw/display/ads7846.c +++ b/hw/display/ads7846.c @@ -16,8 +16,9 @@ #include "migration/vmstate.h" #include "qemu/module.h" #include "ui/console.h" +#include "qom/object.h" -typedef struct { +struct ADS7846State { SSISlave ssidev; qemu_irq interrupt; @@ -27,7 +28,10 @@ typedef struct { int cycle; int output; -} ADS7846State; +}; + +#define TYPE_ADS7846 "ads7846" +OBJECT_DECLARE_SIMPLE_TYPE(ADS7846State, ADS7846) /* Control-byte bitfields */ #define CB_PD0 (1 << 0) @@ -61,7 +65,7 @@ static void ads7846_int_update(ADS7846State *s) static uint32_t ads7846_transfer(SSISlave *dev, uint32_t value) { - ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, dev); + ADS7846State *s = ADS7846(dev); switch (s->cycle ++) { case 0: @@ -139,7 +143,7 @@ static const VMStateDescription vmstate_ads7846 = { static void ads7846_realize(SSISlave *d, Error **errp) { DeviceState *dev = DEVICE(d); - ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, d); + ADS7846State *s = ADS7846(d); qdev_init_gpio_out(dev, &s->interrupt, 1); @@ -159,14 +163,16 @@ static void ads7846_realize(SSISlave *d, Error **errp) static void ads7846_class_init(ObjectClass *klass, void *data) { + DeviceClass *dc = DEVICE_CLASS(klass); SSISlaveClass *k = SSI_SLAVE_CLASS(klass); k->realize = ads7846_realize; k->transfer = ads7846_transfer; + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } static const TypeInfo ads7846_info = { - .name = "ads7846", + .name = TYPE_ADS7846, .parent = TYPE_SSI_SLAVE, .instance_size = sizeof(ADS7846State), .class_init = ads7846_class_init, diff --git a/hw/display/artist.c b/hw/display/artist.c index 6261bfe65b725139d48ba4ee8ca896880be0962f..ed0e637f250c972c920956bafeb7603324e1830a 100644 --- a/hw/display/artist.c +++ b/hw/display/artist.c @@ -22,9 +22,10 @@ #include "ui/console.h" #include "trace.h" #include "framebuffer.h" +#include "qom/object.h" #define TYPE_ARTIST "artist" -#define ARTIST(obj) OBJECT_CHECK(ARTISTState, (obj), TYPE_ARTIST) +OBJECT_DECLARE_SIMPLE_TYPE(ARTISTState, ARTIST) #ifdef HOST_WORDS_BIGENDIAN #define ROP8OFF(_i) (3 - (_i)) @@ -35,12 +36,12 @@ struct vram_buffer { MemoryRegion mr; uint8_t *data; - int size; - int width; - int height; + unsigned int size; + unsigned int width; + unsigned int height; }; -typedef struct ARTISTState { +struct ARTISTState { SysBusDevice parent_obj; QemuConsole *con; @@ -103,7 +104,7 @@ typedef struct ARTISTState { uint32_t font_write_pos_y; int draw_line_pattern; -} ARTISTState; +}; typedef enum { ARTIST_BUFFER_AP = 1, @@ -192,6 +193,10 @@ static const char *artist_reg_name(uint64_t addr) } #undef REG_NAME +/* artist has a fixed line length of 2048 bytes. */ +#define ADDR_TO_Y(addr) extract32(addr, 11, 11) +#define ADDR_TO_X(addr) extract32(addr, 0, 11) + static int16_t artist_get_x(uint32_t reg) { return reg >> 16; @@ -206,7 +211,12 @@ static void artist_invalidate_lines(struct vram_buffer *buf, int starty, int height) { int start = starty * buf->width; - int size = height * buf->width; + int size; + + if (starty + height > buf->height) + height = buf->height - starty; + + size = height * buf->width; if (start + size <= buf->size) { memory_region_set_dirty(&buf->mr, start, size); @@ -273,11 +283,20 @@ static artist_rop_t artist_get_op(ARTISTState *s) return (s->image_bitmap_op >> 8) & 0xf; } -static void artist_rop8(ARTISTState *s, uint8_t *dst, uint8_t val) +static void artist_rop8(ARTISTState *s, struct vram_buffer *buf, + unsigned int offset, uint8_t val) { - const artist_rop_t op = artist_get_op(s); - uint8_t plane_mask = s->plane_mask & 0xff; + uint8_t plane_mask; + uint8_t *dst; + + if (offset >= buf->size) { + qemu_log_mask(LOG_GUEST_ERROR, + "rop8 offset:%u bufsize:%u\n", offset, buf->size); + return; + } + dst = buf->data + offset; + plane_mask = s->plane_mask & 0xff; switch (op) { case ARTIST_ROP_CLEAR: @@ -285,8 +304,7 @@ static void artist_rop8(ARTISTState *s, uint8_t *dst, uint8_t val) break; case ARTIST_ROP_COPY: - *dst &= ~plane_mask; - *dst |= val & plane_mask; + *dst = (*dst & ~plane_mask) | (val & plane_mask); break; case ARTIST_ROP_XOR: @@ -335,29 +353,30 @@ static void artist_invalidate_cursor(ARTISTState *s) y, s->cursor_height); } -static void vram_bit_write(ARTISTState *s, int posx, int posy, bool incr_x, +static void vram_bit_write(ARTISTState *s, int posy, bool incr_x, int size, uint32_t data) { struct vram_buffer *buf; uint32_t vram_bitmask = s->vram_bitmask; - int mask, i, pix_count, pix_length, offset, height, width; + int mask, i, pix_count, pix_length; + unsigned int posx, offset, width; uint8_t *data8, *p; pix_count = vram_write_pix_per_transfer(s); pix_length = vram_pixel_length(s); buf = vram_write_buffer(s); - height = buf->height; width = buf->width; if (s->cmap_bm_access) { offset = s->vram_pos; } else { + posx = ADDR_TO_X(s->vram_pos >> 2); + posy += ADDR_TO_Y(s->vram_pos >> 2); offset = posy * width + posx; } - if (!buf->size) { - qemu_log("write to non-existent buffer\n"); + if (!buf->size || offset >= buf->size) { return; } @@ -367,13 +386,6 @@ static void vram_bit_write(ARTISTState *s, int posx, int posy, bool incr_x, pix_count = size * 8; } - if (posy * width + posx + pix_count > buf->size) { - qemu_log("write outside bounds: wants %dx%d, max size %dx%d\n", - posx, posy, width, height); - return; - } - - switch (pix_length) { case 0: if (s->image_bitmap_op & 0x20000000) { @@ -381,8 +393,11 @@ static void vram_bit_write(ARTISTState *s, int posx, int posy, bool incr_x, } for (i = 0; i < pix_count; i++) { - artist_rop8(s, p + offset + pix_count - 1 - i, - (data & 1) ? (s->plane_mask >> 24) : 0); + uint32_t off = offset + pix_count - 1 - i; + if (off < buf->size) { + artist_rop8(s, buf, off, + (data & 1) ? (s->plane_mask >> 24) : 0); + } data >>= 1; } memory_region_set_dirty(&buf->mr, offset, pix_count); @@ -390,7 +405,9 @@ static void vram_bit_write(ARTISTState *s, int posx, int posy, bool incr_x, case 3: if (s->cmap_bm_access) { - *(uint32_t *)(p + offset) = data; + if (offset + 3 < buf->size) { + *(uint32_t *)(p + offset) = data; + } break; } data8 = (uint8_t *)&data; @@ -398,7 +415,10 @@ static void vram_bit_write(ARTISTState *s, int posx, int posy, bool incr_x, for (i = 3; i >= 0; i--) { if (!(s->image_bitmap_op & 0x20000000) || s->vram_bitmask & (1 << (28 + i))) { - artist_rop8(s, p + offset + 3 - i, data8[ROP8OFF(i)]); + uint32_t off = offset + 3 - i; + if (off < buf->size) { + artist_rop8(s, buf, off, data8[ROP8OFF(i)]); + } } } memory_region_set_dirty(&buf->mr, offset, 3); @@ -420,16 +440,16 @@ static void vram_bit_write(ARTISTState *s, int posx, int posy, bool incr_x, break; } - for (i = 0; i < pix_count; i++) { + for (i = 0; i < pix_count && offset + i < buf->size; i++) { mask = 1 << (pix_count - 1 - i); if (!(s->image_bitmap_op & 0x20000000) || (vram_bitmask & mask)) { if (data & mask) { - artist_rop8(s, p + offset + i, s->fg_color); + artist_rop8(s, buf, offset + i, s->fg_color); } else { if (!(s->image_bitmap_op & 0x10000002)) { - artist_rop8(s, p + offset + i, s->bg_color); + artist_rop8(s, buf, offset + i, s->bg_color); } } } @@ -457,12 +477,14 @@ static void vram_bit_write(ARTISTState *s, int posx, int posy, bool incr_x, } } -static void block_move(ARTISTState *s, int source_x, int source_y, int dest_x, - int dest_y, int width, int height) +static void block_move(ARTISTState *s, + unsigned int source_x, unsigned int source_y, + unsigned int dest_x, unsigned int dest_y, + unsigned int width, unsigned int height) { struct vram_buffer *buf; int line, endline, lineincr, startcolumn, endcolumn, columnincr, column; - uint32_t dst, src; + unsigned int dst, src; trace_artist_block_move(source_x, source_y, dest_x, dest_y, width, height); @@ -474,6 +496,12 @@ static void block_move(ARTISTState *s, int source_x, int source_y, int dest_x, } buf = &s->vram_buffer[ARTIST_BUFFER_AP]; + if (height > buf->height) { + height = buf->height; + } + if (width > buf->width) { + width = buf->width; + } if (dest_y > source_y) { /* move down */ @@ -500,24 +528,27 @@ static void block_move(ARTISTState *s, int source_x, int source_y, int dest_x, } for ( ; line != endline; line += lineincr) { - src = source_x + ((line + source_y) * buf->width); - dst = dest_x + ((line + dest_y) * buf->width); + src = source_x + ((line + source_y) * buf->width) + startcolumn; + dst = dest_x + ((line + dest_y) * buf->width) + startcolumn; for (column = startcolumn; column != endcolumn; column += columnincr) { - if (dst + column > buf->size || src + column > buf->size) { + if (dst >= buf->size || src >= buf->size) { continue; } - artist_rop8(s, buf->data + dst + column, buf->data[src + column]); + artist_rop8(s, buf, dst, buf->data[src]); + src += columnincr; + dst += columnincr; } } artist_invalidate_lines(buf, dest_y, height); } -static void fill_window(ARTISTState *s, int startx, int starty, - int width, int height) +static void fill_window(ARTISTState *s, + unsigned int startx, unsigned int starty, + unsigned int width, unsigned int height) { - uint32_t offset; + unsigned int offset; uint8_t color = artist_get_color(s); struct vram_buffer *buf; int x, y; @@ -548,23 +579,30 @@ static void fill_window(ARTISTState *s, int startx, int starty, offset = y * s->width; for (x = startx; x < startx + width; x++) { - artist_rop8(s, buf->data + offset + x, color); + artist_rop8(s, buf, offset + x, color); } } artist_invalidate_lines(buf, starty, height); } -static void draw_line(ARTISTState *s, int x1, int y1, int x2, int y2, +static void draw_line(ARTISTState *s, + unsigned int x1, unsigned int y1, + unsigned int x2, unsigned int y2, bool update_start, int skip_pix, int max_pix) { - struct vram_buffer *buf; + struct vram_buffer *buf = &s->vram_buffer[ARTIST_BUFFER_AP]; uint8_t color; int dx, dy, t, e, x, y, incy, diago, horiz; bool c1; - uint8_t *p; trace_artist_draw_line(x1, y1, x2, y2); + if ((x1 >= buf->width && x2 >= buf->width) || + (y1 >= buf->height && y2 >= buf->height)) { + return; + } + + if (update_start) { s->vram_start = (x2 << 16) | y2; } @@ -579,9 +617,6 @@ static void draw_line(ARTISTState *s, int x1, int y1, int x2, int y2, } else { dy = y1 - y2; } - if (!dx || !dy) { - return; - } c1 = false; if (dy > dx) { @@ -622,23 +657,23 @@ static void draw_line(ARTISTState *s, int x1, int y1, int x2, int y2, x = x1; y = y1; color = artist_get_color(s); - buf = &s->vram_buffer[ARTIST_BUFFER_AP]; do { + unsigned int ofs; + if (c1) { - p = buf->data + x * s->width + y; + ofs = x * s->width + y; } else { - p = buf->data + y * s->width + x; + ofs = y * s->width + x; } if (skip_pix > 0) { skip_pix--; } else { - artist_rop8(s, p, color); + artist_rop8(s, buf, ofs, color); } if (e > 0) { - artist_invalidate_lines(buf, y, 1); y += incy; e += diago; } else { @@ -646,6 +681,10 @@ static void draw_line(ARTISTState *s, int x1, int y1, int x2, int y2, } x++; } while (x <= x2 && (max_pix == -1 || --max_pix > 0)); + if (c1) + artist_invalidate_lines(buf, x, dy+1); + else + artist_invalidate_lines(buf, y, dx+1); } static void draw_line_pattern_start(ARTISTState *s) @@ -755,23 +794,24 @@ static void font_write16(ARTISTState *s, uint16_t val) uint16_t mask; int i; - int startx = artist_get_x(s->vram_start); - int starty = artist_get_y(s->vram_start) + s->font_write_pos_y; - int offset = starty * s->width + startx; + unsigned int startx = artist_get_x(s->vram_start); + unsigned int starty = artist_get_y(s->vram_start) + s->font_write_pos_y; + unsigned int offset = starty * s->width + startx; buf = &s->vram_buffer[ARTIST_BUFFER_AP]; - if (offset + 16 > buf->size) { + if (startx >= buf->width || starty >= buf->height || + offset + 16 >= buf->size) { return; } for (i = 0; i < 16; i++) { mask = 1 << (15 - i); if (val & mask) { - artist_rop8(s, buf->data + offset + i, color); + artist_rop8(s, buf, offset + i, color); } else { if (!(s->image_bitmap_op & 0x20000000)) { - artist_rop8(s, buf->data + offset + i, s->bg_color); + artist_rop8(s, buf, offset + i, s->bg_color); } } } @@ -825,7 +865,6 @@ static void artist_reg_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { ARTISTState *s = opaque; - int posx, posy; int width, height; trace_artist_reg_write(size, addr, artist_reg_name(addr & ~3ULL), val); @@ -848,16 +887,12 @@ static void artist_reg_write(void *opaque, hwaddr addr, uint64_t val, break; case VRAM_WRITE_INCR_Y: - posx = (s->vram_pos >> 2) & 0x7ff; - posy = (s->vram_pos >> 13) & 0x3ff; - vram_bit_write(s, posx, posy + s->vram_char_y++, false, size, val); + vram_bit_write(s, s->vram_char_y++, false, size, val); break; case VRAM_WRITE_INCR_X: case VRAM_WRITE_INCR_X2: - posx = (s->vram_pos >> 2) & 0x7ff; - posy = (s->vram_pos >> 13) & 0x3ff; - vram_bit_write(s, posx, posy + s->vram_char_y, true, size, val); + vram_bit_write(s, s->vram_char_y, true, size, val); break; case VRAM_IDX: @@ -1123,9 +1158,8 @@ static void artist_vram_write(void *opaque, hwaddr addr, uint64_t val, { ARTISTState *s = opaque; struct vram_buffer *buf; - int posy = (addr >> 11) & 0x3ff; - int posx = addr & 0x7ff; - uint32_t offset; + unsigned int posy, posx; + unsigned int offset; trace_artist_vram_write(size, addr, val); if (s->cmap_bm_access) { @@ -1137,6 +1171,9 @@ static void artist_vram_write(void *opaque, hwaddr addr, uint64_t val, } buf = vram_write_buffer(s); + posy = ADDR_TO_Y(addr); + posx = ADDR_TO_X(addr); + if (!buf->size) { return; } @@ -1146,18 +1183,28 @@ static void artist_vram_write(void *opaque, hwaddr addr, uint64_t val, } offset = posy * buf->width + posx; + if (offset >= buf->size) { + return; + } + switch (size) { case 4: - *(uint32_t *)(buf->data + offset) = be32_to_cpu(val); - memory_region_set_dirty(&buf->mr, offset, 4); + if (offset + 3 < buf->size) { + *(uint32_t *)(buf->data + offset) = be32_to_cpu(val); + memory_region_set_dirty(&buf->mr, offset, 4); + } break; case 2: - *(uint16_t *)(buf->data + offset) = be16_to_cpu(val); - memory_region_set_dirty(&buf->mr, offset, 2); + if (offset + 1 < buf->size) { + *(uint16_t *)(buf->data + offset) = be16_to_cpu(val); + memory_region_set_dirty(&buf->mr, offset, 2); + } break; case 1: - *(uint8_t *)(buf->data + offset) = val; - memory_region_set_dirty(&buf->mr, offset, 1); + if (offset < buf->size) { + *(uint8_t *)(buf->data + offset) = val; + memory_region_set_dirty(&buf->mr, offset, 1); + } break; default: break; @@ -1169,13 +1216,16 @@ static uint64_t artist_vram_read(void *opaque, hwaddr addr, unsigned size) ARTISTState *s = opaque; struct vram_buffer *buf; uint64_t val; - int posy, posx; + unsigned int posy, posx; if (s->cmap_bm_access) { buf = &s->vram_buffer[ARTIST_BUFFER_CMAP]; - val = *(uint32_t *)(buf->data + addr); + val = 0; + if (addr < buf->size && addr + 3 < buf->size) { + val = *(uint32_t *)(buf->data + addr); + } trace_artist_vram_read(size, addr, 0, 0, val); - return 0; + return val; } buf = vram_read_buffer(s); @@ -1183,8 +1233,8 @@ static uint64_t artist_vram_read(void *opaque, hwaddr addr, unsigned size) return 0; } - posy = (addr >> 13) & 0x3ff; - posx = (addr >> 2) & 0x7ff; + posy = ADDR_TO_Y(addr); + posx = ADDR_TO_X(addr); if (posy > buf->height || posx > buf->width) { return 0; @@ -1199,20 +1249,16 @@ static const MemoryRegionOps artist_reg_ops = { .read = artist_reg_read, .write = artist_reg_write, .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 1, - .max_access_size = 4, - }, + .impl.min_access_size = 1, + .impl.max_access_size = 4, }; static const MemoryRegionOps artist_vram_ops = { .read = artist_vram_read, .write = artist_vram_write, .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 1, - .max_access_size = 4, - }, + .impl.min_access_size = 1, + .impl.max_access_size = 4, }; static void artist_draw_cursor(ARTISTState *s) @@ -1332,6 +1378,18 @@ static void artist_realizefn(DeviceState *dev, Error **errp) struct vram_buffer *buf; hwaddr offset = 0; + if (s->width > 2048 || s->height > 2048) { + error_report("artist: screen size can not exceed 2048 x 2048 pixel."); + s->width = MIN(s->width, 2048); + s->height = MIN(s->height, 2048); + } + + if (s->width < 640 || s->height < 480) { + error_report("artist: minimum screen size is 640 x 480 pixel."); + s->width = MAX(s->width, 640); + s->height = MAX(s->height, 480); + } + memory_region_init(&s->mem_as_root, OBJECT(dev), "artist", ~0ull); address_space_init(&s->as, &s->mem_as_root, "artist"); diff --git a/hw/display/ati.c b/hw/display/ati.c index 065f197678e49faeb45cd29de59f753699f42c41..4c3ad8f47b0dd487552b1eceb3f232bd1af72c19 100644 --- a/hw/display/ati.c +++ b/hw/display/ati.c @@ -86,8 +86,8 @@ static void ati_vga_switch_mode(ATIVGAState *s) break; default: qemu_log_mask(LOG_UNIMP, "Unsupported bpp value\n"); + return; } - assert(bpp != 0); DPRINTF("Switching to %dx%d %d %d @ %x\n", h, v, stride, bpp, offs); vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_ENABLE); vbe_ioport_write_data(&s->vga, 0, VBE_DISPI_DISABLED); @@ -285,8 +285,11 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size) if (idx <= s->vga.vram_size - size) { val = ldn_le_p(s->vga.vram_ptr + idx, size); } - } else { + } else if (s->regs.mm_index > MM_DATA + 3) { val = ati_mm_read(s, s->regs.mm_index + addr - MM_DATA, size); + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "ati_mm_read: mm_index too small: %u\n", s->regs.mm_index); } break; case BIOS_0_SCRATCH ... BUS_CNTL - 1: @@ -358,6 +361,11 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size) case MC_STATUS: val = 5; break; + case MEM_SDRAM_MODE_REG: + if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) { + val = BIT(28) | BIT(20); + } + break; case RBBM_STATUS: case GUI_STAT: val = 64; /* free CMDFIFO entries */ @@ -386,22 +394,28 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size) case 0xf00 ... 0xfff: val = pci_default_read_config(&s->dev, addr - 0xf00, size); break; - case CUR_OFFSET: - val = s->regs.cur_offset; + case CUR_OFFSET ... CUR_OFFSET + 3: + val = ati_reg_read_offs(s->regs.cur_offset, addr - CUR_OFFSET, size); break; - case CUR_HORZ_VERT_POSN: - val = s->regs.cur_hv_pos; - val |= s->regs.cur_offset & BIT(31); + case CUR_HORZ_VERT_POSN ... CUR_HORZ_VERT_POSN + 3: + val = ati_reg_read_offs(s->regs.cur_hv_pos, + addr - CUR_HORZ_VERT_POSN, size); + if (addr + size > CUR_HORZ_VERT_POSN + 3) { + val |= (s->regs.cur_offset & BIT(31)) >> (4 - size); + } break; - case CUR_HORZ_VERT_OFF: - val = s->regs.cur_hv_offs; - val |= s->regs.cur_offset & BIT(31); + case CUR_HORZ_VERT_OFF ... CUR_HORZ_VERT_OFF + 3: + val = ati_reg_read_offs(s->regs.cur_hv_offs, + addr - CUR_HORZ_VERT_OFF, size); + if (addr + size > CUR_HORZ_VERT_OFF + 3) { + val |= (s->regs.cur_offset & BIT(31)) >> (4 - size); + } break; - case CUR_CLR0: - val = s->regs.cur_color0; + case CUR_CLR0 ... CUR_CLR0 + 3: + val = ati_reg_read_offs(s->regs.cur_color0, addr - CUR_CLR0, size); break; - case CUR_CLR1: - val = s->regs.cur_color1; + case CUR_CLR1 ... CUR_CLR1 + 3: + val = ati_reg_read_offs(s->regs.cur_color1, addr - CUR_CLR1, size); break; case DST_OFFSET: val = s->regs.dst_offset; @@ -520,8 +534,11 @@ static void ati_mm_write(void *opaque, hwaddr addr, if (idx <= s->vga.vram_size - size) { stn_le_p(s->vga.vram_ptr + idx, size, data); } - } else { + } else if (s->regs.mm_index > MM_DATA + 3) { ati_mm_write(s, s->regs.mm_index + addr - MM_DATA, data, size); + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "ati_mm_write: mm_index too small: %u\n", s->regs.mm_index); } break; case BIOS_0_SCRATCH ... BUS_CNTL - 1: @@ -673,48 +690,71 @@ static void ati_mm_write(void *opaque, hwaddr addr, case 0xf00 ... 0xfff: /* read-only copy of PCI config space so ignore writes */ break; - case CUR_OFFSET: - if (s->regs.cur_offset != (data & 0x87fffff0)) { - s->regs.cur_offset = data & 0x87fffff0; + case CUR_OFFSET ... CUR_OFFSET + 3: + { + uint32_t t = s->regs.cur_offset; + + ati_reg_write_offs(&t, addr - CUR_OFFSET, data, size); + t &= 0x87fffff0; + if (s->regs.cur_offset != t) { + s->regs.cur_offset = t; ati_cursor_define(s); } break; - case CUR_HORZ_VERT_POSN: - s->regs.cur_hv_pos = data & 0x3fff0fff; - if (data & BIT(31)) { - s->regs.cur_offset |= data & BIT(31); + } + case CUR_HORZ_VERT_POSN ... CUR_HORZ_VERT_POSN + 3: + { + uint32_t t = s->regs.cur_hv_pos | (s->regs.cur_offset & BIT(31)); + + ati_reg_write_offs(&t, addr - CUR_HORZ_VERT_POSN, data, size); + s->regs.cur_hv_pos = t & 0x3fff0fff; + if (t & BIT(31)) { + s->regs.cur_offset |= t & BIT(31); } else if (s->regs.cur_offset & BIT(31)) { s->regs.cur_offset &= ~BIT(31); ati_cursor_define(s); } if (!s->cursor_guest_mode && - (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) && !(data & BIT(31))) { + (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) && !(t & BIT(31))) { dpy_mouse_set(s->vga.con, s->regs.cur_hv_pos >> 16, s->regs.cur_hv_pos & 0xffff, 1); } break; + } case CUR_HORZ_VERT_OFF: - s->regs.cur_hv_offs = data & 0x3f003f; - if (data & BIT(31)) { - s->regs.cur_offset |= data & BIT(31); + { + uint32_t t = s->regs.cur_hv_offs | (s->regs.cur_offset & BIT(31)); + + ati_reg_write_offs(&t, addr - CUR_HORZ_VERT_OFF, data, size); + s->regs.cur_hv_offs = t & 0x3f003f; + if (t & BIT(31)) { + s->regs.cur_offset |= t & BIT(31); } else if (s->regs.cur_offset & BIT(31)) { s->regs.cur_offset &= ~BIT(31); ati_cursor_define(s); } break; - case CUR_CLR0: - if (s->regs.cur_color0 != (data & 0xffffff)) { - s->regs.cur_color0 = data & 0xffffff; + } + case CUR_CLR0 ... CUR_CLR0 + 3: + { + uint32_t t = s->regs.cur_color0; + + ati_reg_write_offs(&t, addr - CUR_CLR0, data, size); + t &= 0xffffff; + if (s->regs.cur_color0 != t) { + s->regs.cur_color0 = t; ati_cursor_define(s); } break; - case CUR_CLR1: + } + case CUR_CLR1 ... CUR_CLR1 + 3: /* * Update cursor unconditionally here because some clients set up * other registers before actually writing cursor data to memory at * offset so we would miss cursor change unless always updating here */ - s->regs.cur_color1 = data & 0xffffff; + ati_reg_write_offs(&s->regs.cur_color1, addr - CUR_CLR1, data, size); + s->regs.cur_color1 &= 0xffffff; ati_cursor_define(s); break; case DST_OFFSET: @@ -927,8 +967,9 @@ static void ati_vga_realize(PCIDevice *dev, Error **errp) /* ddc, edid */ I2CBus *i2cbus = i2c_init_bus(DEVICE(s), "ati-vga.ddc"); bitbang_i2c_init(&s->bbi2c, i2cbus); - I2CSlave *i2cddc = I2C_SLAVE(qdev_create(BUS(i2cbus), TYPE_I2CDDC)); + I2CSlave *i2cddc = I2C_SLAVE(qdev_new(TYPE_I2CDDC)); i2c_set_slave_address(i2cddc, 0x50); + qdev_realize_and_unref(DEVICE(i2cddc), BUS(i2cbus), &error_abort); /* mmio register space */ memory_region_init_io(&s->mm, OBJECT(s), &ati_mm_ops, s, diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c index 23a8ae0cd8ceb7b59408c0709e2f13b3531d994e..4dc10ea79529b354f6bdeb92e0056def6ed69f30 100644 --- a/hw/display/ati_2d.c +++ b/hw/display/ati_2d.c @@ -75,8 +75,9 @@ void ati_2d_blt(ATIVGAState *s) dst_stride *= bpp; } uint8_t *end = s->vga.vram_ptr + s->vga.vram_size; - if (dst_bits >= end || dst_bits + dst_x + (dst_y + s->regs.dst_height) * - dst_stride >= end) { + if (dst_x > 0x3fff || dst_y > 0x3fff || dst_bits >= end + || dst_bits + dst_x + + (dst_y + s->regs.dst_height) * dst_stride >= end) { qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n"); return; } @@ -107,8 +108,9 @@ void ati_2d_blt(ATIVGAState *s) src_bits += s->regs.crtc_offset & 0x07ffffff; src_stride *= bpp; } - if (src_bits >= end || src_bits + src_x + - (src_y + s->regs.dst_height) * src_stride >= end) { + if (src_x > 0x3fff || src_y > 0x3fff || src_bits >= end + || src_bits + src_x + + (src_y + s->regs.dst_height) * src_stride >= end) { qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n"); return; } diff --git a/hw/display/ati_dbg.c b/hw/display/ati_dbg.c index 0ebbd36f1477e9981e80a316bfe40db16dccdb5e..bd0ecd48c7a743a797398ca65cd6109effff5472 100644 --- a/hw/display/ati_dbg.c +++ b/hw/display/ati_dbg.c @@ -42,6 +42,7 @@ static struct ati_regdesc ati_reg_names[] = { {"MC_FB_LOCATION", 0x0148}, {"MC_AGP_LOCATION", 0x014C}, {"MC_STATUS", 0x0150}, + {"MEM_SDRAM_MODE_REG", 0x0158}, {"MEM_POWER_MISC", 0x015c}, {"AGP_BASE", 0x0170}, {"AGP_CNTL", 0x0174}, diff --git a/hw/display/ati_int.h b/hw/display/ati_int.h index 2a16708e4f3ea066f0fb4120281eaede5d130f7f..8acb9c746697f96b5c87ccf3baebbfc88ec7c3ed 100644 --- a/hw/display/ati_int.h +++ b/hw/display/ati_int.h @@ -13,6 +13,7 @@ #include "hw/pci/pci.h" #include "hw/i2c/bitbang_i2c.h" #include "vga_int.h" +#include "qom/object.h" /*#define DEBUG_ATI*/ @@ -29,7 +30,7 @@ #define PCI_DEVICE_ID_ATI_RADEON_QY 0x5159 #define TYPE_ATI_VGA "ati-vga" -#define ATI_VGA(obj) OBJECT_CHECK(ATIVGAState, (obj), TYPE_ATI_VGA) +OBJECT_DECLARE_SIMPLE_TYPE(ATIVGAState, ATI_VGA) typedef struct ATIVGARegs { uint32_t mm_index; @@ -82,7 +83,7 @@ typedef struct ATIVGARegs { uint32_t default_sc_bottom_right; } ATIVGARegs; -typedef struct ATIVGAState { +struct ATIVGAState { PCIDevice dev; VGACommonState vga; char *model; @@ -97,7 +98,7 @@ typedef struct ATIVGAState { MemoryRegion io; MemoryRegion mm; ATIVGARegs regs; -} ATIVGAState; +}; const char *ati_reg_name(int num); diff --git a/hw/display/ati_regs.h b/hw/display/ati_regs.h index ebd37ee30d3f35908d9e2a049b796525831f6dba..d6282b2ef21006f73a124081e8ee5a23a21f4347 100644 --- a/hw/display/ati_regs.h +++ b/hw/display/ati_regs.h @@ -60,6 +60,7 @@ #define MC_FB_LOCATION 0x0148 #define MC_AGP_LOCATION 0x014C #define MC_STATUS 0x0150 +#define MEM_SDRAM_MODE_REG 0x0158 #define MEM_POWER_MISC 0x015c #define AGP_BASE 0x0170 #define AGP_CNTL 0x0174 diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c index c6263808a27af277b764327491dc1063e518b954..2be77bdd3a0637a0a7910fa112ef93f501ada0db 100644 --- a/hw/display/bcm2835_fb.c +++ b/hw/display/bcm2835_fb.c @@ -10,7 +10,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -282,6 +282,10 @@ static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value) newconf.base = s->vcram_base | (value & 0xc0000000); newconf.base += BCM2835_FB_OFFSET; + /* Copy fields which we don't want to change from the existing config */ + newconf.pixo = s->config.pixo; + newconf.alpha = s->config.alpha; + bcm2835_fb_validate_config(&newconf); pitch = bcm2835_fb_get_pitch(&newconf); @@ -401,7 +405,6 @@ static void bcm2835_fb_reset(DeviceState *dev) static void bcm2835_fb_realize(DeviceState *dev, Error **errp) { BCM2835FBState *s = BCM2835_FB(dev); - Error *err = NULL; Object *obj; if (s->vcram_base == 0) { @@ -409,12 +412,7 @@ static void bcm2835_fb_realize(DeviceState *dev, Error **errp) return; } - obj = object_property_get_link(OBJECT(dev), "dma-mr", &err); - if (obj == NULL) { - error_setg(errp, "%s: required dma-mr link not found: %s", - __func__, error_get_pretty(err)); - return; - } + obj = object_property_get_link(OBJECT(dev), "dma-mr", &error_abort); /* Fill in the parts of initial_config that are not set by QOM properties */ s->initial_config.xres_virtual = s->initial_config.xres; diff --git a/hw/display/bochs-display.c b/hw/display/bochs-display.c index a8e8ab8325f0cb33be82db6e6998e17e74675071..8ed734b195689b82d0b5a476d99504ee8d520700 100644 --- a/hw/display/bochs-display.c +++ b/hw/display/bochs-display.c @@ -18,6 +18,7 @@ #include "ui/console.h" #include "ui/qemu-pixman.h" +#include "qom/object.h" typedef struct BochsDisplayMode { pixman_format_code_t format; @@ -29,7 +30,7 @@ typedef struct BochsDisplayMode { uint64_t size; } BochsDisplayMode; -typedef struct BochsDisplayState { +struct BochsDisplayState { /* parent */ PCIDevice pci; @@ -53,11 +54,10 @@ typedef struct BochsDisplayState { /* device state */ BochsDisplayMode mode; -} BochsDisplayState; +}; #define TYPE_BOCHS_DISPLAY "bochs-display" -#define BOCHS_DISPLAY(obj) OBJECT_CHECK(BochsDisplayState, (obj), \ - TYPE_BOCHS_DISPLAY) +OBJECT_DECLARE_SIMPLE_TYPE(BochsDisplayState, BOCHS_DISPLAY) static const VMStateDescription vmstate_bochs_display = { .name = "bochs-display", diff --git a/hw/display/cg3.c b/hw/display/cg3.c index f7f1c199ce54d12a4a1193153ede3b10fbb061aa..42fcf40010207eac5a389bdee61048904ccee5a1 100644 --- a/hw/display/cg3.c +++ b/hw/display/cg3.c @@ -35,6 +35,8 @@ #include "hw/qdev-properties.h" #include "qemu/log.h" #include "qemu/module.h" +#include "trace.h" +#include "qom/object.h" /* Change to 1 to enable debugging */ #define DEBUG_CG3 0 @@ -63,16 +65,10 @@ #define CG3_VRAM_SIZE 0x100000 #define CG3_VRAM_OFFSET 0x800000 -#define DPRINTF(fmt, ...) do { \ - if (DEBUG_CG3) { \ - printf("CG3: " fmt , ## __VA_ARGS__); \ - } \ -} while (0) - #define TYPE_CG3 "cgthree" -#define CG3(obj) OBJECT_CHECK(CG3State, (obj), TYPE_CG3) +OBJECT_DECLARE_SIMPLE_TYPE(CG3State, CG3) -typedef struct CG3State { +struct CG3State { SysBusDevice parent_obj; QemuConsole *con; @@ -87,7 +83,7 @@ typedef struct CG3State { uint8_t r[256], g[256], b[256]; uint16_t width, height, depth; uint8_t dac_index, dac_state; -} CG3State; +}; static void cg3_update_display(void *opaque) { @@ -195,7 +191,8 @@ static uint64_t cg3_reg_read(void *opaque, hwaddr addr, unsigned size) val = 0; break; } - DPRINTF("read %02x from reg %" HWADDR_PRIx "\n", val, addr); + trace_cg3_read(addr, val, size); + return val; } @@ -206,9 +203,7 @@ static void cg3_reg_write(void *opaque, hwaddr addr, uint64_t val, uint8_t regval; int i; - DPRINTF("write %" PRIx64 " to reg %" HWADDR_PRIx " size %d\n", - val, addr, size); - + trace_cg3_write(addr, val, size); switch (addr) { case CG3_REG_BT458_ADDR: s->dac_index = val; diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index 1f29731ffe115959cc089edf5073e1945d45f814..fdca6ca659f9147a630a64804d784ec890564aae 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -35,6 +35,7 @@ #include "qemu/osdep.h" #include "qemu/module.h" #include "qemu/units.h" +#include "qemu/log.h" #include "sysemu/reset.h" #include "qapi/error.h" #include "trace.h" @@ -43,6 +44,7 @@ #include "migration/vmstate.h" #include "ui/pixel_ops.h" #include "cirrus_vga_internal.h" +#include "qom/object.h" /* * TODO: @@ -52,7 +54,6 @@ */ //#define DEBUG_CIRRUS -//#define DEBUG_BITBLT /*************************************** * @@ -178,14 +179,13 @@ typedef void (*cirrus_fill_t)(struct CirrusVGAState *s, uint32_t dstaddr, int dst_pitch, int width, int height); -typedef struct PCICirrusVGAState { +struct PCICirrusVGAState { PCIDevice dev; CirrusVGAState cirrus_vga; -} PCICirrusVGAState; +}; #define TYPE_PCI_CIRRUS_VGA "cirrus-vga" -#define PCI_CIRRUS_VGA(obj) \ - OBJECT_CHECK(PCICirrusVGAState, (obj), TYPE_PCI_CIRRUS_VGA) +OBJECT_DECLARE_SIMPLE_TYPE(PCICirrusVGAState, PCI_CIRRUS_VGA) static uint8_t rop_to_index[256]; @@ -640,10 +640,16 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin, } for (y = 0; y < lines; y++) { - off_cur = off_begin; + off_cur = off_begin & s->cirrus_addr_mask; off_cur_end = ((off_cur + bytesperline - 1) & s->cirrus_addr_mask) + 1; - assert(off_cur_end >= off_cur); - memory_region_set_dirty(&s->vga.vram, off_cur, off_cur_end - off_cur); + if (off_cur_end >= off_cur) { + memory_region_set_dirty(&s->vga.vram, off_cur, off_cur_end - off_cur); + } else { + /* wraparound */ + memory_region_set_dirty(&s->vga.vram, off_cur, + s->cirrus_addr_mask + 1 - off_cur); + memory_region_set_dirty(&s->vga.vram, 0, off_cur_end); + } off_begin += off_pitch; } } @@ -905,9 +911,8 @@ static int cirrus_bitblt_cputovideo(CirrusVGAState * s) static int cirrus_bitblt_videotocpu(CirrusVGAState * s) { /* XXX */ -#ifdef DEBUG_BITBLT - printf("cirrus: bitblt (video to cpu) is not implemented yet\n"); -#endif + qemu_log_mask(LOG_UNIMP, + "cirrus: bitblt (video to cpu) is not implemented\n"); return 0; } @@ -950,19 +955,16 @@ static void cirrus_bitblt_start(CirrusVGAState * s) s->cirrus_blt_dstaddr &= s->cirrus_addr_mask; s->cirrus_blt_srcaddr &= s->cirrus_addr_mask; -#ifdef DEBUG_BITBLT - printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spitch=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n", - blt_rop, - s->cirrus_blt_mode, - s->cirrus_blt_modeext, - s->cirrus_blt_width, - s->cirrus_blt_height, - s->cirrus_blt_dstpitch, - s->cirrus_blt_srcpitch, - s->cirrus_blt_dstaddr, - s->cirrus_blt_srcaddr, - s->vga.gr[0x2f]); -#endif + trace_vga_cirrus_bitblt_start(blt_rop, + s->cirrus_blt_mode, + s->cirrus_blt_modeext, + s->cirrus_blt_width, + s->cirrus_blt_height, + s->cirrus_blt_dstpitch, + s->cirrus_blt_srcpitch, + s->cirrus_blt_dstaddr, + s->cirrus_blt_srcaddr, + s->vga.gr[0x2f]); switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) { case CIRRUS_BLTMODE_PIXELWIDTH8: @@ -978,9 +980,8 @@ static void cirrus_bitblt_start(CirrusVGAState * s) s->cirrus_blt_pixelwidth = 4; break; default: -#ifdef DEBUG_BITBLT - printf("cirrus: bitblt - pixel width is unknown\n"); -#endif + qemu_log_mask(LOG_GUEST_ERROR, + "cirrus: bitblt - pixel width is unknown\n"); goto bitblt_ignore; } s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK; @@ -989,9 +990,8 @@ static void cirrus_bitblt_start(CirrusVGAState * s) cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) { -#ifdef DEBUG_BITBLT - printf("cirrus: bitblt - memory-to-memory copy is requested\n"); -#endif + qemu_log_mask(LOG_UNIMP, + "cirrus: bitblt - memory-to-memory copy requested\n"); goto bitblt_ignore; } @@ -1038,7 +1038,9 @@ static void cirrus_bitblt_start(CirrusVGAState * s) } else { if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { if (s->cirrus_blt_pixelwidth > 2) { - printf("src transparent without colorexpand must be 8bpp or 16bpp\n"); + qemu_log_mask(LOG_GUEST_ERROR, + "cirrus: src transparent without colorexpand " + "must be 8bpp or 16bpp\n"); goto bitblt_ignore; } if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) { @@ -1136,10 +1138,9 @@ static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s) ret = 16; break; /* XGA HiColor */ default: -#ifdef DEBUG_CIRRUS - printf("cirrus: invalid DAC value %x in 16bpp\n", - (s->cirrus_hidden_dac_data & 0xf)); -#endif + qemu_log_mask(LOG_GUEST_ERROR, + "cirrus: invalid DAC value 0x%x in 16bpp\n", + (s->cirrus_hidden_dac_data & 0xf)); ret = 15; /* XXX */ break; } @@ -1308,11 +1309,9 @@ static int cirrus_vga_read_sr(CirrusVGAState * s) #endif return s->vga.sr[s->vga.sr_index]; default: -#ifdef DEBUG_CIRRUS - printf("cirrus: inport sr_index %02x\n", s->vga.sr_index); -#endif + qemu_log_mask(LOG_GUEST_ERROR, + "cirrus: inport sr_index 0x%02x\n", s->vga.sr_index); return 0xff; - break; } } @@ -1401,10 +1400,9 @@ static void cirrus_vga_write_sr(CirrusVGAState * s, uint32_t val) cirrus_update_memory_access(s); break; default: -#ifdef DEBUG_CIRRUS - printf("cirrus: outport sr_index %02x, sr_value %02x\n", - s->vga.sr_index, val); -#endif + qemu_log_mask(LOG_GUEST_ERROR, + "cirrus: outport sr_index 0x%02x, sr_value 0x%02x\n", + s->vga.sr_index, val); break; } } @@ -1502,9 +1500,8 @@ static int cirrus_vga_read_gr(CirrusVGAState * s, unsigned reg_index) if (reg_index < 0x3a) { return s->vga.gr[reg_index]; } else { -#ifdef DEBUG_CIRRUS - printf("cirrus: inport gr_index %02x\n", reg_index); -#endif + qemu_log_mask(LOG_GUEST_ERROR, + "cirrus: inport gr_index 0x%02x\n", reg_index); return 0xff; } } @@ -1512,9 +1509,7 @@ static int cirrus_vga_read_gr(CirrusVGAState * s, unsigned reg_index) static void cirrus_vga_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value) { -#if defined(DEBUG_BITBLT) && 0 - printf("gr%02x: %02x\n", reg_index, reg_value); -#endif + trace_vga_cirrus_write_gr(reg_index, reg_value); switch (reg_index) { case 0x00: // Standard VGA, BGCOLOR 0x000000ff s->vga.gr[reg_index] = reg_value & gr_mask[reg_index]; @@ -1593,10 +1588,9 @@ cirrus_vga_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value) cirrus_write_bitblt(s, reg_value); break; default: -#ifdef DEBUG_CIRRUS - printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index, - reg_value); -#endif + qemu_log_mask(LOG_GUEST_ERROR, + "cirrus: outport gr_index 0x%02x, gr_value 0x%02x\n", + reg_index, reg_value); break; } } @@ -1649,11 +1643,9 @@ static int cirrus_vga_read_cr(CirrusVGAState * s, unsigned reg_index) return s->vga.cr[s->vga.cr_index]; case 0x26: // Attribute Controller Index Readback (R) return s->vga.ar_index & 0x3f; - break; default: -#ifdef DEBUG_CIRRUS - printf("cirrus: inport cr_index %02x\n", reg_index); -#endif + qemu_log_mask(LOG_GUEST_ERROR, + "cirrus: inport cr_index 0x%02x\n", reg_index); return 0xff; } } @@ -1724,10 +1716,9 @@ static void cirrus_vga_write_cr(CirrusVGAState * s, int reg_value) break; case 0x25: // Part Status default: -#ifdef DEBUG_CIRRUS - printf("cirrus: outport cr_index %02x, cr_value %02x\n", - s->vga.cr_index, reg_value); -#endif + qemu_log_mask(LOG_GUEST_ERROR, + "cirrus: outport cr_index 0x%02x, cr_value 0x%02x\n", + s->vga.cr_index, reg_value); break; } } @@ -1837,9 +1828,8 @@ static uint8_t cirrus_mmio_blt_read(CirrusVGAState * s, unsigned address) value = cirrus_vga_read_gr(s, 0x31); break; default: -#ifdef DEBUG_CIRRUS - printf("cirrus: mmio read - address 0x%04x\n", address); -#endif + qemu_log_mask(LOG_GUEST_ERROR, + "cirrus: mmio read - address 0x%04x\n", address); break; } @@ -1949,10 +1939,9 @@ static void cirrus_mmio_blt_write(CirrusVGAState * s, unsigned address, cirrus_vga_write_gr(s, 0x31, value); break; default: -#ifdef DEBUG_CIRRUS - printf("cirrus: mmio write - addr 0x%04x val 0x%02x (ignored)\n", - address, value); -#endif + qemu_log_mask(LOG_GUEST_ERROR, + "cirrus: mmio write - addr 0x%04x val 0x%02x (ignored)\n", + address, value); break; } } @@ -2050,9 +2039,8 @@ static uint64_t cirrus_vga_mem_read(void *opaque, } } else { val = 0xff; -#ifdef DEBUG_CIRRUS - printf("cirrus: mem_readb " TARGET_FMT_plx "\n", addr); -#endif + qemu_log_mask(LOG_GUEST_ERROR, + "cirrus: mem_readb 0x" TARGET_FMT_plx "\n", addr); } return val; } @@ -2115,10 +2103,9 @@ static void cirrus_vga_mem_write(void *opaque, cirrus_mmio_blt_write(s, addr & 0xff, mem_value); } } else { -#ifdef DEBUG_CIRRUS - printf("cirrus: mem_writeb " TARGET_FMT_plx " value 0x%02" PRIu64 "\n", addr, - mem_value); -#endif + qemu_log_mask(LOG_GUEST_ERROR, + "cirrus: mem_writeb 0x" TARGET_FMT_plx " " + "value 0x%02" PRIx64 "\n", addr, mem_value); } } @@ -2414,6 +2401,9 @@ static uint64_t cirrus_linear_bitblt_read(void *opaque, /* XXX handle bitblt */ (void)s; + qemu_log_mask(LOG_UNIMP, + "cirrus: linear bitblt is not implemented\n"); + return 0xff; } @@ -2542,9 +2532,6 @@ static uint64_t cirrus_vga_ioport_read(void *opaque, hwaddr addr, case 0x3c5: val = cirrus_vga_read_sr(c); break; -#ifdef DEBUG_VGA_REG - printf("vga: read SR%x = 0x%02x\n", s->sr_index, val); -#endif break; case 0x3c6: val = cirrus_read_hidden_dac(c); @@ -2570,9 +2557,6 @@ static uint64_t cirrus_vga_ioport_read(void *opaque, hwaddr addr, break; case 0x3cf: val = cirrus_vga_read_gr(c, s->gr_index); -#ifdef DEBUG_VGA_REG - printf("vga: read GR%x = 0x%02x\n", s->gr_index, val); -#endif break; case 0x3b4: case 0x3d4: @@ -2581,9 +2565,6 @@ static uint64_t cirrus_vga_ioport_read(void *opaque, hwaddr addr, case 0x3b5: case 0x3d5: val = cirrus_vga_read_cr(c, s->cr_index); -#ifdef DEBUG_VGA_REG - printf("vga: read CR%x = 0x%02x\n", s->cr_index, val); -#endif break; case 0x3ba: case 0x3da: @@ -2655,9 +2636,6 @@ static void cirrus_vga_ioport_write(void *opaque, hwaddr addr, uint64_t val, s->sr_index = val; break; case 0x3c5: -#ifdef DEBUG_VGA_REG - printf("vga: write SR%x = 0x%02" PRIu64 "\n", s->sr_index, val); -#endif cirrus_vga_write_sr(c, val); break; case 0x3c6: @@ -2680,9 +2658,6 @@ static void cirrus_vga_ioport_write(void *opaque, hwaddr addr, uint64_t val, s->gr_index = val; break; case 0x3cf: -#ifdef DEBUG_VGA_REG - printf("vga: write GR%x = 0x%02" PRIu64 "\n", s->gr_index, val); -#endif cirrus_vga_write_gr(c, s->gr_index, val); break; case 0x3b4: @@ -2691,9 +2666,6 @@ static void cirrus_vga_ioport_write(void *opaque, hwaddr addr, uint64_t val, break; case 0x3b5: case 0x3d5: -#ifdef DEBUG_VGA_REG - printf("vga: write CR%x = 0x%02"PRIu64"\n", s->cr_index, val); -#endif cirrus_vga_write_cr(c, val); break; case 0x3ba: diff --git a/hw/display/cirrus_vga_isa.c b/hw/display/cirrus_vga_isa.c index 825ba57298059270aae215cbe2f3a7fc69472160..4f6fb1af3bd59e6b69afb99500eb8fa7e16f1e36 100644 --- a/hw/display/cirrus_vga_isa.c +++ b/hw/display/cirrus_vga_isa.c @@ -30,16 +30,16 @@ #include "hw/qdev-properties.h" #include "hw/isa/isa.h" #include "cirrus_vga_internal.h" +#include "qom/object.h" #define TYPE_ISA_CIRRUS_VGA "isa-cirrus-vga" -#define ISA_CIRRUS_VGA(obj) \ - OBJECT_CHECK(ISACirrusVGAState, (obj), TYPE_ISA_CIRRUS_VGA) +OBJECT_DECLARE_SIMPLE_TYPE(ISACirrusVGAState, ISA_CIRRUS_VGA) -typedef struct ISACirrusVGAState { +struct ISACirrusVGAState { ISADevice parent_obj; CirrusVGAState cirrus_vga; -} ISACirrusVGAState; +}; static void isa_cirrus_vga_realizefn(DeviceState *dev, Error **errp) { diff --git a/hw/display/dpcd.c b/hw/display/dpcd.c index 170545c605ee98aad1bc52305a62d4dd59f45f81..64463654a1a007d7476d78f83785b089a8eccdd9 100644 --- a/hw/display/dpcd.c +++ b/hw/display/dpcd.c @@ -1,5 +1,5 @@ /* - * dpcd.c + * Xilinx Display Port Control Data * * Copyright (C) 2015 : GreenSocs Ltd * http://www.greensocs.com/ , email: info@greensocs.com @@ -32,16 +32,7 @@ #include "hw/misc/auxbus.h" #include "migration/vmstate.h" #include "hw/display/dpcd.h" - -#ifndef DEBUG_DPCD -#define DEBUG_DPCD 0 -#endif - -#define DPRINTF(fmt, ...) do { \ - if (DEBUG_DPCD) { \ - qemu_log("dpcd: " fmt, ## __VA_ARGS__); \ - } \ -} while (0) +#include "trace.h" #define DPCD_READABLE_AREA 0x600 @@ -70,8 +61,8 @@ static uint64_t dpcd_read(void *opaque, hwaddr offset, unsigned size) offset); ret = 0; } + trace_dpcd_read(offset, ret); - DPRINTF("read 0x%" PRIX8 " @0x%" HWADDR_PRIX "\n", ret, offset); return ret; } @@ -80,8 +71,7 @@ static void dpcd_write(void *opaque, hwaddr offset, uint64_t value, { DPCDState *e = DPCD(opaque); - DPRINTF("write 0x%" PRIX8 " @0x%" HWADDR_PRIX "\n", (uint8_t)value, offset); - + trace_dpcd_write(offset, value); if (offset < DPCD_READABLE_AREA) { e->dpcd_info[offset] = value; } else { @@ -137,7 +127,7 @@ static void dpcd_init(Object *obj) { DPCDState *s = DPCD(obj); - memory_region_init_io(&s->iomem, obj, &aux_ops, s, TYPE_DPCD, 0x7FFFF); + memory_region_init_io(&s->iomem, obj, &aux_ops, s, TYPE_DPCD, 0x80000); aux_init_mmio(AUX_SLAVE(obj), &s->iomem); } diff --git a/hw/display/edid-generate.c b/hw/display/edid-generate.c index e58472fde5015589f710235fd4b573790ac5f239..1665b7cbb29ae681fee9379571cabaf2a5a313d4 100644 --- a/hw/display/edid-generate.c +++ b/hw/display/edid-generate.c @@ -205,12 +205,8 @@ static void edid_desc_dummy(uint8_t *desc) static void edid_desc_timing(uint8_t *desc, uint32_t xres, uint32_t yres, - uint32_t dpi) + uint32_t xmm, uint32_t ymm) { - /* physical display size */ - uint32_t xmm = xres * dpi / 254; - uint32_t ymm = yres * dpi / 254; - /* pull some realistic looking timings out of thin air */ uint32_t xfront = xres * 25 / 100; uint32_t xsync = xres * 3 / 100; @@ -290,12 +286,24 @@ static void edid_colorspace(uint8_t *edid, edid[34] = white_y >> 2; } +static uint32_t qemu_edid_dpi_from_mm(uint32_t mm, uint32_t res) +{ + return res * 254 / 10 / mm; +} + +uint32_t qemu_edid_dpi_to_mm(uint32_t dpi, uint32_t res) +{ + return res * 254 / 10 / dpi; +} + void qemu_edid_generate(uint8_t *edid, size_t size, qemu_edid_info *info) { uint32_t desc = 54; uint8_t *xtra3 = NULL; uint8_t *dta = NULL; + uint32_t width_mm, height_mm; + uint32_t dpi = 100; /* if no width_mm/height_mm */ /* =============== set defaults =============== */ @@ -305,15 +313,20 @@ void qemu_edid_generate(uint8_t *edid, size_t size, if (!info->name) { info->name = "QEMU Monitor"; } - if (!info->dpi) { - info->dpi = 100; - } if (!info->prefx) { info->prefx = 1024; } if (!info->prefy) { info->prefy = 768; } + if (info->width_mm && info->height_mm) { + width_mm = info->width_mm; + height_mm = info->height_mm; + dpi = qemu_edid_dpi_from_mm(width_mm, info->prefx); + } else { + width_mm = qemu_edid_dpi_to_mm(dpi, info->prefx); + height_mm = qemu_edid_dpi_to_mm(dpi, info->prefy); + } /* =============== extensions =============== */ @@ -360,8 +373,8 @@ void qemu_edid_generate(uint8_t *edid, size_t size, edid[20] = 0xa5; /* screen size: undefined */ - edid[21] = info->prefx * 254 / 100 / info->dpi; - edid[22] = info->prefy * 254 / 100 / info->dpi; + edid[21] = width_mm / 10; + edid[22] = height_mm / 10; /* display gamma: 2.2 */ edid[23] = 220 - 100; @@ -387,7 +400,8 @@ void qemu_edid_generate(uint8_t *edid, size_t size, /* =============== descriptor blocks =============== */ - edid_desc_timing(edid + desc, info->prefx, info->prefy, info->dpi); + edid_desc_timing(edid + desc, info->prefx, info->prefy, + width_mm, height_mm); desc += 18; edid_desc_ranges(edid + desc); diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c index 1c0266ce9f2d74f0abc958b6b836a25998c24f34..34a960a976534ac8b960302d42fcd8ce4e175f43 100644 --- a/hw/display/exynos4210_fimd.c +++ b/hw/display/exynos4210_fimd.c @@ -31,6 +31,8 @@ #include "ui/pixel_ops.h" #include "qemu/bswap.h" #include "qemu/module.h" +#include "qemu/log.h" +#include "qom/object.h" /* Debug messages configuration */ #define EXYNOS4210_FIMD_DEBUG 0 @@ -39,20 +41,15 @@ #if EXYNOS4210_FIMD_DEBUG == 0 #define DPRINT_L1(fmt, args...) do { } while (0) #define DPRINT_L2(fmt, args...) do { } while (0) - #define DPRINT_ERROR(fmt, args...) do { } while (0) #elif EXYNOS4210_FIMD_DEBUG == 1 #define DPRINT_L1(fmt, args...) \ do {fprintf(stderr, "QEMU FIMD: "fmt, ## args); } while (0) #define DPRINT_L2(fmt, args...) do { } while (0) - #define DPRINT_ERROR(fmt, args...) \ - do {fprintf(stderr, "QEMU FIMD ERROR: "fmt, ## args); } while (0) #else #define DPRINT_L1(fmt, args...) \ do {fprintf(stderr, "QEMU FIMD: "fmt, ## args); } while (0) #define DPRINT_L2(fmt, args...) \ do {fprintf(stderr, "QEMU FIMD: "fmt, ## args); } while (0) - #define DPRINT_ERROR(fmt, args...) \ - do {fprintf(stderr, "QEMU FIMD ERROR: "fmt, ## args); } while (0) #endif #if EXYNOS4210_FIMD_MODE_TRACE == 0 @@ -297,10 +294,9 @@ struct Exynos4210fimdWindow { }; #define TYPE_EXYNOS4210_FIMD "exynos4210.fimd" -#define EXYNOS4210_FIMD(obj) \ - OBJECT_CHECK(Exynos4210fimdState, (obj), TYPE_EXYNOS4210_FIMD) +OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210fimdState, EXYNOS4210_FIMD) -typedef struct { +struct Exynos4210fimdState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -329,7 +325,7 @@ typedef struct { uint8_t *ifb; /* Internal frame buffer */ bool invalidate; /* Image needs to be redrawn */ bool enabled; /* Display controller is enabled */ -} Exynos4210fimdState; +}; /* Perform byte/halfword/word swap of data according to WINCON */ static inline void fimd_swap_data(unsigned int swap_ctl, uint64_t *data) @@ -1108,7 +1104,7 @@ static inline int fimd_get_buffer_id(Exynos4210fimdWindow *w) case FIMD_WINCON_BUF2_STAT: return 2; default: - DPRINT_ERROR("Non-existent buffer index\n"); + qemu_log_mask(LOG_GUEST_ERROR, "FIMD: Non-existent buffer index\n"); return 0; } } @@ -1160,20 +1156,24 @@ static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win) if (int128_get64(w->mem_section.size) != w->fb_len || !memory_region_is_ram(w->mem_section.mr)) { - DPRINT_ERROR("Failed to find window %u framebuffer region\n", win); + qemu_log_mask(LOG_GUEST_ERROR, + "FIMD: Failed to find window %u framebuffer region\n", + win); goto error_return; } w->host_fb_addr = cpu_physical_memory_map(fb_start_addr, &fb_mapped_len, false); if (!w->host_fb_addr) { - DPRINT_ERROR("Failed to map window %u framebuffer\n", win); + qemu_log_mask(LOG_GUEST_ERROR, + "FIMD: Failed to map window %u framebuffer\n", win); goto error_return; } if (fb_mapped_len != w->fb_len) { - DPRINT_ERROR("Window %u mapped framebuffer length is less then " - "expected\n", win); + qemu_log_mask(LOG_GUEST_ERROR, + "FIMD: Window %u mapped framebuffer length is less than " + "expected\n", win); cpu_physical_memory_unmap(w->host_fb_addr, fb_mapped_len, 0, 0); goto error_return; } @@ -1275,12 +1275,14 @@ static void exynos4210_fimd_update(void *opaque) bool blend = false; uint8_t *host_fb_addr; bool is_dirty = false; - const int global_width = (s->vidtcon[2] & FIMD_VIDTCON2_SIZE_MASK) + 1; + int global_width; if (!s || !s->console || !s->enabled || surface_bits_per_pixel(qemu_console_surface(s->console)) == 0) { return; } + + global_width = (s->vidtcon[2] & FIMD_VIDTCON2_SIZE_MASK) + 1; exynos4210_update_resolution(s); surface = qemu_console_surface(s->console); @@ -1490,7 +1492,9 @@ static void exynos4210_fimd_write(void *opaque, hwaddr offset, break; case 3: if (w != 1 && w != 2) { - DPRINT_ERROR("Bad write offset 0x%08x\n", offset); + qemu_log_mask(LOG_GUEST_ERROR, + "FIMD: Bad write offset 0x%08"HWADDR_PRIx"\n", + offset); return; } s->window[w].osdsize = val; @@ -1624,7 +1628,9 @@ static void exynos4210_fimd_write(void *opaque, hwaddr offset, break; case FIMD_VIDW0ADD0_B2 ... FIMD_VIDW4ADD0_B2: if (offset & 0x0004) { - DPRINT_ERROR("bad write offset 0x%08x\n", offset); + qemu_log_mask(LOG_GUEST_ERROR, + "FIMD: bad write offset 0x%08"HWADDR_PRIx"\n", + offset); break; } w = (offset - FIMD_VIDW0ADD0_B2) >> 3; @@ -1638,14 +1644,18 @@ static void exynos4210_fimd_write(void *opaque, hwaddr offset, break; case FIMD_SHD_ADD0_START ... FIMD_SHD_ADD0_END: if (offset & 0x0004) { - DPRINT_ERROR("bad write offset 0x%08x\n", offset); + qemu_log_mask(LOG_GUEST_ERROR, + "FIMD: bad write offset 0x%08"HWADDR_PRIx"\n", + offset); break; } s->window[(offset - FIMD_SHD_ADD0_START) >> 3].shadow_buf_start = val; break; case FIMD_SHD_ADD1_START ... FIMD_SHD_ADD1_END: if (offset & 0x0004) { - DPRINT_ERROR("bad write offset 0x%08x\n", offset); + qemu_log_mask(LOG_GUEST_ERROR, + "FIMD: bad write offset 0x%08"HWADDR_PRIx"\n", + offset); break; } s->window[(offset - FIMD_SHD_ADD1_START) >> 3].shadow_buf_end = val; @@ -1665,7 +1675,8 @@ static void exynos4210_fimd_write(void *opaque, hwaddr offset, s->window[w].palette[i] = val; break; default: - DPRINT_ERROR("bad write offset 0x%08x\n", offset); + qemu_log_mask(LOG_GUEST_ERROR, + "FIMD: bad write offset 0x%08"HWADDR_PRIx"\n", offset); break; } } @@ -1715,7 +1726,9 @@ static uint64_t exynos4210_fimd_read(void *opaque, hwaddr offset, break; case 3: if (w != 1 && w != 2) { - DPRINT_ERROR("bad read offset 0x%08x\n", offset); + qemu_log_mask(LOG_GUEST_ERROR, + "FIMD: bad read offset 0x%08"HWADDR_PRIx"\n", + offset); return 0xBAADBAAD; } ret = s->window[w].osdsize; @@ -1809,7 +1822,8 @@ static uint64_t exynos4210_fimd_read(void *opaque, hwaddr offset, return s->window[w].palette[i]; } - DPRINT_ERROR("bad read offset 0x%08x\n", offset); + qemu_log_mask(LOG_GUEST_ERROR, + "FIMD: bad read offset 0x%08"HWADDR_PRIx"\n", offset); return 0xBAADBAAD; } diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c index adcba96e34f87594d56f1a4b1e8cc2f31164d017..8f1725432cd1c1611158f5d7240499b953ac1708 100644 --- a/hw/display/g364fb.c +++ b/hw/display/g364fb.c @@ -29,6 +29,7 @@ #include "trace.h" #include "hw/sysbus.h" #include "migration/vmstate.h" +#include "qom/object.h" typedef struct G364State { /* hardware */ @@ -486,13 +487,13 @@ static void g364fb_init(DeviceState *dev, G364State *s) } #define TYPE_G364 "sysbus-g364" -#define G364(obj) OBJECT_CHECK(G364SysBusState, (obj), TYPE_G364) +OBJECT_DECLARE_SIMPLE_TYPE(G364SysBusState, G364) -typedef struct { +struct G364SysBusState { SysBusDevice parent_obj; G364State g364; -} G364SysBusState; +}; static void g364fb_sysbus_realize(DeviceState *dev, Error **errp) { diff --git a/hw/display/jazz_led.c b/hw/display/jazz_led.c index 1d845597f903b938afac406f40b09cc0d4bdd40e..dd5f4696c4f65fdb879e56d5a4625efb27d7bf3b 100644 --- a/hw/display/jazz_led.c +++ b/hw/display/jazz_led.c @@ -29,22 +29,23 @@ #include "trace.h" #include "hw/sysbus.h" #include "migration/vmstate.h" +#include "qom/object.h" typedef enum { REDRAW_NONE = 0, REDRAW_SEGMENTS = 1, REDRAW_BACKGROUND = 2, } screen_state_t; #define TYPE_JAZZ_LED "jazz-led" -#define JAZZ_LED(obj) OBJECT_CHECK(LedState, (obj), TYPE_JAZZ_LED) +OBJECT_DECLARE_SIMPLE_TYPE(LedState, JAZZ_LED) -typedef struct LedState { +struct LedState { SysBusDevice parent_obj; MemoryRegion iomem; uint8_t segments; QemuConsole *con; screen_state_t state; -} LedState; +}; static uint64_t jazz_led_read(void *opaque, hwaddr addr, unsigned int size) diff --git a/hw/display/macfb.c b/hw/display/macfb.c index b68faff4bb0cdf1e28dcfeb41e78372352be7670..ff8bdb846b97dc56c57ff70455f94bf5b6fcbc45 100644 --- a/hw/display/macfb.c +++ b/hw/display/macfb.c @@ -391,7 +391,7 @@ static void macfb_nubus_realize(DeviceState *dev, Error **errp) { NubusDevice *nd = NUBUS_DEVICE(dev); MacfbNubusState *s = NUBUS_MACFB(dev); - MacfbNubusDeviceClass *ndc = MACFB_NUBUS_GET_CLASS(dev); + MacfbNubusDeviceClass *ndc = NUBUS_MACFB_GET_CLASS(dev); MacfbState *ms = &s->macfb; ndc->parent_realize(dev, errp); @@ -443,7 +443,7 @@ static void macfb_sysbus_class_init(ObjectClass *klass, void *data) static void macfb_nubus_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - MacfbNubusDeviceClass *ndc = MACFB_NUBUS_DEVICE_CLASS(klass); + MacfbNubusDeviceClass *ndc = NUBUS_MACFB_CLASS(klass); device_class_set_parent_realize(dc, macfb_nubus_realize, &ndc->parent_realize); diff --git a/hw/display/meson.build b/hw/display/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..dad3bd2b414be7450a9624b78e530180ff9f9919 --- /dev/null +++ b/hw/display/meson.build @@ -0,0 +1,88 @@ +hw_display_modules = {} + +softmmu_ss.add(when: 'CONFIG_DDC', if_true: files('i2c-ddc.c')) +softmmu_ss.add(when: 'CONFIG_EDID', if_true: files('edid-generate.c', 'edid-region.c')) + +softmmu_ss.add(when: 'CONFIG_FW_CFG_DMA', if_true: files('ramfb.c')) +softmmu_ss.add(when: 'CONFIG_FW_CFG_DMA', if_true: files('ramfb-standalone.c')) + +softmmu_ss.add(when: 'CONFIG_ADS7846', if_true: files('ads7846.c')) +softmmu_ss.add(when: 'CONFIG_VGA_CIRRUS', if_true: files('cirrus_vga.c')) +softmmu_ss.add(when: ['CONFIG_VGA_CIRRUS', 'CONFIG_VGA_ISA'], if_true: files('cirrus_vga_isa.c')) +softmmu_ss.add(when: 'CONFIG_G364FB', if_true: files('g364fb.c')) +softmmu_ss.add(when: 'CONFIG_JAZZ_LED', if_true: files('jazz_led.c')) +softmmu_ss.add(when: 'CONFIG_PL110', if_true: files('pl110.c')) +softmmu_ss.add(when: 'CONFIG_SII9022', if_true: files('sii9022.c')) +softmmu_ss.add(when: 'CONFIG_SSD0303', if_true: files('ssd0303.c')) +softmmu_ss.add(when: 'CONFIG_SSD0323', if_true: files('ssd0323.c')) +softmmu_ss.add(when: 'CONFIG_XEN', if_true: files('xenfb.c')) + +softmmu_ss.add(when: 'CONFIG_VGA_PCI', if_true: files('vga-pci.c')) +softmmu_ss.add(when: 'CONFIG_VGA_ISA', if_true: files('vga-isa.c')) +softmmu_ss.add(when: 'CONFIG_VGA_ISA_MM', if_true: files('vga-isa-mm.c')) +softmmu_ss.add(when: 'CONFIG_VMWARE_VGA', if_true: files('vmware_vga.c')) +softmmu_ss.add(when: 'CONFIG_BOCHS_DISPLAY', if_true: files('bochs-display.c')) + +softmmu_ss.add(when: 'CONFIG_BLIZZARD', if_true: files('blizzard.c')) +softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_fimd.c')) +softmmu_ss.add(when: 'CONFIG_FRAMEBUFFER', if_true: files('framebuffer.c')) +softmmu_ss.add(when: 'CONFIG_ZAURUS', if_true: files('tc6393xb.c')) + +softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_dss.c')) +softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_lcd.c')) +softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_fb.c')) +softmmu_ss.add(when: 'CONFIG_SM501', if_true: files('sm501.c')) +softmmu_ss.add(when: 'CONFIG_TCX', if_true: files('tcx.c')) +softmmu_ss.add(when: 'CONFIG_CG3', if_true: files('cg3.c')) +softmmu_ss.add(when: 'CONFIG_MACFB', if_true: files('macfb.c')) +softmmu_ss.add(when: 'CONFIG_NEXTCUBE', if_true: files('next-fb.c')) + +specific_ss.add(when: 'CONFIG_VGA', if_true: files('vga.c')) + +if config_all_devices.has_key('CONFIG_QXL') + qxl_ss = ss.source_set() + qxl_ss.add(when: 'CONFIG_QXL', if_true: [files('qxl.c', 'qxl-logger.c', 'qxl-render.c'), + pixman, spice]) + hw_display_modules += {'qxl': qxl_ss} +endif + +softmmu_ss.add(when: 'CONFIG_DPCD', if_true: files('dpcd.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx_dp.c')) + +softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-vgafb.c')) +softmmu_ss.add(when: 'CONFIG_ARTIST', if_true: files('artist.c')) + +softmmu_ss.add(when: [pixman, 'CONFIG_ATI_VGA'], if_true: files('ati.c', 'ati_2d.c', 'ati_dbg.c')) + +if config_all_devices.has_key('CONFIG_VIRTIO_GPU') + virtio_gpu_ss = ss.source_set() + virtio_gpu_ss.add(when: 'CONFIG_VIRTIO_GPU', + if_true: [files('virtio-gpu-base.c', 'virtio-gpu.c'), pixman, virgl]) + virtio_gpu_ss.add(when: ['CONFIG_VIRTIO_GPU', 'CONFIG_VIRGL'], + if_true: [files('virtio-gpu-3d.c'), pixman, virgl]) + virtio_gpu_ss.add(when: 'CONFIG_VHOST_USER_GPU', if_true: files('vhost-user-gpu.c')) + hw_display_modules += {'virtio-gpu': virtio_gpu_ss} +endif + +if config_all_devices.has_key('CONFIG_VIRTIO_PCI') + virtio_gpu_pci_ss = ss.source_set() + virtio_gpu_pci_ss.add(when: ['CONFIG_VIRTIO_GPU', 'CONFIG_VIRTIO_PCI'], + if_true: [files('virtio-gpu-pci.c'), pixman]) + virtio_gpu_pci_ss.add(when: ['CONFIG_VHOST_USER_GPU', 'CONFIG_VIRTIO_PCI'], + if_true: files('vhost-user-gpu-pci.c')) + hw_display_modules += {'virtio-gpu-pci': virtio_gpu_pci_ss} +endif + +if config_all_devices.has_key('CONFIG_VIRTIO_VGA') + virtio_vga_ss = ss.source_set() + virtio_vga_ss.add(when: 'CONFIG_VIRTIO_VGA', + if_true: [files('virtio-vga.c'), pixman]) + virtio_vga_ss.add(when: 'CONFIG_VHOST_USER_VGA', + if_true: files('vhost-user-vga.c')) + hw_display_modules += {'virtio-vga': virtio_vga_ss} +endif + +specific_ss.add(when: [x11, opengl, 'CONFIG_MILKYMIST_TMU2'], if_true: files('milkymist-tmu2.c')) +specific_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_lcdc.c')) + +modules += { 'hw-display': hw_display_modules } diff --git a/hw/display/milkymist-tmu2.c b/hw/display/milkymist-tmu2.c index 513c0d5babd08676f0ace14a578a1b44a9b47801..02a28c807b5b88fcaaf493fac4152be64c33432a 100644 --- a/hw/display/milkymist-tmu2.c +++ b/hw/display/milkymist-tmu2.c @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -38,6 +38,7 @@ #include #include #include +#include "qom/object.h" enum { R_CTL = 0, @@ -82,8 +83,7 @@ struct vertex { } QEMU_PACKED; #define TYPE_MILKYMIST_TMU2 "milkymist-tmu2" -#define MILKYMIST_TMU2(obj) \ - OBJECT_CHECK(MilkymistTMU2State, (obj), TYPE_MILKYMIST_TMU2) +OBJECT_DECLARE_SIMPLE_TYPE(MilkymistTMU2State, MILKYMIST_TMU2) struct MilkymistTMU2State { SysBusDevice parent_obj; @@ -98,7 +98,6 @@ struct MilkymistTMU2State { GLXFBConfig glx_fb_config; GLXContext glx_context; }; -typedef struct MilkymistTMU2State MilkymistTMU2State; static const int glx_fbconfig_attr[] = { GLX_GREEN_SIZE, 5, @@ -543,8 +542,8 @@ DeviceState *milkymist_tmu2_create(hwaddr base, qemu_irq irq) XFree(configs); XCloseDisplay(d); - dev = qdev_create(NULL, TYPE_MILKYMIST_TMU2); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_MILKYMIST_TMU2); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq); diff --git a/hw/display/milkymist-vgafb.c b/hw/display/milkymist-vgafb.c index 6a6441e6ea367ffe567b2aec920d51b2e78c202f..e2c587e2dfcd0427ddf25f61eed0b1d5bdb9d8db 100644 --- a/hw/display/milkymist-vgafb.c +++ b/hw/display/milkymist-vgafb.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -32,6 +32,7 @@ #include "ui/pixel_ops.h" #include "qemu/error-report.h" #include "qemu/module.h" +#include "qom/object.h" #define BITS 8 #include "migration/vmstate.h" @@ -68,8 +69,7 @@ enum { }; #define TYPE_MILKYMIST_VGAFB "milkymist-vgafb" -#define MILKYMIST_VGAFB(obj) \ - OBJECT_CHECK(MilkymistVgafbState, (obj), TYPE_MILKYMIST_VGAFB) +OBJECT_DECLARE_SIMPLE_TYPE(MilkymistVgafbState, MILKYMIST_VGAFB) struct MilkymistVgafbState { SysBusDevice parent_obj; @@ -84,7 +84,6 @@ struct MilkymistVgafbState { uint32_t regs[R_MAX]; }; -typedef struct MilkymistVgafbState MilkymistVgafbState; static int vgafb_enabled(MilkymistVgafbState *s) { diff --git a/hw/display/milkymist-vgafb_template.h b/hw/display/milkymist-vgafb_template.h index 48837809eb0c43844dc2599192f0f75c6277c0b4..96137f970933c6cf4b45dd3007fdb0c9eb8317f8 100644 --- a/hw/display/milkymist-vgafb_template.h +++ b/hw/display/milkymist-vgafb_template.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/display/next-fb.c b/hw/display/next-fb.c index b0513a8fba62599235b6ecb2119998006c32f6d8..e2d895109dbe6608f02b8b870f5efaf149c4ab2e 100644 --- a/hw/display/next-fb.c +++ b/hw/display/next-fb.c @@ -30,8 +30,9 @@ #include "framebuffer.h" #include "ui/pixel_ops.h" #include "hw/m68k/next-cube.h" +#include "qom/object.h" -#define NEXTFB(obj) OBJECT_CHECK(NeXTFbState, (obj), TYPE_NEXTFB) +OBJECT_DECLARE_SIMPLE_TYPE(NeXTFbState, NEXTFB) struct NeXTFbState { SysBusDevice parent_obj; @@ -44,7 +45,6 @@ struct NeXTFbState { uint32_t rows; int invalidate; }; -typedef struct NeXTFbState NeXTFbState; static void nextfb_draw_line(void *opaque, uint8_t *d, const uint8_t *s, int width, int pitch) diff --git a/hw/display/omap_dss.c b/hw/display/omap_dss.c index 32dc0d6aa71697c66ce421a23d5b4fd0f3718a9c..21fde58a2602fd4878cdfe227038e545dd01d17f 100644 --- a/hw/display/omap_dss.c +++ b/hw/display/omap_dss.c @@ -619,7 +619,7 @@ static void omap_rfbi_transfer_start(struct omap_dss_s *s) if (s->rfbi.control & (1 << 1)) { /* BYPASS */ /* TODO: in non-Bypass mode we probably need to just assert the * DRQ and wait for DMA to write the pixels. */ - fprintf(stderr, "%s: Bypass mode unimplemented\n", __func__); + qemu_log_mask(LOG_UNIMP, "%s: Bypass mode unimplemented\n", __func__); return; } diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c index fa4a381db64b0828878b1f24ebcb67284d37ef98..58e659c94ff2f6b194744d90c521dd48fabefa9b 100644 --- a/hw/display/omap_lcdc.c +++ b/hw/display/omap_lcdc.c @@ -78,14 +78,18 @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s) static void omap_update_display(void *opaque) { struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque; - DisplaySurface *surface = qemu_console_surface(omap_lcd->con); + DisplaySurface *surface; draw_line_func draw_line; int size, height, first, last; int width, linesize, step, bpp, frame_offset; hwaddr frame_base; - if (!omap_lcd || omap_lcd->plm == 1 || !omap_lcd->enable || - !surface_bits_per_pixel(surface)) { + if (!omap_lcd || omap_lcd->plm == 1 || !omap_lcd->enable) { + return; + } + + surface = qemu_console_surface(omap_lcd->con); + if (!surface_bits_per_pixel(surface)) { return; } diff --git a/hw/display/pl110.c b/hw/display/pl110.c index c2991a28d20f1cf2487b20c20401b945695375a2..02b0d45f06246c79b07d9fa3c50a6064ded66328 100644 --- a/hw/display/pl110.c +++ b/hw/display/pl110.c @@ -17,6 +17,7 @@ #include "qemu/timer.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" #define PL110_CR_EN 0x001 #define PL110_CR_BGR 0x100 @@ -42,15 +43,15 @@ enum pl110_bppmode /* The Versatile/PB uses a slightly modified PL110 controller. */ enum pl110_version { - PL110, - PL110_VERSATILE, - PL111 + VERSION_PL110, + VERSION_PL110_VERSATILE, + VERSION_PL111 }; #define TYPE_PL110 "pl110" -#define PL110(obj) OBJECT_CHECK(PL110State, (obj), TYPE_PL110) +OBJECT_DECLARE_SIMPLE_TYPE(PL110State, PL110) -typedef struct PL110State { +struct PL110State { SysBusDevice parent_obj; MemoryRegion iomem; @@ -73,7 +74,7 @@ typedef struct PL110State { uint32_t palette[256]; uint32_t raw_palette[128]; qemu_irq irq; -} PL110State; +}; static int vmstate_pl110_post_load(void *opaque, int version_id); @@ -189,7 +190,7 @@ static void pl110_update_display(void *opaque) else bpp_offset = 24; - if ((s->version != PL111) && (s->bpp == BPP_16)) { + if ((s->version != VERSION_PL111) && (s->bpp == BPP_16)) { /* The PL110's native 16 bit mode is 5551; however * most boards with a PL110 implement an external * mux which allows bits to be reshuffled to give @@ -372,12 +373,12 @@ static uint64_t pl110_read(void *opaque, hwaddr offset, case 5: /* LCDLPBASE */ return s->lpbase; case 6: /* LCDIMSC */ - if (s->version != PL110) { + if (s->version != VERSION_PL110) { return s->cr; } return s->int_mask; case 7: /* LCDControl */ - if (s->version != PL110) { + if (s->version != VERSION_PL110) { return s->int_mask; } return s->cr; @@ -437,7 +438,7 @@ static void pl110_write(void *opaque, hwaddr offset, s->lpbase = val; break; case 6: /* LCDIMSC */ - if (s->version != PL110) { + if (s->version != VERSION_PL110) { goto control; } imsc: @@ -445,7 +446,7 @@ static void pl110_write(void *opaque, hwaddr offset, pl110_update(s); break; case 7: /* LCDControl */ - if (s->version != PL110) { + if (s->version != VERSION_PL110) { goto imsc; } control: @@ -513,21 +514,21 @@ static void pl110_init(Object *obj) { PL110State *s = PL110(obj); - s->version = PL110; + s->version = VERSION_PL110; } static void pl110_versatile_init(Object *obj) { PL110State *s = PL110(obj); - s->version = PL110_VERSATILE; + s->version = VERSION_PL110_VERSATILE; } static void pl111_init(Object *obj) { PL110State *s = PL110(obj); - s->version = PL111; + s->version = VERSION_PL111; } static void pl110_class_init(ObjectClass *klass, void *data) diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c index d5f2e82a4ec3687b24c667d1c6bbe60de590e5e9..ff90104b8011294c779552a0ecd840b04af478ba 100644 --- a/hw/display/pxa2xx_lcd.c +++ b/hw/display/pxa2xx_lcd.c @@ -426,9 +426,10 @@ static void pxa2xx_lcdc_write(void *opaque, hwaddr offset, if ((s->control[0] & LCCR0_ENB) && !(value & LCCR0_ENB)) s->status[0] |= LCSR0_QD; - if (!(s->control[0] & LCCR0_LCDT) && (value & LCCR0_LCDT)) - printf("%s: internal frame buffer unsupported\n", __func__); - + if (!(s->control[0] & LCCR0_LCDT) && (value & LCCR0_LCDT)) { + qemu_log_mask(LOG_UNIMP, + "%s: internal frame buffer unsupported\n", __func__); + } if ((s->control[3] & LCCR3_API) && (value & LCCR0_ENB) && !(value & LCCR0_LCDT)) s->status[0] |= LCSR0_ABC; @@ -462,9 +463,9 @@ static void pxa2xx_lcdc_write(void *opaque, hwaddr offset, break; case OVL1C1: - if (!(s->ovl1c[0] & OVLC1_EN) && (value & OVLC1_EN)) - printf("%s: Overlay 1 not supported\n", __func__); - + if (!(s->ovl1c[0] & OVLC1_EN) && (value & OVLC1_EN)) { + qemu_log_mask(LOG_UNIMP, "%s: Overlay 1 not supported\n", __func__); + } s->ovl1c[0] = value & 0x80ffffff; s->dma_ch[1].up = (value & OVLC1_EN) || (s->control[0] & LCCR0_SDS); break; @@ -474,9 +475,9 @@ static void pxa2xx_lcdc_write(void *opaque, hwaddr offset, break; case OVL2C1: - if (!(s->ovl2c[0] & OVLC1_EN) && (value & OVLC1_EN)) - printf("%s: Overlay 2 not supported\n", __func__); - + if (!(s->ovl2c[0] & OVLC1_EN) && (value & OVLC1_EN)) { + qemu_log_mask(LOG_UNIMP, "%s: Overlay 2 not supported\n", __func__); + } s->ovl2c[0] = value & 0x80ffffff; s->dma_ch[2].up = !!(value & OVLC1_EN); s->dma_ch[3].up = !!(value & OVLC1_EN); @@ -488,9 +489,10 @@ static void pxa2xx_lcdc_write(void *opaque, hwaddr offset, break; case CCR: - if (!(s->ccr & CCR_CEN) && (value & CCR_CEN)) - printf("%s: Hardware cursor unimplemented\n", __func__); - + if (!(s->ccr & CCR_CEN) && (value & CCR_CEN)) { + qemu_log_mask(LOG_UNIMP, + "%s: Hardware cursor unimplemented\n", __func__); + } s->ccr = value & 0x81ffffe7; s->dma_ch[5].up = !!(value & CCR_CEN); break; diff --git a/hw/display/qxl-logger.c b/hw/display/qxl-logger.c index 2ec6d8fa3d6cd3b6596d76654d53a923e64c5164..c15175bce3226737a5c206b81736302e6bb1bb6d 100644 --- a/hw/display/qxl-logger.c +++ b/hw/display/qxl-logger.c @@ -161,7 +161,6 @@ static int qxl_log_cmd_draw(PCIQXLDevice *qxl, QXLDrawable *draw, int group_id) switch (draw->type) { case QXL_DRAW_COPY: return qxl_log_cmd_draw_copy(qxl, &draw->u.copy, group_id); - break; } return 0; } @@ -180,7 +179,6 @@ static int qxl_log_cmd_draw_compat(PCIQXLDevice *qxl, QXLCompatDrawable *draw, switch (draw->type) { case QXL_DRAW_COPY: return qxl_log_cmd_draw_copy(qxl, &draw->u.copy, group_id); - break; } return 0; } diff --git a/hw/display/qxl.c b/hw/display/qxl.c index d5627119ec62a03475a75f5430a5ce620bc9b6c7..431c1070967abe6b6e43364f6170d2b43524d6d8 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -1762,7 +1762,16 @@ async_common: qxl_set_mode(d, val, 0); break; case QXL_IO_LOG: +#ifdef CONFIG_MODULES + /* + * FIXME + * trace_event_get_state_backends() does not work for modules, + * it leads to "undefined symbol: qemu_qxl_io_log_semaphore" + */ + if (true) { +#else if (trace_event_get_state_backends(TRACE_QXL_IO_LOG) || d->guestdebug) { +#endif /* We cannot trust the guest to NUL terminate d->ram->log_buf */ char *log_buf = g_strndup((const char *)d->ram->log_buf, sizeof(d->ram->log_buf)); @@ -1899,7 +1908,7 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events) /* * Older versions of Spice forgot to define the QXLRam struct * with the '__aligned__(4)' attribute. clang 7 and newer will - * thus warn that atomic_fetch_or(&d->ram->int_pending, ...) + * thus warn that qatomic_fetch_or(&d->ram->int_pending, ...) * might be a misaligned atomic access, and will generate an * out-of-line call for it, which results in a link error since * we don't currently link against libatomic. @@ -1919,7 +1928,7 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events) #define ALIGNED_UINT32_PTR(P) ((uint32_t *)P) #endif - old_pending = atomic_fetch_or(ALIGNED_UINT32_PTR(&d->ram->int_pending), + old_pending = qatomic_fetch_or(ALIGNED_UINT32_PTR(&d->ram->int_pending), le_events); if ((old_pending & le_events) == le_events) { return; diff --git a/hw/display/qxl.h b/hw/display/qxl.h index 707631a1f573169d2b04e4d827b75f4118f2dd7b..379d3304abc181df5bff81490c3330ed7b8baf7b 100644 --- a/hw/display/qxl.h +++ b/hw/display/qxl.h @@ -8,6 +8,7 @@ #include "ui/qemu-spice.h" #include "ui/spice-display.h" +#include "qom/object.h" enum qxl_mode { QXL_MODE_UNDEFINED, @@ -27,7 +28,7 @@ enum qxl_mode { #define QXL_PAGE_BITS 12 #define QXL_PAGE_SIZE (1 << QXL_PAGE_BITS); -typedef struct PCIQXLDevice { +struct PCIQXLDevice { PCIDevice pci; PortioList vga_port_list; SimpleSpiceDisplay ssd; @@ -126,10 +127,10 @@ typedef struct PCIQXLDevice { int num_dirty_rects; QXLRect dirty[QXL_NUM_DIRTY_RECTS]; QEMUBH *update_area_bh; -} PCIQXLDevice; +}; #define TYPE_PCI_QXL "pci-qxl" -#define PCI_QXL(obj) OBJECT_CHECK(PCIQXLDevice, (obj), TYPE_PCI_QXL) +OBJECT_DECLARE_SIMPLE_TYPE(PCIQXLDevice, PCI_QXL) #define PANIC_ON(x) if ((x)) { \ printf("%s: PANIC %s failed\n", __func__, #x); \ diff --git a/hw/display/ramfb-standalone.c b/hw/display/ramfb-standalone.c index b18db97eeb1b0728d20606881f6754abe63e7231..8c0094397f5b384df94cafa87cc854d4353e19f4 100644 --- a/hw/display/ramfb-standalone.c +++ b/hw/display/ramfb-standalone.c @@ -5,14 +5,17 @@ #include "hw/qdev-properties.h" #include "hw/display/ramfb.h" #include "ui/console.h" +#include "qom/object.h" -#define RAMFB(obj) OBJECT_CHECK(RAMFBStandaloneState, (obj), TYPE_RAMFB_DEVICE) +typedef struct RAMFBStandaloneState RAMFBStandaloneState; +DECLARE_INSTANCE_CHECKER(RAMFBStandaloneState, RAMFB, + TYPE_RAMFB_DEVICE) -typedef struct RAMFBStandaloneState { +struct RAMFBStandaloneState { SysBusDevice parent_obj; QemuConsole *con; RAMFBState *state; -} RAMFBStandaloneState; +}; static void display_update_wrapper(void *dev) { diff --git a/hw/display/sii9022.c b/hw/display/sii9022.c index 0710ce9de5a3247cc88b28427b9939057f5f4085..b591a5878901e6ea91637c5bba85ef679b72970e 100644 --- a/hw/display/sii9022.c +++ b/hw/display/sii9022.c @@ -19,6 +19,7 @@ #include "migration/vmstate.h" #include "hw/display/i2c-ddc.h" #include "trace.h" +#include "qom/object.h" #define SII9022_SYS_CTRL_DATA 0x1a #define SII9022_SYS_CTRL_PWR_DWN 0x10 @@ -35,16 +36,16 @@ #define SII9022_INT_STATUS_PLUGGED 0x04; #define TYPE_SII9022 "sii9022" -#define SII9022(obj) OBJECT_CHECK(sii9022_state, (obj), TYPE_SII9022) +OBJECT_DECLARE_SIMPLE_TYPE(sii9022_state, SII9022) -typedef struct sii9022_state { +struct sii9022_state { I2CSlave parent_obj; uint8_t ptr; bool addr_byte; bool ddc_req; bool ddc_skip_finish; bool ddc; -} sii9022_state; +}; static const VMStateDescription vmstate_sii9022 = { .name = "sii9022", @@ -161,7 +162,7 @@ static void sii9022_realize(DeviceState *dev, Error **errp) I2CBus *bus; bus = I2C_BUS(qdev_get_parent_bus(dev)); - i2c_create_slave(bus, TYPE_I2CDDC, 0x50); + i2c_slave_create_simple(bus, TYPE_I2CDDC, 0x50); } static void sii9022_class_init(ObjectClass *klass, void *data) diff --git a/hw/display/sm501.c b/hw/display/sm501.c index acc692531ac7673eb9eceb974c9f3e2ddafe67bb..8966b69bc735b25a78d0e5ffdf38aa94a7e9eedd 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -2,7 +2,7 @@ * QEMU SM501 Device * * Copyright (c) 2008 Shin-ichiro KAWASAKI - * Copyright (c) 2016 BALATON Zoltan + * Copyright (c) 2016-2020 BALATON Zoltan * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,32 +39,8 @@ #include "qemu/range.h" #include "ui/pixel_ops.h" #include "qemu/bswap.h" - -/* - * Status: 2010/05/07 - * - Minimum implementation for Linux console : mmio regs and CRT layer. - * - 2D graphics acceleration partially supported : only fill rectangle. - * - * Status: 2016/12/04 - * - Misc fixes: endianness, hardware cursor - * - Panel support - * - * TODO: - * - Touch panel support - * - USB support - * - UART support - * - More 2D graphics engine support - * - Performance tuning - */ - -/*#define DEBUG_SM501*/ -/*#define DEBUG_BITBLT*/ - -#ifdef DEBUG_SM501 -#define SM501_DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else -#define SM501_DPRINTF(fmt, ...) do {} while (0) -#endif +#include "trace.h" +#include "qom/object.h" #define MMIO_BASE_OFFSET 0x3e00000 #define MMIO_SIZE 0x200000 @@ -699,139 +675,190 @@ static inline void hwc_invalidate(SM501State *s, int crt) static void sm501_2d_operation(SM501State *s) { - /* obtain operation parameters */ - int operation = (s->twoD_control >> 16) & 0x1f; - int rtl = s->twoD_control & 0x8000000; - int src_x = (s->twoD_source >> 16) & 0x01FFF; - int src_y = s->twoD_source & 0xFFFF; - int dst_x = (s->twoD_destination >> 16) & 0x01FFF; - int dst_y = s->twoD_destination & 0xFFFF; - int operation_width = (s->twoD_dimension >> 16) & 0x1FFF; - int operation_height = s->twoD_dimension & 0xFFFF; - uint32_t color = s->twoD_foreground; - int format_flags = (s->twoD_stretch >> 20) & 0x3; - int addressing = (s->twoD_stretch >> 16) & 0xF; - int rop_mode = (s->twoD_control >> 15) & 0x1; /* 1 for rop2, else rop3 */ + int cmd = (s->twoD_control >> 16) & 0x1F; + int rtl = s->twoD_control & BIT(27); + int format = (s->twoD_stretch >> 20) & 3; + int bypp = 1 << format; /* bytes per pixel */ + int rop_mode = (s->twoD_control >> 15) & 1; /* 1 for rop2, else rop3 */ /* 1 if rop2 source is the pattern, otherwise the source is the bitmap */ - int rop2_source_is_pattern = (s->twoD_control >> 14) & 0x1; + int rop2_source_is_pattern = (s->twoD_control >> 14) & 1; int rop = s->twoD_control & 0xFF; - uint32_t src_base = s->twoD_source_base & 0x03FFFFFF; + unsigned int dst_x = (s->twoD_destination >> 16) & 0x01FFF; + unsigned int dst_y = s->twoD_destination & 0xFFFF; + unsigned int width = (s->twoD_dimension >> 16) & 0x1FFF; + unsigned int height = s->twoD_dimension & 0xFFFF; uint32_t dst_base = s->twoD_destination_base & 0x03FFFFFF; - - /* get frame buffer info */ - uint8_t *src = s->local_mem + src_base; - uint8_t *dst = s->local_mem + dst_base; - int src_width = s->twoD_pitch & 0x1FFF; - int dst_width = (s->twoD_pitch >> 16) & 0x1FFF; + unsigned int dst_pitch = (s->twoD_pitch >> 16) & 0x1FFF; int crt = (s->dc_crt_control & SM501_DC_CRT_CONTROL_SEL) ? 1 : 0; int fb_len = get_width(s, crt) * get_height(s, crt) * get_bpp(s, crt); + bool overlap = false; - if (addressing != 0x0) { - printf("%s: only XY addressing is supported.\n", __func__); - abort(); + if ((s->twoD_stretch >> 16) & 0xF) { + qemu_log_mask(LOG_UNIMP, "sm501: only XY addressing is supported.\n"); + return; } - if (rop_mode == 0) { - if (rop != 0xcc) { - /* Anything other than plain copies are not supported */ - qemu_log_mask(LOG_UNIMP, "sm501: rop3 mode with rop %x is not " - "supported.\n", rop); - } - } else { - if (rop2_source_is_pattern && rop != 0x5) { - /* For pattern source, we support only inverse dest */ - qemu_log_mask(LOG_UNIMP, "sm501: rop2 source being the pattern and " - "rop %x is not supported.\n", rop); - } else { - if (rop != 0x5 && rop != 0xc) { - /* Anything other than plain copies or inverse dest is not - * supported */ - qemu_log_mask(LOG_UNIMP, "sm501: rop mode %x is not " - "supported.\n", rop); - } - } + if (s->twoD_source_base & BIT(27) || s->twoD_destination_base & BIT(27)) { + qemu_log_mask(LOG_UNIMP, "sm501: only local memory is supported.\n"); + return; } - if ((s->twoD_source_base & 0x08000000) || - (s->twoD_destination_base & 0x08000000)) { - printf("%s: only local memory is supported.\n", __func__); - abort(); + if (!dst_pitch) { + qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero dest pitch.\n"); + return; } - switch (operation) { - case 0x00: /* copy area */ -#define COPY_AREA(_bpp, _pixel_type, rtl) { \ - int y, x, index_d, index_s; \ - for (y = 0; y < operation_height; y++) { \ - for (x = 0; x < operation_width; x++) { \ - _pixel_type val; \ - \ - if (rtl) { \ - index_s = ((src_y - y) * src_width + src_x - x) * _bpp; \ - index_d = ((dst_y - y) * dst_width + dst_x - x) * _bpp; \ - } else { \ - index_s = ((src_y + y) * src_width + src_x + x) * _bpp; \ - index_d = ((dst_y + y) * dst_width + dst_x + x) * _bpp; \ - } \ - if (rop_mode == 1 && rop == 5) { \ - /* Invert dest */ \ - val = ~*(_pixel_type *)&dst[index_d]; \ - } else { \ - val = *(_pixel_type *)&src[index_s]; \ - } \ - *(_pixel_type *)&dst[index_d] = val; \ - } \ - } \ + if (!width || !height) { + qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero size 2D op.\n"); + return; } - switch (format_flags) { - case 0: - COPY_AREA(1, uint8_t, rtl); - break; - case 1: - COPY_AREA(2, uint16_t, rtl); - break; - case 2: - COPY_AREA(4, uint32_t, rtl); - break; + + if (rtl) { + dst_x -= width - 1; + dst_y -= height - 1; + } + + if (dst_base >= get_local_mem_size(s) || + dst_base + (dst_x + width + (dst_y + height) * dst_pitch) * bypp >= + get_local_mem_size(s)) { + qemu_log_mask(LOG_GUEST_ERROR, "sm501: 2D op dest is outside vram.\n"); + return; + } + + switch (cmd) { + case 0: /* BitBlt */ + { + static uint32_t tmp_buf[16384]; + unsigned int src_x = (s->twoD_source >> 16) & 0x01FFF; + unsigned int src_y = s->twoD_source & 0xFFFF; + uint32_t src_base = s->twoD_source_base & 0x03FFFFFF; + unsigned int src_pitch = s->twoD_pitch & 0x1FFF; + + if (!src_pitch) { + qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero src pitch.\n"); + return; } - break; - case 0x01: /* fill rectangle */ -#define FILL_RECT(_bpp, _pixel_type) { \ - int y, x; \ - for (y = 0; y < operation_height; y++) { \ - for (x = 0; x < operation_width; x++) { \ - int index = ((dst_y + y) * dst_width + dst_x + x) * _bpp; \ - *(_pixel_type *)&dst[index] = (_pixel_type)color; \ - } \ - } \ + if (rtl) { + src_x -= width - 1; + src_y -= height - 1; + } + + if (src_base >= get_local_mem_size(s) || + src_base + (src_x + width + (src_y + height) * src_pitch) * bypp >= + get_local_mem_size(s)) { + qemu_log_mask(LOG_GUEST_ERROR, + "sm501: 2D op src is outside vram.\n"); + return; + } + + if ((rop_mode && rop == 0x5) || (!rop_mode && rop == 0x55)) { + /* Invert dest, is there a way to do this with pixman? */ + unsigned int x, y, i; + uint8_t *d = s->local_mem + dst_base; + + for (y = 0; y < height; y++) { + i = (dst_x + (dst_y + y) * dst_pitch) * bypp; + for (x = 0; x < width; x++, i += bypp) { + stn_he_p(&d[i], bypp, ~ldn_he_p(&d[i], bypp)); + } + } + } else { + /* Do copy src for unimplemented ops, better than unpainted area */ + if ((rop_mode && (rop != 0xc || rop2_source_is_pattern)) || + (!rop_mode && rop != 0xcc)) { + qemu_log_mask(LOG_UNIMP, + "sm501: rop%d op %x%s not implemented\n", + (rop_mode ? 2 : 3), rop, + (rop2_source_is_pattern ? + " with pattern source" : "")); + } + /* Ignore no-op blits, some guests seem to do this */ + if (src_base == dst_base && src_pitch == dst_pitch && + src_x == dst_x && src_y == dst_y) { + break; + } + /* Some clients also do 1 pixel blits, avoid overhead for these */ + if (width == 1 && height == 1) { + unsigned int si = (src_x + src_y * src_pitch) * bypp; + unsigned int di = (dst_x + dst_y * dst_pitch) * bypp; + stn_he_p(&s->local_mem[dst_base + di], bypp, + ldn_he_p(&s->local_mem[src_base + si], bypp)); + break; + } + /* If reverse blit do simple check for overlaps */ + if (rtl && src_base == dst_base && src_pitch == dst_pitch) { + overlap = (src_x < dst_x + width && src_x + width > dst_x && + src_y < dst_y + height && src_y + height > dst_y); + } else if (rtl) { + unsigned int sb, se, db, de; + sb = src_base + (src_x + src_y * src_pitch) * bypp; + se = sb + (width + (height - 1) * src_pitch) * bypp; + db = dst_base + (dst_x + dst_y * dst_pitch) * bypp; + de = db + (width + (height - 1) * dst_pitch) * bypp; + overlap = (db < se && sb < de); + } + if (overlap) { + /* pixman can't do reverse blit: copy via temporary */ + int tmp_stride = DIV_ROUND_UP(width * bypp, sizeof(uint32_t)); + uint32_t *tmp = tmp_buf; + + if (tmp_stride * sizeof(uint32_t) * height > sizeof(tmp_buf)) { + tmp = g_malloc(tmp_stride * sizeof(uint32_t) * height); + } + pixman_blt((uint32_t *)&s->local_mem[src_base], tmp, + src_pitch * bypp / sizeof(uint32_t), + tmp_stride, 8 * bypp, 8 * bypp, + src_x, src_y, 0, 0, width, height); + pixman_blt(tmp, (uint32_t *)&s->local_mem[dst_base], + tmp_stride, + dst_pitch * bypp / sizeof(uint32_t), + 8 * bypp, 8 * bypp, + 0, 0, dst_x, dst_y, width, height); + if (tmp != tmp_buf) { + g_free(tmp); + } + } else { + pixman_blt((uint32_t *)&s->local_mem[src_base], + (uint32_t *)&s->local_mem[dst_base], + src_pitch * bypp / sizeof(uint32_t), + dst_pitch * bypp / sizeof(uint32_t), + 8 * bypp, 8 * bypp, + src_x, src_y, dst_x, dst_y, width, height); + } + } + break; } + case 1: /* Rectangle Fill */ + { + uint32_t color = s->twoD_foreground; - switch (format_flags) { - case 0: - FILL_RECT(1, uint8_t); - break; - case 1: - color = cpu_to_le16(color); - FILL_RECT(2, uint16_t); - break; - case 2: + if (format == 2) { color = cpu_to_le32(color); - FILL_RECT(4, uint32_t); - break; + } else if (format == 1) { + color = cpu_to_le16(color); } - break; - default: - printf("non-implemented SM501 2D operation. %d\n", operation); - abort(); + if (width == 1 && height == 1) { + unsigned int i = (dst_x + dst_y * dst_pitch) * bypp; + stn_he_p(&s->local_mem[dst_base + i], bypp, color); + } else { + pixman_fill((uint32_t *)&s->local_mem[dst_base], + dst_pitch * bypp / sizeof(uint32_t), + 8 * bypp, dst_x, dst_y, width, height, color); + } break; } + default: + qemu_log_mask(LOG_UNIMP, "sm501: not implemented 2D operation: %d\n", + cmd); + return; + } if (dst_base >= get_fb_addr(s, crt) && dst_base <= get_fb_addr(s, crt) + fb_len) { - int dst_len = MIN(fb_len, ((dst_y + operation_height - 1) * dst_width + - dst_x + operation_width) * (1 << format_flags)); + int dst_len = MIN(fb_len, ((dst_y + height - 1) * dst_pitch + + dst_x + width) * bypp); if (dst_len) { memory_region_set_dirty(&s->local_mem_region, dst_base, dst_len); } @@ -843,7 +870,6 @@ static uint64_t sm501_system_config_read(void *opaque, hwaddr addr, { SM501State *s = (SM501State *)opaque; uint32_t ret = 0; - SM501_DPRINTF("sm501 system config regs : read addr=%x\n", (int)addr); switch (addr) { case SM501_SYSTEM_CONTROL: @@ -892,11 +918,10 @@ static uint64_t sm501_system_config_read(void *opaque, hwaddr addr, break; default: - printf("sm501 system config : not implemented register read." - " addr=%x\n", (int)addr); - abort(); + qemu_log_mask(LOG_UNIMP, "sm501: not implemented system config" + "register read. addr=%" HWADDR_PRIx "\n", addr); } - + trace_sm501_system_config_read(addr, ret); return ret; } @@ -904,9 +929,8 @@ static void sm501_system_config_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { SM501State *s = (SM501State *)opaque; - SM501_DPRINTF("sm501 system config regs : write addr=%x, val=%x\n", - (uint32_t)addr, (uint32_t)value); + trace_sm501_system_config_write((uint32_t)addr, (uint32_t)value); switch (addr) { case SM501_SYSTEM_CONTROL: s->system_control &= 0x10DB0000; @@ -948,15 +972,15 @@ static void sm501_system_config_write(void *opaque, hwaddr addr, break; case SM501_ENDIAN_CONTROL: if (value & 0x00000001) { - printf("sm501 system config : big endian mode not implemented.\n"); - abort(); + qemu_log_mask(LOG_UNIMP, "sm501: system config big endian mode not" + " implemented.\n"); } break; default: - printf("sm501 system config : not implemented register write." - " addr=%x, val=%x\n", (int)addr, (uint32_t)value); - abort(); + qemu_log_mask(LOG_UNIMP, "sm501: not implemented system config" + "register write. addr=%" HWADDR_PRIx + ", val=%" PRIx64 "\n", addr, value); } } @@ -992,9 +1016,7 @@ static uint64_t sm501_i2c_read(void *opaque, hwaddr addr, unsigned size) qemu_log_mask(LOG_UNIMP, "sm501 i2c : not implemented register read." " addr=0x%" HWADDR_PRIx "\n", addr); } - - SM501_DPRINTF("sm501 i2c regs : read addr=%" HWADDR_PRIx " val=%x\n", - addr, ret); + trace_sm501_i2c_read((uint32_t)addr, ret); return ret; } @@ -1002,9 +1024,8 @@ static void sm501_i2c_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { SM501State *s = (SM501State *)opaque; - SM501_DPRINTF("sm501 i2c regs : write addr=%" HWADDR_PRIx - " val=%" PRIx64 "\n", addr, value); + trace_sm501_i2c_write((uint32_t)addr, (uint32_t)value); switch (addr) { case SM501_I2C_BYTE_COUNT: s->i2c_byte_count = value & 0xf; @@ -1018,25 +1039,19 @@ static void sm501_i2c_write(void *opaque, hwaddr addr, uint64_t value, s->i2c_status |= (res ? SM501_I2C_STATUS_ERROR : 0); if (!res) { int i; - SM501_DPRINTF("sm501 i2c : transferring %d bytes to 0x%x\n", - s->i2c_byte_count + 1, s->i2c_addr >> 1); for (i = 0; i <= s->i2c_byte_count; i++) { res = i2c_send_recv(s->i2c_bus, &s->i2c_data[i], !(s->i2c_addr & 1)); if (res) { - SM501_DPRINTF("sm501 i2c : transfer failed" - " i=%d, res=%d\n", i, res); s->i2c_status |= SM501_I2C_STATUS_ERROR; return; } } if (i) { - SM501_DPRINTF("sm501 i2c : transferred %d bytes\n", i); s->i2c_status = SM501_I2C_STATUS_COMPLETE; } } } else { - SM501_DPRINTF("sm501 i2c : end transfer\n"); i2c_end_transfer(s->i2c_bus); s->i2c_status &= ~SM501_I2C_STATUS_ERROR; } @@ -1076,7 +1091,8 @@ static const MemoryRegionOps sm501_i2c_ops = { static uint32_t sm501_palette_read(void *opaque, hwaddr addr) { SM501State *s = (SM501State *)opaque; - SM501_DPRINTF("sm501 palette read addr=%x\n", (int)addr); + + trace_sm501_palette_read((uint32_t)addr); /* TODO : consider BYTE/WORD access */ /* TODO : consider endian */ @@ -1089,8 +1105,8 @@ static void sm501_palette_write(void *opaque, hwaddr addr, uint32_t value) { SM501State *s = (SM501State *)opaque; - SM501_DPRINTF("sm501 palette write addr=%x, val=%x\n", - (int)addr, value); + + trace_sm501_palette_write((uint32_t)addr, value); /* TODO : consider BYTE/WORD access */ /* TODO : consider endian */ @@ -1105,7 +1121,6 @@ static uint64_t sm501_disp_ctrl_read(void *opaque, hwaddr addr, { SM501State *s = (SM501State *)opaque; uint32_t ret = 0; - SM501_DPRINTF("sm501 disp ctrl regs : read addr=%x\n", (int)addr); switch (addr) { @@ -1207,11 +1222,10 @@ static uint64_t sm501_disp_ctrl_read(void *opaque, hwaddr addr, break; default: - printf("sm501 disp ctrl : not implemented register read." - " addr=%x\n", (int)addr); - abort(); + qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register " + "read. addr=%" HWADDR_PRIx "\n", addr); } - + trace_sm501_disp_ctrl_read((uint32_t)addr, ret); return ret; } @@ -1219,9 +1233,8 @@ static void sm501_disp_ctrl_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { SM501State *s = (SM501State *)opaque; - SM501_DPRINTF("sm501 disp ctrl regs : write addr=%x, val=%x\n", - (unsigned)addr, (unsigned)value); + trace_sm501_disp_ctrl_write((uint32_t)addr, (uint32_t)value); switch (addr) { case SM501_DC_PANEL_CONTROL: s->dc_panel_control = value & 0x0FFF73FF; @@ -1345,9 +1358,9 @@ static void sm501_disp_ctrl_write(void *opaque, hwaddr addr, break; default: - printf("sm501 disp ctrl : not implemented register write." - " addr=%x, val=%x\n", (int)addr, (unsigned)value); - abort(); + qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register " + "write. addr=%" HWADDR_PRIx + ", val=%" PRIx64 "\n", addr, value); } } @@ -1366,7 +1379,6 @@ static uint64_t sm501_2d_engine_read(void *opaque, hwaddr addr, { SM501State *s = (SM501State *)opaque; uint32_t ret = 0; - SM501_DPRINTF("sm501 2d engine regs : read addr=%x\n", (int)addr); switch (addr) { case SM501_2D_SOURCE: @@ -1433,11 +1445,10 @@ static uint64_t sm501_2d_engine_read(void *opaque, hwaddr addr, ret = 0; /* Should return interrupt status */ break; default: - printf("sm501 disp ctrl : not implemented register read." - " addr=%x\n", (int)addr); - abort(); + qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register " + "read. addr=%" HWADDR_PRIx "\n", addr); } - + trace_sm501_2d_engine_read((uint32_t)addr, ret); return ret; } @@ -1445,9 +1456,8 @@ static void sm501_2d_engine_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { SM501State *s = (SM501State *)opaque; - SM501_DPRINTF("sm501 2d engine regs : write addr=%x, val=%x\n", - (unsigned)addr, (unsigned)value); + trace_sm501_2d_engine_write((uint32_t)addr, (uint32_t)value); switch (addr) { case SM501_2D_SOURCE: s->twoD_source = value; @@ -1478,6 +1488,9 @@ static void sm501_2d_engine_write(void *opaque, hwaddr addr, s->twoD_background = value; break; case SM501_2D_STRETCH: + if (((value >> 20) & 3) == 3) { + value &= ~BIT(20); + } s->twoD_stretch = value; break; case SM501_2D_COLOR_COMPARE: @@ -1520,9 +1533,9 @@ static void sm501_2d_engine_write(void *opaque, hwaddr addr, /* ignored, writing 0 should clear interrupt status */ break; default: - printf("sm501 2d engine : not implemented register write." - " addr=%x, val=%x\n", (int)addr, (unsigned)value); - abort(); + qemu_log_mask(LOG_UNIMP, "sm501: not implemented 2d engine register " + "write. addr=%" HWADDR_PRIx + ", val=%" PRIx64 "\n", addr, value); } } @@ -1670,9 +1683,9 @@ static void sm501_update_display(void *opaque) draw_line = draw_line32_funcs[dst_depth_index]; break; default: - printf("sm501 update display : invalid control register value.\n"); - abort(); - break; + qemu_log_mask(LOG_GUEST_ERROR, "sm501: update display" + "invalid control register value.\n"); + return; } /* set up to draw hardware cursor */ @@ -1802,8 +1815,6 @@ static void sm501_init(SM501State *s, DeviceState *dev, uint32_t local_mem_bytes) { s->local_mem_size_index = get_local_mem_size_index(local_mem_bytes); - SM501_DPRINTF("sm501 local mem size=%x. index=%d\n", get_local_mem_size(s), - s->local_mem_size_index); /* local memory */ memory_region_init_ram(&s->local_mem_region, OBJECT(dev), "sm501.local", @@ -1814,8 +1825,9 @@ static void sm501_init(SM501State *s, DeviceState *dev, /* i2c */ s->i2c_bus = i2c_init_bus(dev, "sm501.i2c"); /* ddc */ - I2CDDCState *ddc = I2CDDC(qdev_create(BUS(s->i2c_bus), TYPE_I2CDDC)); + I2CDDCState *ddc = I2CDDC(qdev_new(TYPE_I2CDDC)); i2c_set_slave_address(I2C_SLAVE(ddc), 0x50); + qdev_realize_and_unref(DEVICE(ddc), BUS(s->i2c_bus), &error_abort); /* mmio */ memory_region_init(&s->mmio_region, OBJECT(dev), "sm501.mmio", MMIO_SIZE); @@ -1920,10 +1932,9 @@ static const VMStateDescription vmstate_sm501_state = { }; #define TYPE_SYSBUS_SM501 "sysbus-sm501" -#define SYSBUS_SM501(obj) \ - OBJECT_CHECK(SM501SysBusState, (obj), TYPE_SYSBUS_SM501) +OBJECT_DECLARE_SIMPLE_TYPE(SM501SysBusState, SYSBUS_SM501) -typedef struct { +struct SM501SysBusState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -1931,7 +1942,7 @@ typedef struct { uint32_t vram_size; uint32_t base; SerialMM serial; -} SM501SysBusState; +}; static void sm501_realize_sysbus(DeviceState *dev, Error **errp) { @@ -1950,16 +1961,16 @@ static void sm501_realize_sysbus(DeviceState *dev, Error **errp) sysbus_init_mmio(sbd, &s->state.mmio_region); /* bridge to usb host emulation module */ - usb_dev = qdev_create(NULL, "sysbus-ohci"); + usb_dev = qdev_new("sysbus-ohci"); qdev_prop_set_uint32(usb_dev, "num-ports", 2); qdev_prop_set_uint64(usb_dev, "dma-offset", s->base); - qdev_init_nofail(usb_dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(usb_dev), &error_fatal); memory_region_add_subregion(&s->state.mmio_region, SM501_USB_HOST, sysbus_mmio_get_region(SYS_BUS_DEVICE(usb_dev), 0)); sysbus_pass_irq(sbd, SYS_BUS_DEVICE(usb_dev)); /* bridge to serial emulation module */ - qdev_init_nofail(DEVICE(&s->serial)); + sysbus_realize(SYS_BUS_DEVICE(&s->serial), &error_fatal); mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->serial), 0); memory_region_add_subregion(&s->state.mmio_region, SM501_UART0, mr); /* TODO : chain irq to IRL */ @@ -2005,7 +2016,7 @@ static void sm501_sysbus_init(Object *o) SM501SysBusState *sm501 = SYSBUS_SM501(o); SerialMM *smm = &sm501->serial; - sysbus_init_child_obj(o, "serial", smm, sizeof(SerialMM), TYPE_SERIAL_MM); + object_initialize_child(o, "serial", smm, TYPE_SERIAL_MM); qdev_set_legacy_instance_id(DEVICE(smm), SM501_UART0, 2); qdev_prop_set_uint8(DEVICE(smm), "regshift", 2); qdev_prop_set_uint8(DEVICE(smm), "endianness", DEVICE_LITTLE_ENDIAN); @@ -2023,15 +2034,15 @@ static const TypeInfo sm501_sysbus_info = { }; #define TYPE_PCI_SM501 "sm501" -#define PCI_SM501(obj) OBJECT_CHECK(SM501PCIState, (obj), TYPE_PCI_SM501) +OBJECT_DECLARE_SIMPLE_TYPE(SM501PCIState, PCI_SM501) -typedef struct { +struct SM501PCIState { /*< private >*/ PCIDevice parent_obj; /*< public >*/ SM501State state; uint32_t vram_size; -} SM501PCIState; +}; static void sm501_realize_pci(PCIDevice *dev, Error **errp) { diff --git a/hw/display/ssd0303.c b/hw/display/ssd0303.c index 718378f6deca9f10f2e25ba67432b9f4dfaaeb75..aeae22da9c299d39019ea453a8071b69654e3985 100644 --- a/hw/display/ssd0303.c +++ b/hw/display/ssd0303.c @@ -16,6 +16,7 @@ #include "migration/vmstate.h" #include "qemu/module.h" #include "ui/console.h" +#include "qom/object.h" //#define DEBUG_SSD0303 1 @@ -46,9 +47,9 @@ enum ssd0303_cmd { }; #define TYPE_SSD0303 "ssd0303" -#define SSD0303(obj) OBJECT_CHECK(ssd0303_state, (obj), TYPE_SSD0303) +OBJECT_DECLARE_SIMPLE_TYPE(ssd0303_state, SSD0303) -typedef struct { +struct ssd0303_state { I2CSlave parent_obj; QemuConsole *con; @@ -63,7 +64,7 @@ typedef struct { enum ssd0303_mode mode; enum ssd0303_cmd cmd_state; uint8_t framebuffer[132*8]; -} ssd0303_state; +}; static uint8_t ssd0303_recv(I2CSlave *i2c) { diff --git a/hw/display/ssd0323.c b/hw/display/ssd0323.c index c3bdb18742c991234cf2d17b558614c74bccb7db..cbfd21dfd56a8f471cd05f4eb57937cc9b3d5192 100644 --- a/hw/display/ssd0323.c +++ b/hw/display/ssd0323.c @@ -16,6 +16,7 @@ #include "migration/vmstate.h" #include "qemu/module.h" #include "ui/console.h" +#include "qom/object.h" //#define DEBUG_SSD0323 1 @@ -47,7 +48,7 @@ enum ssd0323_mode SSD0323_DATA }; -typedef struct { +struct ssd0323_state { SSISlave ssidev; QemuConsole *con; @@ -64,11 +65,15 @@ typedef struct { int32_t remap; uint32_t mode; uint8_t framebuffer[128 * 80 / 2]; -} ssd0323_state; +}; + +#define TYPE_SSD0323 "ssd0323" +OBJECT_DECLARE_SIMPLE_TYPE(ssd0323_state, SSD0323) + static uint32_t ssd0323_transfer(SSISlave *dev, uint32_t data) { - ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, dev); + ssd0323_state *s = SSD0323(dev); switch (s->mode) { case SSD0323_DATA: @@ -346,7 +351,7 @@ static const GraphicHwOps ssd0323_ops = { static void ssd0323_realize(SSISlave *d, Error **errp) { DeviceState *dev = DEVICE(d); - ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, d); + ssd0323_state *s = SSD0323(d); s->col_end = 63; s->row_end = 79; @@ -365,10 +370,11 @@ static void ssd0323_class_init(ObjectClass *klass, void *data) k->transfer = ssd0323_transfer; k->cs_polarity = SSI_CS_HIGH; dc->vmsd = &vmstate_ssd0323; + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); } static const TypeInfo ssd0323_info = { - .name = "ssd0323", + .name = TYPE_SSD0323, .parent = TYPE_SSI_SLAVE, .instance_size = sizeof(ssd0323_state), .class_init = ssd0323_class_init, diff --git a/hw/display/tcx.c b/hw/display/tcx.c index 1fb45b1aab857db27226a5071ccf6672a75d56eb..3799d29b75923d7bc6314fc3499d74be3f85d9a1 100644 --- a/hw/display/tcx.c +++ b/hw/display/tcx.c @@ -33,6 +33,7 @@ #include "migration/vmstate.h" #include "qemu/error-report.h" #include "qemu/module.h" +#include "qom/object.h" #define TCX_ROM_FILE "QEMU,tcx.bin" #define FCODE_MAX_ROM_SIZE 0x10000 @@ -55,9 +56,9 @@ #define TCX_THC_CURSBITS 0x980 #define TYPE_TCX "SUNW,tcx" -#define TCX(obj) OBJECT_CHECK(TCXState, (obj), TYPE_TCX) +OBJECT_DECLARE_SIMPLE_TYPE(TCXState, TCX) -typedef struct TCXState { +struct TCXState { SysBusDevice parent_obj; QemuConsole *con; @@ -93,7 +94,7 @@ typedef struct TCXState { uint32_t cursbits[32]; uint16_t cursx; uint16_t cursy; -} TCXState; +}; static void tcx_set_dirty(TCXState *s, ram_addr_t addr, int len) { @@ -548,20 +549,28 @@ static const MemoryRegionOps tcx_stip_ops = { .read = tcx_stip_readl, .write = tcx_stip_writel, .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { + .impl = { .min_access_size = 4, .max_access_size = 4, }, + .valid = { + .min_access_size = 4, + .max_access_size = 8, + }, }; static const MemoryRegionOps tcx_rstip_ops = { .read = tcx_stip_readl, .write = tcx_rstip_writel, .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { + .impl = { .min_access_size = 4, .max_access_size = 4, }, + .valid = { + .min_access_size = 4, + .max_access_size = 8, + }, }; static uint64_t tcx_blit_readl(void *opaque, hwaddr addr, @@ -640,20 +649,28 @@ static const MemoryRegionOps tcx_blit_ops = { .read = tcx_blit_readl, .write = tcx_blit_writel, .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { + .impl = { .min_access_size = 4, .max_access_size = 4, }, + .valid = { + .min_access_size = 4, + .max_access_size = 8, + }, }; static const MemoryRegionOps tcx_rblit_ops = { .read = tcx_blit_readl, .write = tcx_rblit_writel, .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { + .impl = { .min_access_size = 4, .max_access_size = 4, }, + .valid = { + .min_access_size = 4, + .max_access_size = 8, + }, }; static void tcx_invalidate_cursor_position(TCXState *s) diff --git a/hw/display/trace-events b/hw/display/trace-events index e6e22bef889935ce1e7ae3384cdde5f8ede30057..957b8ba99436ef42138792fe0fa1beec13dc5840 100644 --- a/hw/display/trace-events +++ b/hw/display/trace-events @@ -32,9 +32,11 @@ vmware_scratch_read(uint32_t index, uint32_t value) "index %d, value 0x%x" vmware_scratch_write(uint32_t index, uint32_t value) "index %d, value 0x%x" vmware_setmode(uint32_t w, uint32_t h, uint32_t bpp) "%dx%d @ %d bpp" +# virtio-gpu-base.c +virtio_gpu_features(bool virgl) "virgl %d" + # virtio-gpu-3d.c # virtio-gpu.c -virtio_gpu_features(bool virgl) "virgl %d" virtio_gpu_cmd_get_display_info(void) "" virtio_gpu_cmd_get_edid(uint32_t scanout) "scanout %d" virtio_gpu_cmd_set_scanout(uint32_t id, uint32_t res, uint32_t w, uint32_t h, uint32_t x, uint32_t y) "id %d, res 0x%x, w %d, h %d, x %d, y %d" @@ -133,6 +135,8 @@ vga_vbe_write(uint32_t index, uint32_t val) "index 0x%x, val 0x%x" vga_cirrus_read_io(uint32_t addr, uint32_t val) "addr 0x%x, val 0x%x" vga_cirrus_write_io(uint32_t addr, uint32_t val) "addr 0x%x, val 0x%x" vga_cirrus_write_blt(uint32_t offset, uint32_t val) "offset 0x%x, val 0x%x" +vga_cirrus_write_gr(uint8_t index, uint8_t val) "GR addr 0x%02x, val 0x%02x" +vga_cirrus_bitblt_start(uint8_t blt_rop, uint8_t blt_mode, uint8_t blt_modeext, int blt_width, int blt_height, int blt_dstpitch, int blt_srcpitch, uint32_t blt_dstaddr, uint32_t blt_srcaddr, uint8_t gr_val) "rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spitch=%d daddr=0x%08"PRIx32" saddr=0x%08"PRIx32" writemask=0x%02x" # sii9022.c sii9022_read_reg(uint8_t addr, uint8_t val) "addr 0x%02x, val 0x%02x" @@ -151,3 +155,23 @@ artist_vram_write(unsigned int size, uint64_t addr, uint64_t val) "%u 0x%"PRIx64 artist_fill_window(unsigned int start_x, unsigned int start_y, unsigned int width, unsigned int height, uint32_t op, uint32_t ctlpln) "start=%ux%u length=%ux%u op=0x%08x ctlpln=0x%08x" artist_block_move(unsigned int start_x, unsigned int start_y, unsigned int dest_x, unsigned int dest_y, unsigned int width, unsigned int height) "source %ux%u -> dest %ux%u size %ux%u" artist_draw_line(unsigned int start_x, unsigned int start_y, unsigned int end_x, unsigned int end_y) "%ux%u %ux%u" + +# cg3.c +cg3_read(uint32_t addr, uint32_t val, unsigned size) "read addr:0x%06"PRIx32" val:0x%08"PRIx32" size:%u" +cg3_write(uint32_t addr, uint32_t val, unsigned size) "write addr:0x%06"PRIx32" val:0x%08"PRIx32" size:%u" + +# dpcd.c +dpcd_read(uint32_t addr, uint8_t val) "read addr:0x%"PRIx32" val:0x%02x" +dpcd_write(uint32_t addr, uint8_t val) "write addr:0x%"PRIx32" val:0x%02x" + +# sm501.c +sm501_system_config_read(uint32_t addr, uint32_t val) "addr=0x%x, val=0x%x" +sm501_system_config_write(uint32_t addr, uint32_t val) "addr=0x%x, val=0x%x" +sm501_i2c_read(uint32_t addr, uint8_t val) "addr=0x%x, val=0x%x" +sm501_i2c_write(uint32_t addr, uint32_t val) "addr=0x%x, val=0x%x" +sm501_palette_read(uint32_t addr) "addr=0x%x" +sm501_palette_write(uint32_t addr, uint32_t val) "addr=0x%x, val=0x%x" +sm501_disp_ctrl_read(uint32_t addr, uint32_t val) "addr=0x%x, val=0x%x" +sm501_disp_ctrl_write(uint32_t addr, uint32_t val) "addr=0x%x, val=0x%x" +sm501_2d_engine_read(uint32_t addr, uint32_t val) "addr=0x%x, val=0x%x" +sm501_2d_engine_write(uint32_t addr, uint32_t val) "addr=0x%x, val=0x%x" diff --git a/hw/display/trace.h b/hw/display/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..4ed0e9165ba0d63f4142f10b365b7c497f7839b5 --- /dev/null +++ b/hw/display/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_display.h" diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c index 3aaeeeca1e46406a653f1640b54e8a08b4a57c64..90851e730bcde1aeff855119ca251418d9ef228e 100644 --- a/hw/display/vga-isa.c +++ b/hw/display/vga-isa.c @@ -32,17 +32,18 @@ #include "qemu/timer.h" #include "hw/loader.h" #include "hw/qdev-properties.h" +#include "qom/object.h" #define TYPE_ISA_VGA "isa-vga" -#define ISA_VGA(obj) OBJECT_CHECK(ISAVGAState, (obj), TYPE_ISA_VGA) +OBJECT_DECLARE_SIMPLE_TYPE(ISAVGAState, ISA_VGA) -typedef struct ISAVGAState { +struct ISAVGAState { ISADevice parent_obj; struct VGACommonState state; PortioList portio_vga; PortioList portio_vbe; -} ISAVGAState; +}; static void vga_isa_reset(DeviceState *dev) { diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c index a640fd866d8ba043c50de05bc13e0f87645a54e8..48d29630ab773832e11448dab50251819bc9bc83 100644 --- a/hw/display/vga-pci.c +++ b/hw/display/vga-pci.c @@ -34,6 +34,7 @@ #include "qemu/timer.h" #include "hw/loader.h" #include "hw/display/edid.h" +#include "qom/object.h" enum vga_pci_flags { PCI_VGA_FLAG_ENABLE_MMIO = 1, @@ -41,7 +42,7 @@ enum vga_pci_flags { PCI_VGA_FLAG_ENABLE_EDID = 3, }; -typedef struct PCIVGAState { +struct PCIVGAState { PCIDevice dev; VGACommonState vga; uint32_t flags; @@ -49,10 +50,10 @@ typedef struct PCIVGAState { MemoryRegion mmio; MemoryRegion mrs[4]; uint8_t edid[256]; -} PCIVGAState; +}; #define TYPE_PCI_VGA "pci-vga" -#define PCI_VGA(obj) OBJECT_CHECK(PCIVGAState, (obj), TYPE_PCI_VGA) +OBJECT_DECLARE_SIMPLE_TYPE(PCIVGAState, PCI_VGA) static const VMStateDescription vmstate_vga_pci = { .name = "vga", @@ -266,13 +267,6 @@ static void pci_std_vga_realize(PCIDevice *dev, Error **errp) } } -static void pci_std_vga_init(Object *obj) -{ - /* Expose framebuffer byteorder via QOM */ - object_property_add_bool(obj, "big-endian-framebuffer", - vga_get_big_endian_fb, vga_set_big_endian_fb); -} - static void pci_secondary_vga_realize(PCIDevice *dev, Error **errp) { PCIVGAState *d = PCI_VGA(dev); @@ -385,6 +379,10 @@ static void vga_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_DISPLAY_VGA; device_class_set_props(dc, vga_pci_properties); dc->hotpluggable = false; + + /* Expose framebuffer byteorder via QOM */ + object_class_property_add_bool(klass, "big-endian-framebuffer", + vga_get_big_endian_fb, vga_set_big_endian_fb); } static void secondary_class_init(ObjectClass *klass, void *data) @@ -402,7 +400,6 @@ static void secondary_class_init(ObjectClass *klass, void *data) static const TypeInfo vga_info = { .name = "VGA", .parent = TYPE_PCI_VGA, - .instance_init = pci_std_vga_init, .class_init = vga_class_init, }; diff --git a/hw/display/vga.c b/hw/display/vga.c index 061fd9ab8f6c1ee2398ee745249effc7daaf8cd3..836ad50c7b6d8cd127eabdfe74ebe2fc4115c0be 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -1674,7 +1674,6 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) if (!(s->cr[VGA_CRTC_MODE] & 2)) { addr = (addr & ~0x8000) | ((y1 & 2) << 14); } - update = full_update; page0 = addr & s->vbe_size_mask; page1 = (addr + bwidth - 1) & s->vbe_size_mask; if (full_update) { diff --git a/hw/display/vhost-user-gpu-pci.c b/hw/display/vhost-user-gpu-pci.c index 23ce655e0fb94700d47cc72e010d399353bf44a6..a02b23ecaf11f454d722629cce4d5a959814509e 100644 --- a/hw/display/vhost-user-gpu-pci.c +++ b/hw/display/vhost-user-gpu-pci.c @@ -11,16 +11,18 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/virtio/virtio-gpu-pci.h" +#include "qom/object.h" #define TYPE_VHOST_USER_GPU_PCI "vhost-user-gpu-pci" -#define VHOST_USER_GPU_PCI(obj) \ - OBJECT_CHECK(VhostUserGPUPCI, (obj), TYPE_VHOST_USER_GPU_PCI) +typedef struct VhostUserGPUPCI VhostUserGPUPCI; +DECLARE_INSTANCE_CHECKER(VhostUserGPUPCI, VHOST_USER_GPU_PCI, + TYPE_VHOST_USER_GPU_PCI) -typedef struct VhostUserGPUPCI { +struct VhostUserGPUPCI { VirtIOGPUPCIBase parent_obj; VhostUserGPU vdev; -} VhostUserGPUPCI; +}; static void vhost_user_gpu_pci_initfn(Object *obj) { diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 4cdaee1bde49385bf340533573f52834464b9c1d..51f1747c4a41baf8488089ec64cf31958807de0e 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -17,9 +17,6 @@ #include "qapi/error.h" #include "migration/blocker.h" -#define VHOST_USER_GPU(obj) \ - OBJECT_CHECK(VhostUserGPU, (obj), TYPE_VHOST_USER_GPU) - typedef enum VhostUserGpuRequest { VHOST_USER_GPU_NONE = 0, VHOST_USER_GPU_GET_PROTOCOL_FEATURES, diff --git a/hw/display/vhost-user-vga.c b/hw/display/vhost-user-vga.c index 1690f6b6102b48468a10495dd953d7cb723e5aa5..a34a99856d738fcb47bbb01b3262c414b23bb111 100644 --- a/hw/display/vhost-user-vga.c +++ b/hw/display/vhost-user-vga.c @@ -11,17 +11,19 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "virtio-vga.h" +#include "qom/object.h" #define TYPE_VHOST_USER_VGA "vhost-user-vga" -#define VHOST_USER_VGA(obj) \ - OBJECT_CHECK(VhostUserVGA, (obj), TYPE_VHOST_USER_VGA) +typedef struct VhostUserVGA VhostUserVGA; +DECLARE_INSTANCE_CHECKER(VhostUserVGA, VHOST_USER_VGA, + TYPE_VHOST_USER_VGA) -typedef struct VhostUserVGA { +struct VhostUserVGA { VirtIOVGABase parent_obj; VhostUserGPU vdev; -} VhostUserVGA; +}; static void vhost_user_vga_inst_initfn(Object *obj) { @@ -39,7 +41,7 @@ static void vhost_user_vga_inst_initfn(Object *obj) static const VirtioPCIDeviceTypeInfo vhost_user_vga_info = { .generic_name = TYPE_VHOST_USER_VGA, .parent = TYPE_VIRTIO_VGA_BASE, - .instance_size = sizeof(struct VhostUserVGA), + .instance_size = sizeof(VhostUserVGA), .instance_init = vhost_user_vga_inst_initfn, }; diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c index 96621576c2224166a7e735144d04fe0b5303aa8d..0b0c11474dd3e1b683e51574332d8707c7c0f85a 100644 --- a/hw/display/virtio-gpu-3d.c +++ b/hw/display/virtio-gpu-3d.c @@ -17,8 +17,6 @@ #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-gpu.h" -#ifdef CONFIG_VIRGL - #include static struct virgl_renderer_callbacks virtio_gpu_3d_cbs; @@ -595,7 +593,7 @@ void virtio_gpu_virgl_reset(VirtIOGPU *g) { int i; - /* virgl_renderer_reset() ??? */ + virgl_renderer_reset(); for (i = 0; i < g->parent_obj.conf.max_outputs; i++) { if (i != 0) { dpy_gfx_replace_surface(g->parent_obj.scanout[i].con, NULL); @@ -633,5 +631,3 @@ int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g) return capset2_max_ver ? 2 : 1; } - -#endif /* CONFIG_VIRGL */ diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c index c159351be3f8785f104512e2691e9a75a9a36701..40ccd00f94216b3848d3a5ad67d56cea3b7247f9 100644 --- a/hw/display/virtio-gpu-base.c +++ b/hw/display/virtio-gpu-base.c @@ -82,6 +82,8 @@ static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) g->req_state[idx].y = info->yoff; g->req_state[idx].width = info->width; g->req_state[idx].height = info->height; + g->req_state[idx].width_mm = info->width_mm; + g->req_state[idx].height_mm = info->height_mm; if (info->width && info->height) { g->enabled_output_bitmask |= (1 << idx); @@ -112,7 +114,7 @@ virtio_gpu_gl_block(void *opaque, bool block) } } -const GraphicHwOps virtio_gpu_ops = { +static const GraphicHwOps virtio_gpu_ops = { .invalidate = virtio_gpu_invalidate_display, .gfx_update = virtio_gpu_update_display, .text_update = virtio_gpu_text_update, @@ -128,7 +130,6 @@ virtio_gpu_base_device_realize(DeviceState *qdev, { VirtIODevice *vdev = VIRTIO_DEVICE(qdev); VirtIOGPUBase *g = VIRTIO_GPU_BASE(qdev); - Error *local_err = NULL; int i; if (g->conf.max_outputs > VIRTIO_GPU_MAX_SCANOUTS) { @@ -139,9 +140,7 @@ virtio_gpu_base_device_realize(DeviceState *qdev, g->use_virgl_renderer = false; if (virtio_gpu_virgl_enabled(g->conf)) { error_setg(&g->migration_blocker, "virgl is not yet migratable"); - migrate_add_blocker(g->migration_blocker, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (migrate_add_blocker(g->migration_blocker, errp) < 0) { error_free(g->migration_blocker); return false; } @@ -165,6 +164,7 @@ virtio_gpu_base_device_realize(DeviceState *qdev, g->req_state[0].width = g->conf.xres; g->req_state[0].height = g->conf.yres; + g->hw_ops = &virtio_gpu_ops; for (i = 0; i < g->conf.max_outputs; i++) { g->scanout[i].con = graphic_console_init(DEVICE(g), i, &virtio_gpu_ops, g); diff --git a/hw/display/virtio-gpu-pci.c b/hw/display/virtio-gpu-pci.c index 3d152ff5c8730aeeaf8e0352fa07451d2cb88a94..d742a30aecf75a01fbb8ee8eb4ad247e096532c1 100644 --- a/hw/display/virtio-gpu-pci.c +++ b/hw/display/virtio-gpu-pci.c @@ -19,6 +19,7 @@ #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-bus.h" #include "hw/virtio/virtio-gpu-pci.h" +#include "qom/object.h" static Property virtio_gpu_pci_base_properties[] = { DEFINE_VIRTIO_GPU_PCI_PROPERTIES(VirtIOPCIProxy), @@ -31,21 +32,15 @@ static void virtio_gpu_pci_base_realize(VirtIOPCIProxy *vpci_dev, Error **errp) VirtIOGPUBase *g = vgpu->vgpu; DeviceState *vdev = DEVICE(g); int i; - Error *local_error = NULL; - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); virtio_pci_force_virtio_1(vpci_dev); - object_property_set_bool(OBJECT(vdev), true, "realized", &local_error); - - if (local_error) { - error_propagate(errp, local_error); + if (!qdev_realize(vdev, BUS(&vpci_dev->bus), errp)) { return; } for (i = 0; i < g->conf.max_outputs; i++) { - object_property_set_link(OBJECT(g->scanout[i].con), - OBJECT(vpci_dev), - "device", errp); + object_property_set_link(OBJECT(g->scanout[i].con), "device", + OBJECT(vpci_dev), &error_abort); } } @@ -71,13 +66,14 @@ static const TypeInfo virtio_gpu_pci_base_info = { }; #define TYPE_VIRTIO_GPU_PCI "virtio-gpu-pci" -#define VIRTIO_GPU_PCI(obj) \ - OBJECT_CHECK(VirtIOGPUPCI, (obj), TYPE_VIRTIO_GPU_PCI) +typedef struct VirtIOGPUPCI VirtIOGPUPCI; +DECLARE_INSTANCE_CHECKER(VirtIOGPUPCI, VIRTIO_GPU_PCI, + TYPE_VIRTIO_GPU_PCI) -typedef struct VirtIOGPUPCI { +struct VirtIOGPUPCI { VirtIOGPUPCIBase parent_obj; VirtIOGPU vdev; -} VirtIOGPUPCI; +}; static void virtio_gpu_initfn(Object *obj) { diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 5f0dd7c1500229011893274574b72c0e8c7a61ca..f3b71fa9c7c366e55554e99a25455fcfb321980c 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -212,6 +212,8 @@ virtio_gpu_generate_edid(VirtIOGPU *g, int scanout, { VirtIOGPUBase *b = VIRTIO_GPU_BASE(g); qemu_edid_info info = { + .width_mm = b->req_state[scanout].width_mm, + .height_mm = b->req_state[scanout].height_mm, .prefx = b->req_state[scanout].width, .prefy = b->req_state[scanout].height, }; @@ -646,9 +648,9 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g, uint64_t a = le64_to_cpu(ents[i].addr); uint32_t l = le32_to_cpu(ents[i].length); hwaddr len = l; - (*iov)[i].iov_len = l; (*iov)[i].iov_base = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, a, &len, DMA_DIRECTION_TO_DEVICE); + (*iov)[i].iov_len = len; if (addr) { (*addr)[i] = a; } @@ -656,6 +658,9 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g, qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for" " resource %d element %d\n", __func__, ab->resource_id, i); + if ((*iov)[i].iov_base) { + i++; /* cleanup the 'i'th map */ + } virtio_gpu_cleanup_mapping_iov(g, *iov, i); g_free(ents); *iov = NULL; diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c index 95757a6619ca9c2f1c81e4853aed9d3c8963e806..81f776ee36e737a8343aed4cc76fdd56b45b080f 100644 --- a/hw/display/virtio-vga.c +++ b/hw/display/virtio-vga.c @@ -5,6 +5,7 @@ #include "qapi/error.h" #include "qemu/module.h" #include "virtio-vga.h" +#include "qom/object.h" static void virtio_vga_base_invalidate_display(void *opaque) { @@ -12,7 +13,7 @@ static void virtio_vga_base_invalidate_display(void *opaque) VirtIOGPUBase *g = vvga->vgpu; if (g->enable) { - virtio_gpu_ops.invalidate(g); + g->hw_ops->invalidate(g); } else { vvga->vga.hw_ops->invalidate(&vvga->vga); } @@ -24,7 +25,7 @@ static void virtio_vga_base_update_display(void *opaque) VirtIOGPUBase *g = vvga->vgpu; if (g->enable) { - virtio_gpu_ops.gfx_update(g); + g->hw_ops->gfx_update(g); } else { vvga->vga.hw_ops->gfx_update(&vvga->vga); } @@ -36,8 +37,8 @@ static void virtio_vga_base_text_update(void *opaque, console_ch_t *chardata) VirtIOGPUBase *g = vvga->vgpu; if (g->enable) { - if (virtio_gpu_ops.text_update) { - virtio_gpu_ops.text_update(g, chardata); + if (g->hw_ops->text_update) { + g->hw_ops->text_update(g, chardata); } } else { if (vvga->vga.hw_ops->text_update) { @@ -51,8 +52,8 @@ static int virtio_vga_base_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) VirtIOVGABase *vvga = opaque; VirtIOGPUBase *g = vvga->vgpu; - if (virtio_gpu_ops.ui_info) { - return virtio_gpu_ops.ui_info(g, idx, info); + if (g->hw_ops->ui_info) { + return g->hw_ops->ui_info(g, idx, info); } return -1; } @@ -62,8 +63,8 @@ static void virtio_vga_base_gl_block(void *opaque, bool block) VirtIOVGABase *vvga = opaque; VirtIOGPUBase *g = vvga->vgpu; - if (virtio_gpu_ops.gl_block) { - virtio_gpu_ops.gl_block(g, block); + if (g->hw_ops->gl_block) { + g->hw_ops->gl_block(g, block); } } @@ -93,7 +94,6 @@ static void virtio_vga_base_realize(VirtIOPCIProxy *vpci_dev, Error **errp) VirtIOVGABase *vvga = VIRTIO_VGA_BASE(vpci_dev); VirtIOGPUBase *g = vvga->vgpu; VGACommonState *vga = &vvga->vga; - Error *err = NULL; uint32_t offset; int i; @@ -137,11 +137,8 @@ static void virtio_vga_base_realize(VirtIOPCIProxy *vpci_dev, Error **errp) vpci_dev->common.offset = offset; /* init virtio bits */ - qdev_set_parent_bus(DEVICE(g), BUS(&vpci_dev->bus)); virtio_pci_force_virtio_1(vpci_dev); - object_property_set_bool(OBJECT(g), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(g), BUS(&vpci_dev->bus), errp)) { return; } @@ -153,9 +150,8 @@ static void virtio_vga_base_realize(VirtIOPCIProxy *vpci_dev, Error **errp) graphic_console_set_hwops(vga->con, &virtio_vga_base_ops, vvga); for (i = 0; i < g->conf.max_outputs; i++) { - object_property_set_link(OBJECT(g->scanout[i].con), - OBJECT(vpci_dev), - "device", errp); + object_property_set_link(OBJECT(g->scanout[i].con), "device", + OBJECT(vpci_dev), &error_abort); } } @@ -172,6 +168,20 @@ static void virtio_vga_base_reset(DeviceState *dev) vga_dirty_log_start(&vvga->vga); } +static bool virtio_vga_get_big_endian_fb(Object *obj, Error **errp) +{ + VirtIOVGABase *d = VIRTIO_VGA_BASE(obj); + + return d->vga.big_endian_fb; +} + +static void virtio_vga_set_big_endian_fb(Object *obj, bool value, Error **errp) +{ + VirtIOVGABase *d = VIRTIO_VGA_BASE(obj); + + d->vga.big_endian_fb = value; +} + static Property virtio_vga_base_properties[] = { DEFINE_VIRTIO_GPU_PCI_PROPERTIES(VirtIOPCIProxy), DEFINE_PROP_END_OF_LIST(), @@ -194,27 +204,33 @@ static void virtio_vga_base_class_init(ObjectClass *klass, void *data) k->realize = virtio_vga_base_realize; pcidev_k->romfile = "vgabios-virtio.bin"; pcidev_k->class_id = PCI_CLASS_DISPLAY_VGA; + + /* Expose framebuffer byteorder via QOM */ + object_class_property_add_bool(klass, "big-endian-framebuffer", + virtio_vga_get_big_endian_fb, + virtio_vga_set_big_endian_fb); } static TypeInfo virtio_vga_base_info = { .name = TYPE_VIRTIO_VGA_BASE, .parent = TYPE_VIRTIO_PCI, - .instance_size = sizeof(struct VirtIOVGABase), - .class_size = sizeof(struct VirtIOVGABaseClass), + .instance_size = sizeof(VirtIOVGABase), + .class_size = sizeof(VirtIOVGABaseClass), .class_init = virtio_vga_base_class_init, .abstract = true, }; #define TYPE_VIRTIO_VGA "virtio-vga" -#define VIRTIO_VGA(obj) \ - OBJECT_CHECK(VirtIOVGA, (obj), TYPE_VIRTIO_VGA) +typedef struct VirtIOVGA VirtIOVGA; +DECLARE_INSTANCE_CHECKER(VirtIOVGA, VIRTIO_VGA, + TYPE_VIRTIO_VGA) -typedef struct VirtIOVGA { +struct VirtIOVGA { VirtIOVGABase parent_obj; VirtIOGPU vdev; -} VirtIOVGA; +}; static void virtio_vga_inst_initfn(Object *obj) { @@ -229,7 +245,7 @@ static void virtio_vga_inst_initfn(Object *obj) static VirtioPCIDeviceTypeInfo virtio_vga_info = { .generic_name = TYPE_VIRTIO_VGA, .parent = TYPE_VIRTIO_VGA_BASE, - .instance_size = sizeof(struct VirtIOVGA), + .instance_size = sizeof(VirtIOVGA), .instance_init = virtio_vga_inst_initfn, }; diff --git a/hw/display/virtio-vga.h b/hw/display/virtio-vga.h index c41281a0106f14d03903bbca4afb895e727f79ff..977ad5edc2934e0e03ed3ae9ab82369ff7c9a64c 100644 --- a/hw/display/virtio-vga.h +++ b/hw/display/virtio-vga.h @@ -3,30 +3,27 @@ #include "hw/virtio/virtio-gpu-pci.h" #include "vga_int.h" +#include "qom/object.h" /* * virtio-vga-base: This extends VirtioPCIProxy. */ #define TYPE_VIRTIO_VGA_BASE "virtio-vga-base" -#define VIRTIO_VGA_BASE(obj) \ - OBJECT_CHECK(VirtIOVGABase, (obj), TYPE_VIRTIO_VGA_BASE) -#define VIRTIO_VGA_BASE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtIOVGABaseClass, obj, TYPE_VIRTIO_VGA_BASE) -#define VIRTIO_VGA_BASE_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtIOVGABaseClass, klass, TYPE_VIRTIO_VGA_BASE) +OBJECT_DECLARE_TYPE(VirtIOVGABase, VirtIOVGABaseClass, + VIRTIO_VGA_BASE) -typedef struct VirtIOVGABase { +struct VirtIOVGABase { VirtIOPCIProxy parent_obj; VirtIOGPUBase *vgpu; VGACommonState vga; MemoryRegion vga_mrs[3]; -} VirtIOVGABase; +}; -typedef struct VirtIOVGABaseClass { +struct VirtIOVGABaseClass { VirtioPCIClass parent_class; DeviceReset parent_reset; -} VirtIOVGABaseClass; +}; #endif /* VIRTIO_VGA_H */ diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index 58ea82e3e581e3799dc952c4f25bf1040db65519..bef0d7d69a79bab6348b81d99787bab548935dfd 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -26,12 +26,14 @@ #include "qemu/module.h" #include "qemu/units.h" #include "qapi/error.h" +#include "qemu/log.h" #include "hw/loader.h" #include "trace.h" #include "ui/vnc.h" #include "hw/pci/pci.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" +#include "qom/object.h" #undef VERBOSE #define HW_RECT_ACCEL @@ -84,8 +86,8 @@ struct vmsvga_state_s { #define TYPE_VMWARE_SVGA "vmware-svga" -#define VMWARE_SVGA(obj) \ - OBJECT_CHECK(struct pci_vmsvga_state_s, (obj), TYPE_VMWARE_SVGA) +DECLARE_INSTANCE_CHECKER(struct pci_vmsvga_state_s, VMWARE_SVGA, + TYPE_VMWARE_SVGA) struct pci_vmsvga_state_s { /*< private >*/ @@ -953,7 +955,8 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) ret = s->scratch[s->index - SVGA_SCRATCH_BASE]; break; } - printf("%s: Bad register %02x\n", __func__, s->index); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad register %02x\n", __func__, s->index); ret = 0; break; } @@ -1002,7 +1005,8 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) s->new_width = value; s->invalidated = 1; } else { - printf("%s: Bad width: %i\n", __func__, value); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad width: %i\n", __func__, value); } break; @@ -1011,13 +1015,15 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) s->new_height = value; s->invalidated = 1; } else { - printf("%s: Bad height: %i\n", __func__, value); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad height: %i\n", __func__, value); } break; case SVGA_REG_BITS_PER_PIXEL: if (value != 32) { - printf("%s: Bad bits per pixel: %i bits\n", __func__, value); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad bits per pixel: %i bits\n", __func__, value); s->config = 0; s->invalidated = 1; } @@ -1082,7 +1088,8 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) s->scratch[s->index - SVGA_SCRATCH_BASE] = value; break; } - printf("%s: Bad register %02x\n", __func__, s->index); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad register %02x\n", __func__, s->index); } } @@ -1300,7 +1307,7 @@ static void pci_vmsvga_realize(PCIDevice *dev, Error **errp) dev->config[PCI_LATENCY_TIMER] = 0x40; dev->config[PCI_INTERRUPT_LINE] = 0xff; /* End */ - memory_region_init_io(&s->io_bar, NULL, &vmsvga_io_ops, &s->chip, + memory_region_init_io(&s->io_bar, OBJECT(dev), &vmsvga_io_ops, &s->chip, "vmsvga-io", 0x10); memory_region_set_flush_coalesced(&s->io_bar); pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar); diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c index 3e5fb44e06eed4995c6353bcf25e08187ddb7011..c56e6ec593657760972638938c25804d974e0408 100644 --- a/hw/display/xlnx_dp.c +++ b/hw/display/xlnx_dp.c @@ -1,5 +1,5 @@ /* - * xlnx_dp.c + * Xilinx Display Port * * Copyright (C) 2015 : GreenSocs Ltd * http://www.greensocs.com/ , email: info@greensocs.com @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" +#include "qemu/error-report.h" #include "qemu/log.h" #include "qemu/module.h" #include "hw/display/xlnx_dp.h" @@ -465,7 +466,7 @@ static uint8_t xlnx_dp_aux_pop_tx_fifo(XlnxDPState *s) uint8_t ret; if (fifo8_is_empty(&s->tx_fifo)) { - DPRINTF("tx_fifo underflow..\n"); + error_report("%s: TX_FIFO underflow", __func__); abort(); } ret = fifo8_pop(&s->tx_fifo); @@ -525,6 +526,7 @@ static void xlnx_dp_aux_set_command(XlnxDPState *s, uint32_t value) qemu_log_mask(LOG_UNIMP, "xlnx_dp: Write i2c status not implemented\n"); break; default: + error_report("%s: invalid command: %u", __func__, cmd); abort(); } @@ -631,8 +633,8 @@ static void xlnx_dp_change_graphic_fmt(XlnxDPState *s) s->g_plane.format = PIXMAN_b8g8r8; break; default: - DPRINTF("error: unsupported graphic format %u.\n", - s->avbufm_registers[AV_BUF_FORMAT] & DP_GRAPHIC_MASK); + error_report("%s: unsupported graphic format %u", __func__, + s->avbufm_registers[AV_BUF_FORMAT] & DP_GRAPHIC_MASK); abort(); } @@ -647,8 +649,8 @@ static void xlnx_dp_change_graphic_fmt(XlnxDPState *s) s->v_plane.format = PIXMAN_x8b8g8r8; break; default: - DPRINTF("error: unsupported video format %u.\n", - s->avbufm_registers[AV_BUF_FORMAT] & DP_NL_VID_FMT_MASK); + error_report("%s: unsupported video format %u", __func__, + s->avbufm_registers[AV_BUF_FORMAT] & DP_NL_VID_FMT_MASK); abort(); } @@ -1242,15 +1244,15 @@ static void xlnx_dp_init(Object *obj) /* * Initialize AUX Bus. */ - s->aux_bus = aux_init_bus(DEVICE(obj), "aux"); + s->aux_bus = aux_bus_init(DEVICE(obj), "aux"); /* * Initialize DPCD and EDID.. */ - s->dpcd = DPCD(aux_create_slave(s->aux_bus, "dpcd")); + s->dpcd = DPCD(qdev_new("dpcd")); object_property_add_child(OBJECT(s), "dpcd", OBJECT(s->dpcd)); - s->edid = I2CDDC(qdev_create(BUS(aux_get_i2c_bus(s->aux_bus)), "i2c-ddc")); + s->edid = I2CDDC(qdev_new("i2c-ddc")); i2c_set_slave_address(I2C_SLAVE(s->edid), 0x50); object_property_add_child(OBJECT(s), "edid", OBJECT(s->edid)); @@ -1264,9 +1266,14 @@ static void xlnx_dp_realize(DeviceState *dev, Error **errp) DisplaySurface *surface; struct audsettings as; - qdev_init_nofail(DEVICE(s->dpcd)); + aux_bus_realize(s->aux_bus); + + qdev_realize(DEVICE(s->dpcd), BUS(s->aux_bus), &error_fatal); aux_map_slave(AUX_SLAVE(s->dpcd), 0x0000); + qdev_realize_and_unref(DEVICE(s->edid), BUS(aux_get_i2c_bus(s->aux_bus)), + &error_fatal); + s->console = graphic_console_init(dev, 0, &xlnx_dp_gfx_ops, s); surface = qemu_console_surface(s->console); xlnx_dpdma_set_host_data_location(s->dpdma, DP_GRAPHIC_DMA_CHANNEL, diff --git a/hw/dma/Kconfig b/hw/dma/Kconfig index 5c61b67bc0509e7fcdcfda3cdc867b4b0cb544ab..d67492d36c15afb94dae5198d8894bfb8c328733 100644 --- a/hw/dma/Kconfig +++ b/hw/dma/Kconfig @@ -20,3 +20,6 @@ config ZYNQ_DEVCFG config STP2000 bool + +config SIFIVE_PDMA + bool diff --git a/hw/dma/Makefile.objs b/hw/dma/Makefile.objs deleted file mode 100644 index f4b1cfe26da0f1aa02a23e2f9dc7d67cee20dbd9..0000000000000000000000000000000000000000 --- a/hw/dma/Makefile.objs +++ /dev/null @@ -1,16 +0,0 @@ -common-obj-$(CONFIG_PUV3) += puv3_dma.o -common-obj-$(CONFIG_RC4030) += rc4030.o -common-obj-$(CONFIG_PL080) += pl080.o -common-obj-$(CONFIG_PL330) += pl330.o -common-obj-$(CONFIG_I82374) += i82374.o -common-obj-$(CONFIG_I8257) += i8257.o -common-obj-$(CONFIG_XILINX_AXI) += xilinx_axidma.o -common-obj-$(CONFIG_ZYNQ_DEVCFG) += xlnx-zynq-devcfg.o -common-obj-$(CONFIG_ETRAXFS) += etraxfs_dma.o -common-obj-$(CONFIG_STP2000) += sparc32_dma.o -common-obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx_dpdma.o -common-obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zdma.o - -common-obj-$(CONFIG_OMAP) += omap_dma.o soc_dma.o -common-obj-$(CONFIG_PXA2XX) += pxa2xx_dma.o -common-obj-$(CONFIG_RASPI) += bcm2835_dma.o diff --git a/hw/dma/bcm2835_dma.c b/hw/dma/bcm2835_dma.c index 4cd9dab745a3de56f8d5efe2cdd874c4f7faf9e2..eb0002a2b98a31002e30009a80c7e5d148da0b2b 100644 --- a/hw/dma/bcm2835_dma.c +++ b/hw/dma/bcm2835_dma.c @@ -376,16 +376,9 @@ static void bcm2835_dma_reset(DeviceState *dev) static void bcm2835_dma_realize(DeviceState *dev, Error **errp) { BCM2835DMAState *s = BCM2835_DMA(dev); - Error *err = NULL; Object *obj; - obj = object_property_get_link(OBJECT(dev), "dma-mr", &err); - if (obj == NULL) { - error_setg(errp, "%s: required dma-mr link not found: %s", - __func__, error_get_pretty(err)); - return; - } - + obj = object_property_get_link(OBJECT(dev), "dma-mr", &error_abort); s->dma_mr = MEMORY_REGION(obj); address_space_init(&s->dma_as, s->dma_mr, TYPE_BCM2835_DMA "-memory"); diff --git a/hw/dma/i82374.c b/hw/dma/i82374.c index 6977d85ef88347d162ad7ef9d9adcc9a6f95b6be..34c3aaf7d3447d7d7c6cb4d98cbc8e7538e71ba8 100644 --- a/hw/dma/i82374.c +++ b/hw/dma/i82374.c @@ -29,9 +29,10 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "hw/dma/i8257.h" +#include "qom/object.h" #define TYPE_I82374 "i82374" -#define I82374(obj) OBJECT_CHECK(I82374State, (obj), TYPE_I82374) +OBJECT_DECLARE_SIMPLE_TYPE(I82374State, I82374) //#define DEBUG_I82374 @@ -45,13 +46,13 @@ do {} while (0) #define BADF(fmt, ...) \ do { fprintf(stderr, "i82374 ERROR: " fmt , ## __VA_ARGS__); } while (0) -typedef struct I82374State { +struct I82374State { ISADevice parent_obj; uint32_t iobase; uint8_t commands[8]; PortioList port_list; -} I82374State; +}; static const VMStateDescription vmstate_i82374 = { .name = "i82374", diff --git a/hw/dma/i8257.c b/hw/dma/i8257.c index 1b3435ab58cd8932bbbed485196fdc793319cb61..de5f696919ca131fd9560bae404895f54b4936f2 100644 --- a/hw/dma/i8257.c +++ b/hw/dma/i8257.c @@ -27,13 +27,12 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "hw/dma/i8257.h" +#include "qapi/error.h" #include "qemu/main-loop.h" #include "qemu/module.h" #include "qemu/log.h" #include "trace.h" -#define I8257(obj) \ - OBJECT_CHECK(I8257State, (obj), TYPE_I8257) /* #define DEBUG_DMA */ @@ -638,21 +637,21 @@ void i8257_dma_init(ISABus *bus, bool high_page_enable) ISADevice *isa1, *isa2; DeviceState *d; - isa1 = isa_create(bus, TYPE_I8257); + isa1 = isa_new(TYPE_I8257); d = DEVICE(isa1); qdev_prop_set_int32(d, "base", 0x00); qdev_prop_set_int32(d, "page-base", 0x80); qdev_prop_set_int32(d, "pageh-base", high_page_enable ? 0x480 : -1); qdev_prop_set_int32(d, "dshift", 0); - qdev_init_nofail(d); + isa_realize_and_unref(isa1, bus, &error_fatal); - isa2 = isa_create(bus, TYPE_I8257); + isa2 = isa_new(TYPE_I8257); d = DEVICE(isa2); qdev_prop_set_int32(d, "base", 0xc0); qdev_prop_set_int32(d, "page-base", 0x88); qdev_prop_set_int32(d, "pageh-base", high_page_enable ? 0x488 : -1); qdev_prop_set_int32(d, "dshift", 1); - qdev_init_nofail(d); + isa_realize_and_unref(isa2, bus, &error_fatal); isa_bus_dma(bus, ISADMA(isa1), ISADMA(isa2)); } diff --git a/hw/dma/meson.build b/hw/dma/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..b991d7698c7498d8a9f06e55bcc2ede9a5fd68d7 --- /dev/null +++ b/hw/dma/meson.build @@ -0,0 +1,16 @@ +softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_dma.c')) +softmmu_ss.add(when: 'CONFIG_RC4030', if_true: files('rc4030.c')) +softmmu_ss.add(when: 'CONFIG_PL080', if_true: files('pl080.c')) +softmmu_ss.add(when: 'CONFIG_PL330', if_true: files('pl330.c')) +softmmu_ss.add(when: 'CONFIG_I82374', if_true: files('i82374.c')) +softmmu_ss.add(when: 'CONFIG_I8257', if_true: files('i8257.c')) +softmmu_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('xilinx_axidma.c')) +softmmu_ss.add(when: 'CONFIG_ZYNQ_DEVCFG', if_true: files('xlnx-zynq-devcfg.c')) +softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_dma.c')) +softmmu_ss.add(when: 'CONFIG_STP2000', if_true: files('sparc32_dma.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx_dpdma.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zdma.c')) +softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_dma.c', 'soc_dma.c')) +softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_dma.c')) +softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_dma.c')) +softmmu_ss.add(when: 'CONFIG_SIFIVE_PDMA', if_true: files('sifive_pdma.c')) diff --git a/hw/dma/pl330.c b/hw/dma/pl330.c index 0bd63a43f50319d9c29ee8ab9239a7e84e0b22d2..944ba296b088218078824d90975ab67e31e8a82b 100644 --- a/hw/dma/pl330.c +++ b/hw/dma/pl330.c @@ -26,6 +26,7 @@ #include "qemu/log.h" #include "qemu/module.h" #include "trace.h" +#include "qom/object.h" #ifndef PL330_ERR_DEBUG #define PL330_ERR_DEBUG 0 @@ -271,7 +272,7 @@ struct PL330State { }; #define TYPE_PL330 "pl330" -#define PL330(obj) OBJECT_CHECK(PL330State, (obj), TYPE_PL330) +OBJECT_DECLARE_SIMPLE_TYPE(PL330State, PL330) static const VMStateDescription vmstate_pl330 = { .name = "pl330", diff --git a/hw/dma/puv3_dma.c b/hw/dma/puv3_dma.c index 5488d388a962cc5737d8306efef118433f6679e4..cca1e9ec21b87cbbc08b053507ac07a978d3c281 100644 --- a/hw/dma/puv3_dma.c +++ b/hw/dma/puv3_dma.c @@ -11,24 +11,26 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" +#include "qom/object.h" #undef DEBUG_PUV3 #include "hw/unicore32/puv3.h" #include "qemu/module.h" +#include "qemu/log.h" #define PUV3_DMA_CH_NR (6) #define PUV3_DMA_CH_MASK (0xff) #define PUV3_DMA_CH(offset) ((offset) >> 8) #define TYPE_PUV3_DMA "puv3_dma" -#define PUV3_DMA(obj) OBJECT_CHECK(PUV3DMAState, (obj), TYPE_PUV3_DMA) +OBJECT_DECLARE_SIMPLE_TYPE(PUV3DMAState, PUV3_DMA) -typedef struct PUV3DMAState { +struct PUV3DMAState { SysBusDevice parent_obj; MemoryRegion iomem; uint32_t reg_CFG[PUV3_DMA_CH_NR]; -} PUV3DMAState; +}; static uint64_t puv3_dma_read(void *opaque, hwaddr offset, unsigned size) @@ -43,7 +45,9 @@ static uint64_t puv3_dma_read(void *opaque, hwaddr offset, ret = s->reg_CFG[PUV3_DMA_CH(offset)]; break; default: - DPRINTF("Bad offset 0x%x\n", offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad read offset 0x%"HWADDR_PRIx"\n", + __func__, offset); } DPRINTF("offset 0x%x, value 0x%x\n", offset, ret); @@ -62,7 +66,9 @@ static void puv3_dma_write(void *opaque, hwaddr offset, s->reg_CFG[PUV3_DMA_CH(offset)] = value; break; default: - DPRINTF("Bad offset 0x%x\n", offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad write offset 0x%"HWADDR_PRIx"\n", + __func__, offset); } DPRINTF("offset 0x%x, value 0x%x\n", offset, value); } diff --git a/hw/dma/pxa2xx_dma.c b/hw/dma/pxa2xx_dma.c index 8a2eeb32bc3e3c921e94c459ea8d09e74485c214..b3707ff3de25020637bc7f8113891ea8b511e4eb 100644 --- a/hw/dma/pxa2xx_dma.c +++ b/hw/dma/pxa2xx_dma.c @@ -18,6 +18,7 @@ #include "migration/vmstate.h" #include "qapi/error.h" #include "qemu/module.h" +#include "qom/object.h" #define PXA255_DMA_NUM_CHANNELS 16 #define PXA27X_DMA_NUM_CHANNELS 32 @@ -34,9 +35,9 @@ typedef struct { } PXA2xxDMAChannel; #define TYPE_PXA2XX_DMA "pxa2xx-dma" -#define PXA2XX_DMA(obj) OBJECT_CHECK(PXA2xxDMAState, (obj), TYPE_PXA2XX_DMA) +OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxDMAState, PXA2XX_DMA) -typedef struct PXA2xxDMAState { +struct PXA2xxDMAState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -58,7 +59,7 @@ typedef struct PXA2xxDMAState { /* Flag to avoid recursive DMA invocations. */ int running; -} PXA2xxDMAState; +}; #define DCSR0 0x0000 /* DMA Control / Status register for Channel 0 */ #define DCSR31 0x007c /* DMA Control / Status register for Channel 31 */ @@ -495,9 +496,9 @@ DeviceState *pxa27x_dma_init(hwaddr base, qemu_irq irq) { DeviceState *dev; - dev = qdev_create(NULL, "pxa2xx-dma"); + dev = qdev_new("pxa2xx-dma"); qdev_prop_set_int32(dev, "channels", PXA27X_DMA_NUM_CHANNELS); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq); @@ -509,9 +510,9 @@ DeviceState *pxa255_dma_init(hwaddr base, qemu_irq irq) { DeviceState *dev; - dev = qdev_create(NULL, "pxa2xx-dma"); + dev = qdev_new("pxa2xx-dma"); qdev_prop_set_int32(dev, "channels", PXA27X_DMA_NUM_CHANNELS); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq); diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c index eefbabd75818f3cf3e3ff0b4b8c49b9223ec3c45..e4d2f1725bcc7fd7c0266d62ca9008c44ec9a5b3 100644 --- a/hw/dma/rc4030.c +++ b/hw/dma/rc4030.c @@ -28,11 +28,13 @@ #include "hw/mips/mips.h" #include "hw/sysbus.h" #include "migration/vmstate.h" +#include "qapi/error.h" #include "qemu/timer.h" #include "qemu/log.h" #include "qemu/module.h" #include "exec/address-spaces.h" #include "trace.h" +#include "qom/object.h" /********************************************************/ /* rc4030 emulation */ @@ -54,12 +56,11 @@ typedef struct dma_pagetable_entry { #define DMA_FLAG_ADDR_INTR 0x0400 #define TYPE_RC4030 "rc4030" -#define RC4030(obj) \ - OBJECT_CHECK(rc4030State, (obj), TYPE_RC4030) +OBJECT_DECLARE_SIMPLE_TYPE(rc4030State, RC4030) #define TYPE_RC4030_IOMMU_MEMORY_REGION "rc4030-iommu-memory-region" -typedef struct rc4030State { +struct rc4030State { SysBusDevice parent; @@ -100,7 +101,7 @@ typedef struct rc4030State { MemoryRegion iomem_chipset; MemoryRegion iomem_jazzio; -} rc4030State; +}; static void set_next_tick(rc4030State *s) { @@ -744,8 +745,8 @@ DeviceState *rc4030_init(rc4030_dma **dmas, IOMMUMemoryRegion **dma_mr) { DeviceState *dev; - dev = qdev_create(NULL, TYPE_RC4030); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_RC4030); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); *dmas = rc4030_allocate_dmas(dev, 4); *dma_mr = &RC4030(dev)->dma_mr; diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c new file mode 100644 index 0000000000000000000000000000000000000000..e1f6fedbda7333c0aa287dc447a21404f234aa5c --- /dev/null +++ b/hw/dma/sifive_pdma.c @@ -0,0 +1,313 @@ +/* + * SiFive Platform DMA emulation + * + * Copyright (c) 2020 Wind River Systems, Inc. + * + * Author: + * Bin Meng + * + * 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 or + * (at your option) version 3 of the License. + * + * 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/sysbus.h" +#include "migration/vmstate.h" +#include "sysemu/dma.h" +#include "hw/dma/sifive_pdma.h" + +#define DMA_CONTROL 0x000 +#define CONTROL_CLAIM BIT(0) +#define CONTROL_RUN BIT(1) +#define CONTROL_DONE_IE BIT(14) +#define CONTROL_ERR_IE BIT(15) +#define CONTROL_DONE BIT(30) +#define CONTROL_ERR BIT(31) + +#define DMA_NEXT_CONFIG 0x004 +#define CONFIG_REPEAT BIT(2) +#define CONFIG_ORDER BIT(3) +#define CONFIG_WRSZ_SHIFT 24 +#define CONFIG_RDSZ_SHIFT 28 +#define CONFIG_SZ_MASK 0xf + +#define DMA_NEXT_BYTES 0x008 +#define DMA_NEXT_DST 0x010 +#define DMA_NEXT_SRC 0x018 +#define DMA_EXEC_CONFIG 0x104 +#define DMA_EXEC_BYTES 0x108 +#define DMA_EXEC_DST 0x110 +#define DMA_EXEC_SRC 0x118 + +enum dma_chan_state { + DMA_CHAN_STATE_IDLE, + DMA_CHAN_STATE_STARTED, + DMA_CHAN_STATE_ERROR, + DMA_CHAN_STATE_DONE +}; + +static void sifive_pdma_run(SiFivePDMAState *s, int ch) +{ + uint64_t bytes = s->chan[ch].next_bytes; + uint64_t dst = s->chan[ch].next_dst; + uint64_t src = s->chan[ch].next_src; + uint32_t config = s->chan[ch].next_config; + int wsize, rsize, size; + uint8_t buf[64]; + int n; + + /* do nothing if bytes to transfer is zero */ + if (!bytes) { + goto error; + } + + /* + * The manual does not describe how the hardware behaviors when + * config.wsize and config.rsize are given different values. + * A common case is memory to memory DMA, and in this case they + * are normally the same. Abort if this expectation fails. + */ + wsize = (config >> CONFIG_WRSZ_SHIFT) & CONFIG_SZ_MASK; + rsize = (config >> CONFIG_RDSZ_SHIFT) & CONFIG_SZ_MASK; + if (wsize != rsize) { + goto error; + } + + /* + * Calculate the transaction size + * + * size field is base 2 logarithm of DMA transaction size, + * but there is an upper limit of 64 bytes per transaction. + */ + size = wsize; + if (size > 6) { + size = 6; + } + size = 1 << size; + + /* the bytes to transfer should be multiple of transaction size */ + if (bytes % size) { + goto error; + } + + /* indicate a DMA transfer is started */ + s->chan[ch].state = DMA_CHAN_STATE_STARTED; + s->chan[ch].control &= ~CONTROL_DONE; + s->chan[ch].control &= ~CONTROL_ERR; + + /* load the next_ registers into their exec_ counterparts */ + s->chan[ch].exec_config = config; + s->chan[ch].exec_bytes = bytes; + s->chan[ch].exec_dst = dst; + s->chan[ch].exec_src = src; + + for (n = 0; n < bytes / size; n++) { + cpu_physical_memory_read(s->chan[ch].exec_src, buf, size); + cpu_physical_memory_write(s->chan[ch].exec_dst, buf, size); + s->chan[ch].exec_src += size; + s->chan[ch].exec_dst += size; + s->chan[ch].exec_bytes -= size; + } + + /* indicate a DMA transfer is done */ + s->chan[ch].state = DMA_CHAN_STATE_DONE; + s->chan[ch].control &= ~CONTROL_RUN; + s->chan[ch].control |= CONTROL_DONE; + + /* reload exec_ registers if repeat is required */ + if (s->chan[ch].next_config & CONFIG_REPEAT) { + s->chan[ch].exec_bytes = bytes; + s->chan[ch].exec_dst = dst; + s->chan[ch].exec_src = src; + } + + return; + +error: + s->chan[ch].state = DMA_CHAN_STATE_ERROR; + s->chan[ch].control |= CONTROL_ERR; + return; +} + +static inline void sifive_pdma_update_irq(SiFivePDMAState *s, int ch) +{ + bool done_ie, err_ie; + + done_ie = !!(s->chan[ch].control & CONTROL_DONE_IE); + err_ie = !!(s->chan[ch].control & CONTROL_ERR_IE); + + if (done_ie && (s->chan[ch].control & CONTROL_DONE)) { + qemu_irq_raise(s->irq[ch * 2]); + } else { + qemu_irq_lower(s->irq[ch * 2]); + } + + if (err_ie && (s->chan[ch].control & CONTROL_ERR)) { + qemu_irq_raise(s->irq[ch * 2 + 1]); + } else { + qemu_irq_lower(s->irq[ch * 2 + 1]); + } + + s->chan[ch].state = DMA_CHAN_STATE_IDLE; +} + +static uint64_t sifive_pdma_read(void *opaque, hwaddr offset, unsigned size) +{ + SiFivePDMAState *s = opaque; + int ch = SIFIVE_PDMA_CHAN_NO(offset); + uint64_t val = 0; + + if (ch >= SIFIVE_PDMA_CHANS) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n", + __func__, ch); + return 0; + } + + offset &= 0xfff; + switch (offset) { + case DMA_CONTROL: + val = s->chan[ch].control; + break; + case DMA_NEXT_CONFIG: + val = s->chan[ch].next_config; + break; + case DMA_NEXT_BYTES: + val = s->chan[ch].next_bytes; + break; + case DMA_NEXT_DST: + val = s->chan[ch].next_dst; + break; + case DMA_NEXT_SRC: + val = s->chan[ch].next_src; + break; + case DMA_EXEC_CONFIG: + val = s->chan[ch].exec_config; + break; + case DMA_EXEC_BYTES: + val = s->chan[ch].exec_bytes; + break; + case DMA_EXEC_DST: + val = s->chan[ch].exec_dst; + break; + case DMA_EXEC_SRC: + val = s->chan[ch].exec_src; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", + __func__, offset); + break; + } + + return val; +} + +static void sifive_pdma_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + SiFivePDMAState *s = opaque; + int ch = SIFIVE_PDMA_CHAN_NO(offset); + + if (ch >= SIFIVE_PDMA_CHANS) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n", + __func__, ch); + return; + } + + offset &= 0xfff; + switch (offset) { + case DMA_CONTROL: + s->chan[ch].control = value; + + if (value & CONTROL_RUN) { + sifive_pdma_run(s, ch); + } + + sifive_pdma_update_irq(s, ch); + break; + case DMA_NEXT_CONFIG: + s->chan[ch].next_config = value; + break; + case DMA_NEXT_BYTES: + s->chan[ch].next_bytes = value; + break; + case DMA_NEXT_DST: + s->chan[ch].next_dst = value; + break; + case DMA_NEXT_SRC: + s->chan[ch].next_src = value; + break; + case DMA_EXEC_CONFIG: + case DMA_EXEC_BYTES: + case DMA_EXEC_DST: + case DMA_EXEC_SRC: + /* these are read-only registers */ + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", + __func__, offset); + break; + } +} + +static const MemoryRegionOps sifive_pdma_ops = { + .read = sifive_pdma_read, + .write = sifive_pdma_write, + .endianness = DEVICE_LITTLE_ENDIAN, + /* there are 32-bit and 64-bit wide registers */ + .impl = { + .min_access_size = 4, + .max_access_size = 8, + } +}; + +static void sifive_pdma_realize(DeviceState *dev, Error **errp) +{ + SiFivePDMAState *s = SIFIVE_PDMA(dev); + int i; + + memory_region_init_io(&s->iomem, OBJECT(dev), &sifive_pdma_ops, s, + TYPE_SIFIVE_PDMA, SIFIVE_PDMA_REG_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); + + for (i = 0; i < SIFIVE_PDMA_IRQS; i++) { + sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]); + } +} + +static void sifive_pdma_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "SiFive Platform DMA controller"; + dc->realize = sifive_pdma_realize; +} + +static const TypeInfo sifive_pdma_info = { + .name = TYPE_SIFIVE_PDMA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SiFivePDMAState), + .class_init = sifive_pdma_class_init, +}; + +static void sifive_pdma_register_types(void) +{ + type_register_static(&sifive_pdma_info); +} + +type_init(sifive_pdma_register_types) diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index 84b9c5dc77b6808b1d74e688f0606e3c6e33fb81..b643b413c5266a06126c309598182bfe8ee81bca 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -290,27 +290,26 @@ static const TypeInfo sparc32_dma_device_info = { static void sparc32_espdma_device_init(Object *obj) { DMADeviceState *s = SPARC32_DMA_DEVICE(obj); + ESPDMADeviceState *es = SPARC32_ESPDMA_DEVICE(obj); memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s, "espdma-mmio", DMA_SIZE); + + object_initialize_child(obj, "esp", &es->esp, TYPE_ESP); } static void sparc32_espdma_device_realize(DeviceState *dev, Error **errp) { - DeviceState *d; - SysBusESPState *sysbus; - ESPState *esp; - - d = qdev_create(NULL, TYPE_ESP); - object_property_add_child(OBJECT(dev), "esp", OBJECT(d)); - sysbus = ESP_STATE(d); - esp = &sysbus->esp; + ESPDMADeviceState *es = SPARC32_ESPDMA_DEVICE(dev); + SysBusESPState *sysbus = ESP(&es->esp); + ESPState *esp = &sysbus->esp; + esp->dma_memory_read = espdma_memory_read; esp->dma_memory_write = espdma_memory_write; esp->dma_opaque = SPARC32_DMA_DEVICE(dev); sysbus->it_shift = 2; esp->dma_enabled = 1; - qdev_init_nofail(d); + sysbus_realize(SYS_BUS_DEVICE(sysbus), &error_fatal); } static void sparc32_espdma_device_class_init(ObjectClass *klass, void *data) @@ -331,23 +330,21 @@ static const TypeInfo sparc32_espdma_device_info = { static void sparc32_ledma_device_init(Object *obj) { DMADeviceState *s = SPARC32_DMA_DEVICE(obj); + LEDMADeviceState *ls = SPARC32_LEDMA_DEVICE(obj); memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s, "ledma-mmio", DMA_SIZE); + + object_initialize_child(obj, "lance", &ls->lance, TYPE_LANCE); } static void sparc32_ledma_device_realize(DeviceState *dev, Error **errp) { - DeviceState *d; - NICInfo *nd = &nd_table[0]; + LEDMADeviceState *s = SPARC32_LEDMA_DEVICE(dev); + SysBusPCNetState *lance = SYSBUS_PCNET(&s->lance); - qemu_check_nic_model(nd, TYPE_LANCE); - - d = qdev_create(NULL, TYPE_LANCE); - object_property_add_child(OBJECT(dev), "lance", OBJECT(d)); - qdev_set_nic_properties(d, nd); - object_property_set_link(OBJECT(d), OBJECT(dev), "dma", errp); - qdev_init_nofail(d); + object_property_set_link(OBJECT(lance), "dma", OBJECT(dev), &error_abort); + sysbus_realize(SYS_BUS_DEVICE(lance), &error_fatal); } static void sparc32_ledma_device_class_init(ObjectClass *klass, void *data) @@ -378,10 +375,9 @@ static void sparc32_dma_realize(DeviceState *dev, Error **errp) return; } - espdma = qdev_create(NULL, TYPE_SPARC32_ESPDMA_DEVICE); - object_property_set_link(OBJECT(espdma), iommu, "iommu", errp); - object_property_add_child(OBJECT(s), "espdma", OBJECT(espdma)); - qdev_init_nofail(espdma); + espdma = DEVICE(&s->espdma); + object_property_set_link(OBJECT(espdma), "iommu", iommu, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(espdma), &error_fatal); esp = DEVICE(object_resolve_path_component(OBJECT(espdma), "esp")); sbd = SYS_BUS_DEVICE(esp); @@ -393,10 +389,9 @@ static void sparc32_dma_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(&s->dmamem, 0x0, sysbus_mmio_get_region(sbd, 0)); - ledma = qdev_create(NULL, TYPE_SPARC32_LEDMA_DEVICE); - object_property_set_link(OBJECT(ledma), iommu, "iommu", errp); - object_property_add_child(OBJECT(s), "ledma", OBJECT(ledma)); - qdev_init_nofail(ledma); + ledma = DEVICE(&s->ledma); + object_property_set_link(OBJECT(ledma), "iommu", iommu, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(ledma), &error_fatal); lance = DEVICE(object_resolve_path_component(OBJECT(ledma), "lance")); sbd = SYS_BUS_DEVICE(lance); @@ -420,6 +415,11 @@ static void sparc32_dma_init(Object *obj) memory_region_init(&s->dmamem, OBJECT(s), "dma", DMA_SIZE + DMA_ETH_SIZE); sysbus_init_mmio(sbd, &s->dmamem); + + object_initialize_child(obj, "espdma", &s->espdma, + TYPE_SPARC32_ESPDMA_DEVICE); + object_initialize_child(obj, "ledma", &s->ledma, + TYPE_SPARC32_LEDMA_DEVICE); } static void sparc32_dma_class_init(ObjectClass *klass, void *data) diff --git a/hw/dma/trace.h b/hw/dma/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..4bcb28b47cc7fb71745c81e2c6e81f56206fc3bf --- /dev/null +++ b/hw/dma/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_dma.h" diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c index 460102b1421747935ef7ecec99a6fc328dc3a2d9..0a7f5acb4b7cbf5e5d1a92a173ba4192e83960f6 100644 --- a/hw/dma/xilinx_axidma.c +++ b/hw/dma/xilinx_axidma.c @@ -35,6 +35,7 @@ #include "sysemu/dma.h" #include "hw/stream.h" +#include "qom/object.h" #define D(x) @@ -42,16 +43,14 @@ #define TYPE_XILINX_AXI_DMA_DATA_STREAM "xilinx-axi-dma-data-stream" #define TYPE_XILINX_AXI_DMA_CONTROL_STREAM "xilinx-axi-dma-control-stream" -#define XILINX_AXI_DMA(obj) \ - OBJECT_CHECK(XilinxAXIDMA, (obj), TYPE_XILINX_AXI_DMA) +OBJECT_DECLARE_SIMPLE_TYPE(XilinxAXIDMA, XILINX_AXI_DMA) -#define XILINX_AXI_DMA_DATA_STREAM(obj) \ - OBJECT_CHECK(XilinxAXIDMAStreamSlave, (obj),\ - TYPE_XILINX_AXI_DMA_DATA_STREAM) +typedef struct XilinxAXIDMAStreamSlave XilinxAXIDMAStreamSlave; +DECLARE_INSTANCE_CHECKER(XilinxAXIDMAStreamSlave, XILINX_AXI_DMA_DATA_STREAM, + TYPE_XILINX_AXI_DMA_DATA_STREAM) -#define XILINX_AXI_DMA_CONTROL_STREAM(obj) \ - OBJECT_CHECK(XilinxAXIDMAStreamSlave, (obj),\ - TYPE_XILINX_AXI_DMA_CONTROL_STREAM) +DECLARE_INSTANCE_CHECKER(XilinxAXIDMAStreamSlave, XILINX_AXI_DMA_CONTROL_STREAM, + TYPE_XILINX_AXI_DMA_CONTROL_STREAM) #define R_DMACR (0x00 / 4) #define R_DMASR (0x04 / 4) @@ -62,8 +61,6 @@ #define CONTROL_PAYLOAD_WORDS 5 #define CONTROL_PAYLOAD_SIZE (CONTROL_PAYLOAD_WORDS * (sizeof(uint32_t))) -typedef struct XilinxAXIDMA XilinxAXIDMA; -typedef struct XilinxAXIDMAStreamSlave XilinxAXIDMAStreamSlave; enum { DMACR_RUNSTOP = 1, @@ -537,7 +534,6 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp) XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(&s->rx_data_dev); XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM( &s->rx_control_dev); - Error *local_err = NULL; int i; object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA, @@ -548,11 +544,8 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp) (Object **)&cs->dma, object_property_allow_set_link, OBJ_PROP_LINK_STRONG); - object_property_set_link(OBJECT(ds), OBJECT(s), "dma", &local_err); - object_property_set_link(OBJECT(cs), OBJECT(s), "dma", &local_err); - if (local_err) { - goto xilinx_axidma_realize_fail; - } + object_property_set_link(OBJECT(ds), "dma", OBJECT(s), &error_abort); + object_property_set_link(OBJECT(cs), "dma", OBJECT(s), &error_abort); for (i = 0; i < 2; i++) { struct Stream *st = &s->streams[i]; @@ -567,10 +560,6 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp) address_space_init(&s->as, s->dma_mr ? s->dma_mr : get_system_memory(), "dma"); - return; - -xilinx_axidma_realize_fail: - error_propagate(errp, local_err); } static void xilinx_axidma_init(Object *obj) @@ -579,13 +568,10 @@ static void xilinx_axidma_init(Object *obj) SysBusDevice *sbd = SYS_BUS_DEVICE(obj); object_initialize_child(OBJECT(s), "axistream-connected-target", - &s->rx_data_dev, sizeof(s->rx_data_dev), - TYPE_XILINX_AXI_DMA_DATA_STREAM, &error_abort, - NULL); + &s->rx_data_dev, TYPE_XILINX_AXI_DMA_DATA_STREAM); object_initialize_child(OBJECT(s), "axistream-control-connected-target", - &s->rx_control_dev, sizeof(s->rx_control_dev), - TYPE_XILINX_AXI_DMA_CONTROL_STREAM, &error_abort, - NULL); + &s->rx_control_dev, + TYPE_XILINX_AXI_DMA_CONTROL_STREAM); object_property_add_link(obj, "dma", TYPE_MEMORY_REGION, (Object **)&s->dma_mr, qdev_prop_allow_set_link_before_realize, @@ -645,7 +631,7 @@ static const TypeInfo axidma_info = { static const TypeInfo xilinx_axidma_data_stream_info = { .name = TYPE_XILINX_AXI_DMA_DATA_STREAM, .parent = TYPE_OBJECT, - .instance_size = sizeof(struct XilinxAXIDMAStreamSlave), + .instance_size = sizeof(XilinxAXIDMAStreamSlave), .class_init = xilinx_axidma_stream_class_init, .class_data = &xilinx_axidma_data_stream_class, .interfaces = (InterfaceInfo[]) { @@ -657,7 +643,7 @@ static const TypeInfo xilinx_axidma_data_stream_info = { static const TypeInfo xilinx_axidma_control_stream_info = { .name = TYPE_XILINX_AXI_DMA_CONTROL_STREAM, .parent = TYPE_OBJECT, - .instance_size = sizeof(struct XilinxAXIDMAStreamSlave), + .instance_size = sizeof(XilinxAXIDMAStreamSlave), .class_init = xilinx_axidma_stream_class_init, .class_data = &xilinx_axidma_control_stream_class, .interfaces = (InterfaceInfo[]) { diff --git a/hw/dma/xlnx_dpdma.c b/hw/dma/xlnx_dpdma.c index b40c897de2c7eac7d5b56b1b13e408e6d1e6f700..967548abd3158ed687bc5abc2779849a06ca070b 100644 --- a/hw/dma/xlnx_dpdma.c +++ b/hw/dma/xlnx_dpdma.c @@ -388,7 +388,7 @@ static void xlnx_dpdma_dump_descriptor(DPDMADescriptor *desc) { if (DEBUG_DPDMA) { qemu_log("DUMP DESCRIPTOR:\n"); - qemu_hexdump((char *)desc, stdout, "", sizeof(DPDMADescriptor)); + qemu_hexdump(stdout, "", desc, sizeof(DPDMADescriptor)); } } diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig index 9227cb55987fd76b88f517839095508648b97e53..b6fdaa2586d028a70b13cd5b8e6fb2ea993a5df8 100644 --- a/hw/gpio/Kconfig +++ b/hw/gpio/Kconfig @@ -7,3 +7,6 @@ config PL061 config GPIO_KEY bool + +config SIFIVE_GPIO + bool diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs deleted file mode 100644 index 3cfc261f9b7462e9af60d3cea2636eef43e5d3ca..0000000000000000000000000000000000000000 --- a/hw/gpio/Makefile.objs +++ /dev/null @@ -1,12 +0,0 @@ -common-obj-$(CONFIG_MAX7310) += max7310.o -common-obj-$(CONFIG_PL061) += pl061.o -common-obj-$(CONFIG_PUV3) += puv3_gpio.o -common-obj-$(CONFIG_ZAURUS) += zaurus.o -common-obj-$(CONFIG_E500) += mpc8xxx.o -common-obj-$(CONFIG_GPIO_KEY) += gpio_key.o - -common-obj-$(CONFIG_OMAP) += omap_gpio.o -common-obj-$(CONFIG_IMX) += imx_gpio.o -common-obj-$(CONFIG_RASPI) += bcm2835_gpio.o -common-obj-$(CONFIG_NRF51_SOC) += nrf51_gpio.o -common-obj-$(CONFIG_ASPEED_SOC) += aspeed_gpio.o diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c index dfa9db3d333a1ea3fb315dabddfad3da062d0012..985a259e05b72f4c280ba3ab239edf059c20f421 100644 --- a/hw/gpio/aspeed_gpio.c +++ b/hw/gpio/aspeed_gpio.c @@ -755,16 +755,13 @@ static void aspeed_gpio_get_pin(Object *obj, Visitor *v, const char *name, static void aspeed_gpio_set_pin(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - Error *local_err = NULL; bool level; int pin = 0xfff; char group[4]; AspeedGPIOState *s = ASPEED_GPIO(obj); int set_idx, group_idx = 0; - visit_type_bool(v, name, &level, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_bool(v, name, &level, errp)) { return; } if (sscanf(name, "gpio%2[A-Z]%1d", group, &pin) != 2) { diff --git a/hw/gpio/bcm2835_gpio.c b/hw/gpio/bcm2835_gpio.c index 91ce3d10cc8ea69e531db57337da74db3e3d580b..abdddbc67c2202bb61cd11f49bca881f08bb6b36 100644 --- a/hw/gpio/bcm2835_gpio.c +++ b/hw/gpio/bcm2835_gpio.c @@ -312,22 +312,11 @@ static void bcm2835_gpio_realize(DeviceState *dev, Error **errp) { BCM2835GpioState *s = BCM2835_GPIO(dev); Object *obj; - Error *err = NULL; - obj = object_property_get_link(OBJECT(dev), "sdbus-sdhci", &err); - if (obj == NULL) { - error_setg(errp, "%s: required sdhci link not found: %s", - __func__, error_get_pretty(err)); - return; - } + obj = object_property_get_link(OBJECT(dev), "sdbus-sdhci", &error_abort); s->sdbus_sdhci = SD_BUS(obj); - obj = object_property_get_link(OBJECT(dev), "sdbus-sdhost", &err); - if (obj == NULL) { - error_setg(errp, "%s: required sdhost link not found: %s", - __func__, error_get_pretty(err)); - return; - } + obj = object_property_get_link(OBJECT(dev), "sdbus-sdhost", &error_abort); s->sdbus_sdhost = SD_BUS(obj); } diff --git a/hw/gpio/gpio_key.c b/hw/gpio/gpio_key.c index 46bbd427720d27b66d35f2bd52ea92eacdd98e96..74f61383562dae28288333f02f7b2562d10a0111 100644 --- a/hw/gpio/gpio_key.c +++ b/hw/gpio/gpio_key.c @@ -28,17 +28,18 @@ #include "migration/vmstate.h" #include "qemu/module.h" #include "qemu/timer.h" +#include "qom/object.h" #define TYPE_GPIOKEY "gpio-key" -#define GPIOKEY(obj) OBJECT_CHECK(GPIOKEYState, (obj), TYPE_GPIOKEY) +OBJECT_DECLARE_SIMPLE_TYPE(GPIOKEYState, GPIOKEY) #define GPIO_KEY_LATENCY 100 /* 100ms */ -typedef struct GPIOKEYState { +struct GPIOKEYState { SysBusDevice parent_obj; QEMUTimer *timer; qemu_irq irq; -} GPIOKEYState; +}; static const VMStateDescription vmstate_gpio_key = { .name = "gpio-key", diff --git a/hw/gpio/max7310.c b/hw/gpio/max7310.c index bebb4030d276704c110947ef214a711c4d61fe9a..db6b5e3d764e5a970207b68856c08495c94586a6 100644 --- a/hw/gpio/max7310.c +++ b/hw/gpio/max7310.c @@ -8,17 +8,17 @@ */ #include "qemu/osdep.h" -#include "hw/hw.h" #include "hw/i2c/i2c.h" -#include "hw/hw.h" #include "hw/irq.h" #include "migration/vmstate.h" +#include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" #define TYPE_MAX7310 "max7310" -#define MAX7310(obj) OBJECT_CHECK(MAX7310State, (obj), TYPE_MAX7310) +OBJECT_DECLARE_SIMPLE_TYPE(MAX7310State, MAX7310) -typedef struct MAX7310State { +struct MAX7310State { I2CSlave parent_obj; int i2c_command_byte; @@ -31,7 +31,7 @@ typedef struct MAX7310State { uint8_t command; qemu_irq handler[8]; qemu_irq *gpio_in; -} MAX7310State; +}; static void max7310_reset(DeviceState *dev) { @@ -51,11 +51,9 @@ static uint8_t max7310_rx(I2CSlave *i2c) switch (s->command) { case 0x00: /* Input port */ return s->level ^ s->polarity; - break; case 0x01: /* Output port */ return s->level & ~s->direction; - break; case 0x02: /* Polarity inversion */ return s->polarity; @@ -65,15 +63,13 @@ static uint8_t max7310_rx(I2CSlave *i2c) case 0x04: /* Timeout */ return s->status; - break; case 0xff: /* Reserved */ return 0xff; default: -#ifdef VERBOSE - printf("%s: unknown register %02x\n", __func__, s->command); -#endif + qemu_log_mask(LOG_UNIMP, "%s: Unsupported register 0x02%" PRIx8 "\n", + __func__, s->command); break; } return 0xff; @@ -125,9 +121,8 @@ static int max7310_tx(I2CSlave *i2c, uint8_t data) case 0x00: /* Input port - ignore writes */ break; default: -#ifdef VERBOSE - printf("%s: unknown register %02x\n", __func__, s->command); -#endif + qemu_log_mask(LOG_UNIMP, "%s: Unsupported register 0x02%" PRIx8 "\n", + __func__, s->command); return 1; } @@ -176,8 +171,7 @@ static const VMStateDescription vmstate_max7310 = { static void max7310_gpio_set(void *opaque, int line, int level) { MAX7310State *s = (MAX7310State *) opaque; - if (line >= ARRAY_SIZE(s->handler) || line < 0) - hw_error("bad GPIO line"); + assert(line >= 0 && line < ARRAY_SIZE(s->handler)); if (level) s->level |= s->direction & (1 << line); diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..5c0a7d7b95ab48386fe12862bb08b29986768cfb --- /dev/null +++ b/hw/gpio/meson.build @@ -0,0 +1,14 @@ +softmmu_ss.add(when: 'CONFIG_E500', if_true: files('mpc8xxx.c')) +softmmu_ss.add(when: 'CONFIG_GPIO_KEY', if_true: files('gpio_key.c')) +softmmu_ss.add(when: 'CONFIG_MAX7310', if_true: files('max7310.c')) +softmmu_ss.add(when: 'CONFIG_PL061', if_true: files('pl061.c')) +softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_gpio.c')) +softmmu_ss.add(when: 'CONFIG_ZAURUS', if_true: files('zaurus.c')) + +softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_gpio.c')) +softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_gpio.c')) +softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_gpio.c')) +softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_gpio.c')) +softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_gpio.c')) +softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c')) +softmmu_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c')) diff --git a/hw/gpio/mpc8xxx.c b/hw/gpio/mpc8xxx.c index 1d99667094c3b1099f328ce79fbbcc2d9b2def19..cb42acb6da83e43e99989dd61dbd8c0d6c7440cb 100644 --- a/hw/gpio/mpc8xxx.c +++ b/hw/gpio/mpc8xxx.c @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -24,11 +24,12 @@ #include "hw/sysbus.h" #include "migration/vmstate.h" #include "qemu/module.h" +#include "qom/object.h" #define TYPE_MPC8XXX_GPIO "mpc8xxx_gpio" -#define MPC8XXX_GPIO(obj) OBJECT_CHECK(MPC8XXXGPIOState, (obj), TYPE_MPC8XXX_GPIO) +OBJECT_DECLARE_SIMPLE_TYPE(MPC8XXXGPIOState, MPC8XXX_GPIO) -typedef struct MPC8XXXGPIOState { +struct MPC8XXXGPIOState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -41,7 +42,7 @@ typedef struct MPC8XXXGPIOState { uint32_t ier; uint32_t imr; uint32_t icr; -} MPC8XXXGPIOState; +}; static const VMStateDescription vmstate_mpc8xxx_gpio = { .name = "mpc8xxx_gpio", diff --git a/hw/gpio/npcm7xx_gpio.c b/hw/gpio/npcm7xx_gpio.c new file mode 100644 index 0000000000000000000000000000000000000000..3376901ab13ec8053137ddbd9bc8fa686495deb1 --- /dev/null +++ b/hw/gpio/npcm7xx_gpio.c @@ -0,0 +1,424 @@ +/* + * Nuvoton NPCM7xx General Purpose Input / Output (GPIO) + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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. + */ + +#include "qemu/osdep.h" + +#include "hw/gpio/npcm7xx_gpio.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "migration/vmstate.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/units.h" +#include "trace.h" + +/* 32-bit register indices. */ +enum NPCM7xxGPIORegister { + NPCM7XX_GPIO_TLOCK1, + NPCM7XX_GPIO_DIN, + NPCM7XX_GPIO_POL, + NPCM7XX_GPIO_DOUT, + NPCM7XX_GPIO_OE, + NPCM7XX_GPIO_OTYP, + NPCM7XX_GPIO_MP, + NPCM7XX_GPIO_PU, + NPCM7XX_GPIO_PD, + NPCM7XX_GPIO_DBNC, + NPCM7XX_GPIO_EVTYP, + NPCM7XX_GPIO_EVBE, + NPCM7XX_GPIO_OBL0, + NPCM7XX_GPIO_OBL1, + NPCM7XX_GPIO_OBL2, + NPCM7XX_GPIO_OBL3, + NPCM7XX_GPIO_EVEN, + NPCM7XX_GPIO_EVENS, + NPCM7XX_GPIO_EVENC, + NPCM7XX_GPIO_EVST, + NPCM7XX_GPIO_SPLCK, + NPCM7XX_GPIO_MPLCK, + NPCM7XX_GPIO_IEM, + NPCM7XX_GPIO_OSRC, + NPCM7XX_GPIO_ODSC, + NPCM7XX_GPIO_DOS = 0x68 / sizeof(uint32_t), + NPCM7XX_GPIO_DOC, + NPCM7XX_GPIO_OES, + NPCM7XX_GPIO_OEC, + NPCM7XX_GPIO_TLOCK2 = 0x7c / sizeof(uint32_t), + NPCM7XX_GPIO_REGS_END, +}; + +#define NPCM7XX_GPIO_REGS_SIZE (4 * KiB) + +#define NPCM7XX_GPIO_LOCK_MAGIC1 (0xc0defa73) +#define NPCM7XX_GPIO_LOCK_MAGIC2 (0xc0de1248) + +static void npcm7xx_gpio_update_events(NPCM7xxGPIOState *s, uint32_t din_diff) +{ + uint32_t din_new = s->regs[NPCM7XX_GPIO_DIN]; + + /* Trigger on high level */ + s->regs[NPCM7XX_GPIO_EVST] |= din_new & ~s->regs[NPCM7XX_GPIO_EVTYP]; + /* Trigger on both edges */ + s->regs[NPCM7XX_GPIO_EVST] |= (din_diff & s->regs[NPCM7XX_GPIO_EVTYP] + & s->regs[NPCM7XX_GPIO_EVBE]); + /* Trigger on rising edge */ + s->regs[NPCM7XX_GPIO_EVST] |= (din_diff & din_new + & s->regs[NPCM7XX_GPIO_EVTYP]); + + trace_npcm7xx_gpio_update_events(DEVICE(s)->canonical_path, + s->regs[NPCM7XX_GPIO_EVST], + s->regs[NPCM7XX_GPIO_EVEN]); + qemu_set_irq(s->irq, !!(s->regs[NPCM7XX_GPIO_EVST] + & s->regs[NPCM7XX_GPIO_EVEN])); +} + +static void npcm7xx_gpio_update_pins(NPCM7xxGPIOState *s, uint32_t diff) +{ + uint32_t drive_en; + uint32_t drive_lvl; + uint32_t not_driven; + uint32_t undefined; + uint32_t pin_diff; + uint32_t din_old; + + /* Calculate level of each pin driven by GPIO controller. */ + drive_lvl = s->regs[NPCM7XX_GPIO_DOUT] ^ s->regs[NPCM7XX_GPIO_POL]; + /* If OTYP=1, only drive low (open drain) */ + drive_en = s->regs[NPCM7XX_GPIO_OE] & ~(s->regs[NPCM7XX_GPIO_OTYP] + & drive_lvl); + /* + * If a pin is driven to opposite levels by the GPIO controller and the + * external driver, the result is undefined. + */ + undefined = drive_en & s->ext_driven & (drive_lvl ^ s->ext_level); + if (undefined) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: pins have multiple drivers: 0x%" PRIx32 "\n", + DEVICE(s)->canonical_path, undefined); + } + + not_driven = ~(drive_en | s->ext_driven); + pin_diff = s->pin_level; + + /* Set pins to externally driven level. */ + s->pin_level = s->ext_level & s->ext_driven; + /* Set internally driven pins, ignoring any conflicts. */ + s->pin_level |= drive_lvl & drive_en; + /* Pull up undriven pins with internal pull-up enabled. */ + s->pin_level |= not_driven & s->regs[NPCM7XX_GPIO_PU]; + /* Pins not driven, pulled up or pulled down are undefined */ + undefined |= not_driven & ~(s->regs[NPCM7XX_GPIO_PU] + | s->regs[NPCM7XX_GPIO_PD]); + + /* If any pins changed state, update the outgoing GPIOs. */ + pin_diff ^= s->pin_level; + pin_diff |= undefined & diff; + if (pin_diff) { + int i; + + for (i = 0; i < NPCM7XX_GPIO_NR_PINS; i++) { + uint32_t mask = BIT(i); + if (pin_diff & mask) { + int level = (undefined & mask) ? -1 : !!(s->pin_level & mask); + trace_npcm7xx_gpio_set_output(DEVICE(s)->canonical_path, + i, level); + qemu_set_irq(s->output[i], level); + } + } + } + + /* Calculate new value of DIN after masking and polarity setting. */ + din_old = s->regs[NPCM7XX_GPIO_DIN]; + s->regs[NPCM7XX_GPIO_DIN] = ((s->pin_level & s->regs[NPCM7XX_GPIO_IEM]) + ^ s->regs[NPCM7XX_GPIO_POL]); + + /* See if any new events triggered because of all this. */ + npcm7xx_gpio_update_events(s, din_old ^ s->regs[NPCM7XX_GPIO_DIN]); +} + +static bool npcm7xx_gpio_is_locked(NPCM7xxGPIOState *s) +{ + return s->regs[NPCM7XX_GPIO_TLOCK1] == 1; +} + +static uint64_t npcm7xx_gpio_regs_read(void *opaque, hwaddr addr, + unsigned int size) +{ + hwaddr reg = addr / sizeof(uint32_t); + NPCM7xxGPIOState *s = opaque; + uint64_t value = 0; + + switch (reg) { + case NPCM7XX_GPIO_TLOCK1 ... NPCM7XX_GPIO_EVEN: + case NPCM7XX_GPIO_EVST ... NPCM7XX_GPIO_ODSC: + value = s->regs[reg]; + break; + + case NPCM7XX_GPIO_EVENS ... NPCM7XX_GPIO_EVENC: + case NPCM7XX_GPIO_DOS ... NPCM7XX_GPIO_TLOCK2: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: read from write-only register 0x%" HWADDR_PRIx "\n", + DEVICE(s)->canonical_path, addr); + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: read from invalid offset 0x%" HWADDR_PRIx "\n", + DEVICE(s)->canonical_path, addr); + break; + } + + trace_npcm7xx_gpio_read(DEVICE(s)->canonical_path, addr, value); + + return value; +} + +static void npcm7xx_gpio_regs_write(void *opaque, hwaddr addr, uint64_t v, + unsigned int size) +{ + hwaddr reg = addr / sizeof(uint32_t); + NPCM7xxGPIOState *s = opaque; + uint32_t value = v; + uint32_t diff; + + trace_npcm7xx_gpio_write(DEVICE(s)->canonical_path, addr, v); + + if (npcm7xx_gpio_is_locked(s)) { + switch (reg) { + case NPCM7XX_GPIO_TLOCK1: + if (s->regs[NPCM7XX_GPIO_TLOCK2] == NPCM7XX_GPIO_LOCK_MAGIC2 && + value == NPCM7XX_GPIO_LOCK_MAGIC1) { + s->regs[NPCM7XX_GPIO_TLOCK1] = 0; + s->regs[NPCM7XX_GPIO_TLOCK2] = 0; + } + break; + + case NPCM7XX_GPIO_TLOCK2: + s->regs[reg] = value; + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: write to locked register @ 0x%" HWADDR_PRIx "\n", + DEVICE(s)->canonical_path, addr); + break; + } + + return; + } + + diff = s->regs[reg] ^ value; + + switch (reg) { + case NPCM7XX_GPIO_TLOCK1: + case NPCM7XX_GPIO_TLOCK2: + s->regs[NPCM7XX_GPIO_TLOCK1] = 1; + s->regs[NPCM7XX_GPIO_TLOCK2] = 0; + break; + + case NPCM7XX_GPIO_DIN: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: write to read-only register @ 0x%" HWADDR_PRIx "\n", + DEVICE(s)->canonical_path, addr); + break; + + case NPCM7XX_GPIO_POL: + case NPCM7XX_GPIO_DOUT: + case NPCM7XX_GPIO_OE: + case NPCM7XX_GPIO_OTYP: + case NPCM7XX_GPIO_PU: + case NPCM7XX_GPIO_PD: + case NPCM7XX_GPIO_IEM: + s->regs[reg] = value; + npcm7xx_gpio_update_pins(s, diff); + break; + + case NPCM7XX_GPIO_DOS: + s->regs[NPCM7XX_GPIO_DOUT] |= value; + npcm7xx_gpio_update_pins(s, value); + break; + case NPCM7XX_GPIO_DOC: + s->regs[NPCM7XX_GPIO_DOUT] &= ~value; + npcm7xx_gpio_update_pins(s, value); + break; + case NPCM7XX_GPIO_OES: + s->regs[NPCM7XX_GPIO_OE] |= value; + npcm7xx_gpio_update_pins(s, value); + break; + case NPCM7XX_GPIO_OEC: + s->regs[NPCM7XX_GPIO_OE] &= ~value; + npcm7xx_gpio_update_pins(s, value); + break; + + case NPCM7XX_GPIO_EVTYP: + case NPCM7XX_GPIO_EVBE: + case NPCM7XX_GPIO_EVEN: + s->regs[reg] = value; + npcm7xx_gpio_update_events(s, 0); + break; + + case NPCM7XX_GPIO_EVENS: + s->regs[NPCM7XX_GPIO_EVEN] |= value; + npcm7xx_gpio_update_events(s, 0); + break; + case NPCM7XX_GPIO_EVENC: + s->regs[NPCM7XX_GPIO_EVEN] &= ~value; + npcm7xx_gpio_update_events(s, 0); + break; + + case NPCM7XX_GPIO_EVST: + s->regs[reg] &= ~value; + npcm7xx_gpio_update_events(s, 0); + break; + + case NPCM7XX_GPIO_MP: + case NPCM7XX_GPIO_DBNC: + case NPCM7XX_GPIO_OSRC: + case NPCM7XX_GPIO_ODSC: + /* Nothing to do; just store the value. */ + s->regs[reg] = value; + break; + + case NPCM7XX_GPIO_OBL0: + case NPCM7XX_GPIO_OBL1: + case NPCM7XX_GPIO_OBL2: + case NPCM7XX_GPIO_OBL3: + s->regs[reg] = value; + qemu_log_mask(LOG_UNIMP, "%s: Blinking is not implemented\n", + __func__); + break; + + case NPCM7XX_GPIO_SPLCK: + case NPCM7XX_GPIO_MPLCK: + qemu_log_mask(LOG_UNIMP, "%s: Per-pin lock is not implemented\n", + __func__); + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: write to invalid offset 0x%" HWADDR_PRIx "\n", + DEVICE(s)->canonical_path, addr); + break; + } +} + +static const MemoryRegionOps npcm7xx_gpio_regs_ops = { + .read = npcm7xx_gpio_regs_read, + .write = npcm7xx_gpio_regs_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + .unaligned = false, + }, +}; + +static void npcm7xx_gpio_set_input(void *opaque, int line, int level) +{ + NPCM7xxGPIOState *s = opaque; + + trace_npcm7xx_gpio_set_input(DEVICE(s)->canonical_path, line, level); + + g_assert(line >= 0 && line < NPCM7XX_GPIO_NR_PINS); + + s->ext_driven = deposit32(s->ext_driven, line, 1, level >= 0); + s->ext_level = deposit32(s->ext_level, line, 1, level > 0); + + npcm7xx_gpio_update_pins(s, BIT(line)); +} + +static void npcm7xx_gpio_enter_reset(Object *obj, ResetType type) +{ + NPCM7xxGPIOState *s = NPCM7XX_GPIO(obj); + + memset(s->regs, 0, sizeof(s->regs)); + + s->regs[NPCM7XX_GPIO_PU] = s->reset_pu; + s->regs[NPCM7XX_GPIO_PD] = s->reset_pd; + s->regs[NPCM7XX_GPIO_OSRC] = s->reset_osrc; + s->regs[NPCM7XX_GPIO_ODSC] = s->reset_odsc; +} + +static void npcm7xx_gpio_hold_reset(Object *obj) +{ + NPCM7xxGPIOState *s = NPCM7XX_GPIO(obj); + + npcm7xx_gpio_update_pins(s, -1); +} + +static void npcm7xx_gpio_init(Object *obj) +{ + NPCM7xxGPIOState *s = NPCM7XX_GPIO(obj); + DeviceState *dev = DEVICE(obj); + + memory_region_init_io(&s->mmio, obj, &npcm7xx_gpio_regs_ops, s, + "regs", NPCM7XX_GPIO_REGS_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); + + qdev_init_gpio_in(dev, npcm7xx_gpio_set_input, NPCM7XX_GPIO_NR_PINS); + qdev_init_gpio_out(dev, s->output, NPCM7XX_GPIO_NR_PINS); +} + +static const VMStateDescription vmstate_npcm7xx_gpio = { + .name = "npcm7xx-gpio", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32(pin_level, NPCM7xxGPIOState), + VMSTATE_UINT32(ext_level, NPCM7xxGPIOState), + VMSTATE_UINT32(ext_driven, NPCM7xxGPIOState), + VMSTATE_UINT32_ARRAY(regs, NPCM7xxGPIOState, NPCM7XX_GPIO_NR_REGS), + VMSTATE_END_OF_LIST(), + }, +}; + +static Property npcm7xx_gpio_properties[] = { + /* Bit n set => pin n has pullup enabled by default. */ + DEFINE_PROP_UINT32("reset-pullup", NPCM7xxGPIOState, reset_pu, 0), + /* Bit n set => pin n has pulldown enabled by default. */ + DEFINE_PROP_UINT32("reset-pulldown", NPCM7xxGPIOState, reset_pd, 0), + /* Bit n set => pin n has high slew rate by default. */ + DEFINE_PROP_UINT32("reset-osrc", NPCM7xxGPIOState, reset_osrc, 0), + /* Bit n set => pin n has high drive strength by default. */ + DEFINE_PROP_UINT32("reset-odsc", NPCM7xxGPIOState, reset_odsc, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void npcm7xx_gpio_class_init(ObjectClass *klass, void *data) +{ + ResettableClass *reset = RESETTABLE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + QEMU_BUILD_BUG_ON(NPCM7XX_GPIO_REGS_END > NPCM7XX_GPIO_NR_REGS); + + dc->desc = "NPCM7xx GPIO Controller"; + dc->vmsd = &vmstate_npcm7xx_gpio; + reset->phases.enter = npcm7xx_gpio_enter_reset; + reset->phases.hold = npcm7xx_gpio_hold_reset; + device_class_set_props(dc, npcm7xx_gpio_properties); +} + +static const TypeInfo npcm7xx_gpio_types[] = { + { + .name = TYPE_NPCM7XX_GPIO, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(NPCM7xxGPIOState), + .class_init = npcm7xx_gpio_class_init, + .instance_init = npcm7xx_gpio_init, + }, +}; +DEFINE_TYPES(npcm7xx_gpio_types); diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c index f662c4cb9588b07592cfd7068d6e3e27509f128a..e25084b40c9550733436c77f18fd34a3a67fcd79 100644 --- a/hw/gpio/omap_gpio.c +++ b/hw/gpio/omap_gpio.c @@ -392,8 +392,10 @@ static void omap2_gpio_module_write(void *opaque, hwaddr addr, break; case 0x10: /* GPIO_SYSCONFIG */ - if (((value >> 3) & 3) == 3) - fprintf(stderr, "%s: bad IDLEMODE value\n", __func__); + if (((value >> 3) & 3) == 3) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Illegal IDLEMODE value: 3\n", __func__); + } if (value & 2) omap2_gpio_module_reset(s); s->config[0] = value & 0x1d; diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c index 6d3c36bc16cf9e0d649425cb7e193f665dad69d4..e72e77572a04f9998f0823bf6080e0cc9354a794 100644 --- a/hw/gpio/pl061.c +++ b/hw/gpio/pl061.c @@ -14,6 +14,7 @@ #include "migration/vmstate.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" //#define DEBUG_PL061 1 @@ -34,11 +35,11 @@ static const uint8_t pl061_id_luminary[12] = { 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 }; #define TYPE_PL061 "pl061" -#define PL061(obj) OBJECT_CHECK(PL061State, (obj), TYPE_PL061) +OBJECT_DECLARE_SIMPLE_TYPE(PL061State, PL061) #define N_GPIOS 8 -typedef struct PL061State { +struct PL061State { SysBusDevice parent_obj; MemoryRegion iomem; @@ -67,7 +68,7 @@ typedef struct PL061State { qemu_irq out[N_GPIOS]; const unsigned char *id; uint32_t rsvd_start; /* reserved area: [rsvd_start, 0xfcc] */ -} PL061State; +}; static const VMStateDescription vmstate_pl061 = { .name = "pl061", diff --git a/hw/gpio/puv3_gpio.c b/hw/gpio/puv3_gpio.c index d19e3425140ebd77faf1176b9476e08573f71e3f..e003ae505cfc409e0ccff63817d3407fe81d520f 100644 --- a/hw/gpio/puv3_gpio.c +++ b/hw/gpio/puv3_gpio.c @@ -11,15 +11,17 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" +#include "qom/object.h" #undef DEBUG_PUV3 #include "hw/unicore32/puv3.h" #include "qemu/module.h" +#include "qemu/log.h" #define TYPE_PUV3_GPIO "puv3_gpio" -#define PUV3_GPIO(obj) OBJECT_CHECK(PUV3GPIOState, (obj), TYPE_PUV3_GPIO) +OBJECT_DECLARE_SIMPLE_TYPE(PUV3GPIOState, PUV3_GPIO) -typedef struct PUV3GPIOState { +struct PUV3GPIOState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -28,7 +30,7 @@ typedef struct PUV3GPIOState { uint32_t reg_GPLR; uint32_t reg_GPDR; uint32_t reg_GPIR; -} PUV3GPIOState; +}; static uint64_t puv3_gpio_read(void *opaque, hwaddr offset, unsigned size) @@ -47,7 +49,9 @@ static uint64_t puv3_gpio_read(void *opaque, hwaddr offset, ret = s->reg_GPIR; break; default: - DPRINTF("Bad offset 0x%x\n", offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad read offset 0x%"HWADDR_PRIx"\n", + __func__, offset); } DPRINTF("offset 0x%x, value 0x%x\n", offset, ret); @@ -68,14 +72,16 @@ static void puv3_gpio_write(void *opaque, hwaddr offset, if (s->reg_GPDR & value) { s->reg_GPLR |= value; } else { - DPRINTF("Write gpio input port error!"); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Write gpio input port\n", + __func__); } break; case 0x0c: if (s->reg_GPDR & value) { s->reg_GPLR &= ~value; } else { - DPRINTF("Write gpio input port error!"); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Write gpio input port\n", + __func__); } break; case 0x10: /* GRER */ @@ -86,7 +92,9 @@ static void puv3_gpio_write(void *opaque, hwaddr offset, s->reg_GPIR = value; break; default: - DPRINTF("Bad offset 0x%x\n", offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad write offset 0x%"HWADDR_PRIx"\n", + __func__, offset); } } diff --git a/hw/riscv/sifive_gpio.c b/hw/gpio/sifive_gpio.c similarity index 88% rename from hw/riscv/sifive_gpio.c rename to hw/gpio/sifive_gpio.c index 5c7c596e6b4e5b932e823d7340323c40e955d9c6..78bf29e996f923fcec37baaf636ec8d6ceecc91d 100644 --- a/hw/riscv/sifive_gpio.c +++ b/hw/gpio/sifive_gpio.c @@ -1,5 +1,5 @@ /* - * sifive System-on-Chip general purpose input/output register definition + * SiFive System-on-Chip general purpose input/output register definition * * Copyright 2019 AdaCore * @@ -14,13 +14,13 @@ #include "qemu/osdep.h" #include "qemu/log.h" #include "hw/irq.h" -#include "hw/riscv/sifive_gpio.h" +#include "hw/qdev-properties.h" +#include "hw/gpio/sifive_gpio.h" #include "migration/vmstate.h" #include "trace.h" static void update_output_irq(SIFIVEGPIOState *s) { - uint32_t pending; uint32_t pin; @@ -29,7 +29,7 @@ static void update_output_irq(SIFIVEGPIOState *s) pending |= s->rise_ip & s->rise_ie; pending |= s->fall_ip & s->fall_ie; - for (int i = 0; i < SIFIVE_GPIO_PINS; i++) { + for (int i = 0; i < s->ngpio; i++) { pin = 1 << i; qemu_set_irq(s->irq[i], (pending & pin) != 0); trace_sifive_gpio_update_output_irq(i, (pending & pin) != 0); @@ -42,7 +42,7 @@ static void update_state(SIFIVEGPIOState *s) bool prev_ival, in, in_mask, port, out_xor, pull, output_en, input_en, rise_ip, fall_ip, low_ip, high_ip, oval, actual_value, ival; - for (i = 0; i < SIFIVE_GPIO_PINS; i++) { + for (i = 0; i < s->ngpio; i++) { prev_ival = extract32(s->value, i, 1); in = extract32(s->in, i, 1); @@ -76,7 +76,9 @@ static void update_state(SIFIVEGPIOState *s) actual_value = pull; } - qemu_set_irq(s->output[i], actual_value); + if (output_en) { + qemu_set_irq(s->output[i], actual_value); + } /* Input value */ ival = input_en && actual_value; @@ -186,7 +188,7 @@ static uint64_t sifive_gpio_read(void *opaque, hwaddr offset, unsigned int size) } static void sifive_gpio_write(void *opaque, hwaddr offset, - uint64_t value, unsigned int size) + uint64_t value, unsigned int size) { SIFIVEGPIOState *s = SIFIVE_GPIO(opaque); @@ -318,7 +320,6 @@ static void sifive_gpio_reset(DeviceState *dev) s->out_xor = 0; s->in = 0; s->in_mask = 0; - } static const VMStateDescription vmstate_sifive_gpio = { @@ -342,43 +343,49 @@ static const VMStateDescription vmstate_sifive_gpio = { VMSTATE_UINT32(iof_en, SIFIVEGPIOState), VMSTATE_UINT32(iof_sel, SIFIVEGPIOState), VMSTATE_UINT32(out_xor, SIFIVEGPIOState), - VMSTATE_UINT32(in, SIFIVEGPIOState), - VMSTATE_UINT32(in_mask, SIFIVEGPIOState), + VMSTATE_UINT32(in, SIFIVEGPIOState), + VMSTATE_UINT32(in_mask, SIFIVEGPIOState), VMSTATE_END_OF_LIST() } }; -static void sifive_gpio_init(Object *obj) +static Property sifive_gpio_properties[] = { + DEFINE_PROP_UINT32("ngpio", SIFIVEGPIOState, ngpio, SIFIVE_GPIO_PINS), + DEFINE_PROP_END_OF_LIST(), +}; + +static void sifive_gpio_realize(DeviceState *dev, Error **errp) { - SIFIVEGPIOState *s = SIFIVE_GPIO(obj); + SIFIVEGPIOState *s = SIFIVE_GPIO(dev); - memory_region_init_io(&s->mmio, obj, &gpio_ops, s, + memory_region_init_io(&s->mmio, OBJECT(dev), &gpio_ops, s, TYPE_SIFIVE_GPIO, SIFIVE_GPIO_SIZE); - sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); - for (int i = 0; i < SIFIVE_GPIO_PINS; i++) { - sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq[i]); + for (int i = 0; i < s->ngpio; i++) { + sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]); } - qdev_init_gpio_in(DEVICE(s), sifive_gpio_set, SIFIVE_GPIO_PINS); - qdev_init_gpio_out(DEVICE(s), s->output, SIFIVE_GPIO_PINS); + qdev_init_gpio_in(DEVICE(s), sifive_gpio_set, s->ngpio); + qdev_init_gpio_out(DEVICE(s), s->output, s->ngpio); } static void sifive_gpio_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + device_class_set_props(dc, sifive_gpio_properties); dc->vmsd = &vmstate_sifive_gpio; + dc->realize = sifive_gpio_realize; dc->reset = sifive_gpio_reset; - dc->desc = "sifive GPIO"; + dc->desc = "SiFive GPIO"; } static const TypeInfo sifive_gpio_info = { .name = TYPE_SIFIVE_GPIO, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(SIFIVEGPIOState), - .instance_init = sifive_gpio_init, .class_init = sifive_gpio_class_init }; diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events index c1271fdfb27b77f2d6d3fc1e3eb6a011c00fe048..46ab9323bd09e42c7a5c2736b5805670ffd44462 100644 --- a/hw/gpio/trace-events +++ b/hw/gpio/trace-events @@ -1,7 +1,20 @@ # See docs/devel/tracing.txt for syntax documentation. +# npcm7xx_gpio.c +npcm7xx_gpio_read(const char *id, uint64_t offset, uint64_t value) " %s offset: 0x%04" PRIx64 " value 0x%08" PRIx64 +npcm7xx_gpio_write(const char *id, uint64_t offset, uint64_t value) "%s offset: 0x%04" PRIx64 " value 0x%08" PRIx64 +npcm7xx_gpio_set_input(const char *id, int32_t line, int32_t level) "%s line: %" PRIi32 " level: %" PRIi32 +npcm7xx_gpio_set_output(const char *id, int32_t line, int32_t level) "%s line: %" PRIi32 " level: %" PRIi32 +npcm7xx_gpio_update_events(const char *id, uint32_t evst, uint32_t even) "%s evst: 0x%08" PRIx32 " even: 0x%08" PRIx32 + # nrf51_gpio.c nrf51_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64 nrf51_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64 nrf51_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 nrf51_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 + +# sifive_gpio.c +sifive_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64 +sifive_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64 +sifive_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 +sifive_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 diff --git a/hw/gpio/trace.h b/hw/gpio/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..8b139071bcae5c6aaf18b7d0e67763e22dffeda0 --- /dev/null +++ b/hw/gpio/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_gpio.h" diff --git a/hw/gpio/zaurus.c b/hw/gpio/zaurus.c index 9a12c683420e2f2a2517a3ffa032c6e3be9fbedc..7cf52a50412a765eabb807f2f1a18ca43b7ef485 100644 --- a/hw/gpio/zaurus.c +++ b/hw/gpio/zaurus.c @@ -22,16 +22,14 @@ #include "hw/sysbus.h" #include "migration/vmstate.h" #include "qemu/module.h" - -#undef REG_FMT -#define REG_FMT "0x%02lx" +#include "qemu/log.h" +#include "qom/object.h" /* SCOOP devices */ #define TYPE_SCOOP "scoop" -#define SCOOP(obj) OBJECT_CHECK(ScoopInfo, (obj), TYPE_SCOOP) +OBJECT_DECLARE_SIMPLE_TYPE(ScoopInfo, SCOOP) -typedef struct ScoopInfo ScoopInfo; struct ScoopInfo { SysBusDevice parent_obj; @@ -104,7 +102,9 @@ static uint64_t scoop_read(void *opaque, hwaddr addr, case SCOOP_GPRR: return s->gpio_level; default: - zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr); + qemu_log_mask(LOG_GUEST_ERROR, + "scoop_read: bad register offset 0x%02" HWADDR_PRIx "\n", + addr); } return 0; @@ -150,7 +150,9 @@ static void scoop_write(void *opaque, hwaddr addr, scoop_gpio_handler_update(s); break; default: - zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr); + qemu_log_mask(LOG_GUEST_ERROR, + "scoop_write: bad register offset 0x%02" HWADDR_PRIx "\n", + addr); } } diff --git a/hw/hppa/Makefile.objs b/hw/hppa/Makefile.objs deleted file mode 100644 index eac3467d8a08413bea50fbe7cc172a3bd01bb367..0000000000000000000000000000000000000000 --- a/hw/hppa/Makefile.objs +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_DINO) += pci.o machine.o dino.o lasi.o diff --git a/hw/hppa/dino.c b/hw/hppa/dino.c index 2b1b38c58abc52b59a7632afa400c6e7324be5ee..81053b5fb647b1dedeabc47cd5b1c89f331377d6 100644 --- a/hw/hppa/dino.c +++ b/hw/hppa/dino.c @@ -22,6 +22,7 @@ #include "hppa_sys.h" #include "exec/address-spaces.h" #include "trace.h" +#include "qom/object.h" #define TYPE_DINO_PCI_HOST_BRIDGE "dino-pcihost" @@ -80,8 +81,7 @@ #define DINO_MEM_CHUNK_SIZE (8 * MiB) -#define DINO_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(DinoState, (obj), TYPE_DINO_PCI_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(DinoState, DINO_PCI_HOST_BRIDGE) #define DINO800_REGS (1 + (DINO_TLTIM - DINO_GMASK) / 4) static const uint32_t reg800_keep_bits[DINO800_REGS] = { @@ -100,7 +100,7 @@ static const uint32_t reg800_keep_bits[DINO800_REGS] = { MAKE_64BIT_MASK(0, 9), /* TLTIM */ }; -typedef struct DinoState { +struct DinoState { PCIHostState parent_obj; /* PCI_CONFIG_ADDR is parent_obj.config_reg, via pci_host_conf_be_ops, @@ -129,7 +129,7 @@ typedef struct DinoState { MemoryRegion bm_ram_alias; MemoryRegion bm_pci_alias; MemoryRegion bm_cpu_alias; -} DinoState; +}; /* * Dino can forward memory accesses from the CPU in the range between @@ -521,7 +521,7 @@ PCIBus *dino_init(MemoryRegion *addr_space, PCIBus *b; int i; - dev = qdev_create(NULL, TYPE_DINO_PCI_HOST_BRIDGE); + dev = qdev_new(TYPE_DINO_PCI_HOST_BRIDGE); s = DINO_PCI_HOST_BRIDGE(dev); s->iar0 = s->iar1 = CPU_HPA + 3; s->toc_addr = 0xFFFA0030; /* IO_COMMAND of CPU */ @@ -542,13 +542,13 @@ PCIBus *dino_init(MemoryRegion *addr_space, &s->parent_obj.data_mem); /* Dino PCI bus memory. */ - memory_region_init(&s->pci_mem, OBJECT(s), "pci-memory", 1ull << 32); + memory_region_init(&s->pci_mem, OBJECT(s), "pci-memory", 4 * GiB); b = pci_register_root_bus(dev, "pci", dino_set_irq, dino_pci_map_irq, s, &s->pci_mem, get_system_io(), PCI_DEVFN(0, 0), 32, TYPE_PCI_BUS); s->parent_obj.bus = b; - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); /* Set up windows into PCI bus memory. */ for (i = 1; i < 31; i++) { @@ -561,7 +561,7 @@ PCIBus *dino_init(MemoryRegion *addr_space, } /* Set up PCI view of memory: Bus master address space. */ - memory_region_init(&s->bm, OBJECT(s), "bm-dino", 1ull << 32); + memory_region_init(&s->bm, OBJECT(s), "bm-dino", 4 * GiB); memory_region_init_alias(&s->bm_ram_alias, OBJECT(s), "bm-system", addr_space, 0, 0xf0000000 + DINO_MEM_CHUNK_SIZE); diff --git a/hw/hppa/hppa_hardware.h b/hw/hppa/hppa_hardware.h index 4a2fe2df606883d52c0f307a69650c82f4b0dd98..bc258895c95b47f4dab51a6aa6b8beed081976df 100644 --- a/hw/hppa/hppa_hardware.h +++ b/hw/hppa/hppa_hardware.h @@ -17,6 +17,7 @@ #define LASI_UART_HPA 0xffd05000 #define LASI_SCSI_HPA 0xffd06000 #define LASI_LAN_HPA 0xffd07000 +#define LASI_RTC_HPA 0xffd09000 #define LASI_LPT_HPA 0xffd02000 #define LASI_AUDIO_HPA 0xffd04000 #define LASI_PS2KBD_HPA 0xffd08000 @@ -37,10 +38,14 @@ #define PORT_PCI_CMD (PCI_HPA + DINO_PCI_ADDR) #define PORT_PCI_DATA (PCI_HPA + DINO_CONFIG_DATA) +#define FW_CFG_IO_BASE 0xfffa0000 + #define PORT_SERIAL1 (DINO_UART_HPA + 0x800) #define PORT_SERIAL2 (LASI_UART_HPA + 0x800) #define HPPA_MAX_CPUS 8 /* max. number of SMP CPUs */ #define CPU_CLOCK_MHZ 250 /* emulate a 250 MHz CPU */ +#define CPU_HPA_CR_REG 7 /* store CPU HPA in cr7 (SeaBIOS internal) */ + #endif diff --git a/hw/hppa/lasi.c b/hw/hppa/lasi.c index d8d03f95c026ed8ac17cdd643eef02aa74243ce5..1a8565794846f547c26e83ff6c433b890eb79a17 100644 --- a/hw/hppa/lasi.c +++ b/hw/hppa/lasi.c @@ -11,6 +11,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" +#include "qemu/log.h" #include "qapi/error.h" #include "cpu.h" #include "trace.h" @@ -25,6 +26,7 @@ #include "hw/input/lasips2.h" #include "exec/address-spaces.h" #include "migration/vmstate.h" +#include "qom/object.h" #define TYPE_LASI_CHIP "lasi-chip" @@ -51,12 +53,9 @@ #define ICR_BUS_ERROR_BIT LASI_BIT(8) /* bit 8 in ICR */ #define ICR_TOC_BIT LASI_BIT(1) /* bit 1 in ICR */ -#define LASI_CHIP(obj) \ - OBJECT_CHECK(LasiState, (obj), TYPE_LASI_CHIP) +OBJECT_DECLARE_SIMPLE_TYPE(LasiState, LASI_CHIP) -#define LASI_RTC_HPA (LASI_HPA + 0x9000) - -typedef struct LasiState { +struct LasiState { PCIHostState parent_obj; uint32_t irr; @@ -71,7 +70,7 @@ typedef struct LasiState { time_t rtc_ref; MemoryRegion this_mem; -} LasiState; +}; static bool lasi_chip_mem_valid(void *opaque, hwaddr addr, unsigned size, bool is_write, @@ -172,8 +171,11 @@ static MemTxResult lasi_chip_write_with_attrs(void *opaque, hwaddr addr, /* read-only. */ break; case LASI_IMR: - s->imr = val; /* 0x20 ?? */ - assert((val & LASI_IRQ_BITS) == val); + s->imr = val; + if (((val & LASI_IRQ_BITS) != val) && (val != 0xffffffff)) + qemu_log_mask(LOG_GUEST_ERROR, + "LASI: tried to set invalid %lx IMR value.\n", + (unsigned long) val); break; case LASI_IPR: /* Any write to IPR clears the register. */ @@ -300,7 +302,7 @@ DeviceState *lasi_init(MemoryRegion *address_space) DeviceState *dev; LasiState *s; - dev = qdev_create(NULL, TYPE_LASI_CHIP); + dev = qdev_new(TYPE_LASI_CHIP); s = LASI_CHIP(dev); s->iar = CPU_HPA + 3; @@ -309,7 +311,7 @@ DeviceState *lasi_init(MemoryRegion *address_space) s, "lasi", 0x100000); memory_region_add_subregion(address_space, LASI_HPA, &s->this_mem); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); /* LAN */ if (enable_lasi_lan()) { diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index 00dd9f58d6d4cce52e5245f72a0424096ea59f23..d5164457ee95d2512368cf8d3cd5e93c2b899dcd 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -12,6 +12,7 @@ #include "qemu/error-report.h" #include "sysemu/reset.h" #include "sysemu/sysemu.h" +#include "sysemu/runstate.h" #include "hw/rtc/mc146818rtc.h" #include "hw/timer/i8254.h" #include "hw/char/serial.h" @@ -25,6 +26,32 @@ #define MAX_IDE_BUS 2 +#define MIN_SEABIOS_HPPA_VERSION 1 /* require at least this fw version */ + +#define HPA_POWER_BUTTON (FIRMWARE_END - 0x10) + +static void hppa_powerdown_req(Notifier *n, void *opaque) +{ + hwaddr soft_power_reg = HPA_POWER_BUTTON; + uint32_t val; + + val = ldl_be_phys(&address_space_memory, soft_power_reg); + if ((val >> 8) == 0) { + /* immediately shut down when under hardware control */ + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + return; + } + + /* clear bit 31 to indicate that the power switch was pressed. */ + val &= ~1; + stl_be_phys(&address_space_memory, soft_power_reg, val); +} + +static Notifier hppa_system_powerdown_notifier = { + .notify = hppa_powerdown_req +}; + + static ISABus *hppa_isa_bus(void) { ISABus *isa_bus; @@ -56,6 +83,44 @@ static uint64_t cpu_hppa_to_phys(void *opaque, uint64_t addr) static HPPACPU *cpu[HPPA_MAX_CPUS]; static uint64_t firmware_entry; +static void fw_cfg_boot_set(void *opaque, const char *boot_device, + Error **errp) +{ + fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]); +} + +static FWCfgState *create_fw_cfg(MachineState *ms) +{ + FWCfgState *fw_cfg; + uint64_t val; + + fw_cfg = fw_cfg_init_mem(FW_CFG_IO_BASE, FW_CFG_IO_BASE + 4); + fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, ms->smp.cpus); + fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, HPPA_MAX_CPUS); + fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ram_size); + + val = cpu_to_le64(MIN_SEABIOS_HPPA_VERSION); + fw_cfg_add_file(fw_cfg, "/etc/firmware-min-version", + g_memdup(&val, sizeof(val)), sizeof(val)); + + val = cpu_to_le64(HPPA_TLB_ENTRIES); + fw_cfg_add_file(fw_cfg, "/etc/cpu/tlb_entries", + g_memdup(&val, sizeof(val)), sizeof(val)); + + val = cpu_to_le64(HPPA_BTLB_ENTRIES); + fw_cfg_add_file(fw_cfg, "/etc/cpu/btlb_entries", + g_memdup(&val, sizeof(val)), sizeof(val)); + + val = cpu_to_le64(HPA_POWER_BUTTON); + fw_cfg_add_file(fw_cfg, "/etc/power-button-addr", + g_memdup(&val, sizeof(val)), sizeof(val)); + + fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ms->boot_order[0]); + qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); + + return fw_cfg; +} + static void machine_hppa_init(MachineState *machine) { const char *kernel_filename = machine->kernel_filename; @@ -118,15 +183,18 @@ static void machine_hppa_init(MachineState *machine) 115200, serial_hd(0), DEVICE_BIG_ENDIAN); } + /* fw_cfg configuration interface */ + create_fw_cfg(machine); + /* SCSI disk setup. */ dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a")); lsi53c8xx_handle_legacy_cmdline(dev); /* Graphics setup. */ if (machine->enable_graphics && vga_interface_type != VGA_NONE) { - dev = qdev_create(NULL, "artist"); - qdev_init_nofail(dev); + dev = qdev_new("artist"); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, LASI_GFX_HPA); sysbus_mmio_map(s, 1, ARTIST_FB_ADDR); } @@ -138,6 +206,9 @@ static void machine_hppa_init(MachineState *machine) } } + /* register power switch emulation */ + qemu_register_powerdown_notifier(&hppa_system_powerdown_notifier); + /* Load firmware. Given that this is not "real" firmware, but one explicitly written for the emulation, we might as well load it directly from an ELF image. */ @@ -251,6 +322,9 @@ static void machine_hppa_init(MachineState *machine) /* tell firmware how many SMP CPUs to present in inventory table */ cpu[0]->env.gr[21] = smp_cpus; + + /* tell firmware fw_cfg port */ + cpu[0]->env.gr[19] = FW_CFG_IO_BASE; } static void hppa_machine_reset(MachineState *ms) @@ -278,6 +352,8 @@ static void hppa_machine_reset(MachineState *ms) cpu[0]->env.gr[24] = 'c'; /* gr22/gr23 unused, no initrd while reboot. */ cpu[0]->env.gr[21] = smp_cpus; + /* tell firmware fw_cfg port */ + cpu[0]->env.gr[19] = FW_CFG_IO_BASE; } diff --git a/hw/hppa/meson.build b/hw/hppa/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..1deae83aee8292d52a0ee8e669c9ca7d29eacdbf --- /dev/null +++ b/hw/hppa/meson.build @@ -0,0 +1,4 @@ +hppa_ss = ss.source_set() +hppa_ss.add(when: 'CONFIG_DINO', if_true: files('pci.c', 'machine.c', 'dino.c', 'lasi.c')) + +hw_arch += {'hppa': hppa_ss} diff --git a/hw/hppa/trace.h b/hw/hppa/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..4e8b52dc28c01f01a1b5f3c2cb9685943f4d9e9f --- /dev/null +++ b/hw/hppa/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_hppa.h" diff --git a/hw/hyperv/Kconfig b/hw/hyperv/Kconfig index a1fa8ff9becc5739fb7da20a90ea789134fd4abc..3fbfe41c9e558089bbbd535c160c35bda1a6ce9b 100644 --- a/hw/hyperv/Kconfig +++ b/hw/hyperv/Kconfig @@ -6,3 +6,8 @@ config HYPERV_TESTDEV bool default y if TEST_DEVICES depends on HYPERV + +config VMBUS + bool + default y + depends on HYPERV diff --git a/hw/hyperv/Makefile.objs b/hw/hyperv/Makefile.objs deleted file mode 100644 index edaca2f7636cf1d7a8d9eec4d5c2f960f5a7bf13..0000000000000000000000000000000000000000 --- a/hw/hyperv/Makefile.objs +++ /dev/null @@ -1,2 +0,0 @@ -obj-y += hyperv.o -obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c index 4b11f7a76b12324f07bd79c1c4526e75bd04e7d4..cb1074f234c896a0544009ad2eb41202339fe467 100644 --- a/hw/hyperv/hyperv.c +++ b/hw/hyperv/hyperv.c @@ -20,8 +20,9 @@ #include "qemu/rcu.h" #include "qemu/rcu_queue.h" #include "hw/hyperv/hyperv.h" +#include "qom/object.h" -typedef struct SynICState { +struct SynICState { DeviceState parent_obj; CPUState *cs; @@ -33,10 +34,17 @@ typedef struct SynICState { MemoryRegion event_page_mr; struct hyperv_message_page *msg_page; struct hyperv_event_flags_page *event_page; -} SynICState; +}; #define TYPE_SYNIC "hyperv-synic" -#define SYNIC(obj) OBJECT_CHECK(SynICState, (obj), TYPE_SYNIC) +OBJECT_DECLARE_SIMPLE_TYPE(SynICState, SYNIC) + +static bool synic_enabled; + +bool hyperv_is_synic_enabled(void) +{ + return synic_enabled; +} static SynICState *get_synic(CPUState *cs) { @@ -133,7 +141,8 @@ void hyperv_synic_add(CPUState *cs) synic->cs = cs; object_property_add_child(OBJECT(cs), "synic", obj); object_unref(obj); - object_property_set_bool(obj, true, "realized", &error_abort); + qdev_realize(DEVICE(obj), NULL, &error_abort); + synic_enabled = true; } void hyperv_synic_reset(CPUState *cs) @@ -222,7 +231,7 @@ static void sint_msg_bh(void *opaque) HvSintRoute *sint_route = opaque; HvSintStagedMessage *staged_msg = sint_route->staged_msg; - if (atomic_read(&staged_msg->state) != HV_STAGED_MSG_POSTED) { + if (qatomic_read(&staged_msg->state) != HV_STAGED_MSG_POSTED) { /* status nor ready yet (spurious ack from guest?), ignore */ return; } @@ -231,7 +240,7 @@ static void sint_msg_bh(void *opaque) staged_msg->status = 0; /* staged message processing finished, ready to start over */ - atomic_set(&staged_msg->state, HV_STAGED_MSG_FREE); + qatomic_set(&staged_msg->state, HV_STAGED_MSG_FREE); /* drop the reference taken in hyperv_post_msg */ hyperv_sint_route_unref(sint_route); } @@ -269,7 +278,7 @@ static void cpu_post_msg(CPUState *cs, run_on_cpu_data data) memory_region_set_dirty(&synic->msg_page_mr, 0, sizeof(*synic->msg_page)); posted: - atomic_set(&staged_msg->state, HV_STAGED_MSG_POSTED); + qatomic_set(&staged_msg->state, HV_STAGED_MSG_POSTED); /* * Notify the msg originator of the progress made; if the slot was busy we * set msg_pending flag in it so it will be the guest who will do EOM and @@ -292,7 +301,7 @@ int hyperv_post_msg(HvSintRoute *sint_route, struct hyperv_message *src_msg) assert(staged_msg); /* grab the staging area */ - if (atomic_cmpxchg(&staged_msg->state, HV_STAGED_MSG_FREE, + if (qatomic_cmpxchg(&staged_msg->state, HV_STAGED_MSG_FREE, HV_STAGED_MSG_BUSY) != HV_STAGED_MSG_FREE) { return -EAGAIN; } @@ -342,7 +351,7 @@ int hyperv_set_event_flag(HvSintRoute *sint_route, unsigned eventno) set_mask = BIT_MASK(eventno); flags = synic->event_page->slot[sint_route->sint].flags; - if ((atomic_fetch_or(&flags[set_idx], set_mask) & set_mask) != set_mask) { + if ((qatomic_fetch_or(&flags[set_idx], set_mask) & set_mask) != set_mask) { memory_region_set_dirty(&synic->event_page_mr, 0, sizeof(*synic->event_page)); ret = hyperv_sint_route_set_sint(sint_route); diff --git a/hw/hyperv/hyperv_testdev.c b/hw/hyperv/hyperv_testdev.c index 88a5a637822a1a7ed7dcbb8bab554a611dd0a245..9a56ddf83fe164b99c2d74cc0765f864fd91ec95 100644 --- a/hw/hyperv/hyperv_testdev.c +++ b/hw/hyperv/hyperv_testdev.c @@ -17,6 +17,7 @@ #include "qemu/queue.h" #include "hw/isa/isa.h" #include "hw/hyperv/hyperv.h" +#include "qom/object.h" typedef struct TestSintRoute { QLIST_ENTRY(TestSintRoute) le; @@ -46,11 +47,9 @@ struct HypervTestDev { QLIST_HEAD(, TestMsgConn) msg_conns; QLIST_HEAD(, TestEvtConn) evt_conns; }; -typedef struct HypervTestDev HypervTestDev; #define TYPE_HYPERV_TEST_DEV "hyperv-testdev" -#define HYPERV_TEST_DEV(obj) \ - OBJECT_CHECK(HypervTestDev, (obj), TYPE_HYPERV_TEST_DEV) +OBJECT_DECLARE_SIMPLE_TYPE(HypervTestDev, HYPERV_TEST_DEV) enum { HV_TEST_DEV_SINT_ROUTE_CREATE = 1, diff --git a/hw/hyperv/meson.build b/hw/hyperv/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..1367e2994f25db287bb181f94c3c52e6d3dee2ee --- /dev/null +++ b/hw/hyperv/meson.build @@ -0,0 +1,3 @@ +specific_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c')) +specific_ss.add(when: 'CONFIG_HYPERV_TESTDEV', if_true: files('hyperv_testdev.c')) +specific_ss.add(when: 'CONFIG_VMBUS', if_true: files('vmbus.c')) diff --git a/hw/hyperv/trace-events b/hw/hyperv/trace-events new file mode 100644 index 0000000000000000000000000000000000000000..b4c35ca8e377054f0a2118edc2a9ce37fbdb091b --- /dev/null +++ b/hw/hyperv/trace-events @@ -0,0 +1,18 @@ +# vmbus.c +vmbus_recv_message(uint32_t type, uint32_t size) "type %d size %d" +vmbus_signal_event(void) "" +vmbus_channel_notify_guest(uint32_t chan_id) "channel #%d" +vmbus_post_msg(uint32_t type, uint32_t size) "type %d size %d" +vmbus_msg_cb(int status) "message status %d" +vmbus_process_incoming_message(uint32_t message_type) "type %d" +vmbus_initiate_contact(uint16_t major, uint16_t minor, uint32_t vcpu, uint64_t monitor_page1, uint64_t monitor_page2, uint64_t interrupt_page) "version %d.%d target vp %d mon pages 0x%"PRIx64",0x%"PRIx64" int page 0x%"PRIx64 +vmbus_send_offer(uint32_t chan_id, void *dev) "channel #%d dev %p" +vmbus_terminate_offers(void) "" +vmbus_gpadl_header(uint32_t gpadl_id, uint16_t num_gfns) "gpadl #%d gfns %d" +vmbus_gpadl_body(uint32_t gpadl_id) "gpadl #%d" +vmbus_gpadl_created(uint32_t gpadl_id) "gpadl #%d" +vmbus_gpadl_teardown(uint32_t gpadl_id) "gpadl #%d" +vmbus_gpadl_torndown(uint32_t gpadl_id) "gpadl #%d" +vmbus_open_channel(uint32_t chan_id, uint32_t gpadl_id, uint32_t target_vp) "channel #%d gpadl #%d target vp %d" +vmbus_channel_open(uint32_t chan_id, uint32_t status) "channel #%d status %d" +vmbus_close_channel(uint32_t chan_id) "channel #%d" diff --git a/hw/hyperv/trace.h b/hw/hyperv/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..7f2a88881b0e7e1c53c97354dc13ac168396586a --- /dev/null +++ b/hw/hyperv/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_hyperv.h" diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c new file mode 100644 index 0000000000000000000000000000000000000000..896e981f85fd32bcb31b198f3af136ab5f401475 --- /dev/null +++ b/hw/hyperv/vmbus.c @@ -0,0 +1,2774 @@ +/* + * QEMU Hyper-V VMBus + * + * Copyright (c) 2017-2018 Virtuozzo International GmbH. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" +#include "hw/hyperv/hyperv.h" +#include "hw/hyperv/vmbus.h" +#include "hw/hyperv/vmbus-bridge.h" +#include "hw/sysbus.h" +#include "cpu.h" +#include "trace.h" + +enum { + VMGPADL_INIT, + VMGPADL_ALIVE, + VMGPADL_TEARINGDOWN, + VMGPADL_TORNDOWN, +}; + +struct VMBusGpadl { + /* GPADL id */ + uint32_t id; + /* associated channel id (rudimentary?) */ + uint32_t child_relid; + + /* number of pages in the GPADL as declared in GPADL_HEADER message */ + uint32_t num_gfns; + /* + * Due to limited message size, GPADL may not fit fully in a single + * GPADL_HEADER message, and is further popluated using GPADL_BODY + * messages. @seen_gfns is the number of pages seen so far; once it + * reaches @num_gfns, the GPADL is ready to use. + */ + uint32_t seen_gfns; + /* array of GFNs (of size @num_gfns once allocated) */ + uint64_t *gfns; + + uint8_t state; + + QTAILQ_ENTRY(VMBusGpadl) link; + VMBus *vmbus; + unsigned refcount; +}; + +/* + * Wrap sequential read from / write to GPADL. + */ +typedef struct GpadlIter { + VMBusGpadl *gpadl; + AddressSpace *as; + DMADirection dir; + /* offset into GPADL where the next i/o will be performed */ + uint32_t off; + /* + * Cached mapping of the currently accessed page, up to page boundary. + * Updated lazily on i/o. + * Note: MemoryRegionCache can not be used here because pages in the GPADL + * are non-contiguous and may belong to different memory regions. + */ + void *map; + /* offset after last i/o (i.e. not affected by seek) */ + uint32_t last_off; + /* + * Indicator that the iterator is active and may have a cached mapping. + * Allows to enforce bracketing of all i/o (which may create cached + * mappings) and thus exclude mapping leaks. + */ + bool active; +} GpadlIter; + +/* + * Ring buffer. There are two of them, sitting in the same GPADL, for each + * channel. + * Each ring buffer consists of a set of pages, with the first page containing + * the ring buffer header, and the remaining pages being for data packets. + */ +typedef struct VMBusRingBufCommon { + AddressSpace *as; + /* GPA of the ring buffer header */ + dma_addr_t rb_addr; + /* start and length of the ring buffer data area within GPADL */ + uint32_t base; + uint32_t len; + + GpadlIter iter; +} VMBusRingBufCommon; + +typedef struct VMBusSendRingBuf { + VMBusRingBufCommon common; + /* current write index, to be committed at the end of send */ + uint32_t wr_idx; + /* write index at the start of send */ + uint32_t last_wr_idx; + /* space to be requested from the guest */ + uint32_t wanted; + /* space reserved for planned sends */ + uint32_t reserved; + /* last seen read index */ + uint32_t last_seen_rd_idx; +} VMBusSendRingBuf; + +typedef struct VMBusRecvRingBuf { + VMBusRingBufCommon common; + /* current read index, to be committed at the end of receive */ + uint32_t rd_idx; + /* read index at the start of receive */ + uint32_t last_rd_idx; + /* last seen write index */ + uint32_t last_seen_wr_idx; +} VMBusRecvRingBuf; + + +enum { + VMOFFER_INIT, + VMOFFER_SENDING, + VMOFFER_SENT, +}; + +enum { + VMCHAN_INIT, + VMCHAN_OPENING, + VMCHAN_OPEN, +}; + +struct VMBusChannel { + VMBusDevice *dev; + + /* channel id */ + uint32_t id; + /* + * subchannel index within the device; subchannel #0 is "primary" and + * always exists + */ + uint16_t subchan_idx; + uint32_t open_id; + /* VP_INDEX of the vCPU to notify with (synthetic) interrupts */ + uint32_t target_vp; + /* GPADL id to use for the ring buffers */ + uint32_t ringbuf_gpadl; + /* start (in pages) of the send ring buffer within @ringbuf_gpadl */ + uint32_t ringbuf_send_offset; + + uint8_t offer_state; + uint8_t state; + bool is_open; + + /* main device worker; copied from the device class */ + VMBusChannelNotifyCb notify_cb; + /* + * guest->host notifications, either sent directly or dispatched via + * interrupt page (older VMBus) + */ + EventNotifier notifier; + + VMBus *vmbus; + /* + * SINT route to signal with host->guest notifications; may be shared with + * the main VMBus SINT route + */ + HvSintRoute *notify_route; + VMBusGpadl *gpadl; + + VMBusSendRingBuf send_ringbuf; + VMBusRecvRingBuf recv_ringbuf; + + QTAILQ_ENTRY(VMBusChannel) link; +}; + +/* + * Hyper-V spec mandates that every message port has 16 buffers, which means + * that the guest can post up to this many messages without blocking. + * Therefore a queue for incoming messages has to be provided. + * For outgoing (i.e. host->guest) messages there's no queue; the VMBus just + * doesn't transition to a new state until the message is known to have been + * successfully delivered to the respective SynIC message slot. + */ +#define HV_MSG_QUEUE_LEN 16 + +/* Hyper-V devices never use channel #0. Must be something special. */ +#define VMBUS_FIRST_CHANID 1 +/* Each channel occupies one bit within a single event page sint slot. */ +#define VMBUS_CHANID_COUNT (HV_EVENT_FLAGS_COUNT - VMBUS_FIRST_CHANID) +/* Leave a few connection numbers for other purposes. */ +#define VMBUS_CHAN_CONNECTION_OFFSET 16 + +/* + * Since the success or failure of sending a message is reported + * asynchronously, the VMBus state machine has effectively two entry points: + * vmbus_run and vmbus_msg_cb (the latter is called when the host->guest + * message delivery status becomes known). Both are run as oneshot BHs on the + * main aio context, ensuring serialization. + */ +enum { + VMBUS_LISTEN, + VMBUS_HANDSHAKE, + VMBUS_OFFER, + VMBUS_CREATE_GPADL, + VMBUS_TEARDOWN_GPADL, + VMBUS_OPEN_CHANNEL, + VMBUS_UNLOAD, + VMBUS_STATE_MAX +}; + +struct VMBus { + BusState parent; + + uint8_t state; + /* protection against recursive aio_poll (see vmbus_run) */ + bool in_progress; + /* whether there's a message being delivered to the guest */ + bool msg_in_progress; + uint32_t version; + /* VP_INDEX of the vCPU to send messages and interrupts to */ + uint32_t target_vp; + HvSintRoute *sint_route; + /* + * interrupt page for older protocol versions; newer ones use SynIC event + * flags directly + */ + hwaddr int_page_gpa; + + DECLARE_BITMAP(chanid_bitmap, VMBUS_CHANID_COUNT); + + /* incoming message queue */ + struct hyperv_post_message_input rx_queue[HV_MSG_QUEUE_LEN]; + uint8_t rx_queue_head; + uint8_t rx_queue_size; + QemuMutex rx_queue_lock; + + QTAILQ_HEAD(, VMBusGpadl) gpadl_list; + QTAILQ_HEAD(, VMBusChannel) channel_list; + + /* + * guest->host notifications for older VMBus, to be dispatched via + * interrupt page + */ + EventNotifier notifier; +}; + +static bool gpadl_full(VMBusGpadl *gpadl) +{ + return gpadl->seen_gfns == gpadl->num_gfns; +} + +static VMBusGpadl *create_gpadl(VMBus *vmbus, uint32_t id, + uint32_t child_relid, uint32_t num_gfns) +{ + VMBusGpadl *gpadl = g_new0(VMBusGpadl, 1); + + gpadl->id = id; + gpadl->child_relid = child_relid; + gpadl->num_gfns = num_gfns; + gpadl->gfns = g_new(uint64_t, num_gfns); + QTAILQ_INSERT_HEAD(&vmbus->gpadl_list, gpadl, link); + gpadl->vmbus = vmbus; + gpadl->refcount = 1; + return gpadl; +} + +static void free_gpadl(VMBusGpadl *gpadl) +{ + QTAILQ_REMOVE(&gpadl->vmbus->gpadl_list, gpadl, link); + g_free(gpadl->gfns); + g_free(gpadl); +} + +static VMBusGpadl *find_gpadl(VMBus *vmbus, uint32_t gpadl_id) +{ + VMBusGpadl *gpadl; + QTAILQ_FOREACH(gpadl, &vmbus->gpadl_list, link) { + if (gpadl->id == gpadl_id) { + return gpadl; + } + } + return NULL; +} + +VMBusGpadl *vmbus_get_gpadl(VMBusChannel *chan, uint32_t gpadl_id) +{ + VMBusGpadl *gpadl = find_gpadl(chan->vmbus, gpadl_id); + if (!gpadl || !gpadl_full(gpadl)) { + return NULL; + } + gpadl->refcount++; + return gpadl; +} + +void vmbus_put_gpadl(VMBusGpadl *gpadl) +{ + if (!gpadl) { + return; + } + if (--gpadl->refcount) { + return; + } + free_gpadl(gpadl); +} + +uint32_t vmbus_gpadl_len(VMBusGpadl *gpadl) +{ + return gpadl->num_gfns * TARGET_PAGE_SIZE; +} + +static void gpadl_iter_init(GpadlIter *iter, VMBusGpadl *gpadl, + AddressSpace *as, DMADirection dir) +{ + iter->gpadl = gpadl; + iter->as = as; + iter->dir = dir; + iter->active = false; +} + +static inline void gpadl_iter_cache_unmap(GpadlIter *iter) +{ + uint32_t map_start_in_page = (uintptr_t)iter->map & ~TARGET_PAGE_MASK; + uint32_t io_end_in_page = ((iter->last_off - 1) & ~TARGET_PAGE_MASK) + 1; + + /* mapping is only done to do non-zero amount of i/o */ + assert(iter->last_off > 0); + assert(map_start_in_page < io_end_in_page); + + dma_memory_unmap(iter->as, iter->map, TARGET_PAGE_SIZE - map_start_in_page, + iter->dir, io_end_in_page - map_start_in_page); +} + +/* + * Copy exactly @len bytes between the GPADL pointed to by @iter and @buf. + * The direction of the copy is determined by @iter->dir. + * The caller must ensure the operation overflows neither @buf nor the GPADL + * (there's an assert for the latter). + * Reuse the currently mapped page in the GPADL if possible. + */ +static ssize_t gpadl_iter_io(GpadlIter *iter, void *buf, uint32_t len) +{ + ssize_t ret = len; + + assert(iter->active); + + while (len) { + uint32_t off_in_page = iter->off & ~TARGET_PAGE_MASK; + uint32_t pgleft = TARGET_PAGE_SIZE - off_in_page; + uint32_t cplen = MIN(pgleft, len); + void *p; + + /* try to reuse the cached mapping */ + if (iter->map) { + uint32_t map_start_in_page = + (uintptr_t)iter->map & ~TARGET_PAGE_MASK; + uint32_t off_base = iter->off & ~TARGET_PAGE_MASK; + uint32_t mapped_base = (iter->last_off - 1) & ~TARGET_PAGE_MASK; + if (off_base != mapped_base || off_in_page < map_start_in_page) { + gpadl_iter_cache_unmap(iter); + iter->map = NULL; + } + } + + if (!iter->map) { + dma_addr_t maddr; + dma_addr_t mlen = pgleft; + uint32_t idx = iter->off >> TARGET_PAGE_BITS; + assert(idx < iter->gpadl->num_gfns); + + maddr = (iter->gpadl->gfns[idx] << TARGET_PAGE_BITS) | off_in_page; + + iter->map = dma_memory_map(iter->as, maddr, &mlen, iter->dir); + if (mlen != pgleft) { + dma_memory_unmap(iter->as, iter->map, mlen, iter->dir, 0); + iter->map = NULL; + return -EFAULT; + } + } + + p = (void *)(uintptr_t)(((uintptr_t)iter->map & TARGET_PAGE_MASK) | + off_in_page); + if (iter->dir == DMA_DIRECTION_FROM_DEVICE) { + memcpy(p, buf, cplen); + } else { + memcpy(buf, p, cplen); + } + + buf += cplen; + len -= cplen; + iter->off += cplen; + iter->last_off = iter->off; + } + + return ret; +} + +/* + * Position the iterator @iter at new offset @new_off. + * If this results in the cached mapping being unusable with the new offset, + * unmap it. + */ +static inline void gpadl_iter_seek(GpadlIter *iter, uint32_t new_off) +{ + assert(iter->active); + iter->off = new_off; +} + +/* + * Start a series of i/o on the GPADL. + * After this i/o and seek operations on @iter become legal. + */ +static inline void gpadl_iter_start_io(GpadlIter *iter) +{ + assert(!iter->active); + /* mapping is cached lazily on i/o */ + iter->map = NULL; + iter->active = true; +} + +/* + * End the eariler started series of i/o on the GPADL and release the cached + * mapping if any. + */ +static inline void gpadl_iter_end_io(GpadlIter *iter) +{ + assert(iter->active); + + if (iter->map) { + gpadl_iter_cache_unmap(iter); + } + + iter->active = false; +} + +static void vmbus_resched(VMBus *vmbus); +static void vmbus_msg_cb(void *data, int status); + +ssize_t vmbus_iov_to_gpadl(VMBusChannel *chan, VMBusGpadl *gpadl, uint32_t off, + const struct iovec *iov, size_t iov_cnt) +{ + GpadlIter iter; + size_t i; + ssize_t ret = 0; + + gpadl_iter_init(&iter, gpadl, chan->dev->dma_as, + DMA_DIRECTION_FROM_DEVICE); + gpadl_iter_start_io(&iter); + gpadl_iter_seek(&iter, off); + for (i = 0; i < iov_cnt; i++) { + ret = gpadl_iter_io(&iter, iov[i].iov_base, iov[i].iov_len); + if (ret < 0) { + goto out; + } + } +out: + gpadl_iter_end_io(&iter); + return ret; +} + +int vmbus_map_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov, + unsigned iov_cnt, size_t len, size_t off) +{ + int ret_cnt = 0, ret; + unsigned i; + QEMUSGList *sgl = &req->sgl; + ScatterGatherEntry *sg = sgl->sg; + + for (i = 0; i < sgl->nsg; i++) { + if (sg[i].len > off) { + break; + } + off -= sg[i].len; + } + for (; len && i < sgl->nsg; i++) { + dma_addr_t mlen = MIN(sg[i].len - off, len); + dma_addr_t addr = sg[i].base + off; + len -= mlen; + off = 0; + + for (; mlen; ret_cnt++) { + dma_addr_t l = mlen; + dma_addr_t a = addr; + + if (ret_cnt == iov_cnt) { + ret = -ENOBUFS; + goto err; + } + + iov[ret_cnt].iov_base = dma_memory_map(sgl->as, a, &l, dir); + if (!l) { + ret = -EFAULT; + goto err; + } + iov[ret_cnt].iov_len = l; + addr += l; + mlen -= l; + } + } + + return ret_cnt; +err: + vmbus_unmap_sgl(req, dir, iov, ret_cnt, 0); + return ret; +} + +void vmbus_unmap_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov, + unsigned iov_cnt, size_t accessed) +{ + QEMUSGList *sgl = &req->sgl; + unsigned i; + + for (i = 0; i < iov_cnt; i++) { + size_t acsd = MIN(accessed, iov[i].iov_len); + dma_memory_unmap(sgl->as, iov[i].iov_base, iov[i].iov_len, dir, acsd); + accessed -= acsd; + } +} + +static const VMStateDescription vmstate_gpadl = { + .name = "vmbus/gpadl", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32(id, VMBusGpadl), + VMSTATE_UINT32(child_relid, VMBusGpadl), + VMSTATE_UINT32(num_gfns, VMBusGpadl), + VMSTATE_UINT32(seen_gfns, VMBusGpadl), + VMSTATE_VARRAY_UINT32_ALLOC(gfns, VMBusGpadl, num_gfns, 0, + vmstate_info_uint64, uint64_t), + VMSTATE_UINT8(state, VMBusGpadl), + VMSTATE_END_OF_LIST() + } +}; + +/* + * Wrap the index into a ring buffer of @len bytes. + * @idx is assumed not to exceed twice the size of the ringbuffer, so only + * single wraparound is considered. + */ +static inline uint32_t rb_idx_wrap(uint32_t idx, uint32_t len) +{ + if (idx >= len) { + idx -= len; + } + return idx; +} + +/* + * Circular difference between two indices into a ring buffer of @len bytes. + * @allow_catchup - whether @idx1 may catch up @idx2; e.g. read index may catch + * up write index but not vice versa. + */ +static inline uint32_t rb_idx_delta(uint32_t idx1, uint32_t idx2, uint32_t len, + bool allow_catchup) +{ + return rb_idx_wrap(idx2 + len - idx1 - !allow_catchup, len); +} + +static vmbus_ring_buffer *ringbuf_map_hdr(VMBusRingBufCommon *ringbuf) +{ + vmbus_ring_buffer *rb; + dma_addr_t mlen = sizeof(*rb); + + rb = dma_memory_map(ringbuf->as, ringbuf->rb_addr, &mlen, + DMA_DIRECTION_FROM_DEVICE); + if (mlen != sizeof(*rb)) { + dma_memory_unmap(ringbuf->as, rb, mlen, + DMA_DIRECTION_FROM_DEVICE, 0); + return NULL; + } + return rb; +} + +static void ringbuf_unmap_hdr(VMBusRingBufCommon *ringbuf, + vmbus_ring_buffer *rb, bool dirty) +{ + assert(rb); + + dma_memory_unmap(ringbuf->as, rb, sizeof(*rb), DMA_DIRECTION_FROM_DEVICE, + dirty ? sizeof(*rb) : 0); +} + +static void ringbuf_init_common(VMBusRingBufCommon *ringbuf, VMBusGpadl *gpadl, + AddressSpace *as, DMADirection dir, + uint32_t begin, uint32_t end) +{ + ringbuf->as = as; + ringbuf->rb_addr = gpadl->gfns[begin] << TARGET_PAGE_BITS; + ringbuf->base = (begin + 1) << TARGET_PAGE_BITS; + ringbuf->len = (end - begin - 1) << TARGET_PAGE_BITS; + gpadl_iter_init(&ringbuf->iter, gpadl, as, dir); +} + +static int ringbufs_init(VMBusChannel *chan) +{ + vmbus_ring_buffer *rb; + VMBusSendRingBuf *send_ringbuf = &chan->send_ringbuf; + VMBusRecvRingBuf *recv_ringbuf = &chan->recv_ringbuf; + + if (chan->ringbuf_send_offset <= 1 || + chan->gpadl->num_gfns <= chan->ringbuf_send_offset + 1) { + return -EINVAL; + } + + ringbuf_init_common(&recv_ringbuf->common, chan->gpadl, chan->dev->dma_as, + DMA_DIRECTION_TO_DEVICE, 0, chan->ringbuf_send_offset); + ringbuf_init_common(&send_ringbuf->common, chan->gpadl, chan->dev->dma_as, + DMA_DIRECTION_FROM_DEVICE, chan->ringbuf_send_offset, + chan->gpadl->num_gfns); + send_ringbuf->wanted = 0; + send_ringbuf->reserved = 0; + + rb = ringbuf_map_hdr(&recv_ringbuf->common); + if (!rb) { + return -EFAULT; + } + recv_ringbuf->rd_idx = recv_ringbuf->last_rd_idx = rb->read_index; + ringbuf_unmap_hdr(&recv_ringbuf->common, rb, false); + + rb = ringbuf_map_hdr(&send_ringbuf->common); + if (!rb) { + return -EFAULT; + } + send_ringbuf->wr_idx = send_ringbuf->last_wr_idx = rb->write_index; + send_ringbuf->last_seen_rd_idx = rb->read_index; + rb->feature_bits |= VMBUS_RING_BUFFER_FEAT_PENDING_SZ; + ringbuf_unmap_hdr(&send_ringbuf->common, rb, true); + + if (recv_ringbuf->rd_idx >= recv_ringbuf->common.len || + send_ringbuf->wr_idx >= send_ringbuf->common.len) { + return -EOVERFLOW; + } + + return 0; +} + +/* + * Perform io between the GPADL-backed ringbuffer @ringbuf and @buf, wrapping + * around if needed. + * @len is assumed not to exceed the size of the ringbuffer, so only single + * wraparound is considered. + */ +static ssize_t ringbuf_io(VMBusRingBufCommon *ringbuf, void *buf, uint32_t len) +{ + ssize_t ret1 = 0, ret2 = 0; + uint32_t remain = ringbuf->len + ringbuf->base - ringbuf->iter.off; + + if (len >= remain) { + ret1 = gpadl_iter_io(&ringbuf->iter, buf, remain); + if (ret1 < 0) { + return ret1; + } + gpadl_iter_seek(&ringbuf->iter, ringbuf->base); + buf += remain; + len -= remain; + } + ret2 = gpadl_iter_io(&ringbuf->iter, buf, len); + if (ret2 < 0) { + return ret2; + } + return ret1 + ret2; +} + +/* + * Position the circular iterator within @ringbuf to offset @new_off, wrapping + * around if needed. + * @new_off is assumed not to exceed twice the size of the ringbuffer, so only + * single wraparound is considered. + */ +static inline void ringbuf_seek(VMBusRingBufCommon *ringbuf, uint32_t new_off) +{ + gpadl_iter_seek(&ringbuf->iter, + ringbuf->base + rb_idx_wrap(new_off, ringbuf->len)); +} + +static inline uint32_t ringbuf_tell(VMBusRingBufCommon *ringbuf) +{ + return ringbuf->iter.off - ringbuf->base; +} + +static inline void ringbuf_start_io(VMBusRingBufCommon *ringbuf) +{ + gpadl_iter_start_io(&ringbuf->iter); +} + +static inline void ringbuf_end_io(VMBusRingBufCommon *ringbuf) +{ + gpadl_iter_end_io(&ringbuf->iter); +} + +VMBusDevice *vmbus_channel_device(VMBusChannel *chan) +{ + return chan->dev; +} + +VMBusChannel *vmbus_device_channel(VMBusDevice *dev, uint32_t chan_idx) +{ + if (chan_idx >= dev->num_channels) { + return NULL; + } + return &dev->channels[chan_idx]; +} + +uint32_t vmbus_channel_idx(VMBusChannel *chan) +{ + return chan - chan->dev->channels; +} + +void vmbus_channel_notify_host(VMBusChannel *chan) +{ + event_notifier_set(&chan->notifier); +} + +bool vmbus_channel_is_open(VMBusChannel *chan) +{ + return chan->is_open; +} + +/* + * Notify the guest side about the data to work on in the channel ring buffer. + * The notification is done by signaling a dedicated per-channel SynIC event + * flag (more recent guests) or setting a bit in the interrupt page and firing + * the VMBus SINT (older guests). + */ +static int vmbus_channel_notify_guest(VMBusChannel *chan) +{ + int res = 0; + unsigned long *int_map, mask; + unsigned idx; + hwaddr addr = chan->vmbus->int_page_gpa; + hwaddr len = TARGET_PAGE_SIZE / 2, dirty = 0; + + trace_vmbus_channel_notify_guest(chan->id); + + if (!addr) { + return hyperv_set_event_flag(chan->notify_route, chan->id); + } + + int_map = cpu_physical_memory_map(addr, &len, 1); + if (len != TARGET_PAGE_SIZE / 2) { + res = -ENXIO; + goto unmap; + } + + idx = BIT_WORD(chan->id); + mask = BIT_MASK(chan->id); + if ((qatomic_fetch_or(&int_map[idx], mask) & mask) != mask) { + res = hyperv_sint_route_set_sint(chan->notify_route); + dirty = len; + } + +unmap: + cpu_physical_memory_unmap(int_map, len, 1, dirty); + return res; +} + +#define VMBUS_PKT_TRAILER sizeof(uint64_t) + +static uint32_t vmbus_pkt_hdr_set_offsets(vmbus_packet_hdr *hdr, + uint32_t desclen, uint32_t msglen) +{ + hdr->offset_qwords = sizeof(*hdr) / sizeof(uint64_t) + + DIV_ROUND_UP(desclen, sizeof(uint64_t)); + hdr->len_qwords = hdr->offset_qwords + + DIV_ROUND_UP(msglen, sizeof(uint64_t)); + return hdr->len_qwords * sizeof(uint64_t) + VMBUS_PKT_TRAILER; +} + +/* + * Simplified ring buffer operation with paired barriers annotations in the + * producer and consumer loops: + * + * producer * consumer + * ~~~~~~~~ * ~~~~~~~~ + * write pending_send_sz * read write_index + * smp_mb [A] * smp_mb [C] + * read read_index * read packet + * smp_mb [B] * read/write out-of-band data + * read/write out-of-band data * smp_mb [B] + * write packet * write read_index + * smp_mb [C] * smp_mb [A] + * write write_index * read pending_send_sz + * smp_wmb [D] * smp_rmb [D] + * write pending_send_sz * read write_index + * ... * ... + */ + +static inline uint32_t ringbuf_send_avail(VMBusSendRingBuf *ringbuf) +{ + /* don't trust guest data */ + if (ringbuf->last_seen_rd_idx >= ringbuf->common.len) { + return 0; + } + return rb_idx_delta(ringbuf->wr_idx, ringbuf->last_seen_rd_idx, + ringbuf->common.len, false); +} + +static ssize_t ringbuf_send_update_idx(VMBusChannel *chan) +{ + VMBusSendRingBuf *ringbuf = &chan->send_ringbuf; + vmbus_ring_buffer *rb; + uint32_t written; + + written = rb_idx_delta(ringbuf->last_wr_idx, ringbuf->wr_idx, + ringbuf->common.len, true); + if (!written) { + return 0; + } + + rb = ringbuf_map_hdr(&ringbuf->common); + if (!rb) { + return -EFAULT; + } + + ringbuf->reserved -= written; + + /* prevent reorder with the data operation and packet write */ + smp_mb(); /* barrier pair [C] */ + rb->write_index = ringbuf->wr_idx; + + /* + * If the producer earlier indicated that it wants to be notified when the + * consumer frees certain amount of space in the ring buffer, that amount + * is reduced by the size of the completed write. + */ + if (ringbuf->wanted) { + /* otherwise reservation would fail */ + assert(ringbuf->wanted < written); + ringbuf->wanted -= written; + /* prevent reorder with write_index write */ + smp_wmb(); /* barrier pair [D] */ + rb->pending_send_sz = ringbuf->wanted; + } + + /* prevent reorder with write_index or pending_send_sz write */ + smp_mb(); /* barrier pair [A] */ + ringbuf->last_seen_rd_idx = rb->read_index; + + /* + * The consumer may have missed the reduction of pending_send_sz and skip + * notification, so re-check the blocking condition, and, if it's no longer + * true, ensure processing another iteration by simulating consumer's + * notification. + */ + if (ringbuf_send_avail(ringbuf) >= ringbuf->wanted) { + vmbus_channel_notify_host(chan); + } + + /* skip notification by consumer's request */ + if (rb->interrupt_mask) { + goto out; + } + + /* + * The consumer hasn't caught up with the producer's previous state so it's + * not blocked. + * (last_seen_rd_idx comes from the guest but it's safe to use w/o + * validation here as it only affects notification.) + */ + if (rb_idx_delta(ringbuf->last_seen_rd_idx, ringbuf->wr_idx, + ringbuf->common.len, true) > written) { + goto out; + } + + vmbus_channel_notify_guest(chan); +out: + ringbuf_unmap_hdr(&ringbuf->common, rb, true); + ringbuf->last_wr_idx = ringbuf->wr_idx; + return written; +} + +int vmbus_channel_reserve(VMBusChannel *chan, + uint32_t desclen, uint32_t msglen) +{ + VMBusSendRingBuf *ringbuf = &chan->send_ringbuf; + vmbus_ring_buffer *rb = NULL; + vmbus_packet_hdr hdr; + uint32_t needed = ringbuf->reserved + + vmbus_pkt_hdr_set_offsets(&hdr, desclen, msglen); + + /* avoid touching the guest memory if possible */ + if (likely(needed <= ringbuf_send_avail(ringbuf))) { + goto success; + } + + rb = ringbuf_map_hdr(&ringbuf->common); + if (!rb) { + return -EFAULT; + } + + /* fetch read index from guest memory and try again */ + ringbuf->last_seen_rd_idx = rb->read_index; + + if (likely(needed <= ringbuf_send_avail(ringbuf))) { + goto success; + } + + rb->pending_send_sz = needed; + + /* + * The consumer may have made progress and freed up some space before + * seeing updated pending_send_sz, so re-read read_index (preventing + * reorder with the pending_send_sz write) and try again. + */ + smp_mb(); /* barrier pair [A] */ + ringbuf->last_seen_rd_idx = rb->read_index; + + if (needed > ringbuf_send_avail(ringbuf)) { + goto out; + } + +success: + ringbuf->reserved = needed; + needed = 0; + + /* clear pending_send_sz if it was set */ + if (ringbuf->wanted) { + if (!rb) { + rb = ringbuf_map_hdr(&ringbuf->common); + if (!rb) { + /* failure to clear pending_send_sz is non-fatal */ + goto out; + } + } + + rb->pending_send_sz = 0; + } + + /* prevent reorder of the following data operation with read_index read */ + smp_mb(); /* barrier pair [B] */ + +out: + if (rb) { + ringbuf_unmap_hdr(&ringbuf->common, rb, ringbuf->wanted == needed); + } + ringbuf->wanted = needed; + return needed ? -ENOSPC : 0; +} + +ssize_t vmbus_channel_send(VMBusChannel *chan, uint16_t pkt_type, + void *desc, uint32_t desclen, + void *msg, uint32_t msglen, + bool need_comp, uint64_t transaction_id) +{ + ssize_t ret = 0; + vmbus_packet_hdr hdr; + uint32_t totlen; + VMBusSendRingBuf *ringbuf = &chan->send_ringbuf; + + if (!vmbus_channel_is_open(chan)) { + return -EINVAL; + } + + totlen = vmbus_pkt_hdr_set_offsets(&hdr, desclen, msglen); + hdr.type = pkt_type; + hdr.flags = need_comp ? VMBUS_PACKET_FLAG_REQUEST_COMPLETION : 0; + hdr.transaction_id = transaction_id; + + assert(totlen <= ringbuf->reserved); + + ringbuf_start_io(&ringbuf->common); + ringbuf_seek(&ringbuf->common, ringbuf->wr_idx); + ret = ringbuf_io(&ringbuf->common, &hdr, sizeof(hdr)); + if (ret < 0) { + goto out; + } + if (desclen) { + assert(desc); + ret = ringbuf_io(&ringbuf->common, desc, desclen); + if (ret < 0) { + goto out; + } + ringbuf_seek(&ringbuf->common, + ringbuf->wr_idx + hdr.offset_qwords * sizeof(uint64_t)); + } + ret = ringbuf_io(&ringbuf->common, msg, msglen); + if (ret < 0) { + goto out; + } + ringbuf_seek(&ringbuf->common, ringbuf->wr_idx + totlen); + ringbuf->wr_idx = ringbuf_tell(&ringbuf->common); + ret = 0; +out: + ringbuf_end_io(&ringbuf->common); + if (ret) { + return ret; + } + return ringbuf_send_update_idx(chan); +} + +ssize_t vmbus_channel_send_completion(VMBusChanReq *req, + void *msg, uint32_t msglen) +{ + assert(req->need_comp); + return vmbus_channel_send(req->chan, VMBUS_PACKET_COMP, NULL, 0, + msg, msglen, false, req->transaction_id); +} + +static int sgl_from_gpa_ranges(QEMUSGList *sgl, VMBusDevice *dev, + VMBusRingBufCommon *ringbuf, uint32_t len) +{ + int ret; + vmbus_pkt_gpa_direct hdr; + hwaddr curaddr = 0; + hwaddr curlen = 0; + int num; + + if (len < sizeof(hdr)) { + return -EIO; + } + ret = ringbuf_io(ringbuf, &hdr, sizeof(hdr)); + if (ret < 0) { + return ret; + } + len -= sizeof(hdr); + + num = (len - hdr.rangecount * sizeof(vmbus_gpa_range)) / sizeof(uint64_t); + if (num < 0) { + return -EIO; + } + qemu_sglist_init(sgl, DEVICE(dev), num, ringbuf->as); + + for (; hdr.rangecount; hdr.rangecount--) { + vmbus_gpa_range range; + + if (len < sizeof(range)) { + goto eio; + } + ret = ringbuf_io(ringbuf, &range, sizeof(range)); + if (ret < 0) { + goto err; + } + len -= sizeof(range); + + if (range.byte_offset & TARGET_PAGE_MASK) { + goto eio; + } + + for (; range.byte_count; range.byte_offset = 0) { + uint64_t paddr; + uint32_t plen = MIN(range.byte_count, + TARGET_PAGE_SIZE - range.byte_offset); + + if (len < sizeof(uint64_t)) { + goto eio; + } + ret = ringbuf_io(ringbuf, &paddr, sizeof(paddr)); + if (ret < 0) { + goto err; + } + len -= sizeof(uint64_t); + paddr <<= TARGET_PAGE_BITS; + paddr |= range.byte_offset; + range.byte_count -= plen; + + if (curaddr + curlen == paddr) { + /* consecutive fragments - join */ + curlen += plen; + } else { + if (curlen) { + qemu_sglist_add(sgl, curaddr, curlen); + } + + curaddr = paddr; + curlen = plen; + } + } + } + + if (curlen) { + qemu_sglist_add(sgl, curaddr, curlen); + } + + return 0; +eio: + ret = -EIO; +err: + qemu_sglist_destroy(sgl); + return ret; +} + +static VMBusChanReq *vmbus_alloc_req(VMBusChannel *chan, + uint32_t size, uint16_t pkt_type, + uint32_t msglen, uint64_t transaction_id, + bool need_comp) +{ + VMBusChanReq *req; + uint32_t msgoff = QEMU_ALIGN_UP(size, __alignof__(*req->msg)); + uint32_t totlen = msgoff + msglen; + + req = g_malloc0(totlen); + req->chan = chan; + req->pkt_type = pkt_type; + req->msg = (void *)req + msgoff; + req->msglen = msglen; + req->transaction_id = transaction_id; + req->need_comp = need_comp; + return req; +} + +int vmbus_channel_recv_start(VMBusChannel *chan) +{ + VMBusRecvRingBuf *ringbuf = &chan->recv_ringbuf; + vmbus_ring_buffer *rb; + + rb = ringbuf_map_hdr(&ringbuf->common); + if (!rb) { + return -EFAULT; + } + ringbuf->last_seen_wr_idx = rb->write_index; + ringbuf_unmap_hdr(&ringbuf->common, rb, false); + + if (ringbuf->last_seen_wr_idx >= ringbuf->common.len) { + return -EOVERFLOW; + } + + /* prevent reorder of the following data operation with write_index read */ + smp_mb(); /* barrier pair [C] */ + return 0; +} + +void *vmbus_channel_recv_peek(VMBusChannel *chan, uint32_t size) +{ + VMBusRecvRingBuf *ringbuf = &chan->recv_ringbuf; + vmbus_packet_hdr hdr = {}; + VMBusChanReq *req; + uint32_t avail; + uint32_t totlen, pktlen, msglen, msgoff, desclen; + + assert(size >= sizeof(*req)); + + /* safe as last_seen_wr_idx is validated in vmbus_channel_recv_start */ + avail = rb_idx_delta(ringbuf->rd_idx, ringbuf->last_seen_wr_idx, + ringbuf->common.len, true); + if (avail < sizeof(hdr)) { + return NULL; + } + + ringbuf_seek(&ringbuf->common, ringbuf->rd_idx); + if (ringbuf_io(&ringbuf->common, &hdr, sizeof(hdr)) < 0) { + return NULL; + } + + pktlen = hdr.len_qwords * sizeof(uint64_t); + totlen = pktlen + VMBUS_PKT_TRAILER; + if (totlen > avail) { + return NULL; + } + + msgoff = hdr.offset_qwords * sizeof(uint64_t); + if (msgoff > pktlen || msgoff < sizeof(hdr)) { + error_report("%s: malformed packet: %u %u", __func__, msgoff, pktlen); + return NULL; + } + + msglen = pktlen - msgoff; + + req = vmbus_alloc_req(chan, size, hdr.type, msglen, hdr.transaction_id, + hdr.flags & VMBUS_PACKET_FLAG_REQUEST_COMPLETION); + + switch (hdr.type) { + case VMBUS_PACKET_DATA_USING_GPA_DIRECT: + desclen = msgoff - sizeof(hdr); + if (sgl_from_gpa_ranges(&req->sgl, chan->dev, &ringbuf->common, + desclen) < 0) { + error_report("%s: failed to convert GPA ranges to SGL", __func__); + goto free_req; + } + break; + case VMBUS_PACKET_DATA_INBAND: + case VMBUS_PACKET_COMP: + break; + default: + error_report("%s: unexpected msg type: %x", __func__, hdr.type); + goto free_req; + } + + ringbuf_seek(&ringbuf->common, ringbuf->rd_idx + msgoff); + if (ringbuf_io(&ringbuf->common, req->msg, msglen) < 0) { + goto free_req; + } + ringbuf_seek(&ringbuf->common, ringbuf->rd_idx + totlen); + + return req; +free_req: + vmbus_free_req(req); + return NULL; +} + +void vmbus_channel_recv_pop(VMBusChannel *chan) +{ + VMBusRecvRingBuf *ringbuf = &chan->recv_ringbuf; + ringbuf->rd_idx = ringbuf_tell(&ringbuf->common); +} + +ssize_t vmbus_channel_recv_done(VMBusChannel *chan) +{ + VMBusRecvRingBuf *ringbuf = &chan->recv_ringbuf; + vmbus_ring_buffer *rb; + uint32_t read; + + read = rb_idx_delta(ringbuf->last_rd_idx, ringbuf->rd_idx, + ringbuf->common.len, true); + if (!read) { + return 0; + } + + rb = ringbuf_map_hdr(&ringbuf->common); + if (!rb) { + return -EFAULT; + } + + /* prevent reorder with the data operation and packet read */ + smp_mb(); /* barrier pair [B] */ + rb->read_index = ringbuf->rd_idx; + + /* prevent reorder of the following pending_send_sz read */ + smp_mb(); /* barrier pair [A] */ + + if (rb->interrupt_mask) { + goto out; + } + + if (rb->feature_bits & VMBUS_RING_BUFFER_FEAT_PENDING_SZ) { + uint32_t wr_idx, wr_avail; + uint32_t wanted = rb->pending_send_sz; + + if (!wanted) { + goto out; + } + + /* prevent reorder with pending_send_sz read */ + smp_rmb(); /* barrier pair [D] */ + wr_idx = rb->write_index; + + wr_avail = rb_idx_delta(wr_idx, ringbuf->rd_idx, ringbuf->common.len, + true); + + /* the producer wasn't blocked on the consumer state */ + if (wr_avail >= read + wanted) { + goto out; + } + /* there's not enough space for the producer to make progress */ + if (wr_avail < wanted) { + goto out; + } + } + + vmbus_channel_notify_guest(chan); +out: + ringbuf_unmap_hdr(&ringbuf->common, rb, true); + ringbuf->last_rd_idx = ringbuf->rd_idx; + return read; +} + +void vmbus_free_req(void *req) +{ + VMBusChanReq *r = req; + + if (!req) { + return; + } + + if (r->sgl.dev) { + qemu_sglist_destroy(&r->sgl); + } + g_free(req); +} + +static const VMStateDescription vmstate_sgent = { + .name = "vmbus/sgentry", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT64(base, ScatterGatherEntry), + VMSTATE_UINT64(len, ScatterGatherEntry), + VMSTATE_END_OF_LIST() + } +}; + +typedef struct VMBusChanReqSave { + uint16_t chan_idx; + uint16_t pkt_type; + uint32_t msglen; + void *msg; + uint64_t transaction_id; + bool need_comp; + uint32_t num; + ScatterGatherEntry *sgl; +} VMBusChanReqSave; + +static const VMStateDescription vmstate_vmbus_chan_req = { + .name = "vmbus/vmbus_chan_req", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT16(chan_idx, VMBusChanReqSave), + VMSTATE_UINT16(pkt_type, VMBusChanReqSave), + VMSTATE_UINT32(msglen, VMBusChanReqSave), + VMSTATE_VBUFFER_ALLOC_UINT32(msg, VMBusChanReqSave, 0, NULL, msglen), + VMSTATE_UINT64(transaction_id, VMBusChanReqSave), + VMSTATE_BOOL(need_comp, VMBusChanReqSave), + VMSTATE_UINT32(num, VMBusChanReqSave), + VMSTATE_STRUCT_VARRAY_POINTER_UINT32(sgl, VMBusChanReqSave, num, + vmstate_sgent, ScatterGatherEntry), + VMSTATE_END_OF_LIST() + } +}; + +void vmbus_save_req(QEMUFile *f, VMBusChanReq *req) +{ + VMBusChanReqSave req_save; + + req_save.chan_idx = req->chan->subchan_idx; + req_save.pkt_type = req->pkt_type; + req_save.msglen = req->msglen; + req_save.msg = req->msg; + req_save.transaction_id = req->transaction_id; + req_save.need_comp = req->need_comp; + req_save.num = req->sgl.nsg; + req_save.sgl = g_memdup(req->sgl.sg, + req_save.num * sizeof(ScatterGatherEntry)); + + vmstate_save_state(f, &vmstate_vmbus_chan_req, &req_save, NULL); + + g_free(req_save.sgl); +} + +void *vmbus_load_req(QEMUFile *f, VMBusDevice *dev, uint32_t size) +{ + VMBusChanReqSave req_save; + VMBusChanReq *req = NULL; + VMBusChannel *chan = NULL; + uint32_t i; + + vmstate_load_state(f, &vmstate_vmbus_chan_req, &req_save, 0); + + if (req_save.chan_idx >= dev->num_channels) { + error_report("%s: %u(chan_idx) > %u(num_channels)", __func__, + req_save.chan_idx, dev->num_channels); + goto out; + } + chan = &dev->channels[req_save.chan_idx]; + + if (vmbus_channel_reserve(chan, 0, req_save.msglen)) { + goto out; + } + + req = vmbus_alloc_req(chan, size, req_save.pkt_type, req_save.msglen, + req_save.transaction_id, req_save.need_comp); + if (req_save.msglen) { + memcpy(req->msg, req_save.msg, req_save.msglen); + } + + for (i = 0; i < req_save.num; i++) { + qemu_sglist_add(&req->sgl, req_save.sgl[i].base, req_save.sgl[i].len); + } + +out: + if (req_save.msglen) { + g_free(req_save.msg); + } + if (req_save.num) { + g_free(req_save.sgl); + } + return req; +} + +static void channel_event_cb(EventNotifier *e) +{ + VMBusChannel *chan = container_of(e, VMBusChannel, notifier); + if (event_notifier_test_and_clear(e)) { + /* + * All receives are supposed to happen within the device worker, so + * bracket it with ringbuf_start/end_io on the receive ringbuffer, and + * potentially reuse the cached mapping throughout the worker. + * Can't do this for sends as they may happen outside the device + * worker. + */ + VMBusRecvRingBuf *ringbuf = &chan->recv_ringbuf; + ringbuf_start_io(&ringbuf->common); + chan->notify_cb(chan); + ringbuf_end_io(&ringbuf->common); + + } +} + +static int alloc_chan_id(VMBus *vmbus) +{ + int ret; + + ret = find_next_zero_bit(vmbus->chanid_bitmap, VMBUS_CHANID_COUNT, 0); + if (ret == VMBUS_CHANID_COUNT) { + return -ENOMEM; + } + return ret + VMBUS_FIRST_CHANID; +} + +static int register_chan_id(VMBusChannel *chan) +{ + return test_and_set_bit(chan->id - VMBUS_FIRST_CHANID, + chan->vmbus->chanid_bitmap) ? -EEXIST : 0; +} + +static void unregister_chan_id(VMBusChannel *chan) +{ + clear_bit(chan->id - VMBUS_FIRST_CHANID, chan->vmbus->chanid_bitmap); +} + +static uint32_t chan_connection_id(VMBusChannel *chan) +{ + return VMBUS_CHAN_CONNECTION_OFFSET + chan->id; +} + +static void init_channel(VMBus *vmbus, VMBusDevice *dev, VMBusDeviceClass *vdc, + VMBusChannel *chan, uint16_t idx, Error **errp) +{ + int res; + + chan->dev = dev; + chan->notify_cb = vdc->chan_notify_cb; + chan->subchan_idx = idx; + chan->vmbus = vmbus; + + res = alloc_chan_id(vmbus); + if (res < 0) { + error_setg(errp, "no spare channel id"); + return; + } + chan->id = res; + register_chan_id(chan); + + /* + * The guest drivers depend on the device subchannels (idx #1+) to be + * offered after the primary channel (idx #0) of that device. To ensure + * that, record the channels on the channel list in the order they appear + * within the device. + */ + QTAILQ_INSERT_TAIL(&vmbus->channel_list, chan, link); +} + +static void deinit_channel(VMBusChannel *chan) +{ + assert(chan->state == VMCHAN_INIT); + QTAILQ_REMOVE(&chan->vmbus->channel_list, chan, link); + unregister_chan_id(chan); +} + +static void create_channels(VMBus *vmbus, VMBusDevice *dev, Error **errp) +{ + uint16_t i; + VMBusDeviceClass *vdc = VMBUS_DEVICE_GET_CLASS(dev); + Error *err = NULL; + + dev->num_channels = vdc->num_channels ? vdc->num_channels(dev) : 1; + if (dev->num_channels < 1) { + error_setg(errp, "invalid #channels: %u", dev->num_channels); + return; + } + + dev->channels = g_new0(VMBusChannel, dev->num_channels); + for (i = 0; i < dev->num_channels; i++) { + init_channel(vmbus, dev, vdc, &dev->channels[i], i, &err); + if (err) { + goto err_init; + } + } + + return; + +err_init: + while (i--) { + deinit_channel(&dev->channels[i]); + } + error_propagate(errp, err); +} + +static void free_channels(VMBusDevice *dev) +{ + uint16_t i; + for (i = 0; i < dev->num_channels; i++) { + deinit_channel(&dev->channels[i]); + } + g_free(dev->channels); +} + +static HvSintRoute *make_sint_route(VMBus *vmbus, uint32_t vp_index) +{ + VMBusChannel *chan; + + if (vp_index == vmbus->target_vp) { + hyperv_sint_route_ref(vmbus->sint_route); + return vmbus->sint_route; + } + + QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { + if (chan->target_vp == vp_index && vmbus_channel_is_open(chan)) { + hyperv_sint_route_ref(chan->notify_route); + return chan->notify_route; + } + } + + return hyperv_sint_route_new(vp_index, VMBUS_SINT, NULL, NULL); +} + +static void open_channel(VMBusChannel *chan) +{ + VMBusDeviceClass *vdc = VMBUS_DEVICE_GET_CLASS(chan->dev); + + chan->gpadl = vmbus_get_gpadl(chan, chan->ringbuf_gpadl); + if (!chan->gpadl) { + return; + } + + if (ringbufs_init(chan)) { + goto put_gpadl; + } + + if (event_notifier_init(&chan->notifier, 0)) { + goto put_gpadl; + } + + event_notifier_set_handler(&chan->notifier, channel_event_cb); + + if (hyperv_set_event_flag_handler(chan_connection_id(chan), + &chan->notifier)) { + goto cleanup_notifier; + } + + chan->notify_route = make_sint_route(chan->vmbus, chan->target_vp); + if (!chan->notify_route) { + goto clear_event_flag_handler; + } + + if (vdc->open_channel && vdc->open_channel(chan)) { + goto unref_sint_route; + } + + chan->is_open = true; + return; + +unref_sint_route: + hyperv_sint_route_unref(chan->notify_route); +clear_event_flag_handler: + hyperv_set_event_flag_handler(chan_connection_id(chan), NULL); +cleanup_notifier: + event_notifier_set_handler(&chan->notifier, NULL); + event_notifier_cleanup(&chan->notifier); +put_gpadl: + vmbus_put_gpadl(chan->gpadl); +} + +static void close_channel(VMBusChannel *chan) +{ + VMBusDeviceClass *vdc = VMBUS_DEVICE_GET_CLASS(chan->dev); + + if (!chan->is_open) { + return; + } + + if (vdc->close_channel) { + vdc->close_channel(chan); + } + + hyperv_sint_route_unref(chan->notify_route); + hyperv_set_event_flag_handler(chan_connection_id(chan), NULL); + event_notifier_set_handler(&chan->notifier, NULL); + event_notifier_cleanup(&chan->notifier); + vmbus_put_gpadl(chan->gpadl); + chan->is_open = false; +} + +static int channel_post_load(void *opaque, int version_id) +{ + VMBusChannel *chan = opaque; + + return register_chan_id(chan); +} + +static const VMStateDescription vmstate_channel = { + .name = "vmbus/channel", + .version_id = 0, + .minimum_version_id = 0, + .post_load = channel_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT32(id, VMBusChannel), + VMSTATE_UINT16(subchan_idx, VMBusChannel), + VMSTATE_UINT32(open_id, VMBusChannel), + VMSTATE_UINT32(target_vp, VMBusChannel), + VMSTATE_UINT32(ringbuf_gpadl, VMBusChannel), + VMSTATE_UINT32(ringbuf_send_offset, VMBusChannel), + VMSTATE_UINT8(offer_state, VMBusChannel), + VMSTATE_UINT8(state, VMBusChannel), + VMSTATE_END_OF_LIST() + } +}; + +static VMBusChannel *find_channel(VMBus *vmbus, uint32_t id) +{ + VMBusChannel *chan; + QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { + if (chan->id == id) { + return chan; + } + } + return NULL; +} + +static int enqueue_incoming_message(VMBus *vmbus, + const struct hyperv_post_message_input *msg) +{ + int ret = 0; + uint8_t idx, prev_size; + + qemu_mutex_lock(&vmbus->rx_queue_lock); + + if (vmbus->rx_queue_size == HV_MSG_QUEUE_LEN) { + ret = -ENOBUFS; + goto out; + } + + prev_size = vmbus->rx_queue_size; + idx = (vmbus->rx_queue_head + vmbus->rx_queue_size) % HV_MSG_QUEUE_LEN; + memcpy(&vmbus->rx_queue[idx], msg, sizeof(*msg)); + vmbus->rx_queue_size++; + + /* only need to resched if the queue was empty before */ + if (!prev_size) { + vmbus_resched(vmbus); + } +out: + qemu_mutex_unlock(&vmbus->rx_queue_lock); + return ret; +} + +static uint16_t vmbus_recv_message(const struct hyperv_post_message_input *msg, + void *data) +{ + VMBus *vmbus = data; + struct vmbus_message_header *vmbus_msg; + + if (msg->message_type != HV_MESSAGE_VMBUS) { + return HV_STATUS_INVALID_HYPERCALL_INPUT; + } + + if (msg->payload_size < sizeof(struct vmbus_message_header)) { + return HV_STATUS_INVALID_HYPERCALL_INPUT; + } + + vmbus_msg = (struct vmbus_message_header *)msg->payload; + + trace_vmbus_recv_message(vmbus_msg->message_type, msg->payload_size); + + if (vmbus_msg->message_type == VMBUS_MSG_INVALID || + vmbus_msg->message_type >= VMBUS_MSG_COUNT) { + error_report("vmbus: unknown message type %#x", + vmbus_msg->message_type); + return HV_STATUS_INVALID_HYPERCALL_INPUT; + } + + if (enqueue_incoming_message(vmbus, msg)) { + return HV_STATUS_INSUFFICIENT_BUFFERS; + } + return HV_STATUS_SUCCESS; +} + +static bool vmbus_initialized(VMBus *vmbus) +{ + return vmbus->version > 0 && vmbus->version <= VMBUS_VERSION_CURRENT; +} + +static void vmbus_reset_all(VMBus *vmbus) +{ + qbus_reset_all(BUS(vmbus)); +} + +static void post_msg(VMBus *vmbus, void *msgdata, uint32_t msglen) +{ + int ret; + struct hyperv_message msg = { + .header.message_type = HV_MESSAGE_VMBUS, + }; + + assert(!vmbus->msg_in_progress); + assert(msglen <= sizeof(msg.payload)); + assert(msglen >= sizeof(struct vmbus_message_header)); + + vmbus->msg_in_progress = true; + + trace_vmbus_post_msg(((struct vmbus_message_header *)msgdata)->message_type, + msglen); + + memcpy(msg.payload, msgdata, msglen); + msg.header.payload_size = ROUND_UP(msglen, VMBUS_MESSAGE_SIZE_ALIGN); + + ret = hyperv_post_msg(vmbus->sint_route, &msg); + if (ret == 0 || ret == -EAGAIN) { + return; + } + + error_report("message delivery fatal failure: %d; aborting vmbus", ret); + vmbus_reset_all(vmbus); +} + +static int vmbus_init(VMBus *vmbus) +{ + if (vmbus->target_vp != (uint32_t)-1) { + vmbus->sint_route = hyperv_sint_route_new(vmbus->target_vp, VMBUS_SINT, + vmbus_msg_cb, vmbus); + if (!vmbus->sint_route) { + error_report("failed to set up SINT route"); + return -ENOMEM; + } + } + return 0; +} + +static void vmbus_deinit(VMBus *vmbus) +{ + VMBusGpadl *gpadl, *tmp_gpadl; + VMBusChannel *chan; + + QTAILQ_FOREACH_SAFE(gpadl, &vmbus->gpadl_list, link, tmp_gpadl) { + if (gpadl->state == VMGPADL_TORNDOWN) { + continue; + } + vmbus_put_gpadl(gpadl); + } + + QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { + chan->offer_state = VMOFFER_INIT; + } + + hyperv_sint_route_unref(vmbus->sint_route); + vmbus->sint_route = NULL; + vmbus->int_page_gpa = 0; + vmbus->target_vp = (uint32_t)-1; + vmbus->version = 0; + vmbus->state = VMBUS_LISTEN; + vmbus->msg_in_progress = false; +} + +static void handle_initiate_contact(VMBus *vmbus, + vmbus_message_initiate_contact *msg, + uint32_t msglen) +{ + if (msglen < sizeof(*msg)) { + return; + } + + trace_vmbus_initiate_contact(msg->version_requested >> 16, + msg->version_requested & 0xffff, + msg->target_vcpu, msg->monitor_page1, + msg->monitor_page2, msg->interrupt_page); + + /* + * Reset vmbus on INITIATE_CONTACT regardless of its previous state. + * Useful, in particular, with vmbus-aware BIOS which can't shut vmbus down + * before handing over to OS loader. + */ + vmbus_reset_all(vmbus); + + vmbus->target_vp = msg->target_vcpu; + vmbus->version = msg->version_requested; + if (vmbus->version < VMBUS_VERSION_WIN8) { + /* linux passes interrupt page even when it doesn't need it */ + vmbus->int_page_gpa = msg->interrupt_page; + } + vmbus->state = VMBUS_HANDSHAKE; + + if (vmbus_init(vmbus)) { + error_report("failed to init vmbus; aborting"); + vmbus_deinit(vmbus); + return; + } +} + +static void send_handshake(VMBus *vmbus) +{ + struct vmbus_message_version_response msg = { + .header.message_type = VMBUS_MSG_VERSION_RESPONSE, + .version_supported = vmbus_initialized(vmbus), + }; + + post_msg(vmbus, &msg, sizeof(msg)); +} + +static void handle_request_offers(VMBus *vmbus, void *msgdata, uint32_t msglen) +{ + VMBusChannel *chan; + + if (!vmbus_initialized(vmbus)) { + return; + } + + QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { + if (chan->offer_state == VMOFFER_INIT) { + chan->offer_state = VMOFFER_SENDING; + break; + } + } + + vmbus->state = VMBUS_OFFER; +} + +static void send_offer(VMBus *vmbus) +{ + VMBusChannel *chan; + struct vmbus_message_header alloffers_msg = { + .message_type = VMBUS_MSG_ALLOFFERS_DELIVERED, + }; + + QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { + if (chan->offer_state == VMOFFER_SENDING) { + VMBusDeviceClass *vdc = VMBUS_DEVICE_GET_CLASS(chan->dev); + /* Hyper-V wants LE GUIDs */ + QemuUUID classid = qemu_uuid_bswap(vdc->classid); + QemuUUID instanceid = qemu_uuid_bswap(chan->dev->instanceid); + struct vmbus_message_offer_channel msg = { + .header.message_type = VMBUS_MSG_OFFERCHANNEL, + .child_relid = chan->id, + .connection_id = chan_connection_id(chan), + .channel_flags = vdc->channel_flags, + .mmio_size_mb = vdc->mmio_size_mb, + .sub_channel_index = vmbus_channel_idx(chan), + .interrupt_flags = VMBUS_OFFER_INTERRUPT_DEDICATED, + }; + + memcpy(msg.type_uuid, &classid, sizeof(classid)); + memcpy(msg.instance_uuid, &instanceid, sizeof(instanceid)); + + trace_vmbus_send_offer(chan->id, chan->dev); + + post_msg(vmbus, &msg, sizeof(msg)); + return; + } + } + + /* no more offers, send terminator message */ + trace_vmbus_terminate_offers(); + post_msg(vmbus, &alloffers_msg, sizeof(alloffers_msg)); +} + +static bool complete_offer(VMBus *vmbus) +{ + VMBusChannel *chan; + + QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { + if (chan->offer_state == VMOFFER_SENDING) { + chan->offer_state = VMOFFER_SENT; + goto next_offer; + } + } + /* + * no transitioning channels found so this is completing the terminator + * message, and vmbus can move to the next state + */ + return true; + +next_offer: + /* try to mark another channel for offering */ + QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { + if (chan->offer_state == VMOFFER_INIT) { + chan->offer_state = VMOFFER_SENDING; + break; + } + } + /* + * if an offer has been sent there are more offers or the terminator yet to + * send, so no state transition for vmbus + */ + return false; +} + + +static void handle_gpadl_header(VMBus *vmbus, vmbus_message_gpadl_header *msg, + uint32_t msglen) +{ + VMBusGpadl *gpadl; + uint32_t num_gfns, i; + + /* must include at least one gpa range */ + if (msglen < sizeof(*msg) + sizeof(msg->range[0]) || + !vmbus_initialized(vmbus)) { + return; + } + + num_gfns = (msg->range_buflen - msg->rangecount * sizeof(msg->range[0])) / + sizeof(msg->range[0].pfn_array[0]); + + trace_vmbus_gpadl_header(msg->gpadl_id, num_gfns); + + /* + * In theory the GPADL_HEADER message can define a GPADL with multiple GPA + * ranges each with arbitrary size and alignment. However in practice only + * single-range page-aligned GPADLs have been observed so just ignore + * anything else and simplify things greatly. + */ + if (msg->rangecount != 1 || msg->range[0].byte_offset || + (msg->range[0].byte_count != (num_gfns << TARGET_PAGE_BITS))) { + return; + } + + /* ignore requests to create already existing GPADLs */ + if (find_gpadl(vmbus, msg->gpadl_id)) { + return; + } + + gpadl = create_gpadl(vmbus, msg->gpadl_id, msg->child_relid, num_gfns); + + for (i = 0; i < num_gfns && + (void *)&msg->range[0].pfn_array[i + 1] <= (void *)msg + msglen; + i++) { + gpadl->gfns[gpadl->seen_gfns++] = msg->range[0].pfn_array[i]; + } + + if (gpadl_full(gpadl)) { + vmbus->state = VMBUS_CREATE_GPADL; + } +} + +static void handle_gpadl_body(VMBus *vmbus, vmbus_message_gpadl_body *msg, + uint32_t msglen) +{ + VMBusGpadl *gpadl; + uint32_t num_gfns_left, i; + + if (msglen < sizeof(*msg) || !vmbus_initialized(vmbus)) { + return; + } + + trace_vmbus_gpadl_body(msg->gpadl_id); + + gpadl = find_gpadl(vmbus, msg->gpadl_id); + if (!gpadl) { + return; + } + + num_gfns_left = gpadl->num_gfns - gpadl->seen_gfns; + assert(num_gfns_left); + + for (i = 0; i < num_gfns_left && + (void *)&msg->pfn_array[i + 1] <= (void *)msg + msglen; i++) { + gpadl->gfns[gpadl->seen_gfns++] = msg->pfn_array[i]; + } + + if (gpadl_full(gpadl)) { + vmbus->state = VMBUS_CREATE_GPADL; + } +} + +static void send_create_gpadl(VMBus *vmbus) +{ + VMBusGpadl *gpadl; + + QTAILQ_FOREACH(gpadl, &vmbus->gpadl_list, link) { + if (gpadl_full(gpadl) && gpadl->state == VMGPADL_INIT) { + struct vmbus_message_gpadl_created msg = { + .header.message_type = VMBUS_MSG_GPADL_CREATED, + .gpadl_id = gpadl->id, + .child_relid = gpadl->child_relid, + }; + + trace_vmbus_gpadl_created(gpadl->id); + post_msg(vmbus, &msg, sizeof(msg)); + return; + } + } + + assert(false); +} + +static bool complete_create_gpadl(VMBus *vmbus) +{ + VMBusGpadl *gpadl; + + QTAILQ_FOREACH(gpadl, &vmbus->gpadl_list, link) { + if (gpadl_full(gpadl) && gpadl->state == VMGPADL_INIT) { + gpadl->state = VMGPADL_ALIVE; + + return true; + } + } + + assert(false); + return false; +} + +static void handle_gpadl_teardown(VMBus *vmbus, + vmbus_message_gpadl_teardown *msg, + uint32_t msglen) +{ + VMBusGpadl *gpadl; + + if (msglen < sizeof(*msg) || !vmbus_initialized(vmbus)) { + return; + } + + trace_vmbus_gpadl_teardown(msg->gpadl_id); + + gpadl = find_gpadl(vmbus, msg->gpadl_id); + if (!gpadl || gpadl->state == VMGPADL_TORNDOWN) { + return; + } + + gpadl->state = VMGPADL_TEARINGDOWN; + vmbus->state = VMBUS_TEARDOWN_GPADL; +} + +static void send_teardown_gpadl(VMBus *vmbus) +{ + VMBusGpadl *gpadl; + + QTAILQ_FOREACH(gpadl, &vmbus->gpadl_list, link) { + if (gpadl->state == VMGPADL_TEARINGDOWN) { + struct vmbus_message_gpadl_torndown msg = { + .header.message_type = VMBUS_MSG_GPADL_TORNDOWN, + .gpadl_id = gpadl->id, + }; + + trace_vmbus_gpadl_torndown(gpadl->id); + post_msg(vmbus, &msg, sizeof(msg)); + return; + } + } + + assert(false); +} + +static bool complete_teardown_gpadl(VMBus *vmbus) +{ + VMBusGpadl *gpadl; + + QTAILQ_FOREACH(gpadl, &vmbus->gpadl_list, link) { + if (gpadl->state == VMGPADL_TEARINGDOWN) { + gpadl->state = VMGPADL_TORNDOWN; + vmbus_put_gpadl(gpadl); + return true; + } + } + + assert(false); + return false; +} + +static void handle_open_channel(VMBus *vmbus, vmbus_message_open_channel *msg, + uint32_t msglen) +{ + VMBusChannel *chan; + + if (msglen < sizeof(*msg) || !vmbus_initialized(vmbus)) { + return; + } + + trace_vmbus_open_channel(msg->child_relid, msg->ring_buffer_gpadl_id, + msg->target_vp); + chan = find_channel(vmbus, msg->child_relid); + if (!chan || chan->state != VMCHAN_INIT) { + return; + } + + chan->ringbuf_gpadl = msg->ring_buffer_gpadl_id; + chan->ringbuf_send_offset = msg->ring_buffer_offset; + chan->target_vp = msg->target_vp; + chan->open_id = msg->open_id; + + open_channel(chan); + + chan->state = VMCHAN_OPENING; + vmbus->state = VMBUS_OPEN_CHANNEL; +} + +static void send_open_channel(VMBus *vmbus) +{ + VMBusChannel *chan; + + QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { + if (chan->state == VMCHAN_OPENING) { + struct vmbus_message_open_result msg = { + .header.message_type = VMBUS_MSG_OPENCHANNEL_RESULT, + .child_relid = chan->id, + .open_id = chan->open_id, + .status = !vmbus_channel_is_open(chan), + }; + + trace_vmbus_channel_open(chan->id, msg.status); + post_msg(vmbus, &msg, sizeof(msg)); + return; + } + } + + assert(false); +} + +static bool complete_open_channel(VMBus *vmbus) +{ + VMBusChannel *chan; + + QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { + if (chan->state == VMCHAN_OPENING) { + if (vmbus_channel_is_open(chan)) { + chan->state = VMCHAN_OPEN; + /* + * simulate guest notification of ringbuffer space made + * available, for the channel protocols where the host + * initiates the communication + */ + vmbus_channel_notify_host(chan); + } else { + chan->state = VMCHAN_INIT; + } + return true; + } + } + + assert(false); + return false; +} + +static void vdev_reset_on_close(VMBusDevice *vdev) +{ + uint16_t i; + + for (i = 0; i < vdev->num_channels; i++) { + if (vmbus_channel_is_open(&vdev->channels[i])) { + return; + } + } + + /* all channels closed -- reset device */ + qdev_reset_all(DEVICE(vdev)); +} + +static void handle_close_channel(VMBus *vmbus, vmbus_message_close_channel *msg, + uint32_t msglen) +{ + VMBusChannel *chan; + + if (msglen < sizeof(*msg) || !vmbus_initialized(vmbus)) { + return; + } + + trace_vmbus_close_channel(msg->child_relid); + + chan = find_channel(vmbus, msg->child_relid); + if (!chan) { + return; + } + + close_channel(chan); + chan->state = VMCHAN_INIT; + + vdev_reset_on_close(chan->dev); +} + +static void handle_unload(VMBus *vmbus, void *msg, uint32_t msglen) +{ + vmbus->state = VMBUS_UNLOAD; +} + +static void send_unload(VMBus *vmbus) +{ + vmbus_message_header msg = { + .message_type = VMBUS_MSG_UNLOAD_RESPONSE, + }; + + qemu_mutex_lock(&vmbus->rx_queue_lock); + vmbus->rx_queue_size = 0; + qemu_mutex_unlock(&vmbus->rx_queue_lock); + + post_msg(vmbus, &msg, sizeof(msg)); + return; +} + +static bool complete_unload(VMBus *vmbus) +{ + vmbus_reset_all(vmbus); + return true; +} + +static void process_message(VMBus *vmbus) +{ + struct hyperv_post_message_input *hv_msg; + struct vmbus_message_header *msg; + void *msgdata; + uint32_t msglen; + + qemu_mutex_lock(&vmbus->rx_queue_lock); + + if (!vmbus->rx_queue_size) { + goto unlock; + } + + hv_msg = &vmbus->rx_queue[vmbus->rx_queue_head]; + msglen = hv_msg->payload_size; + if (msglen < sizeof(*msg)) { + goto out; + } + msgdata = hv_msg->payload; + msg = (struct vmbus_message_header *)msgdata; + + trace_vmbus_process_incoming_message(msg->message_type); + + switch (msg->message_type) { + case VMBUS_MSG_INITIATE_CONTACT: + handle_initiate_contact(vmbus, msgdata, msglen); + break; + case VMBUS_MSG_REQUESTOFFERS: + handle_request_offers(vmbus, msgdata, msglen); + break; + case VMBUS_MSG_GPADL_HEADER: + handle_gpadl_header(vmbus, msgdata, msglen); + break; + case VMBUS_MSG_GPADL_BODY: + handle_gpadl_body(vmbus, msgdata, msglen); + break; + case VMBUS_MSG_GPADL_TEARDOWN: + handle_gpadl_teardown(vmbus, msgdata, msglen); + break; + case VMBUS_MSG_OPENCHANNEL: + handle_open_channel(vmbus, msgdata, msglen); + break; + case VMBUS_MSG_CLOSECHANNEL: + handle_close_channel(vmbus, msgdata, msglen); + break; + case VMBUS_MSG_UNLOAD: + handle_unload(vmbus, msgdata, msglen); + break; + default: + error_report("unknown message type %#x", msg->message_type); + break; + } + +out: + vmbus->rx_queue_size--; + vmbus->rx_queue_head++; + vmbus->rx_queue_head %= HV_MSG_QUEUE_LEN; + + vmbus_resched(vmbus); +unlock: + qemu_mutex_unlock(&vmbus->rx_queue_lock); +} + +static const struct { + void (*run)(VMBus *vmbus); + bool (*complete)(VMBus *vmbus); +} state_runner[] = { + [VMBUS_LISTEN] = {process_message, NULL}, + [VMBUS_HANDSHAKE] = {send_handshake, NULL}, + [VMBUS_OFFER] = {send_offer, complete_offer}, + [VMBUS_CREATE_GPADL] = {send_create_gpadl, complete_create_gpadl}, + [VMBUS_TEARDOWN_GPADL] = {send_teardown_gpadl, complete_teardown_gpadl}, + [VMBUS_OPEN_CHANNEL] = {send_open_channel, complete_open_channel}, + [VMBUS_UNLOAD] = {send_unload, complete_unload}, +}; + +static void vmbus_do_run(VMBus *vmbus) +{ + if (vmbus->msg_in_progress) { + return; + } + + assert(vmbus->state < VMBUS_STATE_MAX); + assert(state_runner[vmbus->state].run); + state_runner[vmbus->state].run(vmbus); +} + +static void vmbus_run(void *opaque) +{ + VMBus *vmbus = opaque; + + /* make sure no recursion happens (e.g. due to recursive aio_poll()) */ + if (vmbus->in_progress) { + return; + } + + vmbus->in_progress = true; + /* + * FIXME: if vmbus_resched() is called from within vmbus_do_run(), it + * should go *after* the code that can result in aio_poll; otherwise + * reschedules can be missed. No idea how to enforce that. + */ + vmbus_do_run(vmbus); + vmbus->in_progress = false; +} + +static void vmbus_msg_cb(void *data, int status) +{ + VMBus *vmbus = data; + bool (*complete)(VMBus *vmbus); + + assert(vmbus->msg_in_progress); + + trace_vmbus_msg_cb(status); + + if (status == -EAGAIN) { + goto out; + } + if (status) { + error_report("message delivery fatal failure: %d; aborting vmbus", + status); + vmbus_reset_all(vmbus); + return; + } + + assert(vmbus->state < VMBUS_STATE_MAX); + complete = state_runner[vmbus->state].complete; + if (!complete || complete(vmbus)) { + vmbus->state = VMBUS_LISTEN; + } +out: + vmbus->msg_in_progress = false; + vmbus_resched(vmbus); +} + +static void vmbus_resched(VMBus *vmbus) +{ + aio_bh_schedule_oneshot(qemu_get_aio_context(), vmbus_run, vmbus); +} + +static void vmbus_signal_event(EventNotifier *e) +{ + VMBusChannel *chan; + VMBus *vmbus = container_of(e, VMBus, notifier); + unsigned long *int_map; + hwaddr addr, len; + bool is_dirty = false; + + if (!event_notifier_test_and_clear(e)) { + return; + } + + trace_vmbus_signal_event(); + + if (!vmbus->int_page_gpa) { + return; + } + + addr = vmbus->int_page_gpa + TARGET_PAGE_SIZE / 2; + len = TARGET_PAGE_SIZE / 2; + int_map = cpu_physical_memory_map(addr, &len, 1); + if (len != TARGET_PAGE_SIZE / 2) { + goto unmap; + } + + QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { + if (bitmap_test_and_clear_atomic(int_map, chan->id, 1)) { + if (!vmbus_channel_is_open(chan)) { + continue; + } + vmbus_channel_notify_host(chan); + is_dirty = true; + } + } + +unmap: + cpu_physical_memory_unmap(int_map, len, 1, is_dirty); +} + +static void vmbus_dev_realize(DeviceState *dev, Error **errp) +{ + VMBusDevice *vdev = VMBUS_DEVICE(dev); + VMBusDeviceClass *vdc = VMBUS_DEVICE_GET_CLASS(vdev); + VMBus *vmbus = VMBUS(qdev_get_parent_bus(dev)); + BusChild *child; + Error *err = NULL; + char idstr[UUID_FMT_LEN + 1]; + + assert(!qemu_uuid_is_null(&vdev->instanceid)); + + /* Check for instance id collision for this class id */ + QTAILQ_FOREACH(child, &BUS(vmbus)->children, sibling) { + VMBusDevice *child_dev = VMBUS_DEVICE(child->child); + + if (child_dev == vdev) { + continue; + } + + if (qemu_uuid_is_equal(&child_dev->instanceid, &vdev->instanceid)) { + qemu_uuid_unparse(&vdev->instanceid, idstr); + error_setg(&err, "duplicate vmbus device instance id %s", idstr); + goto error_out; + } + } + + vdev->dma_as = &address_space_memory; + + create_channels(vmbus, vdev, &err); + if (err) { + goto error_out; + } + + if (vdc->vmdev_realize) { + vdc->vmdev_realize(vdev, &err); + if (err) { + goto err_vdc_realize; + } + } + return; + +err_vdc_realize: + free_channels(vdev); +error_out: + error_propagate(errp, err); +} + +static void vmbus_dev_reset(DeviceState *dev) +{ + uint16_t i; + VMBusDevice *vdev = VMBUS_DEVICE(dev); + VMBusDeviceClass *vdc = VMBUS_DEVICE_GET_CLASS(vdev); + + if (vdev->channels) { + for (i = 0; i < vdev->num_channels; i++) { + VMBusChannel *chan = &vdev->channels[i]; + close_channel(chan); + chan->state = VMCHAN_INIT; + } + } + + if (vdc->vmdev_reset) { + vdc->vmdev_reset(vdev); + } +} + +static void vmbus_dev_unrealize(DeviceState *dev) +{ + VMBusDevice *vdev = VMBUS_DEVICE(dev); + VMBusDeviceClass *vdc = VMBUS_DEVICE_GET_CLASS(vdev); + + if (vdc->vmdev_unrealize) { + vdc->vmdev_unrealize(vdev); + } + free_channels(vdev); +} + +static void vmbus_dev_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *kdev = DEVICE_CLASS(klass); + kdev->bus_type = TYPE_VMBUS; + kdev->realize = vmbus_dev_realize; + kdev->unrealize = vmbus_dev_unrealize; + kdev->reset = vmbus_dev_reset; +} + +static Property vmbus_dev_instanceid = + DEFINE_PROP_UUID("instanceid", VMBusDevice, instanceid); + +static void vmbus_dev_instance_init(Object *obj) +{ + VMBusDevice *vdev = VMBUS_DEVICE(obj); + VMBusDeviceClass *vdc = VMBUS_DEVICE_GET_CLASS(vdev); + + if (!qemu_uuid_is_null(&vdc->instanceid)) { + /* Class wants to only have a single instance with a fixed UUID */ + vdev->instanceid = vdc->instanceid; + } else { + qdev_property_add_static(DEVICE(vdev), &vmbus_dev_instanceid); + } +} + +const VMStateDescription vmstate_vmbus_dev = { + .name = TYPE_VMBUS_DEVICE, + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT8_ARRAY(instanceid.data, VMBusDevice, 16), + VMSTATE_UINT16(num_channels, VMBusDevice), + VMSTATE_STRUCT_VARRAY_POINTER_UINT16(channels, VMBusDevice, + num_channels, vmstate_channel, + VMBusChannel), + VMSTATE_END_OF_LIST() + } +}; + +/* vmbus generic device base */ +static const TypeInfo vmbus_dev_type_info = { + .name = TYPE_VMBUS_DEVICE, + .parent = TYPE_DEVICE, + .abstract = true, + .instance_size = sizeof(VMBusDevice), + .class_size = sizeof(VMBusDeviceClass), + .class_init = vmbus_dev_class_init, + .instance_init = vmbus_dev_instance_init, +}; + +static void vmbus_realize(BusState *bus, Error **errp) +{ + int ret = 0; + Error *local_err = NULL; + VMBus *vmbus = VMBUS(bus); + + qemu_mutex_init(&vmbus->rx_queue_lock); + + QTAILQ_INIT(&vmbus->gpadl_list); + QTAILQ_INIT(&vmbus->channel_list); + + ret = hyperv_set_msg_handler(VMBUS_MESSAGE_CONNECTION_ID, + vmbus_recv_message, vmbus); + if (ret != 0) { + error_setg(&local_err, "hyperv set message handler failed: %d", ret); + goto error_out; + } + + ret = event_notifier_init(&vmbus->notifier, 0); + if (ret != 0) { + error_setg(&local_err, "event notifier failed to init with %d", ret); + goto remove_msg_handler; + } + + event_notifier_set_handler(&vmbus->notifier, vmbus_signal_event); + ret = hyperv_set_event_flag_handler(VMBUS_EVENT_CONNECTION_ID, + &vmbus->notifier); + if (ret != 0) { + error_setg(&local_err, "hyperv set event handler failed with %d", ret); + goto clear_event_notifier; + } + + return; + +clear_event_notifier: + event_notifier_cleanup(&vmbus->notifier); +remove_msg_handler: + hyperv_set_msg_handler(VMBUS_MESSAGE_CONNECTION_ID, NULL, NULL); +error_out: + qemu_mutex_destroy(&vmbus->rx_queue_lock); + error_propagate(errp, local_err); +} + +static void vmbus_unrealize(BusState *bus) +{ + VMBus *vmbus = VMBUS(bus); + + hyperv_set_msg_handler(VMBUS_MESSAGE_CONNECTION_ID, NULL, NULL); + hyperv_set_event_flag_handler(VMBUS_EVENT_CONNECTION_ID, NULL); + event_notifier_cleanup(&vmbus->notifier); + + qemu_mutex_destroy(&vmbus->rx_queue_lock); +} + +static void vmbus_reset(BusState *bus) +{ + vmbus_deinit(VMBUS(bus)); +} + +static char *vmbus_get_dev_path(DeviceState *dev) +{ + BusState *bus = qdev_get_parent_bus(dev); + return qdev_get_dev_path(bus->parent); +} + +static char *vmbus_get_fw_dev_path(DeviceState *dev) +{ + VMBusDevice *vdev = VMBUS_DEVICE(dev); + char uuid[UUID_FMT_LEN + 1]; + + qemu_uuid_unparse(&vdev->instanceid, uuid); + return g_strdup_printf("%s@%s", qdev_fw_name(dev), uuid); +} + +static void vmbus_class_init(ObjectClass *klass, void *data) +{ + BusClass *k = BUS_CLASS(klass); + + k->get_dev_path = vmbus_get_dev_path; + k->get_fw_dev_path = vmbus_get_fw_dev_path; + k->realize = vmbus_realize; + k->unrealize = vmbus_unrealize; + k->reset = vmbus_reset; +} + +static int vmbus_pre_load(void *opaque) +{ + VMBusChannel *chan; + VMBus *vmbus = VMBUS(opaque); + + /* + * channel IDs allocated by the source will come in the migration stream + * for each channel, so clean up the ones allocated at realize + */ + QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { + unregister_chan_id(chan); + } + + return 0; +} +static int vmbus_post_load(void *opaque, int version_id) +{ + int ret; + VMBus *vmbus = VMBUS(opaque); + VMBusGpadl *gpadl; + VMBusChannel *chan; + + ret = vmbus_init(vmbus); + if (ret) { + return ret; + } + + QTAILQ_FOREACH(gpadl, &vmbus->gpadl_list, link) { + gpadl->vmbus = vmbus; + gpadl->refcount = 1; + } + + /* + * reopening channels depends on initialized vmbus so it's done here + * instead of channel_post_load() + */ + QTAILQ_FOREACH(chan, &vmbus->channel_list, link) { + + if (chan->state == VMCHAN_OPENING || chan->state == VMCHAN_OPEN) { + open_channel(chan); + } + + if (chan->state != VMCHAN_OPEN) { + continue; + } + + if (!vmbus_channel_is_open(chan)) { + /* reopen failed, abort loading */ + return -1; + } + + /* resume processing on the guest side if it missed the notification */ + hyperv_sint_route_set_sint(chan->notify_route); + /* ditto on the host side */ + vmbus_channel_notify_host(chan); + } + + vmbus_resched(vmbus); + return 0; +} + +static const VMStateDescription vmstate_post_message_input = { + .name = "vmbus/hyperv_post_message_input", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + /* + * skip connection_id and message_type as they are validated before + * queueing and ignored on dequeueing + */ + VMSTATE_UINT32(payload_size, struct hyperv_post_message_input), + VMSTATE_UINT8_ARRAY(payload, struct hyperv_post_message_input, + HV_MESSAGE_PAYLOAD_SIZE), + VMSTATE_END_OF_LIST() + } +}; + +static bool vmbus_rx_queue_needed(void *opaque) +{ + VMBus *vmbus = VMBUS(opaque); + return vmbus->rx_queue_size; +} + +static const VMStateDescription vmstate_rx_queue = { + .name = "vmbus/rx_queue", + .version_id = 0, + .minimum_version_id = 0, + .needed = vmbus_rx_queue_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT8(rx_queue_head, VMBus), + VMSTATE_UINT8(rx_queue_size, VMBus), + VMSTATE_STRUCT_ARRAY(rx_queue, VMBus, + HV_MSG_QUEUE_LEN, 0, + vmstate_post_message_input, + struct hyperv_post_message_input), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_vmbus = { + .name = TYPE_VMBUS, + .version_id = 0, + .minimum_version_id = 0, + .pre_load = vmbus_pre_load, + .post_load = vmbus_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT8(state, VMBus), + VMSTATE_UINT32(version, VMBus), + VMSTATE_UINT32(target_vp, VMBus), + VMSTATE_UINT64(int_page_gpa, VMBus), + VMSTATE_QTAILQ_V(gpadl_list, VMBus, 0, + vmstate_gpadl, VMBusGpadl, link), + VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription * []) { + &vmstate_rx_queue, + NULL + } +}; + +static const TypeInfo vmbus_type_info = { + .name = TYPE_VMBUS, + .parent = TYPE_BUS, + .instance_size = sizeof(VMBus), + .class_init = vmbus_class_init, +}; + +static void vmbus_bridge_realize(DeviceState *dev, Error **errp) +{ + VMBusBridge *bridge = VMBUS_BRIDGE(dev); + + /* + * here there's at least one vmbus bridge that is being realized, so + * vmbus_bridge_find can only return NULL if it's not unique + */ + if (!vmbus_bridge_find()) { + error_setg(errp, "there can be at most one %s in the system", + TYPE_VMBUS_BRIDGE); + return; + } + + if (!hyperv_is_synic_enabled()) { + error_report("VMBus requires usable Hyper-V SynIC and VP_INDEX"); + return; + } + + bridge->bus = VMBUS(qbus_create(TYPE_VMBUS, dev, "vmbus")); +} + +static char *vmbus_bridge_ofw_unit_address(const SysBusDevice *dev) +{ + /* there can be only one VMBus */ + return g_strdup("0"); +} + +static const VMStateDescription vmstate_vmbus_bridge = { + .name = TYPE_VMBUS_BRIDGE, + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_STRUCT_POINTER(bus, VMBusBridge, vmstate_vmbus, VMBus), + VMSTATE_END_OF_LIST() + }, +}; + +static Property vmbus_bridge_props[] = { + DEFINE_PROP_UINT8("irq", VMBusBridge, irq, 7), + DEFINE_PROP_END_OF_LIST() +}; + +static void vmbus_bridge_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *k = DEVICE_CLASS(klass); + SysBusDeviceClass *sk = SYS_BUS_DEVICE_CLASS(klass); + + k->realize = vmbus_bridge_realize; + k->fw_name = "vmbus"; + sk->explicit_ofw_unit_address = vmbus_bridge_ofw_unit_address; + set_bit(DEVICE_CATEGORY_BRIDGE, k->categories); + k->vmsd = &vmstate_vmbus_bridge; + device_class_set_props(k, vmbus_bridge_props); + /* override SysBusDevice's default */ + k->user_creatable = true; +} + +static const TypeInfo vmbus_bridge_type_info = { + .name = TYPE_VMBUS_BRIDGE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(VMBusBridge), + .class_init = vmbus_bridge_class_init, +}; + +static void vmbus_register_types(void) +{ + type_register_static(&vmbus_bridge_type_info); + type_register_static(&vmbus_dev_type_info); + type_register_static(&vmbus_type_info); +} + +type_init(vmbus_register_types) diff --git a/hw/i2c/Kconfig b/hw/i2c/Kconfig index 2bbd395813c8810efaf6c59d1dcb0199693fe61e..09642a6dcb726ba68b605998bc0e7e9e21aadaf7 100644 --- a/hw/i2c/Kconfig +++ b/hw/i2c/Kconfig @@ -1,9 +1,13 @@ config I2C bool +config SMBUS + bool + select I2C + config SMBUS_EEPROM bool - depends on I2C + select SMBUS config VERSATILE_I2C bool @@ -11,7 +15,7 @@ config VERSATILE_I2C config ACPI_SMBUS bool - select I2C + select SMBUS config BITBANG_I2C bool diff --git a/hw/i2c/Makefile.objs b/hw/i2c/Makefile.objs deleted file mode 100644 index 6ba976b257f7f2e0a40888f785d00c0ead1851b9..0000000000000000000000000000000000000000 --- a/hw/i2c/Makefile.objs +++ /dev/null @@ -1,13 +0,0 @@ -common-obj-$(CONFIG_I2C) += core.o smbus_slave.o smbus_master.o -common-obj-$(CONFIG_SMBUS_EEPROM) += smbus_eeprom.o -common-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o -common-obj-$(CONFIG_ACPI_X86_ICH) += smbus_ich9.o -common-obj-$(CONFIG_ACPI_SMBUS) += pm_smbus.o -common-obj-$(CONFIG_BITBANG_I2C) += bitbang_i2c.o -common-obj-$(CONFIG_EXYNOS4) += exynos4210_i2c.o -common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o -common-obj-$(CONFIG_ASPEED_SOC) += aspeed_i2c.o -common-obj-$(CONFIG_NRF51_SOC) += microbit_i2c.o -common-obj-$(CONFIG_MPC_I2C) += mpc_i2c.o -common-obj-$(CONFIG_OMAP) += omap_i2c.o -common-obj-$(CONFIG_PPC4XX) += ppc4xx_i2c.o diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c index fb973a983dcd78dcd296665c9ca7311b98fa4a2e..518a3f5c6f9db9837c50b18a43711ba892421e36 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -959,9 +959,8 @@ static void aspeed_i2c_register_types(void) type_init(aspeed_i2c_register_types) -I2CBus *aspeed_i2c_get_bus(DeviceState *dev, int busnr) +I2CBus *aspeed_i2c_get_bus(AspeedI2CState *s, int busnr) { - AspeedI2CState *s = ASPEED_I2C(dev); AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(s); I2CBus *bus = NULL; diff --git a/hw/i2c/bitbang_i2c.c b/hw/i2c/bitbang_i2c.c index b000952b98a808d39441d2de73be4c489ba475d0..e9a0612a0434390abd27909e487a448fae116993 100644 --- a/hw/i2c/bitbang_i2c.c +++ b/hw/i2c/bitbang_i2c.c @@ -15,6 +15,7 @@ #include "hw/i2c/bitbang_i2c.h" #include "hw/sysbus.h" #include "qemu/module.h" +#include "qom/object.h" //#define DEBUG_BITBANG_I2C @@ -162,16 +163,16 @@ void bitbang_i2c_init(bitbang_i2c_interface *s, I2CBus *bus) /* GPIO interface. */ #define TYPE_GPIO_I2C "gpio_i2c" -#define GPIO_I2C(obj) OBJECT_CHECK(GPIOI2CState, (obj), TYPE_GPIO_I2C) +OBJECT_DECLARE_SIMPLE_TYPE(GPIOI2CState, GPIO_I2C) -typedef struct GPIOI2CState { +struct GPIOI2CState { SysBusDevice parent_obj; MemoryRegion dummy_iomem; bitbang_i2c_interface bitbang; int last_level; qemu_irq out; -} GPIOI2CState; +}; static void bitbang_i2c_gpio_set(void *opaque, int irq, int level) { diff --git a/hw/i2c/core.c b/hw/i2c/core.c index d413a192eddf97db26c2cfc082286bf6d718afb0..21ec52ac5ade21ef5d25075eb1f4bf946849d8e6 100644 --- a/hw/i2c/core.c +++ b/hw/i2c/core.c @@ -11,6 +11,7 @@ #include "hw/i2c/i2c.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" +#include "qapi/error.h" #include "qemu/module.h" #include "trace.h" @@ -266,13 +267,26 @@ const VMStateDescription vmstate_i2c_slave = { } }; -DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr) +I2CSlave *i2c_slave_new(const char *name, uint8_t addr) { DeviceState *dev; - dev = qdev_create(&bus->qbus, name); + dev = qdev_new(name); qdev_prop_set_uint8(dev, "address", addr); - qdev_init_nofail(dev); + return I2C_SLAVE(dev); +} + +bool i2c_slave_realize_and_unref(I2CSlave *dev, I2CBus *bus, Error **errp) +{ + return qdev_realize_and_unref(&dev->qdev, &bus->qbus, errp); +} + +I2CSlave *i2c_slave_create_simple(I2CBus *bus, const char *name, uint8_t addr) +{ + I2CSlave *dev = i2c_slave_new(name, addr); + + i2c_slave_realize_and_unref(dev, bus, &error_abort); + return dev; } diff --git a/hw/i2c/exynos4210_i2c.c b/hw/i2c/exynos4210_i2c.c index a600f655605e97f192be7ac730575cfbfebc215d..b65a7d0222ef42ba8b535d0337d92c2a9439f626 100644 --- a/hw/i2c/exynos4210_i2c.c +++ b/hw/i2c/exynos4210_i2c.c @@ -27,14 +27,14 @@ #include "migration/vmstate.h" #include "hw/i2c/i2c.h" #include "hw/irq.h" +#include "qom/object.h" #ifndef EXYNOS4_I2C_DEBUG #define EXYNOS4_I2C_DEBUG 0 #endif #define TYPE_EXYNOS4_I2C "exynos4210.i2c" -#define EXYNOS4_I2C(obj) \ - OBJECT_CHECK(Exynos4210I2CState, (obj), TYPE_EXYNOS4_I2C) +OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210I2CState, EXYNOS4_I2C) /* Exynos4210 I2C memory map */ #define EXYNOS4_I2C_MEM_SIZE 0x14 @@ -83,7 +83,7 @@ static const char *exynos4_i2c_get_regname(unsigned offset) #define DPRINT(fmt, args...) do { } while (0) #endif -typedef struct Exynos4210I2CState { +struct Exynos4210I2CState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -96,7 +96,7 @@ typedef struct Exynos4210I2CState { uint8_t i2cds; uint8_t i2clc; bool scl_free; -} Exynos4210I2CState; +}; static inline void exynos4210_i2c_raise_interrupt(Exynos4210I2CState *s) { diff --git a/hw/i2c/meson.build b/hw/i2c/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..3a511539ad2453d1b0c94d895d991e6a376ade5a --- /dev/null +++ b/hw/i2c/meson.build @@ -0,0 +1,16 @@ +i2c_ss = ss.source_set() +i2c_ss.add(when: 'CONFIG_I2C', if_true: files('core.c')) +i2c_ss.add(when: 'CONFIG_SMBUS', if_true: files('smbus_slave.c', 'smbus_master.c')) +i2c_ss.add(when: 'CONFIG_ACPI_SMBUS', if_true: files('pm_smbus.c')) +i2c_ss.add(when: 'CONFIG_ACPI_X86_ICH', if_true: files('smbus_ich9.c')) +i2c_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_i2c.c')) +i2c_ss.add(when: 'CONFIG_BITBANG_I2C', if_true: files('bitbang_i2c.c')) +i2c_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_i2c.c')) +i2c_ss.add(when: 'CONFIG_IMX_I2C', if_true: files('imx_i2c.c')) +i2c_ss.add(when: 'CONFIG_MPC_I2C', if_true: files('mpc_i2c.c')) +i2c_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('microbit_i2c.c')) +i2c_ss.add(when: 'CONFIG_SMBUS_EEPROM', if_true: files('smbus_eeprom.c')) +i2c_ss.add(when: 'CONFIG_VERSATILE_I2C', if_true: files('versatile_i2c.c')) +i2c_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_i2c.c')) +i2c_ss.add(when: 'CONFIG_PPC4XX', if_true: files('ppc4xx_i2c.c')) +softmmu_ss.add_all(when: 'CONFIG_I2C', if_true: i2c_ss) diff --git a/hw/i2c/microbit_i2c.c b/hw/i2c/microbit_i2c.c index 80247398208272ebd097808a2657a7c49a1c64dd..e92f9f84ea81596bd64695452818430ddaf77c87 100644 --- a/hw/i2c/microbit_i2c.c +++ b/hw/i2c/microbit_i2c.c @@ -83,6 +83,7 @@ static const VMStateDescription microbit_i2c_vmstate = { .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(regs, MicrobitI2CState, MICROBIT_I2C_NREGS), VMSTATE_UINT32(read_idx, MicrobitI2CState), + VMSTATE_END_OF_LIST() }, }; diff --git a/hw/i2c/mpc_i2c.c b/hw/i2c/mpc_i2c.c index 9a724f3a3e8fa6e08df083377f08dd9519aa3759..720d2331e9529021e67b11d0af19f34ce8160524 100644 --- a/hw/i2c/mpc_i2c.c +++ b/hw/i2c/mpc_i2c.c @@ -24,6 +24,7 @@ #include "qemu/module.h" #include "hw/sysbus.h" #include "migration/vmstate.h" +#include "qom/object.h" /* #define DEBUG_I2C */ @@ -36,8 +37,7 @@ #endif #define TYPE_MPC_I2C "mpc-i2c" -#define MPC_I2C(obj) \ - OBJECT_CHECK(MPCI2CState, (obj), TYPE_MPC_I2C) +OBJECT_DECLARE_SIMPLE_TYPE(MPCI2CState, MPC_I2C) #define MPC_I2C_ADR 0x00 #define MPC_I2C_FDR 0x04 @@ -70,7 +70,7 @@ #define CYCLE_RESET 0xFF -typedef struct MPCI2CState { +struct MPCI2CState { SysBusDevice parent_obj; I2CBus *bus; @@ -84,7 +84,7 @@ typedef struct MPCI2CState { uint8_t sr; uint8_t dr; uint8_t dfssr; -} MPCI2CState; +}; static bool mpc_i2c_is_enabled(MPCI2CState *s) { diff --git a/hw/i2c/pm_smbus.c b/hw/i2c/pm_smbus.c index 4728540c37e600180d9f3433e89aa6dce8d822d0..06e1e5321b995195dab03bb7f6936128dae7ed38 100644 --- a/hw/i2c/pm_smbus.c +++ b/hw/i2c/pm_smbus.c @@ -6,7 +6,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c index e199fc8678a777b9a537d96ff9631b5f27693b31..4d2bf99207a791b47a1eb8f811a42c5da8c2b143 100644 --- a/hw/i2c/smbus_eeprom.c +++ b/hw/i2c/smbus_eeprom.c @@ -31,23 +31,23 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "hw/i2c/smbus_eeprom.h" +#include "qom/object.h" //#define DEBUG #define TYPE_SMBUS_EEPROM "smbus-eeprom" -#define SMBUS_EEPROM(obj) \ - OBJECT_CHECK(SMBusEEPROMDevice, (obj), TYPE_SMBUS_EEPROM) +OBJECT_DECLARE_SIMPLE_TYPE(SMBusEEPROMDevice, SMBUS_EEPROM) #define SMBUS_EEPROM_SIZE 256 -typedef struct SMBusEEPROMDevice { +struct SMBusEEPROMDevice { SMBusDevice smbusdev; uint8_t data[SMBUS_EEPROM_SIZE]; uint8_t *init_data; uint8_t offset; bool accessed; -} SMBusEEPROMDevice; +}; static uint8_t eeprom_receive_byte(SMBusDevice *dev) { @@ -169,11 +169,11 @@ void smbus_eeprom_init_one(I2CBus *smbus, uint8_t address, uint8_t *eeprom_buf) { DeviceState *dev; - dev = qdev_create((BusState *) smbus, TYPE_SMBUS_EEPROM); + dev = qdev_new(TYPE_SMBUS_EEPROM); qdev_prop_set_uint8(dev, "address", address); /* FIXME: use an array of byte or block backend property? */ SMBUS_EEPROM(dev)->init_data = eeprom_buf; - qdev_init_nofail(dev); + qdev_realize_and_unref(dev, (BusState *)smbus, &error_fatal); } void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom, diff --git a/hw/i2c/smbus_ich9.c b/hw/i2c/smbus_ich9.c index 48f1ff419174c9b5c736fed5de7d09fb5a4d29a7..44dd5653b7f1ffe3ef7b5314a6c590330cd14115 100644 --- a/hw/i2c/smbus_ich9.c +++ b/hw/i2c/smbus_ich9.c @@ -28,17 +28,17 @@ #include "qemu/module.h" #include "hw/i386/ich9.h" +#include "qom/object.h" -#define ICH9_SMB_DEVICE(obj) \ - OBJECT_CHECK(ICH9SMBState, (obj), TYPE_ICH9_SMB_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(ICH9SMBState, ICH9_SMB_DEVICE) -typedef struct ICH9SMBState { +struct ICH9SMBState { PCIDevice dev; bool irq_enabled; PMSMBus smb; -} ICH9SMBState; +}; static bool ich9_vmstate_need_smbus(void *opaque, int version_id) { diff --git a/hw/i2c/trace.h b/hw/i2c/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..4843a8d5444ebc013d417e4c846c788d11a4f1b5 --- /dev/null +++ b/hw/i2c/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_i2c.h" diff --git a/hw/i2c/versatile_i2c.c b/hw/i2c/versatile_i2c.c index 1ac2a6f59a0aa82fff4cc2e0e92af17b9cee257f..3a04ba3969170940a31145dedb21dc813e6c9fbd 100644 --- a/hw/i2c/versatile_i2c.c +++ b/hw/i2c/versatile_i2c.c @@ -1,5 +1,6 @@ /* - * ARM Versatile I2C controller + * ARM SBCon two-wire serial bus interface (I2C bitbang) + * a.k.a. ARM Versatile I2C controller * * Copyright (c) 2006-2007 CodeSourcery. * Copyright (c) 2012 Oskar Andero @@ -22,32 +23,34 @@ */ #include "qemu/osdep.h" -#include "hw/sysbus.h" -#include "hw/i2c/bitbang_i2c.h" +#include "hw/i2c/arm_sbcon_i2c.h" +#include "hw/registerfields.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" -#define TYPE_VERSATILE_I2C "versatile_i2c" -#define VERSATILE_I2C(obj) \ - OBJECT_CHECK(VersatileI2CState, (obj), TYPE_VERSATILE_I2C) +typedef ArmSbconI2CState VersatileI2CState; +DECLARE_INSTANCE_CHECKER(VersatileI2CState, VERSATILE_I2C, + TYPE_VERSATILE_I2C) -typedef struct VersatileI2CState { - SysBusDevice parent_obj; - MemoryRegion iomem; - bitbang_i2c_interface bitbang; - int out; - int in; -} VersatileI2CState; + +REG32(CONTROL_GET, 0) +REG32(CONTROL_SET, 0) +REG32(CONTROL_CLR, 4) + +#define SCL BIT(0) +#define SDA BIT(1) static uint64_t versatile_i2c_read(void *opaque, hwaddr offset, unsigned size) { VersatileI2CState *s = (VersatileI2CState *)opaque; - if (offset == 0) { + switch (offset) { + case A_CONTROL_SET: return (s->out & 1) | (s->in << 1); - } else { + default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%x\n", __func__, (int)offset); return -1; @@ -60,18 +63,18 @@ static void versatile_i2c_write(void *opaque, hwaddr offset, VersatileI2CState *s = (VersatileI2CState *)opaque; switch (offset) { - case 0: + case A_CONTROL_SET: s->out |= value & 3; break; - case 4: + case A_CONTROL_CLR: s->out &= ~value; break; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%x\n", __func__, (int)offset); } - bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SCL, (s->out & 1) != 0); - s->in = bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SDA, (s->out & 2) != 0); + bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SCL, (s->out & SCL) != 0); + s->in = bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SDA, (s->out & SDA) != 0); } static const MemoryRegionOps versatile_i2c_ops = { @@ -90,7 +93,7 @@ static void versatile_i2c_init(Object *obj) bus = i2c_init_bus(dev, "i2c"); bitbang_i2c_init(&s->bitbang, bus); memory_region_init_io(&s->iomem, obj, &versatile_i2c_ops, s, - "versatile_i2c", 0x1000); + "arm_sbcon_i2c", 0x1000); sysbus_init_mmio(sbd, &s->iomem); } diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig index c93f32f6579dbbf3d94eb9b03aa783d3d066d011..eea059ffef54f1accfea7f944b4aaba69282506e 100644 --- a/hw/i386/Kconfig +++ b/hw/i386/Kconfig @@ -35,6 +35,7 @@ config PC select ACPI_PCI select ACPI_VMGENID select VIRTIO_PMEM_SUPPORTED + select VIRTIO_MEM_SUPPORTED config PC_PCI bool @@ -102,6 +103,9 @@ config MICROVM select I8259 select MC146818RTC select VIRTIO_MMIO + select ACPI_HW_REDUCED + select PCI_EXPRESS_GENERIC_BRIDGE + select USB_XHCI_SYSBUS config X86_IOMMU bool diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs deleted file mode 100644 index 8ce1b265335b28c98069911a8bd9bafb53a79ece..0000000000000000000000000000000000000000 --- a/hw/i386/Makefile.objs +++ /dev/null @@ -1,19 +0,0 @@ -obj-$(CONFIG_KVM) += kvm/ -obj-y += e820_memory_layout.o multiboot.o -obj-y += x86.o -obj-$(CONFIG_PC) += pc.o pc_sysfw.o -obj-$(CONFIG_I440FX) += pc_piix.o -obj-$(CONFIG_Q35) += pc_q35.o -obj-$(CONFIG_MICROVM) += microvm.o -obj-y += fw_cfg.o -obj-$(CONFIG_X86_IOMMU) += x86-iommu.o -obj-$(call lnot,$(CONFIG_X86_IOMMU)) += x86-iommu-stub.o -obj-$(CONFIG_VTD) += intel_iommu.o -obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o -obj-$(CONFIG_XEN) += ../xenpv/ xen/ -obj-$(CONFIG_VMPORT) += vmport.o -obj-$(CONFIG_VMMOUSE) += vmmouse.o -obj-$(CONFIG_PC) += port92.o - -obj-y += kvmvapic.o -obj-$(CONFIG_PC) += acpi-build.o diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 2e15f6848e7e2f3a3583659caa0f01771d1eab4f..1f5c2112452a74bc19cb3a129fa92ba70e984a70 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -24,6 +24,7 @@ #include "qapi/error.h" #include "qapi/qmp/qnum.h" #include "acpi-build.h" +#include "acpi-common.h" #include "qemu/bitmap.h" #include "qemu/error-report.h" #include "hw/pci/pci.h" @@ -50,6 +51,7 @@ #include "hw/mem/nvdimm.h" #include "sysemu/numa.h" #include "sysemu/reset.h" +#include "hw/hyperv/vmbus-bridge.h" /* Supported chipsets: */ #include "hw/southbridge/piix.h" @@ -89,13 +91,12 @@ #define ACPI_BUILD_DPRINTF(fmt, ...) #endif -/* Default IOAPIC ID */ -#define ACPI_BUILD_IOAPIC_ID 0x0 - typedef struct AcpiPmInfo { bool s3_disabled; bool s4_disabled; bool pcihp_bridge_en; + bool smi_on_cpuhp; + bool pcihp_root_en; uint8_t s4_val; AcpiFadtData fadt; uint16_t cpu_hp_io_base; @@ -195,6 +196,7 @@ static void acpi_get_pm_info(MachineState *machine, AcpiPmInfo *pm) pm->cpu_hp_io_base = 0; pm->pcihp_io_base = 0; pm->pcihp_io_len = 0; + pm->smi_on_cpuhp = false; assert(obj); init_common_fadt_data(machine, obj, &pm->fadt); @@ -208,12 +210,16 @@ static void acpi_get_pm_info(MachineState *machine, AcpiPmInfo *pm) object_property_get_uint(obj, ACPI_PCIHP_IO_LEN_PROP, NULL); } if (lpc) { + uint64_t smi_features = object_property_get_uint(lpc, + ICH9_LPC_SMI_NEGOTIATED_FEAT_PROP, NULL); struct AcpiGenericAddress r = { .space_id = AML_AS_SYSTEM_IO, .bit_width = 8, .address = ICH9_RST_CNT_IOPORT }; pm->fadt.reset_reg = r; pm->fadt.reset_val = 0xf; pm->fadt.flags |= 1 << ACPI_FADT_F_RESET_REG_SUP; pm->cpu_hp_io_base = ICH9_CPU_HOTPLUG_IO_BASE; + pm->smi_on_cpuhp = + !!(smi_features & BIT_ULL(ICH9_LPC_SMI_F_CPU_HOTPLUG_BIT)); } /* The above need not be conditional on machine type because the reset port @@ -246,6 +252,9 @@ static void acpi_get_pm_info(MachineState *machine, AcpiPmInfo *pm) pm->pcihp_bridge_en = object_property_get_bool(obj, "acpi-pci-hotplug-with-bridge-support", NULL); + pm->pcihp_root_en = + object_property_get_bool(obj, "acpi-root-pci-hotplug", + NULL); } static void acpi_get_misc_info(AcpiMiscInfo *info) @@ -327,125 +336,6 @@ build_facs(GArray *table_data) facs->length = cpu_to_le32(sizeof(*facs)); } -void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid, - const CPUArchIdList *apic_ids, GArray *entry) -{ - uint32_t apic_id = apic_ids->cpus[uid].arch_id; - - /* ACPI spec says that LAPIC entry for non present - * CPU may be omitted from MADT or it must be marked - * as disabled. However omitting non present CPU from - * MADT breaks hotplug on linux. So possible CPUs - * should be put in MADT but kept disabled. - */ - if (apic_id < 255) { - AcpiMadtProcessorApic *apic = acpi_data_push(entry, sizeof *apic); - - apic->type = ACPI_APIC_PROCESSOR; - apic->length = sizeof(*apic); - apic->processor_id = uid; - apic->local_apic_id = apic_id; - if (apic_ids->cpus[uid].cpu != NULL) { - apic->flags = cpu_to_le32(1); - } else { - apic->flags = cpu_to_le32(0); - } - } else { - AcpiMadtProcessorX2Apic *apic = acpi_data_push(entry, sizeof *apic); - - apic->type = ACPI_APIC_LOCAL_X2APIC; - apic->length = sizeof(*apic); - apic->uid = cpu_to_le32(uid); - apic->x2apic_id = cpu_to_le32(apic_id); - if (apic_ids->cpus[uid].cpu != NULL) { - apic->flags = cpu_to_le32(1); - } else { - apic->flags = cpu_to_le32(0); - } - } -} - -static void -build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms) -{ - MachineClass *mc = MACHINE_GET_CLASS(pcms); - X86MachineState *x86ms = X86_MACHINE(pcms); - const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(pcms)); - int madt_start = table_data->len; - AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(pcms->acpi_dev); - AcpiDeviceIf *adev = ACPI_DEVICE_IF(pcms->acpi_dev); - bool x2apic_mode = false; - - AcpiMultipleApicTable *madt; - AcpiMadtIoApic *io_apic; - AcpiMadtIntsrcovr *intsrcovr; - int i; - - madt = acpi_data_push(table_data, sizeof *madt); - madt->local_apic_address = cpu_to_le32(APIC_DEFAULT_ADDRESS); - madt->flags = cpu_to_le32(1); - - for (i = 0; i < apic_ids->len; i++) { - adevc->madt_cpu(adev, i, apic_ids, table_data); - if (apic_ids->cpus[i].arch_id > 254) { - x2apic_mode = true; - } - } - - io_apic = acpi_data_push(table_data, sizeof *io_apic); - io_apic->type = ACPI_APIC_IO; - io_apic->length = sizeof(*io_apic); - io_apic->io_apic_id = ACPI_BUILD_IOAPIC_ID; - io_apic->address = cpu_to_le32(IO_APIC_DEFAULT_ADDRESS); - io_apic->interrupt = cpu_to_le32(0); - - if (x86ms->apic_xrupt_override) { - intsrcovr = acpi_data_push(table_data, sizeof *intsrcovr); - intsrcovr->type = ACPI_APIC_XRUPT_OVERRIDE; - intsrcovr->length = sizeof(*intsrcovr); - intsrcovr->source = 0; - intsrcovr->gsi = cpu_to_le32(2); - intsrcovr->flags = cpu_to_le16(0); /* conforms to bus specifications */ - } - for (i = 1; i < 16; i++) { -#define ACPI_BUILD_PCI_IRQS ((1<<5) | (1<<9) | (1<<10) | (1<<11)) - if (!(ACPI_BUILD_PCI_IRQS & (1 << i))) { - /* No need for a INT source override structure. */ - continue; - } - intsrcovr = acpi_data_push(table_data, sizeof *intsrcovr); - intsrcovr->type = ACPI_APIC_XRUPT_OVERRIDE; - intsrcovr->length = sizeof(*intsrcovr); - intsrcovr->source = i; - intsrcovr->gsi = cpu_to_le32(i); - intsrcovr->flags = cpu_to_le16(0xd); /* active high, level triggered */ - } - - if (x2apic_mode) { - AcpiMadtLocalX2ApicNmi *local_nmi; - - local_nmi = acpi_data_push(table_data, sizeof *local_nmi); - local_nmi->type = ACPI_APIC_LOCAL_X2APIC_NMI; - local_nmi->length = sizeof(*local_nmi); - local_nmi->uid = 0xFFFFFFFF; /* all processors */ - local_nmi->flags = cpu_to_le16(0); - local_nmi->lint = 1; /* ACPI_LINT1 */ - } else { - AcpiMadtLocalNmi *local_nmi; - - local_nmi = acpi_data_push(table_data, sizeof *local_nmi); - local_nmi->type = ACPI_APIC_LOCAL_NMI; - local_nmi->length = sizeof(*local_nmi); - local_nmi->processor_id = 0xff; /* all processors */ - local_nmi->flags = cpu_to_le16(0); - local_nmi->lint = 1; /* ACPI_LINT1 */ - } - - build_header(linker, table_data, - (void *)(table_data->data + madt_start), "APIC", - table_data->len - madt_start, 1, NULL, NULL); -} - static void build_append_pcihp_notify_entry(Aml *method, int slot) { Aml *if_ctx; @@ -479,6 +369,7 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, int slot = PCI_SLOT(i); bool hotplug_enabled_dev; bool bridge_in_acpi; + bool cold_plugged_bridge; if (!pdev) { if (bsel) { /* add hotplug slots for non present devices */ @@ -500,15 +391,14 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, pc = PCI_DEVICE_GET_CLASS(pdev); dc = DEVICE_GET_CLASS(pdev); - /* When hotplug for bridges is enabled, bridges are - * described in ACPI separately (see build_pci_bus_end). - * In this case they aren't themselves hot-pluggable. + /* + * Cold plugged bridges aren't themselves hot-pluggable. * Hotplugged bridges *are* hot-pluggable. */ - bridge_in_acpi = pc->is_bridge && pcihp_bridge_en && - !DEVICE(pdev)->hotplugged; + cold_plugged_bridge = pc->is_bridge && !DEVICE(pdev)->hotplugged; + bridge_in_acpi = cold_plugged_bridge && pcihp_bridge_en; - hotplug_enabled_dev = bsel && dc->hotpluggable && !bridge_in_acpi; + hotplug_enabled_dev = bsel && dc->hotpluggable && !cold_plugged_bridge; if (pc->class_id == PCI_CLASS_BRIDGE_ISA) { continue; @@ -570,36 +460,38 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, } /* Append PCNT method to notify about events on local and child buses. - * Add unconditionally for root since DSDT expects it. + * Add this method for root bus only when hotplug is enabled since DSDT + * expects it. */ - method = aml_method("PCNT", 0, AML_NOTSERIALIZED); - - /* If bus supports hotplug select it and notify about local events */ - if (bsel) { - uint64_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel)); + if (bsel || pcihp_bridge_en) { + method = aml_method("PCNT", 0, AML_NOTSERIALIZED); + + /* If bus supports hotplug select it and notify about local events */ + if (bsel) { + uint64_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel)); + + aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM"))); + aml_append(method, aml_call2("DVNT", aml_name("PCIU"), + aml_int(1))); /* Device Check */ + aml_append(method, aml_call2("DVNT", aml_name("PCID"), + aml_int(3))); /* Eject Request */ + } - aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM"))); - aml_append(method, - aml_call2("DVNT", aml_name("PCIU"), aml_int(1) /* Device Check */) - ); - aml_append(method, - aml_call2("DVNT", aml_name("PCID"), aml_int(3)/* Eject Request */) - ); - } + /* Notify about child bus events in any case */ + if (pcihp_bridge_en) { + QLIST_FOREACH(sec, &bus->child, sibling) { + int32_t devfn = sec->parent_dev->devfn; - /* Notify about child bus events in any case */ - if (pcihp_bridge_en) { - QLIST_FOREACH(sec, &bus->child, sibling) { - int32_t devfn = sec->parent_dev->devfn; + if (pci_bus_is_root(sec) || pci_bus_is_express(sec)) { + continue; + } - if (pci_bus_is_root(sec) || pci_bus_is_express(sec)) { - continue; + aml_append(method, aml_name("^S%.02X.PCNT", devfn)); } - - aml_append(method, aml_name("^S%.02X.PCNT", devfn)); } + + aml_append(parent_scope, method); } - aml_append(parent_scope, method); qobject_unref(bsel); } @@ -891,8 +783,14 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) crs_range_insert(temp_range_set.io_ranges, range_base, range_limit); } else { /* "memory" */ - crs_range_insert(temp_range_set.mem_ranges, - range_base, range_limit); + uint64_t length = range_limit - range_base + 1; + if (range_limit <= UINT32_MAX && length <= UINT32_MAX) { + crs_range_insert(temp_range_set.mem_ranges, range_base, + range_limit); + } else { + crs_range_insert(temp_range_set.mem_64bit_ranges, + range_base, range_limit); + } } } @@ -971,6 +869,8 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) crs_range_merge(temp_range_set.mem_ranges); for (i = 0; i < temp_range_set.mem_ranges->len; i++) { entry = g_ptr_array_index(temp_range_set.mem_ranges, i); + assert(entry->limit <= UINT32_MAX && + (entry->limit - entry->base + 1) <= UINT32_MAX); aml_append(crs, aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, AML_NON_CACHEABLE, @@ -1058,213 +958,36 @@ static void build_hpet_aml(Aml *table) aml_append(table, scope); } -static Aml *build_fdinfo_aml(int idx, FloppyDriveType type) -{ - Aml *dev, *fdi; - uint8_t maxc, maxh, maxs; - - isa_fdc_get_drive_max_chs(type, &maxc, &maxh, &maxs); - - dev = aml_device("FLP%c", 'A' + idx); - - aml_append(dev, aml_name_decl("_ADR", aml_int(idx))); - - fdi = aml_package(16); - aml_append(fdi, aml_int(idx)); /* Drive Number */ - aml_append(fdi, - aml_int(cmos_get_fd_drive_type(type))); /* Device Type */ - /* - * the values below are the limits of the drive, and are thus independent - * of the inserted media - */ - aml_append(fdi, aml_int(maxc)); /* Maximum Cylinder Number */ - aml_append(fdi, aml_int(maxs)); /* Maximum Sector Number */ - aml_append(fdi, aml_int(maxh)); /* Maximum Head Number */ - /* - * SeaBIOS returns the below values for int 0x13 func 0x08 regardless of - * the drive type, so shall we - */ - aml_append(fdi, aml_int(0xAF)); /* disk_specify_1 */ - aml_append(fdi, aml_int(0x02)); /* disk_specify_2 */ - aml_append(fdi, aml_int(0x25)); /* disk_motor_wait */ - aml_append(fdi, aml_int(0x02)); /* disk_sector_siz */ - aml_append(fdi, aml_int(0x12)); /* disk_eot */ - aml_append(fdi, aml_int(0x1B)); /* disk_rw_gap */ - aml_append(fdi, aml_int(0xFF)); /* disk_dtl */ - aml_append(fdi, aml_int(0x6C)); /* disk_formt_gap */ - aml_append(fdi, aml_int(0xF6)); /* disk_fill */ - aml_append(fdi, aml_int(0x0F)); /* disk_head_sttl */ - aml_append(fdi, aml_int(0x08)); /* disk_motor_strt */ - - aml_append(dev, aml_name_decl("_FDI", fdi)); - return dev; -} - -static Aml *build_fdc_device_aml(ISADevice *fdc) -{ - int i; - Aml *dev; - Aml *crs; - -#define ACPI_FDE_MAX_FD 4 - uint32_t fde_buf[5] = { - 0, 0, 0, 0, /* presence of floppy drives #0 - #3 */ - cpu_to_le32(2) /* tape presence (2 == never present) */ - }; - - dev = aml_device("FDC0"); - aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0700"))); - - crs = aml_resource_template(); - aml_append(crs, aml_io(AML_DECODE16, 0x03F2, 0x03F2, 0x00, 0x04)); - aml_append(crs, aml_io(AML_DECODE16, 0x03F7, 0x03F7, 0x00, 0x01)); - aml_append(crs, aml_irq_no_flags(6)); - aml_append(crs, - aml_dma(AML_COMPATIBILITY, AML_NOTBUSMASTER, AML_TRANSFER8, 2)); - aml_append(dev, aml_name_decl("_CRS", crs)); - - for (i = 0; i < MIN(MAX_FD, ACPI_FDE_MAX_FD); i++) { - FloppyDriveType type = isa_fdc_get_drive_type(fdc, i); - - if (type < FLOPPY_DRIVE_TYPE_NONE) { - fde_buf[i] = cpu_to_le32(1); /* drive present */ - aml_append(dev, build_fdinfo_aml(i, type)); - } - } - aml_append(dev, aml_name_decl("_FDE", - aml_buffer(sizeof(fde_buf), (uint8_t *)fde_buf))); - - return dev; -} - -static Aml *build_rtc_device_aml(void) +static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) { Aml *dev; - Aml *crs; - - dev = aml_device("RTC"); - aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0B00"))); - crs = aml_resource_template(); - aml_append(crs, aml_io(AML_DECODE16, 0x0070, 0x0070, 0x10, 0x02)); - aml_append(crs, aml_irq_no_flags(8)); - aml_append(crs, aml_io(AML_DECODE16, 0x0072, 0x0072, 0x02, 0x06)); - aml_append(dev, aml_name_decl("_CRS", crs)); - - return dev; -} - -static Aml *build_kbd_device_aml(void) -{ - Aml *dev; - Aml *crs; - - dev = aml_device("KBD"); - aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0303"))); - - aml_append(dev, aml_name_decl("_STA", aml_int(0xf))); - - crs = aml_resource_template(); - aml_append(crs, aml_io(AML_DECODE16, 0x0060, 0x0060, 0x01, 0x01)); - aml_append(crs, aml_io(AML_DECODE16, 0x0064, 0x0064, 0x01, 0x01)); - aml_append(crs, aml_irq_no_flags(1)); - aml_append(dev, aml_name_decl("_CRS", crs)); - - return dev; -} - -static Aml *build_mouse_device_aml(void) -{ - Aml *dev; - Aml *crs; - - dev = aml_device("MOU"); - aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0F13"))); - - aml_append(dev, aml_name_decl("_STA", aml_int(0xf))); - - crs = aml_resource_template(); - aml_append(crs, aml_irq_no_flags(12)); - aml_append(dev, aml_name_decl("_CRS", crs)); - - return dev; -} - -static Aml *build_lpt_device_aml(void) -{ - Aml *dev; - Aml *crs; Aml *method; - Aml *if_ctx; - Aml *else_ctx; - Aml *zero = aml_int(0); - Aml *is_present = aml_local(0); + Aml *crs; - dev = aml_device("LPT"); - aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0400"))); + dev = aml_device("VMBS"); + aml_append(dev, aml_name_decl("STA", aml_int(0xF))); + aml_append(dev, aml_name_decl("_HID", aml_string("VMBus"))); + aml_append(dev, aml_name_decl("_UID", aml_int(0x0))); + aml_append(dev, aml_name_decl("_DDN", aml_string("VMBUS"))); - method = aml_method("_STA", 0, AML_NOTSERIALIZED); - aml_append(method, aml_store(aml_name("LPEN"), is_present)); - if_ctx = aml_if(aml_equal(is_present, zero)); - { - aml_append(if_ctx, aml_return(aml_int(0x00))); - } - aml_append(method, if_ctx); - else_ctx = aml_else(); - { - aml_append(else_ctx, aml_return(aml_int(0x0f))); - } - aml_append(method, else_ctx); + method = aml_method("_DIS", 0, AML_NOTSERIALIZED); + aml_append(method, aml_store(aml_and(aml_name("STA"), aml_int(0xD), NULL), + aml_name("STA"))); aml_append(dev, method); - crs = aml_resource_template(); - aml_append(crs, aml_io(AML_DECODE16, 0x0378, 0x0378, 0x08, 0x08)); - aml_append(crs, aml_irq_no_flags(7)); - aml_append(dev, aml_name_decl("_CRS", crs)); - - return dev; -} - -static Aml *build_com_device_aml(uint8_t uid) -{ - Aml *dev; - Aml *crs; - Aml *method; - Aml *if_ctx; - Aml *else_ctx; - Aml *zero = aml_int(0); - Aml *is_present = aml_local(0); - const char *enabled_field = "CAEN"; - uint8_t irq = 4; - uint16_t io_port = 0x03F8; - - assert(uid == 1 || uid == 2); - if (uid == 2) { - enabled_field = "CBEN"; - irq = 3; - io_port = 0x02F8; - } - - dev = aml_device("COM%d", uid); - aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0501"))); - aml_append(dev, aml_name_decl("_UID", aml_int(uid))); + method = aml_method("_PS0", 0, AML_NOTSERIALIZED); + aml_append(method, aml_store(aml_or(aml_name("STA"), aml_int(0xF), NULL), + aml_name("STA"))); + aml_append(dev, method); method = aml_method("_STA", 0, AML_NOTSERIALIZED); - aml_append(method, aml_store(aml_name("%s", enabled_field), is_present)); - if_ctx = aml_if(aml_equal(is_present, zero)); - { - aml_append(if_ctx, aml_return(aml_int(0x00))); - } - aml_append(method, if_ctx); - else_ctx = aml_else(); - { - aml_append(else_ctx, aml_return(aml_int(0x0f))); - } - aml_append(method, else_ctx); + aml_append(method, aml_return(aml_name("STA"))); aml_append(dev, method); + aml_append(dev, aml_name_decl("_PS3", aml_int(0x0))); + crs = aml_resource_template(); - aml_append(crs, aml_io(AML_DECODE16, io_port, io_port, 0x00, 0x08)); - aml_append(crs, aml_irq_no_flags(irq)); + aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq)); aml_append(dev, aml_name_decl("_CRS", crs)); return dev; @@ -1272,30 +995,15 @@ static Aml *build_com_device_aml(uint8_t uid) static void build_isa_devices_aml(Aml *table) { - ISADevice *fdc = pc_find_fdc0(); bool ambiguous; - - Aml *scope = aml_scope("_SB.PCI0.ISA"); Object *obj = object_resolve_path_type("", TYPE_ISA_BUS, &ambiguous); + Aml *scope; - aml_append(scope, build_rtc_device_aml()); - aml_append(scope, build_kbd_device_aml()); - aml_append(scope, build_mouse_device_aml()); - if (fdc) { - aml_append(scope, build_fdc_device_aml(fdc)); - } - aml_append(scope, build_lpt_device_aml()); - aml_append(scope, build_com_device_aml(1)); - aml_append(scope, build_com_device_aml(2)); + assert(obj && !ambiguous); - if (ambiguous) { - error_report("Multiple ISA busses, unable to define IPMI ACPI data"); - } else if (!obj) { - error_report("No ISA bus, unable to define IPMI ACPI data"); - } else { - build_acpi_ipmi_devices(scope, BUS(obj), "\\_SB.PCI0.ISA"); - isa_build_aml(ISA_BUS(obj), scope); - } + scope = aml_scope("_SB.PCI0.ISA"); + build_acpi_ipmi_devices(scope, BUS(obj), "\\_SB.PCI0.ISA"); + isa_build_aml(ISA_BUS(obj), scope); aml_append(table, scope); } @@ -1645,7 +1353,6 @@ static void build_q35_isa_bridge(Aml *table) { Aml *dev; Aml *scope; - Aml *field; scope = aml_scope("_SB.PCI0"); dev = aml_device("ISA"); @@ -1655,40 +1362,6 @@ static void build_q35_isa_bridge(Aml *table) aml_append(dev, aml_operation_region("PIRQ", AML_PCI_CONFIG, aml_int(0x60), 0x0C)); - aml_append(dev, aml_operation_region("LPCD", AML_PCI_CONFIG, - aml_int(0x80), 0x02)); - field = aml_field("LPCD", AML_ANY_ACC, AML_NOLOCK, AML_PRESERVE); - aml_append(field, aml_named_field("COMA", 3)); - aml_append(field, aml_reserved_field(1)); - aml_append(field, aml_named_field("COMB", 3)); - aml_append(field, aml_reserved_field(1)); - aml_append(field, aml_named_field("LPTD", 2)); - aml_append(dev, field); - - aml_append(dev, aml_operation_region("LPCE", AML_PCI_CONFIG, - aml_int(0x82), 0x02)); - /* enable bits */ - field = aml_field("LPCE", AML_ANY_ACC, AML_NOLOCK, AML_PRESERVE); - aml_append(field, aml_named_field("CAEN", 1)); - aml_append(field, aml_named_field("CBEN", 1)); - aml_append(field, aml_named_field("LPEN", 1)); - aml_append(dev, field); - - aml_append(scope, dev); - aml_append(table, scope); -} - -static void build_piix4_pm(Aml *table) -{ - Aml *dev; - Aml *scope; - - scope = aml_scope("_SB.PCI0"); - dev = aml_device("PX13"); - aml_append(dev, aml_name_decl("_ADR", aml_int(0x00010003))); - - aml_append(dev, aml_operation_region("P13C", AML_PCI_CONFIG, - aml_int(0x00), 0xff)); aml_append(scope, dev); aml_append(table, scope); } @@ -1697,7 +1370,6 @@ static void build_piix4_isa_bridge(Aml *table) { Aml *dev; Aml *scope; - Aml *field; scope = aml_scope("_SB.PCI0"); dev = aml_device("ISA"); @@ -1706,19 +1378,6 @@ static void build_piix4_isa_bridge(Aml *table) /* PIIX PCI to ISA irq remapping */ aml_append(dev, aml_operation_region("P40C", AML_PCI_CONFIG, aml_int(0x60), 0x04)); - /* enable bits */ - field = aml_field("^PX13.P13C", AML_ANY_ACC, AML_NOLOCK, AML_PRESERVE); - /* Offset(0x5f),, 7, */ - aml_append(field, aml_reserved_field(0x2f8)); - aml_append(field, aml_reserved_field(7)); - aml_append(field, aml_named_field("LPEN", 1)); - /* Offset(0x67),, 3, */ - aml_append(field, aml_reserved_field(0x38)); - aml_append(field, aml_reserved_field(3)); - aml_append(field, aml_named_field("CAEN", 1)); - aml_append(field, aml_reserved_field(3)); - aml_append(field, aml_named_field("CBEN", 1)); - aml_append(dev, field); aml_append(scope, dev); aml_append(table, scope); @@ -1841,6 +1500,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, PCIBus *bus = NULL; TPMIf *tpm = tpm_find(); int i; + VMBusBridge *vmbus_bridge = vmbus_bridge_find(); dsdt = init_aml_allocator(); @@ -1853,15 +1513,16 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, dev = aml_device("PCI0"); aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03"))); aml_append(dev, aml_name_decl("_ADR", aml_int(0))); - aml_append(dev, aml_name_decl("_UID", aml_int(1))); + aml_append(dev, aml_name_decl("_UID", aml_int(0))); aml_append(sb_scope, dev); aml_append(dsdt, sb_scope); build_hpet_aml(dsdt); - build_piix4_pm(dsdt); build_piix4_isa_bridge(dsdt); build_isa_devices_aml(dsdt); - build_piix4_pci_hotplug(dsdt); + if (pm->pcihp_bridge_en || pm->pcihp_root_en) { + build_piix4_pci_hotplug(dsdt); + } build_piix4_pci0_int(dsdt); } else { sb_scope = aml_scope("_SB"); @@ -1869,9 +1530,35 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08"))); aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03"))); aml_append(dev, aml_name_decl("_ADR", aml_int(0))); - aml_append(dev, aml_name_decl("_UID", aml_int(1))); + aml_append(dev, aml_name_decl("_UID", aml_int(0))); aml_append(dev, build_q35_osc_method()); aml_append(sb_scope, dev); + + if (pm->smi_on_cpuhp) { + /* reserve SMI block resources, IO ports 0xB2, 0xB3 */ + dev = aml_device("PCI0.SMI0"); + aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A06"))); + aml_append(dev, aml_name_decl("_UID", aml_string("SMI resources"))); + crs = aml_resource_template(); + aml_append(crs, + aml_io( + AML_DECODE16, + ACPI_PORT_SMI_CMD, + ACPI_PORT_SMI_CMD, + 1, + 2) + ); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(dev, aml_operation_region("SMIR", AML_SYSTEM_IO, + aml_int(ACPI_PORT_SMI_CMD), 2)); + field = aml_field("SMIR", AML_BYTE_ACC, AML_NOLOCK, + AML_WRITE_AS_ZEROS); + aml_append(field, aml_named_field("SMIC", 8)); + aml_append(field, aml_reserved_field(8)); + aml_append(dev, field); + aml_append(sb_scope, dev); + } + aml_append(dsdt, sb_scope); build_hpet_aml(dsdt); @@ -1883,11 +1570,18 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, } } + if (vmbus_bridge) { + sb_scope = aml_scope("_SB"); + aml_append(sb_scope, build_vmbus_device_aml(vmbus_bridge)); + aml_append(dsdt, sb_scope); + } + if (pcmc->legacy_cpu_hotplug) { build_legacy_cpu_hotplug_aml(dsdt, machine, pm->cpu_hp_io_base); } else { CPUHotplugFeatures opts = { - .acpi_1_compatible = true, .has_legacy_cphp = true + .acpi_1_compatible = true, .has_legacy_cphp = true, + .smi_path = pm->smi_on_cpuhp ? "\\_SB.PCI0.SMI0.SMIC" : NULL, }; build_cpus_aml(dsdt, machine, opts, pm->cpu_hp_io_base, "\\_SB.PCI0", "\\_GPE._E02"); @@ -1903,7 +1597,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, { aml_append(scope, aml_name_decl("_HID", aml_string("ACPI0006"))); - if (misc->is_piix4) { + if (misc->is_piix4 && (pm->pcihp_bridge_en || pm->pcihp_root_en)) { method = aml_method("_E01", 0, AML_NOTSERIALIZED); aml_append(method, aml_acquire(aml_name("\\_SB.PCI0.BLCK"), 0xFFFF)); @@ -2055,7 +1749,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, crs_range_set_free(&crs_range_set); /* reserve PCIHP resources */ - if (pm->pcihp_io_len) { + if (pm->pcihp_io_len && (pm->pcihp_bridge_en || pm->pcihp_root_en)) { dev = aml_device("PHPR"); aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A06"))); aml_append(dev, @@ -2103,30 +1797,8 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, /* create fw_cfg node, unconditionally */ { - /* when using port i/o, the 8-bit data register *always* overlaps - * with half of the 16-bit control register. Hence, the total size - * of the i/o region used is FW_CFG_CTL_SIZE; when using DMA, the - * DMA control register is located at FW_CFG_DMA_IO_BASE + 4 */ - uint8_t io_size = object_property_get_bool(OBJECT(x86ms->fw_cfg), - "dma_enabled", NULL) ? - ROUND_UP(FW_CFG_CTL_SIZE, 4) + sizeof(dma_addr_t) : - FW_CFG_CTL_SIZE; - scope = aml_scope("\\_SB.PCI0"); - dev = aml_device("FWCF"); - - aml_append(dev, aml_name_decl("_HID", aml_string("QEMU0002"))); - - /* device present, functioning, decoding, not shown in UI */ - aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); - - crs = aml_resource_template(); - aml_append(crs, - aml_io(AML_DECODE16, FW_CFG_IO_BASE, FW_CFG_IO_BASE, 0x01, io_size) - ); - aml_append(dev, aml_name_decl("_CRS", crs)); - - aml_append(scope, dev); + fw_cfg_add_acpi_dsdt(scope, x86ms->fw_cfg); aml_append(dsdt, scope); } @@ -2295,36 +1967,6 @@ build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog) (void *)tcpa, "TCPA", sizeof(*tcpa), 2, NULL, NULL); } -static void -build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog) -{ - Acpi20TPM2 *tpm2_ptr = acpi_data_push(table_data, sizeof *tpm2_ptr); - unsigned log_addr_size = sizeof(tpm2_ptr->log_area_start_address); - unsigned log_addr_offset = - (char *)&tpm2_ptr->log_area_start_address - table_data->data; - - tpm2_ptr->platform_class = cpu_to_le16(TPM2_ACPI_CLASS_CLIENT); - if (TPM_IS_TIS_ISA(tpm_find())) { - tpm2_ptr->control_area_address = cpu_to_le64(0); - tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO); - } else if (TPM_IS_CRB(tpm_find())) { - tpm2_ptr->control_area_address = cpu_to_le64(TPM_CRB_ADDR_CTRL); - tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_CRB); - } else { - g_warn_if_reached(); - } - - tpm2_ptr->log_area_minimum_length = - cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE); - - /* log area start address to be filled by Guest linker */ - bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, - log_addr_offset, log_addr_size, - ACPI_BUILD_TPMLOG_FILE, 0); - build_header(linker, table_data, - (void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4, NULL, NULL); -} - #define HOLE_640K_START (640 * KiB) #define HOLE_640K_END (1 * MiB) @@ -2428,6 +2070,11 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) MEM_AFFINITY_ENABLED); } } + + if (machine->nvdimms_state->is_enabled) { + nvdimm_build_srat(table_data); + } + slots = (table_data->len - numa_start) / sizeof *numamem; for (; slots < pcms->numa_nodes + 2; slots++) { numamem = acpi_data_push(table_data, sizeof *numamem); @@ -2834,7 +2481,8 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) aml_len += tables_blob->len - fadt; acpi_add_table(table_offsets, tables_blob); - build_madt(tables_blob, tables->linker, pcms); + acpi_build_madt(tables_blob, tables->linker, x86ms, + ACPI_DEVICE_IF(x86ms->acpi_dev)); vmgenid_dev = find_vmgenid_dev(); if (vmgenid_dev) { @@ -2848,10 +2496,10 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) build_hpet(tables_blob, tables->linker); } if (misc.tpm_version != TPM_VERSION_UNSPEC) { - acpi_add_table(table_offsets, tables_blob); - build_tpm_tcpa(tables_blob, tables->linker, tables->tcpalog); - - if (misc.tpm_version == TPM_VERSION_2_0) { + if (misc.tpm_version == TPM_VERSION_1_2) { + acpi_add_table(table_offsets, tables_blob); + build_tpm_tcpa(tables_blob, tables->linker, tables->tcpalog); + } else { /* TPM_VERSION_2_0 */ acpi_add_table(table_offsets, tables_blob); build_tpm2(tables_blob, tables->linker, tables->tcpalog); } diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c new file mode 100644 index 0000000000000000000000000000000000000000..8a769654060ebbf66437ba7b6675bf66ce2a71ad --- /dev/null +++ b/hw/i386/acpi-common.c @@ -0,0 +1,152 @@ +/* Support for generating ACPI tables and passing them to Guests + * + * Copyright (C) 2008-2010 Kevin O'Connor + * Copyright (C) 2006 Fabrice Bellard + * Copyright (C) 2013 Red Hat Inc + * + * Author: Michael S. Tsirkin + * + * 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 . + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" + +#include "exec/memory.h" +#include "hw/acpi/acpi.h" +#include "hw/acpi/aml-build.h" +#include "hw/acpi/utils.h" +#include "hw/i386/pc.h" +#include "target/i386/cpu.h" + +#include "acpi-build.h" +#include "acpi-common.h" + +void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid, + const CPUArchIdList *apic_ids, GArray *entry) +{ + uint32_t apic_id = apic_ids->cpus[uid].arch_id; + + /* ACPI spec says that LAPIC entry for non present + * CPU may be omitted from MADT or it must be marked + * as disabled. However omitting non present CPU from + * MADT breaks hotplug on linux. So possible CPUs + * should be put in MADT but kept disabled. + */ + if (apic_id < 255) { + AcpiMadtProcessorApic *apic = acpi_data_push(entry, sizeof *apic); + + apic->type = ACPI_APIC_PROCESSOR; + apic->length = sizeof(*apic); + apic->processor_id = uid; + apic->local_apic_id = apic_id; + if (apic_ids->cpus[uid].cpu != NULL) { + apic->flags = cpu_to_le32(1); + } else { + apic->flags = cpu_to_le32(0); + } + } else { + AcpiMadtProcessorX2Apic *apic = acpi_data_push(entry, sizeof *apic); + + apic->type = ACPI_APIC_LOCAL_X2APIC; + apic->length = sizeof(*apic); + apic->uid = cpu_to_le32(uid); + apic->x2apic_id = cpu_to_le32(apic_id); + if (apic_ids->cpus[uid].cpu != NULL) { + apic->flags = cpu_to_le32(1); + } else { + apic->flags = cpu_to_le32(0); + } + } +} + +void acpi_build_madt(GArray *table_data, BIOSLinker *linker, + X86MachineState *x86ms, AcpiDeviceIf *adev) +{ + MachineClass *mc = MACHINE_GET_CLASS(x86ms); + const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms)); + int madt_start = table_data->len; + AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(adev); + bool x2apic_mode = false; + + AcpiMultipleApicTable *madt; + AcpiMadtIoApic *io_apic; + AcpiMadtIntsrcovr *intsrcovr; + int i; + + madt = acpi_data_push(table_data, sizeof *madt); + madt->local_apic_address = cpu_to_le32(APIC_DEFAULT_ADDRESS); + madt->flags = cpu_to_le32(1); + + for (i = 0; i < apic_ids->len; i++) { + adevc->madt_cpu(adev, i, apic_ids, table_data); + if (apic_ids->cpus[i].arch_id > 254) { + x2apic_mode = true; + } + } + + io_apic = acpi_data_push(table_data, sizeof *io_apic); + io_apic->type = ACPI_APIC_IO; + io_apic->length = sizeof(*io_apic); + io_apic->io_apic_id = ACPI_BUILD_IOAPIC_ID; + io_apic->address = cpu_to_le32(IO_APIC_DEFAULT_ADDRESS); + io_apic->interrupt = cpu_to_le32(0); + + if (x86ms->apic_xrupt_override) { + intsrcovr = acpi_data_push(table_data, sizeof *intsrcovr); + intsrcovr->type = ACPI_APIC_XRUPT_OVERRIDE; + intsrcovr->length = sizeof(*intsrcovr); + intsrcovr->source = 0; + intsrcovr->gsi = cpu_to_le32(2); + intsrcovr->flags = cpu_to_le16(0); /* conforms to bus specifications */ + } + + for (i = 1; i < 16; i++) { + if (!(x86ms->pci_irq_mask & (1 << i))) { + /* No need for a INT source override structure. */ + continue; + } + intsrcovr = acpi_data_push(table_data, sizeof *intsrcovr); + intsrcovr->type = ACPI_APIC_XRUPT_OVERRIDE; + intsrcovr->length = sizeof(*intsrcovr); + intsrcovr->source = i; + intsrcovr->gsi = cpu_to_le32(i); + intsrcovr->flags = cpu_to_le16(0xd); /* active high, level triggered */ + } + + if (x2apic_mode) { + AcpiMadtLocalX2ApicNmi *local_nmi; + + local_nmi = acpi_data_push(table_data, sizeof *local_nmi); + local_nmi->type = ACPI_APIC_LOCAL_X2APIC_NMI; + local_nmi->length = sizeof(*local_nmi); + local_nmi->uid = 0xFFFFFFFF; /* all processors */ + local_nmi->flags = cpu_to_le16(0); + local_nmi->lint = 1; /* ACPI_LINT1 */ + } else { + AcpiMadtLocalNmi *local_nmi; + + local_nmi = acpi_data_push(table_data, sizeof *local_nmi); + local_nmi->type = ACPI_APIC_LOCAL_NMI; + local_nmi->length = sizeof(*local_nmi); + local_nmi->processor_id = 0xff; /* all processors */ + local_nmi->flags = cpu_to_le16(0); + local_nmi->lint = 1; /* ACPI_LINT1 */ + } + + build_header(linker, table_data, + (void *)(table_data->data + madt_start), "APIC", + table_data->len - madt_start, 1, NULL, NULL); +} + diff --git a/hw/i386/acpi-common.h b/hw/i386/acpi-common.h new file mode 100644 index 0000000000000000000000000000000000000000..c30e461f18545667a623af133109461498cc49e1 --- /dev/null +++ b/hw/i386/acpi-common.h @@ -0,0 +1,14 @@ +#ifndef HW_I386_ACPI_COMMON_H +#define HW_I386_ACPI_COMMON_H +#include "include/hw/acpi/acpi_dev_interface.h" + +#include "include/hw/acpi/bios-linker-loader.h" +#include "include/hw/i386/x86.h" + +/* Default IOAPIC ID */ +#define ACPI_BUILD_IOAPIC_ID 0x0 + +void acpi_build_madt(GArray *table_data, BIOSLinker *linker, + X86MachineState *x86ms, AcpiDeviceIf *adev); + +#endif diff --git a/hw/i386/acpi-microvm.c b/hw/i386/acpi-microvm.c new file mode 100644 index 0000000000000000000000000000000000000000..d34a301b8410ba2ec08c84ba6d2b499c23d26b8a --- /dev/null +++ b/hw/i386/acpi-microvm.c @@ -0,0 +1,261 @@ +/* Support for generating ACPI tables and passing them to Guests + * + * Copyright (C) 2008-2010 Kevin O'Connor + * Copyright (C) 2006 Fabrice Bellard + * Copyright (C) 2013 Red Hat Inc + * + * Author: Michael S. Tsirkin + * + * 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/cutils.h" +#include "qapi/error.h" + +#include "exec/memory.h" +#include "hw/acpi/acpi.h" +#include "hw/acpi/aml-build.h" +#include "hw/acpi/bios-linker-loader.h" +#include "hw/acpi/generic_event_device.h" +#include "hw/acpi/utils.h" +#include "hw/boards.h" +#include "hw/i386/fw_cfg.h" +#include "hw/i386/microvm.h" +#include "hw/pci/pci.h" +#include "hw/pci/pcie_host.h" +#include "hw/usb/xhci.h" +#include "hw/virtio/virtio-mmio.h" + +#include "acpi-common.h" +#include "acpi-microvm.h" + +static void acpi_dsdt_add_virtio(Aml *scope, + MicrovmMachineState *mms) +{ + gchar *separator; + long int index; + BusState *bus; + BusChild *kid; + + bus = sysbus_get_default(); + QTAILQ_FOREACH(kid, &bus->children, sibling) { + DeviceState *dev = kid->child; + Object *obj = object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MMIO); + + if (obj) { + VirtIOMMIOProxy *mmio = VIRTIO_MMIO(obj); + VirtioBusState *mmio_virtio_bus = &mmio->bus; + BusState *mmio_bus = &mmio_virtio_bus->parent_obj; + + if (QTAILQ_EMPTY(&mmio_bus->children)) { + continue; + } + separator = g_strrstr(mmio_bus->name, "."); + if (!separator) { + continue; + } + if (qemu_strtol(separator + 1, NULL, 10, &index) != 0) { + continue; + } + + uint32_t irq = mms->virtio_irq_base + index; + hwaddr base = VIRTIO_MMIO_BASE + index * 512; + hwaddr size = 512; + + Aml *dev = aml_device("VR%02u", (unsigned)index); + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0005"))); + aml_append(dev, aml_name_decl("_UID", aml_int(index))); + aml_append(dev, aml_name_decl("_CCA", aml_int(1))); + + Aml *crs = aml_resource_template(); + aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE)); + aml_append(crs, + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, &irq, 1)); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); + } + } +} + +static void acpi_dsdt_add_xhci(Aml *scope, MicrovmMachineState *mms) +{ + if (machine_usb(MACHINE(mms))) { + xhci_sysbus_build_aml(scope, MICROVM_XHCI_BASE, MICROVM_XHCI_IRQ); + } +} + +static void acpi_dsdt_add_pci(Aml *scope, MicrovmMachineState *mms) +{ + if (mms->pcie != ON_OFF_AUTO_ON) { + return; + } + + acpi_dsdt_add_gpex(scope, &mms->gpex); +} + +static void +build_dsdt_microvm(GArray *table_data, BIOSLinker *linker, + MicrovmMachineState *mms) +{ + X86MachineState *x86ms = X86_MACHINE(mms); + Aml *dsdt, *sb_scope, *scope, *pkg; + bool ambiguous; + Object *isabus; + + isabus = object_resolve_path_type("", TYPE_ISA_BUS, &ambiguous); + assert(isabus); + assert(!ambiguous); + + dsdt = init_aml_allocator(); + + /* Reserve space for header */ + acpi_data_push(dsdt->buf, sizeof(AcpiTableHeader)); + + sb_scope = aml_scope("_SB"); + fw_cfg_add_acpi_dsdt(sb_scope, x86ms->fw_cfg); + isa_build_aml(ISA_BUS(isabus), sb_scope); + build_ged_aml(sb_scope, GED_DEVICE, x86ms->acpi_dev, + GED_MMIO_IRQ, AML_SYSTEM_MEMORY, GED_MMIO_BASE); + acpi_dsdt_add_power_button(sb_scope); + acpi_dsdt_add_virtio(sb_scope, mms); + acpi_dsdt_add_xhci(sb_scope, mms); + acpi_dsdt_add_pci(sb_scope, mms); + aml_append(dsdt, sb_scope); + + /* ACPI 5.0: Table 7-209 System State Package */ + scope = aml_scope("\\"); + pkg = aml_package(4); + aml_append(pkg, aml_int(ACPI_GED_SLP_TYP_S5)); + aml_append(pkg, aml_int(0)); /* ignored */ + aml_append(pkg, aml_int(0)); /* reserved */ + aml_append(pkg, aml_int(0)); /* reserved */ + aml_append(scope, aml_name_decl("_S5", pkg)); + aml_append(dsdt, scope); + + /* copy AML table into ACPI tables blob and patch header there */ + g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len); + build_header(linker, table_data, + (void *)(table_data->data + table_data->len - dsdt->buf->len), + "DSDT", dsdt->buf->len, 2, NULL, NULL); + free_aml_allocator(); +} + +static void acpi_build_microvm(AcpiBuildTables *tables, + MicrovmMachineState *mms) +{ + MachineState *machine = MACHINE(mms); + X86MachineState *x86ms = X86_MACHINE(mms); + GArray *table_offsets; + GArray *tables_blob = tables->table_data; + unsigned dsdt, xsdt; + AcpiFadtData pmfadt = { + /* ACPI 5.0: 4.1 Hardware-Reduced ACPI */ + .rev = 5, + .flags = ((1 << ACPI_FADT_F_HW_REDUCED_ACPI) | + (1 << ACPI_FADT_F_RESET_REG_SUP)), + + /* ACPI 5.0: 4.8.3.7 Sleep Control and Status Registers */ + .sleep_ctl = { + .space_id = AML_AS_SYSTEM_MEMORY, + .bit_width = 8, + .address = GED_MMIO_BASE_REGS + ACPI_GED_REG_SLEEP_CTL, + }, + .sleep_sts = { + .space_id = AML_AS_SYSTEM_MEMORY, + .bit_width = 8, + .address = GED_MMIO_BASE_REGS + ACPI_GED_REG_SLEEP_STS, + }, + + /* ACPI 5.0: 4.8.3.6 Reset Register */ + .reset_reg = { + .space_id = AML_AS_SYSTEM_MEMORY, + .bit_width = 8, + .address = GED_MMIO_BASE_REGS + ACPI_GED_REG_RESET, + }, + .reset_val = ACPI_GED_RESET_VALUE, + }; + + table_offsets = g_array_new(false, true /* clear */, + sizeof(uint32_t)); + bios_linker_loader_alloc(tables->linker, + ACPI_BUILD_TABLE_FILE, tables_blob, + 64 /* Ensure FACS is aligned */, + false /* high memory */); + + dsdt = tables_blob->len; + build_dsdt_microvm(tables_blob, tables->linker, mms); + + pmfadt.dsdt_tbl_offset = &dsdt; + pmfadt.xdsdt_tbl_offset = &dsdt; + acpi_add_table(table_offsets, tables_blob); + build_fadt(tables_blob, tables->linker, &pmfadt, NULL, NULL); + + acpi_add_table(table_offsets, tables_blob); + acpi_build_madt(tables_blob, tables->linker, X86_MACHINE(machine), + ACPI_DEVICE_IF(x86ms->acpi_dev)); + + xsdt = tables_blob->len; + build_xsdt(tables_blob, tables->linker, table_offsets, NULL, NULL); + + /* RSDP is in FSEG memory, so allocate it separately */ + { + AcpiRsdpData rsdp_data = { + /* ACPI 2.0: 5.2.4.3 RSDP Structure */ + .revision = 2, /* xsdt needs v2 */ + .oem_id = ACPI_BUILD_APPNAME6, + .xsdt_tbl_offset = &xsdt, + .rsdt_tbl_offset = NULL, + }; + build_rsdp(tables->rsdp, tables->linker, &rsdp_data); + } + + /* Cleanup memory that's no longer used. */ + g_array_free(table_offsets, true); +} + +static void acpi_build_no_update(void *build_opaque) +{ + /* nothing, microvm tables don't change at runtime */ +} + +void acpi_setup_microvm(MicrovmMachineState *mms) +{ + X86MachineState *x86ms = X86_MACHINE(mms); + AcpiBuildTables tables; + + assert(x86ms->fw_cfg); + + if (!x86_machine_is_acpi_enabled(x86ms)) { + return; + } + + acpi_build_tables_init(&tables); + acpi_build_microvm(&tables, mms); + + /* Now expose it all to Guest */ + acpi_add_rom_blob(acpi_build_no_update, NULL, + tables.table_data, + ACPI_BUILD_TABLE_FILE, + ACPI_BUILD_TABLE_MAX_SIZE); + acpi_add_rom_blob(acpi_build_no_update, NULL, + tables.linker->cmd_blob, + "etc/table-loader", 0); + acpi_add_rom_blob(acpi_build_no_update, NULL, + tables.rsdp, + ACPI_BUILD_RSDP_FILE, 0); + + acpi_build_tables_cleanup(&tables, false); +} diff --git a/hw/i386/acpi-microvm.h b/hw/i386/acpi-microvm.h new file mode 100644 index 0000000000000000000000000000000000000000..dfe853690e1576a15268c45df6cc434a4dbc8456 --- /dev/null +++ b/hw/i386/acpi-microvm.h @@ -0,0 +1,8 @@ +#ifndef HW_I386_ACPI_MICROVM_H +#define HW_I386_ACPI_MICROVM_H + +#include "hw/i386/microvm.h" + +void acpi_setup_microvm(MicrovmMachineState *mms); + +#endif diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c index fd75cae02437ad2a776c755a03446648e0fb580c..74a93a5d93f4b5e3ac565e9ed10e79f1d6fe34f1 100644 --- a/hw/i386/amd_iommu.c +++ b/hw/i386/amd_iommu.c @@ -370,7 +370,7 @@ static void amdvi_completion_wait(AMDVIState *s, uint64_t *cmd) hwaddr addr = cpu_to_le64(extract64(cmd[0], 3, 49)) << 3; uint64_t data = cpu_to_le64(cmd[1]); - if (extract64(cmd[0], 51, 8)) { + if (extract64(cmd[0], 52, 8)) { amdvi_log_illegalcom_error(s, extract64(cmd[0], 60, 4), s->cmdbuf + s->cmdbuf_head); } @@ -395,7 +395,7 @@ static void amdvi_inval_devtab_entry(AMDVIState *s, uint64_t *cmd) uint16_t devid = cpu_to_le16((uint16_t)extract64(cmd[0], 0, 16)); /* This command should invalidate internal caches of which there isn't */ - if (extract64(cmd[0], 15, 16) || cmd[1]) { + if (extract64(cmd[0], 16, 44) || cmd[1]) { amdvi_log_illegalcom_error(s, extract64(cmd[0], 60, 4), s->cmdbuf + s->cmdbuf_head); } @@ -405,9 +405,9 @@ static void amdvi_inval_devtab_entry(AMDVIState *s, uint64_t *cmd) static void amdvi_complete_ppr(AMDVIState *s, uint64_t *cmd) { - if (extract64(cmd[0], 15, 16) || extract64(cmd[0], 19, 8) || + if (extract64(cmd[0], 16, 16) || extract64(cmd[0], 52, 8) || extract64(cmd[1], 0, 2) || extract64(cmd[1], 3, 29) - || extract64(cmd[1], 47, 16)) { + || extract64(cmd[1], 48, 16)) { amdvi_log_illegalcom_error(s, extract64(cmd[0], 60, 4), s->cmdbuf + s->cmdbuf_head); } @@ -438,8 +438,8 @@ static void amdvi_inval_pages(AMDVIState *s, uint64_t *cmd) { uint16_t domid = cpu_to_le16((uint16_t)extract64(cmd[0], 32, 16)); - if (extract64(cmd[0], 20, 12) || extract64(cmd[0], 16, 12) || - extract64(cmd[0], 3, 10)) { + if (extract64(cmd[0], 20, 12) || extract64(cmd[0], 48, 12) || + extract64(cmd[1], 3, 9)) { amdvi_log_illegalcom_error(s, extract64(cmd[0], 60, 4), s->cmdbuf + s->cmdbuf_head); } @@ -451,7 +451,7 @@ static void amdvi_inval_pages(AMDVIState *s, uint64_t *cmd) static void amdvi_prefetch_pages(AMDVIState *s, uint64_t *cmd) { - if (extract64(cmd[0], 16, 8) || extract64(cmd[0], 20, 8) || + if (extract64(cmd[0], 16, 8) || extract64(cmd[0], 52, 8) || extract64(cmd[1], 1, 1) || extract64(cmd[1], 3, 1) || extract64(cmd[1], 5, 7)) { amdvi_log_illegalcom_error(s, extract64(cmd[0], 60, 4), @@ -463,7 +463,7 @@ static void amdvi_prefetch_pages(AMDVIState *s, uint64_t *cmd) static void amdvi_inval_inttable(AMDVIState *s, uint64_t *cmd) { - if (extract64(cmd[0], 16, 16) || cmd[1]) { + if (extract64(cmd[0], 16, 44) || cmd[1]) { amdvi_log_illegalcom_error(s, extract64(cmd[0], 60, 4), s->cmdbuf + s->cmdbuf_head); return; @@ -479,7 +479,8 @@ static void iommu_inval_iotlb(AMDVIState *s, uint64_t *cmd) { uint16_t devid = extract64(cmd[0], 0, 16); - if (extract64(cmd[1], 1, 1) || extract64(cmd[1], 3, 9)) { + if (extract64(cmd[1], 1, 1) || extract64(cmd[1], 3, 1) || + extract64(cmd[1], 6, 6)) { amdvi_log_illegalcom_error(s, extract64(cmd[0], 60, 4), s->cmdbuf + s->cmdbuf_head); return; @@ -1548,8 +1549,9 @@ static void amdvi_realize(DeviceState *dev, Error **errp) /* This device should take care of IOMMU PCI properties */ x86_iommu->type = TYPE_AMD; - qdev_set_parent_bus(DEVICE(&s->pci), &bus->qbus); - object_property_set_bool(OBJECT(&s->pci), true, "realized", errp); + if (!qdev_realize(DEVICE(&s->pci), &bus->qbus, errp)) { + return; + } ret = pci_add_capability(&s->pci.dev, AMDVI_CAPAB_ID_SEC, 0, AMDVI_CAPAB_SIZE, errp); if (ret < 0) { @@ -1578,7 +1580,7 @@ static void amdvi_realize(DeviceState *dev, Error **errp) sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio); sysbus_mmio_map(SYS_BUS_DEVICE(s), 0, AMDVI_BASE_ADDR); pci_setup_iommu(bus, amdvi_host_dma_iommu, s); - s->devid = object_property_get_int(OBJECT(&s->pci), "addr", errp); + s->devid = object_property_get_int(OBJECT(&s->pci), "addr", &error_abort); msi_init(&s->pci.dev, 0, 1, true, false, errp); amdvi_init(s); } @@ -1598,7 +1600,7 @@ static void amdvi_instance_init(Object *klass) static void amdvi_class_init(ObjectClass *klass, void* data) { DeviceClass *dc = DEVICE_CLASS(klass); - X86IOMMUClass *dc_class = X86_IOMMU_CLASS(klass); + X86IOMMUClass *dc_class = X86_IOMMU_DEVICE_CLASS(klass); dc->reset = amdvi_reset; dc->vmsd = &vmstate_amdvi; @@ -1620,7 +1622,7 @@ static const TypeInfo amdvi = { }; static const TypeInfo amdviPCI = { - .name = "AMDVI-PCI", + .name = TYPE_AMD_IOMMU_PCI, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(AMDVIPCIState), .interfaces = (InterfaceInfo[]) { diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h index e05a4eff5d9b73028d6333f1d04515bb205337f6..79d38a3e41843bc48180e3a4cc8779289c5d5e6e 100644 --- a/hw/i386/amd_iommu.h +++ b/hw/i386/amd_iommu.h @@ -23,6 +23,7 @@ #include "hw/pci/pci.h" #include "hw/i386/x86-iommu.h" +#include "qom/object.h" /* Capability registers */ #define AMDVI_CAPAB_BAR_LOW 0x04 @@ -296,8 +297,7 @@ struct irte_ga { }; #define TYPE_AMD_IOMMU_DEVICE "amd-iommu" -#define AMD_IOMMU_DEVICE(obj)\ - OBJECT_CHECK(AMDVIState, (obj), TYPE_AMD_IOMMU_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(AMDVIState, AMD_IOMMU_DEVICE) #define TYPE_AMD_IOMMU_PCI "AMDVI-PCI" @@ -310,7 +310,7 @@ typedef struct AMDVIPCIState { PCIDevice dev; /* The PCI device itself */ } AMDVIPCIState; -typedef struct AMDVIState { +struct AMDVIState { X86IOMMUState iommu; /* IOMMU bus device */ AMDVIPCIState pci; /* IOMMU PCI device */ @@ -367,6 +367,6 @@ typedef struct AMDVIState { /* Interrupt remapping */ bool ga_enabled; -} AMDVIState; +}; #endif diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c index da60ada5946281007307d4e554f708fbc81388e5..e06579490c409c2c5d370b20b5d7e3b4c3c38760 100644 --- a/hw/i386/fw_cfg.c +++ b/hw/i386/fw_cfg.c @@ -15,13 +15,14 @@ #include "qemu/osdep.h" #include "sysemu/numa.h" #include "hw/acpi/acpi.h" +#include "hw/acpi/aml-build.h" #include "hw/firmware/smbios.h" #include "hw/i386/fw_cfg.h" #include "hw/timer/hpet.h" #include "hw/nvram/fw_cfg.h" #include "e820_memory_layout.h" #include "kvm_i386.h" -#include "config-devices.h" +#include CONFIG_DEVICES struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX}; @@ -122,7 +123,7 @@ FWCfgState *fw_cfg_arch_create(MachineState *ms, fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES, acpi_tables, acpi_tables_len); #endif - fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override()); + fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, 1); fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE, &e820_reserve, sizeof(e820_reserve)); @@ -179,3 +180,30 @@ void fw_cfg_build_feature_control(MachineState *ms, FWCfgState *fw_cfg) *val = cpu_to_le64(feature_control_bits | FEATURE_CONTROL_LOCKED); fw_cfg_add_file(fw_cfg, "etc/msr_feature_control", val, sizeof(*val)); } + +void fw_cfg_add_acpi_dsdt(Aml *scope, FWCfgState *fw_cfg) +{ + /* + * when using port i/o, the 8-bit data register *always* overlaps + * with half of the 16-bit control register. Hence, the total size + * of the i/o region used is FW_CFG_CTL_SIZE; when using DMA, the + * DMA control register is located at FW_CFG_DMA_IO_BASE + 4 + */ + Object *obj = OBJECT(fw_cfg); + uint8_t io_size = object_property_get_bool(obj, "dma_enabled", NULL) ? + ROUND_UP(FW_CFG_CTL_SIZE, 4) + sizeof(dma_addr_t) : + FW_CFG_CTL_SIZE; + Aml *dev = aml_device("FWCF"); + Aml *crs = aml_resource_template(); + + aml_append(dev, aml_name_decl("_HID", aml_string("QEMU0002"))); + + /* device present, functioning, decoding, not shown in UI */ + aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); + + aml_append(crs, + aml_io(AML_DECODE16, FW_CFG_IO_BASE, FW_CFG_IO_BASE, 0x01, io_size)); + + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); +} diff --git a/hw/i386/fw_cfg.h b/hw/i386/fw_cfg.h index 9e742787792bff1f4636310844066d967fe733b6..275f15c1c5e853f0bedfb27d06d4eacf70dc6b99 100644 --- a/hw/i386/fw_cfg.h +++ b/hw/i386/fw_cfg.h @@ -25,5 +25,6 @@ FWCfgState *fw_cfg_arch_create(MachineState *ms, uint16_t apic_id_limit); void fw_cfg_build_smbios(MachineState *ms, FWCfgState *fw_cfg); void fw_cfg_build_feature_control(MachineState *ms, FWCfgState *fw_cfg); +void fw_cfg_add_acpi_dsdt(Aml *scope, FWCfgState *fw_cfg); #endif diff --git a/hw/i386/generic_event_device_x86.c b/hw/i386/generic_event_device_x86.c new file mode 100644 index 0000000000000000000000000000000000000000..e26fb02a2ef654050226bf5175a90ca480d42962 --- /dev/null +++ b/hw/i386/generic_event_device_x86.c @@ -0,0 +1,36 @@ +/* + * x86 variant of the generic event device for hw reduced acpi + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + */ + +#include "qemu/osdep.h" +#include "hw/acpi/generic_event_device.h" +#include "hw/i386/pc.h" + +static void acpi_ged_x86_class_init(ObjectClass *class, void *data) +{ + AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(class); + + adevc->madt_cpu = pc_madt_cpu_entry; +} + +static const TypeInfo acpi_ged_x86_info = { + .name = TYPE_ACPI_GED_X86, + .parent = TYPE_ACPI_GED, + .class_init = acpi_ged_x86_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { TYPE_ACPI_DEVICE_IF }, + { } + } +}; + +static void acpi_ged_x86_register_types(void) +{ + type_register_static(&acpi_ged_x86_info); +} + +type_init(acpi_ged_x86_register_types) diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index df7ad254ac15f09ae5138a6304aea4b6e0a8553b..70ac83773394b97e1bb572f88a0286888da56e84 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -2356,7 +2356,7 @@ static bool vtd_process_iotlb_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc) if ((inv_desc->lo & VTD_INV_DESC_IOTLB_RSVD_LO) || (inv_desc->hi & VTD_INV_DESC_IOTLB_RSVD_HI)) { error_report_once("%s: invalid iotlb inv desc: hi=0x%"PRIx64 - ", lo=0x%"PRIx64" (reserved bits unzero)\n", + ", lo=0x%"PRIx64" (reserved bits unzero)", __func__, inv_desc->hi, inv_desc->lo); return false; } @@ -2377,7 +2377,7 @@ static bool vtd_process_iotlb_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc) am = VTD_INV_DESC_IOTLB_AM(inv_desc->hi); if (am > VTD_MAMV) { error_report_once("%s: invalid iotlb inv desc: hi=0x%"PRIx64 - ", lo=0x%"PRIx64" (am=%u > VTD_MAMV=%u)\n", + ", lo=0x%"PRIx64" (am=%u > VTD_MAMV=%u)", __func__, inv_desc->hi, inv_desc->lo, am, (unsigned)VTD_MAMV); return false; @@ -2387,7 +2387,7 @@ static bool vtd_process_iotlb_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc) default: error_report_once("%s: invalid iotlb inv desc: hi=0x%"PRIx64 - ", lo=0x%"PRIx64" (type mismatch: 0x%llx)\n", + ", lo=0x%"PRIx64" (type mismatch: 0x%llx)", __func__, inv_desc->hi, inv_desc->lo, inv_desc->lo & VTD_INV_DESC_IOTLB_G); return false; @@ -2549,6 +2549,11 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s) /* Try to fetch and process more Invalidation Descriptors */ static void vtd_fetch_inv_desc(IntelIOMMUState *s) { + int qi_shift; + + /* Refer to 10.4.23 of VT-d spec 3.0 */ + qi_shift = s->iq_dw ? VTD_IQH_QH_SHIFT_5 : VTD_IQH_QH_SHIFT_4; + trace_vtd_inv_qi_fetch(); if (s->iq_tail >= s->iq_size) { @@ -2567,7 +2572,7 @@ static void vtd_fetch_inv_desc(IntelIOMMUState *s) } /* Must update the IQH_REG in time */ vtd_set_quad_raw(s, DMAR_IQH_REG, - (((uint64_t)(s->iq_head)) << VTD_IQH_QH_SHIFT) & + (((uint64_t)(s->iq_head)) << qi_shift) & VTD_IQH_QH_MASK); } } @@ -2660,7 +2665,7 @@ static uint64_t vtd_mem_read(void *opaque, hwaddr addr, unsigned size) if (addr + size > DMAR_REG_SIZE) { error_report_once("%s: MMIO over range: addr=0x%" PRIx64 - " size=0x%u", __func__, addr, size); + " size=0x%x", __func__, addr, size); return (uint64_t)-1; } @@ -2711,7 +2716,7 @@ static void vtd_mem_write(void *opaque, hwaddr addr, if (addr + size > DMAR_REG_SIZE) { error_report_once("%s: MMIO over range: addr=0x%" PRIx64 - " size=0x%u", __func__, addr, size); + " size=0x%x", __func__, addr, size); return; } @@ -3163,7 +3168,6 @@ static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index, index, entry->irte.sid_vtype); /* Take this as verification failure. */ return -VTD_FR_IR_SID_ERR; - break; } } @@ -3758,7 +3762,7 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp) /* Currently only address widths supported are 39 and 48 bits */ if ((s->aw_bits != VTD_HOST_AW_39BIT) && (s->aw_bits != VTD_HOST_AW_48BIT)) { - error_setg(errp, "Supported values for x-aw-bits are: %d, %d", + error_setg(errp, "Supported values for aw-bits are: %d, %d", VTD_HOST_AW_39BIT, VTD_HOST_AW_48BIT); return false; } @@ -3849,7 +3853,7 @@ static void vtd_realize(DeviceState *dev, Error **errp) static void vtd_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - X86IOMMUClass *x86_class = X86_IOMMU_CLASS(klass); + X86IOMMUClass *x86_class = X86_IOMMU_DEVICE_CLASS(klass); dc->reset = vtd_reset; dc->vmsd = &vtd_vmstate; diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h index 862033ebe6c9c08d3c510916b21be8e92ac0236e..3d5487fe2cef908efca28217356a6fc9e87b23ef 100644 --- a/hw/i386/intel_iommu_internal.h +++ b/hw/i386/intel_iommu_internal.h @@ -230,7 +230,8 @@ #define VTD_IQA_DW_MASK 0x800 /* IQH_REG */ -#define VTD_IQH_QH_SHIFT 4 +#define VTD_IQH_QH_SHIFT_4 4 +#define VTD_IQH_QH_SHIFT_5 5 #define VTD_IQH_QH_MASK 0x7fff0ULL /* ICS_REG */ diff --git a/hw/i386/kvm/Makefile.objs b/hw/i386/kvm/Makefile.objs deleted file mode 100644 index 0c8d5f2dee0419d91c1e4112db392e11d9cf94b6..0000000000000000000000000000000000000000 --- a/hw/i386/kvm/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -obj-y += clock.o -obj-$(CONFIG_APIC) += apic.o -obj-$(CONFIG_IOAPIC) += ioapic.o -obj-$(CONFIG_I8254) += i8254.o -obj-$(CONFIG_I8259) += i8259.o diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c index 4eb2d77b87b8b2b7452192ffe6836b8dbbf2aa5c..dd29906061ce1a8149d7d14b8854bd87f241c265 100644 --- a/hw/i386/kvm/apic.c +++ b/hw/i386/kvm/apic.c @@ -225,9 +225,8 @@ static void kvm_apic_realize(DeviceState *dev, Error **errp) memory_region_init_io(&s->io_memory, OBJECT(s), &kvm_apic_io_ops, s, "kvm-apic-msi", APIC_SPACE_SIZE); - if (kvm_has_gsi_routing()) { - msi_nonbroken = true; - } + assert(kvm_has_gsi_routing()); + msi_nonbroken = true; } static void kvm_apic_unrealize(DeviceState *dev) diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c index 64283358f91d08f0bffc48386c299209428e8cca..24fe5091b6b47c9a9de83553c6a603f22e9fe978 100644 --- a/hw/i386/kvm/clock.c +++ b/hw/i386/kvm/clock.c @@ -29,11 +29,12 @@ #include #include "standard-headers/asm-x86/kvm_para.h" +#include "qom/object.h" #define TYPE_KVM_CLOCK "kvmclock" -#define KVM_CLOCK(obj) OBJECT_CHECK(KVMClockState, (obj), TYPE_KVM_CLOCK) +OBJECT_DECLARE_SIMPLE_TYPE(KVMClockState, KVM_CLOCK) -typedef struct KVMClockState { +struct KVMClockState { /*< private >*/ SysBusDevice busdev; /*< public >*/ @@ -50,7 +51,7 @@ typedef struct KVMClockState { /* whether the 'clock' value was obtained in a host with * reliable KVM_GET_CLOCK */ bool clock_is_reliable; -} KVMClockState; +}; struct pvclock_vcpu_time_info { uint32_t version; @@ -328,11 +329,14 @@ static const TypeInfo kvmclock_info = { }; /* Note: Must be called after VCPU initialization. */ -void kvmclock_create(void) +void kvmclock_create(bool create_always) { X86CPU *cpu = X86_CPU(first_cpu); - if (kvm_enabled() && + if (!kvm_enabled() || !kvm_has_adjust_clock()) + return; + + if (create_always || cpu->env.features[FEAT_KVM] & ((1ULL << KVM_FEATURE_CLOCKSOURCE) | (1ULL << KVM_FEATURE_CLOCKSOURCE2))) { sysbus_create_simple(TYPE_KVM_CLOCK, -1, NULL); diff --git a/hw/i386/kvm/i8254.c b/hw/i386/kvm/i8254.c index 876f5aa6fa37aa1bda2bfa9a2c0e9a52d47b2d5a..40d84734e7f52ccb1449c3cad283ae446c6eaf71 100644 --- a/hw/i386/kvm/i8254.c +++ b/hw/i386/kvm/i8254.c @@ -25,7 +25,7 @@ #include "qemu/osdep.h" #include -#include "qapi/qapi-types-misc.h" +#include "qapi/qapi-types-machine.h" #include "qapi/error.h" #include "qemu/module.h" #include "qemu/timer.h" @@ -33,30 +33,30 @@ #include "hw/timer/i8254.h" #include "hw/timer/i8254_internal.h" #include "sysemu/kvm.h" +#include "qom/object.h" #define KVM_PIT_REINJECT_BIT 0 #define CALIBRATION_ROUNDS 3 -#define KVM_PIT(obj) OBJECT_CHECK(KVMPITState, (obj), TYPE_KVM_I8254) -#define KVM_PIT_CLASS(class) \ - OBJECT_CLASS_CHECK(KVMPITClass, (class), TYPE_KVM_I8254) -#define KVM_PIT_GET_CLASS(obj) \ - OBJECT_GET_CLASS(KVMPITClass, (obj), TYPE_KVM_I8254) +typedef struct KVMPITClass KVMPITClass; +typedef struct KVMPITState KVMPITState; +DECLARE_OBJ_CHECKERS(KVMPITState, KVMPITClass, + KVM_PIT, TYPE_KVM_I8254) -typedef struct KVMPITState { +struct KVMPITState { PITCommonState parent_obj; LostTickPolicy lost_tick_policy; bool vm_stopped; int64_t kernel_clock_offset; -} KVMPITState; +}; -typedef struct KVMPITClass { +struct KVMPITClass { PITCommonClass parent_class; DeviceRealize parent_realize; -} KVMPITClass; +}; static int64_t abs64(int64_t v) { diff --git a/hw/i386/kvm/i8259.c b/hw/i386/kvm/i8259.c index e404fdcdac77cf7088f226389afc7921e9b4d35f..3f8bf69e9ca4591737e65c83736f64579a6b1658 100644 --- a/hw/i386/kvm/i8259.c +++ b/hw/i386/kvm/i8259.c @@ -17,22 +17,22 @@ #include "hw/i386/apic_internal.h" #include "hw/irq.h" #include "sysemu/kvm.h" +#include "qom/object.h" #define TYPE_KVM_I8259 "kvm-i8259" -#define KVM_PIC_CLASS(class) \ - OBJECT_CLASS_CHECK(KVMPICClass, (class), TYPE_KVM_I8259) -#define KVM_PIC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(KVMPICClass, (obj), TYPE_KVM_I8259) +typedef struct KVMPICClass KVMPICClass; +DECLARE_CLASS_CHECKERS(KVMPICClass, KVM_PIC, + TYPE_KVM_I8259) /** * KVMPICClass: * @parent_realize: The parent's realizefn. */ -typedef struct KVMPICClass { +struct KVMPICClass { PICCommonClass parent_class; DeviceRealize parent_realize; -} KVMPICClass; +}; static void kvm_pic_get(PICCommonState *s) { diff --git a/hw/i386/kvm/ioapic.c b/hw/i386/kvm/ioapic.c index 4ba8e472510d450010bdd5a88b7b71a856a1547f..dfc3c9800574f2c7bc5c5d65fedae8d16ef9e180 100644 --- a/hw/i386/kvm/ioapic.c +++ b/hw/i386/kvm/ioapic.c @@ -25,27 +25,26 @@ void kvm_pc_setup_irq_routing(bool pci_enabled) KVMState *s = kvm_state; int i; - if (kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) { - for (i = 0; i < 8; ++i) { - if (i == 2) { - continue; - } - kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_MASTER, i); - } - for (i = 8; i < 16; ++i) { - kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_SLAVE, i - 8); + assert(kvm_has_gsi_routing()); + for (i = 0; i < 8; ++i) { + if (i == 2) { + continue; } - if (pci_enabled) { - for (i = 0; i < 24; ++i) { - if (i == 0) { - kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, 2); - } else if (i != 2) { - kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, i); - } + kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_MASTER, i); + } + for (i = 8; i < 16; ++i) { + kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_SLAVE, i - 8); + } + if (pci_enabled) { + for (i = 0; i < 24; ++i) { + if (i == 0) { + kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, 2); + } else if (i != 2) { + kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, i); } } - kvm_irqchip_commit_routes(s); } + kvm_irqchip_commit_routes(s); } typedef struct KVMIOAPICState KVMIOAPICState; @@ -97,7 +96,7 @@ static void kvm_ioapic_put(IOAPICCommonState *s) ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, &chip); if (ret < 0) { - fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); + fprintf(stderr, "KVM_SET_IRQCHIP failed: %s\n", strerror(ret)); abort(); } } diff --git a/hw/i386/kvm/meson.build b/hw/i386/kvm/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..95467f1ded6a9e16ee812ee48f2586d5340d4c3f --- /dev/null +++ b/hw/i386/kvm/meson.build @@ -0,0 +1,8 @@ +i386_kvm_ss = ss.source_set() +i386_kvm_ss.add(files('clock.c')) +i386_kvm_ss.add(when: 'CONFIG_APIC', if_true: files('apic.c')) +i386_kvm_ss.add(when: 'CONFIG_I8254', if_true: files('i8254.c')) +i386_kvm_ss.add(when: 'CONFIG_I8259', if_true: files('i8259.c')) +i386_kvm_ss.add(when: 'CONFIG_IOAPIC', if_true: files('ioapic.c')) + +i386_ss.add_all(when: 'CONFIG_KVM', if_true: i386_kvm_ss) diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c index 51639202c2a210c1fbbdfc6518c4833d0a172f53..077c3f4866c32c7a93e84ca42dcc87ad505fbcdd 100644 --- a/hw/i386/kvmvapic.c +++ b/hw/i386/kvmvapic.c @@ -22,6 +22,7 @@ #include "hw/boards.h" #include "migration/vmstate.h" #include "tcg/tcg.h" +#include "qom/object.h" #define VAPIC_IO_PORT 0x7e @@ -56,7 +57,7 @@ typedef struct GuestROMState { VAPICHandlers mp; } QEMU_PACKED GuestROMState; -typedef struct VAPICROMState { +struct VAPICROMState { SysBusDevice busdev; MemoryRegion io; MemoryRegion rom; @@ -69,10 +70,10 @@ typedef struct VAPICROMState { size_t rom_size; bool rom_mapped_writable; VMChangeStateEntry *vmsentry; -} VAPICROMState; +}; #define TYPE_VAPIC "kvmvapic" -#define VAPIC(obj) OBJECT_CHECK(VAPICROMState, (obj), TYPE_VAPIC) +OBJECT_DECLARE_SIMPLE_TYPE(VAPICROMState, VAPIC) #define TPR_INSTR_ABS_MODRM 0x1 #define TPR_INSTR_MATCH_MODRM_REG 0x2 diff --git a/hw/i386/meson.build b/hw/i386/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..e5d109f5c64df70c760d9e7e811030e53f99fd79 --- /dev/null +++ b/hw/i386/meson.build @@ -0,0 +1,33 @@ +i386_ss = ss.source_set() +i386_ss.add(files( + 'fw_cfg.c', + 'kvmvapic.c', + 'e820_memory_layout.c', + 'multiboot.c', + 'x86.c', +)) + +i386_ss.add(when: 'CONFIG_X86_IOMMU', if_true: files('x86-iommu.c'), + if_false: files('x86-iommu-stub.c')) +i386_ss.add(when: 'CONFIG_AMD_IOMMU', if_true: files('amd_iommu.c')) +i386_ss.add(when: 'CONFIG_I440FX', if_true: files('pc_piix.c')) +i386_ss.add(when: 'CONFIG_MICROVM', if_true: files('microvm.c', 'acpi-microvm.c')) +i386_ss.add(when: 'CONFIG_Q35', if_true: files('pc_q35.c')) +i386_ss.add(when: 'CONFIG_VMMOUSE', if_true: files('vmmouse.c')) +i386_ss.add(when: 'CONFIG_VMPORT', if_true: files('vmport.c')) +i386_ss.add(when: 'CONFIG_VTD', if_true: files('intel_iommu.c')) + +i386_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-common.c')) +i386_ss.add(when: 'CONFIG_ACPI_HW_REDUCED', if_true: files('generic_event_device_x86.c')) +i386_ss.add(when: 'CONFIG_PC', if_true: files( + 'pc.c', + 'pc_sysfw.c', + 'acpi-build.c', + 'port92.c')) + +subdir('kvm') +subdir('xen') + +i386_ss.add_all(xenpv_ss) + +hw_arch += {'i386': i386_ss} diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index 937db10ae6a539ac38c117881a5cc5320c1b3660..5428448b7059969a5648e1da275c09e39cee8dfe 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -26,6 +26,8 @@ #include "sysemu/cpus.h" #include "sysemu/numa.h" #include "sysemu/reset.h" +#include "sysemu/runstate.h" +#include "acpi-microvm.h" #include "hw/loader.h" #include "hw/irq.h" @@ -37,17 +39,23 @@ #include "hw/timer/i8254.h" #include "hw/rtc/mc146818rtc.h" #include "hw/char/serial.h" +#include "hw/display/ramfb.h" #include "hw/i386/topology.h" #include "hw/i386/e820_memory_layout.h" #include "hw/i386/fw_cfg.h" #include "hw/virtio/virtio-mmio.h" +#include "hw/acpi/acpi.h" +#include "hw/acpi/generic_event_device.h" +#include "hw/pci-host/gpex.h" +#include "hw/usb/xhci.h" #include "cpu.h" #include "elf.h" #include "kvm_i386.h" #include "hw/xen/start_info.h" -#define MICROVM_BIOS_FILENAME "bios-microvm.bin" +#define MICROVM_QBOOT_FILENAME "qboot.rom" +#define MICROVM_BIOS_FILENAME "bios-microvm.bin" static void microvm_set_rtc(MicrovmMachineState *mms, ISADevice *s) { @@ -95,6 +103,55 @@ static void microvm_gsi_handler(void *opaque, int n, int level) qemu_set_irq(s->ioapic_irq[n], level); } +static void create_gpex(MicrovmMachineState *mms) +{ + X86MachineState *x86ms = X86_MACHINE(mms); + MemoryRegion *mmio32_alias; + MemoryRegion *mmio64_alias; + MemoryRegion *mmio_reg; + MemoryRegion *ecam_alias; + MemoryRegion *ecam_reg; + DeviceState *dev; + int i; + + dev = qdev_new(TYPE_GPEX_HOST); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + /* Map only the first size_ecam bytes of ECAM space */ + ecam_alias = g_new0(MemoryRegion, 1); + ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam", + ecam_reg, 0, mms->gpex.ecam.size); + memory_region_add_subregion(get_system_memory(), + mms->gpex.ecam.base, ecam_alias); + + /* Map the MMIO window into system address space so as to expose + * the section of PCI MMIO space which starts at the same base address + * (ie 1:1 mapping for that part of PCI MMIO space visible through + * the window). + */ + mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1); + if (mms->gpex.mmio32.size) { + mmio32_alias = g_new0(MemoryRegion, 1); + memory_region_init_alias(mmio32_alias, OBJECT(dev), "pcie-mmio32", mmio_reg, + mms->gpex.mmio32.base, mms->gpex.mmio32.size); + memory_region_add_subregion(get_system_memory(), + mms->gpex.mmio32.base, mmio32_alias); + } + if (mms->gpex.mmio64.size) { + mmio64_alias = g_new0(MemoryRegion, 1); + memory_region_init_alias(mmio64_alias, OBJECT(dev), "pcie-mmio64", mmio_reg, + mms->gpex.mmio64.base, mms->gpex.mmio64.size); + memory_region_add_subregion(get_system_memory(), + mms->gpex.mmio64.base, mmio64_alias); + } + + for (i = 0; i < GPEX_NUM_IRQS; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, + x86ms->gsi[mms->gpex.irq + i]); + } +} + static void microvm_devices_init(MicrovmMachineState *mms) { X86MachineState *x86ms = X86_MACHINE(mms); @@ -119,15 +176,60 @@ static void microvm_devices_init(MicrovmMachineState *mms) ioapic_init_gsi(gsi_state, "machine"); - kvmclock_create(); + kvmclock_create(true); + mms->virtio_irq_base = x86_machine_is_acpi_enabled(x86ms) ? 16 : 5; for (i = 0; i < VIRTIO_NUM_TRANSPORTS; i++) { sysbus_create_simple("virtio-mmio", VIRTIO_MMIO_BASE + i * 512, - x86ms->gsi[VIRTIO_IRQ_BASE + i]); + x86ms->gsi[mms->virtio_irq_base + i]); } /* Optional and legacy devices */ + if (x86_machine_is_acpi_enabled(x86ms)) { + DeviceState *dev = qdev_new(TYPE_ACPI_GED_X86); + qdev_prop_set_uint32(dev, "ged-event", ACPI_GED_PWR_DOWN_EVT); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, GED_MMIO_BASE); + /* sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, GED_MMIO_BASE_MEMHP); */ + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, GED_MMIO_BASE_REGS); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, + x86ms->gsi[GED_MMIO_IRQ]); + sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal); + x86ms->acpi_dev = HOTPLUG_HANDLER(dev); + } + + if (x86_machine_is_acpi_enabled(x86ms) && machine_usb(MACHINE(mms))) { + DeviceState *dev = qdev_new(TYPE_XHCI_SYSBUS); + qdev_prop_set_uint32(dev, "intrs", 1); + qdev_prop_set_uint32(dev, "slots", XHCI_MAXSLOTS); + qdev_prop_set_uint32(dev, "p2", 8); + qdev_prop_set_uint32(dev, "p3", 8); + sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, MICROVM_XHCI_BASE); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, + x86ms->gsi[MICROVM_XHCI_IRQ]); + } + + if (x86_machine_is_acpi_enabled(x86ms) && mms->pcie == ON_OFF_AUTO_ON) { + /* use topmost 25% of the address space available */ + hwaddr phys_size = (hwaddr)1 << X86_CPU(first_cpu)->phys_bits; + if (phys_size > 0x1000000ll) { + mms->gpex.mmio64.size = phys_size / 4; + mms->gpex.mmio64.base = phys_size - mms->gpex.mmio64.size; + } + mms->gpex.mmio32.base = PCIE_MMIO_BASE; + mms->gpex.mmio32.size = PCIE_MMIO_SIZE; + mms->gpex.ecam.base = PCIE_ECAM_BASE; + mms->gpex.ecam.size = PCIE_ECAM_SIZE; + mms->gpex.irq = PCIE_IRQ_BASE; + create_gpex(mms); + x86ms->pci_irq_mask = ((1 << (PCIE_IRQ_BASE + 0)) | + (1 << (PCIE_IRQ_BASE + 1)) | + (1 << (PCIE_IRQ_BASE + 2)) | + (1 << (PCIE_IRQ_BASE + 3))); + } else { + x86ms->pci_irq_mask = 0; + } if (mms->pic == ON_OFF_AUTO_ON || mms->pic == ON_OFF_AUTO_AUTO) { qemu_irq *i8259; @@ -158,7 +260,9 @@ static void microvm_devices_init(MicrovmMachineState *mms) } if (bios_name == NULL) { - bios_name = MICROVM_BIOS_FILENAME; + bios_name = x86_machine_is_acpi_enabled(x86ms) + ? MICROVM_BIOS_FILENAME + : MICROVM_QBOOT_FILENAME; } x86_bios_rom_init(get_system_memory(), true); } @@ -170,42 +274,9 @@ static void microvm_memory_init(MicrovmMachineState *mms) MemoryRegion *ram_below_4g, *ram_above_4g; MemoryRegion *system_memory = get_system_memory(); FWCfgState *fw_cfg; - ram_addr_t lowmem; + ram_addr_t lowmem = 0xc0000000; /* 3G */ int i; - /* - * Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory - * and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping - * also known as MMCFG). - * If it doesn't, we need to split it in chunks below and above 4G. - * In any case, try to make sure that guest addresses aligned at - * 1G boundaries get mapped to host addresses aligned at 1G boundaries. - */ - if (machine->ram_size >= 0xb0000000) { - lowmem = 0x80000000; - } else { - lowmem = 0xb0000000; - } - - /* - * Handle the machine opt max-ram-below-4g. It is basically doing - * min(qemu limit, user limit). - */ - if (!x86ms->max_ram_below_4g) { - x86ms->max_ram_below_4g = 4 * GiB; - } - if (lowmem > x86ms->max_ram_below_4g) { - lowmem = x86ms->max_ram_below_4g; - if (machine->ram_size - lowmem > lowmem && - lowmem & (1 * GiB - 1)) { - warn_report("There is possibly poor performance as the ram size " - " (0x%" PRIx64 ") is more then twice the size of" - " max-ram-below-4g (%"PRIu64") and" - " max-ram-below-4g is not a multiple of 1G.", - (uint64_t)machine->ram_size, x86ms->max_ram_below_4g); - } - } - if (machine->ram_size > lowmem) { x86ms->above_4g_mem_size = machine->ram_size - lowmem; x86ms->below_4g_mem_size = lowmem; @@ -238,7 +309,7 @@ static void microvm_memory_init(MicrovmMachineState *mms) fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, machine->smp.cpus); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, machine->smp.max_cpus); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)machine->ram_size); - fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override()); + fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, 1); fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE, &e820_reserve, sizeof(e820_reserve)); fw_cfg_add_file(fw_cfg, "etc/e820", e820_table, @@ -260,7 +331,7 @@ static void microvm_memory_init(MicrovmMachineState *mms) x86ms->ioapic_as = &address_space_memory; } -static gchar *microvm_get_mmio_cmdline(gchar *name) +static gchar *microvm_get_mmio_cmdline(gchar *name, uint32_t virtio_irq_base) { gchar *cmdline; gchar *separator; @@ -280,7 +351,7 @@ static gchar *microvm_get_mmio_cmdline(gchar *name) ret = g_snprintf(cmdline, VIRTIO_CMDLINE_MAXLEN, " virtio_mmio.device=512@0x%lx:%ld", VIRTIO_MMIO_BASE + index * 512, - VIRTIO_IRQ_BASE + index); + virtio_irq_base + index); if (ret < 0 || ret >= VIRTIO_CMDLINE_MAXLEN) { g_free(cmdline); return NULL; @@ -292,6 +363,7 @@ static gchar *microvm_get_mmio_cmdline(gchar *name) static void microvm_fix_kernel_cmdline(MachineState *machine) { X86MachineState *x86ms = X86_MACHINE(machine); + MicrovmMachineState *mms = MICROVM_MACHINE(machine); BusState *bus; BusChild *kid; char *cmdline; @@ -315,7 +387,8 @@ static void microvm_fix_kernel_cmdline(MachineState *machine) BusState *mmio_bus = &mmio_virtio_bus->parent_obj; if (!QTAILQ_EMPTY(&mmio_bus->children)) { - gchar *mmio_cmdline = microvm_get_mmio_cmdline(mmio_bus->name); + gchar *mmio_cmdline = microvm_get_mmio_cmdline + (mmio_bus->name, mms->virtio_irq_base); if (mmio_cmdline) { char *newcmd = g_strjoin(NULL, cmdline, mmio_cmdline, NULL); g_free(mmio_cmdline); @@ -332,6 +405,42 @@ static void microvm_fix_kernel_cmdline(MachineState *machine) g_free(cmdline); } +static void microvm_device_pre_plug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + X86CPU *cpu = X86_CPU(dev); + + cpu->host_phys_bits = true; /* need reliable phys-bits */ + x86_cpu_pre_plug(hotplug_dev, dev, errp); +} + +static void microvm_device_plug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + x86_cpu_plug(hotplug_dev, dev, errp); +} + +static void microvm_device_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + error_setg(errp, "unplug not supported by microvm"); +} + +static void microvm_device_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + error_setg(errp, "unplug not supported by microvm"); +} + +static HotplugHandler *microvm_get_hotplug_handler(MachineState *machine, + DeviceState *dev) +{ + if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + return HOTPLUG_HANDLER(machine); + } + return NULL; +} + static void microvm_machine_state_init(MachineState *machine) { MicrovmMachineState *mms = MICROVM_MACHINE(machine); @@ -355,7 +464,8 @@ static void microvm_machine_reset(MachineState *machine) CPUState *cs; X86CPU *cpu; - if (machine->kernel_filename != NULL && + if (!x86_machine_is_acpi_enabled(X86_MACHINE(machine)) && + machine->kernel_filename != NULL && mms->auto_kernel_cmdline && !mms->kernel_cmdline_fixed) { microvm_fix_kernel_cmdline(machine); mms->kernel_cmdline_fixed = true; @@ -423,6 +533,23 @@ static void microvm_machine_set_rtc(Object *obj, Visitor *v, const char *name, visit_type_OnOffAuto(v, name, &mms->rtc, errp); } +static void microvm_machine_get_pcie(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + MicrovmMachineState *mms = MICROVM_MACHINE(obj); + OnOffAuto pcie = mms->pcie; + + visit_type_OnOffAuto(v, name, &pcie, errp); +} + +static void microvm_machine_set_pcie(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + MicrovmMachineState *mms = MICROVM_MACHINE(obj); + + visit_type_OnOffAuto(v, name, &mms->pcie, errp); +} + static bool microvm_machine_get_isa_serial(Object *obj, Error **errp) { MicrovmMachineState *mms = MICROVM_MACHINE(obj); @@ -468,6 +595,28 @@ static void microvm_machine_set_auto_kernel_cmdline(Object *obj, bool value, mms->auto_kernel_cmdline = value; } +static void microvm_machine_done(Notifier *notifier, void *data) +{ + MicrovmMachineState *mms = container_of(notifier, MicrovmMachineState, + machine_done); + + acpi_setup_microvm(mms); +} + +static void microvm_powerdown_req(Notifier *notifier, void *data) +{ + MicrovmMachineState *mms = container_of(notifier, MicrovmMachineState, + powerdown_req); + X86MachineState *x86ms = X86_MACHINE(mms); + + if (x86ms->acpi_dev) { + Object *obj = OBJECT(x86ms->acpi_dev); + AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj); + adevc->send_event(ACPI_DEVICE_IF(x86ms->acpi_dev), + ACPI_POWER_DOWN_STATUS); + } +} + static void microvm_machine_initfn(Object *obj) { MicrovmMachineState *mms = MICROVM_MACHINE(obj); @@ -476,17 +625,24 @@ static void microvm_machine_initfn(Object *obj) mms->pic = ON_OFF_AUTO_AUTO; mms->pit = ON_OFF_AUTO_AUTO; mms->rtc = ON_OFF_AUTO_AUTO; + mms->pcie = ON_OFF_AUTO_AUTO; mms->isa_serial = true; mms->option_roms = true; mms->auto_kernel_cmdline = true; /* State */ mms->kernel_cmdline_fixed = false; + + mms->machine_done.notify = microvm_machine_done; + qemu_add_machine_init_done_notifier(&mms->machine_done); + mms->powerdown_req.notify = microvm_powerdown_req; + qemu_register_powerdown_notifier(&mms->powerdown_req); } static void microvm_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); mc->init = microvm_machine_state_init; @@ -497,6 +653,7 @@ static void microvm_class_init(ObjectClass *oc, void *data) mc->max_cpus = 288; mc->has_hotpluggable_cpus = false; mc->auto_enable_numa_with_memhp = false; + mc->auto_enable_numa_with_memdev = false; mc->default_cpu_type = TARGET_DEFAULT_CPU_TYPE; mc->nvdimm_supported = false; mc->default_ram_id = "microvm.ram"; @@ -507,6 +664,13 @@ static void microvm_class_init(ObjectClass *oc, void *data) /* Machine class handlers */ mc->reset = microvm_machine_reset; + /* hotplug (for cpu coldplug) */ + mc->get_hotplug_handler = microvm_get_hotplug_handler; + hc->pre_plug = microvm_device_pre_plug_cb; + hc->plug = microvm_device_plug_cb; + hc->unplug_request = microvm_device_unplug_request_cb; + hc->unplug = microvm_device_unplug_cb; + object_class_property_add(oc, MICROVM_MACHINE_PIC, "OnOffAuto", microvm_machine_get_pic, microvm_machine_set_pic, @@ -528,6 +692,13 @@ static void microvm_class_init(ObjectClass *oc, void *data) object_class_property_set_description(oc, MICROVM_MACHINE_RTC, "Enable MC146818 RTC"); + object_class_property_add(oc, MICROVM_MACHINE_PCIE, "OnOffAuto", + microvm_machine_get_pcie, + microvm_machine_set_pcie, + NULL, NULL); + object_class_property_set_description(oc, MICROVM_MACHINE_PCIE, + "Enable PCIe"); + object_class_property_add_bool(oc, MICROVM_MACHINE_ISA_SERIAL, microvm_machine_get_isa_serial, microvm_machine_set_isa_serial); @@ -546,6 +717,8 @@ static void microvm_class_init(ObjectClass *oc, void *data) object_class_property_set_description(oc, MICROVM_MACHINE_AUTO_KERNEL_CMDLINE, "Set off to disable adding virtio-mmio devices to the kernel cmdline"); + + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE); } static const TypeInfo microvm_machine_info = { @@ -556,6 +729,7 @@ static const TypeInfo microvm_machine_info = { .class_size = sizeof(MicrovmMachineClass), .class_init = microvm_class_init, .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, { } }, }; diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 2128f3d6fe8baa81a2f5be0030c84fa273db7bc0..17b514d1da50e25c3d77d7e36ca87a808186dda9 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -31,6 +31,7 @@ #include "hw/i386/apic.h" #include "hw/i386/topology.h" #include "hw/i386/fw_cfg.h" +#include "hw/i386/vmport.h" #include "sysemu/cpus.h" #include "hw/block/fdc.h" #include "hw/ide.h" @@ -56,6 +57,7 @@ #include "sysemu/tcg.h" #include "sysemu/numa.h" #include "sysemu/kvm.h" +#include "sysemu/xen.h" #include "sysemu/qtest.h" #include "sysemu/reset.h" #include "sysemu/runstate.h" @@ -86,16 +88,22 @@ #include "hw/net/ne2000-isa.h" #include "standard-headers/asm-x86/bootparam.h" #include "hw/virtio/virtio-pmem-pci.h" +#include "hw/virtio/virtio-mem-pci.h" #include "hw/mem/memory-device.h" #include "sysemu/replay.h" #include "qapi/qmp/qerror.h" -#include "config-devices.h" #include "e820_memory_layout.h" -#include "vmport.h" #include "fw_cfg.h" #include "trace.h" +#include CONFIG_DEVICES -GlobalProperty pc_compat_5_0[] = {}; +GlobalProperty pc_compat_5_1[] = { + { "ICH9-LPC", "x-smi-cpu-hotplug", "off" }, +}; +const size_t pc_compat_5_1_len = G_N_ELEMENTS(pc_compat_5_1); + +GlobalProperty pc_compat_5_0[] = { +}; const size_t pc_compat_5_0_len = G_N_ELEMENTS(pc_compat_5_0); GlobalProperty pc_compat_4_2[] = { @@ -385,31 +393,6 @@ static uint64_t ioportF0_read(void *opaque, hwaddr addr, unsigned size) #define REG_EQUIPMENT_BYTE 0x14 -int cmos_get_fd_drive_type(FloppyDriveType fd0) -{ - int val; - - switch (fd0) { - case FLOPPY_DRIVE_TYPE_144: - /* 1.44 Mb 3"5 drive */ - val = 4; - break; - case FLOPPY_DRIVE_TYPE_288: - /* 2.88 Mb 3"5 drive */ - val = 5; - break; - case FLOPPY_DRIVE_TYPE_120: - /* 1.2 Mb 5"5 drive */ - val = 2; - break; - case FLOPPY_DRIVE_TYPE_NONE: - default: - val = 0; - break; - } - return val; -} - static void cmos_init_hd(ISADevice *s, int type_ofs, int info_ofs, int16_t cylinders, int8_t heads, int8_t sectors) { @@ -663,8 +646,8 @@ void pc_cmos_init(PCMachineState *pcms, (Object **)&x86ms->rtc, object_property_allow_set_link, OBJ_PROP_LINK_STRONG); - object_property_set_link(OBJECT(pcms), OBJECT(s), - "rtc_state", &error_abort); + object_property_set_link(OBJECT(pcms), "rtc_state", OBJECT(s), + &error_abort); set_boot_dev(s, MACHINE(pcms)->boot_order, &error_fatal); @@ -765,23 +748,15 @@ void pc_smp_parse(MachineState *ms, QemuOpts *opts) exit(1); } - if (sockets * dies * cores * threads > ms->smp.max_cpus) { - error_report("cpu topology: " - "sockets (%u) * dies (%u) * cores (%u) * threads (%u) > " - "maxcpus (%u)", + if (sockets * dies * cores * threads != ms->smp.max_cpus) { + error_report("Invalid CPU topology deprecated: " + "sockets (%u) * dies (%u) * cores (%u) * threads (%u) " + "!= maxcpus (%u)", sockets, dies, cores, threads, ms->smp.max_cpus); exit(1); } - if (sockets * dies * cores * threads != ms->smp.max_cpus) { - warn_report("Invalid CPU topology deprecated: " - "sockets (%u) * dies (%u) * cores (%u) * threads (%u) " - "!= maxcpus (%u)", - sockets, dies, cores, threads, - ms->smp.max_cpus); - } - ms->smp.cpus = cpus; ms->smp.cores = cores; ms->smp.threads = threads; @@ -796,45 +771,6 @@ void pc_smp_parse(MachineState *ms, QemuOpts *opts) } } -void pc_hot_add_cpu(MachineState *ms, const int64_t id, Error **errp) -{ - X86MachineState *x86ms = X86_MACHINE(ms); - int64_t apic_id = x86_cpu_apic_id_from_index(x86ms, id); - Error *local_err = NULL; - - if (id < 0) { - error_setg(errp, "Invalid CPU id: %" PRIi64, id); - return; - } - - if (apic_id >= ACPI_CPU_HOTPLUG_ID_LIMIT) { - error_setg(errp, "Unable to add CPU: %" PRIi64 - ", resulting APIC ID (%" PRIi64 ") is too large", - id, apic_id); - return; - } - - - x86_cpu_new(X86_MACHINE(ms), apic_id, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } -} - -static void rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count) -{ - if (cpus_count > 0xff) { - /* If the number of CPUs can't be represented in 8 bits, the - * BIOS must use "FW_CFG_NB_CPUS". Set RTC field to 0 just - * to make old BIOSes fail more predictably. - */ - rtc_set_memory(rtc, 0x5f, 0); - } else { - rtc_set_memory(rtc, 0x5f, cpus_count - 1); - } -} - static void pc_machine_done(Notifier *notifier, void *data) { @@ -844,7 +780,7 @@ void pc_machine_done(Notifier *notifier, void *data) PCIBus *bus = pcms->bus; /* set the number of CPUs */ - rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus); + x86_rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus); if (bus) { int extra_hosts = 0; @@ -891,7 +827,7 @@ void pc_guest_info_init(PCMachineState *pcms) MachineState *ms = MACHINE(pcms); X86MachineState *x86ms = X86_MACHINE(pcms); - x86ms->apic_xrupt_override = kvm_allows_irq0_override(); + x86ms->apic_xrupt_override = true; pcms->numa_nodes = ms->numa_state->num_nodes; pcms->node_mem = g_malloc0(pcms->numa_nodes * sizeof *pcms->node_mem); @@ -1141,7 +1077,7 @@ static void pc_superio_init(ISABus *isa_bus, bool create_fdctrl, bool no_vmport) int i; DriveInfo *fd[MAX_FD]; qemu_irq *a20_line; - ISADevice *i8042, *port92, *vmmouse; + ISADevice *fdc, *i8042, *port92, *vmmouse; serial_hds_isa_init(isa_bus, 0, MAX_ISA_SERIAL_PORTS); parallel_hds_isa_init(isa_bus, MAX_PARALLEL_PORTS); @@ -1151,20 +1087,24 @@ static void pc_superio_init(ISABus *isa_bus, bool create_fdctrl, bool no_vmport) create_fdctrl |= !!fd[i]; } if (create_fdctrl) { - fdctrl_init_isa(isa_bus, fd); + fdc = isa_new(TYPE_ISA_FDC); + if (fdc) { + isa_realize_and_unref(fdc, isa_bus, &error_fatal); + isa_fdc_init_drives(fdc, fd); + } } i8042 = isa_create_simple(isa_bus, "i8042"); if (!no_vmport) { isa_create_simple(isa_bus, TYPE_VMPORT); - vmmouse = isa_try_create(isa_bus, "vmmouse"); + vmmouse = isa_try_new("vmmouse"); } else { vmmouse = NULL; } if (vmmouse) { - object_property_set_link(OBJECT(vmmouse), OBJECT(i8042), - "i8042", &error_abort); - qdev_init_nofail(DEVICE(vmmouse)); + object_property_set_link(OBJECT(vmmouse), "i8042", OBJECT(i8042), + &error_abort); + isa_realize_and_unref(vmmouse, isa_bus, &error_fatal); } port92 = isa_create_simple(isa_bus, TYPE_PORT92); @@ -1175,11 +1115,10 @@ static void pc_superio_init(ISABus *isa_bus, bool create_fdctrl, bool no_vmport) g_free(a20_line); } -void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, +void pc_basic_device_init(struct PCMachineState *pcms, + ISABus *isa_bus, qemu_irq *gsi, ISADevice **rtc_state, bool create_fdctrl, - bool no_vmport, - bool has_pit, uint32_t hpet_irqs) { int i; @@ -1203,34 +1142,38 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, * Without KVM_CAP_PIT_STATE2, we cannot switch off the in-kernel PIT * when the HPET wants to take over. Thus we have to disable the latter. */ - if (!no_hpet && (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) { - hpet = qdev_try_create(NULL, TYPE_HPET); - if (hpet) { - /* For pc-piix-*, hpet's intcap is always IRQ2. For pc-q35-1.7 - * and earlier, use IRQ2 for compat. Otherwise, use IRQ16~23, - * IRQ8 and IRQ2. - */ - uint8_t compat = object_property_get_uint(OBJECT(hpet), - HPET_INTCAP, NULL); - if (!compat) { - qdev_prop_set_uint32(hpet, HPET_INTCAP, hpet_irqs); - } - qdev_init_nofail(hpet); - sysbus_mmio_map(SYS_BUS_DEVICE(hpet), 0, HPET_BASE); + if (pcms->hpet_enabled && (!kvm_irqchip_in_kernel() || + kvm_has_pit_state2())) { + hpet = qdev_try_new(TYPE_HPET); + if (!hpet) { + error_report("couldn't create HPET device"); + exit(1); + } + /* + * For pc-piix-*, hpet's intcap is always IRQ2. For pc-q35-1.7 and + * earlier, use IRQ2 for compat. Otherwise, use IRQ16~23, IRQ8 and + * IRQ2. + */ + uint8_t compat = object_property_get_uint(OBJECT(hpet), + HPET_INTCAP, NULL); + if (!compat) { + qdev_prop_set_uint32(hpet, HPET_INTCAP, hpet_irqs); + } + sysbus_realize_and_unref(SYS_BUS_DEVICE(hpet), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(hpet), 0, HPET_BASE); - for (i = 0; i < GSI_NUM_PINS; i++) { - sysbus_connect_irq(SYS_BUS_DEVICE(hpet), i, gsi[i]); - } - pit_isa_irq = -1; - pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT); - rtc_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_RTC_INT); + for (i = 0; i < GSI_NUM_PINS; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(hpet), i, gsi[i]); } + pit_isa_irq = -1; + pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT); + rtc_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_RTC_INT); } *rtc_state = mc146818_rtc_init(isa_bus, 2000, rtc_irq); qemu_register_boot_set(pc_boot_set, *rtc_state); - if (!xen_enabled() && has_pit) { + if (!xen_enabled() && pcms->pit_enabled) { if (kvm_pit_in_kernel()) { pit = kvm_pit_init(isa_bus, 0x40); } else { @@ -1240,13 +1183,13 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, /* connect PIT to output control line of the HPET */ qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(DEVICE(pit), 0)); } - pcspk_init(isa_bus, pit); + pcspk_init(pcms->pcspk, isa_bus, pit); } i8257_dma_init(isa_bus, 0); /* Super I/O */ - pc_superio_init(isa_bus, create_fdctrl, no_vmport); + pc_superio_init(isa_bus, create_fdctrl, pcms->vmport != ON_OFF_AUTO_ON); } void pc_nic_init(PCMachineClass *pcmc, ISABus *isa_bus, PCIBus *pci_bus) @@ -1290,6 +1233,7 @@ static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { const PCMachineState *pcms = PC_MACHINE(hotplug_dev); + const X86MachineState *x86ms = X86_MACHINE(hotplug_dev); const PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); const MachineState *ms = MACHINE(hotplug_dev); const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); @@ -1301,7 +1245,7 @@ static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, * but pcms->acpi_dev is still created. Check !acpi_enabled in * addition to cover this case. */ - if (!pcms->acpi_dev || !x86_machine_is_acpi_enabled(X86_MACHINE(pcms))) { + if (!x86ms->acpi_dev || !x86_machine_is_acpi_enabled(x86ms)) { error_setg(errp, "memory hotplug is not enabled: missing acpi device or acpi disabled"); return; @@ -1312,7 +1256,7 @@ static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, return; } - hotplug_handler_pre_plug(pcms->acpi_dev, dev, &local_err); + hotplug_handler_pre_plug(x86ms->acpi_dev, dev, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -1325,351 +1269,77 @@ static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, static void pc_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - Error *local_err = NULL; PCMachineState *pcms = PC_MACHINE(hotplug_dev); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); MachineState *ms = MACHINE(hotplug_dev); bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); - pc_dimm_plug(PC_DIMM(dev), MACHINE(pcms), &local_err); - if (local_err) { - goto out; - } + pc_dimm_plug(PC_DIMM(dev), MACHINE(pcms)); if (is_nvdimm) { nvdimm_plug(ms->nvdimms_state); } - hotplug_handler_plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &error_abort); -out: - error_propagate(errp, local_err); + hotplug_handler_plug(x86ms->acpi_dev, dev, &error_abort); } static void pc_memory_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - Error *local_err = NULL; - PCMachineState *pcms = PC_MACHINE(hotplug_dev); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); /* * When -no-acpi is used with Q35 machine type, no ACPI is built, * but pcms->acpi_dev is still created. Check !acpi_enabled in * addition to cover this case. */ - if (!pcms->acpi_dev || !x86_machine_is_acpi_enabled(X86_MACHINE(pcms))) { - error_setg(&local_err, + if (!x86ms->acpi_dev || !x86_machine_is_acpi_enabled(x86ms)) { + error_setg(errp, "memory hotplug is not enabled: missing acpi device or acpi disabled"); - goto out; + return; } if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { - error_setg(&local_err, - "nvdimm device hot unplug is not supported yet."); - goto out; + error_setg(errp, "nvdimm device hot unplug is not supported yet."); + return; } - hotplug_handler_unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, - &local_err); -out: - error_propagate(errp, local_err); + hotplug_handler_unplug_request(x86ms->acpi_dev, dev, + errp); } static void pc_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { PCMachineState *pcms = PC_MACHINE(hotplug_dev); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); Error *local_err = NULL; - hotplug_handler_unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err); + hotplug_handler_unplug(x86ms->acpi_dev, dev, &local_err); if (local_err) { goto out; } pc_dimm_unplug(PC_DIMM(dev), MACHINE(pcms)); - object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); - out: - error_propagate(errp, local_err); -} - -static int pc_apic_cmp(const void *a, const void *b) -{ - CPUArchId *apic_a = (CPUArchId *)a; - CPUArchId *apic_b = (CPUArchId *)b; - - return apic_a->arch_id - apic_b->arch_id; -} - -/* returns pointer to CPUArchId descriptor that matches CPU's apic_id - * in ms->possible_cpus->cpus, if ms->possible_cpus->cpus has no - * entry corresponding to CPU's apic_id returns NULL. - */ -static CPUArchId *pc_find_cpu_slot(MachineState *ms, uint32_t id, int *idx) -{ - CPUArchId apic_id, *found_cpu; - - apic_id.arch_id = id; - found_cpu = bsearch(&apic_id, ms->possible_cpus->cpus, - ms->possible_cpus->len, sizeof(*ms->possible_cpus->cpus), - pc_apic_cmp); - if (found_cpu && idx) { - *idx = found_cpu - ms->possible_cpus->cpus; - } - return found_cpu; -} - -static void pc_cpu_plug(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) -{ - CPUArchId *found_cpu; - Error *local_err = NULL; - X86CPU *cpu = X86_CPU(dev); - PCMachineState *pcms = PC_MACHINE(hotplug_dev); - X86MachineState *x86ms = X86_MACHINE(pcms); - - if (pcms->acpi_dev) { - hotplug_handler_plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err); - if (local_err) { - goto out; - } - } - - /* increment the number of CPUs */ - x86ms->boot_cpus++; - if (x86ms->rtc) { - rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus); - } - if (x86ms->fw_cfg) { - fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus); - } - - found_cpu = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, NULL); - found_cpu->cpu = OBJECT(dev); -out: - error_propagate(errp, local_err); -} -static void pc_cpu_unplug_request_cb(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) -{ - int idx = -1; - Error *local_err = NULL; - X86CPU *cpu = X86_CPU(dev); - PCMachineState *pcms = PC_MACHINE(hotplug_dev); - - if (!pcms->acpi_dev) { - error_setg(&local_err, "CPU hot unplug not supported without ACPI"); - goto out; - } - - pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, &idx); - assert(idx != -1); - if (idx == 0) { - error_setg(&local_err, "Boot CPU is unpluggable"); - goto out; - } - - hotplug_handler_unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, - &local_err); - if (local_err) { - goto out; - } - - out: - error_propagate(errp, local_err); - -} - -static void pc_cpu_unplug_cb(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) -{ - CPUArchId *found_cpu; - Error *local_err = NULL; - X86CPU *cpu = X86_CPU(dev); - PCMachineState *pcms = PC_MACHINE(hotplug_dev); - X86MachineState *x86ms = X86_MACHINE(pcms); - - hotplug_handler_unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err); - if (local_err) { - goto out; - } - - found_cpu = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, NULL); - found_cpu->cpu = NULL; - object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); - - /* decrement the number of CPUs */ - x86ms->boot_cpus--; - /* Update the number of CPUs in CMOS */ - rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus); - fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus); + qdev_unrealize(dev); out: error_propagate(errp, local_err); } -static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) -{ - int idx; - CPUState *cs; - CPUArchId *cpu_slot; - X86CPUTopoIDs topo_ids; - X86CPU *cpu = X86_CPU(dev); - CPUX86State *env = &cpu->env; - MachineState *ms = MACHINE(hotplug_dev); - PCMachineState *pcms = PC_MACHINE(hotplug_dev); - X86MachineState *x86ms = X86_MACHINE(pcms); - unsigned int smp_cores = ms->smp.cores; - unsigned int smp_threads = ms->smp.threads; - X86CPUTopoInfo topo_info; - - if(!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) { - error_setg(errp, "Invalid CPU type, expected cpu type: '%s'", - ms->cpu_type); - return; - } - - init_topo_info(&topo_info, x86ms); - - env->nr_dies = x86ms->smp_dies; - env->nr_nodes = topo_info.nodes_per_pkg; - env->pkg_offset = x86ms->apicid_pkg_offset(&topo_info); - - /* - * If APIC ID is not set, - * set it based on socket/die/core/thread properties. - */ - if (cpu->apic_id == UNASSIGNED_APIC_ID) { - int max_socket = (ms->smp.max_cpus - 1) / - smp_threads / smp_cores / x86ms->smp_dies; - - /* - * die-id was optional in QEMU 4.0 and older, so keep it optional - * if there's only one die per socket. - */ - if (cpu->die_id < 0 && x86ms->smp_dies == 1) { - cpu->die_id = 0; - } - - if (cpu->socket_id < 0) { - error_setg(errp, "CPU socket-id is not set"); - return; - } else if (cpu->socket_id > max_socket) { - error_setg(errp, "Invalid CPU socket-id: %u must be in range 0:%u", - cpu->socket_id, max_socket); - return; - } - if (cpu->die_id < 0) { - error_setg(errp, "CPU die-id is not set"); - return; - } else if (cpu->die_id > x86ms->smp_dies - 1) { - error_setg(errp, "Invalid CPU die-id: %u must be in range 0:%u", - cpu->die_id, x86ms->smp_dies - 1); - return; - } - if (cpu->core_id < 0) { - error_setg(errp, "CPU core-id is not set"); - return; - } else if (cpu->core_id > (smp_cores - 1)) { - error_setg(errp, "Invalid CPU core-id: %u must be in range 0:%u", - cpu->core_id, smp_cores - 1); - return; - } - if (cpu->thread_id < 0) { - error_setg(errp, "CPU thread-id is not set"); - return; - } else if (cpu->thread_id > (smp_threads - 1)) { - error_setg(errp, "Invalid CPU thread-id: %u must be in range 0:%u", - cpu->thread_id, smp_threads - 1); - return; - } - - topo_ids.pkg_id = cpu->socket_id; - topo_ids.die_id = cpu->die_id; - topo_ids.core_id = cpu->core_id; - topo_ids.smt_id = cpu->thread_id; - cpu->apic_id = x86ms->apicid_from_topo_ids(&topo_info, &topo_ids); - } - - cpu_slot = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, &idx); - if (!cpu_slot) { - MachineState *ms = MACHINE(pcms); - - x86ms->topo_ids_from_apicid(cpu->apic_id, &topo_info, &topo_ids); - error_setg(errp, - "Invalid CPU [socket: %u, die: %u, core: %u, thread: %u] with" - " APIC ID %" PRIu32 ", valid index range 0:%d", - topo_ids.pkg_id, topo_ids.die_id, topo_ids.core_id, topo_ids.smt_id, - cpu->apic_id, ms->possible_cpus->len - 1); - return; - } - - if (cpu_slot->cpu) { - error_setg(errp, "CPU[%d] with APIC ID %" PRIu32 " exists", - idx, cpu->apic_id); - return; - } - - /* if 'address' properties socket-id/core-id/thread-id are not set, set them - * so that machine_query_hotpluggable_cpus would show correct values - */ - /* TODO: move socket_id/core_id/thread_id checks into x86_cpu_realizefn() - * once -smp refactoring is complete and there will be CPU private - * CPUState::nr_cores and CPUState::nr_threads fields instead of globals */ - x86ms->topo_ids_from_apicid(cpu->apic_id, &topo_info, &topo_ids); - if (cpu->socket_id != -1 && cpu->socket_id != topo_ids.pkg_id) { - error_setg(errp, "property socket-id: %u doesn't match set apic-id:" - " 0x%x (socket-id: %u)", cpu->socket_id, cpu->apic_id, - topo_ids.pkg_id); - return; - } - cpu->socket_id = topo_ids.pkg_id; - - if (cpu->die_id != -1 && cpu->die_id != topo_ids.die_id) { - error_setg(errp, "property die-id: %u doesn't match set apic-id:" - " 0x%x (die-id: %u)", cpu->die_id, cpu->apic_id, topo_ids.die_id); - return; - } - cpu->die_id = topo_ids.die_id; - - if (cpu->core_id != -1 && cpu->core_id != topo_ids.core_id) { - error_setg(errp, "property core-id: %u doesn't match set apic-id:" - " 0x%x (core-id: %u)", cpu->core_id, cpu->apic_id, - topo_ids.core_id); - return; - } - cpu->core_id = topo_ids.core_id; - - if (cpu->thread_id != -1 && cpu->thread_id != topo_ids.smt_id) { - error_setg(errp, "property thread-id: %u doesn't match set apic-id:" - " 0x%x (thread-id: %u)", cpu->thread_id, cpu->apic_id, - topo_ids.smt_id); - return; - } - cpu->thread_id = topo_ids.smt_id; - - if (hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX) && - !kvm_hv_vpindex_settable()) { - error_setg(errp, "kernel doesn't allow setting HyperV VP_INDEX"); - return; - } - - cs = CPU(cpu); - cs->cpu_index = idx; - - numa_cpu_pre_plug(cpu_slot, dev, errp); -} - -static void pc_virtio_pmem_pci_pre_plug(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) +static void pc_virtio_md_pci_pre_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) { HotplugHandler *hotplug_dev2 = qdev_get_bus_hotplug_handler(dev); Error *local_err = NULL; - if (!hotplug_dev2) { + if (!hotplug_dev2 && dev->hotplugged) { /* * Without a bus hotplug handler, we cannot control the plug/unplug - * order. This should never be the case on x86, however better add - * a safety net. + * order. We should never reach this point when hotplugging on x86, + * however, better add a safety net. */ - error_setg(errp, "virtio-pmem-pci not supported on this bus."); + error_setg(errp, "hotplug of virtio based memory devices not supported" + " on this bus."); return; } /* @@ -1678,14 +1348,14 @@ static void pc_virtio_pmem_pci_pre_plug(HotplugHandler *hotplug_dev, */ memory_device_pre_plug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev), NULL, &local_err); - if (!local_err) { + if (!local_err && hotplug_dev2) { hotplug_handler_pre_plug(hotplug_dev2, dev, &local_err); } error_propagate(errp, local_err); } -static void pc_virtio_pmem_pci_plug(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) +static void pc_virtio_md_pci_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) { HotplugHandler *hotplug_dev2 = qdev_get_bus_hotplug_handler(dev); Error *local_err = NULL; @@ -1696,24 +1366,26 @@ static void pc_virtio_pmem_pci_plug(HotplugHandler *hotplug_dev, * device bits. */ memory_device_plug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev)); - hotplug_handler_plug(hotplug_dev2, dev, &local_err); - if (local_err) { - memory_device_unplug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev)); + if (hotplug_dev2) { + hotplug_handler_plug(hotplug_dev2, dev, &local_err); + if (local_err) { + memory_device_unplug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev)); + } } error_propagate(errp, local_err); } -static void pc_virtio_pmem_pci_unplug_request(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) +static void pc_virtio_md_pci_unplug_request(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) { - /* We don't support virtio pmem hot unplug */ - error_setg(errp, "virtio pmem device unplug not supported."); + /* We don't support hot unplug of virtio based memory devices */ + error_setg(errp, "virtio based memory devices cannot be unplugged."); } -static void pc_virtio_pmem_pci_unplug(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) +static void pc_virtio_md_pci_unplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) { - /* We don't support virtio pmem hot unplug */ + /* We don't support hot unplug of virtio based memory devices */ } static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, @@ -1722,9 +1394,10 @@ static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { pc_memory_pre_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { - pc_cpu_pre_plug(hotplug_dev, dev, errp); - } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI)) { - pc_virtio_pmem_pci_pre_plug(hotplug_dev, dev, errp); + x86_cpu_pre_plug(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI) || + object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI)) { + pc_virtio_md_pci_pre_plug(hotplug_dev, dev, errp); } } @@ -1734,9 +1407,10 @@ static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev, if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { pc_memory_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { - pc_cpu_plug(hotplug_dev, dev, errp); - } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI)) { - pc_virtio_pmem_pci_plug(hotplug_dev, dev, errp); + x86_cpu_plug(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI) || + object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI)) { + pc_virtio_md_pci_plug(hotplug_dev, dev, errp); } } @@ -1746,9 +1420,10 @@ static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev, if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { pc_memory_unplug_request(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { - pc_cpu_unplug_request_cb(hotplug_dev, dev, errp); - } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI)) { - pc_virtio_pmem_pci_unplug_request(hotplug_dev, dev, errp); + x86_cpu_unplug_request_cb(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI) || + object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI)) { + pc_virtio_md_pci_unplug_request(hotplug_dev, dev, errp); } else { error_setg(errp, "acpi: device unplug request for not supported device" " type: %s", object_get_typename(OBJECT(dev))); @@ -1761,9 +1436,10 @@ static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev, if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { pc_memory_unplug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { - pc_cpu_unplug_cb(hotplug_dev, dev, errp); - } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI)) { - pc_virtio_pmem_pci_unplug(hotplug_dev, dev, errp); + x86_cpu_unplug_cb(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI) || + object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI)) { + pc_virtio_md_pci_unplug(hotplug_dev, dev, errp); } else { error_setg(errp, "acpi: device unplug for not supported device" " type: %s", object_get_typename(OBJECT(dev))); @@ -1775,7 +1451,8 @@ static HotplugHandler *pc_get_hotplug_handler(MachineState *machine, { if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || object_dynamic_cast(OBJECT(dev), TYPE_CPU) || - object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI)) { + object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI) || + object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI)) { return HOTPLUG_HANDLER(machine); } @@ -1856,6 +1533,55 @@ static void pc_machine_set_pit(Object *obj, bool value, Error **errp) pcms->pit_enabled = value; } +static bool pc_machine_get_hpet(Object *obj, Error **errp) +{ + PCMachineState *pcms = PC_MACHINE(obj); + + return pcms->hpet_enabled; +} + +static void pc_machine_set_hpet(Object *obj, bool value, Error **errp) +{ + PCMachineState *pcms = PC_MACHINE(obj); + + pcms->hpet_enabled = value; +} + +static void pc_machine_get_max_ram_below_4g(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + PCMachineState *pcms = PC_MACHINE(obj); + uint64_t value = pcms->max_ram_below_4g; + + visit_type_size(v, name, &value, errp); +} + +static void pc_machine_set_max_ram_below_4g(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + PCMachineState *pcms = PC_MACHINE(obj); + uint64_t value; + + if (!visit_type_size(v, name, &value, errp)) { + return; + } + if (value > 4 * GiB) { + error_setg(errp, + "Machine option 'max-ram-below-4g=%"PRIu64 + "' expects size less than or equal to 4G", value); + return; + } + + if (value < 1 * MiB) { + warn_report("Only %" PRIu64 " bytes of RAM below the 4GiB boundary," + "BIOS may not work with less than 1MiB", value); + } + + pcms->max_ram_below_4g = value; +} + static void pc_machine_initfn(Object *obj) { PCMachineState *pcms = PC_MACHINE(obj); @@ -1865,13 +1591,20 @@ static void pc_machine_initfn(Object *obj) #else pcms->vmport = ON_OFF_AUTO_OFF; #endif /* CONFIG_VMPORT */ + pcms->max_ram_below_4g = 0; /* use default */ /* acpi build is enabled by default if machine supports it */ pcms->acpi_build_enabled = PC_MACHINE_GET_CLASS(pcms)->has_acpi_build; pcms->smbus_enabled = true; pcms->sata_enabled = true; pcms->pit_enabled = true; +#ifdef CONFIG_HPET + pcms->hpet_enabled = true; +#endif pc_system_flash_create(pcms); + pcms->pcspk = isa_new(TYPE_PC_SPEAKER); + object_property_add_alias(OBJECT(pcms), "pcspk-audiodev", + OBJECT(pcms->pcspk), "audiodev"); } static void pc_machine_reset(MachineState *machine) @@ -1939,6 +1672,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) pcmc->acpi_data_size = 0x20000 + 0x8000; pcmc->linuxboot_dma_enabled = true; pcmc->pvh_enabled = true; + pcmc->kvmclock_create_always = true; assert(!mc->get_hotplug_handler); mc->get_hotplug_handler = pc_get_hotplug_handler; mc->hotplug_allowed = pc_hotplug_allowed; @@ -1946,9 +1680,9 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) mc->get_default_cpu_node_id = x86_get_default_cpu_node_id; mc->possible_cpu_arch_ids = x86_possible_cpu_arch_ids; mc->auto_enable_numa_with_memhp = true; + mc->auto_enable_numa_with_memdev = true; mc->has_hotpluggable_cpus = true; mc->default_boot_order = "cad"; - mc->hot_add_cpu = pc_hot_add_cpu; mc->smp_parse = pc_smp_parse; mc->block_default_type = IF_IDE; mc->max_cpus = 255; @@ -1960,9 +1694,14 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) hc->unplug = pc_machine_device_unplug_cb; mc->default_cpu_type = TARGET_DEFAULT_CPU_TYPE; mc->nvdimm_supported = true; - mc->numa_mem_supported = true; mc->default_ram_id = "pc.ram"; + object_class_property_add(oc, PC_MACHINE_MAX_RAM_BELOW_4G, "size", + pc_machine_get_max_ram_below_4g, pc_machine_set_max_ram_below_4g, + NULL, NULL); + object_class_property_set_description(oc, PC_MACHINE_MAX_RAM_BELOW_4G, + "Maximum ram below the 4G boundary (32bit boundary)"); + object_class_property_add(oc, PC_MACHINE_DEVMEM_REGION_SIZE, "int", pc_machine_get_device_memory_region_size, NULL, NULL, NULL); @@ -1981,6 +1720,9 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) object_class_property_add_bool(oc, PC_MACHINE_PIT, pc_machine_get_pit, pc_machine_set_pit); + + object_class_property_add_bool(oc, "hpet", + pc_machine_get_hpet, pc_machine_set_hpet); } static const TypeInfo pc_machine_info = { diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index f66e1d73ce0bfcef379e7019a730196f589e1121..13d1628f13bfc537cbefaec47e276f270f73771e 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -23,7 +23,7 @@ */ #include "qemu/osdep.h" -#include "config-devices.h" +#include CONFIG_DEVICES #include "qemu/units.h" #include "hw/loader.h" @@ -46,13 +46,14 @@ #include "hw/sysbus.h" #include "sysemu/arch_init.h" #include "hw/i2c/smbus_eeprom.h" -#include "hw/xen/xen.h" +#include "hw/xen/xen-x86.h" #include "exec/memory.h" #include "exec/address-spaces.h" #include "hw/acpi/acpi.h" #include "cpu.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "sysemu/xen.h" #ifdef CONFIG_XEN #include #include "hw/xen/xen_pt.h" @@ -60,6 +61,7 @@ #include "migration/global_state.h" #include "migration/misc.h" #include "sysemu/numa.h" +#include "hw/hyperv/vmbus-bridge.h" #include "hw/mem/nvdimm.h" #include "hw/i386/acpi-build.h" @@ -115,8 +117,8 @@ static void pc_init1(MachineState *machine, * so legacy non-PAE guests can get as much memory as possible in * the 32bit address space below 4G. * - * - Note that Xen has its own ram setp code in xen_ram_init(), - * called via xen_hvm_init(). + * - Note that Xen has its own ram setup code in xen_ram_init(), + * called via xen_hvm_init_pc(). * * Examples: * qemu -M pc-1.7 -m 4G (old default) -> 3584M low, 512M high @@ -125,13 +127,13 @@ static void pc_init1(MachineState *machine, * qemu -M pc,max-ram-below-4g=4G -m 3968M -> 3968M low (=4G-128M) */ if (xen_enabled()) { - xen_hvm_init(pcms, &ram_memory); + xen_hvm_init_pc(pcms, &ram_memory); } else { - if (!x86ms->max_ram_below_4g) { - x86ms->max_ram_below_4g = 0xe0000000; /* default: 3.5G */ + if (!pcms->max_ram_below_4g) { + pcms->max_ram_below_4g = 0xe0000000; /* default: 3.5G */ } - lowmem = x86ms->max_ram_below_4g; - if (machine->ram_size >= x86ms->max_ram_below_4g) { + lowmem = pcms->max_ram_below_4g; + if (machine->ram_size >= pcms->max_ram_below_4g) { if (pcmc->gigabyte_align) { if (lowmem > 0xc0000000) { lowmem = 0xc0000000; @@ -140,7 +142,7 @@ static void pc_init1(MachineState *machine, warn_report("Large machine and max_ram_below_4g " "(%" PRIu64 ") not a multiple of 1G; " "possible bad performance.", - x86ms->max_ram_below_4g); + pcms->max_ram_below_4g); } } } @@ -156,8 +158,8 @@ static void pc_init1(MachineState *machine, x86_cpus_init(x86ms, pcmc->default_cpu_version); - if (kvm_enabled() && pcmc->kvmclock_enabled) { - kvmclock_create(); + if (pcmc->kvmclock_enabled) { + kvmclock_create(pcmc->kvmclock_create_always); } if (pcmc->pci_enabled) { @@ -184,9 +186,12 @@ static void pc_init1(MachineState *machine, if (!xen_enabled()) { pc_memory_init(pcms, system_memory, rom_memory, &ram_memory); - } else if (machine->kernel_filename != NULL) { - /* For xen HVM direct kernel boot, load linux here */ - xen_load_linux(pcms); + } else { + pc_system_flash_cleanup_unused(pcms); + if (machine->kernel_filename != NULL) { + /* For xen HVM direct kernel boot, load linux here */ + xen_load_linux(pcms); + } } gsi_state = pc_gsi_create(&x86ms->gsi, pcmc->pci_enabled); @@ -211,7 +216,7 @@ static void pc_init1(MachineState *machine, i440fx_state = NULL; isa_bus = isa_bus_new(NULL, get_system_memory(), system_io, &error_abort); - no_hpet = 1; + pcms->hpet_enabled = false; } isa_bus_irqs(isa_bus, x86ms->gsi); @@ -233,8 +238,7 @@ static void pc_init1(MachineState *machine, } /* init basic PC hardware */ - pc_basic_device_init(isa_bus, x86ms->gsi, &rtc_state, true, - (pcms->vmport != ON_OFF_AUTO_ON), pcms->pit_enabled, + pc_basic_device_init(pcms, isa_bus, x86ms->gsi, &rtc_state, true, 0x4); pc_nic_init(pcmc, isa_bus, pci_bus); @@ -289,11 +293,11 @@ static void pc_init1(MachineState *machine, object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP, TYPE_HOTPLUG_HANDLER, - (Object **)&pcms->acpi_dev, + (Object **)&x86ms->acpi_dev, object_property_allow_set_link, OBJ_PROP_LINK_STRONG); - object_property_set_link(OBJECT(machine), OBJECT(piix4_pm), - PC_MACHINE_ACPI_DEVICE_PROP, &error_abort); + object_property_set_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP, + OBJECT(piix4_pm), &error_abort); } if (machine->nvdimms_state->is_enabled) { @@ -375,7 +379,7 @@ static void pc_init_isa(MachineState *machine) #ifdef CONFIG_XEN static void pc_xen_hvm_init_pci(MachineState *machine) { - const char *pci_type = has_igd_gfx_passthru ? + const char *pci_type = xen_igd_gfx_pt_enabled() ? TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE : TYPE_I440FX_PCI_DEVICE; pc_init1(machine, @@ -419,9 +423,10 @@ static void pc_i440fx_machine_options(MachineClass *m) m->default_machine_opts = "firmware=bios-256k.bin"; m->default_display = "std"; machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE); + machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE); } -static void pc_i440fx_5_1_machine_options(MachineClass *m) +static void pc_i440fx_5_2_machine_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_i440fx_machine_options(m); @@ -430,6 +435,21 @@ static void pc_i440fx_5_1_machine_options(MachineClass *m) pcmc->default_cpu_version = 1; } +DEFINE_I440FX_MACHINE(v5_2, "pc-i440fx-5.2", NULL, + pc_i440fx_5_2_machine_options); + +static void pc_i440fx_5_1_machine_options(MachineClass *m) +{ + PCMachineClass *pcmc = PC_MACHINE_CLASS(m); + + pc_i440fx_5_2_machine_options(m); + m->alias = NULL; + m->is_default = false; + compat_props_add(m->compat_props, hw_compat_5_1, hw_compat_5_1_len); + compat_props_add(m->compat_props, pc_compat_5_1, pc_compat_5_1_len); + pcmc->kvmclock_create_always = false; +} + DEFINE_I440FX_MACHINE(v5_1, "pc-i440fx-5.1", NULL, pc_i440fx_5_1_machine_options); @@ -438,8 +458,10 @@ static void pc_i440fx_5_0_machine_options(MachineClass *m) pc_i440fx_5_1_machine_options(m); m->alias = NULL; m->is_default = false; + m->numa_mem_supported = true; compat_props_add(m->compat_props, hw_compat_5_0, hw_compat_5_0_len); compat_props_add(m->compat_props, pc_compat_5_0, pc_compat_5_0_len); + m->auto_enable_numa_with_memdev = false; } DEFINE_I440FX_MACHINE(v5_0, "pc-i440fx-5.0", NULL, @@ -546,7 +568,6 @@ static void pc_i440fx_2_9_machine_options(MachineClass *m) pc_i440fx_2_10_machine_options(m); compat_props_add(m->compat_props, hw_compat_2_9, hw_compat_2_9_len); compat_props_add(m->compat_props, pc_compat_2_9, pc_compat_2_9_len); - m->numa_auto_assign_ram = numa_legacy_auto_assign_ram; } DEFINE_I440FX_MACHINE(v2_9, "pc-i440fx-2.9", NULL, @@ -733,7 +754,6 @@ static void pc_i440fx_1_4_machine_options(MachineClass *m) { pc_i440fx_1_5_machine_options(m); m->hw_version = "1.4.0"; - m->hot_add_cpu = NULL; compat_props_add(m->compat_props, pc_compat_1_4, pc_compat_1_4_len); } @@ -911,7 +931,7 @@ void igd_passthrough_isa_bridge_create(PCIBus *bus, uint16_t gpu_dev_id) struct PCIDevice *bridge_dev; int i, num; uint16_t pch_dev_id = 0xffff; - uint8_t pch_rev_id; + uint8_t pch_rev_id = 0; num = ARRAY_SIZE(igd_combo_id_infos); for (i = 0; i < num; i++) { @@ -967,7 +987,7 @@ static void xenfv_4_2_machine_options(MachineClass *m) pc_i440fx_4_2_machine_options(m); m->desc = "Xen Fully-virtualized PC"; m->max_cpus = HVM_MAX_VCPUS; - m->default_machine_opts = "accel=xen"; + m->default_machine_opts = "accel=xen,suppress-vmdesc=on"; } DEFINE_PC_MACHINE(xenfv_4_2, "xenfv-4.2", pc_xen_hvm_init, @@ -979,7 +999,7 @@ static void xenfv_3_1_machine_options(MachineClass *m) m->desc = "Xen Fully-virtualized PC"; m->alias = "xenfv"; m->max_cpus = HVM_MAX_VCPUS; - m->default_machine_opts = "accel=xen"; + m->default_machine_opts = "accel=xen,suppress-vmdesc=on"; } DEFINE_PC_MACHINE(xenfv, "xenfv-3.1", pc_xen_hvm_init, diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 4ba8ac8774e474850a82ffe3e8b5771c9c4599b0..a3f4959c43575ad9809a0ac8b7a596169a95b2fc 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -34,7 +34,6 @@ #include "sysemu/arch_init.h" #include "hw/i2c/smbus_eeprom.h" #include "hw/rtc/mc146818rtc.h" -#include "hw/xen/xen.h" #include "sysemu/kvm.h" #include "hw/kvm/clock.h" #include "hw/pci-host/q35.h" @@ -53,6 +52,7 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "sysemu/numa.h" +#include "hw/hyperv/vmbus-bridge.h" #include "hw/mem/nvdimm.h" #include "hw/i386/acpi-build.h" @@ -98,16 +98,16 @@ static int ehci_create_ich9_with_companions(PCIBus *bus, int slot) return -1; } - ehci = pci_create_multifunction(bus, PCI_DEVFN(slot, 7), true, name); - qdev_init_nofail(&ehci->qdev); + ehci = pci_new_multifunction(PCI_DEVFN(slot, 7), true, name); + pci_realize_and_unref(ehci, bus, &error_fatal); usbbus = QLIST_FIRST(&ehci->qdev.child_bus); for (i = 0; i < 3; i++) { - uhci = pci_create_multifunction(bus, PCI_DEVFN(slot, comp[i].func), - true, comp[i].name); + uhci = pci_new_multifunction(PCI_DEVFN(slot, comp[i].func), true, + comp[i].name); qdev_prop_set_string(&uhci->qdev, "masterbus", usbbus->name); qdev_prop_set_uint32(&uhci->qdev, "firstport", comp[i].port); - qdev_init_nofail(&uhci->qdev); + pci_realize_and_unref(uhci, bus, &error_fatal); } return 0; } @@ -154,18 +154,18 @@ static void pc_q35_init(MachineState *machine) /* Handle the machine opt max-ram-below-4g. It is basically doing * min(qemu limit, user limit). */ - if (!x86ms->max_ram_below_4g) { - x86ms->max_ram_below_4g = 4 * GiB; + if (!pcms->max_ram_below_4g) { + pcms->max_ram_below_4g = 4 * GiB; } - if (lowmem > x86ms->max_ram_below_4g) { - lowmem = x86ms->max_ram_below_4g; + if (lowmem > pcms->max_ram_below_4g) { + lowmem = pcms->max_ram_below_4g; if (machine->ram_size - lowmem > lowmem && lowmem & (1 * GiB - 1)) { warn_report("There is possibly poor performance as the ram size " " (0x%" PRIx64 ") is more then twice the size of" " max-ram-below-4g (%"PRIu64") and" " max-ram-below-4g is not a multiple of 1G.", - (uint64_t)machine->ram_size, x86ms->max_ram_below_4g); + (uint64_t)machine->ram_size, pcms->max_ram_below_4g); } } @@ -177,13 +177,9 @@ static void pc_q35_init(MachineState *machine) x86ms->below_4g_mem_size = machine->ram_size; } - if (xen_enabled()) { - xen_hvm_init(pcms, &ram_memory); - } - x86_cpus_init(x86ms, pcmc->default_cpu_version); - kvmclock_create(); + kvmclock_create(pcmc->kvmclock_create_always); /* pci enabled */ if (pcmc->pci_enabled) { @@ -206,29 +202,26 @@ static void pc_q35_init(MachineState *machine) } /* allocate ram and load rom/bios */ - if (!xen_enabled()) { - pc_memory_init(pcms, get_system_memory(), - rom_memory, &ram_memory); - } + pc_memory_init(pcms, get_system_memory(), rom_memory, &ram_memory); /* create pci host bus */ - q35_host = Q35_HOST_DEVICE(qdev_create(NULL, TYPE_Q35_HOST_DEVICE)); + q35_host = Q35_HOST_DEVICE(qdev_new(TYPE_Q35_HOST_DEVICE)); object_property_add_child(qdev_get_machine(), "q35", OBJECT(q35_host)); - object_property_set_link(OBJECT(q35_host), OBJECT(ram_memory), - MCH_HOST_PROP_RAM_MEM, NULL); - object_property_set_link(OBJECT(q35_host), OBJECT(pci_memory), - MCH_HOST_PROP_PCI_MEM, NULL); - object_property_set_link(OBJECT(q35_host), OBJECT(get_system_memory()), - MCH_HOST_PROP_SYSTEM_MEM, NULL); - object_property_set_link(OBJECT(q35_host), OBJECT(system_io), - MCH_HOST_PROP_IO_MEM, NULL); - object_property_set_int(OBJECT(q35_host), x86ms->below_4g_mem_size, - PCI_HOST_BELOW_4G_MEM_SIZE, NULL); - object_property_set_int(OBJECT(q35_host), x86ms->above_4g_mem_size, - PCI_HOST_ABOVE_4G_MEM_SIZE, NULL); + object_property_set_link(OBJECT(q35_host), MCH_HOST_PROP_RAM_MEM, + OBJECT(ram_memory), NULL); + object_property_set_link(OBJECT(q35_host), MCH_HOST_PROP_PCI_MEM, + OBJECT(pci_memory), NULL); + object_property_set_link(OBJECT(q35_host), MCH_HOST_PROP_SYSTEM_MEM, + OBJECT(get_system_memory()), NULL); + object_property_set_link(OBJECT(q35_host), MCH_HOST_PROP_IO_MEM, + OBJECT(system_io), NULL); + object_property_set_int(OBJECT(q35_host), PCI_HOST_BELOW_4G_MEM_SIZE, + x86ms->below_4g_mem_size, NULL); + object_property_set_int(OBJECT(q35_host), PCI_HOST_ABOVE_4G_MEM_SIZE, + x86ms->above_4g_mem_size, NULL); /* pci */ - qdev_init_nofail(DEVICE(q35_host)); + sysbus_realize_and_unref(SYS_BUS_DEVICE(q35_host), &error_fatal); phb = PCI_HOST_BRIDGE(q35_host); host_bus = phb->bus; /* create ISA bus */ @@ -238,11 +231,11 @@ static void pc_q35_init(MachineState *machine) object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP, TYPE_HOTPLUG_HANDLER, - (Object **)&pcms->acpi_dev, + (Object **)&x86ms->acpi_dev, object_property_allow_set_link, OBJ_PROP_LINK_STRONG); - object_property_set_link(OBJECT(machine), OBJECT(lpc), - PC_MACHINE_ACPI_DEVICE_PROP, &error_abort); + object_property_set_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP, + OBJECT(lpc), &error_abort); /* irq lines */ gsi_state = pc_gsi_create(&x86ms->gsi, pcmc->pci_enabled); @@ -269,12 +262,11 @@ static void pc_q35_init(MachineState *machine) assert(pcms->vmport != ON_OFF_AUTO__MAX); if (pcms->vmport == ON_OFF_AUTO_AUTO) { - pcms->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON; + pcms->vmport = ON_OFF_AUTO_ON; } /* init basic PC hardware */ - pc_basic_device_init(isa_bus, x86ms->gsi, &rtc_state, !mc->no_floppy, - (pcms->vmport != ON_OFF_AUTO_ON), pcms->pit_enabled, + pc_basic_device_init(pcms, isa_bus, x86ms->gsi, &rtc_state, !mc->no_floppy, 0xff0104); /* connect pm stuff to lpc */ @@ -348,10 +340,11 @@ static void pc_q35_machine_options(MachineClass *m) machine_class_allow_dynamic_sysbus_dev(m, TYPE_AMD_IOMMU_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_INTEL_IOMMU_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE); + machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE); m->max_cpus = 288; } -static void pc_q35_5_1_machine_options(MachineClass *m) +static void pc_q35_5_2_machine_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_q35_machine_options(m); @@ -359,6 +352,20 @@ static void pc_q35_5_1_machine_options(MachineClass *m) pcmc->default_cpu_version = 1; } +DEFINE_Q35_MACHINE(v5_2, "pc-q35-5.2", NULL, + pc_q35_5_2_machine_options); + +static void pc_q35_5_1_machine_options(MachineClass *m) +{ + PCMachineClass *pcmc = PC_MACHINE_CLASS(m); + + pc_q35_5_2_machine_options(m); + m->alias = NULL; + compat_props_add(m->compat_props, hw_compat_5_1, hw_compat_5_1_len); + compat_props_add(m->compat_props, pc_compat_5_1, pc_compat_5_1_len); + pcmc->kvmclock_create_always = false; +} + DEFINE_Q35_MACHINE(v5_1, "pc-q35-5.1", NULL, pc_q35_5_1_machine_options); @@ -366,8 +373,10 @@ static void pc_q35_5_0_machine_options(MachineClass *m) { pc_q35_5_1_machine_options(m); m->alias = NULL; + m->numa_mem_supported = true; compat_props_add(m->compat_props, hw_compat_5_0, hw_compat_5_0_len); compat_props_add(m->compat_props, pc_compat_5_0, pc_compat_5_0_len); + m->auto_enable_numa_with_memdev = false; } DEFINE_Q35_MACHINE(v5_0, "pc-q35-5.0", NULL, @@ -479,7 +488,6 @@ static void pc_q35_2_10_machine_options(MachineClass *m) pc_q35_2_11_machine_options(m); compat_props_add(m->compat_props, hw_compat_2_10, hw_compat_2_10_len); compat_props_add(m->compat_props, pc_compat_2_10, pc_compat_2_10_len); - m->numa_auto_assign_ram = numa_legacy_auto_assign_ram; m->auto_enable_numa_with_memhp = false; } diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c index b8d8ef59eb17c6ace8194fc69c3d27809becfbc0..b6c0822fe3246a2c62d7999d5ac9a1de2943bc01 100644 --- a/hw/i386/pc_sysfw.c +++ b/hw/i386/pc_sysfw.c @@ -85,7 +85,7 @@ static PFlashCFI01 *pc_pflash_create(PCMachineState *pcms, const char *name, const char *alias_prop_name) { - DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01); + DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01); qdev_prop_set_uint64(dev, "sector-length", FLASH_SECTOR_SIZE); qdev_prop_set_uint8(dev, "width", 1); @@ -93,6 +93,11 @@ static PFlashCFI01 *pc_pflash_create(PCMachineState *pcms, object_property_add_child(OBJECT(pcms), name, OBJECT(dev)); object_property_add_alias(OBJECT(pcms), alias_prop_name, OBJECT(dev), "drive"); + /* + * The returned reference is tied to the child property and + * will be removed with object_unparent. + */ + object_unref(OBJECT(dev)); return PFLASH_CFI01(dev); } @@ -108,7 +113,7 @@ void pc_system_flash_create(PCMachineState *pcms) } } -static void pc_system_flash_cleanup_unused(PCMachineState *pcms) +void pc_system_flash_cleanup_unused(PCMachineState *pcms) { char *prop_name; int i; @@ -187,7 +192,7 @@ static void pc_system_flash_map(PCMachineState *pcms, total_size += size; qdev_prop_set_uint32(DEVICE(system_flash), "num-blocks", size / FLASH_SECTOR_SIZE); - qdev_init_nofail(DEVICE(system_flash)); + sysbus_realize_and_unref(SYS_BUS_DEVICE(system_flash), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(system_flash), 0, 0x100000000ULL - total_size); diff --git a/hw/i386/port92.c b/hw/i386/port92.c index 19866c44efa064d4d29148072cd05312f2dfb450..e1379a4f98001ea5ce741a7ba10ff5c02a057ed7 100644 --- a/hw/i386/port92.c +++ b/hw/i386/port92.c @@ -12,16 +12,17 @@ #include "hw/irq.h" #include "hw/i386/pc.h" #include "trace.h" +#include "qom/object.h" -#define PORT92(obj) OBJECT_CHECK(Port92State, (obj), TYPE_PORT92) +OBJECT_DECLARE_SIMPLE_TYPE(Port92State, PORT92) -typedef struct Port92State { +struct Port92State { ISADevice parent_obj; MemoryRegion io; uint8_t outport; qemu_irq a20_out; -} Port92State; +}; static void port92_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) diff --git a/hw/i386/trace.h b/hw/i386/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..37a9f67e5de11ecf1360d4316d7e1ad9a46177a8 --- /dev/null +++ b/hw/i386/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_i386.h" diff --git a/hw/i386/vmmouse.c b/hw/i386/vmmouse.c index b3aef4132700f4b9f8dacb1415bbd7ea60f5375d..a3556438f0ff67db25a4f278c54c0aa687ebf100 100644 --- a/hw/i386/vmmouse.c +++ b/hw/i386/vmmouse.c @@ -25,21 +25,16 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "ui/console.h" +#include "hw/i386/vmport.h" #include "hw/input/i8042.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" -#include "vmport.h" #include "cpu.h" +#include "qom/object.h" /* debug only vmmouse */ //#define DEBUG_VMMOUSE -/* VMMouse Commands */ -#define VMMOUSE_GETVERSION 10 -#define VMMOUSE_DATA 39 -#define VMMOUSE_STATUS 40 -#define VMMOUSE_COMMAND 41 - #define VMMOUSE_READ_ID 0x45414552 #define VMMOUSE_DISABLE 0x000000f5 #define VMMOUSE_REQUEST_RELATIVE 0x4c455252 @@ -56,10 +51,9 @@ #endif #define TYPE_VMMOUSE "vmmouse" -#define VMMOUSE(obj) OBJECT_CHECK(VMMouseState, (obj), TYPE_VMMOUSE) +OBJECT_DECLARE_SIMPLE_TYPE(VMMouseState, VMMOUSE) -typedef struct VMMouseState -{ +struct VMMouseState { ISADevice parent_obj; uint32_t queue[VMMOUSE_QUEUE_SIZE]; @@ -69,7 +63,7 @@ typedef struct VMMouseState uint8_t absolute; QEMUPutMouseEntry *entry; ISAKBDState *i8042; -} VMMouseState; +}; static void vmmouse_get_data(uint32_t *data) { @@ -217,10 +211,10 @@ static uint32_t vmmouse_ioport_read(void *opaque, uint32_t addr) command = data[2] & 0xFFFF; switch (command) { - case VMMOUSE_STATUS: + case VMPORT_CMD_VMMOUSE_STATUS: data[0] = vmmouse_get_status(s); break; - case VMMOUSE_COMMAND: + case VMPORT_CMD_VMMOUSE_COMMAND: switch (data[1]) { case VMMOUSE_DISABLE: vmmouse_disable(s); @@ -239,7 +233,7 @@ static uint32_t vmmouse_ioport_read(void *opaque, uint32_t addr) break; } break; - case VMMOUSE_DATA: + case VMPORT_CMD_VMMOUSE_DATA: vmmouse_data(s, data, data[1]); break; default: @@ -296,9 +290,9 @@ static void vmmouse_realizefn(DeviceState *dev, Error **errp) return; } - vmport_register(VMMOUSE_STATUS, vmmouse_ioport_read, s); - vmport_register(VMMOUSE_COMMAND, vmmouse_ioport_read, s); - vmport_register(VMMOUSE_DATA, vmmouse_ioport_read, s); + vmport_register(VMPORT_CMD_VMMOUSE_STATUS, vmmouse_ioport_read, s); + vmport_register(VMPORT_CMD_VMMOUSE_COMMAND, vmmouse_ioport_read, s); + vmport_register(VMPORT_CMD_VMMOUSE_DATA, vmmouse_ioport_read, s); } static Property vmmouse_properties[] = { diff --git a/hw/i386/vmport.c b/hw/i386/vmport.c index 1aaaab691a4ecabeb12e2f86d13cd313696da397..20d605506bac948c40e6214320d3b8be90bd6da1 100644 --- a/hw/i386/vmport.c +++ b/hw/i386/vmport.c @@ -21,37 +21,69 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + +/* + * Guest code that interacts with this virtual device can be found + * in VMware open-vm-tools open-source project: + * https://github.com/vmware/open-vm-tools + */ + #include "qemu/osdep.h" #include "hw/isa/isa.h" +#include "hw/i386/vmport.h" +#include "hw/qdev-properties.h" +#include "sysemu/sysemu.h" #include "sysemu/hw_accel.h" +#include "sysemu/qtest.h" #include "qemu/log.h" -#include "vmport.h" #include "cpu.h" #include "trace.h" +#include "qom/object.h" -#define VMPORT_CMD_GETVERSION 0x0a -#define VMPORT_CMD_GETRAMSIZE 0x14 - -#define VMPORT_ENTRIES 0x2c #define VMPORT_MAGIC 0x564D5868 -#define VMPORT(obj) OBJECT_CHECK(VMPortState, (obj), TYPE_VMPORT) +/* Compatibility flags for migration */ +#define VMPORT_COMPAT_READ_SET_EAX_BIT 0 +#define VMPORT_COMPAT_SIGNAL_UNSUPPORTED_CMD_BIT 1 +#define VMPORT_COMPAT_REPORT_VMX_TYPE_BIT 2 +#define VMPORT_COMPAT_CMDS_V2_BIT 3 +#define VMPORT_COMPAT_READ_SET_EAX \ + (1 << VMPORT_COMPAT_READ_SET_EAX_BIT) +#define VMPORT_COMPAT_SIGNAL_UNSUPPORTED_CMD \ + (1 << VMPORT_COMPAT_SIGNAL_UNSUPPORTED_CMD_BIT) +#define VMPORT_COMPAT_REPORT_VMX_TYPE \ + (1 << VMPORT_COMPAT_REPORT_VMX_TYPE_BIT) +#define VMPORT_COMPAT_CMDS_V2 \ + (1 << VMPORT_COMPAT_CMDS_V2_BIT) + +/* vCPU features reported by CMD_GET_VCPU_INFO */ +#define VCPU_INFO_SLC64_BIT 0 +#define VCPU_INFO_SYNC_VTSCS_BIT 1 +#define VCPU_INFO_HV_REPLAY_OK_BIT 2 +#define VCPU_INFO_LEGACY_X2APIC_BIT 3 +#define VCPU_INFO_RESERVED_BIT 31 + +OBJECT_DECLARE_SIMPLE_TYPE(VMPortState, VMPORT) -typedef struct VMPortState { +struct VMPortState { ISADevice parent_obj; MemoryRegion io; VMPortReadFunc *func[VMPORT_ENTRIES]; void *opaque[VMPORT_ENTRIES]; -} VMPortState; + + uint32_t vmware_vmx_version; + uint8_t vmware_vmx_type; + + uint32_t compat_flags; +}; static VMPortState *port_state; -void vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque) +void vmport_register(VMPortCommand command, VMPortReadFunc *func, void *opaque) { - if (command >= VMPORT_ENTRIES) { - return; - } + assert(command < VMPORT_ENTRIES); + assert(port_state); trace_vmport_register(command, func, opaque); port_state->func[command] = func; @@ -64,25 +96,51 @@ static uint64_t vmport_ioport_read(void *opaque, hwaddr addr, VMPortState *s = opaque; CPUState *cs = current_cpu; X86CPU *cpu = X86_CPU(cs); - CPUX86State *env = &cpu->env; + CPUX86State *env; unsigned char command; uint32_t eax; + if (qtest_enabled()) { + return -1; + } + env = &cpu->env; cpu_synchronize_state(cs); eax = env->regs[R_EAX]; if (eax != VMPORT_MAGIC) { - return eax; + goto err; } command = env->regs[R_ECX]; trace_vmport_command(command); if (command >= VMPORT_ENTRIES || !s->func[command]) { qemu_log_mask(LOG_UNIMP, "vmport: unknown command %x\n", command); - return eax; + goto err; } - return s->func[command](s->opaque[command], addr); + eax = s->func[command](s->opaque[command], addr); + goto out; + +err: + if (s->compat_flags & VMPORT_COMPAT_SIGNAL_UNSUPPORTED_CMD) { + eax = UINT32_MAX; + } + +out: + /* + * The call above to cpu_synchronize_state() gets vCPU registers values + * to QEMU but also cause QEMU to write QEMU vCPU registers values to + * vCPU implementation (e.g. Accelerator such as KVM) just before + * resuming guest. + * + * Therefore, in order to make IOPort return value propagate to + * guest EAX, we need to explicitly update QEMU EAX register value. + */ + if (s->compat_flags & VMPORT_COMPAT_READ_SET_EAX) { + cpu->env.regs[R_EAX] = eax; + } + + return eax; } static void vmport_ioport_write(void *opaque, hwaddr addr, @@ -90,6 +148,9 @@ static void vmport_ioport_write(void *opaque, hwaddr addr, { X86CPU *cpu = X86_CPU(current_cpu); + if (qtest_enabled()) { + return; + } cpu->env.regs[R_EAX] = vmport_ioport_read(opaque, addr, 4); } @@ -97,18 +158,69 @@ static uint32_t vmport_cmd_get_version(void *opaque, uint32_t addr) { X86CPU *cpu = X86_CPU(current_cpu); + if (qtest_enabled()) { + return -1; + } cpu->env.regs[R_EBX] = VMPORT_MAGIC; - return 6; + if (port_state->compat_flags & VMPORT_COMPAT_REPORT_VMX_TYPE) { + cpu->env.regs[R_ECX] = port_state->vmware_vmx_type; + } + return port_state->vmware_vmx_version; +} + +static uint32_t vmport_cmd_get_bios_uuid(void *opaque, uint32_t addr) +{ + X86CPU *cpu = X86_CPU(current_cpu); + uint32_t *uuid_parts = (uint32_t *)(qemu_uuid.data); + + cpu->env.regs[R_EAX] = le32_to_cpu(uuid_parts[0]); + cpu->env.regs[R_EBX] = le32_to_cpu(uuid_parts[1]); + cpu->env.regs[R_ECX] = le32_to_cpu(uuid_parts[2]); + cpu->env.regs[R_EDX] = le32_to_cpu(uuid_parts[3]); + return cpu->env.regs[R_EAX]; } static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr) { X86CPU *cpu = X86_CPU(current_cpu); + if (qtest_enabled()) { + return -1; + } cpu->env.regs[R_EBX] = 0x1177; return ram_size; } +static uint32_t vmport_cmd_get_hz(void *opaque, uint32_t addr) +{ + X86CPU *cpu = X86_CPU(current_cpu); + + if (cpu->env.tsc_khz && cpu->env.apic_bus_freq) { + uint64_t tsc_freq = (uint64_t)cpu->env.tsc_khz * 1000; + + cpu->env.regs[R_ECX] = cpu->env.apic_bus_freq; + cpu->env.regs[R_EBX] = (uint32_t)(tsc_freq >> 32); + cpu->env.regs[R_EAX] = (uint32_t)tsc_freq; + } else { + /* Signal cmd as not supported */ + cpu->env.regs[R_EBX] = UINT32_MAX; + } + + return cpu->env.regs[R_EAX]; +} + +static uint32_t vmport_cmd_get_vcpu_info(void *opaque, uint32_t addr) +{ + X86CPU *cpu = X86_CPU(current_cpu); + uint32_t ret = 0; + + if (cpu->env.features[FEAT_1_ECX] & CPUID_EXT_X2APIC) { + ret |= 1 << VCPU_INFO_LEGACY_X2APIC_BIT; + } + + return ret; +} + static const MemoryRegionOps vmport_ops = { .read = vmport_ioport_read, .write = vmport_ioport_write, @@ -128,11 +240,54 @@ static void vmport_realizefn(DeviceState *dev, Error **errp) isa_register_ioport(isadev, &s->io, 0x5658); port_state = s; + /* Register some generic port commands */ vmport_register(VMPORT_CMD_GETVERSION, vmport_cmd_get_version, NULL); vmport_register(VMPORT_CMD_GETRAMSIZE, vmport_cmd_ram_size, NULL); + if (s->compat_flags & VMPORT_COMPAT_CMDS_V2) { + vmport_register(VMPORT_CMD_GETBIOSUUID, vmport_cmd_get_bios_uuid, NULL); + vmport_register(VMPORT_CMD_GETHZ, vmport_cmd_get_hz, NULL); + vmport_register(VMPORT_CMD_GET_VCPU_INFO, vmport_cmd_get_vcpu_info, + NULL); + } } +static Property vmport_properties[] = { + /* Used to enforce compatibility for migration */ + DEFINE_PROP_BIT("x-read-set-eax", VMPortState, compat_flags, + VMPORT_COMPAT_READ_SET_EAX_BIT, true), + DEFINE_PROP_BIT("x-signal-unsupported-cmd", VMPortState, compat_flags, + VMPORT_COMPAT_SIGNAL_UNSUPPORTED_CMD_BIT, true), + DEFINE_PROP_BIT("x-report-vmx-type", VMPortState, compat_flags, + VMPORT_COMPAT_REPORT_VMX_TYPE_BIT, true), + DEFINE_PROP_BIT("x-cmds-v2", VMPortState, compat_flags, + VMPORT_COMPAT_CMDS_V2_BIT, true), + + /* Default value taken from open-vm-tools code VERSION_MAGIC definition */ + DEFINE_PROP_UINT32("vmware-vmx-version", VMPortState, + vmware_vmx_version, 6), + /* + * Value determines which VMware product type host report itself to guest. + * + * Most guests are fine with exposing host as VMware ESX server. + * Some legacy/proprietary guests hard-code a given type. + * + * For a complete list of values, refer to enum VMXType at open-vm-tools + * project (Defined at lib/include/vm_vmx_type.h). + * + * Reasonable options: + * 0 - Unset + * 1 - VMware Express (deprecated) + * 2 - VMware ESX Server + * 3 - VMware Server (Deprecated) + * 4 - VMware Workstation + * 5 - ACE 1.x (Deprecated) + */ + DEFINE_PROP_UINT8("vmware-vmx-type", VMPortState, vmware_vmx_type, 2), + + DEFINE_PROP_END_OF_LIST(), +}; + static void vmport_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -140,6 +295,7 @@ static void vmport_class_initfn(ObjectClass *klass, void *data) dc->realize = vmport_realizefn; /* Reason: realize sets global port_state */ dc->user_creatable = false; + device_class_set_props(dc, vmport_properties); } static const TypeInfo vmport_info = { diff --git a/hw/i386/x86-iommu.c b/hw/i386/x86-iommu.c index 4104060e6881499beadfb39b15e5301dd5260566..5f4301639c5bfcfc5ae01a666784486ca7af8a13 100644 --- a/hw/i386/x86-iommu.c +++ b/hw/i386/x86-iommu.c @@ -107,7 +107,7 @@ IommuType x86_iommu_get_type(void) static void x86_iommu_realize(DeviceState *dev, Error **errp) { X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(dev); - X86IOMMUClass *x86_class = X86_IOMMU_GET_CLASS(dev); + X86IOMMUClass *x86_class = X86_IOMMU_DEVICE_GET_CLASS(dev); MachineState *ms = MACHINE(qdev_get_machine()); MachineClass *mc = MACHINE_GET_CLASS(ms); PCMachineState *pcms = diff --git a/hw/i386/x86.c b/hw/i386/x86.c index 7a3bc7ab6639fd05037b12cdc50fece3476123b2..5944fc44edca8aba1426fa107f4de1871d982aad 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -34,6 +34,7 @@ #include "sysemu/numa.h" #include "sysemu/replay.h" #include "sysemu/sysemu.h" +#include "sysemu/cpu-timers.h" #include "trace.h" #include "hw/i386/x86.h" @@ -41,6 +42,7 @@ #include "hw/i386/topology.h" #include "hw/i386/fw_cfg.h" #include "hw/intc/i8259.h" +#include "hw/rtc/mc146818rtc.h" #include "hw/acpi/cpu_hotplug.h" #include "hw/irq.h" @@ -49,7 +51,7 @@ #include "multiboot.h" #include "elf.h" #include "standard-headers/asm-x86/bootparam.h" -#include "config-devices.h" +#include CONFIG_DEVICES #include "kvm_i386.h" #define BIOS_FILENAME "bios.bin" @@ -62,28 +64,11 @@ inline void init_topo_info(X86CPUTopoInfo *topo_info, { MachineState *ms = MACHINE(x86ms); - topo_info->nodes_per_pkg = ms->numa_state->num_nodes / ms->smp.sockets; topo_info->dies_per_pkg = x86ms->smp_dies; topo_info->cores_per_die = ms->smp.cores; topo_info->threads_per_core = ms->smp.threads; } -/* - * Set up with the new EPYC topology handlers - * - * AMD uses different apic id encoding for EPYC based cpus. Override - * the default topo handlers with EPYC encoding handlers. - */ -static void x86_set_epyc_topo_handlers(MachineState *machine) -{ - X86MachineState *x86ms = X86_MACHINE(machine); - - x86ms->apicid_from_cpu_idx = x86_apicid_from_cpu_idx_epyc; - x86ms->topo_ids_from_apicid = x86_topo_ids_from_apicid_epyc; - x86ms->apicid_from_topo_ids = x86_apicid_from_topo_ids_epyc; - x86ms->apicid_pkg_offset = apicid_pkg_offset_epyc; -} - /* * Calculates initial APIC ID for a specific CPU index * @@ -102,7 +87,7 @@ uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms, init_topo_info(&topo_info, x86ms); - correct_id = x86ms->apicid_from_cpu_idx(&topo_info, cpu_index); + correct_id = x86_apicid_from_cpu_idx(&topo_info, cpu_index); if (x86mc->compat_apic_id_mode) { if (cpu_index != correct_id && !warned && !qtest_enabled()) { error_report("APIC IDs set in compatibility mode, " @@ -118,16 +103,15 @@ uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms, void x86_cpu_new(X86MachineState *x86ms, int64_t apic_id, Error **errp) { - Object *cpu = NULL; - Error *local_err = NULL; + Object *cpu = object_new(MACHINE(x86ms)->cpu_type); - cpu = object_new(MACHINE(x86ms)->cpu_type); - - object_property_set_uint(cpu, apic_id, "apic-id", &local_err); - object_property_set_bool(cpu, true, "realized", &local_err); + if (!object_property_set_uint(cpu, "apic-id", apic_id, errp)) { + goto out; + } + qdev_realize(DEVICE(cpu), NULL, errp); +out: object_unref(cpu); - error_propagate(errp, local_err); } void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version) @@ -137,11 +121,6 @@ void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version) MachineState *ms = MACHINE(x86ms); MachineClass *mc = MACHINE_GET_CLASS(x86ms); - /* Check for apicid encoding */ - if (cpu_x86_use_epyc_apic_id_encoding(ms->cpu_type)) { - x86_set_epyc_topo_handlers(ms); - } - x86_cpu_set_default_version(default_cpu_version); /* @@ -155,15 +134,290 @@ void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version) x86ms->apic_id_limit = x86_cpu_apic_id_from_index(x86ms, ms->smp.max_cpus - 1) + 1; possible_cpus = mc->possible_cpu_arch_ids(ms); + for (i = 0; i < ms->smp.cpus; i++) { + x86_cpu_new(x86ms, possible_cpus->cpus[i].arch_id, &error_fatal); + } +} - for (i = 0; i < ms->possible_cpus->len; i++) { - ms->possible_cpus->cpus[i].arch_id = - x86_cpu_apic_id_from_index(x86ms, i); +void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count) +{ + if (cpus_count > 0xff) { + /* + * If the number of CPUs can't be represented in 8 bits, the + * BIOS must use "FW_CFG_NB_CPUS". Set RTC field to 0 just + * to make old BIOSes fail more predictably. + */ + rtc_set_memory(rtc, 0x5f, 0); + } else { + rtc_set_memory(rtc, 0x5f, cpus_count - 1); } +} - for (i = 0; i < ms->smp.cpus; i++) { - x86_cpu_new(x86ms, possible_cpus->cpus[i].arch_id, &error_fatal); +static int x86_apic_cmp(const void *a, const void *b) +{ + CPUArchId *apic_a = (CPUArchId *)a; + CPUArchId *apic_b = (CPUArchId *)b; + + return apic_a->arch_id - apic_b->arch_id; +} + +/* + * returns pointer to CPUArchId descriptor that matches CPU's apic_id + * in ms->possible_cpus->cpus, if ms->possible_cpus->cpus has no + * entry corresponding to CPU's apic_id returns NULL. + */ +CPUArchId *x86_find_cpu_slot(MachineState *ms, uint32_t id, int *idx) +{ + CPUArchId apic_id, *found_cpu; + + apic_id.arch_id = id; + found_cpu = bsearch(&apic_id, ms->possible_cpus->cpus, + ms->possible_cpus->len, sizeof(*ms->possible_cpus->cpus), + x86_apic_cmp); + if (found_cpu && idx) { + *idx = found_cpu - ms->possible_cpus->cpus; + } + return found_cpu; +} + +void x86_cpu_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + CPUArchId *found_cpu; + Error *local_err = NULL; + X86CPU *cpu = X86_CPU(dev); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); + + if (x86ms->acpi_dev) { + hotplug_handler_plug(x86ms->acpi_dev, dev, &local_err); + if (local_err) { + goto out; + } + } + + /* increment the number of CPUs */ + x86ms->boot_cpus++; + if (x86ms->rtc) { + x86_rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus); + } + if (x86ms->fw_cfg) { + fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus); + } + + found_cpu = x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, NULL); + found_cpu->cpu = OBJECT(dev); +out: + error_propagate(errp, local_err); +} + +void x86_cpu_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + int idx = -1; + X86CPU *cpu = X86_CPU(dev); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); + + if (!x86ms->acpi_dev) { + error_setg(errp, "CPU hot unplug not supported without ACPI"); + return; + } + + x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, &idx); + assert(idx != -1); + if (idx == 0) { + error_setg(errp, "Boot CPU is unpluggable"); + return; + } + + hotplug_handler_unplug_request(x86ms->acpi_dev, dev, + errp); +} + +void x86_cpu_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + CPUArchId *found_cpu; + Error *local_err = NULL; + X86CPU *cpu = X86_CPU(dev); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); + + hotplug_handler_unplug(x86ms->acpi_dev, dev, &local_err); + if (local_err) { + goto out; + } + + found_cpu = x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, NULL); + found_cpu->cpu = NULL; + qdev_unrealize(dev); + + /* decrement the number of CPUs */ + x86ms->boot_cpus--; + /* Update the number of CPUs in CMOS */ + x86_rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus); + fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus); + out: + error_propagate(errp, local_err); +} + +void x86_cpu_pre_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + int idx; + CPUState *cs; + CPUArchId *cpu_slot; + X86CPUTopoIDs topo_ids; + X86CPU *cpu = X86_CPU(dev); + CPUX86State *env = &cpu->env; + MachineState *ms = MACHINE(hotplug_dev); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); + unsigned int smp_cores = ms->smp.cores; + unsigned int smp_threads = ms->smp.threads; + X86CPUTopoInfo topo_info; + + if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) { + error_setg(errp, "Invalid CPU type, expected cpu type: '%s'", + ms->cpu_type); + return; + } + + if (x86ms->acpi_dev) { + Error *local_err = NULL; + + hotplug_handler_pre_plug(HOTPLUG_HANDLER(x86ms->acpi_dev), dev, + &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + } + + init_topo_info(&topo_info, x86ms); + + env->nr_dies = x86ms->smp_dies; + + /* + * If APIC ID is not set, + * set it based on socket/die/core/thread properties. + */ + if (cpu->apic_id == UNASSIGNED_APIC_ID) { + int max_socket = (ms->smp.max_cpus - 1) / + smp_threads / smp_cores / x86ms->smp_dies; + + /* + * die-id was optional in QEMU 4.0 and older, so keep it optional + * if there's only one die per socket. + */ + if (cpu->die_id < 0 && x86ms->smp_dies == 1) { + cpu->die_id = 0; + } + + if (cpu->socket_id < 0) { + error_setg(errp, "CPU socket-id is not set"); + return; + } else if (cpu->socket_id > max_socket) { + error_setg(errp, "Invalid CPU socket-id: %u must be in range 0:%u", + cpu->socket_id, max_socket); + return; + } + if (cpu->die_id < 0) { + error_setg(errp, "CPU die-id is not set"); + return; + } else if (cpu->die_id > x86ms->smp_dies - 1) { + error_setg(errp, "Invalid CPU die-id: %u must be in range 0:%u", + cpu->die_id, x86ms->smp_dies - 1); + return; + } + if (cpu->core_id < 0) { + error_setg(errp, "CPU core-id is not set"); + return; + } else if (cpu->core_id > (smp_cores - 1)) { + error_setg(errp, "Invalid CPU core-id: %u must be in range 0:%u", + cpu->core_id, smp_cores - 1); + return; + } + if (cpu->thread_id < 0) { + error_setg(errp, "CPU thread-id is not set"); + return; + } else if (cpu->thread_id > (smp_threads - 1)) { + error_setg(errp, "Invalid CPU thread-id: %u must be in range 0:%u", + cpu->thread_id, smp_threads - 1); + return; + } + + topo_ids.pkg_id = cpu->socket_id; + topo_ids.die_id = cpu->die_id; + topo_ids.core_id = cpu->core_id; + topo_ids.smt_id = cpu->thread_id; + cpu->apic_id = x86_apicid_from_topo_ids(&topo_info, &topo_ids); } + + cpu_slot = x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, &idx); + if (!cpu_slot) { + MachineState *ms = MACHINE(x86ms); + + x86_topo_ids_from_apicid(cpu->apic_id, &topo_info, &topo_ids); + error_setg(errp, + "Invalid CPU [socket: %u, die: %u, core: %u, thread: %u] with" + " APIC ID %" PRIu32 ", valid index range 0:%d", + topo_ids.pkg_id, topo_ids.die_id, topo_ids.core_id, topo_ids.smt_id, + cpu->apic_id, ms->possible_cpus->len - 1); + return; + } + + if (cpu_slot->cpu) { + error_setg(errp, "CPU[%d] with APIC ID %" PRIu32 " exists", + idx, cpu->apic_id); + return; + } + + /* if 'address' properties socket-id/core-id/thread-id are not set, set them + * so that machine_query_hotpluggable_cpus would show correct values + */ + /* TODO: move socket_id/core_id/thread_id checks into x86_cpu_realizefn() + * once -smp refactoring is complete and there will be CPU private + * CPUState::nr_cores and CPUState::nr_threads fields instead of globals */ + x86_topo_ids_from_apicid(cpu->apic_id, &topo_info, &topo_ids); + if (cpu->socket_id != -1 && cpu->socket_id != topo_ids.pkg_id) { + error_setg(errp, "property socket-id: %u doesn't match set apic-id:" + " 0x%x (socket-id: %u)", cpu->socket_id, cpu->apic_id, + topo_ids.pkg_id); + return; + } + cpu->socket_id = topo_ids.pkg_id; + + if (cpu->die_id != -1 && cpu->die_id != topo_ids.die_id) { + error_setg(errp, "property die-id: %u doesn't match set apic-id:" + " 0x%x (die-id: %u)", cpu->die_id, cpu->apic_id, topo_ids.die_id); + return; + } + cpu->die_id = topo_ids.die_id; + + if (cpu->core_id != -1 && cpu->core_id != topo_ids.core_id) { + error_setg(errp, "property core-id: %u doesn't match set apic-id:" + " 0x%x (core-id: %u)", cpu->core_id, cpu->apic_id, + topo_ids.core_id); + return; + } + cpu->core_id = topo_ids.core_id; + + if (cpu->thread_id != -1 && cpu->thread_id != topo_ids.smt_id) { + error_setg(errp, "property thread-id: %u doesn't match set apic-id:" + " 0x%x (thread-id: %u)", cpu->thread_id, cpu->apic_id, + topo_ids.smt_id); + return; + } + cpu->thread_id = topo_ids.smt_id; + + if (hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX) && + !kvm_hv_vpindex_settable()) { + error_setg(errp, "kernel doesn't allow setting HyperV VP_INDEX"); + return; + } + + cs = CPU(cpu); + cs->cpu_index = idx; + + numa_cpu_pre_plug(cpu_slot, dev, errp); } CpuInstanceProperties @@ -185,7 +439,8 @@ int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx) init_topo_info(&topo_info, x86ms); assert(idx < ms->possible_cpus->len); - x86_topo_ids_from_idx(&topo_info, idx, &topo_ids); + x86_topo_ids_from_apicid(ms->possible_cpus->cpus[idx].arch_id, + &topo_info, &topo_ids); return topo_ids.pkg_id % ms->numa_state->num_nodes; } @@ -216,7 +471,10 @@ const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms) ms->possible_cpus->cpus[i].type = ms->cpu_type; ms->possible_cpus->cpus[i].vcpus_count = 1; - x86_topo_ids_from_idx(&topo_info, i, &topo_ids); + ms->possible_cpus->cpus[i].arch_id = + x86_cpu_apic_id_from_index(x86ms, i); + x86_topo_ids_from_apicid(ms->possible_cpus->cpus[i].arch_id, + &topo_info, &topo_ids); ms->possible_cpus->cpus[i].props.has_socket_id = true; ms->possible_cpus->cpus[i].props.socket_id = topo_ids.pkg_id; if (x86ms->smp_dies > 1) { @@ -264,7 +522,7 @@ static long get_file_size(FILE *f) /* TSC handling */ uint64_t cpu_get_tsc(CPUX86State *env) { - return cpu_get_ticks(); + return cpus_get_elapsed_ticks(); } /* IRQ handling */ @@ -345,14 +603,14 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name) assert(parent_name); if (kvm_ioapic_in_kernel()) { - dev = qdev_create(NULL, TYPE_KVM_IOAPIC); + dev = qdev_new(TYPE_KVM_IOAPIC); } else { - dev = qdev_create(NULL, TYPE_IOAPIC); + dev = qdev_new(TYPE_IOAPIC); } object_property_add_child(object_resolve_path(parent_name, NULL), "ioapic", OBJECT(dev)); - qdev_init_nofail(dev); d = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(d, &error_fatal); sysbus_mmio_map(d, 0, IO_APIC_DEFAULT_ADDRESS); for (i = 0; i < IOAPIC_NUM_PINS; i++) { @@ -846,46 +1104,7 @@ void x86_bios_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw) bios); } -static void x86_machine_get_max_ram_below_4g(Object *obj, Visitor *v, - const char *name, void *opaque, - Error **errp) -{ - X86MachineState *x86ms = X86_MACHINE(obj); - uint64_t value = x86ms->max_ram_below_4g; - - visit_type_size(v, name, &value, errp); -} - -static void x86_machine_set_max_ram_below_4g(Object *obj, Visitor *v, - const char *name, void *opaque, - Error **errp) -{ - X86MachineState *x86ms = X86_MACHINE(obj); - Error *error = NULL; - uint64_t value; - - visit_type_size(v, name, &value, &error); - if (error) { - error_propagate(errp, error); - return; - } - if (value > 4 * GiB) { - error_setg(&error, - "Machine option 'max-ram-below-4g=%"PRIu64 - "' expects size less than or equal to 4G", value); - error_propagate(errp, error); - return; - } - - if (value < 1 * MiB) { - warn_report("Only %" PRIu64 " bytes of RAM below the 4GiB boundary," - "BIOS may not work with less than 1MiB", value); - } - - x86ms->max_ram_below_4g = value; -} - -bool x86_machine_is_smm_enabled(X86MachineState *x86ms) +bool x86_machine_is_smm_enabled(const X86MachineState *x86ms) { bool smm_available = false; @@ -927,7 +1146,7 @@ static void x86_machine_set_smm(Object *obj, Visitor *v, const char *name, visit_type_OnOffAuto(v, name, &x86ms->smm, errp); } -bool x86_machine_is_acpi_enabled(X86MachineState *x86ms) +bool x86_machine_is_acpi_enabled(const X86MachineState *x86ms) { if (x86ms->acpi == ON_OFF_AUTO_OFF) { return false; @@ -958,13 +1177,8 @@ static void x86_machine_initfn(Object *obj) x86ms->smm = ON_OFF_AUTO_AUTO; x86ms->acpi = ON_OFF_AUTO_AUTO; - x86ms->max_ram_below_4g = 0; /* use default */ x86ms->smp_dies = 1; - - x86ms->apicid_from_cpu_idx = x86_apicid_from_cpu_idx; - x86ms->topo_ids_from_apicid = x86_topo_ids_from_apicid; - x86ms->apicid_from_topo_ids = x86_apicid_from_topo_ids; - x86ms->apicid_pkg_offset = apicid_pkg_offset; + x86ms->pci_irq_mask = ACPI_BUILD_PCI_IRQS; } static void x86_machine_class_init(ObjectClass *oc, void *data) @@ -980,12 +1194,6 @@ static void x86_machine_class_init(ObjectClass *oc, void *data) x86mc->save_tsc_khz = true; nc->nmi_monitor_handler = x86_nmi; - object_class_property_add(oc, X86_MACHINE_MAX_RAM_BELOW_4G, "size", - x86_machine_get_max_ram_below_4g, x86_machine_set_max_ram_below_4g, - NULL, NULL); - object_class_property_set_description(oc, X86_MACHINE_MAX_RAM_BELOW_4G, - "Maximum ram below the 4G boundary (32bit boundary)"); - object_class_property_add(oc, X86_MACHINE_SMM, "OnOffAuto", x86_machine_get_smm, x86_machine_set_smm, NULL, NULL); diff --git a/hw/i386/xen/Makefile.objs b/hw/i386/xen/Makefile.objs deleted file mode 100644 index be9d10cf2a1194c1af2a47b245e4c5f1ec7c8405..0000000000000000000000000000000000000000 --- a/hw/i386/xen/Makefile.objs +++ /dev/null @@ -1 +0,0 @@ -obj-y += xen_platform.o xen_apic.o xen_pvdevice.o xen-hvm.o xen-mapcache.o diff --git a/hw/i386/xen/meson.build b/hw/i386/xen/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..be84130300cb9993e7647bf575c9f084fabf7838 --- /dev/null +++ b/hw/i386/xen/meson.build @@ -0,0 +1,7 @@ +i386_ss.add(when: 'CONFIG_XEN', if_true: files( + 'xen-hvm.c', + 'xen-mapcache.c', + 'xen_apic.c', + 'xen_platform.c', + 'xen_pvdevice.c', +)) diff --git a/hw/i386/xen/trace.h b/hw/i386/xen/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..a02bf755dc9e835c3e677f8241cd797f7d9db85c --- /dev/null +++ b/hw/i386/xen/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_i386_xen.h" diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c index 82ece6b9e73935a4b959c79bad0a17b2637c21c9..9519c33c098db2111ea241f7602d57b33cc1fd0a 100644 --- a/hw/i386/xen/xen-hvm.c +++ b/hw/i386/xen/xen-hvm.c @@ -9,6 +9,7 @@ */ #include "qemu/osdep.h" +#include "qemu/units.h" #include "cpu.h" #include "hw/pci/pci.h" @@ -21,13 +22,15 @@ #include "hw/xen/xen_common.h" #include "hw/xen/xen-legacy-backend.h" #include "hw/xen/xen-bus.h" +#include "hw/xen/xen-x86.h" #include "qapi/error.h" -#include "qapi/qapi-commands-misc.h" +#include "qapi/qapi-commands-migration.h" #include "qemu/error-report.h" #include "qemu/main-loop.h" #include "qemu/range.h" #include "sysemu/runstate.h" #include "sysemu/sysemu.h" +#include "sysemu/xen.h" #include "sysemu/xen-mapcache.h" #include "trace.h" #include "exec/address-spaces.h" @@ -203,7 +206,7 @@ static void xen_ram_init(PCMachineState *pcms, ram_addr_t block_len; uint64_t user_lowmem = object_property_get_uint(qdev_get_machine(), - X86_MACHINE_MAX_RAM_BELOW_4G, + PC_MACHINE_MAX_RAM_BELOW_4G, &error_abort); /* Handle the machine opt max-ram-below-4g. It is basically doing @@ -230,7 +233,7 @@ static void xen_ram_init(PCMachineState *pcms, * Xen does not allocate the memory continuously, it keeps a * hole of the size computed above or passed in. */ - block_len = (1ULL << 32) + x86ms->above_4g_mem_size; + block_len = (4 * GiB) + x86ms->above_4g_mem_size; } memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len, &error_fatal); @@ -1138,7 +1141,7 @@ static int handle_buffered_iopage(XenIOState *state) assert(req.dir == IOREQ_WRITE); assert(!req.data_is_ptr); - atomic_add(&buf_page->read_pointer, qw + 1); + qatomic_add(&buf_page->read_pointer, qw + 1); } return req.count; @@ -1393,7 +1396,7 @@ static int xen_map_ioreq_server(XenIOState *state) return 0; } -void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory) +void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion **ram_memory) { MachineState *ms = MACHINE(pcms); unsigned int max_cpus = ms->smp.max_cpus; diff --git a/hw/i386/xen/xen_platform.c b/hw/i386/xen/xen_platform.c index 0f7b05e5e1bbe2ae1f31d5a1a58c9a26e47d5aae..7c4db35debbd15cfffa58037326a032d2d1e77d3 100644 --- a/hw/i386/xen/xen_platform.c +++ b/hw/i386/xen/xen_platform.c @@ -33,11 +33,11 @@ #include "hw/xen/xen-legacy-backend.h" #include "trace.h" #include "exec/address-spaces.h" +#include "sysemu/xen.h" #include "sysemu/block-backend.h" #include "qemu/error-report.h" #include "qemu/module.h" - -#include +#include "qom/object.h" //#define DEBUG_PLATFORM @@ -51,7 +51,7 @@ #define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */ -typedef struct PCIXenPlatformState { +struct PCIXenPlatformState { /*< private >*/ PCIDevice parent_obj; /*< public >*/ @@ -66,11 +66,10 @@ typedef struct PCIXenPlatformState { /* Log from guest drivers */ char log_buffer[4096]; int log_buffer_off; -} PCIXenPlatformState; +}; #define TYPE_XEN_PLATFORM "xen-platform" -#define XEN_PLATFORM(obj) \ - OBJECT_CHECK(PCIXenPlatformState, (obj), TYPE_XEN_PLATFORM) +OBJECT_DECLARE_SIMPLE_TYPE(PCIXenPlatformState, XEN_PLATFORM) #define XEN_PLATFORM_IOPORT 0x10 diff --git a/hw/i386/xen/xen_pvdevice.c b/hw/i386/xen/xen_pvdevice.c index ee2610c7a0eaa4b6d72dbabe208aef77b672a6fc..1ea95fa6012fd068b956a29d1f632b76a6f68537 100644 --- a/hw/i386/xen/xen_pvdevice.c +++ b/hw/i386/xen/xen_pvdevice.c @@ -36,13 +36,13 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "trace.h" +#include "qom/object.h" #define TYPE_XEN_PV_DEVICE "xen-pvdevice" -#define XEN_PV_DEVICE(obj) \ - OBJECT_CHECK(XenPVDevice, (obj), TYPE_XEN_PV_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(XenPVDevice, XEN_PV_DEVICE) -typedef struct XenPVDevice { +struct XenPVDevice { /*< private >*/ PCIDevice parent_obj; /*< public >*/ @@ -51,7 +51,7 @@ typedef struct XenPVDevice { uint8_t revision; uint32_t size; MemoryRegion mmio; -} XenPVDevice; +}; static uint64_t xen_pv_mmio_read(void *opaque, hwaddr addr, unsigned size) diff --git a/hw/ide/Makefile.objs b/hw/ide/Makefile.objs deleted file mode 100644 index faf04e020909f7532d81cf5e2455d9bfc54aeffd..0000000000000000000000000000000000000000 --- a/hw/ide/Makefile.objs +++ /dev/null @@ -1,14 +0,0 @@ -common-obj-$(CONFIG_IDE_CORE) += core.o atapi.o -common-obj-$(CONFIG_IDE_QDEV) += qdev.o -common-obj-$(CONFIG_IDE_PCI) += pci.o -common-obj-$(CONFIG_IDE_ISA) += isa.o ioport.o -common-obj-$(CONFIG_IDE_PIIX) += piix.o ioport.o -common-obj-$(CONFIG_IDE_CMD646) += cmd646.o -common-obj-$(CONFIG_IDE_MACIO) += macio.o -common-obj-$(CONFIG_IDE_MMIO) += mmio.o -common-obj-$(CONFIG_IDE_VIA) += via.o -common-obj-$(CONFIG_MICRODRIVE) += microdrive.o -common-obj-$(CONFIG_AHCI) += ahci.o -common-obj-$(CONFIG_AHCI_ICH9) += ich.o -common-obj-$(CONFIG_ALLWINNER_A10) += ahci-allwinner.o -common-obj-$(CONFIG_IDE_SII3112) += sii3112.o diff --git a/hw/ide/ahci-allwinner.c b/hw/ide/ahci-allwinner.c index 8536b9eb5a488464277a95ad7dae9c359df4ae78..227e747ba722d2934090193f7e11db2095a604da 100644 --- a/hw/ide/ahci-allwinner.c +++ b/hw/ide/ahci-allwinner.c @@ -25,9 +25,6 @@ #include "trace.h" -#define ALLWINNER_AHCI(obj) \ - OBJECT_CHECK(AllwinnerAHCIState, (obj), TYPE_ALLWINNER_AHCI) - #define ALLWINNER_AHCI_BISTAFR ((0xa0 - ALLWINNER_AHCI_MMIO_OFF) / 4) #define ALLWINNER_AHCI_BISTCR ((0xa4 - ALLWINNER_AHCI_MMIO_OFF) / 4) #define ALLWINNER_AHCI_BISTFCTR ((0xa8 - ALLWINNER_AHCI_MMIO_OFF) / 4) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index fc82cbd5f1d070e38b63608183c639d79f6bdc14..4b675b9cfd8d579bfcde09525fa7ac49658fc57e 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -9,7 +9,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -44,7 +44,7 @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot); static void ahci_reset_port(AHCIState *s, int port); static bool ahci_write_fis_d2h(AHCIDevice *ad); static void ahci_init_d2h(AHCIDevice *ad); -static int ahci_dma_prepare_buf(IDEDMA *dma, int32_t limit); +static int ahci_dma_prepare_buf(const IDEDMA *dma, int32_t limit); static bool ahci_map_clb_address(AHCIDevice *ad); static bool ahci_map_fis_address(AHCIDevice *ad); static void ahci_unmap_clb_address(AHCIDevice *ad); @@ -250,7 +250,7 @@ static void map_page(AddressSpace *as, uint8_t **ptr, uint64_t addr, } *ptr = dma_memory_map(as, addr, &len, DMA_DIRECTION_FROM_DEVICE); - if (len < wanted) { + if (len < wanted && *ptr) { dma_memory_unmap(as, *ptr, len, DMA_DIRECTION_FROM_DEVICE, len); *ptr = NULL; } @@ -1151,7 +1151,7 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis, if (!ncq_tfs->sector_count) { ncq_tfs->sector_count = 0x10000; } - size = ncq_tfs->sector_count * 512; + size = ncq_tfs->sector_count * BDRV_SECTOR_SIZE; ahci_populate_sglist(ad, &ncq_tfs->sglist, ncq_tfs->cmdh, size, 0); if (ncq_tfs->sglist.size < size) { @@ -1338,7 +1338,7 @@ out: } /* Transfer PIO data between RAM and device */ -static void ahci_pio_transfer(IDEDMA *dma) +static void ahci_pio_transfer(const IDEDMA *dma) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); IDEState *s = &ad->port.ifs[0]; @@ -1397,7 +1397,7 @@ out: } } -static void ahci_start_dma(IDEDMA *dma, IDEState *s, +static void ahci_start_dma(const IDEDMA *dma, IDEState *s, BlockCompletionFunc *dma_cb) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); @@ -1406,7 +1406,7 @@ static void ahci_start_dma(IDEDMA *dma, IDEState *s, dma_cb(s, 0); } -static void ahci_restart_dma(IDEDMA *dma) +static void ahci_restart_dma(const IDEDMA *dma) { /* Nothing to do, ahci_start_dma already resets s->io_buffer_offset. */ } @@ -1415,7 +1415,7 @@ static void ahci_restart_dma(IDEDMA *dma) * IDE/PIO restarts are handled by the core layer, but NCQ commands * need an extra kick from the AHCI HBA. */ -static void ahci_restart(IDEDMA *dma) +static void ahci_restart(const IDEDMA *dma) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); int i; @@ -1432,7 +1432,7 @@ static void ahci_restart(IDEDMA *dma) * Called in DMA and PIO R/W chains to read the PRDT. * Not shared with NCQ pathways. */ -static int32_t ahci_dma_prepare_buf(IDEDMA *dma, int32_t limit) +static int32_t ahci_dma_prepare_buf(const IDEDMA *dma, int32_t limit) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); IDEState *s = &ad->port.ifs[0]; @@ -1453,7 +1453,7 @@ static int32_t ahci_dma_prepare_buf(IDEDMA *dma, int32_t limit) * Called via dma_buf_commit, for both DMA and PIO paths. * sglist destruction is handled within dma_buf_commit. */ -static void ahci_commit_buf(IDEDMA *dma, uint32_t tx_bytes) +static void ahci_commit_buf(const IDEDMA *dma, uint32_t tx_bytes) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); @@ -1461,7 +1461,7 @@ static void ahci_commit_buf(IDEDMA *dma, uint32_t tx_bytes) ad->cur_cmd->status = cpu_to_le32(tx_bytes); } -static int ahci_dma_rw_buf(IDEDMA *dma, bool is_write) +static int ahci_dma_rw_buf(const IDEDMA *dma, bool is_write) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); IDEState *s = &ad->port.ifs[0]; @@ -1486,7 +1486,7 @@ static int ahci_dma_rw_buf(IDEDMA *dma, bool is_write) return 1; } -static void ahci_cmd_done(IDEDMA *dma) +static void ahci_cmd_done(const IDEDMA *dma) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); @@ -1703,7 +1703,8 @@ static int ahci_state_post_load(void *opaque, int version_id) return -1; } ahci_populate_sglist(ncq_tfs->drive, &ncq_tfs->sglist, - ncq_tfs->cmdh, ncq_tfs->sector_count * 512, + ncq_tfs->cmdh, + ncq_tfs->sector_count * BDRV_SECTOR_SIZE, 0); if (ncq_tfs->sector_count != ncq_tfs->sglist.size >> 9) { return -1; @@ -1818,7 +1819,7 @@ type_init(sysbus_ahci_register_types) int32_t ahci_get_num_ports(PCIDevice *dev) { - AHCIPCIState *d = ICH_AHCI(dev); + AHCIPCIState *d = ICH9_AHCI(dev); AHCIState *ahci = &d->ahci; return ahci->ports; @@ -1826,7 +1827,7 @@ int32_t ahci_get_num_ports(PCIDevice *dev) void ahci_ide_create_devs(PCIDevice *dev, DriveInfo **hd) { - AHCIPCIState *d = ICH_AHCI(dev); + AHCIPCIState *d = ICH9_AHCI(dev); AHCIState *ahci = &d->ahci; int i; diff --git a/hw/ide/ahci_internal.h b/hw/ide/ahci_internal.h index bab0459774ed3392c8ac34721c7e386d89f4c706..7f32e87731d93e787187c6cd7bb609e3f60cc800 100644 --- a/hw/ide/ahci_internal.h +++ b/hw/ide/ahci_internal.h @@ -9,7 +9,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -332,9 +332,6 @@ struct AHCIPCIState { AHCIState ahci; }; -#define ICH_AHCI(obj) \ - OBJECT_CHECK(AHCIPCIState, (obj), TYPE_ICH9_AHCI) - extern const VMStateDescription vmstate_ahci; #define VMSTATE_AHCI(_field, _state) { \ @@ -394,6 +391,4 @@ void ahci_uninit(AHCIState *s); void ahci_reset(AHCIState *s); -#define SYSBUS_AHCI(obj) OBJECT_CHECK(SysbusAHCIState, (obj), TYPE_SYSBUS_AHCI) - #endif /* HW_IDE_AHCI_INTERNAL_H */ diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index 17a9d635d8426684512d2a37bfa6c951f3cc9668..e79157863fa942feeadbe4b9006192f413c49368 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -276,6 +276,8 @@ void ide_atapi_cmd_reply_end(IDEState *s) s->packet_transfer_size -= size; s->elementary_transfer_size -= size; s->io_buffer_index += size; + assert(size <= s->io_buffer_total_len); + assert(s->io_buffer_index <= s->io_buffer_total_len); /* Some adapters process PIO data right away. In that case, we need * to avoid mutual recursion between ide_transfer_start @@ -824,9 +826,9 @@ static void cmd_get_configuration(IDEState *s, uint8_t *buf) * * Only a problem if the feature/profiles grow. */ - if (max_len > 512) { + if (max_len > BDRV_SECTOR_SIZE) { /* XXX: assume 1 sector */ - max_len = 512; + max_len = BDRV_SECTOR_SIZE; } memset(buf, 0, max_len); @@ -1186,8 +1188,8 @@ static void cmd_read_dvd_structure(IDEState *s, uint8_t* buf) } } - memset(buf, 0, max_len > IDE_DMA_BUF_SECTORS * 512 + 4 ? - IDE_DMA_BUF_SECTORS * 512 + 4 : max_len); + memset(buf, 0, max_len > IDE_DMA_BUF_SECTORS * BDRV_SECTOR_SIZE + 4 ? + IDE_DMA_BUF_SECTORS * BDRV_SECTOR_SIZE + 4 : max_len); switch (format) { case 0x00 ... 0x7f: diff --git a/hw/ide/core.c b/hw/ide/core.c index 689bb36409ed6e901d1df9d875881893a9d54c9d..e85821637c961121ad7a2ccfbaf9869e5463074b 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -367,7 +367,7 @@ fill_buffer: static void ide_set_signature(IDEState *s) { - s->select &= 0xf0; /* clear head */ + s->select &= ~(ATA_DEV_HS); /* clear head */ /* put signature */ s->nsector = 1; s->sector = 1; @@ -586,48 +586,54 @@ void ide_transfer_stop(IDEState *s) int64_t ide_get_sector(IDEState *s) { int64_t sector_num; - if (s->select & 0x40) { - /* lba */ - if (!s->lba48) { - sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) | - (s->lcyl << 8) | s->sector; - } else { + if (s->select & (ATA_DEV_LBA)) { + if (s->lba48) { sector_num = ((int64_t)s->hob_hcyl << 40) | ((int64_t) s->hob_lcyl << 32) | ((int64_t) s->hob_sector << 24) | ((int64_t) s->hcyl << 16) | ((int64_t) s->lcyl << 8) | s->sector; + } else { + /* LBA28 */ + sector_num = ((s->select & (ATA_DEV_LBA_MSB)) << 24) | + (s->hcyl << 16) | (s->lcyl << 8) | s->sector; } } else { + /* CHS */ sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors + - (s->select & 0x0f) * s->sectors + (s->sector - 1); + (s->select & (ATA_DEV_HS)) * s->sectors + (s->sector - 1); } + return sector_num; } void ide_set_sector(IDEState *s, int64_t sector_num) { unsigned int cyl, r; - if (s->select & 0x40) { - if (!s->lba48) { - s->select = (s->select & 0xf0) | (sector_num >> 24); - s->hcyl = (sector_num >> 16); - s->lcyl = (sector_num >> 8); - s->sector = (sector_num); - } else { + if (s->select & (ATA_DEV_LBA)) { + if (s->lba48) { s->sector = sector_num; s->lcyl = sector_num >> 8; s->hcyl = sector_num >> 16; s->hob_sector = sector_num >> 24; s->hob_lcyl = sector_num >> 32; s->hob_hcyl = sector_num >> 40; + } else { + /* LBA28 */ + s->select = (s->select & ~(ATA_DEV_LBA_MSB)) | + ((sector_num >> 24) & (ATA_DEV_LBA_MSB)); + s->hcyl = (sector_num >> 16); + s->lcyl = (sector_num >> 8); + s->sector = (sector_num); } } else { + /* CHS */ cyl = sector_num / (s->heads * s->sectors); r = sector_num % (s->heads * s->sectors); s->hcyl = cyl >> 8; s->lcyl = cyl; - s->select = (s->select & 0xf0) | ((r / s->sectors) & 0x0f); + s->select = (s->select & ~(ATA_DEV_HS)) | + ((r / s->sectors) & (ATA_DEV_HS)); s->sector = (r % s->sectors) + 1; } } @@ -709,7 +715,7 @@ void ide_cancel_dma_sync(IDEState *s) /* * We can't cancel Scatter Gather DMA in the middle of the * operation or a partial (not full) DMA transfer would reach - * the storage so we wait for completion instead (we beahve + * the storage so we wait for completion instead (we behave * like if the DMA was completed by the time the guest trying * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not * set). @@ -1215,8 +1221,7 @@ static void ide_cmd_lba48_transform(IDEState *s, int lba48) static void ide_clear_hob(IDEBus *bus) { /* any write clears HOB high bit of device control register */ - bus->ifs[0].select &= ~(1 << 7); - bus->ifs[1].select &= ~(1 << 7); + bus->cmd &= ~(IDE_CTRL_HOB); } /* IOport [W]rite [R]egisters */ @@ -1256,12 +1261,14 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) return; } + /* NOTE: Device0 and Device1 both receive incoming register writes. + * (They're on the same bus! They have to!) */ + switch (reg_num) { case 0: break; case ATA_IOPORT_WR_FEATURES: ide_clear_hob(bus); - /* NOTE: data is written to the two drives */ bus->ifs[0].hob_feature = bus->ifs[0].feature; bus->ifs[1].hob_feature = bus->ifs[1].feature; bus->ifs[0].feature = val; @@ -1296,15 +1303,16 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) bus->ifs[1].hcyl = val; break; case ATA_IOPORT_WR_DEVICE_HEAD: - /* FIXME: HOB readback uses bit 7 */ - bus->ifs[0].select = (val & ~0x10) | 0xa0; - bus->ifs[1].select = (val | 0x10) | 0xa0; + ide_clear_hob(bus); + bus->ifs[0].select = val | (ATA_DEV_ALWAYS_ON); + bus->ifs[1].select = val | (ATA_DEV_ALWAYS_ON); /* select drive */ - bus->unit = (val >> 4) & 1; + bus->unit = (val & (ATA_DEV_SELECT)) ? 1 : 0; break; default: case ATA_IOPORT_WR_COMMAND: - /* command */ + ide_clear_hob(bus); + qemu_irq_lower(bus->irq); ide_exec_cmd(bus, val); break; } @@ -1338,7 +1346,7 @@ static void ide_reset(IDEState *s) s->hob_lcyl = 0; s->hob_hcyl = 0; - s->select = 0xa0; + s->select = (ATA_DEV_ALWAYS_ON); s->status = READY_STAT | SEEK_STAT; s->lba48 = 0; @@ -2142,9 +2150,7 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr) int ret, hob; reg_num = addr & 7; - /* FIXME: HOB readback uses bit 7, but it's always set right now */ - //hob = s->select & (1 << 7); - hob = 0; + hob = bus->cmd & (IDE_CTRL_HOB); switch (reg_num) { case ATA_IOPORT_RR_DATA: ret = 0xff; @@ -2235,34 +2241,54 @@ uint32_t ide_status_read(void *opaque, uint32_t addr) return ret; } -void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val) +static void ide_perform_srst(IDEState *s) +{ + s->status |= BUSY_STAT; + + /* Halt PIO (Via register state); PIO BH remains scheduled. */ + ide_transfer_halt(s); + + /* Cancel DMA -- may drain block device and invoke callbacks */ + ide_cancel_dma_sync(s); + + /* Cancel PIO callback, reset registers/signature, etc */ + ide_reset(s); + + /* perform diagnostic */ + cmd_exec_dev_diagnostic(s, WIN_DIAGNOSE); +} + +static void ide_bus_perform_srst(void *opaque) { IDEBus *bus = opaque; IDEState *s; int i; - trace_ide_cmd_write(addr, val, bus); + for (i = 0; i < 2; i++) { + s = &bus->ifs[i]; + ide_perform_srst(s); + } - /* common for both drives */ - if (!(bus->cmd & IDE_CMD_RESET) && - (val & IDE_CMD_RESET)) { - /* reset low to high */ - for(i = 0;i < 2; i++) { - s = &bus->ifs[i]; - s->status = BUSY_STAT | SEEK_STAT; - s->error = 0x01; - } - } else if ((bus->cmd & IDE_CMD_RESET) && - !(val & IDE_CMD_RESET)) { - /* high to low */ - for(i = 0;i < 2; i++) { + bus->cmd &= ~IDE_CTRL_RESET; +} + +void ide_ctrl_write(void *opaque, uint32_t addr, uint32_t val) +{ + IDEBus *bus = opaque; + IDEState *s; + int i; + + trace_ide_ctrl_write(addr, val, bus); + + /* Device0 and Device1 each have their own control register, + * but QEMU models it as just one register in the controller. */ + if (!(bus->cmd & IDE_CTRL_RESET) && (val & IDE_CTRL_RESET)) { + for (i = 0; i < 2; i++) { s = &bus->ifs[i]; - if (s->drive_kind == IDE_CD) - s->status = 0x00; /* NOTE: READY is _not_ set */ - else - s->status = READY_STAT | SEEK_STAT; - ide_set_signature(s); + s->status |= BUSY_STAT; } + replay_bh_schedule_oneshot_event(qemu_get_aio_context(), + ide_bus_perform_srst, bus); } bus->cmd = val; @@ -2570,16 +2596,16 @@ static void ide_init1(IDEBus *bus, int unit) ide_sector_write_timer_cb, s); } -static int ide_nop_int(IDEDMA *dma, bool is_write) +static int ide_nop_int(const IDEDMA *dma, bool is_write) { return 0; } -static void ide_nop(IDEDMA *dma) +static void ide_nop(const IDEDMA *dma) { } -static int32_t ide_nop_int32(IDEDMA *dma, int32_t l) +static int32_t ide_nop_int32(const IDEDMA *dma, int32_t l) { return 0; } diff --git a/hw/ide/ich.c b/hw/ide/ich.c index eff3188fff8f3737ce563a0ccd72a4cf3d849cc3..1007a51fcb115811382f729a11c6a900b3902ca0 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -91,14 +91,14 @@ static const VMStateDescription vmstate_ich9_ahci = { static void pci_ich9_reset(DeviceState *dev) { - AHCIPCIState *d = ICH_AHCI(dev); + AHCIPCIState *d = ICH9_AHCI(dev); ahci_reset(&d->ahci); } static void pci_ich9_ahci_init(Object *obj) { - struct AHCIPCIState *d = ICH_AHCI(obj); + struct AHCIPCIState *d = ICH9_AHCI(obj); ahci_init(&d->ahci, DEVICE(obj)); } @@ -108,7 +108,7 @@ static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp) struct AHCIPCIState *d; int sata_cap_offset; uint8_t *sata_cap; - d = ICH_AHCI(dev); + d = ICH9_AHCI(dev); int ret; ahci_realize(&d->ahci, DEVICE(dev), pci_get_address_space(dev), 6); @@ -154,7 +154,7 @@ static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp) static void pci_ich9_uninit(PCIDevice *dev) { struct AHCIPCIState *d; - d = ICH_AHCI(dev); + d = ICH9_AHCI(dev); msi_uninit(dev); ahci_uninit(&d->ahci); diff --git a/hw/ide/ioport.c b/hw/ide/ioport.c index ab1f4e5d9c06e87b6ed6f7011b491e37f3a6f9d4..b613ff3bbafbcd3d49236eb2106ace85a7c49631 100644 --- a/hw/ide/ioport.c +++ b/hw/ide/ioport.c @@ -46,7 +46,7 @@ static const MemoryRegionPortio ide_portio_list[] = { }; static const MemoryRegionPortio ide_portio2_list[] = { - { 0, 1, 1, .read = ide_status_read, .write = ide_cmd_write }, + { 0, 1, 1, .read = ide_status_read, .write = ide_ctrl_write }, PORTIO_END_OF_LIST(), }; diff --git a/hw/ide/isa.c b/hw/ide/isa.c index 8395807b08ad4f86632cb7f3670971e1e8032c6a..6bc19de22653d53ef2534305229ea4db6e60765e 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -27,18 +27,20 @@ #include "hw/isa/isa.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" +#include "qapi/error.h" #include "qemu/module.h" #include "sysemu/dma.h" #include "hw/ide/internal.h" +#include "qom/object.h" /***********************************************************/ /* ISA IDE definitions */ #define TYPE_ISA_IDE "isa-ide" -#define ISA_IDE(obj) OBJECT_CHECK(ISAIDEState, (obj), TYPE_ISA_IDE) +OBJECT_DECLARE_SIMPLE_TYPE(ISAIDEState, ISA_IDE) -typedef struct ISAIDEState { +struct ISAIDEState { ISADevice parent_obj; IDEBus bus; @@ -46,7 +48,7 @@ typedef struct ISAIDEState { uint32_t iobase2; uint32_t isairq; qemu_irq irq; -} ISAIDEState; +}; static void isa_ide_reset(DeviceState *d) { @@ -86,12 +88,12 @@ ISADevice *isa_ide_init(ISABus *bus, int iobase, int iobase2, int isairq, ISADevice *isadev; ISAIDEState *s; - isadev = isa_create(bus, TYPE_ISA_IDE); + isadev = isa_new(TYPE_ISA_IDE); dev = DEVICE(isadev); qdev_prop_set_uint32(dev, "iobase", iobase); qdev_prop_set_uint32(dev, "iobase2", iobase2); qdev_prop_set_uint32(dev, "irq", isairq); - qdev_init_nofail(dev); + isa_realize_and_unref(isadev, bus, &error_fatal); s = ISA_IDE(dev); if (hd0) { diff --git a/hw/ide/macio.c b/hw/ide/macio.c index 30af0e93e629c6bdf7e02aeff3ed3367604a0d17..b270a101632012c4db21686fd9d281c5562df05a 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -329,7 +329,7 @@ static void pmac_ide_write(void *opaque, hwaddr addr, uint64_t val, case 0x8: case 0x16: if (size == 1) { - ide_cmd_write(&d->bus, 0, val); + ide_ctrl_write(&d->bus, 0, val); } break; case 0x20: @@ -376,17 +376,17 @@ static void macio_ide_reset(DeviceState *dev) ide_bus_reset(&d->bus); } -static int ide_nop_int(IDEDMA *dma, bool is_write) +static int ide_nop_int(const IDEDMA *dma, bool is_write) { return 0; } -static int32_t ide_nop_int32(IDEDMA *dma, int32_t l) +static int32_t ide_nop_int32(const IDEDMA *dma, int32_t l) { return 0; } -static void ide_dbdma_start(IDEDMA *dma, IDEState *s, +static void ide_dbdma_start(const IDEDMA *dma, IDEState *s, BlockCompletionFunc *cb) { MACIOIDEState *m = container_of(dma, MACIOIDEState, dma); diff --git a/hw/ide/meson.build b/hw/ide/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..ddcb3b28d23a9e67c096fbf20ad3ab01fe297085 --- /dev/null +++ b/hw/ide/meson.build @@ -0,0 +1,14 @@ +softmmu_ss.add(when: 'CONFIG_AHCI', if_true: files('ahci.c')) +softmmu_ss.add(when: 'CONFIG_AHCI_ICH9', if_true: files('ich.c')) +softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: files('ahci-allwinner.c')) +softmmu_ss.add(when: 'CONFIG_IDE_CMD646', if_true: files('cmd646.c')) +softmmu_ss.add(when: 'CONFIG_IDE_CORE', if_true: files('core.c', 'atapi.c')) +softmmu_ss.add(when: 'CONFIG_IDE_ISA', if_true: files('isa.c', 'ioport.c')) +softmmu_ss.add(when: 'CONFIG_IDE_MACIO', if_true: files('macio.c')) +softmmu_ss.add(when: 'CONFIG_IDE_MMIO', if_true: files('mmio.c')) +softmmu_ss.add(when: 'CONFIG_IDE_PCI', if_true: files('pci.c')) +softmmu_ss.add(when: 'CONFIG_IDE_PIIX', if_true: files('piix.c', 'ioport.c')) +softmmu_ss.add(when: 'CONFIG_IDE_QDEV', if_true: files('qdev.c')) +softmmu_ss.add(when: 'CONFIG_IDE_SII3112', if_true: files('sii3112.c')) +softmmu_ss.add(when: 'CONFIG_IDE_VIA', if_true: files('via.c')) +softmmu_ss.add(when: 'CONFIG_MICRODRIVE', if_true: files('microdrive.c')) diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c index 6b30e36ed833bae464f39078f7fcf0cd06331831..58a14fea36371fada70fafe63e3bf1c050a08636 100644 --- a/hw/ide/microdrive.c +++ b/hw/ide/microdrive.c @@ -26,13 +26,15 @@ #include "qemu/osdep.h" #include "hw/pcmcia.h" #include "migration/vmstate.h" +#include "qapi/error.h" #include "qemu/module.h" #include "sysemu/dma.h" #include "hw/ide/internal.h" +#include "qom/object.h" #define TYPE_MICRODRIVE "microdrive" -#define MICRODRIVE(obj) OBJECT_CHECK(MicroDriveState, (obj), TYPE_MICRODRIVE) +OBJECT_DECLARE_SIMPLE_TYPE(MicroDriveState, MICRODRIVE) /***********************************************************/ /* CF-ATA Microdrive */ @@ -41,7 +43,7 @@ /* DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface. */ -typedef struct MicroDriveState { +struct MicroDriveState { /*< private >*/ PCMCIACardState parent_obj; /*< public >*/ @@ -58,7 +60,7 @@ typedef struct MicroDriveState { uint8_t ctrl; uint16_t io; uint8_t cycle; -} MicroDriveState; +}; /* Register bitfields */ enum md_opt { @@ -560,7 +562,7 @@ PCMCIACardState *dscm1xxxx_init(DriveInfo *dinfo) MicroDriveState *md; md = MICRODRIVE(object_new(TYPE_DSCM1XXXX)); - qdev_init_nofail(DEVICE(md)); + qdev_realize(DEVICE(md), NULL, &error_fatal); if (dinfo != NULL) { ide_create_drive(&md->bus, 0, dinfo); diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c index d233bd8c01cab1ba7a5af1c549380b9e6810eb7e..36e2f4790abc73e9d325cea6388cf6fa21367291 100644 --- a/hw/ide/mmio.c +++ b/hw/ide/mmio.c @@ -31,6 +31,7 @@ #include "hw/ide/internal.h" #include "hw/qdev-properties.h" +#include "qom/object.h" /***********************************************************/ /* MMIO based ide port @@ -39,9 +40,11 @@ */ #define TYPE_MMIO_IDE "mmio-ide" -#define MMIO_IDE(obj) OBJECT_CHECK(MMIOState, (obj), TYPE_MMIO_IDE) +typedef struct MMIOIDEState MMIOState; +DECLARE_INSTANCE_CHECKER(MMIOState, MMIO_IDE, + TYPE_MMIO_IDE) -typedef struct MMIOIDEState { +struct MMIOIDEState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -51,7 +54,7 @@ typedef struct MMIOIDEState { uint32_t shift; qemu_irq irq; MemoryRegion iomem1, iomem2; -} MMIOState; +}; static void mmio_ide_reset(DeviceState *dev) { @@ -95,16 +98,16 @@ static uint64_t mmio_ide_status_read(void *opaque, hwaddr addr, return ide_status_read(&s->bus, 0); } -static void mmio_ide_cmd_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) +static void mmio_ide_ctrl_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) { MMIOState *s = opaque; - ide_cmd_write(&s->bus, 0, val); + ide_ctrl_write(&s->bus, 0, val); } static const MemoryRegionOps mmio_ide_cs_ops = { .read = mmio_ide_status_read, - .write = mmio_ide_cmd_write, + .write = mmio_ide_ctrl_write, .endianness = DEVICE_LITTLE_ENDIAN, }; diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 97347f07f1197e3663e0394118f96d61876cfab4..84ba733548e5d2d92b57fb9a8d92b1e716669a35 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -38,7 +38,7 @@ (IDE_RETRY_DMA | IDE_RETRY_PIO | \ IDE_RETRY_READ | IDE_RETRY_FLUSH) -static uint64_t pci_ide_cmd_read(void *opaque, hwaddr addr, unsigned size) +static uint64_t pci_ide_status_read(void *opaque, hwaddr addr, unsigned size) { IDEBus *bus = opaque; @@ -48,20 +48,20 @@ static uint64_t pci_ide_cmd_read(void *opaque, hwaddr addr, unsigned size) return ide_status_read(bus, addr + 2); } -static void pci_ide_cmd_write(void *opaque, hwaddr addr, - uint64_t data, unsigned size) +static void pci_ide_ctrl_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) { IDEBus *bus = opaque; if (addr != 2 || size != 1) { return; } - ide_cmd_write(bus, addr + 2, data); + ide_ctrl_write(bus, addr + 2, data); } const MemoryRegionOps pci_ide_cmd_le_ops = { - .read = pci_ide_cmd_read, - .write = pci_ide_cmd_write, + .read = pci_ide_status_read, + .write = pci_ide_ctrl_write, .endianness = DEVICE_LITTLE_ENDIAN, }; @@ -103,7 +103,7 @@ const MemoryRegionOps pci_ide_data_le_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static void bmdma_start_dma(IDEDMA *dma, IDEState *s, +static void bmdma_start_dma(const IDEDMA *dma, IDEState *s, BlockCompletionFunc *dma_cb) { BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); @@ -126,7 +126,7 @@ static void bmdma_start_dma(IDEDMA *dma, IDEState *s, * IDEState.io_buffer_size will contain the number of bytes described * by the PRDs, whether or not we added them to the sglist. */ -static int32_t bmdma_prepare_buf(IDEDMA *dma, int32_t limit) +static int32_t bmdma_prepare_buf(const IDEDMA *dma, int32_t limit) { BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); IDEState *s = bmdma_active_if(bm); @@ -138,7 +138,7 @@ static int32_t bmdma_prepare_buf(IDEDMA *dma, int32_t limit) int l, len; pci_dma_sglist_init(&s->sg, pci_dev, - s->nsector / (BMDMA_PAGE_SIZE / 512) + 1); + s->nsector / (BMDMA_PAGE_SIZE / BDRV_SECTOR_SIZE) + 1); s->io_buffer_size = 0; for(;;) { if (bm->cur_prd_len == 0) { @@ -181,7 +181,7 @@ static int32_t bmdma_prepare_buf(IDEDMA *dma, int32_t limit) } /* return 0 if buffer completed */ -static int bmdma_rw_buf(IDEDMA *dma, bool is_write) +static int bmdma_rw_buf(const IDEDMA *dma, bool is_write) { BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); IDEState *s = bmdma_active_if(bm); @@ -230,7 +230,7 @@ static int bmdma_rw_buf(IDEDMA *dma, bool is_write) return 1; } -static void bmdma_set_inactive(IDEDMA *dma, bool more) +static void bmdma_set_inactive(const IDEDMA *dma, bool more) { BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); @@ -242,7 +242,7 @@ static void bmdma_set_inactive(IDEDMA *dma, bool more) } } -static void bmdma_restart_dma(IDEDMA *dma) +static void bmdma_restart_dma(const IDEDMA *dma) { BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); @@ -257,7 +257,7 @@ static void bmdma_cancel(BMDMAState *bm) } } -static void bmdma_reset(IDEDMA *dma) +static void bmdma_reset(const IDEDMA *dma) { BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); diff --git a/hw/ide/piix.c b/hw/ide/piix.c index b402a936362bf3a785aefc9d692832752b1322b5..b9860e35a5c463b7bd281dd2b996e2e684c6b2a7 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -164,30 +164,29 @@ static void pci_piix_ide_realize(PCIDevice *dev, Error **errp) int pci_piix3_xen_ide_unplug(DeviceState *dev, bool aux) { PCIIDEState *pci_ide; - DriveInfo *di; int i; IDEDevice *idedev; + IDEBus *idebus; + BlockBackend *blk; pci_ide = PCI_IDE(dev); for (i = aux ? 1 : 0; i < 4; i++) { - di = drive_get_by_index(IF_IDE, i); - if (di != NULL && !di->media_cd) { - BlockBackend *blk = blk_by_legacy_dinfo(di); - DeviceState *ds = blk_get_attached_dev(blk); + idebus = &pci_ide->bus[i / 2]; + blk = idebus->ifs[i % 2].blk; - blk_drain(blk); - blk_flush(blk); - - if (ds) { - blk_detach_dev(blk, ds); - } - pci_ide->bus[di->bus].ifs[di->unit].blk = NULL; + if (blk && idebus->ifs[i % 2].drive_kind != IDE_CD) { if (!(i % 2)) { - idedev = pci_ide->bus[di->bus].master; + idedev = idebus->master; } else { - idedev = pci_ide->bus[di->bus].slave; + idedev = idebus->slave; } + + blk_drain(blk); + blk_flush(blk); + + blk_detach_dev(blk, DEVICE(idedev)); + idebus->ifs[i % 2].blk = NULL; idedev->conf.blk = NULL; monitor_remove_blk(blk); blk_unref(blk); diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 06b11583f5768d185d45a1ce95ab1228d8099ee7..1086b7a3272e73fb50e12d9553fa1779467d3716 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -127,11 +127,11 @@ IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive) { DeviceState *dev; - dev = qdev_create(&bus->qbus, drive->media_cd ? "ide-cd" : "ide-hd"); + dev = qdev_new(drive->media_cd ? "ide-cd" : "ide-hd"); qdev_prop_set_uint32(dev, "unit", unit); - qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(drive), - &error_fatal); - qdev_init_nofail(dev); + qdev_prop_set_drive_err(dev, "drive", blk_by_legacy_dinfo(drive), + &error_fatal); + qdev_realize_and_unref(dev, &bus->qbus, &error_fatal); return DO_UPCAST(IDEDevice, qdev, dev); } @@ -187,7 +187,10 @@ static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp) return; } - blkconf_blocksizes(&dev->conf); + if (!blkconf_blocksizes(&dev->conf, errp)) { + return; + } + if (dev->conf.logical_block_size != 512) { error_setg(errp, "logical_block_size must be 512 for IDE"); return; @@ -242,9 +245,8 @@ static void ide_dev_set_bootindex(Object *obj, Visitor *v, const char *name, int32_t boot_index; Error *local_err = NULL; - visit_type_int32(v, name, &boot_index, &local_err); - if (local_err) { - goto out; + if (!visit_type_int32(v, name, &boot_index, errp)) { + return; } /* check whether bootindex is present in fw_boot_order list */ check_boot_index(boot_index, &local_err); @@ -267,7 +269,7 @@ static void ide_dev_instance_init(Object *obj) object_property_add(obj, "bootindex", "int32", ide_dev_get_bootindex, ide_dev_set_bootindex, NULL, NULL); - object_property_set_int(obj, -1, "bootindex", NULL); + object_property_set_int(obj, "bootindex", -1, NULL); } static void ide_hd_realize(IDEDevice *dev, Error **errp) diff --git a/hw/ide/sii3112.c b/hw/ide/sii3112.c index 94d2b57f9535e217963a3ce613eb4c77696857f2..34c347b9c20fa31353ced10bada79fee31fdfff9 100644 --- a/hw/ide/sii3112.c +++ b/hw/ide/sii3112.c @@ -16,10 +16,10 @@ #include "hw/ide/pci.h" #include "qemu/module.h" #include "trace.h" +#include "qom/object.h" #define TYPE_SII3112_PCI "sii3112" -#define SII3112_PCI(obj) OBJECT_CHECK(SiI3112PCIState, (obj), \ - TYPE_SII3112_PCI) +OBJECT_DECLARE_SIMPLE_TYPE(SiI3112PCIState, SII3112_PCI) typedef struct SiI3112Regs { uint32_t confstat; @@ -28,11 +28,11 @@ typedef struct SiI3112Regs { uint8_t swdata; } SiI3112Regs; -typedef struct SiI3112PCIState { +struct SiI3112PCIState { PCIIDEState i; MemoryRegion mmio; SiI3112Regs regs[2]; -} SiI3112PCIState; +}; /* The sii3112_reg_read and sii3112_reg_write functions implement the * Internal Register Space - BAR5 (section 6.7 of the data sheet). diff --git a/hw/ide/trace-events b/hw/ide/trace-events index 2e4162629f4e0022fcbef410231fc1116024af91..6e357685f9b132bd31aafa6e3f7c72d2154a87fc 100644 --- a/hw/ide/trace-events +++ b/hw/ide/trace-events @@ -5,7 +5,7 @@ ide_ioport_read(uint32_t addr, const char *reg, uint32_t val, void *bus, void *s) "IDE PIO rd @ 0x%"PRIx32" (%s); val 0x%02"PRIx32"; bus %p IDEState %p" ide_ioport_write(uint32_t addr, const char *reg, uint32_t val, void *bus, void *s) "IDE PIO wr @ 0x%"PRIx32" (%s); val 0x%02"PRIx32"; bus %p IDEState %p" ide_status_read(uint32_t addr, uint32_t val, void *bus, void *s) "IDE PIO rd @ 0x%"PRIx32" (Alt Status); val 0x%02"PRIx32"; bus %p; IDEState %p" -ide_cmd_write(uint32_t addr, uint32_t val, void *bus) "IDE PIO wr @ 0x%"PRIx32" (Device Control); val 0x%02"PRIx32"; bus %p" +ide_ctrl_write(uint32_t addr, uint32_t val, void *bus) "IDE PIO wr @ 0x%"PRIx32" (Device Control); val 0x%02"PRIx32"; bus %p" # Warning: verbose ide_data_readw(uint32_t addr, uint32_t val, void *bus, void *s) "IDE PIO rd @ 0x%"PRIx32" (Data: Word); val 0x%04"PRIx32"; bus %p; IDEState %p" ide_data_writew(uint32_t addr, uint32_t val, void *bus, void *s) "IDE PIO wr @ 0x%"PRIx32" (Data: Word); val 0x%04"PRIx32"; bus %p; IDEState %p" diff --git a/hw/ide/trace.h b/hw/ide/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..e060e0aef193613ddf8b6d6795a8b917bced55da --- /dev/null +++ b/hw/ide/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_ide.h" diff --git a/hw/input/Makefile.objs b/hw/input/Makefile.objs deleted file mode 100644 index abc1ff03c0a8168508f51ec667bfedea2ccaf329..0000000000000000000000000000000000000000 --- a/hw/input/Makefile.objs +++ /dev/null @@ -1,18 +0,0 @@ -common-obj-$(CONFIG_ADB) += adb.o adb-mouse.o adb-kbd.o -common-obj-y += hid.o -common-obj-$(CONFIG_LM832X) += lm832x.o -common-obj-$(CONFIG_PCKBD) += pckbd.o -common-obj-$(CONFIG_PL050) += pl050.o -common-obj-$(CONFIG_PS2) += ps2.o -common-obj-$(CONFIG_STELLARIS_INPUT) += stellaris_input.o -common-obj-$(CONFIG_TSC2005) += tsc2005.o - -common-obj-$(CONFIG_VIRTIO_INPUT) += virtio-input.o -common-obj-$(CONFIG_VIRTIO_INPUT) += virtio-input-hid.o -common-obj-$(CONFIG_VIRTIO_INPUT_HOST) += virtio-input-host.o -common-obj-$(CONFIG_VHOST_USER_INPUT) += vhost-user-input.o - -common-obj-$(CONFIG_MILKYMIST) += milkymist-softusb.o -common-obj-$(CONFIG_PXA2XX) += pxa2xx_keypad.o -common-obj-$(CONFIG_TSC210X) += tsc210x.o -common-obj-$(CONFIG_LASIPS2) += lasips2.o diff --git a/hw/input/adb-kbd.c b/hw/input/adb-kbd.c index a6d5c9b7c9ac86c2ea64547870e185bc79a9ec1a..a9088c910cc7a88257d8a70f7159944f99edfc4c 100644 --- a/hw/input/adb-kbd.c +++ b/hw/input/adb-kbd.c @@ -30,30 +30,27 @@ #include "hw/input/adb-keys.h" #include "adb-internal.h" #include "trace.h" +#include "qom/object.h" -#define ADB_KEYBOARD(obj) OBJECT_CHECK(KBDState, (obj), TYPE_ADB_KEYBOARD) +OBJECT_DECLARE_TYPE(KBDState, ADBKeyboardClass, ADB_KEYBOARD) -typedef struct KBDState { +struct KBDState { /*< private >*/ ADBDevice parent_obj; /*< public >*/ uint8_t data[128]; int rptr, wptr, count; -} KBDState; +}; -#define ADB_KEYBOARD_CLASS(class) \ - OBJECT_CLASS_CHECK(ADBKeyboardClass, (class), TYPE_ADB_KEYBOARD) -#define ADB_KEYBOARD_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ADBKeyboardClass, (obj), TYPE_ADB_KEYBOARD) -typedef struct ADBKeyboardClass { +struct ADBKeyboardClass { /*< private >*/ ADBDeviceClass parent_class; /*< public >*/ DeviceRealize parent_realize; -} ADBKeyboardClass; +}; /* The adb keyboard doesn't have every key imaginable */ #define NO_KEY 0xff @@ -243,7 +240,7 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf, olen = 0; switch (cmd) { case ADB_WRITEREG: - trace_adb_kbd_writereg(reg, buf[1]); + trace_adb_device_kbd_writereg(reg, buf[1]); switch (reg) { case 2: /* LED status */ @@ -256,24 +253,22 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf, case ADB_CMD_CHANGE_ID_AND_ACT: case ADB_CMD_CHANGE_ID_AND_ENABLE: d->devaddr = buf[1] & 0xf; - trace_adb_kbd_request_change_addr(d->devaddr); + trace_adb_device_kbd_request_change_addr(d->devaddr); break; default: - if (!d->disable_direct_reg3_writes) { - d->devaddr = buf[1] & 0xf; - - /* we support handlers: - * 1: Apple Standard Keyboard - * 2: Apple Extended Keyboard (LShift = RShift) - * 3: Apple Extended Keyboard (LShift != RShift) - */ - if (buf[2] == 1 || buf[2] == 2 || buf[2] == 3) { - d->handler = buf[2]; - } - - trace_adb_kbd_request_change_addr_and_handler(d->devaddr, - d->handler); + d->devaddr = buf[1] & 0xf; + /* + * we support handlers: + * 1: Apple Standard Keyboard + * 2: Apple Extended Keyboard (LShift = RShift) + * 3: Apple Extended Keyboard (LShift != RShift) + */ + if (buf[2] == 1 || buf[2] == 2 || buf[2] == 3) { + d->handler = buf[2]; } + + trace_adb_device_kbd_request_change_addr_and_handler( + d->devaddr, d->handler); break; } } @@ -296,12 +291,19 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf, olen = 2; break; } - trace_adb_kbd_readreg(reg, obuf[0], obuf[1]); + trace_adb_device_kbd_readreg(reg, obuf[0], obuf[1]); break; } return olen; } +static bool adb_kbd_has_data(ADBDevice *d) +{ + KBDState *s = ADB_KEYBOARD(d); + + return s->count > 0; +} + /* This is where keyboard events enter this file */ static void adb_keyboard_event(DeviceState *dev, QemuConsole *src, InputEvent *evt) @@ -316,7 +318,7 @@ static void adb_keyboard_event(DeviceState *dev, QemuConsole *src, /* FIXME: take handler into account when translating qcode */ keycode = qcode_to_adb_keycode[qcode]; if (keycode == NO_KEY) { /* We don't want to send this to the guest */ - trace_adb_kbd_no_key(); + trace_adb_device_kbd_no_key(); return; } if (evt->u.key.data->down == false) { /* if key release event */ @@ -384,6 +386,7 @@ static void adb_kbd_class_init(ObjectClass *oc, void *data) set_bit(DEVICE_CATEGORY_INPUT, dc->categories); adc->devreq = adb_kbd_request; + adc->devhasdata = adb_kbd_has_data; dc->reset = adb_kbd_reset; dc->vmsd = &vmstate_adb_kbd; } diff --git a/hw/input/adb-mouse.c b/hw/input/adb-mouse.c index aeba41bddd30030076264c79c27a8ef90bc41c67..e6b341f0280809caab87dc6d61316dd979df442a 100644 --- a/hw/input/adb-mouse.c +++ b/hw/input/adb-mouse.c @@ -29,30 +29,27 @@ #include "qemu/module.h" #include "adb-internal.h" #include "trace.h" +#include "qom/object.h" -#define ADB_MOUSE(obj) OBJECT_CHECK(MouseState, (obj), TYPE_ADB_MOUSE) +OBJECT_DECLARE_TYPE(MouseState, ADBMouseClass, ADB_MOUSE) -typedef struct MouseState { +struct MouseState { /*< public >*/ ADBDevice parent_obj; /*< private >*/ int buttons_state, last_buttons_state; int dx, dy, dz; -} MouseState; +}; -#define ADB_MOUSE_CLASS(class) \ - OBJECT_CLASS_CHECK(ADBMouseClass, (class), TYPE_ADB_MOUSE) -#define ADB_MOUSE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ADBMouseClass, (obj), TYPE_ADB_MOUSE) -typedef struct ADBMouseClass { +struct ADBMouseClass { /*< public >*/ ADBDeviceClass parent_class; /*< private >*/ DeviceRealize parent_realize; -} ADBMouseClass; +}; static void adb_mouse_event(void *opaque, int dx1, int dy1, int dz1, int buttons_state) @@ -121,7 +118,7 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf, s->dx = 0; s->dy = 0; s->dz = 0; - trace_adb_mouse_flush(); + trace_adb_device_mouse_flush(); return 0; } @@ -130,11 +127,21 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf, olen = 0; switch (cmd) { case ADB_WRITEREG: - trace_adb_mouse_writereg(reg, buf[1]); + trace_adb_device_mouse_writereg(reg, buf[1]); switch (reg) { case 2: break; case 3: + /* + * MacOS 9 has a bug in its ADB driver whereby after configuring + * the ADB bus devices it sends another write of invalid length + * to reg 3. Make sure we ignore it to prevent an address clash + * with the previous device. + */ + if (len != 3) { + return 0; + } + switch (buf[2]) { case ADB_CMD_SELF_TEST: break; @@ -142,30 +149,28 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf, case ADB_CMD_CHANGE_ID_AND_ACT: case ADB_CMD_CHANGE_ID_AND_ENABLE: d->devaddr = buf[1] & 0xf; - trace_adb_mouse_request_change_addr(d->devaddr); + trace_adb_device_mouse_request_change_addr(d->devaddr); break; default: - if (!d->disable_direct_reg3_writes) { - d->devaddr = buf[1] & 0xf; - - /* we support handlers: - * 0x01: Classic Apple Mouse Protocol / 100 cpi operations - * 0x02: Classic Apple Mouse Protocol / 200 cpi operations - * we don't support handlers (at least): - * 0x03: Mouse systems A3 trackball - * 0x04: Extended Apple Mouse Protocol - * 0x2f: Microspeed mouse - * 0x42: Macally - * 0x5f: Microspeed mouse - * 0x66: Microspeed mouse - */ - if (buf[2] == 1 || buf[2] == 2) { - d->handler = buf[2]; - } - - trace_adb_mouse_request_change_addr_and_handler( - d->devaddr, d->handler); + d->devaddr = buf[1] & 0xf; + /* + * we support handlers: + * 0x01: Classic Apple Mouse Protocol / 100 cpi operations + * 0x02: Classic Apple Mouse Protocol / 200 cpi operations + * we don't support handlers (at least): + * 0x03: Mouse systems A3 trackball + * 0x04: Extended Apple Mouse Protocol + * 0x2f: Microspeed mouse + * 0x42: Macally + * 0x5f: Microspeed mouse + * 0x66: Microspeed mouse + */ + if (buf[2] == 1 || buf[2] == 2) { + d->handler = buf[2]; } + + trace_adb_device_mouse_request_change_addr_and_handler( + d->devaddr, d->handler); break; } } @@ -183,12 +188,20 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf, olen = 2; break; } - trace_adb_mouse_readreg(reg, obuf[0], obuf[1]); + trace_adb_device_mouse_readreg(reg, obuf[0], obuf[1]); break; } return olen; } +static bool adb_mouse_has_data(ADBDevice *d) +{ + MouseState *s = ADB_MOUSE(d); + + return !(s->last_buttons_state == s->buttons_state && + s->dx == 0 && s->dy == 0); +} + static void adb_mouse_reset(DeviceState *dev) { ADBDevice *d = ADB_DEVICE(dev); @@ -244,6 +257,7 @@ static void adb_mouse_class_init(ObjectClass *oc, void *data) set_bit(DEVICE_CATEGORY_INPUT, dc->categories); adc->devreq = adb_mouse_request; + adc->devhasdata = adb_mouse_has_data; dc->reset = adb_mouse_reset; dc->vmsd = &vmstate_adb_mouse; } diff --git a/hw/input/adb.c b/hw/input/adb.c index b1ac4a385295cbc0a7ed732510ec45e7e4dd932e..84331b9fce6fdbc89f8d812fc8dbef89eed8f104 100644 --- a/hw/input/adb.c +++ b/hw/input/adb.c @@ -27,41 +27,85 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "qemu/module.h" +#include "qemu/timer.h" #include "adb-internal.h" +#include "trace.h" /* error codes */ #define ADB_RET_NOTPRESENT (-2) +static const char *adb_commands[] = { + "RESET", "FLUSH", "(Reserved 0x2)", "(Reserved 0x3)", + "Reserved (0x4)", "(Reserved 0x5)", "(Reserved 0x6)", "(Reserved 0x7)", + "LISTEN r0", "LISTEN r1", "LISTEN r2", "LISTEN r3", + "TALK r0", "TALK r1", "TALK r2", "TALK r3", +}; + static void adb_device_reset(ADBDevice *d) { qdev_reset_all(DEVICE(d)); } -int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len) +static int do_adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, + int len) { ADBDevice *d; - int devaddr, cmd, i; + ADBDeviceClass *adc; + int devaddr, cmd, olen, i; cmd = buf[0] & 0xf; if (cmd == ADB_BUSRESET) { - for(i = 0; i < s->nb_devices; i++) { + for (i = 0; i < s->nb_devices; i++) { d = s->devices[i]; adb_device_reset(d); } + s->status = 0; return 0; } + + s->pending = 0; + for (i = 0; i < s->nb_devices; i++) { + d = s->devices[i]; + adc = ADB_DEVICE_GET_CLASS(d); + + if (adc->devhasdata(d)) { + s->pending |= (1 << d->devaddr); + } + } + + s->status = 0; devaddr = buf[0] >> 4; - for(i = 0; i < s->nb_devices; i++) { + for (i = 0; i < s->nb_devices; i++) { d = s->devices[i]; + adc = ADB_DEVICE_GET_CLASS(d); + if (d->devaddr == devaddr) { - ADBDeviceClass *adc = ADB_DEVICE_GET_CLASS(d); - return adc->devreq(d, obuf, buf, len); + olen = adc->devreq(d, obuf, buf, len); + if (!olen) { + s->status |= ADB_STATUS_BUSTIMEOUT; + } + return olen; } } + + s->status |= ADB_STATUS_BUSTIMEOUT; return ADB_RET_NOTPRESENT; } -/* XXX: move that to cuda ? */ +int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len) +{ + int ret; + + trace_adb_bus_request(buf[0] >> 4, adb_commands[buf[0] & 0xf], len); + + assert(s->autopoll_blocked); + + ret = do_adb_request(s, obuf, buf, len); + + trace_adb_bus_request_done(buf[0] >> 4, adb_commands[buf[0] & 0xf], ret); + return ret; +} + int adb_poll(ADBBusState *s, uint8_t *obuf, uint16_t poll_mask) { ADBDevice *d; @@ -69,18 +113,20 @@ int adb_poll(ADBBusState *s, uint8_t *obuf, uint16_t poll_mask) uint8_t buf[1]; olen = 0; - for(i = 0; i < s->nb_devices; i++) { - if (s->poll_index >= s->nb_devices) + for (i = 0; i < s->nb_devices; i++) { + if (s->poll_index >= s->nb_devices) { s->poll_index = 0; + } d = s->devices[s->poll_index]; if ((1 << d->devaddr) & poll_mask) { buf[0] = ADB_READREG | (d->devaddr << 4); - olen = adb_request(s, obuf + 1, buf, 1); + olen = do_adb_request(s, obuf + 1, buf, 1); /* if there is data, we poll again the same device */ if (olen > 0) { + s->status |= ADB_STATUS_POLLREPLY; obuf[0] = buf[0]; olen++; - break; + return olen; } } s->poll_index++; @@ -88,10 +134,145 @@ int adb_poll(ADBBusState *s, uint8_t *obuf, uint16_t poll_mask) return olen; } +void adb_set_autopoll_enabled(ADBBusState *s, bool enabled) +{ + if (s->autopoll_enabled != enabled) { + s->autopoll_enabled = enabled; + if (s->autopoll_enabled) { + timer_mod(s->autopoll_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + + s->autopoll_rate_ms); + } else { + timer_del(s->autopoll_timer); + } + } +} + +void adb_set_autopoll_rate_ms(ADBBusState *s, int rate_ms) +{ + s->autopoll_rate_ms = rate_ms; + + if (s->autopoll_enabled) { + timer_mod(s->autopoll_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + + s->autopoll_rate_ms); + } +} + +void adb_set_autopoll_mask(ADBBusState *s, uint16_t mask) +{ + if (s->autopoll_mask != mask) { + s->autopoll_mask = mask; + if (s->autopoll_enabled && s->autopoll_mask) { + timer_mod(s->autopoll_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + + s->autopoll_rate_ms); + } else { + timer_del(s->autopoll_timer); + } + } +} + +void adb_autopoll_block(ADBBusState *s) +{ + s->autopoll_blocked = true; + trace_adb_bus_autopoll_block(s->autopoll_blocked); + + if (s->autopoll_enabled) { + timer_del(s->autopoll_timer); + } +} + +void adb_autopoll_unblock(ADBBusState *s) +{ + s->autopoll_blocked = false; + trace_adb_bus_autopoll_block(s->autopoll_blocked); + + if (s->autopoll_enabled) { + timer_mod(s->autopoll_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + + s->autopoll_rate_ms); + } +} + +static void adb_autopoll(void *opaque) +{ + ADBBusState *s = opaque; + + if (!s->autopoll_blocked) { + trace_adb_bus_autopoll_cb(s->autopoll_mask); + s->autopoll_cb(s->autopoll_cb_opaque); + trace_adb_bus_autopoll_cb_done(s->autopoll_mask); + } + + timer_mod(s->autopoll_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + + s->autopoll_rate_ms); +} + +void adb_register_autopoll_callback(ADBBusState *s, void (*cb)(void *opaque), + void *opaque) +{ + s->autopoll_cb = cb; + s->autopoll_cb_opaque = opaque; +} + +static const VMStateDescription vmstate_adb_bus = { + .name = "adb_bus", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_TIMER_PTR(autopoll_timer, ADBBusState), + VMSTATE_BOOL(autopoll_enabled, ADBBusState), + VMSTATE_UINT8(autopoll_rate_ms, ADBBusState), + VMSTATE_UINT16(autopoll_mask, ADBBusState), + VMSTATE_BOOL(autopoll_blocked, ADBBusState), + VMSTATE_END_OF_LIST() + } +}; + +static void adb_bus_reset(BusState *qbus) +{ + ADBBusState *adb_bus = ADB_BUS(qbus); + + adb_bus->autopoll_enabled = false; + adb_bus->autopoll_mask = 0xffff; + adb_bus->autopoll_rate_ms = 20; +} + +static void adb_bus_realize(BusState *qbus, Error **errp) +{ + ADBBusState *adb_bus = ADB_BUS(qbus); + + adb_bus->autopoll_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, adb_autopoll, + adb_bus); + + vmstate_register(NULL, -1, &vmstate_adb_bus, adb_bus); +} + +static void adb_bus_unrealize(BusState *qbus) +{ + ADBBusState *adb_bus = ADB_BUS(qbus); + + timer_del(adb_bus->autopoll_timer); + + vmstate_unregister(NULL, &vmstate_adb_bus, adb_bus); +} + +static void adb_bus_class_init(ObjectClass *klass, void *data) +{ + BusClass *k = BUS_CLASS(klass); + + k->realize = adb_bus_realize; + k->unrealize = adb_bus_unrealize; + k->reset = adb_bus_reset; +} + static const TypeInfo adb_bus_type_info = { .name = TYPE_ADB_BUS, .parent = TYPE_BUS, .instance_size = sizeof(ADBBusState), + .class_init = adb_bus_class_init, }; const VMStateDescription vmstate_adb_device = { @@ -117,24 +298,18 @@ static void adb_device_realizefn(DeviceState *dev, Error **errp) bus->devices[bus->nb_devices++] = d; } -static Property adb_device_properties[] = { - DEFINE_PROP_BOOL("disable-direct-reg3-writes", ADBDevice, - disable_direct_reg3_writes, false), - DEFINE_PROP_END_OF_LIST(), -}; - static void adb_device_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); dc->realize = adb_device_realizefn; - device_class_set_props(dc, adb_device_properties); dc->bus_type = TYPE_ADB_BUS; } static const TypeInfo adb_device_type_info = { .name = TYPE_ADB_DEVICE, .parent = TYPE_DEVICE, + .class_size = sizeof(ADBDeviceClass), .instance_size = sizeof(ADBDevice), .abstract = true, .class_init = adb_device_class_init, diff --git a/hw/input/lm832x.c b/hw/input/lm832x.c index aa629ddbf197d63b6b32d4ad9b179857c6ea05a2..4cb1e9de01f2fc6fa8fccb3354d3b262be0403e1 100644 --- a/hw/input/lm832x.c +++ b/hw/input/lm832x.c @@ -25,11 +25,12 @@ #include "qemu/module.h" #include "qemu/timer.h" #include "ui/console.h" +#include "qom/object.h" #define TYPE_LM8323 "lm8323" -#define LM8323(obj) OBJECT_CHECK(LM823KbdState, (obj), TYPE_LM8323) +OBJECT_DECLARE_SIMPLE_TYPE(LM823KbdState, LM8323) -typedef struct { +struct LM823KbdState { I2CSlave parent_obj; uint8_t i2c_dir; @@ -72,7 +73,7 @@ typedef struct { uint8_t addr[3]; QEMUTimer *tm[3]; } pwm; -} LM823KbdState; +}; #define INT_KEYPAD (1 << 0) #define INT_ERROR (1 << 3) diff --git a/hw/input/meson.build b/hw/input/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..e7285b15ae6de1a1af51a7e4349a9a392e69571c --- /dev/null +++ b/hw/input/meson.build @@ -0,0 +1,18 @@ +softmmu_ss.add(files('hid.c')) +softmmu_ss.add(when: 'CONFIG_ADB', if_true: files('adb.c', 'adb-mouse.c', 'adb-kbd.c')) +softmmu_ss.add(when: 'CONFIG_LM832X', if_true: files('lm832x.c')) +softmmu_ss.add(when: 'CONFIG_PCKBD', if_true: files('pckbd.c')) +softmmu_ss.add(when: 'CONFIG_PL050', if_true: files('pl050.c')) +softmmu_ss.add(when: 'CONFIG_PS2', if_true: files('ps2.c')) +softmmu_ss.add(when: 'CONFIG_STELLARIS_INPUT', if_true: files('stellaris_input.c')) +softmmu_ss.add(when: 'CONFIG_TSC2005', if_true: files('tsc2005.c')) + +softmmu_ss.add(when: 'CONFIG_VIRTIO_INPUT', if_true: files('virtio-input.c')) +softmmu_ss.add(when: 'CONFIG_VIRTIO_INPUT', if_true: files('virtio-input-hid.c')) +softmmu_ss.add(when: 'CONFIG_VIRTIO_INPUT_HOST', if_true: files('virtio-input-host.c')) +softmmu_ss.add(when: 'CONFIG_VHOST_USER_INPUT', if_true: files('vhost-user-input.c')) + +softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-softusb.c')) +softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_keypad.c')) +softmmu_ss.add(when: 'CONFIG_TSC210X', if_true: files('tsc210x.c')) +softmmu_ss.add(when: 'CONFIG_LASIPS2', if_true: files('lasips2.c')) diff --git a/hw/input/milkymist-softusb.c b/hw/input/milkymist-softusb.c index 3e0a7eb0bd519f5c1157034a1a8cd9d199bb8d96..d885c708d7cbaa5ca77a587e331d4c77077749f0 100644 --- a/hw/input/milkymist-softusb.c +++ b/hw/input/milkymist-softusb.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -32,6 +32,7 @@ #include "hw/qdev-properties.h" #include "qemu/error-report.h" #include "qemu/module.h" +#include "qom/object.h" enum { R_CTRL = 0, @@ -50,8 +51,7 @@ enum { #define COMLOC_KEVT_BASE 0x1143 #define TYPE_MILKYMIST_SOFTUSB "milkymist-softusb" -#define MILKYMIST_SOFTUSB(obj) \ - OBJECT_CHECK(MilkymistSoftUsbState, (obj), TYPE_MILKYMIST_SOFTUSB) +OBJECT_DECLARE_SIMPLE_TYPE(MilkymistSoftUsbState, MILKYMIST_SOFTUSB) struct MilkymistSoftUsbState { SysBusDevice parent_obj; @@ -80,7 +80,6 @@ struct MilkymistSoftUsbState { /* keyboard state */ uint8_t kbd_hid_buffer[8]; }; -typedef struct MilkymistSoftUsbState MilkymistSoftUsbState; static uint64_t softusb_read(void *opaque, hwaddr addr, unsigned size) diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c index 60a41303203af4c17b0484537af600424f4f6429..dde85ba6c683e851961160296b2fd8a986f3e49b 100644 --- a/hw/input/pckbd.c +++ b/hw/input/pckbd.c @@ -26,6 +26,7 @@ #include "qemu/log.h" #include "hw/isa/isa.h" #include "migration/vmstate.h" +#include "hw/acpi/aml-build.h" #include "hw/input/ps2.h" #include "hw/irq.h" #include "hw/input/i8042.h" @@ -480,8 +481,6 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, qemu_register_reset(kbd_reset, s); } -#define I8042(obj) OBJECT_CHECK(ISAKBDState, (obj), TYPE_I8042) - struct ISAKBDState { ISADevice parent_obj; @@ -561,12 +560,42 @@ static void i8042_realizefn(DeviceState *dev, Error **errp) qemu_register_reset(kbd_reset, s); } +static void i8042_build_aml(ISADevice *isadev, Aml *scope) +{ + Aml *kbd; + Aml *mou; + Aml *crs; + + crs = aml_resource_template(); + aml_append(crs, aml_io(AML_DECODE16, 0x0060, 0x0060, 0x01, 0x01)); + aml_append(crs, aml_io(AML_DECODE16, 0x0064, 0x0064, 0x01, 0x01)); + aml_append(crs, aml_irq_no_flags(1)); + + kbd = aml_device("KBD"); + aml_append(kbd, aml_name_decl("_HID", aml_eisaid("PNP0303"))); + aml_append(kbd, aml_name_decl("_STA", aml_int(0xf))); + aml_append(kbd, aml_name_decl("_CRS", crs)); + + crs = aml_resource_template(); + aml_append(crs, aml_irq_no_flags(12)); + + mou = aml_device("MOU"); + aml_append(mou, aml_name_decl("_HID", aml_eisaid("PNP0F13"))); + aml_append(mou, aml_name_decl("_STA", aml_int(0xf))); + aml_append(mou, aml_name_decl("_CRS", crs)); + + aml_append(scope, kbd); + aml_append(scope, mou); +} + static void i8042_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *isa = ISA_DEVICE_CLASS(klass); dc->realize = i8042_realizefn; dc->vmsd = &vmstate_kbd_isa; + isa->build_aml = i8042_build_aml; set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } diff --git a/hw/input/pl050.c b/hw/input/pl050.c index 1123037b380512cef6218dc699e8bd0f22e14a87..d279b6c1488c45d456479193752f895bdc2c1e81 100644 --- a/hw/input/pl050.c +++ b/hw/input/pl050.c @@ -14,11 +14,12 @@ #include "hw/irq.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" #define TYPE_PL050 "pl050" -#define PL050(obj) OBJECT_CHECK(PL050State, (obj), TYPE_PL050) +OBJECT_DECLARE_SIMPLE_TYPE(PL050State, PL050) -typedef struct PL050State { +struct PL050State { SysBusDevice parent_obj; MemoryRegion iomem; @@ -29,7 +30,7 @@ typedef struct PL050State { int pending; qemu_irq irq; bool is_mouse; -} PL050State; +}; static const VMStateDescription vmstate_pl050 = { .name = "pl050", diff --git a/hw/input/ps2.c b/hw/input/ps2.c index f8746d2f52cbc377508ee8cba12a9df31321a38a..72cdb80ae1cdd4d84d3b68e24c627476b5fad614 100644 --- a/hw/input/ps2.c +++ b/hw/input/ps2.c @@ -33,12 +33,6 @@ #include "trace.h" -/* debug PC keyboard */ -//#define DEBUG_KBD - -/* debug PC keyboard : only mouse */ -//#define DEBUG_MOUSE - /* Keyboard Commands */ #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ #define KBD_CMD_ECHO 0xEE @@ -790,9 +784,6 @@ void ps2_write_mouse(void *opaque, int val) PS2MouseState *s = (PS2MouseState *)opaque; trace_ps2_write_mouse(opaque, val); -#ifdef DEBUG_MOUSE - printf("kbd: write mouse 0x%02x\n", val); -#endif switch(s->common.write_cmd) { default: case -1: diff --git a/hw/input/pxa2xx_keypad.c b/hw/input/pxa2xx_keypad.c index 31862a7d16c4cd776b92f04063597b05de4cc157..7f2f739fb3359c7fa5aeaebe09deb18fe616d00e 100644 --- a/hw/input/pxa2xx_keypad.c +++ b/hw/input/pxa2xx_keypad.c @@ -12,7 +12,7 @@ */ #include "qemu/osdep.h" -#include "hw/hw.h" +#include "qemu/log.h" #include "hw/irq.h" #include "migration/vmstate.h" #include "hw/arm/pxa.h" @@ -192,10 +192,8 @@ static uint64_t pxa2xx_keypad_read(void *opaque, hwaddr offset, s->kpc &= ~(KPC_DI); qemu_irq_lower(s->irq); return tmp; - break; case KPDK: return s->kpdk; - break; case KPREC: tmp = s->kprec; if(tmp & KPREC_OF1) @@ -207,33 +205,27 @@ static uint64_t pxa2xx_keypad_read(void *opaque, hwaddr offset, if(tmp & KPREC_UF0) s->kprec &= ~(KPREC_UF0); return tmp; - break; case KPMK: tmp = s->kpmk; if(tmp & KPMK_MKP) s->kpmk &= ~(KPMK_MKP); return tmp; - break; case KPAS: return s->kpas; - break; case KPASMKP0: return s->kpasmkp[0]; - break; case KPASMKP1: return s->kpasmkp[1]; - break; case KPASMKP2: return s->kpasmkp[2]; - break; case KPASMKP3: return s->kpasmkp[3]; - break; case KPKDI: return s->kpkdi; - break; default: - hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad read offset 0x%"HWADDR_PRIx"\n", + __func__, offset); } return 0; @@ -280,7 +272,9 @@ static void pxa2xx_keypad_write(void *opaque, hwaddr offset, break; default: - hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad write offset 0x%"HWADDR_PRIx"\n", + __func__, offset); } } diff --git a/hw/input/trace-events b/hw/input/trace-events index a2888fd10c1976e87847eaa095780a1d8c398d63..1dd8ad6018aac1acafba0f006d0d6858270f3321 100644 --- a/hw/input/trace-events +++ b/hw/input/trace-events @@ -1,18 +1,25 @@ # See docs/devel/tracing.txt for syntax documentation. # adb-kbd.c -adb_kbd_no_key(void) "Ignoring NO_KEY" -adb_kbd_writereg(int reg, uint8_t val) "reg %d val 0x%2.2x" -adb_kbd_readreg(int reg, uint8_t val0, uint8_t val1) "reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x" -adb_kbd_request_change_addr(int devaddr) "change addr to 0x%x" -adb_kbd_request_change_addr_and_handler(int devaddr, int handler) "change addr and handler to 0x%x, 0x%x" +adb_device_kbd_no_key(void) "Ignoring NO_KEY" +adb_device_kbd_writereg(int reg, uint8_t val) "reg %d val 0x%2.2x" +adb_device_kbd_readreg(int reg, uint8_t val0, uint8_t val1) "reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x" +adb_device_kbd_request_change_addr(int devaddr) "change addr to 0x%x" +adb_device_kbd_request_change_addr_and_handler(int devaddr, int handler) "change addr and handler to 0x%x, 0x%x" # adb-mouse.c -adb_mouse_flush(void) "flush" -adb_mouse_writereg(int reg, uint8_t val) "reg %d val 0x%2.2x" -adb_mouse_readreg(int reg, uint8_t val0, uint8_t val1) "reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x" -adb_mouse_request_change_addr(int devaddr) "change addr to 0x%x" -adb_mouse_request_change_addr_and_handler(int devaddr, int handler) "change addr and handler to 0x%x, 0x%x" +adb_device_mouse_flush(void) "flush" +adb_device_mouse_writereg(int reg, uint8_t val) "reg %d val 0x%2.2x" +adb_device_mouse_readreg(int reg, uint8_t val0, uint8_t val1) "reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x" +adb_device_mouse_request_change_addr(int devaddr) "change addr to 0x%x" +adb_device_mouse_request_change_addr_and_handler(int devaddr, int handler) "change addr and handler to 0x%x, 0x%x" + +# adb.c +adb_bus_request(uint8_t addr, const char *cmd, int size) "device 0x%x %s cmdsize=%d" +adb_bus_request_done(uint8_t addr, const char *cmd, int size) "device 0x%x %s replysize=%d" +adb_bus_autopoll_block(bool blocked) "blocked: %d" +adb_bus_autopoll_cb(uint16_t mask) "executing autopoll_cb with autopoll mask 0x%x" +adb_bus_autopoll_cb_done(uint16_t mask) "done executing autopoll_cb with autopoll mask 0x%x" # pckbd.c pckbd_kbd_read_data(uint32_t val) "0x%02x" diff --git a/hw/input/trace.h b/hw/input/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..d1cc5d924cc22ca05a487073680d139ff8beaa5f --- /dev/null +++ b/hw/input/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_input.h" diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c index 09cf2609854fa1e40c7c4bb82aa06765c27c8f9a..a7a244a95dbb50dc0cc182a9a6b4af2e55a38723 100644 --- a/hw/input/virtio-input-hid.c +++ b/hw/input/virtio-input-hid.c @@ -12,7 +12,6 @@ #include "hw/qdev-properties.h" #include "hw/virtio/virtio-input.h" -#undef CONFIG_CURSES #include "ui/console.h" #include "standard-headers/linux/input.h" diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig index a189d6fedd41b4f16d59cb8443685d40593e11e2..d07954086a59cfbdc7a6602f0139bd0b7ce24ed2 100644 --- a/hw/intc/Kconfig +++ b/hw/intc/Kconfig @@ -61,3 +61,15 @@ config S390_FLIC_KVM config OMPIC bool + +config RX_ICU + bool + +config LOONGSON_LIOINTC + bool + +config SIFIVE_CLINT + bool + +config SIFIVE_PLIC + bool diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs deleted file mode 100644 index f726d875327637446186255abb53f3bbdd2e740d..0000000000000000000000000000000000000000 --- a/hw/intc/Makefile.objs +++ /dev/null @@ -1,51 +0,0 @@ -common-obj-$(CONFIG_HEATHROW_PIC) += heathrow_pic.o -common-obj-$(CONFIG_I8259) += i8259_common.o i8259.o -common-obj-$(CONFIG_PL190) += pl190.o -common-obj-$(CONFIG_PUV3) += puv3_intc.o -common-obj-$(CONFIG_XILINX) += xilinx_intc.o -common-obj-$(CONFIG_XLNX_ZYNQMP_PMU) += xlnx-pmu-iomod-intc.o -common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp-ipi.o -common-obj-$(CONFIG_ETRAXFS) += etraxfs_pic.o -common-obj-$(CONFIG_IMX) += imx_avic.o imx_gpcv2.o -common-obj-$(CONFIG_LM32) += lm32_pic.o -common-obj-$(CONFIG_REALVIEW) += realview_gic.o -common-obj-$(CONFIG_SLAVIO) += slavio_intctl.o -common-obj-$(CONFIG_IOAPIC) += ioapic_common.o -common-obj-$(CONFIG_ARM_GIC) += arm_gic_common.o -common-obj-$(CONFIG_ARM_GIC) += arm_gic.o -common-obj-$(CONFIG_ARM_GIC) += arm_gicv2m.o -common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_common.o -common-obj-$(CONFIG_ARM_GIC) += arm_gicv3.o -common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_dist.o -common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_redist.o -common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_its_common.o -common-obj-$(CONFIG_OPENPIC) += openpic.o -common-obj-y += intc.o - -obj-$(CONFIG_APIC) += apic.o apic_common.o -obj-$(CONFIG_ARM_GIC_KVM) += arm_gic_kvm.o -obj-$(call land,$(CONFIG_ARM_GIC_KVM),$(TARGET_AARCH64)) += arm_gicv3_kvm.o -obj-$(call land,$(CONFIG_ARM_GIC_KVM),$(TARGET_AARCH64)) += arm_gicv3_its_kvm.o -obj-$(CONFIG_ARM_V7M) += armv7m_nvic.o -obj-$(CONFIG_EXYNOS4) += exynos4210_gic.o exynos4210_combiner.o -obj-$(CONFIG_GRLIB) += grlib_irqmp.o -obj-$(CONFIG_IOAPIC) += ioapic.o -obj-$(CONFIG_OMAP) += omap_intc.o -obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o -obj-$(CONFIG_RASPI) += bcm2835_ic.o bcm2836_control.o -obj-$(CONFIG_SH4) += sh_intc.o -obj-$(CONFIG_XICS) += xics.o -obj-$(CONFIG_XICS_SPAPR) += xics_spapr.o -obj-$(CONFIG_XICS_KVM) += xics_kvm.o -obj-$(CONFIG_XIVE) += xive.o -obj-$(CONFIG_XIVE_SPAPR) += spapr_xive.o -obj-$(CONFIG_XIVE_KVM) += spapr_xive_kvm.o -obj-$(CONFIG_POWERNV) += xics_pnv.o pnv_xive.o -obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o -obj-$(CONFIG_S390_FLIC) += s390_flic.o -obj-$(CONFIG_S390_FLIC_KVM) += s390_flic_kvm.o -obj-$(CONFIG_ASPEED_SOC) += aspeed_vic.o -obj-$(CONFIG_ARM_GIC) += arm_gicv3_cpuif.o -obj-$(CONFIG_MIPS_CPS) += mips_gic.o -obj-$(CONFIG_NIOS2) += nios2_iic.o -obj-$(CONFIG_OMPIC) += ompic.o diff --git a/hw/intc/apic.c b/hw/intc/apic.c index 6b46839ef409987c290a62c6fb10997b98eb010c..1c8be40d8b44bfb8f15c943d94ff7f412113a7d8 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -28,6 +28,7 @@ #include "trace.h" #include "hw/i386/apic-msidef.h" #include "qapi/error.h" +#include "qom/object.h" #define MAX_APICS 255 #define MAX_APIC_WORDS 8 @@ -39,8 +40,9 @@ static APICCommonState *local_apics[MAX_APICS + 1]; #define TYPE_APIC "apic" -#define APIC(obj) \ - OBJECT_CHECK(APICCommonState, (obj), TYPE_APIC) +/*This is reusing the APICCommonState typedef from APIC_COMMON */ +DECLARE_INSTANCE_CHECKER(APICCommonState, APIC, + TYPE_APIC) static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode); static void apic_update_irq(APICCommonState *s); @@ -615,24 +617,6 @@ int apic_accept_pic_intr(DeviceState *dev) return 0; } -static uint32_t apic_get_current_count(APICCommonState *s) -{ - int64_t d; - uint32_t val; - d = (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->initial_count_load_time) >> - s->count_shift; - if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) { - /* periodic */ - val = s->initial_count - (d % ((uint64_t)s->initial_count + 1)); - } else { - if (d >= s->initial_count) - val = 0; - else - val = s->initial_count - d; - } - return val; -} - static void apic_timer_update(APICCommonState *s, int64_t current_time) { if (apic_next_timer(s, current_time)) { diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index 7da2862b3d6a39fb58d372302178ea4b0b01d4e6..502e94effc58ac7da3c5bd0f30ea525b86bbbef8 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -189,6 +189,25 @@ bool apic_next_timer(APICCommonState *s, int64_t current_time) return true; } +uint32_t apic_get_current_count(APICCommonState *s) +{ + int64_t d; + uint32_t val; + d = (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->initial_count_load_time) >> + s->count_shift; + if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) { + /* periodic */ + val = s->initial_count - (d % ((uint64_t)s->initial_count + 1)); + } else { + if (d >= s->initial_count) { + val = 0; + } else { + val = s->initial_count - d; + } + } + return val; +} + void apic_init_reset(DeviceState *dev) { APICCommonState *s; @@ -420,7 +439,6 @@ static void apic_common_set_id(Object *obj, Visitor *v, const char *name, { APICCommonState *s = APIC_COMMON(obj); DeviceState *dev = DEVICE(obj); - Error *local_err = NULL; uint32_t value; if (dev->realized) { @@ -428,9 +446,7 @@ static void apic_common_set_id(Object *obj, Visitor *v, const char *name, return; } - visit_type_uint32(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_uint32(v, name, &value, errp)) { return; } diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c index d7df423a7a3793798e4a35e4d35adf14ba182e73..9494185cf467e3ed82592f22f182df28f0f9b210 100644 --- a/hw/intc/arm_gic_kvm.c +++ b/hw/intc/arm_gic_kvm.c @@ -29,20 +29,19 @@ #include "kvm_arm.h" #include "gic_internal.h" #include "vgic_common.h" +#include "qom/object.h" #define TYPE_KVM_ARM_GIC "kvm-arm-gic" -#define KVM_ARM_GIC(obj) \ - OBJECT_CHECK(GICState, (obj), TYPE_KVM_ARM_GIC) -#define KVM_ARM_GIC_CLASS(klass) \ - OBJECT_CLASS_CHECK(KVMARMGICClass, (klass), TYPE_KVM_ARM_GIC) -#define KVM_ARM_GIC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(KVMARMGICClass, (obj), TYPE_KVM_ARM_GIC) - -typedef struct KVMARMGICClass { +typedef struct KVMARMGICClass KVMARMGICClass; +/* This is reusing the GICState typedef from ARM_GIC_COMMON */ +DECLARE_OBJ_CHECKERS(GICState, KVMARMGICClass, + KVM_ARM_GIC, TYPE_KVM_ARM_GIC) + +struct KVMARMGICClass { ARMGICCommonClass parent_class; DeviceRealize parent_realize; void (*parent_reset)(DeviceState *dev); -} KVMARMGICClass; +}; void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level) { @@ -517,9 +516,7 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) if (!kvm_arm_gic_can_save_restore(s)) { error_setg(&s->migration_blocker, "This operating system kernel does " "not support vGICv2 migration"); - migrate_add_blocker(s->migration_blocker, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (migrate_add_blocker(s->migration_blocker, errp) < 0) { error_free(s->migration_blocker); return; } diff --git a/hw/intc/arm_gicv2m.c b/hw/intc/arm_gicv2m.c index 0b7e2b4f8422548816ae346a3bbe1988a886c091..d564b857eba5ff8d0937d5efd13691bccce12ff1 100644 --- a/hw/intc/arm_gicv2m.c +++ b/hw/intc/arm_gicv2m.c @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -34,9 +34,10 @@ #include "sysemu/kvm.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" #define TYPE_ARM_GICV2M "arm-gicv2m" -#define ARM_GICV2M(obj) OBJECT_CHECK(ARMGICv2mState, (obj), TYPE_ARM_GICV2M) +OBJECT_DECLARE_SIMPLE_TYPE(ARMGICv2mState, ARM_GICV2M) #define GICV2M_NUM_SPI_MAX 128 @@ -48,7 +49,7 @@ #define PRODUCT_ID_QEMU 0x51 /* ASCII code Q */ -typedef struct ARMGICv2mState { +struct ARMGICv2mState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -56,7 +57,7 @@ typedef struct ARMGICv2mState { uint32_t base_spi; uint32_t num_spi; -} ARMGICv2mState; +}; static void gicv2m_set_irq(void *opaque, int irq) { diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c index 08e000e33c630f40ae2b47243ed3763185a415c9..43ef1d7a8405b4bc8b87654885a066d3cff2c754 100644 --- a/hw/intc/arm_gicv3_cpuif.c +++ b/hw/intc/arm_gicv3_cpuif.c @@ -399,6 +399,7 @@ static void gicv3_cpuif_virt_update(GICv3CPUState *cs) int irqlevel = 0; int fiqlevel = 0; int maintlevel = 0; + ARMCPU *cpu = ARM_CPU(cs->cpu); idx = hppvi_index(cs); trace_gicv3_cpuif_virt_update(gicv3_redist_affid(cs), idx); @@ -424,7 +425,7 @@ static void gicv3_cpuif_virt_update(GICv3CPUState *cs) qemu_set_irq(cs->parent_vfiq, fiqlevel); qemu_set_irq(cs->parent_virq, irqlevel); - qemu_set_irq(cs->maintenance_irq, maintlevel); + qemu_set_irq(cpu->gicv3_maintenance_interrupt, maintlevel); } static uint64_t icv_ap_read(CPUARMState *env, const ARMCPRegInfo *ri) @@ -2624,8 +2625,6 @@ void gicv3_init_cpuif(GICv3State *s) && cpu->gic_num_lrs) { int j; - cs->maintenance_irq = cpu->gicv3_maintenance_interrupt; - cs->num_list_regs = cpu->gic_num_lrs; cs->vpribits = cpu->gic_vpribits; cs->vprebits = cpu->gic_vprebits; diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c index ad0ebabc87956558f07f4025f50573644b3d0a59..057cb53f13c280860e18e2bbeb76098a6ba4894d 100644 --- a/hw/intc/arm_gicv3_its_kvm.c +++ b/hw/intc/arm_gicv3_its_kvm.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -27,18 +27,18 @@ #include "sysemu/kvm.h" #include "kvm_arm.h" #include "migration/blocker.h" +#include "qom/object.h" #define TYPE_KVM_ARM_ITS "arm-its-kvm" -#define KVM_ARM_ITS(obj) OBJECT_CHECK(GICv3ITSState, (obj), TYPE_KVM_ARM_ITS) -#define KVM_ARM_ITS_CLASS(klass) \ - OBJECT_CLASS_CHECK(KVMARMITSClass, (klass), TYPE_KVM_ARM_ITS) -#define KVM_ARM_ITS_GET_CLASS(obj) \ - OBJECT_GET_CLASS(KVMARMITSClass, (obj), TYPE_KVM_ARM_ITS) +typedef struct KVMARMITSClass KVMARMITSClass; +/* This is reusing the GICv3ITSState typedef from ARM_GICV3_ITS_COMMON */ +DECLARE_OBJ_CHECKERS(GICv3ITSState, KVMARMITSClass, + KVM_ARM_ITS, TYPE_KVM_ARM_ITS) -typedef struct KVMARMITSClass { +struct KVMARMITSClass { GICv3ITSCommonClass parent_class; void (*parent_reset)(DeviceState *dev); -} KVMARMITSClass; +}; static int kvm_its_send_msi(GICv3ITSState *s, uint32_t value, uint16_t devid) @@ -91,7 +91,6 @@ static void vm_change_state_handler(void *opaque, int running, static void kvm_arm_its_realize(DeviceState *dev, Error **errp) { GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev); - Error *local_err = NULL; s->dev_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_ITS, false); if (s->dev_fd < 0) { @@ -113,9 +112,7 @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp) GITS_CTLR)) { error_setg(&s->migration_blocker, "This operating system kernel " "does not support vITS migration"); - migrate_add_blocker(s->migration_blocker, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (migrate_add_blocker(s->migration_blocker, errp) < 0) { error_free(s->migration_blocker); return; } diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c index ca43bf87caba0383b8d1cfe3ed1a4dbe6a781861..187eb054e00b8f2850f719ae02be7b2ba8698a45 100644 --- a/hw/intc/arm_gicv3_kvm.c +++ b/hw/intc/arm_gicv3_kvm.c @@ -31,6 +31,7 @@ #include "gicv3_internal.h" #include "vgic_common.h" #include "migration/blocker.h" +#include "qom/object.h" #ifdef DEBUG_GICV3_KVM #define DPRINTF(fmt, ...) \ @@ -41,12 +42,10 @@ #endif #define TYPE_KVM_ARM_GICV3 "kvm-arm-gicv3" -#define KVM_ARM_GICV3(obj) \ - OBJECT_CHECK(GICv3State, (obj), TYPE_KVM_ARM_GICV3) -#define KVM_ARM_GICV3_CLASS(klass) \ - OBJECT_CLASS_CHECK(KVMARMGICv3Class, (klass), TYPE_KVM_ARM_GICV3) -#define KVM_ARM_GICV3_GET_CLASS(obj) \ - OBJECT_GET_CLASS(KVMARMGICv3Class, (obj), TYPE_KVM_ARM_GICV3) +typedef struct KVMARMGICv3Class KVMARMGICv3Class; +/* This is reusing the GICv3State typedef from ARM_GICV3_ITS_COMMON */ +DECLARE_OBJ_CHECKERS(GICv3State, KVMARMGICv3Class, + KVM_ARM_GICV3, TYPE_KVM_ARM_GICV3) #define KVM_DEV_ARM_VGIC_SYSREG(op0, op1, crn, crm, op2) \ (ARM64_SYS_REG_SHIFT_MASK(op0, OP0) | \ @@ -74,11 +73,11 @@ #define ICC_IGRPEN1_EL1 \ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 12, 7) -typedef struct KVMARMGICv3Class { +struct KVMARMGICv3Class { ARMGICv3CommonClass parent_class; DeviceRealize parent_realize; void (*parent_reset)(DeviceState *dev); -} KVMARMGICv3Class; +}; static void kvm_arm_gicv3_set_irq(void *opaque, int irq, int level) { @@ -858,9 +857,7 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) GICD_CTLR)) { error_setg(&s->migration_blocker, "This operating system kernel does " "not support vGICv3 migration"); - migrate_add_blocker(s->migration_blocker, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (migrate_add_blocker(s->migration_blocker, errp) < 0) { error_free(s->migration_blocker); return; } diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 1ad35e55292b79c0dd7d1aeece673492afd4c267..42b1ad59e65d6e934333b58bc945df00a6836297 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -19,6 +19,7 @@ #include "hw/intc/armv7m_nvic.h" #include "hw/irq.h" #include "hw/qdev-properties.h" +#include "sysemu/runstate.h" #include "target/arm/cpu.h" #include "exec/exec-all.h" #include "exec/memop.h" @@ -64,6 +65,20 @@ static const uint8_t nvic_id[] = { 0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1 }; +static void signal_sysresetreq(NVICState *s) +{ + if (qemu_irq_is_connected(s->sysresetreq)) { + qemu_irq_pulse(s->sysresetreq); + } else { + /* + * Default behaviour if the SoC doesn't need to wire up + * SYSRESETREQ (eg to a system reset controller of some kind): + * perform a system reset via the usual QEMU API. + */ + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + } +} + static int nvic_pending_prio(NVICState *s) { /* return the group priority of the current pending interrupt, @@ -1223,32 +1238,74 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) "Aux Fault status registers unimplemented\n"); return 0; case 0xd40: /* PFR0. */ - return cpu->id_pfr0; + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } + return cpu->isar.id_pfr0; case 0xd44: /* PFR1. */ - return cpu->id_pfr1; + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } + return cpu->isar.id_pfr1; case 0xd48: /* DFR0. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_dfr0; case 0xd4c: /* AFR0. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->id_afr0; case 0xd50: /* MMFR0. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_mmfr0; case 0xd54: /* MMFR1. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_mmfr1; case 0xd58: /* MMFR2. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_mmfr2; case 0xd5c: /* MMFR3. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_mmfr3; case 0xd60: /* ISAR0. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_isar0; case 0xd64: /* ISAR1. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_isar1; case 0xd68: /* ISAR2. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_isar2; case 0xd6c: /* ISAR3. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_isar3; case 0xd70: /* ISAR4. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_isar4; case 0xd74: /* ISAR5. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_isar5; case 0xd78: /* CLIDR */ return cpu->clidr; @@ -1275,7 +1332,6 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) case 0xd90: /* MPU_TYPE */ /* Unified MPU; if the MPU is not present this value is zero */ return cpu->pmsav7_dregion << 8; - break; case 0xd94: /* MPU_CTRL */ return cpu->env.v7m.mpu_ctrl[attrs.secure]; case 0xd98: /* MPU_RNR */ @@ -1524,7 +1580,7 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value, if (value & R_V7M_AIRCR_SYSRESETREQ_MASK) { if (attrs.secure || !(cpu->env.v7m.aircr & R_V7M_AIRCR_SYSRESETREQS_MASK)) { - qemu_irq_pulse(s->sysresetreq); + signal_sysresetreq(s); } } if (value & R_V7M_AIRCR_VECTCLRACTIVE_MASK) { @@ -2619,7 +2675,6 @@ static void nvic_systick_trigger(void *opaque, int n, int level) static void armv7m_nvic_realize(DeviceState *dev, Error **errp) { NVICState *s = NVIC(dev); - Error *err = NULL; int regionlen; /* The armv7m container object will have set our CPU pointer */ @@ -2640,10 +2695,7 @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp) s->num_prio_bits = arm_feature(&s->cpu->env, ARM_FEATURE_V7) ? 8 : 2; - object_property_set_bool(OBJECT(&s->systick[M_REG_NS]), true, - "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->systick[M_REG_NS]), errp)) { return; } sysbus_connect_irq(SYS_BUS_DEVICE(&s->systick[M_REG_NS]), 0, @@ -2655,14 +2707,10 @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp) * as we didn't know then if the CPU had the security extensions; * so we have to do it here. */ - sysbus_init_child_obj(OBJECT(dev), "systick-reg-s", - &s->systick[M_REG_S], - sizeof(s->systick[M_REG_S]), TYPE_SYSTICK); - - object_property_set_bool(OBJECT(&s->systick[M_REG_S]), true, - "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + object_initialize_child(OBJECT(dev), "systick-reg-s", + &s->systick[M_REG_S], TYPE_SYSTICK); + + if (!sysbus_realize(SYS_BUS_DEVICE(&s->systick[M_REG_S]), errp)) { return; } sysbus_connect_irq(SYS_BUS_DEVICE(&s->systick[M_REG_S]), 0, @@ -2737,8 +2785,8 @@ static void armv7m_nvic_instance_init(Object *obj) NVICState *nvic = NVIC(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - sysbus_init_child_obj(obj, "systick-reg-ns", &nvic->systick[M_REG_NS], - sizeof(nvic->systick[M_REG_NS]), TYPE_SYSTICK); + object_initialize_child(obj, "systick-reg-ns", &nvic->systick[M_REG_NS], + TYPE_SYSTICK); /* We can't initialize the secure systick here, as we don't know * yet if we need it. */ diff --git a/hw/intc/bcm2835_ic.c b/hw/intc/bcm2835_ic.c index 53ab8f588106a043ef3ef54544c97759190c086a..9000d995e81f42c221f92ff4cfd0ae7fa8678d33 100644 --- a/hw/intc/bcm2835_ic.c +++ b/hw/intc/bcm2835_ic.c @@ -18,6 +18,7 @@ #include "migration/vmstate.h" #include "qemu/log.h" #include "qemu/module.h" +#include "trace.h" #define GPU_IRQS 64 #define ARM_IRQS 8 @@ -51,7 +52,6 @@ static void bcm2835_ic_update(BCM2835ICState *s) set = (s->gpu_irq_level & s->gpu_irq_enable) || (s->arm_irq_level & s->arm_irq_enable); qemu_set_irq(s->irq, set); - } static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level) @@ -59,6 +59,7 @@ static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level) BCM2835ICState *s = opaque; assert(irq >= 0 && irq < 64); + trace_bcm2835_ic_set_gpu_irq(irq, level); s->gpu_irq_level = deposit64(s->gpu_irq_level, irq, 1, level != 0); bcm2835_ic_update(s); } @@ -68,6 +69,7 @@ static void bcm2835_ic_set_arm_irq(void *opaque, int irq, int level) BCM2835ICState *s = opaque; assert(irq >= 0 && irq < 8); + trace_bcm2835_ic_set_cpu_irq(irq, level); s->arm_irq_level = deposit32(s->arm_irq_level, irq, 1, level != 0); bcm2835_ic_update(s); } diff --git a/hw/intc/bcm2836_control.c b/hw/intc/bcm2836_control.c index 53dba0080ca8908006657206170c2750ba52fe6d..2ead76ffdce205e797a97d7d450b8a3dba1800b5 100644 --- a/hw/intc/bcm2836_control.c +++ b/hw/intc/bcm2836_control.c @@ -157,22 +157,22 @@ static void bcm2836_control_set_local_irq(void *opaque, int core, int local_irq, static void bcm2836_control_set_local_irq0(void *opaque, int core, int level) { - bcm2836_control_set_local_irq(opaque, core, 0, level); + bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPSIRQ, level); } static void bcm2836_control_set_local_irq1(void *opaque, int core, int level) { - bcm2836_control_set_local_irq(opaque, core, 1, level); + bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPNSIRQ, level); } static void bcm2836_control_set_local_irq2(void *opaque, int core, int level) { - bcm2836_control_set_local_irq(opaque, core, 2, level); + bcm2836_control_set_local_irq(opaque, core, IRQ_CNTHPIRQ, level); } static void bcm2836_control_set_local_irq3(void *opaque, int core, int level) { - bcm2836_control_set_local_irq(opaque, core, 3, level); + bcm2836_control_set_local_irq(opaque, core, IRQ_CNTVIRQ, level); } static void bcm2836_control_set_gpu_irq(void *opaque, int irq, int level) diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c index 12988c7aa96a985c0294849e09163a6e043fd54f..54ed4c77f73411d42ddd6f7f9bd4e1ec204c12de 100644 --- a/hw/intc/etraxfs_pic.c +++ b/hw/intc/etraxfs_pic.c @@ -27,6 +27,7 @@ #include "qemu/module.h" #include "hw/irq.h" #include "hw/qdev-properties.h" +#include "qom/object.h" #define D(x) @@ -38,8 +39,8 @@ #define R_MAX 5 #define TYPE_ETRAX_FS_PIC "etraxfs,pic" -#define ETRAX_FS_PIC(obj) \ - OBJECT_CHECK(struct etrax_pic, (obj), TYPE_ETRAX_FS_PIC) +DECLARE_INSTANCE_CHECKER(struct etrax_pic, ETRAX_FS_PIC, + TYPE_ETRAX_FS_PIC) struct etrax_pic { diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c index b8561e418037ef435bc6dd27ba9f5df1f3809964..4534ee248db26697ae170e03b6ac98d0969c68a2 100644 --- a/hw/intc/exynos4210_combiner.c +++ b/hw/intc/exynos4210_combiner.c @@ -36,6 +36,7 @@ #include "hw/hw.h" #include "hw/irq.h" #include "hw/qdev-properties.h" +#include "qom/object.h" //#define DEBUG_COMBINER @@ -63,10 +64,9 @@ typedef struct CombinerGroupState { } CombinerGroupState; #define TYPE_EXYNOS4210_COMBINER "exynos4210.combiner" -#define EXYNOS4210_COMBINER(obj) \ - OBJECT_CHECK(Exynos4210CombinerState, (obj), TYPE_EXYNOS4210_COMBINER) +OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210CombinerState, EXYNOS4210_COMBINER) -typedef struct Exynos4210CombinerState { +struct Exynos4210CombinerState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -77,7 +77,7 @@ typedef struct Exynos4210CombinerState { uint32_t external; /* 1 means that this combiner is external */ qemu_irq output_irq[IIC_NGRP]; -} Exynos4210CombinerState; +}; static const VMStateDescription vmstate_exynos4210_combiner_group_state = { .name = "exynos4210.combiner.groupstate", @@ -229,7 +229,6 @@ exynos4210_combiner_read(void *opaque, hwaddr offset, unsigned size) TARGET_FMT_plx "offset\n", offset); } val = s->reg_set[offset >> 2]; - return 0; } return val; } diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c index 82c8f4192cbc34fe4c8762846728230fcfd84a77..bc73d1f1152438de04c252a2ec84472c43f0de21 100644 --- a/hw/intc/exynos4210_gic.c +++ b/hw/intc/exynos4210_gic.c @@ -23,10 +23,12 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" #include "migration/vmstate.h" +#include "qapi/error.h" #include "qemu/module.h" #include "hw/irq.h" #include "hw/qdev-properties.h" #include "hw/arm/exynos4210.h" +#include "qom/object.h" enum ExtGicId { EXT_GIC_ID_MDMA_LCD0 = 66, @@ -263,10 +265,9 @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit) /********* GIC part *********/ #define TYPE_EXYNOS4210_GIC "exynos4210.gic" -#define EXYNOS4210_GIC(obj) \ - OBJECT_CHECK(Exynos4210GicState, (obj), TYPE_EXYNOS4210_GIC) +OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC) -typedef struct { +struct Exynos4210GicState { SysBusDevice parent_obj; MemoryRegion cpu_container; @@ -275,7 +276,7 @@ typedef struct { MemoryRegion dist_alias[EXYNOS4210_NCPUS]; uint32_t num_cpu; DeviceState *gic; -} Exynos4210GicState; +}; static void exynos4210_gic_set_irq(void *opaque, int irq, int level) { @@ -296,11 +297,11 @@ static void exynos4210_gic_realize(DeviceState *dev, Error **errp) uint32_t n = s->num_cpu; uint32_t i; - s->gic = qdev_create(NULL, "arm_gic"); + s->gic = qdev_new("arm_gic"); qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu); qdev_prop_set_uint32(s->gic, "num-irq", EXYNOS4210_GIC_NIRQ); - qdev_init_nofail(s->gic); gicbusdev = SYS_BUS_DEVICE(s->gic); + sysbus_realize_and_unref(gicbusdev, &error_fatal); /* Pass through outbound IRQ lines from the GIC */ sysbus_pass_irq(sbd, gicbusdev); @@ -381,16 +382,15 @@ type_init(exynos4210_gic_register_types) */ #define TYPE_EXYNOS4210_IRQ_GATE "exynos4210.irq_gate" -#define EXYNOS4210_IRQ_GATE(obj) \ - OBJECT_CHECK(Exynos4210IRQGateState, (obj), TYPE_EXYNOS4210_IRQ_GATE) +OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210IRQGateState, EXYNOS4210_IRQ_GATE) -typedef struct Exynos4210IRQGateState { +struct Exynos4210IRQGateState { SysBusDevice parent_obj; uint32_t n_in; /* inputs amount */ uint32_t *level; /* input levels */ qemu_irq out; /* output IRQ */ -} Exynos4210IRQGateState; +}; static Property exynos4210_irq_gate_properties[] = { DEFINE_PROP_UINT32("n_in", Exynos4210IRQGateState, n_in, 1), diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c index 794c643af2685b3a03d618109903253e9cd69248..ffec4a07eece4830a1b0e97dc9b24c4502e865be 100644 --- a/hw/intc/grlib_irqmp.c +++ b/hw/intc/grlib_irqmp.c @@ -35,6 +35,7 @@ #include "trace.h" #include "qapi/error.h" #include "qemu/module.h" +#include "qom/object.h" #define IRQMP_MAX_CPU 16 #define IRQMP_REG_SIZE 256 /* Size of memory mapped registers */ @@ -50,18 +51,18 @@ #define FORCE_OFFSET 0x80 #define EXTENDED_OFFSET 0xC0 -#define GRLIB_IRQMP(obj) OBJECT_CHECK(IRQMP, (obj), TYPE_GRLIB_IRQMP) +OBJECT_DECLARE_SIMPLE_TYPE(IRQMP, GRLIB_IRQMP) typedef struct IRQMPState IRQMPState; -typedef struct IRQMP { +struct IRQMP { SysBusDevice parent_obj; MemoryRegion iomem; IRQMPState *state; qemu_irq irq; -} IRQMP; +}; struct IRQMPState { uint32_t level; diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c index 51b27f6a34b720ce9f9e71bde3367d96c903fec7..344fd04db14da7a9aead0061c07a57210085dd23 100644 --- a/hw/intc/i8259.c +++ b/hw/intc/i8259.c @@ -30,6 +30,7 @@ #include "qemu/log.h" #include "hw/isa/i8259_internal.h" #include "trace.h" +#include "qom/object.h" /* debug PIC */ //#define DEBUG_PIC @@ -37,18 +38,19 @@ //#define DEBUG_IRQ_LATENCY #define TYPE_I8259 "isa-i8259" -#define PIC_CLASS(class) OBJECT_CLASS_CHECK(PICClass, (class), TYPE_I8259) -#define PIC_GET_CLASS(obj) OBJECT_GET_CLASS(PICClass, (obj), TYPE_I8259) +typedef struct PICClass PICClass; +DECLARE_CLASS_CHECKERS(PICClass, PIC, + TYPE_I8259) /** * PICClass: * @parent_realize: The parent's realizefn. */ -typedef struct PICClass { +struct PICClass { PICCommonClass parent_class; DeviceRealize parent_realize; -} PICClass; +}; #ifdef DEBUG_IRQ_LATENCY static int64_t irq_time[16]; diff --git a/hw/intc/i8259_common.c b/hw/intc/i8259_common.c index 99f8f6abd53e08668979faabade37f1f703193f0..d90b40fe4c12e4aeaf4bcbe13e0c7b25a187e43e 100644 --- a/hw/intc/i8259_common.c +++ b/hw/intc/i8259_common.c @@ -29,6 +29,7 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "monitor/monitor.h" +#include "qapi/error.h" static int irq_level[16]; static uint64_t irq_count[16]; @@ -94,13 +95,13 @@ ISADevice *i8259_init_chip(const char *name, ISABus *bus, bool master) DeviceState *dev; ISADevice *isadev; - isadev = isa_create(bus, name); + isadev = isa_new(name); dev = DEVICE(isadev); qdev_prop_set_uint32(dev, "iobase", master ? 0x20 : 0xa0); qdev_prop_set_uint32(dev, "elcr_addr", master ? 0x4d0 : 0x4d1); qdev_prop_set_uint8(dev, "elcr_mask", master ? 0xf8 : 0xde); qdev_prop_set_bit(dev, "master", master); - qdev_init_nofail(dev); + isa_realize_and_unref(isadev, bus, &error_fatal); return isadev; } diff --git a/hw/intc/ibex_plic.c b/hw/intc/ibex_plic.c new file mode 100644 index 0000000000000000000000000000000000000000..341c9db405575e60d7d090d5bb77324af8e7e415 --- /dev/null +++ b/hw/intc/ibex_plic.c @@ -0,0 +1,305 @@ +/* + * QEMU RISC-V lowRISC Ibex PLIC + * + * Copyright (c) 2020 Western Digital + * + * Documentation avaliable: https://docs.opentitan.org/hw/ip/rv_plic/doc/ + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "hw/qdev-properties.h" +#include "hw/core/cpu.h" +#include "hw/boards.h" +#include "hw/pci/msi.h" +#include "target/riscv/cpu_bits.h" +#include "target/riscv/cpu.h" +#include "hw/intc/ibex_plic.h" + +static bool addr_between(uint32_t addr, uint32_t base, uint32_t num) +{ + uint32_t end = base + (num * 0x04); + + if (addr >= base && addr < end) { + return true; + } + + return false; +} + +static void ibex_plic_irqs_set_pending(IbexPlicState *s, int irq, bool level) +{ + int pending_num = irq / 32; + + if (s->claimed[pending_num] & 1 << (irq % 32)) { + /* + * The interrupt has been claimed, but not completed. + * The pending bit can't be set. + */ + s->hidden_pending[pending_num] |= level << (irq % 32); + return; + } + + s->pending[pending_num] |= level << (irq % 32); +} + +static bool ibex_plic_irqs_pending(IbexPlicState *s, uint32_t context) +{ + int i; + uint32_t max_irq = 0; + uint32_t max_prio = s->threshold; + + for (i = 0; i < s->pending_num; i++) { + uint32_t irq_num = ctz64(s->pending[i]) + (i * 32); + + if (!(s->pending[i] & s->enable[i])) { + /* No pending and enabled IRQ */ + continue; + } + + if (s->priority[irq_num] > max_prio) { + max_irq = irq_num; + max_prio = s->priority[irq_num]; + } + } + + if (max_irq) { + s->claim = max_irq; + return true; + } + + return false; +} + +static void ibex_plic_update(IbexPlicState *s) +{ + CPUState *cpu; + int level, i; + + for (i = 0; i < s->num_cpus; i++) { + cpu = qemu_get_cpu(i); + + if (!cpu) { + continue; + } + + level = ibex_plic_irqs_pending(s, 0); + + riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MEIP, BOOL_TO_MASK(level)); + } +} + +static void ibex_plic_reset(DeviceState *dev) +{ + IbexPlicState *s = IBEX_PLIC(dev); + + s->threshold = 0x00000000; + s->claim = 0x00000000; +} + +static uint64_t ibex_plic_read(void *opaque, hwaddr addr, + unsigned int size) +{ + IbexPlicState *s = opaque; + int offset; + uint32_t ret = 0; + + if (addr_between(addr, s->pending_base, s->pending_num)) { + offset = (addr - s->pending_base) / 4; + ret = s->pending[offset]; + } else if (addr_between(addr, s->source_base, s->source_num)) { + qemu_log_mask(LOG_UNIMP, + "%s: Interrupt source mode not supported\n", __func__); + } else if (addr_between(addr, s->priority_base, s->priority_num)) { + offset = (addr - s->priority_base) / 4; + ret = s->priority[offset]; + } else if (addr_between(addr, s->enable_base, s->enable_num)) { + offset = (addr - s->enable_base) / 4; + ret = s->enable[offset]; + } else if (addr_between(addr, s->threshold_base, 1)) { + ret = s->threshold; + } else if (addr_between(addr, s->claim_base, 1)) { + int pending_num = s->claim / 32; + s->pending[pending_num] &= ~(1 << (s->claim % 32)); + + /* Set the interrupt as claimed, but not completed */ + s->claimed[pending_num] |= 1 << (s->claim % 32); + + /* Return the current claimed interrupt */ + ret = s->claim; + + /* Clear the claimed interrupt */ + s->claim = 0x00000000; + + /* Update the interrupt status after the claim */ + ibex_plic_update(s); + } + + return ret; +} + +static void ibex_plic_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + IbexPlicState *s = opaque; + + if (addr_between(addr, s->pending_base, s->pending_num)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Pending registers are read only\n", __func__); + } else if (addr_between(addr, s->source_base, s->source_num)) { + qemu_log_mask(LOG_UNIMP, + "%s: Interrupt source mode not supported\n", __func__); + } else if (addr_between(addr, s->priority_base, s->priority_num)) { + uint32_t irq = ((addr - s->priority_base) >> 2) + 1; + s->priority[irq] = value & 7; + ibex_plic_update(s); + } else if (addr_between(addr, s->enable_base, s->enable_num)) { + uint32_t enable_reg = (addr - s->enable_base) / 4; + + s->enable[enable_reg] = value; + } else if (addr_between(addr, s->threshold_base, 1)) { + s->threshold = value & 3; + } else if (addr_between(addr, s->claim_base, 1)) { + if (s->claim == value) { + /* Interrupt was completed */ + s->claim = 0; + } + if (s->claimed[value / 32] & 1 << (value % 32)) { + int pending_num = value / 32; + + /* This value was already claimed, clear it. */ + s->claimed[pending_num] &= ~(1 << (value % 32)); + + if (s->hidden_pending[pending_num] & (1 << (value % 32))) { + /* + * If the bit in hidden_pending is set then that means we + * received an interrupt between claiming and completing + * the interrupt that hasn't since been de-asserted. + * On hardware this would trigger an interrupt, so let's + * trigger one here as well. + */ + s->pending[pending_num] |= 1 << (value % 32); + } + } + } + + ibex_plic_update(s); +} + +static const MemoryRegionOps ibex_plic_ops = { + .read = ibex_plic_read, + .write = ibex_plic_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4 + } +}; + +static void ibex_plic_irq_request(void *opaque, int irq, int level) +{ + IbexPlicState *s = opaque; + + ibex_plic_irqs_set_pending(s, irq, level > 0); + ibex_plic_update(s); +} + +static Property ibex_plic_properties[] = { + DEFINE_PROP_UINT32("num-cpus", IbexPlicState, num_cpus, 1), + DEFINE_PROP_UINT32("num-sources", IbexPlicState, num_sources, 80), + + DEFINE_PROP_UINT32("pending-base", IbexPlicState, pending_base, 0), + DEFINE_PROP_UINT32("pending-num", IbexPlicState, pending_num, 3), + + DEFINE_PROP_UINT32("source-base", IbexPlicState, source_base, 0x0c), + DEFINE_PROP_UINT32("source-num", IbexPlicState, source_num, 3), + + DEFINE_PROP_UINT32("priority-base", IbexPlicState, priority_base, 0x18), + DEFINE_PROP_UINT32("priority-num", IbexPlicState, priority_num, 80), + + DEFINE_PROP_UINT32("enable-base", IbexPlicState, enable_base, 0x200), + DEFINE_PROP_UINT32("enable-num", IbexPlicState, enable_num, 3), + + DEFINE_PROP_UINT32("threshold-base", IbexPlicState, threshold_base, 0x20c), + + DEFINE_PROP_UINT32("claim-base", IbexPlicState, claim_base, 0x210), + DEFINE_PROP_END_OF_LIST(), +}; + +static void ibex_plic_init(Object *obj) +{ + IbexPlicState *s = IBEX_PLIC(obj); + + memory_region_init_io(&s->mmio, obj, &ibex_plic_ops, s, + TYPE_IBEX_PLIC, 0x400); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); +} + +static void ibex_plic_realize(DeviceState *dev, Error **errp) +{ + IbexPlicState *s = IBEX_PLIC(dev); + int i; + + s->pending = g_new0(uint32_t, s->pending_num); + s->hidden_pending = g_new0(uint32_t, s->pending_num); + s->claimed = g_new0(uint32_t, s->pending_num); + s->source = g_new0(uint32_t, s->source_num); + s->priority = g_new0(uint32_t, s->priority_num); + s->enable = g_new0(uint32_t, s->enable_num); + + qdev_init_gpio_in(dev, ibex_plic_irq_request, s->num_sources); + + /* + * We can't allow the supervisor to control SEIP as this would allow the + * supervisor to clear a pending external interrupt which will result in + * a lost interrupt in the case a PLIC is attached. The SEIP bit must be + * hardware controlled when a PLIC is attached. + */ + MachineState *ms = MACHINE(qdev_get_machine()); + unsigned int smp_cpus = ms->smp.cpus; + for (i = 0; i < smp_cpus; i++) { + RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(i)); + if (riscv_cpu_claim_interrupts(cpu, MIP_SEIP) < 0) { + error_report("SEIP already claimed"); + exit(1); + } + } + + msi_nonbroken = true; +} + +static void ibex_plic_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = ibex_plic_reset; + device_class_set_props(dc, ibex_plic_properties); + dc->realize = ibex_plic_realize; +} + +static const TypeInfo ibex_plic_info = { + .name = TYPE_IBEX_PLIC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(IbexPlicState), + .instance_init = ibex_plic_init, + .class_init = ibex_plic_class_init, +}; + +static void ibex_plic_register_types(void) +{ + type_register_static(&ibex_plic_info); +} + +type_init(ibex_plic_register_types) diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c index ffe30dc457130a6fa671018f8920acc1aea25d95..a3021a4de167f9a887e89c2f17070c3b84716808 100644 --- a/hw/intc/ioapic.c +++ b/hw/intc/ioapic.c @@ -9,7 +9,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -241,6 +241,25 @@ void ioapic_eoi_broadcast(int vector) continue; } +#ifdef CONFIG_KVM + /* + * When IOAPIC is in the userspace while APIC is still in + * the kernel (i.e., split irqchip), we have a trick to + * kick the resamplefd logic for registered irqfds from + * userspace to deactivate the IRQ. When that happens, it + * means the irq bypassed userspace IOAPIC (so the irr and + * remote-irr of the table entry should be bypassed too + * even if interrupt come). Still kick the resamplefds if + * they're bound to the IRQ, to make sure to EOI the + * interrupt for the hardware correctly. + * + * Note: We still need to go through the irr & remote-irr + * operations below because we don't know whether there're + * emulated devices that are using/sharing the same IRQ. + */ + kvm_resample_fd_notify(n); +#endif + if (!(entry & IOAPIC_LVT_REMOTE_IRR)) { continue; } diff --git a/hw/intc/ioapic_common.c b/hw/intc/ioapic_common.c index 5538b5b86eca89df50fdba9d36a0b66a80dc5c6e..3cccfc1556068371833584565078bf3a1b042ab5 100644 --- a/hw/intc/ioapic_common.c +++ b/hw/intc/ioapic_common.c @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/intc/lm32_pic.c b/hw/intc/lm32_pic.c index 36de670c9e8c3f6aeba4703f588dcdc8d0dab7ec..991a90bc99ef03b8f85f6f98d345eacc75f7efe5 100644 --- a/hw/intc/lm32_pic.c +++ b/hw/intc/lm32_pic.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -27,9 +27,10 @@ #include "hw/lm32/lm32_pic.h" #include "hw/intc/intc.h" #include "hw/irq.h" +#include "qom/object.h" #define TYPE_LM32_PIC "lm32-pic" -#define LM32_PIC(obj) OBJECT_CHECK(LM32PicState, (obj), TYPE_LM32_PIC) +OBJECT_DECLARE_SIMPLE_TYPE(LM32PicState, LM32_PIC) struct LM32PicState { SysBusDevice parent_obj; @@ -42,7 +43,6 @@ struct LM32PicState { /* statistics */ uint64_t stats_irq_count[32]; }; -typedef struct LM32PicState LM32PicState; static void update_irq(LM32PicState *s) { diff --git a/hw/intc/loongson_liointc.c b/hw/intc/loongson_liointc.c new file mode 100644 index 0000000000000000000000000000000000000000..fbbfb57ee9c3f4cdf5da59321589c314b34e87ff --- /dev/null +++ b/hw/intc/loongson_liointc.c @@ -0,0 +1,243 @@ +/* + * QEMU Loongson Local I/O interrupt controler. + * + * Copyright (c) 2020 Jiaxun Yang + * + * 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 . + * + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "qemu/module.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "qom/object.h" + +#define D(x) + +#define NUM_IRQS 32 + +#define NUM_CORES 4 +#define NUM_IPS 4 +#define NUM_PARENTS (NUM_CORES * NUM_IPS) +#define PARENT_COREx_IPy(x, y) (NUM_IPS * x + y) + +#define R_MAPPER_START 0x0 +#define R_MAPPER_END 0x20 +#define R_ISR R_MAPPER_END +#define R_IEN 0x24 +#define R_IEN_SET 0x28 +#define R_IEN_CLR 0x2c +#define R_PERCORE_ISR(x) (0x40 + 0x8 * x) +#define R_END 0x64 + +#define TYPE_LOONGSON_LIOINTC "loongson.liointc" +DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC, + TYPE_LOONGSON_LIOINTC) + +struct loongson_liointc { + SysBusDevice parent_obj; + + MemoryRegion mmio; + qemu_irq parent_irq[NUM_PARENTS]; + + uint8_t mapper[NUM_IRQS]; /* 0:3 for core, 4:7 for IP */ + uint32_t isr; + uint32_t ien; + uint32_t per_core_isr[NUM_CORES]; + + /* state of the interrupt input pins */ + uint32_t pin_state; + bool parent_state[NUM_PARENTS]; +}; + +static void update_irq(struct loongson_liointc *p) +{ + uint32_t irq, core, ip; + uint32_t per_ip_isr[NUM_IPS] = {0}; + + /* level triggered interrupt */ + p->isr = p->pin_state; + + /* Clear disabled IRQs */ + p->isr &= p->ien; + + /* Clear per_core_isr */ + for (core = 0; core < NUM_CORES; core++) { + p->per_core_isr[core] = 0; + } + + /* Update per_core_isr and per_ip_isr */ + for (irq = 0; irq < NUM_IRQS; irq++) { + if (!(p->isr & (1 << irq))) { + continue; + } + + for (core = 0; core < NUM_CORES; core++) { + if ((p->mapper[irq] & (1 << core))) { + p->per_core_isr[core] |= (1 << irq); + } + } + + for (ip = 0; ip < NUM_IPS; ip++) { + if ((p->mapper[irq] & (1 << (ip + 4)))) { + per_ip_isr[ip] |= (1 << irq); + } + } + } + + /* Emit IRQ to parent! */ + for (core = 0; core < NUM_CORES; core++) { + for (ip = 0; ip < NUM_IPS; ip++) { + int parent = PARENT_COREx_IPy(core, ip); + if (p->parent_state[parent] != + (!!p->per_core_isr[core] && !!per_ip_isr[ip])) { + p->parent_state[parent] = !p->parent_state[parent]; + qemu_set_irq(p->parent_irq[parent], p->parent_state[parent]); + } + } + } +} + +static uint64_t +liointc_read(void *opaque, hwaddr addr, unsigned int size) +{ + struct loongson_liointc *p = opaque; + uint32_t r = 0; + + /* Mapper is 1 byte */ + if (size == 1 && addr < R_MAPPER_END) { + r = p->mapper[addr]; + goto out; + } + + /* Rest is 4 byte */ + if (size != 4 || (addr % 4)) { + goto out; + } + + if (addr >= R_PERCORE_ISR(0) && + addr < R_PERCORE_ISR(NUM_CORES)) { + int core = (addr - R_PERCORE_ISR(0)) / 8; + r = p->per_core_isr[core]; + goto out; + } + + switch (addr) { + case R_ISR: + r = p->isr; + break; + case R_IEN: + r = p->ien; + break; + default: + break; + } + +out: + D(qemu_log("%s: size=%d addr=%lx val=%x\n", __func__, size, addr, r)); + return r; +} + +static void +liointc_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned int size) +{ + struct loongson_liointc *p = opaque; + uint32_t value = val64; + + D(qemu_log("%s: size=%d, addr=%lx val=%x\n", __func__, size, addr, value)); + + /* Mapper is 1 byte */ + if (size == 1 && addr < R_MAPPER_END) { + p->mapper[addr] = value; + goto out; + } + + /* Rest is 4 byte */ + if (size != 4 || (addr % 4)) { + goto out; + } + + if (addr >= R_PERCORE_ISR(0) && + addr < R_PERCORE_ISR(NUM_CORES)) { + int core = (addr - R_PERCORE_ISR(0)) / 8; + p->per_core_isr[core] = value; + goto out; + } + + switch (addr) { + case R_IEN_SET: + p->ien |= value; + break; + case R_IEN_CLR: + p->ien &= ~value; + break; + default: + break; + } + +out: + update_irq(p); +} + +static const MemoryRegionOps pic_ops = { + .read = liointc_read, + .write = liointc_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 4 + } +}; + +static void irq_handler(void *opaque, int irq, int level) +{ + struct loongson_liointc *p = opaque; + + p->pin_state &= ~(1 << irq); + p->pin_state |= level << irq; + update_irq(p); +} + +static void loongson_liointc_init(Object *obj) +{ + struct loongson_liointc *p = LOONGSON_LIOINTC(obj); + int i; + + qdev_init_gpio_in(DEVICE(obj), irq_handler, 32); + + for (i = 0; i < NUM_PARENTS; i++) { + sysbus_init_irq(SYS_BUS_DEVICE(obj), &p->parent_irq[i]); + } + + memory_region_init_io(&p->mmio, obj, &pic_ops, p, + "loongson.liointc", R_END); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &p->mmio); +} + +static const TypeInfo loongson_liointc_info = { + .name = TYPE_LOONGSON_LIOINTC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(struct loongson_liointc), + .instance_init = loongson_liointc_init, +}; + +static void loongson_liointc_register_types(void) +{ + type_register_static(&loongson_liointc_info); +} + +type_init(loongson_liointc_register_types) diff --git a/hw/intc/meson.build b/hw/intc/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..3f82cc230ad7948608043f07b9cda5672ec4f045 --- /dev/null +++ b/hw/intc/meson.build @@ -0,0 +1,57 @@ +softmmu_ss.add(files('intc.c')) +softmmu_ss.add(when: 'CONFIG_ARM_GIC', if_true: files( + 'arm_gic.c', + 'arm_gic_common.c', + 'arm_gicv2m.c', + 'arm_gicv3.c', + 'arm_gicv3_common.c', + 'arm_gicv3_dist.c', + 'arm_gicv3_its_common.c', + 'arm_gicv3_redist.c', +)) +softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_pic.c')) +softmmu_ss.add(when: 'CONFIG_HEATHROW_PIC', if_true: files('heathrow_pic.c')) +softmmu_ss.add(when: 'CONFIG_I8259', if_true: files('i8259_common.c', 'i8259.c')) +softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_avic.c', 'imx_gpcv2.c')) +softmmu_ss.add(when: 'CONFIG_IOAPIC', if_true: files('ioapic_common.c')) +softmmu_ss.add(when: 'CONFIG_LM32', if_true: files('lm32_pic.c')) +softmmu_ss.add(when: 'CONFIG_OPENPIC', if_true: files('openpic.c')) +softmmu_ss.add(when: 'CONFIG_PL190', if_true: files('pl190.c')) +softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_intc.c')) +softmmu_ss.add(when: 'CONFIG_REALVIEW', if_true: files('realview_gic.c')) +softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_intctl.c')) +softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_intc.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-ipi.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP_PMU', if_true: files('xlnx-pmu-iomod-intc.c')) + +specific_ss.add(when: 'CONFIG_ALLWINNER_A10_PIC', if_true: files('allwinner-a10-pic.c')) +specific_ss.add(when: 'CONFIG_APIC', if_true: files('apic.c', 'apic_common.c')) +specific_ss.add(when: 'CONFIG_ARM_GIC', if_true: files('arm_gicv3_cpuif.c')) +specific_ss.add(when: 'CONFIG_ARM_GIC_KVM', if_true: files('arm_gic_kvm.c')) +specific_ss.add(when: ['CONFIG_ARM_GIC_KVM', 'TARGET_AARCH64'], if_true: files('arm_gicv3_kvm.c', 'arm_gicv3_its_kvm.c')) +specific_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m_nvic.c')) +specific_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_vic.c')) +specific_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_gic.c', 'exynos4210_combiner.c')) +specific_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_irqmp.c')) +specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_plic.c')) +specific_ss.add(when: 'CONFIG_IOAPIC', if_true: files('ioapic.c')) +specific_ss.add(when: 'CONFIG_LOONGSON_LIOINTC', if_true: files('loongson_liointc.c')) +specific_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_gic.c')) +specific_ss.add(when: 'CONFIG_NIOS2', if_true: files('nios2_iic.c')) +specific_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_intc.c')) +specific_ss.add(when: 'CONFIG_OMPIC', if_true: files('ompic.c')) +specific_ss.add(when: 'CONFIG_OPENPIC_KVM', if_true: files('openpic_kvm.c')) +specific_ss.add(when: 'CONFIG_POWERNV', if_true: files('xics_pnv.c', 'pnv_xive.c')) +specific_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_ic.c', 'bcm2836_control.c')) +specific_ss.add(when: 'CONFIG_RX_ICU', if_true: files('rx_icu.c')) +specific_ss.add(when: 'CONFIG_S390_FLIC', if_true: files('s390_flic.c')) +specific_ss.add(when: 'CONFIG_S390_FLIC_KVM', if_true: files('s390_flic_kvm.c')) +specific_ss.add(when: 'CONFIG_SH4', if_true: files('sh_intc.c')) +specific_ss.add(when: 'CONFIG_SIFIVE_CLINT', if_true: files('sifive_clint.c')) +specific_ss.add(when: 'CONFIG_SIFIVE_PLIC', if_true: files('sifive_plic.c')) +specific_ss.add(when: 'CONFIG_XICS', if_true: files('xics.c')) +specific_ss.add(when: 'CONFIG_XICS_KVM', if_true: files('xics_kvm.c')) +specific_ss.add(when: 'CONFIG_XICS_SPAPR', if_true: files('xics_spapr.c')) +specific_ss.add(when: 'CONFIG_XIVE', if_true: files('xive.c')) +specific_ss.add(when: 'CONFIG_XIVE_KVM', if_true: files('spapr_xive_kvm.c')) +specific_ss.add(when: 'CONFIG_XIVE_SPAPR', if_true: files('spapr_xive.c')) diff --git a/hw/intc/nios2_iic.c b/hw/intc/nios2_iic.c index 3a5d86c2a45b3df2057d6c7d8f2da92bfefac141..216db6705940c84244d1bb97048508c117448bd9 100644 --- a/hw/intc/nios2_iic.c +++ b/hw/intc/nios2_iic.c @@ -25,16 +25,16 @@ #include "hw/irq.h" #include "hw/sysbus.h" #include "cpu.h" +#include "qom/object.h" #define TYPE_ALTERA_IIC "altera,iic" -#define ALTERA_IIC(obj) \ - OBJECT_CHECK(AlteraIIC, (obj), TYPE_ALTERA_IIC) +OBJECT_DECLARE_SIMPLE_TYPE(AlteraIIC, ALTERA_IIC) -typedef struct AlteraIIC { +struct AlteraIIC { SysBusDevice parent_obj; void *cpu; qemu_irq parent_irq; -} AlteraIIC; +}; static void update_irq(AlteraIIC *pv) { @@ -66,14 +66,8 @@ static void altera_iic_init(Object *obj) static void altera_iic_realize(DeviceState *dev, Error **errp) { struct AlteraIIC *pv = ALTERA_IIC(dev); - Error *err = NULL; - - pv->cpu = object_property_get_link(OBJECT(dev), "cpu", &err); - if (!pv->cpu) { - error_setg(errp, "altera,iic: CPU link not found: %s", - error_get_pretty(err)); - return; - } + + pv->cpu = object_property_get_link(OBJECT(dev), "cpu", &error_abort); } static void altera_iic_class_init(ObjectClass *klass, void *data) @@ -86,7 +80,7 @@ static void altera_iic_class_init(ObjectClass *klass, void *data) } static TypeInfo altera_iic_info = { - .name = "altera,iic", + .name = TYPE_ALTERA_IIC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(AlteraIIC), .instance_init = altera_iic_init, diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c index b8a1d1fd7d5d176ffaefd9c639da4be4b45f177b..d7183d035e9a657657d34a90733aec20361ca181 100644 --- a/hw/intc/omap_intc.c +++ b/hw/intc/omap_intc.c @@ -676,7 +676,7 @@ static const TypeInfo omap2_intc_info = { static const TypeInfo omap_intc_type_info = { .name = TYPE_OMAP_INTC, .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(struct omap_intr_handler_s), + .instance_size = sizeof(omap_intr_handler), .abstract = true, }; diff --git a/hw/intc/ompic.c b/hw/intc/ompic.c index c354427a61463b8dbf6a083cc0b80f111be6c712..1731a1068385c66bf6a37f5bfafba249f653a6e9 100644 --- a/hw/intc/ompic.c +++ b/hw/intc/ompic.c @@ -15,9 +15,10 @@ #include "hw/sysbus.h" #include "migration/vmstate.h" #include "exec/memory.h" +#include "qom/object.h" #define TYPE_OR1K_OMPIC "or1k-ompic" -#define OR1K_OMPIC(obj) OBJECT_CHECK(OR1KOMPICState, (obj), TYPE_OR1K_OMPIC) +OBJECT_DECLARE_SIMPLE_TYPE(OR1KOMPICState, OR1K_OMPIC) #define OMPIC_CTRL_IRQ_ACK (1 << 31) #define OMPIC_CTRL_IRQ_GEN (1 << 30) @@ -37,7 +38,6 @@ #define OMPIC_MAX_CPUS 4 /* Real max is much higher, but dont waste memory */ #define OMPIC_ADDRSPACE_SZ (OMPIC_MAX_CPUS * 2 * 4) /* 2 32-bit regs per cpu */ -typedef struct OR1KOMPICState OR1KOMPICState; typedef struct OR1KOMPICCPUState OR1KOMPICCPUState; struct OR1KOMPICCPUState { diff --git a/hw/intc/openpic_kvm.c b/hw/intc/openpic_kvm.c index e4bf47d885887e166b6de464ec10dcd0bb6657bc..e1a39e33cb1e7f75b28dbdded806dbda9f4de267 100644 --- a/hw/intc/openpic_kvm.c +++ b/hw/intc/openpic_kvm.c @@ -35,13 +35,13 @@ #include "sysemu/kvm.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" #define GCR_RESET 0x80000000 -#define KVM_OPENPIC(obj) \ - OBJECT_CHECK(KVMOpenPICState, (obj), TYPE_KVM_OPENPIC) +OBJECT_DECLARE_SIMPLE_TYPE(KVMOpenPICState, KVM_OPENPIC) -typedef struct KVMOpenPICState { +struct KVMOpenPICState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -51,7 +51,7 @@ typedef struct KVMOpenPICState { uint32_t fd; uint32_t model; hwaddr mapped; -} KVMOpenPICState; +}; static void kvm_openpic_set_irq(void *opaque, int n_IRQ, int level) { diff --git a/hw/intc/pl190.c b/hw/intc/pl190.c index e3bd3dd12137d9cf73756023ed9fe73e08e830d3..cd88443601e781c79caf976caa4e977d116b35e6 100644 --- a/hw/intc/pl190.c +++ b/hw/intc/pl190.c @@ -13,6 +13,7 @@ #include "migration/vmstate.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" /* The number of virtual priority levels. 16 user vectors plus the unvectored IRQ. Chained interrupts would require an additional level @@ -21,9 +22,9 @@ #define PL190_NUM_PRIO 17 #define TYPE_PL190 "pl190" -#define PL190(obj) OBJECT_CHECK(PL190State, (obj), TYPE_PL190) +OBJECT_DECLARE_SIMPLE_TYPE(PL190State, PL190) -typedef struct PL190State { +struct PL190State { SysBusDevice parent_obj; MemoryRegion iomem; @@ -41,7 +42,7 @@ typedef struct PL190State { int prev_prio[PL190_NUM_PRIO]; qemu_irq irq; qemu_irq fiq; -} PL190State; +}; static const unsigned char pl190_id[] = { 0x90, 0x11, 0x04, 0x00, 0x0D, 0xf0, 0x05, 0xb1 }; diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c index aeda488bd113322ef1b2e01911792fc89ca5de11..5f69626b3a8d2db092f34c3750b225c216c66fce 100644 --- a/hw/intc/pnv_xive.c +++ b/hw/intc/pnv_xive.c @@ -1796,11 +1796,9 @@ static void pnv_xive_init(Object *obj) PnvXive *xive = PNV_XIVE(obj); object_initialize_child(obj, "ipi_source", &xive->ipi_source, - sizeof(xive->ipi_source), TYPE_XIVE_SOURCE, - &error_abort, NULL); + TYPE_XIVE_SOURCE); object_initialize_child(obj, "end_source", &xive->end_source, - sizeof(xive->end_source), TYPE_XIVE_END_SOURCE, - &error_abort, NULL); + TYPE_XIVE_END_SOURCE); } /* @@ -1831,23 +1829,18 @@ static void pnv_xive_realize(DeviceState *dev, Error **errp) * resized dynamically when the controller is configured by the FW * to limit accesses to resources not provisioned. */ - object_property_set_int(OBJECT(xsrc), PNV_XIVE_NR_IRQS, "nr-irqs", + object_property_set_int(OBJECT(xsrc), "nr-irqs", PNV_XIVE_NR_IRQS, &error_fatal); - object_property_set_link(OBJECT(xsrc), OBJECT(xive), "xive", - &error_abort); - object_property_set_bool(OBJECT(xsrc), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + object_property_set_link(OBJECT(xsrc), "xive", OBJECT(xive), &error_abort); + if (!qdev_realize(DEVICE(xsrc), NULL, errp)) { return; } - object_property_set_int(OBJECT(end_xsrc), PNV_XIVE_NR_ENDS, "nr-ends", + object_property_set_int(OBJECT(end_xsrc), "nr-ends", PNV_XIVE_NR_ENDS, &error_fatal); - object_property_set_link(OBJECT(end_xsrc), OBJECT(xive), "xive", + object_property_set_link(OBJECT(end_xsrc), "xive", OBJECT(xive), &error_abort); - object_property_set_bool(OBJECT(end_xsrc), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qdev_realize(DEVICE(end_xsrc), NULL, errp)) { return; } diff --git a/hw/intc/puv3_intc.c b/hw/intc/puv3_intc.c index e018955ce8cbff5fb1b22e810ffb17a05979033a..65226f5e7c495fbca7ca3ee14477a54aa9bb0137 100644 --- a/hw/intc/puv3_intc.c +++ b/hw/intc/puv3_intc.c @@ -12,15 +12,17 @@ #include "qemu/osdep.h" #include "hw/irq.h" #include "hw/sysbus.h" +#include "qom/object.h" #undef DEBUG_PUV3 #include "hw/unicore32/puv3.h" #include "qemu/module.h" +#include "qemu/log.h" #define TYPE_PUV3_INTC "puv3_intc" -#define PUV3_INTC(obj) OBJECT_CHECK(PUV3INTCState, (obj), TYPE_PUV3_INTC) +OBJECT_DECLARE_SIMPLE_TYPE(PUV3INTCState, PUV3_INTC) -typedef struct PUV3INTCState { +struct PUV3INTCState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -28,7 +30,7 @@ typedef struct PUV3INTCState { uint32_t reg_ICMR; uint32_t reg_ICPR; -} PUV3INTCState; +}; /* Update interrupt status after enabled or pending bits have been changed. */ static void puv3_intc_update(PUV3INTCState *s) @@ -68,7 +70,9 @@ static uint64_t puv3_intc_read(void *opaque, hwaddr offset, ret = s->reg_ICPR; /* the same value with ICPR */ break; default: - DPRINTF("Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad read offset 0x%"HWADDR_PRIx"\n", + __func__, offset); } DPRINTF("offset 0x%x, value 0x%x\n", offset, ret); return ret; @@ -88,7 +92,9 @@ static void puv3_intc_write(void *opaque, hwaddr offset, s->reg_ICMR = value; break; default: - DPRINTF("Bad offset 0x%x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad write offset 0x%"HWADDR_PRIx"\n", + __func__, offset); return; } puv3_intc_update(s); diff --git a/hw/intc/realview_gic.c b/hw/intc/realview_gic.c index 73fe8cd81566f4c285d86eda9ac9d93d881f5970..9b12116b2afd1299ba9477854cddba9bafaafe8a 100644 --- a/hw/intc/realview_gic.c +++ b/hw/intc/realview_gic.c @@ -26,7 +26,6 @@ static void realview_gic_realize(DeviceState *dev, Error **errp) SysBusDevice *sbd = SYS_BUS_DEVICE(dev); RealViewGICState *s = REALVIEW_GIC(dev); SysBusDevice *busdev; - Error *err = NULL; /* The GICs on the RealView boards have a fixed nonconfigurable * number of interrupt lines, so we don't need to expose this as * a qdev property. @@ -34,9 +33,7 @@ static void realview_gic_realize(DeviceState *dev, Error **errp) int numirq = 96; qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", numirq); - object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gic), errp)) { return; } busdev = SYS_BUS_DEVICE(&s->gic); @@ -62,7 +59,7 @@ static void realview_gic_init(Object *obj) "realview-gic-container", 0x2000); sysbus_init_mmio(sbd, &s->container); - sysbus_init_child_obj(obj, "gic", &s->gic, sizeof(s->gic), TYPE_ARM_GIC); + object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GIC); qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", 1); } diff --git a/hw/intc/rx_icu.c b/hw/intc/rx_icu.c new file mode 100644 index 0000000000000000000000000000000000000000..e5c01807b9afa19b1384b9478d4618c8b878f176 --- /dev/null +++ b/hw/intc/rx_icu.c @@ -0,0 +1,395 @@ +/* + * RX Interrupt Control Unit + * + * Warning: Only ICUa is supported. + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * + * Copyright (c) 2019 Yoshinori Sato + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "hw/irq.h" +#include "hw/registerfields.h" +#include "hw/qdev-properties.h" +#include "hw/intc/rx_icu.h" +#include "migration/vmstate.h" + +REG8(IR, 0) + FIELD(IR, IR, 0, 1) +REG8(DTCER, 0x100) + FIELD(DTCER, DTCE, 0, 1) +REG8(IER, 0x200) +REG8(SWINTR, 0x2e0) + FIELD(SWINTR, SWINT, 0, 1) +REG16(FIR, 0x2f0) + FIELD(FIR, FVCT, 0, 8) + FIELD(FIR, FIEN, 15, 1) +REG8(IPR, 0x300) + FIELD(IPR, IPR, 0, 4) +REG8(DMRSR, 0x400) +REG8(IRQCR, 0x500) + FIELD(IRQCR, IRQMD, 2, 2) +REG8(NMISR, 0x580) + FIELD(NMISR, NMIST, 0, 1) + FIELD(NMISR, LVDST, 1, 1) + FIELD(NMISR, OSTST, 2, 1) +REG8(NMIER, 0x581) + FIELD(NMIER, NMIEN, 0, 1) + FIELD(NMIER, LVDEN, 1, 1) + FIELD(NMIER, OSTEN, 2, 1) +REG8(NMICLR, 0x582) + FIELD(NMICLR, NMICLR, 0, 1) + FIELD(NMICLR, OSTCLR, 2, 1) +REG8(NMICR, 0x583) + FIELD(NMICR, NMIMD, 3, 1) + +static void set_irq(RXICUState *icu, int n_IRQ, int req) +{ + if ((icu->fir & R_FIR_FIEN_MASK) && + (icu->fir & R_FIR_FVCT_MASK) == n_IRQ) { + qemu_set_irq(icu->_fir, req); + } else { + qemu_set_irq(icu->_irq, req); + } +} + +static uint16_t rxicu_level(RXICUState *icu, unsigned n) +{ + return (icu->ipr[icu->map[n]] << 8) | n; +} + +static void rxicu_request(RXICUState *icu, int n_IRQ) +{ + int enable; + + enable = icu->ier[n_IRQ / 8] & (1 << (n_IRQ & 7)); + if (n_IRQ > 0 && enable != 0 && qatomic_read(&icu->req_irq) < 0) { + qatomic_set(&icu->req_irq, n_IRQ); + set_irq(icu, n_IRQ, rxicu_level(icu, n_IRQ)); + } +} + +static void rxicu_set_irq(void *opaque, int n_IRQ, int level) +{ + RXICUState *icu = opaque; + struct IRQSource *src; + int issue; + + if (n_IRQ >= NR_IRQS) { + error_report("%s: IRQ %d out of range", __func__, n_IRQ); + return; + } + + src = &icu->src[n_IRQ]; + + level = (level != 0); + switch (src->sense) { + case TRG_LEVEL: + /* level-sensitive irq */ + issue = level; + src->level = level; + break; + case TRG_NEDGE: + issue = (level == 0 && src->level == 1); + src->level = level; + break; + case TRG_PEDGE: + issue = (level == 1 && src->level == 0); + src->level = level; + break; + case TRG_BEDGE: + issue = ((level ^ src->level) & 1); + src->level = level; + break; + default: + g_assert_not_reached(); + } + if (issue == 0 && src->sense == TRG_LEVEL) { + icu->ir[n_IRQ] = 0; + if (qatomic_read(&icu->req_irq) == n_IRQ) { + /* clear request */ + set_irq(icu, n_IRQ, 0); + qatomic_set(&icu->req_irq, -1); + } + return; + } + if (issue) { + icu->ir[n_IRQ] = 1; + rxicu_request(icu, n_IRQ); + } +} + +static void rxicu_ack_irq(void *opaque, int no, int level) +{ + RXICUState *icu = opaque; + int i; + int n_IRQ; + int max_pri; + + n_IRQ = qatomic_read(&icu->req_irq); + if (n_IRQ < 0) { + return; + } + qatomic_set(&icu->req_irq, -1); + if (icu->src[n_IRQ].sense != TRG_LEVEL) { + icu->ir[n_IRQ] = 0; + } + + max_pri = 0; + n_IRQ = -1; + for (i = 0; i < NR_IRQS; i++) { + if (icu->ir[i]) { + if (max_pri < icu->ipr[icu->map[i]]) { + n_IRQ = i; + max_pri = icu->ipr[icu->map[i]]; + } + } + } + + if (n_IRQ >= 0) { + rxicu_request(icu, n_IRQ); + } +} + +static uint64_t icu_read(void *opaque, hwaddr addr, unsigned size) +{ + RXICUState *icu = opaque; + int reg = addr & 0xff; + + if ((addr != A_FIR && size != 1) || + (addr == A_FIR && size != 2)) { + qemu_log_mask(LOG_GUEST_ERROR, "rx_icu: Invalid read size 0x%" + HWADDR_PRIX "\n", + addr); + return UINT64_MAX; + } + switch (addr) { + case A_IR ... A_IR + 0xff: + return icu->ir[reg] & R_IR_IR_MASK; + case A_DTCER ... A_DTCER + 0xff: + return icu->dtcer[reg] & R_DTCER_DTCE_MASK; + case A_IER ... A_IER + 0x1f: + return icu->ier[reg]; + case A_SWINTR: + return 0; + case A_FIR: + return icu->fir & (R_FIR_FIEN_MASK | R_FIR_FVCT_MASK); + case A_IPR ... A_IPR + 0x8f: + return icu->ipr[reg] & R_IPR_IPR_MASK; + case A_DMRSR: + case A_DMRSR + 4: + case A_DMRSR + 8: + case A_DMRSR + 12: + return icu->dmasr[reg >> 2]; + case A_IRQCR ... A_IRQCR + 0x1f: + return icu->src[64 + reg].sense << R_IRQCR_IRQMD_SHIFT; + case A_NMISR: + case A_NMICLR: + return 0; + case A_NMIER: + return icu->nmier; + case A_NMICR: + return icu->nmicr; + default: + qemu_log_mask(LOG_UNIMP, "rx_icu: Register 0x%" HWADDR_PRIX " " + "not implemented.\n", + addr); + break; + } + return UINT64_MAX; +} + +static void icu_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) +{ + RXICUState *icu = opaque; + int reg = addr & 0xff; + + if ((addr != A_FIR && size != 1) || + (addr == A_FIR && size != 2)) { + qemu_log_mask(LOG_GUEST_ERROR, "rx_icu: Invalid write size at " + "0x%" HWADDR_PRIX "\n", + addr); + return; + } + switch (addr) { + case A_IR ... A_IR + 0xff: + if (icu->src[reg].sense != TRG_LEVEL && val == 0) { + icu->ir[reg] = 0; + } + break; + case A_DTCER ... A_DTCER + 0xff: + icu->dtcer[reg] = val & R_DTCER_DTCE_MASK; + qemu_log_mask(LOG_UNIMP, "rx_icu: DTC not implemented\n"); + break; + case A_IER ... A_IER + 0x1f: + icu->ier[reg] = val; + break; + case A_SWINTR: + if (val & R_SWINTR_SWINT_MASK) { + qemu_irq_pulse(icu->_swi); + } + break; + case A_FIR: + icu->fir = val & (R_FIR_FIEN_MASK | R_FIR_FVCT_MASK); + break; + case A_IPR ... A_IPR + 0x8f: + icu->ipr[reg] = val & R_IPR_IPR_MASK; + break; + case A_DMRSR: + case A_DMRSR + 4: + case A_DMRSR + 8: + case A_DMRSR + 12: + icu->dmasr[reg >> 2] = val; + qemu_log_mask(LOG_UNIMP, "rx_icu: DMAC not implemented\n"); + break; + case A_IRQCR ... A_IRQCR + 0x1f: + icu->src[64 + reg].sense = val >> R_IRQCR_IRQMD_SHIFT; + break; + case A_NMICLR: + break; + case A_NMIER: + icu->nmier |= val & (R_NMIER_NMIEN_MASK | + R_NMIER_LVDEN_MASK | + R_NMIER_OSTEN_MASK); + break; + case A_NMICR: + if ((icu->nmier & R_NMIER_NMIEN_MASK) == 0) { + icu->nmicr = val & R_NMICR_NMIMD_MASK; + } + break; + default: + qemu_log_mask(LOG_UNIMP, "rx_icu: Register 0x%" HWADDR_PRIX " " + "not implemented\n", + addr); + break; + } +} + +static const MemoryRegionOps icu_ops = { + .write = icu_write, + .read = icu_read, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl = { + .min_access_size = 1, + .max_access_size = 2, + }, + .valid = { + .min_access_size = 1, + .max_access_size = 2, + }, +}; + +static void rxicu_realize(DeviceState *dev, Error **errp) +{ + RXICUState *icu = RX_ICU(dev); + int i; + + if (icu->init_sense == NULL) { + qemu_log_mask(LOG_GUEST_ERROR, + "rx_icu: trigger-level property must be set."); + return; + } + + for (i = 0; i < NR_IRQS; i++) { + icu->src[i].sense = TRG_PEDGE; + } + for (i = 0; i < icu->nr_sense; i++) { + uint8_t irqno = icu->init_sense[i]; + icu->src[irqno].sense = TRG_LEVEL; + } + icu->req_irq = -1; +} + +static void rxicu_init(Object *obj) +{ + SysBusDevice *d = SYS_BUS_DEVICE(obj); + RXICUState *icu = RX_ICU(obj); + + memory_region_init_io(&icu->memory, OBJECT(icu), &icu_ops, + icu, "rx-icu", 0x600); + sysbus_init_mmio(d, &icu->memory); + + qdev_init_gpio_in(DEVICE(d), rxicu_set_irq, NR_IRQS); + qdev_init_gpio_in_named(DEVICE(d), rxicu_ack_irq, "ack", 1); + sysbus_init_irq(d, &icu->_irq); + sysbus_init_irq(d, &icu->_fir); + sysbus_init_irq(d, &icu->_swi); +} + +static void rxicu_fini(Object *obj) +{ + RXICUState *icu = RX_ICU(obj); + g_free(icu->map); + g_free(icu->init_sense); +} + +static const VMStateDescription vmstate_rxicu = { + .name = "rx-icu", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8_ARRAY(ir, RXICUState, NR_IRQS), + VMSTATE_UINT8_ARRAY(dtcer, RXICUState, NR_IRQS), + VMSTATE_UINT8_ARRAY(ier, RXICUState, NR_IRQS / 8), + VMSTATE_UINT8_ARRAY(ipr, RXICUState, 142), + VMSTATE_UINT8_ARRAY(dmasr, RXICUState, 4), + VMSTATE_UINT16(fir, RXICUState), + VMSTATE_UINT8(nmisr, RXICUState), + VMSTATE_UINT8(nmier, RXICUState), + VMSTATE_UINT8(nmiclr, RXICUState), + VMSTATE_UINT8(nmicr, RXICUState), + VMSTATE_INT16(req_irq, RXICUState), + VMSTATE_END_OF_LIST() + } +}; + +static Property rxicu_properties[] = { + DEFINE_PROP_ARRAY("ipr-map", RXICUState, nr_irqs, map, + qdev_prop_uint8, uint8_t), + DEFINE_PROP_ARRAY("trigger-level", RXICUState, nr_sense, init_sense, + qdev_prop_uint8, uint8_t), + DEFINE_PROP_END_OF_LIST(), +}; + +static void rxicu_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = rxicu_realize; + dc->vmsd = &vmstate_rxicu; + device_class_set_props(dc, rxicu_properties); +} + +static const TypeInfo rxicu_info = { + .name = TYPE_RX_ICU, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(RXICUState), + .instance_init = rxicu_init, + .instance_finalize = rxicu_fini, + .class_init = rxicu_class_init, +}; + +static void rxicu_register_types(void) +{ + type_register_static(&rxicu_info); +} + +type_init(rxicu_register_types) diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c index baca4d8a2d7402435a6e4124eed171a683c90555..aacdb1bbc26aefce9131dc9487cd08c83ff19b74 100644 --- a/hw/intc/s390_flic.c +++ b/hw/intc/s390_flic.c @@ -63,15 +63,15 @@ void s390_flic_init(void) DeviceState *dev; if (kvm_enabled()) { - dev = qdev_create(NULL, TYPE_KVM_S390_FLIC); + dev = qdev_new(TYPE_KVM_S390_FLIC); object_property_add_child(qdev_get_machine(), TYPE_KVM_S390_FLIC, OBJECT(dev)); } else { - dev = qdev_create(NULL, TYPE_QEMU_S390_FLIC); + dev = qdev_new(TYPE_QEMU_S390_FLIC); object_property_add_child(qdev_get_machine(), TYPE_QEMU_S390_FLIC, OBJECT(dev)); } - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); } static int qemu_s390_register_io_adapter(S390FLICState *fs, uint32_t id, diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c index a306b26faa07eed69c90d2d0e5af185aecb5b099..35d91afa557259b32b4ebf6293499792bf8e7342 100644 --- a/hw/intc/s390_flic_kvm.c +++ b/hw/intc/s390_flic_kvm.c @@ -24,17 +24,18 @@ #include "hw/s390x/css.h" #include "migration/qemu-file-types.h" #include "trace.h" +#include "qom/object.h" #define FLIC_SAVE_INITIAL_SIZE qemu_real_host_page_size #define FLIC_FAILED (-1UL) #define FLIC_SAVEVM_VERSION 1 -typedef struct KVMS390FLICState { +struct KVMS390FLICState{ S390FLICState parent_obj; uint32_t fd; bool clear_io_supported; -} KVMS390FLICState; +}; static KVMS390FLICState *s390_get_kvm_flic(S390FLICState *fs) { @@ -569,16 +570,15 @@ static const VMStateDescription kvm_s390_flic_vmstate = { } }; -typedef struct KVMS390FLICStateClass { +struct KVMS390FLICStateClass { S390FLICStateClass parent_class; DeviceRealize parent_realize; -} KVMS390FLICStateClass; +}; +typedef struct KVMS390FLICStateClass KVMS390FLICStateClass; -#define KVM_S390_FLIC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(KVMS390FLICStateClass, (obj), TYPE_KVM_S390_FLIC) +DECLARE_CLASS_CHECKERS(KVMS390FLICStateClass, KVM_S390_FLIC, + TYPE_KVM_S390_FLIC) -#define KVM_S390_FLIC_CLASS(klass) \ - OBJECT_CLASS_CHECK(KVMS390FLICStateClass, (klass), TYPE_KVM_S390_FLIC) static void kvm_s390_flic_realize(DeviceState *dev, Error **errp) { diff --git a/hw/riscv/sifive_clint.c b/hw/intc/sifive_clint.c similarity index 88% rename from hw/riscv/sifive_clint.c rename to hw/intc/sifive_clint.c index 7d713fd743d20652046c7d7498fff44c72ae85d9..0f41e5ea1cec0aa3d5f197fb85298878d5559028 100644 --- a/hw/riscv/sifive_clint.c +++ b/hw/intc/sifive_clint.c @@ -20,30 +20,32 @@ */ #include "qemu/osdep.h" +#include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/module.h" #include "hw/sysbus.h" #include "target/riscv/cpu.h" #include "hw/qdev-properties.h" -#include "hw/riscv/sifive_clint.h" +#include "hw/intc/sifive_clint.h" #include "qemu/timer.h" -static uint64_t cpu_riscv_read_rtc(void) +static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq) { return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - SIFIVE_CLINT_TIMEBASE_FREQ, NANOSECONDS_PER_SECOND); + timebase_freq, NANOSECONDS_PER_SECOND); } /* * Called when timecmp is written to update the QEMU timer or immediately * trigger timer interrupt if mtimecmp <= current timer value. */ -static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value) +static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value, + uint32_t timebase_freq) { uint64_t next; uint64_t diff; - uint64_t rtc_r = cpu_riscv_read_rtc(); + uint64_t rtc_r = cpu_riscv_read_rtc(timebase_freq); cpu->env.timecmp = value; if (cpu->env.timecmp <= rtc_r) { @@ -58,7 +60,7 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value) diff = cpu->env.timecmp - rtc_r; /* back to ns (note args switched in muldiv64) */ next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - muldiv64(diff, NANOSECONDS_PER_SECOND, SIFIVE_CLINT_TIMEBASE_FREQ); + muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq); timer_mod(cpu->env.timer, next); } @@ -111,10 +113,10 @@ static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size) } } else if (addr == clint->time_base) { /* time_lo */ - return cpu_riscv_read_rtc() & 0xFFFFFFFF; + return cpu_riscv_read_rtc(clint->timebase_freq) & 0xFFFFFFFF; } else if (addr == clint->time_base + 4) { /* time_hi */ - return (cpu_riscv_read_rtc() >> 32) & 0xFFFFFFFF; + return (cpu_riscv_read_rtc(clint->timebase_freq) >> 32) & 0xFFFFFFFF; } error_report("clint: invalid read: %08x", (uint32_t)addr); @@ -152,13 +154,13 @@ static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value, /* timecmp_lo */ uint64_t timecmp_hi = env->timecmp >> 32; sifive_clint_write_timecmp(RISCV_CPU(cpu), - timecmp_hi << 32 | (value & 0xFFFFFFFF)); + timecmp_hi << 32 | (value & 0xFFFFFFFF), clint->timebase_freq); return; } else if ((addr & 0x7) == 4) { /* timecmp_hi */ uint64_t timecmp_lo = env->timecmp; sifive_clint_write_timecmp(RISCV_CPU(cpu), - value << 32 | (timecmp_lo & 0xFFFFFFFF)); + value << 32 | (timecmp_lo & 0xFFFFFFFF), clint->timebase_freq); } else { error_report("clint: invalid timecmp write: %08x", (uint32_t)addr); } @@ -182,7 +184,7 @@ static const MemoryRegionOps sifive_clint_ops = { .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 4, - .max_access_size = 4 + .max_access_size = 8 } }; @@ -193,6 +195,7 @@ static Property sifive_clint_properties[] = { DEFINE_PROP_UINT32("timecmp-base", SiFiveCLINTState, timecmp_base, 0), DEFINE_PROP_UINT32("time-base", SiFiveCLINTState, time_base, 0), DEFINE_PROP_UINT32("aperture-size", SiFiveCLINTState, aperture_size, 0), + DEFINE_PROP_UINT32("timebase-freq", SiFiveCLINTState, timebase_freq, 0), DEFINE_PROP_END_OF_LIST(), }; @@ -231,7 +234,8 @@ type_init(sifive_clint_register_types) */ DeviceState *sifive_clint_create(hwaddr addr, hwaddr size, uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base, - uint32_t timecmp_base, uint32_t time_base, bool provide_rdtime) + uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq, + bool provide_rdtime) { int i; for (i = 0; i < num_harts; i++) { @@ -241,21 +245,22 @@ DeviceState *sifive_clint_create(hwaddr addr, hwaddr size, continue; } if (provide_rdtime) { - riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc); + riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, timebase_freq); } env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &sifive_clint_timer_cb, cpu); env->timecmp = 0; } - DeviceState *dev = qdev_create(NULL, TYPE_SIFIVE_CLINT); + DeviceState *dev = qdev_new(TYPE_SIFIVE_CLINT); qdev_prop_set_uint32(dev, "hartid-base", hartid_base); qdev_prop_set_uint32(dev, "num-harts", num_harts); qdev_prop_set_uint32(dev, "sip-base", sip_base); qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base); qdev_prop_set_uint32(dev, "time-base", time_base); qdev_prop_set_uint32(dev, "aperture-size", size); - qdev_init_nofail(dev); + qdev_prop_set_uint32(dev, "timebase-freq", timebase_freq); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); return dev; } diff --git a/hw/riscv/sifive_plic.c b/hw/intc/sifive_plic.c similarity index 95% rename from hw/riscv/sifive_plic.c rename to hw/intc/sifive_plic.c index 4ed5fd43bf168d64d61a82e24b7655e6bccc8b6b..a419ca3a3c0981be000eb467aa36dd9624a817bf 100644 --- a/hw/riscv/sifive_plic.c +++ b/hw/intc/sifive_plic.c @@ -19,6 +19,7 @@ */ #include "qemu/osdep.h" +#include "qapi/error.h" #include "qemu/log.h" #include "qemu/module.h" #include "qemu/error-report.h" @@ -26,12 +27,12 @@ #include "hw/pci/msi.h" #include "hw/boards.h" #include "hw/qdev-properties.h" +#include "hw/intc/sifive_plic.h" #include "target/riscv/cpu.h" #include "sysemu/sysemu.h" -#include "hw/riscv/sifive_plic.h" +#include "migration/vmstate.h" #include "sysemu/kvm.h" #include "kvm_riscv.h" -#include "migration/vmstate.h" #define RISCV_DEBUG_PLIC 0 @@ -91,12 +92,12 @@ static void sifive_plic_print_state(SiFivePLICState *plic) static uint32_t atomic_set_masked(uint32_t *a, uint32_t mask, uint32_t value) { - uint32_t old, new, cmp = atomic_read(a); + uint32_t old, new, cmp = qatomic_read(a); do { old = cmp; new = (old & ~mask) | (value & mask); - cmp = atomic_cmpxchg(a, old, new); + cmp = qatomic_cmpxchg(a, old, new); } while (old != cmp); return old; @@ -179,6 +180,9 @@ static void sifive_plic_update(SiFivePLICState *plic) static uint32_t sifive_plic_claim(SiFivePLICState *plic, uint32_t addrid) { int i, j; + uint32_t max_irq = 0; + uint32_t max_prio = plic->target_priority[addrid]; + for (i = 0; i < plic->bitfield_words; i++) { uint32_t pending_enabled_not_claimed = (plic->pending[i] & ~plic->claimed[i]) & @@ -190,14 +194,18 @@ static uint32_t sifive_plic_claim(SiFivePLICState *plic, uint32_t addrid) int irq = (i << 5) + j; uint32_t prio = plic->source_priority[irq]; int enabled = pending_enabled_not_claimed & (1 << j); - if (enabled && prio > plic->target_priority[addrid]) { - sifive_plic_set_pending(plic, irq, false); - sifive_plic_set_claimed(plic, irq, true); - return irq; + if (enabled && prio > max_prio) { + max_irq = irq; + max_prio = prio; } } } - return 0; + + if (max_irq) { + sifive_plic_set_pending(plic, max_irq, false); + sifive_plic_set_claimed(plic, max_irq, true); + } + return max_irq; } static uint64_t sifive_plic_read(void *opaque, hwaddr addr, unsigned size) @@ -261,8 +269,8 @@ static uint64_t sifive_plic_read(void *opaque, hwaddr addr, unsigned size) plic->addr_config[addrid].hartid, mode_to_char(plic->addr_config[addrid].mode), value); - sifive_plic_print_state(plic); } + sifive_plic_update(plic); return value; } } @@ -293,6 +301,7 @@ static void sifive_plic_write(void *opaque, hwaddr addr, uint64_t value, qemu_log("plic: write priority: irq=%d priority=%d\n", irq, plic->source_priority[irq]); } + sifive_plic_update(plic); return; } else if (addr >= plic->pending_base && /* 1 bit per source */ addr < plic->pending_base + (plic->num_sources >> 3)) @@ -483,9 +492,11 @@ static const VMStateDescription vmstate_sifive_plic = { .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_VARRAY_UINT32(source_priority, SiFivePLICState, num_sources, 0, + VMSTATE_VARRAY_UINT32(source_priority, SiFivePLICState, + num_sources, 0, vmstate_info_uint32, uint32_t), - VMSTATE_VARRAY_UINT32(target_priority, SiFivePLICState, num_addrs, 0, + VMSTATE_VARRAY_UINT32(target_priority, SiFivePLICState, + num_addrs, 0, vmstate_info_uint32, uint32_t), VMSTATE_VARRAY_UINT32(pending, SiFivePLICState, bitfield_words, 0, vmstate_info_uint32, uint32_t), @@ -530,7 +541,7 @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config, uint32_t enable_stride, uint32_t context_base, uint32_t context_stride, uint32_t aperture_size) { - DeviceState *dev = qdev_create(NULL, TYPE_SIFIVE_PLIC); + DeviceState *dev = qdev_new(TYPE_SIFIVE_PLIC); assert(enable_stride == (enable_stride & -enable_stride)); assert(context_stride == (context_stride & -context_stride)); qdev_prop_set_string(dev, "hart-config", hart_config); @@ -544,7 +555,7 @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config, qdev_prop_set_uint32(dev, "context-base", context_base); qdev_prop_set_uint32(dev, "context-stride", context_stride); qdev_prop_set_uint32(dev, "aperture-size", aperture_size); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); return dev; } diff --git a/hw/intc/slavio_intctl.c b/hw/intc/slavio_intctl.c index c4cf9096eb93b817817fd23c481c1e8139e10047..f7e59ba6432e4dd50ecc45cfa16f3b8a459fc262 100644 --- a/hw/intc/slavio_intctl.c +++ b/hw/intc/slavio_intctl.c @@ -30,6 +30,7 @@ #include "hw/intc/intc.h" #include "hw/irq.h" #include "trace.h" +#include "qom/object.h" //#define DEBUG_IRQ_COUNT @@ -58,10 +59,9 @@ typedef struct SLAVIO_CPUINTCTLState { } SLAVIO_CPUINTCTLState; #define TYPE_SLAVIO_INTCTL "slavio_intctl" -#define SLAVIO_INTCTL(obj) \ - OBJECT_CHECK(SLAVIO_INTCTLState, (obj), TYPE_SLAVIO_INTCTL) +OBJECT_DECLARE_SIMPLE_TYPE(SLAVIO_INTCTLState, SLAVIO_INTCTL) -typedef struct SLAVIO_INTCTLState { +struct SLAVIO_INTCTLState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -73,7 +73,7 @@ typedef struct SLAVIO_INTCTLState { uint32_t intregm_pending; uint32_t intregm_disabled; uint32_t target_cpu; -} SLAVIO_INTCTLState; +}; #define INTCTL_MAXADDR 0xf #define INTCTL_SIZE (INTCTL_MAXADDR + 1) diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 6608d7220a473c43cde6a106eda3f2f35d82292b..1fa09f287ac0e7925631054ffa8d7c83fe1cd6c5 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -148,12 +148,19 @@ static void spapr_xive_end_pic_print_info(SpaprXive *xive, XiveEND *end, xive_end_queue_pic_print_info(end, 6, mon); } +/* + * kvm_irqchip_in_kernel() will cause the compiler to turn this + * info a nop if CONFIG_KVM isn't defined. + */ +#define spapr_xive_in_kernel(xive) \ + (kvm_irqchip_in_kernel() && (xive)->fd != -1) + void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon) { XiveSource *xsrc = &xive->source; int i; - if (kvm_irqchip_in_kernel()) { + if (spapr_xive_in_kernel(xive)) { Error *local_err = NULL; kvmppc_xive_synchronize_state(xive, &local_err); @@ -272,12 +279,10 @@ static void spapr_xive_instance_init(Object *obj) { SpaprXive *xive = SPAPR_XIVE(obj); - object_initialize_child(obj, "source", &xive->source, sizeof(xive->source), - TYPE_XIVE_SOURCE, &error_abort, NULL); + object_initialize_child(obj, "source", &xive->source, TYPE_XIVE_SOURCE); object_initialize_child(obj, "end_source", &xive->end_source, - sizeof(xive->end_source), TYPE_XIVE_END_SOURCE, - &error_abort, NULL); + TYPE_XIVE_END_SOURCE); /* Not connected to the KVM XIVE device */ xive->fd = -1; @@ -310,13 +315,10 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp) /* * Initialize the internal sources, for IPIs and virtual devices. */ - object_property_set_int(OBJECT(xsrc), xive->nr_irqs, "nr-irqs", + object_property_set_int(OBJECT(xsrc), "nr-irqs", xive->nr_irqs, &error_fatal); - object_property_set_link(OBJECT(xsrc), OBJECT(xive), "xive", - &error_abort); - object_property_set_bool(OBJECT(xsrc), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + object_property_set_link(OBJECT(xsrc), "xive", OBJECT(xive), &error_abort); + if (!qdev_realize(DEVICE(xsrc), NULL, errp)) { return; } sysbus_init_mmio(SYS_BUS_DEVICE(xive), &xsrc->esb_mmio); @@ -324,19 +326,17 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp) /* * Initialize the END ESB source */ - object_property_set_int(OBJECT(end_xsrc), xive->nr_irqs, "nr-ends", + object_property_set_int(OBJECT(end_xsrc), "nr-ends", xive->nr_irqs, &error_fatal); - object_property_set_link(OBJECT(end_xsrc), OBJECT(xive), "xive", + object_property_set_link(OBJECT(end_xsrc), "xive", OBJECT(xive), &error_abort); - object_property_set_bool(OBJECT(end_xsrc), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qdev_realize(DEVICE(end_xsrc), NULL, errp)) { return; } sysbus_init_mmio(SYS_BUS_DEVICE(xive), &end_xsrc->esb_mmio); /* Set the mapping address of the END ESB pages after the source ESBs */ - xive->end_base = xive->vc_base + (1ull << xsrc->esb_shift) * xsrc->nr_irqs; + xive->end_base = xive->vc_base + xive_source_esb_len(xsrc); /* * Allocate the routing tables @@ -514,8 +514,10 @@ static const VMStateDescription vmstate_spapr_xive_eas = { static int vmstate_spapr_xive_pre_save(void *opaque) { - if (kvm_irqchip_in_kernel()) { - return kvmppc_xive_pre_save(SPAPR_XIVE(opaque)); + SpaprXive *xive = SPAPR_XIVE(opaque); + + if (spapr_xive_in_kernel(xive)) { + return kvmppc_xive_pre_save(xive); } return 0; @@ -527,8 +529,10 @@ static int vmstate_spapr_xive_pre_save(void *opaque) */ static int spapr_xive_post_load(SpaprInterruptController *intc, int version_id) { - if (kvm_irqchip_in_kernel()) { - return kvmppc_xive_post_load(SPAPR_XIVE(intc), version_id); + SpaprXive *xive = SPAPR_XIVE(intc); + + if (spapr_xive_in_kernel(xive)) { + return kvmppc_xive_post_load(xive, version_id); } return 0; @@ -571,7 +575,7 @@ static int spapr_xive_claim_irq(SpaprInterruptController *intc, int lisn, xive_source_irq_set_lsi(xsrc, lisn); } - if (kvm_irqchip_in_kernel()) { + if (spapr_xive_in_kernel(xive)) { return kvmppc_xive_source_reset_one(xsrc, lisn, errp); } @@ -591,6 +595,7 @@ static Property spapr_xive_properties[] = { DEFINE_PROP_UINT32("nr-ends", SpaprXive, nr_ends, 0), DEFINE_PROP_UINT64("vc-base", SpaprXive, vc_base, SPAPR_XIVE_VC_BASE), DEFINE_PROP_UINT64("tm-base", SpaprXive, tm_base, SPAPR_XIVE_TM_BASE), + DEFINE_PROP_UINT8("hv-prio", SpaprXive, hv_prio, 7), DEFINE_PROP_END_OF_LIST(), }; @@ -648,7 +653,7 @@ static void spapr_xive_set_irq(SpaprInterruptController *intc, int irq, int val) { SpaprXive *xive = SPAPR_XIVE(intc); - if (kvm_irqchip_in_kernel()) { + if (spapr_xive_in_kernel(xive)) { kvmppc_xive_source_set_irq(&xive->source, irq, val); } else { xive_source_set_irq(&xive->source, irq, val); @@ -688,12 +693,13 @@ static void spapr_xive_dt(SpaprInterruptController *intc, uint32_t nr_servers, cpu_to_be32(16), /* 64K */ }; /* - * The following array is in sync with the reserved priorities - * defined by the 'spapr_xive_priority_is_reserved' routine. + * QEMU/KVM only needs to define a single range to reserve the + * escalation priority. A priority bitmask would have been more + * appropriate. */ uint32_t plat_res_int_priorities[] = { - cpu_to_be32(7), /* start */ - cpu_to_be32(0xf8), /* count */ + cpu_to_be32(xive->hv_prio), /* start */ + cpu_to_be32(0xff - xive->hv_prio), /* count */ }; /* Thread Interrupt Management Area : User (ring 3) and OS (ring 2) */ @@ -756,11 +762,16 @@ static void spapr_xive_deactivate(SpaprInterruptController *intc) spapr_xive_mmio_set_enabled(xive, false); - if (kvm_irqchip_in_kernel()) { + if (spapr_xive_in_kernel(xive)) { kvmppc_xive_disconnect(intc); } } +static bool spapr_xive_in_kernel_xptr(const XivePresenter *xptr) +{ + return spapr_xive_in_kernel(SPAPR_XIVE(xptr)); +} + static void spapr_xive_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -795,6 +806,7 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data) sicc->post_load = spapr_xive_post_load; xpc->match_nvt = spapr_xive_match_nvt; + xpc->in_kernel = spapr_xive_in_kernel_xptr; } static const TypeInfo spapr_xive_info = { @@ -834,19 +846,12 @@ type_init(spapr_xive_register_types) */ /* - * Linux hosts under OPAL reserve priority 7 for their own escalation - * interrupts (DD2.X POWER9). So we only allow the guest to use - * priorities [0..6]. + * On POWER9, the KVM XIVE device uses priority 7 for the escalation + * interrupts. So we only allow the guest to use priorities [0..6]. */ -static bool spapr_xive_priority_is_reserved(uint8_t priority) +static bool spapr_xive_priority_is_reserved(SpaprXive *xive, uint8_t priority) { - switch (priority) { - case 0 ... 6: - return false; - case 7: /* OPAL escalation queue */ - default: - return true; - } + return priority >= xive->hv_prio; } /* @@ -1043,7 +1048,7 @@ static target_ulong h_int_set_source_config(PowerPCCPU *cpu, new_eas.w = eas.w & cpu_to_be64(~EAS_MASKED); } - if (spapr_xive_priority_is_reserved(priority)) { + if (spapr_xive_priority_is_reserved(xive, priority)) { qemu_log_mask(LOG_GUEST_ERROR, "XIVE: priority " TARGET_FMT_ld " is reserved\n", priority); return H_P4; @@ -1065,7 +1070,7 @@ static target_ulong h_int_set_source_config(PowerPCCPU *cpu, new_eas.w = xive_set_field64(EAS_END_DATA, new_eas.w, eisn); } - if (kvm_irqchip_in_kernel()) { + if (spapr_xive_in_kernel(xive)) { Error *local_err = NULL; kvmppc_xive_set_source_config(xive, lisn, &new_eas, &local_err); @@ -1202,7 +1207,7 @@ static target_ulong h_int_get_queue_info(PowerPCCPU *cpu, * This is not needed when running the emulation under QEMU */ - if (spapr_xive_priority_is_reserved(priority)) { + if (spapr_xive_priority_is_reserved(xive, priority)) { qemu_log_mask(LOG_GUEST_ERROR, "XIVE: priority " TARGET_FMT_ld " is reserved\n", priority); return H_P3; @@ -1289,7 +1294,7 @@ static target_ulong h_int_set_queue_config(PowerPCCPU *cpu, * This is not needed when running the emulation under QEMU */ - if (spapr_xive_priority_is_reserved(priority)) { + if (spapr_xive_priority_is_reserved(xive, priority)) { qemu_log_mask(LOG_GUEST_ERROR, "XIVE: priority " TARGET_FMT_ld " is reserved\n", priority); return H_P3; @@ -1386,7 +1391,7 @@ static target_ulong h_int_set_queue_config(PowerPCCPU *cpu, */ out: - if (kvm_irqchip_in_kernel()) { + if (spapr_xive_in_kernel(xive)) { Error *local_err = NULL; kvmppc_xive_set_queue_config(xive, end_blk, end_idx, &end, &local_err); @@ -1456,7 +1461,7 @@ static target_ulong h_int_get_queue_config(PowerPCCPU *cpu, * This is not needed when running the emulation under QEMU */ - if (spapr_xive_priority_is_reserved(priority)) { + if (spapr_xive_priority_is_reserved(xive, priority)) { qemu_log_mask(LOG_GUEST_ERROR, "XIVE: priority " TARGET_FMT_ld " is reserved\n", priority); return H_P3; @@ -1487,7 +1492,7 @@ static target_ulong h_int_get_queue_config(PowerPCCPU *cpu, args[2] = 0; } - if (kvm_irqchip_in_kernel()) { + if (spapr_xive_in_kernel(xive)) { Error *local_err = NULL; kvmppc_xive_get_queue_config(xive, end_blk, end_idx, end, &local_err); @@ -1649,7 +1654,7 @@ static target_ulong h_int_esb(PowerPCCPU *cpu, return H_P3; } - if (kvm_irqchip_in_kernel()) { + if (spapr_xive_in_kernel(xive)) { args[0] = kvmppc_xive_esb_rw(xsrc, lisn, offset, data, flags & SPAPR_XIVE_ESB_STORE); } else { @@ -1724,7 +1729,7 @@ static target_ulong h_int_sync(PowerPCCPU *cpu, * under KVM */ - if (kvm_irqchip_in_kernel()) { + if (spapr_xive_in_kernel(xive)) { Error *local_err = NULL; kvmppc_xive_sync_source(xive, lisn, &local_err); @@ -1768,7 +1773,7 @@ static target_ulong h_int_reset(PowerPCCPU *cpu, device_legacy_reset(DEVICE(xive)); - if (kvm_irqchip_in_kernel()) { + if (spapr_xive_in_kernel(xive)) { Error *local_err = NULL; kvmppc_xive_reset(xive, &local_err); diff --git a/hw/intc/spapr_xive_kvm.c b/hw/intc/spapr_xive_kvm.c index edb7ee0e74f19c34cc416c73c5fe9fd8d78eb28e..e8667ce5f621e58591c958c0f43583053b297c3b 100644 --- a/hw/intc/spapr_xive_kvm.c +++ b/hw/intc/spapr_xive_kvm.c @@ -73,54 +73,54 @@ static void kvm_cpu_disable_all(void) * XIVE Thread Interrupt Management context (KVM) */ -void kvmppc_xive_cpu_set_state(XiveTCTX *tctx, Error **errp) +int kvmppc_xive_cpu_set_state(XiveTCTX *tctx, Error **errp) { SpaprXive *xive = SPAPR_XIVE(tctx->xptr); uint64_t state[2]; int ret; - /* The KVM XIVE device is not in use yet */ - if (xive->fd == -1) { - return; - } + assert(xive->fd != -1); /* word0 and word1 of the OS ring. */ state[0] = *((uint64_t *) &tctx->regs[TM_QW1_OS]); ret = kvm_set_one_reg(tctx->cs, KVM_REG_PPC_VP_STATE, state); if (ret != 0) { - error_setg_errno(errp, errno, + error_setg_errno(errp, -ret, "XIVE: could not restore KVM state of CPU %ld", kvm_arch_vcpu_id(tctx->cs)); + return ret; } + + return 0; } -void kvmppc_xive_cpu_get_state(XiveTCTX *tctx, Error **errp) +int kvmppc_xive_cpu_get_state(XiveTCTX *tctx, Error **errp) { SpaprXive *xive = SPAPR_XIVE(tctx->xptr); uint64_t state[2] = { 0 }; int ret; - /* The KVM XIVE device is not in use */ - if (xive->fd == -1) { - return; - } + assert(xive->fd != -1); ret = kvm_get_one_reg(tctx->cs, KVM_REG_PPC_VP_STATE, state); if (ret != 0) { - error_setg_errno(errp, errno, + error_setg_errno(errp, -ret, "XIVE: could not capture KVM state of CPU %ld", kvm_arch_vcpu_id(tctx->cs)); - return; + return ret; } /* word0 and word1 of the OS ring. */ *((uint64_t *) &tctx->regs[TM_QW1_OS]) = state[0]; + + return 0; } typedef struct { XiveTCTX *tctx; - Error *err; + Error **errp; + int ret; } XiveCpuGetState; static void kvmppc_xive_cpu_do_synchronize_state(CPUState *cpu, @@ -128,14 +128,14 @@ static void kvmppc_xive_cpu_do_synchronize_state(CPUState *cpu, { XiveCpuGetState *s = arg.host_ptr; - kvmppc_xive_cpu_get_state(s->tctx, &s->err); + s->ret = kvmppc_xive_cpu_get_state(s->tctx, s->errp); } -void kvmppc_xive_cpu_synchronize_state(XiveTCTX *tctx, Error **errp) +int kvmppc_xive_cpu_synchronize_state(XiveTCTX *tctx, Error **errp) { XiveCpuGetState s = { .tctx = tctx, - .err = NULL, + .errp = errp, }; /* @@ -144,26 +144,21 @@ void kvmppc_xive_cpu_synchronize_state(XiveTCTX *tctx, Error **errp) run_on_cpu(tctx->cs, kvmppc_xive_cpu_do_synchronize_state, RUN_ON_CPU_HOST_PTR(&s)); - if (s.err) { - error_propagate(errp, s.err); - return; - } + return s.ret; } -void kvmppc_xive_cpu_connect(XiveTCTX *tctx, Error **errp) +int kvmppc_xive_cpu_connect(XiveTCTX *tctx, Error **errp) { + ERRP_GUARD(); SpaprXive *xive = SPAPR_XIVE(tctx->xptr); unsigned long vcpu_id; int ret; - /* The KVM XIVE device is not in use */ - if (xive->fd == -1) { - return; - } + assert(xive->fd != -1); /* Check if CPU was hot unplugged and replugged. */ if (kvm_cpu_is_enabled(tctx->cs)) { - return; + return 0; } vcpu_id = kvm_arch_vcpu_id(tctx->cs); @@ -171,28 +166,26 @@ void kvmppc_xive_cpu_connect(XiveTCTX *tctx, Error **errp) ret = kvm_vcpu_enable_cap(tctx->cs, KVM_CAP_PPC_IRQ_XIVE, 0, xive->fd, vcpu_id, 0); if (ret < 0) { - Error *local_err = NULL; - - error_setg(&local_err, - "XIVE: unable to connect CPU%ld to KVM device: %s", - vcpu_id, strerror(errno)); - if (errno == ENOSPC) { - error_append_hint(&local_err, "Try -smp maxcpus=N with N < %u\n", + error_setg_errno(errp, -ret, + "XIVE: unable to connect CPU%ld to KVM device", + vcpu_id); + if (ret == -ENOSPC) { + error_append_hint(errp, "Try -smp maxcpus=N with N < %u\n", MACHINE(qdev_get_machine())->smp.max_cpus); } - error_propagate(errp, local_err); - return; + return ret; } kvm_cpu_enable(tctx->cs); + return 0; } /* * XIVE Interrupt Source (KVM) */ -void kvmppc_xive_set_source_config(SpaprXive *xive, uint32_t lisn, XiveEAS *eas, - Error **errp) +int kvmppc_xive_set_source_config(SpaprXive *xive, uint32_t lisn, XiveEAS *eas, + Error **errp) { uint32_t end_idx; uint32_t end_blk; @@ -201,7 +194,6 @@ void kvmppc_xive_set_source_config(SpaprXive *xive, uint32_t lisn, XiveEAS *eas, bool masked; uint32_t eisn; uint64_t kvm_src; - Error *local_err = NULL; assert(xive_eas_is_valid(eas)); @@ -221,12 +213,8 @@ void kvmppc_xive_set_source_config(SpaprXive *xive, uint32_t lisn, XiveEAS *eas, kvm_src |= ((uint64_t)eisn << KVM_XIVE_SOURCE_EISN_SHIFT) & KVM_XIVE_SOURCE_EISN_MASK; - kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_SOURCE_CONFIG, lisn, - &kvm_src, true, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } + return kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_SOURCE_CONFIG, lisn, + &kvm_src, true, errp); } void kvmppc_xive_sync_source(SpaprXive *xive, uint32_t lisn, Error **errp) @@ -245,10 +233,7 @@ int kvmppc_xive_source_reset_one(XiveSource *xsrc, int srcno, Error **errp) SpaprXive *xive = SPAPR_XIVE(xsrc->xive); uint64_t state = 0; - /* The KVM XIVE device is not in use */ - if (xive->fd == -1) { - return -ENODEV; - } + assert(xive->fd != -1); if (xive_source_irq_is_lsi(xsrc, srcno)) { state |= KVM_XIVE_LEVEL_SENSITIVE; @@ -261,24 +246,25 @@ int kvmppc_xive_source_reset_one(XiveSource *xsrc, int srcno, Error **errp) true, errp); } -static void kvmppc_xive_source_reset(XiveSource *xsrc, Error **errp) +static int kvmppc_xive_source_reset(XiveSource *xsrc, Error **errp) { SpaprXive *xive = SPAPR_XIVE(xsrc->xive); int i; for (i = 0; i < xsrc->nr_irqs; i++) { - Error *local_err = NULL; + int ret; if (!xive_eas_is_valid(&xive->eat[i])) { continue; } - kvmppc_xive_source_reset_one(xsrc, i, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; + ret = kvmppc_xive_source_reset_one(xsrc, i, errp); + if (ret < 0) { + return ret; } } + + return 0; } /* @@ -381,15 +367,15 @@ void kvmppc_xive_source_set_irq(void *opaque, int srcno, int val) /* * sPAPR XIVE interrupt controller (KVM) */ -void kvmppc_xive_get_queue_config(SpaprXive *xive, uint8_t end_blk, - uint32_t end_idx, XiveEND *end, - Error **errp) +int kvmppc_xive_get_queue_config(SpaprXive *xive, uint8_t end_blk, + uint32_t end_idx, XiveEND *end, + Error **errp) { struct kvm_ppc_xive_eq kvm_eq = { 0 }; uint64_t kvm_eq_idx; uint8_t priority; uint32_t server; - Error *local_err = NULL; + int ret; assert(xive_end_is_valid(end)); @@ -401,11 +387,10 @@ void kvmppc_xive_get_queue_config(SpaprXive *xive, uint8_t end_blk, kvm_eq_idx |= server << KVM_XIVE_EQ_SERVER_SHIFT & KVM_XIVE_EQ_SERVER_MASK; - kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_EQ_CONFIG, kvm_eq_idx, - &kvm_eq, false, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; + ret = kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_EQ_CONFIG, kvm_eq_idx, + &kvm_eq, false, errp); + if (ret < 0) { + return ret; } /* @@ -415,17 +400,18 @@ void kvmppc_xive_get_queue_config(SpaprXive *xive, uint8_t end_blk, */ end->w1 = xive_set_field32(END_W1_GENERATION, 0ul, kvm_eq.qtoggle) | xive_set_field32(END_W1_PAGE_OFF, 0ul, kvm_eq.qindex); + + return 0; } -void kvmppc_xive_set_queue_config(SpaprXive *xive, uint8_t end_blk, - uint32_t end_idx, XiveEND *end, - Error **errp) +int kvmppc_xive_set_queue_config(SpaprXive *xive, uint8_t end_blk, + uint32_t end_idx, XiveEND *end, + Error **errp) { struct kvm_ppc_xive_eq kvm_eq = { 0 }; uint64_t kvm_eq_idx; uint8_t priority; uint32_t server; - Error *local_err = NULL; /* * Build the KVM state from the local END structure. @@ -463,12 +449,9 @@ void kvmppc_xive_set_queue_config(SpaprXive *xive, uint8_t end_blk, kvm_eq_idx |= server << KVM_XIVE_EQ_SERVER_SHIFT & KVM_XIVE_EQ_SERVER_MASK; - kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_EQ_CONFIG, kvm_eq_idx, - &kvm_eq, true, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } + return + kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_EQ_CONFIG, kvm_eq_idx, + &kvm_eq, true, errp); } void kvmppc_xive_reset(SpaprXive *xive, Error **errp) @@ -477,23 +460,24 @@ void kvmppc_xive_reset(SpaprXive *xive, Error **errp) NULL, true, errp); } -static void kvmppc_xive_get_queues(SpaprXive *xive, Error **errp) +static int kvmppc_xive_get_queues(SpaprXive *xive, Error **errp) { - Error *local_err = NULL; int i; + int ret; for (i = 0; i < xive->nr_ends; i++) { if (!xive_end_is_valid(&xive->endt[i])) { continue; } - kvmppc_xive_get_queue_config(xive, SPAPR_XIVE_BLOCK_ID, i, - &xive->endt[i], &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; + ret = kvmppc_xive_get_queue_config(xive, SPAPR_XIVE_BLOCK_ID, i, + &xive->endt[i], errp); + if (ret < 0) { + return ret; } } + + return 0; } /* @@ -592,10 +576,7 @@ static void kvmppc_xive_change_state_handler(void *opaque, int running, void kvmppc_xive_synchronize_state(SpaprXive *xive, Error **errp) { - /* The KVM XIVE device is not in use */ - if (xive->fd == -1) { - return; - } + assert(xive->fd != -1); /* * When the VM is stopped, the sources are masked and the previous @@ -621,19 +602,17 @@ void kvmppc_xive_synchronize_state(SpaprXive *xive, Error **errp) int kvmppc_xive_pre_save(SpaprXive *xive) { Error *local_err = NULL; + int ret; - /* The KVM XIVE device is not in use */ - if (xive->fd == -1) { - return 0; - } + assert(xive->fd != -1); /* EAT: there is no extra state to query from KVM */ /* ENDT */ - kvmppc_xive_get_queues(xive, &local_err); - if (local_err) { + ret = kvmppc_xive_get_queues(xive, &local_err); + if (ret < 0) { error_report_err(local_err); - return -1; + return ret; } return 0; @@ -650,6 +629,7 @@ int kvmppc_xive_post_load(SpaprXive *xive, int version_id) Error *local_err = NULL; CPUState *cs; int i; + int ret; /* The KVM XIVE device should be in use */ assert(xive->fd != -1); @@ -660,11 +640,10 @@ int kvmppc_xive_post_load(SpaprXive *xive, int version_id) continue; } - kvmppc_xive_set_queue_config(xive, SPAPR_XIVE_BLOCK_ID, i, - &xive->endt[i], &local_err); - if (local_err) { - error_report_err(local_err); - return -1; + ret = kvmppc_xive_set_queue_config(xive, SPAPR_XIVE_BLOCK_ID, i, + &xive->endt[i], &local_err); + if (ret < 0) { + goto fail; } } @@ -679,16 +658,14 @@ int kvmppc_xive_post_load(SpaprXive *xive, int version_id) * previously set in KVM. Since we don't do that for all interrupts * at reset time anymore, let's do it now. */ - kvmppc_xive_source_reset_one(&xive->source, i, &local_err); - if (local_err) { - error_report_err(local_err); - return -1; + ret = kvmppc_xive_source_reset_one(&xive->source, i, &local_err); + if (ret < 0) { + goto fail; } - kvmppc_xive_set_source_config(xive, i, &xive->eat[i], &local_err); - if (local_err) { - error_report_err(local_err); - return -1; + ret = kvmppc_xive_set_source_config(xive, i, &xive->eat[i], &local_err); + if (ret < 0) { + goto fail; } } @@ -705,17 +682,21 @@ int kvmppc_xive_post_load(SpaprXive *xive, int version_id) CPU_FOREACH(cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); - kvmppc_xive_cpu_set_state(spapr_cpu_state(cpu)->tctx, &local_err); - if (local_err) { - error_report_err(local_err); - return -1; + ret = kvmppc_xive_cpu_set_state(spapr_cpu_state(cpu)->tctx, &local_err); + if (ret < 0) { + goto fail; } } /* The source states will be restored when the machine starts running */ return 0; + +fail: + error_report_err(local_err); + return ret; } +/* Returns MAP_FAILED on error and sets errno */ static void *kvmppc_xive_mmap(SpaprXive *xive, int pgoff, size_t len, Error **errp) { @@ -726,7 +707,6 @@ static void *kvmppc_xive_mmap(SpaprXive *xive, int pgoff, size_t len, pgoff << page_shift); if (addr == MAP_FAILED) { error_setg_errno(errp, errno, "XIVE: unable to set memory mapping"); - return NULL; } return addr; @@ -741,10 +721,12 @@ int kvmppc_xive_connect(SpaprInterruptController *intc, uint32_t nr_servers, { SpaprXive *xive = SPAPR_XIVE(intc); XiveSource *xsrc = &xive->source; - Error *local_err = NULL; - size_t esb_len = (1ull << xsrc->esb_shift) * xsrc->nr_irqs; + size_t esb_len = xive_source_esb_len(xsrc); size_t tima_len = 4ull << TM_SHIFT; CPUState *cs; + int fd; + void *addr; + int ret; /* * The KVM XIVE device already in use. This is the case when @@ -760,18 +742,20 @@ int kvmppc_xive_connect(SpaprInterruptController *intc, uint32_t nr_servers, } /* First, create the KVM XIVE device */ - xive->fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_XIVE, false); - if (xive->fd < 0) { - error_setg_errno(errp, -xive->fd, "XIVE: error creating KVM device"); + fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_XIVE, false); + if (fd < 0) { + error_setg_errno(errp, -fd, "XIVE: error creating KVM device"); return -1; } + xive->fd = fd; /* Tell KVM about the # of VCPUs we may have */ if (kvm_device_check_attr(xive->fd, KVM_DEV_XIVE_GRP_CTRL, KVM_DEV_XIVE_NR_SERVERS)) { - if (kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_CTRL, - KVM_DEV_XIVE_NR_SERVERS, &nr_servers, true, - &local_err)) { + ret = kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_CTRL, + KVM_DEV_XIVE_NR_SERVERS, &nr_servers, true, + errp); + if (ret < 0) { goto fail; } } @@ -779,14 +763,14 @@ int kvmppc_xive_connect(SpaprInterruptController *intc, uint32_t nr_servers, /* * 1. Source ESB pages - KVM mapping */ - xsrc->esb_mmap = kvmppc_xive_mmap(xive, KVM_XIVE_ESB_PAGE_OFFSET, esb_len, - &local_err); - if (local_err) { + addr = kvmppc_xive_mmap(xive, KVM_XIVE_ESB_PAGE_OFFSET, esb_len, errp); + if (addr == MAP_FAILED) { goto fail; } + xsrc->esb_mmap = addr; memory_region_init_ram_device_ptr(&xsrc->esb_mmio_kvm, OBJECT(xsrc), - "xive.esb", esb_len, xsrc->esb_mmap); + "xive.esb-kvm", esb_len, xsrc->esb_mmap); memory_region_add_subregion_overlap(&xsrc->esb_mmio, 0, &xsrc->esb_mmio_kvm, 1); @@ -797,11 +781,12 @@ int kvmppc_xive_connect(SpaprInterruptController *intc, uint32_t nr_servers, /* * 3. TIMA pages - KVM mapping */ - xive->tm_mmap = kvmppc_xive_mmap(xive, KVM_XIVE_TIMA_PAGE_OFFSET, tima_len, - &local_err); - if (local_err) { + addr = kvmppc_xive_mmap(xive, KVM_XIVE_TIMA_PAGE_OFFSET, tima_len, errp); + if (addr == MAP_FAILED) { goto fail; } + xive->tm_mmap = addr; + memory_region_init_ram_device_ptr(&xive->tm_mmio_kvm, OBJECT(xive), "xive.tima", tima_len, xive->tm_mmap); memory_region_add_subregion_overlap(&xive->tm_mmio, 0, @@ -814,15 +799,15 @@ int kvmppc_xive_connect(SpaprInterruptController *intc, uint32_t nr_servers, CPU_FOREACH(cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); - kvmppc_xive_cpu_connect(spapr_cpu_state(cpu)->tctx, &local_err); - if (local_err) { + ret = kvmppc_xive_cpu_connect(spapr_cpu_state(cpu)->tctx, errp); + if (ret < 0) { goto fail; } } /* Update the KVM sources */ - kvmppc_xive_source_reset(xsrc, &local_err); - if (local_err) { + ret = kvmppc_xive_source_reset(xsrc, errp); + if (ret < 0) { goto fail; } @@ -832,7 +817,6 @@ int kvmppc_xive_connect(SpaprInterruptController *intc, uint32_t nr_servers, return 0; fail: - error_propagate(errp, local_err); kvmppc_xive_disconnect(intc); return -1; } @@ -843,14 +827,11 @@ void kvmppc_xive_disconnect(SpaprInterruptController *intc) XiveSource *xsrc; size_t esb_len; - /* The KVM XIVE device is not in use */ - if (!xive || xive->fd == -1) { - return; - } + assert(xive->fd != -1); /* Clear the KVM mapping */ xsrc = &xive->source; - esb_len = (1ull << xsrc->esb_shift) * xsrc->nr_irqs; + esb_len = xive_source_esb_len(xsrc); if (xsrc->esb_mmap) { memory_region_del_subregion(&xsrc->esb_mmio, &xsrc->esb_mmio_kvm); @@ -871,10 +852,8 @@ void kvmppc_xive_disconnect(SpaprInterruptController *intc) * and removed from the list of devices of the VM. The VCPU * presenters are also detached from the device. */ - if (xive->fd != -1) { - close(xive->fd); - xive->fd = -1; - } + close(xive->fd); + xive->fd = -1; kvm_kernel_irqchip = false; kvm_msi_via_irqfd_allowed = false; diff --git a/hw/intc/trace-events b/hw/intc/trace-events index 527c3f76caed5dd66f2b183627e946a013b00afc..22782b3f089b5d4febc5179353a2518bb8cc25c2 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -199,3 +199,7 @@ nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg wri heathrow_write(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64 heathrow_read(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64 heathrow_set_irq(int num, int level) "set_irq: num=0x%02x level=%d" + +# bcm2835_ic.c +bcm2835_ic_set_gpu_irq(int irq, int level) "GPU irq #%d level %d" +bcm2835_ic_set_cpu_irq(int irq, int level) "CPU irq #%d level %d" diff --git a/hw/intc/trace.h b/hw/intc/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..02394aea201ca35f1338b2e4b6ac4367d9079993 --- /dev/null +++ b/hw/intc/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_intc.h" diff --git a/hw/intc/xics.c b/hw/intc/xics.c index d5032c8f8a4bd5d9bca1ad9a42417ebb99719507..68f9d44feb412db3d9fb0ec78af7e0c9d303a1f2 100644 --- a/hw/intc/xics.c +++ b/hw/intc/xics.c @@ -376,18 +376,15 @@ static const TypeInfo icp_info = { Object *icp_create(Object *cpu, const char *type, XICSFabric *xi, Error **errp) { - Error *local_err = NULL; Object *obj; obj = object_new(type); object_property_add_child(cpu, type, obj); object_unref(obj); - object_property_set_link(obj, OBJECT(xi), ICP_PROP_XICS, &error_abort); - object_property_set_link(obj, cpu, ICP_PROP_CPU, &error_abort); - object_property_set_bool(obj, true, "realized", &local_err); - if (local_err) { + object_property_set_link(obj, ICP_PROP_XICS, OBJECT(xi), &error_abort); + object_property_set_link(obj, ICP_PROP_CPU, cpu, &error_abort); + if (!qdev_realize(DEVICE(obj), NULL, errp)) { object_unparent(obj); - error_propagate(errp, local_err); obj = NULL; } diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c index 8d6156578fbc1e39e75c21e958354ec7619af763..68bb1914b9bbbba6977de8ec83a7c5c31280896b 100644 --- a/hw/intc/xics_kvm.c +++ b/hw/intc/xics_kvm.c @@ -309,16 +309,14 @@ int ics_set_kvm_state(ICSState *ics, Error **errp) } for (i = 0; i < ics->nr_irqs; i++) { - Error *local_err = NULL; int ret; if (ics_irq_free(ics, i)) { continue; } - ret = ics_set_kvm_state_one(ics, i, &local_err); + ret = ics_set_kvm_state_one(ics, i, errp); if (ret < 0) { - error_propagate(errp, local_err); return ret; } } diff --git a/hw/intc/xics_pnv.c b/hw/intc/xics_pnv.c index 35f38112649f908eeb985c3d981937a3b112e24a..753c067f172ea08c9b32551eec5c0eb06c690b12 100644 --- a/hw/intc/xics_pnv.c +++ b/hw/intc/xics_pnv.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2 of + * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but diff --git a/hw/intc/xilinx_intc.c b/hw/intc/xilinx_intc.c index 3e65e68619969deeeae01e8278ee1c595f4a1db4..4c4397b3d2c35d3b9edc21516f33d3c02d8ace45 100644 --- a/hw/intc/xilinx_intc.c +++ b/hw/intc/xilinx_intc.c @@ -27,6 +27,7 @@ #include "qemu/module.h" #include "hw/irq.h" #include "hw/qdev-properties.h" +#include "qom/object.h" #define D(x) @@ -41,7 +42,8 @@ #define R_MAX 8 #define TYPE_XILINX_INTC "xlnx.xps-intc" -#define XILINX_INTC(obj) OBJECT_CHECK(struct xlx_pic, (obj), TYPE_XILINX_INTC) +DECLARE_INSTANCE_CHECKER(struct xlx_pic, XILINX_INTC, + TYPE_XILINX_INTC) struct xlx_pic { diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 8f2b4050cb2579326b17f9b49278c5d44335f1a2..489e6256ef702cce8fb0fbbb975bf88655394b8a 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -592,6 +592,17 @@ static const char * const xive_tctx_ring_names[] = { "USER", "OS", "POOL", "PHYS", }; +/* + * kvm_irqchip_in_kernel() will cause the compiler to turn this + * info a nop if CONFIG_KVM isn't defined. + */ +#define xive_in_kernel(xptr) \ + (kvm_irqchip_in_kernel() && \ + ({ \ + XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); \ + xpc->in_kernel ? xpc->in_kernel(xptr) : false; \ + })) + void xive_tctx_pic_print_info(XiveTCTX *tctx, Monitor *mon) { int cpu_index; @@ -606,7 +617,7 @@ void xive_tctx_pic_print_info(XiveTCTX *tctx, Monitor *mon) cpu_index = tctx->cs ? tctx->cs->cpu_index : -1; - if (kvm_irqchip_in_kernel()) { + if (xive_in_kernel(tctx->xptr)) { Error *local_err = NULL; kvmppc_xive_cpu_synchronize_state(tctx, &local_err); @@ -651,7 +662,6 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp) XiveTCTX *tctx = XIVE_TCTX(dev); PowerPCCPU *cpu; CPUPPCState *env; - Error *local_err = NULL; assert(tctx->cs); assert(tctx->xptr); @@ -671,10 +681,8 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp) } /* Connect the presenter to the VCPU (required for CPU hotplug) */ - if (kvm_irqchip_in_kernel()) { - kvmppc_xive_cpu_connect(tctx, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (xive_in_kernel(tctx->xptr)) { + if (kvmppc_xive_cpu_connect(tctx, errp) < 0) { return; } } @@ -682,13 +690,15 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp) static int vmstate_xive_tctx_pre_save(void *opaque) { + XiveTCTX *tctx = XIVE_TCTX(opaque); Error *local_err = NULL; + int ret; - if (kvm_irqchip_in_kernel()) { - kvmppc_xive_cpu_get_state(XIVE_TCTX(opaque), &local_err); - if (local_err) { + if (xive_in_kernel(tctx->xptr)) { + ret = kvmppc_xive_cpu_get_state(tctx, &local_err); + if (ret < 0) { error_report_err(local_err); - return -1; + return ret; } } @@ -697,17 +707,19 @@ static int vmstate_xive_tctx_pre_save(void *opaque) static int vmstate_xive_tctx_post_load(void *opaque, int version_id) { + XiveTCTX *tctx = XIVE_TCTX(opaque); Error *local_err = NULL; + int ret; - if (kvm_irqchip_in_kernel()) { + if (xive_in_kernel(tctx->xptr)) { /* * Required for hotplugged CPU, for which the state comes * after all states of the machine. */ - kvmppc_xive_cpu_set_state(XIVE_TCTX(opaque), &local_err); - if (local_err) { + ret = kvmppc_xive_cpu_set_state(tctx, &local_err); + if (ret < 0) { error_report_err(local_err); - return -1; + return ret; } } @@ -757,25 +769,18 @@ static const TypeInfo xive_tctx_info = { Object *xive_tctx_create(Object *cpu, XivePresenter *xptr, Error **errp) { - Error *local_err = NULL; Object *obj; obj = object_new(TYPE_XIVE_TCTX); object_property_add_child(cpu, TYPE_XIVE_TCTX, obj); object_unref(obj); - object_property_set_link(obj, cpu, "cpu", &error_abort); - object_property_set_link(obj, OBJECT(xptr), "presenter", &error_abort); - object_property_set_bool(obj, true, "realized", &local_err); - if (local_err) { - goto error; + object_property_set_link(obj, "cpu", cpu, &error_abort); + object_property_set_link(obj, "presenter", OBJECT(xptr), &error_abort); + if (!qdev_realize(DEVICE(obj), NULL, errp)) { + object_unparent(obj); + return NULL; } - return obj; - -error: - object_unparent(obj); - error_propagate(errp, local_err); - return NULL; } void xive_tctx_destroy(XiveTCTX *tctx) @@ -1135,6 +1140,7 @@ static void xive_source_reset(void *dev) static void xive_source_realize(DeviceState *dev, Error **errp) { XiveSource *xsrc = XIVE_SOURCE(dev); + size_t esb_len = xive_source_esb_len(xsrc); assert(xsrc->xive); @@ -1154,11 +1160,11 @@ static void xive_source_realize(DeviceState *dev, Error **errp) xsrc->status = g_malloc0(xsrc->nr_irqs); xsrc->lsi_map = bitmap_new(xsrc->nr_irqs); - if (!kvm_irqchip_in_kernel()) { - memory_region_init_io(&xsrc->esb_mmio, OBJECT(xsrc), - &xive_source_esb_ops, xsrc, "xive.esb", - (1ull << xsrc->esb_shift) * xsrc->nr_irqs); - } + memory_region_init(&xsrc->esb_mmio, OBJECT(xsrc), "xive.esb", esb_len); + memory_region_init_io(&xsrc->esb_mmio_emulated, OBJECT(xsrc), + &xive_source_esb_ops, xsrc, "xive.esb-emulated", + esb_len); + memory_region_add_subregion(&xsrc->esb_mmio, 0, &xsrc->esb_mmio_emulated); qemu_register_reset(xive_source_reset, dev); } @@ -1509,7 +1515,7 @@ static bool xive_presenter_notify(XiveFabric *xfb, uint8_t format, /* * Notification using the END ESe/ESn bit (Event State Buffer for - * escalation and notification). Profide futher coalescing in the + * escalation and notification). Provide further coalescing in the * Router. */ static bool xive_router_end_es_notify(XiveRouter *xrtr, uint8_t end_blk, @@ -1588,7 +1594,7 @@ static void xive_router_end_notify(XiveRouter *xrtr, uint8_t end_blk, /* * Check the END ESn (Event State Buffer for notification) for - * even futher coalescing in the Router + * even further coalescing in the Router */ if (!xive_end_is_notify(&end)) { /* ESn[Q]=1 : end of notification */ @@ -1667,7 +1673,7 @@ do_escalation: /* * Check the END ESe (Event State Buffer for escalation) for even - * futher coalescing in the Router + * further coalescing in the Router */ if (!xive_end_is_uncond_escalation(&end)) { /* ESe[Q]=1 : end of notification */ diff --git a/hw/ipack/Makefile.objs b/hw/ipack/Makefile.objs deleted file mode 100644 index 8b9bdcb5498a8ffe307f091ea0807b54e20e2093..0000000000000000000000000000000000000000 --- a/hw/ipack/Makefile.objs +++ /dev/null @@ -1,2 +0,0 @@ -common-obj-$(CONFIG_IPACK) += ipack.o -common-obj-$(CONFIG_IPACK) += tpci200.o diff --git a/hw/ipack/meson.build b/hw/ipack/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..3f8138b6f21b8b16681a906545a0f5ba2ee4eae2 --- /dev/null +++ b/hw/ipack/meson.build @@ -0,0 +1 @@ +softmmu_ss.add(when: 'CONFIG_IPACK', if_true: files('ipack.c', 'tpci200.c')) diff --git a/hw/ipack/tpci200.c b/hw/ipack/tpci200.c index f931d4df62762ce5b0bfe291682866ba2be9142c..d107e134c4e94ae06ccd9687e7ba15c5cae0c7da 100644 --- a/hw/ipack/tpci200.c +++ b/hw/ipack/tpci200.c @@ -16,6 +16,7 @@ #include "migration/vmstate.h" #include "qemu/bitops.h" #include "qemu/module.h" +#include "qom/object.h" /* #define DEBUG_TPCI */ @@ -54,7 +55,7 @@ #define REG_STATUS 0x0C #define IP_N_FROM_REG(REG) ((REG) / 2 - 1) -typedef struct { +struct TPCI200State { PCIDevice dev; IPackBus bus; MemoryRegion mmio; @@ -67,12 +68,11 @@ typedef struct { uint8_t ctrl[N_MODULES]; uint16_t status; uint8_t int_set; -} TPCI200State; +}; #define TYPE_TPCI200 "tpci200" -#define TPCI200(obj) \ - OBJECT_CHECK(TPCI200State, (obj), TYPE_TPCI200) +OBJECT_DECLARE_SIMPLE_TYPE(TPCI200State, TPCI200) static const uint8_t local_config_regs[] = { 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFC, 0xFF, 0x0F, 0x00, 0x00, 0x00, diff --git a/hw/ipmi/Makefile.objs b/hw/ipmi/Makefile.objs deleted file mode 100644 index 3cca10bc506fbd29b51ab7c363aa000bc176cfac..0000000000000000000000000000000000000000 --- a/hw/ipmi/Makefile.objs +++ /dev/null @@ -1,8 +0,0 @@ -common-obj-$(CONFIG_IPMI) += ipmi.o ipmi_kcs.o ipmi_bt.o -common-obj-$(CONFIG_IPMI_LOCAL) += ipmi_bmc_sim.o -common-obj-$(CONFIG_IPMI_EXTERN) += ipmi_bmc_extern.o -common-obj-$(CONFIG_ISA_IPMI_KCS) += isa_ipmi_kcs.o -common-obj-$(CONFIG_PCI_IPMI_KCS) += pci_ipmi_kcs.o -common-obj-$(CONFIG_ISA_IPMI_BT) += isa_ipmi_bt.o -common-obj-$(CONFIG_PCI_IPMI_BT) += pci_ipmi_bt.o -common-obj-$(CONFIG_IPMI_SSIF) += smbus_ipmi.o diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c index f9a13e0a44f859b9ace0fe9a35d2cdd7c8788958..c3f3306e66bc8b1ea785fa447dc709c409ac6bb2 100644 --- a/hw/ipmi/ipmi_bmc_extern.c +++ b/hw/ipmi/ipmi_bmc_extern.c @@ -36,6 +36,7 @@ #include "hw/ipmi/ipmi.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" +#include "qom/object.h" #define VM_MSG_CHAR 0xA0 /* Marks end of message */ #define VM_CMD_CHAR 0xA1 /* Marks end of a command */ @@ -61,9 +62,8 @@ #define VM_CMD_GRACEFUL_SHUTDOWN 0x09 #define TYPE_IPMI_BMC_EXTERN "ipmi-bmc-extern" -#define IPMI_BMC_EXTERN(obj) OBJECT_CHECK(IPMIBmcExtern, (obj), \ - TYPE_IPMI_BMC_EXTERN) -typedef struct IPMIBmcExtern { +OBJECT_DECLARE_SIMPLE_TYPE(IPMIBmcExtern, IPMI_BMC_EXTERN) +struct IPMIBmcExtern { IPMIBmc parent; CharBackend chr; @@ -85,7 +85,7 @@ typedef struct IPMIBmcExtern { /* A reset event is pending to be sent upstream. */ bool send_reset; -} IPMIBmcExtern; +}; static unsigned char ipmb_checksum(const unsigned char *data, int size, unsigned char start) diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c index 0b97e04774cab55b5aea605063da366819c5922d..f78e92d3d5ab2b52e0a3dde7b3ee87696fc8e06a 100644 --- a/hw/ipmi/ipmi_bmc_sim.c +++ b/hw/ipmi/ipmi_bmc_sim.c @@ -49,6 +49,7 @@ #define IPMI_CMD_GET_SENSOR_READING 0x2d #define IPMI_CMD_SET_SENSOR_TYPE 0x2e #define IPMI_CMD_GET_SENSOR_TYPE 0x2f +#define IPMI_CMD_SET_SENSOR_READING 0x30 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */ @@ -1747,6 +1748,227 @@ static void get_sensor_type(IPMIBmcSim *ibs, rsp_buffer_push(rsp, sens->evt_reading_type_code); } +/* + * bytes parameter + * 1 sensor number + * 2 operation (see below for bits meaning) + * 3 sensor reading + * 4:5 assertion states (optional) + * 6:7 deassertion states (optional) + * 8:10 event data 1,2,3 (optional) + */ +static void set_sensor_reading(IPMIBmcSim *ibs, + uint8_t *cmd, unsigned int cmd_len, + RspBuffer *rsp) +{ + IPMISensor *sens; + uint8_t evd1 = 0; + uint8_t evd2 = 0; + uint8_t evd3 = 0; + uint8_t new_reading = 0; + uint16_t new_assert_states = 0; + uint16_t new_deassert_states = 0; + bool change_reading = false; + bool change_assert = false; + bool change_deassert = false; + enum { + SENSOR_GEN_EVENT_NONE, + SENSOR_GEN_EVENT_DATA, + SENSOR_GEN_EVENT_BMC, + } do_gen_event = SENSOR_GEN_EVENT_NONE; + + if ((cmd[2] >= MAX_SENSORS) || + !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) { + rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT); + return; + } + + sens = ibs->sensors + cmd[2]; + + /* [1:0] Sensor Reading operation */ + switch ((cmd[3]) & 0x3) { + case 0: /* Do not change */ + break; + case 1: /* write given value to sensor reading byte */ + new_reading = cmd[4]; + if (sens->reading != new_reading) { + change_reading = true; + } + break; + case 2: + case 3: + rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); + return; + } + + /* [3:2] Deassertion bits operation */ + switch ((cmd[3] >> 2) & 0x3) { + case 0: /* Do not change */ + break; + case 1: /* write given value */ + if (cmd_len > 7) { + new_deassert_states = cmd[7]; + change_deassert = true; + } + if (cmd_len > 8) { + new_deassert_states |= (cmd[8] << 8); + } + break; + + case 2: /* mask on */ + if (cmd_len > 7) { + new_deassert_states = (sens->deassert_states | cmd[7]); + change_deassert = true; + } + if (cmd_len > 8) { + new_deassert_states |= (sens->deassert_states | (cmd[8] << 8)); + } + break; + + case 3: /* mask off */ + if (cmd_len > 7) { + new_deassert_states = (sens->deassert_states & cmd[7]); + change_deassert = true; + } + if (cmd_len > 8) { + new_deassert_states |= (sens->deassert_states & (cmd[8] << 8)); + } + break; + } + + if (change_deassert && (new_deassert_states == sens->deassert_states)) { + change_deassert = false; + } + + /* [5:4] Assertion bits operation */ + switch ((cmd[3] >> 4) & 0x3) { + case 0: /* Do not change */ + break; + case 1: /* write given value */ + if (cmd_len > 5) { + new_assert_states = cmd[5]; + change_assert = true; + } + if (cmd_len > 6) { + new_assert_states |= (cmd[6] << 8); + } + break; + + case 2: /* mask on */ + if (cmd_len > 5) { + new_assert_states = (sens->assert_states | cmd[5]); + change_assert = true; + } + if (cmd_len > 6) { + new_assert_states |= (sens->assert_states | (cmd[6] << 8)); + } + break; + + case 3: /* mask off */ + if (cmd_len > 5) { + new_assert_states = (sens->assert_states & cmd[5]); + change_assert = true; + } + if (cmd_len > 6) { + new_assert_states |= (sens->assert_states & (cmd[6] << 8)); + } + break; + } + + if (change_assert && (new_assert_states == sens->assert_states)) { + change_assert = false; + } + + if (cmd_len > 9) { + evd1 = cmd[9]; + } + if (cmd_len > 10) { + evd2 = cmd[10]; + } + if (cmd_len > 11) { + evd3 = cmd[11]; + } + + /* [7:6] Event Data Bytes operation */ + switch ((cmd[3] >> 6) & 0x3) { + case 0: /* + * Don’t use Event Data bytes from this command. BMC will + * generate it's own Event Data bytes based on its sensor + * implementation. + */ + evd1 = evd2 = evd3 = 0x0; + do_gen_event = SENSOR_GEN_EVENT_BMC; + break; + case 1: /* + * Write given values to event data bytes including bits + * [3:0] Event Data 1. + */ + do_gen_event = SENSOR_GEN_EVENT_DATA; + break; + case 2: /* + * Write given values to event data bytes excluding bits + * [3:0] Event Data 1. + */ + evd1 &= 0xf0; + do_gen_event = SENSOR_GEN_EVENT_DATA; + break; + case 3: + rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); + return; + } + + /* + * Event Data Bytes operation and parameter are inconsistent. The + * Specs are not clear on that topic but generating an error seems + * correct. + */ + if (do_gen_event == SENSOR_GEN_EVENT_DATA && cmd_len < 10) { + rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); + return; + } + + /* commit values */ + if (change_reading) { + sens->reading = new_reading; + } + + if (change_assert) { + sens->assert_states = new_assert_states; + } + + if (change_deassert) { + sens->deassert_states = new_deassert_states; + } + + /* TODO: handle threshold sensor */ + if (!IPMI_SENSOR_IS_DISCRETE(sens)) { + return; + } + + switch (do_gen_event) { + case SENSOR_GEN_EVENT_DATA: { + unsigned int bit = evd1 & 0xf; + uint16_t mask = (1 << bit); + + if (sens->assert_states & mask & sens->assert_enable) { + gen_event(ibs, cmd[2], 0, evd1, evd2, evd3); + } + + if (sens->deassert_states & mask & sens->deassert_enable) { + gen_event(ibs, cmd[2], 1, evd1, evd2, evd3); + } + break; + } + case SENSOR_GEN_EVENT_BMC: + /* + * TODO: generate event and event data bytes depending on the + * sensor + */ + break; + case SENSOR_GEN_EVENT_NONE: + break; + } +} static const IPMICmdHandler chassis_cmds[] = { [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities }, @@ -1768,6 +1990,7 @@ static const IPMICmdHandler sensor_event_cmds[] = { [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 }, [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 }, [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 }, + [IPMI_CMD_SET_SENSOR_READING] = { set_sensor_reading, 5 }, }; static const IPMINetfn sensor_event_netfn = { .cmd_nums = ARRAY_SIZE(sensor_event_cmds), diff --git a/hw/ipmi/isa_ipmi_bt.c b/hw/ipmi/isa_ipmi_bt.c index c8dc0a09dcd42c4c57db0c9e096a37ca9a5f6d89..b7c2ad557b2c8b2f497859755ee60d639bd6f621 100644 --- a/hw/ipmi/isa_ipmi_bt.c +++ b/hw/ipmi/isa_ipmi_bt.c @@ -31,18 +31,18 @@ #include "hw/isa/isa.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" +#include "qom/object.h" #define TYPE_ISA_IPMI_BT "isa-ipmi-bt" -#define ISA_IPMI_BT(obj) OBJECT_CHECK(ISAIPMIBTDevice, (obj), \ - TYPE_ISA_IPMI_BT) +OBJECT_DECLARE_SIMPLE_TYPE(ISAIPMIBTDevice, ISA_IPMI_BT) -typedef struct ISAIPMIBTDevice { +struct ISAIPMIBTDevice { ISADevice dev; int32_t isairq; qemu_irq irq; IPMIBT bt; uint32_t uuid; -} ISAIPMIBTDevice; +}; static void isa_ipmi_bt_get_fwinfo(struct IPMIInterface *ii, IPMIFwInfo *info) { diff --git a/hw/ipmi/isa_ipmi_kcs.c b/hw/ipmi/isa_ipmi_kcs.c index 4b421c33f43299e169c064cdafbbdb1fdcecec30..7dd6bf0040a42a160fe1ecc35183bb70448a44d7 100644 --- a/hw/ipmi/isa_ipmi_kcs.c +++ b/hw/ipmi/isa_ipmi_kcs.c @@ -31,18 +31,18 @@ #include "hw/isa/isa.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" +#include "qom/object.h" #define TYPE_ISA_IPMI_KCS "isa-ipmi-kcs" -#define ISA_IPMI_KCS(obj) OBJECT_CHECK(ISAIPMIKCSDevice, (obj), \ - TYPE_ISA_IPMI_KCS) +OBJECT_DECLARE_SIMPLE_TYPE(ISAIPMIKCSDevice, ISA_IPMI_KCS) -typedef struct ISAIPMIKCSDevice { +struct ISAIPMIKCSDevice { ISADevice dev; int32_t isairq; qemu_irq irq; IPMIKCS kcs; uint32_t uuid; -} ISAIPMIKCSDevice; +}; static void isa_ipmi_kcs_get_fwinfo(IPMIInterface *ii, IPMIFwInfo *info) { diff --git a/hw/ipmi/meson.build b/hw/ipmi/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..9622ea2a2c849fb032d3f80851388e76ddea7769 --- /dev/null +++ b/hw/ipmi/meson.build @@ -0,0 +1,11 @@ +ipmi_ss = ss.source_set() +ipmi_ss.add(when: 'CONFIG_IPMI', if_true: files('ipmi.c', 'ipmi_kcs.c', 'ipmi_bt.c')) +ipmi_ss.add(when: 'CONFIG_IPMI_LOCAL', if_true: files('ipmi_bmc_sim.c')) +ipmi_ss.add(when: 'CONFIG_IPMI_EXTERN', if_true: files('ipmi_bmc_extern.c')) +ipmi_ss.add(when: 'CONFIG_ISA_IPMI_KCS', if_true: files('isa_ipmi_kcs.c')) +ipmi_ss.add(when: 'CONFIG_PCI_IPMI_KCS', if_true: files('pci_ipmi_kcs.c')) +ipmi_ss.add(when: 'CONFIG_ISA_IPMI_BT', if_true: files('isa_ipmi_bt.c')) +ipmi_ss.add(when: 'CONFIG_PCI_IPMI_BT', if_true: files('pci_ipmi_bt.c')) +ipmi_ss.add(when: 'CONFIG_IPMI_SSIF', if_true: files('smbus_ipmi.c')) + +softmmu_ss.add_all(when: 'CONFIG_IPMI', if_true: ipmi_ss) diff --git a/hw/ipmi/pci_ipmi_bt.c b/hw/ipmi/pci_ipmi_bt.c index ba9cf016b54a0fa0251bd32fa19226e327472abc..b6e52730d389d9c2c71c001dfcceb9186e3c219e 100644 --- a/hw/ipmi/pci_ipmi_bt.c +++ b/hw/ipmi/pci_ipmi_bt.c @@ -26,17 +26,17 @@ #include "qapi/error.h" #include "hw/ipmi/ipmi_bt.h" #include "hw/pci/pci.h" +#include "qom/object.h" #define TYPE_PCI_IPMI_BT "pci-ipmi-bt" -#define PCI_IPMI_BT(obj) OBJECT_CHECK(PCIIPMIBTDevice, (obj), \ - TYPE_PCI_IPMI_BT) +OBJECT_DECLARE_SIMPLE_TYPE(PCIIPMIBTDevice, PCI_IPMI_BT) -typedef struct PCIIPMIBTDevice { +struct PCIIPMIBTDevice { PCIDevice dev; IPMIBT bt; bool irq_enabled; uint32_t uuid; -} PCIIPMIBTDevice; +}; static void pci_ipmi_raise_irq(IPMIBT *ik) { diff --git a/hw/ipmi/pci_ipmi_kcs.c b/hw/ipmi/pci_ipmi_kcs.c index 99f46152f48cd9aaee6fc46b90b5680da75dea0b..de13418862fe22b86b7fb542729fdef5a6fdc8da 100644 --- a/hw/ipmi/pci_ipmi_kcs.c +++ b/hw/ipmi/pci_ipmi_kcs.c @@ -26,17 +26,17 @@ #include "qapi/error.h" #include "hw/ipmi/ipmi_kcs.h" #include "hw/pci/pci.h" +#include "qom/object.h" #define TYPE_PCI_IPMI_KCS "pci-ipmi-kcs" -#define PCI_IPMI_KCS(obj) OBJECT_CHECK(PCIIPMIKCSDevice, (obj), \ - TYPE_PCI_IPMI_KCS) +OBJECT_DECLARE_SIMPLE_TYPE(PCIIPMIKCSDevice, PCI_IPMI_KCS) -typedef struct PCIIPMIKCSDevice { +struct PCIIPMIKCSDevice { PCIDevice dev; IPMIKCS kcs; bool irq_enabled; uint32_t uuid; -} PCIIPMIKCSDevice; +}; static void pci_ipmi_raise_irq(IPMIKCS *ik) { diff --git a/hw/ipmi/smbus_ipmi.c b/hw/ipmi/smbus_ipmi.c index f1a0148755c75ab825a698f762e0a8590982726d..1fdf0a66b698512afe2635020905c9d65a04aff0 100644 --- a/hw/ipmi/smbus_ipmi.c +++ b/hw/ipmi/smbus_ipmi.c @@ -27,9 +27,10 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "hw/ipmi/ipmi.h" +#include "qom/object.h" #define TYPE_SMBUS_IPMI "smbus-ipmi" -#define SMBUS_IPMI(obj) OBJECT_CHECK(SMBusIPMIDevice, (obj), TYPE_SMBUS_IPMI) +OBJECT_DECLARE_SIMPLE_TYPE(SMBusIPMIDevice, SMBUS_IPMI) #define SSIF_IPMI_REQUEST 2 #define SSIF_IPMI_MULTI_PART_REQUEST_START 6 @@ -44,7 +45,7 @@ #define IPMI_GET_SYS_INTF_CAP_CMD 0x57 -typedef struct SMBusIPMIDevice { +struct SMBusIPMIDevice { SMBusDevice parent; IPMIBmc *bmc; @@ -67,7 +68,7 @@ typedef struct SMBusIPMIDevice { uint8_t waiting_rsp; uint32_t uuid; -} SMBusIPMIDevice; +}; static void smbus_ipmi_handle_event(IPMIInterface *ii) { diff --git a/hw/isa/Makefile.objs b/hw/isa/Makefile.objs deleted file mode 100644 index 8e73960a750ab0dff328d86010e86744d5c8874d..0000000000000000000000000000000000000000 --- a/hw/isa/Makefile.objs +++ /dev/null @@ -1,11 +0,0 @@ -common-obj-$(CONFIG_ISA_BUS) += isa-bus.o -common-obj-$(CONFIG_ISA_SUPERIO) += isa-superio.o -common-obj-$(CONFIG_APM) += apm.o -common-obj-$(CONFIG_I82378) += i82378.o -common-obj-$(CONFIG_PC87312) += pc87312.o -common-obj-$(CONFIG_PIIX3) += piix3.o -common-obj-$(CONFIG_PIIX4) += piix4.o -common-obj-$(CONFIG_VT82C686) += vt82c686.o -common-obj-$(CONFIG_SMC37C669) += smc37c669-superio.o - -obj-$(CONFIG_LPC_ICH9) += lpc_ich9.o diff --git a/hw/isa/apm.c b/hw/isa/apm.c index 6300b1ba7ace4f9fd97895e0daa8de4c9b4bbf21..dfe9020d30b768202f48d0eed2b97bfdffae6d12 100644 --- a/hw/isa/apm.c +++ b/hw/isa/apm.c @@ -6,7 +6,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -24,14 +24,8 @@ #include "hw/isa/apm.h" #include "hw/pci/pci.h" #include "migration/vmstate.h" +#include "trace.h" -//#define DEBUG - -#ifdef DEBUG -# define APM_DPRINTF(format, ...) printf(format, ## __VA_ARGS__) -#else -# define APM_DPRINTF(format, ...) do { } while (0) -#endif /* fixed I/O location */ #define APM_STS_IOPORT 0xb3 @@ -41,8 +35,8 @@ static void apm_ioport_writeb(void *opaque, hwaddr addr, uint64_t val, { APMState *apm = opaque; addr &= 1; - APM_DPRINTF("apm_ioport_writeb addr=0x%" HWADDR_PRIx - " val=0x%02" PRIx64 "\n", addr, val); + + trace_apm_io_write(addr, val); if (addr == 0) { apm->apmc = val; @@ -65,7 +59,8 @@ static uint64_t apm_ioport_readb(void *opaque, hwaddr addr, unsigned size) } else { val = apm->apms; } - APM_DPRINTF("apm_ioport_readb addr=0x%" HWADDR_PRIx " val=0x%02x\n", addr, val); + trace_apm_io_read(addr, val); + return val; } diff --git a/hw/isa/i82378.c b/hw/isa/i82378.c index d9e6c7fa0096e818118cc5759f38e5e00511725d..2a2ff05b93727b7557d01f22145d3299418d6251 100644 --- a/hw/isa/i82378.c +++ b/hw/isa/i82378.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -24,18 +24,18 @@ #include "hw/timer/i8254.h" #include "migration/vmstate.h" #include "hw/audio/pcspk.h" +#include "qom/object.h" #define TYPE_I82378 "i82378" -#define I82378(obj) \ - OBJECT_CHECK(I82378State, (obj), TYPE_I82378) +OBJECT_DECLARE_SIMPLE_TYPE(I82378State, I82378) -typedef struct I82378State { +struct I82378State { PCIDevice parent_obj; qemu_irq out[2]; qemu_irq *i8259; MemoryRegion io; -} I82378State; +}; static const VMStateDescription vmstate_i82378 = { .name = "pci-i82378", @@ -102,7 +102,7 @@ static void i82378_realize(PCIDevice *pci, Error **errp) pit = i8254_pit_init(isabus, 0x40, 0, NULL); /* speaker */ - pcspk_init(isabus, pit); + pcspk_init(isa_new(TYPE_PC_SPEAKER), isabus, pit); /* 2 82C37 (dma) */ isa_create_simple(isabus, "i82374"); diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c index 1f2189f4d5db281213340aa3478e79c234fce12c..7820068e6e17f3f3f8c2498043ca53484cdd5bd7 100644 --- a/hw/isa/isa-bus.c +++ b/hw/isa/isa-bus.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -21,7 +21,6 @@ #include "qemu/error-report.h" #include "qemu/module.h" #include "qapi/error.h" -#include "hw/hw.h" #include "monitor/monitor.h" #include "hw/sysbus.h" #include "sysemu/sysemu.h" @@ -61,8 +60,8 @@ ISABus *isa_bus_new(DeviceState *dev, MemoryRegion* address_space, return NULL; } if (!dev) { - dev = qdev_create(NULL, "isabus-bridge"); - qdev_init_nofail(dev); + dev = qdev_new("isabus-bridge"); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); } isabus = ISA_BUS(qbus_create(TYPE_ISA_BUS, dev, NULL)); @@ -85,18 +84,14 @@ void isa_bus_irqs(ISABus *bus, qemu_irq *irqs) qemu_irq isa_get_irq(ISADevice *dev, unsigned isairq) { assert(!dev || ISA_BUS(qdev_get_parent_bus(DEVICE(dev))) == isabus); - if (isairq >= ISA_NUM_IRQS) { - hw_error("isa irq %d invalid", isairq); - } + assert(isairq < ISA_NUM_IRQS); return isabus->irqs[isairq]; } void isa_init_irq(ISADevice *dev, qemu_irq *p, unsigned isairq) { assert(dev->nirqs < ARRAY_SIZE(dev->isairq)); - if (isairq >= ISA_NUM_IRQS) { - hw_error("isa irq %d invalid", isairq); - } + assert(isairq < ISA_NUM_IRQS); dev->isairq[dev->nirqs] = isairq; *p = isa_get_irq(dev, isairq); dev->nirqs++; @@ -160,31 +155,30 @@ static void isa_device_init(Object *obj) dev->isairq[1] = -1; } -ISADevice *isa_create(ISABus *bus, const char *name) +ISADevice *isa_new(const char *name) { - DeviceState *dev; - - dev = qdev_create(BUS(bus), name); - return ISA_DEVICE(dev); + return ISA_DEVICE(qdev_new(name)); } -ISADevice *isa_try_create(ISABus *bus, const char *name) +ISADevice *isa_try_new(const char *name) { - DeviceState *dev; - - dev = qdev_try_create(BUS(bus), name); - return ISA_DEVICE(dev); + return ISA_DEVICE(qdev_try_new(name)); } ISADevice *isa_create_simple(ISABus *bus, const char *name) { ISADevice *dev; - dev = isa_create(bus, name); - qdev_init_nofail(DEVICE(dev)); + dev = isa_new(name); + isa_realize_and_unref(dev, bus, &error_fatal); return dev; } +bool isa_realize_and_unref(ISADevice *dev, ISABus *bus, Error **errp) +{ + return qdev_realize_and_unref(&dev->parent_obj, &bus->parent_obj, errp); +} + ISADevice *isa_vga_init(ISABus *bus) { switch (vga_interface_type) { diff --git a/hw/isa/isa-superio.c b/hw/isa/isa-superio.c index 3dcdc234a4f7b6aadd8d4b5eac76f3497ad3a669..179c1856956bb75729532208476eecd4682c25dc 100644 --- a/hw/isa/isa-superio.c +++ b/hw/isa/isa-superio.c @@ -17,6 +17,7 @@ #include "sysemu/sysemu.h" #include "sysemu/blockdev.h" #include "chardev/char.h" +#include "hw/block/fdc.h" #include "hw/isa/superio.h" #include "hw/qdev-properties.h" #include "hw/input/i8042.h" @@ -31,7 +32,7 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) ISADevice *isa; DeviceState *d; Chardev *chr; - DriveInfo *drive; + DriveInfo *fd[MAX_FD]; char *name; int i; @@ -51,7 +52,7 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) } else { name = g_strdup_printf("parallel%d", i); } - isa = isa_create(bus, "isa-parallel"); + isa = isa_new("isa-parallel"); d = DEVICE(isa); qdev_prop_set_uint32(d, "index", i); if (k->parallel.get_iobase) { @@ -63,7 +64,7 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) } qdev_prop_set_chr(d, "chardev", chr); object_property_add_child(OBJECT(dev), name, OBJECT(isa)); - qdev_init_nofail(d); + isa_realize_and_unref(isa, bus, &error_fatal); sio->parallel[i] = isa; trace_superio_create_parallel(i, k->parallel.get_iobase ? @@ -90,7 +91,7 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) } else { name = g_strdup_printf("serial%d", i); } - isa = isa_create(bus, TYPE_ISA_SERIAL); + isa = isa_new(TYPE_ISA_SERIAL); d = DEVICE(isa); qdev_prop_set_uint32(d, "index", i); if (k->serial.get_iobase) { @@ -102,7 +103,7 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) } qdev_prop_set_chr(d, "chardev", chr); object_property_add_child(OBJECT(dev), name, OBJECT(isa)); - qdev_init_nofail(d); + isa_realize_and_unref(isa, bus, &error_fatal); sio->serial[i] = isa; trace_superio_create_serial(i, k->serial.get_iobase ? @@ -115,7 +116,7 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) /* Floppy disc */ if (!k->floppy.is_enabled || k->floppy.is_enabled(sio, 0)) { - isa = isa_create(bus, "isa-fdc"); + isa = isa_new(TYPE_ISA_FDC); d = DEVICE(isa); if (k->floppy.get_iobase) { qdev_prop_set_uint32(d, "iobase", k->floppy.get_iobase(sio, 0)); @@ -124,19 +125,12 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) qdev_prop_set_uint32(d, "irq", k->floppy.get_irq(sio, 0)); } /* FIXME use a qdev drive property instead of drive_get() */ - drive = drive_get(IF_FLOPPY, 0, 0); - if (drive != NULL) { - qdev_prop_set_drive(d, "driveA", blk_by_legacy_dinfo(drive), - &error_fatal); - } - /* FIXME use a qdev drive property instead of drive_get() */ - drive = drive_get(IF_FLOPPY, 0, 1); - if (drive != NULL) { - qdev_prop_set_drive(d, "driveB", blk_by_legacy_dinfo(drive), - &error_fatal); + for (i = 0; i < MAX_FD; i++) { + fd[i] = drive_get(IF_FLOPPY, 0, i); } object_property_add_child(OBJECT(sio), "isa-fdc", OBJECT(isa)); - qdev_init_nofail(d); + isa_realize_and_unref(isa, bus, &error_fatal); + isa_fdc_init_drives(isa, fd); sio->floppy = isa; trace_superio_create_floppy(0, k->floppy.get_iobase ? @@ -146,14 +140,14 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) } /* Keyboard, mouse */ - isa = isa_create(bus, TYPE_I8042); + isa = isa_new(TYPE_I8042); object_property_add_child(OBJECT(sio), TYPE_I8042, OBJECT(isa)); - qdev_init_nofail(DEVICE(isa)); + isa_realize_and_unref(isa, bus, &error_fatal); sio->kbc = isa; /* IDE */ if (k->ide.count && (!k->ide.is_enabled || k->ide.is_enabled(sio, 0))) { - isa = isa_create(bus, "isa-ide"); + isa = isa_new("isa-ide"); d = DEVICE(isa); if (k->ide.get_iobase) { qdev_prop_set_uint32(d, "iobase", k->ide.get_iobase(sio, 0)); @@ -164,8 +158,8 @@ static void isa_superio_realize(DeviceState *dev, Error **errp) if (k->ide.get_irq) { qdev_prop_set_uint32(d, "irq", k->ide.get_irq(sio, 0)); } - qdev_init_nofail(d); object_property_add_child(OBJECT(sio), "isa-ide", OBJECT(isa)); + isa_realize_and_unref(isa, bus, &error_fatal); sio->ide = isa; trace_superio_create_ide(0, k->ide.get_iobase ? diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index cd6e169d47a05ac8e091c7aecea26697a0f1fbf4..087a18d04de475df3cfdb2a1158a01f795645961 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -29,6 +29,7 @@ */ #include "qemu/osdep.h" +#include "qemu/log.h" #include "cpu.h" #include "qapi/visitor.h" #include "qemu/range.h" @@ -312,10 +313,12 @@ void ich9_generate_smi(void) cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI); } +/* Returns -1 on error, IRQ number on success */ static int ich9_lpc_sci_irq(ICH9LPCState *lpc) { - switch (lpc->d.config[ICH9_LPC_ACPI_CTRL] & - ICH9_LPC_ACPI_CTRL_SCI_IRQ_SEL_MASK) { + uint8_t sel = lpc->d.config[ICH9_LPC_ACPI_CTRL] & + ICH9_LPC_ACPI_CTRL_SCI_IRQ_SEL_MASK; + switch (sel) { case ICH9_LPC_ACPI_CTRL_9: return 9; case ICH9_LPC_ACPI_CTRL_10: @@ -328,6 +331,8 @@ static int ich9_lpc_sci_irq(ICH9LPCState *lpc) return 21; default: /* reserved */ + qemu_log_mask(LOG_GUEST_ERROR, + "ICH9 LPC: SCI IRQ SEL #%u is reserved\n", sel); break; } return -1; @@ -373,6 +378,15 @@ static void smi_features_ok_callback(void *opaque) /* guest requests invalid features, leave @features_ok at zero */ return; } + if (!(guest_features & BIT_ULL(ICH9_LPC_SMI_F_BROADCAST_BIT)) && + guest_features & (BIT_ULL(ICH9_LPC_SMI_F_CPU_HOTPLUG_BIT) | + BIT_ULL(ICH9_LPC_SMI_F_CPU_HOT_UNPLUG_BIT))) { + /* + * cpu hot-[un]plug with SMI requires SMI broadcast, + * leave @features_ok at zero + */ + return; + } /* valid feature subset requested, lock it down, report success */ lpc->smi_negotiated_features = guest_features; @@ -450,7 +464,7 @@ ich9_lpc_pmbase_sci_update(ICH9LPCState *lpc) { uint32_t pm_io_base = pci_get_long(lpc->d.config + ICH9_LPC_PMBASE); uint8_t acpi_cntl = pci_get_long(lpc->d.config + ICH9_LPC_ACPI_CTRL); - uint8_t new_gsi; + int new_gsi; if (acpi_cntl & ICH9_LPC_ACPI_CTRL_ACPI_EN) { pm_io_base &= ICH9_LPC_PMBASE_BASE_ADDRESS_MASK; @@ -461,6 +475,9 @@ ich9_lpc_pmbase_sci_update(ICH9LPCState *lpc) ich9_pm_iospace_update(&lpc->pm, pm_io_base); new_gsi = ich9_lpc_sci_irq(lpc); + if (new_gsi == -1) { + return; + } if (lpc->sci_level && new_gsi != lpc->sci_gsi) { qemu_set_irq(lpc->pm.irq, 0); lpc->sci_gsi = new_gsi; @@ -638,6 +655,9 @@ static void ich9_lpc_initfn(Object *obj) &acpi_enable_cmd, OBJ_PROP_FLAG_READ); object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_DISABLE_CMD, &acpi_disable_cmd, OBJ_PROP_FLAG_READ); + object_property_add_uint64_ptr(obj, ICH9_LPC_SMI_NEGOTIATED_FEAT_PROP, + &lpc->smi_negotiated_features, + OBJ_PROP_FLAG_READ); ich9_pm_add_properties(obj, &lpc->pm); } @@ -747,6 +767,10 @@ static Property ich9_lpc_properties[] = { DEFINE_PROP_BOOL("noreboot", ICH9LPCState, pin_strap.spkr_hi, true), DEFINE_PROP_BIT64("x-smi-broadcast", ICH9LPCState, smi_host_features, ICH9_LPC_SMI_F_BROADCAST_BIT, true), + DEFINE_PROP_BIT64("x-smi-cpu-hotplug", ICH9LPCState, smi_host_features, + ICH9_LPC_SMI_F_CPU_HOTPLUG_BIT, true), + DEFINE_PROP_BIT64("x-smi-cpu-hotunplug", ICH9LPCState, smi_host_features, + ICH9_LPC_SMI_F_CPU_HOT_UNPLUG_BIT, false), DEFINE_PROP_END_OF_LIST(), }; @@ -792,7 +816,7 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data) static const TypeInfo ich9_lpc_info = { .name = TYPE_ICH9_LPC_DEVICE, .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(struct ICH9LPCState), + .instance_size = sizeof(ICH9LPCState), .instance_init = ich9_lpc_initfn, .class_init = ich9_lpc_class_init, .interfaces = (InterfaceInfo[]) { diff --git a/hw/isa/meson.build b/hw/isa/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..8bf678ca0aa604811aebbb0ada280dc24c90590a --- /dev/null +++ b/hw/isa/meson.build @@ -0,0 +1,11 @@ +softmmu_ss.add(when: 'CONFIG_APM', if_true: files('apm.c')) +softmmu_ss.add(when: 'CONFIG_I82378', if_true: files('i82378.c')) +softmmu_ss.add(when: 'CONFIG_ISA_BUS', if_true: files('isa-bus.c')) +softmmu_ss.add(when: 'CONFIG_ISA_SUPERIO', if_true: files('isa-superio.c')) +softmmu_ss.add(when: 'CONFIG_PC87312', if_true: files('pc87312.c')) +softmmu_ss.add(when: 'CONFIG_PIIX3', if_true: files('piix3.c')) +softmmu_ss.add(when: 'CONFIG_PIIX4', if_true: files('piix4.c')) +softmmu_ss.add(when: 'CONFIG_SMC37C669', if_true: files('smc37c669-superio.c')) +softmmu_ss.add(when: 'CONFIG_VT82C686', if_true: files('vt82c686.c')) + +specific_ss.add(when: 'CONFIG_LPC_ICH9', if_true: files('lpc_ich9.c')) diff --git a/hw/isa/pc87312.c b/hw/isa/pc87312.c index 0cacbbc91b12e6b82ab7698a1f5afbb8719d6353..8d7b8d3db2beb609874f1f4f1881ee00d18d8c33 100644 --- a/hw/isa/pc87312.c +++ b/hw/isa/pc87312.c @@ -371,7 +371,7 @@ static void pc87312_class_init(ObjectClass *klass, void *data) } static const TypeInfo pc87312_type_info = { - .name = TYPE_PC87312_SUPERIO, + .name = TYPE_PC87312, .parent = TYPE_ISA_SUPERIO, .instance_size = sizeof(PC87312State), .instance_init = pc87312_initfn, diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c index fd1c78879f20dded4be04d21815192eb69a35a02..587850b88817d32f09fbd231d4b2f6cf1bc06cce 100644 --- a/hw/isa/piix3.c +++ b/hw/isa/piix3.c @@ -28,6 +28,7 @@ #include "hw/irq.h" #include "hw/isa/isa.h" #include "hw/xen/xen.h" +#include "sysemu/xen.h" #include "sysemu/sysemu.h" #include "sysemu/reset.h" #include "sysemu/runstate.h" @@ -35,10 +36,6 @@ #define XEN_PIIX_NUM_PIRQS 128ULL -#define TYPE_PIIX3_PCI_DEVICE "pci-piix3" -#define PIIX3_PCI_DEVICE(obj) \ - OBJECT_CHECK(PIIX3State, (obj), TYPE_PIIX3_PCI_DEVICE) - #define TYPE_PIIX3_DEVICE "PIIX3" #define TYPE_PIIX3_XEN_DEVICE "PIIX3-xen" diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index 9a10fb9b3cd62d119012378132a64fec146d8359..a50d97834c760e3ebc5103614ee97a57511dcc25 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -38,10 +38,11 @@ #include "migration/vmstate.h" #include "sysemu/reset.h" #include "sysemu/runstate.h" +#include "qom/object.h" PCIDevice *piix4_dev; -typedef struct PIIX4State { +struct PIIX4State { PCIDevice dev; qemu_irq cpu_intr; qemu_irq *isa; @@ -50,10 +51,9 @@ typedef struct PIIX4State { /* Reset Control Register */ MemoryRegion rcr_mem; uint8_t rcr; -} PIIX4State; +}; -#define PIIX4_PCI_DEVICE(obj) \ - OBJECT_CHECK(PIIX4State, (obj), TYPE_PIIX4_PCI_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(PIIX4State, PIIX4_PCI_DEVICE) static void piix4_isa_reset(DeviceState *dev) { @@ -150,7 +150,6 @@ static void piix4_realize(PCIDevice *dev, Error **errp) PIIX4State *s = PIIX4_PCI_DEVICE(dev); ISABus *isa_bus; qemu_irq *i8259_out_irq; - Error *err = NULL; isa_bus = isa_bus_new(DEVICE(dev), pci_address_space(dev), pci_address_space_io(dev), errp); @@ -182,11 +181,8 @@ static void piix4_realize(PCIDevice *dev, Error **errp) i8257_dma_init(isa_bus, 0); /* RTC */ - qdev_set_parent_bus(DEVICE(&s->rtc), BUS(isa_bus)); qdev_prop_set_int32(DEVICE(&s->rtc), "base_year", 2000); - object_property_set_bool(OBJECT(&s->rtc), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->rtc), BUS(isa_bus), errp)) { return; } isa_init_irq(ISA_DEVICE(&s->rtc), &s->rtc.irq, RTC_ISA_IRQ); diff --git a/hw/isa/trace-events b/hw/isa/trace-events index 202f8938e7b86a0a4338d8a41707699a84d06d83..3544c6213c39e0d422c1b4bbb6f548ce000f7bab 100644 --- a/hw/isa/trace-events +++ b/hw/isa/trace-events @@ -9,3 +9,7 @@ superio_create_ide(int id, uint16_t base, unsigned int irq) "id=%d, base 0x%03x, # pc87312.c pc87312_io_read(uint32_t addr, uint32_t val) "read addr=0x%x val=0x%x" pc87312_io_write(uint32_t addr, uint32_t val) "write addr=0x%x val=0x%x" + +# apm.c +apm_io_read(uint8_t addr, uint8_t val) "read addr=0x%x val=0x%02x" +apm_io_write(uint8_t addr, uint8_t val) "write addr=0x%x val=0x%02x" diff --git a/hw/isa/trace.h b/hw/isa/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..501205cfc1037f6f6c09cbab0f49905ad2d8fe1a --- /dev/null +++ b/hw/isa/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_isa.h" diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index fac4e56b7d758e0af3c73af9fde672adb88597b6..b3170c70c3d2f0a9755d2c5ff6d6e4f48ff57472 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -23,9 +23,11 @@ #include "hw/isa/apm.h" #include "hw/acpi/acpi.h" #include "hw/i2c/pm_smbus.h" +#include "qapi/error.h" #include "qemu/module.h" #include "qemu/timer.h" #include "exec/address-spaces.h" +#include "qom/object.h" /* #define DEBUG_VT82C686B */ @@ -41,15 +43,14 @@ typedef struct SuperIOConfig { uint8_t data; } SuperIOConfig; -typedef struct VT82C686BState { +struct VT82C686BState { PCIDevice dev; MemoryRegion superio; SuperIOConfig superio_conf; -} VT82C686BState; +}; #define TYPE_VT82C686B_DEVICE "VT82C686B" -#define VT82C686B_DEVICE(obj) \ - OBJECT_CHECK(VT82C686BState, (obj), TYPE_VT82C686B_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(VT82C686BState, VT82C686B_DEVICE) static void superio_ioport_writeb(void *opaque, hwaddr addr, uint64_t data, unsigned size) @@ -158,34 +159,31 @@ static void vt82c686b_write_config(PCIDevice *d, uint32_t address, #define ACPI_DBG_IO_ADDR 0xb044 -typedef struct VT686PMState { +struct VT686PMState { PCIDevice dev; MemoryRegion io; ACPIREGS ar; APMState apm; PMSMBus smb; uint32_t smb_io_base; -} VT686PMState; +}; -typedef struct VT686AC97State { +struct VT686AC97State { PCIDevice dev; -} VT686AC97State; +}; -typedef struct VT686MC97State { +struct VT686MC97State { PCIDevice dev; -} VT686MC97State; +}; #define TYPE_VT82C686B_PM_DEVICE "VT82C686B_PM" -#define VT82C686B_PM_DEVICE(obj) \ - OBJECT_CHECK(VT686PMState, (obj), TYPE_VT82C686B_PM_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(VT686PMState, VT82C686B_PM_DEVICE) #define TYPE_VT82C686B_MC97_DEVICE "VT82C686B_MC97" -#define VT82C686B_MC97_DEVICE(obj) \ - OBJECT_CHECK(VT686MC97State, (obj), TYPE_VT82C686B_MC97_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(VT686MC97State, VT82C686B_MC97_DEVICE) #define TYPE_VT82C686B_AC97_DEVICE "VT82C686B_AC97" -#define VT82C686B_AC97_DEVICE(obj) \ - OBJECT_CHECK(VT686AC97State, (obj), TYPE_VT82C686B_AC97_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(VT686AC97State, VT82C686B_AC97_DEVICE) static void pm_update_sci(VT686PMState *s) { @@ -276,8 +274,8 @@ void vt82c686b_ac97_init(PCIBus *bus, int devfn) { PCIDevice *dev; - dev = pci_create(bus, devfn, TYPE_VT82C686B_AC97_DEVICE); - qdev_init_nofail(&dev->qdev); + dev = pci_new(devfn, TYPE_VT82C686B_AC97_DEVICE); + pci_realize_and_unref(dev, bus, &error_fatal); } static void via_ac97_class_init(ObjectClass *klass, void *data) @@ -320,8 +318,8 @@ void vt82c686b_mc97_init(PCIBus *bus, int devfn) { PCIDevice *dev; - dev = pci_create(bus, devfn, TYPE_VT82C686B_MC97_DEVICE); - qdev_init_nofail(&dev->qdev); + dev = pci_new(devfn, TYPE_VT82C686B_MC97_DEVICE); + pci_realize_and_unref(dev, bus, &error_fatal); } static void via_mc97_class_init(ObjectClass *klass, void *data) @@ -388,12 +386,12 @@ I2CBus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, PCIDevice *dev; VT686PMState *s; - dev = pci_create(bus, devfn, TYPE_VT82C686B_PM_DEVICE); + dev = pci_new(devfn, TYPE_VT82C686B_PM_DEVICE); qdev_prop_set_uint32(&dev->qdev, "smb_io_base", smb_io_base); s = VT82C686B_PM_DEVICE(dev); - qdev_init_nofail(&dev->qdev); + pci_realize_and_unref(dev, bus, &error_fatal); return s->smb.smbus; } diff --git a/hw/lm32/Makefile.objs b/hw/lm32/Makefile.objs deleted file mode 100644 index c3941866c746f810ec125f488f608a9109e9eec6..0000000000000000000000000000000000000000 --- a/hw/lm32/Makefile.objs +++ /dev/null @@ -1,3 +0,0 @@ -# LM32 boards -obj-$(CONFIG_LM32) += lm32_boards.o -obj-$(CONFIG_MILKYMIST) += milkymist.o diff --git a/hw/lm32/lm32.h b/hw/lm32/lm32.h index 98de07acf2cea4639331b901877c2ce709ce3ecd..7b4f6255b91167adb6221f1646715d8c41460ffb 100644 --- a/hw/lm32/lm32.h +++ b/hw/lm32/lm32.h @@ -3,15 +3,16 @@ #include "hw/char/lm32_juart.h" #include "hw/qdev-properties.h" +#include "qapi/error.h" static inline DeviceState *lm32_pic_init(qemu_irq cpu_irq) { DeviceState *dev; SysBusDevice *d; - dev = qdev_create(NULL, "lm32-pic"); - qdev_init_nofail(dev); + dev = qdev_new("lm32-pic"); d = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(d, &error_fatal); sysbus_connect_irq(d, 0, cpu_irq); return dev; @@ -21,9 +22,9 @@ static inline DeviceState *lm32_juart_init(Chardev *chr) { DeviceState *dev; - dev = qdev_create(NULL, TYPE_LM32_JUART); + dev = qdev_new(TYPE_LM32_JUART); qdev_prop_set_chr(dev, "chardev", chr); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); return dev; } @@ -35,10 +36,10 @@ static inline DeviceState *lm32_uart_create(hwaddr addr, DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, "lm32-uart"); + dev = qdev_new("lm32-uart"); s = SYS_BUS_DEVICE(dev); qdev_prop_set_chr(dev, "chardev", chr); - qdev_init_nofail(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, addr); sysbus_connect_irq(s, 0, irq); return dev; diff --git a/hw/lm32/lm32_boards.c b/hw/lm32/lm32_boards.c index b842f74344478670cab15dde5969db0c9c5d9d50..b5d97dd53edd5d8ed789ff0238de81cc9c54a07b 100644 --- a/hw/lm32/lm32_boards.c +++ b/hw/lm32/lm32_boards.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/lm32/lm32_hwsetup.h b/hw/lm32/lm32_hwsetup.h index de94de177aa1e99918b6918c8794710fda1afdc1..e6cd30ad6865b01891fd1f4855e7fa59e74ad6a1 100644 --- a/hw/lm32/lm32_hwsetup.h +++ b/hw/lm32/lm32_hwsetup.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/lm32/meson.build b/hw/lm32/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..8caf0a727ff82a5b65f7a132719cad26744a8961 --- /dev/null +++ b/hw/lm32/meson.build @@ -0,0 +1,6 @@ +lm32_ss = ss.source_set() +# LM32 boards +lm32_ss.add(when: 'CONFIG_LM32', if_true: files('lm32_boards.c')) +lm32_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist.c')) + +hw_arch += {'lm32': lm32_ss} diff --git a/hw/lm32/milkymist-hw.h b/hw/lm32/milkymist-hw.h index 5f630243559bd3b4b9e4122def9464d3ec58ef09..5dca5d52f579f4a65a18db61c8600817047bbbf3 100644 --- a/hw/lm32/milkymist-hw.h +++ b/hw/lm32/milkymist-hw.h @@ -3,6 +3,7 @@ #include "hw/qdev-core.h" #include "net/net.h" +#include "qapi/error.h" static inline DeviceState *milkymist_uart_create(hwaddr base, qemu_irq irq, @@ -10,9 +11,9 @@ static inline DeviceState *milkymist_uart_create(hwaddr base, { DeviceState *dev; - dev = qdev_create(NULL, "milkymist-uart"); + dev = qdev_new("milkymist-uart"); qdev_prop_set_chr(dev, "chardev", chr); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq); @@ -23,19 +24,8 @@ static inline DeviceState *milkymist_hpdmc_create(hwaddr base) { DeviceState *dev; - dev = qdev_create(NULL, "milkymist-hpdmc"); - qdev_init_nofail(dev); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); - - return dev; -} - -static inline DeviceState *milkymist_memcard_create(hwaddr base) -{ - DeviceState *dev; - - dev = qdev_create(NULL, "milkymist-memcard"); - qdev_init_nofail(dev); + dev = qdev_new("milkymist-hpdmc"); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); return dev; @@ -46,10 +36,10 @@ static inline DeviceState *milkymist_vgafb_create(hwaddr base, { DeviceState *dev; - dev = qdev_create(NULL, "milkymist-vgafb"); + dev = qdev_new("milkymist-vgafb"); qdev_prop_set_uint32(dev, "fb_offset", fb_offset); qdev_prop_set_uint32(dev, "fb_mask", fb_mask); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); return dev; @@ -62,12 +52,12 @@ static inline DeviceState *milkymist_sysctl_create(hwaddr base, { DeviceState *dev; - dev = qdev_create(NULL, "milkymist-sysctl"); + dev = qdev_new("milkymist-sysctl"); qdev_prop_set_uint32(dev, "frequency", freq_hz); qdev_prop_set_uint32(dev, "systemid", system_id); qdev_prop_set_uint32(dev, "capabilities", capabilities); qdev_prop_set_uint32(dev, "gpio_strappings", gpio_strappings); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, gpio_irq); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, timer0_irq); @@ -81,8 +71,8 @@ static inline DeviceState *milkymist_pfpu_create(hwaddr base, { DeviceState *dev; - dev = qdev_create(NULL, "milkymist-pfpu"); - qdev_init_nofail(dev); + dev = qdev_new("milkymist-pfpu"); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq); return dev; @@ -94,8 +84,8 @@ static inline DeviceState *milkymist_ac97_create(hwaddr base, { DeviceState *dev; - dev = qdev_create(NULL, "milkymist-ac97"); - qdev_init_nofail(dev); + dev = qdev_new("milkymist-ac97"); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, crrequest_irq); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, crreply_irq); @@ -111,9 +101,9 @@ static inline DeviceState *milkymist_minimac2_create(hwaddr base, DeviceState *dev; qemu_check_nic_model(&nd_table[0], "minimac2"); - dev = qdev_create(NULL, "milkymist-minimac2"); + dev = qdev_new("milkymist-minimac2"); qdev_set_nic_properties(dev, &nd_table[0]); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, buffers_base); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, rx_irq); @@ -128,10 +118,10 @@ static inline DeviceState *milkymist_softusb_create(hwaddr base, { DeviceState *dev; - dev = qdev_create(NULL, "milkymist-softusb"); + dev = qdev_new("milkymist-softusb"); qdev_prop_set_uint32(dev, "pmem_size", pmem_size); qdev_prop_set_uint32(dev, "dmem_size", dmem_size); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, pmem_base); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, dmem_base); diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c index 85913bb68b6c3f3473107d01c1cbfc681387db80..9ef94883d5074c2262578d59d441bb0ac209a4de 100644 --- a/hw/lm32/milkymist.c +++ b/hw/lm32/milkymist.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -34,6 +34,7 @@ #include "elf.h" #include "milkymist-hw.h" #include "hw/display/milkymist_tmu2.h" +#include "hw/sd/sd.h" #include "lm32.h" #include "exec/address-spaces.h" #include "qemu/cutils.h" @@ -80,6 +81,29 @@ static void main_cpu_reset(void *opaque) env->deba = reset_info->flash_base; } +static DeviceState *milkymist_memcard_create(hwaddr base) +{ + DeviceState *dev; + DriveInfo *dinfo; + + dev = qdev_new("milkymist-memcard"); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); + + dinfo = drive_get_next(IF_SD); + if (dinfo) { + DeviceState *card; + + card = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo), + &error_fatal); + qdev_realize_and_unref(card, qdev_get_child_bus(dev, "sd-bus"), + &error_fatal); + } + + return dev; +} + static void milkymist_init(MachineState *machine) { diff --git a/hw/m68k/Makefile.objs b/hw/m68k/Makefile.objs deleted file mode 100644 index b2c9e5ab125fdb344d2051821b43c1f96e5b508f..0000000000000000000000000000000000000000 --- a/hw/m68k/Makefile.objs +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_AN5206) += an5206.o mcf5206.o -obj-$(CONFIG_MCF5208) += mcf5208.o mcf_intc.o -obj-$(CONFIG_NEXTCUBE) += next-kbd.o next-cube.o -obj-$(CONFIG_Q800) += q800.o diff --git a/hw/m68k/an5206.c b/hw/m68k/an5206.c index 846f4e40c6970aa484e11c0796a6d20ea60e3d95..673898b0eac6756fd599888af2186be7f57eb1ef 100644 --- a/hw/m68k/an5206.c +++ b/hw/m68k/an5206.c @@ -21,7 +21,17 @@ #define AN5206_MBAR_ADDR 0x10000000 #define AN5206_RAMBAR_ADDR 0x20000000 -/* Board init. */ +static void mcf5206_init(MemoryRegion *sysmem, uint32_t base) +{ + DeviceState *dev; + SysBusDevice *s; + + dev = qdev_new(TYPE_MCF5206_MBAR); + s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); + + memory_region_add_subregion(sysmem, base, sysbus_mmio_get_region(s, 0)); +} static void an5206_init(MachineState *machine) { @@ -51,7 +61,7 @@ static void an5206_init(MachineState *machine) memory_region_init_ram(sram, NULL, "an5206.sram", 512, &error_fatal); memory_region_add_subregion(address_space_mem, AN5206_RAMBAR_ADDR, sram); - mcf5206_init(address_space_mem, AN5206_MBAR_ADDR, cpu); + mcf5206_init(address_space_mem, AN5206_MBAR_ADDR); /* Load kernel. */ if (!kernel_filename) { diff --git a/hw/m68k/mcf5206.c b/hw/m68k/mcf5206.c index b155dd81705d7e399a9b6ec3285b05fdf6068be5..51d2e0da1c994126db082b21f0633b480aa52999 100644 --- a/hw/m68k/mcf5206.c +++ b/hw/m68k/mcf5206.c @@ -8,13 +8,14 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" +#include "qemu/log.h" #include "cpu.h" -#include "hw/hw.h" #include "hw/irq.h" #include "hw/m68k/mcf.h" #include "qemu/timer.h" #include "hw/ptimer.h" #include "sysemu/sysemu.h" +#include "hw/sysbus.h" /* General purpose timer module. */ typedef struct { @@ -68,10 +69,16 @@ static void m5206_timer_recalibrate(m5206_timer_state *s) if (mode == 2) prescale *= 16; - if (mode == 3 || mode == 0) - hw_error("m5206_timer: mode %d not implemented\n", mode); - if ((s->tmr & TMR_FRR) == 0) - hw_error("m5206_timer: free running mode not implemented\n"); + if (mode == 3 || mode == 0) { + qemu_log_mask(LOG_UNIMP, "m5206_timer: mode %d not implemented\n", + mode); + goto exit; + } + if ((s->tmr & TMR_FRR) == 0) { + qemu_log_mask(LOG_UNIMP, + "m5206_timer: free running mode not implemented\n"); + goto exit; + } /* Assume 66MHz system clock. */ ptimer_set_freq(s->timer, 66000000 / prescale); @@ -153,6 +160,8 @@ static m5206_timer_state *m5206_timer_init(qemu_irq irq) /* System Integration Module. */ typedef struct { + SysBusDevice parent_obj; + M68kCPU *cpu; MemoryRegion iomem; m5206_timer_state *timer[2]; @@ -168,6 +177,8 @@ typedef struct { uint8_t uivr[2]; } m5206_mbar_state; +#define MCF5206_MBAR(obj) OBJECT_CHECK(m5206_mbar_state, (obj), TYPE_MCF5206_MBAR) + /* Interrupt controller. */ static int m5206_find_pending_irq(m5206_mbar_state *s) @@ -225,7 +236,8 @@ static void m5206_mbar_update(m5206_mbar_state *s) break; default: /* Unknown vector. */ - error_report("Unhandled vector for IRQ %d", irq); + qemu_log_mask(LOG_UNIMP, "%s: Unhandled vector for IRQ %d\n", + __func__, irq); vector = 0xf; break; } @@ -250,8 +262,10 @@ static void m5206_mbar_set_irq(void *opaque, int irq, int level) /* System Integration Module. */ -static void m5206_mbar_reset(m5206_mbar_state *s) +static void m5206_mbar_reset(DeviceState *dev) { + m5206_mbar_state *s = MCF5206_MBAR(dev); + s->scr = 0xc0; s->icr[1] = 0x04; s->icr[2] = 0x08; @@ -273,7 +287,7 @@ static void m5206_mbar_reset(m5206_mbar_state *s) } static uint64_t m5206_mbar_read(m5206_mbar_state *s, - uint64_t offset, unsigned size) + uint16_t offset, unsigned size) { if (offset >= 0x100 && offset < 0x120) { return m5206_timer_read(s->timer[0], offset - 0x100); @@ -306,11 +320,12 @@ static uint64_t m5206_mbar_read(m5206_mbar_state *s, case 0x170: return s->uivr[0]; case 0x1b0: return s->uivr[1]; } - hw_error("Bad MBAR read offset 0x%x", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad MBAR offset 0x%"PRIx16"\n", + __func__, offset); return 0; } -static void m5206_mbar_write(m5206_mbar_state *s, uint32_t offset, +static void m5206_mbar_write(m5206_mbar_state *s, uint16_t offset, uint64_t value, unsigned size) { if (offset >= 0x100 && offset < 0x120) { @@ -360,7 +375,8 @@ static void m5206_mbar_write(m5206_mbar_state *s, uint32_t offset, s->uivr[1] = value; break; default: - hw_error("Bad MBAR write offset 0x%x", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad MBAR offset 0x%"PRIx16"\n", + __func__, offset); break; } } @@ -387,7 +403,9 @@ static uint32_t m5206_mbar_readb(void *opaque, hwaddr offset) m5206_mbar_state *s = (m5206_mbar_state *)opaque; offset &= 0x3ff; if (offset >= 0x200) { - hw_error("Bad MBAR read offset 0x%x", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR read offset 0x%" HWADDR_PRIX, + offset); + return 0; } if (m5206_mbar_width[offset >> 2] > 1) { uint16_t val; @@ -406,7 +424,9 @@ static uint32_t m5206_mbar_readw(void *opaque, hwaddr offset) int width; offset &= 0x3ff; if (offset >= 0x200) { - hw_error("Bad MBAR read offset 0x%x", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR read offset 0x%" HWADDR_PRIX, + offset); + return 0; } width = m5206_mbar_width[offset >> 2]; if (width > 2) { @@ -430,7 +450,9 @@ static uint32_t m5206_mbar_readl(void *opaque, hwaddr offset) int width; offset &= 0x3ff; if (offset >= 0x200) { - hw_error("Bad MBAR read offset 0x%x", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR read offset 0x%" HWADDR_PRIX, + offset); + return 0; } width = m5206_mbar_width[offset >> 2]; if (width < 4) { @@ -454,7 +476,9 @@ static void m5206_mbar_writeb(void *opaque, hwaddr offset, int width; offset &= 0x3ff; if (offset >= 0x200) { - hw_error("Bad MBAR write offset 0x%x", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR write offset 0x%" HWADDR_PRIX, + offset); + return; } width = m5206_mbar_width[offset >> 2]; if (width > 1) { @@ -478,7 +502,9 @@ static void m5206_mbar_writew(void *opaque, hwaddr offset, int width; offset &= 0x3ff; if (offset >= 0x200) { - hw_error("Bad MBAR write offset 0x%x", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR write offset 0x%" HWADDR_PRIX, + offset); + return; } width = m5206_mbar_width[offset >> 2]; if (width > 2) { @@ -506,7 +532,9 @@ static void m5206_mbar_writel(void *opaque, hwaddr offset, int width; offset &= 0x3ff; if (offset >= 0x200) { - hw_error("Bad MBAR write offset 0x%x", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR write offset 0x%" HWADDR_PRIX, + offset); + return; } width = m5206_mbar_width[offset >> 2]; if (width < 4) { @@ -557,24 +585,43 @@ static const MemoryRegionOps m5206_mbar_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -qemu_irq *mcf5206_init(MemoryRegion *sysmem, uint32_t base, M68kCPU *cpu) +static void mcf5206_mbar_realize(DeviceState *dev, Error **errp) { - m5206_mbar_state *s; + m5206_mbar_state *s = MCF5206_MBAR(dev); qemu_irq *pic; - s = g_new0(m5206_mbar_state, 1); - memory_region_init_io(&s->iomem, NULL, &m5206_mbar_ops, s, "mbar", 0x00001000); - memory_region_add_subregion(sysmem, base, &s->iomem); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); pic = qemu_allocate_irqs(m5206_mbar_set_irq, s, 14); s->timer[0] = m5206_timer_init(pic[9]); s->timer[1] = m5206_timer_init(pic[10]); s->uart[0] = mcf_uart_init(pic[12], serial_hd(0)); s->uart[1] = mcf_uart_init(pic[13], serial_hd(1)); - s->cpu = cpu; + s->cpu = M68K_CPU(qemu_get_cpu(0)); +} - m5206_mbar_reset(s); - return pic; +static void mcf5206_mbar_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + dc->desc = "MCF5206 system integration module"; + dc->realize = mcf5206_mbar_realize; + dc->reset = m5206_mbar_reset; } + +static const TypeInfo mcf5206_mbar_info = { + .name = TYPE_MCF5206_MBAR, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(m5206_mbar_state), + .class_init = mcf5206_mbar_class_init, +}; + +static void mcf5206_mbar_register_types(void) +{ + type_register_static(&mcf5206_mbar_info); +} + +type_init(mcf5206_mbar_register_types) diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c index b84c152ce3ca996b4fe05b4236edadb84fdcc1d6..d310a98e7b7fdd4d8d9a48b30a017b9ac97f1376 100644 --- a/hw/m68k/mcf5208.c +++ b/hw/m68k/mcf5208.c @@ -9,10 +9,10 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qemu/error-report.h" +#include "qemu/log.h" #include "qapi/error.h" #include "qemu-common.h" #include "cpu.h" -#include "hw/hw.h" #include "hw/irq.h" #include "hw/m68k/mcf.h" #include "hw/m68k/mcf_fec.h" @@ -111,8 +111,9 @@ static void m5208_timer_write(void *opaque, hwaddr offset, case 4: break; default: - hw_error("m5208_timer_write: Bad offset 0x%x\n", (int)offset); - break; + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", + __func__, offset); + return; } m5208_timer_update(s); } @@ -136,7 +137,8 @@ static uint64_t m5208_timer_read(void *opaque, hwaddr addr, case 4: return ptimer_get_count(s->timer); default: - hw_error("m5208_timer_read: Bad offset 0x%x\n", (int)addr); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", + __func__, addr); return 0; } } @@ -164,7 +166,8 @@ static uint64_t m5208_sys_read(void *opaque, hwaddr addr, return 0; default: - hw_error("m5208_sys_read: Bad offset 0x%x\n", (int)addr); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", + __func__, addr); return 0; } } @@ -172,7 +175,8 @@ static uint64_t m5208_sys_read(void *opaque, hwaddr addr, static void m5208_sys_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { - hw_error("m5208_sys_write: Bad offset 0x%x\n", (int)addr); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", + __func__, addr); } static const MemoryRegionOps m5208_sys_ops = { @@ -210,11 +214,11 @@ static void mcf_fec_init(MemoryRegion *sysmem, NICInfo *nd, hwaddr base, int i; qemu_check_nic_model(nd, TYPE_MCF_FEC_NET); - dev = qdev_create(NULL, TYPE_MCF_FEC_NET); + dev = qdev_new(TYPE_MCF_FEC_NET); qdev_set_nic_properties(dev, nd); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); for (i = 0; i < FEC_NUM_IRQ; i++) { sysbus_connect_irq(s, i, irqs[i]); } diff --git a/hw/m68k/mcf_intc.c b/hw/m68k/mcf_intc.c index d9e03a06ab390ca8c26b1aefded4ec5aab08482f..cf02f57a711773581298c2d8c436ecb28dc16122 100644 --- a/hw/m68k/mcf_intc.c +++ b/hw/m68k/mcf_intc.c @@ -7,17 +7,20 @@ */ #include "qemu/osdep.h" +#include "qapi/error.h" #include "qemu/module.h" +#include "qemu/log.h" #include "cpu.h" #include "hw/hw.h" #include "hw/irq.h" #include "hw/sysbus.h" #include "hw/m68k/mcf.h" +#include "qom/object.h" #define TYPE_MCF_INTC "mcf-intc" -#define MCF_INTC(obj) OBJECT_CHECK(mcf_intc_state, (obj), TYPE_MCF_INTC) +OBJECT_DECLARE_SIMPLE_TYPE(mcf_intc_state, MCF_INTC) -typedef struct { +struct mcf_intc_state { SysBusDevice parent_obj; MemoryRegion iomem; @@ -28,7 +31,7 @@ typedef struct { uint8_t icr[64]; M68kCPU *cpu; int active_vector; -} mcf_intc_state; +}; static void mcf_intc_update(mcf_intc_state *s) { @@ -80,7 +83,9 @@ static uint64_t mcf_intc_read(void *opaque, hwaddr addr, case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: /* LnIACK */ - hw_error("mcf_intc_read: LnIACK not implemented\n"); + qemu_log_mask(LOG_UNIMP, "%s: LnIACK not implemented (offset 0x%02x)\n", + __func__, offset); + /* fallthru */ default: return 0; } @@ -127,8 +132,9 @@ static void mcf_intc_write(void *opaque, hwaddr addr, } break; default: - hw_error("mcf_intc_write: Bad write offset %d\n", offset); - break; + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%02x\n", + __func__, offset); + return; } mcf_intc_update(s); } @@ -200,8 +206,8 @@ qemu_irq *mcf_intc_init(MemoryRegion *sysmem, DeviceState *dev; mcf_intc_state *s; - dev = qdev_create(NULL, TYPE_MCF_INTC); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_MCF_INTC); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); s = MCF_INTC(dev); s->cpu = cpu; diff --git a/hw/m68k/meson.build b/hw/m68k/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..ca0044c652d3a5234e56b2be766c17f393b4625d --- /dev/null +++ b/hw/m68k/meson.build @@ -0,0 +1,7 @@ +m68k_ss = ss.source_set() +m68k_ss.add(when: 'CONFIG_AN5206', if_true: files('an5206.c', 'mcf5206.c')) +m68k_ss.add(when: 'CONFIG_MCF5208', if_true: files('mcf5208.c', 'mcf_intc.c')) +m68k_ss.add(when: 'CONFIG_NEXTCUBE', if_true: files('next-kbd.c', 'next-cube.c')) +m68k_ss.add(when: 'CONFIG_Q800', if_true: files('q800.c')) + +hw_arch += {'m68k': m68k_ss} diff --git a/hw/m68k/next-cube.c b/hw/m68k/next-cube.c index 14b99ed25d90d62e61d5f4c99ba19a319ba38747..e7045980b7f03ea547921b9b31701febd7db442c 100644 --- a/hw/m68k/next-cube.c +++ b/hw/m68k/next-cube.c @@ -21,6 +21,7 @@ #include "hw/loader.h" #include "hw/scsi/esp.h" #include "hw/sysbus.h" +#include "qom/object.h" #include "hw/char/escc.h" /* ZILOG 8530 Serial Emulation */ #include "hw/block/fdc.h" #include "hw/qdev-properties.h" @@ -37,7 +38,7 @@ #endif #define TYPE_NEXT_MACHINE MACHINE_TYPE_NAME("next-cube") -#define NEXT_MACHINE(obj) OBJECT_CHECK(NeXTState, (obj), TYPE_NEXT_MACHINE) +OBJECT_DECLARE_SIMPLE_TYPE(NeXTState, NEXT_MACHINE) #define ENTRY 0x0100001e #define RAM_SIZE 0x4000000 @@ -69,7 +70,7 @@ typedef struct NextRtc { uint8_t retval; } NextRtc; -typedef struct { +struct NeXTState { MachineState parent; uint32_t int_mask; @@ -87,7 +88,7 @@ typedef struct { uint32_t scr2; NextRtc rtc; -} NeXTState; +}; /* Thanks to NeXT forums for this */ /* @@ -839,7 +840,7 @@ static void next_escc_init(M68kCPU *cpu) DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, TYPE_ESCC); + dev = qdev_new(TYPE_ESCC); qdev_prop_set_uint32(dev, "disabled", 0); qdev_prop_set_uint32(dev, "frequency", 9600 * 384); qdev_prop_set_uint32(dev, "it_shift", 0); @@ -848,9 +849,9 @@ static void next_escc_init(M68kCPU *cpu) qdev_prop_set_chr(dev, "chrA", serial_hd(0)); qdev_prop_set_uint32(dev, "chnBtype", escc_serial); qdev_prop_set_uint32(dev, "chnAtype", escc_serial); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_connect_irq(s, 0, ser_irq[0]); sysbus_connect_irq(s, 1, ser_irq[1]); sysbus_mmio_map(s, 0, 0x2118000); @@ -895,8 +896,8 @@ static void next_cube_init(MachineState *machine) memory_region_add_subregion(sysmem, 0x04000000, machine->ram); /* Framebuffer */ - dev = qdev_create(NULL, TYPE_NEXTFB); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_NEXTFB); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x0B000000); /* MMIO */ @@ -918,8 +919,8 @@ static void next_cube_init(MachineState *machine) memory_region_add_subregion(sysmem, 0x02100000, scrmem); /* KBD */ - dev = qdev_create(NULL, TYPE_NEXTKBD); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_NEXTKBD); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x0200e000); /* Load ROM here */ diff --git a/hw/m68k/next-kbd.c b/hw/m68k/next-kbd.c index 2dff87be151b98241b2f8f95167e904c603e9ea1..c11b5281f19967215c6754e3035356fd399e80d2 100644 --- a/hw/m68k/next-kbd.c +++ b/hw/m68k/next-kbd.c @@ -36,8 +36,9 @@ #include "ui/console.h" #include "sysemu/sysemu.h" #include "migration/vmstate.h" +#include "qom/object.h" -#define NEXTKBD(obj) OBJECT_CHECK(NextKBDState, (obj), TYPE_NEXTKBD) +OBJECT_DECLARE_SIMPLE_TYPE(NextKBDState, NEXTKBD) /* following defintions from next68k netbsd */ #define CSR_INT 0x00800000 @@ -63,12 +64,12 @@ typedef struct { } KBDQueue; -typedef struct NextKBDState { +struct NextKBDState { SysBusDevice sbd; MemoryRegion mr; KBDQueue queue; uint16_t shift; -} NextKBDState; +}; static void queue_code(void *opaque, int code); diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c index 81749e7ec6cf514a1641d65c13154da08e83cb87..ce4b47c3e34dffd0462dcc320c7481829b7c1396 100644 --- a/hw/m68k/q800.c +++ b/hw/m68k/q800.c @@ -218,24 +218,23 @@ static void q800_init(MachineState *machine) /* VIA */ - via_dev = qdev_create(NULL, TYPE_MAC_VIA); + via_dev = qdev_new(TYPE_MAC_VIA); dinfo = drive_get(IF_MTD, 0, 0); if (dinfo) { - qdev_prop_set_drive(via_dev, "drive", blk_by_legacy_dinfo(dinfo), - &error_abort); + qdev_prop_set_drive(via_dev, "drive", blk_by_legacy_dinfo(dinfo)); } - qdev_init_nofail(via_dev); sysbus = SYS_BUS_DEVICE(via_dev); + sysbus_realize_and_unref(sysbus, &error_fatal); sysbus_mmio_map(sysbus, 0, VIA_BASE); qdev_connect_gpio_out_named(DEVICE(sysbus), "irq", 0, pic[0]); qdev_connect_gpio_out_named(DEVICE(sysbus), "irq", 1, pic[1]); adb_bus = qdev_get_child_bus(via_dev, "adb.0"); - dev = qdev_create(adb_bus, TYPE_ADB_KEYBOARD); - qdev_init_nofail(dev); - dev = qdev_create(adb_bus, TYPE_ADB_MOUSE); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_ADB_KEYBOARD); + qdev_realize_and_unref(dev, adb_bus, &error_fatal); + dev = qdev_new(TYPE_ADB_MOUSE); + qdev_realize_and_unref(dev, adb_bus, &error_fatal); /* MACSONIC */ @@ -259,21 +258,21 @@ static void q800_init(MachineState *machine) nd_table[0].macaddr.a[1] = 0x00; nd_table[0].macaddr.a[2] = 0x07; - dev = qdev_create(NULL, "dp8393x"); + dev = qdev_new("dp8393x"); qdev_set_nic_properties(dev, &nd_table[0]); qdev_prop_set_uint8(dev, "it_shift", 2); qdev_prop_set_bit(dev, "big_endian", true); - object_property_set_link(OBJECT(dev), OBJECT(get_system_memory()), - "dma_mr", &error_abort); - qdev_init_nofail(dev); + object_property_set_link(OBJECT(dev), "dma_mr", + OBJECT(get_system_memory()), &error_abort); sysbus = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sysbus, &error_fatal); sysbus_mmio_map(sysbus, 0, SONIC_BASE); sysbus_mmio_map(sysbus, 1, SONIC_PROM_BASE); sysbus_connect_irq(sysbus, 0, pic[2]); /* SCC */ - dev = qdev_create(NULL, TYPE_ESCC); + dev = qdev_new(TYPE_ESCC); qdev_prop_set_uint32(dev, "disabled", 0); qdev_prop_set_uint32(dev, "frequency", MAC_CLOCK); qdev_prop_set_uint32(dev, "it_shift", 1); @@ -282,25 +281,25 @@ static void q800_init(MachineState *machine) qdev_prop_set_chr(dev, "chrB", serial_hd(1)); qdev_prop_set_uint32(dev, "chnBtype", 0); qdev_prop_set_uint32(dev, "chnAtype", 0); - qdev_init_nofail(dev); sysbus = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sysbus, &error_fatal); sysbus_connect_irq(sysbus, 0, pic[3]); sysbus_connect_irq(sysbus, 1, pic[3]); sysbus_mmio_map(sysbus, 0, SCC_BASE); /* SCSI */ - dev = qdev_create(NULL, TYPE_ESP); - sysbus_esp = ESP_STATE(dev); + dev = qdev_new(TYPE_ESP); + sysbus_esp = ESP(dev); esp = &sysbus_esp->esp; esp->dma_memory_read = NULL; esp->dma_memory_write = NULL; esp->dma_opaque = NULL; sysbus_esp->it_shift = 4; esp->dma_enabled = 1; - qdev_init_nofail(dev); sysbus = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sysbus, &error_fatal); sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in_named(via_dev, "via2-irq", VIA2_IRQ_SCSI_BIT)); @@ -314,14 +313,14 @@ static void q800_init(MachineState *machine) /* SWIM floppy controller */ - dev = qdev_create(NULL, TYPE_SWIM); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_SWIM); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, SWIM_BASE); /* NuBus */ - dev = qdev_create(NULL, TYPE_MAC_NUBUS_BRIDGE); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_MAC_NUBUS_BRIDGE); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, NUBUS_SUPER_SLOT_BASE); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, NUBUS_SLOT_BASE); @@ -329,11 +328,11 @@ static void q800_init(MachineState *machine) /* framebuffer in nubus slot #9 */ - dev = qdev_create(BUS(nubus), TYPE_NUBUS_MACFB); + dev = qdev_new(TYPE_NUBUS_MACFB); qdev_prop_set_uint32(dev, "width", graphic_width); qdev_prop_set_uint32(dev, "height", graphic_height); qdev_prop_set_uint8(dev, "depth", graphic_depth); - qdev_init_nofail(dev); + qdev_realize_and_unref(dev, BUS(nubus), &error_fatal); cs = CPU(cpu); if (linux_boot) { diff --git a/hw/mem/Kconfig b/hw/mem/Kconfig index c27844900d3a5adc9dd06eb69e5c4ec30e1f6c32..a0ef2cf648e112233744ec859da1a4bb3cc6372d 100644 --- a/hw/mem/Kconfig +++ b/hw/mem/Kconfig @@ -9,3 +9,4 @@ config NVDIMM bool default y depends on (PC || PSERIES || ARM_VIRT) + select MEM_DEVICE diff --git a/hw/mem/Makefile.objs b/hw/mem/Makefile.objs deleted file mode 100644 index 56345befd0c719e4fa4ee09fef8a28ba28564301..0000000000000000000000000000000000000000 --- a/hw/mem/Makefile.objs +++ /dev/null @@ -1,3 +0,0 @@ -common-obj-$(CONFIG_DIMM) += pc-dimm.o -common-obj-y += memory-device.o -common-obj-$(CONFIG_NVDIMM) += nvdimm.o diff --git a/hw/mem/memory-device.c b/hw/mem/memory-device.c index 4bc9cf0917bf5734fb22af4e0be0102ad5b59122..cf0627fd01c1abd411385b8bfc337f16cf7ebe37 100644 --- a/hw/mem/memory-device.c +++ b/hw/mem/memory-device.c @@ -119,9 +119,10 @@ static uint64_t memory_device_get_free_addr(MachineState *ms, /* start of address space indicates the maximum alignment we expect */ if (!QEMU_IS_ALIGNED(range_lob(&as), align)) { - error_setg(errp, "the alignment (0x%" PRIx64 ") is not supported", - align); - return 0; + warn_report("the alignment (0x%" PRIx64 ") exceeds the expected" + " maximum alignment, memory will get fragmented and not" + " all 'maxmem' might be usable for memory devices.", + align); } memory_device_check_addable(ms, size, &err); @@ -151,7 +152,7 @@ static uint64_t memory_device_get_free_addr(MachineState *ms, return 0; } } else { - if (range_init(&new, range_lob(&as), size)) { + if (range_init(&new, QEMU_ALIGN_UP(range_lob(&as), align), size)) { error_setg(errp, "can't add memory device, device too big"); return 0; } @@ -258,7 +259,7 @@ void memory_device_pre_plug(MemoryDeviceState *md, MachineState *ms, { const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(md); Error *local_err = NULL; - uint64_t addr, align; + uint64_t addr, align = 0; MemoryRegion *mr; mr = mdc->get_memory_region(md, &local_err); @@ -266,7 +267,14 @@ void memory_device_pre_plug(MemoryDeviceState *md, MachineState *ms, goto out; } - align = legacy_align ? *legacy_align : memory_region_get_alignment(mr); + if (legacy_align) { + align = *legacy_align; + } else { + if (mdc->get_min_alignment) { + align = mdc->get_min_alignment(md); + } + align = MAX(align, memory_region_get_alignment(mr)); + } addr = mdc->get_addr(md); addr = memory_device_get_free_addr(ms, !addr ? NULL : &addr, align, memory_region_size(mr), &local_err); diff --git a/hw/mem/meson.build b/hw/mem/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..0d22f2b5727ebd75a21621941d85419b0d1eab71 --- /dev/null +++ b/hw/mem/meson.build @@ -0,0 +1,7 @@ +mem_ss = ss.source_set() +mem_ss.add(files('memory-device.c')) +mem_ss.add(when: 'CONFIG_DIMM', if_true: files('pc-dimm.c')) +mem_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_mc.c')) +mem_ss.add(when: 'CONFIG_NVDIMM', if_true: files('nvdimm.c')) + +softmmu_ss.add_all(when: 'CONFIG_MEM_DEVICE', if_true: mem_ss) diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c new file mode 100644 index 0000000000000000000000000000000000000000..0435d06ab446302d9eb02cad3676e1d70ce33075 --- /dev/null +++ b/hw/mem/npcm7xx_mc.c @@ -0,0 +1,84 @@ +/* + * Nuvoton NPCM7xx Memory Controller stub + * + * Copyright 2020 Google LLC + * + * 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. + */ + +#include "qemu/osdep.h" + +#include "hw/mem/npcm7xx_mc.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/units.h" + +#define NPCM7XX_MC_REGS_SIZE (4 * KiB) + +static uint64_t npcm7xx_mc_read(void *opaque, hwaddr addr, unsigned int size) +{ + /* + * If bits 8..11 @ offset 0 are not zero, the boot block thinks the memory + * controller has already been initialized and will skip DDR training. + */ + if (addr == 0) { + return 0x100; + } + + qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__); + + return 0; +} + +static void npcm7xx_mc_write(void *opaque, hwaddr addr, uint64_t v, + unsigned int size) +{ + qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__); +} + +static const MemoryRegionOps npcm7xx_mc_ops = { + .read = npcm7xx_mc_read, + .write = npcm7xx_mc_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + .unaligned = false, + }, +}; + +static void npcm7xx_mc_realize(DeviceState *dev, Error **errp) +{ + NPCM7xxMCState *s = NPCM7XX_MC(dev); + + memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_mc_ops, s, "regs", + NPCM7XX_MC_REGS_SIZE); + sysbus_init_mmio(&s->parent, &s->mmio); +} + +static void npcm7xx_mc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "NPCM7xx Memory Controller stub"; + dc->realize = npcm7xx_mc_realize; +} + +static const TypeInfo npcm7xx_mc_types[] = { + { + .name = TYPE_NPCM7XX_MC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(NPCM7xxMCState), + .class_init = npcm7xx_mc_class_init, + }, +}; +DEFINE_TYPES(npcm7xx_mc_types); diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c index c5adedcc6951bc18d25e073aed8874ce116e73ff..03c2201b564f405a8354da74f0887cbfb82d6f01 100644 --- a/hw/mem/nvdimm.c +++ b/hw/mem/nvdimm.c @@ -11,7 +11,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -45,28 +45,24 @@ static void nvdimm_set_label_size(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { NVDIMMDevice *nvdimm = NVDIMM(obj); - Error *local_err = NULL; uint64_t value; if (nvdimm->nvdimm_mr) { - error_setg(&local_err, "cannot change property value"); - goto out; + error_setg(errp, "cannot change property value"); + return; } - visit_type_size(v, name, &value, &local_err); - if (local_err) { - goto out; + if (!visit_type_size(v, name, &value, errp)) { + return; } if (value < MIN_NAMESPACE_LABEL_SIZE) { - error_setg(&local_err, "Property '%s.%s' (0x%" PRIx64 ") is required" - " at least 0x%lx", object_get_typename(obj), - name, value, MIN_NAMESPACE_LABEL_SIZE); - goto out; + error_setg(errp, "Property '%s.%s' (0x%" PRIx64 ") is required" + " at least 0x%lx", object_get_typename(obj), name, value, + MIN_NAMESPACE_LABEL_SIZE); + return; } nvdimm->label_size = value; -out: - error_propagate(errp, local_err); } static void nvdimm_get_uuid(Object *obj, Visitor *v, const char *name, @@ -86,23 +82,18 @@ static void nvdimm_set_uuid(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { NVDIMMDevice *nvdimm = NVDIMM(obj); - Error *local_err = NULL; char *value; - visit_type_str(v, name, &value, &local_err); - if (local_err) { - goto out; + if (!visit_type_str(v, name, &value, errp)) { + return; } if (qemu_uuid_parse(value, &nvdimm->uuid) != 0) { error_setg(errp, "Property '%s.%s' has invalid value", object_get_typename(obj), name); - goto out; } - g_free(value); -out: - error_propagate(errp, local_err); + g_free(value); } @@ -146,13 +137,12 @@ static void nvdimm_prepare_memory_region(NVDIMMDevice *nvdimm, Error **errp) if (size <= nvdimm->label_size || !pmem_size) { HostMemoryBackend *hostmem = dimm->hostmem; - char *path = object_get_canonical_path_component(OBJECT(hostmem)); error_setg(errp, "the size of memdev %s (0x%" PRIx64 ") is too " "small to contain nvdimm label (0x%" PRIx64 ") and " "aligned PMEM (0x%" PRIx64 ")", - path, memory_region_size(mr), nvdimm->label_size, align); - g_free(path); + object_get_canonical_path_component(OBJECT(hostmem)), + memory_region_size(mr), nvdimm->label_size, align); return; } diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c index f2a86ec4ee7d8d423548d8c78469fab683c23afb..12b655eda8b83ffd4f051b7acb70080315eb8d74 100644 --- a/hw/mem/pc-dimm.c +++ b/hw/mem/pc-dimm.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -44,27 +44,27 @@ void pc_dimm_pre_plug(PCDIMMDevice *dimm, MachineState *machine, &error_abort); if ((slot < 0 || slot >= machine->ram_slots) && slot != PC_DIMM_UNASSIGNED_SLOT) { - error_setg(&local_err, "invalid slot number %d, valid range is [0-%" - PRIu64 "]", slot, machine->ram_slots - 1); - goto out; + error_setg(errp, + "invalid slot number %d, valid range is [0-%" PRIu64 "]", + slot, machine->ram_slots - 1); + return; } slot = pc_dimm_get_free_slot(slot == PC_DIMM_UNASSIGNED_SLOT ? NULL : &slot, machine->ram_slots, &local_err); if (local_err) { - goto out; + error_propagate(errp, local_err); + return; } - object_property_set_int(OBJECT(dimm), slot, PC_DIMM_SLOT_PROP, + object_property_set_int(OBJECT(dimm), PC_DIMM_SLOT_PROP, slot, &error_abort); trace_mhp_pc_dimm_assigned_slot(slot); memory_device_pre_plug(MEMORY_DEVICE(dimm), machine, legacy_align, - &local_err); -out: - error_propagate(errp, local_err); + errp); } -void pc_dimm_plug(PCDIMMDevice *dimm, MachineState *machine, Error **errp) +void pc_dimm_plug(PCDIMMDevice *dimm, MachineState *machine) { PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region(dimm, @@ -179,9 +179,8 @@ static void pc_dimm_realize(DeviceState *dev, Error **errp) error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property is not set"); return; } else if (host_memory_backend_is_mapped(dimm->hostmem)) { - char *path = object_get_canonical_path_component(OBJECT(dimm->hostmem)); - error_setg(errp, "can't use already busy memdev: %s", path); - g_free(path); + error_setg(errp, "can't use already busy memdev: %s", + object_get_canonical_path_component(OBJECT(dimm->hostmem))); return; } if (((nb_numa_nodes > 0) && (dimm->node >= nb_numa_nodes)) || @@ -225,7 +224,7 @@ static uint64_t pc_dimm_md_get_addr(const MemoryDeviceState *md) static void pc_dimm_md_set_addr(MemoryDeviceState *md, uint64_t addr, Error **errp) { - object_property_set_uint(OBJECT(md), addr, PC_DIMM_ADDR_PROP, errp); + object_property_set_uint(OBJECT(md), PC_DIMM_ADDR_PROP, addr, errp); } static MemoryRegion *pc_dimm_md_get_memory_region(MemoryDeviceState *md, diff --git a/hw/mem/trace.h b/hw/mem/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..2f2c9454079bcfcdc962690371f981f7f537a58b --- /dev/null +++ b/hw/mem/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_mem.h" diff --git a/hw/meson.build b/hw/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..010de7219c1db1e461776cf1e8d2eceb8500881d --- /dev/null +++ b/hw/meson.build @@ -0,0 +1,67 @@ +subdir('9pfs') +subdir('acpi') +subdir('adc') +subdir('audio') +subdir('block') +subdir('char') +subdir('core') +subdir('cpu') +subdir('display') +subdir('dma') +subdir('gpio') +subdir('hyperv') +subdir('i2c') +subdir('ide') +subdir('input') +subdir('intc') +subdir('ipack') +subdir('ipmi') +subdir('isa') +subdir('mem') +subdir('misc') +subdir('net') +subdir('nubus') +subdir('nvram') +subdir('pci') +subdir('pci-bridge') +subdir('pci-host') +subdir('pcmcia') +subdir('rdma') +subdir('rtc') +subdir('scsi') +subdir('sd') +subdir('semihosting') +subdir('smbios') +subdir('ssi') +subdir('timer') +subdir('tpm') +subdir('usb') +subdir('vfio') +subdir('virtio') +subdir('watchdog') +subdir('xen') +subdir('xenpv') + +subdir('alpha') +subdir('arm') +subdir('avr') +subdir('cris') +subdir('hppa') +subdir('i386') +subdir('lm32') +subdir('m68k') +subdir('microblaze') +subdir('mips') +subdir('moxie') +subdir('nios2') +subdir('openrisc') +subdir('ppc') +subdir('riscv') +subdir('rx') +subdir('s390x') +subdir('sh4') +subdir('sparc') +subdir('sparc64') +subdir('tricore') +subdir('unicore32') +subdir('xtensa') diff --git a/hw/microblaze/Makefile.objs b/hw/microblaze/Makefile.objs deleted file mode 100644 index 8595a62f6c6feaa17c861233f093f903b26fc9db..0000000000000000000000000000000000000000 --- a/hw/microblaze/Makefile.objs +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_PETALOGIX_S3ADSP1800) += petalogix_s3adsp1800_mmu.o -obj-$(CONFIG_PETALOGIX_ML605) += petalogix_ml605_mmu.o -obj-$(CONFIG_XLNX_ZYNQMP_PMU) += xlnx-zynqmp-pmu.o -obj-y += boot.o diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c index 925e3f7c9db2adeccf4a761b2389a38a939451f1..8ad3c27f2c363caa997afe3028080968e56b6a4d 100644 --- a/hw/microblaze/boot.c +++ b/hw/microblaze/boot.c @@ -135,7 +135,7 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, if (kernel_filename) { int kernel_size; - uint64_t entry, low, high; + uint64_t entry, high; uint32_t base32; int big_endian = 0; @@ -145,7 +145,7 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, /* Boots a kernel elf binary. */ kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, - &entry, &low, &high, NULL, + &entry, NULL, &high, NULL, big_endian, EM_MICROBLAZE, 0, 0); base32 = entry; if (base32 == 0xc0000000) { diff --git a/hw/microblaze/meson.build b/hw/microblaze/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..bb9e4eb8f47aa099d048949024639a2933d5f1e8 --- /dev/null +++ b/hw/microblaze/meson.build @@ -0,0 +1,7 @@ +microblaze_ss = ss.source_set() +microblaze_ss.add(files('boot.c')) +microblaze_ss.add(when: 'CONFIG_PETALOGIX_S3ADSP1800', if_true: files('petalogix_s3adsp1800_mmu.c')) +microblaze_ss.add(when: 'CONFIG_PETALOGIX_ML605', if_true: files('petalogix_ml605_mmu.c')) +microblaze_ss.add(when: 'CONFIG_XLNX_ZYNQMP_PMU', if_true: files('xlnx-zynqmp-pmu.c')) + +hw_arch += {'microblaze': microblaze_ss} diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c index 05a5614a04a3e94af000de695c8bcc2365d26a88..159db6cbe2249b4d7551f79f236ca9f9a1626e9d 100644 --- a/hw/microblaze/petalogix_ml605_mmu.c +++ b/hw/microblaze/petalogix_ml605_mmu.c @@ -83,15 +83,15 @@ petalogix_ml605_init(MachineState *machine) /* init CPUs */ cpu = MICROBLAZE_CPU(object_new(TYPE_MICROBLAZE_CPU)); - object_property_set_str(OBJECT(cpu), "8.10.a", "version", &error_abort); + object_property_set_str(OBJECT(cpu), "version", "8.10.a", &error_abort); /* Use FPU but don't use floating point conversion and square * root instructions */ - object_property_set_int(OBJECT(cpu), 1, "use-fpu", &error_abort); - object_property_set_bool(OBJECT(cpu), true, "dcache-writeback", + object_property_set_int(OBJECT(cpu), "use-fpu", 1, &error_abort); + object_property_set_bool(OBJECT(cpu), "dcache-writeback", true, &error_abort); - object_property_set_bool(OBJECT(cpu), true, "endianness", &error_abort); - object_property_set_bool(OBJECT(cpu), true, "realized", &error_abort); + object_property_set_bool(OBJECT(cpu), "endianness", true, &error_abort); + qdev_realize(DEVICE(cpu), NULL, &error_abort); /* Attach emulated BRAM through the LMB. */ memory_region_init_ram(phys_lmb_bram, NULL, "petalogix_ml605.lmb_bram", @@ -110,9 +110,9 @@ petalogix_ml605_init(MachineState *machine) 64 * KiB, 2, 0x89, 0x18, 0x0000, 0x0, 0); - dev = qdev_create(NULL, "xlnx.xps-intc"); + dev = qdev_new("xlnx.xps-intc"); qdev_prop_set_uint32(dev, "kind-of-intr", 1 << TIMER_IRQ); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, INTC_BASEADDR); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(DEVICE(cpu), MB_CPU_IRQ)); @@ -125,17 +125,17 @@ petalogix_ml605_init(MachineState *machine) DEVICE_LITTLE_ENDIAN); /* 2 timers at irq 2 @ 100 Mhz. */ - dev = qdev_create(NULL, "xlnx.xps-timer"); + dev = qdev_new("xlnx.xps-timer"); qdev_prop_set_uint32(dev, "one-timer-only", 0); qdev_prop_set_uint32(dev, "clock-frequency", 100 * 1000000); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, TIMER_BASEADDR); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[TIMER_IRQ]); /* axi ethernet and dma initialization. */ qemu_check_nic_model(&nd_table[0], "xlnx.axi-ethernet"); - eth0 = qdev_create(NULL, "xlnx.axi-ethernet"); - dma = qdev_create(NULL, "xlnx.axi-dma"); + eth0 = qdev_new("xlnx.axi-ethernet"); + dma = qdev_new("xlnx.axi-dma"); /* FIXME: attach to the sysbus instead */ object_property_add_child(qdev_get_machine(), "xilinx-eth", OBJECT(eth0)); @@ -148,11 +148,11 @@ petalogix_ml605_init(MachineState *machine) qdev_set_nic_properties(eth0, &nd_table[0]); qdev_prop_set_uint32(eth0, "rxmem", 0x1000); qdev_prop_set_uint32(eth0, "txmem", 0x1000); - object_property_set_link(OBJECT(eth0), ds, - "axistream-connected", &error_abort); - object_property_set_link(OBJECT(eth0), cs, - "axistream-control-connected", &error_abort); - qdev_init_nofail(eth0); + object_property_set_link(OBJECT(eth0), "axistream-connected", ds, + &error_abort); + object_property_set_link(OBJECT(eth0), "axistream-control-connected", cs, + &error_abort); + sysbus_realize_and_unref(SYS_BUS_DEVICE(eth0), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(eth0), 0, AXIENET_BASEADDR); sysbus_connect_irq(SYS_BUS_DEVICE(eth0), 0, irq[AXIENET_IRQ]); @@ -161,11 +161,11 @@ petalogix_ml605_init(MachineState *machine) cs = object_property_get_link(OBJECT(eth0), "axistream-control-connected-target", NULL); qdev_prop_set_uint32(dma, "freqhz", 100 * 1000000); - object_property_set_link(OBJECT(dma), ds, - "axistream-connected", &error_abort); - object_property_set_link(OBJECT(dma), cs, - "axistream-control-connected", &error_abort); - qdev_init_nofail(dma); + object_property_set_link(OBJECT(dma), "axistream-connected", ds, + &error_abort); + object_property_set_link(OBJECT(dma), "axistream-control-connected", cs, + &error_abort); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dma), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dma), 0, AXIDMA_BASEADDR); sysbus_connect_irq(SYS_BUS_DEVICE(dma), 0, irq[AXIDMA_IRQ0]); sysbus_connect_irq(SYS_BUS_DEVICE(dma), 1, irq[AXIDMA_IRQ1]); @@ -173,10 +173,10 @@ petalogix_ml605_init(MachineState *machine) { SSIBus *spi; - dev = qdev_create(NULL, "xlnx.xps-spi"); + dev = qdev_new("xlnx.xps-spi"); qdev_prop_set_uint8(dev, "num-ss-bits", NUM_SPI_FLASHES); - qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, SPI_BASEADDR); sysbus_connect_irq(busdev, 0, irq[SPI_IRQ]); @@ -186,12 +186,13 @@ petalogix_ml605_init(MachineState *machine) DriveInfo *dinfo = drive_get_next(IF_MTD); qemu_irq cs_line; - dev = ssi_create_slave_no_init(spi, "n25q128"); + dev = qdev_new("n25q128"); if (dinfo) { - qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo), - &error_fatal); + qdev_prop_set_drive_err(dev, "drive", + blk_by_legacy_dinfo(dinfo), + &error_fatal); } - qdev_init_nofail(dev); + qdev_realize_and_unref(dev, BUS(spi), &error_fatal); cs_line = qdev_get_gpio_in_named(dev, SSI_GPIO_CS, 0); sysbus_connect_irq(busdev, i+1, cs_line); @@ -199,9 +200,9 @@ petalogix_ml605_init(MachineState *machine) } /* setup PVR to match kernel settings */ - cpu->env.pvr.regs[4] = 0xc56b8000; - cpu->env.pvr.regs[5] = 0xc56be000; - cpu->env.pvr.regs[10] = 0x0e000000; /* virtex 6 */ + cpu->cfg.pvr_regs[4] = 0xc56b8000; + cpu->cfg.pvr_regs[5] = 0xc56be000; + cpu->cfg.pvr_regs[10] = 0x0e000000; /* virtex 6 */ microblaze_load_kernel(cpu, MEMORY_BASEADDR, ram_size, machine->initrd_filename, diff --git a/hw/microblaze/petalogix_s3adsp1800_mmu.c b/hw/microblaze/petalogix_s3adsp1800_mmu.c index 0bb6cdea8d9022bb2c87db4cdec8708f60c1c587..9d959d1ad8038f5ee0dda49882d76c9be0893b86 100644 --- a/hw/microblaze/petalogix_s3adsp1800_mmu.c +++ b/hw/microblaze/petalogix_s3adsp1800_mmu.c @@ -70,8 +70,8 @@ petalogix_s3adsp1800_init(MachineState *machine) MemoryRegion *sysmem = get_system_memory(); cpu = MICROBLAZE_CPU(object_new(TYPE_MICROBLAZE_CPU)); - object_property_set_str(OBJECT(cpu), "7.10.d", "version", &error_abort); - object_property_set_bool(OBJECT(cpu), true, "realized", &error_abort); + object_property_set_str(OBJECT(cpu), "version", "7.10.d", &error_abort); + qdev_realize(DEVICE(cpu), NULL, &error_abort); /* Attach emulated BRAM through the LMB. */ memory_region_init_ram(phys_lmb_bram, NULL, @@ -89,10 +89,10 @@ petalogix_s3adsp1800_init(MachineState *machine) dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, 64 * KiB, 1, 0x89, 0x18, 0x0000, 0x0, 1); - dev = qdev_create(NULL, "xlnx.xps-intc"); + dev = qdev_new("xlnx.xps-intc"); qdev_prop_set_uint32(dev, "kind-of-intr", 1 << ETHLITE_IRQ | 1 << UARTLITE_IRQ); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, INTC_BASEADDR); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(DEVICE(cpu), MB_CPU_IRQ)); @@ -104,19 +104,19 @@ petalogix_s3adsp1800_init(MachineState *machine) serial_hd(0)); /* 2 timers at irq 2 @ 62 Mhz. */ - dev = qdev_create(NULL, "xlnx.xps-timer"); + dev = qdev_new("xlnx.xps-timer"); qdev_prop_set_uint32(dev, "one-timer-only", 0); qdev_prop_set_uint32(dev, "clock-frequency", 62 * 1000000); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, TIMER_BASEADDR); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[TIMER_IRQ]); qemu_check_nic_model(&nd_table[0], "xlnx.xps-ethernetlite"); - dev = qdev_create(NULL, "xlnx.xps-ethernetlite"); + dev = qdev_new("xlnx.xps-ethernetlite"); qdev_set_nic_properties(dev, &nd_table[0]); qdev_prop_set_uint32(dev, "tx-ping-pong", 0); qdev_prop_set_uint32(dev, "rx-ping-pong", 0); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, ETHLITE_BASEADDR); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[ETHLITE_IRQ]); diff --git a/hw/microblaze/xlnx-zynqmp-pmu.c b/hw/microblaze/xlnx-zynqmp-pmu.c index 028f31894d9d9669f08ad74dc0d554dfd429df90..1d1b4b5c192e878969b92d80e03e2e78b3640bcc 100644 --- a/hw/microblaze/xlnx-zynqmp-pmu.c +++ b/hw/microblaze/xlnx-zynqmp-pmu.c @@ -24,12 +24,12 @@ #include "hw/intc/xlnx-zynqmp-ipi.h" #include "hw/intc/xlnx-pmu-iomod-intc.h" +#include "qom/object.h" /* Define the PMU device */ #define TYPE_XLNX_ZYNQMP_PMU_SOC "xlnx,zynqmp-pmu-soc" -#define XLNX_ZYNQMP_PMU_SOC(obj) OBJECT_CHECK(XlnxZynqMPPMUSoCState, (obj), \ - TYPE_XLNX_ZYNQMP_PMU_SOC) +OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPPMUSoCState, XLNX_ZYNQMP_PMU_SOC) #define XLNX_ZYNQMP_PMU_ROM_SIZE 0x8000 #define XLNX_ZYNQMP_PMU_ROM_ADDR 0xFFD00000 @@ -46,7 +46,7 @@ static const uint64_t ipi_irq[XLNX_ZYNQMP_PMU_NUM_IPIS] = { 19, 20, 21, 22, }; -typedef struct XlnxZynqMPPMUSoCState { +struct XlnxZynqMPPMUSoCState { /*< private >*/ DeviceState parent_obj; @@ -54,24 +54,21 @@ typedef struct XlnxZynqMPPMUSoCState { MicroBlazeCPU cpu; XlnxPMUIOIntc intc; XlnxZynqMPIPI ipi[XLNX_ZYNQMP_PMU_NUM_IPIS]; -} XlnxZynqMPPMUSoCState; +}; static void xlnx_zynqmp_pmu_soc_init(Object *obj) { XlnxZynqMPPMUSoCState *s = XLNX_ZYNQMP_PMU_SOC(obj); - object_initialize_child(obj, "pmu-cpu", &s->cpu, sizeof(s->cpu), - TYPE_MICROBLAZE_CPU, &error_abort, NULL); + object_initialize_child(obj, "pmu-cpu", &s->cpu, TYPE_MICROBLAZE_CPU); - sysbus_init_child_obj(obj, "intc", &s->intc, sizeof(s->intc), - TYPE_XLNX_PMU_IO_INTC); + object_initialize_child(obj, "intc", &s->intc, TYPE_XLNX_PMU_IO_INTC); /* Create the IPI device */ for (int i = 0; i < XLNX_ZYNQMP_PMU_NUM_IPIS; i++) { char *name = g_strdup_printf("ipi%d", i); - sysbus_init_child_obj(obj, name, &s->ipi[i], - sizeof(XlnxZynqMPIPI), TYPE_XLNX_ZYNQMP_IPI); + object_initialize_child(obj, name, &s->ipi[i], TYPE_XLNX_ZYNQMP_IPI); g_free(name); } } @@ -79,41 +76,36 @@ static void xlnx_zynqmp_pmu_soc_init(Object *obj) static void xlnx_zynqmp_pmu_soc_realize(DeviceState *dev, Error **errp) { XlnxZynqMPPMUSoCState *s = XLNX_ZYNQMP_PMU_SOC(dev); - Error *err = NULL; - object_property_set_uint(OBJECT(&s->cpu), XLNX_ZYNQMP_PMU_ROM_ADDR, - "base-vectors", &error_abort); - object_property_set_bool(OBJECT(&s->cpu), true, "use-stack-protection", + object_property_set_uint(OBJECT(&s->cpu), "base-vectors", + XLNX_ZYNQMP_PMU_ROM_ADDR, &error_abort); + object_property_set_bool(OBJECT(&s->cpu), "use-stack-protection", true, &error_abort); - object_property_set_uint(OBJECT(&s->cpu), 0, "use-fpu", &error_abort); - object_property_set_uint(OBJECT(&s->cpu), 0, "use-hw-mul", &error_abort); - object_property_set_bool(OBJECT(&s->cpu), true, "use-barrel", + object_property_set_uint(OBJECT(&s->cpu), "use-fpu", 0, &error_abort); + object_property_set_uint(OBJECT(&s->cpu), "use-hw-mul", 0, &error_abort); + object_property_set_bool(OBJECT(&s->cpu), "use-barrel", true, &error_abort); - object_property_set_bool(OBJECT(&s->cpu), true, "use-msr-instr", + object_property_set_bool(OBJECT(&s->cpu), "use-msr-instr", true, &error_abort); - object_property_set_bool(OBJECT(&s->cpu), true, "use-pcmp-instr", + object_property_set_bool(OBJECT(&s->cpu), "use-pcmp-instr", true, &error_abort); - object_property_set_bool(OBJECT(&s->cpu), false, "use-mmu", &error_abort); - object_property_set_bool(OBJECT(&s->cpu), true, "endianness", + object_property_set_bool(OBJECT(&s->cpu), "use-mmu", false, &error_abort); + object_property_set_bool(OBJECT(&s->cpu), "endianness", true, &error_abort); - object_property_set_str(OBJECT(&s->cpu), "8.40.b", "version", + object_property_set_str(OBJECT(&s->cpu), "version", "8.40.b", &error_abort); - object_property_set_uint(OBJECT(&s->cpu), 0, "pvr", &error_abort); - object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err); - if (err) { - error_propagate(errp, err); + object_property_set_uint(OBJECT(&s->cpu), "pvr", 0, &error_abort); + if (!qdev_realize(DEVICE(&s->cpu), NULL, errp)) { return; } - object_property_set_uint(OBJECT(&s->intc), 0x10, "intc-intr-size", + object_property_set_uint(OBJECT(&s->intc), "intc-intr-size", 0x10, &error_abort); - object_property_set_uint(OBJECT(&s->intc), 0x0, "intc-level-edge", + object_property_set_uint(OBJECT(&s->intc), "intc-level-edge", 0x0, &error_abort); - object_property_set_uint(OBJECT(&s->intc), 0xffff, "intc-positive", + object_property_set_uint(OBJECT(&s->intc), "intc-positive", 0xffff, &error_abort); - object_property_set_bool(OBJECT(&s->intc), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->intc), errp)) { return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->intc), 0, XLNX_ZYNQMP_PMU_INTC_ADDR); @@ -122,8 +114,7 @@ static void xlnx_zynqmp_pmu_soc_realize(DeviceState *dev, Error **errp) /* Connect the IPI device */ for (int i = 0; i < XLNX_ZYNQMP_PMU_NUM_IPIS; i++) { - object_property_set_bool(OBJECT(&s->ipi[i]), true, "realized", - &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->ipi[i]), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->ipi[i]), 0, ipi_addr[i]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->ipi[i]), 0, qdev_get_gpio_in(DEVICE(&s->intc), ipi_irq[i])); @@ -175,9 +166,8 @@ static void xlnx_zynqmp_pmu_init(MachineState *machine) /* Create the PMU device */ object_initialize_child(OBJECT(machine), "pmu", pmu, - sizeof(XlnxZynqMPPMUSoCState), - TYPE_XLNX_ZYNQMP_PMU_SOC, &error_abort, NULL); - object_property_set_bool(OBJECT(pmu), true, "realized", &error_fatal); + TYPE_XLNX_ZYNQMP_PMU_SOC); + qdev_realize(DEVICE(pmu), NULL, &error_fatal); /* Load the kernel */ microblaze_load_kernel(&pmu->cpu, XLNX_ZYNQMP_PMU_RAM_ADDR, diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig index 67d39c56a4e7af08f347b4dd240694f514ce2aea..8be70122f4c8d30d0b352c7cd080b7d79b2b2bf0 100644 --- a/hw/mips/Kconfig +++ b/hw/mips/Kconfig @@ -1,16 +1,3 @@ -config R4K - bool - select ISA_BUS - select SERIAL_ISA - select I8259 - select I8254 - select MC146818RTC - imply VGA_ISA - imply NE2000_ISA - select IDE_ISA - select PCKBD - select PFLASH_CFI01 - config MALTA bool select ISA_SUPERIO diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs deleted file mode 100644 index 739e2b7b40f27764542b4c56e57d3fbb5da1af04..0000000000000000000000000000000000000000 --- a/hw/mips/Makefile.objs +++ /dev/null @@ -1,8 +0,0 @@ -obj-y += addr.o mips_int.o -obj-$(CONFIG_R4K) += r4k.o -obj-$(CONFIG_MALTA) += gt64xxx_pci.o malta.o -obj-$(CONFIG_MIPSSIM) += mipssim.o -obj-$(CONFIG_JAZZ) += jazz.o -obj-$(CONFIG_FULOONG) += fuloong2e.o -obj-$(CONFIG_MIPS_CPS) += cps.o -obj-$(CONFIG_MIPS_BOSTON) += boston.o diff --git a/hw/mips/boston.c b/hw/mips/boston.c index 98ecd25e8ecc580779a8adb55150963de8081d6c..3d40867dc4c220c6f0c1b326df4baed5e6ec31c9 100644 --- a/hw/mips/boston.c +++ b/hw/mips/boston.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -30,6 +30,7 @@ #include "hw/mips/cps.h" #include "hw/mips/cpudevs.h" #include "hw/pci-host/xilinx-pcie.h" +#include "hw/qdev-clock.h" #include "hw/qdev-properties.h" #include "qapi/error.h" #include "qemu/error-report.h" @@ -41,16 +42,20 @@ #include "sysemu/runstate.h" #include +#include "qom/object.h" -#define TYPE_MIPS_BOSTON "mips-boston" -#define BOSTON(obj) OBJECT_CHECK(BostonState, (obj), TYPE_MIPS_BOSTON) +#define TYPE_BOSTON "mips-boston" +typedef struct BostonState BostonState; +DECLARE_INSTANCE_CHECKER(BostonState, BOSTON, + TYPE_BOSTON) -typedef struct { +struct BostonState { SysBusDevice parent_obj; MachineState *mach; MIPSCPSState cps; SerialMM *uart; + Clock *cpuclk; CharBackend lcd_display; char lcd_content[8]; @@ -58,7 +63,7 @@ typedef struct { hwaddr kernel_entry; hwaddr fdt_base; -} BostonState; +}; enum boston_plat_reg { PLAT_FPGA_BUILD = 0x00, @@ -248,10 +253,19 @@ static const MemoryRegionOps boston_platreg_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; +static void mips_boston_instance_init(Object *obj) +{ + BostonState *s = BOSTON(obj); + + s->cpuclk = qdev_init_clock_out(DEVICE(obj), "cpu-refclk"); + clock_set_hz(s->cpuclk, 1000000000); /* 1 GHz */ +} + static const TypeInfo boston_device = { - .name = TYPE_MIPS_BOSTON, + .name = TYPE_BOSTON, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(BostonState), + .instance_init = mips_boston_instance_init, }; static void boston_register_types(void) @@ -335,11 +349,9 @@ static const void *boston_fdt_filter(void *opaque, const void *fdt_orig, MachineState *machine = s->mach; const char *cmdline; int err; - void *fdt; - size_t fdt_sz, ram_low_sz, ram_high_sz; - - fdt_sz = fdt_totalsize(fdt_orig) * 2; - fdt = g_malloc0(fdt_sz); + size_t ram_low_sz, ram_high_sz; + size_t fdt_sz = fdt_totalsize(fdt_orig) * 2; + g_autofree void *fdt = g_malloc0(fdt_sz); err = fdt_open_into(fdt_orig, fdt, fdt_sz); if (err) { @@ -366,7 +378,7 @@ static const void *boston_fdt_filter(void *opaque, const void *fdt_orig, s->fdt_base = *load_addr; - return fdt; + return g_steal_pointer(&fdt); } static const void *boston_kernel_filter(void *opaque, const void *kernel, @@ -400,7 +412,7 @@ xilinx_pcie_init(MemoryRegion *sys_mem, uint32_t bus_nr, DeviceState *dev; MemoryRegion *cfg, *mmio; - dev = qdev_create(NULL, TYPE_XILINX_PCIE_HOST); + dev = qdev_new(TYPE_XILINX_PCIE_HOST); qdev_prop_set_uint32(dev, "bus_nr", bus_nr); qdev_prop_set_uint64(dev, "cfg_base", cfg_base); @@ -409,7 +421,7 @@ xilinx_pcie_init(MemoryRegion *sys_mem, uint32_t bus_nr, qdev_prop_set_uint64(dev, "mmio_size", mmio_size); qdev_prop_set_bit(dev, "link_up", link_up); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); cfg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); memory_region_add_subregion_overlap(sys_mem, cfg_base, cfg, 0); @@ -426,7 +438,6 @@ static void boston_mach_init(MachineState *machine) { DeviceState *dev; BostonState *s; - Error *err = NULL; MemoryRegion *flash, *ddr_low_alias, *lcd, *platreg; MemoryRegion *sys_mem = get_system_memory(); XilinxPCIEHost *pcie2; @@ -442,8 +453,8 @@ static void boston_mach_init(MachineState *machine) exit(1); } - dev = qdev_create(NULL, TYPE_MIPS_BOSTON); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_BOSTON); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); s = BOSTON(dev); s->mach = machine; @@ -455,22 +466,20 @@ static void boston_mach_init(MachineState *machine) is_64b = cpu_supports_isa(machine->cpu_type, ISA_MIPS64); - sysbus_init_child_obj(OBJECT(machine), "cps", OBJECT(&s->cps), - sizeof(s->cps), TYPE_MIPS_CPS); - object_property_set_str(OBJECT(&s->cps), machine->cpu_type, "cpu-type", - &err); - object_property_set_int(OBJECT(&s->cps), machine->smp.cpus, "num-vp", &err); - object_property_set_bool(OBJECT(&s->cps), true, "realized", &err); - - if (err != NULL) { - error_report("%s", error_get_pretty(err)); - exit(1); - } + object_initialize_child(OBJECT(machine), "cps", &s->cps, TYPE_MIPS_CPS); + object_property_set_str(OBJECT(&s->cps), "cpu-type", machine->cpu_type, + &error_fatal); + object_property_set_int(OBJECT(&s->cps), "num-vp", machine->smp.cpus, + &error_fatal); + qdev_connect_clock_in(DEVICE(&s->cps), "clk-in", + qdev_get_clock_out(dev, "cpu-refclk")); + sysbus_realize(SYS_BUS_DEVICE(&s->cps), &error_fatal); sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->cps), 0, 0, 1); flash = g_new(MemoryRegion, 1); - memory_region_init_rom(flash, NULL, "boston.flash", 128 * MiB, &err); + memory_region_init_rom(flash, NULL, "boston.flash", 128 * MiB, + &error_fatal); memory_region_add_subregion_overlap(sys_mem, 0x18000000, flash, 0); memory_region_add_subregion_overlap(sys_mem, 0x80000000, machine->ram, 0); diff --git a/hw/mips/cps.c b/hw/mips/cps.c index 92b9b1a5f69654078cdf3b6aa8388c1a672ab4d7..962b1b0b87cc0480a30f5b7e7ea18a39caf34d0a 100644 --- a/hw/mips/cps.c +++ b/hw/mips/cps.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -22,6 +22,7 @@ #include "qemu/module.h" #include "hw/mips/cps.h" #include "hw/mips/mips.h" +#include "hw/qdev-clock.h" #include "hw/qdev-properties.h" #include "hw/mips/cpudevs.h" #include "sysemu/kvm.h" @@ -38,6 +39,7 @@ static void mips_cps_init(Object *obj) SysBusDevice *sbd = SYS_BUS_DEVICE(obj); MIPSCPSState *s = MIPS_CPS(obj); + s->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, NULL); /* * Cover entire address space as there do not seem to be any * constraints for the base address of CPC and GIC. @@ -52,9 +54,6 @@ static void main_cpu_reset(void *opaque) CPUState *cs = CPU(cpu); cpu_reset(cs); - - /* All VPs are halted on reset. Leave powering up to CPC. */ - cs->halted = 1; } static bool cpu_mips_itu_supported(CPUMIPSState *env) @@ -71,13 +70,29 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) CPUMIPSState *env; MIPSCPU *cpu; int i; - Error *err = NULL; target_ulong gcr_base; bool itu_present = false; bool saar_present = false; + if (!clock_get(s->clock)) { + error_setg(errp, "CPS input clock is not connected to an output clock"); + return; + } + for (i = 0; i < s->num_vp; i++) { - cpu = MIPS_CPU(cpu_create(s->cpu_type)); + cpu = MIPS_CPU(object_new(s->cpu_type)); + + /* All VPs are halted on reset. Leave powering up to CPC. */ + if (!object_property_set_bool(OBJECT(cpu), "start-powered-off", true, + errp)) { + return; + } + /* All cores use the same clock tree */ + qdev_connect_clock_in(DEVICE(cpu), "clk-in", s->clock); + + if (!qdev_realize_and_unref(DEVICE(cpu), NULL, errp)) { + return; + } /* Init internal devices */ cpu_mips_irq_init_cpu(cpu); @@ -99,18 +114,17 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) /* Inter-Thread Communication Unit */ if (itu_present) { - sysbus_init_child_obj(OBJECT(dev), "itu", &s->itu, sizeof(s->itu), - TYPE_MIPS_ITU); - object_property_set_int(OBJECT(&s->itu), 16, "num-fifo", &err); - object_property_set_int(OBJECT(&s->itu), 16, "num-semaphores", &err); - object_property_set_bool(OBJECT(&s->itu), saar_present, "saar-present", - &err); + object_initialize_child(OBJECT(dev), "itu", &s->itu, TYPE_MIPS_ITU); + object_property_set_int(OBJECT(&s->itu), "num-fifo", 16, + &error_abort); + object_property_set_int(OBJECT(&s->itu), "num-semaphores", 16, + &error_abort); + object_property_set_bool(OBJECT(&s->itu), "saar-present", saar_present, + &error_abort); if (saar_present) { s->itu.saar = &env->CP0_SAAR; } - object_property_set_bool(OBJECT(&s->itu), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->itu), errp)) { return; } @@ -119,13 +133,12 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) } /* Cluster Power Controller */ - sysbus_init_child_obj(OBJECT(dev), "cpc", &s->cpc, sizeof(s->cpc), - TYPE_MIPS_CPC); - object_property_set_int(OBJECT(&s->cpc), s->num_vp, "num-vp", &err); - object_property_set_int(OBJECT(&s->cpc), 1, "vp-start-running", &err); - object_property_set_bool(OBJECT(&s->cpc), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + object_initialize_child(OBJECT(dev), "cpc", &s->cpc, TYPE_MIPS_CPC); + object_property_set_int(OBJECT(&s->cpc), "num-vp", s->num_vp, + &error_abort); + object_property_set_int(OBJECT(&s->cpc), "vp-start-running", 1, + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpc), errp)) { return; } @@ -133,13 +146,12 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpc), 0)); /* Global Interrupt Controller */ - sysbus_init_child_obj(OBJECT(dev), "gic", &s->gic, sizeof(s->gic), - TYPE_MIPS_GIC); - object_property_set_int(OBJECT(&s->gic), s->num_vp, "num-vp", &err); - object_property_set_int(OBJECT(&s->gic), 128, "num-irq", &err); - object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + object_initialize_child(OBJECT(dev), "gic", &s->gic, TYPE_MIPS_GIC); + object_property_set_int(OBJECT(&s->gic), "num-vp", s->num_vp, + &error_abort); + object_property_set_int(OBJECT(&s->gic), "num-irq", 128, + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gic), errp)) { return; } @@ -149,16 +161,18 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) /* Global Configuration Registers */ gcr_base = env->CP0_CMGCRBase << 4; - sysbus_init_child_obj(OBJECT(dev), "gcr", &s->gcr, sizeof(s->gcr), - TYPE_MIPS_GCR); - object_property_set_int(OBJECT(&s->gcr), s->num_vp, "num-vp", &err); - object_property_set_int(OBJECT(&s->gcr), 0x800, "gcr-rev", &err); - object_property_set_int(OBJECT(&s->gcr), gcr_base, "gcr-base", &err); - object_property_set_link(OBJECT(&s->gcr), OBJECT(&s->gic.mr), "gic", &err); - object_property_set_link(OBJECT(&s->gcr), OBJECT(&s->cpc.mr), "cpc", &err); - object_property_set_bool(OBJECT(&s->gcr), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + object_initialize_child(OBJECT(dev), "gcr", &s->gcr, TYPE_MIPS_GCR); + object_property_set_int(OBJECT(&s->gcr), "num-vp", s->num_vp, + &error_abort); + object_property_set_int(OBJECT(&s->gcr), "gcr-rev", 0x800, + &error_abort); + object_property_set_int(OBJECT(&s->gcr), "gcr-base", gcr_base, + &error_abort); + object_property_set_link(OBJECT(&s->gcr), "gic", OBJECT(&s->gic.mr), + &error_abort); + object_property_set_link(OBJECT(&s->gcr), "cpc", OBJECT(&s->cpc.mr), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gcr), errp)) { return; } diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index f583c44b79038bc618fa020bf79cd9f961d82301..a9e0c2f8d30dcdf4a99fede7c063bba3e192663e 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -23,6 +23,7 @@ #include "qemu/units.h" #include "qapi/error.h" #include "cpu.h" +#include "hw/clock.h" #include "hw/intc/i8259.h" #include "hw/dma/i8257.h" #include "hw/isa/superio.h" @@ -107,7 +108,7 @@ static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t *prom_buf, int index, static int64_t load_kernel(CPUMIPSState *env) { - int64_t kernel_entry, kernel_low, kernel_high, initrd_size; + int64_t kernel_entry, kernel_high, initrd_size; int index = 0; long kernel_size; ram_addr_t initrd_offset; @@ -116,9 +117,9 @@ static int64_t load_kernel(CPUMIPSState *env) kernel_size = load_elf(loaderparams.kernel_filename, NULL, cpu_mips_kseg0_to_phys, NULL, - (uint64_t *)&kernel_entry, - (uint64_t *)&kernel_low, (uint64_t *)&kernel_high, - NULL, 0, EM_MIPS, 1, 0); + (uint64_t *)&kernel_entry, NULL, + (uint64_t *)&kernel_high, NULL, + 0, EM_MIPS, 1, 0); if (kernel_size < 0) { error_report("could not load kernel '%s': %s", loaderparams.kernel_filename, @@ -132,8 +133,7 @@ static int64_t load_kernel(CPUMIPSState *env) if (loaderparams.initrd_filename) { initrd_size = get_image_size(loaderparams.initrd_filename); if (initrd_size > 0) { - initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & - INITRD_PAGE_MASK; + initrd_offset = ROUND_UP(kernel_high, INITRD_PAGE_SIZE); if (initrd_offset + initrd_size > ram_size) { error_report("memory too small for initial ram disk '%s'", loaderparams.initrd_filename); @@ -240,10 +240,7 @@ static void vt82c686b_southbridge_init(PCIBus *pci_bus, int slot, qemu_irq intc, PCIDevice *dev; isa_bus = vt82c686b_isa_init(pci_bus, PCI_DEVFN(slot, 0)); - if (!isa_bus) { - fprintf(stderr, "vt82c686b_init error\n"); - exit(1); - } + assert(isa_bus); *p_isa_bus = isa_bus; /* Interrupt controller */ /* The 8259 -> IP5 */ @@ -297,15 +294,20 @@ static void mips_fuloong2e_init(MachineState *machine) long bios_size; uint8_t *spd_data; int64_t kernel_entry; + PCIDevice *pci_dev; PCIBus *pci_bus; ISABus *isa_bus; I2CBus *smbus; + Clock *cpuclk; MIPSCPU *cpu; CPUMIPSState *env; DeviceState *dev; + cpuclk = clock_new(OBJECT(machine), "cpu-refclk"); + clock_set_hz(cpuclk, 533080000); /* ~533 MHz */ + /* init CPUs */ - cpu = MIPS_CPU(cpu_create(machine->cpu_type)); + cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk); env = &cpu->env; qemu_register_reset(main_cpu_reset, cpu); @@ -335,10 +337,8 @@ static void mips_fuloong2e_init(MachineState *machine) kernel_entry = load_kernel(env); write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry); } else { - if (bios_name == NULL) { - bios_name = FULOONG_BIOSNAME; - } - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, + bios_name ?: FULOONG_BIOSNAME); if (filename) { bios_size = load_image_targphys(filename, 0x1fc00000LL, BIOS_SIZE); @@ -348,7 +348,7 @@ static void mips_fuloong2e_init(MachineState *machine) } if ((bios_size < 0 || bios_size > BIOS_SIZE) && - !kernel_filename && !qtest_enabled()) { + bios_name && !qtest_enabled()) { error_report("Could not load MIPS bios '%s'", bios_name); exit(1); } @@ -367,10 +367,11 @@ static void mips_fuloong2e_init(MachineState *machine) /* GPU */ if (vga_interface_type != VGA_NONE) { - dev = DEVICE(pci_create(pci_bus, -1, "ati-vga")); + pci_dev = pci_new(-1, "ati-vga"); + dev = DEVICE(pci_dev); qdev_prop_set_uint32(dev, "vgamem_mb", 16); qdev_prop_set_uint16(dev, "x-device-id", 0x5159); - qdev_init_nofail(dev); + pci_realize_and_unref(pci_dev, pci_bus, &error_fatal); } /* Populate SPD eeprom data */ @@ -392,6 +393,7 @@ static void mips_fuloong2e_machine_init(MachineClass *mc) mc->default_cpu_type = MIPS_CPU_TYPE_NAME("Loongson-2E"); mc->default_ram_size = 256 * MiB; mc->default_ram_id = "fuloong2e.ram"; + mc->minimum_page_bits = 14; } DEFINE_MACHINE("fuloong2e", mips_fuloong2e_machine_init) diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c index b2ea13f09da1c0375b01f6d4270904c0c63efc93..e091bc4ed55fbba6caf9be04c6ba78ee2d8306ea 100644 --- a/hw/mips/gt64xxx_pci.c +++ b/hw/mips/gt64xxx_pci.c @@ -23,6 +23,7 @@ */ #include "qemu/osdep.h" +#include "qapi/error.h" #include "qemu/units.h" #include "qemu/log.h" #include "hw/mips/mips.h" @@ -34,6 +35,7 @@ #include "hw/irq.h" #include "exec/address-spaces.h" #include "trace.h" +#include "qom/object.h" #define GT_REGS (0x1000 >> 2) @@ -229,10 +231,9 @@ #define TYPE_GT64120_PCI_HOST_BRIDGE "gt64120" -#define GT64120_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(GT64120State, (obj), TYPE_GT64120_PCI_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(GT64120State, GT64120_PCI_HOST_BRIDGE) -typedef struct GT64120State { +struct GT64120State { PCIHostState parent_obj; uint32_t regs[GT_REGS]; @@ -242,7 +243,7 @@ typedef struct GT64120State { PCI_MAPPING_ENTRY(ISD); MemoryRegion pci0_mem; AddressSpace pci0_mem_as; -} GT64120State; +}; /* Adjust range to avoid touching space which isn't mappable via PCI */ /* @@ -1201,7 +1202,7 @@ PCIBus *gt64120_register(qemu_irq *pic) PCIHostState *phb; DeviceState *dev; - dev = qdev_create(NULL, TYPE_GT64120_PCI_HOST_BRIDGE); + dev = qdev_new(TYPE_GT64120_PCI_HOST_BRIDGE); d = GT64120_PCI_HOST_BRIDGE(dev); phb = PCI_HOST_BRIDGE(dev); memory_region_init(&d->pci0_mem, OBJECT(dev), "pci0-mem", 4 * GiB); @@ -1212,7 +1213,7 @@ PCIBus *gt64120_register(qemu_irq *pic) &d->pci0_mem, get_system_io(), PCI_DEVFN(18, 0), 4, TYPE_PCI_BUS); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); memory_region_init_io(&d->ISD_mem, OBJECT(dev), &isd_mem_ops, d, "isd-mem", 0x1000); diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c index afea52b41b0580c3ed44de4dde96bbd8766a0a73..71448f72ac97dad7b7b859fe3fc7be6d4905d33b 100644 --- a/hw/mips/jazz.c +++ b/hw/mips/jazz.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "hw/clock.h" #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" #include "hw/intc/i8259.h" @@ -142,6 +143,7 @@ static void mips_jazz_init(MachineState *machine, MemoryRegion *address_space = get_system_memory(); char *filename; int bios_size, n; + Clock *cpuclk; MIPSCPU *cpu; CPUClass *cc; CPUMIPSState *env; @@ -163,14 +165,25 @@ static void mips_jazz_init(MachineState *machine, MemoryRegion *bios2 = g_new(MemoryRegion, 1); SysBusESPState *sysbus_esp; ESPState *esp; + static const struct { + unsigned freq_hz; + unsigned pll_mult; + } ext_clk[] = { + [JAZZ_MAGNUM] = {50000000, 2}, + [JAZZ_PICA61] = {33333333, 4}, + }; if (machine->ram_size > 256 * MiB) { error_report("RAM size more than 256Mb is not supported"); exit(EXIT_FAILURE); } + cpuclk = clock_new(OBJECT(machine), "cpu-refclk"); + clock_set_hz(cpuclk, ext_clk[jazz_model].freq_hz + * ext_clk[jazz_model].pll_mult); + /* init CPUs */ - cpu = MIPS_CPU(cpu_create(machine->cpu_type)); + cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk); env = &cpu->env; qemu_register_reset(main_cpu_reset, cpu); @@ -205,10 +218,7 @@ static void mips_jazz_init(MachineState *machine, memory_region_add_subregion(address_space, 0xfff00000LL, bios2); /* load the BIOS image. */ - if (bios_name == NULL) { - bios_name = BIOS_FILENAME; - } - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name ?: BIOS_FILENAME); if (filename) { bios_size = load_image_targphys(filename, 0xfff00000LL, MAGNUM_BIOS_SIZE); @@ -216,7 +226,8 @@ static void mips_jazz_init(MachineState *machine, } else { bios_size = -1; } - if ((bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) && !qtest_enabled()) { + if ((bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) + && bios_name && !qtest_enabled()) { error_report("Could not load MIPS bios '%s'", bios_name); exit(1); } @@ -250,14 +261,14 @@ static void mips_jazz_init(MachineState *machine, isa_bus_irqs(isa_bus, i8259); i8257_dma_init(isa_bus, 0); pit = i8254_pit_init(isa_bus, 0x40, 0, NULL); - pcspk_init(isa_bus, pit); + pcspk_init(isa_new(TYPE_PC_SPEAKER), isa_bus, pit); /* Video card */ switch (jazz_model) { case JAZZ_MAGNUM: - dev = qdev_create(NULL, "sysbus-g364"); - qdev_init_nofail(dev); + dev = qdev_new("sysbus-g364"); sysbus = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sysbus, &error_fatal); sysbus_mmio_map(sysbus, 0, 0x60080000); sysbus_mmio_map(sysbus, 1, 0x40000000); sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(rc4030, 3)); @@ -287,13 +298,13 @@ static void mips_jazz_init(MachineState *machine, if (strcmp(nd->model, "dp83932") == 0) { qemu_check_nic_model(nd, "dp83932"); - dev = qdev_create(NULL, "dp8393x"); + dev = qdev_new("dp8393x"); qdev_set_nic_properties(dev, nd); qdev_prop_set_uint8(dev, "it_shift", 2); - object_property_set_link(OBJECT(dev), OBJECT(rc4030_dma_mr), - "dma_mr", &error_abort); - qdev_init_nofail(dev); + object_property_set_link(OBJECT(dev), "dma_mr", + OBJECT(rc4030_dma_mr), &error_abort); sysbus = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sysbus, &error_fatal); sysbus_mmio_map(sysbus, 0, 0x80001000); sysbus_mmio_map(sysbus, 1, 0x8000b000); sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(rc4030, 4)); @@ -308,8 +319,8 @@ static void mips_jazz_init(MachineState *machine, } /* SCSI adapter */ - dev = qdev_create(NULL, TYPE_ESP); - sysbus_esp = ESP_STATE(dev); + dev = qdev_new(TYPE_ESP); + sysbus_esp = ESP(dev); esp = &sysbus_esp->esp; esp->dma_memory_read = rc4030_dma_read; esp->dma_memory_write = rc4030_dma_write; @@ -317,9 +328,9 @@ static void mips_jazz_init(MachineState *machine, sysbus_esp->it_shift = 0; /* XXX for now until rc4030 has been changed to use DMA enable signal */ esp->dma_enabled = 1; - qdev_init_nofail(dev); sysbus = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sysbus, &error_fatal); sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(rc4030, 5)); sysbus_mmio_map(sysbus, 0, 0x80002000); @@ -362,9 +373,9 @@ static void mips_jazz_init(MachineState *machine, /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */ /* NVRAM */ - dev = qdev_create(NULL, "ds1225y"); - qdev_init_nofail(dev); + dev = qdev_new("ds1225y"); sysbus = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sysbus, &error_fatal); sysbus_mmio_map(sysbus, 0, 0x80009000); /* LED indicator */ diff --git a/hw/mips/malta.c b/hw/mips/malta.c index b673a3a2489ad07b0294e18057f01bbcab2e7ea1..9d1a3b50b7a82d00577fd931c942ca49d6d2902c 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -26,6 +26,7 @@ #include "qemu/units.h" #include "qemu-common.h" #include "cpu.h" +#include "hw/clock.h" #include "hw/southbridge/piix.h" #include "hw/isa/superio.h" #include "hw/char/serial.h" @@ -45,6 +46,7 @@ #include "hw/loader.h" #include "elf.h" #include "exec/address-spaces.h" +#include "qom/object.h" #include "hw/sysbus.h" /* SysBusDevice */ #include "qemu/host-utils.h" #include "sysemu/qtest.h" @@ -52,10 +54,11 @@ #include "sysemu/runstate.h" #include "qapi/error.h" #include "qemu/error-report.h" -#include "hw/empty_slot.h" +#include "hw/misc/empty_slot.h" #include "sysemu/kvm.h" #include "hw/semihosting/semihost.h" #include "hw/mips/cps.h" +#include "hw/qdev-clock.h" #define ENVP_ADDR 0x80002000l #define ENVP_NB_ENTRIES 16 @@ -88,14 +91,15 @@ typedef struct { } MaltaFPGAState; #define TYPE_MIPS_MALTA "mips-malta" -#define MIPS_MALTA(obj) OBJECT_CHECK(MaltaState, (obj), TYPE_MIPS_MALTA) +OBJECT_DECLARE_SIMPLE_TYPE(MaltaState, MIPS_MALTA) -typedef struct { +struct MaltaState { SysBusDevice parent_obj; + Clock *cpuclk; MIPSCPSState cps; qemu_irq i8259[ISA_NUM_IRQS]; -} MaltaState; +}; static struct _loaderparams { int ram_size, ram_low_size; @@ -574,7 +578,7 @@ static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space, memory_region_init_alias(&s->iomem_lo, NULL, "malta-fpga", &s->iomem, 0, 0x900); memory_region_init_alias(&s->iomem_hi, NULL, "malta-fpga", - &s->iomem, 0xa00, 0x10000 - 0xa00); + &s->iomem, 0xa00, 0x100000 - 0xa00); memory_region_add_subregion(address_space, base, &s->iomem_lo); memory_region_add_subregion(address_space, base + 0xa00, &s->iomem_hi); @@ -1073,9 +1077,9 @@ static int64_t load_kernel(void) * the initrd. It takes at most 128kiB for 2GB RAM and 4kiB * pages. */ - initrd_offset = (loaderparams.ram_low_size - initrd_size - - (128 * KiB) - - ~INITRD_PAGE_MASK) & INITRD_PAGE_MASK; + initrd_offset = ROUND_UP(loaderparams.ram_low_size + - (initrd_size + 128 * KiB), + INITRD_PAGE_SIZE); if (kernel_high >= initrd_offset) { error_report("memory too small for initial ram disk '%s'", loaderparams.initrd_filename); @@ -1158,7 +1162,7 @@ static void main_cpu_reset(void *opaque) } } -static void create_cpu_without_cps(MachineState *ms, +static void create_cpu_without_cps(MachineState *ms, MaltaState *s, qemu_irq *cbus_irq, qemu_irq *i8259_irq) { CPUMIPSState *env; @@ -1166,7 +1170,7 @@ static void create_cpu_without_cps(MachineState *ms, int i; for (i = 0; i < ms->smp.cpus; i++) { - cpu = MIPS_CPU(cpu_create(ms->cpu_type)); + cpu = mips_cpu_create_with_clock(ms->cpu_type, s->cpuclk); /* Init internal devices */ cpu_mips_irq_init_cpu(cpu); @@ -1183,17 +1187,13 @@ static void create_cpu_without_cps(MachineState *ms, static void create_cps(MachineState *ms, MaltaState *s, qemu_irq *cbus_irq, qemu_irq *i8259_irq) { - Error *err = NULL; - - sysbus_init_child_obj(OBJECT(s), "cps", OBJECT(&s->cps), sizeof(s->cps), - TYPE_MIPS_CPS); - object_property_set_str(OBJECT(&s->cps), ms->cpu_type, "cpu-type", &err); - object_property_set_int(OBJECT(&s->cps), ms->smp.cpus, "num-vp", &err); - object_property_set_bool(OBJECT(&s->cps), true, "realized", &err); - if (err != NULL) { - error_report("%s", error_get_pretty(err)); - exit(1); - } + object_initialize_child(OBJECT(s), "cps", &s->cps, TYPE_MIPS_CPS); + object_property_set_str(OBJECT(&s->cps), "cpu-type", ms->cpu_type, + &error_fatal); + object_property_set_int(OBJECT(&s->cps), "num-vp", ms->smp.cpus, + &error_fatal); + qdev_connect_clock_in(DEVICE(&s->cps), "clk-in", s->cpuclk); + sysbus_realize(SYS_BUS_DEVICE(&s->cps), &error_fatal); sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->cps), 0, 0, 1); @@ -1207,7 +1207,7 @@ static void mips_create_cpu(MachineState *ms, MaltaState *s, if ((ms->smp.cpus > 1) && cpu_supports_cps_smp(ms->cpu_type)) { create_cps(ms, s, cbus_irq, i8259_irq); } else { - create_cpu_without_cps(ms, cbus_irq, i8259_irq); + create_cpu_without_cps(ms, s, cbus_irq, i8259_irq); } } @@ -1235,18 +1235,11 @@ void mips_malta_init(MachineState *machine) DriveInfo *dinfo; int fl_idx = 0; int be; + MaltaState *s; + DeviceState *dev; - DeviceState *dev = qdev_create(NULL, TYPE_MIPS_MALTA); - MaltaState *s = MIPS_MALTA(dev); - - /* - * The whole address space decoded by the GT-64120A doesn't generate - * exception when accessing invalid memory. Create an empty slot to - * emulate this feature. - */ - empty_slot_init(0, 0x20000000); - - qdev_init_nofail(dev); + s = MIPS_MALTA(qdev_new(TYPE_MIPS_MALTA)); + sysbus_realize_and_unref(SYS_BUS_DEVICE(s), &error_fatal); /* create CPU */ mips_create_cpu(machine, s, &cbus_irq, &i8259_irq); @@ -1339,10 +1332,8 @@ void mips_malta_init(MachineState *machine) /* Load firmware from flash. */ if (!dinfo) { /* Load a BIOS image. */ - if (bios_name == NULL) { - bios_name = BIOS_FILENAME; - } - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, + bios_name ?: BIOS_FILENAME); if (filename) { bios_size = load_image_targphys(filename, FLASH_ADDRESS, BIOS_SIZE); @@ -1351,9 +1342,8 @@ void mips_malta_init(MachineState *machine) bios_size = -1; } if ((bios_size < 0 || bios_size > BIOS_SIZE) && - !kernel_filename && !qtest_enabled()) { - error_report("Could not load MIPS bios '%s', and no " - "-kernel argument was specified", bios_name); + bios_name && !qtest_enabled()) { + error_report("Could not load MIPS bios '%s'", bios_name); exit(1); } } @@ -1399,6 +1389,12 @@ void mips_malta_init(MachineState *machine) /* Northbridge */ pci_bus = gt64120_register(s->i8259); + /* + * The whole address space decoded by the GT-64120A doesn't generate + * exception when accessing invalid memory. Create an empty slot to + * emulate this feature. + */ + empty_slot_init("GT64120", 0, 0x20000000); /* Southbridge */ dev = piix4_create(pci_bus, &isa_bus, &smbus); @@ -1425,10 +1421,19 @@ void mips_malta_init(MachineState *machine) pci_vga_init(pci_bus); } +static void mips_malta_instance_init(Object *obj) +{ + MaltaState *s = MIPS_MALTA(obj); + + s->cpuclk = qdev_init_clock_out(DEVICE(obj), "cpu-refclk"); + clock_set_hz(s->cpuclk, 320000000); /* 320 MHz */ +} + static const TypeInfo mips_malta_device = { .name = TYPE_MIPS_MALTA, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(MaltaState), + .instance_init = mips_malta_instance_init, }; static void mips_malta_machine_init(MachineClass *mc) diff --git a/hw/mips/meson.build b/hw/mips/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..bcdf96be69f1d35c9a37b6196f819e414b698822 --- /dev/null +++ b/hw/mips/meson.build @@ -0,0 +1,10 @@ +mips_ss = ss.source_set() +mips_ss.add(files('addr.c', 'mips_int.c')) +mips_ss.add(when: 'CONFIG_FULOONG', if_true: files('fuloong2e.c')) +mips_ss.add(when: 'CONFIG_JAZZ', if_true: files('jazz.c')) +mips_ss.add(when: 'CONFIG_MALTA', if_true: files('gt64xxx_pci.c', 'malta.c')) +mips_ss.add(when: 'CONFIG_MIPSSIM', if_true: files('mipssim.c')) +mips_ss.add(when: 'CONFIG_MIPS_BOSTON', if_true: [files('boston.c'), fdt]) +mips_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('cps.c')) + +hw_arch += {'mips': mips_ss} diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c index 4a1bf846da8df4bbc6753f6b93bb13c7abd0b363..0f9c6f07c1c700754a4f511ae3252531d9141638 100644 --- a/hw/mips/mips_int.c +++ b/hw/mips/mips_int.c @@ -51,7 +51,7 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level) env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP)); } - if (kvm_enabled() && irq == 2) { + if (kvm_enabled() && (irq == 2 || irq == 3)) { kvm_mips_set_interrupt(cpu, irq, level); } diff --git a/hw/mips/mipssim.c b/hw/mips/mipssim.c index d220318939e28d624d6d3939c4f8dbcd2f614d9b..aaa62a0f4b704ecbea41bdafd9ae8ecdfb57ced1 100644 --- a/hw/mips/mipssim.c +++ b/hw/mips/mipssim.c @@ -29,6 +29,7 @@ #include "qapi/error.h" #include "qemu-common.h" #include "cpu.h" +#include "hw/clock.h" #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" #include "hw/char/serial.h" @@ -76,11 +77,7 @@ static int64_t load_kernel(void) (uint64_t *)&entry, NULL, (uint64_t *)&kernel_high, NULL, big_endian, EM_MIPS, 1, 0); - if (kernel_size >= 0) { - if ((entry & ~0x7fffffffULL) == 0x80000000) { - entry = (int32_t)entry; - } - } else { + if (kernel_size < 0) { error_report("could not load kernel '%s': %s", loaderparams.kernel_filename, load_elf_strerror(kernel_size)); @@ -93,8 +90,7 @@ static int64_t load_kernel(void) if (loaderparams.initrd_filename) { initrd_size = get_image_size(loaderparams.initrd_filename); if (initrd_size > 0) { - initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & - INITRD_PAGE_MASK; + initrd_offset = ROUND_UP(kernel_high, INITRD_PAGE_SIZE); if (initrd_offset + initrd_size > loaderparams.ram_size) { error_report("memory too small for initial ram disk '%s'", loaderparams.initrd_filename); @@ -129,11 +125,11 @@ static void mipsnet_init(int base, qemu_irq irq, NICInfo *nd) DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, "mipsnet"); + dev = qdev_new("mipsnet"); qdev_set_nic_properties(dev, nd); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_connect_irq(s, 0, irq); memory_region_add_subregion(get_system_io(), base, @@ -150,13 +146,21 @@ mips_mipssim_init(MachineState *machine) MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *isa = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); + Clock *cpuclk; MIPSCPU *cpu; CPUMIPSState *env; ResetData *reset_info; int bios_size; + cpuclk = clock_new(OBJECT(machine), "cpu-refclk"); +#ifdef TARGET_MIPS64 + clock_set_hz(cpuclk, 6000000); /* 6 MHz */ +#else + clock_set_hz(cpuclk, 12000000); /* 12 MHz */ +#endif + /* Init CPUs. */ - cpu = MIPS_CPU(cpu_create(machine->cpu_type)); + cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk); env = &cpu->env; reset_info = g_malloc0(sizeof(ResetData)); @@ -173,10 +177,7 @@ mips_mipssim_init(MachineState *machine) /* Map the BIOS / boot exception handler. */ memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios); /* Load a BIOS / boot exception handler image. */ - if (bios_name == NULL) { - bios_name = BIOS_FILENAME; - } - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name ?: BIOS_FILENAME); if (filename) { bios_size = load_image_targphys(filename, 0x1fc00000LL, BIOS_SIZE); g_free(filename); @@ -184,10 +185,9 @@ mips_mipssim_init(MachineState *machine) bios_size = -1; } if ((bios_size < 0 || bios_size > BIOS_SIZE) && - !kernel_filename && !qtest_enabled()) { + bios_name && !qtest_enabled()) { /* Bail out if we have neither a kernel image nor boot vector code. */ - error_report("Could not load MIPS bios '%s', and no " - "-kernel argument was specified", bios_name); + error_report("Could not load MIPS bios '%s'", bios_name); exit(1); } else { /* We have a boot vector start address. */ @@ -216,11 +216,12 @@ mips_mipssim_init(MachineState *machine) * MIPS CPU INT2, which is interrupt 4. */ if (serial_hd(0)) { - DeviceState *dev = qdev_create(NULL, TYPE_SERIAL_IO); + DeviceState *dev = qdev_new(TYPE_SERIAL_MM); qdev_prop_set_chr(dev, "chardev", serial_hd(0)); - qdev_set_legacy_instance_id(dev, 0x3f8, 2); - qdev_init_nofail(dev); + qdev_prop_set_uint8(dev, "regshift", 0); + qdev_prop_set_uint8(dev, "endianness", DEVICE_LITTLE_ENDIAN); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, env->irq[4]); sysbus_add_io(SYS_BUS_DEVICE(dev), 0x3f8, sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0)); diff --git a/hw/mips/r4k.c b/hw/mips/r4k.c deleted file mode 100644 index 3487013a4a15061a56e1ba3e7a5462d026a5f019..0000000000000000000000000000000000000000 --- a/hw/mips/r4k.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * QEMU/MIPS pseudo-board - * - * emulates a simple machine with ISA-like bus. - * ISA IO space mapped to the 0x14000000 (PHYS) and - * ISA memory at the 0x10000000 (PHYS, 16Mb in size). - * All peripherial devices are attached to this "bus" with - * the standard PC ISA addresses. - */ - -#include "qemu/osdep.h" -#include "qemu/units.h" -#include "qapi/error.h" -#include "qemu-common.h" -#include "cpu.h" -#include "hw/mips/mips.h" -#include "hw/mips/cpudevs.h" -#include "hw/intc/i8259.h" -#include "hw/char/serial.h" -#include "hw/isa/isa.h" -#include "net/net.h" -#include "hw/net/ne2000-isa.h" -#include "sysemu/sysemu.h" -#include "hw/boards.h" -#include "hw/block/flash.h" -#include "qemu/log.h" -#include "hw/mips/bios.h" -#include "hw/ide.h" -#include "hw/ide/internal.h" -#include "hw/loader.h" -#include "elf.h" -#include "hw/rtc/mc146818rtc.h" -#include "hw/input/i8042.h" -#include "hw/timer/i8254.h" -#include "exec/address-spaces.h" -#include "sysemu/qtest.h" -#include "sysemu/reset.h" -#include "sysemu/runstate.h" -#include "qemu/error-report.h" - -#define MAX_IDE_BUS 2 - -static const int ide_iobase[2] = { 0x1f0, 0x170 }; -static const int ide_iobase2[2] = { 0x3f6, 0x376 }; -static const int ide_irq[2] = { 14, 15 }; - -static ISADevice *pit; /* PIT i8254 */ - -/* i8254 PIT is attached to the IRQ0 at PIC i8259 */ - -static struct _loaderparams { - int ram_size; - const char *kernel_filename; - const char *kernel_cmdline; - const char *initrd_filename; -} loaderparams; - -static void mips_qemu_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - if ((addr & 0xffff) == 0 && val == 42) { - qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); - } else if ((addr & 0xffff) == 4 && val == 42) { - qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); - } -} - -static uint64_t mips_qemu_read(void *opaque, hwaddr addr, - unsigned size) -{ - return 0; -} - -static const MemoryRegionOps mips_qemu_ops = { - .read = mips_qemu_read, - .write = mips_qemu_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -typedef struct ResetData { - MIPSCPU *cpu; - uint64_t vector; -} ResetData; - -static int64_t load_kernel(void) -{ - const size_t params_size = 264; - int64_t entry, kernel_high, initrd_size; - long kernel_size; - ram_addr_t initrd_offset; - uint32_t *params_buf; - int big_endian; - -#ifdef TARGET_WORDS_BIGENDIAN - big_endian = 1; -#else - big_endian = 0; -#endif - kernel_size = load_elf(loaderparams.kernel_filename, NULL, - cpu_mips_kseg0_to_phys, NULL, - (uint64_t *)&entry, NULL, - (uint64_t *)&kernel_high, NULL, big_endian, - EM_MIPS, 1, 0); - if (kernel_size >= 0) { - if ((entry & ~0x7fffffffULL) == 0x80000000) { - entry = (int32_t)entry; - } - } else { - error_report("could not load kernel '%s': %s", - loaderparams.kernel_filename, - load_elf_strerror(kernel_size)); - exit(1); - } - - /* load initrd */ - initrd_size = 0; - initrd_offset = 0; - if (loaderparams.initrd_filename) { - initrd_size = get_image_size(loaderparams.initrd_filename); - if (initrd_size > 0) { - initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & - INITRD_PAGE_MASK; - if (initrd_offset + initrd_size > ram_size) { - error_report("memory too small for initial ram disk '%s'", - loaderparams.initrd_filename); - exit(1); - } - initrd_size = load_image_targphys(loaderparams.initrd_filename, - initrd_offset, - ram_size - initrd_offset); - } - if (initrd_size == (target_ulong) -1) { - error_report("could not load initial ram disk '%s'", - loaderparams.initrd_filename); - exit(1); - } - } - - /* Store command line. */ - params_buf = g_malloc(params_size); - - params_buf[0] = tswap32(ram_size); - params_buf[1] = tswap32(0x12345678); - - if (initrd_size > 0) { - snprintf((char *)params_buf + 8, 256, - "rd_start=0x%" PRIx64 " rd_size=%" PRId64 " %s", - cpu_mips_phys_to_kseg0(NULL, initrd_offset), - initrd_size, loaderparams.kernel_cmdline); - } else { - snprintf((char *)params_buf + 8, 256, - "%s", loaderparams.kernel_cmdline); - } - - rom_add_blob_fixed("params", params_buf, params_size, - 16 * MiB - params_size); - - g_free(params_buf); - return entry; -} - -static void main_cpu_reset(void *opaque) -{ - ResetData *s = (ResetData *)opaque; - CPUMIPSState *env = &s->cpu->env; - - cpu_reset(CPU(s->cpu)); - env->active_tc.PC = s->vector; -} - -static const int sector_len = 32 * KiB; -static -void mips_r4k_init(MachineState *machine) -{ - const char *kernel_filename = machine->kernel_filename; - const char *kernel_cmdline = machine->kernel_cmdline; - const char *initrd_filename = machine->initrd_filename; - char *filename; - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *bios; - MemoryRegion *iomem = g_new(MemoryRegion, 1); - MemoryRegion *isa_io = g_new(MemoryRegion, 1); - MemoryRegion *isa_mem = g_new(MemoryRegion, 1); - int bios_size; - MIPSCPU *cpu; - CPUMIPSState *env; - ResetData *reset_info; - int i; - qemu_irq *i8259; - ISABus *isa_bus; - DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; - DriveInfo *dinfo; - int be; - - /* init CPUs */ - cpu = MIPS_CPU(cpu_create(machine->cpu_type)); - env = &cpu->env; - - reset_info = g_malloc0(sizeof(ResetData)); - reset_info->cpu = cpu; - reset_info->vector = env->active_tc.PC; - qemu_register_reset(main_cpu_reset, reset_info); - - /* allocate RAM */ - if (machine->ram_size > 256 * MiB) { - error_report("Too much memory for this machine: %" PRId64 "MB," - " maximum 256MB", ram_size / MiB); - exit(1); - } - memory_region_add_subregion(address_space_mem, 0, machine->ram); - - memory_region_init_io(iomem, NULL, &mips_qemu_ops, - NULL, "mips-qemu", 0x10000); - - memory_region_add_subregion(address_space_mem, 0x1fbf0000, iomem); - - /* - * Try to load a BIOS image. If this fails, we continue regardless, - * but initialize the hardware ourselves. When a kernel gets - * preloaded we also initialize the hardware, since the BIOS wasn't - * run. - */ - - if (bios_name == NULL) { - bios_name = BIOS_FILENAME; - } - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - if (filename) { - bios_size = get_image_size(filename); - } else { - bios_size = -1; - } -#ifdef TARGET_WORDS_BIGENDIAN - be = 1; -#else - be = 0; -#endif - dinfo = drive_get(IF_PFLASH, 0, 0); - if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) { - bios = g_new(MemoryRegion, 1); - memory_region_init_rom(bios, NULL, "mips_r4k.bios", BIOS_SIZE, - &error_fatal); - memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios); - - load_image_targphys(filename, 0x1fc00000, BIOS_SIZE); - } else if (dinfo != NULL) { - uint32_t mips_rom = 0x00400000; - if (!pflash_cfi01_register(0x1fc00000, "mips_r4k.bios", mips_rom, - blk_by_legacy_dinfo(dinfo), - sector_len, 4, 0, 0, 0, 0, be)) { - fprintf(stderr, "qemu: Error registering flash memory.\n"); - } - } else if (!qtest_enabled()) { - /* not fatal */ - warn_report("could not load MIPS bios '%s'", bios_name); - } - g_free(filename); - - if (kernel_filename) { - loaderparams.ram_size = machine->ram_size; - loaderparams.kernel_filename = kernel_filename; - loaderparams.kernel_cmdline = kernel_cmdline; - loaderparams.initrd_filename = initrd_filename; - reset_info->vector = load_kernel(); - } - - /* Init CPU internal devices */ - cpu_mips_irq_init_cpu(cpu); - cpu_mips_clock_init(cpu); - - /* ISA bus: IO space at 0x14000000, mem space at 0x10000000 */ - memory_region_init_alias(isa_io, NULL, "isa-io", - get_system_io(), 0, 0x00010000); - memory_region_init(isa_mem, NULL, "isa-mem", 0x01000000); - memory_region_add_subregion(get_system_memory(), 0x14000000, isa_io); - memory_region_add_subregion(get_system_memory(), 0x10000000, isa_mem); - isa_bus = isa_bus_new(NULL, isa_mem, get_system_io(), &error_abort); - - /* The PIC is attached to the MIPS CPU INT0 pin */ - i8259 = i8259_init(isa_bus, env->irq[2]); - isa_bus_irqs(isa_bus, i8259); - - mc146818_rtc_init(isa_bus, 2000, NULL); - - pit = i8254_pit_init(isa_bus, 0x40, 0, NULL); - - serial_hds_isa_init(isa_bus, 0, MAX_ISA_SERIAL_PORTS); - - isa_vga_init(isa_bus); - - if (nd_table[0].used) { - isa_ne2000_init(isa_bus, 0x300, 9, &nd_table[0]); - } - - ide_drive_get(hd, ARRAY_SIZE(hd)); - for (i = 0; i < MAX_IDE_BUS; i++) - isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i], - hd[MAX_IDE_DEVS * i], - hd[MAX_IDE_DEVS * i + 1]); - - isa_create_simple(isa_bus, TYPE_I8042); -} - -static void mips_machine_init(MachineClass *mc) -{ - mc->deprecation_reason = "use malta machine type instead"; - mc->desc = "mips r4k platform"; - mc->init = mips_r4k_init; - mc->block_default_type = IF_IDE; -#ifdef TARGET_MIPS64 - mc->default_cpu_type = MIPS_CPU_TYPE_NAME("R4000"); -#else - mc->default_cpu_type = MIPS_CPU_TYPE_NAME("24Kf"); -#endif - mc->default_ram_id = "mips_r4k.ram"; -} - -DEFINE_MACHINE("mips", mips_machine_init) diff --git a/hw/mips/trace-events b/hw/mips/trace-events index 321933283f7005bcbfe9776c143d5561b05b9c5b..915139d981121c2b4d1c5a3a63ce003b0128e063 100644 --- a/hw/mips/trace-events +++ b/hw/mips/trace-events @@ -1,4 +1,4 @@ -# gt64xxx.c +# gt64xxx_pci.c gt64120_read(const char *regname, unsigned size, uint64_t value) "gt64120 read %s size:%u value:0x%08" PRIx64 gt64120_write(const char *regname, unsigned size, uint64_t value) "gt64120 write %s size:%u value:0x%08" PRIx64 gt64120_isd_remap(uint64_t from_length, uint64_t from_addr, uint64_t to_length, uint64_t to_addr) "ISD: 0x%08" PRIx64 "@0x%08" PRIx64 " -> 0x%08" PRIx64 "@0x%08" PRIx64 diff --git a/hw/mips/trace.h b/hw/mips/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..8d1fd7c9e208c0d3d044f2b16d7d3a5f1e9ac552 --- /dev/null +++ b/hw/mips/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_mips.h" diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index bdd77d80205907562b748fbe51584423f2e4b1c8..dc44dc14f6250c6853b83a7f4641c54afb336d6c 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -93,9 +93,11 @@ config MIPS_ITU config MPS2_FPGAIO bool + select LED config MPS2_SCC bool + select LED config TZ_MPC bool @@ -126,9 +128,36 @@ config AUX config UNIMP bool +config LED + bool + config MAC_VIA bool select MOS6522 select ADB +config AVR_POWER + bool + +config MCHP_PFSOC_DMC + bool + +config MCHP_PFSOC_IOSCB + bool + +config MCHP_PFSOC_SYSREG + bool + +config SIFIVE_TEST + bool + +config SIFIVE_E_PRCI + bool + +config SIFIVE_U_OTP + bool + +config SIFIVE_U_PRCI + bool + source macio/Kconfig diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs deleted file mode 100644 index b25181b7113bc338b220e99ca134d49801164144..0000000000000000000000000000000000000000 --- a/hw/misc/Makefile.objs +++ /dev/null @@ -1,91 +0,0 @@ -common-obj-$(CONFIG_APPLESMC) += applesmc.o -common-obj-$(CONFIG_MAX111X) += max111x.o -common-obj-$(CONFIG_TMP105) += tmp105.o -common-obj-$(CONFIG_TMP421) += tmp421.o -common-obj-$(CONFIG_ISA_DEBUG) += debugexit.o -common-obj-$(CONFIG_SGA) += sga.o -common-obj-$(CONFIG_ISA_TESTDEV) += pc-testdev.o -common-obj-$(CONFIG_PCI_TESTDEV) += pci-testdev.o -common-obj-$(CONFIG_EDU) += edu.o -common-obj-$(CONFIG_PCA9552) += pca9552.o - -common-obj-$(CONFIG_UNIMP) += unimp.o -common-obj-$(CONFIG_FW_CFG_DMA) += vmcoreinfo.o - -# ARM devices -common-obj-$(CONFIG_PL310) += arm_l2x0.o -common-obj-$(CONFIG_INTEGRATOR_DEBUG) += arm_integrator_debug.o -common-obj-$(CONFIG_A9SCU) += a9scu.o -common-obj-$(CONFIG_ARM11SCU) += arm11scu.o - -# Mac devices -common-obj-$(CONFIG_MOS6522) += mos6522.o - -# PKUnity SoC devices -common-obj-$(CONFIG_PUV3) += puv3_pm.o - -common-obj-$(CONFIG_MACIO) += macio/ - -common-obj-$(CONFIG_IVSHMEM_DEVICE) += ivshmem.o - -common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-ccu.o -obj-$(CONFIG_ALLWINNER_H3) += allwinner-cpucfg.o -common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-dramc.o -common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-sysctrl.o -common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-sid.o -common-obj-$(CONFIG_REALVIEW) += arm_sysctl.o -common-obj-$(CONFIG_NSERIES) += cbus.o -common-obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o -common-obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o exynos4210_clk.o exynos4210_rng.o -common-obj-$(CONFIG_IMX) += imx_ccm.o -common-obj-$(CONFIG_IMX) += imx31_ccm.o -common-obj-$(CONFIG_IMX) += imx25_ccm.o -common-obj-$(CONFIG_IMX) += imx6_ccm.o -common-obj-$(CONFIG_IMX) += imx6ul_ccm.o -obj-$(CONFIG_IMX) += imx6_src.o -common-obj-$(CONFIG_IMX) += imx7_ccm.o -common-obj-$(CONFIG_IMX) += imx7_snvs.o -common-obj-$(CONFIG_IMX) += imx7_gpr.o -common-obj-$(CONFIG_IMX) += imx_rngc.o -common-obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o -common-obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o -common-obj-$(CONFIG_MAINSTONE) += mst_fpga.o -common-obj-$(CONFIG_OMAP) += omap_clk.o -common-obj-$(CONFIG_OMAP) += omap_gpmc.o -common-obj-$(CONFIG_OMAP) += omap_l4.o -common-obj-$(CONFIG_OMAP) += omap_sdrc.o -common-obj-$(CONFIG_OMAP) += omap_tap.o -common-obj-$(CONFIG_RASPI) += bcm2835_mbox.o -common-obj-$(CONFIG_RASPI) += bcm2835_property.o -common-obj-$(CONFIG_RASPI) += bcm2835_rng.o -common-obj-$(CONFIG_RASPI) += bcm2835_thermal.o -common-obj-$(CONFIG_SLAVIO) += slavio_misc.o -common-obj-$(CONFIG_ZYNQ) += zynq_slcr.o -common-obj-$(CONFIG_ZYNQ) += zynq-xadc.o -common-obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o -common-obj-$(CONFIG_STM32F4XX_SYSCFG) += stm32f4xx_syscfg.o -common-obj-$(CONFIG_STM32F4XX_EXTI) += stm32f4xx_exti.o -obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o -obj-$(CONFIG_MIPS_CPS) += mips_cpc.o -obj-$(CONFIG_MIPS_ITU) += mips_itu.o -common-obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o -common-obj-$(CONFIG_MPS2_SCC) += mps2-scc.o - -common-obj-$(CONFIG_TZ_MPC) += tz-mpc.o -common-obj-$(CONFIG_TZ_MSC) += tz-msc.o -common-obj-$(CONFIG_TZ_PPC) += tz-ppc.o -common-obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o -obj-$(CONFIG_IOTKIT_SYSCTL) += iotkit-sysctl.o -common-obj-$(CONFIG_IOTKIT_SYSINFO) += iotkit-sysinfo.o -common-obj-$(CONFIG_ARMSSE_CPUID) += armsse-cpuid.o -common-obj-$(CONFIG_ARMSSE_MHU) += armsse-mhu.o - -common-obj-$(CONFIG_PVPANIC) += pvpanic.o -common-obj-$(CONFIG_AUX) += auxbus.o -common-obj-$(CONFIG_ASPEED_SOC) += aspeed_xdma.o -common-obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o -common-obj-$(CONFIG_MSF2) += msf2-sysreg.o -common-obj-$(CONFIG_NRF51_SOC) += nrf51_rng.o -obj-$(CONFIG_MAC_VIA) += mac_via.o - -common-obj-$(CONFIG_GRLIB) += grlib_ahb_apb_pnp.o diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c index 324371a1c0085a628c8f34f9fb56e808ffcd8b6f..a375ebc9878deca095e2dc6f88304a1c2d8732bb 100644 --- a/hw/misc/a9scu.c +++ b/hw/misc/a9scu.c @@ -12,8 +12,12 @@ #include "hw/misc/a9scu.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" +#include "qapi/error.h" +#include "qemu/log.h" #include "qemu/module.h" +#define A9_SCU_CPU_MAX 4 + static uint64_t a9_scu_read(void *opaque, hwaddr offset, unsigned size) { @@ -25,12 +29,6 @@ static uint64_t a9_scu_read(void *opaque, hwaddr offset, return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1); case 0x08: /* CPU Power Status */ return s->status; - case 0x09: /* CPU status. */ - return s->status >> 8; - case 0x0a: /* CPU status. */ - return s->status >> 16; - case 0x0b: /* CPU status. */ - return s->status >> 24; case 0x0c: /* Invalidate All Registers In Secure State */ return 0; case 0x40: /* Filtering Start Address Register */ @@ -41,6 +39,8 @@ static uint64_t a9_scu_read(void *opaque, hwaddr offset, case 0x54: /* SCU Non-secure Access Control Register */ /* unimplemented, fall through */ default: + qemu_log_mask(LOG_UNIMP, "%s: Unsupported offset 0x%"HWADDR_PRIx"\n", + __func__, offset); return 0; } } @@ -49,23 +49,6 @@ static void a9_scu_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { A9SCUState *s = (A9SCUState *)opaque; - uint32_t mask; - uint32_t shift; - switch (size) { - case 1: - mask = 0xff; - break; - case 2: - mask = 0xffff; - break; - case 4: - mask = 0xffffffff; - break; - default: - fprintf(stderr, "Invalid size %u in write to a9 scu register %x\n", - size, (unsigned)offset); - return; - } switch (offset) { case 0x00: /* Control */ @@ -74,9 +57,7 @@ static void a9_scu_write(void *opaque, hwaddr offset, case 0x4: /* Configuration: RO */ break; case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */ - shift = (offset - 0x8) * 8; - s->status &= ~(mask << shift); - s->status |= ((value & mask) << shift); + s->status = value; break; case 0x0c: /* Invalidate All Registers In Secure State */ /* no-op as we do not implement caches */ @@ -89,6 +70,9 @@ static void a9_scu_write(void *opaque, hwaddr offset, case 0x54: /* SCU Non-secure Access Control Register */ /* unimplemented, fall through */ default: + qemu_log_mask(LOG_UNIMP, "%s: Unsupported offset 0x%"HWADDR_PRIx + " value 0x%"PRIx64"\n", + __func__, offset, value); break; } } @@ -96,6 +80,14 @@ static void a9_scu_write(void *opaque, hwaddr offset, static const MemoryRegionOps a9_scu_ops = { .read = a9_scu_read, .write = a9_scu_write, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + }, .endianness = DEVICE_NATIVE_ENDIAN, }; @@ -105,12 +97,17 @@ static void a9_scu_reset(DeviceState *dev) s->control = 0; } -static void a9_scu_init(Object *obj) +static void a9_scu_realize(DeviceState *dev, Error **errp) { - A9SCUState *s = A9_SCU(obj); - SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + A9SCUState *s = A9_SCU(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + + if (!s->num_cpu || s->num_cpu > A9_SCU_CPU_MAX) { + error_setg(errp, "Illegal CPU count: %u", s->num_cpu); + return; + } - memory_region_init_io(&s->iomem, obj, &a9_scu_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &a9_scu_ops, s, "a9-scu", 0x100); sysbus_init_mmio(sbd, &s->iomem); } @@ -138,13 +135,13 @@ static void a9_scu_class_init(ObjectClass *klass, void *data) device_class_set_props(dc, a9_scu_properties); dc->vmsd = &vmstate_a9_scu; dc->reset = a9_scu_reset; + dc->realize = a9_scu_realize; } static const TypeInfo a9_scu_info = { .name = TYPE_A9_SCU, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(A9SCUState), - .instance_init = a9_scu_init, .class_init = a9_scu_class_init, }; diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c index 1c4addb20123c4b0c6bdc2faa5815eca25bd7c7c..1b9acaf1d38de119e8a88ae34d0d8d54addff0f1 100644 --- a/hw/misc/applesmc.c +++ b/hw/misc/applesmc.c @@ -9,7 +9,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -36,6 +36,7 @@ #include "ui/console.h" #include "qemu/module.h" #include "qemu/timer.h" +#include "qom/object.h" /* #define DEBUG_SMC */ @@ -89,9 +90,8 @@ struct AppleSMCData { QLIST_ENTRY(AppleSMCData) node; }; -#define APPLE_SMC(obj) OBJECT_CHECK(AppleSMCState, (obj), TYPE_APPLE_SMC) +OBJECT_DECLARE_SIMPLE_TYPE(AppleSMCState, APPLE_SMC) -typedef struct AppleSMCState AppleSMCState; struct AppleSMCState { ISADevice parent_obj; diff --git a/hw/misc/arm_integrator_debug.c b/hw/misc/arm_integrator_debug.c index 3e23201ae673d5988988aa87731e627479ae785f..ec0d4b90d3dda68d85b6f9b419b4dac8796b78e2 100644 --- a/hw/misc/arm_integrator_debug.c +++ b/hw/misc/arm_integrator_debug.c @@ -19,15 +19,15 @@ #include "hw/misc/arm_integrator_debug.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" -#define INTEGRATOR_DEBUG(obj) \ - OBJECT_CHECK(IntegratorDebugState, (obj), TYPE_INTEGRATOR_DEBUG) +OBJECT_DECLARE_SIMPLE_TYPE(IntegratorDebugState, INTEGRATOR_DEBUG) -typedef struct { +struct IntegratorDebugState { SysBusDevice parent_obj; MemoryRegion iomem; -} IntegratorDebugState; +}; static uint64_t intdbg_control_read(void *opaque, hwaddr offset, unsigned size) diff --git a/hw/misc/arm_l2x0.c b/hw/misc/arm_l2x0.c index 2066c97f5f2e0d14c14f95cab8610ae28dfe3294..75c3eb8982f7731d544a74bec9b8bda42bf706ff 100644 --- a/hw/misc/arm_l2x0.c +++ b/hw/misc/arm_l2x0.c @@ -24,14 +24,15 @@ #include "migration/vmstate.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" /* L2C-310 r3p2 */ #define CACHE_ID 0x410000c8 #define TYPE_ARM_L2X0 "l2x0" -#define ARM_L2X0(obj) OBJECT_CHECK(L2x0State, (obj), TYPE_ARM_L2X0) +OBJECT_DECLARE_SIMPLE_TYPE(L2x0State, ARM_L2X0) -typedef struct L2x0State { +struct L2x0State { SysBusDevice parent_obj; MemoryRegion iomem; @@ -42,7 +43,7 @@ typedef struct L2x0State { uint32_t tag_ctrl; uint32_t filter_start; uint32_t filter_end; -} L2x0State; +}; static const VMStateDescription vmstate_l2x0 = { .name = "l2x0", diff --git a/hw/misc/arm_sysctl.c b/hw/misc/arm_sysctl.c index a474bbdd19ef8370157893719ef7c9b2fc2fd26f..42d46938543b7b8838e880cf76590453da21752d 100644 --- a/hw/misc/arm_sysctl.c +++ b/hw/misc/arm_sysctl.c @@ -18,14 +18,14 @@ #include "hw/arm/primecell.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" #define LOCK_VALUE 0xa05f #define TYPE_ARM_SYSCTL "realview_sysctl" -#define ARM_SYSCTL(obj) \ - OBJECT_CHECK(arm_sysctl_state, (obj), TYPE_ARM_SYSCTL) +OBJECT_DECLARE_SIMPLE_TYPE(arm_sysctl_state, ARM_SYSCTL) -typedef struct { +struct arm_sysctl_state { SysBusDevice parent_obj; MemoryRegion iomem; @@ -51,7 +51,7 @@ typedef struct { uint32_t *db_voltage; uint32_t db_num_clocks; uint32_t *db_clock_reset; -} arm_sysctl_state; +}; static const VMStateDescription vmstate_arm_sysctl = { .name = "realview_sysctl", diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c index ec4fef900e27c63bdd6665ec346a822da24a01e2..40a38ebd854977e7273fd9322951628d108b0e6d 100644 --- a/hw/misc/aspeed_scu.c +++ b/hw/misc/aspeed_scu.c @@ -328,9 +328,10 @@ static const MemoryRegionOps aspeed_ast2400_scu_ops = { .read = aspeed_scu_read, .write = aspeed_ast2400_scu_write, .endianness = DEVICE_LITTLE_ENDIAN, - .valid.min_access_size = 4, - .valid.max_access_size = 4, - .valid.unaligned = false, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + }, }; static const MemoryRegionOps aspeed_ast2500_scu_ops = { @@ -655,7 +656,7 @@ static const uint32_t ast2600_a1_resets[ASPEED_AST2600_SCU_NR_REGS] = { [AST2600_SYS_RST_CTRL2] = 0xFFFFFFFC, [AST2600_CLK_STOP_CTRL] = 0xFFFF7F8A, [AST2600_CLK_STOP_CTRL2] = 0xFFF0FFF0, - [AST2600_SDRAM_HANDSHAKE] = 0x00000040, /* SoC completed DRAM init */ + [AST2600_SDRAM_HANDSHAKE] = 0x00000000, [AST2600_HPLL_PARAM] = 0x1000405F, [AST2600_CHIP_ID0] = 0x1234ABCD, [AST2600_CHIP_ID1] = 0x88884444, @@ -669,7 +670,12 @@ static void aspeed_ast2600_scu_reset(DeviceState *dev) memcpy(s->regs, asc->resets, asc->nr_regs * 4); - s->regs[AST2600_SILICON_REV] = s->silicon_rev; + /* + * A0 reports A0 in _REV, but subsequent revisions report A1 regardless + * of actual revision. QEMU and Linux only support A1 onwards so this is + * sufficient. + */ + s->regs[AST2600_SILICON_REV] = AST2600_A1_SILICON_REV; s->regs[AST2600_SILICON_REV2] = s->silicon_rev; s->regs[AST2600_HW_STRAP1] = s->hw_strap1; s->regs[AST2600_HW_STRAP2] = s->hw_strap2; diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c index 25e1e58356035cd8b304998fceb6944563be18b0..08f856cbda7ef61c9cda55f785d298c92680eb14 100644 --- a/hw/misc/aspeed_sdmc.c +++ b/hw/misc/aspeed_sdmc.c @@ -33,15 +33,28 @@ /* Configuration Register */ #define R_CONF (0x04 / 4) +/* Interrupt control/status */ +#define R_ISR (0x50 / 4) + /* Control/Status Register #1 (ast2500) */ #define R_STATUS1 (0x60 / 4) #define PHY_BUSY_STATE BIT(0) #define PHY_PLL_LOCK_STATUS BIT(4) +/* Reserved */ +#define R_MCR6C (0x6c / 4) + #define R_ECC_TEST_CTRL (0x70 / 4) #define ECC_TEST_FINISHED BIT(12) #define ECC_TEST_FAIL BIT(13) +#define R_TEST_START_LEN (0x74 / 4) +#define R_TEST_FAIL_DQ (0x78 / 4) +#define R_TEST_INIT_VAL (0x7c / 4) +#define R_DRAM_SW (0x88 / 4) +#define R_DRAM_TIME (0x8c / 4) +#define R_ECC_ERR_INJECT (0xb4 / 4) + /* * Configuration register Ox4 (for Aspeed AST2400 SOC) * @@ -113,7 +126,7 @@ static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size) if (addr >= ARRAY_SIZE(s->regs)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", - __func__, addr); + __func__, addr * 4); return 0; } @@ -146,57 +159,6 @@ static const MemoryRegionOps aspeed_sdmc_ops = { .valid.max_access_size = 4, }; -static int ast2400_rambits(AspeedSDMCState *s) -{ - switch (s->ram_size >> 20) { - case 64: - return ASPEED_SDMC_DRAM_64MB; - case 128: - return ASPEED_SDMC_DRAM_128MB; - case 256: - return ASPEED_SDMC_DRAM_256MB; - case 512: - return ASPEED_SDMC_DRAM_512MB; - default: - g_assert_not_reached(); - break; - } -} - -static int ast2500_rambits(AspeedSDMCState *s) -{ - switch (s->ram_size >> 20) { - case 128: - return ASPEED_SDMC_AST2500_128MB; - case 256: - return ASPEED_SDMC_AST2500_256MB; - case 512: - return ASPEED_SDMC_AST2500_512MB; - case 1024: - return ASPEED_SDMC_AST2500_1024MB; - default: - g_assert_not_reached(); - break; - } -} - -static int ast2600_rambits(AspeedSDMCState *s) -{ - switch (s->ram_size >> 20) { - case 256: - return ASPEED_SDMC_AST2600_256MB; - case 512: - return ASPEED_SDMC_AST2600_512MB; - case 1024: - return ASPEED_SDMC_AST2600_1024MB; - case 2048: - return ASPEED_SDMC_AST2600_2048MB; - default: - g_assert_not_reached(); - break; - } -} - static void aspeed_sdmc_reset(DeviceState *dev) { AspeedSDMCState *s = ASPEED_SDMC(dev); @@ -206,6 +168,19 @@ static void aspeed_sdmc_reset(DeviceState *dev) /* Set ram size bit and defaults values */ s->regs[R_CONF] = asc->compute_conf(s, 0); + + /* + * PHY status: + * - set phy status ok (set bit 1) + * - initial PVT calibration ok (clear bit 3) + * - runtime calibration ok (clear bit 5) + */ + s->regs[0x100] = BIT(1); + + /* PHY eye window: set all as passing */ + s->regs[0x100 | (0x68 / 4)] = 0xff; + s->regs[0x100 | (0x7c / 4)] = 0xff; + s->regs[0x100 | (0x50 / 4)] = 0xfffffff; } static void aspeed_sdmc_get_ram_size(Object *obj, Visitor *v, const char *name, @@ -223,13 +198,10 @@ static void aspeed_sdmc_set_ram_size(Object *obj, Visitor *v, const char *name, int i; char *sz; int64_t value; - Error *local_err = NULL; AspeedSDMCState *s = ASPEED_SDMC(obj); AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s); - visit_type_int(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_int(v, name, &value, errp)) { return; } @@ -241,9 +213,8 @@ static void aspeed_sdmc_set_ram_size(Object *obj, Visitor *v, const char *name, } sz = size_to_str(value); - error_setg(&local_err, "Invalid RAM size %s", sz); + error_setg(errp, "Invalid RAM size %s", sz); g_free(sz); - error_propagate(errp, local_err); } static void aspeed_sdmc_initfn(Object *obj) @@ -259,6 +230,7 @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp) AspeedSDMCState *s = ASPEED_SDMC(dev); AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s); + assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */ s->max_ram_size = asc->max_ram_size; memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops, s, @@ -301,10 +273,32 @@ static const TypeInfo aspeed_sdmc_info = { .abstract = true, }; +static int aspeed_sdmc_get_ram_bits(AspeedSDMCState *s) +{ + AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s); + int i; + + /* + * The bitfield value encoding the RAM size is the index of the + * possible RAM size array + */ + for (i = 0; asc->valid_ram_sizes[i]; i++) { + if (s->ram_size == asc->valid_ram_sizes[i]) { + return i; + } + } + + /* + * Invalid RAM sizes should have been excluded when setting the + * SoC RAM size. + */ + g_assert_not_reached(); +} + static uint32_t aspeed_2400_sdmc_compute_conf(AspeedSDMCState *s, uint32_t data) { uint32_t fixed_conf = ASPEED_SDMC_VGA_COMPAT | - ASPEED_SDMC_DRAM_SIZE(ast2400_rambits(s)); + ASPEED_SDMC_DRAM_SIZE(aspeed_sdmc_get_ram_bits(s)); /* Make sure readonly bits are kept */ data &= ~ASPEED_SDMC_READONLY_MASK; @@ -345,7 +339,7 @@ static void aspeed_2400_sdmc_class_init(ObjectClass *klass, void *data) AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass); dc->desc = "ASPEED 2400 SDRAM Memory Controller"; - asc->max_ram_size = 512 << 20; + asc->max_ram_size = 512 * MiB; asc->compute_conf = aspeed_2400_sdmc_compute_conf; asc->write = aspeed_2400_sdmc_write; asc->valid_ram_sizes = aspeed_2400_ram_sizes; @@ -362,7 +356,7 @@ static uint32_t aspeed_2500_sdmc_compute_conf(AspeedSDMCState *s, uint32_t data) uint32_t fixed_conf = ASPEED_SDMC_HW_VERSION(1) | ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) | ASPEED_SDMC_CACHE_INITIAL_DONE | - ASPEED_SDMC_DRAM_SIZE(ast2500_rambits(s)); + ASPEED_SDMC_DRAM_SIZE(aspeed_sdmc_get_ram_bits(s)); /* Make sure readonly bits are kept */ data &= ~ASPEED_SDMC_AST2500_READONLY_MASK; @@ -412,7 +406,7 @@ static void aspeed_2500_sdmc_class_init(ObjectClass *klass, void *data) AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass); dc->desc = "ASPEED 2500 SDRAM Memory Controller"; - asc->max_ram_size = 1024 << 20; + asc->max_ram_size = 1 * GiB; asc->compute_conf = aspeed_2500_sdmc_compute_conf; asc->write = aspeed_2500_sdmc_write; asc->valid_ram_sizes = aspeed_2500_ram_sizes; @@ -428,7 +422,7 @@ static uint32_t aspeed_2600_sdmc_compute_conf(AspeedSDMCState *s, uint32_t data) { uint32_t fixed_conf = ASPEED_SDMC_HW_VERSION(3) | ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) | - ASPEED_SDMC_DRAM_SIZE(ast2600_rambits(s)); + ASPEED_SDMC_DRAM_SIZE(aspeed_sdmc_get_ram_bits(s)); /* Make sure readonly bits are kept (use ast2500 mask) */ data &= ~ASPEED_SDMC_AST2500_READONLY_MASK; @@ -439,6 +433,20 @@ static uint32_t aspeed_2600_sdmc_compute_conf(AspeedSDMCState *s, uint32_t data) static void aspeed_2600_sdmc_write(AspeedSDMCState *s, uint32_t reg, uint32_t data) { + /* Unprotected registers */ + switch (reg) { + case R_ISR: + case R_MCR6C: + case R_TEST_START_LEN: + case R_TEST_FAIL_DQ: + case R_TEST_INIT_VAL: + case R_DRAM_SW: + case R_DRAM_TIME: + case R_ECC_ERR_INJECT: + s->regs[reg] = data; + return; + } + if (s->regs[R_PROT] == PROT_HARDLOCKED) { qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked until system reset!\n", __func__); @@ -446,7 +454,9 @@ static void aspeed_2600_sdmc_write(AspeedSDMCState *s, uint32_t reg, } if (reg != R_PROT && s->regs[R_PROT] == PROT_SOFTLOCKED) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", __func__); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: SDMC is locked! (write to MCR%02x blocked)\n", + __func__, reg * 4); return; } @@ -489,7 +499,7 @@ static void aspeed_2600_sdmc_class_init(ObjectClass *klass, void *data) AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass); dc->desc = "ASPEED 2600 SDRAM Memory Controller"; - asc->max_ram_size = 2048 << 20; + asc->max_ram_size = 2 * GiB; asc->compute_conf = aspeed_2600_sdmc_compute_conf; asc->write = aspeed_2600_sdmc_write; asc->valid_ram_sizes = aspeed_2600_ram_sizes; diff --git a/hw/misc/auxbus.c b/hw/misc/auxbus.c index f8e7b979712571cdf66565cf4ba2cea372a35183..6c099ae2a2dd6539a550962203ce7270bba5c0b7 100644 --- a/hw/misc/auxbus.c +++ b/hw/misc/auxbus.c @@ -45,8 +45,6 @@ } \ } while (0) -#define TYPE_AUXTOI2C "aux-to-i2c-bridge" -#define AUXTOI2C(obj) OBJECT_CHECK(AUXTOI2CState, (obj), TYPE_AUXTOI2C) static void aux_slave_dev_print(Monitor *mon, DeviceState *dev, int indent); static inline I2CBus *aux_bridge_get_i2c_bus(AUXTOI2CState *bridge); @@ -62,7 +60,7 @@ static void aux_bus_class_init(ObjectClass *klass, void *data) k->print_dev = aux_slave_dev_print; } -AUXBus *aux_init_bus(DeviceState *parent, const char *name) +AUXBus *aux_bus_init(DeviceState *parent, const char *name) { AUXBus *bus; Object *auxtoi2c; @@ -70,7 +68,6 @@ AUXBus *aux_init_bus(DeviceState *parent, const char *name) bus = AUX_BUS(qbus_create(TYPE_AUX_BUS, parent, name)); auxtoi2c = object_new_with_props(TYPE_AUXTOI2C, OBJECT(bus), "i2c", &error_abort, NULL); - qdev_set_parent_bus(DEVICE(auxtoi2c), BUS(bus)); bus->bridge = AUXTOI2C(auxtoi2c); @@ -81,6 +78,11 @@ AUXBus *aux_init_bus(DeviceState *parent, const char *name) return bus; } +void aux_bus_realize(AUXBus *bus) +{ + qdev_realize(DEVICE(bus->bridge), BUS(bus), &error_fatal); +} + void aux_map_slave(AUXSlave *aux_dev, hwaddr addr) { DeviceState *dev = DEVICE(aux_dev); @@ -196,7 +198,7 @@ AUXReply aux_request(AUXBus *bus, AUXCommand cmd, uint32_t address, } break; default: - DPRINTF("Not implemented!\n"); + qemu_log_mask(LOG_UNIMP, "AUX cmd=%u not implemented\n", cmd); return AUX_NACK; } @@ -225,7 +227,7 @@ static void aux_bridge_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); /* This device is private and is created only once for each - * aux-bus in aux_init_bus(..). So don't allow the user to add one. + * aux-bus in aux_bus_init(..). So don't allow the user to add one. */ dc->user_creatable = false; } @@ -244,7 +246,7 @@ static inline I2CBus *aux_bridge_get_i2c_bus(AUXTOI2CState *bridge) static const TypeInfo aux_to_i2c_type_info = { .name = TYPE_AUXTOI2C, - .parent = TYPE_DEVICE, + .parent = TYPE_AUX_SLAVE, .class_init = aux_bridge_class_init, .instance_size = sizeof(AUXTOI2CState), .instance_init = aux_bridge_init @@ -269,16 +271,6 @@ static void aux_slave_dev_print(Monitor *mon, DeviceState *dev, int indent) memory_region_size(s->mmio)); } -DeviceState *aux_create_slave(AUXBus *bus, const char *type) -{ - DeviceState *dev; - - dev = DEVICE(object_new(type)); - assert(dev); - qdev_set_parent_bus(dev, &bus->qbus); - return dev; -} - void aux_init_mmio(AUXSlave *aux_slave, MemoryRegion *mmio) { assert(!aux_slave->mmio); diff --git a/hw/misc/avr_power.c b/hw/misc/avr_power.c new file mode 100644 index 0000000000000000000000000000000000000000..a5412f2cfe667edd4467950aa868a0c7fa494b33 --- /dev/null +++ b/hw/misc/avr_power.c @@ -0,0 +1,113 @@ +/* + * AVR Power Reduction Management + * + * Copyright (c) 2019-2020 Michael Rolnik + * + * 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/misc/avr_power.h" +#include "qemu/log.h" +#include "hw/qdev-properties.h" +#include "hw/irq.h" +#include "trace.h" + +static void avr_mask_reset(DeviceState *dev) +{ + AVRMaskState *s = AVR_MASK(dev); + + s->val = 0x00; + + for (int i = 0; i < 8; i++) { + qemu_set_irq(s->irq[i], 0); + } +} + +static uint64_t avr_mask_read(void *opaque, hwaddr offset, unsigned size) +{ + assert(size == 1); + assert(offset == 0); + AVRMaskState *s = opaque; + + trace_avr_power_read(s->val); + + return (uint64_t)s->val; +} + +static void avr_mask_write(void *opaque, hwaddr offset, + uint64_t val64, unsigned size) +{ + assert(size == 1); + assert(offset == 0); + AVRMaskState *s = opaque; + uint8_t val8 = val64; + + trace_avr_power_write(val8); + s->val = val8; + for (int i = 0; i < 8; i++) { + qemu_set_irq(s->irq[i], (val8 & (1 << i)) != 0); + } +} + +static const MemoryRegionOps avr_mask_ops = { + .read = avr_mask_read, + .write = avr_mask_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .max_access_size = 1, + }, +}; + +static void avr_mask_init(Object *dev) +{ + AVRMaskState *s = AVR_MASK(dev); + SysBusDevice *busdev = SYS_BUS_DEVICE(dev); + + memory_region_init_io(&s->iomem, dev, &avr_mask_ops, s, TYPE_AVR_MASK, + 0x01); + sysbus_init_mmio(busdev, &s->iomem); + + for (int i = 0; i < 8; i++) { + sysbus_init_irq(busdev, &s->irq[i]); + } + s->val = 0x00; +} + +static void avr_mask_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = avr_mask_reset; +} + +static const TypeInfo avr_mask_info = { + .name = TYPE_AVR_MASK, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AVRMaskState), + .class_init = avr_mask_class_init, + .instance_init = avr_mask_init, +}; + +static void avr_mask_register_types(void) +{ + type_register_static(&avr_mask_info); +} + +type_init(avr_mask_register_types) diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c new file mode 100644 index 0000000000000000000000000000000000000000..7e415a017c904ca2eb2181c904c6945a5220ca86 --- /dev/null +++ b/hw/misc/bcm2835_cprman.c @@ -0,0 +1,808 @@ +/* + * BCM2835 CPRMAN clock manager + * + * Copyright (c) 2020 Luc Michel + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* + * This peripheral is roughly divided into 3 main parts: + * - the PLLs + * - the PLL channels + * - the clock muxes + * + * A main oscillator (xosc) feeds all the PLLs. Each PLLs has one or more + * channels. Those channel are then connected to the clock muxes. Each mux has + * multiples sources (usually the xosc, some of the PLL channels and some "test + * debug" clocks). A mux is configured to select a given source through its + * control register. Each mux has one output clock that also goes out of the + * CPRMAN. This output clock usually connects to another peripheral in the SoC + * (so a given mux is dedicated to a peripheral). + * + * At each level (PLL, channel and mux), the clock can be altered through + * dividers (and multipliers in case of the PLLs), and can be disabled (in this + * case, the next levels see no clock). + * + * This can be sum-up as follows (this is an example and not the actual BCM2835 + * clock tree): + * + * /-->[PLL]-|->[PLL channel]--... [mux]--> to peripherals + * | |->[PLL channel] muxes takes [mux] + * | \->[PLL channel] inputs from [mux] + * | some channels [mux] + * [xosc]---|-->[PLL]-|->[PLL channel] and other srcs [mux] + * | \->[PLL channel] ...-->[mux] + * | [mux] + * \-->[PLL]--->[PLL channel] [mux] + * + * The page at https://elinux.org/The_Undocumented_Pi gives the actual clock + * tree configuration. + * + * The CPRMAN exposes clock outputs with the name of the clock mux suffixed + * with "-out" (e.g. "uart-out", "h264-out", ...). + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" +#include "hw/misc/bcm2835_cprman.h" +#include "hw/misc/bcm2835_cprman_internals.h" +#include "trace.h" + +/* PLL */ + +static void pll_reset(DeviceState *dev) +{ + CprmanPllState *s = CPRMAN_PLL(dev); + const PLLResetInfo *info = &PLL_RESET_INFO[s->id]; + + *s->reg_cm = info->cm; + *s->reg_a2w_ctrl = info->a2w_ctrl; + memcpy(s->reg_a2w_ana, info->a2w_ana, sizeof(info->a2w_ana)); + *s->reg_a2w_frac = info->a2w_frac; +} + +static bool pll_is_locked(const CprmanPllState *pll) +{ + return !FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, PWRDN) + && !FIELD_EX32(*pll->reg_cm, CM_PLLx, ANARST); +} + +static void pll_update(CprmanPllState *pll) +{ + uint64_t freq, ndiv, fdiv, pdiv; + + if (!pll_is_locked(pll)) { + clock_update(pll->out, 0); + return; + } + + pdiv = FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, PDIV); + + if (!pdiv) { + clock_update(pll->out, 0); + return; + } + + ndiv = FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, NDIV); + fdiv = FIELD_EX32(*pll->reg_a2w_frac, A2W_PLLx_FRAC, FRAC); + + if (pll->reg_a2w_ana[1] & pll->prediv_mask) { + /* The prescaler doubles the parent frequency */ + ndiv *= 2; + fdiv *= 2; + } + + /* + * We have a multiplier with an integer part (ndiv) and a fractional part + * (fdiv), and a divider (pdiv). + */ + freq = clock_get_hz(pll->xosc_in) * + ((ndiv << R_A2W_PLLx_FRAC_FRAC_LENGTH) + fdiv); + freq /= pdiv; + freq >>= R_A2W_PLLx_FRAC_FRAC_LENGTH; + + clock_update_hz(pll->out, freq); +} + +static void pll_xosc_update(void *opaque) +{ + pll_update(CPRMAN_PLL(opaque)); +} + +static void pll_init(Object *obj) +{ + CprmanPllState *s = CPRMAN_PLL(obj); + + s->xosc_in = qdev_init_clock_in(DEVICE(s), "xosc-in", pll_xosc_update, s); + s->out = qdev_init_clock_out(DEVICE(s), "out"); +} + +static const VMStateDescription pll_vmstate = { + .name = TYPE_CPRMAN_PLL, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_CLOCK(xosc_in, CprmanPllState), + VMSTATE_END_OF_LIST() + } +}; + +static void pll_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = pll_reset; + dc->vmsd = &pll_vmstate; +} + +static const TypeInfo cprman_pll_info = { + .name = TYPE_CPRMAN_PLL, + .parent = TYPE_DEVICE, + .instance_size = sizeof(CprmanPllState), + .class_init = pll_class_init, + .instance_init = pll_init, +}; + + +/* PLL channel */ + +static void pll_channel_reset(DeviceState *dev) +{ + CprmanPllChannelState *s = CPRMAN_PLL_CHANNEL(dev); + const PLLChannelResetInfo *info = &PLL_CHANNEL_RESET_INFO[s->id]; + + *s->reg_a2w_ctrl = info->a2w_ctrl; +} + +static bool pll_channel_is_enabled(CprmanPllChannelState *channel) +{ + /* + * XXX I'm not sure of the purpose of the LOAD field. The Linux driver does + * not set it when enabling the channel, but does clear it when disabling + * it. + */ + return !FIELD_EX32(*channel->reg_a2w_ctrl, A2W_PLLx_CHANNELy, DISABLE) + && !(*channel->reg_cm & channel->hold_mask); +} + +static void pll_channel_update(CprmanPllChannelState *channel) +{ + uint64_t freq, div; + + if (!pll_channel_is_enabled(channel)) { + clock_update(channel->out, 0); + return; + } + + div = FIELD_EX32(*channel->reg_a2w_ctrl, A2W_PLLx_CHANNELy, DIV); + + if (!div) { + /* + * It seems that when the divider value is 0, it is considered as + * being maximum by the hardware (see the Linux driver). + */ + div = R_A2W_PLLx_CHANNELy_DIV_MASK; + } + + /* Some channels have an additional fixed divider */ + freq = clock_get_hz(channel->pll_in) / (div * channel->fixed_divider); + + clock_update_hz(channel->out, freq); +} + +/* Update a PLL and all its channels */ +static void pll_update_all_channels(BCM2835CprmanState *s, + CprmanPllState *pll) +{ + size_t i; + + pll_update(pll); + + for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) { + CprmanPllChannelState *channel = &s->channels[i]; + if (channel->parent == pll->id) { + pll_channel_update(channel); + } + } +} + +static void pll_channel_pll_in_update(void *opaque) +{ + pll_channel_update(CPRMAN_PLL_CHANNEL(opaque)); +} + +static void pll_channel_init(Object *obj) +{ + CprmanPllChannelState *s = CPRMAN_PLL_CHANNEL(obj); + + s->pll_in = qdev_init_clock_in(DEVICE(s), "pll-in", + pll_channel_pll_in_update, s); + s->out = qdev_init_clock_out(DEVICE(s), "out"); +} + +static const VMStateDescription pll_channel_vmstate = { + .name = TYPE_CPRMAN_PLL_CHANNEL, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_CLOCK(pll_in, CprmanPllChannelState), + VMSTATE_END_OF_LIST() + } +}; + +static void pll_channel_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = pll_channel_reset; + dc->vmsd = &pll_channel_vmstate; +} + +static const TypeInfo cprman_pll_channel_info = { + .name = TYPE_CPRMAN_PLL_CHANNEL, + .parent = TYPE_DEVICE, + .instance_size = sizeof(CprmanPllChannelState), + .class_init = pll_channel_class_init, + .instance_init = pll_channel_init, +}; + + +/* clock mux */ + +static bool clock_mux_is_enabled(CprmanClockMuxState *mux) +{ + return FIELD_EX32(*mux->reg_ctl, CM_CLOCKx_CTL, ENABLE); +} + +static void clock_mux_update(CprmanClockMuxState *mux) +{ + uint64_t freq; + uint32_t div, src = FIELD_EX32(*mux->reg_ctl, CM_CLOCKx_CTL, SRC); + bool enabled = clock_mux_is_enabled(mux); + + *mux->reg_ctl = FIELD_DP32(*mux->reg_ctl, CM_CLOCKx_CTL, BUSY, enabled); + + if (!enabled) { + clock_update(mux->out, 0); + return; + } + + freq = clock_get_hz(mux->srcs[src]); + + if (mux->int_bits == 0 && mux->frac_bits == 0) { + clock_update_hz(mux->out, freq); + return; + } + + /* + * The divider has an integer and a fractional part. The size of each part + * varies with the muxes (int_bits and frac_bits). Both parts are + * concatenated, with the integer part always starting at bit 12. + * + * 31 12 11 0 + * ------------------------------ + * CM_DIV | | int | frac | | + * ------------------------------ + * <-----> <------> + * int_bits frac_bits + */ + div = extract32(*mux->reg_div, + R_CM_CLOCKx_DIV_FRAC_LENGTH - mux->frac_bits, + mux->int_bits + mux->frac_bits); + + if (!div) { + clock_update(mux->out, 0); + return; + } + + freq = muldiv64(freq, 1 << mux->frac_bits, div); + + clock_update_hz(mux->out, freq); +} + +static void clock_mux_src_update(void *opaque) +{ + CprmanClockMuxState **backref = opaque; + CprmanClockMuxState *s = *backref; + CprmanClockMuxSource src = backref - s->backref; + + if (FIELD_EX32(*s->reg_ctl, CM_CLOCKx_CTL, SRC) != src) { + return; + } + + clock_mux_update(s); +} + +static void clock_mux_reset(DeviceState *dev) +{ + CprmanClockMuxState *clock = CPRMAN_CLOCK_MUX(dev); + const ClockMuxResetInfo *info = &CLOCK_MUX_RESET_INFO[clock->id]; + + *clock->reg_ctl = info->cm_ctl; + *clock->reg_div = info->cm_div; +} + +static void clock_mux_init(Object *obj) +{ + CprmanClockMuxState *s = CPRMAN_CLOCK_MUX(obj); + size_t i; + + for (i = 0; i < CPRMAN_NUM_CLOCK_MUX_SRC; i++) { + char *name = g_strdup_printf("srcs[%zu]", i); + s->backref[i] = s; + s->srcs[i] = qdev_init_clock_in(DEVICE(s), name, + clock_mux_src_update, + &s->backref[i]); + g_free(name); + } + + s->out = qdev_init_clock_out(DEVICE(s), "out"); +} + +static const VMStateDescription clock_mux_vmstate = { + .name = TYPE_CPRMAN_CLOCK_MUX, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_ARRAY_CLOCK(srcs, CprmanClockMuxState, + CPRMAN_NUM_CLOCK_MUX_SRC), + VMSTATE_END_OF_LIST() + } +}; + +static void clock_mux_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = clock_mux_reset; + dc->vmsd = &clock_mux_vmstate; +} + +static const TypeInfo cprman_clock_mux_info = { + .name = TYPE_CPRMAN_CLOCK_MUX, + .parent = TYPE_DEVICE, + .instance_size = sizeof(CprmanClockMuxState), + .class_init = clock_mux_class_init, + .instance_init = clock_mux_init, +}; + + +/* DSI0HSCK mux */ + +static void dsi0hsck_mux_update(CprmanDsi0HsckMuxState *s) +{ + bool src_is_plld = FIELD_EX32(*s->reg_cm, CM_DSI0HSCK, SELPLLD); + Clock *src = src_is_plld ? s->plld_in : s->plla_in; + + clock_update(s->out, clock_get(src)); +} + +static void dsi0hsck_mux_in_update(void *opaque) +{ + dsi0hsck_mux_update(CPRMAN_DSI0HSCK_MUX(opaque)); +} + +static void dsi0hsck_mux_init(Object *obj) +{ + CprmanDsi0HsckMuxState *s = CPRMAN_DSI0HSCK_MUX(obj); + DeviceState *dev = DEVICE(obj); + + s->plla_in = qdev_init_clock_in(dev, "plla-in", dsi0hsck_mux_in_update, s); + s->plld_in = qdev_init_clock_in(dev, "plld-in", dsi0hsck_mux_in_update, s); + s->out = qdev_init_clock_out(DEVICE(s), "out"); +} + +static const VMStateDescription dsi0hsck_mux_vmstate = { + .name = TYPE_CPRMAN_DSI0HSCK_MUX, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_CLOCK(plla_in, CprmanDsi0HsckMuxState), + VMSTATE_CLOCK(plld_in, CprmanDsi0HsckMuxState), + VMSTATE_END_OF_LIST() + } +}; + +static void dsi0hsck_mux_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->vmsd = &dsi0hsck_mux_vmstate; +} + +static const TypeInfo cprman_dsi0hsck_mux_info = { + .name = TYPE_CPRMAN_DSI0HSCK_MUX, + .parent = TYPE_DEVICE, + .instance_size = sizeof(CprmanDsi0HsckMuxState), + .class_init = dsi0hsck_mux_class_init, + .instance_init = dsi0hsck_mux_init, +}; + + +/* CPRMAN "top level" model */ + +static uint32_t get_cm_lock(const BCM2835CprmanState *s) +{ + static const int CM_LOCK_MAPPING[CPRMAN_NUM_PLL] = { + [CPRMAN_PLLA] = R_CM_LOCK_FLOCKA_SHIFT, + [CPRMAN_PLLC] = R_CM_LOCK_FLOCKC_SHIFT, + [CPRMAN_PLLD] = R_CM_LOCK_FLOCKD_SHIFT, + [CPRMAN_PLLH] = R_CM_LOCK_FLOCKH_SHIFT, + [CPRMAN_PLLB] = R_CM_LOCK_FLOCKB_SHIFT, + }; + + uint32_t r = 0; + size_t i; + + for (i = 0; i < CPRMAN_NUM_PLL; i++) { + r |= pll_is_locked(&s->plls[i]) << CM_LOCK_MAPPING[i]; + } + + return r; +} + +static uint64_t cprman_read(void *opaque, hwaddr offset, + unsigned size) +{ + BCM2835CprmanState *s = CPRMAN(opaque); + uint64_t r = 0; + size_t idx = offset / sizeof(uint32_t); + + switch (idx) { + case R_CM_LOCK: + r = get_cm_lock(s); + break; + + default: + r = s->regs[idx]; + } + + trace_bcm2835_cprman_read(offset, r); + return r; +} + +static inline void update_pll_and_channels_from_cm(BCM2835CprmanState *s, + size_t idx) +{ + size_t i; + + for (i = 0; i < CPRMAN_NUM_PLL; i++) { + if (PLL_INIT_INFO[i].cm_offset == idx) { + pll_update_all_channels(s, &s->plls[i]); + return; + } + } +} + +static inline void update_channel_from_a2w(BCM2835CprmanState *s, size_t idx) +{ + size_t i; + + for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) { + if (PLL_CHANNEL_INIT_INFO[i].a2w_ctrl_offset == idx) { + pll_channel_update(&s->channels[i]); + return; + } + } +} + +static inline void update_mux_from_cm(BCM2835CprmanState *s, size_t idx) +{ + size_t i; + + for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) { + if ((CLOCK_MUX_INIT_INFO[i].cm_offset == idx) || + (CLOCK_MUX_INIT_INFO[i].cm_offset + 4 == idx)) { + /* matches CM_CTL or CM_DIV mux register */ + clock_mux_update(&s->clock_muxes[i]); + return; + } + } +} + +#define CASE_PLL_A2W_REGS(pll_) \ + case R_A2W_ ## pll_ ## _CTRL: \ + case R_A2W_ ## pll_ ## _ANA0: \ + case R_A2W_ ## pll_ ## _ANA1: \ + case R_A2W_ ## pll_ ## _ANA2: \ + case R_A2W_ ## pll_ ## _ANA3: \ + case R_A2W_ ## pll_ ## _FRAC + +static void cprman_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + BCM2835CprmanState *s = CPRMAN(opaque); + size_t idx = offset / sizeof(uint32_t); + + if (FIELD_EX32(value, CPRMAN, PASSWORD) != CPRMAN_PASSWORD) { + trace_bcm2835_cprman_write_invalid_magic(offset, value); + return; + } + + value &= ~R_CPRMAN_PASSWORD_MASK; + + trace_bcm2835_cprman_write(offset, value); + s->regs[idx] = value; + + switch (idx) { + case R_CM_PLLA ... R_CM_PLLH: + case R_CM_PLLB: + /* + * A given CM_PLLx register is shared by both the PLL and the channels + * of this PLL. + */ + update_pll_and_channels_from_cm(s, idx); + break; + + CASE_PLL_A2W_REGS(PLLA) : + pll_update(&s->plls[CPRMAN_PLLA]); + break; + + CASE_PLL_A2W_REGS(PLLC) : + pll_update(&s->plls[CPRMAN_PLLC]); + break; + + CASE_PLL_A2W_REGS(PLLD) : + pll_update(&s->plls[CPRMAN_PLLD]); + break; + + CASE_PLL_A2W_REGS(PLLH) : + pll_update(&s->plls[CPRMAN_PLLH]); + break; + + CASE_PLL_A2W_REGS(PLLB) : + pll_update(&s->plls[CPRMAN_PLLB]); + break; + + case R_A2W_PLLA_DSI0: + case R_A2W_PLLA_CORE: + case R_A2W_PLLA_PER: + case R_A2W_PLLA_CCP2: + case R_A2W_PLLC_CORE2: + case R_A2W_PLLC_CORE1: + case R_A2W_PLLC_PER: + case R_A2W_PLLC_CORE0: + case R_A2W_PLLD_DSI0: + case R_A2W_PLLD_CORE: + case R_A2W_PLLD_PER: + case R_A2W_PLLD_DSI1: + case R_A2W_PLLH_AUX: + case R_A2W_PLLH_RCAL: + case R_A2W_PLLH_PIX: + case R_A2W_PLLB_ARM: + update_channel_from_a2w(s, idx); + break; + + case R_CM_GNRICCTL ... R_CM_SMIDIV: + case R_CM_TCNTCNT ... R_CM_VECDIV: + case R_CM_PULSECTL ... R_CM_PULSEDIV: + case R_CM_SDCCTL ... R_CM_ARMCTL: + case R_CM_AVEOCTL ... R_CM_EMMCDIV: + case R_CM_EMMC2CTL ... R_CM_EMMC2DIV: + update_mux_from_cm(s, idx); + break; + + case R_CM_DSI0HSCK: + dsi0hsck_mux_update(&s->dsi0hsck_mux); + break; + } +} + +#undef CASE_PLL_A2W_REGS + +static const MemoryRegionOps cprman_ops = { + .read = cprman_read, + .write = cprman_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + /* + * Although this hasn't been checked against real hardware, nor the + * information can be found in a datasheet, it seems reasonable because + * of the "PASSWORD" magic value found in every registers. + */ + .min_access_size = 4, + .max_access_size = 4, + .unaligned = false, + }, + .impl = { + .max_access_size = 4, + }, +}; + +static void cprman_reset(DeviceState *dev) +{ + BCM2835CprmanState *s = CPRMAN(dev); + size_t i; + + memset(s->regs, 0, sizeof(s->regs)); + + for (i = 0; i < CPRMAN_NUM_PLL; i++) { + device_cold_reset(DEVICE(&s->plls[i])); + } + + for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) { + device_cold_reset(DEVICE(&s->channels[i])); + } + + device_cold_reset(DEVICE(&s->dsi0hsck_mux)); + + for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) { + device_cold_reset(DEVICE(&s->clock_muxes[i])); + } + + clock_update_hz(s->xosc, s->xosc_freq); +} + +static void cprman_init(Object *obj) +{ + BCM2835CprmanState *s = CPRMAN(obj); + size_t i; + + for (i = 0; i < CPRMAN_NUM_PLL; i++) { + object_initialize_child(obj, PLL_INIT_INFO[i].name, + &s->plls[i], TYPE_CPRMAN_PLL); + set_pll_init_info(s, &s->plls[i], i); + } + + for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) { + object_initialize_child(obj, PLL_CHANNEL_INIT_INFO[i].name, + &s->channels[i], + TYPE_CPRMAN_PLL_CHANNEL); + set_pll_channel_init_info(s, &s->channels[i], i); + } + + object_initialize_child(obj, "dsi0hsck-mux", + &s->dsi0hsck_mux, TYPE_CPRMAN_DSI0HSCK_MUX); + s->dsi0hsck_mux.reg_cm = &s->regs[R_CM_DSI0HSCK]; + + for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) { + char *alias; + + object_initialize_child(obj, CLOCK_MUX_INIT_INFO[i].name, + &s->clock_muxes[i], + TYPE_CPRMAN_CLOCK_MUX); + set_clock_mux_init_info(s, &s->clock_muxes[i], i); + + /* Expose muxes output as CPRMAN outputs */ + alias = g_strdup_printf("%s-out", CLOCK_MUX_INIT_INFO[i].name); + qdev_alias_clock(DEVICE(&s->clock_muxes[i]), "out", DEVICE(obj), alias); + g_free(alias); + } + + s->xosc = clock_new(obj, "xosc"); + s->gnd = clock_new(obj, "gnd"); + + clock_set(s->gnd, 0); + + memory_region_init_io(&s->iomem, obj, &cprman_ops, + s, "bcm2835-cprman", 0x2000); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); +} + +static void connect_mux_sources(BCM2835CprmanState *s, + CprmanClockMuxState *mux, + const CprmanPllChannel *clk_mapping) +{ + size_t i; + Clock *td0 = s->clock_muxes[CPRMAN_CLOCK_TD0].out; + Clock *td1 = s->clock_muxes[CPRMAN_CLOCK_TD1].out; + + /* For sources from 0 to 3. Source 4 to 9 are mux specific */ + Clock * const CLK_SRC_MAPPING[] = { + [CPRMAN_CLOCK_SRC_GND] = s->gnd, + [CPRMAN_CLOCK_SRC_XOSC] = s->xosc, + [CPRMAN_CLOCK_SRC_TD0] = td0, + [CPRMAN_CLOCK_SRC_TD1] = td1, + }; + + for (i = 0; i < CPRMAN_NUM_CLOCK_MUX_SRC; i++) { + CprmanPllChannel mapping = clk_mapping[i]; + Clock *src; + + if (mapping == CPRMAN_CLOCK_SRC_FORCE_GROUND) { + src = s->gnd; + } else if (mapping == CPRMAN_CLOCK_SRC_DSI0HSCK) { + src = s->dsi0hsck_mux.out; + } else if (i < CPRMAN_CLOCK_SRC_PLLA) { + src = CLK_SRC_MAPPING[i]; + } else { + src = s->channels[mapping].out; + } + + clock_set_source(mux->srcs[i], src); + } +} + +static void cprman_realize(DeviceState *dev, Error **errp) +{ + BCM2835CprmanState *s = CPRMAN(dev); + size_t i; + + for (i = 0; i < CPRMAN_NUM_PLL; i++) { + CprmanPllState *pll = &s->plls[i]; + + clock_set_source(pll->xosc_in, s->xosc); + + if (!qdev_realize(DEVICE(pll), NULL, errp)) { + return; + } + } + + for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) { + CprmanPllChannelState *channel = &s->channels[i]; + CprmanPll parent = PLL_CHANNEL_INIT_INFO[i].parent; + Clock *parent_clk = s->plls[parent].out; + + clock_set_source(channel->pll_in, parent_clk); + + if (!qdev_realize(DEVICE(channel), NULL, errp)) { + return; + } + } + + clock_set_source(s->dsi0hsck_mux.plla_in, + s->channels[CPRMAN_PLLA_CHANNEL_DSI0].out); + clock_set_source(s->dsi0hsck_mux.plld_in, + s->channels[CPRMAN_PLLD_CHANNEL_DSI0].out); + + if (!qdev_realize(DEVICE(&s->dsi0hsck_mux), NULL, errp)) { + return; + } + + for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) { + CprmanClockMuxState *clock_mux = &s->clock_muxes[i]; + + connect_mux_sources(s, clock_mux, CLOCK_MUX_INIT_INFO[i].src_mapping); + + if (!qdev_realize(DEVICE(clock_mux), NULL, errp)) { + return; + } + } +} + +static const VMStateDescription cprman_vmstate = { + .name = TYPE_BCM2835_CPRMAN, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, BCM2835CprmanState, CPRMAN_NUM_REGS), + VMSTATE_END_OF_LIST() + } +}; + +static Property cprman_properties[] = { + DEFINE_PROP_UINT32("xosc-freq-hz", BCM2835CprmanState, xosc_freq, 19200000), + DEFINE_PROP_END_OF_LIST() +}; + +static void cprman_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = cprman_realize; + dc->reset = cprman_reset; + dc->vmsd = &cprman_vmstate; + device_class_set_props(dc, cprman_properties); +} + +static const TypeInfo cprman_info = { + .name = TYPE_BCM2835_CPRMAN, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(BCM2835CprmanState), + .class_init = cprman_class_init, + .instance_init = cprman_init, +}; + +static void cprman_register_types(void) +{ + type_register_static(&cprman_info); + type_register_static(&cprman_pll_info); + type_register_static(&cprman_pll_channel_info); + type_register_static(&cprman_clock_mux_info); + type_register_static(&cprman_dsi0hsck_mux_info); +} + +type_init(cprman_register_types); diff --git a/hw/misc/bcm2835_mbox.c b/hw/misc/bcm2835_mbox.c index 2afa06a7464faa098a13c4fc64b43cc225a12bc5..9f73cbd5e419142680ff5bf80900ea807ba2aebf 100644 --- a/hw/misc/bcm2835_mbox.c +++ b/hw/misc/bcm2835_mbox.c @@ -308,15 +308,8 @@ static void bcm2835_mbox_realize(DeviceState *dev, Error **errp) { BCM2835MboxState *s = BCM2835_MBOX(dev); Object *obj; - Error *err = NULL; - - obj = object_property_get_link(OBJECT(dev), "mbox-mr", &err); - if (obj == NULL) { - error_setg(errp, "%s: required mbox-mr link not found: %s", - __func__, error_get_pretty(err)); - return; - } + obj = object_property_get_link(OBJECT(dev), "mbox-mr", &error_abort); s->mbox_mr = MEMORY_REGION(obj); address_space_init(&s->mbox_as, s->mbox_mr, TYPE_BCM2835_MBOX "-memory"); bcm2835_mbox_reset(dev); diff --git a/hw/misc/bcm2835_mphi.c b/hw/misc/bcm2835_mphi.c new file mode 100644 index 0000000000000000000000000000000000000000..0428e10ba5cc4fc3b9dcbf86a0a151d09db9330a --- /dev/null +++ b/hw/misc/bcm2835_mphi.c @@ -0,0 +1,191 @@ +/* + * BCM2835 SOC MPHI emulation + * + * Very basic emulation, only providing the FIQ interrupt needed to + * allow the dwc-otg USB host controller driver in the Raspbian kernel + * to function. + * + * Copyright (c) 2020 Paul Zimmerman + * + * 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. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/misc/bcm2835_mphi.h" +#include "migration/vmstate.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qemu/main-loop.h" + +static inline void mphi_raise_irq(BCM2835MphiState *s) +{ + qemu_set_irq(s->irq, 1); +} + +static inline void mphi_lower_irq(BCM2835MphiState *s) +{ + qemu_set_irq(s->irq, 0); +} + +static uint64_t mphi_reg_read(void *ptr, hwaddr addr, unsigned size) +{ + BCM2835MphiState *s = ptr; + uint32_t val = 0; + + switch (addr) { + case 0x28: /* outdda */ + val = s->outdda; + break; + case 0x2c: /* outddb */ + val = s->outddb; + break; + case 0x4c: /* ctrl */ + val = s->ctrl; + val |= 1 << 17; + break; + case 0x50: /* intstat */ + val = s->intstat; + break; + case 0x1f0: /* swirq_set */ + val = s->swirq; + break; + case 0x1f4: /* swirq_clr */ + val = s->swirq; + break; + default: + qemu_log_mask(LOG_UNIMP, "read from unknown register"); + break; + } + + return val; +} + +static void mphi_reg_write(void *ptr, hwaddr addr, uint64_t val, unsigned size) +{ + BCM2835MphiState *s = ptr; + int do_irq = 0; + + switch (addr) { + case 0x28: /* outdda */ + s->outdda = val; + break; + case 0x2c: /* outddb */ + s->outddb = val; + if (val & (1 << 29)) { + do_irq = 1; + } + break; + case 0x4c: /* ctrl */ + s->ctrl = val; + if (val & (1 << 16)) { + do_irq = -1; + } + break; + case 0x50: /* intstat */ + s->intstat = val; + if (val & ((1 << 16) | (1 << 29))) { + do_irq = -1; + } + break; + case 0x1f0: /* swirq_set */ + s->swirq |= val; + do_irq = 1; + break; + case 0x1f4: /* swirq_clr */ + s->swirq &= ~val; + do_irq = -1; + break; + default: + qemu_log_mask(LOG_UNIMP, "write to unknown register"); + return; + } + + if (do_irq > 0) { + mphi_raise_irq(s); + } else if (do_irq < 0) { + mphi_lower_irq(s); + } +} + +static const MemoryRegionOps mphi_mmio_ops = { + .read = mphi_reg_read, + .write = mphi_reg_write, + .impl.min_access_size = 4, + .impl.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void mphi_reset(DeviceState *dev) +{ + BCM2835MphiState *s = BCM2835_MPHI(dev); + + s->outdda = 0; + s->outddb = 0; + s->ctrl = 0; + s->intstat = 0; + s->swirq = 0; +} + +static void mphi_realize(DeviceState *dev, Error **errp) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + BCM2835MphiState *s = BCM2835_MPHI(dev); + + sysbus_init_irq(sbd, &s->irq); +} + +static void mphi_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + BCM2835MphiState *s = BCM2835_MPHI(obj); + + memory_region_init_io(&s->iomem, obj, &mphi_mmio_ops, s, "mphi", MPHI_MMIO_SIZE); + sysbus_init_mmio(sbd, &s->iomem); +} + +const VMStateDescription vmstate_mphi_state = { + .name = "mphi", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(outdda, BCM2835MphiState), + VMSTATE_UINT32(outddb, BCM2835MphiState), + VMSTATE_UINT32(ctrl, BCM2835MphiState), + VMSTATE_UINT32(intstat, BCM2835MphiState), + VMSTATE_UINT32(swirq, BCM2835MphiState), + VMSTATE_END_OF_LIST() + } +}; + +static void mphi_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = mphi_realize; + dc->reset = mphi_reset; + dc->vmsd = &vmstate_mphi_state; +} + +static const TypeInfo bcm2835_mphi_type_info = { + .name = TYPE_BCM2835_MPHI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(BCM2835MphiState), + .instance_init = mphi_init, + .class_init = mphi_class_init, +}; + +static void bcm2835_mphi_register_types(void) +{ + type_register_static(&bcm2835_mphi_type_info); +} + +type_init(bcm2835_mphi_register_types) diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c index 3e228ca0ae418a1240935eec7ae91e336581b788..73941bdae977d65abc457c99fb23883b0bb331a2 100644 --- a/hw/misc/bcm2835_property.c +++ b/hw/misc/bcm2835_property.c @@ -392,24 +392,11 @@ static void bcm2835_property_realize(DeviceState *dev, Error **errp) { BCM2835PropertyState *s = BCM2835_PROPERTY(dev); Object *obj; - Error *err = NULL; - - obj = object_property_get_link(OBJECT(dev), "fb", &err); - if (obj == NULL) { - error_setg(errp, "%s: required fb link not found: %s", - __func__, error_get_pretty(err)); - return; - } + obj = object_property_get_link(OBJECT(dev), "fb", &error_abort); s->fbdev = BCM2835_FB(obj); - obj = object_property_get_link(OBJECT(dev), "dma-mr", &err); - if (obj == NULL) { - error_setg(errp, "%s: required dma-mr link not found: %s", - __func__, error_get_pretty(err)); - return; - } - + obj = object_property_get_link(OBJECT(dev), "dma-mr", &error_abort); s->dma_mr = MEMORY_REGION(obj); address_space_init(&s->dma_as, s->dma_mr, TYPE_BCM2835_PROPERTY "-memory"); diff --git a/hw/misc/debugexit.c b/hw/misc/debugexit.c index 99a814f10c38d4bcbac0153481a1192b69d40a36..ab6de69ce72ff9ae9661e7c3354aa6951f49b29f 100644 --- a/hw/misc/debugexit.c +++ b/hw/misc/debugexit.c @@ -11,18 +11,18 @@ #include "hw/isa/isa.h" #include "hw/qdev-properties.h" #include "qemu/module.h" +#include "qom/object.h" #define TYPE_ISA_DEBUG_EXIT_DEVICE "isa-debug-exit" -#define ISA_DEBUG_EXIT_DEVICE(obj) \ - OBJECT_CHECK(ISADebugExitState, (obj), TYPE_ISA_DEBUG_EXIT_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(ISADebugExitState, ISA_DEBUG_EXIT_DEVICE) -typedef struct ISADebugExitState { +struct ISADebugExitState { ISADevice parent_obj; uint32_t iobase; uint32_t iosize; MemoryRegion io; -} ISADebugExitState; +}; static uint64_t debug_exit_read(void *opaque, hwaddr addr, unsigned size) { diff --git a/hw/misc/eccmemctl.c b/hw/misc/eccmemctl.c index aec447368e9fe3fb41a04cfb401af8b93c6fe8e7..c65806e3d9a987a68e5a2a8d124e84ee5b2e188e 100644 --- a/hw/misc/eccmemctl.c +++ b/hw/misc/eccmemctl.c @@ -29,6 +29,7 @@ #include "migration/vmstate.h" #include "qemu/module.h" #include "trace.h" +#include "qom/object.h" /* There are 3 versions of this chip used in SMP sun4m systems: * MCC (version 0, implementation 0) SS-600MP @@ -126,9 +127,9 @@ #define ECC_DIAG_MASK (ECC_DIAG_SIZE - 1) #define TYPE_ECC_MEMCTL "eccmemctl" -#define ECC_MEMCTL(obj) OBJECT_CHECK(ECCState, (obj), TYPE_ECC_MEMCTL) +OBJECT_DECLARE_SIMPLE_TYPE(ECCState, ECC_MEMCTL) -typedef struct ECCState { +struct ECCState { SysBusDevice parent_obj; MemoryRegion iomem, iomem_diag; @@ -136,7 +137,7 @@ typedef struct ECCState { uint32_t regs[ECC_NREGS]; uint8_t diag[ECC_DIAG_SIZE]; uint32_t version; -} ECCState; +}; static void ecc_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) diff --git a/hw/misc/edu.c b/hw/misc/edu.c index ec617e63f32d060d26a161dfedd80610113f2697..e935c418d40066b600a434c3bd9b04babbad96ea 100644 --- a/hw/misc/edu.c +++ b/hw/misc/edu.c @@ -28,12 +28,15 @@ #include "hw/hw.h" #include "hw/pci/msi.h" #include "qemu/timer.h" +#include "qom/object.h" #include "qemu/main-loop.h" /* iothread mutex */ #include "qemu/module.h" #include "qapi/visitor.h" #define TYPE_PCI_EDU_DEVICE "edu" -#define EDU(obj) OBJECT_CHECK(EduState, obj, TYPE_PCI_EDU_DEVICE) +typedef struct EduState EduState; +DECLARE_INSTANCE_CHECKER(EduState, EDU, + TYPE_PCI_EDU_DEVICE) #define FACT_IRQ 0x00000001 #define DMA_IRQ 0x00000100 @@ -41,7 +44,7 @@ #define DMA_START 0x40000 #define DMA_SIZE 4096 -typedef struct { +struct EduState { PCIDevice pdev; MemoryRegion mmio; @@ -72,7 +75,7 @@ typedef struct { QEMUTimer dma_timer; char dma_buf[DMA_SIZE]; uint64_t dma_mask; -} EduState; +}; static bool edu_msi_enabled(EduState *edu) { @@ -209,7 +212,7 @@ static uint64_t edu_mmio_read(void *opaque, hwaddr addr, unsigned size) qemu_mutex_unlock(&edu->thr_mutex); break; case 0x20: - val = atomic_read(&edu->status); + val = qatomic_read(&edu->status); break; case 0x24: val = edu->irq_status; @@ -249,7 +252,7 @@ static void edu_mmio_write(void *opaque, hwaddr addr, uint64_t val, edu->addr4 = ~val; break; case 0x08: - if (atomic_read(&edu->status) & EDU_STATUS_COMPUTING) { + if (qatomic_read(&edu->status) & EDU_STATUS_COMPUTING) { break; } /* EDU_STATUS_COMPUTING cannot go 0->1 concurrently, because it is only @@ -257,15 +260,15 @@ static void edu_mmio_write(void *opaque, hwaddr addr, uint64_t val, */ qemu_mutex_lock(&edu->thr_mutex); edu->fact = val; - atomic_or(&edu->status, EDU_STATUS_COMPUTING); + qatomic_or(&edu->status, EDU_STATUS_COMPUTING); qemu_cond_signal(&edu->thr_cond); qemu_mutex_unlock(&edu->thr_mutex); break; case 0x20: if (val & EDU_STATUS_IRQFACT) { - atomic_or(&edu->status, EDU_STATUS_IRQFACT); + qatomic_or(&edu->status, EDU_STATUS_IRQFACT); } else { - atomic_and(&edu->status, ~EDU_STATUS_IRQFACT); + qatomic_and(&edu->status, ~EDU_STATUS_IRQFACT); } break; case 0x60: @@ -319,7 +322,7 @@ static void *edu_fact_thread(void *opaque) uint32_t val, ret = 1; qemu_mutex_lock(&edu->thr_mutex); - while ((atomic_read(&edu->status) & EDU_STATUS_COMPUTING) == 0 && + while ((qatomic_read(&edu->status) & EDU_STATUS_COMPUTING) == 0 && !edu->stopping) { qemu_cond_wait(&edu->thr_cond, &edu->thr_mutex); } @@ -344,9 +347,9 @@ static void *edu_fact_thread(void *opaque) qemu_mutex_lock(&edu->thr_mutex); edu->fact = ret; qemu_mutex_unlock(&edu->thr_mutex); - atomic_and(&edu->status, ~EDU_STATUS_COMPUTING); + qatomic_and(&edu->status, ~EDU_STATUS_COMPUTING); - if (atomic_read(&edu->status) & EDU_STATUS_IRQFACT) { + if (qatomic_read(&edu->status) & EDU_STATUS_IRQFACT) { qemu_mutex_lock_iothread(); edu_raise_irq(edu, FACT_IRQ); qemu_mutex_unlock_iothread(); diff --git a/hw/core/empty_slot.c b/hw/misc/empty_slot.c similarity index 59% rename from hw/core/empty_slot.c rename to hw/misc/empty_slot.c index 3ba450e1caba88fe703df77cf27aa32d77df92cb..37b0ddfb02a90740d03cc75e86218d8f3549d8b6 100644 --- a/hw/core/empty_slot.c +++ b/hw/misc/empty_slot.c @@ -11,39 +11,39 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "qemu/module.h" -#include "hw/empty_slot.h" - -//#define DEBUG_EMPTY_SLOT - -#ifdef DEBUG_EMPTY_SLOT -#define DPRINTF(fmt, ...) \ - do { printf("empty_slot: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) do {} while (0) -#endif +#include "hw/qdev-properties.h" +#include "hw/misc/empty_slot.h" +#include "qapi/error.h" +#include "trace.h" +#include "qom/object.h" #define TYPE_EMPTY_SLOT "empty_slot" -#define EMPTY_SLOT(obj) OBJECT_CHECK(EmptySlot, (obj), TYPE_EMPTY_SLOT) +OBJECT_DECLARE_SIMPLE_TYPE(EmptySlot, EMPTY_SLOT) -typedef struct EmptySlot { +struct EmptySlot { SysBusDevice parent_obj; MemoryRegion iomem; + char *name; uint64_t size; -} EmptySlot; +}; static uint64_t empty_slot_read(void *opaque, hwaddr addr, unsigned size) { - DPRINTF("read from " TARGET_FMT_plx "\n", addr); + EmptySlot *s = EMPTY_SLOT(opaque); + + trace_empty_slot_write(addr, size << 1, 0, size, s->name); + return 0; } static void empty_slot_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { - DPRINTF("write 0x%x to " TARGET_FMT_plx "\n", (unsigned)val, addr); + EmptySlot *s = EMPTY_SLOT(opaque); + + trace_empty_slot_write(addr, size << 1, val, size, s->name); } static const MemoryRegionOps empty_slot_ops = { @@ -52,22 +52,18 @@ static const MemoryRegionOps empty_slot_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -void empty_slot_init(hwaddr addr, uint64_t slot_size) +void empty_slot_init(const char *name, hwaddr addr, uint64_t slot_size) { if (slot_size > 0) { /* Only empty slots larger than 0 byte need handling. */ DeviceState *dev; - SysBusDevice *s; - EmptySlot *e; - dev = qdev_create(NULL, TYPE_EMPTY_SLOT); - s = SYS_BUS_DEVICE(dev); - e = EMPTY_SLOT(dev); - e->size = slot_size; + dev = qdev_new(TYPE_EMPTY_SLOT); - qdev_init_nofail(dev); + qdev_prop_set_uint64(dev, "size", slot_size); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - sysbus_mmio_map(s, 0, addr); + sysbus_mmio_map_overlap(SYS_BUS_DEVICE(dev), 0, addr, -10000); } } @@ -75,16 +71,27 @@ static void empty_slot_realize(DeviceState *dev, Error **errp) { EmptySlot *s = EMPTY_SLOT(dev); + if (s->name == NULL) { + s->name = g_strdup("empty-slot"); + } memory_region_init_io(&s->iomem, OBJECT(s), &empty_slot_ops, s, - "empty-slot", s->size); + s->name, s->size); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); } +static Property empty_slot_properties[] = { + DEFINE_PROP_UINT64("size", EmptySlot, size, 0), + DEFINE_PROP_STRING("name", EmptySlot, name), + DEFINE_PROP_END_OF_LIST(), +}; + static void empty_slot_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = empty_slot_realize; + device_class_set_props(dc, empty_slot_properties); + set_bit(DEVICE_CATEGORY_MISC, dc->categories); } static const TypeInfo empty_slot_info = { diff --git a/hw/misc/exynos4210_clk.c b/hw/misc/exynos4210_clk.c index bc1463ff89e8a4e62735c2141b59ae112c6096fa..58cec282f755e84244ea7f85c9fe8194f2c6848b 100644 --- a/hw/misc/exynos4210_clk.c +++ b/hw/misc/exynos4210_clk.c @@ -22,10 +22,10 @@ #include "migration/vmstate.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" #define TYPE_EXYNOS4210_CLK "exynos4210.clk" -#define EXYNOS4210_CLK(obj) \ - OBJECT_CHECK(Exynos4210ClkState, (obj), TYPE_EXYNOS4210_CLK) +OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210ClkState, EXYNOS4210_CLK) #define CLK_PLL_LOCKED BIT(29) @@ -55,12 +55,12 @@ static const Exynos4210Reg exynos4210_clk_regs[] = { #define EXYNOS4210_REGS_NUM ARRAY_SIZE(exynos4210_clk_regs) -typedef struct Exynos4210ClkState { +struct Exynos4210ClkState { SysBusDevice parent_obj; MemoryRegion iomem; uint32_t reg[EXYNOS4210_REGS_NUM]; -} Exynos4210ClkState; +}; static uint64_t exynos4210_clk_read(void *opaque, hwaddr offset, unsigned size) diff --git a/hw/misc/exynos4210_pmu.c b/hw/misc/exynos4210_pmu.c index 500f28343f54565c97b8b566e93a478e969742c7..e24139c630b83543116dab41b81b1d95a163a31e 100644 --- a/hw/misc/exynos4210_pmu.c +++ b/hw/misc/exynos4210_pmu.c @@ -29,6 +29,7 @@ #include "migration/vmstate.h" #include "qemu/module.h" #include "sysemu/runstate.h" +#include "qom/object.h" #ifndef DEBUG_PMU #define DEBUG_PMU 0 @@ -394,15 +395,14 @@ static const Exynos4210PmuReg exynos4210_pmu_regs[] = { #define PMU_NUM_OF_REGISTERS ARRAY_SIZE(exynos4210_pmu_regs) #define TYPE_EXYNOS4210_PMU "exynos4210.pmu" -#define EXYNOS4210_PMU(obj) \ - OBJECT_CHECK(Exynos4210PmuState, (obj), TYPE_EXYNOS4210_PMU) +OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210PmuState, EXYNOS4210_PMU) -typedef struct Exynos4210PmuState { +struct Exynos4210PmuState { SysBusDevice parent_obj; MemoryRegion iomem; uint32_t reg[PMU_NUM_OF_REGISTERS]; -} Exynos4210PmuState; +}; static void exynos4210_pmu_poweroff(void) { diff --git a/hw/misc/exynos4210_rng.c b/hw/misc/exynos4210_rng.c index 38cd61c7ea786c149d98de48a961ce3d63792447..1b9e8347a1a85bb324a27f583bb711884995538d 100644 --- a/hw/misc/exynos4210_rng.c +++ b/hw/misc/exynos4210_rng.c @@ -24,6 +24,7 @@ #include "qemu/log.h" #include "qemu/guest-random.h" #include "qemu/module.h" +#include "qom/object.h" #define DEBUG_EXYNOS_RNG 0 @@ -35,8 +36,7 @@ } while (0) #define TYPE_EXYNOS4210_RNG "exynos4210.rng" -#define EXYNOS4210_RNG(obj) \ - OBJECT_CHECK(Exynos4210RngState, (obj), TYPE_EXYNOS4210_RNG) +OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210RngState, EXYNOS4210_RNG) /* * Exynos4220, PRNG, only polling mode is supported. @@ -68,7 +68,7 @@ #define EXYNOS4210_RNG_REGS_MEM_SIZE 0x200 -typedef struct Exynos4210RngState { +struct Exynos4210RngState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -79,7 +79,7 @@ typedef struct Exynos4210RngState { /* Register values */ uint32_t reg_control; uint32_t reg_status; -} Exynos4210RngState; +}; static bool exynos4210_rng_seed_ready(const Exynos4210RngState *s) { diff --git a/hw/misc/grlib_ahb_apb_pnp.c b/hw/misc/grlib_ahb_apb_pnp.c index e230e2536361bfc02e87136f6f90a0c4ef86dc4c..43e001c3c7b78a0e6b1e9cd7ddbf7dabd57f3a3d 100644 --- a/hw/misc/grlib_ahb_apb_pnp.c +++ b/hw/misc/grlib_ahb_apb_pnp.c @@ -25,6 +25,7 @@ #include "qemu/log.h" #include "hw/sysbus.h" #include "hw/misc/grlib_ahb_apb_pnp.h" +#include "trace.h" #define GRLIB_PNP_VENDOR_SHIFT (24) #define GRLIB_PNP_VENDOR_SIZE (8) @@ -132,13 +133,28 @@ void grlib_ahb_pnp_add_entry(AHBPnp *dev, uint32_t address, uint32_t mask, static uint64_t grlib_ahb_pnp_read(void *opaque, hwaddr offset, unsigned size) { AHBPnp *ahb_pnp = GRLIB_AHB_PNP(opaque); + uint32_t val; - return ahb_pnp->regs[offset >> 2]; + val = ahb_pnp->regs[offset >> 2]; + trace_grlib_ahb_pnp_read(offset, val); + + return val; +} + +static void grlib_ahb_pnp_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + qemu_log_mask(LOG_UNIMP, "%s not implemented\n", __func__); } static const MemoryRegionOps grlib_ahb_pnp_ops = { .read = grlib_ahb_pnp_read, + .write = grlib_ahb_pnp_write, .endianness = DEVICE_BIG_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, }; static void grlib_ahb_pnp_realize(DeviceState *dev, Error **errp) @@ -228,8 +244,12 @@ void grlib_apb_pnp_add_entry(APBPnp *dev, uint32_t address, uint32_t mask, static uint64_t grlib_apb_pnp_read(void *opaque, hwaddr offset, unsigned size) { APBPnp *apb_pnp = GRLIB_APB_PNP(opaque); + uint32_t val; + + val = apb_pnp->regs[offset >> 2]; + trace_grlib_apb_pnp_read(offset, val); - return apb_pnp->regs[offset >> 2]; + return val; } static void grlib_apb_pnp_write(void *opaque, hwaddr addr, diff --git a/hw/misc/imx6ul_ccm.c b/hw/misc/imx6ul_ccm.c index a2fc1d0364af3cbbdd7e94e99b1dda3677c5c986..5e0661dacf7e2bfd0c80aa414a0c5482d713b823 100644 --- a/hw/misc/imx6ul_ccm.c +++ b/hw/misc/imx6ul_ccm.c @@ -19,6 +19,62 @@ #include "trace.h" +static const uint32_t ccm_mask[CCM_MAX] = { + [CCM_CCR] = 0xf01fef80, + [CCM_CCDR] = 0xfffeffff, + [CCM_CSR] = 0xffffffff, + [CCM_CCSR] = 0xfffffef2, + [CCM_CACRR] = 0xfffffff8, + [CCM_CBCDR] = 0xc1f8e000, + [CCM_CBCMR] = 0xfc03cfff, + [CCM_CSCMR1] = 0x80700000, + [CCM_CSCMR2] = 0xe01ff003, + [CCM_CSCDR1] = 0xfe00c780, + [CCM_CS1CDR] = 0xfe00fe00, + [CCM_CS2CDR] = 0xf8007000, + [CCM_CDCDR] = 0xf00fffff, + [CCM_CHSCCDR] = 0xfffc01ff, + [CCM_CSCDR2] = 0xfe0001ff, + [CCM_CSCDR3] = 0xffffc1ff, + [CCM_CDHIPR] = 0xffffffff, + [CCM_CTOR] = 0x00000000, + [CCM_CLPCR] = 0xf39ff01c, + [CCM_CISR] = 0xfb85ffbe, + [CCM_CIMR] = 0xfb85ffbf, + [CCM_CCOSR] = 0xfe00fe00, + [CCM_CGPR] = 0xfffc3fea, + [CCM_CCGR0] = 0x00000000, + [CCM_CCGR1] = 0x00000000, + [CCM_CCGR2] = 0x00000000, + [CCM_CCGR3] = 0x00000000, + [CCM_CCGR4] = 0x00000000, + [CCM_CCGR5] = 0x00000000, + [CCM_CCGR6] = 0x00000000, + [CCM_CMEOR] = 0xafffff1f, +}; + +static const uint32_t analog_mask[CCM_ANALOG_MAX] = { + [CCM_ANALOG_PLL_ARM] = 0xfff60f80, + [CCM_ANALOG_PLL_USB1] = 0xfffe0fbc, + [CCM_ANALOG_PLL_USB2] = 0xfffe0fbc, + [CCM_ANALOG_PLL_SYS] = 0xfffa0ffe, + [CCM_ANALOG_PLL_SYS_SS] = 0x00000000, + [CCM_ANALOG_PLL_SYS_NUM] = 0xc0000000, + [CCM_ANALOG_PLL_SYS_DENOM] = 0xc0000000, + [CCM_ANALOG_PLL_AUDIO] = 0xffe20f80, + [CCM_ANALOG_PLL_AUDIO_NUM] = 0xc0000000, + [CCM_ANALOG_PLL_AUDIO_DENOM] = 0xc0000000, + [CCM_ANALOG_PLL_VIDEO] = 0xffe20f80, + [CCM_ANALOG_PLL_VIDEO_NUM] = 0xc0000000, + [CCM_ANALOG_PLL_VIDEO_DENOM] = 0xc0000000, + [CCM_ANALOG_PLL_ENET] = 0xffc20ff0, + [CCM_ANALOG_PFD_480] = 0x40404040, + [CCM_ANALOG_PFD_528] = 0x40404040, + [PMU_MISC0] = 0x01fe8306, + [PMU_MISC1] = 0x07fcede0, + [PMU_MISC2] = 0x005f5f5f, +}; + static const char *imx6ul_ccm_reg_name(uint32_t reg) { static char unknown[20]; @@ -596,11 +652,8 @@ static void imx6ul_ccm_write(void *opaque, hwaddr offset, uint64_t value, trace_ccm_write_reg(imx6ul_ccm_reg_name(index), (uint32_t)value); - /* - * We will do a better implementation later. In particular some bits - * cannot be written to. - */ - s->ccm[index] = (uint32_t)value; + s->ccm[index] = (s->ccm[index] & ccm_mask[index]) | + ((uint32_t)value & ~ccm_mask[index]); } static uint64_t imx6ul_analog_read(void *opaque, hwaddr offset, unsigned size) @@ -737,7 +790,7 @@ static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value, * the REG_NAME register. So we change the value of the * REG_NAME register, setting bits passed in the value. */ - s->analog[index - 1] |= value; + s->analog[index - 1] |= (value & ~analog_mask[index - 1]); break; case CCM_ANALOG_PLL_ARM_CLR: case CCM_ANALOG_PLL_USB1_CLR: @@ -762,7 +815,7 @@ static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value, * the REG_NAME register. So we change the value of the * REG_NAME register, unsetting bits passed in the value. */ - s->analog[index - 2] &= ~value; + s->analog[index - 2] &= ~(value & ~analog_mask[index - 2]); break; case CCM_ANALOG_PLL_ARM_TOG: case CCM_ANALOG_PLL_USB1_TOG: @@ -787,14 +840,11 @@ static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value, * the REG_NAME register. So we change the value of the * REG_NAME register, toggling bits passed in the value. */ - s->analog[index - 3] ^= value; + s->analog[index - 3] ^= (value & ~analog_mask[index - 3]); break; default: - /* - * We will do a better implementation later. In particular some bits - * cannot be written to. - */ - s->analog[index] = value; + s->analog[index] = (s->analog[index] & analog_mask[index]) | + (value & ~analog_mask[index]); break; } } diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c index 2f81b0ad73d28db26fe2c6ea03eb687b19c1d10b..52882071d3b7a5b0566bb5d6451efaf31c29d235 100644 --- a/hw/misc/imx_ccm.c +++ b/hw/misc/imx_ccm.c @@ -32,7 +32,7 @@ uint32_t imx_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock) { uint32_t freq = 0; - IMXCCMClass *klass = IMX_GET_CLASS(dev); + IMXCCMClass *klass = IMX_CCM_GET_CLASS(dev); if (klass->get_clock_frequency) { freq = klass->get_clock_frequency(dev, clock); diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c index ec1cc1931a83f3f8a1a841025e9bcbceeffd2067..964b48c74d97b4b4cfadb4f200e6a16157a79c8d 100644 --- a/hw/misc/iotkit-sysctl.c +++ b/hw/misc/iotkit-sysctl.c @@ -83,8 +83,8 @@ static void set_init_vtor(uint64_t cpuid, uint32_t vtor) Object *cpuobj = OBJECT(arm_get_cpu_by_id(cpuid)); if (cpuobj) { - if (object_property_find(cpuobj, "init-svtor", NULL)) { - object_property_set_uint(cpuobj, vtor, "init-svtor", &error_abort); + if (object_property_find(cpuobj, "init-svtor")) { + object_property_set_uint(cpuobj, "init-svtor", vtor, &error_abort); } } } diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c index a8dc9b377d000988c2f9a81ca137b3433a7d2076..e321e5cb69dabe8554f4aa7a66d0091e17ff03f6 100644 --- a/hw/misc/ivshmem.c +++ b/hw/misc/ivshmem.c @@ -38,6 +38,7 @@ #include "qapi/visitor.h" #include "hw/misc/ivshmem.h" +#include "qom/object.h" #define PCI_VENDOR_ID_IVSHMEM PCI_VENDOR_ID_REDHAT_QUMRANET #define PCI_DEVICE_ID_IVSHMEM 0x1110 @@ -57,20 +58,21 @@ } while (0) #define TYPE_IVSHMEM_COMMON "ivshmem-common" -#define IVSHMEM_COMMON(obj) \ - OBJECT_CHECK(IVShmemState, (obj), TYPE_IVSHMEM_COMMON) +typedef struct IVShmemState IVShmemState; +DECLARE_INSTANCE_CHECKER(IVShmemState, IVSHMEM_COMMON, + TYPE_IVSHMEM_COMMON) #define TYPE_IVSHMEM_PLAIN "ivshmem-plain" -#define IVSHMEM_PLAIN(obj) \ - OBJECT_CHECK(IVShmemState, (obj), TYPE_IVSHMEM_PLAIN) +DECLARE_INSTANCE_CHECKER(IVShmemState, IVSHMEM_PLAIN, + TYPE_IVSHMEM_PLAIN) #define TYPE_IVSHMEM_DOORBELL "ivshmem-doorbell" -#define IVSHMEM_DOORBELL(obj) \ - OBJECT_CHECK(IVShmemState, (obj), TYPE_IVSHMEM_DOORBELL) +DECLARE_INSTANCE_CHECKER(IVShmemState, IVSHMEM_DOORBELL, + TYPE_IVSHMEM_DOORBELL) #define TYPE_IVSHMEM "ivshmem" -#define IVSHMEM(obj) \ - OBJECT_CHECK(IVShmemState, (obj), TYPE_IVSHMEM) +DECLARE_INSTANCE_CHECKER(IVShmemState, IVSHMEM, + TYPE_IVSHMEM) typedef struct Peer { int nb_eventfds; @@ -83,7 +85,7 @@ typedef struct MSIVector { bool unmasked; } MSIVector; -typedef struct IVShmemState { +struct IVShmemState { /*< private >*/ PCIDevice parent_obj; /*< public >*/ @@ -115,7 +117,7 @@ typedef struct IVShmemState { /* migration stuff */ OnOffAuto master; Error *migration_blocker; -} IVShmemState; +}; /* registers for the Inter-VM shared memory device */ enum ivshmem_registers { @@ -898,9 +900,7 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp) if (!ivshmem_is_master(s)) { error_setg(&s->migration_blocker, "Migration is disabled when using feature 'peer mode' in device 'ivshmem'"); - migrate_add_blocker(s->migration_blocker, &err); - if (err) { - error_propagate(errp, err); + if (migrate_add_blocker(s->migration_blocker, errp) < 0) { error_free(s->migration_blocker); return; } @@ -1039,9 +1039,8 @@ static void ivshmem_plain_realize(PCIDevice *dev, Error **errp) error_setg(errp, "You must specify a 'memdev'"); return; } else if (host_memory_backend_is_mapped(s->hostmem)) { - char *path = object_get_canonical_path_component(OBJECT(s->hostmem)); - error_setg(errp, "can't use already busy memdev: %s", path); - g_free(path); + error_setg(errp, "can't use already busy memdev: %s", + object_get_canonical_path_component(OBJECT(s->hostmem))); return; } diff --git a/hw/misc/led.c b/hw/misc/led.c new file mode 100644 index 0000000000000000000000000000000000000000..5266d026d0b07267505996acb93c2aaab09f3d49 --- /dev/null +++ b/hw/misc/led.c @@ -0,0 +1,161 @@ +/* + * QEMU single LED device + * + * Copyright (C) 2020 Philippe Mathieu-DaudĂ© + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" +#include "hw/misc/led.h" +#include "hw/irq.h" +#include "trace.h" + +#define LED_INTENSITY_PERCENT_MAX 100 + +static const char * const led_color_name[] = { + [LED_COLOR_VIOLET] = "violet", + [LED_COLOR_BLUE] = "blue", + [LED_COLOR_CYAN] = "cyan", + [LED_COLOR_GREEN] = "green", + [LED_COLOR_AMBER] = "amber", + [LED_COLOR_ORANGE] = "orange", + [LED_COLOR_RED] = "red", +}; + +static bool led_color_name_is_valid(const char *color_name) +{ + for (size_t i = 0; i < ARRAY_SIZE(led_color_name); i++) { + if (strcmp(color_name, led_color_name[i]) == 0) { + return true; + } + } + return false; +} + +void led_set_intensity(LEDState *s, unsigned intensity_percent) +{ + if (intensity_percent > LED_INTENSITY_PERCENT_MAX) { + intensity_percent = LED_INTENSITY_PERCENT_MAX; + } + trace_led_set_intensity(s->description, s->color, intensity_percent); + if (intensity_percent != s->intensity_percent) { + trace_led_change_intensity(s->description, s->color, + s->intensity_percent, intensity_percent); + } + s->intensity_percent = intensity_percent; +} + +unsigned led_get_intensity(LEDState *s) +{ + return s->intensity_percent; +} + +void led_set_state(LEDState *s, bool is_emitting) +{ + led_set_intensity(s, is_emitting ? LED_INTENSITY_PERCENT_MAX : 0); +} + +static void led_set_state_gpio_handler(void *opaque, int line, int new_state) +{ + LEDState *s = LED(opaque); + + assert(line == 0); + led_set_state(s, !!new_state != s->gpio_active_high); +} + +static void led_reset(DeviceState *dev) +{ + LEDState *s = LED(dev); + + led_set_state(s, s->gpio_active_high); +} + +static const VMStateDescription vmstate_led = { + .name = TYPE_LED, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8(intensity_percent, LEDState), + VMSTATE_END_OF_LIST() + } +}; + +static void led_realize(DeviceState *dev, Error **errp) +{ + LEDState *s = LED(dev); + + if (s->color == NULL) { + error_setg(errp, "property 'color' not specified"); + return; + } else if (!led_color_name_is_valid(s->color)) { + error_setg(errp, "property 'color' invalid or not supported"); + return; + } + if (s->description == NULL) { + s->description = g_strdup("n/a"); + } + + qdev_init_gpio_in(DEVICE(s), led_set_state_gpio_handler, 1); +} + +static Property led_properties[] = { + DEFINE_PROP_STRING("color", LEDState, color), + DEFINE_PROP_STRING("description", LEDState, description), + DEFINE_PROP_BOOL("gpio-active-high", LEDState, gpio_active_high, true), + DEFINE_PROP_END_OF_LIST(), +}; + +static void led_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "LED"; + dc->vmsd = &vmstate_led; + dc->reset = led_reset; + dc->realize = led_realize; + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + device_class_set_props(dc, led_properties); +} + +static const TypeInfo led_info = { + .name = TYPE_LED, + .parent = TYPE_DEVICE, + .instance_size = sizeof(LEDState), + .class_init = led_class_init +}; + +static void led_register_types(void) +{ + type_register_static(&led_info); +} + +type_init(led_register_types) + +LEDState *led_create_simple(Object *parentobj, + GpioPolarity gpio_polarity, + LEDColor color, + const char *description) +{ + g_autofree char *name = NULL; + DeviceState *dev; + + dev = qdev_new(TYPE_LED); + qdev_prop_set_bit(dev, "gpio-active-high", + gpio_polarity == GPIO_POLARITY_ACTIVE_HIGH); + qdev_prop_set_string(dev, "color", led_color_name[color]); + if (!description) { + static unsigned undescribed_led_id; + name = g_strdup_printf("undescribed-led-#%u", undescribed_led_id++); + } else { + qdev_prop_set_string(dev, "description", description); + name = g_ascii_strdown(description, -1); + name = g_strdelimit(name, " #", '-'); + } + object_property_add_child(parentobj, name, OBJECT(dev)); + qdev_realize_and_unref(dev, NULL, &error_fatal); + + return LED(dev); +} diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c index e05623d73003ed8a713e7b882257157db3fe8d52..6db62dab7dbf598a4352411a5dab171a3d9308bb 100644 --- a/hw/misc/mac_via.c +++ b/hw/misc/mac_via.c @@ -328,7 +328,7 @@ static void via1_VBL(void *opaque) { MOS6522Q800VIA1State *v1s = opaque; MOS6522State *s = MOS6522(v1s); - MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s); + MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s); s->ifr |= VIA1_IRQ_VBLANK; mdc->update_irq(s); @@ -340,7 +340,7 @@ static void via1_one_second(void *opaque) { MOS6522Q800VIA1State *v1s = opaque; MOS6522State *s = MOS6522(v1s); - MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s); + MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s); s->ifr |= VIA1_IRQ_ONE_SECOND; mdc->update_irq(s); @@ -352,7 +352,7 @@ static void via1_irq_request(void *opaque, int irq, int level) { MOS6522Q800VIA1State *v1s = opaque; MOS6522State *s = MOS6522(v1s); - MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s); + MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s); if (level) { s->ifr |= 1 << irq; @@ -367,7 +367,7 @@ static void via2_irq_request(void *opaque, int irq, int level) { MOS6522Q800VIA2State *v2s = opaque; MOS6522State *s = MOS6522(v2s); - MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s); + MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s); if (level) { s->ifr |= 1 << irq; @@ -599,179 +599,310 @@ static void via1_rtc_update(MacVIAState *m) m->cmd = REG_EMPTY; } -static int adb_via_poll(MacVIAState *s, int state, uint8_t *data) +static void adb_via_poll(void *opaque) { - if (state != ADB_STATE_IDLE) { - return 0; - } + MacVIAState *m = opaque; + MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&m->mos6522_via1); + MOS6522State *s = MOS6522(v1s); + ADBBusState *adb_bus = &m->adb_bus; + uint8_t obuf[9]; + uint8_t *data = &s->sr; + int olen; + uint16_t pending; - if (s->adb_data_in_size < s->adb_data_in_index) { - return 0; - } + /* + * Setting vADBInt below indicates that an autopoll reply has been + * received, however we must block autopoll until the point where + * the entire reply has been read back to the host + */ + adb_autopoll_block(adb_bus); + + m->adb_data_in_index = 0; + m->adb_data_out_index = 0; + olen = adb_poll(adb_bus, obuf, adb_bus->autopoll_mask); + + if (olen > 0) { + /* Autopoll response */ + *data = obuf[0]; + olen--; + memcpy(m->adb_data_in, &obuf[1], olen); + m->adb_data_in_size = olen; + + s->b &= ~VIA1B_vADBInt; + qemu_irq_raise(m->adb_data_ready); + } else if (olen < 0) { + /* Bus timeout (device does not exist) */ + *data = 0xff; + s->b |= VIA1B_vADBInt; + adb_autopoll_unblock(adb_bus); + } else { + pending = adb_bus->pending & ~(1 << (m->adb_autopoll_cmd >> 4)); + + if (pending) { + /* + * Bus timeout (device exists but another device has data). Block + * autopoll so the OS can read out the first EVEN and first ODD + * byte to determine bus timeout and SRQ status + */ + *data = m->adb_autopoll_cmd; + s->b &= ~VIA1B_vADBInt; - if (s->adb_data_out_index != 0) { - return 0; - } + obuf[0] = 0xff; + obuf[1] = 0xff; + olen = 2; - s->adb_data_in_index = 0; - s->adb_data_out_index = 0; - s->adb_data_in_size = adb_poll(&s->adb_bus, s->adb_data_in, 0xffff); + memcpy(m->adb_data_in, obuf, olen); + m->adb_data_in_size = olen; - if (s->adb_data_in_size) { - *data = s->adb_data_in[s->adb_data_in_index++]; - qemu_irq_raise(s->adb_data_ready); + qemu_irq_raise(m->adb_data_ready); + } else { + /* Bus timeout (device exists but no other device has data) */ + *data = 0; + s->b |= VIA1B_vADBInt; + adb_autopoll_unblock(adb_bus); + } } - return s->adb_data_in_size; + trace_via1_adb_poll(*data, (s->b & VIA1B_vADBInt) ? "+" : "-", + adb_bus->status, m->adb_data_in_index, olen); } -static int adb_via_send(MacVIAState *s, int state, uint8_t data) +static int adb_via_send_len(uint8_t data) { - switch (state) { - case ADB_STATE_NEW: - s->adb_data_out_index = 0; - break; - case ADB_STATE_EVEN: - if ((s->adb_data_out_index & 1) == 0) { - return 0; - } - break; - case ADB_STATE_ODD: - if (s->adb_data_out_index & 1) { - return 0; + /* Determine the send length from the given ADB command */ + uint8_t cmd = data & 0xc; + uint8_t reg = data & 0x3; + + switch (cmd) { + case 0x8: + /* Listen command */ + switch (reg) { + case 2: + /* Register 2 is only used for the keyboard */ + return 3; + case 3: + /* + * Fortunately our devices only implement writes + * to register 3 which is fixed at 2 bytes + */ + return 3; + default: + qemu_log_mask(LOG_UNIMP, "ADB unknown length for register %d\n", + reg); + return 1; } - break; - case ADB_STATE_IDLE: - return 0; + default: + /* Talk, BusReset */ + return 1; } - - assert(s->adb_data_out_index < sizeof(s->adb_data_out) - 1); - - s->adb_data_out[s->adb_data_out_index++] = data; - qemu_irq_raise(s->adb_data_ready); - return 1; } -static int adb_via_receive(MacVIAState *s, int state, uint8_t *data) +static void adb_via_send(MacVIAState *s, int state, uint8_t data) { + MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&s->mos6522_via1); + MOS6522State *ms = MOS6522(v1s); + ADBBusState *adb_bus = &s->adb_bus; + uint16_t autopoll_mask; + switch (state) { case ADB_STATE_NEW: - return 0; - - case ADB_STATE_EVEN: - if (s->adb_data_in_size <= 0) { - qemu_irq_raise(s->adb_data_ready); - return 0; - } - - if (s->adb_data_in_index >= s->adb_data_in_size) { - *data = 0; - qemu_irq_raise(s->adb_data_ready); - return 1; - } - - if ((s->adb_data_in_index & 1) == 0) { - return 0; + /* + * Command byte: vADBInt tells host autopoll data already present + * in VIA shift register and ADB transceiver + */ + adb_autopoll_block(adb_bus); + + if (adb_bus->status & ADB_STATUS_POLLREPLY) { + /* Tell the host the existing data is from autopoll */ + ms->b &= ~VIA1B_vADBInt; + } else { + ms->b |= VIA1B_vADBInt; + s->adb_data_out_index = 0; + s->adb_data_out[s->adb_data_out_index++] = data; } + trace_via1_adb_send(" NEW", data, (ms->b & VIA1B_vADBInt) ? "+" : "-"); + qemu_irq_raise(s->adb_data_ready); break; + case ADB_STATE_EVEN: case ADB_STATE_ODD: - if (s->adb_data_in_size <= 0) { - qemu_irq_raise(s->adb_data_ready); - return 0; - } - - if (s->adb_data_in_index >= s->adb_data_in_size) { - *data = 0; - qemu_irq_raise(s->adb_data_ready); - return 1; - } - - if (s->adb_data_in_index & 1) { - return 0; - } + ms->b |= VIA1B_vADBInt; + s->adb_data_out[s->adb_data_out_index++] = data; + trace_via1_adb_send(state == ADB_STATE_EVEN ? "EVEN" : " ODD", + data, (ms->b & VIA1B_vADBInt) ? "+" : "-"); + qemu_irq_raise(s->adb_data_ready); break; case ADB_STATE_IDLE: - if (s->adb_data_out_index == 0) { - return 0; - } + return; + } - s->adb_data_in_size = adb_request(&s->adb_bus, s->adb_data_in, + /* If the command is complete, execute it */ + if (s->adb_data_out_index == adb_via_send_len(s->adb_data_out[0])) { + s->adb_data_in_size = adb_request(adb_bus, s->adb_data_in, s->adb_data_out, s->adb_data_out_index); - s->adb_data_out_index = 0; s->adb_data_in_index = 0; - if (s->adb_data_in_size < 0) { - *data = 0xff; - qemu_irq_raise(s->adb_data_ready); - return -1; - } - if (s->adb_data_in_size == 0) { - return 0; + if (adb_bus->status & ADB_STATUS_BUSTIMEOUT) { + /* + * Bus timeout (but allow first EVEN and ODD byte to indicate + * timeout via vADBInt and SRQ status) + */ + s->adb_data_in[0] = 0xff; + s->adb_data_in[1] = 0xff; + s->adb_data_in_size = 2; } - break; - } - - assert(s->adb_data_in_index < sizeof(s->adb_data_in) - 1); + /* + * If last command is TALK, store it for use by autopoll and adjust + * the autopoll mask accordingly + */ + if ((s->adb_data_out[0] & 0xc) == 0xc) { + s->adb_autopoll_cmd = s->adb_data_out[0]; - *data = s->adb_data_in[s->adb_data_in_index++]; - qemu_irq_raise(s->adb_data_ready); - if (*data == 0xff || *data == 0) { - return 0; + autopoll_mask = 1 << (s->adb_autopoll_cmd >> 4); + adb_set_autopoll_mask(adb_bus, autopoll_mask); + } } - return 1; } -static void via1_adb_update(MacVIAState *m) +static void adb_via_receive(MacVIAState *s, int state, uint8_t *data) { - MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&m->mos6522_via1); - MOS6522State *s = MOS6522(v1s); - int state; - int ret; + MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&s->mos6522_via1); + MOS6522State *ms = MOS6522(v1s); + ADBBusState *adb_bus = &s->adb_bus; + uint16_t pending; - state = (s->b & VIA1B_vADB_StateMask) >> VIA1B_vADB_StateShift; + switch (state) { + case ADB_STATE_NEW: + ms->b |= VIA1B_vADBInt; + return; - if (s->acr & VIA1ACR_vShiftOut) { - /* output mode */ - ret = adb_via_send(m, state, s->sr); - if (ret > 0) { - s->b &= ~VIA1B_vADBInt; + case ADB_STATE_IDLE: + /* + * Since adb_request() will have already consumed the data from the + * device, we must detect this extra state change and re-inject the + * reponse as either a "fake" autopoll reply or bus timeout + * accordingly + */ + if (s->adb_data_in_index == 0) { + if (adb_bus->status & ADB_STATUS_BUSTIMEOUT) { + *data = 0xff; + ms->b |= VIA1B_vADBInt; + qemu_irq_raise(s->adb_data_ready); + } else if (s->adb_data_in_size > 0) { + adb_bus->status = ADB_STATUS_POLLREPLY; + *data = s->adb_autopoll_cmd; + ms->b &= ~VIA1B_vADBInt; + qemu_irq_raise(s->adb_data_ready); + } } else { - s->b |= VIA1B_vADBInt; + ms->b |= VIA1B_vADBInt; + adb_autopoll_unblock(adb_bus); } - } else { - /* input mode */ - ret = adb_via_receive(m, state, &s->sr); - if (ret > 0 && s->sr != 0xff) { - s->b &= ~VIA1B_vADBInt; - } else { - s->b |= VIA1B_vADBInt; + + trace_via1_adb_receive("IDLE", *data, + (ms->b & VIA1B_vADBInt) ? "+" : "-", adb_bus->status, + s->adb_data_in_index, s->adb_data_in_size); + + break; + + case ADB_STATE_EVEN: + case ADB_STATE_ODD: + switch (s->adb_data_in_index) { + case 0: + /* First EVEN byte: vADBInt indicates bus timeout */ + trace_via1_adb_receive(state == ADB_STATE_EVEN ? "EVEN" : " ODD", + *data, (ms->b & VIA1B_vADBInt) ? "+" : "-", + adb_bus->status, s->adb_data_in_index, + s->adb_data_in_size); + + *data = s->adb_data_in[s->adb_data_in_index++]; + if (adb_bus->status & ADB_STATUS_BUSTIMEOUT) { + ms->b &= ~VIA1B_vADBInt; + } else { + ms->b |= VIA1B_vADBInt; + } + break; + + case 1: + /* First ODD byte: vADBInt indicates SRQ */ + trace_via1_adb_receive(state == ADB_STATE_EVEN ? "EVEN" : " ODD", + *data, (ms->b & VIA1B_vADBInt) ? "+" : "-", + adb_bus->status, s->adb_data_in_index, + s->adb_data_in_size); + + *data = s->adb_data_in[s->adb_data_in_index++]; + pending = adb_bus->pending & ~(1 << (s->adb_autopoll_cmd >> 4)); + if (pending) { + ms->b &= ~VIA1B_vADBInt; + } else { + ms->b |= VIA1B_vADBInt; + } + break; + + default: + /* + * Otherwise vADBInt indicates end of data. Note that Linux + * specifically checks for the sequence 0x0 0xff to confirm the + * end of the poll reply, so provide these extra bytes below to + * keep it happy + */ + trace_via1_adb_receive(state == ADB_STATE_EVEN ? "EVEN" : " ODD", + *data, (ms->b & VIA1B_vADBInt) ? "+" : "-", + adb_bus->status, s->adb_data_in_index, + s->adb_data_in_size); + + if (s->adb_data_in_index < s->adb_data_in_size) { + /* Next data byte */ + *data = s->adb_data_in[s->adb_data_in_index++]; + ms->b |= VIA1B_vADBInt; + } else if (s->adb_data_in_index == s->adb_data_in_size) { + if (adb_bus->status & ADB_STATUS_BUSTIMEOUT) { + /* Bus timeout (no more data) */ + *data = 0xff; + } else { + /* Return 0x0 after reply */ + *data = 0; + } + s->adb_data_in_index++; + ms->b &= ~VIA1B_vADBInt; + } else { + /* Bus timeout (no more data) */ + *data = 0xff; + ms->b &= ~VIA1B_vADBInt; + adb_bus->status = 0; + adb_autopoll_unblock(adb_bus); + } + break; } + + qemu_irq_raise(s->adb_data_ready); + break; } } -static void via_adb_poll(void *opaque) +static void via1_adb_update(MacVIAState *m) { - MacVIAState *m = opaque; MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&m->mos6522_via1); MOS6522State *s = MOS6522(v1s); - int state; + int oldstate, state; - if (s->b & VIA1B_vADBInt) { - state = (s->b & VIA1B_vADB_StateMask) >> VIA1B_vADB_StateShift; - if (adb_via_poll(m, state, &s->sr)) { - s->b &= ~VIA1B_vADBInt; + oldstate = (v1s->last_b & VIA1B_vADB_StateMask) >> VIA1B_vADB_StateShift; + state = (s->b & VIA1B_vADB_StateMask) >> VIA1B_vADB_StateShift; + + if (state != oldstate) { + if (s->acr & VIA1ACR_vShiftOut) { + /* output mode */ + adb_via_send(m, state, s->sr); + } else { + /* input mode */ + adb_via_receive(m, state, &s->sr); } } - - timer_mod(m->adb_poll_timer, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - (NANOSECONDS_PER_SECOND / VIA_ADB_POLL_FREQ)); } static uint64_t mos6522_q800_via1_read(void *opaque, hwaddr addr, unsigned size) @@ -802,11 +933,21 @@ static void mos6522_q800_via1_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(opaque); + MacVIAState *m = container_of(v1s, MacVIAState, mos6522_via1); MOS6522State *ms = MOS6522(v1s); addr = (addr >> 9) & 0xf; mos6522_write(ms, addr, val, size); + switch (addr) { + case VIA_REG_B: + via1_rtc_update(m); + via1_adb_update(m); + + v1s->last_b = ms->b; + break; + } + via1_one_second_update(v1s); via1_VBL_update(v1s); } @@ -854,10 +995,9 @@ static void mac_via_reset(DeviceState *dev) { MacVIAState *m = MAC_VIA(dev); MOS6522Q800VIA1State *v1s = &m->mos6522_via1; + ADBBusState *adb_bus = &m->adb_bus; - timer_mod(m->adb_poll_timer, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - (NANOSECONDS_PER_SECOND / VIA_ADB_POLL_FREQ)); + adb_set_autopoll_enabled(adb_bus, true); timer_del(v1s->VBL_timer); v1s->next_VBL = 0; @@ -872,15 +1012,16 @@ static void mac_via_realize(DeviceState *dev, Error **errp) { MacVIAState *m = MAC_VIA(dev); MOS6522State *ms; + ADBBusState *adb_bus = &m->adb_bus; struct tm tm; int ret; /* Init VIAs 1 and 2 */ - sysbus_init_child_obj(OBJECT(dev), "via1", &m->mos6522_via1, - sizeof(m->mos6522_via1), TYPE_MOS6522_Q800_VIA1); + object_initialize_child(OBJECT(dev), "via1", &m->mos6522_via1, + TYPE_MOS6522_Q800_VIA1); - sysbus_init_child_obj(OBJECT(dev), "via2", &m->mos6522_via2, - sizeof(m->mos6522_via2), TYPE_MOS6522_Q800_VIA2); + object_initialize_child(OBJECT(dev), "via2", &m->mos6522_via2, + TYPE_MOS6522_Q800_VIA2); /* Pass through mos6522 output IRQs */ ms = MOS6522(&m->mos6522_via1); @@ -890,6 +1031,9 @@ static void mac_via_realize(DeviceState *dev, Error **errp) object_property_add_alias(OBJECT(dev), "irq[1]", OBJECT(ms), SYSBUS_DEVICE_GPIO_IRQ "[0]"); + sysbus_realize(SYS_BUS_DEVICE(&m->mos6522_via1), &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&m->mos6522_via2), &error_abort); + /* Pass through mos6522 input IRQs */ qdev_pass_gpios(DEVICE(&m->mos6522_via1), dev, "via1-irq"); qdev_pass_gpios(DEVICE(&m->mos6522_via2), dev, "via2-irq"); @@ -904,7 +1048,7 @@ static void mac_via_realize(DeviceState *dev, Error **errp) qemu_get_timedate(&tm, 0); m->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET; - m->adb_poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, via_adb_poll, m); + adb_register_autopoll_callback(adb_bus, adb_via_poll, m); m->adb_data_ready = qdev_get_gpio_in_named(dev, "via1-irq", VIA1_IRQ_ADB_READY_BIT); @@ -977,8 +1121,8 @@ static int mac_via_post_load(void *opaque, int version_id) static const VMStateDescription vmstate_mac_via = { .name = "mac-via", - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .post_load = mac_via_post_load, .fields = (VMStateField[]) { /* VIAs */ @@ -1002,12 +1146,12 @@ static const VMStateDescription vmstate_mac_via = { VMSTATE_INT32(wprotect, MacVIAState), VMSTATE_INT32(alt, MacVIAState), /* ADB */ - VMSTATE_TIMER_PTR(adb_poll_timer, MacVIAState), VMSTATE_INT32(adb_data_in_size, MacVIAState), VMSTATE_INT32(adb_data_in_index, MacVIAState), VMSTATE_INT32(adb_data_out_index, MacVIAState), VMSTATE_BUFFER(adb_data_in, MacVIAState), VMSTATE_BUFFER(adb_data_out, MacVIAState), + VMSTATE_UINT8(adb_autopoll_cmd, MacVIAState), VMSTATE_END_OF_LIST() } }; @@ -1036,22 +1180,10 @@ static TypeInfo mac_via_info = { }; /* VIA 1 */ -static void mos6522_q800_via1_portB_write(MOS6522State *s) -{ - MOS6522Q800VIA1State *v1s = container_of(s, MOS6522Q800VIA1State, - parent_obj); - MacVIAState *m = container_of(v1s, MacVIAState, mos6522_via1); - - via1_rtc_update(m); - via1_adb_update(m); - - v1s->last_b = s->b; -} - static void mos6522_q800_via1_reset(DeviceState *dev) { MOS6522State *ms = MOS6522(dev); - MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms); + MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(ms); mdc->parent_reset(dev); @@ -1070,10 +1202,8 @@ static void mos6522_q800_via1_init(Object *obj) static void mos6522_q800_via1_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); - MOS6522DeviceClass *mdc = MOS6522_DEVICE_CLASS(oc); dc->reset = mos6522_q800_via1_reset; - mdc->portB_write = mos6522_q800_via1_portB_write; } static const TypeInfo mos6522_q800_via1_type_info = { @@ -1096,7 +1226,7 @@ static void mos6522_q800_via2_portB_write(MOS6522State *s) static void mos6522_q800_via2_reset(DeviceState *dev) { MOS6522State *ms = MOS6522(dev); - MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms); + MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(ms); mdc->parent_reset(dev); @@ -1116,7 +1246,7 @@ static void mos6522_q800_via2_init(Object *obj) static void mos6522_q800_via2_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); - MOS6522DeviceClass *mdc = MOS6522_DEVICE_CLASS(oc); + MOS6522DeviceClass *mdc = MOS6522_CLASS(oc); dc->reset = mos6522_q800_via2_reset; mdc->portB_write = mos6522_q800_via2_portB_write; diff --git a/hw/misc/macio/Makefile.objs b/hw/misc/macio/Makefile.objs deleted file mode 100644 index 07fdb320d40ca374d3cc58f4f645ab2984c6a47d..0000000000000000000000000000000000000000 --- a/hw/misc/macio/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -common-obj-y += macio.o -common-obj-$(CONFIG_CUDA) += cuda.o -common-obj-$(CONFIG_MAC_PMU) += pmu.o -common-obj-$(CONFIG_MAC_DBDMA) += mac_dbdma.o -common-obj-$(CONFIG_MACIO_GPIO) += gpio.o diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c index e0cc0aac5df30975863b8cc74aab57a4daeac6cb..edbd4186b2a5ea1cf7e57d5268cf39eaba9fb40a 100644 --- a/hw/misc/macio/cuda.c +++ b/hw/misc/macio/cuda.c @@ -31,8 +31,10 @@ #include "hw/input/adb.h" #include "hw/misc/mos6522.h" #include "hw/misc/macio/cuda.h" +#include "qapi/error.h" #include "qemu/timer.h" #include "sysemu/runstate.h" +#include "qapi/error.h" #include "qemu/cutils.h" #include "qemu/log.h" #include "qemu/module.h" @@ -94,7 +96,7 @@ static void cuda_set_sr_int(void *opaque) CUDAState *s = opaque; MOS6522CUDAState *mcs = &s->mos6522_cuda; MOS6522State *ms = MOS6522(mcs); - MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms); + MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(ms); mdc->set_sr_int(ms); } @@ -114,6 +116,7 @@ static void cuda_update(CUDAState *s) { MOS6522CUDAState *mcs = &s->mos6522_cuda; MOS6522State *ms = MOS6522(mcs); + ADBBusState *adb_bus = &s->adb_bus; int packet_received, len; packet_received = 0; @@ -124,6 +127,9 @@ static void cuda_update(CUDAState *s) /* data output */ if ((ms->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) { if (s->data_out_index < sizeof(s->data_out)) { + if (s->data_out_index == 0) { + adb_autopoll_block(adb_bus); + } trace_cuda_data_send(ms->sr); s->data_out[s->data_out_index++] = ms->sr; cuda_delay_set_sr_int(s); @@ -138,6 +144,7 @@ static void cuda_update(CUDAState *s) /* indicate end of transfer */ if (s->data_in_index >= s->data_in_size) { ms->b = (ms->b | TREQ); + adb_autopoll_unblock(adb_bus); } cuda_delay_set_sr_int(s); } @@ -199,17 +206,16 @@ static void cuda_send_packet_to_host(CUDAState *s, static void cuda_adb_poll(void *opaque) { CUDAState *s = opaque; + ADBBusState *adb_bus = &s->adb_bus; uint8_t obuf[ADB_MAX_OUT_LEN + 2]; int olen; - olen = adb_poll(&s->adb_bus, obuf + 2, s->adb_poll_mask); + olen = adb_poll(adb_bus, obuf + 2, adb_bus->autopoll_mask); if (olen > 0) { obuf[0] = ADB_PACKET; obuf[1] = 0x40; /* polled data */ cuda_send_packet_to_host(s, obuf, olen + 2); } - timer_mod(s->adb_poll_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - (NANOSECONDS_PER_SECOND / (1000 / s->autopoll_rate_ms))); } /* description of commands */ @@ -225,23 +231,16 @@ static bool cuda_cmd_autopoll(CUDAState *s, const uint8_t *in_data, int in_len, uint8_t *out_data, int *out_len) { - int autopoll; + ADBBusState *adb_bus = &s->adb_bus; + bool autopoll; if (in_len != 1) { return false; } - autopoll = (in_data[0] != 0); - if (autopoll != s->autopoll) { - s->autopoll = autopoll; - if (autopoll) { - timer_mod(s->adb_poll_timer, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - (NANOSECONDS_PER_SECOND / (1000 / s->autopoll_rate_ms))); - } else { - timer_del(s->adb_poll_timer); - } - } + autopoll = (in_data[0] != 0) ? true : false; + + adb_set_autopoll_enabled(adb_bus, autopoll); return true; } @@ -249,6 +248,8 @@ static bool cuda_cmd_set_autorate(CUDAState *s, const uint8_t *in_data, int in_len, uint8_t *out_data, int *out_len) { + ADBBusState *adb_bus = &s->adb_bus; + if (in_len != 1) { return false; } @@ -259,12 +260,7 @@ static bool cuda_cmd_set_autorate(CUDAState *s, return false; } - s->autopoll_rate_ms = in_data[0]; - if (s->autopoll) { - timer_mod(s->adb_poll_timer, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - (NANOSECONDS_PER_SECOND / (1000 / s->autopoll_rate_ms))); - } + adb_set_autopoll_rate_ms(adb_bus, in_data[0]); return true; } @@ -272,11 +268,16 @@ static bool cuda_cmd_set_device_list(CUDAState *s, const uint8_t *in_data, int in_len, uint8_t *out_data, int *out_len) { + ADBBusState *adb_bus = &s->adb_bus; + uint16_t mask; + if (in_len != 2) { return false; } - s->adb_poll_mask = (((uint16_t)in_data[0]) << 8) | in_data[1]; + mask = (((uint16_t)in_data[0]) << 8) | in_data[1]; + + adb_set_autopoll_mask(adb_bus, mask); return true; } @@ -487,8 +488,8 @@ static const MemoryRegionOps mos6522_cuda_ops = { static const VMStateDescription vmstate_cuda = { .name = "cuda", - .version_id = 5, - .minimum_version_id = 5, + .version_id = 6, + .minimum_version_id = 6, .fields = (VMStateField[]) { VMSTATE_STRUCT(mos6522_cuda.parent_obj, CUDAState, 0, vmstate_mos6522, MOS6522State), @@ -497,13 +498,9 @@ static const VMStateDescription vmstate_cuda = { VMSTATE_INT32(data_in_size, CUDAState), VMSTATE_INT32(data_in_index, CUDAState), VMSTATE_INT32(data_out_index, CUDAState), - VMSTATE_UINT8(autopoll, CUDAState), - VMSTATE_UINT8(autopoll_rate_ms, CUDAState), - VMSTATE_UINT16(adb_poll_mask, CUDAState), VMSTATE_BUFFER(data_in, CUDAState), VMSTATE_BUFFER(data_out, CUDAState), VMSTATE_UINT32(tick_offset, CUDAState), - VMSTATE_TIMER_PTR(adb_poll_timer, CUDAState), VMSTATE_TIMER_PTR(sr_delay_timer, CUDAState), VMSTATE_END_OF_LIST() } @@ -512,26 +509,29 @@ static const VMStateDescription vmstate_cuda = { static void cuda_reset(DeviceState *dev) { CUDAState *s = CUDA(dev); + ADBBusState *adb_bus = &s->adb_bus; s->data_in_size = 0; s->data_in_index = 0; s->data_out_index = 0; - s->autopoll = 0; + + adb_set_autopoll_enabled(adb_bus, false); } static void cuda_realize(DeviceState *dev, Error **errp) { CUDAState *s = CUDA(dev); SysBusDevice *sbd; - MOS6522State *ms; - DeviceState *d; + ADBBusState *adb_bus = &s->adb_bus; struct tm tm; + if (!sysbus_realize(SYS_BUS_DEVICE(&s->mos6522_cuda), errp)) { + return; + } + /* Pass IRQ from 6522 */ - d = DEVICE(&s->mos6522_cuda); - ms = MOS6522(d); sbd = SYS_BUS_DEVICE(s); - sysbus_pass_irq(sbd, SYS_BUS_DEVICE(ms)); + sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->mos6522_cuda)); qemu_get_timedate(&tm, 0); s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET; @@ -539,9 +539,7 @@ static void cuda_realize(DeviceState *dev, Error **errp) s->sr_delay_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_set_sr_int, s); s->sr_delay_ns = 20 * SCALE_US; - s->adb_poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_adb_poll, s); - s->adb_poll_mask = 0xffff; - s->autopoll_rate_ms = 20; + adb_register_autopoll_callback(adb_bus, cuda_adb_poll, s); } static void cuda_init(Object *obj) @@ -549,8 +547,8 @@ static void cuda_init(Object *obj) CUDAState *s = CUDA(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - sysbus_init_child_obj(obj, "mos6522-cuda", &s->mos6522_cuda, - sizeof(s->mos6522_cuda), TYPE_MOS6522_CUDA); + object_initialize_child(obj, "mos6522-cuda", &s->mos6522_cuda, + TYPE_MOS6522_CUDA); memory_region_init_io(&s->mem, obj, &mos6522_cuda_ops, s, "cuda", 0x2000); sysbus_init_mmio(sbd, &s->mem); @@ -594,7 +592,7 @@ static void mos6522_cuda_portB_write(MOS6522State *s) static void mos6522_cuda_reset(DeviceState *dev) { MOS6522State *ms = MOS6522(dev); - MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms); + MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(ms); mdc->parent_reset(dev); @@ -605,7 +603,7 @@ static void mos6522_cuda_reset(DeviceState *dev) static void mos6522_cuda_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); - MOS6522DeviceClass *mdc = MOS6522_DEVICE_CLASS(oc); + MOS6522DeviceClass *mdc = MOS6522_CLASS(oc); dc->reset = mos6522_cuda_reset; mdc->portB_write = mos6522_cuda_portB_write; diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c index 3779865ab29df12f1d4cf4dd9e9c54b4570521bd..bb601f782c7296aed070a6011bd80761ad7d2ad3 100644 --- a/hw/misc/macio/macio.c +++ b/hw/misc/macio/macio.c @@ -94,24 +94,12 @@ static void macio_bar_setup(MacIOState *s) macio_escc_legacy_setup(s); } -static void macio_init_child_obj(MacIOState *s, const char *childname, - void *child, size_t childsize, - const char *childtype) -{ - object_initialize_child(OBJECT(s), childname, child, childsize, childtype, - &error_abort, NULL); - qdev_set_parent_bus(DEVICE(child), BUS(&s->macio_bus)); -} - static void macio_common_realize(PCIDevice *d, Error **errp) { MacIOState *s = MACIO(d); SysBusDevice *sysbus_dev; - Error *err = NULL; - object_property_set_bool(OBJECT(&s->dbdma), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->dbdma), BUS(&s->macio_bus), errp)) { return; } sysbus_dev = SYS_BUS_DEVICE(&s->dbdma); @@ -121,13 +109,9 @@ static void macio_common_realize(PCIDevice *d, Error **errp) qdev_prop_set_uint32(DEVICE(&s->escc), "disabled", 0); qdev_prop_set_uint32(DEVICE(&s->escc), "frequency", ESCC_CLOCK); qdev_prop_set_uint32(DEVICE(&s->escc), "it_shift", 4); - qdev_prop_set_chr(DEVICE(&s->escc), "chrA", serial_hd(0)); - qdev_prop_set_chr(DEVICE(&s->escc), "chrB", serial_hd(1)); qdev_prop_set_uint32(DEVICE(&s->escc), "chnBtype", escc_serial); qdev_prop_set_uint32(DEVICE(&s->escc), "chnAtype", escc_serial); - object_property_set_bool(OBJECT(&s->escc), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->escc), BUS(&s->macio_bus), errp)) { return; } @@ -145,10 +129,11 @@ static void macio_realize_ide(MacIOState *s, MACIOIDEState *ide, sysbus_connect_irq(sysbus_dev, 0, irq0); sysbus_connect_irq(sysbus_dev, 1, irq1); qdev_prop_set_uint32(DEVICE(ide), "channel", dmaid); - object_property_set_link(OBJECT(ide), OBJECT(&s->dbdma), "dbdma", errp); + object_property_set_link(OBJECT(ide), "dbdma", OBJECT(&s->dbdma), + &error_abort); macio_ide_register_dma(ide); - object_property_set_bool(OBJECT(ide), true, "realized", errp); + qdev_realize(DEVICE(ide), BUS(&s->macio_bus), errp); } static void macio_oldworld_realize(PCIDevice *d, Error **errp) @@ -167,9 +152,7 @@ static void macio_oldworld_realize(PCIDevice *d, Error **errp) qdev_prop_set_uint64(DEVICE(&s->cuda), "timebase-frequency", s->frequency); - object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->cuda), BUS(&s->macio_bus), errp)) { return; } sysbus_dev = SYS_BUS_DEVICE(&s->cuda); @@ -184,9 +167,7 @@ static void macio_oldworld_realize(PCIDevice *d, Error **errp) sysbus_connect_irq(sysbus_dev, 1, qdev_get_gpio_in(pic_dev, OLDWORLD_ESCCA_IRQ)); - object_property_set_bool(OBJECT(&os->nvram), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&os->nvram), BUS(&s->macio_bus), errp)) { return; } sysbus_dev = SYS_BUS_DEVICE(&os->nvram); @@ -219,13 +200,12 @@ static void macio_oldworld_realize(PCIDevice *d, Error **errp) } } -static void macio_init_ide(MacIOState *s, MACIOIDEState *ide, size_t ide_size, - int index) +static void macio_init_ide(MacIOState *s, MACIOIDEState *ide, int index) { gchar *name = g_strdup_printf("ide[%i]", index); uint32_t addr = 0x1f000 + ((index + 1) * 0x1000); - macio_init_child_obj(s, name, ide, ide_size, TYPE_MACIO_IDE); + object_initialize_child(OBJECT(s), name, ide, TYPE_MACIO_IDE); qdev_prop_set_uint32(DEVICE(ide), "addr", addr); memory_region_add_subregion(&s->bar, addr, &ide->mem); g_free(name); @@ -243,15 +223,15 @@ static void macio_oldworld_init(Object *obj) qdev_prop_allow_set_link_before_realize, 0); - macio_init_child_obj(s, "cuda", &s->cuda, sizeof(s->cuda), TYPE_CUDA); + object_initialize_child(OBJECT(s), "cuda", &s->cuda, TYPE_CUDA); - object_initialize(&os->nvram, sizeof(os->nvram), TYPE_MACIO_NVRAM); + object_initialize_child(OBJECT(s), "nvram", &os->nvram, TYPE_MACIO_NVRAM); dev = DEVICE(&os->nvram); qdev_prop_set_uint32(dev, "size", 0x2000); qdev_prop_set_uint32(dev, "it_shift", 4); for (i = 0; i < 2; i++) { - macio_init_ide(s, &os->ide[i], sizeof(os->ide[i]), i); + macio_init_ide(s, &os->ide[i], i); } } @@ -343,23 +323,20 @@ static void macio_newworld_realize(PCIDevice *d, Error **errp) if (ns->has_pmu) { /* GPIOs */ sysbus_dev = SYS_BUS_DEVICE(&ns->gpio); - object_property_set_link(OBJECT(&ns->gpio), OBJECT(pic_dev), "pic", + object_property_set_link(OBJECT(&ns->gpio), "pic", OBJECT(pic_dev), &error_abort); memory_region_add_subregion(&s->bar, 0x50, sysbus_mmio_get_region(sysbus_dev, 0)); - object_property_set_bool(OBJECT(&ns->gpio), true, "realized", &err); + if (!qdev_realize(DEVICE(&ns->gpio), BUS(&s->macio_bus), errp)) { + return; + } /* PMU */ - object_initialize_child(OBJECT(s), "pmu", &s->pmu, sizeof(s->pmu), - TYPE_VIA_PMU, &error_abort, NULL); - object_property_set_link(OBJECT(&s->pmu), OBJECT(sysbus_dev), "gpio", + object_initialize_child(OBJECT(s), "pmu", &s->pmu, TYPE_VIA_PMU); + object_property_set_link(OBJECT(&s->pmu), "gpio", OBJECT(sysbus_dev), &error_abort); qdev_prop_set_bit(DEVICE(&s->pmu), "has-adb", ns->has_adb); - qdev_set_parent_bus(DEVICE(&s->pmu), BUS(&s->macio_bus)); - - object_property_set_bool(OBJECT(&s->pmu), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->pmu), BUS(&s->macio_bus), errp)) { return; } sysbus_dev = SYS_BUS_DEVICE(&s->pmu); @@ -368,16 +345,14 @@ static void macio_newworld_realize(PCIDevice *d, Error **errp) memory_region_add_subregion(&s->bar, 0x16000, sysbus_mmio_get_region(sysbus_dev, 0)); } else { + object_unparent(OBJECT(&ns->gpio)); + /* CUDA */ - object_initialize_child(OBJECT(s), "cuda", &s->cuda, sizeof(s->cuda), - TYPE_CUDA, &error_abort, NULL); - qdev_set_parent_bus(DEVICE(&s->cuda), BUS(&s->macio_bus)); + object_initialize_child(OBJECT(s), "cuda", &s->cuda, TYPE_CUDA); qdev_prop_set_uint64(DEVICE(&s->cuda), "timebase-frequency", s->frequency); - object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(&s->cuda), BUS(&s->macio_bus), errp)) { return; } sysbus_dev = SYS_BUS_DEVICE(&s->cuda); @@ -399,11 +374,10 @@ static void macio_newworld_init(Object *obj) qdev_prop_allow_set_link_before_realize, 0); - macio_init_child_obj(s, "gpio", &ns->gpio, sizeof(ns->gpio), - TYPE_MACIO_GPIO); + object_initialize_child(OBJECT(s), "gpio", &ns->gpio, TYPE_MACIO_GPIO); for (i = 0; i < 2; i++) { - macio_init_ide(s, &ns->ide[i], sizeof(ns->ide[i]), i); + macio_init_ide(s, &ns->ide[i], i); } } @@ -416,10 +390,9 @@ static void macio_instance_init(Object *obj) qbus_create_inplace(&s->macio_bus, sizeof(s->macio_bus), TYPE_MACIO_BUS, DEVICE(obj), "macio.0"); - macio_init_child_obj(s, "dbdma", &s->dbdma, sizeof(s->dbdma), - TYPE_MAC_DBDMA); + object_initialize_child(OBJECT(s), "dbdma", &s->dbdma, TYPE_MAC_DBDMA); - macio_init_child_obj(s, "escc", &s->escc, sizeof(s->escc), TYPE_ESCC); + object_initialize_child(OBJECT(s), "escc", &s->escc, TYPE_ESCC); } static const VMStateDescription vmstate_macio_oldworld = { @@ -483,13 +456,13 @@ static void macio_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_OTHERS << 8; device_class_set_props(dc, macio_properties); set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - /* Reason: Uses serial_hds in macio_instance_init */ + /* Reason: requires PIC property links to be set in macio_*_realize() */ dc->user_creatable = false; } static const TypeInfo macio_bus_info = { .name = TYPE_MACIO_BUS, - .parent = TYPE_BUS, + .parent = TYPE_SYSTEM_BUS, .instance_size = sizeof(MacIOBusState), }; diff --git a/hw/misc/macio/meson.build b/hw/misc/macio/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..17282da20a66d3568b1fd92ad8e83d319e9d568b --- /dev/null +++ b/hw/misc/macio/meson.build @@ -0,0 +1,8 @@ +macio_ss = ss.source_set() +macio_ss.add(files('macio.c')) +macio_ss.add(when: 'CONFIG_CUDA', if_true: files('cuda.c')) +macio_ss.add(when: 'CONFIG_MACIO_GPIO', if_true: files('gpio.c')) +macio_ss.add(when: 'CONFIG_MAC_DBDMA', if_true: files('mac_dbdma.c')) +macio_ss.add(when: 'CONFIG_MAC_PMU', if_true: files('pmu.c')) + +softmmu_ss.add_all(when: 'CONFIG_MACIO', if_true: macio_ss) diff --git a/hw/misc/macio/pmu.c b/hw/misc/macio/pmu.c index 9a9cd427e1b2e256d1b6907522452f508c85812d..71924d4768c821aea5e523546448d3e1d6023cb3 100644 --- a/hw/misc/macio/pmu.c +++ b/hw/misc/macio/pmu.c @@ -38,8 +38,10 @@ #include "hw/misc/mos6522.h" #include "hw/misc/macio/gpio.h" #include "hw/misc/macio/pmu.h" +#include "qapi/error.h" #include "qemu/timer.h" #include "sysemu/runstate.h" +#include "qapi/error.h" #include "qemu/cutils.h" #include "qemu/log.h" #include "qemu/module.h" @@ -73,7 +75,7 @@ static void via_set_sr_int(void *opaque) PMUState *s = opaque; MOS6522PMUState *mps = MOS6522_PMU(&s->mos6522_pmu); MOS6522State *ms = MOS6522(mps); - MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms); + MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(ms); mdc->set_sr_int(ms); } @@ -90,10 +92,11 @@ static void pmu_update_extirq(PMUState *s) static void pmu_adb_poll(void *opaque) { PMUState *s = opaque; + ADBBusState *adb_bus = &s->adb_bus; int olen; if (!(s->intbits & PMU_INT_ADB)) { - olen = adb_poll(&s->adb_bus, s->adb_reply, s->adb_poll_mask); + olen = adb_poll(adb_bus, s->adb_reply, adb_bus->autopoll_mask); trace_pmu_adb_poll(olen); if (olen > 0) { @@ -102,9 +105,6 @@ static void pmu_adb_poll(void *opaque) pmu_update_extirq(s); } } - - timer_mod(s->adb_poll_timer, - qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 30); } static void pmu_one_sec_timer(void *opaque) @@ -171,18 +171,15 @@ static void pmu_cmd_set_int_mask(PMUState *s, static void pmu_cmd_set_adb_autopoll(PMUState *s, uint16_t mask) { - trace_pmu_cmd_set_adb_autopoll(mask); + ADBBusState *adb_bus = &s->adb_bus; - if (s->autopoll_mask == mask) { - return; - } + trace_pmu_cmd_set_adb_autopoll(mask); - s->autopoll_mask = mask; if (mask) { - timer_mod(s->adb_poll_timer, - qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 30); + adb_set_autopoll_mask(adb_bus, mask); + adb_set_autopoll_enabled(adb_bus, true); } else { - timer_del(s->adb_poll_timer); + adb_set_autopoll_enabled(adb_bus, false); } } @@ -265,6 +262,8 @@ static void pmu_cmd_adb_poll_off(PMUState *s, const uint8_t *in_data, uint8_t in_len, uint8_t *out_data, uint8_t *out_len) { + ADBBusState *adb_bus = &s->adb_bus; + if (in_len != 0) { qemu_log_mask(LOG_GUEST_ERROR, "PMU: ADB POLL OFF command, invalid len: %d want: 0\n", @@ -272,9 +271,8 @@ static void pmu_cmd_adb_poll_off(PMUState *s, return; } - if (s->has_adb && s->autopoll_mask) { - timer_del(s->adb_poll_timer); - s->autopoll_mask = false; + if (s->has_adb) { + adb_set_autopoll_enabled(adb_bus, false); } } @@ -519,6 +517,7 @@ static void pmu_update(PMUState *s) { MOS6522PMUState *mps = &s->mos6522_pmu; MOS6522State *ms = MOS6522(mps); + ADBBusState *adb_bus = &s->adb_bus; /* Only react to changes in reg B */ if (ms->b == s->last_b) { @@ -580,6 +579,7 @@ static void pmu_update(PMUState *s) s->cmd_rsp_pos = 0; s->cmd_state = pmu_state_cmd; + adb_autopoll_block(adb_bus); trace_pmu_debug_protocol_cmd(s->cmd, s->cmdlen, s->rsplen); break; @@ -638,6 +638,7 @@ static void pmu_update(PMUState *s) if (s->cmd_state == pmu_state_rsp && s->rsplen == s->cmd_rsp_pos) { trace_pmu_debug_protocol_cmd_resp_complete(ms->ier); + adb_autopoll_unblock(adb_bus); s->cmd_state = pmu_state_idle; } } @@ -682,12 +683,10 @@ static bool pmu_adb_state_needed(void *opaque) static const VMStateDescription vmstate_pmu_adb = { .name = "pmu/adb", - .version_id = 0, - .minimum_version_id = 0, + .version_id = 1, + .minimum_version_id = 1, .needed = pmu_adb_state_needed, .fields = (VMStateField[]) { - VMSTATE_UINT16(adb_poll_mask, PMUState), - VMSTATE_TIMER_PTR(adb_poll_timer, PMUState), VMSTATE_UINT8(adb_reply_size, PMUState), VMSTATE_BUFFER(adb_reply, PMUState), VMSTATE_END_OF_LIST() @@ -696,8 +695,8 @@ static const VMStateDescription vmstate_pmu_adb = { static const VMStateDescription vmstate_pmu = { .name = "pmu", - .version_id = 0, - .minimum_version_id = 0, + .version_id = 1, + .minimum_version_id = 1, .fields = (VMStateField[]) { VMSTATE_STRUCT(mos6522_pmu.parent_obj, PMUState, 0, vmstate_mos6522, MOS6522State), @@ -712,8 +711,6 @@ static const VMStateDescription vmstate_pmu = { VMSTATE_BUFFER(cmd_rsp, PMUState), VMSTATE_UINT8(intbits, PMUState), VMSTATE_UINT8(intmask, PMUState), - VMSTATE_UINT8(autopoll_rate_ms, PMUState), - VMSTATE_UINT8(autopoll_mask, PMUState), VMSTATE_UINT32(tick_offset, PMUState), VMSTATE_TIMER_PTR(one_sec_timer, PMUState), VMSTATE_INT64(one_sec_target, PMUState), @@ -733,22 +730,22 @@ static void pmu_reset(DeviceState *dev) s->intbits = 0; s->cmd_state = pmu_state_idle; - s->autopoll_mask = 0; } static void pmu_realize(DeviceState *dev, Error **errp) { PMUState *s = VIA_PMU(dev); SysBusDevice *sbd; - MOS6522State *ms; - DeviceState *d; + ADBBusState *adb_bus = &s->adb_bus; struct tm tm; + if (!sysbus_realize(SYS_BUS_DEVICE(&s->mos6522_pmu), errp)) { + return; + } + /* Pass IRQ from 6522 */ - d = DEVICE(&s->mos6522_pmu); - ms = MOS6522(d); sbd = SYS_BUS_DEVICE(s); - sysbus_pass_irq(sbd, SYS_BUS_DEVICE(ms)); + sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->mos6522_pmu)); qemu_get_timedate(&tm, 0); s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET; @@ -759,9 +756,7 @@ static void pmu_realize(DeviceState *dev, Error **errp) if (s->has_adb) { qbus_create_inplace(&s->adb_bus, sizeof(s->adb_bus), TYPE_ADB_BUS, dev, "adb.0"); - s->adb_poll_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, pmu_adb_poll, s); - s->adb_poll_mask = 0xffff; - s->autopoll_rate_ms = 20; + adb_register_autopoll_callback(adb_bus, pmu_adb_poll, s); } } @@ -775,8 +770,8 @@ static void pmu_init(Object *obj) qdev_prop_allow_set_link_before_realize, 0); - sysbus_init_child_obj(obj, "mos6522-pmu", &s->mos6522_pmu, - sizeof(s->mos6522_pmu), TYPE_MOS6522_PMU); + object_initialize_child(obj, "mos6522-pmu", &s->mos6522_pmu, + TYPE_MOS6522_PMU); memory_region_init_io(&s->mem, obj, &mos6522_pmu_ops, s, "via-pmu", 0x2000); @@ -839,7 +834,7 @@ static void mos6522_pmu_reset(DeviceState *dev) MOS6522State *ms = MOS6522(dev); MOS6522PMUState *mps = container_of(ms, MOS6522PMUState, parent_obj); PMUState *s = container_of(mps, PMUState, mos6522_pmu); - MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms); + MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(ms); mdc->parent_reset(dev); @@ -852,7 +847,7 @@ static void mos6522_pmu_reset(DeviceState *dev) static void mos6522_pmu_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); - MOS6522DeviceClass *mdc = MOS6522_DEVICE_CLASS(oc); + MOS6522DeviceClass *mdc = MOS6522_CLASS(oc); dc->reset = mos6522_pmu_reset; mdc->portB_write = mos6522_pmu_portB_write; diff --git a/hw/misc/macio/trace.h b/hw/misc/macio/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..34a3cf1b42dd60ba2f2b93bc47e8a731dfea216d --- /dev/null +++ b/hw/misc/macio/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_misc_macio.h" diff --git a/hw/misc/max111x.c b/hw/misc/max111x.c index 2b87bdee5b76e29ceac74214a93664c0749e700e..eae0f9b598dc47ff8b331c0e28af1f920d29435e 100644 --- a/hw/misc/max111x.c +++ b/hw/misc/max111x.c @@ -11,29 +11,11 @@ */ #include "qemu/osdep.h" +#include "hw/misc/max111x.h" #include "hw/irq.h" -#include "hw/ssi/ssi.h" #include "migration/vmstate.h" #include "qemu/module.h" - -typedef struct { - SSISlave parent_obj; - - qemu_irq interrupt; - uint8_t tb1, rb2, rb3; - int cycle; - - uint8_t input[8]; - int inputs, com; -} MAX111xState; - -#define TYPE_MAX_111X "max111x" - -#define MAX_111X(obj) \ - OBJECT_CHECK(MAX111xState, (obj), TYPE_MAX_111X) - -#define TYPE_MAX_1110 "max1110" -#define TYPE_MAX_1111 "max1111" +#include "hw/qdev-properties.h" /* Control-byte bitfields */ #define CB_PD0 (1 << 0) @@ -127,27 +109,24 @@ static const VMStateDescription vmstate_max111x = { } }; +static void max111x_input_set(void *opaque, int line, int value) +{ + MAX111xState *s = MAX_111X(opaque); + + assert(line >= 0 && line < s->inputs); + s->input[line] = value; +} + static int max111x_init(SSISlave *d, int inputs) { DeviceState *dev = DEVICE(d); MAX111xState *s = MAX_111X(dev); qdev_init_gpio_out(dev, &s->interrupt, 1); + qdev_init_gpio_in(dev, max111x_input_set, inputs); s->inputs = inputs; - /* TODO: add a user interface for setting these */ - s->input[0] = 0xf0; - s->input[1] = 0xe0; - s->input[2] = 0xd0; - s->input[3] = 0xc0; - s->input[4] = 0xb0; - s->input[5] = 0xa0; - s->input[6] = 0x90; - s->input[7] = 0x80; - s->com = 0; - vmstate_register(VMSTATE_IF(dev), VMSTATE_INSTANCE_ID_ANY, - &vmstate_max111x, s); return 0; } @@ -161,18 +140,52 @@ static void max1111_realize(SSISlave *dev, Error **errp) max111x_init(dev, 4); } -void max111x_set_input(DeviceState *dev, int line, uint8_t value) +static void max111x_reset(DeviceState *dev) { MAX111xState *s = MAX_111X(dev); - assert(line >= 0 && line < s->inputs); - s->input[line] = value; + int i; + + for (i = 0; i < s->inputs; i++) { + s->input[i] = s->reset_input[i]; + } + s->com = 0; + s->tb1 = 0; + s->rb2 = 0; + s->rb3 = 0; + s->cycle = 0; } +static Property max1110_properties[] = { + /* Reset values for ADC inputs */ + DEFINE_PROP_UINT8("input0", MAX111xState, reset_input[0], 0xf0), + DEFINE_PROP_UINT8("input1", MAX111xState, reset_input[1], 0xe0), + DEFINE_PROP_UINT8("input2", MAX111xState, reset_input[2], 0xd0), + DEFINE_PROP_UINT8("input3", MAX111xState, reset_input[3], 0xc0), + DEFINE_PROP_END_OF_LIST(), +}; + +static Property max1111_properties[] = { + /* Reset values for ADC inputs */ + DEFINE_PROP_UINT8("input0", MAX111xState, reset_input[0], 0xf0), + DEFINE_PROP_UINT8("input1", MAX111xState, reset_input[1], 0xe0), + DEFINE_PROP_UINT8("input2", MAX111xState, reset_input[2], 0xd0), + DEFINE_PROP_UINT8("input3", MAX111xState, reset_input[3], 0xc0), + DEFINE_PROP_UINT8("input4", MAX111xState, reset_input[4], 0xb0), + DEFINE_PROP_UINT8("input5", MAX111xState, reset_input[5], 0xa0), + DEFINE_PROP_UINT8("input6", MAX111xState, reset_input[6], 0x90), + DEFINE_PROP_UINT8("input7", MAX111xState, reset_input[7], 0x80), + DEFINE_PROP_END_OF_LIST(), +}; + static void max111x_class_init(ObjectClass *klass, void *data) { SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); k->transfer = max111x_transfer; + dc->reset = max111x_reset; + dc->vmsd = &vmstate_max111x; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); } static const TypeInfo max111x_info = { @@ -186,8 +199,10 @@ static const TypeInfo max111x_info = { static void max1110_class_init(ObjectClass *klass, void *data) { SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); k->realize = max1110_realize; + device_class_set_props(dc, max1110_properties); } static const TypeInfo max1110_info = { @@ -199,8 +214,10 @@ static const TypeInfo max1110_info = { static void max1111_class_init(ObjectClass *klass, void *data) { SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); k->realize = max1111_realize; + device_class_set_props(dc, max1111_properties); } static const TypeInfo max1111_info = { diff --git a/hw/misc/mchp_pfsoc_dmc.c b/hw/misc/mchp_pfsoc_dmc.c new file mode 100644 index 0000000000000000000000000000000000000000..15cf3d77252c6cafab68554d9745bf1ed423d3fb --- /dev/null +++ b/hw/misc/mchp_pfsoc_dmc.c @@ -0,0 +1,216 @@ +/* + * Microchip PolarFire SoC DDR Memory Controller module emulation + * + * Copyright (c) 2020 Wind River Systems, Inc. + * + * Author: + * Bin Meng + * + * 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 or + * (at your option) version 3 of the License. + * + * 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/misc/mchp_pfsoc_dmc.h" + +/* DDR SGMII PHY module */ + +#define SGMII_PHY_IOC_REG1 0x208 +#define SGMII_PHY_TRAINING_STATUS 0x814 +#define SGMII_PHY_DQ_DQS_ERR_DONE 0x834 +#define SGMII_PHY_DQDQS_STATUS1 0x84c +#define SGMII_PHY_PVT_STAT 0xc20 + +static uint64_t mchp_pfsoc_ddr_sgmii_phy_read(void *opaque, hwaddr offset, + unsigned size) +{ + uint32_t val = 0; + static int training_status_bit; + + switch (offset) { + case SGMII_PHY_IOC_REG1: + /* See ddr_pvt_calibration() in HSS */ + val = BIT(4) | BIT(2); + break; + case SGMII_PHY_TRAINING_STATUS: + /* + * The codes logic emulates the training status change from + * DDR_TRAINING_IP_SM_BCLKSCLK to DDR_TRAINING_IP_SM_DQ_DQS. + * + * See ddr_setup() in mss_ddr.c in the HSS source codes. + */ + val = 1 << training_status_bit; + training_status_bit = (training_status_bit + 1) % 5; + break; + case SGMII_PHY_DQ_DQS_ERR_DONE: + /* + * DDR_TRAINING_IP_SM_VERIFY state in ddr_setup(), + * check that DQ/DQS training passed without error. + */ + val = 8; + break; + case SGMII_PHY_DQDQS_STATUS1: + /* + * DDR_TRAINING_IP_SM_VERIFY state in ddr_setup(), + * check that DQ/DQS calculated window is above 5 taps. + */ + val = 0xff; + break; + case SGMII_PHY_PVT_STAT: + /* See sgmii_channel_setup() in HSS */ + val = BIT(14) | BIT(6); + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read " + "(size %d, offset 0x%" HWADDR_PRIx ")\n", + __func__, size, offset); + break; + } + + return val; +} + +static void mchp_pfsoc_ddr_sgmii_phy_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device write " + "(size %d, value 0x%" PRIx64 + ", offset 0x%" HWADDR_PRIx ")\n", + __func__, size, value, offset); +} + +static const MemoryRegionOps mchp_pfsoc_ddr_sgmii_phy_ops = { + .read = mchp_pfsoc_ddr_sgmii_phy_read, + .write = mchp_pfsoc_ddr_sgmii_phy_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void mchp_pfsoc_ddr_sgmii_phy_realize(DeviceState *dev, Error **errp) +{ + MchpPfSoCDdrSgmiiPhyState *s = MCHP_PFSOC_DDR_SGMII_PHY(dev); + + memory_region_init_io(&s->sgmii_phy, OBJECT(dev), + &mchp_pfsoc_ddr_sgmii_phy_ops, s, + "mchp.pfsoc.ddr_sgmii_phy", + MCHP_PFSOC_DDR_SGMII_PHY_REG_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->sgmii_phy); +} + +static void mchp_pfsoc_ddr_sgmii_phy_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "Microchip PolarFire SoC DDR SGMII PHY module"; + dc->realize = mchp_pfsoc_ddr_sgmii_phy_realize; +} + +static const TypeInfo mchp_pfsoc_ddr_sgmii_phy_info = { + .name = TYPE_MCHP_PFSOC_DDR_SGMII_PHY, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(MchpPfSoCDdrSgmiiPhyState), + .class_init = mchp_pfsoc_ddr_sgmii_phy_class_init, +}; + +static void mchp_pfsoc_ddr_sgmii_phy_register_types(void) +{ + type_register_static(&mchp_pfsoc_ddr_sgmii_phy_info); +} + +type_init(mchp_pfsoc_ddr_sgmii_phy_register_types) + +/* DDR CFG module */ + +#define CFG_MT_DONE_ACK 0x4428 +#define CFG_STAT_DFI_INIT_COMPLETE 0x10034 +#define CFG_STAT_DFI_TRAINING_COMPLETE 0x10038 + +static uint64_t mchp_pfsoc_ddr_cfg_read(void *opaque, hwaddr offset, + unsigned size) +{ + uint32_t val = 0; + + switch (offset) { + case CFG_MT_DONE_ACK: + /* memory test in MTC_test() */ + val = BIT(0); + break; + case CFG_STAT_DFI_INIT_COMPLETE: + /* DDR_TRAINING_IP_SM_START_CHECK state in ddr_setup() */ + val = BIT(0); + break; + case CFG_STAT_DFI_TRAINING_COMPLETE: + /* DDR_TRAINING_IP_SM_VERIFY state in ddr_setup() */ + val = BIT(0); + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read " + "(size %d, offset 0x%" HWADDR_PRIx ")\n", + __func__, size, offset); + break; + } + + return val; +} + +static void mchp_pfsoc_ddr_cfg_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device write " + "(size %d, value 0x%" PRIx64 + ", offset 0x%" HWADDR_PRIx ")\n", + __func__, size, value, offset); +} + +static const MemoryRegionOps mchp_pfsoc_ddr_cfg_ops = { + .read = mchp_pfsoc_ddr_cfg_read, + .write = mchp_pfsoc_ddr_cfg_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void mchp_pfsoc_ddr_cfg_realize(DeviceState *dev, Error **errp) +{ + MchpPfSoCDdrCfgState *s = MCHP_PFSOC_DDR_CFG(dev); + + memory_region_init_io(&s->cfg, OBJECT(dev), + &mchp_pfsoc_ddr_cfg_ops, s, + "mchp.pfsoc.ddr_cfg", + MCHP_PFSOC_DDR_CFG_REG_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->cfg); +} + +static void mchp_pfsoc_ddr_cfg_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "Microchip PolarFire SoC DDR CFG module"; + dc->realize = mchp_pfsoc_ddr_cfg_realize; +} + +static const TypeInfo mchp_pfsoc_ddr_cfg_info = { + .name = TYPE_MCHP_PFSOC_DDR_CFG, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(MchpPfSoCDdrCfgState), + .class_init = mchp_pfsoc_ddr_cfg_class_init, +}; + +static void mchp_pfsoc_ddr_cfg_register_types(void) +{ + type_register_static(&mchp_pfsoc_ddr_cfg_info); +} + +type_init(mchp_pfsoc_ddr_cfg_register_types) diff --git a/hw/misc/mchp_pfsoc_ioscb.c b/hw/misc/mchp_pfsoc_ioscb.c new file mode 100644 index 0000000000000000000000000000000000000000..8b0d1cacd7efe0eae61234e8996c311d5ad82b80 --- /dev/null +++ b/hw/misc/mchp_pfsoc_ioscb.c @@ -0,0 +1,242 @@ +/* + * Microchip PolarFire SoC IOSCB module emulation + * + * Copyright (c) 2020 Wind River Systems, Inc. + * + * Author: + * Bin Meng + * + * 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 or + * (at your option) version 3 of the License. + * + * 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/misc/mchp_pfsoc_ioscb.h" + +/* + * The whole IOSCB module registers map into the system address at 0x3000_0000, + * named as "System Port 0 (AXI-D0)". + */ +#define IOSCB_WHOLE_REG_SIZE 0x10000000 +#define IOSCB_SUBMOD_REG_SIZE 0x1000 + +/* + * There are many sub-modules in the IOSCB module. + * See Microchip PolarFire SoC documentation (Register_Map.zip), + * Register Map/PF_SoC_RegMap_V1_1/MPFS250T/mpfs250t_ioscb_memmap_dri.htm + * + * The following are sub-modules offsets that are of concern. + */ +#define IOSCB_LANE01_BASE 0x06500000 +#define IOSCB_LANE23_BASE 0x06510000 +#define IOSCB_CTRL_BASE 0x07020000 +#define IOSCB_CFG_BASE 0x07080000 +#define IOSCB_PLL_MSS_BASE 0x0E001000 +#define IOSCB_CFM_MSS_BASE 0x0E002000 +#define IOSCB_PLL_DDR_BASE 0x0E010000 +#define IOSCB_BC_DDR_BASE 0x0E020000 +#define IOSCB_IO_CALIB_DDR_BASE 0x0E040000 +#define IOSCB_PLL_SGMII_BASE 0x0E080000 +#define IOSCB_DLL_SGMII_BASE 0x0E100000 +#define IOSCB_CFM_SGMII_BASE 0x0E200000 +#define IOSCB_BC_SGMII_BASE 0x0E400000 +#define IOSCB_IO_CALIB_SGMII_BASE 0x0E800000 + +static uint64_t mchp_pfsoc_dummy_read(void *opaque, hwaddr offset, + unsigned size) +{ + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read " + "(size %d, offset 0x%" HWADDR_PRIx ")\n", + __func__, size, offset); + + return 0; +} + +static void mchp_pfsoc_dummy_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device write " + "(size %d, value 0x%" PRIx64 + ", offset 0x%" HWADDR_PRIx ")\n", + __func__, size, value, offset); +} + +static const MemoryRegionOps mchp_pfsoc_dummy_ops = { + .read = mchp_pfsoc_dummy_read, + .write = mchp_pfsoc_dummy_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +/* All PLL modules in IOSCB have the same register layout */ + +#define PLL_CTRL 0x04 + +static uint64_t mchp_pfsoc_pll_read(void *opaque, hwaddr offset, + unsigned size) +{ + uint32_t val = 0; + + switch (offset) { + case PLL_CTRL: + /* PLL is locked */ + val = BIT(25); + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read " + "(size %d, offset 0x%" HWADDR_PRIx ")\n", + __func__, size, offset); + break; + } + + return val; +} + +static const MemoryRegionOps mchp_pfsoc_pll_ops = { + .read = mchp_pfsoc_pll_read, + .write = mchp_pfsoc_dummy_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +/* IO_CALIB_DDR submodule */ + +#define IO_CALIB_DDR_IOC_REG1 0x08 + +static uint64_t mchp_pfsoc_io_calib_ddr_read(void *opaque, hwaddr offset, + unsigned size) +{ + uint32_t val = 0; + + switch (offset) { + case IO_CALIB_DDR_IOC_REG1: + /* calibration completed */ + val = BIT(2); + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read " + "(size %d, offset 0x%" HWADDR_PRIx ")\n", + __func__, size, offset); + break; + } + + return val; +} + +static const MemoryRegionOps mchp_pfsoc_io_calib_ddr_ops = { + .read = mchp_pfsoc_io_calib_ddr_read, + .write = mchp_pfsoc_dummy_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void mchp_pfsoc_ioscb_realize(DeviceState *dev, Error **errp) +{ + MchpPfSoCIoscbState *s = MCHP_PFSOC_IOSCB(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + + memory_region_init(&s->container, OBJECT(s), + "mchp.pfsoc.ioscb", IOSCB_WHOLE_REG_SIZE); + sysbus_init_mmio(sbd, &s->container); + + /* add subregions for all sub-modules in IOSCB */ + + memory_region_init_io(&s->lane01, OBJECT(s), &mchp_pfsoc_dummy_ops, s, + "mchp.pfsoc.ioscb.lane01", IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_LANE01_BASE, &s->lane01); + + memory_region_init_io(&s->lane23, OBJECT(s), &mchp_pfsoc_dummy_ops, s, + "mchp.pfsoc.ioscb.lane23", IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_LANE23_BASE, &s->lane23); + + memory_region_init_io(&s->ctrl, OBJECT(s), &mchp_pfsoc_dummy_ops, s, + "mchp.pfsoc.ioscb.ctrl", IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_CTRL_BASE, &s->ctrl); + + memory_region_init_io(&s->cfg, OBJECT(s), &mchp_pfsoc_dummy_ops, s, + "mchp.pfsoc.ioscb.cfg", IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_CFG_BASE, &s->cfg); + + memory_region_init_io(&s->pll_mss, OBJECT(s), &mchp_pfsoc_pll_ops, s, + "mchp.pfsoc.ioscb.pll_mss", IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_PLL_MSS_BASE, &s->pll_mss); + + memory_region_init_io(&s->cfm_mss, OBJECT(s), &mchp_pfsoc_dummy_ops, s, + "mchp.pfsoc.ioscb.cfm_mss", IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_CFM_MSS_BASE, &s->cfm_mss); + + memory_region_init_io(&s->pll_ddr, OBJECT(s), &mchp_pfsoc_pll_ops, s, + "mchp.pfsoc.ioscb.pll_ddr", IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_PLL_DDR_BASE, &s->pll_ddr); + + memory_region_init_io(&s->bc_ddr, OBJECT(s), &mchp_pfsoc_dummy_ops, s, + "mchp.pfsoc.ioscb.bc_ddr", IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_BC_DDR_BASE, &s->bc_ddr); + + memory_region_init_io(&s->io_calib_ddr, OBJECT(s), + &mchp_pfsoc_io_calib_ddr_ops, s, + "mchp.pfsoc.ioscb.io_calib_ddr", + IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_IO_CALIB_DDR_BASE, + &s->io_calib_ddr); + + memory_region_init_io(&s->pll_sgmii, OBJECT(s), &mchp_pfsoc_pll_ops, s, + "mchp.pfsoc.ioscb.pll_sgmii", IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_PLL_SGMII_BASE, + &s->pll_sgmii); + + memory_region_init_io(&s->dll_sgmii, OBJECT(s), &mchp_pfsoc_dummy_ops, s, + "mchp.pfsoc.ioscb.dll_sgmii", IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_DLL_SGMII_BASE, + &s->dll_sgmii); + + memory_region_init_io(&s->cfm_sgmii, OBJECT(s), &mchp_pfsoc_dummy_ops, s, + "mchp.pfsoc.ioscb.cfm_sgmii", IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_CFM_SGMII_BASE, + &s->cfm_sgmii); + + memory_region_init_io(&s->bc_sgmii, OBJECT(s), &mchp_pfsoc_dummy_ops, s, + "mchp.pfsoc.ioscb.bc_sgmii", IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_BC_SGMII_BASE, + &s->bc_sgmii); + + memory_region_init_io(&s->io_calib_sgmii, OBJECT(s), &mchp_pfsoc_dummy_ops, + s, "mchp.pfsoc.ioscb.io_calib_sgmii", + IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_IO_CALIB_SGMII_BASE, + &s->io_calib_sgmii); +} + +static void mchp_pfsoc_ioscb_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "Microchip PolarFire SoC IOSCB modules"; + dc->realize = mchp_pfsoc_ioscb_realize; +} + +static const TypeInfo mchp_pfsoc_ioscb_info = { + .name = TYPE_MCHP_PFSOC_IOSCB, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(MchpPfSoCIoscbState), + .class_init = mchp_pfsoc_ioscb_class_init, +}; + +static void mchp_pfsoc_ioscb_register_types(void) +{ + type_register_static(&mchp_pfsoc_ioscb_info); +} + +type_init(mchp_pfsoc_ioscb_register_types) diff --git a/hw/misc/mchp_pfsoc_sysreg.c b/hw/misc/mchp_pfsoc_sysreg.c new file mode 100644 index 0000000000000000000000000000000000000000..248a3133455c827a352f91fe85aa102f785eef2e --- /dev/null +++ b/hw/misc/mchp_pfsoc_sysreg.c @@ -0,0 +1,99 @@ +/* + * Microchip PolarFire SoC SYSREG module emulation + * + * Copyright (c) 2020 Wind River Systems, Inc. + * + * Author: + * Bin Meng + * + * 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 or + * (at your option) version 3 of the License. + * + * 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/misc/mchp_pfsoc_sysreg.h" + +#define ENVM_CR 0xb8 + +static uint64_t mchp_pfsoc_sysreg_read(void *opaque, hwaddr offset, + unsigned size) +{ + uint32_t val = 0; + + switch (offset) { + case ENVM_CR: + /* Indicate the eNVM is running at the configured divider rate */ + val = BIT(6); + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read " + "(size %d, offset 0x%" HWADDR_PRIx ")\n", + __func__, size, offset); + break; + } + + return val; +} + +static void mchp_pfsoc_sysreg_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device write " + "(size %d, value 0x%" PRIx64 + ", offset 0x%" HWADDR_PRIx ")\n", + __func__, size, value, offset); +} + +static const MemoryRegionOps mchp_pfsoc_sysreg_ops = { + .read = mchp_pfsoc_sysreg_read, + .write = mchp_pfsoc_sysreg_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void mchp_pfsoc_sysreg_realize(DeviceState *dev, Error **errp) +{ + MchpPfSoCSysregState *s = MCHP_PFSOC_SYSREG(dev); + + memory_region_init_io(&s->sysreg, OBJECT(dev), + &mchp_pfsoc_sysreg_ops, s, + "mchp.pfsoc.sysreg", + MCHP_PFSOC_SYSREG_REG_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->sysreg); +} + +static void mchp_pfsoc_sysreg_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "Microchip PolarFire SoC SYSREG module"; + dc->realize = mchp_pfsoc_sysreg_realize; +} + +static const TypeInfo mchp_pfsoc_sysreg_info = { + .name = TYPE_MCHP_PFSOC_SYSREG, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(MchpPfSoCSysregState), + .class_init = mchp_pfsoc_sysreg_class_init, +}; + +static void mchp_pfsoc_sysreg_register_types(void) +{ + type_register_static(&mchp_pfsoc_sysreg_info); +} + +type_init(mchp_pfsoc_sysreg_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..1cd48e8a0fb55a5d6b1aed03677aa14ec1b51584 --- /dev/null +++ b/hw/misc/meson.build @@ -0,0 +1,117 @@ +softmmu_ss.add(when: 'CONFIG_APPLESMC', if_true: files('applesmc.c')) +softmmu_ss.add(when: 'CONFIG_EDU', if_true: files('edu.c')) +softmmu_ss.add(when: 'CONFIG_FW_CFG_DMA', if_true: files('vmcoreinfo.c')) +softmmu_ss.add(when: 'CONFIG_ISA_DEBUG', if_true: files('debugexit.c')) +softmmu_ss.add(when: 'CONFIG_ISA_TESTDEV', if_true: files('pc-testdev.c')) +softmmu_ss.add(when: 'CONFIG_MAX111X', if_true: files('max111x.c')) +softmmu_ss.add(when: 'CONFIG_PCA9552', if_true: files('pca9552.c')) +softmmu_ss.add(when: 'CONFIG_PCI_TESTDEV', if_true: files('pci-testdev.c')) +softmmu_ss.add(when: 'CONFIG_SGA', if_true: files('sga.c')) +softmmu_ss.add(when: 'CONFIG_TMP105', if_true: files('tmp105.c')) +softmmu_ss.add(when: 'CONFIG_TMP421', if_true: files('tmp421.c')) +softmmu_ss.add(when: 'CONFIG_UNIMP', if_true: files('unimp.c')) +softmmu_ss.add(when: 'CONFIG_EMPTY_SLOT', if_true: files('empty_slot.c')) +softmmu_ss.add(when: 'CONFIG_LED', if_true: files('led.c')) + +# ARM devices +softmmu_ss.add(when: 'CONFIG_PL310', if_true: files('arm_l2x0.c')) +softmmu_ss.add(when: 'CONFIG_INTEGRATOR_DEBUG', if_true: files('arm_integrator_debug.c')) +softmmu_ss.add(when: 'CONFIG_A9SCU', if_true: files('a9scu.c')) +softmmu_ss.add(when: 'CONFIG_ARM11SCU', if_true: files('arm11scu.c')) + +# Mac devices +softmmu_ss.add(when: 'CONFIG_MOS6522', if_true: files('mos6522.c')) + +# RISC-V devices +softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_DMC', if_true: files('mchp_pfsoc_dmc.c')) +softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_IOSCB', if_true: files('mchp_pfsoc_ioscb.c')) +softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_SYSREG', if_true: files('mchp_pfsoc_sysreg.c')) +softmmu_ss.add(when: 'CONFIG_SIFIVE_TEST', if_true: files('sifive_test.c')) +softmmu_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true: files('sifive_e_prci.c')) +softmmu_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true: files('sifive_u_otp.c')) +softmmu_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: files('sifive_u_prci.c')) + +# PKUnity SoC devices +softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_pm.c')) + +subdir('macio') + +softmmu_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem.c')) + +softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-ccu.c')) +specific_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-cpucfg.c')) +softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c')) +softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-sysctrl.c')) +softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sid.c')) +softmmu_ss.add(when: 'CONFIG_REALVIEW', if_true: files('arm_sysctl.c')) +softmmu_ss.add(when: 'CONFIG_NSERIES', if_true: files('cbus.c')) +softmmu_ss.add(when: 'CONFIG_ECCMEMCTL', if_true: files('eccmemctl.c')) +softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_pmu.c', 'exynos4210_clk.c', 'exynos4210_rng.c')) +softmmu_ss.add(when: 'CONFIG_IMX', if_true: files( + 'imx25_ccm.c', + 'imx31_ccm.c', + 'imx6_ccm.c', + 'imx6ul_ccm.c', + 'imx7_ccm.c', + 'imx7_gpr.c', + 'imx7_snvs.c', + 'imx_ccm.c', + 'imx_rngc.c', +)) +softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-hpdmc.c', 'milkymist-pfpu.c')) +softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c')) +softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files( + 'npcm7xx_clk.c', + 'npcm7xx_gcr.c', + 'npcm7xx_rng.c', +)) +softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files( + 'omap_clk.c', + 'omap_gpmc.c', + 'omap_l4.c', + 'omap_sdrc.c', + 'omap_tap.c', +)) +softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files( + 'bcm2835_mbox.c', + 'bcm2835_mphi.c', + 'bcm2835_property.c', + 'bcm2835_rng.c', + 'bcm2835_thermal.c', + 'bcm2835_cprman.c', +)) +softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c')) +softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c', 'zynq-xadc.c')) +softmmu_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c')) +softmmu_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c')) +softmmu_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c')) +softmmu_ss.add(when: 'CONFIG_MPS2_FPGAIO', if_true: files('mps2-fpgaio.c')) +softmmu_ss.add(when: 'CONFIG_MPS2_SCC', if_true: files('mps2-scc.c')) + +softmmu_ss.add(when: 'CONFIG_TZ_MPC', if_true: files('tz-mpc.c')) +softmmu_ss.add(when: 'CONFIG_TZ_MSC', if_true: files('tz-msc.c')) +softmmu_ss.add(when: 'CONFIG_TZ_PPC', if_true: files('tz-ppc.c')) +softmmu_ss.add(when: 'CONFIG_IOTKIT_SECCTL', if_true: files('iotkit-secctl.c')) +softmmu_ss.add(when: 'CONFIG_IOTKIT_SYSINFO', if_true: files('iotkit-sysinfo.c')) +softmmu_ss.add(when: 'CONFIG_ARMSSE_CPUID', if_true: files('armsse-cpuid.c')) +softmmu_ss.add(when: 'CONFIG_ARMSSE_MHU', if_true: files('armsse-mhu.c')) + +softmmu_ss.add(when: 'CONFIG_PVPANIC', if_true: files('pvpanic.c')) +softmmu_ss.add(when: 'CONFIG_AUX', if_true: files('auxbus.c')) +softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_scu.c', 'aspeed_sdmc.c', 'aspeed_xdma.c')) +softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-sysreg.c')) +softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_rng.c')) + +softmmu_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_ahb_apb_pnp.c')) + +specific_ss.add(when: 'CONFIG_AVR_POWER', if_true: files('avr_power.c')) + +specific_ss.add(when: 'CONFIG_IMX', if_true: files('imx6_src.c')) +specific_ss.add(when: 'CONFIG_IOTKIT_SYSCTL', if_true: files('iotkit-sysctl.c')) + +specific_ss.add(when: 'CONFIG_MAC_VIA', if_true: files('mac_via.c')) + +specific_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_cmgcr.c', 'mips_cpc.c')) +specific_ss.add(when: 'CONFIG_MIPS_ITU', if_true: files('mips_itu.c')) + +specific_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa_ec.c')) diff --git a/hw/misc/milkymist-hpdmc.c b/hw/misc/milkymist-hpdmc.c index 61e86e6b341aee6f69c639acf5d1bea158d84d83..09a3875f02ce70d7058274a870c84f8b25a223c8 100644 --- a/hw/misc/milkymist-hpdmc.c +++ b/hw/misc/milkymist-hpdmc.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -27,6 +27,7 @@ #include "trace.h" #include "qemu/error-report.h" #include "qemu/module.h" +#include "qom/object.h" enum { R_SYSTEM = 0, @@ -43,8 +44,7 @@ enum { }; #define TYPE_MILKYMIST_HPDMC "milkymist-hpdmc" -#define MILKYMIST_HPDMC(obj) \ - OBJECT_CHECK(MilkymistHpdmcState, (obj), TYPE_MILKYMIST_HPDMC) +OBJECT_DECLARE_SIMPLE_TYPE(MilkymistHpdmcState, MILKYMIST_HPDMC) struct MilkymistHpdmcState { SysBusDevice parent_obj; @@ -53,7 +53,6 @@ struct MilkymistHpdmcState { uint32_t regs[R_MAX]; }; -typedef struct MilkymistHpdmcState MilkymistHpdmcState; static uint64_t hpdmc_read(void *opaque, hwaddr addr, unsigned size) diff --git a/hw/misc/milkymist-pfpu.c b/hw/misc/milkymist-pfpu.c index 516825e83deae0372861bc3a94c24290553b4e60..e4ee209c1019b61994a39dd0fd41e75474be48e9 100644 --- a/hw/misc/milkymist-pfpu.c +++ b/hw/misc/milkymist-pfpu.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,6 +31,7 @@ #include "qemu/module.h" #include "qemu/error-report.h" #include +#include "qom/object.h" /* #define TRACE_EXEC */ @@ -120,8 +121,7 @@ static const char *opcode_to_str[] = { #endif #define TYPE_MILKYMIST_PFPU "milkymist-pfpu" -#define MILKYMIST_PFPU(obj) \ - OBJECT_CHECK(MilkymistPFPUState, (obj), TYPE_MILKYMIST_PFPU) +OBJECT_DECLARE_SIMPLE_TYPE(MilkymistPFPUState, MILKYMIST_PFPU) struct MilkymistPFPUState { SysBusDevice parent_obj; @@ -137,7 +137,6 @@ struct MilkymistPFPUState { int output_queue_pos; uint32_t output_queue[MAX_LATENCY]; }; -typedef struct MilkymistPFPUState MilkymistPFPUState; static inline uint32_t get_dma_address(uint32_t base, uint32_t x, uint32_t y) diff --git a/hw/misc/mips_cpc.c b/hw/misc/mips_cpc.c index 2f7b2c95928f6bb1ea50926104e05fd798e7feb0..4a94c87054644c247f9fd4ea74724356a7d532fb 100644 --- a/hw/misc/mips_cpc.c +++ b/hw/misc/mips_cpc.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -38,6 +38,7 @@ static void mips_cpu_reset_async_work(CPUState *cs, run_on_cpu_data data) MIPSCPCState *cpc = (MIPSCPCState *) data.host_ptr; cpu_reset(cs); + cs->halted = 0; cpc->vp_running |= 1ULL << cs->cpu_index; } diff --git a/hw/misc/mips_itu.c b/hw/misc/mips_itu.c index 3540985258846c2652b371d6f30092f67ac4fcb3..133399598fce58e0bb8b2a2337eebb3fe5a8bfed 100644 --- a/hw/misc/mips_itu.c +++ b/hw/misc/mips_itu.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/misc/mos6522.c b/hw/misc/mos6522.c index 19e154b870f96d2a5f436b59b3b978521d333bda..ac4cd1d58ebefad3314e755459df833307f551c8 100644 --- a/hw/misc/mos6522.c +++ b/hw/misc/mos6522.c @@ -54,7 +54,7 @@ static void mos6522_update_irq(MOS6522State *s) static uint64_t get_counter_value(MOS6522State *s, MOS6522Timer *ti) { - MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s); + MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s); if (ti->index == 0) { return mdc->get_timer1_counter_value(s, ti); @@ -65,7 +65,7 @@ static uint64_t get_counter_value(MOS6522State *s, MOS6522Timer *ti) static uint64_t get_load_time(MOS6522State *s, MOS6522Timer *ti) { - MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s); + MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s); if (ti->index == 0) { return mdc->get_timer1_load_time(s, ti); @@ -313,7 +313,7 @@ uint64_t mos6522_read(void *opaque, hwaddr addr, unsigned size) void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { MOS6522State *s = opaque; - MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s); + MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s); trace_mos6522_write(addr, val); @@ -498,7 +498,7 @@ static Property mos6522_properties[] = { static void mos6522_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); - MOS6522DeviceClass *mdc = MOS6522_DEVICE_CLASS(oc); + MOS6522DeviceClass *mdc = MOS6522_CLASS(oc); dc->reset = mos6522_reset; dc->vmsd = &vmstate_mos6522; diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c index 2f3fbeef34856963c66f70e721054276122b590f..6af0e8f837aa269311466139d4f9ad76fa40201c 100644 --- a/hw/misc/mps2-fpgaio.c +++ b/hw/misc/mps2-fpgaio.c @@ -24,6 +24,7 @@ #include "migration/vmstate.h" #include "hw/registerfields.h" #include "hw/misc/mps2-fpgaio.h" +#include "hw/misc/led.h" #include "hw/qdev-properties.h" #include "qemu/timer.h" @@ -176,12 +177,9 @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value, switch (offset) { case A_LED0: - /* LED bits [1:0] control board LEDs. We don't currently have - * a mechanism for displaying this graphically, so use a trace event. - */ - trace_mps2_fpgaio_leds(value & 0x02 ? '*' : '.', - value & 0x01 ? '*' : '.'); s->led0 = value & 0x3; + led_set_state(s->led[0], value & 0x01); + led_set_state(s->led[1], value & 0x02); break; case A_PRESCALE: resync_counter(s); @@ -239,6 +237,10 @@ static void mps2_fpgaio_reset(DeviceState *dev) s->counter = 0; s->pscntr = 0; s->pscntr_sync_ticks = now; + + for (size_t i = 0; i < ARRAY_SIZE(s->led); i++) { + device_cold_reset(DEVICE(s->led[i])); + } } static void mps2_fpgaio_init(Object *obj) @@ -251,6 +253,16 @@ static void mps2_fpgaio_init(Object *obj) sysbus_init_mmio(sbd, &s->iomem); } +static void mps2_fpgaio_realize(DeviceState *dev, Error **errp) +{ + MPS2FPGAIO *s = MPS2_FPGAIO(dev); + + s->led[0] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH, + LED_COLOR_GREEN, "USERLED0"); + s->led[1] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH, + LED_COLOR_GREEN, "USERLED1"); +} + static bool mps2_fpgaio_counters_needed(void *opaque) { /* Currently vmstate.c insists all subsections have a 'needed' function */ @@ -299,6 +311,7 @@ static void mps2_fpgaio_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); dc->vmsd = &mps2_fpgaio_vmstate; + dc->realize = mps2_fpgaio_realize; dc->reset = mps2_fpgaio_reset; device_class_set_props(dc, mps2_fpgaio_properties); } diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c index 9d0909e7b35fb0e3cd5a66e430af8ea6937145a9..ce1dfe93562ab78d7db6a6bcf3cade1a0f0e453b 100644 --- a/hw/misc/mps2-scc.c +++ b/hw/misc/mps2-scc.c @@ -20,11 +20,13 @@ #include "qemu/osdep.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qemu/bitops.h" #include "trace.h" #include "hw/sysbus.h" #include "migration/vmstate.h" #include "hw/registerfields.h" #include "hw/misc/mps2-scc.h" +#include "hw/misc/led.h" #include "hw/qdev-properties.h" REG32(CFG0, 0) @@ -152,18 +154,10 @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value, s->cfg0 = value; break; case A_CFG1: - /* CFG1 bits [7:0] control the board LEDs. We don't currently have - * a mechanism for displaying this graphically, so use a trace event. - */ - trace_mps2_scc_leds(value & 0x80 ? '*' : '.', - value & 0x40 ? '*' : '.', - value & 0x20 ? '*' : '.', - value & 0x10 ? '*' : '.', - value & 0x08 ? '*' : '.', - value & 0x04 ? '*' : '.', - value & 0x02 ? '*' : '.', - value & 0x01 ? '*' : '.'); s->cfg1 = value; + for (size_t i = 0; i < ARRAY_SIZE(s->led); i++) { + led_set_state(s->led[i], extract32(value, i, 1)); + } break; case A_CFGDATA_OUT: s->cfgdata_out = value; @@ -236,6 +230,9 @@ static void mps2_scc_reset(DeviceState *dev) for (i = 0; i < NUM_OSCCLK; i++) { s->oscclk[i] = s->oscclk_reset[i]; } + for (i = 0; i < ARRAY_SIZE(s->led); i++) { + device_cold_reset(DEVICE(s->led[i])); + } } static void mps2_scc_init(Object *obj) @@ -249,6 +246,14 @@ static void mps2_scc_init(Object *obj) static void mps2_scc_realize(DeviceState *dev, Error **errp) { + MPS2SCC *s = MPS2_SCC(dev); + + for (size_t i = 0; i < ARRAY_SIZE(s->led); i++) { + char *name = g_strdup_printf("SCC LED%zu", i); + s->led[i] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH, + LED_COLOR_GREEN, name); + g_free(name); + } } static const VMStateDescription mps2_scc_vmstate = { diff --git a/hw/misc/mst_fpga.c b/hw/misc/mst_fpga.c index 81abdf8ede645e7109bb5c159237c6cb1700ffdc..edfc35d5f0f9b0d5c38c32309949cfd360f8566f 100644 --- a/hw/misc/mst_fpga.c +++ b/hw/misc/mst_fpga.c @@ -16,6 +16,7 @@ #include "hw/sysbus.h" #include "migration/vmstate.h" #include "qemu/module.h" +#include "qom/object.h" /* Mainstone FPGA for extern irqs */ #define FPGA_GPIO_PIN 0 @@ -40,10 +41,9 @@ #define MST_PCMCIA_CD1_IRQ 13 #define TYPE_MAINSTONE_FPGA "mainstone-fpga" -#define MAINSTONE_FPGA(obj) \ - OBJECT_CHECK(mst_irq_state, (obj), TYPE_MAINSTONE_FPGA) +OBJECT_DECLARE_SIMPLE_TYPE(mst_irq_state, MAINSTONE_FPGA) -typedef struct mst_irq_state{ +struct mst_irq_state { SysBusDevice parent_obj; MemoryRegion iomem; @@ -63,7 +63,7 @@ typedef struct mst_irq_state{ uint32_t intsetclr; uint32_t pcmcia0; uint32_t pcmcia1; -}mst_irq_state; +}; static void mst_fpga_set_irq(void *opaque, int irq, int level) diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c new file mode 100644 index 0000000000000000000000000000000000000000..6732437fe22718bf80f0633cde35ca5ef1348a52 --- /dev/null +++ b/hw/misc/npcm7xx_clk.c @@ -0,0 +1,294 @@ +/* + * Nuvoton NPCM7xx Clock Control Registers. + * + * Copyright 2020 Google LLC + * + * 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. + */ + +#include "qemu/osdep.h" + +#include "hw/misc/npcm7xx_clk.h" +#include "hw/timer/npcm7xx_timer.h" +#include "migration/vmstate.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/timer.h" +#include "qemu/units.h" +#include "trace.h" +#include "sysemu/watchdog.h" + +#define PLLCON_LOKI BIT(31) +#define PLLCON_LOKS BIT(30) +#define PLLCON_PWDEN BIT(12) + +enum NPCM7xxCLKRegisters { + NPCM7XX_CLK_CLKEN1, + NPCM7XX_CLK_CLKSEL, + NPCM7XX_CLK_CLKDIV1, + NPCM7XX_CLK_PLLCON0, + NPCM7XX_CLK_PLLCON1, + NPCM7XX_CLK_SWRSTR, + NPCM7XX_CLK_IPSRST1 = 0x20 / sizeof(uint32_t), + NPCM7XX_CLK_IPSRST2, + NPCM7XX_CLK_CLKEN2, + NPCM7XX_CLK_CLKDIV2, + NPCM7XX_CLK_CLKEN3, + NPCM7XX_CLK_IPSRST3, + NPCM7XX_CLK_WD0RCR, + NPCM7XX_CLK_WD1RCR, + NPCM7XX_CLK_WD2RCR, + NPCM7XX_CLK_SWRSTC1, + NPCM7XX_CLK_SWRSTC2, + NPCM7XX_CLK_SWRSTC3, + NPCM7XX_CLK_SWRSTC4, + NPCM7XX_CLK_PLLCON2, + NPCM7XX_CLK_CLKDIV3, + NPCM7XX_CLK_CORSTC, + NPCM7XX_CLK_PLLCONG, + NPCM7XX_CLK_AHBCKFI, + NPCM7XX_CLK_SECCNT, + NPCM7XX_CLK_CNTR25M, + NPCM7XX_CLK_REGS_END, +}; + +/* + * These reset values were taken from version 0.91 of the NPCM750R data sheet. + * + * All are loaded on power-up reset. CLKENx and SWRSTR should also be loaded on + * core domain reset, but this reset type is not yet supported by QEMU. + */ +static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = { + [NPCM7XX_CLK_CLKEN1] = 0xffffffff, + [NPCM7XX_CLK_CLKSEL] = 0x004aaaaa, + [NPCM7XX_CLK_CLKDIV1] = 0x5413f855, + [NPCM7XX_CLK_PLLCON0] = 0x00222101 | PLLCON_LOKI, + [NPCM7XX_CLK_PLLCON1] = 0x00202101 | PLLCON_LOKI, + [NPCM7XX_CLK_IPSRST1] = 0x00001000, + [NPCM7XX_CLK_IPSRST2] = 0x80000000, + [NPCM7XX_CLK_CLKEN2] = 0xffffffff, + [NPCM7XX_CLK_CLKDIV2] = 0xaa4f8f9f, + [NPCM7XX_CLK_CLKEN3] = 0xffffffff, + [NPCM7XX_CLK_IPSRST3] = 0x03000000, + [NPCM7XX_CLK_WD0RCR] = 0xffffffff, + [NPCM7XX_CLK_WD1RCR] = 0xffffffff, + [NPCM7XX_CLK_WD2RCR] = 0xffffffff, + [NPCM7XX_CLK_SWRSTC1] = 0x00000003, + [NPCM7XX_CLK_PLLCON2] = 0x00c02105 | PLLCON_LOKI, + [NPCM7XX_CLK_CORSTC] = 0x04000003, + [NPCM7XX_CLK_PLLCONG] = 0x01228606 | PLLCON_LOKI, + [NPCM7XX_CLK_AHBCKFI] = 0x000000c8, +}; + +/* Register Field Definitions */ +#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */ + +/* The number of watchdogs that can trigger a reset. */ +#define NPCM7XX_NR_WATCHDOGS (3) + +static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size) +{ + uint32_t reg = offset / sizeof(uint32_t); + NPCM7xxCLKState *s = opaque; + int64_t now_ns; + uint32_t value = 0; + + if (reg >= NPCM7XX_CLK_NR_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: offset 0x%04" HWADDR_PRIx " out of range\n", + __func__, offset); + return 0; + } + + switch (reg) { + case NPCM7XX_CLK_SWRSTR: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: register @ 0x%04" HWADDR_PRIx " is write-only\n", + __func__, offset); + break; + + case NPCM7XX_CLK_SECCNT: + now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + value = (now_ns - s->ref_ns) / NANOSECONDS_PER_SECOND; + break; + + case NPCM7XX_CLK_CNTR25M: + now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + /* + * This register counts 25 MHz cycles, updating every 640 ns. It rolls + * over to zero every second. + * + * The 4 LSBs are always zero: (1e9 / 640) << 4 = 25000000. + */ + value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_TIMER_REF_HZ; + break; + + default: + value = s->regs[reg]; + break; + }; + + trace_npcm7xx_clk_read(offset, value); + + return value; +} + +static void npcm7xx_clk_write(void *opaque, hwaddr offset, + uint64_t v, unsigned size) +{ + uint32_t reg = offset / sizeof(uint32_t); + NPCM7xxCLKState *s = opaque; + uint32_t value = v; + + trace_npcm7xx_clk_write(offset, value); + + if (reg >= NPCM7XX_CLK_NR_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: offset 0x%04" HWADDR_PRIx " out of range\n", + __func__, offset); + return; + } + + switch (reg) { + case NPCM7XX_CLK_SWRSTR: + qemu_log_mask(LOG_UNIMP, "%s: SW reset not implemented: 0x%02x\n", + __func__, value); + value = 0; + break; + + case NPCM7XX_CLK_PLLCON0: + case NPCM7XX_CLK_PLLCON1: + case NPCM7XX_CLK_PLLCON2: + case NPCM7XX_CLK_PLLCONG: + if (value & PLLCON_PWDEN) { + /* Power down -- clear lock and indicate loss of lock */ + value &= ~PLLCON_LOKI; + value |= PLLCON_LOKS; + } else { + /* Normal mode -- assume always locked */ + value |= PLLCON_LOKI; + /* Keep LOKS unchanged unless cleared by writing 1 */ + if (value & PLLCON_LOKS) { + value &= ~PLLCON_LOKS; + } else { + value |= (value & PLLCON_LOKS); + } + } + break; + + case NPCM7XX_CLK_CNTR25M: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n", + __func__, offset); + return; + } + + s->regs[reg] = value; +} + +/* Perform reset action triggered by a watchdog */ +static void npcm7xx_clk_perform_watchdog_reset(void *opaque, int n, + int level) +{ + NPCM7xxCLKState *clk = NPCM7XX_CLK(opaque); + uint32_t rcr; + + g_assert(n >= 0 && n <= NPCM7XX_NR_WATCHDOGS); + rcr = clk->regs[NPCM7XX_CLK_WD0RCR + n]; + if (rcr & NPCM7XX_CLK_WDRCR_CA9C) { + watchdog_perform_action(); + } else { + qemu_log_mask(LOG_UNIMP, + "%s: only CPU reset is implemented. (requested 0x%" PRIx32")\n", + __func__, rcr); + } +} + +static const struct MemoryRegionOps npcm7xx_clk_ops = { + .read = npcm7xx_clk_read, + .write = npcm7xx_clk_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + .unaligned = false, + }, +}; + +static void npcm7xx_clk_enter_reset(Object *obj, ResetType type) +{ + NPCM7xxCLKState *s = NPCM7XX_CLK(obj); + + QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values)); + + switch (type) { + case RESET_TYPE_COLD: + memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values)); + s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + return; + } + + /* + * A small number of registers need to be reset on a core domain reset, + * but no such reset type exists yet. + */ + qemu_log_mask(LOG_UNIMP, "%s: reset type %d not implemented.", + __func__, type); +} + +static void npcm7xx_clk_init(Object *obj) +{ + NPCM7xxCLKState *s = NPCM7XX_CLK(obj); + + memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s, + TYPE_NPCM7XX_CLK, 4 * KiB); + sysbus_init_mmio(&s->parent, &s->iomem); + qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset, + NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS); +} + +static const VMStateDescription vmstate_npcm7xx_clk = { + .name = "npcm7xx-clk", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS), + VMSTATE_INT64(ref_ns, NPCM7xxCLKState), + VMSTATE_END_OF_LIST(), + }, +}; + +static void npcm7xx_clk_class_init(ObjectClass *klass, void *data) +{ + ResettableClass *rc = RESETTABLE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + QEMU_BUILD_BUG_ON(NPCM7XX_CLK_REGS_END > NPCM7XX_CLK_NR_REGS); + + dc->desc = "NPCM7xx Clock Control Registers"; + dc->vmsd = &vmstate_npcm7xx_clk; + rc->phases.enter = npcm7xx_clk_enter_reset; +} + +static const TypeInfo npcm7xx_clk_info = { + .name = TYPE_NPCM7XX_CLK, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(NPCM7xxCLKState), + .instance_init = npcm7xx_clk_init, + .class_init = npcm7xx_clk_class_init, +}; + +static void npcm7xx_clk_register_type(void) +{ + type_register_static(&npcm7xx_clk_info); +} +type_init(npcm7xx_clk_register_type); diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c new file mode 100644 index 0000000000000000000000000000000000000000..745f69080975d5aa10867cc9eafab78f00deb3a3 --- /dev/null +++ b/hw/misc/npcm7xx_gcr.c @@ -0,0 +1,269 @@ +/* + * Nuvoton NPCM7xx System Global Control Registers. + * + * Copyright 2020 Google LLC + * + * 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. + */ + +#include "qemu/osdep.h" + +#include "hw/misc/npcm7xx_gcr.h" +#include "hw/qdev-properties.h" +#include "migration/vmstate.h" +#include "qapi/error.h" +#include "qemu/cutils.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/units.h" + +#include "trace.h" + +#define NPCM7XX_GCR_MIN_DRAM_SIZE (128 * MiB) +#define NPCM7XX_GCR_MAX_DRAM_SIZE (2 * GiB) + +enum NPCM7xxGCRRegisters { + NPCM7XX_GCR_PDID, + NPCM7XX_GCR_PWRON, + NPCM7XX_GCR_MFSEL1 = 0x0c / sizeof(uint32_t), + NPCM7XX_GCR_MFSEL2, + NPCM7XX_GCR_MISCPE, + NPCM7XX_GCR_SPSWC = 0x038 / sizeof(uint32_t), + NPCM7XX_GCR_INTCR, + NPCM7XX_GCR_INTSR, + NPCM7XX_GCR_HIFCR = 0x050 / sizeof(uint32_t), + NPCM7XX_GCR_INTCR2 = 0x060 / sizeof(uint32_t), + NPCM7XX_GCR_MFSEL3, + NPCM7XX_GCR_SRCNT, + NPCM7XX_GCR_RESSR, + NPCM7XX_GCR_RLOCKR1, + NPCM7XX_GCR_FLOCKR1, + NPCM7XX_GCR_DSCNT, + NPCM7XX_GCR_MDLR, + NPCM7XX_GCR_SCRPAD3, + NPCM7XX_GCR_SCRPAD2, + NPCM7XX_GCR_DAVCLVLR = 0x098 / sizeof(uint32_t), + NPCM7XX_GCR_INTCR3, + NPCM7XX_GCR_VSINTR = 0x0ac / sizeof(uint32_t), + NPCM7XX_GCR_MFSEL4, + NPCM7XX_GCR_CPBPNTR = 0x0c4 / sizeof(uint32_t), + NPCM7XX_GCR_CPCTL = 0x0d0 / sizeof(uint32_t), + NPCM7XX_GCR_CP2BST, + NPCM7XX_GCR_B2CPNT, + NPCM7XX_GCR_CPPCTL, + NPCM7XX_GCR_I2CSEGSEL, + NPCM7XX_GCR_I2CSEGCTL, + NPCM7XX_GCR_VSRCR, + NPCM7XX_GCR_MLOCKR, + NPCM7XX_GCR_SCRPAD = 0x013c / sizeof(uint32_t), + NPCM7XX_GCR_USB1PHYCTL, + NPCM7XX_GCR_USB2PHYCTL, + NPCM7XX_GCR_REGS_END, +}; + +static const uint32_t cold_reset_values[NPCM7XX_GCR_NR_REGS] = { + [NPCM7XX_GCR_PDID] = 0x04a92750, /* Poleg A1 */ + [NPCM7XX_GCR_MISCPE] = 0x0000ffff, + [NPCM7XX_GCR_SPSWC] = 0x00000003, + [NPCM7XX_GCR_INTCR] = 0x0000035e, + [NPCM7XX_GCR_HIFCR] = 0x0000004e, + [NPCM7XX_GCR_INTCR2] = (1U << 19), /* DDR initialized */ + [NPCM7XX_GCR_RESSR] = 0x80000000, + [NPCM7XX_GCR_DSCNT] = 0x000000c0, + [NPCM7XX_GCR_DAVCLVLR] = 0x5a00f3cf, + [NPCM7XX_GCR_SCRPAD] = 0x00000008, + [NPCM7XX_GCR_USB1PHYCTL] = 0x034730e4, + [NPCM7XX_GCR_USB2PHYCTL] = 0x034730e4, +}; + +static uint64_t npcm7xx_gcr_read(void *opaque, hwaddr offset, unsigned size) +{ + uint32_t reg = offset / sizeof(uint32_t); + NPCM7xxGCRState *s = opaque; + + if (reg >= NPCM7XX_GCR_NR_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: offset 0x%04" HWADDR_PRIx " out of range\n", + __func__, offset); + return 0; + } + + trace_npcm7xx_gcr_read(offset, s->regs[reg]); + + return s->regs[reg]; +} + +static void npcm7xx_gcr_write(void *opaque, hwaddr offset, + uint64_t v, unsigned size) +{ + uint32_t reg = offset / sizeof(uint32_t); + NPCM7xxGCRState *s = opaque; + uint32_t value = v; + + trace_npcm7xx_gcr_write(offset, value); + + if (reg >= NPCM7XX_GCR_NR_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: offset 0x%04" HWADDR_PRIx " out of range\n", + __func__, offset); + return; + } + + switch (reg) { + case NPCM7XX_GCR_PDID: + case NPCM7XX_GCR_PWRON: + case NPCM7XX_GCR_INTSR: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n", + __func__, offset); + return; + + case NPCM7XX_GCR_RESSR: + case NPCM7XX_GCR_CP2BST: + /* Write 1 to clear */ + value = s->regs[reg] & ~value; + break; + + case NPCM7XX_GCR_RLOCKR1: + case NPCM7XX_GCR_MDLR: + /* Write 1 to set */ + value |= s->regs[reg]; + break; + }; + + s->regs[reg] = value; +} + +static const struct MemoryRegionOps npcm7xx_gcr_ops = { + .read = npcm7xx_gcr_read, + .write = npcm7xx_gcr_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + .unaligned = false, + }, +}; + +static void npcm7xx_gcr_enter_reset(Object *obj, ResetType type) +{ + NPCM7xxGCRState *s = NPCM7XX_GCR(obj); + + QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values)); + + switch (type) { + case RESET_TYPE_COLD: + memcpy(s->regs, cold_reset_values, sizeof(s->regs)); + s->regs[NPCM7XX_GCR_PWRON] = s->reset_pwron; + s->regs[NPCM7XX_GCR_MDLR] = s->reset_mdlr; + s->regs[NPCM7XX_GCR_INTCR3] = s->reset_intcr3; + break; + } +} + +static void npcm7xx_gcr_realize(DeviceState *dev, Error **errp) +{ + ERRP_GUARD(); + NPCM7xxGCRState *s = NPCM7XX_GCR(dev); + uint64_t dram_size; + Object *obj; + + obj = object_property_get_link(OBJECT(dev), "dram-mr", errp); + if (!obj) { + error_prepend(errp, "%s: required dram-mr link not found: ", __func__); + return; + } + dram_size = memory_region_size(MEMORY_REGION(obj)); + if (!is_power_of_2(dram_size) || + dram_size < NPCM7XX_GCR_MIN_DRAM_SIZE || + dram_size > NPCM7XX_GCR_MAX_DRAM_SIZE) { + g_autofree char *sz = size_to_str(dram_size); + g_autofree char *min_sz = size_to_str(NPCM7XX_GCR_MIN_DRAM_SIZE); + g_autofree char *max_sz = size_to_str(NPCM7XX_GCR_MAX_DRAM_SIZE); + error_setg(errp, "%s: unsupported DRAM size %s", __func__, sz); + error_append_hint(errp, + "DRAM size must be a power of two between %s and %s," + " inclusive.\n", min_sz, max_sz); + return; + } + + /* Power-on reset value */ + s->reset_intcr3 = 0x00001002; + + /* + * The GMMAP (Graphics Memory Map) field is used by u-boot to detect the + * DRAM size, and is normally initialized by the boot block as part of DRAM + * training. However, since we don't have a complete emulation of the + * memory controller and try to make it look like it has already been + * initialized, the boot block will skip this initialization, and we need + * to make sure this field is set correctly up front. + * + * WARNING: some versions of u-boot only looks at bits 8 and 9, so 2 GiB of + * DRAM will be interpreted as 128 MiB. + * + * https://github.com/Nuvoton-Israel/u-boot/blob/2aef993bd2aafeb5408dbaad0f3ce099ee40c4aa/board/nuvoton/poleg/poleg.c#L244 + */ + s->reset_intcr3 |= ctz64(dram_size / NPCM7XX_GCR_MIN_DRAM_SIZE) << 8; +} + +static void npcm7xx_gcr_init(Object *obj) +{ + NPCM7xxGCRState *s = NPCM7XX_GCR(obj); + + memory_region_init_io(&s->iomem, obj, &npcm7xx_gcr_ops, s, + TYPE_NPCM7XX_GCR, 4 * KiB); + sysbus_init_mmio(&s->parent, &s->iomem); +} + +static const VMStateDescription vmstate_npcm7xx_gcr = { + .name = "npcm7xx-gcr", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, NPCM7xxGCRState, NPCM7XX_GCR_NR_REGS), + VMSTATE_END_OF_LIST(), + }, +}; + +static Property npcm7xx_gcr_properties[] = { + DEFINE_PROP_UINT32("disabled-modules", NPCM7xxGCRState, reset_mdlr, 0), + DEFINE_PROP_UINT32("power-on-straps", NPCM7xxGCRState, reset_pwron, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void npcm7xx_gcr_class_init(ObjectClass *klass, void *data) +{ + ResettableClass *rc = RESETTABLE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + QEMU_BUILD_BUG_ON(NPCM7XX_GCR_REGS_END > NPCM7XX_GCR_NR_REGS); + + dc->desc = "NPCM7xx System Global Control Registers"; + dc->realize = npcm7xx_gcr_realize; + dc->vmsd = &vmstate_npcm7xx_gcr; + rc->phases.enter = npcm7xx_gcr_enter_reset; + + device_class_set_props(dc, npcm7xx_gcr_properties); +} + +static const TypeInfo npcm7xx_gcr_info = { + .name = TYPE_NPCM7XX_GCR, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(NPCM7xxGCRState), + .instance_init = npcm7xx_gcr_init, + .class_init = npcm7xx_gcr_class_init, +}; + +static void npcm7xx_gcr_register_type(void) +{ + type_register_static(&npcm7xx_gcr_info); +} +type_init(npcm7xx_gcr_register_type); diff --git a/hw/misc/npcm7xx_rng.c b/hw/misc/npcm7xx_rng.c new file mode 100644 index 0000000000000000000000000000000000000000..f650f3401f865270c8bde7e04204eef22732deec --- /dev/null +++ b/hw/misc/npcm7xx_rng.c @@ -0,0 +1,180 @@ +/* + * Nuvoton NPCM7xx Random Number Generator. + * + * Copyright 2020 Google LLC + * + * 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. + */ + +#include "qemu/osdep.h" + +#include "hw/misc/npcm7xx_rng.h" +#include "migration/vmstate.h" +#include "qemu/bitops.h" +#include "qemu/guest-random.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/units.h" + +#include "trace.h" + +#define NPCM7XX_RNG_REGS_SIZE (4 * KiB) + +#define NPCM7XX_RNGCS (0x00) +#define NPCM7XX_RNGCS_CLKP(rv) extract32(rv, 2, 4) +#define NPCM7XX_RNGCS_DVALID BIT(1) +#define NPCM7XX_RNGCS_RNGE BIT(0) + +#define NPCM7XX_RNGD (0x04) +#define NPCM7XX_RNGMODE (0x08) +#define NPCM7XX_RNGMODE_NORMAL (0x02) + +static bool npcm7xx_rng_is_enabled(NPCM7xxRNGState *s) +{ + return (s->rngcs & NPCM7XX_RNGCS_RNGE) && + (s->rngmode == NPCM7XX_RNGMODE_NORMAL); +} + +static uint64_t npcm7xx_rng_read(void *opaque, hwaddr offset, unsigned size) +{ + NPCM7xxRNGState *s = opaque; + uint64_t value = 0; + + switch (offset) { + case NPCM7XX_RNGCS: + /* + * If the RNG is enabled, but we don't have any valid random data, try + * obtaining some and update the DVALID bit accordingly. + */ + if (!npcm7xx_rng_is_enabled(s)) { + s->rngcs &= ~NPCM7XX_RNGCS_DVALID; + } else if (!(s->rngcs & NPCM7XX_RNGCS_DVALID)) { + uint8_t byte = 0; + + if (qemu_guest_getrandom(&byte, sizeof(byte), NULL) == 0) { + s->rngd = byte; + s->rngcs |= NPCM7XX_RNGCS_DVALID; + } + } + value = s->rngcs; + break; + case NPCM7XX_RNGD: + if (npcm7xx_rng_is_enabled(s) && s->rngcs & NPCM7XX_RNGCS_DVALID) { + s->rngcs &= ~NPCM7XX_RNGCS_DVALID; + value = s->rngd; + s->rngd = 0; + } + break; + case NPCM7XX_RNGMODE: + value = s->rngmode; + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: read from invalid offset 0x%" HWADDR_PRIx "\n", + DEVICE(s)->canonical_path, offset); + break; + } + + trace_npcm7xx_rng_read(offset, value, size); + + return value; +} + +static void npcm7xx_rng_write(void *opaque, hwaddr offset, uint64_t value, + unsigned size) +{ + NPCM7xxRNGState *s = opaque; + + trace_npcm7xx_rng_write(offset, value, size); + + switch (offset) { + case NPCM7XX_RNGCS: + s->rngcs &= NPCM7XX_RNGCS_DVALID; + s->rngcs |= value & ~NPCM7XX_RNGCS_DVALID; + break; + case NPCM7XX_RNGD: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: write to read-only register @ 0x%" HWADDR_PRIx "\n", + DEVICE(s)->canonical_path, offset); + break; + case NPCM7XX_RNGMODE: + s->rngmode = value; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: write to invalid offset 0x%" HWADDR_PRIx "\n", + DEVICE(s)->canonical_path, offset); + break; + } +} + +static const MemoryRegionOps npcm7xx_rng_ops = { + .read = npcm7xx_rng_read, + .write = npcm7xx_rng_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + .unaligned = false, + }, +}; + +static void npcm7xx_rng_enter_reset(Object *obj, ResetType type) +{ + NPCM7xxRNGState *s = NPCM7XX_RNG(obj); + + s->rngcs = 0; + s->rngd = 0; + s->rngmode = 0; +} + +static void npcm7xx_rng_init(Object *obj) +{ + NPCM7xxRNGState *s = NPCM7XX_RNG(obj); + + memory_region_init_io(&s->iomem, obj, &npcm7xx_rng_ops, s, "regs", + NPCM7XX_RNG_REGS_SIZE); + sysbus_init_mmio(&s->parent, &s->iomem); +} + +static const VMStateDescription vmstate_npcm7xx_rng = { + .name = "npcm7xx-rng", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT8(rngcs, NPCM7xxRNGState), + VMSTATE_UINT8(rngd, NPCM7xxRNGState), + VMSTATE_UINT8(rngmode, NPCM7xxRNGState), + VMSTATE_END_OF_LIST(), + }, +}; + +static void npcm7xx_rng_class_init(ObjectClass *klass, void *data) +{ + ResettableClass *rc = RESETTABLE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "NPCM7xx Random Number Generator"; + dc->vmsd = &vmstate_npcm7xx_rng; + rc->phases.enter = npcm7xx_rng_enter_reset; +} + +static const TypeInfo npcm7xx_rng_types[] = { + { + .name = TYPE_NPCM7XX_RNG, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(NPCM7xxRNGState), + .class_init = npcm7xx_rng_class_init, + .instance_init = npcm7xx_rng_init, + }, +}; +DEFINE_TYPES(npcm7xx_rng_types); diff --git a/hw/misc/pc-testdev.c b/hw/misc/pc-testdev.c index 8aa8e6549f53ce77753ef21610568d3c38618749..e38965186942e4612f5563550e64c41f9e1814e8 100644 --- a/hw/misc/pc-testdev.c +++ b/hw/misc/pc-testdev.c @@ -39,10 +39,11 @@ #include "qemu/module.h" #include "hw/irq.h" #include "hw/isa/isa.h" +#include "qom/object.h" #define IOMEM_LEN 0x10000 -typedef struct PCTestdev { +struct PCTestdev { ISADevice parent_obj; MemoryRegion ioport; @@ -52,11 +53,10 @@ typedef struct PCTestdev { MemoryRegion iomem; uint32_t ioport_data; char iomem_buf[IOMEM_LEN]; -} PCTestdev; +}; #define TYPE_TESTDEV "pc-testdev" -#define TESTDEV(obj) \ - OBJECT_CHECK(PCTestdev, (obj), TYPE_TESTDEV) +OBJECT_DECLARE_SIMPLE_TYPE(PCTestdev, TESTDEV) static uint64_t test_irq_line_read(void *opaque, hwaddr addr, unsigned size) { diff --git a/hw/misc/pca9552.c b/hw/misc/pca9552.c index cac729e35afcd64d38588f00973e8d4683ae2503..b7686e27d7fac579c557e54be7c08253d2508cfd 100644 --- a/hw/misc/pca9552.c +++ b/hw/misc/pca9552.c @@ -4,6 +4,7 @@ * https://www.nxp.com/docs/en/application-note/AN264.pdf * * Copyright (c) 2017-2018, IBM Corporation. + * Copyright (c) 2020 Philippe Mathieu-DaudĂ© * * This work is licensed under the terms of the GNU GPL, version 2 or * later. See the COPYING file in the top-level directory. @@ -12,11 +13,29 @@ #include "qemu/osdep.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qemu/bitops.h" +#include "hw/qdev-properties.h" #include "hw/misc/pca9552.h" #include "hw/misc/pca9552_regs.h" +#include "hw/irq.h" #include "migration/vmstate.h" #include "qapi/error.h" #include "qapi/visitor.h" +#include "trace.h" +#include "qom/object.h" + +struct PCA955xClass { + /*< private >*/ + I2CSlaveClass parent_class; + /*< public >*/ + + uint8_t pin_count; + uint8_t max_reg; +}; +typedef struct PCA955xClass PCA955xClass; + +DECLARE_CLASS_CHECKERS(PCA955xClass, PCA955X, + TYPE_PCA955X) #define PCA9552_LED_ON 0x0 #define PCA9552_LED_OFF 0x1 @@ -25,7 +44,7 @@ static const char *led_state[] = {"on", "off", "pwm0", "pwm1"}; -static uint8_t pca9552_pin_get_config(PCA9552State *s, int pin) +static uint8_t pca955x_pin_get_config(PCA955xState *s, int pin) { uint8_t reg = PCA9552_LS0 + (pin / 4); uint8_t shift = (pin % 4) << 1; @@ -33,20 +52,71 @@ static uint8_t pca9552_pin_get_config(PCA9552State *s, int pin) return extract32(s->regs[reg], shift, 2); } -static void pca9552_update_pin_input(PCA9552State *s) +/* Return INPUT status (bit #N belongs to GPIO #N) */ +static uint16_t pca955x_pins_get_status(PCA955xState *s) +{ + return (s->regs[PCA9552_INPUT1] << 8) | s->regs[PCA9552_INPUT0]; +} + +static void pca955x_display_pins_status(PCA955xState *s, + uint16_t previous_pins_status) { + PCA955xClass *k = PCA955X_GET_CLASS(s); + uint16_t pins_status, pins_changed; int i; - for (i = 0; i < s->nr_leds; i++) { + pins_status = pca955x_pins_get_status(s); + pins_changed = previous_pins_status ^ pins_status; + if (!pins_changed) { + return; + } + if (trace_event_get_state_backends(TRACE_PCA955X_GPIO_STATUS)) { + char *buf = g_newa(char, k->pin_count + 1); + + for (i = 0; i < k->pin_count; i++) { + if (extract32(pins_status, i, 1)) { + buf[i] = '*'; + } else { + buf[i] = '.'; + } + } + buf[i] = '\0'; + trace_pca955x_gpio_status(s->description, buf); + } + if (trace_event_get_state_backends(TRACE_PCA955X_GPIO_CHANGE)) { + for (i = 0; i < k->pin_count; i++) { + if (extract32(pins_changed, i, 1)) { + unsigned new_state = extract32(pins_status, i, 1); + + /* + * We display the state using the PCA logic ("active-high"). + * This is not the state of the LED, which signal might be + * wired "active-low" on the board. + */ + trace_pca955x_gpio_change(s->description, i, + !new_state, new_state); + } + } + } +} + +static void pca955x_update_pin_input(PCA955xState *s) +{ + PCA955xClass *k = PCA955X_GET_CLASS(s); + int i; + + for (i = 0; i < k->pin_count; i++) { uint8_t input_reg = PCA9552_INPUT0 + (i / 8); uint8_t input_shift = (i % 8); - uint8_t config = pca9552_pin_get_config(s, i); + uint8_t config = pca955x_pin_get_config(s, i); switch (config) { case PCA9552_LED_ON: + qemu_set_irq(s->gpio[i], 1); s->regs[input_reg] |= 1 << input_shift; break; case PCA9552_LED_OFF: + qemu_set_irq(s->gpio[i], 0); s->regs[input_reg] &= ~(1 << input_shift); break; case PCA9552_LED_PWM0: @@ -58,7 +128,7 @@ static void pca9552_update_pin_input(PCA9552State *s) } } -static uint8_t pca9552_read(PCA9552State *s, uint8_t reg) +static uint8_t pca955x_read(PCA955xState *s, uint8_t reg) { switch (reg) { case PCA9552_INPUT0: @@ -79,8 +149,10 @@ static uint8_t pca9552_read(PCA9552State *s, uint8_t reg) } } -static void pca9552_write(PCA9552State *s, uint8_t reg, uint8_t data) +static void pca955x_write(PCA955xState *s, uint8_t reg, uint8_t data) { + uint16_t pins_status; + switch (reg) { case PCA9552_PSC0: case PCA9552_PWM0: @@ -93,8 +165,10 @@ static void pca9552_write(PCA9552State *s, uint8_t reg, uint8_t data) case PCA9552_LS1: case PCA9552_LS2: case PCA9552_LS3: + pins_status = pca955x_pins_get_status(s); s->regs[reg] = data; - pca9552_update_pin_input(s); + pca955x_update_pin_input(s); + pca955x_display_pins_status(s, pins_status); break; case PCA9552_INPUT0: @@ -110,22 +184,24 @@ static void pca9552_write(PCA9552State *s, uint8_t reg, uint8_t data) * after each byte is sent to or received by the device. The index * rollovers to 0 when the maximum register address is reached. */ -static void pca9552_autoinc(PCA9552State *s) +static void pca955x_autoinc(PCA955xState *s) { + PCA955xClass *k = PCA955X_GET_CLASS(s); + if (s->pointer != 0xFF && s->pointer & PCA9552_AUTOINC) { uint8_t reg = s->pointer & 0xf; - reg = (reg + 1) % (s->max_reg + 1); + reg = (reg + 1) % (k->max_reg + 1); s->pointer = reg | PCA9552_AUTOINC; } } -static uint8_t pca9552_recv(I2CSlave *i2c) +static uint8_t pca955x_recv(I2CSlave *i2c) { - PCA9552State *s = PCA9552(i2c); + PCA955xState *s = PCA955X(i2c); uint8_t ret; - ret = pca9552_read(s, s->pointer & 0xf); + ret = pca955x_read(s, s->pointer & 0xf); /* * From the Specs: @@ -143,40 +219,41 @@ static uint8_t pca9552_recv(I2CSlave *i2c) __func__); } - pca9552_autoinc(s); + pca955x_autoinc(s); return ret; } -static int pca9552_send(I2CSlave *i2c, uint8_t data) +static int pca955x_send(I2CSlave *i2c, uint8_t data) { - PCA9552State *s = PCA9552(i2c); + PCA955xState *s = PCA955X(i2c); /* First byte sent by is the register address */ if (s->len == 0) { s->pointer = data; s->len++; } else { - pca9552_write(s, s->pointer & 0xf, data); + pca955x_write(s, s->pointer & 0xf, data); - pca9552_autoinc(s); + pca955x_autoinc(s); } return 0; } -static int pca9552_event(I2CSlave *i2c, enum i2c_event event) +static int pca955x_event(I2CSlave *i2c, enum i2c_event event) { - PCA9552State *s = PCA9552(i2c); + PCA955xState *s = PCA955X(i2c); s->len = 0; return 0; } -static void pca9552_get_led(Object *obj, Visitor *v, const char *name, +static void pca955x_get_led(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - PCA9552State *s = PCA9552(obj); + PCA955xClass *k = PCA955X_GET_CLASS(obj); + PCA955xState *s = PCA955X(obj); int led, rc, reg; uint8_t state; @@ -185,7 +262,7 @@ static void pca9552_get_led(Object *obj, Visitor *v, const char *name, error_setg(errp, "%s: error reading %s", __func__, name); return; } - if (led < 0 || led > s->nr_leds) { + if (led < 0 || led > k->pin_count) { error_setg(errp, "%s invalid led %s", __func__, name); return; } @@ -195,7 +272,7 @@ static void pca9552_get_led(Object *obj, Visitor *v, const char *name, * reading the INPUTx reg */ reg = PCA9552_LS0 + led / 4; - state = (pca9552_read(s, reg) >> (led % 8)) & 0x3; + state = (pca955x_read(s, reg) >> (led % 8)) & 0x3; visit_type_str(v, name, (char **)&led_state[state], errp); } @@ -209,18 +286,16 @@ static inline uint8_t pca955x_ledsel(uint8_t oldval, int led_num, int state) ((state & 0x3) << (led_num << 1)); } -static void pca9552_set_led(Object *obj, Visitor *v, const char *name, +static void pca955x_set_led(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - PCA9552State *s = PCA9552(obj); - Error *local_err = NULL; + PCA955xClass *k = PCA955X_GET_CLASS(obj); + PCA955xState *s = PCA955X(obj); int led, rc, reg, val; uint8_t state; char *state_str; - visit_type_str(v, name, &state_str, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_str(v, name, &state_str, errp)) { return; } rc = sscanf(name, "led%2d", &led); @@ -228,7 +303,7 @@ static void pca9552_set_led(Object *obj, Visitor *v, const char *name, error_setg(errp, "%s: error reading %s", __func__, name); return; } - if (led < 0 || led > s->nr_leds) { + if (led < 0 || led > k->pin_count) { error_setg(errp, "%s invalid led %s", __func__, name); return; } @@ -244,9 +319,9 @@ static void pca9552_set_led(Object *obj, Visitor *v, const char *name, } reg = PCA9552_LS0 + led / 4; - val = pca9552_read(s, reg); + val = pca955x_read(s, reg); val = pca955x_ledsel(val, led % 4, state); - pca9552_write(s, reg, val); + pca955x_write(s, reg, val); } static const VMStateDescription pca9552_vmstate = { @@ -254,17 +329,17 @@ static const VMStateDescription pca9552_vmstate = { .version_id = 0, .minimum_version_id = 0, .fields = (VMStateField[]) { - VMSTATE_UINT8(len, PCA9552State), - VMSTATE_UINT8(pointer, PCA9552State), - VMSTATE_UINT8_ARRAY(regs, PCA9552State, PCA9552_NR_REGS), - VMSTATE_I2C_SLAVE(i2c, PCA9552State), + VMSTATE_UINT8(len, PCA955xState), + VMSTATE_UINT8(pointer, PCA955xState), + VMSTATE_UINT8_ARRAY(regs, PCA955xState, PCA955X_NR_REGS), + VMSTATE_I2C_SLAVE(i2c, PCA955xState), VMSTATE_END_OF_LIST() } }; static void pca9552_reset(DeviceState *dev) { - PCA9552State *s = PCA9552(dev); + PCA955xState *s = PCA955X(dev); s->regs[PCA9552_PSC0] = 0xFF; s->regs[PCA9552_PWM0] = 0x80; @@ -275,57 +350,88 @@ static void pca9552_reset(DeviceState *dev) s->regs[PCA9552_LS2] = 0x55; s->regs[PCA9552_LS3] = 0x55; - pca9552_update_pin_input(s); + pca955x_update_pin_input(s); s->pointer = 0xFF; s->len = 0; } -static void pca9552_initfn(Object *obj) +static void pca955x_initfn(Object *obj) { - PCA9552State *s = PCA9552(obj); + PCA955xClass *k = PCA955X_GET_CLASS(obj); int led; - /* If support for the other PCA955X devices are implemented, these - * constant values might be part of class structure describing the - * PCA955X device - */ - s->max_reg = PCA9552_LS3; - s->nr_leds = 16; - - for (led = 0; led < s->nr_leds; led++) { + assert(k->pin_count <= PCA955X_PIN_COUNT_MAX); + for (led = 0; led < k->pin_count; led++) { char *name; name = g_strdup_printf("led%d", led); - object_property_add(obj, name, "bool", pca9552_get_led, pca9552_set_led, + object_property_add(obj, name, "bool", pca955x_get_led, pca955x_set_led, NULL, NULL); g_free(name); } } -static void pca9552_class_init(ObjectClass *klass, void *data) +static void pca955x_realize(DeviceState *dev, Error **errp) +{ + PCA955xClass *k = PCA955X_GET_CLASS(dev); + PCA955xState *s = PCA955X(dev); + + if (!s->description) { + s->description = g_strdup("pca-unspecified"); + } + + qdev_init_gpio_out(dev, s->gpio, k->pin_count); +} + +static Property pca955x_properties[] = { + DEFINE_PROP_STRING("description", PCA955xState, description), + DEFINE_PROP_END_OF_LIST(), +}; + +static void pca955x_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); I2CSlaveClass *k = I2C_SLAVE_CLASS(klass); - k->event = pca9552_event; - k->recv = pca9552_recv; - k->send = pca9552_send; + k->event = pca955x_event; + k->recv = pca955x_recv; + k->send = pca955x_send; + dc->realize = pca955x_realize; + device_class_set_props(dc, pca955x_properties); +} + +static const TypeInfo pca955x_info = { + .name = TYPE_PCA955X, + .parent = TYPE_I2C_SLAVE, + .instance_init = pca955x_initfn, + .instance_size = sizeof(PCA955xState), + .class_init = pca955x_class_init, + .class_size = sizeof(PCA955xClass), + .abstract = true, +}; + +static void pca9552_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + PCA955xClass *pc = PCA955X_CLASS(oc); + dc->reset = pca9552_reset; dc->vmsd = &pca9552_vmstate; + pc->max_reg = PCA9552_LS3; + pc->pin_count = 16; } static const TypeInfo pca9552_info = { .name = TYPE_PCA9552, - .parent = TYPE_I2C_SLAVE, - .instance_init = pca9552_initfn, - .instance_size = sizeof(PCA9552State), + .parent = TYPE_PCA955X, .class_init = pca9552_class_init, }; -static void pca9552_register_types(void) +static void pca955x_register_types(void) { + type_register_static(&pca955x_info); type_register_static(&pca9552_info); } -type_init(pca9552_register_types) +type_init(pca955x_register_types) diff --git a/hw/misc/pci-testdev.c b/hw/misc/pci-testdev.c index 188de4d9cc03186f999b8cfd46495b909e1fbc8d..03845c8de343c3871e97b6fb521d8e2b872c48ed 100644 --- a/hw/misc/pci-testdev.c +++ b/hw/misc/pci-testdev.c @@ -24,6 +24,7 @@ #include "qemu/event_notifier.h" #include "qemu/module.h" #include "sysemu/kvm.h" +#include "qom/object.h" typedef struct PCITestDevHdr { uint8_t test; @@ -78,7 +79,7 @@ enum { #define IOTEST_ACCESS_TYPE uint8_t #define IOTEST_ACCESS_WIDTH (sizeof(uint8_t)) -typedef struct PCITestDevState { +struct PCITestDevState { /*< private >*/ PCIDevice parent_obj; /*< public >*/ @@ -90,12 +91,11 @@ typedef struct PCITestDevState { uint64_t membar_size; MemoryRegion membar; -} PCITestDevState; +}; #define TYPE_PCI_TEST_DEV "pci-testdev" -#define PCI_TEST_DEV(obj) \ - OBJECT_CHECK(PCITestDevState, (obj), TYPE_PCI_TEST_DEV) +OBJECT_DECLARE_SIMPLE_TYPE(PCITestDevState, PCI_TEST_DEV) #define IOTEST_IS_MEM(i) (strcmp(IOTEST_TYPE(i), "portio")) #define IOTEST_REGION(d, i) (IOTEST_IS_MEM(i) ? &(d)->mmio : &(d)->portio) diff --git a/hw/misc/puv3_pm.c b/hw/misc/puv3_pm.c index c213500d9c3c1122af47c3d0bec1408699190571..676c23f7dbc292f4159f6b3052d4d2c9104c1e82 100644 --- a/hw/misc/puv3_pm.c +++ b/hw/misc/puv3_pm.c @@ -11,15 +11,17 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" +#include "qom/object.h" #undef DEBUG_PUV3 #include "hw/unicore32/puv3.h" #include "qemu/module.h" +#include "qemu/log.h" #define TYPE_PUV3_PM "puv3_pm" -#define PUV3_PM(obj) OBJECT_CHECK(PUV3PMState, (obj), TYPE_PUV3_PM) +OBJECT_DECLARE_SIMPLE_TYPE(PUV3PMState, PUV3_PM) -typedef struct PUV3PMState { +struct PUV3PMState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -30,7 +32,7 @@ typedef struct PUV3PMState { uint32_t reg_PLL_DDR_CFG; uint32_t reg_PLL_VGA_CFG; uint32_t reg_DIVCFG; -} PUV3PMState; +}; static uint64_t puv3_pm_read(void *opaque, hwaddr offset, unsigned size) @@ -73,7 +75,9 @@ static uint64_t puv3_pm_read(void *opaque, hwaddr offset, ret = 0x7; break; default: - DPRINTF("Bad offset 0x%x\n", offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad read offset 0x%"HWADDR_PRIx"\n", + __func__, offset); } DPRINTF("offset 0x%x, value 0x%x\n", offset, ret); @@ -105,7 +109,9 @@ static void puv3_pm_write(void *opaque, hwaddr offset, case 0x38: break; default: - DPRINTF("Bad offset 0x%x\n", offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad write offset 0x%"HWADDR_PRIx"\n", + __func__, offset); } DPRINTF("offset 0x%x, value 0x%x\n", offset, value); } diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c index abb10bbcaf6ebab6c9c49b76b84d61dcc5bd6042..35d6797831db483887c79d844f5d0351d66e5ba5 100644 --- a/hw/misc/pvpanic.c +++ b/hw/misc/pvpanic.c @@ -20,6 +20,7 @@ #include "hw/nvram/fw_cfg.h" #include "hw/qdev-properties.h" #include "hw/misc/pvpanic.h" +#include "qom/object.h" /* The bit of supported pv event, TODO: include uapi header and remove this */ #define PVPANIC_F_PANICKED 0 @@ -29,8 +30,9 @@ #define PVPANIC_PANICKED (1 << PVPANIC_F_PANICKED) #define PVPANIC_CRASHLOADED (1 << PVPANIC_F_CRASHLOADED) -#define ISA_PVPANIC_DEVICE(obj) \ - OBJECT_CHECK(PVPanicState, (obj), TYPE_PVPANIC) +typedef struct PVPanicState PVPanicState; +DECLARE_INSTANCE_CHECKER(PVPanicState, ISA_PVPANIC_DEVICE, + TYPE_PVPANIC) static void handle_event(int event) { @@ -54,17 +56,19 @@ static void handle_event(int event) #include "hw/isa/isa.h" -typedef struct PVPanicState { +struct PVPanicState { ISADevice parent_obj; MemoryRegion io; uint16_t ioport; -} PVPanicState; + uint8_t events; +}; /* return supported events on read */ static uint64_t pvpanic_ioport_read(void *opaque, hwaddr addr, unsigned size) { - return PVPANIC_PANICKED; + PVPanicState *pvp = opaque; + return pvp->events; } static void pvpanic_ioport_write(void *opaque, hwaddr addr, uint64_t val, @@ -110,6 +114,7 @@ static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp) static Property pvpanic_isa_properties[] = { DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicState, ioport, 0x505), + DEFINE_PROP_UINT8("events", PVPanicState, events, PVPANIC_PANICKED | PVPANIC_CRASHLOADED), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/misc/sbsa_ec.c b/hw/misc/sbsa_ec.c new file mode 100644 index 0000000000000000000000000000000000000000..9a7d7f914a9767294c3b8ea8e95d46a23932575c --- /dev/null +++ b/hw/misc/sbsa_ec.c @@ -0,0 +1,98 @@ +/* + * ARM SBSA Reference Platform Embedded Controller + * + * A device to allow PSCI running in the secure side of sbsa-ref machine + * to communicate platform power states to qemu. + * + * Copyright (c) 2020 Nuvia Inc + * Written by Graeme Gregory + * + * SPDX-License-Identifer: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/log.h" +#include "hw/sysbus.h" +#include "sysemu/runstate.h" + +typedef struct { + SysBusDevice parent_obj; + MemoryRegion iomem; +} SECUREECState; + +#define TYPE_SBSA_EC "sbsa-ec" +#define SECURE_EC(obj) OBJECT_CHECK(SECUREECState, (obj), TYPE_SBSA_EC) + +enum sbsa_ec_powerstates { + SBSA_EC_CMD_POWEROFF = 0x01, + SBSA_EC_CMD_REBOOT = 0x02, +}; + +static uint64_t sbsa_ec_read(void *opaque, hwaddr offset, unsigned size) +{ + /* No use for this currently */ + qemu_log_mask(LOG_GUEST_ERROR, "sbsa-ec: no readable registers"); + return 0; +} + +static void sbsa_ec_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + if (offset == 0) { /* PSCI machine power command register */ + switch (value) { + case SBSA_EC_CMD_POWEROFF: + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + break; + case SBSA_EC_CMD_REBOOT: + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "sbsa-ec: unknown power command"); + } + } else { + qemu_log_mask(LOG_GUEST_ERROR, "sbsa-ec: unknown EC register"); + } +} + +static const MemoryRegionOps sbsa_ec_ops = { + .read = sbsa_ec_read, + .write = sbsa_ec_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid.min_access_size = 4, + .valid.max_access_size = 4, +}; + +static void sbsa_ec_init(Object *obj) +{ + SECUREECState *s = SECURE_EC(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &sbsa_ec_ops, s, "sbsa-ec", + 0x1000); + sysbus_init_mmio(dev, &s->iomem); +} + +static void sbsa_ec_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + /* No vmstate or reset required: device has no internal state */ + dc->user_creatable = false; +} + +static const TypeInfo sbsa_ec_info = { + .name = TYPE_SBSA_EC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SECUREECState), + .instance_init = sbsa_ec_init, + .class_init = sbsa_ec_class_init, +}; + +static void sbsa_ec_register_type(void) +{ + type_register_static(&sbsa_ec_info); +} + +type_init(sbsa_ec_register_type); diff --git a/hw/misc/sga.c b/hw/misc/sga.c index 6866bf72cb7c5ebea51a1a07b036b5cb05715899..4dbe6d78f9e5251e4ee30ba9a756755b4fa38b70 100644 --- a/hw/misc/sga.c +++ b/hw/misc/sga.c @@ -29,15 +29,16 @@ #include "hw/isa/isa.h" #include "hw/loader.h" #include "qemu/module.h" +#include "qom/object.h" #define SGABIOS_FILENAME "sgabios.bin" #define TYPE_SGA "sga" -#define SGA(obj) OBJECT_CHECK(ISASGAState, (obj), TYPE_SGA) +OBJECT_DECLARE_SIMPLE_TYPE(ISASGAState, SGA) -typedef struct ISASGAState { +struct ISASGAState { ISADevice parent_obj; -} ISASGAState; +}; static void sga_realizefn(DeviceState *dev, Error **errp) { diff --git a/hw/riscv/sifive_e_prci.c b/hw/misc/sifive_e_prci.c similarity index 95% rename from hw/riscv/sifive_e_prci.c rename to hw/misc/sifive_e_prci.c index a1c0d44f18af1ae011bb27216e88a60851ec2ea9..8ec4ee4b41fc0bce9ce77362ba086496a0b1c185 100644 --- a/hw/riscv/sifive_e_prci.c +++ b/hw/misc/sifive_e_prci.c @@ -20,10 +20,11 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" +#include "qapi/error.h" #include "qemu/log.h" #include "qemu/module.h" #include "hw/hw.h" -#include "hw/riscv/sifive_e_prci.h" +#include "hw/misc/sifive_e_prci.h" static uint64_t sifive_e_prci_read(void *opaque, hwaddr addr, unsigned int size) { @@ -117,8 +118,8 @@ type_init(sifive_e_prci_register_types) */ DeviceState *sifive_e_prci_create(hwaddr addr) { - DeviceState *dev = qdev_create(NULL, TYPE_SIFIVE_E_PRCI); - qdev_init_nofail(dev); + DeviceState *dev = qdev_new(TYPE_SIFIVE_E_PRCI); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); return dev; } diff --git a/hw/riscv/sifive_test.c b/hw/misc/sifive_test.c similarity index 92% rename from hw/riscv/sifive_test.c rename to hw/misc/sifive_test.c index 339195c6ffcef267e2e4acf8a87f2bf0b56e2bdd..2deb2072cc8e198c6788f7a34ba97f8f45fe4cdb 100644 --- a/hw/riscv/sifive_test.c +++ b/hw/misc/sifive_test.c @@ -20,11 +20,12 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" +#include "qapi/error.h" #include "qemu/log.h" #include "qemu/module.h" #include "sysemu/runstate.h" #include "hw/hw.h" -#include "hw/riscv/sifive_test.h" +#include "hw/misc/sifive_test.h" static uint64_t sifive_test_read(void *opaque, hwaddr addr, unsigned int size) { @@ -58,7 +59,7 @@ static const MemoryRegionOps sifive_test_ops = { .write = sifive_test_write, .endianness = DEVICE_NATIVE_ENDIAN, .valid = { - .min_access_size = 4, + .min_access_size = 2, .max_access_size = 4 } }; @@ -92,8 +93,8 @@ type_init(sifive_test_register_types) */ DeviceState *sifive_test_create(hwaddr addr) { - DeviceState *dev = qdev_create(NULL, TYPE_SIFIVE_TEST); - qdev_init_nofail(dev); + DeviceState *dev = qdev_new(TYPE_SIFIVE_TEST); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); return dev; } diff --git a/hw/riscv/sifive_u_otp.c b/hw/misc/sifive_u_otp.c similarity index 63% rename from hw/riscv/sifive_u_otp.c rename to hw/misc/sifive_u_otp.c index f6ecbaa2caad04b7d993367b9236491541788ae1..60066375abddfa4e74e424b7d6930a95a877117a 100644 --- a/hw/riscv/sifive_u_otp.c +++ b/hw/misc/sifive_u_otp.c @@ -19,11 +19,22 @@ */ #include "qemu/osdep.h" +#include "qapi/error.h" #include "hw/qdev-properties.h" #include "hw/sysbus.h" #include "qemu/log.h" #include "qemu/module.h" -#include "hw/riscv/sifive_u_otp.h" +#include "hw/misc/sifive_u_otp.h" +#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" + +#define WRITTEN_BIT_ON 0x1 + +#define SET_FUSEARRAY_BIT(map, i, off, bit) \ + map[i] = bit ? (map[i] | bit << off) : (map[i] & ~(0x1 << off)) + +#define GET_FUSEARRAY_BIT(map, i, off) \ + ((map[i] >> off) & 0x1) static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size) { @@ -46,6 +57,16 @@ static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size) if ((s->pce & SIFIVE_U_OTP_PCE_EN) && (s->pdstb & SIFIVE_U_OTP_PDSTB_EN) && (s->ptrim & SIFIVE_U_OTP_PTRIM_EN)) { + + /* read from backend */ + if (s->blk) { + int32_t buf; + + blk_pread(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &buf, + SIFIVE_U_OTP_FUSE_WORD); + return buf; + } + return s->fuse[s->pa & SIFIVE_U_OTP_PA_MASK]; } else { return 0xff; @@ -123,7 +144,30 @@ static void sifive_u_otp_write(void *opaque, hwaddr addr, s->ptrim = val32; break; case SIFIVE_U_OTP_PWE: - s->pwe = val32; + s->pwe = val32 & SIFIVE_U_OTP_PWE_EN; + + /* PWE is enabled. Ignore PAS=1 (no redundancy cell) */ + if (s->pwe && !s->pas) { + if (GET_FUSEARRAY_BIT(s->fuse_wo, s->pa, s->paio)) { + qemu_log_mask(LOG_GUEST_ERROR, + "write once error: idx<%u>, bit<%u>\n", + s->pa, s->paio); + break; + } + + /* write bit data */ + SET_FUSEARRAY_BIT(s->fuse, s->pa, s->paio, s->pdin); + + /* write to backend */ + if (s->blk) { + blk_pwrite(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, + &s->fuse[s->pa], SIFIVE_U_OTP_FUSE_WORD, 0); + } + + /* update written bit */ + SET_FUSEARRAY_BIT(s->fuse_wo, s->pa, s->paio, WRITTEN_BIT_ON); + } + break; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx @@ -143,16 +187,48 @@ static const MemoryRegionOps sifive_u_otp_ops = { static Property sifive_u_otp_properties[] = { DEFINE_PROP_UINT32("serial", SiFiveUOTPState, serial, 0), + DEFINE_PROP_DRIVE("drive", SiFiveUOTPState, blk), DEFINE_PROP_END_OF_LIST(), }; static void sifive_u_otp_realize(DeviceState *dev, Error **errp) { SiFiveUOTPState *s = SIFIVE_U_OTP(dev); + DriveInfo *dinfo; memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_otp_ops, s, TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); + + dinfo = drive_get_next(IF_NONE); + if (dinfo) { + int ret; + uint64_t perm; + int filesize; + BlockBackend *blk; + + blk = blk_by_legacy_dinfo(dinfo); + filesize = SIFIVE_U_OTP_NUM_FUSES * SIFIVE_U_OTP_FUSE_WORD; + if (blk_getlength(blk) < filesize) { + error_setg(errp, "OTP drive size < 16K"); + return; + } + + qdev_prop_set_drive_err(dev, "drive", blk, errp); + + if (s->blk) { + perm = BLK_PERM_CONSISTENT_READ | + (blk_is_read_only(s->blk) ? 0 : BLK_PERM_WRITE); + ret = blk_set_perm(s->blk, perm, BLK_PERM_ALL, errp); + if (ret < 0) { + return; + } + + if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) { + error_setg(errp, "failed to read the initial flash content"); + } + } + } } static void sifive_u_otp_reset(DeviceState *dev) @@ -165,6 +241,23 @@ static void sifive_u_otp_reset(DeviceState *dev) /* Make a valid content of serial number */ s->fuse[SIFIVE_U_OTP_SERIAL_ADDR] = s->serial; s->fuse[SIFIVE_U_OTP_SERIAL_ADDR + 1] = ~(s->serial); + + if (s->blk) { + /* Put serial number to backend as well*/ + uint32_t serial_data; + int index = SIFIVE_U_OTP_SERIAL_ADDR; + + serial_data = s->serial; + blk_pwrite(s->blk, index * SIFIVE_U_OTP_FUSE_WORD, + &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0); + + serial_data = ~(s->serial); + blk_pwrite(s->blk, (index + 1) * SIFIVE_U_OTP_FUSE_WORD, + &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0); + } + + /* Initialize write-once map */ + memset(s->fuse_wo, 0x00, sizeof(s->fuse_wo)); } static void sifive_u_otp_class_init(ObjectClass *klass, void *data) diff --git a/hw/riscv/sifive_u_prci.c b/hw/misc/sifive_u_prci.c similarity index 99% rename from hw/riscv/sifive_u_prci.c rename to hw/misc/sifive_u_prci.c index 4fa590c064f85a61b954bb8cb7aeb220ea78543b..5d9d446ee8633f8fc512b0858e766fce9ac6d619 100644 --- a/hw/riscv/sifive_u_prci.c +++ b/hw/misc/sifive_u_prci.c @@ -22,7 +22,7 @@ #include "hw/sysbus.h" #include "qemu/log.h" #include "qemu/module.h" -#include "hw/riscv/sifive_u_prci.h" +#include "hw/misc/sifive_u_prci.h" static uint64_t sifive_u_prci_read(void *opaque, hwaddr addr, unsigned int size) { diff --git a/hw/misc/slavio_misc.c b/hw/misc/slavio_misc.c index 279b38dfc736ea12b38e343a0081079f2310d9c3..e8eb71570a89d56c74252d6e9d84b15fc602a6b8 100644 --- a/hw/misc/slavio_misc.c +++ b/hw/misc/slavio_misc.c @@ -29,6 +29,7 @@ #include "qemu/module.h" #include "sysemu/runstate.h" #include "trace.h" +#include "qom/object.h" /* * This is the auxio port, chip control and system control part of @@ -39,9 +40,9 @@ */ #define TYPE_SLAVIO_MISC "slavio_misc" -#define SLAVIO_MISC(obj) OBJECT_CHECK(MiscState, (obj), TYPE_SLAVIO_MISC) +OBJECT_DECLARE_SIMPLE_TYPE(MiscState, SLAVIO_MISC) -typedef struct MiscState { +struct MiscState { SysBusDevice parent_obj; MemoryRegion cfg_iomem; @@ -59,17 +60,19 @@ typedef struct MiscState { uint8_t diag, mctrl; uint8_t sysctrl; uint16_t leds; -} MiscState; +}; #define TYPE_APC "apc" -#define APC(obj) OBJECT_CHECK(APCState, (obj), TYPE_APC) +typedef struct APCState APCState; +DECLARE_INSTANCE_CHECKER(APCState, APC, + TYPE_APC) -typedef struct APCState { +struct APCState { SysBusDevice parent_obj; MemoryRegion iomem; qemu_irq cpu_halt; -} APCState; +}; #define MISC_SIZE 1 #define LED_SIZE 2 diff --git a/hw/misc/stm32f2xx_syscfg.c b/hw/misc/stm32f2xx_syscfg.c index aa59b43549845a680b5a180188dab45f34768407..04c22c2850250210f0d1918cede8589343475b55 100644 --- a/hw/misc/stm32f2xx_syscfg.c +++ b/hw/misc/stm32f2xx_syscfg.c @@ -133,8 +133,6 @@ static void stm32f2xx_syscfg_init(Object *obj) { STM32F2XXSyscfgState *s = STM32F2XX_SYSCFG(obj); - sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); - memory_region_init_io(&s->mmio, obj, &stm32f2xx_syscfg_ops, s, TYPE_STM32F2XX_SYSCFG, 0x400); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); diff --git a/hw/misc/tmp105.c b/hw/misc/tmp105.c index 58dbebca905622ea958b0c8f53f4d32c7fe76669..d299d9b21b762710db246432b12c343b3d7043db 100644 --- a/hw/misc/tmp105.c +++ b/hw/misc/tmp105.c @@ -41,16 +41,40 @@ static void tmp105_alarm_update(TMP105State *s) return; } - if ((s->config >> 1) & 1) { /* TM */ - if (s->temperature >= s->limit[1]) - s->alarm = 1; - else if (s->temperature < s->limit[0]) - s->alarm = 1; + if (s->config >> 1 & 1) { + /* + * TM == 1 : Interrupt mode. We signal Alert when the + * temperature rises above T_high, and expect the guest to clear + * it (eg by reading a device register). + */ + if (s->detect_falling) { + if (s->temperature < s->limit[0]) { + s->alarm = 1; + s->detect_falling = false; + } + } else { + if (s->temperature >= s->limit[1]) { + s->alarm = 1; + s->detect_falling = true; + } + } } else { - if (s->temperature >= s->limit[1]) - s->alarm = 1; - else if (s->temperature < s->limit[0]) - s->alarm = 0; + /* + * TM == 0 : Comparator mode. We signal Alert when the temperature + * rises above T_high, and stop signalling it when the temperature + * falls below T_low. + */ + if (s->detect_falling) { + if (s->temperature < s->limit[0]) { + s->alarm = 0; + s->detect_falling = false; + } + } else { + if (s->temperature >= s->limit[1]) { + s->alarm = 1; + s->detect_falling = true; + } + } } tmp105_interrupt_update(s); @@ -72,12 +96,9 @@ static void tmp105_set_temperature(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { TMP105State *s = TMP105(obj); - Error *local_err = NULL; int64_t temp; - visit_type_int(v, name, &temp, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_int(v, name, &temp, errp)) { return; } if (temp >= 128000 || temp < -128000) { @@ -200,6 +221,29 @@ static int tmp105_post_load(void *opaque, int version_id) return 0; } +static bool detect_falling_needed(void *opaque) +{ + TMP105State *s = opaque; + + /* + * We only need to migrate the detect_falling bool if it's set; + * for migration from older machines we assume that it is false + * (ie temperature is not out of range). + */ + return s->detect_falling; +} + +static const VMStateDescription vmstate_tmp105_detect_falling = { + .name = "TMP105/detect-falling", + .version_id = 1, + .minimum_version_id = 1, + .needed = detect_falling_needed, + .fields = (VMStateField[]) { + VMSTATE_BOOL(detect_falling, TMP105State), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_tmp105 = { .name = "TMP105", .version_id = 0, @@ -215,6 +259,10 @@ static const VMStateDescription vmstate_tmp105 = { VMSTATE_UINT8(alarm, TMP105State), VMSTATE_I2C_SLAVE(i2c, TMP105State), VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription*[]) { + &vmstate_tmp105_detect_falling, + NULL } }; @@ -227,6 +275,10 @@ static void tmp105_reset(I2CSlave *i2c) s->config = 0; s->faults = tmp105_faultq[(s->config >> 3) & 3]; s->alarm = 0; + s->detect_falling = false; + + s->limit[0] = 0x4b00; /* T_LOW, 75 degrees C */ + s->limit[1] = 0x5000; /* T_HIGH, 80 degrees C */ tmp105_interrupt_update(s); } diff --git a/hw/misc/tmp105.h b/hw/misc/tmp105.h index 9ba05ecc9c72c1d414d87edf9a14f99b26d9a55d..7c97071ad75e42d8d74a14bcfb00cff132fa4a2e 100644 --- a/hw/misc/tmp105.h +++ b/hw/misc/tmp105.h @@ -16,9 +16,10 @@ #include "hw/i2c/i2c.h" #include "hw/misc/tmp105_regs.h" +#include "qom/object.h" #define TYPE_TMP105 "tmp105" -#define TMP105(obj) OBJECT_CHECK(TMP105State, (obj), TYPE_TMP105) +OBJECT_DECLARE_SIMPLE_TYPE(TMP105State, TMP105) /** * TMP105State: @@ -27,7 +28,7 @@ * * @see_also: http://www.ti.com/lit/gpn/tmp105 */ -typedef struct TMP105State { +struct TMP105State { /*< private >*/ I2CSlave i2c; /*< public >*/ @@ -42,6 +43,13 @@ typedef struct TMP105State { int16_t limit[2]; int faults; uint8_t alarm; -} TMP105State; + /* + * The TMP105 initially looks for a temperature rising above T_high; + * once this is detected, the condition it looks for next is the + * temperature falling below T_low. This flag is false when initially + * looking for T_high, true when looking for T_low. + */ + bool detect_falling; +}; #endif diff --git a/hw/misc/tmp421.c b/hw/misc/tmp421.c index 74864cd93d3082162bb727225b122988753f13bc..ef3c682e328f1c09b68a9570a8516188a50e1cde 100644 --- a/hw/misc/tmp421.c +++ b/hw/misc/tmp421.c @@ -30,6 +30,7 @@ #include "qapi/error.h" #include "qapi/visitor.h" #include "qemu/module.h" +#include "qom/object.h" /* Manufacturer / Device ID's */ #define TMP421_MANUFACTURER_ID 0x55 @@ -48,7 +49,7 @@ static const DeviceInfo devices[] = { { TMP423_DEVICE_ID, "tmp423" }, }; -typedef struct TMP421State { +struct TMP421State { /*< private >*/ I2CSlave i2c; /*< public >*/ @@ -63,20 +64,16 @@ typedef struct TMP421State { uint8_t buf[2]; uint8_t pointer; -} TMP421State; +}; -typedef struct TMP421Class { +struct TMP421Class { I2CSlaveClass parent_class; DeviceInfo *dev; -} TMP421Class; +}; #define TYPE_TMP421 "tmp421-generic" -#define TMP421(obj) OBJECT_CHECK(TMP421State, (obj), TYPE_TMP421) +OBJECT_DECLARE_TYPE(TMP421State, TMP421Class, TMP421) -#define TMP421_CLASS(klass) \ - OBJECT_CLASS_CHECK(TMP421Class, (klass), TYPE_TMP421) -#define TMP421_GET_CLASS(obj) \ - OBJECT_GET_CLASS(TMP421Class, (obj), TYPE_TMP421) /* the TMP421 registers */ #define TMP421_STATUS_REG 0x08 @@ -141,15 +138,12 @@ static void tmp421_set_temperature(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { TMP421State *s = TMP421(obj); - Error *local_err = NULL; int64_t temp; bool ext_range = (s->config[0] & TMP421_CONFIG_RANGE); int offset = ext_range * 64 * 256; int tempid; - visit_type_int(v, name, &temp, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_int(v, name, &temp, errp)) { return; } diff --git a/hw/misc/trace-events b/hw/misc/trace-events index a5862b2bed11e08f7e3eb3c73684cc51e8259720..b5118acd3fd5bf309f05e7d69e426cca3bfc0021 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -19,6 +19,10 @@ allwinner_h3_dramphy_write(uint64_t offset, uint64_t data, unsigned size) "write allwinner_sid_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32 allwinner_sid_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32 +# avr_power.c +avr_power_read(uint8_t value) "power_reduc read value:%u" +avr_power_write(uint8_t value) "power_reduc write value:%u" + # eccmemctl.c ecc_mem_writel_mer(uint32_t val) "Write memory enable 0x%08x" ecc_mem_writel_mdr(uint32_t val) "Write memory delay 0x%08x" @@ -39,6 +43,9 @@ ecc_mem_readl_ecr1(uint32_t ret) "Read event count 2 0x%08x" ecc_diag_mem_writeb(uint64_t addr, uint32_t val) "Write diagnostic %"PRId64" = 0x%02x" ecc_diag_mem_readb(uint64_t addr, uint32_t ret) "Read diagnostic %"PRId64"= 0x%02x" +# empty_slot.c +empty_slot_write(uint64_t addr, unsigned width, uint64_t value, unsigned size, const char *name) "wr addr:0x%04"PRIx64" data:0x%0*"PRIx64" size %u [%s]" + # slavio_misc.c slavio_misc_update_irq_raise(void) "Raise IRQ" slavio_misc_update_irq_lower(void) "Lower IRQ" @@ -77,7 +84,6 @@ aspeed_scu_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 mps2_scc_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 SCC read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" mps2_scc_write(uint64_t offset, uint64_t data, unsigned size) "MPS2 SCC write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" mps2_scc_reset(void) "MPS2 SCC: reset" -mps2_scc_leds(char led7, char led6, char led5, char led4, char led3, char led2, char led1, char led0) "MPS2 SCC LEDs: %c%c%c%c%c%c%c%c" mps2_scc_cfg_write(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config write: function %d device %d data 0x%" PRIx32 mps2_scc_cfg_read(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config read: function %d device %d data 0x%" PRIx32 @@ -85,7 +91,6 @@ mps2_scc_cfg_read(unsigned function, unsigned device, uint32_t value) "MPS2 SCC mps2_fpgaio_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 FPGAIO read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" mps2_fpgaio_write(uint64_t offset, uint64_t data, unsigned size) "MPS2 FPGAIO write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" mps2_fpgaio_reset(void) "MPS2 FPGAIO: reset" -mps2_fpgaio_leds(char led1, char led0) "MPS2 FPGAIO LEDs: %c%c" # msf2-sysreg.c msf2_sysreg_write(uint64_t offset, uint32_t val, uint32_t prev) "msf2-sysreg write: addr 0x%08" PRIx64 " data 0x%" PRIx32 " prev 0x%" PRIx32 @@ -103,13 +108,25 @@ mos6522_set_sr_int(void) "set sr_int" mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64 mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x" -# stm32f4xx_syscfg +# npcm7xx_clk.c +npcm7xx_clk_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 +npcm7xx_clk_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 + +# npcm7xx_gcr.c +npcm7xx_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 +npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 + +# npcm7xx_rng.c +npcm7xx_rng_read(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u" +npcm7xx_rng_write(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u" + +# stm32f4xx_syscfg.c stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d, Line: %d; Level: %d" stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d" stm32f4xx_syscfg_read(uint64_t addr) "reg read: addr: 0x%" PRIx64 " " stm32f4xx_syscfg_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 "" -# stm32f4xx_exti +# stm32f4xx_exti.c stm32f4xx_exti_set_irq(int irq, int leve) "Set EXTI: %d to %d" stm32f4xx_exti_read(uint64_t addr) "reg read: addr: 0x%" PRIx64 " " stm32f4xx_exti_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 "" @@ -174,11 +191,13 @@ armsse_mhu_write(uint64_t offset, uint64_t data, unsigned size) "SSE-200 MHU wri # aspeed_xdma.c aspeed_xdma_write(uint64_t offset, uint64_t data) "XDMA write: offset 0x%" PRIx64 " data 0x%" PRIx64 +# bcm2835_property.c +bcm2835_mbox_property(uint32_t tag, uint32_t bufsize, size_t resplen) "mbox property tag:0x%08x in_sz:%u out_sz:%zu" + # bcm2835_mbox.c bcm2835_mbox_write(unsigned int size, uint64_t addr, uint64_t value) "mbox write sz:%u addr:0x%"PRIx64" data:0x%"PRIx64 bcm2835_mbox_read(unsigned int size, uint64_t addr, uint64_t value) "mbox read sz:%u addr:0x%"PRIx64" data:0x%"PRIx64 bcm2835_mbox_irq(unsigned level) "mbox irq:ARM level:%u" -bcm2835_mbox_property(uint32_t tag, uint32_t bufsize, size_t resplen) "mbox property tag:0x%08x in_sz:%u out_sz:%zu" # mac_via.c via1_rtc_update_data_out(int count, int value) "count=%d value=0x%02x" @@ -198,3 +217,23 @@ via1_rtc_cmd_pram_read(int addr, int value) "addr=%u value=0x%02x" via1_rtc_cmd_pram_write(int addr, int value) "addr=%u value=0x%02x" via1_rtc_cmd_pram_sect_read(int sector, int offset, int addr, int value) "sector=%u offset=%u addr=%d value=0x%02x" via1_rtc_cmd_pram_sect_write(int sector, int offset, int addr, int value) "sector=%u offset=%u addr=%d value=0x%02x" +via1_adb_send(const char *state, uint8_t data, const char *vadbint) "state %s data=0x%02x vADBInt=%s" +via1_adb_receive(const char *state, uint8_t data, const char *vadbint, int status, int index, int size) "state %s data=0x%02x vADBInt=%s status=0x%x index=%d size=%d" +via1_adb_poll(uint8_t data, const char *vadbint, int status, int index, int size) "data=0x%02x vADBInt=%s status=0x%x index=%d size=%d" + +# grlib_ahb_apb_pnp.c +grlib_ahb_pnp_read(uint64_t addr, uint32_t value) "AHB PnP read addr:0x%03"PRIx64" data:0x%08x" +grlib_apb_pnp_read(uint64_t addr, uint32_t value) "APB PnP read addr:0x%03"PRIx64" data:0x%08x" + +# led.c +led_set_intensity(const char *color, const char *desc, uint8_t intensity_percent) "LED desc:'%s' color:%s intensity: %u%%" +led_change_intensity(const char *color, const char *desc, uint8_t old_intensity_percent, uint8_t new_intensity_percent) "LED desc:'%s' color:%s intensity %u%% -> %u%%" + +# pca9552.c +pca955x_gpio_status(const char *description, const char *buf) "%s GPIOs 0-15 [%s]" +pca955x_gpio_change(const char *description, unsigned id, unsigned prev_state, unsigned current_state) "%s GPIO id:%u status: %u -> %u" + +# bcm2835_cprman.c +bcm2835_cprman_read(uint64_t offset, uint64_t value) "offset:0x%" PRIx64 " value:0x%" PRIx64 +bcm2835_cprman_write(uint64_t offset, uint64_t value) "offset:0x%" PRIx64 " value:0x%" PRIx64 +bcm2835_cprman_write_invalid_magic(uint64_t offset, uint64_t value) "offset:0x%" PRIx64 " value:0x%" PRIx64 diff --git a/hw/misc/trace.h b/hw/misc/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..1ab6923d1157f8c68c95ff1a7a4b2cf2d633948b --- /dev/null +++ b/hw/misc/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_misc.h" diff --git a/hw/misc/unimp.c b/hw/misc/unimp.c index bc4084d344ecdbe97ef64fb72cb18366b11eb2c1..6cfc5727f0b60a2cdc6e8e140a741437a93c15e4 100644 --- a/hw/misc/unimp.c +++ b/hw/misc/unimp.c @@ -22,9 +22,9 @@ static uint64_t unimp_read(void *opaque, hwaddr offset, unsigned size) { UnimplementedDeviceState *s = UNIMPLEMENTED_DEVICE(opaque); - qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read " - "(size %d, offset 0x%" HWADDR_PRIx ")\n", - s->name, size, offset); + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read " + "(size %d, offset 0x%0*" HWADDR_PRIx ")\n", + s->name, size, s->offset_fmt_width, offset); return 0; } @@ -34,9 +34,9 @@ static void unimp_write(void *opaque, hwaddr offset, UnimplementedDeviceState *s = UNIMPLEMENTED_DEVICE(opaque); qemu_log_mask(LOG_UNIMP, "%s: unimplemented device write " - "(size %d, value 0x%" PRIx64 - ", offset 0x%" HWADDR_PRIx ")\n", - s->name, size, value, offset); + "(size %d, offset 0x%0*" HWADDR_PRIx + ", value 0x%0*" PRIx64 ")\n", + s->name, size, s->offset_fmt_width, offset, size << 1, value); } static const MemoryRegionOps unimp_ops = { @@ -63,6 +63,8 @@ static void unimp_realize(DeviceState *dev, Error **errp) return; } + s->offset_fmt_width = DIV_ROUND_UP(64 - clz64(s->size - 1), 4); + memory_region_init_io(&s->iomem, OBJECT(s), &unimp_ops, s, s->name, s->size); sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c index f7472d1f3c05741114ccaf9b1e32c0ed966898af..a2b28019e3c70f9894f4ccc5628ee71445c578d4 100644 --- a/hw/misc/zynq_slcr.c +++ b/hw/misc/zynq_slcr.c @@ -23,6 +23,7 @@ #include "qemu/module.h" #include "hw/registerfields.h" #include "hw/qdev-clock.h" +#include "qom/object.h" #ifndef ZYNQ_SLCR_ERR_DEBUG #define ZYNQ_SLCR_ERR_DEBUG 0 @@ -182,9 +183,9 @@ REG32(DDRIOB, 0xb40) #define ZYNQ_SLCR_NUM_REGS (ZYNQ_SLCR_MMIO_SIZE / 4) #define TYPE_ZYNQ_SLCR "xilinx,zynq_slcr" -#define ZYNQ_SLCR(obj) OBJECT_CHECK(ZynqSLCRState, (obj), TYPE_ZYNQ_SLCR) +OBJECT_DECLARE_SIMPLE_TYPE(ZynqSLCRState, ZYNQ_SLCR) -typedef struct ZynqSLCRState { +struct ZynqSLCRState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -194,7 +195,7 @@ typedef struct ZynqSLCRState { Clock *ps_clk; Clock *uart0_ref_clk; Clock *uart1_ref_clk; -} ZynqSLCRState; +}; /* * return the output frequency of ARM/DDR/IO pll diff --git a/hw/moxie/Makefile.objs b/hw/moxie/Makefile.objs deleted file mode 100644 index ddbf300f548ac55b1c4ec0314c8dcd2cfbd00891..0000000000000000000000000000000000000000 --- a/hw/moxie/Makefile.objs +++ /dev/null @@ -1,2 +0,0 @@ -# moxie boards -obj-$(CONFIG_MOXIESIM) += moxiesim.o diff --git a/hw/moxie/meson.build b/hw/moxie/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..05a7c2e00fc7bfd150c2d99b894087d2276f4949 --- /dev/null +++ b/hw/moxie/meson.build @@ -0,0 +1,4 @@ +moxie_ss = ss.source_set() +moxie_ss.add(when: 'CONFIG_MOXIESIM', if_true: files('moxiesim.c')) + +hw_arch += {'moxie': moxie_ss} diff --git a/hw/moxie/moxiesim.c b/hw/moxie/moxiesim.c index 51a98287b582595c90cfd954991ad3e244c962c9..a765e9f6be6b0b8adfa6d23f097c6b7f8e7fc678 100644 --- a/hw/moxie/moxiesim.c +++ b/hw/moxie/moxiesim.c @@ -52,13 +52,13 @@ typedef struct { static void load_kernel(MoxieCPU *cpu, LoaderParams *loader_params) { - uint64_t entry, kernel_low, kernel_high; + uint64_t entry, kernel_high; int64_t initrd_size; long kernel_size; ram_addr_t initrd_offset; kernel_size = load_elf(loader_params->kernel_filename, NULL, NULL, NULL, - &entry, &kernel_low, &kernel_high, NULL, 1, EM_MOXIE, + &entry, NULL, &kernel_high, NULL, 1, EM_MOXIE, 0, 0); if (kernel_size <= 0) { diff --git a/hw/net/Kconfig b/hw/net/Kconfig index e43c96dae0b562b50e061557978f19201e1aa534..6d795ec75256c0c85034979077d1c832fd2071b0 100644 --- a/hw/net/Kconfig +++ b/hw/net/Kconfig @@ -132,14 +132,24 @@ config ROCKER config CAN_BUS bool +config CAN_SJA1000 + bool + default y if PCI_DEVICES + select CAN_BUS + config CAN_PCI bool default y if PCI_DEVICES - depends on PCI + depends on PCI && CAN_SJA1000 select CAN_BUS -config CAN_SJA1000 +config CAN_CTUCANFD bool default y if PCI_DEVICES - depends on PCI + select CAN_BUS + +config CAN_CTUCANFD_PCI + bool + default y if PCI_DEVICES + depends on PCI && CAN_CTUCANFD select CAN_BUS diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs deleted file mode 100644 index f2b73983eeca76dd47e03e76f036879ba59e2e51..0000000000000000000000000000000000000000 --- a/hw/net/Makefile.objs +++ /dev/null @@ -1,58 +0,0 @@ -common-obj-$(CONFIG_DP8393X) += dp8393x.o -common-obj-$(CONFIG_XEN) += xen_nic.o -common-obj-$(CONFIG_NE2000_COMMON) += ne2000.o - -# PCI network cards -common-obj-$(CONFIG_NE2000_PCI) += ne2000-pci.o -common-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o -common-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o -common-obj-$(CONFIG_PCNET_COMMON) += pcnet.o -common-obj-$(CONFIG_E1000_PCI) += e1000.o e1000x_common.o -common-obj-$(CONFIG_E1000E_PCI_EXPRESS) += net_tx_pkt.o net_rx_pkt.o -common-obj-$(CONFIG_E1000E_PCI_EXPRESS) += e1000e.o e1000e_core.o e1000x_common.o -common-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o -common-obj-$(CONFIG_VMXNET3_PCI) += net_tx_pkt.o net_rx_pkt.o -common-obj-$(CONFIG_VMXNET3_PCI) += vmxnet3.o -common-obj-$(CONFIG_TULIP) += tulip.o - -common-obj-$(CONFIG_SMC91C111) += smc91c111.o -common-obj-$(CONFIG_LAN9118) += lan9118.o -common-obj-$(CONFIG_NE2000_ISA) += ne2000-isa.o -common-obj-$(CONFIG_OPENCORES_ETH) += opencores_eth.o -common-obj-$(CONFIG_XGMAC) += xgmac.o -common-obj-$(CONFIG_MIPSNET) += mipsnet.o -common-obj-$(CONFIG_XILINX_AXI) += xilinx_axienet.o -common-obj-$(CONFIG_ALLWINNER_EMAC) += allwinner_emac.o -common-obj-$(CONFIG_ALLWINNER_SUN8I_EMAC) += allwinner-sun8i-emac.o -common-obj-$(CONFIG_IMX_FEC) += imx_fec.o - -common-obj-$(CONFIG_CADENCE) += cadence_gem.o -common-obj-$(CONFIG_STELLARIS_ENET) += stellaris_enet.o -common-obj-$(CONFIG_LANCE) += lance.o -common-obj-$(CONFIG_LASI_82596) += lasi_i82596.o -common-obj-$(CONFIG_I82596_COMMON) += i82596.o -common-obj-$(CONFIG_SUNHME) += sunhme.o -common-obj-$(CONFIG_FTGMAC100) += ftgmac100.o -common-obj-$(CONFIG_SUNGEM) += sungem.o - -common-obj-$(CONFIG_ETRAXFS) += etraxfs_eth.o -common-obj-$(CONFIG_COLDFIRE) += mcf_fec.o -obj-$(CONFIG_MILKYMIST) += milkymist-minimac2.o -obj-$(CONFIG_PSERIES) += spapr_llan.o -obj-$(CONFIG_XILINX_ETHLITE) += xilinx_ethlite.o - -obj-$(CONFIG_VIRTIO_NET) += virtio-net.o -common-obj-$(call land,$(CONFIG_VIRTIO_NET),$(CONFIG_VHOST_NET)) += vhost_net.o -common-obj-$(call lnot,$(call land,$(CONFIG_VIRTIO_NET),$(CONFIG_VHOST_NET))) += vhost_net-stub.o -common-obj-$(CONFIG_ALL) += vhost_net-stub.o - -common-obj-$(CONFIG_ETSEC) += fsl_etsec/etsec.o fsl_etsec/registers.o \ - fsl_etsec/rings.o fsl_etsec/miim.o - -common-obj-$(CONFIG_ROCKER) += rocker/rocker.o rocker/rocker_fp.o \ - rocker/rocker_desc.o rocker/rocker_world.o \ - rocker/rocker_of_dpa.o -obj-$(call lnot,$(CONFIG_ROCKER)) += rocker/qmp-norocker.o - -common-obj-$(CONFIG_CAN_BUS) += can/ -common-obj-$(CONFIG_MSF2) += msf2-emac.o diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c index 28637ff4c12d1986e6f965883da2bdca15f962b3..38d328587e382439748d7a89c6589ccb1b62ee17 100644 --- a/hw/net/allwinner-sun8i-emac.c +++ b/hw/net/allwinner-sun8i-emac.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" +#include "qapi/error.h" #include "hw/sysbus.h" #include "migration/vmstate.h" #include "net/net.h" @@ -29,6 +30,7 @@ #include "net/checksum.h" #include "qemu/module.h" #include "exec/cpu-common.h" +#include "sysemu/dma.h" #include "hw/net/allwinner-sun8i-emac.h" /* EMAC register offsets */ @@ -337,12 +339,13 @@ static void allwinner_sun8i_emac_update_irq(AwSun8iEmacState *s) qemu_set_irq(s->irq, (s->int_sta & s->int_en) != 0); } -static uint32_t allwinner_sun8i_emac_next_desc(FrameDescriptor *desc, +static uint32_t allwinner_sun8i_emac_next_desc(AwSun8iEmacState *s, + FrameDescriptor *desc, size_t min_size) { uint32_t paddr = desc->next; - cpu_physical_memory_read(paddr, desc, sizeof(*desc)); + dma_memory_read(&s->dma_as, paddr, desc, sizeof(*desc)); if ((desc->status & DESC_STATUS_CTL) && (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) { @@ -352,7 +355,8 @@ static uint32_t allwinner_sun8i_emac_next_desc(FrameDescriptor *desc, } } -static uint32_t allwinner_sun8i_emac_get_desc(FrameDescriptor *desc, +static uint32_t allwinner_sun8i_emac_get_desc(AwSun8iEmacState *s, + FrameDescriptor *desc, uint32_t start_addr, size_t min_size) { @@ -360,7 +364,7 @@ static uint32_t allwinner_sun8i_emac_get_desc(FrameDescriptor *desc, /* Note that the list is a cycle. Last entry points back to the head. */ while (desc_addr != 0) { - cpu_physical_memory_read(desc_addr, desc, sizeof(*desc)); + dma_memory_read(&s->dma_as, desc_addr, desc, sizeof(*desc)); if ((desc->status & DESC_STATUS_CTL) && (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) { @@ -379,20 +383,21 @@ static uint32_t allwinner_sun8i_emac_rx_desc(AwSun8iEmacState *s, FrameDescriptor *desc, size_t min_size) { - return allwinner_sun8i_emac_get_desc(desc, s->rx_desc_curr, min_size); + return allwinner_sun8i_emac_get_desc(s, desc, s->rx_desc_curr, min_size); } static uint32_t allwinner_sun8i_emac_tx_desc(AwSun8iEmacState *s, FrameDescriptor *desc, size_t min_size) { - return allwinner_sun8i_emac_get_desc(desc, s->tx_desc_head, min_size); + return allwinner_sun8i_emac_get_desc(s, desc, s->tx_desc_head, min_size); } -static void allwinner_sun8i_emac_flush_desc(FrameDescriptor *desc, +static void allwinner_sun8i_emac_flush_desc(AwSun8iEmacState *s, + FrameDescriptor *desc, uint32_t phys_addr) { - cpu_physical_memory_write(phys_addr, desc, sizeof(*desc)); + dma_memory_write(&s->dma_as, phys_addr, desc, sizeof(*desc)); } static bool allwinner_sun8i_emac_can_receive(NetClientState *nc) @@ -450,8 +455,8 @@ static ssize_t allwinner_sun8i_emac_receive(NetClientState *nc, << RX_DESC_STATUS_FRM_LEN_SHIFT; } - cpu_physical_memory_write(desc.addr, buf, desc_bytes); - allwinner_sun8i_emac_flush_desc(&desc, s->rx_desc_curr); + dma_memory_write(&s->dma_as, desc.addr, buf, desc_bytes); + allwinner_sun8i_emac_flush_desc(s, &desc, s->rx_desc_curr); trace_allwinner_sun8i_emac_receive(s->rx_desc_curr, desc.addr, desc_bytes); @@ -465,7 +470,7 @@ static ssize_t allwinner_sun8i_emac_receive(NetClientState *nc, bytes_left -= desc_bytes; /* Move to the next descriptor */ - s->rx_desc_curr = allwinner_sun8i_emac_next_desc(&desc, 64); + s->rx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc, 64); if (!s->rx_desc_curr) { /* Not enough buffer space available */ s->int_sta |= INT_STA_RX_BUF_UA; @@ -501,10 +506,10 @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s) desc.status |= TX_DESC_STATUS_LENGTH_ERR; break; } - cpu_physical_memory_read(desc.addr, packet_buf + packet_bytes, bytes); + dma_memory_read(&s->dma_as, desc.addr, packet_buf + packet_bytes, bytes); packet_bytes += bytes; desc.status &= ~DESC_STATUS_CTL; - allwinner_sun8i_emac_flush_desc(&desc, s->tx_desc_curr); + allwinner_sun8i_emac_flush_desc(s, &desc, s->tx_desc_curr); /* After the last descriptor, send the packet */ if (desc.status2 & TX_DESC_STATUS2_LAST_DESC) { @@ -519,7 +524,7 @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s) packet_bytes = 0; transmitted++; } - s->tx_desc_curr = allwinner_sun8i_emac_next_desc(&desc, 0); + s->tx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc, 0); } /* Raise transmit completed interrupt */ @@ -623,7 +628,7 @@ static uint64_t allwinner_sun8i_emac_read(void *opaque, hwaddr offset, break; case REG_TX_CUR_BUF: /* Transmit Current Buffer */ if (s->tx_desc_curr != 0) { - cpu_physical_memory_read(s->tx_desc_curr, &desc, sizeof(desc)); + dma_memory_read(&s->dma_as, s->tx_desc_curr, &desc, sizeof(desc)); value = desc.addr; } else { value = 0; @@ -636,7 +641,7 @@ static uint64_t allwinner_sun8i_emac_read(void *opaque, hwaddr offset, break; case REG_RX_CUR_BUF: /* Receive Current Buffer */ if (s->rx_desc_curr != 0) { - cpu_physical_memory_read(s->rx_desc_curr, &desc, sizeof(desc)); + dma_memory_read(&s->dma_as, s->rx_desc_curr, &desc, sizeof(desc)); value = desc.addr; } else { value = 0; @@ -790,6 +795,13 @@ static void allwinner_sun8i_emac_realize(DeviceState *dev, Error **errp) { AwSun8iEmacState *s = AW_SUN8I_EMAC(dev); + if (!s->dma_mr) { + error_setg(errp, TYPE_AW_SUN8I_EMAC " 'dma-memory' link not set"); + return; + } + + address_space_init(&s->dma_as, s->dma_mr, "emac-dma"); + qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_allwinner_sun8i_emac_info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s); @@ -799,6 +811,8 @@ static void allwinner_sun8i_emac_realize(DeviceState *dev, Error **errp) static Property allwinner_sun8i_emac_properties[] = { DEFINE_NIC_PROPERTIES(AwSun8iEmacState, conf), DEFINE_PROP_UINT8("phy-addr", AwSun8iEmacState, mii_phy_addr, 0), + DEFINE_PROP_LINK("dma-memory", AwSun8iEmacState, dma_mr, + TYPE_MEMORY_REGION, MemoryRegion *), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index e8f9cc7f1ede5ffd5fda23184d44909d026e9873..7a534691f1f43ab4fefaf2f82dc9b9dba9072510 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -34,120 +34,123 @@ #include "qemu/module.h" #include "sysemu/dma.h" #include "net/checksum.h" - -#ifdef CADENCE_GEM_ERR_DEBUG -#define DB_PRINT(...) do { \ - fprintf(stderr, ": %s: ", __func__); \ - fprintf(stderr, ## __VA_ARGS__); \ - } while (0) -#else - #define DB_PRINT(...) -#endif - -#define GEM_NWCTRL (0x00000000/4) /* Network Control reg */ -#define GEM_NWCFG (0x00000004/4) /* Network Config reg */ -#define GEM_NWSTATUS (0x00000008/4) /* Network Status reg */ -#define GEM_USERIO (0x0000000C/4) /* User IO reg */ -#define GEM_DMACFG (0x00000010/4) /* DMA Control reg */ -#define GEM_TXSTATUS (0x00000014/4) /* TX Status reg */ -#define GEM_RXQBASE (0x00000018/4) /* RX Q Base address reg */ -#define GEM_TXQBASE (0x0000001C/4) /* TX Q Base address reg */ -#define GEM_RXSTATUS (0x00000020/4) /* RX Status reg */ -#define GEM_ISR (0x00000024/4) /* Interrupt Status reg */ -#define GEM_IER (0x00000028/4) /* Interrupt Enable reg */ -#define GEM_IDR (0x0000002C/4) /* Interrupt Disable reg */ -#define GEM_IMR (0x00000030/4) /* Interrupt Mask reg */ -#define GEM_PHYMNTNC (0x00000034/4) /* Phy Maintenance reg */ -#define GEM_RXPAUSE (0x00000038/4) /* RX Pause Time reg */ -#define GEM_TXPAUSE (0x0000003C/4) /* TX Pause Time reg */ -#define GEM_TXPARTIALSF (0x00000040/4) /* TX Partial Store and Forward */ -#define GEM_RXPARTIALSF (0x00000044/4) /* RX Partial Store and Forward */ -#define GEM_HASHLO (0x00000080/4) /* Hash Low address reg */ -#define GEM_HASHHI (0x00000084/4) /* Hash High address reg */ -#define GEM_SPADDR1LO (0x00000088/4) /* Specific addr 1 low reg */ -#define GEM_SPADDR1HI (0x0000008C/4) /* Specific addr 1 high reg */ -#define GEM_SPADDR2LO (0x00000090/4) /* Specific addr 2 low reg */ -#define GEM_SPADDR2HI (0x00000094/4) /* Specific addr 2 high reg */ -#define GEM_SPADDR3LO (0x00000098/4) /* Specific addr 3 low reg */ -#define GEM_SPADDR3HI (0x0000009C/4) /* Specific addr 3 high reg */ -#define GEM_SPADDR4LO (0x000000A0/4) /* Specific addr 4 low reg */ -#define GEM_SPADDR4HI (0x000000A4/4) /* Specific addr 4 high reg */ -#define GEM_TIDMATCH1 (0x000000A8/4) /* Type ID1 Match reg */ -#define GEM_TIDMATCH2 (0x000000AC/4) /* Type ID2 Match reg */ -#define GEM_TIDMATCH3 (0x000000B0/4) /* Type ID3 Match reg */ -#define GEM_TIDMATCH4 (0x000000B4/4) /* Type ID4 Match reg */ -#define GEM_WOLAN (0x000000B8/4) /* Wake on LAN reg */ -#define GEM_IPGSTRETCH (0x000000BC/4) /* IPG Stretch reg */ -#define GEM_SVLAN (0x000000C0/4) /* Stacked VLAN reg */ -#define GEM_MODID (0x000000FC/4) /* Module ID reg */ -#define GEM_OCTTXLO (0x00000100/4) /* Octects transmitted Low reg */ -#define GEM_OCTTXHI (0x00000104/4) /* Octects transmitted High reg */ -#define GEM_TXCNT (0x00000108/4) /* Error-free Frames transmitted */ -#define GEM_TXBCNT (0x0000010C/4) /* Error-free Broadcast Frames */ -#define GEM_TXMCNT (0x00000110/4) /* Error-free Multicast Frame */ -#define GEM_TXPAUSECNT (0x00000114/4) /* Pause Frames Transmitted */ -#define GEM_TX64CNT (0x00000118/4) /* Error-free 64 TX */ -#define GEM_TX65CNT (0x0000011C/4) /* Error-free 65-127 TX */ -#define GEM_TX128CNT (0x00000120/4) /* Error-free 128-255 TX */ -#define GEM_TX256CNT (0x00000124/4) /* Error-free 256-511 */ -#define GEM_TX512CNT (0x00000128/4) /* Error-free 512-1023 TX */ -#define GEM_TX1024CNT (0x0000012C/4) /* Error-free 1024-1518 TX */ -#define GEM_TX1519CNT (0x00000130/4) /* Error-free larger than 1519 TX */ -#define GEM_TXURUNCNT (0x00000134/4) /* TX under run error counter */ -#define GEM_SINGLECOLLCNT (0x00000138/4) /* Single Collision Frames */ -#define GEM_MULTCOLLCNT (0x0000013C/4) /* Multiple Collision Frames */ -#define GEM_EXCESSCOLLCNT (0x00000140/4) /* Excessive Collision Frames */ -#define GEM_LATECOLLCNT (0x00000144/4) /* Late Collision Frames */ -#define GEM_DEFERTXCNT (0x00000148/4) /* Deferred Transmission Frames */ -#define GEM_CSENSECNT (0x0000014C/4) /* Carrier Sense Error Counter */ -#define GEM_OCTRXLO (0x00000150/4) /* Octects Received register Low */ -#define GEM_OCTRXHI (0x00000154/4) /* Octects Received register High */ -#define GEM_RXCNT (0x00000158/4) /* Error-free Frames Received */ -#define GEM_RXBROADCNT (0x0000015C/4) /* Error-free Broadcast Frames RX */ -#define GEM_RXMULTICNT (0x00000160/4) /* Error-free Multicast Frames RX */ -#define GEM_RXPAUSECNT (0x00000164/4) /* Pause Frames Received Counter */ -#define GEM_RX64CNT (0x00000168/4) /* Error-free 64 byte Frames RX */ -#define GEM_RX65CNT (0x0000016C/4) /* Error-free 65-127B Frames RX */ -#define GEM_RX128CNT (0x00000170/4) /* Error-free 128-255B Frames RX */ -#define GEM_RX256CNT (0x00000174/4) /* Error-free 256-512B Frames RX */ -#define GEM_RX512CNT (0x00000178/4) /* Error-free 512-1023B Frames RX */ -#define GEM_RX1024CNT (0x0000017C/4) /* Error-free 1024-1518B Frames RX */ -#define GEM_RX1519CNT (0x00000180/4) /* Error-free 1519-max Frames RX */ -#define GEM_RXUNDERCNT (0x00000184/4) /* Undersize Frames Received */ -#define GEM_RXOVERCNT (0x00000188/4) /* Oversize Frames Received */ -#define GEM_RXJABCNT (0x0000018C/4) /* Jabbers Received Counter */ -#define GEM_RXFCSCNT (0x00000190/4) /* Frame Check seq. Error Counter */ -#define GEM_RXLENERRCNT (0x00000194/4) /* Length Field Error Counter */ -#define GEM_RXSYMERRCNT (0x00000198/4) /* Symbol Error Counter */ -#define GEM_RXALIGNERRCNT (0x0000019C/4) /* Alignment Error Counter */ -#define GEM_RXRSCERRCNT (0x000001A0/4) /* Receive Resource Error Counter */ -#define GEM_RXORUNCNT (0x000001A4/4) /* Receive Overrun Counter */ -#define GEM_RXIPCSERRCNT (0x000001A8/4) /* IP header Checksum Error Counter */ -#define GEM_RXTCPCCNT (0x000001AC/4) /* TCP Checksum Error Counter */ -#define GEM_RXUDPCCNT (0x000001B0/4) /* UDP Checksum Error Counter */ - -#define GEM_1588S (0x000001D0/4) /* 1588 Timer Seconds */ -#define GEM_1588NS (0x000001D4/4) /* 1588 Timer Nanoseconds */ -#define GEM_1588ADJ (0x000001D8/4) /* 1588 Timer Adjust */ -#define GEM_1588INC (0x000001DC/4) /* 1588 Timer Increment */ -#define GEM_PTPETXS (0x000001E0/4) /* PTP Event Frame Transmitted (s) */ -#define GEM_PTPETXNS (0x000001E4/4) /* PTP Event Frame Transmitted (ns) */ -#define GEM_PTPERXS (0x000001E8/4) /* PTP Event Frame Received (s) */ -#define GEM_PTPERXNS (0x000001EC/4) /* PTP Event Frame Received (ns) */ -#define GEM_PTPPTXS (0x000001E0/4) /* PTP Peer Frame Transmitted (s) */ -#define GEM_PTPPTXNS (0x000001E4/4) /* PTP Peer Frame Transmitted (ns) */ -#define GEM_PTPPRXS (0x000001E8/4) /* PTP Peer Frame Received (s) */ -#define GEM_PTPPRXNS (0x000001EC/4) /* PTP Peer Frame Received (ns) */ +#include "net/eth.h" + +#define CADENCE_GEM_ERR_DEBUG 0 +#define DB_PRINT(...) do {\ + if (CADENCE_GEM_ERR_DEBUG) { \ + qemu_log(": %s: ", __func__); \ + qemu_log(__VA_ARGS__); \ + } \ +} while (0) + +#define GEM_NWCTRL (0x00000000 / 4) /* Network Control reg */ +#define GEM_NWCFG (0x00000004 / 4) /* Network Config reg */ +#define GEM_NWSTATUS (0x00000008 / 4) /* Network Status reg */ +#define GEM_USERIO (0x0000000C / 4) /* User IO reg */ +#define GEM_DMACFG (0x00000010 / 4) /* DMA Control reg */ +#define GEM_TXSTATUS (0x00000014 / 4) /* TX Status reg */ +#define GEM_RXQBASE (0x00000018 / 4) /* RX Q Base address reg */ +#define GEM_TXQBASE (0x0000001C / 4) /* TX Q Base address reg */ +#define GEM_RXSTATUS (0x00000020 / 4) /* RX Status reg */ +#define GEM_ISR (0x00000024 / 4) /* Interrupt Status reg */ +#define GEM_IER (0x00000028 / 4) /* Interrupt Enable reg */ +#define GEM_IDR (0x0000002C / 4) /* Interrupt Disable reg */ +#define GEM_IMR (0x00000030 / 4) /* Interrupt Mask reg */ +#define GEM_PHYMNTNC (0x00000034 / 4) /* Phy Maintenance reg */ +#define GEM_RXPAUSE (0x00000038 / 4) /* RX Pause Time reg */ +#define GEM_TXPAUSE (0x0000003C / 4) /* TX Pause Time reg */ +#define GEM_TXPARTIALSF (0x00000040 / 4) /* TX Partial Store and Forward */ +#define GEM_RXPARTIALSF (0x00000044 / 4) /* RX Partial Store and Forward */ +#define GEM_JUMBO_MAX_LEN (0x00000048 / 4) /* Max Jumbo Frame Size */ +#define GEM_HASHLO (0x00000080 / 4) /* Hash Low address reg */ +#define GEM_HASHHI (0x00000084 / 4) /* Hash High address reg */ +#define GEM_SPADDR1LO (0x00000088 / 4) /* Specific addr 1 low reg */ +#define GEM_SPADDR1HI (0x0000008C / 4) /* Specific addr 1 high reg */ +#define GEM_SPADDR2LO (0x00000090 / 4) /* Specific addr 2 low reg */ +#define GEM_SPADDR2HI (0x00000094 / 4) /* Specific addr 2 high reg */ +#define GEM_SPADDR3LO (0x00000098 / 4) /* Specific addr 3 low reg */ +#define GEM_SPADDR3HI (0x0000009C / 4) /* Specific addr 3 high reg */ +#define GEM_SPADDR4LO (0x000000A0 / 4) /* Specific addr 4 low reg */ +#define GEM_SPADDR4HI (0x000000A4 / 4) /* Specific addr 4 high reg */ +#define GEM_TIDMATCH1 (0x000000A8 / 4) /* Type ID1 Match reg */ +#define GEM_TIDMATCH2 (0x000000AC / 4) /* Type ID2 Match reg */ +#define GEM_TIDMATCH3 (0x000000B0 / 4) /* Type ID3 Match reg */ +#define GEM_TIDMATCH4 (0x000000B4 / 4) /* Type ID4 Match reg */ +#define GEM_WOLAN (0x000000B8 / 4) /* Wake on LAN reg */ +#define GEM_IPGSTRETCH (0x000000BC / 4) /* IPG Stretch reg */ +#define GEM_SVLAN (0x000000C0 / 4) /* Stacked VLAN reg */ +#define GEM_MODID (0x000000FC / 4) /* Module ID reg */ +#define GEM_OCTTXLO (0x00000100 / 4) /* Octects transmitted Low reg */ +#define GEM_OCTTXHI (0x00000104 / 4) /* Octects transmitted High reg */ +#define GEM_TXCNT (0x00000108 / 4) /* Error-free Frames transmitted */ +#define GEM_TXBCNT (0x0000010C / 4) /* Error-free Broadcast Frames */ +#define GEM_TXMCNT (0x00000110 / 4) /* Error-free Multicast Frame */ +#define GEM_TXPAUSECNT (0x00000114 / 4) /* Pause Frames Transmitted */ +#define GEM_TX64CNT (0x00000118 / 4) /* Error-free 64 TX */ +#define GEM_TX65CNT (0x0000011C / 4) /* Error-free 65-127 TX */ +#define GEM_TX128CNT (0x00000120 / 4) /* Error-free 128-255 TX */ +#define GEM_TX256CNT (0x00000124 / 4) /* Error-free 256-511 */ +#define GEM_TX512CNT (0x00000128 / 4) /* Error-free 512-1023 TX */ +#define GEM_TX1024CNT (0x0000012C / 4) /* Error-free 1024-1518 TX */ +#define GEM_TX1519CNT (0x00000130 / 4) /* Error-free larger than 1519 TX */ +#define GEM_TXURUNCNT (0x00000134 / 4) /* TX under run error counter */ +#define GEM_SINGLECOLLCNT (0x00000138 / 4) /* Single Collision Frames */ +#define GEM_MULTCOLLCNT (0x0000013C / 4) /* Multiple Collision Frames */ +#define GEM_EXCESSCOLLCNT (0x00000140 / 4) /* Excessive Collision Frames */ +#define GEM_LATECOLLCNT (0x00000144 / 4) /* Late Collision Frames */ +#define GEM_DEFERTXCNT (0x00000148 / 4) /* Deferred Transmission Frames */ +#define GEM_CSENSECNT (0x0000014C / 4) /* Carrier Sense Error Counter */ +#define GEM_OCTRXLO (0x00000150 / 4) /* Octects Received register Low */ +#define GEM_OCTRXHI (0x00000154 / 4) /* Octects Received register High */ +#define GEM_RXCNT (0x00000158 / 4) /* Error-free Frames Received */ +#define GEM_RXBROADCNT (0x0000015C / 4) /* Error-free Broadcast Frames RX */ +#define GEM_RXMULTICNT (0x00000160 / 4) /* Error-free Multicast Frames RX */ +#define GEM_RXPAUSECNT (0x00000164 / 4) /* Pause Frames Received Counter */ +#define GEM_RX64CNT (0x00000168 / 4) /* Error-free 64 byte Frames RX */ +#define GEM_RX65CNT (0x0000016C / 4) /* Error-free 65-127B Frames RX */ +#define GEM_RX128CNT (0x00000170 / 4) /* Error-free 128-255B Frames RX */ +#define GEM_RX256CNT (0x00000174 / 4) /* Error-free 256-512B Frames RX */ +#define GEM_RX512CNT (0x00000178 / 4) /* Error-free 512-1023B Frames RX */ +#define GEM_RX1024CNT (0x0000017C / 4) /* Error-free 1024-1518B Frames RX */ +#define GEM_RX1519CNT (0x00000180 / 4) /* Error-free 1519-max Frames RX */ +#define GEM_RXUNDERCNT (0x00000184 / 4) /* Undersize Frames Received */ +#define GEM_RXOVERCNT (0x00000188 / 4) /* Oversize Frames Received */ +#define GEM_RXJABCNT (0x0000018C / 4) /* Jabbers Received Counter */ +#define GEM_RXFCSCNT (0x00000190 / 4) /* Frame Check seq. Error Counter */ +#define GEM_RXLENERRCNT (0x00000194 / 4) /* Length Field Error Counter */ +#define GEM_RXSYMERRCNT (0x00000198 / 4) /* Symbol Error Counter */ +#define GEM_RXALIGNERRCNT (0x0000019C / 4) /* Alignment Error Counter */ +#define GEM_RXRSCERRCNT (0x000001A0 / 4) /* Receive Resource Error Counter */ +#define GEM_RXORUNCNT (0x000001A4 / 4) /* Receive Overrun Counter */ +#define GEM_RXIPCSERRCNT (0x000001A8 / 4) /* IP header Checksum Err Counter */ +#define GEM_RXTCPCCNT (0x000001AC / 4) /* TCP Checksum Error Counter */ +#define GEM_RXUDPCCNT (0x000001B0 / 4) /* UDP Checksum Error Counter */ + +#define GEM_1588S (0x000001D0 / 4) /* 1588 Timer Seconds */ +#define GEM_1588NS (0x000001D4 / 4) /* 1588 Timer Nanoseconds */ +#define GEM_1588ADJ (0x000001D8 / 4) /* 1588 Timer Adjust */ +#define GEM_1588INC (0x000001DC / 4) /* 1588 Timer Increment */ +#define GEM_PTPETXS (0x000001E0 / 4) /* PTP Event Frame Transmitted (s) */ +#define GEM_PTPETXNS (0x000001E4 / 4) /* + * PTP Event Frame Transmitted (ns) + */ +#define GEM_PTPERXS (0x000001E8 / 4) /* PTP Event Frame Received (s) */ +#define GEM_PTPERXNS (0x000001EC / 4) /* PTP Event Frame Received (ns) */ +#define GEM_PTPPTXS (0x000001E0 / 4) /* PTP Peer Frame Transmitted (s) */ +#define GEM_PTPPTXNS (0x000001E4 / 4) /* PTP Peer Frame Transmitted (ns) */ +#define GEM_PTPPRXS (0x000001E8 / 4) /* PTP Peer Frame Received (s) */ +#define GEM_PTPPRXNS (0x000001EC / 4) /* PTP Peer Frame Received (ns) */ /* Design Configuration Registers */ -#define GEM_DESCONF (0x00000280/4) -#define GEM_DESCONF2 (0x00000284/4) -#define GEM_DESCONF3 (0x00000288/4) -#define GEM_DESCONF4 (0x0000028C/4) -#define GEM_DESCONF5 (0x00000290/4) -#define GEM_DESCONF6 (0x00000294/4) +#define GEM_DESCONF (0x00000280 / 4) +#define GEM_DESCONF2 (0x00000284 / 4) +#define GEM_DESCONF3 (0x00000288 / 4) +#define GEM_DESCONF4 (0x0000028C / 4) +#define GEM_DESCONF5 (0x00000290 / 4) +#define GEM_DESCONF6 (0x00000294 / 4) #define GEM_DESCONF6_64B_MASK (1U << 23) -#define GEM_DESCONF7 (0x00000298/4) +#define GEM_DESCONF7 (0x00000298 / 4) #define GEM_INT_Q1_STATUS (0x00000400 / 4) #define GEM_INT_Q1_MASK (0x00000640 / 4) @@ -211,10 +214,12 @@ #define GEM_NWCFG_LERR_DISC 0x00010000 /* Discard RX frames with len err */ #define GEM_NWCFG_BUFF_OFST_M 0x0000C000 /* Receive buffer offset mask */ #define GEM_NWCFG_BUFF_OFST_S 14 /* Receive buffer offset shift */ +#define GEM_NWCFG_RCV_1538 0x00000100 /* Receive 1538 bytes frame */ #define GEM_NWCFG_UCAST_HASH 0x00000080 /* accept unicast if hash match */ #define GEM_NWCFG_MCAST_HASH 0x00000040 /* accept multicast if hash match */ #define GEM_NWCFG_BCAST_REJ 0x00000020 /* Reject broadcast packets */ #define GEM_NWCFG_PROMISC 0x00000010 /* Accept all packets */ +#define GEM_NWCFG_JUMBO_FRAME 0x00000008 /* Jumbo Frames enable */ #define GEM_DMACFG_ADDR_64B (1U << 30) #define GEM_DMACFG_TX_BD_EXT (1U << 29) @@ -232,6 +237,7 @@ /* GEM_ISR GEM_IER GEM_IDR GEM_IMR */ #define GEM_INT_TXCMPL 0x00000080 /* Transmit Complete */ +#define GEM_INT_AMBA_ERR 0x00000040 #define GEM_INT_TXUSED 0x00000008 #define GEM_INT_RXUSED 0x00000004 #define GEM_INT_RXCMPL 0x00000002 @@ -244,7 +250,7 @@ #define GEM_PHYMNTNC_REG_SHIFT 18 /* Marvell PHY definitions */ -#define BOARD_PHY_ADDRESS 23 /* PHY address we will emulate a device at */ +#define BOARD_PHY_ADDRESS 0 /* PHY address we will emulate a device at */ #define PHY_REG_CONTROL 0 #define PHY_REG_STATUS 1 @@ -345,11 +351,6 @@ static inline unsigned tx_desc_get_last(uint32_t *desc) return (desc[1] & DESC_1_TX_LAST) ? 1 : 0; } -static inline void tx_desc_set_last(uint32_t *desc) -{ - desc[1] |= DESC_1_TX_LAST; -} - static inline unsigned tx_desc_get_length(uint32_t *desc) { return desc[1] & DESC_1_LENGTH; @@ -452,6 +453,34 @@ static inline void rx_desc_set_sar(uint32_t *desc, int sar_idx) /* The broadcast MAC address: 0xFFFFFFFFFFFF */ static const uint8_t broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +static uint32_t gem_get_max_buf_len(CadenceGEMState *s, bool tx) +{ + uint32_t size; + if (s->regs[GEM_NWCFG] & GEM_NWCFG_JUMBO_FRAME) { + size = s->regs[GEM_JUMBO_MAX_LEN]; + if (size > s->jumbo_max_len) { + size = s->jumbo_max_len; + qemu_log_mask(LOG_GUEST_ERROR, "GEM_JUMBO_MAX_LEN reg cannot be" + " greater than 0x%" PRIx32 "\n", s->jumbo_max_len); + } + } else if (tx) { + size = 1518; + } else { + size = s->regs[GEM_NWCFG] & GEM_NWCFG_RCV_1538 ? 1538 : 1518; + } + return size; +} + +static void gem_set_isr(CadenceGEMState *s, int q, uint32_t flag) +{ + if (q == 0) { + s->regs[GEM_ISR] |= flag & ~(s->regs[GEM_IMR]); + } else { + s->regs[GEM_INT_Q1_STATUS + q - 1] |= flag & + ~(s->regs[GEM_INT_Q1_MASK + q - 1]); + } +} + /* * gem_init_register_masks: * One time initialization. @@ -459,6 +488,7 @@ static const uint8_t broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; */ static void gem_init_register_masks(CadenceGEMState *s) { + unsigned int i; /* Mask of register bits which are read only */ memset(&s->regs_ro[0], 0, sizeof(s->regs_ro)); s->regs_ro[GEM_NWCTRL] = 0xFFF80000; @@ -471,10 +501,19 @@ static void gem_init_register_masks(CadenceGEMState *s) s->regs_ro[GEM_ISR] = 0xFFFFFFFF; s->regs_ro[GEM_IMR] = 0xFFFFFFFF; s->regs_ro[GEM_MODID] = 0xFFFFFFFF; + for (i = 0; i < s->num_priority_queues; i++) { + s->regs_ro[GEM_INT_Q1_STATUS + i] = 0xFFFFFFFF; + s->regs_ro[GEM_INT_Q1_ENABLE + i] = 0xFFFFF319; + s->regs_ro[GEM_INT_Q1_DISABLE + i] = 0xFFFFF319; + s->regs_ro[GEM_INT_Q1_MASK + i] = 0xFFFFFFFF; + } /* Mask of register bits which are clear on read */ memset(&s->regs_rtc[0], 0, sizeof(s->regs_rtc)); s->regs_rtc[GEM_ISR] = 0xFFFFFFFF; + for (i = 0; i < s->num_priority_queues; i++) { + s->regs_rtc[GEM_INT_Q1_STATUS + i] = 0x00000CE6; + } /* Mask of register bits which are write 1 to clear */ memset(&s->regs_w1c[0], 0, sizeof(s->regs_w1c)); @@ -486,6 +525,10 @@ static void gem_init_register_masks(CadenceGEMState *s) s->regs_wo[GEM_NWCTRL] = 0x00073E60; s->regs_wo[GEM_IER] = 0x07FFFFFF; s->regs_wo[GEM_IDR] = 0x07FFFFFF; + for (i = 0; i < s->num_priority_queues; i++) { + s->regs_wo[GEM_INT_Q1_ENABLE + i] = 0x00000CE6; + s->regs_wo[GEM_INT_Q1_DISABLE + i] = 0x00000CE6; + } } /* @@ -555,29 +598,10 @@ static void gem_update_int_status(CadenceGEMState *s) { int i; - if (!s->regs[GEM_ISR]) { - /* ISR isn't set, clear all the interrupts */ - for (i = 0; i < s->num_priority_queues; ++i) { - qemu_set_irq(s->irq[i], 0); - } - return; - } - - /* If we get here we know s->regs[GEM_ISR] is set, so we don't need to - * check it again. - */ - if (s->num_priority_queues == 1) { - /* No priority queues, just trigger the interrupt */ - DB_PRINT("asserting int.\n"); - qemu_set_irq(s->irq[0], 1); - return; - } + qemu_set_irq(s->irq[0], !!s->regs[GEM_ISR]); - for (i = 0; i < s->num_priority_queues; ++i) { - if (s->regs[GEM_INT_Q1_STATUS + i]) { - DB_PRINT("asserting int. (q=%d)\n", i); - qemu_set_irq(s->irq[i], 1); - } + for (i = 1; i < s->num_priority_queues; ++i) { + qemu_set_irq(s->irq[i], !!s->regs[GEM_INT_Q1_STATUS + i - 1]); } } @@ -679,7 +703,7 @@ static unsigned calc_mac_hash(const uint8_t *mac) static int gem_mac_address_filter(CadenceGEMState *s, const uint8_t *packet) { uint8_t *gem_spaddr; - int i; + int i, is_mc; /* Promiscuous mode? */ if (s->regs[GEM_NWCFG] & GEM_NWCFG_PROMISC) { @@ -695,22 +719,17 @@ static int gem_mac_address_filter(CadenceGEMState *s, const uint8_t *packet) } /* Accept packets -w- hash match? */ - if ((packet[0] == 0x01 && (s->regs[GEM_NWCFG] & GEM_NWCFG_MCAST_HASH)) || - (packet[0] != 0x01 && (s->regs[GEM_NWCFG] & GEM_NWCFG_UCAST_HASH))) { + is_mc = is_multicast_ether_addr(packet); + if ((is_mc && (s->regs[GEM_NWCFG] & GEM_NWCFG_MCAST_HASH)) || + (!is_mc && (s->regs[GEM_NWCFG] & GEM_NWCFG_UCAST_HASH))) { + uint64_t buckets; unsigned hash_index; hash_index = calc_mac_hash(packet); - if (hash_index < 32) { - if (s->regs[GEM_HASHLO] & (1<regs[GEM_HASHHI] & (1<regs[GEM_HASHHI] << 32) | s->regs[GEM_HASHLO]; + if ((buckets >> hash_index) & 1) { + return is_mc ? GEM_RX_MULTICAST_HASH_ACCEPT + : GEM_RX_UNICAST_HASH_ACCEPT; } } @@ -846,6 +865,35 @@ static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr, return 0; } +static uint32_t gem_get_queue_base_addr(CadenceGEMState *s, bool tx, int q) +{ + uint32_t base_addr = 0; + + switch (q) { + case 0: + base_addr = s->regs[tx ? GEM_TXQBASE : GEM_RXQBASE]; + break; + case 1 ... (MAX_PRIORITY_QUEUES - 1): + base_addr = s->regs[(tx ? GEM_TRANSMIT_Q1_PTR : + GEM_RECEIVE_Q1_PTR) + q - 1]; + break; + default: + g_assert_not_reached(); + }; + + return base_addr; +} + +static inline uint32_t gem_get_tx_queue_base_addr(CadenceGEMState *s, int q) +{ + return gem_get_queue_base_addr(s, true, q); +} + +static inline uint32_t gem_get_rx_queue_base_addr(CadenceGEMState *s, int q) +{ + return gem_get_queue_base_addr(s, false, q); +} + static hwaddr gem_get_desc_addr(CadenceGEMState *s, bool tx, int q) { hwaddr desc_addr = 0; @@ -883,7 +931,7 @@ static void gem_get_rx_desc(CadenceGEMState *s, int q) if (rx_desc_get_ownership(s->rx_desc[q]) == 1) { DB_PRINT("descriptor 0x%" HWADDR_PRIx " owned by sw.\n", desc_addr); s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_NOBUF; - s->regs[GEM_ISR] |= GEM_INT_RXUSED & ~(s->regs[GEM_IMR]); + gem_set_isr(s, q, GEM_INT_RXUSED); /* Handle interrupt consequences */ gem_update_int_status(s); } @@ -895,21 +943,18 @@ static void gem_get_rx_desc(CadenceGEMState *s, int q) */ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) { - CadenceGEMState *s; + CadenceGEMState *s = qemu_get_nic_opaque(nc); unsigned rxbufsize, bytes_to_copy; unsigned rxbuf_offset; - uint8_t rxbuf[2048]; uint8_t *rxbuf_ptr; bool first_desc = true; int maf; int q = 0; - s = qemu_get_nic_opaque(nc); - /* Is this destination MAC address "for us" ? */ maf = gem_mac_address_filter(s, buf); if (maf == GEM_RX_REJECT) { - return -1; + return size; /* no, drop siliently b/c it's not an error */ } /* Discard packets with receive length error enabled ? */ @@ -961,29 +1006,35 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) } else { unsigned crc_val; - if (size > sizeof(rxbuf) - sizeof(crc_val)) { - size = sizeof(rxbuf) - sizeof(crc_val); + if (size > MAX_FRAME_SIZE - sizeof(crc_val)) { + size = MAX_FRAME_SIZE - sizeof(crc_val); } bytes_to_copy = size; /* The application wants the FCS field, which QEMU does not provide. * We must try and calculate one. */ - memcpy(rxbuf, buf, size); - memset(rxbuf + size, 0, sizeof(rxbuf) - size); - rxbuf_ptr = rxbuf; - crc_val = cpu_to_le32(crc32(0, rxbuf, MAX(size, 60))); - memcpy(rxbuf + size, &crc_val, sizeof(crc_val)); + memcpy(s->rx_packet, buf, size); + memset(s->rx_packet + size, 0, MAX_FRAME_SIZE - size); + rxbuf_ptr = s->rx_packet; + crc_val = cpu_to_le32(crc32(0, s->rx_packet, MAX(size, 60))); + memcpy(s->rx_packet + size, &crc_val, sizeof(crc_val)); bytes_to_copy += 4; size += 4; } - DB_PRINT("config bufsize: %d packet size: %ld\n", rxbufsize, size); + DB_PRINT("config bufsize: %u packet size: %zd\n", rxbufsize, size); /* Find which queue we are targeting */ q = get_queue_from_screen(s, rxbuf_ptr, rxbufsize); + if (size > gem_get_max_buf_len(s, false)) { + qemu_log_mask(LOG_GUEST_ERROR, "rx frame too long\n"); + gem_set_isr(s, q, GEM_INT_AMBA_ERR); + return -1; + } + while (bytes_to_copy) { hwaddr desc_addr; @@ -992,9 +1043,9 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) return -1; } - DB_PRINT("copy %u bytes to 0x%" PRIx64 "\n", - MIN(bytes_to_copy, rxbufsize), - rx_desc_get_buffer(s, s->rx_desc[q])); + DB_PRINT("copy %" PRIu32 " bytes to 0x%" PRIx64 "\n", + MIN(bytes_to_copy, rxbufsize), + rx_desc_get_buffer(s, s->rx_desc[q])); /* Copy packet data to emulated DMA buffer */ address_space_write(&s->dma_as, rx_desc_get_buffer(s, s->rx_desc[q]) + @@ -1044,7 +1095,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) /* Next descriptor */ if (rx_desc_get_wrap(s->rx_desc[q])) { DB_PRINT("wrapping RX descriptor list\n"); - s->rx_desc_addr[q] = s->regs[GEM_RXQBASE]; + s->rx_desc_addr[q] = gem_get_rx_queue_base_addr(s, q); } else { DB_PRINT("incrementing RX descriptor list\n"); s->rx_desc_addr[q] += 4 * gem_get_desc_len(s, true); @@ -1057,7 +1108,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) gem_receive_updatestats(s, buf, size); s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_FRMRCVD; - s->regs[GEM_ISR] |= GEM_INT_RXCMPL & ~(s->regs[GEM_IMR]); + gem_set_isr(s, q, GEM_INT_RXCMPL); /* Handle interrupt consequences */ gem_update_int_status(s); @@ -1119,7 +1170,6 @@ static void gem_transmit(CadenceGEMState *s) { uint32_t desc[DESC_MAX_NUM_WORDS]; hwaddr packet_desc_addr; - uint8_t tx_packet[2048]; uint8_t *p; unsigned total_bytes; int q = 0; @@ -1135,7 +1185,7 @@ static void gem_transmit(CadenceGEMState *s) * Packets scattered across multiple descriptors are gathered to this * one contiguous buffer first. */ - p = tx_packet; + p = s->tx_packet; total_bytes = 0; for (q = s->num_priority_queues - 1; q >= 0; q--) { @@ -1160,17 +1210,18 @@ static void gem_transmit(CadenceGEMState *s) */ if ((tx_desc_get_buffer(s, desc) == 0) || (tx_desc_get_length(desc) == 0)) { - DB_PRINT("Invalid TX descriptor @ 0x%x\n", - (unsigned)packet_desc_addr); + DB_PRINT("Invalid TX descriptor @ 0x%" HWADDR_PRIx "\n", + packet_desc_addr); break; } - if (tx_desc_get_length(desc) > sizeof(tx_packet) - - (p - tx_packet)) { - DB_PRINT("TX descriptor @ 0x%" HWADDR_PRIx \ - " too large: size 0x%x space 0x%zx\n", + if (tx_desc_get_length(desc) > gem_get_max_buf_len(s, true) - + (p - s->tx_packet)) { + qemu_log_mask(LOG_GUEST_ERROR, "TX descriptor @ 0x%" \ + HWADDR_PRIx " too large: size 0x%x space 0x%zx\n", packet_desc_addr, tx_desc_get_length(desc), - sizeof(tx_packet) - (p - tx_packet)); + gem_get_max_buf_len(s, true) - (p - s->tx_packet)); + gem_set_isr(s, q, GEM_INT_AMBA_ERR); break; } @@ -1200,7 +1251,7 @@ static void gem_transmit(CadenceGEMState *s) sizeof(desc_first)); /* Advance the hardware current descriptor past this packet */ if (tx_desc_get_wrap(desc)) { - s->tx_desc_addr[q] = s->regs[GEM_TXQBASE]; + s->tx_desc_addr[q] = gem_get_tx_queue_base_addr(s, q); } else { s->tx_desc_addr[q] = packet_desc_addr + 4 * gem_get_desc_len(s, false); @@ -1208,43 +1259,36 @@ static void gem_transmit(CadenceGEMState *s) DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr[q]); s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_TXCMPL; - s->regs[GEM_ISR] |= GEM_INT_TXCMPL & ~(s->regs[GEM_IMR]); - - /* Update queue interrupt status */ - if (s->num_priority_queues > 1) { - s->regs[GEM_INT_Q1_STATUS + q] |= - GEM_INT_TXCMPL & ~(s->regs[GEM_INT_Q1_MASK + q]); - } + gem_set_isr(s, q, GEM_INT_TXCMPL); /* Handle interrupt consequences */ gem_update_int_status(s); /* Is checksum offload enabled? */ if (s->regs[GEM_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) { - net_checksum_calculate(tx_packet, total_bytes); + net_checksum_calculate(s->tx_packet, total_bytes); } /* Update MAC statistics */ - gem_transmit_updatestats(s, tx_packet, total_bytes); + gem_transmit_updatestats(s, s->tx_packet, total_bytes); /* Send the packet somewhere */ if (s->phy_loop || (s->regs[GEM_NWCTRL] & GEM_NWCTRL_LOCALLOOP)) { - gem_receive(qemu_get_queue(s->nic), tx_packet, + gem_receive(qemu_get_queue(s->nic), s->tx_packet, total_bytes); } else { - qemu_send_packet(qemu_get_queue(s->nic), tx_packet, + qemu_send_packet(qemu_get_queue(s->nic), s->tx_packet, total_bytes); } /* Prepare for next packet */ - p = tx_packet; + p = s->tx_packet; total_bytes = 0; } /* read next descriptor */ if (tx_desc_get_wrap(desc)) { - tx_desc_set_last(desc); if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) { packet_desc_addr = s->regs[GEM_TBQPH]; @@ -1252,7 +1296,7 @@ static void gem_transmit(CadenceGEMState *s) } else { packet_desc_addr = 0; } - packet_desc_addr |= s->regs[GEM_TXQBASE]; + packet_desc_addr |= gem_get_tx_queue_base_addr(s, q); } else { packet_desc_addr += 4 * gem_get_desc_len(s, false); } @@ -1264,7 +1308,10 @@ static void gem_transmit(CadenceGEMState *s) if (tx_desc_get_used(desc)) { s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_USED; - s->regs[GEM_ISR] |= GEM_INT_TXUSED & ~(s->regs[GEM_IMR]); + /* IRQ TXUSED is defined only for queue 0 */ + if (q == 0) { + gem_set_isr(s, 0, GEM_INT_TXUSED); + } gem_update_int_status(s); } } @@ -1314,10 +1361,12 @@ static void gem_reset(DeviceState *d) s->regs[GEM_TXPARTIALSF] = 0x000003ff; s->regs[GEM_RXPARTIALSF] = 0x000003ff; s->regs[GEM_MODID] = s->revision; - s->regs[GEM_DESCONF] = 0x02500111; - s->regs[GEM_DESCONF2] = 0x2ab13fff; + s->regs[GEM_DESCONF] = 0x02D00111; + s->regs[GEM_DESCONF2] = 0x2ab10000 | s->jumbo_max_len; s->regs[GEM_DESCONF5] = 0x002f2045; s->regs[GEM_DESCONF6] = GEM_DESCONF6_64B_MASK; + s->regs[GEM_INT_Q1_MASK] = 0x00000CE6; + s->regs[GEM_JUMBO_MAX_LEN] = s->jumbo_max_len; if (s->num_priority_queues > 1) { queues_mask = MAKE_64BIT_MASK(1, s->num_priority_queues - 1); @@ -1397,7 +1446,7 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size) uint32_t phy_addr, reg_num; phy_addr = (retval & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT; - if (phy_addr == BOARD_PHY_ADDRESS || phy_addr == 0) { + if (phy_addr == s->phy_addr) { reg_num = (retval & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT; retval &= 0xFFFF0000; retval |= gem_phy_read(s, reg_num); @@ -1458,7 +1507,7 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val, if (!(val & GEM_NWCTRL_TXENA)) { /* Reset to start of Q when transmit disabled. */ for (i = 0; i < s->num_priority_queues; i++) { - s->tx_desc_addr[i] = s->regs[GEM_TXQBASE]; + s->tx_desc_addr[i] = gem_get_tx_queue_base_addr(s, i); } } if (gem_can_receive(qemu_get_queue(s->nic))) { @@ -1488,6 +1537,9 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val, s->regs[GEM_IMR] &= ~val; gem_update_int_status(s); break; + case GEM_JUMBO_MAX_LEN: + s->regs[GEM_JUMBO_MAX_LEN] = val & MAX_JUMBO_FRAME_SIZE_MASK; + break; case GEM_INT_Q1_ENABLE ... GEM_INT_Q7_ENABLE: s->regs[GEM_INT_Q1_MASK + offset - GEM_INT_Q1_ENABLE] &= ~val; gem_update_int_status(s); @@ -1517,7 +1569,7 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val, uint32_t phy_addr, reg_num; phy_addr = (val & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT; - if (phy_addr == BOARD_PHY_ADDRESS || phy_addr == 0) { + if (phy_addr == s->phy_addr) { reg_num = (val & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT; gem_phy_write(s, reg_num, val); } @@ -1582,6 +1634,12 @@ static void gem_realize(DeviceState *dev, Error **errp) s->nic = qemu_new_nic(&net_gem_info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s); + + if (s->jumbo_max_len > MAX_FRAME_SIZE) { + error_setg(errp, "jumbo-max-len is greater than %d", + MAX_FRAME_SIZE); + return; + } } static void gem_init(Object *obj) @@ -1624,12 +1682,15 @@ static Property gem_properties[] = { DEFINE_NIC_PROPERTIES(CadenceGEMState, conf), DEFINE_PROP_UINT32("revision", CadenceGEMState, revision, GEM_MODID_VALUE), + DEFINE_PROP_UINT8("phy-addr", CadenceGEMState, phy_addr, BOARD_PHY_ADDRESS), DEFINE_PROP_UINT8("num-priority-queues", CadenceGEMState, num_priority_queues, 1), DEFINE_PROP_UINT8("num-type1-screeners", CadenceGEMState, num_type1_screeners, 4), DEFINE_PROP_UINT8("num-type2-screeners", CadenceGEMState, num_type2_screeners, 4), + DEFINE_PROP_UINT16("jumbo-max-len", CadenceGEMState, + jumbo_max_len, 10240), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/net/can/Makefile.objs b/hw/net/can/Makefile.objs deleted file mode 100644 index 9f0c4ee33239cb57e3d13b7c08f12dc580df22ba..0000000000000000000000000000000000000000 --- a/hw/net/can/Makefile.objs +++ /dev/null @@ -1,4 +0,0 @@ -common-obj-$(CONFIG_CAN_SJA1000) += can_sja1000.o -common-obj-$(CONFIG_CAN_PCI) += can_kvaser_pci.o -common-obj-$(CONFIG_CAN_PCI) += can_pcm3680_pci.o -common-obj-$(CONFIG_CAN_PCI) += can_mioe3680_pci.o diff --git a/hw/net/can/can_kvaser_pci.c b/hw/net/can/can_kvaser_pci.c index 4b941370d05b77fc96be2bb24c54df8d8cb21f69..168b3a620d91a42d7e026a7c91fb3705ab704569 100644 --- a/hw/net/can/can_kvaser_pci.c +++ b/hw/net/can/can_kvaser_pci.c @@ -43,11 +43,13 @@ #include "net/can_emu.h" #include "can_sja1000.h" +#include "qom/object.h" #define TYPE_CAN_PCI_DEV "kvaser_pci" -#define KVASER_PCI_DEV(obj) \ - OBJECT_CHECK(KvaserPCIState, (obj), TYPE_CAN_PCI_DEV) +typedef struct KvaserPCIState KvaserPCIState; +DECLARE_INSTANCE_CHECKER(KvaserPCIState, KVASER_PCI_DEV, + TYPE_CAN_PCI_DEV) #ifndef KVASER_PCI_VENDOR_ID1 #define KVASER_PCI_VENDOR_ID1 0x10e8 /* the PCI device and vendor IDs */ @@ -78,7 +80,7 @@ #define KVASER_PCI_XILINX_VERSION_NUMBER 13 -typedef struct KvaserPCIState { +struct KvaserPCIState { /*< private >*/ PCIDevice dev; /*< public >*/ @@ -93,7 +95,7 @@ typedef struct KvaserPCIState { uint32_t s5920_irqstate; CanBusState *canbus; -} KvaserPCIState; +}; static void kvaser_pci_irq_handler(void *opaque, int irq_num, int level) { diff --git a/hw/net/can/can_mioe3680_pci.c b/hw/net/can/can_mioe3680_pci.c index 695e762a8d14abac1d08f304ebb4f0b458cc5e86..7a79e2605ae6763b9f5db6c832f9f95e8aff738c 100644 --- a/hw/net/can/can_mioe3680_pci.c +++ b/hw/net/can/can_mioe3680_pci.c @@ -39,11 +39,13 @@ #include "net/can_emu.h" #include "can_sja1000.h" +#include "qom/object.h" #define TYPE_CAN_PCI_DEV "mioe3680_pci" -#define MIOe3680_PCI_DEV(obj) \ - OBJECT_CHECK(Mioe3680PCIState, (obj), TYPE_CAN_PCI_DEV) +typedef struct Mioe3680PCIState Mioe3680PCIState; +DECLARE_INSTANCE_CHECKER(Mioe3680PCIState, MIOe3680_PCI_DEV, + TYPE_CAN_PCI_DEV) /* the PCI device and vendor IDs */ #ifndef MIOe3680_PCI_VENDOR_ID1 @@ -59,7 +61,7 @@ #define MIOe3680_PCI_BYTES_PER_SJA 0x80 -typedef struct Mioe3680PCIState { +struct Mioe3680PCIState { /*< private >*/ PCIDevice dev; /*< public >*/ @@ -70,7 +72,7 @@ typedef struct Mioe3680PCIState { char *model; /* The model that support, only SJA1000 now. */ CanBusState *canbus[MIOe3680_PCI_SJA_COUNT]; -} Mioe3680PCIState; +}; static void mioe3680_pci_reset(DeviceState *dev) { diff --git a/hw/net/can/can_pcm3680_pci.c b/hw/net/can/can_pcm3680_pci.c index 4218e63eb2588876a9bd99b56483234889ceccd0..8ef4e74af02cfd04caa1a274104783c4442f304c 100644 --- a/hw/net/can/can_pcm3680_pci.c +++ b/hw/net/can/can_pcm3680_pci.c @@ -39,11 +39,13 @@ #include "net/can_emu.h" #include "can_sja1000.h" +#include "qom/object.h" #define TYPE_CAN_PCI_DEV "pcm3680_pci" -#define PCM3680i_PCI_DEV(obj) \ - OBJECT_CHECK(Pcm3680iPCIState, (obj), TYPE_CAN_PCI_DEV) +typedef struct Pcm3680iPCIState Pcm3680iPCIState; +DECLARE_INSTANCE_CHECKER(Pcm3680iPCIState, PCM3680i_PCI_DEV, + TYPE_CAN_PCI_DEV) /* the PCI device and vendor IDs */ #ifndef PCM3680i_PCI_VENDOR_ID1 @@ -59,7 +61,7 @@ #define PCM3680i_PCI_BYTES_PER_SJA 0x20 -typedef struct Pcm3680iPCIState { +struct Pcm3680iPCIState { /*< private >*/ PCIDevice dev; /*< public >*/ @@ -70,7 +72,7 @@ typedef struct Pcm3680iPCIState { char *model; /* The model that support, only SJA1000 now. */ CanBusState *canbus[PCM3680i_PCI_SJA_COUNT]; -} Pcm3680iPCIState; +}; static void pcm3680i_pci_reset(DeviceState *dev) { diff --git a/hw/net/can/can_sja1000.c b/hw/net/can/can_sja1000.c index ea915a023a510231ca94933aba95f1434e89ebcc..42d2f99dfb1d3cd3fa26f56ccb8d94eba3814735 100644 --- a/hw/net/can/can_sja1000.c +++ b/hw/net/can/can_sja1000.c @@ -268,6 +268,7 @@ static void buff2frame_pel(const uint8_t *buff, qemu_can_frame *frame) { uint8_t i; + frame->flags = 0; frame->can_id = 0; if (buff[0] & 0x40) { /* RTR */ frame->can_id = QEMU_CAN_RTR_FLAG; @@ -303,6 +304,7 @@ static void buff2frame_bas(const uint8_t *buff, qemu_can_frame *frame) { uint8_t i; + frame->flags = 0; frame->can_id = ((buff[0] << 3) & (0xff << 3)) + ((buff[1] >> 5) & 0x07); if (buff[1] & 0x10) { /* RTR */ frame->can_id = QEMU_CAN_RTR_FLAG; @@ -321,11 +323,16 @@ static void buff2frame_bas(const uint8_t *buff, qemu_can_frame *frame) static int frame2buff_pel(const qemu_can_frame *frame, uint8_t *buff) { int i; + int dlen = frame->can_dlc; if (frame->can_id & QEMU_CAN_ERR_FLAG) { /* error frame, NOT support now. */ return -1; } + if (dlen > 8) { + return -1; + } + buff[0] = 0x0f & frame->can_dlc; /* DLC */ if (frame->can_id & QEMU_CAN_RTR_FLAG) { /* RTR */ buff[0] |= (1 << 6); @@ -336,18 +343,18 @@ static int frame2buff_pel(const qemu_can_frame *frame, uint8_t *buff) buff[2] = extract32(frame->can_id, 13, 8); /* ID.20~ID.13 */ buff[3] = extract32(frame->can_id, 5, 8); /* ID.12~ID.05 */ buff[4] = extract32(frame->can_id, 0, 5) << 3; /* ID.04~ID.00,xxx */ - for (i = 0; i < frame->can_dlc; i++) { + for (i = 0; i < dlen; i++) { buff[5 + i] = frame->data[i]; } - return frame->can_dlc + 5; + return dlen + 5; } else { /* SFF */ buff[1] = extract32(frame->can_id, 3, 8); /* ID.10~ID.03 */ buff[2] = extract32(frame->can_id, 0, 3) << 5; /* ID.02~ID.00,xxxxx */ - for (i = 0; i < frame->can_dlc; i++) { + for (i = 0; i < dlen; i++) { buff[3 + i] = frame->data[i]; } - return frame->can_dlc + 3; + return dlen + 3; } return -1; @@ -356,6 +363,7 @@ static int frame2buff_pel(const qemu_can_frame *frame, uint8_t *buff) static int frame2buff_bas(const qemu_can_frame *frame, uint8_t *buff) { int i; + int dlen = frame->can_dlc; /* * EFF, no support for BasicMode @@ -367,17 +375,21 @@ static int frame2buff_bas(const qemu_can_frame *frame, uint8_t *buff) return -1; } + if (dlen > 8) { + return -1; + } + buff[0] = extract32(frame->can_id, 3, 8); /* ID.10~ID.03 */ buff[1] = extract32(frame->can_id, 0, 3) << 5; /* ID.02~ID.00,xxxxx */ if (frame->can_id & QEMU_CAN_RTR_FLAG) { /* RTR */ buff[1] |= (1 << 4); } buff[1] |= frame->can_dlc & 0x0f; - for (i = 0; i < frame->can_dlc; i++) { + for (i = 0; i < dlen; i++) { buff[2 + i] = frame->data[i]; } - return frame->can_dlc + 2; + return dlen + 2; } static void can_sja_update_pel_irq(CanSJA1000State *s) @@ -523,6 +535,7 @@ void can_sja_mem_write(CanSJA1000State *s, hwaddr addr, uint64_t val, break; case 16: /* RX frame information addr16-28. */ s->status_pel |= (1 << 5); /* Set transmit status. */ + /* fallthrough */ case 17 ... 28: if (s->mode & 0x01) { /* Reset mode */ if (addr < 24) { @@ -620,6 +633,7 @@ void can_sja_mem_write(CanSJA1000State *s, hwaddr addr, uint64_t val, break; case 10: s->status_bas |= (1 << 5); /* Set transmit status. */ + /* fallthrough */ case 11 ... 19: if ((s->control & 0x01) == 0) { /* Operation mode */ s->tx_buff[addr - 10] = val; /* Store to TX buffer directly. */ @@ -762,6 +776,13 @@ ssize_t can_sja_receive(CanBusClientState *client, const qemu_can_frame *frames, if (frames_cnt <= 0) { return 0; } + if (frame->flags & QEMU_CAN_FRMF_TYPE_FD) { + if (DEBUG_FILTER) { + can_display_msg("[cansja]: ignor fd frame ", frame); + } + return 1; + } + if (DEBUG_FILTER) { can_display_msg("[cansja]: receive ", frame); } diff --git a/hw/net/can/ctu_can_fd_frame.h b/hw/net/can/ctu_can_fd_frame.h new file mode 100644 index 0000000000000000000000000000000000000000..04d956c84ee7386ee60063a2198181b21fc52477 --- /dev/null +++ b/hw/net/can/ctu_can_fd_frame.h @@ -0,0 +1,189 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/******************************************************************************* + * + * CTU CAN FD IP Core + * + * Copyright (C) 2015-2018 Ondrej Ille FEE CTU + * Copyright (C) 2018-2020 Ondrej Ille self-funded + * Copyright (C) 2018-2019 Martin Jerabek FEE CTU + * Copyright (C) 2018-2020 Pavel Pisa FEE CTU/self-funded + * + * Project advisors: + * Jiri Novak + * Pavel Pisa + * + * Department of Measurement (http://meas.fel.cvut.cz/) + * Faculty of Electrical Engineering (http://www.fel.cvut.cz) + * Czech Technical University (http://www.cvut.cz/) + * + * 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. + ******************************************************************************/ + +/* This file is autogenerated, DO NOT EDIT! */ + +#ifndef __CTU_CAN_FD_CAN_FD_FRAME_FORMAT__ +#define __CTU_CAN_FD_CAN_FD_FRAME_FORMAT__ + +/* CAN_Frame_format memory map */ +enum ctu_can_fd_can_frame_format { + CTU_CAN_FD_FRAME_FORM_W = 0x0, + CTU_CAN_FD_IDENTIFIER_W = 0x4, + CTU_CAN_FD_TIMESTAMP_L_W = 0x8, + CTU_CAN_FD_TIMESTAMP_U_W = 0xc, + CTU_CAN_FD_DATA_1_4_W = 0x10, + CTU_CAN_FD_DATA_5_8_W = 0x14, + CTU_CAN_FD_DATA_61_64_W = 0x4c, +}; + + +/* Register descriptions: */ +union ctu_can_fd_frame_form_w { + uint32_t u32; + struct ctu_can_fd_frame_form_w_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* FRAME_FORM_W */ + uint32_t dlc : 4; + uint32_t reserved_4 : 1; + uint32_t rtr : 1; + uint32_t ide : 1; + uint32_t fdf : 1; + uint32_t reserved_8 : 1; + uint32_t brs : 1; + uint32_t esi_rsv : 1; + uint32_t rwcnt : 5; + uint32_t reserved_31_16 : 16; +#else + uint32_t reserved_31_16 : 16; + uint32_t rwcnt : 5; + uint32_t esi_rsv : 1; + uint32_t brs : 1; + uint32_t reserved_8 : 1; + uint32_t fdf : 1; + uint32_t ide : 1; + uint32_t rtr : 1; + uint32_t reserved_4 : 1; + uint32_t dlc : 4; +#endif + } s; +}; + +enum ctu_can_fd_frame_form_w_rtr { + NO_RTR_FRAME = 0x0, + RTR_FRAME = 0x1, +}; + +enum ctu_can_fd_frame_form_w_ide { + BASE = 0x0, + EXTENDED = 0x1, +}; + +enum ctu_can_fd_frame_form_w_fdf { + NORMAL_CAN = 0x0, + FD_CAN = 0x1, +}; + +enum ctu_can_fd_frame_form_w_brs { + BR_NO_SHIFT = 0x0, + BR_SHIFT = 0x1, +}; + +enum ctu_can_fd_frame_form_w_esi_rsv { + ESI_ERR_ACTIVE = 0x0, + ESI_ERR_PASIVE = 0x1, +}; + +union ctu_can_fd_identifier_w { + uint32_t u32; + struct ctu_can_fd_identifier_w_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* IDENTIFIER_W */ + uint32_t identifier_ext : 18; + uint32_t identifier_base : 11; + uint32_t reserved_31_29 : 3; +#else + uint32_t reserved_31_29 : 3; + uint32_t identifier_base : 11; + uint32_t identifier_ext : 18; +#endif + } s; +}; + +union ctu_can_fd_timestamp_l_w { + uint32_t u32; + struct ctu_can_fd_timestamp_l_w_s { + /* TIMESTAMP_L_W */ + uint32_t time_stamp_31_0 : 32; + } s; +}; + +union ctu_can_fd_timestamp_u_w { + uint32_t u32; + struct ctu_can_fd_timestamp_u_w_s { + /* TIMESTAMP_U_W */ + uint32_t timestamp_l_w : 32; + } s; +}; + +union ctu_can_fd_data_1_4_w { + uint32_t u32; + struct ctu_can_fd_data_1_4_w_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* DATA_1_4_W */ + uint32_t data_1 : 8; + uint32_t data_2 : 8; + uint32_t data_3 : 8; + uint32_t data_4 : 8; +#else + uint32_t data_4 : 8; + uint32_t data_3 : 8; + uint32_t data_2 : 8; + uint32_t data_1 : 8; +#endif + } s; +}; + +union ctu_can_fd_data_5_8_w { + uint32_t u32; + struct ctu_can_fd_data_5_8_w_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* DATA_5_8_W */ + uint32_t data_5 : 8; + uint32_t data_6 : 8; + uint32_t data_7 : 8; + uint32_t data_8 : 8; +#else + uint32_t data_8 : 8; + uint32_t data_7 : 8; + uint32_t data_6 : 8; + uint32_t data_5 : 8; +#endif + } s; +}; + +union ctu_can_fd_data_61_64_w { + uint32_t u32; + struct ctu_can_fd_data_61_64_w_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* DATA_61_64_W */ + uint32_t data_61 : 8; + uint32_t data_62 : 8; + uint32_t data_63 : 8; + uint32_t data_64 : 8; +#else + uint32_t data_64 : 8; + uint32_t data_63 : 8; + uint32_t data_62 : 8; + uint32_t data_61 : 8; +#endif + } s; +}; + +#endif diff --git a/hw/net/can/ctu_can_fd_regs.h b/hw/net/can/ctu_can_fd_regs.h new file mode 100644 index 0000000000000000000000000000000000000000..450f4b9fb3c4157c3640ac6ffd4951f91160de0a --- /dev/null +++ b/hw/net/can/ctu_can_fd_regs.h @@ -0,0 +1,971 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/******************************************************************************* + * + * CTU CAN FD IP Core + * + * Copyright (C) 2015-2018 Ondrej Ille FEE CTU + * Copyright (C) 2018-2020 Ondrej Ille self-funded + * Copyright (C) 2018-2019 Martin Jerabek FEE CTU + * Copyright (C) 2018-2020 Pavel Pisa FEE CTU/self-funded + * + * Project advisors: + * Jiri Novak + * Pavel Pisa + * + * Department of Measurement (http://meas.fel.cvut.cz/) + * Faculty of Electrical Engineering (http://www.fel.cvut.cz) + * Czech Technical University (http://www.cvut.cz/) + * + * 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. + ******************************************************************************/ + +/* This file is autogenerated, DO NOT EDIT! */ + +#ifndef __CTU_CAN_FD_CAN_FD_REGISTER_MAP__ +#define __CTU_CAN_FD_CAN_FD_REGISTER_MAP__ + +/* CAN_Registers memory map */ +enum ctu_can_fd_can_registers { + CTU_CAN_FD_DEVICE_ID = 0x0, + CTU_CAN_FD_VERSION = 0x2, + CTU_CAN_FD_MODE = 0x4, + CTU_CAN_FD_SETTINGS = 0x6, + CTU_CAN_FD_STATUS = 0x8, + CTU_CAN_FD_COMMAND = 0xc, + CTU_CAN_FD_INT_STAT = 0x10, + CTU_CAN_FD_INT_ENA_SET = 0x14, + CTU_CAN_FD_INT_ENA_CLR = 0x18, + CTU_CAN_FD_INT_MASK_SET = 0x1c, + CTU_CAN_FD_INT_MASK_CLR = 0x20, + CTU_CAN_FD_BTR = 0x24, + CTU_CAN_FD_BTR_FD = 0x28, + CTU_CAN_FD_EWL = 0x2c, + CTU_CAN_FD_ERP = 0x2d, + CTU_CAN_FD_FAULT_STATE = 0x2e, + CTU_CAN_FD_REC = 0x30, + CTU_CAN_FD_TEC = 0x32, + CTU_CAN_FD_ERR_NORM = 0x34, + CTU_CAN_FD_ERR_FD = 0x36, + CTU_CAN_FD_CTR_PRES = 0x38, + CTU_CAN_FD_FILTER_A_MASK = 0x3c, + CTU_CAN_FD_FILTER_A_VAL = 0x40, + CTU_CAN_FD_FILTER_B_MASK = 0x44, + CTU_CAN_FD_FILTER_B_VAL = 0x48, + CTU_CAN_FD_FILTER_C_MASK = 0x4c, + CTU_CAN_FD_FILTER_C_VAL = 0x50, + CTU_CAN_FD_FILTER_RAN_LOW = 0x54, + CTU_CAN_FD_FILTER_RAN_HIGH = 0x58, + CTU_CAN_FD_FILTER_CONTROL = 0x5c, + CTU_CAN_FD_FILTER_STATUS = 0x5e, + CTU_CAN_FD_RX_MEM_INFO = 0x60, + CTU_CAN_FD_RX_POINTERS = 0x64, + CTU_CAN_FD_RX_STATUS = 0x68, + CTU_CAN_FD_RX_SETTINGS = 0x6a, + CTU_CAN_FD_RX_DATA = 0x6c, + CTU_CAN_FD_TX_STATUS = 0x70, + CTU_CAN_FD_TX_COMMAND = 0x74, + CTU_CAN_FD_TX_PRIORITY = 0x78, + CTU_CAN_FD_ERR_CAPT = 0x7c, + CTU_CAN_FD_ALC = 0x7e, + CTU_CAN_FD_TRV_DELAY = 0x80, + CTU_CAN_FD_SSP_CFG = 0x82, + CTU_CAN_FD_RX_FR_CTR = 0x84, + CTU_CAN_FD_TX_FR_CTR = 0x88, + CTU_CAN_FD_DEBUG_REGISTER = 0x8c, + CTU_CAN_FD_YOLO_REG = 0x90, + CTU_CAN_FD_TIMESTAMP_LOW = 0x94, + CTU_CAN_FD_TIMESTAMP_HIGH = 0x98, + CTU_CAN_FD_TXTB1_DATA_1 = 0x100, + CTU_CAN_FD_TXTB1_DATA_2 = 0x104, + CTU_CAN_FD_TXTB1_DATA_20 = 0x14c, + CTU_CAN_FD_TXTB2_DATA_1 = 0x200, + CTU_CAN_FD_TXTB2_DATA_2 = 0x204, + CTU_CAN_FD_TXTB2_DATA_20 = 0x24c, + CTU_CAN_FD_TXTB3_DATA_1 = 0x300, + CTU_CAN_FD_TXTB3_DATA_2 = 0x304, + CTU_CAN_FD_TXTB3_DATA_20 = 0x34c, + CTU_CAN_FD_TXTB4_DATA_1 = 0x400, + CTU_CAN_FD_TXTB4_DATA_2 = 0x404, + CTU_CAN_FD_TXTB4_DATA_20 = 0x44c, +}; + + +/* Register descriptions: */ +union ctu_can_fd_device_id_version { + uint32_t u32; + struct ctu_can_fd_device_id_version_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* DEVICE_ID */ + uint32_t device_id : 16; + /* VERSION */ + uint32_t ver_minor : 8; + uint32_t ver_major : 8; +#else + uint32_t ver_major : 8; + uint32_t ver_minor : 8; + uint32_t device_id : 16; +#endif + } s; +}; + +enum ctu_can_fd_device_id_device_id { + CTU_CAN_FD_ID = 0xcafd, +}; + +union ctu_can_fd_mode_settings { + uint32_t u32; + struct ctu_can_fd_mode_settings_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* MODE */ + uint32_t rst : 1; + uint32_t lom : 1; + uint32_t stm : 1; + uint32_t afm : 1; + uint32_t fde : 1; + uint32_t reserved_6_5 : 2; + uint32_t acf : 1; + uint32_t tstm : 1; + uint32_t reserved_15_9 : 7; + /* SETTINGS */ + uint32_t rtrle : 1; + uint32_t rtrth : 4; + uint32_t ilbp : 1; + uint32_t ena : 1; + uint32_t nisofd : 1; + uint32_t pex : 1; + uint32_t reserved_31_25 : 7; +#else + uint32_t reserved_31_25 : 7; + uint32_t pex : 1; + uint32_t nisofd : 1; + uint32_t ena : 1; + uint32_t ilbp : 1; + uint32_t rtrth : 4; + uint32_t rtrle : 1; + uint32_t reserved_15_9 : 7; + uint32_t tstm : 1; + uint32_t acf : 1; + uint32_t reserved_6_5 : 2; + uint32_t fde : 1; + uint32_t afm : 1; + uint32_t stm : 1; + uint32_t lom : 1; + uint32_t rst : 1; +#endif + } s; +}; + +enum ctu_can_fd_mode_lom { + LOM_DISABLED = 0x0, + LOM_ENABLED = 0x1, +}; + +enum ctu_can_fd_mode_stm { + STM_DISABLED = 0x0, + STM_ENABLED = 0x1, +}; + +enum ctu_can_fd_mode_afm { + AFM_DISABLED = 0x0, + AFM_ENABLED = 0x1, +}; + +enum ctu_can_fd_mode_fde { + FDE_DISABLE = 0x0, + FDE_ENABLE = 0x1, +}; + +enum ctu_can_fd_mode_acf { + ACF_DISABLED = 0x0, + ACF_ENABLED = 0x1, +}; + +enum ctu_can_fd_settings_rtrle { + RTRLE_DISABLED = 0x0, + RTRLE_ENABLED = 0x1, +}; + +enum ctu_can_fd_settings_ilbp { + INT_LOOP_DISABLED = 0x0, + INT_LOOP_ENABLED = 0x1, +}; + +enum ctu_can_fd_settings_ena { + CTU_CAN_DISABLED = 0x0, + CTU_CAN_ENABLED = 0x1, +}; + +enum ctu_can_fd_settings_nisofd { + ISO_FD = 0x0, + NON_ISO_FD = 0x1, +}; + +enum ctu_can_fd_settings_pex { + PROTOCOL_EXCEPTION_DISABLED = 0x0, + PROTOCOL_EXCEPTION_ENABLED = 0x1, +}; + +union ctu_can_fd_status { + uint32_t u32; + struct ctu_can_fd_status_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* STATUS */ + uint32_t rxne : 1; + uint32_t dor : 1; + uint32_t txnf : 1; + uint32_t eft : 1; + uint32_t rxs : 1; + uint32_t txs : 1; + uint32_t ewl : 1; + uint32_t idle : 1; + uint32_t reserved_31_8 : 24; +#else + uint32_t reserved_31_8 : 24; + uint32_t idle : 1; + uint32_t ewl : 1; + uint32_t txs : 1; + uint32_t rxs : 1; + uint32_t eft : 1; + uint32_t txnf : 1; + uint32_t dor : 1; + uint32_t rxne : 1; +#endif + } s; +}; + +union ctu_can_fd_command { + uint32_t u32; + struct ctu_can_fd_command_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + uint32_t reserved_1_0 : 2; + /* COMMAND */ + uint32_t rrb : 1; + uint32_t cdo : 1; + uint32_t ercrst : 1; + uint32_t rxfcrst : 1; + uint32_t txfcrst : 1; + uint32_t reserved_31_7 : 25; +#else + uint32_t reserved_31_7 : 25; + uint32_t txfcrst : 1; + uint32_t rxfcrst : 1; + uint32_t ercrst : 1; + uint32_t cdo : 1; + uint32_t rrb : 1; + uint32_t reserved_1_0 : 2; +#endif + } s; +}; + +union ctu_can_fd_int_stat { + uint32_t u32; + struct ctu_can_fd_int_stat_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* INT_STAT */ + uint32_t rxi : 1; + uint32_t txi : 1; + uint32_t ewli : 1; + uint32_t doi : 1; + uint32_t fcsi : 1; + uint32_t ali : 1; + uint32_t bei : 1; + uint32_t ofi : 1; + uint32_t rxfi : 1; + uint32_t bsi : 1; + uint32_t rbnei : 1; + uint32_t txbhci : 1; + uint32_t reserved_31_12 : 20; +#else + uint32_t reserved_31_12 : 20; + uint32_t txbhci : 1; + uint32_t rbnei : 1; + uint32_t bsi : 1; + uint32_t rxfi : 1; + uint32_t ofi : 1; + uint32_t bei : 1; + uint32_t ali : 1; + uint32_t fcsi : 1; + uint32_t doi : 1; + uint32_t ewli : 1; + uint32_t txi : 1; + uint32_t rxi : 1; +#endif + } s; +}; + +union ctu_can_fd_int_ena_set { + uint32_t u32; + struct ctu_can_fd_int_ena_set_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* INT_ENA_SET */ + uint32_t int_ena_set : 12; + uint32_t reserved_31_12 : 20; +#else + uint32_t reserved_31_12 : 20; + uint32_t int_ena_set : 12; +#endif + } s; +}; + +union ctu_can_fd_int_ena_clr { + uint32_t u32; + struct ctu_can_fd_int_ena_clr_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* INT_ENA_CLR */ + uint32_t int_ena_clr : 12; + uint32_t reserved_31_12 : 20; +#else + uint32_t reserved_31_12 : 20; + uint32_t int_ena_clr : 12; +#endif + } s; +}; + +union ctu_can_fd_int_mask_set { + uint32_t u32; + struct ctu_can_fd_int_mask_set_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* INT_MASK_SET */ + uint32_t int_mask_set : 12; + uint32_t reserved_31_12 : 20; +#else + uint32_t reserved_31_12 : 20; + uint32_t int_mask_set : 12; +#endif + } s; +}; + +union ctu_can_fd_int_mask_clr { + uint32_t u32; + struct ctu_can_fd_int_mask_clr_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* INT_MASK_CLR */ + uint32_t int_mask_clr : 12; + uint32_t reserved_31_12 : 20; +#else + uint32_t reserved_31_12 : 20; + uint32_t int_mask_clr : 12; +#endif + } s; +}; + +union ctu_can_fd_btr { + uint32_t u32; + struct ctu_can_fd_btr_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* BTR */ + uint32_t prop : 7; + uint32_t ph1 : 6; + uint32_t ph2 : 6; + uint32_t brp : 8; + uint32_t sjw : 5; +#else + uint32_t sjw : 5; + uint32_t brp : 8; + uint32_t ph2 : 6; + uint32_t ph1 : 6; + uint32_t prop : 7; +#endif + } s; +}; + +union ctu_can_fd_btr_fd { + uint32_t u32; + struct ctu_can_fd_btr_fd_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* BTR_FD */ + uint32_t prop_fd : 6; + uint32_t reserved_6 : 1; + uint32_t ph1_fd : 5; + uint32_t reserved_12 : 1; + uint32_t ph2_fd : 5; + uint32_t reserved_18 : 1; + uint32_t brp_fd : 8; + uint32_t sjw_fd : 5; +#else + uint32_t sjw_fd : 5; + uint32_t brp_fd : 8; + uint32_t reserved_18 : 1; + uint32_t ph2_fd : 5; + uint32_t reserved_12 : 1; + uint32_t ph1_fd : 5; + uint32_t reserved_6 : 1; + uint32_t prop_fd : 6; +#endif + } s; +}; + +union ctu_can_fd_ewl_erp_fault_state { + uint32_t u32; + struct ctu_can_fd_ewl_erp_fault_state_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* EWL */ + uint32_t ew_limit : 8; + /* ERP */ + uint32_t erp_limit : 8; + /* FAULT_STATE */ + uint32_t era : 1; + uint32_t erp : 1; + uint32_t bof : 1; + uint32_t reserved_31_19 : 13; +#else + uint32_t reserved_31_19 : 13; + uint32_t bof : 1; + uint32_t erp : 1; + uint32_t era : 1; + uint32_t erp_limit : 8; + uint32_t ew_limit : 8; +#endif + } s; +}; + +union ctu_can_fd_rec_tec { + uint32_t u32; + struct ctu_can_fd_rec_tec_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* REC */ + uint32_t rec_val : 9; + uint32_t reserved_15_9 : 7; + /* TEC */ + uint32_t tec_val : 9; + uint32_t reserved_31_25 : 7; +#else + uint32_t reserved_31_25 : 7; + uint32_t tec_val : 9; + uint32_t reserved_15_9 : 7; + uint32_t rec_val : 9; +#endif + } s; +}; + +union ctu_can_fd_err_norm_err_fd { + uint32_t u32; + struct ctu_can_fd_err_norm_err_fd_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* ERR_NORM */ + uint32_t err_norm_val : 16; + /* ERR_FD */ + uint32_t err_fd_val : 16; +#else + uint32_t err_fd_val : 16; + uint32_t err_norm_val : 16; +#endif + } s; +}; + +union ctu_can_fd_ctr_pres { + uint32_t u32; + struct ctu_can_fd_ctr_pres_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* CTR_PRES */ + uint32_t ctpv : 9; + uint32_t ptx : 1; + uint32_t prx : 1; + uint32_t enorm : 1; + uint32_t efd : 1; + uint32_t reserved_31_13 : 19; +#else + uint32_t reserved_31_13 : 19; + uint32_t efd : 1; + uint32_t enorm : 1; + uint32_t prx : 1; + uint32_t ptx : 1; + uint32_t ctpv : 9; +#endif + } s; +}; + +union ctu_can_fd_filter_a_mask { + uint32_t u32; + struct ctu_can_fd_filter_a_mask_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* FILTER_A_MASK */ + uint32_t bit_mask_a_val : 29; + uint32_t reserved_31_29 : 3; +#else + uint32_t reserved_31_29 : 3; + uint32_t bit_mask_a_val : 29; +#endif + } s; +}; + +union ctu_can_fd_filter_a_val { + uint32_t u32; + struct ctu_can_fd_filter_a_val_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* FILTER_A_VAL */ + uint32_t bit_val_a_val : 29; + uint32_t reserved_31_29 : 3; +#else + uint32_t reserved_31_29 : 3; + uint32_t bit_val_a_val : 29; +#endif + } s; +}; + +union ctu_can_fd_filter_b_mask { + uint32_t u32; + struct ctu_can_fd_filter_b_mask_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* FILTER_B_MASK */ + uint32_t bit_mask_b_val : 29; + uint32_t reserved_31_29 : 3; +#else + uint32_t reserved_31_29 : 3; + uint32_t bit_mask_b_val : 29; +#endif + } s; +}; + +union ctu_can_fd_filter_b_val { + uint32_t u32; + struct ctu_can_fd_filter_b_val_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* FILTER_B_VAL */ + uint32_t bit_val_b_val : 29; + uint32_t reserved_31_29 : 3; +#else + uint32_t reserved_31_29 : 3; + uint32_t bit_val_b_val : 29; +#endif + } s; +}; + +union ctu_can_fd_filter_c_mask { + uint32_t u32; + struct ctu_can_fd_filter_c_mask_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* FILTER_C_MASK */ + uint32_t bit_mask_c_val : 29; + uint32_t reserved_31_29 : 3; +#else + uint32_t reserved_31_29 : 3; + uint32_t bit_mask_c_val : 29; +#endif + } s; +}; + +union ctu_can_fd_filter_c_val { + uint32_t u32; + struct ctu_can_fd_filter_c_val_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* FILTER_C_VAL */ + uint32_t bit_val_c_val : 29; + uint32_t reserved_31_29 : 3; +#else + uint32_t reserved_31_29 : 3; + uint32_t bit_val_c_val : 29; +#endif + } s; +}; + +union ctu_can_fd_filter_ran_low { + uint32_t u32; + struct ctu_can_fd_filter_ran_low_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* FILTER_RAN_LOW */ + uint32_t bit_ran_low_val : 29; + uint32_t reserved_31_29 : 3; +#else + uint32_t reserved_31_29 : 3; + uint32_t bit_ran_low_val : 29; +#endif + } s; +}; + +union ctu_can_fd_filter_ran_high { + uint32_t u32; + struct ctu_can_fd_filter_ran_high_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* FILTER_RAN_HIGH */ + uint32_t bit_ran_high_val : 29; + uint32_t reserved_31_29 : 3; +#else + uint32_t reserved_31_29 : 3; + uint32_t bit_ran_high_val : 29; +#endif + } s; +}; + +union ctu_can_fd_filter_control_filter_status { + uint32_t u32; + struct ctu_can_fd_filter_control_filter_status_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* FILTER_CONTROL */ + uint32_t fanb : 1; + uint32_t fane : 1; + uint32_t fafb : 1; + uint32_t fafe : 1; + uint32_t fbnb : 1; + uint32_t fbne : 1; + uint32_t fbfb : 1; + uint32_t fbfe : 1; + uint32_t fcnb : 1; + uint32_t fcne : 1; + uint32_t fcfb : 1; + uint32_t fcfe : 1; + uint32_t frnb : 1; + uint32_t frne : 1; + uint32_t frfb : 1; + uint32_t frfe : 1; + /* FILTER_STATUS */ + uint32_t sfa : 1; + uint32_t sfb : 1; + uint32_t sfc : 1; + uint32_t sfr : 1; + uint32_t reserved_31_20 : 12; +#else + uint32_t reserved_31_20 : 12; + uint32_t sfr : 1; + uint32_t sfc : 1; + uint32_t sfb : 1; + uint32_t sfa : 1; + uint32_t frfe : 1; + uint32_t frfb : 1; + uint32_t frne : 1; + uint32_t frnb : 1; + uint32_t fcfe : 1; + uint32_t fcfb : 1; + uint32_t fcne : 1; + uint32_t fcnb : 1; + uint32_t fbfe : 1; + uint32_t fbfb : 1; + uint32_t fbne : 1; + uint32_t fbnb : 1; + uint32_t fafe : 1; + uint32_t fafb : 1; + uint32_t fane : 1; + uint32_t fanb : 1; +#endif + } s; +}; + +union ctu_can_fd_rx_mem_info { + uint32_t u32; + struct ctu_can_fd_rx_mem_info_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* RX_MEM_INFO */ + uint32_t rx_buff_size : 13; + uint32_t reserved_15_13 : 3; + uint32_t rx_mem_free : 13; + uint32_t reserved_31_29 : 3; +#else + uint32_t reserved_31_29 : 3; + uint32_t rx_mem_free : 13; + uint32_t reserved_15_13 : 3; + uint32_t rx_buff_size : 13; +#endif + } s; +}; + +union ctu_can_fd_rx_pointers { + uint32_t u32; + struct ctu_can_fd_rx_pointers_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* RX_POINTERS */ + uint32_t rx_wpp : 12; + uint32_t reserved_15_12 : 4; + uint32_t rx_rpp : 12; + uint32_t reserved_31_28 : 4; +#else + uint32_t reserved_31_28 : 4; + uint32_t rx_rpp : 12; + uint32_t reserved_15_12 : 4; + uint32_t rx_wpp : 12; +#endif + } s; +}; + +union ctu_can_fd_rx_status_rx_settings { + uint32_t u32; + struct ctu_can_fd_rx_status_rx_settings_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* RX_STATUS */ + uint32_t rxe : 1; + uint32_t rxf : 1; + uint32_t reserved_3_2 : 2; + uint32_t rxfrc : 11; + uint32_t reserved_15 : 1; + /* RX_SETTINGS */ + uint32_t rtsop : 1; + uint32_t reserved_31_17 : 15; +#else + uint32_t reserved_31_17 : 15; + uint32_t rtsop : 1; + uint32_t reserved_15 : 1; + uint32_t rxfrc : 11; + uint32_t reserved_3_2 : 2; + uint32_t rxf : 1; + uint32_t rxe : 1; +#endif + } s; +}; + +enum ctu_can_fd_rx_settings_rtsop { + RTS_END = 0x0, + RTS_BEG = 0x1, +}; + +union ctu_can_fd_rx_data { + uint32_t u32; + struct ctu_can_fd_rx_data_s { + /* RX_DATA */ + uint32_t rx_data : 32; + } s; +}; + +union ctu_can_fd_tx_status { + uint32_t u32; + struct ctu_can_fd_tx_status_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* TX_STATUS */ + uint32_t tx1s : 4; + uint32_t tx2s : 4; + uint32_t tx3s : 4; + uint32_t tx4s : 4; + uint32_t reserved_31_16 : 16; +#else + uint32_t reserved_31_16 : 16; + uint32_t tx4s : 4; + uint32_t tx3s : 4; + uint32_t tx2s : 4; + uint32_t tx1s : 4; +#endif + } s; +}; + +enum ctu_can_fd_tx_status_tx1s { + TXT_RDY = 0x1, + TXT_TRAN = 0x2, + TXT_ABTP = 0x3, + TXT_TOK = 0x4, + TXT_ERR = 0x6, + TXT_ABT = 0x7, + TXT_ETY = 0x8, +}; + +union ctu_can_fd_tx_command { + uint32_t u32; + struct ctu_can_fd_tx_command_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* TX_COMMAND */ + uint32_t txce : 1; + uint32_t txcr : 1; + uint32_t txca : 1; + uint32_t reserved_7_3 : 5; + uint32_t txb1 : 1; + uint32_t txb2 : 1; + uint32_t txb3 : 1; + uint32_t txb4 : 1; + uint32_t reserved_31_12 : 20; +#else + uint32_t reserved_31_12 : 20; + uint32_t txb4 : 1; + uint32_t txb3 : 1; + uint32_t txb2 : 1; + uint32_t txb1 : 1; + uint32_t reserved_7_3 : 5; + uint32_t txca : 1; + uint32_t txcr : 1; + uint32_t txce : 1; +#endif + } s; +}; + +union ctu_can_fd_tx_priority { + uint32_t u32; + struct ctu_can_fd_tx_priority_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* TX_PRIORITY */ + uint32_t txt1p : 3; + uint32_t reserved_3 : 1; + uint32_t txt2p : 3; + uint32_t reserved_7 : 1; + uint32_t txt3p : 3; + uint32_t reserved_11 : 1; + uint32_t txt4p : 3; + uint32_t reserved_31_15 : 17; +#else + uint32_t reserved_31_15 : 17; + uint32_t txt4p : 3; + uint32_t reserved_11 : 1; + uint32_t txt3p : 3; + uint32_t reserved_7 : 1; + uint32_t txt2p : 3; + uint32_t reserved_3 : 1; + uint32_t txt1p : 3; +#endif + } s; +}; + +union ctu_can_fd_err_capt_alc { + uint32_t u32; + struct ctu_can_fd_err_capt_alc_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* ERR_CAPT */ + uint32_t err_pos : 5; + uint32_t err_type : 3; + uint32_t reserved_15_8 : 8; + /* ALC */ + uint32_t alc_bit : 5; + uint32_t alc_id_field : 3; + uint32_t reserved_31_24 : 8; +#else + uint32_t reserved_31_24 : 8; + uint32_t alc_id_field : 3; + uint32_t alc_bit : 5; + uint32_t reserved_15_8 : 8; + uint32_t err_type : 3; + uint32_t err_pos : 5; +#endif + } s; +}; + +enum ctu_can_fd_err_capt_err_pos { + ERC_POS_SOF = 0x0, + ERC_POS_ARB = 0x1, + ERC_POS_CTRL = 0x2, + ERC_POS_DATA = 0x3, + ERC_POS_CRC = 0x4, + ERC_POS_ACK = 0x5, + ERC_POS_EOF = 0x6, + ERC_POS_ERR = 0x7, + ERC_POS_OVRL = 0x8, + ERC_POS_OTHER = 0x1f, +}; + +enum ctu_can_fd_err_capt_err_type { + ERC_BIT_ERR = 0x0, + ERC_CRC_ERR = 0x1, + ERC_FRM_ERR = 0x2, + ERC_ACK_ERR = 0x3, + ERC_STUF_ERR = 0x4, +}; + +enum ctu_can_fd_alc_alc_id_field { + ALC_RSVD = 0x0, + ALC_BASE_ID = 0x1, + ALC_SRR_RTR = 0x2, + ALC_IDE = 0x3, + ALC_EXTENSION = 0x4, + ALC_RTR = 0x5, +}; + +union ctu_can_fd_trv_delay_ssp_cfg { + uint32_t u32; + struct ctu_can_fd_trv_delay_ssp_cfg_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* TRV_DELAY */ + uint32_t trv_delay_value : 7; + uint32_t reserved_15_7 : 9; + /* SSP_CFG */ + uint32_t ssp_offset : 8; + uint32_t ssp_src : 2; + uint32_t reserved_31_26 : 6; +#else + uint32_t reserved_31_26 : 6; + uint32_t ssp_src : 2; + uint32_t ssp_offset : 8; + uint32_t reserved_15_7 : 9; + uint32_t trv_delay_value : 7; +#endif + } s; +}; + +enum ctu_can_fd_ssp_cfg_ssp_src { + SSP_SRC_MEAS_N_OFFSET = 0x0, + SSP_SRC_NO_SSP = 0x1, + SSP_SRC_OFFSET = 0x2, +}; + +union ctu_can_fd_rx_fr_ctr { + uint32_t u32; + struct ctu_can_fd_rx_fr_ctr_s { + /* RX_FR_CTR */ + uint32_t rx_fr_ctr_val : 32; + } s; +}; + +union ctu_can_fd_tx_fr_ctr { + uint32_t u32; + struct ctu_can_fd_tx_fr_ctr_s { + /* TX_FR_CTR */ + uint32_t tx_fr_ctr_val : 32; + } s; +}; + +union ctu_can_fd_debug_register { + uint32_t u32; + struct ctu_can_fd_debug_register_s { +#ifdef __LITTLE_ENDIAN_BITFIELD + /* DEBUG_REGISTER */ + uint32_t stuff_count : 3; + uint32_t destuff_count : 3; + uint32_t pc_arb : 1; + uint32_t pc_con : 1; + uint32_t pc_dat : 1; + uint32_t pc_stc : 1; + uint32_t pc_crc : 1; + uint32_t pc_crcd : 1; + uint32_t pc_ack : 1; + uint32_t pc_ackd : 1; + uint32_t pc_eof : 1; + uint32_t pc_int : 1; + uint32_t pc_susp : 1; + uint32_t pc_ovr : 1; + uint32_t pc_sof : 1; + uint32_t reserved_31_19 : 13; +#else + uint32_t reserved_31_19 : 13; + uint32_t pc_sof : 1; + uint32_t pc_ovr : 1; + uint32_t pc_susp : 1; + uint32_t pc_int : 1; + uint32_t pc_eof : 1; + uint32_t pc_ackd : 1; + uint32_t pc_ack : 1; + uint32_t pc_crcd : 1; + uint32_t pc_crc : 1; + uint32_t pc_stc : 1; + uint32_t pc_dat : 1; + uint32_t pc_con : 1; + uint32_t pc_arb : 1; + uint32_t destuff_count : 3; + uint32_t stuff_count : 3; +#endif + } s; +}; + +union ctu_can_fd_yolo_reg { + uint32_t u32; + struct ctu_can_fd_yolo_reg_s { + /* YOLO_REG */ + uint32_t yolo_val : 32; + } s; +}; + +union ctu_can_fd_timestamp_low { + uint32_t u32; + struct ctu_can_fd_timestamp_low_s { + /* TIMESTAMP_LOW */ + uint32_t timestamp_low : 32; + } s; +}; + +union ctu_can_fd_timestamp_high { + uint32_t u32; + struct ctu_can_fd_timestamp_high_s { + /* TIMESTAMP_HIGH */ + uint32_t timestamp_high : 32; + } s; +}; + +#endif diff --git a/hw/net/can/ctucan_core.c b/hw/net/can/ctucan_core.c new file mode 100644 index 0000000000000000000000000000000000000000..d171c372e008ea5df25da6d3b39024a9b9eab2be --- /dev/null +++ b/hw/net/can/ctucan_core.c @@ -0,0 +1,687 @@ +/* + * CTU CAN FD PCI device emulation + * http://canbus.pages.fel.cvut.cz/ + * + * Copyright (c) 2019 Jan Charvat (jancharvat.charvat@gmail.com) + * + * Based on Kvaser PCI CAN device (SJA1000 based) emulation implemented by + * Jin Yang and Pavel Pisa + * + * 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 "qemu/log.h" +#include "chardev/char.h" +#include "hw/irq.h" +#include "migration/vmstate.h" +#include "net/can_emu.h" + +#include "ctucan_core.h" + +#ifndef DEBUG_CAN +#define DEBUG_CAN 0 +#endif /*DEBUG_CAN*/ + +#define DPRINTF(fmt, ...) \ + do { \ + if (DEBUG_CAN) { \ + qemu_log("[ctucan]: " fmt , ## __VA_ARGS__); \ + } \ + } while (0) + +static void ctucan_buff2frame(const uint8_t *buff, qemu_can_frame *frame) +{ + frame->can_id = 0; + frame->can_dlc = 0; + frame->flags = 0; + + if (buff == NULL) { + return; + } + { + union ctu_can_fd_frame_form_w frame_form_w; + union ctu_can_fd_identifier_w identifier_w; + unsigned int ide; + uint32_t w; + + w = le32_to_cpu(*(uint32_t *)buff); + frame_form_w = (union ctu_can_fd_frame_form_w)w; + frame->can_dlc = can_dlc2len(frame_form_w.s.dlc); + + w = le32_to_cpu(*(uint32_t *)(buff + 4)); + identifier_w = (union ctu_can_fd_identifier_w)w; + + ide = frame_form_w.s.ide; + if (ide) { + frame->can_id = (identifier_w.s.identifier_base << 18) | + identifier_w.s.identifier_ext; + frame->can_id |= QEMU_CAN_EFF_FLAG; + } else { + frame->can_id = identifier_w.s.identifier_base; + } + + if (frame_form_w.s.esi_rsv) { + frame->flags |= QEMU_CAN_FRMF_ESI; + } + + if (frame_form_w.s.rtr) { + frame->can_id |= QEMU_CAN_RTR_FLAG; + } + + if (frame_form_w.s.fdf) { /*CAN FD*/ + frame->flags |= QEMU_CAN_FRMF_TYPE_FD; + if (frame_form_w.s.brs) { + frame->flags |= QEMU_CAN_FRMF_BRS; + } + } + } + + memcpy(frame->data, buff + 0x10, 0x40); +} + + +static int ctucan_frame2buff(const qemu_can_frame *frame, uint8_t *buff) +{ + unsigned int bytes_cnt = -1; + memset(buff, 0, CTUCAN_MSG_MAX_LEN * sizeof(*buff)); + + if (frame == NULL) { + return bytes_cnt; + } + { + union ctu_can_fd_frame_form_w frame_form_w; + union ctu_can_fd_identifier_w identifier_w; + + frame_form_w.u32 = 0; + identifier_w.u32 = 0; + + bytes_cnt = frame->can_dlc; + bytes_cnt = (bytes_cnt + 3) & ~3; + bytes_cnt += 16; + frame_form_w.s.rwcnt = (bytes_cnt >> 2) - 1; + + frame_form_w.s.dlc = can_len2dlc(frame->can_dlc); + + if (frame->can_id & QEMU_CAN_EFF_FLAG) { + frame_form_w.s.ide = 1; + identifier_w.s.identifier_base = + (frame->can_id & 0x1FFC0000) >> 18; + identifier_w.s.identifier_ext = frame->can_id & 0x3FFFF; + } else { + identifier_w.s.identifier_base = frame->can_id & 0x7FF; + } + + if (frame->flags & QEMU_CAN_FRMF_ESI) { + frame_form_w.s.esi_rsv = 1; + } + + if (frame->can_id & QEMU_CAN_RTR_FLAG) { + frame_form_w.s.rtr = 1; + } + + if (frame->flags & QEMU_CAN_FRMF_TYPE_FD) { /*CAN FD*/ + frame_form_w.s.fdf = 1; + if (frame->flags & QEMU_CAN_FRMF_BRS) { + frame_form_w.s.brs = 1; + } + } + *(uint32_t *)buff = cpu_to_le32(frame_form_w.u32); + *(uint32_t *)(buff + 4) = cpu_to_le32(identifier_w.u32); + } + + memcpy(buff + 0x10, frame->data, 0x40); + + return bytes_cnt; +} + +static void ctucan_update_irq(CtuCanCoreState *s) +{ + union ctu_can_fd_int_stat int_rq; + + int_rq.u32 = 0; + + if (s->rx_status_rx_settings.s.rxfrc) { + int_rq.s.rbnei = 1; + } + + int_rq.u32 &= ~s->int_mask.u32; + s->int_stat.u32 |= int_rq.u32; + if (s->int_stat.u32 & s->int_ena.u32) { + qemu_irq_raise(s->irq); + } else { + qemu_irq_lower(s->irq); + } +} + +static void ctucan_update_txnf(CtuCanCoreState *s) +{ + int i; + int txnf; + unsigned int buff_st; + + txnf = 0; + + for (i = 0; i < CTUCAN_CORE_TXBUF_NUM; i++) { + buff_st = (s->tx_status.u32 >> (i * 4)) & 0xf; + if (buff_st == TXT_ETY) { + txnf = 1; + } + } + s->status.s.txnf = txnf; +} + +void ctucan_hardware_reset(CtuCanCoreState *s) +{ + DPRINTF("Hardware reset in progress!!!\n"); + int i; + unsigned int buff_st; + uint32_t buff_st_mask; + + s->tx_status.u32 = 0; + for (i = 0; i < CTUCAN_CORE_TXBUF_NUM; i++) { + buff_st_mask = 0xf << (i * 4); + buff_st = TXT_ETY; + s->tx_status.u32 = (s->tx_status.u32 & ~buff_st_mask) | + (buff_st << (i * 4)); + } + s->status.s.idle = 1; + + ctucan_update_txnf(s); + + s->rx_status_rx_settings.u32 = 0; + s->rx_tail_pos = 0; + s->rx_cnt = 0; + s->rx_frame_rem = 0; + + /* Flush RX buffer */ + s->rx_tail_pos = 0; + s->rx_cnt = 0; + s->rx_frame_rem = 0; + + /* Set on progdokum reset value */ + s->mode_settings.u32 = 0; + s->mode_settings.s.fde = 1; + + s->int_stat.u32 = 0; + s->int_ena.u32 = 0; + s->int_mask.u32 = 0; + + s->rx_status_rx_settings.u32 = 0; + s->rx_status_rx_settings.s.rxe = 0; + + s->rx_fr_ctr.u32 = 0; + s->tx_fr_ctr.u32 = 0; + + s->yolo_reg.s.yolo_val = 3735928559; + + qemu_irq_lower(s->irq); +} + +static void ctucan_send_ready_buffers(CtuCanCoreState *s) +{ + qemu_can_frame frame; + uint8_t *pf; + int buff2tx_idx; + uint32_t tx_prio_max; + + if (!s->mode_settings.s.ena) { + return; + } + + do { + union ctu_can_fd_int_stat int_stat; + int i; + buff2tx_idx = -1; + tx_prio_max = 0; + + for (i = 0; i < CTUCAN_CORE_TXBUF_NUM; i++) { + uint32_t prio; + + if (extract32(s->tx_status.u32, i * 4, 4) != TXT_RDY) { + continue; + } + prio = (s->tx_priority.u32 >> (i * 4)) & 0x7; + if (tx_prio_max < prio) { + tx_prio_max = prio; + buff2tx_idx = i; + } + } + if (buff2tx_idx == -1) { + break; + } + int_stat.u32 = 0; + pf = s->tx_buffer[buff2tx_idx].data; + ctucan_buff2frame(pf, &frame); + s->status.s.idle = 0; + s->status.s.txs = 1; + can_bus_client_send(&s->bus_client, &frame, 1); + s->status.s.idle = 1; + s->status.s.txs = 0; + s->tx_fr_ctr.s.tx_fr_ctr_val++; + int_stat.s.txi = 1; + int_stat.s.txbhci = 1; + s->int_stat.u32 |= int_stat.u32 & ~s->int_mask.u32; + s->tx_status.u32 = deposit32(s->tx_status.u32, + buff2tx_idx * 4, 4, TXT_TOK); + } while (1); +} + +#define CTUCAN_CORE_TXBUFF_SPAN \ + (CTU_CAN_FD_TXTB2_DATA_1 - CTU_CAN_FD_TXTB1_DATA_1) + +void ctucan_mem_write(CtuCanCoreState *s, hwaddr addr, uint64_t val, + unsigned size) +{ + int i; + + DPRINTF("write 0x%02llx addr 0x%02x\n", + (unsigned long long)val, (unsigned int)addr); + + if (addr >= CTUCAN_CORE_MEM_SIZE) { + return; + } + + if (addr >= CTU_CAN_FD_TXTB1_DATA_1) { + int buff_num; + addr -= CTU_CAN_FD_TXTB1_DATA_1; + buff_num = addr / CTUCAN_CORE_TXBUFF_SPAN; + addr %= CTUCAN_CORE_TXBUFF_SPAN; + if ((buff_num < CTUCAN_CORE_TXBUF_NUM) && + ((addr + size) <= sizeof(s->tx_buffer[buff_num].data))) { + stn_le_p(s->tx_buffer[buff_num].data + addr, size, val); + } + } else { + switch (addr & ~3) { + case CTU_CAN_FD_MODE: + s->mode_settings.u32 = (uint32_t)val; + if (s->mode_settings.s.rst) { + ctucan_hardware_reset(s); + s->mode_settings.s.rst = 0; + } + break; + case CTU_CAN_FD_COMMAND: + { + union ctu_can_fd_command command; + command.u32 = (uint32_t)val; + if (command.s.cdo) { + s->status.s.dor = 0; + } + if (command.s.rrb) { + s->rx_tail_pos = 0; + s->rx_cnt = 0; + s->rx_frame_rem = 0; + s->rx_status_rx_settings.s.rxfrc = 0; + } + if (command.s.txfcrst) { + s->tx_fr_ctr.s.tx_fr_ctr_val = 0; + } + if (command.s.rxfcrst) { + s->rx_fr_ctr.s.rx_fr_ctr_val = 0; + } + break; + } + case CTU_CAN_FD_INT_STAT: + s->int_stat.u32 &= ~(uint32_t)val; + break; + case CTU_CAN_FD_INT_ENA_SET: + s->int_ena.u32 |= (uint32_t)val; + break; + case CTU_CAN_FD_INT_ENA_CLR: + s->int_ena.u32 &= ~(uint32_t)val; + break; + case CTU_CAN_FD_INT_MASK_SET: + s->int_mask.u32 |= (uint32_t)val; + break; + case CTU_CAN_FD_INT_MASK_CLR: + s->int_mask.u32 &= ~(uint32_t)val; + break; + case CTU_CAN_FD_TX_COMMAND: + if (s->mode_settings.s.ena) { + union ctu_can_fd_tx_command tx_command; + union ctu_can_fd_tx_command mask; + unsigned int buff_st; + uint32_t buff_st_mask; + + tx_command.u32 = (uint32_t)val; + mask.u32 = 0; + mask.s.txb1 = 1; + + for (i = 0; i < CTUCAN_CORE_TXBUF_NUM; i++) { + if (!(tx_command.u32 & (mask.u32 << i))) { + continue; + } + buff_st_mask = 0xf << (i * 4); + buff_st = (s->tx_status.u32 >> (i * 4)) & 0xf; + if (tx_command.s.txca) { + if (buff_st == TXT_RDY) { + buff_st = TXT_ABT; + } + } + if (tx_command.s.txcr) { + if ((buff_st == TXT_TOK) || (buff_st == TXT_ERR) || + (buff_st == TXT_ABT) || (buff_st == TXT_ETY)) + buff_st = TXT_RDY; + } + if (tx_command.s.txce) { + if ((buff_st == TXT_TOK) || (buff_st == TXT_ERR) || + (buff_st == TXT_ABT)) + buff_st = TXT_ETY; + } + s->tx_status.u32 = (s->tx_status.u32 & ~buff_st_mask) | + (buff_st << (i * 4)); + } + + ctucan_send_ready_buffers(s); + ctucan_update_txnf(s); + } + break; + case CTU_CAN_FD_TX_PRIORITY: + s->tx_priority.u32 = (uint32_t)val; + break; + } + + ctucan_update_irq(s); + } + + return; +} + +uint64_t ctucan_mem_read(CtuCanCoreState *s, hwaddr addr, unsigned size) +{ + uint32_t val = 0; + + DPRINTF("read addr 0x%02x ...\n", (unsigned int)addr); + + if (addr > CTUCAN_CORE_MEM_SIZE) { + return 0; + } + + switch (addr & ~3) { + case CTU_CAN_FD_DEVICE_ID: + { + union ctu_can_fd_device_id_version idver; + idver.u32 = 0; + idver.s.device_id = CTU_CAN_FD_ID; + idver.s.ver_major = 2; + idver.s.ver_minor = 2; + val = idver.u32; + } + break; + case CTU_CAN_FD_MODE: + val = s->mode_settings.u32; + break; + case CTU_CAN_FD_STATUS: + val = s->status.u32; + break; + case CTU_CAN_FD_INT_STAT: + val = s->int_stat.u32; + break; + case CTU_CAN_FD_INT_ENA_SET: + case CTU_CAN_FD_INT_ENA_CLR: + val = s->int_ena.u32; + break; + case CTU_CAN_FD_INT_MASK_SET: + case CTU_CAN_FD_INT_MASK_CLR: + val = s->int_mask.u32; + break; + case CTU_CAN_FD_RX_MEM_INFO: + s->rx_mem_info.u32 = 0; + s->rx_mem_info.s.rx_buff_size = CTUCAN_RCV_BUF_LEN >> 2; + s->rx_mem_info.s.rx_mem_free = (CTUCAN_RCV_BUF_LEN - + s->rx_cnt) >> 2; + val = s->rx_mem_info.u32; + break; + case CTU_CAN_FD_RX_POINTERS: + { + uint32_t rx_head_pos = s->rx_tail_pos + s->rx_cnt; + rx_head_pos %= CTUCAN_RCV_BUF_LEN; + s->rx_pointers.s.rx_wpp = rx_head_pos; + s->rx_pointers.s.rx_rpp = s->rx_tail_pos; + val = s->rx_pointers.u32; + break; + } + case CTU_CAN_FD_RX_STATUS: + case CTU_CAN_FD_RX_SETTINGS: + if (!s->rx_status_rx_settings.s.rxfrc) { + s->rx_status_rx_settings.s.rxe = 1; + } else { + s->rx_status_rx_settings.s.rxe = 0; + } + if (((s->rx_cnt + 3) & ~3) == CTUCAN_RCV_BUF_LEN) { + s->rx_status_rx_settings.s.rxf = 1; + } else { + s->rx_status_rx_settings.s.rxf = 0; + } + val = s->rx_status_rx_settings.u32; + break; + case CTU_CAN_FD_RX_DATA: + if (s->rx_cnt) { + memcpy(&val, s->rx_buff + s->rx_tail_pos, 4); + val = le32_to_cpu(val); + if (!s->rx_frame_rem) { + union ctu_can_fd_frame_form_w frame_form_w; + frame_form_w.u32 = val; + s->rx_frame_rem = frame_form_w.s.rwcnt * 4 + 4; + } + s->rx_cnt -= 4; + s->rx_frame_rem -= 4; + if (!s->rx_frame_rem) { + s->rx_status_rx_settings.s.rxfrc--; + if (!s->rx_status_rx_settings.s.rxfrc) { + s->status.s.rxne = 0; + s->status.s.idle = 1; + s->status.s.rxs = 0; + } + } + s->rx_tail_pos = (s->rx_tail_pos + 4) % CTUCAN_RCV_BUF_LEN; + } else { + val = 0; + } + break; + case CTU_CAN_FD_TX_STATUS: + val = s->tx_status.u32; + break; + case CTU_CAN_FD_TX_PRIORITY: + val = s->tx_priority.u32; + break; + case CTU_CAN_FD_RX_FR_CTR: + val = s->rx_fr_ctr.s.rx_fr_ctr_val; + break; + case CTU_CAN_FD_TX_FR_CTR: + val = s->tx_fr_ctr.s.tx_fr_ctr_val; + break; + case CTU_CAN_FD_YOLO_REG: + val = s->yolo_reg.s.yolo_val; + break; + } + + val >>= ((addr & 3) << 3); + if (size < 8) { + val &= ((uint64_t)1 << (size << 3)) - 1; + } + + return val; +} + +bool ctucan_can_receive(CanBusClientState *client) +{ + CtuCanCoreState *s = container_of(client, CtuCanCoreState, bus_client); + + if (!s->mode_settings.s.ena) { + return false; + } + + return true; /* always return true, when operation mode */ +} + +ssize_t ctucan_receive(CanBusClientState *client, const qemu_can_frame *frames, + size_t frames_cnt) +{ + CtuCanCoreState *s = container_of(client, CtuCanCoreState, bus_client); + static uint8_t rcv[CTUCAN_MSG_MAX_LEN]; + int i; + int ret = -1; + const qemu_can_frame *frame = frames; + union ctu_can_fd_int_stat int_stat; + int_stat.u32 = 0; + + if (frames_cnt <= 0) { + return 0; + } + + ret = ctucan_frame2buff(frame, rcv); + + if (s->rx_cnt + ret > CTUCAN_RCV_BUF_LEN) { /* Data overrun. */ + s->status.s.dor = 1; + int_stat.s.doi = 1; + s->int_stat.u32 |= int_stat.u32 & ~s->int_mask.u32; + ctucan_update_irq(s); + DPRINTF("Receive FIFO overrun\n"); + return ret; + } + s->status.s.idle = 0; + s->status.s.rxs = 1; + int_stat.s.rxi = 1; + if (((s->rx_cnt + 3) & ~3) == CTUCAN_RCV_BUF_LEN) { + int_stat.s.rxfi = 1; + } + s->int_stat.u32 |= int_stat.u32 & ~s->int_mask.u32; + s->rx_fr_ctr.s.rx_fr_ctr_val++; + s->rx_status_rx_settings.s.rxfrc++; + for (i = 0; i < ret; i++) { + s->rx_buff[(s->rx_tail_pos + s->rx_cnt) % CTUCAN_RCV_BUF_LEN] = rcv[i]; + s->rx_cnt++; + } + s->status.s.rxne = 1; + + ctucan_update_irq(s); + + return 1; +} + +static CanBusClientInfo ctucan_bus_client_info = { + .can_receive = ctucan_can_receive, + .receive = ctucan_receive, +}; + + +int ctucan_connect_to_bus(CtuCanCoreState *s, CanBusState *bus) +{ + s->bus_client.info = &ctucan_bus_client_info; + + if (!bus) { + return -EINVAL; + } + + if (can_bus_insert_client(bus, &s->bus_client) < 0) { + return -1; + } + + return 0; +} + +void ctucan_disconnect(CtuCanCoreState *s) +{ + can_bus_remove_client(&s->bus_client); +} + +int ctucan_init(CtuCanCoreState *s, qemu_irq irq) +{ + s->irq = irq; + + qemu_irq_lower(s->irq); + + ctucan_hardware_reset(s); + + return 0; +} + +const VMStateDescription vmstate_qemu_ctucan_tx_buffer = { + .name = "qemu_ctucan_tx_buffer", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8_ARRAY(data, CtuCanCoreMsgBuffer, CTUCAN_CORE_MSG_MAX_LEN), + VMSTATE_END_OF_LIST() + } +}; + +static int ctucan_post_load(void *opaque, int version_id) +{ + CtuCanCoreState *s = opaque; + ctucan_update_irq(s); + return 0; +} + +/* VMState is needed for live migration of QEMU images */ +const VMStateDescription vmstate_ctucan = { + .name = "ctucan", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .post_load = ctucan_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT32(mode_settings.u32, CtuCanCoreState), + VMSTATE_UINT32(status.u32, CtuCanCoreState), + VMSTATE_UINT32(int_stat.u32, CtuCanCoreState), + VMSTATE_UINT32(int_ena.u32, CtuCanCoreState), + VMSTATE_UINT32(int_mask.u32, CtuCanCoreState), + VMSTATE_UINT32(brt.u32, CtuCanCoreState), + VMSTATE_UINT32(brt_fd.u32, CtuCanCoreState), + VMSTATE_UINT32(ewl_erp_fault_state.u32, CtuCanCoreState), + VMSTATE_UINT32(rec_tec.u32, CtuCanCoreState), + VMSTATE_UINT32(err_norm_err_fd.u32, CtuCanCoreState), + VMSTATE_UINT32(ctr_pres.u32, CtuCanCoreState), + VMSTATE_UINT32(filter_a_mask.u32, CtuCanCoreState), + VMSTATE_UINT32(filter_a_val.u32, CtuCanCoreState), + VMSTATE_UINT32(filter_b_mask.u32, CtuCanCoreState), + VMSTATE_UINT32(filter_b_val.u32, CtuCanCoreState), + VMSTATE_UINT32(filter_c_mask.u32, CtuCanCoreState), + VMSTATE_UINT32(filter_c_val.u32, CtuCanCoreState), + VMSTATE_UINT32(filter_ran_low.u32, CtuCanCoreState), + VMSTATE_UINT32(filter_ran_high.u32, CtuCanCoreState), + VMSTATE_UINT32(filter_control_filter_status.u32, CtuCanCoreState), + VMSTATE_UINT32(rx_mem_info.u32, CtuCanCoreState), + VMSTATE_UINT32(rx_pointers.u32, CtuCanCoreState), + VMSTATE_UINT32(rx_status_rx_settings.u32, CtuCanCoreState), + VMSTATE_UINT32(tx_status.u32, CtuCanCoreState), + VMSTATE_UINT32(tx_priority.u32, CtuCanCoreState), + VMSTATE_UINT32(err_capt_alc.u32, CtuCanCoreState), + VMSTATE_UINT32(trv_delay_ssp_cfg.u32, CtuCanCoreState), + VMSTATE_UINT32(rx_fr_ctr.u32, CtuCanCoreState), + VMSTATE_UINT32(tx_fr_ctr.u32, CtuCanCoreState), + VMSTATE_UINT32(debug_register.u32, CtuCanCoreState), + VMSTATE_UINT32(yolo_reg.u32, CtuCanCoreState), + VMSTATE_UINT32(timestamp_low.u32, CtuCanCoreState), + VMSTATE_UINT32(timestamp_high.u32, CtuCanCoreState), + + VMSTATE_STRUCT_ARRAY(tx_buffer, CtuCanCoreState, + CTUCAN_CORE_TXBUF_NUM, 0, vmstate_qemu_ctucan_tx_buffer, + CtuCanCoreMsgBuffer), + + VMSTATE_BUFFER(rx_buff, CtuCanCoreState), + VMSTATE_UINT32(rx_tail_pos, CtuCanCoreState), + VMSTATE_UINT32(rx_cnt, CtuCanCoreState), + VMSTATE_UINT32(rx_frame_rem, CtuCanCoreState), + + VMSTATE_END_OF_LIST() + } +}; diff --git a/hw/net/can/ctucan_core.h b/hw/net/can/ctucan_core.h new file mode 100644 index 0000000000000000000000000000000000000000..bbc09ae06785ded48201beb8cead188e10da5a29 --- /dev/null +++ b/hw/net/can/ctucan_core.h @@ -0,0 +1,126 @@ +/* + * CTU CAN FD device emulation + * http://canbus.pages.fel.cvut.cz/ + * + * Copyright (c) 2019 Jan Charvat (jancharvat.charvat@gmail.com) + * + * Based on Kvaser PCI CAN device (SJA1000 based) emulation implemented by + * Jin Yang and Pavel Pisa + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef HW_CAN_CTUCAN_CORE_H +#define HW_CAN_CTUCAN_CORE_H + +#include "exec/hwaddr.h" +#include "net/can_emu.h" + +#ifndef HOST_WORDS_BIGENDIAN +#define __LITTLE_ENDIAN_BITFIELD 1 +#endif + +#include "ctu_can_fd_frame.h" +#include "ctu_can_fd_regs.h" + +#define CTUCAN_CORE_MEM_SIZE 0x500 + +/* The max size for a message in FIFO */ +#define CTUCAN_MSG_MAX_LEN (CTU_CAN_FD_DATA_1_4_W + 64) +/* The receive buffer size. */ +#define CTUCAN_RCV_BUF_LEN (1024 * 8) + + +/* The max size for a message buffer */ +#define CTUCAN_CORE_MSG_MAX_LEN 0x50 +/* The receive buffer size. */ +#define CTUCAN_CORE_RCV_BUF_LEN 0x1000 + +#define CTUCAN_CORE_TXBUF_NUM 4 + +typedef struct CtuCanCoreMsgBuffer { + uint8_t data[CTUCAN_CORE_MSG_MAX_LEN]; +} CtuCanCoreMsgBuffer; + +typedef struct CtuCanCoreState { + union ctu_can_fd_mode_settings mode_settings; + union ctu_can_fd_status status; + union ctu_can_fd_int_stat int_stat; + union ctu_can_fd_int_ena_set int_ena; + union ctu_can_fd_int_mask_set int_mask; + union ctu_can_fd_btr brt; + union ctu_can_fd_btr_fd brt_fd; + union ctu_can_fd_ewl_erp_fault_state ewl_erp_fault_state; + union ctu_can_fd_rec_tec rec_tec; + union ctu_can_fd_err_norm_err_fd err_norm_err_fd; + union ctu_can_fd_ctr_pres ctr_pres; + union ctu_can_fd_filter_a_mask filter_a_mask; + union ctu_can_fd_filter_a_val filter_a_val; + union ctu_can_fd_filter_b_mask filter_b_mask; + union ctu_can_fd_filter_b_val filter_b_val; + union ctu_can_fd_filter_c_mask filter_c_mask; + union ctu_can_fd_filter_c_val filter_c_val; + union ctu_can_fd_filter_ran_low filter_ran_low; + union ctu_can_fd_filter_ran_high filter_ran_high; + union ctu_can_fd_filter_control_filter_status filter_control_filter_status; + union ctu_can_fd_rx_mem_info rx_mem_info; + union ctu_can_fd_rx_pointers rx_pointers; + union ctu_can_fd_rx_status_rx_settings rx_status_rx_settings; + union ctu_can_fd_tx_status tx_status; + union ctu_can_fd_tx_priority tx_priority; + union ctu_can_fd_err_capt_alc err_capt_alc; + union ctu_can_fd_trv_delay_ssp_cfg trv_delay_ssp_cfg; + union ctu_can_fd_rx_fr_ctr rx_fr_ctr; + union ctu_can_fd_tx_fr_ctr tx_fr_ctr; + union ctu_can_fd_debug_register debug_register; + union ctu_can_fd_yolo_reg yolo_reg; + union ctu_can_fd_timestamp_low timestamp_low; + union ctu_can_fd_timestamp_high timestamp_high; + + CtuCanCoreMsgBuffer tx_buffer[CTUCAN_CORE_TXBUF_NUM]; + + uint8_t rx_buff[CTUCAN_RCV_BUF_LEN]; /* 32~95 .. 64bytes Rx FIFO */ + uint32_t rx_tail_pos; /* Count by bytes. */ + uint32_t rx_cnt; /* Count by bytes. */ + uint32_t rx_frame_rem; + + qemu_irq irq; + CanBusClientState bus_client; +} CtuCanCoreState; + +void ctucan_hardware_reset(CtuCanCoreState *s); + +void ctucan_mem_write(CtuCanCoreState *s, hwaddr addr, uint64_t val, + unsigned size); + +uint64_t ctucan_mem_read(CtuCanCoreState *s, hwaddr addr, unsigned size); + +int ctucan_connect_to_bus(CtuCanCoreState *s, CanBusState *bus); + +void ctucan_disconnect(CtuCanCoreState *s); + +int ctucan_init(CtuCanCoreState *s, qemu_irq irq); + +bool ctucan_can_receive(CanBusClientState *client); + +ssize_t ctucan_receive(CanBusClientState *client, + const qemu_can_frame *frames, size_t frames_cnt); + +extern const VMStateDescription vmstate_ctucan; + +#endif diff --git a/hw/net/can/ctucan_pci.c b/hw/net/can/ctucan_pci.c new file mode 100644 index 0000000000000000000000000000000000000000..f1c86cd06a785dbda5fb000574feb0f98f5d1c6d --- /dev/null +++ b/hw/net/can/ctucan_pci.c @@ -0,0 +1,281 @@ +/* + * CTU CAN FD PCI device emulation + * http://canbus.pages.fel.cvut.cz/ + * + * Copyright (c) 2019 Jan Charvat (jancharvat.charvat@gmail.com) + * + * Based on Kvaser PCI CAN device (SJA1000 based) emulation implemented by + * Jin Yang and Pavel Pisa + * + * 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 "qemu/event_notifier.h" +#include "qemu/module.h" +#include "qemu/thread.h" +#include "qemu/sockets.h" +#include "qapi/error.h" +#include "chardev/char.h" +#include "hw/irq.h" +#include "hw/pci/pci.h" +#include "hw/qdev-properties.h" +#include "migration/vmstate.h" +#include "net/can_emu.h" + +#include "ctucan_core.h" + +#define TYPE_CTUCAN_PCI_DEV "ctucan_pci" + +typedef struct CtuCanPCIState CtuCanPCIState; +DECLARE_INSTANCE_CHECKER(CtuCanPCIState, CTUCAN_PCI_DEV, + TYPE_CTUCAN_PCI_DEV) + +#define CTUCAN_PCI_CORE_COUNT 2 +#define CTUCAN_PCI_CORE_RANGE 0x10000 + +#define CTUCAN_PCI_BAR_COUNT 2 + +#define CTUCAN_PCI_BYTES_PER_CORE 0x4000 + +#ifndef PCI_VENDOR_ID_TEDIA +#define PCI_VENDOR_ID_TEDIA 0x1760 +#endif + +#define PCI_DEVICE_ID_TEDIA_CTUCAN_VER21 0xff00 + +#define CTUCAN_BAR0_RANGE 0x8000 +#define CTUCAN_BAR0_CTUCAN_ID 0x0000 +#define CTUCAN_BAR0_CRA_BASE 0x4000 +#define CYCLONE_IV_CRA_A2P_IE (0x0050) + +#define CTUCAN_WITHOUT_CTUCAN_ID 0 +#define CTUCAN_WITH_CTUCAN_ID 1 + +struct CtuCanPCIState { + /*< private >*/ + PCIDevice dev; + /*< public >*/ + MemoryRegion ctucan_io[CTUCAN_PCI_BAR_COUNT]; + + CtuCanCoreState ctucan_state[CTUCAN_PCI_CORE_COUNT]; + qemu_irq irq; + + char *model; /* The model that support, only SJA1000 now. */ + CanBusState *canbus[CTUCAN_PCI_CORE_COUNT]; +}; + +static void ctucan_pci_reset(DeviceState *dev) +{ + CtuCanPCIState *d = CTUCAN_PCI_DEV(dev); + int i; + + for (i = 0 ; i < CTUCAN_PCI_CORE_COUNT; i++) { + ctucan_hardware_reset(&d->ctucan_state[i]); + } +} + +static uint64_t ctucan_pci_id_cra_io_read(void *opaque, hwaddr addr, + unsigned size) +{ + if (addr >= 4) { + return 0; + } + + uint64_t tmp = 0xC0000000 + CTUCAN_PCI_CORE_COUNT; + tmp >>= ((addr & 3) << 3); + if (size < 8) { + tmp &= ((uint64_t)1 << (size << 3)) - 1; + } + return tmp; +} + +static void ctucan_pci_id_cra_io_write(void *opaque, hwaddr addr, uint64_t data, + unsigned size) +{ + +} + +static uint64_t ctucan_pci_cores_io_read(void *opaque, hwaddr addr, + unsigned size) +{ + CtuCanPCIState *d = opaque; + CtuCanCoreState *s; + hwaddr core_num = addr / CTUCAN_PCI_BYTES_PER_CORE; + + if (core_num >= CTUCAN_PCI_CORE_COUNT) { + return 0; + } + + s = &d->ctucan_state[core_num]; + + return ctucan_mem_read(s, addr % CTUCAN_PCI_BYTES_PER_CORE, size); +} + +static void ctucan_pci_cores_io_write(void *opaque, hwaddr addr, uint64_t data, + unsigned size) +{ + CtuCanPCIState *d = opaque; + CtuCanCoreState *s; + hwaddr core_num = addr / CTUCAN_PCI_BYTES_PER_CORE; + + if (core_num >= CTUCAN_PCI_CORE_COUNT) { + return; + } + + s = &d->ctucan_state[core_num]; + + return ctucan_mem_write(s, addr % CTUCAN_PCI_BYTES_PER_CORE, data, size); +} + +static const MemoryRegionOps ctucan_pci_id_cra_io_ops = { + .read = ctucan_pci_id_cra_io_read, + .write = ctucan_pci_id_cra_io_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 1, + .impl.max_access_size = 4, + .valid.min_access_size = 1, + .valid.max_access_size = 4, +}; + +static const MemoryRegionOps ctucan_pci_cores_io_ops = { + .read = ctucan_pci_cores_io_read, + .write = ctucan_pci_cores_io_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 1, + .impl.max_access_size = 4, + .valid.min_access_size = 1, + .valid.max_access_size = 4, +}; + +static void ctucan_pci_realize(PCIDevice *pci_dev, Error **errp) +{ + CtuCanPCIState *d = CTUCAN_PCI_DEV(pci_dev); + uint8_t *pci_conf; + int i; + + pci_conf = pci_dev->config; + pci_conf[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */ + + d->irq = pci_allocate_irq(&d->dev); + + for (i = 0 ; i < CTUCAN_PCI_CORE_COUNT; i++) { + ctucan_init(&d->ctucan_state[i], d->irq); + } + + for (i = 0 ; i < CTUCAN_PCI_CORE_COUNT; i++) { + if (ctucan_connect_to_bus(&d->ctucan_state[i], d->canbus[i]) < 0) { + error_setg(errp, "ctucan_connect_to_bus failed"); + return; + } + } + + memory_region_init_io(&d->ctucan_io[0], OBJECT(d), + &ctucan_pci_id_cra_io_ops, d, + "ctucan_pci-core0", CTUCAN_BAR0_RANGE); + memory_region_init_io(&d->ctucan_io[1], OBJECT(d), + &ctucan_pci_cores_io_ops, d, + "ctucan_pci-core1", CTUCAN_PCI_CORE_RANGE); + + for (i = 0 ; i < CTUCAN_PCI_BAR_COUNT; i++) { + pci_register_bar(&d->dev, i, PCI_BASE_ADDRESS_MEM_MASK & 0, + &d->ctucan_io[i]); + } +} + +static void ctucan_pci_exit(PCIDevice *pci_dev) +{ + CtuCanPCIState *d = CTUCAN_PCI_DEV(pci_dev); + int i; + + for (i = 0 ; i < CTUCAN_PCI_CORE_COUNT; i++) { + ctucan_disconnect(&d->ctucan_state[i]); + } + + qemu_free_irq(d->irq); +} + +static const VMStateDescription vmstate_ctucan_pci = { + .name = "ctucan_pci", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_PCI_DEVICE(dev, CtuCanPCIState), + VMSTATE_STRUCT(ctucan_state[0], CtuCanPCIState, 0, vmstate_ctucan, + CtuCanCoreState), +#if CTUCAN_PCI_CORE_COUNT >= 2 + VMSTATE_STRUCT(ctucan_state[1], CtuCanPCIState, 0, vmstate_ctucan, + CtuCanCoreState), +#endif + VMSTATE_END_OF_LIST() + } +}; + +static void ctucan_pci_instance_init(Object *obj) +{ + CtuCanPCIState *d = CTUCAN_PCI_DEV(obj); + + object_property_add_link(obj, "canbus0", TYPE_CAN_BUS, + (Object **)&d->canbus[0], + qdev_prop_allow_set_link_before_realize, 0); +#if CTUCAN_PCI_CORE_COUNT >= 2 + object_property_add_link(obj, "canbus1", TYPE_CAN_BUS, + (Object **)&d->canbus[1], + qdev_prop_allow_set_link_before_realize, 0); +#endif +} + +static void ctucan_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->realize = ctucan_pci_realize; + k->exit = ctucan_pci_exit; + k->vendor_id = PCI_VENDOR_ID_TEDIA; + k->device_id = PCI_DEVICE_ID_TEDIA_CTUCAN_VER21; + k->revision = 0x00; + k->class_id = 0x000c09; + k->subsystem_vendor_id = PCI_VENDOR_ID_TEDIA; + k->subsystem_id = PCI_DEVICE_ID_TEDIA_CTUCAN_VER21; + dc->desc = "CTU CAN PCI"; + dc->vmsd = &vmstate_ctucan_pci; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + dc->reset = ctucan_pci_reset; +} + +static const TypeInfo ctucan_pci_info = { + .name = TYPE_CTUCAN_PCI_DEV, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(CtuCanPCIState), + .class_init = ctucan_pci_class_init, + .instance_init = ctucan_pci_instance_init, + .interfaces = (InterfaceInfo[]) { + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { }, + }, +}; + +static void ctucan_pci_register_types(void) +{ + type_register_static(&ctucan_pci_info); +} + +type_init(ctucan_pci_register_types) diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..714951f375a547304ff136bbfee448dc38aeedac --- /dev/null +++ b/hw/net/can/meson.build @@ -0,0 +1,6 @@ +softmmu_ss.add(when: 'CONFIG_CAN_SJA1000', if_true: files('can_sja1000.c')) +softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_kvaser_pci.c')) +softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_pcm3680_pci.c')) +softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_mioe3680_pci.c')) +softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD', if_true: files('ctucan_core.c')) +softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD_PCI', if_true: files('ctucan_pci.c')) diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index c54db0d62dd23113a8e8a21f5f1a0baa34a1cd94..205c0decc535724de568023e9f2349f29911e625 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -27,6 +27,7 @@ #include "qemu/module.h" #include "qemu/timer.h" #include +#include "qom/object.h" //#define DEBUG_SONIC @@ -150,9 +151,9 @@ do { printf("sonic ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0) #define SONIC_DESC_ADDR 0xFFFE #define TYPE_DP8393X "dp8393x" -#define DP8393X(obj) OBJECT_CHECK(dp8393xState, (obj), TYPE_DP8393X) +OBJECT_DECLARE_SIMPLE_TYPE(dp8393xState, DP8393X) -typedef struct dp8393xState { +struct dp8393xState { SysBusDevice parent_obj; /* Hardware */ @@ -182,7 +183,7 @@ typedef struct dp8393xState { /* Memory access */ MemoryRegion *dma_mr; AddressSpace as; -} dp8393xState; +}; /* Accessor functions for values which are formed by * concatenating two 16 bit device registers. By putting these @@ -494,6 +495,10 @@ static void dp8393x_do_transmit_packets(dp8393xState *s) } else { /* Remove existing FCS */ tx_len -= 4; + if (tx_len < 0) { + SONIC_ERROR("tx_len is %d\n", tx_len); + break; + } } if (s->regs[SONIC_RCR] & (SONIC_RCR_LB1 | SONIC_RCR_LB0)) { diff --git a/hw/net/e1000.c b/hw/net/e1000.c index a18f80e3695328d872b6acd3095bef5c3aaddef0..d7d05ae30afafb2e7979c74564a64ef5a0f513fe 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -13,7 +13,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -39,6 +39,7 @@ #include "e1000x_common.h" #include "trace.h" +#include "qom/object.h" static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; @@ -76,7 +77,7 @@ static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL); * Others never tested */ -typedef struct E1000State_st { +struct E1000State_st { /*< private >*/ PCIDevice parent_obj; /*< public >*/ @@ -137,24 +138,22 @@ typedef struct E1000State_st { bool received_tx_tso; bool use_tso_for_migration; e1000x_txd_props mig_props; -} E1000State; +}; +typedef struct E1000State_st E1000State; #define chkflag(x) (s->compat_flags & E1000_FLAG_##x) -typedef struct E1000BaseClass { +struct E1000BaseClass { PCIDeviceClass parent_class; uint16_t phy_id2; -} E1000BaseClass; +}; +typedef struct E1000BaseClass E1000BaseClass; #define TYPE_E1000_BASE "e1000-base" -#define E1000(obj) \ - OBJECT_CHECK(E1000State, (obj), TYPE_E1000_BASE) +DECLARE_OBJ_CHECKERS(E1000State, E1000BaseClass, + E1000, TYPE_E1000_BASE) -#define E1000_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(E1000BaseClass, (klass), TYPE_E1000_BASE) -#define E1000_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(E1000BaseClass, (obj), TYPE_E1000_BASE) static void e1000_link_up(E1000State *s) @@ -365,7 +364,7 @@ e1000_autoneg_timer(void *opaque) static void e1000_reset(void *opaque) { E1000State *d = opaque; - E1000BaseClass *edc = E1000_DEVICE_GET_CLASS(d); + E1000BaseClass *edc = E1000_GET_CLASS(d); uint8_t *macaddr = d->conf.macaddr.a; timer_del(d->autoneg_timer); @@ -1751,7 +1750,7 @@ static void e1000_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - E1000BaseClass *e = E1000_DEVICE_CLASS(klass); + E1000BaseClass *e = E1000_CLASS(klass); const E1000Info *info = data; k->realize = pci_e1000_realize; diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c index fda34518c9dc9d0974ab37bac62be0b3225aa96e..a8a77eca9565d4db935d64666d9fd9ed28f0f2cc 100644 --- a/hw/net/e1000e.c +++ b/hw/net/e1000e.c @@ -22,7 +22,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either -* version 2 of the License, or (at your option) any later version. +* version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -53,11 +53,12 @@ #include "trace.h" #include "qapi/error.h" +#include "qom/object.h" #define TYPE_E1000E "e1000e" -#define E1000E(obj) OBJECT_CHECK(E1000EState, (obj), TYPE_E1000E) +OBJECT_DECLARE_SIMPLE_TYPE(E1000EState, E1000E) -typedef struct E1000EState { +struct E1000EState { PCIDevice parent_obj; NICState *nic; NICConf conf; @@ -79,7 +80,7 @@ typedef struct E1000EState { E1000ECore core; -} E1000EState; +}; #define E1000E_MMIO_IDX 0 #define E1000E_FLASH_IDX 1 diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c index d5676871fabc53d850903d4b7d6865c8872728e4..095c01ebc6034db2c5d676b87d2d313c4e9dc9d0 100644 --- a/hw/net/e1000e_core.c +++ b/hw/net/e1000e_core.c @@ -22,7 +22,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either -* version 2 of the License, or (at your option) any later version. +* version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -34,9 +34,9 @@ */ #include "qemu/osdep.h" +#include "qemu/log.h" #include "net/net.h" #include "net/tap.h" -#include "hw/hw.h" #include "hw/pci/msi.h" #include "hw/pci/msix.h" #include "sysemu/runstate.h" @@ -1596,13 +1596,13 @@ e1000e_write_packet_to_guest(E1000ECore *core, struct NetRxPkt *pkt, (const char *) &fcs_pad, e1000x_fcs_len(core->mac)); } } - desc_offset += desc_size; - if (desc_offset >= total_size) { - is_last = true; - } } else { /* as per intel docs; skip descriptors with null buf addr */ trace_e1000e_rx_null_descriptor(); } + desc_offset += desc_size; + if (desc_offset >= total_size) { + is_last = true; + } e1000e_write_rx_descr(core, desc, is_last ? core->rx_pkt : NULL, rss_info, do_ps ? ps_hdr_len : 0, &bastate.written); @@ -2816,11 +2816,15 @@ e1000e_set_psrctl(E1000ECore *core, int index, uint32_t val) if (core->mac[RCTL] & E1000_RCTL_DTYP_MASK) { if ((val & E1000_PSRCTL_BSIZE0_MASK) == 0) { - hw_error("e1000e: PSRCTL.BSIZE0 cannot be zero"); + qemu_log_mask(LOG_GUEST_ERROR, + "e1000e: PSRCTL.BSIZE0 cannot be zero"); + return; } if ((val & E1000_PSRCTL_BSIZE1_MASK) == 0) { - hw_error("e1000e: PSRCTL.BSIZE1 cannot be zero"); + qemu_log_mask(LOG_GUEST_ERROR, + "e1000e: PSRCTL.BSIZE1 cannot be zero"); + return; } } @@ -2912,7 +2916,6 @@ static const readops e1000e_macreg_readops[] = { e1000e_getreg(TSYNCRXCTL), e1000e_getreg(TDH), e1000e_getreg(LEDCTL), - e1000e_getreg(STATUS), e1000e_getreg(TCTL), e1000e_getreg(TDBAL), e1000e_getreg(TDLEN), @@ -3138,7 +3141,6 @@ static const writeops e1000e_macreg_writeops[] = { e1000e_putreg(RXCFGL), e1000e_putreg(TSYNCRXCTL), e1000e_putreg(TSYNCTXCTL), - e1000e_putreg(FLSWDATA), e1000e_putreg(EXTCNF_SIZE), e1000e_putreg(EEMNGCTL), e1000e_putreg(RA), diff --git a/hw/net/e1000e_core.h b/hw/net/e1000e_core.h index aee32f7e483d0c43af94991a66e09e2777c1fab2..4ddb4d2c39fac913d7a55f16000c0956c6a677fa 100644 --- a/hw/net/e1000e_core.h +++ b/hw/net/e1000e_core.h @@ -22,7 +22,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either -* version 2 of the License, or (at your option) any later version. +* version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/net/e1000x_common.c b/hw/net/e1000x_common.c index 717f9df1c9330850d719108a22f89b1b336564b0..a8d93870b5a082695fc047699f60a13285dd684d 100644 --- a/hw/net/e1000x_common.c +++ b/hw/net/e1000x_common.c @@ -11,7 +11,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either -* version 2 of the License, or (at your option) any later version. +* version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/net/e1000x_common.h b/hw/net/e1000x_common.h index 19c56f409f7918c213e1661cf54ce2f569649465..b7742775c477cc774156de9ea30889135f788df4 100644 --- a/hw/net/e1000x_common.h +++ b/hw/net/e1000x_common.h @@ -11,7 +11,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either -* version 2 of the License, or (at your option) any later version. +* version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c index 27fd069b96434bfcb31001cdce86c6d19d89b14d..1b82aec7943d26b7850acf39f50eec3104bb78e1 100644 --- a/hw/net/etraxfs_eth.c +++ b/hw/net/etraxfs_eth.c @@ -30,6 +30,7 @@ #include "qemu/error-report.h" #include "qemu/module.h" #include "trace.h" +#include "qom/object.h" #define D(x) @@ -323,11 +324,9 @@ static void mdio_cycle(struct qemu_mdio *bus) #define FS_ETH_MAX_REGS 0x17 #define TYPE_ETRAX_FS_ETH "etraxfs-eth" -#define ETRAX_FS_ETH(obj) \ - OBJECT_CHECK(ETRAXFSEthState, (obj), TYPE_ETRAX_FS_ETH) +OBJECT_DECLARE_SIMPLE_TYPE(ETRAXFSEthState, ETRAX_FS_ETH) -typedef struct ETRAXFSEthState -{ +struct ETRAXFSEthState { SysBusDevice parent_obj; MemoryRegion mmio; @@ -348,7 +347,7 @@ typedef struct ETRAXFSEthState /* PHY. */ struct qemu_phy phy; -} ETRAXFSEthState; +}; static void eth_validate_duplex(ETRAXFSEthState *eth) { @@ -654,7 +653,7 @@ etraxfs_eth_init(NICInfo *nd, hwaddr base, int phyaddr, DeviceState *dev; qemu_check_nic_model(nd, "fseth"); - dev = qdev_create(NULL, "etraxfs-eth"); + dev = qdev_new("etraxfs-eth"); qdev_set_nic_properties(dev, nd); qdev_prop_set_uint32(dev, "phyaddr", phyaddr); @@ -668,7 +667,7 @@ etraxfs_eth_init(NICInfo *nd, hwaddr base, int phyaddr, */ ETRAX_FS_ETH(dev)->dma_out = dma_out; ETRAX_FS_ETH(dev)->dma_in = dma_in; - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); return dev; diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c index 475f3c887a2e823c0b57d93599c3bdc2e865bbd0..93886bba60fcd63a16e597779ac11a1927d8b074 100644 --- a/hw/net/fsl_etsec/etsec.c +++ b/hw/net/fsl_etsec/etsec.c @@ -33,6 +33,7 @@ #include "hw/qdev-properties.h" #include "etsec.h" #include "registers.h" +#include "qapi/error.h" #include "qemu/log.h" #include "qemu/module.h" @@ -356,7 +357,7 @@ static ssize_t etsec_receive(NetClientState *nc, #if defined(HEX_DUMP) fprintf(stderr, "%s receive size:%zd\n", nc->name, size); - qemu_hexdump((void *)buf, stderr, "", size); + qemu_hexdump(stderr, "", buf, size); #endif /* Flush is unnecessary as are already in receiving path */ etsec->need_flush = false; @@ -429,7 +430,7 @@ static void etsec_class_init(ObjectClass *klass, void *data) } static TypeInfo etsec_info = { - .name = "eTSEC", + .name = TYPE_ETSEC_COMMON, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(eTSEC), .class_init = etsec_class_init, @@ -452,9 +453,9 @@ DeviceState *etsec_create(hwaddr base, { DeviceState *dev; - dev = qdev_create(NULL, "eTSEC"); + dev = qdev_new("eTSEC"); qdev_set_nic_properties(dev, nd); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, tx_irq); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, rx_irq); diff --git a/hw/net/fsl_etsec/etsec.h b/hw/net/fsl_etsec/etsec.h index 7951c3ad65fd8f833ef3069ba994aafb637926ca..fddf551544aa1b5a88667b0c4239a1d6a3850527 100644 --- a/hw/net/fsl_etsec/etsec.h +++ b/hw/net/fsl_etsec/etsec.h @@ -28,6 +28,7 @@ #include "hw/sysbus.h" #include "net/net.h" #include "hw/ptimer.h" +#include "qom/object.h" /* Buffer Descriptors */ @@ -104,7 +105,7 @@ typedef struct eTSEC_Register { uint32_t value; } eTSEC_Register; -typedef struct eTSEC { +struct eTSEC { SysBusDevice busdev; MemoryRegion io_area; @@ -145,11 +146,11 @@ typedef struct eTSEC { /* Whether we should flush the rx queue when buffer becomes available. */ bool need_flush; -} eTSEC; +}; +typedef struct eTSEC eTSEC; #define TYPE_ETSEC_COMMON "eTSEC" -#define ETSEC_COMMON(obj) \ - OBJECT_CHECK(eTSEC, (obj), TYPE_ETSEC_COMMON) +OBJECT_DECLARE_SIMPLE_TYPE(eTSEC, ETSEC_COMMON) #define eTSEC_TRANSMIT 1 #define eTSEC_RECEIVE 2 diff --git a/hw/net/fsl_etsec/rings.c b/hw/net/fsl_etsec/rings.c index 337a55fc957c55194dac9a2a254d187da0922b7e..628648a9c37f59a295fe7442032e76f79447f89e 100644 --- a/hw/net/fsl_etsec/rings.c +++ b/hw/net/fsl_etsec/rings.c @@ -269,7 +269,7 @@ static void process_tx_bd(eTSEC *etsec, #if defined(HEX_DUMP) qemu_log("eTSEC Send packet size:%d\n", etsec->tx_buffer_len); - qemu_hexdump(etsec->tx_buffer, stderr, "", etsec->tx_buffer_len); + qemu_hexdump(stderr, "", etsec->tx_buffer, etsec->tx_buffer_len); #endif /* ETSEC_RING_DEBUG */ if (etsec->first_bd.flags & BD_TX_TOEUN) { diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c index 25ebee7ec2babe09c7e55aef203f51fb585540f0..782ff192cedc876944bae65f44f1f071f3602841 100644 --- a/hw/net/ftgmac100.c +++ b/hw/net/ftgmac100.c @@ -79,6 +79,16 @@ #define FTGMAC100_APTC_TXPOLL_CNT(x) (((x) >> 8) & 0xf) #define FTGMAC100_APTC_TXPOLL_TIME_SEL (1 << 12) +/* + * DMA burst length and arbitration control register + */ +#define FTGMAC100_DBLAC_RXBURST_SIZE(x) (((x) >> 8) & 0x3) +#define FTGMAC100_DBLAC_TXBURST_SIZE(x) (((x) >> 10) & 0x3) +#define FTGMAC100_DBLAC_RXDES_SIZE(x) ((((x) >> 12) & 0xf) * 8) +#define FTGMAC100_DBLAC_TXDES_SIZE(x) ((((x) >> 16) & 0xf) * 8) +#define FTGMAC100_DBLAC_IFG_CNT(x) (((x) >> 20) & 0x7) +#define FTGMAC100_DBLAC_IFG_INC (1 << 23) + /* * PHY control register */ @@ -471,6 +481,37 @@ static int ftgmac100_write_bd(FTGMAC100Desc *bd, dma_addr_t addr) return 0; } +static int ftgmac100_insert_vlan(FTGMAC100State *s, int frame_size, + uint8_t vlan_tci) +{ + uint8_t *vlan_hdr = s->frame + (ETH_ALEN * 2); + uint8_t *payload = vlan_hdr + sizeof(struct vlan_header); + + if (frame_size < sizeof(struct eth_header)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: frame too small for VLAN insertion : %d bytes\n", + __func__, frame_size); + s->isr |= FTGMAC100_INT_XPKT_LOST; + goto out; + } + + if (frame_size + sizeof(struct vlan_header) > sizeof(s->frame)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: frame too big : %d bytes\n", + __func__, frame_size); + s->isr |= FTGMAC100_INT_XPKT_LOST; + frame_size -= sizeof(struct vlan_header); + } + + memmove(payload, vlan_hdr, frame_size - (ETH_ALEN * 2)); + stw_be_p(vlan_hdr, ETH_P_VLAN); + stw_be_p(vlan_hdr + 2, vlan_tci); + frame_size += sizeof(struct vlan_header); + +out: + return frame_size; +} + static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring, uint32_t tx_descriptor) { @@ -497,6 +538,15 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring, } len = FTGMAC100_TXDES0_TXBUF_SIZE(bd.des0); + if (!len) { + /* + * 0 is an invalid size, however the HW does not raise any + * interrupt. Flag an error because the guest is buggy. + */ + qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid segment size\n", + __func__); + } + if (frame_size + len > sizeof(s->frame)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %d bytes\n", __func__, len); @@ -507,29 +557,21 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring, if (dma_memory_read(&address_space_memory, bd.des3, ptr, len)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to read packet @ 0x%x\n", __func__, bd.des3); - s->isr |= FTGMAC100_INT_NO_NPTXBUF; + s->isr |= FTGMAC100_INT_AHB_ERR; break; } - /* Check for VLAN */ - if (bd.des0 & FTGMAC100_TXDES0_FTS && - bd.des1 & FTGMAC100_TXDES1_INS_VLANTAG && - be16_to_cpu(PKT_GET_ETH_HDR(ptr)->h_proto) != ETH_P_VLAN) { - if (frame_size + len + 4 > sizeof(s->frame)) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %d bytes\n", - __func__, len); - s->isr |= FTGMAC100_INT_XPKT_LOST; - len = sizeof(s->frame) - frame_size - 4; - } - memmove(ptr + 16, ptr + 12, len - 12); - stw_be_p(ptr + 12, ETH_P_VLAN); - stw_be_p(ptr + 14, bd.des1); - len += 4; - } - ptr += len; frame_size += len; if (bd.des0 & FTGMAC100_TXDES0_LTS) { + + /* Check for VLAN */ + if (flags & FTGMAC100_TXDES1_INS_VLANTAG && + be16_to_cpu(PKT_GET_ETH_HDR(s->frame)->h_proto) != ETH_P_VLAN) { + frame_size = ftgmac100_insert_vlan(s, frame_size, + FTGMAC100_TXDES1_VLANTAG_CI(flags)); + } + if (flags & FTGMAC100_TXDES1_IP_CHKSUM) { net_checksum_calculate(s->frame, frame_size); } @@ -537,9 +579,7 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring, qemu_send_packet(qemu_get_queue(s->nic), s->frame, frame_size); ptr = s->frame; frame_size = 0; - if (flags & FTGMAC100_TXDES1_TXIC) { - s->isr |= FTGMAC100_INT_XPKT_ETH; - } + s->isr |= FTGMAC100_INT_XPKT_ETH; } if (flags & FTGMAC100_TXDES1_TX2FIC) { @@ -553,7 +593,7 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring, if (bd.des0 & s->txdes0_edotr) { addr = tx_ring; } else { - addr += sizeof(FTGMAC100Desc); + addr += FTGMAC100_DBLAC_TXDES_SIZE(s->dblac); } } @@ -609,10 +649,8 @@ static uint32_t ftgmac100_rxpoll(FTGMAC100State *s) return cnt / div[speed]; } -static void ftgmac100_reset(DeviceState *d) +static void ftgmac100_do_reset(FTGMAC100State *s, bool sw_reset) { - FTGMAC100State *s = FTGMAC100(d); - /* Reset the FTGMAC100 */ s->isr = 0; s->ier = 0; @@ -631,7 +669,12 @@ static void ftgmac100_reset(DeviceState *d) s->fear1 = 0; s->tpafcr = 0xf1; - s->maccr = 0; + if (sw_reset) { + s->maccr &= FTGMAC100_MACCR_GIGA_MODE | FTGMAC100_MACCR_FAST_MODE; + } else { + s->maccr = 0; + } + s->phycr = 0; s->phydata = 0; s->fcr = 0x400; @@ -640,6 +683,11 @@ static void ftgmac100_reset(DeviceState *d) phy_reset(s); } +static void ftgmac100_reset(DeviceState *d) +{ + ftgmac100_do_reset(FTGMAC100(d), false); +} + static uint64_t ftgmac100_read(void *opaque, hwaddr addr, unsigned size) { FTGMAC100State *s = FTGMAC100(opaque); @@ -659,6 +707,10 @@ static uint64_t ftgmac100_read(void *opaque, hwaddr addr, unsigned size) return s->math[0]; case FTGMAC100_MATH1: return s->math[1]; + case FTGMAC100_RXR_BADR: + return s->rx_ring; + case FTGMAC100_NPTXR_BADR: + return s->tx_ring; case FTGMAC100_ITC: return s->itc; case FTGMAC100_DBLAC: @@ -780,7 +832,7 @@ static void ftgmac100_write(void *opaque, hwaddr addr, case FTGMAC100_MACCR: /* MAC Device control */ s->maccr = value; if (value & FTGMAC100_MACCR_SW_RST) { - ftgmac100_reset(DEVICE(s)); + ftgmac100_do_reset(s, true); } if (ftgmac100_can_receive(qemu_get_queue(s->nic))) { @@ -800,6 +852,20 @@ static void ftgmac100_write(void *opaque, hwaddr addr, s->phydata = value & 0xffff; break; case FTGMAC100_DBLAC: /* DMA Burst Length and Arbitration Control */ + if (FTGMAC100_DBLAC_TXDES_SIZE(value) < sizeof(FTGMAC100Desc)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: transmit descriptor too small: %" PRIx64 + " bytes\n", __func__, + FTGMAC100_DBLAC_TXDES_SIZE(value)); + break; + } + if (FTGMAC100_DBLAC_RXDES_SIZE(value) < sizeof(FTGMAC100Desc)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: receive descriptor too small : %" PRIx64 + " bytes\n", __func__, + FTGMAC100_DBLAC_RXDES_SIZE(value)); + break; + } s->dblac = value; break; case FTGMAC100_REVR: /* Feature Register */ @@ -924,6 +990,7 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf, break; } + s->isr |= FTGMAC100_INT_RPKT_FIFO; addr = s->rx_descriptor; while (size > 0) { if (!ftgmac100_can_receive(nc)) { @@ -975,14 +1042,12 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf, /* Last buffer in frame. */ bd.des0 |= flags | FTGMAC100_RXDES0_LRS; s->isr |= FTGMAC100_INT_RPKT_BUF; - } else { - s->isr |= FTGMAC100_INT_RPKT_FIFO; } ftgmac100_write_bd(&bd, addr); if (bd.des0 & s->rxdes0_edorr) { addr = s->rx_ring; } else { - addr += sizeof(FTGMAC100Desc); + addr += FTGMAC100_DBLAC_RXDES_SIZE(s->dblac); } } s->rx_descriptor = addr; diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c index 7adcc9df6541e8d9a7b634cf08011e54500ae6a1..2c1480404140f525e05b008231cba236ea677864 100644 --- a/hw/net/imx_fec.c +++ b/hw/net/imx_fec.c @@ -31,34 +31,11 @@ #include "qemu/module.h" #include "net/checksum.h" #include "net/eth.h" +#include "trace.h" /* For crc32 */ #include -#ifndef DEBUG_IMX_FEC -#define DEBUG_IMX_FEC 0 -#endif - -#define FEC_PRINTF(fmt, args...) \ - do { \ - if (DEBUG_IMX_FEC) { \ - fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_FEC, \ - __func__, ##args); \ - } \ - } while (0) - -#ifndef DEBUG_IMX_PHY -#define DEBUG_IMX_PHY 0 -#endif - -#define PHY_PRINTF(fmt, args...) \ - do { \ - if (DEBUG_IMX_PHY) { \ - fprintf(stderr, "[%s.phy]%s: " fmt , TYPE_IMX_FEC, \ - __func__, ##args); \ - } \ - } while (0) - #define IMX_MAX_DESC 1024 static const char *imx_default_reg_name(IMXFECState *s, uint32_t index) @@ -262,51 +239,57 @@ static void imx_eth_update(IMXFECState *s); * For now we don't handle any GPIO/interrupt line, so the OS will * have to poll for the PHY status. */ -static void phy_update_irq(IMXFECState *s) +static void imx_phy_update_irq(IMXFECState *s) { imx_eth_update(s); } -static void phy_update_link(IMXFECState *s) +static void imx_phy_update_link(IMXFECState *s) { /* Autonegotiation status mirrors link status. */ if (qemu_get_queue(s->nic)->link_down) { - PHY_PRINTF("link is down\n"); + trace_imx_phy_update_link("down"); s->phy_status &= ~0x0024; s->phy_int |= PHY_INT_DOWN; } else { - PHY_PRINTF("link is up\n"); + trace_imx_phy_update_link("up"); s->phy_status |= 0x0024; s->phy_int |= PHY_INT_ENERGYON; s->phy_int |= PHY_INT_AUTONEG_COMPLETE; } - phy_update_irq(s); + imx_phy_update_irq(s); } static void imx_eth_set_link(NetClientState *nc) { - phy_update_link(IMX_FEC(qemu_get_nic_opaque(nc))); + imx_phy_update_link(IMX_FEC(qemu_get_nic_opaque(nc))); } -static void phy_reset(IMXFECState *s) +static void imx_phy_reset(IMXFECState *s) { + trace_imx_phy_reset(); + s->phy_status = 0x7809; s->phy_control = 0x3000; s->phy_advertise = 0x01e1; s->phy_int_mask = 0; s->phy_int = 0; - phy_update_link(s); + imx_phy_update_link(s); } -static uint32_t do_phy_read(IMXFECState *s, int reg) +static uint32_t imx_phy_read(IMXFECState *s, int reg) { uint32_t val; + uint32_t phy = reg / 32; - if (reg > 31) { - /* we only advertise one phy */ + if (phy != s->phy_num) { + qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad phy num %u\n", + TYPE_IMX_FEC, __func__, phy); return 0; } + reg %= 32; + switch (reg) { case 0: /* Basic Control */ val = s->phy_control; @@ -332,7 +315,7 @@ static uint32_t do_phy_read(IMXFECState *s, int reg) case 29: /* Interrupt source. */ val = s->phy_int; s->phy_int = 0; - phy_update_irq(s); + imx_phy_update_irq(s); break; case 30: /* Interrupt mask */ val = s->phy_int_mask; @@ -352,24 +335,29 @@ static uint32_t do_phy_read(IMXFECState *s, int reg) break; } - PHY_PRINTF("read 0x%04x @ %d\n", val, reg); + trace_imx_phy_read(val, phy, reg); return val; } -static void do_phy_write(IMXFECState *s, int reg, uint32_t val) +static void imx_phy_write(IMXFECState *s, int reg, uint32_t val) { - PHY_PRINTF("write 0x%04x @ %d\n", val, reg); + uint32_t phy = reg / 32; - if (reg > 31) { - /* we only advertise one phy */ + if (phy != s->phy_num) { + qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad phy num %u\n", + TYPE_IMX_FEC, __func__, phy); return; } + reg %= 32; + + trace_imx_phy_write(val, phy, reg); + switch (reg) { case 0: /* Basic Control */ if (val & 0x8000) { - phy_reset(s); + imx_phy_reset(s); } else { s->phy_control = val & 0x7980; /* Complete autonegotiation immediately. */ @@ -383,7 +371,7 @@ static void do_phy_write(IMXFECState *s, int reg, uint32_t val) break; case 30: /* Interrupt mask */ s->phy_int_mask = val & 0xff; - phy_update_irq(s); + imx_phy_update_irq(s); break; case 17: case 18: @@ -402,6 +390,8 @@ static void do_phy_write(IMXFECState *s, int reg, uint32_t val) static void imx_fec_read_bd(IMXFECBufDesc *bd, dma_addr_t addr) { dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd)); + + trace_imx_fec_read_bd(addr, bd->flags, bd->length, bd->data); } static void imx_fec_write_bd(IMXFECBufDesc *bd, dma_addr_t addr) @@ -412,6 +402,9 @@ static void imx_fec_write_bd(IMXFECBufDesc *bd, dma_addr_t addr) static void imx_enet_read_bd(IMXENETBufDesc *bd, dma_addr_t addr) { dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd)); + + trace_imx_enet_read_bd(addr, bd->flags, bd->length, bd->data, + bd->option, bd->status); } static void imx_enet_write_bd(IMXENETBufDesc *bd, dma_addr_t addr) @@ -471,11 +464,11 @@ static void imx_fec_do_tx(IMXFECState *s) int len; imx_fec_read_bd(&bd, addr); - FEC_PRINTF("tx_bd %x flags %04x len %d data %08x\n", - addr, bd.flags, bd.length, bd.data); if ((bd.flags & ENET_BD_R) == 0) { + /* Run out of descriptors to transmit. */ - FEC_PRINTF("tx_bd ran out of descriptors to transmit\n"); + trace_imx_eth_tx_bd_busy(); + break; } len = bd.length; @@ -552,11 +545,11 @@ static void imx_enet_do_tx(IMXFECState *s, uint32_t index) int len; imx_enet_read_bd(&bd, addr); - FEC_PRINTF("tx_bd %x flags %04x len %d data %08x option %04x " - "status %04x\n", addr, bd.flags, bd.length, bd.data, - bd.option, bd.status); if ((bd.flags & ENET_BD_R) == 0) { /* Run out of descriptors to transmit. */ + + trace_imx_eth_tx_bd_busy(); + break; } len = bd.length; @@ -633,7 +626,7 @@ static void imx_eth_enable_rx(IMXFECState *s, bool flush) s->regs[ENET_RDAR] = (bd.flags & ENET_BD_E) ? ENET_RDAR_RDAR : 0; if (!s->regs[ENET_RDAR]) { - FEC_PRINTF("RX buffer full\n"); + trace_imx_eth_rx_bd_full(); } else if (flush) { qemu_flush_queued_packets(qemu_get_queue(s->nic)); } @@ -676,7 +669,7 @@ static void imx_eth_reset(DeviceState *d) memset(s->tx_descriptor, 0, sizeof(s->tx_descriptor)); /* We also reset the PHY */ - phy_reset(s); + imx_phy_reset(s); } static uint32_t imx_default_read(IMXFECState *s, uint32_t index) @@ -774,8 +767,7 @@ static uint64_t imx_eth_read(void *opaque, hwaddr offset, unsigned size) break; } - FEC_PRINTF("reg[%s] => 0x%" PRIx32 "\n", imx_eth_reg_name(s, index), - value); + trace_imx_eth_read(index, imx_eth_reg_name(s, index), value); return value; } @@ -884,8 +876,7 @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value, const bool single_tx_ring = !imx_eth_is_multi_tx_ring(s); uint32_t index = offset >> 2; - FEC_PRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx_eth_reg_name(s, index), - (uint32_t)value); + trace_imx_eth_write(index, imx_eth_reg_name(s, index), value); switch (index) { case ENET_EIR: @@ -940,12 +931,12 @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value, if (extract32(value, 29, 1)) { /* This is a read operation */ s->regs[ENET_MMFR] = deposit32(s->regs[ENET_MMFR], 0, 16, - do_phy_read(s, + imx_phy_read(s, extract32(value, 18, 10))); } else { - /* This a write operation */ - do_phy_write(s, extract32(value, 18, 10), extract32(value, 0, 16)); + /* This is a write operation */ + imx_phy_write(s, extract32(value, 18, 10), extract32(value, 0, 16)); } /* raise the interrupt as the PHY operation is done */ s->regs[ENET_EIR] |= ENET_INT_MII; @@ -1053,8 +1044,6 @@ static bool imx_eth_can_receive(NetClientState *nc) { IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc)); - FEC_PRINTF("\n"); - return !!s->regs[ENET_RDAR]; } @@ -1071,7 +1060,7 @@ static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf, unsigned int buf_len; size_t size = len; - FEC_PRINTF("len %d\n", (int)size); + trace_imx_fec_receive(size); if (!s->regs[ENET_RDAR]) { qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Unexpected packet\n", @@ -1113,7 +1102,7 @@ static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf, bd.length = buf_len; size -= buf_len; - FEC_PRINTF("rx_bd 0x%x length %d\n", addr, bd.length); + trace_imx_fec_receive_len(addr, bd.length); /* The last 4 bytes are the CRC. */ if (size < 4) { @@ -1131,7 +1120,9 @@ static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf, if (size == 0) { /* Last buffer in frame. */ bd.flags |= flags | ENET_BD_L; - FEC_PRINTF("rx frame flags %04x\n", bd.flags); + + trace_imx_fec_receive_last(bd.flags); + s->regs[ENET_EIR] |= ENET_INT_RXF; } else { s->regs[ENET_EIR] |= ENET_INT_RXB; @@ -1164,7 +1155,7 @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf, size_t size = len; bool shift16 = s->regs[ENET_RACC] & ENET_RACC_SHIFT16; - FEC_PRINTF("len %d\n", (int)size); + trace_imx_enet_receive(size); if (!s->regs[ENET_RDAR]) { qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Unexpected packet\n", @@ -1210,7 +1201,7 @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf, bd.length = buf_len; size -= buf_len; - FEC_PRINTF("rx_bd 0x%x length %d\n", addr, bd.length); + trace_imx_enet_receive_len(addr, bd.length); /* The last 4 bytes are the CRC. */ if (size < 4) { @@ -1246,7 +1237,9 @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf, if (size == 0) { /* Last buffer in frame. */ bd.flags |= flags | ENET_BD_L; - FEC_PRINTF("rx frame flags %04x\n", bd.flags); + + trace_imx_enet_receive_last(bd.flags); + /* Indicate that we've updated the last buffer descriptor. */ bd.last_buffer = ENET_BD_BDU; if (bd.option & ENET_BD_RX_INT) { @@ -1331,6 +1324,7 @@ static void imx_eth_realize(DeviceState *dev, Error **errp) static Property imx_eth_properties[] = { DEFINE_NIC_PROPERTIES(IMXFECState, conf), DEFINE_PROP_UINT32("tx-ring-num", IMXFECState, tx_ring_num, 1), + DEFINE_PROP_UINT32("phy-num", IMXFECState, phy_num, 0), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c index da7e0bb0e8b6803323c012a12a935f2e8b2d3126..ab57c02c8e10d3ea1feb258fa4c53cb3c24558b2 100644 --- a/hw/net/lan9118.c +++ b/hw/net/lan9118.c @@ -20,10 +20,12 @@ #include "hw/net/lan9118.h" #include "hw/ptimer.h" #include "hw/qdev-properties.h" +#include "qapi/error.h" #include "qemu/log.h" #include "qemu/module.h" /* For crc32 */ #include +#include "qom/object.h" //#define DEBUG_LAN9118 @@ -179,9 +181,9 @@ static const VMStateDescription vmstate_lan9118_packet = { } }; -#define LAN9118(obj) OBJECT_CHECK(lan9118_state, (obj), TYPE_LAN9118) +OBJECT_DECLARE_SIMPLE_TYPE(lan9118_state, LAN9118) -typedef struct { +struct lan9118_state { SysBusDevice parent_obj; NICState *nic; @@ -257,7 +259,7 @@ typedef struct { uint32_t read_long; uint32_t mode_16bit; -} lan9118_state; +}; static const VMStateDescription vmstate_lan9118 = { .name = "lan9118", @@ -930,10 +932,8 @@ static uint32_t do_mac_read(lan9118_state *s, int reg) | (s->conf.macaddr.a[2] << 16) | (s->conf.macaddr.a[3] << 24); case MAC_HASHH: return s->mac_hashh; - break; case MAC_HASHL: return s->mac_hashl; - break; case MAC_MII_ACC: return s->mac_mii_acc; case MAC_MII_DATA: @@ -1394,10 +1394,10 @@ void lan9118_init(NICInfo *nd, uint32_t base, qemu_irq irq) SysBusDevice *s; qemu_check_nic_model(nd, "lan9118"); - dev = qdev_create(NULL, TYPE_LAN9118); + dev = qdev_new(TYPE_LAN9118); qdev_set_nic_properties(dev, nd); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, base); sysbus_connect_irq(s, 0, irq); } diff --git a/hw/net/lasi_i82596.c b/hw/net/lasi_i82596.c index 5e0fd69763bad914fac9d6513a07ff7ac1bfaf59..820b63f35098624a9779a17cf4941fd0175b67df 100644 --- a/hw/net/lasi_i82596.c +++ b/hw/net/lasi_i82596.c @@ -11,6 +11,7 @@ */ #include "qemu/osdep.h" +#include "qapi/error.h" #include "qemu/timer.h" #include "hw/sysbus.h" #include "net/eth.h" @@ -126,11 +127,11 @@ SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space, .a = { 0x08, 0x00, 0x09, 0xef, 0x34, 0xf6 } }; qemu_check_nic_model(&nd_table[0], TYPE_LASI_82596); - dev = qdev_create(NULL, TYPE_LASI_82596); + dev = qdev_new(TYPE_LASI_82596); s = SYSBUS_I82596(dev); s->state.irq = lan_irq; qdev_set_nic_properties(dev, &nd_table[0]); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); s->state.conf.macaddr = HP_MAC; /* set HP MAC prefix */ /* LASI 82596 ports in main memory. */ diff --git a/hw/net/mcf_fec.c b/hw/net/mcf_fec.c index 9327ac8a304a59f81e554a3af04aeada12d04ef8..25e3e453ab12dff8912ca57a7865cbd37fa94b5e 100644 --- a/hw/net/mcf_fec.c +++ b/hw/net/mcf_fec.c @@ -7,7 +7,7 @@ */ #include "qemu/osdep.h" -#include "hw/hw.h" +#include "qemu/log.h" #include "hw/irq.h" #include "net/net.h" #include "qemu/module.h" @@ -32,7 +32,7 @@ do { printf("mcf_fec: " fmt , ## __VA_ARGS__); } while (0) #define FEC_MAX_FRAME_SIZE 2032 #define FEC_MIB_SIZE 64 -typedef struct { +struct mcf_fec_state { SysBusDevice parent_obj; MemoryRegion iomem; @@ -56,7 +56,7 @@ typedef struct { uint32_t etdsr; uint32_t emrbr; uint32_t mib[FEC_MIB_SIZE]; -} mcf_fec_state; +}; #define FEC_INT_HB 0x80000000 #define FEC_INT_BABR 0x40000000 @@ -392,7 +392,8 @@ static uint64_t mcf_fec_read(void *opaque, hwaddr addr, case 0x188: return s->emrbr; case 0x200 ... 0x2e0: return s->mib[(addr & 0x1ff) / 4]; default: - hw_error("mcf_fec_read: Bad address 0x%x\n", (int)addr); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%" HWADDR_PRIX "\n", + __func__, addr); return 0; } } @@ -492,7 +493,9 @@ static void mcf_fec_write(void *opaque, hwaddr addr, s->mib[(addr & 0x1ff) / 4] = value; break; default: - hw_error("mcf_fec_write Bad address 0x%x\n", (int)addr); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%" HWADDR_PRIX "\n", + __func__, addr); + return; } mcf_fec_update(s); } diff --git a/hw/net/meson.build b/hw/net/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..4a7051b54a08b7ea347a6059d3bdd8a5cc7cc35d --- /dev/null +++ b/hw/net/meson.build @@ -0,0 +1,67 @@ +softmmu_ss.add(when: 'CONFIG_DP8393X', if_true: files('dp8393x.c')) +softmmu_ss.add(when: 'CONFIG_XEN', if_true: files('xen_nic.c')) +softmmu_ss.add(when: 'CONFIG_NE2000_COMMON', if_true: files('ne2000.c')) + +# PCI network cards +softmmu_ss.add(when: 'CONFIG_NE2000_PCI', if_true: files('ne2000-pci.c')) +softmmu_ss.add(when: 'CONFIG_EEPRO100_PCI', if_true: files('eepro100.c')) +softmmu_ss.add(when: 'CONFIG_PCNET_PCI', if_true: files('pcnet-pci.c')) +softmmu_ss.add(when: 'CONFIG_PCNET_COMMON', if_true: files('pcnet.c')) +softmmu_ss.add(when: 'CONFIG_E1000_PCI', if_true: files('e1000.c', 'e1000x_common.c')) +softmmu_ss.add(when: 'CONFIG_E1000E_PCI_EXPRESS', if_true: files('net_tx_pkt.c', 'net_rx_pkt.c')) +softmmu_ss.add(when: 'CONFIG_E1000E_PCI_EXPRESS', if_true: files('e1000e.c', 'e1000e_core.c', 'e1000x_common.c')) +softmmu_ss.add(when: 'CONFIG_RTL8139_PCI', if_true: files('rtl8139.c')) +softmmu_ss.add(when: 'CONFIG_TULIP', if_true: files('tulip.c')) +softmmu_ss.add(when: 'CONFIG_VMXNET3_PCI', if_true: files('net_tx_pkt.c', 'net_rx_pkt.c')) +softmmu_ss.add(when: 'CONFIG_VMXNET3_PCI', if_true: files('vmxnet3.c')) + +softmmu_ss.add(when: 'CONFIG_SMC91C111', if_true: files('smc91c111.c')) +softmmu_ss.add(when: 'CONFIG_LAN9118', if_true: files('lan9118.c')) +softmmu_ss.add(when: 'CONFIG_NE2000_ISA', if_true: files('ne2000-isa.c')) +softmmu_ss.add(when: 'CONFIG_OPENCORES_ETH', if_true: files('opencores_eth.c')) +softmmu_ss.add(when: 'CONFIG_XGMAC', if_true: files('xgmac.c')) +softmmu_ss.add(when: 'CONFIG_MIPSNET', if_true: files('mipsnet.c')) +softmmu_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('xilinx_axienet.c')) +softmmu_ss.add(when: 'CONFIG_ALLWINNER_EMAC', if_true: files('allwinner_emac.c')) +softmmu_ss.add(when: 'CONFIG_ALLWINNER_SUN8I_EMAC', if_true: files('allwinner-sun8i-emac.c')) +softmmu_ss.add(when: 'CONFIG_IMX_FEC', if_true: files('imx_fec.c')) +softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-emac.c')) + +softmmu_ss.add(when: 'CONFIG_CADENCE', if_true: files('cadence_gem.c')) +softmmu_ss.add(when: 'CONFIG_STELLARIS_ENET', if_true: files('stellaris_enet.c')) +softmmu_ss.add(when: 'CONFIG_LANCE', if_true: files('lance.c')) +softmmu_ss.add(when: 'CONFIG_LASI_I82596', if_true: files('lasi_i82596.c')) +softmmu_ss.add(when: 'CONFIG_I82596_COMMON', if_true: files('i82596.c')) +softmmu_ss.add(when: 'CONFIG_SUNHME', if_true: files('sunhme.c')) +softmmu_ss.add(when: 'CONFIG_FTGMAC100', if_true: files('ftgmac100.c')) +softmmu_ss.add(when: 'CONFIG_SUNGEM', if_true: files('sungem.c')) + +softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_eth.c')) +softmmu_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_fec.c')) +specific_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-minimac2.c')) +specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_llan.c')) +specific_ss.add(when: 'CONFIG_XILINX_ETHLITE', if_true: files('xilinx_ethlite.c')) + +softmmu_ss.add(when: 'CONFIG_VIRTIO_NET', if_true: files('net_rx_pkt.c')) +specific_ss.add(when: 'CONFIG_VIRTIO_NET', if_true: files('virtio-net.c')) + +softmmu_ss.add(when: ['CONFIG_VIRTIO_NET', 'CONFIG_VHOST_NET'], if_true: files('vhost_net.c'), if_false: files('vhost_net-stub.c')) +softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('vhost_net-stub.c')) + +softmmu_ss.add(when: 'CONFIG_ETSEC', if_true: files( + 'fsl_etsec/etsec.c', + 'fsl_etsec/miim.c', + 'fsl_etsec/registers.c', + 'fsl_etsec/rings.c', +)) + +softmmu_ss.add(when: 'CONFIG_ROCKER', if_true: files( + 'rocker/rocker.c', + 'rocker/rocker_desc.c', + 'rocker/rocker_fp.c', + 'rocker/rocker_of_dpa.c', + 'rocker/rocker_world.c', +), if_false: files('rocker/qmp-norocker.c')) +softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('rocker/qmp-norocker.c')) + +subdir('can') diff --git a/hw/net/milkymist-minimac2.c b/hw/net/milkymist-minimac2.c index 1ba01754eeb686b61707b6dfeb4f7b0177b7d50d..5826944fd57df2c0fb3fb7d7691caa7b9da240d6 100644 --- a/hw/net/milkymist-minimac2.c +++ b/hw/net/milkymist-minimac2.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" +#include "qom/object.h" #include "cpu.h" /* FIXME: why does this use TARGET_PAGE_ALIGN? */ #include "hw/irq.h" #include "hw/qdev-properties.h" @@ -98,8 +99,7 @@ struct MilkymistMinimac2MdioState { typedef struct MilkymistMinimac2MdioState MilkymistMinimac2MdioState; #define TYPE_MILKYMIST_MINIMAC2 "milkymist-minimac2" -#define MILKYMIST_MINIMAC2(obj) \ - OBJECT_CHECK(MilkymistMinimac2State, (obj), TYPE_MILKYMIST_MINIMAC2) +OBJECT_DECLARE_SIMPLE_TYPE(MilkymistMinimac2State, MILKYMIST_MINIMAC2) struct MilkymistMinimac2State { SysBusDevice parent_obj; @@ -123,7 +123,6 @@ struct MilkymistMinimac2State { uint8_t *rx1_buf; uint8_t *tx_buf; }; -typedef struct MilkymistMinimac2State MilkymistMinimac2State; static const uint8_t preamble_sfd[] = { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5 diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c index 0c578c430c83a9c2bd366a11400278f43715735d..2ade72dea081f5895056591587bd0e9e3ed06729 100644 --- a/hw/net/mipsnet.c +++ b/hw/net/mipsnet.c @@ -6,6 +6,7 @@ #include "trace.h" #include "hw/sysbus.h" #include "migration/vmstate.h" +#include "qom/object.h" /* MIPSnet register offsets */ @@ -24,9 +25,9 @@ #define MAX_ETH_FRAME_SIZE 1514 #define TYPE_MIPS_NET "mipsnet" -#define MIPS_NET(obj) OBJECT_CHECK(MIPSnetState, (obj), TYPE_MIPS_NET) +OBJECT_DECLARE_SIMPLE_TYPE(MIPSnetState, MIPS_NET) -typedef struct MIPSnetState { +struct MIPSnetState { SysBusDevice parent_obj; uint32_t busy; @@ -41,7 +42,7 @@ typedef struct MIPSnetState { qemu_irq irq; NICState *nic; NICConf conf; -} MIPSnetState; +}; static void mipsnet_reset(MIPSnetState *s) { diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c index fdf8faa0d9a69263c4c48048eea05e0b59c4bfc4..dd6f6e34d3cfb262b7dfd8e28056000c7077927e 100644 --- a/hw/net/ne2000-isa.c +++ b/hw/net/ne2000-isa.c @@ -31,16 +31,17 @@ #include "qapi/error.h" #include "qapi/visitor.h" #include "qemu/module.h" +#include "qom/object.h" -#define ISA_NE2000(obj) OBJECT_CHECK(ISANE2000State, (obj), TYPE_ISA_NE2000) +OBJECT_DECLARE_SIMPLE_TYPE(ISANE2000State, ISA_NE2000) -typedef struct ISANE2000State { +struct ISANE2000State { ISADevice parent_obj; uint32_t iobase; uint32_t isairq; NE2000State ne2000; -} ISANE2000State; +}; static NetClientInfo net_ne2000_isa_info = { .type = NET_CLIENT_DRIVER_NIC, @@ -113,9 +114,8 @@ static void isa_ne2000_set_bootindex(Object *obj, Visitor *v, int32_t boot_index; Error *local_err = NULL; - visit_type_int32(v, name, &boot_index, &local_err); - if (local_err) { - goto out; + if (!visit_type_int32(v, name, &boot_index, errp)) { + return; } /* check whether bootindex is present in fw_boot_order list */ check_boot_index(boot_index, &local_err); @@ -134,7 +134,7 @@ static void isa_ne2000_instance_init(Object *obj) object_property_add(obj, "bootindex", "int32", isa_ne2000_get_bootindex, isa_ne2000_set_bootindex, NULL, NULL); - object_property_set_int(obj, -1, "bootindex", NULL); + object_property_set_int(obj, "bootindex", -1, NULL); } static const TypeInfo ne2000_isa_info = { .name = TYPE_ISA_NE2000, diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c index 162f802dd77e09b89c0cb65583e82ddfcc1d3487..da262edc3e95e71f2aa8a52026f9951452b6ec61 100644 --- a/hw/net/net_tx_pkt.c +++ b/hw/net/net_tx_pkt.c @@ -379,7 +379,10 @@ bool net_tx_pkt_add_raw_fragment(struct NetTxPkt *pkt, hwaddr pa, hwaddr mapped_len = 0; struct iovec *ventry; assert(pkt); - assert(pkt->max_raw_frags > pkt->raw_frags); + + if (pkt->raw_frags >= pkt->max_raw_frags) { + return false; + } if (!len) { return true; @@ -468,8 +471,8 @@ static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt) /* num of iovec without vhdr */ uint32_t iov_len = pkt->payload_frags + NET_TX_PKT_PL_START_FRAG - 1; uint16_t csl; - struct ip_header *iphdr; size_t csum_offset = pkt->virt_hdr.csum_start + pkt->virt_hdr.csum_offset; + uint16_t l3_proto = eth_get_l3_proto(iov, 1, iov->iov_len); /* Put zero to checksum field */ iov_from_buf(iov, iov_len, csum_offset, &csum, sizeof csum); @@ -477,9 +480,18 @@ static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt) /* Calculate L4 TCP/UDP checksum */ csl = pkt->payload_len; + csum_cntr = 0; + cso = 0; /* add pseudo header to csum */ - iphdr = pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_base; - csum_cntr = eth_calc_ip4_pseudo_hdr_csum(iphdr, csl, &cso); + if (l3_proto == ETH_P_IP) { + csum_cntr = eth_calc_ip4_pseudo_hdr_csum( + pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_base, + csl, &cso); + } else if (l3_proto == ETH_P_IPV6) { + csum_cntr = eth_calc_ip6_pseudo_hdr_csum( + pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_base, + csl, pkt->l4proto, &cso); + } /* data checksum */ csum_cntr += @@ -617,6 +629,7 @@ bool net_tx_pkt_send(struct NetTxPkt *pkt, NetClientState *nc) if (pkt->has_virt_hdr || pkt->virt_hdr.gso_type == VIRTIO_NET_HDR_GSO_NONE) { + net_tx_pkt_fix_ip6_payload_len(pkt); net_tx_pkt_sendv(pkt, nc, pkt->vec, pkt->payload_frags + NET_TX_PKT_PL_START_FRAG); return true; @@ -635,3 +648,25 @@ bool net_tx_pkt_send_loopback(struct NetTxPkt *pkt, NetClientState *nc) return res; } + +void net_tx_pkt_fix_ip6_payload_len(struct NetTxPkt *pkt) +{ + struct iovec *l2 = &pkt->vec[NET_TX_PKT_L2HDR_FRAG]; + if (eth_get_l3_proto(l2, 1, l2->iov_len) == ETH_P_IPV6) { + struct ip6_header *ip6 = (struct ip6_header *) pkt->l3_hdr; + /* + * TODO: if qemu would support >64K packets - add jumbo option check + * something like that: + * 'if (ip6->ip6_plen == 0 && !has_jumbo_option(ip6)) {' + */ + if (ip6->ip6_plen == 0) { + if (pkt->payload_len <= ETH_MAX_IP_DGRAM_LEN) { + ip6->ip6_plen = htons(pkt->payload_len); + } + /* + * TODO: if qemu would support >64K packets + * add jumbo option for packets greater then 65,535 bytes + */ + } + } +} diff --git a/hw/net/net_tx_pkt.h b/hw/net/net_tx_pkt.h index 212ecc62fc465a02c8ea59975b96734dbf648497..4ec8bbe9bd93eaa17a87c401b439d5a94e909ee8 100644 --- a/hw/net/net_tx_pkt.h +++ b/hw/net/net_tx_pkt.h @@ -187,4 +187,18 @@ bool net_tx_pkt_parse(struct NetTxPkt *pkt); */ bool net_tx_pkt_has_fragments(struct NetTxPkt *pkt); +/** + * Fix IPv6 'plen' field. + * If ipv6 payload length field is 0 - then there should be Hop-by-Hop + * option for packets greater than 65,535. + * For packets with a payload less than 65,535: fix 'plen' field. + * For backends with vheader, we need just one packet with proper + * payload size. For now, qemu drops every packet with size greater 64K + * (see net_tx_pkt_send()) so, there is no reason to add jumbo option to ip6 + * hop-by-hop extension if it's missed + * + * @pkt packet + */ +void net_tx_pkt_fix_ip6_payload_len(struct NetTxPkt *pkt); + #endif diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c index 2ba0dc8c2fb9c1850c15adb042ed4e62183eac3f..0b3dc3146e61f73056ff29ce8964f77cba0950a1 100644 --- a/hw/net/opencores_eth.c +++ b/hw/net/opencores_eth.c @@ -40,6 +40,7 @@ #include "qemu/module.h" #include "net/eth.h" #include "trace.h" +#include "qom/object.h" /* RECSMALL is not used because it breaks tap networking in linux: * incoming ARP responses are too short @@ -271,9 +272,9 @@ typedef struct desc { #define DEFAULT_PHY 1 #define TYPE_OPEN_ETH "open_eth" -#define OPEN_ETH(obj) OBJECT_CHECK(OpenEthState, (obj), TYPE_OPEN_ETH) +OBJECT_DECLARE_SIMPLE_TYPE(OpenEthState, OPEN_ETH) -typedef struct OpenEthState { +struct OpenEthState { SysBusDevice parent_obj; NICState *nic; @@ -287,7 +288,7 @@ typedef struct OpenEthState { unsigned tx_desc; unsigned rx_desc; desc desc[128]; -} OpenEthState; +}; static desc *rx_desc(OpenEthState *s) { diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c index 49d3e42e83d6b1037695727b0500552a1247fc89..ccc3fce2a00e20e7c44b1f045df7ee0ea7290f00 100644 --- a/hw/net/pcnet-pci.c +++ b/hw/net/pcnet-pci.c @@ -40,6 +40,7 @@ #include "trace.h" #include "pcnet.h" +#include "qom/object.h" //#define PCNET_DEBUG //#define PCNET_DEBUG_IO @@ -51,17 +52,16 @@ #define TYPE_PCI_PCNET "pcnet" -#define PCI_PCNET(obj) \ - OBJECT_CHECK(PCIPCNetState, (obj), TYPE_PCI_PCNET) +OBJECT_DECLARE_SIMPLE_TYPE(PCIPCNetState, PCI_PCNET) -typedef struct { +struct PCIPCNetState { /*< private >*/ PCIDevice parent_obj; /*< public >*/ PCNetState state; MemoryRegion io_bar; -} PCIPCNetState; +}; static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val) { diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c index 15d66f6cbcf0dcb6d155e0ae6ab76fba6a54d495..1af1e6fa2f9ba84fd486c57d2c0d9174779a0b5c 100644 --- a/hw/net/rocker/rocker.c +++ b/hw/net/rocker/rocker.c @@ -73,11 +73,6 @@ struct rocker { QLIST_ENTRY(rocker) next; }; -#define TYPE_ROCKER "rocker" - -#define ROCKER(obj) \ - OBJECT_CHECK(Rocker, (obj), TYPE_ROCKER) - static QLIST_HEAD(, rocker) rockers; Rocker *rocker_find(const char *name) diff --git a/hw/net/rocker/rocker.h b/hw/net/rocker/rocker.h index 7ae0495d9ec7521c5e7140f117b7f9bd7e6d96e1..941c9322658cc22c5681a663303b8963cbe045bf 100644 --- a/hw/net/rocker/rocker.h +++ b/hw/net/rocker/rocker.h @@ -20,6 +20,7 @@ #define ROCKER_H #include "qemu/sockets.h" +#include "qom/object.h" #if defined(DEBUG_ROCKER) # define DPRINTF(fmt, ...) \ @@ -66,11 +67,15 @@ static inline bool ipv6_addr_is_multicast(const Ipv6Addr *addr) return (addr->addr32[0] & htonl(0xFF000000)) == htonl(0xFF000000); } -typedef struct rocker Rocker; typedef struct world World; typedef struct desc_info DescInfo; typedef struct desc_ring DescRing; +#define TYPE_ROCKER "rocker" +typedef struct rocker Rocker; +DECLARE_INSTANCE_CHECKER(Rocker, ROCKER, + TYPE_ROCKER) + Rocker *rocker_find(const char *name); uint32_t rocker_fp_ports(Rocker *r); int rocker_event_link_changed(Rocker *r, uint32_t pport, bool link_up); diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index ab93d78ab3c2492c99bed55ff4a0efd2329cc86f..ba5ace1ab75cc91330f8f60b25c04c556da926d2 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -62,6 +62,7 @@ #include "net/net.h" #include "net/eth.h" #include "sysemu/sysemu.h" +#include "qom/object.h" /* debug RTL8139 card */ //#define DEBUG_RTL8139 1 @@ -93,8 +94,7 @@ static inline GCC_FMT_ATTR(1, 2) int DPRINTF(const char *fmt, ...) #define TYPE_RTL8139 "rtl8139" -#define RTL8139(obj) \ - OBJECT_CHECK(RTL8139State, (obj), TYPE_RTL8139) +OBJECT_DECLARE_SIMPLE_TYPE(RTL8139State, RTL8139) /* Symbolic offsets to registers. */ enum RTL8139_registers { @@ -431,7 +431,7 @@ typedef struct RTL8139TallyCounters /* Clears all tally counters */ static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters); -typedef struct RTL8139State { +struct RTL8139State { /*< private >*/ PCIDevice parent_obj; /*< public >*/ @@ -513,7 +513,7 @@ typedef struct RTL8139State { /* Support migration to/from old versions */ int rtl8139_mmio_io_addr_dummy; -} RTL8139State; +}; /* Writes tally counters to memory via DMA */ static void RTL8139TallyCounters_dma_write(RTL8139State *s, dma_addr_t tc_addr); diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c index b3240b9335596ec8e462b95033b0bd41856163e0..ad778cd8fc791ff5990744c063ce895c2d758050 100644 --- a/hw/net/smc91c111.c +++ b/hw/net/smc91c111.c @@ -14,18 +14,20 @@ #include "hw/irq.h" #include "hw/net/smc91c111.h" #include "hw/qdev-properties.h" +#include "qapi/error.h" #include "qemu/log.h" #include "qemu/module.h" /* For crc32 */ #include +#include "qom/object.h" /* Number of 2k memory pages available. */ #define NUM_PACKETS 4 #define TYPE_SMC91C111 "smc91c111" -#define SMC91C111(obj) OBJECT_CHECK(smc91c111_state, (obj), TYPE_SMC91C111) +OBJECT_DECLARE_SIMPLE_TYPE(smc91c111_state, SMC91C111) -typedef struct { +struct smc91c111_state { SysBusDevice parent_obj; NICState *nic; @@ -54,7 +56,7 @@ typedef struct { uint8_t int_level; uint8_t int_mask; MemoryRegion mmio; -} smc91c111_state; +}; static const VMStateDescription vmstate_smc91c111 = { .name = "smc91c111", @@ -821,10 +823,10 @@ void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq) SysBusDevice *s; qemu_check_nic_model(nd, "smc91c111"); - dev = qdev_create(NULL, TYPE_SMC91C111); + dev = qdev_new(TYPE_SMC91C111); qdev_set_nic_properties(dev, nd); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, base); sysbus_connect_irq(s, 0, irq); } diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c index 968a1ce78e8ab100636b5ccce1b1a40ae0222d58..581320a0e7dd6fd71259c399f3f2af7cc5ab57ed 100644 --- a/hw/net/spapr_llan.c +++ b/hw/net/spapr_llan.c @@ -38,6 +38,7 @@ #include "trace.h" #include +#include "qom/object.h" #define ETH_ALEN 6 #define MAX_PACKET_SIZE 65536 @@ -84,8 +85,7 @@ typedef uint64_t vlan_bd_t; #define VLAN_MAX_BUFS (VLAN_RX_BDS_LEN / 8) #define TYPE_VIO_SPAPR_VLAN_DEVICE "spapr-vlan" -#define VIO_SPAPR_VLAN_DEVICE(obj) \ - OBJECT_CHECK(SpaprVioVlan, (obj), TYPE_VIO_SPAPR_VLAN_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(SpaprVioVlan, VIO_SPAPR_VLAN_DEVICE) #define RX_POOL_MAX_BDS 4096 #define RX_MAX_POOLS 5 @@ -96,7 +96,7 @@ typedef struct { vlan_bd_t bds[RX_POOL_MAX_BDS]; } RxBufPool; -typedef struct SpaprVioVlan { +struct SpaprVioVlan { SpaprVioDevice sdev; NICConf nicconf; NICState *nic; @@ -108,7 +108,7 @@ typedef struct SpaprVioVlan { QEMUTimer *rxp_timer; uint32_t compat_flags; /* Compatibility flags for migration */ RxBufPool *rx_pool[RX_MAX_POOLS]; /* Receive buffer descriptor pools */ -} SpaprVioVlan; +}; static bool spapr_vlan_can_receive(NetClientState *nc) { @@ -372,11 +372,11 @@ void spapr_vlan_create(SpaprVioBus *bus, NICInfo *nd) { DeviceState *dev; - dev = qdev_create(&bus->bus, "spapr-vlan"); + dev = qdev_new("spapr-vlan"); qdev_set_nic_properties(dev, nd); - qdev_init_nofail(dev); + qdev_realize_and_unref(dev, &bus->bus, &error_fatal); } static int spapr_vlan_devnode(SpaprVioDevice *dev, void *fdt, int node_off) @@ -688,7 +688,8 @@ static target_ulong h_send_logical_lan(PowerPCCPU *cpu, SpaprVioDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg); SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(sdev); unsigned total_len; - uint8_t *lbuf, *p; + uint8_t *p; + g_autofree uint8_t *lbuf = NULL; int i, nbufs; int ret; @@ -729,7 +730,7 @@ static target_ulong h_send_logical_lan(PowerPCCPU *cpu, return H_RESOURCE; } - lbuf = alloca(total_len); + lbuf = g_malloc(total_len); p = lbuf; for (i = 0; i < nbufs; i++) { ret = spapr_vio_dma_read(sdev, VLAN_BD_ADDR(bufs[i]), diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c index cb6e2509ea47ab8bb67fe24bdbfa421d5482e45b..8dd60783d81ddcada047227034a8ffc6972ae9cf 100644 --- a/hw/net/stellaris_enet.c +++ b/hw/net/stellaris_enet.c @@ -16,6 +16,7 @@ #include "qemu/log.h" #include "qemu/module.h" #include +#include "qom/object.h" //#define DEBUG_STELLARIS_ENET 1 @@ -50,15 +51,14 @@ do { fprintf(stderr, "stellaris_enet: error: " fmt , ## __VA_ARGS__);} while (0) #define SE_TCTL_DUPLEX 0x08 #define TYPE_STELLARIS_ENET "stellaris_enet" -#define STELLARIS_ENET(obj) \ - OBJECT_CHECK(stellaris_enet_state, (obj), TYPE_STELLARIS_ENET) +OBJECT_DECLARE_SIMPLE_TYPE(stellaris_enet_state, STELLARIS_ENET) typedef struct { uint8_t data[2048]; uint32_t len; } StellarisEnetRxFrame; -typedef struct { +struct stellaris_enet_state { SysBusDevice parent_obj; uint32_t ris; @@ -82,7 +82,7 @@ typedef struct { NICConf conf; qemu_irq irq; MemoryRegion mmio; -} stellaris_enet_state; +}; static const VMStateDescription vmstate_rx_frame = { .name = "stellaris_enet/rx_frame", diff --git a/hw/net/sungem.c b/hw/net/sungem.c index e4b7b577046f1710bc827e4a304ea44217a236de..33c3722df6f7c052b1632115e602fcb208541eab 100644 --- a/hw/net/sungem.c +++ b/hw/net/sungem.c @@ -19,10 +19,11 @@ #include "hw/net/mii.h" #include "sysemu/sysemu.h" #include "trace.h" +#include "qom/object.h" #define TYPE_SUNGEM "sungem" -#define SUNGEM(obj) OBJECT_CHECK(SunGEMState, (obj), TYPE_SUNGEM) +OBJECT_DECLARE_SIMPLE_TYPE(SunGEMState, SUNGEM) #define MAX_PACKET_SIZE 9016 @@ -192,7 +193,7 @@ struct gem_rxd { #define RXDCTRL_ALTMAC 0x2000000000000000ULL /* Matched ALT MAC */ -typedef struct { +struct SunGEMState { PCIDevice pdev; MemoryRegion sungem; @@ -221,7 +222,7 @@ typedef struct { uint8_t tx_data[MAX_PACKET_SIZE]; uint32_t tx_size; uint64_t tx_first_ctl; -} SunGEMState; +}; static void sungem_eval_irq(SunGEMState *s) diff --git a/hw/net/sunhme.c b/hw/net/sunhme.c index bc48d46b9f58b83584c010461e0cd2783a70bf49..fc34905f87590b4e5f516e8ba45c3275b127f588 100644 --- a/hw/net/sunhme.c +++ b/hw/net/sunhme.c @@ -33,6 +33,7 @@ #include "net/eth.h" #include "sysemu/sysemu.h" #include "trace.h" +#include "qom/object.h" #define HME_REG_SIZE 0x8000 @@ -129,7 +130,7 @@ #define MII_COMMAND_WRITE 0x1 #define TYPE_SUNHME "sunhme" -#define SUNHME(obj) OBJECT_CHECK(SunHMEState, (obj), TYPE_SUNHME) +OBJECT_DECLARE_SIMPLE_TYPE(SunHMEState, SUNHME) /* Maximum size of buffer */ #define HME_FIFO_SIZE 0x800 @@ -153,7 +154,7 @@ #define HME_MII_REGS_SIZE 0x20 -typedef struct SunHMEState { +struct SunHMEState { /*< private >*/ PCIDevice parent_obj; @@ -174,7 +175,7 @@ typedef struct SunHMEState { uint32_t mifregs[HME_MIF_REG_SIZE >> 2]; uint16_t miiregs[HME_MII_REGS_SIZE]; -} SunHMEState; +}; static Property sunhme_properties[] = { DEFINE_NIC_PROPERTIES(SunHMEState, conf), diff --git a/hw/net/trace-events b/hw/net/trace-events index e18f883cfd439c57b9db762490dbad53cedf0918..5db45456d922e6d8f423b7cc0ae86a5f2f9c2987 100644 --- a/hw/net/trace-events +++ b/hw/net/trace-events @@ -381,6 +381,9 @@ virtio_net_announce_notify(void) "" virtio_net_announce_timer(int round) "%d" virtio_net_handle_announce(int round) "%d" virtio_net_post_load_device(void) +virtio_net_rss_disable(void) +virtio_net_rss_error(const char *msg, uint32_t value) "%s, value 0x%08x" +virtio_net_rss_enable(uint32_t p1, uint16_t p2, uint8_t p3) "hashes 0x%x, table of %d, key of %d" # tulip.c tulip_reg_write(uint64_t addr, const char *name, int size, uint64_t val) "addr 0x%02"PRIx64" (%s) size %d value 0x%08"PRIx64 @@ -408,3 +411,21 @@ i82596_receive_packet(size_t sz) "len=%zu" i82596_new_mac(const char *id_with_mac) "New MAC for: %s" i82596_set_multicast(uint16_t count) "Added %d multicast entries" i82596_channel_attention(void *s) "%p: Received CHANNEL ATTENTION" + +# imx_fec.c +imx_phy_read(uint32_t val, int phy, int reg) "0x%04"PRIx32" <= phy[%d].reg[%d]" +imx_phy_write(uint32_t val, int phy, int reg) "0x%04"PRIx32" => phy[%d].reg[%d]" +imx_phy_update_link(const char *s) "%s" +imx_phy_reset(void) "" +imx_fec_read_bd(uint64_t addr, int flags, int len, int data) "tx_bd 0x%"PRIx64" flags 0x%04x len %d data 0x%08x" +imx_enet_read_bd(uint64_t addr, int flags, int len, int data, int options, int status) "tx_bd 0x%"PRIx64" flags 0x%04x len %d data 0x%08x option 0x%04x status 0x%04x" +imx_eth_tx_bd_busy(void) "tx_bd ran out of descriptors to transmit" +imx_eth_rx_bd_full(void) "RX buffer is full" +imx_eth_read(int reg, const char *reg_name, uint32_t value) "reg[%d:%s] => 0x%08"PRIx32 +imx_eth_write(int reg, const char *reg_name, uint64_t value) "reg[%d:%s] <= 0x%08"PRIx64 +imx_fec_receive(size_t size) "len %zu" +imx_fec_receive_len(uint64_t addr, int len) "rx_bd 0x%"PRIx64" length %d" +imx_fec_receive_last(int last) "rx frame flags 0x%04x" +imx_enet_receive(size_t size) "len %zu" +imx_enet_receive_len(uint64_t addr, int len) "rx_bd 0x%"PRIx64" length %d" +imx_enet_receive_last(int last) "rx frame flags 0x%04x" diff --git a/hw/net/trace.h b/hw/net/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..93249af0ac264b51d951de3efb69a9586654251b --- /dev/null +++ b/hw/net/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_net.h" diff --git a/hw/net/tulip.c b/hw/net/tulip.c index 6cefc0add27b172aa80b6fba72de117e701322fb..ca69f7ea5e17785afda221ddb6fe07242d16a149 100644 --- a/hw/net/tulip.c +++ b/hw/net/tulip.c @@ -18,7 +18,7 @@ #include "trace.h" #include "net/eth.h" -typedef struct TULIPState { +struct TULIPState { PCIDevice dev; MemoryRegion io; MemoryRegion memory; @@ -44,7 +44,7 @@ typedef struct TULIPState { uint32_t rx_status; uint8_t filter[16][6]; -} TULIPState; +}; static const VMStateDescription vmstate_pci_tulip = { .name = "tulip", @@ -171,9 +171,6 @@ static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc) len = s->rx_frame_len; } - if (s->rx_frame_len + len > sizeof(s->rx_frame)) { - return; - } pci_dma_write(&s->dev, desc->buf_addr1, s->rx_frame + (s->rx_frame_size - s->rx_frame_len), len); s->rx_frame_len -= len; @@ -186,9 +183,6 @@ static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc) len = s->rx_frame_len; } - if (s->rx_frame_len + len > sizeof(s->rx_frame)) { - return; - } pci_dma_write(&s->dev, desc->buf_addr2, s->rx_frame + (s->rx_frame_size - s->rx_frame_len), len); s->rx_frame_len -= len; @@ -584,6 +578,9 @@ static int tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc) int len2 = (desc->control >> TDES1_BUF2_SIZE_SHIFT) & TDES1_BUF2_SIZE_MASK; if (s->tx_frame_len + len1 > sizeof(s->tx_frame)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: descriptor overflow (ofs: %u, len:%d, size:%zu)\n", + __func__, s->tx_frame_len, len1, sizeof(s->tx_frame)); return -1; } if (len1) { @@ -593,6 +590,9 @@ static int tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc) } if (s->tx_frame_len + len2 > sizeof(s->tx_frame)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: descriptor overflow (ofs: %u, len:%d, size:%zu)\n", + __func__, s->tx_frame_len, len2, sizeof(s->tx_frame)); return -1; } if (len2) { diff --git a/hw/net/tulip.h b/hw/net/tulip.h index 97521b21db2a96b114c93be1e92903d0c5268aed..ffd1f88d57663302c3636217f6cd0fb79c14bc7d 100644 --- a/hw/net/tulip.h +++ b/hw/net/tulip.h @@ -3,9 +3,10 @@ #include "qemu/units.h" #include "net/net.h" +#include "qom/object.h" #define TYPE_TULIP "tulip" -#define TULIP(obj) OBJECT_CHECK(TULIPState, (obj), TYPE_TULIP) +OBJECT_DECLARE_SIMPLE_TYPE(TULIPState, TULIP) #define CSR(_x) ((_x) << 3) @@ -211,7 +212,7 @@ #define RDES0_RF BIT(11) #define RDES0_DT_SHIFT 12 #define RDES0_DT_MASK 3 -#define RDES0_LE BIT(14) +#define RDES0_DE BIT(14) #define RDES0_ES BIT(15) #define RDES0_FL_SHIFT 16 #define RDES0_FL_MASK 0x3fff diff --git a/hw/net/vhost_net-stub.c b/hw/net/vhost_net-stub.c index aac0e9822801a7710790cb0ab494e799f9a3be3f..a7f42526304753d8333c7ed7051cd2ad410ea41a 100644 --- a/hw/net/vhost_net-stub.c +++ b/hw/net/vhost_net-stub.c @@ -52,6 +52,17 @@ uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features) return features; } +int vhost_net_get_config(struct vhost_net *net, uint8_t *config, + uint32_t config_len) +{ + return 0; +} +int vhost_net_set_config(struct vhost_net *net, const uint8_t *data, + uint32_t offset, uint32_t size, uint32_t flags) +{ + return 0; +} + void vhost_net_ack_features(struct vhost_net *net, uint64_t features) { } diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 6b82803fa707584547a71b4cefa9fae8c7353773..24d555e764a82cc531901d8b33050355a4cee164 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -17,6 +17,7 @@ #include "net/net.h" #include "net/tap.h" #include "net/vhost-user.h" +#include "net/vhost-vdpa.h" #include "standard-headers/linux/vhost_types.h" #include "hw/virtio/virtio-net.h" @@ -33,12 +34,6 @@ #include "hw/virtio/vhost.h" #include "hw/virtio/virtio-bus.h" -struct vhost_net { - struct vhost_dev dev; - struct vhost_virtqueue vqs[2]; - int backend; - NetClientState *nc; -}; /* Features supported by host kernel. */ static const int kernel_feature_bits[] = { @@ -96,6 +91,11 @@ static const int *vhost_net_get_feature_bits(struct vhost_net *net) case NET_CLIENT_DRIVER_VHOST_USER: feature_bits = user_feature_bits; break; +#ifdef CONFIG_VHOST_NET_VDPA + case NET_CLIENT_DRIVER_VHOST_VDPA: + feature_bits = vdpa_feature_bits; + break; +#endif default: error_report("Feature bits not defined for this type: %d", net->nc->info->type); @@ -110,6 +110,16 @@ uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features) return vhost_get_features(&net->dev, vhost_net_get_feature_bits(net), features); } +int vhost_net_get_config(struct vhost_net *net, uint8_t *config, + uint32_t config_len) +{ + return vhost_dev_get_config(&net->dev, config, config_len); +} +int vhost_net_set_config(struct vhost_net *net, const uint8_t *data, + uint32_t offset, uint32_t size, uint32_t flags) +{ + return vhost_dev_set_config(&net->dev, data, offset, size, flags); +} void vhost_net_ack_features(struct vhost_net *net, uint64_t features) { @@ -306,7 +316,9 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); VirtioBusState *vbus = VIRTIO_BUS(qbus); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); + struct vhost_net *net; int r, e, i; + NetClientState *peer; if (!k->set_guest_notifiers) { error_report("binding does not support guest notifiers"); @@ -314,9 +326,9 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, } for (i = 0; i < total_queues; i++) { - struct vhost_net *net; - net = get_vhost_net(ncs[i].peer); + peer = qemu_get_peer(ncs, i); + net = get_vhost_net(peer); vhost_net_set_vq_index(net, i * 2); /* Suppress the masking guest notifiers on vhost user @@ -335,15 +347,16 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, } for (i = 0; i < total_queues; i++) { - r = vhost_net_start_one(get_vhost_net(ncs[i].peer), dev); + peer = qemu_get_peer(ncs, i); + r = vhost_net_start_one(get_vhost_net(peer), dev); if (r < 0) { goto err_start; } - if (ncs[i].peer->vring_enable) { + if (peer->vring_enable) { /* restore vring enable state */ - r = vhost_set_vring_enable(ncs[i].peer, ncs[i].peer->vring_enable); + r = vhost_set_vring_enable(peer, peer->vring_enable); if (r < 0) { goto err_start; @@ -355,7 +368,8 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, err_start: while (--i >= 0) { - vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev); + peer = qemu_get_peer(ncs , i); + vhost_net_stop_one(get_vhost_net(peer), dev); } e = k->set_guest_notifiers(qbus->parent, total_queues * 2, false); if (e < 0) { @@ -429,6 +443,12 @@ VHostNetState *get_vhost_net(NetClientState *nc) vhost_net = vhost_user_get_vhost_net(nc); assert(vhost_net); break; +#endif +#ifdef CONFIG_VHOST_NET_VDPA + case NET_CLIENT_DRIVER_VHOST_VDPA: + vhost_net = vhost_vdpa_get_vhost_net(nc); + assert(vhost_net); + break; #endif default: break; diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index b7f3d1b2eb2b500c507e7798ddaed453d447be93..9179013ac4025d31481c5b0004f8fffc45d1cadd 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -42,6 +42,8 @@ #include "trace.h" #include "monitor/qdev.h" #include "hw/pci/pci.h" +#include "net_rx_pkt.h" +#include "hw/virtio/vhost.h" #define VIRTIO_NET_VM_VERSION 11 @@ -77,25 +79,15 @@ tso/gso/gro 'off'. */ #define VIRTIO_NET_RSC_DEFAULT_INTERVAL 300000 -/* temporary until standard header include it */ -#if !defined(VIRTIO_NET_HDR_F_RSC_INFO) - -#define VIRTIO_NET_HDR_F_RSC_INFO 4 /* rsc_ext data in csum_ fields */ -#define VIRTIO_NET_F_RSC_EXT 61 - -#endif - -static inline __virtio16 *virtio_net_rsc_ext_num_packets( - struct virtio_net_hdr *hdr) -{ - return &hdr->csum_start; -} - -static inline __virtio16 *virtio_net_rsc_ext_num_dupacks( - struct virtio_net_hdr *hdr) -{ - return &hdr->csum_offset; -} +#define VIRTIO_NET_RSS_SUPPORTED_HASHES (VIRTIO_NET_RSS_HASH_TYPE_IPv4 | \ + VIRTIO_NET_RSS_HASH_TYPE_TCPv4 | \ + VIRTIO_NET_RSS_HASH_TYPE_UDPv4 | \ + VIRTIO_NET_RSS_HASH_TYPE_IPv6 | \ + VIRTIO_NET_RSS_HASH_TYPE_TCPv6 | \ + VIRTIO_NET_RSS_HASH_TYPE_UDPv6 | \ + VIRTIO_NET_RSS_HASH_TYPE_IP_EX | \ + VIRTIO_NET_RSS_HASH_TYPE_TCP_EX | \ + VIRTIO_NET_RSS_HASH_TYPE_UDP_EX) static VirtIOFeature feature_sizes[] = { {.flags = 1ULL << VIRTIO_NET_F_MAC, @@ -108,6 +100,8 @@ static VirtIOFeature feature_sizes[] = { .end = endof(struct virtio_net_config, mtu)}, {.flags = 1ULL << VIRTIO_NET_F_SPEED_DUPLEX, .end = endof(struct virtio_net_config, duplex)}, + {.flags = (1ULL << VIRTIO_NET_F_RSS) | (1ULL << VIRTIO_NET_F_HASH_REPORT), + .end = endof(struct virtio_net_config, supported_hash_types)}, {} }; @@ -131,20 +125,42 @@ static void virtio_net_get_config(VirtIODevice *vdev, uint8_t *config) { VirtIONet *n = VIRTIO_NET(vdev); struct virtio_net_config netcfg; + NetClientState *nc = qemu_get_queue(n->nic); + int ret = 0; + memset(&netcfg, 0 , sizeof(struct virtio_net_config)); virtio_stw_p(vdev, &netcfg.status, n->status); virtio_stw_p(vdev, &netcfg.max_virtqueue_pairs, n->max_queues); virtio_stw_p(vdev, &netcfg.mtu, n->net_conf.mtu); memcpy(netcfg.mac, n->mac, ETH_ALEN); virtio_stl_p(vdev, &netcfg.speed, n->net_conf.speed); netcfg.duplex = n->net_conf.duplex; + netcfg.rss_max_key_size = VIRTIO_NET_RSS_MAX_KEY_SIZE; + virtio_stw_p(vdev, &netcfg.rss_max_indirection_table_length, + virtio_host_has_feature(vdev, VIRTIO_NET_F_RSS) ? + VIRTIO_NET_RSS_MAX_TABLE_LEN : 1); + virtio_stl_p(vdev, &netcfg.supported_hash_types, + VIRTIO_NET_RSS_SUPPORTED_HASHES); memcpy(config, &netcfg, n->config_size); + + /* + * Is this VDPA? No peer means not VDPA: there's no way to + * disconnect/reconnect a VDPA peer. + */ + if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_VDPA) { + ret = vhost_net_get_config(get_vhost_net(nc->peer), (uint8_t *)&netcfg, + n->config_size); + if (ret != -1) { + memcpy(config, &netcfg, n->config_size); + } + } } static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config) { VirtIONet *n = VIRTIO_NET(vdev); struct virtio_net_config netcfg = {}; + NetClientState *nc = qemu_get_queue(n->nic); memcpy(&netcfg, config, n->config_size); @@ -154,6 +170,16 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config) memcpy(n->mac, netcfg.mac, ETH_ALEN); qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac); } + + /* + * Is this VDPA? No peer means not VDPA: there's no way to + * disconnect/reconnect a VDPA peer. + */ + if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_VDPA) { + vhost_net_set_config(get_vhost_net(nc->peer), + (uint8_t *)&netcfg, 0, n->config_size, + VHOST_SET_CONFIG_TYPE_MASTER); + } } static bool virtio_net_started(VirtIONet *n, uint8_t status) @@ -561,7 +587,7 @@ static int peer_has_ufo(VirtIONet *n) } static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs, - int version_1) + int version_1, int hash_report) { int i; NetClientState *nc; @@ -569,7 +595,10 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs, n->mergeable_rx_bufs = mergeable_rx_bufs; if (version_1) { - n->guest_hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); + n->guest_hdr_len = hash_report ? + sizeof(struct virtio_net_hdr_v1_hash) : + sizeof(struct virtio_net_hdr_mrg_rxbuf); + n->rss_data.populate_hash = !!hash_report; } else { n->guest_hdr_len = n->mergeable_rx_bufs ? sizeof(struct virtio_net_hdr_mrg_rxbuf) : @@ -690,6 +719,8 @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features, virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_TSO4); virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_TSO6); virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_ECN); + + virtio_clear_feature(&features, VIRTIO_NET_F_HASH_REPORT); } if (!peer_has_vnet_hdr(n) || !peer_has_ufo(n)) { @@ -701,6 +732,8 @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features, return features; } + virtio_clear_feature(&features, VIRTIO_NET_F_RSS); + virtio_clear_feature(&features, VIRTIO_NET_F_HASH_REPORT); features = vhost_net_get_features(get_vhost_net(nc->peer), features); vdev->backend_features = features; @@ -784,9 +817,7 @@ static void failover_add_primary(VirtIONet *n, Error **errp) "sure primary device has parameter" " failover_pair_id=\n"); } - if (err) { - error_propagate(errp, err); - } + error_propagate(errp, err); } static int is_my_primary(void *opaque, QemuOpts *opts, Error **errp) @@ -840,9 +871,7 @@ static DeviceState *virtio_connect_failover_devices(VirtIONet *n, n->primary_device_id = g_strdup(prim_dev->id); n->primary_device_opts = prim_dev->opts; } else { - if (err) { - error_propagate(errp, err); - } + error_propagate(errp, err); } return prim_dev; @@ -860,18 +889,22 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features) } virtio_net_set_multiqueue(n, + virtio_has_feature(features, VIRTIO_NET_F_RSS) || virtio_has_feature(features, VIRTIO_NET_F_MQ)); virtio_net_set_mrg_rx_bufs(n, virtio_has_feature(features, VIRTIO_NET_F_MRG_RXBUF), virtio_has_feature(features, - VIRTIO_F_VERSION_1)); + VIRTIO_F_VERSION_1), + virtio_has_feature(features, + VIRTIO_NET_F_HASH_REPORT)); n->rsc4_enabled = virtio_has_feature(features, VIRTIO_NET_F_RSC_EXT) && virtio_has_feature(features, VIRTIO_NET_F_GUEST_TSO4); n->rsc6_enabled = virtio_has_feature(features, VIRTIO_NET_F_RSC_EXT) && virtio_has_feature(features, VIRTIO_NET_F_GUEST_TSO6); + n->rss_data.redirect = virtio_has_feature(features, VIRTIO_NET_F_RSS); if (n->has_vnet_hdr) { n->curr_guest_offloads = @@ -896,7 +929,7 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features) if (virtio_has_feature(features, VIRTIO_NET_F_STANDBY)) { qapi_event_send_failover_negotiated(n->netclient_name); - atomic_set(&n->primary_should_be_hidden, false); + qatomic_set(&n->primary_should_be_hidden, false); failover_add_primary(n, &err); if (err) { n->primary_dev = virtio_connect_failover_devices(n, n->qdev, &err); @@ -1136,25 +1169,165 @@ static int virtio_net_handle_announce(VirtIONet *n, uint8_t cmd, } } +static void virtio_net_disable_rss(VirtIONet *n) +{ + if (n->rss_data.enabled) { + trace_virtio_net_rss_disable(); + } + n->rss_data.enabled = false; +} + +static uint16_t virtio_net_handle_rss(VirtIONet *n, + struct iovec *iov, + unsigned int iov_cnt, + bool do_rss) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(n); + struct virtio_net_rss_config cfg; + size_t s, offset = 0, size_get; + uint16_t queues, i; + struct { + uint16_t us; + uint8_t b; + } QEMU_PACKED temp; + const char *err_msg = ""; + uint32_t err_value = 0; + + if (do_rss && !virtio_vdev_has_feature(vdev, VIRTIO_NET_F_RSS)) { + err_msg = "RSS is not negotiated"; + goto error; + } + if (!do_rss && !virtio_vdev_has_feature(vdev, VIRTIO_NET_F_HASH_REPORT)) { + err_msg = "Hash report is not negotiated"; + goto error; + } + size_get = offsetof(struct virtio_net_rss_config, indirection_table); + s = iov_to_buf(iov, iov_cnt, offset, &cfg, size_get); + if (s != size_get) { + err_msg = "Short command buffer"; + err_value = (uint32_t)s; + goto error; + } + n->rss_data.hash_types = virtio_ldl_p(vdev, &cfg.hash_types); + n->rss_data.indirections_len = + virtio_lduw_p(vdev, &cfg.indirection_table_mask); + n->rss_data.indirections_len++; + if (!do_rss) { + n->rss_data.indirections_len = 1; + } + if (!is_power_of_2(n->rss_data.indirections_len)) { + err_msg = "Invalid size of indirection table"; + err_value = n->rss_data.indirections_len; + goto error; + } + if (n->rss_data.indirections_len > VIRTIO_NET_RSS_MAX_TABLE_LEN) { + err_msg = "Too large indirection table"; + err_value = n->rss_data.indirections_len; + goto error; + } + n->rss_data.default_queue = do_rss ? + virtio_lduw_p(vdev, &cfg.unclassified_queue) : 0; + if (n->rss_data.default_queue >= n->max_queues) { + err_msg = "Invalid default queue"; + err_value = n->rss_data.default_queue; + goto error; + } + offset += size_get; + size_get = sizeof(uint16_t) * n->rss_data.indirections_len; + g_free(n->rss_data.indirections_table); + n->rss_data.indirections_table = g_malloc(size_get); + if (!n->rss_data.indirections_table) { + err_msg = "Can't allocate indirections table"; + err_value = n->rss_data.indirections_len; + goto error; + } + s = iov_to_buf(iov, iov_cnt, offset, + n->rss_data.indirections_table, size_get); + if (s != size_get) { + err_msg = "Short indirection table buffer"; + err_value = (uint32_t)s; + goto error; + } + for (i = 0; i < n->rss_data.indirections_len; ++i) { + uint16_t val = n->rss_data.indirections_table[i]; + n->rss_data.indirections_table[i] = virtio_lduw_p(vdev, &val); + } + offset += size_get; + size_get = sizeof(temp); + s = iov_to_buf(iov, iov_cnt, offset, &temp, size_get); + if (s != size_get) { + err_msg = "Can't get queues"; + err_value = (uint32_t)s; + goto error; + } + queues = do_rss ? virtio_lduw_p(vdev, &temp.us) : n->curr_queues; + if (queues == 0 || queues > n->max_queues) { + err_msg = "Invalid number of queues"; + err_value = queues; + goto error; + } + if (temp.b > VIRTIO_NET_RSS_MAX_KEY_SIZE) { + err_msg = "Invalid key size"; + err_value = temp.b; + goto error; + } + if (!temp.b && n->rss_data.hash_types) { + err_msg = "No key provided"; + err_value = 0; + goto error; + } + if (!temp.b && !n->rss_data.hash_types) { + virtio_net_disable_rss(n); + return queues; + } + offset += size_get; + size_get = temp.b; + s = iov_to_buf(iov, iov_cnt, offset, n->rss_data.key, size_get); + if (s != size_get) { + err_msg = "Can get key buffer"; + err_value = (uint32_t)s; + goto error; + } + n->rss_data.enabled = true; + trace_virtio_net_rss_enable(n->rss_data.hash_types, + n->rss_data.indirections_len, + temp.b); + return queues; +error: + trace_virtio_net_rss_error(err_msg, err_value); + virtio_net_disable_rss(n); + return 0; +} + static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd, struct iovec *iov, unsigned int iov_cnt) { VirtIODevice *vdev = VIRTIO_DEVICE(n); - struct virtio_net_ctrl_mq mq; - size_t s; uint16_t queues; - s = iov_to_buf(iov, iov_cnt, 0, &mq, sizeof(mq)); - if (s != sizeof(mq)) { - return VIRTIO_NET_ERR; - } + virtio_net_disable_rss(n); + if (cmd == VIRTIO_NET_CTRL_MQ_HASH_CONFIG) { + queues = virtio_net_handle_rss(n, iov, iov_cnt, false); + return queues ? VIRTIO_NET_OK : VIRTIO_NET_ERR; + } + if (cmd == VIRTIO_NET_CTRL_MQ_RSS_CONFIG) { + queues = virtio_net_handle_rss(n, iov, iov_cnt, true); + } else if (cmd == VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET) { + struct virtio_net_ctrl_mq mq; + size_t s; + if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_MQ)) { + return VIRTIO_NET_ERR; + } + s = iov_to_buf(iov, iov_cnt, 0, &mq, sizeof(mq)); + if (s != sizeof(mq)) { + return VIRTIO_NET_ERR; + } + queues = virtio_lduw_p(vdev, &mq.virtqueue_pairs); - if (cmd != VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET) { + } else { return VIRTIO_NET_ERR; } - queues = virtio_lduw_p(vdev, &mq.virtqueue_pairs); - if (queues < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN || queues > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX || queues > n->max_queues || @@ -1387,8 +1560,107 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) return 0; } +static uint8_t virtio_net_get_hash_type(bool isip4, + bool isip6, + bool isudp, + bool istcp, + uint32_t types) +{ + if (isip4) { + if (istcp && (types & VIRTIO_NET_RSS_HASH_TYPE_TCPv4)) { + return NetPktRssIpV4Tcp; + } + if (isudp && (types & VIRTIO_NET_RSS_HASH_TYPE_UDPv4)) { + return NetPktRssIpV4Udp; + } + if (types & VIRTIO_NET_RSS_HASH_TYPE_IPv4) { + return NetPktRssIpV4; + } + } else if (isip6) { + uint32_t mask = VIRTIO_NET_RSS_HASH_TYPE_TCP_EX | + VIRTIO_NET_RSS_HASH_TYPE_TCPv6; + + if (istcp && (types & mask)) { + return (types & VIRTIO_NET_RSS_HASH_TYPE_TCP_EX) ? + NetPktRssIpV6TcpEx : NetPktRssIpV6Tcp; + } + mask = VIRTIO_NET_RSS_HASH_TYPE_UDP_EX | VIRTIO_NET_RSS_HASH_TYPE_UDPv6; + if (isudp && (types & mask)) { + return (types & VIRTIO_NET_RSS_HASH_TYPE_UDP_EX) ? + NetPktRssIpV6UdpEx : NetPktRssIpV6Udp; + } + mask = VIRTIO_NET_RSS_HASH_TYPE_IP_EX | VIRTIO_NET_RSS_HASH_TYPE_IPv6; + if (types & mask) { + return (types & VIRTIO_NET_RSS_HASH_TYPE_IP_EX) ? + NetPktRssIpV6Ex : NetPktRssIpV6; + } + } + return 0xff; +} + +static void virtio_set_packet_hash(const uint8_t *buf, uint8_t report, + uint32_t hash) +{ + struct virtio_net_hdr_v1_hash *hdr = (void *)buf; + hdr->hash_value = hash; + hdr->hash_report = report; +} + +static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf, + size_t size) +{ + VirtIONet *n = qemu_get_nic_opaque(nc); + unsigned int index = nc->queue_index, new_index = index; + struct NetRxPkt *pkt = n->rx_pkt; + uint8_t net_hash_type; + uint32_t hash; + bool isip4, isip6, isudp, istcp; + static const uint8_t reports[NetPktRssIpV6UdpEx + 1] = { + VIRTIO_NET_HASH_REPORT_IPv4, + VIRTIO_NET_HASH_REPORT_TCPv4, + VIRTIO_NET_HASH_REPORT_TCPv6, + VIRTIO_NET_HASH_REPORT_IPv6, + VIRTIO_NET_HASH_REPORT_IPv6_EX, + VIRTIO_NET_HASH_REPORT_TCPv6_EX, + VIRTIO_NET_HASH_REPORT_UDPv4, + VIRTIO_NET_HASH_REPORT_UDPv6, + VIRTIO_NET_HASH_REPORT_UDPv6_EX + }; + + net_rx_pkt_set_protocols(pkt, buf + n->host_hdr_len, + size - n->host_hdr_len); + net_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp); + if (isip4 && (net_rx_pkt_get_ip4_info(pkt)->fragment)) { + istcp = isudp = false; + } + if (isip6 && (net_rx_pkt_get_ip6_info(pkt)->fragment)) { + istcp = isudp = false; + } + net_hash_type = virtio_net_get_hash_type(isip4, isip6, isudp, istcp, + n->rss_data.hash_types); + if (net_hash_type > NetPktRssIpV6UdpEx) { + if (n->rss_data.populate_hash) { + virtio_set_packet_hash(buf, VIRTIO_NET_HASH_REPORT_NONE, 0); + } + return n->rss_data.redirect ? n->rss_data.default_queue : -1; + } + + hash = net_rx_pkt_calc_rss_hash(pkt, net_hash_type, n->rss_data.key); + + if (n->rss_data.populate_hash) { + virtio_set_packet_hash(buf, reports[net_hash_type], hash); + } + + if (n->rss_data.redirect) { + new_index = hash & (n->rss_data.indirections_len - 1); + new_index = n->rss_data.indirections_table[new_index]; + } + + return (index == new_index) ? -1 : new_index; +} + static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf, - size_t size) + size_t size, bool no_rss) { VirtIONet *n = qemu_get_nic_opaque(nc); VirtIONetQueue *q = virtio_net_get_subqueue(nc); @@ -1402,6 +1674,14 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf, return -1; } + if (!no_rss && n->rss_data.enabled) { + int index = virtio_net_process_rss(nc, buf, size); + if (index >= 0) { + NetClientState *nc2 = qemu_get_subqueue(n->nic, index); + return virtio_net_receive_rcu(nc2, buf, size, true); + } + } + /* hdr_len refers to the header we supply to the guest */ if (!virtio_net_has_buffers(q, size + n->guest_hdr_len - n->host_hdr_len)) { return 0; @@ -1452,6 +1732,11 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf, } receive_header(n, sg, elem->in_num, buf, size); + if (n->rss_data.populate_hash) { + offset = sizeof(mhdr); + iov_from_buf(sg, elem->in_num, offset, + buf + offset, n->host_hdr_len - sizeof(mhdr)); + } offset = n->host_hdr_len; total += n->guest_hdr_len; guest_offset = n->guest_hdr_len; @@ -1496,7 +1781,7 @@ static ssize_t virtio_net_do_receive(NetClientState *nc, const uint8_t *buf, { RCU_READ_LOCK_GUARD(); - return virtio_net_receive_rcu(nc, buf, size); + return virtio_net_receive_rcu(nc, buf, size, false); } static void virtio_net_rsc_extract_unit4(VirtioNetRscChain *chain, @@ -1539,15 +1824,15 @@ static size_t virtio_net_rsc_drain_seg(VirtioNetRscChain *chain, VirtioNetRscSeg *seg) { int ret; - struct virtio_net_hdr *h; + struct virtio_net_hdr_v1 *h; - h = (struct virtio_net_hdr *)seg->buf; + h = (struct virtio_net_hdr_v1 *)seg->buf; h->flags = 0; h->gso_type = VIRTIO_NET_HDR_GSO_NONE; if (seg->is_coalesced) { - *virtio_net_rsc_ext_num_packets(h) = seg->packets; - *virtio_net_rsc_ext_num_dupacks(h) = seg->dup_ack; + h->rsc.segments = seg->packets; + h->rsc.dup_acks = seg->dup_ack; h->flags = VIRTIO_NET_HDR_F_RSC_INFO; if (chain->proto == ETH_P_IP) { h->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; @@ -1786,7 +2071,6 @@ static int virtio_net_rsc_tcp_ctrl_check(VirtioNetRscChain *chain, tcp_flag = htons(tcp->th_offset_flags); tcp_hdr = (tcp_flag & VIRTIO_NET_TCP_HDR_LENGTH) >> 10; tcp_flag &= VIRTIO_NET_TCP_FLAG; - tcp_flag = htons(tcp->th_offset_flags) & 0x3F; if (tcp_flag & TH_SYN) { chain->stat.tcp_syn++; return RSC_BYPASS; @@ -2444,7 +2728,9 @@ static int virtio_net_post_load_device(void *opaque, int version_id) trace_virtio_net_post_load_device(); virtio_net_set_mrg_rx_bufs(n, n->mergeable_rx_bufs, virtio_vdev_has_feature(vdev, - VIRTIO_F_VERSION_1)); + VIRTIO_F_VERSION_1), + virtio_vdev_has_feature(vdev, + VIRTIO_NET_F_HASH_REPORT)); /* MAC_TABLE_ENTRIES may be different from the saved image */ if (n->mac_table.in_use > MAC_TABLE_ENTRIES) { @@ -2493,6 +2779,13 @@ static int virtio_net_post_load_device(void *opaque, int version_id) } } + if (n->rss_data.enabled) { + trace_virtio_net_rss_enable(n->rss_data.hash_types, + n->rss_data.indirections_len, + sizeof(n->rss_data.key)); + } else { + trace_virtio_net_rss_disable(); + } return 0; } @@ -2670,6 +2963,32 @@ static const VMStateDescription vmstate_virtio_net_has_vnet = { }, }; +static bool virtio_net_rss_needed(void *opaque) +{ + return VIRTIO_NET(opaque)->rss_data.enabled; +} + +static const VMStateDescription vmstate_virtio_net_rss = { + .name = "virtio-net-device/rss", + .version_id = 1, + .minimum_version_id = 1, + .needed = virtio_net_rss_needed, + .fields = (VMStateField[]) { + VMSTATE_BOOL(rss_data.enabled, VirtIONet), + VMSTATE_BOOL(rss_data.redirect, VirtIONet), + VMSTATE_BOOL(rss_data.populate_hash, VirtIONet), + VMSTATE_UINT32(rss_data.hash_types, VirtIONet), + VMSTATE_UINT16(rss_data.indirections_len, VirtIONet), + VMSTATE_UINT16(rss_data.default_queue, VirtIONet), + VMSTATE_UINT8_ARRAY(rss_data.key, VirtIONet, + VIRTIO_NET_RSS_MAX_KEY_SIZE), + VMSTATE_VARRAY_UINT16_ALLOC(rss_data.indirections_table, VirtIONet, + rss_data.indirections_len, 0, + vmstate_info_uint16, uint16_t), + VMSTATE_END_OF_LIST() + }, +}; + static const VMStateDescription vmstate_virtio_net_device = { .name = "virtio-net-device", .version_id = VIRTIO_NET_VM_VERSION, @@ -2720,6 +3039,10 @@ static const VMStateDescription vmstate_virtio_net_device = { has_ctrl_guest_offloads), VMSTATE_END_OF_LIST() }, + .subsections = (const VMStateDescription * []) { + &vmstate_virtio_net_rss, + NULL + } }; static NetClientInfo net_virtio_info = { @@ -2815,12 +3138,11 @@ static bool failover_replug_primary(VirtIONet *n, Error **errp) error_setg(errp, "virtio_net: couldn't find primary bus"); return false; } - qdev_set_parent_bus(n->primary_dev, n->primary_bus); + qdev_set_parent_bus(n->primary_dev, n->primary_bus, &error_abort); n->primary_should_be_hidden = false; - qemu_opt_set_bool(n->primary_device_opts, - "partially_hotplugged", true, &err); - if (err) { - goto out; + if (!qemu_opt_set_bool(n->primary_device_opts, + "partially_hotplugged", true, errp)) { + return false; } hotplug_ctrl = qdev_get_hotplug_handler(n->primary_dev); if (hotplug_ctrl) { @@ -2828,7 +3150,7 @@ static bool failover_replug_primary(VirtIONet *n, Error **errp) if (err) { goto out; } - hotplug_handler_plug(hotplug_ctrl, n->primary_dev, errp); + hotplug_handler_plug(hotplug_ctrl, n->primary_dev, &err); } out: @@ -2842,7 +3164,7 @@ static void virtio_net_handle_migration_primary(VirtIONet *n, bool should_be_hidden; Error *err = NULL; - should_be_hidden = atomic_read(&n->primary_should_be_hidden); + should_be_hidden = qatomic_read(&n->primary_should_be_hidden); if (!n->primary_dev) { n->primary_dev = virtio_connect_failover_devices(n, n->qdev, &err); @@ -2857,7 +3179,7 @@ static void virtio_net_handle_migration_primary(VirtIONet *n, qdev_get_vmsd(n->primary_dev), n->primary_dev); qapi_event_send_unplug_primary(n->primary_device_id); - atomic_set(&n->primary_should_be_hidden, true); + qatomic_set(&n->primary_should_be_hidden, true); } else { warn_report("couldn't unplug primary device"); } @@ -2908,7 +3230,7 @@ static int virtio_net_primary_should_be_hidden(DeviceListener *listener, n->primary_device_opts = device_opts; /* primary_should_be_hidden is set during feature negotiation */ - hide = atomic_read(&n->primary_should_be_hidden); + hide = qatomic_read(&n->primary_should_be_hidden); if (n->primary_device_dict) { g_free(n->primary_device_id); @@ -2965,7 +3287,7 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) if (n->failover) { n->primary_listener.should_be_hidden = virtio_net_primary_should_be_hidden; - atomic_set(&n->primary_should_be_hidden, true); + qatomic_set(&n->primary_should_be_hidden, true); device_listener_register(&n->primary_listener); n->migration_state.notify = virtio_net_migration_state_notifier; add_migration_state_change_notifier(&n->migration_state); @@ -3063,7 +3385,7 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) n->vqs[0].tx_waiting = 0; n->tx_burst = n->net_conf.txburst; - virtio_net_set_mrg_rx_bufs(n, 0, 0); + virtio_net_set_mrg_rx_bufs(n, 0, 0, 0); n->promisc = 1; /* for compatibility */ n->mac_table.macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN); @@ -3073,8 +3395,16 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) nc = qemu_get_queue(n->nic); nc->rxfilter_notify_enabled = 1; + if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_VDPA) { + struct virtio_net_config netcfg = {}; + memcpy(&netcfg.mac, &n->nic_conf.macaddr, ETH_ALEN); + vhost_net_set_config(get_vhost_net(nc->peer), + (uint8_t *)&netcfg, 0, ETH_ALEN, VHOST_SET_CONFIG_TYPE_MASTER); + } QTAILQ_INIT(&n->rsc_chains); n->qdev = dev; + + net_rx_pkt_init(&n->rx_pkt, false); } static void virtio_net_device_unrealize(DeviceState *dev) @@ -3095,6 +3425,7 @@ static void virtio_net_device_unrealize(DeviceState *dev) g_free(n->vlans); if (n->failover) { + device_listener_unregister(&n->primary_listener); g_free(n->primary_device_id); g_free(n->standby_id); qobject_unref(n->primary_device_dict); @@ -3111,6 +3442,8 @@ static void virtio_net_device_unrealize(DeviceState *dev) g_free(n->vqs); qemu_del_nic(n->nic); virtio_net_rsc_cleanup(n); + g_free(n->rss_data.indirections_table); + net_rx_pkt_uninit(n->rx_pkt); virtio_cleanup(vdev); } @@ -3212,6 +3545,10 @@ static Property virtio_net_properties[] = { DEFINE_PROP_BIT64("ctrl_guest_offloads", VirtIONet, host_features, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, true), DEFINE_PROP_BIT64("mq", VirtIONet, host_features, VIRTIO_NET_F_MQ, false), + DEFINE_PROP_BIT64("rss", VirtIONet, host_features, + VIRTIO_NET_F_RSS, false), + DEFINE_PROP_BIT64("hash", VirtIONet, host_features, + VIRTIO_NET_F_HASH_REPORT, false), DEFINE_PROP_BIT64("guest_rsc_ext", VirtIONet, host_features, VIRTIO_NET_F_RSC_EXT, false), DEFINE_PROP_UINT32("rsc_interval", VirtIONet, rsc_timeout, diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index 7a6ca4ec350ec3baff278f2ec6baf15ba4a54a50..eff299f6290cee3e784d9356179893d76999c375 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -35,6 +35,7 @@ #include "vmware_utils.h" #include "net_tx_pkt.h" #include "net_rx_pkt.h" +#include "qom/object.h" #define PCI_DEVICE_ID_VMWARE_VMXNET3_REVISION 0x1 #define VMXNET3_MSIX_BAR_SIZE 0x2000 @@ -128,15 +129,14 @@ #define VMXNET_FLAG_IS_SET(field, flag) (((field) & (flag)) == (flag)) -typedef struct VMXNET3Class { +struct VMXNET3Class { PCIDeviceClass parent_class; DeviceRealize parent_dc_realize; -} VMXNET3Class; +}; +typedef struct VMXNET3Class VMXNET3Class; -#define VMXNET3_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(VMXNET3Class, (klass), TYPE_VMXNET3) -#define VMXNET3_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VMXNET3Class, (obj), TYPE_VMXNET3) +DECLARE_CLASS_CHECKERS(VMXNET3Class, VMXNET3_DEVICE, + TYPE_VMXNET3) static inline void vmxnet3_ring_init(PCIDevice *d, Vmxnet3Ring *ring, diff --git a/hw/net/vmxnet3_defs.h b/hw/net/vmxnet3_defs.h index 65780c576d8411fb4db5b5b11ed705f11c9c4838..71440509cabf402a09d8cfcad220c18331c13916 100644 --- a/hw/net/vmxnet3_defs.h +++ b/hw/net/vmxnet3_defs.h @@ -19,9 +19,12 @@ #include "net/net.h" #include "hw/net/vmxnet3.h" +#include "qom/object.h" #define TYPE_VMXNET3 "vmxnet3" -#define VMXNET3(obj) OBJECT_CHECK(VMXNET3State, (obj), TYPE_VMXNET3) +typedef struct VMXNET3State VMXNET3State; +DECLARE_INSTANCE_CHECKER(VMXNET3State, VMXNET3, + TYPE_VMXNET3) /* Device state and helper functions */ #define VMXNET3_RX_RINGS_PER_QUEUE (2) @@ -58,7 +61,7 @@ typedef struct { bool is_asserted; } Vmxnet3IntState; -typedef struct { +struct VMXNET3State { PCIDevice parent_obj; NICState *nic; NICConf conf; @@ -132,6 +135,6 @@ typedef struct { /* Compatibility flags for migration */ uint32_t compat_flags; -} VMXNET3State; +}; #endif diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c index 574dd47b412fef025943f8e4b8be23bd6829db02..00859a7d508cd8098fe27687754490bc3724683b 100644 --- a/hw/net/xgmac.c +++ b/hw/net/xgmac.c @@ -32,6 +32,7 @@ #include "qemu/log.h" #include "qemu/module.h" #include "net/net.h" +#include "qom/object.h" #ifdef DEBUG_XGMAC #define DEBUGF_BRK(message, args...) do { \ @@ -139,9 +140,9 @@ typedef struct RxTxStats { } RxTxStats; #define TYPE_XGMAC "xgmac" -#define XGMAC(obj) OBJECT_CHECK(XgmacState, (obj), TYPE_XGMAC) +OBJECT_DECLARE_SIMPLE_TYPE(XgmacState, XGMAC) -typedef struct XgmacState { +struct XgmacState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -153,7 +154,7 @@ typedef struct XgmacState { struct RxTxStats stats; uint32_t regs[R_MAX]; -} XgmacState; +}; static const VMStateDescription vmstate_rxtx_stats = { .name = "xgmac_stats", @@ -220,21 +221,31 @@ static void xgmac_enet_send(XgmacState *s) } len = (bd.buffer1_size & 0xfff) + (bd.buffer2_size & 0xfff); + /* + * FIXME: these cases of malformed tx descriptors (bad sizes) + * should probably be reported back to the guest somehow + * rather than simply silently stopping processing, but we + * don't know what the hardware does in this situation. + * This will only happen for buggy guests anyway. + */ if ((bd.buffer1_size & 0xfff) > 2048) { DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- " "xgmac buffer 1 len on send > 2048 (0x%x)\n", __func__, bd.buffer1_size & 0xfff); + break; } if ((bd.buffer2_size & 0xfff) != 0) { DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- " "xgmac buffer 2 len on send != 0 (0x%x)\n", __func__, bd.buffer2_size & 0xfff); + break; } - if (len >= sizeof(frame)) { + if (frame_size + len >= sizeof(frame)) { DEBUGF_BRK("qemu:%s: buffer overflow %d read into %zu " - "buffer\n" , __func__, len, sizeof(frame)); + "buffer\n" , __func__, frame_size + len, sizeof(frame)); DEBUGF_BRK("qemu:%s: buffer1.size=%d; buffer2.size=%d\n", __func__, bd.buffer1_size, bd.buffer2_size); + break; } cpu_physical_memory_read(bd.buffer1_addr, ptr, len); diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c index 44fe04d889da7e48ed99af920ceec848eeb474a0..f8cf5290e165dbb3ce9f826b0284665c7bd68982 100644 --- a/hw/net/xilinx_axienet.c +++ b/hw/net/xilinx_axienet.c @@ -35,6 +35,7 @@ #include "hw/irq.h" #include "hw/qdev-properties.h" #include "hw/stream.h" +#include "qom/object.h" #define DPHY(x) @@ -42,19 +43,16 @@ #define TYPE_XILINX_AXI_ENET_DATA_STREAM "xilinx-axienet-data-stream" #define TYPE_XILINX_AXI_ENET_CONTROL_STREAM "xilinx-axienet-control-stream" -#define XILINX_AXI_ENET(obj) \ - OBJECT_CHECK(XilinxAXIEnet, (obj), TYPE_XILINX_AXI_ENET) +OBJECT_DECLARE_SIMPLE_TYPE(XilinxAXIEnet, XILINX_AXI_ENET) -#define XILINX_AXI_ENET_DATA_STREAM(obj) \ - OBJECT_CHECK(XilinxAXIEnetStreamSlave, (obj),\ - TYPE_XILINX_AXI_ENET_DATA_STREAM) +typedef struct XilinxAXIEnetStreamSlave XilinxAXIEnetStreamSlave; +DECLARE_INSTANCE_CHECKER(XilinxAXIEnetStreamSlave, XILINX_AXI_ENET_DATA_STREAM, + TYPE_XILINX_AXI_ENET_DATA_STREAM) -#define XILINX_AXI_ENET_CONTROL_STREAM(obj) \ - OBJECT_CHECK(XilinxAXIEnetStreamSlave, (obj),\ - TYPE_XILINX_AXI_ENET_CONTROL_STREAM) +DECLARE_INSTANCE_CHECKER(XilinxAXIEnetStreamSlave, XILINX_AXI_ENET_CONTROL_STREAM, + TYPE_XILINX_AXI_ENET_CONTROL_STREAM) /* Advertisement control register. */ -#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ #define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ #define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ #define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ @@ -169,28 +167,6 @@ tdk_init(struct PHY *phy) } struct MDIOBus { - /* bus. */ - int mdc; - int mdio; - - /* decoder. */ - enum { - PREAMBLE, - SOF, - OPC, - ADDR, - REQ, - TURNAROUND, - DATA - } state; - unsigned int drive; - - unsigned int cnt; - unsigned int addr; - unsigned int opc; - unsigned int req; - unsigned int data; - struct PHY *devs[32]; }; @@ -333,8 +309,6 @@ struct TEMAC { void *parent; }; -typedef struct XilinxAXIEnetStreamSlave XilinxAXIEnetStreamSlave; -typedef struct XilinxAXIEnet XilinxAXIEnet; struct XilinxAXIEnetStreamSlave { Object parent; @@ -980,7 +954,6 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp) XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(&s->rx_data_dev); XilinxAXIEnetStreamSlave *cs = XILINX_AXI_ENET_CONTROL_STREAM( &s->rx_control_dev); - Error *local_err = NULL; object_property_add_link(OBJECT(ds), "enet", "xlnx.axi-ethernet", (Object **) &ds->enet, @@ -990,11 +963,8 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp) (Object **) &cs->enet, object_property_allow_set_link, OBJ_PROP_LINK_STRONG); - object_property_set_link(OBJECT(ds), OBJECT(s), "enet", &local_err); - object_property_set_link(OBJECT(cs), OBJECT(s), "enet", &local_err); - if (local_err) { - goto xilinx_enet_realize_fail; - } + object_property_set_link(OBJECT(ds), "enet", OBJECT(s), &error_abort); + object_property_set_link(OBJECT(cs), "enet", OBJECT(s), &error_abort); qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_xilinx_enet_info, &s->conf, @@ -1008,10 +978,6 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp) s->rxmem = g_malloc(s->c_rxmem); s->txmem = g_malloc(s->c_txmem); - return; - -xilinx_enet_realize_fail: - error_propagate(errp, local_err); } static void xilinx_enet_init(Object *obj) @@ -1020,13 +986,10 @@ static void xilinx_enet_init(Object *obj) SysBusDevice *sbd = SYS_BUS_DEVICE(obj); object_initialize_child(OBJECT(s), "axistream-connected-target", - &s->rx_data_dev, sizeof(s->rx_data_dev), - TYPE_XILINX_AXI_ENET_DATA_STREAM, &error_abort, - NULL); + &s->rx_data_dev, TYPE_XILINX_AXI_ENET_DATA_STREAM); object_initialize_child(OBJECT(s), "axistream-control-connected-target", - &s->rx_control_dev, sizeof(s->rx_control_dev), - TYPE_XILINX_AXI_ENET_CONTROL_STREAM, &error_abort, - NULL); + &s->rx_control_dev, + TYPE_XILINX_AXI_ENET_CONTROL_STREAM); sysbus_init_irq(sbd, &s->irq); memory_region_init_io(&s->iomem, OBJECT(s), &enet_ops, s, "enet", 0x40000); @@ -1080,7 +1043,7 @@ static const TypeInfo xilinx_enet_info = { static const TypeInfo xilinx_enet_data_stream_info = { .name = TYPE_XILINX_AXI_ENET_DATA_STREAM, .parent = TYPE_OBJECT, - .instance_size = sizeof(struct XilinxAXIEnetStreamSlave), + .instance_size = sizeof(XilinxAXIEnetStreamSlave), .class_init = xilinx_enet_data_stream_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_STREAM_SLAVE }, @@ -1091,7 +1054,7 @@ static const TypeInfo xilinx_enet_data_stream_info = { static const TypeInfo xilinx_enet_control_stream_info = { .name = TYPE_XILINX_AXI_ENET_CONTROL_STREAM, .parent = TYPE_OBJECT, - .instance_size = sizeof(struct XilinxAXIEnetStreamSlave), + .instance_size = sizeof(XilinxAXIEnetStreamSlave), .class_init = xilinx_enet_control_stream_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_STREAM_SLAVE }, diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index 71d16fef3d7bc8cecfbe74916d82668e1f9a25da..6e09f7e422e6072c8d38e799de7fcf398bf18e51 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu/module.h" +#include "qom/object.h" #include "cpu.h" /* FIXME should not use tswap* */ #include "hw/sysbus.h" #include "hw/irq.h" @@ -52,8 +53,8 @@ #define CTRL_S 0x1 #define TYPE_XILINX_ETHLITE "xlnx.xps-ethernetlite" -#define XILINX_ETHLITE(obj) \ - OBJECT_CHECK(struct xlx_ethlite, (obj), TYPE_XILINX_ETHLITE) +DECLARE_INSTANCE_CHECKER(struct xlx_ethlite, XILINX_ETHLITE, + TYPE_XILINX_ETHLITE) struct xlx_ethlite { diff --git a/hw/nios2/10m50_devboard.c b/hw/nios2/10m50_devboard.c index 4c60a27fb7289c64ead1dd5698cb69bd32a82b3c..5c13b74306f06458e03a57254a5eea820a9eba48 100644 --- a/hw/nios2/10m50_devboard.c +++ b/hw/nios2/10m50_devboard.c @@ -80,9 +80,9 @@ static void nios2_10m50_ghrd_init(MachineState *machine) cpu_irq = nios2_cpu_pic_init(cpu); /* Register: Internal Interrupt Controller (IIC) */ - dev = qdev_create(NULL, "altera,iic"); + dev = qdev_new("altera,iic"); object_property_add_const_link(OBJECT(dev), "cpu", OBJECT(cpu)); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irq[0]); for (i = 0; i < 32; i++) { irq[i] = qdev_get_gpio_in(dev, i); @@ -93,16 +93,16 @@ static void nios2_10m50_ghrd_init(MachineState *machine) serial_hd(0), DEVICE_NATIVE_ENDIAN); /* Register: Timer sys_clk_timer */ - dev = qdev_create(NULL, "ALTR.timer"); + dev = qdev_new("ALTR.timer"); qdev_prop_set_uint32(dev, "clock-frequency", 75 * 1000000); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xf8001440); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[0]); /* Register: Timer sys_clk_timer_1 */ - dev = qdev_create(NULL, "ALTR.timer"); + dev = qdev_new("ALTR.timer"); qdev_prop_set_uint32(dev, "clock-frequency", 75 * 1000000); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xe0000880); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[5]); diff --git a/hw/nios2/Makefile.objs b/hw/nios2/Makefile.objs deleted file mode 100644 index 3e017981baa522958b2b087577d6c5918938c446..0000000000000000000000000000000000000000 --- a/hw/nios2/Makefile.objs +++ /dev/null @@ -1,3 +0,0 @@ -obj-y = boot.o cpu_pic.o -obj-$(CONFIG_NIOS2_10M50) += 10m50_devboard.o -obj-$(CONFIG_NIOS2_GENERIC_NOMMU) += generic_nommu.o diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c index 88224aa84c8b2ac28ae59452727140d0d85c4065..1df3b66c2926afb3864b0ea54adcfe9525922e9b 100644 --- a/hw/nios2/boot.c +++ b/hw/nios2/boot.c @@ -139,7 +139,7 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base, if (kernel_filename) { int kernel_size, fdt_size; - uint64_t entry, low, high; + uint64_t entry, high; int big_endian = 0; #ifdef TARGET_WORDS_BIGENDIAN @@ -148,7 +148,7 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base, /* Boots a kernel elf binary. */ kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, - &entry, &low, &high, NULL, + &entry, NULL, &high, NULL, big_endian, EM_ALTERA_NIOS2, 0, 0); if ((uint32_t)entry == 0xc0000000) { /* diff --git a/hw/nios2/cpu_pic.c b/hw/nios2/cpu_pic.c index 1c1989d56a0f4e216f38571a854c3d1696efd3c9..5ea7e52ab8302e5153981baf78bba76c79ce4506 100644 --- a/hw/nios2/cpu_pic.c +++ b/hw/nios2/cpu_pic.c @@ -54,7 +54,8 @@ static void nios2_pic_cpu_handler(void *opaque, int irq, int level) void nios2_check_interrupts(CPUNios2State *env) { - if (env->irq_pending) { + if (env->irq_pending && + (env->regs[CR_STATUS] & CR_STATUS_PIE)) { env->irq_pending = 0; cpu_interrupt(env_cpu(env), CPU_INTERRUPT_HARD); } diff --git a/hw/nios2/meson.build b/hw/nios2/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..dd66ebb32f67c6be7fb847e70552e865f925659f --- /dev/null +++ b/hw/nios2/meson.build @@ -0,0 +1,6 @@ +nios2_ss = ss.source_set() +nios2_ss.add(files('boot.c', 'cpu_pic.c')) +nios2_ss.add(when: 'CONFIG_NIOS2_10M50', if_true: files('10m50_devboard.c')) +nios2_ss.add(when: 'CONFIG_NIOS2_GENERIC_NOMMU', if_true: files('generic_nommu.c')) + +hw_arch += {'nios2': nios2_ss} diff --git a/hw/nubus/Makefile.objs b/hw/nubus/Makefile.objs deleted file mode 100644 index 135ba7878d469363a5b997eb758c2a634c3da40f..0000000000000000000000000000000000000000 --- a/hw/nubus/Makefile.objs +++ /dev/null @@ -1,4 +0,0 @@ -common-obj-y += nubus-device.o -common-obj-y += nubus-bus.o -common-obj-y += nubus-bridge.o -common-obj-$(CONFIG_Q800) += mac-nubus-bridge.o diff --git a/hw/nubus/meson.build b/hw/nubus/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..9287c633aaeef673455ba1001759cc143c431e90 --- /dev/null +++ b/hw/nubus/meson.build @@ -0,0 +1,7 @@ +nubus_ss = ss.source_set() +nubus_ss.add(files('nubus-device.c')) +nubus_ss.add(files('nubus-bus.c')) +nubus_ss.add(files('nubus-bridge.c')) +nubus_ss.add(when: 'CONFIG_Q800', if_true: files('mac-nubus-bridge.c')) + +softmmu_ss.add_all(when: 'CONFIG_NUBUS', if_true: nubus_ss) diff --git a/hw/nvram/Makefile.objs b/hw/nvram/Makefile.objs deleted file mode 100644 index f3ad921382053dbc666aa2040963c60dedc94a3e..0000000000000000000000000000000000000000 --- a/hw/nvram/Makefile.objs +++ /dev/null @@ -1,8 +0,0 @@ -common-obj-$(CONFIG_DS1225Y) += ds1225y.o -common-obj-$(CONFIG_NMC93XX_EEPROM) += eeprom93xx.o -common-obj-$(CONFIG_AT24C) += eeprom_at24c.o -common-obj-y += fw_cfg.o -common-obj-$(CONFIG_CHRP_NVRAM) += chrp_nvram.o -common-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o -common-obj-$(CONFIG_NRF51_SOC) += nrf51_nvm.o -obj-$(CONFIG_PSERIES) += spapr_nvram.o diff --git a/hw/nvram/chrp_nvram.c b/hw/nvram/chrp_nvram.c index d969f267048e626007d284dcfa72844ddcd61c84..d4d10a7c03c7d0f1cf02275806c81525fd34903c 100644 --- a/hw/nvram/chrp_nvram.c +++ b/hw/nvram/chrp_nvram.c @@ -21,14 +21,21 @@ #include "qemu/osdep.h" #include "qemu/cutils.h" +#include "qemu/error-report.h" #include "hw/nvram/chrp_nvram.h" #include "sysemu/sysemu.h" -static int chrp_nvram_set_var(uint8_t *nvram, int addr, const char *str) +static int chrp_nvram_set_var(uint8_t *nvram, int addr, const char *str, + int max_len) { int len; len = strlen(str) + 1; + + if (max_len < len) { + return -1; + } + memcpy(&nvram[addr], str, len); return addr + len; @@ -38,19 +45,26 @@ static int chrp_nvram_set_var(uint8_t *nvram, int addr, const char *str) * Create a "system partition", used for the Open Firmware * environment variables. */ -int chrp_nvram_create_system_partition(uint8_t *data, int min_len) +int chrp_nvram_create_system_partition(uint8_t *data, int min_len, int max_len) { ChrpNvramPartHdr *part_header; unsigned int i; int end; + if (max_len < sizeof(*part_header)) { + goto fail; + } + part_header = (ChrpNvramPartHdr *)data; part_header->signature = CHRP_NVPART_SYSTEM; pstrcpy(part_header->name, sizeof(part_header->name), "system"); end = sizeof(ChrpNvramPartHdr); for (i = 0; i < nb_prom_envs; i++) { - end = chrp_nvram_set_var(data, end, prom_envs[i]); + end = chrp_nvram_set_var(data, end, prom_envs[i], max_len - end); + if (end == -1) { + goto fail; + } } /* End marker */ @@ -65,6 +79,10 @@ int chrp_nvram_create_system_partition(uint8_t *data, int min_len) chrp_nvram_finish_partition(part_header, end); return end; + +fail: + error_report("NVRAM is too small. Try to pass less data to -prom-env"); + exit(EXIT_FAILURE); } /** diff --git a/hw/nvram/ds1225y.c b/hw/nvram/ds1225y.c index d5cb922287aab2f230b8b6705654cb9fac2c0a86..3660a47c51ca6cb177d9e9293beb431bdd53c0e9 100644 --- a/hw/nvram/ds1225y.c +++ b/hw/nvram/ds1225y.c @@ -29,6 +29,7 @@ #include "trace.h" #include "qemu/error-report.h" #include "qemu/module.h" +#include "qom/object.h" typedef struct { MemoryRegion iomem; @@ -109,13 +110,13 @@ static const VMStateDescription vmstate_nvram = { }; #define TYPE_DS1225Y "ds1225y" -#define DS1225Y(obj) OBJECT_CHECK(SysBusNvRamState, (obj), TYPE_DS1225Y) +OBJECT_DECLARE_SIMPLE_TYPE(SysBusNvRamState, DS1225Y) -typedef struct { +struct SysBusNvRamState { SysBusDevice parent_obj; NvRamState nvram; -} SysBusNvRamState; +}; static void nvram_sysbus_realize(DeviceState *dev, Error **errp) { diff --git a/hw/nvram/eeprom_at24c.c b/hw/nvram/eeprom_at24c.c index d46a2bec3f0355bff83cd845c32be685fabd47eb..3e93dbbffb119959dca53a93085abcf893f76cb3 100644 --- a/hw/nvram/eeprom_at24c.c +++ b/hw/nvram/eeprom_at24c.c @@ -14,6 +14,7 @@ #include "hw/i2c/i2c.h" #include "hw/qdev-properties.h" #include "sysemu/block-backend.h" +#include "qom/object.h" /* #define DEBUG_AT24C */ @@ -27,9 +28,11 @@ ## __VA_ARGS__) #define TYPE_AT24C_EE "at24c-eeprom" -#define AT24C_EE(obj) OBJECT_CHECK(EEPROMState, (obj), TYPE_AT24C_EE) +typedef struct EEPROMState EEPROMState; +DECLARE_INSTANCE_CHECKER(EEPROMState, AT24C_EE, + TYPE_AT24C_EE) -typedef struct EEPROMState { +struct EEPROMState { I2CSlave parent_obj; /* address counter */ @@ -45,7 +48,7 @@ typedef struct EEPROMState { uint8_t *mem; BlockBackend *blk; -} EEPROMState; +}; static int at24c_eeprom_event(I2CSlave *s, enum i2c_event event) diff --git a/hw/nvram/fw_cfg-interface.c b/hw/nvram/fw_cfg-interface.c new file mode 100644 index 0000000000000000000000000000000000000000..0e93feeae5e4987d4aedc34eaa81ebd680388c43 --- /dev/null +++ b/hw/nvram/fw_cfg-interface.c @@ -0,0 +1,23 @@ +/* + * QEMU Firmware configuration device emulation (QOM interfaces) + * + * Copyright 2020 Red Hat, Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/nvram/fw_cfg.h" + +static const TypeInfo fw_cfg_data_generator_interface_info = { + .parent = TYPE_INTERFACE, + .name = TYPE_FW_CFG_DATA_GENERATOR_INTERFACE, + .class_size = sizeof(FWCfgDataGeneratorClass), +}; + +static void fw_cfg_register_interfaces(void) +{ + type_register_static(&fw_cfg_data_generator_interface_info); +} + +type_init(fw_cfg_register_interfaces) diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 8dd50c2c72030412ceec24d9400fb66b5e102cfe..08539a1aabb0a242d960630dd2ecae02e6af1c54 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -1032,6 +1032,35 @@ void *fw_cfg_modify_file(FWCfgState *s, const char *filename, return NULL; } +bool fw_cfg_add_from_generator(FWCfgState *s, const char *filename, + const char *gen_id, Error **errp) +{ + FWCfgDataGeneratorClass *klass; + GByteArray *array; + Object *obj; + gsize size; + + obj = object_resolve_path_component(object_get_objects_root(), gen_id); + if (!obj) { + error_setg(errp, "Cannot find object ID '%s'", gen_id); + return false; + } + if (!object_dynamic_cast(obj, TYPE_FW_CFG_DATA_GENERATOR_INTERFACE)) { + error_setg(errp, "Object ID '%s' is not a '%s' subclass", + gen_id, TYPE_FW_CFG_DATA_GENERATOR_INTERFACE); + return false; + } + klass = FW_CFG_DATA_GENERATOR_GET_CLASS(obj); + array = klass->get_data(obj, errp); + if (!array) { + return false; + } + size = array->len; + fw_cfg_add_file(s, filename, g_byte_array_free(array, FALSE), size); + + return true; +} + static void fw_cfg_machine_reset(void *opaque) { MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); @@ -1099,16 +1128,16 @@ FWCfgState *fw_cfg_init_io_dma(uint32_t iobase, uint32_t dma_iobase, FWCfgState *s; bool dma_requested = dma_iobase && dma_as; - dev = qdev_create(NULL, TYPE_FW_CFG_IO); + dev = qdev_new(TYPE_FW_CFG_IO); if (!dma_requested) { qdev_prop_set_bit(dev, "dma_enabled", false); } object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG, OBJECT(dev)); - qdev_init_nofail(dev); sbd = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sbd, &error_fatal); ios = FW_CFG_IO(dev); sysbus_add_io(sbd, iobase, &ios->comb_iomem); @@ -1138,7 +1167,7 @@ FWCfgState *fw_cfg_init_mem_wide(hwaddr ctl_addr, FWCfgState *s; bool dma_requested = dma_addr && dma_as; - dev = qdev_create(NULL, TYPE_FW_CFG_MEM); + dev = qdev_new(TYPE_FW_CFG_MEM); qdev_prop_set_uint32(dev, "data_width", data_width); if (!dma_requested) { qdev_prop_set_bit(dev, "dma_enabled", false); @@ -1146,9 +1175,9 @@ FWCfgState *fw_cfg_init_mem_wide(hwaddr ctl_addr, object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG, OBJECT(dev)); - qdev_init_nofail(dev); sbd = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sbd, &error_fatal); sysbus_mmio_map(sbd, 0, ctl_addr); sysbus_mmio_map(sbd, 1, data_addr); @@ -1231,12 +1260,11 @@ static Property fw_cfg_io_properties[] = { static void fw_cfg_io_realize(DeviceState *dev, Error **errp) { + ERRP_GUARD(); FWCfgIoState *s = FW_CFG_IO(dev); - Error *local_err = NULL; - fw_cfg_file_slots_allocate(FW_CFG(s), &local_err); - if (local_err) { - error_propagate(errp, local_err); + fw_cfg_file_slots_allocate(FW_CFG(s), errp); + if (*errp) { return; } @@ -1282,14 +1310,13 @@ static Property fw_cfg_mem_properties[] = { static void fw_cfg_mem_realize(DeviceState *dev, Error **errp) { + ERRP_GUARD(); FWCfgMemState *s = FW_CFG_MEM(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); const MemoryRegionOps *data_ops = &fw_cfg_data_mem_ops; - Error *local_err = NULL; - fw_cfg_file_slots_allocate(FW_CFG(s), &local_err); - if (local_err) { - error_propagate(errp, local_err); + fw_cfg_file_slots_allocate(FW_CFG(s), errp); + if (*errp) { return; } @@ -1333,7 +1360,6 @@ static const TypeInfo fw_cfg_mem_info = { .class_init = fw_cfg_mem_class_init, }; - static void fw_cfg_register_types(void) { type_register_static(&fw_cfg_info); diff --git a/hw/nvram/mac_nvram.c b/hw/nvram/mac_nvram.c index ff5db03e6be258ee40ce964be0f90c3bff38a050..11f2d31cdb2024e55cf1f8ab7bd2d34ea785bd18 100644 --- a/hw/nvram/mac_nvram.c +++ b/hw/nvram/mac_nvram.c @@ -30,18 +30,9 @@ #include "migration/vmstate.h" #include "qemu/cutils.h" #include "qemu/module.h" +#include "trace.h" #include -/* debug NVR */ -//#define DEBUG_NVR - -#ifdef DEBUG_NVR -#define NVR_DPRINTF(fmt, ...) \ - do { printf("NVR: " fmt , ## __VA_ARGS__); } while (0) -#else -#define NVR_DPRINTF(fmt, ...) -#endif - #define DEF_SYSTEM_SIZE 0xc10 /* macio style NVRAM device */ @@ -51,9 +42,8 @@ static void macio_nvram_writeb(void *opaque, hwaddr addr, MacIONVRAMState *s = opaque; addr = (addr >> s->it_shift) & (s->size - 1); + trace_macio_nvram_write(addr, value); s->data[addr] = value; - NVR_DPRINTF("writeb addr %04" HWADDR_PRIx " val %" PRIx64 "\n", - addr, value); } static uint64_t macio_nvram_readb(void *opaque, hwaddr addr, @@ -64,8 +54,7 @@ static uint64_t macio_nvram_readb(void *opaque, hwaddr addr, addr = (addr >> s->it_shift) & (s->size - 1); value = s->data[addr]; - NVR_DPRINTF("readb addr %04" HWADDR_PRIx " val %" PRIx32 "\n", - addr, value); + trace_macio_nvram_read(addr, value); return value; } @@ -152,7 +141,7 @@ static void pmac_format_nvram_partition_of(MacIONVRAMState *nvr, int off, /* OpenBIOS nvram variables partition */ sysp_end = chrp_nvram_create_system_partition(&nvr->data[off], - DEF_SYSTEM_SIZE) + off; + DEF_SYSTEM_SIZE, len) + off; /* Free space partition */ chrp_nvram_create_free_partition(&nvr->data[sysp_end], len - sysp_end); diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..fd2951a860f4e089cb0b835776c191b9b4b19ca4 --- /dev/null +++ b/hw/nvram/meson.build @@ -0,0 +1,13 @@ +# QOM interfaces must be available anytime QOM is used. +qom_ss.add(files('fw_cfg-interface.c')) + +softmmu_ss.add(files('fw_cfg.c')) +softmmu_ss.add(when: 'CONFIG_CHRP_NVRAM', if_true: files('chrp_nvram.c')) +softmmu_ss.add(when: 'CONFIG_DS1225Y', if_true: files('ds1225y.c')) +softmmu_ss.add(when: 'CONFIG_NMC93XX_EEPROM', if_true: files('eeprom93xx.c')) +softmmu_ss.add(when: 'CONFIG_AT24C', if_true: files('eeprom_at24c.c')) +softmmu_ss.add(when: 'CONFIG_MAC_NVRAM', if_true: files('mac_nvram.c')) +softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_otp.c')) +softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c')) + +specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c')) diff --git a/hw/nvram/npcm7xx_otp.c b/hw/nvram/npcm7xx_otp.c new file mode 100644 index 0000000000000000000000000000000000000000..b16ca530baaa4371a13dd84c6afe1a7857c2e4d1 --- /dev/null +++ b/hw/nvram/npcm7xx_otp.c @@ -0,0 +1,440 @@ +/* + * Nuvoton NPCM7xx OTP (Fuse Array) Interface + * + * Copyright 2020 Google LLC + * + * 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. + */ + +#include "qemu/osdep.h" + +#include "hw/nvram/npcm7xx_otp.h" +#include "migration/vmstate.h" +#include "qapi/error.h" +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/units.h" + +/* Each module has 4 KiB of register space. Only a fraction of it is used. */ +#define NPCM7XX_OTP_REGS_SIZE (4 * KiB) + +/* 32-bit register indices. */ +typedef enum NPCM7xxOTPRegister { + NPCM7XX_OTP_FST, + NPCM7XX_OTP_FADDR, + NPCM7XX_OTP_FDATA, + NPCM7XX_OTP_FCFG, + /* Offset 0x10 is FKEYIND in OTP1, FUSTRAP in OTP2 */ + NPCM7XX_OTP_FKEYIND = 0x0010 / sizeof(uint32_t), + NPCM7XX_OTP_FUSTRAP = 0x0010 / sizeof(uint32_t), + NPCM7XX_OTP_FCTL, + NPCM7XX_OTP_REGS_END, +} NPCM7xxOTPRegister; + +/* Register field definitions. */ +#define FST_RIEN BIT(2) +#define FST_RDST BIT(1) +#define FST_RDY BIT(0) +#define FST_RO_MASK (FST_RDST | FST_RDY) + +#define FADDR_BYTEADDR(rv) extract32((rv), 0, 10) +#define FADDR_BITPOS(rv) extract32((rv), 10, 3) + +#define FDATA_CLEAR 0x00000001 + +#define FCFG_FDIS BIT(31) +#define FCFG_FCFGLK_MASK 0x00ff0000 + +#define FCTL_PROG_CMD1 0x00000001 +#define FCTL_PROG_CMD2 0xbf79e5d0 +#define FCTL_READ_CMD 0x00000002 + +/** + * struct NPCM7xxOTPClass - OTP module class. + * @parent: System bus device class. + * @mmio_ops: MMIO register operations for this type of module. + * + * The two OTP modules (key-storage and fuse-array) have slightly different + * behavior, so we give them different MMIO register operations. + */ +struct NPCM7xxOTPClass { + SysBusDeviceClass parent; + + const MemoryRegionOps *mmio_ops; +}; + +#define NPCM7XX_OTP_CLASS(klass) \ + OBJECT_CLASS_CHECK(NPCM7xxOTPClass, (klass), TYPE_NPCM7XX_OTP) +#define NPCM7XX_OTP_GET_CLASS(obj) \ + OBJECT_GET_CLASS(NPCM7xxOTPClass, (obj), TYPE_NPCM7XX_OTP) + +static uint8_t ecc_encode_nibble(uint8_t n) +{ + uint8_t result = n; + + result |= (((n >> 0) & 1) ^ ((n >> 1) & 1)) << 4; + result |= (((n >> 2) & 1) ^ ((n >> 3) & 1)) << 5; + result |= (((n >> 0) & 1) ^ ((n >> 2) & 1)) << 6; + result |= (((n >> 1) & 1) ^ ((n >> 3) & 1)) << 7; + + return result; +} + +void npcm7xx_otp_array_write(NPCM7xxOTPState *s, const void *data, + unsigned int offset, unsigned int len) +{ + const uint8_t *src = data; + uint8_t *dst = &s->array[offset]; + + while (len-- > 0) { + uint8_t c = *src++; + + *dst++ = ecc_encode_nibble(extract8(c, 0, 4)); + *dst++ = ecc_encode_nibble(extract8(c, 4, 4)); + } +} + +/* Common register read handler for both OTP classes. */ +static uint64_t npcm7xx_otp_read(NPCM7xxOTPState *s, NPCM7xxOTPRegister reg) +{ + uint32_t value = 0; + + switch (reg) { + case NPCM7XX_OTP_FST: + case NPCM7XX_OTP_FADDR: + case NPCM7XX_OTP_FDATA: + case NPCM7XX_OTP_FCFG: + value = s->regs[reg]; + break; + + case NPCM7XX_OTP_FCTL: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: read from write-only FCTL register\n", + DEVICE(s)->canonical_path); + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: read from invalid offset 0x%zx\n", + DEVICE(s)->canonical_path, reg * sizeof(uint32_t)); + break; + } + + return value; +} + +/* Read a byte from the OTP array into the data register. */ +static void npcm7xx_otp_read_array(NPCM7xxOTPState *s) +{ + uint32_t faddr = s->regs[NPCM7XX_OTP_FADDR]; + + s->regs[NPCM7XX_OTP_FDATA] = s->array[FADDR_BYTEADDR(faddr)]; + s->regs[NPCM7XX_OTP_FST] |= FST_RDST | FST_RDY; +} + +/* Program a byte from the data register into the OTP array. */ +static void npcm7xx_otp_program_array(NPCM7xxOTPState *s) +{ + uint32_t faddr = s->regs[NPCM7XX_OTP_FADDR]; + + /* Bits can only go 0->1, never 1->0. */ + s->array[FADDR_BYTEADDR(faddr)] |= (1U << FADDR_BITPOS(faddr)); + s->regs[NPCM7XX_OTP_FST] |= FST_RDST | FST_RDY; +} + +/* Compute the next value of the FCFG register. */ +static uint32_t npcm7xx_otp_compute_fcfg(uint32_t cur_value, uint32_t new_value) +{ + uint32_t lock_mask; + uint32_t value; + + /* + * FCFGLK holds sticky bits 16..23, indicating which bits in FPRGLK (8..15) + * and FRDLK (0..7) that are read-only. + */ + lock_mask = (cur_value & FCFG_FCFGLK_MASK) >> 8; + lock_mask |= lock_mask >> 8; + /* FDIS and FCFGLK bits are sticky (write 1 to set; can't clear). */ + value = cur_value & (FCFG_FDIS | FCFG_FCFGLK_MASK); + /* Preserve read-only bits in FPRGLK and FRDLK */ + value |= cur_value & lock_mask; + /* Set all bits that aren't read-only. */ + value |= new_value & ~lock_mask; + + return value; +} + +/* Common register write handler for both OTP classes. */ +static void npcm7xx_otp_write(NPCM7xxOTPState *s, NPCM7xxOTPRegister reg, + uint32_t value) +{ + switch (reg) { + case NPCM7XX_OTP_FST: + /* RDST is cleared by writing 1 to it. */ + if (value & FST_RDST) { + s->regs[NPCM7XX_OTP_FST] &= ~FST_RDST; + } + /* Preserve read-only and write-one-to-clear bits */ + value &= ~FST_RO_MASK; + value |= s->regs[NPCM7XX_OTP_FST] & FST_RO_MASK; + break; + + case NPCM7XX_OTP_FADDR: + break; + + case NPCM7XX_OTP_FDATA: + /* + * This register is cleared by writing a magic value to it; no other + * values can be written. + */ + if (value == FDATA_CLEAR) { + value = 0; + } else { + value = s->regs[NPCM7XX_OTP_FDATA]; + } + break; + + case NPCM7XX_OTP_FCFG: + value = npcm7xx_otp_compute_fcfg(s->regs[NPCM7XX_OTP_FCFG], value); + break; + + case NPCM7XX_OTP_FCTL: + switch (value) { + case FCTL_READ_CMD: + npcm7xx_otp_read_array(s); + break; + + case FCTL_PROG_CMD1: + /* + * Programming requires writing two separate magic values to this + * register; this is the first one. Just store it so it can be + * verified later when the second magic value is received. + */ + break; + + case FCTL_PROG_CMD2: + /* + * Only initiate programming if we received the first half of the + * command immediately before this one. + */ + if (s->regs[NPCM7XX_OTP_FCTL] == FCTL_PROG_CMD1) { + npcm7xx_otp_program_array(s); + } + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: unrecognized FCNTL value 0x%" PRIx32 "\n", + DEVICE(s)->canonical_path, value); + break; + } + if (value != FCTL_PROG_CMD1) { + value = 0; + } + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: write to invalid offset 0x%zx\n", + DEVICE(s)->canonical_path, reg * sizeof(uint32_t)); + return; + } + + s->regs[reg] = value; +} + +/* Register read handler specific to the fuse array OTP module. */ +static uint64_t npcm7xx_fuse_array_read(void *opaque, hwaddr addr, + unsigned int size) +{ + NPCM7xxOTPRegister reg = addr / sizeof(uint32_t); + NPCM7xxOTPState *s = opaque; + uint32_t value; + + /* + * Only the Fuse Strap register needs special handling; all other registers + * work the same way for both kinds of OTP modules. + */ + if (reg != NPCM7XX_OTP_FUSTRAP) { + value = npcm7xx_otp_read(s, reg); + } else { + /* FUSTRAP is stored as three copies in the OTP array. */ + uint32_t fustrap[3]; + + memcpy(fustrap, &s->array[0], sizeof(fustrap)); + + /* Determine value by a majority vote on each bit. */ + value = (fustrap[0] & fustrap[1]) | (fustrap[0] & fustrap[2]) | + (fustrap[1] & fustrap[2]); + } + + return value; +} + +/* Register write handler specific to the fuse array OTP module. */ +static void npcm7xx_fuse_array_write(void *opaque, hwaddr addr, uint64_t v, + unsigned int size) +{ + NPCM7xxOTPRegister reg = addr / sizeof(uint32_t); + NPCM7xxOTPState *s = opaque; + + /* + * The Fuse Strap register is read-only. Other registers are handled by + * common code. + */ + if (reg != NPCM7XX_OTP_FUSTRAP) { + npcm7xx_otp_write(s, reg, v); + } +} + +static const MemoryRegionOps npcm7xx_fuse_array_ops = { + .read = npcm7xx_fuse_array_read, + .write = npcm7xx_fuse_array_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + .unaligned = false, + }, +}; + +/* Register read handler specific to the key storage OTP module. */ +static uint64_t npcm7xx_key_storage_read(void *opaque, hwaddr addr, + unsigned int size) +{ + NPCM7xxOTPRegister reg = addr / sizeof(uint32_t); + NPCM7xxOTPState *s = opaque; + + /* + * Only the Fuse Key Index register needs special handling; all other + * registers work the same way for both kinds of OTP modules. + */ + if (reg != NPCM7XX_OTP_FKEYIND) { + return npcm7xx_otp_read(s, reg); + } + + qemu_log_mask(LOG_UNIMP, "%s: FKEYIND is not implemented\n", __func__); + + return s->regs[NPCM7XX_OTP_FKEYIND]; +} + +/* Register write handler specific to the key storage OTP module. */ +static void npcm7xx_key_storage_write(void *opaque, hwaddr addr, uint64_t v, + unsigned int size) +{ + NPCM7xxOTPRegister reg = addr / sizeof(uint32_t); + NPCM7xxOTPState *s = opaque; + + /* + * Only the Fuse Key Index register needs special handling; all other + * registers work the same way for both kinds of OTP modules. + */ + if (reg != NPCM7XX_OTP_FKEYIND) { + npcm7xx_otp_write(s, reg, v); + return; + } + + qemu_log_mask(LOG_UNIMP, "%s: FKEYIND is not implemented\n", __func__); + + s->regs[NPCM7XX_OTP_FKEYIND] = v; +} + +static const MemoryRegionOps npcm7xx_key_storage_ops = { + .read = npcm7xx_key_storage_read, + .write = npcm7xx_key_storage_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + .unaligned = false, + }, +}; + +static void npcm7xx_otp_enter_reset(Object *obj, ResetType type) +{ + NPCM7xxOTPState *s = NPCM7XX_OTP(obj); + + memset(s->regs, 0, sizeof(s->regs)); + + s->regs[NPCM7XX_OTP_FST] = 0x00000001; + s->regs[NPCM7XX_OTP_FCFG] = 0x20000000; +} + +static void npcm7xx_otp_realize(DeviceState *dev, Error **errp) +{ + NPCM7xxOTPClass *oc = NPCM7XX_OTP_GET_CLASS(dev); + NPCM7xxOTPState *s = NPCM7XX_OTP(dev); + SysBusDevice *sbd = &s->parent; + + memset(s->array, 0, sizeof(s->array)); + + memory_region_init_io(&s->mmio, OBJECT(s), oc->mmio_ops, s, "regs", + NPCM7XX_OTP_REGS_SIZE); + sysbus_init_mmio(sbd, &s->mmio); +} + +static const VMStateDescription vmstate_npcm7xx_otp = { + .name = "npcm7xx-otp", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, NPCM7xxOTPState, NPCM7XX_OTP_NR_REGS), + VMSTATE_UINT8_ARRAY(array, NPCM7xxOTPState, NPCM7XX_OTP_ARRAY_BYTES), + VMSTATE_END_OF_LIST(), + }, +}; + +static void npcm7xx_otp_class_init(ObjectClass *klass, void *data) +{ + ResettableClass *rc = RESETTABLE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + QEMU_BUILD_BUG_ON(NPCM7XX_OTP_REGS_END > NPCM7XX_OTP_NR_REGS); + + dc->realize = npcm7xx_otp_realize; + dc->vmsd = &vmstate_npcm7xx_otp; + rc->phases.enter = npcm7xx_otp_enter_reset; +} + +static void npcm7xx_key_storage_class_init(ObjectClass *klass, void *data) +{ + NPCM7xxOTPClass *oc = NPCM7XX_OTP_CLASS(klass); + + oc->mmio_ops = &npcm7xx_key_storage_ops; +} + +static void npcm7xx_fuse_array_class_init(ObjectClass *klass, void *data) +{ + NPCM7xxOTPClass *oc = NPCM7XX_OTP_CLASS(klass); + + oc->mmio_ops = &npcm7xx_fuse_array_ops; +} + +static const TypeInfo npcm7xx_otp_types[] = { + { + .name = TYPE_NPCM7XX_OTP, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(NPCM7xxOTPState), + .class_size = sizeof(NPCM7xxOTPClass), + .class_init = npcm7xx_otp_class_init, + .abstract = true, + }, + { + .name = TYPE_NPCM7XX_KEY_STORAGE, + .parent = TYPE_NPCM7XX_OTP, + .class_init = npcm7xx_key_storage_class_init, + }, + { + .name = TYPE_NPCM7XX_FUSE_ARRAY, + .parent = TYPE_NPCM7XX_OTP, + .class_init = npcm7xx_fuse_array_class_init, + }, +}; +DEFINE_TYPES(npcm7xx_otp_types); diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c index 15d08281d411db8c2c14fa1549e978334e93286d..fc53a425721853ac18bfd4e833439a53fdd7fd21 100644 --- a/hw/nvram/spapr_nvram.c +++ b/hw/nvram/spapr_nvram.c @@ -39,18 +39,18 @@ #include "hw/ppc/spapr.h" #include "hw/ppc/spapr_vio.h" #include "hw/qdev-properties.h" +#include "qom/object.h" -typedef struct SpaprNvram { +struct SpaprNvram { SpaprVioDevice sdev; uint32_t size; uint8_t *buf; BlockBackend *blk; VMChangeStateEntry *vmstate; -} SpaprNvram; +}; #define TYPE_VIO_SPAPR_NVRAM "spapr-nvram" -#define VIO_SPAPR_NVRAM(obj) \ - OBJECT_CHECK(SpaprNvram, (obj), TYPE_VIO_SPAPR_NVRAM) +OBJECT_DECLARE_SIMPLE_TYPE(SpaprNvram, VIO_SPAPR_NVRAM) #define MIN_NVRAM_SIZE (8 * KiB) #define DEFAULT_NVRAM_SIZE (64 * KiB) @@ -188,7 +188,8 @@ static void spapr_nvram_realize(SpaprVioDevice *dev, Error **errp) } } else if (nb_prom_envs > 0) { /* Create a system partition to pass the -prom-env variables */ - chrp_nvram_create_system_partition(nvram->buf, MIN_NVRAM_SIZE / 4); + chrp_nvram_create_system_partition(nvram->buf, MIN_NVRAM_SIZE / 4, + nvram->size); chrp_nvram_create_free_partition(&nvram->buf[MIN_NVRAM_SIZE / 4], nvram->size - MIN_NVRAM_SIZE / 4); } diff --git a/hw/nvram/trace-events b/hw/nvram/trace-events index 0dea9260ce1e3d5c463adde265220feb3c8db75e..e0231932959bd3c25564b4f5f84f851ebf344cdf 100644 --- a/hw/nvram/trace-events +++ b/hw/nvram/trace-events @@ -13,3 +13,7 @@ fw_cfg_add_string(uint16_t key_value, const char *key_name, const char *value) " fw_cfg_add_i16(uint16_t key_value, const char *key_name, uint16_t value) "key 0x%04" PRIx16 " '%s', value 0x%" PRIx16 fw_cfg_add_i32(uint16_t key_value, const char *key_name, uint32_t value) "key 0x%04" PRIx16 " '%s', value 0x%" PRIx32 fw_cfg_add_i64(uint16_t key_value, const char *key_name, uint64_t value) "key 0x%04" PRIx16 " '%s', value 0x%" PRIx64 + +# mac_nvram.c +macio_nvram_read(uint32_t addr, uint8_t val) "read addr=0x%04"PRIx32" val=0x%02x" +macio_nvram_write(uint32_t addr, uint8_t val) "write addr=0x%04"PRIx32" val=0x%02x" diff --git a/hw/nvram/trace.h b/hw/nvram/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..88fa900ad3c971b3719c1149618bedde6f414646 --- /dev/null +++ b/hw/nvram/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_nvram.h" diff --git a/hw/openrisc/Makefile.objs b/hw/openrisc/Makefile.objs deleted file mode 100644 index aa04de7f5a6573aaf376e710eced2a4fea63e94c..0000000000000000000000000000000000000000 --- a/hw/openrisc/Makefile.objs +++ /dev/null @@ -1,2 +0,0 @@ -obj-y = pic_cpu.o cputimer.o -obj-$(CONFIG_OR1K_SIM) += openrisc_sim.o diff --git a/hw/openrisc/meson.build b/hw/openrisc/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..57c42558e18bbb60c6ba5ce4f921c0e5619c2da8 --- /dev/null +++ b/hw/openrisc/meson.build @@ -0,0 +1,5 @@ +openrisc_ss = ss.source_set() +openrisc_ss.add(files('pic_cpu.c', 'cputimer.c')) +openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: files('openrisc_sim.c')) + +hw_arch += {'openrisc': openrisc_ss} diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c index d08ce6181199aa1e75a7c5bc215710ce7b152c86..d752282e675f01015b95575287b10e1ad06d47b7 100644 --- a/hw/openrisc/openrisc_sim.c +++ b/hw/openrisc/openrisc_sim.c @@ -59,11 +59,11 @@ static void openrisc_sim_net_init(hwaddr base, hwaddr descriptors, SysBusDevice *s; int i; - dev = qdev_create(NULL, "open_eth"); + dev = qdev_new("open_eth"); qdev_set_nic_properties(dev, nd); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); for (i = 0; i < num_cpus; i++) { sysbus_connect_irq(s, 0, cpu_irqs[i][irq_pin]); } @@ -78,11 +78,11 @@ static void openrisc_sim_ompic_init(hwaddr base, int num_cpus, SysBusDevice *s; int i; - dev = qdev_create(NULL, "or1k-ompic"); + dev = qdev_new("or1k-ompic"); qdev_prop_set_uint32(dev, "num-cpus", num_cpus); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); for (i = 0; i < num_cpus; i++) { sysbus_connect_irq(s, i, cpu_irqs[i][irq_pin]); } @@ -134,6 +134,7 @@ static void openrisc_sim_init(MachineState *machine) int n; unsigned int smp_cpus = machine->smp.cpus; + assert(smp_cpus >= 1 && smp_cpus <= 2); for (n = 0; n < smp_cpus; n++) { cpu = OPENRISC_CPU(cpu_create(machine->cpu_type)); if (cpu == NULL) { diff --git a/hw/pci-bridge/Makefile.objs b/hw/pci-bridge/Makefile.objs deleted file mode 100644 index 47065f87d9bf31f7de764ce798a2cb7f234f84cd..0000000000000000000000000000000000000000 --- a/hw/pci-bridge/Makefile.objs +++ /dev/null @@ -1,10 +0,0 @@ -common-obj-y += pci_bridge_dev.o -common-obj-$(CONFIG_PCIE_PORT) += pcie_root_port.o gen_pcie_root_port.o pcie_pci_bridge.o -common-obj-$(CONFIG_PXB) += pci_expander_bridge.o -common-obj-$(CONFIG_XIO3130) += xio3130_upstream.o xio3130_downstream.o -common-obj-$(CONFIG_IOH3420) += ioh3420.o -common-obj-$(CONFIG_I82801B11) += i82801b11.o -# NewWorld PowerMac -common-obj-$(CONFIG_DEC_PCI) += dec.o -# Sun4u -common-obj-$(CONFIG_SIMBA) += simba.o diff --git a/hw/pci-bridge/dec.c b/hw/pci-bridge/dec.c index 3ae2f788a4ec0cc01326235f2e9e563538fa96ad..4773d07e6d5808837ac4236081a111b9e56c36c5 100644 --- a/hw/pci-bridge/dec.c +++ b/hw/pci-bridge/dec.c @@ -26,27 +26,19 @@ #include "qemu/osdep.h" #include "dec.h" #include "hw/sysbus.h" +#include "qapi/error.h" #include "qemu/module.h" #include "hw/pci/pci.h" #include "hw/pci/pci_host.h" #include "hw/pci/pci_bridge.h" #include "hw/pci/pci_bus.h" +#include "qom/object.h" -/* debug DEC */ -//#define DEBUG_DEC +OBJECT_DECLARE_SIMPLE_TYPE(DECState, DEC_21154) -#ifdef DEBUG_DEC -#define DEC_DPRINTF(fmt, ...) \ - do { printf("DEC: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DEC_DPRINTF(fmt, ...) -#endif - -#define DEC_21154(obj) OBJECT_CHECK(DECState, (obj), TYPE_DEC_21154) - -typedef struct DECState { +struct DECState { PCIHostState parent_obj; -} DECState; +}; static int dec_map_irq(PCIDevice *pci_dev, int irq_num) { @@ -91,11 +83,10 @@ PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn) PCIDevice *dev; PCIBridge *br; - dev = pci_create_multifunction(parent_bus, devfn, false, - "dec-21154-p2p-bridge"); + dev = pci_new_multifunction(devfn, false, "dec-21154-p2p-bridge"); br = PCI_BRIDGE(dev); pci_bridge_map_irq(br, "DEC 21154 PCI-PCI bridge", dec_map_irq); - qdev_init_nofail(&dev->qdev); + pci_realize_and_unref(dev, parent_bus, &error_fatal); return pci_bridge_get_sec_bus(br); } diff --git a/hw/pci-bridge/gen_pcie_root_port.c b/hw/pci-bridge/gen_pcie_root_port.c index bb26e272c1189639ab8d5bbf69b134320a2c55fb..8931afc04925f11626d86bec21435df8eb723b6a 100644 --- a/hw/pci-bridge/gen_pcie_root_port.c +++ b/hw/pci-bridge/gen_pcie_root_port.c @@ -17,10 +17,10 @@ #include "hw/pci/pcie_port.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" +#include "qom/object.h" #define TYPE_GEN_PCIE_ROOT_PORT "pcie-root-port" -#define GEN_PCIE_ROOT_PORT(obj) \ - OBJECT_CHECK(GenPCIERootPort, (obj), TYPE_GEN_PCIE_ROOT_PORT) +OBJECT_DECLARE_SIMPLE_TYPE(GenPCIERootPort, GEN_PCIE_ROOT_PORT) #define GEN_PCIE_ROOT_PORT_AER_OFFSET 0x100 #define GEN_PCIE_ROOT_PORT_ACS_OFFSET \ @@ -28,7 +28,7 @@ #define GEN_PCIE_ROOT_PORT_MSIX_NR_VECTOR 1 -typedef struct GenPCIERootPort { +struct GenPCIERootPort { /*< private >*/ PCIESlot parent_obj; /*< public >*/ @@ -37,7 +37,7 @@ typedef struct GenPCIERootPort { /* additional resources to reserve */ PCIResReserve res_reserve; -} GenPCIERootPort; +}; static uint8_t gen_rp_aer_vector(const PCIDevice *d) { diff --git a/hw/pci-bridge/i82801b11.c b/hw/pci-bridge/i82801b11.c index 2b3907655b9688e645dccf2fc41cc8d75556cd0f..f28181e2101c5c99b977ec2fd5e7d031670541d3 100644 --- a/hw/pci-bridge/i82801b11.c +++ b/hw/pci-bridge/i82801b11.c @@ -30,7 +30,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/pci-bridge/meson.build b/hw/pci-bridge/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..daab8acf2aae19b7e42263f265fc9b0880126fea --- /dev/null +++ b/hw/pci-bridge/meson.build @@ -0,0 +1,14 @@ +pci_ss = ss.source_set() +pci_ss.add(files('pci_bridge_dev.c')) +pci_ss.add(when: 'CONFIG_I82801B11', if_true: files('i82801b11.c')) +pci_ss.add(when: 'CONFIG_IOH3420', if_true: files('ioh3420.c')) +pci_ss.add(when: 'CONFIG_PCIE_PORT', if_true: files('pcie_root_port.c', 'gen_pcie_root_port.c', 'pcie_pci_bridge.c')) +pci_ss.add(when: 'CONFIG_PXB', if_true: files('pci_expander_bridge.c')) +pci_ss.add(when: 'CONFIG_XIO3130', if_true: files('xio3130_upstream.c', 'xio3130_downstream.c')) + +# NewWorld PowerMac +pci_ss.add(when: 'CONFIG_DEC_PCI', if_true: files('dec.c')) +# Sun4u +pci_ss.add(when: 'CONFIG_SIMBA', if_true: files('simba.c')) + +softmmu_ss.add_all(when: 'CONFIG_PCI', if_true: pci_ss) diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c index 4a080b7c7bfbf1981413e54ce5973c24c0dbb08b..657a06ddbe81b83f1a66e58e840cdcdb7a14e9dd 100644 --- a/hw/pci-bridge/pci_bridge_dev.c +++ b/hw/pci-bridge/pci_bridge_dev.c @@ -31,11 +31,11 @@ #include "exec/memory.h" #include "hw/pci/pci_bus.h" #include "hw/hotplug.h" +#include "qom/object.h" #define TYPE_PCI_BRIDGE_DEV "pci-bridge" #define TYPE_PCI_BRIDGE_SEAT_DEV "pci-bridge-seat" -#define PCI_BRIDGE_DEV(obj) \ - OBJECT_CHECK(PCIBridgeDev, (obj), TYPE_PCI_BRIDGE_DEV) +OBJECT_DECLARE_SIMPLE_TYPE(PCIBridgeDev, PCI_BRIDGE_DEV) struct PCIBridgeDev { /*< private >*/ @@ -52,7 +52,6 @@ struct PCIBridgeDev { /* additional resources to reserve */ PCIResReserve res_reserve; }; -typedef struct PCIBridgeDev PCIBridgeDev; static void pci_bridge_dev_realize(PCIDevice *dev, Error **errp) { diff --git a/hw/pci-bridge/pci_expander_bridge.c b/hw/pci-bridge/pci_expander_bridge.c index 47aaaf8fd1b2459012657a207f8216fc5233a138..aedded106422c9cbd6e409e9ef7efe72de0a288c 100644 --- a/hw/pci-bridge/pci_expander_bridge.c +++ b/hw/pci-bridge/pci_expander_bridge.c @@ -22,35 +22,42 @@ #include "qemu/module.h" #include "sysemu/numa.h" #include "hw/boards.h" +#include "qom/object.h" #define TYPE_PXB_BUS "pxb-bus" -#define PXB_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_BUS) +typedef struct PXBBus PXBBus; +DECLARE_INSTANCE_CHECKER(PXBBus, PXB_BUS, + TYPE_PXB_BUS) #define TYPE_PXB_PCIE_BUS "pxb-pcie-bus" -#define PXB_PCIE_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_PCIE_BUS) +DECLARE_INSTANCE_CHECKER(PXBBus, PXB_PCIE_BUS, + TYPE_PXB_PCIE_BUS) -typedef struct PXBBus { +struct PXBBus { /*< private >*/ PCIBus parent_obj; /*< public >*/ char bus_path[8]; -} PXBBus; +}; #define TYPE_PXB_DEVICE "pxb" -#define PXB_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_DEVICE) +typedef struct PXBDev PXBDev; +DECLARE_INSTANCE_CHECKER(PXBDev, PXB_DEV, + TYPE_PXB_DEVICE) #define TYPE_PXB_PCIE_DEVICE "pxb-pcie" -#define PXB_PCIE_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_PCIE_DEVICE) +DECLARE_INSTANCE_CHECKER(PXBDev, PXB_PCIE_DEV, + TYPE_PXB_PCIE_DEVICE) -typedef struct PXBDev { +struct PXBDev { /*< private >*/ PCIDevice parent_obj; /*< public >*/ uint8_t bus_nr; uint16_t numa_node; -} PXBDev; +}; static PXBDev *convert_to_pxb(PCIDevice *dev) { @@ -231,12 +238,12 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool pcie, Error **errp) dev_name = dev->qdev.id; } - ds = qdev_create(NULL, TYPE_PXB_HOST); + ds = qdev_new(TYPE_PXB_HOST); if (pcie) { bus = pci_root_bus_new(ds, dev_name, NULL, NULL, 0, TYPE_PXB_PCIE_BUS); } else { bus = pci_root_bus_new(ds, "pxb-internal", NULL, NULL, 0, TYPE_PXB_BUS); - bds = qdev_create(BUS(bus), "pci-bridge"); + bds = qdev_new("pci-bridge"); bds->id = dev_name; qdev_prop_set_uint8(bds, PCI_BRIDGE_DEV_PROP_CHASSIS_NR, pxb->bus_nr); qdev_prop_set_bit(bds, PCI_BRIDGE_DEV_PROP_SHPC, false); @@ -255,9 +262,9 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool pcie, Error **errp) goto err_register_bus; } - qdev_init_nofail(ds); + sysbus_realize_and_unref(SYS_BUS_DEVICE(ds), &error_fatal); if (bds) { - qdev_init_nofail(bds); + qdev_realize_and_unref(bds, &bus->qbus, &error_fatal); } pci_word_test_and_set_mask(dev->config + PCI_STATUS, diff --git a/hw/pci-bridge/pcie_pci_bridge.c b/hw/pci-bridge/pcie_pci_bridge.c index eade133968c85badf36dc6ff1651a1aa137531a9..1cd917a459741fedff798129027f24950a64e9b0 100644 --- a/hw/pci-bridge/pcie_pci_bridge.c +++ b/hw/pci-bridge/pcie_pci_bridge.c @@ -17,19 +17,19 @@ #include "hw/pci/shpc.h" #include "hw/pci/slotid_cap.h" #include "hw/qdev-properties.h" +#include "qom/object.h" -typedef struct PCIEPCIBridge { +struct PCIEPCIBridge { /*< private >*/ PCIBridge parent_obj; OnOffAuto msi; MemoryRegion shpc_bar; /*< public >*/ -} PCIEPCIBridge; +}; #define TYPE_PCIE_PCI_BRIDGE_DEV "pcie-pci-bridge" -#define PCIE_PCI_BRIDGE_DEV(obj) \ - OBJECT_CHECK(PCIEPCIBridge, (obj), TYPE_PCIE_PCI_BRIDGE_DEV) +OBJECT_DECLARE_SIMPLE_TYPE(PCIEPCIBridge, PCIE_PCI_BRIDGE_DEV) static void pcie_pci_bridge_realize(PCIDevice *d, Error **errp) { diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs deleted file mode 100644 index e422e0aca04b9531e8e71cef690d75d9bb1c3f54..0000000000000000000000000000000000000000 --- a/hw/pci-host/Makefile.objs +++ /dev/null @@ -1,24 +0,0 @@ -common-obj-$(CONFIG_PAM) += pam.o - -# PPC devices -common-obj-$(CONFIG_PREP_PCI) += prep.o -common-obj-$(CONFIG_GRACKLE_PCI) += grackle.o -# NewWorld PowerMac -common-obj-$(CONFIG_UNIN_PCI) += uninorth.o -# PowerPC E500 boards -common-obj-$(CONFIG_PPCE500_PCI) += ppce500.o - -# ARM devices -common-obj-$(CONFIG_VERSATILE_PCI) += versatile.o - -common-obj-$(CONFIG_PCI_SABRE) += sabre.o -common-obj-$(CONFIG_PCI_BONITO) += bonito.o -common-obj-$(CONFIG_PCI_I440FX) += i440fx.o -common-obj-$(CONFIG_XEN_IGD_PASSTHROUGH) += xen_igd_pt.o -common-obj-$(CONFIG_PCI_EXPRESS_Q35) += q35.o -common-obj-$(CONFIG_PCI_EXPRESS_GENERIC_BRIDGE) += gpex.o -common-obj-$(CONFIG_PCI_EXPRESS_XILINX) += xilinx-pcie.o - -common-obj-$(CONFIG_PCI_EXPRESS_DESIGNWARE) += designware.o -obj-$(CONFIG_POWERNV) += pnv_phb4.o pnv_phb4_pec.o -obj-$(CONFIG_POWERNV) += pnv_phb3.o pnv_phb3_msi.o pnv_phb3_pbcq.o diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c index f9697dcc43950fd203851b89a999fd1ef14fce1f..a99eced06574f999f3f1b999576ae09d5f4b06ca 100644 --- a/hw/pci-host/bonito.c +++ b/hw/pci-host/bonito.c @@ -40,6 +40,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" +#include "qapi/error.h" #include "qemu/error-report.h" #include "hw/pci/pci.h" #include "hw/irq.h" @@ -51,6 +52,7 @@ #include "exec/address-spaces.h" #include "hw/misc/unimp.h" #include "hw/registerfields.h" +#include "qom/object.h" /* #define DEBUG_BONITO */ @@ -199,7 +201,7 @@ FIELD(BONGENCFG, PCIQUEUE, 12, 1) typedef struct BonitoState BonitoState; -typedef struct PCIBonitoState { +struct PCIBonitoState { PCIDevice dev; BonitoState *pcihost; @@ -227,7 +229,8 @@ typedef struct PCIBonitoState { MemoryRegion bonito_pciio; MemoryRegion bonito_localio; -} PCIBonitoState; +}; +typedef struct PCIBonitoState PCIBonitoState; struct BonitoState { PCIHostState parent_obj; @@ -237,12 +240,10 @@ struct BonitoState { }; #define TYPE_BONITO_PCI_HOST_BRIDGE "Bonito-pcihost" -#define BONITO_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(BonitoState, (obj), TYPE_BONITO_PCI_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(BonitoState, BONITO_PCI_HOST_BRIDGE) #define TYPE_PCI_BONITO "Bonito" -#define PCI_BONITO(obj) \ - OBJECT_CHECK(PCIBonitoState, (obj), TYPE_PCI_BONITO) +OBJECT_DECLARE_SIMPLE_TYPE(PCIBonitoState, PCI_BONITO) static void bonito_writel(void *opaque, hwaddr addr, uint64_t val, unsigned size) @@ -743,17 +744,17 @@ PCIBus *bonito_init(qemu_irq *pic) PCIBonitoState *s; PCIDevice *d; - dev = qdev_create(NULL, TYPE_BONITO_PCI_HOST_BRIDGE); + dev = qdev_new(TYPE_BONITO_PCI_HOST_BRIDGE); phb = PCI_HOST_BRIDGE(dev); pcihost = BONITO_PCI_HOST_BRIDGE(dev); pcihost->pic = pic; - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - d = pci_create(phb->bus, PCI_DEVFN(0, 0), TYPE_PCI_BONITO); + d = pci_new(PCI_DEVFN(0, 0), TYPE_PCI_BONITO); s = PCI_BONITO(d); s->pcihost = pcihost; pcihost->pci_dev = s; - qdev_init_nofail(DEVICE(d)); + pci_realize_and_unref(d, phb->bus, &error_fatal); return phb->bus; } diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c index dd245516dd9b5fef3ab05cdc1ea621e335037bfb..f9fb97a3e3b28220fb5c54409789efbfdfbb6864 100644 --- a/hw/pci-host/designware.c +++ b/hw/pci-host/designware.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -688,8 +688,7 @@ static void designware_pcie_host_realize(DeviceState *dev, Error **errp) "pcie-bus-address-space"); pci_setup_iommu(pci->bus, designware_pcie_host_set_iommu, s); - qdev_set_parent_bus(DEVICE(&s->root), BUS(pci->bus)); - qdev_init_nofail(DEVICE(&s->root)); + qdev_realize(DEVICE(&s->root), BUS(pci->bus), &error_fatal); } static const VMStateDescription vmstate_designware_pcie_host = { @@ -723,8 +722,7 @@ static void designware_pcie_host_init(Object *obj) DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(obj); DesignwarePCIERoot *root = &s->root; - object_initialize_child(obj, "root", root, sizeof(*root), - TYPE_DESIGNWARE_PCIE_ROOT, &error_abort, NULL); + object_initialize_child(obj, "root", root, TYPE_DESIGNWARE_PCIE_ROOT); qdev_prop_set_int32(DEVICE(root), "addr", PCI_DEVFN(0, 0)); qdev_prop_set_bit(DEVICE(root), "multifunction", false); } diff --git a/hw/pci-host/gpex-acpi.c b/hw/pci-host/gpex-acpi.c new file mode 100644 index 0000000000000000000000000000000000000000..dbb350a837f8e7f73adfd482b4c28d483f9bc59c --- /dev/null +++ b/hw/pci-host/gpex-acpi.c @@ -0,0 +1,177 @@ +#include "qemu/osdep.h" +#include "hw/acpi/aml-build.h" +#include "hw/pci-host/gpex.h" + +void acpi_dsdt_add_gpex(Aml *scope, struct GPEXConfig *cfg) +{ + int nr_pcie_buses = cfg->ecam.size / PCIE_MMCFG_SIZE_MIN; + Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf; + int i, slot_no; + + Aml *dev = aml_device("%s", "PCI0"); + aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08"))); + aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03"))); + aml_append(dev, aml_name_decl("_SEG", aml_int(0))); + aml_append(dev, aml_name_decl("_BBN", aml_int(0))); + aml_append(dev, aml_name_decl("_UID", aml_int(0))); + aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device"))); + aml_append(dev, aml_name_decl("_CCA", aml_int(1))); + + /* Declare the PCI Routing Table. */ + Aml *rt_pkg = aml_varpackage(PCI_SLOT_MAX * PCI_NUM_PINS); + for (slot_no = 0; slot_no < PCI_SLOT_MAX; slot_no++) { + for (i = 0; i < PCI_NUM_PINS; i++) { + int gsi = (i + slot_no) % PCI_NUM_PINS; + Aml *pkg = aml_package(4); + aml_append(pkg, aml_int((slot_no << 16) | 0xFFFF)); + aml_append(pkg, aml_int(i)); + aml_append(pkg, aml_name("GSI%d", gsi)); + aml_append(pkg, aml_int(0)); + aml_append(rt_pkg, pkg); + } + } + aml_append(dev, aml_name_decl("_PRT", rt_pkg)); + + /* Create GSI link device */ + for (i = 0; i < PCI_NUM_PINS; i++) { + uint32_t irqs = cfg->irq + i; + Aml *dev_gsi = aml_device("GSI%d", i); + aml_append(dev_gsi, aml_name_decl("_HID", aml_string("PNP0C0F"))); + aml_append(dev_gsi, aml_name_decl("_UID", aml_int(i))); + crs = aml_resource_template(); + aml_append(crs, + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, &irqs, 1)); + aml_append(dev_gsi, aml_name_decl("_PRS", crs)); + crs = aml_resource_template(); + aml_append(crs, + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, &irqs, 1)); + aml_append(dev_gsi, aml_name_decl("_CRS", crs)); + method = aml_method("_SRS", 1, AML_NOTSERIALIZED); + aml_append(dev_gsi, method); + aml_append(dev, dev_gsi); + } + + method = aml_method("_CBA", 0, AML_NOTSERIALIZED); + aml_append(method, aml_return(aml_int(cfg->ecam.base))); + aml_append(dev, method); + + Aml *rbuf = aml_resource_template(); + aml_append(rbuf, + aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, + 0x0000, 0x0000, nr_pcie_buses - 1, 0x0000, + nr_pcie_buses)); + if (cfg->mmio32.size) { + aml_append(rbuf, + aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, + AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, + cfg->mmio32.base, + cfg->mmio32.base + cfg->mmio32.size - 1, + 0x0000, + cfg->mmio32.size)); + } + if (cfg->pio.size) { + aml_append(rbuf, + aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, + AML_ENTIRE_RANGE, 0x0000, 0x0000, + cfg->pio.size - 1, + cfg->pio.base, + cfg->pio.size)); + } + if (cfg->mmio64.size) { + aml_append(rbuf, + aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, + AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, + cfg->mmio64.base, + cfg->mmio64.base + cfg->mmio64.size - 1, + 0x0000, + cfg->mmio64.size)); + } + aml_append(dev, aml_name_decl("_CRS", rbuf)); + + /* Declare an _OSC (OS Control Handoff) method */ + aml_append(dev, aml_name_decl("SUPP", aml_int(0))); + aml_append(dev, aml_name_decl("CTRL", aml_int(0))); + method = aml_method("_OSC", 4, AML_NOTSERIALIZED); + aml_append(method, + aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1")); + + /* PCI Firmware Specification 3.0 + * 4.5.1. _OSC Interface for PCI Host Bridge Devices + * The _OSC interface for a PCI/PCI-X/PCI Express hierarchy is + * identified by the Universal Unique IDentifier (UUID) + * 33DB4D5B-1FF7-401C-9657-7441C03DD766 + */ + UUID = aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766"); + ifctx = aml_if(aml_equal(aml_arg(0), UUID)); + aml_append(ifctx, + aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2")); + aml_append(ifctx, + aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3")); + aml_append(ifctx, aml_store(aml_name("CDW2"), aml_name("SUPP"))); + aml_append(ifctx, aml_store(aml_name("CDW3"), aml_name("CTRL"))); + + /* + * Allow OS control for all 5 features: + * PCIeHotplug SHPCHotplug PME AER PCIeCapability. + */ + aml_append(ifctx, aml_and(aml_name("CTRL"), aml_int(0x1F), + aml_name("CTRL"))); + + ifctx1 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(0x1)))); + aml_append(ifctx1, aml_or(aml_name("CDW1"), aml_int(0x08), + aml_name("CDW1"))); + aml_append(ifctx, ifctx1); + + ifctx1 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), aml_name("CTRL")))); + aml_append(ifctx1, aml_or(aml_name("CDW1"), aml_int(0x10), + aml_name("CDW1"))); + aml_append(ifctx, ifctx1); + + aml_append(ifctx, aml_store(aml_name("CTRL"), aml_name("CDW3"))); + aml_append(ifctx, aml_return(aml_arg(3))); + aml_append(method, ifctx); + + elsectx = aml_else(); + aml_append(elsectx, aml_or(aml_name("CDW1"), aml_int(4), + aml_name("CDW1"))); + aml_append(elsectx, aml_return(aml_arg(3))); + aml_append(method, elsectx); + aml_append(dev, method); + + method = aml_method("_DSM", 4, AML_NOTSERIALIZED); + + /* PCI Firmware Specification 3.0 + * 4.6.1. _DSM for PCI Express Slot Information + * The UUID in _DSM in this context is + * {E5C937D0-3553-4D7A-9117-EA4D19C3434D} + */ + UUID = aml_touuid("E5C937D0-3553-4D7A-9117-EA4D19C3434D"); + ifctx = aml_if(aml_equal(aml_arg(0), UUID)); + ifctx1 = aml_if(aml_equal(aml_arg(2), aml_int(0))); + uint8_t byte_list[1] = {1}; + buf = aml_buffer(1, byte_list); + aml_append(ifctx1, aml_return(buf)); + aml_append(ifctx, ifctx1); + aml_append(method, ifctx); + + byte_list[0] = 0; + buf = aml_buffer(1, byte_list); + aml_append(method, aml_return(buf)); + aml_append(dev, method); + + Aml *dev_res0 = aml_device("%s", "RES0"); + aml_append(dev_res0, aml_name_decl("_HID", aml_string("PNP0C02"))); + crs = aml_resource_template(); + aml_append(crs, + aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, + AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, + cfg->ecam.base, + cfg->ecam.base + cfg->ecam.size - 1, + 0x0000, + cfg->ecam.size)); + aml_append(dev_res0, aml_name_decl("_CRS", crs)); + aml_append(dev, dev_res0); + aml_append(scope, dev); +} diff --git a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c index 0ca604dc628ebccc3f622625bb18d091529ac4c2..2bdbe7b4561281965f67ed919f2955ef8cc5e167 100644 --- a/hw/pci-host/gpex.c +++ b/hw/pci-host/gpex.c @@ -98,9 +98,8 @@ static void gpex_host_realize(DeviceState *dev, Error **errp) pci_swizzle_map_irq_fn, s, &s->io_mmio, &s->io_ioport, 0, 4, TYPE_PCIE_BUS); - qdev_set_parent_bus(DEVICE(&s->gpex_root), BUS(pci->bus)); pci_bus_set_route_irq_fn(pci->bus, gpex_route_intx_pin_to_irq); - qdev_init_nofail(DEVICE(&s->gpex_root)); + qdev_realize(DEVICE(&s->gpex_root), BUS(pci->bus), &error_fatal); } static const char *gpex_host_root_bus_path(PCIHostState *host_bridge, @@ -125,8 +124,7 @@ static void gpex_host_initfn(Object *obj) GPEXHost *s = GPEX_HOST(obj); GPEXRootState *root = &s->gpex_root; - object_initialize_child(obj, "gpex_root", root, sizeof(*root), - TYPE_GPEX_ROOT_DEVICE, &error_abort, NULL); + object_initialize_child(obj, "gpex_root", root, TYPE_GPEX_ROOT_DEVICE); qdev_prop_set_int32(DEVICE(root), "addr", PCI_DEVFN(0, 0)); qdev_prop_set_bit(DEVICE(root), "multifunction", false); } diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c index 4b3af0c70403b8e9fd88cdf19c3f786118e745e4..b05facf4635328e9906f5091670c3c85f44af563 100644 --- a/hw/pci-host/grackle.c +++ b/hw/pci-host/grackle.c @@ -28,25 +28,23 @@ #include "hw/ppc/mac.h" #include "hw/qdev-properties.h" #include "hw/pci/pci.h" -#include "hw/intc/heathrow_pic.h" #include "hw/irq.h" #include "qapi/error.h" #include "qemu/module.h" #include "trace.h" +#include "qom/object.h" -#define GRACKLE_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(GrackleState, (obj), TYPE_GRACKLE_PCI_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(GrackleState, GRACKLE_PCI_HOST_BRIDGE) -typedef struct GrackleState { +struct GrackleState { PCIHostState parent_obj; uint32_t ofw_addr; - HeathrowState *pic; qemu_irq irqs[4]; MemoryRegion pci_mmio; MemoryRegion pci_hole; MemoryRegion pci_io; -} GrackleState; +}; /* Don't know if this matches real hardware, but it agrees with OHW. */ static int pci_grackle_map_irq(PCIDevice *pci_dev, int irq_num) @@ -62,15 +60,6 @@ static void pci_grackle_set_irq(void *opaque, int irq_num, int level) qemu_set_irq(s->irqs[irq_num], level); } -static void grackle_init_irqs(GrackleState *s) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(s->irqs); i++) { - s->irqs[i] = qdev_get_gpio_in(DEVICE(s->pic), 0x15 + i); - } -} - static void grackle_realize(DeviceState *dev, Error **errp) { GrackleState *s = GRACKLE_PCI_HOST_BRIDGE(dev); @@ -85,7 +74,6 @@ static void grackle_realize(DeviceState *dev, Error **errp) 0, 4, TYPE_PCI_BUS); pci_create_simple(phb->bus, 0, "grackle"); - grackle_init_irqs(s); } static void grackle_init(Object *obj) @@ -106,15 +94,12 @@ static void grackle_init(Object *obj) memory_region_init_io(&phb->data_mem, obj, &pci_host_data_le_ops, DEVICE(obj), "pci-data-idx", 0x1000); - object_property_add_link(obj, "pic", TYPE_HEATHROW, - (Object **) &s->pic, - qdev_prop_allow_set_link_before_realize, - 0); - sysbus_init_mmio(sbd, &phb->conf_mem); sysbus_init_mmio(sbd, &phb->data_mem); sysbus_init_mmio(sbd, &s->pci_hole); sysbus_init_mmio(sbd, &s->pci_io); + + qdev_init_gpio_out(DEVICE(obj), s->irqs, ARRAY_SIZE(s->irqs)); } static void grackle_pci_realize(PCIDevice *d, Error **errp) diff --git a/hw/pci-host/i440fx.c b/hw/pci-host/i440fx.c index 0adbd77553e026c632d87631111b739c55e8e978..28c9bae89944c0929d2e4c80dbf6781d397e6fb4 100644 --- a/hw/pci-host/i440fx.c +++ b/hw/pci-host/i440fx.c @@ -23,6 +23,7 @@ */ #include "qemu/osdep.h" +#include "qemu/units.h" #include "qemu/range.h" #include "hw/i386/pc.h" #include "hw/pci/pci.h" @@ -34,22 +35,22 @@ #include "migration/vmstate.h" #include "qapi/visitor.h" #include "qemu/error-report.h" +#include "qom/object.h" /* * I440FX chipset data sheet. * https://wiki.qemu.org/File:29054901.pdf */ -#define I440FX_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(I440FXState, (obj), TYPE_I440FX_PCI_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(I440FXState, I440FX_PCI_HOST_BRIDGE) -typedef struct I440FXState { +struct I440FXState { PCIHostState parent_obj; Range pci_hole; uint64_t pci_hole64_size; bool pci_hole64_fix; uint32_t short_root_bus; -} I440FXState; +}; #define I440FX_PAM 0x59 #define I440FX_PAM_SIZE 7 @@ -209,22 +210,6 @@ static void i440fx_pcihost_initfn(Object *obj) "pci-conf-idx", 4); memory_region_init_io(&s->data_mem, obj, &pci_host_data_le_ops, s, "pci-conf-data", 4); - - object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32", - i440fx_pcihost_get_pci_hole_start, - NULL, NULL, NULL); - - object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "uint32", - i440fx_pcihost_get_pci_hole_end, - NULL, NULL, NULL); - - object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "uint64", - i440fx_pcihost_get_pci_hole64_start, - NULL, NULL, NULL); - - object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "uint64", - i440fx_pcihost_get_pci_hole64_end, - NULL, NULL, NULL); } static void i440fx_pcihost_realize(DeviceState *dev, Error **errp) @@ -270,13 +255,13 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type, unsigned i; I440FXState *i440fx; - dev = qdev_create(NULL, host_type); + dev = qdev_new(host_type); s = PCI_HOST_BRIDGE(dev); b = pci_root_bus_new(dev, NULL, pci_address_space, address_space_io, 0, TYPE_PCI_BUS); s->bus = b; object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev)); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); d = pci_create_simple(b, 0, pci_type); *pi440fx_state = I440FX_PCI_DEVICE(d); @@ -301,7 +286,7 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type, memory_region_set_enabled(&f->smram_region, true); /* smram, as seen by SMM CPUs */ - memory_region_init(&f->smram, OBJECT(d), "smram", 1ull << 32); + memory_region_init(&f->smram, OBJECT(d), "smram", 4 * GiB); memory_region_set_enabled(&f->smram, true); memory_region_init_alias(&f->low_smram, OBJECT(d), "smram-low", f->ram_memory, 0xa0000, 0x20000); @@ -400,6 +385,22 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data) device_class_set_props(dc, i440fx_props); /* Reason: needs to be wired up by pc_init1 */ dc->user_creatable = false; + + object_class_property_add(klass, PCI_HOST_PROP_PCI_HOLE_START, "uint32", + i440fx_pcihost_get_pci_hole_start, + NULL, NULL, NULL); + + object_class_property_add(klass, PCI_HOST_PROP_PCI_HOLE_END, "uint32", + i440fx_pcihost_get_pci_hole_end, + NULL, NULL, NULL); + + object_class_property_add(klass, PCI_HOST_PROP_PCI_HOLE64_START, "uint64", + i440fx_pcihost_get_pci_hole64_start, + NULL, NULL, NULL); + + object_class_property_add(klass, PCI_HOST_PROP_PCI_HOLE64_END, "uint64", + i440fx_pcihost_get_pci_hole64_end, + NULL, NULL, NULL); } static const TypeInfo i440fx_pcihost_info = { diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..e6d1b896848c9254ae0080dc918f9db7bda073bb --- /dev/null +++ b/hw/pci-host/meson.build @@ -0,0 +1,32 @@ +pci_ss = ss.source_set() +pci_ss.add(when: 'CONFIG_PAM', if_true: files('pam.c')) +pci_ss.add(when: 'CONFIG_PCI_BONITO', if_true: files('bonito.c')) +pci_ss.add(when: 'CONFIG_PCI_EXPRESS_DESIGNWARE', if_true: files('designware.c')) +pci_ss.add(when: 'CONFIG_PCI_EXPRESS_GENERIC_BRIDGE', if_true: files('gpex.c')) +pci_ss.add(when: 'CONFIG_ACPI', if_true: files('gpex-acpi.c')) +pci_ss.add(when: 'CONFIG_PCI_EXPRESS_Q35', if_true: files('q35.c')) +pci_ss.add(when: 'CONFIG_PCI_EXPRESS_XILINX', if_true: files('xilinx-pcie.c')) +pci_ss.add(when: 'CONFIG_PCI_I440FX', if_true: files('i440fx.c')) +pci_ss.add(when: 'CONFIG_PCI_SABRE', if_true: files('sabre.c')) +pci_ss.add(when: 'CONFIG_XEN_IGD_PASSTHROUGH', if_true: files('xen_igd_pt.c')) + +# PPC devices +pci_ss.add(when: 'CONFIG_PREP_PCI', if_true: files('prep.c')) +pci_ss.add(when: 'CONFIG_GRACKLE_PCI', if_true: files('grackle.c')) +# NewWorld PowerMac +pci_ss.add(when: 'CONFIG_UNIN_PCI', if_true: files('uninorth.c')) +# PowerPC E500 boards +pci_ss.add(when: 'CONFIG_PPCE500_PCI', if_true: files('ppce500.c')) + +# ARM devices +pci_ss.add(when: 'CONFIG_VERSATILE_PCI', if_true: files('versatile.c')) + +softmmu_ss.add_all(when: 'CONFIG_PCI', if_true: pci_ss) + +specific_ss.add(when: 'CONFIG_POWERNV', if_true: files( + 'pnv_phb3.c', + 'pnv_phb3_msi.c', + 'pnv_phb3_pbcq.c', + 'pnv_phb4.c', + 'pnv_phb4_pec.c' +)) diff --git a/hw/pci-host/pam.c b/hw/pci-host/pam.c index 45c4333cd38fd079c8a8d7c98d53e6374897e096..a4962057833f1f60aa093530007c16162de0acd8 100644 --- a/hw/pci-host/pam.c +++ b/hw/pci-host/pam.c @@ -28,7 +28,6 @@ */ #include "qemu/osdep.h" -#include "qom/object.h" #include "hw/pci-host/pam.h" void init_pam(DeviceState *dev, MemoryRegion *ram_memory, diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index 74618fadf0858cfb85aa56d8e85a640f63920f5a..a7f96850055a7ff24120d2bb4e153a4a4e80b250 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -18,6 +18,7 @@ #include "hw/ppc/pnv.h" #include "hw/irq.h" #include "hw/qdev-properties.h" +#include "qom/object.h" #define phb3_error(phb, fmt, ...) \ qemu_log_mask(LOG_GUEST_ERROR, "phb3[%d:%d]: " fmt "\n", \ @@ -877,8 +878,8 @@ static IOMMUTLBEntry pnv_phb3_translate_iommu(IOMMUMemoryRegion *iommu, } #define TYPE_PNV_PHB3_IOMMU_MEMORY_REGION "pnv-phb3-iommu-memory-region" -#define PNV_PHB3_IOMMU_MEMORY_REGION(obj) \ - OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_PNV_PHB3_IOMMU_MEMORY_REGION) +DECLARE_INSTANCE_CHECKER(IOMMUMemoryRegion, PNV_PHB3_IOMMU_MEMORY_REGION, + TYPE_PNV_PHB3_IOMMU_MEMORY_REGION) static void pnv_phb3_iommu_memory_region_class_init(ObjectClass *klass, void *data) @@ -968,23 +969,19 @@ static void pnv_phb3_instance_init(Object *obj) QLIST_INIT(&phb->dma_spaces); /* LSI sources */ - object_initialize_child(obj, "lsi", &phb->lsis, sizeof(phb->lsis), - TYPE_ICS, &error_abort, NULL); + object_initialize_child(obj, "lsi", &phb->lsis, TYPE_ICS); /* Default init ... will be fixed by HW inits */ phb->lsis.offset = 0; /* MSI sources */ - object_initialize_child(obj, "msi", &phb->msis, sizeof(phb->msis), - TYPE_PHB3_MSI, &error_abort, NULL); + object_initialize_child(obj, "msi", &phb->msis, TYPE_PHB3_MSI); /* Power Bus Common Queue */ - object_initialize_child(obj, "pbcq", &phb->pbcq, sizeof(phb->pbcq), - TYPE_PNV_PBCQ, &error_abort, NULL); + object_initialize_child(obj, "pbcq", &phb->pbcq, TYPE_PNV_PBCQ); /* Root Port */ - object_initialize_child(obj, "root", &phb->root, sizeof(phb->root), - TYPE_PNV_PHB3_ROOT_PORT, &error_abort, NULL); + object_initialize_child(obj, "root", &phb->root, TYPE_PNV_PHB3_ROOT_PORT); qdev_prop_set_int32(DEVICE(&phb->root), "addr", PCI_DEVFN(0, 0)); qdev_prop_set_bit(DEVICE(&phb->root), "multifunction", false); } @@ -994,7 +991,6 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp) PnvPHB3 *phb = PNV_PHB3(dev); PCIHostState *pci = PCI_HOST_BRIDGE(dev); PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); - Error *local_err = NULL; int i; if (phb->phb_id >= PNV8_CHIP_PHB3_MAX) { @@ -1003,13 +999,11 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp) } /* LSI sources */ - object_property_set_link(OBJECT(&phb->lsis), OBJECT(pnv), "xics", - &error_abort); - object_property_set_int(OBJECT(&phb->lsis), PNV_PHB3_NUM_LSI, "nr-irqs", + object_property_set_link(OBJECT(&phb->lsis), "xics", OBJECT(pnv), + &error_abort); + object_property_set_int(OBJECT(&phb->lsis), "nr-irqs", PNV_PHB3_NUM_LSI, &error_abort); - object_property_set_bool(OBJECT(&phb->lsis), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qdev_realize(DEVICE(&phb->lsis), NULL, errp)) { return; } @@ -1020,24 +1014,20 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp) phb->qirqs = qemu_allocate_irqs(ics_set_irq, &phb->lsis, phb->lsis.nr_irqs); /* MSI sources */ - object_property_set_link(OBJECT(&phb->msis), OBJECT(phb), "phb", - &error_abort); - object_property_set_link(OBJECT(&phb->msis), OBJECT(pnv), "xics", - &error_abort); - object_property_set_int(OBJECT(&phb->msis), PHB3_MAX_MSI, "nr-irqs", + object_property_set_link(OBJECT(&phb->msis), "phb", OBJECT(phb), + &error_abort); + object_property_set_link(OBJECT(&phb->msis), "xics", OBJECT(pnv), + &error_abort); + object_property_set_int(OBJECT(&phb->msis), "nr-irqs", PHB3_MAX_MSI, &error_abort); - object_property_set_bool(OBJECT(&phb->msis), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qdev_realize(DEVICE(&phb->msis), NULL, errp)) { return; } /* Power Bus Common Queue */ - object_property_set_link(OBJECT(&phb->pbcq), OBJECT(phb), "phb", - &error_abort); - object_property_set_bool(OBJECT(&phb->pbcq), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + object_property_set_link(OBJECT(&phb->pbcq), "phb", OBJECT(phb), + &error_abort); + if (!qdev_realize(DEVICE(&phb->pbcq), NULL, errp)) { return; } @@ -1064,8 +1054,7 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp) /* Add a single Root port */ qdev_prop_set_uint8(DEVICE(&phb->root), "chassis", phb->chip_id); qdev_prop_set_uint16(DEVICE(&phb->root), "slot", phb->phb_id); - qdev_set_parent_bus(DEVICE(&phb->root), BUS(pci->bus)); - qdev_init_nofail(DEVICE(&phb->root)); + qdev_realize(DEVICE(&phb->root), BUS(pci->bus), &error_fatal); } void pnv_phb3_update_regions(PnvPHB3 *phb) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 23cf093928edd0bdac41fe4ab4bbd5c08a08d97d..03daf40a237b8ae694baeb0d83b3c5d7530040d5 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -21,6 +21,7 @@ #include "hw/ppc/pnv_xscom.h" #include "hw/irq.h" #include "hw/qdev-properties.h" +#include "qom/object.h" #define phb_error(phb, fmt, ...) \ qemu_log_mask(LOG_GUEST_ERROR, "phb4[%d:%d]: " fmt "\n", \ @@ -1042,8 +1043,8 @@ static IOMMUTLBEntry pnv_phb4_translate_iommu(IOMMUMemoryRegion *iommu, } #define TYPE_PNV_PHB4_IOMMU_MEMORY_REGION "pnv-phb4-iommu-memory-region" -#define PNV_PHB4_IOMMU_MEMORY_REGION(obj) \ - OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_PNV_PHB4_IOMMU_MEMORY_REGION) +DECLARE_INSTANCE_CHECKER(IOMMUMemoryRegion, PNV_PHB4_IOMMU_MEMORY_REGION, + TYPE_PNV_PHB4_IOMMU_MEMORY_REGION) static void pnv_phb4_iommu_memory_region_class_init(ObjectClass *klass, void *data) @@ -1155,12 +1156,10 @@ static void pnv_phb4_instance_init(Object *obj) QLIST_INIT(&phb->dma_spaces); /* XIVE interrupt source object */ - object_initialize_child(obj, "source", &phb->xsrc, sizeof(XiveSource), - TYPE_XIVE_SOURCE, &error_abort, NULL); + object_initialize_child(obj, "source", &phb->xsrc, TYPE_XIVE_SOURCE); /* Root Port */ - object_initialize_child(obj, "root", &phb->root, sizeof(phb->root), - TYPE_PNV_PHB4_ROOT_PORT, &error_abort, NULL); + object_initialize_child(obj, "root", &phb->root, TYPE_PNV_PHB4_ROOT_PORT); qdev_prop_set_int32(DEVICE(&phb->root), "addr", PCI_DEVFN(0, 0)); qdev_prop_set_bit(DEVICE(&phb->root), "multifunction", false); @@ -1171,7 +1170,6 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) PnvPHB4 *phb = PNV_PHB4(dev); PCIHostState *pci = PCI_HOST_BRIDGE(dev); XiveSource *xsrc = &phb->xsrc; - Error *local_err = NULL; int nr_irqs; char name[32]; @@ -1210,8 +1208,7 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) /* Add a single Root port */ qdev_prop_set_uint8(DEVICE(&phb->root), "chassis", phb->chip_id); qdev_prop_set_uint16(DEVICE(&phb->root), "slot", phb->phb_id); - qdev_set_parent_bus(DEVICE(&phb->root), BUS(pci->bus)); - qdev_init_nofail(DEVICE(&phb->root)); + qdev_realize(DEVICE(&phb->root), BUS(pci->bus), &error_fatal); /* Setup XIVE Source */ if (phb->big_phb) { @@ -1219,11 +1216,9 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) } else { nr_irqs = PNV_PHB4_MAX_INTs >> 1; } - object_property_set_int(OBJECT(xsrc), nr_irqs, "nr-irqs", &error_fatal); - object_property_set_link(OBJECT(xsrc), OBJECT(phb), "xive", &error_fatal); - object_property_set_bool(OBJECT(xsrc), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + object_property_set_int(OBJECT(xsrc), "nr-irqs", nr_irqs, &error_fatal); + object_property_set_link(OBJECT(xsrc), "xive", OBJECT(phb), &error_fatal); + if (!qdev_realize(DEVICE(xsrc), NULL, errp)) { return; } diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index 911d147ffd7d78fb616bdc514eeca5b48e9eb7ab..741ddc90ed8dbe29560f4242daa8a94cc92bfc51 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -370,15 +370,13 @@ static void pnv_pec_instance_init(Object *obj) for (i = 0; i < PHB4_PEC_MAX_STACKS; i++) { object_initialize_child(obj, "stack[*]", &pec->stacks[i], - sizeof(pec->stacks[i]), TYPE_PNV_PHB4_PEC_STACK, - &error_abort, NULL); + TYPE_PNV_PHB4_PEC_STACK); } } static void pnv_pec_realize(DeviceState *dev, Error **errp) { PnvPhb4PecState *pec = PNV_PHB4_PEC(dev); - Error *local_err = NULL; char name[64]; int i; @@ -389,14 +387,15 @@ static void pnv_pec_realize(DeviceState *dev, Error **errp) PnvPhb4PecStack *stack = &pec->stacks[i]; Object *stk_obj = OBJECT(stack); - object_property_set_int(stk_obj, i, "stack-no", &error_abort); - object_property_set_link(stk_obj, OBJECT(pec), "pec", &error_abort); - object_property_set_bool(stk_obj, true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + object_property_set_int(stk_obj, "stack-no", i, &error_abort); + object_property_set_link(stk_obj, "pec", OBJECT(pec), &error_abort); + if (!qdev_realize(DEVICE(stk_obj), NULL, errp)) { return; } } + for (; i < PHB4_PEC_MAX_STACKS; i++) { + object_unparent(OBJECT(&pec->stacks[i])); + } /* Initialize the XSCOM regions for the PEC registers */ snprintf(name, sizeof(name), "xscom-pec-%d.%d-nest", pec->chip_id, @@ -519,8 +518,7 @@ static void pnv_pec_stk_instance_init(Object *obj) { PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(obj); - object_initialize_child(obj, "phb", &stack->phb, sizeof(stack->phb), - TYPE_PNV_PHB4, &error_abort, NULL); + object_initialize_child(obj, "phb", &stack->phb, TYPE_PNV_PHB4); } static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c index d71072731df13b0fb736b2381bccd652009546b0..9517aab913e23795e73baebbc589d0eb244653d6 100644 --- a/hw/pci-host/ppce500.c +++ b/hw/pci-host/ppce500.c @@ -24,6 +24,7 @@ #include "qemu/bswap.h" #include "qemu/module.h" #include "hw/pci-host/ppce500.h" +#include "qom/object.h" #ifdef DEBUG_PCI #define pci_debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__) @@ -91,8 +92,7 @@ struct pci_inbound { #define TYPE_PPC_E500_PCI_HOST_BRIDGE "e500-pcihost" -#define PPC_E500_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(PPCE500PCIState, (obj), TYPE_PPC_E500_PCI_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(PPCE500PCIState, PPC_E500_PCI_HOST_BRIDGE) struct PPCE500PCIState { PCIHostState parent_obj; @@ -114,8 +114,7 @@ struct PPCE500PCIState { }; #define TYPE_PPC_E500_PCI_BRIDGE "e500-host-bridge" -#define PPC_E500_PCI_BRIDGE(obj) \ - OBJECT_CHECK(PPCE500PCIBridgeState, (obj), TYPE_PPC_E500_PCI_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(PPCE500PCIBridgeState, PPC_E500_PCI_BRIDGE) struct PPCE500PCIBridgeState { /*< private >*/ @@ -125,8 +124,6 @@ struct PPCE500PCIBridgeState { MemoryRegion bar0; }; -typedef struct PPCE500PCIBridgeState PPCE500PCIBridgeState; -typedef struct PPCE500PCIState PPCE500PCIState; static uint64_t pci_reg_read4(void *opaque, hwaddr addr, unsigned size) @@ -509,7 +506,7 @@ static void e500_host_bridge_class_init(ObjectClass *klass, void *data) } static const TypeInfo e500_host_bridge_info = { - .name = "e500-host-bridge", + .name = TYPE_PPC_E500_PCI_BRIDGE, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PPCE500PCIBridgeState), .class_init = e500_host_bridge_class_init, diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c index 1a02e9a670b4426c62e3d8bd19f75ff135fe5d69..d0323fefb10f3fb8b053025440a560b87fb55366 100644 --- a/hw/pci-host/prep.c +++ b/hw/pci-host/prep.c @@ -38,25 +38,26 @@ #include "hw/or-irq.h" #include "exec/address-spaces.h" #include "elf.h" +#include "qom/object.h" #define TYPE_RAVEN_PCI_DEVICE "raven" #define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost" -#define RAVEN_PCI_DEVICE(obj) \ - OBJECT_CHECK(RavenPCIState, (obj), TYPE_RAVEN_PCI_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(RavenPCIState, RAVEN_PCI_DEVICE) -typedef struct RavenPCIState { +struct RavenPCIState { PCIDevice dev; uint32_t elf_machine; char *bios_name; MemoryRegion bios; -} RavenPCIState; +}; -#define RAVEN_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(PREPPCIState, (obj), TYPE_RAVEN_PCI_HOST_BRIDGE) +typedef struct PRePPCIState PREPPCIState; +DECLARE_INSTANCE_CHECKER(PREPPCIState, RAVEN_PCI_HOST_BRIDGE, + TYPE_RAVEN_PCI_HOST_BRIDGE) -typedef struct PRePPCIState { +struct PRePPCIState { PCIHostState parent_obj; qemu_or_irq *or_irq; @@ -75,7 +76,7 @@ typedef struct PRePPCIState { int contiguous_map; bool is_legacy_prep; -} PREPPCIState; +}; #define BIOS_SIZE (1 * MiB) @@ -236,10 +237,9 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp) /* According to PReP specification section 6.1.6 "System Interrupt * Assignments", all PCI interrupts are routed via IRQ 15 */ s->or_irq = OR_IRQ(object_new(TYPE_OR_IRQ)); - object_property_set_int(OBJECT(s->or_irq), PCI_NUM_PINS, "num-lines", + object_property_set_int(OBJECT(s->or_irq), "num-lines", PCI_NUM_PINS, &error_fatal); - object_property_set_bool(OBJECT(s->or_irq), true, "realized", - &error_fatal); + qdev_realize(DEVICE(s->or_irq), NULL, &error_fatal); sysbus_init_irq(dev, &s->or_irq->out_irq); for (i = 0; i < PCI_NUM_PINS; i++) { @@ -268,8 +268,7 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp) memory_region_add_subregion(address_space_mem, 0xbffffff0, &s->pci_intack); /* TODO Remove once realize propagates to child devices. */ - object_property_set_bool(OBJECT(&s->pci_bus), true, "realized", errp); - object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp); + qdev_realize(DEVICE(&s->pci_dev), BUS(&s->pci_bus), errp); } static void raven_pcihost_initfn(Object *obj) @@ -294,7 +293,7 @@ static void raven_pcihost_initfn(Object *obj) &s->pci_memory, &s->pci_io, 0, TYPE_PCI_BUS); /* Bus master address space */ - memory_region_init(&s->bm, obj, "bm-raven", UINT32_MAX); + memory_region_init(&s->bm, obj, "bm-raven", 4 * GiB); memory_region_init_alias(&s->bm_pci_memory_alias, obj, "bm-pci-memory", &s->pci_memory, 0, memory_region_size(&s->pci_memory)); @@ -309,8 +308,7 @@ static void raven_pcihost_initfn(Object *obj) object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_RAVEN_PCI_DEVICE); pci_dev = DEVICE(&s->pci_dev); - qdev_set_parent_bus(pci_dev, BUS(&s->pci_bus)); - object_property_set_int(OBJECT(&s->pci_dev), PCI_DEVFN(0, 0), "addr", + object_property_set_int(OBJECT(&s->pci_dev), "addr", PCI_DEVFN(0, 0), NULL); qdev_prop_set_bit(pci_dev, "multifunction", false); } diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index 352aeecfa74e62c45a9cde1febbb015141dc9b3e..b67cb9c29f8ebca535bfae3c405f056b109ab1c9 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -64,8 +64,7 @@ static void q35_host_realize(DeviceState *dev, Error **errp) s->mch.address_space_io, 0, TYPE_PCIE_BUS); PC_MACHINE(qdev_get_machine())->bus = pci->bus; - qdev_set_parent_bus(DEVICE(&s->mch), BUS(pci->bus)); - qdev_init_nofail(DEVICE(&s->mch)); + qdev_realize(DEVICE(&s->mch), BUS(pci->bus), &error_fatal); } static const char *q35_host_root_bus_path(PCIHostState *host_bridge, @@ -213,8 +212,7 @@ static void q35_host_initfn(Object *obj) memory_region_init_io(&phb->data_mem, obj, &pci_host_data_le_ops, phb, "pci-conf-data", 4); - object_initialize_child(OBJECT(s), "mch", &s->mch, sizeof(s->mch), - TYPE_MCH_PCI_DEVICE, &error_abort, NULL); + object_initialize_child(OBJECT(s), "mch", &s->mch, TYPE_MCH_PCI_DEVICE); qdev_prop_set_int32(DEVICE(&s->mch), "addr", PCI_DEVFN(0, 0)); qdev_prop_set_bit(DEVICE(&s->mch), "multifunction", false); /* mch's object_initialize resets the default value, set it again */ @@ -589,7 +587,7 @@ static void mch_realize(PCIDevice *d, Error **errp) memory_region_set_enabled(&mch->open_high_smram, false); /* smram, as seen by SMM CPUs */ - memory_region_init(&mch->smram, OBJECT(mch), "smram", 1ull << 32); + memory_region_init(&mch->smram, OBJECT(mch), "smram", 4 * GiB); memory_region_set_enabled(&mch->smram, true); memory_region_init_alias(&mch->low_smram, OBJECT(mch), "smram-low", mch->ram_memory, MCH_HOST_BRIDGE_SMRAM_C_BASE, diff --git a/hw/pci-host/sabre.c b/hw/pci-host/sabre.c index 475bcb01d7bac17be7c5811c9dddea6e0d469d66..f41a0cc3013132251437d914deca052f6b2e2ba0 100644 --- a/hw/pci-host/sabre.c +++ b/hw/pci-host/sabre.c @@ -35,6 +35,7 @@ #include "hw/pci-bridge/simba.h" #include "hw/pci-host/sabre.h" #include "exec/address-spaces.h" +#include "qapi/error.h" #include "qemu/log.h" #include "qemu/module.h" #include "sysemu/runstate.h" @@ -43,7 +44,7 @@ /* * Chipset docs: * PBM: "UltraSPARC IIi User's Manual", - * http://www.sun.com/processors/manuals/805-0087.pdf + * https://web.archive.org/web/20030403110020/http://www.sun.com/processors/manuals/805-0087.pdf */ #define PBM_PCI_IMR_MASK 0x7fffffff @@ -119,7 +120,7 @@ static void sabre_config_write(void *opaque, hwaddr addr, trace_sabre_config_write(addr, val); - switch (addr & 0xffff) { + switch (addr) { case 0x30 ... 0x4f: /* DMA error registers */ /* XXX: not implemented yet */ break; @@ -194,32 +195,25 @@ static uint64_t sabre_config_read(void *opaque, hwaddr addr, unsigned size) { SabreState *s = opaque; - uint32_t val; + uint32_t val = 0; - switch (addr & 0xffff) { + switch (addr) { case 0x30 ... 0x4f: /* DMA error registers */ - val = 0; /* XXX: not implemented yet */ break; case 0xc00 ... 0xc3f: /* PCI interrupt control */ if (addr & 4) { val = s->pci_irq_map[(addr & 0x3f) >> 3]; - } else { - val = 0; } break; case 0x1000 ... 0x107f: /* OBIO interrupt control */ if (addr & 4) { val = s->obio_irq_map[(addr & 0xff) >> 3]; - } else { - val = 0; } break; case 0x1080 ... 0x108f: /* PCI bus error */ if (addr & 4) { val = s->pci_err_irq_map[(addr & 0xf) >> 3]; - } else { - val = 0; } break; case 0x2000 ... 0x202f: /* PCI control */ @@ -228,8 +222,6 @@ static uint64_t sabre_config_read(void *opaque, case 0xf020 ... 0xf027: /* Reset control */ if (addr & 4) { val = s->reset_control; - } else { - val = 0; } break; case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */ @@ -238,7 +230,6 @@ static uint64_t sabre_config_read(void *opaque, case 0xf000 ... 0xf01f: /* FFB config, memory control */ /* we don't care */ default: - val = 0; break; } trace_sabre_config_read(addr, val); @@ -337,7 +328,7 @@ static void pci_sabre_set_irq(void *opaque, int irq_num, int level) static void sabre_reset(DeviceState *d) { - SabreState *s = SABRE_DEVICE(d); + SabreState *s = SABRE(d); PCIDevice *pci_dev; unsigned int i; uint16_t cmd; @@ -375,18 +366,10 @@ static const MemoryRegionOps pci_config_ops = { static void sabre_realize(DeviceState *dev, Error **errp) { - SabreState *s = SABRE_DEVICE(dev); + SabreState *s = SABRE(dev); PCIHostState *phb = PCI_HOST_BRIDGE(dev); - SysBusDevice *sbd = SYS_BUS_DEVICE(s); PCIDevice *pci_dev; - /* sabre_config */ - sysbus_mmio_map(sbd, 0, s->special_base); - /* PCI configuration space */ - sysbus_mmio_map(sbd, 1, s->special_base + 0x1000000ULL); - /* pci_ioport */ - sysbus_mmio_map(sbd, 2, s->special_base + 0x2000000ULL); - memory_region_init(&s->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL); memory_region_add_subregion(get_system_memory(), s->mem_base, &s->pci_mmio); @@ -395,7 +378,7 @@ static void sabre_realize(DeviceState *dev, Error **errp) pci_sabre_set_irq, pci_sabre_map_irq, s, &s->pci_mmio, &s->pci_ioport, - 0, 32, TYPE_PCI_BUS); + 0, 0x40, TYPE_PCI_BUS); pci_create_simple(phb->bus, 0, TYPE_SABRE_PCI_DEVICE); @@ -405,22 +388,22 @@ static void sabre_realize(DeviceState *dev, Error **errp) pci_setup_iommu(phb->bus, sabre_pci_dma_iommu, s->iommu); /* APB secondary busses */ - pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true, - TYPE_SIMBA_PCI_BRIDGE); + pci_dev = pci_new_multifunction(PCI_DEVFN(1, 0), true, + TYPE_SIMBA_PCI_BRIDGE); s->bridgeB = PCI_BRIDGE(pci_dev); pci_bridge_map_irq(s->bridgeB, "pciB", pci_simbaB_map_irq); - qdev_init_nofail(&pci_dev->qdev); + pci_realize_and_unref(pci_dev, phb->bus, &error_fatal); - pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true, - TYPE_SIMBA_PCI_BRIDGE); + pci_dev = pci_new_multifunction(PCI_DEVFN(1, 1), true, + TYPE_SIMBA_PCI_BRIDGE); s->bridgeA = PCI_BRIDGE(pci_dev); pci_bridge_map_irq(s->bridgeA, "pciA", pci_simbaA_map_irq); - qdev_init_nofail(&pci_dev->qdev); + pci_realize_and_unref(pci_dev, phb->bus, &error_fatal); } static void sabre_init(Object *obj) { - SabreState *s = SABRE_DEVICE(obj); + SabreState *s = SABRE(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); unsigned int i; @@ -501,7 +484,7 @@ static const TypeInfo sabre_pci_info = { static char *sabre_ofw_unit_address(const SysBusDevice *dev) { - SabreState *s = SABRE_DEVICE(dev); + SabreState *s = SABRE(dev); return g_strdup_printf("%x,%x", (uint32_t)((s->special_base >> 32) & 0xffffffff), diff --git a/hw/pci-host/trace.h b/hw/pci-host/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..93ec814a73cdf87d84e93a6052b5348534d35306 --- /dev/null +++ b/hw/pci-host/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_pci_host.h" diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c index 1ed1072eeb5239b8291dace111fe52494ec7d886..0c0a9ecee145c5ea6f0dddd1d0cd4eec8aefb779 100644 --- a/hw/pci-host/uninorth.c +++ b/hw/pci-host/uninorth.c @@ -32,8 +32,6 @@ #include "hw/pci-host/uninorth.h" #include "trace.h" -static const int unin_irq_line[] = { 0x1b, 0x1c, 0x1d, 0x1e }; - static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num) { return (irq_num + (pci_dev->devfn >> 3)) & 3; @@ -43,7 +41,7 @@ static void pci_unin_set_irq(void *opaque, int irq_num, int level) { UNINHostState *s = opaque; - trace_unin_set_irq(unin_irq_line[irq_num], level); + trace_unin_set_irq(irq_num, level); qemu_set_irq(s->irqs[irq_num], level); } @@ -112,15 +110,6 @@ static const MemoryRegionOps unin_data_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static void pci_unin_init_irqs(UNINHostState *s) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(s->irqs); i++) { - s->irqs[i] = qdev_get_gpio_in(DEVICE(s->pic), unin_irq_line[i]); - } -} - static char *pci_unin_main_ofw_unit_address(const SysBusDevice *dev) { UNINHostState *s = UNI_NORTH_PCI_HOST_BRIDGE(dev); @@ -141,7 +130,6 @@ static void pci_unin_main_realize(DeviceState *dev, Error **errp) PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS); pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-pci"); - pci_unin_init_irqs(s); /* DEC 21154 bridge */ #if 0 @@ -172,15 +160,12 @@ static void pci_unin_main_init(Object *obj) "unin-pci-hole", &s->pci_mmio, 0x80000000ULL, 0x10000000ULL); - object_property_add_link(obj, "pic", TYPE_OPENPIC, - (Object **) &s->pic, - qdev_prop_allow_set_link_before_realize, - 0); - sysbus_init_mmio(sbd, &h->conf_mem); sysbus_init_mmio(sbd, &h->data_mem); sysbus_init_mmio(sbd, &s->pci_hole); sysbus_init_mmio(sbd, &s->pci_io); + + qdev_init_gpio_out(DEVICE(obj), s->irqs, ARRAY_SIZE(s->irqs)); } static void pci_u3_agp_realize(DeviceState *dev, Error **errp) @@ -196,7 +181,6 @@ static void pci_u3_agp_realize(DeviceState *dev, Error **errp) PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS); pci_create_simple(h->bus, PCI_DEVFN(11, 0), "u3-agp"); - pci_unin_init_irqs(s); } static void pci_u3_agp_init(Object *obj) @@ -220,15 +204,12 @@ static void pci_u3_agp_init(Object *obj) "unin-pci-hole", &s->pci_mmio, 0x80000000ULL, 0x70000000ULL); - object_property_add_link(obj, "pic", TYPE_OPENPIC, - (Object **) &s->pic, - qdev_prop_allow_set_link_before_realize, - 0); - sysbus_init_mmio(sbd, &h->conf_mem); sysbus_init_mmio(sbd, &h->data_mem); sysbus_init_mmio(sbd, &s->pci_hole); sysbus_init_mmio(sbd, &s->pci_io); + + qdev_init_gpio_out(DEVICE(obj), s->irqs, ARRAY_SIZE(s->irqs)); } static void pci_unin_agp_realize(DeviceState *dev, Error **errp) @@ -244,7 +225,6 @@ static void pci_unin_agp_realize(DeviceState *dev, Error **errp) PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS); pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-agp"); - pci_unin_init_irqs(s); } static void pci_unin_agp_init(Object *obj) @@ -259,13 +239,10 @@ static void pci_unin_agp_init(Object *obj) memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops, obj, "unin-agp-conf-data", 0x1000); - object_property_add_link(obj, "pic", TYPE_OPENPIC, - (Object **) &s->pic, - qdev_prop_allow_set_link_before_realize, - 0); - sysbus_init_mmio(sbd, &h->conf_mem); sysbus_init_mmio(sbd, &h->data_mem); + + qdev_init_gpio_out(DEVICE(obj), s->irqs, ARRAY_SIZE(s->irqs)); } static void pci_unin_internal_realize(DeviceState *dev, Error **errp) @@ -281,7 +258,6 @@ static void pci_unin_internal_realize(DeviceState *dev, Error **errp) PCI_DEVFN(14, 0), 4, TYPE_PCI_BUS); pci_create_simple(h->bus, PCI_DEVFN(14, 0), "uni-north-internal-pci"); - pci_unin_init_irqs(s); } static void pci_unin_internal_init(Object *obj) @@ -296,13 +272,10 @@ static void pci_unin_internal_init(Object *obj) memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops, obj, "unin-pci-conf-data", 0x1000); - object_property_add_link(obj, "pic", TYPE_OPENPIC, - (Object **) &s->pic, - qdev_prop_allow_set_link_before_realize, - 0); - sysbus_init_mmio(sbd, &h->conf_mem); sysbus_init_mmio(sbd, &h->data_mem); + + qdev_init_gpio_out(DEVICE(obj), s->irqs, ARRAY_SIZE(s->irqs)); } static void unin_main_pci_host_realize(PCIDevice *d, Error **errp) diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c index cfb9a78ea6b116ec29bcc611648004a89dd00a38..3553277f941e570a70b060263d6b91aaec5b8581 100644 --- a/hw/pci-host/versatile.c +++ b/hw/pci-host/versatile.c @@ -8,6 +8,7 @@ */ #include "qemu/osdep.h" +#include "qemu/units.h" #include "hw/sysbus.h" #include "migration/vmstate.h" #include "hw/irq.h" @@ -17,6 +18,7 @@ #include "hw/qdev-properties.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" /* Old and buggy versions of QEMU used the wrong mapping from * PCI IRQs to system interrupt lines. Unfortunately the Linux @@ -70,7 +72,7 @@ enum { PCI_VPB_IRQMAP_FORCE_OK, }; -typedef struct { +struct PCIVPBState { PCIHostState parent_obj; qemu_irq irq[4]; @@ -99,7 +101,8 @@ typedef struct { uint32_t selfid; uint32_t flags; uint8_t irq_mapping; -} PCIVPBState; +}; +typedef struct PCIVPBState PCIVPBState; static void pci_vpb_update_window(PCIVPBState *s, int i) { @@ -155,12 +158,12 @@ static const VMStateDescription pci_vpb_vmstate = { }; #define TYPE_VERSATILE_PCI "versatile_pci" -#define PCI_VPB(obj) \ - OBJECT_CHECK(PCIVPBState, (obj), TYPE_VERSATILE_PCI) +DECLARE_INSTANCE_CHECKER(PCIVPBState, PCI_VPB, + TYPE_VERSATILE_PCI) #define TYPE_VERSATILE_PCI_HOST "versatile_pci_host" -#define PCI_VPB_HOST(obj) \ - OBJECT_CHECK(PCIDevice, (obj), TYPE_VERSATILE_PCIHOST) +DECLARE_INSTANCE_CHECKER(PCIDevice, PCI_VPB_HOST, + TYPE_VERSATILE_PCI_HOST) typedef enum { PCI_IMAP0 = 0x0, @@ -399,8 +402,8 @@ static void pci_vpb_realize(DeviceState *dev, Error **errp) pci_map_irq_fn mapfn; int i; - memory_region_init(&s->pci_io_space, OBJECT(s), "pci_io", 1ULL << 32); - memory_region_init(&s->pci_mem_space, OBJECT(s), "pci_mem", 1ULL << 32); + memory_region_init(&s->pci_io_space, OBJECT(s), "pci_io", 4 * GiB); + memory_region_init(&s->pci_mem_space, OBJECT(s), "pci_mem", 4 * GiB); pci_root_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), dev, "pci", &s->pci_mem_space, &s->pci_io_space, @@ -408,7 +411,6 @@ static void pci_vpb_realize(DeviceState *dev, Error **errp) h->bus = &s->pci_bus; object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_VERSATILE_PCI_HOST); - qdev_set_parent_bus(DEVICE(&s->pci_dev), BUS(&s->pci_bus)); for (i = 0; i < 4; i++) { sysbus_init_irq(sbd, &s->irq[i]); @@ -458,8 +460,7 @@ static void pci_vpb_realize(DeviceState *dev, Error **errp) } /* TODO Remove once realize propagates to child devices. */ - object_property_set_bool(OBJECT(&s->pci_bus), true, "realized", errp); - object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp); + qdev_realize(DEVICE(&s->pci_dev), BUS(&s->pci_bus), errp); } static void versatile_pci_host_realize(PCIDevice *d, Error **errp) diff --git a/hw/pci-host/xen_igd_pt.c b/hw/pci-host/xen_igd_pt.c index efcc9347ff6908370c54925cb44959a659cadffc..d094b675d6d3961c277f2f32457b16f87d367233 100644 --- a/hw/pci-host/xen_igd_pt.c +++ b/hw/pci-host/xen_igd_pt.c @@ -79,17 +79,16 @@ static void host_pci_config_read(int pos, int len, uint32_t *val, Error **errp) static void igd_pt_i440fx_realize(PCIDevice *pci_dev, Error **errp) { + ERRP_GUARD(); uint32_t val = 0; size_t i; int pos, len; - Error *local_err = NULL; for (i = 0; i < ARRAY_SIZE(igd_host_bridge_infos); i++) { pos = igd_host_bridge_infos[i].offset; len = igd_host_bridge_infos[i].len; - host_pci_config_read(pos, len, &val, &local_err); - if (local_err) { - error_propagate(errp, local_err); + host_pci_config_read(pos, len, &val, errp); + if (*errp) { return; } pci_default_write_config(pci_dev, pos, val, len); diff --git a/hw/pci-host/xilinx-pcie.c b/hw/pci-host/xilinx-pcie.c index e06f2b59cffc73a9c5fbdfc9cdb3d8b2051df2a3..38d5901a454fd92cc5bc343772fe9679643daf11 100644 --- a/hw/pci-host/xilinx-pcie.c +++ b/hw/pci-host/xilinx-pcie.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -137,8 +137,7 @@ static void xilinx_pcie_host_realize(DeviceState *dev, Error **errp) pci_swizzle_map_irq_fn, s, &s->mmio, &s->io, 0, 4, TYPE_PCIE_BUS); - qdev_set_parent_bus(DEVICE(&s->root), BUS(pci->bus)); - qdev_init_nofail(DEVICE(&s->root)); + qdev_realize(DEVICE(&s->root), BUS(pci->bus), &error_fatal); } static const char *xilinx_pcie_host_root_bus_path(PCIHostState *host_bridge, @@ -152,8 +151,7 @@ static void xilinx_pcie_host_init(Object *obj) XilinxPCIEHost *s = XILINX_PCIE_HOST(obj); XilinxPCIERoot *root = &s->root; - object_initialize_child(obj, "root", root, sizeof(*root), - TYPE_XILINX_PCIE_ROOT, &error_abort, NULL); + object_initialize_child(obj, "root", root, TYPE_XILINX_PCIE_ROOT); qdev_prop_set_int32(DEVICE(root), "addr", PCI_DEVFN(0, 0)); qdev_prop_set_bit(DEVICE(root), "multifunction", false); } diff --git a/hw/pci/Makefile.objs b/hw/pci/Makefile.objs deleted file mode 100644 index c78f2fb24b535a6b3d40729cab1da2c89167cfbb..0000000000000000000000000000000000000000 --- a/hw/pci/Makefile.objs +++ /dev/null @@ -1,14 +0,0 @@ -common-obj-$(CONFIG_PCI) += pci.o pci_bridge.o -common-obj-$(CONFIG_PCI) += msix.o msi.o -common-obj-$(CONFIG_PCI) += shpc.o -common-obj-$(CONFIG_PCI) += slotid_cap.o -common-obj-$(CONFIG_PCI) += pci_host.o - -# The functions in these modules can be used by devices too. Since we -# allow plugging PCIe devices into PCI buses, include them even if -# CONFIG_PCI_EXPRESS=n. -common-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o -common-obj-$(CONFIG_PCI_EXPRESS) += pcie_port.o pcie_host.o - -common-obj-$(call lnot,$(CONFIG_PCI)) += pci-stub.o -common-obj-$(CONFIG_ALL) += pci-stub.o diff --git a/hw/pci/meson.build b/hw/pci/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..5c4bbac81716b81637fbfaba7a2eb3db494e0d97 --- /dev/null +++ b/hw/pci/meson.build @@ -0,0 +1,19 @@ +pci_ss = ss.source_set() +pci_ss.add(files( + 'msi.c', + 'msix.c', + 'pci.c', + 'pci_bridge.c', + 'pci_host.c', + 'shpc.c', + 'slotid_cap.c' +)) +# The functions in these modules can be used by devices too. Since we +# allow plugging PCIe devices into PCI buses, include them even if +# CONFIG_PCI_EXPRESS=n. +pci_ss.add(files('pcie.c', 'pcie_aer.c')) +softmmu_ss.add(when: 'CONFIG_PCI_EXPRESS', if_true: files('pcie_port.c', 'pcie_host.c')) +softmmu_ss.add_all(when: 'CONFIG_PCI', if_true: pci_ss) + +softmmu_ss.add(when: 'CONFIG_PCI', if_false: files('pci-stub.c')) +softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('pci-stub.c')) diff --git a/hw/pci/msix.c b/hw/pci/msix.c index 29187898f2b9c160c6896178f912aae9eea24652..67e34f34d6584eff4eb55ffe053b5bb677032600 100644 --- a/hw/pci/msix.c +++ b/hw/pci/msix.c @@ -19,6 +19,7 @@ #include "hw/pci/msix.h" #include "hw/pci/pci.h" #include "hw/xen/xen.h" +#include "sysemu/xen.h" #include "migration/qemu-file-types.h" #include "migration/vmstate.h" #include "qemu/range.h" @@ -199,6 +200,9 @@ static const MemoryRegionOps msix_table_mmio_ops = { .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 4, + .max_access_size = 8, + }, + .impl = { .max_access_size = 4, }, }; @@ -227,6 +231,9 @@ static const MemoryRegionOps msix_pba_mmio_ops = { .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 4, + .max_access_size = 8, + }, + .impl = { .max_access_size = 4, }, }; diff --git a/hw/pci/pci-stub.c b/hw/pci/pci-stub.c index cc2a2e1f735d9c620920d5ff7b5cc24eb521491a..3a027c42e43bcac0003cea966697f8918e46b53e 100644 --- a/hw/pci/pci-stub.c +++ b/hw/pci/pci-stub.c @@ -22,7 +22,7 @@ #include "sysemu/sysemu.h" #include "monitor/monitor.h" #include "qapi/error.h" -#include "qapi/qapi-commands-misc.h" +#include "qapi/qapi-commands-pci.h" #include "qapi/qmp/qerror.h" #include "hw/pci/pci.h" #include "hw/pci/msi.h" diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 70c66965f56868691dd0f1112d12c6b0be3e63f1..0131d9d02c16ad02044d8658af83631e3b09bb92 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -46,7 +46,7 @@ #include "hw/hotplug.h" #include "hw/boards.h" #include "qapi/error.h" -#include "qapi/qapi-commands-misc.h" +#include "qapi/qapi-commands-pci.h" #include "qemu/cutils.h" //#define DEBUG_PCI @@ -248,6 +248,14 @@ static inline void pci_set_irq_state(PCIDevice *d, int irq_num, int level) d->irq_state |= level << irq_num; } +static void pci_bus_change_irq_level(PCIBus *bus, int irq_num, int change) +{ + assert(irq_num >= 0); + assert(irq_num < bus->nirq); + bus->irq_count[irq_num] += change; + bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0); +} + static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change) { PCIBus *bus; @@ -258,8 +266,7 @@ static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change) break; pci_dev = bus->parent_dev; } - bus->irq_count[irq_num] += change; - bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0); + pci_bus_change_irq_level(bus, irq_num, change); } int pci_bus_get_irq_level(PCIBus *bus, int irq_num) @@ -456,7 +463,7 @@ void pci_root_bus_cleanup(PCIBus *bus) { pci_bus_uninit(bus); /* the caller of the unplug hotplug handler will delete this device */ - object_property_set_bool(OBJECT(bus), false, "realized", &error_abort); + qbus_unrealize(BUS(bus)); } void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, @@ -1036,7 +1043,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, return NULL; } else if (dev->hotplugged && pci_get_function_0(pci_dev)) { - error_setg(errp, "PCI: slot %d function 0 already ocuppied by %s," + error_setg(errp, "PCI: slot %d function 0 already occupied by %s," " new func %s cannot be exposed to guest.", PCI_SLOT(pci_get_function_0(pci_dev)->devfn), pci_get_function_0(pci_dev)->name, @@ -1141,14 +1148,16 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num, uint32_t addr; /* offset in pci config space */ uint64_t wmask; pcibus_t size = memory_region_size(memory); + uint8_t hdr_type; assert(region_num >= 0); assert(region_num < PCI_NUM_REGIONS); - if (size & (size-1)) { - error_report("ERROR: PCI region size must be pow2 " - "type=0x%x, size=0x%"FMT_PCIBUS"", type, size); - exit(1); - } + assert(is_power_of_2(size)); + + /* A PCI bridge device (with Type 1 header) may only have at most 2 BARs */ + hdr_type = + pci_dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION; + assert(hdr_type != PCI_HEADER_TYPE_BRIDGE || region_num < 2); r = &pci_dev->io_regions[region_num]; r->addr = PCI_BAR_UNMAPPED; @@ -1381,6 +1390,8 @@ uint32_t pci_default_read_config(PCIDevice *d, { uint32_t val = 0; + assert(address + len <= pci_config_size(d)); + if (pci_is_express_downstream_port(d) && ranges_overlap(address, len, d->exp.exp_cap + PCI_EXP_LNKSTA, 2)) { pcie_sync_bridge_lnk(d); @@ -1394,6 +1405,8 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val_in, int int i, was_irq_disabled = pci_irq_disabled(d); uint32_t val = val_in; + assert(addr + l <= pci_config_size(d)); + for (i = 0; i < l; val >>= 8, ++i) { uint8_t wmask = d->wmask[addr + i]; uint8_t w1cmask = d->w1cmask[addr + i]; @@ -1772,6 +1785,7 @@ static PciDeviceInfo *qmp_query_pci_device(PCIDevice *dev, PCIBus *bus, info->regions = qmp_query_pci_regions(dev); info->qdev_id = g_strdup(dev->qdev.id ? dev->qdev.id : ""); + info->irq_pin = dev->config[PCI_INTERRUPT_PIN]; if (dev->config[PCI_INTERRUPT_PIN] != 0) { info->has_irq = true; info->irq = dev->config[PCI_INTERRUPT_LINE]; @@ -1887,7 +1901,18 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus, if (test_bit(DEVICE_CATEGORY_NETWORK, dc->categories) && dc->user_creatable) { const char *name = object_class_get_name(list->data); - g_ptr_array_add(pci_nic_models, (gpointer)name); + /* + * A network device might also be something else than a NIC, see + * e.g. the "rocker" device. Thus we have to look for the "netdev" + * property, too. Unfortunately, some devices like virtio-net only + * create this property during instance_init, so we have to create + * a temporary instance here to be able to check it. + */ + Object *obj = object_new_with_class(OBJECT_CLASS(dc)); + if (object_property_find(obj, "netdev")) { + g_ptr_array_add(pci_nic_models, (gpointer)name); + } + object_unref(obj); } next = list->next; g_slist_free_1(list); @@ -1937,10 +1962,10 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus, exit(1); } - pci_dev = pci_create(bus, devfn, nd->model); + pci_dev = pci_new(devfn, nd->model); dev = &pci_dev->qdev; qdev_set_nic_properties(dev, nd); - qdev_init_nofail(dev); + pci_realize_and_unref(pci_dev, bus, &error_fatal); g_ptr_array_free(pci_nic_models, true); return pci_dev; } @@ -2107,7 +2132,6 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) if (!pci_bus_is_express(pci_get_bus(pci_dev))) { error_setg(errp, "failover primary device must be on " "PCIExpress bus"); - error_propagate(errp, local_err); pci_qdev_unrealize(DEVICE(pci_dev)); return; } @@ -2115,7 +2139,6 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) if (class_id != PCI_CLASS_NETWORK_ETHERNET) { error_setg(errp, "failover primary device is not an " "Ethernet device"); - error_propagate(errp, local_err); pci_qdev_unrealize(DEVICE(pci_dev)); return; } @@ -2125,7 +2148,6 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) } else { error_setg(errp, "failover: primary device must be in its own " "PCI slot"); - error_propagate(errp, local_err); pci_qdev_unrealize(DEVICE(pci_dev)); return; } @@ -2147,31 +2169,36 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) } } -PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction, - const char *name) +PCIDevice *pci_new_multifunction(int devfn, bool multifunction, + const char *name) { DeviceState *dev; - dev = qdev_create(&bus->qbus, name); + dev = qdev_new(name); qdev_prop_set_int32(dev, "addr", devfn); qdev_prop_set_bit(dev, "multifunction", multifunction); return PCI_DEVICE(dev); } +PCIDevice *pci_new(int devfn, const char *name) +{ + return pci_new_multifunction(devfn, false, name); +} + +bool pci_realize_and_unref(PCIDevice *dev, PCIBus *bus, Error **errp) +{ + return qdev_realize_and_unref(&dev->qdev, &bus->qbus, errp); +} + PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn, bool multifunction, const char *name) { - PCIDevice *dev = pci_create_multifunction(bus, devfn, multifunction, name); - qdev_init_nofail(&dev->qdev); + PCIDevice *dev = pci_new_multifunction(devfn, multifunction, name); + pci_realize_and_unref(dev, bus, &error_fatal); return dev; } -PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name) -{ - return pci_create_multifunction(bus, devfn, false, name); -} - PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name) { return pci_create_simple_multifunction(bus, devfn, false, name); diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c index 97967d12eb4503f5d7594409a156084e65741a27..3789c17edc2ad3b1064aeb32a89bfd6f8c4bfdbb 100644 --- a/hw/pci/pci_bridge.c +++ b/hw/pci/pci_bridge.c @@ -30,6 +30,7 @@ */ #include "qemu/osdep.h" +#include "qemu/units.h" #include "hw/pci/pci_bridge.h" #include "hw/pci/pci_bus.h" #include "qemu/module.h" @@ -381,7 +382,7 @@ void pci_bridge_initfn(PCIDevice *dev, const char *typename) memory_region_init(&br->address_space_mem, OBJECT(br), "pci_bridge_pci", UINT64_MAX); sec_bus->address_space_io = &br->address_space_io; memory_region_init(&br->address_space_io, OBJECT(br), "pci_bridge_io", - UINT32_MAX); + 4 * GiB); br->windows = pci_bridge_region_init(br); QLIST_INIT(&sec_bus->child); QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling); @@ -422,14 +423,14 @@ int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset, } if (res_reserve.mem_non_pref != (uint64_t)-1 && - res_reserve.mem_non_pref >= (1ULL << 32)) { + res_reserve.mem_non_pref >= 4 * GiB) { error_setg(errp, "PCI resource reserve cap: mem-reserve must be less than 4G"); return -EINVAL; } if (res_reserve.mem_pref_32 != (uint64_t)-1 && - res_reserve.mem_pref_32 >= (1ULL << 32)) { + res_reserve.mem_pref_32 >= 4 * GiB) { error_setg(errp, "PCI resource reserve cap: pref32-reserve must be less than 4G"); return -EINVAL; diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c index ce7bcdb1d52cf4b4680f80ef7818eeadd7f0badf..8ca5fadcbd4c49fc71c1a0e44ab4aced2953aa0c 100644 --- a/hw/pci/pci_host.c +++ b/hw/pci/pci_host.c @@ -22,8 +22,10 @@ #include "hw/pci/pci.h" #include "hw/pci/pci_bridge.h" #include "hw/pci/pci_host.h" +#include "hw/qdev-properties.h" #include "qemu/module.h" #include "hw/pci/pci_bus.h" +#include "migration/vmstate.h" #include "trace.h" /* debug PCI */ @@ -200,12 +202,43 @@ const MemoryRegionOps pci_host_data_be_ops = { .endianness = DEVICE_BIG_ENDIAN, }; +static bool pci_host_needed(void *opaque) +{ + PCIHostState *s = opaque; + return s->mig_enabled; +} + +const VMStateDescription vmstate_pcihost = { + .name = "PCIHost", + .needed = pci_host_needed, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(config_reg, PCIHostState), + VMSTATE_END_OF_LIST() + } +}; + +static Property pci_host_properties_common[] = { + DEFINE_PROP_BOOL("x-config-reg-migration-enabled", PCIHostState, + mig_enabled, true), + DEFINE_PROP_END_OF_LIST(), +}; + +static void pci_host_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + device_class_set_props(dc, pci_host_properties_common); + dc->vmsd = &vmstate_pcihost; +} + static const TypeInfo pci_host_type_info = { .name = TYPE_PCI_HOST_BRIDGE, .parent = TYPE_SYS_BUS_DEVICE, .abstract = true, .class_size = sizeof(PCIHostBridgeClass), .instance_size = sizeof(PCIHostState), + .class_init = pci_host_class_init, }; static void pci_host_register_types(void) diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index f50e10b8fbbb1f130748c992a8404141622a7d12..d4010cf8f36178758315627d56bb44780742b71a 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -407,6 +407,17 @@ static void pcie_cap_slot_plug_common(PCIDevice *hotplug_dev, DeviceState *dev, void pcie_cap_slot_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { + PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev); + uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap; + uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP); + + /* Check if hot-plug is disabled on the slot */ + if (dev->hotplugged && (sltcap & PCI_EXP_SLTCAP_HPC) == 0) { + error_setg(errp, "Hot-plug failed: unsupported by the port device '%s'", + DEVICE(hotplug_pdev)->id); + return; + } + pcie_cap_slot_plug_common(PCI_DEVICE(hotplug_dev), dev, errp); } @@ -415,7 +426,6 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, { PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev); uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap; - uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP); PCIDevice *pci_dev = PCI_DEVICE(dev); /* Don't send event when device is enabled during qemu machine creation: @@ -431,13 +441,6 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, return; } - /* Check if hot-plug is disabled on the slot */ - if ((sltcap & PCI_EXP_SLTCAP_HPC) == 0) { - error_setg(errp, "Hot-plug failed: unsupported by the port device '%s'", - DEVICE(hotplug_pdev)->id); - return; - } - /* To enable multifunction hot-plug, we just ensure the function * 0 added last. When function 0 is added, we set the sltsta and * inform OS via event notification. @@ -457,7 +460,7 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, void pcie_cap_slot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + qdev_unrealize(dev); } static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque) @@ -571,7 +574,7 @@ void pcie_cap_slot_init(PCIDevice *dev, PCIESlot *s) dev->exp.hpev_notified = false; qbus_set_hotplug_handler(BUS(pci_bridge_get_sec_bus(PCI_BRIDGE(dev))), - OBJECT(dev), NULL); + OBJECT(dev)); } void pcie_cap_slot_reset(PCIDevice *dev) @@ -968,8 +971,9 @@ void pcie_ats_init(PCIDevice *dev, uint16_t offset) dev->exp.ats_cap = offset; - /* Invalidate Queue Depth 0, Page Aligned Request 0 */ - pci_set_word(dev->config + offset + PCI_ATS_CAP, 0); + /* Invalidate Queue Depth 0, Page Aligned Request 1 */ + pci_set_word(dev->config + offset + PCI_ATS_CAP, + PCI_ATS_CAP_PAGE_ALIGNED); /* STU 0, Disabled by default */ pci_set_word(dev->config + offset + PCI_ATS_CTRL, 0); diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c index b76d3d2c9ab7e67e44eb3343911434f786199429..b00dce629c0bd1311e6c69f23df32348c2df13b1 100644 --- a/hw/pci/shpc.c +++ b/hw/pci/shpc.c @@ -547,7 +547,7 @@ void shpc_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, void shpc_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + qdev_unrealize(dev); } void shpc_device_unplug_request_cb(HotplugHandler *hotplug_dev, @@ -649,7 +649,7 @@ int shpc_init(PCIDevice *d, PCIBus *sec_bus, MemoryRegion *bar, shpc_cap_update_dword(d); memory_region_add_subregion(bar, offset, &shpc->mmio); - qbus_set_hotplug_handler(BUS(sec_bus), OBJECT(d), NULL); + qbus_set_hotplug_handler(BUS(sec_bus), OBJECT(d)); d->cap_present |= QEMU_PCI_CAP_SHPC; return 0; diff --git a/hw/pci/trace.h b/hw/pci/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..3dd773e22ac02ce6c02375a653eb54635ff533b1 --- /dev/null +++ b/hw/pci/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_pci.h" diff --git a/hw/pcmcia/Makefile.objs b/hw/pcmcia/Makefile.objs deleted file mode 100644 index 02cd986a2c760e8da429bf93aa0185578dd752f6..0000000000000000000000000000000000000000 --- a/hw/pcmcia/Makefile.objs +++ /dev/null @@ -1,2 +0,0 @@ -common-obj-y += pcmcia.o -common-obj-$(CONFIG_PXA2XX) += pxa2xx.o diff --git a/hw/pcmcia/meson.build b/hw/pcmcia/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..ab50bd325d6c86160e7aaeed248eed8184fd5a50 --- /dev/null +++ b/hw/pcmcia/meson.build @@ -0,0 +1,2 @@ +softmmu_ss.add(files('pcmcia.c')) +softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx.c')) diff --git a/hw/pcmcia/pxa2xx.c b/hw/pcmcia/pxa2xx.c index 8667244df4db1aadea467f5c4e4cf6606c6eb291..fcca7e571b2ffb1cd61765f3c6a5866032baa2b5 100644 --- a/hw/pcmcia/pxa2xx.c +++ b/hw/pcmcia/pxa2xx.c @@ -13,14 +13,11 @@ #include "qemu/osdep.h" #include "hw/irq.h" #include "hw/sysbus.h" +#include "qapi/error.h" #include "qemu/module.h" #include "hw/pcmcia.h" #include "hw/arm/pxa.h" -#define TYPE_PXA2XX_PCMCIA "pxa2xx-pcmcia" -#define PXA2XX_PCMCIA(obj) \ - OBJECT_CHECK(PXA2xxPCMCIAState, obj, TYPE_PXA2XX_PCMCIA) - struct PXA2xxPCMCIAState { SysBusDevice parent_obj; @@ -147,11 +144,11 @@ PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, DeviceState *dev; PXA2xxPCMCIAState *s; - dev = qdev_create(NULL, TYPE_PXA2XX_PCMCIA); + dev = qdev_new(TYPE_PXA2XX_PCMCIA); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); s = PXA2XX_PCMCIA(dev); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); return s; } diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs deleted file mode 100644 index c3d3cc56eb5142b85e69b652e544d8eec4f39b0c..0000000000000000000000000000000000000000 --- a/hw/ppc/Makefile.objs +++ /dev/null @@ -1,35 +0,0 @@ -# shared objects -obj-y += ppc.o ppc_booke.o -obj-$(CONFIG_FDT_PPC) += fdt.o -obj-$(CONFIG_FW_CFG_PPC) += fw_cfg.o -# IBM pSeries (sPAPR) -obj-$(CONFIG_PSERIES) += spapr.o spapr_caps.o spapr_vio.o spapr_events.o -obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o -obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o -obj-$(CONFIG_PSERIES) += spapr_cpu_core.o spapr_ovec.o spapr_irq.o -obj-$(CONFIG_PSERIES) += spapr_tpm_proxy.o spapr_nvdimm.o -obj-$(CONFIG_SPAPR_RNG) += spapr_rng.o -obj-$(call land,$(CONFIG_PSERIES),$(CONFIG_LINUX)) += spapr_pci_vfio.o spapr_pci_nvlink2.o -# IBM PowerNV -obj-$(CONFIG_POWERNV) += pnv.o pnv_xscom.o pnv_core.o pnv_lpc.o pnv_psi.o pnv_occ.o pnv_bmc.o -obj-$(CONFIG_POWERNV) += pnv_homer.o pnv_pnor.o - -obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o -# PowerPC 4xx boards -obj-$(CONFIG_PPC405) += ppc405_boards.o ppc405_uc.o -obj-$(CONFIG_PPC440) += ppc440_bamboo.o ppc440_pcix.o ppc440_uc.o -obj-$(CONFIG_PPC4XX) += ppc4xx_pci.o ppc4xx_devs.o -obj-$(CONFIG_SAM460EX) += sam460ex.o -# PReP -obj-$(CONFIG_PREP) += prep.o -obj-$(CONFIG_PREP) += prep_systemio.o -obj-${CONFIG_RS6000_MC} += rs6000_mc.o -# OldWorld PowerMac -obj-$(CONFIG_MAC_OLDWORLD) += mac_oldworld.o -# NewWorld PowerMac -obj-$(CONFIG_MAC_NEWWORLD) += mac_newworld.o -# e500 -obj-$(CONFIG_E500) += e500.o mpc8544ds.o e500plat.o -obj-$(CONFIG_E500) += mpc8544_guts.o ppce500_spin.o -# PowerPC 440 Xilinx ML507 reference board. -obj-$(CONFIG_VIRTEX) += virtex_ml507.o diff --git a/hw/ppc/e500-ccsr.h b/hw/ppc/e500-ccsr.h index 12a2ba4b97826b67408fffaf72ce3788cd4796d1..249c17be3b8107e6a3cee1369c3761e9f54e4b08 100644 --- a/hw/ppc/e500-ccsr.h +++ b/hw/ppc/e500-ccsr.h @@ -2,16 +2,17 @@ #define E500_CCSR_H #include "hw/sysbus.h" +#include "qom/object.h" -typedef struct PPCE500CCSRState { +struct PPCE500CCSRState { /*< private >*/ SysBusDevice parent; /*< public >*/ MemoryRegion ccsr_space; -} PPCE500CCSRState; +}; #define TYPE_CCSR "e500-ccsr" -#define CCSR(obj) OBJECT_CHECK(PPCE500CCSRState, (obj), TYPE_CCSR) +OBJECT_DECLARE_SIMPLE_TYPE(PPCE500CCSRState, CCSR) #endif /* E500_CCSR_H */ diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 2a0b66a15298c20deaa4462cccd90fc16958b151..ae39b9358e88c6705d1509c54f4abd214f3ae63c 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -704,9 +704,6 @@ static void ppce500_cpu_reset_sec(void *opaque) cpu_reset(cs); - /* Secondary CPU starts in halted state for now. Needs to change when - implementing non-kernel boot. */ - cs->halted = 1; cs->exception_index = EXCP_HLT; } @@ -743,13 +740,13 @@ static DeviceState *ppce500_init_mpic_qemu(PPCE500MachineState *pms, unsigned int smp_cpus = machine->smp.cpus; const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms); - dev = qdev_create(NULL, TYPE_OPENPIC); + dev = qdev_new(TYPE_OPENPIC); object_property_add_child(OBJECT(machine), "pic", OBJECT(dev)); qdev_prop_set_uint32(dev, "model", pmc->mpic_version); qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); k = 0; for (i = 0; i < smp_cpus; i++) { @@ -764,16 +761,13 @@ static DeviceState *ppce500_init_mpic_qemu(PPCE500MachineState *pms, static DeviceState *ppce500_init_mpic_kvm(const PPCE500MachineClass *pmc, IrqLines *irqs, Error **errp) { - Error *err = NULL; DeviceState *dev; CPUState *cs; - dev = qdev_create(NULL, TYPE_KVM_OPENPIC); + dev = qdev_new(TYPE_KVM_OPENPIC); qdev_prop_set_uint32(dev, "model", pmc->mpic_version); - object_property_set_bool(OBJECT(dev), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp)) { object_unparent(OBJECT(dev)); return NULL; } @@ -868,7 +862,7 @@ void ppce500_init(MachineState *machine) CPUState *cs; qemu_irq *input; - cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); + cpu = POWERPC_CPU(object_new(machine->cpu_type)); env = &cpu->env; cs = CPU(cpu); @@ -878,6 +872,14 @@ void ppce500_init(MachineState *machine) exit(1); } + /* + * Secondary CPU starts in halted state for now. Needs to change + * when implementing non-kernel boot. + */ + object_property_set_bool(OBJECT(cs), "start-powered-off", i != 0, + &error_fatal); + qdev_realize_and_unref(DEVICE(cs), NULL, &error_fatal); + if (!firstenv) { firstenv = env; } @@ -913,10 +915,10 @@ void ppce500_init(MachineState *machine) /* Register Memory */ memory_region_add_subregion(address_space_mem, 0, machine->ram); - dev = qdev_create(NULL, "e500-ccsr"); + dev = qdev_new("e500-ccsr"); object_property_add_child(qdev_get_machine(), "e500-ccsr", OBJECT(dev)); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); ccsr = CCSR(dev); ccsr_addr_space = &ccsr->ccsr_space; memory_region_add_subregion(address_space_mem, pmc->ccsrbar_base, @@ -937,30 +939,30 @@ void ppce500_init(MachineState *machine) serial_hd(1), DEVICE_BIG_ENDIAN); } /* I2C */ - dev = qdev_create(NULL, "mpc-i2c"); + dev = qdev_new("mpc-i2c"); s = SYS_BUS_DEVICE(dev); - qdev_init_nofail(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_connect_irq(s, 0, qdev_get_gpio_in(mpicdev, MPC8544_I2C_IRQ)); memory_region_add_subregion(ccsr_addr_space, MPC8544_I2C_REGS_OFFSET, sysbus_mmio_get_region(s, 0)); i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c"); - i2c_create_slave(i2c, "ds1338", RTC_REGS_OFFSET); + i2c_slave_create_simple(i2c, "ds1338", RTC_REGS_OFFSET); /* General Utility device */ - dev = qdev_create(NULL, "mpc8544-guts"); - qdev_init_nofail(dev); + dev = qdev_new("mpc8544-guts"); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); memory_region_add_subregion(ccsr_addr_space, MPC8544_UTIL_OFFSET, sysbus_mmio_get_region(s, 0)); /* PCI */ - dev = qdev_create(NULL, "e500-pcihost"); + dev = qdev_new("e500-pcihost"); object_property_add_child(qdev_get_machine(), "pci-host", OBJECT(dev)); qdev_prop_set_uint32(dev, "first_slot", pmc->pci_first_slot); qdev_prop_set_uint32(dev, "first_pin_irq", pci_irq_nrs[0]); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); for (i = 0; i < PCI_NUM_PINS; i++) { sysbus_connect_irq(s, i, qdev_get_gpio_in(mpicdev, pci_irq_nrs[i])); } @@ -985,9 +987,9 @@ void ppce500_init(MachineState *machine) if (pmc->has_mpc8xxx_gpio) { qemu_irq poweroff_irq; - dev = qdev_create(NULL, "mpc8xxx_gpio"); + dev = qdev_new("mpc8xxx_gpio"); s = SYS_BUS_DEVICE(dev); - qdev_init_nofail(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_connect_irq(s, 0, qdev_get_gpio_in(mpicdev, MPC8XXX_GPIO_IRQ)); memory_region_add_subregion(ccsr_addr_space, MPC8XXX_GPIO_OFFSET, sysbus_mmio_get_region(s, 0)); @@ -999,11 +1001,11 @@ void ppce500_init(MachineState *machine) /* Platform Bus Device */ if (pmc->has_platform_bus) { - dev = qdev_create(NULL, TYPE_PLATFORM_BUS_DEVICE); + dev = qdev_new(TYPE_PLATFORM_BUS_DEVICE); dev->id = TYPE_PLATFORM_BUS_DEVICE; qdev_prop_set_uint32(dev, "num_irqs", pmc->platform_bus_num_irqs); qdev_prop_set_uint32(dev, "mmio_size", pmc->platform_bus_size); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); pms->pbus_dev = PLATFORM_BUS_DEVICE(dev); s = SYS_BUS_DEVICE(pms->pbus_dev); diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h index 3fd9f825cac3ad409f8e1aeb62f8e3a7f2486552..1e5853b032b71aebb628d75b0a98b31758e3204a 100644 --- a/hw/ppc/e500.h +++ b/hw/ppc/e500.h @@ -3,8 +3,9 @@ #include "hw/boards.h" #include "hw/platform-bus.h" +#include "qom/object.h" -typedef struct PPCE500MachineState { +struct PPCE500MachineState { /*< private >*/ MachineState parent_obj; @@ -12,9 +13,9 @@ typedef struct PPCE500MachineState { * board supports dynamic sysbus devices */ PlatformBusDevice *pbus_dev; -} PPCE500MachineState; +}; -typedef struct PPCE500MachineClass { +struct PPCE500MachineClass { /*< private >*/ MachineClass parent_class; @@ -36,18 +37,13 @@ typedef struct PPCE500MachineClass { hwaddr pci_mmio_base; hwaddr pci_mmio_bus_base; hwaddr spin_base; -} PPCE500MachineClass; +}; void ppce500_init(MachineState *machine); hwaddr booke206_page_size_to_tlb(uint64_t size); #define TYPE_PPCE500_MACHINE "ppce500-base-machine" -#define PPCE500_MACHINE(obj) \ - OBJECT_CHECK(PPCE500MachineState, (obj), TYPE_PPCE500_MACHINE) -#define PPCE500_MACHINE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PPCE500MachineClass, obj, TYPE_PPCE500_MACHINE) -#define PPCE500_MACHINE_CLASS(klass) \ - OBJECT_CLASS_CHECK(PPCE500MachineClass, klass, TYPE_PPCE500_MACHINE) +OBJECT_DECLARE_TYPE(PPCE500MachineState, PPCE500MachineClass, PPCE500_MACHINE) #endif diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h index 6af87d1fa051742a676fbcc595d7d621e58169ca..22c8408078d2c0689aa56e37f083bf0483401aa3 100644 --- a/hw/ppc/mac.h +++ b/hw/ppc/mac.h @@ -34,14 +34,13 @@ #include "hw/misc/mos6522.h" #include "hw/pci/pci_host.h" #include "hw/pci-host/uninorth.h" +#include "qom/object.h" /* SMP is not enabled, for now */ #define MAX_CPUS 1 -#define BIOS_SIZE (1 * MiB) #define NVRAM_SIZE 0x2000 #define PROM_FILENAME "openbios-ppc" -#define PROM_ADDR 0xfff00000 #define KERNEL_LOAD_ADDR 0x01000000 #define KERNEL_GAP 0x00100000 @@ -71,29 +70,29 @@ /* Core99 machine */ #define TYPE_CORE99_MACHINE MACHINE_TYPE_NAME("mac99") -#define CORE99_MACHINE(obj) OBJECT_CHECK(Core99MachineState, (obj), \ - TYPE_CORE99_MACHINE) +typedef struct Core99MachineState Core99MachineState; +DECLARE_INSTANCE_CHECKER(Core99MachineState, CORE99_MACHINE, + TYPE_CORE99_MACHINE) #define CORE99_VIA_CONFIG_CUDA 0x0 #define CORE99_VIA_CONFIG_PMU 0x1 #define CORE99_VIA_CONFIG_PMU_ADB 0x2 -typedef struct Core99MachineState { +struct Core99MachineState { /*< private >*/ MachineState parent; uint8_t via_config; -} Core99MachineState; +}; /* Grackle PCI */ #define TYPE_GRACKLE_PCI_HOST_BRIDGE "grackle-pcihost" /* Mac NVRAM */ #define TYPE_MACIO_NVRAM "macio-nvram" -#define MACIO_NVRAM(obj) \ - OBJECT_CHECK(MacIONVRAMState, (obj), TYPE_MACIO_NVRAM) +OBJECT_DECLARE_SIMPLE_TYPE(MacIONVRAMState, MACIO_NVRAM) -typedef struct MacIONVRAMState { +struct MacIONVRAMState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -103,7 +102,7 @@ typedef struct MacIONVRAMState { MemoryRegion mem; uint8_t *data; -} MacIONVRAMState; +}; void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len); #endif /* PPC_MAC_H */ diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 3507f26f6eefdaaf6529940fc701bea455c72640..f9a1cc894472bb74e59d80829126680772a8d39d 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -82,6 +82,8 @@ #define NDRV_VGA_FILENAME "qemu_vga.ndrv" +#define PROM_BASE 0xfff00000 +#define PROM_SIZE (1 * MiB) static void fw_cfg_boot_set(void *opaque, const char *boot_device, Error **errp) @@ -100,7 +102,7 @@ static void ppc_core99_reset(void *opaque) cpu_reset(CPU(cpu)); /* 970 CPUs want to get their initial IP as part of their boot protocol */ - cpu->env.nip = PROM_ADDR + 0x100; + cpu->env.nip = PROM_BASE + 0x100; } /* PowerPC Mac99 hardware initialisation */ @@ -122,7 +124,8 @@ static void ppc_core99_init(MachineState *machine) long kernel_size, initrd_size; UNINHostState *uninorth_pci; PCIBus *pci_bus; - NewWorldMacIOState *macio; + PCIDevice *macio; + ESCCState *escc; bool has_pmu, has_adb; MACIOIDEState *macio_ide; BusState *adb_bus; @@ -153,31 +156,34 @@ static void ppc_core99_init(MachineState *machine) /* allocate RAM */ memory_region_add_subregion(get_system_memory(), 0, machine->ram); - /* allocate and load BIOS */ - memory_region_init_rom(bios, NULL, "ppc_core99.bios", BIOS_SIZE, + /* allocate and load firmware ROM */ + memory_region_init_rom(bios, NULL, "ppc_core99.bios", PROM_SIZE, &error_fatal); + memory_region_add_subregion(get_system_memory(), PROM_BASE, bios); - if (bios_name == NULL) + if (!bios_name) { bios_name = PROM_FILENAME; + } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - memory_region_add_subregion(get_system_memory(), PROM_ADDR, bios); - - /* Load OpenBIOS (ELF) */ if (filename) { + /* Load OpenBIOS (ELF) */ bios_size = load_elf(filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0); + if (bios_size <= 0) { + /* or load binary ROM image */ + bios_size = load_image_targphys(filename, PROM_BASE, PROM_SIZE); + } g_free(filename); } else { bios_size = -1; } - if (bios_size < 0 || bios_size > BIOS_SIZE) { + if (bios_size < 0 || bios_size > PROM_SIZE) { error_report("could not load PowerPC bios '%s'", bios_name); exit(1); } if (linux_boot) { - uint64_t lowaddr = 0; int bswap_needed; #ifdef BSWAP_NEEDED @@ -188,9 +194,8 @@ static void ppc_core99_init(MachineState *machine) kernel_base = KERNEL_LOAD_ADDR; kernel_size = load_elf(kernel_filename, NULL, - translate_kernel_address, NULL, - NULL, &lowaddr, NULL, NULL, 1, PPC_ELF_MACHINE, - 0, 0); + translate_kernel_address, NULL, NULL, NULL, + NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0); if (kernel_size < 0) kernel_size = load_aout(kernel_filename, kernel_base, ram_size - kernel_base, bswap_needed, @@ -242,9 +247,9 @@ static void ppc_core99_init(MachineState *machine) } /* UniN init */ - dev = qdev_create(NULL, TYPE_UNI_NORTH); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_UNI_NORTH); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); memory_region_add_subregion(get_system_memory(), 0xf8000000, sysbus_mmio_get_region(s, 0)); @@ -288,10 +293,10 @@ static void ppc_core99_init(MachineState *machine) } } - pic_dev = qdev_create(NULL, TYPE_OPENPIC); + pic_dev = qdev_new(TYPE_OPENPIC); qdev_prop_set_uint32(pic_dev, "model", OPENPIC_MODEL_KEYLARGO); - qdev_init_nofail(pic_dev); s = SYS_BUS_DEVICE(pic_dev); + sysbus_realize_and_unref(s, &error_fatal); k = 0; for (i = 0; i < smp_cpus; i++) { for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { @@ -303,10 +308,8 @@ static void ppc_core99_init(MachineState *machine) if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) { /* 970 gets a U3 bus */ /* Uninorth AGP bus */ - dev = qdev_create(NULL, TYPE_U3_AGP_HOST_BRIDGE); - object_property_set_link(OBJECT(dev), OBJECT(pic_dev), "pic", - &error_abort); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_U3_AGP_HOST_BRIDGE); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); uninorth_pci = U3_AGP_HOST_BRIDGE(dev); s = SYS_BUS_DEVICE(dev); /* PCI hole */ @@ -318,33 +321,39 @@ static void ppc_core99_init(MachineState *machine) sysbus_mmio_map(s, 0, 0xf0800000); sysbus_mmio_map(s, 1, 0xf0c00000); + for (i = 0; i < 4; i++) { + qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(pic_dev, 0x1b + i)); + } + machine_arch = ARCH_MAC99_U3; } else { /* Use values found on a real PowerMac */ /* Uninorth AGP bus */ - dev = qdev_create(NULL, TYPE_UNI_NORTH_AGP_HOST_BRIDGE); - object_property_set_link(OBJECT(dev), OBJECT(pic_dev), "pic", - &error_abort); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_UNI_NORTH_AGP_HOST_BRIDGE); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, 0xf0800000); sysbus_mmio_map(s, 1, 0xf0c00000); + for (i = 0; i < 4; i++) { + qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(pic_dev, 0x1b + i)); + } + /* Uninorth internal bus */ - dev = qdev_create(NULL, TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE); - object_property_set_link(OBJECT(dev), OBJECT(pic_dev), "pic", - &error_abort); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, 0xf4800000); sysbus_mmio_map(s, 1, 0xf4c00000); + for (i = 0; i < 4; i++) { + qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(pic_dev, 0x1b + i)); + } + /* Uninorth main bus */ - dev = qdev_create(NULL, TYPE_UNI_NORTH_PCI_HOST_BRIDGE); + dev = qdev_new(TYPE_UNI_NORTH_PCI_HOST_BRIDGE); qdev_prop_set_uint32(dev, "ofw-addr", 0xf2000000); - object_property_set_link(OBJECT(dev), OBJECT(pic_dev), "pic", - &error_abort); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); uninorth_pci = UNI_NORTH_PCI_HOST_BRIDGE(dev); s = SYS_BUS_DEVICE(dev); /* PCI hole */ @@ -356,6 +365,10 @@ static void ppc_core99_init(MachineState *machine) sysbus_mmio_map(s, 0, 0xf2800000); sysbus_mmio_map(s, 1, 0xf2c00000); + for (i = 0; i < 4; i++) { + qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(pic_dev, 0x1b + i)); + } + machine_arch = ARCH_MAC99; } @@ -375,14 +388,19 @@ static void ppc_core99_init(MachineState *machine) pci_bus = PCI_HOST_BRIDGE(uninorth_pci)->bus; /* MacIO */ - macio = NEWWORLD_MACIO(pci_create(pci_bus, -1, TYPE_NEWWORLD_MACIO)); + macio = pci_new(-1, TYPE_NEWWORLD_MACIO); dev = DEVICE(macio); qdev_prop_set_uint64(dev, "frequency", tbfreq); qdev_prop_set_bit(dev, "has-pmu", has_pmu); qdev_prop_set_bit(dev, "has-adb", has_adb); - object_property_set_link(OBJECT(macio), OBJECT(pic_dev), "pic", + object_property_set_link(OBJECT(macio), "pic", OBJECT(pic_dev), &error_abort); - qdev_init_nofail(dev); + + escc = ESCC(object_resolve_path_component(OBJECT(macio), "escc")); + qdev_prop_set_chr(DEVICE(escc), "chrA", serial_hd(0)); + qdev_prop_set_chr(DEVICE(escc), "chrB", serial_hd(1)); + + pci_realize_and_unref(macio, pci_bus, &error_fatal); /* We only emulate 2 out of 3 IDE controllers for now */ ide_drive_get(hd, ARRAY_SIZE(hd)); @@ -403,13 +421,11 @@ static void ppc_core99_init(MachineState *machine) } adb_bus = qdev_get_child_bus(dev, "adb.0"); - dev = qdev_create(adb_bus, TYPE_ADB_KEYBOARD); - qdev_prop_set_bit(dev, "disable-direct-reg3-writes", true); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_ADB_KEYBOARD); + qdev_realize_and_unref(dev, adb_bus, &error_fatal); - dev = qdev_create(adb_bus, TYPE_ADB_MOUSE); - qdev_prop_set_bit(dev, "disable-direct-reg3-writes", true); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_ADB_MOUSE); + qdev_realize_and_unref(dev, adb_bus, &error_fatal); } if (machine->usb) { @@ -441,23 +457,23 @@ static void ppc_core99_init(MachineState *machine) move the NVRAM out of ROM again for KVM */ nvram_addr = 0xFFE00000; } - dev = qdev_create(NULL, TYPE_MACIO_NVRAM); + dev = qdev_new(TYPE_MACIO_NVRAM); qdev_prop_set_uint32(dev, "size", 0x2000); qdev_prop_set_uint32(dev, "it_shift", 1); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, nvram_addr); nvr = MACIO_NVRAM(dev); pmac_format_nvram_partition(nvr, 0x2000); /* No PCI init: the BIOS will do it */ - dev = qdev_create(NULL, TYPE_FW_CFG_MEM); + dev = qdev_new(TYPE_FW_CFG_MEM); fw_cfg = FW_CFG(dev); qdev_prop_set_uint32(dev, "data_width", 1); qdev_prop_set_bit(dev, "dma_enabled", false); object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG, OBJECT(fw_cfg)); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, CFG_ADDR); sysbus_mmio_map(s, 1, CFG_ADDR + 2); diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 0b4c1c6373f53e16ade7794b47c923bafd437d4e..6c59aa56018ef0ba0f449de54768e883747a52b8 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -59,6 +59,8 @@ #define NDRV_VGA_FILENAME "qemu_vga.ndrv" #define GRACKLE_BASE 0xfec00000 +#define PROM_BASE 0xffc00000 +#define PROM_SIZE (4 * MiB) static void fw_cfg_boot_set(void *opaque, const char *boot_device, Error **errp) @@ -81,24 +83,22 @@ static void ppc_heathrow_reset(void *opaque) static void ppc_heathrow_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; - const char *kernel_filename = machine->kernel_filename; - const char *kernel_cmdline = machine->kernel_cmdline; - const char *initrd_filename = machine->initrd_filename; const char *boot_device = machine->boot_order; - MemoryRegion *sysmem = get_system_memory(); PowerPCCPU *cpu = NULL; CPUPPCState *env = NULL; char *filename; - int linux_boot, i; + int i; MemoryRegion *bios = g_new(MemoryRegion, 1); uint32_t kernel_base, initrd_base, cmdline_base = 0; int32_t kernel_size, initrd_size; PCIBus *pci_bus; - OldWorldMacIOState *macio; + PCIDevice *macio; MACIOIDEState *macio_ide; + ESCCState *escc; SysBusDevice *s; DeviceState *dev, *pic_dev; BusState *adb_bus; + uint64_t bios_addr; int bios_size; unsigned int smp_cpus = machine->smp.cpus; uint16_t ppc_boot_device; @@ -106,8 +106,6 @@ static void ppc_heathrow_init(MachineState *machine) void *fw_cfg; uint64_t tbfreq; - linux_boot = (kernel_filename != NULL); - /* init CPUs */ for (i = 0; i < smp_cpus; i++) { cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); @@ -125,32 +123,39 @@ static void ppc_heathrow_init(MachineState *machine) exit(1); } - memory_region_add_subregion(sysmem, 0, machine->ram); + memory_region_add_subregion(get_system_memory(), 0, machine->ram); - /* allocate and load BIOS */ - memory_region_init_rom(bios, NULL, "ppc_heathrow.bios", BIOS_SIZE, + /* allocate and load firmware ROM */ + memory_region_init_rom(bios, NULL, "ppc_heathrow.bios", PROM_SIZE, &error_fatal); + memory_region_add_subregion(get_system_memory(), PROM_BASE, bios); - if (bios_name == NULL) + if (!bios_name) { bios_name = PROM_FILENAME; + } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - memory_region_add_subregion(sysmem, PROM_ADDR, bios); - - /* Load OpenBIOS (ELF) */ if (filename) { - bios_size = load_elf(filename, NULL, 0, NULL, NULL, NULL, NULL, NULL, - 1, PPC_ELF_MACHINE, 0, 0); + /* Load OpenBIOS (ELF) */ + bios_size = load_elf(filename, NULL, NULL, NULL, NULL, &bios_addr, + NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0); + /* Unfortunately, load_elf sign-extends reading elf32 */ + bios_addr = (uint32_t)bios_addr; + + if (bios_size <= 0) { + /* or if could not load ELF try loading a binary ROM image */ + bios_size = load_image_targphys(filename, PROM_BASE, PROM_SIZE); + bios_addr = PROM_BASE; + } g_free(filename); } else { bios_size = -1; } - if (bios_size < 0 || bios_size > BIOS_SIZE) { + if (bios_size < 0 || bios_addr - PROM_BASE + bios_size > PROM_SIZE) { error_report("could not load PowerPC bios '%s'", bios_name); exit(1); } - if (linux_boot) { - uint64_t lowaddr = 0; + if (machine->kernel_filename) { int bswap_needed; #ifdef BSWAP_NEEDED @@ -159,30 +164,32 @@ static void ppc_heathrow_init(MachineState *machine) bswap_needed = 0; #endif kernel_base = KERNEL_LOAD_ADDR; - kernel_size = load_elf(kernel_filename, NULL, - translate_kernel_address, NULL, - NULL, &lowaddr, NULL, NULL, 1, PPC_ELF_MACHINE, - 0, 0); + kernel_size = load_elf(machine->kernel_filename, NULL, + translate_kernel_address, NULL, NULL, NULL, + NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0); if (kernel_size < 0) - kernel_size = load_aout(kernel_filename, kernel_base, + kernel_size = load_aout(machine->kernel_filename, kernel_base, ram_size - kernel_base, bswap_needed, TARGET_PAGE_SIZE); if (kernel_size < 0) - kernel_size = load_image_targphys(kernel_filename, + kernel_size = load_image_targphys(machine->kernel_filename, kernel_base, ram_size - kernel_base); if (kernel_size < 0) { - error_report("could not load kernel '%s'", kernel_filename); + error_report("could not load kernel '%s'", + machine->kernel_filename); exit(1); } /* load initrd */ - if (initrd_filename) { - initrd_base = TARGET_PAGE_ALIGN(kernel_base + kernel_size + KERNEL_GAP); - initrd_size = load_image_targphys(initrd_filename, initrd_base, + if (machine->initrd_filename) { + initrd_base = TARGET_PAGE_ALIGN(kernel_base + kernel_size + + KERNEL_GAP); + initrd_size = load_image_targphys(machine->initrd_filename, + initrd_base, ram_size - initrd_base); if (initrd_size < 0) { error_report("could not load initial ram disk '%s'", - initrd_filename); + machine->initrd_filename); exit(1); } cmdline_base = TARGET_PAGE_ALIGN(initrd_base + initrd_size); @@ -222,8 +229,8 @@ static void ppc_heathrow_init(MachineState *machine) } /* XXX: we register only 1 output pin for heathrow PIC */ - pic_dev = qdev_create(NULL, TYPE_HEATHROW); - qdev_init_nofail(pic_dev); + pic_dev = qdev_new(TYPE_HEATHROW); + sysbus_realize_and_unref(SYS_BUS_DEVICE(pic_dev), &error_fatal); /* Connect the heathrow PIC outputs to the 6xx bus */ for (i = 0; i < smp_cpus; i++) { @@ -252,12 +259,11 @@ static void ppc_heathrow_init(MachineState *machine) } /* Grackle PCI host bridge */ - dev = qdev_create(NULL, TYPE_GRACKLE_PCI_HOST_BRIDGE); + dev = qdev_new(TYPE_GRACKLE_PCI_HOST_BRIDGE); qdev_prop_set_uint32(dev, "ofw-addr", 0x80000000); - object_property_set_link(OBJECT(dev), OBJECT(pic_dev), "pic", - &error_abort); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); + sysbus_mmio_map(s, 0, GRACKLE_BASE); sysbus_mmio_map(s, 1, GRACKLE_BASE + 0x200000); /* PCI hole */ @@ -267,6 +273,10 @@ static void ppc_heathrow_init(MachineState *machine) memory_region_add_subregion(get_system_memory(), 0xfe000000, sysbus_mmio_get_region(s, 3)); + for (i = 0; i < 4; i++) { + qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(pic_dev, 0x15 + i)); + } + pci_bus = PCI_HOST_BRIDGE(dev)->bus; pci_vga_init(pci_bus); @@ -278,12 +288,17 @@ static void ppc_heathrow_init(MachineState *machine) ide_drive_get(hd, ARRAY_SIZE(hd)); /* MacIO */ - macio = OLDWORLD_MACIO(pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO)); + macio = pci_new(PCI_DEVFN(16, 0), TYPE_OLDWORLD_MACIO); dev = DEVICE(macio); qdev_prop_set_uint64(dev, "frequency", tbfreq); - object_property_set_link(OBJECT(macio), OBJECT(pic_dev), "pic", + object_property_set_link(OBJECT(macio), "pic", OBJECT(pic_dev), &error_abort); - qdev_init_nofail(dev); + + escc = ESCC(object_resolve_path_component(OBJECT(macio), "escc")); + qdev_prop_set_chr(DEVICE(escc), "chrA", serial_hd(0)); + qdev_prop_set_chr(DEVICE(escc), "chrB", serial_hd(1)); + + pci_realize_and_unref(macio, pci_bus, &error_fatal); macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), "ide[0]")); @@ -295,10 +310,10 @@ static void ppc_heathrow_init(MachineState *machine) dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda")); adb_bus = qdev_get_child_bus(dev, "adb.0"); - dev = qdev_create(adb_bus, TYPE_ADB_KEYBOARD); - qdev_init_nofail(dev); - dev = qdev_create(adb_bus, TYPE_ADB_MOUSE); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_ADB_KEYBOARD); + qdev_realize_and_unref(dev, adb_bus, &error_fatal); + dev = qdev_new(TYPE_ADB_MOUSE); + qdev_realize_and_unref(dev, adb_bus, &error_fatal); if (machine_usb(machine)) { pci_create_simple(pci_bus, -1, "pci-ohci"); @@ -309,14 +324,14 @@ static void ppc_heathrow_init(MachineState *machine) /* No PCI init: the BIOS will do it */ - dev = qdev_create(NULL, TYPE_FW_CFG_MEM); + dev = qdev_new(TYPE_FW_CFG_MEM); fw_cfg = FW_CFG(dev); qdev_prop_set_uint32(dev, "data_width", 1); qdev_prop_set_bit(dev, "dma_enabled", false); object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG, OBJECT(fw_cfg)); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, CFG_ADDR); sysbus_mmio_map(s, 1, CFG_ADDR + 2); @@ -326,9 +341,10 @@ static void ppc_heathrow_init(MachineState *machine) fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_HEATHROW); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); - if (kernel_cmdline) { + if (machine->kernel_cmdline) { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base); - pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline); + pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, + machine->kernel_cmdline); } else { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0); } diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..ffa2ec37fa2518bfbb8b7a8249f511d1a38843a3 --- /dev/null +++ b/hw/ppc/meson.build @@ -0,0 +1,81 @@ +ppc_ss = ss.source_set() +ppc_ss.add(files( + 'ppc.c', + 'ppc_booke.c', +)) +ppc_ss.add(when: 'CONFIG_FDT_PPC', if_true: [files( + 'fdt.c', +), fdt]) +ppc_ss.add(when: 'CONFIG_FW_CFG_PPC', if_true: files('fw_cfg.c')) + +# IBM pSeries (sPAPR) +ppc_ss.add(when: 'CONFIG_PSERIES', if_true: files( + 'spapr.c', + 'spapr_caps.c', + 'spapr_vio.c', + 'spapr_events.c', + 'spapr_hcall.c', + 'spapr_iommu.c', + 'spapr_rtas.c', + 'spapr_pci.c', + 'spapr_rtc.c', + 'spapr_drc.c', + 'spapr_cpu_core.c', + 'spapr_ovec.c', + 'spapr_irq.c', + 'spapr_tpm_proxy.c', + 'spapr_nvdimm.c', + 'spapr_rtas_ddw.c', + 'spapr_numa.c', +)) +ppc_ss.add(when: 'CONFIG_SPAPR_RNG', if_true: files('spapr_rng.c')) +ppc_ss.add(when: ['CONFIG_PSERIES', 'CONFIG_LINUX'], if_true: files( + 'spapr_pci_vfio.c', + 'spapr_pci_nvlink2.c' +)) + +# IBM PowerNV +ppc_ss.add(when: 'CONFIG_POWERNV', if_true: files( + 'pnv.c', + 'pnv_xscom.c', + 'pnv_core.c', + 'pnv_lpc.c', + 'pnv_psi.c', + 'pnv_occ.c', + 'pnv_bmc.c', + 'pnv_homer.c', + 'pnv_pnor.c', +)) +# PowerPC 4xx boards +ppc_ss.add(when: 'CONFIG_PPC405', if_true: files( + 'ppc405_boards.c', + 'ppc405_uc.c')) +ppc_ss.add(when: 'CONFIG_PPC440', if_true: files( + 'ppc440_bamboo.c', + 'ppc440_pcix.c', 'ppc440_uc.c')) +ppc_ss.add(when: 'CONFIG_PPC4XX', if_true: files( + 'ppc4xx_pci.c', + 'ppc4xx_devs.c')) +ppc_ss.add(when: 'CONFIG_SAM460EX', if_true: files('sam460ex.c')) +# PReP +ppc_ss.add(when: 'CONFIG_PREP', if_true: files('prep.c')) +ppc_ss.add(when: 'CONFIG_PREP', if_true: files('prep_systemio.c')) +ppc_ss.add(when: 'CONFIG_RS6000_MC', if_true: files('rs6000_mc.c')) +# OldWorld PowerMac +ppc_ss.add(when: 'CONFIG_MAC_OLDWORLD', if_true: files('mac_oldworld.c')) +# NewWorld PowerMac +ppc_ss.add(when: 'CONFIG_MAC_NEWWORLD', if_true: files('mac_newworld.c')) +# e500 +ppc_ss.add(when: 'CONFIG_E500', if_true: files( + 'e500.c', + 'mpc8544ds.c', + 'e500plat.c' +)) +ppc_ss.add(when: 'CONFIG_E500', if_true: files( + 'mpc8544_guts.c', + 'ppce500_spin.c' +)) +# PowerPC 440 Xilinx ML507 reference board. +ppc_ss.add(when: 'CONFIG_VIRTEX', if_true: files('virtex_ml507.c')) + +hw_arch += {'ppc': ppc_ss} diff --git a/hw/ppc/mpc8544_guts.c b/hw/ppc/mpc8544_guts.c index b96ea36f98721a30785dd6f773f8b47b64c737af..e8d2d51c20c0edb301ed6b0ed1fec6b5caf2f094 100644 --- a/hw/ppc/mpc8544_guts.c +++ b/hw/ppc/mpc8544_guts.c @@ -22,6 +22,7 @@ #include "sysemu/runstate.h" #include "cpu.h" #include "hw/sysbus.h" +#include "qom/object.h" #define MPC8544_GUTS_MMIO_SIZE 0x1000 #define MPC8544_GUTS_RSTCR_RESET 0x02 @@ -54,7 +55,7 @@ #define MPC8544_GUTS_ADDR_SRDS2CR3 0xF18 #define TYPE_MPC8544_GUTS "mpc8544-guts" -#define MPC8544_GUTS(obj) OBJECT_CHECK(GutsState, (obj), TYPE_MPC8544_GUTS) +OBJECT_DECLARE_SIMPLE_TYPE(GutsState, MPC8544_GUTS) struct GutsState { /*< private >*/ @@ -64,7 +65,6 @@ struct GutsState { MemoryRegion iomem; }; -typedef struct GutsState GutsState; static uint64_t mpc8544_guts_read(void *opaque, hwaddr addr, unsigned size) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index da637822f9eb1260f742ec9d18256faa44e91be5..50ebd4a484d11dfca05b2450c40f74107b4cda94 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -21,6 +21,7 @@ #include "qemu-common.h" #include "qemu/units.h" #include "qapi/error.h" +#include "sysemu/qtest.h" #include "sysemu/sysemu.h" #include "sysemu/numa.h" #include "sysemu/reset.h" @@ -60,7 +61,7 @@ #define FW_FILE_NAME "skiboot.lid" #define FW_LOAD_ADDR 0x0 -#define FW_MAX_SIZE (4 * MiB) +#define FW_MAX_SIZE (16 * MiB) #define KERNEL_LOAD_ADDR 0x20000000 #define KERNEL_MAX_SIZE (256 * MiB) @@ -587,9 +588,11 @@ static void pnv_reset(MachineState *machine) bmc = pnv_bmc_find(&error_fatal); if (!pnv->bmc) { if (!bmc) { - warn_report("machine has no BMC device. Use '-device " - "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' " - "to define one"); + if (!qtest_enabled()) { + warn_report("machine has no BMC device. Use '-device " + "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' " + "to define one"); + } } else { pnv_bmc_set_pnor(bmc, pnv->pnor); pnv->bmc = bmc; @@ -694,12 +697,11 @@ static bool pnv_match_cpu(const char *default_type, const char *cpu_type) static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq) { - Object *obj; + ISADevice *dev = isa_new("isa-ipmi-bt"); - obj = OBJECT(isa_create(bus, "isa-ipmi-bt")); - object_property_set_link(obj, OBJECT(bmc), "bmc", &error_fatal); - object_property_set_int(obj, irq, "irq", &error_fatal); - object_property_set_bool(obj, true, "realized", &error_fatal); + object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal); + object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal); + isa_realize_and_unref(dev, bus, &error_fatal); } static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) @@ -729,12 +731,11 @@ static void pnv_init(MachineState *machine) /* * Create our simple PNOR device */ - dev = qdev_create(NULL, TYPE_PNV_PNOR); + dev = qdev_new(TYPE_PNV_PNOR); if (pnor) { - qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor), - &error_abort); + qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor)); } - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); pnv->pnor = PNV_PNOR(dev); /* load skiboot firmware */ @@ -818,7 +819,7 @@ static void pnv_init(MachineState *machine) pnv->chips = g_new0(PnvChip *, pnv->num_chips); for (i = 0; i < pnv->num_chips; i++) { char chip_name[32]; - Object *chip = object_new(chip_typename); + Object *chip = OBJECT(qdev_new(chip_typename)); pnv->chips[i] = PNV_CHIP(chip); @@ -827,30 +828,30 @@ static void pnv_init(MachineState *machine) * way to specify different ranges for each chip */ if (i == 0) { - object_property_set_int(chip, machine->ram_size, "ram-size", + object_property_set_int(chip, "ram-size", machine->ram_size, &error_fatal); } snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i)); object_property_add_child(OBJECT(pnv), chip_name, chip); - object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id", + object_property_set_int(chip, "chip-id", PNV_CHIP_HWID(i), + &error_fatal); + object_property_set_int(chip, "nr-cores", machine->smp.cores, + &error_fatal); + object_property_set_int(chip, "nr-threads", machine->smp.threads, &error_fatal); - object_property_set_int(chip, machine->smp.cores, - "nr-cores", &error_fatal); - object_property_set_int(chip, machine->smp.threads, - "nr-threads", &error_fatal); /* * The POWER8 machine use the XICS interrupt interface. * Propagate the XICS fabric to the chip and its controllers. */ if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) { - object_property_set_link(chip, OBJECT(pnv), "xics", &error_abort); + object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort); } if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) { - object_property_set_link(chip, OBJECT(pnv), "xive-fabric", + object_property_set_link(chip, "xive-fabric", OBJECT(pnv), &error_abort); } - object_property_set_bool(chip, true, "realized", &error_fatal); + sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal); } g_free(chip_typename); @@ -1062,22 +1063,16 @@ static void pnv_chip_power8_instance_init(Object *obj) object_property_allow_set_link, OBJ_PROP_LINK_STRONG); - object_initialize_child(obj, "psi", &chip8->psi, sizeof(chip8->psi), - TYPE_PNV8_PSI, &error_abort, NULL); + object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI); - object_initialize_child(obj, "lpc", &chip8->lpc, sizeof(chip8->lpc), - TYPE_PNV8_LPC, &error_abort, NULL); + object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC); - object_initialize_child(obj, "occ", &chip8->occ, sizeof(chip8->occ), - TYPE_PNV8_OCC, &error_abort, NULL); + object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC); - object_initialize_child(obj, "homer", &chip8->homer, sizeof(chip8->homer), - TYPE_PNV8_HOMER, &error_abort, NULL); + object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER); for (i = 0; i < pcc->num_phbs; i++) { - object_initialize_child(obj, "phb[*]", &chip8->phbs[i], - sizeof(chip8->phbs[i]), TYPE_PNV_PHB3, - &error_abort, NULL); + object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB3); } /* @@ -1141,23 +1136,20 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) } /* Processor Service Interface (PSI) Host Bridge */ - object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip), - "bar", &error_fatal); - object_property_set_link(OBJECT(&chip8->psi), OBJECT(chip8->xics), - ICS_PROP_XICS, &error_abort); - object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + object_property_set_int(OBJECT(&chip8->psi), "bar", PNV_PSIHB_BASE(chip), + &error_fatal); + object_property_set_link(OBJECT(&chip8->psi), ICS_PROP_XICS, + OBJECT(chip8->xics), &error_abort); + if (!qdev_realize(DEVICE(&chip8->psi), NULL, errp)) { return; } pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, &PNV_PSI(psi8)->xscom_regs); /* Create LPC controller */ - object_property_set_link(OBJECT(&chip8->lpc), OBJECT(&chip8->psi), "psi", + object_property_set_link(OBJECT(&chip8->lpc), "psi", OBJECT(&chip8->psi), &error_abort); - object_property_set_bool(OBJECT(&chip8->lpc), true, "realized", - &error_fatal); + qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal); pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", @@ -1175,11 +1167,9 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) } /* Create the simplified OCC model */ - object_property_set_link(OBJECT(&chip8->occ), OBJECT(&chip8->psi), "psi", + object_property_set_link(OBJECT(&chip8->occ), "psi", OBJECT(&chip8->psi), &error_abort); - object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) { return; } pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); @@ -1189,12 +1179,9 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) &chip8->occ.sram_regs); /* HOMER */ - object_property_set_link(OBJECT(&chip8->homer), OBJECT(chip), "chip", + object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip), &error_abort); - object_property_set_bool(OBJECT(&chip8->homer), true, "realized", - &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) { return; } /* Homer Xscom region */ @@ -1209,15 +1196,12 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) PnvPHB3 *phb = &chip8->phbs[i]; PnvPBCQState *pbcq = &phb->pbcq; - object_property_set_int(OBJECT(phb), i, "index", &error_fatal); - object_property_set_int(OBJECT(phb), chip->chip_id, "chip-id", + object_property_set_int(OBJECT(phb), "index", i, &error_fatal); + object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id, &error_fatal); - object_property_set_bool(OBJECT(phb), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) { return; } - qdev_set_parent_bus(DEVICE(phb), sysbus_get_default()); /* Populate the XSCOM address space. */ pnv_xscom_add_subregion(chip, @@ -1317,27 +1301,21 @@ static void pnv_chip_power9_instance_init(Object *obj) PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); int i; - object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive), - TYPE_PNV_XIVE, &error_abort, NULL); + object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE); object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive), "xive-fabric"); - object_initialize_child(obj, "psi", &chip9->psi, sizeof(chip9->psi), - TYPE_PNV9_PSI, &error_abort, NULL); + object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI); - object_initialize_child(obj, "lpc", &chip9->lpc, sizeof(chip9->lpc), - TYPE_PNV9_LPC, &error_abort, NULL); + object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC); - object_initialize_child(obj, "occ", &chip9->occ, sizeof(chip9->occ), - TYPE_PNV9_OCC, &error_abort, NULL); + object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC); - object_initialize_child(obj, "homer", &chip9->homer, sizeof(chip9->homer), - TYPE_PNV9_HOMER, &error_abort, NULL); + object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER); for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) { object_initialize_child(obj, "pec[*]", &chip9->pecs[i], - sizeof(chip9->pecs[i]), TYPE_PNV_PHB4_PEC, - &error_abort, NULL); + TYPE_PNV_PHB4_PEC); } /* @@ -1361,11 +1339,12 @@ static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) int core_id = CPU_CORE(pnv_core)->core_id; snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); - object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq), - TYPE_PNV_QUAD, &error_fatal, NULL); + object_initialize_child_with_props(OBJECT(chip), eq_name, eq, + sizeof(*eq), TYPE_PNV_QUAD, + &error_fatal, NULL); - object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal); - object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal); + object_property_set_int(OBJECT(eq), "id", core_id, &error_fatal); + qdev_realize(DEVICE(eq), NULL, &error_fatal); pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id), &eq->xscom_regs); @@ -1375,7 +1354,6 @@ static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) static void pnv_chip_power9_phb_realize(PnvChip *chip, Error **errp) { Pnv9Chip *chip9 = PNV9_CHIP(chip); - Error *local_err = NULL; int i, j; int phb_id = 0; @@ -1385,21 +1363,19 @@ static void pnv_chip_power9_phb_realize(PnvChip *chip, Error **errp) uint32_t pec_nest_base; uint32_t pec_pci_base; - object_property_set_int(OBJECT(pec), i, "index", &error_fatal); + object_property_set_int(OBJECT(pec), "index", i, &error_fatal); /* * PEC0 -> 1 stack * PEC1 -> 2 stacks * PEC2 -> 3 stacks */ - object_property_set_int(OBJECT(pec), i + 1, "num-stacks", + object_property_set_int(OBJECT(pec), "num-stacks", i + 1, + &error_fatal); + object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id, &error_fatal); - object_property_set_int(OBJECT(pec), chip->chip_id, "chip-id", - &error_fatal); - object_property_set_link(OBJECT(pec), OBJECT(get_system_memory()), - "system-memory", &error_abort); - object_property_set_bool(OBJECT(pec), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + object_property_set_link(OBJECT(pec), "system-memory", + OBJECT(get_system_memory()), &error_abort); + if (!qdev_realize(DEVICE(pec), NULL, errp)) { return; } @@ -1414,20 +1390,18 @@ static void pnv_chip_power9_phb_realize(PnvChip *chip, Error **errp) PnvPhb4PecStack *stack = &pec->stacks[j]; Object *obj = OBJECT(&stack->phb); - object_property_set_int(obj, phb_id, "index", &error_fatal); - object_property_set_int(obj, chip->chip_id, "chip-id", + object_property_set_int(obj, "index", phb_id, &error_fatal); + object_property_set_int(obj, "chip-id", chip->chip_id, &error_fatal); - object_property_set_int(obj, PNV_PHB4_VERSION, "version", + object_property_set_int(obj, "version", PNV_PHB4_VERSION, &error_fatal); - object_property_set_int(obj, PNV_PHB4_DEVICE_ID, "device-id", + object_property_set_int(obj, "device-id", PNV_PHB4_DEVICE_ID, &error_fatal); - object_property_set_link(obj, OBJECT(stack), "stack", &error_abort); - object_property_set_bool(obj, true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + object_property_set_link(obj, "stack", OBJECT(stack), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(obj), errp)) { return; } - qdev_set_parent_bus(DEVICE(obj), sysbus_get_default()); /* Populate the XSCOM address space. */ pnv_xscom_add_subregion(chip, @@ -1473,42 +1447,35 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) } /* XIVE interrupt controller (POWER9) */ - object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip), - "ic-bar", &error_fatal); - object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip), - "vc-bar", &error_fatal); - object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip), - "pc-bar", &error_fatal); - object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip), - "tm-bar", &error_fatal); - object_property_set_link(OBJECT(&chip9->xive), OBJECT(chip), "chip", + object_property_set_int(OBJECT(&chip9->xive), "ic-bar", + PNV9_XIVE_IC_BASE(chip), &error_fatal); + object_property_set_int(OBJECT(&chip9->xive), "vc-bar", + PNV9_XIVE_VC_BASE(chip), &error_fatal); + object_property_set_int(OBJECT(&chip9->xive), "pc-bar", + PNV9_XIVE_PC_BASE(chip), &error_fatal); + object_property_set_int(OBJECT(&chip9->xive), "tm-bar", + PNV9_XIVE_TM_BASE(chip), &error_fatal); + object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip), &error_abort); - object_property_set_bool(OBJECT(&chip9->xive), true, "realized", - &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) { return; } pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, &chip9->xive.xscom_regs); /* Processor Service Interface (PSI) Host Bridge */ - object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip), - "bar", &error_fatal); - object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip), + &error_fatal); + if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) { return; } pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE, &PNV_PSI(psi9)->xscom_regs); /* LPC */ - object_property_set_link(OBJECT(&chip9->lpc), OBJECT(&chip9->psi), "psi", + object_property_set_link(OBJECT(&chip9->lpc), "psi", OBJECT(&chip9->psi), &error_abort); - object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) { return; } memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), @@ -1518,11 +1485,9 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) (uint64_t) PNV9_LPCM_BASE(chip)); /* Create the simplified OCC model */ - object_property_set_link(OBJECT(&chip9->occ), OBJECT(&chip9->psi), "psi", + object_property_set_link(OBJECT(&chip9->occ), "psi", OBJECT(&chip9->psi), &error_abort); - object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) { return; } pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); @@ -1532,12 +1497,9 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) &chip9->occ.sram_regs); /* HOMER */ - object_property_set_link(OBJECT(&chip9->homer), OBJECT(chip), "chip", + object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip), &error_abort); - object_property_set_bool(OBJECT(&chip9->homer), true, "realized", - &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) { return; } /* Homer Xscom region */ @@ -1589,10 +1551,8 @@ static void pnv_chip_power10_instance_init(Object *obj) { Pnv10Chip *chip10 = PNV10_CHIP(obj); - object_initialize_child(obj, "psi", &chip10->psi, sizeof(chip10->psi), - TYPE_PNV10_PSI, &error_abort, NULL); - object_initialize_child(obj, "lpc", &chip10->lpc, sizeof(chip10->lpc), - TYPE_PNV10_LPC, &error_abort, NULL); + object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI); + object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC); } static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) @@ -1617,24 +1577,18 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) } /* Processor Service Interface (PSI) Host Bridge */ - object_property_set_int(OBJECT(&chip10->psi), PNV10_PSIHB_BASE(chip), - "bar", &error_fatal); - object_property_set_bool(OBJECT(&chip10->psi), true, "realized", - &local_err); - if (local_err) { - error_propagate(errp, local_err); + object_property_set_int(OBJECT(&chip10->psi), "bar", + PNV10_PSIHB_BASE(chip), &error_fatal); + if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) { return; } pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE, &PNV_PSI(&chip10->psi)->xscom_regs); /* LPC */ - object_property_set_link(OBJECT(&chip10->lpc), OBJECT(&chip10->psi), "psi", - &error_abort); - object_property_set_bool(OBJECT(&chip10->lpc), true, "realized", - &local_err); - if (local_err) { - error_propagate(errp, local_err); + object_property_set_link(OBJECT(&chip10->lpc), "psi", + OBJECT(&chip10->psi), &error_abort); + if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) { return; } memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip), @@ -1740,19 +1694,17 @@ static void pnv_chip_core_realize(PnvChip *chip, Error **errp) snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core)); chip->cores[i] = pnv_core; - object_property_set_int(OBJECT(pnv_core), chip->nr_threads, - "nr-threads", &error_fatal); - object_property_set_int(OBJECT(pnv_core), core_hwid, - CPU_CORE_PROP_CORE_ID, &error_fatal); - object_property_set_int(OBJECT(pnv_core), - pcc->core_pir(chip, core_hwid), - "pir", &error_fatal); - object_property_set_int(OBJECT(pnv_core), pnv->fw_load_addr, - "hrmor", &error_fatal); - object_property_set_link(OBJECT(pnv_core), OBJECT(chip), "chip", + object_property_set_int(OBJECT(pnv_core), "nr-threads", + chip->nr_threads, &error_fatal); + object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID, + core_hwid, &error_fatal); + object_property_set_int(OBJECT(pnv_core), "pir", + pcc->core_pir(chip, core_hwid), &error_fatal); + object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr, + &error_fatal); + object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip), &error_abort); - object_property_set_bool(OBJECT(pnv_core), true, "realized", - &error_fatal); + qdev_realize(DEVICE(pnv_core), NULL, &error_fatal); /* Each core has an XSCOM MMIO region */ xscom_core_base = pcc->xscom_core_base(chip, core_hwid); @@ -1984,12 +1936,26 @@ static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg) cpu_synchronize_state(cs); ppc_cpu_do_system_reset(cs); - /* - * SRR1[42:45] is set to 0100 which the ISA defines as implementation - * dependent. POWER processors use this for xscom triggered interrupts, - * which come from the BMC or NMI IPIs. - */ - env->spr[SPR_SRR1] |= PPC_BIT(43); + if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) { + /* + * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the + * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100 + * (PPC_BIT(43)). + */ + if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) { + warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason"); + env->spr[SPR_SRR1] |= SRR1_WAKERESET; + } + } else { + /* + * For non-powersave system resets, SRR1[42:45] are defined to be + * implementation-dependent. The POWER9 User Manual specifies that + * an external (SCOM driven, which may come from a BMC nmi command or + * another CPU requesting a NMI IPI) system reset exception should be + * 0b0010 (PPC_BIT(44)). + */ + env->spr[SPR_SRR1] |= SRR1_WAKESCOM; + } } static void pnv_nmi(NMIState *n, int cpu_index, Error **errp) diff --git a/hw/ppc/pnv_bmc.c b/hw/ppc/pnv_bmc.c index 5f86453b6a79d8234015f292ba1c83615292392f..67ebb16c4d5f49439afd68f139cabe5c6018fa75 100644 --- a/hw/ppc/pnv_bmc.c +++ b/hw/ppc/pnv_bmc.c @@ -140,6 +140,27 @@ static uint16_t bytes_to_blocks(uint32_t bytes) return bytes >> BLOCK_SHIFT; } +static uint32_t blocks_to_bytes(uint16_t blocks) +{ + return blocks << BLOCK_SHIFT; +} + +static int hiomap_erase(PnvPnor *pnor, uint32_t offset, uint32_t size) +{ + MemTxResult result; + int i; + + for (i = 0; i < size / 4; i++) { + result = memory_region_dispatch_write(&pnor->mmio, offset + i * 4, + 0xFFFFFFFF, MO_32, + MEMTXATTRS_UNSPECIFIED); + if (result != MEMTX_OK) { + return -1; + } + } + return 0; +} + static void hiomap_cmd(IPMIBmcSim *ibs, uint8_t *cmd, unsigned int cmd_len, RspBuffer *rsp) { @@ -155,10 +176,16 @@ static void hiomap_cmd(IPMIBmcSim *ibs, uint8_t *cmd, unsigned int cmd_len, switch (cmd[2]) { case HIOMAP_C_MARK_DIRTY: case HIOMAP_C_FLUSH: - case HIOMAP_C_ERASE: case HIOMAP_C_ACK: break; + case HIOMAP_C_ERASE: + if (hiomap_erase(pnor, blocks_to_bytes(cmd[5] << 8 | cmd[4]), + blocks_to_bytes(cmd[7] << 8 | cmd[6]))) { + rsp_buffer_set_error(rsp, IPMI_CC_UNSPECIFIED); + } + break; + case HIOMAP_C_GET_INFO: rsp_buffer_push(rsp, 2); /* Version 2 */ rsp_buffer_push(rsp, BLOCK_SHIFT); /* block size */ @@ -235,7 +262,7 @@ IPMIBmc *pnv_bmc_create(PnvPnor *pnor) obj = object_new(TYPE_IPMI_BMC_SIMULATOR); object_ref(OBJECT(pnor)); object_property_add_const_link(obj, "pnor", OBJECT(pnor)); - object_property_set_bool(obj, true, "realized", &error_fatal); + qdev_realize(DEVICE(obj), NULL, &error_fatal); /* Install the HIOMAP protocol handlers to access the PNOR */ ipmi_sim_register_netfn(IPMI_BMC_SIMULATOR(obj), IPMI_NETFN_OEM, diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 96a446f001909add3bf71562dd75660f6a45da67..bd2bf2e044725f1675138d926d373f7a59bf8485 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2 of + * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but @@ -173,9 +173,7 @@ static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp) Error *local_err = NULL; PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip); - object_property_set_bool(OBJECT(cpu), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qdev_realize(DEVICE(cpu), NULL, errp)) { return; } diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c index b5ffa48dac7179b5e7320a5c551a6d927e2f558c..5903590220849407cb898b56d74a883b3514f60f 100644 --- a/hw/ppc/pnv_lpc.c +++ b/hw/ppc/pnv_lpc.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -646,7 +646,6 @@ static void pnv_lpc_power8_class_init(ObjectClass *klass, void *data) static const TypeInfo pnv_lpc_power8_info = { .name = TYPE_PNV8_LPC, .parent = TYPE_PNV_LPC, - .instance_size = sizeof(PnvLpcController), .class_init = pnv_lpc_power8_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_PNV_XSCOM_INTERFACE }, @@ -687,7 +686,6 @@ static void pnv_lpc_power9_class_init(ObjectClass *klass, void *data) static const TypeInfo pnv_lpc_power9_info = { .name = TYPE_PNV9_LPC, .parent = TYPE_PNV_LPC, - .instance_size = sizeof(PnvLpcController), .class_init = pnv_lpc_power9_class_init, }; @@ -768,6 +766,7 @@ static void pnv_lpc_class_init(ObjectClass *klass, void *data) static const TypeInfo pnv_lpc_info = { .name = TYPE_PNV_LPC, .parent = TYPE_DEVICE, + .instance_size = sizeof(PnvLpcController), .class_init = pnv_lpc_class_init, .class_size = sizeof(PnvLpcClass), .abstract = true, diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c index cfd5b7bc25d529e238b68edfdd97f6cb9c970f98..3e868c8c8dadf6c140733d8c3bc13ae3f72238d2 100644 --- a/hw/ppc/pnv_psi.c +++ b/hw/ppc/pnv_psi.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -483,8 +483,7 @@ static void pnv_psi_power8_instance_init(Object *obj) { Pnv8Psi *psi8 = PNV8_PSI(obj); - object_initialize_child(obj, "ics-psi", &psi8->ics, sizeof(psi8->ics), - TYPE_ICS, &error_abort, NULL); + object_initialize_child(obj, "ics-psi", &psi8->ics, TYPE_ICS); object_property_add_alias(obj, ICS_PROP_XICS, OBJECT(&psi8->ics), ICS_PROP_XICS); } @@ -502,18 +501,14 @@ static void pnv_psi_power8_realize(DeviceState *dev, Error **errp) { PnvPsi *psi = PNV_PSI(dev); ICSState *ics = &PNV8_PSI(psi)->ics; - Error *err = NULL; unsigned int i; /* Create PSI interrupt control source */ - object_property_set_int(OBJECT(ics), PSI_NUM_INTERRUPTS, "nr-irqs", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_int(OBJECT(ics), "nr-irqs", PSI_NUM_INTERRUPTS, + errp)) { return; } - object_property_set_bool(OBJECT(ics), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(DEVICE(ics), NULL, errp)) { return; } @@ -836,26 +831,21 @@ static void pnv_psi_power9_instance_init(Object *obj) { Pnv9Psi *psi = PNV9_PSI(obj); - object_initialize_child(obj, "source", &psi->source, sizeof(psi->source), - TYPE_XIVE_SOURCE, &error_abort, NULL); + object_initialize_child(obj, "source", &psi->source, TYPE_XIVE_SOURCE); } static void pnv_psi_power9_realize(DeviceState *dev, Error **errp) { PnvPsi *psi = PNV_PSI(dev); XiveSource *xsrc = &PNV9_PSI(psi)->source; - Error *local_err = NULL; int i; /* This is the only device with 4k ESB pages */ - object_property_set_int(OBJECT(xsrc), XIVE_ESB_4K, "shift", + object_property_set_int(OBJECT(xsrc), "shift", XIVE_ESB_4K, &error_fatal); + object_property_set_int(OBJECT(xsrc), "nr-irqs", PSIHB9_NUM_IRQS, &error_fatal); - object_property_set_int(OBJECT(xsrc), PSIHB9_NUM_IRQS, "nr-irqs", - &error_fatal); - object_property_set_link(OBJECT(xsrc), OBJECT(psi), "xive", &error_abort); - object_property_set_bool(OBJECT(xsrc), true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + object_property_set_link(OBJECT(xsrc), "xive", OBJECT(psi), &error_abort); + if (!qdev_realize(DEVICE(xsrc), NULL, errp)) { return; } @@ -939,11 +929,12 @@ static void pnv_psi_class_init(ObjectClass *klass, void *data) dc->desc = "PowerNV PSI Controller"; device_class_set_props(dc, pnv_psi_properties); dc->reset = pnv_psi_reset; + dc->user_creatable = false; } static const TypeInfo pnv_psi_info = { .name = TYPE_PNV_PSI, - .parent = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_DEVICE, .instance_size = sizeof(PnvPsi), .class_init = pnv_psi_class_init, .class_size = sizeof(PnvPsiClass), diff --git a/hw/ppc/pnv_xscom.c b/hw/ppc/pnv_xscom.c index b681c72575b20a034f4235f098aae63f9a7f3ff3..e9ae1569ffcfbdb7f79f7d2393b7e30a43e61b37 100644 --- a/hw/ppc/pnv_xscom.c +++ b/hw/ppc/pnv_xscom.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index 6198ec1035b7b40da282130baf24050a54afdc62..4687715b15cbb9e53478febf5eb8e9e2346a7c97 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -28,6 +28,8 @@ #include "qemu-common.h" #include "cpu.h" #include "hw/ppc/ppc.h" +#include "hw/qdev-properties.h" +#include "hw/sysbus.h" #include "ppc405.h" #include "hw/rtc/m48t59.h" #include "hw/block/flash.h" @@ -145,6 +147,8 @@ static void ref405ep_init(MachineState *machine) char *filename; ppc4xx_bd_info_t bd; CPUPPCState *env; + DeviceState *dev; + SysBusDevice *s; qemu_irq *pic; MemoryRegion *bios; MemoryRegion *sram = g_new(MemoryRegion, 1); @@ -227,7 +231,11 @@ static void ref405ep_init(MachineState *machine) /* Register FPGA */ ref405ep_fpga_init(sysmem, 0xF0300000); /* Register NVRAM */ - m48t59_init(NULL, 0xF0000000, 0, 8192, 1968, 8); + dev = qdev_new("sysbus-m48t08"); + qdev_prop_set_int32(dev, "base-year", 1968); + s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); + sysbus_mmio_map(s, 0, 0xF0000000); /* Load kernel */ linux_boot = (kernel_filename != NULL); if (linux_boot) { diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c index 4c5e9e4373e421ea6c67dc7b275e2f2a571989ca..74028dc986120cea79571948d2899f470173fdb6 100644 --- a/hw/ppc/ppc440_bamboo.c +++ b/hw/ppc/ppc440_bamboo.c @@ -172,9 +172,6 @@ static void bamboo_init(MachineState *machine) PCIBus *pcibus; PowerPCCPU *cpu; CPUPPCState *env; - uint64_t elf_entry; - uint64_t elf_lowaddr; - hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID; target_long initrd_size = 0; DeviceState *dev; int success; @@ -246,14 +243,14 @@ static void bamboo_init(MachineState *machine) /* Load kernel. */ if (kernel_filename) { + hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID; success = load_uimage(kernel_filename, &entry, &loadaddr, NULL, NULL, NULL); if (success < 0) { + uint64_t elf_entry; success = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry, - &elf_lowaddr, NULL, NULL, 1, PPC_ELF_MACHINE, - 0, 0); + NULL, NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0); entry = elf_entry; - loadaddr = elf_lowaddr; } /* XXX try again as binary */ if (success < 0) { diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c index 2ee2d4f4fc7a8e164f8b3013cb12d2f21be775c9..ee952314c8407d09392dec42eba3a47aa7a6e3e8 100644 --- a/hw/ppc/ppc440_pcix.c +++ b/hw/ppc/ppc440_pcix.c @@ -30,6 +30,7 @@ #include "hw/pci/pci_host.h" #include "exec/address-spaces.h" #include "trace.h" +#include "qom/object.h" struct PLBOutMap { uint64_t la; @@ -45,13 +46,12 @@ struct PLBInMap { }; #define TYPE_PPC440_PCIX_HOST_BRIDGE "ppc440-pcix-host" -#define PPC440_PCIX_HOST_BRIDGE(obj) \ - OBJECT_CHECK(PPC440PCIXState, (obj), TYPE_PPC440_PCIX_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(PPC440PCIXState, PPC440_PCIX_HOST_BRIDGE) #define PPC440_PCIX_NR_POMS 3 #define PPC440_PCIX_NR_PIMS 3 -typedef struct PPC440PCIXState { +struct PPC440PCIXState { PCIHostState parent_obj; PCIDevice *dev; @@ -65,7 +65,7 @@ typedef struct PPC440PCIXState { MemoryRegion container; MemoryRegion iomem; MemoryRegion busmem; -} PPC440PCIXState; +}; #define PPC440_REG_BASE 0x80000 #define PPC440_REG_SIZE 0xff diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index b30e093cbb0333c540d72bf8d1d7ca669882b498..f6f89058ab7c1631af1fa768d7a383f7a909235f 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -24,6 +24,7 @@ #include "sysemu/block-backend.h" #include "sysemu/reset.h" #include "ppc440.h" +#include "qom/object.h" /*****************************************************************************/ /* L2 Cache as SRAM */ @@ -1032,10 +1033,9 @@ void ppc4xx_dma_init(CPUPPCState *env, int dcr_base) #include "hw/pci/pcie_host.h" #define TYPE_PPC460EX_PCIE_HOST "ppc460ex-pcie-host" -#define PPC460EX_PCIE_HOST(obj) \ - OBJECT_CHECK(PPC460EXPCIEState, (obj), TYPE_PPC460EX_PCIE_HOST) +OBJECT_DECLARE_SIMPLE_TYPE(PPC460EXPCIEState, PPC460EX_PCIE_HOST) -typedef struct PPC460EXPCIEState { +struct PPC460EXPCIEState { PCIExpressHost host; MemoryRegion iomem; @@ -1056,7 +1056,7 @@ typedef struct PPC460EXPCIEState { uint32_t reg_mask; uint32_t special; uint32_t cfg; -} PPC460EXPCIEState; +}; #define DCRN_PCIE0_BASE 0x100 #define DCRN_PCIE1_BASE 0x120 @@ -1367,15 +1367,13 @@ void ppc460ex_pcie_init(CPUPPCState *env) { DeviceState *dev; - dev = qdev_create(NULL, TYPE_PPC460EX_PCIE_HOST); + dev = qdev_new(TYPE_PPC460EX_PCIE_HOST); qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE0_BASE); - qdev_init_nofail(dev); - object_property_set_bool(OBJECT(dev), true, "realized", NULL); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), env); - dev = qdev_create(NULL, TYPE_PPC460EX_PCIE_HOST); + dev = qdev_new(TYPE_PPC460EX_PCIE_HOST); qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE1_BASE); - qdev_init_nofail(dev); - object_property_set_bool(OBJECT(dev), true, "realized", NULL); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), env); } diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c index 3ea47df71fe39a68ac971a0022f259712be408a3..28724c06f8822933472c4d55081d49a54119fb6a 100644 --- a/hw/ppc/ppc4xx_pci.c +++ b/hw/ppc/ppc4xx_pci.c @@ -30,6 +30,7 @@ #include "hw/pci/pci_host.h" #include "exec/address-spaces.h" #include "trace.h" +#include "qom/object.h" struct PCIMasterMap { uint32_t la; @@ -43,8 +44,7 @@ struct PCITargetMap { uint32_t la; }; -#define PPC4xx_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(PPC4xxPCIState, (obj), TYPE_PPC4xx_PCI_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(PPC4xxPCIState, PPC4xx_PCI_HOST_BRIDGE) #define PPC4xx_PCI_NR_PMMS 3 #define PPC4xx_PCI_NR_PTMS 2 @@ -54,12 +54,11 @@ struct PPC4xxPCIState { struct PCIMasterMap pmm[PPC4xx_PCI_NR_PMMS]; struct PCITargetMap ptm[PPC4xx_PCI_NR_PTMS]; - qemu_irq irq[4]; + qemu_irq irq[PCI_NUM_PINS]; MemoryRegion container; MemoryRegion iomem; }; -typedef struct PPC4xxPCIState PPC4xxPCIState; #define PCIC0_CFGADDR 0x0 #define PCIC0_CFGDATA 0x4 @@ -256,10 +255,7 @@ static void ppc4xx_pci_set_irq(void *opaque, int irq_num, int level) qemu_irq *pci_irqs = opaque; trace_ppc4xx_pci_set_irq(irq_num); - if (irq_num < 0) { - fprintf(stderr, "%s: PCI irq %d\n", __func__, irq_num); - return; - } + assert(irq_num >= 0); qemu_set_irq(pci_irqs[irq_num], level); } @@ -320,7 +316,8 @@ static void ppc4xx_pcihost_realize(DeviceState *dev, Error **errp) b = pci_register_root_bus(dev, NULL, ppc4xx_pci_set_irq, ppc4xx_pci_map_irq, s->irq, get_system_memory(), - get_system_io(), 0, 4, TYPE_PCI_BUS); + get_system_io(), 0, ARRAY_SIZE(s->irq), + TYPE_PCI_BUS); h->bus = b; pci_create_simple(b, 0, "ppc4xx-host-bridge"); diff --git a/hw/ppc/ppce500_spin.c b/hw/ppc/ppce500_spin.c index 66c1065db245a748148b368e7b43bf45b9f2a5e4..d57b199797f10d47f671e598e6ed691b7321f9c8 100644 --- a/hw/ppc/ppce500_spin.c +++ b/hw/ppc/ppce500_spin.c @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -34,6 +34,7 @@ #include "hw/sysbus.h" #include "sysemu/hw_accel.h" #include "e500.h" +#include "qom/object.h" #define MAX_CPUS 32 @@ -46,14 +47,14 @@ typedef struct spin_info { } QEMU_PACKED SpinInfo; #define TYPE_E500_SPIN "e500-spin" -#define E500_SPIN(obj) OBJECT_CHECK(SpinState, (obj), TYPE_E500_SPIN) +OBJECT_DECLARE_SIMPLE_TYPE(SpinState, E500_SPIN) -typedef struct SpinState { +struct SpinState { SysBusDevice parent_obj; MemoryRegion iomem; SpinInfo spin[MAX_CPUS]; -} SpinState; +}; static void spin_reset(DeviceState *dev) { diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index 9266453dd9c10ccb44e862473b6a2d5dc7bd53b6..4a0cb434a60e4ace8980ff6cc580bddc89744455 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -35,6 +35,7 @@ #include "hw/pci/pci_host.h" #include "hw/ppc/ppc.h" #include "hw/boards.h" +#include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/log.h" #include "hw/irq.h" @@ -243,6 +244,7 @@ static void ibm_40p_init(MachineState *machine) SysBusDevice *pcihost, *s; Nvram *m48t59 = NULL; PCIBus *pci_bus; + ISADevice *isa_dev; ISABus *isa_bus; void *fw_cfg; int i; @@ -268,7 +270,7 @@ static void ibm_40p_init(MachineState *machine) qemu_register_reset(ppc_prep_reset, cpu); /* PCI host */ - dev = qdev_create(NULL, "raven-pcihost"); + dev = qdev_new("raven-pcihost"); if (!bios_name) { bios_name = "openbios-ppc"; } @@ -276,7 +278,7 @@ static void ibm_40p_init(MachineState *machine) qdev_prop_set_uint32(dev, "elf-machine", PPC_ELF_MACHINE); pcihost = SYS_BUS_DEVICE(dev); object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev)); - qdev_init_nofail(dev); + sysbus_realize_and_unref(pcihost, &error_fatal); pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci.0")); if (!pci_bus) { error_report("could not create PCI host controller"); @@ -291,14 +293,16 @@ static void ibm_40p_init(MachineState *machine) isa_bus = ISA_BUS(qdev_get_child_bus(i82378_dev, "isa.0")); /* Memory controller */ - dev = DEVICE(isa_create(isa_bus, "rs6000-mc")); + isa_dev = isa_new("rs6000-mc"); + dev = DEVICE(isa_dev); qdev_prop_set_uint32(dev, "ram-size", machine->ram_size); - qdev_init_nofail(dev); + isa_realize_and_unref(isa_dev, isa_bus, &error_fatal); /* RTC */ - dev = DEVICE(isa_create(isa_bus, TYPE_MC146818_RTC)); + isa_dev = isa_new(TYPE_MC146818_RTC); + dev = DEVICE(isa_dev); qdev_prop_set_int32(dev, "base_year", 1900); - qdev_init_nofail(dev); + isa_realize_and_unref(isa_dev, isa_bus, &error_fatal); /* initialize CMOS checksums */ cmos_checksum = 0x6aa9; @@ -309,19 +313,22 @@ static void ibm_40p_init(MachineState *machine) if (defaults_enabled()) { m48t59 = NVRAM(isa_create_simple(isa_bus, "isa-m48t59")); - dev = DEVICE(isa_create(isa_bus, "cs4231a")); + isa_dev = isa_new("cs4231a"); + dev = DEVICE(isa_dev); qdev_prop_set_uint32(dev, "iobase", 0x830); qdev_prop_set_uint32(dev, "irq", 10); - qdev_init_nofail(dev); + isa_realize_and_unref(isa_dev, isa_bus, &error_fatal); - dev = DEVICE(isa_create(isa_bus, "pc87312")); + isa_dev = isa_new("pc87312"); + dev = DEVICE(isa_dev); qdev_prop_set_uint32(dev, "config", 12); - qdev_init_nofail(dev); + isa_realize_and_unref(isa_dev, isa_bus, &error_fatal); - dev = DEVICE(isa_create(isa_bus, "prep-systemio")); + isa_dev = isa_new("prep-systemio"); + dev = DEVICE(isa_dev); qdev_prop_set_uint32(dev, "ibm-planar-id", 0xfc); qdev_prop_set_uint32(dev, "equipment", 0xc0); - qdev_init_nofail(dev); + isa_realize_and_unref(isa_dev, isa_bus, &error_fatal); dev = DEVICE(pci_create_simple(pci_bus, PCI_DEVFN(1, 0), "lsi53c810")); @@ -338,14 +345,14 @@ static void ibm_40p_init(MachineState *machine) } /* Prepare firmware configuration for OpenBIOS */ - dev = qdev_create(NULL, TYPE_FW_CFG_MEM); + dev = qdev_new(TYPE_FW_CFG_MEM); fw_cfg = FW_CFG(dev); qdev_prop_set_uint32(dev, "data_width", 1); qdev_prop_set_bit(dev, "dma_enabled", false); object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG, OBJECT(fw_cfg)); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, CFG_ADDR); sysbus_mmio_map(s, 1, CFG_ADDR + 2); diff --git a/hw/ppc/prep_systemio.c b/hw/ppc/prep_systemio.c index bbc51b6e9abfe4a57520ac17fabeaeb81df0039e..4e48ef245c3bc9271e3fee6ae8dc552225aefd82 100644 --- a/hw/ppc/prep_systemio.c +++ b/hw/ppc/prep_systemio.c @@ -28,6 +28,7 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "exec/address-spaces.h" +#include "qom/object.h" #include "qemu/error-report.h" /* for error_report() */ #include "qemu/module.h" #include "sysemu/runstate.h" @@ -35,13 +36,12 @@ #include "trace.h" #define TYPE_PREP_SYSTEMIO "prep-systemio" -#define PREP_SYSTEMIO(obj) \ - OBJECT_CHECK(PrepSystemIoState, (obj), TYPE_PREP_SYSTEMIO) +OBJECT_DECLARE_SIMPLE_TYPE(PrepSystemIoState, PREP_SYSTEMIO) /* Bit as defined in PowerPC Reference Plaform v1.1, sect. 6.1.5, p. 132 */ #define PREP_BIT(n) (1 << (7 - (n))) -typedef struct PrepSystemIoState { +struct PrepSystemIoState { ISADevice parent_obj; MemoryRegion ppc_parity_mem; @@ -53,7 +53,7 @@ typedef struct PrepSystemIoState { uint8_t ibm_planar_id; /* 0x0852 */ qemu_irq softreset_irq; PortioList portio; -} PrepSystemIoState; +}; /* PORT 0092 -- Special Port 92 (Read/Write) */ diff --git a/hw/ppc/rs6000_mc.c b/hw/ppc/rs6000_mc.c index f8a498bd8a51f41dde1d0a61d8103ccff9cdbd79..4db5b51a2dd08d17d333f109d6777494ed8f0abf 100644 --- a/hw/ppc/rs6000_mc.c +++ b/hw/ppc/rs6000_mc.c @@ -26,12 +26,12 @@ #include "hw/boards.h" #include "qapi/error.h" #include "trace.h" +#include "qom/object.h" #define TYPE_RS6000MC "rs6000-mc" -#define RS6000MC_DEVICE(obj) \ - OBJECT_CHECK(RS6000MCState, (obj), TYPE_RS6000MC) +OBJECT_DECLARE_SIMPLE_TYPE(RS6000MCState, RS6000MC) -typedef struct RS6000MCState { +struct RS6000MCState { ISADevice parent_obj; /* see US patent 5,684,979 for details (expired 2001-11-04) */ uint32_t ram_size; @@ -41,7 +41,7 @@ typedef struct RS6000MCState { uint32_t end_address[8]; uint8_t port0820_index; PortioList portio; -} RS6000MCState; +}; /* P0RT 0803 -- SIMM ID Register (32/8 MB) (Read Only) */ @@ -141,7 +141,7 @@ static const MemoryRegionPortio rs6000mc_port_list[] = { static void rs6000mc_realize(DeviceState *dev, Error **errp) { - RS6000MCState *s = RS6000MC_DEVICE(dev); + RS6000MCState *s = RS6000MC(dev); int socket = 0; unsigned int ram_size = s->ram_size / MiB; Error *local_err = NULL; @@ -169,7 +169,8 @@ static void rs6000mc_realize(DeviceState *dev, Error **errp) memory_region_init_ram(&s->simm[socket], OBJECT(dev), name, s->simm_size[socket] * MiB, &local_err); if (local_err) { - goto out; + error_propagate(errp, local_err); + return; } memory_region_add_subregion_overlap(get_system_memory(), 0, &s->simm[socket], socket); @@ -177,10 +178,10 @@ static void rs6000mc_realize(DeviceState *dev, Error **errp) } if (ram_size) { /* unable to push all requested RAM in SIMMs */ - error_setg(&local_err, "RAM size incompatible with this board. " + error_setg(errp, "RAM size incompatible with this board. " "Try again with something else, like %" PRId64 " MB", s->ram_size / MiB - ram_size); - goto out; + return; } if (s->autoconfigure) { @@ -196,8 +197,6 @@ static void rs6000mc_realize(DeviceState *dev, Error **errp) isa_register_portio_list(ISA_DEVICE(dev), &s->portio, 0x0, rs6000mc_port_list, s, "rs6000mc"); -out: - error_propagate(errp, local_err); } static const VMStateDescription vmstate_rs6000mc = { diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index 42a8c9fb7ff371d5883648244d309d5586401b31..7e59a91981a882d50120a1903529c07a8bf52744 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -286,7 +286,6 @@ static void sam460ex_init(MachineState *machine) CPUPPCState *env; I2CBus *i2c; hwaddr entry = UBOOT_ENTRY; - hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID; target_long initrd_size = 0; DeviceState *dev; SysBusDevice *sbdev; @@ -339,7 +338,7 @@ static void sam460ex_init(MachineState *machine) spd_data[20] = 4; /* SO-DIMM module */ smbus_eeprom_init_one(i2c, 0x50, spd_data); /* RTC */ - i2c_create_slave(i2c, "m41t80", 0x68); + i2c_slave_create_simple(i2c, "m41t80", 0x68); dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600800, uic[0][3]); @@ -370,11 +369,11 @@ static void sam460ex_init(MachineState *machine) /* USB */ sysbus_create_simple(TYPE_PPC4xx_EHCI, 0x4bffd0400, uic[2][29]); - dev = qdev_create(NULL, "sysbus-ohci"); + dev = qdev_new("sysbus-ohci"); qdev_prop_set_string(dev, "masterbus", "usb-bus.0"); qdev_prop_set_uint32(dev, "num-ports", 6); - qdev_init_nofail(dev); sbdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sbdev, &error_fatal); sysbus_mmio_map(sbdev, 0, 0x4bffd0000); sysbus_connect_irq(sbdev, 0, uic[2][30]); usb_create_simple(usb_bus_find(-1), "usb-kbd"); @@ -426,17 +425,16 @@ static void sam460ex_init(MachineState *machine) /* Load kernel. */ if (machine->kernel_filename) { + hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID; success = load_uimage(machine->kernel_filename, &entry, &loadaddr, NULL, NULL, NULL); if (success < 0) { - uint64_t elf_entry, elf_lowaddr; + uint64_t elf_entry; - success = load_elf(machine->kernel_filename, NULL, - NULL, NULL, &elf_entry, - &elf_lowaddr, NULL, NULL, 1, PPC_ELF_MACHINE, 0, - 0); + success = load_elf(machine->kernel_filename, NULL, NULL, NULL, + &elf_entry, NULL, NULL, NULL, + 1, PPC_ELF_MACHINE, 0, 0); entry = elf_entry; - loadaddr = elf_lowaddr; } /* XXX try again as binary */ if (success < 0) { diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 9b358fcc60948a7b4dc9638431d27edeb84aa592..12a012d9dd09cfb7b52d8c1d29539787908e9bc0 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -81,6 +81,7 @@ #include "hw/mem/memory-device.h" #include "hw/ppc/spapr_tpm_proxy.h" #include "hw/ppc/spapr_nvdimm.h" +#include "hw/ppc/spapr_numa.h" #include "monitor/monitor.h" @@ -201,21 +202,6 @@ static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, return ret; } -static int spapr_fixup_cpu_numa_dt(void *fdt, int offset, PowerPCCPU *cpu) -{ - int index = spapr_get_vcpu_id(cpu); - uint32_t associativity[] = {cpu_to_be32(0x5), - cpu_to_be32(0x0), - cpu_to_be32(0x0), - cpu_to_be32(0x0), - cpu_to_be32(cpu->node_id), - cpu_to_be32(index)}; - - /* Advertise NUMA via ibm,associativity */ - return fdt_setprop(fdt, offset, "ibm,associativity", associativity, - sizeof(associativity)); -} - static void spapr_dt_pa_features(SpaprMachineState *spapr, PowerPCCPU *cpu, void *fdt, int offset) @@ -308,19 +294,23 @@ static hwaddr spapr_node0_size(MachineState *machine) return machine->ram_size; } +bool spapr_machine_using_legacy_numa(SpaprMachineState *spapr) +{ + MachineState *machine = MACHINE(spapr); + SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); + + return smc->pre_5_2_numa_associativity || + machine->numa_state->num_nodes <= 1; +} + static void add_str(GString *s, const gchar *s1) { g_string_append_len(s, s1, strlen(s1) + 1); } -static int spapr_dt_memory_node(void *fdt, int nodeid, hwaddr start, - hwaddr size) +static int spapr_dt_memory_node(SpaprMachineState *spapr, void *fdt, int nodeid, + hwaddr start, hwaddr size) { - uint32_t associativity[] = { - cpu_to_be32(0x4), /* length */ - cpu_to_be32(0x0), cpu_to_be32(0x0), - cpu_to_be32(0x0), cpu_to_be32(nodeid) - }; char mem_name[32]; uint64_t mem_reg_property[2]; int off; @@ -334,8 +324,7 @@ static int spapr_dt_memory_node(void *fdt, int nodeid, hwaddr start, _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, sizeof(mem_reg_property)))); - _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity, - sizeof(associativity)))); + spapr_numa_write_associativity_dt(spapr, fdt, off, nodeid); return off; } @@ -445,7 +434,8 @@ static int spapr_dt_dynamic_memory_v2(SpaprMachineState *spapr, void *fdt, g_assert(drc); elem = spapr_get_drconf_cell(size / lmb_size, addr, spapr_drc_index(drc), node, - SPAPR_LMB_FLAGS_ASSIGNED); + (SPAPR_LMB_FLAGS_ASSIGNED | + SPAPR_LMB_FLAGS_HOTREMOVABLE)); QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry); nr_entries++; cur_addr = addr + size; @@ -554,12 +544,10 @@ static int spapr_dt_dynamic_reconfiguration_memory(SpaprMachineState *spapr, void *fdt) { MachineState *machine = MACHINE(spapr); - int nb_numa_nodes = machine->numa_state->num_nodes; - int ret, i, offset; + int ret, offset; uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; - uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; - uint32_t *int_buf, *cur_index, buf_len; - int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; + uint32_t prop_lmb_size[] = {cpu_to_be32(lmb_size >> 32), + cpu_to_be32(lmb_size & 0xffffffff)}; MemoryDeviceInfoList *dimms = NULL; /* @@ -600,25 +588,7 @@ static int spapr_dt_dynamic_reconfiguration_memory(SpaprMachineState *spapr, return ret; } - /* ibm,associativity-lookup-arrays */ - buf_len = (nr_nodes * 4 + 2) * sizeof(uint32_t); - cur_index = int_buf = g_malloc0(buf_len); - int_buf[0] = cpu_to_be32(nr_nodes); - int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */ - cur_index += 2; - for (i = 0; i < nr_nodes; i++) { - uint32_t associativity[] = { - cpu_to_be32(0x0), - cpu_to_be32(0x0), - cpu_to_be32(0x0), - cpu_to_be32(i) - }; - memcpy(cur_index, associativity, sizeof(associativity)); - cur_index += 4; - } - ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf, - (cur_index - int_buf) * sizeof(uint32_t)); - g_free(int_buf); + ret = spapr_numa_write_assoc_lookup_arrays(spapr, fdt, offset); return ret; } @@ -646,7 +616,7 @@ static int spapr_dt_memory(SpaprMachineState *spapr, void *fdt) if (!mem_start) { /* spapr_machine_init() checks for rma_size <= node0_size * already */ - spapr_dt_memory_node(fdt, i, 0, spapr->rma_size); + spapr_dt_memory_node(spapr, fdt, i, 0, spapr->rma_size); mem_start += spapr->rma_size; node_size -= spapr->rma_size; } @@ -658,7 +628,7 @@ static int spapr_dt_memory(SpaprMachineState *spapr, void *fdt) sizetmp = 1ULL << ctzl(mem_start); } - spapr_dt_memory_node(fdt, i, mem_start, sizetmp); + spapr_dt_memory_node(spapr, fdt, i, mem_start, sizetmp); node_size -= sizetmp; mem_start += sizetmp; } @@ -788,7 +758,7 @@ static void spapr_dt_cpu(CPUState *cs, void *fdt, int offset, pft_size_prop, sizeof(pft_size_prop)))); if (ms->numa_state->num_nodes > 1) { - _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cpu)); + _FDT(spapr_numa_fixup_cpu_dt(spapr, fdt, offset, cpu)); } _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt)); @@ -892,23 +862,15 @@ static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt) int rtas; GString *hypertas = g_string_sized_new(256); GString *qemu_hypertas = g_string_sized_new(256); - uint32_t refpoints[] = { cpu_to_be32(0x4), cpu_to_be32(0x4) }; uint64_t max_device_addr = MACHINE(spapr)->device_memory->base + memory_region_size(&MACHINE(spapr)->device_memory->mr); uint32_t lrdr_capacity[] = { cpu_to_be32(max_device_addr >> 32), cpu_to_be32(max_device_addr & 0xffffffff), - 0, cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE), + cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE >> 32), + cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE & 0xffffffff), cpu_to_be32(ms->smp.max_cpus / ms->smp.threads), }; - uint32_t maxdomain = cpu_to_be32(spapr->gpu_numa_id > 1 ? 1 : 0); - uint32_t maxdomains[] = { - cpu_to_be32(4), - maxdomain, - maxdomain, - maxdomain, - cpu_to_be32(spapr->gpu_numa_id), - }; _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas")); @@ -944,11 +906,7 @@ static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt) qemu_hypertas->str, qemu_hypertas->len)); g_string_free(qemu_hypertas, TRUE); - _FDT(fdt_setprop(fdt, rtas, "ibm,associativity-reference-points", - refpoints, sizeof(refpoints))); - - _FDT(fdt_setprop(fdt, rtas, "ibm,max-associativity-domains", - maxdomains, sizeof(maxdomains))); + spapr_numa_write_rtas_dt(spapr, fdt, rtas); /* * FWNMI reserves RTAS_ERROR_LOG_MAX for the machine check error log, @@ -1284,7 +1242,7 @@ void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space) /* NVDIMM devices */ if (mc->nvdimm_supported) { - spapr_dt_persistent_memory(fdt); + spapr_dt_persistent_memory(spapr, fdt); } return fdt; @@ -1525,28 +1483,35 @@ void spapr_free_hpt(SpaprMachineState *spapr) close_htab_fd(spapr); } -void spapr_reallocate_hpt(SpaprMachineState *spapr, int shift, - Error **errp) +int spapr_reallocate_hpt(SpaprMachineState *spapr, int shift, Error **errp) { + ERRP_GUARD(); long rc; /* Clean up any HPT info from a previous boot */ spapr_free_hpt(spapr); rc = kvmppc_reset_htab(shift); + + if (rc == -EOPNOTSUPP) { + error_setg(errp, "HPT not supported in nested guests"); + return -EOPNOTSUPP; + } + if (rc < 0) { /* kernel-side HPT needed, but couldn't allocate one */ - error_setg_errno(errp, errno, - "Failed to allocate KVM HPT of order %d (try smaller maxmem?)", + error_setg_errno(errp, errno, "Failed to allocate KVM HPT of order %d", shift); - /* This is almost certainly fatal, but if the caller really - * wants to carry on with shift == 0, it's welcome to try */ + error_append_hint(errp, "Try smaller maxmem?\n"); + return -errno; } else if (rc > 0) { /* kernel-side HPT allocated */ if (rc != shift) { error_setg(errp, - "Requested order %d HPT, but kernel allocated order %ld (try smaller maxmem?)", + "Requested order %d HPT, but kernel allocated order %ld", shift, rc); + error_append_hint(errp, "Try smaller maxmem?\n"); + return -ENOSPC; } spapr->htab_shift = shift; @@ -1557,12 +1522,6 @@ void spapr_reallocate_hpt(SpaprMachineState *spapr, int shift, int i; spapr->htab = qemu_memalign(size, size); - if (!spapr->htab) { - error_setg_errno(errp, errno, - "Could not allocate HPT of order %d", shift); - return; - } - memset(spapr->htab, 0, size); spapr->htab_shift = shift; @@ -1573,6 +1532,7 @@ void spapr_reallocate_hpt(SpaprMachineState *spapr, int shift, /* We're setting up a hash table, so that means we're not radix */ spapr->patb_entry = 0; spapr_set_all_lpcrs(0, LPCR_HR | LPCR_UPRT); + return 0; } void spapr_setup_hpt(SpaprMachineState *spapr) @@ -1711,26 +1671,25 @@ static void spapr_machine_reset(MachineState *machine) static void spapr_create_nvram(SpaprMachineState *spapr) { - DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); + DeviceState *dev = qdev_new("spapr-nvram"); DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); if (dinfo) { - qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo), - &error_fatal); + qdev_prop_set_drive_err(dev, "drive", blk_by_legacy_dinfo(dinfo), + &error_fatal); } - qdev_init_nofail(dev); + qdev_realize_and_unref(dev, &spapr->vio_bus->bus, &error_fatal); spapr->nvram = (struct SpaprNvram *)dev; } static void spapr_rtc_create(SpaprMachineState *spapr) { - object_initialize_child(OBJECT(spapr), "rtc", - &spapr->rtc, sizeof(spapr->rtc), TYPE_SPAPR_RTC, - &error_fatal, NULL); - object_property_set_bool(OBJECT(&spapr->rtc), true, "realized", - &error_fatal); + object_initialize_child_with_props(OBJECT(spapr), "rtc", &spapr->rtc, + sizeof(spapr->rtc), TYPE_SPAPR_RTC, + &error_fatal, NULL); + qdev_realize(DEVICE(&spapr->rtc), NULL, &error_fatal); object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc), "date"); } @@ -2327,11 +2286,13 @@ static int htab_load(QEMUFile *f, void *opaque, int version_id) } if (section_hdr) { + int ret; + /* First section gives the htab size */ - spapr_reallocate_hpt(spapr, section_hdr, &local_err); - if (local_err) { + ret = spapr_reallocate_hpt(spapr, section_hdr, &local_err); + if (ret < 0) { error_report_err(local_err); - return -EINVAL; + return ret; } return 0; } @@ -2382,8 +2343,10 @@ static int htab_load(QEMUFile *f, void *opaque, int version_id) assert(fd >= 0); - rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid); + rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid, + &local_err); if (rc < 0) { + error_report_err(local_err); return rc; } } @@ -2497,23 +2460,23 @@ static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp) unsigned int smp_threads = ms->smp.threads; if (!kvm_enabled() && (smp_threads > 1)) { - error_setg(&local_err, "TCG cannot support more than 1 thread/core " - "on a pseries machine"); - goto out; + error_setg(errp, "TCG cannot support more than 1 thread/core " + "on a pseries machine"); + return; } if (!is_power_of_2(smp_threads)) { - error_setg(&local_err, "Cannot support %d threads/core on a pseries " - "machine because it must be a power of 2", smp_threads); - goto out; + error_setg(errp, "Cannot support %d threads/core on a pseries " + "machine because it must be a power of 2", smp_threads); + return; } /* Detemine the VSMT mode to use: */ if (vsmt_user) { if (spapr->vsmt < smp_threads) { - error_setg(&local_err, "Cannot support VSMT mode %d" - " because it must be >= threads/core (%d)", - spapr->vsmt, smp_threads); - goto out; + error_setg(errp, "Cannot support VSMT mode %d" + " because it must be >= threads/core (%d)", + spapr->vsmt, smp_threads); + return; } /* In this case, spapr->vsmt has been set by the command line */ } else if (!smc->smp_threads_vsmt) { @@ -2543,8 +2506,6 @@ static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp) * behaviour will be correct */ if ((kvm_smt >= smp_threads) && ((spapr->vsmt % kvm_smt) == 0)) { warn_report_err(local_err); - local_err = NULL; - goto out; } else { if (!vsmt_user) { error_append_hint(&local_err, @@ -2554,13 +2515,11 @@ static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp) smp_threads, kvm_smt, spapr->vsmt); } kvmppc_error_append_smt_possible_hint(&local_err); - goto out; + error_propagate(errp, local_err); } } } /* else TCG: nothing to do currently */ -out: - error_propagate(errp, local_err); } static void spapr_init_cpus(SpaprMachineState *spapr) @@ -2624,11 +2583,11 @@ static void spapr_init_cpus(SpaprMachineState *spapr) nr_threads = smp_cpus - i * smp_threads; } - object_property_set_int(core, nr_threads, "nr-threads", + object_property_set_int(core, "nr-threads", nr_threads, &error_fatal); - object_property_set_int(core, core_id, CPU_CORE_PROP_CORE_ID, + object_property_set_int(core, CPU_CORE_PROP_CORE_ID, core_id, &error_fatal); - object_property_set_bool(core, true, "realized", &error_fatal); + qdev_realize(DEVICE(core), NULL, &error_fatal); object_unref(core); } @@ -2639,9 +2598,9 @@ static PCIHostState *spapr_create_default_phb(void) { DeviceState *dev; - dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE); + dev = qdev_new(TYPE_SPAPR_PCI_HOST_BRIDGE); qdev_prop_set_uint32(dev, "index", 0); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); return PCI_HOST_BRIDGE(dev); } @@ -2682,6 +2641,16 @@ static hwaddr spapr_rma_size(SpaprMachineState *spapr, Error **errp) return rma_size; } +static void spapr_create_nvdimm_dr_connectors(SpaprMachineState *spapr) +{ + MachineState *machine = MACHINE(spapr); + int i; + + for (i = 0; i < machine->ram_slots; i++) { + spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_PMEM, i); + } +} + /* pSeries LPAR / sPAPR hardware init */ static void spapr_machine_init(MachineState *machine) { @@ -2731,6 +2700,7 @@ static void spapr_machine_init(MachineState *machine) error_report_err(resize_hpt_err); exit(1); } + error_free(resize_hpt_err); spapr->rma_size = spapr_rma_size(spapr, &error_fatal); @@ -2823,6 +2793,9 @@ static void spapr_machine_init(MachineState *machine) */ spapr->gpu_numa_id = MAX(1, machine->numa_state->num_nodes); + /* Init numa_assoc_array */ + spapr_numa_associativity_init(spapr, machine); + if ((!kvm_enabled() || kvmppc_has_cap_mmu_radix()) && ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0, spapr->max_compat_pvr)) { @@ -2971,18 +2944,15 @@ static void spapr_machine_init(MachineState *machine) } if (kernel_filename) { - uint64_t lowaddr = 0; - spapr->kernel_size = load_elf(kernel_filename, NULL, translate_kernel_address, spapr, - NULL, &lowaddr, NULL, NULL, 1, + NULL, NULL, NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0); if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) { spapr->kernel_size = load_elf(kernel_filename, NULL, - translate_kernel_address, spapr, NULL, - &lowaddr, NULL, NULL, 0, - PPC_ELF_MACHINE, - 0, 0); + translate_kernel_address, spapr, + NULL, NULL, NULL, NULL, 0, + PPC_ELF_MACHINE, 0, 0); spapr->kernel_le = spapr->kernel_size > 0; } if (spapr->kernel_size < 0) { @@ -3032,8 +3002,7 @@ static void spapr_machine_init(MachineState *machine) register_savevm_live("spapr/htab", VMSTATE_INSTANCE_ID_ANY, 1, &savevm_htab_handlers, spapr); - qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine), - &error_fatal); + qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine)); qemu_register_boot_set(spapr_boot_set, spapr); @@ -3408,12 +3377,12 @@ int spapr_lmb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, addr = spapr_drc_index(drc) * SPAPR_MEMORY_BLOCK_SIZE; node = object_property_get_uint(OBJECT(drc->dev), PC_DIMM_NODE_PROP, &error_abort); - *fdt_start_offset = spapr_dt_memory_node(fdt, node, addr, + *fdt_start_offset = spapr_dt_memory_node(spapr, fdt, node, addr, SPAPR_MEMORY_BLOCK_SIZE); return 0; } -static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, +static bool spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, bool dedicated_hp_event_source, Error **errp) { SpaprDrc *drc; @@ -3421,23 +3390,20 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, int i; uint64_t addr = addr_start; bool hotplugged = spapr_drc_hotplugged(dev); - Error *local_err = NULL; for (i = 0; i < nr_lmbs; i++) { drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr / SPAPR_MEMORY_BLOCK_SIZE); g_assert(drc); - spapr_drc_attach(drc, dev, &local_err); - if (local_err) { + if (!spapr_drc_attach(drc, dev, errp)) { while (addr > addr_start) { addr -= SPAPR_MEMORY_BLOCK_SIZE; drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr / SPAPR_MEMORY_BLOCK_SIZE); spapr_drc_detach(drc); } - error_propagate(errp, local_err); - return; + return false; } if (!hotplugged) { spapr_drc_reset(drc); @@ -3459,52 +3425,43 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, nr_lmbs); } } + return true; } static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - Error *local_err = NULL; SpaprMachineState *ms = SPAPR_MACHINE(hotplug_dev); PCDIMMDevice *dimm = PC_DIMM(dev); - uint64_t size, addr, slot; + uint64_t size, addr; + int64_t slot; bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); size = memory_device_get_region_size(MEMORY_DEVICE(dev), &error_abort); - pc_dimm_plug(dimm, MACHINE(ms), &local_err); - if (local_err) { - goto out; - } + pc_dimm_plug(dimm, MACHINE(ms)); if (!is_nvdimm) { addr = object_property_get_uint(OBJECT(dimm), - PC_DIMM_ADDR_PROP, &local_err); - if (local_err) { + PC_DIMM_ADDR_PROP, &error_abort); + if (!spapr_add_lmbs(dev, addr, size, + spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), errp)) { goto out_unplug; } - spapr_add_lmbs(dev, addr, size, - spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), - &local_err); } else { - slot = object_property_get_uint(OBJECT(dimm), - PC_DIMM_SLOT_PROP, &local_err); - if (local_err) { + slot = object_property_get_int(OBJECT(dimm), + PC_DIMM_SLOT_PROP, &error_abort); + /* We should have valid slot number at this point */ + g_assert(slot >= 0); + if (!spapr_add_nvdimm(dev, slot, errp)) { goto out_unplug; } - spapr_add_nvdimm(dev, slot, &local_err); - } - - if (local_err) { - goto out_unplug; } return; out_unplug: pc_dimm_unplug(dimm, MACHINE(ms)); -out: - error_propagate(errp, local_err); } static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, @@ -3512,7 +3469,6 @@ static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, { const SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev); SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); - const MachineClass *mc = MACHINE_CLASS(smc); bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); PCDIMMDevice *dimm = PC_DIMM(dev); Error *local_err = NULL; @@ -3525,35 +3481,26 @@ static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, return; } - if (is_nvdimm && !mc->nvdimm_supported) { - error_setg(errp, "NVDIMM hotplug not supported for this machine"); - return; - } - size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &local_err); if (local_err) { error_propagate(errp, local_err); return; } - if (!is_nvdimm && size % SPAPR_MEMORY_BLOCK_SIZE) { + if (is_nvdimm) { + if (!spapr_nvdimm_validate(hotplug_dev, NVDIMM(dev), size, errp)) { + return; + } + } else if (size % SPAPR_MEMORY_BLOCK_SIZE) { error_setg(errp, "Hotplugged memory size must be a multiple of " "%" PRIu64 " MB", SPAPR_MEMORY_BLOCK_SIZE / MiB); return; - } else if (is_nvdimm) { - spapr_nvdimm_validate_opts(NVDIMM(dev), size, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } } memdev = object_property_get_link(OBJECT(dimm), PC_DIMM_MEMDEV_PROP, &error_abort); pagesize = host_memory_backend_pagesize(MEMORY_BACKEND(memdev)); - spapr_check_pagesize(spapr, pagesize, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!spapr_check_pagesize(spapr, pagesize, errp)) { return; } @@ -3619,8 +3566,8 @@ static SpaprDimmState *spapr_recover_pending_dimm_state(SpaprMachineState *ms, uint64_t addr_start, addr; int i; - addr_start = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, - &error_abort); + addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, + &error_abort); addr = addr_start; for (i = 0; i < nr_lmbs; i++) { @@ -3670,7 +3617,7 @@ static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev)); - object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + qdev_unrealize(dev); spapr_pending_dimm_unplugs_remove(spapr, ds); } @@ -3678,7 +3625,6 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev); - Error *local_err = NULL; PCDIMMDevice *dimm = PC_DIMM(dev); uint32_t nr_lmbs; uint64_t size, addr_start, addr; @@ -3686,19 +3632,15 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, SpaprDrc *drc; if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { - error_setg(&local_err, - "nvdimm device hot unplug is not supported yet."); - goto out; + error_setg(errp, "nvdimm device hot unplug is not supported yet."); + return; } size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &error_abort); nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, - &local_err); - if (local_err) { - goto out; - } + &error_abort); /* * An existing pending dimm state for this DIMM means that there is an @@ -3707,10 +3649,9 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, * bail out to avoid detaching DRCs that were already released. */ if (spapr_pending_dimm_unplugs_find(spapr, dimm)) { - error_setg(&local_err, - "Memory unplug already in progress for device %s", + error_setg(errp, "Memory unplug already in progress for device %s", dev->id); - goto out; + return; } spapr_pending_dimm_unplugs_add(spapr, nr_lmbs, dimm); @@ -3729,8 +3670,6 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, addr_start / SPAPR_MEMORY_BLOCK_SIZE); spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs, spapr_drc_index(drc)); -out: - error_propagate(errp, local_err); } /* Callback to be called during DRC release. */ @@ -3763,7 +3702,7 @@ static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) assert(core_slot); core_slot->cpu = NULL; - object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + qdev_unrealize(dev); } static @@ -3826,7 +3765,6 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, CPUCore *cc = CPU_CORE(dev); CPUState *cs; SpaprDrc *drc; - Error *local_err = NULL; CPUArchId *core_slot; int index; bool hotplugged = spapr_drc_hotplugged(dev); @@ -3844,9 +3782,7 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, g_assert(drc || !mc->has_hotpluggable_cpus); if (drc) { - spapr_drc_attach(drc, dev, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!spapr_drc_attach(drc, dev, errp)) { return; } @@ -3876,10 +3812,9 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, */ if (hotplugged) { for (i = 0; i < cc->nr_threads; i++) { - ppc_set_compat(core->threads[i], POWERPC_CPU(first_cpu)->compat_pvr, - &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (ppc_set_compat(core->threads[i], + POWERPC_CPU(first_cpu)->compat_pvr, + errp) < 0) { return; } } @@ -3891,7 +3826,6 @@ static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, { MachineState *machine = MACHINE(OBJECT(hotplug_dev)); MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); - Error *local_err = NULL; CPUCore *cc = CPU_CORE(dev); const char *base_core_type = spapr_get_cpu_core_type(machine->cpu_type); const char *type = object_get_typename(OBJECT(dev)); @@ -3900,18 +3834,18 @@ static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, unsigned int smp_threads = machine->smp.threads; if (dev->hotplugged && !mc->has_hotpluggable_cpus) { - error_setg(&local_err, "CPU hotplug not supported for this machine"); - goto out; + error_setg(errp, "CPU hotplug not supported for this machine"); + return; } if (strcmp(base_core_type, type)) { - error_setg(&local_err, "CPU core type should be %s", base_core_type); - goto out; + error_setg(errp, "CPU core type should be %s", base_core_type); + return; } if (cc->core_id % smp_threads) { - error_setg(&local_err, "invalid core id %d", cc->core_id); - goto out; + error_setg(errp, "invalid core id %d", cc->core_id); + return; } /* @@ -3921,26 +3855,23 @@ static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, * total vcpus not a multiple of threads-per-core. */ if (mc->has_hotpluggable_cpus && (cc->nr_threads != smp_threads)) { - error_setg(&local_err, "invalid nr-threads %d, must be %d", - cc->nr_threads, smp_threads); - goto out; + error_setg(errp, "invalid nr-threads %d, must be %d", cc->nr_threads, + smp_threads); + return; } core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); if (!core_slot) { - error_setg(&local_err, "core id %d out of range", cc->core_id); - goto out; + error_setg(errp, "core id %d out of range", cc->core_id); + return; } if (core_slot->cpu) { - error_setg(&local_err, "core %d already populated", cc->core_id); - goto out; + error_setg(errp, "core %d already populated", cc->core_id); + return; } - numa_cpu_pre_plug(core_slot, dev, &local_err); - -out: - error_propagate(errp, local_err); + numa_cpu_pre_plug(core_slot, dev, errp); } int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, @@ -4003,7 +3934,6 @@ static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev, SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); SpaprDrc *drc; bool hotplugged = spapr_drc_hotplugged(dev); - Error *local_err = NULL; if (!smc->dr_phb_enabled) { return; @@ -4013,9 +3943,7 @@ static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev, /* hotplug hooks should check it's enabled before getting this far */ assert(drc); - spapr_drc_attach(drc, dev, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!spapr_drc_attach(drc, dev, errp)) { return; } @@ -4036,7 +3964,7 @@ void spapr_phb_release(DeviceState *dev) static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) { - object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + qdev_unrealize(dev); } static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev, @@ -4072,7 +4000,7 @@ static void spapr_tpm_proxy_unplug(HotplugHandler *hotplug_dev, DeviceState *dev { SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); - object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + qdev_unrealize(dev); object_unparent(OBJECT(dev)); spapr->tpm_proxy = NULL; } @@ -4359,7 +4287,7 @@ int spapr_get_vcpu_id(PowerPCCPU *cpu) return cpu->vcpu_id; } -void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp) +bool spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp) { SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); MachineState *ms = MACHINE(spapr); @@ -4372,10 +4300,11 @@ void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp) error_append_hint(errp, "Adjust the number of cpus to %d " "or try to raise the number of threads per core\n", vcpu_id * ms->smp.threads / spapr->vsmt); - return; + return false; } cpu->vcpu_id = vcpu_id; + return true; } PowerPCCPU *spapr_find_cpu(int vcpu_id) @@ -4510,7 +4439,6 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) * in which LMBs are represented and hot-added */ mc->numa_mem_align_shift = 28; - mc->numa_mem_supported = true; mc->auto_enable_numa = true; smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF; @@ -4581,23 +4509,45 @@ static void spapr_machine_latest_class_options(MachineClass *mc) } \ type_init(spapr_machine_register_##suffix) +/* + * pseries-5.2 + */ +static void spapr_machine_5_2_class_options(MachineClass *mc) +{ + /* Defaults for the latest behaviour inherited from the base class */ +} + +DEFINE_SPAPR_MACHINE(5_2, "5.2", true); + /* * pseries-5.1 */ static void spapr_machine_5_1_class_options(MachineClass *mc) { - /* Defaults for the latest behaviour inherited from the base class */ + SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); + + spapr_machine_5_2_class_options(mc); + compat_props_add(mc->compat_props, hw_compat_5_1, hw_compat_5_1_len); + smc->pre_5_2_numa_associativity = true; } -DEFINE_SPAPR_MACHINE(5_1, "5.1", true); +DEFINE_SPAPR_MACHINE(5_1, "5.1", false); /* * pseries-5.0 */ static void spapr_machine_5_0_class_options(MachineClass *mc) { + SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); + static GlobalProperty compat[] = { + { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-5.1-associativity", "on" }, + }; + spapr_machine_5_1_class_options(mc); compat_props_add(mc->compat_props, hw_compat_5_0, hw_compat_5_0_len); + compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); + mc->numa_mem_supported = true; + smc->pre_5_1_assoc_refpoints = true; } DEFINE_SPAPR_MACHINE(5_0, "5.0", false); @@ -4785,7 +4735,6 @@ static void spapr_machine_2_9_class_options(MachineClass *mc) spapr_machine_2_10_class_options(mc); compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len); compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); - mc->numa_auto_assign_ram = numa_legacy_auto_assign_ram; smc->pre_2_10_has_unused_icps = true; smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED; } diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c index efdc0dbbcfc05a85c3fed9219d92602318fe9fcd..9341e9782a3ff1fb1027dc96677d354b767242b5 100644 --- a/hw/ppc/spapr_caps.c +++ b/hw/ppc/spapr_caps.c @@ -86,11 +86,8 @@ static void spapr_cap_set_bool(Object *obj, Visitor *v, const char *name, SpaprCapabilityInfo *cap = opaque; SpaprMachineState *spapr = SPAPR_MACHINE(obj); bool value; - Error *local_err = NULL; - visit_type_bool(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_bool(v, name, &value, errp)) { return; } @@ -123,13 +120,10 @@ static void spapr_cap_set_string(Object *obj, Visitor *v, const char *name, { SpaprCapabilityInfo *cap = opaque; SpaprMachineState *spapr = SPAPR_MACHINE(obj); - Error *local_err = NULL; uint8_t i; char *val; - visit_type_str(v, name, &val, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_str(v, name, &val, errp)) { return; } @@ -169,11 +163,8 @@ static void spapr_cap_set_pagesize(Object *obj, Visitor *v, const char *name, SpaprMachineState *spapr = SPAPR_MACHINE(obj); uint64_t pagesize; uint8_t val; - Error *local_err = NULL; - visit_type_size(v, name, &pagesize, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_size(v, name, &pagesize, errp)) { return; } @@ -189,24 +180,24 @@ static void spapr_cap_set_pagesize(Object *obj, Visitor *v, const char *name, static void cap_htm_apply(SpaprMachineState *spapr, uint8_t val, Error **errp) { + ERRP_GUARD(); if (!val) { /* TODO: We don't support disabling htm yet */ return; } if (tcg_enabled()) { - error_setg(errp, - "No Transactional Memory support in TCG," - " try appending -machine cap-htm=off"); + error_setg(errp, "No Transactional Memory support in TCG"); + error_append_hint(errp, "Try appending -machine cap-htm=off\n"); } else if (kvm_enabled() && !kvmppc_has_cap_htm()) { error_setg(errp, -"KVM implementation does not support Transactional Memory," - " try appending -machine cap-htm=off" - ); + "KVM implementation does not support Transactional Memory"); + error_append_hint(errp, "Try appending -machine cap-htm=off\n"); } } static void cap_vsx_apply(SpaprMachineState *spapr, uint8_t val, Error **errp) { + ERRP_GUARD(); PowerPCCPU *cpu = POWERPC_CPU(first_cpu); CPUPPCState *env = &cpu->env; @@ -218,13 +209,14 @@ static void cap_vsx_apply(SpaprMachineState *spapr, uint8_t val, Error **errp) * rid of anything that doesn't do VMX */ g_assert(env->insns_flags & PPC_ALTIVEC); if (!(env->insns_flags2 & PPC2_VSX)) { - error_setg(errp, "VSX support not available," - " try appending -machine cap-vsx=off"); + error_setg(errp, "VSX support not available"); + error_append_hint(errp, "Try appending -machine cap-vsx=off\n"); } } static void cap_dfp_apply(SpaprMachineState *spapr, uint8_t val, Error **errp) { + ERRP_GUARD(); PowerPCCPU *cpu = POWERPC_CPU(first_cpu); CPUPPCState *env = &cpu->env; @@ -233,8 +225,8 @@ static void cap_dfp_apply(SpaprMachineState *spapr, uint8_t val, Error **errp) return; } if (!(env->insns_flags2 & PPC2_DFP)) { - error_setg(errp, "DFP support not available," - " try appending -machine cap-dfp=off"); + error_setg(errp, "DFP support not available"); + error_append_hint(errp, "Try appending -machine cap-dfp=off\n"); } } @@ -248,23 +240,19 @@ SpaprCapPossible cap_cfpc_possible = { static void cap_safe_cache_apply(SpaprMachineState *spapr, uint8_t val, Error **errp) { - Error *local_err = NULL; + ERRP_GUARD(); uint8_t kvm_val = kvmppc_get_cap_safe_cache(); if (tcg_enabled() && val) { /* TCG only supports broken, allow other values and print a warning */ - error_setg(&local_err, - "TCG doesn't support requested feature, cap-cfpc=%s", - cap_cfpc_possible.vals[val]); + warn_report("TCG doesn't support requested feature, cap-cfpc=%s", + cap_cfpc_possible.vals[val]); } else if (kvm_enabled() && (val > kvm_val)) { error_setg(errp, - "Requested safe cache capability level not supported by kvm," - " try appending -machine cap-cfpc=%s", - cap_cfpc_possible.vals[kvm_val]); + "Requested safe cache capability level not supported by KVM"); + error_append_hint(errp, "Try appending -machine cap-cfpc=%s\n", + cap_cfpc_possible.vals[kvm_val]); } - - if (local_err != NULL) - warn_report_err(local_err); } SpaprCapPossible cap_sbbc_possible = { @@ -277,23 +265,19 @@ SpaprCapPossible cap_sbbc_possible = { static void cap_safe_bounds_check_apply(SpaprMachineState *spapr, uint8_t val, Error **errp) { - Error *local_err = NULL; + ERRP_GUARD(); uint8_t kvm_val = kvmppc_get_cap_safe_bounds_check(); if (tcg_enabled() && val) { /* TCG only supports broken, allow other values and print a warning */ - error_setg(&local_err, - "TCG doesn't support requested feature, cap-sbbc=%s", - cap_sbbc_possible.vals[val]); + warn_report("TCG doesn't support requested feature, cap-sbbc=%s", + cap_sbbc_possible.vals[val]); } else if (kvm_enabled() && (val > kvm_val)) { error_setg(errp, -"Requested safe bounds check capability level not supported by kvm," - " try appending -machine cap-sbbc=%s", - cap_sbbc_possible.vals[kvm_val]); +"Requested safe bounds check capability level not supported by KVM"); + error_append_hint(errp, "Try appending -machine cap-sbbc=%s\n", + cap_sbbc_possible.vals[kvm_val]); } - - if (local_err != NULL) - warn_report_err(local_err); } SpaprCapPossible cap_ibs_possible = { @@ -309,35 +293,30 @@ SpaprCapPossible cap_ibs_possible = { static void cap_safe_indirect_branch_apply(SpaprMachineState *spapr, uint8_t val, Error **errp) { - Error *local_err = NULL; + ERRP_GUARD(); uint8_t kvm_val = kvmppc_get_cap_safe_indirect_branch(); if (tcg_enabled() && val) { /* TCG only supports broken, allow other values and print a warning */ - error_setg(&local_err, - "TCG doesn't support requested feature, cap-ibs=%s", - cap_ibs_possible.vals[val]); + warn_report("TCG doesn't support requested feature, cap-ibs=%s", + cap_ibs_possible.vals[val]); } else if (kvm_enabled() && (val > kvm_val)) { error_setg(errp, -"Requested safe indirect branch capability level not supported by kvm," - " try appending -machine cap-ibs=%s", - cap_ibs_possible.vals[kvm_val]); - } - - if (local_err != NULL) { - warn_report_err(local_err); +"Requested safe indirect branch capability level not supported by KVM"); + error_append_hint(errp, "Try appending -machine cap-ibs=%s\n", + cap_ibs_possible.vals[kvm_val]); } } #define VALUE_DESC_TRISTATE " (broken, workaround, fixed)" -void spapr_check_pagesize(SpaprMachineState *spapr, hwaddr pagesize, +bool spapr_check_pagesize(SpaprMachineState *spapr, hwaddr pagesize, Error **errp) { hwaddr maxpagesize = (1ULL << spapr->eff.caps[SPAPR_CAP_HPT_MAXPAGESIZE]); if (!kvmppc_hpt_needs_host_contiguous_pages()) { - return; + return true; } if (maxpagesize > pagesize) { @@ -345,7 +324,10 @@ void spapr_check_pagesize(SpaprMachineState *spapr, hwaddr pagesize, "Can't support %"HWADDR_PRIu" kiB guest pages with %" HWADDR_PRIu" kiB host pages with this KVM implementation", maxpagesize >> 10, pagesize >> 10); + return false; } + + return true; } static void cap_hpt_maxpagesize_apply(SpaprMachineState *spapr, @@ -402,23 +384,35 @@ static void cap_hpt_maxpagesize_cpu_apply(SpaprMachineState *spapr, static void cap_nested_kvm_hv_apply(SpaprMachineState *spapr, uint8_t val, Error **errp) { + ERRP_GUARD(); + PowerPCCPU *cpu = POWERPC_CPU(first_cpu); + if (!val) { /* capability disabled by default */ return; } if (tcg_enabled()) { - error_setg(errp, - "No Nested KVM-HV support in tcg," - " try appending -machine cap-nested-hv=off"); + error_setg(errp, "No Nested KVM-HV support in TCG"); + error_append_hint(errp, "Try appending -machine cap-nested-hv=off\n"); } else if (kvm_enabled()) { + if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0, + spapr->max_compat_pvr)) { + error_setg(errp, "Nested KVM-HV only supported on POWER9"); + error_append_hint(errp, + "Try appending -machine max-cpu-compat=power9\n"); + return; + } + if (!kvmppc_has_cap_nested_kvm_hv()) { error_setg(errp, -"KVM implementation does not support Nested KVM-HV," - " try appending -machine cap-nested-hv=off"); + "KVM implementation does not support Nested KVM-HV"); + error_append_hint(errp, + "Try appending -machine cap-nested-hv=off\n"); } else if (kvmppc_set_cap_nested_kvm_hv(val) < 0) { - error_setg(errp, -"Error enabling cap-nested-hv with KVM, try cap-nested-hv=off"); + error_setg(errp, "Error enabling cap-nested-hv with KVM"); + error_append_hint(errp, + "Try appending -machine cap-nested-hv=off\n"); } } } @@ -426,6 +420,7 @@ static void cap_nested_kvm_hv_apply(SpaprMachineState *spapr, static void cap_large_decr_apply(SpaprMachineState *spapr, uint8_t val, Error **errp) { + ERRP_GUARD(); PowerPCCPU *cpu = POWERPC_CPU(first_cpu); PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); @@ -436,22 +431,23 @@ static void cap_large_decr_apply(SpaprMachineState *spapr, if (tcg_enabled()) { if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0, spapr->max_compat_pvr)) { - error_setg(errp, - "Large decrementer only supported on POWER9, try -cpu POWER9"); + error_setg(errp, "Large decrementer only supported on POWER9"); + error_append_hint(errp, "Try -cpu POWER9\n"); return; } } else if (kvm_enabled()) { int kvm_nr_bits = kvmppc_get_cap_large_decr(); if (!kvm_nr_bits) { - error_setg(errp, - "No large decrementer support," - " try appending -machine cap-large-decr=off"); + error_setg(errp, "No large decrementer support"); + error_append_hint(errp, + "Try appending -machine cap-large-decr=off\n"); } else if (pcc->lrg_decr_bits != kvm_nr_bits) { error_setg(errp, -"KVM large decrementer size (%d) differs to model (%d)," - " try appending -machine cap-large-decr=off", - kvm_nr_bits, pcc->lrg_decr_bits); + "KVM large decrementer size (%d) differs to model (%d)", + kvm_nr_bits, pcc->lrg_decr_bits); + error_append_hint(errp, + "Try appending -machine cap-large-decr=off\n"); } } } @@ -460,14 +456,15 @@ static void cap_large_decr_cpu_apply(SpaprMachineState *spapr, PowerPCCPU *cpu, uint8_t val, Error **errp) { + ERRP_GUARD(); CPUPPCState *env = &cpu->env; target_ulong lpcr = env->spr[SPR_LPCR]; if (kvm_enabled()) { if (kvmppc_enable_cap_large_decr(cpu, val)) { - error_setg(errp, - "No large decrementer support," - " try appending -machine cap-large-decr=off"); + error_setg(errp, "No large decrementer support"); + error_append_hint(errp, + "Try appending -machine cap-large-decr=off\n"); } } @@ -482,6 +479,7 @@ static void cap_large_decr_cpu_apply(SpaprMachineState *spapr, static void cap_ccf_assist_apply(SpaprMachineState *spapr, uint8_t val, Error **errp) { + ERRP_GUARD(); uint8_t kvm_val = kvmppc_get_cap_count_cache_flush_assist(); if (tcg_enabled() && val) { @@ -504,14 +502,15 @@ static void cap_ccf_assist_apply(SpaprMachineState *spapr, uint8_t val, return; } error_setg(errp, -"Requested count cache flush assist capability level not supported by kvm," - " try appending -machine cap-ccf-assist=off"); + "Requested count cache flush assist capability level not supported by KVM"); + error_append_hint(errp, "Try appending -machine cap-ccf-assist=off\n"); } } static void cap_fwnmi_apply(SpaprMachineState *spapr, uint8_t val, Error **errp) { + ERRP_GUARD(); if (!val) { return; /* Disabled by default */ } diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index e1f76c74f3c4b7d4f071f50b1c786f5695d0c8ca..2f7dc3c23ded4d4d2c09ee3c777cdfcfe85a2f12 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -36,11 +36,6 @@ static void spapr_reset_vcpu(PowerPCCPU *cpu) cpu_reset(cs); - /* All CPUs start halted. CPU0 is unhalted from the machine level - * reset code and the rest are explicitly started up by the guest - * using an RTAS call */ - cs->halted = 1; - env->spr[SPR_HIOR] = 0; lpcr = env->spr[SPR_LPCR]; @@ -192,8 +187,7 @@ static void spapr_unrealize_vcpu(PowerPCCPU *cpu, SpaprCpuCore *sc) vmstate_unregister(NULL, &vmstate_spapr_cpu_state, cpu->machine_data); } spapr_irq_cpu_intc_destroy(SPAPR_MACHINE(qdev_get_machine()), cpu); - cpu_remove_sync(CPU(cpu)); - object_unparent(OBJECT(cpu)); + qdev_unrealize(DEVICE(cpu)); } /* @@ -218,30 +212,47 @@ static void spapr_cpu_core_reset_handler(void *opaque) spapr_cpu_core_reset(opaque); } +static void spapr_delete_vcpu(PowerPCCPU *cpu) +{ + SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); + + cpu->machine_data = NULL; + g_free(spapr_cpu); + object_unparent(OBJECT(cpu)); +} + static void spapr_cpu_core_unrealize(DeviceState *dev) { SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); CPUCore *cc = CPU_CORE(dev); int i; - qemu_unregister_reset(spapr_cpu_core_reset_handler, sc); - for (i = 0; i < cc->nr_threads; i++) { - spapr_unrealize_vcpu(sc->threads[i], sc); + if (sc->threads[i]) { + /* + * Since this we can get here from the error path of + * spapr_cpu_core_realize(), make sure we only unrealize + * vCPUs that have already been realized. + */ + if (object_property_get_bool(OBJECT(sc->threads[i]), "realized", + &error_abort)) { + spapr_unrealize_vcpu(sc->threads[i], sc); + } + spapr_delete_vcpu(sc->threads[i]); + } } g_free(sc->threads); + qemu_unregister_reset(spapr_cpu_core_reset_handler, sc); } -static void spapr_realize_vcpu(PowerPCCPU *cpu, SpaprMachineState *spapr, +static bool spapr_realize_vcpu(PowerPCCPU *cpu, SpaprMachineState *spapr, SpaprCpuCore *sc, Error **errp) { CPUPPCState *env = &cpu->env; CPUState *cs = CPU(cpu); - Error *local_err = NULL; - object_property_set_bool(OBJECT(cpu), true, "realized", &local_err); - if (local_err) { - goto error; + if (!qdev_realize(DEVICE(cpu), NULL, errp)) { + return false; } /* Set time-base frequency to 512 MHz */ @@ -250,21 +261,16 @@ static void spapr_realize_vcpu(PowerPCCPU *cpu, SpaprMachineState *spapr, cpu_ppc_set_vhyp(cpu, PPC_VIRTUAL_HYPERVISOR(spapr)); kvmppc_set_papr(cpu); - if (spapr_irq_cpu_intc_create(spapr, cpu, &local_err) < 0) { - goto error_intc_create; + if (spapr_irq_cpu_intc_create(spapr, cpu, errp) < 0) { + qdev_unrealize(DEVICE(cpu)); + return false; } if (!sc->pre_3_0_migration) { vmstate_register(NULL, cs->cpu_index, &vmstate_spapr_cpu_state, cpu->machine_data); } - - return; - -error_intc_create: - cpu_remove_sync(CPU(cpu)); -error: - error_propagate(errp, local_err); + return true; } static PowerPCCPU *spapr_create_vcpu(SpaprCpuCore *sc, int i, Error **errp) @@ -275,15 +281,18 @@ static PowerPCCPU *spapr_create_vcpu(SpaprCpuCore *sc, int i, Error **errp) char *id; CPUState *cs; PowerPCCPU *cpu; - Error *local_err = NULL; obj = object_new(scc->cpu_type); cs = CPU(obj); cpu = POWERPC_CPU(obj); + /* + * All CPUs start halted. CPU0 is unhalted from the machine level reset code + * and the rest are explicitly started up by the guest using an RTAS call. + */ + cs->start_powered_off = true; cs->cpu_index = cc->core_id + i; - spapr_set_vcpu_id(cpu, cs->cpu_index, &local_err); - if (local_err) { + if (!spapr_set_vcpu_id(cpu, cs->cpu_index, errp)) { goto err; } @@ -300,19 +309,9 @@ static PowerPCCPU *spapr_create_vcpu(SpaprCpuCore *sc, int i, Error **errp) err: object_unref(obj); - error_propagate(errp, local_err); return NULL; } -static void spapr_delete_vcpu(PowerPCCPU *cpu, SpaprCpuCore *sc) -{ - SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); - - cpu->machine_data = NULL; - g_free(spapr_cpu); - object_unparent(OBJECT(cpu)); -} - static void spapr_cpu_core_realize(DeviceState *dev, Error **errp) { /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user @@ -323,42 +322,23 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp) TYPE_SPAPR_MACHINE); SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); CPUCore *cc = CPU_CORE(OBJECT(dev)); - Error *local_err = NULL; - int i, j; + int i; if (!spapr) { error_setg(errp, TYPE_SPAPR_CPU_CORE " needs a pseries machine"); return; } - sc->threads = g_new(PowerPCCPU *, cc->nr_threads); + qemu_register_reset(spapr_cpu_core_reset_handler, sc); + sc->threads = g_new0(PowerPCCPU *, cc->nr_threads); for (i = 0; i < cc->nr_threads; i++) { - sc->threads[i] = spapr_create_vcpu(sc, i, &local_err); - if (local_err) { - goto err; - } - } - - for (j = 0; j < cc->nr_threads; j++) { - spapr_realize_vcpu(sc->threads[j], spapr, sc, &local_err); - if (local_err) { - goto err_unrealize; + sc->threads[i] = spapr_create_vcpu(sc, i, errp); + if (!sc->threads[i] || + !spapr_realize_vcpu(sc->threads[i], spapr, sc, errp)) { + spapr_cpu_core_unrealize(dev); + return; } } - - qemu_register_reset(spapr_cpu_core_reset_handler, sc); - return; - -err_unrealize: - while (--j >= 0) { - spapr_unrealize_vcpu(sc->threads[j], sc); - } -err: - while (--i >= 0) { - spapr_delete_vcpu(sc->threads[i], sc); - } - g_free(sc->threads); - error_propagate(errp, local_err); } static Property spapr_cpu_core_properties[] = { @@ -407,6 +387,7 @@ static const TypeInfo spapr_cpu_core_type_infos[] = { DEFINE_SPAPR_CPU_CORE_TYPE("power8nvl_v1.0"), DEFINE_SPAPR_CPU_CORE_TYPE("power9_v1.0"), DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.0"), + DEFINE_SPAPR_CPU_CORE_TYPE("power10_v1.0"), #ifdef CONFIG_KVM DEFINE_SPAPR_CPU_CORE_TYPE("host"), #endif diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index b958f8acb5ef114b9d0a21c78a11346332137b21..77718cde1ff2339f4a19b95b4951e255b8a67466 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -302,7 +302,6 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, { SpaprDrc *drc = SPAPR_DR_CONNECTOR(obj); QNull *null = NULL; - Error *err = NULL; int fdt_offset_next, fdt_offset, fdt_depth; void *fdt; @@ -321,25 +320,23 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, const struct fdt_property *prop = NULL; int prop_len = 0, name_len = 0; uint32_t tag; + bool ok; tag = fdt_next_tag(fdt, fdt_offset, &fdt_offset_next); switch (tag) { case FDT_BEGIN_NODE: fdt_depth++; name = fdt_get_name(fdt, fdt_offset, &name_len); - visit_start_struct(v, name, NULL, 0, &err); - if (err) { - error_propagate(errp, err); + if (!visit_start_struct(v, name, NULL, 0, errp)) { return; } break; case FDT_END_NODE: /* shouldn't ever see an FDT_END_NODE before FDT_BEGIN_NODE */ g_assert(fdt_depth > 0); - visit_check_struct(v, &err); + ok = visit_check_struct(v, errp); visit_end_struct(v, NULL); - if (err) { - error_propagate(errp, err); + if (!ok) { return; } fdt_depth--; @@ -348,22 +345,18 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, int i; prop = fdt_get_property_by_offset(fdt, fdt_offset, &prop_len); name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); - visit_start_list(v, name, NULL, 0, &err); - if (err) { - error_propagate(errp, err); + if (!visit_start_list(v, name, NULL, 0, errp)) { return; } for (i = 0; i < prop_len; i++) { - visit_type_uint8(v, NULL, (uint8_t *)&prop->data[i], &err); - if (err) { - error_propagate(errp, err); + if (!visit_type_uint8(v, NULL, (uint8_t *)&prop->data[i], + errp)) { return; } } - visit_check_list(v, &err); + ok = visit_check_list(v, errp); visit_end_list(v, NULL); - if (err) { - error_propagate(errp, err); + if (!ok) { return; } break; @@ -376,13 +369,13 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, } while (fdt_depth != 0); } -void spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp) +bool spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp) { trace_spapr_drc_attach(spapr_drc_index(drc)); if (drc->dev) { error_setg(errp, "an attached device is still awaiting release"); - return; + return false; } g_assert((drc->state == SPAPR_DRC_STATE_LOGICAL_UNUSABLE) || (drc->state == SPAPR_DRC_STATE_PHYSICAL_POWERON)); @@ -393,6 +386,7 @@ void spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp) object_get_typename(OBJECT(drc->dev)), (Object **)(&drc->dev), NULL, 0); + return true; } static void spapr_drc_release(SpaprDrc *drc) @@ -518,7 +512,7 @@ static void realize(DeviceState *d, Error **errp) SpaprDrc *drc = SPAPR_DR_CONNECTOR(d); Object *root_container; gchar *link_name; - char *child_name; + const char *child_name; trace_spapr_drc_realize(spapr_drc_index(drc)); /* NOTE: we do this as part of realize/unrealize due to the fact @@ -534,7 +528,6 @@ static void realize(DeviceState *d, Error **errp) trace_spapr_drc_realize_child(spapr_drc_index(drc), child_name); object_property_add_alias(root_container, link_name, drc->owner, child_name); - g_free(child_name); g_free(link_name); vmstate_register(VMSTATE_IF(drc), spapr_drc_index(drc), &vmstate_spapr_drc, drc); @@ -567,7 +560,7 @@ SpaprDrc *spapr_dr_connector_new(Object *owner, const char *type, spapr_drc_index(drc)); object_property_add_child(owner, prop_name, OBJECT(drc)); object_unref(OBJECT(drc)); - object_property_set_bool(OBJECT(drc), true, "realized", NULL); + qdev_realize(DEVICE(drc), NULL, NULL); g_free(prop_name); return drc; @@ -593,7 +586,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data) dk->realize = realize; dk->unrealize = unrealize; /* - * Reason: it crashes FIXME find and document the real reason + * Reason: DR connector needs to be wired to either the machine or to a + * PHB in spapr_dr_connector_new(). */ dk->user_creatable = false; } @@ -872,7 +866,8 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask) continue; } - obj = object_property_get_link(root_container, prop->name, NULL); + obj = object_property_get_link(root_container, prop->name, + &error_abort); drc = SPAPR_DR_CONNECTOR(obj); drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); @@ -1163,16 +1158,14 @@ static void rtas_ibm_configure_connector(PowerPCCPU *cpu, drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); if (!drc->fdt) { - Error *local_err = NULL; void *fdt; int fdt_size; fdt = create_device_tree(&fdt_size); if (drck->dt_populate(drc, spapr, fdt, &drc->fdt_start_offset, - &local_err)) { + NULL)) { g_free(fdt); - error_free(local_err); rc = SPAPR_DR_CC_RESPONSE_ERROR; goto out; } diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c index 1069d0197b4f3d16dd9ee0b5b2cbff306bc34ccf..1add53547ec3e82d88e90b4ece0f73210864ed31 100644 --- a/hw/ppc/spapr_events.c +++ b/hw/ppc/spapr_events.c @@ -1000,10 +1000,22 @@ static void event_scan(PowerPCCPU *cpu, SpaprMachineState *spapr, target_ulong args, uint32_t nret, target_ulong rets) { + int i; if (nargs != 4 || nret != 1) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; } + + for (i = 0; i < EVENT_CLASS_MAX; i++) { + if (rtas_event_log_contains(EVENT_CLASS_MASK(i))) { + const SpaprEventSource *source = + spapr_event_sources_get_source(spapr->event_sources, i); + + g_assert(source->enabled); + qemu_irq_pulse(spapr_qirq(spapr, source->irq)); + } + } + rtas_st(rets, 0, RTAS_OUT_NO_ERRORS_FOUND); } diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 0f54988f2e28d56b8e855b867d92e5214ffee3d1..1d8e8e6a888f015a0e9eabd3ec8f23d448eed498 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -360,7 +360,7 @@ static void *hpt_prepare_thread(void *opaque) SpaprPendingHpt *pending = opaque; size_t size = 1ULL << pending->shift; - pending->hpt = qemu_memalign(size, size); + pending->hpt = qemu_try_memalign(size, size); if (pending->hpt) { memset(pending->hpt, 0, size); pending->ret = H_SUCCESS; @@ -1590,12 +1590,11 @@ static target_ulong h_signal_sys_reset(PowerPCCPU *cpu, } } -static uint32_t cas_check_pvr(SpaprMachineState *spapr, PowerPCCPU *cpu, - target_ulong *addr, bool *raw_mode_supported, - Error **errp) +/* Returns either a logical PVR or zero if none was found */ +static uint32_t cas_check_pvr(PowerPCCPU *cpu, uint32_t max_compat, + target_ulong *addr, bool *raw_mode_supported) { bool explicit_match = false; /* Matched the CPU's real PVR */ - uint32_t max_compat = spapr->max_compat_pvr; uint32_t best_compat = 0; int i; @@ -1624,14 +1623,6 @@ static uint32_t cas_check_pvr(SpaprMachineState *spapr, PowerPCCPU *cpu, } } - if ((best_compat == 0) && (!explicit_match || max_compat)) { - /* We couldn't find a suitable compatibility mode, and either - * the guest doesn't support "raw" mode for this CPU, or raw - * mode is disabled because a maximum compat mode is set */ - error_setg(errp, "Couldn't negotiate a suitable PVR during CAS"); - return 0; - } - *raw_mode_supported = explicit_match; /* Parsing finished */ @@ -1655,7 +1646,8 @@ static void spapr_handle_transient_dev_before_cas(SpaprMachineState *spapr) continue; } drc = SPAPR_DR_CONNECTOR(object_property_get_link(drc_container, - prop->name, NULL)); + prop->name, + &error_abort)); if (spapr_drc_transient(drc)) { spapr_drc_reset(drc); @@ -1674,11 +1666,11 @@ target_ulong do_client_architecture_support(PowerPCCPU *cpu, uint32_t cas_pvr; SpaprOptionVector *ov1_guest, *ov5_guest; bool guest_radix; - Error *local_err = NULL; bool raw_mode_supported = false; bool guest_xive; CPUState *cs; void *fdt; + uint32_t max_compat = spapr->max_compat_pvr; /* CAS is supposed to be called early when only the boot vCPU is active. */ CPU_FOREACH(cs) { @@ -1691,16 +1683,22 @@ target_ulong do_client_architecture_support(PowerPCCPU *cpu, } } - cas_pvr = cas_check_pvr(spapr, cpu, &vec, &raw_mode_supported, &local_err); - if (local_err) { - error_report_err(local_err); + cas_pvr = cas_check_pvr(cpu, max_compat, &vec, &raw_mode_supported); + if (!cas_pvr && (!raw_mode_supported || max_compat)) { + /* + * We couldn't find a suitable compatibility mode, and either + * the guest doesn't support "raw" mode for this CPU, or "raw" + * mode is disabled because a maximum compat mode is set. + */ + error_report("Couldn't negotiate a suitable PVR during CAS"); return H_HARDWARE; } /* Update CPUs */ if (cpu->compat_pvr != cas_pvr) { - ppc_set_compat_all(cas_pvr, &local_err); - if (local_err) { + Error *local_err = NULL; + + if (ppc_set_compat_all(cas_pvr, &local_err) < 0) { /* We fail to set compat mode (likely because running with KVM PR), * but maybe we can fallback to raw mode if the guest supports it. */ @@ -1709,7 +1707,6 @@ target_ulong do_client_architecture_support(PowerPCCPU *cpu, return H_HARDWARE; } error_free(local_err); - local_err = NULL; } } @@ -1872,42 +1869,6 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, return ret; } -static target_ulong h_home_node_associativity(PowerPCCPU *cpu, - SpaprMachineState *spapr, - target_ulong opcode, - target_ulong *args) -{ - target_ulong flags = args[0]; - target_ulong procno = args[1]; - PowerPCCPU *tcpu; - int idx; - - /* only support procno from H_REGISTER_VPA */ - if (flags != 0x1) { - return H_FUNCTION; - } - - tcpu = spapr_find_cpu(procno); - if (tcpu == NULL) { - return H_P2; - } - - /* sequence is the same as in the "ibm,associativity" property */ - - idx = 0; -#define ASSOCIATIVITY(a, b) (((uint64_t)(a) << 32) | \ - ((uint64_t)(b) & 0xffffffff)) - args[idx++] = ASSOCIATIVITY(0, 0); - args[idx++] = ASSOCIATIVITY(0, tcpu->node_id); - args[idx++] = ASSOCIATIVITY(procno, -1); - for ( ; idx < 6; idx++) { - args[idx] = -1; - } -#undef ASSOCIATIVITY - - return H_SUCCESS; -} - static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu, SpaprMachineState *spapr, target_ulong opcode, @@ -2138,10 +2099,6 @@ static void hypercall_register_types(void) spapr_register_hypercall(KVMPPC_H_CAS, h_client_architecture_support); spapr_register_hypercall(KVMPPC_H_UPDATE_DT, h_update_dt); - - /* Virtual Processor Home Node */ - spapr_register_hypercall(H_HOME_NODE_ASSOCIATIVITY, - h_home_node_associativity); } type_init(hypercall_register_types) diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index 7e1d6d59acd8e04b3c695b203636467ffbca04ef..0790239ba5c867ab1a9b1dc0b4680c0fdacacc27 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -369,7 +369,7 @@ SpaprTceTable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn) g_free(tmp); object_unref(OBJECT(tcet)); - object_property_set_bool(OBJECT(tcet), true, "realized", NULL); + qdev_realize(DEVICE(tcet), NULL, NULL); return tcet; } diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c index 0c594aa72e15d827f7487eee6e61806a4e9806a5..f59960339ec3cb379f6978eb1ae30cc608bc88b9 100644 --- a/hw/ppc/spapr_irq.c +++ b/hw/ppc/spapr_irq.c @@ -139,6 +139,7 @@ SpaprIrq spapr_irq_dual = { static int spapr_irq_check(SpaprMachineState *spapr, Error **errp) { + ERRP_GUARD(); MachineState *machine = MACHINE(spapr); /* @@ -171,7 +172,7 @@ static int spapr_irq_check(SpaprMachineState *spapr, Error **errp) * To cover both and not confuse the OS, add an early failure in * QEMU. */ - if (spapr->irq == &spapr_irq_xive) { + if (!spapr->irq->xics) { error_setg(errp, "XIVE-only machines require a POWER9 CPU"); return -1; } @@ -179,14 +180,19 @@ static int spapr_irq_check(SpaprMachineState *spapr, Error **errp) /* * On a POWER9 host, some older KVM XICS devices cannot be destroyed and - * re-created. Detect that early to avoid QEMU to exit later when the - * guest reboots. + * re-created. Same happens with KVM nested guests. Detect that early to + * avoid QEMU to exit later when the guest reboots. */ if (kvm_enabled() && spapr->irq == &spapr_irq_dual && kvm_kernel_irqchip_required() && xics_kvm_has_broken_disconnect(spapr)) { - error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on"); + error_setg(errp, + "KVM is incompatible with ic-mode=dual,kernel-irqchip=on"); + error_append_hint(errp, + "This can happen with an old KVM or in a KVM nested guest.\n"); + error_append_hint(errp, + "Try without kernel-irqchip or with kernel-irqchip=off.\n"); return -1; } @@ -302,18 +308,15 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp) spapr_irq_msi_init(spapr); if (spapr->irq->xics) { - Error *local_err = NULL; Object *obj; obj = object_new(TYPE_ICS_SPAPR); object_property_add_child(OBJECT(spapr), "ics", obj); - object_property_set_link(obj, OBJECT(spapr), ICS_PROP_XICS, + object_property_set_link(obj, ICS_PROP_XICS, OBJECT(spapr), &error_abort); - object_property_set_int(obj, smc->nr_xirqs, "nr-irqs", &error_abort); - object_property_set_bool(obj, true, "realized", &local_err); - if (local_err) { - error_propagate(errp, local_err); + object_property_set_int(obj, "nr-irqs", smc->nr_xirqs, &error_abort); + if (!qdev_realize(DEVICE(obj), NULL, errp)) { return; } @@ -325,16 +328,16 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp) DeviceState *dev; int i; - dev = qdev_create(NULL, TYPE_SPAPR_XIVE); + dev = qdev_new(TYPE_SPAPR_XIVE); qdev_prop_set_uint32(dev, "nr-irqs", smc->nr_xirqs + SPAPR_XIRQ_BASE); /* * 8 XIVE END structures per CPU. One for each available * priority */ qdev_prop_set_uint32(dev, "nr-ends", nr_servers << 3); - object_property_set_link(OBJECT(dev), OBJECT(spapr), "xive-fabric", + object_property_set_link(OBJECT(dev), "xive-fabric", OBJECT(spapr), &error_abort); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); spapr->xive = SPAPR_XIVE(dev); diff --git a/hw/ppc/spapr_numa.c b/hw/ppc/spapr_numa.c new file mode 100644 index 0000000000000000000000000000000000000000..b50796bbe30eb6519b7668209a34784f3887d2b7 --- /dev/null +++ b/hw/ppc/spapr_numa.c @@ -0,0 +1,411 @@ +/* + * QEMU PowerPC pSeries Logical Partition NUMA associativity handling + * + * Copyright IBM Corp. 2020 + * + * Authors: + * Daniel Henrique Barboza + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "hw/ppc/spapr_numa.h" +#include "hw/pci-host/spapr.h" +#include "hw/ppc/fdt.h" + +/* Moved from hw/ppc/spapr_pci_nvlink2.c */ +#define SPAPR_GPU_NUMA_ID (cpu_to_be32(1)) + +static bool spapr_numa_is_symmetrical(MachineState *ms) +{ + int src, dst; + int nb_numa_nodes = ms->numa_state->num_nodes; + NodeInfo *numa_info = ms->numa_state->nodes; + + for (src = 0; src < nb_numa_nodes; src++) { + for (dst = src; dst < nb_numa_nodes; dst++) { + if (numa_info[src].distance[dst] != + numa_info[dst].distance[src]) { + return false; + } + } + } + + return true; +} + +/* + * This function will translate the user distances into + * what the kernel understand as possible values: 10 + * (local distance), 20, 40, 80 and 160, and return the equivalent + * NUMA level for each. Current heuristic is: + * - local distance (10) returns numa_level = 0x4, meaning there is + * no rounding for local distance + * - distances between 11 and 30 inclusive -> rounded to 20, + * numa_level = 0x3 + * - distances between 31 and 60 inclusive -> rounded to 40, + * numa_level = 0x2 + * - distances between 61 and 120 inclusive -> rounded to 80, + * numa_level = 0x1 + * - everything above 120 returns numa_level = 0 to indicate that + * there is no match. This will be calculated as disntace = 160 + * by the kernel (as of v5.9) + */ +static uint8_t spapr_numa_get_numa_level(uint8_t distance) +{ + if (distance == 10) { + return 0x4; + } else if (distance > 11 && distance <= 30) { + return 0x3; + } else if (distance > 31 && distance <= 60) { + return 0x2; + } else if (distance > 61 && distance <= 120) { + return 0x1; + } + + return 0; +} + +static void spapr_numa_define_associativity_domains(SpaprMachineState *spapr) +{ + MachineState *ms = MACHINE(spapr); + NodeInfo *numa_info = ms->numa_state->nodes; + int nb_numa_nodes = ms->numa_state->num_nodes; + int src, dst, i; + + for (src = 0; src < nb_numa_nodes; src++) { + for (dst = src; dst < nb_numa_nodes; dst++) { + /* + * This is how the associativity domain between A and B + * is calculated: + * + * - get the distance D between them + * - get the correspondent NUMA level 'n_level' for D + * - all associativity arrays were initialized with their own + * numa_ids, and we're calculating the distance in node_id + * ascending order, starting from node id 0 (the first node + * retrieved by numa_state). This will have a cascade effect in + * the algorithm because the associativity domains that node 0 + * defines will be carried over to other nodes, and node 1 + * associativities will be carried over after taking node 0 + * associativities into account, and so on. This happens because + * we'll assign assoc_src as the associativity domain of dst + * as well, for all NUMA levels beyond and including n_level. + * + * The PPC kernel expects the associativity domains of node 0 to + * be always 0, and this algorithm will grant that by default. + */ + uint8_t distance = numa_info[src].distance[dst]; + uint8_t n_level = spapr_numa_get_numa_level(distance); + uint32_t assoc_src; + + /* + * n_level = 0 means that the distance is greater than our last + * rounded value (120). In this case there is no NUMA level match + * between src and dst and we can skip the remaining of the loop. + * + * The Linux kernel will assume that the distance between src and + * dst, in this case of no match, is 10 (local distance) doubled + * for each NUMA it didn't match. We have MAX_DISTANCE_REF_POINTS + * levels (4), so this gives us 10*2*2*2*2 = 160. + * + * This logic can be seen in the Linux kernel source code, as of + * v5.9, in arch/powerpc/mm/numa.c, function __node_distance(). + */ + if (n_level == 0) { + continue; + } + + /* + * We must assign all assoc_src to dst, starting from n_level + * and going up to 0x1. + */ + for (i = n_level; i > 0; i--) { + assoc_src = spapr->numa_assoc_array[src][i]; + spapr->numa_assoc_array[dst][i] = assoc_src; + } + } + } + +} + +void spapr_numa_associativity_init(SpaprMachineState *spapr, + MachineState *machine) +{ + SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); + int nb_numa_nodes = machine->numa_state->num_nodes; + int i, j, max_nodes_with_gpus; + bool using_legacy_numa = spapr_machine_using_legacy_numa(spapr); + + /* + * For all associativity arrays: first position is the size, + * position MAX_DISTANCE_REF_POINTS is always the numa_id, + * represented by the index 'i'. + * + * This will break on sparse NUMA setups, when/if QEMU starts + * to support it, because there will be no more guarantee that + * 'i' will be a valid node_id set by the user. + */ + for (i = 0; i < nb_numa_nodes; i++) { + spapr->numa_assoc_array[i][0] = cpu_to_be32(MAX_DISTANCE_REF_POINTS); + spapr->numa_assoc_array[i][MAX_DISTANCE_REF_POINTS] = cpu_to_be32(i); + + /* + * Fill all associativity domains of non-zero NUMA nodes with + * node_id. This is required because the default value (0) is + * considered a match with associativity domains of node 0. + */ + if (!using_legacy_numa && i != 0) { + for (j = 1; j < MAX_DISTANCE_REF_POINTS; j++) { + spapr->numa_assoc_array[i][j] = cpu_to_be32(i); + } + } + } + + /* + * Initialize NVLink GPU associativity arrays. We know that + * the first GPU will take the first available NUMA id, and + * we'll have a maximum of NVGPU_MAX_NUM GPUs in the machine. + * At this point we're not sure if there are GPUs or not, but + * let's initialize the associativity arrays and allow NVLink + * GPUs to be handled like regular NUMA nodes later on. + */ + max_nodes_with_gpus = nb_numa_nodes + NVGPU_MAX_NUM; + + for (i = nb_numa_nodes; i < max_nodes_with_gpus; i++) { + spapr->numa_assoc_array[i][0] = cpu_to_be32(MAX_DISTANCE_REF_POINTS); + + for (j = 1; j < MAX_DISTANCE_REF_POINTS; j++) { + uint32_t gpu_assoc = smc->pre_5_1_assoc_refpoints ? + SPAPR_GPU_NUMA_ID : cpu_to_be32(i); + spapr->numa_assoc_array[i][j] = gpu_assoc; + } + + spapr->numa_assoc_array[i][MAX_DISTANCE_REF_POINTS] = cpu_to_be32(i); + } + + /* + * Legacy NUMA guests (pseries-5.1 and older, or guests with only + * 1 NUMA node) will not benefit from anything we're going to do + * after this point. + */ + if (using_legacy_numa) { + return; + } + + if (!spapr_numa_is_symmetrical(machine)) { + error_report("Asymmetrical NUMA topologies aren't supported " + "in the pSeries machine"); + exit(EXIT_FAILURE); + } + + spapr_numa_define_associativity_domains(spapr); +} + +void spapr_numa_write_associativity_dt(SpaprMachineState *spapr, void *fdt, + int offset, int nodeid) +{ + _FDT((fdt_setprop(fdt, offset, "ibm,associativity", + spapr->numa_assoc_array[nodeid], + sizeof(spapr->numa_assoc_array[nodeid])))); +} + +static uint32_t *spapr_numa_get_vcpu_assoc(SpaprMachineState *spapr, + PowerPCCPU *cpu) +{ + uint32_t *vcpu_assoc = g_new(uint32_t, VCPU_ASSOC_SIZE); + int index = spapr_get_vcpu_id(cpu); + + /* + * VCPUs have an extra 'cpu_id' value in ibm,associativity + * compared to other resources. Increment the size at index + * 0, put cpu_id last, then copy the remaining associativity + * domains. + */ + vcpu_assoc[0] = cpu_to_be32(MAX_DISTANCE_REF_POINTS + 1); + vcpu_assoc[VCPU_ASSOC_SIZE - 1] = cpu_to_be32(index); + memcpy(vcpu_assoc + 1, spapr->numa_assoc_array[cpu->node_id] + 1, + (VCPU_ASSOC_SIZE - 2) * sizeof(uint32_t)); + + return vcpu_assoc; +} + +int spapr_numa_fixup_cpu_dt(SpaprMachineState *spapr, void *fdt, + int offset, PowerPCCPU *cpu) +{ + g_autofree uint32_t *vcpu_assoc = NULL; + + vcpu_assoc = spapr_numa_get_vcpu_assoc(spapr, cpu); + + /* Advertise NUMA via ibm,associativity */ + return fdt_setprop(fdt, offset, "ibm,associativity", vcpu_assoc, + VCPU_ASSOC_SIZE * sizeof(uint32_t)); +} + + +int spapr_numa_write_assoc_lookup_arrays(SpaprMachineState *spapr, void *fdt, + int offset) +{ + MachineState *machine = MACHINE(spapr); + int nb_numa_nodes = machine->numa_state->num_nodes; + int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; + uint32_t *int_buf, *cur_index, buf_len; + int ret, i; + + /* ibm,associativity-lookup-arrays */ + buf_len = (nr_nodes * MAX_DISTANCE_REF_POINTS + 2) * sizeof(uint32_t); + cur_index = int_buf = g_malloc0(buf_len); + int_buf[0] = cpu_to_be32(nr_nodes); + /* Number of entries per associativity list */ + int_buf[1] = cpu_to_be32(MAX_DISTANCE_REF_POINTS); + cur_index += 2; + for (i = 0; i < nr_nodes; i++) { + /* + * For the lookup-array we use the ibm,associativity array, + * from numa_assoc_array. without the first element (size). + */ + uint32_t *associativity = spapr->numa_assoc_array[i]; + memcpy(cur_index, ++associativity, + sizeof(uint32_t) * MAX_DISTANCE_REF_POINTS); + cur_index += MAX_DISTANCE_REF_POINTS; + } + ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf, + (cur_index - int_buf) * sizeof(uint32_t)); + g_free(int_buf); + + return ret; +} + +/* + * Helper that writes ibm,associativity-reference-points and + * max-associativity-domains in the RTAS pointed by @rtas + * in the DT @fdt. + */ +void spapr_numa_write_rtas_dt(SpaprMachineState *spapr, void *fdt, int rtas) +{ + MachineState *ms = MACHINE(spapr); + SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); + uint32_t refpoints[] = { + cpu_to_be32(0x4), + cpu_to_be32(0x3), + cpu_to_be32(0x2), + cpu_to_be32(0x1), + }; + uint32_t nr_refpoints = ARRAY_SIZE(refpoints); + uint32_t maxdomain = ms->numa_state->num_nodes + spapr->gpu_numa_id; + uint32_t maxdomains[] = { + cpu_to_be32(4), + cpu_to_be32(maxdomain), + cpu_to_be32(maxdomain), + cpu_to_be32(maxdomain), + cpu_to_be32(maxdomain) + }; + + if (spapr_machine_using_legacy_numa(spapr)) { + uint32_t legacy_refpoints[] = { + cpu_to_be32(0x4), + cpu_to_be32(0x4), + cpu_to_be32(0x2), + }; + uint32_t legacy_maxdomain = spapr->gpu_numa_id > 1 ? 1 : 0; + uint32_t legacy_maxdomains[] = { + cpu_to_be32(4), + cpu_to_be32(legacy_maxdomain), + cpu_to_be32(legacy_maxdomain), + cpu_to_be32(legacy_maxdomain), + cpu_to_be32(spapr->gpu_numa_id), + }; + + G_STATIC_ASSERT(sizeof(legacy_refpoints) <= sizeof(refpoints)); + G_STATIC_ASSERT(sizeof(legacy_maxdomains) <= sizeof(maxdomains)); + + nr_refpoints = 3; + + memcpy(refpoints, legacy_refpoints, sizeof(legacy_refpoints)); + memcpy(maxdomains, legacy_maxdomains, sizeof(legacy_maxdomains)); + + /* pseries-5.0 and older reference-points array is {0x4, 0x4} */ + if (smc->pre_5_1_assoc_refpoints) { + nr_refpoints = 2; + } + } + + _FDT(fdt_setprop(fdt, rtas, "ibm,associativity-reference-points", + refpoints, nr_refpoints * sizeof(refpoints[0]))); + + _FDT(fdt_setprop(fdt, rtas, "ibm,max-associativity-domains", + maxdomains, sizeof(maxdomains))); +} + +static target_ulong h_home_node_associativity(PowerPCCPU *cpu, + SpaprMachineState *spapr, + target_ulong opcode, + target_ulong *args) +{ + g_autofree uint32_t *vcpu_assoc = NULL; + target_ulong flags = args[0]; + target_ulong procno = args[1]; + PowerPCCPU *tcpu; + int idx, assoc_idx; + + /* only support procno from H_REGISTER_VPA */ + if (flags != 0x1) { + return H_FUNCTION; + } + + tcpu = spapr_find_cpu(procno); + if (tcpu == NULL) { + return H_P2; + } + + /* + * Given that we want to be flexible with the sizes and indexes, + * we must consider that there is a hard limit of how many + * associativities domain we can fit in R4 up to R9, which would be + * 12 associativity domains for vcpus. Assert and bail if that's + * not the case. + */ + G_STATIC_ASSERT((VCPU_ASSOC_SIZE - 1) <= 12); + + vcpu_assoc = spapr_numa_get_vcpu_assoc(spapr, tcpu); + /* assoc_idx starts at 1 to skip associativity size */ + assoc_idx = 1; + +#define ASSOCIATIVITY(a, b) (((uint64_t)(a) << 32) | \ + ((uint64_t)(b) & 0xffffffff)) + + for (idx = 0; idx < 6; idx++) { + int32_t a, b; + + /* + * vcpu_assoc[] will contain the associativity domains for tcpu, + * including tcpu->node_id and procno, meaning that we don't + * need to use these variables here. + * + * We'll read 2 values at a time to fill up the ASSOCIATIVITY() + * macro. The ternary will fill the remaining registers with -1 + * after we went through vcpu_assoc[]. + */ + a = assoc_idx < VCPU_ASSOC_SIZE ? + be32_to_cpu(vcpu_assoc[assoc_idx++]) : -1; + b = assoc_idx < VCPU_ASSOC_SIZE ? + be32_to_cpu(vcpu_assoc[assoc_idx++]) : -1; + + args[idx] = ASSOCIATIVITY(a, b); + } +#undef ASSOCIATIVITY + + return H_SUCCESS; +} + +static void spapr_numa_register_types(void) +{ + /* Virtual Processor Home Node */ + spapr_register_hypercall(H_HOME_NODE_ASSOCIATIVITY, + h_home_node_associativity); +} + +type_init(spapr_numa_register_types) diff --git a/hw/ppc/spapr_nvdimm.c b/hw/ppc/spapr_nvdimm.c index 81410aa63fe924fba0d8fd5214fc683489add842..a833a63b5ed346108128406175f659509459d196 100644 --- a/hw/ppc/spapr_nvdimm.c +++ b/hw/ppc/spapr_nvdimm.c @@ -27,85 +27,88 @@ #include "hw/ppc/spapr_nvdimm.h" #include "hw/mem/nvdimm.h" #include "qemu/nvdimm-utils.h" +#include "qemu/option.h" #include "hw/ppc/fdt.h" #include "qemu/range.h" +#include "sysemu/sysemu.h" +#include "hw/ppc/spapr_numa.h" -void spapr_nvdimm_validate_opts(NVDIMMDevice *nvdimm, uint64_t size, - Error **errp) +bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm, + uint64_t size, Error **errp) { - char *uuidstr = NULL; + const MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); + const MachineState *ms = MACHINE(hotplug_dev); + const char *nvdimm_opt = qemu_opt_get(qemu_get_machine_opts(), "nvdimm"); + g_autofree char *uuidstr = NULL; QemuUUID uuid; int ret; + if (!mc->nvdimm_supported) { + error_setg(errp, "NVDIMM hotplug not supported for this machine"); + return false; + } + + /* + * NVDIMM support went live in 5.1 without considering that, in + * other archs, the user needs to enable NVDIMM support with the + * 'nvdimm' machine option and the default behavior is NVDIMM + * support disabled. It is too late to roll back to the standard + * behavior without breaking 5.1 guests. What we can do is to + * ensure that, if the user sets nvdimm=off, we error out + * regardless of being 5.1 or newer. + */ + if (!ms->nvdimms_state->is_enabled && nvdimm_opt) { + error_setg(errp, "nvdimm device found but 'nvdimm=off' was set"); + return false; + } + if (object_property_get_int(OBJECT(nvdimm), NVDIMM_LABEL_SIZE_PROP, &error_abort) == 0) { error_setg(errp, "PAPR requires NVDIMM devices to have label-size set"); - return; + return false; } if (size % SPAPR_MINIMUM_SCM_BLOCK_SIZE) { error_setg(errp, "PAPR requires NVDIMM memory size (excluding label)" " to be a multiple of %" PRIu64 "MB", SPAPR_MINIMUM_SCM_BLOCK_SIZE / MiB); - return; + return false; } uuidstr = object_property_get_str(OBJECT(nvdimm), NVDIMM_UUID_PROP, &error_abort); ret = qemu_uuid_parse(uuidstr, &uuid); g_assert(!ret); - g_free(uuidstr); if (qemu_uuid_is_null(&uuid)) { error_setg(errp, "NVDIMM device requires the uuid to be set"); - return; + return false; } + + return true; } -void spapr_add_nvdimm(DeviceState *dev, uint64_t slot, Error **errp) +bool spapr_add_nvdimm(DeviceState *dev, uint64_t slot, Error **errp) { SpaprDrc *drc; bool hotplugged = spapr_drc_hotplugged(dev); - Error *local_err = NULL; drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PMEM, slot); g_assert(drc); - spapr_drc_attach(drc, dev, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; + if (!spapr_drc_attach(drc, dev, errp)) { + return false; } if (hotplugged) { spapr_hotplug_req_add_by_index(drc); } + return true; } -int spapr_pmem_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, - void *fdt, int *fdt_start_offset, Error **errp) -{ - NVDIMMDevice *nvdimm = NVDIMM(drc->dev); - - *fdt_start_offset = spapr_dt_nvdimm(fdt, 0, nvdimm); - - return 0; -} - -void spapr_create_nvdimm_dr_connectors(SpaprMachineState *spapr) -{ - MachineState *machine = MACHINE(spapr); - int i; - - for (i = 0; i < machine->ram_slots; i++) { - spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_PMEM, i); - } -} - - -int spapr_dt_nvdimm(void *fdt, int parent_offset, - NVDIMMDevice *nvdimm) +static int spapr_dt_nvdimm(SpaprMachineState *spapr, void *fdt, + int parent_offset, NVDIMMDevice *nvdimm) { int child_offset; char *buf; @@ -115,11 +118,6 @@ int spapr_dt_nvdimm(void *fdt, int parent_offset, &error_abort); uint64_t slot = object_property_get_uint(OBJECT(nvdimm), PC_DIMM_SLOT_PROP, &error_abort); - uint32_t associativity[] = { - cpu_to_be32(0x4), /* length */ - cpu_to_be32(0x0), cpu_to_be32(0x0), - cpu_to_be32(0x0), cpu_to_be32(node) - }; uint64_t lsize = nvdimm->label_size; uint64_t size = object_property_get_int(OBJECT(nvdimm), PC_DIMM_SIZE_PROP, NULL); @@ -139,8 +137,7 @@ int spapr_dt_nvdimm(void *fdt, int parent_offset, _FDT((fdt_setprop_string(fdt, child_offset, "compatible", "ibm,pmemory"))); _FDT((fdt_setprop_string(fdt, child_offset, "device_type", "ibm,pmemory"))); - _FDT((fdt_setprop(fdt, child_offset, "ibm,associativity", associativity, - sizeof(associativity)))); + spapr_numa_write_associativity_dt(spapr, fdt, child_offset, node); buf = qemu_uuid_unparse_strdup(&nvdimm->uuid); _FDT((fdt_setprop_string(fdt, child_offset, "ibm,unit-guid", buf))); @@ -161,7 +158,17 @@ int spapr_dt_nvdimm(void *fdt, int parent_offset, return child_offset; } -void spapr_dt_persistent_memory(void *fdt) +int spapr_pmem_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, + void *fdt, int *fdt_start_offset, Error **errp) +{ + NVDIMMDevice *nvdimm = NVDIMM(drc->dev); + + *fdt_start_offset = spapr_dt_nvdimm(spapr, fdt, 0, nvdimm); + + return 0; +} + +void spapr_dt_persistent_memory(SpaprMachineState *spapr, void *fdt) { int offset = fdt_subnode_offset(fdt, 0, "persistent-memory"); GSList *iter, *nvdimms = nvdimm_get_device_list(); @@ -179,7 +186,7 @@ void spapr_dt_persistent_memory(void *fdt) for (iter = nvdimms; iter; iter = iter->next) { NVDIMMDevice *nvdimm = iter->data; - spapr_dt_nvdimm(fdt, offset, nvdimm); + spapr_dt_nvdimm(spapr, fdt, offset, nvdimm); } g_slist_free(nvdimms); diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 83f14530969edd047bcb7b84546ede061587c2c5..88ce87f130a51048731cc3a12fbb98c5fd94a77a 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -52,6 +52,7 @@ #include "sysemu/kvm.h" #include "sysemu/hostmem.h" #include "sysemu/numa.h" +#include "hw/ppc/spapr_numa.h" /* Copied from the kernel arch/powerpc/platforms/pseries/msi.c */ #define RTAS_QUERY_FN 0 @@ -1480,6 +1481,57 @@ static void spapr_pci_bridge_plug(SpaprPhbState *phb, add_drcs(phb, bus); } +/* Returns non-zero if the value of "chassis_nr" is already in use */ +static int check_chassis_nr(Object *obj, void *opaque) +{ + int new_chassis_nr = + object_property_get_uint(opaque, "chassis_nr", &error_abort); + int chassis_nr = + object_property_get_uint(obj, "chassis_nr", NULL); + + if (!object_dynamic_cast(obj, TYPE_PCI_BRIDGE)) { + return 0; + } + + /* Skip unsupported bridge types */ + if (!chassis_nr) { + return 0; + } + + /* Skip self */ + if (obj == opaque) { + return 0; + } + + return chassis_nr == new_chassis_nr; +} + +static bool bridge_has_valid_chassis_nr(Object *bridge, Error **errp) +{ + int chassis_nr = + object_property_get_uint(bridge, "chassis_nr", NULL); + + /* + * slotid_cap_init() already ensures that "chassis_nr" isn't null for + * standard PCI bridges, so this really tells if "chassis_nr" is present + * or not. + */ + if (!chassis_nr) { + error_setg(errp, "PCI Bridge lacks a \"chassis_nr\" property"); + error_append_hint(errp, "Try -device pci-bridge instead.\n"); + return false; + } + + /* We want unique values for "chassis_nr" */ + if (object_child_foreach_recursive(object_get_root(), check_chassis_nr, + bridge)) { + error_setg(errp, "Bridge chassis %d already in use", chassis_nr); + return false; + } + + return true; +} + static void spapr_pci_plug(HotplugHandler *plug_handler, DeviceState *plugged_dev, Error **errp) { @@ -1487,7 +1539,6 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, PCIDevice *pdev = PCI_DEVICE(plugged_dev); PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(plugged_dev); SpaprDrc *drc = drc_from_dev(phb, pdev); - Error *local_err = NULL; PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(pdev))); uint32_t slotnr = PCI_SLOT(pdev->devfn); @@ -1499,15 +1550,18 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, * we need to let them know it's not enabled */ if (plugged_dev->hotplugged) { - error_setg(&local_err, QERR_BUS_NO_HOTPLUG, + error_setg(errp, QERR_BUS_NO_HOTPLUG, object_get_typename(OBJECT(phb))); } - goto out; + return; } g_assert(drc); if (pc->is_bridge) { + if (!bridge_has_valid_chassis_nr(OBJECT(plugged_dev), errp)) { + return; + } spapr_pci_bridge_plug(phb, PCI_BRIDGE(plugged_dev)); } @@ -1517,15 +1571,14 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, */ if (plugged_dev->hotplugged && bus->devices[PCI_DEVFN(slotnr, 0)] && PCI_FUNC(pdev->devfn) != 0) { - error_setg(&local_err, "PCI: slot %d function 0 already ocuppied by %s," + error_setg(errp, "PCI: slot %d function 0 already occupied by %s," " additional functions can no longer be exposed to guest.", slotnr, bus->devices[PCI_DEVFN(slotnr, 0)]->name); - goto out; + return; } - spapr_drc_attach(drc, DEVICE(pdev), &local_err); - if (local_err) { - goto out; + if (!spapr_drc_attach(drc, DEVICE(pdev), errp)) { + return; } /* If this is function 0, signal hotplug for all the device functions. @@ -1551,9 +1604,6 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, } } } - -out: - error_propagate(errp, local_err); } static void spapr_pci_bridge_unplug(SpaprPhbState *phb, @@ -1587,8 +1637,7 @@ static void spapr_pci_unplug(HotplugHandler *plug_handler, return; } - object_property_set_bool(OBJECT(plugged_dev), false, "realized", - &error_abort); + qdev_unrealize(plugged_dev); } static void spapr_pci_unplug_request(HotplugHandler *plug_handler, @@ -1720,7 +1769,7 @@ static void spapr_phb_unrealize(DeviceState *dev) address_space_remove_listeners(&sphb->iommu_as); address_space_destroy(&sphb->iommu_as); - qbus_set_hotplug_handler(BUS(phb->bus), NULL, &error_abort); + qbus_set_hotplug_handler(BUS(phb->bus), NULL); pci_unregister_root_bus(phb->bus); memory_region_del_subregion(get_system_memory(), &sphb->iowindow); @@ -1745,6 +1794,7 @@ static void spapr_phb_destroy_msi(gpointer opaque) static void spapr_phb_realize(DeviceState *dev, Error **errp) { + ERRP_GUARD(); /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user * tries to add a sPAPR PHB to a non-pseries machine. */ @@ -1762,7 +1812,6 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) uint64_t msi_window_size = 4096; SpaprTceTable *tcet; const unsigned windows_supported = spapr_phb_windows_supported(sphb); - Error *local_err = NULL; if (!spapr) { error_setg(errp, TYPE_SPAPR_PCI_HOST_BRIDGE " needs a pseries machine"); @@ -1869,7 +1918,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; } phb->bus = bus; - qbus_set_hotplug_handler(BUS(phb->bus), OBJECT(sphb), NULL); + qbus_set_hotplug_handler(BUS(phb->bus), OBJECT(sphb)); /* * Initialize PHB address space. @@ -1913,13 +1962,12 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) /* Initialize the LSI table */ for (i = 0; i < PCI_NUM_PINS; i++) { - uint32_t irq = SPAPR_IRQ_PCI_LSI + sphb->index * PCI_NUM_PINS + i; + int irq = SPAPR_IRQ_PCI_LSI + sphb->index * PCI_NUM_PINS + i; if (smc->legacy_irq_allocation) { - irq = spapr_irq_findone(spapr, &local_err); - if (local_err) { - error_propagate_prepend(errp, local_err, - "can't allocate LSIs: "); + irq = spapr_irq_findone(spapr, errp); + if (irq < 0) { + error_prepend(errp, "can't allocate LSIs: "); /* * Older machines will never support PHB hotplug, ie, this is an * init only path and QEMU will terminate. No need to rollback. @@ -1928,9 +1976,8 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) } } - spapr_irq_claim(spapr, irq, true, &local_err); - if (local_err) { - error_propagate_prepend(errp, local_err, "can't allocate LSIs: "); + if (spapr_irq_claim(spapr, irq, true, errp) < 0) { + error_prepend(errp, "can't allocate LSIs: "); goto unrealize; } @@ -2038,6 +2085,8 @@ static Property spapr_phb_properties[] = { pcie_ecs, true), DEFINE_PROP_UINT64("gpa", SpaprPhbState, nv2_gpa_win_addr, 0), DEFINE_PROP_UINT64("atsd", SpaprPhbState, nv2_atsd_win_addr, 0), + DEFINE_PROP_BOOL("pre-5.1-associativity", SpaprPhbState, + pre_5_1_assoc, false), DEFINE_PROP_END_OF_LIST(), }; @@ -2270,11 +2319,6 @@ int spapr_dt_phb(SpaprMachineState *spapr, SpaprPhbState *phb, cpu_to_be32(1), cpu_to_be32(RTAS_IBM_RESET_PE_DMA_WINDOW) }; - uint32_t associativity[] = {cpu_to_be32(0x4), - cpu_to_be32(0x0), - cpu_to_be32(0x0), - cpu_to_be32(0x0), - cpu_to_be32(phb->numa_node)}; SpaprTceTable *tcet; SpaprDrc *drc; Error *err = NULL; @@ -2307,8 +2351,7 @@ int spapr_dt_phb(SpaprMachineState *spapr, SpaprPhbState *phb, /* Advertise NUMA via ibm,associativity */ if (phb->numa_node != -1) { - _FDT(fdt_setprop(fdt, bus_off, "ibm,associativity", associativity, - sizeof(associativity))); + spapr_numa_write_associativity_dt(spapr, fdt, bus_off, phb->numa_node); } /* Build the interrupt-map, this must matches what is done @@ -2418,8 +2461,10 @@ static int spapr_switch_one_vga(DeviceState *dev, void *opaque) bool be = *(bool *)opaque; if (object_dynamic_cast(OBJECT(dev), "VGA") - || object_dynamic_cast(OBJECT(dev), "secondary-vga")) { - object_property_set_bool(OBJECT(dev), be, "big-endian-framebuffer", + || object_dynamic_cast(OBJECT(dev), "secondary-vga") + || object_dynamic_cast(OBJECT(dev), "bochs-display") + || object_dynamic_cast(OBJECT(dev), "virtio-vga")) { + object_property_set_bool(OBJECT(dev), "big-endian-framebuffer", be, &error_abort); } return 0; diff --git a/hw/ppc/spapr_pci_nvlink2.c b/hw/ppc/spapr_pci_nvlink2.c index 8332d5694e462d43a958d173282db7e9e11c27d0..8ef9b40a18dcd040ed932711b38dcfb54d33b27c 100644 --- a/hw/ppc/spapr_pci_nvlink2.c +++ b/hw/ppc/spapr_pci_nvlink2.c @@ -26,6 +26,7 @@ #include "qemu-common.h" #include "hw/pci/pci.h" #include "hw/pci-host/spapr.h" +#include "hw/ppc/spapr_numa.h" #include "qemu/error-report.h" #include "hw/ppc/fdt.h" #include "hw/pci/pci_bridge.h" @@ -37,8 +38,6 @@ #define PHANDLE_NVLINK(phb, gn, nn) (0x00130000 | (((phb)->index) << 8) | \ ((gn) << 4) | (nn)) -#define SPAPR_GPU_NUMA_ID (cpu_to_be32(1)) - typedef struct SpaprPhbPciNvGpuSlot { uint64_t tgt; uint64_t gpa; @@ -358,14 +357,8 @@ void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, void *fdt) for (i = 0; i < sphb->nvgpus->num; ++i) { SpaprPhbPciNvGpuSlot *nvslot = &sphb->nvgpus->slots[i]; Object *nv_mrobj = object_property_get_link(OBJECT(nvslot->gpdev), - "nvlink2-mr[0]", NULL); - uint32_t associativity[] = { - cpu_to_be32(0x4), - SPAPR_GPU_NUMA_ID, - SPAPR_GPU_NUMA_ID, - SPAPR_GPU_NUMA_ID, - cpu_to_be32(nvslot->numa_id) - }; + "nvlink2-mr[0]", + &error_abort); uint64_t size = object_property_get_uint(nv_mrobj, "size", NULL); uint64_t mem_reg[2] = { cpu_to_be64(nvslot->gpa), cpu_to_be64(size) }; char *mem_name = g_strdup_printf("memory@%"PRIx64, nvslot->gpa); @@ -374,8 +367,9 @@ void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, void *fdt) _FDT(off); _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); _FDT((fdt_setprop(fdt, off, "reg", mem_reg, sizeof(mem_reg)))); - _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity, - sizeof(associativity)))); + + spapr_numa_write_associativity_dt(SPAPR_MACHINE(qdev_get_machine()), + fdt, off, nvslot->numa_id); _FDT((fdt_setprop_string(fdt, off, "compatible", "ibm,coherent-device-memory"))); diff --git a/hw/ppc/spapr_rng.c b/hw/ppc/spapr_rng.c index 85bf64d68ec6a02daab4a61fc2cea9484811683b..d14800e9def441df75e9ad0cfcb82d1b3e72adf5 100644 --- a/hw/ppc/spapr_rng.c +++ b/hw/ppc/spapr_rng.c @@ -28,9 +28,9 @@ #include "hw/ppc/spapr.h" #include "hw/qdev-properties.h" #include "kvm_ppc.h" +#include "qom/object.h" -#define SPAPR_RNG(obj) \ - OBJECT_CHECK(SpaprRngState, (obj), TYPE_SPAPR_RNG) +OBJECT_DECLARE_SIMPLE_TYPE(SpaprRngState, SPAPR_RNG) struct SpaprRngState { /*< private >*/ @@ -38,7 +38,6 @@ struct SpaprRngState { RngBackend *backend; bool use_kvm; }; -typedef struct SpaprRngState SpaprRngState; struct HRandomData { QemuSemaphore sem; diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index bcac0d00e7b6b5cf639c65b82cca9bc631824b1b..513c7a84351bcfb31638c7b655e91edc4a6ebb6f 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -438,7 +438,7 @@ static void rtas_ibm_nmi_register(PowerPCCPU *cpu, } if (kvm_enabled()) { - if (kvmppc_set_fwnmi() < 0) { + if (kvmppc_set_fwnmi(cpu) < 0) { rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED); return; } diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c index 0b085eabe4c8eb81bc9f6934b125410e3d150c9c..5d6c56473fca50b88efd241906e6f4748275d3c8 100644 --- a/hw/ppc/spapr_vio.c +++ b/hw/ppc/spapr_vio.c @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -420,7 +420,7 @@ static void spapr_vio_busdev_reset(DeviceState *qdev) } /* - * The register property of a VIO device is defined in livirt using + * The register property of a VIO device is defined in libvirt using * 0x1000 as a base register number plus a 0x1000 increment. For the * VIO tty device, the base number is changed to 0x30000000. QEMU uses * a base register number of 0x71000000 and then a simple increment. @@ -450,7 +450,7 @@ static inline uint32_t spapr_vio_reg_to_irq(uint32_t reg) } else if (reg >= 0x30000000) { /* - * VIO tty devices register values, when allocated by livirt, + * VIO tty devices register values, when allocated by libvirt, * are mapped in range [0xf0 - 0xff], gives us a maximum of 16 * vtys. */ @@ -459,7 +459,7 @@ static inline uint32_t spapr_vio_reg_to_irq(uint32_t reg) } else { /* * Other VIO devices register values, when allocated by - * livirt, should be mapped in range [0x00 - 0xef]. Conflicts + * libvirt, should be mapped in range [0x00 - 0xef]. Conflicts * will be detected when IRQ is claimed. */ irq = (reg >> 12) & 0xff; @@ -474,7 +474,6 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp) SpaprVioDevice *dev = (SpaprVioDevice *)qdev; SpaprVioDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev); char *id; - Error *local_err = NULL; if (dev->reg != -1) { /* @@ -510,16 +509,15 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp) dev->irq = spapr_vio_reg_to_irq(dev->reg); if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { - dev->irq = spapr_irq_findone(spapr, &local_err); - if (local_err) { - error_propagate(errp, local_err); + int irq = spapr_irq_findone(spapr, errp); + + if (irq < 0) { return; } + dev->irq = irq; } - spapr_irq_claim(spapr, dev->irq, false, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (spapr_irq_claim(spapr, dev->irq, false, errp) < 0) { return; } @@ -576,8 +574,8 @@ SpaprVioBus *spapr_vio_bus_init(void) DeviceState *dev; /* Create bridge device */ - dev = qdev_create(NULL, TYPE_SPAPR_VIO_BRIDGE); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_SPAPR_VIO_BRIDGE); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); /* Create bus on bridge device */ qbus = qbus_create(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio"); diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index 9ea620f23c850a44499346b6f80510f46e238365..dcc06d49b5a2bbb0ff2d066d0e8e5713c98aa79f 100644 --- a/hw/ppc/trace-events +++ b/hw/ppc/trace-events @@ -9,11 +9,8 @@ spapr_pci_msi_write(uint64_t addr, uint64_t data, uint32_t dt_irq) "@0x%"PRIx64" spapr_pci_lsi_set(const char *busname, int pin, uint32_t irq) "%s PIN%d IRQ %u" spapr_pci_msi_retry(unsigned config_addr, unsigned req_num, unsigned max_irqs) "Guest device at 0x%x asked %u, have only %u" -# spapr.c -spapr_cas_failed(unsigned long n) "DT diff buffer is too small: %ld bytes" -spapr_cas_continue(unsigned long n) "Copy changes to the guest: %ld bytes" - # spapr_hcall.c +spapr_cas_continue(unsigned long n) "Copy changes to the guest: %ld bytes" spapr_cas_pvr(uint32_t cur_pvr, bool explicit_match, uint32_t new_pvr) "current=0x%x, explicit_match=%u, new=0x%x" spapr_h_resize_hpt_prepare(uint64_t flags, uint64_t shift) "flags=0x%"PRIx64", shift=%"PRIu64 spapr_h_resize_hpt_commit(uint64_t flags, uint64_t shift) "flags=0x%"PRIx64", shift=%"PRIu64 @@ -21,7 +18,7 @@ spapr_update_dt(unsigned cb) "New blob %u bytes" spapr_update_dt_failed_size(unsigned cbold, unsigned cbnew, unsigned magic) "Old blob %u bytes, new blob %u bytes, magic 0x%x" spapr_update_dt_failed_check(unsigned cbold, unsigned cbnew, unsigned magic) "Old blob %u bytes, new blob %u bytes, magic 0x%x" -# spapr_hcall_tpm.c +# spapr_tpm_proxy.c spapr_h_tpm_comm(const char *device_path, uint64_t operation) "tpm_device_path=%s operation=0x%"PRIu64 spapr_tpm_execute(uint64_t data_in, uint64_t data_in_sz, uint64_t data_out, uint64_t data_out_sz) "data_in=0x%"PRIx64", data_in_sz=%"PRIu64", data_out=0x%"PRIx64", data_out_sz=%"PRIu64 @@ -57,7 +54,7 @@ spapr_drc_detach(uint32_t index) "drc: 0x%"PRIx32 spapr_drc_awaiting_quiesce(uint32_t index) "drc: 0x%"PRIx32 spapr_drc_reset(uint32_t index) "drc: 0x%"PRIx32 spapr_drc_realize(uint32_t index) "drc: 0x%"PRIx32 -spapr_drc_realize_child(uint32_t index, char *childname) "drc: 0x%"PRIx32", child name: %s" +spapr_drc_realize_child(uint32_t index, const char *childname) "drc: 0x%"PRIx32", child name: %s" spapr_drc_realize_complete(uint32_t index) "drc: 0x%"PRIx32 spapr_drc_unrealize(uint32_t index) "drc: 0x%"PRIx32 @@ -77,9 +74,6 @@ spapr_vio_free_crq(uint32_t reg) "CRQ for dev 0x%" PRIx32 " freed" # ppc.c ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "adjusted from 0x%"PRIx64" to 0x%"PRIx64", diff %"PRId64" (%"PRId64"s)" -# prep.c -prep_io_800_writeb(uint32_t addr, uint32_t val) "0x%08" PRIx32 " => 0x%02" PRIx32 -prep_io_800_readb(uint32_t addr, uint32_t retval) "0x%08" PRIx32 " <= 0x%02" PRIx32 # prep_systemio.c prep_systemio_read(uint32_t addr, uint32_t val) "read addr=0x%x val=0x%x" diff --git a/hw/ppc/trace.h b/hw/ppc/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..87c4198e6114ebb8d3353879563b34d1e3d7de20 --- /dev/null +++ b/hw/ppc/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_ppc.h" diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c index 0dacfcd23600847f9e0bc6f1d300ae567a5be1e6..c790c1113f076b0f464a8d2d57a13def8c52c884 100644 --- a/hw/ppc/virtex_ml507.c +++ b/hw/ppc/virtex_ml507.c @@ -36,6 +36,7 @@ #include "sysemu/device_tree.h" #include "hw/loader.h" #include "elf.h" +#include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/log.h" #include "qemu/option.h" @@ -228,9 +229,9 @@ static void virtex_init(MachineState *machine) 64 * KiB, 1, 0x89, 0x18, 0x0000, 0x0, 1); cpu_irq = (qemu_irq *) &env->irq_inputs[PPC40x_INPUT_INT]; - dev = qdev_create(NULL, "xlnx.xps-intc"); + dev = qdev_new("xlnx.xps-intc"); qdev_prop_set_uint32(dev, "kind-of-intr", 0); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, INTC_BASEADDR); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irq[0]); for (i = 0; i < 32; i++) { @@ -241,20 +242,20 @@ static void virtex_init(MachineState *machine) 115200, serial_hd(0), DEVICE_LITTLE_ENDIAN); /* 2 timers at irq 2 @ 62 Mhz. */ - dev = qdev_create(NULL, "xlnx.xps-timer"); + dev = qdev_new("xlnx.xps-timer"); qdev_prop_set_uint32(dev, "one-timer-only", 0); qdev_prop_set_uint32(dev, "clock-frequency", 62 * 1000000); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, TIMER_BASEADDR); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[TIMER_IRQ]); if (kernel_filename) { - uint64_t entry, low, high; + uint64_t entry, high; hwaddr boot_offset; /* Boots a kernel elf binary. */ kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, - &entry, &low, &high, NULL, 1, PPC_ELF_MACHINE, + &entry, NULL, &high, NULL, 1, PPC_ELF_MACHINE, 0, 0); boot_info.bootstrap_pc = entry & 0x00ffffff; diff --git a/hw/rdma/Makefile.objs b/hw/rdma/Makefile.objs deleted file mode 100644 index 819bb12a35aa9dd2f7a67c34800b1e8d0b911d50..0000000000000000000000000000000000000000 --- a/hw/rdma/Makefile.objs +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_VMW_PVRDMA) += rdma_utils.o rdma_backend.o rdma_rm.o rdma.o -obj-$(CONFIG_VMW_PVRDMA) += vmw/pvrdma_dev_ring.o vmw/pvrdma_cmd.o \ - vmw/pvrdma_qp_ops.o vmw/pvrdma_main.o diff --git a/hw/rdma/meson.build b/hw/rdma/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..7325f40c32e9db38f705c2007fce2b70d8b0a62c --- /dev/null +++ b/hw/rdma/meson.build @@ -0,0 +1,10 @@ +specific_ss.add(when: 'CONFIG_VMW_PVRDMA', if_true: files( + 'rdma.c', + 'rdma_backend.c', + 'rdma_rm.c', + 'rdma_utils.c', + 'vmw/pvrdma_cmd.c', + 'vmw/pvrdma_dev_ring.c', + 'vmw/pvrdma_main.c', + 'vmw/pvrdma_qp_ops.c', +)) diff --git a/hw/rdma/rdma_backend.c b/hw/rdma/rdma_backend.c index db7e5c8be5c50c8cfa16e8f9a529e3020f7c6da7..5de010b1fabab1dde0118a3cb6d2c2cd837fad9f 100644 --- a/hw/rdma/rdma_backend.c +++ b/hw/rdma/rdma_backend.c @@ -68,7 +68,7 @@ static void free_cqe_ctx(gpointer data, gpointer user_data) bctx = rdma_rm_get_cqe_ctx(rdma_dev_res, cqe_ctx_id); if (bctx) { rdma_rm_dealloc_cqe_ctx(rdma_dev_res, cqe_ctx_id); - atomic_dec(&rdma_dev_res->stats.missing_cqe); + qatomic_dec(&rdma_dev_res->stats.missing_cqe); } g_free(bctx); } @@ -81,7 +81,7 @@ static void clean_recv_mads(RdmaBackendDev *backend_dev) cqe_ctx_id = rdma_protected_qlist_pop_int64(&backend_dev-> recv_mads_list); if (cqe_ctx_id != -ENOENT) { - atomic_inc(&backend_dev->rdma_dev_res->stats.missing_cqe); + qatomic_inc(&backend_dev->rdma_dev_res->stats.missing_cqe); free_cqe_ctx(GINT_TO_POINTER(cqe_ctx_id), backend_dev->rdma_dev_res); } @@ -123,7 +123,7 @@ static int rdma_poll_cq(RdmaDeviceResources *rdma_dev_res, struct ibv_cq *ibcq) } total_ne += ne; } while (ne > 0); - atomic_sub(&rdma_dev_res->stats.missing_cqe, total_ne); + qatomic_sub(&rdma_dev_res->stats.missing_cqe, total_ne); } if (ne < 0) { @@ -195,17 +195,17 @@ static void *comp_handler_thread(void *arg) static inline void disable_rdmacm_mux_async(RdmaBackendDev *backend_dev) { - atomic_set(&backend_dev->rdmacm_mux.can_receive, 0); + qatomic_set(&backend_dev->rdmacm_mux.can_receive, 0); } static inline void enable_rdmacm_mux_async(RdmaBackendDev *backend_dev) { - atomic_set(&backend_dev->rdmacm_mux.can_receive, sizeof(RdmaCmMuxMsg)); + qatomic_set(&backend_dev->rdmacm_mux.can_receive, sizeof(RdmaCmMuxMsg)); } static inline int rdmacm_mux_can_process_async(RdmaBackendDev *backend_dev) { - return atomic_read(&backend_dev->rdmacm_mux.can_receive); + return qatomic_read(&backend_dev->rdmacm_mux.can_receive); } static int rdmacm_mux_check_op_status(CharBackend *mad_chr_be) @@ -555,7 +555,7 @@ void rdma_backend_post_send(RdmaBackendDev *backend_dev, goto err_dealloc_cqe_ctx; } - atomic_inc(&backend_dev->rdma_dev_res->stats.missing_cqe); + qatomic_inc(&backend_dev->rdma_dev_res->stats.missing_cqe); backend_dev->rdma_dev_res->stats.tx++; return; @@ -658,7 +658,7 @@ void rdma_backend_post_recv(RdmaBackendDev *backend_dev, goto err_dealloc_cqe_ctx; } - atomic_inc(&backend_dev->rdma_dev_res->stats.missing_cqe); + qatomic_inc(&backend_dev->rdma_dev_res->stats.missing_cqe); backend_dev->rdma_dev_res->stats.rx_bufs++; return; @@ -710,7 +710,7 @@ void rdma_backend_post_srq_recv(RdmaBackendDev *backend_dev, goto err_dealloc_cqe_ctx; } - atomic_inc(&backend_dev->rdma_dev_res->stats.missing_cqe); + qatomic_inc(&backend_dev->rdma_dev_res->stats.missing_cqe); backend_dev->rdma_dev_res->stats.rx_bufs++; backend_dev->rdma_dev_res->stats.rx_srq++; diff --git a/hw/rdma/rdma_rm.c b/hw/rdma/rdma_rm.c index 60957f88db9311412ec6d26be1a4158eeeeb3808..49141d4074b29e33a028b5bc34dd0d476fe9e92f 100644 --- a/hw/rdma/rdma_rm.c +++ b/hw/rdma/rdma_rm.c @@ -790,7 +790,7 @@ int rdma_rm_init(RdmaDeviceResources *dev_res, struct ibv_device_attr *dev_attr) qemu_mutex_init(&dev_res->lock); memset(&dev_res->stats, 0, sizeof(dev_res->stats)); - atomic_set(&dev_res->stats.missing_cqe, 0); + qatomic_set(&dev_res->stats.missing_cqe, 0); return 0; } diff --git a/hw/rdma/trace.h b/hw/rdma/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..b3fa8ebc51d16b871508e1f1b41c7bdb2dcfda34 --- /dev/null +++ b/hw/rdma/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_rdma.h" diff --git a/hw/rdma/vmw/pvrdma.h b/hw/rdma/vmw/pvrdma.h index a8a04a253c5f437e64152d3b0d8ef010df3eff71..1d36a76f1e3be409812c07475043fa8ebc206a42 100644 --- a/hw/rdma/vmw/pvrdma.h +++ b/hw/rdma/vmw/pvrdma.h @@ -29,6 +29,7 @@ #include "standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h" #include "standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_dev_api.h" #include "pvrdma_dev_ring.h" +#include "qom/object.h" /* BARs */ #define RDMA_MSIX_BAR_IDX 0 @@ -78,7 +79,7 @@ typedef struct PVRDMADevStats { uint64_t interrupts; } PVRDMADevStats; -typedef struct PVRDMADev { +struct PVRDMADev { PCIDevice parent_obj; MemoryRegion msix; MemoryRegion regs; @@ -98,8 +99,10 @@ typedef struct PVRDMADev { VMXNET3State *func0; Notifier shutdown_notifier; PVRDMADevStats stats; -} PVRDMADev; -#define PVRDMA_DEV(dev) OBJECT_CHECK(PVRDMADev, (dev), PVRDMA_HW_NAME) +}; +typedef struct PVRDMADev PVRDMADev; +DECLARE_INSTANCE_CHECKER(PVRDMADev, PVRDMA_DEV, + PVRDMA_HW_NAME) static inline int get_reg_val(PVRDMADev *dev, hwaddr addr, uint32_t *val) { diff --git a/hw/rdma/vmw/pvrdma_dev_ring.c b/hw/rdma/vmw/pvrdma_dev_ring.c index c122fe7035bda328761ec01359eb4f4928fc1aed..f0bcde74b06a4360f34990b9401b915c0ed004eb 100644 --- a/hw/rdma/vmw/pvrdma_dev_ring.c +++ b/hw/rdma/vmw/pvrdma_dev_ring.c @@ -38,8 +38,8 @@ int pvrdma_ring_init(PvrdmaRing *ring, const char *name, PCIDevice *dev, ring->max_elems = max_elems; ring->elem_sz = elem_sz; /* TODO: Give a moment to think if we want to redo driver settings - atomic_set(&ring->ring_state->prod_tail, 0); - atomic_set(&ring->ring_state->cons_head, 0); + qatomic_set(&ring->ring_state->prod_tail, 0); + qatomic_set(&ring->ring_state->cons_head, 0); */ ring->npages = npages; ring->pages = g_malloc(npages * sizeof(void *)); diff --git a/hw/rdma/vmw/pvrdma_main.c b/hw/rdma/vmw/pvrdma_main.c index 3254aadb6e34943c53754d853711113e73dda217..77b1235a3f353fa14082e7459762b207bf2da96f 100644 --- a/hw/rdma/vmw/pvrdma_main.c +++ b/hw/rdma/vmw/pvrdma_main.c @@ -681,7 +681,7 @@ static void pvrdma_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - RdmaProviderClass *ir = INTERFACE_RDMA_PROVIDER_CLASS(klass); + RdmaProviderClass *ir = RDMA_PROVIDER_CLASS(klass); k->realize = pvrdma_realize; k->vendor_id = PCI_VENDOR_ID_VMWARE; diff --git a/hw/rdma/vmw/trace.h b/hw/rdma/vmw/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..3ebc9fb7ad617d28502a52567bc55888e310a370 --- /dev/null +++ b/hw/rdma/vmw/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_rdma_vmw.h" diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index ff9fbe958aed17bffc6dd0ba617229e7da305990..facb0cbacc74db9df3782a860b4aaab2234e5f97 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -1,41 +1,65 @@ -config HTIF +config IBEX bool -config HART +config MICROCHIP_PFSOC bool + select CADENCE_SDHCI + select MCHP_PFSOC_DMC + select MCHP_PFSOC_IOSCB + select MCHP_PFSOC_MMUART + select MCHP_PFSOC_SYSREG + select MSI_NONBROKEN + select SIFIVE_CLINT + select SIFIVE_PDMA + select SIFIVE_PLIC + select UNIMP -config SIFIVE +config OPENTITAN bool + select IBEX + select UNIMP + +config RISCV_VIRT + bool + imply PCI_DEVICES + imply TEST_DEVICES + select GOLDFISH_RTC select MSI_NONBROKEN + select PCI + select PCI_EXPRESS_GENERIC_BRIDGE + select PFLASH_CFI01 + select SERIAL + select SIFIVE_CLINT + select SIFIVE_PLIC + select SIFIVE_TEST + select VIRTIO_MMIO config SIFIVE_E bool - select HART - select SIFIVE + select MSI_NONBROKEN + select SIFIVE_CLINT + select SIFIVE_GPIO + select SIFIVE_PLIC + select SIFIVE_UART + select SIFIVE_E_PRCI select UNIMP config SIFIVE_U bool select CADENCE - select HART - select SIFIVE + select MSI_NONBROKEN + select SIFIVE_CLINT + select SIFIVE_GPIO + select SIFIVE_PDMA + select SIFIVE_PLIC + select SIFIVE_UART + select SIFIVE_U_OTP + select SIFIVE_U_PRCI select UNIMP config SPIKE bool - select HART select HTIF - select SIFIVE - -config RISCV_VIRT - bool - imply PCI_DEVICES - imply TEST_DEVICES - select PCI - select HART - select SERIAL - select GOLDFISH_RTC - select VIRTIO_MMIO - select PCI_EXPRESS_GENERIC_BRIDGE - select PFLASH_CFI01 - select SIFIVE + select MSI_NONBROKEN + select SIFIVE_CLINT + select SIFIVE_PLIC diff --git a/hw/riscv/Makefile.objs b/hw/riscv/Makefile.objs deleted file mode 100644 index 4483e618795189bc49cf231bce55f393a86052b7..0000000000000000000000000000000000000000 --- a/hw/riscv/Makefile.objs +++ /dev/null @@ -1,16 +0,0 @@ -obj-y += boot.o -obj-y += numa.o -obj-$(CONFIG_SPIKE) += riscv_htif.o -obj-$(CONFIG_HART) += riscv_hart.o -obj-$(CONFIG_SIFIVE_E) += sifive_e.o -obj-$(CONFIG_SIFIVE_E) += sifive_e_prci.o -obj-$(CONFIG_SIFIVE) += sifive_clint.o -obj-$(CONFIG_SIFIVE) += sifive_gpio.o -obj-$(CONFIG_SIFIVE) += sifive_plic.o -obj-$(CONFIG_SIFIVE) += sifive_test.o -obj-$(CONFIG_SIFIVE_U) += sifive_u.o -obj-$(CONFIG_SIFIVE_U) += sifive_u_otp.o -obj-$(CONFIG_SIFIVE_U) += sifive_u_prci.o -obj-$(CONFIG_SIFIVE) += sifive_uart.o -obj-$(CONFIG_SPIKE) += spike.o -obj-$(CONFIG_RISCV_VIRT) += virt.o diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 726300a171e09e6c7096dc540311c2da33bf6012..9b3fe3fb1e0fdd3431f6c6ef7f2122dda624e185 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -25,50 +25,50 @@ #include "hw/boards.h" #include "hw/loader.h" #include "hw/riscv/boot.h" +#include "hw/riscv/boot_opensbi.h" #include "elf.h" +#include "sysemu/device_tree.h" #include "sysemu/qtest.h" +#include + #if defined(TARGET_RISCV32) -# define KERNEL_BOOT_ADDRESS 0x80400000 +#define fw_dynamic_info_data(__val) cpu_to_le32(__val) #else -# define KERNEL_BOOT_ADDRESS 0x80200000 +#define fw_dynamic_info_data(__val) cpu_to_le64(__val) #endif -void riscv_find_and_load_firmware(MachineState *machine, - const char *default_machine_firmware, - hwaddr firmware_load_addr, - symbol_fn_t sym_cb) +bool riscv_is_32_bit(MachineState *machine) { - char *firmware_filename = NULL; + if (!strncmp(machine->cpu_type, "rv32", 4)) { + return true; + } else { + return false; + } +} - if (!machine->firmware) { - /* - * The user didn't specify -bios. - * At the moment we default to loading nothing when this hapens. - * In the future this defaul will change to loading the prebuilt - * OpenSBI firmware. Let's warn the user and then continue. - */ - if (!qtest_enabled()) { - warn_report("No -bios option specified. Not loading a firmware."); - warn_report("This default will change in a future QEMU release. " \ - "Please use the -bios option to avoid breakages when "\ - "this happens."); - warn_report("See QEMU's deprecation documentation for details."); - } - return; +target_ulong riscv_calc_kernel_start_addr(MachineState *machine, + target_ulong firmware_end_addr) { + if (riscv_is_32_bit(machine)) { + return QEMU_ALIGN_UP(firmware_end_addr, 4 * MiB); + } else { + return QEMU_ALIGN_UP(firmware_end_addr, 2 * MiB); } +} + +target_ulong riscv_find_and_load_firmware(MachineState *machine, + const char *default_machine_firmware, + hwaddr firmware_load_addr, + symbol_fn_t sym_cb) +{ + char *firmware_filename = NULL; + target_ulong firmware_end_addr = firmware_load_addr; - if (!strcmp(machine->firmware, "default")) { + if ((!machine->firmware) || (!strcmp(machine->firmware, "default"))) { /* - * The user has specified "-bios default". That means we are going to - * load the OpenSBI binary included in the QEMU source. - * - * We can't load the binary by default as it will break existing users - * as users are already loading their own firmware. - * - * Let's try to get everyone to specify the -bios option at all times, - * so then in the future we can make "-bios default" the default option - * if no -bios option is set without breaking anything. + * The user didn't specify -bios, or has specified "-bios default". + * That means we are going to load the OpenSBI binary included in + * the QEMU source. */ firmware_filename = riscv_find_firmware(default_machine_firmware); } else if (strcmp(machine->firmware, "none")) { @@ -77,9 +77,12 @@ void riscv_find_and_load_firmware(MachineState *machine, if (firmware_filename) { /* If not "none" load the firmware */ - riscv_load_firmware(firmware_filename, firmware_load_addr, sym_cb); + firmware_end_addr = riscv_load_firmware(firmware_filename, + firmware_load_addr, sym_cb); g_free(firmware_filename); } + + return firmware_end_addr; } char *riscv_find_firmware(const char *firmware_filename) @@ -88,9 +91,17 @@ char *riscv_find_firmware(const char *firmware_filename) filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, firmware_filename); if (filename == NULL) { - error_report("Unable to load the RISC-V firmware \"%s\"", - firmware_filename); - exit(1); + if (!qtest_enabled()) { + /* + * We only ship plain binary bios images in the QEMU source. + * With Spike machine that uses ELF images as the default bios, + * running QEMU test will complain hence let's suppress the error + * report for QEMU testing. + */ + error_report("Unable to load the RISC-V firmware \"%s\"", + firmware_filename); + exit(1); + } } return filename; @@ -100,29 +111,33 @@ target_ulong riscv_load_firmware(const char *firmware_filename, hwaddr firmware_load_addr, symbol_fn_t sym_cb) { - uint64_t firmware_entry, firmware_start, firmware_end; + uint64_t firmware_entry, firmware_size, firmware_end; if (load_elf_ram_sym(firmware_filename, NULL, NULL, NULL, - &firmware_entry, &firmware_start, &firmware_end, NULL, + &firmware_entry, NULL, &firmware_end, NULL, 0, EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) { - return firmware_entry; + return firmware_end; } - if (load_image_targphys_as(firmware_filename, firmware_load_addr, - ram_size, NULL) > 0) { - return firmware_load_addr; + firmware_size = load_image_targphys_as(firmware_filename, + firmware_load_addr, ram_size, NULL); + + if (firmware_size > 0) { + return firmware_load_addr + firmware_size; } error_report("could not load firmware '%s'", firmware_filename); exit(1); } -target_ulong riscv_load_kernel(const char *kernel_filename, symbol_fn_t sym_cb) +target_ulong riscv_load_kernel(const char *kernel_filename, + target_ulong kernel_start_addr, + symbol_fn_t sym_cb) { - uint64_t kernel_entry, kernel_high; + uint64_t kernel_entry; if (load_elf_ram_sym(kernel_filename, NULL, NULL, NULL, - &kernel_entry, NULL, &kernel_high, NULL, 0, + &kernel_entry, NULL, NULL, NULL, 0, EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) { return kernel_entry; } @@ -132,9 +147,9 @@ target_ulong riscv_load_kernel(const char *kernel_filename, symbol_fn_t sym_cb) return kernel_entry; } - if (load_image_targphys_as(kernel_filename, KERNEL_BOOT_ADDRESS, + if (load_image_targphys_as(kernel_filename, kernel_start_addr, ram_size, NULL) > 0) { - return KERNEL_BOOT_ADDRESS; + return kernel_start_addr; } error_report("could not load kernel '%s'", kernel_filename); @@ -170,3 +185,104 @@ hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size, return *start + size; } + +uint32_t riscv_load_fdt(hwaddr dram_base, uint64_t mem_size, void *fdt) +{ + uint32_t temp, fdt_addr; + hwaddr dram_end = dram_base + mem_size; + int fdtsize = fdt_totalsize(fdt); + + if (fdtsize <= 0) { + error_report("invalid device-tree"); + exit(1); + } + + /* + * We should put fdt as far as possible to avoid kernel/initrd overwriting + * its content. But it should be addressable by 32 bit system as well. + * Thus, put it at an aligned address that less than fdt size from end of + * dram or 4GB whichever is lesser. + */ + temp = MIN(dram_end, 4096 * MiB); + fdt_addr = QEMU_ALIGN_DOWN(temp - fdtsize, 2 * MiB); + + fdt_pack(fdt); + /* copy in the device tree */ + qemu_fdt_dumpdtb(fdt, fdtsize); + + rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr, + &address_space_memory); + + return fdt_addr; +} + +void riscv_rom_copy_firmware_info(hwaddr rom_base, hwaddr rom_size, + uint32_t reset_vec_size, uint64_t kernel_entry) +{ + struct fw_dynamic_info dinfo; + size_t dinfo_len; + + dinfo.magic = fw_dynamic_info_data(FW_DYNAMIC_INFO_MAGIC_VALUE); + dinfo.version = fw_dynamic_info_data(FW_DYNAMIC_INFO_VERSION); + dinfo.next_mode = fw_dynamic_info_data(FW_DYNAMIC_INFO_NEXT_MODE_S); + dinfo.next_addr = fw_dynamic_info_data(kernel_entry); + dinfo.options = 0; + dinfo.boot_hart = 0; + dinfo_len = sizeof(dinfo); + + /** + * copy the dynamic firmware info. This information is specific to + * OpenSBI but doesn't break any other firmware as long as they don't + * expect any certain value in "a2" register. + */ + if (dinfo_len > (rom_size - reset_vec_size)) { + error_report("not enough space to store dynamic firmware info"); + exit(1); + } + + rom_add_blob_fixed_as("mrom.finfo", &dinfo, dinfo_len, + rom_base + reset_vec_size, + &address_space_memory); +} + +void riscv_setup_rom_reset_vec(hwaddr start_addr, hwaddr rom_base, + hwaddr rom_size, uint64_t kernel_entry, + uint32_t fdt_load_addr, void *fdt) +{ + int i; + uint32_t start_addr_hi32 = 0x00000000; + + #if defined(TARGET_RISCV64) + start_addr_hi32 = start_addr >> 32; + #endif + /* reset vector */ + uint32_t reset_vec[10] = { + 0x00000297, /* 1: auipc t0, %pcrel_hi(fw_dyn) */ + 0x02828613, /* addi a2, t0, %pcrel_lo(1b) */ + 0xf1402573, /* csrr a0, mhartid */ +#if defined(TARGET_RISCV32) + 0x0202a583, /* lw a1, 32(t0) */ + 0x0182a283, /* lw t0, 24(t0) */ +#elif defined(TARGET_RISCV64) + 0x0202b583, /* ld a1, 32(t0) */ + 0x0182b283, /* ld t0, 24(t0) */ +#endif + 0x00028067, /* jr t0 */ + start_addr, /* start: .dword */ + start_addr_hi32, + fdt_load_addr, /* fdt_laddr: .dword */ + 0x00000000, + /* fw_dyn: */ + }; + + /* copy in the reset vector in little_endian byte order */ + for (i = 0; i < ARRAY_SIZE(reset_vec); i++) { + reset_vec[i] = cpu_to_le32(reset_vec[i]); + } + rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec), + rom_base, &address_space_memory); + riscv_rom_copy_firmware_info(rom_base, rom_size, sizeof(reset_vec), + kernel_entry); + + return; +} diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..275c0f7eb7c4de824731c25277df989f36b055d8 --- /dev/null +++ b/hw/riscv/meson.build @@ -0,0 +1,12 @@ +riscv_ss = ss.source_set() +riscv_ss.add(files('boot.c'), fdt) +riscv_ss.add(files('numa.c')) +riscv_ss.add(files('riscv_hart.c')) +riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c')) +riscv_ss.add(when: 'CONFIG_RISCV_VIRT', if_true: files('virt.c')) +riscv_ss.add(when: 'CONFIG_SIFIVE_E', if_true: files('sifive_e.c')) +riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u.c')) +riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c')) +riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: files('microchip_pfsoc.c')) + +hw_arch += {'riscv': riscv_ss} diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c new file mode 100644 index 0000000000000000000000000000000000000000..37ac46a1afe4d5f47a8609fe0b7a59f7b7c5c7e8 --- /dev/null +++ b/hw/riscv/microchip_pfsoc.c @@ -0,0 +1,532 @@ +/* + * QEMU RISC-V Board Compatible with Microchip PolarFire SoC Icicle Kit + * + * Copyright (c) 2020 Wind River Systems, Inc. + * + * Author: + * Bin Meng + * + * Provides a board compatible with the Microchip PolarFire SoC Icicle Kit + * + * 0) CLINT (Core Level Interruptor) + * 1) PLIC (Platform Level Interrupt Controller) + * 2) eNVM (Embedded Non-Volatile Memory) + * 3) MMUARTs (Multi-Mode UART) + * 4) Cadence eMMC/SDHC controller and an SD card connected to it + * 5) SiFive Platform DMA (Direct Memory Access Controller) + * 6) GEM (Gigabit Ethernet MAC Controller) + * 7) DMC (DDR Memory Controller) + * 8) IOSCB modules + * + * This board currently generates devicetree dynamically that indicates at least + * two harts and up to five harts. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qemu/units.h" +#include "qemu/cutils.h" +#include "qapi/error.h" +#include "hw/boards.h" +#include "hw/irq.h" +#include "hw/loader.h" +#include "hw/sysbus.h" +#include "chardev/char.h" +#include "hw/cpu/cluster.h" +#include "target/riscv/cpu.h" +#include "hw/misc/unimp.h" +#include "hw/riscv/boot.h" +#include "hw/riscv/riscv_hart.h" +#include "hw/riscv/microchip_pfsoc.h" +#include "hw/intc/sifive_clint.h" +#include "hw/intc/sifive_plic.h" +#include "sysemu/sysemu.h" + +/* + * The BIOS image used by this machine is called Hart Software Services (HSS). + * See https://github.com/polarfire-soc/hart-software-services + */ +#define BIOS_FILENAME "hss.bin" +#define RESET_VECTOR 0x20220000 + +/* CLINT timebase frequency */ +#define CLINT_TIMEBASE_FREQ 1000000 + +/* GEM version */ +#define GEM_REVISION 0x0107010c + +/* + * The complete description of the whole PolarFire SoC memory map is scattered + * in different documents. There are several places to look at for memory maps: + * + * 1 Chapter 11 "MSS Memory Map", in the doc "UG0880: PolarFire SoC FPGA + * Microprocessor Subsystem (MSS) User Guide", which can be downloaded from + * https://www.microsemi.com/document-portal/doc_download/ + * 1244570-ug0880-polarfire-soc-fpga-microprocessor-subsystem-mss-user-guide, + * describes the whole picture of the PolarFire SoC memory map. + * + * 2 A zip file for PolarFire soC memory map, which can be downloaded from + * https://www.microsemi.com/document-portal/doc_download/ + * 1244581-polarfire-soc-register-map, contains the following 2 major parts: + * - Register Map/PF_SoC_RegMap_V1_1/pfsoc_regmap.htm + * describes the complete integrated peripherals memory map + * - Register Map/PF_SoC_RegMap_V1_1/MPFS250T/mpfs250t_ioscb_memmap_dri.htm + * describes the complete IOSCB modules memory maps + */ +static const struct MemmapEntry { + hwaddr base; + hwaddr size; +} microchip_pfsoc_memmap[] = { + [MICROCHIP_PFSOC_RSVD0] = { 0x0, 0x100 }, + [MICROCHIP_PFSOC_DEBUG] = { 0x100, 0xf00 }, + [MICROCHIP_PFSOC_E51_DTIM] = { 0x1000000, 0x2000 }, + [MICROCHIP_PFSOC_BUSERR_UNIT0] = { 0x1700000, 0x1000 }, + [MICROCHIP_PFSOC_BUSERR_UNIT1] = { 0x1701000, 0x1000 }, + [MICROCHIP_PFSOC_BUSERR_UNIT2] = { 0x1702000, 0x1000 }, + [MICROCHIP_PFSOC_BUSERR_UNIT3] = { 0x1703000, 0x1000 }, + [MICROCHIP_PFSOC_BUSERR_UNIT4] = { 0x1704000, 0x1000 }, + [MICROCHIP_PFSOC_CLINT] = { 0x2000000, 0x10000 }, + [MICROCHIP_PFSOC_L2CC] = { 0x2010000, 0x1000 }, + [MICROCHIP_PFSOC_DMA] = { 0x3000000, 0x100000 }, + [MICROCHIP_PFSOC_L2LIM] = { 0x8000000, 0x2000000 }, + [MICROCHIP_PFSOC_PLIC] = { 0xc000000, 0x4000000 }, + [MICROCHIP_PFSOC_MMUART0] = { 0x20000000, 0x1000 }, + [MICROCHIP_PFSOC_SYSREG] = { 0x20002000, 0x2000 }, + [MICROCHIP_PFSOC_MPUCFG] = { 0x20005000, 0x1000 }, + [MICROCHIP_PFSOC_DDR_SGMII_PHY] = { 0x20007000, 0x1000 }, + [MICROCHIP_PFSOC_EMMC_SD] = { 0x20008000, 0x1000 }, + [MICROCHIP_PFSOC_DDR_CFG] = { 0x20080000, 0x40000 }, + [MICROCHIP_PFSOC_MMUART1] = { 0x20100000, 0x1000 }, + [MICROCHIP_PFSOC_MMUART2] = { 0x20102000, 0x1000 }, + [MICROCHIP_PFSOC_MMUART3] = { 0x20104000, 0x1000 }, + [MICROCHIP_PFSOC_MMUART4] = { 0x20106000, 0x1000 }, + [MICROCHIP_PFSOC_I2C1] = { 0x2010b000, 0x1000 }, + [MICROCHIP_PFSOC_GEM0] = { 0x20110000, 0x2000 }, + [MICROCHIP_PFSOC_GEM1] = { 0x20112000, 0x2000 }, + [MICROCHIP_PFSOC_GPIO0] = { 0x20120000, 0x1000 }, + [MICROCHIP_PFSOC_GPIO1] = { 0x20121000, 0x1000 }, + [MICROCHIP_PFSOC_GPIO2] = { 0x20122000, 0x1000 }, + [MICROCHIP_PFSOC_ENVM_CFG] = { 0x20200000, 0x1000 }, + [MICROCHIP_PFSOC_ENVM_DATA] = { 0x20220000, 0x20000 }, + [MICROCHIP_PFSOC_IOSCB] = { 0x30000000, 0x10000000 }, + [MICROCHIP_PFSOC_DRAM_LO] = { 0x80000000, 0x40000000 }, + [MICROCHIP_PFSOC_DRAM_LO_ALIAS] = { 0xc0000000, 0x40000000 }, + [MICROCHIP_PFSOC_DRAM_HI] = { 0x1000000000, 0x0 }, + [MICROCHIP_PFSOC_DRAM_HI_ALIAS] = { 0x1400000000, 0x0 }, +}; + +static void microchip_pfsoc_soc_instance_init(Object *obj) +{ + MachineState *ms = MACHINE(qdev_get_machine()); + MicrochipPFSoCState *s = MICROCHIP_PFSOC(obj); + + object_initialize_child(obj, "e-cluster", &s->e_cluster, TYPE_CPU_CLUSTER); + qdev_prop_set_uint32(DEVICE(&s->e_cluster), "cluster-id", 0); + + object_initialize_child(OBJECT(&s->e_cluster), "e-cpus", &s->e_cpus, + TYPE_RISCV_HART_ARRAY); + qdev_prop_set_uint32(DEVICE(&s->e_cpus), "num-harts", 1); + qdev_prop_set_uint32(DEVICE(&s->e_cpus), "hartid-base", 0); + qdev_prop_set_string(DEVICE(&s->e_cpus), "cpu-type", + TYPE_RISCV_CPU_SIFIVE_E51); + qdev_prop_set_uint64(DEVICE(&s->e_cpus), "resetvec", RESET_VECTOR); + + object_initialize_child(obj, "u-cluster", &s->u_cluster, TYPE_CPU_CLUSTER); + qdev_prop_set_uint32(DEVICE(&s->u_cluster), "cluster-id", 1); + + object_initialize_child(OBJECT(&s->u_cluster), "u-cpus", &s->u_cpus, + TYPE_RISCV_HART_ARRAY); + qdev_prop_set_uint32(DEVICE(&s->u_cpus), "num-harts", ms->smp.cpus - 1); + qdev_prop_set_uint32(DEVICE(&s->u_cpus), "hartid-base", 1); + qdev_prop_set_string(DEVICE(&s->u_cpus), "cpu-type", + TYPE_RISCV_CPU_SIFIVE_U54); + qdev_prop_set_uint64(DEVICE(&s->u_cpus), "resetvec", RESET_VECTOR); + + object_initialize_child(obj, "dma-controller", &s->dma, + TYPE_SIFIVE_PDMA); + + object_initialize_child(obj, "sysreg", &s->sysreg, + TYPE_MCHP_PFSOC_SYSREG); + + object_initialize_child(obj, "ddr-sgmii-phy", &s->ddr_sgmii_phy, + TYPE_MCHP_PFSOC_DDR_SGMII_PHY); + object_initialize_child(obj, "ddr-cfg", &s->ddr_cfg, + TYPE_MCHP_PFSOC_DDR_CFG); + + object_initialize_child(obj, "gem0", &s->gem0, TYPE_CADENCE_GEM); + object_initialize_child(obj, "gem1", &s->gem1, TYPE_CADENCE_GEM); + + object_initialize_child(obj, "sd-controller", &s->sdhci, + TYPE_CADENCE_SDHCI); + + object_initialize_child(obj, "ioscb", &s->ioscb, TYPE_MCHP_PFSOC_IOSCB); +} + +static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp) +{ + MachineState *ms = MACHINE(qdev_get_machine()); + MicrochipPFSoCState *s = MICROCHIP_PFSOC(dev); + const struct MemmapEntry *memmap = microchip_pfsoc_memmap; + MemoryRegion *system_memory = get_system_memory(); + MemoryRegion *rsvd0_mem = g_new(MemoryRegion, 1); + MemoryRegion *e51_dtim_mem = g_new(MemoryRegion, 1); + MemoryRegion *l2lim_mem = g_new(MemoryRegion, 1); + MemoryRegion *envm_data = g_new(MemoryRegion, 1); + char *plic_hart_config; + size_t plic_hart_config_len; + NICInfo *nd; + int i; + + sysbus_realize(SYS_BUS_DEVICE(&s->e_cpus), &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->u_cpus), &error_abort); + /* + * The cluster must be realized after the RISC-V hart array container, + * as the container's CPU object is only created on realize, and the + * CPU must exist and have been parented into the cluster before the + * cluster is realized. + */ + qdev_realize(DEVICE(&s->e_cluster), NULL, &error_abort); + qdev_realize(DEVICE(&s->u_cluster), NULL, &error_abort); + + /* Reserved Memory at address 0 */ + memory_region_init_ram(rsvd0_mem, NULL, "microchip.pfsoc.rsvd0_mem", + memmap[MICROCHIP_PFSOC_RSVD0].size, &error_fatal); + memory_region_add_subregion(system_memory, + memmap[MICROCHIP_PFSOC_RSVD0].base, + rsvd0_mem); + + /* E51 DTIM */ + memory_region_init_ram(e51_dtim_mem, NULL, "microchip.pfsoc.e51_dtim_mem", + memmap[MICROCHIP_PFSOC_E51_DTIM].size, &error_fatal); + memory_region_add_subregion(system_memory, + memmap[MICROCHIP_PFSOC_E51_DTIM].base, + e51_dtim_mem); + + /* Bus Error Units */ + create_unimplemented_device("microchip.pfsoc.buserr_unit0_mem", + memmap[MICROCHIP_PFSOC_BUSERR_UNIT0].base, + memmap[MICROCHIP_PFSOC_BUSERR_UNIT0].size); + create_unimplemented_device("microchip.pfsoc.buserr_unit1_mem", + memmap[MICROCHIP_PFSOC_BUSERR_UNIT1].base, + memmap[MICROCHIP_PFSOC_BUSERR_UNIT1].size); + create_unimplemented_device("microchip.pfsoc.buserr_unit2_mem", + memmap[MICROCHIP_PFSOC_BUSERR_UNIT2].base, + memmap[MICROCHIP_PFSOC_BUSERR_UNIT2].size); + create_unimplemented_device("microchip.pfsoc.buserr_unit3_mem", + memmap[MICROCHIP_PFSOC_BUSERR_UNIT3].base, + memmap[MICROCHIP_PFSOC_BUSERR_UNIT3].size); + create_unimplemented_device("microchip.pfsoc.buserr_unit4_mem", + memmap[MICROCHIP_PFSOC_BUSERR_UNIT4].base, + memmap[MICROCHIP_PFSOC_BUSERR_UNIT4].size); + + /* CLINT */ + sifive_clint_create(memmap[MICROCHIP_PFSOC_CLINT].base, + memmap[MICROCHIP_PFSOC_CLINT].size, 0, ms->smp.cpus, + SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, + CLINT_TIMEBASE_FREQ, false); + + /* L2 cache controller */ + create_unimplemented_device("microchip.pfsoc.l2cc", + memmap[MICROCHIP_PFSOC_L2CC].base, memmap[MICROCHIP_PFSOC_L2CC].size); + + /* + * Add L2-LIM at reset size. + * This should be reduced in size as the L2 Cache Controller WayEnable + * register is incremented. Unfortunately I don't see a nice (or any) way + * to handle reducing or blocking out the L2 LIM while still allowing it + * be re returned to all enabled after a reset. For the time being, just + * leave it enabled all the time. This won't break anything, but will be + * too generous to misbehaving guests. + */ + memory_region_init_ram(l2lim_mem, NULL, "microchip.pfsoc.l2lim", + memmap[MICROCHIP_PFSOC_L2LIM].size, &error_fatal); + memory_region_add_subregion(system_memory, + memmap[MICROCHIP_PFSOC_L2LIM].base, + l2lim_mem); + + /* create PLIC hart topology configuration string */ + plic_hart_config_len = (strlen(MICROCHIP_PFSOC_PLIC_HART_CONFIG) + 1) * + ms->smp.cpus; + plic_hart_config = g_malloc0(plic_hart_config_len); + for (i = 0; i < ms->smp.cpus; i++) { + if (i != 0) { + strncat(plic_hart_config, "," MICROCHIP_PFSOC_PLIC_HART_CONFIG, + plic_hart_config_len); + } else { + strncat(plic_hart_config, "M", plic_hart_config_len); + } + plic_hart_config_len -= (strlen(MICROCHIP_PFSOC_PLIC_HART_CONFIG) + 1); + } + + /* PLIC */ + s->plic = sifive_plic_create(memmap[MICROCHIP_PFSOC_PLIC].base, + plic_hart_config, 0, + MICROCHIP_PFSOC_PLIC_NUM_SOURCES, + MICROCHIP_PFSOC_PLIC_NUM_PRIORITIES, + MICROCHIP_PFSOC_PLIC_PRIORITY_BASE, + MICROCHIP_PFSOC_PLIC_PENDING_BASE, + MICROCHIP_PFSOC_PLIC_ENABLE_BASE, + MICROCHIP_PFSOC_PLIC_ENABLE_STRIDE, + MICROCHIP_PFSOC_PLIC_CONTEXT_BASE, + MICROCHIP_PFSOC_PLIC_CONTEXT_STRIDE, + memmap[MICROCHIP_PFSOC_PLIC].size); + g_free(plic_hart_config); + + /* DMA */ + sysbus_realize(SYS_BUS_DEVICE(&s->dma), errp); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->dma), 0, + memmap[MICROCHIP_PFSOC_DMA].base); + for (i = 0; i < SIFIVE_PDMA_IRQS; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), i, + qdev_get_gpio_in(DEVICE(s->plic), + MICROCHIP_PFSOC_DMA_IRQ0 + i)); + } + + /* SYSREG */ + sysbus_realize(SYS_BUS_DEVICE(&s->sysreg), errp); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysreg), 0, + memmap[MICROCHIP_PFSOC_SYSREG].base); + + /* MPUCFG */ + create_unimplemented_device("microchip.pfsoc.mpucfg", + memmap[MICROCHIP_PFSOC_MPUCFG].base, + memmap[MICROCHIP_PFSOC_MPUCFG].size); + + /* DDR SGMII PHY */ + sysbus_realize(SYS_BUS_DEVICE(&s->ddr_sgmii_phy), errp); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->ddr_sgmii_phy), 0, + memmap[MICROCHIP_PFSOC_DDR_SGMII_PHY].base); + + /* DDR CFG */ + sysbus_realize(SYS_BUS_DEVICE(&s->ddr_cfg), errp); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->ddr_cfg), 0, + memmap[MICROCHIP_PFSOC_DDR_CFG].base); + + /* SDHCI */ + sysbus_realize(SYS_BUS_DEVICE(&s->sdhci), errp); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci), 0, + memmap[MICROCHIP_PFSOC_EMMC_SD].base); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0, + qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_EMMC_SD_IRQ)); + + /* MMUARTs */ + s->serial0 = mchp_pfsoc_mmuart_create(system_memory, + memmap[MICROCHIP_PFSOC_MMUART0].base, + qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART0_IRQ), + serial_hd(0)); + s->serial1 = mchp_pfsoc_mmuart_create(system_memory, + memmap[MICROCHIP_PFSOC_MMUART1].base, + qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART1_IRQ), + serial_hd(1)); + s->serial2 = mchp_pfsoc_mmuart_create(system_memory, + memmap[MICROCHIP_PFSOC_MMUART2].base, + qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART2_IRQ), + serial_hd(2)); + s->serial3 = mchp_pfsoc_mmuart_create(system_memory, + memmap[MICROCHIP_PFSOC_MMUART3].base, + qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART3_IRQ), + serial_hd(3)); + s->serial4 = mchp_pfsoc_mmuart_create(system_memory, + memmap[MICROCHIP_PFSOC_MMUART4].base, + qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART4_IRQ), + serial_hd(4)); + + /* I2C1 */ + create_unimplemented_device("microchip.pfsoc.i2c1", + memmap[MICROCHIP_PFSOC_I2C1].base, + memmap[MICROCHIP_PFSOC_I2C1].size); + + /* GEMs */ + + nd = &nd_table[0]; + if (nd->used) { + qemu_check_nic_model(nd, TYPE_CADENCE_GEM); + qdev_set_nic_properties(DEVICE(&s->gem0), nd); + } + nd = &nd_table[1]; + if (nd->used) { + qemu_check_nic_model(nd, TYPE_CADENCE_GEM); + qdev_set_nic_properties(DEVICE(&s->gem1), nd); + } + + object_property_set_int(OBJECT(&s->gem0), "revision", GEM_REVISION, errp); + object_property_set_int(OBJECT(&s->gem0), "phy-addr", 8, errp); + sysbus_realize(SYS_BUS_DEVICE(&s->gem0), errp); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gem0), 0, + memmap[MICROCHIP_PFSOC_GEM0].base); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gem0), 0, + qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_GEM0_IRQ)); + + object_property_set_int(OBJECT(&s->gem1), "revision", GEM_REVISION, errp); + object_property_set_int(OBJECT(&s->gem1), "phy-addr", 9, errp); + sysbus_realize(SYS_BUS_DEVICE(&s->gem1), errp); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gem1), 0, + memmap[MICROCHIP_PFSOC_GEM1].base); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gem1), 0, + qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_GEM1_IRQ)); + + /* GPIOs */ + create_unimplemented_device("microchip.pfsoc.gpio0", + memmap[MICROCHIP_PFSOC_GPIO0].base, + memmap[MICROCHIP_PFSOC_GPIO0].size); + create_unimplemented_device("microchip.pfsoc.gpio1", + memmap[MICROCHIP_PFSOC_GPIO1].base, + memmap[MICROCHIP_PFSOC_GPIO1].size); + create_unimplemented_device("microchip.pfsoc.gpio2", + memmap[MICROCHIP_PFSOC_GPIO2].base, + memmap[MICROCHIP_PFSOC_GPIO2].size); + + /* eNVM */ + memory_region_init_rom(envm_data, OBJECT(dev), "microchip.pfsoc.envm.data", + memmap[MICROCHIP_PFSOC_ENVM_DATA].size, + &error_fatal); + memory_region_add_subregion(system_memory, + memmap[MICROCHIP_PFSOC_ENVM_DATA].base, + envm_data); + + /* IOSCB */ + sysbus_realize(SYS_BUS_DEVICE(&s->ioscb), errp); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->ioscb), 0, + memmap[MICROCHIP_PFSOC_IOSCB].base); +} + +static void microchip_pfsoc_soc_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = microchip_pfsoc_soc_realize; + /* Reason: Uses serial_hds in realize function, thus can't be used twice */ + dc->user_creatable = false; +} + +static const TypeInfo microchip_pfsoc_soc_type_info = { + .name = TYPE_MICROCHIP_PFSOC, + .parent = TYPE_DEVICE, + .instance_size = sizeof(MicrochipPFSoCState), + .instance_init = microchip_pfsoc_soc_instance_init, + .class_init = microchip_pfsoc_soc_class_init, +}; + +static void microchip_pfsoc_soc_register_types(void) +{ + type_register_static(µchip_pfsoc_soc_type_info); +} + +type_init(microchip_pfsoc_soc_register_types) + +static void microchip_icicle_kit_machine_init(MachineState *machine) +{ + MachineClass *mc = MACHINE_GET_CLASS(machine); + const struct MemmapEntry *memmap = microchip_pfsoc_memmap; + MicrochipIcicleKitState *s = MICROCHIP_ICICLE_KIT_MACHINE(machine); + MemoryRegion *system_memory = get_system_memory(); + MemoryRegion *mem_low = g_new(MemoryRegion, 1); + MemoryRegion *mem_low_alias = g_new(MemoryRegion, 1); + MemoryRegion *mem_high = g_new(MemoryRegion, 1); + MemoryRegion *mem_high_alias = g_new(MemoryRegion, 1); + uint64_t mem_high_size; + DriveInfo *dinfo = drive_get_next(IF_SD); + + /* Sanity check on RAM size */ + if (machine->ram_size < mc->default_ram_size) { + char *sz = size_to_str(mc->default_ram_size); + error_report("Invalid RAM size, should be bigger than %s", sz); + g_free(sz); + exit(EXIT_FAILURE); + } + + /* Initialize SoC */ + object_initialize_child(OBJECT(machine), "soc", &s->soc, + TYPE_MICROCHIP_PFSOC); + qdev_realize(DEVICE(&s->soc), NULL, &error_abort); + + /* Register RAM */ + memory_region_init_ram(mem_low, NULL, "microchip.icicle.kit.ram_low", + memmap[MICROCHIP_PFSOC_DRAM_LO].size, + &error_fatal); + memory_region_init_alias(mem_low_alias, NULL, + "microchip.icicle.kit.ram_low.alias", + mem_low, 0, + memmap[MICROCHIP_PFSOC_DRAM_LO_ALIAS].size); + memory_region_add_subregion(system_memory, + memmap[MICROCHIP_PFSOC_DRAM_LO].base, + mem_low); + memory_region_add_subregion(system_memory, + memmap[MICROCHIP_PFSOC_DRAM_LO_ALIAS].base, + mem_low_alias); + + mem_high_size = machine->ram_size - 1 * GiB; + + memory_region_init_ram(mem_high, NULL, "microchip.icicle.kit.ram_high", + mem_high_size, &error_fatal); + memory_region_init_alias(mem_high_alias, NULL, + "microchip.icicle.kit.ram_high.alias", + mem_high, 0, mem_high_size); + memory_region_add_subregion(system_memory, + memmap[MICROCHIP_PFSOC_DRAM_HI].base, + mem_high); + memory_region_add_subregion(system_memory, + memmap[MICROCHIP_PFSOC_DRAM_HI_ALIAS].base, + mem_high_alias); + + /* Load the firmware */ + riscv_find_and_load_firmware(machine, BIOS_FILENAME, RESET_VECTOR, NULL); + + /* Attach an SD card */ + if (dinfo) { + CadenceSDHCIState *sdhci = &(s->soc.sdhci); + DeviceState *card = qdev_new(TYPE_SD_CARD); + + qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo), + &error_fatal); + qdev_realize_and_unref(card, sdhci->bus, &error_fatal); + } +} + +static void microchip_icicle_kit_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "Microchip PolarFire SoC Icicle Kit"; + mc->init = microchip_icicle_kit_machine_init; + mc->max_cpus = MICROCHIP_PFSOC_MANAGEMENT_CPU_COUNT + + MICROCHIP_PFSOC_COMPUTE_CPU_COUNT; + mc->min_cpus = MICROCHIP_PFSOC_MANAGEMENT_CPU_COUNT + 1; + mc->default_cpus = mc->min_cpus; + + /* + * Map 513 MiB high memory, the mimimum required high memory size, because + * HSS will do memory test against the high memory address range regardless + * of physical memory installed. + * + * See memory_tests() in mss_ddr.c in the HSS source code. + */ + mc->default_ram_size = 1537 * MiB; +} + +static const TypeInfo microchip_icicle_kit_machine_typeinfo = { + .name = MACHINE_TYPE_NAME("microchip-icicle-kit"), + .parent = TYPE_MACHINE, + .class_init = microchip_icicle_kit_machine_class_init, + .instance_size = sizeof(MicrochipIcicleKitState), +}; + +static void microchip_icicle_kit_machine_init_register_types(void) +{ + type_register_static(µchip_icicle_kit_machine_typeinfo); +} + +type_init(microchip_icicle_kit_machine_init_register_types) diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c new file mode 100644 index 0000000000000000000000000000000000000000..cc758b78b881a7c5b23c4a84d43b5c111d65e72e --- /dev/null +++ b/hw/riscv/opentitan.c @@ -0,0 +1,207 @@ +/* + * QEMU RISC-V Board Compatible with OpenTitan FPGA platform + * + * Copyright (c) 2020 Western Digital + * + * Provides a board compatible with the OpenTitan FPGA platform: + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#include "qemu/osdep.h" +#include "hw/riscv/opentitan.h" +#include "qapi/error.h" +#include "hw/boards.h" +#include "hw/misc/unimp.h" +#include "hw/riscv/boot.h" +#include "exec/address-spaces.h" +#include "qemu/units.h" +#include "sysemu/sysemu.h" + +static const struct MemmapEntry { + hwaddr base; + hwaddr size; +} ibex_memmap[] = { + [IBEX_DEV_ROM] = { 0x00008000, 16 * KiB }, + [IBEX_DEV_RAM] = { 0x10000000, 0x10000 }, + [IBEX_DEV_FLASH] = { 0x20000000, 0x80000 }, + [IBEX_DEV_UART] = { 0x40000000, 0x10000 }, + [IBEX_DEV_GPIO] = { 0x40010000, 0x10000 }, + [IBEX_DEV_SPI] = { 0x40020000, 0x10000 }, + [IBEX_DEV_FLASH_CTRL] = { 0x40030000, 0x10000 }, + [IBEX_DEV_PINMUX] = { 0x40070000, 0x10000 }, + [IBEX_DEV_RV_TIMER] = { 0x40080000, 0x10000 }, + [IBEX_DEV_PLIC] = { 0x40090000, 0x10000 }, + [IBEX_DEV_PWRMGR] = { 0x400A0000, 0x10000 }, + [IBEX_DEV_RSTMGR] = { 0x400B0000, 0x10000 }, + [IBEX_DEV_CLKMGR] = { 0x400C0000, 0x10000 }, + [IBEX_DEV_AES] = { 0x40110000, 0x10000 }, + [IBEX_DEV_HMAC] = { 0x40120000, 0x10000 }, + [IBEX_DEV_ALERT_HANDLER] = { 0x40130000, 0x10000 }, + [IBEX_DEV_NMI_GEN] = { 0x40140000, 0x10000 }, + [IBEX_DEV_USBDEV] = { 0x40150000, 0x10000 }, + [IBEX_DEV_PADCTRL] = { 0x40160000, 0x10000 } +}; + +static void opentitan_board_init(MachineState *machine) +{ + const struct MemmapEntry *memmap = ibex_memmap; + OpenTitanState *s = g_new0(OpenTitanState, 1); + MemoryRegion *sys_mem = get_system_memory(); + MemoryRegion *main_mem = g_new(MemoryRegion, 1); + + /* Initialize SoC */ + object_initialize_child(OBJECT(machine), "soc", &s->soc, + TYPE_RISCV_IBEX_SOC); + qdev_realize(DEVICE(&s->soc), NULL, &error_abort); + + memory_region_init_ram(main_mem, NULL, "riscv.lowrisc.ibex.ram", + memmap[IBEX_DEV_RAM].size, &error_fatal); + memory_region_add_subregion(sys_mem, + memmap[IBEX_DEV_RAM].base, main_mem); + + if (machine->firmware) { + riscv_load_firmware(machine->firmware, memmap[IBEX_DEV_RAM].base, NULL); + } + + if (machine->kernel_filename) { + riscv_load_kernel(machine->kernel_filename, + memmap[IBEX_DEV_RAM].base, NULL); + } +} + +static void opentitan_machine_init(MachineClass *mc) +{ + mc->desc = "RISC-V Board compatible with OpenTitan"; + mc->init = opentitan_board_init; + mc->max_cpus = 1; + mc->default_cpu_type = TYPE_RISCV_CPU_IBEX; +} + +DEFINE_MACHINE("opentitan", opentitan_machine_init) + +static void lowrisc_ibex_soc_init(Object *obj) +{ + LowRISCIbexSoCState *s = RISCV_IBEX_SOC(obj); + + object_initialize_child(obj, "cpus", &s->cpus, TYPE_RISCV_HART_ARRAY); + + object_initialize_child(obj, "plic", &s->plic, TYPE_IBEX_PLIC); + + object_initialize_child(obj, "uart", &s->uart, TYPE_IBEX_UART); +} + +static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp) +{ + const struct MemmapEntry *memmap = ibex_memmap; + MachineState *ms = MACHINE(qdev_get_machine()); + LowRISCIbexSoCState *s = RISCV_IBEX_SOC(dev_soc); + MemoryRegion *sys_mem = get_system_memory(); + + object_property_set_str(OBJECT(&s->cpus), "cpu-type", ms->cpu_type, + &error_abort); + object_property_set_int(OBJECT(&s->cpus), "num-harts", ms->smp.cpus, + &error_abort); + object_property_set_int(OBJECT(&s->cpus), "resetvec", 0x8090, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_abort); + + /* Boot ROM */ + memory_region_init_rom(&s->rom, OBJECT(dev_soc), "riscv.lowrisc.ibex.rom", + memmap[IBEX_DEV_ROM].size, &error_fatal); + memory_region_add_subregion(sys_mem, + memmap[IBEX_DEV_ROM].base, &s->rom); + + /* Flash memory */ + memory_region_init_rom(&s->flash_mem, OBJECT(dev_soc), "riscv.lowrisc.ibex.flash", + memmap[IBEX_DEV_FLASH].size, &error_fatal); + memory_region_add_subregion(sys_mem, memmap[IBEX_DEV_FLASH].base, + &s->flash_mem); + + /* PLIC */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->plic), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->plic), 0, memmap[IBEX_DEV_PLIC].base); + + /* UART */ + qdev_prop_set_chr(DEVICE(&(s->uart)), "chardev", serial_hd(0)); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart), 0, memmap[IBEX_DEV_UART].base); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart), + 0, qdev_get_gpio_in(DEVICE(&s->plic), + IBEX_UART_TX_WATERMARK_IRQ)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart), + 1, qdev_get_gpio_in(DEVICE(&s->plic), + IBEX_UART_RX_WATERMARK_IRQ)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart), + 2, qdev_get_gpio_in(DEVICE(&s->plic), + IBEX_UART_TX_EMPTY_IRQ)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart), + 3, qdev_get_gpio_in(DEVICE(&s->plic), + IBEX_UART_RX_OVERFLOW_IRQ)); + + create_unimplemented_device("riscv.lowrisc.ibex.gpio", + memmap[IBEX_DEV_GPIO].base, memmap[IBEX_DEV_GPIO].size); + create_unimplemented_device("riscv.lowrisc.ibex.spi", + memmap[IBEX_DEV_SPI].base, memmap[IBEX_DEV_SPI].size); + create_unimplemented_device("riscv.lowrisc.ibex.flash_ctrl", + memmap[IBEX_DEV_FLASH_CTRL].base, memmap[IBEX_DEV_FLASH_CTRL].size); + create_unimplemented_device("riscv.lowrisc.ibex.rv_timer", + memmap[IBEX_DEV_RV_TIMER].base, memmap[IBEX_DEV_RV_TIMER].size); + create_unimplemented_device("riscv.lowrisc.ibex.pwrmgr", + memmap[IBEX_DEV_PWRMGR].base, memmap[IBEX_DEV_PWRMGR].size); + create_unimplemented_device("riscv.lowrisc.ibex.rstmgr", + memmap[IBEX_DEV_RSTMGR].base, memmap[IBEX_DEV_RSTMGR].size); + create_unimplemented_device("riscv.lowrisc.ibex.clkmgr", + memmap[IBEX_DEV_CLKMGR].base, memmap[IBEX_DEV_CLKMGR].size); + create_unimplemented_device("riscv.lowrisc.ibex.aes", + memmap[IBEX_DEV_AES].base, memmap[IBEX_DEV_AES].size); + create_unimplemented_device("riscv.lowrisc.ibex.hmac", + memmap[IBEX_DEV_HMAC].base, memmap[IBEX_DEV_HMAC].size); + create_unimplemented_device("riscv.lowrisc.ibex.pinmux", + memmap[IBEX_DEV_PINMUX].base, memmap[IBEX_DEV_PINMUX].size); + create_unimplemented_device("riscv.lowrisc.ibex.alert_handler", + memmap[IBEX_DEV_ALERT_HANDLER].base, memmap[IBEX_DEV_ALERT_HANDLER].size); + create_unimplemented_device("riscv.lowrisc.ibex.nmi_gen", + memmap[IBEX_DEV_NMI_GEN].base, memmap[IBEX_DEV_NMI_GEN].size); + create_unimplemented_device("riscv.lowrisc.ibex.usbdev", + memmap[IBEX_DEV_USBDEV].base, memmap[IBEX_DEV_USBDEV].size); + create_unimplemented_device("riscv.lowrisc.ibex.padctrl", + memmap[IBEX_DEV_PADCTRL].base, memmap[IBEX_DEV_PADCTRL].size); +} + +static void lowrisc_ibex_soc_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = lowrisc_ibex_soc_realize; + /* Reason: Uses serial_hds in realize function, thus can't be used twice */ + dc->user_creatable = false; +} + +static const TypeInfo lowrisc_ibex_soc_type_info = { + .name = TYPE_RISCV_IBEX_SOC, + .parent = TYPE_DEVICE, + .instance_size = sizeof(LowRISCIbexSoCState), + .instance_init = lowrisc_ibex_soc_init, + .class_init = lowrisc_ibex_soc_class_init, +}; + +static void lowrisc_ibex_soc_register_types(void) +{ + type_register_static(&lowrisc_ibex_soc_type_info); +} + +type_init(lowrisc_ibex_soc_register_types) diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c index 276a9baca084cb72c779a84311aa29b0910bc260..613ea2aaa0bc58771f5547498d796d15b32a6c08 100644 --- a/hw/riscv/riscv_hart.c +++ b/hw/riscv/riscv_hart.c @@ -31,6 +31,8 @@ static Property riscv_harts_props[] = { DEFINE_PROP_UINT32("num-harts", RISCVHartArrayState, num_harts, 1), DEFINE_PROP_UINT32("hartid-base", RISCVHartArrayState, hartid_base, 0), DEFINE_PROP_STRING("cpu-type", RISCVHartArrayState, cpu_type), + DEFINE_PROP_UINT64("resetvec", RISCVHartArrayState, resetvec, + DEFAULT_RSTVEC), DEFINE_PROP_END_OF_LIST(), }; @@ -40,22 +42,14 @@ static void riscv_harts_cpu_reset(void *opaque) cpu_reset(CPU(cpu)); } -static void riscv_hart_realize(RISCVHartArrayState *s, int idx, +static bool riscv_hart_realize(RISCVHartArrayState *s, int idx, char *cpu_type, Error **errp) { - Error *err = NULL; - - object_initialize_child(OBJECT(s), "harts[*]", &s->harts[idx], - sizeof(RISCVCPU), cpu_type, - &error_abort, NULL); + object_initialize_child(OBJECT(s), "harts[*]", &s->harts[idx], cpu_type); + qdev_prop_set_uint64(DEVICE(&s->harts[idx]), "resetvec", s->resetvec); s->harts[idx].env.mhartid = s->hartid_base + idx; qemu_register_reset(riscv_harts_cpu_reset, &s->harts[idx]); - object_property_set_bool(OBJECT(&s->harts[idx]), true, - "realized", &err); - if (err) { - error_propagate(errp, err); - return; - } + return qdev_realize(DEVICE(&s->harts[idx]), NULL, errp); } static void riscv_harts_realize(DeviceState *dev, Error **errp) @@ -66,7 +60,9 @@ static void riscv_harts_realize(DeviceState *dev, Error **errp) s->harts = g_new0(RISCVCPU, s->num_harts); for (n = 0; n < s->num_harts; n++) { - riscv_hart_realize(s, n, s->cpu_type, errp); + if (!riscv_hart_realize(s, n, s->cpu_type, errp)) { + return; + } } } diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index bd122e71aead0ef67967951fedb5a096d59367ef..59bac4cc9ad5125b5fb25eae7db73696136099e6 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -39,12 +39,12 @@ #include "hw/misc/unimp.h" #include "target/riscv/cpu.h" #include "hw/riscv/riscv_hart.h" -#include "hw/riscv/sifive_plic.h" -#include "hw/riscv/sifive_clint.h" -#include "hw/riscv/sifive_uart.h" #include "hw/riscv/sifive_e.h" -#include "hw/riscv/sifive_e_prci.h" #include "hw/riscv/boot.h" +#include "hw/char/sifive_uart.h" +#include "hw/intc/sifive_clint.h" +#include "hw/intc/sifive_plic.h" +#include "hw/misc/sifive_e_prci.h" #include "chardev/char.h" #include "sysemu/arch_init.h" #include "sysemu/sysemu.h" @@ -54,104 +54,155 @@ static const struct MemmapEntry { hwaddr base; hwaddr size; } sifive_e_memmap[] = { - [SIFIVE_E_DEBUG] = { 0x0, 0x100 }, - [SIFIVE_E_MROM] = { 0x1000, 0x2000 }, - [SIFIVE_E_OTP] = { 0x20000, 0x2000 }, - [SIFIVE_E_CLINT] = { 0x2000000, 0x10000 }, - [SIFIVE_E_PLIC] = { 0xc000000, 0x4000000 }, - [SIFIVE_E_AON] = { 0x10000000, 0x8000 }, - [SIFIVE_E_PRCI] = { 0x10008000, 0x8000 }, - [SIFIVE_E_OTP_CTRL] = { 0x10010000, 0x1000 }, - [SIFIVE_E_GPIO0] = { 0x10012000, 0x1000 }, - [SIFIVE_E_UART0] = { 0x10013000, 0x1000 }, - [SIFIVE_E_QSPI0] = { 0x10014000, 0x1000 }, - [SIFIVE_E_PWM0] = { 0x10015000, 0x1000 }, - [SIFIVE_E_UART1] = { 0x10023000, 0x1000 }, - [SIFIVE_E_QSPI1] = { 0x10024000, 0x1000 }, - [SIFIVE_E_PWM1] = { 0x10025000, 0x1000 }, - [SIFIVE_E_QSPI2] = { 0x10034000, 0x1000 }, - [SIFIVE_E_PWM2] = { 0x10035000, 0x1000 }, - [SIFIVE_E_XIP] = { 0x20000000, 0x20000000 }, - [SIFIVE_E_DTIM] = { 0x80000000, 0x4000 } + [SIFIVE_E_DEV_DEBUG] = { 0x0, 0x1000 }, + [SIFIVE_E_DEV_MROM] = { 0x1000, 0x2000 }, + [SIFIVE_E_DEV_OTP] = { 0x20000, 0x2000 }, + [SIFIVE_E_DEV_CLINT] = { 0x2000000, 0x10000 }, + [SIFIVE_E_DEV_PLIC] = { 0xc000000, 0x4000000 }, + [SIFIVE_E_DEV_AON] = { 0x10000000, 0x8000 }, + [SIFIVE_E_DEV_PRCI] = { 0x10008000, 0x8000 }, + [SIFIVE_E_DEV_OTP_CTRL] = { 0x10010000, 0x1000 }, + [SIFIVE_E_DEV_GPIO0] = { 0x10012000, 0x1000 }, + [SIFIVE_E_DEV_UART0] = { 0x10013000, 0x1000 }, + [SIFIVE_E_DEV_QSPI0] = { 0x10014000, 0x1000 }, + [SIFIVE_E_DEV_PWM0] = { 0x10015000, 0x1000 }, + [SIFIVE_E_DEV_UART1] = { 0x10023000, 0x1000 }, + [SIFIVE_E_DEV_QSPI1] = { 0x10024000, 0x1000 }, + [SIFIVE_E_DEV_PWM1] = { 0x10025000, 0x1000 }, + [SIFIVE_E_DEV_QSPI2] = { 0x10034000, 0x1000 }, + [SIFIVE_E_DEV_PWM2] = { 0x10035000, 0x1000 }, + [SIFIVE_E_DEV_XIP] = { 0x20000000, 0x20000000 }, + [SIFIVE_E_DEV_DTIM] = { 0x80000000, 0x4000 } }; -static void riscv_sifive_e_init(MachineState *machine) +static void sifive_e_machine_init(MachineState *machine) { const struct MemmapEntry *memmap = sifive_e_memmap; - SiFiveEState *s = g_new0(SiFiveEState, 1); + SiFiveEState *s = RISCV_E_MACHINE(machine); MemoryRegion *sys_mem = get_system_memory(); MemoryRegion *main_mem = g_new(MemoryRegion, 1); int i; /* Initialize SoC */ - object_initialize_child(OBJECT(machine), "soc", &s->soc, - sizeof(s->soc), TYPE_RISCV_E_SOC, - &error_abort, NULL); - object_property_set_bool(OBJECT(&s->soc), true, "realized", - &error_abort); + object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_E_SOC); + qdev_realize(DEVICE(&s->soc), NULL, &error_abort); /* Data Tightly Integrated Memory */ memory_region_init_ram(main_mem, NULL, "riscv.sifive.e.ram", - memmap[SIFIVE_E_DTIM].size, &error_fatal); + memmap[SIFIVE_E_DEV_DTIM].size, &error_fatal); memory_region_add_subregion(sys_mem, - memmap[SIFIVE_E_DTIM].base, main_mem); + memmap[SIFIVE_E_DEV_DTIM].base, main_mem); /* Mask ROM reset vector */ - uint32_t reset_vec[2] = { - 0x204002b7, /* 0x1000: lui t0,0x20400 */ - 0x00028067, /* 0x1004: jr t0 */ - }; + uint32_t reset_vec[4]; + + if (s->revb) { + reset_vec[1] = 0x200102b7; /* 0x1004: lui t0,0x20010 */ + } else { + reset_vec[1] = 0x204002b7; /* 0x1004: lui t0,0x20400 */ + } + reset_vec[2] = 0x00028067; /* 0x1008: jr t0 */ + + reset_vec[0] = reset_vec[3] = 0; /* copy in the reset vector in little_endian byte order */ for (i = 0; i < sizeof(reset_vec) >> 2; i++) { reset_vec[i] = cpu_to_le32(reset_vec[i]); } rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec), - memmap[SIFIVE_E_MROM].base, &address_space_memory); + memmap[SIFIVE_E_DEV_MROM].base, &address_space_memory); if (machine->kernel_filename) { - riscv_load_kernel(machine->kernel_filename, NULL); + riscv_load_kernel(machine->kernel_filename, + memmap[SIFIVE_E_DEV_DTIM].base, NULL); } } -static void riscv_sifive_e_soc_init(Object *obj) +static bool sifive_e_machine_get_revb(Object *obj, Error **errp) +{ + SiFiveEState *s = RISCV_E_MACHINE(obj); + + return s->revb; +} + +static void sifive_e_machine_set_revb(Object *obj, bool value, Error **errp) +{ + SiFiveEState *s = RISCV_E_MACHINE(obj); + + s->revb = value; +} + +static void sifive_e_machine_instance_init(Object *obj) +{ + SiFiveEState *s = RISCV_E_MACHINE(obj); + + s->revb = false; +} + +static void sifive_e_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "RISC-V Board compatible with SiFive E SDK"; + mc->init = sifive_e_machine_init; + mc->max_cpus = 1; + mc->default_cpu_type = SIFIVE_E_CPU; + + object_class_property_add_bool(oc, "revb", sifive_e_machine_get_revb, + sifive_e_machine_set_revb); + object_class_property_set_description(oc, "revb", + "Set on to tell QEMU that it should model " + "the revB HiFive1 board"); +} + +static const TypeInfo sifive_e_machine_typeinfo = { + .name = MACHINE_TYPE_NAME("sifive_e"), + .parent = TYPE_MACHINE, + .class_init = sifive_e_machine_class_init, + .instance_init = sifive_e_machine_instance_init, + .instance_size = sizeof(SiFiveEState), +}; + +static void sifive_e_machine_init_register_types(void) +{ + type_register_static(&sifive_e_machine_typeinfo); +} + +type_init(sifive_e_machine_init_register_types) + +static void sifive_e_soc_init(Object *obj) { MachineState *ms = MACHINE(qdev_get_machine()); SiFiveESoCState *s = RISCV_E_SOC(obj); - object_initialize_child(obj, "cpus", &s->cpus, - sizeof(s->cpus), TYPE_RISCV_HART_ARRAY, - &error_abort, NULL); - object_property_set_int(OBJECT(&s->cpus), ms->smp.cpus, "num-harts", + object_initialize_child(obj, "cpus", &s->cpus, TYPE_RISCV_HART_ARRAY); + object_property_set_int(OBJECT(&s->cpus), "num-harts", ms->smp.cpus, &error_abort); - sysbus_init_child_obj(obj, "riscv.sifive.e.gpio0", - &s->gpio, sizeof(s->gpio), - TYPE_SIFIVE_GPIO); + object_property_set_int(OBJECT(&s->cpus), "resetvec", 0x1004, &error_abort); + object_initialize_child(obj, "riscv.sifive.e.gpio0", &s->gpio, + TYPE_SIFIVE_GPIO); } -static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) +static void sifive_e_soc_realize(DeviceState *dev, Error **errp) { MachineState *ms = MACHINE(qdev_get_machine()); const struct MemmapEntry *memmap = sifive_e_memmap; - Error *err = NULL; - SiFiveESoCState *s = RISCV_E_SOC(dev); MemoryRegion *sys_mem = get_system_memory(); - object_property_set_str(OBJECT(&s->cpus), ms->cpu_type, "cpu-type", - &error_abort); - object_property_set_bool(OBJECT(&s->cpus), true, "realized", + object_property_set_str(OBJECT(&s->cpus), "cpu-type", ms->cpu_type, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_abort); /* Mask ROM */ memory_region_init_rom(&s->mask_rom, OBJECT(dev), "riscv.sifive.e.mrom", - memmap[SIFIVE_E_MROM].size, &error_fatal); + memmap[SIFIVE_E_DEV_MROM].size, &error_fatal); memory_region_add_subregion(sys_mem, - memmap[SIFIVE_E_MROM].base, &s->mask_rom); + memmap[SIFIVE_E_DEV_MROM].base, &s->mask_rom); /* MMIO */ - s->plic = sifive_plic_create(memmap[SIFIVE_E_PLIC].base, + s->plic = sifive_plic_create(memmap[SIFIVE_E_DEV_PLIC].base, (char *)SIFIVE_E_PLIC_HART_CONFIG, 0, SIFIVE_E_PLIC_NUM_SOURCES, SIFIVE_E_PLIC_NUM_PRIORITIES, @@ -161,24 +212,23 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) SIFIVE_E_PLIC_ENABLE_STRIDE, SIFIVE_E_PLIC_CONTEXT_BASE, SIFIVE_E_PLIC_CONTEXT_STRIDE, - memmap[SIFIVE_E_PLIC].size); - sifive_clint_create(memmap[SIFIVE_E_CLINT].base, - memmap[SIFIVE_E_CLINT].size, 0, ms->smp.cpus, - SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false); + memmap[SIFIVE_E_DEV_PLIC].size); + sifive_clint_create(memmap[SIFIVE_E_DEV_CLINT].base, + memmap[SIFIVE_E_DEV_CLINT].size, 0, ms->smp.cpus, + SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, + SIFIVE_CLINT_TIMEBASE_FREQ, false); create_unimplemented_device("riscv.sifive.e.aon", - memmap[SIFIVE_E_AON].base, memmap[SIFIVE_E_AON].size); - sifive_e_prci_create(memmap[SIFIVE_E_PRCI].base); + memmap[SIFIVE_E_DEV_AON].base, memmap[SIFIVE_E_DEV_AON].size); + sifive_e_prci_create(memmap[SIFIVE_E_DEV_PRCI].base); /* GPIO */ - object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) { return; } /* Map GPIO registers */ - sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio), 0, memmap[SIFIVE_E_GPIO0].base); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio), 0, memmap[SIFIVE_E_DEV_GPIO0].base); /* Pass all GPIOs to the SOC layer so they are available to the board */ qdev_pass_gpios(DEVICE(&s->gpio), dev, NULL); @@ -190,60 +240,50 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) SIFIVE_E_GPIO0_IRQ0 + i)); } - sifive_uart_create(sys_mem, memmap[SIFIVE_E_UART0].base, + sifive_uart_create(sys_mem, memmap[SIFIVE_E_DEV_UART0].base, serial_hd(0), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_E_UART0_IRQ)); create_unimplemented_device("riscv.sifive.e.qspi0", - memmap[SIFIVE_E_QSPI0].base, memmap[SIFIVE_E_QSPI0].size); + memmap[SIFIVE_E_DEV_QSPI0].base, memmap[SIFIVE_E_DEV_QSPI0].size); create_unimplemented_device("riscv.sifive.e.pwm0", - memmap[SIFIVE_E_PWM0].base, memmap[SIFIVE_E_PWM0].size); - sifive_uart_create(sys_mem, memmap[SIFIVE_E_UART1].base, + memmap[SIFIVE_E_DEV_PWM0].base, memmap[SIFIVE_E_DEV_PWM0].size); + sifive_uart_create(sys_mem, memmap[SIFIVE_E_DEV_UART1].base, serial_hd(1), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_E_UART1_IRQ)); create_unimplemented_device("riscv.sifive.e.qspi1", - memmap[SIFIVE_E_QSPI1].base, memmap[SIFIVE_E_QSPI1].size); + memmap[SIFIVE_E_DEV_QSPI1].base, memmap[SIFIVE_E_DEV_QSPI1].size); create_unimplemented_device("riscv.sifive.e.pwm1", - memmap[SIFIVE_E_PWM1].base, memmap[SIFIVE_E_PWM1].size); + memmap[SIFIVE_E_DEV_PWM1].base, memmap[SIFIVE_E_DEV_PWM1].size); create_unimplemented_device("riscv.sifive.e.qspi2", - memmap[SIFIVE_E_QSPI2].base, memmap[SIFIVE_E_QSPI2].size); + memmap[SIFIVE_E_DEV_QSPI2].base, memmap[SIFIVE_E_DEV_QSPI2].size); create_unimplemented_device("riscv.sifive.e.pwm2", - memmap[SIFIVE_E_PWM2].base, memmap[SIFIVE_E_PWM2].size); + memmap[SIFIVE_E_DEV_PWM2].base, memmap[SIFIVE_E_DEV_PWM2].size); /* Flash memory */ memory_region_init_rom(&s->xip_mem, OBJECT(dev), "riscv.sifive.e.xip", - memmap[SIFIVE_E_XIP].size, &error_fatal); - memory_region_add_subregion(sys_mem, memmap[SIFIVE_E_XIP].base, + memmap[SIFIVE_E_DEV_XIP].size, &error_fatal); + memory_region_add_subregion(sys_mem, memmap[SIFIVE_E_DEV_XIP].base, &s->xip_mem); } -static void riscv_sifive_e_machine_init(MachineClass *mc) -{ - mc->desc = "RISC-V Board compatible with SiFive E SDK"; - mc->init = riscv_sifive_e_init; - mc->max_cpus = 1; - mc->default_cpu_type = SIFIVE_E_CPU; -} - -DEFINE_MACHINE("sifive_e", riscv_sifive_e_machine_init) - -static void riscv_sifive_e_soc_class_init(ObjectClass *oc, void *data) +static void sifive_e_soc_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); - dc->realize = riscv_sifive_e_soc_realize; + dc->realize = sifive_e_soc_realize; /* Reason: Uses serial_hds in realize function, thus can't be used twice */ dc->user_creatable = false; } -static const TypeInfo riscv_sifive_e_soc_type_info = { +static const TypeInfo sifive_e_soc_type_info = { .name = TYPE_RISCV_E_SOC, .parent = TYPE_DEVICE, .instance_size = sizeof(SiFiveESoCState), - .instance_init = riscv_sifive_e_soc_init, - .class_init = riscv_sifive_e_soc_class_init, + .instance_init = sifive_e_soc_init, + .class_init = sifive_e_soc_class_init, }; -static void riscv_sifive_e_soc_register_types(void) +static void sifive_e_soc_register_types(void) { - type_register_static(&riscv_sifive_e_soc_type_info); + type_register_static(&sifive_e_soc_type_info); } -type_init(riscv_sifive_e_soc_register_types) +type_init(sifive_e_soc_register_types) diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 53e48e2ff5a6cf9255fa00aecc753e1c3dac06f7..2f19a9cda2ef1c8a23e120cece66be7af0885de1 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -11,8 +11,10 @@ * 1) CLINT (Core Level Interruptor) * 2) PLIC (Platform Level Interrupt Controller) * 3) PRCI (Power, Reset, Clock, Interrupt) - * 4) OTP (One-Time Programmable) memory with stored serial number - * 5) GEM (Gigabit Ethernet Controller) and management block + * 4) GPIO (General Purpose Input/Output Controller) + * 5) OTP (One-Time Programmable) memory with stored serial number + * 6) GEM (Gigabit Ethernet Controller) and management block + * 7) DMA (Direct Memory Access Controller) * * This board currently generates devicetree dynamically that indicates at least * two harts and up to five harts. @@ -36,6 +38,7 @@ #include "qapi/error.h" #include "qapi/visitor.h" #include "hw/boards.h" +#include "hw/irq.h" #include "hw/loader.h" #include "hw/sysbus.h" #include "hw/char/serial.h" @@ -43,43 +46,47 @@ #include "hw/misc/unimp.h" #include "target/riscv/cpu.h" #include "hw/riscv/riscv_hart.h" -#include "hw/riscv/sifive_plic.h" -#include "hw/riscv/sifive_clint.h" -#include "hw/riscv/sifive_uart.h" #include "hw/riscv/sifive_u.h" #include "hw/riscv/boot.h" +#include "hw/char/sifive_uart.h" +#include "hw/intc/sifive_clint.h" +#include "hw/intc/sifive_plic.h" #include "chardev/char.h" #include "net/eth.h" #include "sysemu/arch_init.h" #include "sysemu/device_tree.h" +#include "sysemu/runstate.h" #include "sysemu/sysemu.h" -#include "exec/address-spaces.h" #include #if defined(TARGET_RISCV32) -# define BIOS_FILENAME "opensbi-riscv32-sifive_u-fw_jump.bin" +# define BIOS_FILENAME "opensbi-riscv32-generic-fw_dynamic.bin" #else -# define BIOS_FILENAME "opensbi-riscv64-sifive_u-fw_jump.bin" +# define BIOS_FILENAME "opensbi-riscv64-generic-fw_dynamic.bin" #endif static const struct MemmapEntry { hwaddr base; hwaddr size; } sifive_u_memmap[] = { - [SIFIVE_U_DEBUG] = { 0x0, 0x100 }, - [SIFIVE_U_MROM] = { 0x1000, 0x11000 }, - [SIFIVE_U_CLINT] = { 0x2000000, 0x10000 }, - [SIFIVE_U_L2LIM] = { 0x8000000, 0x2000000 }, - [SIFIVE_U_PLIC] = { 0xc000000, 0x4000000 }, - [SIFIVE_U_PRCI] = { 0x10000000, 0x1000 }, - [SIFIVE_U_UART0] = { 0x10010000, 0x1000 }, - [SIFIVE_U_UART1] = { 0x10011000, 0x1000 }, - [SIFIVE_U_OTP] = { 0x10070000, 0x1000 }, - [SIFIVE_U_FLASH0] = { 0x20000000, 0x10000000 }, - [SIFIVE_U_DRAM] = { 0x80000000, 0x0 }, - [SIFIVE_U_GEM] = { 0x10090000, 0x2000 }, - [SIFIVE_U_GEM_MGMT] = { 0x100a0000, 0x1000 }, + [SIFIVE_U_DEV_DEBUG] = { 0x0, 0x100 }, + [SIFIVE_U_DEV_MROM] = { 0x1000, 0xf000 }, + [SIFIVE_U_DEV_CLINT] = { 0x2000000, 0x10000 }, + [SIFIVE_U_DEV_L2CC] = { 0x2010000, 0x1000 }, + [SIFIVE_U_DEV_PDMA] = { 0x3000000, 0x100000 }, + [SIFIVE_U_DEV_L2LIM] = { 0x8000000, 0x2000000 }, + [SIFIVE_U_DEV_PLIC] = { 0xc000000, 0x4000000 }, + [SIFIVE_U_DEV_PRCI] = { 0x10000000, 0x1000 }, + [SIFIVE_U_DEV_UART0] = { 0x10010000, 0x1000 }, + [SIFIVE_U_DEV_UART1] = { 0x10011000, 0x1000 }, + [SIFIVE_U_DEV_GPIO] = { 0x10060000, 0x1000 }, + [SIFIVE_U_DEV_OTP] = { 0x10070000, 0x1000 }, + [SIFIVE_U_DEV_GEM] = { 0x10090000, 0x2000 }, + [SIFIVE_U_DEV_GEM_MGMT] = { 0x100a0000, 0x1000 }, + [SIFIVE_U_DEV_DMC] = { 0x100b0000, 0x10000 }, + [SIFIVE_U_DEV_FLASH0] = { 0x20000000, 0x10000000 }, + [SIFIVE_U_DEV_DRAM] = { 0x80000000, 0x0 }, }; #define OTP_SERIAL 1 @@ -93,14 +100,25 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, int cpu; uint32_t *cells; char *nodename; + const char *dtb_filename; char ethclk_names[] = "pclk\0hclk"; - uint32_t plic_phandle, prci_phandle, phandle = 1; + uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1; uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle; - fdt = s->fdt = create_device_tree(&s->fdt_size); - if (!fdt) { - error_report("create_device_tree() failed"); - exit(1); + dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb"); + if (dtb_filename) { + fdt = s->fdt = load_device_tree(dtb_filename, &s->fdt_size); + if (!fdt) { + error_report("load_device_tree() failed"); + exit(1); + } + goto update_bootargs; + } else { + fdt = s->fdt = create_device_tree(&s->fdt_size); + if (!fdt) { + error_report("create_device_tree() failed"); + exit(1); + } } qemu_fdt_setprop_string(fdt, "/", "model", "SiFive HiFive Unleashed A00"); @@ -138,10 +156,10 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, g_free(nodename); nodename = g_strdup_printf("/memory@%lx", - (long)memmap[SIFIVE_U_DRAM].base); + (long)memmap[SIFIVE_U_DEV_DRAM].base); qemu_fdt_add_subnode(fdt, nodename); qemu_fdt_setprop_cells(fdt, nodename, "reg", - memmap[SIFIVE_U_DRAM].base >> 32, memmap[SIFIVE_U_DRAM].base, + memmap[SIFIVE_U_DEV_DRAM].base >> 32, memmap[SIFIVE_U_DEV_DRAM].base, mem_size >> 32, mem_size); qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory"); g_free(nodename); @@ -196,28 +214,39 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, g_free(nodename); } nodename = g_strdup_printf("/soc/clint@%lx", - (long)memmap[SIFIVE_U_CLINT].base); + (long)memmap[SIFIVE_U_DEV_CLINT].base); qemu_fdt_add_subnode(fdt, nodename); qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv,clint0"); qemu_fdt_setprop_cells(fdt, nodename, "reg", - 0x0, memmap[SIFIVE_U_CLINT].base, - 0x0, memmap[SIFIVE_U_CLINT].size); + 0x0, memmap[SIFIVE_U_DEV_CLINT].base, + 0x0, memmap[SIFIVE_U_DEV_CLINT].size); qemu_fdt_setprop(fdt, nodename, "interrupts-extended", cells, ms->smp.cpus * sizeof(uint32_t) * 4); g_free(cells); g_free(nodename); + nodename = g_strdup_printf("/soc/otp@%lx", + (long)memmap[SIFIVE_U_DEV_OTP].base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_cell(fdt, nodename, "fuse-count", SIFIVE_U_OTP_REG_SIZE); + qemu_fdt_setprop_cells(fdt, nodename, "reg", + 0x0, memmap[SIFIVE_U_DEV_OTP].base, + 0x0, memmap[SIFIVE_U_DEV_OTP].size); + qemu_fdt_setprop_string(fdt, nodename, "compatible", + "sifive,fu540-c000-otp"); + g_free(nodename); + prci_phandle = phandle++; nodename = g_strdup_printf("/soc/clock-controller@%lx", - (long)memmap[SIFIVE_U_PRCI].base); + (long)memmap[SIFIVE_U_DEV_PRCI].base); qemu_fdt_add_subnode(fdt, nodename); qemu_fdt_setprop_cell(fdt, nodename, "phandle", prci_phandle); qemu_fdt_setprop_cell(fdt, nodename, "#clock-cells", 0x1); qemu_fdt_setprop_cells(fdt, nodename, "clocks", hfclk_phandle, rtcclk_phandle); qemu_fdt_setprop_cells(fdt, nodename, "reg", - 0x0, memmap[SIFIVE_U_PRCI].base, - 0x0, memmap[SIFIVE_U_PRCI].size); + 0x0, memmap[SIFIVE_U_DEV_PRCI].base, + 0x0, memmap[SIFIVE_U_DEV_PRCI].size); qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,fu540-c000-prci"); g_free(nodename); @@ -241,7 +270,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, g_free(nodename); } nodename = g_strdup_printf("/soc/interrupt-controller@%lx", - (long)memmap[SIFIVE_U_PLIC].base); + (long)memmap[SIFIVE_U_DEV_PLIC].base); qemu_fdt_add_subnode(fdt, nodename); qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 1); qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv,plic0"); @@ -249,25 +278,89 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop(fdt, nodename, "interrupts-extended", cells, (ms->smp.cpus * 4 - 2) * sizeof(uint32_t)); qemu_fdt_setprop_cells(fdt, nodename, "reg", - 0x0, memmap[SIFIVE_U_PLIC].base, - 0x0, memmap[SIFIVE_U_PLIC].size); + 0x0, memmap[SIFIVE_U_DEV_PLIC].base, + 0x0, memmap[SIFIVE_U_DEV_PLIC].size); qemu_fdt_setprop_cell(fdt, nodename, "riscv,ndev", 0x35); qemu_fdt_setprop_cell(fdt, nodename, "phandle", plic_phandle); plic_phandle = qemu_fdt_get_phandle(fdt, nodename); g_free(cells); g_free(nodename); + gpio_phandle = phandle++; + nodename = g_strdup_printf("/soc/gpio@%lx", + (long)memmap[SIFIVE_U_DEV_GPIO].base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_cell(fdt, nodename, "phandle", gpio_phandle); + qemu_fdt_setprop_cells(fdt, nodename, "clocks", + prci_phandle, PRCI_CLK_TLCLK); + qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 2); + qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0); + qemu_fdt_setprop_cell(fdt, nodename, "#gpio-cells", 2); + qemu_fdt_setprop(fdt, nodename, "gpio-controller", NULL, 0); + qemu_fdt_setprop_cells(fdt, nodename, "reg", + 0x0, memmap[SIFIVE_U_DEV_GPIO].base, + 0x0, memmap[SIFIVE_U_DEV_GPIO].size); + qemu_fdt_setprop_cells(fdt, nodename, "interrupts", SIFIVE_U_GPIO_IRQ0, + SIFIVE_U_GPIO_IRQ1, SIFIVE_U_GPIO_IRQ2, SIFIVE_U_GPIO_IRQ3, + SIFIVE_U_GPIO_IRQ4, SIFIVE_U_GPIO_IRQ5, SIFIVE_U_GPIO_IRQ6, + SIFIVE_U_GPIO_IRQ7, SIFIVE_U_GPIO_IRQ8, SIFIVE_U_GPIO_IRQ9, + SIFIVE_U_GPIO_IRQ10, SIFIVE_U_GPIO_IRQ11, SIFIVE_U_GPIO_IRQ12, + SIFIVE_U_GPIO_IRQ13, SIFIVE_U_GPIO_IRQ14, SIFIVE_U_GPIO_IRQ15); + qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,gpio0"); + g_free(nodename); + + nodename = g_strdup_printf("/gpio-restart"); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_cells(fdt, nodename, "gpios", gpio_phandle, 10, 1); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "gpio-restart"); + g_free(nodename); + + nodename = g_strdup_printf("/soc/dma@%lx", + (long)memmap[SIFIVE_U_DEV_PDMA].base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_cell(fdt, nodename, "#dma-cells", 1); + qemu_fdt_setprop_cells(fdt, nodename, "interrupts", + SIFIVE_U_PDMA_IRQ0, SIFIVE_U_PDMA_IRQ1, SIFIVE_U_PDMA_IRQ2, + SIFIVE_U_PDMA_IRQ3, SIFIVE_U_PDMA_IRQ4, SIFIVE_U_PDMA_IRQ5, + SIFIVE_U_PDMA_IRQ6, SIFIVE_U_PDMA_IRQ7); + qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle); + qemu_fdt_setprop_cells(fdt, nodename, "reg", + 0x0, memmap[SIFIVE_U_DEV_PDMA].base, + 0x0, memmap[SIFIVE_U_DEV_PDMA].size); + qemu_fdt_setprop_string(fdt, nodename, "compatible", + "sifive,fu540-c000-pdma"); + g_free(nodename); + + nodename = g_strdup_printf("/soc/cache-controller@%lx", + (long)memmap[SIFIVE_U_DEV_L2CC].base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_cells(fdt, nodename, "reg", + 0x0, memmap[SIFIVE_U_DEV_L2CC].base, + 0x0, memmap[SIFIVE_U_DEV_L2CC].size); + qemu_fdt_setprop_cells(fdt, nodename, "interrupts", + SIFIVE_U_L2CC_IRQ0, SIFIVE_U_L2CC_IRQ1, SIFIVE_U_L2CC_IRQ2); + qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle); + qemu_fdt_setprop(fdt, nodename, "cache-unified", NULL, 0); + qemu_fdt_setprop_cell(fdt, nodename, "cache-size", 2097152); + qemu_fdt_setprop_cell(fdt, nodename, "cache-sets", 1024); + qemu_fdt_setprop_cell(fdt, nodename, "cache-level", 2); + qemu_fdt_setprop_cell(fdt, nodename, "cache-block-size", 64); + qemu_fdt_setprop_string(fdt, nodename, "compatible", + "sifive,fu540-c000-ccache"); + g_free(nodename); + phy_phandle = phandle++; nodename = g_strdup_printf("/soc/ethernet@%lx", - (long)memmap[SIFIVE_U_GEM].base); + (long)memmap[SIFIVE_U_DEV_GEM].base); qemu_fdt_add_subnode(fdt, nodename); qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,fu540-c000-gem"); qemu_fdt_setprop_cells(fdt, nodename, "reg", - 0x0, memmap[SIFIVE_U_GEM].base, - 0x0, memmap[SIFIVE_U_GEM].size, - 0x0, memmap[SIFIVE_U_GEM_MGMT].base, - 0x0, memmap[SIFIVE_U_GEM_MGMT].size); + 0x0, memmap[SIFIVE_U_DEV_GEM].base, + 0x0, memmap[SIFIVE_U_DEV_GEM].size, + 0x0, memmap[SIFIVE_U_DEV_GEM_MGMT].base, + 0x0, memmap[SIFIVE_U_DEV_GEM_MGMT].size); qemu_fdt_setprop_string(fdt, nodename, "reg-names", "control"); qemu_fdt_setprop_string(fdt, nodename, "phy-mode", "gmii"); qemu_fdt_setprop_cell(fdt, nodename, "phy-handle", phy_phandle); @@ -288,19 +381,19 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, g_free(nodename); nodename = g_strdup_printf("/soc/ethernet@%lx/ethernet-phy@0", - (long)memmap[SIFIVE_U_GEM].base); + (long)memmap[SIFIVE_U_DEV_GEM].base); qemu_fdt_add_subnode(fdt, nodename); qemu_fdt_setprop_cell(fdt, nodename, "phandle", phy_phandle); qemu_fdt_setprop_cell(fdt, nodename, "reg", 0x0); g_free(nodename); nodename = g_strdup_printf("/soc/serial@%lx", - (long)memmap[SIFIVE_U_UART0].base); + (long)memmap[SIFIVE_U_DEV_UART0].base); qemu_fdt_add_subnode(fdt, nodename); qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,uart0"); qemu_fdt_setprop_cells(fdt, nodename, "reg", - 0x0, memmap[SIFIVE_U_UART0].base, - 0x0, memmap[SIFIVE_U_UART0].size); + 0x0, memmap[SIFIVE_U_DEV_UART0].base, + 0x0, memmap[SIFIVE_U_DEV_UART0].size); qemu_fdt_setprop_cells(fdt, nodename, "clocks", prci_phandle, PRCI_CLK_TLCLK); qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle); @@ -308,13 +401,22 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_add_subnode(fdt, "/chosen"); qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename); + qemu_fdt_setprop_string(fdt, "/aliases", "serial0", nodename); + + g_free(nodename); + +update_bootargs: if (cmdline) { qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline); } +} - qemu_fdt_setprop_string(fdt, "/aliases", "serial0", nodename); - - g_free(nodename); +static void sifive_u_machine_reset(void *opaque, int n, int level) +{ + /* gpio pin active low triggers reset */ + if (!level) { + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + } } static void sifive_u_machine_init(MachineState *machine) @@ -324,39 +426,76 @@ static void sifive_u_machine_init(MachineState *machine) MemoryRegion *system_memory = get_system_memory(); MemoryRegion *main_mem = g_new(MemoryRegion, 1); MemoryRegion *flash0 = g_new(MemoryRegion, 1); - target_ulong start_addr = memmap[SIFIVE_U_DRAM].base; + target_ulong start_addr = memmap[SIFIVE_U_DEV_DRAM].base; + target_ulong firmware_end_addr, kernel_start_addr; + uint32_t start_addr_hi32 = 0x00000000; int i; + uint32_t fdt_load_addr; + uint64_t kernel_entry; /* Initialize SoC */ - object_initialize_child(OBJECT(machine), "soc", &s->soc, - sizeof(s->soc), TYPE_RISCV_U_SOC, - &error_abort, NULL); - object_property_set_uint(OBJECT(&s->soc), s->serial, "serial", - &error_abort); - object_property_set_bool(OBJECT(&s->soc), true, "realized", - &error_abort); + object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_U_SOC); + object_property_set_uint(OBJECT(&s->soc), "serial", s->serial, + &error_abort); + object_property_set_str(OBJECT(&s->soc), "cpu-type", machine->cpu_type, + &error_abort); + qdev_realize(DEVICE(&s->soc), NULL, &error_abort); /* register RAM */ memory_region_init_ram(main_mem, NULL, "riscv.sifive.u.ram", machine->ram_size, &error_fatal); - memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DRAM].base, + memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DEV_DRAM].base, main_mem); /* register QSPI0 Flash */ memory_region_init_ram(flash0, NULL, "riscv.sifive.u.flash0", - memmap[SIFIVE_U_FLASH0].size, &error_fatal); - memory_region_add_subregion(system_memory, memmap[SIFIVE_U_FLASH0].base, + memmap[SIFIVE_U_DEV_FLASH0].size, &error_fatal); + memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DEV_FLASH0].base, flash0); + /* register gpio-restart */ + qdev_connect_gpio_out(DEVICE(&(s->soc.gpio)), 10, + qemu_allocate_irq(sifive_u_machine_reset, NULL, 0)); + /* create device tree */ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline); - riscv_find_and_load_firmware(machine, BIOS_FILENAME, - memmap[SIFIVE_U_DRAM].base, NULL); + if (s->start_in_flash) { + /* + * If start_in_flash property is given, assign s->msel to a value + * that representing booting from QSPI0 memory-mapped flash. + * + * This also means that when both start_in_flash and msel properties + * are given, start_in_flash takes the precedence over msel. + * + * Note this is to keep backward compatibility not to break existing + * users that use start_in_flash property. + */ + s->msel = MSEL_MEMMAP_QSPI0_FLASH; + } + + switch (s->msel) { + case MSEL_MEMMAP_QSPI0_FLASH: + start_addr = memmap[SIFIVE_U_DEV_FLASH0].base; + break; + case MSEL_L2LIM_QSPI0_FLASH: + case MSEL_L2LIM_QSPI2_SD: + start_addr = memmap[SIFIVE_U_DEV_L2LIM].base; + break; + default: + start_addr = memmap[SIFIVE_U_DEV_DRAM].base; + break; + } + + firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME, + start_addr, NULL); if (machine->kernel_filename) { - uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename, - NULL); + kernel_start_addr = riscv_calc_kernel_start_addr(machine, + firmware_end_addr); + + kernel_entry = riscv_load_kernel(machine->kernel_filename, + kernel_start_addr, NULL); if (machine->initrd_filename) { hwaddr start; @@ -368,46 +507,52 @@ static void sifive_u_machine_init(MachineState *machine) qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-end", end); } + } else { + /* + * If dynamic firmware is used, it doesn't know where is the next mode + * if kernel argument is not set. + */ + kernel_entry = 0; } - if (s->start_in_flash) { - start_addr = memmap[SIFIVE_U_FLASH0].base; - } + /* Compute the fdt load address in dram */ + fdt_load_addr = riscv_load_fdt(memmap[SIFIVE_U_DEV_DRAM].base, + machine->ram_size, s->fdt); + #if defined(TARGET_RISCV64) + start_addr_hi32 = start_addr >> 32; + #endif /* reset vector */ - uint32_t reset_vec[8] = { - 0x00000297, /* 1: auipc t0, %pcrel_hi(dtb) */ - 0x02028593, /* addi a1, t0, %pcrel_lo(1b) */ + uint32_t reset_vec[11] = { + s->msel, /* MSEL pin state */ + 0x00000297, /* 1: auipc t0, %pcrel_hi(fw_dyn) */ + 0x02828613, /* addi a2, t0, %pcrel_lo(1b) */ 0xf1402573, /* csrr a0, mhartid */ #if defined(TARGET_RISCV32) + 0x0202a583, /* lw a1, 32(t0) */ 0x0182a283, /* lw t0, 24(t0) */ #elif defined(TARGET_RISCV64) + 0x0202b583, /* ld a1, 32(t0) */ 0x0182b283, /* ld t0, 24(t0) */ #endif 0x00028067, /* jr t0 */ - 0x00000000, start_addr, /* start: .dword */ + start_addr_hi32, + fdt_load_addr, /* fdt_laddr: .dword */ 0x00000000, - /* dtb: */ + /* fw_dyn: */ }; /* copy in the reset vector in little_endian byte order */ - for (i = 0; i < sizeof(reset_vec) >> 2; i++) { + for (i = 0; i < ARRAY_SIZE(reset_vec); i++) { reset_vec[i] = cpu_to_le32(reset_vec[i]); } rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec), - memmap[SIFIVE_U_MROM].base, &address_space_memory); + memmap[SIFIVE_U_DEV_MROM].base, &address_space_memory); - /* copy in the device tree */ - if (fdt_pack(s->fdt) || fdt_totalsize(s->fdt) > - memmap[SIFIVE_U_MROM].size - sizeof(reset_vec)) { - error_report("not enough space to store device-tree"); - exit(1); - } - qemu_fdt_dumpdtb(s->fdt, fdt_totalsize(s->fdt)); - rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt), - memmap[SIFIVE_U_MROM].base + sizeof(reset_vec), - &address_space_memory); + riscv_rom_copy_firmware_info(memmap[SIFIVE_U_DEV_MROM].base, + memmap[SIFIVE_U_DEV_MROM].size, + sizeof(reset_vec), kernel_entry); } static bool sifive_u_machine_get_start_in_flash(Object *obj, Error **errp) @@ -424,14 +569,16 @@ static void sifive_u_machine_set_start_in_flash(Object *obj, bool value, Error * s->start_in_flash = value; } -static void sifive_u_machine_get_serial(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) +static void sifive_u_machine_get_uint32_prop(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) { visit_type_uint32(v, name, (uint32_t *)opaque, errp); } -static void sifive_u_machine_set_serial(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) +static void sifive_u_machine_set_uint32_prop(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) { visit_type_uint32(v, name, (uint32_t *)opaque, errp); } @@ -441,17 +588,17 @@ static void sifive_u_machine_instance_init(Object *obj) SiFiveUState *s = RISCV_U_MACHINE(obj); s->start_in_flash = false; - object_property_add_bool(obj, "start-in-flash", - sifive_u_machine_get_start_in_flash, - sifive_u_machine_set_start_in_flash); - object_property_set_description(obj, "start-in-flash", - "Set on to tell QEMU's ROM to jump to " - "flash. Otherwise QEMU will jump to DRAM"); + s->msel = 0; + object_property_add(obj, "msel", "uint32", + sifive_u_machine_get_uint32_prop, + sifive_u_machine_set_uint32_prop, NULL, &s->msel); + object_property_set_description(obj, "msel", + "Mode Select (MSEL[3:0]) pin state"); s->serial = OTP_SERIAL; object_property_add(obj, "serial", "uint32", - sifive_u_machine_get_serial, - sifive_u_machine_set_serial, NULL, &s->serial); + sifive_u_machine_get_uint32_prop, + sifive_u_machine_set_uint32_prop, NULL, &s->serial); object_property_set_description(obj, "serial", "Board serial number"); } @@ -463,7 +610,20 @@ static void sifive_u_machine_class_init(ObjectClass *oc, void *data) mc->init = sifive_u_machine_init; mc->max_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + SIFIVE_U_COMPUTE_CPU_COUNT; mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1; +#if defined(TARGET_RISCV32) + mc->default_cpu_type = TYPE_RISCV_CPU_SIFIVE_U34; +#elif defined(TARGET_RISCV64) + mc->default_cpu_type = TYPE_RISCV_CPU_SIFIVE_U54; +#endif mc->default_cpus = mc->min_cpus; + + object_class_property_add_bool(oc, "start-in-flash", + sifive_u_machine_get_start_in_flash, + sifive_u_machine_set_start_in_flash); + object_class_property_set_description(oc, "start-in-flash", + "Set on to tell QEMU's ROM to jump to " + "flash. Otherwise QEMU will jump to DRAM " + "or L2LIM depending on the msel value"); } static const TypeInfo sifive_u_machine_typeinfo = { @@ -481,46 +641,34 @@ static void sifive_u_machine_init_register_types(void) type_init(sifive_u_machine_init_register_types) -static void riscv_sifive_u_soc_init(Object *obj) +static void sifive_u_soc_instance_init(Object *obj) { - MachineState *ms = MACHINE(qdev_get_machine()); SiFiveUSoCState *s = RISCV_U_SOC(obj); - object_initialize_child(obj, "e-cluster", &s->e_cluster, - sizeof(s->e_cluster), TYPE_CPU_CLUSTER, - &error_abort, NULL); + object_initialize_child(obj, "e-cluster", &s->e_cluster, TYPE_CPU_CLUSTER); qdev_prop_set_uint32(DEVICE(&s->e_cluster), "cluster-id", 0); - object_initialize_child(OBJECT(&s->e_cluster), "e-cpus", - &s->e_cpus, sizeof(s->e_cpus), - TYPE_RISCV_HART_ARRAY, &error_abort, - NULL); + object_initialize_child(OBJECT(&s->e_cluster), "e-cpus", &s->e_cpus, + TYPE_RISCV_HART_ARRAY); qdev_prop_set_uint32(DEVICE(&s->e_cpus), "num-harts", 1); qdev_prop_set_uint32(DEVICE(&s->e_cpus), "hartid-base", 0); qdev_prop_set_string(DEVICE(&s->e_cpus), "cpu-type", SIFIVE_E_CPU); + qdev_prop_set_uint64(DEVICE(&s->e_cpus), "resetvec", 0x1004); - object_initialize_child(obj, "u-cluster", &s->u_cluster, - sizeof(s->u_cluster), TYPE_CPU_CLUSTER, - &error_abort, NULL); + object_initialize_child(obj, "u-cluster", &s->u_cluster, TYPE_CPU_CLUSTER); qdev_prop_set_uint32(DEVICE(&s->u_cluster), "cluster-id", 1); - object_initialize_child(OBJECT(&s->u_cluster), "u-cpus", - &s->u_cpus, sizeof(s->u_cpus), - TYPE_RISCV_HART_ARRAY, &error_abort, - NULL); - qdev_prop_set_uint32(DEVICE(&s->u_cpus), "num-harts", ms->smp.cpus - 1); - qdev_prop_set_uint32(DEVICE(&s->u_cpus), "hartid-base", 1); - qdev_prop_set_string(DEVICE(&s->u_cpus), "cpu-type", SIFIVE_U_CPU); - - sysbus_init_child_obj(obj, "prci", &s->prci, sizeof(s->prci), - TYPE_SIFIVE_U_PRCI); - sysbus_init_child_obj(obj, "otp", &s->otp, sizeof(s->otp), - TYPE_SIFIVE_U_OTP); - sysbus_init_child_obj(obj, "gem", &s->gem, sizeof(s->gem), - TYPE_CADENCE_GEM); + object_initialize_child(OBJECT(&s->u_cluster), "u-cpus", &s->u_cpus, + TYPE_RISCV_HART_ARRAY); + + object_initialize_child(obj, "prci", &s->prci, TYPE_SIFIVE_U_PRCI); + object_initialize_child(obj, "otp", &s->otp, TYPE_SIFIVE_U_OTP); + object_initialize_child(obj, "gem", &s->gem, TYPE_CADENCE_GEM); + object_initialize_child(obj, "gpio", &s->gpio, TYPE_SIFIVE_GPIO); + object_initialize_child(obj, "pdma", &s->dma, TYPE_SIFIVE_PDMA); } -static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) +static void sifive_u_soc_realize(DeviceState *dev, Error **errp) { MachineState *ms = MACHINE(qdev_get_machine()); SiFiveUSoCState *s = RISCV_U_SOC(dev); @@ -528,32 +676,31 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) MemoryRegion *system_memory = get_system_memory(); MemoryRegion *mask_rom = g_new(MemoryRegion, 1); MemoryRegion *l2lim_mem = g_new(MemoryRegion, 1); - qemu_irq plic_gpios[SIFIVE_U_PLIC_NUM_SOURCES]; char *plic_hart_config; size_t plic_hart_config_len; int i; - Error *err = NULL; NICInfo *nd = &nd_table[0]; - object_property_set_bool(OBJECT(&s->e_cpus), true, "realized", - &error_abort); - object_property_set_bool(OBJECT(&s->u_cpus), true, "realized", - &error_abort); + qdev_prop_set_uint32(DEVICE(&s->u_cpus), "num-harts", ms->smp.cpus - 1); + qdev_prop_set_uint32(DEVICE(&s->u_cpus), "hartid-base", 1); + qdev_prop_set_string(DEVICE(&s->u_cpus), "cpu-type", s->cpu_type); + qdev_prop_set_uint64(DEVICE(&s->u_cpus), "resetvec", 0x1004); + + sysbus_realize(SYS_BUS_DEVICE(&s->e_cpus), &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->u_cpus), &error_abort); /* * The cluster must be realized after the RISC-V hart array container, * as the container's CPU object is only created on realize, and the * CPU must exist and have been parented into the cluster before the * cluster is realized. */ - object_property_set_bool(OBJECT(&s->e_cluster), true, "realized", - &error_abort); - object_property_set_bool(OBJECT(&s->u_cluster), true, "realized", - &error_abort); + qdev_realize(DEVICE(&s->e_cluster), NULL, &error_abort); + qdev_realize(DEVICE(&s->u_cluster), NULL, &error_abort); /* boot rom */ memory_region_init_rom(mask_rom, OBJECT(dev), "riscv.sifive.u.mrom", - memmap[SIFIVE_U_MROM].size, &error_fatal); - memory_region_add_subregion(system_memory, memmap[SIFIVE_U_MROM].base, + memmap[SIFIVE_U_DEV_MROM].size, &error_fatal); + memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DEV_MROM].base, mask_rom); /* @@ -566,8 +713,8 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) * too generous to misbehaving guests. */ memory_region_init_ram(l2lim_mem, NULL, "riscv.sifive.u.l2lim", - memmap[SIFIVE_U_L2LIM].size, &error_fatal); - memory_region_add_subregion(system_memory, memmap[SIFIVE_U_L2LIM].base, + memmap[SIFIVE_U_DEV_L2LIM].size, &error_fatal); + memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DEV_L2LIM].base, l2lim_mem); /* create PLIC hart topology configuration string */ @@ -585,7 +732,7 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) } /* MMIO */ - s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base, + s->plic = sifive_plic_create(memmap[SIFIVE_U_DEV_PLIC].base, plic_hart_config, 0, SIFIVE_U_PLIC_NUM_SOURCES, SIFIVE_U_PLIC_NUM_PRIORITIES, @@ -595,72 +742,106 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) SIFIVE_U_PLIC_ENABLE_STRIDE, SIFIVE_U_PLIC_CONTEXT_BASE, SIFIVE_U_PLIC_CONTEXT_STRIDE, - memmap[SIFIVE_U_PLIC].size); + memmap[SIFIVE_U_DEV_PLIC].size); g_free(plic_hart_config); - sifive_uart_create(system_memory, memmap[SIFIVE_U_UART0].base, + sifive_uart_create(system_memory, memmap[SIFIVE_U_DEV_UART0].base, serial_hd(0), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_UART0_IRQ)); - sifive_uart_create(system_memory, memmap[SIFIVE_U_UART1].base, + sifive_uart_create(system_memory, memmap[SIFIVE_U_DEV_UART1].base, serial_hd(1), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_UART1_IRQ)); - sifive_clint_create(memmap[SIFIVE_U_CLINT].base, - memmap[SIFIVE_U_CLINT].size, 0, ms->smp.cpus, - SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false); + sifive_clint_create(memmap[SIFIVE_U_DEV_CLINT].base, + memmap[SIFIVE_U_DEV_CLINT].size, 0, ms->smp.cpus, + SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, + SIFIVE_CLINT_TIMEBASE_FREQ, false); - object_property_set_bool(OBJECT(&s->prci), true, "realized", &err); - sysbus_mmio_map(SYS_BUS_DEVICE(&s->prci), 0, memmap[SIFIVE_U_PRCI].base); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->prci), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->prci), 0, memmap[SIFIVE_U_DEV_PRCI].base); - qdev_prop_set_uint32(DEVICE(&s->otp), "serial", s->serial); - object_property_set_bool(OBJECT(&s->otp), true, "realized", &err); - sysbus_mmio_map(SYS_BUS_DEVICE(&s->otp), 0, memmap[SIFIVE_U_OTP].base); + qdev_prop_set_uint32(DEVICE(&s->gpio), "ngpio", 16); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio), 0, memmap[SIFIVE_U_DEV_GPIO].base); - for (i = 0; i < SIFIVE_U_PLIC_NUM_SOURCES; i++) { - plic_gpios[i] = qdev_get_gpio_in(DEVICE(s->plic), i); + /* Pass all GPIOs to the SOC layer so they are available to the board */ + qdev_pass_gpios(DEVICE(&s->gpio), dev, NULL); + + /* Connect GPIO interrupts to the PLIC */ + for (i = 0; i < 16; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), i, + qdev_get_gpio_in(DEVICE(s->plic), + SIFIVE_U_GPIO_IRQ0 + i)); + } + + /* PDMA */ + sysbus_realize(SYS_BUS_DEVICE(&s->dma), errp); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->dma), 0, memmap[SIFIVE_U_DEV_PDMA].base); + + /* Connect PDMA interrupts to the PLIC */ + for (i = 0; i < SIFIVE_PDMA_IRQS; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), i, + qdev_get_gpio_in(DEVICE(s->plic), + SIFIVE_U_PDMA_IRQ0 + i)); + } + + qdev_prop_set_uint32(DEVICE(&s->otp), "serial", s->serial); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->otp), errp)) { + return; } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->otp), 0, memmap[SIFIVE_U_DEV_OTP].base); + /* FIXME use qdev NIC properties instead of nd_table[] */ if (nd->used) { qemu_check_nic_model(nd, TYPE_CADENCE_GEM); qdev_set_nic_properties(DEVICE(&s->gem), nd); } - object_property_set_int(OBJECT(&s->gem), GEM_REVISION, "revision", + object_property_set_int(OBJECT(&s->gem), "revision", GEM_REVISION, &error_abort); - object_property_set_bool(OBJECT(&s->gem), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gem), errp)) { return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->gem), 0, memmap[SIFIVE_U_GEM].base); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gem), 0, memmap[SIFIVE_U_DEV_GEM].base); sysbus_connect_irq(SYS_BUS_DEVICE(&s->gem), 0, - plic_gpios[SIFIVE_U_GEM_IRQ]); + qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_GEM_IRQ)); create_unimplemented_device("riscv.sifive.u.gem-mgmt", - memmap[SIFIVE_U_GEM_MGMT].base, memmap[SIFIVE_U_GEM_MGMT].size); + memmap[SIFIVE_U_DEV_GEM_MGMT].base, memmap[SIFIVE_U_DEV_GEM_MGMT].size); + + create_unimplemented_device("riscv.sifive.u.dmc", + memmap[SIFIVE_U_DEV_DMC].base, memmap[SIFIVE_U_DEV_DMC].size); + + create_unimplemented_device("riscv.sifive.u.l2cc", + memmap[SIFIVE_U_DEV_L2CC].base, memmap[SIFIVE_U_DEV_L2CC].size); } -static Property riscv_sifive_u_soc_props[] = { +static Property sifive_u_soc_props[] = { DEFINE_PROP_UINT32("serial", SiFiveUSoCState, serial, OTP_SERIAL), + DEFINE_PROP_STRING("cpu-type", SiFiveUSoCState, cpu_type), DEFINE_PROP_END_OF_LIST() }; -static void riscv_sifive_u_soc_class_init(ObjectClass *oc, void *data) +static void sifive_u_soc_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); - device_class_set_props(dc, riscv_sifive_u_soc_props); - dc->realize = riscv_sifive_u_soc_realize; + device_class_set_props(dc, sifive_u_soc_props); + dc->realize = sifive_u_soc_realize; /* Reason: Uses serial_hds in realize function, thus can't be used twice */ dc->user_creatable = false; } -static const TypeInfo riscv_sifive_u_soc_type_info = { +static const TypeInfo sifive_u_soc_type_info = { .name = TYPE_RISCV_U_SOC, .parent = TYPE_DEVICE, .instance_size = sizeof(SiFiveUSoCState), - .instance_init = riscv_sifive_u_soc_init, - .class_init = riscv_sifive_u_soc_class_init, + .instance_init = sifive_u_soc_instance_init, + .class_init = sifive_u_soc_class_init, }; -static void riscv_sifive_u_soc_register_types(void) +static void sifive_u_soc_register_types(void) { - type_register_static(&riscv_sifive_u_soc_type_info); + type_register_static(&sifive_u_soc_type_info); } -type_init(riscv_sifive_u_soc_register_types) +type_init(sifive_u_soc_register_types) diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index 29e7270035941ca38b07bbe4db0dc2caf00575e7..facac6e7d2d7491b54504b0c72d1b8b6d98802a8 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -31,32 +31,34 @@ #include "hw/loader.h" #include "hw/sysbus.h" #include "target/riscv/cpu.h" -#include "hw/riscv/riscv_htif.h" #include "hw/riscv/riscv_hart.h" -#include "hw/riscv/sifive_clint.h" #include "hw/riscv/spike.h" #include "hw/riscv/boot.h" #include "hw/riscv/numa.h" +#include "hw/char/riscv_htif.h" +#include "hw/intc/sifive_clint.h" #include "chardev/char.h" #include "sysemu/arch_init.h" #include "sysemu/device_tree.h" #include "sysemu/qtest.h" #include "sysemu/sysemu.h" -#include "exec/address-spaces.h" - -#include +/* + * Not like other RISC-V machines that use plain binary bios images, + * keeping ELF files here was intentional because BIN files don't work + * for the Spike machine as HTIF emulation depends on ELF parsing. + */ #if defined(TARGET_RISCV32) -# define BIOS_FILENAME "opensbi-riscv32-spike-fw_jump.elf" +# define BIOS_FILENAME "opensbi-riscv32-generic-fw_dynamic.elf" #else -# define BIOS_FILENAME "opensbi-riscv64-spike-fw_jump.elf" +# define BIOS_FILENAME "opensbi-riscv64-generic-fw_dynamic.elf" #endif static const struct MemmapEntry { hwaddr base; hwaddr size; } spike_memmap[] = { - [SPIKE_MROM] = { 0x1000, 0x11000 }, + [SPIKE_MROM] = { 0x1000, 0xf000 }, [SPIKE_CLINT] = { 0x2000000, 0x10000 }, [SPIKE_DRAM] = { 0x80000000, 0x0 }, }; @@ -193,6 +195,9 @@ static void spike_board_init(MachineState *machine) MemoryRegion *system_memory = get_system_memory(); MemoryRegion *main_mem = g_new(MemoryRegion, 1); MemoryRegion *mask_rom = g_new(MemoryRegion, 1); + target_ulong firmware_end_addr, kernel_start_addr; + uint32_t fdt_load_addr; + uint64_t kernel_entry; char *soc_name; int i, base_hartid, hart_count; @@ -224,22 +229,22 @@ static void spike_board_init(MachineState *machine) soc_name = g_strdup_printf("soc%d", i); object_initialize_child(OBJECT(machine), soc_name, &s->soc[i], - sizeof(s->soc[i]), TYPE_RISCV_HART_ARRAY, &error_abort, NULL); + TYPE_RISCV_HART_ARRAY); g_free(soc_name); - object_property_set_str(OBJECT(&s->soc[i]), - machine->cpu_type, "cpu-type", &error_abort); - object_property_set_int(OBJECT(&s->soc[i]), - base_hartid, "hartid-base", &error_abort); - object_property_set_int(OBJECT(&s->soc[i]), - hart_count, "num-harts", &error_abort); - object_property_set_bool(OBJECT(&s->soc[i]), - true, "realized", &error_abort); + object_property_set_str(OBJECT(&s->soc[i]), "cpu-type", + machine->cpu_type, &error_abort); + object_property_set_int(OBJECT(&s->soc[i]), "hartid-base", + base_hartid, &error_abort); + object_property_set_int(OBJECT(&s->soc[i]), "num-harts", + hart_count, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->soc[i]), &error_abort); /* Core Local Interruptor (timer and IPI) for each socket */ sifive_clint_create( memmap[SPIKE_CLINT].base + i * memmap[SPIKE_CLINT].size, memmap[SPIKE_CLINT].size, base_hartid, hart_count, - SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false); + SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, + SIFIVE_CLINT_TIMEBASE_FREQ, false); } /* register system main memory (actual RAM) */ @@ -257,13 +262,17 @@ static void spike_board_init(MachineState *machine) memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base, mask_rom); - riscv_find_and_load_firmware(machine, BIOS_FILENAME, - memmap[SPIKE_DRAM].base, - htif_symbol_callback); + firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME, + memmap[SPIKE_DRAM].base, + htif_symbol_callback); if (machine->kernel_filename) { - uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename, - htif_symbol_callback); + kernel_start_addr = riscv_calc_kernel_start_addr(machine, + firmware_end_addr); + + kernel_entry = riscv_load_kernel(machine->kernel_filename, + kernel_start_addr, + htif_symbol_callback); if (machine->initrd_filename) { hwaddr start; @@ -275,42 +284,21 @@ static void spike_board_init(MachineState *machine) qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-end", end); } + } else { + /* + * If dynamic firmware is used, it doesn't know where is the next mode + * if kernel argument is not set. + */ + kernel_entry = 0; } - /* reset vector */ - uint32_t reset_vec[8] = { - 0x00000297, /* 1: auipc t0, %pcrel_hi(dtb) */ - 0x02028593, /* addi a1, t0, %pcrel_lo(1b) */ - 0xf1402573, /* csrr a0, mhartid */ -#if defined(TARGET_RISCV32) - 0x0182a283, /* lw t0, 24(t0) */ -#elif defined(TARGET_RISCV64) - 0x0182b283, /* ld t0, 24(t0) */ -#endif - 0x00028067, /* jr t0 */ - 0x00000000, - memmap[SPIKE_DRAM].base, /* start: .dword DRAM_BASE */ - 0x00000000, - /* dtb: */ - }; - - /* copy in the reset vector in little_endian byte order */ - for (i = 0; i < sizeof(reset_vec) >> 2; i++) { - reset_vec[i] = cpu_to_le32(reset_vec[i]); - } - rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec), - memmap[SPIKE_MROM].base, &address_space_memory); - - /* copy in the device tree */ - if (fdt_pack(s->fdt) || fdt_totalsize(s->fdt) > - memmap[SPIKE_MROM].size - sizeof(reset_vec)) { - error_report("not enough space to store device-tree"); - exit(1); - } - qemu_fdt_dumpdtb(s->fdt, fdt_totalsize(s->fdt)); - rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt), - memmap[SPIKE_MROM].base + sizeof(reset_vec), - &address_space_memory); + /* Compute the fdt load address in dram */ + fdt_load_addr = riscv_load_fdt(memmap[SPIKE_DRAM].base, + machine->ram_size, s->fdt); + /* load the reset vector */ + riscv_setup_rom_reset_vec(memmap[SPIKE_DRAM].base, memmap[SPIKE_MROM].base, + memmap[SPIKE_MROM].size, kernel_entry, + fdt_load_addr, s->fdt); /* initialize HTIF using symbols found in load_kernel */ htif_mm_init(system_memory, mask_rom, diff --git a/hw/riscv/trace-events b/hw/riscv/trace-events deleted file mode 100644 index 6d59233e23d2be585b93272a999dce404b793de2..0000000000000000000000000000000000000000 --- a/hw/riscv/trace-events +++ /dev/null @@ -1,7 +0,0 @@ -# See docs/devel/tracing.txt for syntax documentation. - -# hw/gpio/sifive_gpio.c -sifive_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64 -sifive_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64 -sifive_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 -sifive_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 270c4a8876accff67b88e8f8178faa6d1b9b1d26..47b701819315afd075b6a6151566e4d84f9be4eb 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -30,27 +30,24 @@ #include "hw/char/serial.h" #include "target/riscv/cpu.h" #include "hw/riscv/riscv_hart.h" -#include "hw/riscv/sifive_plic.h" -#include "hw/riscv/sifive_clint.h" -#include "hw/riscv/sifive_test.h" #include "hw/riscv/virt.h" #include "hw/riscv/boot.h" #include "hw/riscv/numa.h" +#include "hw/intc/sifive_clint.h" +#include "hw/intc/sifive_plic.h" +#include "hw/misc/sifive_test.h" #include "chardev/char.h" #include "sysemu/arch_init.h" #include "sysemu/device_tree.h" #include "sysemu/sysemu.h" -#include "exec/address-spaces.h" #include "hw/pci/pci.h" #include "hw/pci-host/gpex.h" #include "sysemu/kvm.h" -#include - #if defined(TARGET_RISCV32) -# define BIOS_FILENAME "opensbi-riscv32-virt-fw_jump.bin" +# define BIOS_FILENAME "opensbi-riscv32-generic-fw_dynamic.bin" #else -# define BIOS_FILENAME "opensbi-riscv64-virt-fw_jump.bin" +# define BIOS_FILENAME "opensbi-riscv64-generic-fw_dynamic.bin" #endif static const struct MemmapEntry { @@ -58,18 +55,18 @@ static const struct MemmapEntry { hwaddr size; } virt_memmap[] = { [VIRT_DEBUG] = { 0x0, 0x100 }, - [VIRT_MROM] = { 0x1000, 0x11000 }, + [VIRT_MROM] = { 0x1000, 0xf000 }, [VIRT_TEST] = { 0x100000, 0x1000 }, [VIRT_RTC] = { 0x101000, 0x1000 }, [VIRT_CLINT] = { 0x2000000, 0x10000 }, + [VIRT_PCIE_PIO] = { 0x3000000, 0x10000 }, [VIRT_PLIC] = { 0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) }, [VIRT_UART0] = { 0x10000000, 0x100 }, [VIRT_VIRTIO] = { 0x10001000, 0x1000 }, [VIRT_FLASH] = { 0x20000000, 0x4000000 }, - [VIRT_DRAM] = { 0x80000000, 0x0 }, - [VIRT_PCIE_MMIO] = { 0x40000000, 0x40000000 }, - [VIRT_PCIE_PIO] = { 0x03000000, 0x00010000 }, [VIRT_PCIE_ECAM] = { 0x30000000, 0x10000000 }, + [VIRT_PCIE_MMIO] = { 0x40000000, 0x40000000 }, + [VIRT_DRAM] = { 0x80000000, 0x0 }, }; #define VIRT_FLASH_SECTOR_SIZE (256 * KiB) @@ -82,7 +79,7 @@ static PFlashCFI01 *virt_flash_create1(RISCVVirtState *s, * Create a single flash device. We use the same parameters as * the flash devices on the ARM virt board. */ - DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01); + DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01); qdev_prop_set_uint64(dev, "sector-length", VIRT_FLASH_SECTOR_SIZE); qdev_prop_set_uint8(dev, "width", 4); @@ -116,7 +113,7 @@ static void virt_flash_map1(PFlashCFI01 *flash, assert(QEMU_IS_ALIGNED(size, VIRT_FLASH_SECTOR_SIZE)); assert(size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX); qdev_prop_set_uint32(dev, "num-blocks", size / VIRT_FLASH_SECTOR_SIZE); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); memory_region_add_subregion(sysmem, base, sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), @@ -185,6 +182,7 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, { void *fdt; int i, cpu, socket; + const char *dtb_filename; MachineState *mc = MACHINE(s); uint64_t addr, size; uint32_t *clint_cells, *plic_cells; @@ -198,10 +196,20 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2; hwaddr flashbase = virt_memmap[VIRT_FLASH].base; - fdt = s->fdt = create_device_tree(&s->fdt_size); - if (!fdt) { - error_report("create_device_tree() failed"); - exit(1); + dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb"); + if (dtb_filename) { + fdt = s->fdt = load_device_tree(dtb_filename, &s->fdt_size); + if (!fdt) { + error_report("load_device_tree() failed"); + exit(1); + } + goto update_bootargs; + } else { + fdt = s->fdt = create_device_tree(&s->fdt_size); + if (!fdt) { + error_report("create_device_tree() failed"); + exit(1); + } } qemu_fdt_setprop_string(fdt, "/", "model", "riscv-virtio,qemu"); @@ -422,9 +430,6 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, qemu_fdt_add_subnode(fdt, "/chosen"); qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", name); - if (cmdline) { - qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline); - } g_free(name); name = g_strdup_printf("/soc/rtc@%lx", (long)memmap[VIRT_RTC].base); @@ -445,6 +450,11 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, 2, flashbase + flashsize, 2, flashsize); qemu_fdt_setprop_cell(s->fdt, name, "bank-width", 4); g_free(name); + +update_bootargs: + if (cmdline) { + qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline); + } } static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem, @@ -459,9 +469,9 @@ static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem, qemu_irq irq; int i; - dev = qdev_create(NULL, TYPE_GPEX_HOST); + dev = qdev_new(TYPE_GPEX_HOST); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); ecam_alias = g_new0(MemoryRegion, 1); ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); @@ -487,7 +497,7 @@ static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem, return dev; } -static void riscv_virt_board_init(MachineState *machine) +static void virt_machine_init(MachineState *machine) { const struct MemmapEntry *memmap = virt_memmap; RISCVVirtState *s = RISCV_VIRT_MACHINE(machine); @@ -497,10 +507,11 @@ static void riscv_virt_board_init(MachineState *machine) char *plic_hart_config, *soc_name; size_t plic_hart_config_len; target_ulong start_addr = memmap[VIRT_DRAM].base; + target_ulong firmware_end_addr, kernel_start_addr; + uint32_t fdt_load_addr; + uint64_t kernel_entry; DeviceState *mmio_plic, *virtio_plic, *pcie_plic; int i, j, base_hartid, hart_count; - uint64_t kernel_entry = 0; - hwaddr start_fdt; CPUState *cs; /* Check socket count limit */ @@ -532,22 +543,22 @@ static void riscv_virt_board_init(MachineState *machine) soc_name = g_strdup_printf("soc%d", i); object_initialize_child(OBJECT(machine), soc_name, &s->soc[i], - sizeof(s->soc[i]), TYPE_RISCV_HART_ARRAY, &error_abort, NULL); + TYPE_RISCV_HART_ARRAY); g_free(soc_name); - object_property_set_str(OBJECT(&s->soc[i]), - machine->cpu_type, "cpu-type", &error_abort); - object_property_set_int(OBJECT(&s->soc[i]), - base_hartid, "hartid-base", &error_abort); - object_property_set_int(OBJECT(&s->soc[i]), - hart_count, "num-harts", &error_abort); - object_property_set_bool(OBJECT(&s->soc[i]), - true, "realized", &error_abort); + object_property_set_str(OBJECT(&s->soc[i]), "cpu-type", + machine->cpu_type, &error_abort); + object_property_set_int(OBJECT(&s->soc[i]), "hartid-base", + base_hartid, &error_abort); + object_property_set_int(OBJECT(&s->soc[i]), "num-harts", + hart_count, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->soc[i]), &error_abort); /* Per-socket CLINT */ sifive_clint_create( memmap[VIRT_CLINT].base + i * memmap[VIRT_CLINT].size, memmap[VIRT_CLINT].size, base_hartid, hart_count, - SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, true); + SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, + SIFIVE_CLINT_TIMEBASE_FREQ, true); /* Per-socket PLIC hart topology configuration string */ plic_hart_config_len = @@ -607,12 +618,15 @@ static void riscv_virt_board_init(MachineState *machine) memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base, mask_rom); - riscv_find_and_load_firmware(machine, BIOS_FILENAME, - memmap[VIRT_DRAM].base, NULL); + firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME, + start_addr, NULL); if (machine->kernel_filename) { + kernel_start_addr = riscv_calc_kernel_start_addr(machine, + firmware_end_addr); + kernel_entry = riscv_load_kernel(machine->kernel_filename, - NULL); + kernel_start_addr, NULL); if (machine->initrd_filename) { hwaddr start; @@ -624,6 +638,12 @@ static void riscv_virt_board_init(MachineState *machine) qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-end", end); } + } else { + /* + * If dynamic firmware is used, it doesn't know where is the next mode + * if kernel argument is not set. + */ + kernel_entry = 0; } if (drive_get(IF_PFLASH, 0, 0)) { @@ -634,46 +654,18 @@ static void riscv_virt_board_init(MachineState *machine) start_addr = virt_memmap[VIRT_FLASH].base; } - /* reset vector */ - uint32_t reset_vec[8] = { - 0x00000297, /* 1: auipc t0, %pcrel_hi(dtb) */ - 0x02028593, /* addi a1, t0, %pcrel_lo(1b) */ - 0xf1402573, /* csrr a0, mhartid */ -#if defined(TARGET_RISCV32) - 0x0182a283, /* lw t0, 24(t0) */ -#elif defined(TARGET_RISCV64) - 0x0182b283, /* ld t0, 24(t0) */ -#endif - 0x00028067, /* jr t0 */ - 0x00000000, - start_addr, /* start: .dword */ - 0x00000000, - /* dtb: */ - }; - - /* copy in the reset vector in little_endian byte order */ - for (i = 0; i < sizeof(reset_vec) >> 2; i++) { - reset_vec[i] = cpu_to_le32(reset_vec[i]); - } - rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec), - memmap[VIRT_MROM].base, &address_space_memory); - - /* copy in the device tree */ - if (fdt_pack(s->fdt) || fdt_totalsize(s->fdt) > - memmap[VIRT_MROM].size - sizeof(reset_vec)) { - error_report("not enough space to store device-tree"); - exit(1); - } - qemu_fdt_dumpdtb(s->fdt, fdt_totalsize(s->fdt)); - start_fdt = memmap[VIRT_MROM].base + sizeof(reset_vec); - rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt), - start_fdt, - &address_space_memory); + /* Compute the fdt load address in dram */ + fdt_load_addr = riscv_load_fdt(memmap[VIRT_DRAM].base, + machine->ram_size, s->fdt); + /* load the reset vector */ + riscv_setup_rom_reset_vec(start_addr, virt_memmap[VIRT_MROM].base, + virt_memmap[VIRT_MROM].size, kernel_entry, + fdt_load_addr, s->fdt); for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) { RISCVCPU *riscv_cpu = RISCV_CPU(cs); - riscv_cpu->env.loader_start = kernel_entry; - riscv_cpu->env.fdt_start = start_fdt; + riscv_cpu->env.kernel_addr = kernel_entry; + riscv_cpu->env.fdt_addr = fdt_load_addr; } /* SiFive Test MMIO device */ @@ -711,16 +703,16 @@ static void riscv_virt_board_init(MachineState *machine) virt_flash_map(s, system_memory); } -static void riscv_virt_machine_instance_init(Object *obj) +static void virt_machine_instance_init(Object *obj) { } -static void riscv_virt_machine_class_init(ObjectClass *oc, void *data) +static void virt_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); mc->desc = "RISC-V VirtIO board"; - mc->init = riscv_virt_board_init; + mc->init = virt_machine_init; mc->max_cpus = VIRT_CPUS_MAX; mc->default_cpu_type = VIRT_CPU; mc->pci_allow_0_address = true; @@ -730,17 +722,17 @@ static void riscv_virt_machine_class_init(ObjectClass *oc, void *data) mc->numa_mem_supported = true; } -static const TypeInfo riscv_virt_machine_typeinfo = { +static const TypeInfo virt_machine_typeinfo = { .name = MACHINE_TYPE_NAME("virt"), .parent = TYPE_MACHINE, - .class_init = riscv_virt_machine_class_init, - .instance_init = riscv_virt_machine_instance_init, + .class_init = virt_machine_class_init, + .instance_init = virt_machine_instance_init, .instance_size = sizeof(RISCVVirtState), }; -static void riscv_virt_machine_init_register_types(void) +static void virt_machine_init_register_types(void) { - type_register_static(&riscv_virt_machine_typeinfo); + type_register_static(&virt_machine_typeinfo); } -type_init(riscv_virt_machine_init_register_types) +type_init(virt_machine_init_register_types) diff --git a/hw/rtc/Makefile.objs b/hw/rtc/Makefile.objs deleted file mode 100644 index e4c1b8617c8afa2f052fdf62fa4f3f9b9c498344..0000000000000000000000000000000000000000 --- a/hw/rtc/Makefile.objs +++ /dev/null @@ -1,15 +0,0 @@ -common-obj-$(CONFIG_DS1338) += ds1338.o -common-obj-$(CONFIG_M41T80) += m41t80.o -common-obj-$(CONFIG_M48T59) += m48t59.o -ifeq ($(CONFIG_ISA_BUS),y) -common-obj-$(CONFIG_M48T59) += m48t59-isa.o -endif -common-obj-$(CONFIG_PL031) += pl031.o -common-obj-$(CONFIG_TWL92230) += twl92230.o -common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp-rtc.o -common-obj-$(CONFIG_EXYNOS4) += exynos4210_rtc.o -obj-$(CONFIG_MC146818RTC) += mc146818rtc.o -common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o -common-obj-$(CONFIG_ASPEED_SOC) += aspeed_rtc.o -common-obj-$(CONFIG_GOLDFISH_RTC) += goldfish_rtc.o -common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-rtc.o diff --git a/hw/rtc/ds1338.c b/hw/rtc/ds1338.c index 588a9ba9be8ae5675a0f46068f564fc3d272b132..bc5ce1a9f46d951f6045c7e0de59e3b1fabae3b4 100644 --- a/hw/rtc/ds1338.c +++ b/hw/rtc/ds1338.c @@ -16,6 +16,7 @@ #include "migration/vmstate.h" #include "qemu/bcd.h" #include "qemu/module.h" +#include "qom/object.h" /* Size of NVRAM including both the user-accessible area and the * secondary register area. @@ -29,9 +30,9 @@ #define CTRL_OSF 0x20 #define TYPE_DS1338 "ds1338" -#define DS1338(obj) OBJECT_CHECK(DS1338State, (obj), TYPE_DS1338) +OBJECT_DECLARE_SIMPLE_TYPE(DS1338State, DS1338) -typedef struct DS1338State { +struct DS1338State { I2CSlave parent_obj; int64_t offset; @@ -39,7 +40,7 @@ typedef struct DS1338State { uint8_t nvram[NVRAM_SIZE]; int32_t ptr; bool addr_byte; -} DS1338State; +}; static const VMStateDescription vmstate_ds1338 = { .name = "ds1338", diff --git a/hw/rtc/exynos4210_rtc.c b/hw/rtc/exynos4210_rtc.c index f85483a07f8c886af49362158bb2b0b24150d066..4c976244786b2dde2bc531262301254e18396fe4 100644 --- a/hw/rtc/exynos4210_rtc.c +++ b/hw/rtc/exynos4210_rtc.c @@ -38,6 +38,7 @@ #include "hw/irq.h" #include "hw/arm/exynos4210.h" +#include "qom/object.h" #define DEBUG_RTC 0 @@ -84,10 +85,9 @@ #define RTC_BASE_FREQ 32768 #define TYPE_EXYNOS4210_RTC "exynos4210.rtc" -#define EXYNOS4210_RTC(obj) \ - OBJECT_CHECK(Exynos4210RTCState, (obj), TYPE_EXYNOS4210_RTC) +OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210RTCState, EXYNOS4210_RTC) -typedef struct Exynos4210RTCState { +struct Exynos4210RTCState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -113,7 +113,7 @@ typedef struct Exynos4210RTCState { qemu_irq alm_irq; /* alarm irq */ struct tm current_tm; /* current time */ -} Exynos4210RTCState; +}; #define TICCKSEL(value) ((value & (0x0F << 4)) >> 4) diff --git a/hw/rtc/goldfish_rtc.c b/hw/rtc/goldfish_rtc.c index 01e9d2b083e5aff5ba56ee1d547a7213326a6bb1..0f4e8185a796911fd909e7c55b5ffe942eeb43d4 100644 --- a/hw/rtc/goldfish_rtc.c +++ b/hw/rtc/goldfish_rtc.c @@ -94,12 +94,22 @@ static uint64_t goldfish_rtc_read(void *opaque, hwaddr offset, GoldfishRTCState *s = opaque; uint64_t r = 0; + /* + * From the documentation linked at the top of the file: + * + * To read the value, the kernel must perform an IO_READ(TIME_LOW), which + * returns an unsigned 32-bit value, before an IO_READ(TIME_HIGH), which + * returns a signed 32-bit value, corresponding to the higher half of the + * full value. + */ switch (offset) { case RTC_TIME_LOW: - r = goldfish_rtc_get_count(s) & 0xffffffff; + r = goldfish_rtc_get_count(s); + s->time_high = r >> 32; + r &= 0xffffffff; break; case RTC_TIME_HIGH: - r = goldfish_rtc_get_count(s) >> 32; + r = s->time_high; break; case RTC_ALARM_LOW: r = s->alarm_next & 0xffffffff; @@ -207,7 +217,7 @@ static int goldfish_rtc_post_load(void *opaque, int version_id) static const MemoryRegionOps goldfish_rtc_ops = { .read = goldfish_rtc_read, .write = goldfish_rtc_write, - .endianness = DEVICE_LITTLE_ENDIAN, + .endianness = DEVICE_NATIVE_ENDIAN, .valid = { .min_access_size = 4, .max_access_size = 4 @@ -216,7 +226,7 @@ static const MemoryRegionOps goldfish_rtc_ops = { static const VMStateDescription goldfish_rtc_vmstate = { .name = TYPE_GOLDFISH_RTC, - .version_id = 1, + .version_id = 2, .pre_save = goldfish_rtc_pre_save, .post_load = goldfish_rtc_post_load, .fields = (VMStateField[]) { @@ -225,6 +235,7 @@ static const VMStateDescription goldfish_rtc_vmstate = { VMSTATE_UINT32(alarm_running, GoldfishRTCState), VMSTATE_UINT32(irq_pending, GoldfishRTCState), VMSTATE_UINT32(irq_enabled, GoldfishRTCState), + VMSTATE_UINT32(time_high, GoldfishRTCState), VMSTATE_END_OF_LIST() } }; diff --git a/hw/rtc/m41t80.c b/hw/rtc/m41t80.c index 914ecac8f4db418633d6daf92608cb50f6b89052..396d110ba2d266c5e6bd45892f6ecdea168cd19e 100644 --- a/hw/rtc/m41t80.c +++ b/hw/rtc/m41t80.c @@ -14,14 +14,15 @@ #include "qemu/timer.h" #include "qemu/bcd.h" #include "hw/i2c/i2c.h" +#include "qom/object.h" #define TYPE_M41T80 "m41t80" -#define M41T80(obj) OBJECT_CHECK(M41t80State, (obj), TYPE_M41T80) +OBJECT_DECLARE_SIMPLE_TYPE(M41t80State, M41T80) -typedef struct M41t80State { +struct M41t80State { I2CSlave parent_obj; int8_t addr; -} M41t80State; +}; static void m41t80_realize(DeviceState *dev, Error **errp) { diff --git a/hw/rtc/m48t59-isa.c b/hw/rtc/m48t59-isa.c index 131eb5b7d3d8389d0c0028d4c0e080cb386b05ff..dc21fb10a529afa222889edfcaa890bf697332c9 100644 --- a/hw/rtc/m48t59-isa.c +++ b/hw/rtc/m48t59-isa.c @@ -28,27 +28,27 @@ #include "hw/qdev-properties.h" #include "hw/rtc/m48t59.h" #include "m48t59-internal.h" +#include "qapi/error.h" #include "qemu/module.h" +#include "qom/object.h" #define TYPE_M48TXX_ISA "isa-m48txx" -#define M48TXX_ISA_GET_CLASS(obj) \ - OBJECT_GET_CLASS(M48txxISADeviceClass, (obj), TYPE_M48TXX_ISA) -#define M48TXX_ISA_CLASS(klass) \ - OBJECT_CLASS_CHECK(M48txxISADeviceClass, (klass), TYPE_M48TXX_ISA) -#define M48TXX_ISA(obj) \ - OBJECT_CHECK(M48txxISAState, (obj), TYPE_M48TXX_ISA) - -typedef struct M48txxISAState { +typedef struct M48txxISADeviceClass M48txxISADeviceClass; +typedef struct M48txxISAState M48txxISAState; +DECLARE_OBJ_CHECKERS(M48txxISAState, M48txxISADeviceClass, + M48TXX_ISA, TYPE_M48TXX_ISA) + +struct M48txxISAState { ISADevice parent_obj; M48t59State state; uint32_t io_base; MemoryRegion io; -} M48txxISAState; +}; -typedef struct M48txxISADeviceClass { +struct M48txxISADeviceClass { ISADeviceClass parent_class; M48txxInfo info; -} M48txxISADeviceClass; +}; static M48txxInfo m48txx_isa_info[] = { { @@ -58,29 +58,6 @@ static M48txxInfo m48txx_isa_info[] = { } }; -Nvram *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size, - int base_year, int model) -{ - DeviceState *dev; - int i; - - for (i = 0; i < ARRAY_SIZE(m48txx_isa_info); i++) { - if (m48txx_isa_info[i].size != size || - m48txx_isa_info[i].model != model) { - continue; - } - - dev = DEVICE(isa_create(bus, m48txx_isa_info[i].bus_name)); - qdev_prop_set_uint32(dev, "iobase", io_base); - qdev_prop_set_int32(dev, "base-year", base_year); - qdev_init_nofail(dev); - return NVRAM(dev); - } - - assert(false); - return NULL; -} - static uint32_t m48txx_isa_read(Nvram *obj, uint32_t addr) { M48txxISAState *d = M48TXX_ISA(obj); diff --git a/hw/rtc/m48t59.c b/hw/rtc/m48t59.c index 47d48054fdc1a4afff27ec1dd76f34ddd43eb42c..d54929e86127f8e569dbbf64cf2046e6cf48ff1c 100644 --- a/hw/rtc/m48t59.c +++ b/hw/rtc/m48t59.c @@ -33,20 +33,20 @@ #include "sysemu/sysemu.h" #include "hw/sysbus.h" #include "exec/address-spaces.h" +#include "qapi/error.h" #include "qemu/bcd.h" #include "qemu/module.h" #include "trace.h" #include "m48t59-internal.h" #include "migration/vmstate.h" +#include "qom/object.h" #define TYPE_M48TXX_SYS_BUS "sysbus-m48txx" -#define M48TXX_SYS_BUS_GET_CLASS(obj) \ - OBJECT_GET_CLASS(M48txxSysBusDeviceClass, (obj), TYPE_M48TXX_SYS_BUS) -#define M48TXX_SYS_BUS_CLASS(klass) \ - OBJECT_CLASS_CHECK(M48txxSysBusDeviceClass, (klass), TYPE_M48TXX_SYS_BUS) -#define M48TXX_SYS_BUS(obj) \ - OBJECT_CHECK(M48txxSysBusState, (obj), TYPE_M48TXX_SYS_BUS) +typedef struct M48txxSysBusDeviceClass M48txxSysBusDeviceClass; +typedef struct M48txxSysBusState M48txxSysBusState; +DECLARE_OBJ_CHECKERS(M48txxSysBusState, M48txxSysBusDeviceClass, + M48TXX_SYS_BUS, TYPE_M48TXX_SYS_BUS) /* * Chipset docs: @@ -55,16 +55,16 @@ * http://www.st.com/stonline/products/literature/od/7001/m48t59y.pdf */ -typedef struct M48txxSysBusState { +struct M48txxSysBusState { SysBusDevice parent_obj; M48t59State state; MemoryRegion io; -} M48txxSysBusState; +}; -typedef struct M48txxSysBusDeviceClass { +struct M48txxSysBusDeviceClass { SysBusDeviceClass parent_class; M48txxInfo info; -} M48txxSysBusDeviceClass; +}; static M48txxInfo m48txx_sysbus_info[] = { { @@ -564,41 +564,6 @@ const MemoryRegionOps m48t59_io_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -/* Initialisation routine */ -Nvram *m48t59_init(qemu_irq IRQ, hwaddr mem_base, - uint32_t io_base, uint16_t size, int base_year, - int model) -{ - DeviceState *dev; - SysBusDevice *s; - int i; - - for (i = 0; i < ARRAY_SIZE(m48txx_sysbus_info); i++) { - if (m48txx_sysbus_info[i].size != size || - m48txx_sysbus_info[i].model != model) { - continue; - } - - dev = qdev_create(NULL, m48txx_sysbus_info[i].bus_name); - qdev_prop_set_int32(dev, "base-year", base_year); - qdev_init_nofail(dev); - s = SYS_BUS_DEVICE(dev); - sysbus_connect_irq(s, 0, IRQ); - if (io_base != 0) { - memory_region_add_subregion(get_system_io(), io_base, - sysbus_mmio_get_region(s, 1)); - } - if (mem_base != 0) { - sysbus_mmio_map(s, 0, mem_base); - } - - return NVRAM(s); - } - - assert(false); - return NULL; -} - void m48t59_realize_common(M48t59State *s, Error **errp) { s->buffer = g_malloc0(s->size); diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c index 9c30cbdcd76fdd5dc7665b8464c74ca07e7e2d4b..7a38540cb9dd3da8ea9f46d0496c9d376564649f 100644 --- a/hw/rtc/mc146818rtc.c +++ b/hw/rtc/mc146818rtc.c @@ -27,6 +27,7 @@ #include "qemu/cutils.h" #include "qemu/module.h" #include "qemu/bcd.h" +#include "hw/acpi/aml-build.h" #include "hw/irq.h" #include "hw/qdev-properties.h" #include "qemu/timer.h" @@ -973,10 +974,10 @@ ISADevice *mc146818_rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq) DeviceState *dev; ISADevice *isadev; - isadev = isa_create(bus, TYPE_MC146818_RTC); + isadev = isa_new(TYPE_MC146818_RTC); dev = DEVICE(isadev); qdev_prop_set_int32(dev, "base_year", base_year); - qdev_init_nofail(dev); + isa_realize_and_unref(isadev, bus, &error_fatal); if (intercept_irq) { qdev_connect_gpio_out(dev, 0, intercept_irq); } else { @@ -1007,13 +1008,36 @@ static void rtc_resetdev(DeviceState *d) } } +static void rtc_build_aml(ISADevice *isadev, Aml *scope) +{ + Aml *dev; + Aml *crs; + + /* + * Reserving 8 io ports here, following what physical hardware + * does, even though qemu only responds to the first two ports. + */ + crs = aml_resource_template(); + aml_append(crs, aml_io(AML_DECODE16, RTC_ISA_BASE, RTC_ISA_BASE, + 0x01, 0x08)); + aml_append(crs, aml_irq_no_flags(RTC_ISA_IRQ)); + + dev = aml_device("RTC"); + aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0B00"))); + aml_append(dev, aml_name_decl("_CRS", crs)); + + aml_append(scope, dev); +} + static void rtc_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *isa = ISA_DEVICE_CLASS(klass); dc->realize = rtc_realizefn; dc->reset = rtc_resetdev; dc->vmsd = &vmstate_rtc; + isa->build_aml = rtc_build_aml; device_class_set_props(dc, mc146818rtc_properties); } diff --git a/hw/rtc/meson.build b/hw/rtc/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..7cecdee5ddb01326cfb3b8f88ca42fd8e4f2e50d --- /dev/null +++ b/hw/rtc/meson.build @@ -0,0 +1,16 @@ + +softmmu_ss.add(when: 'CONFIG_DS1338', if_true: files('ds1338.c')) +softmmu_ss.add(when: 'CONFIG_M41T80', if_true: files('m41t80.c')) +softmmu_ss.add(when: 'CONFIG_M48T59', if_true: files('m48t59.c')) +softmmu_ss.add(when: 'CONFIG_PL031', if_true: files('pl031.c')) +softmmu_ss.add(when: 'CONFIG_TWL92230', if_true: files('twl92230.c')) +softmmu_ss.add(when: ['CONFIG_ISA_BUS', 'CONFIG_M48T59'], if_true: files('m48t59-isa.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-rtc.c')) + +softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_rtc.c')) +softmmu_ss.add(when: 'CONFIG_SUN4V_RTC', if_true: files('sun4v-rtc.c')) +softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_rtc.c')) +softmmu_ss.add(when: 'CONFIG_GOLDFISH_RTC', if_true: files('goldfish_rtc.c')) +softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-rtc.c')) + +specific_ss.add(when: 'CONFIG_MC146818RTC', if_true: files('mc146818rtc.c')) diff --git a/hw/rtc/sun4v-rtc.c b/hw/rtc/sun4v-rtc.c index ada01b57748bfc2dfebf2e21b6f4344d22479040..e037acd1b56d723f91fa8871f9fd491decd59c1d 100644 --- a/hw/rtc/sun4v-rtc.c +++ b/hw/rtc/sun4v-rtc.c @@ -11,20 +11,22 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" +#include "qapi/error.h" #include "qemu/module.h" #include "qemu/timer.h" #include "hw/rtc/sun4v-rtc.h" #include "trace.h" +#include "qom/object.h" #define TYPE_SUN4V_RTC "sun4v_rtc" -#define SUN4V_RTC(obj) OBJECT_CHECK(Sun4vRtc, (obj), TYPE_SUN4V_RTC) +OBJECT_DECLARE_SIMPLE_TYPE(Sun4vRtc, SUN4V_RTC) -typedef struct Sun4vRtc { +struct Sun4vRtc { SysBusDevice parent_obj; MemoryRegion iomem; -} Sun4vRtc; +}; static uint64_t sun4v_rtc_read(void *opaque, hwaddr addr, unsigned size) @@ -55,10 +57,10 @@ void sun4v_rtc_init(hwaddr addr) DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, TYPE_SUN4V_RTC); + dev = qdev_new(TYPE_SUN4V_RTC); s = SYS_BUS_DEVICE(dev); - qdev_init_nofail(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, addr); } diff --git a/hw/rtc/trace-events b/hw/rtc/trace-events index 1bc7147d0e093c5ec73ee91d18d9dd8104960811..8bdcf742640da269a301757529a08663c565518e 100644 --- a/hw/rtc/trace-events +++ b/hw/rtc/trace-events @@ -18,7 +18,7 @@ pl031_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" pl031_alarm_raised(void) "alarm raised" pl031_set_alarm(uint32_t ticks) "alarm set for %u ticks" -# aspeed-rtc.c +# aspeed_rtc.c aspeed_rtc_read(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64 aspeed_rtc_write(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64 diff --git a/hw/rtc/trace.h b/hw/rtc/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..cfd5d6ee62f5d9a16aa7b724dd25124050e501fe --- /dev/null +++ b/hw/rtc/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_rtc.h" diff --git a/hw/rtc/twl92230.c b/hw/rtc/twl92230.c index d0011be89eefbcb9e71a12181184ec51b24c763e..f838913b378d5760a405171d6600eaef53753c64 100644 --- a/hw/rtc/twl92230.c +++ b/hw/rtc/twl92230.c @@ -29,13 +29,14 @@ #include "sysemu/sysemu.h" #include "qemu/bcd.h" #include "qemu/module.h" +#include "qom/object.h" #define VERBOSE 1 #define TYPE_TWL92230 "twl92230" -#define TWL92230(obj) OBJECT_CHECK(MenelausState, (obj), TYPE_TWL92230) +OBJECT_DECLARE_SIMPLE_TYPE(MenelausState, TWL92230) -typedef struct MenelausState { +struct MenelausState { I2CSlave parent_obj; int firstbyte; @@ -71,7 +72,7 @@ typedef struct MenelausState { uint16_t rtc_next_vmstate; qemu_irq out[4]; uint8_t pwrbtn_state; -} MenelausState; +}; static inline void menelaus_update(MenelausState *s) { diff --git a/hw/rx/Kconfig b/hw/rx/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..2b297c5a6a686eb84f7d50701e9d849868a8fdcb --- /dev/null +++ b/hw/rx/Kconfig @@ -0,0 +1,10 @@ +config RX62N_MCU + bool + select RX_ICU + select RENESAS_TMR + select RENESAS_CMT + select RENESAS_SCI + +config RX_GDBSIM + bool + select RX62N_MCU diff --git a/hw/rx/meson.build b/hw/rx/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..d223512a7802788c2e25347ca7da01f07c9aa8c6 --- /dev/null +++ b/hw/rx/meson.build @@ -0,0 +1,5 @@ +rx_ss = ss.source_set() +rx_ss.add(when: 'CONFIG_RX_GDBSIM', if_true: files('rx-gdbsim.c')) +rx_ss.add(when: 'CONFIG_RX62N_MCU', if_true: files('rx62n.c')) + +hw_arch += {'rx': rx_ss} diff --git a/hw/rx/rx-gdbsim.c b/hw/rx/rx-gdbsim.c new file mode 100644 index 0000000000000000000000000000000000000000..285549c79b580d9fb89c11a66a8616668e14ed0f --- /dev/null +++ b/hw/rx/rx-gdbsim.c @@ -0,0 +1,196 @@ +/* + * RX QEMU GDB simulator + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/cutils.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "qemu-common.h" +#include "cpu.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/loader.h" +#include "hw/rx/rx62n.h" +#include "sysemu/sysemu.h" +#include "sysemu/qtest.h" +#include "sysemu/device_tree.h" +#include "hw/boards.h" +#include "qom/object.h" + +/* Same address of GDB integrated simulator */ +#define SDRAM_BASE EXT_CS_BASE + +struct RxGdbSimMachineClass { + /*< private >*/ + MachineClass parent_class; + /*< public >*/ + const char *mcu_name; + uint32_t xtal_freq_hz; +}; +typedef struct RxGdbSimMachineClass RxGdbSimMachineClass; + +struct RxGdbSimMachineState { + /*< private >*/ + MachineState parent_obj; + /*< public >*/ + RX62NState mcu; +}; +typedef struct RxGdbSimMachineState RxGdbSimMachineState; + +#define TYPE_RX_GDBSIM_MACHINE MACHINE_TYPE_NAME("rx62n-common") + +DECLARE_OBJ_CHECKERS(RxGdbSimMachineState, RxGdbSimMachineClass, + RX_GDBSIM_MACHINE, TYPE_RX_GDBSIM_MACHINE) + + +static void rx_load_image(RXCPU *cpu, const char *filename, + uint32_t start, uint32_t size) +{ + static uint32_t extable[32]; + long kernel_size; + int i; + + kernel_size = load_image_targphys(filename, start, size); + if (kernel_size < 0) { + fprintf(stderr, "qemu: could not load kernel '%s'\n", filename); + exit(1); + } + cpu->env.pc = start; + + /* setup exception trap trampoline */ + /* linux kernel only works little-endian mode */ + for (i = 0; i < ARRAY_SIZE(extable); i++) { + extable[i] = cpu_to_le32(0x10 + i * 4); + } + rom_add_blob_fixed("extable", extable, sizeof(extable), VECTOR_TABLE_BASE); +} + +static void rx_gdbsim_init(MachineState *machine) +{ + MachineClass *mc = MACHINE_GET_CLASS(machine); + RxGdbSimMachineState *s = RX_GDBSIM_MACHINE(machine); + RxGdbSimMachineClass *rxc = RX_GDBSIM_MACHINE_GET_CLASS(machine); + MemoryRegion *sysmem = get_system_memory(); + const char *kernel_filename = machine->kernel_filename; + const char *dtb_filename = machine->dtb; + + if (machine->ram_size < mc->default_ram_size) { + char *sz = size_to_str(mc->default_ram_size); + error_report("Invalid RAM size, should be more than %s", sz); + g_free(sz); + } + + /* Allocate memory space */ + memory_region_add_subregion(sysmem, SDRAM_BASE, machine->ram); + + /* Initialize MCU */ + object_initialize_child(OBJECT(machine), "mcu", &s->mcu, rxc->mcu_name); + object_property_set_link(OBJECT(&s->mcu), "main-bus", OBJECT(sysmem), + &error_abort); + object_property_set_uint(OBJECT(&s->mcu), "xtal-frequency-hz", + rxc->xtal_freq_hz, &error_abort); + object_property_set_bool(OBJECT(&s->mcu), "load-kernel", + kernel_filename != NULL, &error_abort); + qdev_realize(DEVICE(&s->mcu), NULL, &error_abort); + + /* Load kernel and dtb */ + if (kernel_filename) { + ram_addr_t kernel_offset; + + /* + * The kernel image is loaded into + * the latter half of the SDRAM space. + */ + kernel_offset = machine->ram_size / 2; + rx_load_image(RX_CPU(first_cpu), kernel_filename, + SDRAM_BASE + kernel_offset, kernel_offset); + if (dtb_filename) { + ram_addr_t dtb_offset; + int dtb_size; + g_autofree void *dtb = load_device_tree(dtb_filename, &dtb_size); + + if (dtb == NULL) { + error_report("Couldn't open dtb file %s", dtb_filename); + exit(1); + } + if (machine->kernel_cmdline && + qemu_fdt_setprop_string(dtb, "/chosen", "bootargs", + machine->kernel_cmdline) < 0) { + error_report("Couldn't set /chosen/bootargs"); + exit(1); + } + /* DTB is located at the end of SDRAM space. */ + dtb_offset = machine->ram_size - dtb_size; + rom_add_blob_fixed("dtb", dtb, dtb_size, + SDRAM_BASE + dtb_offset); + /* Set dtb address to R1 */ + RX_CPU(first_cpu)->env.regs[1] = SDRAM_BASE + dtb_offset; + } + } +} + +static void rx_gdbsim_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->init = rx_gdbsim_init; + mc->default_cpu_type = TYPE_RX62N_CPU; + mc->default_ram_size = 16 * MiB; + mc->default_ram_id = "ext-sdram"; +} + +static void rx62n7_class_init(ObjectClass *oc, void *data) +{ + RxGdbSimMachineClass *rxc = RX_GDBSIM_MACHINE_CLASS(oc); + MachineClass *mc = MACHINE_CLASS(oc); + + rxc->mcu_name = TYPE_R5F562N7_MCU; + rxc->xtal_freq_hz = 12 * 1000 * 1000; + mc->desc = "gdb simulator (R5F562N7 MCU and external RAM)"; +}; + +static void rx62n8_class_init(ObjectClass *oc, void *data) +{ + RxGdbSimMachineClass *rxc = RX_GDBSIM_MACHINE_CLASS(oc); + MachineClass *mc = MACHINE_CLASS(oc); + + rxc->mcu_name = TYPE_R5F562N8_MCU; + rxc->xtal_freq_hz = 12 * 1000 * 1000; + mc->desc = "gdb simulator (R5F562N8 MCU and external RAM)"; +}; + +static const TypeInfo rx_gdbsim_types[] = { + { + .name = MACHINE_TYPE_NAME("gdbsim-r5f562n7"), + .parent = TYPE_RX_GDBSIM_MACHINE, + .class_init = rx62n7_class_init, + }, { + .name = MACHINE_TYPE_NAME("gdbsim-r5f562n8"), + .parent = TYPE_RX_GDBSIM_MACHINE, + .class_init = rx62n8_class_init, + }, { + .name = TYPE_RX_GDBSIM_MACHINE, + .parent = TYPE_MACHINE, + .instance_size = sizeof(RxGdbSimMachineState), + .class_size = sizeof(RxGdbSimMachineClass), + .class_init = rx_gdbsim_class_init, + .abstract = true, + } +}; + +DEFINE_TYPES(rx_gdbsim_types) diff --git a/hw/rx/rx62n.c b/hw/rx/rx62n.c new file mode 100644 index 0000000000000000000000000000000000000000..6eb4eea700518fab79804f4a6cf938bf54e0bd0a --- /dev/null +++ b/hw/rx/rx62n.c @@ -0,0 +1,323 @@ +/* + * RX62N Microcontroller + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * + * Copyright (c) 2019 Yoshinori Sato + * Copyright (c) 2020 Philippe Mathieu-DaudĂ© + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "hw/hw.h" +#include "hw/rx/rx62n.h" +#include "hw/loader.h" +#include "hw/sysbus.h" +#include "hw/qdev-properties.h" +#include "sysemu/sysemu.h" +#include "sysemu/qtest.h" +#include "cpu.h" +#include "qom/object.h" + +/* + * RX62N Internal Memory + */ +#define RX62N_IRAM_BASE 0x00000000 +#define RX62N_DFLASH_BASE 0x00100000 +#define RX62N_CFLASH_BASE 0xfff80000 + +/* + * RX62N Peripheral Address + * See users manual section 5 + */ +#define RX62N_ICU_BASE 0x00087000 +#define RX62N_TMR_BASE 0x00088200 +#define RX62N_CMT_BASE 0x00088000 +#define RX62N_SCI_BASE 0x00088240 + +/* + * RX62N Peripheral IRQ + * See users manual section 11 + */ +#define RX62N_TMR_IRQ 174 +#define RX62N_CMT_IRQ 28 +#define RX62N_SCI_IRQ 214 + +#define RX62N_XTAL_MIN_HZ (8 * 1000 * 1000) +#define RX62N_XTAL_MAX_HZ (14 * 1000 * 1000) +#define RX62N_PCLK_MAX_HZ (50 * 1000 * 1000) + +struct RX62NClass { + /*< private >*/ + DeviceClass parent_class; + /*< public >*/ + const char *name; + uint64_t ram_size; + uint64_t rom_flash_size; + uint64_t data_flash_size; +}; +typedef struct RX62NClass RX62NClass; + +DECLARE_CLASS_CHECKERS(RX62NClass, RX62N_MCU, + TYPE_RX62N_MCU) + +/* + * IRQ -> IPR mapping table + * 0x00 - 0x91: IPR no (IPR00 to IPR91) + * 0xff: IPR not assigned + * See "11.3.1 Interrupt Vector Table" in hardware manual. + */ +static const uint8_t ipr_table[NR_IRQS] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 15 */ + 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x02, + 0xff, 0xff, 0xff, 0x03, 0x04, 0x05, 0x06, 0x07, /* 31 */ + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x14, 0x14, 0x14, /* 47 */ + 0x15, 0x15, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1d, 0x1e, 0x1f, /* 63 */ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 79 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x3a, 0x3b, 0x3c, 0xff, 0xff, 0xff, /* 95 */ + 0x40, 0xff, 0x44, 0x45, 0xff, 0xff, 0x48, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 111 */ + 0xff, 0xff, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52, + 0x52, 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, /* 127 */ + 0x56, 0x57, 0x57, 0x57, 0x57, 0x58, 0x59, 0x59, + 0x59, 0x59, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, /* 143 */ + 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, + 0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x62, /* 159 */ + 0x62, 0x63, 0x64, 0x64, 0x64, 0x64, 0x65, 0x66, + 0x66, 0x66, 0x67, 0x67, 0x67, 0x67, 0x68, 0x68, /* 175 */ + 0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, + 0x6b, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 191 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x71, + 0x72, 0x73, 0x74, 0x75, 0xff, 0xff, 0xff, 0xff, /* 207 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, + 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, /* 223 */ + 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0xff, 0xff, + 0xff, 0xff, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, /* 239 */ + 0x86, 0x86, 0xff, 0xff, 0xff, 0xff, 0x88, 0x89, + 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, /* 255 */ +}; + +/* + * Level triggerd IRQ list + * Not listed IRQ is Edge trigger. + * See "11.3.1 Interrupt Vector Table" in hardware manual. + */ +static const uint8_t levelirq[] = { + 16, 21, 32, 44, 47, 48, 51, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 90, 91, 170, 171, 172, 173, 214, + 217, 218, 221, 222, 225, 226, 229, 234, 237, 238, + 241, 246, 249, 250, 253, +}; + +static void register_icu(RX62NState *s) +{ + int i; + SysBusDevice *icu; + + object_initialize_child(OBJECT(s), "icu", &s->icu, TYPE_RX_ICU); + icu = SYS_BUS_DEVICE(&s->icu); + qdev_prop_set_uint32(DEVICE(icu), "len-ipr-map", NR_IRQS); + for (i = 0; i < NR_IRQS; i++) { + char propname[32]; + snprintf(propname, sizeof(propname), "ipr-map[%d]", i); + qdev_prop_set_uint32(DEVICE(icu), propname, ipr_table[i]); + } + qdev_prop_set_uint32(DEVICE(icu), "len-trigger-level", + ARRAY_SIZE(levelirq)); + for (i = 0; i < ARRAY_SIZE(levelirq); i++) { + char propname[32]; + snprintf(propname, sizeof(propname), "trigger-level[%d]", i); + qdev_prop_set_uint32(DEVICE(icu), propname, levelirq[i]); + } + + for (i = 0; i < NR_IRQS; i++) { + s->irq[i] = qdev_get_gpio_in(DEVICE(icu), i); + } + sysbus_realize(icu, &error_abort); + sysbus_connect_irq(icu, 0, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_IRQ)); + sysbus_connect_irq(icu, 1, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_FIR)); + sysbus_connect_irq(icu, 2, s->irq[SWI]); + sysbus_mmio_map(SYS_BUS_DEVICE(icu), 0, RX62N_ICU_BASE); +} + +static void register_tmr(RX62NState *s, int unit) +{ + SysBusDevice *tmr; + int i, irqbase; + + object_initialize_child(OBJECT(s), "tmr[*]", + &s->tmr[unit], TYPE_RENESAS_TMR); + tmr = SYS_BUS_DEVICE(&s->tmr[unit]); + qdev_prop_set_uint64(DEVICE(tmr), "input-freq", s->pclk_freq_hz); + sysbus_realize(tmr, &error_abort); + + irqbase = RX62N_TMR_IRQ + TMR_NR_IRQ * unit; + for (i = 0; i < TMR_NR_IRQ; i++) { + sysbus_connect_irq(tmr, i, s->irq[irqbase + i]); + } + sysbus_mmio_map(tmr, 0, RX62N_TMR_BASE + unit * 0x10); +} + +static void register_cmt(RX62NState *s, int unit) +{ + SysBusDevice *cmt; + int i, irqbase; + + object_initialize_child(OBJECT(s), "cmt[*]", + &s->cmt[unit], TYPE_RENESAS_CMT); + cmt = SYS_BUS_DEVICE(&s->cmt[unit]); + qdev_prop_set_uint64(DEVICE(cmt), "input-freq", s->pclk_freq_hz); + sysbus_realize(cmt, &error_abort); + + irqbase = RX62N_CMT_IRQ + CMT_NR_IRQ * unit; + for (i = 0; i < CMT_NR_IRQ; i++) { + sysbus_connect_irq(cmt, i, s->irq[irqbase + i]); + } + sysbus_mmio_map(cmt, 0, RX62N_CMT_BASE + unit * 0x10); +} + +static void register_sci(RX62NState *s, int unit) +{ + SysBusDevice *sci; + int i, irqbase; + + object_initialize_child(OBJECT(s), "sci[*]", + &s->sci[unit], TYPE_RENESAS_SCI); + sci = SYS_BUS_DEVICE(&s->sci[unit]); + qdev_prop_set_chr(DEVICE(sci), "chardev", serial_hd(unit)); + qdev_prop_set_uint64(DEVICE(sci), "input-freq", s->pclk_freq_hz); + sysbus_realize(sci, &error_abort); + + irqbase = RX62N_SCI_IRQ + SCI_NR_IRQ * unit; + for (i = 0; i < SCI_NR_IRQ; i++) { + sysbus_connect_irq(sci, i, s->irq[irqbase + i]); + } + sysbus_mmio_map(sci, 0, RX62N_SCI_BASE + unit * 0x08); +} + +static void rx62n_realize(DeviceState *dev, Error **errp) +{ + RX62NState *s = RX62N_MCU(dev); + RX62NClass *rxc = RX62N_MCU_GET_CLASS(dev); + + if (s->xtal_freq_hz == 0) { + error_setg(errp, "\"xtal-frequency-hz\" property must be provided."); + return; + } + /* XTAL range: 8-14 MHz */ + if (s->xtal_freq_hz < RX62N_XTAL_MIN_HZ + || s->xtal_freq_hz > RX62N_XTAL_MAX_HZ) { + error_setg(errp, "\"xtal-frequency-hz\" property in incorrect range."); + return; + } + /* Use a 4x fixed multiplier */ + s->pclk_freq_hz = 4 * s->xtal_freq_hz; + /* PCLK range: 8-50 MHz */ + assert(s->pclk_freq_hz <= RX62N_PCLK_MAX_HZ); + + memory_region_init_ram(&s->iram, OBJECT(dev), "iram", + rxc->ram_size, &error_abort); + memory_region_add_subregion(s->sysmem, RX62N_IRAM_BASE, &s->iram); + memory_region_init_rom(&s->d_flash, OBJECT(dev), "flash-data", + rxc->data_flash_size, &error_abort); + memory_region_add_subregion(s->sysmem, RX62N_DFLASH_BASE, &s->d_flash); + memory_region_init_rom(&s->c_flash, OBJECT(dev), "flash-code", + rxc->rom_flash_size, &error_abort); + memory_region_add_subregion(s->sysmem, RX62N_CFLASH_BASE, &s->c_flash); + + if (!s->kernel) { + if (bios_name) { + rom_add_file_fixed(bios_name, RX62N_CFLASH_BASE, 0); + } else if (!qtest_enabled()) { + error_report("No bios or kernel specified"); + exit(1); + } + } + + /* Initialize CPU */ + object_initialize_child(OBJECT(s), "cpu", &s->cpu, TYPE_RX62N_CPU); + qdev_realize(DEVICE(&s->cpu), NULL, &error_abort); + + register_icu(s); + s->cpu.env.ack = qdev_get_gpio_in_named(DEVICE(&s->icu), "ack", 0); + register_tmr(s, 0); + register_tmr(s, 1); + register_cmt(s, 0); + register_cmt(s, 1); + register_sci(s, 0); +} + +static Property rx62n_properties[] = { + DEFINE_PROP_LINK("main-bus", RX62NState, sysmem, TYPE_MEMORY_REGION, + MemoryRegion *), + DEFINE_PROP_BOOL("load-kernel", RX62NState, kernel, false), + DEFINE_PROP_UINT32("xtal-frequency-hz", RX62NState, xtal_freq_hz, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void rx62n_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = rx62n_realize; + device_class_set_props(dc, rx62n_properties); +} + +static void r5f562n7_class_init(ObjectClass *oc, void *data) +{ + RX62NClass *rxc = RX62N_MCU_CLASS(oc); + + rxc->ram_size = 64 * KiB; + rxc->rom_flash_size = 384 * KiB; + rxc->data_flash_size = 32 * KiB; +}; + +static void r5f562n8_class_init(ObjectClass *oc, void *data) +{ + RX62NClass *rxc = RX62N_MCU_CLASS(oc); + + rxc->ram_size = 96 * KiB; + rxc->rom_flash_size = 512 * KiB; + rxc->data_flash_size = 32 * KiB; +}; + +static const TypeInfo rx62n_types[] = { + { + .name = TYPE_R5F562N7_MCU, + .parent = TYPE_RX62N_MCU, + .class_init = r5f562n7_class_init, + }, { + .name = TYPE_R5F562N8_MCU, + .parent = TYPE_RX62N_MCU, + .class_init = r5f562n8_class_init, + }, { + .name = TYPE_RX62N_MCU, + .parent = TYPE_DEVICE, + .instance_size = sizeof(RX62NState), + .class_size = sizeof(RX62NClass), + .class_init = rx62n_class_init, + .abstract = true, + } +}; + +DEFINE_TYPES(rx62n_types) diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs deleted file mode 100644 index a46a1c7894e0f612a2d74cec74f6d0c3ff8840a0..0000000000000000000000000000000000000000 --- a/hw/s390x/Makefile.objs +++ /dev/null @@ -1,37 +0,0 @@ -obj-y += s390-virtio-hcall.o -obj-y += sclp.o -obj-y += event-facility.o -obj-y += sclpquiesce.o -obj-y += sclpcpu.o -obj-y += ipl.o -obj-y += css.o -obj-$(CONFIG_S390_CCW_VIRTIO) += s390-virtio-ccw.o -obj-$(CONFIG_TERMINAL3270) += 3270-ccw.o -ifeq ($(CONFIG_VIRTIO_CCW),y) -obj-y += virtio-ccw.o -obj-$(CONFIG_VIRTIO_SERIAL) += virtio-ccw-serial.o -obj-$(CONFIG_VIRTIO_BALLOON) += virtio-ccw-balloon.o -obj-$(CONFIG_VIRTIO_SCSI) += virtio-ccw-scsi.o -obj-$(CONFIG_VIRTIO_RNG) += virtio-ccw-rng.o -obj-$(CONFIG_VIRTIO_CRYPTO) += virtio-ccw-crypto.o -obj-$(CONFIG_VIRTIO_GPU) += virtio-ccw-gpu.o -obj-$(CONFIG_VIRTIO_INPUT) += virtio-ccw-input.o -obj-$(CONFIG_VIRTIO_NET) += virtio-ccw-net.o -obj-$(CONFIG_VIRTIO_BLK) += virtio-ccw-blk.o -obj-$(call land,$(CONFIG_VIRTIO_9P),$(CONFIG_VIRTFS)) += virtio-ccw-9p.o -obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock-ccw.o -endif -obj-y += css-bridge.o -obj-y += ccw-device.o -obj-y += s390-pci-bus.o s390-pci-inst.o -obj-y += s390-skeys.o -obj-y += s390-stattrib.o -obj-y += tod.o -obj-y += tod-qemu.o -obj-$(CONFIG_KVM) += tod-kvm.o -obj-$(CONFIG_KVM) += s390-skeys-kvm.o -obj-$(CONFIG_KVM) += s390-stattrib-kvm.o -obj-$(CONFIG_KVM) += pv.o -obj-y += s390-ccw.o -obj-y += ap-device.o -obj-y += ap-bridge.o diff --git a/hw/s390x/ap-bridge.c b/hw/s390x/ap-bridge.c index d0dbd0f1b6423ac9b5a0f766b35688f3f20c185e..8bcf8ece9dd651b01d532054b7ae39c45824cf2d 100644 --- a/hw/s390x/ap-bridge.c +++ b/hw/s390x/ap-bridge.c @@ -49,16 +49,16 @@ void s390_init_ap(void) } /* Create bridge device */ - dev = qdev_create(NULL, TYPE_AP_BRIDGE); + dev = qdev_new(TYPE_AP_BRIDGE); object_property_add_child(qdev_get_machine(), TYPE_AP_BRIDGE, OBJECT(dev)); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); /* Create bus on bridge device */ bus = qbus_create(TYPE_AP_BUS, dev, TYPE_AP_BUS); /* Enable hotplugging */ - qbus_set_hotplug_handler(bus, OBJECT(dev), &error_abort); + qbus_set_hotplug_handler(bus, OBJECT(dev)); } static void ap_bridge_class_init(ObjectClass *oc, void *data) diff --git a/hw/s390x/ap-device.c b/hw/s390x/ap-device.c index fc0b41e9373bc18b9582ab530ddadb78a3119d56..237d1f19c50409ab9de9eb413c59cacccbd03a3c 100644 --- a/hw/s390x/ap-device.c +++ b/hw/s390x/ap-device.c @@ -21,7 +21,7 @@ static void ap_class_init(ObjectClass *klass, void *data) } static const TypeInfo ap_device_info = { - .name = AP_DEVICE_TYPE, + .name = TYPE_AP_DEVICE, .parent = TYPE_DEVICE, .instance_size = sizeof(APDevice), .class_size = sizeof(DeviceClass), diff --git a/hw/s390x/ccw-device.h b/hw/s390x/ccw-device.h index 4e6af287e768c09e34e7a6b7eaefcfd0b7e27faf..832c78cd4213194794e14df60278d042bfad2d2c 100644 --- a/hw/s390x/ccw-device.h +++ b/hw/s390x/ccw-device.h @@ -15,7 +15,7 @@ #include "hw/qdev-core.h" #include "hw/s390x/css.h" -typedef struct CcwDevice { +struct CcwDevice { DeviceState parent_obj; SubchDev *sch; /* .. */ @@ -25,18 +25,19 @@ typedef struct CcwDevice { CssDevId dev_id; /* The actual busid of the virtual subchannel. */ CssDevId subch_id; -} CcwDevice; +}; +typedef struct CcwDevice CcwDevice; extern const VMStateDescription vmstate_ccw_dev; #define VMSTATE_CCW_DEVICE(_field, _state) \ VMSTATE_STRUCT(_field, _state, 1, vmstate_ccw_dev, CcwDevice) -typedef struct CCWDeviceClass { +struct CCWDeviceClass { DeviceClass parent_class; void (*unplug)(HotplugHandler *, DeviceState *, Error **); void (*realize)(CcwDevice *, Error **); void (*refill_ids)(CcwDevice *); -} CCWDeviceClass; +}; static inline CcwDevice *to_ccw_dev_fast(DeviceState *d) { @@ -45,10 +46,6 @@ static inline CcwDevice *to_ccw_dev_fast(DeviceState *d) #define TYPE_CCW_DEVICE "ccw-device" -#define CCW_DEVICE(obj) OBJECT_CHECK(CcwDevice, (obj), TYPE_CCW_DEVICE) -#define CCW_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(CCWDeviceClass, (obj), TYPE_CCW_DEVICE) -#define CCW_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(CCWDeviceClass, (klass), TYPE_CCW_DEVICE) +OBJECT_DECLARE_TYPE(CcwDevice, CCWDeviceClass, CCW_DEVICE) #endif diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c index 3f6aec6b6a776716d40dfe5a34edb7ef0699a491..9d793d671e19aee3f5205737944ac4ce07b6e1a6 100644 --- a/hw/s390x/css-bridge.c +++ b/hw/s390x/css-bridge.c @@ -54,7 +54,7 @@ static void ccw_device_unplug(HotplugHandler *hotplug_dev, css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0); - object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + qdev_unrealize(dev); } static void virtual_css_bus_reset(BusState *qbus) @@ -101,17 +101,17 @@ VirtualCssBus *virtual_css_bus_init(void) DeviceState *dev; /* Create bridge device */ - dev = qdev_create(NULL, TYPE_VIRTUAL_CSS_BRIDGE); + dev = qdev_new(TYPE_VIRTUAL_CSS_BRIDGE); object_property_add_child(qdev_get_machine(), TYPE_VIRTUAL_CSS_BRIDGE, OBJECT(dev)); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); /* Create bus on bridge device */ bus = qbus_create(TYPE_VIRTUAL_CSS_BUS, dev, "virtual-css"); cbus = VIRTUAL_CSS_BUS(bus); /* Enable hotplugging */ - qbus_set_hotplug_handler(bus, OBJECT(dev), &error_abort); + qbus_set_hotplug_handler(bus, OBJECT(dev)); css_register_io_adapters(CSS_IO_ADAPTER_VIRTIO, true, false, 0, &error_abort); diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 5d8e08667e6f914117cd6c23a6fb99e3c18f3f52..9961cfe7bf67460924ea68cb72bd3692168749fe 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -353,7 +353,6 @@ static ChannelSubSys channel_subsys = { .pending_crws = QTAILQ_HEAD_INITIALIZER(channel_subsys.pending_crws), .do_crw_mchk = true, .sei_pending = false, - .do_crw_mchk = true, .crws_lost = false, .chnmon_active = false, .indicator_addresses = @@ -1335,11 +1334,20 @@ static void copy_schib_to_guest(SCHIB *dest, const SCHIB *src) } } -int css_do_stsch(SubchDev *sch, SCHIB *schib) +IOInstEnding css_do_stsch(SubchDev *sch, SCHIB *schib) { + int ret; + + /* + * For some subchannels, we may want to update parts of + * the schib (e.g., update path masks from the host device + * for passthrough subchannels). + */ + ret = s390_ccw_store(sch); + /* Use current status. */ copy_schib_to_guest(schib, &sch->curr_status); - return 0; + return ret; } static void copy_pmcw_from_guest(PMCW *dest, const PMCW *src) @@ -2161,30 +2169,23 @@ void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid, } } -void css_queue_crw(uint8_t rsc, uint8_t erc, int solicited, - int chain, uint16_t rsid) +void css_crw_add_to_queue(CRW crw) { CrwContainer *crw_cont; - trace_css_crw(rsc, erc, rsid, chain ? "(chained)" : ""); + trace_css_crw((crw.flags & CRW_FLAGS_MASK_RSC) >> 8, + crw.flags & CRW_FLAGS_MASK_ERC, + crw.rsid, + (crw.flags & CRW_FLAGS_MASK_C) ? "(chained)" : ""); + /* TODO: Maybe use a static crw pool? */ crw_cont = g_try_new0(CrwContainer, 1); if (!crw_cont) { channel_subsys.crws_lost = true; return; } - crw_cont->crw.flags = (rsc << 8) | erc; - if (solicited) { - crw_cont->crw.flags |= CRW_FLAGS_MASK_S; - } - if (chain) { - crw_cont->crw.flags |= CRW_FLAGS_MASK_C; - } - crw_cont->crw.rsid = rsid; - if (channel_subsys.crws_lost) { - crw_cont->crw.flags |= CRW_FLAGS_MASK_R; - channel_subsys.crws_lost = false; - } + + crw_cont->crw = crw; QTAILQ_INSERT_TAIL(&channel_subsys.pending_crws, crw_cont, sibling); @@ -2195,6 +2196,27 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int solicited, } } +void css_queue_crw(uint8_t rsc, uint8_t erc, int solicited, + int chain, uint16_t rsid) +{ + CRW crw; + + crw.flags = (rsc << 8) | erc; + if (solicited) { + crw.flags |= CRW_FLAGS_MASK_S; + } + if (chain) { + crw.flags |= CRW_FLAGS_MASK_C; + } + crw.rsid = rsid; + if (channel_subsys.crws_lost) { + crw.flags |= CRW_FLAGS_MASK_R; + channel_subsys.crws_lost = false; + } + + css_crw_add_to_queue(crw); +} + void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, int hotplugged, int add) { @@ -2354,7 +2376,6 @@ static void set_css_devid(Object *obj, Visitor *v, const char *name, DeviceState *dev = DEVICE(obj); Property *prop = opaque; CssDevId *dev_id = qdev_get_prop_ptr(dev, prop); - Error *local_err = NULL; char *str; int num, n1, n2; unsigned int cssid, ssid, devid; @@ -2364,9 +2385,7 @@ static void set_css_devid(Object *obj, Visitor *v, const char *name, return; } - visit_type_str(v, name, &str, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_str(v, name, &str, errp)) { return; } diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c index 97a4f0b1f51ca3fc565c62c75b57f8f14b5ce2be..ed92ce510d9e73315c3cda5a180e72f69ddb5b1f 100644 --- a/hw/s390x/event-facility.c +++ b/hw/s390x/event-facility.c @@ -39,6 +39,7 @@ typedef struct SCLPEventsBus { struct SCLPEventFacility { SysBusDevice parent_obj; SCLPEventsBus sbus; + SCLPEvent quiesce, cpu_hotplug; /* guest's receive mask */ union { uint32_t receive_mask_pieces[2]; @@ -212,7 +213,7 @@ static uint16_t handle_sccb_read_events(SCLPEventFacility *ef, SCCB *sccb, event_buf = &red->ebh; event_buf->length = 0; - slen = sizeof(sccb->data); + slen = sccb_data_len(sccb); rc = SCLP_RC_NO_EVENT_BUFFERS_STORED; @@ -328,34 +329,9 @@ static void write_event_mask(SCLPEventFacility *ef, SCCB *sccb) #define TYPE_SCLP_EVENTS_BUS "s390-sclp-events-bus" -static void sclp_events_bus_realize(BusState *bus, Error **errp) -{ - Error *err = NULL; - BusChild *kid; - - /* TODO: recursive realization has to be done in common code */ - QTAILQ_FOREACH(kid, &bus->children, sibling) { - DeviceState *dev = kid->child; - - object_property_set_bool(OBJECT(dev), true, "realized", &err); - if (err) { - error_propagate(errp, err); - return; - } - } -} - -static void sclp_events_bus_class_init(ObjectClass *klass, void *data) -{ - BusClass *bc = BUS_CLASS(klass); - - bc->realize = sclp_events_bus_realize; -} - static const TypeInfo sclp_events_bus_info = { .name = TYPE_SCLP_EVENTS_BUS, .parent = TYPE_BUS, - .class_init = sclp_events_bus_class_init, }; static void command_handler(SCLPEventFacility *ef, SCCB *sccb, uint64_t code) @@ -443,27 +419,39 @@ static void init_event_facility(Object *obj) { SCLPEventFacility *event_facility = EVENT_FACILITY(obj); DeviceState *sdev = DEVICE(obj); - Object *new; event_facility->mask_length = 4; event_facility->allow_all_mask_sizes = true; object_property_add_bool(obj, "allow_all_mask_sizes", sclp_event_get_allow_all_mask_sizes, sclp_event_set_allow_all_mask_sizes); + /* Spawn a new bus for SCLP events */ qbus_create_inplace(&event_facility->sbus, sizeof(event_facility->sbus), TYPE_SCLP_EVENTS_BUS, sdev, NULL); - new = object_new(TYPE_SCLP_QUIESCE); - object_property_add_child(obj, TYPE_SCLP_QUIESCE, new); - object_unref(new); - qdev_set_parent_bus(DEVICE(new), BUS(&event_facility->sbus)); + object_initialize_child(obj, TYPE_SCLP_QUIESCE, + &event_facility->quiesce, + TYPE_SCLP_QUIESCE); - new = object_new(TYPE_SCLP_CPU_HOTPLUG); - object_property_add_child(obj, TYPE_SCLP_CPU_HOTPLUG, new); - object_unref(new); - qdev_set_parent_bus(DEVICE(new), BUS(&event_facility->sbus)); - /* the facility will automatically realize the devices via the bus */ + object_initialize_child(obj, TYPE_SCLP_CPU_HOTPLUG, + &event_facility->cpu_hotplug, + TYPE_SCLP_CPU_HOTPLUG); +} + +static void realize_event_facility(DeviceState *dev, Error **errp) +{ + SCLPEventFacility *event_facility = EVENT_FACILITY(dev); + + if (!qdev_realize(DEVICE(&event_facility->quiesce), + BUS(&event_facility->sbus), errp)) { + return; + } + if (!qdev_realize(DEVICE(&event_facility->cpu_hotplug), + BUS(&event_facility->sbus), errp)) { + qdev_unrealize(DEVICE(&event_facility->quiesce)); + return; + } } static void reset_event_facility(DeviceState *dev) @@ -479,6 +467,7 @@ static void init_event_facility_class(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(sbdc); SCLPEventFacilityClass *k = EVENT_FACILITY_CLASS(dc); + dc->realize = realize_event_facility; dc->reset = reset_event_facility; dc->vmsd = &vmstate_event_facility; set_bit(DEVICE_CATEGORY_MISC, dc->categories); diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index ce21494c08f77a35269b5e4b3ad5763eb6e76e7b..3d2652d75abde36e59ebbf79b34f1eae7fc8d4e1 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -117,7 +117,6 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) uint64_t pentry; char *magic; int kernel_size; - Error *err = NULL; int bios_size; char *bios_filename; @@ -135,8 +134,8 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (bios_filename == NULL) { - error_setg(&err, "could not find stage1 bootloader"); - goto error; + error_setg(errp, "could not find stage1 bootloader"); + return; } bios_size = load_elf(bios_filename, NULL, @@ -155,8 +154,8 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) g_free(bios_filename); if (bios_size == -1) { - error_setg(&err, "could not load bootloader '%s'", bios_name); - goto error; + error_setg(errp, "could not load bootloader '%s'", bios_name); + return; } /* default boot target is the bios */ @@ -170,8 +169,8 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) if (kernel_size < 0) { kernel_size = load_image_targphys(ipl->kernel, 0, ram_size); if (kernel_size < 0) { - error_setg(&err, "could not load kernel '%s'", ipl->kernel); - goto error; + error_setg(errp, "could not load kernel '%s'", ipl->kernel); + return; } /* if this is Linux use KERN_IMAGE_START */ magic = rom_ptr(LINUX_MAGIC_ADDR, 6); @@ -183,8 +182,8 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) if (ipl_psw) { pentry = be32_to_cpu(*ipl_psw) & PSW_MASK_SHORT_ADDR; } else { - error_setg(&err, "Could not get IPL PSW"); - goto error; + error_setg(errp, "Could not get IPL PSW"); + return; } } } @@ -217,8 +216,8 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) initrd_size = load_image_targphys(ipl->initrd, initrd_offset, ram_size - initrd_offset); if (initrd_size == -1) { - error_setg(&err, "could not load initrd '%s'", ipl->initrd); - goto error; + error_setg(errp, "could not load initrd '%s'", ipl->initrd); + return; } /* @@ -248,8 +247,6 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) * TODO: there should be a better way to do this. */ qemu_register_reset(resettable_cold_reset_fn, dev); -error: - error_propagate(errp, err); } static Property s390_ipl_properties[] = { @@ -555,9 +552,9 @@ static void update_machine_ipl_properties(IplParameterBlock *iplb) ascii_loadparm[i] = ebcdic2ascii[(uint8_t) ebcdic_loadparm[i]]; } ascii_loadparm[i] = 0; - object_property_set_str(machine, ascii_loadparm, "loadparm", &err); + object_property_set_str(machine, "loadparm", ascii_loadparm, &err); } else { - object_property_set_str(machine, "", "loadparm", &err); + object_property_set_str(machine, "loadparm", "", &err); } if (err) { warn_report_err(err); @@ -633,7 +630,8 @@ void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type) } } if (reset_type == S390_RESET_MODIFIED_CLEAR || - reset_type == S390_RESET_LOAD_NORMAL) { + reset_type == S390_RESET_LOAD_NORMAL || + reset_type == S390_RESET_PV) { /* ignore -no-reboot, send no event */ qemu_system_reset_request(SHUTDOWN_CAUSE_SUBSYSTEM_RESET); } else { diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h index 53cc9eb5ac4d326b2b61bf1668a807110d53c624..dfc6dfd89c886cf821dfdd1e119930791c6871ba 100644 --- a/hw/s390x/ipl.h +++ b/hw/s390x/ipl.h @@ -16,6 +16,7 @@ #include "cpu.h" #include "exec/address-spaces.h" #include "hw/qdev-core.h" +#include "qom/object.h" struct IPLBlockPVComp { uint64_t tweak_pref; @@ -31,7 +32,7 @@ struct IPLBlockPV { uint32_t num_comp; /* 0x74 */ uint64_t pv_header_addr; /* 0x78 */ uint64_t pv_header_len; /* 0x80 */ - struct IPLBlockPVComp components[]; + struct IPLBlockPVComp components[0]; } QEMU_PACKED; typedef struct IPLBlockPV IPLBlockPV; @@ -62,7 +63,7 @@ struct IplBlockFcp { uint64_t br_lba; uint32_t scp_data_len; uint8_t reserved6[260]; - uint8_t scp_data[]; + uint8_t scp_data[0]; } QEMU_PACKED; typedef struct IplBlockFcp IplBlockFcp; @@ -152,7 +153,7 @@ struct QemuIplParameters { typedef struct QemuIplParameters QemuIplParameters; #define TYPE_S390_IPL "s390-ipl" -#define S390_IPL(obj) OBJECT_CHECK(S390IPLState, (obj), TYPE_S390_IPL) +OBJECT_DECLARE_SIMPLE_TYPE(S390IPLState, S390_IPL) struct S390IPLState { /*< private >*/ @@ -183,7 +184,6 @@ struct S390IPLState { uint16_t devno; bool iplbext_migration; }; -typedef struct S390IPLState S390IPLState; QEMU_BUILD_BUG_MSG(offsetof(S390IPLState, iplb) & 3, "alignment of iplb wrong"); #define DIAG_308_RC_OK 0x0001 diff --git a/hw/s390x/meson.build b/hw/s390x/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..2a7818d94b94d3832c0e944ecc42711ffd1c28a6 --- /dev/null +++ b/hw/s390x/meson.build @@ -0,0 +1,48 @@ +s390x_ss = ss.source_set() +s390x_ss.add(files( + 'ap-bridge.c', + 'ap-device.c', + 'ccw-device.c', + 'css-bridge.c', + 'css.c', + 'event-facility.c', + 'ipl.c', + 's390-ccw.c', + 's390-pci-bus.c', + 's390-pci-inst.c', + 's390-skeys.c', + 's390-stattrib.c', + 's390-virtio-hcall.c', + 'sclp.c', + 'sclpcpu.c', + 'sclpquiesce.c', + 'tod-qemu.c', + 'tod.c', +)) +s390x_ss.add(when: 'CONFIG_KVM', if_true: files( + 'tod-kvm.c', + 's390-skeys-kvm.c', + 's390-stattrib-kvm.c', + 'pv.c', +)) +s390x_ss.add(when: 'CONFIG_S390_CCW_VIRTIO', if_true: files('s390-virtio-ccw.c')) +s390x_ss.add(when: 'CONFIG_TERMINAL3270', if_true: files('3270-ccw.c')) +s390x_ss.add(when: 'CONFIG_VFIO', if_true: files('s390-pci-vfio.c')) + +virtio_ss = ss.source_set() +virtio_ss.add(files('virtio-ccw.c')) +virtio_ss.add(when: 'CONFIG_VIRTIO_BALLOON', if_true: files('virtio-ccw-balloon.c')) +virtio_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-ccw-blk.c')) +virtio_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('virtio-ccw-crypto.c')) +virtio_ss.add(when: 'CONFIG_VIRTIO_GPU', if_true: files('virtio-ccw-gpu.c')) +virtio_ss.add(when: 'CONFIG_VIRTIO_INPUT', if_true: files('virtio-ccw-input.c')) +virtio_ss.add(when: 'CONFIG_VIRTIO_NET', if_true: files('virtio-ccw-net.c')) +virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-ccw-rng.c')) +virtio_ss.add(when: 'CONFIG_VIRTIO_SCSI', if_true: files('virtio-ccw-scsi.c')) +virtio_ss.add(when: 'CONFIG_VIRTIO_SERIAL', if_true: files('virtio-ccw-serial.c')) +virtio_ss.add(when: ['CONFIG_VIRTIO_9P', 'CONFIG_VIRTFS'], if_true: files('virtio-ccw-blk.c')) +virtio_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock-ccw.c')) +virtio_ss.add(when: 'CONFIG_VHOST_USER_FS', if_true: files('vhost-user-fs-ccw.c')) +s390x_ss.add_all(when: 'CONFIG_VIRTIO_CCW', if_true: virtio_ss) + +hw_arch += {'s390x': s390x_ss} diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c index f11868e865fa0910182cc11275bf9a8516cfb466..ab3a2482aad73ed5faf32e49789a2ea7ff0d6e05 100644 --- a/hw/s390x/pv.c +++ b/hw/s390x/pv.c @@ -88,7 +88,7 @@ int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) return s390_pv_cmd(KVM_PV_UNPACK, &args); } -void s390_pv_perf_clear_reset(void) +void s390_pv_prep_reset(void) { s390_pv_cmd_exit(KVM_PV_PREP_RESET, NULL); } diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c index c48510f9e5430f28f122f05b92b534e204a84a12..b497571863f692f4cf34578947f9dcca35b344da 100644 --- a/hw/s390x/s390-ccw.c +++ b/hw/s390x/s390-ccw.c @@ -51,6 +51,27 @@ int s390_ccw_clear(SubchDev *sch) return cdc->handle_clear(sch); } +IOInstEnding s390_ccw_store(SubchDev *sch) +{ + S390CCWDeviceClass *cdc = NULL; + int ret = IOINST_CC_EXPECTED; + + /* + * This code is called for both virtual and passthrough devices, + * but only applies to to the latter. This ugly check makes that + * distinction for us. + */ + if (object_dynamic_cast(OBJECT(sch->driver_data), TYPE_S390_CCW)) { + cdc = S390_CCW_DEVICE_GET_CLASS(sch->driver_data); + } + + if (cdc && cdc->handle_store) { + ret = cdc->handle_store(sch); + } + + return ret; +} + static void s390_ccw_get_dev_info(S390CCWDevice *cdev, char *sysfsdev, Error **errp) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index c4a4259f0cf1acf567eebb2656a7c34f4b51837a..05f7460aec9b87c24d4f76295e4d6d7ff0989839 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -15,8 +15,9 @@ #include "qapi/error.h" #include "qapi/visitor.h" #include "cpu.h" -#include "s390-pci-bus.h" -#include "s390-pci-inst.h" +#include "hw/s390x/s390-pci-bus.h" +#include "hw/s390x/s390-pci-inst.h" +#include "hw/s390x/s390-pci-vfio.h" #include "hw/pci/pci_bus.h" #include "hw/qdev-properties.h" #include "hw/pci/pci_bridge.h" @@ -637,22 +638,24 @@ static AddressSpace *s390_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn) static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set) { - uint8_t ind_old, ind_new; + uint8_t expected, actual; hwaddr len = 1; - uint8_t *ind_addr; + /* avoid multiple fetches */ + uint8_t volatile *ind_addr; ind_addr = cpu_physical_memory_map(ind_loc, &len, true); if (!ind_addr) { s390_pci_generate_error_event(ERR_EVENT_AIRERR, 0, 0, 0, 0); return -1; } + actual = *ind_addr; do { - ind_old = *ind_addr; - ind_new = ind_old | to_be_set; - } while (atomic_cmpxchg(ind_addr, ind_old, ind_new) != ind_old); - cpu_physical_memory_unmap(ind_addr, len, 1, len); + expected = actual; + actual = qatomic_cmpxchg(ind_addr, expected, expected | to_be_set); + } while (actual != expected); + cpu_physical_memory_unmap((void *)ind_addr, len, 1, len); - return ind_old; + return actual; } static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data, @@ -729,19 +732,76 @@ static void s390_pci_iommu_free(S390pciState *s, PCIBus *bus, int32_t devfn) table->iommu[PCI_SLOT(devfn)] = NULL; g_hash_table_destroy(iommu->iotlb); + /* + * An attached PCI device may have memory listeners, eg. VFIO PCI. + * The associated subregion will already have been unmapped in + * s390_pci_iommu_disable in response to the guest deconfigure request. + * Remove the listeners now before destroying the address space. + */ + address_space_remove_listeners(&iommu->as); address_space_destroy(&iommu->as); object_unparent(OBJECT(&iommu->mr)); object_unparent(OBJECT(iommu)); object_unref(OBJECT(iommu)); } +S390PCIGroup *s390_group_create(int id) +{ + S390PCIGroup *group; + S390pciState *s = s390_get_phb(); + + group = g_new0(S390PCIGroup, 1); + group->id = id; + QTAILQ_INSERT_TAIL(&s->zpci_groups, group, link); + return group; +} + +S390PCIGroup *s390_group_find(int id) +{ + S390PCIGroup *group; + S390pciState *s = s390_get_phb(); + + QTAILQ_FOREACH(group, &s->zpci_groups, link) { + if (group->id == id) { + return group; + } + } + return NULL; +} + +static void s390_pci_init_default_group(void) +{ + S390PCIGroup *group; + ClpRspQueryPciGrp *resgrp; + + group = s390_group_create(ZPCI_DEFAULT_FN_GRP); + resgrp = &group->zpci_group; + resgrp->fr = 1; + resgrp->dasm = 0; + resgrp->msia = ZPCI_MSI_ADDR; + resgrp->mui = DEFAULT_MUI; + resgrp->i = 128; + resgrp->maxstbl = 128; + resgrp->version = 0; +} + +static void set_pbdev_info(S390PCIBusDevice *pbdev) +{ + pbdev->zpci_fn.sdma = ZPCI_SDMA_ADDR; + pbdev->zpci_fn.edma = ZPCI_EDMA_ADDR; + pbdev->zpci_fn.pchid = 0; + pbdev->zpci_fn.pfgid = ZPCI_DEFAULT_FN_GRP; + pbdev->zpci_fn.fid = pbdev->fid; + pbdev->zpci_fn.uid = pbdev->uid; + pbdev->pci_group = s390_group_find(ZPCI_DEFAULT_FN_GRP); +} + static void s390_pcihost_realize(DeviceState *dev, Error **errp) { PCIBus *b; BusState *bus; PCIHostState *phb = PCI_HOST_BRIDGE(dev); S390pciState *s = S390_PCI_HOST_BRIDGE(dev); - Error *local_err = NULL; DPRINTF("host_init\n"); @@ -751,19 +811,11 @@ static void s390_pcihost_realize(DeviceState *dev, Error **errp) pci_setup_iommu(b, s390_pci_dma_iommu, s); bus = BUS(b); - qbus_set_hotplug_handler(bus, OBJECT(dev), &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } + qbus_set_hotplug_handler(bus, OBJECT(dev)); phb->bus = b; s->bus = S390_PCI_BUS(qbus_create(TYPE_S390_PCI_BUS, dev, NULL)); - qbus_set_hotplug_handler(BUS(s->bus), OBJECT(dev), &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } + qbus_set_hotplug_handler(BUS(s->bus), OBJECT(dev)); s->iommu_table = g_hash_table_new_full(g_int64_hash, g_int64_equal, NULL, g_free); @@ -771,10 +823,23 @@ static void s390_pcihost_realize(DeviceState *dev, Error **errp) s->bus_no = 0; QTAILQ_INIT(&s->pending_sei); QTAILQ_INIT(&s->zpci_devs); + QTAILQ_INIT(&s->zpci_dma_limit); + QTAILQ_INIT(&s->zpci_groups); + s390_pci_init_default_group(); css_register_io_adapters(CSS_IO_ADAPTER_PCI, true, false, - S390_ADAPTER_SUPPRESSIBLE, &local_err); - error_propagate(errp, local_err); + S390_ADAPTER_SUPPRESSIBLE, errp); +} + +static void s390_pcihost_unrealize(DeviceState *dev) +{ + S390PCIGroup *group; + S390pciState *s = S390_PCI_HOST_BRIDGE(dev); + + while (!QTAILQ_EMPTY(&s->zpci_groups)) { + group = QTAILQ_FIRST(&s->zpci_groups); + QTAILQ_REMOVE(&s->zpci_groups, group, link); + } } static int s390_pci_msix_init(S390PCIBusDevice *pbdev) @@ -805,7 +870,8 @@ static int s390_pci_msix_init(S390PCIBusDevice *pbdev) name = g_strdup_printf("msix-s390-%04x", pbdev->uid); memory_region_init_io(&pbdev->msix_notify_mr, OBJECT(pbdev), &s390_msi_ctrl_ops, pbdev, name, PAGE_SIZE); - memory_region_add_subregion(&pbdev->iommu->mr, ZPCI_MSI_ADDR, + memory_region_add_subregion(&pbdev->iommu->mr, + pbdev->pci_group->zpci_group.msia, &pbdev->msix_notify_mr); g_free(name); @@ -824,21 +890,19 @@ static S390PCIBusDevice *s390_pci_device_new(S390pciState *s, Error *local_err = NULL; DeviceState *dev; - dev = qdev_try_create(BUS(s->bus), TYPE_S390_PCI_DEVICE); + dev = qdev_try_new(TYPE_S390_PCI_DEVICE); if (!dev) { error_setg(errp, "zPCI device could not be created"); return NULL; } - object_property_set_str(OBJECT(dev), target, "target", &local_err); - if (local_err) { + if (!object_property_set_str(OBJECT(dev), "target", target, &local_err)) { object_unparent(OBJECT(dev)); error_propagate_prepend(errp, local_err, "zPCI device could not be created: "); return NULL; } - object_property_set_bool(OBJECT(dev), true, "realized", &local_err); - if (local_err) { + if (!qdev_realize_and_unref(dev, BUS(s->bus), &local_err)) { object_unparent(OBJECT(dev)); error_propagate_prepend(errp, local_err, "zPCI device could not be created: "); @@ -921,7 +985,7 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, pci_bridge_map_irq(pb, dev->id, s390_pci_map_irq); pci_setup_iommu(&pb->sec_bus, s390_pci_dma_iommu, s); - qbus_set_hotplug_handler(BUS(&pb->sec_bus), OBJECT(s), errp); + qbus_set_hotplug_handler(BUS(&pb->sec_bus), OBJECT(s)); if (dev->hotplugged) { pci_default_write_config(pdev, PCI_PRIMARY_BUS, @@ -951,17 +1015,21 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, } } + pbdev->pdev = pdev; + pbdev->iommu = s390_pci_get_iommu(s, pci_get_bus(pdev), pdev->devfn); + pbdev->iommu->pbdev = pbdev; + pbdev->state = ZPCI_FS_DISABLED; + set_pbdev_info(pbdev); + if (object_dynamic_cast(OBJECT(dev), "vfio-pci")) { pbdev->fh |= FH_SHM_VFIO; + pbdev->iommu->dma_limit = s390_pci_start_dma_count(s, pbdev); + /* Fill in CLP information passed via the vfio region */ + s390_pci_get_clp_info(pbdev); } else { pbdev->fh |= FH_SHM_EMUL; } - pbdev->pdev = pdev; - pbdev->iommu = s390_pci_get_iommu(s, pci_get_bus(pdev), pdev->devfn); - pbdev->iommu->pbdev = pbdev; - pbdev->state = ZPCI_FS_DISABLED; - if (s390_pci_msix_init(pbdev)) { error_setg(errp, "MSI-X support is mandatory " "in the S390 architecture"); @@ -1003,7 +1071,7 @@ static void s390_pcihost_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, pbdev->fh, pbdev->fid); bus = pci_get_bus(pci_dev); devfn = pci_dev->devfn; - object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + qdev_unrealize(dev); s390_pci_msix_free(pbdev); s390_pci_iommu_free(s, bus, devfn); @@ -1014,7 +1082,10 @@ static void s390_pcihost_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, pbdev->fid = 0; QTAILQ_REMOVE(&s->zpci_devs, pbdev, link); g_hash_table_remove(s->zpci_table, &pbdev->idx); - object_property_set_bool(OBJECT(dev), false, "realized", &error_abort); + if (pbdev->iommu->dma_limit) { + s390_pci_end_dma_count(s, pbdev->iommu->dma_limit); + } + qdev_unrealize(dev); } } @@ -1133,6 +1204,7 @@ static void s390_pcihost_class_init(ObjectClass *klass, void *data) dc->reset = s390_pcihost_reset; dc->realize = s390_pcihost_realize; + dc->unrealize = s390_pcihost_unrealize; hc->pre_plug = s390_pcihost_pre_plug; hc->plug = s390_pcihost_plug; hc->unplug_request = s390_pcihost_unplug_request; @@ -1276,7 +1348,9 @@ static void s390_pci_set_fid(Object *obj, Visitor *v, const char *name, return; } - visit_type_uint32(v, name, ptr, errp); + if (!visit_type_uint32(v, name, ptr, errp)) { + return; + } zpci->fid_defined = true; } diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 2f7a7d7bd1b2c3b6bacb63548b51f856c3e3ae9d..70bfd91bf70edafaa7c93469f459d0511132573b 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -13,12 +13,12 @@ #include "qemu/osdep.h" #include "cpu.h" -#include "s390-pci-inst.h" -#include "s390-pci-bus.h" #include "exec/memop.h" #include "exec/memory-internal.h" #include "qemu/error-report.h" #include "sysemu/hw_accel.h" +#include "hw/s390x/s390-pci-inst.h" +#include "hw/s390x/s390-pci-bus.h" #include "hw/s390x/tod.h" #ifndef DEBUG_S390PCI_INST @@ -32,6 +32,20 @@ } \ } while (0) +static inline void inc_dma_avail(S390PCIIOMMU *iommu) +{ + if (iommu->dma_limit) { + iommu->dma_limit->avail++; + } +} + +static inline void dec_dma_avail(S390PCIIOMMU *iommu) +{ + if (iommu->dma_limit) { + iommu->dma_limit->avail--; + } +} + static void s390_set_status_code(CPUS390XState *env, uint8_t r, uint64_t status_code) { @@ -267,6 +281,14 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra) goto out; } + stq_p(&resquery->sdma, pbdev->zpci_fn.sdma); + stq_p(&resquery->edma, pbdev->zpci_fn.edma); + stw_p(&resquery->pchid, pbdev->zpci_fn.pchid); + resquery->flags = pbdev->zpci_fn.flags; + resquery->pfgid = pbdev->zpci_fn.pfgid; + stl_p(&resquery->fid, pbdev->zpci_fn.fid); + stl_p(&resquery->uid, pbdev->zpci_fn.uid); + for (i = 0; i < PCI_BAR_COUNT; i++) { uint32_t data = pci_get_long(pbdev->pdev->config + PCI_BASE_ADDRESS_0 + (i * 4)); @@ -280,25 +302,29 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra) resquery->bar_size[i]); } - stq_p(&resquery->sdma, ZPCI_SDMA_ADDR); - stq_p(&resquery->edma, ZPCI_EDMA_ADDR); - stl_p(&resquery->fid, pbdev->fid); - stw_p(&resquery->pchid, 0); - stw_p(&resquery->ug, 1); - stl_p(&resquery->uid, pbdev->uid); stw_p(&resquery->hdr.rsp, CLP_RC_OK); break; } case CLP_QUERY_PCI_FNGRP: { ClpRspQueryPciGrp *resgrp = (ClpRspQueryPciGrp *)resh; - resgrp->fr = 1; - stq_p(&resgrp->dasm, 0); - stq_p(&resgrp->msia, ZPCI_MSI_ADDR); - stw_p(&resgrp->mui, DEFAULT_MUI); - stw_p(&resgrp->i, 128); - stw_p(&resgrp->maxstbl, 128); - resgrp->version = 0; + ClpReqQueryPciGrp *reqgrp = (ClpReqQueryPciGrp *)reqh; + S390PCIGroup *group; + + group = s390_group_find(reqgrp->g); + if (!group) { + /* We do not allow access to unknown groups */ + /* The group must have been obtained with a vfio device */ + stw_p(&resgrp->hdr.rsp, CLP_RC_QUERYPCIFG_PFGID); + goto out; + } + resgrp->fr = group->zpci_group.fr; + stq_p(&resgrp->dasm, group->zpci_group.dasm); + stq_p(&resgrp->msia, group->zpci_group.msia); + stw_p(&resgrp->mui, group->zpci_group.mui); + stw_p(&resgrp->i, group->zpci_group.i); + stw_p(&resgrp->maxstbl, group->zpci_group.maxstbl); + resgrp->version = group->zpci_group.version; stw_p(&resgrp->hdr.rsp, CLP_RC_OK); break; } @@ -572,7 +598,8 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) return 0; } -static void s390_pci_update_iotlb(S390PCIIOMMU *iommu, S390IOTLBEntry *entry) +static uint32_t s390_pci_update_iotlb(S390PCIIOMMU *iommu, + S390IOTLBEntry *entry) { S390IOTLBEntry *cache = g_hash_table_lookup(iommu->iotlb, &entry->iova); IOMMUTLBEntry notify = { @@ -585,14 +612,15 @@ static void s390_pci_update_iotlb(S390PCIIOMMU *iommu, S390IOTLBEntry *entry) if (entry->perm == IOMMU_NONE) { if (!cache) { - return; + goto out; } g_hash_table_remove(iommu->iotlb, &entry->iova); + inc_dma_avail(iommu); } else { if (cache) { if (cache->perm == entry->perm && cache->translated_addr == entry->translated_addr) { - return; + goto out; } notify.perm = IOMMU_NONE; @@ -606,9 +634,13 @@ static void s390_pci_update_iotlb(S390PCIIOMMU *iommu, S390IOTLBEntry *entry) cache->len = PAGE_SIZE; cache->perm = entry->perm; g_hash_table_replace(iommu->iotlb, &cache->iova, cache); + dec_dma_avail(iommu); } memory_region_notify_iommu(&iommu->iommu_mr, 0, notify); + +out: + return iommu->dma_limit ? iommu->dma_limit->avail : 1; } int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) @@ -620,6 +652,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) S390PCIIOMMU *iommu; S390IOTLBEntry entry; hwaddr start, end; + uint32_t dma_avail; if (env->psw.mask & PSW_MASK_PSTATE) { s390_program_interrupt(env, PGM_PRIVILEGED, ra); @@ -658,6 +691,11 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) } iommu = pbdev->iommu; + if (iommu->dma_limit) { + dma_avail = iommu->dma_limit->avail; + } else { + dma_avail = 1; + } if (!iommu->g_iota) { error = ERR_EVENT_INVALAS; goto err; @@ -675,8 +713,9 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) } start += entry.len; - while (entry.iova < start && entry.iova < end) { - s390_pci_update_iotlb(iommu, &entry); + while (entry.iova < start && entry.iova < end && + (dma_avail > 0 || entry.perm == IOMMU_NONE)) { + dma_avail = s390_pci_update_iotlb(iommu, &entry); entry.iova += PAGE_SIZE; entry.translated_addr += PAGE_SIZE; } @@ -689,7 +728,13 @@ err: s390_pci_generate_error_event(error, pbdev->fh, pbdev->fid, start, 0); } else { pbdev->fmb.counter[ZPCI_FMB_CNT_RPCIT]++; - setcc(cpu, ZPCI_PCI_LS_OK); + if (dma_avail > 0) { + setcc(cpu, ZPCI_PCI_LS_OK); + } else { + /* vfio DMA mappings are exhausted, trigger a RPCIT */ + setcc(cpu, ZPCI_PCI_LS_ERR); + s390_set_status_code(env, r1, ZPCI_RPCIT_ST_INSUFF_RES); + } } return 0; } @@ -754,7 +799,8 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, } /* Length must be greater than 8, a multiple of 8 */ /* and not greater than maxstbl */ - if ((len <= 8) || (len % 8) || (len > pbdev->maxstbl)) { + if ((len <= 8) || (len % 8) || + (len > pbdev->pci_group->zpci_group.maxstbl)) { goto specification_error; } /* Do not cross a 4K-byte boundary */ diff --git a/hw/s390x/s390-pci-vfio.c b/hw/s390x/s390-pci-vfio.c new file mode 100644 index 0000000000000000000000000000000000000000..9296e1bb6efae945f436f75ddc76659564e758c4 --- /dev/null +++ b/hw/s390x/s390-pci-vfio.c @@ -0,0 +1,276 @@ +/* + * s390 vfio-pci interfaces + * + * Copyright 2020 IBM Corp. + * Author(s): Matthew Rosato + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include +#include +#include + +#include "qemu/osdep.h" +#include "trace.h" +#include "hw/s390x/s390-pci-bus.h" +#include "hw/s390x/s390-pci-clp.h" +#include "hw/s390x/s390-pci-vfio.h" +#include "hw/vfio/pci.h" +#include "hw/vfio/vfio-common.h" + +/* + * Get the current DMA available count from vfio. Returns true if vfio is + * limiting DMA requests, false otherwise. The current available count read + * from vfio is returned in avail. + */ +bool s390_pci_update_dma_avail(int fd, unsigned int *avail) +{ + g_autofree struct vfio_iommu_type1_info *info; + uint32_t argsz; + + assert(avail); + + argsz = sizeof(struct vfio_iommu_type1_info); + info = g_malloc0(argsz); + + /* + * If the specified argsz is not large enough to contain all capabilities + * it will be updated upon return from the ioctl. Retry until we have + * a big enough buffer to hold the entire capability chain. + */ +retry: + info->argsz = argsz; + + if (ioctl(fd, VFIO_IOMMU_GET_INFO, info)) { + return false; + } + + if (info->argsz > argsz) { + argsz = info->argsz; + info = g_realloc(info, argsz); + goto retry; + } + + /* If the capability exists, update with the current value */ + return vfio_get_info_dma_avail(info, avail); +} + +S390PCIDMACount *s390_pci_start_dma_count(S390pciState *s, + S390PCIBusDevice *pbdev) +{ + S390PCIDMACount *cnt; + uint32_t avail; + VFIOPCIDevice *vpdev = container_of(pbdev->pdev, VFIOPCIDevice, pdev); + int id; + + assert(vpdev); + + id = vpdev->vbasedev.group->container->fd; + + if (!s390_pci_update_dma_avail(id, &avail)) { + return NULL; + } + + QTAILQ_FOREACH(cnt, &s->zpci_dma_limit, link) { + if (cnt->id == id) { + cnt->users++; + return cnt; + } + } + + cnt = g_new0(S390PCIDMACount, 1); + cnt->id = id; + cnt->users = 1; + cnt->avail = avail; + QTAILQ_INSERT_TAIL(&s->zpci_dma_limit, cnt, link); + return cnt; +} + +void s390_pci_end_dma_count(S390pciState *s, S390PCIDMACount *cnt) +{ + assert(cnt); + + cnt->users--; + if (cnt->users == 0) { + QTAILQ_REMOVE(&s->zpci_dma_limit, cnt, link); + } +} + +static void s390_pci_read_base(S390PCIBusDevice *pbdev, + struct vfio_device_info *info) +{ + struct vfio_info_cap_header *hdr; + struct vfio_device_info_cap_zpci_base *cap; + VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev); + + hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_BASE); + + /* If capability not provided, just leave the defaults in place */ + if (hdr == NULL) { + trace_s390_pci_clp_cap(vpci->vbasedev.name, + VFIO_DEVICE_INFO_CAP_ZPCI_BASE); + return; + } + cap = (void *) hdr; + + pbdev->zpci_fn.sdma = cap->start_dma; + pbdev->zpci_fn.edma = cap->end_dma; + pbdev->zpci_fn.pchid = cap->pchid; + pbdev->zpci_fn.vfn = cap->vfn; + pbdev->zpci_fn.pfgid = cap->gid; + /* The following values remain 0 until we support other FMB formats */ + pbdev->zpci_fn.fmbl = 0; + pbdev->zpci_fn.pft = 0; +} + +static void s390_pci_read_group(S390PCIBusDevice *pbdev, + struct vfio_device_info *info) +{ + struct vfio_info_cap_header *hdr; + struct vfio_device_info_cap_zpci_group *cap; + ClpRspQueryPciGrp *resgrp; + VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev); + + hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_GROUP); + + /* If capability not provided, just use the default group */ + if (hdr == NULL) { + trace_s390_pci_clp_cap(vpci->vbasedev.name, + VFIO_DEVICE_INFO_CAP_ZPCI_GROUP); + pbdev->zpci_fn.pfgid = ZPCI_DEFAULT_FN_GRP; + pbdev->pci_group = s390_group_find(ZPCI_DEFAULT_FN_GRP); + return; + } + cap = (void *) hdr; + + /* See if the PCI group is already defined, create if not */ + pbdev->pci_group = s390_group_find(pbdev->zpci_fn.pfgid); + + if (!pbdev->pci_group) { + pbdev->pci_group = s390_group_create(pbdev->zpci_fn.pfgid); + + resgrp = &pbdev->pci_group->zpci_group; + if (cap->flags & VFIO_DEVICE_INFO_ZPCI_FLAG_REFRESH) { + resgrp->fr = 1; + } + resgrp->dasm = cap->dasm; + resgrp->msia = cap->msi_addr; + resgrp->mui = cap->mui; + resgrp->i = cap->noi; + resgrp->maxstbl = cap->maxstbl; + resgrp->version = cap->version; + } +} + +static void s390_pci_read_util(S390PCIBusDevice *pbdev, + struct vfio_device_info *info) +{ + struct vfio_info_cap_header *hdr; + struct vfio_device_info_cap_zpci_util *cap; + VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev); + + hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_UTIL); + + /* If capability not provided, just leave the defaults in place */ + if (hdr == NULL) { + trace_s390_pci_clp_cap(vpci->vbasedev.name, + VFIO_DEVICE_INFO_CAP_ZPCI_UTIL); + return; + } + cap = (void *) hdr; + + if (cap->size > CLP_UTIL_STR_LEN) { + trace_s390_pci_clp_cap_size(vpci->vbasedev.name, cap->size, + VFIO_DEVICE_INFO_CAP_ZPCI_UTIL); + return; + } + + pbdev->zpci_fn.flags |= CLP_RSP_QPCI_MASK_UTIL; + memcpy(pbdev->zpci_fn.util_str, cap->util_str, CLP_UTIL_STR_LEN); +} + +static void s390_pci_read_pfip(S390PCIBusDevice *pbdev, + struct vfio_device_info *info) +{ + struct vfio_info_cap_header *hdr; + struct vfio_device_info_cap_zpci_pfip *cap; + VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev); + + hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_PFIP); + + /* If capability not provided, just leave the defaults in place */ + if (hdr == NULL) { + trace_s390_pci_clp_cap(vpci->vbasedev.name, + VFIO_DEVICE_INFO_CAP_ZPCI_PFIP); + return; + } + cap = (void *) hdr; + + if (cap->size > CLP_PFIP_NR_SEGMENTS) { + trace_s390_pci_clp_cap_size(vpci->vbasedev.name, cap->size, + VFIO_DEVICE_INFO_CAP_ZPCI_PFIP); + return; + } + + memcpy(pbdev->zpci_fn.pfip, cap->pfip, CLP_PFIP_NR_SEGMENTS); +} + +/* + * This function will issue the VFIO_DEVICE_GET_INFO ioctl and look for + * capabilities that contain information about CLP features provided by the + * underlying host. + * On entry, defaults have already been placed into the guest CLP response + * buffers. On exit, defaults will have been overwritten for any CLP features + * found in the capability chain; defaults will remain for any CLP features not + * found in the chain. + */ +void s390_pci_get_clp_info(S390PCIBusDevice *pbdev) +{ + g_autofree struct vfio_device_info *info; + VFIOPCIDevice *vfio_pci; + uint32_t argsz; + int fd; + + argsz = sizeof(*info); + info = g_malloc0(argsz); + + vfio_pci = container_of(pbdev->pdev, VFIOPCIDevice, pdev); + fd = vfio_pci->vbasedev.fd; + + /* + * If the specified argsz is not large enough to contain all capabilities + * it will be updated upon return from the ioctl. Retry until we have + * a big enough buffer to hold the entire capability chain. On error, + * just exit and rely on CLP defaults. + */ +retry: + info->argsz = argsz; + + if (ioctl(fd, VFIO_DEVICE_GET_INFO, info)) { + trace_s390_pci_clp_dev_info(vfio_pci->vbasedev.name); + return; + } + + if (info->argsz > argsz) { + argsz = info->argsz; + info = g_realloc(info, argsz); + goto retry; + } + + /* + * Find the CLP features provided and fill in the guest CLP responses. + * Always call s390_pci_read_base first as information from this could + * determine which function group is used in s390_pci_read_group. + * For any feature not found, the default values will remain in the CLP + * response. + */ + s390_pci_read_base(pbdev, info); + s390_pci_read_group(pbdev, info); + s390_pci_read_util(pbdev, info); + s390_pci_read_pfip(pbdev, info); + + return; +} diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c index d304b8564064542144271ef1f781392c9cd7c261..5cc559fe4c77f521bdc21b05985da6de29a6ba34 100644 --- a/hw/s390x/s390-skeys.c +++ b/hw/s390x/s390-skeys.c @@ -48,7 +48,7 @@ void s390_skeys_init(void) obj); object_unref(obj); - qdev_init_nofail(DEVICE(obj)); + qdev_realize(DEVICE(obj), NULL, &error_fatal); } static void write_keys(FILE *f, uint8_t *keys, uint64_t startgfn, @@ -125,7 +125,7 @@ void qmp_dump_skeys(const char *filename, Error **errp) return; } - fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600); + fd = qemu_open_old(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { error_setg_file_open(errp, errno, filename); return; @@ -401,7 +401,7 @@ static void s390_skeys_instance_init(Object *obj) object_property_add_bool(obj, "migration-enabled", s390_skeys_get_migration_enabled, s390_skeys_set_migration_enabled); - object_property_set_bool(obj, true, "migration-enabled", NULL); + object_property_set_bool(obj, "migration-enabled", true, NULL); } static void s390_skeys_class_init(ObjectClass *oc, void *data) diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c index 6d1e587527e763f61b0271c9a6ed314d3939ff5a..4441e1d331c3324454311b2d8a59e5712ac29cf2 100644 --- a/hw/s390x/s390-stattrib.c +++ b/hw/s390x/s390-stattrib.c @@ -50,7 +50,7 @@ void s390_stattrib_init(void) obj); object_unref(obj); - qdev_init_nofail(DEVICE(obj)); + qdev_realize(DEVICE(obj), NULL, &error_fatal); } /* Console commands: */ @@ -388,7 +388,7 @@ static void s390_stattrib_instance_init(Object *obj) object_property_add_bool(obj, "migration-enabled", s390_stattrib_get_migration_enabled, s390_stattrib_set_migration_enabled); - object_property_set_bool(obj, true, "migration-enabled", NULL); + object_property_set_bool(obj, "migration-enabled", true, NULL); sas->migration_cur_gfn = 0; } diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 67ae2e02ffd88e2bc93ba07ae02098a3acf69979..4e140bbead936bfd3fe383c81276eb114abef555 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -28,7 +28,7 @@ #include "qemu/error-report.h" #include "qemu/option.h" #include "qemu/qemu-print.h" -#include "s390-pci-bus.h" +#include "hw/s390x/s390-pci-bus.h" #include "sysemu/reset.h" #include "hw/s390x/storage-keys.h" #include "hw/s390x/storage-attributes.h" @@ -43,7 +43,6 @@ #include "hw/qdev-properties.h" #include "hw/s390x/tod.h" #include "sysemu/sysemu.h" -#include "sysemu/balloon.h" #include "hw/s390x/pv.h" #include "migration/blocker.h" @@ -69,21 +68,19 @@ static S390CPU *s390x_new_cpu(const char *typename, uint32_t core_id, Error **errp) { S390CPU *cpu = S390_CPU(object_new(typename)); - Error *err = NULL; + S390CPU *ret = NULL; - object_property_set_int(OBJECT(cpu), core_id, "core-id", &err); - if (err != NULL) { + if (!object_property_set_int(OBJECT(cpu), "core-id", core_id, errp)) { goto out; } - object_property_set_bool(OBJECT(cpu), true, "realized", &err); + if (!qdev_realize(DEVICE(cpu), NULL, errp)) { + goto out; + } + ret = cpu; out: object_unref(OBJECT(cpu)); - if (err) { - error_propagate(errp, err); - cpu = NULL; - } - return cpu; + return ret; } static void s390_init_cpus(MachineState *machine) @@ -104,6 +101,7 @@ static const char *const reset_dev_types[] = { "s390-sclp-event-facility", "s390-flic", "diag288", + TYPE_S390_PCI_HOST_BRIDGE, }; static void subsystem_reset(void) @@ -164,7 +162,6 @@ static void virtio_ccw_register_hcalls(void) static void s390_memory_init(MemoryRegion *ram) { MemoryRegion *sysmem = get_system_memory(); - Error *local_err = NULL; /* allocate RAM for core */ memory_region_add_subregion(sysmem, 0, ram); @@ -173,11 +170,7 @@ static void s390_memory_init(MemoryRegion *ram) * Configure the maximum page size. As no memory devices were created * yet, this is the page size of initial memory only. */ - s390_set_max_pagesize(qemu_maxrampagesize(), &local_err); - if (local_err) { - error_report_err(local_err); - exit(EXIT_FAILURE); - } + s390_set_max_pagesize(qemu_maxrampagesize(), &error_fatal); /* Initialize storage key device */ s390_skeys_init(); /* Initialize storage attributes device */ @@ -210,7 +203,7 @@ static void s390_init_ipl_dev(const char *kernel_filename, object_property_add_child(qdev_get_machine(), TYPE_S390_IPL, new); object_unref(new); - qdev_init_nofail(dev); + qdev_realize(dev, NULL, &error_fatal); } static void s390_create_virtio_net(BusState *bus, const char *name) @@ -227,9 +220,9 @@ static void s390_create_virtio_net(BusState *bus, const char *name) qemu_check_nic_model(nd, "virtio"); - dev = qdev_create(bus, name); + dev = qdev_new(name); qdev_set_nic_properties(dev, nd); - qdev_init_nofail(dev); + qdev_realize_and_unref(dev, bus, &error_fatal); } } @@ -237,9 +230,9 @@ static void s390_create_sclpconsole(const char *type, Chardev *chardev) { DeviceState *dev; - dev = qdev_create(sclp_get_event_facility_bus(), type); + dev = qdev_new(type); qdev_prop_set_chr(dev, "chardev", chardev); - qdev_init_nofail(dev); + qdev_realize_and_unref(dev, sclp_get_event_facility_bus(), &error_fatal); } static void ccw_init(MachineState *machine) @@ -269,10 +262,10 @@ static void ccw_init(MachineState *machine) machine->initrd_filename, "s390-ccw.img", "s390-netboot.img", true); - dev = qdev_create(NULL, TYPE_S390_PCI_HOST_BRIDGE); + dev = qdev_new(TYPE_S390_PCI_HOST_BRIDGE); object_property_add_child(qdev_get_machine(), TYPE_S390_PCI_HOST_BRIDGE, OBJECT(dev)); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); /* register hypercalls */ virtio_ccw_register_hcalls(); @@ -329,7 +322,7 @@ static void s390_machine_unprotect(S390CcwMachineState *ms) ms->pv = false; migrate_del_blocker(pv_mig_blocker); error_free_or_abort(&pv_mig_blocker); - qemu_balloon_inhibit(false); + ram_block_discard_disable(false); } static int s390_machine_protect(S390CcwMachineState *ms) @@ -338,17 +331,22 @@ static int s390_machine_protect(S390CcwMachineState *ms) int rc; /* - * Ballooning on protected VMs needs support in the guest for - * sharing and unsharing balloon pages. Block ballooning for - * now, until we have a solution to make at least Linux guests - * either support it or fail gracefully. + * Discarding of memory in RAM blocks does not work as expected with + * protected VMs. Sharing and unsharing pages would be required. Disable + * it for now, until until we have a solution to make at least Linux + * guests either support it (e.g., virtio-balloon) or fail gracefully. */ - qemu_balloon_inhibit(true); + rc = ram_block_discard_disable(true); + if (rc) { + error_report("protected VMs: cannot disable RAM discard"); + return rc; + } + error_setg(&pv_mig_blocker, "protected VMs are currently not migrateable."); rc = migrate_add_blocker(pv_mig_blocker, &local_err); if (rc) { - qemu_balloon_inhibit(false); + ram_block_discard_disable(false); error_report_err(local_err); error_free_or_abort(&pv_mig_blocker); return rc; @@ -357,7 +355,7 @@ static int s390_machine_protect(S390CcwMachineState *ms) /* Create SE VM */ rc = s390_pv_vm_enable(); if (rc) { - qemu_balloon_inhibit(false); + ram_block_discard_disable(false); migrate_del_blocker(pv_mig_blocker); error_free_or_abort(&pv_mig_blocker); return rc; @@ -401,7 +399,7 @@ static void s390_pv_prepare_reset(S390CcwMachineState *ms) s390_cpu_set_state(S390_CPU_STATE_STOPPED, S390_CPU(cs)); } s390_pv_unshare(); - s390_pv_perf_clear_reset(); + s390_pv_prep_reset(); } static void s390_machine_reset(MachineState *machine) @@ -488,6 +486,10 @@ static void s390_machine_reset(MachineState *machine) default: g_assert_not_reached(); } + + CPU_FOREACH(t) { + run_on_cpu(t, s390_do_cpu_set_diag318, RUN_ON_CPU_HOST_ULONG(0)); + } s390_ipl_clear_reset_request(); } @@ -551,17 +553,6 @@ static HotplugHandler *s390_get_hotplug_handler(MachineState *machine, return NULL; } -static void s390_hot_add_cpu(MachineState *machine, - const int64_t id, Error **errp) -{ - ObjectClass *oc; - - g_assert(machine->possible_cpus->cpus[0].cpu); - oc = OBJECT_CLASS(CPU_GET_CLASS(machine->possible_cpus->cpus[0].cpu)); - - s390x_new_cpu(object_class_get_name(oc), id, errp); -} - static void s390_nmi(NMIState *n, int cpu_index, Error **errp) { CPUState *cs = qemu_get_cpu(cpu_index); @@ -594,7 +585,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) MachineClass *mc = MACHINE_CLASS(oc); NMIClass *nc = NMI_CLASS(oc); HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); - S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc); + S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc); s390mc->ri_allowed = true; s390mc->cpu_model_allowed = true; @@ -602,7 +593,6 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) s390mc->hpage_1m_allowed = true; mc->init = ccw_init; mc->reset = s390_machine_reset; - mc->hot_add_cpu = s390_hot_add_cpu; mc->block_default_type = IF_VIRTIO; mc->no_cdrom = 1; mc->no_floppy = 1; @@ -675,7 +665,7 @@ static S390CcwMachineClass *get_machine_class(void) * be called for the 'none' machine. The properties will * have their after-initialization values. */ - current_mc = S390_MACHINE_CLASS( + current_mc = S390_CCW_MACHINE_CLASS( object_class_by_name(TYPE_S390_CCW_MACHINE)); } return current_mc; @@ -700,7 +690,8 @@ static char *machine_get_loadparm(Object *obj, Error **errp) { S390CcwMachineState *ms = S390_CCW_MACHINE(obj); - return g_memdup(ms->loadparm, sizeof(ms->loadparm)); + /* make a NUL-terminated string */ + return g_strndup((char *) ms->loadparm, sizeof(ms->loadparm)); } static void machine_set_loadparm(Object *obj, const char *val, Error **errp) @@ -732,14 +723,14 @@ static inline void s390_machine_initfn(Object *obj) machine_set_aes_key_wrap); object_property_set_description(obj, "aes-key-wrap", "enable/disable AES key wrapping using the CPACF wrapping key"); - object_property_set_bool(obj, true, "aes-key-wrap", NULL); + object_property_set_bool(obj, "aes-key-wrap", true, NULL); object_property_add_bool(obj, "dea-key-wrap", machine_get_dea_key_wrap, machine_set_dea_key_wrap); object_property_set_description(obj, "dea-key-wrap", "enable/disable DEA key wrapping using the CPACF wrapping key"); - object_property_set_bool(obj, true, "dea-key-wrap", NULL); + object_property_set_bool(obj, "dea-key-wrap", true, NULL); object_property_add_str(obj, "loadparm", machine_get_loadparm, machine_set_loadparm); object_property_set_description(obj, "loadparm", @@ -783,7 +774,7 @@ bool css_migration_enabled(void) static void ccw_machine_##suffix##_instance_init(Object *obj) \ { \ MachineState *machine = MACHINE(obj); \ - current_mc = S390_MACHINE_CLASS(MACHINE_GET_CLASS(machine)); \ + current_mc = S390_CCW_MACHINE_CLASS(MACHINE_GET_CLASS(machine)); \ ccw_machine_##suffix##_instance_options(machine); \ } \ static const TypeInfo ccw_machine_##suffix##_info = { \ @@ -798,14 +789,26 @@ bool css_migration_enabled(void) } \ type_init(ccw_machine_register_##suffix) +static void ccw_machine_5_2_instance_options(MachineState *machine) +{ +} + +static void ccw_machine_5_2_class_options(MachineClass *mc) +{ +} +DEFINE_CCW_MACHINE(5_2, "5.2", true); + static void ccw_machine_5_1_instance_options(MachineState *machine) { + ccw_machine_5_2_instance_options(machine); } static void ccw_machine_5_1_class_options(MachineClass *mc) { + ccw_machine_5_2_class_options(mc); + compat_props_add(mc->compat_props, hw_compat_5_1, hw_compat_5_1_len); } -DEFINE_CCW_MACHINE(5_1, "5.1", true); +DEFINE_CCW_MACHINE(5_1, "5.1", false); static void ccw_machine_5_0_instance_options(MachineState *machine) { @@ -883,7 +886,7 @@ static void ccw_machine_3_0_instance_options(MachineState *machine) static void ccw_machine_3_0_class_options(MachineClass *mc) { - S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc); + S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc); s390mc->hpage_1m_allowed = false; ccw_machine_3_1_class_options(mc); @@ -950,7 +953,7 @@ static void ccw_machine_2_9_instance_options(MachineState *machine) static void ccw_machine_2_9_class_options(MachineClass *mc) { - S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc); + S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc); static GlobalProperty compat[] = { { TYPE_S390_STATTRIB, "migration-enabled", "off", }, }; @@ -986,7 +989,7 @@ static void ccw_machine_2_7_instance_options(MachineState *machine) static void ccw_machine_2_7_class_options(MachineClass *mc) { - S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc); + S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc); s390mc->cpu_model_allowed = false; ccw_machine_2_8_class_options(mc); @@ -1001,7 +1004,7 @@ static void ccw_machine_2_6_instance_options(MachineState *machine) static void ccw_machine_2_6_class_options(MachineClass *mc) { - S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc); + S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc); static GlobalProperty compat[] = { { TYPE_S390_IPL, "iplbext_migration", "off", }, { TYPE_VIRTUAL_CSS_BRIDGE, "css_dev_path", "off", }, diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c index 20aca30ac433a9f6b9d896ae43a6422ffd3c0837..0cf229082670dede687c8a49fddfb24a2464d63b 100644 --- a/hw/s390x/sclp.c +++ b/hw/s390x/sclp.c @@ -49,9 +49,37 @@ static inline bool sclp_command_code_valid(uint32_t code) return false; } -static void prepare_cpu_entries(SCLPDevice *sclp, CPUEntry *entry, int *count) +static bool sccb_verify_boundary(uint64_t sccb_addr, uint16_t sccb_len, + uint32_t code) +{ + uint64_t sccb_max_addr = sccb_addr + sccb_len - 1; + uint64_t sccb_boundary = (sccb_addr & PAGE_MASK) + PAGE_SIZE; + + switch (code & SCLP_CMD_CODE_MASK) { + case SCLP_CMDW_READ_SCP_INFO: + case SCLP_CMDW_READ_SCP_INFO_FORCED: + case SCLP_CMDW_READ_CPU_INFO: + /* + * An extended-length SCCB is only allowed for Read SCP/CPU Info and + * is allowed to exceed the 4k boundary. The respective commands will + * set the length field to the required length if an insufficient + * SCCB length is provided. + */ + if (s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB)) { + return true; + } + /* fallthrough */ + default: + if (sccb_max_addr < sccb_boundary) { + return true; + } + } + + return false; +} + +static void prepare_cpu_entries(MachineState *ms, CPUEntry *entry, int *count) { - MachineState *ms = MACHINE(qdev_get_machine()); uint8_t features[SCCB_CPU_FEATURE_LEN] = { 0 }; int i; @@ -67,6 +95,14 @@ static void prepare_cpu_entries(SCLPDevice *sclp, CPUEntry *entry, int *count) } } +#define SCCB_REQ_LEN(s, max_cpus) (sizeof(s) + max_cpus * sizeof(CPUEntry)) + +static inline bool ext_len_sccb_supported(SCCBHeader header) +{ + return s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB) && + header.control_mask[2] & SCLP_VARIABLE_LENGTH_RESPONSE; +} + /* Provide information about the configuration, CPUs and storage */ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb) { @@ -75,27 +111,39 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb) int cpu_count; int rnsize, rnmax; IplParameterBlock *ipib = s390_ipl_get_iplb(); + int required_len = SCCB_REQ_LEN(ReadInfo, machine->possible_cpus->len); + int offset_cpu = s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB) ? + offsetof(ReadInfo, entries) : + SCLP_READ_SCP_INFO_FIXED_CPU_OFFSET; + CPUEntry *entries_start = (void *)sccb + offset_cpu; + + if (be16_to_cpu(sccb->h.length) < required_len) { + if (ext_len_sccb_supported(sccb->h)) { + sccb->h.length = cpu_to_be16(required_len); + } + sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH); + return; + } /* CPU information */ - prepare_cpu_entries(sclp, read_info->entries, &cpu_count); + prepare_cpu_entries(machine, entries_start, &cpu_count); read_info->entries_cpu = cpu_to_be16(cpu_count); - read_info->offset_cpu = cpu_to_be16(offsetof(ReadInfo, entries)); + read_info->offset_cpu = cpu_to_be16(offset_cpu); read_info->highest_cpu = cpu_to_be16(machine->smp.max_cpus - 1); read_info->ibc_val = cpu_to_be32(s390_get_ibc_val()); - if (be16_to_cpu(sccb->h.length) < - (sizeof(ReadInfo) + cpu_count * sizeof(CPUEntry))) { - sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH); - return; - } - /* Configuration Characteristic (Extension) */ s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR, read_info->conf_char); s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, read_info->conf_char_ext); + if (s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB)) { + s390_get_feat_block(S390_FEAT_TYPE_SCLP_FAC134, + &read_info->fac134); + } + read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO | SCLP_HAS_IOA_RECONFIG); @@ -132,20 +180,24 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb) /* Provide information about the CPU */ static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB *sccb) { + MachineState *machine = MACHINE(qdev_get_machine()); ReadCpuInfo *cpu_info = (ReadCpuInfo *) sccb; int cpu_count; + int required_len = SCCB_REQ_LEN(ReadCpuInfo, machine->possible_cpus->len); - prepare_cpu_entries(sclp, cpu_info->entries, &cpu_count); - cpu_info->nr_configured = cpu_to_be16(cpu_count); - cpu_info->offset_configured = cpu_to_be16(offsetof(ReadCpuInfo, entries)); - cpu_info->nr_standby = cpu_to_be16(0); - - if (be16_to_cpu(sccb->h.length) < - (sizeof(ReadCpuInfo) + cpu_count * sizeof(CPUEntry))) { + if (be16_to_cpu(sccb->h.length) < required_len) { + if (ext_len_sccb_supported(sccb->h)) { + sccb->h.length = cpu_to_be16(required_len); + } sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH); return; } + prepare_cpu_entries(machine, cpu_info->entries, &cpu_count); + cpu_info->nr_configured = cpu_to_be16(cpu_count); + cpu_info->offset_configured = cpu_to_be16(offsetof(ReadCpuInfo, entries)); + cpu_info->nr_standby = cpu_to_be16(0); + /* The standby offset is 16-byte for each CPU */ cpu_info->offset_standby = cpu_to_be16(cpu_info->offset_configured + cpu_info->nr_configured*sizeof(CPUEntry)); @@ -219,20 +271,24 @@ int sclp_service_call_protected(CPUS390XState *env, uint64_t sccb, { SCLPDevice *sclp = get_sclp_device(); SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp); - SCCB work_sccb; - hwaddr sccb_len = sizeof(SCCB); + SCCBHeader header; + g_autofree SCCB *work_sccb = NULL; + + s390_cpu_pv_mem_read(env_archcpu(env), 0, &header, sizeof(SCCBHeader)); - s390_cpu_pv_mem_read(env_archcpu(env), 0, &work_sccb, sccb_len); + work_sccb = g_malloc0(be16_to_cpu(header.length)); + s390_cpu_pv_mem_read(env_archcpu(env), 0, work_sccb, + be16_to_cpu(header.length)); if (!sclp_command_code_valid(code)) { - work_sccb.h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND); + work_sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND); goto out_write; } - sclp_c->execute(sclp, &work_sccb, code); + sclp_c->execute(sclp, work_sccb, code); out_write: - s390_cpu_pv_mem_write(env_archcpu(env), 0, &work_sccb, - be16_to_cpu(work_sccb.h.length)); + s390_cpu_pv_mem_write(env_archcpu(env), 0, work_sccb, + be16_to_cpu(work_sccb->h.length)); sclp_c->service_interrupt(sclp, SCLP_PV_DUMMY_ADDR); return 0; } @@ -241,9 +297,8 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code) { SCLPDevice *sclp = get_sclp_device(); SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp); - SCCB work_sccb; - - hwaddr sccb_len = sizeof(SCCB); + SCCBHeader header; + g_autofree SCCB *work_sccb = NULL; /* first some basic checks on program checks */ if (env->psw.mask & PSW_MASK_PSTATE) { @@ -257,32 +312,36 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code) return -PGM_SPECIFICATION; } + /* the header contains the actual length of the sccb */ + cpu_physical_memory_read(sccb, &header, sizeof(SCCBHeader)); + + /* Valid sccb sizes */ + if (be16_to_cpu(header.length) < sizeof(SCCBHeader)) { + return -PGM_SPECIFICATION; + } + /* * we want to work on a private copy of the sccb, to prevent guests * from playing dirty tricks by modifying the memory content after * the host has checked the values */ - cpu_physical_memory_read(sccb, &work_sccb, sccb_len); - - /* Valid sccb sizes */ - if (be16_to_cpu(work_sccb.h.length) < sizeof(SCCBHeader)) { - return -PGM_SPECIFICATION; - } + work_sccb = g_malloc0(be16_to_cpu(header.length)); + cpu_physical_memory_read(sccb, work_sccb, be16_to_cpu(header.length)); if (!sclp_command_code_valid(code)) { - work_sccb.h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND); + work_sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND); goto out_write; } - if ((sccb + be16_to_cpu(work_sccb.h.length)) > ((sccb & PAGE_MASK) + PAGE_SIZE)) { - work_sccb.h.response_code = cpu_to_be16(SCLP_RC_SCCB_BOUNDARY_VIOLATION); + if (!sccb_verify_boundary(sccb, be16_to_cpu(work_sccb->h.length), code)) { + work_sccb->h.response_code = cpu_to_be16(SCLP_RC_SCCB_BOUNDARY_VIOLATION); goto out_write; } - sclp_c->execute(sclp, &work_sccb, code); + sclp_c->execute(sclp, work_sccb, code); out_write: - cpu_physical_memory_write(sccb, &work_sccb, - be16_to_cpu(work_sccb.h.length)); + cpu_physical_memory_write(sccb, work_sccb, + be16_to_cpu(work_sccb->h.length)); sclp_c->service_interrupt(sclp, sccb); @@ -322,39 +381,32 @@ void s390_sclp_init(void) object_property_add_child(qdev_get_machine(), TYPE_SCLP, new); object_unref(new); - qdev_init_nofail(DEVICE(new)); + qdev_realize(DEVICE(new), NULL, &error_fatal); } static void sclp_realize(DeviceState *dev, Error **errp) { MachineState *machine = MACHINE(qdev_get_machine()); SCLPDevice *sclp = SCLP(dev); - Error *err = NULL; uint64_t hw_limit; int ret; - object_property_set_bool(OBJECT(sclp->event_facility), true, "realized", - &err); - if (err) { - goto out; - } /* * qdev_device_add searches the sysbus for TYPE_SCLP_EVENTS_BUS. As long * as we can't find a fitting bus via the qom tree, we have to add the * event facility to the sysbus, so e.g. a sclp console can be created. */ - qdev_set_parent_bus(DEVICE(sclp->event_facility), sysbus_get_default()); + if (!sysbus_realize(SYS_BUS_DEVICE(sclp->event_facility), errp)) { + return; + } ret = s390_set_memory_limit(machine->maxram_size, &hw_limit); if (ret == -E2BIG) { - error_setg(&err, "host supports a maximum of %" PRIu64 " GB", + error_setg(errp, "host supports a maximum of %" PRIu64 " GB", hw_limit / GiB); } else if (ret) { - error_setg(&err, "setting the guest size failed"); + error_setg(errp, "setting the guest size failed"); } - -out: - error_propagate(errp, err); } static void sclp_memory_init(SCLPDevice *sclp) diff --git a/hw/s390x/tod.c b/hw/s390x/tod.c index 7324e37b5e8be4a34049ad7531e14c74621f9197..3c2979175ef7d83da027d038cda4a79f270b9254 100644 --- a/hw/s390x/tod.c +++ b/hw/s390x/tod.c @@ -29,7 +29,7 @@ void s390_init_tod(void) object_property_add_child(qdev_get_machine(), TYPE_S390_TOD, obj); object_unref(obj); - qdev_init_nofail(DEVICE(obj)); + qdev_realize(DEVICE(obj), NULL, &error_fatal); } S390TODState *s390_get_todstate(void) diff --git a/hw/s390x/trace-events b/hw/s390x/trace-events index 0dc5b818c471135799b358e8bd91be024bbe6380..8156693749d706afb28338e3a7c57c92497a7706 100644 --- a/hw/s390x/trace-events +++ b/hw/s390x/trace-events @@ -14,3 +14,8 @@ css_do_sic(uint16_t mode, uint8_t isc) "CSS: set interruption mode 0x%x on isc 0 virtio_ccw_interpret_ccw(int cssid, int ssid, int schid, int cmd_code) "VIRTIO-CCW: %x.%x.%04x: interpret command 0x%x" virtio_ccw_new_device(int cssid, int ssid, int schid, int devno, const char *devno_mode) "VIRTIO-CCW: add subchannel %x.%x.%04x, devno 0x%04x (%s)" virtio_ccw_set_ind(uint64_t ind_loc, uint8_t ind_old, uint8_t ind_new) "VIRTIO-CCW: indicator at %" PRIu64 ": 0x%x->0x%x" + +# s390-pci-vfio.c +s390_pci_clp_cap(const char *id, uint32_t cap) "PCI: %s: missing expected CLP capability %u" +s390_pci_clp_cap_size(const char *id, uint32_t size, uint32_t cap) "PCI: %s: bad size (%u) for CLP capability %u" +s390_pci_clp_dev_info(const char *id) "PCI: %s: cannot read vfio device info" diff --git a/hw/s390x/trace.h b/hw/s390x/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..d6568b36483684c0212276ea31d62a740b361e07 --- /dev/null +++ b/hw/s390x/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_s390x.h" diff --git a/hw/s390x/vhost-user-fs-ccw.c b/hw/s390x/vhost-user-fs-ccw.c new file mode 100644 index 0000000000000000000000000000000000000000..6c6f2692930110aebf8038061b259407238942bf --- /dev/null +++ b/hw/s390x/vhost-user-fs-ccw.c @@ -0,0 +1,75 @@ +/* + * virtio ccw vhost-user-fs implementation + * + * Copyright 2020 IBM Corp. + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ +#include "qemu/osdep.h" +#include "hw/qdev-properties.h" +#include "qapi/error.h" +#include "hw/virtio/vhost-user-fs.h" +#include "virtio-ccw.h" + +typedef struct VHostUserFSCcw { + VirtioCcwDevice parent_obj; + VHostUserFS vdev; +} VHostUserFSCcw; + +#define TYPE_VHOST_USER_FS_CCW "vhost-user-fs-ccw" +#define VHOST_USER_FS_CCW(obj) \ + OBJECT_CHECK(VHostUserFSCcw, (obj), TYPE_VHOST_USER_FS_CCW) + + +static Property vhost_user_fs_ccw_properties[] = { + DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, + VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), + DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, + VIRTIO_CCW_MAX_REV), + DEFINE_PROP_END_OF_LIST(), +}; + +static void vhost_user_fs_ccw_realize(VirtioCcwDevice *ccw_dev, Error **errp) +{ + VHostUserFSCcw *dev = VHOST_USER_FS_CCW(ccw_dev); + DeviceState *vdev = DEVICE(&dev->vdev); + + qdev_realize(vdev, BUS(&ccw_dev->bus), errp); +} + +static void vhost_user_fs_ccw_instance_init(Object *obj) +{ + VHostUserFSCcw *dev = VHOST_USER_FS_CCW(obj); + VirtioCcwDevice *ccw_dev = VIRTIO_CCW_DEVICE(obj); + + ccw_dev->force_revision_1 = true; + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VHOST_USER_FS); +} + +static void vhost_user_fs_ccw_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass); + + k->realize = vhost_user_fs_ccw_realize; + device_class_set_props(dc, vhost_user_fs_ccw_properties); + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); +} + +static const TypeInfo vhost_user_fs_ccw = { + .name = TYPE_VHOST_USER_FS_CCW, + .parent = TYPE_VIRTIO_CCW_DEVICE, + .instance_size = sizeof(VHostUserFSCcw), + .instance_init = vhost_user_fs_ccw_instance_init, + .class_init = vhost_user_fs_ccw_class_init, +}; + +static void vhost_user_fs_ccw_register(void) +{ + type_register_static(&vhost_user_fs_ccw); +} + +type_init(vhost_user_fs_ccw_register) diff --git a/hw/s390x/vhost-vsock-ccw.c b/hw/s390x/vhost-vsock-ccw.c index 12dee15e112cec3caff9b5df386f8de41f149914..246416a8f964a1d9ad23c16b9b41d95fa9c01efe 100644 --- a/hw/s390x/vhost-vsock-ccw.c +++ b/hw/s390x/vhost-vsock-ccw.c @@ -24,8 +24,7 @@ static void vhost_vsock_ccw_realize(VirtioCcwDevice *ccw_dev, Error **errp) VHostVSockCCWState *dev = VHOST_VSOCK_CCW(ccw_dev); DeviceState *vdev = DEVICE(&dev->vdev); - qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&ccw_dev->bus), errp); } static void vhost_vsock_ccw_class_init(ObjectClass *klass, void *data) @@ -41,9 +40,21 @@ static void vhost_vsock_ccw_class_init(ObjectClass *klass, void *data) static void vhost_vsock_ccw_instance_init(Object *obj) { VHostVSockCCWState *dev = VHOST_VSOCK_CCW(obj); + VirtioCcwDevice *ccw_dev = VIRTIO_CCW_DEVICE(obj); + VirtIODevice *virtio_dev; virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), TYPE_VHOST_VSOCK); + + virtio_dev = VIRTIO_DEVICE(&dev->vdev); + + /* + * To avoid migration issues, we force virtio version 1 only when + * legacy check is enabled in the new machine types (>= 5.1). + */ + if (!virtio_legacy_check_disabled(virtio_dev)) { + ccw_dev->force_revision_1 = true; + } } static const TypeInfo vhost_vsock_ccw_info = { diff --git a/hw/s390x/virtio-ccw-9p.c b/hw/s390x/virtio-ccw-9p.c index 08e1d5d41615a123e9c7a3143c017e950bda1aab..88c8884fc51d722fddd7f89c35806d51567cd56b 100644 --- a/hw/s390x/virtio-ccw-9p.c +++ b/hw/s390x/virtio-ccw-9p.c @@ -21,8 +21,7 @@ static void virtio_ccw_9p_realize(VirtioCcwDevice *ccw_dev, Error **errp) V9fsCCWState *dev = VIRTIO_9P_CCW(ccw_dev); DeviceState *vdev = DEVICE(&dev->vdev); - qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&ccw_dev->bus), errp); } static void virtio_ccw_9p_instance_init(Object *obj) diff --git a/hw/s390x/virtio-ccw-balloon.c b/hw/s390x/virtio-ccw-balloon.c index ef3308ecabb0297144c847bae25fd52a354260aa..4c7631a4335051defd3e48197efd476f3a23a25b 100644 --- a/hw/s390x/virtio-ccw-balloon.c +++ b/hw/s390x/virtio-ccw-balloon.c @@ -21,8 +21,7 @@ static void virtio_ccw_balloon_realize(VirtioCcwDevice *ccw_dev, Error **errp) VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(ccw_dev); DeviceState *vdev = DEVICE(&dev->vdev); - qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&ccw_dev->bus), errp); } static void virtio_ccw_balloon_instance_init(Object *obj) diff --git a/hw/s390x/virtio-ccw-blk.c b/hw/s390x/virtio-ccw-blk.c index 7287932b7ec49854aa4369eb2df7bb20241cb738..2294ce1ce4a04b4a7513ac8fb76f4be808cb7efd 100644 --- a/hw/s390x/virtio-ccw-blk.c +++ b/hw/s390x/virtio-ccw-blk.c @@ -21,8 +21,7 @@ static void virtio_ccw_blk_realize(VirtioCcwDevice *ccw_dev, Error **errp) VirtIOBlkCcw *dev = VIRTIO_BLK_CCW(ccw_dev); DeviceState *vdev = DEVICE(&dev->vdev); - qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&ccw_dev->bus), errp); } static void virtio_ccw_blk_instance_init(Object *obj) diff --git a/hw/s390x/virtio-ccw-crypto.c b/hw/s390x/virtio-ccw-crypto.c index 1a2690cf9e624f975cc8270d625c8b15ec7c1804..358c74fb4bca223b6c470ffe2d0bd6d117d00a12 100644 --- a/hw/s390x/virtio-ccw-crypto.c +++ b/hw/s390x/virtio-ccw-crypto.c @@ -19,18 +19,10 @@ static void virtio_ccw_crypto_realize(VirtioCcwDevice *ccw_dev, Error **errp) { VirtIOCryptoCcw *dev = VIRTIO_CRYPTO_CCW(ccw_dev); DeviceState *vdev = DEVICE(&dev->vdev); - Error *err = NULL; - qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(vdev, BUS(&ccw_dev->bus), errp)) { return; } - - object_property_set_link(OBJECT(vdev), - OBJECT(dev->vdev.conf.cryptodev), "cryptodev", - NULL); } static void virtio_ccw_crypto_instance_init(Object *obj) diff --git a/hw/s390x/virtio-ccw-gpu.c b/hw/s390x/virtio-ccw-gpu.c index f69e3ff5a0e5dab82d5e529524338a1b40bf26df..c301e2586bde8aff7333ea029c024266ad5d1071 100644 --- a/hw/s390x/virtio-ccw-gpu.c +++ b/hw/s390x/virtio-ccw-gpu.c @@ -20,8 +20,7 @@ static void virtio_ccw_gpu_realize(VirtioCcwDevice *ccw_dev, Error **errp) VirtIOGPUCcw *dev = VIRTIO_GPU_CCW(ccw_dev); DeviceState *vdev = DEVICE(&dev->vdev); - qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&ccw_dev->bus), errp); } static void virtio_ccw_gpu_instance_init(Object *obj) diff --git a/hw/s390x/virtio-ccw-input.c b/hw/s390x/virtio-ccw-input.c index b257dfd46775d460288a89376a60f117f47d8bb2..83136fbba15cf2724bdae2abc88612d0f958ed4b 100644 --- a/hw/s390x/virtio-ccw-input.c +++ b/hw/s390x/virtio-ccw-input.c @@ -1,5 +1,5 @@ /* - * virtio ccw scsi implementation + * virtio ccw input implementation * * Copyright 2012, 2015 IBM Corp. * @@ -20,8 +20,7 @@ static void virtio_ccw_input_realize(VirtioCcwDevice *ccw_dev, Error **errp) VirtIOInputCcw *dev = VIRTIO_INPUT_CCW(ccw_dev); DeviceState *vdev = DEVICE(&dev->vdev); - qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&ccw_dev->bus), errp); } static Property virtio_ccw_input_properties[] = { diff --git a/hw/s390x/virtio-ccw-net.c b/hw/s390x/virtio-ccw-net.c index 26c4d873bfb35e653ab6b27d874f8c8d1e7f8d45..3860d4e6ea93c5a72d005d862d3d5d9b6c05f240 100644 --- a/hw/s390x/virtio-ccw-net.c +++ b/hw/s390x/virtio-ccw-net.c @@ -24,8 +24,7 @@ static void virtio_ccw_net_realize(VirtioCcwDevice *ccw_dev, Error **errp) virtio_net_set_netclient_name(&dev->vdev, qdev->id, object_get_typename(OBJECT(qdev))); - qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&ccw_dev->bus), errp); } static void virtio_ccw_net_instance_init(Object *obj) diff --git a/hw/s390x/virtio-ccw-rng.c b/hw/s390x/virtio-ccw-rng.c index d575e30cc6ff95ebb11e6b59fcd47a9f7619157d..2e3a9da5e8beaaa1ca9a25bd9f3a855ef979d8f7 100644 --- a/hw/s390x/virtio-ccw-rng.c +++ b/hw/s390x/virtio-ccw-rng.c @@ -20,18 +20,10 @@ static void virtio_ccw_rng_realize(VirtioCcwDevice *ccw_dev, Error **errp) { VirtIORNGCcw *dev = VIRTIO_RNG_CCW(ccw_dev); DeviceState *vdev = DEVICE(&dev->vdev); - Error *err = NULL; - qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(vdev, BUS(&ccw_dev->bus), errp)) { return; } - - object_property_set_link(OBJECT(dev), - OBJECT(dev->vdev.conf.rng), "rng", - NULL); } static void virtio_ccw_rng_instance_init(Object *obj) diff --git a/hw/s390x/virtio-ccw-scsi.c b/hw/s390x/virtio-ccw-scsi.c index 3cb3ad669d2aefe511a63f685dd84807ebe8d989..6e4beef700bd49b59874ad1b94f36eff32ad3daa 100644 --- a/hw/s390x/virtio-ccw-scsi.c +++ b/hw/s390x/virtio-ccw-scsi.c @@ -33,8 +33,7 @@ static void virtio_ccw_scsi_realize(VirtioCcwDevice *ccw_dev, Error **errp) g_free(bus_name); } - qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&ccw_dev->bus), errp); } static void virtio_ccw_scsi_instance_init(Object *obj) @@ -78,8 +77,7 @@ static void vhost_ccw_scsi_realize(VirtioCcwDevice *ccw_dev, Error **errp) VHostSCSICcw *dev = VHOST_SCSI_CCW(ccw_dev); DeviceState *vdev = DEVICE(&dev->vdev); - qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&ccw_dev->bus), errp); } static void vhost_ccw_scsi_instance_init(Object *obj) diff --git a/hw/s390x/virtio-ccw-serial.c b/hw/s390x/virtio-ccw-serial.c index 1764db2e70b47938032eee53051d29eddb4ba125..61958228d16974674e934e32e3d5e732eecae235 100644 --- a/hw/s390x/virtio-ccw-serial.c +++ b/hw/s390x/virtio-ccw-serial.c @@ -33,8 +33,7 @@ static void virtio_ccw_serial_realize(VirtioCcwDevice *ccw_dev, Error **errp) g_free(bus_name); } - qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&ccw_dev->bus), errp); } diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index c1f4bb1d331df1efb1026a8da50778f28d36f47a..4582e94ae7dc4d75117ffc20104799d12ed4915e 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -786,9 +786,10 @@ static inline VirtioCcwDevice *to_virtio_ccw_dev_fast(DeviceState *d) static uint8_t virtio_set_ind_atomic(SubchDev *sch, uint64_t ind_loc, uint8_t to_be_set) { - uint8_t ind_old, ind_new; + uint8_t expected, actual; hwaddr len = 1; - uint8_t *ind_addr; + /* avoid multiple fetches */ + uint8_t volatile *ind_addr; ind_addr = cpu_physical_memory_map(ind_loc, &len, true); if (!ind_addr) { @@ -796,14 +797,15 @@ static uint8_t virtio_set_ind_atomic(SubchDev *sch, uint64_t ind_loc, __func__, sch->cssid, sch->ssid, sch->schid); return -1; } + actual = *ind_addr; do { - ind_old = *ind_addr; - ind_new = ind_old | to_be_set; - } while (atomic_cmpxchg(ind_addr, ind_old, ind_new) != ind_old); - trace_virtio_ccw_set_ind(ind_loc, ind_old, ind_new); - cpu_physical_memory_unmap(ind_addr, len, 1, len); + expected = actual; + actual = qatomic_cmpxchg(ind_addr, expected, expected | to_be_set); + } while (actual != expected); + trace_virtio_ccw_set_ind(ind_loc, actual, actual | to_be_set); + cpu_physical_memory_unmap((void *)ind_addr, len, 1, len); - return ind_old; + return actual; } static void virtio_ccw_notify(DeviceState *d, uint16_t vector) @@ -1119,6 +1121,21 @@ static void virtio_ccw_device_plugged(DeviceState *d, Error **errp) dev->max_rev = 0; } + if (!virtio_ccw_rev_max(dev) && !virtio_legacy_allowed(vdev)) { + /* + * To avoid migration issues, we allow legacy mode when legacy + * check is disabled in the old machine types (< 5.1). + */ + if (virtio_legacy_check_disabled(vdev)) { + warn_report("device requires revision >= 1, but for backward " + "compatibility max_revision=0 is allowed"); + } else { + error_setg(errp, "Invalid value of property max_rev " + "(is %d expected >= 1)", virtio_ccw_rev_max(dev)); + return; + } + } + if (virtio_get_num_queues(vdev) > VIRTIO_QUEUE_MAX) { error_setg(errp, "The number of virtqueues %d " "exceeds virtio limit %d", n, @@ -1229,6 +1246,7 @@ static const TypeInfo virtio_ccw_bus_info = { .name = TYPE_VIRTIO_CCW_BUS, .parent = TYPE_VIRTIO_BUS, .instance_size = sizeof(VirtioCcwBusState), + .class_size = sizeof(VirtioCcwBusClass), .class_init = virtio_ccw_bus_class_init, }; diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h index c0e33552487290aff7ceaaaa7e658c19d0c9ce6e..49a2b8ca42df799f1815f8af32d15d492c9b3a2d 100644 --- a/hw/s390x/virtio-ccw.h +++ b/hw/s390x/virtio-ccw.h @@ -17,6 +17,7 @@ #include "hw/virtio/virtio-net.h" #include "hw/virtio/virtio-serial.h" #include "hw/virtio/virtio-scsi.h" +#include "qom/object.h" #ifdef CONFIG_VHOST_SCSI #include "hw/virtio/vhost-scsi.h" #endif @@ -53,32 +54,22 @@ #define CCW_CMD_SET_VIRTIO_REV 0x83 #define TYPE_VIRTIO_CCW_DEVICE "virtio-ccw-device" -#define VIRTIO_CCW_DEVICE(obj) \ - OBJECT_CHECK(VirtioCcwDevice, (obj), TYPE_VIRTIO_CCW_DEVICE) -#define VIRTIO_CCW_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtIOCCWDeviceClass, (klass), TYPE_VIRTIO_CCW_DEVICE) -#define VIRTIO_CCW_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtIOCCWDeviceClass, (obj), TYPE_VIRTIO_CCW_DEVICE) +OBJECT_DECLARE_TYPE(VirtioCcwDevice, VirtIOCCWDeviceClass, VIRTIO_CCW_DEVICE) typedef struct VirtioBusState VirtioCcwBusState; typedef struct VirtioBusClass VirtioCcwBusClass; #define TYPE_VIRTIO_CCW_BUS "virtio-ccw-bus" -#define VIRTIO_CCW_BUS(obj) \ - OBJECT_CHECK(VirtioCcwBus, (obj), TYPE_VIRTIO_CCW_BUS) -#define VIRTIO_CCW_BUS_GET_CLASS(obj) \ - OBJECT_CHECK(VirtioCcwBusState, (obj), TYPE_VIRTIO_CCW_BUS) -#define VIRTIO_CCW_BUS_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtioCcwBusClass, klass, TYPE_VIRTIO_CCW_BUS) +DECLARE_OBJ_CHECKERS(VirtioCcwBusState, VirtioCcwBusClass, + VIRTIO_CCW_BUS, TYPE_VIRTIO_CCW_BUS) -typedef struct VirtioCcwDevice VirtioCcwDevice; -typedef struct VirtIOCCWDeviceClass { +struct VirtIOCCWDeviceClass { CCWDeviceClass parent_class; void (*realize)(VirtioCcwDevice *dev, Error **errp); void (*unrealize)(VirtioCcwDevice *dev); void (*parent_reset)(DeviceState *dev); -} VirtIOCCWDeviceClass; +}; /* Performance improves when virtqueue kick processing is decoupled from the * vcpu thread using ioeventfd for some devices. */ @@ -111,92 +102,84 @@ static inline int virtio_ccw_rev_max(VirtioCcwDevice *dev) /* virtio-scsi-ccw */ #define TYPE_VIRTIO_SCSI_CCW "virtio-scsi-ccw" -#define VIRTIO_SCSI_CCW(obj) \ - OBJECT_CHECK(VirtIOSCSICcw, (obj), TYPE_VIRTIO_SCSI_CCW) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOSCSICcw, VIRTIO_SCSI_CCW) -typedef struct VirtIOSCSICcw { +struct VirtIOSCSICcw { VirtioCcwDevice parent_obj; VirtIOSCSI vdev; -} VirtIOSCSICcw; +}; #ifdef CONFIG_VHOST_SCSI /* vhost-scsi-ccw */ #define TYPE_VHOST_SCSI_CCW "vhost-scsi-ccw" -#define VHOST_SCSI_CCW(obj) \ - OBJECT_CHECK(VHostSCSICcw, (obj), TYPE_VHOST_SCSI_CCW) +OBJECT_DECLARE_SIMPLE_TYPE(VHostSCSICcw, VHOST_SCSI_CCW) -typedef struct VHostSCSICcw { +struct VHostSCSICcw { VirtioCcwDevice parent_obj; VHostSCSI vdev; -} VHostSCSICcw; +}; #endif /* virtio-blk-ccw */ #define TYPE_VIRTIO_BLK_CCW "virtio-blk-ccw" -#define VIRTIO_BLK_CCW(obj) \ - OBJECT_CHECK(VirtIOBlkCcw, (obj), TYPE_VIRTIO_BLK_CCW) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOBlkCcw, VIRTIO_BLK_CCW) -typedef struct VirtIOBlkCcw { +struct VirtIOBlkCcw { VirtioCcwDevice parent_obj; VirtIOBlock vdev; -} VirtIOBlkCcw; +}; /* virtio-balloon-ccw */ #define TYPE_VIRTIO_BALLOON_CCW "virtio-balloon-ccw" -#define VIRTIO_BALLOON_CCW(obj) \ - OBJECT_CHECK(VirtIOBalloonCcw, (obj), TYPE_VIRTIO_BALLOON_CCW) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOBalloonCcw, VIRTIO_BALLOON_CCW) -typedef struct VirtIOBalloonCcw { +struct VirtIOBalloonCcw { VirtioCcwDevice parent_obj; VirtIOBalloon vdev; -} VirtIOBalloonCcw; +}; /* virtio-serial-ccw */ #define TYPE_VIRTIO_SERIAL_CCW "virtio-serial-ccw" -#define VIRTIO_SERIAL_CCW(obj) \ - OBJECT_CHECK(VirtioSerialCcw, (obj), TYPE_VIRTIO_SERIAL_CCW) +OBJECT_DECLARE_SIMPLE_TYPE(VirtioSerialCcw, VIRTIO_SERIAL_CCW) -typedef struct VirtioSerialCcw { +struct VirtioSerialCcw { VirtioCcwDevice parent_obj; VirtIOSerial vdev; -} VirtioSerialCcw; +}; /* virtio-net-ccw */ #define TYPE_VIRTIO_NET_CCW "virtio-net-ccw" -#define VIRTIO_NET_CCW(obj) \ - OBJECT_CHECK(VirtIONetCcw, (obj), TYPE_VIRTIO_NET_CCW) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIONetCcw, VIRTIO_NET_CCW) -typedef struct VirtIONetCcw { +struct VirtIONetCcw { VirtioCcwDevice parent_obj; VirtIONet vdev; -} VirtIONetCcw; +}; /* virtio-rng-ccw */ #define TYPE_VIRTIO_RNG_CCW "virtio-rng-ccw" -#define VIRTIO_RNG_CCW(obj) \ - OBJECT_CHECK(VirtIORNGCcw, (obj), TYPE_VIRTIO_RNG_CCW) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIORNGCcw, VIRTIO_RNG_CCW) -typedef struct VirtIORNGCcw { +struct VirtIORNGCcw { VirtioCcwDevice parent_obj; VirtIORNG vdev; -} VirtIORNGCcw; +}; /* virtio-crypto-ccw */ #define TYPE_VIRTIO_CRYPTO_CCW "virtio-crypto-ccw" -#define VIRTIO_CRYPTO_CCW(obj) \ - OBJECT_CHECK(VirtIOCryptoCcw, (obj), TYPE_VIRTIO_CRYPTO_CCW) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOCryptoCcw, VIRTIO_CRYPTO_CCW) -typedef struct VirtIOCryptoCcw { +struct VirtIOCryptoCcw { VirtioCcwDevice parent_obj; VirtIOCrypto vdev; -} VirtIOCryptoCcw; +}; VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch); @@ -204,56 +187,51 @@ VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch); #include "hw/9pfs/virtio-9p.h" #define TYPE_VIRTIO_9P_CCW "virtio-9p-ccw" -#define VIRTIO_9P_CCW(obj) \ - OBJECT_CHECK(V9fsCCWState, (obj), TYPE_VIRTIO_9P_CCW) +OBJECT_DECLARE_SIMPLE_TYPE(V9fsCCWState, VIRTIO_9P_CCW) -typedef struct V9fsCCWState { +struct V9fsCCWState { VirtioCcwDevice parent_obj; V9fsVirtioState vdev; -} V9fsCCWState; +}; #endif /* CONFIG_VIRTFS */ #ifdef CONFIG_VHOST_VSOCK #define TYPE_VHOST_VSOCK_CCW "vhost-vsock-ccw" -#define VHOST_VSOCK_CCW(obj) \ - OBJECT_CHECK(VHostVSockCCWState, (obj), TYPE_VHOST_VSOCK_CCW) +OBJECT_DECLARE_SIMPLE_TYPE(VHostVSockCCWState, VHOST_VSOCK_CCW) -typedef struct VHostVSockCCWState { +struct VHostVSockCCWState { VirtioCcwDevice parent_obj; VHostVSock vdev; -} VHostVSockCCWState; +}; #endif /* CONFIG_VHOST_VSOCK */ #define TYPE_VIRTIO_GPU_CCW "virtio-gpu-ccw" -#define VIRTIO_GPU_CCW(obj) \ - OBJECT_CHECK(VirtIOGPUCcw, (obj), TYPE_VIRTIO_GPU_CCW) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOGPUCcw, VIRTIO_GPU_CCW) -typedef struct VirtIOGPUCcw { +struct VirtIOGPUCcw { VirtioCcwDevice parent_obj; VirtIOGPU vdev; -} VirtIOGPUCcw; +}; #define TYPE_VIRTIO_INPUT_CCW "virtio-input-ccw" -#define VIRTIO_INPUT_CCW(obj) \ - OBJECT_CHECK(VirtIOInputCcw, (obj), TYPE_VIRTIO_INPUT_CCW) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOInputCcw, VIRTIO_INPUT_CCW) -typedef struct VirtIOInputCcw { +struct VirtIOInputCcw { VirtioCcwDevice parent_obj; VirtIOInput vdev; -} VirtIOInputCcw; +}; #define TYPE_VIRTIO_INPUT_HID_CCW "virtio-input-hid-ccw" #define TYPE_VIRTIO_KEYBOARD_CCW "virtio-keyboard-ccw" #define TYPE_VIRTIO_MOUSE_CCW "virtio-mouse-ccw" #define TYPE_VIRTIO_TABLET_CCW "virtio-tablet-ccw" -#define VIRTIO_INPUT_HID_CCW(obj) \ - OBJECT_CHECK(VirtIOInputHIDCcw, (obj), TYPE_VIRTIO_INPUT_HID_CCW) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOInputHIDCcw, VIRTIO_INPUT_HID_CCW) -typedef struct VirtIOInputHIDCcw { +struct VirtIOInputHIDCcw { VirtioCcwDevice parent_obj; VirtIOInputHID vdev; -} VirtIOInputHIDCcw; +}; #endif diff --git a/hw/scsi/Makefile.objs b/hw/scsi/Makefile.objs deleted file mode 100644 index 54b36ed8b1068bd3c8ff188118976f0a6faf52f4..0000000000000000000000000000000000000000 --- a/hw/scsi/Makefile.objs +++ /dev/null @@ -1,15 +0,0 @@ -common-obj-y += scsi-disk.o emulation.o -common-obj-y += scsi-generic.o scsi-bus.o -common-obj-$(CONFIG_LSI_SCSI_PCI) += lsi53c895a.o -common-obj-$(CONFIG_MPTSAS_SCSI_PCI) += mptsas.o mptconfig.o mptendian.o -common-obj-$(CONFIG_MEGASAS_SCSI_PCI) += megasas.o -common-obj-$(CONFIG_VMW_PVSCSI_SCSI_PCI) += vmw_pvscsi.o -common-obj-$(CONFIG_ESP) += esp.o -common-obj-$(CONFIG_ESP_PCI) += esp-pci.o -obj-$(CONFIG_SPAPR_VSCSI) += spapr_vscsi.o - -ifeq ($(CONFIG_VIRTIO_SCSI),y) -obj-y += virtio-scsi.o virtio-scsi-dataplane.o -obj-$(CONFIG_VHOST_SCSI) += vhost-scsi-common.o vhost-scsi.o -obj-$(CONFIG_VHOST_USER_SCSI) += vhost-scsi-common.o vhost-user-scsi.o -endif diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c index 497a8d59019018f44aebb450f0a82f001c1bec00..2ce96dc56eebbf587ca788c85c1034fac8a0fa14 100644 --- a/hw/scsi/esp-pci.c +++ b/hw/scsi/esp-pci.c @@ -33,11 +33,13 @@ #include "qapi/error.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" #define TYPE_AM53C974_DEVICE "am53c974" -#define PCI_ESP(obj) \ - OBJECT_CHECK(PCIESPState, (obj), TYPE_AM53C974_DEVICE) +typedef struct PCIESPState PCIESPState; +DECLARE_INSTANCE_CHECKER(PCIESPState, PCI_ESP, + TYPE_AM53C974_DEVICE) #define DMA_CMD 0x0 #define DMA_STC 0x1 @@ -64,7 +66,7 @@ #define SBAC_STATUS (1 << 24) -typedef struct PCIESPState { +struct PCIESPState { /*< private >*/ PCIDevice parent_obj; /*< public >*/ @@ -73,7 +75,7 @@ typedef struct PCIESPState { uint32_t dma_regs[8]; uint32_t sbac; ESPState esp; -} PCIESPState; +}; static void esp_pci_handle_idle(PCIESPState *pci, uint32_t val) { @@ -408,14 +410,15 @@ static const TypeInfo esp_pci_info = { }, }; -typedef struct { +struct DC390State { PCIESPState pci; eeprom_t *eeprom; -} DC390State; +}; +typedef struct DC390State DC390State; #define TYPE_DC390_DEVICE "dc390" -#define DC390(obj) \ - OBJECT_CHECK(DC390State, obj, TYPE_DC390_DEVICE) +DECLARE_INSTANCE_CHECKER(DC390State, DC390, + TYPE_DC390_DEVICE) #define EE_ADAPT_SCSI_ID 64 #define EE_MODE2 65 @@ -521,7 +524,7 @@ static void dc390_class_init(ObjectClass *klass, void *data) } static const TypeInfo dc390_info = { - .name = "dc390", + .name = TYPE_DC390_DEVICE, .parent = TYPE_AM53C974_DEVICE, .instance_size = sizeof(DC390State), .class_init = dc390_class_init, diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 405f8b7cbcf7d3712295dd6df126cf5c5a19742a..b84e0fe33e9e18446eda28786e8f462fdf2f9b3f 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -929,7 +929,7 @@ static const struct SCSIBusInfo esp_scsi_info = { static void sysbus_esp_gpio_demux(void *opaque, int irq, int level) { - SysBusESPState *sysbus = ESP_STATE(opaque); + SysBusESPState *sysbus = ESP(opaque); ESPState *s = &sysbus->esp; switch (irq) { @@ -945,7 +945,7 @@ static void sysbus_esp_gpio_demux(void *opaque, int irq, int level) static void sysbus_esp_realize(DeviceState *dev, Error **errp) { SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - SysBusESPState *sysbus = ESP_STATE(dev); + SysBusESPState *sysbus = ESP(dev); ESPState *s = &sysbus->esp; sysbus_init_irq(sbd, &s->irq); @@ -967,7 +967,7 @@ static void sysbus_esp_realize(DeviceState *dev, Error **errp) static void sysbus_esp_hard_reset(DeviceState *dev) { - SysBusESPState *sysbus = ESP_STATE(dev); + SysBusESPState *sysbus = ESP(dev); esp_hard_reset(&sysbus->esp); } diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index 63ff4181de588b82602b5c14b0e24e4305b3dcd0..7d13c7dc1c46e8a32ed0e3e090ff4fc6fe8c98f5 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -23,6 +23,7 @@ #include "qemu/log.h" #include "qemu/module.h" #include "trace.h" +#include "qom/object.h" static const char *names[] = { "SCNTL0", "SCNTL1", "SCNTL2", "SCNTL3", "SCID", "SXFER", "SDID", "GPREG", @@ -213,7 +214,7 @@ enum { LSI_MSG_ACTION_DIN = 3, }; -typedef struct { +struct LSIState { /*< private >*/ PCIDevice parent_obj; /*< public >*/ @@ -303,13 +304,12 @@ typedef struct { uint32_t adder; uint8_t script_ram[2048 * sizeof(uint32_t)]; -} LSIState; +}; #define TYPE_LSI53C810 "lsi53c810" #define TYPE_LSI53C895A "lsi53c895a" -#define LSI53C895A(obj) \ - OBJECT_CHECK(LSIState, (obj), TYPE_LSI53C895A) +OBJECT_DECLARE_SIMPLE_TYPE(LSIState, LSI53C895A) static const char *scsi_phases[] = { "DOUT", diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index af18c88b656e7f5fa299c5f0dda1158ad66472e9..1a5fc5857db34a9963cb47201acee7c171e642f2 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -34,6 +34,7 @@ #include "qapi/error.h" #include "mfi.h" #include "migration/vmstate.h" +#include "qom/object.h" #define MEGASAS_VERSION_GEN1 "1.70" #define MEGASAS_VERSION_GEN2 "1.80" @@ -54,10 +55,6 @@ #define MEGASAS_FLAG_USE_QUEUE64 1 #define MEGASAS_MASK_USE_QUEUE64 (1 << MEGASAS_FLAG_USE_QUEUE64) -static const char *mfi_frame_desc[] = { - "MFI init", "LD Read", "LD Write", "LD SCSI", "PD SCSI", - "MFI Doorbell", "MFI Abort", "MFI SMP", "MFI Stop"}; - typedef struct MegasasCmd { uint32_t index; uint16_t flags; @@ -76,7 +73,7 @@ typedef struct MegasasCmd { struct MegasasState *state; } MegasasCmd; -typedef struct MegasasState { +struct MegasasState { /*< private >*/ PCIDevice parent_obj; /*< public >*/ @@ -86,62 +83,60 @@ typedef struct MegasasState { MemoryRegion queue_io; uint32_t frame_hi; - int fw_state; + uint32_t fw_state; uint32_t fw_sge; uint32_t fw_cmds; uint32_t flags; - int fw_luns; - int intr_mask; - int doorbell; - int busy; - int diag; - int adp_reset; + uint32_t fw_luns; + uint32_t intr_mask; + uint32_t doorbell; + uint32_t busy; + uint32_t diag; + uint32_t adp_reset; OnOffAuto msi; OnOffAuto msix; MegasasCmd *event_cmd; - int event_locale; + uint16_t event_locale; int event_class; - int event_count; - int shutdown_event; - int boot_event; + uint32_t event_count; + uint32_t shutdown_event; + uint32_t boot_event; uint64_t sas_addr; char *hba_serial; uint64_t reply_queue_pa; void *reply_queue; - int reply_queue_len; - int reply_queue_head; - int reply_queue_tail; + uint16_t reply_queue_len; + uint16_t reply_queue_head; + uint16_t reply_queue_tail; uint64_t consumer_pa; uint64_t producer_pa; MegasasCmd frames[MEGASAS_MAX_FRAMES]; DECLARE_BITMAP(frame_map, MEGASAS_MAX_FRAMES); SCSIBus bus; -} MegasasState; +}; +typedef struct MegasasState MegasasState; -typedef struct MegasasBaseClass { +struct MegasasBaseClass { PCIDeviceClass parent_class; const char *product_name; const char *product_version; int mmio_bar; int ioport_bar; int osts; -} MegasasBaseClass; +}; +typedef struct MegasasBaseClass MegasasBaseClass; #define TYPE_MEGASAS_BASE "megasas-base" #define TYPE_MEGASAS_GEN1 "megasas" #define TYPE_MEGASAS_GEN2 "megasas-gen2" -#define MEGASAS(obj) \ - OBJECT_CHECK(MegasasState, (obj), TYPE_MEGASAS_BASE) +DECLARE_OBJ_CHECKERS(MegasasState, MegasasBaseClass, + MEGASAS, TYPE_MEGASAS_BASE) -#define MEGASAS_DEVICE_CLASS(oc) \ - OBJECT_CLASS_CHECK(MegasasBaseClass, (oc), TYPE_MEGASAS_BASE) -#define MEGASAS_DEVICE_GET_CLASS(oc) \ - OBJECT_GET_CLASS(MegasasBaseClass, (oc), TYPE_MEGASAS_BASE) #define MEGASAS_INTR_DISABLED_MASK 0xFFFFFFFF @@ -183,6 +178,20 @@ static void megasas_frame_set_scsi_status(MegasasState *s, stb_pci_dma(pci, frame + offsetof(struct mfi_frame_header, scsi_status), v); } +static inline const char *mfi_frame_desc(unsigned int cmd) +{ + static const char *mfi_frame_descs[] = { + "MFI init", "LD Read", "LD Write", "LD SCSI", "PD SCSI", + "MFI Doorbell", "MFI Abort", "MFI SMP", "MFI Stop" + }; + + if (cmd < ARRAY_SIZE(mfi_frame_descs)) { + return mfi_frame_descs[cmd]; + } + + return "Unknown"; +} + /* * Context is considered opaque, but the HBA firmware is running * in little endian mode. So convert it to little endian, too. @@ -268,10 +277,10 @@ static int megasas_map_sgl(MegasasState *s, MegasasCmd *cmd, union mfi_sgl *sgl) cmd->flags = le16_to_cpu(cmd->frame->header.flags); iov_count = cmd->frame->header.sge_count; - if (iov_count > MEGASAS_MAX_SGE) { + if (!iov_count || iov_count > MEGASAS_MAX_SGE) { trace_megasas_iovec_sgl_overflow(cmd->index, iov_count, MEGASAS_MAX_SGE); - return iov_count; + return -1; } pci_dma_sglist_init(&cmd->qsg, PCI_DEVICE(s), iov_count); for (i = 0; i < iov_count; i++) { @@ -301,7 +310,7 @@ static int megasas_map_sgl(MegasasState *s, MegasasCmd *cmd, union mfi_sgl *sgl) return 0; unmap: qemu_sglist_destroy(&cmd->qsg); - return iov_count - i; + return -1; } /* @@ -445,7 +454,7 @@ static MegasasCmd *megasas_lookup_frame(MegasasState *s, index = s->reply_queue_head; - while (num < s->fw_cmds) { + while (num < s->fw_cmds && index < MEGASAS_MAX_FRAMES) { if (s->frames[index].pa && s->frames[index].pa == frame) { cmd = &s->frames[index]; break; @@ -504,7 +513,7 @@ static MegasasCmd *megasas_enqueue_frame(MegasasState *s, cmd->pa = frame; /* Map all possible frames */ cmd->frame = pci_dma_map(pcid, frame, &frame_size_p, 0); - if (frame_size_p != frame_size) { + if (!cmd->frame || frame_size_p != frame_size) { trace_megasas_qf_map_failed(cmd->index, (unsigned long)frame); if (cmd->frame) { megasas_unmap_frame(s, cmd); @@ -723,7 +732,7 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd) { PCIDevice *pci_dev = PCI_DEVICE(s); PCIDeviceClass *pci_class = PCI_DEVICE_GET_CLASS(pci_dev); - MegasasBaseClass *base_class = MEGASAS_DEVICE_GET_CLASS(s); + MegasasBaseClass *base_class = MEGASAS_GET_CLASS(s); struct mfi_ctrl_info info; size_t dcmd_size = sizeof(info); BusChild *kid; @@ -1670,25 +1679,25 @@ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd, if (is_logical) { if (target_id >= MFI_MAX_LD || lun_id != 0) { trace_megasas_scsi_target_not_present( - mfi_frame_desc[frame_cmd], is_logical, target_id, lun_id); + mfi_frame_desc(frame_cmd), is_logical, target_id, lun_id); return MFI_STAT_DEVICE_NOT_FOUND; } } sdev = scsi_device_find(&s->bus, 0, target_id, lun_id); cmd->iov_size = le32_to_cpu(cmd->frame->header.data_len); - trace_megasas_handle_scsi(mfi_frame_desc[frame_cmd], is_logical, + trace_megasas_handle_scsi(mfi_frame_desc(frame_cmd), is_logical, target_id, lun_id, sdev, cmd->iov_size); if (!sdev || (megasas_is_jbod(s) && is_logical)) { trace_megasas_scsi_target_not_present( - mfi_frame_desc[frame_cmd], is_logical, target_id, lun_id); + mfi_frame_desc(frame_cmd), is_logical, target_id, lun_id); return MFI_STAT_DEVICE_NOT_FOUND; } if (cdb_len > 16) { trace_megasas_scsi_invalid_cdb_len( - mfi_frame_desc[frame_cmd], is_logical, + mfi_frame_desc(frame_cmd), is_logical, target_id, lun_id, cdb_len); megasas_write_sense(cmd, SENSE_CODE(INVALID_OPCODE)); cmd->frame->header.scsi_status = CHECK_CONDITION; @@ -1706,7 +1715,7 @@ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd, cmd->req = scsi_req_new(sdev, cmd->index, lun_id, cdb, cmd); if (!cmd->req) { trace_megasas_scsi_req_alloc_failed( - mfi_frame_desc[frame_cmd], target_id, lun_id); + mfi_frame_desc(frame_cmd), target_id, lun_id); megasas_write_sense(cmd, SENSE_CODE(NO_SENSE)); cmd->frame->header.scsi_status = BUSY; s->event_count++; @@ -1751,17 +1760,17 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd, int frame_cmd) } trace_megasas_handle_io(cmd->index, - mfi_frame_desc[frame_cmd], target_id, lun_id, + mfi_frame_desc(frame_cmd), target_id, lun_id, (unsigned long)lba_start, (unsigned long)lba_count); if (!sdev) { trace_megasas_io_target_not_present(cmd->index, - mfi_frame_desc[frame_cmd], target_id, lun_id); + mfi_frame_desc(frame_cmd), target_id, lun_id); return MFI_STAT_DEVICE_NOT_FOUND; } if (cdb_len > 16) { trace_megasas_scsi_invalid_cdb_len( - mfi_frame_desc[frame_cmd], 1, target_id, lun_id, cdb_len); + mfi_frame_desc(frame_cmd), 1, target_id, lun_id, cdb_len); megasas_write_sense(cmd, SENSE_CODE(INVALID_OPCODE)); cmd->frame->header.scsi_status = CHECK_CONDITION; s->event_count++; @@ -1781,7 +1790,7 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd, int frame_cmd) lun_id, cdb, cmd); if (!cmd->req) { trace_megasas_scsi_req_alloc_failed( - mfi_frame_desc[frame_cmd], target_id, lun_id); + mfi_frame_desc(frame_cmd), target_id, lun_id); megasas_write_sense(cmd, SENSE_CODE(NO_SENSE)); cmd->frame->header.scsi_status = BUSY; s->event_count++; @@ -1989,7 +1998,7 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr, { MegasasState *s = opaque; PCIDevice *pci_dev = PCI_DEVICE(s); - MegasasBaseClass *base_class = MEGASAS_DEVICE_GET_CLASS(s); + MegasasBaseClass *base_class = MEGASAS_GET_CLASS(s); uint32_t retval = 0; switch (addr) { @@ -2259,9 +2268,9 @@ static const VMStateDescription vmstate_megasas_gen1 = { VMSTATE_PCI_DEVICE(parent_obj, MegasasState), VMSTATE_MSIX(parent_obj, MegasasState), - VMSTATE_INT32(fw_state, MegasasState), - VMSTATE_INT32(intr_mask, MegasasState), - VMSTATE_INT32(doorbell, MegasasState), + VMSTATE_UINT32(fw_state, MegasasState), + VMSTATE_UINT32(intr_mask, MegasasState), + VMSTATE_UINT32(doorbell, MegasasState), VMSTATE_UINT64(reply_queue_pa, MegasasState), VMSTATE_UINT64(consumer_pa, MegasasState), VMSTATE_UINT64(producer_pa, MegasasState), @@ -2278,9 +2287,9 @@ static const VMStateDescription vmstate_megasas_gen2 = { VMSTATE_PCI_DEVICE(parent_obj, MegasasState), VMSTATE_MSIX(parent_obj, MegasasState), - VMSTATE_INT32(fw_state, MegasasState), - VMSTATE_INT32(intr_mask, MegasasState), - VMSTATE_INT32(doorbell, MegasasState), + VMSTATE_UINT32(fw_state, MegasasState), + VMSTATE_UINT32(intr_mask, MegasasState), + VMSTATE_UINT32(doorbell, MegasasState), VMSTATE_UINT64(reply_queue_pa, MegasasState), VMSTATE_UINT64(consumer_pa, MegasasState), VMSTATE_UINT64(producer_pa, MegasasState), @@ -2312,7 +2321,7 @@ static const struct SCSIBusInfo megasas_scsi_info = { static void megasas_scsi_realize(PCIDevice *dev, Error **errp) { MegasasState *s = MEGASAS(dev); - MegasasBaseClass *b = MEGASAS_DEVICE_GET_CLASS(s); + MegasasBaseClass *b = MEGASAS_GET_CLASS(s); uint8_t *pci_conf; int i, bar_type; Error *err = NULL; @@ -2496,7 +2505,7 @@ static void megasas_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc); - MegasasBaseClass *e = MEGASAS_DEVICE_CLASS(oc); + MegasasBaseClass *e = MEGASAS_CLASS(oc); const MegasasInfo *info = data; pc->realize = megasas_scsi_realize; diff --git a/hw/scsi/meson.build b/hw/scsi/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..923a34f344ccfc036d56b168f08fdc6b9febdc94 --- /dev/null +++ b/hw/scsi/meson.build @@ -0,0 +1,26 @@ +scsi_ss = ss.source_set() +scsi_ss.add(files( + 'emulation.c', + 'scsi-bus.c', + 'scsi-disk.c', + 'scsi-generic.c', +)) +scsi_ss.add(when: 'CONFIG_ESP', if_true: files('esp.c')) +scsi_ss.add(when: 'CONFIG_ESP_PCI', if_true: files('esp-pci.c')) +scsi_ss.add(when: 'CONFIG_LSI_SCSI_PCI', if_true: files('lsi53c895a.c')) +scsi_ss.add(when: 'CONFIG_MEGASAS_SCSI_PCI', if_true: files('megasas.c')) +scsi_ss.add(when: 'CONFIG_MPTSAS_SCSI_PCI', if_true: files('mptsas.c', 'mptconfig.c', 'mptendian.c')) +scsi_ss.add(when: 'CONFIG_VMW_PVSCSI_SCSI_PCI', if_true: files('vmw_pvscsi.c')) +softmmu_ss.add_all(when: 'CONFIG_SCSI', if_true: scsi_ss) + +specific_scsi_ss = ss.source_set() + +virtio_scsi_ss = ss.source_set() +virtio_scsi_ss.add(files('virtio-scsi.c', 'virtio-scsi-dataplane.c')) +virtio_scsi_ss.add(when: 'CONFIG_VHOST_SCSI', if_true: files('vhost-scsi-common.c', 'vhost-scsi.c')) +virtio_scsi_ss.add(when: 'CONFIG_VHOST_USER_SCSI', if_true: files('vhost-scsi-common.c', 'vhost-user-scsi.c')) +specific_scsi_ss.add_all(when: 'CONFIG_VIRTIO_SCSI', if_true: virtio_scsi_ss) + +specific_scsi_ss.add(when: 'CONFIG_SPAPR_VSCSI', if_true: files('spapr_vscsi.c')) + +specific_ss.add_all(when: 'CONFIG_SCSI', if_true: specific_scsi_ss) diff --git a/hw/scsi/mptconfig.c b/hw/scsi/mptconfig.c index 3b2a857b5c1460bfc928f82da9de5f1d0cc4b65e..19d01f39fae83db6b0b5cc112c21fd646c9bcb97 100644 --- a/hw/scsi/mptconfig.c +++ b/hw/scsi/mptconfig.c @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/scsi/mptendian.c b/hw/scsi/mptendian.c index 313f40edf9ae8435cf7759a4bd61458e3fdc9469..0d5abb4b6cc97c116e9671f2196a258c60ea5567 100644 --- a/hw/scsi/mptendian.c +++ b/hw/scsi/mptendian.c @@ -9,7 +9,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c index 14cbed84d070005f44c6d508805ad7788cb70ccd..f86616544bacf71da60270ad06ed88646437ccf2 100644 --- a/hw/scsi/mptsas.c +++ b/hw/scsi/mptsas.c @@ -11,7 +11,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -42,11 +42,6 @@ #define NAA_LOCALLY_ASSIGNED_ID 0x3ULL #define IEEE_COMPANY_LOCALLY_ASSIGNED 0x525400 -#define TYPE_MPTSAS1068 "mptsas1068" - -#define MPT_SAS(obj) \ - OBJECT_CHECK(MPTSASState, (obj), TYPE_MPTSAS1068) - #define MPTSAS1068_PRODUCT_ID \ (MPI_FW_HEADER_PID_FAMILY_1068_SAS | \ MPI_FW_HEADER_PID_PROD_INITIATOR_SCSI | \ diff --git a/hw/scsi/mptsas.h b/hw/scsi/mptsas.h index 0436a339116dc8320aca7557729ba6d3ec6385aa..b85ac1a5fcc7ad3ffc72923c734c175ed8a6651d 100644 --- a/hw/scsi/mptsas.h +++ b/hw/scsi/mptsas.h @@ -2,6 +2,7 @@ #define MPTSAS_H #include "mpi.h" +#include "qom/object.h" #define MPTSAS_NUM_PORTS 8 #define MPTSAS_MAX_FRAMES 2048 /* Firmware limit at 65535 */ @@ -11,9 +12,13 @@ #define MPTSAS_MAXIMUM_CHAIN_DEPTH 0x22 -typedef struct MPTSASState MPTSASState; typedef struct MPTSASRequest MPTSASRequest; +#define TYPE_MPTSAS1068 "mptsas1068" +typedef struct MPTSASState MPTSASState; +DECLARE_INSTANCE_CHECKER(MPTSASState, MPT_SAS, + TYPE_MPTSAS1068) + enum { DOORBELL_NONE, DOORBELL_WRITE, diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 2836f807a0476cad746a8bdfbf895caecd385827..b901e701f081ffc5637fac0cdedbb285d4b4eeaa 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -22,34 +22,67 @@ static void scsi_req_dequeue(SCSIRequest *req); static uint8_t *scsi_target_alloc_buf(SCSIRequest *req, size_t len); static void scsi_target_free_buf(SCSIRequest *req); -static Property scsi_props[] = { - DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0), - DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1), - DEFINE_PROP_UINT32("lun", SCSIDevice, lun, -1), - DEFINE_PROP_END_OF_LIST(), -}; +static int next_scsi_bus; -static void scsi_bus_class_init(ObjectClass *klass, void *data) +static SCSIDevice *do_scsi_device_find(SCSIBus *bus, + int channel, int id, int lun, + bool include_unrealized) { - BusClass *k = BUS_CLASS(klass); - HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); + BusChild *kid; + SCSIDevice *retval = NULL; - k->get_dev_path = scsibus_get_dev_path; - k->get_fw_dev_path = scsibus_get_fw_dev_path; - hc->unplug = qdev_simple_device_unplug_cb; + QTAILQ_FOREACH_RCU(kid, &bus->qbus.children, sibling) { + DeviceState *qdev = kid->child; + SCSIDevice *dev = SCSI_DEVICE(qdev); + + if (dev->channel == channel && dev->id == id) { + if (dev->lun == lun) { + retval = dev; + break; + } + + /* + * If we don't find exact match (channel/bus/lun), + * we will return the first device which matches channel/bus + */ + + if (!retval) { + retval = dev; + } + } + } + + /* + * This function might run on the IO thread and we might race against + * main thread hot-plugging the device. + * We assume that as soon as .realized is set to true we can let + * the user access the device. + */ + + if (retval && !include_unrealized && + !qatomic_load_acquire(&retval->qdev.realized)) { + retval = NULL; + } + + return retval; } -static const TypeInfo scsi_bus_info = { - .name = TYPE_SCSI_BUS, - .parent = TYPE_BUS, - .instance_size = sizeof(SCSIBus), - .class_init = scsi_bus_class_init, - .interfaces = (InterfaceInfo[]) { - { TYPE_HOTPLUG_HANDLER }, - { } +SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun) +{ + RCU_READ_LOCK_GUARD(); + return do_scsi_device_find(bus, channel, id, lun, false); +} + +SCSIDevice *scsi_device_get(SCSIBus *bus, int channel, int id, int lun) +{ + SCSIDevice *d; + RCU_READ_LOCK_GUARD(); + d = do_scsi_device_find(bus, channel, id, lun, false); + if (d) { + object_ref(d); } -}; -static int next_scsi_bus; + return d; +} static void scsi_device_realize(SCSIDevice *s, Error **errp) { @@ -107,7 +140,7 @@ void scsi_bus_new(SCSIBus *bus, size_t bus_size, DeviceState *host, qbus_create_inplace(bus, bus_size, TYPE_SCSI_BUS, host, bus_name); bus->busnr = next_scsi_bus++; bus->info = info; - qbus_set_bus_hotplug_handler(BUS(bus), &error_abort); + qbus_set_bus_hotplug_handler(BUS(bus)); } static void scsi_dma_restart_bh(void *opaque) @@ -160,35 +193,71 @@ static void scsi_dma_restart_cb(void *opaque, int running, RunState state) } } -static void scsi_qdev_realize(DeviceState *qdev, Error **errp) +static bool scsi_bus_is_address_free(SCSIBus *bus, + int channel, int target, int lun, + SCSIDevice **p_dev) { - SCSIDevice *dev = SCSI_DEVICE(qdev); - SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus); SCSIDevice *d; - Error *local_err = NULL; + + RCU_READ_LOCK_GUARD(); + d = do_scsi_device_find(bus, channel, target, lun, true); + if (d && d->lun == lun) { + if (p_dev) { + *p_dev = d; + } + return false; + } + if (p_dev) { + *p_dev = NULL; + } + return true; +} + +static bool scsi_bus_check_address(BusState *qbus, DeviceState *qdev, Error **errp) +{ + SCSIDevice *dev = SCSI_DEVICE(qdev); + SCSIBus *bus = SCSI_BUS(qbus); if (dev->channel > bus->info->max_channel) { error_setg(errp, "bad scsi channel id: %d", dev->channel); - return; + return false; } if (dev->id != -1 && dev->id > bus->info->max_target) { error_setg(errp, "bad scsi device id: %d", dev->id); - return; + return false; } if (dev->lun != -1 && dev->lun > bus->info->max_lun) { error_setg(errp, "bad scsi device lun: %d", dev->lun); - return; + return false; + } + + if (dev->id != -1 && dev->lun != -1) { + SCSIDevice *d; + if (!scsi_bus_is_address_free(bus, dev->channel, dev->id, dev->lun, &d)) { + error_setg(errp, "lun already used by '%s'", d->qdev.id); + return false; + } } + return true; +} + +static void scsi_qdev_realize(DeviceState *qdev, Error **errp) +{ + SCSIDevice *dev = SCSI_DEVICE(qdev); + SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus); + bool is_free; + Error *local_err = NULL; + if (dev->id == -1) { int id = -1; if (dev->lun == -1) { dev->lun = 0; } do { - d = scsi_device_find(bus, dev->channel, ++id, dev->lun); - } while (d && d->lun == dev->lun && id < bus->info->max_target); - if (d && d->lun == dev->lun) { + is_free = scsi_bus_is_address_free(bus, dev->channel, ++id, dev->lun, NULL); + } while (!is_free && id < bus->info->max_target); + if (!is_free) { error_setg(errp, "no free target"); return; } @@ -196,20 +265,13 @@ static void scsi_qdev_realize(DeviceState *qdev, Error **errp) } else if (dev->lun == -1) { int lun = -1; do { - d = scsi_device_find(bus, dev->channel, dev->id, ++lun); - } while (d && d->lun == lun && lun < bus->info->max_lun); - if (d && d->lun == lun) { + is_free = scsi_bus_is_address_free(bus, dev->channel, dev->id, ++lun, NULL); + } while (!is_free && lun < bus->info->max_lun); + if (!is_free) { error_setg(errp, "no free lun"); return; } dev->lun = lun; - } else { - d = scsi_device_find(bus, dev->channel, dev->id, dev->lun); - assert(d); - if (d->lun == dev->lun && dev != d) { - error_setg(errp, "lun already used by '%s'", d->qdev.id); - return; - } } QTAILQ_INIT(&dev->requests); @@ -248,7 +310,6 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk, const char *driver; char *name; DeviceState *dev; - Error *err = NULL; DriveInfo *dinfo; if (blk_is_sg(blk)) { @@ -261,31 +322,27 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk, driver = "scsi-hd"; } } - dev = qdev_create(&bus->qbus, driver); + dev = qdev_new(driver); name = g_strdup_printf("legacy[%d]", unit); object_property_add_child(OBJECT(bus), name, OBJECT(dev)); g_free(name); qdev_prop_set_uint32(dev, "scsi-id", unit); if (bootindex >= 0) { - object_property_set_int(OBJECT(dev), bootindex, "bootindex", + object_property_set_int(OBJECT(dev), "bootindex", bootindex, &error_abort); } - if (object_property_find(OBJECT(dev), "removable", NULL)) { + if (object_property_find(OBJECT(dev), "removable")) { qdev_prop_set_bit(dev, "removable", removable); } - if (serial && object_property_find(OBJECT(dev), "serial", NULL)) { + if (serial && object_property_find(OBJECT(dev), "serial")) { qdev_prop_set_string(dev, "serial", serial); } - qdev_prop_set_drive(dev, "drive", blk, &err); - if (err) { - error_propagate(errp, err); + if (!qdev_prop_set_drive_err(dev, "drive", blk, errp)) { object_unparent(OBJECT(dev)); return NULL; } - object_property_set_bool(OBJECT(dev), share_rw, "share-rw", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!object_property_set_bool(OBJECT(dev), "share-rw", share_rw, errp)) { object_unparent(OBJECT(dev)); return NULL; } @@ -293,9 +350,7 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk, qdev_prop_set_enum(dev, "rerror", rerror); qdev_prop_set_enum(dev, "werror", werror); - object_property_set_bool(OBJECT(dev), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); + if (!qdev_realize_and_unref(dev, &bus->qbus, errp)) { object_unparent(OBJECT(dev)); return NULL; } @@ -383,19 +438,23 @@ struct SCSITargetReq { static void store_lun(uint8_t *outbuf, int lun) { if (lun < 256) { + /* Simple logical unit addressing method*/ + outbuf[0] = 0; outbuf[1] = lun; - return; + } else { + /* Flat space addressing method */ + outbuf[0] = 0x40 | (lun >> 8); + outbuf[1] = (lun & 255); } - outbuf[1] = (lun & 255); - outbuf[0] = (lun >> 8) | 0x40; } static bool scsi_target_emulate_report_luns(SCSITargetReq *r) { BusChild *kid; - int i, len, n; int channel, id; - bool found_lun0; + uint8_t tmp[8] = {0}; + int len = 0; + GByteArray *buf; if (r->req.cmd.xfer < 16) { return false; @@ -403,42 +462,40 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r) if (r->req.cmd.buf[2] > 2) { return false; } + + /* reserve space for 63 LUNs*/ + buf = g_byte_array_sized_new(512); + channel = r->req.dev->channel; id = r->req.dev->id; - found_lun0 = false; - n = 0; - QTAILQ_FOREACH(kid, &r->req.bus->qbus.children, sibling) { - DeviceState *qdev = kid->child; - SCSIDevice *dev = SCSI_DEVICE(qdev); - if (dev->channel == channel && dev->id == id) { - if (dev->lun == 0) { - found_lun0 = true; - } - n += 8; - } - } - if (!found_lun0) { - n += 8; - } + /* add size (will be updated later to correct value */ + g_byte_array_append(buf, tmp, 8); + len += 8; - scsi_target_alloc_buf(&r->req, n + 8); + /* add LUN0 */ + g_byte_array_append(buf, tmp, 8); + len += 8; - len = MIN(n + 8, r->req.cmd.xfer & ~7); - memset(r->buf, 0, len); - stl_be_p(&r->buf[0], n); - i = found_lun0 ? 8 : 16; - QTAILQ_FOREACH(kid, &r->req.bus->qbus.children, sibling) { - DeviceState *qdev = kid->child; - SCSIDevice *dev = SCSI_DEVICE(qdev); + WITH_RCU_READ_LOCK_GUARD() { + QTAILQ_FOREACH_RCU(kid, &r->req.bus->qbus.children, sibling) { + DeviceState *qdev = kid->child; + SCSIDevice *dev = SCSI_DEVICE(qdev); - if (dev->channel == channel && dev->id == id) { - store_lun(&r->buf[i], dev->lun); - i += 8; + if (dev->channel == channel && dev->id == id && dev->lun != 0) { + store_lun(tmp, dev->lun); + g_byte_array_append(buf, tmp, 8); + len += 8; + } } } - assert(i == n + 8); - r->len = len; + + r->buf_len = len; + r->buf = g_byte_array_free(buf, FALSE); + r->len = MIN(len, r->req.cmd.xfer & ~7); + + /* store the LUN list length */ + stl_be_p(&r->buf[0], len - 8); return true; } @@ -1574,25 +1631,6 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev) qdev_fw_name(dev), d->id, d->lun); } -SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun) -{ - BusChild *kid; - SCSIDevice *target_dev = NULL; - - QTAILQ_FOREACH_REVERSE(kid, &bus->qbus.children, sibling) { - DeviceState *qdev = kid->child; - SCSIDevice *dev = SCSI_DEVICE(qdev); - - if (dev->channel == channel && dev->id == id) { - if (dev->lun == lun) { - return dev; - } - target_dev = dev; - } - } - return target_dev; -} - /* SCSI request list. For simplicity, pv points to the whole device */ static int put_scsi_requests(QEMUFile *f, void *pv, size_t size, @@ -1716,6 +1754,13 @@ const VMStateDescription vmstate_scsi_device = { } }; +static Property scsi_props[] = { + DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0), + DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1), + DEFINE_PROP_UINT32("lun", SCSIDevice, lun, -1), + DEFINE_PROP_END_OF_LIST(), +}; + static void scsi_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); @@ -1746,6 +1791,28 @@ static const TypeInfo scsi_device_type_info = { .instance_init = scsi_dev_instance_init, }; +static void scsi_bus_class_init(ObjectClass *klass, void *data) +{ + BusClass *k = BUS_CLASS(klass); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); + + k->get_dev_path = scsibus_get_dev_path; + k->get_fw_dev_path = scsibus_get_fw_dev_path; + k->check_address = scsi_bus_check_address; + hc->unplug = qdev_simple_device_unplug_cb; +} + +static const TypeInfo scsi_bus_info = { + .name = TYPE_SCSI_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(SCSIBus), + .class_init = scsi_bus_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + } +}; + static void scsi_register_types(void) { type_register_static(&scsi_bus_info); diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 387503e11be9bac80a3ce8c01d3923dc118805ce..90841ad79123a3a86547a70d6dd48b525a15b3f4 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -38,6 +38,7 @@ #include "sysemu/sysemu.h" #include "qemu/cutils.h" #include "trace.h" +#include "qom/object.h" #ifdef __linux #include @@ -54,24 +55,19 @@ #define TYPE_SCSI_DISK_BASE "scsi-disk-base" -#define SCSI_DISK_BASE(obj) \ - OBJECT_CHECK(SCSIDiskState, (obj), TYPE_SCSI_DISK_BASE) -#define SCSI_DISK_BASE_CLASS(klass) \ - OBJECT_CLASS_CHECK(SCSIDiskClass, (klass), TYPE_SCSI_DISK_BASE) -#define SCSI_DISK_BASE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SCSIDiskClass, (obj), TYPE_SCSI_DISK_BASE) +OBJECT_DECLARE_TYPE(SCSIDiskState, SCSIDiskClass, SCSI_DISK_BASE) -typedef struct SCSIDiskClass { +struct SCSIDiskClass { SCSIDeviceClass parent_class; DMAIOFunc *dma_readv; DMAIOFunc *dma_writev; bool (*need_fua_emulation)(SCSICommand *cmd); void (*update_sense)(SCSIRequest *r); -} SCSIDiskClass; +}; typedef struct SCSIDiskReq { SCSIRequest req; - /* Both sector and sector_count are in terms of qemu 512 byte blocks. */ + /* Both sector and sector_count are in terms of BDRV_SECTOR_SIZE bytes. */ uint64_t sector; uint32_t sector_count; uint32_t buflen; @@ -87,8 +83,7 @@ typedef struct SCSIDiskReq { #define SCSI_DISK_F_DPOFUA 1 #define SCSI_DISK_F_NO_REMOVABLE_DEVOPS 2 -typedef struct SCSIDiskState -{ +struct SCSIDiskState { SCSIDevice qdev; uint32_t features; bool media_changed; @@ -113,7 +108,7 @@ typedef struct SCSIDiskState * 0xffff - reserved */ uint16_t rotation_rate; -} SCSIDiskState; +}; static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed); @@ -141,7 +136,7 @@ static void scsi_init_iovec(SCSIDiskReq *r, size_t size) r->buflen = size; r->iov.iov_base = blk_blockalign(s->qdev.conf.blk, r->buflen); } - r->iov.iov_len = MIN(r->sector_count * 512, r->buflen); + r->iov.iov_len = MIN(r->sector_count * BDRV_SECTOR_SIZE, r->buflen); qemu_iovec_init_external(&r->qiov, &r->iov, 1); } @@ -311,7 +306,7 @@ static void scsi_read_complete_noio(SCSIDiskReq *r, int ret) goto done; } - n = r->qiov.size / 512; + n = r->qiov.size / BDRV_SECTOR_SIZE; r->sector += n; r->sector_count -= n; scsi_req_data(&r->req, r->qiov.size); @@ -466,6 +461,25 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed) } error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense)); break; +#ifdef CONFIG_LINUX + /* These errno mapping are specific to Linux. For more information: + * - scsi_decide_disposition in drivers/scsi/scsi_error.c + * - scsi_result_to_blk_status in drivers/scsi/scsi_lib.c + * - blk_errors[] in block/blk-core.c + */ + case EBADE: + /* DID_NEXUS_FAILURE -> BLK_STS_NEXUS. */ + scsi_req_complete(&r->req, RESERVATION_CONFLICT); + break; + case ENODATA: + /* DID_MEDIUM_ERROR -> BLK_STS_MEDIUM. */ + scsi_check_condition(r, SENSE_CODE(READ_ERROR)); + break; + case EREMOTEIO: + /* DID_TARGET_FAILURE -> BLK_STS_TARGET. */ + scsi_req_complete(&r->req, HARDWARE_ERROR); + break; +#endif case ENOMEDIUM: scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); break; @@ -505,7 +519,7 @@ static void scsi_write_complete_noio(SCSIDiskReq *r, int ret) goto done; } - n = r->qiov.size / 512; + n = r->qiov.size / BDRV_SECTOR_SIZE; r->sector += n; r->sector_count -= n; if (r->sector_count == 0) { @@ -1284,7 +1298,7 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf) } else { /* MODE_SENSE_10 */ outbuf[7] = 8; /* Block descriptor length */ } - nb_sectors /= (s->qdev.blocksize / 512); + nb_sectors /= (s->qdev.blocksize / BDRV_SECTOR_SIZE); if (nb_sectors > 0xffffff) { nb_sectors = 0; } @@ -1342,7 +1356,7 @@ static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf) start_track = req->cmd.buf[6]; blk_get_geometry(s->qdev.conf.blk, &nb_sectors); trace_scsi_disk_emulate_read_toc(start_track, format, msf >> 1); - nb_sectors /= s->qdev.blocksize / 512; + nb_sectors /= s->qdev.blocksize / BDRV_SECTOR_SIZE; switch (format) { case 0: toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track); @@ -1738,9 +1752,10 @@ static void scsi_write_same_complete(void *opaque, int ret) block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct); - data->nb_sectors -= data->iov.iov_len / 512; - data->sector += data->iov.iov_len / 512; - data->iov.iov_len = MIN(data->nb_sectors * 512, data->iov.iov_len); + data->nb_sectors -= data->iov.iov_len / BDRV_SECTOR_SIZE; + data->sector += data->iov.iov_len / BDRV_SECTOR_SIZE; + data->iov.iov_len = MIN(data->nb_sectors * BDRV_SECTOR_SIZE, + data->iov.iov_len); if (data->iov.iov_len) { block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, data->iov.iov_len, BLOCK_ACCT_WRITE); @@ -1805,9 +1820,10 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf) data = g_new0(WriteSameCBData, 1); data->r = r; - data->sector = r->req.cmd.lba * (s->qdev.blocksize / 512); - data->nb_sectors = nb_sectors * (s->qdev.blocksize / 512); - data->iov.iov_len = MIN(data->nb_sectors * 512, SCSI_WRITE_SAME_MAX); + data->sector = r->req.cmd.lba * (s->qdev.blocksize / BDRV_SECTOR_SIZE); + data->nb_sectors = nb_sectors * (s->qdev.blocksize / BDRV_SECTOR_SIZE); + data->iov.iov_len = MIN(data->nb_sectors * BDRV_SECTOR_SIZE, + SCSI_WRITE_SAME_MAX); data->iov.iov_base = buf = blk_blockalign(s->qdev.conf.blk, data->iov.iov_len); qemu_iovec_init_external(&data->qiov, &data->iov, 1); @@ -1980,7 +1996,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) if ((req->cmd.buf[8] & 1) == 0 && req->cmd.lba) { goto illegal_request; } - nb_sectors /= s->qdev.blocksize / 512; + nb_sectors /= s->qdev.blocksize / BDRV_SECTOR_SIZE; /* Returned value is the address of the last sector. */ nb_sectors--; /* Remember the new size for read/write sanity checking. */ @@ -2049,7 +2065,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) if ((req->cmd.buf[14] & 1) == 0 && req->cmd.lba) { goto illegal_request; } - nb_sectors /= s->qdev.blocksize / 512; + nb_sectors /= s->qdev.blocksize / BDRV_SECTOR_SIZE; /* Returned value is the address of the last sector. */ nb_sectors--; /* Remember the new size for read/write sanity checking. */ @@ -2180,8 +2196,8 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) if (!check_lba_range(s, r->req.cmd.lba, len)) { goto illegal_lba; } - r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512); - r->sector_count = len * (s->qdev.blocksize / 512); + r->sector = r->req.cmd.lba * (s->qdev.blocksize / BDRV_SECTOR_SIZE); + r->sector_count = len * (s->qdev.blocksize / BDRV_SECTOR_SIZE); break; case WRITE_6: case WRITE_10: @@ -2211,8 +2227,8 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) if (!check_lba_range(s, r->req.cmd.lba, len)) { goto illegal_lba; } - r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512); - r->sector_count = len * (s->qdev.blocksize / 512); + r->sector = r->req.cmd.lba * (s->qdev.blocksize / BDRV_SECTOR_SIZE); + r->sector_count = len * (s->qdev.blocksize / BDRV_SECTOR_SIZE); break; default: abort(); @@ -2229,9 +2245,9 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) } assert(r->iov.iov_len == 0); if (r->req.cmd.mode == SCSI_XFER_TO_DEV) { - return -r->sector_count * 512; + return -r->sector_count * BDRV_SECTOR_SIZE; } else { - return r->sector_count * 512; + return r->sector_count * BDRV_SECTOR_SIZE; } } @@ -2243,7 +2259,7 @@ static void scsi_disk_reset(DeviceState *dev) scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET)); blk_get_geometry(s->qdev.conf.blk, &nb_sectors); - nb_sectors /= s->qdev.blocksize / 512; + nb_sectors /= s->qdev.blocksize / BDRV_SECTOR_SIZE; if (nb_sectors) { nb_sectors--; } @@ -2346,12 +2362,7 @@ static void scsi_realize(SCSIDevice *dev, Error **errp) return; } - blkconf_blocksizes(&s->qdev.conf); - - if (s->qdev.conf.logical_block_size > - s->qdev.conf.physical_block_size) { - error_setg(errp, - "logical_block_size > physical_block_size not supported"); + if (!blkconf_blocksizes(&s->qdev.conf, errp)) { return; } @@ -2436,7 +2447,9 @@ static void scsi_hd_realize(SCSIDevice *dev, Error **errp) if (s->qdev.conf.blk) { ctx = blk_get_aio_context(s->qdev.conf.blk); aio_context_acquire(ctx); - blkconf_blocksizes(&s->qdev.conf); + if (!blkconf_blocksizes(&s->qdev.conf, errp)) { + goto out; + } } s->qdev.blocksize = s->qdev.conf.logical_block_size; s->qdev.type = TYPE_DISK; @@ -2444,6 +2457,7 @@ static void scsi_hd_realize(SCSIDevice *dev, Error **errp) s->product = g_strdup("QEMU HARDDISK"); } scsi_realize(&s->qdev, errp); +out: if (ctx) { aio_context_release(ctx); } diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 86ed0a38227330bfac3ef3cca5c833bf2811970c..2cb23ca8913c91fc06f497af21beccca495b9a67 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -162,7 +162,8 @@ static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s) } } - if (s->type == TYPE_DISK && (r->req.cmd.buf[1] & 0x01)) { + if ((s->type == TYPE_DISK || s->type == TYPE_ZBC) && + (r->req.cmd.buf[1] & 0x01)) { page = r->req.cmd.buf[2]; if (page == 0xb0) { uint32_t max_transfer = @@ -299,10 +300,11 @@ static void scsi_read_complete(void * opaque, int ret) } blk_set_guest_block_size(s->conf.blk, s->blocksize); - /* Patch MODE SENSE device specific parameters if the BDS is opened + /* + * Patch MODE SENSE device specific parameters if the BDS is opened * readonly. */ - if ((s->type == TYPE_DISK || s->type == TYPE_TAPE) && + if ((s->type == TYPE_DISK || s->type == TYPE_TAPE || s->type == TYPE_ZBC) && blk_is_read_only(s->conf.blk) && (r->req.cmd.buf[0] == MODE_SENSE || r->req.cmd.buf[0] == MODE_SENSE_10) && @@ -617,7 +619,7 @@ static void scsi_generic_read_device_identification(SCSIDevice *s) void scsi_generic_read_device_inquiry(SCSIDevice *s) { scsi_generic_read_device_identification(s); - if (s->type == TYPE_DISK) { + if (s->type == TYPE_DISK || s->type == TYPE_ZBC) { scsi_generic_set_vpd_bl_emulation(s); } else { s->needs_vpd_bl_emulation = false; diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c index 923488beb221e10fce214a63803aa7738e08e953..4aa0224c47f077d271c084c7defcfafb3cbce0dc 100644 --- a/hw/scsi/spapr_vscsi.c +++ b/hw/scsi/spapr_vscsi.c @@ -46,6 +46,7 @@ #include "trace.h" #include +#include "qom/object.h" /* * Virtual SCSI device @@ -90,14 +91,13 @@ typedef struct vscsi_req { } vscsi_req; #define TYPE_VIO_SPAPR_VSCSI_DEVICE "spapr-vscsi" -#define VIO_SPAPR_VSCSI_DEVICE(obj) \ - OBJECT_CHECK(VSCSIState, (obj), TYPE_VIO_SPAPR_VSCSI_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(VSCSIState, VIO_SPAPR_VSCSI_DEVICE) -typedef struct { +struct VSCSIState { SpaprVioDevice vdev; SCSIBus bus; vscsi_req reqs[VSCSI_REQ_LIMIT]; -} VSCSIState; +}; static union viosrp_iu *req_iu(vscsi_req *req) { @@ -1219,15 +1219,18 @@ static void spapr_vscsi_realize(SpaprVioDevice *dev, Error **errp) scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), &vscsi_scsi_info, NULL); + + /* ibmvscsi SCSI bus does not allow hotplug. */ + qbus_set_hotplug_handler(BUS(&s->bus), NULL); } void spapr_vscsi_create(SpaprVioBus *bus) { DeviceState *dev; - dev = qdev_create(&bus->bus, "spapr-vscsi"); + dev = qdev_new("spapr-vscsi"); - qdev_init_nofail(dev); + qdev_realize_and_unref(dev, &bus->bus, &error_fatal); scsi_bus_legacy_handle_cmdline(&VIO_SPAPR_VSCSI_DEVICE(dev)->bus); } diff --git a/hw/scsi/trace.h b/hw/scsi/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..4ce26735827c473f44531863ada7ac59227e4ddb --- /dev/null +++ b/hw/scsi/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_scsi.h" diff --git a/hw/scsi/vhost-scsi-common.c b/hw/scsi/vhost-scsi-common.c index 8ec49d7fef2ff3608d37dae78991685a0eaa0e13..767f827e55beb923e96b903900aaa1c9e4e9c266 100644 --- a/hw/scsi/vhost-scsi-common.c +++ b/hw/scsi/vhost-scsi-common.c @@ -32,6 +32,8 @@ int vhost_scsi_common_start(VHostSCSICommon *vsc) BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); + VirtIOSCSICommon *vs = (VirtIOSCSICommon *)vsc; + if (!k->set_guest_notifiers) { error_report("binding does not support guest notifiers"); return -ENOSYS; @@ -49,6 +51,23 @@ int vhost_scsi_common_start(VHostSCSICommon *vsc) } vsc->dev.acked_features = vdev->guest_features; + + assert(vsc->inflight == NULL); + vsc->inflight = g_new0(struct vhost_inflight, 1); + ret = vhost_dev_get_inflight(&vsc->dev, + vs->conf.virtqueue_size, + vsc->inflight); + if (ret < 0) { + error_report("Error get inflight: %d", -ret); + goto err_guest_notifiers; + } + + ret = vhost_dev_set_inflight(&vsc->dev, vsc->inflight); + if (ret < 0) { + error_report("Error set inflight: %d", -ret); + goto err_guest_notifiers; + } + ret = vhost_dev_start(&vsc->dev, vdev); if (ret < 0) { error_report("Error start vhost dev"); @@ -66,6 +85,9 @@ int vhost_scsi_common_start(VHostSCSICommon *vsc) return ret; err_guest_notifiers: + g_free(vsc->inflight); + vsc->inflight = NULL; + k->set_guest_notifiers(qbus->parent, vsc->dev.nvqs, false); err_host_notifiers: vhost_dev_disable_notifiers(&vsc->dev, vdev); @@ -89,6 +111,11 @@ void vhost_scsi_common_stop(VHostSCSICommon *vsc) } assert(ret >= 0); + if (vsc->inflight) { + vhost_dev_free_inflight(vsc->inflight); + vsc->inflight = NULL; + } + vhost_dev_disable_notifiers(&vsc->dev, vdev); } diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index c1b012aea40e2c146e4f68313ec5454fc17fe535..4d70fa036bbe5bcb0ad16aae5833292b7a5889b5 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -177,7 +177,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) } if (vs->conf.vhostfd) { - vhostfd = monitor_fd_param(cur_mon, vs->conf.vhostfd, errp); + vhostfd = monitor_fd_param(monitor_cur(), vs->conf.vhostfd, errp); if (vhostfd == -1) { error_prepend(errp, "vhost-scsi: unable to parse vhostfd: "); return; @@ -207,9 +207,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) "When external environment supports it (Orchestrator migrates " "target SCSI device state or use shared storage over network), " "set 'migratable' property to true to enable migration."); - migrate_add_blocker(vsc->migration_blocker, &err); - if (err) { - error_propagate(errp, err); + if (migrate_add_blocker(vsc->migration_blocker, errp) < 0) { error_free(vsc->migration_blocker); goto free_virtio; } @@ -272,7 +270,8 @@ static Property vhost_scsi_properties[] = { DEFINE_PROP_STRING("vhostfd", VirtIOSCSICommon, conf.vhostfd), DEFINE_PROP_STRING("wwpn", VirtIOSCSICommon, conf.wwpn), DEFINE_PROP_UINT32("boot_tpgt", VirtIOSCSICommon, conf.boot_tpgt, 0), - DEFINE_PROP_UINT32("num_queues", VirtIOSCSICommon, conf.num_queues, 1), + DEFINE_PROP_UINT32("num_queues", VirtIOSCSICommon, conf.num_queues, + VIRTIO_SCSI_AUTO_NUM_QUEUES), DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSICommon, conf.virtqueue_size, 128), DEFINE_PROP_BOOL("seg_max_adjust", VirtIOSCSICommon, conf.seg_max_adjust, diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c index cbb5d9759933b0ceed8a894fafa34efd4c32fe17..7c0631656cc0399038407907162f8ec9b20f98e2 100644 --- a/hw/scsi/vhost-user-scsi.c +++ b/hw/scsi/vhost-user-scsi.c @@ -18,7 +18,6 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/error-report.h" -#include "qom/object.h" #include "hw/fw-path-provider.h" #include "hw/qdev-core.h" #include "hw/qdev-properties.h" @@ -115,7 +114,7 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp) goto free_virtio; } - vsc->dev.nvqs = 2 + vs->conf.num_queues; + vsc->dev.nvqs = VIRTIO_SCSI_VQ_NUM_FIXED + vs->conf.num_queues; vsc->dev.vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs); vsc->dev.vq_index = 0; vsc->dev.backend_features = 0; @@ -163,7 +162,8 @@ static void vhost_user_scsi_unrealize(DeviceState *dev) static Property vhost_user_scsi_properties[] = { DEFINE_PROP_CHR("chardev", VirtIOSCSICommon, conf.chardev), DEFINE_PROP_UINT32("boot_tpgt", VirtIOSCSICommon, conf.boot_tpgt, 0), - DEFINE_PROP_UINT32("num_queues", VirtIOSCSICommon, conf.num_queues, 1), + DEFINE_PROP_UINT32("num_queues", VirtIOSCSICommon, conf.num_queues, + VIRTIO_SCSI_AUTO_NUM_QUEUES), DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSICommon, conf.virtqueue_size, 128), DEFINE_PROP_UINT32("max_sectors", VirtIOSCSICommon, conf.max_sectors, diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 9b72094a61f2c9601f0e87b42ccaba12dfbc6c9f..3db9a8aae99362a4621a42e3fceb71820e61d196 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -33,7 +33,7 @@ static inline int virtio_scsi_get_lun(uint8_t *lun) return ((lun[2] << 8) | lun[3]) & 0x3FFF; } -static inline SCSIDevice *virtio_scsi_device_find(VirtIOSCSI *s, uint8_t *lun) +static inline SCSIDevice *virtio_scsi_device_get(VirtIOSCSI *s, uint8_t *lun) { if (lun[0] != 1) { return NULL; @@ -41,7 +41,7 @@ static inline SCSIDevice *virtio_scsi_device_find(VirtIOSCSI *s, uint8_t *lun) if (lun[2] != 0 && !(lun[2] >= 0x40 && lun[2] < 0x80)) { return NULL; } - return scsi_device_find(&s->bus, 0, lun[1], virtio_scsi_get_lun(lun)); + return scsi_device_get(&s->bus, 0, lun[1], virtio_scsi_get_lun(lun)); } void virtio_scsi_init_req(VirtIOSCSI *s, VirtQueue *vq, VirtIOSCSIReq *req) @@ -191,7 +191,7 @@ static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq) VirtIOSCSIReq *req = sreq->hba_private; VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(req->dev); VirtIODevice *vdev = VIRTIO_DEVICE(req->dev); - uint32_t n = virtio_get_queue_index(req->vq) - 2; + uint32_t n = virtio_get_queue_index(req->vq) - VIRTIO_SCSI_VQ_NUM_FIXED; assert(n < vs->conf.num_queues); qemu_put_be32s(f, &n); @@ -256,7 +256,7 @@ static inline void virtio_scsi_ctx_check(VirtIOSCSI *s, SCSIDevice *d) * case of async cancellation. */ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req) { - SCSIDevice *d = virtio_scsi_device_find(s, req->req.tmf.lun); + SCSIDevice *d = virtio_scsi_device_get(s, req->req.tmf.lun); SCSIRequest *r, *next; BusChild *kid; int target; @@ -367,12 +367,16 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req) case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET: target = req->req.tmf.lun[1]; s->resetting++; - QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) { - d = SCSI_DEVICE(kid->child); - if (d->channel == 0 && d->id == target) { - qdev_reset_all(&d->qdev); - } + + rcu_read_lock(); + QTAILQ_FOREACH_RCU(kid, &s->bus.qbus.children, sibling) { + SCSIDevice *d1 = SCSI_DEVICE(kid->child); + if (d1->channel == 0 && d1->id == target) { + qdev_reset_all(&d1->qdev); + } } + rcu_read_unlock(); + s->resetting--; break; @@ -382,14 +386,17 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req) break; } + object_unref(OBJECT(d)); return ret; incorrect_lun: req->resp.tmf.response = VIRTIO_SCSI_S_INCORRECT_LUN; + object_unref(OBJECT(d)); return ret; fail: req->resp.tmf.response = VIRTIO_SCSI_S_BAD_TARGET; + object_unref(OBJECT(d)); return ret; } @@ -560,7 +567,7 @@ static int virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req) } } - d = virtio_scsi_device_find(s, req->req.cmd.lun); + d = virtio_scsi_device_get(s, req->req.cmd.lun); if (!d) { req->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET; virtio_scsi_complete_cmd_req(req); @@ -576,10 +583,12 @@ static int virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req) req->sreq->cmd.xfer > req->qsgl.size)) { req->resp.cmd.response = VIRTIO_SCSI_S_OVERRUN; virtio_scsi_complete_cmd_req(req); + object_unref(OBJECT(d)); return -ENOBUFS; } scsi_req_ref(req->sreq); blk_io_plug(d->conf.blk); + object_unref(OBJECT(d)); return 0; } @@ -891,11 +900,15 @@ void virtio_scsi_common_realize(DeviceState *dev, virtio_init(vdev, "virtio-scsi", VIRTIO_ID_SCSI, sizeof(VirtIOSCSIConfig)); + if (s->conf.num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) { + s->conf.num_queues = 1; + } if (s->conf.num_queues == 0 || - s->conf.num_queues > VIRTIO_QUEUE_MAX - 2) { + s->conf.num_queues > VIRTIO_QUEUE_MAX - VIRTIO_SCSI_VQ_NUM_FIXED) { error_setg(errp, "Invalid number of queues (= %" PRIu32 "), " "must be a positive integer less than %d.", - s->conf.num_queues, VIRTIO_QUEUE_MAX - 2); + s->conf.num_queues, + VIRTIO_QUEUE_MAX - VIRTIO_SCSI_VQ_NUM_FIXED); virtio_cleanup(vdev); return; } @@ -934,7 +947,7 @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp) scsi_bus_new(&s->bus, sizeof(s->bus), dev, &virtio_scsi_scsi_info, vdev->bus_name); /* override default SCSI bus hotplug-handler, with virtio-scsi's one */ - qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(dev), &error_abort); + qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(dev)); virtio_scsi_dataplane_setup(s, errp); } @@ -958,12 +971,13 @@ static void virtio_scsi_device_unrealize(DeviceState *dev) { VirtIOSCSI *s = VIRTIO_SCSI(dev); - qbus_set_hotplug_handler(BUS(&s->bus), NULL, &error_abort); + qbus_set_hotplug_handler(BUS(&s->bus), NULL); virtio_scsi_common_unrealize(dev); } static Property virtio_scsi_properties[] = { - DEFINE_PROP_UINT32("num_queues", VirtIOSCSI, parent_obj.conf.num_queues, 1), + DEFINE_PROP_UINT32("num_queues", VirtIOSCSI, parent_obj.conf.num_queues, + VIRTIO_SCSI_AUTO_NUM_QUEUES), DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSI, parent_obj.conf.virtqueue_size, 256), DEFINE_PROP_BOOL("seg_max_adjust", VirtIOSCSI, diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c index ec5bf9ea34af57c8c6b9f53fd8801c7cea6ecafc..a63d25de48b887414678e15e7f1ebb76903023c1 100644 --- a/hw/scsi/vmw_pvscsi.c +++ b/hw/scsi/vmw_pvscsi.c @@ -36,6 +36,7 @@ #include "hw/qdev-properties.h" #include "vmw_pvscsi.h" #include "trace.h" +#include "qom/object.h" #define PVSCSI_USE_64BIT (true) @@ -56,18 +57,14 @@ (stl_le_pci_dma(&container_of(m, PVSCSIState, rings)->parent_obj, \ (m)->rs_pa + offsetof(struct PVSCSIRingsState, field), val)) -typedef struct PVSCSIClass { +struct PVSCSIClass { PCIDeviceClass parent_class; DeviceRealize parent_dc_realize; -} PVSCSIClass; +}; #define TYPE_PVSCSI "pvscsi" -#define PVSCSI(obj) OBJECT_CHECK(PVSCSIState, (obj), TYPE_PVSCSI) +OBJECT_DECLARE_TYPE(PVSCSIState, PVSCSIClass, PVSCSI) -#define PVSCSI_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(PVSCSIClass, (klass), TYPE_PVSCSI) -#define PVSCSI_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PVSCSIClass, (obj), TYPE_PVSCSI) /* Compatibility flags for migration */ #define PVSCSI_COMPAT_OLD_PCI_CONFIGURATION_BIT 0 @@ -104,7 +101,7 @@ typedef struct PVSCSISGState { typedef QTAILQ_HEAD(, PVSCSIRequest) PVSCSIRequestList; -typedef struct { +struct PVSCSIState { PCIDevice parent_obj; MemoryRegion io_space; SCSIBus bus; @@ -132,7 +129,7 @@ typedef struct { uint32_t resetting; /* Reset in progress */ uint32_t compat_flags; -} PVSCSIState; +}; typedef struct PVSCSIRequest { SCSIRequest *sreq; @@ -1147,7 +1144,7 @@ pvscsi_realizefn(PCIDevice *pci_dev, Error **errp) scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(pci_dev), &pvscsi_scsi_info, NULL); /* override default SCSI bus hotplug-handler, with pvscsi's one */ - qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(s), &error_abort); + qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(s)); pvscsi_reset_state(s); } @@ -1265,7 +1262,7 @@ static Property pvscsi_properties[] = { static void pvscsi_realize(DeviceState *qdev, Error **errp) { - PVSCSIClass *pvs_c = PVSCSI_DEVICE_GET_CLASS(qdev); + PVSCSIClass *pvs_c = PVSCSI_GET_CLASS(qdev); PCIDevice *pci_dev = PCI_DEVICE(qdev); PVSCSIState *s = PVSCSI(qdev); @@ -1280,7 +1277,7 @@ static void pvscsi_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - PVSCSIClass *pvs_k = PVSCSI_DEVICE_CLASS(klass); + PVSCSIClass *pvs_k = PVSCSI_CLASS(klass); HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); k->realize = pvscsi_realizefn; diff --git a/hw/sd/Kconfig b/hw/sd/Kconfig index c5e1e5581c574cfab7ae8662b2c6edcbf836253f..633b9afec915b0dd744deae818103c475a704d4a 100644 --- a/hw/sd/Kconfig +++ b/hw/sd/Kconfig @@ -19,3 +19,7 @@ config SDHCI_PCI default y if PCI_DEVICES depends on PCI select SDHCI + +config CADENCE_SDHCI + bool + select SDHCI diff --git a/hw/sd/Makefile.objs b/hw/sd/Makefile.objs deleted file mode 100644 index 0d1df1721ca950ae87e5d00d1ffde215e0e8fc28..0000000000000000000000000000000000000000 --- a/hw/sd/Makefile.objs +++ /dev/null @@ -1,12 +0,0 @@ -common-obj-$(CONFIG_PL181) += pl181.o -common-obj-$(CONFIG_SSI_SD) += ssi-sd.o -common-obj-$(CONFIG_SD) += sd.o core.o sdmmc-internal.o -common-obj-$(CONFIG_SDHCI) += sdhci.o -common-obj-$(CONFIG_SDHCI_PCI) += sdhci-pci.o - -common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-sdhost.o -common-obj-$(CONFIG_MILKYMIST) += milkymist-memcard.o -common-obj-$(CONFIG_OMAP) += omap_mmc.o -common-obj-$(CONFIG_PXA2XX) += pxa2xx_mmci.o -common-obj-$(CONFIG_RASPI) += bcm2835_sdhost.o -common-obj-$(CONFIG_ASPEED_SOC) += aspeed_sdhci.o diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c index f404e1fdb45ad411204a8741a4de8cb92869fa29..bea6d97ef8767e113e70896ebc53c597b0a5eb04 100644 --- a/hw/sd/allwinner-sdhost.c +++ b/hw/sd/allwinner-sdhost.c @@ -21,15 +21,20 @@ #include "qemu/log.h" #include "qemu/module.h" #include "qemu/units.h" +#include "qapi/error.h" #include "sysemu/blockdev.h" +#include "sysemu/dma.h" +#include "hw/qdev-properties.h" #include "hw/irq.h" #include "hw/sd/allwinner-sdhost.h" #include "migration/vmstate.h" #include "trace.h" +#include "qom/object.h" #define TYPE_AW_SDHOST_BUS "allwinner-sdhost-bus" -#define AW_SDHOST_BUS(obj) \ - OBJECT_CHECK(SDBus, (obj), TYPE_AW_SDHOST_BUS) +/* This is reusing the SDBus typedef from SD_BUS */ +DECLARE_INSTANCE_CHECKER(SDBus, AW_SDHOST_BUS, + TYPE_AW_SDHOST_BUS) /* SD Host register offsets */ enum { @@ -306,7 +311,7 @@ static uint32_t allwinner_sdhost_process_desc(AwSdHostState *s, uint8_t buf[1024]; /* Read descriptor */ - cpu_physical_memory_read(desc_addr, desc, sizeof(*desc)); + dma_memory_read(&s->dma_as, desc_addr, desc, sizeof(*desc)); if (desc->size == 0) { desc->size = klass->max_desc_size; } else if (desc->size > klass->max_desc_size) { @@ -331,27 +336,24 @@ static uint32_t allwinner_sdhost_process_desc(AwSdHostState *s, /* Write to SD bus */ if (is_write) { - cpu_physical_memory_read((desc->addr & DESC_SIZE_MASK) + num_done, - buf, buf_bytes); - - for (uint32_t i = 0; i < buf_bytes; i++) { - sdbus_write_data(&s->sdbus, buf[i]); - } + dma_memory_read(&s->dma_as, + (desc->addr & DESC_SIZE_MASK) + num_done, + buf, buf_bytes); + sdbus_write_data(&s->sdbus, buf, buf_bytes); /* Read from SD bus */ } else { - for (uint32_t i = 0; i < buf_bytes; i++) { - buf[i] = sdbus_read_data(&s->sdbus); - } - cpu_physical_memory_write((desc->addr & DESC_SIZE_MASK) + num_done, - buf, buf_bytes); + sdbus_read_data(&s->sdbus, buf, buf_bytes); + dma_memory_write(&s->dma_as, + (desc->addr & DESC_SIZE_MASK) + num_done, + buf, buf_bytes); } num_done += buf_bytes; } /* Clear hold flag and flush descriptor */ desc->status &= ~DESC_STATUS_HOLD; - cpu_physical_memory_write(desc_addr, desc, sizeof(*desc)); + dma_memory_write(&s->dma_as, desc_addr, desc, sizeof(*desc)); return num_done; } @@ -521,10 +523,8 @@ static uint64_t allwinner_sdhost_read(void *opaque, hwaddr offset, break; case REG_SD_FIFO: /* Read/Write FIFO */ if (sdbus_data_ready(&s->sdbus)) { - res = sdbus_read_data(&s->sdbus); - res |= sdbus_read_data(&s->sdbus) << 8; - res |= sdbus_read_data(&s->sdbus) << 16; - res |= sdbus_read_data(&s->sdbus) << 24; + sdbus_read_data(&s->sdbus, &res, sizeof(uint32_t)); + le32_to_cpus(&res); allwinner_sdhost_update_transfer_cnt(s, sizeof(uint32_t)); allwinner_sdhost_auto_stop(s); allwinner_sdhost_update_irq(s); @@ -548,6 +548,7 @@ static void allwinner_sdhost_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { AwSdHostState *s = AW_SDHOST(opaque); + uint32_t u32; trace_allwinner_sdhost_write(offset, value, size); @@ -654,11 +655,9 @@ static void allwinner_sdhost_write(void *opaque, hwaddr offset, s->startbit_detect = value; break; case REG_SD_FIFO: /* Read/Write FIFO */ - sdbus_write_data(&s->sdbus, value & 0xff); - sdbus_write_data(&s->sdbus, (value >> 8) & 0xff); - sdbus_write_data(&s->sdbus, (value >> 16) & 0xff); - sdbus_write_data(&s->sdbus, (value >> 24) & 0xff); - allwinner_sdhost_update_transfer_cnt(s, sizeof(uint32_t)); + u32 = cpu_to_le32(value); + sdbus_write_data(&s->sdbus, &u32, sizeof(u32)); + allwinner_sdhost_update_transfer_cnt(s, sizeof(u32)); allwinner_sdhost_auto_stop(s); allwinner_sdhost_update_irq(s); break; @@ -729,6 +728,12 @@ static const VMStateDescription vmstate_allwinner_sdhost = { } }; +static Property allwinner_sdhost_properties[] = { + DEFINE_PROP_LINK("dma-memory", AwSdHostState, dma_mr, + TYPE_MEMORY_REGION, MemoryRegion *), + DEFINE_PROP_END_OF_LIST(), +}; + static void allwinner_sdhost_init(Object *obj) { AwSdHostState *s = AW_SDHOST(obj); @@ -742,6 +747,18 @@ static void allwinner_sdhost_init(Object *obj) sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq); } +static void allwinner_sdhost_realize(DeviceState *dev, Error **errp) +{ + AwSdHostState *s = AW_SDHOST(dev); + + if (!s->dma_mr) { + error_setg(errp, TYPE_AW_SDHOST " 'dma-memory' link not set"); + return; + } + + address_space_init(&s->dma_as, s->dma_mr, "sdhost-dma"); +} + static void allwinner_sdhost_reset(DeviceState *dev) { AwSdHostState *s = AW_SDHOST(dev); @@ -800,6 +817,8 @@ static void allwinner_sdhost_class_init(ObjectClass *klass, void *data) dc->reset = allwinner_sdhost_reset; dc->vmsd = &vmstate_allwinner_sdhost; + dc->realize = allwinner_sdhost_realize; + device_class_set_props(dc, allwinner_sdhost_properties); } static void allwinner_sdhost_sun4i_class_init(ObjectClass *klass, void *data) diff --git a/hw/sd/aspeed_sdhci.c b/hw/sd/aspeed_sdhci.c index 6a039a1d2f1f8b3cb0498810c7b979c7bcaf13fe..4f24b7d2f942b2798e83816f4274cc3be128d03d 100644 --- a/hw/sd/aspeed_sdhci.c +++ b/hw/sd/aspeed_sdhci.c @@ -16,7 +16,9 @@ #include "hw/qdev-properties.h" #define ASPEED_SDHCI_INFO 0x00 -#define ASPEED_SDHCI_INFO_RESET 0x00030000 +#define ASPEED_SDHCI_INFO_SLOT1 (1 << 17) +#define ASPEED_SDHCI_INFO_SLOT0 (1 << 16) +#define ASPEED_SDHCI_INFO_RESET (1 << 0) #define ASPEED_SDHCI_DEBOUNCE 0x04 #define ASPEED_SDHCI_DEBOUNCE_RESET 0x00000005 #define ASPEED_SDHCI_BUS 0x08 @@ -67,6 +69,10 @@ static void aspeed_sdhci_write(void *opaque, hwaddr addr, uint64_t val, AspeedSDHCIState *sdhci = opaque; switch (addr) { + case ASPEED_SDHCI_INFO: + /* The RESET bit automatically clears. */ + sdhci->regs[TO_REG(addr)] = (uint32_t)val & ~ASPEED_SDHCI_INFO_RESET; + break; case ASPEED_SDHCI_SDIO_140: sdhci->slots[0].capareg = (uint64_t)(uint32_t)val; break; @@ -115,7 +121,6 @@ static void aspeed_sdhci_set_irq(void *opaque, int n, int level) static void aspeed_sdhci_realize(DeviceState *dev, Error **errp) { - Error *err = NULL; SysBusDevice *sbd = SYS_BUS_DEVICE(dev); AspeedSDHCIState *sdhci = ASPEED_SDHCI(dev); @@ -132,22 +137,16 @@ static void aspeed_sdhci_realize(DeviceState *dev, Error **errp) Object *sdhci_slot = OBJECT(&sdhci->slots[i]); SysBusDevice *sbd_slot = SYS_BUS_DEVICE(&sdhci->slots[i]); - object_property_set_int(sdhci_slot, 2, "sd-spec-version", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_int(sdhci_slot, "sd-spec-version", 2, errp)) { return; } - object_property_set_uint(sdhci_slot, ASPEED_SDHCI_CAPABILITIES, - "capareg", &err); - if (err) { - error_propagate(errp, err); + if (!object_property_set_uint(sdhci_slot, "capareg", + ASPEED_SDHCI_CAPABILITIES, errp)) { return; } - object_property_set_bool(sdhci_slot, true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!sysbus_realize(sbd_slot, errp)) { return; } @@ -162,7 +161,11 @@ static void aspeed_sdhci_reset(DeviceState *dev) AspeedSDHCIState *sdhci = ASPEED_SDHCI(dev); memset(sdhci->regs, 0, ASPEED_SDHCI_REG_SIZE); - sdhci->regs[TO_REG(ASPEED_SDHCI_INFO)] = ASPEED_SDHCI_INFO_RESET; + + sdhci->regs[TO_REG(ASPEED_SDHCI_INFO)] = ASPEED_SDHCI_INFO_SLOT0; + if (sdhci->num_slots == 2) { + sdhci->regs[TO_REG(ASPEED_SDHCI_INFO)] |= ASPEED_SDHCI_INFO_SLOT1; + } sdhci->regs[TO_REG(ASPEED_SDHCI_DEBOUNCE)] = ASPEED_SDHCI_DEBOUNCE_RESET; } diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c index 4a80fbcc861efe8a6033cf852cf9fc65acd4e4b1..50f5fdb88bcdfcae621f6b3c881e35697d7f6a62 100644 --- a/hw/sd/bcm2835_sdhost.c +++ b/hw/sd/bcm2835_sdhost.c @@ -19,10 +19,12 @@ #include "hw/sd/bcm2835_sdhost.h" #include "migration/vmstate.h" #include "trace.h" +#include "qom/object.h" #define TYPE_BCM2835_SDHOST_BUS "bcm2835-sdhost-bus" -#define BCM2835_SDHOST_BUS(obj) \ - OBJECT_CHECK(SDBus, (obj), TYPE_BCM2835_SDHOST_BUS) +/* This is reusing the SDBus typedef from SD_BUS */ +DECLARE_INSTANCE_CHECKER(SDBus, BCM2835_SDHOST_BUS, + TYPE_BCM2835_SDHOST_BUS) #define SDCMD 0x00 /* Command to SD card - 16 R/W */ #define SDARG 0x04 /* Argument to SD card - 32 R/W */ @@ -190,7 +192,7 @@ static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s) if (is_read) { n = 0; while (s->datacnt && s->fifo_len < BCM2835_SDHOST_FIFO_LEN) { - value |= (uint32_t)sdbus_read_data(&s->sdbus) << (n * 8); + value |= (uint32_t)sdbus_read_byte(&s->sdbus) << (n * 8); s->datacnt--; n++; if (n == 4) { @@ -223,7 +225,7 @@ static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s) } n--; s->datacnt--; - sdbus_write_data(&s->sdbus, value & 0xff); + sdbus_write_byte(&s->sdbus, value & 0xff); value >>= 8; } } diff --git a/hw/sd/cadence_sdhci.c b/hw/sd/cadence_sdhci.c new file mode 100644 index 0000000000000000000000000000000000000000..0b371c843d8e38d059925bc2275814b51a02d07b --- /dev/null +++ b/hw/sd/cadence_sdhci.c @@ -0,0 +1,193 @@ +/* + * Cadence SDHCI emulation + * + * Copyright (c) 2020 Wind River Systems, Inc. + * + * Author: + * Bin Meng + * + * 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 or + * (at your option) version 3 of the License. + * + * 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/bitops.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "hw/irq.h" +#include "hw/sd/cadence_sdhci.h" +#include "sdhci-internal.h" + +/* HRS - Host Register Set (specific to Cadence) */ + +#define CADENCE_SDHCI_HRS00 0x00 /* general information */ +#define CADENCE_SDHCI_HRS00_SWR BIT(0) +#define CADENCE_SDHCI_HRS00_POR_VAL 0x00010000 + +#define CADENCE_SDHCI_HRS04 0x10 /* PHY access port */ +#define CADENCE_SDHCI_HRS04_WR BIT(24) +#define CADENCE_SDHCI_HRS04_RD BIT(25) +#define CADENCE_SDHCI_HRS04_ACK BIT(26) + +#define CADENCE_SDHCI_HRS06 0x18 /* eMMC control */ +#define CADENCE_SDHCI_HRS06_TUNE_UP BIT(15) + +/* SRS - Slot Register Set (SDHCI-compatible) */ + +#define CADENCE_SDHCI_SRS_BASE 0x200 + +#define TO_REG(addr) ((addr) / sizeof(uint32_t)) + +static void cadence_sdhci_instance_init(Object *obj) +{ + CadenceSDHCIState *s = CADENCE_SDHCI(obj); + + object_initialize_child(OBJECT(s), "generic-sdhci", + &s->sdhci, TYPE_SYSBUS_SDHCI); +} + +static void cadence_sdhci_reset(DeviceState *dev) +{ + CadenceSDHCIState *s = CADENCE_SDHCI(dev); + + memset(s->regs, 0, CADENCE_SDHCI_REG_SIZE); + s->regs[TO_REG(CADENCE_SDHCI_HRS00)] = CADENCE_SDHCI_HRS00_POR_VAL; + + device_cold_reset(DEVICE(&s->sdhci)); +} + +static uint64_t cadence_sdhci_read(void *opaque, hwaddr addr, unsigned int size) +{ + CadenceSDHCIState *s = opaque; + uint32_t val; + + val = s->regs[TO_REG(addr)]; + + return (uint64_t)val; +} + +static void cadence_sdhci_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int size) +{ + CadenceSDHCIState *s = opaque; + uint32_t val32 = (uint32_t)val; + + switch (addr) { + case CADENCE_SDHCI_HRS00: + /* + * The only writable bit is SWR (software reset) and it automatically + * clears to zero, so essentially this register remains unchanged. + */ + if (val32 & CADENCE_SDHCI_HRS00_SWR) { + cadence_sdhci_reset(DEVICE(s)); + } + + break; + case CADENCE_SDHCI_HRS04: + /* + * Only emulate the ACK bit behavior when read or write transaction + * are requested. + */ + if (val32 & (CADENCE_SDHCI_HRS04_WR | CADENCE_SDHCI_HRS04_RD)) { + val32 |= CADENCE_SDHCI_HRS04_ACK; + } else { + val32 &= ~CADENCE_SDHCI_HRS04_ACK; + } + + s->regs[TO_REG(addr)] = val32; + break; + case CADENCE_SDHCI_HRS06: + if (val32 & CADENCE_SDHCI_HRS06_TUNE_UP) { + val32 &= ~CADENCE_SDHCI_HRS06_TUNE_UP; + } + + s->regs[TO_REG(addr)] = val32; + break; + default: + s->regs[TO_REG(addr)] = val32; + break; + } +} + +static const MemoryRegionOps cadence_sdhci_ops = { + .read = cadence_sdhci_read, + .write = cadence_sdhci_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + } +}; + +static void cadence_sdhci_realize(DeviceState *dev, Error **errp) +{ + CadenceSDHCIState *s = CADENCE_SDHCI(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + SysBusDevice *sbd_sdhci = SYS_BUS_DEVICE(&s->sdhci); + + memory_region_init(&s->container, OBJECT(s), + "cadence.sdhci-container", 0x1000); + sysbus_init_mmio(sbd, &s->container); + + memory_region_init_io(&s->iomem, OBJECT(s), &cadence_sdhci_ops, + s, TYPE_CADENCE_SDHCI, CADENCE_SDHCI_REG_SIZE); + memory_region_add_subregion(&s->container, 0, &s->iomem); + + sysbus_realize(sbd_sdhci, errp); + memory_region_add_subregion(&s->container, CADENCE_SDHCI_SRS_BASE, + sysbus_mmio_get_region(sbd_sdhci, 0)); + + /* propagate irq and "sd-bus" from generic-sdhci */ + sysbus_pass_irq(sbd, sbd_sdhci); + s->bus = qdev_get_child_bus(DEVICE(sbd_sdhci), "sd-bus"); +} + +static const VMStateDescription vmstate_cadence_sdhci = { + .name = TYPE_CADENCE_SDHCI, + .version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, CadenceSDHCIState, CADENCE_SDHCI_NUM_REGS), + VMSTATE_END_OF_LIST(), + }, +}; + +static void cadence_sdhci_class_init(ObjectClass *classp, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(classp); + + dc->desc = "Cadence SD/SDIO/eMMC Host Controller (SD4HC)"; + dc->realize = cadence_sdhci_realize; + dc->reset = cadence_sdhci_reset; + dc->vmsd = &vmstate_cadence_sdhci; +} + +static TypeInfo cadence_sdhci_info = { + .name = TYPE_CADENCE_SDHCI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(CadenceSDHCIState), + .instance_init = cadence_sdhci_instance_init, + .class_init = cadence_sdhci_class_init, +}; + +static void cadence_sdhci_register_types(void) +{ + type_register_static(&cadence_sdhci_info); +} + +type_init(cadence_sdhci_register_types) diff --git a/hw/sd/core.c b/hw/sd/core.c index abec48bccb80a92cf3c8e6dee3975a8558af284f..08c93b59034d2b0bf20ec34f4d9f6c4142c136b4 100644 --- a/hw/sd/core.c +++ b/hw/sd/core.c @@ -23,6 +23,7 @@ #include "hw/qdev-core.h" #include "hw/sd/sd.h" #include "qemu/module.h" +#include "qapi/error.h" #include "trace.h" static inline const char *sdbus_name(SDBus *sdbus) @@ -102,7 +103,7 @@ int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response) return 0; } -void sdbus_write_data(SDBus *sdbus, uint8_t value) +void sdbus_write_byte(SDBus *sdbus, uint8_t value) { SDState *card = get_card(sdbus); @@ -110,11 +111,26 @@ void sdbus_write_data(SDBus *sdbus, uint8_t value) if (card) { SDCardClass *sc = SD_CARD_GET_CLASS(card); - sc->write_data(card, value); + sc->write_byte(card, value); } } -uint8_t sdbus_read_data(SDBus *sdbus) +void sdbus_write_data(SDBus *sdbus, const void *buf, size_t length) +{ + SDState *card = get_card(sdbus); + const uint8_t *data = buf; + + if (card) { + SDCardClass *sc = SD_CARD_GET_CLASS(card); + + for (size_t i = 0; i < length; i++) { + trace_sdbus_write(sdbus_name(sdbus), data[i]); + sc->write_byte(card, data[i]); + } + } +} + +uint8_t sdbus_read_byte(SDBus *sdbus) { SDState *card = get_card(sdbus); uint8_t value = 0; @@ -122,13 +138,28 @@ uint8_t sdbus_read_data(SDBus *sdbus) if (card) { SDCardClass *sc = SD_CARD_GET_CLASS(card); - value = sc->read_data(card); + value = sc->read_byte(card); } trace_sdbus_read(sdbus_name(sdbus), value); return value; } +void sdbus_read_data(SDBus *sdbus, void *buf, size_t length) +{ + SDState *card = get_card(sdbus); + uint8_t *data = buf; + + if (card) { + SDCardClass *sc = SD_CARD_GET_CLASS(card); + + for (size_t i = 0; i < length; i++) { + data[i] = sc->read_byte(card); + trace_sdbus_read(sdbus_name(sdbus), data[i]); + } + } +} + bool sdbus_data_ready(SDBus *sdbus) { SDState *card = get_card(sdbus); @@ -210,7 +241,7 @@ void sdbus_reparent_card(SDBus *from, SDBus *to) readonly = sc->get_readonly(card); sdbus_set_inserted(from, false); - qdev_set_parent_bus(DEVICE(card), &to->qbus); + qdev_set_parent_bus(DEVICE(card), &to->qbus, &error_abort); sdbus_set_inserted(to, true); sdbus_set_readonly(to, readonly); } diff --git a/hw/sd/meson.build b/hw/sd/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..9c29691e13e032de53d8503989d0781c4510d81d --- /dev/null +++ b/hw/sd/meson.build @@ -0,0 +1,13 @@ +softmmu_ss.add(when: 'CONFIG_PL181', if_true: files('pl181.c')) +softmmu_ss.add(when: 'CONFIG_SD', if_true: files('sd.c', 'core.c', 'sdmmc-internal.c')) +softmmu_ss.add(when: 'CONFIG_SDHCI', if_true: files('sdhci.c')) +softmmu_ss.add(when: 'CONFIG_SDHCI_PCI', if_true: files('sdhci-pci.c')) +softmmu_ss.add(when: 'CONFIG_SSI_SD', if_true: files('ssi-sd.c')) + +softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-memcard.c')) +softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_mmc.c')) +softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_mmci.c')) +softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_sdhost.c')) +softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_sdhci.c')) +softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sdhost.c')) +softmmu_ss.add(when: 'CONFIG_CADENCE_SDHCI', if_true: files('cadence_sdhci.c')) diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c index 926e1af475d2dc5cc292e0394c8c0380bc09cd44..a1235aa46c1ae1eb9ef2534283dc82b636880d2f 100644 --- a/hw/sd/milkymist-memcard.c +++ b/hw/sd/milkymist-memcard.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -32,6 +32,7 @@ #include "sysemu/blockdev.h" #include "hw/qdev-properties.h" #include "hw/sd/sd.h" +#include "qom/object.h" enum { ENABLE_CMD_TX = (1<<0), @@ -63,8 +64,9 @@ enum { }; #define TYPE_MILKYMIST_MEMCARD "milkymist-memcard" -#define MILKYMIST_MEMCARD(obj) \ - OBJECT_CHECK(MilkymistMemcardState, (obj), TYPE_MILKYMIST_MEMCARD) +OBJECT_DECLARE_SIMPLE_TYPE(MilkymistMemcardState, MILKYMIST_MEMCARD) + +#define TYPE_MILKYMIST_SDBUS "milkymist-sdbus" struct MilkymistMemcardState { SysBusDevice parent_obj; @@ -81,7 +83,6 @@ struct MilkymistMemcardState { uint8_t response[17]; uint32_t regs[R_MAX]; }; -typedef struct MilkymistMemcardState MilkymistMemcardState; static void update_pending_bits(MilkymistMemcardState *s) { @@ -149,11 +150,8 @@ static uint64_t memcard_read(void *opaque, hwaddr addr, if (!s->enabled) { r = 0xffffffff; } else { - r = 0; - r |= sdbus_read_data(&s->sdbus) << 24; - r |= sdbus_read_data(&s->sdbus) << 16; - r |= sdbus_read_data(&s->sdbus) << 8; - r |= sdbus_read_data(&s->sdbus); + sdbus_read_data(&s->sdbus, &r, sizeof(r)); + be32_to_cpus(&r); } break; case R_CLK2XDIV: @@ -179,6 +177,7 @@ static void memcard_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { MilkymistMemcardState *s = opaque; + uint32_t val32; trace_milkymist_memcard_memory_write(addr, value); @@ -207,10 +206,8 @@ static void memcard_write(void *opaque, hwaddr addr, uint64_t value, if (!s->enabled) { break; } - sdbus_write_data(&s->sdbus, (value >> 24) & 0xff); - sdbus_write_data(&s->sdbus, (value >> 16) & 0xff); - sdbus_write_data(&s->sdbus, (value >> 8) & 0xff); - sdbus_write_data(&s->sdbus, value & 0xff); + val32 = cpu_to_be32(value); + sdbus_write_data(&s->sdbus, &val32, sizeof(val32)); break; case R_ENABLE: s->regs[addr] = value; @@ -253,6 +250,19 @@ static void milkymist_memcard_reset(DeviceState *d) } } +static void milkymist_memcard_set_readonly(DeviceState *dev, bool level) +{ + qemu_log_mask(LOG_UNIMP, + "milkymist_memcard: read-only mode not supported\n"); +} + +static void milkymist_memcard_set_inserted(DeviceState *dev, bool level) +{ + MilkymistMemcardState *s = MILKYMIST_MEMCARD(dev); + + s->enabled = !!level; +} + static void milkymist_memcard_init(Object *obj) { MilkymistMemcardState *s = MILKYMIST_MEMCARD(obj); @@ -261,31 +271,9 @@ static void milkymist_memcard_init(Object *obj) memory_region_init_io(&s->regs_region, OBJECT(s), &memcard_mmio_ops, s, "milkymist-memcard", R_MAX * 4); sysbus_init_mmio(dev, &s->regs_region); -} - -static void milkymist_memcard_realize(DeviceState *dev, Error **errp) -{ - MilkymistMemcardState *s = MILKYMIST_MEMCARD(dev); - DeviceState *carddev; - BlockBackend *blk; - DriveInfo *dinfo; - Error *err = NULL; qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), TYPE_SD_BUS, - dev, "sd-bus"); - - /* Create and plug in the sd card */ - /* FIXME use a qdev drive property instead of drive_get_next() */ - dinfo = drive_get_next(IF_SD); - blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; - carddev = qdev_create(BUS(&s->sdbus), TYPE_SD_CARD); - qdev_prop_set_drive(carddev, "drive", blk, &err); - object_property_set_bool(OBJECT(carddev), true, "realized", &err); - if (err) { - error_setg(errp, "failed to init SD card: %s", error_get_pretty(err)); - return; - } - s->enabled = blk && blk_is_inserted(blk); + DEVICE(obj), "sd-bus"); } static const VMStateDescription vmstate_milkymist_memcard = { @@ -309,10 +297,9 @@ static void milkymist_memcard_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - dc->realize = milkymist_memcard_realize; dc->reset = milkymist_memcard_reset; dc->vmsd = &vmstate_milkymist_memcard; - /* Reason: init() method uses drive_get_next() */ + /* Reason: output IRQs should be wired up */ dc->user_creatable = false; } @@ -324,9 +311,25 @@ static const TypeInfo milkymist_memcard_info = { .class_init = milkymist_memcard_class_init, }; +static void milkymist_sdbus_class_init(ObjectClass *klass, void *data) +{ + SDBusClass *sbc = SD_BUS_CLASS(klass); + + sbc->set_inserted = milkymist_memcard_set_inserted; + sbc->set_readonly = milkymist_memcard_set_readonly; +} + +static const TypeInfo milkymist_sdbus_info = { + .name = TYPE_MILKYMIST_SDBUS, + .parent = TYPE_SD_BUS, + .instance_size = sizeof(SDBus), + .class_init = milkymist_sdbus_class_init, +}; + static void milkymist_memcard_register_types(void) { type_register_static(&milkymist_memcard_info); + type_register_static(&milkymist_sdbus_info); } type_init(milkymist_memcard_register_types) diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c index 4088a8a80bc56eff9a5df86678c400c20d11bcf9..1f946908fe178bf4edae39b76eafc1ba355fc9d1 100644 --- a/hw/sd/omap_mmc.c +++ b/hw/sd/omap_mmc.c @@ -23,7 +23,7 @@ #include "qemu/log.h" #include "hw/irq.h" #include "hw/arm/omap.h" -#include "hw/sd/sd.h" +#include "hw/sd/sdcard_legacy.h" struct omap_mmc_s { qemu_irq irq; @@ -232,10 +232,10 @@ static void omap_mmc_transfer(struct omap_mmc_s *host) if (host->fifo_len > host->af_level) break; - value = sd_read_data(host->card); + value = sd_read_byte(host->card); host->fifo[(host->fifo_start + host->fifo_len) & 31] = value; if (-- host->blen_counter) { - value = sd_read_data(host->card); + value = sd_read_byte(host->card); host->fifo[(host->fifo_start + host->fifo_len) & 31] |= value << 8; host->blen_counter --; @@ -247,10 +247,10 @@ static void omap_mmc_transfer(struct omap_mmc_s *host) break; value = host->fifo[host->fifo_start] & 0xff; - sd_write_data(host->card, value); + sd_write_byte(host->card, value); if (-- host->blen_counter) { value = host->fifo[host->fifo_start] >> 8; - sd_write_data(host->card, value); + sd_write_byte(host->card, value); host->blen_counter --; } diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c index 2b3776a6a0fad0b9308a130826c7e2b46843fd87..960f155098184fc90a2f7301497caf256f73b00a 100644 --- a/hw/sd/pl181.c +++ b/hw/sd/pl181.c @@ -15,27 +15,23 @@ #include "hw/sd/sd.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qemu/error-report.h" #include "qapi/error.h" - -//#define DEBUG_PL181 1 - -#ifdef DEBUG_PL181 -#define DPRINTF(fmt, ...) \ -do { printf("pl181: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) do {} while(0) -#endif +#include "trace.h" +#include "qom/object.h" #define PL181_FIFO_LEN 16 #define TYPE_PL181 "pl181" -#define PL181(obj) OBJECT_CHECK(PL181State, (obj), TYPE_PL181) +OBJECT_DECLARE_SIMPLE_TYPE(PL181State, PL181) + +#define TYPE_PL181_BUS "pl181-bus" -typedef struct PL181State { +struct PL181State { SysBusDevice parent_obj; MemoryRegion iomem; - SDState *card; + SDBus sdbus; uint32_t clock; uint32_t power; uint32_t cmdarg; @@ -56,11 +52,12 @@ typedef struct PL181State { http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=4446/1 */ int32_t linux_hack; - uint32_t fifo[PL181_FIFO_LEN]; + uint32_t fifo[PL181_FIFO_LEN]; /* TODO use Fifo32 */ qemu_irq irq[2]; /* GPIO outputs for 'card is readonly' and 'card inserted' */ - qemu_irq cardstatus[2]; -} PL181State; + qemu_irq card_readonly; + qemu_irq card_inserted; +}; static const VMStateDescription vmstate_pl181 = { .name = "pl181", @@ -148,13 +145,13 @@ static void pl181_fifo_push(PL181State *s, uint32_t value) int n; if (s->fifo_len == PL181_FIFO_LEN) { - fprintf(stderr, "pl181: FIFO overflow\n"); + error_report("%s: FIFO overflow", __func__); return; } n = (s->fifo_pos + s->fifo_len) & (PL181_FIFO_LEN - 1); s->fifo_len++; s->fifo[n] = value; - DPRINTF("FIFO push %08x\n", (int)value); + trace_pl181_fifo_push(value); } static uint32_t pl181_fifo_pop(PL181State *s) @@ -162,17 +159,17 @@ static uint32_t pl181_fifo_pop(PL181State *s) uint32_t value; if (s->fifo_len == 0) { - fprintf(stderr, "pl181: FIFO underflow\n"); + error_report("%s: FIFO underflow", __func__); return 0; } value = s->fifo[s->fifo_pos]; s->fifo_len--; s->fifo_pos = (s->fifo_pos + 1) & (PL181_FIFO_LEN - 1); - DPRINTF("FIFO pop %08x\n", (int)value); + trace_pl181_fifo_pop(value); return value; } -static void pl181_send_command(PL181State *s) +static void pl181_do_command(PL181State *s) { SDRequest request; uint8_t response[16]; @@ -180,8 +177,8 @@ static void pl181_send_command(PL181State *s) request.cmd = s->cmd & PL181_CMD_INDEX; request.arg = s->cmdarg; - DPRINTF("Command %d %08x\n", request.cmd, request.arg); - rlen = sd_do_command(s->card, &request, response); + trace_pl181_command_send(request.cmd, request.arg); + rlen = sdbus_do_command(&s->sdbus, &request, response); if (rlen < 0) goto error; if (s->cmd & PL181_CMD_RESPONSE) { @@ -197,16 +194,16 @@ static void pl181_send_command(PL181State *s) s->response[2] = ldl_be_p(&response[8]); s->response[3] = ldl_be_p(&response[12]) & ~1; } - DPRINTF("Response received\n"); + trace_pl181_command_response_pending(); s->status |= PL181_STATUS_CMDRESPEND; } else { - DPRINTF("Command sent\n"); + trace_pl181_command_sent(); s->status |= PL181_STATUS_CMDSENT; } return; error: - DPRINTF("Timeout\n"); + trace_pl181_command_timeout(); s->status |= PL181_STATUS_CMDTIMEOUT; } @@ -222,12 +219,12 @@ static void pl181_fifo_run(PL181State *s) int is_read; is_read = (s->datactrl & PL181_DATA_DIRECTION) != 0; - if (s->datacnt != 0 && (!is_read || sd_data_ready(s->card)) + if (s->datacnt != 0 && (!is_read || sdbus_data_ready(&s->sdbus)) && !s->linux_hack) { if (is_read) { n = 0; while (s->datacnt && s->fifo_len < PL181_FIFO_LEN) { - value |= (uint32_t)sd_read_data(s->card) << (n * 8); + value |= (uint32_t)sdbus_read_byte(&s->sdbus) << (n * 8); s->datacnt--; n++; if (n == 4) { @@ -248,7 +245,7 @@ static void pl181_fifo_run(PL181State *s) } n--; s->datacnt--; - sd_write_data(s->card, value & 0xff); + sdbus_write_byte(&s->sdbus, value & 0xff); value >>= 8; } } @@ -258,11 +255,11 @@ static void pl181_fifo_run(PL181State *s) s->status |= PL181_STATUS_DATAEND; /* HACK: */ s->status |= PL181_STATUS_DATABLOCKEND; - DPRINTF("Transfer Complete\n"); + trace_pl181_fifo_transfer_complete(); } if (s->datacnt == 0 && s->fifo_len == 0) { s->datactrl &= ~PL181_DATA_ENABLE; - DPRINTF("Data engine idle\n"); + trace_pl181_data_engine_idle(); } else { /* Update FIFO bits. */ bits = PL181_STATUS_TXACTIVE | PL181_STATUS_RXACTIVE; @@ -401,7 +398,7 @@ static void pl181_write(void *opaque, hwaddr offset, qemu_log_mask(LOG_UNIMP, "pl181: Pending commands not implemented\n"); } else { - pl181_send_command(s); + pl181_do_command(s); pl181_fifo_run(s); } /* The command has completed one way or the other. */ @@ -454,6 +451,20 @@ static const MemoryRegionOps pl181_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; +static void pl181_set_readonly(DeviceState *dev, bool level) +{ + PL181State *s = (PL181State *)dev; + + qemu_set_irq(s->card_readonly, level); +} + +static void pl181_set_inserted(DeviceState *dev, bool level) +{ + PL181State *s = (PL181State *)dev; + + qemu_set_irq(s->card_inserted, level); +} + static void pl181_reset(DeviceState *d) { PL181State *s = PL181(d); @@ -477,12 +488,9 @@ static void pl181_reset(DeviceState *d) s->mask[0] = 0; s->mask[1] = 0; - /* We can assume our GPIO outputs have been wired up now */ - sd_set_cb(s->card, s->cardstatus[0], s->cardstatus[1]); - /* Since we're still using the legacy SD API the card is not plugged - * into any bus, and we must reset it manually. - */ - device_legacy_reset(DEVICE(s->card)); + /* Reset other state based on current card insertion/readonly status */ + pl181_set_inserted(DEVICE(s), sdbus_get_inserted(&s->sdbus)); + pl181_set_readonly(DEVICE(s), sdbus_get_readonly(&s->sdbus)); } static void pl181_init(Object *obj) @@ -495,20 +503,11 @@ static void pl181_init(Object *obj) sysbus_init_mmio(sbd, &s->iomem); sysbus_init_irq(sbd, &s->irq[0]); sysbus_init_irq(sbd, &s->irq[1]); - qdev_init_gpio_out(dev, s->cardstatus, 2); -} + qdev_init_gpio_out_named(dev, &s->card_readonly, "card-read-only", 1); + qdev_init_gpio_out_named(dev, &s->card_inserted, "card-inserted", 1); -static void pl181_realize(DeviceState *dev, Error **errp) -{ - PL181State *s = PL181(dev); - DriveInfo *dinfo; - - /* FIXME use a qdev drive property instead of drive_get_next() */ - dinfo = drive_get_next(IF_SD); - s->card = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, false); - if (s->card == NULL) { - error_setg(errp, "sd_init failed"); - } + qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), + TYPE_PL181_BUS, dev, "sd-bus"); } static void pl181_class_init(ObjectClass *klass, void *data) @@ -517,9 +516,8 @@ static void pl181_class_init(ObjectClass *klass, void *data) k->vmsd = &vmstate_pl181; k->reset = pl181_reset; - /* Reason: init() method uses drive_get_next() */ + /* Reason: output IRQs should be wired up */ k->user_creatable = false; - k->realize = pl181_realize; } static const TypeInfo pl181_info = { @@ -530,9 +528,25 @@ static const TypeInfo pl181_info = { .class_init = pl181_class_init, }; +static void pl181_bus_class_init(ObjectClass *klass, void *data) +{ + SDBusClass *sbc = SD_BUS_CLASS(klass); + + sbc->set_inserted = pl181_set_inserted; + sbc->set_readonly = pl181_set_readonly; +} + +static const TypeInfo pl181_bus_info = { + .name = TYPE_PL181_BUS, + .parent = TYPE_SD_BUS, + .instance_size = sizeof(SDBus), + .class_init = pl181_bus_class_init, +}; + static void pl181_register_types(void) { type_register_static(&pl181_info); + type_register_static(&pl181_bus_info); } type_init(pl181_register_types) diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c index 8f9ab0ec1676ec65d7977ffd687e7bdad6fc8b25..3dd2fc7a83fccc83bb8a7d85af52293bbfbac04e 100644 --- a/hw/sd/pxa2xx_mmci.c +++ b/hw/sd/pxa2xx_mmci.c @@ -18,16 +18,15 @@ #include "hw/arm/pxa.h" #include "hw/sd/sd.h" #include "hw/qdev-properties.h" -#include "qemu/error-report.h" #include "qemu/log.h" #include "qemu/module.h" #include "trace.h" - -#define TYPE_PXA2XX_MMCI "pxa2xx-mmci" -#define PXA2XX_MMCI(obj) OBJECT_CHECK(PXA2xxMMCIState, (obj), TYPE_PXA2XX_MMCI) +#include "qom/object.h" #define TYPE_PXA2XX_MMCI_BUS "pxa2xx-mmci-bus" -#define PXA2XX_MMCI_BUS(obj) OBJECT_CHECK(SDBus, (obj), TYPE_PXA2XX_MMCI_BUS) +/* This is reusing the SDBus typedef from SD_BUS */ +DECLARE_INSTANCE_CHECKER(SDBus, PXA2XX_MMCI_BUS, + TYPE_PXA2XX_MMCI_BUS) struct PXA2xxMMCIState { SysBusDevice parent_obj; @@ -185,7 +184,7 @@ static void pxa2xx_mmci_fifo_update(PXA2xxMMCIState *s) if (s->cmdat & CMDAT_WR_RD) { while (s->bytesleft && s->tx_len) { - sdbus_write_data(&s->sdbus, s->tx_fifo[s->tx_start++]); + sdbus_write_byte(&s->sdbus, s->tx_fifo[s->tx_start++]); s->tx_start &= 0x1f; s->tx_len --; s->bytesleft --; @@ -195,7 +194,7 @@ static void pxa2xx_mmci_fifo_update(PXA2xxMMCIState *s) } else while (s->bytesleft && s->rx_len < 32) { s->rx_fifo[(s->rx_start + (s->rx_len ++)) & 0x1f] = - sdbus_read_data(&s->sdbus); + sdbus_read_byte(&s->sdbus); s->bytesleft --; s->intreq |= INT_RXFIFO_REQ; } @@ -477,36 +476,20 @@ static const MemoryRegionOps pxa2xx_mmci_ops = { PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem, hwaddr base, - BlockBackend *blk, qemu_irq irq, - qemu_irq rx_dma, qemu_irq tx_dma) + qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma) { - DeviceState *dev, *carddev; + DeviceState *dev; SysBusDevice *sbd; - PXA2xxMMCIState *s; - Error *err = NULL; - dev = qdev_create(NULL, TYPE_PXA2XX_MMCI); - s = PXA2XX_MMCI(dev); + dev = qdev_new(TYPE_PXA2XX_MMCI); sbd = SYS_BUS_DEVICE(dev); sysbus_mmio_map(sbd, 0, base); sysbus_connect_irq(sbd, 0, irq); qdev_connect_gpio_out_named(dev, "rx-dma", 0, rx_dma); qdev_connect_gpio_out_named(dev, "tx-dma", 0, tx_dma); + sysbus_realize_and_unref(sbd, &error_fatal); - /* Create and plug in the sd card */ - carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD); - qdev_prop_set_drive(carddev, "drive", blk, &err); - if (err) { - error_report("failed to init SD card: %s", error_get_pretty(err)); - return NULL; - } - object_property_set_bool(OBJECT(carddev), true, "realized", &err); - if (err) { - error_report("failed to init SD card: %s", error_get_pretty(err)); - return NULL; - } - - return s; + return PXA2XX_MMCI(dev); } static void pxa2xx_mmci_set_inserted(DeviceState *dev, bool inserted) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 71a9af09ab758a60ad32fc7fc2470d36173ea657..1842c037978c6b17c74d6b81a16965ed9d358362 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -32,10 +32,12 @@ #include "qemu/osdep.h" #include "qemu/units.h" +#include "qemu/cutils.h" #include "hw/irq.h" #include "hw/registerfields.h" #include "sysemu/block-backend.h" #include "hw/sd/sd.h" +#include "hw/sd/sdcard_legacy.h" #include "migration/vmstate.h" #include "qapi/error.h" #include "qemu/bitmap.h" @@ -49,6 +51,10 @@ //#define DEBUG_SD 1 +#define SDSC_MAX_CAPACITY (2 * GiB) + +#define INVALID_ADDRESS UINT32_MAX + typedef enum { sd_r0 = 0, /* no response */ sd_r1, /* normal response command */ @@ -83,6 +89,10 @@ enum SDCardStates { struct SDState { DeviceState parent_obj; + /* If true, created by sd_init() for a non-qdevified caller */ + /* TODO purge them with fire */ + bool me_no_qdev_me_kill_mammoth_with_rocks; + /* SD Memory Card Registers */ uint32_t ocr; uint8_t scr[8]; @@ -92,11 +102,14 @@ struct SDState { uint32_t card_status; uint8_t sd_status[64]; - /* Configurable properties */ + /* Static properties */ + uint8_t spec_version; BlockBackend *blk; bool spi; + /* Runtime changeables */ + uint32_t mode; /* current card mode, one of SDCardModes */ int32_t state; /* current card state, one of SDCardStates */ uint32_t vhs; @@ -129,6 +142,8 @@ struct SDState { bool cmd_line; }; +static void sd_realize(DeviceState *dev, Error **errp); + static const char *sd_state_name(enum SDCardStates state) { static const char *state_name[] = { @@ -239,11 +254,11 @@ static const int sd_cmd_class[SDMMC_CMD_MAX] = { 7, 7, 10, 7, 9, 9, 9, 8, 8, 10, 8, 8, 8, 8, 8, 8, }; -static uint8_t sd_crc7(void *message, size_t width) +static uint8_t sd_crc7(const void *message, size_t width) { int i, bit; uint8_t shift_reg = 0x00; - uint8_t *msg = (uint8_t *) message; + const uint8_t *msg = (const uint8_t *)message; for (i = 0; i < width; i ++, msg ++) for (bit = 7; bit >= 0; bit --) { @@ -255,11 +270,11 @@ static uint8_t sd_crc7(void *message, size_t width) return shift_reg; } -static uint16_t sd_crc16(void *message, size_t width) +static uint16_t sd_crc16(const void *message, size_t width) { int i, bit; uint16_t shift_reg = 0x0000; - uint16_t *msg = (uint16_t *) message; + const uint16_t *msg = (const uint16_t *)message; width <<= 1; for (i = 0; i < width; i ++, msg ++) @@ -306,7 +321,7 @@ static void sd_ocr_powerup(void *opaque) /* card power-up OK */ sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_POWER_UP, 1); - if (sd->size > 1 * GiB) { + if (sd->size > SDSC_MAX_CAPACITY) { sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_CAPACITY, 1); } } @@ -374,18 +389,25 @@ static const uint8_t sd_csd_rw_mask[16] = { static void sd_set_csd(SDState *sd, uint64_t size) { - uint32_t csize = (size >> (CMULT_SHIFT + HWBLOCK_SHIFT)) - 1; + int hwblock_shift = HWBLOCK_SHIFT; + uint32_t csize; uint32_t sectsize = (1 << (SECTOR_SHIFT + 1)) - 1; uint32_t wpsize = (1 << (WPGROUP_SHIFT + 1)) - 1; - if (size <= 1 * GiB) { /* Standard Capacity SD */ + /* To indicate 2 GiB card, BLOCK_LEN shall be 1024 bytes */ + if (size == SDSC_MAX_CAPACITY) { + hwblock_shift += 1; + } + csize = (size >> (CMULT_SHIFT + hwblock_shift)) - 1; + + if (size <= SDSC_MAX_CAPACITY) { /* Standard Capacity SD */ sd->csd[0] = 0x00; /* CSD structure */ sd->csd[1] = 0x26; /* Data read access-time-1 */ sd->csd[2] = 0x00; /* Data read access-time-2 */ sd->csd[3] = 0x32; /* Max. data transfer rate: 25 MHz */ sd->csd[4] = 0x5f; /* Card Command Classes */ sd->csd[5] = 0x50 | /* Max. read data block length */ - HWBLOCK_SHIFT; + hwblock_shift; sd->csd[6] = 0xe0 | /* Partial block for read allowed */ ((csize >> 10) & 0x03); sd->csd[7] = 0x00 | /* Device size */ @@ -399,9 +421,9 @@ static void sd_set_csd(SDState *sd, uint64_t size) sd->csd[11] = 0x00 | /* Write protect group size */ ((sectsize << 7) & 0x80) | wpsize; sd->csd[12] = 0x90 | /* Write speed factor */ - (HWBLOCK_SHIFT >> 2); + (hwblock_shift >> 2); sd->csd[13] = 0x20 | /* Max. write data block length */ - ((HWBLOCK_SHIFT << 6) & 0xc0); + ((hwblock_shift << 6) & 0xc0); sd->csd[14] = 0x00; /* File format group */ } else { /* SDHC */ size /= 512 * KiB; @@ -565,8 +587,8 @@ static void sd_reset(DeviceState *dev) sd->wpgrps_size = sect; sd->wp_groups = bitmap_new(sd->wpgrps_size); memset(sd->function_group, 0, sizeof(sd->function_group)); - sd->erase_start = 0; - sd->erase_end = 0; + sd->erase_start = INVALID_ADDRESS; + sd->erase_end = INVALID_ADDRESS; sd->size = size; sd->blk_len = 0x200; sd->pwd_len = 0; @@ -590,7 +612,7 @@ static void sd_cardchange(void *opaque, bool load, Error **errp) { SDState *sd = opaque; DeviceState *dev = DEVICE(sd); - SDBus *sdbus = SD_BUS(qdev_get_parent_bus(dev)); + SDBus *sdbus; bool inserted = sd_get_inserted(sd); bool readonly = sd_get_readonly(sd); @@ -601,18 +623,16 @@ static void sd_cardchange(void *opaque, bool load, Error **errp) trace_sdcard_ejected(); } - /* The IRQ notification is for legacy non-QOM SD controller devices; - * QOMified controllers use the SDBus APIs. - */ - if (sdbus) { - sdbus_set_inserted(sdbus, inserted); + if (sd->me_no_qdev_me_kill_mammoth_with_rocks) { + qemu_set_irq(sd->inserted_cb, inserted); if (inserted) { - sdbus_set_readonly(sdbus, readonly); + qemu_set_irq(sd->readonly_cb, readonly); } } else { - qemu_set_irq(sd->inserted_cb, inserted); + sdbus = SD_BUS(qdev_get_parent_bus(dev)); + sdbus_set_inserted(sdbus, inserted); if (inserted) { - qemu_set_irq(sd->readonly_cb, readonly); + sdbus_set_readonly(sdbus, readonly); } } } @@ -656,8 +676,8 @@ static int sd_vmstate_pre_load(void *opaque) static const VMStateDescription sd_vmstate = { .name = "sd-card", - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .pre_load = sd_vmstate_pre_load, .fields = (VMStateField[]) { VMSTATE_UINT32(mode, SDState), @@ -697,23 +717,34 @@ SDState *sd_init(BlockBackend *blk, bool is_spi) { Object *obj; DeviceState *dev; + SDState *sd; Error *err = NULL; obj = object_new(TYPE_SD_CARD); dev = DEVICE(obj); - qdev_prop_set_drive(dev, "drive", blk, &err); - if (err) { - error_report("sd_init failed: %s", error_get_pretty(err)); + if (!qdev_prop_set_drive_err(dev, "drive", blk, &err)) { + error_reportf_err(err, "sd_init failed: "); return NULL; } qdev_prop_set_bit(dev, "spi", is_spi); - object_property_set_bool(obj, true, "realized", &err); + + /* + * Realizing the device properly would put it into the QOM + * composition tree even though it is not plugged into an + * appropriate bus. That's a no-no. Hide the device from + * QOM/qdev, and call its qdev realize callback directly. + */ + object_ref(obj); + object_unparent(obj); + sd_realize(dev, &err); if (err) { - error_report("sd_init failed: %s", error_get_pretty(err)); + error_reportf_err(err, "sd_init failed: "); return NULL; } - return SD_CARD(dev); + sd = SD_CARD(dev); + sd->me_no_qdev_me_kill_mammoth_with_rocks = true; + return sd; } void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert) @@ -730,9 +761,12 @@ static void sd_erase(SDState *sd) uint64_t erase_start = sd->erase_start; uint64_t erase_end = sd->erase_end; - trace_sdcard_erase(); - if (!sd->erase_start || !sd->erase_end) { + trace_sdcard_erase(sd->erase_start, sd->erase_end); + if (sd->erase_start == INVALID_ADDRESS + || sd->erase_end == INVALID_ADDRESS) { sd->card_status |= ERASE_SEQ_ERROR; + sd->erase_start = INVALID_ADDRESS; + sd->erase_end = INVALID_ADDRESS; return; } @@ -742,13 +776,21 @@ static void sd_erase(SDState *sd) erase_end *= 512; } + if (sd->erase_start > sd->size || sd->erase_end > sd->size) { + sd->card_status |= OUT_OF_RANGE; + sd->erase_start = INVALID_ADDRESS; + sd->erase_end = INVALID_ADDRESS; + return; + } + erase_start = sd_addr_to_wpnum(erase_start); erase_end = sd_addr_to_wpnum(erase_end); - sd->erase_start = 0; - sd->erase_end = 0; + sd->erase_start = INVALID_ADDRESS; + sd->erase_end = INVALID_ADDRESS; sd->csd[14] |= 0x40; for (i = erase_start; i <= erase_end; i++) { + assert(i < sd->wpgrps_size); if (test_bit(i, sd->wp_groups)) { sd->card_status |= WP_ERASE_SKIP; } @@ -763,6 +805,7 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr) wpnum = sd_addr_to_wpnum(addr); for (i = 0; i < 32; i++, wpnum++, addr += WPGROUP_SIZE) { + assert(wpnum < sd->wpgrps_size); if (addr < sd->size && test_bit(wpnum, sd->wp_groups)) { ret |= (1 << i); } @@ -790,11 +833,13 @@ static void sd_function_switch(SDState *sd, uint32_t arg) sd->data[11] = 0x43; sd->data[12] = 0x80; /* Supported group 1 functions */ sd->data[13] = 0x03; + + memset(&sd->data[14], 0, 3); for (i = 0; i < 6; i ++) { new_func = (arg >> (i * 4)) & 0x0f; if (mode && new_func != 0x0f) sd->function_group[i] = new_func; - sd->data[14 + (i >> 1)] = new_func << ((i * 4) & 4); + sd->data[16 - (i >> 1)] |= new_func << ((i % 2) * 4); } memset(&sd->data[17], 0, 47); stw_be_p(sd->data + 64, sd_crc16(sd->data, 64)); @@ -905,6 +950,11 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) sd->multi_blk_cnt = 0; } + if (sd_cmd_class[req.cmd] == 6 && FIELD_EX32(sd->ocr, OCR, CARD_CAPACITY)) { + /* Only Standard Capacity cards support class 6 commands */ + return sd_illegal; + } + switch (req.cmd) { /* Basic commands (Class 0 and Class 1) */ case 0: /* CMD0: GO_IDLE_STATE */ @@ -1150,12 +1200,15 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) case 17: /* CMD17: READ_SINGLE_BLOCK */ switch (sd->state) { case sd_transfer_state: + + if (addr + sd->blk_len > sd->size) { + sd->card_status |= ADDRESS_ERROR; + return sd_r1; + } + sd->state = sd_sendingdata_state; sd->data_start = addr; sd->data_offset = 0; - - if (sd->data_start + sd->blk_len > sd->size) - sd->card_status |= ADDRESS_ERROR; return sd_r1; default: @@ -1166,12 +1219,15 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) case 18: /* CMD18: READ_MULTIPLE_BLOCK */ switch (sd->state) { case sd_transfer_state: + + if (addr + sd->blk_len > sd->size) { + sd->card_status |= ADDRESS_ERROR; + return sd_r1; + } + sd->state = sd_sendingdata_state; sd->data_start = addr; sd->data_offset = 0; - - if (sd->data_start + sd->blk_len > sd->size) - sd->card_status |= ADDRESS_ERROR; return sd_r1; default: @@ -1211,17 +1267,23 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) /* Writing in SPI mode not implemented. */ if (sd->spi) break; + + if (addr + sd->blk_len > sd->size) { + sd->card_status |= ADDRESS_ERROR; + return sd_r1; + } + sd->state = sd_receivingdata_state; sd->data_start = addr; sd->data_offset = 0; sd->blk_written = 0; - if (sd->data_start + sd->blk_len > sd->size) - sd->card_status |= ADDRESS_ERROR; - if (sd_wp_addr(sd, sd->data_start)) + if (sd_wp_addr(sd, sd->data_start)) { sd->card_status |= WP_VIOLATION; - if (sd->csd[14] & 0x30) + } + if (sd->csd[14] & 0x30) { sd->card_status |= WP_VIOLATION; + } return sd_r1; default: @@ -1235,17 +1297,23 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) /* Writing in SPI mode not implemented. */ if (sd->spi) break; + + if (addr + sd->blk_len > sd->size) { + sd->card_status |= ADDRESS_ERROR; + return sd_r1; + } + sd->state = sd_receivingdata_state; sd->data_start = addr; sd->data_offset = 0; sd->blk_written = 0; - if (sd->data_start + sd->blk_len > sd->size) - sd->card_status |= ADDRESS_ERROR; - if (sd_wp_addr(sd, sd->data_start)) + if (sd_wp_addr(sd, sd->data_start)) { sd->card_status |= WP_VIOLATION; - if (sd->csd[14] & 0x30) + } + if (sd->csd[14] & 0x30) { sd->card_status |= WP_VIOLATION; + } return sd_r1; default: @@ -1619,7 +1687,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd, return sd_illegal; } -static int cmd_valid_while_locked(SDState *sd, SDRequest *req) +static int cmd_valid_while_locked(SDState *sd, const uint8_t cmd) { /* Valid commands in locked state: * basic class (0) @@ -1630,13 +1698,12 @@ static int cmd_valid_while_locked(SDState *sd, SDRequest *req) * Anything else provokes an "illegal command" response. */ if (sd->expecting_acmd) { - return req->cmd == 41 || req->cmd == 42; + return cmd == 41 || cmd == 42; } - if (req->cmd == 16 || req->cmd == 55) { + if (cmd == 16 || cmd == 55) { return 1; } - return sd_cmd_class[req->cmd] == 0 - || sd_cmd_class[req->cmd] == 7; + return sd_cmd_class[cmd] == 0 || sd_cmd_class[cmd] == 7; } int sd_do_command(SDState *sd, SDRequest *req, @@ -1662,7 +1729,7 @@ int sd_do_command(SDState *sd, SDRequest *req, } if (sd->card_status & CARD_IS_LOCKED) { - if (!cmd_valid_while_locked(sd, req)) { + if (!cmd_valid_while_locked(sd, req->cmd)) { sd->card_status |= ILLEGAL_COMMAND; sd->expecting_acmd = false; qemu_log_mask(LOG_GUEST_ERROR, "SD: Card is locked\n"); @@ -1742,7 +1809,7 @@ send_response: } #ifdef DEBUG_SD - qemu_hexdump((const char *)response, stderr, "Response", rsplen); + qemu_hexdump(stderr, "Response", response, rsplen); #endif return rsplen; @@ -1769,7 +1836,7 @@ static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len) #define APP_READ_BLOCK(a, len) memset(sd->data, 0xec, len) #define APP_WRITE_BLOCK(a, len) -void sd_write_data(SDState *sd, uint8_t value) +void sd_write_byte(SDState *sd, uint8_t value) { int i; @@ -1778,7 +1845,7 @@ void sd_write_data(SDState *sd, uint8_t value) if (sd->state != sd_receivingdata_state) { qemu_log_mask(LOG_GUEST_ERROR, - "sd_write_data: not in Receiving-Data state\n"); + "%s: not in Receiving-Data state\n", __func__); return; } @@ -1900,7 +1967,7 @@ void sd_write_data(SDState *sd, uint8_t value) break; default: - qemu_log_mask(LOG_GUEST_ERROR, "sd_write_data: unknown command\n"); + qemu_log_mask(LOG_GUEST_ERROR, "%s: unknown command\n", __func__); break; } } @@ -1919,18 +1986,18 @@ static const uint8_t sd_tuning_block_pattern[SD_TUNING_BLOCK_SIZE] = { 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, }; -uint8_t sd_read_data(SDState *sd) +uint8_t sd_read_byte(SDState *sd) { /* TODO: Append CRCs */ uint8_t ret; - int io_len; + uint32_t io_len; if (!sd->blk || !blk_is_inserted(sd->blk) || !sd->enable) return 0x00; if (sd->state != sd_sendingdata_state) { qemu_log_mask(LOG_GUEST_ERROR, - "sd_read_data: not in Sending-Data state\n"); + "%s: not in Sending-Data state\n", __func__); return 0x00; } @@ -2036,14 +2103,14 @@ uint8_t sd_read_data(SDState *sd) break; default: - qemu_log_mask(LOG_GUEST_ERROR, "sd_read_data: unknown command\n"); + qemu_log_mask(LOG_GUEST_ERROR, "%s: unknown command\n", __func__); return 0x00; } return ret; } -bool sd_data_ready(SDState *sd) +static bool sd_data_ready(SDState *sd) { return sd->state == sd_sendingdata_state; } @@ -2085,12 +2152,36 @@ static void sd_realize(DeviceState *dev, Error **errp) return; } - if (sd->blk && blk_is_read_only(sd->blk)) { - error_setg(errp, "Cannot use read-only drive as SD card"); - return; - } - if (sd->blk) { + int64_t blk_size; + + if (blk_is_read_only(sd->blk)) { + error_setg(errp, "Cannot use read-only drive as SD card"); + return; + } + + blk_size = blk_getlength(sd->blk); + if (blk_size > 0 && !is_power_of_2(blk_size)) { + int64_t blk_size_aligned = pow2ceil(blk_size); + char *blk_size_str; + + blk_size_str = size_to_str(blk_size); + error_setg(errp, "Invalid SD card size: %s", blk_size_str); + g_free(blk_size_str); + + blk_size_str = size_to_str(blk_size_aligned); + error_append_hint(errp, + "SD card size has to be a power of 2, e.g. %s.\n" + "You can resize disk images with" + " 'qemu-img resize '\n" + "(note that this will lose data if you make the" + " image smaller than it currently is).\n", + blk_size_str); + g_free(blk_size_str); + + return; + } + ret = blk_set_perm(sd->blk, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE, BLK_PERM_ALL, errp); if (ret < 0) { @@ -2128,8 +2219,8 @@ static void sd_class_init(ObjectClass *klass, void *data) sc->get_dat_lines = sd_get_dat_lines; sc->get_cmd_line = sd_get_cmd_line; sc->do_command = sd_do_command; - sc->write_data = sd_write_data; - sc->read_data = sd_read_data; + sc->write_byte = sd_write_byte; + sc->read_byte = sd_read_byte; sc->data_ready = sd_data_ready; sc->enable = sd_enable; sc->get_inserted = sd_get_inserted; diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h index e7c8a523b51667fdc8b7549d5e5a5412a0edfce6..e8c753d6d1ee04511aad965c089ef57f15d00a2c 100644 --- a/hw/sd/sdhci-internal.h +++ b/hw/sd/sdhci-internal.h @@ -75,6 +75,7 @@ #define SDHC_CMD_INHIBIT 0x00000001 #define SDHC_DATA_INHIBIT 0x00000002 #define SDHC_DAT_LINE_ACTIVE 0x00000004 +#define SDHC_IMX_CLOCK_GATE_OFF 0x00000080 #define SDHC_DOING_WRITE 0x00000100 #define SDHC_DOING_READ 0x00000200 #define SDHC_SPACE_AVAILABLE 0x00000400 @@ -289,7 +290,10 @@ extern const VMStateDescription sdhci_vmstate; #define ESDHC_MIX_CTRL 0x48 + #define ESDHC_VENDOR_SPEC 0xc0 +#define ESDHC_IMX_FRC_SDCLK_ON (1 << 8) + #define ESDHC_DLL_CTRL 0x60 #define ESDHC_TUNING_CTRL 0xcc @@ -326,6 +330,7 @@ extern const VMStateDescription sdhci_vmstate; #define DEFINE_SDHCI_COMMON_PROPERTIES(_state) \ DEFINE_PROP_UINT8("sd-spec-version", _state, sd_spec_version, 2), \ DEFINE_PROP_UINT8("uhs", _state, uhs_mode, UHS_NOT_SUPPORTED), \ + DEFINE_PROP_UINT8("vendor", _state, vendor, SDHCI_VENDOR_NONE), \ \ /* Capabilities registers provide information on supported * features of this specific host controller implementation */ \ diff --git a/hw/sd/sdhci-pci.c b/hw/sd/sdhci-pci.c index 4f5977d487ee80f729ab2b67694ba0e3e6fdef28..c737c8b930e259b5fb0d61191dafd08027cde83e 100644 --- a/hw/sd/sdhci-pci.c +++ b/hw/sd/sdhci-pci.c @@ -29,13 +29,12 @@ static Property sdhci_pci_properties[] = { static void sdhci_pci_realize(PCIDevice *dev, Error **errp) { + ERRP_GUARD(); SDHCIState *s = PCI_SDHCI(dev); - Error *local_err = NULL; sdhci_initfn(s); - sdhci_common_realize(s, &local_err); - if (local_err) { - error_propagate(errp, local_err); + sdhci_common_realize(s, errp); + if (*errp) { return; } diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 1b75d7bab93ca2df714dee1ea02bf80af3a8085d..2f8b74a84f75ae72153dbffab8c1d256a64c7c92 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -1,6 +1,8 @@ /* * SD Association Host Standard Specification v2.0 controller emulation * + * Datasheet: PartA2_SD_Host_Controller_Simplified_Specification_Ver2.00.pdf + * * Copyright (c) 2011 Samsung Electronics Co., Ltd. * Mitsyanko Igor * Peter A.G. Crosthwaite @@ -37,9 +39,12 @@ #include "qemu/log.h" #include "qemu/module.h" #include "trace.h" +#include "qom/object.h" #define TYPE_SDHCI_BUS "sdhci-bus" -#define SDHCI_BUS(obj) OBJECT_CHECK(SDBus, (obj), TYPE_SDHCI_BUS) +/* This is reusing the SDBus typedef from SD_BUS */ +DECLARE_INSTANCE_CHECKER(SDBus, SDHCI_BUS, + TYPE_SDHCI_BUS) #define MASKED_WRITE(reg, mask, val) (reg = (reg & (mask)) | (val)) @@ -213,9 +218,14 @@ static uint8_t sdhci_slotint(SDHCIState *s) ((s->norintsts & SDHC_NIS_REMOVE) && (s->wakcon & SDHC_WKUP_ON_RMV)); } -static inline void sdhci_update_irq(SDHCIState *s) +/* Return true if IRQ was pending and delivered */ +static bool sdhci_update_irq(SDHCIState *s) { - qemu_set_irq(s->irq, sdhci_slotint(s)); + bool pending = sdhci_slotint(s); + + qemu_set_irq(s->irq, pending); + + return pending; } static void sdhci_raise_insertion_irq(void *opaque) @@ -399,8 +409,6 @@ static void sdhci_end_transfer(SDHCIState *s) /* Fill host controller's read buffer with BLKSIZE bytes of data from card */ static void sdhci_read_block_from_card(SDHCIState *s) { - int index = 0; - uint8_t data; const uint16_t blk_size = s->blksize & BLOCK_SIZE_MASK; if ((s->trnmod & SDHC_TRNS_MULTI) && @@ -408,12 +416,9 @@ static void sdhci_read_block_from_card(SDHCIState *s) return; } - for (index = 0; index < blk_size; index++) { - data = sdbus_read_data(&s->sdbus); - if (!FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) { - /* Device is not in tuning */ - s->fifo_buffer[index] = data; - } + if (!FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) { + /* Device is not in tuning */ + sdbus_read_data(&s->sdbus, s->fifo_buffer, blk_size); } if (FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) { @@ -496,8 +501,6 @@ static uint32_t sdhci_read_dataport(SDHCIState *s, unsigned size) /* Write data from host controller FIFO to card */ static void sdhci_write_block_to_card(SDHCIState *s) { - int index = 0; - if (s->prnsts & SDHC_SPACE_AVAILABLE) { if (s->norintstsen & SDHC_NISEN_WBUFRDY) { s->norintsts |= SDHC_NIS_WBUFRDY; @@ -514,9 +517,7 @@ static void sdhci_write_block_to_card(SDHCIState *s) } } - for (index = 0; index < (s->blksize & BLOCK_SIZE_MASK); index++) { - sdbus_write_data(&s->sdbus, s->fifo_buffer[index]); - } + sdbus_write_data(&s->sdbus, s->fifo_buffer, s->blksize & BLOCK_SIZE_MASK); /* Next data can be written through BUFFER DATORT register */ s->prnsts |= SDHC_SPACE_AVAILABLE; @@ -578,7 +579,7 @@ static void sdhci_write_dataport(SDHCIState *s, uint32_t value, unsigned size) static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s) { bool page_aligned = false; - unsigned int n, begin; + unsigned int begin; const uint16_t block_size = s->blksize & BLOCK_SIZE_MASK; uint32_t boundary_chk = 1 << (((s->blksize & ~BLOCK_SIZE_MASK) >> 12) + 12); uint32_t boundary_count = boundary_chk - (s->sdmasysad % boundary_chk); @@ -600,9 +601,7 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s) SDHC_DAT_LINE_ACTIVE; while (s->blkcnt) { if (s->data_count == 0) { - for (n = 0; n < block_size; n++) { - s->fifo_buffer[n] = sdbus_read_data(&s->sdbus); - } + sdbus_read_data(&s->sdbus, s->fifo_buffer, block_size); } begin = s->data_count; if (((boundary_count + begin) < block_size) && page_aligned) { @@ -641,9 +640,7 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s) &s->fifo_buffer[begin], s->data_count - begin); s->sdmasysad += s->data_count - begin; if (s->data_count == block_size) { - for (n = 0; n < block_size; n++) { - sdbus_write_data(&s->sdbus, s->fifo_buffer[n]); - } + sdbus_write_data(&s->sdbus, s->fifo_buffer, block_size); s->data_count = 0; if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) { s->blkcnt--; @@ -668,19 +665,14 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s) /* single block SDMA transfer */ static void sdhci_sdma_transfer_single_block(SDHCIState *s) { - int n; uint32_t datacnt = s->blksize & BLOCK_SIZE_MASK; if (s->trnmod & SDHC_TRNS_READ) { - for (n = 0; n < datacnt; n++) { - s->fifo_buffer[n] = sdbus_read_data(&s->sdbus); - } + sdbus_read_data(&s->sdbus, s->fifo_buffer, datacnt); dma_memory_write(s->dma_as, s->sdmasysad, s->fifo_buffer, datacnt); } else { dma_memory_read(s->dma_as, s->sdmasysad, s->fifo_buffer, datacnt); - for (n = 0; n < datacnt; n++) { - sdbus_write_data(&s->sdbus, s->fifo_buffer[n]); - } + sdbus_write_data(&s->sdbus, s->fifo_buffer, datacnt); } s->blkcnt--; @@ -739,11 +731,17 @@ static void get_adma_description(SDHCIState *s, ADMADescr *dscr) static void sdhci_do_adma(SDHCIState *s) { - unsigned int n, begin, length; + unsigned int begin, length; const uint16_t block_size = s->blksize & BLOCK_SIZE_MASK; ADMADescr dscr = {}; int i; + if (s->trnmod & SDHC_TRNS_BLK_CNT_EN && !s->blkcnt) { + /* Stop Multiple Transfer */ + sdhci_end_transfer(s); + return; + } + for (i = 0; i < SDHC_ADMA_DESCS_PER_DELAY; ++i) { s->admaerr &= ~SDHC_ADMAERR_LENGTH_MISMATCH; @@ -769,13 +767,10 @@ static void sdhci_do_adma(SDHCIState *s) switch (dscr.attr & SDHC_ADMA_ATTR_ACT_MASK) { case SDHC_ADMA_ATTR_ACT_TRAN: /* data transfer */ - if (s->trnmod & SDHC_TRNS_READ) { while (length) { if (s->data_count == 0) { - for (n = 0; n < block_size; n++) { - s->fifo_buffer[n] = sdbus_read_data(&s->sdbus); - } + sdbus_read_data(&s->sdbus, s->fifo_buffer, block_size); } begin = s->data_count; if ((length + begin) < block_size) { @@ -814,9 +809,7 @@ static void sdhci_do_adma(SDHCIState *s) s->data_count - begin); dscr.addr += s->data_count - begin; if (s->data_count == block_size) { - for (n = 0; n < block_size; n++) { - sdbus_write_data(&s->sdbus, s->fifo_buffer[n]); - } + sdbus_write_data(&s->sdbus, s->fifo_buffer, block_size); s->data_count = 0; if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) { s->blkcnt--; @@ -844,7 +837,10 @@ static void sdhci_do_adma(SDHCIState *s) s->norintsts |= SDHC_NIS_DMA; } - sdhci_update_irq(s); + if (sdhci_update_irq(s) && !(dscr.attr & SDHC_ADMA_ATTR_END)) { + /* IRQ delivered, reschedule current transfer */ + break; + } } /* ADMA transfer terminates if blkcnt == 0 or by END attribute */ @@ -960,11 +956,21 @@ sdhci_buff_access_is_sequential(SDHCIState *s, unsigned byte_num) return true; } +static void sdhci_resume_pending_transfer(SDHCIState *s) +{ + timer_del(s->transfer_timer); + sdhci_data_transfer(s); +} + static uint64_t sdhci_read(void *opaque, hwaddr offset, unsigned size) { SDHCIState *s = (SDHCIState *)opaque; uint32_t ret = 0; + if (timer_pending(s->transfer_timer)) { + sdhci_resume_pending_transfer(s); + } + switch (offset & ~0x3) { case SDHC_SYSAD: ret = s->sdmasysad; @@ -1108,6 +1114,10 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) uint32_t value = val; value <<= shift; + if (timer_pending(s->transfer_timer)) { + sdhci_resume_pending_transfer(s); + } + switch (offset & ~0x3) { case SDHC_SYSAD: s->sdmasysad = (s->sdmasysad & mask) | value; @@ -1124,14 +1134,14 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) break; case SDHC_BLKSIZE: if (!TRANSFERRING_DATA(s->prnsts)) { - MASKED_WRITE(s->blksize, mask, value); + MASKED_WRITE(s->blksize, mask, extract32(value, 0, 12)); MASKED_WRITE(s->blkcnt, mask >> 16, value >> 16); } /* Limit block size to the maximum buffer size */ if (extract32(s->blksize, 0, 12) > s->buf_maxsz) { qemu_log_mask(LOG_GUEST_ERROR, "%s: Size 0x%x is larger than " - "the maximum buffer 0x%x", __func__, s->blksize, + "the maximum buffer 0x%x\n", __func__, s->blksize, s->buf_maxsz); s->blksize = deposit32(s->blksize, 0, 12, s->buf_maxsz); @@ -1288,7 +1298,7 @@ static const MemoryRegionOps sdhci_mmio_ops = { static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp) { - Error *local_err = NULL; + ERRP_GUARD(); switch (s->sd_spec_version) { case 2 ... 3: @@ -1299,9 +1309,8 @@ static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp) } s->version = (SDHC_HCVER_VENDOR << 8) | (s->sd_spec_version - 1); - sdhci_check_capareg(s, &local_err); - if (local_err) { - error_propagate(errp, local_err); + sdhci_check_capareg(s, errp); + if (*errp) { return; } } @@ -1332,11 +1341,10 @@ void sdhci_uninitfn(SDHCIState *s) void sdhci_common_realize(SDHCIState *s, Error **errp) { - Error *local_err = NULL; + ERRP_GUARD(); - sdhci_init_readonly_registers(s, &local_err); - if (local_err) { - error_propagate(errp, local_err); + sdhci_init_readonly_registers(s, errp); + if (*errp) { return; } s->buf_maxsz = sdhci_get_fifolen(s); @@ -1456,13 +1464,12 @@ static void sdhci_sysbus_finalize(Object *obj) static void sdhci_sysbus_realize(DeviceState *dev, Error **errp) { + ERRP_GUARD(); SDHCIState *s = SYSBUS_SDHCI(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - Error *local_err = NULL; - sdhci_common_realize(s, &local_err); - if (local_err) { - error_propagate(errp, local_err); + sdhci_common_realize(s, errp); + if (*errp) { return; } @@ -1569,11 +1576,13 @@ static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size) } break; + case ESDHC_VENDOR_SPEC: + ret = s->vendor_spec; + break; case ESDHC_DLL_CTRL: case ESDHC_TUNE_CTRL_STATUS: case ESDHC_UNDOCUMENTED_REG27: case ESDHC_TUNING_CTRL: - case ESDHC_VENDOR_SPEC: case ESDHC_MIX_CTRL: case ESDHC_WTMK_LVL: ret = 0; @@ -1596,7 +1605,21 @@ usdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) case ESDHC_UNDOCUMENTED_REG27: case ESDHC_TUNING_CTRL: case ESDHC_WTMK_LVL: + break; + case ESDHC_VENDOR_SPEC: + s->vendor_spec = value; + switch (s->vendor) { + case SDHCI_VENDOR_IMX: + if (value & ESDHC_IMX_FRC_SDCLK_ON) { + s->prnsts &= ~SDHC_IMX_CLOCK_GATE_OFF; + } else { + s->prnsts |= SDHC_IMX_CLOCK_GATE_OFF; + } + break; + default: + break; + } break; case SDHC_HOSTCTL: diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c index 829797b5974749a1dedde45eca5ac98903bfb60a..14c8e04a890abc02010f05800f116d0b5db71cd1 100644 --- a/hw/sd/ssi-sd.c +++ b/hw/sd/ssi-sd.c @@ -18,6 +18,7 @@ #include "hw/sd/sd.h" #include "qapi/error.h" #include "qemu/module.h" +#include "qom/object.h" //#define DEBUG_SSI_SD 1 @@ -40,7 +41,7 @@ typedef enum { SSI_SD_DATA_READ, } ssi_sd_mode; -typedef struct { +struct ssi_sd_state { SSISlave ssidev; uint32_t mode; int cmd; @@ -50,10 +51,10 @@ typedef struct { int32_t response_pos; int32_t stopping; SDBus sdbus; -} ssi_sd_state; +}; #define TYPE_SSI_SD "ssi-sd" -#define SSI_SD(obj) OBJECT_CHECK(ssi_sd_state, (obj), TYPE_SSI_SD) +OBJECT_DECLARE_SIMPLE_TYPE(ssi_sd_state, SSI_SD) /* State word bits. */ #define SSI_SDR_LOCKED 0x0001 @@ -74,7 +75,7 @@ typedef struct { static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val) { - ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, dev); + ssi_sd_state *s = SSI_SD(dev); /* Special case: allow CMD12 (STOP TRANSMISSION) while reading data. */ if (s->mode == SSI_SD_DATA_READ && val == 0x4d) { @@ -190,7 +191,7 @@ static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val) s->mode = SSI_SD_DATA_READ; return 0xfe; case SSI_SD_DATA_READ: - val = sdbus_read_data(&s->sdbus); + val = sdbus_read_byte(&s->sdbus); if (!sdbus_data_ready(&s->sdbus)) { DPRINTF("Data read end\n"); s->mode = SSI_SD_CMD; @@ -241,10 +242,10 @@ static const VMStateDescription vmstate_ssi_sd = { static void ssi_sd_realize(SSISlave *d, Error **errp) { - ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, d); + ERRP_GUARD(); + ssi_sd_state *s = SSI_SD(d); DeviceState *carddev; DriveInfo *dinfo; - Error *err = NULL; qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), TYPE_SD_BUS, DEVICE(d), "sd-bus"); @@ -252,28 +253,26 @@ static void ssi_sd_realize(SSISlave *d, Error **errp) /* Create and plug in the sd card */ /* FIXME use a qdev drive property instead of drive_get_next() */ dinfo = drive_get_next(IF_SD); - carddev = qdev_create(BUS(&s->sdbus), TYPE_SD_CARD); + carddev = qdev_new(TYPE_SD_CARD); if (dinfo) { - qdev_prop_set_drive(carddev, "drive", blk_by_legacy_dinfo(dinfo), &err); - if (err) { + if (!qdev_prop_set_drive_err(carddev, "drive", + blk_by_legacy_dinfo(dinfo), errp)) { goto fail; } } - object_property_set_bool(OBJECT(carddev), true, "spi", &err); - if (err) { + if (!object_property_set_bool(OBJECT(carddev), "spi", true, errp)) { goto fail; } - object_property_set_bool(OBJECT(carddev), true, "realized", &err); - if (err) { + if (!qdev_realize_and_unref(carddev, BUS(&s->sdbus), errp)) { goto fail; } return; fail: - error_propagate_prepend(errp, err, "failed to init SD card: "); + error_prepend(errp, "failed to init SD card: "); } static void ssi_sd_reset(DeviceState *dev) diff --git a/hw/sd/trace-events b/hw/sd/trace-events index 5f09d32eb2c8e49aaf57e88c45e011687be3fe04..4140e4854030a4d81ac9f0452958493b19bacce5 100644 --- a/hw/sd/trace-events +++ b/hw/sd/trace-events @@ -46,13 +46,13 @@ sdcard_reset(void) "" sdcard_set_blocklen(uint16_t length) "0x%03x" sdcard_inserted(bool readonly) "read_only: %u" sdcard_ejected(void) "" -sdcard_erase(void) "" +sdcard_erase(uint32_t first, uint32_t last) "addr first 0x%" PRIx32" last 0x%" PRIx32 sdcard_lock(void) "" sdcard_unlock(void) "" sdcard_read_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x" sdcard_write_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x" sdcard_write_data(const char *proto, const char *cmd_desc, uint8_t cmd, uint8_t value) "%s %20s/ CMD%02d value 0x%02x" -sdcard_read_data(const char *proto, const char *cmd_desc, uint8_t cmd, int length) "%s %20s/ CMD%02d len %d" +sdcard_read_data(const char *proto, const char *cmd_desc, uint8_t cmd, uint32_t length) "%s %20s/ CMD%02d len %" PRIu32 sdcard_set_voltage(uint16_t millivolts) "%u mV" # milkymist-memcard.c @@ -62,3 +62,13 @@ milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value # pxa2xx_mmci.c pxa2xx_mmci_read(uint8_t size, uint32_t addr, uint32_t value) "size %d addr 0x%02x value 0x%08x" pxa2xx_mmci_write(uint8_t size, uint32_t addr, uint32_t value) "size %d addr 0x%02x value 0x%08x" + +# pl181.c +pl181_command_send(uint8_t cmd, uint32_t arg) "sending CMD%02d arg 0x%08" PRIx32 +pl181_command_sent(void) "command sent" +pl181_command_response_pending(void) "response received" +pl181_command_timeout(void) "command timeouted" +pl181_fifo_push(uint32_t data) "FIFO push 0x%08" PRIx32 +pl181_fifo_pop(uint32_t data) "FIFO pop 0x%08" PRIx32 +pl181_fifo_transfer_complete(void) "FIFO transfer complete" +pl181_data_engine_idle(void) "data engine idle" diff --git a/hw/sd/trace.h b/hw/sd/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..f3d0c5856341c4c2750d0f49fccc0cab3a55bc6d --- /dev/null +++ b/hw/sd/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_sd.h" diff --git a/hw/semihosting/Makefile.objs b/hw/semihosting/Makefile.objs deleted file mode 100644 index 4ad47c05c060b4399e30a947f3e5bce5e1798f61..0000000000000000000000000000000000000000 --- a/hw/semihosting/Makefile.objs +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_SEMIHOSTING) += config.o -obj-$(CONFIG_SEMIHOSTING) += console.o diff --git a/hw/semihosting/console.c b/hw/semihosting/console.c index 6346bd7f506effa84777589f567dbf2024e6302a..9b4fee92602c6b1e2321ccfe327bb023178f918d 100644 --- a/hw/semihosting/console.c +++ b/hw/semihosting/console.c @@ -23,7 +23,6 @@ #include "exec/exec-all.h" #include "qemu/log.h" #include "chardev/char.h" -#include #include "chardev/char-fe.h" #include "sysemu/sysemu.h" #include "qemu/main-loop.h" @@ -53,7 +52,9 @@ static GString *copy_user_string(CPUArchState *env, target_ulong addr) do { if (cpu_memory_rw_debug(cpu, addr++, &c, 1, 0) == 0) { - s = g_string_append_c(s, c); + if (c) { + s = g_string_append_c(s, c); + } } else { qemu_log_mask(LOG_GUEST_ERROR, "%s: passed inaccessible address " TARGET_FMT_lx, diff --git a/hw/semihosting/meson.build b/hw/semihosting/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..f40ac574c440d2dce2dc244ecbfe9e7370c09fe7 --- /dev/null +++ b/hw/semihosting/meson.build @@ -0,0 +1,4 @@ +specific_ss.add(when: 'CONFIG_SEMIHOSTING', if_true: files( + 'config.c', + 'console.c', +)) diff --git a/hw/sh4/Makefile.objs b/hw/sh4/Makefile.objs deleted file mode 100644 index 2a707f9473c6097e73d3152f124461280faefe93..0000000000000000000000000000000000000000 --- a/hw/sh4/Makefile.objs +++ /dev/null @@ -1,4 +0,0 @@ -obj-y += sh7750.o sh7750_regnames.o -obj-y += sh_pci.o -obj-$(CONFIG_R2D) += r2d.o -obj-$(CONFIG_SHIX) += shix.o diff --git a/hw/sh4/meson.build b/hw/sh4/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..303c0f4287961670034137b7ab1adeadd2802997 --- /dev/null +++ b/hw/sh4/meson.build @@ -0,0 +1,10 @@ +sh4_ss = ss.source_set() +sh4_ss.add(files( + 'sh7750.c', + 'sh7750_regnames.c', + 'sh_pci.c' +)) +sh4_ss.add(when: 'CONFIG_R2D', if_true: files('r2d.c')) +sh4_ss.add(when: 'CONFIG_SHIX', if_true: files('shix.c')) + +hw_arch += {'sh4': sh4_ss} diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c index 72bb5285cc7d23400b9276b1c1d8edbb69c67d7b..443820901d4b036930f549da4fcddb2309fb3a13 100644 --- a/hw/sh4/r2d.c +++ b/hw/sh4/r2d.c @@ -257,9 +257,9 @@ static void r2d_init(MachineState *machine) s = sh7750_init(cpu, address_space_mem); irq = r2d_fpga_init(address_space_mem, 0x04000000, sh7750_irl(s)); - dev = qdev_create(NULL, "sh_pci"); + dev = qdev_new("sh_pci"); busdev = SYS_BUS_DEVICE(dev); - qdev_init_nofail(dev); + sysbus_realize_and_unref(busdev, &error_fatal); pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci")); sysbus_mmio_map(busdev, 0, P4ADDR(0x1e200000)); sysbus_mmio_map(busdev, 1, A7ADDR(0x1e200000)); @@ -268,23 +268,23 @@ static void r2d_init(MachineState *machine) sysbus_connect_irq(busdev, 2, irq[PCI_INTC]); sysbus_connect_irq(busdev, 3, irq[PCI_INTD]); - dev = qdev_create(NULL, "sysbus-sm501"); + dev = qdev_new("sysbus-sm501"); busdev = SYS_BUS_DEVICE(dev); qdev_prop_set_uint32(dev, "vram-size", SM501_VRAM_SIZE); qdev_prop_set_uint32(dev, "base", 0x10000000); qdev_prop_set_chr(dev, "chardev", serial_hd(2)); - qdev_init_nofail(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, 0x10000000); sysbus_mmio_map(busdev, 1, 0x13e00000); sysbus_connect_irq(busdev, 0, irq[SM501]); /* onboard CF (True IDE mode, Master only). */ dinfo = drive_get(IF_IDE, 0, 0); - dev = qdev_create(NULL, "mmio-ide"); + dev = qdev_new("mmio-ide"); busdev = SYS_BUS_DEVICE(dev); sysbus_connect_irq(busdev, 0, irq[CF_IDE]); qdev_prop_set_uint32(dev, "shift", 1); - qdev_init_nofail(dev); + sysbus_realize_and_unref(busdev, &error_fatal); sysbus_mmio_map(busdev, 0, 0x14001000); sysbus_mmio_map(busdev, 1, 0x1400080c); mmio_ide_init_drives(dev, dinfo, NULL); diff --git a/hw/sh4/sh7750.c b/hw/sh4/sh7750.c index d660714443e3623e769f444c8ca80475048ed9a5..f8ac3ec6e3289acf17690c0da9a406252e4bd421 100644 --- a/hw/sh4/sh7750.c +++ b/hw/sh4/sh7750.c @@ -30,6 +30,7 @@ #include "sh7750_regs.h" #include "sh7750_regnames.h" #include "hw/sh4/sh_intc.h" +#include "hw/timer/tmu012.h" #include "cpu.h" #include "exec/exec-all.h" diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c index 0a3e86f9493cd69f0686863c78d2a839c5948140..73d2d0bccb0e6ad067c091c02ed96562ee97de33 100644 --- a/hw/sh4/sh_pci.c +++ b/hw/sh4/sh_pci.c @@ -31,13 +31,13 @@ #include "qemu/bswap.h" #include "qemu/module.h" #include "exec/address-spaces.h" +#include "qom/object.h" #define TYPE_SH_PCI_HOST_BRIDGE "sh_pci" -#define SH_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(SHPCIState, (obj), TYPE_SH_PCI_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(SHPCIState, SH_PCI_HOST_BRIDGE) -typedef struct SHPCIState { +struct SHPCIState { PCIHostState parent_obj; PCIDevice *dev; @@ -48,7 +48,7 @@ typedef struct SHPCIState { uint32_t par; uint32_t mbr; uint32_t iobr; -} SHPCIState; +}; static void sh_pci_reg_write (void *p, hwaddr addr, uint64_t val, unsigned size) diff --git a/hw/smbios/Makefile.objs b/hw/smbios/Makefile.objs deleted file mode 100644 index 23bb2bac0752fafe7f3aa10645d997e2b850aef2..0000000000000000000000000000000000000000 --- a/hw/smbios/Makefile.objs +++ /dev/null @@ -1,10 +0,0 @@ -ifeq ($(CONFIG_SMBIOS),y) -common-obj-y += smbios.o -common-obj-$(CONFIG_IPMI) += smbios_type_38.o -common-obj-$(call lnot,$(CONFIG_IPMI)) += smbios_type_38-stub.o -else -common-obj-y += smbios-stub.o -endif - -common-obj-$(CONFIG_ALL) += smbios-stub.o -common-obj-$(CONFIG_ALL) += smbios_type_38-stub.o diff --git a/hw/smbios/meson.build b/hw/smbios/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..9e762c7108c3be4aa55c06684ab534d72b308fe3 --- /dev/null +++ b/hw/smbios/meson.build @@ -0,0 +1,13 @@ +smbios_ss = ss.source_set() +smbios_ss.add(files('smbios.c')) +smbios_ss.add(when: 'CONFIG_IPMI', + if_true: files('smbios_type_38.c'), + if_false: files('smbios_type_38-stub.c')) + +softmmu_ss.add_all(when: 'CONFIG_SMBIOS', if_true: smbios_ss) +softmmu_ss.add(when: 'CONFIG_SMBIOS', if_false: files('smbios-stub.c')) + +softmmu_ss.add(when: 'CONFIG_ALL', if_true: files( + 'smbios-stub.c', + 'smbios_type_38-stub.c', +)) diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c index ffd98727ee9e503dfce5e5c922415226998d7c42..6a3d39793bc9dd13f6c6cc8c08e4453fea69e28c 100644 --- a/hw/smbios/smbios.c +++ b/hw/smbios/smbios.c @@ -92,13 +92,25 @@ static struct { const char *manufacturer, *version, *serial, *asset, *sku; } type3; +/* + * SVVP requires max_speed and current_speed to be set and not being + * 0 which counts as unknown (SMBIOS 3.1.0/Table 21). Set the + * default value to 2000MHz as we did before. + */ +#define DEFAULT_CPU_SPEED 2000 + static struct { const char *sock_pfx, *manufacturer, *version, *serial, *asset, *part; -} type4; + uint64_t max_speed; + uint64_t current_speed; +} type4 = { + .max_speed = DEFAULT_CPU_SPEED, + .current_speed = DEFAULT_CPU_SPEED +}; static struct { size_t nvalues; - const char **values; + char **values; } type11; static struct { @@ -272,6 +284,14 @@ static const QemuOptDesc qemu_smbios_type4_opts[] = { .name = "version", .type = QEMU_OPT_STRING, .help = "version number", + },{ + .name = "max-speed", + .type = QEMU_OPT_NUMBER, + .help = "max speed in MHz", + },{ + .name = "current-speed", + .type = QEMU_OPT_NUMBER, + .help = "speed at system boot in MHz", },{ .name = "serial", .type = QEMU_OPT_STRING, @@ -294,6 +314,11 @@ static const QemuOptDesc qemu_smbios_type11_opts[] = { .type = QEMU_OPT_STRING, .help = "OEM string data", }, + { + .name = "path", + .type = QEMU_OPT_STRING, + .help = "OEM string data from file", + }, }; static const QemuOptDesc qemu_smbios_type17_opts[] = { @@ -340,6 +365,13 @@ static void smbios_register_config(void) opts_init(smbios_register_config); +/* + * The SMBIOS 2.1 "structure table length" field in the + * entry point uses a 16-bit integer, so we're limited + * in total table size + */ +#define SMBIOS_21_MAX_TABLES_LEN 0xffff + static void smbios_validate_table(MachineState *ms) { uint32_t expect_t4_count = smbios_legacy ? @@ -350,6 +382,13 @@ static void smbios_validate_table(MachineState *ms) expect_t4_count, smbios_type4_count); exit(1); } + + if (smbios_ep_type == SMBIOS_ENTRY_POINT_21 && + smbios_tables_len > SMBIOS_21_MAX_TABLES_LEN) { + error_report("SMBIOS 2.1 table length %zu exceeds %d", + smbios_tables_len, SMBIOS_21_MAX_TABLES_LEN); + exit(1); + } } @@ -586,9 +625,8 @@ static void smbios_build_type_4_table(MachineState *ms, unsigned instance) SMBIOS_TABLE_SET_STR(4, processor_version_str, type4.version); t->voltage = 0; t->external_clock = cpu_to_le16(0); /* Unknown */ - /* SVVP requires max_speed and current_speed to not be unknown. */ - t->max_speed = cpu_to_le16(2000); /* 2000 MHz */ - t->current_speed = cpu_to_le16(2000); /* 2000 MHz */ + t->max_speed = cpu_to_le16(type4.max_speed); + t->current_speed = cpu_to_le16(type4.current_speed); t->status = 0x41; /* Socket populated, CPU enabled */ t->processor_upgrade = 0x01; /* Other */ t->l1_cache_handle = cpu_to_le16(0xFFFF); /* N/A */ @@ -622,6 +660,8 @@ static void smbios_build_type_11_table(void) for (i = 0; i < type11.nvalues; i++) { SMBIOS_TABLE_SET_STR_LIST(11, type11.values[i]); + g_free(type11.values[i]); + type11.values[i] = NULL; } SMBIOS_BUILD_TABLE_POST; @@ -921,9 +961,8 @@ static void save_opt(const char **dest, QemuOpts *opts, const char *name) struct opt_list { - const char *name; size_t *ndest; - const char ***dest; + char ***dest; }; static int save_opt_one(void *opaque, @@ -932,28 +971,66 @@ static int save_opt_one(void *opaque, { struct opt_list *opt = opaque; - if (!g_str_equal(name, opt->name)) { - return 0; + if (g_str_equal(name, "path")) { + g_autoptr(GByteArray) data = g_byte_array_new(); + g_autofree char *buf = g_new(char, 4096); + ssize_t ret; + int fd = qemu_open(value, O_RDONLY, errp); + if (fd < 0) { + return -1; + } + + while (1) { + ret = read(fd, buf, 4096); + if (ret == 0) { + break; + } + if (ret < 0) { + error_setg(errp, "Unable to read from %s: %s", + value, strerror(errno)); + qemu_close(fd); + return -1; + } + if (memchr(buf, '\0', ret)) { + error_setg(errp, "NUL in OEM strings value in %s", value); + qemu_close(fd); + return -1; + } + g_byte_array_append(data, (guint8 *)buf, ret); + } + + qemu_close(fd); + + *opt->dest = g_renew(char *, *opt->dest, (*opt->ndest) + 1); + (*opt->dest)[*opt->ndest] = (char *)g_byte_array_free(data, FALSE); + (*opt->ndest)++; + data = NULL; + } else if (g_str_equal(name, "value")) { + *opt->dest = g_renew(char *, *opt->dest, (*opt->ndest) + 1); + (*opt->dest)[*opt->ndest] = g_strdup(value); + (*opt->ndest)++; + } else if (!g_str_equal(name, "type")) { + error_setg(errp, "Unexpected option %s", name); + return -1; } - *opt->dest = g_renew(const char *, *opt->dest, (*opt->ndest) + 1); - (*opt->dest)[*opt->ndest] = value; - (*opt->ndest)++; return 0; } -static void save_opt_list(size_t *ndest, const char ***dest, - QemuOpts *opts, const char *name) +static bool save_opt_list(size_t *ndest, char ***dest, QemuOpts *opts, + Error **errp) { struct opt_list opt = { - name, ndest, dest, + ndest, dest, }; - qemu_opt_foreach(opts, save_opt_one, &opt, NULL); + if (!qemu_opt_foreach(opts, save_opt_one, &opt, errp)) { + return false; + } + return true; } void smbios_entry_add(QemuOpts *opts, Error **errp) { - Error *err = NULL; const char *val; assert(!smbios_immutable); @@ -964,9 +1041,7 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) int size; struct smbios_table *table; /* legacy mode only */ - qemu_opts_validate(opts, qemu_smbios_file_opts, &err); - if (err) { - error_propagate(errp, err); + if (!qemu_opts_validate(opts, qemu_smbios_file_opts, errp)) { return; } @@ -1051,9 +1126,7 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) switch (type) { case 0: - qemu_opts_validate(opts, qemu_smbios_type0_opts, &err); - if (err) { - error_propagate(errp, err); + if (!qemu_opts_validate(opts, qemu_smbios_type0_opts, errp)) { return; } save_opt(&type0.vendor, opts, "vendor"); @@ -1071,9 +1144,7 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) } return; case 1: - qemu_opts_validate(opts, qemu_smbios_type1_opts, &err); - if (err) { - error_propagate(errp, err); + if (!qemu_opts_validate(opts, qemu_smbios_type1_opts, errp)) { return; } save_opt(&type1.manufacturer, opts, "manufacturer"); @@ -1093,9 +1164,7 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) } return; case 2: - qemu_opts_validate(opts, qemu_smbios_type2_opts, &err); - if (err) { - error_propagate(errp, err); + if (!qemu_opts_validate(opts, qemu_smbios_type2_opts, errp)) { return; } save_opt(&type2.manufacturer, opts, "manufacturer"); @@ -1106,9 +1175,7 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) save_opt(&type2.location, opts, "location"); return; case 3: - qemu_opts_validate(opts, qemu_smbios_type3_opts, &err); - if (err) { - error_propagate(errp, err); + if (!qemu_opts_validate(opts, qemu_smbios_type3_opts, errp)) { return; } save_opt(&type3.manufacturer, opts, "manufacturer"); @@ -1118,9 +1185,7 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) save_opt(&type3.sku, opts, "sku"); return; case 4: - qemu_opts_validate(opts, qemu_smbios_type4_opts, &err); - if (err) { - error_propagate(errp, err); + if (!qemu_opts_validate(opts, qemu_smbios_type4_opts, errp)) { return; } save_opt(&type4.sock_pfx, opts, "sock_pfx"); @@ -1129,19 +1194,26 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) save_opt(&type4.serial, opts, "serial"); save_opt(&type4.asset, opts, "asset"); save_opt(&type4.part, opts, "part"); + type4.max_speed = qemu_opt_get_number(opts, "max-speed", + DEFAULT_CPU_SPEED); + type4.current_speed = qemu_opt_get_number(opts, "current-speed", + DEFAULT_CPU_SPEED); + if (type4.max_speed > UINT16_MAX || + type4.current_speed > UINT16_MAX) { + error_setg(errp, "SMBIOS CPU speed is too large (> %d)", + UINT16_MAX); + } return; case 11: - qemu_opts_validate(opts, qemu_smbios_type11_opts, &err); - if (err) { - error_propagate(errp, err); + if (!qemu_opts_validate(opts, qemu_smbios_type11_opts, errp)) { + return; + } + if (!save_opt_list(&type11.nvalues, &type11.values, opts, errp)) { return; } - save_opt_list(&type11.nvalues, &type11.values, opts, "value"); return; case 17: - qemu_opts_validate(opts, qemu_smbios_type17_opts, &err); - if (err) { - error_propagate(errp, err); + if (!qemu_opts_validate(opts, qemu_smbios_type17_opts, errp)) { return; } save_opt(&type17.loc_pfx, opts, "loc_pfx"); diff --git a/hw/sparc/Kconfig b/hw/sparc/Kconfig index 22aff2f5b766cd062fa8988c1e05ec41e5dadc2f..91805afab66f2a1dac4cb33f34cc3bbedb6aa4ea 100644 --- a/hw/sparc/Kconfig +++ b/hw/sparc/Kconfig @@ -5,6 +5,7 @@ config SUN4M select CS4231 select ECCMEMCTL select EMPTY_SLOT + select UNIMP select ESCC select ESP select FDC diff --git a/hw/sparc/Makefile.objs b/hw/sparc/Makefile.objs deleted file mode 100644 index d57e33f83ea2e12b8dc433b7231eb31da9dd98bc..0000000000000000000000000000000000000000 --- a/hw/sparc/Makefile.objs +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_SUN4M) += sun4m_iommu.o -obj-$(CONFIG_SUN4M) += sun4m.o -obj-$(CONFIG_LEON3) += leon3.o diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index 8f024dab7b1c3376df4e74a7121f24686a48e5fe..d40b7891f600014e1d3154a2ea2a0274725b61c1 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -213,27 +213,27 @@ static void leon3_generic_hw_init(MachineState *machine) reset_info->sp = LEON3_RAM_OFFSET + ram_size; qemu_register_reset(main_cpu_reset, reset_info); - ahb_pnp = GRLIB_AHB_PNP(object_new(TYPE_GRLIB_AHB_PNP)); - object_property_set_bool(OBJECT(ahb_pnp), true, "realized", &error_fatal); + ahb_pnp = GRLIB_AHB_PNP(qdev_new(TYPE_GRLIB_AHB_PNP)); + sysbus_realize_and_unref(SYS_BUS_DEVICE(ahb_pnp), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(ahb_pnp), 0, LEON3_AHB_PNP_OFFSET); grlib_ahb_pnp_add_entry(ahb_pnp, 0, 0, GRLIB_VENDOR_GAISLER, GRLIB_LEON3_DEV, GRLIB_AHB_MASTER, GRLIB_CPU_AREA); - apb_pnp = GRLIB_APB_PNP(object_new(TYPE_GRLIB_APB_PNP)); - object_property_set_bool(OBJECT(apb_pnp), true, "realized", &error_fatal); + apb_pnp = GRLIB_APB_PNP(qdev_new(TYPE_GRLIB_APB_PNP)); + sysbus_realize_and_unref(SYS_BUS_DEVICE(apb_pnp), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(apb_pnp), 0, LEON3_APB_PNP_OFFSET); grlib_ahb_pnp_add_entry(ahb_pnp, LEON3_APB_PNP_OFFSET, 0xFFF, GRLIB_VENDOR_GAISLER, GRLIB_APBMST_DEV, GRLIB_AHB_SLAVE, GRLIB_AHBMEM_AREA); /* Allocate IRQ manager */ - dev = qdev_create(NULL, TYPE_GRLIB_IRQMP); + dev = qdev_new(TYPE_GRLIB_IRQMP); qdev_init_gpio_in_named_with_opaque(DEVICE(cpu), leon3_set_pil_in, env, "pil", 1); qdev_connect_gpio_out_named(dev, "grlib-irq", 0, qdev_get_gpio_in_named(DEVICE(cpu), "pil", 0)); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, LEON3_IRQMP_OFFSET); env->irq_manager = dev; env->qemu_irq_ack = leon3_irq_manager; @@ -322,11 +322,11 @@ static void leon3_generic_hw_init(MachineState *machine) } /* Allocate timers */ - dev = qdev_create(NULL, TYPE_GRLIB_GPTIMER); + dev = qdev_new(TYPE_GRLIB_GPTIMER); qdev_prop_set_uint32(dev, "nr-timers", LEON3_TIMER_COUNT); qdev_prop_set_uint32(dev, "frequency", CPU_CLK); qdev_prop_set_uint32(dev, "irq-line", LEON3_TIMER_IRQ); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, LEON3_TIMER_OFFSET); for (i = 0; i < LEON3_TIMER_COUNT; i++) { @@ -339,16 +339,14 @@ static void leon3_generic_hw_init(MachineState *machine) 0, LEON3_TIMER_IRQ, GRLIB_APBIO_AREA); /* Allocate uart */ - if (serial_hd(0)) { - dev = qdev_create(NULL, TYPE_GRLIB_APB_UART); - qdev_prop_set_chr(dev, "chrdev", serial_hd(0)); - qdev_init_nofail(dev); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, LEON3_UART_OFFSET); - sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irqs[LEON3_UART_IRQ]); - grlib_apb_pnp_add_entry(apb_pnp, LEON3_UART_OFFSET, 0xFFF, - GRLIB_VENDOR_GAISLER, GRLIB_APBUART_DEV, 1, - LEON3_UART_IRQ, GRLIB_APBIO_AREA); - } + dev = qdev_new(TYPE_GRLIB_APB_UART); + qdev_prop_set_chr(dev, "chrdev", serial_hd(0)); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, LEON3_UART_OFFSET); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irqs[LEON3_UART_IRQ]); + grlib_apb_pnp_add_entry(apb_pnp, LEON3_UART_OFFSET, 0xFFF, + GRLIB_VENDOR_GAISLER, GRLIB_APBUART_DEV, 1, + LEON3_UART_IRQ, GRLIB_APBIO_AREA); } static void leon3_generic_machine_init(MachineClass *mc) diff --git a/hw/sparc/meson.build b/hw/sparc/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..19c442c90d9b1803a79b042d9a1b3d7efa722740 --- /dev/null +++ b/hw/sparc/meson.build @@ -0,0 +1,6 @@ +sparc_ss = ss.source_set() +sparc_ss.add(when: 'CONFIG_LEON3', if_true: files('leon3.c')) +sparc_ss.add(when: 'CONFIG_SUN4M', if_true: files('sun4m.c')) +sparc_ss.add(when: 'CONFIG_SUN4M', if_true: files('sun4m_iommu.c')) + +hw_arch += {'sparc': sparc_ss} diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 8dda3f7292fd227fe203cf6a6c96a8f0621c6b0d..66fecb152ac61dfb651da7dbc4db72d637df516a 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -46,11 +46,13 @@ #include "hw/nvram/chrp_nvram.h" #include "hw/nvram/fw_cfg.h" #include "hw/char/escc.h" -#include "hw/empty_slot.h" +#include "hw/misc/empty_slot.h" +#include "hw/misc/unimp.h" #include "hw/irq.h" #include "hw/loader.h" #include "elf.h" #include "trace.h" +#include "qom/object.h" /* * Sun4m architecture was used in the following machines: @@ -142,7 +144,7 @@ static void nvram_init(Nvram *nvram, uint8_t *macaddr, memset(image, '\0', sizeof(image)); /* OpenBIOS nvram variables partition */ - sysp_end = chrp_nvram_create_system_partition(image, 0); + sysp_end = chrp_nvram_create_system_partition(image, 0, 0x1fd0); /* Free space partition */ chrp_nvram_create_free_partition(&image[sysp_end], 0x1fd0 - sysp_end); @@ -217,22 +219,12 @@ static void dummy_cpu_set_irq(void *opaque, int irq, int level) { } -static void main_cpu_reset(void *opaque) +static void sun4m_cpu_reset(void *opaque) { SPARCCPU *cpu = opaque; CPUState *cs = CPU(cpu); cpu_reset(cs); - cs->halted = 0; -} - -static void secondary_cpu_reset(void *opaque) -{ - SPARCCPU *cpu = opaque; - CPUState *cs = CPU(cpu); - - cpu_reset(cs); - cs->halted = 1; } static void cpu_halt_signal(void *opaque, int irq, int level) @@ -315,10 +307,10 @@ static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq) DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, TYPE_SUN4M_IOMMU); + dev = qdev_new(TYPE_SUN4M_IOMMU); qdev_prop_set_uint32(dev, "version", version); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_connect_irq(s, 0, irq); sysbus_mmio_map(s, 0, addr); @@ -327,7 +319,7 @@ static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq) static void *sparc32_dma_init(hwaddr dma_base, hwaddr esp_base, qemu_irq espdma_irq, - hwaddr le_base, qemu_irq ledma_irq) + hwaddr le_base, qemu_irq ledma_irq, NICInfo *nd) { DeviceState *dma; ESPDMADeviceState *espdma; @@ -335,17 +327,12 @@ static void *sparc32_dma_init(hwaddr dma_base, SysBusESPState *esp; SysBusPCNetState *lance; - dma = qdev_create(NULL, TYPE_SPARC32_DMA); - qdev_init_nofail(dma); - sysbus_mmio_map(SYS_BUS_DEVICE(dma), 0, dma_base); - + dma = qdev_new(TYPE_SPARC32_DMA); espdma = SPARC32_ESPDMA_DEVICE(object_resolve_path_component( OBJECT(dma), "espdma")); sysbus_connect_irq(SYS_BUS_DEVICE(espdma), 0, espdma_irq); - esp = ESP_STATE(object_resolve_path_component(OBJECT(espdma), "esp")); - sysbus_mmio_map(SYS_BUS_DEVICE(esp), 0, esp_base); - scsi_bus_legacy_handle_cmdline(&esp->esp.bus); + esp = ESP(object_resolve_path_component(OBJECT(espdma), "esp")); ledma = SPARC32_LEDMA_DEVICE(object_resolve_path_component( OBJECT(dma), "ledma")); @@ -353,6 +340,14 @@ static void *sparc32_dma_init(hwaddr dma_base, lance = SYSBUS_PCNET(object_resolve_path_component( OBJECT(ledma), "lance")); + qdev_set_nic_properties(DEVICE(lance), nd); + + sysbus_realize_and_unref(SYS_BUS_DEVICE(dma), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dma), 0, dma_base); + + sysbus_mmio_map(SYS_BUS_DEVICE(esp), 0, esp_base); + scsi_bus_legacy_handle_cmdline(&esp->esp.bus); + sysbus_mmio_map(SYS_BUS_DEVICE(lance), 0, le_base); return dma; @@ -366,10 +361,10 @@ static DeviceState *slavio_intctl_init(hwaddr addr, SysBusDevice *s; unsigned int i, j; - dev = qdev_create(NULL, "slavio_intctl"); - qdev_init_nofail(dev); + dev = qdev_new("slavio_intctl"); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); for (i = 0; i < MAX_CPUS; i++) { for (j = 0; j < MAX_PILS; j++) { @@ -394,10 +389,10 @@ static void slavio_timer_init_all(hwaddr addr, qemu_irq master_irq, SysBusDevice *s; unsigned int i; - dev = qdev_create(NULL, "slavio_timer"); + dev = qdev_new("slavio_timer"); qdev_prop_set_uint32(dev, "num_cpus", num_cpus); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_connect_irq(s, 0, master_irq); sysbus_mmio_map(s, 0, addr + SYS_TIMER_OFFSET); @@ -432,9 +427,9 @@ static void slavio_misc_init(hwaddr base, DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, "slavio_misc"); - qdev_init_nofail(dev); + dev = qdev_new("slavio_misc"); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); if (base) { /* 8 bit registers */ /* Slavio control */ @@ -469,10 +464,10 @@ static void ecc_init(hwaddr base, qemu_irq irq, uint32_t version) DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, "eccmemctl"); + dev = qdev_new("eccmemctl"); qdev_prop_set_uint32(dev, "version", version); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_connect_irq(s, 0, irq); sysbus_mmio_map(s, 0, base); if (version == 0) { // SS-600MP only @@ -485,9 +480,9 @@ static void apc_init(hwaddr power_base, qemu_irq cpu_halt) DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, "apc"); - qdev_init_nofail(dev); + dev = qdev_new("apc"); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); /* Power management (APC) XXX: not a Slavio device */ sysbus_mmio_map(s, 0, power_base); sysbus_connect_irq(s, 0, cpu_halt); @@ -499,13 +494,13 @@ static void tcx_init(hwaddr addr, qemu_irq irq, int vram_size, int width, DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, "SUNW,tcx"); + dev = qdev_new("SUNW,tcx"); qdev_prop_set_uint32(dev, "vram_size", vram_size); qdev_prop_set_uint16(dev, "width", width); qdev_prop_set_uint16(dev, "height", height); qdev_prop_set_uint16(dev, "depth", depth); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); /* 10/ROM : FCode ROM */ sysbus_mmio_map(s, 0, addr); @@ -551,13 +546,13 @@ static void cg3_init(hwaddr addr, qemu_irq irq, int vram_size, int width, DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, "cgthree"); + dev = qdev_new("cgthree"); qdev_prop_set_uint32(dev, "vram-size", vram_size); qdev_prop_set_uint16(dev, "width", width); qdev_prop_set_uint16(dev, "height", height); qdev_prop_set_uint16(dev, "depth", depth); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); /* FCode ROM */ sysbus_mmio_map(s, 0, addr); @@ -580,9 +575,9 @@ static void idreg_init(hwaddr addr) DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, TYPE_MACIO_ID_REGISTER); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_MACIO_ID_REGISTER); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, addr); address_space_write_rom(&address_space_memory, addr, @@ -590,14 +585,13 @@ static void idreg_init(hwaddr addr) idreg_data, sizeof(idreg_data)); } -#define MACIO_ID_REGISTER(obj) \ - OBJECT_CHECK(IDRegState, (obj), TYPE_MACIO_ID_REGISTER) +OBJECT_DECLARE_SIMPLE_TYPE(IDRegState, MACIO_ID_REGISTER) -typedef struct IDRegState { +struct IDRegState { SysBusDevice parent_obj; MemoryRegion mem; -} IDRegState; +}; static void idreg_realize(DeviceState *ds, Error **errp) { @@ -632,13 +626,13 @@ static const TypeInfo idreg_info = { }; #define TYPE_TCX_AFX "tcx_afx" -#define TCX_AFX(obj) OBJECT_CHECK(AFXState, (obj), TYPE_TCX_AFX) +OBJECT_DECLARE_SIMPLE_TYPE(AFXState, TCX_AFX) -typedef struct AFXState { +struct AFXState { SysBusDevice parent_obj; MemoryRegion mem; -} AFXState; +}; /* SS-5 TCX AFX register */ static void afx_init(hwaddr addr) @@ -646,9 +640,9 @@ static void afx_init(hwaddr addr) DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, TYPE_TCX_AFX); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_TCX_AFX); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, addr); } @@ -685,13 +679,15 @@ static const TypeInfo afx_info = { }; #define TYPE_OPENPROM "openprom" -#define OPENPROM(obj) OBJECT_CHECK(PROMState, (obj), TYPE_OPENPROM) +typedef struct PROMState PROMState; +DECLARE_INSTANCE_CHECKER(PROMState, OPENPROM, + TYPE_OPENPROM) -typedef struct PROMState { +struct PROMState { SysBusDevice parent_obj; MemoryRegion prom; -} PROMState; +}; /* Boot PROM (OpenBIOS) */ static uint64_t translate_prom_address(void *opaque, uint64_t addr) @@ -707,9 +703,9 @@ static void prom_init(hwaddr addr, const char *bios_name) char *filename; int ret; - dev = qdev_create(NULL, TYPE_OPENPROM); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_OPENPROM); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, addr); @@ -773,12 +769,14 @@ static const TypeInfo prom_info = { }; #define TYPE_SUN4M_MEMORY "memory" -#define SUN4M_RAM(obj) OBJECT_CHECK(RamDevice, (obj), TYPE_SUN4M_MEMORY) +typedef struct RamDevice RamDevice; +DECLARE_INSTANCE_CHECKER(RamDevice, SUN4M_RAM, + TYPE_SUN4M_MEMORY) -typedef struct RamDevice { +struct RamDevice { SysBusDevice parent_obj; HostMemoryBackend *memdev; -} RamDevice; +}; /* System RAM */ static void ram_realize(DeviceState *dev, Error **errp) @@ -818,21 +816,17 @@ static const TypeInfo ram_info = { static void cpu_devinit(const char *cpu_type, unsigned int id, uint64_t prom_addr, qemu_irq **cpu_irqs) { - CPUState *cs; SPARCCPU *cpu; CPUSPARCState *env; - cpu = SPARC_CPU(cpu_create(cpu_type)); + cpu = SPARC_CPU(object_new(cpu_type)); env = &cpu->env; cpu_sparc_set_id(env, id); - if (id == 0) { - qemu_register_reset(main_cpu_reset, cpu); - } else { - qemu_register_reset(secondary_cpu_reset, cpu); - cs = CPU(cpu); - cs->halted = 1; - } + qemu_register_reset(sun4m_cpu_reset, cpu); + object_property_set_bool(OBJECT(cpu), "start-powered-off", id != 0, + &error_fatal); + qdev_realize_and_unref(DEVICE(cpu), NULL, &error_fatal); *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, cpu, MAX_PILS); env->prom_addr = prom_addr; } @@ -846,7 +840,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, { DeviceState *slavio_intctl; unsigned int i; - void *nvram; + Nvram *nvram; qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS]; qemu_irq fdc_tc; unsigned long kernel_size; @@ -859,6 +853,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, unsigned int max_cpus = machine->smp.max_cpus; Object *ram_memdev = object_resolve_path_type(machine->ram_memdev_id, TYPE_MEMORY_BACKEND, NULL); + NICInfo *nd = &nd_table[0]; if (machine->ram_size > hwdef->max_mem) { error_report("Too much memory for this machine: %" PRId64 "," @@ -876,14 +871,15 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS); /* Create and map RAM frontend */ - dev = qdev_create(NULL, "memory"); - object_property_set_link(OBJECT(dev), ram_memdev, "memdev", &error_fatal); - qdev_init_nofail(dev); + dev = qdev_new("memory"); + object_property_set_link(OBJECT(dev), "memdev", ram_memdev, &error_fatal); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0); /* models without ECC don't trap when missing ram is accessed */ if (!hwdef->ecc_base) { - empty_slot_init(machine->ram_size, hwdef->max_mem - machine->ram_size); + empty_slot_init("ecc", machine->ram_size, + hwdef->max_mem - machine->ram_size); } prom_init(hwdef->slavio_base, bios_name); @@ -914,12 +910,14 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, Software shouldn't use aliased addresses, neither should it crash when does. Using empty_slot instead of aliasing can help with debugging such accesses */ - empty_slot_init(hwdef->iommu_pad_base,hwdef->iommu_pad_len); + empty_slot_init("iommu.alias", + hwdef->iommu_pad_base, hwdef->iommu_pad_len); } + qemu_check_nic_model(nd, TYPE_LANCE); sparc32_dma_init(hwdef->dma_base, hwdef->esp_base, slavio_irq[18], - hwdef->le_base, slavio_irq[16]); + hwdef->le_base, slavio_irq[16], nd); if (graphic_depth != 8 && graphic_depth != 24) { error_report("Unsupported depth: %d", graphic_depth); @@ -963,21 +961,29 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, for (i = 0; i < MAX_VSIMMS; i++) { /* vsimm registers probed by OBP */ if (hwdef->vsimm[i].reg_base) { - empty_slot_init(hwdef->vsimm[i].reg_base, 0x2000); + char *name = g_strdup_printf("vsimm[%d]", i); + empty_slot_init(name, hwdef->vsimm[i].reg_base, 0x2000); + g_free(name); } } if (hwdef->sx_base) { - empty_slot_init(hwdef->sx_base, 0x2000); + create_unimplemented_device("SUNW,sx", hwdef->sx_base, 0x2000); } - nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x2000, 1968, 8); + dev = qdev_new("sysbus-m48t08"); + qdev_prop_set_int32(dev, "base-year", 1968); + s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); + sysbus_connect_irq(s, 0, slavio_irq[0]); + sysbus_mmio_map(s, 0, hwdef->nvram_base); + nvram = NVRAM(dev); slavio_timer_init_all(hwdef->counter_base, slavio_irq[19], slavio_cpu_irq, smp_cpus); /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */ - dev = qdev_create(NULL, TYPE_ESCC); + dev = qdev_new(TYPE_ESCC); qdev_prop_set_uint32(dev, "disabled", !machine->enable_graphics); qdev_prop_set_uint32(dev, "frequency", ESCC_CLOCK); qdev_prop_set_uint32(dev, "it_shift", 1); @@ -985,13 +991,13 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, qdev_prop_set_chr(dev, "chrA", NULL); qdev_prop_set_uint32(dev, "chnBtype", escc_mouse); qdev_prop_set_uint32(dev, "chnAtype", escc_kbd); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_connect_irq(s, 0, slavio_irq[14]); sysbus_connect_irq(s, 1, slavio_irq[14]); sysbus_mmio_map(s, 0, hwdef->ms_kb_base); - dev = qdev_create(NULL, TYPE_ESCC); + dev = qdev_new(TYPE_ESCC); qdev_prop_set_uint32(dev, "disabled", 0); qdev_prop_set_uint32(dev, "frequency", ESCC_CLOCK); qdev_prop_set_uint32(dev, "it_shift", 1); @@ -999,9 +1005,9 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, qdev_prop_set_chr(dev, "chrA", serial_hd(0)); qdev_prop_set_uint32(dev, "chnBtype", escc_serial); qdev_prop_set_uint32(dev, "chnAtype", escc_serial); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_connect_irq(s, 0, slavio_irq[15]); sysbus_connect_irq(s, 1, slavio_irq[15]); sysbus_mmio_map(s, 0, hwdef->serial_base); @@ -1031,14 +1037,16 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, if (hwdef->dbri_base) { /* ISDN chip with attached CS4215 audio codec */ /* prom space */ - empty_slot_init(hwdef->dbri_base+0x1000, 0x30); + create_unimplemented_device("SUNW,DBRI.prom", + hwdef->dbri_base + 0x1000, 0x30); /* reg space */ - empty_slot_init(hwdef->dbri_base+0x10000, 0x100); + create_unimplemented_device("SUNW,DBRI", + hwdef->dbri_base + 0x10000, 0x100); } if (hwdef->bpp_base) { /* parallel port */ - empty_slot_init(hwdef->bpp_base, 0x20); + create_unimplemented_device("SUNW,bpp", hwdef->bpp_base, 0x20); } initrd_size = 0; @@ -1046,7 +1054,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, machine->initrd_filename, machine->ram_size, &initrd_size); - nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, machine->kernel_cmdline, + nvram_init(nvram, (uint8_t *)&nd->macaddr, machine->kernel_cmdline, machine->boot_order, machine->ram_size, kernel_size, graphic_width, graphic_height, graphic_depth, hwdef->nvram_machine_id, "Sun4m"); @@ -1055,14 +1063,14 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ecc_init(hwdef->ecc_base, slavio_irq[28], hwdef->ecc_version); - dev = qdev_create(NULL, TYPE_FW_CFG_MEM); + dev = qdev_new(TYPE_FW_CFG_MEM); fw_cfg = FW_CFG(dev); qdev_prop_set_uint32(dev, "data_width", 1); qdev_prop_set_bit(dev, "dma_enabled", false); object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG, OBJECT(fw_cfg)); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, CFG_ADDR); sysbus_mmio_map(s, 1, CFG_ADDR + 2); diff --git a/hw/sparc/trace.h b/hw/sparc/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..625d60ca70dc31c5b26bb4c2e24dbf5ef9d4c121 --- /dev/null +++ b/hw/sparc/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_sparc.h" diff --git a/hw/sparc64/Makefile.objs b/hw/sparc64/Makefile.objs deleted file mode 100644 index af0525c1a2b44050209f5892dbf80e21520aa2ce..0000000000000000000000000000000000000000 --- a/hw/sparc64/Makefile.objs +++ /dev/null @@ -1,4 +0,0 @@ -obj-y += sparc64.o -obj-$(CONFIG_SUN4U) += sun4u_iommu.o -obj-$(CONFIG_SUN4U) += sun4u.o -obj-$(CONFIG_NIAGARA) += niagara.o diff --git a/hw/sparc64/meson.build b/hw/sparc64/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..58b550465188c1905e410a1a022b3b8c49708868 --- /dev/null +++ b/hw/sparc64/meson.build @@ -0,0 +1,6 @@ +sparc64_ss = ss.source_set() +sparc64_ss.add(files('sparc64.c')) +sparc64_ss.add(when: 'CONFIG_NIAGARA', if_true: files('niagara.c')) +sparc64_ss.add(when: 'CONFIG_SUN4U', if_true: files('sun4u.c', 'sun4u_iommu.c')) + +hw_arch += {'sparc64': sparc64_ss} diff --git a/hw/sparc64/niagara.c b/hw/sparc64/niagara.c index ab5ef8c5b34311617d15dc34a00fdce83c2f4c9a..a87d55f6bb1a40a6931f75afdc4a60b46fbf4a94 100644 --- a/hw/sparc64/niagara.c +++ b/hw/sparc64/niagara.c @@ -68,7 +68,6 @@ typedef struct NiagaraBoardState { #define NIAGARA_VDISK_BASE 0x1f40000000ULL #define NIAGARA_RTC_BASE 0xfff0c1fff8ULL -#define NIAGARA_UART_BASE 0x1f10000000ULL /* Firmware layout * @@ -152,10 +151,8 @@ static void niagara_init(MachineState *machine) exit(1); } } - if (serial_hd(0)) { - serial_mm_init(sysmem, NIAGARA_UART_BASE, 0, NULL, 115200, - serial_hd(0), DEVICE_BIG_ENDIAN); - } + serial_mm_init(sysmem, NIAGARA_UART_BASE, 0, NULL, + 115200, serial_hd(0), DEVICE_BIG_ENDIAN); create_unimplemented_device("sun4v-iob", NIAGARA_IOBBASE, NIAGARA_IOBSIZE); sun4v_rtc_init(NIAGARA_RTC_BASE); } diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 3a757ec42e0ab77bd00103be1bf6b572dc0d5432..2f8fc670cf13793a7ea1e8c56fa6c82baa8801af 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -55,6 +55,7 @@ #include "hw/fw-path-provider.h" #include "elf.h" #include "trace.h" +#include "qom/object.h" #define KERNEL_LOAD_ADDR 0x00404000 #define CMDLINE_ADDR 0x003ff000 @@ -79,7 +80,7 @@ struct hwdef { uint64_t console_serial_base; }; -typedef struct EbusState { +struct EbusState { /*< private >*/ PCIDevice parent_obj; @@ -88,10 +89,10 @@ typedef struct EbusState { uint64_t console_serial_base; MemoryRegion bar0; MemoryRegion bar1; -} EbusState; +}; #define TYPE_EBUS "ebus" -#define EBUS(obj) OBJECT_CHECK(EbusState, (obj), TYPE_EBUS) +OBJECT_DECLARE_SIMPLE_TYPE(EbusState, EBUS) const char *fw_cfg_arch_key_name(uint16_t key) { @@ -136,7 +137,7 @@ static int sun4u_NVRAM_set_params(Nvram *nvram, uint16_t NVRAM_size, memset(image, '\0', sizeof(image)); /* OpenBIOS nvram variables partition */ - sysp_end = chrp_nvram_create_system_partition(image, 0); + sysp_end = chrp_nvram_create_system_partition(image, 0, 0x1fd0); /* Free space partition */ chrp_nvram_create_free_partition(&image[sysp_end], 0x1fd0 - sysp_end); @@ -226,13 +227,13 @@ typedef struct ResetData { } ResetData; #define TYPE_SUN4U_POWER "power" -#define SUN4U_POWER(obj) OBJECT_CHECK(PowerDevice, (obj), TYPE_SUN4U_POWER) +OBJECT_DECLARE_SIMPLE_TYPE(PowerDevice, SUN4U_POWER) -typedef struct PowerDevice { +struct PowerDevice { SysBusDevice parent_obj; MemoryRegion power_mmio; -} PowerDevice; +}; /* Power */ static uint64_t power_mem_read(void *opaque, hwaddr addr, unsigned size) @@ -300,6 +301,7 @@ static void ebus_isa_irq_handler(void *opaque, int n, int level) static void ebus_realize(PCIDevice *pci_dev, Error **errp) { EbusState *s = EBUS(pci_dev); + ISADevice *isa_dev; SysBusDevice *sbd; DeviceState *dev; qemu_irq *isa_irq; @@ -338,22 +340,16 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp) for (i = 0; i < MAX_FD; i++) { fd[i] = drive_get(IF_FLOPPY, 0, i); } - dev = DEVICE(isa_create(s->isa_bus, TYPE_ISA_FDC)); - if (fd[0]) { - qdev_prop_set_drive(dev, "driveA", blk_by_legacy_dinfo(fd[0]), - &error_abort); - } - if (fd[1]) { - qdev_prop_set_drive(dev, "driveB", blk_by_legacy_dinfo(fd[1]), - &error_abort); - } + isa_dev = isa_new(TYPE_ISA_FDC); + dev = DEVICE(isa_dev); qdev_prop_set_uint32(dev, "dma", -1); - qdev_init_nofail(dev); + isa_realize_and_unref(isa_dev, s->isa_bus, &error_fatal); + isa_fdc_init_drives(isa_dev, fd); /* Power */ - dev = qdev_create(NULL, TYPE_SUN4U_POWER); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_SUN4U_POWER); sbd = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sbd, &error_fatal); memory_region_add_subregion(pci_address_space_io(pci_dev), 0x7240, sysbus_mmio_get_region(sbd, 0)); @@ -404,13 +400,15 @@ static const TypeInfo ebus_info = { }; #define TYPE_OPENPROM "openprom" -#define OPENPROM(obj) OBJECT_CHECK(PROMState, (obj), TYPE_OPENPROM) +typedef struct PROMState PROMState; +DECLARE_INSTANCE_CHECKER(PROMState, OPENPROM, + TYPE_OPENPROM) -typedef struct PROMState { +struct PROMState { SysBusDevice parent_obj; MemoryRegion prom; -} PROMState; +}; static uint64_t translate_prom_address(void *opaque, uint64_t addr) { @@ -426,9 +424,9 @@ static void prom_init(hwaddr addr, const char *bios_name) char *filename; int ret; - dev = qdev_create(NULL, TYPE_OPENPROM); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_OPENPROM); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, addr); @@ -492,14 +490,16 @@ static const TypeInfo prom_info = { #define TYPE_SUN4U_MEMORY "memory" -#define SUN4U_RAM(obj) OBJECT_CHECK(RamDevice, (obj), TYPE_SUN4U_MEMORY) +typedef struct RamDevice RamDevice; +DECLARE_INSTANCE_CHECKER(RamDevice, SUN4U_RAM, + TYPE_SUN4U_MEMORY) -typedef struct RamDevice { +struct RamDevice { SysBusDevice parent_obj; MemoryRegion ram; uint64_t size; -} RamDevice; +}; /* System RAM */ static void ram_realize(DeviceState *dev, Error **errp) @@ -520,12 +520,12 @@ static void ram_init(hwaddr addr, ram_addr_t RAM_size) RamDevice *d; /* allocate RAM */ - dev = qdev_create(NULL, TYPE_SUN4U_MEMORY); + dev = qdev_new(TYPE_SUN4U_MEMORY); s = SYS_BUS_DEVICE(dev); d = SUN4U_RAM(dev); d->size = RAM_size; - qdev_init_nofail(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, addr); } @@ -572,8 +572,8 @@ static void sun4uv_init(MemoryRegion *address_space_mem, cpu = sparc64_cpu_devinit(machine->cpu_type, hwdef->prom_addr); /* IOMMU */ - iommu = qdev_create(NULL, TYPE_SUN4U_IOMMU); - qdev_init_nofail(iommu); + iommu = qdev_new(TYPE_SUN4U_IOMMU); + sysbus_realize_and_unref(SYS_BUS_DEVICE(iommu), &error_fatal); /* set up devices */ ram_init(0, machine->ram_size); @@ -581,12 +581,19 @@ static void sun4uv_init(MemoryRegion *address_space_mem, prom_init(hwdef->prom_addr, bios_name); /* Init sabre (PCI host bridge) */ - sabre = SABRE_DEVICE(qdev_create(NULL, TYPE_SABRE)); + sabre = SABRE(qdev_new(TYPE_SABRE)); qdev_prop_set_uint64(DEVICE(sabre), "special-base", PBM_SPECIAL_BASE); qdev_prop_set_uint64(DEVICE(sabre), "mem-base", PBM_MEM_BASE); - object_property_set_link(OBJECT(sabre), OBJECT(iommu), "iommu", + object_property_set_link(OBJECT(sabre), "iommu", OBJECT(iommu), &error_abort); - qdev_init_nofail(DEVICE(sabre)); + sysbus_realize_and_unref(SYS_BUS_DEVICE(sabre), &error_fatal); + + /* sabre_config */ + sysbus_mmio_map(SYS_BUS_DEVICE(sabre), 0, PBM_SPECIAL_BASE); + /* PCI configuration space */ + sysbus_mmio_map(SYS_BUS_DEVICE(sabre), 1, PBM_SPECIAL_BASE + 0x1000000ULL); + /* pci_ioport */ + sysbus_mmio_map(SYS_BUS_DEVICE(sabre), 2, PBM_SPECIAL_BASE + 0x2000000ULL); /* Wire up PCI interrupts to CPU */ for (i = 0; i < IVEC_MAX; i++) { @@ -605,10 +612,10 @@ static void sun4uv_init(MemoryRegion *address_space_mem, pci_busA->slot_reserved_mask = 0xfffffff1; pci_busB->slot_reserved_mask = 0xfffffff0; - ebus = pci_create_multifunction(pci_busA, PCI_DEVFN(1, 0), true, TYPE_EBUS); + ebus = pci_new_multifunction(PCI_DEVFN(1, 0), true, TYPE_EBUS); qdev_prop_set_uint64(DEVICE(ebus), "console-serial-base", hwdef->console_serial_base); - qdev_init_nofail(DEVICE(ebus)); + pci_realize_and_unref(ebus, pci_busA, &error_fatal); /* Wire up "well-known" ISA IRQs to PBM legacy obio IRQs */ qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 7, @@ -635,24 +642,28 @@ static void sun4uv_init(MemoryRegion *address_space_mem, memset(&macaddr, 0, sizeof(MACAddr)); onboard_nic = false; for (i = 0; i < nb_nics; i++) { + PCIBus *bus; nd = &nd_table[i]; if (!nd->model || strcmp(nd->model, "sunhme") == 0) { if (!onboard_nic) { - pci_dev = pci_create_multifunction(pci_busA, PCI_DEVFN(1, 1), + pci_dev = pci_new_multifunction(PCI_DEVFN(1, 1), true, "sunhme"); + bus = pci_busA; memcpy(&macaddr, &nd->macaddr.a, sizeof(MACAddr)); onboard_nic = true; } else { - pci_dev = pci_create(pci_busB, -1, "sunhme"); + pci_dev = pci_new(-1, "sunhme"); + bus = pci_busB; } } else { - pci_dev = pci_create(pci_busB, -1, nd->model); + pci_dev = pci_new(-1, nd->model); + bus = pci_busB; } dev = &pci_dev->qdev; qdev_set_nic_properties(dev, nd); - qdev_init_nofail(dev); + pci_realize_and_unref(pci_dev, bus, &error_fatal); } /* If we don't have an onboard NIC, grab a default MAC address so that @@ -661,16 +672,19 @@ static void sun4uv_init(MemoryRegion *address_space_mem, qemu_macaddr_default_if_unset(&macaddr); } - pci_dev = pci_create(pci_busA, PCI_DEVFN(3, 0), "cmd646-ide"); + pci_dev = pci_new(PCI_DEVFN(3, 0), "cmd646-ide"); qdev_prop_set_uint32(&pci_dev->qdev, "secondary", 1); - qdev_init_nofail(&pci_dev->qdev); + pci_realize_and_unref(pci_dev, pci_busA, &error_fatal); pci_ide_create_devs(pci_dev); /* Map NVRAM into I/O (ebus) space */ - nvram = m48t59_init(NULL, 0, 0, NVRAM_SIZE, 1968, 59); - s = SYS_BUS_DEVICE(nvram); + dev = qdev_new("sysbus-m48t59"); + qdev_prop_set_int32(dev, "base-year", 1968); + s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); memory_region_add_subregion(pci_address_space_io(ebus), 0x2000, sysbus_mmio_get_region(s, 0)); + nvram = NVRAM(dev); initrd_size = 0; initrd_addr = 0; @@ -689,10 +703,10 @@ static void sun4uv_init(MemoryRegion *address_space_mem, graphic_width, graphic_height, graphic_depth, (uint8_t *)&macaddr); - dev = qdev_create(NULL, TYPE_FW_CFG_IO); + dev = qdev_new(TYPE_FW_CFG_IO); qdev_prop_set_bit(dev, "dma_enabled", false); object_property_add_child(OBJECT(ebus), TYPE_FW_CFG, OBJECT(dev)); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); memory_region_add_subregion(pci_address_space_io(ebus), BIOS_CFG_IOPORT, &FW_CFG_IO(dev)->comb_iomem); diff --git a/hw/sparc64/trace.h b/hw/sparc64/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..b6ef6e611d9ff563ff42d7ecae0c080d607bfd99 --- /dev/null +++ b/hw/sparc64/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_sparc64.h" diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs deleted file mode 100644 index 07a85f1967a80c5d10e71787b4043a962e796ee6..0000000000000000000000000000000000000000 --- a/hw/ssi/Makefile.objs +++ /dev/null @@ -1,10 +0,0 @@ -common-obj-$(CONFIG_PL022) += pl022.o -common-obj-$(CONFIG_SSI) += ssi.o -common-obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o -common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o -common-obj-$(CONFIG_ASPEED_SOC) += aspeed_smc.o -common-obj-$(CONFIG_STM32F2XX_SPI) += stm32f2xx_spi.o -common-obj-$(CONFIG_MSF2) += mss-spi.o - -common-obj-$(CONFIG_OMAP) += omap_spi.o -common-obj-$(CONFIG_IMX) += imx_spi.o diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index 2edccef2d54d9e2c70eb4d687f9c55f0e9f19fda..795784e5f364f9ea1e8d95bd6c590d0f5a43770f 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -230,7 +230,7 @@ static void aspeed_smc_reg_to_segment(const AspeedSMCState *s, uint32_t reg, static const AspeedSegments aspeed_segments_ast2600_fmc[] = { { 0x0, 128 * MiB }, /* start address is readonly */ - { 0x0, 0 }, /* disabled */ + { 128 * MiB, 128 * MiB }, /* default is disabled but needed for -kernel */ { 0x0, 0 }, /* disabled */ }; @@ -259,7 +259,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_TIMINGS, .nregs_timings = 1, .conf_enable_w0 = CONF_ENABLE_W0, - .max_slaves = 5, + .max_slaves = 1, .segments = aspeed_segments_legacy, .flash_window_base = ASPEED_SOC_SMC_FLASH_BASE, .flash_window_size = 0x6000000, @@ -1299,10 +1299,8 @@ static const MemoryRegionOps aspeed_smc_ops = { .read = aspeed_smc_read, .write = aspeed_smc_write, .endianness = DEVICE_LITTLE_ENDIAN, - .valid.unaligned = true, }; - /* * Initialize the custom address spaces for DMAs */ @@ -1356,7 +1354,6 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp) /* Setup cs_lines for slaves */ s->cs_lines = g_new0(qemu_irq, s->num_cs); - ssi_auto_connect_slaves(dev, s->cs_lines, s->spi); for (i = 0; i < s->num_cs; ++i) { sysbus_init_irq(sbd, &s->cs_lines[i]); diff --git a/hw/ssi/imx_spi.c b/hw/ssi/imx_spi.c index 2dd9a631e1287905c27ea7e04cf10cc88ce9e61d..d8885ae454ec0e13315f474ecfcf85896eec441b 100644 --- a/hw/ssi/imx_spi.c +++ b/hw/ssi/imx_spi.c @@ -53,7 +53,7 @@ static const char *imx_spi_reg_name(uint32_t reg) case ECSPI_MSGDATA: return "ECSPI_MSGDATA"; default: - sprintf(unknown, "%d ?", reg); + sprintf(unknown, "%u ?", reg); return unknown; } } @@ -182,7 +182,7 @@ static void imx_spi_flush_txfifo(IMXSPIState *s) rx = 0; - while (tx_burst) { + while (tx_burst > 0) { uint8_t byte = tx & 0xff; DPRINTF("writing 0x%02x\n", (uint32_t)byte); @@ -206,7 +206,7 @@ static void imx_spi_flush_txfifo(IMXSPIState *s) if (fifo32_is_full(&s->rx_fifo)) { s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RO; } else { - fifo32_push(&s->rx_fifo, (uint8_t)rx); + fifo32_push(&s->rx_fifo, rx); } if (s->burst_length <= 0) { @@ -424,8 +424,6 @@ static void imx_spi_realize(DeviceState *dev, Error **errp) sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq); - ssi_auto_connect_slaves(dev, s->cs_lines, s->bus); - for (i = 0; i < 4; ++i) { sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->cs_lines[i]); } diff --git a/hw/ssi/meson.build b/hw/ssi/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..dee00c0da63eb49a08f2c028c0549974e8f6c00b --- /dev/null +++ b/hw/ssi/meson.build @@ -0,0 +1,10 @@ +softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_smc.c')) +softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('mss-spi.c')) +softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_fiu.c')) +softmmu_ss.add(when: 'CONFIG_PL022', if_true: files('pl022.c')) +softmmu_ss.add(when: 'CONFIG_SSI', if_true: files('ssi.c')) +softmmu_ss.add(when: 'CONFIG_STM32F2XX_SPI', if_true: files('stm32f2xx_spi.c')) +softmmu_ss.add(when: 'CONFIG_XILINX_SPI', if_true: files('xilinx_spi.c')) +softmmu_ss.add(when: 'CONFIG_XILINX_SPIPS', if_true: files('xilinx_spips.c')) +softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_spi.c')) +softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_spi.c')) diff --git a/hw/ssi/mss-spi.c b/hw/ssi/mss-spi.c index 3050fabb692152df03da0125cbe28a351f438cab..b2432c5a132837d649a5cd6d3955d43b53b5fbfd 100644 --- a/hw/ssi/mss-spi.c +++ b/hw/ssi/mss-spi.c @@ -376,7 +376,6 @@ static void mss_spi_realize(DeviceState *dev, Error **errp) s->spi = ssi_create_bus(dev, "spi"); sysbus_init_irq(sbd, &s->irq); - ssi_auto_connect_slaves(dev, &s->cs_line, s->spi); sysbus_init_irq(sbd, &s->cs_line); memory_region_init_io(&s->mmio, OBJECT(s), &spi_ops, s, diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c new file mode 100644 index 0000000000000000000000000000000000000000..5040132b074ff5e416d58cd1354bcd11322dd2ba --- /dev/null +++ b/hw/ssi/npcm7xx_fiu.c @@ -0,0 +1,572 @@ +/* + * Nuvoton NPCM7xx Flash Interface Unit (FIU) + * + * Copyright 2020 Google LLC + * + * 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. + */ + +#include "qemu/osdep.h" + +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/ssi/npcm7xx_fiu.h" +#include "migration/vmstate.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/units.h" + +#include "trace.h" + +/* Up to 128 MiB of flash may be accessed directly as memory. */ +#define NPCM7XX_FIU_FLASH_WINDOW_SIZE (128 * MiB) + +/* Each module has 4 KiB of register space. Only a fraction of it is used. */ +#define NPCM7XX_FIU_CTRL_REGS_SIZE (4 * KiB) + +/* 32-bit FIU register indices. */ +enum NPCM7xxFIURegister { + NPCM7XX_FIU_DRD_CFG, + NPCM7XX_FIU_DWR_CFG, + NPCM7XX_FIU_UMA_CFG, + NPCM7XX_FIU_UMA_CTS, + NPCM7XX_FIU_UMA_CMD, + NPCM7XX_FIU_UMA_ADDR, + NPCM7XX_FIU_PRT_CFG, + NPCM7XX_FIU_UMA_DW0 = 0x0020 / sizeof(uint32_t), + NPCM7XX_FIU_UMA_DW1, + NPCM7XX_FIU_UMA_DW2, + NPCM7XX_FIU_UMA_DW3, + NPCM7XX_FIU_UMA_DR0, + NPCM7XX_FIU_UMA_DR1, + NPCM7XX_FIU_UMA_DR2, + NPCM7XX_FIU_UMA_DR3, + NPCM7XX_FIU_PRT_CMD0, + NPCM7XX_FIU_PRT_CMD1, + NPCM7XX_FIU_PRT_CMD2, + NPCM7XX_FIU_PRT_CMD3, + NPCM7XX_FIU_PRT_CMD4, + NPCM7XX_FIU_PRT_CMD5, + NPCM7XX_FIU_PRT_CMD6, + NPCM7XX_FIU_PRT_CMD7, + NPCM7XX_FIU_PRT_CMD8, + NPCM7XX_FIU_PRT_CMD9, + NPCM7XX_FIU_CFG = 0x78 / sizeof(uint32_t), + NPCM7XX_FIU_REGS_END, +}; + +/* FIU_{DRD,DWR,UMA,PTR}_CFG cannot be written when this bit is set. */ +#define NPCM7XX_FIU_CFG_LCK BIT(31) + +/* Direct Read configuration register fields. */ +#define FIU_DRD_CFG_ADDSIZ(rv) extract32(rv, 16, 2) +#define FIU_ADDSIZ_3BYTES 0 +#define FIU_ADDSIZ_4BYTES 1 +#define FIU_DRD_CFG_DBW(rv) extract32(rv, 12, 2) +#define FIU_DRD_CFG_ACCTYPE(rv) extract32(rv, 8, 2) +#define FIU_DRD_CFG_RDCMD(rv) extract32(rv, 0, 8) + +/* Direct Write configuration register fields. */ +#define FIU_DWR_CFG_ADDSIZ(rv) extract32(rv, 16, 2) +#define FIU_DWR_CFG_WRCMD(rv) extract32(rv, 0, 8) + +/* User-Mode Access register fields. */ + +/* Command Mode Lock and the bits protected by it. */ +#define FIU_UMA_CFG_CMMLCK BIT(30) +#define FIU_UMA_CFG_CMMLCK_MASK 0x00000403 + +#define FIU_UMA_CFG_RDATSIZ(rv) extract32(rv, 24, 5) +#define FIU_UMA_CFG_DBSIZ(rv) extract32(rv, 21, 3) +#define FIU_UMA_CFG_WDATSIZ(rv) extract32(rv, 16, 5) +#define FIU_UMA_CFG_ADDSIZ(rv) extract32(rv, 11, 3) +#define FIU_UMA_CFG_CMDSIZ(rv) extract32(rv, 10, 1) +#define FIU_UMA_CFG_DBPCK(rv) extract32(rv, 6, 2) + +#define FIU_UMA_CTS_RDYIE BIT(25) +#define FIU_UMA_CTS_RDYST BIT(24) +#define FIU_UMA_CTS_SW_CS BIT(16) +#define FIU_UMA_CTS_DEV_NUM(rv) extract32(rv, 8, 2) +#define FIU_UMA_CTS_EXEC_DONE BIT(0) + +/* + * Returns the index of flash in the fiu->flash array. This corresponds to the + * chip select ID of the flash. + */ +static unsigned npcm7xx_fiu_cs_index(NPCM7xxFIUState *fiu, + NPCM7xxFIUFlash *flash) +{ + int index = flash - fiu->flash; + + g_assert(index >= 0 && index < fiu->cs_count); + + return index; +} + +/* Assert the chip select specified in the UMA Control/Status Register. */ +static void npcm7xx_fiu_select(NPCM7xxFIUState *s, unsigned cs_id) +{ + trace_npcm7xx_fiu_select(DEVICE(s)->canonical_path, cs_id); + + if (cs_id < s->cs_count) { + qemu_irq_lower(s->cs_lines[cs_id]); + s->active_cs = cs_id; + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: UMA to CS%d; this module has only %d chip selects", + DEVICE(s)->canonical_path, cs_id, s->cs_count); + s->active_cs = -1; + } +} + +/* Deassert the currently active chip select. */ +static void npcm7xx_fiu_deselect(NPCM7xxFIUState *s) +{ + if (s->active_cs < 0) { + return; + } + + trace_npcm7xx_fiu_deselect(DEVICE(s)->canonical_path, s->active_cs); + + qemu_irq_raise(s->cs_lines[s->active_cs]); + s->active_cs = -1; +} + +/* Direct flash memory read handler. */ +static uint64_t npcm7xx_fiu_flash_read(void *opaque, hwaddr addr, + unsigned int size) +{ + NPCM7xxFIUFlash *f = opaque; + NPCM7xxFIUState *fiu = f->fiu; + uint64_t value = 0; + uint32_t drd_cfg; + int dummy_cycles; + int i; + + if (fiu->active_cs != -1) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: direct flash read with CS%d already active", + DEVICE(fiu)->canonical_path, fiu->active_cs); + } + + npcm7xx_fiu_select(fiu, npcm7xx_fiu_cs_index(fiu, f)); + + drd_cfg = fiu->regs[NPCM7XX_FIU_DRD_CFG]; + ssi_transfer(fiu->spi, FIU_DRD_CFG_RDCMD(drd_cfg)); + + switch (FIU_DRD_CFG_ADDSIZ(drd_cfg)) { + case FIU_ADDSIZ_4BYTES: + ssi_transfer(fiu->spi, extract32(addr, 24, 8)); + /* fall through */ + case FIU_ADDSIZ_3BYTES: + ssi_transfer(fiu->spi, extract32(addr, 16, 8)); + ssi_transfer(fiu->spi, extract32(addr, 8, 8)); + ssi_transfer(fiu->spi, extract32(addr, 0, 8)); + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: bad address size %d\n", + DEVICE(fiu)->canonical_path, FIU_DRD_CFG_ADDSIZ(drd_cfg)); + break; + } + + /* Flash chip model expects one transfer per dummy bit, not byte */ + dummy_cycles = + (FIU_DRD_CFG_DBW(drd_cfg) * 8) >> FIU_DRD_CFG_ACCTYPE(drd_cfg); + for (i = 0; i < dummy_cycles; i++) { + ssi_transfer(fiu->spi, 0); + } + + for (i = 0; i < size; i++) { + value = deposit64(value, 8 * i, 8, ssi_transfer(fiu->spi, 0)); + } + + trace_npcm7xx_fiu_flash_read(DEVICE(fiu)->canonical_path, fiu->active_cs, + addr, size, value); + + npcm7xx_fiu_deselect(fiu); + + return value; +} + +/* Direct flash memory write handler. */ +static void npcm7xx_fiu_flash_write(void *opaque, hwaddr addr, uint64_t v, + unsigned int size) +{ + NPCM7xxFIUFlash *f = opaque; + NPCM7xxFIUState *fiu = f->fiu; + uint32_t dwr_cfg; + unsigned cs_id; + int i; + + if (fiu->active_cs != -1) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: direct flash write with CS%d already active", + DEVICE(fiu)->canonical_path, fiu->active_cs); + } + + cs_id = npcm7xx_fiu_cs_index(fiu, f); + trace_npcm7xx_fiu_flash_write(DEVICE(fiu)->canonical_path, cs_id, addr, + size, v); + npcm7xx_fiu_select(fiu, cs_id); + + dwr_cfg = fiu->regs[NPCM7XX_FIU_DWR_CFG]; + ssi_transfer(fiu->spi, FIU_DWR_CFG_WRCMD(dwr_cfg)); + + switch (FIU_DWR_CFG_ADDSIZ(dwr_cfg)) { + case FIU_ADDSIZ_4BYTES: + ssi_transfer(fiu->spi, extract32(addr, 24, 8)); + /* fall through */ + case FIU_ADDSIZ_3BYTES: + ssi_transfer(fiu->spi, extract32(addr, 16, 8)); + ssi_transfer(fiu->spi, extract32(addr, 8, 8)); + ssi_transfer(fiu->spi, extract32(addr, 0, 8)); + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: bad address size %d\n", + DEVICE(fiu)->canonical_path, FIU_DWR_CFG_ADDSIZ(dwr_cfg)); + break; + } + + for (i = 0; i < size; i++) { + ssi_transfer(fiu->spi, extract64(v, i * 8, 8)); + } + + npcm7xx_fiu_deselect(fiu); +} + +static const MemoryRegionOps npcm7xx_fiu_flash_ops = { + .read = npcm7xx_fiu_flash_read, + .write = npcm7xx_fiu_flash_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 8, + .unaligned = true, + }, +}; + +/* Control register read handler. */ +static uint64_t npcm7xx_fiu_ctrl_read(void *opaque, hwaddr addr, + unsigned int size) +{ + hwaddr reg = addr / sizeof(uint32_t); + NPCM7xxFIUState *s = opaque; + uint32_t value; + + if (reg < NPCM7XX_FIU_NR_REGS) { + value = s->regs[reg]; + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: read from invalid offset 0x%" PRIx64 "\n", + DEVICE(s)->canonical_path, addr); + value = 0; + } + + trace_npcm7xx_fiu_ctrl_read(DEVICE(s)->canonical_path, addr, value); + + return value; +} + +/* Send the specified number of address bytes from the UMA address register. */ +static void send_address(SSIBus *spi, unsigned int addsiz, uint32_t addr) +{ + switch (addsiz) { + case 4: + ssi_transfer(spi, extract32(addr, 24, 8)); + /* fall through */ + case 3: + ssi_transfer(spi, extract32(addr, 16, 8)); + /* fall through */ + case 2: + ssi_transfer(spi, extract32(addr, 8, 8)); + /* fall through */ + case 1: + ssi_transfer(spi, extract32(addr, 0, 8)); + /* fall through */ + case 0: + break; + } +} + +/* Send the number of dummy bits specified in the UMA config register. */ +static void send_dummy_bits(SSIBus *spi, uint32_t uma_cfg, uint32_t uma_cmd) +{ + unsigned int bits_per_clock = 1U << FIU_UMA_CFG_DBPCK(uma_cfg); + unsigned int i; + + for (i = 0; i < FIU_UMA_CFG_DBSIZ(uma_cfg); i++) { + /* Use bytes 0 and 1 first, then keep repeating byte 2 */ + unsigned int field = (i < 2) ? ((i + 1) * 8) : 24; + unsigned int j; + + for (j = 0; j < 8; j += bits_per_clock) { + ssi_transfer(spi, extract32(uma_cmd, field + j, bits_per_clock)); + } + } +} + +/* Perform a User-Mode Access transaction. */ +static void npcm7xx_fiu_uma_transaction(NPCM7xxFIUState *s) +{ + uint32_t uma_cts = s->regs[NPCM7XX_FIU_UMA_CTS]; + uint32_t uma_cfg; + unsigned int i; + + /* SW_CS means the CS is already forced low, so don't touch it. */ + if (uma_cts & FIU_UMA_CTS_SW_CS) { + int cs_id = FIU_UMA_CTS_DEV_NUM(s->regs[NPCM7XX_FIU_UMA_CTS]); + npcm7xx_fiu_select(s, cs_id); + } + + /* Send command, if present. */ + uma_cfg = s->regs[NPCM7XX_FIU_UMA_CFG]; + if (FIU_UMA_CFG_CMDSIZ(uma_cfg) > 0) { + ssi_transfer(s->spi, extract32(s->regs[NPCM7XX_FIU_UMA_CMD], 0, 8)); + } + + /* Send address, if present. */ + send_address(s->spi, FIU_UMA_CFG_ADDSIZ(uma_cfg), + s->regs[NPCM7XX_FIU_UMA_ADDR]); + + /* Write data, if present. */ + for (i = 0; i < FIU_UMA_CFG_WDATSIZ(uma_cfg); i++) { + unsigned int reg = + (i < 16) ? (NPCM7XX_FIU_UMA_DW0 + i / 4) : NPCM7XX_FIU_UMA_DW3; + unsigned int field = (i % 4) * 8; + + ssi_transfer(s->spi, extract32(s->regs[reg], field, 8)); + } + + /* Send dummy bits, if present. */ + send_dummy_bits(s->spi, uma_cfg, s->regs[NPCM7XX_FIU_UMA_CMD]); + + /* Read data, if present. */ + for (i = 0; i < FIU_UMA_CFG_RDATSIZ(uma_cfg); i++) { + unsigned int reg = NPCM7XX_FIU_UMA_DR0 + i / 4; + unsigned int field = (i % 4) * 8; + uint8_t c; + + c = ssi_transfer(s->spi, 0); + if (reg <= NPCM7XX_FIU_UMA_DR3) { + s->regs[reg] = deposit32(s->regs[reg], field, 8, c); + } + } + + /* Again, don't touch CS if the user is forcing it low. */ + if (uma_cts & FIU_UMA_CTS_SW_CS) { + npcm7xx_fiu_deselect(s); + } + + /* RDYST means a command has completed since it was cleared. */ + s->regs[NPCM7XX_FIU_UMA_CTS] |= FIU_UMA_CTS_RDYST; + /* EXEC_DONE means Execute Command / Not Done, so clear it here. */ + s->regs[NPCM7XX_FIU_UMA_CTS] &= ~FIU_UMA_CTS_EXEC_DONE; +} + +/* Control register write handler. */ +static void npcm7xx_fiu_ctrl_write(void *opaque, hwaddr addr, uint64_t v, + unsigned int size) +{ + hwaddr reg = addr / sizeof(uint32_t); + NPCM7xxFIUState *s = opaque; + uint32_t value = v; + + trace_npcm7xx_fiu_ctrl_write(DEVICE(s)->canonical_path, addr, value); + + switch (reg) { + case NPCM7XX_FIU_UMA_CFG: + if (s->regs[reg] & FIU_UMA_CFG_CMMLCK) { + value &= ~FIU_UMA_CFG_CMMLCK_MASK; + value |= (s->regs[reg] & FIU_UMA_CFG_CMMLCK_MASK); + } + /* fall through */ + case NPCM7XX_FIU_DRD_CFG: + case NPCM7XX_FIU_DWR_CFG: + if (s->regs[reg] & NPCM7XX_FIU_CFG_LCK) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: write to locked register @ 0x%" PRIx64 "\n", + DEVICE(s)->canonical_path, addr); + return; + } + s->regs[reg] = value; + break; + + case NPCM7XX_FIU_UMA_CTS: + if (value & FIU_UMA_CTS_RDYST) { + value &= ~FIU_UMA_CTS_RDYST; + } else { + value |= s->regs[reg] & FIU_UMA_CTS_RDYST; + } + if ((s->regs[reg] ^ value) & FIU_UMA_CTS_SW_CS) { + if (value & FIU_UMA_CTS_SW_CS) { + /* + * Don't drop CS if there's a transfer in progress, or we're + * about to start one. + */ + if (!((value | s->regs[reg]) & FIU_UMA_CTS_EXEC_DONE)) { + npcm7xx_fiu_deselect(s); + } + } else { + int cs_id = FIU_UMA_CTS_DEV_NUM(s->regs[NPCM7XX_FIU_UMA_CTS]); + npcm7xx_fiu_select(s, cs_id); + } + } + s->regs[reg] = value | (s->regs[reg] & FIU_UMA_CTS_EXEC_DONE); + if (value & FIU_UMA_CTS_EXEC_DONE) { + npcm7xx_fiu_uma_transaction(s); + } + break; + + case NPCM7XX_FIU_UMA_DR0 ... NPCM7XX_FIU_UMA_DR3: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: write to read-only register @ 0x%" PRIx64 "\n", + DEVICE(s)->canonical_path, addr); + return; + + case NPCM7XX_FIU_PRT_CFG: + case NPCM7XX_FIU_PRT_CMD0 ... NPCM7XX_FIU_PRT_CMD9: + qemu_log_mask(LOG_UNIMP, "%s: PRT is not implemented\n", __func__); + break; + + case NPCM7XX_FIU_UMA_CMD: + case NPCM7XX_FIU_UMA_ADDR: + case NPCM7XX_FIU_UMA_DW0 ... NPCM7XX_FIU_UMA_DW3: + case NPCM7XX_FIU_CFG: + s->regs[reg] = value; + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: write to invalid offset 0x%" PRIx64 "\n", + DEVICE(s)->canonical_path, addr); + return; + } +} + +static const MemoryRegionOps npcm7xx_fiu_ctrl_ops = { + .read = npcm7xx_fiu_ctrl_read, + .write = npcm7xx_fiu_ctrl_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + .unaligned = false, + }, +}; + +static void npcm7xx_fiu_enter_reset(Object *obj, ResetType type) +{ + NPCM7xxFIUState *s = NPCM7XX_FIU(obj); + + trace_npcm7xx_fiu_enter_reset(DEVICE(obj)->canonical_path, type); + + memset(s->regs, 0, sizeof(s->regs)); + + s->regs[NPCM7XX_FIU_DRD_CFG] = 0x0300100b; + s->regs[NPCM7XX_FIU_DWR_CFG] = 0x03000002; + s->regs[NPCM7XX_FIU_UMA_CFG] = 0x00000400; + s->regs[NPCM7XX_FIU_UMA_CTS] = 0x00010000; + s->regs[NPCM7XX_FIU_UMA_CMD] = 0x0000000b; + s->regs[NPCM7XX_FIU_PRT_CFG] = 0x00000400; + s->regs[NPCM7XX_FIU_CFG] = 0x0000000b; +} + +static void npcm7xx_fiu_hold_reset(Object *obj) +{ + NPCM7xxFIUState *s = NPCM7XX_FIU(obj); + int i; + + trace_npcm7xx_fiu_hold_reset(DEVICE(obj)->canonical_path); + + for (i = 0; i < s->cs_count; i++) { + qemu_irq_raise(s->cs_lines[i]); + } +} + +static void npcm7xx_fiu_realize(DeviceState *dev, Error **errp) +{ + NPCM7xxFIUState *s = NPCM7XX_FIU(dev); + SysBusDevice *sbd = &s->parent; + int i; + + if (s->cs_count <= 0) { + error_setg(errp, "%s: %d chip selects specified, need at least one", + dev->canonical_path, s->cs_count); + return; + } + + s->spi = ssi_create_bus(dev, "spi"); + s->cs_lines = g_new0(qemu_irq, s->cs_count); + qdev_init_gpio_out_named(DEVICE(s), s->cs_lines, "cs", s->cs_count); + s->flash = g_new0(NPCM7xxFIUFlash, s->cs_count); + + /* + * Register the control registers region first. It may be followed by one + * or more direct flash access regions. + */ + memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_fiu_ctrl_ops, s, "ctrl", + NPCM7XX_FIU_CTRL_REGS_SIZE); + sysbus_init_mmio(sbd, &s->mmio); + + for (i = 0; i < s->cs_count; i++) { + NPCM7xxFIUFlash *flash = &s->flash[i]; + flash->fiu = s; + memory_region_init_io(&flash->direct_access, OBJECT(s), + &npcm7xx_fiu_flash_ops, &s->flash[i], "flash", + NPCM7XX_FIU_FLASH_WINDOW_SIZE); + sysbus_init_mmio(sbd, &flash->direct_access); + } +} + +static const VMStateDescription vmstate_npcm7xx_fiu = { + .name = "npcm7xx-fiu", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_INT32(active_cs, NPCM7xxFIUState), + VMSTATE_UINT32_ARRAY(regs, NPCM7xxFIUState, NPCM7XX_FIU_NR_REGS), + VMSTATE_END_OF_LIST(), + }, +}; + +static Property npcm7xx_fiu_properties[] = { + DEFINE_PROP_INT32("cs-count", NPCM7xxFIUState, cs_count, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void npcm7xx_fiu_class_init(ObjectClass *klass, void *data) +{ + ResettableClass *rc = RESETTABLE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + QEMU_BUILD_BUG_ON(NPCM7XX_FIU_REGS_END > NPCM7XX_FIU_NR_REGS); + + dc->desc = "NPCM7xx Flash Interface Unit"; + dc->realize = npcm7xx_fiu_realize; + dc->vmsd = &vmstate_npcm7xx_fiu; + rc->phases.enter = npcm7xx_fiu_enter_reset; + rc->phases.hold = npcm7xx_fiu_hold_reset; + device_class_set_props(dc, npcm7xx_fiu_properties); +} + +static const TypeInfo npcm7xx_fiu_types[] = { + { + .name = TYPE_NPCM7XX_FIU, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(NPCM7xxFIUState), + .class_init = npcm7xx_fiu_class_init, + }, +}; +DEFINE_TYPES(npcm7xx_fiu_types); diff --git a/hw/ssi/ssi.c b/hw/ssi/ssi.c index c6415eb6e329ee78f822f67231921e08646f124d..4278d0e4440a44f49c669eb60ec159a7f189787e 100644 --- a/hw/ssi/ssi.c +++ b/hw/ssi/ssi.c @@ -16,13 +16,15 @@ #include "hw/ssi/ssi.h" #include "migration/vmstate.h" #include "qemu/module.h" +#include "qapi/error.h" +#include "qom/object.h" struct SSIBus { BusState parent_obj; }; #define TYPE_SSI_BUS "SSI" -#define SSI_BUS(obj) OBJECT_CHECK(SSIBus, (obj), TYPE_SSI_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(SSIBus, SSI_BUS) static const TypeInfo ssi_bus_info = { .name = TYPE_SSI_BUS, @@ -89,16 +91,16 @@ static const TypeInfo ssi_slave_info = { .abstract = true, }; -DeviceState *ssi_create_slave_no_init(SSIBus *bus, const char *name) +bool ssi_realize_and_unref(DeviceState *dev, SSIBus *bus, Error **errp) { - return qdev_create(BUS(bus), name); + return qdev_realize_and_unref(dev, &bus->parent_obj, errp); } DeviceState *ssi_create_slave(SSIBus *bus, const char *name) { - DeviceState *dev = ssi_create_slave_no_init(bus, name); + DeviceState *dev = qdev_new(name); - qdev_init_nofail(dev); + ssi_realize_and_unref(dev, bus, &error_fatal); return dev; } @@ -142,36 +144,3 @@ static void ssi_slave_register_types(void) } type_init(ssi_slave_register_types) - -typedef struct SSIAutoConnectArg { - qemu_irq **cs_linep; - SSIBus *bus; -} SSIAutoConnectArg; - -static int ssi_auto_connect_slave(Object *child, void *opaque) -{ - SSIAutoConnectArg *arg = opaque; - SSISlave *dev = (SSISlave *)object_dynamic_cast(child, TYPE_SSI_SLAVE); - qemu_irq cs_line; - - if (!dev) { - return 0; - } - - cs_line = qdev_get_gpio_in_named(DEVICE(dev), SSI_GPIO_CS, 0); - qdev_set_parent_bus(DEVICE(dev), BUS(arg->bus)); - **arg->cs_linep = cs_line; - (*arg->cs_linep)++; - return 0; -} - -void ssi_auto_connect_slaves(DeviceState *parent, qemu_irq *cs_line, - SSIBus *bus) -{ - SSIAutoConnectArg arg = { - .cs_linep = &cs_line, - .bus = bus - }; - - object_child_foreach(OBJECT(parent), ssi_auto_connect_slave, &arg); -} diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events index 0ea498de910b2e18c969579c338a94528df25b83..612d3d6087aaa5d465019b31373c6ecd39380be5 100644 --- a/hw/ssi/trace-events +++ b/hw/ssi/trace-events @@ -9,3 +9,14 @@ aspeed_smc_dma_checksum(uint32_t addr, uint32_t data) "0x%08x: 0x%08x" aspeed_smc_dma_rw(const char *dir, uint32_t flash_addr, uint32_t dram_addr, uint32_t size) "%s flash:@0x%08x dram:@0x%08x size:0x%08x" aspeed_smc_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64 aspeed_smc_flash_select(int cs, const char *prefix) "CS%d %sselect" + +# npcm7xx_fiu.c + +npcm7xx_fiu_enter_reset(const char *id, int reset_type) "%s reset type: %d" +npcm7xx_fiu_hold_reset(const char *id) "%s" +npcm7xx_fiu_select(const char *id, int cs) "%s select CS%d" +npcm7xx_fiu_deselect(const char *id, int cs) "%s deselect CS%d" +npcm7xx_fiu_ctrl_read(const char *id, uint64_t addr, uint32_t data) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 +npcm7xx_fiu_ctrl_write(const char *id, uint64_t addr, uint32_t data) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 +npcm7xx_fiu_flash_read(const char *id, int cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64 +npcm7xx_fiu_flash_write(const char *id, unsigned cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64 diff --git a/hw/ssi/trace.h b/hw/ssi/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..0c1de2679ec49ca3868f87ec0a09342b3c6ebed9 --- /dev/null +++ b/hw/ssi/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_ssi.h" diff --git a/hw/ssi/xilinx_spi.c b/hw/ssi/xilinx_spi.c index eba7ccd46a7678dddc59e108a36209a3b7ee6ecb..49ff27559355cc743cb912a8705caf757ac54972 100644 --- a/hw/ssi/xilinx_spi.c +++ b/hw/ssi/xilinx_spi.c @@ -34,6 +34,7 @@ #include "hw/irq.h" #include "hw/qdev-properties.h" #include "hw/ssi/ssi.h" +#include "qom/object.h" #ifdef XILINX_SPI_ERR_DEBUG #define DB_PRINT(...) do { \ @@ -78,9 +79,9 @@ #define FIFO_CAPACITY 256 #define TYPE_XILINX_SPI "xlnx.xps-spi" -#define XILINX_SPI(obj) OBJECT_CHECK(XilinxSPI, (obj), TYPE_XILINX_SPI) +OBJECT_DECLARE_SIMPLE_TYPE(XilinxSPI, XILINX_SPI) -typedef struct XilinxSPI { +struct XilinxSPI { SysBusDevice parent_obj; MemoryRegion mmio; @@ -97,7 +98,7 @@ typedef struct XilinxSPI { Fifo8 tx_fifo; uint32_t regs[R_MAX]; -} XilinxSPI; +}; static void txfifo_reset(XilinxSPI *s) { @@ -141,7 +142,7 @@ static void xlx_spi_update_irq(XilinxSPI *s) irq chain unless things really changed. */ if (pending != s->irqline) { s->irqline = pending; - DB_PRINT("irq_change of state %d ISR:%x IER:%X\n", + DB_PRINT("irq_change of state %u ISR:%x IER:%X\n", pending, s->regs[R_IPISR], s->regs[R_IPIER]); qemu_set_irq(s->irq, pending); } @@ -334,7 +335,6 @@ static void xilinx_spi_realize(DeviceState *dev, Error **errp) sysbus_init_irq(sbd, &s->irq); s->cs_lines = g_new0(qemu_irq, s->num_cs); - ssi_auto_connect_slaves(dev, s->cs_lines, s->spi); for (i = 0; i < s->num_cs; ++i) { sysbus_init_irq(sbd, &s->cs_lines[i]); } diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c index e76cf290c8f5b80bd1f791a28483cb4ef08310fb..b9371dbf8d76153298a3ba2866de6e14e1481862 100644 --- a/hw/ssi/xilinx_spips.c +++ b/hw/ssi/xilinx_spips.c @@ -1270,7 +1270,6 @@ static void xilinx_spips_realize(DeviceState *dev, Error **errp) XilinxSPIPS *s = XILINX_SPIPS(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); XilinxSPIPSClass *xsc = XILINX_SPIPS_GET_CLASS(s); - qemu_irq *cs; int i; DB_PRINT_L(0, "realized spips\n"); @@ -1297,9 +1296,6 @@ static void xilinx_spips_realize(DeviceState *dev, Error **errp) s->cs_lines = g_new0(qemu_irq, s->num_cs * s->num_busses); s->cs_lines_state = g_new0(bool, s->num_cs * s->num_busses); - for (i = 0, cs = s->cs_lines; i < s->num_busses; ++i, cs += s->num_cs) { - ssi_auto_connect_slaves(DEVICE(s), cs, s->spi[i]); - } sysbus_init_irq(sbd, &s->irq); for (i = 0; i < s->num_cs * s->num_busses; ++i) { diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig index 59b3f44d693eb0b5ade68a8010c1f62b1e27ecd3..8749edfb6a5249eb3dcb0f952e0268debbb889ae 100644 --- a/hw/timer/Kconfig +++ b/hw/timer/Kconfig @@ -35,3 +35,12 @@ config CMSDK_APB_TIMER config CMSDK_APB_DUALTIMER bool select PTIMER + +config RENESAS_TMR + bool + +config RENESAS_CMT + bool + +config AVR_TIMER16 + bool diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs deleted file mode 100644 index dece235fd72e69567f57bf26fff220859184d942..0000000000000000000000000000000000000000 --- a/hw/timer/Makefile.objs +++ /dev/null @@ -1,37 +0,0 @@ -common-obj-$(CONFIG_ARM_TIMER) += arm_timer.o -common-obj-$(CONFIG_ARM_MPTIMER) += arm_mptimer.o -common-obj-$(CONFIG_ARM_V7M) += armv7m_systick.o -common-obj-$(CONFIG_A9_GTIMER) += a9gtimer.o -common-obj-$(CONFIG_CADENCE) += cadence_ttc.o -common-obj-$(CONFIG_HPET) += hpet.o -common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o -common-obj-$(CONFIG_PUV3) += puv3_ost.o -common-obj-$(CONFIG_XILINX) += xilinx_timer.o -common-obj-$(CONFIG_SLAVIO) += slavio_timer.o -common-obj-$(CONFIG_ETRAXFS) += etraxfs_timer.o -common-obj-$(CONFIG_GRLIB) += grlib_gptimer.o -common-obj-$(CONFIG_IMX) += imx_epit.o -common-obj-$(CONFIG_IMX) += imx_gpt.o -common-obj-$(CONFIG_LM32) += lm32_timer.o -common-obj-$(CONFIG_MILKYMIST) += milkymist-sysctl.o -common-obj-$(CONFIG_NRF51_SOC) += nrf51_timer.o - -common-obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o -common-obj-$(CONFIG_EXYNOS4) += exynos4210_mct.o -common-obj-$(CONFIG_EXYNOS4) += exynos4210_pwm.o -common-obj-$(CONFIG_OMAP) += omap_gptimer.o -common-obj-$(CONFIG_OMAP) += omap_synctimer.o -common-obj-$(CONFIG_PXA2XX) += pxa2xx_timer.o -common-obj-$(CONFIG_SH4) += sh_timer.o -common-obj-$(CONFIG_DIGIC) += digic-timer.o -common-obj-$(CONFIG_MIPS_CPS) += mips_gictimer.o - -common-obj-$(CONFIG_ALLWINNER_A10_PIT) += allwinner-a10-pit.o - -common-obj-$(CONFIG_STM32F2XX_TIMER) += stm32f2xx_timer.o -common-obj-$(CONFIG_ASPEED_SOC) += aspeed_timer.o - -common-obj-$(CONFIG_CMSDK_APB_TIMER) += cmsdk-apb-timer.o -common-obj-$(CONFIG_CMSDK_APB_DUALTIMER) += cmsdk-apb-dualtimer.o -common-obj-$(CONFIG_MSF2) += mss-timer.o -common-obj-$(CONFIG_RASPI) += bcm2835_systmr.o diff --git a/hw/timer/altera_timer.c b/hw/timer/altera_timer.c index be81b7a5182aa685ef6601e5e9243a2c4e69090f..c6e02d2b5a7c8b5fe8efb88d5e359b33bf189337 100644 --- a/hw/timer/altera_timer.c +++ b/hw/timer/altera_timer.c @@ -26,6 +26,7 @@ #include "hw/irq.h" #include "hw/ptimer.h" #include "hw/qdev-properties.h" +#include "qom/object.h" #define R_STATUS 0 #define R_CONTROL 1 @@ -44,17 +45,16 @@ #define CONTROL_STOP 0x0008 #define TYPE_ALTERA_TIMER "ALTR.timer" -#define ALTERA_TIMER(obj) \ - OBJECT_CHECK(AlteraTimer, (obj), TYPE_ALTERA_TIMER) +OBJECT_DECLARE_SIMPLE_TYPE(AlteraTimer, ALTERA_TIMER) -typedef struct AlteraTimer { +struct AlteraTimer { SysBusDevice busdev; MemoryRegion mmio; qemu_irq irq; uint32_t freq_hz; ptimer_state *ptimer; uint32_t regs[R_MAX]; -} AlteraTimer; +}; static int timer_irq_state(AlteraTimer *t) { diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c index 9607366d78d3131ab355e4dfb13f6a8759551727..98e70b2d262b174ab32781e9904ec714c94a0df6 100644 --- a/hw/timer/arm_timer.c +++ b/hw/timer/arm_timer.c @@ -16,6 +16,7 @@ #include "hw/qdev-properties.h" #include "qemu/module.h" #include "qemu/log.h" +#include "qom/object.h" /* Common timer implementation. */ @@ -190,9 +191,9 @@ static arm_timer_state *arm_timer_init(uint32_t freq) */ #define TYPE_SP804 "sp804" -#define SP804(obj) OBJECT_CHECK(SP804State, (obj), TYPE_SP804) +OBJECT_DECLARE_SIMPLE_TYPE(SP804State, SP804) -typedef struct SP804State { +struct SP804State { SysBusDevice parent_obj; MemoryRegion iomem; @@ -200,7 +201,7 @@ typedef struct SP804State { uint32_t freq0, freq1; int level[2]; qemu_irq irq; -} SP804State; +}; static const uint8_t sp804_ids[] = { /* Timer ID */ @@ -310,15 +311,14 @@ static void sp804_realize(DeviceState *dev, Error **errp) /* Integrator/CP timer module. */ #define TYPE_INTEGRATOR_PIT "integrator_pit" -#define INTEGRATOR_PIT(obj) \ - OBJECT_CHECK(icp_pit_state, (obj), TYPE_INTEGRATOR_PIT) +OBJECT_DECLARE_SIMPLE_TYPE(icp_pit_state, INTEGRATOR_PIT) -typedef struct { +struct icp_pit_state { SysBusDevice parent_obj; MemoryRegion iomem; arm_timer_state *timer[3]; -} icp_pit_state; +}; static uint64_t icp_pit_read(void *opaque, hwaddr offset, unsigned size) diff --git a/hw/timer/armv7m_systick.c b/hw/timer/armv7m_systick.c index 74c58bcf245338e70fde5f8935b8bd7e3ed8eb94..2f192011eb045092a8962015ea9d820fb8dffdc4 100644 --- a/hw/timer/armv7m_systick.c +++ b/hw/timer/armv7m_systick.c @@ -39,26 +39,6 @@ static inline int64_t systick_scale(SysTickState *s) } } -static void systick_reload(SysTickState *s, int reset) -{ - /* The Cortex-M3 Devices Generic User Guide says that "When the - * ENABLE bit is set to 1, the counter loads the RELOAD value from the - * SYST RVR register and then counts down". So, we need to check the - * ENABLE bit before reloading the value. - */ - trace_systick_reload(); - - if ((s->control & SYSTICK_ENABLE) == 0) { - return; - } - - if (reset) { - s->tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - } - s->tick += (s->reload + 1) * systick_scale(s); - timer_mod(s->timer, s->tick); -} - static void systick_timer_tick(void *opaque) { SysTickState *s = (SysTickState *)opaque; @@ -70,10 +50,12 @@ static void systick_timer_tick(void *opaque) /* Tell the NVIC to pend the SysTick exception */ qemu_irq_pulse(s->irq); } - if (s->reload == 0) { - s->control &= ~SYSTICK_ENABLE; - } else { - systick_reload(s, 0); + if (ptimer_get_limit(s->ptimer) == 0) { + /* + * Timer expiry with SYST_RVR zero disables the timer + * (but doesn't clear SYST_CSR.ENABLE) + */ + ptimer_stop(s->ptimer); } } @@ -94,30 +76,11 @@ static MemTxResult systick_read(void *opaque, hwaddr addr, uint64_t *data, s->control &= ~SYSTICK_COUNTFLAG; break; case 0x4: /* SysTick Reload Value. */ - val = s->reload; + val = ptimer_get_limit(s->ptimer); break; case 0x8: /* SysTick Current Value. */ - { - int64_t t; - - if ((s->control & SYSTICK_ENABLE) == 0) { - val = 0; - break; - } - t = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - if (t >= s->tick) { - val = 0; - break; - } - val = ((s->tick - (t + 1)) / systick_scale(s)) + 1; - /* The interrupt in triggered when the timer reaches zero. - However the counter is not reloaded until the next clock - tick. This is a hack to return zero during the first tick. */ - if (val > s->reload) { - val = 0; - } + val = ptimer_get_count(s->ptimer); break; - } case 0xc: /* SysTick Calibration Value. */ val = 10000; break; @@ -149,39 +112,50 @@ static MemTxResult systick_write(void *opaque, hwaddr addr, switch (addr) { case 0x0: /* SysTick Control and Status. */ { - uint32_t oldval = s->control; + uint32_t oldval; + ptimer_transaction_begin(s->ptimer); + oldval = s->control; s->control &= 0xfffffff8; s->control |= value & 7; + if ((oldval ^ value) & SYSTICK_ENABLE) { - int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); if (value & SYSTICK_ENABLE) { - if (s->tick) { - s->tick += now; - timer_mod(s->timer, s->tick); - } else { - systick_reload(s, 1); - } + /* + * Always reload the period in case board code has + * changed system_clock_scale. If we ever replace that + * global with a more sensible API then we might be able + * to set the period only when it actually changes. + */ + ptimer_set_period(s->ptimer, systick_scale(s)); + ptimer_run(s->ptimer, 0); } else { - timer_del(s->timer); - s->tick -= now; - if (s->tick < 0) { - s->tick = 0; - } + ptimer_stop(s->ptimer); } } else if ((oldval ^ value) & SYSTICK_CLKSOURCE) { - /* This is a hack. Force the timer to be reloaded - when the reference clock is changed. */ - systick_reload(s, 1); + ptimer_set_period(s->ptimer, systick_scale(s)); } + ptimer_transaction_commit(s->ptimer); break; } case 0x4: /* SysTick Reload Value. */ - s->reload = value; + ptimer_transaction_begin(s->ptimer); + ptimer_set_limit(s->ptimer, value & 0xffffff, 0); + ptimer_transaction_commit(s->ptimer); break; - case 0x8: /* SysTick Current Value. Writes reload the timer. */ - systick_reload(s, 1); + case 0x8: /* SysTick Current Value. */ + /* + * Writing any value clears SYST_CVR to zero and clears + * SYST_CSR.COUNTFLAG. The counter will then reload from SYST_RVR + * on the next clock edge unless SYST_RVR is zero. + */ + ptimer_transaction_begin(s->ptimer); + if (ptimer_get_limit(s->ptimer) == 0) { + ptimer_stop(s->ptimer); + } + ptimer_set_count(s->ptimer, 0); s->control &= ~SYSTICK_COUNTFLAG; + ptimer_transaction_commit(s->ptimer); break; default: qemu_log_mask(LOG_GUEST_ERROR, @@ -202,10 +176,21 @@ static void systick_reset(DeviceState *dev) { SysTickState *s = SYSTICK(dev); + /* + * Forgetting to set system_clock_scale is always a board code + * bug. We can't check this earlier because for some boards + * (like stellaris) it is not yet configured at the point where + * the systick device is realized. + */ + assert(system_clock_scale != 0); + + ptimer_transaction_begin(s->ptimer); s->control = 0; - s->reload = 0; - s->tick = 0; - timer_del(s->timer); + ptimer_stop(s->ptimer); + ptimer_set_count(s->ptimer, 0); + ptimer_set_limit(s->ptimer, 0, 0); + ptimer_set_period(s->ptimer, systick_scale(s)); + ptimer_transaction_commit(s->ptimer); } static void systick_instance_init(Object *obj) @@ -221,18 +206,21 @@ static void systick_instance_init(Object *obj) static void systick_realize(DeviceState *dev, Error **errp) { SysTickState *s = SYSTICK(dev); - s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, systick_timer_tick, s); + s->ptimer = ptimer_init(systick_timer_tick, s, + PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD | + PTIMER_POLICY_NO_COUNTER_ROUND_DOWN | + PTIMER_POLICY_NO_IMMEDIATE_RELOAD | + PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT); } static const VMStateDescription vmstate_systick = { .name = "armv7m_systick", - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .fields = (VMStateField[]) { VMSTATE_UINT32(control, SysTickState), - VMSTATE_UINT32(reload, SysTickState), VMSTATE_INT64(tick, SysTickState), - VMSTATE_TIMER_PTR(timer, SysTickState), + VMSTATE_PTIMER(ptimer, SysTickState), VMSTATE_END_OF_LIST() } }; diff --git a/hw/timer/avr_timer16.c b/hw/timer/avr_timer16.c new file mode 100644 index 0000000000000000000000000000000000000000..c48555da5254370efb069460b0ee805430902e2e --- /dev/null +++ b/hw/timer/avr_timer16.c @@ -0,0 +1,621 @@ +/* + * AVR 16-bit timer + * + * Copyright (c) 2018 University of Kent + * Author: Ed Robbins + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * + */ + +/* + * Driver for 16 bit timers on 8 bit AVR devices. + * Note: + * ATmega640/V-1280/V-1281/V-2560/V-2561/V timers 1, 3, 4 and 5 are 16 bit + */ + +/* + * XXX TODO: Power Reduction Register support + * prescaler pause support + * PWM modes, GPIO, output capture pins, input compare pin + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/timer/avr_timer16.h" +#include "trace.h" + +/* Register offsets */ +#define T16_CRA 0x0 +#define T16_CRB 0x1 +#define T16_CRC 0x2 +#define T16_CNTL 0x4 +#define T16_CNTH 0x5 +#define T16_ICRL 0x6 +#define T16_ICRH 0x7 +#define T16_OCRAL 0x8 +#define T16_OCRAH 0x9 +#define T16_OCRBL 0xa +#define T16_OCRBH 0xb +#define T16_OCRCL 0xc +#define T16_OCRCH 0xd + +/* Field masks */ +#define T16_CRA_WGM01 0x3 +#define T16_CRA_COMC 0xc +#define T16_CRA_COMB 0x30 +#define T16_CRA_COMA 0xc0 +#define T16_CRA_OC_CONF \ + (T16_CRA_COMA | T16_CRA_COMB | T16_CRA_COMC) + +#define T16_CRB_CS 0x7 +#define T16_CRB_WGM23 0x18 +#define T16_CRB_ICES 0x40 +#define T16_CRB_ICNC 0x80 + +#define T16_CRC_FOCC 0x20 +#define T16_CRC_FOCB 0x40 +#define T16_CRC_FOCA 0x80 + +/* Fields masks both TIMSK and TIFR (interrupt mask/flag registers) */ +#define T16_INT_TOV 0x1 /* Timer overflow */ +#define T16_INT_OCA 0x2 /* Output compare A */ +#define T16_INT_OCB 0x4 /* Output compare B */ +#define T16_INT_OCC 0x8 /* Output compare C */ +#define T16_INT_IC 0x20 /* Input capture */ + +/* Clock source values */ +#define T16_CLKSRC_STOPPED 0 +#define T16_CLKSRC_DIV1 1 +#define T16_CLKSRC_DIV8 2 +#define T16_CLKSRC_DIV64 3 +#define T16_CLKSRC_DIV256 4 +#define T16_CLKSRC_DIV1024 5 +#define T16_CLKSRC_EXT_FALLING 6 +#define T16_CLKSRC_EXT_RISING 7 + +/* Timer mode values (not including PWM modes) */ +#define T16_MODE_NORMAL 0 +#define T16_MODE_CTC_OCRA 4 +#define T16_MODE_CTC_ICR 12 + +/* Accessors */ +#define CLKSRC(t16) (t16->crb & T16_CRB_CS) +#define MODE(t16) (((t16->crb & T16_CRB_WGM23) >> 1) | \ + (t16->cra & T16_CRA_WGM01)) +#define CNT(t16) VAL16(t16->cntl, t16->cnth) +#define OCRA(t16) VAL16(t16->ocral, t16->ocrah) +#define OCRB(t16) VAL16(t16->ocrbl, t16->ocrbh) +#define OCRC(t16) VAL16(t16->ocrcl, t16->ocrch) +#define ICR(t16) VAL16(t16->icrl, t16->icrh) + +/* Helper macros */ +#define VAL16(l, h) ((h << 8) | l) +#define DB_PRINT(fmt, args...) /* Nothing */ + +static inline int64_t avr_timer16_ns_to_ticks(AVRTimer16State *t16, int64_t t) +{ + if (t16->period_ns == 0) { + return 0; + } + return t / t16->period_ns; +} + +static void avr_timer16_update_cnt(AVRTimer16State *t16) +{ + uint16_t cnt; + cnt = avr_timer16_ns_to_ticks(t16, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - + t16->reset_time_ns); + t16->cntl = (uint8_t)(cnt & 0xff); + t16->cnth = (uint8_t)((cnt & 0xff00) >> 8); +} + +static inline void avr_timer16_recalc_reset_time(AVRTimer16State *t16) +{ + t16->reset_time_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - + CNT(t16) * t16->period_ns; +} + +static void avr_timer16_clock_reset(AVRTimer16State *t16) +{ + t16->cntl = 0; + t16->cnth = 0; + t16->reset_time_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +} + +static void avr_timer16_clksrc_update(AVRTimer16State *t16) +{ + uint16_t divider = 0; + switch (CLKSRC(t16)) { + case T16_CLKSRC_EXT_FALLING: + case T16_CLKSRC_EXT_RISING: + qemu_log_mask(LOG_UNIMP, "%s: external clock source unsupported\n", + __func__); + break; + case T16_CLKSRC_STOPPED: + break; + case T16_CLKSRC_DIV1: + divider = 1; + break; + case T16_CLKSRC_DIV8: + divider = 8; + break; + case T16_CLKSRC_DIV64: + divider = 64; + break; + case T16_CLKSRC_DIV256: + divider = 256; + break; + case T16_CLKSRC_DIV1024: + divider = 1024; + break; + default: + break; + } + if (divider) { + t16->freq_hz = t16->cpu_freq_hz / divider; + t16->period_ns = NANOSECONDS_PER_SECOND / t16->freq_hz; + trace_avr_timer16_clksrc_update(t16->freq_hz, t16->period_ns, + (uint64_t)(1e6 / t16->freq_hz)); + } +} + +static void avr_timer16_set_alarm(AVRTimer16State *t16) +{ + if (CLKSRC(t16) == T16_CLKSRC_EXT_FALLING || + CLKSRC(t16) == T16_CLKSRC_EXT_RISING || + CLKSRC(t16) == T16_CLKSRC_STOPPED) { + /* Timer is disabled or set to external clock source (unsupported) */ + return; + } + + uint64_t alarm_offset = 0xffff; + enum NextInterrupt next_interrupt = OVERFLOW; + + switch (MODE(t16)) { + case T16_MODE_NORMAL: + /* Normal mode */ + if (OCRA(t16) < alarm_offset && OCRA(t16) > CNT(t16) && + (t16->imsk & T16_INT_OCA)) { + alarm_offset = OCRA(t16); + next_interrupt = COMPA; + } + break; + case T16_MODE_CTC_OCRA: + /* CTC mode, top = ocra */ + if (OCRA(t16) < alarm_offset && OCRA(t16) > CNT(t16)) { + alarm_offset = OCRA(t16); + next_interrupt = COMPA; + } + break; + case T16_MODE_CTC_ICR: + /* CTC mode, top = icr */ + if (ICR(t16) < alarm_offset && ICR(t16) > CNT(t16)) { + alarm_offset = ICR(t16); + next_interrupt = CAPT; + } + if (OCRA(t16) < alarm_offset && OCRA(t16) > CNT(t16) && + (t16->imsk & T16_INT_OCA)) { + alarm_offset = OCRA(t16); + next_interrupt = COMPA; + } + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: pwm modes are unsupported\n", + __func__); + return; + } + if (OCRB(t16) < alarm_offset && OCRB(t16) > CNT(t16) && + (t16->imsk & T16_INT_OCB)) { + alarm_offset = OCRB(t16); + next_interrupt = COMPB; + } + if (OCRC(t16) < alarm_offset && OCRB(t16) > CNT(t16) && + (t16->imsk & T16_INT_OCC)) { + alarm_offset = OCRB(t16); + next_interrupt = COMPC; + } + alarm_offset -= CNT(t16); + + t16->next_interrupt = next_interrupt; + uint64_t alarm_ns = + t16->reset_time_ns + ((CNT(t16) + alarm_offset) * t16->period_ns); + timer_mod(t16->timer, alarm_ns); + + trace_avr_timer16_next_alarm(alarm_offset * t16->period_ns); +} + +static void avr_timer16_interrupt(void *opaque) +{ + AVRTimer16State *t16 = opaque; + uint8_t mode = MODE(t16); + + avr_timer16_update_cnt(t16); + + if (CLKSRC(t16) == T16_CLKSRC_EXT_FALLING || + CLKSRC(t16) == T16_CLKSRC_EXT_RISING || + CLKSRC(t16) == T16_CLKSRC_STOPPED) { + /* Timer is disabled or set to external clock source (unsupported) */ + return; + } + + trace_avr_timer16_interrupt_count(CNT(t16)); + + /* Counter overflow */ + if (t16->next_interrupt == OVERFLOW) { + trace_avr_timer16_interrupt_overflow("counter 0xffff"); + avr_timer16_clock_reset(t16); + if (t16->imsk & T16_INT_TOV) { + t16->ifr |= T16_INT_TOV; + qemu_set_irq(t16->ovf_irq, 1); + } + } + /* Check for ocra overflow in CTC mode */ + if (mode == T16_MODE_CTC_OCRA && t16->next_interrupt == COMPA) { + trace_avr_timer16_interrupt_overflow("CTC OCRA"); + avr_timer16_clock_reset(t16); + } + /* Check for icr overflow in CTC mode */ + if (mode == T16_MODE_CTC_ICR && t16->next_interrupt == CAPT) { + trace_avr_timer16_interrupt_overflow("CTC ICR"); + avr_timer16_clock_reset(t16); + if (t16->imsk & T16_INT_IC) { + t16->ifr |= T16_INT_IC; + qemu_set_irq(t16->capt_irq, 1); + } + } + /* Check for output compare interrupts */ + if (t16->imsk & T16_INT_OCA && t16->next_interrupt == COMPA) { + t16->ifr |= T16_INT_OCA; + qemu_set_irq(t16->compa_irq, 1); + } + if (t16->imsk & T16_INT_OCB && t16->next_interrupt == COMPB) { + t16->ifr |= T16_INT_OCB; + qemu_set_irq(t16->compb_irq, 1); + } + if (t16->imsk & T16_INT_OCC && t16->next_interrupt == COMPC) { + t16->ifr |= T16_INT_OCC; + qemu_set_irq(t16->compc_irq, 1); + } + avr_timer16_set_alarm(t16); +} + +static void avr_timer16_reset(DeviceState *dev) +{ + AVRTimer16State *t16 = AVR_TIMER16(dev); + + avr_timer16_clock_reset(t16); + avr_timer16_clksrc_update(t16); + avr_timer16_set_alarm(t16); + + qemu_set_irq(t16->capt_irq, 0); + qemu_set_irq(t16->compa_irq, 0); + qemu_set_irq(t16->compb_irq, 0); + qemu_set_irq(t16->compc_irq, 0); + qemu_set_irq(t16->ovf_irq, 0); +} + +static uint64_t avr_timer16_read(void *opaque, hwaddr offset, unsigned size) +{ + assert(size == 1); + AVRTimer16State *t16 = opaque; + uint8_t retval = 0; + + switch (offset) { + case T16_CRA: + retval = t16->cra; + break; + case T16_CRB: + retval = t16->crb; + break; + case T16_CRC: + retval = t16->crc; + break; + case T16_CNTL: + avr_timer16_update_cnt(t16); + t16->rtmp = t16->cnth; + retval = t16->cntl; + break; + case T16_CNTH: + retval = t16->rtmp; + break; + case T16_ICRL: + /* + * The timer copies cnt to icr when the input capture pin changes + * state or when the analog comparator has a match. We don't + * emulate this behaviour. We do support it's use for defining a + * TOP value in T16_MODE_CTC_ICR + */ + t16->rtmp = t16->icrh; + retval = t16->icrl; + break; + case T16_ICRH: + retval = t16->rtmp; + break; + case T16_OCRAL: + retval = t16->ocral; + break; + case T16_OCRAH: + retval = t16->ocrah; + break; + case T16_OCRBL: + retval = t16->ocrbl; + break; + case T16_OCRBH: + retval = t16->ocrbh; + break; + case T16_OCRCL: + retval = t16->ocrcl; + break; + case T16_OCRCH: + retval = t16->ocrch; + break; + default: + break; + } + trace_avr_timer16_read(offset, retval); + + return (uint64_t)retval; +} + +static void avr_timer16_write(void *opaque, hwaddr offset, + uint64_t val64, unsigned size) +{ + assert(size == 1); + AVRTimer16State *t16 = opaque; + uint8_t val8 = (uint8_t)val64; + uint8_t prev_clk_src = CLKSRC(t16); + + trace_avr_timer16_write(offset, val8); + + switch (offset) { + case T16_CRA: + t16->cra = val8; + if (t16->cra & T16_CRA_OC_CONF) { + qemu_log_mask(LOG_UNIMP, "%s: output compare pins unsupported\n", + __func__); + } + break; + case T16_CRB: + t16->crb = val8; + if (t16->crb & T16_CRB_ICNC) { + qemu_log_mask(LOG_UNIMP, + "%s: input capture noise canceller unsupported\n", + __func__); + } + if (t16->crb & T16_CRB_ICES) { + qemu_log_mask(LOG_UNIMP, "%s: input capture unsupported\n", + __func__); + } + if (CLKSRC(t16) != prev_clk_src) { + avr_timer16_clksrc_update(t16); + if (prev_clk_src == T16_CLKSRC_STOPPED) { + t16->reset_time_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + } + } + break; + case T16_CRC: + t16->crc = val8; + qemu_log_mask(LOG_UNIMP, "%s: output compare pins unsupported\n", + __func__); + break; + case T16_CNTL: + /* + * CNT is the 16-bit counter value, it must be read/written via + * a temporary register (rtmp) to make the read/write atomic. + */ + /* ICR also has this behaviour, and shares rtmp */ + /* + * Writing CNT blocks compare matches for one clock cycle. + * Writing CNT to TOP or to an OCR value (if in use) will + * skip the relevant interrupt + */ + t16->cntl = val8; + t16->cnth = t16->rtmp; + avr_timer16_recalc_reset_time(t16); + break; + case T16_CNTH: + t16->rtmp = val8; + break; + case T16_ICRL: + /* ICR can only be written in mode T16_MODE_CTC_ICR */ + if (MODE(t16) == T16_MODE_CTC_ICR) { + t16->icrl = val8; + t16->icrh = t16->rtmp; + } + break; + case T16_ICRH: + if (MODE(t16) == T16_MODE_CTC_ICR) { + t16->rtmp = val8; + } + break; + case T16_OCRAL: + /* + * OCRn cause the relevant output compare flag to be raised, and + * trigger an interrupt, when CNT is equal to the value here + */ + t16->ocral = val8; + break; + case T16_OCRAH: + t16->ocrah = val8; + break; + case T16_OCRBL: + t16->ocrbl = val8; + break; + case T16_OCRBH: + t16->ocrbh = val8; + break; + case T16_OCRCL: + t16->ocrcl = val8; + break; + case T16_OCRCH: + t16->ocrch = val8; + break; + default: + break; + } + avr_timer16_set_alarm(t16); +} + +static uint64_t avr_timer16_imsk_read(void *opaque, + hwaddr offset, + unsigned size) +{ + assert(size == 1); + AVRTimer16State *t16 = opaque; + trace_avr_timer16_read_imsk(offset ? 0 : t16->imsk); + if (offset != 0) { + return 0; + } + return t16->imsk; +} + +static void avr_timer16_imsk_write(void *opaque, hwaddr offset, + uint64_t val64, unsigned size) +{ + assert(size == 1); + AVRTimer16State *t16 = opaque; + trace_avr_timer16_write_imsk(val64); + if (offset != 0) { + return; + } + t16->imsk = (uint8_t)val64; +} + +static uint64_t avr_timer16_ifr_read(void *opaque, + hwaddr offset, + unsigned size) +{ + assert(size == 1); + AVRTimer16State *t16 = opaque; + trace_avr_timer16_read_ifr(offset ? 0 : t16->ifr); + if (offset != 0) { + return 0; + } + return t16->ifr; +} + +static void avr_timer16_ifr_write(void *opaque, hwaddr offset, + uint64_t val64, unsigned size) +{ + assert(size == 1); + AVRTimer16State *t16 = opaque; + trace_avr_timer16_write_imsk(val64); + if (offset != 0) { + return; + } + t16->ifr = (uint8_t)val64; +} + +static const MemoryRegionOps avr_timer16_ops = { + .read = avr_timer16_read, + .write = avr_timer16_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = {.max_access_size = 1} +}; + +static const MemoryRegionOps avr_timer16_imsk_ops = { + .read = avr_timer16_imsk_read, + .write = avr_timer16_imsk_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = {.max_access_size = 1} +}; + +static const MemoryRegionOps avr_timer16_ifr_ops = { + .read = avr_timer16_ifr_read, + .write = avr_timer16_ifr_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = {.max_access_size = 1} +}; + +static Property avr_timer16_properties[] = { + DEFINE_PROP_UINT8("id", struct AVRTimer16State, id, 0), + DEFINE_PROP_UINT64("cpu-frequency-hz", struct AVRTimer16State, + cpu_freq_hz, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void avr_timer16_pr(void *opaque, int irq, int level) +{ + AVRTimer16State *s = AVR_TIMER16(opaque); + + s->enabled = !level; + + if (!s->enabled) { + avr_timer16_reset(DEVICE(s)); + } +} + +static void avr_timer16_init(Object *obj) +{ + AVRTimer16State *s = AVR_TIMER16(obj); + + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->capt_irq); + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->compa_irq); + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->compb_irq); + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->compc_irq); + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->ovf_irq); + + memory_region_init_io(&s->iomem, obj, &avr_timer16_ops, + s, "avr-timer16", 0xe); + memory_region_init_io(&s->imsk_iomem, obj, &avr_timer16_imsk_ops, + s, "avr-timer16-intmask", 0x1); + memory_region_init_io(&s->ifr_iomem, obj, &avr_timer16_ifr_ops, + s, "avr-timer16-intflag", 0x1); + + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->imsk_iomem); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->ifr_iomem); + qdev_init_gpio_in(DEVICE(s), avr_timer16_pr, 1); +} + +static void avr_timer16_realize(DeviceState *dev, Error **errp) +{ + AVRTimer16State *s = AVR_TIMER16(dev); + + if (s->cpu_freq_hz == 0) { + error_setg(errp, "AVR timer16: cpu-frequency-hz property must be set"); + return; + } + + s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, avr_timer16_interrupt, s); + s->enabled = true; +} + +static void avr_timer16_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = avr_timer16_reset; + dc->realize = avr_timer16_realize; + device_class_set_props(dc, avr_timer16_properties); +} + +static const TypeInfo avr_timer16_info = { + .name = TYPE_AVR_TIMER16, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AVRTimer16State), + .instance_init = avr_timer16_init, + .class_init = avr_timer16_class_init, +}; + +static void avr_timer16_register_types(void) +{ + type_register_static(&avr_timer16_info); +} + +type_init(avr_timer16_register_types) diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c index 3387a6214a2371392f930b93e872fe6568f76366..67669a57ff351d61f10c068c8c4a871c80769323 100644 --- a/hw/timer/bcm2835_systmr.c +++ b/hw/timer/bcm2835_systmr.c @@ -28,20 +28,13 @@ REG32(COMPARE1, 0x10) REG32(COMPARE2, 0x14) REG32(COMPARE3, 0x18) -static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s) +static void bcm2835_systmr_timer_expire(void *opaque) { - bool enable = !!s->reg.status; + BCM2835SystemTimerCompare *tmr = opaque; - trace_bcm2835_systmr_irq(enable); - qemu_set_irq(s->irq, enable); -} - -static void bcm2835_systmr_update_compare(BCM2835SystemTimerState *s, - unsigned timer_index) -{ - /* TODO fow now, since neither Linux nor U-boot use these timers. */ - qemu_log_mask(LOG_UNIMP, "COMPARE register %u not implemented\n", - timer_index); + trace_bcm2835_systmr_timer_expired(tmr->id); + tmr->state->reg.ctrl_status |= 1 << tmr->id; + qemu_set_irq(tmr->irq, 1); } static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset, @@ -52,7 +45,7 @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset, switch (offset) { case A_CTRL_STATUS: - r = s->reg.status; + r = s->reg.ctrl_status; break; case A_COMPARE0 ... A_COMPARE3: r = s->reg.compare[(offset - A_COMPARE0) >> 2]; @@ -75,19 +68,33 @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset, } static void bcm2835_systmr_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) + uint64_t value64, unsigned size) { BCM2835SystemTimerState *s = BCM2835_SYSTIMER(opaque); + int index; + uint32_t value = value64; + uint32_t triggers_delay_us; + uint64_t now; trace_bcm2835_systmr_write(offset, value); switch (offset) { case A_CTRL_STATUS: - s->reg.status &= ~value; /* Ack */ - bcm2835_systmr_update_irq(s); + s->reg.ctrl_status &= ~value; /* Ack */ + for (index = 0; index < ARRAY_SIZE(s->tmr); index++) { + if (extract32(value, index, 1)) { + trace_bcm2835_systmr_irq_ack(index); + qemu_set_irq(s->tmr[index].irq, 0); + } + } break; case A_COMPARE0 ... A_COMPARE3: - s->reg.compare[(offset - A_COMPARE0) >> 2] = value; - bcm2835_systmr_update_compare(s, (offset - A_COMPARE0) >> 2); + index = (offset - A_COMPARE0) >> 2; + s->reg.compare[index] = value; + now = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL); + /* Compare lower 32-bits of the free-running counter. */ + triggers_delay_us = value - now; + trace_bcm2835_systmr_run(index, triggers_delay_us); + timer_mod(&s->tmr[index].timer, now + triggers_delay_us); break; case A_COUNTER_LOW: case A_COUNTER_HIGH: @@ -125,7 +132,14 @@ static void bcm2835_systmr_realize(DeviceState *dev, Error **errp) memory_region_init_io(&s->iomem, OBJECT(dev), &bcm2835_systmr_ops, s, "bcm2835-sys-timer", 0x20); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); - sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq); + + for (size_t i = 0; i < ARRAY_SIZE(s->tmr); i++) { + s->tmr[i].id = i; + s->tmr[i].state = s; + sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->tmr[i].irq); + timer_init_us(&s->tmr[i].timer, QEMU_CLOCK_VIRTUAL, + bcm2835_systmr_timer_expire, &s->tmr[i]); + } } static const VMStateDescription bcm2835_systmr_vmstate = { @@ -133,8 +147,9 @@ static const VMStateDescription bcm2835_systmr_vmstate = { .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_UINT32(reg.status, BCM2835SystemTimerState), - VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState, 4), + VMSTATE_UINT32(reg.ctrl_status, BCM2835SystemTimerState), + VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState, + BCM2835_SYSTIMER_COUNT), VMSTATE_END_OF_LIST() } }; diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c index b0ba6b2bbaee8602cfc42368c00fc88acc9844cd..64108241ba996f97052c99c8c54f00e58eb4ca8a 100644 --- a/hw/timer/cadence_ttc.c +++ b/hw/timer/cadence_ttc.c @@ -22,6 +22,7 @@ #include "migration/vmstate.h" #include "qemu/module.h" #include "qemu/timer.h" +#include "qom/object.h" #ifdef CADENCE_TTC_ERR_DEBUG #define DB_PRINT(...) do { \ @@ -69,15 +70,14 @@ typedef struct { } CadenceTimerState; #define TYPE_CADENCE_TTC "cadence_ttc" -#define CADENCE_TTC(obj) \ - OBJECT_CHECK(CadenceTTCState, (obj), TYPE_CADENCE_TTC) +OBJECT_DECLARE_SIMPLE_TYPE(CadenceTTCState, CADENCE_TTC) -typedef struct CadenceTTCState { +struct CadenceTTCState { SysBusDevice parent_obj; MemoryRegion iomem; CadenceTimerState timer[3]; -} CadenceTTCState; +}; static void cadence_timer_update(CadenceTimerState *s) { diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c index afe3d30a8ea1dc7b2b75577857b041fdeca21a70..48f2e3ade2f060ddc3ba0430bd1ed32b843d9cfc 100644 --- a/hw/timer/etraxfs_timer.c +++ b/hw/timer/etraxfs_timer.c @@ -30,6 +30,7 @@ #include "qemu/timer.h" #include "hw/irq.h" #include "hw/ptimer.h" +#include "qom/object.h" #define D(x) @@ -48,10 +49,11 @@ #define R_MASKED_INTR 0x54 #define TYPE_ETRAX_FS_TIMER "etraxfs,timer" -#define ETRAX_TIMER(obj) \ - OBJECT_CHECK(ETRAXTimerState, (obj), TYPE_ETRAX_FS_TIMER) +typedef struct ETRAXTimerState ETRAXTimerState; +DECLARE_INSTANCE_CHECKER(ETRAXTimerState, ETRAX_TIMER, + TYPE_ETRAX_FS_TIMER) -typedef struct ETRAXTimerState { +struct ETRAXTimerState { SysBusDevice parent_obj; MemoryRegion mmio; @@ -79,7 +81,7 @@ typedef struct ETRAXTimerState { uint32_t rw_ack_intr; uint32_t r_intr; uint32_t r_masked_intr; -} ETRAXTimerState; +}; static uint64_t timer_read(void *opaque, hwaddr addr, unsigned int size) diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c index 29a4b10676a17189403860847f51d48555c1ae96..439053acd2ac28a0eaecfc1c2541f7cc74c5a51c 100644 --- a/hw/timer/exynos4210_mct.c +++ b/hw/timer/exynos4210_mct.c @@ -62,6 +62,7 @@ #include "hw/arm/exynos4210.h" #include "hw/irq.h" +#include "qom/object.h" //#define DEBUG_MCT @@ -242,10 +243,9 @@ typedef struct { } Exynos4210MCTLT; #define TYPE_EXYNOS4210_MCT "exynos4210.mct" -#define EXYNOS4210_MCT(obj) \ - OBJECT_CHECK(Exynos4210MCTState, (obj), TYPE_EXYNOS4210_MCT) +OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210MCTState, EXYNOS4210_MCT) -typedef struct Exynos4210MCTState { +struct Exynos4210MCTState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -257,7 +257,7 @@ typedef struct Exynos4210MCTState { Exynos4210MCTGT g_timer; uint32_t freq; /* all timers tick frequency, TCLK */ -} Exynos4210MCTState; +}; /*** VMState ***/ static const VMStateDescription vmstate_tick_timer = { @@ -537,7 +537,7 @@ static void exynos4210_gcomp_raise_irq(void *opaque, uint32_t id) /* If CSTAT is pending and IRQ is enabled */ if ((s->reg.int_cstat & G_INT_CSTAT_COMP(id)) && (s->reg.int_enb & G_INT_ENABLE(id))) { - DPRINTF("gcmp timer[%d] IRQ\n", id); + DPRINTF("gcmp timer[%u] IRQ\n", id); qemu_irq_raise(s->irq[id]); } } @@ -1003,7 +1003,7 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState *s) MCT_CFG_GET_DIVIDER(s->reg_mct_cfg)); if (freq != s->freq) { - DPRINTF("freq=%dHz\n", s->freq); + DPRINTF("freq=%uHz\n", s->freq); /* global timer */ tx_ptimer_set_freq(s->g_timer.ptimer_frc, s->freq); diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c index 59a8c08db0fc8773881307de4f598349afed32c7..de181428b47dfd757a316d2bd596e041b00b7556 100644 --- a/hw/timer/exynos4210_pwm.c +++ b/hw/timer/exynos4210_pwm.c @@ -30,6 +30,7 @@ #include "hw/arm/exynos4210.h" #include "hw/irq.h" +#include "qom/object.h" //#define DEBUG_PWM @@ -102,10 +103,9 @@ typedef struct { } Exynos4210PWM; #define TYPE_EXYNOS4210_PWM "exynos4210.pwm" -#define EXYNOS4210_PWM(obj) \ - OBJECT_CHECK(Exynos4210PWMState, (obj), TYPE_EXYNOS4210_PWM) +OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210PWMState, EXYNOS4210_PWM) -typedef struct Exynos4210PWMState { +struct Exynos4210PWMState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -116,7 +116,7 @@ typedef struct Exynos4210PWMState { Exynos4210PWM timer[EXYNOS4210_PWM_TIMERS_NUM]; -} Exynos4210PWMState; +}; /*** VMState ***/ static const VMStateDescription vmstate_exynos4210_pwm = { @@ -169,7 +169,7 @@ static void exynos4210_pwm_update_freq(Exynos4210PWMState *s, uint32_t id) if (freq != s->timer[id].freq) { ptimer_set_freq(s->timer[id].ptimer, s->timer[id].freq); - DPRINTF("freq=%dHz\n", s->timer[id].freq); + DPRINTF("freq=%uHz\n", s->timer[id].freq); } } @@ -183,14 +183,14 @@ static void exynos4210_pwm_tick(void *opaque) uint32_t id = s->id; bool cmp; - DPRINTF("timer %d tick\n", id); + DPRINTF("timer %u tick\n", id); /* set irq status */ p->reg_tint_cstat |= TINT_CSTAT_STATUS(id); /* raise IRQ */ if (p->reg_tint_cstat & TINT_CSTAT_ENABLE(id)) { - DPRINTF("timer %d IRQ\n", id); + DPRINTF("timer %u IRQ\n", id); qemu_irq_raise(p->timer[id].irq); } @@ -202,7 +202,7 @@ static void exynos4210_pwm_tick(void *opaque) } if (cmp) { - DPRINTF("auto reload timer %d count to %x\n", id, + DPRINTF("auto reload timer %u count to %x\n", id, p->timer[id].reg_tcntb); ptimer_set_count(p->timer[id].ptimer, p->timer[id].reg_tcntb); ptimer_run(p->timer[id].ptimer, 1); diff --git a/hw/timer/grlib_gptimer.c b/hw/timer/grlib_gptimer.c index eff0ee3491a0362bbde5719ae946c5026eb9f85c..d51189010975091f064091789c4f8e792a7411f5 100644 --- a/hw/timer/grlib_gptimer.c +++ b/hw/timer/grlib_gptimer.c @@ -32,6 +32,7 @@ #include "qemu/module.h" #include "trace.h" +#include "qom/object.h" #define UNIT_REG_SIZE 16 /* Size of memory mapped regs for the unit */ #define GPTIMER_REG_SIZE 16 /* Size of memory mapped regs for a GPTimer */ @@ -55,11 +56,9 @@ #define COUNTER_RELOAD_OFFSET 0x04 #define TIMER_BASE 0x10 -#define GRLIB_GPTIMER(obj) \ - OBJECT_CHECK(GPTimerUnit, (obj), TYPE_GRLIB_GPTIMER) +OBJECT_DECLARE_SIMPLE_TYPE(GPTimerUnit, GRLIB_GPTIMER) typedef struct GPTimer GPTimer; -typedef struct GPTimerUnit GPTimerUnit; struct GPTimer { struct ptimer_state *ptimer; diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c index 380acfa7c8a5a277a63ecb2be43599cd66eb9951..9520471be2c8e5df1ef356da75e18a6c28fd4228 100644 --- a/hw/timer/hpet.c +++ b/hw/timer/hpet.c @@ -9,7 +9,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -37,6 +37,7 @@ #include "migration/vmstate.h" #include "hw/timer/i8254.h" #include "exec/address-spaces.h" +#include "qom/object.h" //#define HPET_DEBUG #ifdef HPET_DEBUG @@ -47,7 +48,7 @@ #define HPET_MSI_SUPPORT 0 -#define HPET(obj) OBJECT_CHECK(HPETState, (obj), TYPE_HPET) +OBJECT_DECLARE_SIMPLE_TYPE(HPETState, HPET) struct HPETState; typedef struct HPETTimer { /* timers */ @@ -65,7 +66,7 @@ typedef struct HPETTimer { /* timers */ */ } HPETTimer; -typedef struct HPETState { +struct HPETState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -87,7 +88,7 @@ typedef struct HPETState { uint64_t isr; /* interrupt status reg */ uint64_t hpet_counter; /* main counter */ uint8_t hpet_id; /* instance id */ -} HPETState; +}; static uint32_t hpet_in_legacy_mode(HPETState *s) { @@ -416,20 +417,6 @@ static void hpet_del_timer(HPETTimer *t) update_irq(t, 0); } -#ifdef HPET_DEBUG -static uint32_t hpet_ram_readb(void *opaque, hwaddr addr) -{ - printf("qemu: hpet_read b at %" PRIx64 "\n", addr); - return 0; -} - -static uint32_t hpet_ram_readw(void *opaque, hwaddr addr) -{ - printf("qemu: hpet_read w at %" PRIx64 "\n", addr); - return 0; -} -#endif - static uint64_t hpet_ram_read(void *opaque, hwaddr addr, unsigned size) { @@ -509,7 +496,8 @@ static void hpet_ram_write(void *opaque, hwaddr addr, HPETState *s = opaque; uint64_t old_val, new_val, val, index; - DPRINTF("qemu: Enter hpet_ram_writel at %" PRIx64 " = %#x\n", addr, value); + DPRINTF("qemu: Enter hpet_ram_writel at %" PRIx64 " = 0x%" PRIx64 "\n", + addr, value); index = addr; old_val = hpet_ram_read(opaque, addr, 4); new_val = value; @@ -519,7 +507,7 @@ static void hpet_ram_write(void *opaque, hwaddr addr, uint8_t timer_id = (addr - 0x100) / 0x20; HPETTimer *timer = &s->timer[timer_id]; - DPRINTF("qemu: hpet_ram_writel timer_id = %#x\n", timer_id); + DPRINTF("qemu: hpet_ram_writel timer_id = 0x%x\n", timer_id); if (timer_id > s->num_timers) { DPRINTF("qemu: timer id out of range\n"); return; @@ -651,8 +639,8 @@ static void hpet_ram_write(void *opaque, hwaddr addr, } s->hpet_counter = (s->hpet_counter & 0xffffffff00000000ULL) | value; - DPRINTF("qemu: HPET counter written. ctr = %#x -> %" PRIx64 "\n", - value, s->hpet_counter); + DPRINTF("qemu: HPET counter written. ctr = 0x%" PRIx64 " -> " + "%" PRIx64 "\n", value, s->hpet_counter); break; case HPET_COUNTER + 4: if (hpet_enabled(s)) { @@ -660,8 +648,8 @@ static void hpet_ram_write(void *opaque, hwaddr addr, } s->hpet_counter = (s->hpet_counter & 0xffffffffULL) | (((uint64_t)value) << 32); - DPRINTF("qemu: HPET counter + 4 written. ctr = %#x -> %" PRIx64 "\n", - value, s->hpet_counter); + DPRINTF("qemu: HPET counter + 4 written. ctr = 0x%" PRIx64 " -> " + "%" PRIx64 "\n", value, s->hpet_counter); break; default: DPRINTF("qemu: invalid hpet_ram_writel\n"); diff --git a/hw/timer/i8254.c b/hw/timer/i8254.c index 29f62e535603f7a50c8d4c1f987fbc09f338f916..c01ee2c72ace229ecbd37a34f3e4685860a5d7c5 100644 --- a/hw/timer/i8254.c +++ b/hw/timer/i8254.c @@ -28,6 +28,7 @@ #include "qemu/timer.h" #include "hw/timer/i8254.h" #include "hw/timer/i8254_internal.h" +#include "qom/object.h" //#define DEBUG_PIT @@ -36,14 +37,15 @@ #define RW_STATE_WORD0 3 #define RW_STATE_WORD1 4 -#define PIT_CLASS(class) OBJECT_CLASS_CHECK(PITClass, (class), TYPE_I8254) -#define PIT_GET_CLASS(obj) OBJECT_GET_CLASS(PITClass, (obj), TYPE_I8254) +typedef struct PITClass PITClass; +DECLARE_CLASS_CHECKERS(PITClass, PIT, + TYPE_I8254) -typedef struct PITClass { +struct PITClass { PITCommonClass parent_class; DeviceRealize parent_realize; -} PITClass; +}; static void pit_irq_timer_update(PITChannelState *s, int64_t current_time); diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c index baf6338e1a64b99b495c7f04656542d25422b3a0..ebd58254d15fd9d8ca37bbc50592717c2a8b4a1f 100644 --- a/hw/timer/imx_epit.c +++ b/hw/timer/imx_epit.c @@ -199,15 +199,22 @@ static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value, switch (offset >> 2) { case 0: /* CR */ - ptimer_transaction_begin(s->timer_cmp); - ptimer_transaction_begin(s->timer_reload); oldcr = s->cr; s->cr = value & 0x03ffffff; if (s->cr & CR_SWR) { /* handle the reset */ imx_epit_reset(DEVICE(s)); - } else { + /* + * TODO: could we 'break' here? following operations appear + * to duplicate the work imx_epit_reset() already did. + */ + } + + ptimer_transaction_begin(s->timer_cmp); + ptimer_transaction_begin(s->timer_reload); + + if (!(s->cr & CR_SWR)) { imx_epit_set_freq(s); } diff --git a/hw/timer/lm32_timer.c b/hw/timer/lm32_timer.c index f703f407f50b60d826b8b89663aa0a6ffc5781ef..eeaf0ada5fa775f842d00c1f0418306953d7b529 100644 --- a/hw/timer/lm32_timer.c +++ b/hw/timer/lm32_timer.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,6 +31,7 @@ #include "hw/qdev-properties.h" #include "qemu/error-report.h" #include "qemu/module.h" +#include "qom/object.h" #define DEFAULT_FREQUENCY (50*1000000) @@ -55,7 +56,7 @@ enum { }; #define TYPE_LM32_TIMER "lm32-timer" -#define LM32_TIMER(obj) OBJECT_CHECK(LM32TimerState, (obj), TYPE_LM32_TIMER) +OBJECT_DECLARE_SIMPLE_TYPE(LM32TimerState, LM32_TIMER) struct LM32TimerState { SysBusDevice parent_obj; @@ -69,7 +70,6 @@ struct LM32TimerState { uint32_t regs[R_MAX]; }; -typedef struct LM32TimerState LM32TimerState; static void timer_update_irq(LM32TimerState *s) { diff --git a/hw/timer/meson.build b/hw/timer/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..be343f68fede35931e0a1ed9c82708de3de49b61 --- /dev/null +++ b/hw/timer/meson.build @@ -0,0 +1,38 @@ +softmmu_ss.add(when: 'CONFIG_A9_GTIMER', if_true: files('a9gtimer.c')) +softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_PIT', if_true: files('allwinner-a10-pit.c')) +softmmu_ss.add(when: 'CONFIG_ALTERA_TIMER', if_true: files('altera_timer.c')) +softmmu_ss.add(when: 'CONFIG_ARM_MPTIMER', if_true: files('arm_mptimer.c')) +softmmu_ss.add(when: 'CONFIG_ARM_TIMER', if_true: files('arm_timer.c')) +softmmu_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m_systick.c')) +softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_timer.c')) +softmmu_ss.add(when: 'CONFIG_CADENCE', if_true: files('cadence_ttc.c')) +softmmu_ss.add(when: 'CONFIG_CMSDK_APB_DUALTIMER', if_true: files('cmsdk-apb-dualtimer.c')) +softmmu_ss.add(when: 'CONFIG_CMSDK_APB_TIMER', if_true: files('cmsdk-apb-timer.c')) +softmmu_ss.add(when: 'CONFIG_RENESAS_TMR', if_true: files('renesas_tmr.c')) +softmmu_ss.add(when: 'CONFIG_RENESAS_CMT', if_true: files('renesas_cmt.c')) +softmmu_ss.add(when: 'CONFIG_DIGIC', if_true: files('digic-timer.c')) +softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_timer.c')) +softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_mct.c')) +softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_pwm.c')) +softmmu_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_gptimer.c')) +softmmu_ss.add(when: 'CONFIG_HPET', if_true: files('hpet.c')) +softmmu_ss.add(when: 'CONFIG_I8254', if_true: files('i8254_common.c', 'i8254.c')) +softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_epit.c')) +softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_gpt.c')) +softmmu_ss.add(when: 'CONFIG_LM32', if_true: files('lm32_timer.c')) +softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-sysctl.c')) +softmmu_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_gictimer.c')) +softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('mss-timer.c')) +softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_timer.c')) +softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_timer.c')) +softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_gptimer.c')) +softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_synctimer.c')) +softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_ost.c')) +softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_timer.c')) +softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_systmr.c')) +softmmu_ss.add(when: 'CONFIG_SH4', if_true: files('sh_timer.c')) +softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_timer.c')) +softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c')) +softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c')) + +specific_ss.add(when: 'CONFIG_AVR_TIMER16', if_true: files('avr_timer16.c')) diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c index 94389820b2e0787b99f9e91039a9db171fcd7551..9ecea63861cce35fa2e461504c070032b40c4010 100644 --- a/hw/timer/milkymist-sysctl.c +++ b/hw/timer/milkymist-sysctl.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -32,6 +32,7 @@ #include "hw/qdev-properties.h" #include "qemu/error-report.h" #include "qemu/module.h" +#include "qom/object.h" enum { CTRL_ENABLE = (1<<0), @@ -62,8 +63,7 @@ enum { }; #define TYPE_MILKYMIST_SYSCTL "milkymist-sysctl" -#define MILKYMIST_SYSCTL(obj) \ - OBJECT_CHECK(MilkymistSysctlState, (obj), TYPE_MILKYMIST_SYSCTL) +OBJECT_DECLARE_SIMPLE_TYPE(MilkymistSysctlState, MILKYMIST_SYSCTL) struct MilkymistSysctlState { SysBusDevice parent_obj; @@ -84,7 +84,6 @@ struct MilkymistSysctlState { qemu_irq timer0_irq; qemu_irq timer1_irq; }; -typedef struct MilkymistSysctlState MilkymistSysctlState; static void sysctl_icap_write(MilkymistSysctlState *s, uint32_t value) { diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c new file mode 100644 index 0000000000000000000000000000000000000000..d24445bd6e41e4589ef99da96ffc34146a5c0c52 --- /dev/null +++ b/hw/timer/npcm7xx_timer.c @@ -0,0 +1,717 @@ +/* + * Nuvoton NPCM7xx Timer Controller + * + * Copyright 2020 Google LLC + * + * 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. + */ + +#include "qemu/osdep.h" + +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/misc/npcm7xx_clk.h" +#include "hw/timer/npcm7xx_timer.h" +#include "migration/vmstate.h" +#include "qemu/bitops.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/timer.h" +#include "qemu/units.h" +#include "trace.h" + +/* 32-bit register indices. */ +enum NPCM7xxTimerRegisters { + NPCM7XX_TIMER_TCSR0, + NPCM7XX_TIMER_TCSR1, + NPCM7XX_TIMER_TICR0, + NPCM7XX_TIMER_TICR1, + NPCM7XX_TIMER_TDR0, + NPCM7XX_TIMER_TDR1, + NPCM7XX_TIMER_TISR, + NPCM7XX_TIMER_WTCR, + NPCM7XX_TIMER_TCSR2, + NPCM7XX_TIMER_TCSR3, + NPCM7XX_TIMER_TICR2, + NPCM7XX_TIMER_TICR3, + NPCM7XX_TIMER_TDR2, + NPCM7XX_TIMER_TDR3, + NPCM7XX_TIMER_TCSR4 = 0x0040 / sizeof(uint32_t), + NPCM7XX_TIMER_TICR4 = 0x0048 / sizeof(uint32_t), + NPCM7XX_TIMER_TDR4 = 0x0050 / sizeof(uint32_t), + NPCM7XX_TIMER_REGS_END, +}; + +/* Register field definitions. */ +#define NPCM7XX_TCSR_CEN BIT(30) +#define NPCM7XX_TCSR_IE BIT(29) +#define NPCM7XX_TCSR_PERIODIC BIT(27) +#define NPCM7XX_TCSR_CRST BIT(26) +#define NPCM7XX_TCSR_CACT BIT(25) +#define NPCM7XX_TCSR_RSVD 0x01ffff00 +#define NPCM7XX_TCSR_PRESCALE_START 0 +#define NPCM7XX_TCSR_PRESCALE_LEN 8 + +#define NPCM7XX_WTCR_WTCLK(rv) extract32(rv, 10, 2) +#define NPCM7XX_WTCR_FREEZE_EN BIT(9) +#define NPCM7XX_WTCR_WTE BIT(7) +#define NPCM7XX_WTCR_WTIE BIT(6) +#define NPCM7XX_WTCR_WTIS(rv) extract32(rv, 4, 2) +#define NPCM7XX_WTCR_WTIF BIT(3) +#define NPCM7XX_WTCR_WTRF BIT(2) +#define NPCM7XX_WTCR_WTRE BIT(1) +#define NPCM7XX_WTCR_WTR BIT(0) + +/* + * The number of clock cycles between interrupt and reset in watchdog, used + * by the software to handle the interrupt before system is reset. + */ +#define NPCM7XX_WATCHDOG_INTERRUPT_TO_RESET_CYCLES 1024 + +/* Start or resume the timer. */ +static void npcm7xx_timer_start(NPCM7xxBaseTimer *t) +{ + int64_t now; + + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + t->expires_ns = now + t->remaining_ns; + timer_mod(&t->qtimer, t->expires_ns); +} + +/* Stop counting. Record the time remaining so we can continue later. */ +static void npcm7xx_timer_pause(NPCM7xxBaseTimer *t) +{ + int64_t now; + + timer_del(&t->qtimer); + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + t->remaining_ns = t->expires_ns - now; +} + +/* Delete the timer and reset it to default state. */ +static void npcm7xx_timer_clear(NPCM7xxBaseTimer *t) +{ + timer_del(&t->qtimer); + t->expires_ns = 0; + t->remaining_ns = 0; +} + +/* + * Returns the index of timer in the tc->timer array. This can be used to + * locate the registers that belong to this timer. + */ +static int npcm7xx_timer_index(NPCM7xxTimerCtrlState *tc, NPCM7xxTimer *timer) +{ + int index = timer - tc->timer; + + g_assert(index >= 0 && index < NPCM7XX_TIMERS_PER_CTRL); + + return index; +} + +/* Return the value by which to divide the reference clock rate. */ +static uint32_t npcm7xx_tcsr_prescaler(uint32_t tcsr) +{ + return extract32(tcsr, NPCM7XX_TCSR_PRESCALE_START, + NPCM7XX_TCSR_PRESCALE_LEN) + 1; +} + +/* Convert a timer cycle count to a time interval in nanoseconds. */ +static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count) +{ + int64_t ns = count; + + ns *= NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ; + ns *= npcm7xx_tcsr_prescaler(t->tcsr); + + return ns; +} + +/* Convert a time interval in nanoseconds to a timer cycle count. */ +static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns) +{ + int64_t count; + + count = ns / (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ); + count /= npcm7xx_tcsr_prescaler(t->tcsr); + + return count; +} + +static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t) +{ + switch (NPCM7XX_WTCR_WTCLK(t->wtcr)) { + case 0: + return 1; + case 1: + return 256; + case 2: + return 2048; + case 3: + return 65536; + default: + g_assert_not_reached(); + } +} + +static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t, + int64_t cycles) +{ + uint32_t prescaler = npcm7xx_watchdog_timer_prescaler(t); + int64_t ns = (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ) * cycles; + + /* + * The reset function always clears the current timer. The caller of the + * this needs to decide whether to start the watchdog timer based on + * specific flag in WTCR. + */ + npcm7xx_timer_clear(&t->base_timer); + + ns *= prescaler; + t->base_timer.remaining_ns = ns; +} + +static void npcm7xx_watchdog_timer_reset(NPCM7xxWatchdogTimer *t) +{ + int64_t cycles = 1; + uint32_t s = NPCM7XX_WTCR_WTIS(t->wtcr); + + g_assert(s <= 3); + + cycles <<= NPCM7XX_WATCHDOG_BASETIME_SHIFT; + cycles <<= 2 * s; + + npcm7xx_watchdog_timer_reset_cycles(t, cycles); +} + +/* + * Raise the interrupt line if there's a pending interrupt and interrupts are + * enabled for this timer. If not, lower it. + */ +static void npcm7xx_timer_check_interrupt(NPCM7xxTimer *t) +{ + NPCM7xxTimerCtrlState *tc = t->ctrl; + int index = npcm7xx_timer_index(tc, t); + bool pending = (t->tcsr & NPCM7XX_TCSR_IE) && (tc->tisr & BIT(index)); + + qemu_set_irq(t->irq, pending); + trace_npcm7xx_timer_irq(DEVICE(tc)->canonical_path, index, pending); +} + +/* + * Called when the counter reaches zero. Sets the interrupt flag, and either + * restarts or disables the timer. + */ +static void npcm7xx_timer_reached_zero(NPCM7xxTimer *t) +{ + NPCM7xxTimerCtrlState *tc = t->ctrl; + int index = npcm7xx_timer_index(tc, t); + + tc->tisr |= BIT(index); + + if (t->tcsr & NPCM7XX_TCSR_PERIODIC) { + t->base_timer.remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr); + if (t->tcsr & NPCM7XX_TCSR_CEN) { + npcm7xx_timer_start(&t->base_timer); + } + } else { + t->tcsr &= ~(NPCM7XX_TCSR_CEN | NPCM7XX_TCSR_CACT); + } + + npcm7xx_timer_check_interrupt(t); +} + + +/* + * Restart the timer from its initial value. If the timer was enabled and stays + * enabled, adjust the QEMU timer according to the new count. If the timer is + * transitioning from disabled to enabled, the caller is expected to start the + * timer later. + */ +static void npcm7xx_timer_restart(NPCM7xxTimer *t, uint32_t old_tcsr) +{ + t->base_timer.remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr); + + if (old_tcsr & t->tcsr & NPCM7XX_TCSR_CEN) { + npcm7xx_timer_start(&t->base_timer); + } +} + +/* Register read and write handlers */ + +static uint32_t npcm7xx_timer_read_tdr(NPCM7xxTimer *t) +{ + if (t->tcsr & NPCM7XX_TCSR_CEN) { + int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + + return npcm7xx_timer_ns_to_count(t, t->base_timer.expires_ns - now); + } + + return npcm7xx_timer_ns_to_count(t, t->base_timer.remaining_ns); +} + +static void npcm7xx_timer_write_tcsr(NPCM7xxTimer *t, uint32_t new_tcsr) +{ + uint32_t old_tcsr = t->tcsr; + uint32_t tdr; + + if (new_tcsr & NPCM7XX_TCSR_RSVD) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: reserved bits in 0x%08x ignored\n", + __func__, new_tcsr); + new_tcsr &= ~NPCM7XX_TCSR_RSVD; + } + if (new_tcsr & NPCM7XX_TCSR_CACT) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: read-only bits in 0x%08x ignored\n", + __func__, new_tcsr); + new_tcsr &= ~NPCM7XX_TCSR_CACT; + } + if ((new_tcsr & NPCM7XX_TCSR_CRST) && (new_tcsr & NPCM7XX_TCSR_CEN)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: both CRST and CEN set; ignoring CEN.\n", + __func__); + new_tcsr &= ~NPCM7XX_TCSR_CEN; + } + + /* Calculate the value of TDR before potentially changing the prescaler. */ + tdr = npcm7xx_timer_read_tdr(t); + + t->tcsr = (t->tcsr & NPCM7XX_TCSR_CACT) | new_tcsr; + + if (npcm7xx_tcsr_prescaler(old_tcsr) != npcm7xx_tcsr_prescaler(new_tcsr)) { + /* Recalculate time remaining based on the current TDR value. */ + t->base_timer.remaining_ns = npcm7xx_timer_count_to_ns(t, tdr); + if (old_tcsr & t->tcsr & NPCM7XX_TCSR_CEN) { + npcm7xx_timer_start(&t->base_timer); + } + } + + if ((old_tcsr ^ new_tcsr) & NPCM7XX_TCSR_IE) { + npcm7xx_timer_check_interrupt(t); + } + if (new_tcsr & NPCM7XX_TCSR_CRST) { + npcm7xx_timer_restart(t, old_tcsr); + t->tcsr &= ~NPCM7XX_TCSR_CRST; + } + if ((old_tcsr ^ new_tcsr) & NPCM7XX_TCSR_CEN) { + if (new_tcsr & NPCM7XX_TCSR_CEN) { + t->tcsr |= NPCM7XX_TCSR_CACT; + npcm7xx_timer_start(&t->base_timer); + } else { + t->tcsr &= ~NPCM7XX_TCSR_CACT; + npcm7xx_timer_pause(&t->base_timer); + if (t->base_timer.remaining_ns <= 0) { + npcm7xx_timer_reached_zero(t); + } + } + } +} + +static void npcm7xx_timer_write_ticr(NPCM7xxTimer *t, uint32_t new_ticr) +{ + t->ticr = new_ticr; + + npcm7xx_timer_restart(t, t->tcsr); +} + +static void npcm7xx_timer_write_tisr(NPCM7xxTimerCtrlState *s, uint32_t value) +{ + int i; + + s->tisr &= ~value; + for (i = 0; i < ARRAY_SIZE(s->timer); i++) { + if (value & (1U << i)) { + npcm7xx_timer_check_interrupt(&s->timer[i]); + } + + } +} + +static void npcm7xx_timer_write_wtcr(NPCM7xxWatchdogTimer *t, uint32_t new_wtcr) +{ + uint32_t old_wtcr = t->wtcr; + + /* + * WTIF and WTRF are cleared by writing 1. Writing 0 makes these bits + * unchanged. + */ + if (new_wtcr & NPCM7XX_WTCR_WTIF) { + new_wtcr &= ~NPCM7XX_WTCR_WTIF; + } else if (old_wtcr & NPCM7XX_WTCR_WTIF) { + new_wtcr |= NPCM7XX_WTCR_WTIF; + } + if (new_wtcr & NPCM7XX_WTCR_WTRF) { + new_wtcr &= ~NPCM7XX_WTCR_WTRF; + } else if (old_wtcr & NPCM7XX_WTCR_WTRF) { + new_wtcr |= NPCM7XX_WTCR_WTRF; + } + + t->wtcr = new_wtcr; + + if (new_wtcr & NPCM7XX_WTCR_WTR) { + t->wtcr &= ~NPCM7XX_WTCR_WTR; + npcm7xx_watchdog_timer_reset(t); + if (new_wtcr & NPCM7XX_WTCR_WTE) { + npcm7xx_timer_start(&t->base_timer); + } + } else if ((old_wtcr ^ new_wtcr) & NPCM7XX_WTCR_WTE) { + if (new_wtcr & NPCM7XX_WTCR_WTE) { + npcm7xx_timer_start(&t->base_timer); + } else { + npcm7xx_timer_pause(&t->base_timer); + } + } + +} + +static hwaddr npcm7xx_tcsr_index(hwaddr reg) +{ + switch (reg) { + case NPCM7XX_TIMER_TCSR0: + return 0; + case NPCM7XX_TIMER_TCSR1: + return 1; + case NPCM7XX_TIMER_TCSR2: + return 2; + case NPCM7XX_TIMER_TCSR3: + return 3; + case NPCM7XX_TIMER_TCSR4: + return 4; + default: + g_assert_not_reached(); + } +} + +static hwaddr npcm7xx_ticr_index(hwaddr reg) +{ + switch (reg) { + case NPCM7XX_TIMER_TICR0: + return 0; + case NPCM7XX_TIMER_TICR1: + return 1; + case NPCM7XX_TIMER_TICR2: + return 2; + case NPCM7XX_TIMER_TICR3: + return 3; + case NPCM7XX_TIMER_TICR4: + return 4; + default: + g_assert_not_reached(); + } +} + +static hwaddr npcm7xx_tdr_index(hwaddr reg) +{ + switch (reg) { + case NPCM7XX_TIMER_TDR0: + return 0; + case NPCM7XX_TIMER_TDR1: + return 1; + case NPCM7XX_TIMER_TDR2: + return 2; + case NPCM7XX_TIMER_TDR3: + return 3; + case NPCM7XX_TIMER_TDR4: + return 4; + default: + g_assert_not_reached(); + } +} + +static uint64_t npcm7xx_timer_read(void *opaque, hwaddr offset, unsigned size) +{ + NPCM7xxTimerCtrlState *s = opaque; + uint64_t value = 0; + hwaddr reg; + + reg = offset / sizeof(uint32_t); + switch (reg) { + case NPCM7XX_TIMER_TCSR0: + case NPCM7XX_TIMER_TCSR1: + case NPCM7XX_TIMER_TCSR2: + case NPCM7XX_TIMER_TCSR3: + case NPCM7XX_TIMER_TCSR4: + value = s->timer[npcm7xx_tcsr_index(reg)].tcsr; + break; + + case NPCM7XX_TIMER_TICR0: + case NPCM7XX_TIMER_TICR1: + case NPCM7XX_TIMER_TICR2: + case NPCM7XX_TIMER_TICR3: + case NPCM7XX_TIMER_TICR4: + value = s->timer[npcm7xx_ticr_index(reg)].ticr; + break; + + case NPCM7XX_TIMER_TDR0: + case NPCM7XX_TIMER_TDR1: + case NPCM7XX_TIMER_TDR2: + case NPCM7XX_TIMER_TDR3: + case NPCM7XX_TIMER_TDR4: + value = npcm7xx_timer_read_tdr(&s->timer[npcm7xx_tdr_index(reg)]); + break; + + case NPCM7XX_TIMER_TISR: + value = s->tisr; + break; + + case NPCM7XX_TIMER_WTCR: + value = s->watchdog_timer.wtcr; + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid offset 0x%04" HWADDR_PRIx "\n", + __func__, offset); + break; + } + + trace_npcm7xx_timer_read(DEVICE(s)->canonical_path, offset, value); + + return value; +} + +static void npcm7xx_timer_write(void *opaque, hwaddr offset, + uint64_t v, unsigned size) +{ + uint32_t reg = offset / sizeof(uint32_t); + NPCM7xxTimerCtrlState *s = opaque; + uint32_t value = v; + + trace_npcm7xx_timer_write(DEVICE(s)->canonical_path, offset, value); + + switch (reg) { + case NPCM7XX_TIMER_TCSR0: + case NPCM7XX_TIMER_TCSR1: + case NPCM7XX_TIMER_TCSR2: + case NPCM7XX_TIMER_TCSR3: + case NPCM7XX_TIMER_TCSR4: + npcm7xx_timer_write_tcsr(&s->timer[npcm7xx_tcsr_index(reg)], value); + return; + + case NPCM7XX_TIMER_TICR0: + case NPCM7XX_TIMER_TICR1: + case NPCM7XX_TIMER_TICR2: + case NPCM7XX_TIMER_TICR3: + case NPCM7XX_TIMER_TICR4: + npcm7xx_timer_write_ticr(&s->timer[npcm7xx_ticr_index(reg)], value); + return; + + case NPCM7XX_TIMER_TDR0: + case NPCM7XX_TIMER_TDR1: + case NPCM7XX_TIMER_TDR2: + case NPCM7XX_TIMER_TDR3: + case NPCM7XX_TIMER_TDR4: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n", + __func__, offset); + return; + + case NPCM7XX_TIMER_TISR: + npcm7xx_timer_write_tisr(s, value); + return; + + case NPCM7XX_TIMER_WTCR: + npcm7xx_timer_write_wtcr(&s->watchdog_timer, value); + return; + } + + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid offset 0x%04" HWADDR_PRIx "\n", + __func__, offset); +} + +static const struct MemoryRegionOps npcm7xx_timer_ops = { + .read = npcm7xx_timer_read, + .write = npcm7xx_timer_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + .unaligned = false, + }, +}; + +/* Called when the QEMU timer expires. */ +static void npcm7xx_timer_expired(void *opaque) +{ + NPCM7xxTimer *t = opaque; + + if (t->tcsr & NPCM7XX_TCSR_CEN) { + npcm7xx_timer_reached_zero(t); + } +} + +static void npcm7xx_timer_enter_reset(Object *obj, ResetType type) +{ + NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj); + int i; + + for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) { + NPCM7xxTimer *t = &s->timer[i]; + + npcm7xx_timer_clear(&t->base_timer); + t->tcsr = 0x00000005; + t->ticr = 0x00000000; + } + + s->tisr = 0x00000000; + /* + * Set WTCLK to 1(default) and reset all flags except WTRF. + * WTRF is not reset during a core domain reset. + */ + s->watchdog_timer.wtcr = 0x00000400 | (s->watchdog_timer.wtcr & + NPCM7XX_WTCR_WTRF); +} + +static void npcm7xx_watchdog_timer_expired(void *opaque) +{ + NPCM7xxWatchdogTimer *t = opaque; + + if (t->wtcr & NPCM7XX_WTCR_WTE) { + if (t->wtcr & NPCM7XX_WTCR_WTIF) { + if (t->wtcr & NPCM7XX_WTCR_WTRE) { + t->wtcr |= NPCM7XX_WTCR_WTRF; + /* send reset signal to CLK module*/ + qemu_irq_raise(t->reset_signal); + } + } else { + t->wtcr |= NPCM7XX_WTCR_WTIF; + if (t->wtcr & NPCM7XX_WTCR_WTIE) { + /* send interrupt */ + qemu_irq_raise(t->irq); + } + npcm7xx_watchdog_timer_reset_cycles(t, + NPCM7XX_WATCHDOG_INTERRUPT_TO_RESET_CYCLES); + npcm7xx_timer_start(&t->base_timer); + } + } +} + +static void npcm7xx_timer_hold_reset(Object *obj) +{ + NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj); + int i; + + for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) { + qemu_irq_lower(s->timer[i].irq); + } + qemu_irq_lower(s->watchdog_timer.irq); +} + +static void npcm7xx_timer_realize(DeviceState *dev, Error **errp) +{ + NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(dev); + SysBusDevice *sbd = &s->parent; + int i; + NPCM7xxWatchdogTimer *w; + + for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) { + NPCM7xxTimer *t = &s->timer[i]; + t->ctrl = s; + timer_init_ns(&t->base_timer.qtimer, QEMU_CLOCK_VIRTUAL, + npcm7xx_timer_expired, t); + sysbus_init_irq(sbd, &t->irq); + } + + w = &s->watchdog_timer; + w->ctrl = s; + timer_init_ns(&w->base_timer.qtimer, QEMU_CLOCK_VIRTUAL, + npcm7xx_watchdog_timer_expired, w); + sysbus_init_irq(sbd, &w->irq); + + memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_timer_ops, s, + TYPE_NPCM7XX_TIMER, 4 * KiB); + sysbus_init_mmio(sbd, &s->iomem); + qdev_init_gpio_out_named(dev, &w->reset_signal, + NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 1); +} + +static const VMStateDescription vmstate_npcm7xx_base_timer = { + .name = "npcm7xx-base-timer", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_TIMER(qtimer, NPCM7xxBaseTimer), + VMSTATE_INT64(expires_ns, NPCM7xxBaseTimer), + VMSTATE_INT64(remaining_ns, NPCM7xxBaseTimer), + VMSTATE_END_OF_LIST(), + }, +}; + +static const VMStateDescription vmstate_npcm7xx_timer = { + .name = "npcm7xx-timer", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_STRUCT(base_timer, NPCM7xxTimer, + 0, vmstate_npcm7xx_base_timer, + NPCM7xxBaseTimer), + VMSTATE_UINT32(tcsr, NPCM7xxTimer), + VMSTATE_UINT32(ticr, NPCM7xxTimer), + VMSTATE_END_OF_LIST(), + }, +}; + +static const VMStateDescription vmstate_npcm7xx_watchdog_timer = { + .name = "npcm7xx-watchdog-timer", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_STRUCT(base_timer, NPCM7xxWatchdogTimer, + 0, vmstate_npcm7xx_base_timer, + NPCM7xxBaseTimer), + VMSTATE_UINT32(wtcr, NPCM7xxWatchdogTimer), + VMSTATE_END_OF_LIST(), + }, +}; + +static const VMStateDescription vmstate_npcm7xx_timer_ctrl = { + .name = "npcm7xx-timer-ctrl", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(tisr, NPCM7xxTimerCtrlState), + VMSTATE_STRUCT_ARRAY(timer, NPCM7xxTimerCtrlState, + NPCM7XX_TIMERS_PER_CTRL, 0, vmstate_npcm7xx_timer, + NPCM7xxTimer), + VMSTATE_STRUCT(watchdog_timer, NPCM7xxTimerCtrlState, + 0, vmstate_npcm7xx_watchdog_timer, + NPCM7xxWatchdogTimer), + VMSTATE_END_OF_LIST(), + }, +}; + +static void npcm7xx_timer_class_init(ObjectClass *klass, void *data) +{ + ResettableClass *rc = RESETTABLE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + QEMU_BUILD_BUG_ON(NPCM7XX_TIMER_REGS_END > NPCM7XX_TIMER_NR_REGS); + + dc->desc = "NPCM7xx Timer Controller"; + dc->realize = npcm7xx_timer_realize; + dc->vmsd = &vmstate_npcm7xx_timer_ctrl; + rc->phases.enter = npcm7xx_timer_enter_reset; + rc->phases.hold = npcm7xx_timer_hold_reset; +} + +static const TypeInfo npcm7xx_timer_info = { + .name = TYPE_NPCM7XX_TIMER, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(NPCM7xxTimerCtrlState), + .class_init = npcm7xx_timer_class_init, +}; + +static void npcm7xx_timer_register_type(void) +{ + type_register_static(&npcm7xx_timer_info); +} +type_init(npcm7xx_timer_register_type); diff --git a/hw/timer/puv3_ost.c b/hw/timer/puv3_ost.c index 697519593bb5a8aa56d74fc0364416e6025e9314..d5bf26b56bcbf4c611166ee31a9f91fe7ee99f38 100644 --- a/hw/timer/puv3_ost.c +++ b/hw/timer/puv3_ost.c @@ -14,15 +14,17 @@ #include "hw/irq.h" #include "hw/ptimer.h" #include "qemu/module.h" +#include "qemu/log.h" +#include "qom/object.h" #undef DEBUG_PUV3 #include "hw/unicore32/puv3.h" #define TYPE_PUV3_OST "puv3_ost" -#define PUV3_OST(obj) OBJECT_CHECK(PUV3OSTState, (obj), TYPE_PUV3_OST) +OBJECT_DECLARE_SIMPLE_TYPE(PUV3OSTState, PUV3_OST) /* puv3 ostimer implementation. */ -typedef struct PUV3OSTState { +struct PUV3OSTState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -33,7 +35,7 @@ typedef struct PUV3OSTState { uint32_t reg_OSCR; uint32_t reg_OSSR; uint32_t reg_OIER; -} PUV3OSTState; +}; static uint64_t puv3_ost_read(void *opaque, hwaddr offset, unsigned size) @@ -52,7 +54,9 @@ static uint64_t puv3_ost_read(void *opaque, hwaddr offset, ret = s->reg_OIER; break; default: - DPRINTF("Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad read offset 0x%"HWADDR_PRIx"\n", + __func__, offset); } DPRINTF("offset 0x%x, value 0x%x\n", offset, ret); return ret; @@ -88,7 +92,9 @@ static void puv3_ost_write(void *opaque, hwaddr offset, s->reg_OIER = value; break; default: - DPRINTF("Bad offset %x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad write offset 0x%"HWADDR_PRIx"\n", + __func__, offset); } } diff --git a/hw/timer/pxa2xx_timer.c b/hw/timer/pxa2xx_timer.c index 944c165889269bc72c9eb10d416d5d4bdb9cf15c..2ae5ae3212311eeaf18e56a7b583fb7c8c3477c9 100644 --- a/hw/timer/pxa2xx_timer.c +++ b/hw/timer/pxa2xx_timer.c @@ -17,6 +17,7 @@ #include "migration/vmstate.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" #define OSMR0 0x00 #define OSMR1 0x04 @@ -66,10 +67,8 @@ static int pxa2xx_timer4_freq[8] = { }; #define TYPE_PXA2XX_TIMER "pxa2xx-timer" -#define PXA2XX_TIMER(obj) \ - OBJECT_CHECK(PXA2xxTimerInfo, (obj), TYPE_PXA2XX_TIMER) +OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxTimerInfo, PXA2XX_TIMER) -typedef struct PXA2xxTimerInfo PXA2xxTimerInfo; typedef struct { uint32_t value; diff --git a/hw/timer/renesas_cmt.c b/hw/timer/renesas_cmt.c new file mode 100644 index 0000000000000000000000000000000000000000..2e0fd21a36c3eb2438a0e09bd4ebfd93d2b20b71 --- /dev/null +++ b/hw/timer/renesas_cmt.c @@ -0,0 +1,283 @@ +/* + * Renesas 16bit Compare-match timer + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * + * Copyright (c) 2019 Yoshinori Sato + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "hw/irq.h" +#include "hw/registerfields.h" +#include "hw/qdev-properties.h" +#include "hw/timer/renesas_cmt.h" +#include "migration/vmstate.h" + +/* + * +0 CMSTR - common control + * +2 CMCR - ch0 + * +4 CMCNT - ch0 + * +6 CMCOR - ch0 + * +8 CMCR - ch1 + * +10 CMCNT - ch1 + * +12 CMCOR - ch1 + * If we think that the address of CH 0 has an offset of +2, + * we can treat it with the same address as CH 1, so define it like that. + */ +REG16(CMSTR, 0) + FIELD(CMSTR, STR0, 0, 1) + FIELD(CMSTR, STR1, 1, 1) + FIELD(CMSTR, STR, 0, 2) +/* This addeess is channel offset */ +REG16(CMCR, 0) + FIELD(CMCR, CKS, 0, 2) + FIELD(CMCR, CMIE, 6, 1) +REG16(CMCNT, 2) +REG16(CMCOR, 4) + +static void update_events(RCMTState *cmt, int ch) +{ + int64_t next_time; + + if ((cmt->cmstr & (1 << ch)) == 0) { + /* count disable, so not happened next event. */ + return ; + } + next_time = cmt->cmcor[ch] - cmt->cmcnt[ch]; + next_time *= NANOSECONDS_PER_SECOND; + next_time /= cmt->input_freq; + /* + * CKS -> div rate + * 0 -> 8 (1 << 3) + * 1 -> 32 (1 << 5) + * 2 -> 128 (1 << 7) + * 3 -> 512 (1 << 9) + */ + next_time *= 1 << (3 + FIELD_EX16(cmt->cmcr[ch], CMCR, CKS) * 2); + next_time += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + timer_mod(&cmt->timer[ch], next_time); +} + +static int64_t read_cmcnt(RCMTState *cmt, int ch) +{ + int64_t delta, now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + + if (cmt->cmstr & (1 << ch)) { + delta = (now - cmt->tick[ch]); + delta /= NANOSECONDS_PER_SECOND; + delta /= cmt->input_freq; + delta /= 1 << (3 + FIELD_EX16(cmt->cmcr[ch], CMCR, CKS) * 2); + cmt->tick[ch] = now; + return cmt->cmcnt[ch] + delta; + } else { + return cmt->cmcnt[ch]; + } +} + +static uint64_t cmt_read(void *opaque, hwaddr offset, unsigned size) +{ + RCMTState *cmt = opaque; + int ch = offset / 0x08; + uint64_t ret; + + if (offset == A_CMSTR) { + ret = 0; + ret = FIELD_DP16(ret, CMSTR, STR, + FIELD_EX16(cmt->cmstr, CMSTR, STR)); + return ret; + } else { + offset &= 0x07; + if (ch == 0) { + offset -= 0x02; + } + switch (offset) { + case A_CMCR: + ret = 0; + ret = FIELD_DP16(ret, CMCR, CKS, + FIELD_EX16(cmt->cmstr, CMCR, CKS)); + ret = FIELD_DP16(ret, CMCR, CMIE, + FIELD_EX16(cmt->cmstr, CMCR, CMIE)); + return ret; + case A_CMCNT: + return read_cmcnt(cmt, ch); + case A_CMCOR: + return cmt->cmcor[ch]; + } + } + qemu_log_mask(LOG_UNIMP, "renesas_cmt: Register 0x%" HWADDR_PRIX " " + "not implemented\n", + offset); + return UINT64_MAX; +} + +static void start_stop(RCMTState *cmt, int ch, int st) +{ + if (st) { + update_events(cmt, ch); + } else { + timer_del(&cmt->timer[ch]); + } +} + +static void cmt_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) +{ + RCMTState *cmt = opaque; + int ch = offset / 0x08; + + if (offset == A_CMSTR) { + cmt->cmstr = FIELD_EX16(val, CMSTR, STR); + start_stop(cmt, 0, FIELD_EX16(cmt->cmstr, CMSTR, STR0)); + start_stop(cmt, 1, FIELD_EX16(cmt->cmstr, CMSTR, STR1)); + } else { + offset &= 0x07; + if (ch == 0) { + offset -= 0x02; + } + switch (offset) { + case A_CMCR: + cmt->cmcr[ch] = FIELD_DP16(cmt->cmcr[ch], CMCR, CKS, + FIELD_EX16(val, CMCR, CKS)); + cmt->cmcr[ch] = FIELD_DP16(cmt->cmcr[ch], CMCR, CMIE, + FIELD_EX16(val, CMCR, CMIE)); + break; + case 2: + cmt->cmcnt[ch] = val; + break; + case 4: + cmt->cmcor[ch] = val; + break; + default: + qemu_log_mask(LOG_UNIMP, "renesas_cmt: Register 0x%" HWADDR_PRIX " " + "not implemented\n", + offset); + return; + } + if (FIELD_EX16(cmt->cmstr, CMSTR, STR) & (1 << ch)) { + update_events(cmt, ch); + } + } +} + +static const MemoryRegionOps cmt_ops = { + .write = cmt_write, + .read = cmt_read, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .min_access_size = 2, + .max_access_size = 2, + }, + .valid = { + .min_access_size = 2, + .max_access_size = 2, + }, +}; + +static void timer_events(RCMTState *cmt, int ch) +{ + cmt->cmcnt[ch] = 0; + cmt->tick[ch] = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + update_events(cmt, ch); + if (FIELD_EX16(cmt->cmcr[ch], CMCR, CMIE)) { + qemu_irq_pulse(cmt->cmi[ch]); + } +} + +static void timer_event0(void *opaque) +{ + RCMTState *cmt = opaque; + + timer_events(cmt, 0); +} + +static void timer_event1(void *opaque) +{ + RCMTState *cmt = opaque; + + timer_events(cmt, 1); +} + +static void rcmt_reset(DeviceState *dev) +{ + RCMTState *cmt = RCMT(dev); + cmt->cmstr = 0; + cmt->cmcr[0] = cmt->cmcr[1] = 0; + cmt->cmcnt[0] = cmt->cmcnt[1] = 0; + cmt->cmcor[0] = cmt->cmcor[1] = 0xffff; +} + +static void rcmt_init(Object *obj) +{ + SysBusDevice *d = SYS_BUS_DEVICE(obj); + RCMTState *cmt = RCMT(obj); + int i; + + memory_region_init_io(&cmt->memory, OBJECT(cmt), &cmt_ops, + cmt, "renesas-cmt", 0x10); + sysbus_init_mmio(d, &cmt->memory); + + for (i = 0; i < ARRAY_SIZE(cmt->cmi); i++) { + sysbus_init_irq(d, &cmt->cmi[i]); + } + timer_init_ns(&cmt->timer[0], QEMU_CLOCK_VIRTUAL, timer_event0, cmt); + timer_init_ns(&cmt->timer[1], QEMU_CLOCK_VIRTUAL, timer_event1, cmt); +} + +static const VMStateDescription vmstate_rcmt = { + .name = "rx-cmt", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT16(cmstr, RCMTState), + VMSTATE_UINT16_ARRAY(cmcr, RCMTState, CMT_CH), + VMSTATE_UINT16_ARRAY(cmcnt, RCMTState, CMT_CH), + VMSTATE_UINT16_ARRAY(cmcor, RCMTState, CMT_CH), + VMSTATE_INT64_ARRAY(tick, RCMTState, CMT_CH), + VMSTATE_TIMER_ARRAY(timer, RCMTState, CMT_CH), + VMSTATE_END_OF_LIST() + } +}; + +static Property rcmt_properties[] = { + DEFINE_PROP_UINT64("input-freq", RCMTState, input_freq, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void rcmt_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->vmsd = &vmstate_rcmt; + dc->reset = rcmt_reset; + device_class_set_props(dc, rcmt_properties); +} + +static const TypeInfo rcmt_info = { + .name = TYPE_RENESAS_CMT, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(RCMTState), + .instance_init = rcmt_init, + .class_init = rcmt_class_init, +}; + +static void rcmt_register_types(void) +{ + type_register_static(&rcmt_info); +} + +type_init(rcmt_register_types) diff --git a/hw/timer/renesas_tmr.c b/hw/timer/renesas_tmr.c new file mode 100644 index 0000000000000000000000000000000000000000..446f2eacdd76d7bbc1bac0b41295da06eed08f64 --- /dev/null +++ b/hw/timer/renesas_tmr.c @@ -0,0 +1,477 @@ +/* + * Renesas 8bit timer + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * + * Copyright (c) 2019 Yoshinori Sato + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "hw/irq.h" +#include "hw/registerfields.h" +#include "hw/qdev-properties.h" +#include "hw/timer/renesas_tmr.h" +#include "migration/vmstate.h" + +REG8(TCR, 0) + FIELD(TCR, CCLR, 3, 2) + FIELD(TCR, OVIE, 5, 1) + FIELD(TCR, CMIEA, 6, 1) + FIELD(TCR, CMIEB, 7, 1) +REG8(TCSR, 2) + FIELD(TCSR, OSA, 0, 2) + FIELD(TCSR, OSB, 2, 2) + FIELD(TCSR, ADTE, 4, 2) +REG8(TCORA, 4) +REG8(TCORB, 6) +REG8(TCNT, 8) +REG8(TCCR, 10) + FIELD(TCCR, CKS, 0, 3) + FIELD(TCCR, CSS, 3, 2) + FIELD(TCCR, TMRIS, 7, 1) + +#define INTERNAL 0x01 +#define CASCADING 0x03 +#define CCLR_A 0x01 +#define CCLR_B 0x02 + +static const int clkdiv[] = {0, 1, 2, 8, 32, 64, 1024, 8192}; + +static uint8_t concat_reg(uint8_t *reg) +{ + return (reg[0] << 8) | reg[1]; +} + +static void update_events(RTMRState *tmr, int ch) +{ + uint16_t diff[TMR_NR_EVENTS], min; + int64_t next_time; + int i, event; + + if (tmr->tccr[ch] == 0) { + return ; + } + if (FIELD_EX8(tmr->tccr[ch], TCCR, CSS) == 0) { + /* external clock mode */ + /* event not happened */ + return ; + } + if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) == CASCADING) { + /* cascading mode */ + if (ch == 1) { + tmr->next[ch] = none; + return ; + } + diff[cmia] = concat_reg(tmr->tcora) - concat_reg(tmr->tcnt); + diff[cmib] = concat_reg(tmr->tcorb) - concat_reg(tmr->tcnt); + diff[ovi] = 0x10000 - concat_reg(tmr->tcnt); + } else { + /* separate mode */ + diff[cmia] = tmr->tcora[ch] - tmr->tcnt[ch]; + diff[cmib] = tmr->tcorb[ch] - tmr->tcnt[ch]; + diff[ovi] = 0x100 - tmr->tcnt[ch]; + } + /* Search for the most recently occurring event. */ + for (event = 0, min = diff[0], i = 1; i < none; i++) { + if (min > diff[i]) { + event = i; + min = diff[i]; + } + } + tmr->next[ch] = event; + next_time = diff[event]; + next_time *= clkdiv[FIELD_EX8(tmr->tccr[ch], TCCR, CKS)]; + next_time *= NANOSECONDS_PER_SECOND; + next_time /= tmr->input_freq; + next_time += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + timer_mod(&tmr->timer[ch], next_time); +} + +static int elapsed_time(RTMRState *tmr, int ch, int64_t delta) +{ + int divrate = clkdiv[FIELD_EX8(tmr->tccr[ch], TCCR, CKS)]; + int et; + + tmr->div_round[ch] += delta; + if (divrate > 0) { + et = tmr->div_round[ch] / divrate; + tmr->div_round[ch] %= divrate; + } else { + /* disble clock. so no update */ + et = 0; + } + return et; +} + +static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch) +{ + int64_t delta, now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + int elapsed, ovf = 0; + uint16_t tcnt[2]; + uint32_t ret; + + delta = (now - tmr->tick) * NANOSECONDS_PER_SECOND / tmr->input_freq; + if (delta > 0) { + tmr->tick = now; + + if (FIELD_EX8(tmr->tccr[1], TCCR, CSS) == INTERNAL) { + /* timer1 count update */ + elapsed = elapsed_time(tmr, 1, delta); + if (elapsed >= 0x100) { + ovf = elapsed >> 8; + } + tcnt[1] = tmr->tcnt[1] + (elapsed & 0xff); + } + switch (FIELD_EX8(tmr->tccr[0], TCCR, CSS)) { + case INTERNAL: + elapsed = elapsed_time(tmr, 0, delta); + tcnt[0] = tmr->tcnt[0] + elapsed; + break; + case CASCADING: + if (ovf > 0) { + tcnt[0] = tmr->tcnt[0] + ovf; + } + break; + } + } else { + tcnt[0] = tmr->tcnt[0]; + tcnt[1] = tmr->tcnt[1]; + } + if (size == 1) { + return tcnt[ch]; + } else { + ret = 0; + ret = deposit32(ret, 0, 8, tcnt[1]); + ret = deposit32(ret, 8, 8, tcnt[0]); + return ret; + } +} + +static uint8_t read_tccr(uint8_t r) +{ + uint8_t tccr = 0; + tccr = FIELD_DP8(tccr, TCCR, TMRIS, + FIELD_EX8(r, TCCR, TMRIS)); + tccr = FIELD_DP8(tccr, TCCR, CSS, + FIELD_EX8(r, TCCR, CSS)); + tccr = FIELD_DP8(tccr, TCCR, CKS, + FIELD_EX8(r, TCCR, CKS)); + return tccr; +} + +static uint64_t tmr_read(void *opaque, hwaddr addr, unsigned size) +{ + RTMRState *tmr = opaque; + int ch = addr & 1; + uint64_t ret; + + if (size == 2 && (ch != 0 || addr == A_TCR || addr == A_TCSR)) { + qemu_log_mask(LOG_GUEST_ERROR, "renesas_tmr: Invalid read size 0x%" + HWADDR_PRIX "\n", + addr); + return UINT64_MAX; + } + switch (addr & 0x0e) { + case A_TCR: + ret = 0; + ret = FIELD_DP8(ret, TCR, CCLR, + FIELD_EX8(tmr->tcr[ch], TCR, CCLR)); + ret = FIELD_DP8(ret, TCR, OVIE, + FIELD_EX8(tmr->tcr[ch], TCR, OVIE)); + ret = FIELD_DP8(ret, TCR, CMIEA, + FIELD_EX8(tmr->tcr[ch], TCR, CMIEA)); + ret = FIELD_DP8(ret, TCR, CMIEB, + FIELD_EX8(tmr->tcr[ch], TCR, CMIEB)); + return ret; + case A_TCSR: + ret = 0; + ret = FIELD_DP8(ret, TCSR, OSA, + FIELD_EX8(tmr->tcsr[ch], TCSR, OSA)); + ret = FIELD_DP8(ret, TCSR, OSB, + FIELD_EX8(tmr->tcsr[ch], TCSR, OSB)); + switch (ch) { + case 0: + ret = FIELD_DP8(ret, TCSR, ADTE, + FIELD_EX8(tmr->tcsr[ch], TCSR, ADTE)); + break; + case 1: /* CH1 ADTE unimplement always 1 */ + ret = FIELD_DP8(ret, TCSR, ADTE, 1); + break; + } + return ret; + case A_TCORA: + if (size == 1) { + return tmr->tcora[ch]; + } else if (ch == 0) { + return concat_reg(tmr->tcora); + } + case A_TCORB: + if (size == 1) { + return tmr->tcorb[ch]; + } else { + return concat_reg(tmr->tcorb); + } + case A_TCNT: + return read_tcnt(tmr, size, ch); + case A_TCCR: + if (size == 1) { + return read_tccr(tmr->tccr[ch]); + } else { + return read_tccr(tmr->tccr[0]) << 8 | read_tccr(tmr->tccr[1]); + } + default: + qemu_log_mask(LOG_UNIMP, "renesas_tmr: Register 0x%" HWADDR_PRIX + " not implemented\n", + addr); + break; + } + return UINT64_MAX; +} + +static void tmr_write_count(RTMRState *tmr, int ch, unsigned size, + uint8_t *reg, uint64_t val) +{ + if (size == 1) { + reg[ch] = val; + update_events(tmr, ch); + } else { + reg[0] = extract32(val, 8, 8); + reg[1] = extract32(val, 0, 8); + update_events(tmr, 0); + update_events(tmr, 1); + } +} + +static void tmr_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) +{ + RTMRState *tmr = opaque; + int ch = addr & 1; + + if (size == 2 && (ch != 0 || addr == A_TCR || addr == A_TCSR)) { + qemu_log_mask(LOG_GUEST_ERROR, + "renesas_tmr: Invalid write size 0x%" HWADDR_PRIX "\n", + addr); + return; + } + switch (addr & 0x0e) { + case A_TCR: + tmr->tcr[ch] = val; + break; + case A_TCSR: + tmr->tcsr[ch] = val; + break; + case A_TCORA: + tmr_write_count(tmr, ch, size, tmr->tcora, val); + break; + case A_TCORB: + tmr_write_count(tmr, ch, size, tmr->tcorb, val); + break; + case A_TCNT: + tmr_write_count(tmr, ch, size, tmr->tcnt, val); + break; + case A_TCCR: + tmr_write_count(tmr, ch, size, tmr->tccr, val); + break; + default: + qemu_log_mask(LOG_UNIMP, "renesas_tmr: Register 0x%" HWADDR_PRIX + " not implemented\n", + addr); + break; + } +} + +static const MemoryRegionOps tmr_ops = { + .write = tmr_write, + .read = tmr_read, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl = { + .min_access_size = 1, + .max_access_size = 2, + }, + .valid = { + .min_access_size = 1, + .max_access_size = 2, + }, +}; + +static void timer_events(RTMRState *tmr, int ch); + +static uint16_t issue_event(RTMRState *tmr, int ch, int sz, + uint16_t tcnt, uint16_t tcora, uint16_t tcorb) +{ + uint16_t ret = tcnt; + + switch (tmr->next[ch]) { + case none: + break; + case cmia: + if (tcnt >= tcora) { + if (FIELD_EX8(tmr->tcr[ch], TCR, CCLR) == CCLR_A) { + ret = tcnt - tcora; + } + if (FIELD_EX8(tmr->tcr[ch], TCR, CMIEA)) { + qemu_irq_pulse(tmr->cmia[ch]); + } + if (sz == 8 && ch == 0 && + FIELD_EX8(tmr->tccr[1], TCCR, CSS) == CASCADING) { + tmr->tcnt[1]++; + timer_events(tmr, 1); + } + } + break; + case cmib: + if (tcnt >= tcorb) { + if (FIELD_EX8(tmr->tcr[ch], TCR, CCLR) == CCLR_B) { + ret = tcnt - tcorb; + } + if (FIELD_EX8(tmr->tcr[ch], TCR, CMIEB)) { + qemu_irq_pulse(tmr->cmib[ch]); + } + } + break; + case ovi: + if ((tcnt >= (1 << sz)) && FIELD_EX8(tmr->tcr[ch], TCR, OVIE)) { + qemu_irq_pulse(tmr->ovi[ch]); + } + break; + default: + g_assert_not_reached(); + } + return ret; +} + +static void timer_events(RTMRState *tmr, int ch) +{ + uint16_t tcnt; + + tmr->tcnt[ch] = read_tcnt(tmr, 1, ch); + if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) != CASCADING) { + tmr->tcnt[ch] = issue_event(tmr, ch, 8, + tmr->tcnt[ch], + tmr->tcora[ch], + tmr->tcorb[ch]) & 0xff; + } else { + if (ch == 1) { + return ; + } + tcnt = issue_event(tmr, ch, 16, + concat_reg(tmr->tcnt), + concat_reg(tmr->tcora), + concat_reg(tmr->tcorb)); + tmr->tcnt[0] = (tcnt >> 8) & 0xff; + tmr->tcnt[1] = tcnt & 0xff; + } + update_events(tmr, ch); +} + +static void timer_event0(void *opaque) +{ + RTMRState *tmr = opaque; + + timer_events(tmr, 0); +} + +static void timer_event1(void *opaque) +{ + RTMRState *tmr = opaque; + + timer_events(tmr, 1); +} + +static void rtmr_reset(DeviceState *dev) +{ + RTMRState *tmr = RTMR(dev); + tmr->tcr[0] = tmr->tcr[1] = 0x00; + tmr->tcsr[0] = 0x00; + tmr->tcsr[1] = 0x10; + tmr->tcnt[0] = tmr->tcnt[1] = 0x00; + tmr->tcora[0] = tmr->tcora[1] = 0xff; + tmr->tcorb[0] = tmr->tcorb[1] = 0xff; + tmr->tccr[0] = tmr->tccr[1] = 0x00; + tmr->next[0] = tmr->next[1] = none; + tmr->tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +} + +static void rtmr_init(Object *obj) +{ + SysBusDevice *d = SYS_BUS_DEVICE(obj); + RTMRState *tmr = RTMR(obj); + int i; + + memory_region_init_io(&tmr->memory, OBJECT(tmr), &tmr_ops, + tmr, "renesas-tmr", 0x10); + sysbus_init_mmio(d, &tmr->memory); + + for (i = 0; i < ARRAY_SIZE(tmr->ovi); i++) { + sysbus_init_irq(d, &tmr->cmia[i]); + sysbus_init_irq(d, &tmr->cmib[i]); + sysbus_init_irq(d, &tmr->ovi[i]); + } + timer_init_ns(&tmr->timer[0], QEMU_CLOCK_VIRTUAL, timer_event0, tmr); + timer_init_ns(&tmr->timer[1], QEMU_CLOCK_VIRTUAL, timer_event1, tmr); +} + +static const VMStateDescription vmstate_rtmr = { + .name = "rx-tmr", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_INT64(tick, RTMRState), + VMSTATE_UINT8_ARRAY(tcnt, RTMRState, TMR_CH), + VMSTATE_UINT8_ARRAY(tcora, RTMRState, TMR_CH), + VMSTATE_UINT8_ARRAY(tcorb, RTMRState, TMR_CH), + VMSTATE_UINT8_ARRAY(tcr, RTMRState, TMR_CH), + VMSTATE_UINT8_ARRAY(tccr, RTMRState, TMR_CH), + VMSTATE_UINT8_ARRAY(tcor, RTMRState, TMR_CH), + VMSTATE_UINT8_ARRAY(tcsr, RTMRState, TMR_CH), + VMSTATE_INT64_ARRAY(div_round, RTMRState, TMR_CH), + VMSTATE_UINT8_ARRAY(next, RTMRState, TMR_CH), + VMSTATE_TIMER_ARRAY(timer, RTMRState, TMR_CH), + VMSTATE_END_OF_LIST() + } +}; + +static Property rtmr_properties[] = { + DEFINE_PROP_UINT64("input-freq", RTMRState, input_freq, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void rtmr_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->vmsd = &vmstate_rtmr; + dc->reset = rtmr_reset; + device_class_set_props(dc, rtmr_properties); +} + +static const TypeInfo rtmr_info = { + .name = TYPE_RENESAS_TMR, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(RTMRState), + .instance_init = rtmr_init, + .class_init = rtmr_class_init, +}; + +static void rtmr_register_types(void) +{ + type_register_static(&rtmr_info); +} + +type_init(rtmr_register_types) diff --git a/hw/timer/sh_timer.c b/hw/timer/sh_timer.c index 13c4051808fc26ab3451d3a518a2c25f3211dc3f..58af1a1edbdc9db3981173ae331cd97357da1279 100644 --- a/hw/timer/sh_timer.c +++ b/hw/timer/sh_timer.c @@ -9,10 +9,11 @@ */ #include "qemu/osdep.h" +#include "exec/memory.h" #include "hw/hw.h" #include "hw/irq.h" #include "hw/sh4/sh.h" -#include "qemu/timer.h" +#include "hw/timer/tmu012.h" #include "hw/ptimer.h" //#define DEBUG_TIMER @@ -116,35 +117,55 @@ static void sh_timer_write(void *opaque, hwaddr offset, case 2: freq >>= 6; break; case 3: freq >>= 8; break; case 4: freq >>= 10; break; - case 6: - case 7: if (s->feat & TIMER_FEAT_EXTCLK) break; - default: hw_error("sh_timer_write: Reserved TPSC value\n"); break; + case 6: + case 7: + if (s->feat & TIMER_FEAT_EXTCLK) { + break; + } + /* fallthrough */ + default: + hw_error("sh_timer_write: Reserved TPSC value\n"); } switch ((value & TIMER_TCR_CKEG) >> 3) { - case 0: break; + case 0: + break; case 1: case 2: - case 3: if (s->feat & TIMER_FEAT_EXTCLK) break; - default: hw_error("sh_timer_write: Reserved CKEG value\n"); break; + case 3: + if (s->feat & TIMER_FEAT_EXTCLK) { + break; + } + /* fallthrough */ + default: + hw_error("sh_timer_write: Reserved CKEG value\n"); } switch ((value & TIMER_TCR_ICPE) >> 6) { - case 0: break; + case 0: + break; case 2: - case 3: if (s->feat & TIMER_FEAT_CAPT) break; - default: hw_error("sh_timer_write: Reserved ICPE value\n"); break; + case 3: + if (s->feat & TIMER_FEAT_CAPT) { + break; + } + /* fallthrough */ + default: + hw_error("sh_timer_write: Reserved ICPE value\n"); } - if ((value & TIMER_TCR_UNF) == 0) + if ((value & TIMER_TCR_UNF) == 0) { s->int_level = 0; + } - value &= ~TIMER_TCR_UNF; + value &= ~TIMER_TCR_UNF; - if ((value & TIMER_TCR_ICPF) && (!(s->feat & TIMER_FEAT_CAPT))) + if ((value & TIMER_TCR_ICPF) && (!(s->feat & TIMER_FEAT_CAPT))) { hw_error("sh_timer_write: Reserved ICPF value\n"); + } - value &= ~TIMER_TCR_ICPF; /* capture not supported */ + value &= ~TIMER_TCR_ICPF; /* capture not supported */ - if (value & TIMER_TCR_RESERVED) + if (value & TIMER_TCR_RESERVED) { hw_error("sh_timer_write: Reserved TCR bits set\n"); + } s->tcr = value; ptimer_set_limit(s->timer, s->tcor, 0); ptimer_set_freq(s->timer, freq); @@ -157,8 +178,9 @@ static void sh_timer_write(void *opaque, hwaddr offset, case OFFSET_TCPR: if (s->feat & TIMER_FEAT_CAPT) { s->tcpr = value; - break; - } + break; + } + /* fallthrough */ default: hw_error("sh_timer_write: Bad offset %x\n", (int)offset); } @@ -240,8 +262,9 @@ static uint64_t tmu012_read(void *opaque, hwaddr offset, #endif if (offset >= 0x20) { - if (!(s->feat & TMU012_FEAT_3CHAN)) - hw_error("tmu012_write: Bad channel offset %x\n", (int)offset); + if (!(s->feat & TMU012_FEAT_3CHAN)) { + hw_error("tmu012_write: Bad channel offset %x\n", (int)offset); + } return sh_timer_read(s->timer[2], offset - 0x20); } @@ -271,33 +294,36 @@ static void tmu012_write(void *opaque, hwaddr offset, #endif if (offset >= 0x20) { - if (!(s->feat & TMU012_FEAT_3CHAN)) - hw_error("tmu012_write: Bad channel offset %x\n", (int)offset); + if (!(s->feat & TMU012_FEAT_3CHAN)) { + hw_error("tmu012_write: Bad channel offset %x\n", (int)offset); + } sh_timer_write(s->timer[2], offset - 0x20, value); - return; + return; } if (offset >= 0x14) { sh_timer_write(s->timer[1], offset - 0x14, value); - return; + return; } if (offset >= 0x08) { sh_timer_write(s->timer[0], offset - 0x08, value); - return; + return; } if (offset == 4) { sh_timer_start_stop(s->timer[0], value & (1 << 0)); sh_timer_start_stop(s->timer[1], value & (1 << 1)); - if (s->feat & TMU012_FEAT_3CHAN) + if (s->feat & TMU012_FEAT_3CHAN) { sh_timer_start_stop(s->timer[2], value & (1 << 2)); - else - if (value & (1 << 2)) + } else { + if (value & (1 << 2)) { hw_error("tmu012_write: Bad channel\n"); + } + } - s->tstr = value; - return; + s->tstr = value; + return; } if ((s->feat & TMU012_FEAT_TOCR) && offset == 0) { @@ -313,8 +339,8 @@ static const MemoryRegionOps tmu012_ops = { void tmu012_init(MemoryRegion *sysmem, hwaddr base, int feat, uint32_t freq, - qemu_irq ch0_irq, qemu_irq ch1_irq, - qemu_irq ch2_irq0, qemu_irq ch2_irq1) + qemu_irq ch0_irq, qemu_irq ch1_irq, + qemu_irq ch2_irq0, qemu_irq ch2_irq1) { tmu012_state *s; int timer_feat = (feat & TMU012_FEAT_EXTCLK) ? TIMER_FEAT_EXTCLK : 0; @@ -323,9 +349,10 @@ void tmu012_init(MemoryRegion *sysmem, hwaddr base, s->feat = feat; s->timer[0] = sh_timer_init(freq, timer_feat, ch0_irq); s->timer[1] = sh_timer_init(freq, timer_feat, ch1_irq); - if (feat & TMU012_FEAT_3CHAN) + if (feat & TMU012_FEAT_3CHAN) { s->timer[2] = sh_timer_init(freq, timer_feat | TIMER_FEAT_CAPT, - ch2_irq0); /* ch2_irq1 not supported */ + ch2_irq0); /* ch2_irq1 not supported */ + } memory_region_init_io(&s->iomem, NULL, &tmu012_ops, s, "timer", 0x100000000ULL); diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c index 4c5d65e391af8acc8a262a7314e5ceb1f29f1d15..5b2d20cb6a5a65a762e8021243cb917f6dbc27ac 100644 --- a/hw/timer/slavio_timer.c +++ b/hw/timer/slavio_timer.c @@ -31,6 +31,7 @@ #include "migration/vmstate.h" #include "trace.h" #include "qemu/module.h" +#include "qom/object.h" /* * Registers of hardware timer in sun4m. @@ -59,16 +60,15 @@ typedef struct CPUTimerState { } CPUTimerState; #define TYPE_SLAVIO_TIMER "slavio_timer" -#define SLAVIO_TIMER(obj) \ - OBJECT_CHECK(SLAVIO_TIMERState, (obj), TYPE_SLAVIO_TIMER) +OBJECT_DECLARE_SIMPLE_TYPE(SLAVIO_TIMERState, SLAVIO_TIMER) -typedef struct SLAVIO_TIMERState { +struct SLAVIO_TIMERState { SysBusDevice parent_obj; uint32_t num_cpus; uint32_t cputimer_mode; CPUTimerState cputimer[MAX_CPUS + 1]; -} SLAVIO_TIMERState; +}; typedef struct TimerContext { MemoryRegion iomem; diff --git a/hw/timer/trace-events b/hw/timer/trace-events index 80ea197594eb340c5c22754f0311c74c1b3f0b6a..7a4326d9566ef351f8b749c0746a8e5a2be6345c 100644 --- a/hw/timer/trace-events +++ b/hw/timer/trace-events @@ -19,7 +19,7 @@ slavio_timer_mem_writel_invalid(uint64_t addr) "invalid write address 0x%"PRIx64 grlib_gptimer_enable(int id, uint32_t count) "timer:%d set count 0x%x and run" grlib_gptimer_disabled(int id, uint32_t config) "timer:%d Timer disable config 0x%x" grlib_gptimer_restart(int id, uint32_t reload) "timer:%d reload val: 0x%x" -grlib_gptimer_set_scaler(uint32_t scaler, uint32_t freq) "scaler:0x%x freq: 0x%x" +grlib_gptimer_set_scaler(uint32_t scaler, uint32_t freq) "scaler:0x%x freq:%uHz" grlib_gptimer_hit(int id) "timer:%d HIT" grlib_gptimer_readl(int id, uint64_t addr, uint32_t val) "timer:%d addr 0x%"PRIx64" 0x%x" grlib_gptimer_writel(int id, uint64_t addr, uint32_t val) "timer:%d addr 0x%"PRIx64" 0x%x" @@ -66,12 +66,30 @@ cmsdk_apb_dualtimer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK A cmsdk_apb_dualtimer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB dualtimer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" cmsdk_apb_dualtimer_reset(void) "CMSDK APB dualtimer: reset" +# npcm7xx_timer.c +npcm7xx_timer_read(const char *id, uint64_t offset, uint64_t value) " %s offset: 0x%04" PRIx64 " value 0x%08" PRIx64 +npcm7xx_timer_write(const char *id, uint64_t offset, uint64_t value) "%s offset: 0x%04" PRIx64 " value 0x%08" PRIx64 +npcm7xx_timer_irq(const char *id, int timer, int state) "%s timer %d state %d" + # nrf51_timer.c nrf51_timer_read(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size) "timer %u read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" nrf51_timer_write(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size) "timer %u write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" nrf51_timer_set_count(uint8_t timer_id, uint8_t counter_id, uint32_t value) "timer %u counter %u count 0x%" PRIx32 # bcm2835_systmr.c -bcm2835_systmr_irq(bool enable) "timer irq state %u" +bcm2835_systmr_timer_expired(unsigned id) "timer #%u expired" +bcm2835_systmr_irq_ack(unsigned id) "timer #%u acked" bcm2835_systmr_read(uint64_t offset, uint64_t data) "timer read: offset 0x%" PRIx64 " data 0x%" PRIx64 -bcm2835_systmr_write(uint64_t offset, uint64_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 +bcm2835_systmr_write(uint64_t offset, uint32_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx32 +bcm2835_systmr_run(unsigned id, uint64_t delay_us) "timer #%u expiring in %"PRIu64" us" + +# avr_timer16.c +avr_timer16_read(uint8_t addr, uint8_t value) "timer16 read addr:%u value:%u" +avr_timer16_read_ifr(uint8_t value) "timer16 read addr:ifr value:%u" +avr_timer16_read_imsk(uint8_t value) "timer16 read addr:imsk value:%u" +avr_timer16_write(uint8_t addr, uint8_t value) "timer16 write addr:%u value:%u" +avr_timer16_write_imsk(uint8_t value) "timer16 write addr:imsk value:%u" +avr_timer16_interrupt_count(uint8_t cnt) "count: %u" +avr_timer16_interrupt_overflow(const char *reason) "overflow: %s" +avr_timer16_next_alarm(uint64_t delay_ns) "next alarm: %" PRIu64 " ns from now" +avr_timer16_clksrc_update(uint64_t freq_hz, uint64_t period_ns, uint64_t delay_s) "timer frequency: %" PRIu64 " Hz, period: %" PRIu64 " ns (%" PRId64 " us)" diff --git a/hw/timer/trace.h b/hw/timer/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..5f72c441b0b7b02b6983eb211a7b6c35a996bd06 --- /dev/null +++ b/hw/timer/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_timer.h" diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c index 0190aa47d00dab3aafdcdde001f7c7ce410bc4ef..1eb927eb84730a43022406f2d78bf90d90065c97 100644 --- a/hw/timer/xilinx_timer.c +++ b/hw/timer/xilinx_timer.c @@ -29,6 +29,7 @@ #include "hw/qdev-properties.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qom/object.h" #define D(x) @@ -61,8 +62,8 @@ struct xlx_timer }; #define TYPE_XILINX_TIMER "xlnx.xps-timer" -#define XILINX_TIMER(obj) \ - OBJECT_CHECK(struct timerblock, (obj), TYPE_XILINX_TIMER) +DECLARE_INSTANCE_CHECKER(struct timerblock, XILINX_TIMER, + TYPE_XILINX_TIMER) struct timerblock { diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig index 4794e7fe28ae052073d220b3e046f7d95bef019e..29e82f3c92d9534076834b1e8822c06eec83057d 100644 --- a/hw/tpm/Kconfig +++ b/hw/tpm/Kconfig @@ -1,7 +1,3 @@ -config TPMDEV - bool - depends on TPM - config TPM_TIS_ISA bool depends on TPM && ISA_BUS @@ -15,26 +11,15 @@ config TPM_TIS_SYSBUS config TPM_TIS bool depends on TPM - select TPMDEV + select TPM_BACKEND config TPM_CRB bool depends on TPM && PC - select TPMDEV - -config TPM_PASSTHROUGH - bool - default y - # FIXME: should check for x86 host as well - depends on TPMDEV && LINUX - -config TPM_EMULATOR - bool - default y - depends on TPMDEV + select TPM_BACKEND config TPM_SPAPR bool default y depends on TPM && PSERIES - select TPMDEV + select TPM_BACKEND diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs deleted file mode 100644 index f1ec4beb95cfb4ec7149e66c172a2371beb5b198..0000000000000000000000000000000000000000 --- a/hw/tpm/Makefile.objs +++ /dev/null @@ -1,9 +0,0 @@ -common-obj-$(CONFIG_TPM) += tpm_util.o -obj-$(call lor,$(CONFIG_TPM_TIS),$(CONFIG_TPM_CRB)) += tpm_ppi.o -common-obj-$(CONFIG_TPM_TIS_ISA) += tpm_tis_isa.o -common-obj-$(CONFIG_TPM_TIS_SYSBUS) += tpm_tis_sysbus.o -common-obj-$(CONFIG_TPM_TIS) += tpm_tis_common.o -common-obj-$(CONFIG_TPM_CRB) += tpm_crb.o -common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o -common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o -obj-$(CONFIG_TPM_SPAPR) += tpm_spapr.o diff --git a/hw/tpm/meson.build b/hw/tpm/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..1c68d81d6ab2f0d170bfc1b08b40150153c0d0d6 --- /dev/null +++ b/hw/tpm/meson.build @@ -0,0 +1,8 @@ +softmmu_ss.add(when: 'CONFIG_TPM_TIS', if_true: files('tpm_tis_common.c')) +softmmu_ss.add(when: 'CONFIG_TPM_TIS_ISA', if_true: files('tpm_tis_isa.c')) +softmmu_ss.add(when: 'CONFIG_TPM_TIS_SYSBUS', if_true: files('tpm_tis_sysbus.c')) +softmmu_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb.c')) + +specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TPM_TIS'], if_true: files('tpm_ppi.c')) +specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TPM_CRB'], if_true: files('tpm_ppi.c')) +specific_ss.add(when: 'CONFIG_TPM_SPAPR', if_true: files('tpm_spapr.c')) diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c index cd004e7f8e9c6a2226a17d828b1fb0aed0c3c153..aa9c00aad3a37225e22b0bab5816f55d10e51eaf 100644 --- a/hw/tpm/tpm_crb.c +++ b/hw/tpm/tpm_crb.c @@ -24,13 +24,14 @@ #include "hw/acpi/tpm.h" #include "migration/vmstate.h" #include "sysemu/tpm_backend.h" +#include "sysemu/tpm_util.h" #include "sysemu/reset.h" -#include "tpm_int.h" -#include "tpm_util.h" +#include "tpm_prop.h" #include "tpm_ppi.h" #include "trace.h" +#include "qom/object.h" -typedef struct CRBState { +struct CRBState { DeviceState parent_obj; TPMBackend *tpmbe; @@ -43,9 +44,11 @@ typedef struct CRBState { bool ppi_enabled; TPMPPI ppi; -} CRBState; +}; +typedef struct CRBState CRBState; -#define CRB(obj) OBJECT_CHECK(CRBState, (obj), TYPE_TPM_CRB) +DECLARE_INSTANCE_CHECKER(CRBState, CRB, + TYPE_TPM_CRB) #define CRB_INTF_TYPE_CRB_ACTIVE 0b1 #define CRB_INTF_VERSION_CRB 0b1 diff --git a/hw/tpm/tpm_ppi.c b/hw/tpm/tpm_ppi.c index 6d9c1a3e40ee6f76d0b582d13f5b874742e5eefa..72d7a3d9260839bc1464f4e776949d35ea9f821d 100644 --- a/hw/tpm/tpm_ppi.c +++ b/hw/tpm/tpm_ppi.c @@ -17,6 +17,7 @@ #include "cpu.h" #include "sysemu/memory_mapping.h" #include "migration/vmstate.h" +#include "hw/acpi/tpm.h" #include "tpm_ppi.h" #include "trace.h" diff --git a/hw/tpm/tpm_ppi.h b/hw/tpm/tpm_ppi.h index d33ef27de6d685df8a12c3f8daa24bceb47e22a8..6f773c25a0ba75a4434e6830355865226568e6ba 100644 --- a/hw/tpm/tpm_ppi.h +++ b/hw/tpm/tpm_ppi.h @@ -12,7 +12,6 @@ #ifndef TPM_TPM_PPI_H #define TPM_TPM_PPI_H -#include "hw/acpi/tpm.h" #include "exec/address-spaces.h" typedef struct TPMPPI { diff --git a/hw/tpm/tpm_prop.h b/hw/tpm/tpm_prop.h new file mode 100644 index 0000000000000000000000000000000000000000..d19e40c11202cf1a7f3291cc08a85ce4f2467bf1 --- /dev/null +++ b/hw/tpm/tpm_prop.h @@ -0,0 +1,31 @@ +/* + * TPM utility functions + * + * Copyright (c) 2010 - 2015 IBM Corporation + * Authors: + * Stefan Berger + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + */ + +#ifndef HW_TPM_PROP_H +#define HW_TPM_PROP_H + +#include "sysemu/tpm_backend.h" +#include "hw/qdev-properties.h" + +#define DEFINE_PROP_TPMBE(_n, _s, _f) \ + DEFINE_PROP(_n, _s, _f, qdev_prop_tpm, TPMBackend *) + +#endif /* HW_TPM_PROP_H */ diff --git a/hw/tpm/tpm_spapr.c b/hw/tpm/tpm_spapr.c index ce65eb2e4591d463abcded7f83c7981f57e9fcb1..e3775adc579d0fa4a075ba28165dcd9f57b63cc4 100644 --- a/hw/tpm/tpm_spapr.c +++ b/hw/tpm/tpm_spapr.c @@ -20,17 +20,19 @@ #include "migration/vmstate.h" #include "sysemu/tpm_backend.h" -#include "tpm_int.h" -#include "tpm_util.h" +#include "sysemu/tpm_util.h" +#include "tpm_prop.h" #include "hw/ppc/spapr.h" #include "hw/ppc/spapr_vio.h" #include "trace.h" +#include "qom/object.h" #define DEBUG_SPAPR 0 -#define VIO_SPAPR_VTPM(obj) \ - OBJECT_CHECK(SpaprTpmState, (obj), TYPE_TPM_SPAPR) +typedef struct SpaprTpmState SpaprTpmState; +DECLARE_INSTANCE_CHECKER(SpaprTpmState, VIO_SPAPR_VTPM, + TYPE_TPM_SPAPR) typedef struct TpmCrq { uint8_t valid; /* 0x80: cmd; 0xc0: init crq */ @@ -64,7 +66,7 @@ typedef struct TpmCrq { #define TPM_SPAPR_BUFFER_MAX 4096 -typedef struct { +struct SpaprTpmState { SpaprVioDevice vdev; TpmCrq crq; /* track single TPM command */ @@ -84,7 +86,7 @@ typedef struct { TPMVersion be_tpm_version; size_t be_buffer_size; -} SpaprTpmState; +}; /* * Send a request to the TPM. @@ -306,7 +308,10 @@ static void tpm_spapr_reset(SpaprVioDevice *dev) TPM_SPAPR_BUFFER_MAX); tpm_backend_reset(s->be_driver); - tpm_spapr_do_startup_tpm(s, s->be_buffer_size); + + if (tpm_spapr_do_startup_tpm(s, s->be_buffer_size) < 0) { + exit(1); + } } static enum TPMVersion tpm_spapr_get_version(TPMIf *ti) diff --git a/hw/tpm/tpm_tis.h b/hw/tpm/tpm_tis.h index 555498939532508cfffda8a175b01b51906a2422..f6b5872ba63ed6b7ba4c57d4247826b04caff165 100644 --- a/hw/tpm/tpm_tis.h +++ b/hw/tpm/tpm_tis.h @@ -24,7 +24,6 @@ #ifndef TPM_TPM_TIS_H #define TPM_TPM_TIS_H -#include "qemu/osdep.h" #include "sysemu/tpm_backend.h" #include "tpm_ppi.h" diff --git a/hw/tpm/tpm_tis_common.c b/hw/tpm/tpm_tis_common.c index 1af4bce139f06d6efe04bbec3925c7d225842359..e700d821816a270d3b4f265e1fa51b3b60d076cf 100644 --- a/hw/tpm/tpm_tis_common.c +++ b/hw/tpm/tpm_tis_common.c @@ -33,8 +33,7 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "sysemu/tpm_backend.h" -#include "tpm_int.h" -#include "tpm_util.h" +#include "sysemu/tpm_util.h" #include "tpm_ppi.h" #include "trace.h" @@ -79,9 +78,7 @@ static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags) */ static void tpm_tis_tpm_send(TPMState *s, uint8_t locty) { - if (trace_event_get_state_backends(TRACE_TPM_UTIL_SHOW_BUFFER)) { - tpm_util_show_buffer(s->buffer, s->be_buffer_size, "To TPM"); - } + tpm_util_show_buffer(s->buffer, s->be_buffer_size, "To TPM"); /* * rw_offset serves as length indicator for length of data; @@ -247,9 +244,7 @@ void tpm_tis_request_completed(TPMState *s, int ret) s->loc[locty].state = TPM_TIS_STATE_COMPLETION; s->rw_offset = 0; - if (trace_event_get_state_backends(TRACE_TPM_UTIL_SHOW_BUFFER)) { - tpm_util_show_buffer(s->buffer, s->be_buffer_size, "From TPM"); - } + tpm_util_show_buffer(s->buffer, s->be_buffer_size, "From TPM"); if (TPM_TIS_IS_VALID_LOCTY(s->next_locty)) { tpm_tis_abort(s); diff --git a/hw/tpm/tpm_tis_isa.c b/hw/tpm/tpm_tis_isa.c index 30ba37079de075db3093d2984446b9e5a3960f1d..6fd876eebf1455e5ebb8c76dd69b48082fb759d8 100644 --- a/hw/tpm/tpm_tis_isa.c +++ b/hw/tpm/tpm_tis_isa.c @@ -26,18 +26,20 @@ #include "hw/isa/isa.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" -#include "tpm_util.h" +#include "hw/acpi/tpm.h" +#include "tpm_prop.h" #include "tpm_tis.h" +#include "qom/object.h" -typedef struct TPMStateISA { +struct TPMStateISA { /*< private >*/ ISADevice parent_obj; /*< public >*/ TPMState state; /* not a QOM object */ -} TPMStateISA; +}; -#define TPM_TIS_ISA(obj) OBJECT_CHECK(TPMStateISA, (obj), TYPE_TPM_TIS_ISA) +OBJECT_DECLARE_SIMPLE_TYPE(TPMStateISA, TPM_TIS_ISA) static int tpm_tis_pre_save_isa(void *opaque) { diff --git a/hw/tpm/tpm_tis_sysbus.c b/hw/tpm/tpm_tis_sysbus.c index eced1fc843f136fc5fd691eceb5a6b5e641d8ccc..2c32aa709934bd81bb95909d49c64df8db391367 100644 --- a/hw/tpm/tpm_tis_sysbus.c +++ b/hw/tpm/tpm_tis_sysbus.c @@ -25,19 +25,21 @@ #include "qemu/osdep.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" -#include "tpm_util.h" +#include "hw/acpi/tpm.h" +#include "tpm_prop.h" #include "hw/sysbus.h" #include "tpm_tis.h" +#include "qom/object.h" -typedef struct TPMStateSysBus { +struct TPMStateSysBus { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ TPMState state; /* not a QOM object */ -} TPMStateSysBus; +}; -#define TPM_TIS_SYSBUS(obj) OBJECT_CHECK(TPMStateSysBus, (obj), TYPE_TPM_TIS_SYSBUS) +OBJECT_DECLARE_SIMPLE_TYPE(TPMStateSysBus, TPM_TIS_SYSBUS) static int tpm_tis_pre_save_sysbus(void *opaque) { diff --git a/hw/tpm/trace-events b/hw/tpm/trace-events index 439e5147870c51b0cc86c1674393b5caef2ae9a9..266de17d387903eb400cda46eddef3fec05cc056 100644 --- a/hw/tpm/trace-events +++ b/hw/tpm/trace-events @@ -4,39 +4,7 @@ tpm_crb_mmio_read(uint64_t addr, unsigned size, uint32_t val) "CRB read 0x%016" PRIx64 " len:%u val: 0x%" PRIx32 tpm_crb_mmio_write(uint64_t addr, unsigned size, uint32_t val) "CRB write 0x%016" PRIx64 " len:%u val: 0x%" PRIx32 -# tpm_passthrough.c -tpm_passthrough_handle_request(void *cmd) "processing command %p" -tpm_passthrough_reset(void) "reset" - -# tpm_util.c -tpm_util_get_buffer_size_hdr_len(uint32_t len, size_t expected) "tpm_resp->hdr.len = %u, expected = %zu" -tpm_util_get_buffer_size_len(uint32_t len, size_t expected) "tpm_resp->len = %u, expected = %zu" -tpm_util_get_buffer_size_hdr_len2(uint32_t len, size_t expected) "tpm2_resp->hdr.len = %u, expected = %zu" -tpm_util_get_buffer_size_len2(uint32_t len, size_t expected) "tpm2_resp->len = %u, expected = %zu" -tpm_util_get_buffer_size(size_t len) "buffersize of device: %zu" -tpm_util_show_buffer(const char *direction, size_t len, const char *buf) "direction: %s len: %zu\n%s" - -# tpm_emulator.c -tpm_emulator_set_locality(uint8_t locty) "setting locality to %d" -tpm_emulator_handle_request(void) "processing TPM command" -tpm_emulator_probe_caps(uint64_t caps) "capabilities: 0x%"PRIx64 -tpm_emulator_set_buffer_size(uint32_t buffersize, uint32_t minsize, uint32_t maxsize) "buffer size: %u, min: %u, max: %u" -tpm_emulator_startup_tpm_resume(bool is_resume, size_t buffersize) "is_resume: %d, buffer size: %zu" -tpm_emulator_get_tpm_established_flag(uint8_t flag) "got established flag: %d" -tpm_emulator_cancel_cmd_not_supt(void) "Backend does not support CANCEL_TPM_CMD" -tpm_emulator_handle_device_opts_tpm12(void) "TPM Version 1.2" -tpm_emulator_handle_device_opts_tpm2(void) "TPM Version 2" -tpm_emulator_handle_device_opts_unspec(void) "TPM Version Unspecified" -tpm_emulator_handle_device_opts_startup_error(void) "Startup error" -tpm_emulator_get_state_blob(uint8_t type, uint32_t size, uint32_t flags) "got state blob type %d, %u bytes, flags 0x%08x" -tpm_emulator_set_state_blob(uint8_t type, uint32_t size, uint32_t flags) "set state blob type %d, %u bytes, flags 0x%08x" -tpm_emulator_set_state_blobs(void) "setting state blobs" -tpm_emulator_set_state_blobs_error(const char *msg) "error while setting state blobs: %s" -tpm_emulator_set_state_blobs_done(void) "Done setting state blobs" -tpm_emulator_pre_save(void) "" -tpm_emulator_inst_init(void) "" - -# tpm_tis.c +# tpm_tis_common.c tpm_tis_raise_irq(uint32_t irqmask) "Raising IRQ for flag 0x%08x" tpm_tis_new_active_locality(uint8_t locty) "Active locality is now %d" tpm_tis_abort(uint8_t locty) "New active locality is %d" @@ -56,7 +24,7 @@ tpm_tis_pre_save(uint8_t locty, uint32_t rw_offset) "locty: %d, rw_offset = %u" # tpm_ppi.c tpm_ppi_memset(uint8_t *ptr, size_t size) "memset: %p %zu" -# hw/tpm/tpm_spapr.c +# tpm_spapr.c tpm_spapr_show_buffer(const char *direction, size_t len, const char *buf) "direction: %s len: %zu\n%s" tpm_spapr_do_crq(uint8_t raw1, uint8_t raw2) "1st 2 bytes in CRQ: 0x%02x 0x%02x" tpm_spapr_do_crq_crq_result(void) "SPAPR_VTPM_INIT_CRQ_RESULT" diff --git a/hw/tpm/trace.h b/hw/tpm/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..9827c128aadd23045171acf1b88fbaaad00cbe66 --- /dev/null +++ b/hw/tpm/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_tpm.h" diff --git a/hw/tricore/Makefile.objs b/hw/tricore/Makefile.objs deleted file mode 100644 index 5501f6c1a88296f33a03c39796bee0ce9c914f5d..0000000000000000000000000000000000000000 --- a/hw/tricore/Makefile.objs +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_TRICORE) += tricore_testboard.o diff --git a/hw/tricore/meson.build b/hw/tricore/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..579aa13c78143219878f7fbf9a1d3ee0e783db6b --- /dev/null +++ b/hw/tricore/meson.build @@ -0,0 +1,4 @@ +tricore_ss = ss.source_set() +tricore_ss.add(when: 'CONFIG_TRICORE', if_true: files('tricore_testboard.c')) + +hw_arch += {'tricore': tricore_ss} diff --git a/hw/tricore/tricore_testboard.c b/hw/tricore/tricore_testboard.c index 8ec2b5bddd91c2e0f01db22d1838568b5001fac9..12ea1490fde2265d91f71e3a04031471b839fc06 100644 --- a/hw/tricore/tricore_testboard.c +++ b/hw/tricore/tricore_testboard.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/unicore32/Makefile.objs b/hw/unicore32/Makefile.objs deleted file mode 100644 index e0fd62852308e81f429a97a7770312b22724cb9f..0000000000000000000000000000000000000000 --- a/hw/unicore32/Makefile.objs +++ /dev/null @@ -1,4 +0,0 @@ -# For UniCore32 machines and boards - -# PKUnity-v3 SoC and board information -obj-${CONFIG_PUV3} += puv3.o diff --git a/hw/unicore32/meson.build b/hw/unicore32/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..fc26d6bcabe7e0802534844063d6f6a807d93def --- /dev/null +++ b/hw/unicore32/meson.build @@ -0,0 +1,5 @@ +unicore32_ss = ss.source_set() +# PKUnity-v3 SoC and board information +unicore32_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3.c')) + +hw_arch += {'unicore32': unicore32_ss} diff --git a/hw/unicore32/puv3.c b/hw/unicore32/puv3.c index 7f9c0238fe0f6a3f342a8b64815ff9c4f55074c4..eacacb4249bd84079dc9e3e12c48b42ffcce3d2a 100644 --- a/hw/unicore32/puv3.c +++ b/hw/unicore32/puv3.c @@ -16,8 +16,6 @@ #include "hw/boards.h" #include "hw/loader.h" #include "sysemu/qtest.h" - -#undef DEBUG_PUV3 #include "hw/unicore32/puv3.h" #include "hw/input/i8042.h" #include "hw/irq.h" diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig index 464348ba14296f1a74d667882233702d9ae308ca..7fbae18bc803cfa20c53970272546581ad2d95a5 100644 --- a/hw/usb/Kconfig +++ b/hw/usb/Kconfig @@ -31,21 +31,32 @@ config USB_EHCI_SYSBUS select USB_EHCI config USB_XHCI + bool + select USB + +config USB_XHCI_PCI bool default y if PCI_DEVICES depends on PCI - select USB + select USB_XHCI config USB_XHCI_NEC bool default y if PCI_DEVICES - depends on PCI + select USB_XHCI_PCI + +config USB_XHCI_SYSBUS + bool select USB_XHCI config USB_MUSB bool select USB +config USB_DWC2 + bool + select USB + config TUSB6010 bool select USB_MUSB @@ -92,6 +103,11 @@ config USB_STORAGE_MTP default y depends on USB +config USB_U2F + bool + default y + depends on USB + config IMX_USBPHY bool default y diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs deleted file mode 100644 index 66835e5bf732f951bd3e45073ef28e28ca19449c..0000000000000000000000000000000000000000 --- a/hw/usb/Makefile.objs +++ /dev/null @@ -1,65 +0,0 @@ -# usb subsystem core -common-obj-y += core.o combined-packet.o bus.o libhw.o -common-obj-$(CONFIG_USB) += desc.o desc-msos.o - -# usb host adapters -common-obj-$(CONFIG_USB_UHCI) += hcd-uhci.o -common-obj-$(CONFIG_USB_OHCI) += hcd-ohci.o -common-obj-$(CONFIG_USB_OHCI_PCI) += hcd-ohci-pci.o -common-obj-$(CONFIG_USB_EHCI) += hcd-ehci.o -common-obj-$(CONFIG_USB_EHCI_PCI) += hcd-ehci-pci.o -common-obj-$(CONFIG_USB_EHCI_SYSBUS) += hcd-ehci-sysbus.o -common-obj-$(CONFIG_USB_XHCI) += hcd-xhci.o -common-obj-$(CONFIG_USB_XHCI_NEC) += hcd-xhci-nec.o -common-obj-$(CONFIG_USB_MUSB) += hcd-musb.o - -common-obj-$(CONFIG_TUSB6010) += tusb6010.o -common-obj-$(CONFIG_IMX) += chipidea.o - -# emulated usb devices -common-obj-$(CONFIG_USB) += dev-hub.o -common-obj-$(CONFIG_USB) += dev-hid.o -common-obj-$(CONFIG_USB_TABLET_WACOM) += dev-wacom.o -common-obj-$(CONFIG_USB_STORAGE_BOT) += dev-storage.o -common-obj-$(CONFIG_USB_STORAGE_UAS) += dev-uas.o -common-obj-$(CONFIG_USB_AUDIO) += dev-audio.o -common-obj-$(CONFIG_USB_SERIAL) += dev-serial.o -common-obj-$(CONFIG_USB_NETWORK) += dev-network.o - -ifeq ($(CONFIG_USB_SMARTCARD),y) -common-obj-y += dev-smartcard-reader.o -common-obj-$(CONFIG_SMARTCARD) += smartcard.mo -smartcard.mo-objs := ccid-card-passthru.o ccid-card-emulated.o -smartcard.mo-cflags := $(SMARTCARD_CFLAGS) -smartcard.mo-libs := $(SMARTCARD_LIBS) -endif - -ifeq ($(CONFIG_POSIX),y) -common-obj-$(CONFIG_USB_STORAGE_MTP) += dev-mtp.o -endif - -# usb redirection -ifeq ($(CONFIG_USB),y) -common-obj-$(CONFIG_USB_REDIR) += redirect.o quirks.o -redirect.o-cflags = $(USB_REDIR_CFLAGS) -redirect.o-libs = $(USB_REDIR_LIBS) -endif - -# usb pass-through -ifeq ($(CONFIG_USB_LIBUSB)$(CONFIG_USB),yy) -common-obj-y += host-libusb.o -else -common-obj-y += host-stub.o -endif -common-obj-$(CONFIG_ALL) += host-stub.o - -host-libusb.o-cflags := $(LIBUSB_CFLAGS) -host-libusb.o-libs := $(LIBUSB_LIBS) - -ifeq ($(CONFIG_USB_LIBUSB),y) -common-obj-$(CONFIG_XEN) += xen-usb.o -xen-usb.o-cflags := $(LIBUSB_CFLAGS) -xen-usb.o-libs := $(LIBUSB_LIBS) -endif - -common-obj-$(CONFIG_IMX_USBPHY) += imx-usb-phy.o diff --git a/hw/usb/bus.c b/hw/usb/bus.c index fa07df98a297c4058bba7c1d09f657357f31e4a8..2b1104145157f83b8110b50fd71e99082332cac2 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -84,7 +84,7 @@ void usb_bus_new(USBBus *bus, size_t bus_size, USBBusOps *ops, DeviceState *host) { qbus_create_inplace(bus, bus_size, TYPE_USB_BUS, host, NULL); - qbus_set_bus_hotplug_handler(BUS(bus), &error_abort); + qbus_set_bus_hotplug_handler(BUS(bus)); bus->ops = ops; bus->busnr = next_usb_bus++; QTAILQ_INIT(&bus->free); @@ -296,14 +296,13 @@ typedef struct LegacyUSBFactory { const char *name; const char *usbdevice_name; - USBDevice *(*usbdevice_init)(USBBus *bus, const char *params); + USBDevice *(*usbdevice_init)(const char *params); } LegacyUSBFactory; static GSList *legacy_usb_factory; void usb_legacy_register(const char *typename, const char *usbdevice_name, - USBDevice *(*usbdevice_init)(USBBus *bus, - const char *params)) + USBDevice *(*usbdevice_init)(const char *params)) { if (usbdevice_name) { LegacyUSBFactory *f = g_malloc0(sizeof(*f)); @@ -314,38 +313,27 @@ void usb_legacy_register(const char *typename, const char *usbdevice_name, } } -USBDevice *usb_create(USBBus *bus, const char *name) +USBDevice *usb_new(const char *name) { - DeviceState *dev; - - dev = qdev_create(&bus->qbus, name); - return USB_DEVICE(dev); + return USB_DEVICE(qdev_new(name)); } -static USBDevice *usb_try_create_simple(USBBus *bus, const char *name, - Error **errp) +static USBDevice *usb_try_new(const char *name) { - Error *err = NULL; - USBDevice *dev; + return USB_DEVICE(qdev_try_new(name)); +} - dev = USB_DEVICE(qdev_try_create(&bus->qbus, name)); - if (!dev) { - error_setg(errp, "Failed to create USB device '%s'", name); - return NULL; - } - object_property_set_bool(OBJECT(dev), true, "realized", &err); - if (err) { - error_propagate_prepend(errp, err, - "Failed to initialize USB device '%s': ", - name); - return NULL; - } - return dev; +bool usb_realize_and_unref(USBDevice *dev, USBBus *bus, Error **errp) +{ + return qdev_realize_and_unref(&dev->qdev, &bus->qbus, errp); } USBDevice *usb_create_simple(USBBus *bus, const char *name) { - return usb_try_create_simple(bus, name, &error_abort); + USBDevice *dev = usb_new(name); + + usb_realize_and_unref(dev, bus, &error_abort); + return dev; } static void usb_fill_port(USBPort *port, void *opaque, int index, @@ -425,6 +413,7 @@ void usb_claim_port(USBDevice *dev, Error **errp) { USBBus *bus = usb_bus_from_device(dev); USBPort *port; + USBDevice *hub; assert(dev->port == NULL); @@ -442,7 +431,10 @@ void usb_claim_port(USBDevice *dev, Error **errp) } else { if (bus->nfree == 1 && strcmp(object_get_typename(OBJECT(dev)), "usb-hub") != 0) { /* Create a new hub and chain it on */ - usb_try_create_simple(bus, "usb-hub", NULL); + hub = usb_try_new("usb-hub"); + if (hub) { + usb_realize_and_unref(hub, bus, NULL); + } } if (bus->nfree == 0) { error_setg(errp, "tried to attach usb device %s to a bus " @@ -620,8 +612,8 @@ static char *usb_get_fw_dev_path(DeviceState *qdev) in++; } else { /* the device itself */ - pos += snprintf(fw_path + pos, fw_len - pos, "%s@%lx", - qdev_fw_name(qdev), nr); + snprintf(fw_path + pos, fw_len - pos, "%s@%lx", + qdev_fw_name(qdev), nr); break; } } @@ -700,20 +692,19 @@ USBDevice *usbdevice_create(const char *cmdline) } if (f->usbdevice_init) { - dev = f->usbdevice_init(bus, params); + dev = f->usbdevice_init(params); } else { if (*params) { error_report("usbdevice %s accepts no params", driver); return NULL; } - dev = usb_create(bus, f->name); + dev = usb_new(f->name); } if (!dev) { error_report("Failed to create USB device '%s'", f->name); return NULL; } - object_property_set_bool(OBJECT(dev), true, "realized", &err); - if (err) { + if (!usb_realize_and_unref(dev, bus, &err)) { error_reportf_err(err, "Failed to initialize USB device '%s': ", f->name); object_unparent(OBJECT(dev)); @@ -732,15 +723,13 @@ static bool usb_get_attached(Object *obj, Error **errp) static void usb_set_attached(Object *obj, bool value, Error **errp) { USBDevice *dev = USB_DEVICE(obj); - Error *err = NULL; if (dev->attached == value) { return; } if (value) { - usb_device_attach(dev, &err); - error_propagate(errp, err); + usb_device_attach(dev, errp); } else { usb_device_detach(dev); } diff --git a/hw/usb/ccid-card-emulated.c b/hw/usb/ccid-card-emulated.c index 7d6105ef34d56fb0acfc6ef30f806c4b8edac916..2d566f7db104422015cd61f2de7bc815417950a9 100644 --- a/hw/usb/ccid-card-emulated.c +++ b/hw/usb/ccid-card-emulated.c @@ -30,11 +30,13 @@ #include #include "qemu/thread.h" +#include "qemu/lockable.h" #include "qemu/main-loop.h" #include "qemu/module.h" #include "ccid.h" #include "hw/qdev-properties.h" #include "qapi/error.h" +#include "qom/object.h" #define DPRINTF(card, lvl, fmt, ...) \ do {\ @@ -45,8 +47,9 @@ do {\ #define TYPE_EMULATED_CCID "ccid-card-emulated" -#define EMULATED_CCID_CARD(obj) \ - OBJECT_CHECK(EmulatedState, (obj), TYPE_EMULATED_CCID) +typedef struct EmulatedState EmulatedState; +DECLARE_INSTANCE_CHECKER(EmulatedState, EMULATED_CCID_CARD, + TYPE_EMULATED_CCID) #define BACKEND_NSS_EMULATED_NAME "nss-emulated" #define BACKEND_CERTIFICATES_NAME "certificates" @@ -58,7 +61,6 @@ enum { #define DEFAULT_BACKEND BACKEND_NSS_EMULATED -typedef struct EmulatedState EmulatedState; enum { EMUL_READER_INSERT = 0, @@ -243,34 +245,34 @@ static void *handle_apdu_thread(void* arg) card->quit_apdu_thread = 0; /* debugging */ break; } - qemu_mutex_lock(&card->vreader_mutex); - while (!QSIMPLEQ_EMPTY(&card->guest_apdu_list)) { - event = QSIMPLEQ_FIRST(&card->guest_apdu_list); - assert((unsigned long)event > 1000); - QSIMPLEQ_REMOVE_HEAD(&card->guest_apdu_list, entry); - if (event->p.data.type != EMUL_GUEST_APDU) { - DPRINTF(card, 1, "unexpected message in handle_apdu_thread\n"); - g_free(event); - continue; - } - if (card->reader == NULL) { - DPRINTF(card, 1, "reader is NULL\n"); + WITH_QEMU_LOCK_GUARD(&card->vreader_mutex) { + while (!QSIMPLEQ_EMPTY(&card->guest_apdu_list)) { + event = QSIMPLEQ_FIRST(&card->guest_apdu_list); + assert((unsigned long)event > 1000); + QSIMPLEQ_REMOVE_HEAD(&card->guest_apdu_list, entry); + if (event->p.data.type != EMUL_GUEST_APDU) { + DPRINTF(card, 1, "unexpected message in handle_apdu_thread\n"); + g_free(event); + continue; + } + if (card->reader == NULL) { + DPRINTF(card, 1, "reader is NULL\n"); + g_free(event); + continue; + } + recv_len = sizeof(recv_data); + reader_status = vreader_xfr_bytes(card->reader, + event->p.data.data, event->p.data.len, + recv_data, &recv_len); + DPRINTF(card, 2, "got back apdu of length %d\n", recv_len); + if (reader_status == VREADER_OK) { + emulated_push_response_apdu(card, recv_data, recv_len); + } else { + emulated_push_error(card, reader_status); + } g_free(event); - continue; - } - recv_len = sizeof(recv_data); - reader_status = vreader_xfr_bytes(card->reader, - event->p.data.data, event->p.data.len, - recv_data, &recv_len); - DPRINTF(card, 2, "got back apdu of length %d\n", recv_len); - if (reader_status == VREADER_OK) { - emulated_push_response_apdu(card, recv_data, recv_len); - } else { - emulated_push_error(card, reader_status); } - g_free(event); } - qemu_mutex_unlock(&card->vreader_mutex); } return NULL; } @@ -350,7 +352,6 @@ static void *event_thread(void *arg) case VEVENT_LAST: /* quit */ vevent_delete(event); return NULL; - break; default: break; } @@ -365,7 +366,7 @@ static void card_event_handler(EventNotifier *notifier) EmulEvent *event, *next; event_notifier_test_and_clear(&card->notifier); - qemu_mutex_lock(&card->event_list_mutex); + QEMU_LOCK_GUARD(&card->event_list_mutex); QSIMPLEQ_FOREACH_SAFE(event, &card->event_list, entry, next) { DPRINTF(card, 2, "event %s\n", emul_event_to_string(event->p.gen.type)); switch (event->p.gen.type) { @@ -398,7 +399,6 @@ static void card_event_handler(EventNotifier *notifier) g_free(event); } QSIMPLEQ_INIT(&card->event_list); - qemu_mutex_unlock(&card->event_list_mutex); } static int init_event_notifier(EmulatedState *card, Error **errp) diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c index bb325dbc4a98110acc8feac3f179df6283002d1e..e8e9d37e8833656e5e81207a9317e59228d62dce 100644 --- a/hw/usb/ccid-card-passthru.c +++ b/hw/usb/ccid-card-passthru.c @@ -20,6 +20,7 @@ #include "qemu/sockets.h" #include "ccid.h" #include "qapi/error.h" +#include "qom/object.h" #define DPRINTF(card, lvl, fmt, ...) \ do { \ @@ -64,8 +65,8 @@ struct PassthruState { }; #define TYPE_CCID_PASSTHRU "ccid-card-passthru" -#define PASSTHRU_CCID_CARD(obj) \ - OBJECT_CHECK(PassthruState, (obj), TYPE_CCID_PASSTHRU) +DECLARE_INSTANCE_CHECKER(PassthruState, PASSTHRU_CCID_CARD, + TYPE_CCID_PASSTHRU) /* * VSCard protocol over chardev diff --git a/hw/usb/ccid.h b/hw/usb/ccid.h index 531bf28fb0795a5150c217b53e1cd0e65fbbc89f..6b82a55bd4cca63b6f9ef27cfd13a8fc8cefebc5 100644 --- a/hw/usb/ccid.h +++ b/hw/usb/ccid.h @@ -11,23 +11,18 @@ #define CCID_H #include "hw/qdev-core.h" +#include "qom/object.h" -typedef struct CCIDCardState CCIDCardState; typedef struct CCIDCardInfo CCIDCardInfo; #define TYPE_CCID_CARD "ccid-card" -#define CCID_CARD(obj) \ - OBJECT_CHECK(CCIDCardState, (obj), TYPE_CCID_CARD) -#define CCID_CARD_CLASS(klass) \ - OBJECT_CLASS_CHECK(CCIDCardClass, (klass), TYPE_CCID_CARD) -#define CCID_CARD_GET_CLASS(obj) \ - OBJECT_GET_CLASS(CCIDCardClass, (obj), TYPE_CCID_CARD) +OBJECT_DECLARE_TYPE(CCIDCardState, CCIDCardClass, CCID_CARD) /* * callbacks to be used by the CCID device (hw/usb-ccid.c) to call * into the smartcard device (hw/ccid-card-*.c) */ -typedef struct CCIDCardClass { +struct CCIDCardClass { /*< private >*/ DeviceClass parent_class; /*< public >*/ @@ -37,7 +32,7 @@ typedef struct CCIDCardClass { uint32_t len); void (*realize)(CCIDCardState *card, Error **errp); void (*unrealize)(CCIDCardState *card); -} CCIDCardClass; +}; /* * state of the CCID Card device (i.e. hw/ccid-card-*.c) diff --git a/hw/usb/core.c b/hw/usb/core.c index 5abd128b6bc5f5440e18b143fe410df7fc02a216..5234dcc73fea6012f7143f3076405dc324e80735 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -129,6 +129,7 @@ void usb_wakeup(USBEndpoint *ep, unsigned int stream) static void do_token_setup(USBDevice *s, USBPacket *p) { int request, value, index; + unsigned int setup_len; if (p->iov.size != 8) { p->status = USB_RET_STALL; @@ -138,14 +139,15 @@ static void do_token_setup(USBDevice *s, USBPacket *p) usb_packet_copy(p, s->setup_buf, p->iov.size); s->setup_index = 0; p->actual_length = 0; - s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6]; - if (s->setup_len > sizeof(s->data_buf)) { + setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6]; + if (setup_len > sizeof(s->data_buf)) { fprintf(stderr, "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n", - s->setup_len, sizeof(s->data_buf)); + setup_len, sizeof(s->data_buf)); p->status = USB_RET_STALL; return; } + s->setup_len = setup_len; request = (s->setup_buf[0] << 8) | s->setup_buf[1]; value = (s->setup_buf[3] << 8) | s->setup_buf[2]; @@ -259,26 +261,28 @@ static void do_token_out(USBDevice *s, USBPacket *p) static void do_parameter(USBDevice *s, USBPacket *p) { int i, request, value, index; + unsigned int setup_len; for (i = 0; i < 8; i++) { s->setup_buf[i] = p->parameter >> (i*8); } s->setup_state = SETUP_STATE_PARAM; - s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6]; s->setup_index = 0; request = (s->setup_buf[0] << 8) | s->setup_buf[1]; value = (s->setup_buf[3] << 8) | s->setup_buf[2]; index = (s->setup_buf[5] << 8) | s->setup_buf[4]; - if (s->setup_len > sizeof(s->data_buf)) { + setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6]; + if (setup_len > sizeof(s->data_buf)) { fprintf(stderr, "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n", - s->setup_len, sizeof(s->data_buf)); + setup_len, sizeof(s->data_buf)); p->status = USB_RET_STALL; return; } + s->setup_len = setup_len; if (p->pid == USB_TOKEN_OUT) { usb_packet_copy(p, s->data_buf, s->setup_len); diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index 1371c44f489f3da80004a63113edb347954f3620..e1486f81e06b8894c13a59ca427a1e6e9e8d26c0 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -36,6 +36,7 @@ #include "migration/vmstate.h" #include "desc.h" #include "audio/audio.h" +#include "qom/object.h" static void usb_audio_reinit(USBDevice *dev, unsigned channels); @@ -633,7 +634,7 @@ static uint8_t *streambuf_get(struct streambuf *buf, size_t *len) return data; } -typedef struct USBAudioState { +struct USBAudioState { /* qemu interfaces */ USBDevice dev; QEMUSoundCard card; @@ -652,10 +653,10 @@ typedef struct USBAudioState { uint32_t debug; uint32_t buffer_user, buffer; bool multi; -} USBAudioState; +}; #define TYPE_USB_AUDIO "usb-audio" -#define USB_AUDIO(obj) OBJECT_CHECK(USBAudioState, (obj), TYPE_USB_AUDIO) +OBJECT_DECLARE_SIMPLE_TYPE(USBAudioState, USB_AUDIO) static void output_callback(void *opaque, int avail) { diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c index 89f63b698b8ac6e21788c5f604d932ac2a71ec3a..fc39bab79f94b0a0d06c23fc650d1fc21bf4647e 100644 --- a/hw/usb/dev-hid.c +++ b/hw/usb/dev-hid.c @@ -32,32 +32,21 @@ #include "qemu/module.h" #include "qemu/timer.h" #include "hw/input/hid.h" +#include "hw/usb/hid.h" #include "hw/qdev-properties.h" +#include "qom/object.h" -/* HID interface requests */ -#define GET_REPORT 0xa101 -#define GET_IDLE 0xa102 -#define GET_PROTOCOL 0xa103 -#define SET_REPORT 0x2109 -#define SET_IDLE 0x210a -#define SET_PROTOCOL 0x210b - -/* HID descriptor types */ -#define USB_DT_HID 0x21 -#define USB_DT_REPORT 0x22 -#define USB_DT_PHY 0x23 - -typedef struct USBHIDState { +struct USBHIDState { USBDevice dev; USBEndpoint *intr; HIDState hid; uint32_t usb_version; char *display; uint32_t head; -} USBHIDState; +}; #define TYPE_USB_HID "usb-hid" -#define USB_HID(obj) OBJECT_CHECK(USBHIDState, (obj), TYPE_USB_HID) +OBJECT_DECLARE_SIMPLE_TYPE(USBHIDState, USB_HID) enum { STR_MANUFACTURER = 1, @@ -618,38 +607,38 @@ static void usb_hid_handle_control(USBDevice *dev, USBPacket *p, goto fail; } break; - case GET_REPORT: + case HID_GET_REPORT: if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) { p->actual_length = hid_pointer_poll(hs, data, length); } else if (hs->kind == HID_KEYBOARD) { p->actual_length = hid_keyboard_poll(hs, data, length); } break; - case SET_REPORT: + case HID_SET_REPORT: if (hs->kind == HID_KEYBOARD) { p->actual_length = hid_keyboard_write(hs, data, length); } else { goto fail; } break; - case GET_PROTOCOL: + case HID_GET_PROTOCOL: if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) { goto fail; } data[0] = hs->protocol; p->actual_length = 1; break; - case SET_PROTOCOL: + case HID_SET_PROTOCOL: if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) { goto fail; } hs->protocol = value; break; - case GET_IDLE: + case HID_GET_IDLE: data[0] = hs->idle; p->actual_length = 1; break; - case SET_IDLE: + case HID_SET_IDLE: hs->idle = (uint8_t) (value >> 8); hid_set_next_idle(hs); if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) { diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c index 5f19dd9fb5ef9d7c36ee32e49762e39e325fe19a..40c1f906942555f441386ebc4f453e404831c6bc 100644 --- a/hw/usb/dev-hub.c +++ b/hw/usb/dev-hub.c @@ -32,6 +32,7 @@ #include "desc.h" #include "qemu/error-report.h" #include "qemu/module.h" +#include "qom/object.h" #define MAX_PORTS 8 @@ -41,17 +42,17 @@ typedef struct USBHubPort { uint16_t wPortChange; } USBHubPort; -typedef struct USBHubState { +struct USBHubState { USBDevice dev; USBEndpoint *intr; uint32_t num_ports; bool port_power; QEMUTimer *port_timer; USBHubPort ports[MAX_PORTS]; -} USBHubState; +}; #define TYPE_USB_HUB "usb-hub" -#define USB_HUB(obj) OBJECT_CHECK(USBHubState, (obj), TYPE_USB_HUB) +OBJECT_DECLARE_SIMPLE_TYPE(USBHubState, USB_HUB) #define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE) #define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE) diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c index 20717f026bc03922944317f73a6802805511e7e6..bbb827434482d3b191df857d6fa0f5853cc5e1b6 100644 --- a/hw/usb/dev-mtp.c +++ b/hw/usb/dev-mtp.c @@ -28,6 +28,7 @@ #include "migration/vmstate.h" #include "desc.h" #include "qemu/units.h" +#include "qom/object.h" /* ----------------------------------------------------------------------- */ @@ -237,7 +238,7 @@ typedef struct { } QEMU_PACKED ObjectInfo; #define TYPE_USB_MTP "usb-mtp" -#define USB_MTP(obj) OBJECT_CHECK(MTPState, (obj), TYPE_USB_MTP) +OBJECT_DECLARE_SIMPLE_TYPE(MTPState, USB_MTP) #define QEMU_STORAGE_ID 0x00010001 @@ -631,9 +632,9 @@ static void usb_mtp_object_readdir(MTPState *s, MTPObject *o) int64_t id = qemu_file_monitor_add_watch(s->file_monitor, o->path, NULL, file_monitor_event, s, &err); if (id == -1) { - error_report("usb-mtp: failed to add watch for %s: %s", o->path, - error_get_pretty(err)); - error_free(err); + error_reportf_err(err, + "usb-mtp: failed to add watch for %s: ", + o->path); } else { trace_usb_mtp_file_monitor_event(s->dev.addr, o->path, "Watch Added"); @@ -1276,9 +1277,8 @@ static void usb_mtp_command(MTPState *s, MTPControl *c) s->file_monitor = qemu_file_monitor_new(&err); if (err) { - error_report("usb-mtp: file monitoring init failed: %s", - error_get_pretty(err)); - error_free(err); + error_reportf_err(err, + "usb-mtp: file monitoring init failed: "); } else { QTAILQ_INIT(&s->events); } diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index c69756709b189ff91098155d9bc747de6d70ec26..6c49c16015e03dc44ec631688cb0b786023f5e22 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -37,6 +37,7 @@ #include "qemu/iov.h" #include "qemu/module.h" #include "qemu/cutils.h" +#include "qom/object.h" /*#define TRAFFIC_DEBUG*/ /* Thanks to NetChip Technologies for donating this product ID. @@ -629,7 +630,7 @@ struct rndis_response { uint8_t buf[]; }; -typedef struct USBNetState { +struct USBNetState { USBDevice dev; enum rndis_state rndis_state; @@ -651,10 +652,10 @@ typedef struct USBNetState { NICState *nic; NICConf conf; QTAILQ_HEAD(, rndis_response) rndis_resp; -} USBNetState; +}; #define TYPE_USB_NET "usb-net" -#define USB_NET(obj) OBJECT_CHECK(USBNetState, (obj), TYPE_USB_NET) +OBJECT_DECLARE_SIMPLE_TYPE(USBNetState, USB_NET) static int is_rndis(USBNetState *s) { diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index d2c03681b7f0187d9f7ce4810b456806e3303bf6..19e1933f0496dd0ac949ddeeef680185944d845e 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -19,85 +19,78 @@ #include "desc.h" #include "chardev/char-serial.h" #include "chardev/char-fe.h" +#include "qom/object.h" +#include "trace.h" -//#define DEBUG_Serial - -#ifdef DEBUG_Serial -#define DPRINTF(fmt, ...) \ -do { printf("usb-serial: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) do {} while(0) -#endif #define RECV_BUF (512 - (2 * 8)) /* Commands */ -#define FTDI_RESET 0 -#define FTDI_SET_MDM_CTRL 1 -#define FTDI_SET_FLOW_CTRL 2 -#define FTDI_SET_BAUD 3 -#define FTDI_SET_DATA 4 -#define FTDI_GET_MDM_ST 5 -#define FTDI_SET_EVENT_CHR 6 -#define FTDI_SET_ERROR_CHR 7 -#define FTDI_SET_LATENCY 9 -#define FTDI_GET_LATENCY 10 - -#define DeviceOutVendor ((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8) -#define DeviceInVendor ((USB_DIR_IN |USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8) +#define FTDI_RESET 0 +#define FTDI_SET_MDM_CTRL 1 +#define FTDI_SET_FLOW_CTRL 2 +#define FTDI_SET_BAUD 3 +#define FTDI_SET_DATA 4 +#define FTDI_GET_MDM_ST 5 +#define FTDI_SET_EVENT_CHR 6 +#define FTDI_SET_ERROR_CHR 7 +#define FTDI_SET_LATENCY 9 +#define FTDI_GET_LATENCY 10 /* RESET */ -#define FTDI_RESET_SIO 0 -#define FTDI_RESET_RX 1 -#define FTDI_RESET_TX 2 +#define FTDI_RESET_SIO 0 +#define FTDI_RESET_RX 1 +#define FTDI_RESET_TX 2 /* SET_MDM_CTRL */ -#define FTDI_DTR 1 -#define FTDI_SET_DTR (FTDI_DTR << 8) -#define FTDI_RTS 2 -#define FTDI_SET_RTS (FTDI_RTS << 8) +#define FTDI_DTR 1 +#define FTDI_SET_DTR (FTDI_DTR << 8) +#define FTDI_RTS 2 +#define FTDI_SET_RTS (FTDI_RTS << 8) /* SET_FLOW_CTRL */ -#define FTDI_RTS_CTS_HS 1 -#define FTDI_DTR_DSR_HS 2 -#define FTDI_XON_XOFF_HS 4 +#define FTDI_NO_HS 0 +#define FTDI_RTS_CTS_HS 1 +#define FTDI_DTR_DSR_HS 2 +#define FTDI_XON_XOFF_HS 4 /* SET_DATA */ -#define FTDI_PARITY (0x7 << 8) -#define FTDI_ODD (0x1 << 8) -#define FTDI_EVEN (0x2 << 8) -#define FTDI_MARK (0x3 << 8) -#define FTDI_SPACE (0x4 << 8) +#define FTDI_PARITY (0x7 << 8) +#define FTDI_ODD (0x1 << 8) +#define FTDI_EVEN (0x2 << 8) +#define FTDI_MARK (0x3 << 8) +#define FTDI_SPACE (0x4 << 8) -#define FTDI_STOP (0x3 << 11) -#define FTDI_STOP1 (0x0 << 11) -#define FTDI_STOP15 (0x1 << 11) -#define FTDI_STOP2 (0x2 << 11) +#define FTDI_STOP (0x3 << 11) +#define FTDI_STOP1 (0x0 << 11) +#define FTDI_STOP15 (0x1 << 11) +#define FTDI_STOP2 (0x2 << 11) /* GET_MDM_ST */ /* TODO: should be sent every 40ms */ -#define FTDI_CTS (1<<4) // CTS line status -#define FTDI_DSR (1<<5) // DSR line status -#define FTDI_RI (1<<6) // RI line status -#define FTDI_RLSD (1<<7) // Receive Line Signal Detect +#define FTDI_CTS (1 << 4) /* CTS line status */ +#define FTDI_DSR (1 << 5) /* DSR line status */ +#define FTDI_RI (1 << 6) /* RI line status */ +#define FTDI_RLSD (1 << 7) /* Receive Line Signal Detect */ /* Status */ -#define FTDI_DR (1<<0) // Data Ready -#define FTDI_OE (1<<1) // Overrun Err -#define FTDI_PE (1<<2) // Parity Err -#define FTDI_FE (1<<3) // Framing Err -#define FTDI_BI (1<<4) // Break Interrupt -#define FTDI_THRE (1<<5) // Transmitter Holding Register -#define FTDI_TEMT (1<<6) // Transmitter Empty -#define FTDI_FIFO (1<<7) // Error in FIFO +#define FTDI_DR (1 << 0) /* Data Ready */ +#define FTDI_OE (1 << 1) /* Overrun Err */ +#define FTDI_PE (1 << 2) /* Parity Err */ +#define FTDI_FE (1 << 3) /* Framing Err */ +#define FTDI_BI (1 << 4) /* Break Interrupt */ +#define FTDI_THRE (1 << 5) /* Transmitter Holding Register */ +#define FTDI_TEMT (1 << 6) /* Transmitter Empty */ +#define FTDI_FIFO (1 << 7) /* Error in FIFO */ -typedef struct { +struct USBSerialState { USBDevice dev; + USBEndpoint *intr; uint8_t recv_buf[RECV_BUF]; uint16_t recv_ptr; @@ -105,13 +98,17 @@ typedef struct { uint8_t event_chr; uint8_t error_chr; uint8_t event_trigger; + bool always_plugged; + uint8_t flow_control; + uint8_t xon; + uint8_t xoff; QEMUSerialSetParams params; int latency; /* ms */ CharBackend cs; -} USBSerialState; +}; #define TYPE_USB_SERIAL "usb-serial-dev" -#define USB_SERIAL_DEV(obj) OBJECT_CHECK(USBSerialState, (obj), TYPE_USB_SERIAL) +OBJECT_DECLARE_SIMPLE_TYPE(USBSerialState, USB_SERIAL) enum { STR_MANUFACTURER = 1, @@ -188,21 +185,44 @@ static const USBDesc desc_braille = { .str = desc_strings, }; +static void usb_serial_set_flow_control(USBSerialState *s, + uint8_t flow_control) +{ + USBDevice *dev = USB_DEVICE(s); + USBBus *bus = usb_bus_from_device(dev); + + /* TODO: ioctl */ + s->flow_control = flow_control; + trace_usb_serial_set_flow_control(bus->busnr, dev->addr, flow_control); +} + +static void usb_serial_set_xonxoff(USBSerialState *s, int xonxoff) +{ + USBDevice *dev = USB_DEVICE(s); + USBBus *bus = usb_bus_from_device(dev); + + s->xon = xonxoff & 0xff; + s->xoff = (xonxoff >> 8) & 0xff; + + trace_usb_serial_set_xonxoff(bus->busnr, dev->addr, s->xon, s->xoff); +} + static void usb_serial_reset(USBSerialState *s) { - /* TODO: Set flow control to none */ s->event_chr = 0x0d; s->event_trigger = 0; s->recv_ptr = 0; s->recv_used = 0; /* TODO: purge in char driver */ + usb_serial_set_flow_control(s, FTDI_NO_HS); } static void usb_serial_handle_reset(USBDevice *dev) { - USBSerialState *s = (USBSerialState *)dev; + USBSerialState *s = USB_SERIAL(dev); + USBBus *bus = usb_bus_from_device(dev); - DPRINTF("Reset\n"); + trace_usb_serial_reset(bus->busnr, dev->addr); usb_serial_reset(s); /* TODO: Reset char device, send BREAK? */ @@ -215,29 +235,36 @@ static uint8_t usb_get_modem_lines(USBSerialState *s) if (qemu_chr_fe_ioctl(&s->cs, CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP) { - return FTDI_CTS|FTDI_DSR|FTDI_RLSD; + return FTDI_CTS | FTDI_DSR | FTDI_RLSD; } ret = 0; - if (flags & CHR_TIOCM_CTS) + if (flags & CHR_TIOCM_CTS) { ret |= FTDI_CTS; - if (flags & CHR_TIOCM_DSR) + } + if (flags & CHR_TIOCM_DSR) { ret |= FTDI_DSR; - if (flags & CHR_TIOCM_RI) + } + if (flags & CHR_TIOCM_RI) { ret |= FTDI_RI; - if (flags & CHR_TIOCM_CAR) + } + if (flags & CHR_TIOCM_CAR) { ret |= FTDI_RLSD; + } return ret; } static void usb_serial_handle_control(USBDevice *dev, USBPacket *p, - int request, int value, int index, int length, uint8_t *data) + int request, int value, int index, + int length, uint8_t *data) { - USBSerialState *s = (USBSerialState *)dev; + USBSerialState *s = USB_SERIAL(dev); + USBBus *bus = usb_bus_from_device(dev); int ret; - DPRINTF("got control %x, value %x\n",request, value); + trace_usb_serial_handle_control(bus->busnr, dev->addr, request, value); + ret = usb_desc_handle_control(dev, p, request, value, index, length, data); if (ret >= 0) { return; @@ -247,8 +274,8 @@ static void usb_serial_handle_control(USBDevice *dev, USBPacket *p, case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: break; - /* Class specific requests. */ - case DeviceOutVendor | FTDI_RESET: + /* Class specific requests. */ + case VendorDeviceOutRequest | FTDI_RESET: switch (value) { case FTDI_RESET_SIO: usb_serial_reset(s); @@ -263,96 +290,131 @@ static void usb_serial_handle_control(USBDevice *dev, USBPacket *p, break; } break; - case DeviceOutVendor | FTDI_SET_MDM_CTRL: + case VendorDeviceOutRequest | FTDI_SET_MDM_CTRL: { static int flags; qemu_chr_fe_ioctl(&s->cs, CHR_IOCTL_SERIAL_GET_TIOCM, &flags); if (value & FTDI_SET_RTS) { - if (value & FTDI_RTS) + if (value & FTDI_RTS) { flags |= CHR_TIOCM_RTS; - else + } else { flags &= ~CHR_TIOCM_RTS; + } } if (value & FTDI_SET_DTR) { - if (value & FTDI_DTR) + if (value & FTDI_DTR) { flags |= CHR_TIOCM_DTR; - else + } else { flags &= ~CHR_TIOCM_DTR; + } } qemu_chr_fe_ioctl(&s->cs, CHR_IOCTL_SERIAL_SET_TIOCM, &flags); break; } - case DeviceOutVendor | FTDI_SET_FLOW_CTRL: - /* TODO: ioctl */ + case VendorDeviceOutRequest | FTDI_SET_FLOW_CTRL: { + uint8_t flow_control = index >> 8; + + usb_serial_set_flow_control(s, flow_control); + if (flow_control & FTDI_XON_XOFF_HS) { + usb_serial_set_xonxoff(s, value); + } break; - case DeviceOutVendor | FTDI_SET_BAUD: { + } + case VendorDeviceOutRequest | FTDI_SET_BAUD: { static const int subdivisors8[8] = { 0, 4, 2, 1, 3, 5, 6, 7 }; int subdivisor8 = subdivisors8[((value & 0xc000) >> 14) | ((index & 1) << 2)]; int divisor = value & 0x3fff; /* chip special cases */ - if (divisor == 1 && subdivisor8 == 0) + if (divisor == 1 && subdivisor8 == 0) { subdivisor8 = 4; - if (divisor == 0 && subdivisor8 == 0) + } + if (divisor == 0 && subdivisor8 == 0) { divisor = 1; + } s->params.speed = (48000000 / 2) / (8 * divisor + subdivisor8); + trace_usb_serial_set_baud(bus->busnr, dev->addr, s->params.speed); qemu_chr_fe_ioctl(&s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params); break; } - case DeviceOutVendor | FTDI_SET_DATA: + case VendorDeviceOutRequest | FTDI_SET_DATA: + switch (value & 0xff) { + case 7: + s->params.data_bits = 7; + break; + case 8: + s->params.data_bits = 8; + break; + default: + /* + * According to a comment in Linux's ftdi_sio.c original FTDI + * chips fall back to 8 data bits for unsupported data_bits + */ + trace_usb_serial_unsupported_data_bits(bus->busnr, dev->addr, + value & 0xff); + s->params.data_bits = 8; + } + switch (value & FTDI_PARITY) { - case 0: - s->params.parity = 'N'; - break; - case FTDI_ODD: - s->params.parity = 'O'; - break; - case FTDI_EVEN: - s->params.parity = 'E'; - break; - default: - DPRINTF("unsupported parity %d\n", value & FTDI_PARITY); - goto fail; + case 0: + s->params.parity = 'N'; + break; + case FTDI_ODD: + s->params.parity = 'O'; + break; + case FTDI_EVEN: + s->params.parity = 'E'; + break; + default: + trace_usb_serial_unsupported_parity(bus->busnr, dev->addr, + value & FTDI_PARITY); + goto fail; } + switch (value & FTDI_STOP) { - case FTDI_STOP1: - s->params.stop_bits = 1; - break; - case FTDI_STOP2: - s->params.stop_bits = 2; - break; - default: - DPRINTF("unsupported stop bits %d\n", value & FTDI_STOP); - goto fail; + case FTDI_STOP1: + s->params.stop_bits = 1; + break; + case FTDI_STOP2: + s->params.stop_bits = 2; + break; + default: + trace_usb_serial_unsupported_stopbits(bus->busnr, dev->addr, + value & FTDI_STOP); + goto fail; } + + trace_usb_serial_set_data(bus->busnr, dev->addr, s->params.parity, + s->params.data_bits, s->params.stop_bits); qemu_chr_fe_ioctl(&s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params); /* TODO: TX ON/OFF */ break; - case DeviceInVendor | FTDI_GET_MDM_ST: + case VendorDeviceRequest | FTDI_GET_MDM_ST: data[0] = usb_get_modem_lines(s) | 1; data[1] = FTDI_THRE | FTDI_TEMT; p->actual_length = 2; break; - case DeviceOutVendor | FTDI_SET_EVENT_CHR: + case VendorDeviceOutRequest | FTDI_SET_EVENT_CHR: /* TODO: handle it */ s->event_chr = value; break; - case DeviceOutVendor | FTDI_SET_ERROR_CHR: + case VendorDeviceOutRequest | FTDI_SET_ERROR_CHR: /* TODO: handle it */ s->error_chr = value; break; - case DeviceOutVendor | FTDI_SET_LATENCY: + case VendorDeviceOutRequest | FTDI_SET_LATENCY: s->latency = value; break; - case DeviceInVendor | FTDI_GET_LATENCY: + case VendorDeviceRequest | FTDI_GET_LATENCY: data[0] = s->latency; p->actual_length = 1; break; default: fail: - DPRINTF("got unsupported/bogus control %x, value %x\n", request, value); + trace_usb_serial_unsupported_control(bus->busnr, dev->addr, request, + value); p->status = USB_RET_STALL; break; } @@ -415,32 +477,37 @@ static void usb_serial_token_in(USBSerialState *s, USBPacket *p) static void usb_serial_handle_data(USBDevice *dev, USBPacket *p) { - USBSerialState *s = (USBSerialState *)dev; + USBSerialState *s = USB_SERIAL(dev); + USBBus *bus = usb_bus_from_device(dev); uint8_t devep = p->ep->nr; struct iovec *iov; int i; switch (p->pid) { case USB_TOKEN_OUT: - if (devep != 2) + if (devep != 2) { goto fail; + } for (i = 0; i < p->iov.niov; i++) { iov = p->iov.iov + i; - /* XXX this blocks entire thread. Rewrite to use - * qemu_chr_fe_write and background I/O callbacks */ + /* + * XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks + */ qemu_chr_fe_write_all(&s->cs, iov->iov_base, iov->iov_len); } p->actual_length = p->iov.size; break; case USB_TOKEN_IN: - if (devep != 1) + if (devep != 1) { goto fail; + } usb_serial_token_in(s, p); break; default: - DPRINTF("Bad token\n"); + trace_usb_serial_bad_token(bus->busnr, dev->addr); fail: p->status = USB_RET_STALL; break; @@ -463,21 +530,24 @@ static void usb_serial_read(void *opaque, const uint8_t *buf, int size) int first_size, start; /* room in the buffer? */ - if (size > (RECV_BUF - s->recv_used)) + if (size > (RECV_BUF - s->recv_used)) { size = RECV_BUF - s->recv_used; + } start = s->recv_ptr + s->recv_used; if (start < RECV_BUF) { /* copy data to end of buffer */ first_size = RECV_BUF - start; - if (first_size > size) + if (first_size > size) { first_size = size; + } memcpy(s->recv_buf + start, buf, first_size); /* wrap around to front if needed */ - if (size > first_size) + if (size > first_size) { memcpy(s->recv_buf, buf + first_size, size - first_size); + } } else { start -= RECV_BUF; memcpy(s->recv_buf + start, buf, size); @@ -492,29 +562,29 @@ static void usb_serial_event(void *opaque, QEMUChrEvent event) USBSerialState *s = opaque; switch (event) { - case CHR_EVENT_BREAK: - s->event_trigger |= FTDI_BI; - break; - case CHR_EVENT_OPENED: - if (!s->dev.attached) { - usb_device_attach(&s->dev, &error_abort); - } - break; - case CHR_EVENT_CLOSED: - if (s->dev.attached) { - usb_device_detach(&s->dev); - } - break; - case CHR_EVENT_MUX_IN: - case CHR_EVENT_MUX_OUT: - /* Ignore */ - break; + case CHR_EVENT_BREAK: + s->event_trigger |= FTDI_BI; + break; + case CHR_EVENT_OPENED: + if (!s->always_plugged && !s->dev.attached) { + usb_device_attach(&s->dev, &error_abort); + } + break; + case CHR_EVENT_CLOSED: + if (!s->always_plugged && s->dev.attached) { + usb_device_detach(&s->dev); + } + break; + case CHR_EVENT_MUX_IN: + case CHR_EVENT_MUX_OUT: + /* Ignore */ + break; } } static void usb_serial_realize(USBDevice *dev, Error **errp) { - USBSerialState *s = USB_SERIAL_DEV(dev); + USBSerialState *s = USB_SERIAL(dev); Error *local_err = NULL; usb_desc_create_serial(dev); @@ -536,22 +606,24 @@ static void usb_serial_realize(USBDevice *dev, Error **errp) usb_serial_event, NULL, s, NULL, true); usb_serial_handle_reset(dev); - if (qemu_chr_fe_backend_open(&s->cs) && !dev->attached) { + if ((s->always_plugged || qemu_chr_fe_backend_open(&s->cs)) && + !dev->attached) { usb_device_attach(dev, &error_abort); } s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1); } -static USBDevice *usb_braille_init(USBBus *bus, const char *unused) +static USBDevice *usb_braille_init(const char *unused) { USBDevice *dev; Chardev *cdrv; cdrv = qemu_chr_new("braille", "braille", NULL); - if (!cdrv) + if (!cdrv) { return NULL; + } - dev = usb_create(bus, "usb-braille"); + dev = usb_new("usb-braille"); qdev_prop_set_chr(&dev->qdev, "chardev", cdrv); return dev; } @@ -563,6 +635,7 @@ static const VMStateDescription vmstate_usb_serial = { static Property serial_properties[] = { DEFINE_PROP_CHR("chardev", USBSerialState, cs), + DEFINE_PROP_BOOL("always-plugged", USBSerialState, always_plugged, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index ada18c1983e8fd25efd61d15b4ba28f6fa54769d..946df9734a918f97a0c2915e98525259f4c4cbf2 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -46,6 +46,7 @@ #include "desc.h" #include "ccid.h" +#include "qom/object.h" #define DPRINTF(s, lvl, fmt, ...) \ do { \ @@ -59,8 +60,8 @@ do { \ #define D_MORE_INFO 3 #define D_VERBOSE 4 -#define CCID_DEV_NAME "usb-ccid" -#define USB_CCID_DEV(obj) OBJECT_CHECK(USBCCIDState, (obj), CCID_DEV_NAME) +#define TYPE_USB_CCID_DEV "usb-ccid" +OBJECT_DECLARE_SIMPLE_TYPE(USBCCIDState, USB_CCID_DEV) /* * The two options for variable sized buffers: * make them constant size, for large enough constant, @@ -274,14 +275,15 @@ typedef struct BulkIn { uint32_t pos; } BulkIn; -typedef struct CCIDBus { +struct CCIDBus { BusState qbus; -} CCIDBus; +}; +typedef struct CCIDBus CCIDBus; /* * powered - defaults to true, changed by PowerOn/PowerOff messages */ -typedef struct USBCCIDState { +struct USBCCIDState { USBDevice dev; USBEndpoint *intr; USBEndpoint *bulk; @@ -309,7 +311,7 @@ typedef struct USBCCIDState { uint8_t powered; uint8_t notify_slot_change; uint8_t debug; -} USBCCIDState; +}; /* * CCID Spec chapter 4: CCID uses a standard device descriptor per Chapter 9, @@ -1173,7 +1175,7 @@ static Property ccid_props[] = { }; #define TYPE_CCID_BUS "ccid-bus" -#define CCID_BUS(obj) OBJECT_CHECK(CCIDBus, (obj), TYPE_CCID_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(CCIDBus, CCID_BUS) static const TypeInfo ccid_bus_info = { .name = TYPE_CCID_BUS, @@ -1320,7 +1322,7 @@ static void ccid_realize(USBDevice *dev, Error **errp) usb_desc_init(dev); qbus_create_inplace(&s->bus, sizeof(s->bus), TYPE_CCID_BUS, DEVICE(dev), NULL); - qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(dev), &error_abort); + qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(dev)); s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP); s->bulk = usb_ep_get(dev, USB_TOKEN_IN, CCID_BULK_IN_EP); s->card = NULL; @@ -1457,7 +1459,7 @@ static void ccid_class_initfn(ObjectClass *klass, void *data) } static const TypeInfo ccid_info = { - .name = CCID_DEV_NAME, + .name = TYPE_USB_CCID_DEV, .parent = TYPE_USB_DEVICE, .instance_size = sizeof(USBCCIDState), .class_init = ccid_class_initfn, @@ -1490,7 +1492,7 @@ static void ccid_register_types(void) type_register_static(&ccid_bus_info); type_register_static(&ccid_card_type_info); type_register_static(&ccid_info); - usb_legacy_register(CCID_DEV_NAME, "ccid", NULL); + usb_legacy_register(TYPE_USB_CCID_DEV, "ccid", NULL); } type_init(ccid_register_types) diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 4eba47538d8f17730f1427284c015ad2a525e1f6..f0f005869d25976cc4d5d2394237967c4cf506a4 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -22,15 +22,8 @@ #include "sysemu/block-backend.h" #include "qapi/visitor.h" #include "qemu/cutils.h" - -//#define DEBUG_MSD - -#ifdef DEBUG_MSD -#define DPRINTF(fmt, ...) \ -do { printf("usb-msd: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) do {} while(0) -#endif +#include "qom/object.h" +#include "trace.h" /* USB requests. */ #define MassStorageReset 0xff @@ -50,7 +43,7 @@ struct usb_msd_csw { uint8_t status; }; -typedef struct { +struct MSDState { USBDevice dev; enum USBMSDMode mode; uint32_t scsi_off; @@ -63,12 +56,15 @@ typedef struct { USBPacket *packet; /* usb-storage only */ BlockConf conf; - uint32_t removable; + bool removable; + bool commandlog; SCSIDevice *scsi_dev; -} MSDState; +}; +typedef struct MSDState MSDState; #define TYPE_USB_STORAGE "usb-storage-dev" -#define USB_STORAGE_DEV(obj) OBJECT_CHECK(MSDState, (obj), TYPE_USB_STORAGE) +DECLARE_INSTANCE_CHECKER(MSDState, USB_STORAGE_DEV, + TYPE_USB_STORAGE) struct usb_msd_cbw { uint32_t sig; @@ -229,6 +225,9 @@ static void usb_msd_copy_data(MSDState *s, USBPacket *p) usb_packet_copy(p, scsi_req_get_buf(s->req) + s->scsi_off, len); s->scsi_len -= len; s->scsi_off += len; + if (len > s->data_len) { + len = s->data_len; + } s->data_len -= len; if (s->scsi_len == 0 || s->data_len == 0) { scsi_req_continue(s->req); @@ -239,8 +238,8 @@ static void usb_msd_send_status(MSDState *s, USBPacket *p) { int len; - DPRINTF("Command status %d tag 0x%x, len %zd\n", - s->csw.status, le32_to_cpu(s->csw.tag), p->iov.size); + trace_usb_msd_send_status(s->csw.status, le32_to_cpu(s->csw.tag), + p->iov.size); assert(s->csw.sig == cpu_to_le32(0x53425355)); len = MIN(sizeof(s->csw), p->iov.size); @@ -255,7 +254,7 @@ static void usb_msd_packet_complete(MSDState *s) /* Set s->packet to NULL before calling usb_packet_complete because another request may be issued before usb_packet_complete returns. */ - DPRINTF("Packet complete %p\n", p); + trace_usb_msd_packet_complete(); s->packet = NULL; usb_packet_complete(&s->dev, p); } @@ -283,7 +282,7 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t r MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent); USBPacket *p = s->packet; - DPRINTF("Command complete %d tag 0x%x\n", status, req->tag); + trace_usb_msd_cmd_complete(status, req->tag); s->csw.sig = cpu_to_le32(0x53425355); s->csw.tag = cpu_to_le32(req->tag); @@ -303,6 +302,9 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t r if (s->data_len) { int len = (p->iov.size - p->actual_length); usb_packet_skip(p, len); + if (len > s->data_len) { + len = s->data_len; + } s->data_len -= len; } if (s->data_len == 0) { @@ -322,7 +324,13 @@ static void usb_msd_request_cancelled(SCSIRequest *req) { MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent); + trace_usb_msd_cmd_cancel(req->tag); + if (req == s->req) { + s->csw.sig = cpu_to_le32(0x53425355); + s->csw.tag = cpu_to_le32(req->tag); + s->csw.status = 1; /* error */ + scsi_req_unref(s->req); s->req = NULL; s->scsi_len = 0; @@ -333,7 +341,7 @@ static void usb_msd_handle_reset(USBDevice *dev) { MSDState *s = (MSDState *)dev; - DPRINTF("Reset\n"); + trace_usb_msd_reset(); if (s->req) { scsi_req_cancel(s->req); } @@ -379,7 +387,7 @@ static void usb_msd_handle_control(USBDevice *dev, USBPacket *p, } maxlun++; } - DPRINTF("MaxLun %d\n", maxlun); + trace_usb_msd_maxlun(maxlun); data[0] = maxlun; p->actual_length = 1; break; @@ -427,7 +435,6 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p) le32_to_cpu(cbw.sig)); goto fail; } - DPRINTF("Command on LUN %d\n", cbw.lun); scsi_dev = scsi_device_find(&s->bus, 0, 0, cbw.lun); if (scsi_dev == NULL) { error_report("usb-msd: Bad LUN %d", cbw.lun); @@ -442,14 +449,14 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p) } else { s->mode = USB_MSDM_DATAOUT; } - DPRINTF("Command tag 0x%x flags %08x len %d data %d\n", - tag, cbw.flags, cbw.cmd_len, s->data_len); + trace_usb_msd_cmd_submit(cbw.lun, tag, cbw.flags, + cbw.cmd_len, s->data_len); assert(le32_to_cpu(s->csw.residue) == 0); s->scsi_len = 0; s->req = scsi_req_new(scsi_dev, tag, cbw.lun, cbw.cmd, NULL); -#ifdef DEBUG_MSD - scsi_req_print(s->req); -#endif + if (s->commandlog) { + scsi_req_print(s->req); + } len = scsi_req_enqueue(s->req); if (len) { scsi_req_continue(s->req); @@ -457,7 +464,7 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p) break; case USB_MSDM_DATAOUT: - DPRINTF("Data out %zd/%d\n", p->iov.size, s->data_len); + trace_usb_msd_data_out(p->iov.size, s->data_len); if (p->iov.size > s->data_len) { goto fail; } @@ -469,6 +476,9 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p) int len = p->iov.size - p->actual_length; if (len) { usb_packet_skip(p, len); + if (len > s->data_len) { + len = s->data_len; + } s->data_len -= len; if (s->data_len == 0) { s->mode = USB_MSDM_CSW; @@ -476,14 +486,13 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p) } } if (p->actual_length < p->iov.size) { - DPRINTF("Deferring packet %p [wait data-out]\n", p); + trace_usb_msd_packet_async(); s->packet = p; p->status = USB_RET_ASYNC; } break; default: - DPRINTF("Unexpected write (len %zd)\n", p->iov.size); goto fail; } break; @@ -498,6 +507,7 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p) goto fail; } /* Waiting for SCSI write to complete. */ + trace_usb_msd_packet_async(); s->packet = p; p->status = USB_RET_ASYNC; break; @@ -509,7 +519,7 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p) if (s->req) { /* still in flight */ - DPRINTF("Deferring packet %p [wait status]\n", p); + trace_usb_msd_packet_async(); s->packet = p; p->status = USB_RET_ASYNC; } else { @@ -519,8 +529,7 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p) break; case USB_MSDM_DATAIN: - DPRINTF("Data in %zd/%d, scsi_len %d\n", - p->iov.size, s->data_len, s->scsi_len); + trace_usb_msd_data_in(p->iov.size, s->data_len, s->scsi_len); if (s->scsi_len) { usb_msd_copy_data(s, p); } @@ -528,27 +537,28 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p) int len = p->iov.size - p->actual_length; if (len) { usb_packet_skip(p, len); + if (len > s->data_len) { + len = s->data_len; + } s->data_len -= len; if (s->data_len == 0) { s->mode = USB_MSDM_CSW; } } } - if (p->actual_length < p->iov.size) { - DPRINTF("Deferring packet %p [wait data-in]\n", p); + if (p->actual_length < p->iov.size && s->mode == USB_MSDM_DATAIN) { + trace_usb_msd_packet_async(); s->packet = p; p->status = USB_RET_ASYNC; } break; default: - DPRINTF("Unexpected read (len %zd)\n", p->iov.size); goto fail; } break; default: - DPRINTF("Bad token\n"); fail: p->status = USB_RET_STALL; break; @@ -599,7 +609,10 @@ static void usb_msd_storage_realize(USBDevice *dev, Error **errp) return; } - blkconf_blocksizes(&s->conf); + if (!blkconf_blocksizes(&s->conf, errp)) { + return; + } + if (!blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), true, errp)) { return; @@ -673,7 +686,8 @@ static const VMStateDescription vmstate_usb_msd = { static Property msd_properties[] = { DEFINE_BLOCK_PROPERTIES(MSDState, conf), DEFINE_BLOCK_ERROR_PROPERTIES(MSDState, conf), - DEFINE_PROP_BIT("removable", MSDState, removable, 0, false), + DEFINE_PROP_BOOL("removable", MSDState, removable, false), + DEFINE_PROP_BOOL("commandlog", MSDState, commandlog, false), DEFINE_PROP_END_OF_LIST(), }; @@ -720,9 +734,8 @@ static void usb_msd_set_bootindex(Object *obj, Visitor *v, const char *name, int32_t boot_index; Error *local_err = NULL; - visit_type_int32(v, name, &boot_index, &local_err); - if (local_err) { - goto out; + if (!visit_type_int32(v, name, &boot_index, errp)) { + return; } /* check whether bootindex is present in fw_boot_order list */ check_boot_index(boot_index, &local_err); @@ -733,7 +746,7 @@ static void usb_msd_set_bootindex(Object *obj, Visitor *v, const char *name, s->conf.bootindex = boot_index; if (s->scsi_dev) { - object_property_set_int(OBJECT(s->scsi_dev), boot_index, "bootindex", + object_property_set_int(OBJECT(s->scsi_dev), "bootindex", boot_index, &error_abort); } @@ -754,7 +767,7 @@ static void usb_msd_instance_init(Object *obj) object_property_add(obj, "bootindex", "int32", usb_msd_get_bootindex, usb_msd_set_bootindex, NULL, NULL); - object_property_set_int(obj, -1, "bootindex", NULL); + object_property_set_int(obj, "bootindex", -1, NULL); } static void usb_msd_class_bot_initfn(ObjectClass *klass, void *data) diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c index a3a4d41c075ca91f398c17efecd47fce93d272ab..cec071d96c49f713983b1ec4064d7a75137d23b8 100644 --- a/hw/usb/dev-uas.c +++ b/hw/usb/dev-uas.c @@ -23,6 +23,7 @@ #include "hw/qdev-properties.h" #include "hw/scsi/scsi.h" #include "scsi/constants.h" +#include "qom/object.h" /* --------------------------------------------------------------------- */ @@ -132,7 +133,7 @@ struct UASDevice { }; #define TYPE_USB_UAS "usb-uas" -#define USB_UAS(obj) OBJECT_CHECK(UASDevice, (obj), TYPE_USB_UAS) +OBJECT_DECLARE_SIMPLE_TYPE(UASDevice, USB_UAS) struct UASRequest { uint16_t tag; diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c index 8aba44b8bc3d0c919d71c036d79da836e3a6093a..b595048635090242b5e771a11436e623305a113f 100644 --- a/hw/usb/dev-wacom.c +++ b/hw/usb/dev-wacom.c @@ -29,22 +29,17 @@ #include "qemu/osdep.h" #include "ui/console.h" #include "hw/usb.h" +#include "hw/usb/hid.h" #include "migration/vmstate.h" #include "qemu/module.h" #include "desc.h" +#include "qom/object.h" /* Interface requests */ #define WACOM_GET_REPORT 0x2101 #define WACOM_SET_REPORT 0x2109 -/* HID interface requests */ -#define HID_GET_REPORT 0xa101 -#define HID_GET_IDLE 0xa102 -#define HID_GET_PROTOCOL 0xa103 -#define HID_SET_IDLE 0x210a -#define HID_SET_PROTOCOL 0x210b - -typedef struct USBWacomState { +struct USBWacomState { USBDevice dev; USBEndpoint *intr; QEMUPutMouseEntry *eh_entry; @@ -57,10 +52,10 @@ typedef struct USBWacomState { } mode; uint8_t idle; int changed; -} USBWacomState; +}; #define TYPE_USB_WACOM "usb-wacom-tablet" -#define USB_WACOM(obj) OBJECT_CHECK(USBWacomState, (obj), TYPE_USB_WACOM) +OBJECT_DECLARE_SIMPLE_TYPE(USBWacomState, USB_WACOM) enum { STR_MANUFACTURER = 1, @@ -86,11 +81,11 @@ static const USBDescIface desc_iface_wacom = { /* HID descriptor */ .data = (uint8_t[]) { 0x09, /* u8 bLength */ - 0x21, /* u8 bDescriptorType */ + USB_DT_HID, /* u8 bDescriptorType */ 0x01, 0x10, /* u16 HID_class */ 0x00, /* u8 country_code */ 0x01, /* u8 num_descriptors */ - 0x22, /* u8 type: Report */ + USB_DT_REPORT, /* u8 type: Report */ 0x6e, 0, /* u16 len */ }, }, diff --git a/hw/usb/hcd-dwc2.c b/hw/usb/hcd-dwc2.c new file mode 100644 index 0000000000000000000000000000000000000000..e1d96acf7ecf80319d63e36652e4456ea1c6ba93 --- /dev/null +++ b/hw/usb/hcd-dwc2.c @@ -0,0 +1,1478 @@ +/* + * dwc-hsotg (dwc2) USB host controller emulation + * + * Based on hw/usb/hcd-ehci.c and hw/usb/hcd-ohci.c + * + * Note that to use this emulation with the dwc-otg driver in the + * Raspbian kernel, you must pass the option "dwc_otg.fiq_fsm_enable=0" + * on the kernel command line. + * + * Some useful documentation used to develop this emulation can be + * found online (as of April 2020) at: + * + * http://www.capital-micro.com/PDF/CME-M7_Family_User_Guide_EN.pdf + * which has a pretty complete description of the controller starting + * on page 370. + * + * https://sourceforge.net/p/wive-ng/wive-ng-mt/ci/master/tree/docs/DataSheets/RT3050_5x_V2.0_081408_0902.pdf + * which has a description of the controller registers starting on + * page 130. + * + * Copyright (c) 2020 Paul Zimmerman + * + * 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. + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "hw/usb/dwc2-regs.h" +#include "hw/usb/hcd-dwc2.h" +#include "migration/vmstate.h" +#include "trace.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" +#include "hw/qdev-properties.h" + +#define USB_HZ_FS 12000000 +#define USB_HZ_HS 96000000 +#define USB_FRMINTVL 12000 + +/* nifty macros from Arnon's EHCI version */ +#define get_field(data, field) \ + (((data) & field##_MASK) >> field##_SHIFT) + +#define set_field(data, newval, field) do { \ + uint32_t val = *(data); \ + val &= ~field##_MASK; \ + val |= ((newval) << field##_SHIFT) & field##_MASK; \ + *(data) = val; \ +} while (0) + +#define get_bit(data, bitmask) \ + (!!((data) & (bitmask))) + +/* update irq line */ +static inline void dwc2_update_irq(DWC2State *s) +{ + static int oldlevel; + int level = 0; + + if ((s->gintsts & s->gintmsk) && (s->gahbcfg & GAHBCFG_GLBL_INTR_EN)) { + level = 1; + } + if (level != oldlevel) { + oldlevel = level; + trace_usb_dwc2_update_irq(level); + qemu_set_irq(s->irq, level); + } +} + +/* flag interrupt condition */ +static inline void dwc2_raise_global_irq(DWC2State *s, uint32_t intr) +{ + if (!(s->gintsts & intr)) { + s->gintsts |= intr; + trace_usb_dwc2_raise_global_irq(intr); + dwc2_update_irq(s); + } +} + +static inline void dwc2_lower_global_irq(DWC2State *s, uint32_t intr) +{ + if (s->gintsts & intr) { + s->gintsts &= ~intr; + trace_usb_dwc2_lower_global_irq(intr); + dwc2_update_irq(s); + } +} + +static inline void dwc2_raise_host_irq(DWC2State *s, uint32_t host_intr) +{ + if (!(s->haint & host_intr)) { + s->haint |= host_intr; + s->haint &= 0xffff; + trace_usb_dwc2_raise_host_irq(host_intr); + if (s->haint & s->haintmsk) { + dwc2_raise_global_irq(s, GINTSTS_HCHINT); + } + } +} + +static inline void dwc2_lower_host_irq(DWC2State *s, uint32_t host_intr) +{ + if (s->haint & host_intr) { + s->haint &= ~host_intr; + trace_usb_dwc2_lower_host_irq(host_intr); + if (!(s->haint & s->haintmsk)) { + dwc2_lower_global_irq(s, GINTSTS_HCHINT); + } + } +} + +static inline void dwc2_update_hc_irq(DWC2State *s, int index) +{ + uint32_t host_intr = 1 << (index >> 3); + + if (s->hreg1[index + 2] & s->hreg1[index + 3]) { + dwc2_raise_host_irq(s, host_intr); + } else { + dwc2_lower_host_irq(s, host_intr); + } +} + +/* set a timer for EOF */ +static void dwc2_eof_timer(DWC2State *s) +{ + timer_mod(s->eof_timer, s->sof_time + s->usb_frame_time); +} + +/* Set a timer for EOF and generate SOF event */ +static void dwc2_sof(DWC2State *s) +{ + s->sof_time += s->usb_frame_time; + trace_usb_dwc2_sof(s->sof_time); + dwc2_eof_timer(s); + dwc2_raise_global_irq(s, GINTSTS_SOF); +} + +/* Do frame processing on frame boundary */ +static void dwc2_frame_boundary(void *opaque) +{ + DWC2State *s = opaque; + int64_t now; + uint16_t frcnt; + + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + + /* Frame boundary, so do EOF stuff here */ + + /* Increment frame number */ + frcnt = (uint16_t)((now - s->sof_time) / s->fi); + s->frame_number = (s->frame_number + frcnt) & 0xffff; + s->hfnum = s->frame_number & HFNUM_MAX_FRNUM; + + /* Do SOF stuff here */ + dwc2_sof(s); +} + +/* Start sending SOF tokens on the USB bus */ +static void dwc2_bus_start(DWC2State *s) +{ + trace_usb_dwc2_bus_start(); + s->sof_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + dwc2_eof_timer(s); +} + +/* Stop sending SOF tokens on the USB bus */ +static void dwc2_bus_stop(DWC2State *s) +{ + trace_usb_dwc2_bus_stop(); + timer_del(s->eof_timer); +} + +static USBDevice *dwc2_find_device(DWC2State *s, uint8_t addr) +{ + USBDevice *dev; + + trace_usb_dwc2_find_device(addr); + + if (!(s->hprt0 & HPRT0_ENA)) { + trace_usb_dwc2_port_disabled(0); + } else { + dev = usb_find_device(&s->uport, addr); + if (dev != NULL) { + trace_usb_dwc2_device_found(0); + return dev; + } + } + + trace_usb_dwc2_device_not_found(); + return NULL; +} + +static const char *pstatus[] = { + "USB_RET_SUCCESS", "USB_RET_NODEV", "USB_RET_NAK", "USB_RET_STALL", + "USB_RET_BABBLE", "USB_RET_IOERROR", "USB_RET_ASYNC", + "USB_RET_ADD_TO_QUEUE", "USB_RET_REMOVE_FROM_QUEUE" +}; + +static uint32_t pintr[] = { + HCINTMSK_XFERCOMPL, HCINTMSK_XACTERR, HCINTMSK_NAK, HCINTMSK_STALL, + HCINTMSK_BBLERR, HCINTMSK_XACTERR, HCINTMSK_XACTERR, HCINTMSK_XACTERR, + HCINTMSK_XACTERR +}; + +static const char *types[] = { + "Ctrl", "Isoc", "Bulk", "Intr" +}; + +static const char *dirs[] = { + "Out", "In" +}; + +static void dwc2_handle_packet(DWC2State *s, uint32_t devadr, USBDevice *dev, + USBEndpoint *ep, uint32_t index, bool send) +{ + DWC2Packet *p; + uint32_t hcchar = s->hreg1[index]; + uint32_t hctsiz = s->hreg1[index + 4]; + uint32_t hcdma = s->hreg1[index + 5]; + uint32_t chan, epnum, epdir, eptype, mps, pid, pcnt, len, tlen, intr = 0; + uint32_t tpcnt, stsidx, actual = 0; + bool do_intr = false, done = false; + + epnum = get_field(hcchar, HCCHAR_EPNUM); + epdir = get_bit(hcchar, HCCHAR_EPDIR); + eptype = get_field(hcchar, HCCHAR_EPTYPE); + mps = get_field(hcchar, HCCHAR_MPS); + pid = get_field(hctsiz, TSIZ_SC_MC_PID); + pcnt = get_field(hctsiz, TSIZ_PKTCNT); + len = get_field(hctsiz, TSIZ_XFERSIZE); + if (len > DWC2_MAX_XFER_SIZE) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: HCTSIZ transfer size too large\n", __func__); + return; + } + + chan = index >> 3; + p = &s->packet[chan]; + + trace_usb_dwc2_handle_packet(chan, dev, &p->packet, epnum, types[eptype], + dirs[epdir], mps, len, pcnt); + + if (mps == 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad HCCHAR_MPS set to zero\n", __func__); + return; + } + + if (eptype == USB_ENDPOINT_XFER_CONTROL && pid == TSIZ_SC_MC_PID_SETUP) { + pid = USB_TOKEN_SETUP; + } else { + pid = epdir ? USB_TOKEN_IN : USB_TOKEN_OUT; + } + + if (send) { + tlen = len; + if (p->small) { + if (tlen > mps) { + tlen = mps; + } + } + + if (pid != USB_TOKEN_IN) { + trace_usb_dwc2_memory_read(hcdma, tlen); + if (dma_memory_read(&s->dma_as, hcdma, + s->usb_buf[chan], tlen) != MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: dma_memory_read failed\n", + __func__); + } + } + + usb_packet_init(&p->packet); + usb_packet_setup(&p->packet, pid, ep, 0, hcdma, + pid != USB_TOKEN_IN, true); + usb_packet_addbuf(&p->packet, s->usb_buf[chan], tlen); + p->async = DWC2_ASYNC_NONE; + usb_handle_packet(dev, &p->packet); + } else { + tlen = p->len; + } + + stsidx = -p->packet.status; + assert(stsidx < sizeof(pstatus) / sizeof(*pstatus)); + actual = p->packet.actual_length; + trace_usb_dwc2_packet_status(pstatus[stsidx], actual); + +babble: + if (p->packet.status != USB_RET_SUCCESS && + p->packet.status != USB_RET_NAK && + p->packet.status != USB_RET_STALL && + p->packet.status != USB_RET_ASYNC) { + trace_usb_dwc2_packet_error(pstatus[stsidx]); + } + + if (p->packet.status == USB_RET_ASYNC) { + trace_usb_dwc2_async_packet(&p->packet, chan, dev, epnum, + dirs[epdir], tlen); + usb_device_flush_ep_queue(dev, ep); + assert(p->async != DWC2_ASYNC_INFLIGHT); + p->devadr = devadr; + p->epnum = epnum; + p->epdir = epdir; + p->mps = mps; + p->pid = pid; + p->index = index; + p->pcnt = pcnt; + p->len = tlen; + p->async = DWC2_ASYNC_INFLIGHT; + p->needs_service = false; + return; + } + + if (p->packet.status == USB_RET_SUCCESS) { + if (actual > tlen) { + p->packet.status = USB_RET_BABBLE; + goto babble; + } + + if (pid == USB_TOKEN_IN) { + trace_usb_dwc2_memory_write(hcdma, actual); + if (dma_memory_write(&s->dma_as, hcdma, s->usb_buf[chan], + actual) != MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: dma_memory_write failed\n", + __func__); + } + } + + tpcnt = actual / mps; + if (actual % mps) { + tpcnt++; + if (pid == USB_TOKEN_IN) { + done = true; + } + } + + pcnt -= tpcnt < pcnt ? tpcnt : pcnt; + set_field(&hctsiz, pcnt, TSIZ_PKTCNT); + len -= actual < len ? actual : len; + set_field(&hctsiz, len, TSIZ_XFERSIZE); + s->hreg1[index + 4] = hctsiz; + hcdma += actual; + s->hreg1[index + 5] = hcdma; + + if (!pcnt || len == 0 || actual == 0) { + done = true; + } + } else { + intr |= pintr[stsidx]; + if (p->packet.status == USB_RET_NAK && + (eptype == USB_ENDPOINT_XFER_CONTROL || + eptype == USB_ENDPOINT_XFER_BULK)) { + /* + * for ctrl/bulk, automatically retry on NAK, + * but send the interrupt anyway + */ + intr &= ~HCINTMSK_RESERVED14_31; + s->hreg1[index + 2] |= intr; + do_intr = true; + } else { + intr |= HCINTMSK_CHHLTD; + done = true; + } + } + + usb_packet_cleanup(&p->packet); + + if (done) { + hcchar &= ~HCCHAR_CHENA; + s->hreg1[index] = hcchar; + if (!(intr & HCINTMSK_CHHLTD)) { + intr |= HCINTMSK_CHHLTD | HCINTMSK_XFERCOMPL; + } + intr &= ~HCINTMSK_RESERVED14_31; + s->hreg1[index + 2] |= intr; + p->needs_service = false; + trace_usb_dwc2_packet_done(pstatus[stsidx], actual, len, pcnt); + dwc2_update_hc_irq(s, index); + return; + } + + p->devadr = devadr; + p->epnum = epnum; + p->epdir = epdir; + p->mps = mps; + p->pid = pid; + p->index = index; + p->pcnt = pcnt; + p->len = len; + p->needs_service = true; + trace_usb_dwc2_packet_next(pstatus[stsidx], len, pcnt); + if (do_intr) { + dwc2_update_hc_irq(s, index); + } +} + +/* Attach or detach a device on root hub */ + +static const char *speeds[] = { + "low", "full", "high" +}; + +static void dwc2_attach(USBPort *port) +{ + DWC2State *s = port->opaque; + int hispd = 0; + + trace_usb_dwc2_attach(port); + assert(port->index == 0); + + if (!port->dev || !port->dev->attached) { + return; + } + + assert(port->dev->speed <= USB_SPEED_HIGH); + trace_usb_dwc2_attach_speed(speeds[port->dev->speed]); + s->hprt0 &= ~HPRT0_SPD_MASK; + + switch (port->dev->speed) { + case USB_SPEED_LOW: + s->hprt0 |= HPRT0_SPD_LOW_SPEED << HPRT0_SPD_SHIFT; + break; + case USB_SPEED_FULL: + s->hprt0 |= HPRT0_SPD_FULL_SPEED << HPRT0_SPD_SHIFT; + break; + case USB_SPEED_HIGH: + s->hprt0 |= HPRT0_SPD_HIGH_SPEED << HPRT0_SPD_SHIFT; + hispd = 1; + break; + } + + if (hispd) { + s->usb_frame_time = NANOSECONDS_PER_SECOND / 8000; /* 125000 */ + if (NANOSECONDS_PER_SECOND >= USB_HZ_HS) { + s->usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ_HS; /* 10.4 */ + } else { + s->usb_bit_time = 1; + } + } else { + s->usb_frame_time = NANOSECONDS_PER_SECOND / 1000; /* 1000000 */ + if (NANOSECONDS_PER_SECOND >= USB_HZ_FS) { + s->usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ_FS; /* 83.3 */ + } else { + s->usb_bit_time = 1; + } + } + + s->fi = USB_FRMINTVL - 1; + s->hprt0 |= HPRT0_CONNDET | HPRT0_CONNSTS; + + dwc2_bus_start(s); + dwc2_raise_global_irq(s, GINTSTS_PRTINT); +} + +static void dwc2_detach(USBPort *port) +{ + DWC2State *s = port->opaque; + + trace_usb_dwc2_detach(port); + assert(port->index == 0); + + dwc2_bus_stop(s); + + s->hprt0 &= ~(HPRT0_SPD_MASK | HPRT0_SUSP | HPRT0_ENA | HPRT0_CONNSTS); + s->hprt0 |= HPRT0_CONNDET | HPRT0_ENACHG; + + dwc2_raise_global_irq(s, GINTSTS_PRTINT); +} + +static void dwc2_child_detach(USBPort *port, USBDevice *child) +{ + trace_usb_dwc2_child_detach(port, child); + assert(port->index == 0); +} + +static void dwc2_wakeup(USBPort *port) +{ + DWC2State *s = port->opaque; + + trace_usb_dwc2_wakeup(port); + assert(port->index == 0); + + if (s->hprt0 & HPRT0_SUSP) { + s->hprt0 |= HPRT0_RES; + dwc2_raise_global_irq(s, GINTSTS_PRTINT); + } + + qemu_bh_schedule(s->async_bh); +} + +static void dwc2_async_packet_complete(USBPort *port, USBPacket *packet) +{ + DWC2State *s = port->opaque; + DWC2Packet *p; + USBDevice *dev; + USBEndpoint *ep; + + assert(port->index == 0); + p = container_of(packet, DWC2Packet, packet); + dev = dwc2_find_device(s, p->devadr); + ep = usb_ep_get(dev, p->pid, p->epnum); + trace_usb_dwc2_async_packet_complete(port, packet, p->index >> 3, dev, + p->epnum, dirs[p->epdir], p->len); + assert(p->async == DWC2_ASYNC_INFLIGHT); + + if (packet->status == USB_RET_REMOVE_FROM_QUEUE) { + usb_cancel_packet(packet); + usb_packet_cleanup(packet); + return; + } + + dwc2_handle_packet(s, p->devadr, dev, ep, p->index, false); + + p->async = DWC2_ASYNC_FINISHED; + qemu_bh_schedule(s->async_bh); +} + +static USBPortOps dwc2_port_ops = { + .attach = dwc2_attach, + .detach = dwc2_detach, + .child_detach = dwc2_child_detach, + .wakeup = dwc2_wakeup, + .complete = dwc2_async_packet_complete, +}; + +static uint32_t dwc2_get_frame_remaining(DWC2State *s) +{ + uint32_t fr = 0; + int64_t tks; + + tks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->sof_time; + if (tks < 0) { + tks = 0; + } + + /* avoid muldiv if possible */ + if (tks >= s->usb_frame_time) { + goto out; + } + if (tks < s->usb_bit_time) { + fr = s->fi; + goto out; + } + + /* tks = number of ns since SOF, divided by 83 (fs) or 10 (hs) */ + tks = tks / s->usb_bit_time; + if (tks >= (int64_t)s->fi) { + goto out; + } + + /* remaining = frame interval minus tks */ + fr = (uint32_t)((int64_t)s->fi - tks); + +out: + return fr; +} + +static void dwc2_work_bh(void *opaque) +{ + DWC2State *s = opaque; + DWC2Packet *p; + USBDevice *dev; + USBEndpoint *ep; + int64_t t_now, expire_time; + int chan; + bool found = false; + + trace_usb_dwc2_work_bh(); + if (s->working) { + return; + } + s->working = true; + + t_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + chan = s->next_chan; + + do { + p = &s->packet[chan]; + if (p->needs_service) { + dev = dwc2_find_device(s, p->devadr); + ep = usb_ep_get(dev, p->pid, p->epnum); + trace_usb_dwc2_work_bh_service(s->next_chan, chan, dev, p->epnum); + dwc2_handle_packet(s, p->devadr, dev, ep, p->index, true); + found = true; + } + if (++chan == DWC2_NB_CHAN) { + chan = 0; + } + if (found) { + s->next_chan = chan; + trace_usb_dwc2_work_bh_next(chan); + } + } while (chan != s->next_chan); + + if (found) { + expire_time = t_now + NANOSECONDS_PER_SECOND / 4000; + timer_mod(s->frame_timer, expire_time); + } + s->working = false; +} + +static void dwc2_enable_chan(DWC2State *s, uint32_t index) +{ + USBDevice *dev; + USBEndpoint *ep; + uint32_t hcchar; + uint32_t hctsiz; + uint32_t devadr, epnum, epdir, eptype, pid, len; + DWC2Packet *p; + + assert((index >> 3) < DWC2_NB_CHAN); + p = &s->packet[index >> 3]; + hcchar = s->hreg1[index]; + hctsiz = s->hreg1[index + 4]; + devadr = get_field(hcchar, HCCHAR_DEVADDR); + epnum = get_field(hcchar, HCCHAR_EPNUM); + epdir = get_bit(hcchar, HCCHAR_EPDIR); + eptype = get_field(hcchar, HCCHAR_EPTYPE); + pid = get_field(hctsiz, TSIZ_SC_MC_PID); + len = get_field(hctsiz, TSIZ_XFERSIZE); + + dev = dwc2_find_device(s, devadr); + + trace_usb_dwc2_enable_chan(index >> 3, dev, &p->packet, epnum); + if (dev == NULL) { + return; + } + + if (eptype == USB_ENDPOINT_XFER_CONTROL && pid == TSIZ_SC_MC_PID_SETUP) { + pid = USB_TOKEN_SETUP; + } else { + pid = epdir ? USB_TOKEN_IN : USB_TOKEN_OUT; + } + + ep = usb_ep_get(dev, pid, epnum); + + /* + * Hack: Networking doesn't like us delivering large transfers, it kind + * of works but the latency is horrible. So if the transfer is <= the mtu + * size, we take that as a hint that this might be a network transfer, + * and do the transfer packet-by-packet. + */ + if (len > 1536) { + p->small = false; + } else { + p->small = true; + } + + dwc2_handle_packet(s, devadr, dev, ep, index, true); + qemu_bh_schedule(s->async_bh); +} + +static const char *glbregnm[] = { + "GOTGCTL ", "GOTGINT ", "GAHBCFG ", "GUSBCFG ", "GRSTCTL ", + "GINTSTS ", "GINTMSK ", "GRXSTSR ", "GRXSTSP ", "GRXFSIZ ", + "GNPTXFSIZ", "GNPTXSTS ", "GI2CCTL ", "GPVNDCTL ", "GGPIO ", + "GUID ", "GSNPSID ", "GHWCFG1 ", "GHWCFG2 ", "GHWCFG3 ", + "GHWCFG4 ", "GLPMCFG ", "GPWRDN ", "GDFIFOCFG", "GADPCTL ", + "GREFCLK ", "GINTMSK2 ", "GINTSTS2 " +}; + +static uint64_t dwc2_glbreg_read(void *ptr, hwaddr addr, int index, + unsigned size) +{ + DWC2State *s = ptr; + uint32_t val; + + if (addr > GINTSTS2) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return 0; + } + + val = s->glbreg[index]; + + switch (addr) { + case GRSTCTL: + /* clear any self-clearing bits that were set */ + val &= ~(GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH | GRSTCTL_IN_TKNQ_FLSH | + GRSTCTL_FRMCNTRRST | GRSTCTL_HSFTRST | GRSTCTL_CSFTRST); + s->glbreg[index] = val; + break; + default: + break; + } + + trace_usb_dwc2_glbreg_read(addr, glbregnm[index], val); + return val; +} + +static void dwc2_glbreg_write(void *ptr, hwaddr addr, int index, uint64_t val, + unsigned size) +{ + DWC2State *s = ptr; + uint64_t orig = val; + uint32_t *mmio; + uint32_t old; + int iflg = 0; + + if (addr > GINTSTS2) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return; + } + + mmio = &s->glbreg[index]; + old = *mmio; + + switch (addr) { + case GOTGCTL: + /* don't allow setting of read-only bits */ + val &= ~(GOTGCTL_MULT_VALID_BC_MASK | GOTGCTL_BSESVLD | + GOTGCTL_ASESVLD | GOTGCTL_DBNC_SHORT | GOTGCTL_CONID_B | + GOTGCTL_HSTNEGSCS | GOTGCTL_SESREQSCS); + /* don't allow clearing of read-only bits */ + val |= old & (GOTGCTL_MULT_VALID_BC_MASK | GOTGCTL_BSESVLD | + GOTGCTL_ASESVLD | GOTGCTL_DBNC_SHORT | GOTGCTL_CONID_B | + GOTGCTL_HSTNEGSCS | GOTGCTL_SESREQSCS); + break; + case GAHBCFG: + if ((val & GAHBCFG_GLBL_INTR_EN) && !(old & GAHBCFG_GLBL_INTR_EN)) { + iflg = 1; + } + break; + case GRSTCTL: + val |= GRSTCTL_AHBIDLE; + val &= ~GRSTCTL_DMAREQ; + if (!(old & GRSTCTL_TXFFLSH) && (val & GRSTCTL_TXFFLSH)) { + /* TODO - TX fifo flush */ + qemu_log_mask(LOG_UNIMP, "%s: Tx FIFO flush not implemented\n", + __func__); + } + if (!(old & GRSTCTL_RXFFLSH) && (val & GRSTCTL_RXFFLSH)) { + /* TODO - RX fifo flush */ + qemu_log_mask(LOG_UNIMP, "%s: Rx FIFO flush not implemented\n", + __func__); + } + if (!(old & GRSTCTL_IN_TKNQ_FLSH) && (val & GRSTCTL_IN_TKNQ_FLSH)) { + /* TODO - device IN token queue flush */ + qemu_log_mask(LOG_UNIMP, "%s: Token queue flush not implemented\n", + __func__); + } + if (!(old & GRSTCTL_FRMCNTRRST) && (val & GRSTCTL_FRMCNTRRST)) { + /* TODO - host frame counter reset */ + qemu_log_mask(LOG_UNIMP, + "%s: Frame counter reset not implemented\n", + __func__); + } + if (!(old & GRSTCTL_HSFTRST) && (val & GRSTCTL_HSFTRST)) { + /* TODO - host soft reset */ + qemu_log_mask(LOG_UNIMP, "%s: Host soft reset not implemented\n", + __func__); + } + if (!(old & GRSTCTL_CSFTRST) && (val & GRSTCTL_CSFTRST)) { + /* TODO - core soft reset */ + qemu_log_mask(LOG_UNIMP, "%s: Core soft reset not implemented\n", + __func__); + } + /* don't allow clearing of self-clearing bits */ + val |= old & (GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH | + GRSTCTL_IN_TKNQ_FLSH | GRSTCTL_FRMCNTRRST | + GRSTCTL_HSFTRST | GRSTCTL_CSFTRST); + break; + case GINTSTS: + /* clear the write-1-to-clear bits */ + val |= ~old; + val = ~val; + /* don't allow clearing of read-only bits */ + val |= old & (GINTSTS_PTXFEMP | GINTSTS_HCHINT | GINTSTS_PRTINT | + GINTSTS_OEPINT | GINTSTS_IEPINT | GINTSTS_GOUTNAKEFF | + GINTSTS_GINNAKEFF | GINTSTS_NPTXFEMP | GINTSTS_RXFLVL | + GINTSTS_OTGINT | GINTSTS_CURMODE_HOST); + iflg = 1; + break; + case GINTMSK: + iflg = 1; + break; + default: + break; + } + + trace_usb_dwc2_glbreg_write(addr, glbregnm[index], orig, old, val); + *mmio = val; + + if (iflg) { + dwc2_update_irq(s); + } +} + +static uint64_t dwc2_fszreg_read(void *ptr, hwaddr addr, int index, + unsigned size) +{ + DWC2State *s = ptr; + uint32_t val; + + if (addr != HPTXFSIZ) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return 0; + } + + val = s->fszreg[index]; + + trace_usb_dwc2_fszreg_read(addr, val); + return val; +} + +static void dwc2_fszreg_write(void *ptr, hwaddr addr, int index, uint64_t val, + unsigned size) +{ + DWC2State *s = ptr; + uint64_t orig = val; + uint32_t *mmio; + uint32_t old; + + if (addr != HPTXFSIZ) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return; + } + + mmio = &s->fszreg[index]; + old = *mmio; + + trace_usb_dwc2_fszreg_write(addr, orig, old, val); + *mmio = val; +} + +static const char *hreg0nm[] = { + "HCFG ", "HFIR ", "HFNUM ", " ", "HPTXSTS ", + "HAINT ", "HAINTMSK ", "HFLBADDR ", " ", " ", + " ", " ", " ", " ", " ", + " ", "HPRT0 " +}; + +static uint64_t dwc2_hreg0_read(void *ptr, hwaddr addr, int index, + unsigned size) +{ + DWC2State *s = ptr; + uint32_t val; + + if (addr < HCFG || addr > HPRT0) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return 0; + } + + val = s->hreg0[index]; + + switch (addr) { + case HFNUM: + val = (dwc2_get_frame_remaining(s) << HFNUM_FRREM_SHIFT) | + (s->hfnum << HFNUM_FRNUM_SHIFT); + break; + default: + break; + } + + trace_usb_dwc2_hreg0_read(addr, hreg0nm[index], val); + return val; +} + +static void dwc2_hreg0_write(void *ptr, hwaddr addr, int index, uint64_t val, + unsigned size) +{ + DWC2State *s = ptr; + USBDevice *dev = s->uport.dev; + uint64_t orig = val; + uint32_t *mmio; + uint32_t tval, told, old; + int prst = 0; + int iflg = 0; + + if (addr < HCFG || addr > HPRT0) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return; + } + + mmio = &s->hreg0[index]; + old = *mmio; + + switch (addr) { + case HFIR: + break; + case HFNUM: + case HPTXSTS: + case HAINT: + qemu_log_mask(LOG_GUEST_ERROR, "%s: write to read-only register\n", + __func__); + return; + case HAINTMSK: + val &= 0xffff; + break; + case HPRT0: + /* don't allow clearing of read-only bits */ + val |= old & (HPRT0_SPD_MASK | HPRT0_LNSTS_MASK | HPRT0_OVRCURRACT | + HPRT0_CONNSTS); + /* don't allow clearing of self-clearing bits */ + val |= old & (HPRT0_SUSP | HPRT0_RES); + /* don't allow setting of self-setting bits */ + if (!(old & HPRT0_ENA) && (val & HPRT0_ENA)) { + val &= ~HPRT0_ENA; + } + /* clear the write-1-to-clear bits */ + tval = val & (HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_ENA | + HPRT0_CONNDET); + told = old & (HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_ENA | + HPRT0_CONNDET); + tval |= ~told; + tval = ~tval; + tval &= (HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_ENA | + HPRT0_CONNDET); + val &= ~(HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_ENA | + HPRT0_CONNDET); + val |= tval; + if (!(val & HPRT0_RST) && (old & HPRT0_RST)) { + if (dev && dev->attached) { + val |= HPRT0_ENA | HPRT0_ENACHG; + prst = 1; + } + } + if (val & (HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_CONNDET)) { + iflg = 1; + } else { + iflg = -1; + } + break; + default: + break; + } + + if (prst) { + trace_usb_dwc2_hreg0_write(addr, hreg0nm[index], orig, old, + val & ~HPRT0_CONNDET); + trace_usb_dwc2_hreg0_action("call usb_port_reset"); + usb_port_reset(&s->uport); + val &= ~HPRT0_CONNDET; + } else { + trace_usb_dwc2_hreg0_write(addr, hreg0nm[index], orig, old, val); + } + + *mmio = val; + + if (iflg > 0) { + trace_usb_dwc2_hreg0_action("enable PRTINT"); + dwc2_raise_global_irq(s, GINTSTS_PRTINT); + } else if (iflg < 0) { + trace_usb_dwc2_hreg0_action("disable PRTINT"); + dwc2_lower_global_irq(s, GINTSTS_PRTINT); + } +} + +static const char *hreg1nm[] = { + "HCCHAR ", "HCSPLT ", "HCINT ", "HCINTMSK", "HCTSIZ ", "HCDMA ", + " ", "HCDMAB " +}; + +static uint64_t dwc2_hreg1_read(void *ptr, hwaddr addr, int index, + unsigned size) +{ + DWC2State *s = ptr; + uint32_t val; + + if (addr < HCCHAR(0) || addr > HCDMAB(DWC2_NB_CHAN - 1)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return 0; + } + + val = s->hreg1[index]; + + trace_usb_dwc2_hreg1_read(addr, hreg1nm[index & 7], addr >> 5, val); + return val; +} + +static void dwc2_hreg1_write(void *ptr, hwaddr addr, int index, uint64_t val, + unsigned size) +{ + DWC2State *s = ptr; + uint64_t orig = val; + uint32_t *mmio; + uint32_t old; + int iflg = 0; + int enflg = 0; + int disflg = 0; + + if (addr < HCCHAR(0) || addr > HCDMAB(DWC2_NB_CHAN - 1)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return; + } + + mmio = &s->hreg1[index]; + old = *mmio; + + switch (HSOTG_REG(0x500) + (addr & 0x1c)) { + case HCCHAR(0): + if ((val & HCCHAR_CHDIS) && !(old & HCCHAR_CHDIS)) { + val &= ~(HCCHAR_CHENA | HCCHAR_CHDIS); + disflg = 1; + } else { + val |= old & HCCHAR_CHDIS; + if ((val & HCCHAR_CHENA) && !(old & HCCHAR_CHENA)) { + val &= ~HCCHAR_CHDIS; + enflg = 1; + } else { + val |= old & HCCHAR_CHENA; + } + } + break; + case HCINT(0): + /* clear the write-1-to-clear bits */ + val |= ~old; + val = ~val; + val &= ~HCINTMSK_RESERVED14_31; + iflg = 1; + break; + case HCINTMSK(0): + val &= ~HCINTMSK_RESERVED14_31; + iflg = 1; + break; + case HCDMAB(0): + qemu_log_mask(LOG_GUEST_ERROR, "%s: write to read-only register\n", + __func__); + return; + default: + break; + } + + trace_usb_dwc2_hreg1_write(addr, hreg1nm[index & 7], index >> 3, orig, + old, val); + *mmio = val; + + if (disflg) { + /* set ChHltd in HCINT */ + s->hreg1[(index & ~7) + 2] |= HCINTMSK_CHHLTD; + iflg = 1; + } + + if (enflg) { + dwc2_enable_chan(s, index & ~7); + } + + if (iflg) { + dwc2_update_hc_irq(s, index & ~7); + } +} + +static const char *pcgregnm[] = { + "PCGCTL ", "PCGCCTL1 " +}; + +static uint64_t dwc2_pcgreg_read(void *ptr, hwaddr addr, int index, + unsigned size) +{ + DWC2State *s = ptr; + uint32_t val; + + if (addr < PCGCTL || addr > PCGCCTL1) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return 0; + } + + val = s->pcgreg[index]; + + trace_usb_dwc2_pcgreg_read(addr, pcgregnm[index], val); + return val; +} + +static void dwc2_pcgreg_write(void *ptr, hwaddr addr, int index, + uint64_t val, unsigned size) +{ + DWC2State *s = ptr; + uint64_t orig = val; + uint32_t *mmio; + uint32_t old; + + if (addr < PCGCTL || addr > PCGCCTL1) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return; + } + + mmio = &s->pcgreg[index]; + old = *mmio; + + trace_usb_dwc2_pcgreg_write(addr, pcgregnm[index], orig, old, val); + *mmio = val; +} + +static uint64_t dwc2_hsotg_read(void *ptr, hwaddr addr, unsigned size) +{ + uint64_t val; + + switch (addr) { + case HSOTG_REG(0x000) ... HSOTG_REG(0x0fc): + val = dwc2_glbreg_read(ptr, addr, (addr - HSOTG_REG(0x000)) >> 2, size); + break; + case HSOTG_REG(0x100): + val = dwc2_fszreg_read(ptr, addr, (addr - HSOTG_REG(0x100)) >> 2, size); + break; + case HSOTG_REG(0x104) ... HSOTG_REG(0x3fc): + /* Gadget-mode registers, just return 0 for now */ + val = 0; + break; + case HSOTG_REG(0x400) ... HSOTG_REG(0x4fc): + val = dwc2_hreg0_read(ptr, addr, (addr - HSOTG_REG(0x400)) >> 2, size); + break; + case HSOTG_REG(0x500) ... HSOTG_REG(0x7fc): + val = dwc2_hreg1_read(ptr, addr, (addr - HSOTG_REG(0x500)) >> 2, size); + break; + case HSOTG_REG(0x800) ... HSOTG_REG(0xdfc): + /* Gadget-mode registers, just return 0 for now */ + val = 0; + break; + case HSOTG_REG(0xe00) ... HSOTG_REG(0xffc): + val = dwc2_pcgreg_read(ptr, addr, (addr - HSOTG_REG(0xe00)) >> 2, size); + break; + default: + g_assert_not_reached(); + } + + return val; +} + +static void dwc2_hsotg_write(void *ptr, hwaddr addr, uint64_t val, + unsigned size) +{ + switch (addr) { + case HSOTG_REG(0x000) ... HSOTG_REG(0x0fc): + dwc2_glbreg_write(ptr, addr, (addr - HSOTG_REG(0x000)) >> 2, val, size); + break; + case HSOTG_REG(0x100): + dwc2_fszreg_write(ptr, addr, (addr - HSOTG_REG(0x100)) >> 2, val, size); + break; + case HSOTG_REG(0x104) ... HSOTG_REG(0x3fc): + /* Gadget-mode registers, do nothing for now */ + break; + case HSOTG_REG(0x400) ... HSOTG_REG(0x4fc): + dwc2_hreg0_write(ptr, addr, (addr - HSOTG_REG(0x400)) >> 2, val, size); + break; + case HSOTG_REG(0x500) ... HSOTG_REG(0x7fc): + dwc2_hreg1_write(ptr, addr, (addr - HSOTG_REG(0x500)) >> 2, val, size); + break; + case HSOTG_REG(0x800) ... HSOTG_REG(0xdfc): + /* Gadget-mode registers, do nothing for now */ + break; + case HSOTG_REG(0xe00) ... HSOTG_REG(0xffc): + dwc2_pcgreg_write(ptr, addr, (addr - HSOTG_REG(0xe00)) >> 2, val, size); + break; + default: + g_assert_not_reached(); + } +} + +static const MemoryRegionOps dwc2_mmio_hsotg_ops = { + .read = dwc2_hsotg_read, + .write = dwc2_hsotg_write, + .impl.min_access_size = 4, + .impl.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static uint64_t dwc2_hreg2_read(void *ptr, hwaddr addr, unsigned size) +{ + /* TODO - implement FIFOs to support slave mode */ + trace_usb_dwc2_hreg2_read(addr, addr >> 12, 0); + qemu_log_mask(LOG_UNIMP, "%s: FIFO read not implemented\n", __func__); + return 0; +} + +static void dwc2_hreg2_write(void *ptr, hwaddr addr, uint64_t val, + unsigned size) +{ + uint64_t orig = val; + + /* TODO - implement FIFOs to support slave mode */ + trace_usb_dwc2_hreg2_write(addr, addr >> 12, orig, 0, val); + qemu_log_mask(LOG_UNIMP, "%s: FIFO write not implemented\n", __func__); +} + +static const MemoryRegionOps dwc2_mmio_hreg2_ops = { + .read = dwc2_hreg2_read, + .write = dwc2_hreg2_write, + .impl.min_access_size = 4, + .impl.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void dwc2_wakeup_endpoint(USBBus *bus, USBEndpoint *ep, + unsigned int stream) +{ + DWC2State *s = container_of(bus, DWC2State, bus); + + trace_usb_dwc2_wakeup_endpoint(ep, stream); + + /* TODO - do something here? */ + qemu_bh_schedule(s->async_bh); +} + +static USBBusOps dwc2_bus_ops = { + .wakeup_endpoint = dwc2_wakeup_endpoint, +}; + +static void dwc2_work_timer(void *opaque) +{ + DWC2State *s = opaque; + + trace_usb_dwc2_work_timer(); + qemu_bh_schedule(s->async_bh); +} + +static void dwc2_reset_enter(Object *obj, ResetType type) +{ + DWC2Class *c = DWC2_USB_GET_CLASS(obj); + DWC2State *s = DWC2_USB(obj); + int i; + + trace_usb_dwc2_reset_enter(); + + if (c->parent_phases.enter) { + c->parent_phases.enter(obj, type); + } + + timer_del(s->frame_timer); + qemu_bh_cancel(s->async_bh); + + if (s->uport.dev && s->uport.dev->attached) { + usb_detach(&s->uport); + } + + dwc2_bus_stop(s); + + s->gotgctl = GOTGCTL_BSESVLD | GOTGCTL_ASESVLD | GOTGCTL_CONID_B; + s->gotgint = 0; + s->gahbcfg = 0; + s->gusbcfg = 5 << GUSBCFG_USBTRDTIM_SHIFT; + s->grstctl = GRSTCTL_AHBIDLE; + s->gintsts = GINTSTS_CONIDSTSCHNG | GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP | + GINTSTS_CURMODE_HOST; + s->gintmsk = 0; + s->grxstsr = 0; + s->grxstsp = 0; + s->grxfsiz = 1024; + s->gnptxfsiz = 1024 << FIFOSIZE_DEPTH_SHIFT; + s->gnptxsts = (4 << FIFOSIZE_DEPTH_SHIFT) | 1024; + s->gi2cctl = GI2CCTL_I2CDATSE0 | GI2CCTL_ACK; + s->gpvndctl = 0; + s->ggpio = 0; + s->guid = 0; + s->gsnpsid = 0x4f54294a; + s->ghwcfg1 = 0; + s->ghwcfg2 = (8 << GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT) | + (4 << GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT) | + (4 << GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT) | + GHWCFG2_DYNAMIC_FIFO | + GHWCFG2_PERIO_EP_SUPPORTED | + ((DWC2_NB_CHAN - 1) << GHWCFG2_NUM_HOST_CHAN_SHIFT) | + (GHWCFG2_INT_DMA_ARCH << GHWCFG2_ARCHITECTURE_SHIFT) | + (GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST << GHWCFG2_OP_MODE_SHIFT); + s->ghwcfg3 = (4096 << GHWCFG3_DFIFO_DEPTH_SHIFT) | + (4 << GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT) | + (4 << GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT); + s->ghwcfg4 = 0; + s->glpmcfg = 0; + s->gpwrdn = GPWRDN_PWRDNRSTN; + s->gdfifocfg = 0; + s->gadpctl = 0; + s->grefclk = 0; + s->gintmsk2 = 0; + s->gintsts2 = 0; + + s->hptxfsiz = 500 << FIFOSIZE_DEPTH_SHIFT; + + s->hcfg = 2 << HCFG_RESVALID_SHIFT; + s->hfir = 60000; + s->hfnum = 0x3fff; + s->hptxsts = (16 << TXSTS_QSPCAVAIL_SHIFT) | 32768; + s->haint = 0; + s->haintmsk = 0; + s->hprt0 = 0; + + memset(s->hreg1, 0, sizeof(s->hreg1)); + memset(s->pcgreg, 0, sizeof(s->pcgreg)); + + s->sof_time = 0; + s->frame_number = 0; + s->fi = USB_FRMINTVL - 1; + s->next_chan = 0; + s->working = false; + + for (i = 0; i < DWC2_NB_CHAN; i++) { + s->packet[i].needs_service = false; + } +} + +static void dwc2_reset_hold(Object *obj) +{ + DWC2Class *c = DWC2_USB_GET_CLASS(obj); + DWC2State *s = DWC2_USB(obj); + + trace_usb_dwc2_reset_hold(); + + if (c->parent_phases.hold) { + c->parent_phases.hold(obj); + } + + dwc2_update_irq(s); +} + +static void dwc2_reset_exit(Object *obj) +{ + DWC2Class *c = DWC2_USB_GET_CLASS(obj); + DWC2State *s = DWC2_USB(obj); + + trace_usb_dwc2_reset_exit(); + + if (c->parent_phases.exit) { + c->parent_phases.exit(obj); + } + + s->hprt0 = HPRT0_PWR; + if (s->uport.dev && s->uport.dev->attached) { + usb_attach(&s->uport); + usb_device_reset(s->uport.dev); + } +} + +static void dwc2_realize(DeviceState *dev, Error **errp) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + DWC2State *s = DWC2_USB(dev); + Object *obj; + + obj = object_property_get_link(OBJECT(dev), "dma-mr", &error_abort); + + s->dma_mr = MEMORY_REGION(obj); + address_space_init(&s->dma_as, s->dma_mr, "dwc2"); + + usb_bus_new(&s->bus, sizeof(s->bus), &dwc2_bus_ops, dev); + usb_register_port(&s->bus, &s->uport, s, 0, &dwc2_port_ops, + USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL | + (s->usb_version == 2 ? USB_SPEED_MASK_HIGH : 0)); + s->uport.dev = 0; + + s->usb_frame_time = NANOSECONDS_PER_SECOND / 1000; /* 1000000 */ + if (NANOSECONDS_PER_SECOND >= USB_HZ_FS) { + s->usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ_FS; /* 83.3 */ + } else { + s->usb_bit_time = 1; + } + + s->fi = USB_FRMINTVL - 1; + s->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, dwc2_frame_boundary, s); + s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, dwc2_work_timer, s); + s->async_bh = qemu_bh_new(dwc2_work_bh, s); + + sysbus_init_irq(sbd, &s->irq); +} + +static void dwc2_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + DWC2State *s = DWC2_USB(obj); + + memory_region_init(&s->container, obj, "dwc2", DWC2_MMIO_SIZE); + sysbus_init_mmio(sbd, &s->container); + + memory_region_init_io(&s->hsotg, obj, &dwc2_mmio_hsotg_ops, s, + "dwc2-io", 4 * KiB); + memory_region_add_subregion(&s->container, 0x0000, &s->hsotg); + + memory_region_init_io(&s->fifos, obj, &dwc2_mmio_hreg2_ops, s, + "dwc2-fifo", 64 * KiB); + memory_region_add_subregion(&s->container, 0x1000, &s->fifos); +} + +static const VMStateDescription vmstate_dwc2_state_packet = { + .name = "dwc2/packet", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(devadr, DWC2Packet), + VMSTATE_UINT32(epnum, DWC2Packet), + VMSTATE_UINT32(epdir, DWC2Packet), + VMSTATE_UINT32(mps, DWC2Packet), + VMSTATE_UINT32(pid, DWC2Packet), + VMSTATE_UINT32(index, DWC2Packet), + VMSTATE_UINT32(pcnt, DWC2Packet), + VMSTATE_UINT32(len, DWC2Packet), + VMSTATE_INT32(async, DWC2Packet), + VMSTATE_BOOL(small, DWC2Packet), + VMSTATE_BOOL(needs_service, DWC2Packet), + VMSTATE_END_OF_LIST() + }, +}; + +const VMStateDescription vmstate_dwc2_state = { + .name = "dwc2", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(glbreg, DWC2State, + DWC2_GLBREG_SIZE / sizeof(uint32_t)), + VMSTATE_UINT32_ARRAY(fszreg, DWC2State, + DWC2_FSZREG_SIZE / sizeof(uint32_t)), + VMSTATE_UINT32_ARRAY(hreg0, DWC2State, + DWC2_HREG0_SIZE / sizeof(uint32_t)), + VMSTATE_UINT32_ARRAY(hreg1, DWC2State, + DWC2_HREG1_SIZE / sizeof(uint32_t)), + VMSTATE_UINT32_ARRAY(pcgreg, DWC2State, + DWC2_PCGREG_SIZE / sizeof(uint32_t)), + + VMSTATE_TIMER_PTR(eof_timer, DWC2State), + VMSTATE_TIMER_PTR(frame_timer, DWC2State), + VMSTATE_INT64(sof_time, DWC2State), + VMSTATE_INT64(usb_frame_time, DWC2State), + VMSTATE_INT64(usb_bit_time, DWC2State), + VMSTATE_UINT32(usb_version, DWC2State), + VMSTATE_UINT16(frame_number, DWC2State), + VMSTATE_UINT16(fi, DWC2State), + VMSTATE_UINT16(next_chan, DWC2State), + VMSTATE_BOOL(working, DWC2State), + + VMSTATE_STRUCT_ARRAY(packet, DWC2State, DWC2_NB_CHAN, 1, + vmstate_dwc2_state_packet, DWC2Packet), + VMSTATE_UINT8_2DARRAY(usb_buf, DWC2State, DWC2_NB_CHAN, + DWC2_MAX_XFER_SIZE), + + VMSTATE_END_OF_LIST() + } +}; + +static Property dwc2_usb_properties[] = { + DEFINE_PROP_UINT32("usb_version", DWC2State, usb_version, 2), + DEFINE_PROP_END_OF_LIST(), +}; + +static void dwc2_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + DWC2Class *c = DWC2_USB_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); + + dc->realize = dwc2_realize; + dc->vmsd = &vmstate_dwc2_state; + set_bit(DEVICE_CATEGORY_USB, dc->categories); + device_class_set_props(dc, dwc2_usb_properties); + resettable_class_set_parent_phases(rc, dwc2_reset_enter, dwc2_reset_hold, + dwc2_reset_exit, &c->parent_phases); +} + +static const TypeInfo dwc2_usb_type_info = { + .name = TYPE_DWC2_USB, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(DWC2State), + .instance_init = dwc2_init, + .class_size = sizeof(DWC2Class), + .class_init = dwc2_class_init, +}; + +static void dwc2_usb_register_types(void) +{ + type_register_static(&dwc2_usb_type_info); +} + +type_init(dwc2_usb_register_types) diff --git a/hw/usb/hcd-dwc2.h b/hw/usb/hcd-dwc2.h new file mode 100644 index 0000000000000000000000000000000000000000..6998b04706dac1e0c70726282bde36d9476d04f7 --- /dev/null +++ b/hw/usb/hcd-dwc2.h @@ -0,0 +1,186 @@ +/* + * dwc-hsotg (dwc2) USB host controller state definitions + * + * Based on hw/usb/hcd-ehci.h + * + * Copyright (c) 2020 Paul Zimmerman + * + * 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. + */ + +#ifndef HW_USB_DWC2_H +#define HW_USB_DWC2_H + +#include "qemu/timer.h" +#include "hw/irq.h" +#include "hw/sysbus.h" +#include "hw/usb.h" +#include "sysemu/dma.h" +#include "qom/object.h" + +#define DWC2_MMIO_SIZE 0x11000 + +#define DWC2_NB_CHAN 8 /* Number of host channels */ +#define DWC2_MAX_XFER_SIZE 65536 /* Max transfer size expected in HCTSIZ */ + +typedef struct DWC2Packet DWC2Packet; +typedef struct DWC2State DWC2State; +typedef struct DWC2Class DWC2Class; + +enum async_state { + DWC2_ASYNC_NONE = 0, + DWC2_ASYNC_INITIALIZED, + DWC2_ASYNC_INFLIGHT, + DWC2_ASYNC_FINISHED, +}; + +struct DWC2Packet { + USBPacket packet; + uint32_t devadr; + uint32_t epnum; + uint32_t epdir; + uint32_t mps; + uint32_t pid; + uint32_t index; + uint32_t pcnt; + uint32_t len; + int32_t async; + bool small; + bool needs_service; +}; + +struct DWC2State { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + USBBus bus; + qemu_irq irq; + MemoryRegion *dma_mr; + AddressSpace dma_as; + MemoryRegion container; + MemoryRegion hsotg; + MemoryRegion fifos; + + union { +#define DWC2_GLBREG_SIZE 0x70 + uint32_t glbreg[DWC2_GLBREG_SIZE / sizeof(uint32_t)]; + struct { + uint32_t gotgctl; /* 00 */ + uint32_t gotgint; /* 04 */ + uint32_t gahbcfg; /* 08 */ + uint32_t gusbcfg; /* 0c */ + uint32_t grstctl; /* 10 */ + uint32_t gintsts; /* 14 */ + uint32_t gintmsk; /* 18 */ + uint32_t grxstsr; /* 1c */ + uint32_t grxstsp; /* 20 */ + uint32_t grxfsiz; /* 24 */ + uint32_t gnptxfsiz; /* 28 */ + uint32_t gnptxsts; /* 2c */ + uint32_t gi2cctl; /* 30 */ + uint32_t gpvndctl; /* 34 */ + uint32_t ggpio; /* 38 */ + uint32_t guid; /* 3c */ + uint32_t gsnpsid; /* 40 */ + uint32_t ghwcfg1; /* 44 */ + uint32_t ghwcfg2; /* 48 */ + uint32_t ghwcfg3; /* 4c */ + uint32_t ghwcfg4; /* 50 */ + uint32_t glpmcfg; /* 54 */ + uint32_t gpwrdn; /* 58 */ + uint32_t gdfifocfg; /* 5c */ + uint32_t gadpctl; /* 60 */ + uint32_t grefclk; /* 64 */ + uint32_t gintmsk2; /* 68 */ + uint32_t gintsts2; /* 6c */ + }; + }; + + union { +#define DWC2_FSZREG_SIZE 0x04 + uint32_t fszreg[DWC2_FSZREG_SIZE / sizeof(uint32_t)]; + struct { + uint32_t hptxfsiz; /* 100 */ + }; + }; + + union { +#define DWC2_HREG0_SIZE 0x44 + uint32_t hreg0[DWC2_HREG0_SIZE / sizeof(uint32_t)]; + struct { + uint32_t hcfg; /* 400 */ + uint32_t hfir; /* 404 */ + uint32_t hfnum; /* 408 */ + uint32_t rsvd0; /* 40c */ + uint32_t hptxsts; /* 410 */ + uint32_t haint; /* 414 */ + uint32_t haintmsk; /* 418 */ + uint32_t hflbaddr; /* 41c */ + uint32_t rsvd1[8]; /* 420-43c */ + uint32_t hprt0; /* 440 */ + }; + }; + +#define DWC2_HREG1_SIZE (0x20 * DWC2_NB_CHAN) + uint32_t hreg1[DWC2_HREG1_SIZE / sizeof(uint32_t)]; + +#define hcchar(_ch) hreg1[((_ch) << 3) + 0] /* 500, 520, ... */ +#define hcsplt(_ch) hreg1[((_ch) << 3) + 1] /* 504, 524, ... */ +#define hcint(_ch) hreg1[((_ch) << 3) + 2] /* 508, 528, ... */ +#define hcintmsk(_ch) hreg1[((_ch) << 3) + 3] /* 50c, 52c, ... */ +#define hctsiz(_ch) hreg1[((_ch) << 3) + 4] /* 510, 530, ... */ +#define hcdma(_ch) hreg1[((_ch) << 3) + 5] /* 514, 534, ... */ +#define hcdmab(_ch) hreg1[((_ch) << 3) + 7] /* 51c, 53c, ... */ + + union { +#define DWC2_PCGREG_SIZE 0x08 + uint32_t pcgreg[DWC2_PCGREG_SIZE / sizeof(uint32_t)]; + struct { + uint32_t pcgctl; /* e00 */ + uint32_t pcgcctl1; /* e04 */ + }; + }; + + /* TODO - implement FIFO registers for slave mode */ +#define DWC2_HFIFO_SIZE (0x1000 * DWC2_NB_CHAN) + + /* + * Internal state + */ + QEMUTimer *eof_timer; + QEMUTimer *frame_timer; + QEMUBH *async_bh; + int64_t sof_time; + int64_t usb_frame_time; + int64_t usb_bit_time; + uint32_t usb_version; + uint16_t frame_number; + uint16_t fi; + uint16_t next_chan; + bool working; + USBPort uport; + DWC2Packet packet[DWC2_NB_CHAN]; /* one packet per chan */ + uint8_t usb_buf[DWC2_NB_CHAN][DWC2_MAX_XFER_SIZE]; /* one buffer per chan */ +}; + +struct DWC2Class { + /*< private >*/ + SysBusDeviceClass parent_class; + ResettablePhases parent_phases; + + /*< public >*/ +}; + +#define TYPE_DWC2_USB "dwc2-usb" +OBJECT_DECLARE_TYPE(DWC2State, DWC2Class, DWC2_USB) + +#endif diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c index 3730736540fcd05ec9e5d431a3ab8c46b3a9e872..e3758db1b18e49543dc3b99aa8a40bb95cc9126e 100644 --- a/hw/usb/hcd-ehci-sysbus.c +++ b/hw/usb/hcd-ehci-sysbus.c @@ -147,6 +147,24 @@ static const TypeInfo ehci_aw_h3_type_info = { .class_init = ehci_aw_h3_class_init, }; +static void ehci_npcm7xx_class_init(ObjectClass *oc, void *data) +{ + SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc); + DeviceClass *dc = DEVICE_CLASS(oc); + + sec->capsbase = 0x0; + sec->opregbase = 0x10; + sec->portscbase = 0x44; + sec->portnr = 1; + set_bit(DEVICE_CATEGORY_USB, dc->categories); +} + +static const TypeInfo ehci_npcm7xx_type_info = { + .name = TYPE_NPCM7XX_EHCI, + .parent = TYPE_SYS_BUS_EHCI, + .class_init = ehci_npcm7xx_class_init, +}; + static void ehci_tegra2_class_init(ObjectClass *oc, void *data) { SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc); @@ -269,6 +287,7 @@ static void ehci_sysbus_register_types(void) type_register_static(&ehci_platform_type_info); type_register_static(&ehci_exynos4210_type_info); type_register_static(&ehci_aw_h3_type_info); + type_register_static(&ehci_npcm7xx_type_info); type_register_static(&ehci_tegra2_type_info); type_register_static(&ehci_ppc4xx_type_info); type_register_static(&ehci_fusbh200_type_info); diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 1495e8f7fab1552aa94cf0344d6ac2e3200aae8f..ae7f20c502ac36a37cb08379f93e5747a72d2373 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -352,7 +352,6 @@ static void ehci_trace_sitd(EHCIState *s, hwaddr addr, static void ehci_trace_guest_bug(EHCIState *s, const char *message) { trace_usb_ehci_guest_bug(message); - warn_report("%s", message); } static inline bool ehci_enabled(EHCIState *s) @@ -1373,7 +1372,10 @@ static int ehci_execute(EHCIPacket *p, const char *action) spd = (p->pid == USB_TOKEN_IN && NLPTR_TBIT(p->qtd.altnext) == 0); usb_packet_setup(&p->packet, p->pid, ep, 0, p->qtdaddr, spd, (p->qtd.token & QTD_TOKEN_IOC) != 0); - usb_packet_map(&p->packet, &p->sgl); + if (usb_packet_map(&p->packet, &p->sgl)) { + qemu_sglist_destroy(&p->sgl); + return -1; + } p->async = EHCI_ASYNC_INITIALIZED; } @@ -1445,20 +1447,25 @@ static int ehci_process_itd(EHCIState *ehci, dev = ehci_find_device(ehci, devaddr); if (dev == NULL) { ehci_trace_guest_bug(ehci, "no device found"); - return -1; - } - pid = dir ? USB_TOKEN_IN : USB_TOKEN_OUT; - ep = usb_ep_get(dev, pid, endp); - if (ep && ep->type == USB_ENDPOINT_XFER_ISOC) { - usb_packet_setup(&ehci->ipacket, pid, ep, 0, addr, false, - (itd->transact[i] & ITD_XACT_IOC) != 0); - usb_packet_map(&ehci->ipacket, &ehci->isgl); - usb_handle_packet(dev, &ehci->ipacket); - usb_packet_unmap(&ehci->ipacket, &ehci->isgl); - } else { - DPRINTF("ISOCH: attempt to addess non-iso endpoint\n"); - ehci->ipacket.status = USB_RET_NAK; + ehci->ipacket.status = USB_RET_NODEV; ehci->ipacket.actual_length = 0; + } else { + pid = dir ? USB_TOKEN_IN : USB_TOKEN_OUT; + ep = usb_ep_get(dev, pid, endp); + if (ep && ep->type == USB_ENDPOINT_XFER_ISOC) { + usb_packet_setup(&ehci->ipacket, pid, ep, 0, addr, false, + (itd->transact[i] & ITD_XACT_IOC) != 0); + if (usb_packet_map(&ehci->ipacket, &ehci->isgl)) { + qemu_sglist_destroy(&ehci->isgl); + return -1; + } + usb_handle_packet(dev, &ehci->ipacket); + usb_packet_unmap(&ehci->ipacket, &ehci->isgl); + } else { + DPRINTF("ISOCH: attempt to addess non-iso endpoint\n"); + ehci->ipacket.status = USB_RET_NAK; + ehci->ipacket.actual_length = 0; + } } qemu_sglist_destroy(&ehci->isgl); diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h index 57b38cfc0548967b9cfe9ab9b61d21d243dd04fe..a173707d9bf81ca4752a6f28710d84b7af504775 100644 --- a/hw/usb/hcd-ehci.h +++ b/hw/usb/hcd-ehci.h @@ -23,6 +23,7 @@ #include "sysemu/dma.h" #include "hw/pci/pci.h" #include "hw/sysbus.h" +#include "qom/object.h" #ifndef EHCI_DEBUG #define EHCI_DEBUG 0 @@ -328,41 +329,37 @@ void usb_ehci_unrealize(EHCIState *s, DeviceState *dev); void ehci_reset(void *opaque); #define TYPE_PCI_EHCI "pci-ehci-usb" -#define PCI_EHCI(obj) OBJECT_CHECK(EHCIPCIState, (obj), TYPE_PCI_EHCI) +OBJECT_DECLARE_SIMPLE_TYPE(EHCIPCIState, PCI_EHCI) -typedef struct EHCIPCIState { +struct EHCIPCIState { /*< private >*/ PCIDevice pcidev; /*< public >*/ EHCIState ehci; -} EHCIPCIState; +}; #define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb" #define TYPE_PLATFORM_EHCI "platform-ehci-usb" #define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb" #define TYPE_AW_H3_EHCI "aw-h3-ehci-usb" +#define TYPE_NPCM7XX_EHCI "npcm7xx-ehci-usb" #define TYPE_TEGRA2_EHCI "tegra2-ehci-usb" #define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb" #define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb" -#define SYS_BUS_EHCI(obj) \ - OBJECT_CHECK(EHCISysBusState, (obj), TYPE_SYS_BUS_EHCI) -#define SYS_BUS_EHCI_CLASS(class) \ - OBJECT_CLASS_CHECK(SysBusEHCIClass, (class), TYPE_SYS_BUS_EHCI) -#define SYS_BUS_EHCI_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SysBusEHCIClass, (obj), TYPE_SYS_BUS_EHCI) +OBJECT_DECLARE_TYPE(EHCISysBusState, SysBusEHCIClass, SYS_BUS_EHCI) -typedef struct EHCISysBusState { +struct EHCISysBusState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ EHCIState ehci; -} EHCISysBusState; +}; -typedef struct SysBusEHCIClass { +struct SysBusEHCIClass { /*< private >*/ SysBusDeviceClass parent_class; /*< public >*/ @@ -371,17 +368,16 @@ typedef struct SysBusEHCIClass { uint16_t opregbase; uint16_t portscbase; uint16_t portnr; -} SysBusEHCIClass; +}; -#define FUSBH200_EHCI(obj) \ - OBJECT_CHECK(FUSBH200EHCIState, (obj), TYPE_FUSBH200_EHCI) +OBJECT_DECLARE_SIMPLE_TYPE(FUSBH200EHCIState, FUSBH200_EHCI) -typedef struct FUSBH200EHCIState { +struct FUSBH200EHCIState { /*< private >*/ EHCISysBusState parent_obj; /*< public >*/ MemoryRegion mem_vendor; -} FUSBH200EHCIState; +}; #endif diff --git a/hw/usb/hcd-musb.c b/hw/usb/hcd-musb.c index c29fbef6fc508e86a0ad16f42b3d7621789ab94e..85f5ff5bd48d9d6d3649939548b9ee891b3f0cd6 100644 --- a/hw/usb/hcd-musb.c +++ b/hw/usb/hcd-musb.c @@ -23,6 +23,7 @@ #include "qemu/osdep.h" #include "qemu/timer.h" #include "hw/usb.h" +#include "hw/usb/hcd-musb.h" #include "hw/irq.h" #include "hw/hw.h" @@ -1539,13 +1540,13 @@ static void musb_writew(void *opaque, hwaddr addr, uint32_t value) }; } -CPUReadMemoryFunc * const musb_read[] = { +MUSBReadFunc * const musb_read[] = { musb_readb, musb_readh, musb_readw, }; -CPUWriteMemoryFunc * const musb_write[] = { +MUSBWriteFunc * const musb_write[] = { musb_writeb, musb_writeh, musb_writew, diff --git a/hw/usb/hcd-ohci-pci.c b/hw/usb/hcd-ohci-pci.c index a7fb1666af90b52f1165c278dc6ce827695d92e2..f95199e0bbcff257a4f08a2672b12b9417a6d6db 100644 --- a/hw/usb/hcd-ohci-pci.c +++ b/hw/usb/hcd-ohci-pci.c @@ -29,11 +29,12 @@ #include "hw/qdev-properties.h" #include "trace.h" #include "hcd-ohci.h" +#include "qom/object.h" #define TYPE_PCI_OHCI "pci-ohci" -#define PCI_OHCI(obj) OBJECT_CHECK(OHCIPCIState, (obj), TYPE_PCI_OHCI) +OBJECT_DECLARE_SIMPLE_TYPE(OHCIPCIState, PCI_OHCI) -typedef struct { +struct OHCIPCIState { /*< private >*/ PCIDevice parent_obj; /*< public >*/ @@ -42,7 +43,7 @@ typedef struct { char *masterbus; uint32_t num_ports; uint32_t firstport; -} OHCIPCIState; +}; /** * A typical PCI OHCI will additionally set PERR in its configspace to diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 1e6e85e86a8d721618724013763dd9b1d60d829c..f8c64c8b95bb16e5f3d2105dc85e61cb9ece0b8a 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -691,6 +691,10 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, the next ISO TD of the same ED */ trace_usb_ohci_iso_td_relative_frame_number_big(relative_frame_number, frame_count); + if (OHCI_CC_DATAOVERRUN == OHCI_BM(iso_td.flags, TD_CC)) { + /* avoid infinite loop */ + return 1; + } OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN); ed->head &= ~OHCI_DPTR_MASK; ed->head |= (iso_td.next & OHCI_DPTR_MASK); @@ -731,7 +735,11 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, } start_offset = iso_td.offset[relative_frame_number]; - next_offset = iso_td.offset[relative_frame_number + 1]; + if (relative_frame_number < frame_count) { + next_offset = iso_td.offset[relative_frame_number + 1]; + } else { + next_offset = iso_td.be; + } if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) || ((relative_frame_number < frame_count) && @@ -764,7 +772,12 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, } } else { /* Last packet in the ISO TD */ - end_addr = iso_td.be; + end_addr = next_offset; + } + + if (start_addr > end_addr) { + trace_usb_ohci_iso_td_bad_cc_overrun(start_addr, end_addr); + return 1; } if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) { @@ -773,6 +786,9 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, } else { len = end_addr - start_addr + 1; } + if (len > sizeof(ohci->usb_buf)) { + len = sizeof(ohci->usb_buf); + } if (len && dir != OHCI_TD_DIR_IN) { if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len, @@ -975,8 +991,16 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) { len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff); } else { + if (td.cbp > td.be) { + trace_usb_ohci_iso_td_bad_cc_overrun(td.cbp, td.be); + ohci_die(ohci); + return 1; + } len = (td.be - td.cbp) + 1; } + if (len > sizeof(ohci->usb_buf)) { + len = sizeof(ohci->usb_buf); + } pktlen = len; if (len && dir != OHCI_TD_DIR_IN) { diff --git a/hw/usb/hcd-ohci.h b/hw/usb/hcd-ohci.h index 5c8819aedf90ac9f0411d13f970154c0402395da..11ac57058d1cd72029b7def1281c858e22f2db43 100644 --- a/hw/usb/hcd-ohci.h +++ b/hw/usb/hcd-ohci.h @@ -23,6 +23,7 @@ #include "sysemu/dma.h" #include "hw/usb.h" +#include "qom/object.h" /* Number of Downstream Ports on the root hub: */ #define OHCI_MAX_PORTS 15 @@ -92,9 +93,9 @@ typedef struct OHCIState { } OHCIState; #define TYPE_SYSBUS_OHCI "sysbus-ohci" -#define SYSBUS_OHCI(obj) OBJECT_CHECK(OHCISysBusState, (obj), TYPE_SYSBUS_OHCI) +OBJECT_DECLARE_SIMPLE_TYPE(OHCISysBusState, SYSBUS_OHCI) -typedef struct { +struct OHCISysBusState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -104,7 +105,7 @@ typedef struct { uint32_t num_ports; uint32_t firstport; dma_addr_t dma_offset; -} OHCISysBusState; +}; extern const VMStateDescription vmstate_ohci_state; diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 37f7beb3fa2207eb5dae4ff1d76a0c493cf9d01f..27ca237d71fb85d35520998174bead9b6d81c324 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -39,6 +39,7 @@ #include "trace.h" #include "qemu/main-loop.h" #include "qemu/module.h" +#include "qom/object.h" #define FRAME_TIMER_FREQ 1000 @@ -160,7 +161,8 @@ static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td); static void uhci_resume(void *opaque); #define TYPE_UHCI "pci-uhci-usb" -#define UHCI(obj) OBJECT_CHECK(UHCIState, (obj), TYPE_UHCI) +DECLARE_INSTANCE_CHECKER(UHCIState, UHCI, + TYPE_UHCI) static inline int32_t uhci_queue_token(UHCI_TD *td) { diff --git a/hw/usb/hcd-xhci-nec.c b/hw/usb/hcd-xhci-nec.c index e6a5a22b6d50ba4402c6ad8259cf77babb3819a7..13c9ac5dbd17ac75492942a9dd4c0230c3cac7c7 100644 --- a/hw/usb/hcd-xhci-nec.c +++ b/hw/usb/hcd-xhci-nec.c @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,20 +25,39 @@ #include "hw/pci/pci.h" #include "hw/qdev-properties.h" -#include "hcd-xhci.h" +#include "hcd-xhci-pci.h" + +typedef struct XHCINecState { + /*< private >*/ + XHCIPciState parent_obj; + /*< public >*/ + uint32_t flags; + uint32_t intrs; + uint32_t slots; +} XHCINecState; static Property nec_xhci_properties[] = { - DEFINE_PROP_ON_OFF_AUTO("msi", XHCIState, msi, ON_OFF_AUTO_AUTO), - DEFINE_PROP_ON_OFF_AUTO("msix", XHCIState, msix, ON_OFF_AUTO_AUTO), - DEFINE_PROP_BIT("superspeed-ports-first", - XHCIState, flags, XHCI_FLAG_SS_FIRST, true), - DEFINE_PROP_BIT("force-pcie-endcap", XHCIState, flags, + DEFINE_PROP_ON_OFF_AUTO("msi", XHCIPciState, msi, ON_OFF_AUTO_AUTO), + DEFINE_PROP_ON_OFF_AUTO("msix", XHCIPciState, msix, ON_OFF_AUTO_AUTO), + DEFINE_PROP_BIT("superspeed-ports-first", XHCINecState, flags, + XHCI_FLAG_SS_FIRST, true), + DEFINE_PROP_BIT("force-pcie-endcap", XHCINecState, flags, XHCI_FLAG_FORCE_PCIE_ENDCAP, false), - DEFINE_PROP_UINT32("intrs", XHCIState, numintrs, MAXINTRS), - DEFINE_PROP_UINT32("slots", XHCIState, numslots, MAXSLOTS), + DEFINE_PROP_UINT32("intrs", XHCINecState, intrs, XHCI_MAXINTRS), + DEFINE_PROP_UINT32("slots", XHCINecState, slots, XHCI_MAXSLOTS), DEFINE_PROP_END_OF_LIST(), }; +static void nec_xhci_instance_init(Object *obj) +{ + XHCIPciState *pci = XHCI_PCI(obj); + XHCINecState *nec = container_of(pci, XHCINecState, parent_obj); + + pci->xhci.flags = nec->flags; + pci->xhci.numintrs = nec->intrs; + pci->xhci.numslots = nec->slots; +} + static void nec_xhci_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); @@ -52,7 +71,9 @@ static void nec_xhci_class_init(ObjectClass *klass, void *data) static const TypeInfo nec_xhci_info = { .name = TYPE_NEC_XHCI, - .parent = TYPE_XHCI, + .parent = TYPE_XHCI_PCI, + .instance_size = sizeof(XHCINecState), + .instance_init = nec_xhci_instance_init, .class_init = nec_xhci_class_init, }; diff --git a/hw/usb/hcd-xhci-pci.c b/hw/usb/hcd-xhci-pci.c new file mode 100644 index 0000000000000000000000000000000000000000..bba628d3d230d75194d444be6fdb4e7f7c95ed41 --- /dev/null +++ b/hw/usb/hcd-xhci-pci.c @@ -0,0 +1,261 @@ +/* + * USB xHCI controller with PCI bus emulation + * + * SPDX-FileCopyrightText: 2011 Securiforest + * SPDX-FileContributor: Hector Martin + * SPDX-sourceInfo: Based on usb-ohci.c, emulates Renesas NEC USB 3.0 + * SPDX-FileCopyrightText: 2020 Xilinx + * SPDX-FileContributor: Sai Pavan Boddu + * SPDX-sourceInfo: Moved the pci specific content for hcd-xhci.c to + * hcd-xhci-pci.c + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#include "qemu/osdep.h" +#include "hw/pci/pci.h" +#include "hw/qdev-properties.h" +#include "migration/vmstate.h" +#include "hw/pci/msi.h" +#include "hw/pci/msix.h" +#include "hcd-xhci-pci.h" +#include "trace.h" +#include "qapi/error.h" + +#define OFF_MSIX_TABLE 0x3000 +#define OFF_MSIX_PBA 0x3800 + +static void xhci_pci_intr_update(XHCIState *xhci, int n, bool enable) +{ + XHCIPciState *s = container_of(xhci, XHCIPciState, xhci); + PCIDevice *pci_dev = PCI_DEVICE(s); + + if (!msix_enabled(pci_dev)) { + return; + } + if (enable == !!xhci->intr[n].msix_used) { + return; + } + if (enable) { + trace_usb_xhci_irq_msix_use(n); + msix_vector_use(pci_dev, n); + xhci->intr[n].msix_used = true; + } else { + trace_usb_xhci_irq_msix_unuse(n); + msix_vector_unuse(pci_dev, n); + xhci->intr[n].msix_used = false; + } +} + +static void xhci_pci_intr_raise(XHCIState *xhci, int n, bool level) +{ + XHCIPciState *s = container_of(xhci, XHCIPciState, xhci); + PCIDevice *pci_dev = PCI_DEVICE(s); + + if (n == 0 && + !(msix_enabled(pci_dev) || + msi_enabled(pci_dev))) { + pci_set_irq(pci_dev, level); + } + if (msix_enabled(pci_dev)) { + msix_notify(pci_dev, n); + return; + } + + if (msi_enabled(pci_dev)) { + msi_notify(pci_dev, n); + return; + } +} + +static void xhci_pci_reset(DeviceState *dev) +{ + XHCIPciState *s = XHCI_PCI(dev); + + device_legacy_reset(DEVICE(&s->xhci)); +} + +static int xhci_pci_vmstate_post_load(void *opaque, int version_id) +{ + XHCIPciState *s = XHCI_PCI(opaque); + PCIDevice *pci_dev = PCI_DEVICE(s); + int intr; + + for (intr = 0; intr < s->xhci.numintrs; intr++) { + if (s->xhci.intr[intr].msix_used) { + msix_vector_use(pci_dev, intr); + } else { + msix_vector_unuse(pci_dev, intr); + } + } + return 0; +} + +static void usb_xhci_pci_realize(struct PCIDevice *dev, Error **errp) +{ + int ret; + Error *err = NULL; + XHCIPciState *s = XHCI_PCI(dev); + + dev->config[PCI_CLASS_PROG] = 0x30; /* xHCI */ + dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin 1 */ + dev->config[PCI_CACHE_LINE_SIZE] = 0x10; + dev->config[0x60] = 0x30; /* release number */ + + object_property_set_link(OBJECT(&s->xhci), "host", OBJECT(s), NULL); + s->xhci.intr_update = xhci_pci_intr_update; + s->xhci.intr_raise = xhci_pci_intr_raise; + object_property_set_bool(OBJECT(&s->xhci), "realized", true, &err); + if (err) { + error_propagate(errp, err); + return; + } + if (strcmp(object_get_typename(OBJECT(dev)), TYPE_NEC_XHCI) == 0) { + s->xhci.nec_quirks = true; + } + + if (s->msi != ON_OFF_AUTO_OFF) { + ret = msi_init(dev, 0x70, s->xhci.numintrs, true, false, &err); + /* + * Any error other than -ENOTSUP(board's MSI support is broken) + * is a programming error + */ + assert(!ret || ret == -ENOTSUP); + if (ret && s->msi == ON_OFF_AUTO_ON) { + /* Can't satisfy user's explicit msi=on request, fail */ + error_append_hint(&err, "You have to use msi=auto (default) or " + "msi=off with this machine type.\n"); + error_propagate(errp, err); + return; + } + assert(!err || s->msi == ON_OFF_AUTO_AUTO); + /* With msi=auto, we fall back to MSI off silently */ + error_free(err); + } + pci_register_bar(dev, 0, + PCI_BASE_ADDRESS_SPACE_MEMORY | + PCI_BASE_ADDRESS_MEM_TYPE_64, + &s->xhci.mem); + + if (pci_bus_is_express(pci_get_bus(dev)) || + xhci_get_flag(&s->xhci, XHCI_FLAG_FORCE_PCIE_ENDCAP)) { + ret = pcie_endpoint_cap_init(dev, 0xa0); + assert(ret > 0); + } + + if (s->msix != ON_OFF_AUTO_OFF) { + /* TODO check for errors, and should fail when msix=on */ + msix_init(dev, s->xhci.numintrs, + &s->xhci.mem, 0, OFF_MSIX_TABLE, + &s->xhci.mem, 0, OFF_MSIX_PBA, + 0x90, NULL); + } + s->xhci.as = pci_get_address_space(dev); +} + +static void usb_xhci_pci_exit(PCIDevice *dev) +{ + XHCIPciState *s = XHCI_PCI(dev); + /* destroy msix memory region */ + if (dev->msix_table && dev->msix_pba + && dev->msix_entry_used) { + msix_uninit(dev, &s->xhci.mem, &s->xhci.mem); + } +} + +static const VMStateDescription vmstate_xhci_pci = { + .name = "xhci", + .version_id = 1, + .post_load = xhci_pci_vmstate_post_load, + .fields = (VMStateField[]) { + VMSTATE_PCI_DEVICE(parent_obj, XHCIPciState), + VMSTATE_MSIX(parent_obj, XHCIPciState), + VMSTATE_STRUCT(xhci, XHCIPciState, 1, vmstate_xhci, XHCIState), + VMSTATE_END_OF_LIST() + } +}; + +static void xhci_instance_init(Object *obj) +{ + XHCIPciState *s = XHCI_PCI(obj); + /* + * QEMU_PCI_CAP_EXPRESS initialization does not depend on QEMU command + * line, therefore, no need to wait to realize like other devices + */ + PCI_DEVICE(obj)->cap_present |= QEMU_PCI_CAP_EXPRESS; + object_initialize_child(obj, "xhci-core", &s->xhci, TYPE_XHCI); + qdev_alias_all_properties(DEVICE(&s->xhci), obj); +} + +static void xhci_class_init(ObjectClass *klass, void *data) +{ + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = xhci_pci_reset; + dc->vmsd = &vmstate_xhci_pci; + set_bit(DEVICE_CATEGORY_USB, dc->categories); + k->realize = usb_xhci_pci_realize; + k->exit = usb_xhci_pci_exit; + k->class_id = PCI_CLASS_SERIAL_USB; +} + +static const TypeInfo xhci_pci_info = { + .name = TYPE_XHCI_PCI, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(XHCIPciState), + .class_init = xhci_class_init, + .instance_init = xhci_instance_init, + .abstract = true, + .interfaces = (InterfaceInfo[]) { + { INTERFACE_PCIE_DEVICE }, + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { } + }, +}; + +static void qemu_xhci_class_init(ObjectClass *klass, void *data) +{ + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->vendor_id = PCI_VENDOR_ID_REDHAT; + k->device_id = PCI_DEVICE_ID_REDHAT_XHCI; + k->revision = 0x01; +} + +static void qemu_xhci_instance_init(Object *obj) +{ + XHCIPciState *s = XHCI_PCI(obj); + XHCIState *xhci = &s->xhci; + + s->msi = ON_OFF_AUTO_OFF; + s->msix = ON_OFF_AUTO_AUTO; + xhci->numintrs = XHCI_MAXINTRS; + xhci->numslots = XHCI_MAXSLOTS; + xhci_set_flag(xhci, XHCI_FLAG_SS_FIRST); +} + +static const TypeInfo qemu_xhci_info = { + .name = TYPE_QEMU_XHCI, + .parent = TYPE_XHCI_PCI, + .class_init = qemu_xhci_class_init, + .instance_init = qemu_xhci_instance_init, +}; + +static void xhci_register_types(void) +{ + type_register_static(&xhci_pci_info); + type_register_static(&qemu_xhci_info); +} + +type_init(xhci_register_types) diff --git a/hw/usb/hcd-xhci-pci.h b/hw/usb/hcd-xhci-pci.h new file mode 100644 index 0000000000000000000000000000000000000000..c193f794439ca58f5eb5444452082d8f3a5d0d2f --- /dev/null +++ b/hw/usb/hcd-xhci-pci.h @@ -0,0 +1,44 @@ +/* + * USB xHCI controller emulation + * + * Copyright (c) 2011 Securiforest + * Date: 2011-05-11 ; Author: Hector Martin + * Based on usb-ohci.c, emulates Renesas NEC USB 3.0 + * Date: 2020-01-1; Author: Sai Pavan Boddu + * PCI hooks are moved from XHCIState to XHCIPciState + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef HW_USB_HCD_XHCI_PCI_H +#define HW_USB_HCD_XHCI_PCI_H + +#include "hw/usb.h" +#include "hcd-xhci.h" + +#define TYPE_XHCI_PCI "pci-xhci" +#define XHCI_PCI(obj) \ + OBJECT_CHECK(XHCIPciState, (obj), TYPE_XHCI_PCI) + + +typedef struct XHCIPciState { + /*< private >*/ + PCIDevice parent_obj; + /*< public >*/ + XHCIState xhci; + OnOffAuto msi; + OnOffAuto msix; +} XHCIPciState; + +#endif diff --git a/hw/usb/hcd-xhci-sysbus.c b/hw/usb/hcd-xhci-sysbus.c new file mode 100644 index 0000000000000000000000000000000000000000..29185d2261fb82522e13fa9457684084a7146f75 --- /dev/null +++ b/hw/usb/hcd-xhci-sysbus.c @@ -0,0 +1,124 @@ +/* + * USB xHCI controller for system-bus interface + * Based on hcd-echi-sysbus.c + + * SPDX-FileCopyrightText: 2020 Xilinx + * SPDX-FileContributor: Author: Sai Pavan Boddu + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include "qemu/osdep.h" +#include "hw/qdev-properties.h" +#include "migration/vmstate.h" +#include "trace.h" +#include "qapi/error.h" +#include "hcd-xhci-sysbus.h" +#include "hw/acpi/aml-build.h" +#include "hw/irq.h" + +static void xhci_sysbus_intr_raise(XHCIState *xhci, int n, bool level) +{ + XHCISysbusState *s = container_of(xhci, XHCISysbusState, xhci); + + qemu_set_irq(s->irq[n], level); +} + +void xhci_sysbus_reset(DeviceState *dev) +{ + XHCISysbusState *s = XHCI_SYSBUS(dev); + + device_legacy_reset(DEVICE(&s->xhci)); +} + +static void xhci_sysbus_realize(DeviceState *dev, Error **errp) +{ + XHCISysbusState *s = XHCI_SYSBUS(dev); + Error *err = NULL; + + object_property_set_link(OBJECT(&s->xhci), "host", OBJECT(s), NULL); + object_property_set_bool(OBJECT(&s->xhci), "realized", true, &err); + if (err) { + error_propagate(errp, err); + return; + } + s->irq = g_new0(qemu_irq, s->xhci.numintrs); + qdev_init_gpio_out_named(dev, s->irq, SYSBUS_DEVICE_GPIO_IRQ, + s->xhci.numintrs); + if (s->xhci.dma_mr) { + s->xhci.as = g_malloc0(sizeof(AddressSpace)); + address_space_init(s->xhci.as, s->xhci.dma_mr, NULL); + } else { + s->xhci.as = &address_space_memory; + } + + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->xhci.mem); +} + +static void xhci_sysbus_instance_init(Object *obj) +{ + XHCISysbusState *s = XHCI_SYSBUS(obj); + + object_initialize_child(obj, "xhci-core", &s->xhci, TYPE_XHCI); + qdev_alias_all_properties(DEVICE(&s->xhci), obj); + + object_property_add_link(obj, "dma", TYPE_MEMORY_REGION, + (Object **)&s->xhci.dma_mr, + qdev_prop_allow_set_link_before_realize, + OBJ_PROP_LINK_STRONG); + s->xhci.intr_update = NULL; + s->xhci.intr_raise = xhci_sysbus_intr_raise; +} + +void xhci_sysbus_build_aml(Aml *scope, uint32_t mmio, unsigned int irq) +{ + Aml *dev = aml_device("XHCI"); + Aml *crs = aml_resource_template(); + + aml_append(crs, aml_memory32_fixed(mmio, XHCI_LEN_REGS, AML_READ_WRITE)); + aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, &irq, 1)); + + aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0D10"))); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); +} + +static Property xhci_sysbus_props[] = { + DEFINE_PROP_UINT32("intrs", XHCISysbusState, xhci.numintrs, XHCI_MAXINTRS), + DEFINE_PROP_UINT32("slots", XHCISysbusState, xhci.numslots, XHCI_MAXSLOTS), + DEFINE_PROP_END_OF_LIST(), +}; + +static const VMStateDescription vmstate_xhci_sysbus = { + .name = "xhci-sysbus", + .version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_STRUCT(xhci, XHCISysbusState, 1, vmstate_xhci, XHCIState), + VMSTATE_END_OF_LIST() + } +}; + +static void xhci_sysbus_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = xhci_sysbus_reset; + dc->realize = xhci_sysbus_realize; + dc->vmsd = &vmstate_xhci_sysbus; + device_class_set_props(dc, xhci_sysbus_props); +} + +static const TypeInfo xhci_sysbus_info = { + .name = TYPE_XHCI_SYSBUS, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(XHCISysbusState), + .class_init = xhci_sysbus_class_init, + .instance_init = xhci_sysbus_instance_init +}; + +static void xhci_sysbus_register_types(void) +{ + type_register_static(&xhci_sysbus_info); +} + +type_init(xhci_sysbus_register_types); diff --git a/hw/usb/hcd-xhci-sysbus.h b/hw/usb/hcd-xhci-sysbus.h new file mode 100644 index 0000000000000000000000000000000000000000..fdfcbbee3bf4cbe1cfbc91713c9ba6941422a35f --- /dev/null +++ b/hw/usb/hcd-xhci-sysbus.h @@ -0,0 +1,31 @@ +/* + * USB xHCI controller for system-bus interface + * + * SPDX-FileCopyrightText: 2020 Xilinx + * SPDX-FileContributor: Author: Sai Pavan Boddu + * SPDX-sourceInfo: Based on hcd-echi-sysbus + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_USB_HCD_XHCI_SYSBUS_H +#define HW_USB_HCD_XHCI_SYSBUS_H + +#include "hw/usb.h" +#include "hcd-xhci.h" +#include "hw/sysbus.h" + +#define XHCI_SYSBUS(obj) \ + OBJECT_CHECK(XHCISysbusState, (obj), TYPE_XHCI_SYSBUS) + + +typedef struct XHCISysbusState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + XHCIState xhci; + qemu_irq *irq; +} XHCISysbusState; + +void xhci_sysbus_reset(DeviceState *dev); +#endif diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index b330e36fe6cc69a3b47ddd51ccbae0fc9d1657c8..9ce7ca706e3beff96cde32ddded31a75b665b083 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -23,12 +23,8 @@ #include "qemu/timer.h" #include "qemu/module.h" #include "qemu/queue.h" -#include "hw/usb.h" #include "migration/vmstate.h" -#include "hw/pci/pci.h" #include "hw/qdev-properties.h" -#include "hw/pci/msi.h" -#include "hw/pci/msix.h" #include "trace.h" #include "qapi/error.h" @@ -50,17 +46,13 @@ #define TRANSFER_LIMIT 256 #define LEN_CAP 0x40 -#define LEN_OPER (0x400 + 0x10 * MAXPORTS) -#define LEN_RUNTIME ((MAXINTRS + 1) * 0x20) -#define LEN_DOORBELL ((MAXSLOTS + 1) * 0x20) +#define LEN_OPER (0x400 + 0x10 * XHCI_MAXPORTS) +#define LEN_RUNTIME ((XHCI_MAXINTRS + 1) * 0x20) +#define LEN_DOORBELL ((XHCI_MAXSLOTS + 1) * 0x20) #define OFF_OPER LEN_CAP #define OFF_RUNTIME 0x1000 #define OFF_DOORBELL 0x2000 -#define OFF_MSIX_TABLE 0x3000 -#define OFF_MSIX_PBA 0x3800 -/* must be power of 2 */ -#define LEN_REGS 0x4000 #if (OFF_OPER + LEN_OPER) > OFF_RUNTIME #error Increase OFF_RUNTIME @@ -68,8 +60,8 @@ #if (OFF_RUNTIME + LEN_RUNTIME) > OFF_DOORBELL #error Increase OFF_DOORBELL #endif -#if (OFF_DOORBELL + LEN_DOORBELL) > LEN_REGS -# error Increase LEN_REGS +#if (OFF_DOORBELL + LEN_DOORBELL) > XHCI_LEN_REGS +# error Increase XHCI_LEN_REGS #endif /* bit definitions */ @@ -429,12 +421,12 @@ static const char *ep_state_name(uint32_t state) ARRAY_SIZE(ep_state_names)); } -static bool xhci_get_flag(XHCIState *xhci, enum xhci_flags bit) +bool xhci_get_flag(XHCIState *xhci, enum xhci_flags bit) { return xhci->flags & (1 << bit); } -static void xhci_set_flag(XHCIState *xhci, enum xhci_flags bit) +void xhci_set_flag(XHCIState *xhci, enum xhci_flags bit) { xhci->flags |= (1 << bit); } @@ -495,7 +487,7 @@ static inline void xhci_dma_read_u32s(XHCIState *xhci, dma_addr_t addr, assert((len % sizeof(uint32_t)) == 0); - pci_dma_read(PCI_DEVICE(xhci), addr, buf, len); + dma_memory_read(xhci->as, addr, buf, len); for (i = 0; i < (len / sizeof(uint32_t)); i++) { buf[i] = le32_to_cpu(buf[i]); @@ -515,7 +507,7 @@ static inline void xhci_dma_write_u32s(XHCIState *xhci, dma_addr_t addr, for (i = 0; i < n; i++) { tmp[i] = cpu_to_le32(buf[i]); } - pci_dma_write(PCI_DEVICE(xhci), addr, tmp, len); + dma_memory_write(xhci->as, addr, tmp, len); } static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport) @@ -548,54 +540,28 @@ static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport) return &xhci->ports[index]; } -static void xhci_intx_update(XHCIState *xhci) +static void xhci_intr_update(XHCIState *xhci, int v) { - PCIDevice *pci_dev = PCI_DEVICE(xhci); int level = 0; - if (msix_enabled(pci_dev) || - msi_enabled(pci_dev)) { - return; - } - - if (xhci->intr[0].iman & IMAN_IP && - xhci->intr[0].iman & IMAN_IE && - xhci->usbcmd & USBCMD_INTE) { - level = 1; - } - - trace_usb_xhci_irq_intx(level); - pci_set_irq(pci_dev, level); -} - -static void xhci_msix_update(XHCIState *xhci, int v) -{ - PCIDevice *pci_dev = PCI_DEVICE(xhci); - bool enabled; - - if (!msix_enabled(pci_dev)) { - return; - } - - enabled = xhci->intr[v].iman & IMAN_IE; - if (enabled == xhci->intr[v].msix_used) { - return; + if (v == 0) { + if (xhci->intr[0].iman & IMAN_IP && + xhci->intr[0].iman & IMAN_IE && + xhci->usbcmd & USBCMD_INTE) { + level = 1; + } + if (xhci->intr_raise) { + xhci->intr_raise(xhci, 0, level); + } } - - if (enabled) { - trace_usb_xhci_irq_msix_use(v); - msix_vector_use(pci_dev, v); - xhci->intr[v].msix_used = true; - } else { - trace_usb_xhci_irq_msix_unuse(v); - msix_vector_unuse(pci_dev, v); - xhci->intr[v].msix_used = false; + if (xhci->intr_update) { + xhci->intr_update(xhci, v, + xhci->intr[v].iman & IMAN_IE); } } static void xhci_intr_raise(XHCIState *xhci, int v) { - PCIDevice *pci_dev = PCI_DEVICE(xhci); bool pending = (xhci->intr[v].erdp_low & ERDP_EHB); xhci->intr[v].erdp_low |= ERDP_EHB; @@ -612,22 +578,8 @@ static void xhci_intr_raise(XHCIState *xhci, int v) if (!(xhci->usbcmd & USBCMD_INTE)) { return; } - - if (msix_enabled(pci_dev)) { - trace_usb_xhci_irq_msix(v); - msix_notify(pci_dev, v); - return; - } - - if (msi_enabled(pci_dev)) { - trace_usb_xhci_irq_msi(v); - msi_notify(pci_dev, v); - return; - } - - if (v == 0) { - trace_usb_xhci_irq_intx(1); - pci_irq_assert(pci_dev); + if (xhci->intr_raise) { + xhci->intr_raise(xhci, v, true); } } @@ -644,7 +596,6 @@ static void xhci_die(XHCIState *xhci) static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v) { - PCIDevice *pci_dev = PCI_DEVICE(xhci); XHCIInterrupter *intr = &xhci->intr[v]; XHCITRB ev_trb; dma_addr_t addr; @@ -663,7 +614,7 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v) ev_trb.status, ev_trb.control); addr = intr->er_start + TRB_SIZE*intr->er_ep_idx; - pci_dma_write(pci_dev, addr, &ev_trb, TRB_SIZE); + dma_memory_write(xhci->as, addr, &ev_trb, TRB_SIZE); intr->er_ep_idx++; if (intr->er_ep_idx >= intr->er_size) { @@ -720,12 +671,11 @@ static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring, static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb, dma_addr_t *addr) { - PCIDevice *pci_dev = PCI_DEVICE(xhci); uint32_t link_cnt = 0; while (1) { TRBType type; - pci_dma_read(pci_dev, ring->dequeue, trb, TRB_SIZE); + dma_memory_read(xhci->as, ring->dequeue, trb, TRB_SIZE); trb->addr = ring->dequeue; trb->ccs = ring->ccs; le64_to_cpus(&trb->parameter); @@ -762,7 +712,6 @@ static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb, static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring) { - PCIDevice *pci_dev = PCI_DEVICE(xhci); XHCITRB trb; int length = 0; dma_addr_t dequeue = ring->dequeue; @@ -773,7 +722,7 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring) while (1) { TRBType type; - pci_dma_read(pci_dev, dequeue, &trb, TRB_SIZE); + dma_memory_read(xhci->as, dequeue, &trb, TRB_SIZE); le64_to_cpus(&trb.parameter); le32_to_cpus(&trb.status); le32_to_cpus(&trb.control); @@ -828,7 +777,7 @@ static void xhci_er_reset(XHCIState *xhci, int v) xhci_die(xhci); return; } - pci_dma_read(PCI_DEVICE(xhci), erstba, &seg, sizeof(seg)); + dma_memory_read(xhci->as, erstba, &seg, sizeof(seg)); le32_to_cpus(&seg.addr_low); le32_to_cpus(&seg.addr_high); le32_to_cpus(&seg.size); @@ -1440,7 +1389,7 @@ static int xhci_xfer_create_sgl(XHCITransfer *xfer, int in_xfer) int i; xfer->int_req = false; - pci_dma_sglist_init(&xfer->sgl, PCI_DEVICE(xhci), xfer->trb_count); + qemu_sglist_init(&xfer->sgl, DEVICE(xhci), xfer->trb_count, xhci->as); for (i = 0; i < xfer->trb_count; i++) { XHCITRB *trb = &xfer->trbs[i]; dma_addr_t addr; @@ -1615,7 +1564,10 @@ static int xhci_setup_packet(XHCITransfer *xfer) xhci_xfer_create_sgl(xfer, dir == USB_TOKEN_IN); /* Also sets int_req */ usb_packet_setup(&xfer->packet, dir, ep, xfer->streamid, xfer->trbs[0].addr, false, xfer->int_req); - usb_packet_map(&xfer->packet, &xfer->sgl); + if (usb_packet_map(&xfer->packet, &xfer->sgl)) { + qemu_sglist_destroy(&xfer->sgl); + return -1; + } DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n", xfer->packet.pid, ep->dev->addr, ep->nr); return 0; @@ -1952,7 +1904,9 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid) streamid = 0; xhci_set_ep_state(xhci, epctx, NULL, EP_RUNNING); } - assert(ring->dequeue != 0); + if (!ring->dequeue) { + return; + } epctx->kick_active++; while (1) { @@ -2101,7 +2055,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, assert(slotid >= 1 && slotid <= xhci->numslots); dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high); - poctx = ldq_le_pci_dma(PCI_DEVICE(xhci), dcbaap + 8 * slotid); + poctx = ldq_le_dma(xhci->as, dcbaap + 8 * slotid); ictx = xhci_mask64(pictx); octx = xhci_mask64(poctx); @@ -2439,7 +2393,7 @@ static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx) /* TODO: actually implement real values here */ bw_ctx[0] = 0; memset(&bw_ctx[1], 80, xhci->numports); /* 80% */ - pci_dma_write(PCI_DEVICE(xhci), ctx, bw_ctx, sizeof(bw_ctx)); + dma_memory_write(xhci->as, ctx, bw_ctx, sizeof(bw_ctx)); return CC_SUCCESS; } @@ -2718,7 +2672,6 @@ static void xhci_reset(DeviceState *dev) xhci->intr[i].erstba_high = 0; xhci->intr[i].erdp_low = 0; xhci->intr[i].erdp_high = 0; - xhci->intr[i].msix_used = 0; xhci->intr[i].er_ep_idx = 0; xhci->intr[i].er_pcs = 1; @@ -2940,8 +2893,7 @@ static uint64_t xhci_oper_read(void *ptr, hwaddr reg, unsigned size) static void xhci_oper_write(void *ptr, hwaddr reg, uint64_t val, unsigned size) { - XHCIState *xhci = ptr; - DeviceState *d = DEVICE(ptr); + XHCIState *xhci = XHCI(ptr); trace_usb_xhci_oper_write(reg, val); @@ -2963,15 +2915,15 @@ static void xhci_oper_write(void *ptr, hwaddr reg, xhci->usbcmd = val & 0xc0f; xhci_mfwrap_update(xhci); if (val & USBCMD_HCRST) { - xhci_reset(d); + xhci_reset(DEVICE(xhci)); } - xhci_intx_update(xhci); + xhci_intr_update(xhci, 0); break; case 0x04: /* USBSTS */ /* these bits are write-1-to-clear */ xhci->usbsts &= ~(val & (USBSTS_HSE|USBSTS_EINT|USBSTS_PCD|USBSTS_SRE)); - xhci_intx_update(xhci); + xhci_intr_update(xhci, 0); break; case 0x14: /* DNCTRL */ @@ -3058,14 +3010,17 @@ static void xhci_runtime_write(void *ptr, hwaddr reg, uint64_t val, unsigned size) { XHCIState *xhci = ptr; - int v = (reg - 0x20) / 0x20; - XHCIInterrupter *intr = &xhci->intr[v]; + XHCIInterrupter *intr; + int v; + trace_usb_xhci_runtime_write(reg, val); if (reg < 0x20) { trace_usb_xhci_unimplemented("runtime write", reg); return; } + v = (reg - 0x20) / 0x20; + intr = &xhci->intr[v]; switch (reg & 0x1f) { case 0x00: /* IMAN */ @@ -3074,10 +3029,7 @@ static void xhci_runtime_write(void *ptr, hwaddr reg, } intr->iman &= ~IMAN_IE; intr->iman |= val & IMAN_IE; - if (v == 0) { - xhci_intx_update(xhci); - } - xhci_msix_update(xhci, v); + xhci_intr_update(xhci, v); break; case 0x04: /* IMOD */ intr->imod = val; @@ -3184,7 +3136,7 @@ static const MemoryRegionOps xhci_oper_ops = { .read = xhci_oper_read, .write = xhci_oper_write, .valid.min_access_size = 4, - .valid.max_access_size = 4, + .valid.max_access_size = sizeof(dma_addr_t), .endianness = DEVICE_LITTLE_ENDIAN, }; @@ -3200,7 +3152,7 @@ static const MemoryRegionOps xhci_runtime_ops = { .read = xhci_runtime_read, .write = xhci_runtime_write, .valid.min_access_size = 4, - .valid.max_access_size = 4, + .valid.max_access_size = sizeof(dma_addr_t), .endianness = DEVICE_LITTLE_ENDIAN, }; @@ -3322,22 +3274,21 @@ static USBBusOps xhci_bus_ops = { static void usb_xhci_init(XHCIState *xhci) { - DeviceState *dev = DEVICE(xhci); XHCIPort *port; unsigned int i, usbports, speedmask; xhci->usbsts = USBSTS_HCH; - if (xhci->numports_2 > MAXPORTS_2) { - xhci->numports_2 = MAXPORTS_2; + if (xhci->numports_2 > XHCI_MAXPORTS_2) { + xhci->numports_2 = XHCI_MAXPORTS_2; } - if (xhci->numports_3 > MAXPORTS_3) { - xhci->numports_3 = MAXPORTS_3; + if (xhci->numports_3 > XHCI_MAXPORTS_3) { + xhci->numports_3 = XHCI_MAXPORTS_3; } usbports = MAX(xhci->numports_2, xhci->numports_3); xhci->numports = xhci->numports_2 + xhci->numports_3; - usb_bus_new(&xhci->bus, sizeof(xhci->bus), &xhci_bus_ops, dev); + usb_bus_new(&xhci->bus, sizeof(xhci->bus), &xhci_bus_ops, xhci->hostOpaque); for (i = 0; i < usbports; i++) { speedmask = 0; @@ -3354,7 +3305,7 @@ static void usb_xhci_init(XHCIState *xhci) USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL | USB_SPEED_MASK_HIGH; - assert(i < MAXPORTS); + assert(i < XHCI_MAXPORTS); snprintf(port->name, sizeof(port->name), "usb2 port #%d", i+1); speedmask |= port->speedmask; } @@ -3368,7 +3319,7 @@ static void usb_xhci_init(XHCIState *xhci) } port->uport = &xhci->uports[i]; port->speedmask = USB_SPEED_MASK_SUPER; - assert(i < MAXPORTS); + assert(i < XHCI_MAXPORTS); snprintf(port->name, sizeof(port->name), "usb3 port #%d", i+1); speedmask |= port->speedmask; } @@ -3377,23 +3328,14 @@ static void usb_xhci_init(XHCIState *xhci) } } -static void usb_xhci_realize(struct PCIDevice *dev, Error **errp) +static void usb_xhci_realize(DeviceState *dev, Error **errp) { - int i, ret; - Error *err = NULL; + int i; XHCIState *xhci = XHCI(dev); - dev->config[PCI_CLASS_PROG] = 0x30; /* xHCI */ - dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin 1 */ - dev->config[PCI_CACHE_LINE_SIZE] = 0x10; - dev->config[0x60] = 0x30; /* release number */ - - if (strcmp(object_get_typename(OBJECT(dev)), TYPE_NEC_XHCI) == 0) { - xhci->nec_quirks = true; - } - if (xhci->numintrs > MAXINTRS) { - xhci->numintrs = MAXINTRS; + if (xhci->numintrs > XHCI_MAXINTRS) { + xhci->numintrs = XHCI_MAXINTRS; } while (xhci->numintrs & (xhci->numintrs - 1)) { /* ! power of 2 */ xhci->numintrs++; @@ -3401,8 +3343,8 @@ static void usb_xhci_realize(struct PCIDevice *dev, Error **errp) if (xhci->numintrs < 1) { xhci->numintrs = 1; } - if (xhci->numslots > MAXSLOTS) { - xhci->numslots = MAXSLOTS; + if (xhci->numslots > XHCI_MAXSLOTS) { + xhci->numslots = XHCI_MAXSLOTS; } if (xhci->numslots < 1) { xhci->numslots = 1; @@ -3413,35 +3355,18 @@ static void usb_xhci_realize(struct PCIDevice *dev, Error **errp) xhci->max_pstreams_mask = 0; } - if (xhci->msi != ON_OFF_AUTO_OFF) { - ret = msi_init(dev, 0x70, xhci->numintrs, true, false, &err); - /* Any error other than -ENOTSUP(board's MSI support is broken) - * is a programming error */ - assert(!ret || ret == -ENOTSUP); - if (ret && xhci->msi == ON_OFF_AUTO_ON) { - /* Can't satisfy user's explicit msi=on request, fail */ - error_append_hint(&err, "You have to use msi=auto (default) or " - "msi=off with this machine type.\n"); - error_propagate(errp, err); - return; - } - assert(!err || xhci->msi == ON_OFF_AUTO_AUTO); - /* With msi=auto, we fall back to MSI off silently */ - error_free(err); - } - usb_xhci_init(xhci); xhci->mfwrap_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, xhci_mfwrap_timer, xhci); - memory_region_init(&xhci->mem, OBJECT(xhci), "xhci", LEN_REGS); - memory_region_init_io(&xhci->mem_cap, OBJECT(xhci), &xhci_cap_ops, xhci, + memory_region_init(&xhci->mem, OBJECT(dev), "xhci", XHCI_LEN_REGS); + memory_region_init_io(&xhci->mem_cap, OBJECT(dev), &xhci_cap_ops, xhci, "capabilities", LEN_CAP); - memory_region_init_io(&xhci->mem_oper, OBJECT(xhci), &xhci_oper_ops, xhci, + memory_region_init_io(&xhci->mem_oper, OBJECT(dev), &xhci_oper_ops, xhci, "operational", 0x400); - memory_region_init_io(&xhci->mem_runtime, OBJECT(xhci), &xhci_runtime_ops, xhci, - "runtime", LEN_RUNTIME); - memory_region_init_io(&xhci->mem_doorbell, OBJECT(xhci), &xhci_doorbell_ops, xhci, - "doorbell", LEN_DOORBELL); + memory_region_init_io(&xhci->mem_runtime, OBJECT(dev), &xhci_runtime_ops, + xhci, "runtime", LEN_RUNTIME); + memory_region_init_io(&xhci->mem_doorbell, OBJECT(dev), &xhci_doorbell_ops, + xhci, "doorbell", LEN_DOORBELL); memory_region_add_subregion(&xhci->mem, 0, &xhci->mem_cap); memory_region_add_subregion(&xhci->mem, OFF_OPER, &xhci->mem_oper); @@ -3452,31 +3377,13 @@ static void usb_xhci_realize(struct PCIDevice *dev, Error **errp) XHCIPort *port = &xhci->ports[i]; uint32_t offset = OFF_OPER + 0x400 + 0x10 * i; port->xhci = xhci; - memory_region_init_io(&port->mem, OBJECT(xhci), &xhci_port_ops, port, + memory_region_init_io(&port->mem, OBJECT(dev), &xhci_port_ops, port, port->name, 0x10); memory_region_add_subregion(&xhci->mem, offset, &port->mem); } - - pci_register_bar(dev, 0, - PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64, - &xhci->mem); - - if (pci_bus_is_express(pci_get_bus(dev)) || - xhci_get_flag(xhci, XHCI_FLAG_FORCE_PCIE_ENDCAP)) { - ret = pcie_endpoint_cap_init(dev, 0xa0); - assert(ret > 0); - } - - if (xhci->msix != ON_OFF_AUTO_OFF) { - /* TODO check for errors, and should fail when msix=on */ - msix_init(dev, xhci->numintrs, - &xhci->mem, 0, OFF_MSIX_TABLE, - &xhci->mem, 0, OFF_MSIX_PBA, - 0x90, NULL); - } } -static void usb_xhci_exit(PCIDevice *dev) +static void usb_xhci_unrealize(DeviceState *dev) { int i; XHCIState *xhci = XHCI(dev); @@ -3503,25 +3410,18 @@ static void usb_xhci_exit(PCIDevice *dev) memory_region_del_subregion(&xhci->mem, &port->mem); } - /* destroy msix memory region */ - if (dev->msix_table && dev->msix_pba - && dev->msix_entry_used) { - msix_uninit(dev, &xhci->mem, &xhci->mem); - } - usb_bus_release(&xhci->bus); } static int usb_xhci_post_load(void *opaque, int version_id) { XHCIState *xhci = opaque; - PCIDevice *pci_dev = PCI_DEVICE(xhci); XHCISlot *slot; XHCIEPContext *epctx; dma_addr_t dcbaap, pctx; uint32_t slot_ctx[4]; uint32_t ep_ctx[5]; - int slotid, epid, state, intr; + int slotid, epid, state; dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high); @@ -3531,7 +3431,7 @@ static int usb_xhci_post_load(void *opaque, int version_id) continue; } slot->ctx = - xhci_mask64(ldq_le_pci_dma(pci_dev, dcbaap + 8 * slotid)); + xhci_mask64(ldq_le_dma(xhci->as, dcbaap + 8 * slotid)); xhci_dma_read_u32s(xhci, slot->ctx, slot_ctx, sizeof(slot_ctx)); slot->uport = xhci_lookup_uport(xhci, slot_ctx); if (!slot->uport) { @@ -3559,15 +3459,6 @@ static int usb_xhci_post_load(void *opaque, int version_id) } } } - - for (intr = 0; intr < xhci->numintrs; intr++) { - if (xhci->intr[intr].msix_used) { - msix_vector_use(pci_dev, intr); - } else { - msix_vector_unuse(pci_dev, intr); - } - } - return 0; } @@ -3652,14 +3543,11 @@ static const VMStateDescription vmstate_xhci_intr = { } }; -static const VMStateDescription vmstate_xhci = { - .name = "xhci", +const VMStateDescription vmstate_xhci = { + .name = "xhci-core", .version_id = 1, .post_load = usb_xhci_post_load, .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(parent_obj, XHCIState), - VMSTATE_MSIX(parent_obj, XHCIState), - VMSTATE_STRUCT_VARRAY_UINT32(ports, XHCIState, numports, 1, vmstate_xhci_port, XHCIPort), VMSTATE_STRUCT_VARRAY_UINT32(slots, XHCIState, numslots, 1, @@ -3691,75 +3579,32 @@ static Property xhci_properties[] = { XHCI_FLAG_ENABLE_STREAMS, true), DEFINE_PROP_UINT32("p2", XHCIState, numports_2, 4), DEFINE_PROP_UINT32("p3", XHCIState, numports_3, 4), + DEFINE_PROP_LINK("host", XHCIState, hostOpaque, TYPE_DEVICE, + DeviceState *), DEFINE_PROP_END_OF_LIST(), }; -static void xhci_instance_init(Object *obj) -{ - /* QEMU_PCI_CAP_EXPRESS initialization does not depend on QEMU command - * line, therefore, no need to wait to realize like other devices */ - PCI_DEVICE(obj)->cap_present |= QEMU_PCI_CAP_EXPRESS; -} - static void xhci_class_init(ObjectClass *klass, void *data) { - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - dc->vmsd = &vmstate_xhci; - device_class_set_props(dc, xhci_properties); + dc->realize = usb_xhci_realize; + dc->unrealize = usb_xhci_unrealize; dc->reset = xhci_reset; - set_bit(DEVICE_CATEGORY_USB, dc->categories); - k->realize = usb_xhci_realize; - k->exit = usb_xhci_exit; - k->class_id = PCI_CLASS_SERIAL_USB; + device_class_set_props(dc, xhci_properties); + dc->user_creatable = false; } static const TypeInfo xhci_info = { .name = TYPE_XHCI, - .parent = TYPE_PCI_DEVICE, + .parent = TYPE_DEVICE, .instance_size = sizeof(XHCIState), .class_init = xhci_class_init, - .instance_init = xhci_instance_init, - .abstract = true, - .interfaces = (InterfaceInfo[]) { - { INTERFACE_PCIE_DEVICE }, - { INTERFACE_CONVENTIONAL_PCI_DEVICE }, - { } - }, -}; - -static void qemu_xhci_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->vendor_id = PCI_VENDOR_ID_REDHAT; - k->device_id = PCI_DEVICE_ID_REDHAT_XHCI; - k->revision = 0x01; -} - -static void qemu_xhci_instance_init(Object *obj) -{ - XHCIState *xhci = XHCI(obj); - - xhci->msi = ON_OFF_AUTO_OFF; - xhci->msix = ON_OFF_AUTO_AUTO; - xhci->numintrs = MAXINTRS; - xhci->numslots = MAXSLOTS; - xhci_set_flag(xhci, XHCI_FLAG_SS_FIRST); -} - -static const TypeInfo qemu_xhci_info = { - .name = TYPE_QEMU_XHCI, - .parent = TYPE_XHCI, - .class_init = qemu_xhci_class_init, - .instance_init = qemu_xhci_instance_init, }; static void xhci_register_types(void) { type_register_static(&xhci_info); - type_register_static(&qemu_xhci_info); } type_init(xhci_register_types) diff --git a/hw/usb/hcd-xhci.h b/hw/usb/hcd-xhci.h index 2fad4df2a70473950c622b771ce7bd5f8aa80cca..02ebd764509ab39164ec06fdb976a4075beba340 100644 --- a/hw/usb/hcd-xhci.h +++ b/hw/usb/hcd-xhci.h @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -21,25 +21,17 @@ #ifndef HW_USB_HCD_XHCI_H #define HW_USB_HCD_XHCI_H +#include "qom/object.h" -#define TYPE_XHCI "base-xhci" -#define TYPE_NEC_XHCI "nec-usb-xhci" -#define TYPE_QEMU_XHCI "qemu-xhci" +#include "hw/usb.h" +#include "hw/usb/xhci.h" +#include "sysemu/dma.h" -#define XHCI(obj) \ - OBJECT_CHECK(XHCIState, (obj), TYPE_XHCI) - -#define MAXPORTS_2 15 -#define MAXPORTS_3 15 - -#define MAXPORTS (MAXPORTS_2 + MAXPORTS_3) -#define MAXSLOTS 64 -#define MAXINTRS 16 +OBJECT_DECLARE_SIMPLE_TYPE(XHCIState, XHCI) /* Very pessimistic, let's hope it's enough for all cases */ -#define EV_QUEUE (((3 * 24) + 16) * MAXSLOTS) +#define EV_QUEUE (((3 * 24) + 16) * XHCI_MAXSLOTS) -typedef struct XHCIState XHCIState; typedef struct XHCIStreamContext XHCIStreamContext; typedef struct XHCIEPContext XHCIEPContext; @@ -182,13 +174,13 @@ typedef struct XHCIInterrupter { } XHCIInterrupter; -struct XHCIState { - /*< private >*/ - PCIDevice parent_obj; - /*< public >*/ +typedef struct XHCIState { + DeviceState parent; USBBus bus; MemoryRegion mem; + MemoryRegion *dma_mr; + AddressSpace *as; MemoryRegion mem_cap; MemoryRegion mem_oper; MemoryRegion mem_runtime; @@ -201,8 +193,9 @@ struct XHCIState { uint32_t numslots; uint32_t flags; uint32_t max_pstreams_mask; - OnOffAuto msi; - OnOffAuto msix; + void (*intr_update)(XHCIState *s, int n, bool enable); + void (*intr_raise)(XHCIState *s, int n, bool level); + DeviceState *hostOpaque; /* Operational Registers */ uint32_t usbcmd; @@ -214,19 +207,22 @@ struct XHCIState { uint32_t dcbaap_high; uint32_t config; - USBPort uports[MAX(MAXPORTS_2, MAXPORTS_3)]; - XHCIPort ports[MAXPORTS]; - XHCISlot slots[MAXSLOTS]; + USBPort uports[MAX_CONST(XHCI_MAXPORTS_2, XHCI_MAXPORTS_3)]; + XHCIPort ports[XHCI_MAXPORTS]; + XHCISlot slots[XHCI_MAXSLOTS]; uint32_t numports; /* Runtime Registers */ int64_t mfindex_start; QEMUTimer *mfwrap_timer; - XHCIInterrupter intr[MAXINTRS]; + XHCIInterrupter intr[XHCI_MAXINTRS]; XHCIRing cmd_ring; bool nec_quirks; -}; +} XHCIState; +extern const VMStateDescription vmstate_xhci; +bool xhci_get_flag(XHCIState *xhci, enum xhci_flags bit); +void xhci_set_flag(XHCIState *xhci, enum xhci_flags bit); #endif diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index e28441379d99246848a44162bfc4f32b5037b174..b950501d100f7e695b20e58ce8bf902622742f9e 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -34,11 +34,17 @@ */ #include "qemu/osdep.h" +#include "qom/object.h" #ifndef CONFIG_WIN32 #include #endif #include +#ifdef CONFIG_LINUX +#include +#include +#endif + #include "qapi/error.h" #include "migration/vmstate.h" #include "monitor/monitor.h" @@ -55,10 +61,8 @@ /* ------------------------------------------------------------------------ */ #define TYPE_USB_HOST_DEVICE "usb-host" -#define USB_HOST_DEVICE(obj) \ - OBJECT_CHECK(USBHostDevice, (obj), TYPE_USB_HOST_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(USBHostDevice, USB_HOST_DEVICE) -typedef struct USBHostDevice USBHostDevice; typedef struct USBHostRequest USBHostRequest; typedef struct USBHostIsoXfer USBHostIsoXfer; typedef struct USBHostIsoRing USBHostIsoRing; @@ -80,6 +84,7 @@ struct USBHostDevice { /* properties */ struct USBAutoFilter match; + char *hostdevice; int32_t bootindex; uint32_t iso_urb_count; uint32_t iso_urb_frames; @@ -97,6 +102,7 @@ struct USBHostDevice { int addr; char port[16]; + int hostfd; libusb_device *dev; libusb_device_handle *dh; struct libusb_device_descriptor ddesc; @@ -880,26 +886,46 @@ static void usb_host_ep_update(USBHostDevice *s) libusb_free_config_descriptor(conf); } -static int usb_host_open(USBHostDevice *s, libusb_device *dev) +static int usb_host_open(USBHostDevice *s, libusb_device *dev, int hostfd) { USBDevice *udev = USB_DEVICE(s); - int bus_num = libusb_get_bus_number(dev); - int addr = libusb_get_device_address(dev); + int libusb_speed; + int bus_num = 0; + int addr = 0; int rc; Error *local_err = NULL; if (s->bh_postld_pending) { return -1; } - - trace_usb_host_open_started(bus_num, addr); - if (s->dh != NULL) { goto fail; } - rc = libusb_open(dev, &s->dh); - if (rc != 0) { - goto fail; + + if (dev) { + bus_num = libusb_get_bus_number(dev); + addr = libusb_get_device_address(dev); + trace_usb_host_open_started(bus_num, addr); + + rc = libusb_open(dev, &s->dh); + if (rc != 0) { + goto fail; + } + } else { +#if LIBUSB_API_VERSION >= 0x01000107 && !defined(CONFIG_WIN32) + trace_usb_host_open_hostfd(hostfd); + + rc = libusb_wrap_sys_device(ctx, hostfd, &s->dh); + if (rc != 0) { + goto fail; + } + s->hostfd = hostfd; + dev = libusb_get_device(s->dh); + bus_num = libusb_get_bus_number(dev); + addr = libusb_get_device_address(dev); +#else + g_assert_not_reached(); +#endif } s->dev = dev; @@ -914,7 +940,36 @@ static int usb_host_open(USBHostDevice *s, libusb_device *dev) usb_ep_init(udev); usb_host_ep_update(s); - udev->speed = speed_map[libusb_get_device_speed(dev)]; + libusb_speed = libusb_get_device_speed(dev); +#if LIBUSB_API_VERSION >= 0x01000107 && defined(CONFIG_LINUX) + if (hostfd && libusb_speed == 0) { + /* + * Workaround libusb bug: libusb_get_device_speed() does not + * work for libusb_wrap_sys_device() devices in v1.0.23. + * + * Speeds are defined in linux/usb/ch9.h, file not included + * due to name conflicts. + */ + int rc = ioctl(hostfd, USBDEVFS_GET_SPEED, NULL); + switch (rc) { + case 1: /* low */ + libusb_speed = LIBUSB_SPEED_LOW; + break; + case 2: /* full */ + libusb_speed = LIBUSB_SPEED_FULL; + break; + case 3: /* high */ + case 4: /* wireless */ + libusb_speed = LIBUSB_SPEED_HIGH; + break; + case 5: /* super */ + case 6: /* super plus */ + libusb_speed = LIBUSB_SPEED_SUPER; + break; + } + } +#endif + udev->speed = speed_map[libusb_speed]; usb_host_speed_compat(s); if (s->ddesc.iProduct) { @@ -951,6 +1006,7 @@ fail: static void usb_host_abort_xfers(USBHostDevice *s) { USBHostRequest *r, *rtmp; + int limit = 100; QTAILQ_FOREACH_SAFE(r, &s->requests, next, rtmp) { usb_host_req_abort(r); @@ -961,6 +1017,19 @@ static void usb_host_abort_xfers(USBHostDevice *s) memset(&tv, 0, sizeof(tv)); tv.tv_usec = 2500; libusb_handle_events_timeout(ctx, &tv); + if (--limit == 0) { + /* + * Don't wait forever for libusb calling the complete + * callback (which will unlink and free the request). + * + * Leaking memory here, to make sure libusb will not + * access memory which we have released already. + */ + QTAILQ_FOREACH_SAFE(r, &s->requests, next, rtmp) { + QTAILQ_REMOVE(&s->requests, r, next); + } + return; + } } } @@ -988,6 +1057,11 @@ static int usb_host_close(USBHostDevice *s) s->dh = NULL; s->dev = NULL; + if (s->hostfd != -1) { + close(s->hostfd); + s->hostfd = -1; + } + usb_host_auto_check(NULL); return 0; } @@ -1025,9 +1099,6 @@ static libusb_device *usb_host_find_ref(int bus, int addr) libusb_device *ret = NULL; int i, n; - if (usb_host_init() != 0) { - return NULL; - } n = libusb_get_device_list(ctx, &devs); for (i = 0; i < n; i++) { if (libusb_get_bus_number(devs[i]) == bus && @@ -1046,6 +1117,10 @@ static void usb_host_realize(USBDevice *udev, Error **errp) libusb_device *ldev; int rc; + if (usb_host_init() != 0) { + error_setg(errp, "failed to init libusb"); + return; + } if (s->match.vendor_id > 0xffff) { error_setg(errp, "vendorid out of range"); return; @@ -1064,7 +1139,24 @@ static void usb_host_realize(USBDevice *udev, Error **errp) udev->auto_attach = 0; QTAILQ_INIT(&s->requests); QTAILQ_INIT(&s->isorings); + s->hostfd = -1; +#if LIBUSB_API_VERSION >= 0x01000107 && !defined(CONFIG_WIN32) + if (s->hostdevice) { + int fd; + s->needs_autoscan = false; + fd = qemu_open_old(s->hostdevice, O_RDWR); + if (fd < 0) { + error_setg_errno(errp, errno, "failed to open %s", s->hostdevice); + return; + } + rc = usb_host_open(s, NULL, fd); + if (rc < 0) { + error_setg(errp, "failed to open host usb device %s", s->hostdevice); + return; + } + } else +#endif if (s->match.addr && s->match.bus_num && !s->match.vendor_id && !s->match.product_id && @@ -1077,7 +1169,7 @@ static void usb_host_realize(USBDevice *udev, Error **errp) s->match.bus_num, s->match.addr); return; } - rc = usb_host_open(s, ldev); + rc = usb_host_open(s, ldev, 0); libusb_unref_device(ldev); if (rc < 0) { error_setg(errp, "failed to open host usb device %d:%d", @@ -1605,6 +1697,9 @@ static Property usb_host_dev_properties[] = { DEFINE_PROP_STRING("hostport", USBHostDevice, match.port), DEFINE_PROP_UINT32("vendorid", USBHostDevice, match.vendor_id, 0), DEFINE_PROP_UINT32("productid", USBHostDevice, match.product_id, 0), +#if LIBUSB_API_VERSION >= 0x01000107 + DEFINE_PROP_STRING("hostdevice", USBHostDevice, hostdevice), +#endif DEFINE_PROP_UINT32("isobufs", USBHostDevice, iso_urb_count, 4), DEFINE_PROP_UINT32("isobsize", USBHostDevice, iso_urb_frames, 32), DEFINE_PROP_BOOL("guest-reset", USBHostDevice, @@ -1723,7 +1818,7 @@ static void usb_host_auto_check(void *unused) if (s->dh != NULL) { continue; } - if (usb_host_open(s, devs[i]) < 0) { + if (usb_host_open(s, devs[i], 0) < 0) { s->errcount++; continue; } diff --git a/hw/usb/meson.build b/hw/usb/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..934e4fa67551188cf2bc4e9824223cd94c60163d --- /dev/null +++ b/hw/usb/meson.build @@ -0,0 +1,78 @@ +hw_usb_modules = {} + +# usb subsystem core +softmmu_ss.add(files( + 'bus.c', + 'combined-packet.c', + 'core.c', + 'libhw.c' +)) + +softmmu_ss.add(when: 'CONFIG_USB', if_true: files( + 'desc.c', + 'desc-msos.c', +)) + +# usb host adapters +softmmu_ss.add(when: 'CONFIG_USB_UHCI', if_true: files('hcd-uhci.c')) +softmmu_ss.add(when: 'CONFIG_USB_OHCI', if_true: files('hcd-ohci.c')) +softmmu_ss.add(when: 'CONFIG_USB_OHCI_PCI', if_true: files('hcd-ohci-pci.c')) +softmmu_ss.add(when: 'CONFIG_USB_EHCI', if_true: files('hcd-ehci.c')) +softmmu_ss.add(when: 'CONFIG_USB_EHCI_PCI', if_true: files('hcd-ehci-pci.c')) +softmmu_ss.add(when: 'CONFIG_USB_EHCI_SYSBUS', if_true: files('hcd-ehci.c', 'hcd-ehci-sysbus.c')) +softmmu_ss.add(when: 'CONFIG_USB_XHCI', if_true: files('hcd-xhci.c')) +softmmu_ss.add(when: 'CONFIG_USB_XHCI_PCI', if_true: files('hcd-xhci-pci.c')) +softmmu_ss.add(when: 'CONFIG_USB_XHCI_SYSBUS', if_true: files('hcd-xhci-sysbus.c')) +softmmu_ss.add(when: 'CONFIG_USB_XHCI_NEC', if_true: files('hcd-xhci-nec.c')) +softmmu_ss.add(when: 'CONFIG_USB_MUSB', if_true: files('hcd-musb.c')) +softmmu_ss.add(when: 'CONFIG_USB_DWC2', if_true: files('hcd-dwc2.c')) + +softmmu_ss.add(when: 'CONFIG_TUSB6010', if_true: files('tusb6010.c')) +softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('chipidea.c')) +softmmu_ss.add(when: 'CONFIG_IMX_USBPHY', if_true: files('imx-usb-phy.c')) + +# emulated usb devices +softmmu_ss.add(when: 'CONFIG_USB', if_true: files('dev-hub.c')) +softmmu_ss.add(when: 'CONFIG_USB', if_true: files('dev-hid.c')) +softmmu_ss.add(when: 'CONFIG_USB_TABLET_WACOM', if_true: files('dev-wacom.c')) +softmmu_ss.add(when: 'CONFIG_USB_STORAGE_BOT', if_true: files('dev-storage.c')) +softmmu_ss.add(when: 'CONFIG_USB_STORAGE_UAS', if_true: files('dev-uas.c')) +softmmu_ss.add(when: 'CONFIG_USB_AUDIO', if_true: files('dev-audio.c')) +softmmu_ss.add(when: 'CONFIG_USB_SERIAL', if_true: files('dev-serial.c')) +softmmu_ss.add(when: 'CONFIG_USB_NETWORK', if_true: files('dev-network.c')) +softmmu_ss.add(when: ['CONFIG_POSIX', 'CONFIG_USB_STORAGE_MTP'], if_true: files('dev-mtp.c')) + +# smartcard +softmmu_ss.add(when: 'CONFIG_USB_SMARTCARD', if_true: files('dev-smartcard-reader.c')) + +if config_host.has_key('CONFIG_SMARTCARD') + usbsmartcard_ss = ss.source_set() + usbsmartcard_ss.add(when: 'CONFIG_USB_SMARTCARD', + if_true: [cacard, files('ccid-card-emulated.c', 'ccid-card-passthru.c')]) + hw_usb_modules += {'smartcard': usbsmartcard_ss} +endif + +# U2F +softmmu_ss.add(when: 'CONFIG_USB_U2F', if_true: files('u2f.c')) +softmmu_ss.add(when: ['CONFIG_LINUX', 'CONFIG_USB_U2F'], if_true: [libudev, files('u2f-passthru.c')]) +if u2f.found() + softmmu_ss.add(when: 'CONFIG_USB_U2F', if_true: [u2f, files('u2f-emulated.c')]) +endif + +# usb redirect +if config_host.has_key('CONFIG_USB_REDIR') + usbredir_ss = ss.source_set() + usbredir_ss.add(when: 'CONFIG_USB', + if_true: [usbredir, files('redirect.c', 'quirks.c')]) + hw_usb_modules += {'redirect': usbredir_ss} +endif + +# usb pass-through +softmmu_ss.add(when: ['CONFIG_USB', 'CONFIG_USB_LIBUSB', libusb], + if_true: files('host-libusb.c'), + if_false: files('host-stub.c')) +softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('host-stub.c')) + +softmmu_ss.add(when: ['CONFIG_USB', 'CONFIG_XEN', libusb], if_true: files('xen-usb.c')) + +modules += { 'hw-usb': hw_usb_modules } diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 417a60a2e680335c9c190fb8e9d8b08d3b77700c..3238de6bb82dd5393f67dba64746c377e9ef4ba6 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -45,6 +45,7 @@ #include "hw/usb.h" #include "migration/qemu-file-types.h" #include "migration/vmstate.h" +#include "qom/object.h" /* ERROR is defined below. Remove any previous definition. */ #undef ERROR @@ -144,7 +145,8 @@ struct USBRedirDevice { }; #define TYPE_USB_REDIR "usb-redir" -#define USB_REDIRECT(obj) OBJECT_CHECK(USBRedirDevice, (obj), TYPE_USB_REDIR) +DECLARE_INSTANCE_CHECKER(USBRedirDevice, USB_REDIRECT, + TYPE_USB_REDIR) static void usbredir_hello(void *priv, struct usb_redir_hello_header *h); static void usbredir_device_connect(void *priv, @@ -240,7 +242,7 @@ static void usbredir_log_data(USBRedirDevice *dev, const char *desc, if (dev->debug < usbredirparser_debug_data) { return; } - qemu_hexdump((char *)data, stderr, desc, len); + qemu_hexdump(stderr, desc, data, len); } /* diff --git a/hw/usb/trace-events b/hw/usb/trace-events index 1c24d82c09c0525795a481d13c5dc7b8b585c5fd..38e05fc7f4db11ac8790b784c28510f082ec0483 100644 --- a/hw/usb/trace-events +++ b/hw/usb/trace-events @@ -10,6 +10,9 @@ usb_port_attach(int bus, const char *port, const char *devspeed, const char *por usb_port_detach(int bus, const char *port) "bus %d, port %s" usb_port_release(int bus, const char *port) "bus %d, port %s" +# hcd-ohci-pci.c +usb_ohci_exit(const char *s) "%s" + # hcd-ohci.c usb_ohci_iso_td_read_failed(uint32_t addr) "ISO_TD read error at 0x%x" usb_ohci_iso_td_head(uint32_t head, uint32_t tail, uint32_t flags, uint32_t bp, uint32_t next, uint32_t be, uint32_t framenum, uint32_t startframe, uint32_t framecount, int rel_frame_num) "ISO_TD ED head 0x%.8x tailp 0x%.8x\n0x%.8x 0x%.8x 0x%.8x 0x%.8x\nframe_number 0x%.8x starting_frame 0x%.8x\nframe_count 0x%.8x relative %d" @@ -35,7 +38,6 @@ usb_ohci_reset(const char *s) "%s" usb_ohci_start(const char *s) "%s: USB Operational" usb_ohci_resume(const char *s) "%s: USB Resume" usb_ohci_stop(const char *s) "%s: USB Suspended" -usb_ohci_exit(const char *s) "%s" usb_ohci_set_ctl(const char *s, uint32_t new_state) "%s: new state 0x%x" usb_ohci_td_underrun(void) "" usb_ohci_td_dev_error(void) "" @@ -176,6 +178,56 @@ usb_xhci_xfer_error(void *xfer, uint32_t ret) "%p: ret %d" usb_xhci_unimplemented(const char *item, int nr) "%s (0x%x)" usb_xhci_enforced_limit(const char *item) "%s" +# hcd-dwc2.c +usb_dwc2_update_irq(uint32_t level) "level=%d" +usb_dwc2_raise_global_irq(uint32_t intr) "0x%08x" +usb_dwc2_lower_global_irq(uint32_t intr) "0x%08x" +usb_dwc2_raise_host_irq(uint32_t intr) "0x%04x" +usb_dwc2_lower_host_irq(uint32_t intr) "0x%04x" +usb_dwc2_sof(int64_t next) "next SOF %" PRId64 +usb_dwc2_bus_start(void) "start SOFs" +usb_dwc2_bus_stop(void) "stop SOFs" +usb_dwc2_find_device(uint8_t addr) "%d" +usb_dwc2_port_disabled(uint32_t pnum) "port %d disabled" +usb_dwc2_device_found(uint32_t pnum) "device found on port %d" +usb_dwc2_device_not_found(void) "device not found" +usb_dwc2_handle_packet(uint32_t chan, void *dev, void *pkt, uint32_t ep, const char *type, const char *dir, uint32_t mps, uint32_t len, uint32_t pcnt) "ch %d dev %p pkt %p ep %d type %s dir %s mps %d len %d pcnt %d" +usb_dwc2_memory_read(uint32_t addr, uint32_t len) "addr %d len %d" +usb_dwc2_packet_status(const char *status, uint32_t len) "status %s len %d" +usb_dwc2_packet_error(const char *status) "ERROR %s" +usb_dwc2_async_packet(void *pkt, uint32_t chan, void *dev, uint32_t ep, const char *dir, uint32_t len) "pkt %p ch %d dev %p ep %d %s len %d" +usb_dwc2_memory_write(uint32_t addr, uint32_t len) "addr %d len %d" +usb_dwc2_packet_done(const char *status, uint32_t actual, uint32_t len, uint32_t pcnt) "status %s actual %d len %d pcnt %d" +usb_dwc2_packet_next(const char *status, uint32_t len, uint32_t pcnt) "status %s len %d pcnt %d" +usb_dwc2_attach(void *port) "port %p" +usb_dwc2_attach_speed(const char *speed) "%s-speed device attached" +usb_dwc2_detach(void *port) "port %p" +usb_dwc2_child_detach(void *port, void *child) "port %p child %p" +usb_dwc2_wakeup(void *port) "port %p" +usb_dwc2_async_packet_complete(void *port, void *pkt, uint32_t chan, void *dev, uint32_t ep, const char *dir, uint32_t len) "port %p packet %p ch %d dev %p ep %d %s len %d" +usb_dwc2_work_bh(void) "" +usb_dwc2_work_bh_service(uint32_t first, uint32_t current, void *dev, uint32_t ep) "first %d servicing %d dev %p ep %d" +usb_dwc2_work_bh_next(uint32_t chan) "next %d" +usb_dwc2_enable_chan(uint32_t chan, void *dev, void *pkt, uint32_t ep) "ch %d dev %p pkt %p ep %d" +usb_dwc2_glbreg_read(uint64_t addr, const char *reg, uint32_t val) " 0x%04" PRIx64 " %s val 0x%08x" +usb_dwc2_glbreg_write(uint64_t addr, const char *reg, uint64_t val, uint32_t old, uint64_t result) "0x%04" PRIx64 " %s val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64 +usb_dwc2_fszreg_read(uint64_t addr, uint32_t val) " 0x%04" PRIx64 " HPTXFSIZ val 0x%08x" +usb_dwc2_fszreg_write(uint64_t addr, uint64_t val, uint32_t old, uint64_t result) "0x%04" PRIx64 " HPTXFSIZ val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64 +usb_dwc2_hreg0_read(uint64_t addr, const char *reg, uint32_t val) " 0x%04" PRIx64 " %s val 0x%08x" +usb_dwc2_hreg0_write(uint64_t addr, const char *reg, uint64_t val, uint32_t old, uint64_t result) " 0x%04" PRIx64 " %s val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64 +usb_dwc2_hreg1_read(uint64_t addr, const char *reg, uint64_t chan, uint32_t val) " 0x%04" PRIx64 " %s%" PRId64 " val 0x%08x" +usb_dwc2_hreg1_write(uint64_t addr, const char *reg, uint64_t chan, uint64_t val, uint32_t old, uint64_t result) " 0x%04" PRIx64 " %s%" PRId64 " val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64 +usb_dwc2_pcgreg_read(uint64_t addr, const char *reg, uint32_t val) " 0x%04" PRIx64 " %s val 0x%08x" +usb_dwc2_pcgreg_write(uint64_t addr, const char *reg, uint64_t val, uint32_t old, uint64_t result) "0x%04" PRIx64 " %s val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64 +usb_dwc2_hreg2_read(uint64_t addr, uint64_t fifo, uint32_t val) " 0x%04" PRIx64 " FIFO%" PRId64 " val 0x%08x" +usb_dwc2_hreg2_write(uint64_t addr, uint64_t fifo, uint64_t val, uint32_t old, uint64_t result) " 0x%04" PRIx64 " FIFO%" PRId64 " val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64 +usb_dwc2_hreg0_action(const char *s) "%s" +usb_dwc2_wakeup_endpoint(void *ep, uint32_t stream) "endp %p stream %d" +usb_dwc2_work_timer(void) "" +usb_dwc2_reset_enter(void) "=== RESET enter ===" +usb_dwc2_reset_hold(void) "=== RESET hold ===" +usb_dwc2_reset_exit(void) "=== RESET exit ===" + # desc.c usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d" usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device qualifier, len %d, ret %d" @@ -200,6 +252,18 @@ usb_hub_attach(int addr, int nr) "dev %d, port %d" usb_hub_detach(int addr, int nr) "dev %d, port %d" usb_hub_status_report(int addr, int status) "dev %d, status 0x%x" +# dev-storage.c +usb_msd_reset(void) "" +usb_msd_maxlun(unsigned maxlun) "%d" +usb_msd_send_status(unsigned status, unsigned tag, size_t size) "status %d, tag 0x%x, len %zd" +usb_msd_data_in(unsigned packet, unsigned remaining, unsigned total) "%d/%d (scsi %d)" +usb_msd_data_out(unsigned packet, unsigned remaining) "%d/%d" +usb_msd_packet_async(void) "" +usb_msd_packet_complete(void) "" +usb_msd_cmd_submit(unsigned lun, unsigned tag, unsigned flags, unsigned len, unsigned data_len) "lun %u, tag 0x%x, flags 0x%08x, len %d, data-len %d" +usb_msd_cmd_complete(unsigned status, unsigned tag) "status %d, tag 0x%x" +usb_msd_cmd_cancel(unsigned tag) "tag 0x%x" + # dev-uas.c usb_uas_reset(int addr) "dev %d" usb_uas_command(int addr, uint16_t tag, int lun, uint32_t lun64_1, uint32_t lun64_2) "dev %d, tag 0x%x, lun %d, lun64 0x%08x-0x%08x" @@ -241,6 +305,7 @@ usb_mtp_file_monitor_event(int dev, const char *path, const char *s) "dev %d, pa # host-libusb.c usb_host_open_started(int bus, int addr) "dev %d:%d" +usb_host_open_hostfd(int hostfd) "hostfd %d" usb_host_open_success(int bus, int addr) "dev %d:%d" usb_host_open_failure(int bus, int addr) "dev %d:%d" usb_host_close(int bus, int addr) "dev %d:%d" @@ -267,3 +332,16 @@ usb_host_parse_interface(int bus, int addr, int num, int alt, int active) "dev % usb_host_parse_endpoint(int bus, int addr, int ep, const char *dir, const char *type, int active) "dev %d:%d, ep %d, %s, %s, active %d" usb_host_parse_error(int bus, int addr, const char *errmsg) "dev %d:%d, msg %s" usb_host_remote_wakeup_removed(int bus, int addr) "dev %d:%d" + +# dev-serial.c +usb_serial_reset(int bus, int addr) "dev %d:%u reset" +usb_serial_handle_control(int bus, int addr, int request, int value) "dev %d:%u got control 0x%x, value 0x%x" +usb_serial_unsupported_parity(int bus, int addr, int value) "dev %d:%u unsupported parity %d" +usb_serial_unsupported_stopbits(int bus, int addr, int value) "dev %d:%u unsupported stop bits %d" +usb_serial_unsupported_control(int bus, int addr, int request, int value) "dev %d:%u got unsupported/bogus control 0x%x, value 0x%x" +usb_serial_unsupported_data_bits(int bus, int addr, int value) "dev %d:%u unsupported data bits %d, falling back to 8" +usb_serial_bad_token(int bus, int addr) "dev %d:%u bad token" +usb_serial_set_baud(int bus, int addr, int baud) "dev %d:%u baud rate %d" +usb_serial_set_data(int bus, int addr, int parity, int data, int stop) "dev %d:%u parity %c, data bits %d, stop bits %d" +usb_serial_set_flow_control(int bus, int addr, int index) "dev %d:%u flow control %d" +usb_serial_set_xonxoff(int bus, int addr, uint8_t xon, uint8_t xoff) "dev %d:%u xon 0x%x xoff 0x%x" diff --git a/hw/usb/trace.h b/hw/usb/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..f3962f2baf10af2c6fa10e8e3f342ee338954f00 --- /dev/null +++ b/hw/usb/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_usb.h" diff --git a/hw/usb/tusb6010.c b/hw/usb/tusb6010.c index 17580876c682361cd7266d85677783432be00455..1dd4071e6839babe2f2212fdfba13d3459b0c0e2 100644 --- a/hw/usb/tusb6010.c +++ b/hw/usb/tusb6010.c @@ -23,15 +23,17 @@ #include "qemu/module.h" #include "qemu/timer.h" #include "hw/usb.h" +#include "hw/usb/hcd-musb.h" #include "hw/arm/omap.h" #include "hw/hw.h" #include "hw/irq.h" #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_TUSB6010 "tusb6010" -#define TUSB(obj) OBJECT_CHECK(TUSBState, (obj), TYPE_TUSB6010) +OBJECT_DECLARE_SIMPLE_TYPE(TUSBState, TUSB6010) -typedef struct TUSBState { +struct TUSBState { SysBusDevice parent_obj; MemoryRegion iomem[2]; @@ -67,7 +69,7 @@ typedef struct TUSBState { uint32_t pullup[2]; uint32_t control_config; uint32_t otg_timer_val; -} TUSBState; +}; #define TUSB_DEVCLOCK 60000000 /* 60 MHz */ @@ -775,7 +777,7 @@ static void tusb6010_irq(void *opaque, int source, int level) static void tusb6010_reset(DeviceState *dev) { - TUSBState *s = TUSB(dev); + TUSBState *s = TUSB6010(dev); int i; s->test_reset = TUSB_PROD_TEST_RESET_VAL; @@ -811,7 +813,7 @@ static void tusb6010_reset(DeviceState *dev) static void tusb6010_realize(DeviceState *dev, Error **errp) { - TUSBState *s = TUSB(dev); + TUSBState *s = TUSB6010(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); s->otg_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, tusb_otg_tick, s); diff --git a/hw/usb/u2f-emulated.c b/hw/usb/u2f-emulated.c new file mode 100644 index 0000000000000000000000000000000000000000..9151feb63d449027b47ee6c55708fdc2a7fa9f7b --- /dev/null +++ b/hw/usb/u2f-emulated.c @@ -0,0 +1,405 @@ +/* + * U2F USB Emulated device. + * + * Copyright (c) 2020 CĂ©sar Belley + * Written by CĂ©sar Belley + * + * 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 "qemu/module.h" +#include "qemu/thread.h" +#include "qemu/main-loop.h" +#include "qapi/error.h" +#include "hw/usb.h" +#include "hw/qdev-properties.h" + +#include + +#include "u2f.h" + +/* Counter which sync with a file */ +struct synced_counter { + /* Emulated device counter */ + struct u2f_emu_vdev_counter vdev_counter; + + /* Private attributes */ + uint32_t value; + FILE *fp; +}; + +static void counter_increment(struct u2f_emu_vdev_counter *vdev_counter) +{ + struct synced_counter *counter = (struct synced_counter *)vdev_counter; + ++counter->value; + + /* Write back */ + if (fseek(counter->fp, 0, SEEK_SET) == -1) { + return; + } + fprintf(counter->fp, "%u\n", counter->value); +} + +static uint32_t counter_read(struct u2f_emu_vdev_counter *vdev_counter) +{ + struct synced_counter *counter = (struct synced_counter *)vdev_counter; + return counter->value; +} + +typedef struct U2FEmulatedState U2FEmulatedState; + +#define PENDING_OUT_NUM 32 + +struct U2FEmulatedState { + U2FKeyState base; + + /* U2F virtual emulated device */ + u2f_emu_vdev *vdev; + QemuMutex vdev_mutex; + + /* Properties */ + char *dir; + char *cert; + char *privkey; + char *entropy; + char *counter; + struct synced_counter synced_counter; + + /* Pending packets received from the guest */ + uint8_t pending_out[PENDING_OUT_NUM][U2FHID_PACKET_SIZE]; + uint8_t pending_out_start; + uint8_t pending_out_end; + uint8_t pending_out_num; + QemuMutex pending_out_mutex; + + /* Emulation thread and sync */ + QemuCond key_cond; + QemuMutex key_mutex; + QemuThread key_thread; + bool stop_thread; + EventNotifier notifier; +}; + +#define TYPE_U2F_EMULATED "u2f-emulated" +#define EMULATED_U2F_KEY(obj) \ + OBJECT_CHECK(U2FEmulatedState, (obj), TYPE_U2F_EMULATED) + +static void u2f_emulated_reset(U2FEmulatedState *key) +{ + key->pending_out_start = 0; + key->pending_out_end = 0; + key->pending_out_num = 0; +} + +static void u2f_pending_out_add(U2FEmulatedState *key, + const uint8_t packet[U2FHID_PACKET_SIZE]) +{ + int index; + + if (key->pending_out_num >= PENDING_OUT_NUM) { + return; + } + + index = key->pending_out_end; + key->pending_out_end = (index + 1) % PENDING_OUT_NUM; + ++key->pending_out_num; + + memcpy(&key->pending_out[index], packet, U2FHID_PACKET_SIZE); +} + +static uint8_t *u2f_pending_out_get(U2FEmulatedState *key) +{ + int index; + + if (key->pending_out_num == 0) { + return NULL; + } + + index = key->pending_out_start; + key->pending_out_start = (index + 1) % PENDING_OUT_NUM; + --key->pending_out_num; + + return key->pending_out[index]; +} + +static void u2f_emulated_recv_from_guest(U2FKeyState *base, + const uint8_t packet[U2FHID_PACKET_SIZE]) +{ + U2FEmulatedState *key = EMULATED_U2F_KEY(base); + + qemu_mutex_lock(&key->pending_out_mutex); + u2f_pending_out_add(key, packet); + qemu_mutex_unlock(&key->pending_out_mutex); + + qemu_mutex_lock(&key->key_mutex); + qemu_cond_signal(&key->key_cond); + qemu_mutex_unlock(&key->key_mutex); +} + +static void *u2f_emulated_thread(void* arg) +{ + U2FEmulatedState *key = arg; + uint8_t packet[U2FHID_PACKET_SIZE]; + uint8_t *packet_out = NULL; + + + while (true) { + /* Wait signal */ + qemu_mutex_lock(&key->key_mutex); + qemu_cond_wait(&key->key_cond, &key->key_mutex); + qemu_mutex_unlock(&key->key_mutex); + + /* Exit thread check */ + if (key->stop_thread) { + key->stop_thread = false; + break; + } + + qemu_mutex_lock(&key->pending_out_mutex); + packet_out = u2f_pending_out_get(key); + if (packet_out == NULL) { + qemu_mutex_unlock(&key->pending_out_mutex); + continue; + } + memcpy(packet, packet_out, U2FHID_PACKET_SIZE); + qemu_mutex_unlock(&key->pending_out_mutex); + + qemu_mutex_lock(&key->vdev_mutex); + u2f_emu_vdev_send(key->vdev, U2F_EMU_USB, packet, + U2FHID_PACKET_SIZE); + + /* Notify response */ + if (u2f_emu_vdev_has_response(key->vdev, U2F_EMU_USB)) { + event_notifier_set(&key->notifier); + } + qemu_mutex_unlock(&key->vdev_mutex); + } + return NULL; +} + +static ssize_t u2f_emulated_read(const char *path, char *buffer, + size_t buffer_len) +{ + int fd; + ssize_t ret; + + fd = qemu_open_old(path, O_RDONLY); + if (fd < 0) { + return -1; + } + + ret = read(fd, buffer, buffer_len); + close(fd); + + return ret; +} + +static bool u2f_emulated_setup_counter(const char *path, + struct synced_counter *counter) +{ + int fd, ret; + FILE *fp; + + fd = qemu_open_old(path, O_RDWR); + if (fd < 0) { + return false; + } + fp = fdopen(fd, "r+"); + if (fp == NULL) { + close(fd); + return false; + } + ret = fscanf(fp, "%u", &counter->value); + if (ret == EOF) { + fclose(fp); + return false; + } + counter->fp = fp; + counter->vdev_counter.counter_increment = counter_increment; + counter->vdev_counter.counter_read = counter_read; + + return true; +} + +static u2f_emu_rc u2f_emulated_setup_vdev_manualy(U2FEmulatedState *key) +{ + ssize_t ret; + char cert_pem[4096], privkey_pem[2048]; + struct u2f_emu_vdev_setup setup_info; + + /* Certificate */ + ret = u2f_emulated_read(key->cert, cert_pem, sizeof(cert_pem)); + if (ret < 0) { + return -1; + } + + /* Private key */ + ret = u2f_emulated_read(key->privkey, privkey_pem, sizeof(privkey_pem)); + if (ret < 0) { + return -1; + } + + /* Entropy */ + ret = u2f_emulated_read(key->entropy, (char *)&setup_info.entropy, + sizeof(setup_info.entropy)); + if (ret < 0) { + return -1; + } + + /* Counter */ + if (!u2f_emulated_setup_counter(key->counter, &key->synced_counter)) { + return -1; + } + + /* Setup */ + setup_info.certificate = cert_pem; + setup_info.private_key = privkey_pem; + setup_info.counter = (struct u2f_emu_vdev_counter *)&key->synced_counter; + + return u2f_emu_vdev_new(&key->vdev, &setup_info); +} + +static void u2f_emulated_event_handler(EventNotifier *notifier) +{ + U2FEmulatedState *key = container_of(notifier, U2FEmulatedState, notifier); + size_t packet_size; + uint8_t *packet_in = NULL; + + event_notifier_test_and_clear(&key->notifier); + qemu_mutex_lock(&key->vdev_mutex); + while (u2f_emu_vdev_has_response(key->vdev, U2F_EMU_USB)) { + packet_size = u2f_emu_vdev_get_response(key->vdev, U2F_EMU_USB, + &packet_in); + if (packet_size == U2FHID_PACKET_SIZE) { + u2f_send_to_guest(&key->base, packet_in); + } + u2f_emu_vdev_free_response(packet_in); + } + qemu_mutex_unlock(&key->vdev_mutex); +} + +static void u2f_emulated_realize(U2FKeyState *base, Error **errp) +{ + U2FEmulatedState *key = EMULATED_U2F_KEY(base); + u2f_emu_rc rc; + + if (key->cert != NULL || key->privkey != NULL || key->entropy != NULL + || key->counter != NULL) { + if (key->cert != NULL && key->privkey != NULL + && key->entropy != NULL && key->counter != NULL) { + rc = u2f_emulated_setup_vdev_manualy(key); + } else { + error_setg(errp, "%s: cert, priv, entropy and counter " + "parameters must be provided to manualy configure " + "the emulated device", TYPE_U2F_EMULATED); + return; + } + } else if (key->dir != NULL) { + rc = u2f_emu_vdev_new_from_dir(&key->vdev, key->dir); + } else { + rc = u2f_emu_vdev_new_ephemeral(&key->vdev); + } + + if (rc != U2F_EMU_OK) { + error_setg(errp, "%s: Failed to setup the key", TYPE_U2F_EMULATED); + return; + } + + if (event_notifier_init(&key->notifier, false) < 0) { + error_setg(errp, "%s: Failed to initialize notifier", + TYPE_U2F_EMULATED); + return; + } + /* Notifier */ + event_notifier_set_handler(&key->notifier, u2f_emulated_event_handler); + + /* Synchronization */ + qemu_cond_init(&key->key_cond); + qemu_mutex_init(&key->vdev_mutex); + qemu_mutex_init(&key->pending_out_mutex); + qemu_mutex_init(&key->key_mutex); + u2f_emulated_reset(key); + + /* Thread */ + key->stop_thread = false; + qemu_thread_create(&key->key_thread, "u2f-key", u2f_emulated_thread, + key, QEMU_THREAD_JOINABLE); +} + +static void u2f_emulated_unrealize(U2FKeyState *base) +{ + U2FEmulatedState *key = EMULATED_U2F_KEY(base); + + /* Thread */ + key->stop_thread = true; + qemu_cond_signal(&key->key_cond); + qemu_thread_join(&key->key_thread); + + /* Notifier */ + event_notifier_set_handler(&key->notifier, NULL); + event_notifier_cleanup(&key->notifier); + + /* Synchronization */ + qemu_cond_destroy(&key->key_cond); + qemu_mutex_destroy(&key->vdev_mutex); + qemu_mutex_destroy(&key->key_mutex); + qemu_mutex_destroy(&key->pending_out_mutex); + + /* Vdev */ + u2f_emu_vdev_free(key->vdev); + if (key->synced_counter.fp != NULL) { + fclose(key->synced_counter.fp); + } +} + +static Property u2f_emulated_properties[] = { + DEFINE_PROP_STRING("dir", U2FEmulatedState, dir), + DEFINE_PROP_STRING("cert", U2FEmulatedState, cert), + DEFINE_PROP_STRING("privkey", U2FEmulatedState, privkey), + DEFINE_PROP_STRING("entropy", U2FEmulatedState, entropy), + DEFINE_PROP_STRING("counter", U2FEmulatedState, counter), + DEFINE_PROP_END_OF_LIST(), +}; + +static void u2f_emulated_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + U2FKeyClass *kc = U2F_KEY_CLASS(klass); + + kc->realize = u2f_emulated_realize; + kc->unrealize = u2f_emulated_unrealize; + kc->recv_from_guest = u2f_emulated_recv_from_guest; + dc->desc = "QEMU U2F emulated key"; + device_class_set_props(dc, u2f_emulated_properties); +} + +static const TypeInfo u2f_key_emulated_info = { + .name = TYPE_U2F_EMULATED, + .parent = TYPE_U2F_KEY, + .instance_size = sizeof(U2FEmulatedState), + .class_init = u2f_emulated_class_init +}; + +static void u2f_key_emulated_register_types(void) +{ + type_register_static(&u2f_key_emulated_info); +} + +type_init(u2f_key_emulated_register_types) diff --git a/hw/usb/u2f-passthru.c b/hw/usb/u2f-passthru.c new file mode 100644 index 0000000000000000000000000000000000000000..ae00e93f3507b58122e5ed495a767de21b27b652 --- /dev/null +++ b/hw/usb/u2f-passthru.c @@ -0,0 +1,551 @@ +/* + * U2F USB Passthru device. + * + * Copyright (c) 2020 CĂ©sar Belley + * Written by CĂ©sar Belley + * + * 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 "qemu/module.h" +#include "qemu/main-loop.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/qdev-properties.h" +#include "hw/usb.h" +#include "migration/vmstate.h" + +#include "u2f.h" + +#ifdef CONFIG_LIBUDEV +#include +#endif +#include +#include + +#define NONCE_SIZE 8 +#define BROADCAST_CID 0xFFFFFFFF +#define TRANSACTION_TIMEOUT 120000 + +struct transaction { + uint32_t cid; + uint16_t resp_bcnt; + uint16_t resp_size; + + /* Nonce for broadcast isolation */ + uint8_t nonce[NONCE_SIZE]; +}; + +typedef struct U2FPassthruState U2FPassthruState; + +#define CURRENT_TRANSACTIONS_NUM 4 + +struct U2FPassthruState { + U2FKeyState base; + + /* Host device */ + char *hidraw; + int hidraw_fd; + + /* Current Transactions */ + struct transaction current_transactions[CURRENT_TRANSACTIONS_NUM]; + uint8_t current_transactions_start; + uint8_t current_transactions_end; + uint8_t current_transactions_num; + + /* Transaction time checking */ + int64_t last_transaction_time; + QEMUTimer timer; +}; + +#define TYPE_U2F_PASSTHRU "u2f-passthru" +#define PASSTHRU_U2F_KEY(obj) \ + OBJECT_CHECK(U2FPassthruState, (obj), TYPE_U2F_PASSTHRU) + +/* Init packet sizes */ +#define PACKET_INIT_HEADER_SIZE 7 +#define PACKET_INIT_DATA_SIZE (U2FHID_PACKET_SIZE - PACKET_INIT_HEADER_SIZE) + +/* Cont packet sizes */ +#define PACKET_CONT_HEADER_SIZE 5 +#define PACKET_CONT_DATA_SIZE (U2FHID_PACKET_SIZE - PACKET_CONT_HEADER_SIZE) + +struct packet_init { + uint32_t cid; + uint8_t cmd; + uint8_t bcnth; + uint8_t bcntl; + uint8_t data[PACKET_INIT_DATA_SIZE]; +} QEMU_PACKED; + +static inline uint32_t packet_get_cid(const void *packet) +{ + return *((uint32_t *)packet); +} + +static inline bool packet_is_init(const void *packet) +{ + return ((uint8_t *)packet)[4] & (1 << 7); +} + +static inline uint16_t packet_init_get_bcnt( + const struct packet_init *packet_init) +{ + uint16_t bcnt = 0; + bcnt |= packet_init->bcnth << 8; + bcnt |= packet_init->bcntl; + + return bcnt; +} + +static void u2f_passthru_reset(U2FPassthruState *key) +{ + timer_del(&key->timer); + qemu_set_fd_handler(key->hidraw_fd, NULL, NULL, key); + key->last_transaction_time = 0; + key->current_transactions_start = 0; + key->current_transactions_end = 0; + key->current_transactions_num = 0; +} + +static void u2f_timeout_check(void *opaque) +{ + U2FPassthruState *key = opaque; + int64_t time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); + + if (time > key->last_transaction_time + TRANSACTION_TIMEOUT) { + u2f_passthru_reset(key); + } else { + timer_mod(&key->timer, time + TRANSACTION_TIMEOUT / 4); + } +} + +static int u2f_transaction_get_index(U2FPassthruState *key, uint32_t cid) +{ + for (int i = 0; i < key->current_transactions_num; ++i) { + int index = (key->current_transactions_start + i) + % CURRENT_TRANSACTIONS_NUM; + if (cid == key->current_transactions[index].cid) { + return index; + } + } + return -1; +} + +static struct transaction *u2f_transaction_get(U2FPassthruState *key, + uint32_t cid) +{ + int index = u2f_transaction_get_index(key, cid); + if (index < 0) { + return NULL; + } + return &key->current_transactions[index]; +} + +static struct transaction *u2f_transaction_get_from_nonce(U2FPassthruState *key, + const uint8_t nonce[NONCE_SIZE]) +{ + for (int i = 0; i < key->current_transactions_num; ++i) { + int index = (key->current_transactions_start + i) + % CURRENT_TRANSACTIONS_NUM; + if (key->current_transactions[index].cid == BROADCAST_CID + && memcmp(nonce, key->current_transactions[index].nonce, + NONCE_SIZE) == 0) { + return &key->current_transactions[index]; + } + } + return NULL; +} + +static void u2f_transaction_close(U2FPassthruState *key, uint32_t cid) +{ + int index, next_index; + index = u2f_transaction_get_index(key, cid); + if (index < 0) { + return; + } + next_index = (index + 1) % CURRENT_TRANSACTIONS_NUM; + + /* Rearrange to ensure the oldest is at the start position */ + while (next_index != key->current_transactions_end) { + memcpy(&key->current_transactions[index], + &key->current_transactions[next_index], + sizeof(struct transaction)); + + index = next_index; + next_index = (index + 1) % CURRENT_TRANSACTIONS_NUM; + } + + key->current_transactions_end = index; + --key->current_transactions_num; + + if (key->current_transactions_num == 0) { + u2f_passthru_reset(key); + } +} + +static void u2f_transaction_add(U2FPassthruState *key, uint32_t cid, + const uint8_t nonce[NONCE_SIZE]) +{ + uint8_t index; + struct transaction *transaction; + + if (key->current_transactions_num >= CURRENT_TRANSACTIONS_NUM) { + /* Close the oldest transaction */ + index = key->current_transactions_start; + transaction = &key->current_transactions[index]; + u2f_transaction_close(key, transaction->cid); + } + + /* Index */ + index = key->current_transactions_end; + key->current_transactions_end = (index + 1) % CURRENT_TRANSACTIONS_NUM; + ++key->current_transactions_num; + + /* Transaction */ + transaction = &key->current_transactions[index]; + transaction->cid = cid; + transaction->resp_bcnt = 0; + transaction->resp_size = 0; + + /* Nonce */ + if (nonce != NULL) { + memcpy(transaction->nonce, nonce, NONCE_SIZE); + } +} + +static void u2f_passthru_read(void *opaque); + +static void u2f_transaction_start(U2FPassthruState *key, + const struct packet_init *packet_init) +{ + int64_t time; + + /* Transaction */ + if (packet_init->cid == BROADCAST_CID) { + u2f_transaction_add(key, packet_init->cid, packet_init->data); + } else { + u2f_transaction_add(key, packet_init->cid, NULL); + } + + /* Time */ + time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); + if (key->last_transaction_time == 0) { + qemu_set_fd_handler(key->hidraw_fd, u2f_passthru_read, NULL, key); + timer_init_ms(&key->timer, QEMU_CLOCK_VIRTUAL, u2f_timeout_check, key); + timer_mod(&key->timer, time + TRANSACTION_TIMEOUT / 4); + } + key->last_transaction_time = time; +} + +static void u2f_passthru_recv_from_host(U2FPassthruState *key, + const uint8_t packet[U2FHID_PACKET_SIZE]) +{ + struct transaction *transaction; + uint32_t cid; + + /* Retrieve transaction */ + cid = packet_get_cid(packet); + if (cid == BROADCAST_CID) { + struct packet_init *packet_init; + if (!packet_is_init(packet)) { + return; + } + packet_init = (struct packet_init *)packet; + transaction = u2f_transaction_get_from_nonce(key, packet_init->data); + } else { + transaction = u2f_transaction_get(key, cid); + } + + /* Ignore no started transaction */ + if (transaction == NULL) { + return; + } + + if (packet_is_init(packet)) { + struct packet_init *packet_init = (struct packet_init *)packet; + transaction->resp_bcnt = packet_init_get_bcnt(packet_init); + transaction->resp_size = PACKET_INIT_DATA_SIZE; + + if (packet_init->cid == BROADCAST_CID) { + /* Nonce checking for legitimate response */ + if (memcmp(transaction->nonce, packet_init->data, NONCE_SIZE) + != 0) { + return; + } + } + } else { + transaction->resp_size += PACKET_CONT_DATA_SIZE; + } + + /* Transaction end check */ + if (transaction->resp_size >= transaction->resp_bcnt) { + u2f_transaction_close(key, cid); + } + u2f_send_to_guest(&key->base, packet); +} + +static void u2f_passthru_read(void *opaque) +{ + U2FPassthruState *key = opaque; + U2FKeyState *base = &key->base; + uint8_t packet[2 * U2FHID_PACKET_SIZE]; + int ret; + + /* Full size base queue check */ + if (base->pending_in_num >= U2FHID_PENDING_IN_NUM) { + return; + } + + ret = read(key->hidraw_fd, packet, sizeof(packet)); + if (ret < 0) { + /* Detach */ + if (base->dev.attached) { + usb_device_detach(&base->dev); + u2f_passthru_reset(key); + } + return; + } + if (ret != U2FHID_PACKET_SIZE) { + return; + } + u2f_passthru_recv_from_host(key, packet); +} + +static void u2f_passthru_recv_from_guest(U2FKeyState *base, + const uint8_t packet[U2FHID_PACKET_SIZE]) +{ + U2FPassthruState *key = PASSTHRU_U2F_KEY(base); + uint8_t host_packet[U2FHID_PACKET_SIZE + 1]; + ssize_t written; + + if (packet_is_init(packet)) { + u2f_transaction_start(key, (struct packet_init *)packet); + } + + host_packet[0] = 0; + memcpy(host_packet + 1, packet, U2FHID_PACKET_SIZE); + + written = write(key->hidraw_fd, host_packet, sizeof(host_packet)); + if (written != sizeof(host_packet)) { + error_report("%s: Bad written size (req 0x%zu, val 0x%zd)", + TYPE_U2F_PASSTHRU, sizeof(host_packet), written); + } +} + +static bool u2f_passthru_is_u2f_device(int fd) +{ + int ret, rdesc_size; + struct hidraw_report_descriptor rdesc; + const uint8_t u2f_hid_report_desc_header[] = { + 0x06, 0xd0, 0xf1, /* Usage Page (FIDO) */ + 0x09, 0x01, /* Usage (FIDO) */ + }; + + /* Get report descriptor size */ + ret = ioctl(fd, HIDIOCGRDESCSIZE, &rdesc_size); + if (ret < 0 || rdesc_size < sizeof(u2f_hid_report_desc_header)) { + return false; + } + + /* Get report descriptor */ + memset(&rdesc, 0x0, sizeof(rdesc)); + rdesc.size = rdesc_size; + ret = ioctl(fd, HIDIOCGRDESC, &rdesc); + if (ret < 0) { + return false; + } + + /* Header bytes cover specific U2F rdesc values */ + return memcmp(u2f_hid_report_desc_header, rdesc.value, + sizeof(u2f_hid_report_desc_header)) == 0; +} + +#ifdef CONFIG_LIBUDEV +static int u2f_passthru_open_from_device(struct udev_device *device) +{ + const char *devnode = udev_device_get_devnode(device); + + int fd = qemu_open_old(devnode, O_RDWR); + if (fd < 0) { + return -1; + } else if (!u2f_passthru_is_u2f_device(fd)) { + qemu_close(fd); + return -1; + } + return fd; +} + +static int u2f_passthru_open_from_enumerate(struct udev *udev, + struct udev_enumerate *enumerate) +{ + struct udev_list_entry *devices, *entry; + int ret, fd; + + ret = udev_enumerate_scan_devices(enumerate); + if (ret < 0) { + return -1; + } + + devices = udev_enumerate_get_list_entry(enumerate); + udev_list_entry_foreach(entry, devices) { + struct udev_device *device; + const char *syspath = udev_list_entry_get_name(entry); + + if (syspath == NULL) { + continue; + } + + device = udev_device_new_from_syspath(udev, syspath); + if (device == NULL) { + continue; + } + + fd = u2f_passthru_open_from_device(device); + udev_device_unref(device); + if (fd >= 0) { + return fd; + } + } + return -1; +} + +static int u2f_passthru_open_from_scan(void) +{ + struct udev *udev; + struct udev_enumerate *enumerate; + int ret, fd = -1; + + udev = udev_new(); + if (udev == NULL) { + return -1; + } + + enumerate = udev_enumerate_new(udev); + if (enumerate == NULL) { + udev_unref(udev); + return -1; + } + + ret = udev_enumerate_add_match_subsystem(enumerate, "hidraw"); + if (ret >= 0) { + fd = u2f_passthru_open_from_enumerate(udev, enumerate); + } + + udev_enumerate_unref(enumerate); + udev_unref(udev); + + return fd; +} +#endif + +static void u2f_passthru_unrealize(U2FKeyState *base) +{ + U2FPassthruState *key = PASSTHRU_U2F_KEY(base); + + u2f_passthru_reset(key); + qemu_close(key->hidraw_fd); +} + +static void u2f_passthru_realize(U2FKeyState *base, Error **errp) +{ + U2FPassthruState *key = PASSTHRU_U2F_KEY(base); + int fd; + + if (key->hidraw == NULL) { +#ifdef CONFIG_LIBUDEV + fd = u2f_passthru_open_from_scan(); + if (fd < 0) { + error_setg(errp, "%s: Failed to find a U2F USB device", + TYPE_U2F_PASSTHRU); + return; + } +#else + error_setg(errp, "%s: Missing hidraw", TYPE_U2F_PASSTHRU); + return; +#endif + } else { + fd = qemu_open_old(key->hidraw, O_RDWR); + if (fd < 0) { + error_setg(errp, "%s: Failed to open %s", TYPE_U2F_PASSTHRU, + key->hidraw); + return; + } + + if (!u2f_passthru_is_u2f_device(fd)) { + qemu_close(fd); + error_setg(errp, "%s: Passed hidraw does not represent " + "a U2F HID device", TYPE_U2F_PASSTHRU); + return; + } + } + key->hidraw_fd = fd; + u2f_passthru_reset(key); +} + +static int u2f_passthru_post_load(void *opaque, int version_id) +{ + U2FPassthruState *key = opaque; + u2f_passthru_reset(key); + return 0; +} + +static const VMStateDescription u2f_passthru_vmstate = { + .name = "u2f-key-passthru", + .version_id = 1, + .minimum_version_id = 1, + .post_load = u2f_passthru_post_load, + .fields = (VMStateField[]) { + VMSTATE_U2F_KEY(base, U2FPassthruState), + VMSTATE_END_OF_LIST() + } +}; + +static Property u2f_passthru_properties[] = { + DEFINE_PROP_STRING("hidraw", U2FPassthruState, hidraw), + DEFINE_PROP_END_OF_LIST(), +}; + +static void u2f_passthru_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + U2FKeyClass *kc = U2F_KEY_CLASS(klass); + + kc->realize = u2f_passthru_realize; + kc->unrealize = u2f_passthru_unrealize; + kc->recv_from_guest = u2f_passthru_recv_from_guest; + dc->desc = "QEMU U2F passthrough key"; + dc->vmsd = &u2f_passthru_vmstate; + device_class_set_props(dc, u2f_passthru_properties); +} + +static const TypeInfo u2f_key_passthru_info = { + .name = TYPE_U2F_PASSTHRU, + .parent = TYPE_U2F_KEY, + .instance_size = sizeof(U2FPassthruState), + .class_init = u2f_passthru_class_init +}; + +static void u2f_key_passthru_register_types(void) +{ + type_register_static(&u2f_key_passthru_info); +} + +type_init(u2f_key_passthru_register_types) diff --git a/hw/usb/u2f.c b/hw/usb/u2f.c new file mode 100644 index 0000000000000000000000000000000000000000..bc09191f063e923c3e0cbc9c9c7332df032fa0c0 --- /dev/null +++ b/hw/usb/u2f.c @@ -0,0 +1,352 @@ +/* + * U2F USB device. + * + * Copyright (c) 2020 CĂ©sar Belley + * Written by CĂ©sar Belley + * + * 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 "qemu/module.h" +#include "qapi/error.h" +#include "hw/usb.h" +#include "hw/usb/hid.h" +#include "migration/vmstate.h" +#include "desc.h" + +#include "u2f.h" + +/* U2F key Vendor / Product */ +#define U2F_KEY_VENDOR_NUM 0x46f4 /* CRC16() of "QEMU" */ +#define U2F_KEY_PRODUCT_NUM 0x0005 + +enum { + STR_MANUFACTURER = 1, + STR_PRODUCT, + STR_SERIALNUMBER, + STR_CONFIG, + STR_INTERFACE +}; + +static const USBDescStrings desc_strings = { + [STR_MANUFACTURER] = "QEMU", + [STR_PRODUCT] = "U2F USB key", + [STR_SERIALNUMBER] = "0", + [STR_CONFIG] = "U2F key config", + [STR_INTERFACE] = "U2F key interface" +}; + +static const USBDescIface desc_iface_u2f_key = { + .bInterfaceNumber = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_HID, + .bInterfaceSubClass = 0x0, + .bInterfaceProtocol = 0x0, + .ndesc = 1, + .descs = (USBDescOther[]) { + { + /* HID descriptor */ + .data = (uint8_t[]) { + 0x09, /* u8 bLength */ + USB_DT_HID, /* u8 bDescriptorType */ + 0x10, 0x01, /* u16 HID_class */ + 0x00, /* u8 country_code */ + 0x01, /* u8 num_descriptors */ + USB_DT_REPORT, /* u8 type: Report */ + 0x22, 0, /* u16 len */ + }, + }, + }, + .eps = (USBDescEndpoint[]) { + { + .bEndpointAddress = USB_DIR_IN | 0x01, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = U2FHID_PACKET_SIZE, + .bInterval = 0x05, + }, { + .bEndpointAddress = USB_DIR_OUT | 0x01, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = U2FHID_PACKET_SIZE, + .bInterval = 0x05, + }, + }, + +}; + +static const USBDescDevice desc_device_u2f_key = { + .bcdUSB = 0x0100, + .bMaxPacketSize0 = U2FHID_PACKET_SIZE, + .bNumConfigurations = 1, + .confs = (USBDescConfig[]) { + { + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = STR_CONFIG, + .bmAttributes = USB_CFG_ATT_ONE, + .bMaxPower = 15, + .nif = 1, + .ifs = &desc_iface_u2f_key, + }, + }, +}; + +static const USBDesc desc_u2f_key = { + .id = { + .idVendor = U2F_KEY_VENDOR_NUM, + .idProduct = U2F_KEY_PRODUCT_NUM, + .bcdDevice = 0, + .iManufacturer = STR_MANUFACTURER, + .iProduct = STR_PRODUCT, + .iSerialNumber = STR_SERIALNUMBER, + }, + .full = &desc_device_u2f_key, + .str = desc_strings, +}; + +static const uint8_t u2f_key_hid_report_desc[] = { + 0x06, 0xd0, 0xf1, /* Usage Page (FIDO) */ + 0x09, 0x01, /* Usage (FIDO) */ + 0xa1, 0x01, /* Collection (HID Application) */ + 0x09, 0x20, /* Usage (FIDO data in) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x26, 0xFF, 0x00, /* Logical Maximum (0xff) */ + 0x75, 0x08, /* Report Size (8) */ + 0x95, 0x40, /* Report Count (0x40) */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + 0x09, 0x21, /* Usage (FIDO data out) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x26, 0xFF, 0x00, /* Logical Maximum (0xFF) */ + 0x75, 0x08, /* Report Size (8) */ + 0x95, 0x40, /* Report Count (0x40) */ + 0x91, 0x02, /* Output (Data, Variable, Absolute) */ + 0xC0 /* End Collection */ +}; + +static void u2f_key_reset(U2FKeyState *key) +{ + key->pending_in_start = 0; + key->pending_in_end = 0; + key->pending_in_num = 0; +} + +static void u2f_key_handle_reset(USBDevice *dev) +{ + U2FKeyState *key = U2F_KEY(dev); + + u2f_key_reset(key); +} + +static void u2f_key_handle_control(USBDevice *dev, USBPacket *p, + int request, int value, int index, int length, uint8_t *data) +{ + U2FKeyState *key = U2F_KEY(dev); + int ret; + + ret = usb_desc_handle_control(dev, p, request, value, index, length, data); + if (ret >= 0) { + return; + } + + switch (request) { + case InterfaceRequest | USB_REQ_GET_DESCRIPTOR: + switch (value >> 8) { + case 0x22: + memcpy(data, u2f_key_hid_report_desc, + sizeof(u2f_key_hid_report_desc)); + p->actual_length = sizeof(u2f_key_hid_report_desc); + break; + default: + goto fail; + } + break; + case HID_GET_IDLE: + data[0] = key->idle; + p->actual_length = 1; + break; + case HID_SET_IDLE: + key->idle = (uint8_t)(value >> 8); + break; + default: + fail: + p->status = USB_RET_STALL; + break; + } + +} + +static void u2f_key_recv_from_guest(U2FKeyState *key, USBPacket *p) +{ + U2FKeyClass *kc = U2F_KEY_GET_CLASS(key); + uint8_t packet[U2FHID_PACKET_SIZE]; + + if (kc->recv_from_guest == NULL || p->iov.size != U2FHID_PACKET_SIZE) { + return; + } + + usb_packet_copy(p, packet, p->iov.size); + kc->recv_from_guest(key, packet); +} + +static void u2f_pending_in_add(U2FKeyState *key, + const uint8_t packet[U2FHID_PACKET_SIZE]) +{ + uint8_t index; + + if (key->pending_in_num >= U2FHID_PENDING_IN_NUM) { + return; + } + + index = key->pending_in_end; + key->pending_in_end = (index + 1) % U2FHID_PENDING_IN_NUM; + ++key->pending_in_num; + + memcpy(key->pending_in[index], packet, U2FHID_PACKET_SIZE); +} + +static uint8_t *u2f_pending_in_get(U2FKeyState *key) +{ + uint8_t index; + + if (key->pending_in_num == 0) { + return NULL; + } + + index = key->pending_in_start; + key->pending_in_start = (index + 1) % U2FHID_PENDING_IN_NUM; + --key->pending_in_num; + + return key->pending_in[index]; +} + +static void u2f_key_handle_data(USBDevice *dev, USBPacket *p) +{ + U2FKeyState *key = U2F_KEY(dev); + uint8_t *packet_in; + + /* Endpoint number check */ + if (p->ep->nr != 1) { + p->status = USB_RET_STALL; + return; + } + + switch (p->pid) { + case USB_TOKEN_OUT: + u2f_key_recv_from_guest(key, p); + break; + case USB_TOKEN_IN: + packet_in = u2f_pending_in_get(key); + if (packet_in == NULL) { + p->status = USB_RET_NAK; + return; + } + usb_packet_copy(p, packet_in, U2FHID_PACKET_SIZE); + break; + default: + p->status = USB_RET_STALL; + break; + } +} + +void u2f_send_to_guest(U2FKeyState *key, + const uint8_t packet[U2FHID_PACKET_SIZE]) +{ + u2f_pending_in_add(key, packet); + usb_wakeup(key->ep, 0); +} + +static void u2f_key_unrealize(USBDevice *dev) +{ + U2FKeyState *key = U2F_KEY(dev); + U2FKeyClass *kc = U2F_KEY_GET_CLASS(key); + + if (kc->unrealize != NULL) { + kc->unrealize(key); + } +} + +static void u2f_key_realize(USBDevice *dev, Error **errp) +{ + U2FKeyState *key = U2F_KEY(dev); + U2FKeyClass *kc = U2F_KEY_GET_CLASS(key); + Error *local_err = NULL; + + usb_desc_create_serial(dev); + usb_desc_init(dev); + u2f_key_reset(key); + + if (kc->realize != NULL) { + kc->realize(key, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; + } + } + key->ep = usb_ep_get(dev, USB_TOKEN_IN, 1); +} + +const VMStateDescription vmstate_u2f_key = { + .name = "u2f-key", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_USB_DEVICE(dev, U2FKeyState), + VMSTATE_UINT8(idle, U2FKeyState), + VMSTATE_UINT8_2DARRAY(pending_in, U2FKeyState, + U2FHID_PENDING_IN_NUM, U2FHID_PACKET_SIZE), + VMSTATE_UINT8(pending_in_start, U2FKeyState), + VMSTATE_UINT8(pending_in_end, U2FKeyState), + VMSTATE_UINT8(pending_in_num, U2FKeyState), + VMSTATE_END_OF_LIST() + } +}; + +static void u2f_key_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->product_desc = "QEMU U2F USB key"; + uc->usb_desc = &desc_u2f_key; + uc->handle_reset = u2f_key_handle_reset; + uc->handle_control = u2f_key_handle_control; + uc->handle_data = u2f_key_handle_data; + uc->handle_attach = usb_desc_attach; + uc->realize = u2f_key_realize; + uc->unrealize = u2f_key_unrealize; + dc->desc = "QEMU U2F key"; + dc->vmsd = &vmstate_u2f_key; +} + +static const TypeInfo u2f_key_info = { + .name = TYPE_U2F_KEY, + .parent = TYPE_USB_DEVICE, + .instance_size = sizeof(U2FKeyState), + .abstract = true, + .class_size = sizeof(U2FKeyClass), + .class_init = u2f_key_class_init, +}; + +static void u2f_key_register_types(void) +{ + type_register_static(&u2f_key_info); + usb_legacy_register(TYPE_U2F_KEY, "u2f-key", NULL); +} + +type_init(u2f_key_register_types) diff --git a/hw/usb/u2f.h b/hw/usb/u2f.h new file mode 100644 index 0000000000000000000000000000000000000000..db30f3586bf7ae282b2f67ab40c063841031c332 --- /dev/null +++ b/hw/usb/u2f.h @@ -0,0 +1,92 @@ +/* + * U2F USB device. + * + * Copyright (c) 2020 CĂ©sar Belley + * Written by CĂ©sar Belley + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef U2F_H +#define U2F_H + +#include "hw/qdev-core.h" + +#define U2FHID_PACKET_SIZE 64 +#define U2FHID_PENDING_IN_NUM 32 + +typedef struct U2FKeyState U2FKeyState; +typedef struct U2FKeyInfo U2FKeyInfo; + +#define TYPE_U2F_KEY "u2f-key" +#define U2F_KEY(obj) \ + OBJECT_CHECK(U2FKeyState, (obj), TYPE_U2F_KEY) +#define U2F_KEY_CLASS(klass) \ + OBJECT_CLASS_CHECK(U2FKeyClass, (klass), TYPE_U2F_KEY) +#define U2F_KEY_GET_CLASS(obj) \ + OBJECT_GET_CLASS(U2FKeyClass, (obj), TYPE_U2F_KEY) + +/* + * Callbacks to be used by the U2F key base device (i.e. hw/u2f.c) + * to interact with its variants (i.e. hw/u2f-*.c) + */ +typedef struct U2FKeyClass { + /*< private >*/ + USBDeviceClass parent_class; + + /*< public >*/ + void (*recv_from_guest)(U2FKeyState *key, + const uint8_t packet[U2FHID_PACKET_SIZE]); + void (*realize)(U2FKeyState *key, Error **errp); + void (*unrealize)(U2FKeyState *key); +} U2FKeyClass; + +/* + * State of the U2F key base device (i.e. hw/u2f.c) + */ +typedef struct U2FKeyState { + USBDevice dev; + USBEndpoint *ep; + uint8_t idle; + + /* Pending packets to be send to the guest */ + uint8_t pending_in[U2FHID_PENDING_IN_NUM][U2FHID_PACKET_SIZE]; + uint8_t pending_in_start; + uint8_t pending_in_end; + uint8_t pending_in_num; +} U2FKeyState; + +/* + * API to be used by the U2F key device variants (i.e. hw/u2f-*.c) + * to interact with the the U2F key base device (i.e. hw/u2f.c) + */ +void u2f_send_to_guest(U2FKeyState *key, + const uint8_t packet[U2FHID_PACKET_SIZE]); + +extern const VMStateDescription vmstate_u2f_key; + +#define VMSTATE_U2F_KEY(_field, _state) { \ + .name = (stringify(_field)), \ + .size = sizeof(U2FKeyState), \ + .vmsd = &vmstate_u2f_key, \ + .flags = VMS_STRUCT, \ + .offset = vmstate_offset_value(_state, _field, U2FKeyState), \ +} + +#endif /* U2F_H */ diff --git a/hw/usb/xen-usb.c b/hw/usb/xen-usb.c index 961190d0f78cd68d74508f3de0dae90321a5ba03..4d266d7bb4508c6c8404100be000db53459e7fd3 100644 --- a/hw/usb/xen-usb.c +++ b/hw/usb/xen-usb.c @@ -30,6 +30,7 @@ #include "hw/usb.h" #include "hw/xen/xen-legacy-backend.h" #include "monitor/qdev.h" +#include "qapi/error.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qstring.h" @@ -755,13 +756,16 @@ static void usbback_portid_add(struct usbback_info *usbif, unsigned port, qdict_put_int(qdict, "port", port); qdict_put_int(qdict, "hostbus", atoi(busid)); qdict_put_str(qdict, "hostport", portname); - opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_err); - if (local_err) { - goto err; - } + opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, + &error_abort); usbif->ports[port - 1].dev = USB_DEVICE(qdev_device_add(opts, &local_err)); if (!usbif->ports[port - 1].dev) { - goto err; + qobject_unref(qdict); + xen_pv_printf(&usbif->xendev, 0, + "device %s could not be opened: %s\n", + busid, error_get_pretty(local_err)); + error_free(local_err); + return; } qobject_unref(qdict); speed = usbif->ports[port - 1].dev->speed; @@ -793,11 +797,6 @@ static void usbback_portid_add(struct usbback_info *usbif, unsigned port, usbback_hotplug_enq(usbif, port); TR_BUS(&usbif->xendev, "port %d attached\n", port); - return; - -err: - qobject_unref(qdict); - xen_pv_printf(&usbif->xendev, 0, "device %s could not be opened\n", busid); } static void usbback_process_port(struct usbback_info *usbif, unsigned port) diff --git a/hw/vfio/Makefile.objs b/hw/vfio/Makefile.objs deleted file mode 100644 index 9bb1c09e8477d338729a61109101bca364a52a10..0000000000000000000000000000000000000000 --- a/hw/vfio/Makefile.objs +++ /dev/null @@ -1,8 +0,0 @@ -obj-y += common.o spapr.o -obj-$(CONFIG_VFIO_PCI) += pci.o pci-quirks.o display.o -obj-$(CONFIG_VFIO_CCW) += ccw.o -obj-$(CONFIG_VFIO_PLATFORM) += platform.o -obj-$(CONFIG_VFIO_XGMAC) += calxeda-xgmac.o -obj-$(CONFIG_VFIO_AMD_XGBE) += amd-xgbe.o -obj-$(CONFIG_VFIO_AP) += ap.o -obj-$(CONFIG_VFIO_IGD) += igd.o diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c index 95564c17eda56a9b9c1fb08acf53b6fad772afd1..9571c2f91fdc5f79b0aa1736530dd9695fdf296d 100644 --- a/hw/vfio/ap.c +++ b/hw/vfio/ap.c @@ -28,16 +28,16 @@ #include "hw/qdev-properties.h" #include "hw/s390x/ap-bridge.h" #include "exec/address-spaces.h" +#include "qom/object.h" -#define VFIO_AP_DEVICE_TYPE "vfio-ap" +#define TYPE_VFIO_AP_DEVICE "vfio-ap" -typedef struct VFIOAPDevice { +struct VFIOAPDevice { APDevice apdev; VFIODevice vdev; -} VFIOAPDevice; +}; -#define VFIO_AP_DEVICE(obj) \ - OBJECT_CHECK(VFIOAPDevice, (obj), VFIO_AP_DEVICE_TYPE) +OBJECT_DECLARE_SIMPLE_TYPE(VFIOAPDevice, VFIO_AP_DEVICE) static void vfio_ap_compute_needs_reset(VFIODevice *vdev) { @@ -70,7 +70,8 @@ static VFIOGroup *vfio_ap_get_group(VFIOAPDevice *vapdev, Error **errp) if (!group_path) { error_setg(errp, "%s: no iommu_group found for %s: %s", - VFIO_AP_DEVICE_TYPE, vapdev->vdev.sysfsdev, gerror->message); + TYPE_VFIO_AP_DEVICE, vapdev->vdev.sysfsdev, gerror->message); + g_error_free(gerror); return NULL; } @@ -105,12 +106,12 @@ static void vfio_ap_realize(DeviceState *dev, Error **errp) vapdev->vdev.dev = dev; /* - * vfio-ap devices operate in a way compatible with - * memory ballooning, as no pages are pinned in the host. + * vfio-ap devices operate in a way compatible with discarding of + * memory in RAM blocks, as no pages are pinned in the host. * This needs to be set before vfio_get_device() for vfio common to - * handle the balloon inhibitor. + * handle ram_block_discard_disable(). */ - vapdev->vdev.balloon_allowed = true; + vapdev->vdev.ram_block_discard_allowed = true; ret = vfio_get_device(vfio_group, mdevid, &vapdev->vdev, errp); if (ret) { @@ -173,8 +174,8 @@ static void vfio_ap_class_init(ObjectClass *klass, void *data) } static const TypeInfo vfio_ap_info = { - .name = VFIO_AP_DEVICE_TYPE, - .parent = AP_DEVICE_TYPE, + .name = TYPE_VFIO_AP_DEVICE, + .parent = TYPE_AP_DEVICE, .instance_size = sizeof(VFIOAPDevice), .class_init = vfio_ap_class_init, }; diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index c8624943c1778ec744a636fef56e84681e912f85..d2755d7fc5cace038ca7e4f878228b6854d18f67 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -41,7 +41,14 @@ struct VFIOCCWDevice { uint64_t async_cmd_region_size; uint64_t async_cmd_region_offset; struct ccw_cmd_region *async_cmd_region; + uint64_t schib_region_size; + uint64_t schib_region_offset; + struct ccw_schib_region *schib_region; + uint64_t crw_region_size; + uint64_t crw_region_offset; + struct ccw_crw_region *crw_region; EventNotifier io_notifier; + EventNotifier crw_notifier; bool force_orb_pfch; bool warned_orb_pfch; }; @@ -74,16 +81,9 @@ static IOInstEnding vfio_ccw_handle_request(SubchDev *sch) struct ccw_io_region *region = vcdev->io_region; int ret; - if (!(sch->orb.ctrl0 & ORB_CTRL0_MASK_PFCH)) { - if (!(vcdev->force_orb_pfch)) { - warn_once_pfch(vcdev, sch, "requires PFCH flag set"); - sch_gen_unit_exception(sch); - css_inject_io_interrupt(sch); - return IOINST_CC_EXPECTED; - } else { - sch->orb.ctrl0 |= ORB_CTRL0_MASK_PFCH; - warn_once_pfch(vcdev, sch, "PFCH flag forced"); - } + if (!(sch->orb.ctrl0 & ORB_CTRL0_MASK_PFCH) && vcdev->force_orb_pfch) { + sch->orb.ctrl0 |= ORB_CTRL0_MASK_PFCH; + warn_once_pfch(vcdev, sch, "PFCH flag forced"); } QEMU_BUILD_BUG_ON(sizeof(region->orb_area) != sizeof(ORB)); @@ -123,6 +123,51 @@ again: } } +static IOInstEnding vfio_ccw_handle_store(SubchDev *sch) +{ + S390CCWDevice *cdev = sch->driver_data; + VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); + SCHIB *schib = &sch->curr_status; + struct ccw_schib_region *region = vcdev->schib_region; + SCHIB *s; + int ret; + + /* schib region not available so nothing else to do */ + if (!region) { + return IOINST_CC_EXPECTED; + } + + memset(region, 0, sizeof(*region)); + ret = pread(vcdev->vdev.fd, region, vcdev->schib_region_size, + vcdev->schib_region_offset); + + if (ret == -1) { + /* + * Device is probably damaged, but store subchannel does not + * have a nonzero cc defined for this scenario. Log an error, + * and presume things are otherwise fine. + */ + error_report("vfio-ccw: store region read failed with errno=%d", errno); + return IOINST_CC_EXPECTED; + } + + /* + * Selectively copy path-related bits of the SCHIB, + * rather than copying the entire struct. + */ + s = (SCHIB *)region->schib_area; + schib->pmcw.pnom = s->pmcw.pnom; + schib->pmcw.lpum = s->pmcw.lpum; + schib->pmcw.pam = s->pmcw.pam; + schib->pmcw.pom = s->pmcw.pom; + + if (s->scsw.flags & SCSW_FLAGS_MASK_PNO) { + schib->scsw.flags |= SCSW_FLAGS_MASK_PNO; + } + + return IOINST_CC_EXPECTED; +} + static int vfio_ccw_handle_clear(SubchDev *sch) { S390CCWDevice *cdev = sch->driver_data; @@ -213,6 +258,44 @@ static void vfio_ccw_reset(DeviceState *dev) ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET); } +static void vfio_ccw_crw_read(VFIOCCWDevice *vcdev) +{ + struct ccw_crw_region *region = vcdev->crw_region; + CRW crw; + int size; + + /* Keep reading CRWs as long as data is returned */ + do { + memset(region, 0, sizeof(*region)); + size = pread(vcdev->vdev.fd, region, vcdev->crw_region_size, + vcdev->crw_region_offset); + + if (size == -1) { + error_report("vfio-ccw: Read crw region failed with errno=%d", + errno); + break; + } + + if (region->crw == 0) { + /* No more CRWs to queue */ + break; + } + + memcpy(&crw, ®ion->crw, sizeof(CRW)); + + css_crw_add_to_queue(crw); + } while (1); +} + +static void vfio_ccw_crw_notifier_handler(void *opaque) +{ + VFIOCCWDevice *vcdev = opaque; + + while (event_notifier_test_and_clear(&vcdev->crw_notifier)) { + vfio_ccw_crw_read(vcdev); + } +} + static void vfio_ccw_io_notifier_handler(void *opaque) { VFIOCCWDevice *vcdev = opaque; @@ -283,22 +366,40 @@ read_err: css_inject_io_interrupt(sch); } -static void vfio_ccw_register_io_notifier(VFIOCCWDevice *vcdev, Error **errp) +static void vfio_ccw_register_irq_notifier(VFIOCCWDevice *vcdev, + unsigned int irq, + Error **errp) { VFIODevice *vdev = &vcdev->vdev; struct vfio_irq_info *irq_info; size_t argsz; int fd; + EventNotifier *notifier; + IOHandler *fd_read; + + switch (irq) { + case VFIO_CCW_IO_IRQ_INDEX: + notifier = &vcdev->io_notifier; + fd_read = vfio_ccw_io_notifier_handler; + break; + case VFIO_CCW_CRW_IRQ_INDEX: + notifier = &vcdev->crw_notifier; + fd_read = vfio_ccw_crw_notifier_handler; + break; + default: + error_setg(errp, "vfio: Unsupported device irq(%d)", irq); + return; + } - if (vdev->num_irqs < VFIO_CCW_IO_IRQ_INDEX + 1) { - error_setg(errp, "vfio: unexpected number of io irqs %u", + if (vdev->num_irqs < irq + 1) { + error_setg(errp, "vfio: unexpected number of irqs %u", vdev->num_irqs); return; } argsz = sizeof(*irq_info); irq_info = g_malloc0(argsz); - irq_info->index = VFIO_CCW_IO_IRQ_INDEX; + irq_info->index = irq; irq_info->argsz = argsz; if (ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO, irq_info) < 0 || irq_info->count < 1) { @@ -306,37 +407,52 @@ static void vfio_ccw_register_io_notifier(VFIOCCWDevice *vcdev, Error **errp) goto out_free_info; } - if (event_notifier_init(&vcdev->io_notifier, 0)) { + if (event_notifier_init(notifier, 0)) { error_setg_errno(errp, errno, - "vfio: Unable to init event notifier for IO"); + "vfio: Unable to init event notifier for irq (%d)", + irq); goto out_free_info; } - fd = event_notifier_get_fd(&vcdev->io_notifier); - qemu_set_fd_handler(fd, vfio_ccw_io_notifier_handler, NULL, vcdev); + fd = event_notifier_get_fd(notifier); + qemu_set_fd_handler(fd, fd_read, NULL, vcdev); - if (vfio_set_irq_signaling(vdev, VFIO_CCW_IO_IRQ_INDEX, 0, + if (vfio_set_irq_signaling(vdev, irq, 0, VFIO_IRQ_SET_ACTION_TRIGGER, fd, errp)) { qemu_set_fd_handler(fd, NULL, NULL, vcdev); - event_notifier_cleanup(&vcdev->io_notifier); + event_notifier_cleanup(notifier); } out_free_info: g_free(irq_info); } -static void vfio_ccw_unregister_io_notifier(VFIOCCWDevice *vcdev) +static void vfio_ccw_unregister_irq_notifier(VFIOCCWDevice *vcdev, + unsigned int irq) { Error *err = NULL; + EventNotifier *notifier; + + switch (irq) { + case VFIO_CCW_IO_IRQ_INDEX: + notifier = &vcdev->io_notifier; + break; + case VFIO_CCW_CRW_IRQ_INDEX: + notifier = &vcdev->crw_notifier; + break; + default: + error_report("vfio: Unsupported device irq(%d)", irq); + return; + } - if (vfio_set_irq_signaling(&vcdev->vdev, VFIO_CCW_IO_IRQ_INDEX, 0, + if (vfio_set_irq_signaling(&vcdev->vdev, irq, 0, VFIO_IRQ_SET_ACTION_TRIGGER, -1, &err)) { error_reportf_err(err, VFIO_MSG_PREFIX, vcdev->vdev.name); } - qemu_set_fd_handler(event_notifier_get_fd(&vcdev->io_notifier), + qemu_set_fd_handler(event_notifier_get_fd(notifier), NULL, NULL, vcdev); - event_notifier_cleanup(&vcdev->io_notifier); + event_notifier_cleanup(notifier); } static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp) @@ -370,12 +486,12 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp) vcdev->io_region_size = info->size; if (sizeof(*vcdev->io_region) != vcdev->io_region_size) { error_setg(errp, "vfio: Unexpected size of the I/O region"); - g_free(info); - return; + goto out_err; } vcdev->io_region_offset = info->offset; vcdev->io_region = g_malloc0(info->size); + g_free(info); /* check for the optional async command region */ ret = vfio_get_dev_region_info(vdev, VFIO_REGION_TYPE_CCW, @@ -384,19 +500,55 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp) vcdev->async_cmd_region_size = info->size; if (sizeof(*vcdev->async_cmd_region) != vcdev->async_cmd_region_size) { error_setg(errp, "vfio: Unexpected size of the async cmd region"); - g_free(vcdev->io_region); - g_free(info); - return; + goto out_err; } vcdev->async_cmd_region_offset = info->offset; vcdev->async_cmd_region = g_malloc0(info->size); + g_free(info); + } + + ret = vfio_get_dev_region_info(vdev, VFIO_REGION_TYPE_CCW, + VFIO_REGION_SUBTYPE_CCW_SCHIB, &info); + if (!ret) { + vcdev->schib_region_size = info->size; + if (sizeof(*vcdev->schib_region) != vcdev->schib_region_size) { + error_setg(errp, "vfio: Unexpected size of the schib region"); + goto out_err; + } + vcdev->schib_region_offset = info->offset; + vcdev->schib_region = g_malloc(info->size); + g_free(info); } + ret = vfio_get_dev_region_info(vdev, VFIO_REGION_TYPE_CCW, + VFIO_REGION_SUBTYPE_CCW_CRW, &info); + + if (!ret) { + vcdev->crw_region_size = info->size; + if (sizeof(*vcdev->crw_region) != vcdev->crw_region_size) { + error_setg(errp, "vfio: Unexpected size of the CRW region"); + goto out_err; + } + vcdev->crw_region_offset = info->offset; + vcdev->crw_region = g_malloc(info->size); + g_free(info); + } + + return; + +out_err: + g_free(vcdev->crw_region); + g_free(vcdev->schib_region); + g_free(vcdev->async_cmd_region); + g_free(vcdev->io_region); g_free(info); + return; } static void vfio_ccw_put_region(VFIOCCWDevice *vcdev) { + g_free(vcdev->crw_region); + g_free(vcdev->schib_region); g_free(vcdev->async_cmd_region); g_free(vcdev->io_region); } @@ -425,12 +577,13 @@ static void vfio_ccw_get_device(VFIOGroup *group, VFIOCCWDevice *vcdev, /* * All vfio-ccw devices are believed to operate in a way compatible with - * memory ballooning, ie. pages pinned in the host are in the current - * working set of the guest driver and therefore never overlap with pages - * available to the guest balloon driver. This needs to be set before - * vfio_get_device() for vfio common to handle the balloon inhibitor. + * discarding of memory in RAM blocks, ie. pages pinned in the host are + * in the current working set of the guest driver and therefore never + * overlap e.g., with pages available to the guest balloon driver. This + * needs to be set before vfio_get_device() for vfio common to handle + * ram_block_discard_disable(). */ - vcdev->vdev.balloon_allowed = true; + vcdev->vdev.ram_block_discard_allowed = true; if (vfio_get_device(group, vcdev->cdev.mdevid, &vcdev->vdev, errp)) { goto out_err; @@ -506,11 +659,19 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) goto out_region_err; } - vfio_ccw_register_io_notifier(vcdev, &err); + vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX, &err); if (err) { goto out_notifier_err; } + if (vcdev->crw_region) { + vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_CRW_IRQ_INDEX, &err); + if (err) { + vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX); + goto out_notifier_err; + } + } + return; out_notifier_err: @@ -535,7 +696,8 @@ static void vfio_ccw_unrealize(DeviceState *dev) S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev); VFIOGroup *group = vcdev->vdev.group; - vfio_ccw_unregister_io_notifier(vcdev); + vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_CRW_IRQ_INDEX); + vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX); vfio_ccw_put_region(vcdev); vfio_ccw_put_device(vcdev); vfio_put_group(group); @@ -572,6 +734,7 @@ static void vfio_ccw_class_init(ObjectClass *klass, void *data) cdc->handle_request = vfio_ccw_handle_request; cdc->handle_halt = vfio_ccw_handle_halt; cdc->handle_clear = vfio_ccw_handle_clear; + cdc->handle_store = vfio_ccw_handle_store; } static const TypeInfo vfio_ccw_info = { diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 0b3593b3c0c4b99767b0e130eb38e3f3937d8249..6ff1daa763f87a1ed5351bcc19aeb027c43b8a8f 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -29,15 +29,16 @@ #include "hw/vfio/vfio.h" #include "exec/address-spaces.h" #include "exec/memory.h" +#include "exec/ram_addr.h" #include "hw/hw.h" #include "qemu/error-report.h" #include "qemu/main-loop.h" #include "qemu/range.h" -#include "sysemu/balloon.h" #include "sysemu/kvm.h" #include "sysemu/reset.h" #include "trace.h" #include "qapi/error.h" +#include "migration/migration.h" VFIOGroupList vfio_group_list = QLIST_HEAD_INITIALIZER(vfio_group_list); @@ -204,7 +205,7 @@ void vfio_region_write(void *opaque, hwaddr addr, buf.qword = cpu_to_le64(data); break; default: - hw_error("vfio: unsupported write size, %d bytes", size); + hw_error("vfio: unsupported write size, %u bytes", size); break; } @@ -261,7 +262,7 @@ uint64_t vfio_region_read(void *opaque, data = le64_to_cpu(buf.qword); break; default: - hw_error("vfio: unsupported read size, %d bytes", size); + hw_error("vfio: unsupported read size, %u bytes", size); break; } @@ -287,11 +288,150 @@ const MemoryRegionOps vfio_region_ops = { }, }; +/* + * Device state interfaces + */ + +bool vfio_mig_active(void) +{ + VFIOGroup *group; + VFIODevice *vbasedev; + + if (QLIST_EMPTY(&vfio_group_list)) { + return false; + } + + QLIST_FOREACH(group, &vfio_group_list, next) { + QLIST_FOREACH(vbasedev, &group->device_list, next) { + if (vbasedev->migration_blocker) { + return false; + } + } + } + return true; +} + +static bool vfio_devices_all_saving(VFIOContainer *container) +{ + VFIOGroup *group; + VFIODevice *vbasedev; + MigrationState *ms = migrate_get_current(); + + if (!migration_is_setup_or_active(ms->state)) { + return false; + } + + QLIST_FOREACH(group, &container->group_list, container_next) { + QLIST_FOREACH(vbasedev, &group->device_list, next) { + VFIOMigration *migration = vbasedev->migration; + + if (!migration) { + return false; + } + + if (migration->device_state & VFIO_DEVICE_STATE_SAVING) { + if ((vbasedev->pre_copy_dirty_page_tracking == ON_OFF_AUTO_OFF) + && (migration->device_state & VFIO_DEVICE_STATE_RUNNING)) { + return false; + } + continue; + } else { + return false; + } + } + } + return true; +} + +static bool vfio_devices_all_running_and_saving(VFIOContainer *container) +{ + VFIOGroup *group; + VFIODevice *vbasedev; + MigrationState *ms = migrate_get_current(); + + if (!migration_is_setup_or_active(ms->state)) { + return false; + } + + QLIST_FOREACH(group, &container->group_list, container_next) { + QLIST_FOREACH(vbasedev, &group->device_list, next) { + VFIOMigration *migration = vbasedev->migration; + + if (!migration) { + return false; + } + + if ((migration->device_state & VFIO_DEVICE_STATE_SAVING) && + (migration->device_state & VFIO_DEVICE_STATE_RUNNING)) { + continue; + } else { + return false; + } + } + } + return true; +} + +static int vfio_dma_unmap_bitmap(VFIOContainer *container, + hwaddr iova, ram_addr_t size, + IOMMUTLBEntry *iotlb) +{ + struct vfio_iommu_type1_dma_unmap *unmap; + struct vfio_bitmap *bitmap; + uint64_t pages = TARGET_PAGE_ALIGN(size) >> TARGET_PAGE_BITS; + int ret; + + unmap = g_malloc0(sizeof(*unmap) + sizeof(*bitmap)); + + unmap->argsz = sizeof(*unmap) + sizeof(*bitmap); + unmap->iova = iova; + unmap->size = size; + unmap->flags |= VFIO_DMA_UNMAP_FLAG_GET_DIRTY_BITMAP; + bitmap = (struct vfio_bitmap *)&unmap->data; + + /* + * cpu_physical_memory_set_dirty_lebitmap() expects pages in bitmap of + * TARGET_PAGE_SIZE to mark those dirty. Hence set bitmap_pgsize to + * TARGET_PAGE_SIZE. + */ + + bitmap->pgsize = TARGET_PAGE_SIZE; + bitmap->size = ROUND_UP(pages, sizeof(__u64) * BITS_PER_BYTE) / + BITS_PER_BYTE; + + if (bitmap->size > container->max_dirty_bitmap_size) { + error_report("UNMAP: Size of bitmap too big 0x%"PRIx64, + (uint64_t)bitmap->size); + ret = -E2BIG; + goto unmap_exit; + } + + bitmap->data = g_try_malloc0(bitmap->size); + if (!bitmap->data) { + ret = -ENOMEM; + goto unmap_exit; + } + + ret = ioctl(container->fd, VFIO_IOMMU_UNMAP_DMA, unmap); + if (!ret) { + cpu_physical_memory_set_dirty_lebitmap((unsigned long *)bitmap->data, + iotlb->translated_addr, pages); + } else { + error_report("VFIO_UNMAP_DMA with DIRTY_BITMAP : %m"); + } + + g_free(bitmap->data); +unmap_exit: + g_free(unmap); + return ret; +} + /* * DMA - Mapping and unmapping for the "type1" IOMMU interface used on x86 */ static int vfio_dma_unmap(VFIOContainer *container, - hwaddr iova, ram_addr_t size) + hwaddr iova, ram_addr_t size, + IOMMUTLBEntry *iotlb) { struct vfio_iommu_type1_dma_unmap unmap = { .argsz = sizeof(unmap), @@ -300,6 +440,11 @@ static int vfio_dma_unmap(VFIOContainer *container, .size = size, }; + if (iotlb && container->dirty_pages_supported && + vfio_devices_all_running_and_saving(container)) { + return vfio_dma_unmap_bitmap(container, iova, size, iotlb); + } + while (ioctl(container->fd, VFIO_IOMMU_UNMAP_DMA, &unmap)) { /* * The type1 backend has an off-by-one bug in the kernel (71a7d3d78e3c @@ -347,7 +492,7 @@ static int vfio_dma_map(VFIOContainer *container, hwaddr iova, * the VGA ROM space. */ if (ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map) == 0 || - (errno == EBUSY && vfio_dma_unmap(container, iova, size) == 0 && + (errno == EBUSY && vfio_dma_unmap(container, iova, size, NULL) == 0 && ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map) == 0)) { return 0; } @@ -408,8 +553,8 @@ static bool vfio_listener_skipped_section(MemoryRegionSection *section) } /* Called with rcu_read_lock held. */ -static bool vfio_get_vaddr(IOMMUTLBEntry *iotlb, void **vaddr, - bool *read_only) +static bool vfio_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr, + ram_addr_t *ram_addr, bool *read_only) { MemoryRegion *mr; hwaddr xlat; @@ -440,8 +585,17 @@ static bool vfio_get_vaddr(IOMMUTLBEntry *iotlb, void **vaddr, return false; } - *vaddr = memory_region_get_ram_ptr(mr) + xlat; - *read_only = !writable || mr->readonly; + if (vaddr) { + *vaddr = memory_region_get_ram_ptr(mr) + xlat; + } + + if (ram_addr) { + *ram_addr = memory_region_get_ram_addr(mr) + xlat; + } + + if (read_only) { + *read_only = !writable || mr->readonly; + } return true; } @@ -451,7 +605,6 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) VFIOGuestIOMMU *giommu = container_of(n, VFIOGuestIOMMU, n); VFIOContainer *container = giommu->container; hwaddr iova = iotlb->iova + giommu->iommu_offset; - bool read_only; void *vaddr; int ret; @@ -467,7 +620,9 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) rcu_read_lock(); if ((iotlb->perm & IOMMU_RW) != IOMMU_NONE) { - if (!vfio_get_vaddr(iotlb, &vaddr, &read_only)) { + bool read_only; + + if (!vfio_get_xlat_addr(iotlb, &vaddr, NULL, &read_only)) { goto out; } /* @@ -487,7 +642,7 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) iotlb->addr_mask + 1, vaddr, ret); } } else { - ret = vfio_dma_unmap(container, iova, iotlb->addr_mask + 1); + ret = vfio_dma_unmap(container, iova, iotlb->addr_mask + 1, iotlb); if (ret) { error_report("vfio_dma_unmap(%p, 0x%"HWADDR_PRIx", " "0x%"HWADDR_PRIx") = %d (%m)", @@ -637,6 +792,14 @@ static void vfio_listener_region_add(MemoryListener *listener, int128_get64(llend), iommu_idx); + ret = memory_region_iommu_set_page_size_mask(giommu->iommu, + container->pgsizes, + &err); + if (ret) { + g_free(giommu); + goto fail; + } + ret = memory_region_register_iommu_notifier(section->mr, &giommu->n, &err); if (ret) { @@ -790,7 +953,18 @@ static void vfio_listener_region_del(MemoryListener *listener, } if (try_unmap) { - ret = vfio_dma_unmap(container, iova, int128_get64(llsize)); + if (int128_eq(llsize, int128_2_64())) { + /* The unmap ioctl doesn't accept a full 64-bit span. */ + llsize = int128_rshift(llsize, 1); + ret = vfio_dma_unmap(container, iova, int128_get64(llsize), NULL); + if (ret) { + error_report("vfio_dma_unmap(%p, 0x%"HWADDR_PRIx", " + "0x%"HWADDR_PRIx") = %d (%m)", + container, iova, int128_get64(llsize), ret); + } + iova += int128_get64(llsize); + } + ret = vfio_dma_unmap(container, iova, int128_get64(llsize), NULL); if (ret) { error_report("vfio_dma_unmap(%p, 0x%"HWADDR_PRIx", " "0x%"HWADDR_PRIx") = %d (%m)", @@ -813,9 +987,156 @@ static void vfio_listener_region_del(MemoryListener *listener, } } +static int vfio_get_dirty_bitmap(VFIOContainer *container, uint64_t iova, + uint64_t size, ram_addr_t ram_addr) +{ + struct vfio_iommu_type1_dirty_bitmap *dbitmap; + struct vfio_iommu_type1_dirty_bitmap_get *range; + uint64_t pages; + int ret; + + dbitmap = g_malloc0(sizeof(*dbitmap) + sizeof(*range)); + + dbitmap->argsz = sizeof(*dbitmap) + sizeof(*range); + dbitmap->flags = VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP; + range = (struct vfio_iommu_type1_dirty_bitmap_get *)&dbitmap->data; + range->iova = iova; + range->size = size; + + /* + * cpu_physical_memory_set_dirty_lebitmap() expects pages in bitmap of + * TARGET_PAGE_SIZE to mark those dirty. Hence set bitmap's pgsize to + * TARGET_PAGE_SIZE. + */ + range->bitmap.pgsize = TARGET_PAGE_SIZE; + + pages = TARGET_PAGE_ALIGN(range->size) >> TARGET_PAGE_BITS; + range->bitmap.size = ROUND_UP(pages, sizeof(__u64) * BITS_PER_BYTE) / + BITS_PER_BYTE; + range->bitmap.data = g_try_malloc0(range->bitmap.size); + if (!range->bitmap.data) { + ret = -ENOMEM; + goto err_out; + } + + ret = ioctl(container->fd, VFIO_IOMMU_DIRTY_PAGES, dbitmap); + if (ret) { + error_report("Failed to get dirty bitmap for iova: 0x%"PRIx64 + " size: 0x%"PRIx64" err: %d", (uint64_t)range->iova, + (uint64_t)range->size, errno); + goto err_out; + } + + cpu_physical_memory_set_dirty_lebitmap((unsigned long *)range->bitmap.data, + ram_addr, pages); + + trace_vfio_get_dirty_bitmap(container->fd, range->iova, range->size, + range->bitmap.size, ram_addr); +err_out: + g_free(range->bitmap.data); + g_free(dbitmap); + + return ret; +} + +typedef struct { + IOMMUNotifier n; + VFIOGuestIOMMU *giommu; +} vfio_giommu_dirty_notifier; + +static void vfio_iommu_map_dirty_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) +{ + vfio_giommu_dirty_notifier *gdn = container_of(n, + vfio_giommu_dirty_notifier, n); + VFIOGuestIOMMU *giommu = gdn->giommu; + VFIOContainer *container = giommu->container; + hwaddr iova = iotlb->iova + giommu->iommu_offset; + ram_addr_t translated_addr; + + trace_vfio_iommu_map_dirty_notify(iova, iova + iotlb->addr_mask); + + if (iotlb->target_as != &address_space_memory) { + error_report("Wrong target AS \"%s\", only system memory is allowed", + iotlb->target_as->name ? iotlb->target_as->name : "none"); + return; + } + + rcu_read_lock(); + if (vfio_get_xlat_addr(iotlb, NULL, &translated_addr, NULL)) { + int ret; + + ret = vfio_get_dirty_bitmap(container, iova, iotlb->addr_mask + 1, + translated_addr); + if (ret) { + error_report("vfio_iommu_map_dirty_notify(%p, 0x%"HWADDR_PRIx", " + "0x%"HWADDR_PRIx") = %d (%m)", + container, iova, + iotlb->addr_mask + 1, ret); + } + } + rcu_read_unlock(); +} + +static int vfio_sync_dirty_bitmap(VFIOContainer *container, + MemoryRegionSection *section) +{ + ram_addr_t ram_addr; + + if (memory_region_is_iommu(section->mr)) { + VFIOGuestIOMMU *giommu; + + QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) { + if (MEMORY_REGION(giommu->iommu) == section->mr && + giommu->n.start == section->offset_within_region) { + Int128 llend; + vfio_giommu_dirty_notifier gdn = { .giommu = giommu }; + int idx = memory_region_iommu_attrs_to_index(giommu->iommu, + MEMTXATTRS_UNSPECIFIED); + + llend = int128_add(int128_make64(section->offset_within_region), + section->size); + llend = int128_sub(llend, int128_one()); + + iommu_notifier_init(&gdn.n, + vfio_iommu_map_dirty_notify, + IOMMU_NOTIFIER_MAP, + section->offset_within_region, + int128_get64(llend), + idx); + memory_region_iommu_replay(giommu->iommu, &gdn.n); + break; + } + } + return 0; + } + + ram_addr = memory_region_get_ram_addr(section->mr) + + section->offset_within_region; + + return vfio_get_dirty_bitmap(container, + TARGET_PAGE_ALIGN(section->offset_within_address_space), + int128_get64(section->size), ram_addr); +} + +static void vfio_listerner_log_sync(MemoryListener *listener, + MemoryRegionSection *section) +{ + VFIOContainer *container = container_of(listener, VFIOContainer, listener); + + if (vfio_listener_skipped_section(section) || + !container->dirty_pages_supported) { + return; + } + + if (vfio_devices_all_saving(container)) { + vfio_sync_dirty_bitmap(container, section); + } +} + static const MemoryListener vfio_memory_listener = { .region_add = vfio_listener_region_add, .region_del = vfio_listener_region_del, + .log_sync = vfio_listerner_log_sync, }; static void vfio_listener_release(VFIOContainer *container) @@ -826,17 +1147,12 @@ static void vfio_listener_release(VFIOContainer *container) } } -struct vfio_info_cap_header * -vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id) +static struct vfio_info_cap_header * +vfio_get_cap(void *ptr, uint32_t cap_offset, uint16_t id) { struct vfio_info_cap_header *hdr; - void *ptr = info; - - if (!(info->flags & VFIO_REGION_INFO_FLAG_CAPS)) { - return NULL; - } - for (hdr = ptr + info->cap_offset; hdr != ptr; hdr = ptr + hdr->next) { + for (hdr = ptr + cap_offset; hdr != ptr; hdr = ptr + hdr->next) { if (hdr->id == id) { return hdr; } @@ -845,6 +1161,57 @@ vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id) return NULL; } +struct vfio_info_cap_header * +vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id) +{ + if (!(info->flags & VFIO_REGION_INFO_FLAG_CAPS)) { + return NULL; + } + + return vfio_get_cap((void *)info, info->cap_offset, id); +} + +static struct vfio_info_cap_header * +vfio_get_iommu_type1_info_cap(struct vfio_iommu_type1_info *info, uint16_t id) +{ + if (!(info->flags & VFIO_IOMMU_INFO_CAPS)) { + return NULL; + } + + return vfio_get_cap((void *)info, info->cap_offset, id); +} + +struct vfio_info_cap_header * +vfio_get_device_info_cap(struct vfio_device_info *info, uint16_t id) +{ + if (!(info->flags & VFIO_DEVICE_FLAGS_CAPS)) { + return NULL; + } + + return vfio_get_cap((void *)info, info->cap_offset, id); +} + +bool vfio_get_info_dma_avail(struct vfio_iommu_type1_info *info, + unsigned int *avail) +{ + struct vfio_info_cap_header *hdr; + struct vfio_iommu_type1_info_dma_avail *cap; + + /* If the capability cannot be found, assume no DMA limiting */ + hdr = vfio_get_iommu_type1_info_cap(info, + VFIO_IOMMU_TYPE1_INFO_DMA_AVAIL); + if (hdr == NULL) { + return false; + } + + if (avail != NULL) { + cap = (void *) hdr; + *avail = cap->avail; + } + + return true; +} + static int vfio_setup_region_sparse_mmaps(VFIORegion *region, struct vfio_region_info *info) { @@ -925,6 +1292,18 @@ int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region, return 0; } +static void vfio_subregion_unmap(VFIORegion *region, int index) +{ + trace_vfio_region_unmap(memory_region_name(®ion->mmaps[index].mem), + region->mmaps[index].offset, + region->mmaps[index].offset + + region->mmaps[index].size - 1); + memory_region_del_subregion(region->mem, ®ion->mmaps[index].mem); + munmap(region->mmaps[index].mmap, region->mmaps[index].size); + object_unparent(OBJECT(®ion->mmaps[index].mem)); + region->mmaps[index].mmap = NULL; +} + int vfio_region_mmap(VFIORegion *region) { int i, prot = 0; @@ -955,10 +1334,7 @@ int vfio_region_mmap(VFIORegion *region) region->mmaps[i].mmap = NULL; for (i--; i >= 0; i--) { - memory_region_del_subregion(region->mem, ®ion->mmaps[i].mem); - munmap(region->mmaps[i].mmap, region->mmaps[i].size); - object_unparent(OBJECT(®ion->mmaps[i].mem)); - region->mmaps[i].mmap = NULL; + vfio_subregion_unmap(region, i); } return ret; @@ -983,6 +1359,21 @@ int vfio_region_mmap(VFIORegion *region) return 0; } +void vfio_region_unmap(VFIORegion *region) +{ + int i; + + if (!region->mem) { + return; + } + + for (i = 0; i < region->nr_mmaps; i++) { + if (region->mmaps[i].mmap) { + vfio_subregion_unmap(region, i); + } + } +} + void vfio_region_exit(VFIORegion *region) { int i; @@ -1205,6 +1596,75 @@ static int vfio_init_container(VFIOContainer *container, int group_fd, return 0; } +static int vfio_get_iommu_info(VFIOContainer *container, + struct vfio_iommu_type1_info **info) +{ + + size_t argsz = sizeof(struct vfio_iommu_type1_info); + + *info = g_new0(struct vfio_iommu_type1_info, 1); +again: + (*info)->argsz = argsz; + + if (ioctl(container->fd, VFIO_IOMMU_GET_INFO, *info)) { + g_free(*info); + *info = NULL; + return -errno; + } + + if (((*info)->argsz > argsz)) { + argsz = (*info)->argsz; + *info = g_realloc(*info, argsz); + goto again; + } + + return 0; +} + +static struct vfio_info_cap_header * +vfio_get_iommu_info_cap(struct vfio_iommu_type1_info *info, uint16_t id) +{ + struct vfio_info_cap_header *hdr; + void *ptr = info; + + if (!(info->flags & VFIO_IOMMU_INFO_CAPS)) { + return NULL; + } + + for (hdr = ptr + info->cap_offset; hdr != ptr; hdr = ptr + hdr->next) { + if (hdr->id == id) { + return hdr; + } + } + + return NULL; +} + +static void vfio_get_iommu_info_migration(VFIOContainer *container, + struct vfio_iommu_type1_info *info) +{ + struct vfio_info_cap_header *hdr; + struct vfio_iommu_type1_info_cap_migration *cap_mig; + + hdr = vfio_get_iommu_info_cap(info, VFIO_IOMMU_TYPE1_INFO_CAP_MIGRATION); + if (!hdr) { + return; + } + + cap_mig = container_of(hdr, struct vfio_iommu_type1_info_cap_migration, + header); + + /* + * cpu_physical_memory_set_dirty_lebitmap() expects pages in bitmap of + * TARGET_PAGE_SIZE to mark those dirty. + */ + if (cap_mig->pgsize_bitmap & TARGET_PAGE_SIZE) { + container->dirty_pages_supported = true; + container->max_dirty_bitmap_size = cap_mig->max_dirty_bitmap_size; + container->dirty_pgsizes = cap_mig->pgsize_bitmap; + } +} + static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, Error **errp) { @@ -1215,31 +1675,36 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, space = vfio_get_address_space(as); /* - * VFIO is currently incompatible with memory ballooning insofar as the + * VFIO is currently incompatible with discarding of RAM insofar as the * madvise to purge (zap) the page from QEMU's address space does not * interact with the memory API and therefore leaves stale virtual to * physical mappings in the IOMMU if the page was previously pinned. We - * therefore add a balloon inhibit for each group added to a container, + * therefore set discarding broken for each group added to a container, * whether the container is used individually or shared. This provides * us with options to allow devices within a group to opt-in and allow - * ballooning, so long as it is done consistently for a group (for instance + * discarding, so long as it is done consistently for a group (for instance * if the device is an mdev device where it is known that the host vendor * driver will never pin pages outside of the working set of the guest - * driver, which would thus not be ballooning candidates). + * driver, which would thus not be discarding candidates). * * The first opportunity to induce pinning occurs here where we attempt to * attach the group to existing containers within the AddressSpace. If any - * pages are already zapped from the virtual address space, such as from a - * previous ballooning opt-in, new pinning will cause valid mappings to be + * pages are already zapped from the virtual address space, such as from + * previous discards, new pinning will cause valid mappings to be * re-established. Likewise, when the overall MemoryListener for a new * container is registered, a replay of mappings within the AddressSpace * will occur, re-establishing any previously zapped pages as well. * - * NB. Balloon inhibiting does not currently block operation of the - * balloon driver or revoke previously pinned pages, it only prevents - * calling madvise to modify the virtual mapping of ballooned pages. + * Especially virtio-balloon is currently only prevented from discarding + * new memory, it will not yet set ram_block_discard_set_required() and + * therefore, neither stops us here or deals with the sudden memory + * consumption of inflated memory. */ - qemu_balloon_inhibit(true); + ret = ram_block_discard_disable(true); + if (ret) { + error_setg_errno(errp, -ret, "Cannot set discarding of RAM broken"); + return ret; + } QLIST_FOREACH(container, &space->containers, next) { if (!ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &container->fd)) { @@ -1250,7 +1715,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, } } - fd = qemu_open("/dev/vfio/vfio", O_RDWR); + fd = qemu_open_old("/dev/vfio/vfio", O_RDWR); if (fd < 0) { error_setg_errno(errp, errno, "failed to open /dev/vfio/vfio"); ret = -errno; @@ -1269,6 +1734,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, container->space = space; container->fd = fd; container->error = NULL; + container->dirty_pages_supported = false; QLIST_INIT(&container->giommu_list); QLIST_INIT(&container->hostwin_list); @@ -1281,7 +1747,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, case VFIO_TYPE1v2_IOMMU: case VFIO_TYPE1_IOMMU: { - struct vfio_iommu_type1_info info; + struct vfio_iommu_type1_info *info; /* * FIXME: This assumes that a Type1 IOMMU can map any 64-bit @@ -1290,15 +1756,19 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, * existing Type1 IOMMUs generally support any IOVA we're * going to actually try in practice. */ - info.argsz = sizeof(info); - ret = ioctl(fd, VFIO_IOMMU_GET_INFO, &info); - /* Ignore errors */ - if (ret || !(info.flags & VFIO_IOMMU_INFO_PGSIZES)) { + ret = vfio_get_iommu_info(container, &info); + + if (ret || !(info->flags & VFIO_IOMMU_INFO_PGSIZES)) { /* Assume 4k IOVA page size */ - info.iova_pgsizes = 4096; + info->iova_pgsizes = 4096; + } + vfio_host_win_add(container, 0, (hwaddr)-1, info->iova_pgsizes); + container->pgsizes = info->iova_pgsizes; + + if (!ret) { + vfio_get_iommu_info_migration(container, info); } - vfio_host_win_add(container, 0, (hwaddr)-1, info.iova_pgsizes); - container->pgsizes = info.iova_pgsizes; + g_free(info); break; } case VFIO_SPAPR_TCE_v2_IOMMU: @@ -1405,7 +1875,7 @@ close_fd_exit: close(fd); put_space_exit: - qemu_balloon_inhibit(false); + ram_block_discard_disable(false); vfio_put_address_space(space); return ret; @@ -1475,7 +1945,7 @@ VFIOGroup *vfio_get_group(int groupid, AddressSpace *as, Error **errp) group = g_malloc0(sizeof(*group)); snprintf(path, sizeof(path), "/dev/vfio/%d", groupid); - group->fd = qemu_open(path, O_RDWR); + group->fd = qemu_open_old(path, O_RDWR); if (group->fd < 0) { error_setg_errno(errp, errno, "failed to open %s", path); goto free_group_exit; @@ -1526,8 +1996,8 @@ void vfio_put_group(VFIOGroup *group) return; } - if (!group->balloon_allowed) { - qemu_balloon_inhibit(false); + if (!group->ram_block_discard_allowed) { + ram_block_discard_disable(false); } vfio_kvm_device_del_group(group); vfio_disconnect_container(group); @@ -1565,22 +2035,23 @@ int vfio_get_device(VFIOGroup *group, const char *name, } /* - * Clear the balloon inhibitor for this group if the driver knows the - * device operates compatibly with ballooning. Setting must be consistent - * per group, but since compatibility is really only possible with mdev - * currently, we expect singleton groups. + * Set discarding of RAM as not broken for this group if the driver knows + * the device operates compatibly with discarding. Setting must be + * consistent per group, but since compatibility is really only possible + * with mdev currently, we expect singleton groups. */ - if (vbasedev->balloon_allowed != group->balloon_allowed) { + if (vbasedev->ram_block_discard_allowed != + group->ram_block_discard_allowed) { if (!QLIST_EMPTY(&group->device_list)) { - error_setg(errp, - "Inconsistent device balloon setting within group"); + error_setg(errp, "Inconsistent setting of support for discarding " + "RAM (e.g., balloon) within group"); close(fd); return -1; } - if (!group->balloon_allowed) { - group->balloon_allowed = true; - qemu_balloon_inhibit(false); + if (!group->ram_block_discard_allowed) { + group->ram_block_discard_allowed = true; + ram_block_discard_disable(false); } } diff --git a/hw/vfio/display.c b/hw/vfio/display.c index a57a22674d627a9050326deb945d736d29dad7fc..342054193b3c072a69509b6ee8d1bc182df8b11b 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -405,6 +405,7 @@ static void vfio_display_region_update(void *opaque) if (!plane.drm_format || !plane.size) { if (dpy->ramfb) { ramfb_display_update(dpy->con, dpy->ramfb); + dpy->region.surface = NULL; } return; } diff --git a/hw/vfio/igd.c b/hw/vfio/igd.c index 64e332746b49cd26840339006db2bb2d26305954..470205f487eb7894c157e4ab6a5063cc841d1f49 100644 --- a/hw/vfio/igd.c +++ b/hw/vfio/igd.c @@ -535,7 +535,7 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr) } /* - * Assume we have no GMS memory, but allow it to be overrided by device + * Assume we have no GMS memory, but allow it to be overridden by device * option (experimental). The spec doesn't actually allow zero GMS when * when IVD (IGD VGA Disable) is clear, but the claim is that it's unused, * so let's not waste VM memory for it. diff --git a/hw/vfio/meson.build b/hw/vfio/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..da9af297a0c5914e39be0a6f515caddd37542471 --- /dev/null +++ b/hw/vfio/meson.build @@ -0,0 +1,19 @@ +vfio_ss = ss.source_set() +vfio_ss.add(files( + 'common.c', + 'spapr.c', + 'migration.c', +)) +vfio_ss.add(when: 'CONFIG_VFIO_PCI', if_true: files( + 'display.c', + 'pci-quirks.c', + 'pci.c', +)) +vfio_ss.add(when: 'CONFIG_VFIO_CCW', if_true: files('ccw.c')) +vfio_ss.add(when: 'CONFIG_VFIO_PLATFORM', if_true: files('platform.c')) +vfio_ss.add(when: 'CONFIG_VFIO_XGMAC', if_true: files('calxeda-xgmac.c')) +vfio_ss.add(when: 'CONFIG_VFIO_AMD_XGBE', if_true: files('amd-xgbe.c')) +vfio_ss.add(when: 'CONFIG_VFIO_AP', if_true: files('ap.c')) +vfio_ss.add(when: 'CONFIG_VFIO_IGD', if_true: files('igd.c')) + +specific_ss.add_all(when: 'CONFIG_VFIO', if_true: vfio_ss) diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c new file mode 100644 index 0000000000000000000000000000000000000000..00daa50ed81890b8d9f9fd7d381b0078d71843f2 --- /dev/null +++ b/hw/vfio/migration.c @@ -0,0 +1,933 @@ +/* + * Migration support for VFIO devices + * + * Copyright NVIDIA, Inc. 2020 + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "qemu/cutils.h" +#include +#include + +#include "sysemu/runstate.h" +#include "hw/vfio/vfio-common.h" +#include "cpu.h" +#include "migration/migration.h" +#include "migration/vmstate.h" +#include "migration/qemu-file.h" +#include "migration/register.h" +#include "migration/blocker.h" +#include "migration/misc.h" +#include "qapi/error.h" +#include "exec/ramlist.h" +#include "exec/ram_addr.h" +#include "pci.h" +#include "trace.h" +#include "hw/hw.h" + +/* + * Flags to be used as unique delimiters for VFIO devices in the migration + * stream. These flags are composed as: + * 0xffffffff => MSB 32-bit all 1s + * 0xef10 => Magic ID, represents emulated (virtual) function IO + * 0x0000 => 16-bits reserved for flags + * + * The beginning of state information is marked by _DEV_CONFIG_STATE, + * _DEV_SETUP_STATE, or _DEV_DATA_STATE, respectively. The end of a + * certain state information is marked by _END_OF_STATE. + */ +#define VFIO_MIG_FLAG_END_OF_STATE (0xffffffffef100001ULL) +#define VFIO_MIG_FLAG_DEV_CONFIG_STATE (0xffffffffef100002ULL) +#define VFIO_MIG_FLAG_DEV_SETUP_STATE (0xffffffffef100003ULL) +#define VFIO_MIG_FLAG_DEV_DATA_STATE (0xffffffffef100004ULL) + +static int64_t bytes_transferred; + +static inline int vfio_mig_access(VFIODevice *vbasedev, void *val, int count, + off_t off, bool iswrite) +{ + int ret; + + ret = iswrite ? pwrite(vbasedev->fd, val, count, off) : + pread(vbasedev->fd, val, count, off); + if (ret < count) { + error_report("vfio_mig_%s %d byte %s: failed at offset 0x%" + HWADDR_PRIx", err: %s", iswrite ? "write" : "read", count, + vbasedev->name, off, strerror(errno)); + return (ret < 0) ? ret : -EINVAL; + } + return 0; +} + +static int vfio_mig_rw(VFIODevice *vbasedev, __u8 *buf, size_t count, + off_t off, bool iswrite) +{ + int ret, done = 0; + __u8 *tbuf = buf; + + while (count) { + int bytes = 0; + + if (count >= 8 && !(off % 8)) { + bytes = 8; + } else if (count >= 4 && !(off % 4)) { + bytes = 4; + } else if (count >= 2 && !(off % 2)) { + bytes = 2; + } else { + bytes = 1; + } + + ret = vfio_mig_access(vbasedev, tbuf, bytes, off, iswrite); + if (ret) { + return ret; + } + + count -= bytes; + done += bytes; + off += bytes; + tbuf += bytes; + } + return done; +} + +#define vfio_mig_read(f, v, c, o) vfio_mig_rw(f, (__u8 *)v, c, o, false) +#define vfio_mig_write(f, v, c, o) vfio_mig_rw(f, (__u8 *)v, c, o, true) + +#define VFIO_MIG_STRUCT_OFFSET(f) \ + offsetof(struct vfio_device_migration_info, f) +/* + * Change the device_state register for device @vbasedev. Bits set in @mask + * are preserved, bits set in @value are set, and bits not set in either @mask + * or @value are cleared in device_state. If the register cannot be accessed, + * the resulting state would be invalid, or the device enters an error state, + * an error is returned. + */ + +static int vfio_migration_set_state(VFIODevice *vbasedev, uint32_t mask, + uint32_t value) +{ + VFIOMigration *migration = vbasedev->migration; + VFIORegion *region = &migration->region; + off_t dev_state_off = region->fd_offset + + VFIO_MIG_STRUCT_OFFSET(device_state); + uint32_t device_state; + int ret; + + ret = vfio_mig_read(vbasedev, &device_state, sizeof(device_state), + dev_state_off); + if (ret < 0) { + return ret; + } + + device_state = (device_state & mask) | value; + + if (!VFIO_DEVICE_STATE_VALID(device_state)) { + return -EINVAL; + } + + ret = vfio_mig_write(vbasedev, &device_state, sizeof(device_state), + dev_state_off); + if (ret < 0) { + int rret; + + rret = vfio_mig_read(vbasedev, &device_state, sizeof(device_state), + dev_state_off); + + if ((rret < 0) || (VFIO_DEVICE_STATE_IS_ERROR(device_state))) { + hw_error("%s: Device in error state 0x%x", vbasedev->name, + device_state); + return rret ? rret : -EIO; + } + return ret; + } + + migration->device_state = device_state; + trace_vfio_migration_set_state(vbasedev->name, device_state); + return 0; +} + +static void *get_data_section_size(VFIORegion *region, uint64_t data_offset, + uint64_t data_size, uint64_t *size) +{ + void *ptr = NULL; + uint64_t limit = 0; + int i; + + if (!region->mmaps) { + if (size) { + *size = MIN(data_size, region->size - data_offset); + } + return ptr; + } + + for (i = 0; i < region->nr_mmaps; i++) { + VFIOMmap *map = region->mmaps + i; + + if ((data_offset >= map->offset) && + (data_offset < map->offset + map->size)) { + + /* check if data_offset is within sparse mmap areas */ + ptr = map->mmap + data_offset - map->offset; + if (size) { + *size = MIN(data_size, map->offset + map->size - data_offset); + } + break; + } else if ((data_offset < map->offset) && + (!limit || limit > map->offset)) { + /* + * data_offset is not within sparse mmap areas, find size of + * non-mapped area. Check through all list since region->mmaps list + * is not sorted. + */ + limit = map->offset; + } + } + + if (!ptr && size) { + *size = limit ? MIN(data_size, limit - data_offset) : data_size; + } + return ptr; +} + +static int vfio_save_buffer(QEMUFile *f, VFIODevice *vbasedev, uint64_t *size) +{ + VFIOMigration *migration = vbasedev->migration; + VFIORegion *region = &migration->region; + uint64_t data_offset = 0, data_size = 0, sz; + int ret; + + ret = vfio_mig_read(vbasedev, &data_offset, sizeof(data_offset), + region->fd_offset + VFIO_MIG_STRUCT_OFFSET(data_offset)); + if (ret < 0) { + return ret; + } + + ret = vfio_mig_read(vbasedev, &data_size, sizeof(data_size), + region->fd_offset + VFIO_MIG_STRUCT_OFFSET(data_size)); + if (ret < 0) { + return ret; + } + + trace_vfio_save_buffer(vbasedev->name, data_offset, data_size, + migration->pending_bytes); + + qemu_put_be64(f, data_size); + sz = data_size; + + while (sz) { + void *buf; + uint64_t sec_size; + bool buf_allocated = false; + + buf = get_data_section_size(region, data_offset, sz, &sec_size); + + if (!buf) { + buf = g_try_malloc(sec_size); + if (!buf) { + error_report("%s: Error allocating buffer ", __func__); + return -ENOMEM; + } + buf_allocated = true; + + ret = vfio_mig_read(vbasedev, buf, sec_size, + region->fd_offset + data_offset); + if (ret < 0) { + g_free(buf); + return ret; + } + } + + qemu_put_buffer(f, buf, sec_size); + + if (buf_allocated) { + g_free(buf); + } + sz -= sec_size; + data_offset += sec_size; + } + + ret = qemu_file_get_error(f); + + if (!ret && size) { + *size = data_size; + } + + bytes_transferred += data_size; + return ret; +} + +static int vfio_load_buffer(QEMUFile *f, VFIODevice *vbasedev, + uint64_t data_size) +{ + VFIORegion *region = &vbasedev->migration->region; + uint64_t data_offset = 0, size, report_size; + int ret; + + do { + ret = vfio_mig_read(vbasedev, &data_offset, sizeof(data_offset), + region->fd_offset + VFIO_MIG_STRUCT_OFFSET(data_offset)); + if (ret < 0) { + return ret; + } + + if (data_offset + data_size > region->size) { + /* + * If data_size is greater than the data section of migration region + * then iterate the write buffer operation. This case can occur if + * size of migration region at destination is smaller than size of + * migration region at source. + */ + report_size = size = region->size - data_offset; + data_size -= size; + } else { + report_size = size = data_size; + data_size = 0; + } + + trace_vfio_load_state_device_data(vbasedev->name, data_offset, size); + + while (size) { + void *buf; + uint64_t sec_size; + bool buf_alloc = false; + + buf = get_data_section_size(region, data_offset, size, &sec_size); + + if (!buf) { + buf = g_try_malloc(sec_size); + if (!buf) { + error_report("%s: Error allocating buffer ", __func__); + return -ENOMEM; + } + buf_alloc = true; + } + + qemu_get_buffer(f, buf, sec_size); + + if (buf_alloc) { + ret = vfio_mig_write(vbasedev, buf, sec_size, + region->fd_offset + data_offset); + g_free(buf); + + if (ret < 0) { + return ret; + } + } + size -= sec_size; + data_offset += sec_size; + } + + ret = vfio_mig_write(vbasedev, &report_size, sizeof(report_size), + region->fd_offset + VFIO_MIG_STRUCT_OFFSET(data_size)); + if (ret < 0) { + return ret; + } + } while (data_size); + + return 0; +} + +static int vfio_update_pending(VFIODevice *vbasedev) +{ + VFIOMigration *migration = vbasedev->migration; + VFIORegion *region = &migration->region; + uint64_t pending_bytes = 0; + int ret; + + ret = vfio_mig_read(vbasedev, &pending_bytes, sizeof(pending_bytes), + region->fd_offset + VFIO_MIG_STRUCT_OFFSET(pending_bytes)); + if (ret < 0) { + migration->pending_bytes = 0; + return ret; + } + + migration->pending_bytes = pending_bytes; + trace_vfio_update_pending(vbasedev->name, pending_bytes); + return 0; +} + +static int vfio_save_device_config_state(QEMUFile *f, void *opaque) +{ + VFIODevice *vbasedev = opaque; + + qemu_put_be64(f, VFIO_MIG_FLAG_DEV_CONFIG_STATE); + + if (vbasedev->ops && vbasedev->ops->vfio_save_config) { + vbasedev->ops->vfio_save_config(vbasedev, f); + } + + qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE); + + trace_vfio_save_device_config_state(vbasedev->name); + + return qemu_file_get_error(f); +} + +static int vfio_load_device_config_state(QEMUFile *f, void *opaque) +{ + VFIODevice *vbasedev = opaque; + uint64_t data; + + if (vbasedev->ops && vbasedev->ops->vfio_load_config) { + int ret; + + ret = vbasedev->ops->vfio_load_config(vbasedev, f); + if (ret) { + error_report("%s: Failed to load device config space", + vbasedev->name); + return ret; + } + } + + data = qemu_get_be64(f); + if (data != VFIO_MIG_FLAG_END_OF_STATE) { + error_report("%s: Failed loading device config space, " + "end flag incorrect 0x%"PRIx64, vbasedev->name, data); + return -EINVAL; + } + + trace_vfio_load_device_config_state(vbasedev->name); + return qemu_file_get_error(f); +} + +static int vfio_set_dirty_page_tracking(VFIODevice *vbasedev, bool start) +{ + int ret; + VFIOMigration *migration = vbasedev->migration; + VFIOContainer *container = vbasedev->group->container; + struct vfio_iommu_type1_dirty_bitmap dirty = { + .argsz = sizeof(dirty), + }; + + if (start) { + if (migration->device_state & VFIO_DEVICE_STATE_SAVING) { + dirty.flags = VFIO_IOMMU_DIRTY_PAGES_FLAG_START; + } else { + return -EINVAL; + } + } else { + dirty.flags = VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP; + } + + ret = ioctl(container->fd, VFIO_IOMMU_DIRTY_PAGES, &dirty); + if (ret) { + error_report("Failed to set dirty tracking flag 0x%x errno: %d", + dirty.flags, errno); + return -errno; + } + return ret; +} + +static void vfio_migration_cleanup(VFIODevice *vbasedev) +{ + VFIOMigration *migration = vbasedev->migration; + + vfio_set_dirty_page_tracking(vbasedev, false); + + if (migration->region.mmaps) { + vfio_region_unmap(&migration->region); + } +} + +/* ---------------------------------------------------------------------- */ + +static int vfio_save_setup(QEMUFile *f, void *opaque) +{ + VFIODevice *vbasedev = opaque; + VFIOMigration *migration = vbasedev->migration; + int ret; + + trace_vfio_save_setup(vbasedev->name); + + qemu_put_be64(f, VFIO_MIG_FLAG_DEV_SETUP_STATE); + + if (migration->region.mmaps) { + /* + * Calling vfio_region_mmap() from migration thread. Memory API called + * from this function require locking the iothread when called from + * outside the main loop thread. + */ + qemu_mutex_lock_iothread(); + ret = vfio_region_mmap(&migration->region); + qemu_mutex_unlock_iothread(); + if (ret) { + error_report("%s: Failed to mmap VFIO migration region: %s", + vbasedev->name, strerror(-ret)); + error_report("%s: Falling back to slow path", vbasedev->name); + } + } + + ret = vfio_migration_set_state(vbasedev, VFIO_DEVICE_STATE_MASK, + VFIO_DEVICE_STATE_SAVING); + if (ret) { + error_report("%s: Failed to set state SAVING", vbasedev->name); + return ret; + } + + ret = vfio_set_dirty_page_tracking(vbasedev, true); + if (ret) { + return ret; + } + + qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE); + + ret = qemu_file_get_error(f); + if (ret) { + return ret; + } + + return 0; +} + +static void vfio_save_cleanup(void *opaque) +{ + VFIODevice *vbasedev = opaque; + + vfio_migration_cleanup(vbasedev); + trace_vfio_save_cleanup(vbasedev->name); +} + +static void vfio_save_pending(QEMUFile *f, void *opaque, + uint64_t threshold_size, + uint64_t *res_precopy_only, + uint64_t *res_compatible, + uint64_t *res_postcopy_only) +{ + VFIODevice *vbasedev = opaque; + VFIOMigration *migration = vbasedev->migration; + int ret; + + ret = vfio_update_pending(vbasedev); + if (ret) { + return; + } + + *res_precopy_only += migration->pending_bytes; + + trace_vfio_save_pending(vbasedev->name, *res_precopy_only, + *res_postcopy_only, *res_compatible); +} + +static int vfio_save_iterate(QEMUFile *f, void *opaque) +{ + VFIODevice *vbasedev = opaque; + VFIOMigration *migration = vbasedev->migration; + uint64_t data_size; + int ret; + + qemu_put_be64(f, VFIO_MIG_FLAG_DEV_DATA_STATE); + + if (migration->pending_bytes == 0) { + ret = vfio_update_pending(vbasedev); + if (ret) { + return ret; + } + + if (migration->pending_bytes == 0) { + qemu_put_be64(f, 0); + qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE); + /* indicates data finished, goto complete phase */ + return 1; + } + } + + ret = vfio_save_buffer(f, vbasedev, &data_size); + if (ret) { + error_report("%s: vfio_save_buffer failed %s", vbasedev->name, + strerror(errno)); + return ret; + } + + qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE); + + ret = qemu_file_get_error(f); + if (ret) { + return ret; + } + + /* + * Reset pending_bytes as .save_live_pending is not called during savevm or + * snapshot case, in such case vfio_update_pending() at the start of this + * function updates pending_bytes. + */ + migration->pending_bytes = 0; + trace_vfio_save_iterate(vbasedev->name, data_size); + return 0; +} + +static int vfio_save_complete_precopy(QEMUFile *f, void *opaque) +{ + VFIODevice *vbasedev = opaque; + VFIOMigration *migration = vbasedev->migration; + uint64_t data_size; + int ret; + + ret = vfio_migration_set_state(vbasedev, ~VFIO_DEVICE_STATE_RUNNING, + VFIO_DEVICE_STATE_SAVING); + if (ret) { + error_report("%s: Failed to set state STOP and SAVING", + vbasedev->name); + return ret; + } + + ret = vfio_save_device_config_state(f, opaque); + if (ret) { + return ret; + } + + ret = vfio_update_pending(vbasedev); + if (ret) { + return ret; + } + + while (migration->pending_bytes > 0) { + qemu_put_be64(f, VFIO_MIG_FLAG_DEV_DATA_STATE); + ret = vfio_save_buffer(f, vbasedev, &data_size); + if (ret < 0) { + error_report("%s: Failed to save buffer", vbasedev->name); + return ret; + } + + if (data_size == 0) { + break; + } + + ret = vfio_update_pending(vbasedev); + if (ret) { + return ret; + } + } + + qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE); + + ret = qemu_file_get_error(f); + if (ret) { + return ret; + } + + ret = vfio_migration_set_state(vbasedev, ~VFIO_DEVICE_STATE_SAVING, 0); + if (ret) { + error_report("%s: Failed to set state STOPPED", vbasedev->name); + return ret; + } + + trace_vfio_save_complete_precopy(vbasedev->name); + return ret; +} + +static int vfio_load_setup(QEMUFile *f, void *opaque) +{ + VFIODevice *vbasedev = opaque; + VFIOMigration *migration = vbasedev->migration; + int ret = 0; + + if (migration->region.mmaps) { + ret = vfio_region_mmap(&migration->region); + if (ret) { + error_report("%s: Failed to mmap VFIO migration region %d: %s", + vbasedev->name, migration->region.nr, + strerror(-ret)); + error_report("%s: Falling back to slow path", vbasedev->name); + } + } + + ret = vfio_migration_set_state(vbasedev, ~VFIO_DEVICE_STATE_MASK, + VFIO_DEVICE_STATE_RESUMING); + if (ret) { + error_report("%s: Failed to set state RESUMING", vbasedev->name); + if (migration->region.mmaps) { + vfio_region_unmap(&migration->region); + } + } + return ret; +} + +static int vfio_load_cleanup(void *opaque) +{ + VFIODevice *vbasedev = opaque; + + vfio_migration_cleanup(vbasedev); + trace_vfio_load_cleanup(vbasedev->name); + return 0; +} + +static int vfio_load_state(QEMUFile *f, void *opaque, int version_id) +{ + VFIODevice *vbasedev = opaque; + int ret = 0; + uint64_t data; + + data = qemu_get_be64(f); + while (data != VFIO_MIG_FLAG_END_OF_STATE) { + + trace_vfio_load_state(vbasedev->name, data); + + switch (data) { + case VFIO_MIG_FLAG_DEV_CONFIG_STATE: + { + ret = vfio_load_device_config_state(f, opaque); + if (ret) { + return ret; + } + break; + } + case VFIO_MIG_FLAG_DEV_SETUP_STATE: + { + data = qemu_get_be64(f); + if (data == VFIO_MIG_FLAG_END_OF_STATE) { + return ret; + } else { + error_report("%s: SETUP STATE: EOS not found 0x%"PRIx64, + vbasedev->name, data); + return -EINVAL; + } + break; + } + case VFIO_MIG_FLAG_DEV_DATA_STATE: + { + uint64_t data_size = qemu_get_be64(f); + + if (data_size) { + ret = vfio_load_buffer(f, vbasedev, data_size); + if (ret < 0) { + return ret; + } + } + break; + } + default: + error_report("%s: Unknown tag 0x%"PRIx64, vbasedev->name, data); + return -EINVAL; + } + + data = qemu_get_be64(f); + ret = qemu_file_get_error(f); + if (ret) { + return ret; + } + } + return ret; +} + +static SaveVMHandlers savevm_vfio_handlers = { + .save_setup = vfio_save_setup, + .save_cleanup = vfio_save_cleanup, + .save_live_pending = vfio_save_pending, + .save_live_iterate = vfio_save_iterate, + .save_live_complete_precopy = vfio_save_complete_precopy, + .load_setup = vfio_load_setup, + .load_cleanup = vfio_load_cleanup, + .load_state = vfio_load_state, +}; + +/* ---------------------------------------------------------------------- */ + +static void vfio_vmstate_change(void *opaque, int running, RunState state) +{ + VFIODevice *vbasedev = opaque; + VFIOMigration *migration = vbasedev->migration; + uint32_t value, mask; + int ret; + + if (vbasedev->migration->vm_running == running) { + return; + } + + if (running) { + /* + * Here device state can have one of _SAVING, _RESUMING or _STOP bit. + * Transition from _SAVING to _RUNNING can happen if there is migration + * failure, in that case clear _SAVING bit. + * Transition from _RESUMING to _RUNNING occurs during resuming + * phase, in that case clear _RESUMING bit. + * In both the above cases, set _RUNNING bit. + */ + mask = ~VFIO_DEVICE_STATE_MASK; + value = VFIO_DEVICE_STATE_RUNNING; + } else { + /* + * Here device state could be either _RUNNING or _SAVING|_RUNNING. Reset + * _RUNNING bit + */ + mask = ~VFIO_DEVICE_STATE_RUNNING; + value = 0; + } + + ret = vfio_migration_set_state(vbasedev, mask, value); + if (ret) { + /* + * Migration should be aborted in this case, but vm_state_notify() + * currently does not support reporting failures. + */ + error_report("%s: Failed to set device state 0x%x", vbasedev->name, + (migration->device_state & mask) | value); + qemu_file_set_error(migrate_get_current()->to_dst_file, ret); + } + vbasedev->migration->vm_running = running; + trace_vfio_vmstate_change(vbasedev->name, running, RunState_str(state), + (migration->device_state & mask) | value); +} + +static void vfio_migration_state_notifier(Notifier *notifier, void *data) +{ + MigrationState *s = data; + VFIOMigration *migration = container_of(notifier, VFIOMigration, + migration_state); + VFIODevice *vbasedev = migration->vbasedev; + int ret; + + trace_vfio_migration_state_notifier(vbasedev->name, + MigrationStatus_str(s->state)); + + switch (s->state) { + case MIGRATION_STATUS_CANCELLING: + case MIGRATION_STATUS_CANCELLED: + case MIGRATION_STATUS_FAILED: + bytes_transferred = 0; + ret = vfio_migration_set_state(vbasedev, + ~(VFIO_DEVICE_STATE_SAVING | VFIO_DEVICE_STATE_RESUMING), + VFIO_DEVICE_STATE_RUNNING); + if (ret) { + error_report("%s: Failed to set state RUNNING", vbasedev->name); + } + } +} + +static void vfio_migration_exit(VFIODevice *vbasedev) +{ + VFIOMigration *migration = vbasedev->migration; + + vfio_region_exit(&migration->region); + vfio_region_finalize(&migration->region); + g_free(vbasedev->migration); + vbasedev->migration = NULL; +} + +static int vfio_migration_init(VFIODevice *vbasedev, + struct vfio_region_info *info) +{ + int ret; + Object *obj; + VFIOMigration *migration; + char id[256] = ""; + g_autofree char *path = NULL, *oid = NULL; + + if (!vbasedev->ops->vfio_get_object) { + return -EINVAL; + } + + obj = vbasedev->ops->vfio_get_object(vbasedev); + if (!obj) { + return -EINVAL; + } + + vbasedev->migration = g_new0(VFIOMigration, 1); + + ret = vfio_region_setup(obj, vbasedev, &vbasedev->migration->region, + info->index, "migration"); + if (ret) { + error_report("%s: Failed to setup VFIO migration region %d: %s", + vbasedev->name, info->index, strerror(-ret)); + goto err; + } + + if (!vbasedev->migration->region.size) { + error_report("%s: Invalid zero-sized VFIO migration region %d", + vbasedev->name, info->index); + ret = -EINVAL; + goto err; + } + + migration = vbasedev->migration; + migration->vbasedev = vbasedev; + + oid = vmstate_if_get_id(VMSTATE_IF(DEVICE(obj))); + if (oid) { + path = g_strdup_printf("%s/vfio", oid); + } else { + path = g_strdup("vfio"); + } + strpadcpy(id, sizeof(id), path, '\0'); + + register_savevm_live(id, VMSTATE_INSTANCE_ID_ANY, 1, &savevm_vfio_handlers, + vbasedev); + + migration->vm_state = qemu_add_vm_change_state_handler(vfio_vmstate_change, + vbasedev); + migration->migration_state.notify = vfio_migration_state_notifier; + add_migration_state_change_notifier(&migration->migration_state); + return 0; + +err: + vfio_migration_exit(vbasedev); + return ret; +} + +/* ---------------------------------------------------------------------- */ + +int64_t vfio_mig_bytes_transferred(void) +{ + return bytes_transferred; +} + +int vfio_migration_probe(VFIODevice *vbasedev, Error **errp) +{ + VFIOContainer *container = vbasedev->group->container; + struct vfio_region_info *info = NULL; + Error *local_err = NULL; + int ret = -ENOTSUP; + + if (!vbasedev->enable_migration || !container->dirty_pages_supported) { + goto add_blocker; + } + + ret = vfio_get_dev_region_info(vbasedev, VFIO_REGION_TYPE_MIGRATION, + VFIO_REGION_SUBTYPE_MIGRATION, &info); + if (ret) { + goto add_blocker; + } + + ret = vfio_migration_init(vbasedev, info); + if (ret) { + goto add_blocker; + } + + trace_vfio_migration_probe(vbasedev->name, info->index); + g_free(info); + return 0; + +add_blocker: + error_setg(&vbasedev->migration_blocker, + "VFIO device doesn't support migration"); + g_free(info); + + ret = migrate_add_blocker(vbasedev->migration_blocker, &local_err); + if (local_err) { + error_propagate(errp, local_err); + error_free(vbasedev->migration_blocker); + vbasedev->migration_blocker = NULL; + } + return ret; +} + +void vfio_migration_finalize(VFIODevice *vbasedev) +{ + if (vbasedev->migration) { + VFIOMigration *migration = vbasedev->migration; + + remove_migration_state_change_notifier(&migration->migration_state); + qemu_del_vm_change_state_handler(migration->vm_state); + vfio_migration_exit(vbasedev); + } + + if (vbasedev->migration_blocker) { + migrate_del_blocker(vbasedev->migration_blocker); + error_free(vbasedev->migration_blocker); + vbasedev->migration_blocker = NULL; + } +} diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c index 3bd05fed12bd4231b9f7f3888d50334a1480c827..57150913b7e605e8202f0305fed55c2a363926b0 100644 --- a/hw/vfio/pci-quirks.c +++ b/hw/vfio/pci-quirks.c @@ -11,6 +11,7 @@ */ #include "qemu/osdep.h" +#include CONFIG_DEVICES #include "exec/memop.h" #include "qemu/units.h" #include "qemu/error-report.h" @@ -1501,16 +1502,13 @@ static void set_nv_gpudirect_clique_id(Object *obj, Visitor *v, DeviceState *dev = DEVICE(obj); Property *prop = opaque; uint8_t value, *ptr = qdev_get_prop_ptr(dev, prop); - Error *local_err = NULL; if (dev->realized) { qdev_prop_set_after_realize(dev, name, errp); return; } - visit_type_uint8(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_uint8(v, name, &value, errp)) { return; } @@ -1567,18 +1565,6 @@ static int vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp) return 0; } -int vfio_add_virt_caps(VFIOPCIDevice *vdev, Error **errp) -{ - int ret; - - ret = vfio_add_nv_gpudirect_cap(vdev, errp); - if (ret) { - return ret; - } - - return 0; -} - static void vfio_pci_nvlink2_get_tgt(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) @@ -1620,7 +1606,7 @@ int vfio_pci_nvidia_v100_ram_init(VFIOPCIDevice *vdev, Error **errp) } cap = (void *) hdr; - p = mmap(NULL, nv2reg->size, PROT_READ | PROT_WRITE | PROT_EXEC, + p = mmap(NULL, nv2reg->size, PROT_READ | PROT_WRITE, MAP_SHARED, vdev->vbasedev.fd, nv2reg->offset); if (p == MAP_FAILED) { ret = -errno; @@ -1680,7 +1666,7 @@ int vfio_pci_nvlink2_init(VFIOPCIDevice *vdev, Error **errp) /* Some NVLink bridges may not have assigned ATSD */ if (atsdreg->size) { - p = mmap(NULL, atsdreg->size, PROT_READ | PROT_WRITE | PROT_EXEC, + p = mmap(NULL, atsdreg->size, PROT_READ | PROT_WRITE, MAP_SHARED, vdev->vbasedev.fd, atsdreg->offset); if (p == MAP_FAILED) { ret = -errno; @@ -1709,3 +1695,75 @@ free_exit: return ret; } + +/* + * The VMD endpoint provides a real PCIe domain to the guest and the guest + * kernel performs enumeration of the VMD sub-device domain. Guest transactions + * to VMD sub-devices go through MMU translation from guest addresses to + * physical addresses. When MMIO goes to an endpoint after being translated to + * physical addresses, the bridge rejects the transaction because the window + * has been programmed with guest addresses. + * + * VMD can use the Host Physical Address in order to correctly program the + * bridge windows in its PCIe domain. VMD device 28C0 has HPA shadow registers + * located at offset 0x2000 in MEMBAR2 (BAR 4). This quirk provides the HPA + * shadow registers in a vendor-specific capability register for devices + * without native support. The position of 0xE8-0xFF is in the reserved range + * of the VMD device capability space following the Power Management + * Capability. + */ +#define VMD_SHADOW_CAP_VER 1 +#define VMD_SHADOW_CAP_LEN 24 +static int vfio_add_vmd_shadow_cap(VFIOPCIDevice *vdev, Error **errp) +{ + uint8_t membar_phys[16]; + int ret, pos = 0xE8; + + if (!(vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, 0x201D) || + vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, 0x467F) || + vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, 0x4C3D) || + vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, 0x9A0B))) { + return 0; + } + + ret = pread(vdev->vbasedev.fd, membar_phys, 16, + vdev->config_offset + PCI_BASE_ADDRESS_2); + if (ret != 16) { + error_report("VMD %s cannot read MEMBARs (%d)", + vdev->vbasedev.name, ret); + return -EFAULT; + } + + ret = pci_add_capability(&vdev->pdev, PCI_CAP_ID_VNDR, pos, + VMD_SHADOW_CAP_LEN, errp); + if (ret < 0) { + error_prepend(errp, "Failed to add VMD MEMBAR Shadow cap: "); + return ret; + } + + memset(vdev->emulated_config_bits + pos, 0xFF, VMD_SHADOW_CAP_LEN); + pos += PCI_CAP_FLAGS; + pci_set_byte(vdev->pdev.config + pos++, VMD_SHADOW_CAP_LEN); + pci_set_byte(vdev->pdev.config + pos++, VMD_SHADOW_CAP_VER); + pci_set_long(vdev->pdev.config + pos, 0x53484457); /* SHDW */ + memcpy(vdev->pdev.config + pos + 4, membar_phys, 16); + + return 0; +} + +int vfio_add_virt_caps(VFIOPCIDevice *vdev, Error **errp) +{ + int ret; + + ret = vfio_add_nv_gpudirect_cap(vdev, errp); + if (ret) { + return ret; + } + + ret = vfio_add_vmd_shadow_cap(vdev, errp); + if (ret) { + return ret; + } + + return 0; +} diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 342dd6b9129d45c16ca535f62b1ed5329f4011c8..51dc37369504560f2523e8461b0cdb66f3628590 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -41,9 +41,7 @@ #include "trace.h" #include "qapi/error.h" #include "migration/blocker.h" - -#define TYPE_VFIO_PCI "vfio-pci" -#define PCI_VFIO(obj) OBJECT_CHECK(VFIOPCIDevice, obj, TYPE_VFIO_PCI) +#include "migration/qemu-file.h" #define TYPE_VFIO_PCI_NOHOTPLUG "vfio-pci-nohotplug" @@ -115,12 +113,7 @@ static void vfio_intx_eoi(VFIODevice *vbasedev) static void vfio_intx_enable_kvm(VFIOPCIDevice *vdev, Error **errp) { #ifdef CONFIG_KVM - struct kvm_irqfd irqfd = { - .fd = event_notifier_get_fd(&vdev->intx.interrupt), - .gsi = vdev->intx.route.irq, - .flags = KVM_IRQFD_FLAG_RESAMPLE, - }; - Error *err = NULL; + int irq_fd = event_notifier_get_fd(&vdev->intx.interrupt); if (vdev->no_kvm_intx || !kvm_irqfds_enabled() || vdev->intx.route.mode != PCI_INTX_ENABLED || @@ -129,7 +122,7 @@ static void vfio_intx_enable_kvm(VFIOPCIDevice *vdev, Error **errp) } /* Get to a known interrupt state */ - qemu_set_fd_handler(irqfd.fd, NULL, NULL, vdev); + qemu_set_fd_handler(irq_fd, NULL, NULL, vdev); vfio_mask_single_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX); vdev->intx.pending = false; pci_irq_deassert(&vdev->pdev); @@ -140,18 +133,18 @@ static void vfio_intx_enable_kvm(VFIOPCIDevice *vdev, Error **errp) goto fail; } - /* KVM triggers it, VFIO listens for it */ - irqfd.resamplefd = event_notifier_get_fd(&vdev->intx.unmask); - - if (kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd)) { + if (kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, + &vdev->intx.interrupt, + &vdev->intx.unmask, + vdev->intx.route.irq)) { error_setg_errno(errp, errno, "failed to setup resample irqfd"); goto fail_irqfd; } if (vfio_set_irq_signaling(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX, 0, VFIO_IRQ_SET_ACTION_UNMASK, - irqfd.resamplefd, &err)) { - error_propagate(errp, err); + event_notifier_get_fd(&vdev->intx.unmask), + errp)) { goto fail_vfio; } @@ -165,12 +158,12 @@ static void vfio_intx_enable_kvm(VFIOPCIDevice *vdev, Error **errp) return; fail_vfio: - irqfd.flags = KVM_IRQFD_FLAG_DEASSIGN; - kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd); + kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, &vdev->intx.interrupt, + vdev->intx.route.irq); fail_irqfd: event_notifier_cleanup(&vdev->intx.unmask); fail: - qemu_set_fd_handler(irqfd.fd, vfio_intx_interrupt, NULL, vdev); + qemu_set_fd_handler(irq_fd, vfio_intx_interrupt, NULL, vdev); vfio_unmask_single_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX); #endif } @@ -178,12 +171,6 @@ fail: static void vfio_intx_disable_kvm(VFIOPCIDevice *vdev) { #ifdef CONFIG_KVM - struct kvm_irqfd irqfd = { - .fd = event_notifier_get_fd(&vdev->intx.interrupt), - .gsi = vdev->intx.route.irq, - .flags = KVM_IRQFD_FLAG_DEASSIGN, - }; - if (!vdev->intx.kvm_accel) { return; } @@ -197,7 +184,8 @@ static void vfio_intx_disable_kvm(VFIOPCIDevice *vdev) pci_irq_deassert(&vdev->pdev); /* Tell KVM to stop listening for an INTx irqfd */ - if (kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd)) { + if (kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, &vdev->intx.interrupt, + vdev->intx.route.irq)) { error_report("vfio: Error: Failed to disable INTx irqfd: %m"); } @@ -205,7 +193,8 @@ static void vfio_intx_disable_kvm(VFIOPCIDevice *vdev) event_notifier_cleanup(&vdev->intx.unmask); /* QEMU starts listening for interrupt events. */ - qemu_set_fd_handler(irqfd.fd, vfio_intx_interrupt, NULL, vdev); + qemu_set_fd_handler(event_notifier_get_fd(&vdev->intx.interrupt), + vfio_intx_interrupt, NULL, vdev); vdev->intx.kvm_accel = false; @@ -242,7 +231,7 @@ static void vfio_intx_update(VFIOPCIDevice *vdev, PCIINTxRoute *route) static void vfio_intx_routing_notifier(PCIDevice *pdev) { - VFIOPCIDevice *vdev = PCI_VFIO(pdev); + VFIOPCIDevice *vdev = VFIO_PCI(pdev); PCIINTxRoute route; if (vdev->interrupt != VFIO_INT_INTx) { @@ -301,8 +290,7 @@ static int vfio_intx_enable(VFIOPCIDevice *vdev, Error **errp) qemu_set_fd_handler(fd, vfio_intx_interrupt, NULL, vdev); if (vfio_set_irq_signaling(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX, 0, - VFIO_IRQ_SET_ACTION_TRIGGER, fd, &err)) { - error_propagate(errp, err); + VFIO_IRQ_SET_ACTION_TRIGGER, fd, errp)) { qemu_set_fd_handler(fd, NULL, NULL, vdev); event_notifier_cleanup(&vdev->intx.interrupt); return -errno; @@ -469,7 +457,7 @@ static void vfio_update_kvm_msi_virq(VFIOMSIVector *vector, MSIMessage msg, static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr, MSIMessage *msg, IOHandler *handler) { - VFIOPCIDevice *vdev = PCI_VFIO(pdev); + VFIOPCIDevice *vdev = VFIO_PCI(pdev); VFIOMSIVector *vector; int ret; @@ -554,7 +542,7 @@ static int vfio_msix_vector_use(PCIDevice *pdev, static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr) { - VFIOPCIDevice *vdev = PCI_VFIO(pdev); + VFIOPCIDevice *vdev = VFIO_PCI(pdev); VFIOMSIVector *vector = &vdev->msi_vectors[nr]; trace_vfio_msix_vector_release(vdev->vbasedev.name, nr); @@ -1061,7 +1049,7 @@ static const MemoryRegionOps vfio_vga_ops = { */ static void vfio_sub_page_bar_update_mapping(PCIDevice *pdev, int bar) { - VFIOPCIDevice *vdev = PCI_VFIO(pdev); + VFIOPCIDevice *vdev = VFIO_PCI(pdev); VFIORegion *region = &vdev->bars[bar].region; MemoryRegion *mmap_mr, *region_mr, *base_mr; PCIIORegion *r; @@ -1107,7 +1095,7 @@ static void vfio_sub_page_bar_update_mapping(PCIDevice *pdev, int bar) */ uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len) { - VFIOPCIDevice *vdev = PCI_VFIO(pdev); + VFIOPCIDevice *vdev = VFIO_PCI(pdev); uint32_t emu_bits = 0, emu_val = 0, phys_val = 0, val; memcpy(&emu_bits, vdev->emulated_config_bits + addr, len); @@ -1140,7 +1128,7 @@ uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len) void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr, uint32_t val, int len) { - VFIOPCIDevice *vdev = PCI_VFIO(pdev); + VFIOPCIDevice *vdev = VFIO_PCI(pdev); uint32_t val_le = cpu_to_le32(val); trace_vfio_pci_write_config(vdev->vbasedev.name, addr, val, len); @@ -2407,10 +2395,68 @@ static void vfio_pci_compute_needs_reset(VFIODevice *vbasedev) } } +static Object *vfio_pci_get_object(VFIODevice *vbasedev) +{ + VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev); + + return OBJECT(vdev); +} + +static bool vfio_msix_present(void *opaque, int version_id) +{ + PCIDevice *pdev = opaque; + + return msix_present(pdev); +} + +const VMStateDescription vmstate_vfio_pci_config = { + .name = "VFIOPCIDevice", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_PCI_DEVICE(pdev, VFIOPCIDevice), + VMSTATE_MSIX_TEST(pdev, VFIOPCIDevice, vfio_msix_present), + VMSTATE_END_OF_LIST() + } +}; + +static void vfio_pci_save_config(VFIODevice *vbasedev, QEMUFile *f) +{ + VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev); + + vmstate_save_state(f, &vmstate_vfio_pci_config, vdev, NULL); +} + +static int vfio_pci_load_config(VFIODevice *vbasedev, QEMUFile *f) +{ + VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev); + PCIDevice *pdev = &vdev->pdev; + int ret; + + ret = vmstate_load_state(f, &vmstate_vfio_pci_config, vdev, 1); + if (ret) { + return ret; + } + + vfio_pci_write_config(pdev, PCI_COMMAND, + pci_get_word(pdev->config + PCI_COMMAND), 2); + + if (msi_enabled(pdev)) { + vfio_msi_enable(vdev); + } else if (msix_enabled(pdev)) { + vfio_msix_enable(vdev); + } + + return ret; +} + static VFIODeviceOps vfio_pci_ops = { .vfio_compute_needs_reset = vfio_pci_compute_needs_reset, .vfio_hot_reset_multi = vfio_pci_hot_reset_multi, .vfio_eoi = vfio_intx_eoi, + .vfio_get_object = vfio_pci_get_object, + .vfio_save_config = vfio_pci_save_config, + .vfio_load_config = vfio_pci_load_config, }; int vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp) @@ -2714,7 +2760,7 @@ static void vfio_unregister_req_notifier(VFIOPCIDevice *vdev) static void vfio_realize(PCIDevice *pdev, Error **errp) { - VFIOPCIDevice *vdev = PCI_VFIO(pdev); + VFIOPCIDevice *vdev = VFIO_PCI(pdev); VFIODevice *vbasedev_iter; VFIOGroup *group; char *tmp, *subsys, group_path[PATH_MAX], *group_name; @@ -2745,18 +2791,6 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) return; } - if (!pdev->failover_pair_id) { - error_setg(&vdev->migration_blocker, - "VFIO device doesn't support migration"); - ret = migrate_add_blocker(vdev->migration_blocker, &err); - if (ret) { - error_propagate(errp, err); - error_free(vdev->migration_blocker); - vdev->migration_blocker = NULL; - return; - } - } - vdev->vbasedev.name = g_path_get_basename(vdev->vbasedev.sysfsdev); vdev->vbasedev.ops = &vfio_pci_ops; vdev->vbasedev.type = VFIO_DEVICE_TYPE_PCI; @@ -2796,7 +2830,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) } /* - * Mediated devices *might* operate compatibly with memory ballooning, but + * Mediated devices *might* operate compatibly with discarding of RAM, but * we cannot know for certain, it depends on whether the mdev vendor driver * stays in sync with the active working set of the guest driver. Prevent * the x-balloon-allowed option unless this is minimally an mdev device. @@ -2809,7 +2843,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) trace_vfio_mdev(vdev->vbasedev.name, is_mdev); - if (vdev->vbasedev.balloon_allowed && !is_mdev) { + if (vdev->vbasedev.ram_block_discard_allowed && !is_mdev) { error_setg(errp, "x-balloon-allowed only potentially compatible " "with mdev devices"); vfio_put_group(group); @@ -3024,6 +3058,13 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) } } + if (!pdev->failover_pair_id) { + ret = vfio_migration_probe(&vdev->vbasedev, errp); + if (ret) { + error_report("%s: Migration disabled", vdev->vbasedev.name); + } + } + vfio_register_err_notifier(vdev); vfio_register_req_notifier(vdev); vfio_setup_resetfn_quirk(vdev); @@ -3038,26 +3079,17 @@ out_teardown: vfio_bars_exit(vdev); error: error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.name); - if (vdev->migration_blocker) { - migrate_del_blocker(vdev->migration_blocker); - error_free(vdev->migration_blocker); - vdev->migration_blocker = NULL; - } } static void vfio_instance_finalize(Object *obj) { - VFIOPCIDevice *vdev = PCI_VFIO(obj); + VFIOPCIDevice *vdev = VFIO_PCI(obj); VFIOGroup *group = vdev->vbasedev.group; vfio_display_finalize(vdev); vfio_bars_finalize(vdev); g_free(vdev->emulated_config_bits); g_free(vdev->rom); - if (vdev->migration_blocker) { - migrate_del_blocker(vdev->migration_blocker); - error_free(vdev->migration_blocker); - } /* * XXX Leaking igd_opregion is not an oversight, we can't remove the * fw_cfg entry therefore leaking this allocation seems like the safest @@ -3071,7 +3103,7 @@ static void vfio_instance_finalize(Object *obj) static void vfio_exitfn(PCIDevice *pdev) { - VFIOPCIDevice *vdev = PCI_VFIO(pdev); + VFIOPCIDevice *vdev = VFIO_PCI(pdev); vfio_unregister_req_notifier(vdev); vfio_unregister_err_notifier(vdev); @@ -3085,11 +3117,12 @@ static void vfio_exitfn(PCIDevice *pdev) } vfio_teardown_msi(vdev); vfio_bars_exit(vdev); + vfio_migration_finalize(&vdev->vbasedev); } static void vfio_pci_reset(DeviceState *dev) { - VFIOPCIDevice *vdev = PCI_VFIO(dev); + VFIOPCIDevice *vdev = VFIO_PCI(dev); trace_vfio_pci_reset(vdev->vbasedev.name); @@ -3129,7 +3162,7 @@ post_reset: static void vfio_instance_init(Object *obj) { PCIDevice *pci_dev = PCI_DEVICE(obj); - VFIOPCIDevice *vdev = PCI_VFIO(obj); + VFIOPCIDevice *vdev = VFIO_PCI(obj); device_add_bootindex_property(obj, &vdev->bootindex, "bootindex", NULL, @@ -3149,6 +3182,9 @@ static void vfio_instance_init(Object *obj) static Property vfio_pci_dev_properties[] = { DEFINE_PROP_PCI_HOST_DEVADDR("host", VFIOPCIDevice, host), DEFINE_PROP_STRING("sysfsdev", VFIOPCIDevice, vbasedev.sysfsdev), + DEFINE_PROP_ON_OFF_AUTO("x-pre-copy-dirty-page-tracking", VFIOPCIDevice, + vbasedev.pre_copy_dirty_page_tracking, + ON_OFF_AUTO_ON), DEFINE_PROP_ON_OFF_AUTO("display", VFIOPCIDevice, display, ON_OFF_AUTO_OFF), DEFINE_PROP_UINT32("xres", VFIOPCIDevice, display_xres, 0), @@ -3161,9 +3197,11 @@ static Property vfio_pci_dev_properties[] = { VFIO_FEATURE_ENABLE_REQ_BIT, true), DEFINE_PROP_BIT("x-igd-opregion", VFIOPCIDevice, features, VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT, false), + DEFINE_PROP_BOOL("x-enable-migration", VFIOPCIDevice, + vbasedev.enable_migration, false), DEFINE_PROP_BOOL("x-no-mmap", VFIOPCIDevice, vbasedev.no_mmap, false), DEFINE_PROP_BOOL("x-balloon-allowed", VFIOPCIDevice, - vbasedev.balloon_allowed, false), + vbasedev.ram_block_discard_allowed, false), DEFINE_PROP_BOOL("x-no-kvm-intx", VFIOPCIDevice, no_kvm_intx, false), DEFINE_PROP_BOOL("x-no-kvm-msi", VFIOPCIDevice, no_kvm_msi, false), DEFINE_PROP_BOOL("x-no-kvm-msix", VFIOPCIDevice, no_kvm_msix, false), diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h index 0da7a20a7ec2402d7f1ccef9401ce9f69c474836..1574ef983f8f0f55000ee8c78bb0b149c7d98277 100644 --- a/hw/vfio/pci.h +++ b/hw/vfio/pci.h @@ -18,6 +18,7 @@ #include "qemu/event_notifier.h" #include "qemu/queue.h" #include "qemu/timer.h" +#include "qom/object.h" #define PCI_ANY_ID (~0) @@ -113,7 +114,10 @@ typedef struct VFIOMSIXInfo { unsigned long *pending; } VFIOMSIXInfo; -typedef struct VFIOPCIDevice { +#define TYPE_VFIO_PCI "vfio-pci" +OBJECT_DECLARE_SIMPLE_TYPE(VFIOPCIDevice, VFIO_PCI) + +struct VFIOPCIDevice { PCIDevice pdev; VFIODevice vbasedev; VFIOINTx intx; @@ -168,9 +172,8 @@ typedef struct VFIOPCIDevice { bool no_vfio_ioeventfd; bool enable_ramfb; VFIODisplay *dpy; - Error *migration_blocker; Notifier irqchip_change_notifier; -} VFIOPCIDevice; +}; /* Use uin32_t for vendor & device so PCI_ANY_ID expands and cannot match hw */ static inline bool vfio_pci_is(VFIOPCIDevice *vdev, uint32_t vendor, uint32_t device) diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c index ac2cefc9b184d07f4bdc76136833276aa5743cb8..cc3f66f7e44c747a5dfc336fc0c6142f8559fdf3 100644 --- a/hw/vfio/platform.c +++ b/hw/vfio/platform.c @@ -166,7 +166,7 @@ static void vfio_intp_mmap_enable(void *opaque) VFIOINTp *tmp; VFIOPlatformDevice *vdev = (VFIOPlatformDevice *)opaque; - qemu_mutex_lock(&vdev->intp_mutex); + QEMU_LOCK_GUARD(&vdev->intp_mutex); QLIST_FOREACH(tmp, &vdev->intp_list, next) { if (tmp->state == VFIO_IRQ_ACTIVE) { trace_vfio_platform_intp_mmap_enable(tmp->pin); @@ -174,12 +174,10 @@ static void vfio_intp_mmap_enable(void *opaque) timer_mod(vdev->mmap_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + vdev->mmap_timeout); - qemu_mutex_unlock(&vdev->intp_mutex); return; } } vfio_mmap_set_enabled(vdev, true); - qemu_mutex_unlock(&vdev->intp_mutex); } /** @@ -236,7 +234,7 @@ static void vfio_intp_interrupt(VFIOINTp *intp) trace_vfio_intp_interrupt_set_pending(intp->pin); QSIMPLEQ_INSERT_TAIL(&vdev->pending_intp_queue, intp, pqnext); - ret = event_notifier_test_and_clear(intp->interrupt); + event_notifier_test_and_clear(intp->interrupt); return; } @@ -289,7 +287,7 @@ static void vfio_platform_eoi(VFIODevice *vbasedev) VFIOPlatformDevice *vdev = container_of(vbasedev, VFIOPlatformDevice, vbasedev); - qemu_mutex_lock(&vdev->intp_mutex); + QEMU_LOCK_GUARD(&vdev->intp_mutex); QLIST_FOREACH(intp, &vdev->intp_list, next) { if (intp->state == VFIO_IRQ_ACTIVE) { trace_vfio_platform_eoi(intp->pin, @@ -314,7 +312,6 @@ static void vfio_platform_eoi(VFIODevice *vbasedev) vfio_intp_inject_pending_lockheld(intp); QSIMPLEQ_REMOVE_HEAD(&vdev->pending_intp_queue, pqnext); } - qemu_mutex_unlock(&vdev->intp_mutex); } /** diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events index b1ef55a33ffd1bb16e9e49126677f34e85f1cd74..c0e75f24b76daf3ecf287e0415d358261a22b68b 100644 --- a/hw/vfio/trace-events +++ b/hw/vfio/trace-events @@ -80,16 +80,18 @@ vfio_quirk_ati_bonaire_reset(const char *name) "%s" vfio_ioeventfd_exit(const char *name, uint64_t addr, unsigned size, uint64_t data) "%s+0x%"PRIx64"[%d]:0x%"PRIx64 vfio_ioeventfd_handler(const char *name, uint64_t addr, unsigned size, uint64_t data) "%s+0x%"PRIx64"[%d] -> 0x%"PRIx64 vfio_ioeventfd_init(const char *name, uint64_t addr, unsigned size, uint64_t data, bool vfio) "%s+0x%"PRIx64"[%d]:0x%"PRIx64" vfio:%d" -vfio_pci_igd_bar4_write(const char *name, uint32_t index, uint32_t data, uint32_t base) "%s [0x%03x] 0x%08x -> 0x%08x" -vfio_pci_igd_bdsm_enabled(const char *name, int size) "%s %dMB" vfio_pci_igd_opregion_enabled(const char *name) "%s" -vfio_pci_igd_host_bridge_enabled(const char *name) "%s" -vfio_pci_igd_lpc_bridge_enabled(const char *name) "%s" vfio_pci_nvidia_gpu_setup_quirk(const char *name, uint64_t tgt, uint64_t size) "%s tgt=0x%"PRIx64" size=0x%"PRIx64 vfio_pci_nvlink2_setup_quirk_ssatgt(const char *name, uint64_t tgt, uint64_t size) "%s tgt=0x%"PRIx64" size=0x%"PRIx64 vfio_pci_nvlink2_setup_quirk_lnkspd(const char *name, uint32_t link_speed) "%s link_speed=0x%x" +# igd.c +vfio_pci_igd_bar4_write(const char *name, uint32_t index, uint32_t data, uint32_t base) "%s [0x%03x] 0x%08x -> 0x%08x" +vfio_pci_igd_bdsm_enabled(const char *name, int size) "%s %dMB" +vfio_pci_igd_host_bridge_enabled(const char *name) "%s" +vfio_pci_igd_lpc_bridge_enabled(const char *name) "%s" + # common.c vfio_region_write(const char *name, int index, uint64_t addr, uint64_t data, unsigned size) " (%s:region%d+0x%"PRIx64", 0x%"PRIx64 ", %d)" vfio_region_read(char *name, int index, uint64_t addr, unsigned size, uint64_t data) " (%s:region%d+0x%"PRIx64", %d) = 0x%"PRIx64 @@ -111,6 +113,7 @@ vfio_region_mmap(const char *name, unsigned long offset, unsigned long end) "Reg vfio_region_exit(const char *name, int index) "Device %s, region %d" vfio_region_finalize(const char *name, int index) "Device %s, region %d" vfio_region_mmaps_set_enabled(const char *name, bool enabled) "Region %s mmaps enabled: %d" +vfio_region_unmap(const char *name, unsigned long offset, unsigned long end) "Region %s unmap [0x%lx - 0x%lx]" vfio_region_sparse_mmap_header(const char *name, int index, int nr_areas) "Device %s region %d: %d sparse mmap entries" vfio_region_sparse_mmap_entry(int i, unsigned long start, unsigned long end) "sparse entry %d [0x%lx - 0x%lx]" vfio_get_dev_region(const char *name, int index, uint32_t type, uint32_t subtype) "%s index %d, %08x/%0x8" @@ -142,3 +145,23 @@ vfio_display_edid_link_up(void) "" vfio_display_edid_link_down(void) "" vfio_display_edid_update(uint32_t prefx, uint32_t prefy) "%ux%u" vfio_display_edid_write_error(void) "" + +# migration.c +vfio_migration_probe(const char *name, uint32_t index) " (%s) Region %d" +vfio_migration_set_state(const char *name, uint32_t state) " (%s) state %d" +vfio_vmstate_change(const char *name, int running, const char *reason, uint32_t dev_state) " (%s) running %d reason %s device state %d" +vfio_migration_state_notifier(const char *name, const char *state) " (%s) state %s" +vfio_save_setup(const char *name) " (%s)" +vfio_save_cleanup(const char *name) " (%s)" +vfio_save_buffer(const char *name, uint64_t data_offset, uint64_t data_size, uint64_t pending) " (%s) Offset 0x%"PRIx64" size 0x%"PRIx64" pending 0x%"PRIx64 +vfio_update_pending(const char *name, uint64_t pending) " (%s) pending 0x%"PRIx64 +vfio_save_device_config_state(const char *name) " (%s)" +vfio_save_pending(const char *name, uint64_t precopy, uint64_t postcopy, uint64_t compatible) " (%s) precopy 0x%"PRIx64" postcopy 0x%"PRIx64" compatible 0x%"PRIx64 +vfio_save_iterate(const char *name, int data_size) " (%s) data_size %d" +vfio_save_complete_precopy(const char *name) " (%s)" +vfio_load_device_config_state(const char *name) " (%s)" +vfio_load_state(const char *name, uint64_t data) " (%s) data 0x%"PRIx64 +vfio_load_state_device_data(const char *name, uint64_t data_offset, uint64_t data_size) " (%s) Offset 0x%"PRIx64" size 0x%"PRIx64 +vfio_load_cleanup(const char *name) " (%s)" +vfio_get_dirty_bitmap(int fd, uint64_t iova, uint64_t size, uint64_t bitmap_size, uint64_t start) "container fd=%d, iova=0x%"PRIx64" size= 0x%"PRIx64" bitmap_size=0x%"PRIx64" start=0x%"PRIx64 +vfio_iommu_map_dirty_notify(uint64_t iova_start, uint64_t iova_end) "iommu dirty @ 0x%"PRIx64" - 0x%"PRIx64 diff --git a/hw/vfio/trace.h b/hw/vfio/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..5a343aa59cc9b7aa76df9d900acbeec17a95f046 --- /dev/null +++ b/hw/vfio/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_vfio.h" diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig index 83122424fabc84c5aacfc8e97e6af78c7cb8b6ed..0eda25c4e1bffe421b4d51f9147df02e7f62304d 100644 --- a/hw/virtio/Kconfig +++ b/hw/virtio/Kconfig @@ -47,3 +47,14 @@ config VIRTIO_PMEM depends on VIRTIO depends on VIRTIO_PMEM_SUPPORTED select MEM_DEVICE + +config VIRTIO_MEM_SUPPORTED + bool + +config VIRTIO_MEM + bool + default y + depends on VIRTIO + depends on LINUX + depends on VIRTIO_MEM_SUPPORTED + select MEM_DEVICE diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs deleted file mode 100644 index 4e4d39a0a48fe90dbd99598cc0710a9d246e612e..0000000000000000000000000000000000000000 --- a/hw/virtio/Makefile.objs +++ /dev/null @@ -1,43 +0,0 @@ -ifeq ($(CONFIG_VIRTIO),y) -common-obj-y += virtio-bus.o -obj-y += virtio.o - -obj-$(CONFIG_VHOST) += vhost.o vhost-backend.o -common-obj-$(call lnot,$(CONFIG_VHOST)) += vhost-stub.o -obj-$(CONFIG_VHOST_USER) += vhost-user.o - -common-obj-$(CONFIG_VIRTIO_RNG) += virtio-rng.o -common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o -common-obj-$(CONFIG_VIRTIO_MMIO) += virtio-mmio.o -obj-$(CONFIG_VIRTIO_BALLOON) += virtio-balloon.o -obj-$(CONFIG_VIRTIO_CRYPTO) += virtio-crypto.o -obj-$(CONFIG_VHOST_USER_FS) += vhost-user-fs.o -obj-$(call land,$(CONFIG_VIRTIO_CRYPTO),$(CONFIG_VIRTIO_PCI)) += virtio-crypto-pci.o -obj-$(CONFIG_VIRTIO_PMEM) += virtio-pmem.o -common-obj-$(call land,$(CONFIG_VIRTIO_PMEM),$(CONFIG_VIRTIO_PCI)) += virtio-pmem-pci.o -obj-$(call land,$(CONFIG_VHOST_USER_FS),$(CONFIG_VIRTIO_PCI)) += vhost-user-fs-pci.o -obj-$(CONFIG_VIRTIO_IOMMU) += virtio-iommu.o -obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock.o - -ifeq ($(CONFIG_VIRTIO_PCI),y) -obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock-pci.o -obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk-pci.o -obj-$(CONFIG_VHOST_USER_INPUT) += vhost-user-input-pci.o -obj-$(CONFIG_VHOST_USER_SCSI) += vhost-user-scsi-pci.o -obj-$(CONFIG_VHOST_SCSI) += vhost-scsi-pci.o -obj-$(CONFIG_VIRTIO_INPUT_HOST) += virtio-input-host-pci.o -obj-$(CONFIG_VIRTIO_INPUT) += virtio-input-pci.o -obj-$(CONFIG_VIRTIO_RNG) += virtio-rng-pci.o -obj-$(CONFIG_VIRTIO_BALLOON) += virtio-balloon-pci.o -obj-$(CONFIG_VIRTIO_IOMMU) += virtio-iommu-pci.o -obj-$(CONFIG_VIRTIO_9P) += virtio-9p-pci.o -obj-$(CONFIG_VIRTIO_SCSI) += virtio-scsi-pci.o -obj-$(CONFIG_VIRTIO_BLK) += virtio-blk-pci.o -obj-$(CONFIG_VIRTIO_NET) += virtio-net-pci.o -obj-$(CONFIG_VIRTIO_SERIAL) += virtio-serial-pci.o -endif -else -common-obj-y += vhost-stub.o -endif - -common-obj-$(CONFIG_ALL) += vhost-stub.o diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..fbff9bc9d4de498cad88183c74e4babf461b64a7 --- /dev/null +++ b/hw/virtio/meson.build @@ -0,0 +1,51 @@ +softmmu_virtio_ss = ss.source_set() +softmmu_virtio_ss.add(files('virtio-bus.c')) +softmmu_virtio_ss.add(when: 'CONFIG_VIRTIO_PCI', if_true: files('virtio-pci.c')) +softmmu_virtio_ss.add(when: 'CONFIG_VIRTIO_MMIO', if_true: files('virtio-mmio.c')) +softmmu_virtio_ss.add(when: 'CONFIG_VHOST', if_false: files('vhost-stub.c')) + +softmmu_ss.add_all(when: 'CONFIG_VIRTIO', if_true: softmmu_virtio_ss) +softmmu_ss.add(when: 'CONFIG_VIRTIO', if_false: files('vhost-stub.c')) + +softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('vhost-stub.c')) + +virtio_ss = ss.source_set() +virtio_ss.add(files('virtio.c')) +virtio_ss.add(when: 'CONFIG_VHOST', if_true: files('vhost.c', 'vhost-backend.c')) +virtio_ss.add(when: 'CONFIG_VHOST_USER', if_true: files('vhost-user.c')) +virtio_ss.add(when: 'CONFIG_VHOST_VDPA', if_true: files('vhost-vdpa.c')) +virtio_ss.add(when: 'CONFIG_VIRTIO_BALLOON', if_true: files('virtio-balloon.c')) +virtio_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('virtio-crypto.c')) +virtio_ss.add(when: ['CONFIG_VIRTIO_CRYPTO', 'CONFIG_VIRTIO_PCI'], if_true: files('virtio-crypto-pci.c')) +virtio_ss.add(when: 'CONFIG_VHOST_USER_FS', if_true: files('vhost-user-fs.c')) +virtio_ss.add(when: ['CONFIG_VHOST_USER_FS', 'CONFIG_VIRTIO_PCI'], if_true: files('vhost-user-fs-pci.c')) +virtio_ss.add(when: 'CONFIG_VIRTIO_PMEM', if_true: files('virtio-pmem.c')) +virtio_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock.c', 'vhost-vsock-common.c')) +virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-user-vsock.c', 'vhost-vsock-common.c')) +virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng.c')) +virtio_ss.add(when: 'CONFIG_VIRTIO_IOMMU', if_true: files('virtio-iommu.c')) +virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c')) + +virtio_pci_ss = ss.source_set() +virtio_pci_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-user-vsock-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_BLK', if_true: files('vhost-user-blk-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_INPUT', if_true: files('vhost-user-input-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_SCSI', if_true: files('vhost-user-scsi-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VHOST_SCSI', if_true: files('vhost-scsi-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VIRTIO_INPUT_HOST', if_true: files('virtio-input-host-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VIRTIO_INPUT', if_true: files('virtio-input-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VIRTIO_BALLOON', if_true: files('virtio-balloon-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VIRTIO_9P', if_true: files('virtio-9p-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VIRTIO_SCSI', if_true: files('virtio-scsi-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-blk-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VIRTIO_NET', if_true: files('virtio-net-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VIRTIO_SERIAL', if_true: files('virtio-serial-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VIRTIO_PMEM', if_true: files('virtio-pmem-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VIRTIO_IOMMU', if_true: files('virtio-iommu-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem-pci.c')) + +virtio_ss.add_all(when: 'CONFIG_VIRTIO_PCI', if_true: virtio_pci_ss) + +specific_ss.add_all(when: 'CONFIG_VIRTIO', if_true: virtio_ss) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index e83500bee92ed690df14880e2a2a75bd4b796b40..2060a144a2f41cd6e97c05c331b248cc5216f650 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -5,7 +5,8 @@ vhost_commit(bool started, bool changed) "Started: %d Changed: %d" vhost_region_add_section(const char *name, uint64_t gpa, uint64_t size, uint64_t host) "%s: 0x%"PRIx64"+0x%"PRIx64" @ 0x%"PRIx64 vhost_region_add_section_merge(const char *name, uint64_t new_size, uint64_t gpa, uint64_t owr) "%s: size: 0x%"PRIx64 " gpa: 0x%"PRIx64 " owr: 0x%"PRIx64 vhost_region_add_section_aligned(const char *name, uint64_t gpa, uint64_t size, uint64_t host) "%s: 0x%"PRIx64"+0x%"PRIx64" @ 0x%"PRIx64 -vhost_section(const char *name, int r) "%s:%d" +vhost_section(const char *name) "%s" +vhost_reject_section(const char *name, int d) "%s:%d" vhost_iotlb_miss(void *dev, int step) "%p step %d" # vhost-user.c @@ -21,6 +22,37 @@ vhost_user_postcopy_waker(const char *rb, uint64_t rb_offset) "%s + 0x%"PRIx64 vhost_user_postcopy_waker_found(uint64_t client_addr) "0x%"PRIx64 vhost_user_postcopy_waker_nomatch(const char *rb, uint64_t rb_offset) "%s + 0x%"PRIx64 +# vhost-vdpa.c +vhost_vdpa_dma_map(void *vdpa, int fd, uint32_t msg_type, uint64_t iova, uint64_t size, uint64_t uaddr, uint8_t perm, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" uaddr: 0x%"PRIx64" perm: 0x%"PRIx8" type: %"PRIu8 +vhost_vdpa_dma_unmap(void *vdpa, int fd, uint32_t msg_type, uint64_t iova, uint64_t size, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" type: %"PRIu8 +vhost_vdpa_listener_region_add(void *vdpa, uint64_t iova, uint64_t llend, void *vaddr, bool readonly) "vdpa: %p iova 0x%"PRIx64" llend 0x%"PRIx64" vaddr: %p read-only: %d" +vhost_vdpa_listener_region_del(void *vdpa, uint64_t iova, uint64_t llend) "vdpa: %p iova 0x%"PRIx64" llend 0x%"PRIx64 +vhost_vdpa_add_status(void *dev, uint8_t status) "dev: %p status: 0x%"PRIx8 +vhost_vdpa_init(void *dev, void *vdpa) "dev: %p vdpa: %p" +vhost_vdpa_cleanup(void *dev, void *vdpa) "dev: %p vdpa: %p" +vhost_vdpa_memslots_limit(void *dev, int ret) "dev: %p = 0x%x" +vhost_vdpa_set_mem_table(void *dev, uint32_t nregions, uint32_t padding) "dev: %p nregions: %"PRIu32" padding: 0x%"PRIx32 +vhost_vdpa_dump_regions(void *dev, int i, uint64_t guest_phys_addr, uint64_t memory_size, uint64_t userspace_addr, uint64_t flags_padding) "dev: %p %d: guest_phys_addr: 0x%"PRIx64" memory_size: 0x%"PRIx64" userspace_addr: 0x%"PRIx64" flags_padding: 0x%"PRIx64 +vhost_vdpa_set_features(void *dev, uint64_t features) "dev: %p features: 0x%"PRIx64 +vhost_vdpa_get_device_id(void *dev, uint32_t device_id) "dev: %p device_id %"PRIu32 +vhost_vdpa_reset_device(void *dev, uint8_t status) "dev: %p status: 0x%"PRIx8 +vhost_vdpa_get_vq_index(void *dev, int idx, int vq_idx) "dev: %p idx: %d vq idx: %d" +vhost_vdpa_set_vring_ready(void *dev) "dev: %p" +vhost_vdpa_dump_config(void *dev, const char *line) "dev: %p %s" +vhost_vdpa_set_config(void *dev, uint32_t offset, uint32_t size, uint32_t flags) "dev: %p offset: %"PRIu32" size: %"PRIu32" flags: 0x%"PRIx32 +vhost_vdpa_get_config(void *dev, void *config, uint32_t config_len) "dev: %p config: %p config_len: %"PRIu32 +vhost_vdpa_dev_start(void *dev, bool started) "dev: %p started: %d" +vhost_vdpa_set_log_base(void *dev, uint64_t base, unsigned long long size, int refcnt, int fd, void *log) "dev: %p base: 0x%"PRIx64" size: %llu refcnt: %d fd: %d log: %p" +vhost_vdpa_set_vring_addr(void *dev, unsigned int index, unsigned int flags, uint64_t desc_user_addr, uint64_t used_user_addr, uint64_t avail_user_addr, uint64_t log_guest_addr) "dev: %p index: %u flags: 0x%x desc_user_addr: 0x%"PRIx64" used_user_addr: 0x%"PRIx64" avail_user_addr: 0x%"PRIx64" log_guest_addr: 0x%"PRIx64 +vhost_vdpa_set_vring_num(void *dev, unsigned int index, unsigned int num) "dev: %p index: %u num: %u" +vhost_vdpa_set_vring_base(void *dev, unsigned int index, unsigned int num) "dev: %p index: %u num: %u" +vhost_vdpa_get_vring_base(void *dev, unsigned int index, unsigned int num) "dev: %p index: %u num: %u" +vhost_vdpa_set_vring_kick(void *dev, unsigned int index, int fd) "dev: %p index: %u fd: %d" +vhost_vdpa_set_vring_call(void *dev, unsigned int index, int fd) "dev: %p index: %u fd: %d" +vhost_vdpa_get_features(void *dev, uint64_t features) "dev: %p features: 0x%"PRIx64 +vhost_vdpa_set_owner(void *dev) "dev: %p" +vhost_vdpa_vq_get_addr(void *dev, void *vq, uint64_t desc_user_addr, uint64_t avail_user_addr, uint64_t used_user_addr) "dev: %p vq: %p desc_user_addr: 0x%"PRIx64" avail_user_addr: 0x%"PRIx64" used_user_addr: 0x%"PRIx64 + # virtio.c virtqueue_alloc_element(void *elem, size_t sz, unsigned in_num, unsigned out_num) "elem %p size %zd in_num %u out_num %u" virtqueue_fill(void *vq, const void *elem, unsigned int len, unsigned int idx) "vq %p elem %p len %u idx %u" @@ -54,7 +86,7 @@ virtio_mmio_guest_page(uint64_t size, int shift) "guest page size 0x%" PRIx64 " virtio_mmio_queue_write(uint64_t value, int max_size) "mmio_queue write 0x%" PRIx64 " max %d" virtio_mmio_setting_irq(int level) "virtio_mmio setting IRQ %d" -# hw/virtio/virtio-iommu.c +# virtio-iommu.c virtio_iommu_device_reset(void) "reset!" virtio_iommu_get_features(uint64_t features) "device supports features=0x%"PRIx64 virtio_iommu_device_status(uint8_t status) "driver status = %d" @@ -73,3 +105,20 @@ virtio_iommu_get_domain(uint32_t domain_id) "Alloc domain=%d" virtio_iommu_put_domain(uint32_t domain_id) "Free domain=%d" virtio_iommu_translate_out(uint64_t virt_addr, uint64_t phys_addr, uint32_t sid) "0x%"PRIx64" -> 0x%"PRIx64 " for sid=%d" virtio_iommu_report_fault(uint8_t reason, uint32_t flags, uint32_t endpoint, uint64_t addr) "FAULT reason=%d flags=%d endpoint=%d address =0x%"PRIx64 +virtio_iommu_fill_resv_property(uint32_t devid, uint8_t subtype, uint64_t start, uint64_t end) "dev= %d, type=%d start=0x%"PRIx64" end=0x%"PRIx64 +virtio_iommu_notify_map(const char *name, uint64_t virt_start, uint64_t virt_end, uint64_t phys_start, uint32_t flags) "mr=%s virt_start=0x%"PRIx64" virt_end=0x%"PRIx64" phys_start=0x%"PRIx64" flags=%d" +virtio_iommu_notify_unmap(const char *name, uint64_t virt_start, uint64_t virt_end) "mr=%s virt_start=0x%"PRIx64" virt_end=0x%"PRIx64 +virtio_iommu_remap(const char *name, uint64_t virt_start, uint64_t virt_end, uint64_t phys_start) "mr=%s virt_start=0x%"PRIx64" virt_end=0x%"PRIx64" phys_start=0x%"PRIx64 +virtio_iommu_set_page_size_mask(const char *name, uint64_t old, uint64_t new) "mr=%s old_mask=0x%"PRIx64" new_mask=0x%"PRIx64 +virtio_iommu_notify_flag_add(const char *name) "add notifier to mr %s" +virtio_iommu_notify_flag_del(const char *name) "del notifier from mr %s" + +# virtio-mem.c +virtio_mem_send_response(uint16_t type) "type=%" PRIu16 +virtio_mem_plug_request(uint64_t addr, uint16_t nb_blocks) "addr=0x%" PRIx64 " nb_blocks=%" PRIu16 +virtio_mem_unplug_request(uint64_t addr, uint16_t nb_blocks) "addr=0x%" PRIx64 " nb_blocks=%" PRIu16 +virtio_mem_unplugged_all(void) "" +virtio_mem_unplug_all_request(void) "" +virtio_mem_resized_usable_region(uint64_t old_size, uint64_t new_size) "old_size=0x%" PRIx64 "new_size=0x%" PRIx64 +virtio_mem_state_request(uint64_t addr, uint16_t nb_blocks) "addr=0x%" PRIx64 " nb_blocks=%" PRIu16 +virtio_mem_state_response(uint16_t state) "state=%" PRIu16 diff --git a/hw/virtio/trace.h b/hw/virtio/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..5d7097061beabecb7306b6fbf1d7eab8d00050cd --- /dev/null +++ b/hw/virtio/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_virtio.h" diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c index 48905383f8e2730a06bc6b3303f6aa75c7cf3f67..222bbcc62de5717491de9ce0d2cb2907a11b5471 100644 --- a/hw/virtio/vhost-backend.c +++ b/hw/virtio/vhost-backend.c @@ -15,6 +15,7 @@ #include "qemu/main-loop.h" #include "standard-headers/linux/vhost_types.h" +#include "hw/virtio/vhost-vdpa.h" #ifdef CONFIG_VHOST_KERNEL #include #include @@ -155,6 +156,28 @@ static int vhost_kernel_set_features(struct vhost_dev *dev, return vhost_kernel_call(dev, VHOST_SET_FEATURES, &features); } +static int vhost_kernel_set_backend_cap(struct vhost_dev *dev) +{ + uint64_t features; + uint64_t f = 0x1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2; + int r; + + if (vhost_kernel_call(dev, VHOST_GET_BACKEND_FEATURES, &features)) { + return 0; + } + + features &= f; + r = vhost_kernel_call(dev, VHOST_SET_BACKEND_FEATURES, + &features); + if (r) { + return 0; + } + + dev->backend_cap = features; + + return 0; +} + static int vhost_kernel_get_features(struct vhost_dev *dev, uint64_t *features) { @@ -194,34 +217,65 @@ static int vhost_kernel_vsock_set_running(struct vhost_dev *dev, int start) static void vhost_kernel_iotlb_read(void *opaque) { struct vhost_dev *dev = opaque; - struct vhost_msg msg; ssize_t len; - while ((len = read((uintptr_t)dev->opaque, &msg, sizeof msg)) > 0) { - if (len < sizeof msg) { - error_report("Wrong vhost message len: %d", (int)len); - break; + if (dev->backend_cap & + (0x1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2)) { + struct vhost_msg_v2 msg; + + while ((len = read((uintptr_t)dev->opaque, &msg, sizeof msg)) > 0) { + if (len < sizeof msg) { + error_report("Wrong vhost message len: %d", (int)len); + break; + } + if (msg.type != VHOST_IOTLB_MSG_V2) { + error_report("Unknown vhost iotlb message type"); + break; + } + + vhost_backend_handle_iotlb_msg(dev, &msg.iotlb); } - if (msg.type != VHOST_IOTLB_MSG) { - error_report("Unknown vhost iotlb message type"); - break; + } else { + struct vhost_msg msg; + + while ((len = read((uintptr_t)dev->opaque, &msg, sizeof msg)) > 0) { + if (len < sizeof msg) { + error_report("Wrong vhost message len: %d", (int)len); + break; + } + if (msg.type != VHOST_IOTLB_MSG) { + error_report("Unknown vhost iotlb message type"); + break; + } + + vhost_backend_handle_iotlb_msg(dev, &msg.iotlb); } - - vhost_backend_handle_iotlb_msg(dev, &msg.iotlb); } } static int vhost_kernel_send_device_iotlb_msg(struct vhost_dev *dev, struct vhost_iotlb_msg *imsg) { - struct vhost_msg msg; + if (dev->backend_cap & (1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2)) { + struct vhost_msg_v2 msg = {}; + + msg.type = VHOST_IOTLB_MSG_V2; + msg.iotlb = *imsg; + + if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) { + error_report("Fail to update device iotlb"); + return -EFAULT; + } + } else { + struct vhost_msg msg = {}; - msg.type = VHOST_IOTLB_MSG; - msg.iotlb = *imsg; + msg.type = VHOST_IOTLB_MSG; + msg.iotlb = *imsg; - if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) { - error_report("Fail to update device iotlb"); - return -EFAULT; + if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) { + error_report("Fail to update device iotlb"); + return -EFAULT; + } } return 0; @@ -259,6 +313,7 @@ static const VhostOps kernel_ops = { vhost_kernel_set_vring_busyloop_timeout, .vhost_set_features = vhost_kernel_set_features, .vhost_get_features = vhost_kernel_get_features, + .vhost_set_backend_cap = vhost_kernel_set_backend_cap, .vhost_set_owner = vhost_kernel_set_owner, .vhost_reset_device = vhost_kernel_reset_device, .vhost_get_vq_index = vhost_kernel_get_vq_index, @@ -285,6 +340,11 @@ int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type) case VHOST_BACKEND_TYPE_USER: dev->vhost_ops = &user_ops; break; +#endif +#ifdef CONFIG_VHOST_VDPA + case VHOST_BACKEND_TYPE_VDPA: + dev->vhost_ops = &vdpa_ops; + break; #endif default: error_report("Unknown vhost backend type"); diff --git a/hw/virtio/vhost-scsi-pci.c b/hw/virtio/vhost-scsi-pci.c index 5da6bb64491c783b7e7ec85e7e9f3e6c9a36bf33..cb71a294faaf1d79b70dc54826a57256e071d219 100644 --- a/hw/virtio/vhost-scsi-pci.c +++ b/hw/virtio/vhost-scsi-pci.c @@ -22,6 +22,7 @@ #include "qapi/error.h" #include "qemu/module.h" #include "virtio-pci.h" +#include "qom/object.h" typedef struct VHostSCSIPCI VHostSCSIPCI; @@ -29,8 +30,8 @@ typedef struct VHostSCSIPCI VHostSCSIPCI; * vhost-scsi-pci: This extends VirtioPCIProxy. */ #define TYPE_VHOST_SCSI_PCI "vhost-scsi-pci-base" -#define VHOST_SCSI_PCI(obj) \ - OBJECT_CHECK(VHostSCSIPCI, (obj), TYPE_VHOST_SCSI_PCI) +DECLARE_INSTANCE_CHECKER(VHostSCSIPCI, VHOST_SCSI_PCI, + TYPE_VHOST_SCSI_PCI) struct VHostSCSIPCI { VirtIOPCIProxy parent_obj; @@ -47,14 +48,18 @@ static void vhost_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) { VHostSCSIPCI *dev = VHOST_SCSI_PCI(vpci_dev); DeviceState *vdev = DEVICE(&dev->vdev); - VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev); + VirtIOSCSIConf *conf = &dev->vdev.parent_obj.parent_obj.conf; + + if (conf->num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) { + conf->num_queues = + virtio_pci_optimal_num_queues(VIRTIO_SCSI_VQ_NUM_FIXED); + } if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { - vpci_dev->nvectors = vs->conf.num_queues + 3; + vpci_dev->nvectors = conf->num_queues + VIRTIO_SCSI_VQ_NUM_FIXED + 1; } - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); } static void vhost_scsi_pci_class_init(ObjectClass *klass, void *data) diff --git a/hw/virtio/vhost-user-blk-pci.c b/hw/virtio/vhost-user-blk-pci.c index 58d7c31735bb87c05aab37945fb21b012634967c..33b404d8a225cf8053286a6ed0d81d9a9a17d368 100644 --- a/hw/virtio/vhost-user-blk-pci.c +++ b/hw/virtio/vhost-user-blk-pci.c @@ -27,6 +27,7 @@ #include "qemu/error-report.h" #include "qemu/module.h" #include "virtio-pci.h" +#include "qom/object.h" typedef struct VHostUserBlkPCI VHostUserBlkPCI; @@ -34,8 +35,8 @@ typedef struct VHostUserBlkPCI VHostUserBlkPCI; * vhost-user-blk-pci: This extends VirtioPCIProxy. */ #define TYPE_VHOST_USER_BLK_PCI "vhost-user-blk-pci-base" -#define VHOST_USER_BLK_PCI(obj) \ - OBJECT_CHECK(VHostUserBlkPCI, (obj), TYPE_VHOST_USER_BLK_PCI) +DECLARE_INSTANCE_CHECKER(VHostUserBlkPCI, VHOST_USER_BLK_PCI, + TYPE_VHOST_USER_BLK_PCI) struct VHostUserBlkPCI { VirtIOPCIProxy parent_obj; @@ -54,12 +55,15 @@ static void vhost_user_blk_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) VHostUserBlkPCI *dev = VHOST_USER_BLK_PCI(vpci_dev); DeviceState *vdev = DEVICE(&dev->vdev); + if (dev->vdev.num_queues == VHOST_USER_BLK_AUTO_NUM_QUEUES) { + dev->vdev.num_queues = virtio_pci_optimal_num_queues(0); + } + if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { vpci_dev->nvectors = dev->vdev.num_queues + 1; } - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); } static void vhost_user_blk_pci_class_init(ObjectClass *klass, void *data) diff --git a/hw/virtio/vhost-user-fs-pci.c b/hw/virtio/vhost-user-fs-pci.c index ae36f1172dc09a568eea24efe334a6725b2035a0..8bb389bd282a25d4176d8f5612d9feb9a20aaa41 100644 --- a/hw/virtio/vhost-user-fs-pci.c +++ b/hw/virtio/vhost-user-fs-pci.c @@ -15,6 +15,7 @@ #include "hw/qdev-properties.h" #include "hw/virtio/vhost-user-fs.h" #include "virtio-pci.h" +#include "qom/object.h" struct VHostUserFSPCI { VirtIOPCIProxy parent_obj; @@ -25,8 +26,8 @@ typedef struct VHostUserFSPCI VHostUserFSPCI; #define TYPE_VHOST_USER_FS_PCI "vhost-user-fs-pci-base" -#define VHOST_USER_FS_PCI(obj) \ - OBJECT_CHECK(VHostUserFSPCI, (obj), TYPE_VHOST_USER_FS_PCI) +DECLARE_INSTANCE_CHECKER(VHostUserFSPCI, VHOST_USER_FS_PCI, + TYPE_VHOST_USER_FS_PCI) static Property vhost_user_fs_pci_properties[] = { DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, @@ -44,8 +45,7 @@ static void vhost_user_fs_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) vpci_dev->nvectors = dev->vdev.conf.num_request_queues + 2; } - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); } static void vhost_user_fs_pci_class_init(ObjectClass *klass, void *data) diff --git a/hw/virtio/vhost-user-input-pci.c b/hw/virtio/vhost-user-input-pci.c index 0a50015599f3a1ed7fcfb40cb6650539c208aec8..c9d3e9113a5e22c67eae53f71593aad8a4a79c8f 100644 --- a/hw/virtio/vhost-user-input-pci.c +++ b/hw/virtio/vhost-user-input-pci.c @@ -10,13 +10,14 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "virtio-pci.h" +#include "qom/object.h" typedef struct VHostUserInputPCI VHostUserInputPCI; #define TYPE_VHOST_USER_INPUT_PCI "vhost-user-input-pci" -#define VHOST_USER_INPUT_PCI(obj) \ - OBJECT_CHECK(VHostUserInputPCI, (obj), TYPE_VHOST_USER_INPUT_PCI) +DECLARE_INSTANCE_CHECKER(VHostUserInputPCI, VHOST_USER_INPUT_PCI, + TYPE_VHOST_USER_INPUT_PCI) struct VHostUserInputPCI { VirtIOPCIProxy parent_obj; diff --git a/hw/virtio/vhost-user-scsi-pci.c b/hw/virtio/vhost-user-scsi-pci.c index 6f3375fe554aa2eae7b27ad9a2ed3909844181a6..d5343412a11c106eb75780abcc53b6ae8f07984f 100644 --- a/hw/virtio/vhost-user-scsi-pci.c +++ b/hw/virtio/vhost-user-scsi-pci.c @@ -31,12 +31,13 @@ #include "hw/loader.h" #include "sysemu/kvm.h" #include "virtio-pci.h" +#include "qom/object.h" typedef struct VHostUserSCSIPCI VHostUserSCSIPCI; #define TYPE_VHOST_USER_SCSI_PCI "vhost-user-scsi-pci-base" -#define VHOST_USER_SCSI_PCI(obj) \ - OBJECT_CHECK(VHostUserSCSIPCI, (obj), TYPE_VHOST_USER_SCSI_PCI) +DECLARE_INSTANCE_CHECKER(VHostUserSCSIPCI, VHOST_USER_SCSI_PCI, + TYPE_VHOST_USER_SCSI_PCI) struct VHostUserSCSIPCI { VirtIOPCIProxy parent_obj; @@ -53,14 +54,18 @@ static void vhost_user_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) { VHostUserSCSIPCI *dev = VHOST_USER_SCSI_PCI(vpci_dev); DeviceState *vdev = DEVICE(&dev->vdev); - VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev); + VirtIOSCSIConf *conf = &dev->vdev.parent_obj.parent_obj.conf; + + if (conf->num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) { + conf->num_queues = + virtio_pci_optimal_num_queues(VIRTIO_SCSI_VQ_NUM_FIXED); + } if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { - vpci_dev->nvectors = vs->conf.num_queues + 3; + vpci_dev->nvectors = conf->num_queues + VIRTIO_SCSI_VQ_NUM_FIXED + 1; } - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); } static void vhost_user_scsi_pci_class_init(ObjectClass *klass, void *data) diff --git a/hw/virtio/vhost-user-vsock-pci.c b/hw/virtio/vhost-user-vsock-pci.c new file mode 100644 index 0000000000000000000000000000000000000000..72a96199cd21b242c4cd33eaf9e460cf03f65ef7 --- /dev/null +++ b/hw/virtio/vhost-user-vsock-pci.c @@ -0,0 +1,86 @@ +/* + * Vhost-user vsock PCI Bindings + * + * Copyright 2020 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version. See the COPYING file in the + * top-level directory. + */ + +#include "qemu/osdep.h" + +#include "virtio-pci.h" +#include "hw/qdev-properties.h" +#include "hw/virtio/vhost-user-vsock.h" +#include "qom/object.h" + +typedef struct VHostUserVSockPCI VHostUserVSockPCI; + +/* + * vhost-user-vsock-pci: This extends VirtioPCIProxy. + */ +#define TYPE_VHOST_USER_VSOCK_PCI "vhost-user-vsock-pci-base" +DECLARE_INSTANCE_CHECKER(VHostUserVSockPCI, VHOST_USER_VSOCK_PCI, + TYPE_VHOST_USER_VSOCK_PCI) + +struct VHostUserVSockPCI { + VirtIOPCIProxy parent_obj; + VHostUserVSock vdev; +}; + +/* vhost-user-vsock-pci */ + +static Property vhost_user_vsock_pci_properties[] = { + DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3), + DEFINE_PROP_END_OF_LIST(), +}; + +static void vhost_user_vsock_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) +{ + VHostUserVSockPCI *dev = VHOST_USER_VSOCK_PCI(vpci_dev); + DeviceState *vdev = DEVICE(&dev->vdev); + + /* unlike vhost-vsock, we do not need to care about pre-5.1 compat */ + virtio_pci_force_virtio_1(vpci_dev); + + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); +} + +static void vhost_user_vsock_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); + PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); + k->realize = vhost_user_vsock_pci_realize; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + device_class_set_props(dc, vhost_user_vsock_pci_properties); + pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; + pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_VSOCK; + pcidev_k->revision = 0x00; + pcidev_k->class_id = PCI_CLASS_COMMUNICATION_OTHER; +} + +static void vhost_user_vsock_pci_instance_init(Object *obj) +{ + VHostUserVSockPCI *dev = VHOST_USER_VSOCK_PCI(obj); + + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VHOST_USER_VSOCK); +} + +static const VirtioPCIDeviceTypeInfo vhost_user_vsock_pci_info = { + .base_name = TYPE_VHOST_USER_VSOCK_PCI, + .generic_name = "vhost-user-vsock-pci", + .non_transitional_name = "vhost-user-vsock-pci-non-transitional", + .instance_size = sizeof(VHostUserVSockPCI), + .instance_init = vhost_user_vsock_pci_instance_init, + .class_init = vhost_user_vsock_pci_class_init, +}; + +static void virtio_pci_vhost_register(void) +{ + virtio_pci_types_register(&vhost_user_vsock_pci_info); +} + +type_init(virtio_pci_vhost_register) diff --git a/hw/virtio/vhost-user-vsock.c b/hw/virtio/vhost-user-vsock.c new file mode 100644 index 0000000000000000000000000000000000000000..3534a39d627f62e0b72b95f3510330e9e4e04bf4 --- /dev/null +++ b/hw/virtio/vhost-user-vsock.c @@ -0,0 +1,181 @@ +/* + * Vhost-user vsock virtio device + * + * Copyright 2020 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version. See the COPYING file in the + * top-level directory. + */ + +#include "qemu/osdep.h" + +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "hw/qdev-properties.h" +#include "hw/virtio/vhost-user-vsock.h" + +static const int user_feature_bits[] = { + VIRTIO_F_VERSION_1, + VIRTIO_RING_F_INDIRECT_DESC, + VIRTIO_RING_F_EVENT_IDX, + VIRTIO_F_NOTIFY_ON_EMPTY, + VHOST_INVALID_FEATURE_BIT +}; + +static void vuv_get_config(VirtIODevice *vdev, uint8_t *config) +{ + VHostUserVSock *vsock = VHOST_USER_VSOCK(vdev); + + memcpy(config, &vsock->vsockcfg, sizeof(struct virtio_vsock_config)); +} + +static int vuv_handle_config_change(struct vhost_dev *dev) +{ + VHostUserVSock *vsock = VHOST_USER_VSOCK(dev->vdev); + int ret = vhost_dev_get_config(dev, (uint8_t *)&vsock->vsockcfg, + sizeof(struct virtio_vsock_config)); + if (ret < 0) { + error_report("get config space failed"); + return -1; + } + + virtio_notify_config(dev->vdev); + + return 0; +} + +const VhostDevConfigOps vsock_ops = { + .vhost_dev_config_notifier = vuv_handle_config_change, +}; + +static void vuv_set_status(VirtIODevice *vdev, uint8_t status) +{ + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK; + + if (!vdev->vm_running) { + should_start = false; + } + + if (vvc->vhost_dev.started == should_start) { + return; + } + + if (should_start) { + int ret = vhost_vsock_common_start(vdev); + if (ret < 0) { + return; + } + } else { + vhost_vsock_common_stop(vdev); + } +} + +static uint64_t vuv_get_features(VirtIODevice *vdev, + uint64_t features, + Error **errp) +{ + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + + return vhost_get_features(&vvc->vhost_dev, user_feature_bits, features); +} + +static const VMStateDescription vuv_vmstate = { + .name = "vhost-user-vsock", + .unmigratable = 1, +}; + +static void vuv_device_realize(DeviceState *dev, Error **errp) +{ + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(dev); + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VHostUserVSock *vsock = VHOST_USER_VSOCK(dev); + int ret; + + if (!vsock->conf.chardev.chr) { + error_setg(errp, "missing chardev"); + return; + } + + if (!vhost_user_init(&vsock->vhost_user, &vsock->conf.chardev, errp)) { + return; + } + + vhost_vsock_common_realize(vdev, "vhost-user-vsock"); + + vhost_dev_set_config_notifier(&vvc->vhost_dev, &vsock_ops); + + ret = vhost_dev_init(&vvc->vhost_dev, &vsock->vhost_user, + VHOST_BACKEND_TYPE_USER, 0); + if (ret < 0) { + error_setg_errno(errp, -ret, "vhost_dev_init failed"); + goto err_virtio; + } + + ret = vhost_dev_get_config(&vvc->vhost_dev, (uint8_t *)&vsock->vsockcfg, + sizeof(struct virtio_vsock_config)); + if (ret < 0) { + error_setg_errno(errp, -ret, "get config space failed"); + goto err_vhost_dev; + } + + return; + +err_vhost_dev: + vhost_dev_cleanup(&vvc->vhost_dev); +err_virtio: + vhost_vsock_common_unrealize(vdev); + vhost_user_cleanup(&vsock->vhost_user); + return; +} + +static void vuv_device_unrealize(DeviceState *dev) +{ + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(dev); + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VHostUserVSock *vsock = VHOST_USER_VSOCK(dev); + + /* This will stop vhost backend if appropriate. */ + vuv_set_status(vdev, 0); + + vhost_dev_cleanup(&vvc->vhost_dev); + + vhost_vsock_common_unrealize(vdev); + + vhost_user_cleanup(&vsock->vhost_user); + +} + +static Property vuv_properties[] = { + DEFINE_PROP_CHR("chardev", VHostUserVSock, conf.chardev), + DEFINE_PROP_END_OF_LIST(), +}; + +static void vuv_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + + device_class_set_props(dc, vuv_properties); + dc->vmsd = &vuv_vmstate; + vdc->realize = vuv_device_realize; + vdc->unrealize = vuv_device_unrealize; + vdc->get_features = vuv_get_features; + vdc->get_config = vuv_get_config; + vdc->set_status = vuv_set_status; +} + +static const TypeInfo vuv_info = { + .name = TYPE_VHOST_USER_VSOCK, + .parent = TYPE_VHOST_VSOCK_COMMON, + .instance_size = sizeof(VHostUserVSock), + .class_init = vuv_class_init, +}; + +static void vuv_register_types(void) +{ + type_register_static(&vuv_info); +} + +type_init(vuv_register_types) diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index ec21e8fbe8a67479b5da23caede74780f4ba4157..2fdd5daf74bb5c1e81d97f842e704d7cf2e79394 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -35,10 +35,28 @@ #include #endif -#define VHOST_MEMORY_MAX_NREGIONS 8 +#define VHOST_MEMORY_BASELINE_NREGIONS 8 #define VHOST_USER_F_PROTOCOL_FEATURES 30 #define VHOST_USER_SLAVE_MAX_FDS 8 +/* + * Set maximum number of RAM slots supported to + * the maximum number supported by the target + * hardware plaform. + */ +#if defined(TARGET_X86) || defined(TARGET_X86_64) || \ + defined(TARGET_ARM) || defined(TARGET_ARM_64) +#include "hw/acpi/acpi.h" +#define VHOST_USER_MAX_RAM_SLOTS ACPI_MAX_RAM_SLOTS + +#elif defined(TARGET_PPC) || defined(TARGET_PPC_64) +#include "hw/ppc/spapr.h" +#define VHOST_USER_MAX_RAM_SLOTS SPAPR_MAX_RAM_SLOTS + +#else +#define VHOST_USER_MAX_RAM_SLOTS 512 +#endif + /* * Maximum size of virtio device config space */ @@ -59,6 +77,8 @@ enum VhostUserProtocolFeature { VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11, VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD = 12, VHOST_USER_PROTOCOL_F_RESET_DEVICE = 13, + /* Feature 14 reserved for VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS. */ + VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS = 15, VHOST_USER_PROTOCOL_F_MAX }; @@ -100,6 +120,10 @@ typedef enum VhostUserRequest { VHOST_USER_SET_INFLIGHT_FD = 32, VHOST_USER_GPU_SET_SOCKET = 33, VHOST_USER_RESET_DEVICE = 34, + /* Message number 35 reserved for VHOST_USER_VRING_KICK. */ + VHOST_USER_GET_MAX_MEM_SLOTS = 36, + VHOST_USER_ADD_MEM_REG = 37, + VHOST_USER_REM_MEM_REG = 38, VHOST_USER_MAX } VhostUserRequest; @@ -121,9 +145,14 @@ typedef struct VhostUserMemoryRegion { typedef struct VhostUserMemory { uint32_t nregions; uint32_t padding; - VhostUserMemoryRegion regions[VHOST_MEMORY_MAX_NREGIONS]; + VhostUserMemoryRegion regions[VHOST_MEMORY_BASELINE_NREGIONS]; } VhostUserMemory; +typedef struct VhostUserMemRegMsg { + uint64_t padding; + VhostUserMemoryRegion region; +} VhostUserMemRegMsg; + typedef struct VhostUserLog { uint64_t mmap_size; uint64_t mmap_offset; @@ -182,6 +211,7 @@ typedef union { struct vhost_vring_state state; struct vhost_vring_addr addr; VhostUserMemory memory; + VhostUserMemRegMsg mem_reg; VhostUserLog log; struct vhost_iotlb_msg iotlb; VhostUserConfig config; @@ -210,7 +240,7 @@ struct vhost_user { int slave_fd; NotifierWithReturn postcopy_notifier; struct PostCopyFD postcopy_fd; - uint64_t postcopy_client_bases[VHOST_MEMORY_MAX_NREGIONS]; + uint64_t postcopy_client_bases[VHOST_USER_MAX_RAM_SLOTS]; /* Length of the region_rb and region_rb_offset arrays */ size_t region_rb_len; /* RAMBlock associated with a given region */ @@ -222,6 +252,16 @@ struct vhost_user { /* True once we've entered postcopy_listen */ bool postcopy_listen; + + /* Our current regions */ + int num_shadow_regions; + struct vhost_memory_region shadow_regions[VHOST_USER_MAX_RAM_SLOTS]; +}; + +struct scrub_regions { + struct vhost_memory_region *region; + int reg_idx; + int fd_idx; }; static bool ioeventfd_enabled(void) @@ -370,7 +410,7 @@ int vhost_user_gpu_set_socket(struct vhost_dev *dev, int fd) static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base, struct vhost_log *log) { - int fds[VHOST_MEMORY_MAX_NREGIONS]; + int fds[VHOST_USER_MAX_RAM_SLOTS]; size_t fd_num = 0; bool shmfd = virtio_has_feature(dev->protocol_features, VHOST_USER_PROTOCOL_F_LOG_SHMFD); @@ -407,6 +447,29 @@ static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base, return 0; } +static MemoryRegion *vhost_user_get_mr_data(uint64_t addr, ram_addr_t *offset, + int *fd) +{ + MemoryRegion *mr; + + assert((uintptr_t)addr == addr); + mr = memory_region_from_host((void *)(uintptr_t)addr, offset); + *fd = memory_region_get_fd(mr); + + return mr; +} + +static void vhost_user_fill_msg_region(VhostUserMemoryRegion *dst, + struct vhost_memory_region *src, + uint64_t mmap_offset) +{ + assert(src != NULL && dst != NULL); + dst->userspace_addr = src->userspace_addr; + dst->memory_size = src->memory_size; + dst->guest_phys_addr = src->guest_phys_addr; + dst->mmap_offset = mmap_offset; +} + static int vhost_user_fill_set_mem_table_msg(struct vhost_user *u, struct vhost_dev *dev, VhostUserMsg *msg, @@ -417,19 +480,17 @@ static int vhost_user_fill_set_mem_table_msg(struct vhost_user *u, ram_addr_t offset; MemoryRegion *mr; struct vhost_memory_region *reg; + VhostUserMemoryRegion region_buffer; msg->hdr.request = VHOST_USER_SET_MEM_TABLE; for (i = 0; i < dev->mem->nregions; ++i) { reg = dev->mem->regions + i; - assert((uintptr_t)reg->userspace_addr == reg->userspace_addr); - mr = memory_region_from_host((void *)(uintptr_t)reg->userspace_addr, - &offset); - fd = memory_region_get_fd(mr); + mr = vhost_user_get_mr_data(reg->userspace_addr, &offset, &fd); if (fd > 0) { if (track_ramblocks) { - assert(*fd_num < VHOST_MEMORY_MAX_NREGIONS); + assert(*fd_num < VHOST_MEMORY_BASELINE_NREGIONS); trace_vhost_user_set_mem_table_withfd(*fd_num, mr->name, reg->memory_size, reg->guest_phys_addr, @@ -437,17 +498,12 @@ static int vhost_user_fill_set_mem_table_msg(struct vhost_user *u, offset); u->region_rb_offset[i] = offset; u->region_rb[i] = mr->ram_block; - } else if (*fd_num == VHOST_MEMORY_MAX_NREGIONS) { + } else if (*fd_num == VHOST_MEMORY_BASELINE_NREGIONS) { error_report("Failed preparing vhost-user memory table msg"); return -1; } - msg->payload.memory.regions[*fd_num].userspace_addr = - reg->userspace_addr; - msg->payload.memory.regions[*fd_num].memory_size = - reg->memory_size; - msg->payload.memory.regions[*fd_num].guest_phys_addr = - reg->guest_phys_addr; - msg->payload.memory.regions[*fd_num].mmap_offset = offset; + vhost_user_fill_msg_region(®ion_buffer, reg, offset); + msg->payload.memory.regions[*fd_num] = region_buffer; fds[(*fd_num)++] = fd; } else if (track_ramblocks) { u->region_rb_offset[i] = 0; @@ -470,11 +526,333 @@ static int vhost_user_fill_set_mem_table_msg(struct vhost_user *u, return 1; } +static inline bool reg_equal(struct vhost_memory_region *shadow_reg, + struct vhost_memory_region *vdev_reg) +{ + return shadow_reg->guest_phys_addr == vdev_reg->guest_phys_addr && + shadow_reg->userspace_addr == vdev_reg->userspace_addr && + shadow_reg->memory_size == vdev_reg->memory_size; +} + +static void scrub_shadow_regions(struct vhost_dev *dev, + struct scrub_regions *add_reg, + int *nr_add_reg, + struct scrub_regions *rem_reg, + int *nr_rem_reg, uint64_t *shadow_pcb, + bool track_ramblocks) +{ + struct vhost_user *u = dev->opaque; + bool found[VHOST_USER_MAX_RAM_SLOTS] = {}; + struct vhost_memory_region *reg, *shadow_reg; + int i, j, fd, add_idx = 0, rm_idx = 0, fd_num = 0; + ram_addr_t offset; + MemoryRegion *mr; + bool matching; + + /* + * Find memory regions present in our shadow state which are not in + * the device's current memory state. + * + * Mark regions in both the shadow and device state as "found". + */ + for (i = 0; i < u->num_shadow_regions; i++) { + shadow_reg = &u->shadow_regions[i]; + matching = false; + + for (j = 0; j < dev->mem->nregions; j++) { + reg = &dev->mem->regions[j]; + + mr = vhost_user_get_mr_data(reg->userspace_addr, &offset, &fd); + + if (reg_equal(shadow_reg, reg)) { + matching = true; + found[j] = true; + if (track_ramblocks) { + /* + * Reset postcopy client bases, region_rb, and + * region_rb_offset in case regions are removed. + */ + if (fd > 0) { + u->region_rb_offset[j] = offset; + u->region_rb[j] = mr->ram_block; + shadow_pcb[j] = u->postcopy_client_bases[i]; + } else { + u->region_rb_offset[j] = 0; + u->region_rb[j] = NULL; + } + } + break; + } + } + + /* + * If the region was not found in the current device memory state + * create an entry for it in the removed list. + */ + if (!matching) { + rem_reg[rm_idx].region = shadow_reg; + rem_reg[rm_idx++].reg_idx = i; + } + } + + /* + * For regions not marked "found", create entries in the added list. + * + * Note their indexes in the device memory state and the indexes of their + * file descriptors. + */ + for (i = 0; i < dev->mem->nregions; i++) { + reg = &dev->mem->regions[i]; + vhost_user_get_mr_data(reg->userspace_addr, &offset, &fd); + if (fd > 0) { + ++fd_num; + } + + /* + * If the region was in both the shadow and device state we don't + * need to send a VHOST_USER_ADD_MEM_REG message for it. + */ + if (found[i]) { + continue; + } + + add_reg[add_idx].region = reg; + add_reg[add_idx].reg_idx = i; + add_reg[add_idx++].fd_idx = fd_num; + } + *nr_rem_reg = rm_idx; + *nr_add_reg = add_idx; + + return; +} + +static int send_remove_regions(struct vhost_dev *dev, + struct scrub_regions *remove_reg, + int nr_rem_reg, VhostUserMsg *msg, + bool reply_supported) +{ + struct vhost_user *u = dev->opaque; + struct vhost_memory_region *shadow_reg; + int i, fd, shadow_reg_idx, ret; + ram_addr_t offset; + VhostUserMemoryRegion region_buffer; + + /* + * The regions in remove_reg appear in the same order they do in the + * shadow table. Therefore we can minimize memory copies by iterating + * through remove_reg backwards. + */ + for (i = nr_rem_reg - 1; i >= 0; i--) { + shadow_reg = remove_reg[i].region; + shadow_reg_idx = remove_reg[i].reg_idx; + + vhost_user_get_mr_data(shadow_reg->userspace_addr, &offset, &fd); + + if (fd > 0) { + msg->hdr.request = VHOST_USER_REM_MEM_REG; + vhost_user_fill_msg_region(®ion_buffer, shadow_reg, 0); + msg->payload.mem_reg.region = region_buffer; + + if (vhost_user_write(dev, msg, &fd, 1) < 0) { + return -1; + } + + if (reply_supported) { + ret = process_message_reply(dev, msg); + if (ret) { + return ret; + } + } + } + + /* + * At this point we know the backend has unmapped the region. It is now + * safe to remove it from the shadow table. + */ + memmove(&u->shadow_regions[shadow_reg_idx], + &u->shadow_regions[shadow_reg_idx + 1], + sizeof(struct vhost_memory_region) * + (u->num_shadow_regions - shadow_reg_idx - 1)); + u->num_shadow_regions--; + } + + return 0; +} + +static int send_add_regions(struct vhost_dev *dev, + struct scrub_regions *add_reg, int nr_add_reg, + VhostUserMsg *msg, uint64_t *shadow_pcb, + bool reply_supported, bool track_ramblocks) +{ + struct vhost_user *u = dev->opaque; + int i, fd, ret, reg_idx, reg_fd_idx; + struct vhost_memory_region *reg; + MemoryRegion *mr; + ram_addr_t offset; + VhostUserMsg msg_reply; + VhostUserMemoryRegion region_buffer; + + for (i = 0; i < nr_add_reg; i++) { + reg = add_reg[i].region; + reg_idx = add_reg[i].reg_idx; + reg_fd_idx = add_reg[i].fd_idx; + + mr = vhost_user_get_mr_data(reg->userspace_addr, &offset, &fd); + + if (fd > 0) { + if (track_ramblocks) { + trace_vhost_user_set_mem_table_withfd(reg_fd_idx, mr->name, + reg->memory_size, + reg->guest_phys_addr, + reg->userspace_addr, + offset); + u->region_rb_offset[reg_idx] = offset; + u->region_rb[reg_idx] = mr->ram_block; + } + msg->hdr.request = VHOST_USER_ADD_MEM_REG; + vhost_user_fill_msg_region(®ion_buffer, reg, offset); + msg->payload.mem_reg.region = region_buffer; + + if (vhost_user_write(dev, msg, &fd, 1) < 0) { + return -1; + } + + if (track_ramblocks) { + uint64_t reply_gpa; + + if (vhost_user_read(dev, &msg_reply) < 0) { + return -1; + } + + reply_gpa = msg_reply.payload.mem_reg.region.guest_phys_addr; + + if (msg_reply.hdr.request != VHOST_USER_ADD_MEM_REG) { + error_report("%s: Received unexpected msg type." + "Expected %d received %d", __func__, + VHOST_USER_ADD_MEM_REG, + msg_reply.hdr.request); + return -1; + } + + /* + * We're using the same structure, just reusing one of the + * fields, so it should be the same size. + */ + if (msg_reply.hdr.size != msg->hdr.size) { + error_report("%s: Unexpected size for postcopy reply " + "%d vs %d", __func__, msg_reply.hdr.size, + msg->hdr.size); + return -1; + } + + /* Get the postcopy client base from the backend's reply. */ + if (reply_gpa == dev->mem->regions[reg_idx].guest_phys_addr) { + shadow_pcb[reg_idx] = + msg_reply.payload.mem_reg.region.userspace_addr; + trace_vhost_user_set_mem_table_postcopy( + msg_reply.payload.mem_reg.region.userspace_addr, + msg->payload.mem_reg.region.userspace_addr, + reg_fd_idx, reg_idx); + } else { + error_report("%s: invalid postcopy reply for region. " + "Got guest physical address %" PRIX64 ", expected " + "%" PRIX64, __func__, reply_gpa, + dev->mem->regions[reg_idx].guest_phys_addr); + return -1; + } + } else if (reply_supported) { + ret = process_message_reply(dev, msg); + if (ret) { + return ret; + } + } + } else if (track_ramblocks) { + u->region_rb_offset[reg_idx] = 0; + u->region_rb[reg_idx] = NULL; + } + + /* + * At this point, we know the backend has mapped in the new + * region, if the region has a valid file descriptor. + * + * The region should now be added to the shadow table. + */ + u->shadow_regions[u->num_shadow_regions].guest_phys_addr = + reg->guest_phys_addr; + u->shadow_regions[u->num_shadow_regions].userspace_addr = + reg->userspace_addr; + u->shadow_regions[u->num_shadow_regions].memory_size = + reg->memory_size; + u->num_shadow_regions++; + } + + return 0; +} + +static int vhost_user_add_remove_regions(struct vhost_dev *dev, + VhostUserMsg *msg, + bool reply_supported, + bool track_ramblocks) +{ + struct vhost_user *u = dev->opaque; + struct scrub_regions add_reg[VHOST_USER_MAX_RAM_SLOTS]; + struct scrub_regions rem_reg[VHOST_USER_MAX_RAM_SLOTS]; + uint64_t shadow_pcb[VHOST_USER_MAX_RAM_SLOTS] = {}; + int nr_add_reg, nr_rem_reg; + + msg->hdr.size = sizeof(msg->payload.mem_reg); + + /* Find the regions which need to be removed or added. */ + scrub_shadow_regions(dev, add_reg, &nr_add_reg, rem_reg, &nr_rem_reg, + shadow_pcb, track_ramblocks); + + if (nr_rem_reg && send_remove_regions(dev, rem_reg, nr_rem_reg, msg, + reply_supported) < 0) + { + goto err; + } + + if (nr_add_reg && send_add_regions(dev, add_reg, nr_add_reg, msg, + shadow_pcb, reply_supported, track_ramblocks) < 0) + { + goto err; + } + + if (track_ramblocks) { + memcpy(u->postcopy_client_bases, shadow_pcb, + sizeof(uint64_t) * VHOST_USER_MAX_RAM_SLOTS); + /* + * Now we've registered this with the postcopy code, we ack to the + * client, because now we're in the position to be able to deal with + * any faults it generates. + */ + /* TODO: Use this for failure cases as well with a bad value. */ + msg->hdr.size = sizeof(msg->payload.u64); + msg->payload.u64 = 0; /* OK */ + + if (vhost_user_write(dev, msg, NULL, 0) < 0) { + return -1; + } + } + + return 0; + +err: + if (track_ramblocks) { + memcpy(u->postcopy_client_bases, shadow_pcb, + sizeof(uint64_t) * VHOST_USER_MAX_RAM_SLOTS); + } + + return -1; +} + static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, - struct vhost_memory *mem) + struct vhost_memory *mem, + bool reply_supported, + bool config_mem_slots) { struct vhost_user *u = dev->opaque; - int fds[VHOST_MEMORY_MAX_NREGIONS]; + int fds[VHOST_MEMORY_BASELINE_NREGIONS]; size_t fd_num = 0; VhostUserMsg msg_reply; int region_i, msg_i; @@ -494,71 +872,84 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, u->region_rb_len = dev->mem->nregions; } - if (vhost_user_fill_set_mem_table_msg(u, dev, &msg, fds, &fd_num, + if (config_mem_slots) { + if (vhost_user_add_remove_regions(dev, &msg, reply_supported, true) < 0) { - return -1; - } + return -1; + } + } else { + if (vhost_user_fill_set_mem_table_msg(u, dev, &msg, fds, &fd_num, + true) < 0) { + return -1; + } - if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { - return -1; - } + if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { + return -1; + } - if (vhost_user_read(dev, &msg_reply) < 0) { - return -1; - } + if (vhost_user_read(dev, &msg_reply) < 0) { + return -1; + } - if (msg_reply.hdr.request != VHOST_USER_SET_MEM_TABLE) { - error_report("%s: Received unexpected msg type." - "Expected %d received %d", __func__, - VHOST_USER_SET_MEM_TABLE, msg_reply.hdr.request); - return -1; - } - /* We're using the same structure, just reusing one of the - * fields, so it should be the same size. - */ - if (msg_reply.hdr.size != msg.hdr.size) { - error_report("%s: Unexpected size for postcopy reply " - "%d vs %d", __func__, msg_reply.hdr.size, msg.hdr.size); - return -1; - } - - memset(u->postcopy_client_bases, 0, - sizeof(uint64_t) * VHOST_MEMORY_MAX_NREGIONS); - - /* They're in the same order as the regions that were sent - * but some of the regions were skipped (above) if they - * didn't have fd's - */ - for (msg_i = 0, region_i = 0; - region_i < dev->mem->nregions; - region_i++) { - if (msg_i < fd_num && - msg_reply.payload.memory.regions[msg_i].guest_phys_addr == - dev->mem->regions[region_i].guest_phys_addr) { - u->postcopy_client_bases[region_i] = - msg_reply.payload.memory.regions[msg_i].userspace_addr; - trace_vhost_user_set_mem_table_postcopy( - msg_reply.payload.memory.regions[msg_i].userspace_addr, - msg.payload.memory.regions[msg_i].userspace_addr, - msg_i, region_i); - msg_i++; + if (msg_reply.hdr.request != VHOST_USER_SET_MEM_TABLE) { + error_report("%s: Received unexpected msg type." + "Expected %d received %d", __func__, + VHOST_USER_SET_MEM_TABLE, msg_reply.hdr.request); + return -1; + } + + /* + * We're using the same structure, just reusing one of the + * fields, so it should be the same size. + */ + if (msg_reply.hdr.size != msg.hdr.size) { + error_report("%s: Unexpected size for postcopy reply " + "%d vs %d", __func__, msg_reply.hdr.size, + msg.hdr.size); + return -1; + } + + memset(u->postcopy_client_bases, 0, + sizeof(uint64_t) * VHOST_USER_MAX_RAM_SLOTS); + + /* + * They're in the same order as the regions that were sent + * but some of the regions were skipped (above) if they + * didn't have fd's + */ + for (msg_i = 0, region_i = 0; + region_i < dev->mem->nregions; + region_i++) { + if (msg_i < fd_num && + msg_reply.payload.memory.regions[msg_i].guest_phys_addr == + dev->mem->regions[region_i].guest_phys_addr) { + u->postcopy_client_bases[region_i] = + msg_reply.payload.memory.regions[msg_i].userspace_addr; + trace_vhost_user_set_mem_table_postcopy( + msg_reply.payload.memory.regions[msg_i].userspace_addr, + msg.payload.memory.regions[msg_i].userspace_addr, + msg_i, region_i); + msg_i++; + } + } + if (msg_i != fd_num) { + error_report("%s: postcopy reply not fully consumed " + "%d vs %zd", + __func__, msg_i, fd_num); + return -1; + } + + /* + * Now we've registered this with the postcopy code, we ack to the + * client, because now we're in the position to be able to deal + * with any faults it generates. + */ + /* TODO: Use this for failure cases as well with a bad value. */ + msg.hdr.size = sizeof(msg.payload.u64); + msg.payload.u64 = 0; /* OK */ + if (vhost_user_write(dev, &msg, NULL, 0) < 0) { + return -1; } - } - if (msg_i != fd_num) { - error_report("%s: postcopy reply not fully consumed " - "%d vs %zd", - __func__, msg_i, fd_num); - return -1; - } - /* Now we've registered this with the postcopy code, we ack to the client, - * because now we're in the position to be able to deal with any faults - * it generates. - */ - /* TODO: Use this for failure cases as well with a bad value */ - msg.hdr.size = sizeof(msg.payload.u64); - msg.payload.u64 = 0; /* OK */ - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { - return -1; } return 0; @@ -568,17 +959,22 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev, struct vhost_memory *mem) { struct vhost_user *u = dev->opaque; - int fds[VHOST_MEMORY_MAX_NREGIONS]; + int fds[VHOST_MEMORY_BASELINE_NREGIONS]; size_t fd_num = 0; bool do_postcopy = u->postcopy_listen && u->postcopy_fd.handler; bool reply_supported = virtio_has_feature(dev->protocol_features, VHOST_USER_PROTOCOL_F_REPLY_ACK); + bool config_mem_slots = + virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS); if (do_postcopy) { - /* Postcopy has enough differences that it's best done in it's own + /* + * Postcopy has enough differences that it's best done in it's own * version */ - return vhost_user_set_mem_table_postcopy(dev, mem); + return vhost_user_set_mem_table_postcopy(dev, mem, reply_supported, + config_mem_slots); } VhostUserMsg msg = { @@ -589,17 +985,23 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev, msg.hdr.flags |= VHOST_USER_NEED_REPLY_MASK; } - if (vhost_user_fill_set_mem_table_msg(u, dev, &msg, fds, &fd_num, + if (config_mem_slots) { + if (vhost_user_add_remove_regions(dev, &msg, reply_supported, false) < 0) { - return -1; - } - - if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { - return -1; - } + return -1; + } + } else { + if (vhost_user_fill_set_mem_table_msg(u, dev, &msg, fds, &fd_num, + false) < 0) { + return -1; + } + if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { + return -1; + } - if (reply_supported) { - return process_message_reply(dev, &msg); + if (reply_supported) { + return process_message_reply(dev, &msg); + } } return 0; @@ -764,7 +1166,7 @@ static int vhost_set_vring_file(struct vhost_dev *dev, VhostUserRequest request, struct vhost_vring_file *file) { - int fds[VHOST_MEMORY_MAX_NREGIONS]; + int fds[VHOST_USER_MAX_RAM_SLOTS]; size_t fd_num = 0; VhostUserMsg msg = { .hdr.request = request, @@ -880,6 +1282,23 @@ static int vhost_user_set_owner(struct vhost_dev *dev) return 0; } +static int vhost_user_get_max_memslots(struct vhost_dev *dev, + uint64_t *max_memslots) +{ + uint64_t backend_max_memslots; + int err; + + err = vhost_user_get_u64(dev, VHOST_USER_GET_MAX_MEM_SLOTS, + &backend_max_memslots); + if (err < 0) { + return err; + } + + *max_memslots = backend_max_memslots; + + return 0; +} + static int vhost_user_reset_device(struct vhost_dev *dev) { VhostUserMsg msg = { @@ -1377,7 +1796,7 @@ static int vhost_user_postcopy_notifier(NotifierWithReturn *notifier, static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque) { - uint64_t features, protocol_features; + uint64_t features, protocol_features, ram_slots; struct vhost_user *u; int err; @@ -1439,6 +1858,27 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque) "slave-req protocol features."); return -1; } + + /* get max memory regions if backend supports configurable RAM slots */ + if (!virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS)) { + u->user->memory_slots = VHOST_MEMORY_BASELINE_NREGIONS; + } else { + err = vhost_user_get_max_memslots(dev, &ram_slots); + if (err < 0) { + return err; + } + + if (ram_slots < u->user->memory_slots) { + error_report("The backend specified a max ram slots limit " + "of %" PRIu64", when the prior validated limit was %d. " + "This limit should never decrease.", ram_slots, + u->user->memory_slots); + return -1; + } + + u->user->memory_slots = MIN(ram_slots, VHOST_USER_MAX_RAM_SLOTS); + } } if (dev->migration_blocker == NULL && @@ -1504,7 +1944,9 @@ static int vhost_user_get_vq_index(struct vhost_dev *dev, int idx) static int vhost_user_memslots_limit(struct vhost_dev *dev) { - return VHOST_MEMORY_MAX_NREGIONS; + struct vhost_user *u = dev->opaque; + + return u->user->memory_slots; } static bool vhost_user_requires_shm_log(struct vhost_dev *dev) @@ -1545,13 +1987,9 @@ static bool vhost_user_can_merge(struct vhost_dev *dev, { ram_addr_t offset; int mfd, rfd; - MemoryRegion *mr; - - mr = memory_region_from_host((void *)(uintptr_t)start1, &offset); - mfd = memory_region_get_fd(mr); - mr = memory_region_from_host((void *)(uintptr_t)start2, &offset); - rfd = memory_region_get_fd(mr); + (void)vhost_user_get_mr_data(start1, &offset, &mfd); + (void)vhost_user_get_mr_data(start2, &offset, &rfd); return mfd == rfd; } @@ -1893,6 +2331,7 @@ bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp) return false; } user->chr = chr; + user->memory_slots = 0; return true; } diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c new file mode 100644 index 0000000000000000000000000000000000000000..01d2101d0976fdd8e407a32ec9db1f6cf5e3d0e1 --- /dev/null +++ b/hw/virtio/vhost-vdpa.c @@ -0,0 +1,614 @@ +/* + * vhost-vdpa + * + * Copyright(c) 2017-2018 Intel Corporation. + * Copyright(c) 2020 Red Hat, Inc. + * + * 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 +#include +#include +#include +#include "hw/virtio/vhost.h" +#include "hw/virtio/vhost-backend.h" +#include "hw/virtio/virtio-net.h" +#include "hw/virtio/vhost-vdpa.h" +#include "qemu/main-loop.h" +#include "cpu.h" +#include "trace.h" +#include "qemu-common.h" + +static bool vhost_vdpa_listener_skipped_section(MemoryRegionSection *section) +{ + return (!memory_region_is_ram(section->mr) && + !memory_region_is_iommu(section->mr)) || + /* + * Sizing an enabled 64-bit BAR can cause spurious mappings to + * addresses in the upper part of the 64-bit address space. These + * are never accessed by the CPU and beyond the address width of + * some IOMMU hardware. TODO: VDPA should tell us the IOMMU width. + */ + section->offset_within_address_space & (1ULL << 63); +} + +static int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size, + void *vaddr, bool readonly) +{ + struct vhost_msg_v2 msg = {}; + int fd = v->device_fd; + int ret = 0; + + msg.type = v->msg_type; + msg.iotlb.iova = iova; + msg.iotlb.size = size; + msg.iotlb.uaddr = (uint64_t)(uintptr_t)vaddr; + msg.iotlb.perm = readonly ? VHOST_ACCESS_RO : VHOST_ACCESS_RW; + msg.iotlb.type = VHOST_IOTLB_UPDATE; + + trace_vhost_vdpa_dma_map(v, fd, msg.type, msg.iotlb.iova, msg.iotlb.size, + msg.iotlb.uaddr, msg.iotlb.perm, msg.iotlb.type); + + if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) { + error_report("failed to write, fd=%d, errno=%d (%s)", + fd, errno, strerror(errno)); + return -EIO ; + } + + return ret; +} + +static int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, hwaddr iova, + hwaddr size) +{ + struct vhost_msg_v2 msg = {}; + int fd = v->device_fd; + int ret = 0; + + msg.type = v->msg_type; + msg.iotlb.iova = iova; + msg.iotlb.size = size; + msg.iotlb.type = VHOST_IOTLB_INVALIDATE; + + trace_vhost_vdpa_dma_unmap(v, fd, msg.type, msg.iotlb.iova, + msg.iotlb.size, msg.iotlb.type); + + if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) { + error_report("failed to write, fd=%d, errno=%d (%s)", + fd, errno, strerror(errno)); + return -EIO ; + } + + return ret; +} + +static void vhost_vdpa_listener_begin(MemoryListener *listener) +{ + struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener); + struct vhost_dev *dev = v->dev; + struct vhost_msg_v2 msg = {}; + int fd = v->device_fd; + + if (!(dev->backend_cap & (0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH))) { + return; + } + + msg.type = v->msg_type; + msg.iotlb.type = VHOST_IOTLB_BATCH_BEGIN; + + if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) { + error_report("failed to write, fd=%d, errno=%d (%s)", + fd, errno, strerror(errno)); + } +} + +static void vhost_vdpa_listener_commit(MemoryListener *listener) +{ + struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener); + struct vhost_dev *dev = v->dev; + struct vhost_msg_v2 msg = {}; + int fd = v->device_fd; + + if (!(dev->backend_cap & (0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH))) { + return; + } + + msg.type = v->msg_type; + msg.iotlb.type = VHOST_IOTLB_BATCH_END; + + if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) { + error_report("failed to write, fd=%d, errno=%d (%s)", + fd, errno, strerror(errno)); + } +} + +static void vhost_vdpa_listener_region_add(MemoryListener *listener, + MemoryRegionSection *section) +{ + struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener); + hwaddr iova; + Int128 llend, llsize; + void *vaddr; + int ret; + + if (vhost_vdpa_listener_skipped_section(section)) { + return; + } + + if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) != + (section->offset_within_region & ~TARGET_PAGE_MASK))) { + error_report("%s received unaligned region", __func__); + return; + } + + iova = TARGET_PAGE_ALIGN(section->offset_within_address_space); + llend = int128_make64(section->offset_within_address_space); + llend = int128_add(llend, section->size); + llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK)); + + if (int128_ge(int128_make64(iova), llend)) { + return; + } + + memory_region_ref(section->mr); + + /* Here we assume that memory_region_is_ram(section->mr)==true */ + + vaddr = memory_region_get_ram_ptr(section->mr) + + section->offset_within_region + + (iova - section->offset_within_address_space); + + trace_vhost_vdpa_listener_region_add(v, iova, int128_get64(llend), + vaddr, section->readonly); + + llsize = int128_sub(llend, int128_make64(iova)); + + ret = vhost_vdpa_dma_map(v, iova, int128_get64(llsize), + vaddr, section->readonly); + if (ret) { + error_report("vhost vdpa map fail!"); + if (memory_region_is_ram_device(section->mr)) { + /* Allow unexpected mappings not to be fatal for RAM devices */ + error_report("map ram fail!"); + return ; + } + goto fail; + } + + return; + +fail: + if (memory_region_is_ram_device(section->mr)) { + error_report("failed to vdpa_dma_map. pci p2p may not work"); + return; + + } + /* + * On the initfn path, store the first error in the container so we + * can gracefully fail. Runtime, there's not much we can do other + * than throw a hardware error. + */ + error_report("vhost-vdpa: DMA mapping failed, unable to continue"); + return; + +} + +static void vhost_vdpa_listener_region_del(MemoryListener *listener, + MemoryRegionSection *section) +{ + struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener); + hwaddr iova; + Int128 llend, llsize; + int ret; + + if (vhost_vdpa_listener_skipped_section(section)) { + return; + } + + if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) != + (section->offset_within_region & ~TARGET_PAGE_MASK))) { + error_report("%s received unaligned region", __func__); + return; + } + + iova = TARGET_PAGE_ALIGN(section->offset_within_address_space); + llend = int128_make64(section->offset_within_address_space); + llend = int128_add(llend, section->size); + llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK)); + + trace_vhost_vdpa_listener_region_del(v, iova, int128_get64(llend)); + + if (int128_ge(int128_make64(iova), llend)) { + return; + } + + llsize = int128_sub(llend, int128_make64(iova)); + + ret = vhost_vdpa_dma_unmap(v, iova, int128_get64(llsize)); + if (ret) { + error_report("vhost_vdpa dma unmap error!"); + } + + memory_region_unref(section->mr); +} +/* + * IOTLB API is used by vhost-vpda which requires incremental updating + * of the mapping. So we can not use generic vhost memory listener which + * depends on the addnop(). + */ +static const MemoryListener vhost_vdpa_memory_listener = { + .begin = vhost_vdpa_listener_begin, + .commit = vhost_vdpa_listener_commit, + .region_add = vhost_vdpa_listener_region_add, + .region_del = vhost_vdpa_listener_region_del, +}; + +static int vhost_vdpa_call(struct vhost_dev *dev, unsigned long int request, + void *arg) +{ + struct vhost_vdpa *v = dev->opaque; + int fd = v->device_fd; + + assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA); + + return ioctl(fd, request, arg); +} + +static void vhost_vdpa_add_status(struct vhost_dev *dev, uint8_t status) +{ + uint8_t s; + + trace_vhost_vdpa_add_status(dev, status); + if (vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &s)) { + return; + } + + s |= status; + + vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &s); +} + +static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque) +{ + struct vhost_vdpa *v; + uint64_t features; + assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA); + trace_vhost_vdpa_init(dev, opaque); + + v = opaque; + v->dev = dev; + dev->opaque = opaque ; + vhost_vdpa_call(dev, VHOST_GET_FEATURES, &features); + dev->backend_features = features; + v->listener = vhost_vdpa_memory_listener; + v->msg_type = VHOST_IOTLB_MSG_V2; + + vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE | + VIRTIO_CONFIG_S_DRIVER); + + return 0; +} + +static int vhost_vdpa_cleanup(struct vhost_dev *dev) +{ + struct vhost_vdpa *v; + assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA); + v = dev->opaque; + trace_vhost_vdpa_cleanup(dev, v); + memory_listener_unregister(&v->listener); + + dev->opaque = NULL; + return 0; +} + +static int vhost_vdpa_memslots_limit(struct vhost_dev *dev) +{ + trace_vhost_vdpa_memslots_limit(dev, INT_MAX); + return INT_MAX; +} + +static int vhost_vdpa_set_mem_table(struct vhost_dev *dev, + struct vhost_memory *mem) +{ + trace_vhost_vdpa_set_mem_table(dev, mem->nregions, mem->padding); + if (trace_event_get_state_backends(TRACE_VHOST_VDPA_SET_MEM_TABLE) && + trace_event_get_state_backends(TRACE_VHOST_VDPA_DUMP_REGIONS)) { + int i; + for (i = 0; i < mem->nregions; i++) { + trace_vhost_vdpa_dump_regions(dev, i, + mem->regions[i].guest_phys_addr, + mem->regions[i].memory_size, + mem->regions[i].userspace_addr, + mem->regions[i].flags_padding); + } + } + if (mem->padding) { + return -1; + } + + return 0; +} + +static int vhost_vdpa_set_features(struct vhost_dev *dev, + uint64_t features) +{ + int ret; + trace_vhost_vdpa_set_features(dev, features); + ret = vhost_vdpa_call(dev, VHOST_SET_FEATURES, &features); + uint8_t status = 0; + if (ret) { + return ret; + } + vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK); + vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &status); + + return !(status & VIRTIO_CONFIG_S_FEATURES_OK); +} + +static int vhost_vdpa_set_backend_cap(struct vhost_dev *dev) +{ + uint64_t features; + uint64_t f = 0x1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2 | + 0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH; + int r; + + if (vhost_vdpa_call(dev, VHOST_GET_BACKEND_FEATURES, &features)) { + return 0; + } + + features &= f; + r = vhost_vdpa_call(dev, VHOST_SET_BACKEND_FEATURES, &features); + if (r) { + return 0; + } + + dev->backend_cap = features; + + return 0; +} + +int vhost_vdpa_get_device_id(struct vhost_dev *dev, + uint32_t *device_id) +{ + int ret; + ret = vhost_vdpa_call(dev, VHOST_VDPA_GET_DEVICE_ID, device_id); + trace_vhost_vdpa_get_device_id(dev, *device_id); + return ret; +} + +static int vhost_vdpa_reset_device(struct vhost_dev *dev) +{ + int ret; + uint8_t status = 0; + + ret = vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &status); + trace_vhost_vdpa_reset_device(dev, status); + return ret; +} + +static int vhost_vdpa_get_vq_index(struct vhost_dev *dev, int idx) +{ + assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs); + + trace_vhost_vdpa_get_vq_index(dev, idx, idx - dev->vq_index); + return idx - dev->vq_index; +} + +static int vhost_vdpa_set_vring_ready(struct vhost_dev *dev) +{ + int i; + trace_vhost_vdpa_set_vring_ready(dev); + for (i = 0; i < dev->nvqs; ++i) { + struct vhost_vring_state state = { + .index = dev->vq_index + i, + .num = 1, + }; + vhost_vdpa_call(dev, VHOST_VDPA_SET_VRING_ENABLE, &state); + } + return 0; +} + +static void vhost_vdpa_dump_config(struct vhost_dev *dev, const uint8_t *config, + uint32_t config_len) +{ + int b, len; + char line[QEMU_HEXDUMP_LINE_LEN]; + + for (b = 0; b < config_len; b += 16) { + len = config_len - b; + qemu_hexdump_line(line, b, config, len, false); + trace_vhost_vdpa_dump_config(dev, line); + } +} + +static int vhost_vdpa_set_config(struct vhost_dev *dev, const uint8_t *data, + uint32_t offset, uint32_t size, + uint32_t flags) +{ + struct vhost_vdpa_config *config; + int ret; + unsigned long config_size = offsetof(struct vhost_vdpa_config, buf); + + trace_vhost_vdpa_set_config(dev, offset, size, flags); + config = g_malloc(size + config_size); + config->off = offset; + config->len = size; + memcpy(config->buf, data, size); + if (trace_event_get_state_backends(TRACE_VHOST_VDPA_SET_CONFIG) && + trace_event_get_state_backends(TRACE_VHOST_VDPA_DUMP_CONFIG)) { + vhost_vdpa_dump_config(dev, data, size); + } + ret = vhost_vdpa_call(dev, VHOST_VDPA_SET_CONFIG, config); + g_free(config); + return ret; +} + +static int vhost_vdpa_get_config(struct vhost_dev *dev, uint8_t *config, + uint32_t config_len) +{ + struct vhost_vdpa_config *v_config; + unsigned long config_size = offsetof(struct vhost_vdpa_config, buf); + int ret; + + trace_vhost_vdpa_get_config(dev, config, config_len); + v_config = g_malloc(config_len + config_size); + v_config->len = config_len; + v_config->off = 0; + ret = vhost_vdpa_call(dev, VHOST_VDPA_GET_CONFIG, v_config); + memcpy(config, v_config->buf, config_len); + g_free(v_config); + if (trace_event_get_state_backends(TRACE_VHOST_VDPA_GET_CONFIG) && + trace_event_get_state_backends(TRACE_VHOST_VDPA_DUMP_CONFIG)) { + vhost_vdpa_dump_config(dev, config, config_len); + } + return ret; + } + +static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started) +{ + struct vhost_vdpa *v = dev->opaque; + trace_vhost_vdpa_dev_start(dev, started); + if (started) { + uint8_t status = 0; + memory_listener_register(&v->listener, &address_space_memory); + vhost_vdpa_set_vring_ready(dev); + vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); + vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &status); + + return !(status & VIRTIO_CONFIG_S_DRIVER_OK); + } else { + vhost_vdpa_reset_device(dev); + vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE | + VIRTIO_CONFIG_S_DRIVER); + memory_listener_unregister(&v->listener); + + return 0; + } +} + +static int vhost_vdpa_set_log_base(struct vhost_dev *dev, uint64_t base, + struct vhost_log *log) +{ + trace_vhost_vdpa_set_log_base(dev, base, log->size, log->refcnt, log->fd, + log->log); + return vhost_vdpa_call(dev, VHOST_SET_LOG_BASE, &base); +} + +static int vhost_vdpa_set_vring_addr(struct vhost_dev *dev, + struct vhost_vring_addr *addr) +{ + trace_vhost_vdpa_set_vring_addr(dev, addr->index, addr->flags, + addr->desc_user_addr, addr->used_user_addr, + addr->avail_user_addr, + addr->log_guest_addr); + return vhost_vdpa_call(dev, VHOST_SET_VRING_ADDR, addr); +} + +static int vhost_vdpa_set_vring_num(struct vhost_dev *dev, + struct vhost_vring_state *ring) +{ + trace_vhost_vdpa_set_vring_num(dev, ring->index, ring->num); + return vhost_vdpa_call(dev, VHOST_SET_VRING_NUM, ring); +} + +static int vhost_vdpa_set_vring_base(struct vhost_dev *dev, + struct vhost_vring_state *ring) +{ + trace_vhost_vdpa_set_vring_base(dev, ring->index, ring->num); + return vhost_vdpa_call(dev, VHOST_SET_VRING_BASE, ring); +} + +static int vhost_vdpa_get_vring_base(struct vhost_dev *dev, + struct vhost_vring_state *ring) +{ + int ret; + + ret = vhost_vdpa_call(dev, VHOST_GET_VRING_BASE, ring); + trace_vhost_vdpa_get_vring_base(dev, ring->index, ring->num); + return ret; +} + +static int vhost_vdpa_set_vring_kick(struct vhost_dev *dev, + struct vhost_vring_file *file) +{ + trace_vhost_vdpa_set_vring_kick(dev, file->index, file->fd); + return vhost_vdpa_call(dev, VHOST_SET_VRING_KICK, file); +} + +static int vhost_vdpa_set_vring_call(struct vhost_dev *dev, + struct vhost_vring_file *file) +{ + trace_vhost_vdpa_set_vring_call(dev, file->index, file->fd); + return vhost_vdpa_call(dev, VHOST_SET_VRING_CALL, file); +} + +static int vhost_vdpa_get_features(struct vhost_dev *dev, + uint64_t *features) +{ + int ret; + + ret = vhost_vdpa_call(dev, VHOST_GET_FEATURES, features); + trace_vhost_vdpa_get_features(dev, *features); + return ret; +} + +static int vhost_vdpa_set_owner(struct vhost_dev *dev) +{ + trace_vhost_vdpa_set_owner(dev); + return vhost_vdpa_call(dev, VHOST_SET_OWNER, NULL); +} + +static int vhost_vdpa_vq_get_addr(struct vhost_dev *dev, + struct vhost_vring_addr *addr, struct vhost_virtqueue *vq) +{ + assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA); + addr->desc_user_addr = (uint64_t)(unsigned long)vq->desc_phys; + addr->avail_user_addr = (uint64_t)(unsigned long)vq->avail_phys; + addr->used_user_addr = (uint64_t)(unsigned long)vq->used_phys; + trace_vhost_vdpa_vq_get_addr(dev, vq, addr->desc_user_addr, + addr->avail_user_addr, addr->used_user_addr); + return 0; +} + +static bool vhost_vdpa_force_iommu(struct vhost_dev *dev) +{ + return true; +} + +const VhostOps vdpa_ops = { + .backend_type = VHOST_BACKEND_TYPE_VDPA, + .vhost_backend_init = vhost_vdpa_init, + .vhost_backend_cleanup = vhost_vdpa_cleanup, + .vhost_set_log_base = vhost_vdpa_set_log_base, + .vhost_set_vring_addr = vhost_vdpa_set_vring_addr, + .vhost_set_vring_num = vhost_vdpa_set_vring_num, + .vhost_set_vring_base = vhost_vdpa_set_vring_base, + .vhost_get_vring_base = vhost_vdpa_get_vring_base, + .vhost_set_vring_kick = vhost_vdpa_set_vring_kick, + .vhost_set_vring_call = vhost_vdpa_set_vring_call, + .vhost_get_features = vhost_vdpa_get_features, + .vhost_set_backend_cap = vhost_vdpa_set_backend_cap, + .vhost_set_owner = vhost_vdpa_set_owner, + .vhost_set_vring_endian = NULL, + .vhost_backend_memslots_limit = vhost_vdpa_memslots_limit, + .vhost_set_mem_table = vhost_vdpa_set_mem_table, + .vhost_set_features = vhost_vdpa_set_features, + .vhost_reset_device = vhost_vdpa_reset_device, + .vhost_get_vq_index = vhost_vdpa_get_vq_index, + .vhost_get_config = vhost_vdpa_get_config, + .vhost_set_config = vhost_vdpa_set_config, + .vhost_requires_shm_log = NULL, + .vhost_migration_done = NULL, + .vhost_backend_can_merge = NULL, + .vhost_net_set_mtu = NULL, + .vhost_set_iotlb_callback = NULL, + .vhost_send_device_iotlb_msg = NULL, + .vhost_dev_start = vhost_vdpa_dev_start, + .vhost_get_device_id = vhost_vdpa_get_device_id, + .vhost_vq_get_addr = vhost_vdpa_vq_get_addr, + .vhost_force_iommu = vhost_vdpa_force_iommu, +}; diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c new file mode 100644 index 0000000000000000000000000000000000000000..5b2ebf34961cc0e5c496dc264135bb73d8d283a9 --- /dev/null +++ b/hw/virtio/vhost-vsock-common.c @@ -0,0 +1,258 @@ +/* + * Parent class for vhost-vsock devices + * + * Copyright 2015-2020 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version. See the COPYING file in the + * top-level directory. + */ + +#include "qemu/osdep.h" +#include "standard-headers/linux/virtio_vsock.h" +#include "qapi/error.h" +#include "hw/virtio/virtio-access.h" +#include "qemu/error-report.h" +#include "hw/qdev-properties.h" +#include "hw/virtio/vhost-vsock.h" +#include "qemu/iov.h" +#include "monitor/monitor.h" + +int vhost_vsock_common_start(VirtIODevice *vdev) +{ + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); + int ret; + int i; + + if (!k->set_guest_notifiers) { + error_report("binding does not support guest notifiers"); + return -ENOSYS; + } + + ret = vhost_dev_enable_notifiers(&vvc->vhost_dev, vdev); + if (ret < 0) { + error_report("Error enabling host notifiers: %d", -ret); + return ret; + } + + ret = k->set_guest_notifiers(qbus->parent, vvc->vhost_dev.nvqs, true); + if (ret < 0) { + error_report("Error binding guest notifier: %d", -ret); + goto err_host_notifiers; + } + + vvc->vhost_dev.acked_features = vdev->guest_features; + ret = vhost_dev_start(&vvc->vhost_dev, vdev); + if (ret < 0) { + error_report("Error starting vhost: %d", -ret); + goto err_guest_notifiers; + } + + /* + * guest_notifier_mask/pending not used yet, so just unmask + * everything here. virtio-pci will do the right thing by + * enabling/disabling irqfd. + */ + for (i = 0; i < vvc->vhost_dev.nvqs; i++) { + vhost_virtqueue_mask(&vvc->vhost_dev, vdev, i, false); + } + + return 0; + +err_guest_notifiers: + k->set_guest_notifiers(qbus->parent, vvc->vhost_dev.nvqs, false); +err_host_notifiers: + vhost_dev_disable_notifiers(&vvc->vhost_dev, vdev); + return ret; +} + +void vhost_vsock_common_stop(VirtIODevice *vdev) +{ + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); + int ret; + + if (!k->set_guest_notifiers) { + return; + } + + vhost_dev_stop(&vvc->vhost_dev, vdev); + + ret = k->set_guest_notifiers(qbus->parent, vvc->vhost_dev.nvqs, false); + if (ret < 0) { + error_report("vhost guest notifier cleanup failed: %d", ret); + return; + } + + vhost_dev_disable_notifiers(&vvc->vhost_dev, vdev); +} + + +static void vhost_vsock_common_handle_output(VirtIODevice *vdev, VirtQueue *vq) +{ + /* Do nothing */ +} + +static void vhost_vsock_common_guest_notifier_mask(VirtIODevice *vdev, int idx, + bool mask) +{ + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + + vhost_virtqueue_mask(&vvc->vhost_dev, vdev, idx, mask); +} + +static bool vhost_vsock_common_guest_notifier_pending(VirtIODevice *vdev, + int idx) +{ + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + + return vhost_virtqueue_pending(&vvc->vhost_dev, idx); +} + +static void vhost_vsock_common_send_transport_reset(VHostVSockCommon *vvc) +{ + VirtQueueElement *elem; + VirtQueue *vq = vvc->event_vq; + struct virtio_vsock_event event = { + .id = cpu_to_le32(VIRTIO_VSOCK_EVENT_TRANSPORT_RESET), + }; + + elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); + if (!elem) { + error_report("vhost-vsock missed transport reset event"); + return; + } + + if (elem->out_num) { + error_report("invalid vhost-vsock event virtqueue element with " + "out buffers"); + goto out; + } + + if (iov_from_buf(elem->in_sg, elem->in_num, 0, + &event, sizeof(event)) != sizeof(event)) { + error_report("vhost-vsock event virtqueue element is too short"); + goto out; + } + + virtqueue_push(vq, elem, sizeof(event)); + virtio_notify(VIRTIO_DEVICE(vvc), vq); + +out: + g_free(elem); +} + +static void vhost_vsock_common_post_load_timer_cleanup(VHostVSockCommon *vvc) +{ + if (!vvc->post_load_timer) { + return; + } + + timer_del(vvc->post_load_timer); + timer_free(vvc->post_load_timer); + vvc->post_load_timer = NULL; +} + +static void vhost_vsock_common_post_load_timer_cb(void *opaque) +{ + VHostVSockCommon *vvc = opaque; + + vhost_vsock_common_post_load_timer_cleanup(vvc); + vhost_vsock_common_send_transport_reset(vvc); +} + +int vhost_vsock_common_pre_save(void *opaque) +{ + VHostVSockCommon *vvc = opaque; + + /* + * At this point, backend must be stopped, otherwise + * it might keep writing to memory. + */ + assert(!vvc->vhost_dev.started); + + return 0; +} + +int vhost_vsock_common_post_load(void *opaque, int version_id) +{ + VHostVSockCommon *vvc = opaque; + VirtIODevice *vdev = VIRTIO_DEVICE(vvc); + + if (virtio_queue_get_addr(vdev, 2)) { + /* + * Defer transport reset event to a vm clock timer so that virtqueue + * changes happen after migration has completed. + */ + assert(!vvc->post_load_timer); + vvc->post_load_timer = + timer_new_ns(QEMU_CLOCK_VIRTUAL, + vhost_vsock_common_post_load_timer_cb, + vvc); + timer_mod(vvc->post_load_timer, 1); + } + return 0; +} + +void vhost_vsock_common_realize(VirtIODevice *vdev, const char *name) +{ + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + + virtio_init(vdev, name, VIRTIO_ID_VSOCK, + sizeof(struct virtio_vsock_config)); + + /* Receive and transmit queues belong to vhost */ + vvc->recv_vq = virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE, + vhost_vsock_common_handle_output); + vvc->trans_vq = virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE, + vhost_vsock_common_handle_output); + + /* The event queue belongs to QEMU */ + vvc->event_vq = virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE, + vhost_vsock_common_handle_output); + + vvc->vhost_dev.nvqs = ARRAY_SIZE(vvc->vhost_vqs); + vvc->vhost_dev.vqs = vvc->vhost_vqs; + + vvc->post_load_timer = NULL; +} + +void vhost_vsock_common_unrealize(VirtIODevice *vdev) +{ + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + + vhost_vsock_common_post_load_timer_cleanup(vvc); + + virtio_delete_queue(vvc->recv_vq); + virtio_delete_queue(vvc->trans_vq); + virtio_delete_queue(vvc->event_vq); + virtio_cleanup(vdev); +} + +static void vhost_vsock_common_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + vdc->guest_notifier_mask = vhost_vsock_common_guest_notifier_mask; + vdc->guest_notifier_pending = vhost_vsock_common_guest_notifier_pending; +} + +static const TypeInfo vhost_vsock_common_info = { + .name = TYPE_VHOST_VSOCK_COMMON, + .parent = TYPE_VIRTIO_DEVICE, + .instance_size = sizeof(VHostVSockCommon), + .class_init = vhost_vsock_common_class_init, + .abstract = true, +}; + +static void vhost_vsock_common_register_types(void) +{ + type_register_static(&vhost_vsock_common_info); +} + +type_init(vhost_vsock_common_register_types) diff --git a/hw/virtio/vhost-vsock-pci.c b/hw/virtio/vhost-vsock-pci.c index 01effe3d52f0f141ea680f222627d5c8cc381b86..205da8d1f5e23eea72ec512469bd63c591e3112c 100644 --- a/hw/virtio/vhost-vsock-pci.c +++ b/hw/virtio/vhost-vsock-pci.c @@ -17,6 +17,7 @@ #include "hw/qdev-properties.h" #include "hw/virtio/vhost-vsock.h" #include "qemu/module.h" +#include "qom/object.h" typedef struct VHostVSockPCI VHostVSockPCI; @@ -24,8 +25,8 @@ typedef struct VHostVSockPCI VHostVSockPCI; * vhost-vsock-pci: This extends VirtioPCIProxy. */ #define TYPE_VHOST_VSOCK_PCI "vhost-vsock-pci-base" -#define VHOST_VSOCK_PCI(obj) \ - OBJECT_CHECK(VHostVSockPCI, (obj), TYPE_VHOST_VSOCK_PCI) +DECLARE_INSTANCE_CHECKER(VHostVSockPCI, VHOST_VSOCK_PCI, + TYPE_VHOST_VSOCK_PCI) struct VHostVSockPCI { VirtIOPCIProxy parent_obj; @@ -43,9 +44,17 @@ static void vhost_vsock_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) { VHostVSockPCI *dev = VHOST_VSOCK_PCI(vpci_dev); DeviceState *vdev = DEVICE(&dev->vdev); + VirtIODevice *virtio_dev = VIRTIO_DEVICE(vdev); - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + /* + * To avoid migration issues, we force virtio version 1 only when + * legacy check is enabled in the new machine types (>= 5.1). + */ + if (!virtio_legacy_check_disabled(virtio_dev)) { + virtio_pci_force_virtio_1(vpci_dev); + } + + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); } static void vhost_vsock_pci_class_init(ObjectClass *klass, void *data) @@ -73,7 +82,6 @@ static void vhost_vsock_pci_instance_init(Object *obj) static const VirtioPCIDeviceTypeInfo vhost_vsock_pci_info = { .base_name = TYPE_VHOST_VSOCK_PCI, .generic_name = "vhost-vsock-pci", - .transitional_name = "vhost-vsock-pci-transitional", .non_transitional_name = "vhost-vsock-pci-non-transitional", .instance_size = sizeof(VHostVSockPCI), .instance_init = vhost_vsock_pci_instance_init, diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c index 4a228f51688097faac36ce51af99a09826009ca2..8ddfb9abfe1bfda8062275eb5eeceaa09593b864 100644 --- a/hw/virtio/vhost-vsock.c +++ b/hw/virtio/vhost-vsock.c @@ -12,24 +12,15 @@ */ #include "qemu/osdep.h" -#include #include "standard-headers/linux/virtio_vsock.h" #include "qapi/error.h" -#include "hw/virtio/virtio-bus.h" #include "hw/virtio/virtio-access.h" #include "qemu/error-report.h" +#include "qemu/sockets.h" #include "hw/qdev-properties.h" #include "hw/virtio/vhost-vsock.h" -#include "qemu/iov.h" -#include "qemu/module.h" #include "monitor/monitor.h" -enum { - VHOST_VSOCK_SAVEVM_VERSION = 0, - - VHOST_VSOCK_QUEUE_SIZE = 128, -}; - static void vhost_vsock_get_config(VirtIODevice *vdev, uint8_t *config) { VHostVSock *vsock = VHOST_VSOCK(vdev); @@ -39,16 +30,18 @@ static void vhost_vsock_get_config(VirtIODevice *vdev, uint8_t *config) memcpy(config, &vsockcfg, sizeof(vsockcfg)); } -static int vhost_vsock_set_guest_cid(VHostVSock *vsock) +static int vhost_vsock_set_guest_cid(VirtIODevice *vdev) { - const VhostOps *vhost_ops = vsock->vhost_dev.vhost_ops; + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + VHostVSock *vsock = VHOST_VSOCK(vdev); + const VhostOps *vhost_ops = vvc->vhost_dev.vhost_ops; int ret; if (!vhost_ops->vhost_vsock_set_guest_cid) { return -ENOSYS; } - ret = vhost_ops->vhost_vsock_set_guest_cid(&vsock->vhost_dev, + ret = vhost_ops->vhost_vsock_set_guest_cid(&vvc->vhost_dev, vsock->conf.guest_cid); if (ret < 0) { return -errno; @@ -56,123 +49,58 @@ static int vhost_vsock_set_guest_cid(VHostVSock *vsock) return 0; } -static int vhost_vsock_set_running(VHostVSock *vsock, int start) +static int vhost_vsock_set_running(VirtIODevice *vdev, int start) { - const VhostOps *vhost_ops = vsock->vhost_dev.vhost_ops; + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + const VhostOps *vhost_ops = vvc->vhost_dev.vhost_ops; int ret; if (!vhost_ops->vhost_vsock_set_running) { return -ENOSYS; } - ret = vhost_ops->vhost_vsock_set_running(&vsock->vhost_dev, start); + ret = vhost_ops->vhost_vsock_set_running(&vvc->vhost_dev, start); if (ret < 0) { return -errno; } return 0; } -static void vhost_vsock_start(VirtIODevice *vdev) -{ - VHostVSock *vsock = VHOST_VSOCK(vdev); - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); - int ret; - int i; - - if (!k->set_guest_notifiers) { - error_report("binding does not support guest notifiers"); - return; - } - - ret = vhost_dev_enable_notifiers(&vsock->vhost_dev, vdev); - if (ret < 0) { - error_report("Error enabling host notifiers: %d", -ret); - return; - } - - ret = k->set_guest_notifiers(qbus->parent, vsock->vhost_dev.nvqs, true); - if (ret < 0) { - error_report("Error binding guest notifier: %d", -ret); - goto err_host_notifiers; - } - - vsock->vhost_dev.acked_features = vdev->guest_features; - ret = vhost_dev_start(&vsock->vhost_dev, vdev); - if (ret < 0) { - error_report("Error starting vhost: %d", -ret); - goto err_guest_notifiers; - } - - ret = vhost_vsock_set_running(vsock, 1); - if (ret < 0) { - error_report("Error starting vhost vsock: %d", -ret); - goto err_dev_start; - } - - /* guest_notifier_mask/pending not used yet, so just unmask - * everything here. virtio-pci will do the right thing by - * enabling/disabling irqfd. - */ - for (i = 0; i < vsock->vhost_dev.nvqs; i++) { - vhost_virtqueue_mask(&vsock->vhost_dev, vdev, i, false); - } - - return; - -err_dev_start: - vhost_dev_stop(&vsock->vhost_dev, vdev); -err_guest_notifiers: - k->set_guest_notifiers(qbus->parent, vsock->vhost_dev.nvqs, false); -err_host_notifiers: - vhost_dev_disable_notifiers(&vsock->vhost_dev, vdev); -} - -static void vhost_vsock_stop(VirtIODevice *vdev) -{ - VHostVSock *vsock = VHOST_VSOCK(vdev); - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); - int ret; - - if (!k->set_guest_notifiers) { - return; - } - - ret = vhost_vsock_set_running(vsock, 0); - if (ret < 0) { - error_report("vhost vsock set running failed: %d", ret); - return; - } - - vhost_dev_stop(&vsock->vhost_dev, vdev); - - ret = k->set_guest_notifiers(qbus->parent, vsock->vhost_dev.nvqs, false); - if (ret < 0) { - error_report("vhost guest notifier cleanup failed: %d", ret); - return; - } - - vhost_dev_disable_notifiers(&vsock->vhost_dev, vdev); -} static void vhost_vsock_set_status(VirtIODevice *vdev, uint8_t status) { - VHostVSock *vsock = VHOST_VSOCK(vdev); + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK; + int ret; if (!vdev->vm_running) { should_start = false; } - if (vsock->vhost_dev.started == should_start) { + if (vvc->vhost_dev.started == should_start) { return; } if (should_start) { - vhost_vsock_start(vdev); + ret = vhost_vsock_common_start(vdev); + if (ret < 0) { + return; + } + + ret = vhost_vsock_set_running(vdev, 1); + if (ret < 0) { + vhost_vsock_common_stop(vdev); + error_report("Error starting vhost vsock: %d", -ret); + return; + } } else { - vhost_vsock_stop(vdev); + ret = vhost_vsock_set_running(vdev, 0); + if (ret < 0) { + error_report("vhost vsock set running failed: %d", ret); + return; + } + + vhost_vsock_common_stop(vdev); } } @@ -184,108 +112,6 @@ static uint64_t vhost_vsock_get_features(VirtIODevice *vdev, return requested_features; } -static void vhost_vsock_handle_output(VirtIODevice *vdev, VirtQueue *vq) -{ - /* Do nothing */ -} - -static void vhost_vsock_guest_notifier_mask(VirtIODevice *vdev, int idx, - bool mask) -{ - VHostVSock *vsock = VHOST_VSOCK(vdev); - - vhost_virtqueue_mask(&vsock->vhost_dev, vdev, idx, mask); -} - -static bool vhost_vsock_guest_notifier_pending(VirtIODevice *vdev, int idx) -{ - VHostVSock *vsock = VHOST_VSOCK(vdev); - - return vhost_virtqueue_pending(&vsock->vhost_dev, idx); -} - -static void vhost_vsock_send_transport_reset(VHostVSock *vsock) -{ - VirtQueueElement *elem; - VirtQueue *vq = vsock->event_vq; - struct virtio_vsock_event event = { - .id = cpu_to_le32(VIRTIO_VSOCK_EVENT_TRANSPORT_RESET), - }; - - elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); - if (!elem) { - error_report("vhost-vsock missed transport reset event"); - return; - } - - if (elem->out_num) { - error_report("invalid vhost-vsock event virtqueue element with " - "out buffers"); - goto out; - } - - if (iov_from_buf(elem->in_sg, elem->in_num, 0, - &event, sizeof(event)) != sizeof(event)) { - error_report("vhost-vsock event virtqueue element is too short"); - goto out; - } - - virtqueue_push(vq, elem, sizeof(event)); - virtio_notify(VIRTIO_DEVICE(vsock), vq); - -out: - g_free(elem); -} - -static void vhost_vsock_post_load_timer_cleanup(VHostVSock *vsock) -{ - if (!vsock->post_load_timer) { - return; - } - - timer_del(vsock->post_load_timer); - timer_free(vsock->post_load_timer); - vsock->post_load_timer = NULL; -} - -static void vhost_vsock_post_load_timer_cb(void *opaque) -{ - VHostVSock *vsock = opaque; - - vhost_vsock_post_load_timer_cleanup(vsock); - vhost_vsock_send_transport_reset(vsock); -} - -static int vhost_vsock_pre_save(void *opaque) -{ - VHostVSock *vsock = opaque; - - /* At this point, backend must be stopped, otherwise - * it might keep writing to memory. */ - assert(!vsock->vhost_dev.started); - - return 0; -} - -static int vhost_vsock_post_load(void *opaque, int version_id) -{ - VHostVSock *vsock = opaque; - VirtIODevice *vdev = VIRTIO_DEVICE(vsock); - - if (virtio_queue_get_addr(vdev, 2)) { - /* Defer transport reset event to a vm clock timer so that virtqueue - * changes happen after migration has completed. - */ - assert(!vsock->post_load_timer); - vsock->post_load_timer = - timer_new_ns(QEMU_CLOCK_VIRTUAL, - vhost_vsock_post_load_timer_cb, - vsock); - timer_mod(vsock->post_load_timer, 1); - } - return 0; -} - static const VMStateDescription vmstate_virtio_vhost_vsock = { .name = "virtio-vhost_vsock", .minimum_version_id = VHOST_VSOCK_SAVEVM_VERSION, @@ -294,12 +120,13 @@ static const VMStateDescription vmstate_virtio_vhost_vsock = { VMSTATE_VIRTIO_DEVICE, VMSTATE_END_OF_LIST() }, - .pre_save = vhost_vsock_pre_save, - .post_load = vhost_vsock_post_load, + .pre_save = vhost_vsock_common_pre_save, + .post_load = vhost_vsock_common_post_load, }; static void vhost_vsock_device_realize(DeviceState *dev, Error **errp) { + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(dev); VirtIODevice *vdev = VIRTIO_DEVICE(dev); VHostVSock *vsock = VHOST_VSOCK(dev); int vhostfd; @@ -317,11 +144,18 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp) } if (vsock->conf.vhostfd) { - vhostfd = monitor_fd_param(cur_mon, vsock->conf.vhostfd, errp); + vhostfd = monitor_fd_param(monitor_cur(), vsock->conf.vhostfd, errp); if (vhostfd == -1) { error_prepend(errp, "vhost-vsock: unable to parse vhostfd: "); return; } + + ret = qemu_try_set_nonblock(vhostfd); + if (ret < 0) { + error_setg_errno(errp, -ret, + "vhost-vsock: unable to set non-blocking mode"); + return; + } } else { vhostfd = open("/dev/vhost-vsock", O_RDWR); if (vhostfd < 0) { @@ -329,48 +163,33 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp) "vhost-vsock: failed to open vhost device"); return; } - } - - virtio_init(vdev, "vhost-vsock", VIRTIO_ID_VSOCK, - sizeof(struct virtio_vsock_config)); - /* Receive and transmit queues belong to vhost */ - vsock->recv_vq = virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE, - vhost_vsock_handle_output); - vsock->trans_vq = virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE, - vhost_vsock_handle_output); + qemu_set_nonblock(vhostfd); + } - /* The event queue belongs to QEMU */ - vsock->event_vq = virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE, - vhost_vsock_handle_output); + vhost_vsock_common_realize(vdev, "vhost-vsock"); - vsock->vhost_dev.nvqs = ARRAY_SIZE(vsock->vhost_vqs); - vsock->vhost_dev.vqs = vsock->vhost_vqs; - ret = vhost_dev_init(&vsock->vhost_dev, (void *)(uintptr_t)vhostfd, + ret = vhost_dev_init(&vvc->vhost_dev, (void *)(uintptr_t)vhostfd, VHOST_BACKEND_TYPE_KERNEL, 0); if (ret < 0) { error_setg_errno(errp, -ret, "vhost-vsock: vhost_dev_init failed"); goto err_virtio; } - ret = vhost_vsock_set_guest_cid(vsock); + ret = vhost_vsock_set_guest_cid(vdev); if (ret < 0) { error_setg_errno(errp, -ret, "vhost-vsock: unable to set guest cid"); goto err_vhost_dev; } - vsock->post_load_timer = NULL; return; err_vhost_dev: - vhost_dev_cleanup(&vsock->vhost_dev); + vhost_dev_cleanup(&vvc->vhost_dev); /* vhost_dev_cleanup() closes the vhostfd passed to vhost_dev_init() */ vhostfd = -1; err_virtio: - virtio_delete_queue(vsock->recv_vq); - virtio_delete_queue(vsock->trans_vq); - virtio_delete_queue(vsock->event_vq); - virtio_cleanup(vdev); + vhost_vsock_common_unrealize(vdev); if (vhostfd >= 0) { close(vhostfd); } @@ -379,19 +198,14 @@ err_virtio: static void vhost_vsock_device_unrealize(DeviceState *dev) { + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(dev); VirtIODevice *vdev = VIRTIO_DEVICE(dev); - VHostVSock *vsock = VHOST_VSOCK(dev); - - vhost_vsock_post_load_timer_cleanup(vsock); /* This will stop vhost backend if appropriate. */ vhost_vsock_set_status(vdev, 0); - vhost_dev_cleanup(&vsock->vhost_dev); - virtio_delete_queue(vsock->recv_vq); - virtio_delete_queue(vsock->trans_vq); - virtio_delete_queue(vsock->event_vq); - virtio_cleanup(vdev); + vhost_dev_cleanup(&vvc->vhost_dev); + vhost_vsock_common_unrealize(vdev); } static Property vhost_vsock_properties[] = { @@ -407,19 +221,16 @@ static void vhost_vsock_class_init(ObjectClass *klass, void *data) device_class_set_props(dc, vhost_vsock_properties); dc->vmsd = &vmstate_virtio_vhost_vsock; - set_bit(DEVICE_CATEGORY_MISC, dc->categories); vdc->realize = vhost_vsock_device_realize; vdc->unrealize = vhost_vsock_device_unrealize; vdc->get_features = vhost_vsock_get_features; vdc->get_config = vhost_vsock_get_config; vdc->set_status = vhost_vsock_set_status; - vdc->guest_notifier_mask = vhost_vsock_guest_notifier_mask; - vdc->guest_notifier_pending = vhost_vsock_guest_notifier_pending; } static const TypeInfo vhost_vsock_info = { .name = TYPE_VHOST_VSOCK, - .parent = TYPE_VIRTIO_DEVICE, + .parent = TYPE_VHOST_VSOCK_COMMON, .instance_size = sizeof(VHostVSock), .class_init = vhost_vsock_class_init, }; diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index aff98a0ede56d5ce7d1d20e8c94ea7d06da4e077..614ccc2bcb6cfc98222c36a333884f1066f3488a 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -27,6 +27,7 @@ #include "migration/blocker.h" #include "migration/qemu-file-types.h" #include "sysemu/dma.h" +#include "sysemu/tcg.h" #include "trace.h" /* enabled until disconnected backend stabilizes */ @@ -89,7 +90,7 @@ static void vhost_dev_sync_region(struct vhost_dev *dev, } /* Data must be read atomically. We don't really need barrier semantics * but it's easier to use atomic_* than roll our own. */ - log = atomic_xchg(from, 0); + log = qatomic_xchg(from, 0); while (log) { int bit = ctzl(log); hwaddr page_addr; @@ -171,16 +172,6 @@ static uint64_t vhost_get_log_size(struct vhost_dev *dev) reg->memory_size); log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1); } - for (i = 0; i < dev->nvqs; ++i) { - struct vhost_virtqueue *vq = dev->vqs + i; - - if (!vq->used_phys && !vq->used_size) { - continue; - } - - uint64_t last = vq->used_phys + vq->used_size - 1; - log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1); - } return log_size; } @@ -403,26 +394,50 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev, return r; } +/* + * vhost_section: identify sections needed for vhost access + * + * We only care about RAM sections here (where virtqueue and guest + * internals accessed by virtio might live). If we find one we still + * allow the backend to potentially filter it out of our list. + */ static bool vhost_section(struct vhost_dev *dev, MemoryRegionSection *section) { - bool result; - bool log_dirty = memory_region_get_dirty_log_mask(section->mr) & - ~(1 << DIRTY_MEMORY_MIGRATION); - result = memory_region_is_ram(section->mr) && - !memory_region_is_rom(section->mr); + MemoryRegion *mr = section->mr; + + if (memory_region_is_ram(mr) && !memory_region_is_rom(mr)) { + uint8_t dirty_mask = memory_region_get_dirty_log_mask(mr); + uint8_t handled_dirty; + + /* + * Kernel based vhost doesn't handle any block which is doing + * dirty-tracking other than migration for which it has + * specific logging support. However for TCG the kernel never + * gets involved anyway so we can also ignore it's + * self-modiying code detection flags. However a vhost-user + * client could still confuse a TCG guest if it re-writes + * executable memory that has already been translated. + */ + handled_dirty = (1 << DIRTY_MEMORY_MIGRATION) | + (1 << DIRTY_MEMORY_CODE); - /* Vhost doesn't handle any block which is doing dirty-tracking other - * than migration; this typically fires on VGA areas. - */ - result &= !log_dirty; + if (dirty_mask & ~handled_dirty) { + trace_vhost_reject_section(mr->name, 1); + return false; + } - if (result && dev->vhost_ops->vhost_backend_mem_section_filter) { - result &= - dev->vhost_ops->vhost_backend_mem_section_filter(dev, section); - } + if (dev->vhost_ops->vhost_backend_mem_section_filter && + !dev->vhost_ops->vhost_backend_mem_section_filter(dev, section)) { + trace_vhost_reject_section(mr->name, 2); + return false; + } - trace_vhost_section(section->mr->name, result); - return result; + trace_vhost_section(mr->name); + return true; + } else { + trace_vhost_reject_section(mr->name, 3); + return false; + } } static void vhost_begin(MemoryListener *listener) @@ -687,9 +702,8 @@ static void vhost_iommu_region_add(MemoryListener *listener, iommu_listener); struct vhost_iommu *iommu; Int128 end; - int iommu_idx, ret; + int iommu_idx; IOMMUMemoryRegion *iommu_mr; - Error *err = NULL; if (!memory_region_is_iommu(section->mr)) { return; @@ -712,11 +726,8 @@ static void vhost_iommu_region_add(MemoryListener *listener, iommu->iommu_offset = section->offset_within_address_space - section->offset_within_region; iommu->hdev = dev; - ret = memory_region_register_iommu_notifier(section->mr, &iommu->n, &err); - if (ret) { - error_report_err(err); - exit(1); - } + memory_region_register_iommu_notifier(section->mr, &iommu->n, + &error_fatal); QLIST_INSERT_HEAD(&dev->iommu_list, iommu, iommu_next); /* TODO: can replay help performance here? */ } @@ -748,15 +759,25 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev, struct vhost_virtqueue *vq, unsigned idx, bool enable_log) { - struct vhost_vring_addr addr = { - .index = idx, - .desc_user_addr = (uint64_t)(unsigned long)vq->desc, - .avail_user_addr = (uint64_t)(unsigned long)vq->avail, - .used_user_addr = (uint64_t)(unsigned long)vq->used, - .log_guest_addr = vq->used_phys, - .flags = enable_log ? (1 << VHOST_VRING_F_LOG) : 0, - }; - int r = dev->vhost_ops->vhost_set_vring_addr(dev, &addr); + struct vhost_vring_addr addr; + int r; + memset(&addr, 0, sizeof(struct vhost_vring_addr)); + + if (dev->vhost_ops->vhost_vq_get_addr) { + r = dev->vhost_ops->vhost_vq_get_addr(dev, &addr, vq); + if (r < 0) { + VHOST_OPS_DEBUG("vhost_vq_get_addr failed"); + return -errno; + } + } else { + addr.desc_user_addr = (uint64_t)(unsigned long)vq->desc; + addr.avail_user_addr = (uint64_t)(unsigned long)vq->avail; + addr.used_user_addr = (uint64_t)(unsigned long)vq->used; + } + addr.index = idx; + addr.log_guest_addr = vq->used_phys; + addr.flags = enable_log ? (1 << VHOST_VRING_F_LOG) : 0; + r = dev->vhost_ops->vhost_set_vring_addr(dev, &addr); if (r < 0) { VHOST_OPS_DEBUG("vhost_set_vring_addr failed"); return -errno; @@ -775,22 +796,49 @@ static int vhost_dev_set_features(struct vhost_dev *dev, if (!vhost_dev_has_iommu(dev)) { features &= ~(0x1ULL << VIRTIO_F_IOMMU_PLATFORM); } + if (dev->vhost_ops->vhost_force_iommu) { + if (dev->vhost_ops->vhost_force_iommu(dev) == true) { + features |= 0x1ULL << VIRTIO_F_IOMMU_PLATFORM; + } + } r = dev->vhost_ops->vhost_set_features(dev, features); if (r < 0) { VHOST_OPS_DEBUG("vhost_set_features failed"); + goto out; } + if (dev->vhost_ops->vhost_set_backend_cap) { + r = dev->vhost_ops->vhost_set_backend_cap(dev); + if (r < 0) { + VHOST_OPS_DEBUG("vhost_set_backend_cap failed"); + goto out; + } + } + +out: return r < 0 ? -errno : 0; } static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log) { int r, i, idx; + hwaddr addr; + r = vhost_dev_set_features(dev, enable_log); if (r < 0) { goto err_features; } for (i = 0; i < dev->nvqs; ++i) { idx = dev->vhost_ops->vhost_get_vq_index(dev, dev->vq_index + i); + addr = virtio_queue_get_desc_addr(dev->vdev, idx); + if (!addr) { + /* + * The queue might not be ready for start. If this + * is the case there is no reason to continue the process. + * The similar logic is used by the vhost_virtqueue_start() + * routine. + */ + continue; + } r = vhost_virtqueue_set_addr(dev, dev->vqs + i, idx, enable_log); if (r < 0) { @@ -809,33 +857,54 @@ err_features: return r; } -static int vhost_migration_log(MemoryListener *listener, int enable) +static int vhost_migration_log(MemoryListener *listener, bool enable) { struct vhost_dev *dev = container_of(listener, struct vhost_dev, memory_listener); int r; - if (!!enable == dev->log_enabled) { + if (enable == dev->log_enabled) { return 0; } if (!dev->started) { dev->log_enabled = enable; return 0; } + + r = 0; if (!enable) { r = vhost_dev_set_log(dev, false); if (r < 0) { - return r; + goto check_dev_state; } vhost_log_put(dev, false); } else { vhost_dev_log_resize(dev, vhost_get_log_size(dev)); r = vhost_dev_set_log(dev, true); if (r < 0) { - return r; + goto check_dev_state; } } + +check_dev_state: dev->log_enabled = enable; - return 0; + /* + * vhost-user-* devices could change their state during log + * initialization due to disconnect. So check dev state after + * vhost communication. + */ + if (!dev->started) { + /* + * Since device is in the stopped state, it is okay for + * migration. Return success. + */ + r = 0; + } + if (r) { + /* An error is occured. */ + dev->log_enabled = false; + } + + return r; } static void vhost_log_global_start(MemoryListener *listener) @@ -1576,6 +1645,26 @@ int vhost_dev_load_inflight(struct vhost_inflight *inflight, QEMUFile *f) return 0; } +int vhost_dev_prepare_inflight(struct vhost_dev *hdev, VirtIODevice *vdev) +{ + int r; + + if (hdev->vhost_ops->vhost_get_inflight_fd == NULL || + hdev->vhost_ops->vhost_set_inflight_fd == NULL) { + return 0; + } + + hdev->vdev = vdev; + + r = vhost_dev_set_features(hdev, hdev->log_enabled); + if (r < 0) { + VHOST_OPS_DEBUG("vhost_dev_prepare_inflight failed"); + return r; + } + + return 0; +} + int vhost_dev_set_inflight(struct vhost_dev *dev, struct vhost_inflight *inflight) { @@ -1660,9 +1749,15 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) goto fail_log; } } - - if (vhost_dev_has_iommu(hdev)) { - hdev->vhost_ops->vhost_set_iotlb_callback(hdev, true); + if (hdev->vhost_ops->vhost_dev_start) { + r = hdev->vhost_ops->vhost_dev_start(hdev, true); + if (r) { + goto fail_log; + } + } + if (vhost_dev_has_iommu(hdev) && + hdev->vhost_ops->vhost_set_iotlb_callback) { + hdev->vhost_ops->vhost_set_iotlb_callback(hdev, true); /* Update used ring information for IOTLB to work correctly, * vhost-kernel code requires for this.*/ @@ -1697,6 +1792,9 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) /* should only be called after backend is connected */ assert(hdev->vhost_ops); + if (hdev->vhost_ops->vhost_dev_start) { + hdev->vhost_ops->vhost_dev_start(hdev, false); + } for (i = 0; i < hdev->nvqs; ++i) { vhost_virtqueue_stop(hdev, vdev, @@ -1705,7 +1803,9 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) } if (vhost_dev_has_iommu(hdev)) { - hdev->vhost_ops->vhost_set_iotlb_callback(hdev, false); + if (hdev->vhost_ops->vhost_set_iotlb_callback) { + hdev->vhost_ops->vhost_set_iotlb_callback(hdev, false); + } memory_listener_unregister(&hdev->iommu_listener); } vhost_log_put(hdev, true); diff --git a/hw/virtio/virtio-9p-pci.c b/hw/virtio/virtio-9p-pci.c index 6507ce340b61bd8b405cd98d042297820ad679e8..e07adcd9ea78c6966af732d88f79239ec5f8e326 100644 --- a/hw/virtio/virtio-9p-pci.c +++ b/hw/virtio/virtio-9p-pci.c @@ -19,27 +19,28 @@ #include "hw/9pfs/virtio-9p.h" #include "hw/qdev-properties.h" #include "qemu/module.h" +#include "qom/object.h" /* * virtio-9p-pci: This extends VirtioPCIProxy. */ #define TYPE_VIRTIO_9P_PCI "virtio-9p-pci-base" -#define VIRTIO_9P_PCI(obj) \ - OBJECT_CHECK(V9fsPCIState, (obj), TYPE_VIRTIO_9P_PCI) +typedef struct V9fsPCIState V9fsPCIState; +DECLARE_INSTANCE_CHECKER(V9fsPCIState, VIRTIO_9P_PCI, + TYPE_VIRTIO_9P_PCI) -typedef struct V9fsPCIState { +struct V9fsPCIState { VirtIOPCIProxy parent_obj; V9fsVirtioState vdev; -} V9fsPCIState; +}; static void virtio_9p_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) { V9fsPCIState *dev = VIRTIO_9P_PCI(vpci_dev); DeviceState *vdev = DEVICE(&dev->vdev); - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); } static Property virtio_9p_pci_properties[] = { diff --git a/hw/virtio/virtio-balloon-pci.c b/hw/virtio/virtio-balloon-pci.c index cc25df0a3d3e2b5c5411dc20a017d954b228f042..a2c5cc7207a97c6fa109479adaa56e50093c45a6 100644 --- a/hw/virtio/virtio-balloon-pci.c +++ b/hw/virtio/virtio-balloon-pci.c @@ -19,6 +19,7 @@ #include "hw/virtio/virtio-balloon.h" #include "qapi/error.h" #include "qemu/module.h" +#include "qom/object.h" typedef struct VirtIOBalloonPCI VirtIOBalloonPCI; @@ -26,8 +27,8 @@ typedef struct VirtIOBalloonPCI VirtIOBalloonPCI; * virtio-balloon-pci: This extends VirtioPCIProxy. */ #define TYPE_VIRTIO_BALLOON_PCI "virtio-balloon-pci-base" -#define VIRTIO_BALLOON_PCI(obj) \ - OBJECT_CHECK(VirtIOBalloonPCI, (obj), TYPE_VIRTIO_BALLOON_PCI) +DECLARE_INSTANCE_CHECKER(VirtIOBalloonPCI, VIRTIO_BALLOON_PCI, + TYPE_VIRTIO_BALLOON_PCI) struct VirtIOBalloonPCI { VirtIOPCIProxy parent_obj; @@ -48,8 +49,7 @@ static void virtio_balloon_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) vpci_dev->class_code = PCI_CLASS_OTHERS; } - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); } static void virtio_balloon_pci_class_init(ObjectClass *klass, void *data) diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index 065cd450f10fbaf5a0acf96bc27cb95acd8dd9ca..b22b5beda3ca0866b660480a6f55ae0967c665de 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -24,7 +24,7 @@ #include "hw/virtio/virtio-balloon.h" #include "exec/address-spaces.h" #include "qapi/error.h" -#include "qapi/qapi-events-misc.h" +#include "qapi/qapi-events-machine.h" #include "qapi/visitor.h" #include "trace.h" #include "qemu/error-report.h" @@ -63,6 +63,12 @@ static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp, return pbp->base_gpa == base_gpa; } +static bool virtio_balloon_inhibited(void) +{ + /* Postcopy cannot deal with concurrent discards, so it's special. */ + return ram_block_discard_is_disabled() || migration_in_incoming_postcopy(); +} + static void balloon_inflate_page(VirtIOBalloon *balloon, MemoryRegion *mr, hwaddr mr_offset, PartiallyBalloonedPage *pbp) @@ -233,22 +239,18 @@ static void balloon_stats_get_all(Object *obj, Visitor *v, const char *name, VirtIOBalloon *s = opaque; int i; - visit_start_struct(v, name, NULL, 0, &err); - if (err) { + if (!visit_start_struct(v, name, NULL, 0, &err)) { goto out; } - visit_type_int(v, "last-update", &s->stats_last_update, &err); - if (err) { + if (!visit_type_int(v, "last-update", &s->stats_last_update, &err)) { goto out_end; } - visit_start_struct(v, "stats", NULL, 0, &err); - if (err) { + if (!visit_start_struct(v, "stats", NULL, 0, &err)) { goto out_end; } for (i = 0; i < VIRTIO_BALLOON_S_NR; i++) { - visit_type_uint64(v, balloon_stat_names[i], &s->stats[i], &err); - if (err) { + if (!visit_type_uint64(v, balloon_stat_names[i], &s->stats[i], &err)) { goto out_nested; } } @@ -278,12 +280,9 @@ static void balloon_stats_set_poll_interval(Object *obj, Visitor *v, Error **errp) { VirtIOBalloon *s = opaque; - Error *local_err = NULL; int64_t value; - visit_type_int(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_int(v, name, &value, errp)) { return; } @@ -321,6 +320,67 @@ static void balloon_stats_set_poll_interval(Object *obj, Visitor *v, balloon_stats_change_timer(s, 0); } +static void virtio_balloon_handle_report(VirtIODevice *vdev, VirtQueue *vq) +{ + VirtIOBalloon *dev = VIRTIO_BALLOON(vdev); + VirtQueueElement *elem; + + while ((elem = virtqueue_pop(vq, sizeof(VirtQueueElement)))) { + unsigned int i; + + /* + * When we discard the page it has the effect of removing the page + * from the hypervisor itself and causing it to be zeroed when it + * is returned to us. So we must not discard the page if it is + * accessible by another device or process, or if the guest is + * expecting it to retain a non-zero value. + */ + if (virtio_balloon_inhibited() || dev->poison_val) { + goto skip_element; + } + + for (i = 0; i < elem->in_num; i++) { + void *addr = elem->in_sg[i].iov_base; + size_t size = elem->in_sg[i].iov_len; + ram_addr_t ram_offset; + RAMBlock *rb; + + /* + * There is no need to check the memory section to see if + * it is ram/readonly/romd like there is for handle_output + * below. If the region is not meant to be written to then + * address_space_map will have allocated a bounce buffer + * and it will be freed in address_space_unmap and trigger + * and unassigned_mem_write before failing to copy over the + * buffer. If more than one bad descriptor is provided it + * will return NULL after the first bounce buffer and fail + * to map any resources. + */ + rb = qemu_ram_block_from_host(addr, false, &ram_offset); + if (!rb) { + trace_virtio_balloon_bad_addr(elem->in_addr[i]); + continue; + } + + /* + * For now we will simply ignore unaligned memory regions, or + * regions that overrun the end of the RAMBlock. + */ + if (!QEMU_IS_ALIGNED(ram_offset | size, qemu_ram_pagesize(rb)) || + (ram_offset + size) > qemu_ram_get_used_length(rb)) { + continue; + } + + ram_block_discard_range(rb, ram_offset, size); + } + +skip_element: + virtqueue_push(vq, elem, 0); + virtio_notify(vdev, vq); + g_free(elem); + } +} + static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) { VirtIOBalloon *s = VIRTIO_BALLOON(vdev); @@ -360,7 +420,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) trace_virtio_balloon_handle_output(memory_region_name(section.mr), pa); - if (!qemu_balloon_is_inhibited()) { + if (!virtio_balloon_inhibited()) { if (vq == s->ivq) { balloon_inflate_page(s, section.mr, section.offset_within_region, &pbp); @@ -466,21 +526,22 @@ static bool get_free_page_hints(VirtIOBalloon *dev) ret = false; goto out; } - if (id == dev->free_page_report_cmd_id) { - dev->free_page_report_status = FREE_PAGE_REPORT_S_START; + if (dev->free_page_hint_status == FREE_PAGE_HINT_S_REQUESTED && + id == dev->free_page_hint_cmd_id) { + dev->free_page_hint_status = FREE_PAGE_HINT_S_START; } else { /* * Stop the optimization only when it has started. This * avoids a stale stop sign for the previous command. */ - if (dev->free_page_report_status == FREE_PAGE_REPORT_S_START) { - dev->free_page_report_status = FREE_PAGE_REPORT_S_STOP; + if (dev->free_page_hint_status == FREE_PAGE_HINT_S_START) { + dev->free_page_hint_status = FREE_PAGE_HINT_S_STOP; } } } if (elem->in_num) { - if (dev->free_page_report_status == FREE_PAGE_REPORT_S_START) { + if (dev->free_page_hint_status == FREE_PAGE_HINT_S_START) { qemu_guest_free_page_hint(elem->in_sg[0].iov_base, elem->in_sg[0].iov_len); } @@ -506,11 +567,11 @@ static void virtio_ballloon_get_free_page_hints(void *opaque) qemu_mutex_unlock(&dev->free_page_lock); virtio_notify(vdev, vq); /* - * Start to poll the vq once the reporting started. Otherwise, continue + * Start to poll the vq once the hinting started. Otherwise, continue * only when there are entries on the vq, which need to be given back. */ } while (continue_to_get_hints || - dev->free_page_report_status == FREE_PAGE_REPORT_S_START); + dev->free_page_hint_status == FREE_PAGE_HINT_S_START); virtio_queue_set_notification(vq, 1); } @@ -531,14 +592,18 @@ static void virtio_balloon_free_page_start(VirtIOBalloon *s) return; } - if (s->free_page_report_cmd_id == UINT_MAX) { - s->free_page_report_cmd_id = - VIRTIO_BALLOON_FREE_PAGE_REPORT_CMD_ID_MIN; + qemu_mutex_lock(&s->free_page_lock); + + if (s->free_page_hint_cmd_id == UINT_MAX) { + s->free_page_hint_cmd_id = + VIRTIO_BALLOON_FREE_PAGE_HINT_CMD_ID_MIN; } else { - s->free_page_report_cmd_id++; + s->free_page_hint_cmd_id++; } - s->free_page_report_status = FREE_PAGE_REPORT_S_REQUESTED; + s->free_page_hint_status = FREE_PAGE_HINT_S_REQUESTED; + qemu_mutex_unlock(&s->free_page_lock); + virtio_notify_config(vdev); } @@ -546,18 +611,18 @@ static void virtio_balloon_free_page_stop(VirtIOBalloon *s) { VirtIODevice *vdev = VIRTIO_DEVICE(s); - if (s->free_page_report_status != FREE_PAGE_REPORT_S_STOP) { + if (s->free_page_hint_status != FREE_PAGE_HINT_S_STOP) { /* * The lock also guarantees us that the * virtio_ballloon_get_free_page_hints exits after the - * free_page_report_status is set to S_STOP. + * free_page_hint_status is set to S_STOP. */ qemu_mutex_lock(&s->free_page_lock); /* - * The guest hasn't done the reporting, so host sends a notification - * to the guest to actively stop the reporting. + * The guest isn't done hinting, so send a notification + * to the guest to actively stop the hinting. */ - s->free_page_report_status = FREE_PAGE_REPORT_S_STOP; + s->free_page_hint_status = FREE_PAGE_HINT_S_STOP; qemu_mutex_unlock(&s->free_page_lock); virtio_notify_config(vdev); } @@ -567,15 +632,20 @@ static void virtio_balloon_free_page_done(VirtIOBalloon *s) { VirtIODevice *vdev = VIRTIO_DEVICE(s); - s->free_page_report_status = FREE_PAGE_REPORT_S_DONE; - virtio_notify_config(vdev); + if (s->free_page_hint_status != FREE_PAGE_HINT_S_DONE) { + /* See virtio_balloon_free_page_stop() */ + qemu_mutex_lock(&s->free_page_lock); + s->free_page_hint_status = FREE_PAGE_HINT_S_DONE; + qemu_mutex_unlock(&s->free_page_lock); + virtio_notify_config(vdev); + } } static int -virtio_balloon_free_page_report_notify(NotifierWithReturn *n, void *data) +virtio_balloon_free_page_hint_notify(NotifierWithReturn *n, void *data) { VirtIOBalloon *dev = container_of(n, VirtIOBalloon, - free_page_report_notify); + free_page_hint_notify); VirtIODevice *vdev = VIRTIO_DEVICE(dev); PrecopyNotifyData *pnd = data; @@ -592,17 +662,26 @@ virtio_balloon_free_page_report_notify(NotifierWithReturn *n, void *data) case PRECOPY_NOTIFY_SETUP: precopy_enable_free_page_optimization(); break; - case PRECOPY_NOTIFY_COMPLETE: - case PRECOPY_NOTIFY_CLEANUP: case PRECOPY_NOTIFY_BEFORE_BITMAP_SYNC: virtio_balloon_free_page_stop(dev); break; case PRECOPY_NOTIFY_AFTER_BITMAP_SYNC: if (vdev->vm_running) { virtio_balloon_free_page_start(dev); - } else { - virtio_balloon_free_page_done(dev); + break; } + /* + * Set S_DONE before migrating the vmstate, so the guest will reuse + * all hinted pages once running on the destination. Fall through. + */ + case PRECOPY_NOTIFY_CLEANUP: + /* + * Especially, if something goes wrong during precopy or if migration + * is canceled, we have to properly communicate S_DONE to the VM. + */ + virtio_balloon_free_page_done(dev); + break; + case PRECOPY_NOTIFY_COMPLETE: break; default: virtio_error(vdev, "%s: %d reason unknown", __func__, pnd->reason); @@ -624,7 +703,7 @@ static size_t virtio_balloon_config_size(VirtIOBalloon *s) if (virtio_has_feature(features, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) { return offsetof(struct virtio_balloon_config, poison_val); } - return offsetof(struct virtio_balloon_config, free_page_report_cmd_id); + return offsetof(struct virtio_balloon_config, free_page_hint_cmd_id); } static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data) @@ -634,15 +713,16 @@ static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data) config.num_pages = cpu_to_le32(dev->num_pages); config.actual = cpu_to_le32(dev->actual); + config.poison_val = cpu_to_le32(dev->poison_val); - if (dev->free_page_report_status == FREE_PAGE_REPORT_S_REQUESTED) { - config.free_page_report_cmd_id = - cpu_to_le32(dev->free_page_report_cmd_id); - } else if (dev->free_page_report_status == FREE_PAGE_REPORT_S_STOP) { - config.free_page_report_cmd_id = + if (dev->free_page_hint_status == FREE_PAGE_HINT_S_REQUESTED) { + config.free_page_hint_cmd_id = + cpu_to_le32(dev->free_page_hint_cmd_id); + } else if (dev->free_page_hint_status == FREE_PAGE_HINT_S_STOP) { + config.free_page_hint_cmd_id = cpu_to_le32(VIRTIO_BALLOON_CMD_ID_STOP); - } else if (dev->free_page_report_status == FREE_PAGE_REPORT_S_DONE) { - config.free_page_report_cmd_id = + } else if (dev->free_page_hint_status == FREE_PAGE_HINT_S_DONE) { + config.free_page_hint_cmd_id = cpu_to_le32(VIRTIO_BALLOON_CMD_ID_DONE); } @@ -683,6 +763,14 @@ static ram_addr_t get_current_ram_size(void) return size; } +static bool virtio_balloon_page_poison_support(void *opaque) +{ + VirtIOBalloon *s = opaque; + VirtIODevice *vdev = VIRTIO_DEVICE(s); + + return virtio_vdev_has_feature(vdev, VIRTIO_BALLOON_F_PAGE_POISON); +} + static void virtio_balloon_set_config(VirtIODevice *vdev, const uint8_t *config_data) { @@ -697,6 +785,10 @@ static void virtio_balloon_set_config(VirtIODevice *vdev, qapi_event_send_balloon_change(vm_ram_size - ((ram_addr_t) dev->actual << VIRTIO_BALLOON_PFN_SHIFT)); } + dev->poison_val = 0; + if (virtio_balloon_page_poison_support(dev)) { + dev->poison_val = le32_to_cpu(config.poison_val); + } trace_virtio_balloon_set_config(dev->actual, oldactual); } @@ -743,14 +835,25 @@ static int virtio_balloon_post_load_device(void *opaque, int version_id) return 0; } -static const VMStateDescription vmstate_virtio_balloon_free_page_report = { +static const VMStateDescription vmstate_virtio_balloon_free_page_hint = { .name = "virtio-balloon-device/free-page-report", .version_id = 1, .minimum_version_id = 1, .needed = virtio_balloon_free_page_support, .fields = (VMStateField[]) { - VMSTATE_UINT32(free_page_report_cmd_id, VirtIOBalloon), - VMSTATE_UINT32(free_page_report_status, VirtIOBalloon), + VMSTATE_UINT32(free_page_hint_cmd_id, VirtIOBalloon), + VMSTATE_UINT32(free_page_hint_status, VirtIOBalloon), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_virtio_balloon_page_poison = { + .name = "vitio-balloon-device/page-poison", + .version_id = 1, + .minimum_version_id = 1, + .needed = virtio_balloon_page_poison_support, + .fields = (VMStateField[]) { + VMSTATE_UINT32(poison_val, VirtIOBalloon), VMSTATE_END_OF_LIST() } }; @@ -766,7 +869,8 @@ static const VMStateDescription vmstate_virtio_balloon_device = { VMSTATE_END_OF_LIST() }, .subsections = (const VMStateDescription * []) { - &vmstate_virtio_balloon_free_page_report, + &vmstate_virtio_balloon_free_page_hint, + &vmstate_virtio_balloon_page_poison, NULL } }; @@ -789,6 +893,13 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp) return; } + if (virtio_has_feature(s->host_features, VIRTIO_BALLOON_F_FREE_PAGE_HINT) && + !s->iothread) { + error_setg(errp, "'free-page-hint' requires 'iothread' to be set"); + virtio_cleanup(vdev); + return; + } + s->ivq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output); s->dvq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output); s->svq = virtio_add_queue(vdev, 128, virtio_balloon_receive_stats); @@ -797,25 +908,18 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp) VIRTIO_BALLOON_F_FREE_PAGE_HINT)) { s->free_page_vq = virtio_add_queue(vdev, VIRTQUEUE_MAX_SIZE, virtio_balloon_handle_free_page_vq); - s->free_page_report_status = FREE_PAGE_REPORT_S_STOP; - s->free_page_report_cmd_id = - VIRTIO_BALLOON_FREE_PAGE_REPORT_CMD_ID_MIN; - s->free_page_report_notify.notify = - virtio_balloon_free_page_report_notify; - precopy_add_notifier(&s->free_page_report_notify); - if (s->iothread) { - object_ref(OBJECT(s->iothread)); - s->free_page_bh = aio_bh_new(iothread_get_aio_context(s->iothread), - virtio_ballloon_get_free_page_hints, s); - qemu_mutex_init(&s->free_page_lock); - qemu_cond_init(&s->free_page_cond); - s->block_iothread = false; - } else { - /* Simply disable this feature if the iothread wasn't created. */ - s->host_features &= ~(1 << VIRTIO_BALLOON_F_FREE_PAGE_HINT); - virtio_error(vdev, "iothread is missing"); - } + precopy_add_notifier(&s->free_page_hint_notify); + + object_ref(OBJECT(s->iothread)); + s->free_page_bh = aio_bh_new(iothread_get_aio_context(s->iothread), + virtio_ballloon_get_free_page_hints, s); } + + if (virtio_has_feature(s->host_features, VIRTIO_BALLOON_F_REPORTING)) { + s->reporting_vq = virtio_add_queue(vdev, 32, + virtio_balloon_handle_report); + } + reset_stats(s); } @@ -824,10 +928,11 @@ static void virtio_balloon_device_unrealize(DeviceState *dev) VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIOBalloon *s = VIRTIO_BALLOON(dev); - if (virtio_balloon_free_page_support(s)) { + if (s->free_page_bh) { qemu_bh_delete(s->free_page_bh); + object_unref(OBJECT(s->iothread)); virtio_balloon_free_page_stop(s); - precopy_remove_notifier(&s->free_page_report_notify); + precopy_remove_notifier(&s->free_page_hint_notify); } balloon_stats_destroy_timer(s); qemu_remove_balloon_handler(s); @@ -838,6 +943,9 @@ static void virtio_balloon_device_unrealize(DeviceState *dev) if (s->free_page_vq) { virtio_delete_queue(s->free_page_vq); } + if (s->reporting_vq) { + virtio_delete_queue(s->reporting_vq); + } virtio_cleanup(vdev); } @@ -854,6 +962,8 @@ static void virtio_balloon_device_reset(VirtIODevice *vdev) g_free(s->stats_vq_elem); s->stats_vq_elem = NULL; } + + s->poison_val = 0; } static void virtio_balloon_set_status(VirtIODevice *vdev, uint8_t status) @@ -892,6 +1002,11 @@ static void virtio_balloon_instance_init(Object *obj) { VirtIOBalloon *s = VIRTIO_BALLOON(obj); + qemu_mutex_init(&s->free_page_lock); + qemu_cond_init(&s->free_page_cond); + s->free_page_hint_cmd_id = VIRTIO_BALLOON_FREE_PAGE_HINT_CMD_ID_MIN; + s->free_page_hint_notify.notify = virtio_balloon_free_page_hint_notify; + object_property_add(obj, "guest-stats", "guest statistics", balloon_stats_get_all, NULL, NULL, s); @@ -916,6 +1031,10 @@ static Property virtio_balloon_properties[] = { VIRTIO_BALLOON_F_DEFLATE_ON_OOM, false), DEFINE_PROP_BIT("free-page-hint", VirtIOBalloon, host_features, VIRTIO_BALLOON_F_FREE_PAGE_HINT, false), + DEFINE_PROP_BIT("page-poison", VirtIOBalloon, host_features, + VIRTIO_BALLOON_F_PAGE_POISON, true), + DEFINE_PROP_BIT("free-page-reporting", VirtIOBalloon, host_features, + VIRTIO_BALLOON_F_REPORTING, false), /* QEMU 4.0 accidentally changed the config size even when free-page-hint * is disabled, resulting in QEMU 3.1 migration incompatibility. This * property retains this quirk for QEMU 4.1 machine types. diff --git a/hw/virtio/virtio-blk-pci.c b/hw/virtio/virtio-blk-pci.c index 28838fa95812b77630ae22d9952e991f52f86d8a..9d5795810c36847b5da0ebd0930aad852d271c8f 100644 --- a/hw/virtio/virtio-blk-pci.c +++ b/hw/virtio/virtio-blk-pci.c @@ -22,6 +22,7 @@ #include "virtio-pci.h" #include "qapi/error.h" #include "qemu/module.h" +#include "qom/object.h" typedef struct VirtIOBlkPCI VirtIOBlkPCI; @@ -29,8 +30,8 @@ typedef struct VirtIOBlkPCI VirtIOBlkPCI; * virtio-blk-pci: This extends VirtioPCIProxy. */ #define TYPE_VIRTIO_BLK_PCI "virtio-blk-pci-base" -#define VIRTIO_BLK_PCI(obj) \ - OBJECT_CHECK(VirtIOBlkPCI, (obj), TYPE_VIRTIO_BLK_PCI) +DECLARE_INSTANCE_CHECKER(VirtIOBlkPCI, VIRTIO_BLK_PCI, + TYPE_VIRTIO_BLK_PCI) struct VirtIOBlkPCI { VirtIOPCIProxy parent_obj; @@ -50,13 +51,17 @@ static void virtio_blk_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) { VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(vpci_dev); DeviceState *vdev = DEVICE(&dev->vdev); + VirtIOBlkConf *conf = &dev->vdev.conf; + + if (conf->num_queues == VIRTIO_BLK_AUTO_NUM_QUEUES) { + conf->num_queues = virtio_pci_optimal_num_queues(0); + } if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { - vpci_dev->nvectors = dev->vdev.conf.num_queues + 1; + vpci_dev->nvectors = conf->num_queues + 1; } - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); } static void virtio_blk_pci_class_init(ObjectClass *klass, void *data) diff --git a/hw/virtio/virtio-crypto-pci.c b/hw/virtio/virtio-crypto-pci.c index 0bebe0149ddfb38363dc80ad53380e3e50b77876..0783dc2f7ed2fd79ed726696d15e9bfc1c9bee76 100644 --- a/hw/virtio/virtio-crypto-pci.c +++ b/hw/virtio/virtio-crypto-pci.c @@ -21,6 +21,7 @@ #include "hw/virtio/virtio-crypto.h" #include "qapi/error.h" #include "qemu/module.h" +#include "qom/object.h" typedef struct VirtIOCryptoPCI VirtIOCryptoPCI; @@ -28,8 +29,8 @@ typedef struct VirtIOCryptoPCI VirtIOCryptoPCI; * virtio-crypto-pci: This extends VirtioPCIProxy. */ #define TYPE_VIRTIO_CRYPTO_PCI "virtio-crypto-pci" -#define VIRTIO_CRYPTO_PCI(obj) \ - OBJECT_CHECK(VirtIOCryptoPCI, (obj), TYPE_VIRTIO_CRYPTO_PCI) +DECLARE_INSTANCE_CHECKER(VirtIOCryptoPCI, VIRTIO_CRYPTO_PCI, + TYPE_VIRTIO_CRYPTO_PCI) struct VirtIOCryptoPCI { VirtIOPCIProxy parent_obj; @@ -53,12 +54,10 @@ static void virtio_crypto_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) return; } - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); virtio_pci_force_virtio_1(vpci_dev); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); - object_property_set_link(OBJECT(vcrypto), - OBJECT(vcrypto->vdev.conf.cryptodev), "cryptodev", - NULL); + if (!qdev_realize(vdev, BUS(&vpci_dev->bus), errp)) { + return; + } } static void virtio_crypto_pci_class_init(ObjectClass *klass, void *data) diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c index bd9165c56554377def1c48e5642b257ac36fffd1..54f9bbb789ca304afef59257297aacc4cb9caff9 100644 --- a/hw/virtio/virtio-crypto.c +++ b/hw/virtio/virtio-crypto.c @@ -228,6 +228,8 @@ static void virtio_crypto_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) size_t s; for (;;) { + g_autofree struct iovec *out_iov_copy = NULL; + elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); if (!elem) { break; @@ -240,9 +242,12 @@ static void virtio_crypto_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) } out_num = elem->out_num; - out_iov = elem->out_sg; + out_iov_copy = g_memdup(elem->out_sg, sizeof(out_iov[0]) * out_num); + out_iov = out_iov_copy; + in_num = elem->in_num; in_iov = elem->in_sg; + if (unlikely(iov_to_buf(out_iov, out_num, 0, &ctrl, sizeof(ctrl)) != sizeof(ctrl))) { virtio_error(vdev, "virtio-crypto request ctrl_hdr too short"); @@ -582,6 +587,8 @@ virtio_crypto_handle_request(VirtIOCryptoReq *request) int queue_index = virtio_crypto_vq2q(virtio_get_queue_index(request->vq)); struct virtio_crypto_op_data_req req; int ret; + g_autofree struct iovec *in_iov_copy = NULL; + g_autofree struct iovec *out_iov_copy = NULL; struct iovec *in_iov; struct iovec *out_iov; unsigned in_num; @@ -598,9 +605,13 @@ virtio_crypto_handle_request(VirtIOCryptoReq *request) } out_num = elem->out_num; - out_iov = elem->out_sg; + out_iov_copy = g_memdup(elem->out_sg, sizeof(out_iov[0]) * out_num); + out_iov = out_iov_copy; + in_num = elem->in_num; - in_iov = elem->in_sg; + in_iov_copy = g_memdup(elem->in_sg, sizeof(in_iov[0]) * in_num); + in_iov = in_iov_copy; + if (unlikely(iov_to_buf(out_iov, out_num, 0, &req, sizeof(req)) != sizeof(req))) { virtio_error(vdev, "virtio-crypto request outhdr too short"); @@ -786,9 +797,8 @@ static void virtio_crypto_device_realize(DeviceState *dev, Error **errp) error_setg(errp, "'cryptodev' parameter expects a valid object"); return; } else if (cryptodev_backend_is_used(vcrypto->cryptodev)) { - char *path = object_get_canonical_path_component(OBJECT(vcrypto->conf.cryptodev)); - error_setg(errp, "can't use already used cryptodev backend: %s", path); - g_free(path); + error_setg(errp, "can't use already used cryptodev backend: %s", + object_get_canonical_path_component(OBJECT(vcrypto->conf.cryptodev))); return; } diff --git a/hw/virtio/virtio-input-host-pci.c b/hw/virtio/virtio-input-host-pci.c index a82eb5d914f948c6c0b2b4121dbe14bd1d1d05b1..0ac360de4f34b7f5caa5939952fee2c933b1826b 100644 --- a/hw/virtio/virtio-input-host-pci.c +++ b/hw/virtio/virtio-input-host-pci.c @@ -11,12 +11,13 @@ #include "virtio-pci.h" #include "hw/virtio/virtio-input.h" #include "qemu/module.h" +#include "qom/object.h" typedef struct VirtIOInputHostPCI VirtIOInputHostPCI; #define TYPE_VIRTIO_INPUT_HOST_PCI "virtio-input-host-pci" -#define VIRTIO_INPUT_HOST_PCI(obj) \ - OBJECT_CHECK(VirtIOInputHostPCI, (obj), TYPE_VIRTIO_INPUT_HOST_PCI) +DECLARE_INSTANCE_CHECKER(VirtIOInputHostPCI, VIRTIO_INPUT_HOST_PCI, + TYPE_VIRTIO_INPUT_HOST_PCI) struct VirtIOInputHostPCI { VirtIOPCIProxy parent_obj; diff --git a/hw/virtio/virtio-input-pci.c b/hw/virtio/virtio-input-pci.c index 5a965408df84fdaa85ad274bc997bfead846af34..48e9ff38e2fb9e28796ce35bd97dee31fd7eb19b 100644 --- a/hw/virtio/virtio-input-pci.c +++ b/hw/virtio/virtio-input-pci.c @@ -12,15 +12,13 @@ #include "hw/qdev-properties.h" #include "hw/virtio/virtio-input.h" #include "qemu/module.h" +#include "qom/object.h" -typedef struct VirtIOInputPCI VirtIOInputPCI; -typedef struct VirtIOInputHIDPCI VirtIOInputHIDPCI; /* * virtio-input-pci: This extends VirtioPCIProxy. */ -#define VIRTIO_INPUT_PCI(obj) \ - OBJECT_CHECK(VirtIOInputPCI, (obj), TYPE_VIRTIO_INPUT_PCI) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOInputPCI, VIRTIO_INPUT_PCI) struct VirtIOInputPCI { VirtIOPCIProxy parent_obj; @@ -31,8 +29,7 @@ struct VirtIOInputPCI { #define TYPE_VIRTIO_KEYBOARD_PCI "virtio-keyboard-pci" #define TYPE_VIRTIO_MOUSE_PCI "virtio-mouse-pci" #define TYPE_VIRTIO_TABLET_PCI "virtio-tablet-pci" -#define VIRTIO_INPUT_HID_PCI(obj) \ - OBJECT_CHECK(VirtIOInputHIDPCI, (obj), TYPE_VIRTIO_INPUT_HID_PCI) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOInputHIDPCI, VIRTIO_INPUT_HID_PCI) struct VirtIOInputHIDPCI { VirtIOPCIProxy parent_obj; @@ -49,9 +46,8 @@ static void virtio_input_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) VirtIOInputPCI *vinput = VIRTIO_INPUT_PCI(vpci_dev); DeviceState *vdev = DEVICE(&vinput->vdev); - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); virtio_pci_force_virtio_1(vpci_dev); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); } static void virtio_input_pci_class_init(ObjectClass *klass, void *data) diff --git a/hw/virtio/virtio-iommu-pci.c b/hw/virtio/virtio-iommu-pci.c index 3dfbf55b472dc40c3e6030085a7060eeee1dc473..378f63b2105283033b8f46cbae5bf59d8fb83b35 100644 --- a/hw/virtio/virtio-iommu-pci.c +++ b/hw/virtio/virtio-iommu-pci.c @@ -16,6 +16,7 @@ #include "hw/qdev-properties.h" #include "qapi/error.h" #include "hw/boards.h" +#include "qom/object.h" typedef struct VirtIOIOMMUPCI VirtIOIOMMUPCI; @@ -23,8 +24,8 @@ typedef struct VirtIOIOMMUPCI VirtIOIOMMUPCI; * virtio-iommu-pci: This extends VirtioPCIProxy. * */ -#define VIRTIO_IOMMU_PCI(obj) \ - OBJECT_CHECK(VirtIOIOMMUPCI, (obj), TYPE_VIRTIO_IOMMU_PCI) +DECLARE_INSTANCE_CHECKER(VirtIOIOMMUPCI, VIRTIO_IOMMU_PCI, + TYPE_VIRTIO_IOMMU_PCI) struct VirtIOIOMMUPCI { VirtIOPCIProxy parent_obj; @@ -33,6 +34,9 @@ struct VirtIOIOMMUPCI { static Property virtio_iommu_pci_properties[] = { DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0), + DEFINE_PROP_ARRAY("reserved-regions", VirtIOIOMMUPCI, + vdev.nb_reserved_regions, vdev.reserved_regions, + qdev_prop_reserved_region, ReservedRegion), DEFINE_PROP_END_OF_LIST(), }; @@ -40,6 +44,7 @@ static void virtio_iommu_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) { VirtIOIOMMUPCI *dev = VIRTIO_IOMMU_PCI(vpci_dev); DeviceState *vdev = DEVICE(&dev->vdev); + VirtIOIOMMU *s = VIRTIO_IOMMU(vdev); if (!qdev_get_machine_hotplug_handler(DEVICE(vpci_dev))) { MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); @@ -48,17 +53,24 @@ static void virtio_iommu_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) "%s machine fails to create iommu-map device tree bindings", mc->name); error_append_hint(errp, - "Check you machine implements a hotplug handler " + "Check your machine implements a hotplug handler " "for the virtio-iommu-pci device\n"); error_append_hint(errp, "Check the guest is booted without FW or with " "-no-acpi\n"); return; } - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_link(OBJECT(dev), + for (int i = 0; i < s->nb_reserved_regions; i++) { + if (s->reserved_regions[i].type != VIRTIO_IOMMU_RESV_MEM_T_RESERVED && + s->reserved_regions[i].type != VIRTIO_IOMMU_RESV_MEM_T_MSI) { + error_setg(errp, "reserved region %d has an invalid type", i); + error_append_hint(errp, "Valid values are 0 and 1\n"); + } + } + object_property_set_link(OBJECT(dev), "primary-bus", OBJECT(pci_get_bus(&vpci_dev->pci_dev)), - "primary-bus", errp); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + &error_abort); + virtio_pci_force_virtio_1(vpci_dev); + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); } static void virtio_iommu_pci_class_init(ObjectClass *klass, void *data) @@ -87,7 +99,6 @@ static void virtio_iommu_pci_instance_init(Object *obj) static const VirtioPCIDeviceTypeInfo virtio_iommu_pci_info = { .base_name = TYPE_VIRTIO_IOMMU_PCI, .generic_name = "virtio-iommu-pci", - .transitional_name = "virtio-iommu-pci-transitional", .non_transitional_name = "virtio-iommu-pci-non-transitional", .instance_size = sizeof(VirtIOIOMMUPCI), .instance_init = virtio_iommu_pci_instance_init, diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index 483883ec1d9e63de84474549dbfa30e302acd29a..fc5c75d6933e9e2032db7ea386d8a22bc5214385 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -38,6 +38,7 @@ /* Max size */ #define VIOMMU_DEFAULT_QUEUE_SIZE 256 +#define VIOMMU_PROBE_SIZE 512 typedef struct VirtIOIOMMUDomain { uint32_t id; @@ -48,6 +49,7 @@ typedef struct VirtIOIOMMUDomain { typedef struct VirtIOIOMMUEndpoint { uint32_t id; VirtIOIOMMUDomain *domain; + IOMMUMemoryRegion *iommu_mr; QLIST_ENTRY(VirtIOIOMMUEndpoint) next; } VirtIOIOMMUEndpoint; @@ -100,7 +102,7 @@ static IOMMUMemoryRegion *virtio_iommu_mr(VirtIOIOMMU *s, uint32_t sid) bus_n = PCI_BUS_NUM(sid); iommu_pci_bus = iommu_find_iommu_pcibus(s, bus_n); if (iommu_pci_bus) { - devfn = sid & PCI_DEVFN_MAX; + devfn = sid & (PCI_DEVFN_MAX - 1); dev = iommu_pci_bus->pbdev[devfn]; if (dev) { return &dev->iommu_mr; @@ -123,11 +125,84 @@ static gint interval_cmp(gconstpointer a, gconstpointer b, gpointer user_data) } } +static void virtio_iommu_notify_map(IOMMUMemoryRegion *mr, hwaddr virt_start, + hwaddr virt_end, hwaddr paddr, + uint32_t flags) +{ + IOMMUTLBEntry entry; + IOMMUAccessFlags perm = IOMMU_ACCESS_FLAG(flags & VIRTIO_IOMMU_MAP_F_READ, + flags & VIRTIO_IOMMU_MAP_F_WRITE); + + if (!(mr->iommu_notify_flags & IOMMU_NOTIFIER_MAP) || + (flags & VIRTIO_IOMMU_MAP_F_MMIO) || !perm) { + return; + } + + trace_virtio_iommu_notify_map(mr->parent_obj.name, virt_start, virt_end, + paddr, perm); + + entry.target_as = &address_space_memory; + entry.addr_mask = virt_end - virt_start; + entry.iova = virt_start; + entry.perm = perm; + entry.translated_addr = paddr; + + memory_region_notify_iommu(mr, 0, entry); +} + +static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start, + hwaddr virt_end) +{ + IOMMUTLBEntry entry; + + if (!(mr->iommu_notify_flags & IOMMU_NOTIFIER_UNMAP)) { + return; + } + + trace_virtio_iommu_notify_unmap(mr->parent_obj.name, virt_start, virt_end); + + entry.target_as = &address_space_memory; + entry.addr_mask = virt_end - virt_start; + entry.iova = virt_start; + entry.perm = IOMMU_NONE; + entry.translated_addr = 0; + + memory_region_notify_iommu(mr, 0, entry); +} + +static gboolean virtio_iommu_notify_unmap_cb(gpointer key, gpointer value, + gpointer data) +{ + VirtIOIOMMUInterval *interval = (VirtIOIOMMUInterval *) key; + IOMMUMemoryRegion *mr = (IOMMUMemoryRegion *) data; + + virtio_iommu_notify_unmap(mr, interval->low, interval->high); + + return false; +} + +static gboolean virtio_iommu_notify_map_cb(gpointer key, gpointer value, + gpointer data) +{ + VirtIOIOMMUMapping *mapping = (VirtIOIOMMUMapping *) value; + VirtIOIOMMUInterval *interval = (VirtIOIOMMUInterval *) key; + IOMMUMemoryRegion *mr = (IOMMUMemoryRegion *) data; + + virtio_iommu_notify_map(mr, interval->low, interval->high, + mapping->phys_addr, mapping->flags); + + return false; +} + static void virtio_iommu_detach_endpoint_from_domain(VirtIOIOMMUEndpoint *ep) { + VirtIOIOMMUDomain *domain = ep->domain; + if (!ep->domain) { return; } + g_tree_foreach(domain->mappings, virtio_iommu_notify_unmap_cb, + ep->iommu_mr); QLIST_REMOVE(ep, next); ep->domain = NULL; } @@ -136,16 +211,19 @@ static VirtIOIOMMUEndpoint *virtio_iommu_get_endpoint(VirtIOIOMMU *s, uint32_t ep_id) { VirtIOIOMMUEndpoint *ep; + IOMMUMemoryRegion *mr; ep = g_tree_lookup(s->endpoints, GUINT_TO_POINTER(ep_id)); if (ep) { return ep; } - if (!virtio_iommu_mr(s, ep_id)) { + mr = virtio_iommu_mr(s, ep_id); + if (!mr) { return NULL; } ep = g_malloc0(sizeof(*ep)); ep->id = ep_id; + ep->iommu_mr = mr; trace_virtio_iommu_get_endpoint(ep_id); g_tree_insert(s->endpoints, GUINT_TO_POINTER(ep_id), ep); return ep; @@ -267,6 +345,10 @@ static int virtio_iommu_attach(VirtIOIOMMU *s, ep->domain = domain; + /* Replay domain mappings on the associated memory region */ + g_tree_foreach(domain->mappings, virtio_iommu_notify_map_cb, + ep->iommu_mr); + return VIRTIO_IOMMU_S_OK; } @@ -310,6 +392,7 @@ static int virtio_iommu_map(VirtIOIOMMU *s, VirtIOIOMMUDomain *domain; VirtIOIOMMUInterval *interval; VirtIOIOMMUMapping *mapping; + VirtIOIOMMUEndpoint *ep; if (flags & ~VIRTIO_IOMMU_MAP_F_MASK) { return VIRTIO_IOMMU_S_INVAL; @@ -339,6 +422,11 @@ static int virtio_iommu_map(VirtIOIOMMU *s, g_tree_insert(domain->mappings, interval, mapping); + QLIST_FOREACH(ep, &domain->endpoint_list, next) { + virtio_iommu_notify_map(ep->iommu_mr, virt_start, virt_end, phys_start, + flags); + } + return VIRTIO_IOMMU_S_OK; } @@ -351,6 +439,7 @@ static int virtio_iommu_unmap(VirtIOIOMMU *s, VirtIOIOMMUMapping *iter_val; VirtIOIOMMUInterval interval, *iter_key; VirtIOIOMMUDomain *domain; + VirtIOIOMMUEndpoint *ep; int ret = VIRTIO_IOMMU_S_OK; trace_virtio_iommu_unmap(domain_id, virt_start, virt_end); @@ -368,6 +457,10 @@ static int virtio_iommu_unmap(VirtIOIOMMU *s, uint64_t current_high = iter_key->high; if (interval.low <= current_low && interval.high >= current_high) { + QLIST_FOREACH(ep, &domain->endpoint_list, next) { + virtio_iommu_notify_unmap(ep->iommu_mr, current_low, + current_high); + } g_tree_remove(domain->mappings, iter_key); trace_virtio_iommu_unmap_done(domain_id, current_low, current_high); } else { @@ -378,6 +471,65 @@ static int virtio_iommu_unmap(VirtIOIOMMU *s, return ret; } +static ssize_t virtio_iommu_fill_resv_mem_prop(VirtIOIOMMU *s, uint32_t ep, + uint8_t *buf, size_t free) +{ + struct virtio_iommu_probe_resv_mem prop = {}; + size_t size = sizeof(prop), length = size - sizeof(prop.head), total; + int i; + + total = size * s->nb_reserved_regions; + + if (total > free) { + return -ENOSPC; + } + + for (i = 0; i < s->nb_reserved_regions; i++) { + unsigned subtype = s->reserved_regions[i].type; + + assert(subtype == VIRTIO_IOMMU_RESV_MEM_T_RESERVED || + subtype == VIRTIO_IOMMU_RESV_MEM_T_MSI); + prop.head.type = cpu_to_le16(VIRTIO_IOMMU_PROBE_T_RESV_MEM); + prop.head.length = cpu_to_le16(length); + prop.subtype = subtype; + prop.start = cpu_to_le64(s->reserved_regions[i].low); + prop.end = cpu_to_le64(s->reserved_regions[i].high); + + memcpy(buf, &prop, size); + + trace_virtio_iommu_fill_resv_property(ep, prop.subtype, + prop.start, prop.end); + buf += size; + } + return total; +} + +/** + * virtio_iommu_probe - Fill the probe request buffer with + * the properties the device is able to return + */ +static int virtio_iommu_probe(VirtIOIOMMU *s, + struct virtio_iommu_req_probe *req, + uint8_t *buf) +{ + uint32_t ep_id = le32_to_cpu(req->endpoint); + size_t free = VIOMMU_PROBE_SIZE; + ssize_t count; + + if (!virtio_iommu_mr(s, ep_id)) { + return VIRTIO_IOMMU_S_NOENT; + } + + count = virtio_iommu_fill_resv_mem_prop(s, ep_id, buf, free); + if (count < 0) { + return VIRTIO_IOMMU_S_INVAL; + } + buf += count; + free -= count; + + return VIRTIO_IOMMU_S_OK; +} + static int virtio_iommu_iov_to_req(struct iovec *iov, unsigned int iov_cnt, void *req, size_t req_sz) @@ -407,15 +559,27 @@ virtio_iommu_handle_req(detach) virtio_iommu_handle_req(map) virtio_iommu_handle_req(unmap) +static int virtio_iommu_handle_probe(VirtIOIOMMU *s, + struct iovec *iov, + unsigned int iov_cnt, + uint8_t *buf) +{ + struct virtio_iommu_req_probe req; + int ret = virtio_iommu_iov_to_req(iov, iov_cnt, &req, sizeof(req)); + + return ret ? ret : virtio_iommu_probe(s, &req, buf); +} + static void virtio_iommu_handle_command(VirtIODevice *vdev, VirtQueue *vq) { VirtIOIOMMU *s = VIRTIO_IOMMU(vdev); struct virtio_iommu_req_head head; struct virtio_iommu_req_tail tail = {}; + size_t output_size = sizeof(tail), sz; VirtQueueElement *elem; unsigned int iov_cnt; struct iovec *iov; - size_t sz; + void *buf = NULL; for (;;) { elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); @@ -452,6 +616,18 @@ static void virtio_iommu_handle_command(VirtIODevice *vdev, VirtQueue *vq) case VIRTIO_IOMMU_T_UNMAP: tail.status = virtio_iommu_handle_unmap(s, iov, iov_cnt); break; + case VIRTIO_IOMMU_T_PROBE: + { + struct virtio_iommu_req_tail *ptail; + + output_size = s->config.probe_size + sizeof(tail); + buf = g_malloc0(output_size); + + ptail = (struct virtio_iommu_req_tail *) + (buf + s->config.probe_size); + ptail->status = virtio_iommu_handle_probe(s, iov, iov_cnt, buf); + break; + } default: tail.status = VIRTIO_IOMMU_S_UNSUPP; } @@ -459,12 +635,13 @@ static void virtio_iommu_handle_command(VirtIODevice *vdev, VirtQueue *vq) out: sz = iov_from_buf(elem->in_sg, elem->in_num, 0, - &tail, sizeof(tail)); - assert(sz == sizeof(tail)); + buf ? buf : &tail, output_size); + assert(sz == output_size); - virtqueue_push(vq, elem, sizeof(tail)); + virtqueue_push(vq, elem, sz); virtio_notify(vdev, vq); g_free(elem); + g_free(buf); } } @@ -523,6 +700,7 @@ static IOMMUTLBEntry virtio_iommu_translate(IOMMUMemoryRegion *mr, hwaddr addr, uint32_t sid, flags; bool bypass_allowed; bool found; + int i; interval.low = addr; interval.high = addr + 1; @@ -556,6 +734,25 @@ static IOMMUTLBEntry virtio_iommu_translate(IOMMUMemoryRegion *mr, hwaddr addr, goto unlock; } + for (i = 0; i < s->nb_reserved_regions; i++) { + ReservedRegion *reg = &s->reserved_regions[i]; + + if (addr >= reg->low && addr <= reg->high) { + switch (reg->type) { + case VIRTIO_IOMMU_RESV_MEM_T_MSI: + entry.perm = flag; + break; + case VIRTIO_IOMMU_RESV_MEM_T_RESERVED: + default: + virtio_iommu_report_fault(s, VIRTIO_IOMMU_FAULT_R_MAPPING, + VIRTIO_IOMMU_FAULT_F_ADDRESS, + sid, addr); + break; + } + goto unlock; + } + } + if (!ep->domain) { if (!bypass_allowed) { error_report_once("%s %02x:%02x.%01x not attached to any domain", @@ -650,6 +847,107 @@ static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data) return (ua > ub) - (ua < ub); } +static gboolean virtio_iommu_remap(gpointer key, gpointer value, gpointer data) +{ + VirtIOIOMMUMapping *mapping = (VirtIOIOMMUMapping *) value; + VirtIOIOMMUInterval *interval = (VirtIOIOMMUInterval *) key; + IOMMUMemoryRegion *mr = (IOMMUMemoryRegion *) data; + + trace_virtio_iommu_remap(mr->parent_obj.name, interval->low, interval->high, + mapping->phys_addr); + virtio_iommu_notify_map(mr, interval->low, interval->high, + mapping->phys_addr, mapping->flags); + return false; +} + +static void virtio_iommu_replay(IOMMUMemoryRegion *mr, IOMMUNotifier *n) +{ + IOMMUDevice *sdev = container_of(mr, IOMMUDevice, iommu_mr); + VirtIOIOMMU *s = sdev->viommu; + uint32_t sid; + VirtIOIOMMUEndpoint *ep; + + sid = virtio_iommu_get_bdf(sdev); + + qemu_mutex_lock(&s->mutex); + + if (!s->endpoints) { + goto unlock; + } + + ep = g_tree_lookup(s->endpoints, GUINT_TO_POINTER(sid)); + if (!ep || !ep->domain) { + goto unlock; + } + + g_tree_foreach(ep->domain->mappings, virtio_iommu_remap, mr); + +unlock: + qemu_mutex_unlock(&s->mutex); +} + +static int virtio_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu_mr, + IOMMUNotifierFlag old, + IOMMUNotifierFlag new, + Error **errp) +{ + if (old == IOMMU_NOTIFIER_NONE) { + trace_virtio_iommu_notify_flag_add(iommu_mr->parent_obj.name); + } else if (new == IOMMU_NOTIFIER_NONE) { + trace_virtio_iommu_notify_flag_del(iommu_mr->parent_obj.name); + } + return 0; +} + +/* + * The default mask (TARGET_PAGE_MASK) is the smallest supported guest granule, + * for example 0xfffffffffffff000. When an assigned device has page size + * restrictions due to the hardware IOMMU configuration, apply this restriction + * to the mask. + */ +static int virtio_iommu_set_page_size_mask(IOMMUMemoryRegion *mr, + uint64_t new_mask, + Error **errp) +{ + IOMMUDevice *sdev = container_of(mr, IOMMUDevice, iommu_mr); + VirtIOIOMMU *s = sdev->viommu; + uint64_t cur_mask = s->config.page_size_mask; + + trace_virtio_iommu_set_page_size_mask(mr->parent_obj.name, cur_mask, + new_mask); + + if ((cur_mask & new_mask) == 0) { + error_setg(errp, "virtio-iommu page mask 0x%"PRIx64 + " is incompatible with mask 0x%"PRIx64, cur_mask, new_mask); + return -1; + } + + /* + * After the machine is finalized, we can't change the mask anymore. If by + * chance the hotplugged device supports the same granule, we can still + * accept it. Having a different masks is possible but the guest will use + * sub-optimal block sizes, so warn about it. + */ + if (qdev_hotplug) { + int new_granule = ctz64(new_mask); + int cur_granule = ctz64(cur_mask); + + if (new_granule != cur_granule) { + error_setg(errp, "virtio-iommu page mask 0x%"PRIx64 + " is incompatible with mask 0x%"PRIx64, cur_mask, + new_mask); + return -1; + } else if (new_mask != cur_mask) { + warn_report("virtio-iommu page mask 0x%"PRIx64 + " does not match 0x%"PRIx64, cur_mask, new_mask); + } + return 0; + } + + s->config.page_size_mask &= new_mask; + return 0; +} + static void virtio_iommu_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); @@ -667,6 +965,7 @@ static void virtio_iommu_device_realize(DeviceState *dev, Error **errp) s->config.page_size_mask = TARGET_PAGE_MASK; s->config.input_range.end = -1UL; s->config.domain_range.end = 32; + s->config.probe_size = VIOMMU_PROBE_SIZE; virtio_add_feature(&s->features, VIRTIO_RING_F_EVENT_IDX); virtio_add_feature(&s->features, VIRTIO_RING_F_INDIRECT_DESC); @@ -676,6 +975,7 @@ static void virtio_iommu_device_realize(DeviceState *dev, Error **errp) virtio_add_feature(&s->features, VIRTIO_IOMMU_F_MAP_UNMAP); virtio_add_feature(&s->features, VIRTIO_IOMMU_F_BYPASS); virtio_add_feature(&s->features, VIRTIO_IOMMU_F_MMIO); + virtio_add_feature(&s->features, VIRTIO_IOMMU_F_PROBE); qemu_mutex_init(&s->mutex); @@ -694,8 +994,12 @@ static void virtio_iommu_device_unrealize(DeviceState *dev) VirtIOIOMMU *s = VIRTIO_IOMMU(dev); g_hash_table_destroy(s->as_by_busptr); - g_tree_destroy(s->domains); - g_tree_destroy(s->endpoints); + if (s->domains) { + g_tree_destroy(s->domains); + } + if (s->endpoints) { + g_tree_destroy(s->endpoints); + } virtio_delete_queue(s->req_vq); virtio_delete_queue(s->event_vq); @@ -799,9 +1103,14 @@ static gboolean reconstruct_endpoints(gpointer key, gpointer value, VirtIOIOMMU *s = (VirtIOIOMMU *)data; VirtIOIOMMUDomain *d = (VirtIOIOMMUDomain *)value; VirtIOIOMMUEndpoint *iter; + IOMMUMemoryRegion *mr; QLIST_FOREACH(iter, &d->endpoint_list, next) { + mr = virtio_iommu_mr(s, iter->id); + assert(mr); + iter->domain = d; + iter->iommu_mr = mr; g_tree_insert(s->endpoints, GUINT_TO_POINTER(iter->id), iter); } return false; /* continue the domain traversal */ @@ -868,6 +1177,9 @@ static void virtio_iommu_memory_region_class_init(ObjectClass *klass, IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); imrc->translate = virtio_iommu_translate; + imrc->replay = virtio_iommu_replay; + imrc->notify_flag_changed = virtio_iommu_notify_flag_changed; + imrc->iommu_set_page_size_mask = virtio_iommu_set_page_size_mask; } static const TypeInfo virtio_iommu_info = { diff --git a/hw/virtio/virtio-mem-pci.c b/hw/virtio/virtio-mem-pci.c new file mode 100644 index 0000000000000000000000000000000000000000..fa5395cd88577964fba445c68f2d025b504f5544 --- /dev/null +++ b/hw/virtio/virtio-mem-pci.c @@ -0,0 +1,165 @@ +/* + * Virtio MEM PCI device + * + * Copyright (C) 2020 Red Hat, Inc. + * + * Authors: + * David Hildenbrand + * + * This work is licensed under the terms of the GNU GPL, version 2. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "virtio-mem-pci.h" +#include "hw/mem/memory-device.h" +#include "qapi/error.h" +#include "qapi/qapi-events-machine.h" +#include "qapi/qapi-events-misc.h" + +static void virtio_mem_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) +{ + VirtIOMEMPCI *mem_pci = VIRTIO_MEM_PCI(vpci_dev); + DeviceState *vdev = DEVICE(&mem_pci->vdev); + + virtio_pci_force_virtio_1(vpci_dev); + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); +} + +static void virtio_mem_pci_set_addr(MemoryDeviceState *md, uint64_t addr, + Error **errp) +{ + object_property_set_uint(OBJECT(md), VIRTIO_MEM_ADDR_PROP, addr, errp); +} + +static uint64_t virtio_mem_pci_get_addr(const MemoryDeviceState *md) +{ + return object_property_get_uint(OBJECT(md), VIRTIO_MEM_ADDR_PROP, + &error_abort); +} + +static MemoryRegion *virtio_mem_pci_get_memory_region(MemoryDeviceState *md, + Error **errp) +{ + VirtIOMEMPCI *pci_mem = VIRTIO_MEM_PCI(md); + VirtIOMEM *vmem = VIRTIO_MEM(&pci_mem->vdev); + VirtIOMEMClass *vmc = VIRTIO_MEM_GET_CLASS(vmem); + + return vmc->get_memory_region(vmem, errp); +} + +static uint64_t virtio_mem_pci_get_plugged_size(const MemoryDeviceState *md, + Error **errp) +{ + return object_property_get_uint(OBJECT(md), VIRTIO_MEM_SIZE_PROP, + errp); +} + +static void virtio_mem_pci_fill_device_info(const MemoryDeviceState *md, + MemoryDeviceInfo *info) +{ + VirtioMEMDeviceInfo *vi = g_new0(VirtioMEMDeviceInfo, 1); + VirtIOMEMPCI *pci_mem = VIRTIO_MEM_PCI(md); + VirtIOMEM *vmem = VIRTIO_MEM(&pci_mem->vdev); + VirtIOMEMClass *vpc = VIRTIO_MEM_GET_CLASS(vmem); + DeviceState *dev = DEVICE(md); + + if (dev->id) { + vi->has_id = true; + vi->id = g_strdup(dev->id); + } + + /* let the real device handle everything else */ + vpc->fill_device_info(vmem, vi); + + info->u.virtio_mem.data = vi; + info->type = MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM; +} + +static uint64_t virtio_mem_pci_get_min_alignment(const MemoryDeviceState *md) +{ + return object_property_get_uint(OBJECT(md), VIRTIO_MEM_BLOCK_SIZE_PROP, + &error_abort); +} + +static void virtio_mem_pci_size_change_notify(Notifier *notifier, void *data) +{ + VirtIOMEMPCI *pci_mem = container_of(notifier, VirtIOMEMPCI, + size_change_notifier); + DeviceState *dev = DEVICE(pci_mem); + const uint64_t * const size_p = data; + const char *id = NULL; + + if (dev->id) { + id = g_strdup(dev->id); + } + + qapi_event_send_memory_device_size_change(!!id, id, *size_p); +} + +static void virtio_mem_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); + PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); + MemoryDeviceClass *mdc = MEMORY_DEVICE_CLASS(klass); + + k->realize = virtio_mem_pci_realize; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; + pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_MEM; + pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; + pcidev_k->class_id = PCI_CLASS_OTHERS; + + mdc->get_addr = virtio_mem_pci_get_addr; + mdc->set_addr = virtio_mem_pci_set_addr; + mdc->get_plugged_size = virtio_mem_pci_get_plugged_size; + mdc->get_memory_region = virtio_mem_pci_get_memory_region; + mdc->fill_device_info = virtio_mem_pci_fill_device_info; + mdc->get_min_alignment = virtio_mem_pci_get_min_alignment; +} + +static void virtio_mem_pci_instance_init(Object *obj) +{ + VirtIOMEMPCI *dev = VIRTIO_MEM_PCI(obj); + VirtIOMEMClass *vmc; + VirtIOMEM *vmem; + + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VIRTIO_MEM); + + dev->size_change_notifier.notify = virtio_mem_pci_size_change_notify; + vmem = VIRTIO_MEM(&dev->vdev); + vmc = VIRTIO_MEM_GET_CLASS(vmem); + /* + * We never remove the notifier again, as we expect both devices to + * disappear at the same time. + */ + vmc->add_size_change_notifier(vmem, &dev->size_change_notifier); + + object_property_add_alias(obj, VIRTIO_MEM_BLOCK_SIZE_PROP, + OBJECT(&dev->vdev), VIRTIO_MEM_BLOCK_SIZE_PROP); + object_property_add_alias(obj, VIRTIO_MEM_SIZE_PROP, OBJECT(&dev->vdev), + VIRTIO_MEM_SIZE_PROP); + object_property_add_alias(obj, VIRTIO_MEM_REQUESTED_SIZE_PROP, + OBJECT(&dev->vdev), + VIRTIO_MEM_REQUESTED_SIZE_PROP); +} + +static const VirtioPCIDeviceTypeInfo virtio_mem_pci_info = { + .base_name = TYPE_VIRTIO_MEM_PCI, + .generic_name = "virtio-mem-pci", + .instance_size = sizeof(VirtIOMEMPCI), + .instance_init = virtio_mem_pci_instance_init, + .class_init = virtio_mem_pci_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_MEMORY_DEVICE }, + { } + }, +}; + +static void virtio_mem_pci_register_types(void) +{ + virtio_pci_types_register(&virtio_mem_pci_info); +} +type_init(virtio_mem_pci_register_types) diff --git a/hw/virtio/virtio-mem-pci.h b/hw/virtio/virtio-mem-pci.h new file mode 100644 index 0000000000000000000000000000000000000000..e636e1a48d5e94fd82d3d8a27fe6ef0a738a0eac --- /dev/null +++ b/hw/virtio/virtio-mem-pci.h @@ -0,0 +1,35 @@ +/* + * Virtio MEM PCI device + * + * Copyright (C) 2020 Red Hat, Inc. + * + * Authors: + * David Hildenbrand + * + * This work is licensed under the terms of the GNU GPL, version 2. + * See the COPYING file in the top-level directory. + */ + +#ifndef QEMU_VIRTIO_MEM_PCI_H +#define QEMU_VIRTIO_MEM_PCI_H + +#include "hw/virtio/virtio-pci.h" +#include "hw/virtio/virtio-mem.h" +#include "qom/object.h" + +typedef struct VirtIOMEMPCI VirtIOMEMPCI; + +/* + * virtio-mem-pci: This extends VirtioPCIProxy. + */ +#define TYPE_VIRTIO_MEM_PCI "virtio-mem-pci-base" +DECLARE_INSTANCE_CHECKER(VirtIOMEMPCI, VIRTIO_MEM_PCI, + TYPE_VIRTIO_MEM_PCI) + +struct VirtIOMEMPCI { + VirtIOPCIProxy parent_obj; + VirtIOMEM vdev; + Notifier size_change_notifier; +}; + +#endif /* QEMU_VIRTIO_MEM_PCI_H */ diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c new file mode 100644 index 0000000000000000000000000000000000000000..655824ff81a2a77dcc28306c9d62c0c4c0d8d986 --- /dev/null +++ b/hw/virtio/virtio-mem.c @@ -0,0 +1,979 @@ +/* + * Virtio MEM device + * + * Copyright (C) 2020 Red Hat, Inc. + * + * Authors: + * David Hildenbrand + * + * This work is licensed under the terms of the GNU GPL, version 2. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/iov.h" +#include "qemu/cutils.h" +#include "qemu/error-report.h" +#include "qemu/units.h" +#include "sysemu/numa.h" +#include "sysemu/sysemu.h" +#include "sysemu/reset.h" +#include "hw/virtio/virtio.h" +#include "hw/virtio/virtio-bus.h" +#include "hw/virtio/virtio-access.h" +#include "hw/virtio/virtio-mem.h" +#include "qapi/error.h" +#include "qapi/visitor.h" +#include "exec/ram_addr.h" +#include "migration/misc.h" +#include "hw/boards.h" +#include "hw/qdev-properties.h" +#include CONFIG_DEVICES +#include "trace.h" + +/* + * Let's not allow blocks smaller than 1 MiB, for example, to keep the tracking + * bitmap small. + */ +#define VIRTIO_MEM_MIN_BLOCK_SIZE ((uint32_t)(1 * MiB)) + +#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || \ + defined(__powerpc64__) +#define VIRTIO_MEM_DEFAULT_THP_SIZE ((uint32_t)(2 * MiB)) +#else + /* fallback to 1 MiB (e.g., the THP size on s390x) */ +#define VIRTIO_MEM_DEFAULT_THP_SIZE VIRTIO_MEM_MIN_BLOCK_SIZE +#endif + +/* + * We want to have a reasonable default block size such that + * 1. We avoid splitting THPs when unplugging memory, which degrades + * performance. + * 2. We avoid placing THPs for plugged blocks that also cover unplugged + * blocks. + * + * The actual THP size might differ between Linux kernels, so we try to probe + * it. In the future (if we ever run into issues regarding 2.), we might want + * to disable THP in case we fail to properly probe the THP size, or if the + * block size is configured smaller than the THP size. + */ +static uint32_t thp_size; + +#define HPAGE_PMD_SIZE_PATH "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size" +static uint32_t virtio_mem_thp_size(void) +{ + gchar *content = NULL; + const char *endptr; + uint64_t tmp; + + if (thp_size) { + return thp_size; + } + + /* + * Try to probe the actual THP size, fallback to (sane but eventually + * incorrect) default sizes. + */ + if (g_file_get_contents(HPAGE_PMD_SIZE_PATH, &content, NULL, NULL) && + !qemu_strtou64(content, &endptr, 0, &tmp) && + (!endptr || *endptr == '\n')) { + /* + * Sanity-check the value, if it's too big (e.g., aarch64 with 64k base + * pages) or weird, fallback to something smaller. + */ + if (!tmp || !is_power_of_2(tmp) || tmp > 16 * MiB) { + warn_report("Read unsupported THP size: %" PRIx64, tmp); + } else { + thp_size = tmp; + } + } + + if (!thp_size) { + thp_size = VIRTIO_MEM_DEFAULT_THP_SIZE; + warn_report("Could not detect THP size, falling back to %" PRIx64 + " MiB.", thp_size / MiB); + } + + g_free(content); + return thp_size; +} + +static uint64_t virtio_mem_default_block_size(RAMBlock *rb) +{ + const uint64_t page_size = qemu_ram_pagesize(rb); + + /* We can have hugetlbfs with a page size smaller than the THP size. */ + if (page_size == qemu_real_host_page_size) { + return MAX(page_size, virtio_mem_thp_size()); + } + return MAX(page_size, VIRTIO_MEM_MIN_BLOCK_SIZE); +} + +/* + * Size the usable region bigger than the requested size if possible. Esp. + * Linux guests will only add (aligned) memory blocks in case they fully + * fit into the usable region, but plug+online only a subset of the pages. + * The memory block size corresponds mostly to the section size. + * + * This allows e.g., to add 20MB with a section size of 128MB on x86_64, and + * a section size of 1GB on arm64 (as long as the start address is properly + * aligned, similar to ordinary DIMMs). + * + * We can change this at any time and maybe even make it configurable if + * necessary (as the section size can change). But it's more likely that the + * section size will rather get smaller and not bigger over time. + */ +#if defined(TARGET_X86_64) || defined(TARGET_I386) +#define VIRTIO_MEM_USABLE_EXTENT (2 * (128 * MiB)) +#else +#error VIRTIO_MEM_USABLE_EXTENT not defined +#endif + +static bool virtio_mem_is_busy(void) +{ + /* + * Postcopy cannot handle concurrent discards and we don't want to migrate + * pages on-demand with stale content when plugging new blocks. + * + * For precopy, we don't want unplugged blocks in our migration stream, and + * when plugging new blocks, the page content might differ between source + * and destination (observable by the guest when not initializing pages + * after plugging them) until we're running on the destination (as we didn't + * migrate these blocks when they were unplugged). + */ + return migration_in_incoming_postcopy() || !migration_is_idle(); +} + +static bool virtio_mem_test_bitmap(VirtIOMEM *vmem, uint64_t start_gpa, + uint64_t size, bool plugged) +{ + const unsigned long first_bit = (start_gpa - vmem->addr) / vmem->block_size; + const unsigned long last_bit = first_bit + (size / vmem->block_size) - 1; + unsigned long found_bit; + + /* We fake a shorter bitmap to avoid searching too far. */ + if (plugged) { + found_bit = find_next_zero_bit(vmem->bitmap, last_bit + 1, first_bit); + } else { + found_bit = find_next_bit(vmem->bitmap, last_bit + 1, first_bit); + } + return found_bit > last_bit; +} + +static void virtio_mem_set_bitmap(VirtIOMEM *vmem, uint64_t start_gpa, + uint64_t size, bool plugged) +{ + const unsigned long bit = (start_gpa - vmem->addr) / vmem->block_size; + const unsigned long nbits = size / vmem->block_size; + + if (plugged) { + bitmap_set(vmem->bitmap, bit, nbits); + } else { + bitmap_clear(vmem->bitmap, bit, nbits); + } +} + +static void virtio_mem_send_response(VirtIOMEM *vmem, VirtQueueElement *elem, + struct virtio_mem_resp *resp) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(vmem); + VirtQueue *vq = vmem->vq; + + trace_virtio_mem_send_response(le16_to_cpu(resp->type)); + iov_from_buf(elem->in_sg, elem->in_num, 0, resp, sizeof(*resp)); + + virtqueue_push(vq, elem, sizeof(*resp)); + virtio_notify(vdev, vq); +} + +static void virtio_mem_send_response_simple(VirtIOMEM *vmem, + VirtQueueElement *elem, + uint16_t type) +{ + struct virtio_mem_resp resp = { + .type = cpu_to_le16(type), + }; + + virtio_mem_send_response(vmem, elem, &resp); +} + +static bool virtio_mem_valid_range(VirtIOMEM *vmem, uint64_t gpa, uint64_t size) +{ + if (!QEMU_IS_ALIGNED(gpa, vmem->block_size)) { + return false; + } + if (gpa + size < gpa || !size) { + return false; + } + if (gpa < vmem->addr || gpa >= vmem->addr + vmem->usable_region_size) { + return false; + } + if (gpa + size > vmem->addr + vmem->usable_region_size) { + return false; + } + return true; +} + +static int virtio_mem_set_block_state(VirtIOMEM *vmem, uint64_t start_gpa, + uint64_t size, bool plug) +{ + const uint64_t offset = start_gpa - vmem->addr; + int ret; + + if (virtio_mem_is_busy()) { + return -EBUSY; + } + + if (!plug) { + ret = ram_block_discard_range(vmem->memdev->mr.ram_block, offset, size); + if (ret) { + error_report("Unexpected error discarding RAM: %s", + strerror(-ret)); + return -EBUSY; + } + } + virtio_mem_set_bitmap(vmem, start_gpa, size, plug); + return 0; +} + +static int virtio_mem_state_change_request(VirtIOMEM *vmem, uint64_t gpa, + uint16_t nb_blocks, bool plug) +{ + const uint64_t size = nb_blocks * vmem->block_size; + int ret; + + if (!virtio_mem_valid_range(vmem, gpa, size)) { + return VIRTIO_MEM_RESP_ERROR; + } + + if (plug && (vmem->size + size > vmem->requested_size)) { + return VIRTIO_MEM_RESP_NACK; + } + + /* test if really all blocks are in the opposite state */ + if (!virtio_mem_test_bitmap(vmem, gpa, size, !plug)) { + return VIRTIO_MEM_RESP_ERROR; + } + + ret = virtio_mem_set_block_state(vmem, gpa, size, plug); + if (ret) { + return VIRTIO_MEM_RESP_BUSY; + } + if (plug) { + vmem->size += size; + } else { + vmem->size -= size; + } + notifier_list_notify(&vmem->size_change_notifiers, &vmem->size); + return VIRTIO_MEM_RESP_ACK; +} + +static void virtio_mem_plug_request(VirtIOMEM *vmem, VirtQueueElement *elem, + struct virtio_mem_req *req) +{ + const uint64_t gpa = le64_to_cpu(req->u.plug.addr); + const uint16_t nb_blocks = le16_to_cpu(req->u.plug.nb_blocks); + uint16_t type; + + trace_virtio_mem_plug_request(gpa, nb_blocks); + type = virtio_mem_state_change_request(vmem, gpa, nb_blocks, true); + virtio_mem_send_response_simple(vmem, elem, type); +} + +static void virtio_mem_unplug_request(VirtIOMEM *vmem, VirtQueueElement *elem, + struct virtio_mem_req *req) +{ + const uint64_t gpa = le64_to_cpu(req->u.unplug.addr); + const uint16_t nb_blocks = le16_to_cpu(req->u.unplug.nb_blocks); + uint16_t type; + + trace_virtio_mem_unplug_request(gpa, nb_blocks); + type = virtio_mem_state_change_request(vmem, gpa, nb_blocks, false); + virtio_mem_send_response_simple(vmem, elem, type); +} + +static void virtio_mem_resize_usable_region(VirtIOMEM *vmem, + uint64_t requested_size, + bool can_shrink) +{ + uint64_t newsize = MIN(memory_region_size(&vmem->memdev->mr), + requested_size + VIRTIO_MEM_USABLE_EXTENT); + + /* The usable region size always has to be multiples of the block size. */ + newsize = QEMU_ALIGN_UP(newsize, vmem->block_size); + + if (!requested_size) { + newsize = 0; + } + + if (newsize < vmem->usable_region_size && !can_shrink) { + return; + } + + trace_virtio_mem_resized_usable_region(vmem->usable_region_size, newsize); + vmem->usable_region_size = newsize; +} + +static int virtio_mem_unplug_all(VirtIOMEM *vmem) +{ + RAMBlock *rb = vmem->memdev->mr.ram_block; + int ret; + + if (virtio_mem_is_busy()) { + return -EBUSY; + } + + ret = ram_block_discard_range(rb, 0, qemu_ram_get_used_length(rb)); + if (ret) { + error_report("Unexpected error discarding RAM: %s", strerror(-ret)); + return -EBUSY; + } + bitmap_clear(vmem->bitmap, 0, vmem->bitmap_size); + if (vmem->size) { + vmem->size = 0; + notifier_list_notify(&vmem->size_change_notifiers, &vmem->size); + } + trace_virtio_mem_unplugged_all(); + virtio_mem_resize_usable_region(vmem, vmem->requested_size, true); + return 0; +} + +static void virtio_mem_unplug_all_request(VirtIOMEM *vmem, + VirtQueueElement *elem) +{ + trace_virtio_mem_unplug_all_request(); + if (virtio_mem_unplug_all(vmem)) { + virtio_mem_send_response_simple(vmem, elem, VIRTIO_MEM_RESP_BUSY); + } else { + virtio_mem_send_response_simple(vmem, elem, VIRTIO_MEM_RESP_ACK); + } +} + +static void virtio_mem_state_request(VirtIOMEM *vmem, VirtQueueElement *elem, + struct virtio_mem_req *req) +{ + const uint16_t nb_blocks = le16_to_cpu(req->u.state.nb_blocks); + const uint64_t gpa = le64_to_cpu(req->u.state.addr); + const uint64_t size = nb_blocks * vmem->block_size; + struct virtio_mem_resp resp = { + .type = cpu_to_le16(VIRTIO_MEM_RESP_ACK), + }; + + trace_virtio_mem_state_request(gpa, nb_blocks); + if (!virtio_mem_valid_range(vmem, gpa, size)) { + virtio_mem_send_response_simple(vmem, elem, VIRTIO_MEM_RESP_ERROR); + return; + } + + if (virtio_mem_test_bitmap(vmem, gpa, size, true)) { + resp.u.state.state = cpu_to_le16(VIRTIO_MEM_STATE_PLUGGED); + } else if (virtio_mem_test_bitmap(vmem, gpa, size, false)) { + resp.u.state.state = cpu_to_le16(VIRTIO_MEM_STATE_UNPLUGGED); + } else { + resp.u.state.state = cpu_to_le16(VIRTIO_MEM_STATE_MIXED); + } + trace_virtio_mem_state_response(le16_to_cpu(resp.u.state.state)); + virtio_mem_send_response(vmem, elem, &resp); +} + +static void virtio_mem_handle_request(VirtIODevice *vdev, VirtQueue *vq) +{ + const int len = sizeof(struct virtio_mem_req); + VirtIOMEM *vmem = VIRTIO_MEM(vdev); + VirtQueueElement *elem; + struct virtio_mem_req req; + uint16_t type; + + while (true) { + elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); + if (!elem) { + return; + } + + if (iov_to_buf(elem->out_sg, elem->out_num, 0, &req, len) < len) { + virtio_error(vdev, "virtio-mem protocol violation: invalid request" + " size: %d", len); + virtqueue_detach_element(vq, elem, 0); + g_free(elem); + return; + } + + if (iov_size(elem->in_sg, elem->in_num) < + sizeof(struct virtio_mem_resp)) { + virtio_error(vdev, "virtio-mem protocol violation: not enough space" + " for response: %zu", + iov_size(elem->in_sg, elem->in_num)); + virtqueue_detach_element(vq, elem, 0); + g_free(elem); + return; + } + + type = le16_to_cpu(req.type); + switch (type) { + case VIRTIO_MEM_REQ_PLUG: + virtio_mem_plug_request(vmem, elem, &req); + break; + case VIRTIO_MEM_REQ_UNPLUG: + virtio_mem_unplug_request(vmem, elem, &req); + break; + case VIRTIO_MEM_REQ_UNPLUG_ALL: + virtio_mem_unplug_all_request(vmem, elem); + break; + case VIRTIO_MEM_REQ_STATE: + virtio_mem_state_request(vmem, elem, &req); + break; + default: + virtio_error(vdev, "virtio-mem protocol violation: unknown request" + " type: %d", type); + virtqueue_detach_element(vq, elem, 0); + g_free(elem); + return; + } + + g_free(elem); + } +} + +static void virtio_mem_get_config(VirtIODevice *vdev, uint8_t *config_data) +{ + VirtIOMEM *vmem = VIRTIO_MEM(vdev); + struct virtio_mem_config *config = (void *) config_data; + + config->block_size = cpu_to_le64(vmem->block_size); + config->node_id = cpu_to_le16(vmem->node); + config->requested_size = cpu_to_le64(vmem->requested_size); + config->plugged_size = cpu_to_le64(vmem->size); + config->addr = cpu_to_le64(vmem->addr); + config->region_size = cpu_to_le64(memory_region_size(&vmem->memdev->mr)); + config->usable_region_size = cpu_to_le64(vmem->usable_region_size); +} + +static uint64_t virtio_mem_get_features(VirtIODevice *vdev, uint64_t features, + Error **errp) +{ + MachineState *ms = MACHINE(qdev_get_machine()); + + if (ms->numa_state) { +#if defined(CONFIG_ACPI) + virtio_add_feature(&features, VIRTIO_MEM_F_ACPI_PXM); +#endif + } + return features; +} + +static void virtio_mem_system_reset(void *opaque) +{ + VirtIOMEM *vmem = VIRTIO_MEM(opaque); + + /* + * During usual resets, we will unplug all memory and shrink the usable + * region size. This is, however, not possible in all scenarios. Then, + * the guest has to deal with this manually (VIRTIO_MEM_REQ_UNPLUG_ALL). + */ + virtio_mem_unplug_all(vmem); +} + +static void virtio_mem_device_realize(DeviceState *dev, Error **errp) +{ + MachineState *ms = MACHINE(qdev_get_machine()); + int nb_numa_nodes = ms->numa_state ? ms->numa_state->num_nodes : 0; + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VirtIOMEM *vmem = VIRTIO_MEM(dev); + uint64_t page_size; + RAMBlock *rb; + int ret; + + if (!vmem->memdev) { + error_setg(errp, "'%s' property is not set", VIRTIO_MEM_MEMDEV_PROP); + return; + } else if (host_memory_backend_is_mapped(vmem->memdev)) { + error_setg(errp, "'%s' property specifies a busy memdev: %s", + VIRTIO_MEM_MEMDEV_PROP, + object_get_canonical_path_component(OBJECT(vmem->memdev))); + return; + } else if (!memory_region_is_ram(&vmem->memdev->mr) || + memory_region_is_rom(&vmem->memdev->mr) || + !vmem->memdev->mr.ram_block) { + error_setg(errp, "'%s' property specifies an unsupported memdev", + VIRTIO_MEM_MEMDEV_PROP); + return; + } + + if ((nb_numa_nodes && vmem->node >= nb_numa_nodes) || + (!nb_numa_nodes && vmem->node)) { + error_setg(errp, "'%s' property has value '%" PRIu32 "', which exceeds" + "the number of numa nodes: %d", VIRTIO_MEM_NODE_PROP, + vmem->node, nb_numa_nodes ? nb_numa_nodes : 1); + return; + } + + if (enable_mlock) { + error_setg(errp, "Incompatible with mlock"); + return; + } + + rb = vmem->memdev->mr.ram_block; + page_size = qemu_ram_pagesize(rb); + + /* + * If the block size wasn't configured by the user, use a sane default. This + * allows using hugetlbfs backends of any page size without manual + * intervention. + */ + if (!vmem->block_size) { + vmem->block_size = virtio_mem_default_block_size(rb); + } + + if (vmem->block_size < page_size) { + error_setg(errp, "'%s' property has to be at least the page size (0x%" + PRIx64 ")", VIRTIO_MEM_BLOCK_SIZE_PROP, page_size); + return; + } else if (vmem->block_size < virtio_mem_default_block_size(rb)) { + warn_report("'%s' property is smaller than the default block size (%" + PRIx64 " MiB)", VIRTIO_MEM_BLOCK_SIZE_PROP, + virtio_mem_default_block_size(rb) / MiB); + } else if (!QEMU_IS_ALIGNED(vmem->requested_size, vmem->block_size)) { + error_setg(errp, "'%s' property has to be multiples of '%s' (0x%" PRIx64 + ")", VIRTIO_MEM_REQUESTED_SIZE_PROP, + VIRTIO_MEM_BLOCK_SIZE_PROP, vmem->block_size); + return; + } else if (!QEMU_IS_ALIGNED(vmem->addr, vmem->block_size)) { + error_setg(errp, "'%s' property has to be multiples of '%s' (0x%" PRIx64 + ")", VIRTIO_MEM_ADDR_PROP, VIRTIO_MEM_BLOCK_SIZE_PROP, + vmem->block_size); + return; + } else if (!QEMU_IS_ALIGNED(memory_region_size(&vmem->memdev->mr), + vmem->block_size)) { + error_setg(errp, "'%s' property memdev size has to be multiples of" + "'%s' (0x%" PRIx64 ")", VIRTIO_MEM_MEMDEV_PROP, + VIRTIO_MEM_BLOCK_SIZE_PROP, vmem->block_size); + return; + } + + if (ram_block_discard_require(true)) { + error_setg(errp, "Discarding RAM is disabled"); + return; + } + + ret = ram_block_discard_range(rb, 0, qemu_ram_get_used_length(rb)); + if (ret) { + error_setg_errno(errp, -ret, "Unexpected error discarding RAM"); + ram_block_discard_require(false); + return; + } + + virtio_mem_resize_usable_region(vmem, vmem->requested_size, true); + + vmem->bitmap_size = memory_region_size(&vmem->memdev->mr) / + vmem->block_size; + vmem->bitmap = bitmap_new(vmem->bitmap_size); + + virtio_init(vdev, TYPE_VIRTIO_MEM, VIRTIO_ID_MEM, + sizeof(struct virtio_mem_config)); + vmem->vq = virtio_add_queue(vdev, 128, virtio_mem_handle_request); + + host_memory_backend_set_mapped(vmem->memdev, true); + vmstate_register_ram(&vmem->memdev->mr, DEVICE(vmem)); + qemu_register_reset(virtio_mem_system_reset, vmem); + precopy_add_notifier(&vmem->precopy_notifier); +} + +static void virtio_mem_device_unrealize(DeviceState *dev) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VirtIOMEM *vmem = VIRTIO_MEM(dev); + + precopy_remove_notifier(&vmem->precopy_notifier); + qemu_unregister_reset(virtio_mem_system_reset, vmem); + vmstate_unregister_ram(&vmem->memdev->mr, DEVICE(vmem)); + host_memory_backend_set_mapped(vmem->memdev, false); + virtio_del_queue(vdev, 0); + virtio_cleanup(vdev); + g_free(vmem->bitmap); + ram_block_discard_require(false); +} + +static int virtio_mem_restore_unplugged(VirtIOMEM *vmem) +{ + RAMBlock *rb = vmem->memdev->mr.ram_block; + unsigned long first_zero_bit, last_zero_bit; + uint64_t offset, length; + int ret; + + /* Find consecutive unplugged blocks and discard the consecutive range. */ + first_zero_bit = find_first_zero_bit(vmem->bitmap, vmem->bitmap_size); + while (first_zero_bit < vmem->bitmap_size) { + offset = first_zero_bit * vmem->block_size; + last_zero_bit = find_next_bit(vmem->bitmap, vmem->bitmap_size, + first_zero_bit + 1) - 1; + length = (last_zero_bit - first_zero_bit + 1) * vmem->block_size; + + ret = ram_block_discard_range(rb, offset, length); + if (ret) { + error_report("Unexpected error discarding RAM: %s", + strerror(-ret)); + return -EINVAL; + } + first_zero_bit = find_next_zero_bit(vmem->bitmap, vmem->bitmap_size, + last_zero_bit + 2); + } + return 0; +} + +static int virtio_mem_post_load(void *opaque, int version_id) +{ + if (migration_in_incoming_postcopy()) { + return 0; + } + + return virtio_mem_restore_unplugged(VIRTIO_MEM(opaque)); +} + +typedef struct VirtIOMEMMigSanityChecks { + VirtIOMEM *parent; + uint64_t addr; + uint64_t region_size; + uint64_t block_size; + uint32_t node; +} VirtIOMEMMigSanityChecks; + +static int virtio_mem_mig_sanity_checks_pre_save(void *opaque) +{ + VirtIOMEMMigSanityChecks *tmp = opaque; + VirtIOMEM *vmem = tmp->parent; + + tmp->addr = vmem->addr; + tmp->region_size = memory_region_size(&vmem->memdev->mr); + tmp->block_size = vmem->block_size; + tmp->node = vmem->node; + return 0; +} + +static int virtio_mem_mig_sanity_checks_post_load(void *opaque, int version_id) +{ + VirtIOMEMMigSanityChecks *tmp = opaque; + VirtIOMEM *vmem = tmp->parent; + const uint64_t new_region_size = memory_region_size(&vmem->memdev->mr); + + if (tmp->addr != vmem->addr) { + error_report("Property '%s' changed from 0x%" PRIx64 " to 0x%" PRIx64, + VIRTIO_MEM_ADDR_PROP, tmp->addr, vmem->addr); + return -EINVAL; + } + /* + * Note: Preparation for resizeable memory regions. The maximum size + * of the memory region must not change during migration. + */ + if (tmp->region_size != new_region_size) { + error_report("Property '%s' size changed from 0x%" PRIx64 " to 0x%" + PRIx64, VIRTIO_MEM_MEMDEV_PROP, tmp->region_size, + new_region_size); + return -EINVAL; + } + if (tmp->block_size != vmem->block_size) { + error_report("Property '%s' changed from 0x%" PRIx64 " to 0x%" PRIx64, + VIRTIO_MEM_BLOCK_SIZE_PROP, tmp->block_size, + vmem->block_size); + return -EINVAL; + } + if (tmp->node != vmem->node) { + error_report("Property '%s' changed from %" PRIu32 " to %" PRIu32, + VIRTIO_MEM_NODE_PROP, tmp->node, vmem->node); + return -EINVAL; + } + return 0; +} + +static const VMStateDescription vmstate_virtio_mem_sanity_checks = { + .name = "virtio-mem-device/sanity-checks", + .pre_save = virtio_mem_mig_sanity_checks_pre_save, + .post_load = virtio_mem_mig_sanity_checks_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT64(addr, VirtIOMEMMigSanityChecks), + VMSTATE_UINT64(region_size, VirtIOMEMMigSanityChecks), + VMSTATE_UINT64(block_size, VirtIOMEMMigSanityChecks), + VMSTATE_UINT32(node, VirtIOMEMMigSanityChecks), + VMSTATE_END_OF_LIST(), + }, +}; + +static const VMStateDescription vmstate_virtio_mem_device = { + .name = "virtio-mem-device", + .minimum_version_id = 1, + .version_id = 1, + .post_load = virtio_mem_post_load, + .fields = (VMStateField[]) { + VMSTATE_WITH_TMP(VirtIOMEM, VirtIOMEMMigSanityChecks, + vmstate_virtio_mem_sanity_checks), + VMSTATE_UINT64(usable_region_size, VirtIOMEM), + VMSTATE_UINT64(size, VirtIOMEM), + VMSTATE_UINT64(requested_size, VirtIOMEM), + VMSTATE_BITMAP(bitmap, VirtIOMEM, 0, bitmap_size), + VMSTATE_END_OF_LIST() + }, +}; + +static const VMStateDescription vmstate_virtio_mem = { + .name = "virtio-mem", + .minimum_version_id = 1, + .version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_VIRTIO_DEVICE, + VMSTATE_END_OF_LIST() + }, +}; + +static void virtio_mem_fill_device_info(const VirtIOMEM *vmem, + VirtioMEMDeviceInfo *vi) +{ + vi->memaddr = vmem->addr; + vi->node = vmem->node; + vi->requested_size = vmem->requested_size; + vi->size = vmem->size; + vi->max_size = memory_region_size(&vmem->memdev->mr); + vi->block_size = vmem->block_size; + vi->memdev = object_get_canonical_path(OBJECT(vmem->memdev)); +} + +static MemoryRegion *virtio_mem_get_memory_region(VirtIOMEM *vmem, Error **errp) +{ + if (!vmem->memdev) { + error_setg(errp, "'%s' property must be set", VIRTIO_MEM_MEMDEV_PROP); + return NULL; + } + + return &vmem->memdev->mr; +} + +static void virtio_mem_add_size_change_notifier(VirtIOMEM *vmem, + Notifier *notifier) +{ + notifier_list_add(&vmem->size_change_notifiers, notifier); +} + +static void virtio_mem_remove_size_change_notifier(VirtIOMEM *vmem, + Notifier *notifier) +{ + notifier_remove(notifier); +} + +static void virtio_mem_get_size(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + const VirtIOMEM *vmem = VIRTIO_MEM(obj); + uint64_t value = vmem->size; + + visit_type_size(v, name, &value, errp); +} + +static void virtio_mem_get_requested_size(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + const VirtIOMEM *vmem = VIRTIO_MEM(obj); + uint64_t value = vmem->requested_size; + + visit_type_size(v, name, &value, errp); +} + +static void virtio_mem_set_requested_size(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + VirtIOMEM *vmem = VIRTIO_MEM(obj); + Error *err = NULL; + uint64_t value; + + visit_type_size(v, name, &value, &err); + if (err) { + error_propagate(errp, err); + return; + } + + /* + * The block size and memory backend are not fixed until the device was + * realized. realize() will verify these properties then. + */ + if (DEVICE(obj)->realized) { + if (!QEMU_IS_ALIGNED(value, vmem->block_size)) { + error_setg(errp, "'%s' has to be multiples of '%s' (0x%" PRIx64 + ")", name, VIRTIO_MEM_BLOCK_SIZE_PROP, + vmem->block_size); + return; + } else if (value > memory_region_size(&vmem->memdev->mr)) { + error_setg(errp, "'%s' cannot exceed the memory backend size" + "(0x%" PRIx64 ")", name, + memory_region_size(&vmem->memdev->mr)); + return; + } + + if (value != vmem->requested_size) { + virtio_mem_resize_usable_region(vmem, value, false); + vmem->requested_size = value; + } + /* + * Trigger a config update so the guest gets notified. We trigger + * even if the size didn't change (especially helpful for debugging). + */ + virtio_notify_config(VIRTIO_DEVICE(vmem)); + } else { + vmem->requested_size = value; + } +} + +static void virtio_mem_get_block_size(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + const VirtIOMEM *vmem = VIRTIO_MEM(obj); + uint64_t value = vmem->block_size; + + /* + * If not configured by the user (and we're not realized yet), use the + * default block size we would use with the current memory backend. + */ + if (!value) { + if (vmem->memdev && memory_region_is_ram(&vmem->memdev->mr)) { + value = virtio_mem_default_block_size(vmem->memdev->mr.ram_block); + } else { + value = virtio_mem_thp_size(); + } + } + + visit_type_size(v, name, &value, errp); +} + +static void virtio_mem_set_block_size(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + VirtIOMEM *vmem = VIRTIO_MEM(obj); + Error *err = NULL; + uint64_t value; + + if (DEVICE(obj)->realized) { + error_setg(errp, "'%s' cannot be changed", name); + return; + } + + visit_type_size(v, name, &value, &err); + if (err) { + error_propagate(errp, err); + return; + } + + if (value < VIRTIO_MEM_MIN_BLOCK_SIZE) { + error_setg(errp, "'%s' property has to be at least 0x%" PRIx32, name, + VIRTIO_MEM_MIN_BLOCK_SIZE); + return; + } else if (!is_power_of_2(value)) { + error_setg(errp, "'%s' property has to be a power of two", name); + return; + } + vmem->block_size = value; +} + +static void virtio_mem_precopy_exclude_unplugged(VirtIOMEM *vmem) +{ + void * const host = qemu_ram_get_host_addr(vmem->memdev->mr.ram_block); + unsigned long first_zero_bit, last_zero_bit; + uint64_t offset, length; + + /* + * Find consecutive unplugged blocks and exclude them from migration. + * + * Note: Blocks cannot get (un)plugged during precopy, no locking needed. + */ + first_zero_bit = find_first_zero_bit(vmem->bitmap, vmem->bitmap_size); + while (first_zero_bit < vmem->bitmap_size) { + offset = first_zero_bit * vmem->block_size; + last_zero_bit = find_next_bit(vmem->bitmap, vmem->bitmap_size, + first_zero_bit + 1) - 1; + length = (last_zero_bit - first_zero_bit + 1) * vmem->block_size; + + qemu_guest_free_page_hint(host + offset, length); + first_zero_bit = find_next_zero_bit(vmem->bitmap, vmem->bitmap_size, + last_zero_bit + 2); + } +} + +static int virtio_mem_precopy_notify(NotifierWithReturn *n, void *data) +{ + VirtIOMEM *vmem = container_of(n, VirtIOMEM, precopy_notifier); + PrecopyNotifyData *pnd = data; + + switch (pnd->reason) { + case PRECOPY_NOTIFY_SETUP: + precopy_enable_free_page_optimization(); + break; + case PRECOPY_NOTIFY_AFTER_BITMAP_SYNC: + virtio_mem_precopy_exclude_unplugged(vmem); + break; + default: + break; + } + + return 0; +} + +static void virtio_mem_instance_init(Object *obj) +{ + VirtIOMEM *vmem = VIRTIO_MEM(obj); + + notifier_list_init(&vmem->size_change_notifiers); + vmem->precopy_notifier.notify = virtio_mem_precopy_notify; + + object_property_add(obj, VIRTIO_MEM_SIZE_PROP, "size", virtio_mem_get_size, + NULL, NULL, NULL); + object_property_add(obj, VIRTIO_MEM_REQUESTED_SIZE_PROP, "size", + virtio_mem_get_requested_size, + virtio_mem_set_requested_size, NULL, NULL); + object_property_add(obj, VIRTIO_MEM_BLOCK_SIZE_PROP, "size", + virtio_mem_get_block_size, virtio_mem_set_block_size, + NULL, NULL); +} + +static Property virtio_mem_properties[] = { + DEFINE_PROP_UINT64(VIRTIO_MEM_ADDR_PROP, VirtIOMEM, addr, 0), + DEFINE_PROP_UINT32(VIRTIO_MEM_NODE_PROP, VirtIOMEM, node, 0), + DEFINE_PROP_LINK(VIRTIO_MEM_MEMDEV_PROP, VirtIOMEM, memdev, + TYPE_MEMORY_BACKEND, HostMemoryBackend *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void virtio_mem_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + VirtIOMEMClass *vmc = VIRTIO_MEM_CLASS(klass); + + device_class_set_props(dc, virtio_mem_properties); + dc->vmsd = &vmstate_virtio_mem; + + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + vdc->realize = virtio_mem_device_realize; + vdc->unrealize = virtio_mem_device_unrealize; + vdc->get_config = virtio_mem_get_config; + vdc->get_features = virtio_mem_get_features; + vdc->vmsd = &vmstate_virtio_mem_device; + + vmc->fill_device_info = virtio_mem_fill_device_info; + vmc->get_memory_region = virtio_mem_get_memory_region; + vmc->add_size_change_notifier = virtio_mem_add_size_change_notifier; + vmc->remove_size_change_notifier = virtio_mem_remove_size_change_notifier; +} + +static const TypeInfo virtio_mem_info = { + .name = TYPE_VIRTIO_MEM, + .parent = TYPE_VIRTIO_DEVICE, + .instance_size = sizeof(VirtIOMEM), + .instance_init = virtio_mem_instance_init, + .class_init = virtio_mem_class_init, + .class_size = sizeof(VirtIOMEMClass), +}; + +static void virtio_register_types(void) +{ + type_register_static(&virtio_mem_info); +} + +type_init(virtio_register_types) diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c index f12d1595aa1bd8455a4bb9062b71bd7fadefeeb4..e1b5c3b81e37e28a9e32c48f52085e082d024af7 100644 --- a/hw/virtio/virtio-mmio.c +++ b/hw/virtio/virtio-mmio.c @@ -179,7 +179,7 @@ static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size) } return proxy->vqs[vdev->queue_sel].enabled; case VIRTIO_MMIO_INTERRUPT_STATUS: - return atomic_read(&vdev->isr); + return qatomic_read(&vdev->isr); case VIRTIO_MMIO_STATUS: return vdev->status; case VIRTIO_MMIO_CONFIG_GENERATION: @@ -370,7 +370,7 @@ static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value, } break; case VIRTIO_MMIO_INTERRUPT_ACK: - atomic_and(&vdev->isr, ~value); + qatomic_and(&vdev->isr, ~value); virtio_update_irq(vdev); break; case VIRTIO_MMIO_STATUS: @@ -496,7 +496,7 @@ static void virtio_mmio_update_irq(DeviceState *opaque, uint16_t vector) if (!vdev) { return; } - level = (atomic_read(&vdev->isr) != 0); + level = (qatomic_read(&vdev->isr) != 0); trace_virtio_mmio_setting_irq(level); qemu_set_irq(proxy->irq, level); } diff --git a/hw/virtio/virtio-net-pci.c b/hw/virtio/virtio-net-pci.c index ea43040f7bae12d1c3ee6aae4cc449b9aabf3466..292d13d27815537e559ad997748533f17ff41ad1 100644 --- a/hw/virtio/virtio-net-pci.c +++ b/hw/virtio/virtio-net-pci.c @@ -22,6 +22,7 @@ #include "virtio-pci.h" #include "qapi/error.h" #include "qemu/module.h" +#include "qom/object.h" typedef struct VirtIONetPCI VirtIONetPCI; @@ -29,8 +30,8 @@ typedef struct VirtIONetPCI VirtIONetPCI; * virtio-net-pci: This extends VirtioPCIProxy. */ #define TYPE_VIRTIO_NET_PCI "virtio-net-pci-base" -#define VIRTIO_NET_PCI(obj) \ - OBJECT_CHECK(VirtIONetPCI, (obj), TYPE_VIRTIO_NET_PCI) +DECLARE_INSTANCE_CHECKER(VirtIONetPCI, VIRTIO_NET_PCI, + TYPE_VIRTIO_NET_PCI) struct VirtIONetPCI { VirtIOPCIProxy parent_obj; @@ -52,8 +53,7 @@ static void virtio_net_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) virtio_net_set_netclient_name(&dev->vdev, qdev->id, object_get_typename(OBJECT(qdev))); - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); } static void virtio_net_pci_class_init(ObjectClass *klass, void *data) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index d028c17c240ebf8e141f4eb2dac0af9bc5958b88..36524a5728e40da961b4db8625585837ff5009ef 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -19,6 +19,7 @@ #include "exec/memop.h" #include "standard-headers/linux/virtio_pci.h" +#include "hw/boards.h" #include "hw/virtio/virtio.h" #include "migration/qemu-file-types.h" #include "hw/pci/pci.h" @@ -71,7 +72,7 @@ static void virtio_pci_notify(DeviceState *d, uint16_t vector) msix_notify(&proxy->pci_dev, vector); else { VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - pci_set_irq(&proxy->pci_dev, atomic_read(&vdev->isr) & 1); + pci_set_irq(&proxy->pci_dev, qatomic_read(&vdev->isr) & 1); } } @@ -397,7 +398,7 @@ static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr) break; case VIRTIO_PCI_ISR: /* reading from the ISR also clears it. */ - ret = atomic_xchg(&vdev->isr, 0); + ret = qatomic_xchg(&vdev->isr, 0); pci_irq_deassert(&proxy->pci_dev); break; case VIRTIO_MSI_CONFIG_VECTOR: @@ -1107,6 +1108,18 @@ static AddressSpace *virtio_pci_get_dma_as(DeviceState *d) return pci_get_address_space(dev); } +static bool virtio_pci_queue_enabled(DeviceState *d, int n) +{ + VirtIOPCIProxy *proxy = VIRTIO_PCI(d); + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + + if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) { + return proxy->vqs[n].enabled; + } + + return virtio_queue_enabled_legacy(vdev, n); +} + static int virtio_pci_add_mem_cap(VirtIOPCIProxy *proxy, struct virtio_pci_cap *cap) { @@ -1273,16 +1286,20 @@ static void virtio_pci_common_write(void *opaque, hwaddr addr, virtio_queue_set_vector(vdev, vdev->queue_sel, val); break; case VIRTIO_PCI_COMMON_Q_ENABLE: - virtio_queue_set_num(vdev, vdev->queue_sel, - proxy->vqs[vdev->queue_sel].num); - virtio_queue_set_rings(vdev, vdev->queue_sel, + if (val == 1) { + virtio_queue_set_num(vdev, vdev->queue_sel, + proxy->vqs[vdev->queue_sel].num); + virtio_queue_set_rings(vdev, vdev->queue_sel, ((uint64_t)proxy->vqs[vdev->queue_sel].desc[1]) << 32 | proxy->vqs[vdev->queue_sel].desc[0], ((uint64_t)proxy->vqs[vdev->queue_sel].avail[1]) << 32 | proxy->vqs[vdev->queue_sel].avail[0], ((uint64_t)proxy->vqs[vdev->queue_sel].used[1]) << 32 | proxy->vqs[vdev->queue_sel].used[0]); - proxy->vqs[vdev->queue_sel].enabled = 1; + proxy->vqs[vdev->queue_sel].enabled = 1; + } else { + virtio_error(vdev, "wrong value for queue_enable %"PRIx64, val); + } break; case VIRTIO_PCI_COMMON_Q_DESCLO: proxy->vqs[vdev->queue_sel].desc[0] = val; @@ -1317,11 +1334,12 @@ static uint64_t virtio_pci_notify_read(void *opaque, hwaddr addr, static void virtio_pci_notify_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { - VirtIODevice *vdev = opaque; - VirtIOPCIProxy *proxy = VIRTIO_PCI(DEVICE(vdev)->parent_bus->parent); + VirtIOPCIProxy *proxy = opaque; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + unsigned queue = addr / virtio_pci_queue_mem_mult(proxy); - if (queue < VIRTIO_QUEUE_MAX) { + if (vdev != NULL && queue < VIRTIO_QUEUE_MAX) { virtio_queue_notify(vdev, queue); } } @@ -1329,10 +1347,12 @@ static void virtio_pci_notify_write(void *opaque, hwaddr addr, static void virtio_pci_notify_write_pio(void *opaque, hwaddr addr, uint64_t val, unsigned size) { - VirtIODevice *vdev = opaque; + VirtIOPCIProxy *proxy = opaque; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + unsigned queue = val; - if (queue < VIRTIO_QUEUE_MAX) { + if (vdev != NULL && queue < VIRTIO_QUEUE_MAX) { virtio_queue_notify(vdev, queue); } } @@ -1342,7 +1362,7 @@ static uint64_t virtio_pci_isr_read(void *opaque, hwaddr addr, { VirtIOPCIProxy *proxy = opaque; VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - uint64_t val = atomic_xchg(&vdev->isr, 0); + uint64_t val = qatomic_xchg(&vdev->isr, 0); pci_irq_deassert(&proxy->pci_dev); return val; @@ -1356,9 +1376,14 @@ static void virtio_pci_isr_write(void *opaque, hwaddr addr, static uint64_t virtio_pci_device_read(void *opaque, hwaddr addr, unsigned size) { - VirtIODevice *vdev = opaque; + VirtIOPCIProxy *proxy = opaque; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); uint64_t val = 0; + if (vdev == NULL) { + return val; + } + switch (size) { case 1: val = virtio_config_modern_readb(vdev, addr); @@ -1376,7 +1401,13 @@ static uint64_t virtio_pci_device_read(void *opaque, hwaddr addr, static void virtio_pci_device_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { - VirtIODevice *vdev = opaque; + VirtIOPCIProxy *proxy = opaque; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + + if (vdev == NULL) { + return; + } + switch (size) { case 1: virtio_config_modern_writeb(vdev, addr, val); @@ -1453,19 +1484,19 @@ static void virtio_pci_modern_regions_init(VirtIOPCIProxy *proxy) memory_region_init_io(&proxy->device.mr, OBJECT(proxy), &device_ops, - virtio_bus_get_device(&proxy->bus), + proxy, "virtio-pci-device", proxy->device.size); memory_region_init_io(&proxy->notify.mr, OBJECT(proxy), ¬ify_ops, - virtio_bus_get_device(&proxy->bus), + proxy, "virtio-pci-notify", proxy->notify.size); memory_region_init_io(&proxy->notify_pio.mr, OBJECT(proxy), ¬ify_pio_ops, - virtio_bus_get_device(&proxy->bus), + proxy, "virtio-pci-notify-pio", proxy->notify_pio.size); } @@ -1565,6 +1596,20 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) } if (legacy) { + if (!virtio_legacy_allowed(vdev)) { + /* + * To avoid migration issues, we allow legacy mode when legacy + * check is disabled in the old machine types (< 5.1). + */ + if (virtio_legacy_check_disabled(vdev)) { + warn_report("device is modern-only, but for backward " + "compatibility legacy is allowed"); + } else { + error_setg(errp, + "device is modern-only, use disable-legacy=on"); + return; + } + } if (virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) { error_setg(errp, "VIRTIO_F_IOMMU_PLATFORM was supported by" " neither legacy nor transitional device"); @@ -2024,6 +2069,37 @@ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t) g_free(base_name); } +unsigned virtio_pci_optimal_num_queues(unsigned fixed_queues) +{ + /* + * 1:1 vq to vCPU mapping is ideal because the same vCPU that submitted + * virtqueue buffers can handle their completion. When a different vCPU + * handles completion it may need to IPI the vCPU that submitted the + * request and this adds overhead. + * + * Virtqueues consume guest RAM and MSI-X vectors. This is wasteful in + * guests with very many vCPUs and a device that is only used by a few + * vCPUs. Unfortunately optimizing that case requires manual pinning inside + * the guest, so those users might as well manually set the number of + * queues. There is no upper limit that can be applied automatically and + * doing so arbitrarily would result in a sudden performance drop once the + * threshold number of vCPUs is exceeded. + */ + unsigned num_queues = current_machine->smp.cpus; + + /* + * The maximum number of MSI-X vectors is PCI_MSIX_FLAGS_QSIZE + 1, but the + * config change interrupt and the fixed virtqueues must be taken into + * account too. + */ + num_queues = MIN(num_queues, PCI_MSIX_FLAGS_QSIZE - fixed_queues); + + /* + * There is a limit to how many virtqueues a device can have. + */ + return MIN(num_queues, VIRTIO_QUEUE_MAX - fixed_queues); +} + /* virtio-pci-bus */ static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, @@ -2060,12 +2136,14 @@ static void virtio_pci_bus_class_init(ObjectClass *klass, void *data) k->ioeventfd_enabled = virtio_pci_ioeventfd_enabled; k->ioeventfd_assign = virtio_pci_ioeventfd_assign; k->get_dma_as = virtio_pci_get_dma_as; + k->queue_enabled = virtio_pci_queue_enabled; } static const TypeInfo virtio_pci_bus_info = { .name = TYPE_VIRTIO_PCI_BUS, .parent = TYPE_VIRTIO_BUS, .instance_size = sizeof(VirtioPCIBusState), + .class_size = sizeof(VirtioPCIBusClass), .class_init = virtio_pci_bus_class_init, }; diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index e2eaaa9182e42ce1ed6ccf371e2d556c744dc5b0..06e2af12de64c32f8c26c7f9e8585d09ce8838f3 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -17,8 +17,8 @@ #include "hw/pci/msi.h" #include "hw/virtio/virtio-bus.h" +#include "qom/object.h" -typedef struct VirtIOPCIProxy VirtIOPCIProxy; /* virtio-pci-bus */ @@ -26,12 +26,8 @@ typedef struct VirtioBusState VirtioPCIBusState; typedef struct VirtioBusClass VirtioPCIBusClass; #define TYPE_VIRTIO_PCI_BUS "virtio-pci-bus" -#define VIRTIO_PCI_BUS(obj) \ - OBJECT_CHECK(VirtioPCIBusState, (obj), TYPE_VIRTIO_PCI_BUS) -#define VIRTIO_PCI_BUS_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtioPCIBusClass, obj, TYPE_VIRTIO_PCI_BUS) -#define VIRTIO_PCI_BUS_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtioPCIBusClass, klass, TYPE_VIRTIO_PCI_BUS) +DECLARE_OBJ_CHECKERS(VirtioPCIBusState, VirtioPCIBusClass, + VIRTIO_PCI_BUS, TYPE_VIRTIO_PCI_BUS) enum { VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION_BIT, @@ -94,18 +90,13 @@ typedef struct { * virtio-pci: This is the PCIDevice which has a virtio-pci-bus. */ #define TYPE_VIRTIO_PCI "virtio-pci" -#define VIRTIO_PCI_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtioPCIClass, obj, TYPE_VIRTIO_PCI) -#define VIRTIO_PCI_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtioPCIClass, klass, TYPE_VIRTIO_PCI) -#define VIRTIO_PCI(obj) \ - OBJECT_CHECK(VirtIOPCIProxy, (obj), TYPE_VIRTIO_PCI) - -typedef struct VirtioPCIClass { +OBJECT_DECLARE_TYPE(VirtIOPCIProxy, VirtioPCIClass, VIRTIO_PCI) + +struct VirtioPCIClass { PCIDeviceClass parent_class; DeviceRealize parent_dc_realize; void (*realize)(VirtIOPCIProxy *vpci_dev, Error **errp); -} VirtioPCIClass; +}; typedef struct VirtIOPCIRegion { MemoryRegion mr; @@ -243,4 +234,13 @@ typedef struct VirtioPCIDeviceTypeInfo { /* Register virtio-pci type(s). @t must be static. */ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t); +/** + * virtio_pci_optimal_num_queues: + * @fixed_queues: number of queues that are always present + * + * Returns: The optimal number of queues for a multi-queue device, excluding + * @fixed_queues. + */ +unsigned virtio_pci_optimal_num_queues(unsigned fixed_queues); + #endif diff --git a/hw/virtio/virtio-pmem-pci.c b/hw/virtio/virtio-pmem-pci.c index fe2af00fa1652a7ee9ff20de8d0c757c75d8d712..2b2a0b1eae1006ef89e9f098a7154ffffe2328da 100644 --- a/hw/virtio/virtio-pmem-pci.c +++ b/hw/virtio/virtio-pmem-pci.c @@ -22,14 +22,14 @@ static void virtio_pmem_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) VirtIOPMEMPCI *pmem_pci = VIRTIO_PMEM_PCI(vpci_dev); DeviceState *vdev = DEVICE(&pmem_pci->vdev); - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + virtio_pci_force_virtio_1(vpci_dev); + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); } static void virtio_pmem_pci_set_addr(MemoryDeviceState *md, uint64_t addr, Error **errp) { - object_property_set_uint(OBJECT(md), addr, VIRTIO_PMEM_ADDR_PROP, errp); + object_property_set_uint(OBJECT(md), VIRTIO_PMEM_ADDR_PROP, addr, errp); } static uint64_t virtio_pmem_pci_get_addr(const MemoryDeviceState *md) diff --git a/hw/virtio/virtio-pmem-pci.h b/hw/virtio/virtio-pmem-pci.h index 616abef093ee6e644a4e7aecde0fb452aff1ac86..63cfe727f781937256402d5e9d098b97b670f53c 100644 --- a/hw/virtio/virtio-pmem-pci.h +++ b/hw/virtio/virtio-pmem-pci.h @@ -16,6 +16,7 @@ #include "hw/virtio/virtio-pci.h" #include "hw/virtio/virtio-pmem.h" +#include "qom/object.h" typedef struct VirtIOPMEMPCI VirtIOPMEMPCI; @@ -23,8 +24,8 @@ typedef struct VirtIOPMEMPCI VirtIOPMEMPCI; * virtio-pmem-pci: This extends VirtioPCIProxy. */ #define TYPE_VIRTIO_PMEM_PCI "virtio-pmem-pci-base" -#define VIRTIO_PMEM_PCI(obj) \ - OBJECT_CHECK(VirtIOPMEMPCI, (obj), TYPE_VIRTIO_PMEM_PCI) +DECLARE_INSTANCE_CHECKER(VirtIOPMEMPCI, VIRTIO_PMEM_PCI, + TYPE_VIRTIO_PMEM_PCI) struct VirtIOPMEMPCI { VirtIOPCIProxy parent_obj; diff --git a/hw/virtio/virtio-pmem.c b/hw/virtio/virtio-pmem.c index c3374b2f3fe2803483955603fe51aa36faf245c2..ddb0125901ece4a21640a5592f45defaa52b8702 100644 --- a/hw/virtio/virtio-pmem.c +++ b/hw/virtio/virtio-pmem.c @@ -77,6 +77,7 @@ static void virtio_pmem_flush(VirtIODevice *vdev, VirtQueue *vq) if (req_data->elem.out_num < 1 || req_data->elem.in_num < 1) { virtio_error(vdev, "virtio-pmem request not proper"); + virtqueue_detach_element(vq, (VirtQueueElement *)req_data, 0); g_free(req_data); return; } @@ -112,9 +113,8 @@ static void virtio_pmem_realize(DeviceState *dev, Error **errp) } if (host_memory_backend_is_mapped(pmem->memdev)) { - char *path = object_get_canonical_path_component(OBJECT(pmem->memdev)); - error_setg(errp, "can't use already busy memdev: %s", path); - g_free(path); + error_setg(errp, "can't use already busy memdev: %s", + object_get_canonical_path_component(OBJECT(pmem->memdev))); return; } diff --git a/hw/virtio/virtio-rng-pci.c b/hw/virtio/virtio-rng-pci.c index 8aaf54b781d6545d0597912f29f4977c9870572a..c1f916268be7138443c988d8a08b0ff3edbdba38 100644 --- a/hw/virtio/virtio-rng-pci.c +++ b/hw/virtio/virtio-rng-pci.c @@ -15,6 +15,7 @@ #include "hw/virtio/virtio-rng.h" #include "qapi/error.h" #include "qemu/module.h" +#include "qom/object.h" typedef struct VirtIORngPCI VirtIORngPCI; @@ -22,8 +23,8 @@ typedef struct VirtIORngPCI VirtIORngPCI; * virtio-rng-pci: This extends VirtioPCIProxy. */ #define TYPE_VIRTIO_RNG_PCI "virtio-rng-pci-base" -#define VIRTIO_RNG_PCI(obj) \ - OBJECT_CHECK(VirtIORngPCI, (obj), TYPE_VIRTIO_RNG_PCI) +DECLARE_INSTANCE_CHECKER(VirtIORngPCI, VIRTIO_RNG_PCI, + TYPE_VIRTIO_RNG_PCI) struct VirtIORngPCI { VirtIOPCIProxy parent_obj; @@ -34,18 +35,10 @@ static void virtio_rng_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) { VirtIORngPCI *vrng = VIRTIO_RNG_PCI(vpci_dev); DeviceState *vdev = DEVICE(&vrng->vdev); - Error *err = NULL; - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", &err); - if (err) { - error_propagate(errp, err); + if (!qdev_realize(vdev, BUS(&vpci_dev->bus), errp)) { return; } - - object_property_set_link(OBJECT(vrng), - OBJECT(vrng->vdev.conf.rng), "rng", - NULL); } static void virtio_rng_pci_class_init(ObjectClass *klass, void *data) diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c index a8df41b11b5de7ad433d791462494e86af72ae85..2886c0ce2a6f17c2adbcbd677a81bdbb3a025c07 100644 --- a/hw/virtio/virtio-rng.c +++ b/hw/virtio/virtio-rng.c @@ -176,7 +176,6 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIORNG *vrng = VIRTIO_RNG(dev); - Error *local_err = NULL; if (vrng->conf.period_ms <= 0) { error_setg(errp, "'period' parameter expects a positive integer"); @@ -194,10 +193,8 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp) if (vrng->conf.rng == NULL) { Object *default_backend = object_new(TYPE_RNG_BUILTIN); - user_creatable_complete(USER_CREATABLE(default_backend), - &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!user_creatable_complete(USER_CREATABLE(default_backend), + errp)) { object_unref(default_backend); return; } @@ -208,8 +205,8 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp) /* The child property took a reference, we can safely drop ours now */ object_unref(default_backend); - object_property_set_link(OBJECT(dev), default_backend, - "rng", &error_abort); + object_property_set_link(OBJECT(dev), "rng", default_backend, + &error_abort); } vrng->rng = vrng->conf.rng; diff --git a/hw/virtio/virtio-scsi-pci.c b/hw/virtio/virtio-scsi-pci.c index e82e7e5680eefae0041274097e7c49e89bda5148..97fab742368ac4c4332e4f3f6f1da1153468f488 100644 --- a/hw/virtio/virtio-scsi-pci.c +++ b/hw/virtio/virtio-scsi-pci.c @@ -19,6 +19,7 @@ #include "hw/virtio/virtio-scsi.h" #include "qemu/module.h" #include "virtio-pci.h" +#include "qom/object.h" typedef struct VirtIOSCSIPCI VirtIOSCSIPCI; @@ -26,8 +27,8 @@ typedef struct VirtIOSCSIPCI VirtIOSCSIPCI; * virtio-scsi-pci: This extends VirtioPCIProxy. */ #define TYPE_VIRTIO_SCSI_PCI "virtio-scsi-pci-base" -#define VIRTIO_SCSI_PCI(obj) \ - OBJECT_CHECK(VirtIOSCSIPCI, (obj), TYPE_VIRTIO_SCSI_PCI) +DECLARE_INSTANCE_CHECKER(VirtIOSCSIPCI, VIRTIO_SCSI_PCI, + TYPE_VIRTIO_SCSI_PCI) struct VirtIOSCSIPCI { VirtIOPCIProxy parent_obj; @@ -46,12 +47,17 @@ static void virtio_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) { VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(vpci_dev); DeviceState *vdev = DEVICE(&dev->vdev); - VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev); DeviceState *proxy = DEVICE(vpci_dev); + VirtIOSCSIConf *conf = &dev->vdev.parent_obj.conf; char *bus_name; + if (conf->num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) { + conf->num_queues = + virtio_pci_optimal_num_queues(VIRTIO_SCSI_VQ_NUM_FIXED); + } + if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { - vpci_dev->nvectors = vs->conf.num_queues + 3; + vpci_dev->nvectors = conf->num_queues + VIRTIO_SCSI_VQ_NUM_FIXED + 1; } /* @@ -64,8 +70,7 @@ static void virtio_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) g_free(bus_name); } - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); } static void virtio_scsi_pci_class_init(ObjectClass *klass, void *data) diff --git a/hw/virtio/virtio-serial-pci.c b/hw/virtio/virtio-serial-pci.c index 22ab4d8562e57084137ce5749994f6cd9cc6f6d4..35bcd961c98822d2f3b925007f438833b845edb8 100644 --- a/hw/virtio/virtio-serial-pci.c +++ b/hw/virtio/virtio-serial-pci.c @@ -21,6 +21,7 @@ #include "hw/virtio/virtio-serial.h" #include "qemu/module.h" #include "virtio-pci.h" +#include "qom/object.h" typedef struct VirtIOSerialPCI VirtIOSerialPCI; @@ -28,8 +29,8 @@ typedef struct VirtIOSerialPCI VirtIOSerialPCI; * virtio-serial-pci: This extends VirtioPCIProxy. */ #define TYPE_VIRTIO_SERIAL_PCI "virtio-serial-pci-base" -#define VIRTIO_SERIAL_PCI(obj) \ - OBJECT_CHECK(VirtIOSerialPCI, (obj), TYPE_VIRTIO_SERIAL_PCI) +DECLARE_INSTANCE_CHECKER(VirtIOSerialPCI, VIRTIO_SERIAL_PCI, + TYPE_VIRTIO_SERIAL_PCI) struct VirtIOSerialPCI { VirtIOPCIProxy parent_obj; @@ -65,8 +66,7 @@ static void virtio_serial_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) g_free(bus_name); } - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); } static Property virtio_serial_pci_properties[] = { diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 850fcce5e794c5212c9bd6b1750f6c9aa514f1c3..ceb58fda6c1420db8f6724c9fa2305e768783dcb 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -17,6 +17,7 @@ #include "trace.h" #include "exec/address-spaces.h" #include "qemu/error-report.h" +#include "qemu/log.h" #include "qemu/main-loop.h" #include "qemu/module.h" #include "hw/virtio/virtio.h" @@ -27,6 +28,7 @@ #include "hw/virtio/virtio-access.h" #include "sysemu/dma.h" #include "sysemu/runstate.h" +#include "standard-headers/linux/virtio_ids.h" /* * The alignment to use between consumer and producer parts of vring. @@ -148,8 +150,8 @@ static void virtio_virtqueue_reset_region_cache(struct VirtQueue *vq) { VRingMemoryRegionCaches *caches; - caches = atomic_read(&vq->vring.caches); - atomic_rcu_set(&vq->vring.caches, NULL); + caches = qatomic_read(&vq->vring.caches); + qatomic_rcu_set(&vq->vring.caches, NULL); if (caches) { call_rcu(caches, virtio_free_region_cache, rcu); } @@ -196,7 +198,7 @@ static void virtio_init_region_cache(VirtIODevice *vdev, int n) goto err_avail; } - atomic_rcu_set(&vq->vring.caches, new); + qatomic_rcu_set(&vq->vring.caches, new); if (old) { call_rcu(old, virtio_free_region_cache, rcu); } @@ -282,7 +284,7 @@ static void vring_packed_flags_write(VirtIODevice *vdev, /* Called within rcu_read_lock(). */ static VRingMemoryRegionCaches *vring_get_region_caches(struct VirtQueue *vq) { - return atomic_rcu_read(&vq->vring.caches); + return qatomic_rcu_read(&vq->vring.caches); } /* Called within rcu_read_lock(). */ @@ -2006,7 +2008,7 @@ void virtio_reset(void *opaque) vdev->queue_sel = 0; vdev->status = 0; vdev->disabled = false; - atomic_set(&vdev->isr, 0); + qatomic_set(&vdev->isr, 0); vdev->config_vector = VIRTIO_NO_VECTOR; virtio_notify_vector(vdev, vdev->config_vector); @@ -2438,13 +2440,13 @@ void virtio_del_queue(VirtIODevice *vdev, int n) static void virtio_set_isr(VirtIODevice *vdev, int value) { - uint8_t old = atomic_read(&vdev->isr); + uint8_t old = qatomic_read(&vdev->isr); /* Do not write ISR if it does not change, so that its cacheline remains * shared in the common case where the guest does not read it. */ if ((old & value) != value) { - atomic_or(&vdev->isr, value); + qatomic_or(&vdev->isr, value); } } @@ -2962,17 +2964,16 @@ int virtio_set_features(VirtIODevice *vdev, uint64_t val) return -EINVAL; } ret = virtio_set_features_nocheck(vdev, val); - if (!ret) { - if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { - /* VIRTIO_RING_F_EVENT_IDX changes the size of the caches. */ - int i; - for (i = 0; i < VIRTIO_QUEUE_MAX; i++) { - if (vdev->vq[i].vring.num != 0) { - virtio_init_region_cache(vdev, i); - } + if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { + /* VIRTIO_RING_F_EVENT_IDX changes the size of the caches. */ + int i; + for (i = 0; i < VIRTIO_QUEUE_MAX; i++) { + if (vdev->vq[i].vring.num != 0) { + virtio_init_region_cache(vdev, i); } } - + } + if (!ret) { if (!virtio_device_started(vdev, vdev->status) && !virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) { vdev->start_on_kick = true; @@ -3160,12 +3161,12 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) nheads = vring_avail_idx(&vdev->vq[i]) - vdev->vq[i].last_avail_idx; /* Check it isn't doing strange things with descriptor numbers. */ if (nheads > vdev->vq[i].vring.num) { - error_report("VQ %d size 0x%x Guest index 0x%x " - "inconsistent with Host index 0x%x: delta 0x%x", - i, vdev->vq[i].vring.num, - vring_avail_idx(&vdev->vq[i]), - vdev->vq[i].last_avail_idx, nheads); - return -1; + qemu_log_mask(LOG_GUEST_ERROR, + "VQ %d size 0x%x Guest index 0x%x " + "inconsistent with Host index 0x%x: delta 0x%x", + i, vdev->vq[i].vring.num, + vring_avail_idx(&vdev->vq[i]), + vdev->vq[i].last_avail_idx, nheads); } vdev->vq[i].used_idx = vring_used_idx(&vdev->vq[i]); vdev->vq[i].shadow_avail_idx = vring_avail_idx(&vdev->vq[i]); @@ -3230,8 +3231,9 @@ void virtio_instance_init_common(Object *proxy_obj, void *data, { DeviceState *vdev = data; - object_initialize_child(proxy_obj, "virtio-backend", vdev, vdev_size, - vdev_name, &error_abort, NULL); + object_initialize_child_with_props(proxy_obj, "virtio-backend", vdev, + vdev_size, vdev_name, &error_abort, + NULL); qdev_alias_all_properties(vdev, proxy_obj); } @@ -3252,7 +3254,7 @@ void virtio_init(VirtIODevice *vdev, const char *name, vdev->started = false; vdev->device_id = device_id; vdev->status = 0; - atomic_set(&vdev->isr, 0); + qatomic_set(&vdev->isr, 0); vdev->queue_sel = 0; vdev->config_vector = VIRTIO_NO_VECTOR; vdev->vq = g_malloc0(sizeof(VirtQueue) * VIRTIO_QUEUE_MAX); @@ -3278,16 +3280,56 @@ void virtio_init(VirtIODevice *vdev, const char *name, vdev->use_guest_notifier_mask = true; } +/* + * Only devices that have already been around prior to defining the virtio + * standard support legacy mode; this includes devices not specified in the + * standard. All newer devices conform to the virtio standard only. + */ +bool virtio_legacy_allowed(VirtIODevice *vdev) +{ + switch (vdev->device_id) { + case VIRTIO_ID_NET: + case VIRTIO_ID_BLOCK: + case VIRTIO_ID_CONSOLE: + case VIRTIO_ID_RNG: + case VIRTIO_ID_BALLOON: + case VIRTIO_ID_RPMSG: + case VIRTIO_ID_SCSI: + case VIRTIO_ID_9P: + case VIRTIO_ID_RPROC_SERIAL: + case VIRTIO_ID_CAIF: + return true; + default: + return false; + } +} + +bool virtio_legacy_check_disabled(VirtIODevice *vdev) +{ + return vdev->disable_legacy_check; +} + hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n) { return vdev->vq[n].vring.desc; } -bool virtio_queue_enabled(VirtIODevice *vdev, int n) +bool virtio_queue_enabled_legacy(VirtIODevice *vdev, int n) { return virtio_queue_get_desc_addr(vdev, n) != 0; } +bool virtio_queue_enabled(VirtIODevice *vdev, int n) +{ + BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); + + if (k->queue_enabled) { + return k->queue_enabled(qbus->parent, n); + } + return virtio_queue_enabled_legacy(vdev, n); +} + hwaddr virtio_queue_get_avail_addr(VirtIODevice *vdev, int n) { return vdev->vq[n].vring.avail; @@ -3676,6 +3718,8 @@ static Property virtio_properties[] = { DEFINE_VIRTIO_COMMON_FEATURES(VirtIODevice, host_features), DEFINE_PROP_BOOL("use-started", VirtIODevice, use_started, true), DEFINE_PROP_BOOL("use-disabled-flag", VirtIODevice, use_disabled_flag, true), + DEFINE_PROP_BOOL("x-disable-legacy-check", VirtIODevice, + disable_legacy_check, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/watchdog/Kconfig b/hw/watchdog/Kconfig index 293209b291d6140c72756d0ee4c97954349fe2f1..66e1d029e32ef9747ddcdcedfda30b9b9a3afaa3 100644 --- a/hw/watchdog/Kconfig +++ b/hw/watchdog/Kconfig @@ -17,3 +17,6 @@ config WDT_DIAG288 config WDT_IMX2 bool + +config WDT_SBSA + bool diff --git a/hw/watchdog/Makefile.objs b/hw/watchdog/Makefile.objs deleted file mode 100644 index 631b711d86818bde467100dfffd678bde0c7bb91..0000000000000000000000000000000000000000 --- a/hw/watchdog/Makefile.objs +++ /dev/null @@ -1,7 +0,0 @@ -common-obj-y += watchdog.o -common-obj-$(CONFIG_CMSDK_APB_WATCHDOG) += cmsdk-apb-watchdog.o -common-obj-$(CONFIG_WDT_IB6300ESB) += wdt_i6300esb.o -common-obj-$(CONFIG_WDT_IB700) += wdt_ib700.o -common-obj-$(CONFIG_WDT_DIAG288) += wdt_diag288.o -common-obj-$(CONFIG_ASPEED_SOC) += wdt_aspeed.o -common-obj-$(CONFIG_WDT_IMX2) += wdt_imx2.o diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c index 1541365914ecaa078a25ad5c6a8d9c94ec9c03b2..5bbadadfa68dddc765f017248c77938cd9675ae3 100644 --- a/hw/watchdog/cmsdk-apb-watchdog.c +++ b/hw/watchdog/cmsdk-apb-watchdog.c @@ -225,6 +225,7 @@ static void cmsdk_apb_watchdog_write(void *opaque, hwaddr offset, break; case A_WDOGLOCK: s->lock = (value != WDOG_UNLOCK_VALUE); + trace_cmsdk_apb_watchdog_lock(s->lock); break; case A_WDOGITCR: if (s->is_luminary) { diff --git a/hw/watchdog/meson.build b/hw/watchdog/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..054c403dea7c138d3343fe652a8e0812b5cd9c75 --- /dev/null +++ b/hw/watchdog/meson.build @@ -0,0 +1,8 @@ +softmmu_ss.add(files('watchdog.c')) +softmmu_ss.add(when: 'CONFIG_CMSDK_APB_WATCHDOG', if_true: files('cmsdk-apb-watchdog.c')) +softmmu_ss.add(when: 'CONFIG_WDT_IB6300ESB', if_true: files('wdt_i6300esb.c')) +softmmu_ss.add(when: 'CONFIG_WDT_IB700', if_true: files('wdt_ib700.c')) +softmmu_ss.add(when: 'CONFIG_WDT_DIAG288', if_true: files('wdt_diag288.c')) +softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('wdt_aspeed.c')) +softmmu_ss.add(when: 'CONFIG_WDT_IMX2', if_true: files('wdt_imx2.c')) +softmmu_ss.add(when: 'CONFIG_WDT_SBSA', if_true: files('sbsa_gwdt.c')) diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c new file mode 100644 index 0000000000000000000000000000000000000000..d0998f8489cb665a4d3da98abb3085455fa1e44c --- /dev/null +++ b/hw/watchdog/sbsa_gwdt.c @@ -0,0 +1,293 @@ +/* + * Generic watchdog device model for SBSA + * + * The watchdog device has been implemented as revision 1 variant of + * the ARM SBSA specification v6.0 + * (https://developer.arm.com/documentation/den0029/d?lang=en) + * + * Copyright Linaro.org 2020 + * + * Authors: + * Shashi Mallela + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version. See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "sysemu/reset.h" +#include "sysemu/watchdog.h" +#include "hw/watchdog/sbsa_gwdt.h" +#include "qemu/timer.h" +#include "migration/vmstate.h" +#include "qemu/log.h" +#include "qemu/module.h" + +static WatchdogTimerModel model = { + .wdt_name = TYPE_WDT_SBSA, + .wdt_description = "SBSA-compliant generic watchdog device", +}; + +static const VMStateDescription vmstate_sbsa_gwdt = { + .name = "sbsa-gwdt", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_TIMER_PTR(timer, SBSA_GWDTState), + VMSTATE_UINT32(wcs, SBSA_GWDTState), + VMSTATE_UINT32(worl, SBSA_GWDTState), + VMSTATE_UINT32(woru, SBSA_GWDTState), + VMSTATE_UINT32(wcvl, SBSA_GWDTState), + VMSTATE_UINT32(wcvu, SBSA_GWDTState), + VMSTATE_END_OF_LIST() + } +}; + +typedef enum WdtRefreshType { + EXPLICIT_REFRESH = 0, + TIMEOUT_REFRESH = 1, +} WdtRefreshType; + +static uint64_t sbsa_gwdt_rread(void *opaque, hwaddr addr, unsigned int size) +{ + SBSA_GWDTState *s = SBSA_GWDT(opaque); + uint32_t ret = 0; + + switch (addr) { + case SBSA_GWDT_WRR: + /* watch refresh read has no effect and returns 0 */ + ret = 0; + break; + case SBSA_GWDT_W_IIDR: + ret = s->id; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "bad address in refresh frame read :" + " 0x%x\n", (int)addr); + } + return ret; +} + +static uint64_t sbsa_gwdt_read(void *opaque, hwaddr addr, unsigned int size) +{ + SBSA_GWDTState *s = SBSA_GWDT(opaque); + uint32_t ret = 0; + + switch (addr) { + case SBSA_GWDT_WCS: + ret = s->wcs; + break; + case SBSA_GWDT_WOR: + ret = s->worl; + break; + case SBSA_GWDT_WORU: + ret = s->woru; + break; + case SBSA_GWDT_WCV: + ret = s->wcvl; + break; + case SBSA_GWDT_WCVU: + ret = s->wcvu; + break; + case SBSA_GWDT_W_IIDR: + ret = s->id; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "bad address in control frame read :" + " 0x%x\n", (int)addr); + } + return ret; +} + +static void sbsa_gwdt_update_timer(SBSA_GWDTState *s, WdtRefreshType rtype) +{ + uint64_t timeout = 0; + + timer_del(s->timer); + + if (s->wcs & SBSA_GWDT_WCS_EN) { + /* + * Extract the upper 16 bits from woru & 32 bits from worl + * registers to construct the 48 bit offset value + */ + timeout = s->woru; + timeout <<= 32; + timeout |= s->worl; + timeout = muldiv64(timeout, NANOSECONDS_PER_SECOND, SBSA_TIMER_FREQ); + timeout += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + + if ((rtype == EXPLICIT_REFRESH) || ((rtype == TIMEOUT_REFRESH) && + (!(s->wcs & SBSA_GWDT_WCS_WS0)))) { + /* store the current timeout value into compare registers */ + s->wcvu = timeout >> 32; + s->wcvl = timeout; + } + timer_mod(s->timer, timeout); + } +} + +static void sbsa_gwdt_rwrite(void *opaque, hwaddr offset, uint64_t data, + unsigned size) { + SBSA_GWDTState *s = SBSA_GWDT(opaque); + + if (offset == SBSA_GWDT_WRR) { + s->wcs &= ~(SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_WS1); + + sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH); + } else { + qemu_log_mask(LOG_GUEST_ERROR, "bad address in refresh frame write :" + " 0x%x\n", (int)offset); + } +} + +static void sbsa_gwdt_write(void *opaque, hwaddr offset, uint64_t data, + unsigned size) { + SBSA_GWDTState *s = SBSA_GWDT(opaque); + + switch (offset) { + case SBSA_GWDT_WCS: + s->wcs = data & SBSA_GWDT_WCS_EN; + qemu_set_irq(s->irq, 0); + sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH); + break; + + case SBSA_GWDT_WOR: + s->worl = data; + s->wcs &= ~(SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_WS1); + qemu_set_irq(s->irq, 0); + sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH); + break; + + case SBSA_GWDT_WORU: + s->woru = data & SBSA_GWDT_WOR_MASK; + s->wcs &= ~(SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_WS1); + qemu_set_irq(s->irq, 0); + sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH); + break; + + case SBSA_GWDT_WCV: + s->wcvl = data; + break; + + case SBSA_GWDT_WCVU: + s->wcvu = data; + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, "bad address in control frame write :" + " 0x%x\n", (int)offset); + } + return; +} + +static void wdt_sbsa_gwdt_reset(DeviceState *dev) +{ + SBSA_GWDTState *s = SBSA_GWDT(dev); + + timer_del(s->timer); + + s->wcs = 0; + s->wcvl = 0; + s->wcvu = 0; + s->worl = 0; + s->woru = 0; + s->id = SBSA_GWDT_ID; +} + +static void sbsa_gwdt_timer_sysinterrupt(void *opaque) +{ + SBSA_GWDTState *s = SBSA_GWDT(opaque); + + if (!(s->wcs & SBSA_GWDT_WCS_WS0)) { + s->wcs |= SBSA_GWDT_WCS_WS0; + sbsa_gwdt_update_timer(s, TIMEOUT_REFRESH); + qemu_set_irq(s->irq, 1); + } else { + s->wcs |= SBSA_GWDT_WCS_WS1; + qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n"); + /* + * Reset the watchdog only if the guest gets notified about + * expiry. watchdog_perform_action() may temporarily relinquish + * the BQL; reset before triggering the action to avoid races with + * sbsa_gwdt instructions. + */ + switch (get_watchdog_action()) { + case WATCHDOG_ACTION_DEBUG: + case WATCHDOG_ACTION_NONE: + case WATCHDOG_ACTION_PAUSE: + break; + default: + wdt_sbsa_gwdt_reset(DEVICE(s)); + } + watchdog_perform_action(); + } +} + +static const MemoryRegionOps sbsa_gwdt_rops = { + .read = sbsa_gwdt_rread, + .write = sbsa_gwdt_rwrite, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .valid.unaligned = false, +}; + +static const MemoryRegionOps sbsa_gwdt_ops = { + .read = sbsa_gwdt_read, + .write = sbsa_gwdt_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .valid.unaligned = false, +}; + +static void wdt_sbsa_gwdt_realize(DeviceState *dev, Error **errp) +{ + SBSA_GWDTState *s = SBSA_GWDT(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + + memory_region_init_io(&s->rmmio, OBJECT(dev), + &sbsa_gwdt_rops, s, + "sbsa_gwdt.refresh", + SBSA_GWDT_RMMIO_SIZE); + + memory_region_init_io(&s->cmmio, OBJECT(dev), + &sbsa_gwdt_ops, s, + "sbsa_gwdt.control", + SBSA_GWDT_CMMIO_SIZE); + + sysbus_init_mmio(sbd, &s->rmmio); + sysbus_init_mmio(sbd, &s->cmmio); + + sysbus_init_irq(sbd, &s->irq); + + s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sbsa_gwdt_timer_sysinterrupt, + dev); +} + +static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = wdt_sbsa_gwdt_realize; + dc->reset = wdt_sbsa_gwdt_reset; + dc->hotpluggable = false; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + dc->vmsd = &vmstate_sbsa_gwdt; +} + +static const TypeInfo wdt_sbsa_gwdt_info = { + .class_init = wdt_sbsa_gwdt_class_init, + .parent = TYPE_SYS_BUS_DEVICE, + .name = TYPE_WDT_SBSA, + .instance_size = sizeof(SBSA_GWDTState), +}; + +static void wdt_sbsa_gwdt_register_types(void) +{ + watchdog_add_model(&model); + type_register_static(&wdt_sbsa_gwdt_info); +} + +type_init(wdt_sbsa_gwdt_register_types) diff --git a/hw/watchdog/trace-events b/hw/watchdog/trace-events index ab94d7df502695bb8d55687a6e11f56cf8347e84..3124ca1f1b6c9ba30b2a23aa0eb200f3e96dd6eb 100644 --- a/hw/watchdog/trace-events +++ b/hw/watchdog/trace-events @@ -4,3 +4,4 @@ cmsdk_apb_watchdog_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB watchdog read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" cmsdk_apb_watchdog_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB watchdog write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" cmsdk_apb_watchdog_reset(void) "CMSDK APB watchdog: reset" +cmsdk_apb_watchdog_lock(uint32_t lock) "CMSDK APB watchdog: lock %" PRIu32 diff --git a/hw/watchdog/trace.h b/hw/watchdog/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..5d8495752bdaa6607e9b29a035cbeec7405e3711 --- /dev/null +++ b/hw/watchdog/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_watchdog.h" diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c index 370cf92e856368b4d4331ffcd46b08922cfa8170..502f45a9399ae424e7ac3ab3111e02852c07903f 100644 --- a/hw/watchdog/wdt_i6300esb.c +++ b/hw/watchdog/wdt_i6300esb.c @@ -26,6 +26,7 @@ #include "sysemu/watchdog.h" #include "hw/pci/pci.h" #include "migration/vmstate.h" +#include "qom/object.h" /*#define I6300ESB_DEBUG 1*/ @@ -101,11 +102,9 @@ struct I6300State { */ }; -typedef struct I6300State I6300State; #define TYPE_WATCHDOG_I6300ESB_DEVICE "i6300esb" -#define WATCHDOG_I6300ESB_DEVICE(obj) \ - OBJECT_CHECK(I6300State, (obj), TYPE_WATCHDOG_I6300ESB_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(I6300State, WATCHDOG_I6300ESB_DEVICE) /* This function is called when the watchdog has either been enabled * (hence it starts counting down) or has been keep-alived. diff --git a/hw/watchdog/wdt_ib700.c b/hw/watchdog/wdt_ib700.c index 985944a84a6c78d5a4e051ce782709e91e2bd6df..177aaa503f9b2d589c8e1f035713d434876a4939 100644 --- a/hw/watchdog/wdt_ib700.c +++ b/hw/watchdog/wdt_ib700.c @@ -25,6 +25,7 @@ #include "sysemu/watchdog.h" #include "hw/isa/isa.h" #include "migration/vmstate.h" +#include "qom/object.h" /*#define IB700_DEBUG 1*/ @@ -36,15 +37,17 @@ #endif #define TYPE_IB700 "ib700" -#define IB700(obj) OBJECT_CHECK(IB700State, (obj), TYPE_IB700) +typedef struct IB700state IB700State; +DECLARE_INSTANCE_CHECKER(IB700State, IB700, + TYPE_IB700) -typedef struct IB700state { +struct IB700state { ISADevice parent_obj; QEMUTimer *timer; PortioList port_list; -} IB700State; +}; /* This is the timer. We use a global here because the watchdog * code ensures there is only one watchdog (it is located at a fixed, diff --git a/hw/xen/Makefile.objs b/hw/xen/Makefile.objs deleted file mode 100644 index 84df60a9281a261b4f19ac54d30419c3621f0677..0000000000000000000000000000000000000000 --- a/hw/xen/Makefile.objs +++ /dev/null @@ -1,6 +0,0 @@ -# xen backend driver support -common-obj-$(CONFIG_XEN) += xen-legacy-backend.o xen_devconfig.o xen_pvdev.o xen-common.o xen-bus.o xen-bus-helper.o xen-backend.o - -obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o -obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_graphics.o xen_pt_msi.o -obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt_load_rom.o diff --git a/hw/xen/meson.build b/hw/xen/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..076954b89ca337a426702bf6128531abb87a69b6 --- /dev/null +++ b/hw/xen/meson.build @@ -0,0 +1,20 @@ +softmmu_ss.add(when: ['CONFIG_XEN', xen], if_true: files( + 'xen-backend.c', + 'xen-bus-helper.c', + 'xen-bus.c', + 'xen-legacy-backend.c', + 'xen_devconfig.c', + 'xen_pvdev.c', +)) + +xen_specific_ss = ss.source_set() +xen_specific_ss.add(when: 'CONFIG_XEN_PCI_PASSTHROUGH', if_true: files( + 'xen-host-pci-device.c', + 'xen_pt.c', + 'xen_pt_config_init.c', + 'xen_pt_graphics.c', + 'xen_pt_load_rom.c', + 'xen_pt_msi.c', +), if_false: files('xen_pt_stub.c')) + +specific_ss.add_all(when: ['CONFIG_XEN', xen], if_true: xen_specific_ss) diff --git a/hw/xen/trace.h b/hw/xen/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..adba31a13670076192c1125a965fa5b20432b226 --- /dev/null +++ b/hw/xen/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_xen.h" diff --git a/hw/xen/xen-backend.c b/hw/xen/xen-backend.c index da065f81b736e40ec65e8c9d3f2721fed786db75..5b0fb76eaeb38106f35ceac2830b1375f434b81e 100644 --- a/hw/xen/xen-backend.c +++ b/hw/xen/xen-backend.c @@ -41,6 +41,12 @@ static void xen_backend_table_add(XenBackendImpl *impl) g_hash_table_insert(xen_backend_table_get(), (void *)impl->type, impl); } +static const char **xen_backend_table_keys(unsigned int *count) +{ + return (const char **)g_hash_table_get_keys_as_array( + xen_backend_table_get(), count); +} + static const XenBackendImpl *xen_backend_table_lookup(const char *type) { return g_hash_table_lookup(xen_backend_table_get(), type); @@ -70,6 +76,11 @@ void xen_backend_register(const XenBackendInfo *info) xen_backend_table_add(impl); } +const char **xen_backend_get_types(unsigned int *count) +{ + return xen_backend_table_keys(count); +} + static QLIST_HEAD(, XenBackendInstance) backend_list; static void xen_backend_list_add(XenBackendInstance *backend) @@ -98,9 +109,9 @@ static void xen_backend_list_remove(XenBackendInstance *backend) void xen_backend_device_create(XenBus *xenbus, const char *type, const char *name, QDict *opts, Error **errp) { + ERRP_GUARD(); const XenBackendImpl *impl = xen_backend_table_lookup(type); XenBackendInstance *backend; - Error *local_error = NULL; if (!impl) { return; @@ -110,9 +121,8 @@ void xen_backend_device_create(XenBus *xenbus, const char *type, backend->xenbus = xenbus; backend->name = g_strdup(name); - impl->create(backend, opts, &local_error); - if (local_error) { - error_propagate(errp, local_error); + impl->create(backend, opts, errp); + if (*errp) { g_free(backend->name); g_free(backend); return; diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c index 32dd4461bebd8db1d88dba9578ac2075d843b0bb..8c588920d9fca99346e18a90ce66bb4a103c26cb 100644 --- a/hw/xen/xen-bus.c +++ b/hw/xen/xen-bus.c @@ -53,9 +53,9 @@ static char *xen_device_get_frontend_path(XenDevice *xendev) static void xen_device_unplug(XenDevice *xendev, Error **errp) { + ERRP_GUARD(); XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); const char *type = object_get_typename(OBJECT(xendev)); - Error *local_err = NULL; xs_transaction_t tid; trace_xen_device_unplug(type, xendev->name); @@ -69,14 +69,14 @@ again: } xs_node_printf(xenbus->xsh, tid, xendev->backend_path, "online", - &local_err, "%u", 0); - if (local_err) { + errp, "%u", 0); + if (*errp) { goto abort; } xs_node_printf(xenbus->xsh, tid, xendev->backend_path, "state", - &local_err, "%u", XenbusStateClosing); - if (local_err) { + errp, "%u", XenbusStateClosing); + if (*errp) { goto abort; } @@ -96,7 +96,6 @@ abort: * from ending the transaction. */ xs_transaction_end(xenbus->xsh, tid, true); - error_propagate(errp, local_err); } static void xen_bus_print_dev(Monitor *mon, DeviceState *dev, int indent) @@ -205,15 +204,13 @@ static XenWatch *watch_list_add(XenWatchList *watch_list, const char *node, const char *key, XenWatchHandler handler, void *opaque, Error **errp) { + ERRP_GUARD(); XenWatch *watch = new_watch(node, key, handler, opaque); - Error *local_err = NULL; notifier_list_add(&watch_list->notifiers, &watch->notifier); - xs_node_watch(watch_list->xsh, node, key, watch->token, &local_err); - if (local_err) { - error_propagate(errp, local_err); - + xs_node_watch(watch_list->xsh, node, key, watch->token, errp); + if (*errp) { notifier_remove(&watch->notifier); free_watch(watch); @@ -255,11 +252,11 @@ static void xen_bus_backend_create(XenBus *xenbus, const char *type, const char *name, char *path, Error **errp) { + ERRP_GUARD(); xs_transaction_t tid; char **key; QDict *opts; unsigned int i, n; - Error *local_err = NULL; trace_xen_bus_backend_create(type, path); @@ -314,13 +311,11 @@ again: return; } - xen_backend_device_create(xenbus, type, name, opts, &local_err); + xen_backend_device_create(xenbus, type, name, opts, errp); qobject_unref(opts); - if (local_err) { - error_propagate_prepend(errp, local_err, - "failed to create '%s' device '%s': ", - type, name); + if (*errp) { + error_prepend(errp, "failed to create '%s' device '%s': ", type, name); } } @@ -435,7 +430,15 @@ static void xen_bus_unrealize(BusState *bus) trace_xen_bus_unrealize(); if (xenbus->backend_watch) { - xen_bus_remove_watch(xenbus, xenbus->backend_watch, NULL); + unsigned int i; + + for (i = 0; i < xenbus->backend_types; i++) { + if (xenbus->backend_watch[i]) { + xen_bus_remove_watch(xenbus, xenbus->backend_watch[i], NULL); + } + } + + g_free(xenbus->backend_watch); xenbus->backend_watch = NULL; } @@ -451,8 +454,11 @@ static void xen_bus_unrealize(BusState *bus) static void xen_bus_realize(BusState *bus, Error **errp) { + char *key = g_strdup_printf("%u", xen_domid); XenBus *xenbus = XEN_BUS(bus); unsigned int domid; + const char **type; + unsigned int i; Error *local_err = NULL; trace_xen_bus_realize(); @@ -474,19 +480,32 @@ static void xen_bus_realize(BusState *bus, Error **errp) module_call_init(MODULE_INIT_XEN_BACKEND); - xenbus->backend_watch = - xen_bus_add_watch(xenbus, "", /* domain root node */ - "backend", xen_bus_backend_changed, &local_err); - if (local_err) { - /* This need not be treated as a hard error so don't propagate */ - error_reportf_err(local_err, - "failed to set up enumeration watch: "); + type = xen_backend_get_types(&xenbus->backend_types); + xenbus->backend_watch = g_new(XenWatch *, xenbus->backend_types); + + for (i = 0; i < xenbus->backend_types; i++) { + char *node = g_strdup_printf("backend/%s", type[i]); + + xenbus->backend_watch[i] = + xen_bus_add_watch(xenbus, node, key, xen_bus_backend_changed, + &local_err); + if (local_err) { + /* This need not be treated as a hard error so don't propagate */ + error_reportf_err(local_err, + "failed to set up '%s' enumeration watch: ", + type[i]); + } + + g_free(node); } + g_free(type); + g_free(key); return; fail: xen_bus_unrealize(bus); + g_free(key); } static void xen_bus_unplug_request(HotplugHandler *hotplug, @@ -692,9 +711,9 @@ static void xen_device_remove_watch(XenDevice *xendev, XenWatch *watch, static void xen_device_backend_create(XenDevice *xendev, Error **errp) { + ERRP_GUARD(); XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); struct xs_permissions perms[2]; - Error *local_err = NULL; xendev->backend_path = xen_device_get_backend_path(xendev); @@ -706,30 +725,27 @@ static void xen_device_backend_create(XenDevice *xendev, Error **errp) g_assert(xenbus->xsh); xs_node_create(xenbus->xsh, XBT_NULL, xendev->backend_path, perms, - ARRAY_SIZE(perms), &local_err); - if (local_err) { - error_propagate_prepend(errp, local_err, - "failed to create backend: "); + ARRAY_SIZE(perms), errp); + if (*errp) { + error_prepend(errp, "failed to create backend: "); return; } xendev->backend_state_watch = xen_device_add_watch(xendev, xendev->backend_path, "state", xen_device_backend_changed, - &local_err); - if (local_err) { - error_propagate_prepend(errp, local_err, - "failed to watch backend state: "); + errp); + if (*errp) { + error_prepend(errp, "failed to watch backend state: "); return; } xendev->backend_online_watch = xen_device_add_watch(xendev, xendev->backend_path, "online", xen_device_backend_changed, - &local_err); - if (local_err) { - error_propagate_prepend(errp, local_err, - "failed to watch backend online: "); + errp); + if (*errp) { + error_prepend(errp, "failed to watch backend online: "); return; } } @@ -866,9 +882,9 @@ static bool xen_device_frontend_exists(XenDevice *xendev) static void xen_device_frontend_create(XenDevice *xendev, Error **errp) { + ERRP_GUARD(); XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); struct xs_permissions perms[2]; - Error *local_err = NULL; xendev->frontend_path = xen_device_get_frontend_path(xendev); @@ -885,20 +901,18 @@ static void xen_device_frontend_create(XenDevice *xendev, Error **errp) g_assert(xenbus->xsh); xs_node_create(xenbus->xsh, XBT_NULL, xendev->frontend_path, perms, - ARRAY_SIZE(perms), &local_err); - if (local_err) { - error_propagate_prepend(errp, local_err, - "failed to create frontend: "); + ARRAY_SIZE(perms), errp); + if (*errp) { + error_prepend(errp, "failed to create frontend: "); return; } } xendev->frontend_state_watch = xen_device_add_watch(xendev, xendev->frontend_path, "state", - xen_device_frontend_changed, &local_err); - if (local_err) { - error_propagate_prepend(errp, local_err, - "failed to watch frontend state: "); + xen_device_frontend_changed, errp); + if (*errp) { + error_prepend(errp, "failed to watch frontend state: "); } } @@ -1247,11 +1261,11 @@ static void xen_device_exit(Notifier *n, void *data) static void xen_device_realize(DeviceState *dev, Error **errp) { + ERRP_GUARD(); XenDevice *xendev = XEN_DEVICE(dev); XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev); XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); const char *type = object_get_typename(OBJECT(xendev)); - Error *local_err = NULL; if (xendev->frontend_id == DOMID_INVALID) { xendev->frontend_id = xen_domid; @@ -1267,10 +1281,9 @@ static void xen_device_realize(DeviceState *dev, Error **errp) goto unrealize; } - xendev->name = xendev_class->get_name(xendev, &local_err); - if (local_err) { - error_propagate_prepend(errp, local_err, - "failed to get device name: "); + xendev->name = xendev_class->get_name(xendev, errp); + if (*errp) { + error_prepend(errp, "failed to get device name: "); goto unrealize; } @@ -1293,22 +1306,19 @@ static void xen_device_realize(DeviceState *dev, Error **errp) xendev->feature_grant_copy = (xengnttab_grant_copy(xendev->xgth, 0, NULL) == 0); - xen_device_backend_create(xendev, &local_err); - if (local_err) { - error_propagate(errp, local_err); + xen_device_backend_create(xendev, errp); + if (*errp) { goto unrealize; } - xen_device_frontend_create(xendev, &local_err); - if (local_err) { - error_propagate(errp, local_err); + xen_device_frontend_create(xendev, errp); + if (*errp) { goto unrealize; } if (xendev_class->realize) { - xendev_class->realize(xendev, &local_err); - if (local_err) { - error_propagate(errp, local_err); + xendev_class->realize(xendev, errp); + if (*errp) { goto unrealize; } } @@ -1387,9 +1397,9 @@ type_init(xen_register_types) void xen_bus_init(void) { - DeviceState *dev = qdev_create(NULL, TYPE_XEN_BRIDGE); + DeviceState *dev = qdev_new(TYPE_XEN_BRIDGE); BusState *bus = qbus_create(TYPE_XEN_BUS, dev, NULL); - qdev_init_nofail(dev); - qbus_set_bus_hotplug_handler(bus, &error_abort); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + qbus_set_bus_hotplug_handler(bus); } diff --git a/hw/xen/xen-host-pci-device.c b/hw/xen/xen-host-pci-device.c index 1b44dcafaf44788af81cd807bf39e3f3b6b917b8..8c6e9a1716a2e0a3dd52ed1c531517be65ecec30 100644 --- a/hw/xen/xen-host-pci-device.c +++ b/hw/xen/xen-host-pci-device.c @@ -333,8 +333,8 @@ void xen_host_pci_device_get(XenHostPCIDevice *d, uint16_t domain, uint8_t bus, uint8_t dev, uint8_t func, Error **errp) { + ERRP_GUARD(); unsigned int v; - Error *err = NULL; d->config_fd = -1; d->domain = domain; @@ -342,36 +342,36 @@ void xen_host_pci_device_get(XenHostPCIDevice *d, uint16_t domain, d->dev = dev; d->func = func; - xen_host_pci_config_open(d, &err); - if (err) { + xen_host_pci_config_open(d, errp); + if (*errp) { goto error; } - xen_host_pci_get_resource(d, &err); - if (err) { + xen_host_pci_get_resource(d, errp); + if (*errp) { goto error; } - xen_host_pci_get_hex_value(d, "vendor", &v, &err); - if (err) { + xen_host_pci_get_hex_value(d, "vendor", &v, errp); + if (*errp) { goto error; } d->vendor_id = v; - xen_host_pci_get_hex_value(d, "device", &v, &err); - if (err) { + xen_host_pci_get_hex_value(d, "device", &v, errp); + if (*errp) { goto error; } d->device_id = v; - xen_host_pci_get_dec_value(d, "irq", &v, &err); - if (err) { + xen_host_pci_get_dec_value(d, "irq", &v, errp); + if (*errp) { goto error; } d->irq = v; - xen_host_pci_get_hex_value(d, "class", &v, &err); - if (err) { + xen_host_pci_get_hex_value(d, "class", &v, errp); + if (*errp) { goto error; } d->class_code = v; @@ -381,7 +381,6 @@ void xen_host_pci_device_get(XenHostPCIDevice *d, uint16_t domain, return; error: - error_propagate(errp, err); if (d->config_fd >= 0) { close(d->config_fd); diff --git a/hw/xen/xen-legacy-backend.c b/hw/xen/xen-legacy-backend.c index f9d013811a2e56a9f4589bf85460e2a359dea533..b61a4855b7b80c29000b96ed54b03e3813a0e05b 100644 --- a/hw/xen/xen-legacy-backend.c +++ b/hw/xen/xen-legacy-backend.c @@ -23,7 +23,6 @@ */ #include "qemu/osdep.h" -#include #include "hw/sysbus.h" #include "hw/boards.h" @@ -278,9 +277,8 @@ static struct XenLegacyDevice *xen_be_get_xendev(const char *type, int dom, xendev = g_malloc0(ops->size); object_initialize(&xendev->qdev, ops->size, TYPE_XENBACKEND); OBJECT(xendev)->free = g_free; - qdev_set_parent_bus(DEVICE(xendev), xen_sysbus); qdev_set_id(DEVICE(xendev), g_strdup_printf("xen-%s-%d", type, dev)); - qdev_init_nofail(DEVICE(xendev)); + qdev_realize(DEVICE(xendev), xen_sysbus, &error_fatal); object_unref(OBJECT(xendev)); xendev->type = type; @@ -703,10 +701,10 @@ int xen_be_init(void) xengnttab_close(gnttabdev); } - xen_sysdev = qdev_create(NULL, TYPE_XENSYSDEV); - qdev_init_nofail(xen_sysdev); + xen_sysdev = qdev_new(TYPE_XENSYSDEV); + sysbus_realize_and_unref(SYS_BUS_DEVICE(xen_sysdev), &error_fatal); xen_sysbus = qbus_create(TYPE_XENSYSBUS, xen_sysdev, "xen-sysbus"); - qbus_set_bus_hotplug_handler(xen_sysbus, &error_abort); + qbus_set_bus_hotplug_handler(xen_sysbus); return 0; @@ -790,11 +788,12 @@ static void xendev_class_init(ObjectClass *klass, void *data) set_bit(DEVICE_CATEGORY_MISC, dc->categories); /* xen-backend devices can be plugged/unplugged dynamically */ dc->user_creatable = true; + dc->bus_type = TYPE_XENSYSBUS; } static const TypeInfo xendev_type_info = { .name = TYPE_XENBACKEND, - .parent = TYPE_XENSYSDEV, + .parent = TYPE_DEVICE, .class_init = xendev_class_init, .instance_size = sizeof(struct XenLegacyDevice), }; @@ -825,7 +824,6 @@ static void xen_sysdev_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); device_class_set_props(dc, xen_sysdev_properties); - dc->bus_type = TYPE_XENSYSBUS; } static const TypeInfo xensysdev_info = { diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c index 81d5ad8da7f0519744b10db74fd270608015c85c..6d359ee486f579d7883e9d4b3829012210a5e4b7 100644 --- a/hw/xen/xen_pt.c +++ b/hw/xen/xen_pt.c @@ -65,7 +65,17 @@ #include "qemu/range.h" #include "exec/address-spaces.h" -bool has_igd_gfx_passthru; +static bool has_igd_gfx_passthru; + +bool xen_igd_gfx_pt_enabled(void) +{ + return has_igd_gfx_passthru; +} + +void xen_igd_gfx_pt_set(bool value, Error **errp) +{ + has_igd_gfx_passthru = value; +} #define XEN_PT_NR_IRQS (256) static uint8_t xen_pt_mapped_machine_irq[XEN_PT_NR_IRQS] = {0}; @@ -767,12 +777,12 @@ static void xen_pt_destroy(PCIDevice *d) { static void xen_pt_realize(PCIDevice *d, Error **errp) { + ERRP_GUARD(); XenPCIPassthroughState *s = XEN_PT_DEVICE(d); int i, rc = 0; uint8_t machine_irq = 0, scratch; uint16_t cmd = 0; int pirq = XEN_PT_UNASSIGNED_PIRQ; - Error *err = NULL; /* register real device */ XEN_PT_LOG(d, "Assigning real physical device %02x:%02x.%d" @@ -783,10 +793,9 @@ static void xen_pt_realize(PCIDevice *d, Error **errp) xen_host_pci_device_get(&s->real_device, s->hostaddr.domain, s->hostaddr.bus, s->hostaddr.slot, s->hostaddr.function, - &err); - if (err) { - error_append_hint(&err, "Failed to \"open\" the real pci device"); - error_propagate(errp, err); + errp); + if (*errp) { + error_append_hint(errp, "Failed to \"open\" the real pci device"); return; } @@ -813,11 +822,10 @@ static void xen_pt_realize(PCIDevice *d, Error **errp) return; } - xen_pt_setup_vga(s, &s->real_device, &err); - if (err) { - error_append_hint(&err, "Setup VGA BIOS of passthrough" - " GFX failed"); - error_propagate(errp, err); + xen_pt_setup_vga(s, &s->real_device, errp); + if (*errp) { + error_append_hint(errp, "Setup VGA BIOS of passthrough" + " GFX failed"); xen_host_pci_device_put(&s->real_device); return; } @@ -830,10 +838,9 @@ static void xen_pt_realize(PCIDevice *d, Error **errp) xen_pt_register_regions(s, &cmd); /* reinitialize each config register to be emulated */ - xen_pt_config_init(s, &err); - if (err) { - error_append_hint(&err, "PCI Config space initialisation failed"); - error_propagate(errp, err); + xen_pt_config_init(s, errp); + if (*errp) { + error_append_hint(errp, "PCI Config space initialisation failed"); rc = -1; goto err_out; } diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h index 179775db7b220796334bd0f964eb9b8b0747d80e..c74c4678f20dbe84ebda582fc89a56b4982ddc06 100644 --- a/hw/xen/xen_pt.h +++ b/hw/xen/xen_pt.h @@ -4,6 +4,10 @@ #include "hw/xen/xen_common.h" #include "hw/pci/pci.h" #include "xen-host-pci-device.h" +#include "qom/object.h" + +bool xen_igd_gfx_pt_enabled(void); +void xen_igd_gfx_pt_set(bool value, Error **errp); void xen_pt_log(const PCIDevice *d, const char *f, ...) GCC_FMT_ATTR(2, 3); @@ -33,11 +37,9 @@ void xen_pt_log(const PCIDevice *d, const char *f, ...) GCC_FMT_ATTR(2, 3); typedef const struct XenPTRegInfo XenPTRegInfo; typedef struct XenPTReg XenPTReg; -typedef struct XenPCIPassthroughState XenPCIPassthroughState; #define TYPE_XEN_PT_DEVICE "xen-pci-passthrough" -#define XEN_PT_DEVICE(obj) \ - OBJECT_CHECK(XenPCIPassthroughState, (obj), TYPE_XEN_PT_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(XenPCIPassthroughState, XEN_PT_DEVICE) uint32_t igd_read_opregion(XenPCIPassthroughState *s); void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val); @@ -322,10 +324,9 @@ extern void *pci_assign_dev_load_option_rom(PCIDevice *dev, unsigned int domain, unsigned int bus, unsigned int slot, unsigned int function); -extern bool has_igd_gfx_passthru; static inline bool is_igd_vga_passthrough(XenHostPCIDevice *dev) { - return (has_igd_gfx_passthru + return (xen_igd_gfx_pt_enabled() && ((dev->class_code >> 0x8) == PCI_CLASS_DISPLAY_VGA)); } int xen_pt_register_vga_regions(XenHostPCIDevice *dev); diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c index 31ec5add1d3460647bd7ccf1f334f22de3e4f715..c8724cc7c855660134367d98b45a8f18cd5ca433 100644 --- a/hw/xen/xen_pt_config_init.c +++ b/hw/xen/xen_pt_config_init.c @@ -2008,8 +2008,8 @@ static void xen_pt_config_reg_init(XenPCIPassthroughState *s, void xen_pt_config_init(XenPCIPassthroughState *s, Error **errp) { + ERRP_GUARD(); int i, rc; - Error *err = NULL; QLIST_INIT(&s->reg_grps); @@ -2052,10 +2052,9 @@ void xen_pt_config_init(XenPCIPassthroughState *s, Error **errp) reg_grp_offset, ®_grp_entry->size); if (rc < 0) { - error_setg(&err, "Failed to initialize %d/%zu, type = 0x%x," + error_setg(errp, "Failed to initialize %d/%zu, type = 0x%x," " rc: %d", i, ARRAY_SIZE(xen_pt_emu_reg_grps), xen_pt_emu_reg_grps[i].grp_type, rc); - error_propagate(errp, err); xen_pt_config_delete(s); return; } @@ -2068,13 +2067,14 @@ void xen_pt_config_init(XenPCIPassthroughState *s, Error **errp) /* initialize capability register */ for (j = 0; regs->size != 0; j++, regs++) { - xen_pt_config_reg_init(s, reg_grp_entry, regs, &err); - if (err) { - error_append_hint(&err, "Failed to init register %d" - " offsets 0x%x in grp_type = 0x%x (%d/%zu)", j, - regs->offset, xen_pt_emu_reg_grps[i].grp_type, - i, ARRAY_SIZE(xen_pt_emu_reg_grps)); - error_propagate(errp, err); + xen_pt_config_reg_init(s, reg_grp_entry, regs, errp); + if (*errp) { + error_append_hint(errp, "Failed to init register %d" + " offsets 0x%x in grp_type = 0x%x (%d/%zu)", + j, + regs->offset, + xen_pt_emu_reg_grps[i].grp_type, + i, ARRAY_SIZE(xen_pt_emu_reg_grps)); xen_pt_config_delete(s); return; } diff --git a/hw/xen/xen_pt_stub.c b/hw/xen/xen_pt_stub.c new file mode 100644 index 0000000000000000000000000000000000000000..2d8cac8d54b97a8ad03b0f2a45b11af8e774dcb2 --- /dev/null +++ b/hw/xen/xen_pt_stub.c @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2020 Citrix Systems UK Ltd. + * + * 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/xen/xen_pt.h" +#include "qapi/error.h" + +bool xen_igd_gfx_pt_enabled(void) +{ + return false; +} + +void xen_igd_gfx_pt_set(bool value, Error **errp) +{ + if (value) { + error_setg(errp, "Xen PCI passthrough support not built in"); + } +} diff --git a/hw/xen/xen_pvdev.c b/hw/xen/xen_pvdev.c index 43a336aabfce5356522fab7d5cf5b717e4b4acb4..8ab458922adcc643061caf56e0a06b810389c89c 100644 --- a/hw/xen/xen_pvdev.c +++ b/hw/xen/xen_pvdev.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/hw/xenpv/Makefile.objs b/hw/xenpv/Makefile.objs deleted file mode 100644 index 8bfa4586ab593a1bb21bd1184bf08c17f6bebc9c..0000000000000000000000000000000000000000 --- a/hw/xenpv/Makefile.objs +++ /dev/null @@ -1,2 +0,0 @@ -# Xen PV machine support -obj-$(CONFIG_XEN) += xen_machine_pv.o diff --git a/hw/xenpv/meson.build b/hw/xenpv/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..40f911ac15d90d5422d75a344bf08a497ca1000a --- /dev/null +++ b/hw/xenpv/meson.build @@ -0,0 +1,3 @@ +xenpv_ss = ss.source_set() + +xenpv_ss.add(when: 'CONFIG_XEN', if_true: files('xen_machine_pv.c')) diff --git a/hw/xtensa/Makefile.objs b/hw/xtensa/Makefile.objs deleted file mode 100644 index 2b40e1b60a0e3878c6e574e25da19646eefa29f2..0000000000000000000000000000000000000000 --- a/hw/xtensa/Makefile.objs +++ /dev/null @@ -1,6 +0,0 @@ -obj-y += mx_pic.o -obj-y += pic_cpu.o -obj-y += xtensa_memory.o -obj-$(CONFIG_XTENSA_SIM) += sim.o -obj-$(CONFIG_XTENSA_VIRT) += virt.o -obj-$(CONFIG_XTENSA_XTFPGA) += xtfpga.o diff --git a/hw/xtensa/meson.build b/hw/xtensa/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..1d5835df4bf4b0efdf5be01017da7456bf1a1ff1 --- /dev/null +++ b/hw/xtensa/meson.build @@ -0,0 +1,11 @@ +xtensa_ss = ss.source_set() +xtensa_ss.add(files( + 'mx_pic.c', + 'pic_cpu.c', + 'xtensa_memory.c', +)) +xtensa_ss.add(when: 'CONFIG_XTENSA_SIM', if_true: files('sim.c')) +xtensa_ss.add(when: 'CONFIG_XTENSA_VIRT', if_true: files('virt.c')) +xtensa_ss.add(when: 'CONFIG_XTENSA_XTFPGA', if_true: files('xtfpga.c')) + +hw_arch += {'xtensa': xtensa_ss} diff --git a/hw/xtensa/pic_cpu.c b/hw/xtensa/pic_cpu.c index edd53c9241c5adef0ad5b50b8f21e14720d07649..6c9447565db04bd1da2e428931262a284e4d3817 100644 --- a/hw/xtensa/pic_cpu.c +++ b/hw/xtensa/pic_cpu.c @@ -35,9 +35,13 @@ void check_interrupts(CPUXtensaState *env) { CPUState *cs = env_cpu(env); int minlevel = xtensa_get_cintlevel(env); - uint32_t int_set_enabled = env->sregs[INTSET] & env->sregs[INTENABLE]; + uint32_t int_set_enabled = env->sregs[INTSET] & + (env->sregs[INTENABLE] | env->config->inttype_mask[INTTYPE_NMI]); int level; + if (minlevel >= env->config->nmi_level) { + minlevel = env->config->nmi_level - 1; + } for (level = env->config->nlevel; level > minlevel; --level) { if (env->config->level_mask[level] & int_set_enabled) { env->pending_irq_level = level; @@ -68,9 +72,9 @@ static void xtensa_set_irq(void *opaque, int irq, int active) uint32_t irq_bit = 1 << irq; if (active) { - atomic_or(&env->sregs[INTSET], irq_bit); + qatomic_or(&env->sregs[INTSET], irq_bit); } else if (env->config->interrupt[irq].inttype == INTTYPE_LEVEL) { - atomic_and(&env->sregs[INTSET], ~irq_bit); + qatomic_and(&env->sregs[INTSET], ~irq_bit); } check_interrupts(env); diff --git a/hw/xtensa/sim.c b/hw/xtensa/sim.c index aeb46d86f5dca53125ffb896499b4fd843dd2728..cbac50db2de3e66726b5e213a1ff93022358c3ca 100644 --- a/hw/xtensa/sim.c +++ b/hw/xtensa/sim.c @@ -106,9 +106,8 @@ void xtensa_sim_load_kernel(XtensaCPU *cpu, MachineState *machine) if (kernel_filename) { uint64_t elf_entry; - uint64_t elf_lowaddr; int success = load_elf(kernel_filename, NULL, translate_phys_addr, cpu, - &elf_entry, &elf_lowaddr, NULL, NULL, big_endian, + &elf_entry, NULL, NULL, NULL, big_endian, EM_XTENSA, 0, 0); if (success > 0) { diff --git a/hw/xtensa/virt.c b/hw/xtensa/virt.c index b22dcf938a16c8935b9f0f54a7baeb398c29d6a1..e47e1de676713cdb39af36637b9c6991fbb7afb2 100644 --- a/hw/xtensa/virt.c +++ b/hw/xtensa/virt.c @@ -62,8 +62,8 @@ static void create_pcie(CPUXtensaState *env, int irq_base, hwaddr addr_base) qemu_irq *extints; int i; - dev = qdev_create(NULL, TYPE_GPEX_HOST); - qdev_init_nofail(dev); + dev = qdev_new(TYPE_GPEX_HOST); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); /* Map only the first size_ecam bytes of ECAM space. */ ecam_alias = g_new0(MemoryRegion, 1); diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 60ccc74f5f1d693f5823a784a18349975ffbe29d..b1470b88e6a5ce98e6d15e6da34e459cc22a632b 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -148,11 +148,11 @@ static void xtfpga_net_init(MemoryRegion *address_space, SysBusDevice *s; MemoryRegion *ram; - dev = qdev_create(NULL, "open_eth"); + dev = qdev_new("open_eth"); qdev_set_nic_properties(dev, nd); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_connect_irq(s, 0, irq); memory_region_add_subregion(address_space, base, sysbus_mmio_get_region(s, 0)); @@ -171,18 +171,17 @@ static PFlashCFI01 *xtfpga_flash_init(MemoryRegion *address_space, DriveInfo *dinfo, int be) { SysBusDevice *s; - DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01); + DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01); - qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo), - &error_abort); + qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo)); qdev_prop_set_uint32(dev, "num-blocks", board->flash->size / board->flash->sector_size); qdev_prop_set_uint64(dev, "sector-length", board->flash->sector_size); qdev_prop_set_uint8(dev, "width", 2); qdev_prop_set_bit(dev, "big-endian", be); qdev_prop_set_string(dev, "name", "xtfpga.io.flash"); - qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); memory_region_add_subregion(address_space, board->flash->base, sysbus_mmio_get_region(s, 0)); return PFLASH_CFI01(dev); @@ -414,9 +413,8 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine) env->regs[2] = tagptr; uint64_t elf_entry; - uint64_t elf_lowaddr; int success = load_elf(kernel_filename, NULL, translate_phys_addr, cpu, - &elf_entry, &elf_lowaddr, NULL, NULL, be, EM_XTENSA, 0, 0); + &elf_entry, NULL, NULL, NULL, be, EM_XTENSA, 0, 0); if (success > 0) { entry_point = elf_entry; } else { diff --git a/include/authz/base.h b/include/authz/base.h index 0782981ad81f810510f8a18e46851168a0f4f7d0..b53e4e4507eedf25c960b9e3104c6e41ca7eff74 100644 --- a/include/authz/base.h +++ b/include/authz/base.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -27,18 +27,9 @@ #define TYPE_QAUTHZ "authz" -#define QAUTHZ_CLASS(klass) \ - OBJECT_CLASS_CHECK(QAuthZClass, (klass), \ - TYPE_QAUTHZ) -#define QAUTHZ_GET_CLASS(obj) \ - OBJECT_GET_CLASS(QAuthZClass, (obj), \ - TYPE_QAUTHZ) -#define QAUTHZ(obj) \ - OBJECT_CHECK(QAuthZ, (obj), \ - TYPE_QAUTHZ) - -typedef struct QAuthZ QAuthZ; -typedef struct QAuthZClass QAuthZClass; +OBJECT_DECLARE_TYPE(QAuthZ, QAuthZClass, + QAUTHZ) + /** * QAuthZ: diff --git a/include/authz/list.h b/include/authz/list.h index a88cdbbcf8e3f0709986e408f0adf52ef7bc9685..7ef4ad4b4ede06d660a5422da236660c88ff1bce 100644 --- a/include/authz/list.h +++ b/include/authz/list.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -23,21 +23,13 @@ #include "authz/base.h" #include "qapi/qapi-types-authz.h" +#include "qom/object.h" #define TYPE_QAUTHZ_LIST "authz-list" -#define QAUTHZ_LIST_CLASS(klass) \ - OBJECT_CLASS_CHECK(QAuthZListClass, (klass), \ - TYPE_QAUTHZ_LIST) -#define QAUTHZ_LIST_GET_CLASS(obj) \ - OBJECT_GET_CLASS(QAuthZListClass, (obj), \ - TYPE_QAUTHZ_LIST) -#define QAUTHZ_LIST(obj) \ - OBJECT_CHECK(QAuthZList, (obj), \ - TYPE_QAUTHZ_LIST) +OBJECT_DECLARE_SIMPLE_TYPE(QAuthZList, + QAUTHZ_LIST) -typedef struct QAuthZList QAuthZList; -typedef struct QAuthZListClass QAuthZListClass; /** @@ -76,9 +68,6 @@ struct QAuthZList { }; -struct QAuthZListClass { - QAuthZClass parent_class; -}; QAuthZList *qauthz_list_new(const char *id, diff --git a/include/authz/listfile.h b/include/authz/listfile.h index 24ae2e606cf7def3ccd005c130e0a18031e7f03a..0a1e5bddd3e51cdd5f2fbc929faedc2df7112472 100644 --- a/include/authz/listfile.h +++ b/include/authz/listfile.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -23,21 +23,13 @@ #include "authz/list.h" #include "qemu/filemonitor.h" +#include "qom/object.h" #define TYPE_QAUTHZ_LIST_FILE "authz-list-file" -#define QAUTHZ_LIST_FILE_CLASS(klass) \ - OBJECT_CLASS_CHECK(QAuthZListFileClass, (klass), \ - TYPE_QAUTHZ_LIST_FILE) -#define QAUTHZ_LIST_FILE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(QAuthZListFileClass, (obj), \ - TYPE_QAUTHZ_LIST_FILE) -#define QAUTHZ_LIST_FILE(obj) \ - OBJECT_CHECK(QAuthZListFile, (obj), \ - TYPE_QAUTHZ_LIST_FILE) +OBJECT_DECLARE_SIMPLE_TYPE(QAuthZListFile, + QAUTHZ_LIST_FILE) -typedef struct QAuthZListFile QAuthZListFile; -typedef struct QAuthZListFileClass QAuthZListFileClass; /** @@ -95,9 +87,6 @@ struct QAuthZListFile { }; -struct QAuthZListFileClass { - QAuthZClass parent_class; -}; QAuthZListFile *qauthz_list_file_new(const char *id, diff --git a/include/authz/pamacct.h b/include/authz/pamacct.h index f3a7ef10118e994206a11e22d4ff85e6e505987b..592edb2bf0dff12667b072f236cd2859de8c11de 100644 --- a/include/authz/pamacct.h +++ b/include/authz/pamacct.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -22,22 +22,14 @@ #define QAUTHZ_PAMACCT_H #include "authz/base.h" +#include "qom/object.h" #define TYPE_QAUTHZ_PAM "authz-pam" -#define QAUTHZ_PAM_CLASS(klass) \ - OBJECT_CLASS_CHECK(QAuthZPAMClass, (klass), \ - TYPE_QAUTHZ_PAM) -#define QAUTHZ_PAM_GET_CLASS(obj) \ - OBJECT_GET_CLASS(QAuthZPAMClass, (obj), \ - TYPE_QAUTHZ_PAM) -#define QAUTHZ_PAM(obj) \ - OBJECT_CHECK(QAuthZPAM, (obj), \ - TYPE_QAUTHZ_PAM) +OBJECT_DECLARE_SIMPLE_TYPE(QAuthZPAM, + QAUTHZ_PAM) -typedef struct QAuthZPAM QAuthZPAM; -typedef struct QAuthZPAMClass QAuthZPAMClass; /** @@ -87,9 +79,6 @@ struct QAuthZPAM { }; -struct QAuthZPAMClass { - QAuthZClass parent_class; -}; QAuthZPAM *qauthz_pam_new(const char *id, diff --git a/include/authz/simple.h b/include/authz/simple.h index 2b7ab0cdd9127c242ba4a7ba52d5b000f6cd634f..c46a5ac5a15ad5caa54cd46b37a59bd0e23581ed 100644 --- a/include/authz/simple.h +++ b/include/authz/simple.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -22,21 +22,13 @@ #define QAUTHZ_SIMPLE_H #include "authz/base.h" +#include "qom/object.h" #define TYPE_QAUTHZ_SIMPLE "authz-simple" -#define QAUTHZ_SIMPLE_CLASS(klass) \ - OBJECT_CLASS_CHECK(QAuthZSimpleClass, (klass), \ - TYPE_QAUTHZ_SIMPLE) -#define QAUTHZ_SIMPLE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(QAuthZSimpleClass, (obj), \ - TYPE_QAUTHZ_SIMPLE) -#define QAUTHZ_SIMPLE(obj) \ - OBJECT_CHECK(QAuthZSimple, (obj), \ - TYPE_QAUTHZ_SIMPLE) +OBJECT_DECLARE_SIMPLE_TYPE(QAuthZSimple, + QAUTHZ_SIMPLE) -typedef struct QAuthZSimple QAuthZSimple; -typedef struct QAuthZSimpleClass QAuthZSimpleClass; /** @@ -70,9 +62,6 @@ struct QAuthZSimple { }; -struct QAuthZSimpleClass { - QAuthZClass parent_class; -}; QAuthZSimple *qauthz_simple_new(const char *id, diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h index 716d2639df708f03e3f29d68315b0e27a46bee04..b39eefb38d1607e881b4020e384b644d8849ff1d 100644 --- a/include/block/aio-wait.h +++ b/include/block/aio-wait.h @@ -80,7 +80,7 @@ extern AioWait global_aio_wait; AioWait *wait_ = &global_aio_wait; \ AioContext *ctx_ = (ctx); \ /* Increment wait_->num_waiters before evaluating cond. */ \ - atomic_inc(&wait_->num_waiters); \ + qatomic_inc(&wait_->num_waiters); \ if (ctx_ && in_aio_context_home_thread(ctx_)) { \ while ((cond)) { \ aio_poll(ctx_, true); \ @@ -100,7 +100,7 @@ extern AioWait global_aio_wait; waited_ = true; \ } \ } \ - atomic_dec(&wait_->num_waiters); \ + qatomic_dec(&wait_->num_waiters); \ waited_; }) /** diff --git a/include/block/aio.h b/include/block/aio.h index b2f703fa3fcfea983e2eaa838adea4c0e32456ab..5f342267d5cea100def1d01f378e7956bfa2d7f5 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -17,6 +17,7 @@ #ifdef CONFIG_LINUX_IO_URING #include #endif +#include "qemu/coroutine.h" #include "qemu/queue.h" #include "qemu/event_notifier.h" #include "qemu/thread.h" @@ -595,7 +596,7 @@ int64_t aio_compute_timeout(AioContext *ctx); */ static inline void aio_disable_external(AioContext *ctx) { - atomic_inc(&ctx->external_disable_cnt); + qatomic_inc(&ctx->external_disable_cnt); } /** @@ -608,7 +609,7 @@ static inline void aio_enable_external(AioContext *ctx) { int old; - old = atomic_fetch_dec(&ctx->external_disable_cnt); + old = qatomic_fetch_dec(&ctx->external_disable_cnt); assert(old > 0); if (old == 1) { /* Kick event loop so it re-arms file descriptors */ @@ -624,7 +625,7 @@ static inline void aio_enable_external(AioContext *ctx) */ static inline bool aio_external_disabled(AioContext *ctx) { - return atomic_read(&ctx->external_disable_cnt); + return qatomic_read(&ctx->external_disable_cnt); } /** @@ -637,7 +638,7 @@ static inline bool aio_external_disabled(AioContext *ctx) */ static inline bool aio_node_check(AioContext *ctx, bool is_external) { - return !is_external || !atomic_read(&ctx->external_disable_cnt); + return !is_external || !qatomic_read(&ctx->external_disable_cnt); } /** @@ -654,6 +655,15 @@ static inline bool aio_node_check(AioContext *ctx, bool is_external) */ void aio_co_schedule(AioContext *ctx, struct Coroutine *co); +/** + * aio_co_reschedule_self: + * @new_ctx: the new context + * + * Move the currently running coroutine to new_ctx. If the coroutine is already + * running in new_ctx, do nothing. + */ +void coroutine_fn aio_co_reschedule_self(AioContext *new_ctx); + /** * aio_co_wake: * @co: the coroutine diff --git a/include/block/block.h b/include/block/block.h index 25e299605e19231b38449d090cc46d7b84b4d6ec..c9d7c58765aebcc1ae8875ebee19ea891b343e2c 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -10,6 +10,16 @@ #include "block/blockjob.h" #include "qemu/hbitmap.h" +/* + * generated_co_wrapper + * + * Function specifier, which does nothing but mark functions to be + * generated by scripts/block-coroutine-wrapper.py + * + * Read more in docs/devel/block-coroutine-wrapper.rst + */ +#define generated_co_wrapper + /* block.c */ typedef struct BlockDriver BlockDriver; typedef struct BdrvChild BdrvChild; @@ -21,11 +31,6 @@ typedef struct BlockDriverInfo { /* offset at which the VM state can be saved (0 if not possible) */ int64_t vm_state_offset; bool is_dirty; - /* - * True if unallocated blocks read back as zeroes. This is equivalent - * to the LBPRZ flag in the SCSI logical block provisioning page. - */ - bool unallocated_blocks_are_zero; /* * True if this block driver only supports compressed writes */ @@ -133,8 +138,8 @@ typedef struct HDGeometry { #define BDRV_SECTOR_BITS 9 #define BDRV_SECTOR_SIZE (1ULL << BDRV_SECTOR_BITS) -#define BDRV_REQUEST_MAX_SECTORS MIN(SIZE_MAX >> BDRV_SECTOR_BITS, \ - INT_MAX >> BDRV_SECTOR_BITS) +#define BDRV_REQUEST_MAX_SECTORS MIN_CONST(SIZE_MAX >> BDRV_SECTOR_BITS, \ + INT_MAX >> BDRV_SECTOR_BITS) #define BDRV_REQUEST_MAX_BYTES (BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS) /* @@ -299,7 +304,7 @@ enum BdrvChildRoleBits { BDRV_CHILD_FILTERED = (1 << 2), /* - * Child from which to read all data that isn’t allocated in the + * Child from which to read all data that isn't allocated in the * parent (i.e., the backing child); such data is copied to the * parent through COW (and optionally COR). * This field is mutually exclusive with DATA, METADATA, and @@ -378,9 +383,7 @@ int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset, int bytes, BdrvRequestFlags flags); int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags); int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int bytes); -int bdrv_preadv(BdrvChild *child, int64_t offset, QEMUIOVector *qiov); int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf, int bytes); -int bdrv_pwritev(BdrvChild *child, int64_t offset, QEMUIOVector *qiov); int bdrv_pwrite_sync(BdrvChild *child, int64_t offset, const void *buf, int count); /* @@ -398,8 +401,9 @@ void bdrv_refresh_filename(BlockDriverState *bs); int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, PreallocMode prealloc, BdrvRequestFlags flags, Error **errp); -int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact, - PreallocMode prealloc, BdrvRequestFlags flags, Error **errp); +int generated_co_wrapper +bdrv_truncate(BdrvChild *child, int64_t offset, bool exact, + PreallocMode prealloc, BdrvRequestFlags flags, Error **errp); int64_t bdrv_nb_sectors(BlockDriverState *bs); int64_t bdrv_getlength(BlockDriverState *bs); @@ -410,8 +414,8 @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); void bdrv_refresh_limits(BlockDriverState *bs, Error **errp); int bdrv_commit(BlockDriverState *bs); int bdrv_make_empty(BdrvChild *c, Error **errp); -int bdrv_change_backing_file(BlockDriverState *bs, - const char *backing_file, const char *backing_fmt); +int bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file, + const char *backing_fmt, bool warn); void bdrv_register(BlockDriver *bdrv); int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, const char *backing_file_str); @@ -441,7 +445,8 @@ typedef enum { BDRV_FIX_ERRORS = 2, } BdrvCheckMode; -int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix); +int generated_co_wrapper bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, + BdrvCheckMode fix); /* The units of offset and total_work_size may be chosen arbitrarily by the * block driver; total_work_size may change during the course of the amendment @@ -450,6 +455,7 @@ typedef void BlockDriverAmendStatusCB(BlockDriverState *bs, int64_t offset, int64_t total_work_size, void *opaque); int bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts, BlockDriverAmendStatusCB *status_cb, void *cb_opaque, + bool force, Error **errp); /* check if a named node can be replaced when doing drive-mirror */ @@ -464,12 +470,13 @@ void bdrv_aio_cancel_async(BlockAIOCB *acb); int bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf); /* Invalidate any cached metadata used by image formats */ -void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp); +int generated_co_wrapper bdrv_invalidate_cache(BlockDriverState *bs, + Error **errp); void bdrv_invalidate_cache_all(Error **errp); int bdrv_inactivate_all(void); /* Ensure contents are flushed to disk. */ -int bdrv_flush(BlockDriverState *bs); +int generated_co_wrapper bdrv_flush(BlockDriverState *bs); int coroutine_fn bdrv_co_flush(BlockDriverState *bs); int bdrv_flush_all(void); void bdrv_close_all(void); @@ -484,11 +491,11 @@ void bdrv_drain_all(void); AIO_WAIT_WHILE(bdrv_get_aio_context(bs_), \ cond); }) -int bdrv_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes); +int generated_co_wrapper bdrv_pdiscard(BdrvChild *child, int64_t offset, + int64_t bytes); int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes); int bdrv_has_zero_init_1(BlockDriverState *bs); int bdrv_has_zero_init(BlockDriverState *bs); -bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs); bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs); int bdrv_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, @@ -501,6 +508,8 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes, int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base, bool include_base, int64_t offset, int64_t bytes, int64_t *pnum); +int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, + int64_t bytes); bool bdrv_is_read_only(BlockDriverState *bs); int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, @@ -537,7 +546,7 @@ BlockDriverState *bdrv_next(BdrvNextIterator *it); void bdrv_next_cleanup(BdrvNextIterator *it); BlockDriverState *bdrv_next_monitor_owned(BlockDriverState *bs); -bool bdrv_is_encrypted(BlockDriverState *bs); +bool bdrv_supports_compressed_writes(BlockDriverState *bs); void bdrv_iterate_format(void (*it)(void *opaque, const char *name), void *opaque, bool read_only); const char *bdrv_get_node_name(const BlockDriverState *bs); @@ -565,8 +574,10 @@ int path_has_protocol(const char *path); int path_is_absolute(const char *path); char *path_combine(const char *base_path, const char *filename); -int bdrv_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos); -int bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos); +int generated_co_wrapper +bdrv_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos); +int generated_co_wrapper +bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos); int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf, int64_t pos, int size); @@ -631,6 +642,37 @@ bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag); */ AioContext *bdrv_get_aio_context(BlockDriverState *bs); +/** + * Move the current coroutine to the AioContext of @bs and return the old + * AioContext of the coroutine. Increase bs->in_flight so that draining @bs + * will wait for the operation to proceed until the corresponding + * bdrv_co_leave(). + * + * Consequently, you can't call drain inside a bdrv_co_enter/leave() section as + * this will deadlock. + */ +AioContext *coroutine_fn bdrv_co_enter(BlockDriverState *bs); + +/** + * Ends a section started by bdrv_co_enter(). Move the current coroutine back + * to old_ctx and decrease bs->in_flight again. + */ +void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx); + +/** + * Locks the AioContext of @bs if it's not the current AioContext. This avoids + * double locking which could lead to deadlocks: This is a coroutine_fn, so we + * know we already own the lock of the current AioContext. + * + * May only be called in the main thread. + */ +void coroutine_fn bdrv_co_lock(BlockDriverState *bs); + +/** + * Unlocks the AioContext of @bs if it's not the current AioContext. + */ +void coroutine_fn bdrv_co_unlock(BlockDriverState *bs); + /** * Transfer control to @co in the aio context of @bs */ diff --git a/include/block/block_int.h b/include/block/block_int.h index 791de6a59c2c0ca7dac10b754ca9f266edf01b07..95d9333be14f220f96754c3cdd737ca092b3dbf9 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -53,11 +53,13 @@ #define BLOCK_OPT_ADAPTER_TYPE "adapter_type" #define BLOCK_OPT_REDUNDANCY "redundancy" #define BLOCK_OPT_NOCOW "nocow" +#define BLOCK_OPT_EXTENT_SIZE_HINT "extent_size_hint" #define BLOCK_OPT_OBJECT_SIZE "object_size" #define BLOCK_OPT_REFCOUNT_BITS "refcount_bits" #define BLOCK_OPT_DATA_FILE "data_file" #define BLOCK_OPT_DATA_FILE_RAW "data_file_raw" #define BLOCK_OPT_COMPRESSION_TYPE "compression_type" +#define BLOCK_OPT_EXTL2 "extended_l2" #define BLOCK_PROBE_BUF_SIZE 512 @@ -90,9 +92,17 @@ struct BlockDriver { int instance_size; /* set to true if the BlockDriver is a block filter. Block filters pass - * certain callbacks that refer to data (see block.c) to their bs->file if - * the driver doesn't implement them. Drivers that do not wish to forward - * must implement them and return -ENOTSUP. + * certain callbacks that refer to data (see block.c) to their bs->file + * or bs->backing (whichever one exists) if the driver doesn't implement + * them. Drivers that do not wish to forward must implement them and return + * -ENOTSUP. + * Note that filters are not allowed to modify data. + * + * Filters generally cannot have more than a single filtered child, + * because the data they present must at all times be the same as + * that on their filtered child. That would be impossible to + * achieve for multiple filtered children. + * (And this filtered child must then be bs->file or bs->backing.) */ bool is_filter; /* @@ -123,7 +133,17 @@ struct BlockDriver { */ bool bdrv_needs_filename; - /* Set if a driver can support backing files */ + /* + * Set if a driver can support backing files. This also implies the + * following semantics: + * + * - Return status 0 of .bdrv_co_block_status means that corresponding + * blocks are not allocated in this layer of backing-chain + * - For such (unallocated) blocks, read will: + * - fill buffer with zeros if there is no backing file + * - read from the backing file otherwise, where the block layer + * takes care of reading zeros beyond EOF if backing file is short + */ bool supports_backing; /* For handling image reopen for split or non-split files */ @@ -141,12 +161,27 @@ struct BlockDriver { int (*bdrv_file_open)(BlockDriverState *bs, QDict *options, int flags, Error **errp); void (*bdrv_close)(BlockDriverState *bs); + + int coroutine_fn (*bdrv_co_create)(BlockdevCreateOptions *opts, Error **errp); int coroutine_fn (*bdrv_co_create_opts)(BlockDriver *drv, const char *filename, QemuOpts *opts, Error **errp); + + int coroutine_fn (*bdrv_co_amend)(BlockDriverState *bs, + BlockdevAmendOptions *opts, + bool force, + Error **errp); + + int (*bdrv_amend_options)(BlockDriverState *bs, + QemuOpts *opts, + BlockDriverAmendStatusCB *status_cb, + void *cb_opaque, + bool force, + Error **errp); + int (*bdrv_make_empty)(BlockDriverState *bs); /* @@ -420,6 +455,10 @@ struct BlockDriver { /* List of options for creating images, terminated by name == NULL */ QemuOptsList *create_opts; + + /* List of options for image amend */ + QemuOptsList *amend_opts; + /* * If this driver supports reopening images this contains a * NULL-terminated list of the runtime options that can be @@ -437,11 +476,6 @@ struct BlockDriver { BdrvCheckResult *result, BdrvCheckMode fix); - int (*bdrv_amend_options)(BlockDriverState *bs, QemuOpts *opts, - BlockDriverAmendStatusCB *status_cb, - void *cb_opaque, - Error **errp); - void (*bdrv_debug_event)(BlockDriverState *bs, BlkdebugEvent event); /* TODO Better pass a option string/QDict/QemuOpts to add any rule? */ @@ -813,11 +847,20 @@ struct BlockDriverState { bool walking_aio_notifiers; /* to make removal during iteration safe */ char filename[PATH_MAX]; - char backing_file[PATH_MAX]; /* if non zero, the image is a diff of - this file image */ - /* The backing filename indicated by the image header; if we ever - * open this file, then this is replaced by the resulting BDS's - * filename (i.e. after a bdrv_refresh_filename() run). */ + /* + * If not empty, this image is a diff in relation to backing_file. + * Note that this is the name given in the image header and + * therefore may or may not be equal to .backing->bs->filename. + * If this field contains a relative path, it is to be resolved + * relatively to the overlay's location. + */ + char backing_file[PATH_MAX]; + /* + * The backing filename indicated by the image header. Contrary + * to backing_file, if we ever open this file, auto_backing_file + * is replaced by the resulting BDS's filename (i.e. after a + * bdrv_refresh_filename() run). + */ char auto_backing_file[PATH_MAX]; char backing_format[16]; /* if non-zero and backing_file exists */ @@ -969,11 +1012,6 @@ typedef enum BlockMirrorBackingMode { MIRROR_LEAVE_BACKING_CHAIN, } BlockMirrorBackingMode; -static inline BlockDriverState *backing_bs(BlockDriverState *bs) -{ - return bs->backing ? bs->backing->bs : NULL; -} - /* Essential block drivers which must always be statically linked into qemu, and * which therefore can be accessed without using bdrv_find_format() */ @@ -1024,6 +1062,8 @@ BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size, void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix, QDict *options); +bool bdrv_backing_overridden(BlockDriverState *bs); + /** * bdrv_add_before_write_notifier: @@ -1274,28 +1314,6 @@ void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c, uint64_t perm, uint64_t shared, uint64_t *nperm, uint64_t *nshared); -/* - * Default implementation for drivers to pass bdrv_co_block_status() to - * their file. - */ -int coroutine_fn bdrv_co_block_status_from_file(BlockDriverState *bs, - bool want_zero, - int64_t offset, - int64_t bytes, - int64_t *pnum, - int64_t *map, - BlockDriverState **file); -/* - * Default implementation for drivers to pass bdrv_co_block_status() to - * their backing file. - */ -int coroutine_fn bdrv_co_block_status_from_backing(BlockDriverState *bs, - bool want_zero, - int64_t offset, - int64_t bytes, - int64_t *pnum, - int64_t *map, - BlockDriverState **file); const char *bdrv_get_parent_name(const BlockDriverState *bs); void blk_dev_change_media_cb(BlockBackend *blk, bool load, Error **errp); bool blk_dev_has_removable_media(BlockBackend *blk); @@ -1356,4 +1374,46 @@ BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name, BlockDriverState **bitmap_bs, Error **errp); +BdrvChild *bdrv_cow_child(BlockDriverState *bs); +BdrvChild *bdrv_filter_child(BlockDriverState *bs); +BdrvChild *bdrv_filter_or_cow_child(BlockDriverState *bs); +BdrvChild *bdrv_primary_child(BlockDriverState *bs); +BlockDriverState *bdrv_skip_implicit_filters(BlockDriverState *bs); +BlockDriverState *bdrv_skip_filters(BlockDriverState *bs); +BlockDriverState *bdrv_backing_chain_next(BlockDriverState *bs); + +static inline BlockDriverState *child_bs(BdrvChild *child) +{ + return child ? child->bs : NULL; +} + +static inline BlockDriverState *bdrv_cow_bs(BlockDriverState *bs) +{ + return child_bs(bdrv_cow_child(bs)); +} + +static inline BlockDriverState *bdrv_filter_bs(BlockDriverState *bs) +{ + return child_bs(bdrv_filter_child(bs)); +} + +static inline BlockDriverState *bdrv_filter_or_cow_bs(BlockDriverState *bs) +{ + return child_bs(bdrv_filter_or_cow_child(bs)); +} + +static inline BlockDriverState *bdrv_primary_bs(BlockDriverState *bs) +{ + return child_bs(bdrv_primary_child(bs)); +} + +/** + * End all quiescent sections started by bdrv_drain_all_begin(). This is + * needed when deleting a BDS before bdrv_drain_all_end() is called. + * + * NOTE: this is an internal helper for bdrv_close() *only*. No one else + * should call it. + */ +void bdrv_drain_all_end_quiesce(BlockDriverState *bs); + #endif /* BLOCK_INT_H */ diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index 5a8d52e4deafbb9706b3bfc05fc8724651e196ed..36e8da4fc2e34b6a3c2dda5f545ec260c5206060 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -95,6 +95,7 @@ int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap); void bdrv_dirty_bitmap_truncate(BlockDriverState *bs, int64_t bytes); bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap); bool bdrv_has_readonly_bitmaps(BlockDriverState *bs); +bool bdrv_has_named_bitmaps(BlockDriverState *bs); bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap); bool bdrv_dirty_bitmap_get_persistence(BdrvDirtyBitmap *bitmap); bool bdrv_dirty_bitmap_inconsistent(const BdrvDirtyBitmap *bitmap); diff --git a/include/block/export.h b/include/block/export.h new file mode 100644 index 0000000000000000000000000000000000000000..7feb02e10d471806a17837d8e602e7616bd2a590 --- /dev/null +++ b/include/block/export.h @@ -0,0 +1,89 @@ +/* + * Declarations for block exports + * + * Copyright (c) 2012, 2020 Red Hat, Inc. + * + * Authors: + * Paolo Bonzini + * Kevin Wolf + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * later. See the COPYING file in the top-level directory. + */ + +#ifndef BLOCK_EXPORT_H +#define BLOCK_EXPORT_H + +#include "qapi/qapi-types-block-export.h" +#include "qemu/queue.h" + +typedef struct BlockExport BlockExport; + +typedef struct BlockExportDriver { + /* The export type that this driver services */ + BlockExportType type; + + /* + * The size of the driver-specific state that contains BlockExport as its + * first field. + */ + size_t instance_size; + + /* Creates and starts a new block export */ + int (*create)(BlockExport *, BlockExportOptions *, Error **); + + /* + * Frees a removed block export. This function is only called after all + * references have been dropped. + */ + void (*delete)(BlockExport *); + + /* + * Start to disconnect all clients and drop other references held + * internally by the export driver. When the function returns, there may + * still be active references while the export is in the process of + * shutting down. + */ + void (*request_shutdown)(BlockExport *); +} BlockExportDriver; + +struct BlockExport { + const BlockExportDriver *drv; + + /* Unique identifier for the export */ + char *id; + + /* + * Reference count for this block export. This includes strong references + * both from the owner (qemu-nbd or the monitor) and clients connected to + * the export. + */ + int refcount; + + /* + * True if one of the references in refcount belongs to the user. After the + * user has dropped their reference, they may not e.g. remove the same + * export a second time (which would decrease the refcount without having + * it incremented first). + */ + bool user_owned; + + /* The AioContext whose lock protects this BlockExport object. */ + AioContext *ctx; + + /* The block device to export */ + BlockBackend *blk; + + /* List entry for block_exports */ + QLIST_ENTRY(BlockExport) next; +}; + +BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp); +BlockExport *blk_exp_find(const char *id); +void blk_exp_ref(BlockExport *exp); +void blk_exp_unref(BlockExport *exp); +void blk_exp_request_shutdown(BlockExport *exp); +void blk_exp_close_all(void); +void blk_exp_close_all_type(BlockExportType type); + +#endif diff --git a/include/block/nbd.h b/include/block/nbd.h index 20363280ae012c50947404b93187de372563b7f8..4a52a43ef59882c8c31a06f1400212aa2722d155 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2019 Red Hat, Inc. + * Copyright (C) 2016-2020 Red Hat, Inc. * Copyright (C) 2005 Anthony Liguori * * Network Block Device @@ -20,11 +20,13 @@ #ifndef NBD_H #define NBD_H -#include "qapi/qapi-types-block.h" +#include "block/export.h" #include "io/channel-socket.h" #include "crypto/tlscreds.h" #include "qapi/error.h" +extern const BlockExportDriver blk_exp_nbd; + /* Handshake phase structs - this struct is passed on the wire */ struct NBDOption { @@ -45,7 +47,7 @@ typedef struct NBDOptionReply NBDOptionReply; typedef struct NBDOptionReplyMetaContext { NBDOptionReply h; /* h.type = NBD_REP_META_CONTEXT, h.length > 4 */ uint32_t context_id; - /* meta context name follows */ + /* metadata context name follows */ } QEMU_PACKED NBDOptionReplyMetaContext; /* Transmission phase structs @@ -227,7 +229,7 @@ enum { #define NBD_MAX_BUFFER_SIZE (32 * 1024 * 1024) /* - * Maximum size of a protocol string (export name, meta context name, + * Maximum size of a protocol string (export name, metadata context name, * etc.). Use malloc rather than stack allocation for storage of a * string. */ @@ -257,6 +259,8 @@ enum { /* Extent flags for qemu:dirty-bitmap in NBD_REPLY_TYPE_BLOCK_STATUS */ #define NBD_STATE_DIRTY (1 << 0) +/* No flags needed for qemu:allocation-depth in NBD_REPLY_TYPE_BLOCK_STATUS */ + static inline bool nbd_reply_type_is_error(int type) { return type & (1 << 15); @@ -328,21 +332,10 @@ int nbd_errno_to_system_errno(int err); typedef struct NBDExport NBDExport; typedef struct NBDClient NBDClient; -NBDExport *nbd_export_new(BlockDriverState *bs, uint64_t dev_offset, - uint64_t size, const char *name, const char *desc, - const char *bitmap, bool readonly, bool shared, - void (*close)(NBDExport *), bool writethrough, - BlockBackend *on_eject_blk, Error **errp); -void nbd_export_close(NBDExport *exp); -void nbd_export_remove(NBDExport *exp, NbdServerRemoveMode mode, Error **errp); -void nbd_export_get(NBDExport *exp); -void nbd_export_put(NBDExport *exp); - -BlockBackend *nbd_export_get_blockdev(NBDExport *exp); +void nbd_export_set_on_eject_blk(BlockExport *exp, BlockBackend *blk); AioContext *nbd_export_aio_context(NBDExport *exp); NBDExport *nbd_export_find(const char *name); -void nbd_export_close_all(void); void nbd_client_new(QIOChannelSocket *sioc, QCryptoTLSCreds *tlscreds, @@ -351,8 +344,11 @@ void nbd_client_new(QIOChannelSocket *sioc, void nbd_client_get(NBDClient *client); void nbd_client_put(NBDClient *client); +void nbd_server_is_qemu_nbd(bool value); +bool nbd_server_is_running(void); void nbd_server_start(SocketAddress *addr, const char *tls_creds, - const char *tls_authz, Error **errp); + const char *tls_authz, uint32_t max_connections, + Error **errp); void nbd_server_start_options(NbdServerOptions *arg, Error **errp); /* nbd_read @@ -361,6 +357,7 @@ void nbd_server_start_options(NbdServerOptions *arg, Error **errp); static inline int nbd_read(QIOChannel *ioc, void *buffer, size_t size, const char *desc, Error **errp) { + ERRP_GUARD(); int ret = qio_channel_read_all(ioc, buffer, size, errp) < 0 ? -EIO : 0; if (ret < 0) { diff --git a/include/block/nvme.h b/include/block/nvme.h index 5525c8e34308c95429068d5c585a4c1a1a79e613..3e02d9ca98438a50eda6dd38c581f88cacfc99e6 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -1,7 +1,7 @@ #ifndef BLOCK_NVME_H #define BLOCK_NVME_H -typedef struct NvmeBar { +typedef struct QEMU_PACKED NvmeBar { uint64_t cap; uint32_t vs; uint32_t intms; @@ -21,7 +21,8 @@ typedef struct NvmeBar { uint32_t pmrsts; uint32_t pmrebs; uint32_t pmrswtp; - uint32_t pmrmsc; + uint64_t pmrmsc; + uint8_t reserved[484]; } NvmeBar; enum NvmeCapShift { @@ -81,6 +82,11 @@ enum NvmeCapMask { #define NVME_CAP_SET_PMRS(cap, val) (cap |= (uint64_t)(val & CAP_PMR_MASK)\ << CAP_PMR_SHIFT) +enum NvmeCapCss { + NVME_CAP_CSS_NVM = 1 << 0, + NVME_CAP_CSS_ADMIN_ONLY = 1 << 7, +}; + enum NvmeCcShift { CC_EN_SHIFT = 0, CC_CSS_SHIFT = 4, @@ -109,6 +115,11 @@ enum NvmeCcMask { #define NVME_CC_IOSQES(cc) ((cc >> CC_IOSQES_SHIFT) & CC_IOSQES_MASK) #define NVME_CC_IOCQES(cc) ((cc >> CC_IOCQES_SHIFT) & CC_IOCQES_MASK) +enum NvmeCcCss { + NVME_CC_CSS_NVM = 0x0, + NVME_CC_CSS_ADMIN_ONLY = 0x7, +}; + enum NvmeCstsShift { CSTS_RDY_SHIFT = 0, CSTS_CFS_SHIFT = 1, @@ -377,15 +388,53 @@ enum NvmePmrmscMask { #define NVME_PMRMSC_SET_CBA(pmrmsc, val) \ (pmrmsc |= (uint64_t)(val & PMRMSC_CBA_MASK) << PMRMSC_CBA_SHIFT) -typedef struct NvmeCmd { +enum NvmeSglDescriptorType { + NVME_SGL_DESCR_TYPE_DATA_BLOCK = 0x0, + NVME_SGL_DESCR_TYPE_BIT_BUCKET = 0x1, + NVME_SGL_DESCR_TYPE_SEGMENT = 0x2, + NVME_SGL_DESCR_TYPE_LAST_SEGMENT = 0x3, + NVME_SGL_DESCR_TYPE_KEYED_DATA_BLOCK = 0x4, + + NVME_SGL_DESCR_TYPE_VENDOR_SPECIFIC = 0xf, +}; + +enum NvmeSglDescriptorSubtype { + NVME_SGL_DESCR_SUBTYPE_ADDRESS = 0x0, +}; + +typedef struct QEMU_PACKED NvmeSglDescriptor { + uint64_t addr; + uint32_t len; + uint8_t rsvd[3]; + uint8_t type; +} NvmeSglDescriptor; + +#define NVME_SGL_TYPE(type) ((type >> 4) & 0xf) +#define NVME_SGL_SUBTYPE(type) (type & 0xf) + +typedef union NvmeCmdDptr { + struct { + uint64_t prp1; + uint64_t prp2; + }; + + NvmeSglDescriptor sgl; +} NvmeCmdDptr; + +enum NvmePsdt { + NVME_PSDT_PRP = 0x0, + NVME_PSDT_SGL_MPTR_CONTIGUOUS = 0x1, + NVME_PSDT_SGL_MPTR_SGL = 0x2, +}; + +typedef struct QEMU_PACKED NvmeCmd { uint8_t opcode; - uint8_t fuse; + uint8_t flags; uint16_t cid; uint32_t nsid; uint64_t res1; uint64_t mptr; - uint64_t prp1; - uint64_t prp2; + NvmeCmdDptr dptr; uint32_t cdw10; uint32_t cdw11; uint32_t cdw12; @@ -394,6 +443,9 @@ typedef struct NvmeCmd { uint32_t cdw15; } NvmeCmd; +#define NVME_CMD_FLAGS_FUSE(flags) (flags & 0x3) +#define NVME_CMD_FLAGS_PSDT(flags) ((flags >> 6) & 0x3) + enum NvmeAdminCommands { NVME_ADM_CMD_DELETE_SQ = 0x00, NVME_ADM_CMD_CREATE_SQ = 0x01, @@ -418,11 +470,11 @@ enum NvmeIoCommands { NVME_CMD_READ = 0x02, NVME_CMD_WRITE_UNCOR = 0x04, NVME_CMD_COMPARE = 0x05, - NVME_CMD_WRITE_ZEROS = 0x08, + NVME_CMD_WRITE_ZEROES = 0x08, NVME_CMD_DSM = 0x09, }; -typedef struct NvmeDeleteQ { +typedef struct QEMU_PACKED NvmeDeleteQ { uint8_t opcode; uint8_t flags; uint16_t cid; @@ -432,7 +484,7 @@ typedef struct NvmeDeleteQ { uint32_t rsvd11[5]; } NvmeDeleteQ; -typedef struct NvmeCreateCq { +typedef struct QEMU_PACKED NvmeCreateCq { uint8_t opcode; uint8_t flags; uint16_t cid; @@ -449,7 +501,12 @@ typedef struct NvmeCreateCq { #define NVME_CQ_FLAGS_PC(cq_flags) (cq_flags & 0x1) #define NVME_CQ_FLAGS_IEN(cq_flags) ((cq_flags >> 1) & 0x1) -typedef struct NvmeCreateSq { +enum NvmeFlagsCq { + NVME_CQ_PC = 1, + NVME_CQ_IEN = 2, +}; + +typedef struct QEMU_PACKED NvmeCreateSq { uint8_t opcode; uint8_t flags; uint16_t cid; @@ -466,15 +523,16 @@ typedef struct NvmeCreateSq { #define NVME_SQ_FLAGS_PC(sq_flags) (sq_flags & 0x1) #define NVME_SQ_FLAGS_QPRIO(sq_flags) ((sq_flags >> 1) & 0x3) -enum NvmeQueueFlags { - NVME_Q_PC = 1, - NVME_Q_PRIO_URGENT = 0, - NVME_Q_PRIO_HIGH = 1, - NVME_Q_PRIO_NORMAL = 2, - NVME_Q_PRIO_LOW = 3, +enum NvmeFlagsSq { + NVME_SQ_PC = 1, + + NVME_SQ_PRIO_URGENT = 0, + NVME_SQ_PRIO_HIGH = 1, + NVME_SQ_PRIO_NORMAL = 2, + NVME_SQ_PRIO_LOW = 3, }; -typedef struct NvmeIdentify { +typedef struct QEMU_PACKED NvmeIdentify { uint8_t opcode; uint8_t flags; uint16_t cid; @@ -486,15 +544,14 @@ typedef struct NvmeIdentify { uint32_t rsvd11[5]; } NvmeIdentify; -typedef struct NvmeRwCmd { +typedef struct QEMU_PACKED NvmeRwCmd { uint8_t opcode; uint8_t flags; uint16_t cid; uint32_t nsid; uint64_t rsvd2; uint64_t mptr; - uint64_t prp1; - uint64_t prp2; + NvmeCmdDptr dptr; uint64_t slba; uint16_t nlb; uint16_t control; @@ -528,14 +585,13 @@ enum { NVME_RW_PRINFO_PRCHK_REF = 1 << 10, }; -typedef struct NvmeDsmCmd { +typedef struct QEMU_PACKED NvmeDsmCmd { uint8_t opcode; uint8_t flags; uint16_t cid; uint32_t nsid; uint64_t rsvd2[2]; - uint64_t prp1; - uint64_t prp2; + NvmeCmdDptr dptr; uint32_t nr; uint32_t attributes; uint32_t rsvd12[4]; @@ -547,7 +603,7 @@ enum { NVME_DSMGMT_AD = 1 << 2, }; -typedef struct NvmeDsmRange { +typedef struct QEMU_PACKED NvmeDsmRange { uint32_t cattr; uint32_t nlb; uint64_t slba; @@ -558,8 +614,8 @@ enum NvmeAsyncEventRequest { NVME_AER_TYPE_SMART = 1, NVME_AER_TYPE_IO_SPECIFIC = 6, NVME_AER_TYPE_VENDOR_SPECIFIC = 7, - NVME_AER_INFO_ERR_INVALID_SQ = 0, - NVME_AER_INFO_ERR_INVALID_DB = 1, + NVME_AER_INFO_ERR_INVALID_DB_REGISTER = 0, + NVME_AER_INFO_ERR_INVALID_DB_VALUE = 1, NVME_AER_INFO_ERR_DIAG_FAIL = 2, NVME_AER_INFO_ERR_PERS_INTERNAL_ERR = 3, NVME_AER_INFO_ERR_TRANS_INTERNAL_ERR = 4, @@ -569,14 +625,14 @@ enum NvmeAsyncEventRequest { NVME_AER_INFO_SMART_SPARE_THRESH = 2, }; -typedef struct NvmeAerResult { +typedef struct QEMU_PACKED NvmeAerResult { uint8_t event_type; uint8_t event_info; uint8_t log_page; uint8_t resv; } NvmeAerResult; -typedef struct NvmeCqe { +typedef struct QEMU_PACKED NvmeCqe { uint32_t result; uint32_t rsvd; uint16_t sq_head; @@ -599,6 +655,13 @@ enum NvmeStatusCodes { NVME_CMD_ABORT_MISSING_FUSE = 0x000a, NVME_INVALID_NSID = 0x000b, NVME_CMD_SEQ_ERROR = 0x000c, + NVME_INVALID_SGL_SEG_DESCR = 0x000d, + NVME_INVALID_NUM_SGL_DESCRS = 0x000e, + NVME_DATA_SGL_LEN_INVALID = 0x000f, + NVME_MD_SGL_LEN_INVALID = 0x0010, + NVME_SGL_DESCR_TYPE_INVALID = 0x0011, + NVME_INVALID_USE_OF_CMB = 0x0012, + NVME_INVALID_PRP_OFFSET = 0x0013, NVME_LBA_RANGE = 0x0080, NVME_CAP_EXCEEDED = 0x0081, NVME_NS_NOT_READY = 0x0082, @@ -617,7 +680,8 @@ enum NvmeStatusCodes { NVME_FW_REQ_RESET = 0x010b, NVME_INVALID_QUEUE_DEL = 0x010c, NVME_FID_NOT_SAVEABLE = 0x010d, - NVME_FID_NOT_NSID_SPEC = 0x010f, + NVME_FEAT_NOT_CHANGEABLE = 0x010e, + NVME_FEAT_NOT_NS_SPEC = 0x010f, NVME_FW_REQ_SUSYSTEM_RESET = 0x0110, NVME_CONFLICTING_ATTRS = 0x0180, NVME_INVALID_PROT_INFO = 0x0181, @@ -634,7 +698,7 @@ enum NvmeStatusCodes { NVME_NO_COMPLETE = 0xffff, }; -typedef struct NvmeFwSlotInfoLog { +typedef struct QEMU_PACKED NvmeFwSlotInfoLog { uint8_t afi; uint8_t reserved1[7]; uint8_t frs1[8]; @@ -647,7 +711,7 @@ typedef struct NvmeFwSlotInfoLog { uint8_t reserved2[448]; } NvmeFwSlotInfoLog; -typedef struct NvmeErrorLog { +typedef struct QEMU_PACKED NvmeErrorLog { uint64_t error_count; uint16_t sqid; uint16_t cid; @@ -659,9 +723,9 @@ typedef struct NvmeErrorLog { uint8_t resv[35]; } NvmeErrorLog; -typedef struct NvmeSmartLog { +typedef struct QEMU_PACKED NvmeSmartLog { uint8_t critical_warning; - uint8_t temperature[2]; + uint16_t temperature; uint8_t available_spare; uint8_t available_spare_threshold; uint8_t percentage_used; @@ -687,13 +751,13 @@ enum NvmeSmartWarn { NVME_SMART_FAILED_VOLATILE_MEDIA = 1 << 4, }; -enum LogIdentifier { +enum NvmeLogIdentifier { NVME_LOG_ERROR_INFO = 0x01, NVME_LOG_SMART_INFO = 0x02, NVME_LOG_FW_SLOT_INFO = 0x03, }; -typedef struct NvmePSD { +typedef struct QEMU_PACKED NvmePSD { uint16_t mp; uint16_t reserved; uint32_t enlat; @@ -705,7 +769,16 @@ typedef struct NvmePSD { uint8_t resv[16]; } NvmePSD; -typedef struct NvmeIdCtrl { +#define NVME_IDENTIFY_DATA_SIZE 4096 + +enum { + NVME_ID_CNS_NS = 0x0, + NVME_ID_CNS_CTRL = 0x1, + NVME_ID_CNS_NS_ACTIVE_LIST = 0x2, + NVME_ID_CNS_NS_DESCR_LIST = 0x3, +}; + +typedef struct QEMU_PACKED NvmeIdCtrl { uint16_t vid; uint16_t ssvid; uint8_t sn[20]; @@ -715,7 +788,15 @@ typedef struct NvmeIdCtrl { uint8_t ieee[3]; uint8_t cmic; uint8_t mdts; - uint8_t rsvd255[178]; + uint16_t cntlid; + uint32_t ver; + uint32_t rtd3r; + uint32_t rtd3e; + uint32_t oaes; + uint32_t ctratt; + uint8_t rsvd100[12]; + uint8_t fguid[16]; + uint8_t rsvd128[128]; uint16_t oacs; uint8_t acl; uint8_t aerl; @@ -723,10 +804,28 @@ typedef struct NvmeIdCtrl { uint8_t lpa; uint8_t elpe; uint8_t npss; - uint8_t rsvd511[248]; + uint8_t avscc; + uint8_t apsta; + uint16_t wctemp; + uint16_t cctemp; + uint16_t mtfa; + uint32_t hmpre; + uint32_t hmmin; + uint8_t tnvmcap[16]; + uint8_t unvmcap[16]; + uint32_t rpmbs; + uint16_t edstt; + uint8_t dsto; + uint8_t fwug; + uint16_t kas; + uint16_t hctma; + uint16_t mntmt; + uint16_t mxtmt; + uint32_t sanicap; + uint8_t rsvd332[180]; uint8_t sqes; uint8_t cqes; - uint16_t rsvd515; + uint16_t maxcmd; uint32_t nn; uint16_t oncs; uint16_t fuses; @@ -734,8 +833,14 @@ typedef struct NvmeIdCtrl { uint8_t vwc; uint16_t awun; uint16_t awupf; - uint8_t rsvd703[174]; - uint8_t rsvd2047[1344]; + uint8_t nvscc; + uint8_t rsvd531; + uint16_t acwu; + uint8_t rsvd534[2]; + uint32_t sgls; + uint8_t rsvd540[228]; + uint8_t subnqn[256]; + uint8_t rsvd1024[1024]; NvmePSD psd[32]; uint8_t vs[1024]; } NvmeIdCtrl; @@ -750,32 +855,38 @@ enum NvmeIdCtrlOncs { NVME_ONCS_COMPARE = 1 << 0, NVME_ONCS_WRITE_UNCORR = 1 << 1, NVME_ONCS_DSM = 1 << 2, - NVME_ONCS_WRITE_ZEROS = 1 << 3, + NVME_ONCS_WRITE_ZEROES = 1 << 3, NVME_ONCS_FEATURES = 1 << 4, NVME_ONCS_RESRVATIONS = 1 << 5, NVME_ONCS_TIMESTAMP = 1 << 6, }; +enum NvmeIdCtrlFrmw { + NVME_FRMW_SLOT1_RO = 1 << 0, +}; + +enum NvmeIdCtrlLpa { + NVME_LPA_NS_SMART = 1 << 0, + NVME_LPA_EXTENDED = 1 << 2, +}; + #define NVME_CTRL_SQES_MIN(sqes) ((sqes) & 0xf) #define NVME_CTRL_SQES_MAX(sqes) (((sqes) >> 4) & 0xf) #define NVME_CTRL_CQES_MIN(cqes) ((cqes) & 0xf) #define NVME_CTRL_CQES_MAX(cqes) (((cqes) >> 4) & 0xf) -typedef struct NvmeFeatureVal { - uint32_t arbitration; - uint32_t power_mgmt; - uint32_t temp_thresh; - uint32_t err_rec; - uint32_t volatile_wc; - uint32_t num_queues; - uint32_t int_coalescing; - uint32_t *int_vector_config; - uint32_t write_atomicity; - uint32_t async_config; - uint32_t sw_prog_marker; -} NvmeFeatureVal; +#define NVME_CTRL_SGLS_SUPPORT_MASK (0x3 << 0) +#define NVME_CTRL_SGLS_SUPPORT_NO_ALIGN (0x1 << 0) +#define NVME_CTRL_SGLS_SUPPORT_DWORD_ALIGN (0x1 << 1) +#define NVME_CTRL_SGLS_KEYED (0x1 << 2) +#define NVME_CTRL_SGLS_BITBUCKET (0x1 << 16) +#define NVME_CTRL_SGLS_MPTR_CONTIGUOUS (0x1 << 17) +#define NVME_CTRL_SGLS_EXCESS_LENGTH (0x1 << 18) +#define NVME_CTRL_SGLS_MPTR_SGL (0x1 << 19) +#define NVME_CTRL_SGLS_ADDR_OFFSET (0x1 << 20) #define NVME_ARB_AB(arb) (arb & 0x7) +#define NVME_ARB_AB_NOLIMIT 0x7 #define NVME_ARB_LPW(arb) ((arb >> 8) & 0xff) #define NVME_ARB_MPW(arb) ((arb >> 16) & 0xff) #define NVME_ARB_HPW(arb) ((arb >> 24) & 0xff) @@ -783,6 +894,21 @@ typedef struct NvmeFeatureVal { #define NVME_INTC_THR(intc) (intc & 0xff) #define NVME_INTC_TIME(intc) ((intc >> 8) & 0xff) +#define NVME_INTVC_NOCOALESCING (0x1 << 16) + +#define NVME_TEMP_THSEL(temp) ((temp >> 20) & 0x3) +#define NVME_TEMP_THSEL_OVER 0x0 +#define NVME_TEMP_THSEL_UNDER 0x1 + +#define NVME_TEMP_TMPSEL(temp) ((temp >> 16) & 0xf) +#define NVME_TEMP_TMPSEL_COMPOSITE 0x0 + +#define NVME_TEMP_TMPTH(temp) (temp & 0xffff) + +#define NVME_AEC_SMART(aec) (aec & 0xff) +#define NVME_AEC_NS_ATTR(aec) ((aec >> 8) & 0x1) +#define NVME_AEC_FW_ACTIVATION(aec) ((aec >> 9) & 0x1) + enum NvmeFeatureIds { NVME_ARBITRATION = 0x1, NVME_POWER_MANAGEMENT = 0x2, @@ -796,10 +922,37 @@ enum NvmeFeatureIds { NVME_WRITE_ATOMICITY = 0xa, NVME_ASYNCHRONOUS_EVENT_CONF = 0xb, NVME_TIMESTAMP = 0xe, - NVME_SOFTWARE_PROGRESS_MARKER = 0x80 + NVME_SOFTWARE_PROGRESS_MARKER = 0x80, + NVME_FID_MAX = 0x100, }; -typedef struct NvmeRangeType { +typedef enum NvmeFeatureCap { + NVME_FEAT_CAP_SAVE = 1 << 0, + NVME_FEAT_CAP_NS = 1 << 1, + NVME_FEAT_CAP_CHANGE = 1 << 2, +} NvmeFeatureCap; + +typedef enum NvmeGetFeatureSelect { + NVME_GETFEAT_SELECT_CURRENT = 0x0, + NVME_GETFEAT_SELECT_DEFAULT = 0x1, + NVME_GETFEAT_SELECT_SAVED = 0x2, + NVME_GETFEAT_SELECT_CAP = 0x3, +} NvmeGetFeatureSelect; + +#define NVME_GETSETFEAT_FID_MASK 0xff +#define NVME_GETSETFEAT_FID(dw10) (dw10 & NVME_GETSETFEAT_FID_MASK) + +#define NVME_GETFEAT_SELECT_SHIFT 8 +#define NVME_GETFEAT_SELECT_MASK 0x7 +#define NVME_GETFEAT_SELECT(dw10) \ + ((dw10 >> NVME_GETFEAT_SELECT_SHIFT) & NVME_GETFEAT_SELECT_MASK) + +#define NVME_SETFEAT_SAVE_SHIFT 31 +#define NVME_SETFEAT_SAVE_MASK 0x1 +#define NVME_SETFEAT_SAVE(dw10) \ + ((dw10 >> NVME_SETFEAT_SAVE_SHIFT) & NVME_SETFEAT_SAVE_MASK) + +typedef struct QEMU_PACKED NvmeRangeType { uint8_t type; uint8_t attributes; uint8_t rsvd2[14]; @@ -809,13 +962,15 @@ typedef struct NvmeRangeType { uint8_t rsvd48[16]; } NvmeRangeType; -typedef struct NvmeLBAF { +typedef struct QEMU_PACKED NvmeLBAF { uint16_t ms; uint8_t ds; uint8_t rp; } NvmeLBAF; -typedef struct NvmeIdNs { +#define NVME_NSID_BROADCAST 0xffffffff + +typedef struct QEMU_PACKED NvmeIdNs { uint64_t nsze; uint64_t ncap; uint64_t nuse; @@ -825,18 +980,43 @@ typedef struct NvmeIdNs { uint8_t mc; uint8_t dpc; uint8_t dps; - uint8_t nmic; uint8_t rescap; uint8_t fpi; uint8_t dlfeat; - - uint8_t res34[94]; + uint16_t nawun; + uint16_t nawupf; + uint16_t nacwu; + uint16_t nabsn; + uint16_t nabo; + uint16_t nabspf; + uint16_t noiob; + uint8_t nvmcap[16]; + uint8_t rsvd64[40]; + uint8_t nguid[16]; + uint64_t eui64; NvmeLBAF lbaf[16]; - uint8_t res192[192]; + uint8_t rsvd192[192]; uint8_t vs[3712]; } NvmeIdNs; +typedef struct QEMU_PACKED NvmeIdNsDescr { + uint8_t nidt; + uint8_t nidl; + uint8_t rsvd2[2]; +} NvmeIdNsDescr; + +enum { + NVME_NIDT_EUI64_LEN = 8, + NVME_NIDT_NGUID_LEN = 16, + NVME_NIDT_UUID_LEN = 16, +}; + +enum NvmeNsIdentifierType { + NVME_NIDT_EUI64 = 0x1, + NVME_NIDT_NGUID = 0x2, + NVME_NIDT_UUID = 0x3, +}; /*Deallocate Logical Block Features*/ #define NVME_ID_NS_DLFEAT_GUARD_CRC(dlfeat) ((dlfeat) & 0x10) @@ -871,6 +1051,7 @@ enum NvmeIdNsDps { static inline void _nvme_check_size(void) { + QEMU_BUILD_BUG_ON(sizeof(NvmeBar) != 4096); QEMU_BUILD_BUG_ON(sizeof(NvmeAerResult) != 4); QEMU_BUILD_BUG_ON(sizeof(NvmeCqe) != 16); QEMU_BUILD_BUG_ON(sizeof(NvmeDsmRange) != 16); @@ -887,5 +1068,7 @@ static inline void _nvme_check_size(void) QEMU_BUILD_BUG_ON(sizeof(NvmeSmartLog) != 512); QEMU_BUILD_BUG_ON(sizeof(NvmeIdCtrl) != 4096); QEMU_BUILD_BUG_ON(sizeof(NvmeIdNs) != 4096); + QEMU_BUILD_BUG_ON(sizeof(NvmeSglDescriptor) != 16); + QEMU_BUILD_BUG_ON(sizeof(NvmeIdNsDescr) != 4); } #endif diff --git a/include/block/snapshot.h b/include/block/snapshot.h index 2bfcd57578982cbe312b71fc6be8c3e774a62ef7..b0fe42993dccf8d587159cbd6c9824faea6c071e 100644 --- a/include/block/snapshot.h +++ b/include/block/snapshot.h @@ -42,6 +42,7 @@ typedef struct QEMUSnapshotInfo { uint32_t date_sec; /* UTC date of the snapshot */ uint32_t date_nsec; uint64_t vm_clock_nsec; /* VM clock relative to boot */ + uint64_t icount; /* record/replay step */ } QEMUSnapshotInfo; int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info, diff --git a/include/block/throttle-groups.h b/include/block/throttle-groups.h index 712a8e64b489134d81a8a9391f6778a9e55a286f..8bf7d233fae57b1114aef45530837aa36a75666e 100644 --- a/include/block/throttle-groups.h +++ b/include/block/throttle-groups.h @@ -27,6 +27,7 @@ #include "qemu/throttle.h" #include "block/block_int.h" +#include "qom/object.h" /* The ThrottleGroupMember structure indicates membership in a ThrottleGroup * and holds related data. @@ -59,7 +60,7 @@ typedef struct ThrottleGroupMember { } ThrottleGroupMember; #define TYPE_THROTTLE_GROUP "throttle-group" -#define THROTTLE_GROUP(obj) OBJECT_CHECK(ThrottleGroup, (obj), TYPE_THROTTLE_GROUP) +OBJECT_DECLARE_SIMPLE_TYPE(ThrottleGroup, THROTTLE_GROUP) const char *throttle_group_get_name(ThrottleGroupMember *tgm); diff --git a/include/chardev/char-fd.h b/include/chardev/char-fd.h index e7c2b176f90160fbf24f8a85834a8f214694ab66..9de0e440de5b22dbf6bf93b5daa690e2db03086b 100644 --- a/include/chardev/char-fd.h +++ b/include/chardev/char-fd.h @@ -26,17 +26,20 @@ #include "io/channel.h" #include "chardev/char.h" +#include "qom/object.h" -typedef struct FDChardev { +struct FDChardev { Chardev parent; QIOChannel *ioc_in, *ioc_out; int max_size; -} FDChardev; +}; +typedef struct FDChardev FDChardev; #define TYPE_CHARDEV_FD "chardev-fd" -#define FD_CHARDEV(obj) OBJECT_CHECK(FDChardev, (obj), TYPE_CHARDEV_FD) +DECLARE_INSTANCE_CHECKER(FDChardev, FD_CHARDEV, + TYPE_CHARDEV_FD) void qemu_chr_open_fd(Chardev *chr, int fd_in, int fd_out); int qmp_chardev_open_file_source(char *src, int flags, Error **errp); diff --git a/include/chardev/char-win.h b/include/chardev/char-win.h index fa59e9e423ac66ef68072a85852af1c1cc25e80c..485521469cee5324b203dce1b58ef5eaf4a36d50 100644 --- a/include/chardev/char-win.h +++ b/include/chardev/char-win.h @@ -25,8 +25,9 @@ #define CHAR_WIN_H #include "chardev/char.h" +#include "qom/object.h" -typedef struct { +struct WinChardev { Chardev parent; bool keep_open; /* console do not close file */ @@ -36,13 +37,15 @@ typedef struct { /* Protected by the Chardev chr_write_lock. */ OVERLAPPED osend; -} WinChardev; +}; +typedef struct WinChardev WinChardev; #define NSENDBUF 2048 #define NRECVBUF 2048 #define TYPE_CHARDEV_WIN "chardev-win" -#define WIN_CHARDEV(obj) OBJECT_CHECK(WinChardev, (obj), TYPE_CHARDEV_WIN) +DECLARE_INSTANCE_CHECKER(WinChardev, WIN_CHARDEV, + TYPE_CHARDEV_WIN) void win_chr_set_file(Chardev *chr, HANDLE file, bool keep_open); int win_chr_serial_init(Chardev *chr, const char *filename, Error **errp); diff --git a/include/chardev/char.h b/include/chardev/char.h index 00589a60256cfcabac2adf71413a60958d148ce8..db42f0a8c6310ac22c7c059f33a4a4470dde4111 100644 --- a/include/chardev/char.h +++ b/include/chardev/char.h @@ -226,11 +226,7 @@ int qemu_chr_write(Chardev *s, const uint8_t *buf, int len, bool write_all); int qemu_chr_wait_connected(Chardev *chr, Error **errp); #define TYPE_CHARDEV "chardev" -#define CHARDEV(obj) OBJECT_CHECK(Chardev, (obj), TYPE_CHARDEV) -#define CHARDEV_CLASS(klass) \ - OBJECT_CLASS_CHECK(ChardevClass, (klass), TYPE_CHARDEV) -#define CHARDEV_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ChardevClass, (obj), TYPE_CHARDEV) +OBJECT_DECLARE_TYPE(Chardev, ChardevClass, CHARDEV) #define TYPE_CHARDEV_NULL "chardev-null" #define TYPE_CHARDEV_MUX "chardev-mux" @@ -251,7 +247,7 @@ int qemu_chr_wait_connected(Chardev *chr, Error **errp); #define CHARDEV_IS_PTY(chr) \ object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_PTY) -typedef struct ChardevClass { +struct ChardevClass { ObjectClass parent_class; bool internal; /* TODO: eventually use TYPE_USER_CREATABLE */ @@ -276,7 +272,7 @@ typedef struct ChardevClass { void (*chr_be_event)(Chardev *s, QEMUChrEvent event); /* Return 0 if succeeded, 1 if failed */ int (*chr_machine_done)(Chardev *chr); -} ChardevClass; +}; Chardev *qemu_chardev_new(const char *id, const char *typename, ChardevBackend *backend, GMainContext *context, diff --git a/include/chardev/spice.h b/include/chardev/spice.h index 1f7339b649dc066fb6e138a16187ef44e4e26a7f..58e5b727e9fe35bf112c32989b22fca930a449ec 100644 --- a/include/chardev/spice.h +++ b/include/chardev/spice.h @@ -3,8 +3,9 @@ #include #include "chardev/char-fe.h" +#include "qom/object.h" -typedef struct SpiceChardev { +struct SpiceChardev { Chardev parent; SpiceCharDeviceInstance sin; @@ -12,16 +13,14 @@ typedef struct SpiceChardev { bool blocked; const uint8_t *datapos; int datalen; - QLIST_ENTRY(SpiceChardev) next; -} SpiceChardev; +}; +typedef struct SpiceChardev SpiceChardev; #define TYPE_CHARDEV_SPICE "chardev-spice" #define TYPE_CHARDEV_SPICEVMC "chardev-spicevmc" #define TYPE_CHARDEV_SPICEPORT "chardev-spiceport" -#define SPICE_CHARDEV(obj) OBJECT_CHECK(SpiceChardev, (obj), TYPE_CHARDEV_SPICE) - -void qemu_chr_open_spice_port(Chardev *chr, ChardevBackend *backend, - bool *be_opened, Error **errp); +DECLARE_INSTANCE_CHECKER(SpiceChardev, SPICE_CHARDEV, + TYPE_CHARDEV_SPICE) #endif diff --git a/include/crypto/aes.h b/include/crypto/aes.h index 12fb321b89de319a6ceb42512787cdd2dee195c9..ba297d6a73e7d9075da383a9902d5f8ec43de34b 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -16,7 +16,6 @@ typedef struct aes_key_st AES_KEY; #define AES_set_decrypt_key QEMU_AES_set_decrypt_key #define AES_encrypt QEMU_AES_encrypt #define AES_decrypt QEMU_AES_decrypt -#define AES_cbc_encrypt QEMU_AES_cbc_encrypt int AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key); @@ -27,9 +26,6 @@ void AES_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key); void AES_decrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key); -void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, - const unsigned long length, const AES_KEY *key, - unsigned char *ivec, const int enc); extern const uint8_t AES_sbox[256]; extern const uint8_t AES_isbox[256]; diff --git a/include/crypto/block.h b/include/crypto/block.h index c77ccaf9c0a8cb2875be5a26068ab20bc3e204dc..7a65e8e402a4e72ad1e6874f1e4b8d3ad0408b2e 100644 --- a/include/crypto/block.h +++ b/include/crypto/block.h @@ -144,6 +144,28 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options, void *opaque, Error **errp); +/** + * qcrypto_block_amend_options: + * @block: the block encryption object + * + * @readfunc: callback for reading data from the volume header + * @writefunc: callback for writing data to the volume header + * @opaque: data to pass to @readfunc and @writefunc + * @options: the new/amended encryption options + * @force: hint for the driver to allow unsafe operation + * @errp: error pointer + * + * Changes the crypto options of the encryption format + * + */ +int qcrypto_block_amend_options(QCryptoBlock *block, + QCryptoBlockReadFunc readfunc, + QCryptoBlockWriteFunc writefunc, + void *opaque, + QCryptoBlockAmendOptions *options, + bool force, + Error **errp); + /** * qcrypto_block_calculate_payload_offset: @@ -289,7 +311,5 @@ uint64_t qcrypto_block_get_sector_size(QCryptoBlock *block); void qcrypto_block_free(QCryptoBlock *block); G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoBlock, qcrypto_block_free) -G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoBlockCreateOptions, - qapi_free_QCryptoBlockCreateOptions) #endif /* QCRYPTO_BLOCK_H */ diff --git a/include/crypto/cipher.h b/include/crypto/cipher.h index 5928e5ecc72e762cf5cb79e793b1cb423932eac1..083e12a7d9e824ba021eb0bc7e1c64ce79eb103d 100644 --- a/include/crypto/cipher.h +++ b/include/crypto/cipher.h @@ -24,6 +24,7 @@ #include "qapi/qapi-types-crypto.h" typedef struct QCryptoCipher QCryptoCipher; +typedef struct QCryptoCipherDriver QCryptoCipherDriver; /* See also "QCryptoCipherAlgorithm" and "QCryptoCipherMode" * enums defined in qapi/crypto.json */ @@ -79,8 +80,7 @@ typedef struct QCryptoCipher QCryptoCipher; struct QCryptoCipher { QCryptoCipherAlgorithm alg; QCryptoCipherMode mode; - void *opaque; - void *driver; + const QCryptoCipherDriver *driver; }; /** diff --git a/include/crypto/secret.h b/include/crypto/secret.h index 5e07e29bae4a0346dafe1221724708e0f8496b8d..5d20ae6d2f8b4fe07d39eabc90fb68bd23113e1d 100644 --- a/include/crypto/secret.h +++ b/include/crypto/secret.h @@ -23,12 +23,13 @@ #include "qapi/qapi-types-crypto.h" #include "qom/object.h" +#include "crypto/secret_common.h" #define TYPE_QCRYPTO_SECRET "secret" -#define QCRYPTO_SECRET(obj) \ - OBJECT_CHECK(QCryptoSecret, (obj), TYPE_QCRYPTO_SECRET) - typedef struct QCryptoSecret QCryptoSecret; +DECLARE_INSTANCE_CHECKER(QCryptoSecret, QCRYPTO_SECRET, + TYPE_QCRYPTO_SECRET) + typedef struct QCryptoSecretClass QCryptoSecretClass; /** @@ -119,29 +120,14 @@ typedef struct QCryptoSecretClass QCryptoSecretClass; */ struct QCryptoSecret { - Object parent_obj; - uint8_t *rawdata; - size_t rawlen; - QCryptoSecretFormat format; + QCryptoSecretCommon parent_obj; char *data; char *file; - char *keyid; - char *iv; }; struct QCryptoSecretClass { - ObjectClass parent_class; + QCryptoSecretCommonClass parent_class; }; - -extern int qcrypto_secret_lookup(const char *secretid, - uint8_t **data, - size_t *datalen, - Error **errp); -extern char *qcrypto_secret_lookup_as_utf8(const char *secretid, - Error **errp); -extern char *qcrypto_secret_lookup_as_base64(const char *secretid, - Error **errp); - #endif /* QCRYPTO_SECRET_H */ diff --git a/include/crypto/secret_common.h b/include/crypto/secret_common.h new file mode 100644 index 0000000000000000000000000000000000000000..42c7ff7af65217653266723088976b38ba95b4a6 --- /dev/null +++ b/include/crypto/secret_common.h @@ -0,0 +1,60 @@ +/* + * QEMU crypto secret support + * + * Copyright (c) 2015 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + */ + +#ifndef QCRYPTO_SECRET_COMMON_H +#define QCRYPTO_SECRET_COMMON_H + +#include "qapi/qapi-types-crypto.h" +#include "qom/object.h" + +#define TYPE_QCRYPTO_SECRET_COMMON "secret_common" +OBJECT_DECLARE_TYPE(QCryptoSecretCommon, QCryptoSecretCommonClass, + QCRYPTO_SECRET_COMMON) + + +struct QCryptoSecretCommon { + Object parent_obj; + uint8_t *rawdata; + size_t rawlen; + QCryptoSecretFormat format; + char *keyid; + char *iv; +}; + + +struct QCryptoSecretCommonClass { + ObjectClass parent_class; + void (*load_data)(QCryptoSecretCommon *secret, + uint8_t **output, + size_t *outputlen, + Error **errp); +}; + + +extern int qcrypto_secret_lookup(const char *secretid, + uint8_t **data, + size_t *datalen, + Error **errp); +extern char *qcrypto_secret_lookup_as_utf8(const char *secretid, + Error **errp); +extern char *qcrypto_secret_lookup_as_base64(const char *secretid, + Error **errp); + +#endif /* QCRYPTO_SECRET_COMMON_H */ diff --git a/include/crypto/secret_keyring.h b/include/crypto/secret_keyring.h new file mode 100644 index 0000000000000000000000000000000000000000..3758852cb8988d05631049fae190b8c72f9b9787 --- /dev/null +++ b/include/crypto/secret_keyring.h @@ -0,0 +1,40 @@ +/* + * QEMU crypto secret support + * + * Copyright 2020 Yandex N.V. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + */ + +#ifndef QCRYPTO_SECRET_KEYRING_H +#define QCRYPTO_SECRET_KEYRING_H + +#include "qapi/qapi-types-crypto.h" +#include "qom/object.h" +#include "crypto/secret_common.h" + +#define TYPE_QCRYPTO_SECRET_KEYRING "secret_keyring" +OBJECT_DECLARE_SIMPLE_TYPE(QCryptoSecretKeyring, + QCRYPTO_SECRET_KEYRING) + + +struct QCryptoSecretKeyring { + QCryptoSecretCommon parent; + int32_t serial; +}; + + + +#endif /* QCRYPTO_SECRET_KEYRING_H */ diff --git a/include/crypto/tls-cipher-suites.h b/include/crypto/tls-cipher-suites.h new file mode 100644 index 0000000000000000000000000000000000000000..bb9ee53e03a1dfc2edf39ac09033c261e382853b --- /dev/null +++ b/include/crypto/tls-cipher-suites.h @@ -0,0 +1,40 @@ +/* + * QEMU TLS Cipher Suites Registry (RFC8447) + * + * Copyright (c) 2018-2020 Red Hat, Inc. + * + * Author: Philippe Mathieu-DaudĂ© + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef QCRYPTO_TLSCIPHERSUITES_H +#define QCRYPTO_TLSCIPHERSUITES_H + +#include "qom/object.h" +#include "crypto/tlscreds.h" + +#define TYPE_QCRYPTO_TLS_CIPHER_SUITES "tls-cipher-suites" +typedef struct QCryptoTLSCipherSuites QCryptoTLSCipherSuites; +DECLARE_INSTANCE_CHECKER(QCryptoTLSCipherSuites, QCRYPTO_TLS_CIPHER_SUITES, + TYPE_QCRYPTO_TLS_CIPHER_SUITES) + +struct QCryptoTLSCipherSuites { + /* */ + QCryptoTLSCreds parent_obj; + /* */ +}; + +/** + * qcrypto_tls_cipher_suites_get_data: + * @obj: pointer to a TLS cipher suites object + * @errp: pointer to a NULL-initialized error object + * + * Returns: reference to a byte array containing the data. + * The caller should release the reference when no longer + * required. + */ +GByteArray *qcrypto_tls_cipher_suites_get_data(QCryptoTLSCipherSuites *obj, + Error **errp); + +#endif /* QCRYPTO_TLSCIPHERSUITES_H */ diff --git a/include/crypto/tlscreds.h b/include/crypto/tlscreds.h index fd7a284aa225084a5aecc7d24fd06de52a0241dc..079e37604784959bb2c7a97e7ffe07782228d426 100644 --- a/include/crypto/tlscreds.h +++ b/include/crypto/tlscreds.h @@ -29,10 +29,10 @@ #endif #define TYPE_QCRYPTO_TLS_CREDS "tls-creds" -#define QCRYPTO_TLS_CREDS(obj) \ - OBJECT_CHECK(QCryptoTLSCreds, (obj), TYPE_QCRYPTO_TLS_CREDS) - typedef struct QCryptoTLSCreds QCryptoTLSCreds; +DECLARE_INSTANCE_CHECKER(QCryptoTLSCreds, QCRYPTO_TLS_CREDS, + TYPE_QCRYPTO_TLS_CREDS) + typedef struct QCryptoTLSCredsClass QCryptoTLSCredsClass; #define QCRYPTO_TLS_CREDS_DH_PARAMS "dh-params.pem" diff --git a/include/crypto/tlscredsanon.h b/include/crypto/tlscredsanon.h index 9e9a5ce1a8b33195fa85be095664dc8f4826bdda..3f464a380958266afb47785c00615247b2f4bd1c 100644 --- a/include/crypto/tlscredsanon.h +++ b/include/crypto/tlscredsanon.h @@ -22,13 +22,14 @@ #define QCRYPTO_TLSCREDSANON_H #include "crypto/tlscreds.h" +#include "qom/object.h" #define TYPE_QCRYPTO_TLS_CREDS_ANON "tls-creds-anon" -#define QCRYPTO_TLS_CREDS_ANON(obj) \ - OBJECT_CHECK(QCryptoTLSCredsAnon, (obj), TYPE_QCRYPTO_TLS_CREDS_ANON) +typedef struct QCryptoTLSCredsAnon QCryptoTLSCredsAnon; +DECLARE_INSTANCE_CHECKER(QCryptoTLSCredsAnon, QCRYPTO_TLS_CREDS_ANON, + TYPE_QCRYPTO_TLS_CREDS_ANON) -typedef struct QCryptoTLSCredsAnon QCryptoTLSCredsAnon; typedef struct QCryptoTLSCredsAnonClass QCryptoTLSCredsAnonClass; /** diff --git a/include/crypto/tlscredspsk.h b/include/crypto/tlscredspsk.h index 907035a29b7f3bb32fce3dfd065507a6a54fb7aa..d7e6bdb5edf40ebf47add117679a0069aac62c76 100644 --- a/include/crypto/tlscredspsk.h +++ b/include/crypto/tlscredspsk.h @@ -22,12 +22,13 @@ #define QCRYPTO_TLSCREDSPSK_H #include "crypto/tlscreds.h" +#include "qom/object.h" #define TYPE_QCRYPTO_TLS_CREDS_PSK "tls-creds-psk" -#define QCRYPTO_TLS_CREDS_PSK(obj) \ - OBJECT_CHECK(QCryptoTLSCredsPSK, (obj), TYPE_QCRYPTO_TLS_CREDS_PSK) - typedef struct QCryptoTLSCredsPSK QCryptoTLSCredsPSK; +DECLARE_INSTANCE_CHECKER(QCryptoTLSCredsPSK, QCRYPTO_TLS_CREDS_PSK, + TYPE_QCRYPTO_TLS_CREDS_PSK) + typedef struct QCryptoTLSCredsPSKClass QCryptoTLSCredsPSKClass; #define QCRYPTO_TLS_CREDS_PSKFILE "keys.psk" diff --git a/include/crypto/tlscredsx509.h b/include/crypto/tlscredsx509.h index e1542e5c8cba1d05c6a11f988e6197ec149c3b64..c6d89b78819f441a107033865af4f000856d16cb 100644 --- a/include/crypto/tlscredsx509.h +++ b/include/crypto/tlscredsx509.h @@ -22,12 +22,13 @@ #define QCRYPTO_TLSCREDSX509_H #include "crypto/tlscreds.h" +#include "qom/object.h" #define TYPE_QCRYPTO_TLS_CREDS_X509 "tls-creds-x509" -#define QCRYPTO_TLS_CREDS_X509(obj) \ - OBJECT_CHECK(QCryptoTLSCredsX509, (obj), TYPE_QCRYPTO_TLS_CREDS_X509) - typedef struct QCryptoTLSCredsX509 QCryptoTLSCredsX509; +DECLARE_INSTANCE_CHECKER(QCryptoTLSCredsX509, QCRYPTO_TLS_CREDS_X509, + TYPE_QCRYPTO_TLS_CREDS_X509) + typedef struct QCryptoTLSCredsX509Class QCryptoTLSCredsX509Class; #define QCRYPTO_TLS_CREDS_X509_CA_CERT "ca-cert.pem" diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h index c5f9fa08abcd97b490d3d9a680a98034287389ba..2164762b4670a7c1038eaefc99a0ded6c6781cb4 100644 --- a/include/disas/dis-asm.h +++ b/include/disas/dis-asm.h @@ -211,6 +211,25 @@ enum bfd_architecture #define bfd_mach_m32r 0 /* backwards compatibility */ bfd_arch_mn10200, /* Matsushita MN10200 */ bfd_arch_mn10300, /* Matsushita MN10300 */ + bfd_arch_avr, /* AVR microcontrollers */ +#define bfd_mach_avr1 1 +#define bfd_mach_avr2 2 +#define bfd_mach_avr25 25 +#define bfd_mach_avr3 3 +#define bfd_mach_avr31 31 +#define bfd_mach_avr35 35 +#define bfd_mach_avr4 4 +#define bfd_mach_avr5 5 +#define bfd_mach_avr51 51 +#define bfd_mach_avr6 6 +#define bfd_mach_avrtiny 100 +#define bfd_mach_avrxmega1 101 +#define bfd_mach_avrxmega2 102 +#define bfd_mach_avrxmega3 103 +#define bfd_mach_avrxmega4 104 +#define bfd_mach_avrxmega5 105 +#define bfd_mach_avrxmega6 106 +#define bfd_mach_avrxmega7 107 bfd_arch_cris, /* Axis CRIS */ #define bfd_mach_cris_v0_v10 255 #define bfd_mach_cris_v32 32 @@ -387,7 +406,6 @@ typedef struct disassemble_info { } disassemble_info; - /* Standard disassemblers. Disassemble one instruction at the given target address. Return number of bytes processed. */ typedef int (*disassembler_ftype) (bfd_vma, disassemble_info *); @@ -442,66 +460,17 @@ int print_insn_riscv32 (bfd_vma, disassemble_info*); int print_insn_riscv64 (bfd_vma, disassemble_info*); int print_insn_rx(bfd_vma, disassemble_info *); -#if 0 -/* Fetch the disassembler for a given BFD, if that support is available. */ -disassembler_ftype disassembler(bfd *); -#endif - - -/* This block of definitions is for particular callers who read instructions - into a buffer before calling the instruction decoder. */ - -/* Here is a function which callers may wish to use for read_memory_func. - It gets bytes from a buffer. */ -int buffer_read_memory(bfd_vma, bfd_byte *, int, struct disassemble_info *); - -/* This function goes with buffer_read_memory. - It prints a message using info->fprintf_func and info->stream. */ -void perror_memory(int, bfd_vma, struct disassemble_info *); - - -/* Just print the address in hex. This is included for completeness even - though both GDB and objdump provide their own (to print symbolic - addresses). */ -void generic_print_address(bfd_vma, struct disassemble_info *); - -/* Always true. */ -int generic_symbol_at_address(bfd_vma, struct disassemble_info *); - -/* Macro to initialize a disassemble_info struct. This should be called - by all applications creating such a struct. */ -#define INIT_DISASSEMBLE_INFO(INFO, STREAM, FPRINTF_FUNC) \ - (INFO).flavour = bfd_target_unknown_flavour, \ - (INFO).arch = bfd_arch_unknown, \ - (INFO).mach = 0, \ - (INFO).endian = BFD_ENDIAN_UNKNOWN, \ - INIT_DISASSEMBLE_INFO_NO_ARCH(INFO, STREAM, FPRINTF_FUNC) - -/* Call this macro to initialize only the internal variables for the - disassembler. Architecture dependent things such as byte order, or machine - variant are not touched by this macro. This makes things much easier for - GDB which must initialize these things separately. */ - -#define INIT_DISASSEMBLE_INFO_NO_ARCH(INFO, STREAM, FPRINTF_FUNC) \ - (INFO).fprintf_func = (FPRINTF_FUNC), \ - (INFO).stream = (STREAM), \ - (INFO).symbols = NULL, \ - (INFO).num_symbols = 0, \ - (INFO).private_data = NULL, \ - (INFO).buffer = NULL, \ - (INFO).buffer_vma = 0, \ - (INFO).buffer_length = 0, \ - (INFO).read_memory_func = buffer_read_memory, \ - (INFO).memory_error_func = perror_memory, \ - (INFO).print_address_func = generic_print_address, \ - (INFO).print_insn = NULL, \ - (INFO).symbol_at_address_func = generic_symbol_at_address, \ - (INFO).flags = 0, \ - (INFO).bytes_per_line = 0, \ - (INFO).bytes_per_chunk = 0, \ - (INFO).display_endian = BFD_ENDIAN_UNKNOWN, \ - (INFO).disassembler_options = NULL, \ - (INFO).insn_info_valid = 0 +#ifdef CONFIG_CAPSTONE +bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size); +bool cap_disas_host(disassemble_info *info, void *code, size_t size); +bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count); +bool cap_disas_plugin(disassemble_info *info, uint64_t pc, size_t size); +#else +# define cap_disas_target(i, p, s) false +# define cap_disas_host(i, p, s) false +# define cap_disas_monitor(i, p, c) false +# define cap_disas_plugin(i, p, c) false +#endif /* CONFIG_CAPSTONE */ #ifndef ATTRIBUTE_UNUSED #define ATTRIBUTE_UNUSED __attribute__((unused)) @@ -509,11 +478,33 @@ int generic_symbol_at_address(bfd_vma, struct disassemble_info *); /* from libbfd */ -bfd_vma bfd_getl64 (const bfd_byte *addr); -bfd_vma bfd_getl32 (const bfd_byte *addr); -bfd_vma bfd_getb32 (const bfd_byte *addr); -bfd_vma bfd_getl16 (const bfd_byte *addr); -bfd_vma bfd_getb16 (const bfd_byte *addr); +#include "qemu/bswap.h" + +static inline bfd_vma bfd_getl64(const bfd_byte *addr) +{ + return ldq_le_p(addr); +} + +static inline bfd_vma bfd_getl32(const bfd_byte *addr) +{ + return (uint32_t)ldl_le_p(addr); +} + +static inline bfd_vma bfd_getl16(const bfd_byte *addr) +{ + return lduw_le_p(addr); +} + +static inline bfd_vma bfd_getb32(const bfd_byte *addr) +{ + return (uint32_t)ldl_be_p(addr); +} + +static inline bfd_vma bfd_getb16(const bfd_byte *addr) +{ + return lduw_be_p(addr); +} + typedef bool bfd_boolean; #endif /* DISAS_DIS_ASM_H */ diff --git a/include/disas/disas.h b/include/disas/disas.h index 1b6e035e32db0f0a6cad345ff829de73481d0d8f..36c33f6f194c2541d5deeb07252cfe3ae9078ee4 100644 --- a/include/disas/disas.h +++ b/include/disas/disas.h @@ -7,7 +7,7 @@ #include "cpu.h" /* Disassemble this for me please... (debugging). */ -void disas(FILE *out, void *code, unsigned long size, const char *note); +void disas(FILE *out, void *code, unsigned long size); void target_disas(FILE *out, CPUState *cpu, target_ulong code, target_ulong size); diff --git a/include/elf.h b/include/elf.h index 8fbfe60e09f23be2f905e863026f58594f864ec3..7a418ee559349365fe18bf0924a031df963c599f 100644 --- a/include/elf.h +++ b/include/elf.h @@ -26,9 +26,13 @@ typedef int64_t Elf64_Sxword; #define PT_NOTE 4 #define PT_SHLIB 5 #define PT_PHDR 6 +#define PT_LOOS 0x60000000 +#define PT_HIOS 0x6fffffff #define PT_LOPROC 0x70000000 #define PT_HIPROC 0x7fffffff +#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553) + #define PT_MIPS_REGINFO 0x70000000 #define PT_MIPS_RTPROC 0x70000001 #define PT_MIPS_OPTIONS 0x70000002 @@ -160,6 +164,8 @@ typedef struct mips_elf_abiflags_v0 { #define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ +#define EM_AVR 83 /* AVR 8-bit microcontroller */ + #define EM_V850 87 /* NEC v850 */ #define EM_H8_300H 47 /* Hitachi H8/300H */ @@ -170,6 +176,8 @@ typedef struct mips_elf_abiflags_v0 { #define EM_UNICORE32 110 /* UniCore32 */ +#define EM_RX 173 /* Renesas RX family */ + #define EM_RISCV 243 /* RISC-V */ #define EM_NANOMIPS 249 /* Wave Computing nanoMIPS */ @@ -202,6 +210,8 @@ typedef struct mips_elf_abiflags_v0 { #define EM_MOXIE 223 /* Moxie processor family */ #define EM_MOXIE_OLD 0xFEED +#define EF_AVR_MACH 0x7F /* Mask for AVR e_flags to get core type */ + /* This is the info that is needed to parse the dynamic section of the file */ #define DT_NULL 0 #define DT_NEEDED 1 @@ -554,6 +564,7 @@ typedef struct { #define PPC_FEATURE2_HTM_NOSC 0x01000000 #define PPC_FEATURE2_ARCH_3_00 0x00800000 #define PPC_FEATURE2_HAS_IEEE128 0x00400000 +#define PPC_FEATURE2_ARCH_3_10 0x00040000 /* Bits present in AT_HWCAP for Sparc. */ @@ -1652,6 +1663,24 @@ typedef struct elf64_shdr { #define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */ #define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension regs */ +/* Defined note types for GNU systems. */ + +#define NT_GNU_PROPERTY_TYPE_0 5 /* Program property */ + +/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0). */ + +#define GNU_PROPERTY_STACK_SIZE 1 +#define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2 + +#define GNU_PROPERTY_LOPROC 0xc0000000 +#define GNU_PROPERTY_HIPROC 0xdfffffff +#define GNU_PROPERTY_LOUSER 0xe0000000 +#define GNU_PROPERTY_HIUSER 0xffffffff + +#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 +#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1u << 0) +#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1u << 1) + /* * Physical entry point into the kernel. * diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index d14374bdd4999b556df9b6f05b72855a535d57ec..4b5408c34158c073c3016115a6e42f3c20078fe0 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -176,11 +176,9 @@ extern unsigned long reserved_va; * avoid setting bits at the top of guest addresses that might need * to be used for tags. */ -#if MIN(TARGET_VIRT_ADDR_SPACE_BITS, TARGET_ABI_BITS) <= 32 -# define GUEST_ADDR_MAX_ UINT32_MAX -#else -# define GUEST_ADDR_MAX_ (~0ul) -#endif +#define GUEST_ADDR_MAX_ \ + ((MIN_CONST(TARGET_VIRT_ADDR_SPACE_BITS, TARGET_ABI_BITS) <= 32) ? \ + UINT32_MAX : ~0ul) #define GUEST_ADDR_MAX (reserved_va ? reserved_va - 1 : GUEST_ADDR_MAX_) #else @@ -191,13 +189,13 @@ extern unsigned long reserved_va; #define ARG1 as #define ARG1_DECL AddressSpace *as #define TARGET_ENDIANNESS -#include "exec/memory_ldst.inc.h" +#include "exec/memory_ldst.h.inc" #define SUFFIX _cached_slow #define ARG1 cache #define ARG1_DECL MemoryRegionCache *cache #define TARGET_ENDIANNESS -#include "exec/memory_ldst.inc.h" +#include "exec/memory_ldst.h.inc" static inline void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val) { @@ -209,17 +207,17 @@ static inline void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val #define ARG1 as #define ARG1_DECL AddressSpace *as #define TARGET_ENDIANNESS -#include "exec/memory_ldst_phys.inc.h" +#include "exec/memory_ldst_phys.h.inc" /* Inline fast path for direct RAM access. */ #define ENDIANNESS -#include "exec/memory_ldst_cached.inc.h" +#include "exec/memory_ldst_cached.h.inc" #define SUFFIX _cached #define ARG1 cache #define ARG1_DECL MemoryRegionCache *cache #define TARGET_ENDIANNESS -#include "exec/memory_ldst_phys.inc.h" +#include "exec/memory_ldst_phys.h.inc" #endif /* page related stuff */ @@ -276,6 +274,8 @@ extern intptr_t qemu_host_page_mask; /* FIXME: Code that sets/uses this is broken and needs to go away. */ #define PAGE_RESERVED 0x0020 #endif +/* Target-specific bits that will be used via page_get_flags(). */ +#define PAGE_TARGET_1 0x0080 #if defined(CONFIG_USER_ONLY) void page_dump(FILE *f); @@ -409,10 +409,15 @@ static inline bool tlb_hit(target_ulong tlb_addr, target_ulong addr) return tlb_hit_page(tlb_addr, addr & TARGET_PAGE_MASK); } +#ifdef CONFIG_TCG +void dump_drift_info(void); void dump_exec_info(void); void dump_opcount_info(void); +#endif /* CONFIG_TCG */ + #endif /* !CONFIG_USER_ONLY */ +/* Returns: 0 on success, -1 on error */ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr, void *ptr, target_ulong len, bool is_write); diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index b47e5630e75d3cd387a87b38186d5dbb989f668e..19805ed6db2ea6b697863be3ba6e157e22b0465e 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -14,6 +14,9 @@ void cpu_list_unlock(void); void tcg_flush_softmmu_tlb(CPUState *cs); +void tcg_iommu_init_notifier_list(CPUState *cpu); +void tcg_iommu_free_notifier_list(CPUState *cpu); + #if !defined(CONFIG_USER_ONLY) enum device_endian { @@ -43,9 +46,6 @@ extern ram_addr_t ram_size; /* memory API */ -typedef void CPUWriteMemoryFunc(void *opaque, hwaddr addr, uint32_t value); -typedef uint32_t CPUReadMemoryFunc(void *opaque, hwaddr addr); - void qemu_ram_remap(ram_addr_t addr, ram_addr_t length); /* This should not be used by devices. */ ram_addr_t qemu_ram_addr_from_host(void *ptr); diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index 8c44abefa22a9b0ffecad7386a420cc2fd99efb3..d1f5e3fc3d874dca3738766b4eecd63aecfb3091 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -102,8 +102,13 @@ typedef uint64_t target_ulong; * Skylake's Level-2 STLB has 16 1G entries. * Also, make sure we do not size the TLB past the guest's address space. */ -# define CPU_TLB_DYN_MAX_BITS \ +# ifdef TARGET_PAGE_BITS_VARY +# define CPU_TLB_DYN_MAX_BITS \ MIN(22, TARGET_VIRT_ADDR_SPACE_BITS - TARGET_PAGE_BITS) +# else +# define CPU_TLB_DYN_MAX_BITS \ + MIN_CONST(22, TARGET_VIRT_ADDR_SPACE_BITS - TARGET_PAGE_BITS) +# endif # endif typedef struct CPUTLBEntry { diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h index c14a48f65e215b322a762f17e30fb9a9c47e3f01..ef54cb7e1f87fa03eb58b136f17c41d76cc1f5f3 100644 --- a/include/exec/cpu_ldst.h +++ b/include/exec/cpu_ldst.h @@ -4,7 +4,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -299,7 +299,7 @@ static inline target_ulong tlb_addr_write(const CPUTLBEntry *entry) #if TCG_OVERSIZED_GUEST return entry->addr_write; #else - return atomic_read(&entry->addr_write); + return qatomic_read(&entry->addr_write); #endif } diff --git a/include/exec/cputlb.h b/include/exec/cputlb.h index a62cfb28d5db00027c3ee397c4ca4b097a2ade9e..19b16e58f84e4b93c6cfc771c51afad8a0527657 100644 --- a/include/exec/cputlb.h +++ b/include/exec/cputlb.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 8792bea07ab22bc8ac7290e194f0b58ed223fb73..94fe05daaa189af514e7e01f37483aa58171d900 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,7 +25,7 @@ #ifdef CONFIG_TCG #include "exec/cpu_ldst.h" #endif -#include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" /* allow to see translation results - the slowdown should be negligible, so we leave it */ #define DEBUG_DISAS @@ -89,7 +89,7 @@ void QEMU_NORETURN cpu_loop_exit_atomic(CPUState *cpu, uintptr_t pc); */ static inline bool cpu_loop_exit_requested(CPUState *cpu) { - return (int32_t)atomic_read(&cpu_neg(cpu)->icount_decr.u32) < 0; + return (int32_t)qatomic_read(&cpu_neg(cpu)->icount_decr.u32) < 0; } #if !defined(CONFIG_USER_ONLY) @@ -124,6 +124,11 @@ void cpu_address_space_init(CPUState *cpu, int asidx, * @cpu: CPU whose TLB should be initialized */ void tlb_init(CPUState *cpu); +/** + * tlb_destroy - destroy a CPU's TLB + * @cpu: CPU whose TLB should be destroyed + */ +void tlb_destroy(CPUState *cpu); /** * tlb_flush_page: * @cpu: CPU whose TLB should be flushed @@ -246,6 +251,25 @@ void tlb_flush_by_mmuidx_all_cpus(CPUState *cpu, uint16_t idxmap); * depend on when the guests translation ends the TB. */ void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap); + +/** + * tlb_flush_page_bits_by_mmuidx + * @cpu: CPU whose TLB should be flushed + * @addr: virtual address of page to be flushed + * @idxmap: bitmap of mmu indexes to flush + * @bits: number of significant bits in address + * + * Similar to tlb_flush_page_mask, but with a bitmap of indexes. + */ +void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr, + uint16_t idxmap, unsigned bits); + +/* Similarly, with broadcast and syncing. */ +void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu, target_ulong addr, + uint16_t idxmap, unsigned bits); +void tlb_flush_page_bits_by_mmuidx_all_cpus_synced + (CPUState *cpu, target_ulong addr, uint16_t idxmap, unsigned bits); + /** * tlb_set_page_with_attrs: * @cpu: CPU to add this TLB entry for @@ -284,6 +308,9 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr, static inline void tlb_init(CPUState *cpu) { } +static inline void tlb_destroy(CPUState *cpu) +{ +} static inline void tlb_flush_page(CPUState *cpu, target_ulong addr) { } @@ -329,6 +356,23 @@ static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap) { } +static inline void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, + target_ulong addr, + uint16_t idxmap, + unsigned bits) +{ +} +static inline void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu, + target_ulong addr, + uint16_t idxmap, + unsigned bits) +{ +} +static inline void +tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, target_ulong addr, + uint16_t idxmap, unsigned bits) +{ +} #endif /** * probe_access: @@ -479,17 +523,17 @@ struct TranslationBlock { extern bool parallel_cpus; -/* Hide the atomic_read to make code a little easier on the eyes */ +/* Hide the qatomic_read to make code a little easier on the eyes */ static inline uint32_t tb_cflags(const TranslationBlock *tb) { - return atomic_read(&tb->cflags); + return qatomic_read(&tb->cflags); } /* current cflags for hashing/comparison */ static inline uint32_t curr_cflags(void) { return (parallel_cpus ? CF_PARALLEL : 0) - | (use_icount ? CF_USE_ICOUNT : 0); + | (icount_enabled() ? CF_USE_ICOUNT : 0); } /* TranslationBlock invalidate API */ diff --git a/include/exec/hwaddr.h b/include/exec/hwaddr.h index a71c93cc810aa18d5ddefc8d970ddb3b95409ede..8f16d179a88599dcd8b82aaafbc80193f4d3f846 100644 --- a/include/exec/hwaddr.h +++ b/include/exec/hwaddr.h @@ -18,4 +18,9 @@ typedef uint64_t hwaddr; #define HWADDR_PRIx PRIx64 #define HWADDR_PRIX PRIX64 +typedef struct MemMapEntry { + hwaddr base; + hwaddr size; +} MemMapEntry; + #endif diff --git a/include/exec/ioport.h b/include/exec/ioport.h index 97feb296d234f68f2d9f8ca5251c0ad24b84c9da..e34f668998d35b2bcdd910a3c62de94e23d02f08 100644 --- a/include/exec/ioport.h +++ b/include/exec/ioport.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/exec/log.h b/include/exec/log.h index 3ed797c1c8cdf2af02e57cbf0f52d6c6a1017172..e02fff5de165c979a46769acf1ac04c8cf9f9475 100644 --- a/include/exec/log.h +++ b/include/exec/log.h @@ -19,7 +19,7 @@ static inline void log_cpu_state(CPUState *cpu, int flags) if (qemu_log_enabled()) { rcu_read_lock(); - logfile = atomic_rcu_read(&qemu_logfile); + logfile = qatomic_rcu_read(&qemu_logfile); if (logfile) { cpu_dump_state(cpu, logfile->fd, flags); } @@ -49,20 +49,20 @@ static inline void log_target_disas(CPUState *cpu, target_ulong start, { QemuLogFile *logfile; rcu_read_lock(); - logfile = atomic_rcu_read(&qemu_logfile); + logfile = qatomic_rcu_read(&qemu_logfile); if (logfile) { target_disas(logfile->fd, cpu, start, len); } rcu_read_unlock(); } -static inline void log_disas(void *code, unsigned long size, const char *note) +static inline void log_disas(void *code, unsigned long size) { QemuLogFile *logfile; rcu_read_lock(); - logfile = atomic_rcu_read(&qemu_logfile); + logfile = qatomic_rcu_read(&qemu_logfile); if (logfile) { - disas(logfile->fd, code, size, note); + disas(logfile->fd, code, size); } rcu_read_unlock(); } diff --git a/include/exec/memory.h b/include/exec/memory.h index e000bd2f97b2fce76a41f9b5d9f33ca60d3bedcb..0f3e6bcd5e74a9969913bccd1d93a073f190e55b 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -34,27 +34,37 @@ #define MAX_PHYS_ADDR (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1) #define TYPE_MEMORY_REGION "qemu:memory-region" -#define MEMORY_REGION(obj) \ - OBJECT_CHECK(MemoryRegion, (obj), TYPE_MEMORY_REGION) +DECLARE_INSTANCE_CHECKER(MemoryRegion, MEMORY_REGION, + TYPE_MEMORY_REGION) #define TYPE_IOMMU_MEMORY_REGION "qemu:iommu-memory-region" -#define IOMMU_MEMORY_REGION(obj) \ - OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_IOMMU_MEMORY_REGION) -#define IOMMU_MEMORY_REGION_CLASS(klass) \ - OBJECT_CLASS_CHECK(IOMMUMemoryRegionClass, (klass), \ - TYPE_IOMMU_MEMORY_REGION) -#define IOMMU_MEMORY_REGION_GET_CLASS(obj) \ - OBJECT_GET_CLASS(IOMMUMemoryRegionClass, (obj), \ - TYPE_IOMMU_MEMORY_REGION) +typedef struct IOMMUMemoryRegionClass IOMMUMemoryRegionClass; +DECLARE_OBJ_CHECKERS(IOMMUMemoryRegion, IOMMUMemoryRegionClass, + IOMMU_MEMORY_REGION, TYPE_IOMMU_MEMORY_REGION) + +#ifdef CONFIG_FUZZ +void fuzz_dma_read_cb(size_t addr, + size_t len, + MemoryRegion *mr, + bool is_write); +#else +static inline void fuzz_dma_read_cb(size_t addr, + size_t len, + MemoryRegion *mr, + bool is_write) +{ + /* Do Nothing */ +} +#endif extern bool global_dirty_log; typedef struct MemoryRegionOps MemoryRegionOps; -typedef struct MemoryRegionMmio MemoryRegionMmio; -struct MemoryRegionMmio { - CPUReadMemoryFunc *read[3]; - CPUWriteMemoryFunc *write[3]; +struct ReservedRegion { + hwaddr low; + hwaddr high; + unsigned type; }; typedef struct IOMMUTLBEntry IOMMUTLBEntry; @@ -216,7 +226,7 @@ enum IOMMUMemoryRegionAttr { IOMMU_ATTR_SPAPR_TCE_FD }; -/** +/* * IOMMUMemoryRegionClass: * * All IOMMU implementations need to subclass TYPE_IOMMU_MEMORY_REGION @@ -233,8 +243,11 @@ enum IOMMUMemoryRegionAttr { * attributes and the output TLB entry depends on the transaction * attributes, we represent this using IOMMU indexes. Each index * selects a particular translation table that the IOMMU has: + * * @attrs_to_index returns the IOMMU index for a set of transaction attributes + * * @translate takes an input address and an IOMMU index + * * and the mapping returned can only depend on the input address and the * IOMMU index. * @@ -242,11 +255,14 @@ enum IOMMUMemoryRegionAttr { * only a single IOMMU index. A more complex IOMMU might have one index * for secure transactions and one for non-secure transactions. */ -typedef struct IOMMUMemoryRegionClass { - /* private */ +struct IOMMUMemoryRegionClass { + /* private: */ MemoryRegionClass parent_class; - /* + /* public: */ + /** + * @translate: + * * Return a TLB entry that contains a given address. * * The IOMMUAccessFlags indicated via @flag are optional and may @@ -267,26 +283,38 @@ typedef struct IOMMUMemoryRegionClass { * information when the IOMMU mapping changes. * * @iommu: the IOMMUMemoryRegion + * * @hwaddr: address to be translated within the memory region - * @flag: requested access permissions + * + * @flag: requested access permission + * * @iommu_idx: IOMMU index for the translation */ IOMMUTLBEntry (*translate)(IOMMUMemoryRegion *iommu, hwaddr addr, IOMMUAccessFlags flag, int iommu_idx); - /* Returns minimum supported page size in bytes. + /** + * @get_min_page_size: + * + * Returns minimum supported page size in bytes. + * * If this method is not provided then the minimum is assumed to * be TARGET_PAGE_SIZE. * * @iommu: the IOMMUMemoryRegion */ uint64_t (*get_min_page_size)(IOMMUMemoryRegion *iommu); - /* Called when IOMMU Notifier flag changes (ie when the set of + /** + * @notify_flag_changed: + * + * Called when IOMMU Notifier flag changes (ie when the set of * events which IOMMU users are requesting notification for changes). * Optional method -- need not be provided if the IOMMU does not * need to know exactly which events must be notified. * * @iommu: the IOMMUMemoryRegion + * * @old_flags: events which previously needed to be notified + * * @new_flags: events which now need to be notified * * Returns 0 on success, or a negative errno; in particular @@ -298,7 +326,10 @@ typedef struct IOMMUMemoryRegionClass { IOMMUNotifierFlag old_flags, IOMMUNotifierFlag new_flags, Error **errp); - /* Called to handle memory_region_iommu_replay(). + /** + * @replay: + * + * Called to handle memory_region_iommu_replay(). * * The default implementation of memory_region_iommu_replay() is to * call the IOMMU translate method for every page in the address space @@ -315,7 +346,10 @@ typedef struct IOMMUMemoryRegionClass { */ void (*replay)(IOMMUMemoryRegion *iommu, IOMMUNotifier *notifier); - /* Get IOMMU misc attributes. This is an optional method that + /** + * @get_attr: + * + * Get IOMMU misc attributes. This is an optional method that * can be used to allow users of the IOMMU to get implementation-specific * information. The IOMMU implements this method to handle calls * by IOMMU users to memory_region_iommu_get_attr() by filling in @@ -324,7 +358,9 @@ typedef struct IOMMUMemoryRegionClass { * memory_region_iommu_get_attr() will always return -EINVAL. * * @iommu: the IOMMUMemoryRegion + * * @attr: attribute being queried + * * @data: memory to fill in with the attribute data * * Returns 0 on success, or a negative errno; in particular @@ -333,7 +369,10 @@ typedef struct IOMMUMemoryRegionClass { int (*get_attr)(IOMMUMemoryRegion *iommu, enum IOMMUMemoryRegionAttr attr, void *data); - /* Return the IOMMU index to use for a given set of transaction attributes. + /** + * @attrs_to_index: + * + * Return the IOMMU index to use for a given set of transaction attributes. * * Optional method: if an IOMMU only supports a single IOMMU index then * the default implementation of memory_region_iommu_attrs_to_index() @@ -346,7 +385,10 @@ typedef struct IOMMUMemoryRegionClass { */ int (*attrs_to_index)(IOMMUMemoryRegion *iommu, MemTxAttrs attrs); - /* Return the number of IOMMU indexes this IOMMU supports. + /** + * @num_indexes: + * + * Return the number of IOMMU indexes this IOMMU supports. * * Optional method: if this method is not provided, then * memory_region_iommu_num_indexes() will return 1, indicating that @@ -355,7 +397,33 @@ typedef struct IOMMUMemoryRegionClass { * @iommu: the IOMMUMemoryRegion */ int (*num_indexes)(IOMMUMemoryRegion *iommu); -} IOMMUMemoryRegionClass; + + /** + * @iommu_set_page_size_mask: + * + * Restrict the page size mask that can be supported with a given IOMMU + * memory region. Used for example to propagate host physical IOMMU page + * size mask limitations to the virtual IOMMU. + * + * Optional method: if this method is not provided, then the default global + * page mask is used. + * + * @iommu: the IOMMUMemoryRegion + * + * @page_size_mask: a bitmask of supported page sizes. At least one bit, + * representing the smallest page size, must be set. Additional set bits + * represent supported block sizes. For example a host physical IOMMU that + * uses page tables with a page size of 4kB, and supports 2MB and 4GB + * blocks, will set mask 0x40201000. A granule of 4kB with indiscriminate + * block sizes is specified with mask 0xfffffffffffff000. + * + * Returns 0 on success, or a negative error. In case of failure, the error + * object must be created. + */ + int (*iommu_set_page_size_mask)(IOMMUMemoryRegion *iommu, + uint64_t page_size_mask, + Error **errp); +}; typedef struct CoalescedMemoryRange CoalescedMemoryRange; typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd; @@ -377,7 +445,6 @@ struct MemoryRegion { bool nonvolatile; bool rom_device; bool flush_coalesced_mmio; - bool global_locking; uint8_t dirty_log_mask; bool is_iommu; RAMBlock *ram_block; @@ -417,7 +484,7 @@ struct IOMMUMemoryRegion { QLIST_FOREACH((n), &(mr)->iommu_notify, node) /** - * MemoryListener: callbacks structure for updates to the physical memory map + * struct MemoryListener: callbacks structure for updates to the physical memory map * * Allows a component to adjust to changes in the guest-visible memory map. * Use with memory_listener_register() and memory_listener_unregister(). @@ -655,7 +722,7 @@ struct MemoryListener { }; /** - * AddressSpace: describes a mapping of addresses to #MemoryRegion objects + * struct AddressSpace: describes a mapping of addresses to #MemoryRegion objects */ struct AddressSpace { /* private: */ @@ -690,12 +757,17 @@ struct FlatView { static inline FlatView *address_space_to_flatview(AddressSpace *as) { - return atomic_rcu_read(&as->current_map); + return qatomic_rcu_read(&as->current_map); } +typedef int (*flatview_cb)(Int128 start, + Int128 len, + const MemoryRegion*, void*); + +void flatview_for_each_range(FlatView *fv, flatview_cb cb , void *opaque); /** - * MemoryRegionSection: describes a fragment of a #MemoryRegion + * struct MemoryRegionSection: describes a fragment of a #MemoryRegion * * @mr: the region, or %NULL if empty * @fv: the flat view of the address space the region is mapped in @@ -1363,6 +1435,18 @@ int memory_region_iommu_attrs_to_index(IOMMUMemoryRegion *iommu_mr, */ int memory_region_iommu_num_indexes(IOMMUMemoryRegion *iommu_mr); +/** + * memory_region_iommu_set_page_size_mask: set the supported page + * sizes for a given IOMMU memory region + * + * @iommu_mr: IOMMU memory region + * @page_size_mask: supported page size mask + * @errp: pointer to Error*, to store an error if it happens. + */ +int memory_region_iommu_set_page_size_mask(IOMMUMemoryRegion *iommu_mr, + uint64_t page_size_mask, + Error **errp); + /** * memory_region_name: get a memory region's name * @@ -1473,15 +1557,26 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr); */ void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize, Error **errp); + +/** + * memory_region_msync: Synchronize selected address range of + * a memory mapped region + * + * @mr: the memory region to be msync + * @addr: the initial address of the range to be sync + * @size: the size of the range to be sync + */ +void memory_region_msync(MemoryRegion *mr, hwaddr addr, hwaddr size); + /** - * memory_region_do_writeback: Trigger cache writeback or msync for + * memory_region_writeback: Trigger cache writeback for * selected address range * * @mr: the memory region to be updated * @addr: the initial address of the range to be written back * @size: the size of the range to be written back */ -void memory_region_do_writeback(MemoryRegion *mr, hwaddr addr, hwaddr size); +void memory_region_writeback(MemoryRegion *mr, hwaddr addr, hwaddr size); /** * memory_region_set_log: Turn dirty logging on or off for a region. @@ -1700,19 +1795,6 @@ void memory_region_set_flush_coalesced(MemoryRegion *mr); */ void memory_region_clear_flush_coalesced(MemoryRegion *mr); -/** - * memory_region_clear_global_locking: Declares that access processing does - * not depend on the QEMU global lock. - * - * By clearing this property, accesses to the memory region will be processed - * outside of QEMU's global lock (unless the lock is held on when issuing the - * access request). In this case, the device model implementing the access - * handlers is responsible for synchronization of concurrency. - * - * @mr: the memory region to be updated. - */ -void memory_region_clear_global_locking(MemoryRegion *mr); - /** * memory_region_add_eventfd: Request an eventfd to be triggered when a word * is written to a location. @@ -1973,7 +2055,7 @@ void memory_global_dirty_log_start(void); */ void memory_global_dirty_log_stop(void); -void mtree_info(bool flatview, bool dispatch_tree, bool owner); +void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled); /** * memory_region_dispatch_read: perform a read directly to the specified @@ -2122,12 +2204,12 @@ MemTxResult address_space_write_rom(AddressSpace *as, hwaddr addr, #define SUFFIX #define ARG1 as #define ARG1_DECL AddressSpace *as -#include "exec/memory_ldst.inc.h" +#include "exec/memory_ldst.h.inc" #define SUFFIX #define ARG1 as #define ARG1_DECL AddressSpace *as -#include "exec/memory_ldst_phys.inc.h" +#include "exec/memory_ldst_phys.h.inc" struct MemoryRegionCache { void *ptr; @@ -2168,7 +2250,7 @@ struct MemoryRegionCache { #define SUFFIX _cached_slow #define ARG1 cache #define ARG1_DECL MemoryRegionCache *cache -#include "exec/memory_ldst.inc.h" +#include "exec/memory_ldst.h.inc" /* Inline fast path for direct RAM access. */ static inline uint8_t address_space_ldub_cached(MemoryRegionCache *cache, @@ -2194,15 +2276,15 @@ static inline void address_space_stb_cached(MemoryRegionCache *cache, } #define ENDIANNESS _le -#include "exec/memory_ldst_cached.inc.h" +#include "exec/memory_ldst_cached.h.inc" #define ENDIANNESS _be -#include "exec/memory_ldst_cached.inc.h" +#include "exec/memory_ldst_cached.h.inc" #define SUFFIX _cached #define ARG1 cache #define ARG1_DECL MemoryRegionCache *cache -#include "exec/memory_ldst_phys.inc.h" +#include "exec/memory_ldst_phys.h.inc" /* address_space_cache_init: prepare for repeated access to a physical * memory region @@ -2303,7 +2385,8 @@ bool address_space_access_valid(AddressSpace *as, hwaddr addr, hwaddr len, /* address_space_map: map a physical memory region into a host virtual address * * May map a subset of the requested range, given by and returned in @plen. - * May return %NULL if resources needed to perform the mapping are exhausted. + * May return %NULL and set *@plen to zero(0), if resources needed to perform + * the mapping are exhausted. * Use only for reads OR writes - not for read-modify-write operations. * Use cpu_register_map_client() to know when retrying the map operation is * likely to succeed. @@ -2343,10 +2426,11 @@ void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr); /* Internal functions, part of the implementation of address_space_read_cached * and address_space_write_cached. */ -void address_space_read_cached_slow(MemoryRegionCache *cache, - hwaddr addr, void *buf, hwaddr len); -void address_space_write_cached_slow(MemoryRegionCache *cache, - hwaddr addr, const void *buf, hwaddr len); +MemTxResult address_space_read_cached_slow(MemoryRegionCache *cache, + hwaddr addr, void *buf, hwaddr len); +MemTxResult address_space_write_cached_slow(MemoryRegionCache *cache, + hwaddr addr, const void *buf, + hwaddr len); static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write) { @@ -2411,15 +2495,17 @@ MemTxResult address_space_read(AddressSpace *as, hwaddr addr, * @buf: buffer with the data transferred * @len: length of the data transferred */ -static inline void +static inline MemTxResult address_space_read_cached(MemoryRegionCache *cache, hwaddr addr, void *buf, hwaddr len) { assert(addr < cache->len && len <= cache->len - addr); + fuzz_dma_read_cb(cache->xlat + addr, len, cache->mrs.mr, false); if (likely(cache->ptr)) { memcpy(buf, cache->ptr + addr, len); + return MEMTX_OK; } else { - address_space_read_cached_slow(cache, addr, buf, len); + return address_space_read_cached_slow(cache, addr, buf, len); } } @@ -2431,15 +2517,16 @@ address_space_read_cached(MemoryRegionCache *cache, hwaddr addr, * @buf: buffer with the data transferred * @len: length of the data transferred */ -static inline void +static inline MemTxResult address_space_write_cached(MemoryRegionCache *cache, hwaddr addr, const void *buf, hwaddr len) { assert(addr < cache->len && len <= cache->len - addr); if (likely(cache->ptr)) { memcpy(cache->ptr + addr, buf, len); + return MEMTX_OK; } else { - address_space_write_cached_slow(cache, addr, buf, len); + return address_space_write_cached_slow(cache, addr, buf, len); } } @@ -2463,6 +2550,47 @@ static inline MemOp devend_memop(enum device_endian end) } #endif +/* + * Inhibit technologies that require discarding of pages in RAM blocks, e.g., + * to manage the actual amount of memory consumed by the VM (then, the memory + * provided by RAM blocks might be bigger than the desired memory consumption). + * This *must* be set if: + * - Discarding parts of a RAM blocks does not result in the change being + * reflected in the VM and the pages getting freed. + * - All memory in RAM blocks is pinned or duplicated, invaldiating any previous + * discards blindly. + * - Discarding parts of a RAM blocks will result in integrity issues (e.g., + * encrypted VMs). + * Technologies that only temporarily pin the current working set of a + * driver are fine, because we don't expect such pages to be discarded + * (esp. based on guest action like balloon inflation). + * + * This is *not* to be used to protect from concurrent discards (esp., + * postcopy). + * + * Returns 0 if successful. Returns -EBUSY if a technology that relies on + * discards to work reliably is active. + */ +int ram_block_discard_disable(bool state); + +/* + * Inhibit technologies that disable discarding of pages in RAM blocks. + * + * Returns 0 if successful. Returns -EBUSY if discards are already set to + * broken. + */ +int ram_block_discard_require(bool state); + +/* + * Test if discarding of memory in ram blocks is disabled. + */ +bool ram_block_discard_is_disabled(void); + +/* + * Test if discarding of memory in ram blocks is required to work reliably. + */ +bool ram_block_discard_is_required(void); + #endif #endif diff --git a/include/exec/memory_ldst.inc.h b/include/exec/memory_ldst.h.inc similarity index 98% rename from include/exec/memory_ldst.inc.h rename to include/exec/memory_ldst.h.inc index 272c20f02eae5e94b676f17c2fdc4f139df5f1cd..46e6c220d3539f66a3b12adf26dd5addaec3e8d6 100644 --- a/include/exec/memory_ldst.inc.h +++ b/include/exec/memory_ldst.h.inc @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/exec/memory_ldst_cached.inc.h b/include/exec/memory_ldst_cached.h.inc similarity index 93% rename from include/exec/memory_ldst_cached.inc.h rename to include/exec/memory_ldst_cached.h.inc index fd4bbb40e7c3decd097860ae0c1bd2d7c8f3077d..01efad62ded602e9bc744691586beb62821c3145 100644 --- a/include/exec/memory_ldst_cached.inc.h +++ b/include/exec/memory_ldst_cached.h.inc @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -28,6 +28,7 @@ static inline uint32_t ADDRESS_SPACE_LD_CACHED(l)(MemoryRegionCache *cache, hwaddr addr, MemTxAttrs attrs, MemTxResult *result) { assert(addr < cache->len && 4 <= cache->len - addr); + fuzz_dma_read_cb(cache->xlat + addr, 4, cache->mrs.mr, false); if (likely(cache->ptr)) { return LD_P(l)(cache->ptr + addr); } else { @@ -39,6 +40,7 @@ static inline uint64_t ADDRESS_SPACE_LD_CACHED(q)(MemoryRegionCache *cache, hwaddr addr, MemTxAttrs attrs, MemTxResult *result) { assert(addr < cache->len && 8 <= cache->len - addr); + fuzz_dma_read_cb(cache->xlat + addr, 8, cache->mrs.mr, false); if (likely(cache->ptr)) { return LD_P(q)(cache->ptr + addr); } else { @@ -50,6 +52,7 @@ static inline uint32_t ADDRESS_SPACE_LD_CACHED(uw)(MemoryRegionCache *cache, hwaddr addr, MemTxAttrs attrs, MemTxResult *result) { assert(addr < cache->len && 2 <= cache->len - addr); + fuzz_dma_read_cb(cache->xlat + addr, 2, cache->mrs.mr, false); if (likely(cache->ptr)) { return LD_P(uw)(cache->ptr + addr); } else { diff --git a/include/exec/memory_ldst_phys.inc.h b/include/exec/memory_ldst_phys.h.inc similarity index 98% rename from include/exec/memory_ldst_phys.inc.h rename to include/exec/memory_ldst_phys.h.inc index 91f72973cb2b372a7e1b9f00838dda9433f1b7f2..b9dd53c389d7baf7a35e97f05ec071f264af728f 100644 --- a/include/exec/memory_ldst_phys.inc.h +++ b/include/exec/memory_ldst_phys.h.inc @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index 5e59a3d8d7d97ba13f4b6d698885b94d6f33c1a7..c6d2ef1d07e67b16995e0d61982f1a4e585627ce 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -21,7 +21,7 @@ #ifndef CONFIG_USER_ONLY #include "cpu.h" -#include "hw/xen/xen.h" +#include "sysemu/xen.h" #include "sysemu/tcg.h" #include "exec/ramlist.h" #include "exec/ramblock.h" @@ -136,12 +136,12 @@ void qemu_ram_free(RAMBlock *block); int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp); -void qemu_ram_writeback(RAMBlock *block, ram_addr_t start, ram_addr_t length); +void qemu_ram_msync(RAMBlock *block, ram_addr_t start, ram_addr_t length); /* Clear whole block of mem */ static inline void qemu_ram_block_writeback(RAMBlock *block) { - qemu_ram_writeback(block, 0, block->used_length); + qemu_ram_msync(block, 0, block->used_length); } #define DIRTY_CLIENTS_ALL ((1 << DIRTY_MEMORY_NUM) - 1) @@ -164,7 +164,7 @@ static inline bool cpu_physical_memory_get_dirty(ram_addr_t start, page = start >> TARGET_PAGE_BITS; WITH_RCU_READ_LOCK_GUARD() { - blocks = atomic_rcu_read(&ram_list.dirty_memory[client]); + blocks = qatomic_rcu_read(&ram_list.dirty_memory[client]); idx = page / DIRTY_MEMORY_BLOCK_SIZE; offset = page % DIRTY_MEMORY_BLOCK_SIZE; @@ -205,7 +205,7 @@ static inline bool cpu_physical_memory_all_dirty(ram_addr_t start, RCU_READ_LOCK_GUARD(); - blocks = atomic_rcu_read(&ram_list.dirty_memory[client]); + blocks = qatomic_rcu_read(&ram_list.dirty_memory[client]); idx = page / DIRTY_MEMORY_BLOCK_SIZE; offset = page % DIRTY_MEMORY_BLOCK_SIZE; @@ -278,7 +278,7 @@ static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr, RCU_READ_LOCK_GUARD(); - blocks = atomic_rcu_read(&ram_list.dirty_memory[client]); + blocks = qatomic_rcu_read(&ram_list.dirty_memory[client]); set_bit_atomic(offset, blocks->blocks[idx]); } @@ -301,7 +301,7 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, WITH_RCU_READ_LOCK_GUARD() { for (i = 0; i < DIRTY_MEMORY_NUM; i++) { - blocks[i] = atomic_rcu_read(&ram_list.dirty_memory[i]); + blocks[i] = qatomic_rcu_read(&ram_list.dirty_memory[i]); } idx = page / DIRTY_MEMORY_BLOCK_SIZE; @@ -361,23 +361,25 @@ static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap, WITH_RCU_READ_LOCK_GUARD() { for (i = 0; i < DIRTY_MEMORY_NUM; i++) { - blocks[i] = atomic_rcu_read(&ram_list.dirty_memory[i])->blocks; + blocks[i] = + qatomic_rcu_read(&ram_list.dirty_memory[i])->blocks; } for (k = 0; k < nr; k++) { if (bitmap[k]) { unsigned long temp = leul_to_cpu(bitmap[k]); - atomic_or(&blocks[DIRTY_MEMORY_VGA][idx][offset], temp); + qatomic_or(&blocks[DIRTY_MEMORY_VGA][idx][offset], temp); if (global_dirty_log) { - atomic_or(&blocks[DIRTY_MEMORY_MIGRATION][idx][offset], - temp); + qatomic_or( + &blocks[DIRTY_MEMORY_MIGRATION][idx][offset], + temp); } if (tcg_enabled()) { - atomic_or(&blocks[DIRTY_MEMORY_CODE][idx][offset], - temp); + qatomic_or(&blocks[DIRTY_MEMORY_CODE][idx][offset], + temp); } } @@ -442,8 +444,7 @@ static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, static inline uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock *rb, ram_addr_t start, - ram_addr_t length, - uint64_t *real_dirty_pages) + ram_addr_t length) { ram_addr_t addr; unsigned long word = BIT_WORD((start + rb->offset) >> TARGET_PAGE_BITS); @@ -462,14 +463,13 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock *rb, DIRTY_MEMORY_BLOCK_SIZE); unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS); - src = atomic_rcu_read( + src = qatomic_rcu_read( &ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION])->blocks; for (k = page; k < page + nr; k++) { if (src[idx][offset]) { - unsigned long bits = atomic_xchg(&src[idx][offset], 0); + unsigned long bits = qatomic_xchg(&src[idx][offset], 0); unsigned long new_dirty; - *real_dirty_pages += ctpopl(bits); new_dirty = ~dest[k]; dest[k] |= bits; new_dirty &= bits; @@ -502,7 +502,6 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock *rb, start + addr + offset, TARGET_PAGE_SIZE, DIRTY_MEMORY_MIGRATION)) { - *real_dirty_pages += 1; long k = (start + addr) >> TARGET_PAGE_BITS; if (!test_and_set_bit(k, dest)) { num_dirty++; diff --git a/include/exec/ramlist.h b/include/exec/ramlist.h index bc4faa1b001aef822b3b22762aa73d873f891d92..26704aa3b0d75f6c823037fbe2c5b7fedfdd9cbb 100644 --- a/include/exec/ramlist.h +++ b/include/exec/ramlist.h @@ -19,7 +19,7 @@ typedef struct RAMBlockNotifier RAMBlockNotifier; * rcu_read_lock(); * * DirtyMemoryBlocks *blocks = - * atomic_rcu_read(&ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION]); + * qatomic_rcu_read(&ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION]); * * ram_addr_t idx = (addr >> TARGET_PAGE_BITS) / DIRTY_MEMORY_BLOCK_SIZE; * unsigned long *block = blocks.blocks[idx]; diff --git a/include/exec/tb-context.h b/include/exec/tb-context.h index feb585e0a7654f44b2028a267219bd5bb40740a5..ec4c13b455d139914f63e27951092d177e1d9575 100644 --- a/include/exec/tb-context.h +++ b/include/exec/tb-context.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/exec/tb-hash.h b/include/exec/tb-hash.h index 805235d321c27390f6e85fc3586c65aec5b16992..0a273d9605a27207df58502e11fb3cfe24a8ae32 100644 --- a/include/exec/tb-hash.h +++ b/include/exec/tb-hash.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/exec/tb-lookup.h b/include/exec/tb-lookup.h index 26921b6dafdaf6d44c3b0e5bb587cfd477bae5f5..9cf475bb03338bbd7cd8aca17f8cf68a7fe04631 100644 --- a/include/exec/tb-lookup.h +++ b/include/exec/tb-lookup.h @@ -27,7 +27,7 @@ tb_lookup__cpu_state(CPUState *cpu, target_ulong *pc, target_ulong *cs_base, cpu_get_tb_cpu_state(env, pc, cs_base, flags); hash = tb_jmp_cache_hash_func(*pc); - tb = atomic_rcu_read(&cpu->tb_jmp_cache[hash]); + tb = qatomic_rcu_read(&cpu->tb_jmp_cache[hash]); cf_mask &= ~CF_CLUSTER_MASK; cf_mask |= cpu->cluster_index << CF_CLUSTER_SHIFT; @@ -44,7 +44,7 @@ tb_lookup__cpu_state(CPUState *cpu, target_ulong *pc, target_ulong *cs_base, if (tb == NULL) { return NULL; } - atomic_set(&cpu->tb_jmp_cache[hash], tb); + qatomic_set(&cpu->tb_jmp_cache[hash], tb); return tb; } diff --git a/include/exec/user/thunk.h b/include/exec/user/thunk.h index eae2c27f99daa4f7b02e22911aaad7570c83a0e7..300a840d58d31b3abe5841930eedcd39647c86b6 100644 --- a/include/exec/user/thunk.h +++ b/include/exec/user/thunk.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -42,7 +42,7 @@ typedef enum argtype { } argtype; #define MK_PTR(type) TYPE_PTR, type -#define MK_ARRAY(type, size) TYPE_ARRAY, size, type +#define MK_ARRAY(type, size) TYPE_ARRAY, (int)(size), type #define MK_STRUCT(id) TYPE_STRUCT, id #define THUNK_TARGET 0 @@ -55,6 +55,7 @@ typedef struct { int *field_offsets[2]; /* special handling */ void (*convert[2])(void *dst, const void *src); + void (*print)(void *arg); int size[2]; int align[2]; const char *name; @@ -73,6 +74,7 @@ void thunk_register_struct_direct(int id, const char *name, const StructEntry *se1); const argtype *thunk_convert(void *dst, const void *src, const argtype *type_ptr, int to_host); +const argtype *thunk_print(void *arg, const argtype *type_ptr); extern StructEntry *struct_entries; diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h index 735ed6b653ee45d2f05da42b730aebce56550e65..2f0674fbddec92ea36eb6fbf418614e78060833a 100644 --- a/include/fpu/softfloat-helpers.h +++ b/include/fpu/softfloat-helpers.h @@ -95,6 +95,16 @@ static inline void set_snan_bit_is_one(bool val, float_status *status) status->snan_bit_is_one = val; } +static inline void set_use_first_nan(bool val, float_status *status) +{ + status->use_first_nan = val; +} + +static inline void set_no_signaling_nans(bool val, float_status *status) +{ + status->no_signaling_nans = val; +} + static inline bool get_float_detect_tininess(float_status *status) { return status->tininess_before_rounding; diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h index 7680193ebc1cb96067e96b97ab12f019e6c2efc4..8a3f20fae9e0716cf2cf7fd1a675fec90924cc0c 100644 --- a/include/fpu/softfloat-types.h +++ b/include/fpu/softfloat-types.h @@ -112,6 +112,11 @@ typedef struct { #define make_float128(high_, low_) ((float128) { .high = high_, .low = low_ }) #define make_float128_init(high_, low_) { .high = high_, .low = low_ } +/* + * Software neural-network floating-point types. + */ +typedef uint16_t bfloat16; + /* * Software IEC/IEEE floating-point underflow tininess-detection mode. */ @@ -165,8 +170,14 @@ typedef struct float_status { /* should denormalised inputs go to zero and set the input_denormal flag? */ bool flush_inputs_to_zero; bool default_nan_mode; - /* not always used -- see snan_bit_is_one() in softfloat-specialize.h */ + /* + * The flags below are not used on all specializations and may + * constant fold away (see snan_bit_is_one()/no_signalling_nans() in + * softfloat-specialize.inc.c) + */ bool snan_bit_is_one; + bool use_first_nan; + bool no_signaling_nans; } float_status; #endif /* SOFTFLOAT_TYPES_H */ diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 16ca697a73b7bd2e9c2f74c0b0ac0592240db7e8..78ad5ca738bb7ced65adfdf3bd5f1c92d18fab3d 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -109,6 +109,7 @@ void float_raise(uint8_t flags, float_status *status); float16 float16_squash_input_denormal(float16 a, float_status *status); float32 float32_squash_input_denormal(float32 a, float_status *status); float64 float64_squash_input_denormal(float64 a, float_status *status); +bfloat16 bfloat16_squash_input_denormal(bfloat16 a, float_status *status); /*---------------------------------------------------------------------------- | Options to indicate which negations to perform in float*_muladd() @@ -136,9 +137,11 @@ float16 uint16_to_float16_scalbn(uint16_t a, int, float_status *status); float16 uint32_to_float16_scalbn(uint32_t a, int, float_status *status); float16 uint64_to_float16_scalbn(uint64_t a, int, float_status *status); +float16 int8_to_float16(int8_t a, float_status *status); float16 int16_to_float16(int16_t a, float_status *status); float16 int32_to_float16(int32_t a, float_status *status); float16 int64_to_float16(int64_t a, float_status *status); +float16 uint8_to_float16(uint8_t a, float_status *status); float16 uint16_to_float16(uint16_t a, float_status *status); float16 uint32_to_float16(uint32_t a, float_status *status); float16 uint64_to_float16(uint64_t a, float_status *status); @@ -187,10 +190,13 @@ float32 float16_to_float32(float16, bool ieee, float_status *status); float16 float64_to_float16(float64 a, bool ieee, float_status *status); float64 float16_to_float64(float16 a, bool ieee, float_status *status); +int8_t float16_to_int8_scalbn(float16, FloatRoundMode, int, + float_status *status); int16_t float16_to_int16_scalbn(float16, FloatRoundMode, int, float_status *); int32_t float16_to_int32_scalbn(float16, FloatRoundMode, int, float_status *); int64_t float16_to_int64_scalbn(float16, FloatRoundMode, int, float_status *); +int8_t float16_to_int8(float16, float_status *status); int16_t float16_to_int16(float16, float_status *status); int32_t float16_to_int32(float16, float_status *status); int64_t float16_to_int64(float16, float_status *status); @@ -199,6 +205,8 @@ int16_t float16_to_int16_round_to_zero(float16, float_status *status); int32_t float16_to_int32_round_to_zero(float16, float_status *status); int64_t float16_to_int64_round_to_zero(float16, float_status *status); +uint8_t float16_to_uint8_scalbn(float16 a, FloatRoundMode, + int, float_status *status); uint16_t float16_to_uint16_scalbn(float16 a, FloatRoundMode, int, float_status *status); uint32_t float16_to_uint32_scalbn(float16 a, FloatRoundMode, @@ -206,6 +214,7 @@ uint32_t float16_to_uint32_scalbn(float16 a, FloatRoundMode, uint64_t float16_to_uint64_scalbn(float16 a, FloatRoundMode, int, float_status *status); +uint8_t float16_to_uint8(float16 a, float_status *status); uint16_t float16_to_uint16(float16 a, float_status *status); uint32_t float16_to_uint32(float16 a, float_status *status); uint64_t float16_to_uint64(float16 a, float_status *status); @@ -264,6 +273,11 @@ static inline bool float16_is_zero_or_denormal(float16 a) return (float16_val(a) & 0x7c00) == 0; } +static inline bool float16_is_normal(float16 a) +{ + return (((float16_val(a) >> 10) + 1) & 0x1f) >= 2; +} + static inline float16 float16_abs(float16 a) { /* Note that abs does *not* handle NaN specially, nor does @@ -285,6 +299,47 @@ static inline float16 float16_set_sign(float16 a, int sign) return make_float16((float16_val(a) & 0x7fff) | (sign << 15)); } +static inline bool float16_eq(float16 a, float16 b, float_status *s) +{ + return float16_compare(a, b, s) == float_relation_equal; +} + +static inline bool float16_le(float16 a, float16 b, float_status *s) +{ + return float16_compare(a, b, s) <= float_relation_equal; +} + +static inline bool float16_lt(float16 a, float16 b, float_status *s) +{ + return float16_compare(a, b, s) < float_relation_equal; +} + +static inline bool float16_unordered(float16 a, float16 b, float_status *s) +{ + return float16_compare(a, b, s) == float_relation_unordered; +} + +static inline bool float16_eq_quiet(float16 a, float16 b, float_status *s) +{ + return float16_compare_quiet(a, b, s) == float_relation_equal; +} + +static inline bool float16_le_quiet(float16 a, float16 b, float_status *s) +{ + return float16_compare_quiet(a, b, s) <= float_relation_equal; +} + +static inline bool float16_lt_quiet(float16 a, float16 b, float_status *s) +{ + return float16_compare_quiet(a, b, s) < float_relation_equal; +} + +static inline bool float16_unordered_quiet(float16 a, float16 b, + float_status *s) +{ + return float16_compare_quiet(a, b, s) == float_relation_unordered; +} + #define float16_zero make_float16(0) #define float16_half make_float16(0x3800) #define float16_one make_float16(0x3c00) @@ -293,6 +348,186 @@ static inline float16 float16_set_sign(float16 a, int sign) #define float16_three make_float16(0x4200) #define float16_infinity make_float16(0x7c00) +/*---------------------------------------------------------------------------- +| Software bfloat16 conversion routines. +*----------------------------------------------------------------------------*/ + +bfloat16 bfloat16_round_to_int(bfloat16, float_status *status); +bfloat16 float32_to_bfloat16(float32, float_status *status); +float32 bfloat16_to_float32(bfloat16, float_status *status); +bfloat16 float64_to_bfloat16(float64 a, float_status *status); +float64 bfloat16_to_float64(bfloat16 a, float_status *status); + +int16_t bfloat16_to_int16_scalbn(bfloat16, FloatRoundMode, + int, float_status *status); +int32_t bfloat16_to_int32_scalbn(bfloat16, FloatRoundMode, + int, float_status *status); +int64_t bfloat16_to_int64_scalbn(bfloat16, FloatRoundMode, + int, float_status *status); + +int16_t bfloat16_to_int16(bfloat16, float_status *status); +int32_t bfloat16_to_int32(bfloat16, float_status *status); +int64_t bfloat16_to_int64(bfloat16, float_status *status); + +int16_t bfloat16_to_int16_round_to_zero(bfloat16, float_status *status); +int32_t bfloat16_to_int32_round_to_zero(bfloat16, float_status *status); +int64_t bfloat16_to_int64_round_to_zero(bfloat16, float_status *status); + +uint16_t bfloat16_to_uint16_scalbn(bfloat16 a, FloatRoundMode, + int, float_status *status); +uint32_t bfloat16_to_uint32_scalbn(bfloat16 a, FloatRoundMode, + int, float_status *status); +uint64_t bfloat16_to_uint64_scalbn(bfloat16 a, FloatRoundMode, + int, float_status *status); + +uint16_t bfloat16_to_uint16(bfloat16 a, float_status *status); +uint32_t bfloat16_to_uint32(bfloat16 a, float_status *status); +uint64_t bfloat16_to_uint64(bfloat16 a, float_status *status); + +uint16_t bfloat16_to_uint16_round_to_zero(bfloat16 a, float_status *status); +uint32_t bfloat16_to_uint32_round_to_zero(bfloat16 a, float_status *status); +uint64_t bfloat16_to_uint64_round_to_zero(bfloat16 a, float_status *status); + +bfloat16 int16_to_bfloat16_scalbn(int16_t a, int, float_status *status); +bfloat16 int32_to_bfloat16_scalbn(int32_t a, int, float_status *status); +bfloat16 int64_to_bfloat16_scalbn(int64_t a, int, float_status *status); +bfloat16 uint16_to_bfloat16_scalbn(uint16_t a, int, float_status *status); +bfloat16 uint32_to_bfloat16_scalbn(uint32_t a, int, float_status *status); +bfloat16 uint64_to_bfloat16_scalbn(uint64_t a, int, float_status *status); + +bfloat16 int16_to_bfloat16(int16_t a, float_status *status); +bfloat16 int32_to_bfloat16(int32_t a, float_status *status); +bfloat16 int64_to_bfloat16(int64_t a, float_status *status); +bfloat16 uint16_to_bfloat16(uint16_t a, float_status *status); +bfloat16 uint32_to_bfloat16(uint32_t a, float_status *status); +bfloat16 uint64_to_bfloat16(uint64_t a, float_status *status); + +/*---------------------------------------------------------------------------- +| Software bfloat16 operations. +*----------------------------------------------------------------------------*/ + +bfloat16 bfloat16_add(bfloat16, bfloat16, float_status *status); +bfloat16 bfloat16_sub(bfloat16, bfloat16, float_status *status); +bfloat16 bfloat16_mul(bfloat16, bfloat16, float_status *status); +bfloat16 bfloat16_div(bfloat16, bfloat16, float_status *status); +bfloat16 bfloat16_muladd(bfloat16, bfloat16, bfloat16, int, + float_status *status); +float16 bfloat16_scalbn(bfloat16, int, float_status *status); +bfloat16 bfloat16_min(bfloat16, bfloat16, float_status *status); +bfloat16 bfloat16_max(bfloat16, bfloat16, float_status *status); +bfloat16 bfloat16_minnum(bfloat16, bfloat16, float_status *status); +bfloat16 bfloat16_maxnum(bfloat16, bfloat16, float_status *status); +bfloat16 bfloat16_minnummag(bfloat16, bfloat16, float_status *status); +bfloat16 bfloat16_maxnummag(bfloat16, bfloat16, float_status *status); +bfloat16 bfloat16_sqrt(bfloat16, float_status *status); +FloatRelation bfloat16_compare(bfloat16, bfloat16, float_status *status); +FloatRelation bfloat16_compare_quiet(bfloat16, bfloat16, float_status *status); + +bool bfloat16_is_quiet_nan(bfloat16, float_status *status); +bool bfloat16_is_signaling_nan(bfloat16, float_status *status); +bfloat16 bfloat16_silence_nan(bfloat16, float_status *status); +bfloat16 bfloat16_default_nan(float_status *status); + +static inline bool bfloat16_is_any_nan(bfloat16 a) +{ + return ((a & ~0x8000) > 0x7F80); +} + +static inline bool bfloat16_is_neg(bfloat16 a) +{ + return a >> 15; +} + +static inline bool bfloat16_is_infinity(bfloat16 a) +{ + return (a & 0x7fff) == 0x7F80; +} + +static inline bool bfloat16_is_zero(bfloat16 a) +{ + return (a & 0x7fff) == 0; +} + +static inline bool bfloat16_is_zero_or_denormal(bfloat16 a) +{ + return (a & 0x7F80) == 0; +} + +static inline bool bfloat16_is_normal(bfloat16 a) +{ + return (((a >> 7) + 1) & 0xff) >= 2; +} + +static inline bfloat16 bfloat16_abs(bfloat16 a) +{ + /* Note that abs does *not* handle NaN specially, nor does + * it flush denormal inputs to zero. + */ + return a & 0x7fff; +} + +static inline bfloat16 bfloat16_chs(bfloat16 a) +{ + /* Note that chs does *not* handle NaN specially, nor does + * it flush denormal inputs to zero. + */ + return a ^ 0x8000; +} + +static inline bfloat16 bfloat16_set_sign(bfloat16 a, int sign) +{ + return (a & 0x7fff) | (sign << 15); +} + +static inline bool bfloat16_eq(bfloat16 a, bfloat16 b, float_status *s) +{ + return bfloat16_compare(a, b, s) == float_relation_equal; +} + +static inline bool bfloat16_le(bfloat16 a, bfloat16 b, float_status *s) +{ + return bfloat16_compare(a, b, s) <= float_relation_equal; +} + +static inline bool bfloat16_lt(bfloat16 a, bfloat16 b, float_status *s) +{ + return bfloat16_compare(a, b, s) < float_relation_equal; +} + +static inline bool bfloat16_unordered(bfloat16 a, bfloat16 b, float_status *s) +{ + return bfloat16_compare(a, b, s) == float_relation_unordered; +} + +static inline bool bfloat16_eq_quiet(bfloat16 a, bfloat16 b, float_status *s) +{ + return bfloat16_compare_quiet(a, b, s) == float_relation_equal; +} + +static inline bool bfloat16_le_quiet(bfloat16 a, bfloat16 b, float_status *s) +{ + return bfloat16_compare_quiet(a, b, s) <= float_relation_equal; +} + +static inline bool bfloat16_lt_quiet(bfloat16 a, bfloat16 b, float_status *s) +{ + return bfloat16_compare_quiet(a, b, s) < float_relation_equal; +} + +static inline bool bfloat16_unordered_quiet(bfloat16 a, bfloat16 b, + float_status *s) +{ + return bfloat16_compare_quiet(a, b, s) == float_relation_unordered; +} + +#define bfloat16_zero 0 +#define bfloat16_half 0x3f00 +#define bfloat16_one 0x3f80 +#define bfloat16_one_point_five 0x3fc0 +#define bfloat16_two 0x4000 +#define bfloat16_three 0x4040 +#define bfloat16_infinity 0x7f80 + /*---------------------------------------------------------------------------- | The pattern for a default generated half-precision NaN. *----------------------------------------------------------------------------*/ @@ -687,6 +922,9 @@ floatx80 floatx80_add(floatx80, floatx80, float_status *status); floatx80 floatx80_sub(floatx80, floatx80, float_status *status); floatx80 floatx80_mul(floatx80, floatx80, float_status *status); floatx80 floatx80_div(floatx80, floatx80, float_status *status); +floatx80 floatx80_modrem(floatx80, floatx80, bool, uint64_t *, + float_status *status); +floatx80 floatx80_mod(floatx80, floatx80, float_status *status); floatx80 floatx80_rem(floatx80, floatx80, float_status *status); floatx80 floatx80_sqrt(floatx80, float_status *status); FloatRelation floatx80_compare(floatx80, floatx80, float_status *status); @@ -791,10 +1029,35 @@ static inline bool floatx80_unordered_quiet(floatx80 a, floatx80 b, *----------------------------------------------------------------------------*/ static inline bool floatx80_invalid_encoding(floatx80 a) { +#if defined(TARGET_M68K) + /*------------------------------------------------------------------------- + | With m68k, the explicit integer bit can be zero in the case of: + | - zeros (exp == 0, mantissa == 0) + | - denormalized numbers (exp == 0, mantissa != 0) + | - unnormalized numbers (exp != 0, exp < 0x7FFF) + | - infinities (exp == 0x7FFF, mantissa == 0) + | - not-a-numbers (exp == 0x7FFF, mantissa != 0) + | + | For infinities and NaNs, the explicit integer bit can be either one or + | zero. + | + | The IEEE 754 standard does not define a zero integer bit. Such a number + | is an unnormalized number. Hardware does not directly support + | denormalized and unnormalized numbers, but implicitly supports them by + | trapping them as unimplemented data types, allowing efficient conversion + | in software. + | + | See "M68000 FAMILY PROGRAMMER’S REFERENCE MANUAL", + | "1.6 FLOATING-POINT DATA TYPES" + *------------------------------------------------------------------------*/ + return false; +#else return (a.low & (1ULL << 63)) == 0 && (a.high & 0x7FFF) != 0; +#endif } #define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL) +#define floatx80_zero_init make_floatx80_init(0x0000, 0x0000000000000000LL) #define floatx80_one make_floatx80(0x3fff, 0x8000000000000000LL) #define floatx80_ln2 make_floatx80(0x3ffe, 0xb17217f7d1cf79acLL) #define floatx80_pi make_floatx80(0x4000, 0xc90fdaa22168c235LL) diff --git a/include/glib-compat.h b/include/glib-compat.h index 0b0ec76299f07bb182d26f463815d6ab152f865a..695a96f7ea66fd7910f3f83a935e2bd93642c4f6 100644 --- a/include/glib-compat.h +++ b/include/glib-compat.h @@ -30,6 +30,11 @@ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #include +#if defined(G_OS_UNIX) +#include +#include +#include +#endif /* * Note that because of the GLIB_VERSION_MAX_ALLOWED constant above, allowing @@ -72,6 +77,29 @@ gint g_poll_fixed(GPollFD *fds, guint nfds, gint timeout); #endif +#if defined(G_OS_UNIX) +/* + * Note: The fallback implementation is not MT-safe, and it returns a copy of + * the libc passwd (must be g_free() after use) but not the content. Because of + * these important differences the caller must be aware of, it's not #define for + * GLib API substitution. + */ +static inline struct passwd * +g_unix_get_passwd_entry_qemu(const gchar *user_name, GError **error) +{ +#if GLIB_CHECK_VERSION(2, 64, 0) + return g_unix_get_passwd_entry(user_name, error); +#else + struct passwd *p = getpwnam(user_name); + if (!p) { + g_set_error_literal(error, G_UNIX_ERROR, 0, g_strerror(errno)); + return NULL; + } + return (struct passwd *)g_memdup(p, sizeof(*p)); +#endif +} +#endif /* G_OS_UNIX */ + #pragma GCC diagnostic pop #endif diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h index c13327fa7867f50eddd7393b8170a9438b7cffd8..38a42f409a24c53c0f5f47cde5cd1749434974c9 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h @@ -88,6 +88,8 @@ typedef struct AcpiFadtData { struct AcpiGenericAddress pm_tmr; /* PM_TMR_BLK */ struct AcpiGenericAddress gpe0_blk; /* GPE0_BLK */ struct AcpiGenericAddress reset_reg; /* RESET_REG */ + struct AcpiGenericAddress sleep_ctl; /* SLEEP_CONTROL_REG */ + struct AcpiGenericAddress sleep_sts; /* SLEEP_STATUS_REG */ uint8_t reset_val; /* RESET_VALUE */ uint8_t rev; /* Revision */ uint32_t flags; /* Flags */ @@ -463,24 +465,6 @@ struct Acpi20Tcpa { } QEMU_PACKED; typedef struct Acpi20Tcpa Acpi20Tcpa; -/* - * TPM2 - * - * Following Version 1.2, Revision 8 of specs: - * https://trustedcomputinggroup.org/tcg-acpi-specification/ - */ -struct Acpi20TPM2 { - ACPI_TABLE_HEADER_DEF - uint16_t platform_class; - uint16_t reserved; - uint64_t control_area_address; - uint32_t start_method; - uint8_t start_method_params[12]; - uint32_t log_area_minimum_length; - uint64_t log_area_start_address; -} QEMU_PACKED; -typedef struct Acpi20TPM2 Acpi20TPM2; - /* DMAR - DMA Remapping table r2.2 */ struct AcpiTableDmar { ACPI_TABLE_HEADER_DEF diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h index 4bef5753122926232671c85c48da94e6c545ab42..22b0b65bb2bdea46098172c412bb58adf214a370 100644 --- a/include/hw/acpi/acpi.h +++ b/include/hw/acpi/acpi.h @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h index a2a12af9b90330584cfa9895dc09d8c50c38919f..769ff55c7ee88e6a0566ad3f81ee542176880395 100644 --- a/include/hw/acpi/acpi_dev_interface.h +++ b/include/hw/acpi/acpi_dev_interface.h @@ -1,7 +1,7 @@ #ifndef ACPI_DEV_INTERFACE_H #define ACPI_DEV_INTERFACE_H -#include "qapi/qapi-types-misc.h" +#include "qapi/qapi-types-acpi.h" #include "qom/object.h" #include "hw/boards.h" #include "hw/qdev-core.h" @@ -18,12 +18,9 @@ typedef enum { #define TYPE_ACPI_DEVICE_IF "acpi-device-interface" -#define ACPI_DEVICE_IF_CLASS(klass) \ - OBJECT_CLASS_CHECK(AcpiDeviceIfClass, (klass), \ - TYPE_ACPI_DEVICE_IF) -#define ACPI_DEVICE_IF_GET_CLASS(obj) \ - OBJECT_GET_CLASS(AcpiDeviceIfClass, (obj), \ - TYPE_ACPI_DEVICE_IF) +typedef struct AcpiDeviceIfClass AcpiDeviceIfClass; +DECLARE_CLASS_CHECKERS(AcpiDeviceIfClass, ACPI_DEVICE_IF, + TYPE_ACPI_DEVICE_IF) #define ACPI_DEVICE_IF(obj) \ INTERFACE_CHECK(AcpiDeviceIf, (obj), \ TYPE_ACPI_DEVICE_IF) @@ -48,7 +45,7 @@ void acpi_send_event(DeviceState *dev, AcpiEventStatusBits event); * knowledge about internals of actual device that implements * ACPI interface. */ -typedef struct AcpiDeviceIfClass { +struct AcpiDeviceIfClass { /* */ InterfaceClass parent_class; @@ -57,5 +54,5 @@ typedef struct AcpiDeviceIfClass { void (*send_event)(AcpiDeviceIf *adev, AcpiEventStatusBits ev); void (*madt_cpu)(AcpiDeviceIf *adev, int uid, const CPUArchIdList *apic_ids, GArray *entry); -} AcpiDeviceIfClass; +}; #endif diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index ed7c89309ef1313c059a243a36c6752f93182a1a..fe0055fffb51709eb8e0d4631ee6b5cdb62f371b 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -290,6 +290,7 @@ Aml *aml_to_buffer(Aml *src, Aml *dst); Aml *aml_store(Aml *val, Aml *target); Aml *aml_and(Aml *arg1, Aml *arg2, Aml *dst); Aml *aml_or(Aml *arg1, Aml *arg2, Aml *dst); +Aml *aml_land(Aml *arg1, Aml *arg2); Aml *aml_lor(Aml *arg1, Aml *arg2); Aml *aml_shiftleft(Aml *arg1, Aml *count); Aml *aml_shiftright(Aml *arg1, Aml *count, Aml *dst); @@ -300,6 +301,7 @@ Aml *aml_increment(Aml *arg); Aml *aml_decrement(Aml *arg); Aml *aml_index(Aml *arg1, Aml *idx); Aml *aml_notify(Aml *arg1, Aml *arg2); +Aml *aml_break(void); Aml *aml_call0(const char *method); Aml *aml_call1(const char *method, Aml *arg1); Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2); @@ -437,4 +439,6 @@ void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms); void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f, const char *oem_id, const char *oem_table_id); + +void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog); #endif diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h index 62f0278ba2586fbe2fdaf553691e4a20c5cccf5d..0eeedaa491c14cca4926a388a5461917bb8bcb10 100644 --- a/include/hw/acpi/cpu.h +++ b/include/hw/acpi/cpu.h @@ -50,6 +50,7 @@ void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner, typedef struct CPUHotplugFeatures { bool acpi_1_compatible; bool has_legacy_cphp; + const char *smi_path; } CPUHotplugFeatures; void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h index 83917de0242509dcd8a4849e22616c8001033f7c..6bed92e8fc50ecbb257123b5fce4c58768296e48 100644 --- a/include/hw/acpi/generic_event_device.h +++ b/include/hw/acpi/generic_event_device.h @@ -62,16 +62,31 @@ #include "hw/sysbus.h" #include "hw/acpi/memory_hotplug.h" #include "hw/acpi/ghes.h" +#include "qom/object.h" #define ACPI_POWER_BUTTON_DEVICE "PWRB" #define TYPE_ACPI_GED "acpi-ged" -#define ACPI_GED(obj) \ - OBJECT_CHECK(AcpiGedState, (obj), TYPE_ACPI_GED) +OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED) + +#define TYPE_ACPI_GED_X86 "acpi-ged-x86" +#define ACPI_GED_X86(obj) \ + OBJECT_CHECK(AcpiGedX86State, (obj), TYPE_ACPI_GED_X86) #define ACPI_GED_EVT_SEL_OFFSET 0x0 #define ACPI_GED_EVT_SEL_LEN 0x4 +#define ACPI_GED_REG_SLEEP_CTL 0x00 +#define ACPI_GED_REG_SLEEP_STS 0x01 +#define ACPI_GED_REG_RESET 0x02 +#define ACPI_GED_REG_COUNT 0x03 + +/* ACPI_GED_REG_RESET value for reset*/ +#define ACPI_GED_RESET_VALUE 0x42 + +/* ACPI_GED_REG_SLEEP_CTL.SLP_TYP value for S5 (aka poweroff) */ +#define ACPI_GED_SLP_TYP_S5 0x05 + #define GED_DEVICE "GED" #define AML_GED_EVT_REG "EREG" #define AML_GED_EVT_SEL "ESEL" @@ -86,11 +101,12 @@ #define ACPI_GED_NVDIMM_HOTPLUG_EVT 0x4 typedef struct GEDState { - MemoryRegion io; + MemoryRegion evt; + MemoryRegion regs; uint32_t sel; } GEDState; -typedef struct AcpiGedState { +struct AcpiGedState { SysBusDevice parent_obj; MemHotplugState memhp_state; MemoryRegion container_memhp; @@ -98,9 +114,10 @@ typedef struct AcpiGedState { uint32_t ged_event_bitmap; qemu_irq irq; AcpiGhesState ghes_state; -} AcpiGedState; +}; void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev, uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base); +void acpi_dsdt_add_power_button(Aml *scope); #endif diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h index 28a53181cb22447541b209f5830517593442c1e6..54571c77e07c32d76904653c7a0389d9688b3d92 100644 --- a/include/hw/acpi/ich9.h +++ b/include/hw/acpi/ich9.h @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h index 8bc4a4c01dba268625fe1f56f5b4757e00bee14c..dfd375820f87e97caeba6f9764b4cba01b7ce377 100644 --- a/include/hw/acpi/pcihp.h +++ b/include/hw/acpi/pcihp.h @@ -10,7 +10,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -67,7 +67,7 @@ void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev, Error **errp); /* Called on reset */ -void acpi_pcihp_reset(AcpiPciHpState *s); +void acpi_pcihp_reset(AcpiPciHpState *s, bool acpihp_root_off); extern const VMStateDescription vmstate_acpi_pcihp_pci_status; diff --git a/include/hw/acpi/vmgenid.h b/include/hw/acpi/vmgenid.h index c49d913f3e0e2395bc6044fa330f4dcd7307e301..cb4ad37fc5b35f08f9b261443a28878b46fbfb23 100644 --- a/include/hw/acpi/vmgenid.h +++ b/include/hw/acpi/vmgenid.h @@ -4,8 +4,9 @@ #include "hw/acpi/bios-linker-loader.h" #include "hw/qdev-core.h" #include "qemu/uuid.h" +#include "qom/object.h" -#define VMGENID_DEVICE "vmgenid" +#define TYPE_VMGENID "vmgenid" #define VMGENID_GUID "guid" #define VMGENID_GUID_FW_CFG_FILE "etc/vmgenid_guid" #define VMGENID_ADDR_FW_CFG_FILE "etc/vmgenid_addr" @@ -15,18 +16,18 @@ * OVMF SDT Header Probe Supressor */ -#define VMGENID(obj) OBJECT_CHECK(VmGenIdState, (obj), VMGENID_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(VmGenIdState, VMGENID) -typedef struct VmGenIdState { - DeviceClass parent_obj; +struct VmGenIdState { + DeviceState parent_obj; QemuUUID guid; /* The 128-bit GUID seen by the guest */ uint8_t vmgenid_addr_le[8]; /* Address of the GUID (little-endian) */ -} VmGenIdState; +}; /* returns NULL unless there is exactly one device */ static inline Object *find_vmgenid_dev(void) { - return object_resolve_path_type("", VMGENID_DEVICE, NULL); + return object_resolve_path_type("", TYPE_VMGENID, NULL); } void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid, diff --git a/include/hw/adc/stm32f2xx_adc.h b/include/hw/adc/stm32f2xx_adc.h index 663b79f4f3a8ef32919e2c674011c7d999eecfec..42b48981f2412b78db71759a19b6169d340868cb 100644 --- a/include/hw/adc/stm32f2xx_adc.h +++ b/include/hw/adc/stm32f2xx_adc.h @@ -26,6 +26,7 @@ #define HW_STM32F2XX_ADC_H #include "hw/sysbus.h" +#include "qom/object.h" #define ADC_SR 0x00 #define ADC_CR1 0x04 @@ -58,10 +59,9 @@ #define ADC_COMMON_ADDRESS 0x100 #define TYPE_STM32F2XX_ADC "stm32f2xx-adc" -#define STM32F2XX_ADC(obj) \ - OBJECT_CHECK(STM32F2XXADCState, (obj), TYPE_STM32F2XX_ADC) +OBJECT_DECLARE_SIMPLE_TYPE(STM32F2XXADCState, STM32F2XX_ADC) -typedef struct { +struct STM32F2XXADCState { /* */ SysBusDevice parent_obj; @@ -84,6 +84,6 @@ typedef struct { uint32_t adc_dr; qemu_irq irq; -} STM32F2XXADCState; +}; #endif /* HW_STM32F2XX_ADC_H */ diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h index 77c82a9982826382e53b6c2187136e5ee07f907f..a76dc7b84d6e2848de89011192905bcbc552a378 100644 --- a/include/hw/arm/allwinner-a10.h +++ b/include/hw/arm/allwinner-a10.h @@ -14,6 +14,7 @@ #include "hw/rtc/allwinner-rtc.h" #include "target/arm/cpu.h" +#include "qom/object.h" #define AW_A10_SDRAM_BASE 0x40000000 @@ -21,9 +22,9 @@ #define AW_A10_NUM_USB 2 #define TYPE_AW_A10 "allwinner-a10" -#define AW_A10(obj) OBJECT_CHECK(AwA10State, (obj), TYPE_AW_A10) +OBJECT_DECLARE_SIMPLE_TYPE(AwA10State, AW_A10) -typedef struct AwA10State { +struct AwA10State { /*< private >*/ DeviceState parent_obj; /*< public >*/ @@ -38,6 +39,6 @@ typedef struct AwA10State { MemoryRegion sram_a; EHCISysBusState ehci[AW_A10_NUM_USB]; OHCISysBusState ohci[AW_A10_NUM_USB]; -} AwA10State; +}; #endif diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h index 82e4e59216622d66abbd137b3115902b39f6c3b0..cc308a5d2c95f9f8c3fa244edde6002ba6408ab8 100644 --- a/include/hw/arm/allwinner-h3.h +++ b/include/hw/arm/allwinner-h3.h @@ -61,37 +61,37 @@ * @see AwH3State */ enum { - AW_H3_SRAM_A1, - AW_H3_SRAM_A2, - AW_H3_SRAM_C, - AW_H3_SYSCTRL, - AW_H3_MMC0, - AW_H3_SID, - AW_H3_EHCI0, - AW_H3_OHCI0, - AW_H3_EHCI1, - AW_H3_OHCI1, - AW_H3_EHCI2, - AW_H3_OHCI2, - AW_H3_EHCI3, - AW_H3_OHCI3, - AW_H3_CCU, - AW_H3_PIT, - AW_H3_UART0, - AW_H3_UART1, - AW_H3_UART2, - AW_H3_UART3, - AW_H3_EMAC, - AW_H3_DRAMCOM, - AW_H3_DRAMCTL, - AW_H3_DRAMPHY, - AW_H3_GIC_DIST, - AW_H3_GIC_CPU, - AW_H3_GIC_HYP, - AW_H3_GIC_VCPU, - AW_H3_RTC, - AW_H3_CPUCFG, - AW_H3_SDRAM + AW_H3_DEV_SRAM_A1, + AW_H3_DEV_SRAM_A2, + AW_H3_DEV_SRAM_C, + AW_H3_DEV_SYSCTRL, + AW_H3_DEV_MMC0, + AW_H3_DEV_SID, + AW_H3_DEV_EHCI0, + AW_H3_DEV_OHCI0, + AW_H3_DEV_EHCI1, + AW_H3_DEV_OHCI1, + AW_H3_DEV_EHCI2, + AW_H3_DEV_OHCI2, + AW_H3_DEV_EHCI3, + AW_H3_DEV_OHCI3, + AW_H3_DEV_CCU, + AW_H3_DEV_PIT, + AW_H3_DEV_UART0, + AW_H3_DEV_UART1, + AW_H3_DEV_UART2, + AW_H3_DEV_UART3, + AW_H3_DEV_EMAC, + AW_H3_DEV_DRAMCOM, + AW_H3_DEV_DRAMCTL, + AW_H3_DEV_DRAMPHY, + AW_H3_DEV_GIC_DIST, + AW_H3_DEV_GIC_CPU, + AW_H3_DEV_GIC_HYP, + AW_H3_DEV_GIC_VCPU, + AW_H3_DEV_RTC, + AW_H3_DEV_CPUCFG, + AW_H3_DEV_SDRAM }; /** Total number of CPU cores in the H3 SoC */ @@ -106,7 +106,7 @@ enum { #define TYPE_AW_H3 "allwinner-h3" /** Convert input object to Allwinner H3 state object */ -#define AW_H3(obj) OBJECT_CHECK(AwH3State, (obj), TYPE_AW_H3) +OBJECT_DECLARE_SIMPLE_TYPE(AwH3State, AW_H3) /** @} */ @@ -116,7 +116,7 @@ enum { * This struct contains the state of all the devices * which are currently emulated by the H3 SoC code. */ -typedef struct AwH3State { +struct AwH3State { /*< private >*/ DeviceState parent_obj; /*< public >*/ @@ -136,7 +136,7 @@ typedef struct AwH3State { MemoryRegion sram_a1; MemoryRegion sram_a2; MemoryRegion sram_c; -} AwH3State; +}; /** * Emulate Boot ROM firmware setup functionality. diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h index 84080c2299396ddccd9b4ba9684392a23cc0db86..77f86771c30840942e388a1d47568b7fe1ea47dd 100644 --- a/include/hw/arm/armsse.h +++ b/include/hw/arm/armsse.h @@ -105,9 +105,11 @@ #include "hw/or-irq.h" #include "hw/core/split-irq.h" #include "hw/cpu/cluster.h" +#include "qom/object.h" -#define TYPE_ARMSSE "arm-sse" -#define ARMSSE(obj) OBJECT_CHECK(ARMSSE, (obj), TYPE_ARMSSE) +#define TYPE_ARM_SSE "arm-sse" +OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass, + ARM_SSE) /* * These type names are for specific IoTKit subsystems; other than @@ -140,7 +142,7 @@ #define RAM3_PPU 6 #define NUM_PPUS 7 -typedef struct ARMSSE { +struct ARMSSE { /*< private >*/ SysBusDevice parent_obj; @@ -215,18 +217,14 @@ typedef struct ARMSSE { uint32_t init_svtor; bool cpu_fpu[SSE_MAX_CPUS]; bool cpu_dsp[SSE_MAX_CPUS]; -} ARMSSE; +}; typedef struct ARMSSEInfo ARMSSEInfo; -typedef struct ARMSSEClass { - DeviceClass parent_class; +struct ARMSSEClass { + SysBusDeviceClass parent_class; const ARMSSEInfo *info; -} ARMSSEClass; +}; -#define ARMSSE_CLASS(klass) \ - OBJECT_CLASS_CHECK(ARMSSEClass, (klass), TYPE_ARMSSE) -#define ARMSSE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ARMSSEClass, (obj), TYPE_ARMSSE) #endif diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h index d2c74d3872a16483da7d6617399690fa08c3761e..0791dcb68a6274d0f9243e00065c32fa12b7f455 100644 --- a/include/hw/arm/armv7m.h +++ b/include/hw/arm/armv7m.h @@ -13,11 +13,12 @@ #include "hw/sysbus.h" #include "hw/intc/armv7m_nvic.h" #include "target/arm/idau.h" +#include "qom/object.h" #define TYPE_BITBAND "ARM,bitband-memory" -#define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND) +OBJECT_DECLARE_SIMPLE_TYPE(BitBandState, BITBAND) -typedef struct { +struct BitBandState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -26,16 +27,18 @@ typedef struct { MemoryRegion iomem; uint32_t base; MemoryRegion *source_memory; -} BitBandState; +}; #define TYPE_ARMV7M "armv7m" -#define ARMV7M(obj) OBJECT_CHECK(ARMv7MState, (obj), TYPE_ARMV7M) +OBJECT_DECLARE_SIMPLE_TYPE(ARMv7MState, ARMV7M) #define ARMV7M_NUM_BITBANDS 2 /* ARMv7M container object. * + Unnamed GPIO input lines: external IRQ lines for the NVIC - * + Named GPIO output SYSRESETREQ: signalled for guest AIRCR.SYSRESETREQ + * + Named GPIO output SYSRESETREQ: signalled for guest AIRCR.SYSRESETREQ. + * If this GPIO is not wired up then the NVIC will default to performing + * a qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET). * + Property "cpu-type": CPU type to instantiate * + Property "num-irq": number of external IRQ lines * + Property "memory": MemoryRegion defining the physical address space @@ -47,7 +50,7 @@ typedef struct { * + Property "dsp": enable DSP (forwarded to CPU object) * + Property "enable-bitband": expose bitbanded IO */ -typedef struct ARMv7MState { +struct ARMv7MState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -70,6 +73,6 @@ typedef struct ARMv7MState { bool start_powered_off; bool vfp; bool dsp; -} ARMv7MState; +}; #endif diff --git a/include/hw/arm/aspeed.h b/include/hw/arm/aspeed.h index 18521484b90e24bcb46d5aa8b2f90f7bd00a7550..c9747b15fc5fdbcd479c0c83da93ecee87e0ae90 100644 --- a/include/hw/arm/aspeed.h +++ b/include/hw/arm/aspeed.h @@ -10,25 +10,22 @@ #define ARM_ASPEED_H #include "hw/boards.h" +#include "qom/object.h" -typedef struct AspeedBoardState AspeedBoardState; +typedef struct AspeedMachineState AspeedMachineState; #define TYPE_ASPEED_MACHINE MACHINE_TYPE_NAME("aspeed") -#define ASPEED_MACHINE(obj) \ - OBJECT_CHECK(AspeedMachine, (obj), TYPE_ASPEED_MACHINE) +typedef struct AspeedMachineClass AspeedMachineClass; +DECLARE_OBJ_CHECKERS(AspeedMachineState, AspeedMachineClass, + ASPEED_MACHINE, TYPE_ASPEED_MACHINE) -typedef struct AspeedMachine { - MachineState parent_obj; +#define ASPEED_MAC0_ON (1 << 0) +#define ASPEED_MAC1_ON (1 << 1) +#define ASPEED_MAC2_ON (1 << 2) +#define ASPEED_MAC3_ON (1 << 3) - bool mmio_exec; -} AspeedMachine; -#define ASPEED_MACHINE_CLASS(klass) \ - OBJECT_CLASS_CHECK(AspeedMachineClass, (klass), TYPE_ASPEED_MACHINE) -#define ASPEED_MACHINE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(AspeedMachineClass, (obj), TYPE_ASPEED_MACHINE) - -typedef struct AspeedMachineClass { +struct AspeedMachineClass { MachineClass parent_obj; const char *name; @@ -39,8 +36,9 @@ typedef struct AspeedMachineClass { const char *fmc_model; const char *spi_model; uint32_t num_cs; - void (*i2c_init)(AspeedBoardState *bmc); -} AspeedMachineClass; + uint32_t macs_mask; + void (*i2c_init)(AspeedMachineState *bmc); +}; #endif diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 78b9f6ae532fafcfe335ae49a8231a4ee90a9cfc..11cfe6e3585b55b4fcce78b99fcb8e169934de2e 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -27,6 +27,7 @@ #include "hw/gpio/aspeed_gpio.h" #include "hw/sd/aspeed_sdhci.h" #include "hw/usb/hcd-ehci.h" +#include "qom/object.h" #define ASPEED_SPIS_NUM 2 #define ASPEED_EHCIS_NUM 2 @@ -34,13 +35,12 @@ #define ASPEED_CPUS_NUM 2 #define ASPEED_MACS_NUM 4 -typedef struct AspeedSoCState { +struct AspeedSoCState { /*< private >*/ DeviceState parent; /*< public >*/ ARMCPU cpu[ASPEED_CPUS_NUM]; - uint32_t num_cpus; A15MPPrivState a7mpcore; MemoryRegion *dram_mr; MemoryRegion sram; @@ -61,12 +61,12 @@ typedef struct AspeedSoCState { AspeedGPIOState gpio_1_8v; AspeedSDHCIState sdhci; AspeedSDHCIState emmc; -} AspeedSoCState; +}; #define TYPE_ASPEED_SOC "aspeed-soc" -#define ASPEED_SOC(obj) OBJECT_CHECK(AspeedSoCState, (obj), TYPE_ASPEED_SOC) +OBJECT_DECLARE_TYPE(AspeedSoCState, AspeedSoCClass, ASPEED_SOC) -typedef struct AspeedSoCClass { +struct AspeedSoCClass { DeviceClass parent_class; const char *name; @@ -80,60 +80,56 @@ typedef struct AspeedSoCClass { const int *irqmap; const hwaddr *memmap; uint32_t num_cpus; -} AspeedSoCClass; +}; -#define ASPEED_SOC_CLASS(klass) \ - OBJECT_CLASS_CHECK(AspeedSoCClass, (klass), TYPE_ASPEED_SOC) -#define ASPEED_SOC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(AspeedSoCClass, (obj), TYPE_ASPEED_SOC) enum { - ASPEED_IOMEM, - ASPEED_UART1, - ASPEED_UART2, - ASPEED_UART3, - ASPEED_UART4, - ASPEED_UART5, - ASPEED_VUART, - ASPEED_FMC, - ASPEED_SPI1, - ASPEED_SPI2, - ASPEED_EHCI1, - ASPEED_EHCI2, - ASPEED_VIC, - ASPEED_SDMC, - ASPEED_SCU, - ASPEED_ADC, - ASPEED_VIDEO, - ASPEED_SRAM, - ASPEED_SDHCI, - ASPEED_GPIO, - ASPEED_GPIO_1_8V, - ASPEED_RTC, - ASPEED_TIMER1, - ASPEED_TIMER2, - ASPEED_TIMER3, - ASPEED_TIMER4, - ASPEED_TIMER5, - ASPEED_TIMER6, - ASPEED_TIMER7, - ASPEED_TIMER8, - ASPEED_WDT, - ASPEED_PWM, - ASPEED_LPC, - ASPEED_IBT, - ASPEED_I2C, - ASPEED_ETH1, - ASPEED_ETH2, - ASPEED_ETH3, - ASPEED_ETH4, - ASPEED_MII1, - ASPEED_MII2, - ASPEED_MII3, - ASPEED_MII4, - ASPEED_SDRAM, - ASPEED_XDMA, - ASPEED_EMMC, + ASPEED_DEV_IOMEM, + ASPEED_DEV_UART1, + ASPEED_DEV_UART2, + ASPEED_DEV_UART3, + ASPEED_DEV_UART4, + ASPEED_DEV_UART5, + ASPEED_DEV_VUART, + ASPEED_DEV_FMC, + ASPEED_DEV_SPI1, + ASPEED_DEV_SPI2, + ASPEED_DEV_EHCI1, + ASPEED_DEV_EHCI2, + ASPEED_DEV_VIC, + ASPEED_DEV_SDMC, + ASPEED_DEV_SCU, + ASPEED_DEV_ADC, + ASPEED_DEV_VIDEO, + ASPEED_DEV_SRAM, + ASPEED_DEV_SDHCI, + ASPEED_DEV_GPIO, + ASPEED_DEV_GPIO_1_8V, + ASPEED_DEV_RTC, + ASPEED_DEV_TIMER1, + ASPEED_DEV_TIMER2, + ASPEED_DEV_TIMER3, + ASPEED_DEV_TIMER4, + ASPEED_DEV_TIMER5, + ASPEED_DEV_TIMER6, + ASPEED_DEV_TIMER7, + ASPEED_DEV_TIMER8, + ASPEED_DEV_WDT, + ASPEED_DEV_PWM, + ASPEED_DEV_LPC, + ASPEED_DEV_IBT, + ASPEED_DEV_I2C, + ASPEED_DEV_ETH1, + ASPEED_DEV_ETH2, + ASPEED_DEV_ETH3, + ASPEED_DEV_ETH4, + ASPEED_DEV_MII1, + ASPEED_DEV_MII2, + ASPEED_DEV_MII3, + ASPEED_DEV_MII4, + ASPEED_DEV_SDRAM, + ASPEED_DEV_XDMA, + ASPEED_DEV_EMMC, }; #endif /* ASPEED_SOC_H */ diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h index 2e8655a7c2dde4d2c4cdbb1fb81d59eacf1cff4b..479e2346e80a95d77ad053ac5228a53b5cb6890e 100644 --- a/include/hw/arm/bcm2835_peripherals.h +++ b/include/hw/arm/bcm2835_peripherals.h @@ -21,18 +21,21 @@ #include "hw/misc/bcm2835_property.h" #include "hw/misc/bcm2835_rng.h" #include "hw/misc/bcm2835_mbox.h" +#include "hw/misc/bcm2835_mphi.h" #include "hw/misc/bcm2835_thermal.h" +#include "hw/misc/bcm2835_cprman.h" #include "hw/sd/sdhci.h" #include "hw/sd/bcm2835_sdhost.h" #include "hw/gpio/bcm2835_gpio.h" #include "hw/timer/bcm2835_systmr.h" +#include "hw/usb/hcd-dwc2.h" #include "hw/misc/unimp.h" +#include "qom/object.h" #define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals" -#define BCM2835_PERIPHERALS(obj) \ - OBJECT_CHECK(BCM2835PeripheralState, (obj), TYPE_BCM2835_PERIPHERALS) +OBJECT_DECLARE_SIMPLE_TYPE(BCM2835PeripheralState, BCM2835_PERIPHERALS) -typedef struct BCM2835PeripheralState { +struct BCM2835PeripheralState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -42,9 +45,11 @@ typedef struct BCM2835PeripheralState { qemu_irq irq, fiq; BCM2835SystemTimerState systmr; + BCM2835MphiState mphi; + UnimplementedDeviceState txp; UnimplementedDeviceState armtmr; - UnimplementedDeviceState cprman; - UnimplementedDeviceState a2w; + UnimplementedDeviceState powermgt; + BCM2835CprmanState cprman; PL011State uart0; BCM2835AuxState aux; BCM2835FBState fb; @@ -63,10 +68,11 @@ typedef struct BCM2835PeripheralState { UnimplementedDeviceState otp; UnimplementedDeviceState dbus; UnimplementedDeviceState ave0; + UnimplementedDeviceState v3d; UnimplementedDeviceState bscsl; UnimplementedDeviceState smi; - UnimplementedDeviceState dwc2; + DWC2State dwc2; UnimplementedDeviceState sdramc; -} BCM2835PeripheralState; +}; #endif /* BCM2835_PERIPHERALS_H */ diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h index 024af8aae4f307c6577f1c78e370b4d7c61010cb..6f90cabfa3afd6fce2a307cb2b5d10bad7089399 100644 --- a/include/hw/arm/bcm2836.h +++ b/include/hw/arm/bcm2836.h @@ -15,9 +15,10 @@ #include "hw/arm/bcm2835_peripherals.h" #include "hw/intc/bcm2836_control.h" #include "target/arm/cpu.h" +#include "qom/object.h" #define TYPE_BCM283X "bcm283x" -#define BCM283X(obj) OBJECT_CHECK(BCM283XState, (obj), TYPE_BCM283X) +OBJECT_DECLARE_TYPE(BCM283XState, BCM283XClass, BCM283X) #define BCM283X_NCPUS 4 @@ -25,15 +26,15 @@ * them, code using these devices should always handle them via the * BCM283x base class, so they have no BCM2836(obj) etc macros. */ +#define TYPE_BCM2835 "bcm2835" #define TYPE_BCM2836 "bcm2836" #define TYPE_BCM2837 "bcm2837" -typedef struct BCM283XState { +struct BCM283XState { /*< private >*/ DeviceState parent_obj; /*< public >*/ - char *cpu_type; uint32_t enabled_cpus; struct { @@ -41,18 +42,6 @@ typedef struct BCM283XState { } cpu[BCM283X_NCPUS]; BCM2836ControlState control; BCM2835PeripheralState peripherals; -} BCM283XState; - -typedef struct BCM283XInfo BCM283XInfo; - -typedef struct BCM283XClass { - DeviceClass parent_class; - const BCM283XInfo *info; -} BCM283XClass; - -#define BCM283X_CLASS(klass) \ - OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X) -#define BCM283X_GET_CLASS(obj) \ - OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X) +}; #endif /* BCM2836_H */ diff --git a/include/hw/arm/digic.h b/include/hw/arm/digic.h index 63785baaa87f2b042147511e625c61bfd612c8bc..8f2735c284f87222c626e21631f196066f189813 100644 --- a/include/hw/arm/digic.h +++ b/include/hw/arm/digic.h @@ -21,14 +21,15 @@ #include "cpu.h" #include "hw/timer/digic-timer.h" #include "hw/char/digic-uart.h" +#include "qom/object.h" #define TYPE_DIGIC "digic" -#define DIGIC(obj) OBJECT_CHECK(DigicState, (obj), TYPE_DIGIC) +OBJECT_DECLARE_SIMPLE_TYPE(DigicState, DIGIC) #define DIGIC4_NB_TIMERS 3 -typedef struct DigicState { +struct DigicState { /*< private >*/ DeviceState parent_obj; /*< public >*/ @@ -37,6 +38,6 @@ typedef struct DigicState { DigicTimerState timer[DIGIC4_NB_TIMERS]; DigicUartState uart; -} DigicState; +}; #endif /* HW_ARM_DIGIC_H */ diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h index 55260394af67bba1ab901930c5b9e3f1db5380ea..60b9e126f550c8cf96342fbb70a7c31e001c8d74 100644 --- a/include/hw/arm/exynos4210.h +++ b/include/hw/arm/exynos4210.h @@ -27,6 +27,7 @@ #include "hw/or-irq.h" #include "hw/sysbus.h" #include "target/arm/cpu-qom.h" +#include "qom/object.h" #define EXYNOS4210_NCPUS 2 @@ -85,7 +86,7 @@ typedef struct Exynos4210Irq { qemu_irq board_irqs[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ]; } Exynos4210Irq; -typedef struct Exynos4210State { +struct Exynos4210State { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -101,11 +102,10 @@ typedef struct Exynos4210State { MemoryRegion bootreg_mem; I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER]; qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA]; -} Exynos4210State; +}; #define TYPE_EXYNOS4210_SOC "exynos4210" -#define EXYNOS4210_SOC(obj) \ - OBJECT_CHECK(Exynos4210State, obj, TYPE_EXYNOS4210_SOC) +OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210State, EXYNOS4210_SOC) void exynos4210_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info); diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h index 9e228daceae30bf14dbf103628666f398557b9c4..c1603b2ac21e12d46b925314966448efcfdbd6f3 100644 --- a/include/hw/arm/fsl-imx25.h +++ b/include/hw/arm/fsl-imx25.h @@ -32,9 +32,10 @@ #include "hw/watchdog/wdt_imx2.h" #include "exec/memory.h" #include "target/arm/cpu.h" +#include "qom/object.h" #define TYPE_FSL_IMX25 "fsl,imx25" -#define FSL_IMX25(obj) OBJECT_CHECK(FslIMX25State, (obj), TYPE_FSL_IMX25) +OBJECT_DECLARE_SIMPLE_TYPE(FslIMX25State, FSL_IMX25) #define FSL_IMX25_NUM_UARTS 5 #define FSL_IMX25_NUM_GPTS 4 @@ -44,7 +45,7 @@ #define FSL_IMX25_NUM_ESDHCS 2 #define FSL_IMX25_NUM_USBS 2 -typedef struct FslIMX25State { +struct FslIMX25State { /*< private >*/ DeviceState parent_obj; @@ -65,7 +66,8 @@ typedef struct FslIMX25State { MemoryRegion rom[2]; MemoryRegion iram; MemoryRegion iram_alias; -} FslIMX25State; + uint32_t phy_num; +}; /** * i.MX25 memory map @@ -177,7 +179,7 @@ typedef struct FslIMX25State { * 0xBB00_0000 0xBB00_0FFF 4 Kbytes NAND flash main area buffer * 0xBB00_1000 0xBB00_11FF 512 B NAND flash spare area buffer * 0xBB00_1200 0xBB00_1DFF 3 Kbytes Reserved - * 0xBB00_1E00 0xBB00_1FFF 512 B NAND flash control regisers + * 0xBB00_1E00 0xBB00_1FFF 512 B NAND flash control registers * 0xBB01_2000 0xBFFF_FFFF 96 Mbytes (minus 8 Kbytes) Reserved * 0xC000_0000 0xFFFF_FFFF 1024 Mbytes Reserved */ diff --git a/include/hw/arm/fsl-imx31.h b/include/hw/arm/fsl-imx31.h index dd8561b3098c3db737487b3369a46d979efceb09..b9792d58ae5278817507e1c4e6a86dec8cc99a03 100644 --- a/include/hw/arm/fsl-imx31.h +++ b/include/hw/arm/fsl-imx31.h @@ -28,16 +28,17 @@ #include "hw/watchdog/wdt_imx2.h" #include "exec/memory.h" #include "target/arm/cpu.h" +#include "qom/object.h" #define TYPE_FSL_IMX31 "fsl,imx31" -#define FSL_IMX31(obj) OBJECT_CHECK(FslIMX31State, (obj), TYPE_FSL_IMX31) +OBJECT_DECLARE_SIMPLE_TYPE(FslIMX31State, FSL_IMX31) #define FSL_IMX31_NUM_UARTS 2 #define FSL_IMX31_NUM_EPITS 2 #define FSL_IMX31_NUM_I2CS 3 #define FSL_IMX31_NUM_GPIOS 3 -typedef struct FslIMX31State { +struct FslIMX31State { /*< private >*/ DeviceState parent_obj; @@ -55,7 +56,7 @@ typedef struct FslIMX31State { MemoryRegion rom; MemoryRegion iram; MemoryRegion iram_alias; -} FslIMX31State; +}; #define FSL_IMX31_SECURE_ROM_ADDR 0x00000000 #define FSL_IMX31_SECURE_ROM_SIZE 0x4000 diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h index 1ebd75132464980f622cf48c8fdd0b78a6d53d80..29cc425acc2369f8ea8cfb9af33c8938cf707503 100644 --- a/include/hw/arm/fsl-imx6.h +++ b/include/hw/arm/fsl-imx6.h @@ -34,9 +34,10 @@ #include "hw/usb/imx-usb-phy.h" #include "exec/memory.h" #include "cpu.h" +#include "qom/object.h" #define TYPE_FSL_IMX6 "fsl,imx6" -#define FSL_IMX6(obj) OBJECT_CHECK(FslIMX6State, (obj), TYPE_FSL_IMX6) +OBJECT_DECLARE_SIMPLE_TYPE(FslIMX6State, FSL_IMX6) #define FSL_IMX6_NUM_CPUS 4 #define FSL_IMX6_NUM_UARTS 5 @@ -49,7 +50,7 @@ #define FSL_IMX6_NUM_USB_PHYS 2 #define FSL_IMX6_NUM_USBS 4 -typedef struct FslIMX6State { +struct FslIMX6State { /*< private >*/ DeviceState parent_obj; @@ -73,7 +74,8 @@ typedef struct FslIMX6State { MemoryRegion caam; MemoryRegion ocram; MemoryRegion ocram_alias; -} FslIMX6State; + uint32_t phy_num; +}; #define FSL_IMX6_MMDC_ADDR 0x10000000 diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h index 37c89cc5f92f6f2d50b621ccfc1ab107c34459b7..f8ebfba4f97de9c69980ab2fe79cf8e264576a22 100644 --- a/include/hw/arm/fsl-imx6ul.h +++ b/include/hw/arm/fsl-imx6ul.h @@ -38,9 +38,10 @@ #include "hw/usb/imx-usb-phy.h" #include "exec/memory.h" #include "cpu.h" +#include "qom/object.h" #define TYPE_FSL_IMX6UL "fsl,imx6ul" -#define FSL_IMX6UL(obj) OBJECT_CHECK(FslIMX6ULState, (obj), TYPE_FSL_IMX6UL) +OBJECT_DECLARE_SIMPLE_TYPE(FslIMX6ULState, FSL_IMX6UL) enum FslIMX6ULConfiguration { FSL_IMX6UL_NUM_CPUS = 1, @@ -60,7 +61,7 @@ enum FslIMX6ULConfiguration { FSL_IMX6UL_NUM_USBS = 2, }; -typedef struct FslIMX6ULState { +struct FslIMX6ULState { /*< private >*/ DeviceState parent_obj; @@ -87,7 +88,9 @@ typedef struct FslIMX6ULState { MemoryRegion caam; MemoryRegion ocram; MemoryRegion ocram_alias; -} FslIMX6ULState; + + uint32_t phy_num[FSL_IMX6UL_NUM_ETHS]; +}; enum FslIMX6ULMemoryMap { FSL_IMX6UL_MMDC_ADDR = 0x80000000, diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h index da977f9ffb474f288f27517ecba0dfe49f5e2312..161fdc36da001463b5b514931b84f2a0f3bdfb34 100644 --- a/include/hw/arm/fsl-imx7.h +++ b/include/hw/arm/fsl-imx7.h @@ -39,9 +39,10 @@ #include "hw/pci-host/designware.h" #include "hw/usb/chipidea.h" #include "cpu.h" +#include "qom/object.h" #define TYPE_FSL_IMX7 "fsl,imx7" -#define FSL_IMX7(obj) OBJECT_CHECK(FslIMX7State, (obj), TYPE_FSL_IMX7) +OBJECT_DECLARE_SIMPLE_TYPE(FslIMX7State, FSL_IMX7) enum FslIMX7Configuration { FSL_IMX7_NUM_CPUS = 2, @@ -59,7 +60,7 @@ enum FslIMX7Configuration { FSL_IMX7_NUM_ADCS = 2, }; -typedef struct FslIMX7State { +struct FslIMX7State { /*< private >*/ DeviceState parent_obj; @@ -81,7 +82,8 @@ typedef struct FslIMX7State { IMX7GPRState gpr; ChipideaState usb[FSL_IMX7_NUM_USBS]; DesignwarePCIEHost pcie; -} FslIMX7State; + uint32_t phy_num[FSL_IMX7_NUM_ETHS]; +}; enum FslIMX7MemoryMap { FSL_IMX7_MMDC_ADDR = 0x80000000, diff --git a/include/hw/arm/linux-boot-if.h b/include/hw/arm/linux-boot-if.h index 7bbdfd1cc688328055883811b483a7c5e4179253..c85f33b2c51919a7500f0de4f89a83988b2fb465 100644 --- a/include/hw/arm/linux-boot-if.h +++ b/include/hw/arm/linux-boot-if.h @@ -9,16 +9,15 @@ #include "qom/object.h" #define TYPE_ARM_LINUX_BOOT_IF "arm-linux-boot-if" -#define ARM_LINUX_BOOT_IF_CLASS(klass) \ - OBJECT_CLASS_CHECK(ARMLinuxBootIfClass, (klass), TYPE_ARM_LINUX_BOOT_IF) -#define ARM_LINUX_BOOT_IF_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ARMLinuxBootIfClass, (obj), TYPE_ARM_LINUX_BOOT_IF) +typedef struct ARMLinuxBootIfClass ARMLinuxBootIfClass; +DECLARE_CLASS_CHECKERS(ARMLinuxBootIfClass, ARM_LINUX_BOOT_IF, + TYPE_ARM_LINUX_BOOT_IF) #define ARM_LINUX_BOOT_IF(obj) \ INTERFACE_CHECK(ARMLinuxBootIf, (obj), TYPE_ARM_LINUX_BOOT_IF) typedef struct ARMLinuxBootIf ARMLinuxBootIf; -typedef struct ARMLinuxBootIfClass { +struct ARMLinuxBootIfClass { /*< private >*/ InterfaceClass parent_class; @@ -35,6 +34,6 @@ typedef struct ARMLinuxBootIfClass { * (or for a CPU which doesn't support TrustZone) */ void (*arm_linux_init)(ARMLinuxBootIf *obj, bool secure_boot); -} ARMLinuxBootIfClass; +}; #endif diff --git a/include/hw/arm/msf2-soc.h b/include/hw/arm/msf2-soc.h index c9cb214aa6729b56ac5c71b0bbe206225c0db87d..d4061846855bb6924fce58a6aafb7ed042925856 100644 --- a/include/hw/arm/msf2-soc.h +++ b/include/hw/arm/msf2-soc.h @@ -30,9 +30,10 @@ #include "hw/misc/msf2-sysreg.h" #include "hw/ssi/mss-spi.h" #include "hw/net/msf2-emac.h" +#include "qom/object.h" #define TYPE_MSF2_SOC "msf2-soc" -#define MSF2_SOC(obj) OBJECT_CHECK(MSF2State, (obj), TYPE_MSF2_SOC) +OBJECT_DECLARE_SIMPLE_TYPE(MSF2State, MSF2_SOC) #define MSF2_NUM_SPIS 2 #define MSF2_NUM_UARTS 2 @@ -44,7 +45,7 @@ */ #define MSF2_NUM_TIMERS 2 -typedef struct MSF2State { +struct MSF2State { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -64,6 +65,6 @@ typedef struct MSF2State { MSSTimerState timer; MSSSpiState spi[MSF2_NUM_SPIS]; MSF2EmacState emac; -} MSF2State; +}; #endif diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h new file mode 100644 index 0000000000000000000000000000000000000000..5469247e389fbe2e2b99f7049c0fa222b517e9bb --- /dev/null +++ b/include/hw/arm/npcm7xx.h @@ -0,0 +1,120 @@ +/* + * Nuvoton NPCM7xx SoC family. + * + * Copyright 2020 Google LLC + * + * 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. + */ +#ifndef NPCM7XX_H +#define NPCM7XX_H + +#include "hw/boards.h" +#include "hw/cpu/a9mpcore.h" +#include "hw/gpio/npcm7xx_gpio.h" +#include "hw/mem/npcm7xx_mc.h" +#include "hw/misc/npcm7xx_clk.h" +#include "hw/misc/npcm7xx_gcr.h" +#include "hw/misc/npcm7xx_rng.h" +#include "hw/nvram/npcm7xx_otp.h" +#include "hw/timer/npcm7xx_timer.h" +#include "hw/ssi/npcm7xx_fiu.h" +#include "hw/usb/hcd-ehci.h" +#include "hw/usb/hcd-ohci.h" +#include "target/arm/cpu.h" + +#define NPCM7XX_MAX_NUM_CPUS (2) + +/* The first half of the address space is reserved for DDR4 DRAM. */ +#define NPCM7XX_DRAM_BA (0x00000000) +#define NPCM7XX_DRAM_SZ (2 * GiB) + +/* Magic addresses for setting up direct kernel booting and SMP boot stubs. */ +#define NPCM7XX_LOADER_START (0x00000000) /* Start of SDRAM */ +#define NPCM7XX_SMP_LOADER_START (0xffff0000) /* Boot ROM */ +#define NPCM7XX_SMP_BOOTREG_ADDR (0xf080013c) /* GCR.SCRPAD */ +#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */ +#define NPCM7XX_BOARD_SETUP_ADDR (0xffff1000) /* Boot ROM */ + +typedef struct NPCM7xxMachine { + MachineState parent; +} NPCM7xxMachine; + +#define TYPE_NPCM7XX_MACHINE MACHINE_TYPE_NAME("npcm7xx") +#define NPCM7XX_MACHINE(obj) \ + OBJECT_CHECK(NPCM7xxMachine, (obj), TYPE_NPCM7XX_MACHINE) + +typedef struct NPCM7xxMachineClass { + MachineClass parent; + + const char *soc_type; +} NPCM7xxMachineClass; + +#define NPCM7XX_MACHINE_CLASS(klass) \ + OBJECT_CLASS_CHECK(NPCM7xxMachineClass, (klass), TYPE_NPCM7XX_MACHINE) +#define NPCM7XX_MACHINE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(NPCM7xxMachineClass, (obj), TYPE_NPCM7XX_MACHINE) + +typedef struct NPCM7xxState { + DeviceState parent; + + ARMCPU cpu[NPCM7XX_MAX_NUM_CPUS]; + A9MPPrivState a9mpcore; + + MemoryRegion sram; + MemoryRegion irom; + MemoryRegion ram3; + MemoryRegion *dram; + + NPCM7xxGCRState gcr; + NPCM7xxCLKState clk; + NPCM7xxTimerCtrlState tim[3]; + NPCM7xxOTPState key_storage; + NPCM7xxOTPState fuse_array; + NPCM7xxMCState mc; + NPCM7xxRNGState rng; + NPCM7xxGPIOState gpio[8]; + EHCISysBusState ehci; + OHCISysBusState ohci; + NPCM7xxFIUState fiu[2]; +} NPCM7xxState; + +#define TYPE_NPCM7XX "npcm7xx" +#define NPCM7XX(obj) OBJECT_CHECK(NPCM7xxState, (obj), TYPE_NPCM7XX) + +#define TYPE_NPCM730 "npcm730" +#define TYPE_NPCM750 "npcm750" + +typedef struct NPCM7xxClass { + DeviceClass parent; + + /* Bitmask of modules that are permanently disabled on this chip. */ + uint32_t disabled_modules; + /* Number of CPU cores enabled in this SoC class (may be 1 or 2). */ + uint32_t num_cpus; +} NPCM7xxClass; + +#define NPCM7XX_CLASS(klass) \ + OBJECT_CLASS_CHECK(NPCM7xxClass, (klass), TYPE_NPCM7XX) +#define NPCM7XX_GET_CLASS(obj) \ + OBJECT_GET_CLASS(NPCM7xxClass, (obj), TYPE_NPCM7XX) + +/** + * npcm7xx_load_kernel - Loads memory with everything needed to boot + * @machine - The machine containing the SoC to be booted. + * @soc - The SoC containing the CPU to be booted. + * + * This will set up the ARM boot info structure for the specific NPCM7xx + * derivative and call arm_load_kernel() to set up loading of the kernel, etc. + * into memory, if requested by the user. + */ +void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc); + +#endif /* NPCM7XX_H */ diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h index 0cb78aafea1aa43105ca34aefd5aee22d3cafa71..f8a6725b775da7d60757f45f8f7b619880e17236 100644 --- a/include/hw/arm/nrf51_soc.h +++ b/include/hw/arm/nrf51_soc.h @@ -17,14 +17,14 @@ #include "hw/gpio/nrf51_gpio.h" #include "hw/nvram/nrf51_nvm.h" #include "hw/timer/nrf51_timer.h" +#include "qom/object.h" #define TYPE_NRF51_SOC "nrf51-soc" -#define NRF51_SOC(obj) \ - OBJECT_CHECK(NRF51State, (obj), TYPE_NRF51_SOC) +OBJECT_DECLARE_SIMPLE_TYPE(NRF51State, NRF51_SOC) #define NRF51_NUM_TIMERS 3 -typedef struct NRF51State { +struct NRF51State { /*< private >*/ SysBusDevice parent_obj; @@ -50,6 +50,6 @@ typedef struct NRF51State { MemoryRegion container; -} NRF51State; +}; #endif diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h index 6be386d0e22e6bcdb21fce00c840ed799059e6eb..ff6a173f8a6ba41717f13c358775687296cbfc74 100644 --- a/include/hw/arm/omap.h +++ b/include/hw/arm/omap.h @@ -24,6 +24,7 @@ #include "hw/input/tsc2xxx.h" #include "target/arm/cpu-qom.h" #include "qemu/log.h" +#include "qom/object.h" # define OMAP_EMIFS_BASE 0x00000000 # define OMAP2_Q0_BASE 0x00000000 @@ -69,10 +70,10 @@ void omap_clk_reparent(omap_clk clk, omap_clk parent); /* omap_intc.c */ #define TYPE_OMAP_INTC "common-omap-intc" -#define OMAP_INTC(obj) \ - OBJECT_CHECK(omap_intr_handler, (obj), TYPE_OMAP_INTC) - typedef struct omap_intr_handler_s omap_intr_handler; +DECLARE_INSTANCE_CHECKER(omap_intr_handler, OMAP_INTC, + TYPE_OMAP_INTC) + /* * TODO: Ideally we should have a clock framework that @@ -93,9 +94,8 @@ void omap_intc_set_fclk(omap_intr_handler *intc, omap_clk clk); /* omap_i2c.c */ #define TYPE_OMAP_I2C "omap_i2c" -#define OMAP_I2C(obj) OBJECT_CHECK(OMAPI2CState, (obj), TYPE_OMAP_I2C) +OBJECT_DECLARE_SIMPLE_TYPE(OMAPI2CState, OMAP_I2C) -typedef struct OMAPI2CState OMAPI2CState; /* TODO: clock framework (see above) */ void omap_i2c_set_iclk(OMAPI2CState *i2c, omap_clk clk); @@ -103,12 +103,12 @@ void omap_i2c_set_fclk(OMAPI2CState *i2c, omap_clk clk); /* omap_gpio.c */ #define TYPE_OMAP1_GPIO "omap-gpio" -#define OMAP1_GPIO(obj) \ - OBJECT_CHECK(struct omap_gpif_s, (obj), TYPE_OMAP1_GPIO) +DECLARE_INSTANCE_CHECKER(struct omap_gpif_s, OMAP1_GPIO, + TYPE_OMAP1_GPIO) #define TYPE_OMAP2_GPIO "omap2-gpio" -#define OMAP2_GPIO(obj) \ - OBJECT_CHECK(struct omap2_gpif_s, (obj), TYPE_OMAP2_GPIO) +DECLARE_INSTANCE_CHECKER(struct omap2_gpif_s, OMAP2_GPIO, + TYPE_OMAP2_GPIO) typedef struct omap_gpif_s omap_gpif; typedef struct omap2_gpif_s omap2_gpif; diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h index f6dfb5c0cf0df19f22aca00ed54b63688850c9a2..1095504b86f33fd8455161615f9ed4502762f89e 100644 --- a/include/hw/arm/pxa.h +++ b/include/hw/arm/pxa.h @@ -13,6 +13,7 @@ #include "exec/memory.h" #include "target/arm/cpu-qom.h" #include "hw/pcmcia.h" +#include "qom/object.h" /* Interrupt numbers */ # define PXA2XX_PIC_SSP3 0 @@ -86,16 +87,19 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem, void pxa2xx_lcd_vsync_notifier(PXA2xxLCDState *s, qemu_irq handler); /* pxa2xx_mmci.c */ -typedef struct PXA2xxMMCIState PXA2xxMMCIState; +#define TYPE_PXA2XX_MMCI "pxa2xx-mmci" +OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxMMCIState, PXA2XX_MMCI) + PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem, hwaddr base, - BlockBackend *blk, qemu_irq irq, - qemu_irq rx_dma, qemu_irq tx_dma); + qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma); void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly, qemu_irq coverswitch); /* pxa2xx_pcmcia.c */ -typedef struct PXA2xxPCMCIAState PXA2xxPCMCIAState; +#define TYPE_PXA2XX_PCMCIA "pxa2xx-pcmcia" +OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxPCMCIAState, PXA2XX_PCMCIA) + PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, hwaddr base); int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card); @@ -120,8 +124,12 @@ PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base, qemu_irq irq, uint32_t page_size); I2CBus *pxa2xx_i2c_bus(PXA2xxI2CState *s); +#define TYPE_PXA2XX_I2C "pxa2xx_i2c" typedef struct PXA2xxI2SState PXA2xxI2SState; -typedef struct PXA2xxFIrState PXA2xxFIrState; +OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxI2CState, PXA2XX_I2C) + +#define TYPE_PXA2XX_FIR "pxa2xx-fir" +OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxFIrState, PXA2XX_FIR) typedef struct { ARMCPU *cpu; @@ -184,7 +192,6 @@ struct PXA2xxI2SState { }; # define PA_FMT "0x%08lx" -# define REG_FMT "0x" TARGET_FMT_plx PXA2xxState *pxa270_init(MemoryRegion *address_space, unsigned int sdram_size, const char *revision); diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h index 61b04a1bd4ab8d21dc79eeb5f695a1d78173a124..e0e6c8ce94a2848152a67be1a208a6a837c9b128 100644 --- a/include/hw/arm/raspi_platform.h +++ b/include/hw/arm/raspi_platform.h @@ -20,46 +20,80 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Various undocumented addresses and names come from Herman Hermitage's VC4 + * documentation: + * https://github.com/hermanhermitage/videocoreiv/wiki/MMIO-Register-map */ #ifndef HW_ARM_RASPI_PLATFORM_H #define HW_ARM_RASPI_PLATFORM_H #define MSYNC_OFFSET 0x0000 /* Multicore Sync Block */ -#define IC0_OFFSET 0x2000 +#define CCPT_OFFSET 0x1000 /* Compact Camera Port 2 TX */ +#define INTE_OFFSET 0x2000 /* VC Interrupt controller */ #define ST_OFFSET 0x3000 /* System Timer */ +#define TXP_OFFSET 0x4000 /* Transposer */ +#define JPEG_OFFSET 0x5000 #define MPHI_OFFSET 0x6000 /* Message-based Parallel Host Intf. */ #define DMA_OFFSET 0x7000 /* DMA controller, channels 0-14 */ -#define ARM_OFFSET 0xB000 /* BCM2708 ARM control block */ +#define ARBA_OFFSET 0x9000 +#define BRDG_OFFSET 0xa000 +#define ARM_OFFSET 0xB000 /* ARM control block */ #define ARMCTRL_OFFSET (ARM_OFFSET + 0x000) #define ARMCTRL_IC_OFFSET (ARM_OFFSET + 0x200) /* Interrupt controller */ -#define ARMCTRL_TIMER0_1_OFFSET (ARM_OFFSET + 0x400) /* Timer 0 and 1 */ +#define ARMCTRL_TIMER0_1_OFFSET (ARM_OFFSET + 0x400) /* Timer 0 and 1 (SP804) */ #define ARMCTRL_0_SBM_OFFSET (ARM_OFFSET + 0x800) /* User 0 (ARM) Semaphores * Doorbells & Mailboxes */ -#define CPRMAN_OFFSET 0x100000 /* Power Management, Watchdog */ -#define CM_OFFSET 0x101000 /* Clock Management */ -#define A2W_OFFSET 0x102000 /* Reset controller */ +#define PM_OFFSET 0x100000 /* Power Management */ +#define CPRMAN_OFFSET 0x101000 /* Clock Management */ #define AVS_OFFSET 0x103000 /* Audio Video Standard */ #define RNG_OFFSET 0x104000 #define GPIO_OFFSET 0x200000 -#define UART0_OFFSET 0x201000 -#define MMCI0_OFFSET 0x202000 -#define I2S_OFFSET 0x203000 -#define SPI0_OFFSET 0x204000 +#define UART0_OFFSET 0x201000 /* PL011 */ +#define MMCI0_OFFSET 0x202000 /* Legacy MMC */ +#define I2S_OFFSET 0x203000 /* PCM */ +#define SPI0_OFFSET 0x204000 /* SPI master */ #define BSC0_OFFSET 0x205000 /* BSC0 I2C/TWI */ +#define PIXV0_OFFSET 0x206000 +#define PIXV1_OFFSET 0x207000 +#define DPI_OFFSET 0x208000 +#define DSI0_OFFSET 0x209000 /* Display Serial Interface */ +#define PWM_OFFSET 0x20c000 +#define PERM_OFFSET 0x20d000 +#define TEC_OFFSET 0x20e000 #define OTP_OFFSET 0x20f000 +#define SLIM_OFFSET 0x210000 /* SLIMbus */ +#define CPG_OFFSET 0x211000 #define THERMAL_OFFSET 0x212000 -#define BSC_SL_OFFSET 0x214000 /* SPI slave */ +#define AVSP_OFFSET 0x213000 +#define BSC_SL_OFFSET 0x214000 /* SPI slave (bootrom) */ #define AUX_OFFSET 0x215000 /* AUX: UART1/SPI1/SPI2 */ #define EMMC1_OFFSET 0x300000 +#define EMMC2_OFFSET 0x340000 +#define HVS_OFFSET 0x400000 #define SMI_OFFSET 0x600000 +#define DSI1_OFFSET 0x700000 +#define UCAM_OFFSET 0x800000 +#define CMI_OFFSET 0x802000 #define BSC1_OFFSET 0x804000 /* BSC1 I2C/TWI */ #define BSC2_OFFSET 0x805000 /* BSC2 I2C/TWI */ +#define VECA_OFFSET 0x806000 +#define PIXV2_OFFSET 0x807000 +#define HDMI_OFFSET 0x808000 +#define HDCP_OFFSET 0x809000 +#define ARBR0_OFFSET 0x80a000 #define DBUS_OFFSET 0x900000 #define AVE0_OFFSET 0x910000 #define USB_OTG_OFFSET 0x980000 /* DTC_OTG USB controller */ +#define V3D_OFFSET 0xc00000 #define SDRAMC_OFFSET 0xe00000 +#define L2CC_OFFSET 0xe01000 /* Level 2 Cache controller */ +#define L1CC_OFFSET 0xe02000 /* Level 1 Cache controller */ +#define ARBR1_OFFSET 0xe04000 #define DMA15_OFFSET 0xE05000 /* DMA controller, channel 15 */ +#define DCRC_OFFSET 0xe07000 +#define AXIP_OFFSET 0xe08000 /* GPU interrupts */ #define INTERRUPT_TIMER0 0 diff --git a/include/hw/arm/sharpsl.h b/include/hw/arm/sharpsl.h index 89e168fbff39478e7f294031e9b737e3bc6a2391..e986b28c5273fe7f998bcfd9c4bf2b23f444f8f3 100644 --- a/include/hw/arm/sharpsl.h +++ b/include/hw/arm/sharpsl.h @@ -9,9 +9,6 @@ #include "exec/hwaddr.h" -#define zaurus_printf(format, ...) \ - fprintf(stderr, "%s: " format, __func__, ##__VA_ARGS__) - /* zaurus.c */ #define SL_PXA_PARAM_BASE 0xa0000a00 diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index ca4a4b1ad1ed7f1975382aa50ca172f4d21d2e7c..706be3c6d0a4f0b8fc4ecd6c16b2a2f642d7d89c 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -21,6 +21,7 @@ #include "hw/sysbus.h" #include "hw/pci/pci.h" +#include "qom/object.h" #define SMMU_PCI_BUS_MAX 256 #define SMMU_PCI_DEVFN_MAX 256 @@ -50,8 +51,15 @@ typedef struct SMMUTransTableInfo { uint64_t ttb; /* TT base address */ uint8_t tsz; /* input range, ie. 2^(64 -tsz)*/ uint8_t granule_sz; /* granule page shift */ + bool had; /* hierarchical attribute disable */ } SMMUTransTableInfo; +typedef struct SMMUTLBEntry { + IOMMUTLBEntry entry; + uint8_t level; + uint8_t granule; +} SMMUTLBEntry; + /* * Generic structure populated by derived SMMU devices * after decoding the configuration information and used as @@ -91,9 +99,11 @@ typedef struct SMMUPciBus { typedef struct SMMUIOTLBKey { uint64_t iova; uint16_t asid; + uint8_t tg; + uint8_t level; } SMMUIOTLBKey; -typedef struct SMMUState { +struct SMMUState { /* */ SysBusDevice dev; const char *mrtypename; @@ -107,9 +117,9 @@ typedef struct SMMUState { QLIST_HEAD(, SMMUDevice) devices_with_notifiers; uint8_t bus_num; PCIBus *primary_bus; -} SMMUState; +}; -typedef struct { +struct SMMUBaseClass { /* */ SysBusDeviceClass parent_class; @@ -117,14 +127,10 @@ typedef struct { DeviceRealize parent_realize; -} SMMUBaseClass; +}; #define TYPE_ARM_SMMU "arm-smmu" -#define ARM_SMMU(obj) OBJECT_CHECK(SMMUState, (obj), TYPE_ARM_SMMU) -#define ARM_SMMU_CLASS(klass) \ - OBJECT_CLASS_CHECK(SMMUBaseClass, (klass), TYPE_ARM_SMMU) -#define ARM_SMMU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_ARM_SMMU) +OBJECT_DECLARE_TYPE(SMMUState, SMMUBaseClass, ARM_SMMU) /* Return the SMMUPciBus handle associated to a PCI bus number */ SMMUPciBus *smmu_find_smmu_pcibus(SMMUState *s, uint8_t bus_num); @@ -140,7 +146,7 @@ static inline uint16_t smmu_get_sid(SMMUDevice *sdev) * pair, according to @cfg translation config */ int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm, - IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info); + SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info); /** * select_tt - compute which translation table shall be used according to @@ -153,9 +159,15 @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid); #define SMMU_IOTLB_MAX_SIZE 256 +SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, + SMMUTransTableInfo *tt, hwaddr iova); +void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *entry); +SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova, + uint8_t tg, uint8_t level); void smmu_iotlb_inv_all(SMMUState *s); void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid); -void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova); +void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova, + uint8_t tg, uint64_t num_pages, uint8_t ttl); /* Unmap the range of all the notifiers registered to any IOMMU mr */ void smmu_inv_notifiers_all(SMMUState *s); diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h index 36b2f4525398445b45a0abfe8ac3ea8697381468..c641e60735e06272fbdb8ce8840ca79fce117283 100644 --- a/include/hw/arm/smmuv3.h +++ b/include/hw/arm/smmuv3.h @@ -21,6 +21,7 @@ #include "hw/arm/smmu-common.h" #include "hw/registerfields.h" +#include "qom/object.h" #define TYPE_SMMUV3_IOMMU_MEMORY_REGION "smmuv3-iommu-memory-region" @@ -32,7 +33,7 @@ typedef struct SMMUQueue { uint8_t log2size; } SMMUQueue; -typedef struct SMMUv3State { +struct SMMUv3State { SMMUState smmu_state; uint32_t features; @@ -41,6 +42,7 @@ typedef struct SMMUv3State { uint32_t idr[6]; uint32_t iidr; + uint32_t aidr; uint32_t cr[3]; uint32_t cr0ack; uint32_t statusr; @@ -60,7 +62,7 @@ typedef struct SMMUv3State { qemu_irq irq[4]; QemuMutex mutex; -} SMMUv3State; +}; typedef enum { SMMU_IRQ_EVTQ, @@ -69,20 +71,16 @@ typedef enum { SMMU_IRQ_GERROR, } SMMUIrq; -typedef struct { +struct SMMUv3Class { /*< private >*/ SMMUBaseClass smmu_base_class; /*< public >*/ DeviceRealize parent_realize; DeviceReset parent_reset; -} SMMUv3Class; +}; #define TYPE_ARM_SMMUV3 "arm-smmuv3" -#define ARM_SMMUV3(obj) OBJECT_CHECK(SMMUv3State, (obj), TYPE_ARM_SMMUV3) -#define ARM_SMMUV3_CLASS(klass) \ - OBJECT_CLASS_CHECK(SMMUv3Class, (klass), TYPE_ARM_SMMUV3) -#define ARM_SMMUV3_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SMMUv3Class, (obj), TYPE_ARM_SMMUV3) +OBJECT_DECLARE_TYPE(SMMUv3State, SMMUv3Class, ARM_SMMUV3) #endif diff --git a/include/hw/arm/stm32f205_soc.h b/include/hw/arm/stm32f205_soc.h index 922a733f883d6a9c6dec53add437b913ec86c034..985ff63aa9e38d3fd0ba7f7da38cc498a78bba08 100644 --- a/include/hw/arm/stm32f205_soc.h +++ b/include/hw/arm/stm32f205_soc.h @@ -32,10 +32,10 @@ #include "hw/or-irq.h" #include "hw/ssi/stm32f2xx_spi.h" #include "hw/arm/armv7m.h" +#include "qom/object.h" #define TYPE_STM32F205_SOC "stm32f205-soc" -#define STM32F205_SOC(obj) \ - OBJECT_CHECK(STM32F205State, (obj), TYPE_STM32F205_SOC) +OBJECT_DECLARE_SIMPLE_TYPE(STM32F205State, STM32F205_SOC) #define STM_NUM_USARTS 6 #define STM_NUM_TIMERS 4 @@ -47,7 +47,7 @@ #define SRAM_BASE_ADDRESS 0x20000000 #define SRAM_SIZE (128 * 1024) -typedef struct STM32F205State { +struct STM32F205State { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -63,6 +63,6 @@ typedef struct STM32F205State { STM32F2XXSPIState spi[STM_NUM_SPIS]; qemu_or_irq *adc_irqs; -} STM32F205State; +}; #endif diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h index 1fe97f8c3a33d197f8052ec1206b07c5efe6c4a2..347105e709be87e9830144a60130f8ef55937d17 100644 --- a/include/hw/arm/stm32f405_soc.h +++ b/include/hw/arm/stm32f405_soc.h @@ -33,10 +33,10 @@ #include "hw/or-irq.h" #include "hw/ssi/stm32f2xx_spi.h" #include "hw/arm/armv7m.h" +#include "qom/object.h" #define TYPE_STM32F405_SOC "stm32f405-soc" -#define STM32F405_SOC(obj) \ - OBJECT_CHECK(STM32F405State, (obj), TYPE_STM32F405_SOC) +OBJECT_DECLARE_SIMPLE_TYPE(STM32F405State, STM32F405_SOC) #define STM_NUM_USARTS 7 #define STM_NUM_TIMERS 4 @@ -48,7 +48,7 @@ #define SRAM_BASE_ADDRESS 0x20000000 #define SRAM_SIZE (192 * 1024) -typedef struct STM32F405State { +struct STM32F405State { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -68,6 +68,6 @@ typedef struct STM32F405State { MemoryRegion sram; MemoryRegion flash; MemoryRegion flash_alias; -} STM32F405State; +}; #endif diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 31878ddc72234d227ff520e83ea9bd93fb646e81..aad6d698412a3e16f348cb6831c20a86cce36384 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -37,6 +37,7 @@ #include "hw/block/flash.h" #include "sysemu/kvm.h" #include "hw/intc/arm_gicv3_common.h" +#include "qom/object.h" #define NUM_GICV2M_SPIS 64 #define NUM_VIRTIO_TRANSPORTS 32 @@ -53,6 +54,9 @@ #define PPI(irq) ((irq) + 16) +/* See Linux kernel arch/arm64/include/asm/pvclock-abi.h */ +#define PVTIME_SIZE_PER_CPU 64 + enum { VIRT_FLASH, VIRT_MEM, @@ -80,6 +84,7 @@ enum { VIRT_PCDIMM_ACPI, VIRT_ACPI_GED, VIRT_NVDIMM_ACPI, + VIRT_PVTIME, VIRT_LOWMEMMAP_LAST, }; @@ -96,6 +101,12 @@ typedef enum VirtIOMMUType { VIRT_IOMMU_VIRTIO, } VirtIOMMUType; +typedef enum VirtMSIControllerType { + VIRT_MSI_CTRL_NONE, + VIRT_MSI_CTRL_GICV2M, + VIRT_MSI_CTRL_ITS, +} VirtMSIControllerType; + typedef enum VirtGICType { VIRT_GIC_VERSION_MAX, VIRT_GIC_VERSION_HOST, @@ -104,12 +115,7 @@ typedef enum VirtGICType { VIRT_GIC_VERSION_NOSEL, } VirtGICType; -typedef struct MemMapEntry { - hwaddr base; - hwaddr size; -} MemMapEntry; - -typedef struct { +struct VirtMachineClass { MachineClass parent; bool disallow_affinity_adjustment; bool no_its; @@ -119,9 +125,11 @@ typedef struct { bool no_highmem_ecam; bool no_ged; /* Machines < 4.2 has no support for ACPI GED device */ bool kvm_no_adjvtime; -} VirtMachineClass; + bool no_kvm_steal_time; + bool acpi_expose_flash; +}; -typedef struct { +struct VirtMachineState { MachineState parent; Notifier machine_done; DeviceState *platform_bus_dev; @@ -133,9 +141,11 @@ typedef struct { bool its; bool virt; bool ras; + bool mte; OnOffAuto acpi; VirtGICType gic_version; VirtIOMMUType iommu; + VirtMSIControllerType msi_controller; uint16_t virtio_iommu_bdf; struct arm_boot_info bootinfo; MemMapEntry *memmap; @@ -153,17 +163,12 @@ typedef struct { DeviceState *gic; DeviceState *acpi_dev; Notifier powerdown_notifier; -} VirtMachineState; +}; #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM) #define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt") -#define VIRT_MACHINE(obj) \ - OBJECT_CHECK(VirtMachineState, (obj), TYPE_VIRT_MACHINE) -#define VIRT_MACHINE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtMachineClass, obj, TYPE_VIRT_MACHINE) -#define VIRT_MACHINE_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtMachineClass, klass, TYPE_VIRT_MACHINE) +OBJECT_DECLARE_TYPE(VirtMachineState, VirtMachineClass, VIRT_MACHINE) void virt_acpi_setup(VirtMachineState *vms); bool virt_is_acpi_enabled(VirtMachineState *vms); diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 9c9f47ba9da60ace1b01bcc94bd74ee8009d8f7f..8ce8e63b56c8463dd0a90018486341250421979e 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -20,9 +20,10 @@ #include "hw/dma/xlnx-zdma.h" #include "hw/net/cadence_gem.h" #include "hw/rtc/xlnx-zynqmp-rtc.h" +#include "qom/object.h" #define TYPE_XLNX_VERSAL "xlnx-versal" -#define XLNX_VERSAL(obj) OBJECT_CHECK(Versal, (obj), TYPE_XLNX_VERSAL) +OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL) #define XLNX_VERSAL_NR_ACPUS 2 #define XLNX_VERSAL_NR_UARTS 2 @@ -31,7 +32,7 @@ #define XLNX_VERSAL_NR_SDS 2 #define XLNX_VERSAL_NR_IRQS 192 -typedef struct Versal { +struct Versal { /*< private >*/ SysBusDevice parent_obj; @@ -74,7 +75,7 @@ typedef struct Versal { MemoryRegion *mr_ddr; uint32_t psci_conduit; } cfg; -} Versal; +}; /* Memory-map and IRQ definitions. Copied a subset from * auto-generated files. */ diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index 53076fa29a759bb2103c58d2265e68cc4eb34ccf..567d0dba09b64a80e2098d8067af01ca809c53ef 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -32,10 +32,10 @@ #include "hw/rtc/xlnx-zynqmp-rtc.h" #include "hw/cpu/cluster.h" #include "target/arm/cpu.h" +#include "qom/object.h" #define TYPE_XLNX_ZYNQMP "xlnx,zynqmp" -#define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \ - TYPE_XLNX_ZYNQMP) +OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP) #define XLNX_ZYNQMP_NUM_APU_CPUS 4 #define XLNX_ZYNQMP_NUM_RPU_CPUS 2 @@ -73,7 +73,7 @@ #define XLNX_ZYNQMP_MAX_RAM_SIZE (XLNX_ZYNQMP_MAX_LOW_RAM_SIZE + \ XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE) -typedef struct XlnxZynqMPState { +struct XlnxZynqMPState { /*< private >*/ DeviceState parent_obj; @@ -112,6 +112,6 @@ typedef struct XlnxZynqMPState { bool virt; /* Has the RPU subsystem? */ bool has_rpu; -} XlnxZynqMPState; +}; #endif diff --git a/include/hw/audio/pcspk.h b/include/hw/audio/pcspk.h index 632cce9f68f4f023c5eefade78bf182c2dfcb294..950617958778abd7c0e26f966eaa78dd669c593b 100644 --- a/include/hw/audio/pcspk.h +++ b/include/hw/audio/pcspk.h @@ -27,21 +27,14 @@ #include "hw/isa/isa.h" #include "hw/qdev-properties.h" +#include "qapi/error.h" #define TYPE_PC_SPEAKER "isa-pcspk" -static inline ISADevice *pcspk_init(ISABus *bus, ISADevice *pit) +static inline void pcspk_init(ISADevice *isadev, ISABus *bus, ISADevice *pit) { - DeviceState *dev; - ISADevice *isadev; - - isadev = isa_create(bus, TYPE_PC_SPEAKER); - dev = DEVICE(isadev); - qdev_prop_set_uint32(dev, "iobase", 0x61); - object_property_set_link(OBJECT(dev), OBJECT(pit), "pit", NULL); - qdev_init_nofail(dev); - - return isadev; + object_property_set_link(OBJECT(isadev), "pit", OBJECT(pit), NULL); + isa_realize_and_unref(isadev, bus, &error_fatal); } #endif /* HW_PCSPK_H */ diff --git a/include/hw/audio/soundhw.h b/include/hw/audio/soundhw.h index c8eef82418468ef20ab31231c1ba017f4ffc3850..f09a297854afc78f5d9cd94e4091edcfd9efc125 100644 --- a/include/hw/audio/soundhw.h +++ b/include/hw/audio/soundhw.h @@ -6,6 +6,8 @@ void isa_register_soundhw(const char *name, const char *descr, void pci_register_soundhw(const char *name, const char *descr, int (*init_pci)(PCIBus *bus)); +void deprecated_register_soundhw(const char *name, const char *descr, + int isa, const char *typename); void soundhw_init(void); void select_soundhw(const char *optarg); diff --git a/include/hw/block/block.h b/include/hw/block/block.h index d7246f38628999189fb86a1f9fdf121deb468e9d..1e8b6253dd348f8ef212103c012190fe90effe36 100644 --- a/include/hw/block/block.h +++ b/include/hw/block/block.h @@ -18,9 +18,9 @@ typedef struct BlockConf { BlockBackend *blk; - uint16_t physical_block_size; - uint16_t logical_block_size; - uint16_t min_io_size; + uint32_t physical_block_size; + uint32_t logical_block_size; + uint32_t min_io_size; uint32_t opt_io_size; int32_t bootindex; uint32_t discard_granularity; @@ -51,9 +51,9 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) _conf.logical_block_size), \ DEFINE_PROP_BLOCKSIZE("physical_block_size", _state, \ _conf.physical_block_size), \ - DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0), \ - DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0), \ - DEFINE_PROP_UINT32("discard_granularity", _state, \ + DEFINE_PROP_SIZE32("min_io_size", _state, _conf.min_io_size, 0), \ + DEFINE_PROP_SIZE32("opt_io_size", _state, _conf.opt_io_size, 0), \ + DEFINE_PROP_SIZE32("discard_granularity", _state, \ _conf.discard_granularity, -1), \ DEFINE_PROP_ON_OFF_AUTO("write-cache", _state, _conf.wce, \ ON_OFF_AUTO_AUTO), \ @@ -87,7 +87,7 @@ bool blk_check_size_and_read_all(BlockBackend *blk, void *buf, hwaddr size, bool blkconf_geometry(BlockConf *conf, int *trans, unsigned cyls_max, unsigned heads_max, unsigned secs_max, Error **errp); -void blkconf_blocksizes(BlockConf *conf); +bool blkconf_blocksizes(BlockConf *conf, Error **errp); bool blkconf_apply_backend_options(BlockConf *conf, bool readonly, bool resizable, Error **errp); diff --git a/include/hw/block/fdc.h b/include/hw/block/fdc.h index c15ff4c62315685695aacdc21f2597aeec554eec..1ecca7cac7f0ce7ae54b5c49d69b9e193dc6f04b 100644 --- a/include/hw/block/fdc.h +++ b/include/hw/block/fdc.h @@ -9,14 +9,13 @@ #define TYPE_ISA_FDC "isa-fdc" -ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds); +void isa_fdc_init_drives(ISADevice *fdc, DriveInfo **fds); void fdctrl_init_sysbus(qemu_irq irq, int dma_chann, hwaddr mmio_base, DriveInfo **fds); void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base, DriveInfo **fds, qemu_irq *fdc_tc); FloppyDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i); -void isa_fdc_get_drive_max_chs(FloppyDriveType type, - uint8_t *maxc, uint8_t *maxh, uint8_t *maxs); +int cmos_get_fd_drive_type(FloppyDriveType fd0); #endif diff --git a/include/hw/block/flash.h b/include/hw/block/flash.h index 2136a2d5e4cd2bfde657f2dddcd3c96f17dea632..7dde0adcee78c160a4a2b94e7d551a09132ef240 100644 --- a/include/hw/block/flash.h +++ b/include/hw/block/flash.h @@ -4,14 +4,13 @@ /* NOR flash devices */ #include "exec/hwaddr.h" +#include "qom/object.h" /* pflash_cfi01.c */ #define TYPE_PFLASH_CFI01 "cfi.pflash01" -#define PFLASH_CFI01(obj) \ - OBJECT_CHECK(PFlashCFI01, (obj), TYPE_PFLASH_CFI01) +OBJECT_DECLARE_SIMPLE_TYPE(PFlashCFI01, PFLASH_CFI01) -typedef struct PFlashCFI01 PFlashCFI01; PFlashCFI01 *pflash_cfi01_register(hwaddr base, const char *name, @@ -29,10 +28,8 @@ void pflash_cfi01_legacy_drive(PFlashCFI01 *dev, DriveInfo *dinfo); /* pflash_cfi02.c */ #define TYPE_PFLASH_CFI02 "cfi.pflash02" -#define PFLASH_CFI02(obj) \ - OBJECT_CHECK(PFlashCFI02, (obj), TYPE_PFLASH_CFI02) +OBJECT_DECLARE_SIMPLE_TYPE(PFlashCFI02, PFLASH_CFI02) -typedef struct PFlashCFI02 PFlashCFI02; PFlashCFI02 *pflash_cfi02_register(hwaddr base, const char *name, diff --git a/include/hw/block/swim.h b/include/hw/block/swim.h index 6add3499d068fafab1cad4bbeed806c30995822c..5a49029543bfd8195c2fea9f93fbb7ccb83a3625 100644 --- a/include/hw/block/swim.h +++ b/include/hw/block/swim.h @@ -13,15 +13,14 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" +#include "qom/object.h" #define SWIM_MAX_FD 2 -typedef struct SWIMDrive SWIMDrive; -typedef struct SWIMBus SWIMBus; typedef struct SWIMCtrl SWIMCtrl; #define TYPE_SWIM_DRIVE "swim-drive" -#define SWIM_DRIVE(obj) OBJECT_CHECK(SWIMDrive, (obj), TYPE_SWIM_DRIVE) +OBJECT_DECLARE_SIMPLE_TYPE(SWIMDrive, SWIM_DRIVE) struct SWIMDrive { DeviceState qdev; @@ -30,7 +29,7 @@ struct SWIMDrive { }; #define TYPE_SWIM_BUS "swim-bus" -#define SWIM_BUS(obj) OBJECT_CHECK(SWIMBus, (obj), TYPE_SWIM_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(SWIMBus, SWIM_BUS) struct SWIMBus { BusState bus; @@ -67,10 +66,10 @@ struct SWIMCtrl { }; #define TYPE_SWIM "swim" -#define SWIM(obj) OBJECT_CHECK(SWIM, (obj), TYPE_SWIM) +OBJECT_DECLARE_SIMPLE_TYPE(Swim, SWIM) -typedef struct SWIM { +struct Swim { SysBusDevice parent_obj; SWIMCtrl ctrl; -} SWIM; +}; #endif diff --git a/include/hw/boards.h b/include/hw/boards.h index 18815d9be24f1e81149744a03d29582950a942a3..a49e3a6b44816a63af432ff5c7d73f355b9fc7b7 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -21,12 +21,7 @@ #define TYPE_MACHINE "machine" #undef MACHINE /* BSD defines it and QEMU does not use it */ -#define MACHINE(obj) \ - OBJECT_CHECK(MachineState, (obj), TYPE_MACHINE) -#define MACHINE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(MachineClass, (obj), TYPE_MACHINE) -#define MACHINE_CLASS(klass) \ - OBJECT_CLASS_CHECK(MachineClass, (klass), TYPE_MACHINE) +OBJECT_DECLARE_TYPE(MachineState, MachineClass, MACHINE) extern MachineState *current_machine; @@ -173,7 +168,6 @@ struct MachineClass { void (*init)(MachineState *state); void (*reset)(MachineState *state); void (*wakeup)(MachineState *state); - void (*hot_add_cpu)(MachineState *state, const int64_t id, Error **errp); int (*kvm_type)(MachineState *machine, const char *arg); void (*smp_parse)(MachineState *ms, QemuOpts *opts); @@ -207,8 +201,7 @@ struct MachineClass { const char **valid_cpu_types; strList *allowed_dynamic_sysbus_devices; bool auto_enable_numa_with_memhp; - void (*numa_auto_assign_ram)(MachineClass *mc, NodeInfo *nodes, - int nb_nodes, ram_addr_t size); + bool auto_enable_numa_with_memdev; bool ignore_boot_device_suffixes; bool smbus_no_migration_support; bool nvdimm_supported; @@ -275,7 +268,6 @@ struct MachineState { char *firmware; bool iommu; bool suppress_vmdesc; - bool enforce_config_section; bool enable_graphics; char *memory_encryption; char *ram_memdev_id; @@ -318,6 +310,9 @@ struct MachineState { } \ type_init(machine_initfn##_register_types) +extern GlobalProperty hw_compat_5_1[]; +extern const size_t hw_compat_5_1_len; + extern GlobalProperty hw_compat_5_0[]; extern const size_t hw_compat_5_0_len; diff --git a/include/hw/char/avr_usart.h b/include/hw/char/avr_usart.h new file mode 100644 index 0000000000000000000000000000000000000000..bb57532403674f011f91ba5688d37476c22fce25 --- /dev/null +++ b/include/hw/char/avr_usart.h @@ -0,0 +1,93 @@ +/* + * AVR USART + * + * Copyright (c) 2018 University of Kent + * Author: Sarah Harris + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * + */ + +#ifndef HW_CHAR_AVR_USART_H +#define HW_CHAR_AVR_USART_H + +#include "hw/sysbus.h" +#include "chardev/char-fe.h" +#include "hw/hw.h" +#include "qom/object.h" + +/* Offsets of registers. */ +#define USART_DR 0x06 +#define USART_CSRA 0x00 +#define USART_CSRB 0x01 +#define USART_CSRC 0x02 +#define USART_BRRH 0x05 +#define USART_BRRL 0x04 + +/* Relevant bits in regiters. */ +#define USART_CSRA_RXC (1 << 7) +#define USART_CSRA_TXC (1 << 6) +#define USART_CSRA_DRE (1 << 5) +#define USART_CSRA_MPCM (1 << 0) + +#define USART_CSRB_RXCIE (1 << 7) +#define USART_CSRB_TXCIE (1 << 6) +#define USART_CSRB_DREIE (1 << 5) +#define USART_CSRB_RXEN (1 << 4) +#define USART_CSRB_TXEN (1 << 3) +#define USART_CSRB_CSZ2 (1 << 2) +#define USART_CSRB_RXB8 (1 << 1) +#define USART_CSRB_TXB8 (1 << 0) + +#define USART_CSRC_MSEL1 (1 << 7) +#define USART_CSRC_MSEL0 (1 << 6) +#define USART_CSRC_PM1 (1 << 5) +#define USART_CSRC_PM0 (1 << 4) +#define USART_CSRC_CSZ1 (1 << 2) +#define USART_CSRC_CSZ0 (1 << 1) + +#define TYPE_AVR_USART "avr-usart" +OBJECT_DECLARE_SIMPLE_TYPE(AVRUsartState, AVR_USART) + +struct AVRUsartState { + /* */ + SysBusDevice parent_obj; + + /* */ + MemoryRegion mmio; + + CharBackend chr; + + bool enabled; + + uint8_t data; + bool data_valid; + uint8_t char_mask; + /* Control and Status Registers */ + uint8_t csra; + uint8_t csrb; + uint8_t csrc; + /* Baud Rate Registers (low/high byte) */ + uint8_t brrh; + uint8_t brrl; + + /* Receive Complete */ + qemu_irq rxc_irq; + /* Transmit Complete */ + qemu_irq txc_irq; + /* Data Register Empty */ + qemu_irq dre_irq; +}; + +#endif /* HW_CHAR_AVR_USART_H */ diff --git a/include/hw/char/bcm2835_aux.h b/include/hw/char/bcm2835_aux.h index 934acf9c81392127d263235d98810f422b67a294..9e081793a082fcef988a1a2f6d617c1d4c2803f7 100644 --- a/include/hw/char/bcm2835_aux.h +++ b/include/hw/char/bcm2835_aux.h @@ -11,13 +11,14 @@ #include "hw/sysbus.h" #include "chardev/char-fe.h" +#include "qom/object.h" #define TYPE_BCM2835_AUX "bcm2835-aux" -#define BCM2835_AUX(obj) OBJECT_CHECK(BCM2835AuxState, (obj), TYPE_BCM2835_AUX) +OBJECT_DECLARE_SIMPLE_TYPE(BCM2835AuxState, BCM2835_AUX) #define BCM2835_AUX_RX_FIFO_LEN 8 -typedef struct { +struct BCM2835AuxState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -29,6 +30,6 @@ typedef struct { uint8_t read_fifo[BCM2835_AUX_RX_FIFO_LEN]; uint8_t read_pos, read_count; uint8_t ier, iir; -} BCM2835AuxState; +}; #endif diff --git a/include/hw/char/cadence_uart.h b/include/hw/char/cadence_uart.h index 2a179a572fc91967e9a0a44c00dc914f1aca47bb..e7f7cd84683ed475f8363242aa9e158ef3b6d42f 100644 --- a/include/hw/char/cadence_uart.h +++ b/include/hw/char/cadence_uart.h @@ -22,7 +22,9 @@ #include "hw/qdev-properties.h" #include "hw/sysbus.h" #include "chardev/char-fe.h" +#include "qapi/error.h" #include "qemu/timer.h" +#include "qom/object.h" #define CADENCE_UART_RX_FIFO_SIZE 16 #define CADENCE_UART_TX_FIFO_SIZE 16 @@ -30,10 +32,9 @@ #define CADENCE_UART_R_MAX (0x48/4) #define TYPE_CADENCE_UART "cadence_uart" -#define CADENCE_UART(obj) OBJECT_CHECK(CadenceUARTState, (obj), \ - TYPE_CADENCE_UART) +OBJECT_DECLARE_SIMPLE_TYPE(CadenceUARTState, CADENCE_UART) -typedef struct { +struct CadenceUARTState { /*< private >*/ SysBusDevice parent_obj; @@ -50,23 +51,6 @@ typedef struct { qemu_irq irq; QEMUTimer *fifo_trigger_handle; Clock *refclk; -} CadenceUARTState; - -static inline DeviceState *cadence_uart_create(hwaddr addr, - qemu_irq irq, - Chardev *chr) -{ - DeviceState *dev; - SysBusDevice *s; - - dev = qdev_create(NULL, TYPE_CADENCE_UART); - s = SYS_BUS_DEVICE(dev); - qdev_prop_set_chr(dev, "chardev", chr); - qdev_init_nofail(dev); - sysbus_mmio_map(s, 0, addr); - sysbus_connect_irq(s, 0, irq); - - return dev; -} +}; #endif diff --git a/include/hw/char/cmsdk-apb-uart.h b/include/hw/char/cmsdk-apb-uart.h index 3c1b53db4ec931949d71243ce12618405df7a509..9daff0eeee3411d62a2044412d59402ae46332c7 100644 --- a/include/hw/char/cmsdk-apb-uart.h +++ b/include/hw/char/cmsdk-apb-uart.h @@ -15,12 +15,12 @@ #include "hw/qdev-properties.h" #include "hw/sysbus.h" #include "chardev/char-fe.h" +#include "qom/object.h" #define TYPE_CMSDK_APB_UART "cmsdk-apb-uart" -#define CMSDK_APB_UART(obj) OBJECT_CHECK(CMSDKAPBUART, (obj), \ - TYPE_CMSDK_APB_UART) +OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBUART, CMSDK_APB_UART) -typedef struct { +struct CMSDKAPBUART { /*< private >*/ SysBusDevice parent_obj; @@ -42,7 +42,7 @@ typedef struct { /* This UART has no FIFO, only a 1-character buffer for each of Tx and Rx */ uint8_t txbuf; uint8_t rxbuf; -} CMSDKAPBUART; +}; /** * cmsdk_apb_uart_create - convenience function to create TYPE_CMSDK_APB_UART @@ -62,11 +62,11 @@ static inline DeviceState *cmsdk_apb_uart_create(hwaddr addr, DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, TYPE_CMSDK_APB_UART); + dev = qdev_new(TYPE_CMSDK_APB_UART); s = SYS_BUS_DEVICE(dev); qdev_prop_set_chr(dev, "chardev", chr); qdev_prop_set_uint32(dev, "pclk-frq", pclk_frq); - qdev_init_nofail(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, addr); sysbus_connect_irq(s, 0, txint); sysbus_connect_irq(s, 1, rxint); diff --git a/include/hw/char/digic-uart.h b/include/hw/char/digic-uart.h index de9a3e3551b733136d3cf0d0de45e45255bb8638..f710a1a099eb09db19cc65213950d17fb88c8bcd 100644 --- a/include/hw/char/digic-uart.h +++ b/include/hw/char/digic-uart.h @@ -20,10 +20,10 @@ #include "hw/sysbus.h" #include "chardev/char-fe.h" +#include "qom/object.h" #define TYPE_DIGIC_UART "digic-uart" -#define DIGIC_UART(obj) \ - OBJECT_CHECK(DigicUartState, (obj), TYPE_DIGIC_UART) +OBJECT_DECLARE_SIMPLE_TYPE(DigicUartState, DIGIC_UART) enum { R_TX = 0x00, @@ -32,7 +32,7 @@ enum { R_MAX }; -typedef struct DigicUartState { +struct DigicUartState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -42,6 +42,6 @@ typedef struct DigicUartState { uint32_t reg_rx; uint32_t reg_st; -} DigicUartState; +}; #endif /* HW_CHAR_DIGIC_UART_H */ diff --git a/include/hw/char/escc.h b/include/hw/char/escc.h index 794b6534842ecd31bb3b645ef6675b6388787f13..7e9482dee2be4f8dfefad5442597cd8c27c07fc7 100644 --- a/include/hw/char/escc.h +++ b/include/hw/char/escc.h @@ -5,12 +5,13 @@ #include "chardev/char-serial.h" #include "hw/sysbus.h" #include "ui/input.h" +#include "qom/object.h" /* escc.c */ #define TYPE_ESCC "escc" #define ESCC_SIZE 4 -#define ESCC(obj) OBJECT_CHECK(ESCCState, (obj), TYPE_ESCC) +OBJECT_DECLARE_SIMPLE_TYPE(ESCCState, ESCC) typedef enum { escc_chn_a, escc_chn_b, @@ -46,7 +47,7 @@ typedef struct ESCCChannelState { QemuInputHandlerState *hs; } ESCCChannelState; -typedef struct ESCCState { +struct ESCCState { SysBusDevice parent_obj; struct ESCCChannelState chn[2]; @@ -55,6 +56,6 @@ typedef struct ESCCState { MemoryRegion mmio; uint32_t disabled; uint32_t frequency; -} ESCCState; +}; #endif diff --git a/include/hw/char/ibex_uart.h b/include/hw/char/ibex_uart.h new file mode 100644 index 0000000000000000000000000000000000000000..03d19e3f6f977c49d4b5ee8f71253616f22508f3 --- /dev/null +++ b/include/hw/char/ibex_uart.h @@ -0,0 +1,107 @@ +/* + * QEMU lowRISC Ibex UART device + * + * Copyright (c) 2020 Western Digital + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_IBEX_UART_H +#define HW_IBEX_UART_H + +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "chardev/char-fe.h" +#include "qemu/timer.h" +#include "qom/object.h" + +REG32(INTR_STATE, 0x00) + FIELD(INTR_STATE, TX_WATERMARK, 0, 1) + FIELD(INTR_STATE, RX_WATERMARK, 1, 1) + FIELD(INTR_STATE, TX_EMPTY, 2, 1) + FIELD(INTR_STATE, RX_OVERFLOW, 3, 1) +REG32(INTR_ENABLE, 0x04) +REG32(INTR_TEST, 0x08) +REG32(CTRL, 0x0C) + FIELD(CTRL, TX_ENABLE, 0, 1) + FIELD(CTRL, RX_ENABLE, 1, 1) + FIELD(CTRL, NF, 2, 1) + FIELD(CTRL, SLPBK, 4, 1) + FIELD(CTRL, LLPBK, 5, 1) + FIELD(CTRL, PARITY_EN, 6, 1) + FIELD(CTRL, PARITY_ODD, 7, 1) + FIELD(CTRL, RXBLVL, 8, 2) + FIELD(CTRL, NCO, 16, 16) +REG32(STATUS, 0x10) + FIELD(STATUS, TXFULL, 0, 1) + FIELD(STATUS, RXFULL, 1, 1) + FIELD(STATUS, TXEMPTY, 2, 1) + FIELD(STATUS, RXIDLE, 4, 1) + FIELD(STATUS, RXEMPTY, 5, 1) +REG32(RDATA, 0x14) +REG32(WDATA, 0x18) +REG32(FIFO_CTRL, 0x1c) + FIELD(FIFO_CTRL, RXRST, 0, 1) + FIELD(FIFO_CTRL, TXRST, 1, 1) + FIELD(FIFO_CTRL, RXILVL, 2, 3) + FIELD(FIFO_CTRL, TXILVL, 5, 2) +REG32(FIFO_STATUS, 0x20) +REG32(OVRD, 0x24) +REG32(VAL, 0x28) +REG32(TIMEOUT_CTRL, 0x2c) + +#define IBEX_UART_TX_FIFO_SIZE 16 +#define IBEX_UART_CLOCK 50000000 /* 50MHz clock */ + +#define TYPE_IBEX_UART "ibex-uart" +OBJECT_DECLARE_SIMPLE_TYPE(IbexUartState, IBEX_UART) + +struct IbexUartState { + /* */ + SysBusDevice parent_obj; + + /* */ + MemoryRegion mmio; + + uint8_t tx_fifo[IBEX_UART_TX_FIFO_SIZE]; + uint32_t tx_level; + + QEMUTimer *fifo_trigger_handle; + uint64_t char_tx_time; + + uint32_t uart_intr_state; + uint32_t uart_intr_enable; + uint32_t uart_ctrl; + uint32_t uart_status; + uint32_t uart_rdata; + uint32_t uart_fifo_ctrl; + uint32_t uart_fifo_status; + uint32_t uart_ovrd; + uint32_t uart_val; + uint32_t uart_timeout_ctrl; + + Clock *f_clk; + + CharBackend chr; + qemu_irq tx_watermark; + qemu_irq rx_watermark; + qemu_irq tx_empty; + qemu_irq rx_overflow; +}; +#endif /* HW_IBEX_UART_H */ diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h index c8b74284f87ff642b8e6e4328f4f3f87c562e83e..91c9894ad551e45e621ee84f0165c2003a4e7cb1 100644 --- a/include/hw/char/imx_serial.h +++ b/include/hw/char/imx_serial.h @@ -20,9 +20,10 @@ #include "hw/sysbus.h" #include "chardev/char-fe.h" +#include "qom/object.h" #define TYPE_IMX_SERIAL "imx.serial" -#define IMX_SERIAL(obj) OBJECT_CHECK(IMXSerialState, (obj), TYPE_IMX_SERIAL) +OBJECT_DECLARE_SIMPLE_TYPE(IMXSerialState, IMX_SERIAL) #define URXD_CHARRDY (1<<15) /* character read is valid */ #define URXD_ERR (1<<14) /* Character has error */ @@ -76,7 +77,7 @@ #define UTS1_TXFULL (1<<4) #define UTS1_RXFULL (1<<3) -typedef struct IMXSerialState { +struct IMXSerialState { /*< private >*/ SysBusDevice parent_obj; @@ -103,6 +104,6 @@ typedef struct IMXSerialState { qemu_irq irq; CharBackend chr; -} IMXSerialState; +}; #endif diff --git a/include/hw/char/mchp_pfsoc_mmuart.h b/include/hw/char/mchp_pfsoc_mmuart.h new file mode 100644 index 0000000000000000000000000000000000000000..f61990215f08654441ea041f243b98bf4c6e8f66 --- /dev/null +++ b/include/hw/char/mchp_pfsoc_mmuart.h @@ -0,0 +1,61 @@ +/* + * Microchip PolarFire SoC MMUART emulation + * + * Copyright (c) 2020 Wind River Systems, Inc. + * + * Author: + * Bin Meng + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_MCHP_PFSOC_MMUART_H +#define HW_MCHP_PFSOC_MMUART_H + +#include "hw/char/serial.h" + +#define MCHP_PFSOC_MMUART_REG_SIZE 52 + +typedef struct MchpPfSoCMMUartState { + MemoryRegion iomem; + hwaddr base; + qemu_irq irq; + + SerialMM *serial; + + uint32_t reg[MCHP_PFSOC_MMUART_REG_SIZE / sizeof(uint32_t)]; +} MchpPfSoCMMUartState; + +/** + * mchp_pfsoc_mmuart_create - Create a Microchip PolarFire SoC MMUART + * + * This is a helper routine for board to create a MMUART device that is + * compatible with Microchip PolarFire SoC. + * + * @sysmem: system memory region to map + * @base: base address of the MMUART registers + * @irq: IRQ number of the MMUART device + * @chr: character device to associate to + * + * @return: a pointer to the device specific control structure + */ +MchpPfSoCMMUartState *mchp_pfsoc_mmuart_create(MemoryRegion *sysmem, + hwaddr base, qemu_irq irq, Chardev *chr); + +#endif /* HW_MCHP_PFSOC_MMUART_H */ diff --git a/include/hw/char/nrf51_uart.h b/include/hw/char/nrf51_uart.h index eb1c15b490b8c34f8450052762e143825707e204..561b6383c4082bf722a8a24e1f74b9feccc54494 100644 --- a/include/hw/char/nrf51_uart.h +++ b/include/hw/char/nrf51_uart.h @@ -14,12 +14,13 @@ #include "hw/sysbus.h" #include "chardev/char-fe.h" #include "hw/registerfields.h" +#include "qom/object.h" #define UART_FIFO_LENGTH 6 #define UART_SIZE 0x1000 #define TYPE_NRF51_UART "nrf51_soc.uart" -#define NRF51_UART(obj) OBJECT_CHECK(NRF51UARTState, (obj), TYPE_NRF51_UART) +OBJECT_DECLARE_SIMPLE_TYPE(NRF51UARTState, NRF51_UART) REG32(UART_STARTRX, 0x000) REG32(UART_STOPRX, 0x004) @@ -54,7 +55,7 @@ REG32(UART_TXD, 0x51C) REG32(UART_BAUDRATE, 0x524) REG32(UART_CONFIG, 0x56C) -typedef struct NRF51UARTState { +struct NRF51UARTState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -72,6 +73,6 @@ typedef struct NRF51UARTState { bool tx_started; bool pending_tx_byte; bool enabled; -} NRF51UARTState; +}; #endif diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h index 14187165c613ff5743c6416099429ab3021ce23e..33e5e5317b82caaf39078a10b821bd9d04a5d17e 100644 --- a/include/hw/char/pl011.h +++ b/include/hw/char/pl011.h @@ -18,14 +18,16 @@ #include "hw/qdev-properties.h" #include "hw/sysbus.h" #include "chardev/char-fe.h" +#include "qapi/error.h" +#include "qom/object.h" #define TYPE_PL011 "pl011" -#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011) +OBJECT_DECLARE_SIMPLE_TYPE(PL011State, PL011) /* This shares the same struct (and cast macro) as the base pl011 device */ #define TYPE_PL011_LUMINARY "pl011_luminary" -typedef struct PL011State { +struct PL011State { SysBusDevice parent_obj; MemoryRegion iomem; @@ -47,8 +49,9 @@ typedef struct PL011State { int read_trigger; CharBackend chr; qemu_irq irq[6]; + Clock *clk; const unsigned char *id; -} PL011State; +}; static inline DeviceState *pl011_create(hwaddr addr, qemu_irq irq, @@ -57,10 +60,10 @@ static inline DeviceState *pl011_create(hwaddr addr, DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, "pl011"); + dev = qdev_new("pl011"); s = SYS_BUS_DEVICE(dev); qdev_prop_set_chr(dev, "chardev", chr); - qdev_init_nofail(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, addr); sysbus_connect_irq(s, 0, irq); @@ -74,10 +77,10 @@ static inline DeviceState *pl011_luminary_create(hwaddr addr, DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, "pl011_luminary"); + dev = qdev_new("pl011_luminary"); s = SYS_BUS_DEVICE(dev); qdev_prop_set_chr(dev, "chardev", chr); - qdev_init_nofail(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, addr); sysbus_connect_irq(s, 0, irq); diff --git a/include/hw/char/renesas_sci.h b/include/hw/char/renesas_sci.h new file mode 100644 index 0000000000000000000000000000000000000000..a4764e3eee3a936315ec0a534371e0070a299243 --- /dev/null +++ b/include/hw/char/renesas_sci.h @@ -0,0 +1,54 @@ +/* + * Renesas Serial Communication Interface + * + * Copyright (c) 2018 Yoshinori Sato + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_CHAR_RENESAS_SCI_H +#define HW_CHAR_RENESAS_SCI_H + +#include "chardev/char-fe.h" +#include "hw/sysbus.h" +#include "qom/object.h" + +#define TYPE_RENESAS_SCI "renesas-sci" +typedef struct RSCIState RSCIState; +DECLARE_INSTANCE_CHECKER(RSCIState, RSCI, + TYPE_RENESAS_SCI) + +enum { + ERI = 0, + RXI = 1, + TXI = 2, + TEI = 3, + SCI_NR_IRQ = 4 +}; + +struct RSCIState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + MemoryRegion memory; + QEMUTimer timer; + CharBackend chr; + qemu_irq irq[SCI_NR_IRQ]; + + uint8_t smr; + uint8_t brr; + uint8_t scr; + uint8_t tdr; + uint8_t ssr; + uint8_t rdr; + uint8_t scmr; + uint8_t semr; + + uint8_t read_ssr; + int64_t trtime; + int64_t rx_next; + uint64_t input_freq; +}; + +#endif diff --git a/include/hw/riscv/riscv_htif.h b/include/hw/char/riscv_htif.h similarity index 100% rename from include/hw/riscv/riscv_htif.h rename to include/hw/char/riscv_htif.h diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h index 535fa23a2b847f401a94c12dde49fbd62beed3ba..8ba7eca3d6725267ad96d7a9ded61ff48170c3fd 100644 --- a/include/hw/char/serial.h +++ b/include/hw/char/serial.h @@ -31,10 +31,11 @@ #include "qemu/fifo8.h" #include "chardev/char.h" #include "hw/sysbus.h" +#include "qom/object.h" #define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */ -typedef struct SerialState { +struct SerialState { DeviceState parent; uint16_t divider; @@ -60,7 +61,7 @@ typedef struct SerialState { uint32_t baudbase; uint32_t tsr_retry; guint watch_tag; - uint32_t wakeup; + bool wakeup; /* Time when the last byte was successfully sent out of the tsr */ uint64_t last_xmit_ts; @@ -77,22 +78,17 @@ typedef struct SerialState { QEMUTimer *modem_status_poll; MemoryRegion io; -} SerialState; +}; +typedef struct SerialState SerialState; -typedef struct SerialMM { +struct SerialMM { SysBusDevice parent; SerialState serial; uint8_t regshift; uint8_t endianness; -} SerialMM; - -typedef struct SerialIO { - SysBusDevice parent; - - SerialState serial; -} SerialIO; +}; extern const VMStateDescription vmstate_serial; extern const MemoryRegionOps serial_io_ops; @@ -100,13 +96,10 @@ extern const MemoryRegionOps serial_io_ops; void serial_set_frequency(SerialState *s, uint32_t frequency); #define TYPE_SERIAL "serial" -#define SERIAL(s) OBJECT_CHECK(SerialState, (s), TYPE_SERIAL) +OBJECT_DECLARE_SIMPLE_TYPE(SerialState, SERIAL) #define TYPE_SERIAL_MM "serial-mm" -#define SERIAL_MM(s) OBJECT_CHECK(SerialMM, (s), TYPE_SERIAL_MM) - -#define TYPE_SERIAL_IO "serial-io" -#define SERIAL_IO(s) OBJECT_CHECK(SerialIO, (s), TYPE_SERIAL_IO) +OBJECT_DECLARE_SIMPLE_TYPE(SerialMM, SERIAL_MM) SerialMM *serial_mm_init(MemoryRegion *address_space, hwaddr base, int regshift, diff --git a/include/hw/riscv/sifive_uart.h b/include/hw/char/sifive_uart.h similarity index 91% rename from include/hw/riscv/sifive_uart.h rename to include/hw/char/sifive_uart.h index 65668825a35daa8b0af60629b944bde28dfc325d..3e962be65923da1fdd8baa41de6f746a8609d19e 100644 --- a/include/hw/riscv/sifive_uart.h +++ b/include/hw/char/sifive_uart.h @@ -22,6 +22,7 @@ #include "chardev/char-fe.h" #include "hw/sysbus.h" +#include "qom/object.h" enum { SIFIVE_UART_TXFIFO = 0, @@ -51,10 +52,11 @@ enum { #define TYPE_SIFIVE_UART "riscv.sifive.uart" -#define SIFIVE_UART(obj) \ - OBJECT_CHECK(SiFiveUARTState, (obj), TYPE_SIFIVE_UART) +typedef struct SiFiveUARTState SiFiveUARTState; +DECLARE_INSTANCE_CHECKER(SiFiveUARTState, SIFIVE_UART, + TYPE_SIFIVE_UART) -typedef struct SiFiveUARTState { +struct SiFiveUARTState { /*< private >*/ SysBusDevice parent_obj; @@ -69,7 +71,7 @@ typedef struct SiFiveUARTState { uint32_t txctrl; uint32_t rxctrl; uint32_t div; -} SiFiveUARTState; +}; SiFiveUARTState *sifive_uart_create(MemoryRegion *address_space, hwaddr base, Chardev *chr, qemu_irq irq); diff --git a/include/hw/char/stm32f2xx_usart.h b/include/hw/char/stm32f2xx_usart.h index 8e112671e3c1a6bfb66f3956225d1a380a977b0d..65bcc85470d49c2fa27a8b83a1a665e3ea52c43e 100644 --- a/include/hw/char/stm32f2xx_usart.h +++ b/include/hw/char/stm32f2xx_usart.h @@ -27,6 +27,7 @@ #include "hw/sysbus.h" #include "chardev/char-fe.h" +#include "qom/object.h" #define USART_SR 0x00 #define USART_DR 0x04 @@ -53,10 +54,9 @@ #define USART_CR1_RE (1 << 2) #define TYPE_STM32F2XX_USART "stm32f2xx-usart" -#define STM32F2XX_USART(obj) \ - OBJECT_CHECK(STM32F2XXUsartState, (obj), TYPE_STM32F2XX_USART) +OBJECT_DECLARE_SIMPLE_TYPE(STM32F2XXUsartState, STM32F2XX_USART) -typedef struct { +struct STM32F2XXUsartState { /* */ SysBusDevice parent_obj; @@ -73,5 +73,5 @@ typedef struct { CharBackend chr; qemu_irq irq; -} STM32F2XXUsartState; +}; #endif /* HW_STM32F2XX_USART_H */ diff --git a/include/hw/char/xilinx_uartlite.h b/include/hw/char/xilinx_uartlite.h index 194e2feafec9da5e6edc6d8e83ec1f3b27f85d49..bb32d0fcb30fb7772fd8c4a3930a825b3d763b3f 100644 --- a/include/hw/char/xilinx_uartlite.h +++ b/include/hw/char/xilinx_uartlite.h @@ -25,10 +25,10 @@ static inline DeviceState *xilinx_uartlite_create(hwaddr addr, DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, "xlnx.xps-uartlite"); + dev = qdev_new("xlnx.xps-uartlite"); s = SYS_BUS_DEVICE(dev); qdev_prop_set_chr(dev, "chardev", chr); - qdev_init_nofail(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, addr); sysbus_connect_irq(s, 0, irq); diff --git a/include/hw/clock.h b/include/hw/clock.h index f822a94220972b925ce4fcb4953a846af712e9d1..81bcf3e505a02899faac2a2e503511b262e5eab9 100644 --- a/include/hw/clock.h +++ b/include/hw/clock.h @@ -18,7 +18,7 @@ #include "qemu/queue.h" #define TYPE_CLOCK "clock" -#define CLOCK(obj) OBJECT_CHECK(Clock, (obj), TYPE_CLOCK) +OBJECT_DECLARE_SIMPLE_TYPE(Clock, CLOCK) typedef void ClockCallback(void *opaque); @@ -54,7 +54,6 @@ typedef void ClockCallback(void *opaque); * @sibling: structure used to form a clock list */ -typedef struct Clock Clock; struct Clock { /*< private >*/ @@ -82,6 +81,11 @@ extern const VMStateDescription vmstate_clock; VMSTATE_CLOCK_V(field, state, 0) #define VMSTATE_CLOCK_V(field, state, version) \ VMSTATE_STRUCT_POINTER_V(field, state, version, vmstate_clock, Clock) +#define VMSTATE_ARRAY_CLOCK(field, state, num) \ + VMSTATE_ARRAY_CLOCK_V(field, state, num, 0) +#define VMSTATE_ARRAY_CLOCK_V(field, state, num, version) \ + VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(field, state, num, version, \ + vmstate_clock, Clock) /** * clock_setup_canonical_path: @@ -91,6 +95,19 @@ extern const VMStateDescription vmstate_clock; */ void clock_setup_canonical_path(Clock *clk); +/** + * clock_new: + * @parent: the clock parent + * @name: the clock object name + * + * Helper function to create a new clock and parent it to @parent. There is no + * need to call clock_setup_canonical_path on the returned clock as it is done + * by this function. + * + * @return the newly created clock + */ +Clock *clock_new(Object *parent, const char *name); + /** * clock_set_callback: * @clk: the clock to register the callback into @@ -127,17 +144,19 @@ void clock_set_source(Clock *clk, Clock *src); * @value: the clock's value, 0 means unclocked * * Set the local cached period value of @clk to @value. + * + * @return: true if the clock is changed. */ -void clock_set(Clock *clk, uint64_t value); +bool clock_set(Clock *clk, uint64_t value); -static inline void clock_set_hz(Clock *clk, unsigned hz) +static inline bool clock_set_hz(Clock *clk, unsigned hz) { - clock_set(clk, CLOCK_PERIOD_FROM_HZ(hz)); + return clock_set(clk, CLOCK_PERIOD_FROM_HZ(hz)); } -static inline void clock_set_ns(Clock *clk, unsigned ns) +static inline bool clock_set_ns(Clock *clk, unsigned ns) { - clock_set(clk, CLOCK_PERIOD_FROM_NS(ns)); + return clock_set(clk, CLOCK_PERIOD_FROM_NS(ns)); } /** @@ -163,8 +182,9 @@ void clock_propagate(Clock *clk); */ static inline void clock_update(Clock *clk, uint64_t value) { - clock_set(clk, value); - clock_propagate(clk); + if (clock_set(clk, value)) { + clock_propagate(clk); + } } static inline void clock_update_hz(Clock *clk, unsigned hz) @@ -209,17 +229,4 @@ static inline bool clock_is_enabled(const Clock *clk) return clock_get(clk) != 0; } -static inline void clock_init(Clock *clk, uint64_t value) -{ - clock_set(clk, value); -} -static inline void clock_init_hz(Clock *clk, uint64_t value) -{ - clock_set_hz(clk, value); -} -static inline void clock_init_ns(Clock *clk, uint64_t value) -{ - clock_set_ns(clk, value); -} - #endif /* QEMU_HW_CLOCK_H */ diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 07f7698155022fe5496f9cc0559a1f4a3e1aea7c..3d92c967fffaf348bec0e267398f3cf929744306 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -30,6 +30,7 @@ #include "qemu/queue.h" #include "qemu/thread.h" #include "qemu/plugin.h" +#include "qom/object.h" typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size, void *opaque); @@ -61,8 +62,9 @@ typedef uint64_t vaddr; */ #define CPU(obj) ((CPUState *)(obj)) -#define CPU_CLASS(class) OBJECT_CLASS_CHECK(CPUClass, (class), TYPE_CPU) -#define CPU_GET_CLASS(obj) OBJECT_GET_CLASS(CPUClass, (obj), TYPE_CPU) +typedef struct CPUClass CPUClass; +DECLARE_CLASS_CHECKERS(CPUClass, CPU, + TYPE_CPU) typedef enum MMUAccessType { MMU_DATA_LOAD = 0, @@ -153,10 +155,12 @@ struct TranslationBlock; * @disas_set_info: Setup architecture specific components of disassembly info * @adjust_watchpoint_address: Perform a target-specific adjustment to an * address before attempting to match it against watchpoints. + * @deprecation_note: If this CPUClass is deprecated, this field provides + * related information. * * Represents a CPU family or model. */ -typedef struct CPUClass { +struct CPUClass { /*< private >*/ DeviceClass parent_class; /*< public >*/ @@ -219,10 +223,11 @@ typedef struct CPUClass { vaddr (*adjust_watchpoint_address)(CPUState *cpu, vaddr addr, int len); void (*tcg_initialize)(void); + const char *deprecation_note; /* Keep non-pointer data at the end to minimize holes. */ int gdb_num_core_regs; bool gdb_stop_before_watchpoint; -} CPUClass; +}; /* * Low 16 bits: number of cycles left, used only in icount mode. @@ -259,6 +264,18 @@ struct CPUWatchpoint { QTAILQ_ENTRY(CPUWatchpoint) entry; }; +#ifdef CONFIG_PLUGIN +/* + * For plugins we sometime need to save the resolved iotlb data before + * the memory regions get moved around by io_writex. + */ +typedef struct SavedIOTLB { + hwaddr addr; + MemoryRegionSection *section; + hwaddr mr_offset; +} SavedIOTLB; +#endif + struct KVMState; struct kvm_run; @@ -331,8 +348,8 @@ struct qemu_work_item; * @opaque: User data. * @mem_io_pc: Host Program Counter at which the memory was accessed. * @kvm_fd: vCPU file descriptor for KVM. - * @work_mutex: Lock to prevent multiple access to queued_work_*. - * @queued_work_first: First asynchronous work pending. + * @work_mutex: Lock to prevent multiple access to @work_list. + * @work_list: List of pending asynchronous work. * @trace_dstate_delayed: Delayed changes to trace_dstate (includes all changes * to @trace_dstate). * @trace_dstate: Dynamic tracing state of events for this vCPU (bitmask). @@ -362,6 +379,10 @@ struct CPUState { bool created; bool stop; bool stopped; + + /* Should CPU start in powered-off state? */ + bool start_powered_off; + bool unplug; bool crash_occurred; bool exit_request; @@ -376,7 +397,7 @@ struct CPUState { sigjmp_buf jmp_env; QemuMutex work_mutex; - struct qemu_work_item *queued_work_first, *queued_work_last; + QSIMPLEQ_HEAD(, qemu_work_item) work_list; CPUAddressSpace *cpu_ases; int num_ases; @@ -417,7 +438,11 @@ struct CPUState { DECLARE_BITMAP(plugin_mask, QEMU_PLUGIN_EV_MAX); +#ifdef CONFIG_PLUGIN GArray *plugin_mem_cbs; + /* saved iotlb data from io_writex */ + SavedIOTLB saved_iotlb; +#endif /* TODO Move common fields from CPUArchState here. */ int cpu_index; @@ -460,7 +485,7 @@ static inline void cpu_tb_jmp_cache_clear(CPUState *cpu) unsigned int i; for (i = 0; i < TB_JMP_CACHE_SIZE; i++) { - atomic_set(&cpu->tb_jmp_cache[i], NULL); + qatomic_set(&cpu->tb_jmp_cache[i], NULL); } } @@ -490,6 +515,8 @@ bool cpu_paging_enabled(const CPUState *cpu); void cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list, Error **errp); +#if !defined(CONFIG_USER_ONLY) + /** * cpu_write_elf64_note: * @f: pointer to a function that writes memory to a file @@ -539,6 +566,8 @@ int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu, */ GuestPanicInformation *cpu_get_crash_info(CPUState *cpu); +#endif /* !CONFIG_USER_ONLY */ + /** * CPUDumpFlags: * @CPU_DUMP_CODE: @@ -632,7 +661,8 @@ static inline int cpu_asidx_from_attrs(CPUState *cpu, MemTxAttrs attrs) } return ret; } -#endif + +#endif /* CONFIG_USER_ONLY */ /** * cpu_list_add: @@ -817,49 +847,6 @@ bool cpu_exists(int64_t id); */ CPUState *cpu_by_arch_id(int64_t id); -/** - * cpu_throttle_set: - * @new_throttle_pct: Percent of sleep time. Valid range is 1 to 99. - * - * Throttles all vcpus by forcing them to sleep for the given percentage of - * time. A throttle_percentage of 25 corresponds to a 75% duty cycle roughly. - * (example: 10ms sleep for every 30ms awake). - * - * cpu_throttle_set can be called as needed to adjust new_throttle_pct. - * Once the throttling starts, it will remain in effect until cpu_throttle_stop - * is called. - */ -void cpu_throttle_set(int new_throttle_pct); - -/** - * cpu_throttle_stop: - * - * Stops the vcpu throttling started by cpu_throttle_set. - */ -void cpu_throttle_stop(void); - -/** - * cpu_throttle_active: - * - * Returns: %true if the vcpus are currently being throttled, %false otherwise. - */ -bool cpu_throttle_active(void); - -/** - * cpu_throttle_get_percentage: - * - * Returns the vcpu throttle percentage. See cpu_throttle_set for details. - * - * Returns: The throttle percentage in range 1 to 99. - */ -int cpu_throttle_get_percentage(void); - -#ifndef CONFIG_USER_ONLY - -typedef void (*CPUInterruptHandler)(CPUState *, int); - -extern CPUInterruptHandler cpu_interrupt_handler; - /** * cpu_interrupt: * @cpu: The CPU to set an interrupt on. @@ -867,17 +854,9 @@ extern CPUInterruptHandler cpu_interrupt_handler; * * Invokes the interrupt handler. */ -static inline void cpu_interrupt(CPUState *cpu, int mask) -{ - cpu_interrupt_handler(cpu, mask); -} - -#else /* USER_ONLY */ void cpu_interrupt(CPUState *cpu, int mask); -#endif /* USER_ONLY */ - #ifdef NEED_CPU_H #ifdef CONFIG_SOFTMMU @@ -948,14 +927,6 @@ void cpu_exit(CPUState *cpu); void cpu_resume(CPUState *cpu); /** - * cpu_remove: - * @cpu: The CPU to remove. - * - * Requests the CPU to be removed. - */ -void cpu_remove(CPUState *cpu); - - /** * cpu_remove_sync: * @cpu: The CPU to remove. * diff --git a/include/hw/core/generic-loader.h b/include/hw/core/generic-loader.h index 9ffce1c5a30c464083f01d4e185a87cee113693b..19d87b39c8b093a3e49a89edced20ab765bc5efc 100644 --- a/include/hw/core/generic-loader.h +++ b/include/hw/core/generic-loader.h @@ -20,8 +20,9 @@ #include "elf.h" #include "hw/qdev-core.h" +#include "qom/object.h" -typedef struct GenericLoaderState { +struct GenericLoaderState { /* */ DeviceState parent_obj; @@ -38,10 +39,9 @@ typedef struct GenericLoaderState { bool force_raw; bool data_be; bool set_pc; -} GenericLoaderState; +}; #define TYPE_GENERIC_LOADER "loader" -#define GENERIC_LOADER(obj) OBJECT_CHECK(GenericLoaderState, (obj), \ - TYPE_GENERIC_LOADER) +OBJECT_DECLARE_SIMPLE_TYPE(GenericLoaderState, GENERIC_LOADER) #endif diff --git a/include/hw/core/split-irq.h b/include/hw/core/split-irq.h index 872a39aa4fd4f31025894242fa8a6f8c9ea811e2..ff8852f4071cfb6e8b808f73d1b69a4f535783ce 100644 --- a/include/hw/core/split-irq.h +++ b/include/hw/core/split-irq.h @@ -42,9 +42,8 @@ #define MAX_SPLIT_LINES 16 -typedef struct SplitIRQ SplitIRQ; -#define SPLIT_IRQ(obj) OBJECT_CHECK(SplitIRQ, (obj), TYPE_SPLIT_IRQ) +OBJECT_DECLARE_SIMPLE_TYPE(SplitIRQ, SPLIT_IRQ) struct SplitIRQ { DeviceState parent_obj; diff --git a/include/hw/cpu/a15mpcore.h b/include/hw/cpu/a15mpcore.h index b423533d202b225094500925341ca4af7233aa88..75d39e5458aedd46daf58fc0a0979d966bd9b7c1 100644 --- a/include/hw/cpu/a15mpcore.h +++ b/include/hw/cpu/a15mpcore.h @@ -22,14 +22,14 @@ #include "hw/sysbus.h" #include "hw/intc/arm_gic.h" +#include "qom/object.h" /* A15MP private memory region. */ #define TYPE_A15MPCORE_PRIV "a15mpcore_priv" -#define A15MPCORE_PRIV(obj) \ - OBJECT_CHECK(A15MPPrivState, (obj), TYPE_A15MPCORE_PRIV) +OBJECT_DECLARE_SIMPLE_TYPE(A15MPPrivState, A15MPCORE_PRIV) -typedef struct A15MPPrivState { +struct A15MPPrivState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -39,6 +39,6 @@ typedef struct A15MPPrivState { MemoryRegion container; GICState gic; -} A15MPPrivState; +}; #endif diff --git a/include/hw/cpu/a9mpcore.h b/include/hw/cpu/a9mpcore.h index 5d67ca22c49024e39e331e7d44159540cba77848..e0396ab6af7e7f50730dfedb07cd644596909f0b 100644 --- a/include/hw/cpu/a9mpcore.h +++ b/include/hw/cpu/a9mpcore.h @@ -15,12 +15,12 @@ #include "hw/misc/a9scu.h" #include "hw/timer/arm_mptimer.h" #include "hw/timer/a9gtimer.h" +#include "qom/object.h" #define TYPE_A9MPCORE_PRIV "a9mpcore_priv" -#define A9MPCORE_PRIV(obj) \ - OBJECT_CHECK(A9MPPrivState, (obj), TYPE_A9MPCORE_PRIV) +OBJECT_DECLARE_SIMPLE_TYPE(A9MPPrivState, A9MPCORE_PRIV) -typedef struct A9MPPrivState { +struct A9MPPrivState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -34,6 +34,6 @@ typedef struct A9MPPrivState { A9GTimerState gtimer; ARMMPTimerState mptimer; ARMMPTimerState wdt; -} A9MPPrivState; +}; #endif diff --git a/include/hw/cpu/arm11mpcore.h b/include/hw/cpu/arm11mpcore.h index 6196109ca2ba7f3867125bb784eda096eb5223a9..2cac8c1232d19cee7e033a6e18f07e05a974843d 100644 --- a/include/hw/cpu/arm11mpcore.h +++ b/include/hw/cpu/arm11mpcore.h @@ -14,12 +14,12 @@ #include "hw/misc/arm11scu.h" #include "hw/intc/arm_gic.h" #include "hw/timer/arm_mptimer.h" +#include "qom/object.h" #define TYPE_ARM11MPCORE_PRIV "arm11mpcore_priv" -#define ARM11MPCORE_PRIV(obj) \ - OBJECT_CHECK(ARM11MPCorePriveState, (obj), TYPE_ARM11MPCORE_PRIV) +OBJECT_DECLARE_SIMPLE_TYPE(ARM11MPCorePriveState, ARM11MPCORE_PRIV) -typedef struct ARM11MPCorePriveState { +struct ARM11MPCorePriveState { SysBusDevice parent_obj; uint32_t num_cpu; @@ -30,6 +30,6 @@ typedef struct ARM11MPCorePriveState { GICState gic; ARMMPTimerState mptimer; ARMMPTimerState wdtimer; -} ARM11MPCorePriveState; +}; #endif diff --git a/include/hw/cpu/cluster.h b/include/hw/cpu/cluster.h index a616501a55d2aef22c41ee512541ca8dfb550fe3..53fbf36af54202a1871177cf39726448f2f13575 100644 --- a/include/hw/cpu/cluster.h +++ b/include/hw/cpu/cluster.h @@ -21,6 +21,7 @@ #define HW_CPU_CLUSTER_H #include "hw/qdev-core.h" +#include "qom/object.h" /* * CPU Cluster type @@ -54,8 +55,7 @@ */ #define TYPE_CPU_CLUSTER "cpu-cluster" -#define CPU_CLUSTER(obj) \ - OBJECT_CHECK(CPUClusterState, (obj), TYPE_CPU_CLUSTER) +OBJECT_DECLARE_SIMPLE_TYPE(CPUClusterState, CPU_CLUSTER) /* * This limit is imposed by TCG, which puts the cluster ID into an @@ -70,12 +70,12 @@ * * State of a CPU cluster. */ -typedef struct CPUClusterState { +struct CPUClusterState { /*< private >*/ DeviceState parent_obj; /*< public >*/ uint32_t cluster_id; -} CPUClusterState; +}; #endif diff --git a/include/hw/cpu/core.h b/include/hw/cpu/core.h index 555ad831bb3d5170213237a36eba08cf0d561639..98ab91647eb25053602208cd350107cbce70c6b8 100644 --- a/include/hw/cpu/core.h +++ b/include/hw/cpu/core.h @@ -10,20 +10,20 @@ #define HW_CPU_CORE_H #include "hw/qdev-core.h" +#include "qom/object.h" #define TYPE_CPU_CORE "cpu-core" -#define CPU_CORE(obj) \ - OBJECT_CHECK(CPUCore, (obj), TYPE_CPU_CORE) +OBJECT_DECLARE_SIMPLE_TYPE(CPUCore, CPU_CORE) -typedef struct CPUCore { +struct CPUCore { /*< private >*/ DeviceState parent_obj; /*< public >*/ int core_id; int nr_threads; -} CPUCore; +}; /* Note: topology field names need to be kept in sync with * 'CpuInstanceProperties' */ diff --git a/include/hw/cris/etraxfs.h b/include/hw/cris/etraxfs.h index 403e7f95e62ba869acfb031e77547bd98a31ed39..9e99380e0c9837f2287c59e41d741bc37fc5447d 100644 --- a/include/hw/cris/etraxfs.h +++ b/include/hw/cris/etraxfs.h @@ -41,10 +41,10 @@ static inline DeviceState *etraxfs_ser_create(hwaddr addr, DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, "etraxfs,serial"); + dev = qdev_new("etraxfs,serial"); s = SYS_BUS_DEVICE(dev); qdev_prop_set_chr(dev, "chardev", chr); - qdev_init_nofail(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, addr); sysbus_connect_irq(s, 0, irq); return dev; diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h index 2246be74d8360f7b358e9b1f7092ab24e797409d..38671afffd506480b3e42ee4d08cc8ae4551a3e2 100644 --- a/include/hw/display/bcm2835_fb.h +++ b/include/hw/display/bcm2835_fb.h @@ -14,9 +14,10 @@ #include "hw/sysbus.h" #include "ui/console.h" +#include "qom/object.h" #define TYPE_BCM2835_FB "bcm2835-fb" -#define BCM2835_FB(obj) OBJECT_CHECK(BCM2835FBState, (obj), TYPE_BCM2835_FB) +OBJECT_DECLARE_SIMPLE_TYPE(BCM2835FBState, BCM2835_FB) /* * Configuration information about the fb which the guest can program @@ -32,7 +33,7 @@ typedef struct { uint32_t alpha; } BCM2835FBConfig; -typedef struct { +struct BCM2835FBState { /*< private >*/ SysBusDevice busdev; /*< public >*/ @@ -49,7 +50,7 @@ typedef struct { BCM2835FBConfig config; BCM2835FBConfig initial_config; -} BCM2835FBState; +}; void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig); diff --git a/include/hw/display/dpcd.h b/include/hw/display/dpcd.h index 6880ee36a3523e84136eeb2f36d7e43dc63eb202..a4e37abf6f8644a1ee28b6156eaaec85c5e050aa 100644 --- a/include/hw/display/dpcd.h +++ b/include/hw/display/dpcd.h @@ -24,11 +24,11 @@ #ifndef DPCD_H #define DPCD_H +#include "qom/object.h" -typedef struct DPCDState DPCDState; #define TYPE_DPCD "dpcd" -#define DPCD(obj) OBJECT_CHECK(DPCDState, (obj), TYPE_DPCD) +OBJECT_DECLARE_SIMPLE_TYPE(DPCDState, DPCD) /* DCPD Revision. */ #define DPCD_REVISION 0x00 diff --git a/include/hw/display/edid.h b/include/hw/display/edid.h index ff99dc0a052b9f5e98f4a349ec2ede6545c2632c..1f8fc9b37500a4c128b1e3159b23e67364b4c5ea 100644 --- a/include/hw/display/edid.h +++ b/include/hw/display/edid.h @@ -1,13 +1,12 @@ #ifndef EDID_H #define EDID_H -#include "qom/object.h" - typedef struct qemu_edid_info { const char *vendor; /* http://www.uefi.org/pnp_id_list */ const char *name; const char *serial; - uint32_t dpi; + uint16_t width_mm; + uint16_t height_mm; uint32_t prefx; uint32_t prefy; uint32_t maxx; @@ -20,6 +19,8 @@ size_t qemu_edid_size(uint8_t *edid); void qemu_edid_region_io(MemoryRegion *region, Object *owner, uint8_t *edid, size_t size); +uint32_t qemu_edid_dpi_to_mm(uint32_t dpi, uint32_t res); + #define DEFINE_EDID_PROPERTIES(_state, _edid_info) \ DEFINE_PROP_UINT32("xres", _state, _edid_info.prefx, 0), \ DEFINE_PROP_UINT32("yres", _state, _edid_info.prefy, 0), \ diff --git a/include/hw/display/i2c-ddc.h b/include/hw/display/i2c-ddc.h index 1cf53a0c8dbc8244380d6186897c4eede77c5106..94b5880587460fb9763a14418eccf89b58265b31 100644 --- a/include/hw/display/i2c-ddc.h +++ b/include/hw/display/i2c-ddc.h @@ -21,6 +21,7 @@ #include "hw/display/edid.h" #include "hw/i2c/i2c.h" +#include "qom/object.h" /* A simple I2C slave which just returns the contents of its EDID blob. */ struct I2CDDCState { @@ -33,9 +34,8 @@ struct I2CDDCState { uint8_t edid_blob[128]; }; -typedef struct I2CDDCState I2CDDCState; #define TYPE_I2CDDC "i2c-ddc" -#define I2CDDC(obj) OBJECT_CHECK(I2CDDCState, (obj), TYPE_I2CDDC) +OBJECT_DECLARE_SIMPLE_TYPE(I2CDDCState, I2CDDC) #endif /* I2C_DDC_H */ diff --git a/include/hw/display/macfb.h b/include/hw/display/macfb.h index 26367ae2c4a499eeeb042605a1cbc10f4f847495..c133fa271efc49c78f6474f4de5c12beca31fb93 100644 --- a/include/hw/display/macfb.h +++ b/include/hw/display/macfb.h @@ -16,6 +16,7 @@ #include "qemu/osdep.h" #include "exec/memory.h" #include "ui/console.h" +#include "qom/object.h" typedef struct MacfbState { MemoryRegion mem_vram; @@ -31,34 +32,28 @@ typedef struct MacfbState { } MacfbState; #define TYPE_MACFB "sysbus-macfb" -#define MACFB(obj) \ - OBJECT_CHECK(MacfbSysBusState, (obj), TYPE_MACFB) +OBJECT_DECLARE_SIMPLE_TYPE(MacfbSysBusState, MACFB) -typedef struct { +struct MacfbSysBusState { SysBusDevice busdev; MacfbState macfb; -} MacfbSysBusState; +}; -#define MACFB_NUBUS_DEVICE_CLASS(class) \ - OBJECT_CLASS_CHECK(MacfbNubusDeviceClass, (class), TYPE_NUBUS_MACFB) -#define MACFB_NUBUS_GET_CLASS(obj) \ - OBJECT_GET_CLASS(MacfbNubusDeviceClass, (obj), TYPE_NUBUS_MACFB) +#define TYPE_NUBUS_MACFB "nubus-macfb" +OBJECT_DECLARE_TYPE(MacfbNubusState, MacfbNubusDeviceClass, NUBUS_MACFB) -typedef struct MacfbNubusDeviceClass { +struct MacfbNubusDeviceClass { DeviceClass parent_class; DeviceRealize parent_realize; -} MacfbNubusDeviceClass; +}; -#define TYPE_NUBUS_MACFB "nubus-macfb" -#define NUBUS_MACFB(obj) \ - OBJECT_CHECK(MacfbNubusState, (obj), TYPE_NUBUS_MACFB) -typedef struct { +struct MacfbNubusState { NubusDevice busdev; MacfbState macfb; -} MacfbNubusState; +}; #endif diff --git a/include/hw/display/milkymist_tmu2.h b/include/hw/display/milkymist_tmu2.h index e3394ff158a6f39a8810acaaaa732cd1ec943e4c..fdce9535a1e61db721dc1ff057868901240ede70 100644 --- a/include/hw/display/milkymist_tmu2.h +++ b/include/hw/display/milkymist_tmu2.h @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/hw/display/xlnx_dp.h b/include/hw/display/xlnx_dp.h index ab0dd250cc5bbcab5bb6b97c5c0645171c6be45b..8ab4733bb85418f5908c16cb6441364a2483122d 100644 --- a/include/hw/display/xlnx_dp.h +++ b/include/hw/display/xlnx_dp.h @@ -34,6 +34,7 @@ #include "qemu/units.h" #include "hw/dma/xlnx_dpdma.h" #include "audio/audio.h" +#include "qom/object.h" #define AUD_CHBUF_MAX_DEPTH (32 * KiB) #define MAX_QEMU_BUFFER_SIZE (4 * KiB) @@ -48,7 +49,7 @@ struct PixmanPlane { DisplaySurface *surface; }; -typedef struct XlnxDPState { +struct XlnxDPState { /*< private >*/ SysBusDevice parent_obj; @@ -101,9 +102,9 @@ typedef struct XlnxDPState { */ DPCDState *dpcd; I2CDDCState *edid; -} XlnxDPState; +}; #define TYPE_XLNX_DP "xlnx.v-dp" -#define XLNX_DP(obj) OBJECT_CHECK(XlnxDPState, (obj), TYPE_XLNX_DP) +OBJECT_DECLARE_SIMPLE_TYPE(XlnxDPState, XLNX_DP) #endif diff --git a/include/hw/dma/bcm2835_dma.h b/include/hw/dma/bcm2835_dma.h index a6747842b764b45511f3beb4ed1d99919d137634..1d26b1d8d0f784e9b9a81e8314860e7c672c9451 100644 --- a/include/hw/dma/bcm2835_dma.h +++ b/include/hw/dma/bcm2835_dma.h @@ -9,6 +9,7 @@ #define BCM2835_DMA_H #include "hw/sysbus.h" +#include "qom/object.h" typedef struct { uint32_t cs; @@ -25,12 +26,11 @@ typedef struct { } BCM2835DMAChan; #define TYPE_BCM2835_DMA "bcm2835-dma" -#define BCM2835_DMA(obj) \ - OBJECT_CHECK(BCM2835DMAState, (obj), TYPE_BCM2835_DMA) +OBJECT_DECLARE_SIMPLE_TYPE(BCM2835DMAState, BCM2835_DMA) #define BCM2835_DMA_NCHANS 16 -typedef struct { +struct BCM2835DMAState { /*< private >*/ SysBusDevice busdev; /*< public >*/ @@ -42,6 +42,6 @@ typedef struct { BCM2835DMAChan chan[BCM2835_DMA_NCHANS]; uint32_t int_status; uint32_t enable; -} BCM2835DMAState; +}; #endif diff --git a/include/hw/dma/i8257.h b/include/hw/dma/i8257.h index 03e2c166be72a677c5e97821ead8496da4000e25..f652345d65a27d4b802af39ad74818c34f03e376 100644 --- a/include/hw/dma/i8257.h +++ b/include/hw/dma/i8257.h @@ -3,8 +3,10 @@ #include "hw/isa/isa.h" #include "exec/ioport.h" +#include "qom/object.h" #define TYPE_I8257 "i8257" +OBJECT_DECLARE_SIMPLE_TYPE(I8257State, I8257) typedef struct I8257Regs { int now[2]; @@ -18,7 +20,7 @@ typedef struct I8257Regs { void *opaque; } I8257Regs; -typedef struct I8257State { +struct I8257State { /* */ ISADevice parent_obj; @@ -41,7 +43,7 @@ typedef struct I8257State { int running; PortioList portio_page; PortioList portio_pageh; -} I8257State; +}; void i8257_dma_init(ISABus *bus, bool high_page_enable); diff --git a/include/hw/dma/pl080.h b/include/hw/dma/pl080.h index 9d4b3df143f82e9e3c82f3fd94729147b5cd3986..1883f042701ff727ab0d460ac1d831dff09c730f 100644 --- a/include/hw/dma/pl080.h +++ b/include/hw/dma/pl080.h @@ -29,6 +29,7 @@ #define HW_DMA_PL080_H #include "hw/sysbus.h" +#include "qom/object.h" #define PL080_MAX_CHANNELS 8 @@ -42,9 +43,9 @@ typedef struct { #define TYPE_PL080 "pl080" #define TYPE_PL081 "pl081" -#define PL080(obj) OBJECT_CHECK(PL080State, (obj), TYPE_PL080) +OBJECT_DECLARE_SIMPLE_TYPE(PL080State, PL080) -typedef struct PL080State { +struct PL080State { SysBusDevice parent_obj; MemoryRegion iomem; @@ -66,6 +67,6 @@ typedef struct PL080State { MemoryRegion *downstream; AddressSpace downstream_as; -} PL080State; +}; #endif diff --git a/include/hw/dma/sifive_pdma.h b/include/hw/dma/sifive_pdma.h new file mode 100644 index 0000000000000000000000000000000000000000..e319bbd6c40f58419949789d721888e5279c2f37 --- /dev/null +++ b/include/hw/dma/sifive_pdma.h @@ -0,0 +1,57 @@ +/* + * SiFive Platform DMA emulation + * + * Copyright (c) 2020 Wind River Systems, Inc. + * + * Author: + * Bin Meng + * + * 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 or + * (at your option) version 3 of the License. + * + * 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 . + */ + +#ifndef SIFIVE_PDMA_H +#define SIFIVE_PDMA_H + +struct sifive_pdma_chan { + uint32_t control; + uint32_t next_config; + uint64_t next_bytes; + uint64_t next_dst; + uint64_t next_src; + uint32_t exec_config; + uint64_t exec_bytes; + uint64_t exec_dst; + uint64_t exec_src; + int state; +}; + +#define SIFIVE_PDMA_CHANS 4 +#define SIFIVE_PDMA_IRQS (SIFIVE_PDMA_CHANS * 2) +#define SIFIVE_PDMA_REG_SIZE 0x100000 +#define SIFIVE_PDMA_CHAN_NO(reg) ((reg & (SIFIVE_PDMA_REG_SIZE - 1)) >> 12) + +typedef struct SiFivePDMAState { + SysBusDevice parent; + MemoryRegion iomem; + qemu_irq irq[SIFIVE_PDMA_IRQS]; + + struct sifive_pdma_chan chan[SIFIVE_PDMA_CHANS]; +} SiFivePDMAState; + +#define TYPE_SIFIVE_PDMA "sifive.pdma" + +#define SIFIVE_PDMA(obj) \ + OBJECT_CHECK(SiFivePDMAState, (obj), TYPE_SIFIVE_PDMA) + +#endif /* SIFIVE_PDMA_H */ diff --git a/include/hw/dma/xlnx-zdma.h b/include/hw/dma/xlnx-zdma.h index 0b240b4c3ced962c6df03625192dbabf256bf9c8..6602e7ffa72b18f33fc84ccbe533dac54dbcfed4 100644 --- a/include/hw/dma/xlnx-zdma.h +++ b/include/hw/dma/xlnx-zdma.h @@ -32,6 +32,7 @@ #include "hw/sysbus.h" #include "hw/register.h" #include "sysemu/dma.h" +#include "qom/object.h" #define ZDMA_R_MAX (0x204 / 4) @@ -50,7 +51,7 @@ typedef union { uint32_t words[4]; } XlnxZDMADescr; -typedef struct XlnxZDMA { +struct XlnxZDMA { SysBusDevice parent_obj; MemoryRegion iomem; MemTxAttrs attr; @@ -74,11 +75,10 @@ typedef struct XlnxZDMA { /* We don't model the common bufs. Must be at least 16 bytes to model write only mode. */ uint8_t buf[2048]; -} XlnxZDMA; +}; #define TYPE_XLNX_ZDMA "xlnx.zdma" -#define XLNX_ZDMA(obj) \ - OBJECT_CHECK(XlnxZDMA, (obj), TYPE_XLNX_ZDMA) +OBJECT_DECLARE_SIMPLE_TYPE(XlnxZDMA, XLNX_ZDMA) #endif /* XLNX_ZDMA_H */ diff --git a/include/hw/dma/xlnx-zynq-devcfg.h b/include/hw/dma/xlnx-zynq-devcfg.h index 1d3969d91fa92a22cd9fe086e5474fc6b013a4bc..e4cf085d703b9c1d7b239e4ac8ba754f32244a1f 100644 --- a/include/hw/dma/xlnx-zynq-devcfg.h +++ b/include/hw/dma/xlnx-zynq-devcfg.h @@ -29,11 +29,11 @@ #include "hw/register.h" #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_XLNX_ZYNQ_DEVCFG "xlnx.ps7-dev-cfg" -#define XLNX_ZYNQ_DEVCFG(obj) \ - OBJECT_CHECK(XlnxZynqDevcfg, (obj), TYPE_XLNX_ZYNQ_DEVCFG) +OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqDevcfg, XLNX_ZYNQ_DEVCFG) #define XLNX_ZYNQ_DEVCFG_R_MAX (0x100 / 4) @@ -46,7 +46,7 @@ typedef struct XlnxZynqDevcfgDMACmd { uint32_t dest_len; } XlnxZynqDevcfgDMACmd; -typedef struct XlnxZynqDevcfg { +struct XlnxZynqDevcfg { SysBusDevice parent_obj; MemoryRegion iomem; @@ -57,6 +57,6 @@ typedef struct XlnxZynqDevcfg { uint32_t regs[XLNX_ZYNQ_DEVCFG_R_MAX]; RegisterInfo regs_info[XLNX_ZYNQ_DEVCFG_R_MAX]; -} XlnxZynqDevcfg; +}; #endif diff --git a/include/hw/dma/xlnx_dpdma.h b/include/hw/dma/xlnx_dpdma.h index 7a304a5bb460651cd7645693928dcc56e853499d..40537a848b433517a64dea6bc1e23f82025e338a 100644 --- a/include/hw/dma/xlnx_dpdma.h +++ b/include/hw/dma/xlnx_dpdma.h @@ -28,6 +28,7 @@ #include "hw/sysbus.h" #include "ui/console.h" #include "sysemu/dma.h" +#include "qom/object.h" #define XLNX_DPDMA_REG_ARRAY_SIZE (0x1000 >> 2) @@ -42,10 +43,9 @@ struct XlnxDPDMAState { qemu_irq irq; }; -typedef struct XlnxDPDMAState XlnxDPDMAState; #define TYPE_XLNX_DPDMA "xlnx.dpdma" -#define XLNX_DPDMA(obj) OBJECT_CHECK(XlnxDPDMAState, (obj), TYPE_XLNX_DPDMA) +OBJECT_DECLARE_SIMPLE_TYPE(XlnxDPDMAState, XLNX_DPDMA) /* * xlnx_dpdma_start_operation: Start the operation on the specified channel. The diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h index 398a4a2c85bba0795937fb7d96c915fb671023ef..6fdff3dced59d13e10e40ad936c98917877a452d 100644 --- a/include/hw/elf_ops.h +++ b/include/hw/elf_ops.h @@ -553,9 +553,14 @@ static int glue(load_elf, SZ)(const char *name, int fd, rom_add_elf_program(label, mapped_file, data, file_size, mem_size, addr, as); } else { - address_space_write(as ? as : &address_space_memory, - addr, MEMTXATTRS_UNSPECIFIED, - data, file_size); + MemTxResult res; + + res = address_space_write(as ? as : &address_space_memory, + addr, MEMTXATTRS_UNSPECIFIED, + data, file_size); + if (res != MEMTX_OK) { + goto fail; + } } } diff --git a/include/hw/empty_slot.h b/include/hw/empty_slot.h deleted file mode 100644 index cb9a221aa622a62e9cb33222b3d9bcfb0ac832f0..0000000000000000000000000000000000000000 --- a/include/hw/empty_slot.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef HW_EMPTY_SLOT_H -#define HW_EMPTY_SLOT_H - -#include "exec/hwaddr.h" - -/* empty_slot.c */ -void empty_slot_init(hwaddr addr, uint64_t slot_size); - -#endif diff --git a/include/hw/fw-path-provider.h b/include/hw/fw-path-provider.h index 10d1bd4959482e567194f697ad46d6c0a8d2f80d..8e1d45651cfe5bfbff8928f15f522c78b285e334 100644 --- a/include/hw/fw-path-provider.h +++ b/include/hw/fw-path-provider.h @@ -22,20 +22,19 @@ #define TYPE_FW_PATH_PROVIDER "fw-path-provider" -#define FW_PATH_PROVIDER_CLASS(klass) \ - OBJECT_CLASS_CHECK(FWPathProviderClass, (klass), TYPE_FW_PATH_PROVIDER) -#define FW_PATH_PROVIDER_GET_CLASS(obj) \ - OBJECT_GET_CLASS(FWPathProviderClass, (obj), TYPE_FW_PATH_PROVIDER) +typedef struct FWPathProviderClass FWPathProviderClass; +DECLARE_CLASS_CHECKERS(FWPathProviderClass, FW_PATH_PROVIDER, + TYPE_FW_PATH_PROVIDER) #define FW_PATH_PROVIDER(obj) \ INTERFACE_CHECK(FWPathProvider, (obj), TYPE_FW_PATH_PROVIDER) typedef struct FWPathProvider FWPathProvider; -typedef struct FWPathProviderClass { +struct FWPathProviderClass { InterfaceClass parent_class; char *(*get_dev_path)(FWPathProvider *p, BusState *bus, DeviceState *dev); -} FWPathProviderClass; +}; char *fw_path_provider_get_dev_path(FWPathProvider *p, BusState *bus, DeviceState *dev); diff --git a/include/hw/gpio/aspeed_gpio.h b/include/hw/gpio/aspeed_gpio.h index a2deac046af61f6f5ac6db05270a867e177997bd..e1636ce7fea98617dee7de58e6c4be02b660d522 100644 --- a/include/hw/gpio/aspeed_gpio.h +++ b/include/hw/gpio/aspeed_gpio.h @@ -11,13 +11,10 @@ #define ASPEED_GPIO_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_ASPEED_GPIO "aspeed.gpio" -#define ASPEED_GPIO(obj) OBJECT_CHECK(AspeedGPIOState, (obj), TYPE_ASPEED_GPIO) -#define ASPEED_GPIO_CLASS(klass) \ - OBJECT_CLASS_CHECK(AspeedGPIOClass, (klass), TYPE_ASPEED_GPIO) -#define ASPEED_GPIO_GET_CLASS(obj) \ - OBJECT_GET_CLASS(AspeedGPIOClass, (obj), TYPE_ASPEED_GPIO) +OBJECT_DECLARE_TYPE(AspeedGPIOState, AspeedGPIOClass, ASPEED_GPIO) #define ASPEED_GPIO_MAX_NR_SETS 8 #define ASPEED_REGS_PER_BANK 14 @@ -58,16 +55,16 @@ typedef struct AspeedGPIOReg { enum GPIORegType type; } AspeedGPIOReg; -typedef struct AspeedGPIOClass { +struct AspeedGPIOClass { SysBusDevice parent_obj; const GPIOSetProperties *props; uint32_t nr_gpio_pins; uint32_t nr_gpio_sets; uint32_t gap; const AspeedGPIOReg *reg_table; -} AspeedGPIOClass; +}; -typedef struct AspeedGPIOState { +struct AspeedGPIOState { /* */ SysBusDevice parent; @@ -95,6 +92,6 @@ typedef struct AspeedGPIOState { uint32_t debounce_2; uint32_t input_mask; } sets[ASPEED_GPIO_MAX_NR_SETS]; -} AspeedGPIOState; +}; #endif /* _ASPEED_GPIO_H_ */ diff --git a/include/hw/gpio/bcm2835_gpio.h b/include/hw/gpio/bcm2835_gpio.h index b0de0a3c749dbbfa688c396f77a69823369c9b39..1c53a05090851ddaf4a2901729c6634dfcd895a1 100644 --- a/include/hw/gpio/bcm2835_gpio.h +++ b/include/hw/gpio/bcm2835_gpio.h @@ -16,8 +16,9 @@ #include "hw/sd/sd.h" #include "hw/sysbus.h" +#include "qom/object.h" -typedef struct BCM2835GpioState { +struct BCM2835GpioState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -31,10 +32,9 @@ typedef struct BCM2835GpioState { uint32_t lev0, lev1; uint8_t sd_fsel; qemu_irq out[54]; -} BCM2835GpioState; +}; #define TYPE_BCM2835_GPIO "bcm2835_gpio" -#define BCM2835_GPIO(obj) \ - OBJECT_CHECK(BCM2835GpioState, (obj), TYPE_BCM2835_GPIO) +OBJECT_DECLARE_SIMPLE_TYPE(BCM2835GpioState, BCM2835_GPIO) #endif diff --git a/include/hw/gpio/imx_gpio.h b/include/hw/gpio/imx_gpio.h index ffab437f23f27893c7cf980f845c0c967454a07e..227860b9f0abb6b78916eaee31eb492724b4bc6d 100644 --- a/include/hw/gpio/imx_gpio.h +++ b/include/hw/gpio/imx_gpio.h @@ -21,9 +21,10 @@ #define IMX_GPIO_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_IMX_GPIO "imx.gpio" -#define IMX_GPIO(obj) OBJECT_CHECK(IMXGPIOState, (obj), TYPE_IMX_GPIO) +OBJECT_DECLARE_SIMPLE_TYPE(IMXGPIOState, IMX_GPIO) #define IMX_GPIO_MEM_SIZE 0x20 @@ -39,7 +40,7 @@ #define IMX_GPIO_PIN_COUNT 32 -typedef struct IMXGPIOState { +struct IMXGPIOState { /*< private >*/ SysBusDevice parent_obj; @@ -58,6 +59,6 @@ typedef struct IMXGPIOState { qemu_irq irq[2]; qemu_irq output[IMX_GPIO_PIN_COUNT]; -} IMXGPIOState; +}; #endif /* IMX_GPIO_H */ diff --git a/include/hw/gpio/npcm7xx_gpio.h b/include/hw/gpio/npcm7xx_gpio.h new file mode 100644 index 0000000000000000000000000000000000000000..b1d771bd776c0cedac47a092068ea57f4e3d9d74 --- /dev/null +++ b/include/hw/gpio/npcm7xx_gpio.h @@ -0,0 +1,55 @@ +/* + * Nuvoton NPCM7xx General Purpose Input / Output (GPIO) + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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. + */ +#ifndef NPCM7XX_GPIO_H +#define NPCM7XX_GPIO_H + +#include "exec/memory.h" +#include "hw/sysbus.h" + +/* Number of pins managed by each controller. */ +#define NPCM7XX_GPIO_NR_PINS (32) + +/* + * Number of registers in our device state structure. Don't change this without + * incrementing the version_id in the vmstate. + */ +#define NPCM7XX_GPIO_NR_REGS (0x80 / sizeof(uint32_t)) + +typedef struct NPCM7xxGPIOState { + SysBusDevice parent; + + /* Properties to be defined by the SoC */ + uint32_t reset_pu; + uint32_t reset_pd; + uint32_t reset_osrc; + uint32_t reset_odsc; + + MemoryRegion mmio; + + qemu_irq irq; + qemu_irq output[NPCM7XX_GPIO_NR_PINS]; + + uint32_t pin_level; + uint32_t ext_level; + uint32_t ext_driven; + + uint32_t regs[NPCM7XX_GPIO_NR_REGS]; +} NPCM7xxGPIOState; + +#define TYPE_NPCM7XX_GPIO "npcm7xx-gpio" +#define NPCM7XX_GPIO(obj) \ + OBJECT_CHECK(NPCM7xxGPIOState, (obj), TYPE_NPCM7XX_GPIO) + +#endif /* NPCM7XX_GPIO_H */ diff --git a/include/hw/gpio/nrf51_gpio.h b/include/hw/gpio/nrf51_gpio.h index 1d62bbc9285867613ce9045c6214490db4fa4cf1..8f9c2f86da3c250d44aff1e8f814f2c98801b3b4 100644 --- a/include/hw/gpio/nrf51_gpio.h +++ b/include/hw/gpio/nrf51_gpio.h @@ -27,8 +27,9 @@ #define NRF51_GPIO_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_NRF51_GPIO "nrf51_soc.gpio" -#define NRF51_GPIO(obj) OBJECT_CHECK(NRF51GPIOState, (obj), TYPE_NRF51_GPIO) +OBJECT_DECLARE_SIMPLE_TYPE(NRF51GPIOState, NRF51_GPIO) #define NRF51_GPIO_PINS 32 @@ -47,7 +48,7 @@ #define NRF51_GPIO_PULLDOWN 1 #define NRF51_GPIO_PULLUP 3 -typedef struct NRF51GPIOState { +struct NRF51GPIOState { SysBusDevice parent_obj; MemoryRegion mmio; @@ -63,7 +64,7 @@ typedef struct NRF51GPIOState { uint32_t old_out_connected; qemu_irq output[NRF51_GPIO_PINS]; -} NRF51GPIOState; +}; #endif diff --git a/include/hw/riscv/sifive_gpio.h b/include/hw/gpio/sifive_gpio.h similarity index 84% rename from include/hw/riscv/sifive_gpio.h rename to include/hw/gpio/sifive_gpio.h index fce03d6c410e6d61a036493a0ac260f092d670af..fc53785c9d0ca2b068c4514c5a15b76be5774a61 100644 --- a/include/hw/riscv/sifive_gpio.h +++ b/include/hw/gpio/sifive_gpio.h @@ -1,5 +1,5 @@ /* - * sifive System-on-Chip general purpose input/output register definition + * SiFive System-on-Chip general purpose input/output register definition * * Copyright 2019 AdaCore * @@ -10,12 +10,17 @@ * This code is licensed under the GPL version 2 or later. See * the COPYING file in the top-level directory. */ + #ifndef SIFIVE_GPIO_H #define SIFIVE_GPIO_H #include "hw/sysbus.h" +#include "qom/object.h" + #define TYPE_SIFIVE_GPIO "sifive_soc.gpio" -#define SIFIVE_GPIO(obj) OBJECT_CHECK(SIFIVEGPIOState, (obj), TYPE_SIFIVE_GPIO) +typedef struct SIFIVEGPIOState SIFIVEGPIOState; +DECLARE_INSTANCE_CHECKER(SIFIVEGPIOState, SIFIVE_GPIO, + TYPE_SIFIVE_GPIO) #define SIFIVE_GPIO_PINS 32 @@ -39,7 +44,7 @@ #define SIFIVE_GPIO_REG_IOF_SEL 0x03C #define SIFIVE_GPIO_REG_OUT_XOR 0x040 -typedef struct SIFIVEGPIOState { +struct SIFIVEGPIOState { SysBusDevice parent_obj; MemoryRegion mmio; @@ -67,6 +72,8 @@ typedef struct SIFIVEGPIOState { uint32_t in; uint32_t in_mask; -} SIFIVEGPIOState; + /* config */ + uint32_t ngpio; +}; -#endif +#endif /* SIFIVE_GPIO_H */ diff --git a/include/hw/hotplug.h b/include/hw/hotplug.h index 6321e292fddc0b0e611da6f3767d9b680fc674a3..e15f59c8b3c7646073e4067f298dbc88119b3867 100644 --- a/include/hw/hotplug.h +++ b/include/hw/hotplug.h @@ -16,10 +16,9 @@ #define TYPE_HOTPLUG_HANDLER "hotplug-handler" -#define HOTPLUG_HANDLER_CLASS(klass) \ - OBJECT_CLASS_CHECK(HotplugHandlerClass, (klass), TYPE_HOTPLUG_HANDLER) -#define HOTPLUG_HANDLER_GET_CLASS(obj) \ - OBJECT_GET_CLASS(HotplugHandlerClass, (obj), TYPE_HOTPLUG_HANDLER) +typedef struct HotplugHandlerClass HotplugHandlerClass; +DECLARE_CLASS_CHECKERS(HotplugHandlerClass, HOTPLUG_HANDLER, + TYPE_HOTPLUG_HANDLER) #define HOTPLUG_HANDLER(obj) \ INTERFACE_CHECK(HotplugHandler, (obj), TYPE_HOTPLUG_HANDLER) @@ -50,7 +49,7 @@ typedef void (*hotplug_fn)(HotplugHandler *plug_handler, * Used for device removal with devices that implement * asynchronous and synchronous (surprise) removal. */ -typedef struct HotplugHandlerClass { +struct HotplugHandlerClass { /* */ InterfaceClass parent; @@ -59,7 +58,7 @@ typedef struct HotplugHandlerClass { hotplug_fn plug; hotplug_fn unplug_request; hotplug_fn unplug; -} HotplugHandlerClass; +}; /** * hotplug_handler_plug: diff --git a/include/hw/hyperv/hyperv.h b/include/hw/hyperv/hyperv.h index 597381cb0100af9d18cd09571b949fd08d802f8e..a63ee0003c1befa11f6e363f3c46d85f8871de71 100644 --- a/include/hw/hyperv/hyperv.h +++ b/include/hw/hyperv/hyperv.h @@ -79,5 +79,6 @@ void hyperv_synic_add(CPUState *cs); void hyperv_synic_reset(CPUState *cs); void hyperv_synic_update(CPUState *cs, bool enable, hwaddr msg_page_addr, hwaddr event_page_addr); +bool hyperv_is_synic_enabled(void); #endif diff --git a/include/hw/hyperv/vmbus-bridge.h b/include/hw/hyperv/vmbus-bridge.h new file mode 100644 index 0000000000000000000000000000000000000000..1e5419574ee68a0d6c76bb545f8f7b35db7221cb --- /dev/null +++ b/include/hw/hyperv/vmbus-bridge.h @@ -0,0 +1,34 @@ +/* + * QEMU Hyper-V VMBus root bridge + * + * Copyright (c) 2017-2018 Virtuozzo International GmbH. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_HYPERV_VMBUS_BRIDGE_H +#define HW_HYPERV_VMBUS_BRIDGE_H + +#include "hw/sysbus.h" +#include "hw/hyperv/vmbus.h" +#include "qom/object.h" + +#define TYPE_VMBUS_BRIDGE "vmbus-bridge" + +struct VMBusBridge { + SysBusDevice parent_obj; + + uint8_t irq; + + VMBus *bus; +}; + +OBJECT_DECLARE_SIMPLE_TYPE(VMBusBridge, VMBUS_BRIDGE) + +static inline VMBusBridge *vmbus_bridge_find(void) +{ + return VMBUS_BRIDGE(object_resolve_path_type("", TYPE_VMBUS_BRIDGE, NULL)); +} + +#endif diff --git a/include/hw/hyperv/vmbus-proto.h b/include/hw/hyperv/vmbus-proto.h new file mode 100644 index 0000000000000000000000000000000000000000..4628d3b323a66a98175d141a3b89d0a783aad5d8 --- /dev/null +++ b/include/hw/hyperv/vmbus-proto.h @@ -0,0 +1,222 @@ +/* + * QEMU Hyper-V VMBus support + * + * Copyright (c) 2017-2018 Virtuozzo International GmbH. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_HYPERV_VMBUS_PROTO_H +#define HW_HYPERV_VMBUS_PROTO_H + +#define VMBUS_VERSION_WS2008 ((0 << 16) | (13)) +#define VMBUS_VERSION_WIN7 ((1 << 16) | (1)) +#define VMBUS_VERSION_WIN8 ((2 << 16) | (4)) +#define VMBUS_VERSION_WIN8_1 ((3 << 16) | (0)) +#define VMBUS_VERSION_WIN10 ((4 << 16) | (0)) +#define VMBUS_VERSION_INVAL -1 +#define VMBUS_VERSION_CURRENT VMBUS_VERSION_WIN10 + +#define VMBUS_MESSAGE_CONNECTION_ID 1 +#define VMBUS_EVENT_CONNECTION_ID 2 +#define VMBUS_MONITOR_CONNECTION_ID 3 +#define VMBUS_SINT 2 + +#define VMBUS_MSG_INVALID 0 +#define VMBUS_MSG_OFFERCHANNEL 1 +#define VMBUS_MSG_RESCIND_CHANNELOFFER 2 +#define VMBUS_MSG_REQUESTOFFERS 3 +#define VMBUS_MSG_ALLOFFERS_DELIVERED 4 +#define VMBUS_MSG_OPENCHANNEL 5 +#define VMBUS_MSG_OPENCHANNEL_RESULT 6 +#define VMBUS_MSG_CLOSECHANNEL 7 +#define VMBUS_MSG_GPADL_HEADER 8 +#define VMBUS_MSG_GPADL_BODY 9 +#define VMBUS_MSG_GPADL_CREATED 10 +#define VMBUS_MSG_GPADL_TEARDOWN 11 +#define VMBUS_MSG_GPADL_TORNDOWN 12 +#define VMBUS_MSG_RELID_RELEASED 13 +#define VMBUS_MSG_INITIATE_CONTACT 14 +#define VMBUS_MSG_VERSION_RESPONSE 15 +#define VMBUS_MSG_UNLOAD 16 +#define VMBUS_MSG_UNLOAD_RESPONSE 17 +#define VMBUS_MSG_COUNT 18 + +#define VMBUS_MESSAGE_SIZE_ALIGN sizeof(uint64_t) + +#define VMBUS_PACKET_INVALID 0x0 +#define VMBUS_PACKET_SYNCH 0x1 +#define VMBUS_PACKET_ADD_XFER_PAGESET 0x2 +#define VMBUS_PACKET_RM_XFER_PAGESET 0x3 +#define VMBUS_PACKET_ESTABLISH_GPADL 0x4 +#define VMBUS_PACKET_TEARDOWN_GPADL 0x5 +#define VMBUS_PACKET_DATA_INBAND 0x6 +#define VMBUS_PACKET_DATA_USING_XFER_PAGES 0x7 +#define VMBUS_PACKET_DATA_USING_GPADL 0x8 +#define VMBUS_PACKET_DATA_USING_GPA_DIRECT 0x9 +#define VMBUS_PACKET_CANCEL_REQUEST 0xa +#define VMBUS_PACKET_COMP 0xb +#define VMBUS_PACKET_DATA_USING_ADDITIONAL_PKT 0xc +#define VMBUS_PACKET_ADDITIONAL_DATA 0xd + +#define VMBUS_CHANNEL_USER_DATA_SIZE 120 + +#define VMBUS_OFFER_MONITOR_ALLOCATED 0x1 +#define VMBUS_OFFER_INTERRUPT_DEDICATED 0x1 + +#define VMBUS_RING_BUFFER_FEAT_PENDING_SZ (1ul << 0) + +#define VMBUS_CHANNEL_ENUMERATE_DEVICE_INTERFACE 0x1 +#define VMBUS_CHANNEL_SERVER_SUPPORTS_TRANSFER_PAGES 0x2 +#define VMBUS_CHANNEL_SERVER_SUPPORTS_GPADLS 0x4 +#define VMBUS_CHANNEL_NAMED_PIPE_MODE 0x10 +#define VMBUS_CHANNEL_LOOPBACK_OFFER 0x100 +#define VMBUS_CHANNEL_PARENT_OFFER 0x200 +#define VMBUS_CHANNEL_REQUEST_MONITORED_NOTIFICATION 0x400 +#define VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER 0x2000 + +#define VMBUS_PACKET_FLAG_REQUEST_COMPLETION 1 + +typedef struct vmbus_message_header { + uint32_t message_type; + uint32_t _padding; +} vmbus_message_header; + +typedef struct vmbus_message_initiate_contact { + vmbus_message_header header; + uint32_t version_requested; + uint32_t target_vcpu; + uint64_t interrupt_page; + uint64_t monitor_page1; + uint64_t monitor_page2; +} vmbus_message_initiate_contact; + +typedef struct vmbus_message_version_response { + vmbus_message_header header; + uint8_t version_supported; + uint8_t status; +} vmbus_message_version_response; + +typedef struct vmbus_message_offer_channel { + vmbus_message_header header; + uint8_t type_uuid[16]; + uint8_t instance_uuid[16]; + uint64_t _reserved1; + uint64_t _reserved2; + uint16_t channel_flags; + uint16_t mmio_size_mb; + uint8_t user_data[VMBUS_CHANNEL_USER_DATA_SIZE]; + uint16_t sub_channel_index; + uint16_t _reserved3; + uint32_t child_relid; + uint8_t monitor_id; + uint8_t monitor_flags; + uint16_t interrupt_flags; + uint32_t connection_id; +} vmbus_message_offer_channel; + +typedef struct vmbus_message_rescind_channel_offer { + vmbus_message_header header; + uint32_t child_relid; +} vmbus_message_rescind_channel_offer; + +typedef struct vmbus_gpa_range { + uint32_t byte_count; + uint32_t byte_offset; + uint64_t pfn_array[]; +} vmbus_gpa_range; + +typedef struct vmbus_message_gpadl_header { + vmbus_message_header header; + uint32_t child_relid; + uint32_t gpadl_id; + uint16_t range_buflen; + uint16_t rangecount; + vmbus_gpa_range range[]; +} QEMU_PACKED vmbus_message_gpadl_header; + +typedef struct vmbus_message_gpadl_body { + vmbus_message_header header; + uint32_t message_number; + uint32_t gpadl_id; + uint64_t pfn_array[]; +} vmbus_message_gpadl_body; + +typedef struct vmbus_message_gpadl_created { + vmbus_message_header header; + uint32_t child_relid; + uint32_t gpadl_id; + uint32_t status; +} vmbus_message_gpadl_created; + +typedef struct vmbus_message_gpadl_teardown { + vmbus_message_header header; + uint32_t child_relid; + uint32_t gpadl_id; +} vmbus_message_gpadl_teardown; + +typedef struct vmbus_message_gpadl_torndown { + vmbus_message_header header; + uint32_t gpadl_id; +} vmbus_message_gpadl_torndown; + +typedef struct vmbus_message_open_channel { + vmbus_message_header header; + uint32_t child_relid; + uint32_t open_id; + uint32_t ring_buffer_gpadl_id; + uint32_t target_vp; + uint32_t ring_buffer_offset; + uint8_t user_data[VMBUS_CHANNEL_USER_DATA_SIZE]; +} vmbus_message_open_channel; + +typedef struct vmbus_message_open_result { + vmbus_message_header header; + uint32_t child_relid; + uint32_t open_id; + uint32_t status; +} vmbus_message_open_result; + +typedef struct vmbus_message_close_channel { + vmbus_message_header header; + uint32_t child_relid; +} vmbus_message_close_channel; + +typedef struct vmbus_ring_buffer { + uint32_t write_index; + uint32_t read_index; + uint32_t interrupt_mask; + uint32_t pending_send_sz; + uint32_t _reserved1[12]; + uint32_t feature_bits; +} vmbus_ring_buffer; + +typedef struct vmbus_packet_hdr { + uint16_t type; + uint16_t offset_qwords; + uint16_t len_qwords; + uint16_t flags; + uint64_t transaction_id; +} vmbus_packet_hdr; + +typedef struct vmbus_pkt_gpa_direct { + uint32_t _reserved; + uint32_t rangecount; + vmbus_gpa_range range[]; +} vmbus_pkt_gpa_direct; + +typedef struct vmbus_xferpg_range { + uint32_t byte_count; + uint32_t byte_offset; +} vmbus_xferpg_range; + +typedef struct vmbus_pkt_xferpg { + uint16_t buffer_id; + uint8_t sender_owns_set; + uint8_t _reserved; + uint32_t rangecount; + vmbus_xferpg_range range[]; +} vmbus_pkt_xferpg; + +#endif diff --git a/include/hw/hyperv/vmbus.h b/include/hw/hyperv/vmbus.h new file mode 100644 index 0000000000000000000000000000000000000000..f98bea3888d42aa5b3ccea9f9b91ae1bc7d7f140 --- /dev/null +++ b/include/hw/hyperv/vmbus.h @@ -0,0 +1,229 @@ +/* + * QEMU Hyper-V VMBus + * + * Copyright (c) 2017-2018 Virtuozzo International GmbH. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_HYPERV_VMBUS_H +#define HW_HYPERV_VMBUS_H + +#include "sysemu/sysemu.h" +#include "sysemu/dma.h" +#include "hw/qdev-core.h" +#include "migration/vmstate.h" +#include "hw/hyperv/vmbus-proto.h" +#include "qemu/uuid.h" +#include "qom/object.h" + +#define TYPE_VMBUS_DEVICE "vmbus-dev" + +OBJECT_DECLARE_TYPE(VMBusDevice, VMBusDeviceClass, + VMBUS_DEVICE) + +#define TYPE_VMBUS "vmbus" +OBJECT_DECLARE_SIMPLE_TYPE(VMBus, VMBUS) + +/* + * Object wrapping a GPADL -- GPA Descriptor List -- an array of guest physical + * pages, to be used for various buffers shared between the host and the guest. + */ +typedef struct VMBusGpadl VMBusGpadl; +/* + * VMBus channel -- a pair of ring buffers for either direction, placed within + * one GPADL, and the associated notification means. + */ +typedef struct VMBusChannel VMBusChannel; +/* + * Base class for VMBus devices. Includes one or more channels. Identified by + * class GUID and instance GUID. + */ + +typedef void(*VMBusChannelNotifyCb)(struct VMBusChannel *chan); + +struct VMBusDeviceClass { + DeviceClass parent; + + QemuUUID classid; + QemuUUID instanceid; /* Fixed UUID for singleton devices */ + uint16_t channel_flags; + uint16_t mmio_size_mb; + + /* Extentions to standard device callbacks */ + void (*vmdev_realize)(VMBusDevice *vdev, Error **errp); + void (*vmdev_unrealize)(VMBusDevice *vdev); + void (*vmdev_reset)(VMBusDevice *vdev); + /* + * Calculate the number of channels based on the device properties. Called + * at realize time. + **/ + uint16_t (*num_channels)(VMBusDevice *vdev); + /* + * Device-specific actions to complete the otherwise successful process of + * opening a channel. + * Return 0 on success, -errno on failure. + */ + int (*open_channel)(VMBusChannel *chan); + /* + * Device-specific actions to perform before closing a channel. + */ + void (*close_channel)(VMBusChannel *chan); + /* + * Main device worker; invoked in response to notifications from either + * side, when there's work to do with the data in the channel ring buffers. + */ + VMBusChannelNotifyCb chan_notify_cb; +}; + +struct VMBusDevice { + DeviceState parent; + QemuUUID instanceid; + uint16_t num_channels; + VMBusChannel *channels; + AddressSpace *dma_as; +}; + +extern const VMStateDescription vmstate_vmbus_dev; + +/* + * A unit of work parsed out of a message in the receive (i.e. guest->host) + * ring buffer of a channel. It's supposed to be subclassed (through + * embedding) by the specific devices. + */ +typedef struct VMBusChanReq { + VMBusChannel *chan; + uint16_t pkt_type; + uint32_t msglen; + void *msg; + uint64_t transaction_id; + bool need_comp; + QEMUSGList sgl; +} VMBusChanReq; + +VMBusDevice *vmbus_channel_device(VMBusChannel *chan); +VMBusChannel *vmbus_device_channel(VMBusDevice *dev, uint32_t chan_idx); +uint32_t vmbus_channel_idx(VMBusChannel *chan); +bool vmbus_channel_is_open(VMBusChannel *chan); + +/* + * Notify (on guest's behalf) the host side of the channel that there's data in + * the ringbuffer to process. + */ +void vmbus_channel_notify_host(VMBusChannel *chan); + +/* + * Reserve space for a packet in the send (i.e. host->guest) ringbuffer. If + * there isn't enough room, indicate that to the guest, to be notified when it + * becomes available. + * Return 0 on success, negative errno on failure. + * The ringbuffer indices are NOT updated, the requested space indicator may. + */ +int vmbus_channel_reserve(VMBusChannel *chan, + uint32_t desclen, uint32_t msglen); + +/* + * Send a packet to the guest. The space for the packet MUST be reserved + * first. + * Return total number of bytes placed in the send ringbuffer on success, + * negative errno on failure. + * The ringbuffer indices are updated on success, and the guest is signaled if + * needed. + */ +ssize_t vmbus_channel_send(VMBusChannel *chan, uint16_t pkt_type, + void *desc, uint32_t desclen, + void *msg, uint32_t msglen, + bool need_comp, uint64_t transaction_id); + +/* + * Prepare to fetch a batch of packets from the receive ring buffer. + * Return 0 on success, negative errno on failure. + */ +int vmbus_channel_recv_start(VMBusChannel *chan); + +/* + * Shortcut for a common case of sending a simple completion packet with no + * auxiliary descriptors. + */ +ssize_t vmbus_channel_send_completion(VMBusChanReq *req, + void *msg, uint32_t msglen); + +/* + * Peek at the receive (i.e. guest->host) ring buffer and extract a unit of + * work (a device-specific subclass of VMBusChanReq) from a packet if there's + * one. + * Return an allocated buffer, containing the request of @size with filled + * VMBusChanReq at the beginning, followed by the message payload, or NULL on + * failure. + * The ringbuffer indices are NOT updated, nor is the private copy of the read + * index. + */ +void *vmbus_channel_recv_peek(VMBusChannel *chan, uint32_t size); + +/* + * Update the private copy of the read index once the preceding peek is deemed + * successful. + * The ringbuffer indices are NOT updated. + */ +void vmbus_channel_recv_pop(VMBusChannel *chan); + +/* + * Propagate the private copy of the read index into the receive ring buffer, + * and thus complete the reception of a series of packets. Notify guest if + * needed. + * Return the number of bytes popped off the receive ring buffer by the + * preceding recv_peek/recv_pop calls on success, negative errno on failure. + */ +ssize_t vmbus_channel_recv_done(VMBusChannel *chan); + +/* + * Free the request allocated by vmbus_channel_recv_peek, together with its + * fields. + */ +void vmbus_free_req(void *req); + +/* + * Find and reference a GPADL by @gpadl_id. + * If not found return NULL. + */ +VMBusGpadl *vmbus_get_gpadl(VMBusChannel *chan, uint32_t gpadl_id); + +/* + * Unreference @gpadl. If the reference count drops to zero, free it. + * @gpadl may be NULL, in which case nothing is done. + */ +void vmbus_put_gpadl(VMBusGpadl *gpadl); + +/* + * Calculate total length in bytes of @gpadl. + * @gpadl must be valid. + */ +uint32_t vmbus_gpadl_len(VMBusGpadl *gpadl); + +/* + * Copy data from @iov to @gpadl at offset @off. + * Return the number of bytes copied, or a negative status on failure. + */ +ssize_t vmbus_iov_to_gpadl(VMBusChannel *chan, VMBusGpadl *gpadl, uint32_t off, + const struct iovec *iov, size_t iov_cnt); + +/* + * Map SGList contained in the request @req, at offset @off and no more than + * @len bytes, for io in direction @dir, and populate @iov with the mapped + * iovecs. + * Return the number of iovecs mapped, or negative status on failure. + */ +int vmbus_map_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov, + unsigned iov_cnt, size_t len, size_t off); + +/* + * Unmap *iov mapped with vmbus_map_sgl, marking the number of bytes @accessed. + */ +void vmbus_unmap_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov, + unsigned iov_cnt, size_t accessed); + +void vmbus_save_req(QEMUFile *f, VMBusChanReq *req); +void *vmbus_load_req(QEMUFile *f, VMBusDevice *dev, uint32_t size); + +#endif diff --git a/include/hw/i2c/arm_sbcon_i2c.h b/include/hw/i2c/arm_sbcon_i2c.h new file mode 100644 index 0000000000000000000000000000000000000000..ad96781e7a8421ff6d359af7fbbf213e248126f8 --- /dev/null +++ b/include/hw/i2c/arm_sbcon_i2c.h @@ -0,0 +1,37 @@ +/* + * ARM SBCon two-wire serial bus interface (I2C bitbang) + * a.k.a. + * ARM Versatile I2C controller + * + * Copyright (c) 2006-2007 CodeSourcery. + * Copyright (c) 2012 Oskar Andero + * Copyright (C) 2020 Philippe Mathieu-DaudĂ© + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef HW_I2C_ARM_SBCON_H +#define HW_I2C_ARM_SBCON_H + +#include "hw/sysbus.h" +#include "hw/i2c/bitbang_i2c.h" +#include "qom/object.h" + +#define TYPE_VERSATILE_I2C "versatile_i2c" +#define TYPE_ARM_SBCON_I2C TYPE_VERSATILE_I2C + +typedef struct ArmSbconI2CState ArmSbconI2CState; +DECLARE_INSTANCE_CHECKER(ArmSbconI2CState, ARM_SBCON_I2C, + TYPE_ARM_SBCON_I2C) + +struct ArmSbconI2CState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + MemoryRegion iomem; + bitbang_i2c_interface bitbang; + int out; + int in; +}; + +#endif /* HW_I2C_ARM_SBCON_H */ diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h index f1b9e5bf91e2c9645a0765f920dce4c1e9e3793c..565f83306624eca8a946d83b2884a43d34433946 100644 --- a/include/hw/i2c/aspeed_i2c.h +++ b/include/hw/i2c/aspeed_i2c.h @@ -23,13 +23,13 @@ #include "hw/i2c/i2c.h" #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_ASPEED_I2C "aspeed.i2c" #define TYPE_ASPEED_2400_I2C TYPE_ASPEED_I2C "-ast2400" #define TYPE_ASPEED_2500_I2C TYPE_ASPEED_I2C "-ast2500" #define TYPE_ASPEED_2600_I2C TYPE_ASPEED_I2C "-ast2600" -#define ASPEED_I2C(obj) \ - OBJECT_CHECK(AspeedI2CState, (obj), TYPE_ASPEED_I2C) +OBJECT_DECLARE_TYPE(AspeedI2CState, AspeedI2CClass, ASPEED_I2C) #define ASPEED_I2C_NR_BUSSES 16 #define ASPEED_I2C_MAX_POOL_SIZE 0x800 @@ -56,7 +56,7 @@ typedef struct AspeedI2CBus { uint32_t dma_len; } AspeedI2CBus; -typedef struct AspeedI2CState { +struct AspeedI2CState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -70,14 +70,10 @@ typedef struct AspeedI2CState { AspeedI2CBus busses[ASPEED_I2C_NR_BUSSES]; MemoryRegion *dram_mr; AddressSpace dram_as; -} AspeedI2CState; +}; -#define ASPEED_I2C_CLASS(klass) \ - OBJECT_CLASS_CHECK(AspeedI2CClass, (klass), TYPE_ASPEED_I2C) -#define ASPEED_I2C_GET_CLASS(obj) \ - OBJECT_GET_CLASS(AspeedI2CClass, (obj), TYPE_ASPEED_I2C) -typedef struct AspeedI2CClass { +struct AspeedI2CClass { SysBusDeviceClass parent_class; uint8_t num_busses; @@ -91,8 +87,8 @@ typedef struct AspeedI2CClass { bool check_sram; bool has_dma; -} AspeedI2CClass; +}; -I2CBus *aspeed_i2c_get_bus(DeviceState *dev, int busnr); +I2CBus *aspeed_i2c_get_bus(AspeedI2CState *s, int busnr); #endif /* ASPEED_I2C_H */ diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h index 41172115652b8219811eb6fe4835f8a3a32e8a22..277dd9f2d6d2f54526c4781f7d7cfb8b6f1d279e 100644 --- a/include/hw/i2c/i2c.h +++ b/include/hw/i2c/i2c.h @@ -2,6 +2,7 @@ #define QEMU_I2C_H #include "hw/qdev-core.h" +#include "qom/object.h" /* The QEMU I2C implementation only supports simple transfers that complete immediately. It does not support slave devices that need to be able to @@ -15,17 +16,12 @@ enum i2c_event { I2C_NACK /* Masker NACKed a receive byte. */ }; -typedef struct I2CSlave I2CSlave; #define TYPE_I2C_SLAVE "i2c-slave" -#define I2C_SLAVE(obj) \ - OBJECT_CHECK(I2CSlave, (obj), TYPE_I2C_SLAVE) -#define I2C_SLAVE_CLASS(klass) \ - OBJECT_CLASS_CHECK(I2CSlaveClass, (klass), TYPE_I2C_SLAVE) -#define I2C_SLAVE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(I2CSlaveClass, (obj), TYPE_I2C_SLAVE) - -typedef struct I2CSlaveClass { +OBJECT_DECLARE_TYPE(I2CSlave, I2CSlaveClass, + I2C_SLAVE) + +struct I2CSlaveClass { DeviceClass parent_class; /* Master to slave. Returns non-zero for a NAK, 0 for success. */ @@ -43,7 +39,7 @@ typedef struct I2CSlaveClass { * return code is not used and should be zero. */ int (*event)(I2CSlave *s, enum i2c_event event); -} I2CSlaveClass; +}; struct I2CSlave { DeviceState qdev; @@ -53,7 +49,7 @@ struct I2CSlave { }; #define TYPE_I2C_BUS "i2c-bus" -#define I2C_BUS(obj) OBJECT_CHECK(I2CBus, (obj), TYPE_I2C_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(I2CBus, I2C_BUS) typedef struct I2CNode I2CNode; @@ -79,7 +75,57 @@ int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send); int i2c_send(I2CBus *bus, uint8_t data); uint8_t i2c_recv(I2CBus *bus); -DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr); +/** + * Create an I2C slave device on the heap. + * @name: a device type name + * @addr: I2C address of the slave when put on a bus + * + * This only initializes the device state structure and allows + * properties to be set. Type @name must exist. The device still + * needs to be realized. See qdev-core.h. + */ +I2CSlave *i2c_slave_new(const char *name, uint8_t addr); + +/** + * Create and realize an I2C slave device on the heap. + * @bus: I2C bus to put it on + * @name: I2C slave device type name + * @addr: I2C address of the slave when put on a bus + * + * Create the device state structure, initialize it, put it on the + * specified @bus, and drop the reference to it (the device is realized). + */ +I2CSlave *i2c_slave_create_simple(I2CBus *bus, const char *name, uint8_t addr); + +/** + * Realize and drop a reference an I2C slave device + * @dev: I2C slave device to realize + * @bus: I2C bus to put it on + * @addr: I2C address of the slave on the bus + * @errp: pointer to NULL initialized error object + * + * Returns: %true on success, %false on failure. + * + * Call 'realize' on @dev, put it on the specified @bus, and drop the + * reference to it. + * + * This function is useful if you have created @dev via qdev_new(), + * i2c_slave_new() or i2c_slave_try_new() (which take a reference to + * the device it returns to you), so that you can set properties on it + * before realizing it. If you don't need to set properties then + * i2c_slave_create_simple() is probably better (as it does the create, + * init and realize in one step). + * + * If you are embedding the I2C slave into another QOM device and + * initialized it via some variant on object_initialize_child() then + * do not use this function, because that family of functions arrange + * for the only reference to the child device to be held by the parent + * via the child<> property, and so the reference-count-drop done here + * would be incorrect. (Instead you would want i2c_slave_realize(), + * which doesn't currently exist but would be trivial to create if we + * had any code that wanted it.) + */ +bool i2c_slave_realize_and_unref(I2CSlave *dev, I2CBus *bus, Error **errp); /* lm832x.c */ void lm832x_key_event(DeviceState *dev, int key, int state); diff --git a/include/hw/i2c/imx_i2c.h b/include/hw/i2c/imx_i2c.h index 7c73a1fa2895a803358e0ce9ec61bf54ad8c0a8c..e4f91339f581487a834186ab87c51830fc07c7d5 100644 --- a/include/hw/i2c/imx_i2c.h +++ b/include/hw/i2c/imx_i2c.h @@ -22,9 +22,10 @@ #define IMX_I2C_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_IMX_I2C "imx.i2c" -#define IMX_I2C(obj) OBJECT_CHECK(IMXI2CState, (obj), TYPE_IMX_I2C) +OBJECT_DECLARE_SIMPLE_TYPE(IMXI2CState, IMX_I2C) #define IMX_I2C_MEM_SIZE 0x14 @@ -65,7 +66,7 @@ #define ADDR_RESET 0xFF00 -typedef struct IMXI2CState { +struct IMXI2CState { /*< private >*/ SysBusDevice parent_obj; @@ -82,6 +83,6 @@ typedef struct IMXI2CState { uint16_t i2sr; uint16_t i2dr_read; uint16_t i2dr_write; -} IMXI2CState; +}; #endif /* IMX_I2C_H */ diff --git a/include/hw/i2c/microbit_i2c.h b/include/hw/i2c/microbit_i2c.h index 2bff36680ccaf03200eae5e95e538dc0592542a1..3c29e09bf38bfcf6f9ba09f92b2924ff533d19ff 100644 --- a/include/hw/i2c/microbit_i2c.h +++ b/include/hw/i2c/microbit_i2c.h @@ -13,6 +13,7 @@ #include "hw/sysbus.h" #include "hw/arm/nrf51.h" +#include "qom/object.h" #define NRF51_TWI_TASK_STARTRX 0x000 #define NRF51_TWI_TASK_STARTTX 0x008 @@ -26,17 +27,16 @@ #define NRF51_TWI_REG_ADDRESS 0x588 #define TYPE_MICROBIT_I2C "microbit.i2c" -#define MICROBIT_I2C(obj) \ - OBJECT_CHECK(MicrobitI2CState, (obj), TYPE_MICROBIT_I2C) +OBJECT_DECLARE_SIMPLE_TYPE(MicrobitI2CState, MICROBIT_I2C) #define MICROBIT_I2C_NREGS (NRF51_PERIPHERAL_SIZE / sizeof(uint32_t)) -typedef struct { +struct MicrobitI2CState { SysBusDevice parent_obj; MemoryRegion iomem; uint32_t regs[MICROBIT_I2C_NREGS]; uint32_t read_idx; -} MicrobitI2CState; +}; #endif /* MICROBIT_I2C_H */ diff --git a/include/hw/i2c/ppc4xx_i2c.h b/include/hw/i2c/ppc4xx_i2c.h index f6f837fbec00aae240a8cf08a1075b84ea7d41ae..4e882fa3c80616ea55e430a688507441e314e9b4 100644 --- a/include/hw/i2c/ppc4xx_i2c.h +++ b/include/hw/i2c/ppc4xx_i2c.h @@ -29,11 +29,12 @@ #include "hw/sysbus.h" #include "hw/i2c/bitbang_i2c.h" +#include "qom/object.h" #define TYPE_PPC4xx_I2C "ppc4xx-i2c" -#define PPC4xx_I2C(obj) OBJECT_CHECK(PPC4xxI2CState, (obj), TYPE_PPC4xx_I2C) +OBJECT_DECLARE_SIMPLE_TYPE(PPC4xxI2CState, PPC4xx_I2C) -typedef struct PPC4xxI2CState { +struct PPC4xxI2CState { /*< private >*/ SysBusDevice parent_obj; @@ -57,6 +58,6 @@ typedef struct PPC4xxI2CState { uint8_t xfrcnt; uint8_t xtcntlss; uint8_t directcntl; -} PPC4xxI2CState; +}; #endif /* PPC4XX_I2C_H */ diff --git a/include/hw/i2c/smbus_slave.h b/include/hw/i2c/smbus_slave.h index ebe068304e5c48543d6f2269b8eec8c8755cf448..86bfe0a79e36c0297309c579f837edc279b003a1 100644 --- a/include/hw/i2c/smbus_slave.h +++ b/include/hw/i2c/smbus_slave.h @@ -26,19 +26,14 @@ #define HW_SMBUS_SLAVE_H #include "hw/i2c/i2c.h" +#include "qom/object.h" #define TYPE_SMBUS_DEVICE "smbus-device" -#define SMBUS_DEVICE(obj) \ - OBJECT_CHECK(SMBusDevice, (obj), TYPE_SMBUS_DEVICE) -#define SMBUS_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(SMBusDeviceClass, (klass), TYPE_SMBUS_DEVICE) -#define SMBUS_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SMBusDeviceClass, (obj), TYPE_SMBUS_DEVICE) +OBJECT_DECLARE_TYPE(SMBusDevice, SMBusDeviceClass, + SMBUS_DEVICE) -typedef struct SMBusDevice SMBusDevice; -typedef struct SMBusDeviceClass -{ +struct SMBusDeviceClass { I2CSlaveClass parent_class; /* @@ -67,7 +62,7 @@ typedef struct SMBusDeviceClass * return 0xff in that case. */ uint8_t (*receive_byte)(SMBusDevice *dev); -} SMBusDeviceClass; +}; #define SMBUS_DATA_MAX_LEN 34 /* command + len + 32 bytes of data. */ diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h index b04bdd947f8b08dc9a432adb60cefffec690aad8..c175e7e718165d81824f2b3348ee09ee8637fd86 100644 --- a/include/hw/i386/apic_internal.h +++ b/include/hw/i386/apic_internal.h @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,6 +25,7 @@ #include "exec/memory.h" #include "qemu/timer.h" #include "target/i386/cpu-qom.h" +#include "qom/object.h" /* APIC Local Vector Table */ #define APIC_LVT_TIMER 0 @@ -125,15 +126,11 @@ typedef struct APICCommonState APICCommonState; #define TYPE_APIC_COMMON "apic-common" -#define APIC_COMMON(obj) \ - OBJECT_CHECK(APICCommonState, (obj), TYPE_APIC_COMMON) -#define APIC_COMMON_CLASS(klass) \ - OBJECT_CLASS_CHECK(APICCommonClass, (klass), TYPE_APIC_COMMON) -#define APIC_COMMON_GET_CLASS(obj) \ - OBJECT_GET_CLASS(APICCommonClass, (obj), TYPE_APIC_COMMON) - -typedef struct APICCommonClass -{ +typedef struct APICCommonClass APICCommonClass; +DECLARE_OBJ_CHECKERS(APICCommonState, APICCommonClass, + APIC_COMMON, TYPE_APIC_COMMON) + +struct APICCommonClass { DeviceClass parent_class; DeviceRealize realize; @@ -151,7 +148,7 @@ typedef struct APICCommonClass * device, but it's convenient to have it here for now. */ void (*send_msi)(MSIMessage *msi); -} APICCommonClass; +}; struct APICCommonState { /*< private >*/ @@ -211,6 +208,7 @@ void vapic_report_tpr_access(DeviceState *dev, CPUState *cpu, target_ulong ip, TPRAccess access); int apic_get_ppr(APICCommonState *s); +uint32_t apic_get_current_count(APICCommonState *s); static inline void apic_set_bit(uint32_t *tab, int index) { diff --git a/include/hw/i386/ich9.h b/include/hw/i386/ich9.h index a98d10b252dffe79530a39f7ca2dfc8dd51366e8..d1ea000d3ddbf3138e5c5d7d1222d9f390719915 100644 --- a/include/hw/i386/ich9.h +++ b/include/hw/i386/ich9.h @@ -11,6 +11,7 @@ #include "hw/acpi/acpi.h" #include "hw/acpi/ich9.h" #include "hw/pci/pci_bus.h" +#include "qom/object.h" void ich9_lpc_set_irq(void *opaque, int irq_num, int level); int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx); @@ -23,10 +24,9 @@ void ich9_generate_smi(void); #define ICH9_CC_SIZE (16 * 1024) /* 16KB. Chipset configuration registers */ #define TYPE_ICH9_LPC_DEVICE "ICH9-LPC" -#define ICH9_LPC_DEVICE(obj) \ - OBJECT_CHECK(ICH9LPCState, (obj), TYPE_ICH9_LPC_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(ICH9LPCState, ICH9_LPC_DEVICE) -typedef struct ICH9LPCState { +struct ICH9LPCState { /* ICH9 LPC PCI to ISA bridge */ PCIDevice d; @@ -77,7 +77,7 @@ typedef struct ICH9LPCState { Notifier machine_ready; qemu_irq gsi[GSI_NUM_PINS]; -} ICH9LPCState; +}; #define Q35_MASK(bit, ms_bit, ls_bit) \ ((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1))) @@ -144,6 +144,7 @@ typedef struct ICH9LPCState { #define ICH9_LPC_PMBASE_BASE_ADDRESS_MASK Q35_MASK(32, 15, 7) #define ICH9_LPC_PMBASE_RTE 0x1 #define ICH9_LPC_PMBASE_DEFAULT 0x1 + #define ICH9_LPC_ACPI_CTRL 0x44 #define ICH9_LPC_ACPI_CTRL_ACPI_EN 0x80 #define ICH9_LPC_ACPI_CTRL_SCI_IRQ_SEL_MASK Q35_MASK(8, 2, 0) @@ -245,7 +246,11 @@ typedef struct ICH9LPCState { #define ICH9_SMB_HST_D1 0x06 #define ICH9_SMB_HOST_BLOCK_DB 0x07 +#define ICH9_LPC_SMI_NEGOTIATED_FEAT_PROP "x-smi-negotiated-features" + /* bit positions used in fw_cfg SMI feature negotiation */ #define ICH9_LPC_SMI_F_BROADCAST_BIT 0 +#define ICH9_LPC_SMI_F_CPU_HOTPLUG_BIT 1 +#define ICH9_LPC_SMI_F_CPU_HOT_UNPLUG_BIT 2 #endif /* HW_ICH9_H */ diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h index 3870052f5f0985e35ce54135fdd75f2bbf3cdcca..41783ee46d5eec7ea5f68e797a53c46650b07cba 100644 --- a/include/hw/i386/intel_iommu.h +++ b/include/hw/i386/intel_iommu.h @@ -24,10 +24,10 @@ #include "hw/i386/x86-iommu.h" #include "qemu/iova-tree.h" +#include "qom/object.h" #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu" -#define INTEL_IOMMU_DEVICE(obj) \ - OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(IntelIOMMUState, INTEL_IOMMU_DEVICE) #define TYPE_INTEL_IOMMU_MEMORY_REGION "intel-iommu-iommu-memory-region" @@ -56,7 +56,6 @@ typedef struct VTDContextEntry VTDContextEntry; typedef struct VTDContextCacheEntry VTDContextCacheEntry; -typedef struct IntelIOMMUState IntelIOMMUState; typedef struct VTDAddressSpace VTDAddressSpace; typedef struct VTDIOTLBEntry VTDIOTLBEntry; typedef struct VTDBus VTDBus; diff --git a/include/hw/i386/ioapic.h b/include/hw/i386/ioapic.h index 59fcb158a7342f7ae9698b7e3ef4513197aa8c93..06bfaaeac6b86ca606099b4307be86162425b239 100644 --- a/include/hw/i386/ioapic.h +++ b/include/hw/i386/ioapic.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/hw/i386/ioapic_internal.h b/include/hw/i386/ioapic_internal.h index fe06938bda47f7d95fc3634222ad78918cf04a4b..0f9002a2c23e4a291d04d7eaa6a7d2591462cbbb 100644 --- a/include/hw/i386/ioapic_internal.h +++ b/include/hw/i386/ioapic_internal.h @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,6 +25,7 @@ #include "exec/memory.h" #include "hw/sysbus.h" #include "qemu/notify.h" +#include "qom/object.h" #define MAX_IOAPICS 1 @@ -81,24 +82,18 @@ #define IOAPIC_VER_ENTRIES_SHIFT 16 -typedef struct IOAPICCommonState IOAPICCommonState; #define TYPE_IOAPIC_COMMON "ioapic-common" -#define IOAPIC_COMMON(obj) \ - OBJECT_CHECK(IOAPICCommonState, (obj), TYPE_IOAPIC_COMMON) -#define IOAPIC_COMMON_CLASS(klass) \ - OBJECT_CLASS_CHECK(IOAPICCommonClass, (klass), TYPE_IOAPIC_COMMON) -#define IOAPIC_COMMON_GET_CLASS(obj) \ - OBJECT_GET_CLASS(IOAPICCommonClass, (obj), TYPE_IOAPIC_COMMON) - -typedef struct IOAPICCommonClass { +OBJECT_DECLARE_TYPE(IOAPICCommonState, IOAPICCommonClass, IOAPIC_COMMON) + +struct IOAPICCommonClass { SysBusDeviceClass parent_class; DeviceRealize realize; DeviceUnrealize unrealize; void (*pre_save)(IOAPICCommonState *s); void (*post_load)(IOAPICCommonState *s); -} IOAPICCommonClass; +}; struct IOAPICCommonState { SysBusDevice busdev; diff --git a/include/hw/i386/microvm.h b/include/hw/i386/microvm.h index ba68d1f22bb3d63a827b9ca1412ef34de935c9e1..0fc216007777b5ed7a2cb71cf6fb7f82d8f12653 100644 --- a/include/hw/i386/microvm.h +++ b/include/hw/i386/microvm.h @@ -24,48 +24,87 @@ #include "hw/boards.h" #include "hw/i386/x86.h" +#include "hw/acpi/acpi_dev_interface.h" +#include "hw/pci-host/gpex.h" +#include "qom/object.h" + +/* + * IRQ | pc | microvm (acpi=on) + * --------+------------+------------------ + * 0 | pit | + * 1 | kbd | + * 2 | cascade | + * 3 | serial 1 | + * 4 | serial 0 | serial + * 5 | - | + * 6 | floppy | + * 7 | parallel | + * 8 | rtc | rtc (rtc=on) + * 9 | acpi | acpi (ged) + * 10 | pci lnk | xhci (usb=on) + * 11 | pci lnk | + * 12 | ps2 | pcie + * 13 | fpu | pcie + * 14 | ide 0 | pcie + * 15 | ide 1 | pcie + * 16-23 | pci gsi | virtio + */ /* Platform virtio definitions */ -#define VIRTIO_MMIO_BASE 0xc0000000 -#define VIRTIO_IRQ_BASE 5 +#define VIRTIO_MMIO_BASE 0xfeb00000 #define VIRTIO_NUM_TRANSPORTS 8 #define VIRTIO_CMDLINE_MAXLEN 64 +#define GED_MMIO_BASE 0xfea00000 +#define GED_MMIO_BASE_MEMHP (GED_MMIO_BASE + 0x100) +#define GED_MMIO_BASE_REGS (GED_MMIO_BASE + 0x200) +#define GED_MMIO_IRQ 9 + +#define MICROVM_XHCI_BASE 0xfe900000 +#define MICROVM_XHCI_IRQ 10 + +#define PCIE_MMIO_BASE 0xc0000000 +#define PCIE_MMIO_SIZE 0x20000000 +#define PCIE_ECAM_BASE 0xe0000000 +#define PCIE_ECAM_SIZE 0x10000000 +#define PCIE_IRQ_BASE 12 + /* Machine type options */ #define MICROVM_MACHINE_PIT "pit" #define MICROVM_MACHINE_PIC "pic" #define MICROVM_MACHINE_RTC "rtc" +#define MICROVM_MACHINE_PCIE "pcie" #define MICROVM_MACHINE_ISA_SERIAL "isa-serial" #define MICROVM_MACHINE_OPTION_ROMS "x-option-roms" #define MICROVM_MACHINE_AUTO_KERNEL_CMDLINE "auto-kernel-cmdline" -typedef struct { +struct MicrovmMachineClass { X86MachineClass parent; HotplugHandler *(*orig_hotplug_handler)(MachineState *machine, DeviceState *dev); -} MicrovmMachineClass; +}; -typedef struct { +struct MicrovmMachineState { X86MachineState parent; /* Machine type options */ OnOffAuto pic; OnOffAuto pit; OnOffAuto rtc; + OnOffAuto pcie; bool isa_serial; bool option_roms; bool auto_kernel_cmdline; /* Machine state */ + uint32_t virtio_irq_base; bool kernel_cmdline_fixed; -} MicrovmMachineState; + Notifier machine_done; + Notifier powerdown_req; + struct GPEXConfig gpex; +}; #define TYPE_MICROVM_MACHINE MACHINE_TYPE_NAME("microvm") -#define MICROVM_MACHINE(obj) \ - OBJECT_CHECK(MicrovmMachineState, (obj), TYPE_MICROVM_MACHINE) -#define MICROVM_MACHINE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(MicrovmMachineClass, obj, TYPE_MICROVM_MACHINE) -#define MICROVM_MACHINE_CLASS(class) \ - OBJECT_CLASS_CHECK(MicrovmMachineClass, class, TYPE_MICROVM_MACHINE) +OBJECT_DECLARE_TYPE(MicrovmMachineState, MicrovmMachineClass, MICROVM_MACHINE) #endif diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 8d764f965cd399a2e4f09b7f777884e5e4a52a49..911e4600970c36de9371a46601c694c246e7984e 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -10,6 +10,7 @@ #include "hw/acpi/acpi_dev_interface.h" #include "hw/hotplug.h" +#include "qom/object.h" #define HPET_INTCAP "hpet-intcap" @@ -19,7 +20,7 @@ * @boot_cpus: number of present VCPUs * @smp_dies: number of dies per one package */ -struct PCMachineState { +typedef struct PCMachineState { /*< private >*/ X86MachineState parent_obj; @@ -29,18 +30,20 @@ struct PCMachineState { Notifier machine_done; /* Pointers to devices and objects: */ - HotplugHandler *acpi_dev; PCIBus *bus; I2CBus *smbus; PFlashCFI01 *flash[2]; + ISADevice *pcspk; /* Configuration options: */ + uint64_t max_ram_below_4g; OnOffAuto vmport; bool acpi_build_enabled; bool smbus_enabled; bool sata_enabled; bool pit_enabled; + bool hpet_enabled; /* NUMA information: */ uint64_t numa_nodes; @@ -48,9 +51,10 @@ struct PCMachineState { /* ACPI Memory hotplug IO base address */ hwaddr memhp_io_base; -}; +} PCMachineState; #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device" +#define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g" #define PC_MACHINE_DEVMEM_REGION_SIZE "device-memory-region-size" #define PC_MACHINE_VMPORT "vmport" #define PC_MACHINE_SMBUS "smbus" @@ -73,7 +77,7 @@ struct PCMachineState { * way we can use 1GByte pages in the host. * */ -typedef struct PCMachineClass { +struct PCMachineClass { /*< private >*/ X86MachineClass parent_class; @@ -115,15 +119,13 @@ typedef struct PCMachineClass { /* use PVH to load kernels that support this feature */ bool pvh_enabled; -} PCMachineClass; + + /* create kvmclock device even when KVM PV features are not exposed */ + bool kvmclock_create_always; +}; #define TYPE_PC_MACHINE "generic-pc-machine" -#define PC_MACHINE(obj) \ - OBJECT_CHECK(PCMachineState, (obj), TYPE_PC_MACHINE) -#define PC_MACHINE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PCMachineClass, (obj), TYPE_PC_MACHINE) -#define PC_MACHINE_CLASS(klass) \ - OBJECT_CLASS_CHECK(PCMachineClass, (klass), TYPE_PC_MACHINE) +OBJECT_DECLARE_TYPE(PCMachineState, PCMachineClass, PC_MACHINE) /* ioapic.c */ @@ -134,7 +136,6 @@ extern int fd_bootchk; void pc_acpi_smi_interrupt(void *opaque, int irq, int level); -void pc_hot_add_cpu(MachineState *ms, const int64_t id, Error **errp); void pc_smp_parse(MachineState *ms, QemuOpts *opts); void pc_guest_info_init(PCMachineState *pcms); @@ -158,11 +159,10 @@ void pc_memory_init(PCMachineState *pcms, MemoryRegion **ram_memory); uint64_t pc_pci_hole64_start(void); DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus); -void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, +void pc_basic_device_init(struct PCMachineState *pcms, + ISABus *isa_bus, qemu_irq *gsi, ISADevice **rtc_state, bool create_fdctrl, - bool no_vmport, - bool has_pit, uint32_t hpet_irqs); void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd); void pc_cmos_init(PCMachineState *pcms, @@ -176,7 +176,6 @@ typedef void (*cpu_set_smm_t)(int smm, void *arg); void pc_i8259_create(ISABus *isa_bus, qemu_irq *i8259_irqs); ISADevice *pc_find_fdc0(void); -int cmos_get_fd_drive_type(FloppyDriveType fd0); /* port92.c */ #define PORT92_A20_LINE "a20" @@ -185,12 +184,16 @@ int cmos_get_fd_drive_type(FloppyDriveType fd0); /* pc_sysfw.c */ void pc_system_flash_create(PCMachineState *pcms); +void pc_system_flash_cleanup_unused(PCMachineState *pcms); void pc_system_firmware_init(PCMachineState *pcms, MemoryRegion *rom_memory); /* acpi-build.c */ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid, const CPUArchIdList *apic_ids, GArray *entry); +extern GlobalProperty pc_compat_5_1[]; +extern const size_t pc_compat_5_1_len; + extern GlobalProperty pc_compat_5_0[]; extern const size_t pc_compat_5_0_len; diff --git a/include/hw/i386/topology.h b/include/hw/i386/topology.h index 07239f95f41a5b1874cd95172a41f84bc3c8d85a..81573f6cfde011a477aaab67030ede3a7b8cf5a1 100644 --- a/include/hw/i386/topology.h +++ b/include/hw/i386/topology.h @@ -47,14 +47,12 @@ typedef uint32_t apic_id_t; typedef struct X86CPUTopoIDs { unsigned pkg_id; - unsigned node_id; unsigned die_id; unsigned core_id; unsigned smt_id; } X86CPUTopoIDs; typedef struct X86CPUTopoInfo { - unsigned nodes_per_pkg; unsigned dies_per_pkg; unsigned cores_per_die; unsigned threads_per_core; @@ -89,11 +87,6 @@ static inline unsigned apicid_die_width(X86CPUTopoInfo *topo_info) return apicid_bitwidth_for_count(topo_info->dies_per_pkg); } -/* Bit width of the node_id field per socket */ -static inline unsigned apicid_node_width_epyc(X86CPUTopoInfo *topo_info) -{ - return apicid_bitwidth_for_count(MAX(topo_info->nodes_per_pkg, 1)); -} /* Bit offset of the Core_ID field */ static inline unsigned apicid_core_offset(X86CPUTopoInfo *topo_info) @@ -114,100 +107,6 @@ static inline unsigned apicid_pkg_offset(X86CPUTopoInfo *topo_info) return apicid_die_offset(topo_info) + apicid_die_width(topo_info); } -#define NODE_ID_OFFSET 3 /* Minimum node_id offset if numa configured */ - -/* - * Bit offset of the node_id field - * - * Make sure nodes_per_pkg > 0 if numa configured else zero. - */ -static inline unsigned apicid_node_offset_epyc(X86CPUTopoInfo *topo_info) -{ - unsigned offset = apicid_die_offset(topo_info) + - apicid_die_width(topo_info); - - if (topo_info->nodes_per_pkg) { - return MAX(NODE_ID_OFFSET, offset); - } else { - return offset; - } -} - -/* Bit offset of the Pkg_ID (socket ID) field */ -static inline unsigned apicid_pkg_offset_epyc(X86CPUTopoInfo *topo_info) -{ - return apicid_node_offset_epyc(topo_info) + - apicid_node_width_epyc(topo_info); -} - -/* - * Make APIC ID for the CPU based on Pkg_ID, Core_ID, SMT_ID - * - * The caller must make sure core_id < nr_cores and smt_id < nr_threads. - */ -static inline apic_id_t -x86_apicid_from_topo_ids_epyc(X86CPUTopoInfo *topo_info, - const X86CPUTopoIDs *topo_ids) -{ - return (topo_ids->pkg_id << apicid_pkg_offset_epyc(topo_info)) | - (topo_ids->node_id << apicid_node_offset_epyc(topo_info)) | - (topo_ids->die_id << apicid_die_offset(topo_info)) | - (topo_ids->core_id << apicid_core_offset(topo_info)) | - topo_ids->smt_id; -} - -static inline void x86_topo_ids_from_idx_epyc(X86CPUTopoInfo *topo_info, - unsigned cpu_index, - X86CPUTopoIDs *topo_ids) -{ - unsigned nr_nodes = MAX(topo_info->nodes_per_pkg, 1); - unsigned nr_dies = topo_info->dies_per_pkg; - unsigned nr_cores = topo_info->cores_per_die; - unsigned nr_threads = topo_info->threads_per_core; - unsigned cores_per_node = DIV_ROUND_UP((nr_dies * nr_cores * nr_threads), - nr_nodes); - - topo_ids->pkg_id = cpu_index / (nr_dies * nr_cores * nr_threads); - topo_ids->node_id = (cpu_index / cores_per_node) % nr_nodes; - topo_ids->die_id = cpu_index / (nr_cores * nr_threads) % nr_dies; - topo_ids->core_id = cpu_index / nr_threads % nr_cores; - topo_ids->smt_id = cpu_index % nr_threads; -} - -/* - * Calculate thread/core/package IDs for a specific topology, - * based on APIC ID - */ -static inline void x86_topo_ids_from_apicid_epyc(apic_id_t apicid, - X86CPUTopoInfo *topo_info, - X86CPUTopoIDs *topo_ids) -{ - topo_ids->smt_id = apicid & - ~(0xFFFFFFFFUL << apicid_smt_width(topo_info)); - topo_ids->core_id = - (apicid >> apicid_core_offset(topo_info)) & - ~(0xFFFFFFFFUL << apicid_core_width(topo_info)); - topo_ids->die_id = - (apicid >> apicid_die_offset(topo_info)) & - ~(0xFFFFFFFFUL << apicid_die_width(topo_info)); - topo_ids->node_id = - (apicid >> apicid_node_offset_epyc(topo_info)) & - ~(0xFFFFFFFFUL << apicid_node_width_epyc(topo_info)); - topo_ids->pkg_id = apicid >> apicid_pkg_offset_epyc(topo_info); -} - -/* - * Make APIC ID for the CPU 'cpu_index' - * - * 'cpu_index' is a sequential, contiguous ID for the CPU. - */ -static inline apic_id_t x86_apicid_from_cpu_idx_epyc(X86CPUTopoInfo *topo_info, - unsigned cpu_index) -{ - X86CPUTopoIDs topo_ids; - x86_topo_ids_from_idx_epyc(topo_info, cpu_index, &topo_ids); - return x86_apicid_from_topo_ids_epyc(topo_info, &topo_ids); -} /* Make APIC ID for the CPU based on Pkg_ID, Core_ID, SMT_ID * * The caller must make sure core_id < nr_cores and smt_id < nr_threads. diff --git a/include/hw/i386/vmport.h b/include/hw/i386/vmport.h new file mode 100644 index 0000000000000000000000000000000000000000..8f5e27c6f5956ab82df147328c8b278ef7e8e797 --- /dev/null +++ b/include/hw/i386/vmport.h @@ -0,0 +1,28 @@ +#ifndef HW_VMPORT_H +#define HW_VMPORT_H + +#include "hw/isa/isa.h" + +#define TYPE_VMPORT "vmport" +typedef uint32_t VMPortReadFunc(void *opaque, uint32_t address); + +typedef enum { + VMPORT_CMD_GETVERSION = 10, + VMPORT_CMD_GETBIOSUUID = 19, + VMPORT_CMD_GETRAMSIZE = 20, + VMPORT_CMD_VMMOUSE_DATA = 39, + VMPORT_CMD_VMMOUSE_STATUS = 40, + VMPORT_CMD_VMMOUSE_COMMAND = 41, + VMPORT_CMD_GETHZ = 45, + VMPORT_CMD_GET_VCPU_INFO = 68, + VMPORT_ENTRIES +} VMPortCommand; + +static inline void vmport_init(ISABus *bus) +{ + isa_create_simple(bus, TYPE_VMPORT); +} + +void vmport_register(VMPortCommand command, VMPortReadFunc *func, void *opaque); + +#endif diff --git a/include/hw/i386/x86-iommu.h b/include/hw/i386/x86-iommu.h index 8e10383b11b157a234fb91f5271ff2126282ac64..9de92d33a11e9624223881804c9a3b30e05cd78e 100644 --- a/include/hw/i386/x86-iommu.h +++ b/include/hw/i386/x86-iommu.h @@ -23,19 +23,13 @@ #include "hw/sysbus.h" #include "hw/pci/pci.h" #include "hw/pci/msi.h" +#include "qom/object.h" #define TYPE_X86_IOMMU_DEVICE ("x86-iommu") -#define X86_IOMMU_DEVICE(obj) \ - OBJECT_CHECK(X86IOMMUState, (obj), TYPE_X86_IOMMU_DEVICE) -#define X86_IOMMU_CLASS(klass) \ - OBJECT_CLASS_CHECK(X86IOMMUClass, (klass), TYPE_X86_IOMMU_DEVICE) -#define X86_IOMMU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(X86IOMMUClass, obj, TYPE_X86_IOMMU_DEVICE) +OBJECT_DECLARE_TYPE(X86IOMMUState, X86IOMMUClass, X86_IOMMU_DEVICE) #define X86_IOMMU_SID_INVALID (0xffff) -typedef struct X86IOMMUState X86IOMMUState; -typedef struct X86IOMMUClass X86IOMMUClass; typedef struct X86IOMMUIrq X86IOMMUIrq; typedef struct X86IOMMU_MSIMessage X86IOMMU_MSIMessage; diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h index b522854816870df790a4c90c9aba1aacb9dfec75..739fac50871b9c07ab6ecb0c7f0649de7ccc551b 100644 --- a/include/hw/i386/x86.h +++ b/include/hw/i386/x86.h @@ -26,8 +26,9 @@ #include "hw/nmi.h" #include "hw/isa/isa.h" #include "hw/i386/ioapic.h" +#include "qom/object.h" -typedef struct { +struct X86MachineClass { /*< private >*/ MachineClass parent; @@ -37,9 +38,9 @@ typedef struct { bool save_tsc_khz; /* Enables contiguous-apic-ID mode */ bool compat_apic_id_mode; -} X86MachineClass; +}; -typedef struct { +struct X86MachineState { /*< private >*/ MachineState parent; @@ -50,15 +51,14 @@ typedef struct { FWCfgState *fw_cfg; qemu_irq *gsi; GMappedFile *initrd_mapped_file; - - /* Configuration options: */ - uint64_t max_ram_below_4g; + HotplugHandler *acpi_dev; /* RAM information (sizes, addresses, configuration): */ ram_addr_t below_4g_mem_size, above_4g_mem_size; /* CPU and apic information: */ bool apic_xrupt_override; + unsigned pci_irq_mask; unsigned apic_id_limit; uint16_t boot_cpus; unsigned smp_dies; @@ -66,33 +66,18 @@ typedef struct { OnOffAuto smm; OnOffAuto acpi; - /* Apic id specific handlers */ - uint32_t (*apicid_from_cpu_idx)(X86CPUTopoInfo *topo_info, - unsigned cpu_index); - void (*topo_ids_from_apicid)(apic_id_t apicid, X86CPUTopoInfo *topo_info, - X86CPUTopoIDs *topo_ids); - apic_id_t (*apicid_from_topo_ids)(X86CPUTopoInfo *topo_info, - const X86CPUTopoIDs *topo_ids); - uint32_t (*apicid_pkg_offset)(X86CPUTopoInfo *topo_info); - /* * Address space used by IOAPIC device. All IOAPIC interrupts * will be translated to MSI messages in the address space. */ AddressSpace *ioapic_as; -} X86MachineState; +}; -#define X86_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g" #define X86_MACHINE_SMM "smm" #define X86_MACHINE_ACPI "acpi" #define TYPE_X86_MACHINE MACHINE_TYPE_NAME("x86") -#define X86_MACHINE(obj) \ - OBJECT_CHECK(X86MachineState, (obj), TYPE_X86_MACHINE) -#define X86_MACHINE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(X86MachineClass, obj, TYPE_X86_MACHINE) -#define X86_MACHINE_CLASS(class) \ - OBJECT_CLASS_CHECK(X86MachineClass, class, TYPE_X86_MACHINE) +OBJECT_DECLARE_TYPE(X86MachineState, X86MachineClass, X86_MACHINE) void init_topo_info(X86CPUTopoInfo *topo_info, const X86MachineState *x86ms); @@ -105,6 +90,16 @@ CpuInstanceProperties x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index); int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx); const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms); +CPUArchId *x86_find_cpu_slot(MachineState *ms, uint32_t id, int *idx); +void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count); +void x86_cpu_pre_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); +void x86_cpu_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); +void x86_cpu_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); +void x86_cpu_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); void x86_bios_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw); @@ -114,12 +109,13 @@ void x86_load_linux(X86MachineState *x86ms, bool pvh_enabled, bool linuxboot_dma_enabled); -bool x86_machine_is_smm_enabled(X86MachineState *x86ms); -bool x86_machine_is_acpi_enabled(X86MachineState *x86ms); +bool x86_machine_is_smm_enabled(const X86MachineState *x86ms); +bool x86_machine_is_acpi_enabled(const X86MachineState *x86ms); /* Global System Interrupts */ #define GSI_NUM_PINS IOAPIC_NUM_PINS +#define ACPI_BUILD_PCI_IRQS ((1<<5) | (1<<9) | (1<<10) | (1<<11)) typedef struct GSIState { qemu_irq i8259_irq[ISA_NUM_IRQS]; @@ -130,7 +126,4 @@ qemu_irq x86_allocate_cpu_irq(void); void gsi_handler(void *opaque, int n, int level); void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name); -/* hpet.c */ -extern int no_hpet; - #endif diff --git a/include/hw/ide/ahci.h b/include/hw/ide/ahci.h index b44e3000cf9cbb1e4b34be73f31ae95867a76812..210e5e734cfb57b3726aa0aef1b75b4c12089db4 100644 --- a/include/hw/ide/ahci.h +++ b/include/hw/ide/ahci.h @@ -9,7 +9,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,6 +25,7 @@ #define HW_IDE_AHCI_H #include "hw/sysbus.h" +#include "qom/object.h" typedef struct AHCIDevice AHCIDevice; @@ -50,36 +51,38 @@ typedef struct AHCIState { AddressSpace *as; } AHCIState; -typedef struct AHCIPCIState AHCIPCIState; #define TYPE_ICH9_AHCI "ich9-ahci" +OBJECT_DECLARE_SIMPLE_TYPE(AHCIPCIState, ICH9_AHCI) int32_t ahci_get_num_ports(PCIDevice *dev); void ahci_ide_create_devs(PCIDevice *dev, DriveInfo **hd); #define TYPE_SYSBUS_AHCI "sysbus-ahci" +OBJECT_DECLARE_SIMPLE_TYPE(SysbusAHCIState, SYSBUS_AHCI) -typedef struct SysbusAHCIState { +struct SysbusAHCIState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ AHCIState ahci; uint32_t num_ports; -} SysbusAHCIState; +}; #define TYPE_ALLWINNER_AHCI "allwinner-ahci" +OBJECT_DECLARE_SIMPLE_TYPE(AllwinnerAHCIState, ALLWINNER_AHCI) #define ALLWINNER_AHCI_MMIO_OFF 0x80 #define ALLWINNER_AHCI_MMIO_SIZE 0x80 -typedef struct AllwinnerAHCIState { +struct AllwinnerAHCIState { /*< private >*/ SysbusAHCIState parent_obj; /*< public >*/ MemoryRegion mmio; uint32_t regs[ALLWINNER_AHCI_MMIO_SIZE/4]; -} AllwinnerAHCIState; +}; #endif /* HW_IDE_AHCI_H */ diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h index 55da35d768cf2f6cd56b1672f3291f21fef1d7ee..2d09162eeb7e1c517a07767762cc0f330ef35d96 100644 --- a/include/hw/ide/internal.h +++ b/include/hw/ide/internal.h @@ -17,18 +17,29 @@ /* debug IDE devices */ #define USE_DMA_CDROM +#include "qom/object.h" -typedef struct IDEBus IDEBus; typedef struct IDEDevice IDEDevice; typedef struct IDEState IDEState; typedef struct IDEDMA IDEDMA; typedef struct IDEDMAOps IDEDMAOps; #define TYPE_IDE_BUS "IDE" -#define IDE_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(IDEBus, IDE_BUS) #define MAX_IDE_DEVS 2 +/* Device/Head ("select") Register */ +#define ATA_DEV_SELECT 0x10 +/* ATA1,3: Defined as '1'. + * ATA2: Reserved. + * ATA3-7: obsolete. */ +#define ATA_DEV_ALWAYS_ON 0xA0 +#define ATA_DEV_LBA 0x40 +#define ATA_DEV_LBA_MSB 0x0F /* LBA 24:27 */ +#define ATA_DEV_HS 0x0F /* HS 3:0 */ + + /* Bits of HD_STATUS */ #define ERR_STAT 0x01 #define INDEX_STAT 0x02 @@ -57,8 +68,10 @@ typedef struct IDEDMAOps IDEDMAOps; #define REL 0x04 #define TAG_MASK 0xf8 -#define IDE_CMD_RESET 0x04 -#define IDE_CMD_DISABLE_IRQ 0x02 +/* Bits of Device Control register */ +#define IDE_CTRL_HOB 0x80 +#define IDE_CTRL_RESET 0x04 +#define IDE_CTRL_DISABLE_IRQ 0x02 /* ACS-2 T13/2015-D Table B.2 Command codes */ #define WIN_NOP 0x00 @@ -322,12 +335,12 @@ typedef enum { IDE_HD, IDE_CD, IDE_CFATA } IDEDriveKind; typedef void EndTransferFunc(IDEState *); -typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockCompletionFunc *); -typedef void DMAVoidFunc(IDEDMA *); -typedef int DMAIntFunc(IDEDMA *, bool); -typedef int32_t DMAInt32Func(IDEDMA *, int32_t len); -typedef void DMAu32Func(IDEDMA *, uint32_t); -typedef void DMAStopFunc(IDEDMA *, bool); +typedef void DMAStartFunc(const IDEDMA *, IDEState *, BlockCompletionFunc *); +typedef void DMAVoidFunc(const IDEDMA *); +typedef int DMAIntFunc(const IDEDMA *, bool); +typedef int32_t DMAInt32Func(const IDEDMA *, int32_t len); +typedef void DMAu32Func(const IDEDMA *, uint32_t); +typedef void DMAStopFunc(const IDEDMA *, bool); struct unreported_events { bool eject_request; @@ -486,17 +499,12 @@ struct IDEBus { }; #define TYPE_IDE_DEVICE "ide-device" -#define IDE_DEVICE(obj) \ - OBJECT_CHECK(IDEDevice, (obj), TYPE_IDE_DEVICE) -#define IDE_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(IDEDeviceClass, (klass), TYPE_IDE_DEVICE) -#define IDE_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(IDEDeviceClass, (obj), TYPE_IDE_DEVICE) - -typedef struct IDEDeviceClass { +OBJECT_DECLARE_TYPE(IDEDevice, IDEDeviceClass, IDE_DEVICE) + +struct IDEDeviceClass { DeviceClass parent_class; void (*realize)(IDEDevice *dev, Error **errp); -} IDEDeviceClass; +}; struct IDEDevice { DeviceState qdev; @@ -564,7 +572,7 @@ static inline IDEState *idebus_active_if(IDEBus *bus) static inline void ide_set_irq(IDEBus *bus) { - if (!(bus->cmd & IDE_CMD_DISABLE_IRQ)) { + if (!(bus->cmd & IDE_CTRL_DISABLE_IRQ)) { qemu_irq_raise(bus->irq); } } @@ -603,7 +611,7 @@ void ide_atapi_io_error(IDEState *s, int ret); void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val); uint32_t ide_ioport_read(void *opaque, uint32_t addr1); uint32_t ide_status_read(void *opaque, uint32_t addr); -void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val); +void ide_ctrl_write(void *opaque, uint32_t addr, uint32_t val); void ide_data_writew(void *opaque, uint32_t addr, uint32_t val); uint32_t ide_data_readw(void *opaque, uint32_t addr); void ide_data_writel(void *opaque, uint32_t addr, uint32_t val); diff --git a/include/hw/ide/pci.h b/include/hw/ide/pci.h index dd504e5a0b97d3dbca8e9d770aa7b6c6b73201f6..d8384e1c42204bff58cf580ef7bd8d5f8e387634 100644 --- a/include/hw/ide/pci.h +++ b/include/hw/ide/pci.h @@ -3,6 +3,7 @@ #include "hw/ide/internal.h" #include "hw/pci/pci.h" +#include "qom/object.h" #define BM_STATUS_DMAING 0x01 #define BM_STATUS_ERROR 0x02 @@ -39,9 +40,9 @@ typedef struct BMDMAState { } BMDMAState; #define TYPE_PCI_IDE "pci-ide" -#define PCI_IDE(obj) OBJECT_CHECK(PCIIDEState, (obj), TYPE_PCI_IDE) +OBJECT_DECLARE_SIMPLE_TYPE(PCIIDEState, PCI_IDE) -typedef struct PCIIDEState { +struct PCIIDEState { /*< private >*/ PCIDevice parent_obj; /*< public >*/ @@ -52,7 +53,7 @@ typedef struct PCIIDEState { MemoryRegion bmdma_bar; MemoryRegion cmd_bar[2]; MemoryRegion data_bar[2]; -} PCIIDEState; +}; static inline IDEState *bmdma_active_if(BMDMAState *bmdma) { diff --git a/include/hw/input/adb.h b/include/hw/input/adb.h index b7b32e2b167170e4108cf50ce66a6ad0c296e572..20fced15f707491008e8038cd60294701d217426 100644 --- a/include/hw/input/adb.h +++ b/include/hw/input/adb.h @@ -27,20 +27,22 @@ #define ADB_H #include "hw/qdev-core.h" +#include "qom/object.h" #define MAX_ADB_DEVICES 16 #define ADB_MAX_OUT_LEN 16 -typedef struct ADBBusState ADBBusState; typedef struct ADBDevice ADBDevice; /* buf = NULL means polling */ typedef int ADBDeviceRequest(ADBDevice *d, uint8_t *buf_out, const uint8_t *buf, int len); +typedef bool ADBDeviceHasData(ADBDevice *d); + #define TYPE_ADB_DEVICE "adb-device" -#define ADB_DEVICE(obj) OBJECT_CHECK(ADBDevice, (obj), TYPE_ADB_DEVICE) +OBJECT_DECLARE_TYPE(ADBDevice, ADBDeviceClass, ADB_DEVICE) struct ADBDevice { /*< private >*/ @@ -49,24 +51,23 @@ struct ADBDevice { int devaddr; int handler; - bool disable_direct_reg3_writes; }; -#define ADB_DEVICE_CLASS(cls) \ - OBJECT_CLASS_CHECK(ADBDeviceClass, (cls), TYPE_ADB_DEVICE) -#define ADB_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ADBDeviceClass, (obj), TYPE_ADB_DEVICE) -typedef struct ADBDeviceClass { +struct ADBDeviceClass { /*< private >*/ DeviceClass parent_class; /*< public >*/ ADBDeviceRequest *devreq; -} ADBDeviceClass; + ADBDeviceHasData *devhasdata; +}; #define TYPE_ADB_BUS "apple-desktop-bus" -#define ADB_BUS(obj) OBJECT_CHECK(ADBBusState, (obj), TYPE_ADB_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(ADBBusState, ADB_BUS) + +#define ADB_STATUS_BUSTIMEOUT 0x1 +#define ADB_STATUS_POLLREPLY 0x2 struct ADBBusState { /*< private >*/ @@ -74,14 +75,33 @@ struct ADBBusState { /*< public >*/ ADBDevice *devices[MAX_ADB_DEVICES]; + uint16_t pending; int nb_devices; int poll_index; + uint8_t status; + + QEMUTimer *autopoll_timer; + bool autopoll_enabled; + bool autopoll_blocked; + uint8_t autopoll_rate_ms; + uint16_t autopoll_mask; + void (*autopoll_cb)(void *opaque); + void *autopoll_cb_opaque; }; int adb_request(ADBBusState *s, uint8_t *buf_out, const uint8_t *buf, int len); int adb_poll(ADBBusState *s, uint8_t *buf_out, uint16_t poll_mask); +void adb_autopoll_block(ADBBusState *s); +void adb_autopoll_unblock(ADBBusState *s); + +void adb_set_autopoll_enabled(ADBBusState *s, bool enabled); +void adb_set_autopoll_rate_ms(ADBBusState *s, int rate_ms); +void adb_set_autopoll_mask(ADBBusState *s, uint16_t mask); +void adb_register_autopoll_callback(ADBBusState *s, void (*cb)(void *opaque), + void *opaque); + #define TYPE_ADB_KEYBOARD "adb-keyboard" #define TYPE_ADB_MOUSE "adb-mouse" diff --git a/include/hw/input/i8042.h b/include/hw/input/i8042.h index 8eaebf50ce6d61302926ad7b8c5825bb8a4acf72..1d90432daefee418d9b66c996805f7f8eea1d2bd 100644 --- a/include/hw/input/i8042.h +++ b/include/hw/input/i8042.h @@ -9,12 +9,13 @@ #define HW_INPUT_I8042_H #include "hw/isa/isa.h" +#include "qom/object.h" #define TYPE_I8042 "i8042" +OBJECT_DECLARE_SIMPLE_TYPE(ISAKBDState, I8042) #define I8042_A20_LINE "a20" -typedef struct ISAKBDState ISAKBDState; void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, MemoryRegion *region, ram_addr_t size, diff --git a/include/hw/input/tsc2xxx.h b/include/hw/input/tsc2xxx.h index 3cd8f1bf55be7746faf5ef2ae4741f4d62f8eb51..5b76ebc177619e6da2d2dea7ee32151c46a3f00e 100644 --- a/include/hw/input/tsc2xxx.h +++ b/include/hw/input/tsc2xxx.h @@ -11,7 +11,13 @@ #ifndef HW_INPUT_TSC2XXX_H #define HW_INPUT_TSC2XXX_H -#include "ui/console.h" +typedef struct MouseTransformInfo { + /* Touchscreen resolution */ + int x; + int y; + /* Calibration values as used/generated by tslib */ + int a[7]; +} MouseTransformInfo; typedef struct uWireSlave { uint16_t (*receive)(void *opaque); diff --git a/include/hw/intc/allwinner-a10-pic.h b/include/hw/intc/allwinner-a10-pic.h index a5895401d15fd7ec0db4056bfac8138028fe235e..b8364d3ed40aa505e620a3fcb4ee31bcd5a72732 100644 --- a/include/hw/intc/allwinner-a10-pic.h +++ b/include/hw/intc/allwinner-a10-pic.h @@ -2,9 +2,10 @@ #define ALLWINNER_A10_PIC_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_AW_A10_PIC "allwinner-a10-pic" -#define AW_A10_PIC(obj) OBJECT_CHECK(AwA10PICState, (obj), TYPE_AW_A10_PIC) +OBJECT_DECLARE_SIMPLE_TYPE(AwA10PICState, AW_A10_PIC) #define AW_A10_PIC_VECTOR 0 #define AW_A10_PIC_BASE_ADDR 4 @@ -19,7 +20,7 @@ #define AW_A10_PIC_INT_NR 95 #define AW_A10_PIC_REG_NUM DIV_ROUND_UP(AW_A10_PIC_INT_NR, 32) -typedef struct AwA10PICState { +struct AwA10PICState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -37,6 +38,6 @@ typedef struct AwA10PICState { uint32_t enable[AW_A10_PIC_REG_NUM]; uint32_t mask[AW_A10_PIC_REG_NUM]; /*priority setting here*/ -} AwA10PICState; +}; #endif diff --git a/include/hw/intc/arm_gic.h b/include/hw/intc/arm_gic.h index 303b9748cbbbe66bf3c6db27fc88bdda394bf8ad..116ccbb5a9c7b96afb466c6286fb5309671fdbb8 100644 --- a/include/hw/intc/arm_gic.h +++ b/include/hw/intc/arm_gic.h @@ -65,6 +65,7 @@ #define HW_ARM_GIC_H #include "arm_gic_common.h" +#include "qom/object.h" /* Number of SGI target-list bits */ #define GIC_TARGETLIST_BITS 8 @@ -72,19 +73,17 @@ #define GIC_MIN_PRIORITY_BITS 4 #define TYPE_ARM_GIC "arm_gic" -#define ARM_GIC(obj) \ - OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC) -#define ARM_GIC_CLASS(klass) \ - OBJECT_CLASS_CHECK(ARMGICClass, (klass), TYPE_ARM_GIC) -#define ARM_GIC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ARMGICClass, (obj), TYPE_ARM_GIC) +typedef struct ARMGICClass ARMGICClass; +/* This is reusing the GICState typedef from TYPE_ARM_GIC_COMMON */ +DECLARE_OBJ_CHECKERS(GICState, ARMGICClass, + ARM_GIC, TYPE_ARM_GIC) -typedef struct ARMGICClass { +struct ARMGICClass { /*< private >*/ ARMGICCommonClass parent_class; /*< public >*/ DeviceRealize parent_realize; -} ARMGICClass; +}; #endif diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h index 6e0d6b8a88969039e3f1725704dce42d3869dd1c..70803750081c996c12af988b48f6e15c36afe812 100644 --- a/include/hw/intc/arm_gic_common.h +++ b/include/hw/intc/arm_gic_common.h @@ -22,6 +22,7 @@ #define HW_ARM_GIC_COMMON_H #include "hw/sysbus.h" +#include "qom/object.h" /* Maximum number of possible interrupts, determined by the GIC architecture */ #define GIC_MAXIRQ 1020 @@ -61,7 +62,7 @@ typedef struct gic_irq_state { uint8_t group; } gic_irq_state; -typedef struct GICState { +struct GICState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -143,24 +144,22 @@ typedef struct GICState { bool irq_reset_nonsecure; /* configure IRQs as group 1 (NS) on reset? */ int dev_fd; /* kvm device fd if backed by kvm vgic support */ Error *migration_blocker; -} GICState; +}; +typedef struct GICState GICState; #define TYPE_ARM_GIC_COMMON "arm_gic_common" -#define ARM_GIC_COMMON(obj) \ - OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC_COMMON) -#define ARM_GIC_COMMON_CLASS(klass) \ - OBJECT_CLASS_CHECK(ARMGICCommonClass, (klass), TYPE_ARM_GIC_COMMON) -#define ARM_GIC_COMMON_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ARMGICCommonClass, (obj), TYPE_ARM_GIC_COMMON) - -typedef struct ARMGICCommonClass { +typedef struct ARMGICCommonClass ARMGICCommonClass; +DECLARE_OBJ_CHECKERS(GICState, ARMGICCommonClass, + ARM_GIC_COMMON, TYPE_ARM_GIC_COMMON) + +struct ARMGICCommonClass { /*< private >*/ SysBusDeviceClass parent_class; /*< public >*/ void (*pre_save)(GICState *s); void (*post_load)(GICState *s); -} ARMGICCommonClass; +}; void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler, const MemoryRegionOps *ops, diff --git a/include/hw/intc/arm_gicv3.h b/include/hw/intc/arm_gicv3.h index 4a6fd85e226a6be143cdf01eee9ab378f6270337..a81a6ae7ecad6d1251738842e0ea67e94495eb27 100644 --- a/include/hw/intc/arm_gicv3.h +++ b/include/hw/intc/arm_gicv3.h @@ -13,20 +13,20 @@ #define HW_ARM_GICV3_H #include "arm_gicv3_common.h" +#include "qom/object.h" #define TYPE_ARM_GICV3 "arm-gicv3" -#define ARM_GICV3(obj) OBJECT_CHECK(GICv3State, (obj), TYPE_ARM_GICV3) -#define ARM_GICV3_CLASS(klass) \ - OBJECT_CLASS_CHECK(ARMGICv3Class, (klass), TYPE_ARM_GICV3) -#define ARM_GICV3_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ARMGICv3Class, (obj), TYPE_ARM_GICV3) +typedef struct ARMGICv3Class ARMGICv3Class; +/* This is reusing the GICState typedef from TYPE_ARM_GICV3_COMMON */ +DECLARE_OBJ_CHECKERS(GICv3State, ARMGICv3Class, + ARM_GICV3, TYPE_ARM_GICV3) -typedef struct ARMGICv3Class { +struct ARMGICv3Class { /*< private >*/ ARMGICv3CommonClass parent_class; /*< public >*/ DeviceRealize parent_realize; -} ARMGICv3Class; +}; #endif diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h index 31ec9a1ae43c005f8fd5d955873dd7330690be70..91491a2f664128a22dc70f23c629fc4751576509 100644 --- a/include/hw/intc/arm_gicv3_common.h +++ b/include/hw/intc/arm_gicv3_common.h @@ -26,6 +26,7 @@ #include "hw/sysbus.h" #include "hw/intc/arm_gic_common.h" +#include "qom/object.h" /* * Maximum number of possible interrupts, determined by the GIC architecture. @@ -152,7 +153,6 @@ struct GICv3CPUState { qemu_irq parent_fiq; qemu_irq parent_virq; qemu_irq parent_vfiq; - qemu_irq maintenance_irq; /* Redistributor */ uint32_t level; /* Current IRQ level */ @@ -279,21 +279,18 @@ GICV3_BITMAP_ACCESSORS(level) GICV3_BITMAP_ACCESSORS(edge_trigger) #define TYPE_ARM_GICV3_COMMON "arm-gicv3-common" -#define ARM_GICV3_COMMON(obj) \ - OBJECT_CHECK(GICv3State, (obj), TYPE_ARM_GICV3_COMMON) -#define ARM_GICV3_COMMON_CLASS(klass) \ - OBJECT_CLASS_CHECK(ARMGICv3CommonClass, (klass), TYPE_ARM_GICV3_COMMON) -#define ARM_GICV3_COMMON_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ARMGICv3CommonClass, (obj), TYPE_ARM_GICV3_COMMON) - -typedef struct ARMGICv3CommonClass { +typedef struct ARMGICv3CommonClass ARMGICv3CommonClass; +DECLARE_OBJ_CHECKERS(GICv3State, ARMGICv3CommonClass, + ARM_GICV3_COMMON, TYPE_ARM_GICV3_COMMON) + +struct ARMGICv3CommonClass { /*< private >*/ SysBusDeviceClass parent_class; /*< public >*/ void (*pre_save)(GICv3State *s); void (*post_load)(GICv3State *s); -} ARMGICv3CommonClass; +}; void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler, const MemoryRegionOps *ops, Error **errp); diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h index fd1fe64c03ae6441e2204c3cccf869ee8bbae6a3..5a0952b404996166ee5a66820a49f6fff3e14852 100644 --- a/include/hw/intc/arm_gicv3_its_common.h +++ b/include/hw/intc/arm_gicv3_its_common.h @@ -23,6 +23,7 @@ #include "hw/sysbus.h" #include "hw/intc/arm_gicv3_common.h" +#include "qom/object.h" #define ITS_CONTROL_SIZE 0x10000 #define ITS_TRANS_SIZE 0x10000 @@ -64,12 +65,9 @@ typedef struct GICv3ITSState GICv3ITSState; void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops); #define TYPE_ARM_GICV3_ITS_COMMON "arm-gicv3-its-common" -#define ARM_GICV3_ITS_COMMON(obj) \ - OBJECT_CHECK(GICv3ITSState, (obj), TYPE_ARM_GICV3_ITS_COMMON) -#define ARM_GICV3_ITS_COMMON_CLASS(klass) \ - OBJECT_CLASS_CHECK(GICv3ITSCommonClass, (klass), TYPE_ARM_GICV3_ITS_COMMON) -#define ARM_GICV3_ITS_COMMON_GET_CLASS(obj) \ - OBJECT_GET_CLASS(GICv3ITSCommonClass, (obj), TYPE_ARM_GICV3_ITS_COMMON) +typedef struct GICv3ITSCommonClass GICv3ITSCommonClass; +DECLARE_OBJ_CHECKERS(GICv3ITSState, GICv3ITSCommonClass, + ARM_GICV3_ITS_COMMON, TYPE_ARM_GICV3_ITS_COMMON) struct GICv3ITSCommonClass { /*< private >*/ @@ -81,6 +79,5 @@ struct GICv3ITSCommonClass { void (*post_load)(GICv3ITSState *s); }; -typedef struct GICv3ITSCommonClass GICv3ITSCommonClass; #endif diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h index a472c9b8f058fb1848664f8d2bb1e3d5c6bc7aac..bb087b23c35def83561c457d40446dc41ab02627 100644 --- a/include/hw/intc/armv7m_nvic.h +++ b/include/hw/intc/armv7m_nvic.h @@ -13,11 +13,13 @@ #include "target/arm/cpu.h" #include "hw/sysbus.h" #include "hw/timer/armv7m_systick.h" +#include "qom/object.h" #define TYPE_NVIC "armv7m_nvic" -#define NVIC(obj) \ - OBJECT_CHECK(NVICState, (obj), TYPE_NVIC) +typedef struct NVICState NVICState; +DECLARE_INSTANCE_CHECKER(NVICState, NVIC, + TYPE_NVIC) /* Highest permitted number of exceptions (architectural limit) */ #define NVIC_MAX_VECTORS 512 @@ -35,7 +37,7 @@ typedef struct VecInfo { uint8_t level; /* exceptions <=15 never set level */ } VecInfo; -typedef struct NVICState { +struct NVICState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -88,6 +90,6 @@ typedef struct NVICState { qemu_irq sysresetreq; SysTickState systick[M_REG_NUM_BANKS]; -} NVICState; +}; #endif diff --git a/include/hw/intc/aspeed_vic.h b/include/hw/intc/aspeed_vic.h index 107ff17c3be4562201573c214732b6babd34d0d4..68d6ab997a142fb855596b2e680fc33bd841cc59 100644 --- a/include/hw/intc/aspeed_vic.h +++ b/include/hw/intc/aspeed_vic.h @@ -14,13 +14,14 @@ #define ASPEED_VIC_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_ASPEED_VIC "aspeed.vic" -#define ASPEED_VIC(obj) OBJECT_CHECK(AspeedVICState, (obj), TYPE_ASPEED_VIC) +OBJECT_DECLARE_SIMPLE_TYPE(AspeedVICState, ASPEED_VIC) #define ASPEED_VIC_NR_IRQS 51 -typedef struct AspeedVICState { +struct AspeedVICState { /*< private >*/ SysBusDevice parent_obj; @@ -43,6 +44,6 @@ typedef struct AspeedVICState { /* 0=low-sensitive/falling-edge, 1=high-sensitive/rising-edge */ uint64_t event; -} AspeedVICState; +}; #endif /* ASPEED_VIC_H */ diff --git a/include/hw/intc/bcm2835_ic.h b/include/hw/intc/bcm2835_ic.h index 392ded1cb335608c435efb14e5a0e2329050c555..588eb76c5cbfd6266bfb8909f3efc9ac6593c882 100644 --- a/include/hw/intc/bcm2835_ic.h +++ b/include/hw/intc/bcm2835_ic.h @@ -9,14 +9,15 @@ #define BCM2835_IC_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_BCM2835_IC "bcm2835-ic" -#define BCM2835_IC(obj) OBJECT_CHECK(BCM2835ICState, (obj), TYPE_BCM2835_IC) +OBJECT_DECLARE_SIMPLE_TYPE(BCM2835ICState, BCM2835_IC) #define BCM2835_IC_GPU_IRQ "gpu-irq" #define BCM2835_IC_ARM_IRQ "arm-irq" -typedef struct BCM2835ICState { +struct BCM2835ICState { /*< private >*/ SysBusDevice busdev; /*< public >*/ @@ -30,6 +31,6 @@ typedef struct BCM2835ICState { uint8_t arm_irq_level, arm_irq_enable; bool fiq_enable; uint8_t fiq_select; -} BCM2835ICState; +}; #endif diff --git a/include/hw/intc/bcm2836_control.h b/include/hw/intc/bcm2836_control.h index 2c22405686bf143672930099608a3c45ac577450..a410c817e8face3ec748c9fcf146a2cca2cf1512 100644 --- a/include/hw/intc/bcm2836_control.h +++ b/include/hw/intc/bcm2836_control.h @@ -17,16 +17,16 @@ #include "hw/sysbus.h" #include "qemu/timer.h" +#include "qom/object.h" /* 4 mailboxes per core, for 16 total */ #define BCM2836_NCORES 4 #define BCM2836_MBPERCORE 4 #define TYPE_BCM2836_CONTROL "bcm2836-control" -#define BCM2836_CONTROL(obj) \ - OBJECT_CHECK(BCM2836ControlState, (obj), TYPE_BCM2836_CONTROL) +OBJECT_DECLARE_SIMPLE_TYPE(BCM2836ControlState, BCM2836_CONTROL) -typedef struct BCM2836ControlState { +struct BCM2836ControlState { /*< private >*/ SysBusDevice busdev; /*< public >*/ @@ -56,6 +56,6 @@ typedef struct BCM2836ControlState { /* outputs to CPU cores */ qemu_irq irq[BCM2836_NCORES]; qemu_irq fiq[BCM2836_NCORES]; -} BCM2836ControlState; +}; #endif diff --git a/include/hw/intc/heathrow_pic.h b/include/hw/intc/heathrow_pic.h index b163e27ab940e9d5f77b93d94008653187ae3eb9..c0a7f6f5460cb8765abd9cb786ecccbe5eca9c2a 100644 --- a/include/hw/intc/heathrow_pic.h +++ b/include/hw/intc/heathrow_pic.h @@ -27,9 +27,10 @@ #define HW_INTC_HEATHROW_PIC_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_HEATHROW "heathrow" -#define HEATHROW(obj) OBJECT_CHECK(HeathrowState, (obj), TYPE_HEATHROW) +OBJECT_DECLARE_SIMPLE_TYPE(HeathrowState, HEATHROW) typedef struct HeathrowPICState { uint32_t events; @@ -38,13 +39,13 @@ typedef struct HeathrowPICState { uint32_t level_triggered; } HeathrowPICState; -typedef struct HeathrowState { +struct HeathrowState { SysBusDevice parent_obj; MemoryRegion mem; HeathrowPICState pics[2]; qemu_irq irqs[1]; -} HeathrowState; +}; #define HEATHROW_NUM_IRQS 64 diff --git a/include/hw/intc/ibex_plic.h b/include/hw/intc/ibex_plic.h new file mode 100644 index 0000000000000000000000000000000000000000..7fc495db992ed8743de6165c990814bcc8bb1ae0 --- /dev/null +++ b/include/hw/intc/ibex_plic.h @@ -0,0 +1,65 @@ +/* + * QEMU RISC-V lowRISC Ibex PLIC + * + * Copyright (c) 2020 Western Digital + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#ifndef HW_IBEX_PLIC_H +#define HW_IBEX_PLIC_H + +#include "hw/sysbus.h" +#include "qom/object.h" + +#define TYPE_IBEX_PLIC "ibex-plic" +OBJECT_DECLARE_SIMPLE_TYPE(IbexPlicState, IBEX_PLIC) + +struct IbexPlicState { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion mmio; + + uint32_t *pending; + uint32_t *hidden_pending; + uint32_t *claimed; + uint32_t *source; + uint32_t *priority; + uint32_t *enable; + uint32_t threshold; + uint32_t claim; + + /* config */ + uint32_t num_cpus; + uint32_t num_sources; + + uint32_t pending_base; + uint32_t pending_num; + + uint32_t source_base; + uint32_t source_num; + + uint32_t priority_base; + uint32_t priority_num; + + uint32_t enable_base; + uint32_t enable_num; + + uint32_t threshold_base; + + uint32_t claim_base; +}; + +#endif /* HW_IBEX_PLIC_H */ diff --git a/include/hw/intc/imx_avic.h b/include/hw/intc/imx_avic.h index 1b80769018ed8ba0043d670a2d2fcea0380dd5d7..75fbd1a89c7193121ce1b3bcddbb27a6866f5d67 100644 --- a/include/hw/intc/imx_avic.h +++ b/include/hw/intc/imx_avic.h @@ -18,9 +18,10 @@ #define IMX_AVIC_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_IMX_AVIC "imx.avic" -#define IMX_AVIC(obj) OBJECT_CHECK(IMXAVICState, (obj), TYPE_IMX_AVIC) +OBJECT_DECLARE_SIMPLE_TYPE(IMXAVICState, IMX_AVIC) #define IMX_AVIC_NUM_IRQS 64 @@ -36,7 +37,7 @@ #define PRIO_PER_WORD (sizeof(uint32_t) * 8 / 4) #define PRIO_WORDS (IMX_AVIC_NUM_IRQS/PRIO_PER_WORD) -typedef struct IMXAVICState{ +struct IMXAVICState { /*< private >*/ SysBusDevice parent_obj; @@ -50,6 +51,6 @@ typedef struct IMXAVICState{ qemu_irq irq; qemu_irq fiq; uint32_t prio[PRIO_WORDS]; /* Priorities are 4-bits each */ -} IMXAVICState; +}; #endif /* IMX_AVIC_H */ diff --git a/include/hw/intc/imx_gpcv2.h b/include/hw/intc/imx_gpcv2.h index ed978b24bb8bc8505f7d03e141ef0cbe8679fa13..7bdee7e80a12dabc7458ac20e28ede910b54bfb5 100644 --- a/include/hw/intc/imx_gpcv2.h +++ b/include/hw/intc/imx_gpcv2.h @@ -2,21 +2,22 @@ #define IMX_GPCV2_H #include "hw/sysbus.h" +#include "qom/object.h" enum IMXGPCv2Registers { GPC_NUM = 0xE00 / sizeof(uint32_t), }; -typedef struct IMXGPCv2State { +struct IMXGPCv2State { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ MemoryRegion iomem; uint32_t regs[GPC_NUM]; -} IMXGPCv2State; +}; #define TYPE_IMX_GPCV2 "imx-gpcv2" -#define IMX_GPCV2(obj) OBJECT_CHECK(IMXGPCv2State, (obj), TYPE_IMX_GPCV2) +OBJECT_DECLARE_SIMPLE_TYPE(IMXGPCv2State, IMX_GPCV2) #endif /* IMX_GPCV2_H */ diff --git a/include/hw/intc/intc.h b/include/hw/intc/intc.h index fb3e8e621f0b88b6e1447f3187589a26eef94b3a..7018f608ca5204a01975bb56e2d904c4f35dabdf 100644 --- a/include/hw/intc/intc.h +++ b/include/hw/intc/intc.h @@ -5,19 +5,16 @@ #define TYPE_INTERRUPT_STATS_PROVIDER "intctrl" -#define INTERRUPT_STATS_PROVIDER_CLASS(klass) \ - OBJECT_CLASS_CHECK(InterruptStatsProviderClass, (klass), \ +typedef struct InterruptStatsProviderClass InterruptStatsProviderClass; +DECLARE_CLASS_CHECKERS(InterruptStatsProviderClass, INTERRUPT_STATS_PROVIDER, TYPE_INTERRUPT_STATS_PROVIDER) -#define INTERRUPT_STATS_PROVIDER_GET_CLASS(obj) \ - OBJECT_GET_CLASS(InterruptStatsProviderClass, (obj), \ - TYPE_INTERRUPT_STATS_PROVIDER) #define INTERRUPT_STATS_PROVIDER(obj) \ INTERFACE_CHECK(InterruptStatsProvider, (obj), \ TYPE_INTERRUPT_STATS_PROVIDER) typedef struct InterruptStatsProvider InterruptStatsProvider; -typedef struct InterruptStatsProviderClass { +struct InterruptStatsProviderClass { InterfaceClass parent; /* The returned pointer and statistics must remain valid until @@ -26,6 +23,6 @@ typedef struct InterruptStatsProviderClass { bool (*get_statistics)(InterruptStatsProvider *obj, uint64_t **irq_counts, unsigned int *nb_irqs); void (*print_info)(InterruptStatsProvider *obj, Monitor *mon); -} InterruptStatsProviderClass; +}; #endif diff --git a/include/hw/intc/mips_gic.h b/include/hw/intc/mips_gic.h index 8428287bf981f5b85a3f0d8276bcfb5db5fd281d..eeb136e261f1556d5f71bef34cc8880e85c43eac 100644 --- a/include/hw/intc/mips_gic.h +++ b/include/hw/intc/mips_gic.h @@ -15,6 +15,7 @@ #include "hw/timer/mips_gictimer.h" #include "hw/sysbus.h" #include "cpu.h" +#include "qom/object.h" /* * GIC Specific definitions */ @@ -170,13 +171,12 @@ #define GIC_LOCAL_INT_WD 0 /* GIC watchdog */ #define TYPE_MIPS_GIC "mips-gic" -#define MIPS_GIC(obj) OBJECT_CHECK(MIPSGICState, (obj), TYPE_MIPS_GIC) +OBJECT_DECLARE_SIMPLE_TYPE(MIPSGICState, MIPS_GIC) /* Support up to 32 VPs and 256 IRQs */ #define GIC_MAX_VPS 32 #define GIC_MAX_INTRS 256 -typedef struct MIPSGICState MIPSGICState; typedef struct MIPSGICIRQState MIPSGICIRQState; typedef struct MIPSGICVPState MIPSGICVPState; diff --git a/include/hw/intc/realview_gic.h b/include/hw/intc/realview_gic.h index 1783ea11b9f2dc5358785207e5ad600a51a22b5e..f37339dc0b190641aefdc4d5596485d19e3c0ffb 100644 --- a/include/hw/intc/realview_gic.h +++ b/include/hw/intc/realview_gic.h @@ -12,17 +12,17 @@ #include "hw/sysbus.h" #include "hw/intc/arm_gic.h" +#include "qom/object.h" #define TYPE_REALVIEW_GIC "realview_gic" -#define REALVIEW_GIC(obj) \ - OBJECT_CHECK(RealViewGICState, (obj), TYPE_REALVIEW_GIC) +OBJECT_DECLARE_SIMPLE_TYPE(RealViewGICState, REALVIEW_GIC) -typedef struct RealViewGICState { +struct RealViewGICState { SysBusDevice parent_obj; MemoryRegion container; GICState gic; -} RealViewGICState; +}; #endif diff --git a/include/hw/intc/rx_icu.h b/include/hw/intc/rx_icu.h new file mode 100644 index 0000000000000000000000000000000000000000..7f5889b36f45ccf603a150513252d6a076124324 --- /dev/null +++ b/include/hw/intc/rx_icu.h @@ -0,0 +1,76 @@ +/* + * RX Interrupt Control Unit + * + * Copyright (c) 2019 Yoshinori Sato + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#ifndef HW_INTC_RX_ICU_H +#define HW_INTC_RX_ICU_H + +#include "hw/sysbus.h" +#include "qom/object.h" + +enum TRG_MODE { + TRG_LEVEL = 0, + TRG_NEDGE = 1, /* Falling */ + TRG_PEDGE = 2, /* Raising */ + TRG_BEDGE = 3, /* Both */ +}; + +struct IRQSource { + enum TRG_MODE sense; + int level; +}; + +enum { + /* Software interrupt request */ + SWI = 27, + NR_IRQS = 256 +}; + +struct RXICUState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + MemoryRegion memory; + struct IRQSource src[NR_IRQS]; + uint32_t nr_irqs; + uint8_t *map; + uint32_t nr_sense; + uint8_t *init_sense; + + uint8_t ir[NR_IRQS]; + uint8_t dtcer[NR_IRQS]; + uint8_t ier[NR_IRQS / 8]; + uint8_t ipr[142]; + uint8_t dmasr[4]; + uint16_t fir; + uint8_t nmisr; + uint8_t nmier; + uint8_t nmiclr; + uint8_t nmicr; + int16_t req_irq; + qemu_irq _irq; + qemu_irq _fir; + qemu_irq _swi; +}; + +#define TYPE_RX_ICU "rx-icu" +OBJECT_DECLARE_SIMPLE_TYPE(RXICUState, RX_ICU) + +#endif /* RX_ICU_H */ diff --git a/include/hw/riscv/sifive_clint.h b/include/hw/intc/sifive_clint.h similarity index 92% rename from include/hw/riscv/sifive_clint.h rename to include/hw/intc/sifive_clint.h index 9f5fb3d31d013dd1ed1b7a7617c36cdf1d948f64..a30be0f3d6fb80ee83a62a65bbc150a68adeba70 100644 --- a/include/hw/riscv/sifive_clint.h +++ b/include/hw/intc/sifive_clint.h @@ -39,11 +39,13 @@ typedef struct SiFiveCLINTState { uint32_t timecmp_base; uint32_t time_base; uint32_t aperture_size; + uint32_t timebase_freq; } SiFiveCLINTState; DeviceState *sifive_clint_create(hwaddr addr, hwaddr size, uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base, - uint32_t timecmp_base, uint32_t time_base, bool provide_rdtime); + uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq, + bool provide_rdtime); enum { SIFIVE_SIP_BASE = 0x0, diff --git a/include/hw/riscv/sifive_plic.h b/include/hw/intc/sifive_plic.h similarity index 91% rename from include/hw/riscv/sifive_plic.h rename to include/hw/intc/sifive_plic.h index 96a792cd040950ad608543c4804a944704f5bcea..1e451a270c790227a3f73285ad422057ce005a3f 100644 --- a/include/hw/riscv/sifive_plic.h +++ b/include/hw/intc/sifive_plic.h @@ -22,11 +22,13 @@ #define HW_SIFIVE_PLIC_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_SIFIVE_PLIC "riscv.sifive.plic" -#define SIFIVE_PLIC(obj) \ - OBJECT_CHECK(SiFivePLICState, (obj), TYPE_SIFIVE_PLIC) +typedef struct SiFivePLICState SiFivePLICState; +DECLARE_INSTANCE_CHECKER(SiFivePLICState, SIFIVE_PLIC, + TYPE_SIFIVE_PLIC) typedef enum PLICMode { PLICMode_U, @@ -41,7 +43,7 @@ typedef struct PLICAddr { PLICMode mode; } PLICAddr; -typedef struct SiFivePLICState { +struct SiFivePLICState { /*< private >*/ SysBusDevice parent_obj; @@ -70,7 +72,7 @@ typedef struct SiFivePLICState { uint32_t context_base; uint32_t context_stride; uint32_t aperture_size; -} SiFivePLICState; +}; DeviceState *sifive_plic_create(hwaddr addr, char *hart_config, uint32_t hartid_base, uint32_t num_sources, diff --git a/include/hw/intc/xlnx-pmu-iomod-intc.h b/include/hw/intc/xlnx-pmu-iomod-intc.h index 0bd118884af0a73530b39e0a1c63ae1e0a78f1d0..ccc8bd272a24b8df4e3235c1782c7f6d514a5896 100644 --- a/include/hw/intc/xlnx-pmu-iomod-intc.h +++ b/include/hw/intc/xlnx-pmu-iomod-intc.h @@ -27,16 +27,16 @@ #include "hw/sysbus.h" #include "hw/register.h" +#include "qom/object.h" #define TYPE_XLNX_PMU_IO_INTC "xlnx.pmu_io_intc" -#define XLNX_PMU_IO_INTC(obj) \ - OBJECT_CHECK(XlnxPMUIOIntc, (obj), TYPE_XLNX_PMU_IO_INTC) +OBJECT_DECLARE_SIMPLE_TYPE(XlnxPMUIOIntc, XLNX_PMU_IO_INTC) /* This is R_PIT3_CONTROL + 1 */ #define XLNXPMUIOINTC_R_MAX (0x78 + 1) -typedef struct XlnxPMUIOIntc { +struct XlnxPMUIOIntc { SysBusDevice parent_obj; MemoryRegion iomem; @@ -52,6 +52,6 @@ typedef struct XlnxPMUIOIntc { uint32_t regs[XLNXPMUIOINTC_R_MAX]; RegisterInfo regs_info[XLNXPMUIOINTC_R_MAX]; -} XlnxPMUIOIntc; +}; #endif /* HW_INTC_XLNX_PMU_IOMOD_INTC_H */ diff --git a/include/hw/intc/xlnx-zynqmp-ipi.h b/include/hw/intc/xlnx-zynqmp-ipi.h index 866c719c6f3871bf9c68ed0e863640c02a1102cb..33eff1d4f68519088f1664f4db514160fd192edd 100644 --- a/include/hw/intc/xlnx-zynqmp-ipi.h +++ b/include/hw/intc/xlnx-zynqmp-ipi.h @@ -27,18 +27,18 @@ #include "hw/sysbus.h" #include "hw/register.h" +#include "qom/object.h" #define TYPE_XLNX_ZYNQMP_IPI "xlnx.zynqmp_ipi" -#define XLNX_ZYNQMP_IPI(obj) \ - OBJECT_CHECK(XlnxZynqMPIPI, (obj), TYPE_XLNX_ZYNQMP_IPI) +OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPIPI, XLNX_ZYNQMP_IPI) /* This is R_IPI_IDR + 1 */ #define R_XLNX_ZYNQMP_IPI_MAX ((0x1c / 4) + 1) #define NUM_IPIS 11 -typedef struct XlnxZynqMPIPI { +struct XlnxZynqMPIPI { /* Private */ SysBusDevice parent_obj; @@ -51,6 +51,6 @@ typedef struct XlnxZynqMPIPI { uint32_t regs[R_XLNX_ZYNQMP_IPI_MAX]; RegisterInfo regs_info[R_XLNX_ZYNQMP_IPI_MAX]; -} XlnxZynqMPIPI; +}; #endif /* XLNX_ZYNQMP_IPI_H */ diff --git a/include/hw/ipack/ipack.h b/include/hw/ipack/ipack.h index 1c07969bc98a9e1efef444c3fff4edb8782ccb5b..75014e74ae16a19905bfbc6bec16872a7b428dd1 100644 --- a/include/hw/ipack/ipack.h +++ b/include/hw/ipack/ipack.h @@ -12,11 +12,11 @@ #define QEMU_IPACK_H #include "hw/qdev-core.h" +#include "qom/object.h" -typedef struct IPackBus IPackBus; #define TYPE_IPACK_BUS "IndustryPack" -#define IPACK_BUS(obj) OBJECT_CHECK(IPackBus, (obj), TYPE_IPACK_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(IPackBus, IPACK_BUS) struct IPackBus { /*< private >*/ @@ -28,16 +28,10 @@ struct IPackBus { qemu_irq_handler set_irq; }; -typedef struct IPackDevice IPackDevice; -typedef struct IPackDeviceClass IPackDeviceClass; #define TYPE_IPACK_DEVICE "ipack-device" -#define IPACK_DEVICE(obj) \ - OBJECT_CHECK(IPackDevice, (obj), TYPE_IPACK_DEVICE) -#define IPACK_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(IPackDeviceClass, (klass), TYPE_IPACK_DEVICE) -#define IPACK_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(IPackDeviceClass, (obj), TYPE_IPACK_DEVICE) +OBJECT_DECLARE_TYPE(IPackDevice, IPackDeviceClass, + IPACK_DEVICE) struct IPackDeviceClass { /*< private >*/ diff --git a/include/hw/ipmi/ipmi.h b/include/hw/ipmi/ipmi.h index 8a99d958bbc327c62f63403dca3b37aa634889db..77a7213ed9345a8f8ac862293d4129ff410aaf56 100644 --- a/include/hw/ipmi/ipmi.h +++ b/include/hw/ipmi/ipmi.h @@ -27,6 +27,7 @@ #include "exec/memory.h" #include "hw/qdev-core.h" +#include "qom/object.h" #define MAX_IPMI_MSG_SIZE 300 @@ -53,6 +54,7 @@ enum ipmi_op { #define IPMI_CC_INVALID_DATA_FIELD 0xcc #define IPMI_CC_BMC_INIT_IN_PROGRESS 0xd2 #define IPMI_CC_COMMAND_NOT_SUPPORTED 0xd5 +#define IPMI_CC_UNSPECIFIED 0xff #define IPMI_NETFN_APP 0x06 #define IPMI_NETFN_OEM 0x3a @@ -109,14 +111,13 @@ uint32_t ipmi_next_uuid(void); #define TYPE_IPMI_INTERFACE "ipmi-interface" #define IPMI_INTERFACE(obj) \ INTERFACE_CHECK(IPMIInterface, (obj), TYPE_IPMI_INTERFACE) -#define IPMI_INTERFACE_CLASS(class) \ - OBJECT_CLASS_CHECK(IPMIInterfaceClass, (class), TYPE_IPMI_INTERFACE) -#define IPMI_INTERFACE_GET_CLASS(class) \ - OBJECT_GET_CLASS(IPMIInterfaceClass, (class), TYPE_IPMI_INTERFACE) +typedef struct IPMIInterfaceClass IPMIInterfaceClass; +DECLARE_CLASS_CHECKERS(IPMIInterfaceClass, IPMI_INTERFACE, + TYPE_IPMI_INTERFACE) typedef struct IPMIInterface IPMIInterface; -typedef struct IPMIInterfaceClass { +struct IPMIInterfaceClass { InterfaceClass parent; /* @@ -169,28 +170,24 @@ typedef struct IPMIInterfaceClass { * Return the firmware info for a device. */ void (*get_fwinfo)(struct IPMIInterface *s, IPMIFwInfo *info); -} IPMIInterfaceClass; +}; /* * Define a BMC simulator (or perhaps a connection to a real BMC) */ #define TYPE_IPMI_BMC "ipmi-bmc" -#define IPMI_BMC(obj) \ - OBJECT_CHECK(IPMIBmc, (obj), TYPE_IPMI_BMC) -#define IPMI_BMC_CLASS(obj_class) \ - OBJECT_CLASS_CHECK(IPMIBmcClass, (obj_class), TYPE_IPMI_BMC) -#define IPMI_BMC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(IPMIBmcClass, (obj), TYPE_IPMI_BMC) - -typedef struct IPMIBmc { +OBJECT_DECLARE_TYPE(IPMIBmc, IPMIBmcClass, + IPMI_BMC) + +struct IPMIBmc { DeviceState parent; uint8_t slave_addr; IPMIInterface *intf; -} IPMIBmc; +}; -typedef struct IPMIBmcClass { +struct IPMIBmcClass { DeviceClass parent; /* Called when the system resets to report to the bmc. */ @@ -203,7 +200,7 @@ typedef struct IPMIBmcClass { uint8_t *cmd, unsigned int cmd_len, unsigned int max_cmd_len, uint8_t msg_id); -} IPMIBmcClass; +}; /* * Add a link property to obj that points to a BMC. @@ -267,10 +264,8 @@ int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid, void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log); #define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim" -#define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \ - TYPE_IPMI_BMC_SIMULATOR) +OBJECT_DECLARE_SIMPLE_TYPE(IPMIBmcSim, IPMI_BMC_SIMULATOR) -typedef struct IPMIBmcSim IPMIBmcSim; typedef struct RspBuffer { uint8_t buffer[MAX_IPMI_MSG_SIZE]; diff --git a/include/hw/irq.h b/include/hw/irq.h index 24ba0ece116642a3c01f1d238ebeb9baf69e77ef..dc7abf199e360e387dccfba520a3002f5f3ab7b7 100644 --- a/include/hw/irq.h +++ b/include/hw/irq.h @@ -55,4 +55,22 @@ qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2); on an existing vector of qemu_irq. */ void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n); +/** + * qemu_irq_is_connected: Return true if IRQ line is wired up + * + * If a qemu_irq has a device on the other (receiving) end of it, + * return true; otherwise return false. + * + * Usually device models don't need to care whether the machine model + * has wired up their outbound qemu_irq lines, because functions like + * qemu_set_irq() silently do nothing if there is nothing on the other + * end of the line. However occasionally a device model will want to + * provide default behaviour if its output is left floating, and + * it can use this function to identify when that is the case. + */ +static inline bool qemu_irq_is_connected(qemu_irq irq) +{ + return irq != NULL; +} + #endif diff --git a/include/hw/isa/i8259_internal.h b/include/hw/isa/i8259_internal.h index 861d70d8f8bc29075e0ce059f934c11fecb275af..a6ae8a583feb65b982e7a8b7221eadeceb17db03 100644 --- a/include/hw/isa/i8259_internal.h +++ b/include/hw/isa/i8259_internal.h @@ -28,24 +28,18 @@ #include "hw/isa/isa.h" #include "hw/intc/intc.h" #include "hw/intc/i8259.h" +#include "qom/object.h" -typedef struct PICCommonState PICCommonState; #define TYPE_PIC_COMMON "pic-common" -#define PIC_COMMON(obj) \ - OBJECT_CHECK(PICCommonState, (obj), TYPE_PIC_COMMON) -#define PIC_COMMON_CLASS(klass) \ - OBJECT_CLASS_CHECK(PICCommonClass, (klass), TYPE_PIC_COMMON) -#define PIC_COMMON_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PICCommonClass, (obj), TYPE_PIC_COMMON) +OBJECT_DECLARE_TYPE(PICCommonState, PICCommonClass, PIC_COMMON) -typedef struct PICCommonClass -{ +struct PICCommonClass { ISADeviceClass parent_class; void (*pre_save)(PICCommonState *s); void (*post_load)(PICCommonState *s); -} PICCommonClass; +}; struct PICCommonState { ISADevice parent_obj; diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h index 02c23502748457fadd9ce7fe9c229848debef9c7..ddaae89a8537d3f57997ec37a8b7638f286bf0b6 100644 --- a/include/hw/isa/isa.h +++ b/include/hw/isa/isa.h @@ -6,19 +6,15 @@ #include "exec/memory.h" #include "exec/ioport.h" #include "hw/qdev-core.h" +#include "qom/object.h" #define ISA_NUM_IRQS 16 #define TYPE_ISA_DEVICE "isa-device" -#define ISA_DEVICE(obj) \ - OBJECT_CHECK(ISADevice, (obj), TYPE_ISA_DEVICE) -#define ISA_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(ISADeviceClass, (klass), TYPE_ISA_DEVICE) -#define ISA_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ISADeviceClass, (obj), TYPE_ISA_DEVICE) +OBJECT_DECLARE_TYPE(ISADevice, ISADeviceClass, ISA_DEVICE) #define TYPE_ISA_BUS "ISA" -#define ISA_BUS(obj) OBJECT_CHECK(ISABus, (obj), TYPE_ISA_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(ISABus, ISA_BUS) #define TYPE_APPLE_SMC "isa-applesmc" #define APPLESMC_MAX_DATA_LENGTH 32 @@ -36,10 +32,9 @@ static inline uint16_t applesmc_port(void) #define TYPE_ISADMA "isa-dma" -#define ISADMA_CLASS(klass) \ - OBJECT_CLASS_CHECK(IsaDmaClass, (klass), TYPE_ISADMA) -#define ISADMA_GET_CLASS(obj) \ - OBJECT_GET_CLASS(IsaDmaClass, (obj), TYPE_ISADMA) +typedef struct IsaDmaClass IsaDmaClass; +DECLARE_CLASS_CHECKERS(IsaDmaClass, ISADMA, + TYPE_ISADMA) #define ISADMA(obj) \ INTERFACE_CHECK(IsaDma, (obj), TYPE_ISADMA) @@ -53,7 +48,7 @@ typedef enum { typedef int (*IsaDmaTransferHandler)(void *opaque, int nchan, int pos, int size); -typedef struct IsaDmaClass { +struct IsaDmaClass { InterfaceClass parent; bool (*has_autoinitialization)(IsaDma *obj, int nchan); @@ -65,12 +60,12 @@ typedef struct IsaDmaClass { void (*register_channel)(IsaDma *obj, int nchan, IsaDmaTransferHandler transfer_handler, void *opaque); -} IsaDmaClass; +}; -typedef struct ISADeviceClass { +struct ISADeviceClass { DeviceClass parent_class; void (*build_aml)(ISADevice *dev, Aml *scope); -} ISADeviceClass; +}; struct ISABus { /*< private >*/ @@ -103,8 +98,9 @@ void isa_bus_dma(ISABus *bus, IsaDma *dma8, IsaDma *dma16); IsaDma *isa_get_dma(ISABus *bus, int nchan); MemoryRegion *isa_address_space(ISADevice *dev); MemoryRegion *isa_address_space_io(ISADevice *dev); -ISADevice *isa_create(ISABus *bus, const char *name); -ISADevice *isa_try_create(ISABus *bus, const char *name); +ISADevice *isa_new(const char *name); +ISADevice *isa_try_new(const char *name); +bool isa_realize_and_unref(ISADevice *dev, ISABus *bus, Error **errp); ISADevice *isa_create_simple(ISABus *bus, const char *name); ISADevice *isa_vga_init(ISABus *bus); diff --git a/include/hw/isa/pc87312.h b/include/hw/isa/pc87312.h index e16263d4b1381f357c930fed31f9b7d11da2f329..edaf723f4d2fd1dec0c578eccf6d180a2f4c93f6 100644 --- a/include/hw/isa/pc87312.h +++ b/include/hw/isa/pc87312.h @@ -26,12 +26,13 @@ #define QEMU_PC87312_H #include "hw/isa/superio.h" +#include "qom/object.h" -#define TYPE_PC87312_SUPERIO "pc87312" -#define PC87312(obj) OBJECT_CHECK(PC87312State, (obj), TYPE_PC87312_SUPERIO) +#define TYPE_PC87312 "pc87312" +OBJECT_DECLARE_SIMPLE_TYPE(PC87312State, PC87312) -typedef struct PC87312State { +struct PC87312State { /*< private >*/ ISASuperIODevice parent_dev; /*< public >*/ @@ -49,7 +50,7 @@ typedef struct PC87312State { uint8_t selected_index; uint8_t regs[3]; -} PC87312State; +}; #endif diff --git a/include/hw/isa/superio.h b/include/hw/isa/superio.h index 147cc0a7b751dc46598bd1b35c3e6f7633e8d66f..b9f5c19155f25c8be4bc14cc33c445024f7a9fe4 100644 --- a/include/hw/isa/superio.h +++ b/include/hw/isa/superio.h @@ -12,18 +12,17 @@ #include "sysemu/sysemu.h" #include "hw/isa/isa.h" +#include "qom/object.h" #define TYPE_ISA_SUPERIO "isa-superio" -#define ISA_SUPERIO(obj) \ - OBJECT_CHECK(ISASuperIODevice, (obj), TYPE_ISA_SUPERIO) -#define ISA_SUPERIO_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ISASuperIOClass, (obj), TYPE_ISA_SUPERIO) -#define ISA_SUPERIO_CLASS(klass) \ - OBJECT_CLASS_CHECK(ISASuperIOClass, (klass), TYPE_ISA_SUPERIO) +typedef struct ISASuperIOClass ISASuperIOClass; +typedef struct ISASuperIODevice ISASuperIODevice; +DECLARE_OBJ_CHECKERS(ISASuperIODevice, ISASuperIOClass, + ISA_SUPERIO, TYPE_ISA_SUPERIO) #define SUPERIO_MAX_SERIAL_PORTS 4 -typedef struct ISASuperIODevice { +struct ISASuperIODevice { /*< private >*/ ISADevice parent_obj; /*< public >*/ @@ -33,7 +32,7 @@ typedef struct ISASuperIODevice { ISADevice *floppy; ISADevice *kbc; ISADevice *ide; -} ISASuperIODevice; +}; typedef struct ISASuperIOFuncs { size_t count; @@ -43,7 +42,7 @@ typedef struct ISASuperIOFuncs { unsigned int (*get_dma)(ISASuperIODevice *sio, uint8_t index); } ISASuperIOFuncs; -typedef struct ISASuperIOClass { +struct ISASuperIOClass { /*< private >*/ ISADeviceClass parent_class; /*< public >*/ @@ -53,7 +52,7 @@ typedef struct ISASuperIOClass { ISASuperIOFuncs serial; ISASuperIOFuncs floppy; ISASuperIOFuncs ide; -} ISASuperIOClass; +}; #define TYPE_FDC37M81X_SUPERIO "fdc37m81x-superio" #define TYPE_SMC37C669_SUPERIO "smc37c669-superio" diff --git a/include/hw/kvm/clock.h b/include/hw/kvm/clock.h index 81c66b2302076fe657509033d0455060cda9fba6..7994071c4feeaa9581fc59d704befdcb508c1454 100644 --- a/include/hw/kvm/clock.h +++ b/include/hw/kvm/clock.h @@ -15,11 +15,11 @@ #ifdef CONFIG_KVM -void kvmclock_create(void); +void kvmclock_create(bool create_always); #else /* CONFIG_KVM */ -static inline void kvmclock_create(void) +static inline void kvmclock_create(bool create_always) { } diff --git a/include/hw/loader-fit.h b/include/hw/loader-fit.h index 0284c3e02ce7226675429c0801a4aaca2832842e..0832e379dc9060b7debc492605e4862156837296 100644 --- a/include/hw/loader-fit.h +++ b/include/hw/loader-fit.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/hw/m68k/mcf.h b/include/hw/m68k/mcf.h index 0db49c5e6018330d5b8300265757fe084d0a1817..decf17ce42e9556d3d9d1a8302e13ff752a1c797 100644 --- a/include/hw/m68k/mcf.h +++ b/include/hw/m68k/mcf.h @@ -18,7 +18,6 @@ qemu_irq *mcf_intc_init(struct MemoryRegion *sysmem, M68kCPU *cpu); /* mcf5206.c */ -qemu_irq *mcf5206_init(struct MemoryRegion *sysmem, - uint32_t base, M68kCPU *cpu); +#define TYPE_MCF5206_MBAR "mcf5206-mbar" #endif diff --git a/include/hw/m68k/mcf_fec.h b/include/hw/m68k/mcf_fec.h index eeb471f9c9c598ed32645909fd743a8152e54cd5..80d4f651ba32fc8ff80d69967d3ba70acf413d79 100644 --- a/include/hw/m68k/mcf_fec.h +++ b/include/hw/m68k/mcf_fec.h @@ -9,9 +9,10 @@ #ifndef HW_M68K_MCF_FEC_H #define HW_M68K_MCF_FEC_H +#include "qom/object.h" #define TYPE_MCF_FEC_NET "mcf-fec" -#define MCF_FEC_NET(obj) OBJECT_CHECK(mcf_fec_state, (obj), TYPE_MCF_FEC_NET) +OBJECT_DECLARE_SIMPLE_TYPE(mcf_fec_state, MCF_FEC_NET) #define FEC_NUM_IRQ 13 diff --git a/include/hw/mem/memory-device.h b/include/hw/mem/memory-device.h index 04476acb8fa60b218e8f0016319fabfd6cc82a0f..48d2611fc5eff8911040e0e4fa19dbd533e97616 100644 --- a/include/hw/mem/memory-device.h +++ b/include/hw/mem/memory-device.h @@ -14,15 +14,14 @@ #define MEMORY_DEVICE_H #include "hw/qdev-core.h" -#include "qapi/qapi-types-misc.h" +#include "qapi/qapi-types-machine.h" #include "qom/object.h" #define TYPE_MEMORY_DEVICE "memory-device" -#define MEMORY_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(MemoryDeviceClass, (klass), TYPE_MEMORY_DEVICE) -#define MEMORY_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(MemoryDeviceClass, (obj), TYPE_MEMORY_DEVICE) +typedef struct MemoryDeviceClass MemoryDeviceClass; +DECLARE_CLASS_CHECKERS(MemoryDeviceClass, MEMORY_DEVICE, + TYPE_MEMORY_DEVICE) #define MEMORY_DEVICE(obj) \ INTERFACE_CHECK(MemoryDeviceState, (obj), TYPE_MEMORY_DEVICE) @@ -43,7 +42,7 @@ typedef struct MemoryDeviceState MemoryDeviceState; * be provided. Scattered memory regions are not supported for single * devices. */ -typedef struct MemoryDeviceClass { +struct MemoryDeviceClass { /* private */ InterfaceClass parent_class; @@ -89,12 +88,22 @@ typedef struct MemoryDeviceClass { */ MemoryRegion *(*get_memory_region)(MemoryDeviceState *md, Error **errp); + /* + * Optional: Return the desired minimum alignment of the device in guest + * physical address space. The final alignment is computed based on this + * alignment and the alignment requirements of the memory region. + * + * Called when plugging the memory device to detect the required alignment + * during address assignment. + */ + uint64_t (*get_min_alignment)(const MemoryDeviceState *md); + /* * Translate the memory device into #MemoryDeviceInfo. */ void (*fill_device_info)(const MemoryDeviceState *md, MemoryDeviceInfo *info); -} MemoryDeviceClass; +}; MemoryDeviceInfoList *qmp_memory_device_list(void); uint64_t get_plugged_memory_size(void); diff --git a/include/hw/mem/npcm7xx_mc.h b/include/hw/mem/npcm7xx_mc.h new file mode 100644 index 0000000000000000000000000000000000000000..7ed38be2431f909ae051f1920bd3ee914fc1c8c0 --- /dev/null +++ b/include/hw/mem/npcm7xx_mc.h @@ -0,0 +1,36 @@ +/* + * Nuvoton NPCM7xx Memory Controller stub + * + * Copyright 2020 Google LLC + * + * 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. + */ +#ifndef NPCM7XX_MC_H +#define NPCM7XX_MC_H + +#include "exec/memory.h" +#include "hw/sysbus.h" + +/** + * struct NPCM7xxMCState - Device state for the memory controller. + * @parent: System bus device. + * @mmio: Memory region through which registers are accessed. + */ +typedef struct NPCM7xxMCState { + SysBusDevice parent; + + MemoryRegion mmio; +} NPCM7xxMCState; + +#define TYPE_NPCM7XX_MC "npcm7xx-mc" +#define NPCM7XX_MC(obj) OBJECT_CHECK(NPCM7xxMCState, (obj), TYPE_NPCM7XX_MC) + +#endif /* NPCM7XX_MC_H */ diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h index a3c08955e879d408cd14c8ad155173dfd7a4283f..c699842dd05f920baa777fbf1db47bf7e6c131b2 100644 --- a/include/hw/mem/nvdimm.h +++ b/include/hw/mem/nvdimm.h @@ -27,6 +27,7 @@ #include "hw/acpi/bios-linker-loader.h" #include "qemu/uuid.h" #include "hw/acpi/aml-build.h" +#include "qom/object.h" #define NVDIMM_DEBUG 0 #define nvdimm_debug(fmt, ...) \ @@ -45,10 +46,7 @@ #define MIN_NAMESPACE_LABEL_SIZE (128UL << 10) #define TYPE_NVDIMM "nvdimm" -#define NVDIMM(obj) OBJECT_CHECK(NVDIMMDevice, (obj), TYPE_NVDIMM) -#define NVDIMM_CLASS(oc) OBJECT_CLASS_CHECK(NVDIMMClass, (oc), TYPE_NVDIMM) -#define NVDIMM_GET_CLASS(obj) OBJECT_GET_CLASS(NVDIMMClass, (obj), \ - TYPE_NVDIMM) +OBJECT_DECLARE_TYPE(NVDIMMDevice, NVDIMMClass, NVDIMM) #define NVDIMM_LABEL_SIZE_PROP "label-size" #define NVDIMM_UUID_PROP "uuid" @@ -92,7 +90,6 @@ struct NVDIMMDevice { */ QemuUUID uuid; }; -typedef struct NVDIMMDevice NVDIMMDevice; struct NVDIMMClass { /* private */ @@ -107,7 +104,6 @@ struct NVDIMMClass { void (*write_label_data)(NVDIMMDevice *nvdimm, const void *buf, uint64_t size, uint64_t offset); }; -typedef struct NVDIMMClass NVDIMMClass; #define NVDIMM_DSM_MEM_FILE "etc/acpi/nvdimm-mem" @@ -155,6 +151,7 @@ typedef struct NVDIMMState NVDIMMState; void nvdimm_init_acpi_state(NVDIMMState *state, MemoryRegion *io, struct AcpiGenericAddress dsm_io, FWCfgState *fw_cfg, Object *owner); +void nvdimm_build_srat(GArray *table_data); void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data, BIOSLinker *linker, NVDIMMState *state, uint32_t ram_slots); diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h index 289edc0f3d347526a12697b579b34004bf5f40eb..3d3db82641f8332108d2c6d282ae246400ab7c66 100644 --- a/include/hw/mem/pc-dimm.h +++ b/include/hw/mem/pc-dimm.h @@ -18,14 +18,11 @@ #include "exec/memory.h" #include "hw/qdev-core.h" +#include "qom/object.h" #define TYPE_PC_DIMM "pc-dimm" -#define PC_DIMM(obj) \ - OBJECT_CHECK(PCDIMMDevice, (obj), TYPE_PC_DIMM) -#define PC_DIMM_CLASS(oc) \ - OBJECT_CLASS_CHECK(PCDIMMDeviceClass, (oc), TYPE_PC_DIMM) -#define PC_DIMM_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PCDIMMDeviceClass, (obj), TYPE_PC_DIMM) +OBJECT_DECLARE_TYPE(PCDIMMDevice, PCDIMMDeviceClass, + PC_DIMM) #define PC_DIMM_ADDR_PROP "addr" #define PC_DIMM_SLOT_PROP "slot" @@ -44,7 +41,7 @@ * Default value: -1, means that slot is auto-allocated. * @hostmem: host memory backend providing memory for @PCDIMMDevice */ -typedef struct PCDIMMDevice { +struct PCDIMMDevice { /* private */ DeviceState parent_obj; @@ -53,7 +50,7 @@ typedef struct PCDIMMDevice { uint32_t node; int32_t slot; HostMemoryBackend *hostmem; -} PCDIMMDevice; +}; /** * PCDIMMDeviceClass: @@ -63,7 +60,7 @@ typedef struct PCDIMMDevice { * memory of @dimm should be kept during live migration. Will not fail * after the device was realized. */ -typedef struct PCDIMMDeviceClass { +struct PCDIMMDeviceClass { /* private */ DeviceClass parent_class; @@ -71,10 +68,10 @@ typedef struct PCDIMMDeviceClass { void (*realize)(PCDIMMDevice *dimm, Error **errp); MemoryRegion *(*get_vmstate_memory_region)(PCDIMMDevice *dimm, Error **errp); -} PCDIMMDeviceClass; +}; void pc_dimm_pre_plug(PCDIMMDevice *dimm, MachineState *machine, const uint64_t *legacy_align, Error **errp); -void pc_dimm_plug(PCDIMMDevice *dimm, MachineState *machine, Error **errp); +void pc_dimm_plug(PCDIMMDevice *dimm, MachineState *machine); void pc_dimm_unplug(PCDIMMDevice *dimm, MachineState *machine); #endif diff --git a/include/hw/mips/cps.h b/include/hw/mips/cps.h index a941c55f27e7f6619a92f054eb21a57ff84c7d94..04d636246ab23123c99b95d3de8311cffcb57a33 100644 --- a/include/hw/mips/cps.h +++ b/include/hw/mips/cps.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -21,16 +21,18 @@ #define MIPS_CPS_H #include "hw/sysbus.h" +#include "hw/clock.h" #include "hw/misc/mips_cmgcr.h" #include "hw/intc/mips_gic.h" #include "hw/misc/mips_cpc.h" #include "hw/misc/mips_itu.h" #include "target/mips/cpu.h" +#include "qom/object.h" #define TYPE_MIPS_CPS "mips-cps" -#define MIPS_CPS(obj) OBJECT_CHECK(MIPSCPSState, (obj), TYPE_MIPS_CPS) +OBJECT_DECLARE_SIMPLE_TYPE(MIPSCPSState, MIPS_CPS) -typedef struct MIPSCPSState { +struct MIPSCPSState { SysBusDevice parent_obj; uint32_t num_vp; @@ -42,7 +44,8 @@ typedef struct MIPSCPSState { MIPSGICState gic; MIPSCPCState cpc; MIPSITUState itu; -} MIPSCPSState; + Clock *clock; +}; qemu_irq get_cps_irq(MIPSCPSState *cps, int pin_number); diff --git a/include/hw/mips/mips.h b/include/hw/mips/mips.h index 0af4c3d5d74f566910be7021878179da41ce3236..6c9c8805f3f0c9167e54153d21963ebef32620e2 100644 --- a/include/hw/mips/mips.h +++ b/include/hw/mips/mips.h @@ -2,8 +2,10 @@ #define HW_MIPS_H /* Definitions for mips board emulation. */ +#include "qemu/units.h" + /* Kernels can be configured with 64KB pages */ -#define INITRD_PAGE_MASK (~((1 << 16) - 1)) +#define INITRD_PAGE_SIZE (64 * KiB) #include "exec/memory.h" diff --git a/include/hw/misc/a9scu.h b/include/hw/misc/a9scu.h index efb0c305c22929239caa0fed7f44a1e36b122860..c3759fb8c8c0dbdc0ce517e15e61c136d8c304c7 100644 --- a/include/hw/misc/a9scu.h +++ b/include/hw/misc/a9scu.h @@ -11,10 +11,11 @@ #define HW_MISC_A9SCU_H #include "hw/sysbus.h" +#include "qom/object.h" /* A9MP private memory region. */ -typedef struct A9SCUState { +struct A9SCUState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -23,9 +24,9 @@ typedef struct A9SCUState { uint32_t control; uint32_t status; uint32_t num_cpu; -} A9SCUState; +}; #define TYPE_A9_SCU "a9-scu" -#define A9_SCU(obj) OBJECT_CHECK(A9SCUState, (obj), TYPE_A9_SCU) +OBJECT_DECLARE_SIMPLE_TYPE(A9SCUState, A9_SCU) #endif diff --git a/include/hw/misc/allwinner-cpucfg.h b/include/hw/misc/allwinner-cpucfg.h index 2c3693a8bec9bf2d0b70eeb807657d26fa313bae..a717b47299a9e4e5c1ec9964f111e8959e3a72be 100644 --- a/include/hw/misc/allwinner-cpucfg.h +++ b/include/hw/misc/allwinner-cpucfg.h @@ -29,15 +29,14 @@ */ #define TYPE_AW_CPUCFG "allwinner-cpucfg" -#define AW_CPUCFG(obj) \ - OBJECT_CHECK(AwCpuCfgState, (obj), TYPE_AW_CPUCFG) +OBJECT_DECLARE_SIMPLE_TYPE(AwCpuCfgState, AW_CPUCFG) /** @} */ /** * Allwinner CPU Configuration Module instance state */ -typedef struct AwCpuCfgState { +struct AwCpuCfgState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -47,6 +46,6 @@ typedef struct AwCpuCfgState { uint32_t super_standby; uint32_t entry_addr; -} AwCpuCfgState; +}; #endif /* HW_MISC_ALLWINNER_CPUCFG_H */ diff --git a/include/hw/misc/allwinner-h3-ccu.h b/include/hw/misc/allwinner-h3-ccu.h index eec59649f318a76a63239fcd7cfd3d25afd12e3e..a04875bfca38f6f7acf36141431efd4145f2ca5b 100644 --- a/include/hw/misc/allwinner-h3-ccu.h +++ b/include/hw/misc/allwinner-h3-ccu.h @@ -42,15 +42,14 @@ */ #define TYPE_AW_H3_CCU "allwinner-h3-ccu" -#define AW_H3_CCU(obj) \ - OBJECT_CHECK(AwH3ClockCtlState, (obj), TYPE_AW_H3_CCU) +OBJECT_DECLARE_SIMPLE_TYPE(AwH3ClockCtlState, AW_H3_CCU) /** @} */ /** * Allwinner H3 CCU object instance state. */ -typedef struct AwH3ClockCtlState { +struct AwH3ClockCtlState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -61,6 +60,6 @@ typedef struct AwH3ClockCtlState { /** Array of hardware registers */ uint32_t regs[AW_H3_CCU_REGS_NUM]; -} AwH3ClockCtlState; +}; #endif /* HW_MISC_ALLWINNER_H3_CCU_H */ diff --git a/include/hw/misc/allwinner-h3-dramc.h b/include/hw/misc/allwinner-h3-dramc.h index bacdf236b78f8109b638fc2718ca71ee82b174e4..0b6c877ef74788f126d8e2e22683542a21164490 100644 --- a/include/hw/misc/allwinner-h3-dramc.h +++ b/include/hw/misc/allwinner-h3-dramc.h @@ -58,15 +58,14 @@ */ #define TYPE_AW_H3_DRAMC "allwinner-h3-dramc" -#define AW_H3_DRAMC(obj) \ - OBJECT_CHECK(AwH3DramCtlState, (obj), TYPE_AW_H3_DRAMC) +OBJECT_DECLARE_SIMPLE_TYPE(AwH3DramCtlState, AW_H3_DRAMC) /** @} */ /** * Allwinner H3 SDRAM Controller object instance state. */ -typedef struct AwH3DramCtlState { +struct AwH3DramCtlState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -101,6 +100,6 @@ typedef struct AwH3DramCtlState { /** @} */ -} AwH3DramCtlState; +}; #endif /* HW_MISC_ALLWINNER_H3_DRAMC_H */ diff --git a/include/hw/misc/allwinner-h3-sysctrl.h b/include/hw/misc/allwinner-h3-sysctrl.h index af4119e0269c85cf5d4cef8260ae40f058997b8e..ec1c220535eb0cfa275b83422b2f47385d882e94 100644 --- a/include/hw/misc/allwinner-h3-sysctrl.h +++ b/include/hw/misc/allwinner-h3-sysctrl.h @@ -43,15 +43,14 @@ */ #define TYPE_AW_H3_SYSCTRL "allwinner-h3-sysctrl" -#define AW_H3_SYSCTRL(obj) \ - OBJECT_CHECK(AwH3SysCtrlState, (obj), TYPE_AW_H3_SYSCTRL) +OBJECT_DECLARE_SIMPLE_TYPE(AwH3SysCtrlState, AW_H3_SYSCTRL) /** @} */ /** * Allwinner H3 System Control object instance state */ -typedef struct AwH3SysCtrlState { +struct AwH3SysCtrlState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -62,6 +61,6 @@ typedef struct AwH3SysCtrlState { /** Array of hardware registers */ uint32_t regs[AW_H3_SYSCTRL_REGS_NUM]; -} AwH3SysCtrlState; +}; #endif /* HW_MISC_ALLWINNER_H3_SYSCTRL_H */ diff --git a/include/hw/misc/allwinner-sid.h b/include/hw/misc/allwinner-sid.h index 4c1fa4762b98aea6afa47a6e5ac69477ddefa9da..3bfa887a9691ad40aaf5ad992a235a31d8cc5a18 100644 --- a/include/hw/misc/allwinner-sid.h +++ b/include/hw/misc/allwinner-sid.h @@ -30,15 +30,14 @@ */ #define TYPE_AW_SID "allwinner-sid" -#define AW_SID(obj) \ - OBJECT_CHECK(AwSidState, (obj), TYPE_AW_SID) +OBJECT_DECLARE_SIMPLE_TYPE(AwSidState, AW_SID) /** @} */ /** * Allwinner Security ID object instance state */ -typedef struct AwSidState { +struct AwSidState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -55,6 +54,6 @@ typedef struct AwSidState { /** Stores the emulated device identifier */ QemuUUID identifier; -} AwSidState; +}; #endif /* HW_MISC_ALLWINNER_SID_H */ diff --git a/include/hw/misc/arm11scu.h b/include/hw/misc/arm11scu.h index 5ad0f3d3396972e9ccb92bbe24c33f1ec80db21f..e5c0282aecfd29d245fdf0812eb4f8e3eb3ef73f 100644 --- a/include/hw/misc/arm11scu.h +++ b/include/hw/misc/arm11scu.h @@ -12,11 +12,12 @@ #define HW_MISC_ARM11SCU_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_ARM11_SCU "arm11-scu" -#define ARM11_SCU(obj) OBJECT_CHECK(ARM11SCUState, (obj), TYPE_ARM11_SCU) +OBJECT_DECLARE_SIMPLE_TYPE(ARM11SCUState, ARM11_SCU) -typedef struct ARM11SCUState { +struct ARM11SCUState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -24,6 +25,6 @@ typedef struct ARM11SCUState { uint32_t control; uint32_t num_cpu; MemoryRegion iomem; -} ARM11SCUState; +}; #endif diff --git a/include/hw/misc/armsse-cpuid.h b/include/hw/misc/armsse-cpuid.h index 0ef33fcaba28d7b9e83c60588194c33869144cc2..a61355e5161a66281d6858169588b38e32420218 100644 --- a/include/hw/misc/armsse-cpuid.h +++ b/include/hw/misc/armsse-cpuid.h @@ -23,11 +23,12 @@ #define HW_MISC_ARMSSE_CPUID_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_ARMSSE_CPUID "armsse-cpuid" -#define ARMSSE_CPUID(obj) OBJECT_CHECK(ARMSSECPUID, (obj), TYPE_ARMSSE_CPUID) +OBJECT_DECLARE_SIMPLE_TYPE(ARMSSECPUID, ARMSSE_CPUID) -typedef struct ARMSSECPUID { +struct ARMSSECPUID { /*< private >*/ SysBusDevice parent_obj; @@ -36,6 +37,6 @@ typedef struct ARMSSECPUID { /* Properties */ uint32_t cpuid; -} ARMSSECPUID; +}; #endif diff --git a/include/hw/misc/armsse-mhu.h b/include/hw/misc/armsse-mhu.h index cf5d8a73e6f8a86549bab74d14e7a00efac2b692..2671b5b978b05eede23b4e13b76af91fa3e6db6b 100644 --- a/include/hw/misc/armsse-mhu.h +++ b/include/hw/misc/armsse-mhu.h @@ -24,11 +24,12 @@ #define HW_MISC_ARMSSE_MHU_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_ARMSSE_MHU "armsse-mhu" -#define ARMSSE_MHU(obj) OBJECT_CHECK(ARMSSEMHU, (obj), TYPE_ARMSSE_MHU) +OBJECT_DECLARE_SIMPLE_TYPE(ARMSSEMHU, ARMSSE_MHU) -typedef struct ARMSSEMHU { +struct ARMSSEMHU { /*< private >*/ SysBusDevice parent_obj; @@ -39,6 +40,6 @@ typedef struct ARMSSEMHU { uint32_t cpu0intr; uint32_t cpu1intr; -} ARMSSEMHU; +}; #endif diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h index a6739bb846b6cd6a73c39c764de2a6ee09450271..d49bfb02fbdb433cc40020562cd9f9d05a410ca4 100644 --- a/include/hw/misc/aspeed_scu.h +++ b/include/hw/misc/aspeed_scu.h @@ -12,9 +12,10 @@ #define ASPEED_SCU_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_ASPEED_SCU "aspeed.scu" -#define ASPEED_SCU(obj) OBJECT_CHECK(AspeedSCUState, (obj), TYPE_ASPEED_SCU) +OBJECT_DECLARE_TYPE(AspeedSCUState, AspeedSCUClass, ASPEED_SCU) #define TYPE_ASPEED_2400_SCU TYPE_ASPEED_SCU "-ast2400" #define TYPE_ASPEED_2500_SCU TYPE_ASPEED_SCU "-ast2500" #define TYPE_ASPEED_2600_SCU TYPE_ASPEED_SCU "-ast2600" @@ -22,7 +23,7 @@ #define ASPEED_SCU_NR_REGS (0x1A8 >> 2) #define ASPEED_AST2600_SCU_NR_REGS (0xE20 >> 2) -typedef struct AspeedSCUState { +struct AspeedSCUState { /*< private >*/ SysBusDevice parent_obj; @@ -34,7 +35,7 @@ typedef struct AspeedSCUState { uint32_t hw_strap1; uint32_t hw_strap2; uint32_t hw_prot_key; -} AspeedSCUState; +}; #define AST2400_A0_SILICON_REV 0x02000303U #define AST2400_A1_SILICON_REV 0x02010303U @@ -47,12 +48,8 @@ typedef struct AspeedSCUState { extern bool is_supported_silicon_rev(uint32_t silicon_rev); -#define ASPEED_SCU_CLASS(klass) \ - OBJECT_CLASS_CHECK(AspeedSCUClass, (klass), TYPE_ASPEED_SCU) -#define ASPEED_SCU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(AspeedSCUClass, (obj), TYPE_ASPEED_SCU) -typedef struct AspeedSCUClass { +struct AspeedSCUClass { SysBusDeviceClass parent_class; const uint32_t *resets; @@ -60,7 +57,7 @@ typedef struct AspeedSCUClass { uint32_t apb_divider; uint32_t nr_regs; const MemoryRegionOps *ops; -} AspeedSCUClass; +}; #define ASPEED_SCU_PROT_KEY 0x1688A8A8 @@ -286,6 +283,7 @@ uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s); #define SCU_AST2500_HW_STRAP_ESPI_FLASH_ENABLE (0x1 << 26) #define SCU_AST2500_HW_STRAP_ESPI_ENABLE (0x1 << 25) #define SCU_AST2500_HW_STRAP_DDR4_ENABLE (0x1 << 24) +#define SCU_AST2500_HW_STRAP_25HZ_CLOCK_MODE (0x1 << 23) #define SCU_AST2500_HW_STRAP_ACPI_ENABLE (0x1 << 19) #define SCU_AST2500_HW_STRAP_USBCKI_FREQ (0x1 << 18) diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h index cea1e67fe365a7cae0c872eb4de24ef599822b7e..ec2d59a14f57d0d72f2e751d573e7a8296144375 100644 --- a/include/hw/misc/aspeed_sdmc.h +++ b/include/hw/misc/aspeed_sdmc.h @@ -10,16 +10,28 @@ #define ASPEED_SDMC_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_ASPEED_SDMC "aspeed.sdmc" -#define ASPEED_SDMC(obj) OBJECT_CHECK(AspeedSDMCState, (obj), TYPE_ASPEED_SDMC) +OBJECT_DECLARE_TYPE(AspeedSDMCState, AspeedSDMCClass, ASPEED_SDMC) #define TYPE_ASPEED_2400_SDMC TYPE_ASPEED_SDMC "-ast2400" #define TYPE_ASPEED_2500_SDMC TYPE_ASPEED_SDMC "-ast2500" #define TYPE_ASPEED_2600_SDMC TYPE_ASPEED_SDMC "-ast2600" -#define ASPEED_SDMC_NR_REGS (0x174 >> 2) +/* + * SDMC has 174 documented registers. In addition the u-boot device tree + * describes the following regions: + * - PHY status regs at offset 0x400, length 0x200 + * - PHY setting regs at offset 0x100, length 0x300 + * + * There are two sets of MRS (Mode Registers) configuration in ast2600 memory + * system: one is in the SDRAM MC (memory controller) which is used in run + * time, and the other is in the DDR-PHY IP which is used during DDR-PHY + * training. + */ +#define ASPEED_SDMC_NR_REGS (0x500 >> 2) -typedef struct AspeedSDMCState { +struct AspeedSDMCState { /*< private >*/ SysBusDevice parent_obj; @@ -29,20 +41,16 @@ typedef struct AspeedSDMCState { uint32_t regs[ASPEED_SDMC_NR_REGS]; uint64_t ram_size; uint64_t max_ram_size; -} AspeedSDMCState; +}; -#define ASPEED_SDMC_CLASS(klass) \ - OBJECT_CLASS_CHECK(AspeedSDMCClass, (klass), TYPE_ASPEED_SDMC) -#define ASPEED_SDMC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(AspeedSDMCClass, (obj), TYPE_ASPEED_SDMC) -typedef struct AspeedSDMCClass { +struct AspeedSDMCClass { SysBusDeviceClass parent_class; uint64_t max_ram_size; const uint64_t *valid_ram_sizes; uint32_t (*compute_conf)(AspeedSDMCState *s, uint32_t data); void (*write)(AspeedSDMCState *s, uint32_t reg, uint32_t data); -} AspeedSDMCClass; +}; #endif /* ASPEED_SDMC_H */ diff --git a/include/hw/misc/aspeed_xdma.h b/include/hw/misc/aspeed_xdma.h index 00b45d931f8769d43d0a8f79bd4da6061f7958df..9869ef472895367b71ddeb7e8e9bda90058782fa 100644 --- a/include/hw/misc/aspeed_xdma.h +++ b/include/hw/misc/aspeed_xdma.h @@ -10,14 +10,15 @@ #define ASPEED_XDMA_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_ASPEED_XDMA "aspeed.xdma" -#define ASPEED_XDMA(obj) OBJECT_CHECK(AspeedXDMAState, (obj), TYPE_ASPEED_XDMA) +OBJECT_DECLARE_SIMPLE_TYPE(AspeedXDMAState, ASPEED_XDMA) #define ASPEED_XDMA_NUM_REGS (ASPEED_XDMA_REG_SIZE / sizeof(uint32_t)) #define ASPEED_XDMA_REG_SIZE 0x7C -typedef struct AspeedXDMAState { +struct AspeedXDMAState { SysBusDevice parent; MemoryRegion iomem; @@ -25,6 +26,6 @@ typedef struct AspeedXDMAState { char bmc_cmdq_readp_set; uint32_t regs[ASPEED_XDMA_NUM_REGS]; -} AspeedXDMAState; +}; #endif /* ASPEED_XDMA_H */ diff --git a/include/hw/misc/auxbus.h b/include/hw/misc/auxbus.h index a539a98c4b67f7f849bd68807b396dd67793d7bf..b05799d2f7a944fb667607b4326e2278f17b8a12 100644 --- a/include/hw/misc/auxbus.h +++ b/include/hw/misc/auxbus.h @@ -27,12 +27,14 @@ #include "exec/memory.h" #include "hw/qdev-core.h" +#include "qom/object.h" -typedef struct AUXBus AUXBus; typedef struct AUXSlave AUXSlave; typedef enum AUXCommand AUXCommand; typedef enum AUXReply AUXReply; -typedef struct AUXTOI2CState AUXTOI2CState; + +#define TYPE_AUXTOI2C "aux-to-i2c-bridge" +OBJECT_DECLARE_SIMPLE_TYPE(AUXTOI2CState, AUXTOI2C) enum AUXCommand { WRITE_I2C = 0, @@ -53,7 +55,7 @@ enum AUXReply { }; #define TYPE_AUX_BUS "aux-bus" -#define AUX_BUS(obj) OBJECT_CHECK(AUXBus, (obj), TYPE_AUX_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(AUXBus, AUX_BUS) struct AUXBus { /* < private > */ @@ -72,8 +74,7 @@ struct AUXBus { }; #define TYPE_AUX_SLAVE "aux-slave" -#define AUX_SLAVE(obj) \ - OBJECT_CHECK(AUXSlave, (obj), TYPE_AUX_SLAVE) +OBJECT_DECLARE_SIMPLE_TYPE(AUXSlave, AUX_SLAVE) struct AUXSlave { /* < private > */ @@ -84,14 +85,21 @@ struct AUXSlave { }; /** - * aux_init_bus: Initialize an AUX bus. + * aux_bus_init: Initialize an AUX bus. * * Returns the new AUX bus created. * * @parent The device where this bus is located. * @name The name of the bus. */ -AUXBus *aux_init_bus(DeviceState *parent, const char *name); +AUXBus *aux_bus_init(DeviceState *parent, const char *name); + +/** + * aux_bus_realize: Realize an AUX bus. + * + * @bus: The AUX bus. + */ +void aux_bus_realize(AUXBus *bus); /* * aux_request: Make a request on the bus. @@ -124,13 +132,6 @@ I2CBus *aux_get_i2c_bus(AUXBus *bus); */ void aux_init_mmio(AUXSlave *aux_slave, MemoryRegion *mmio); -/* aux_create_slave: Create a new device on an AUX bus - * - * @bus The AUX bus for the new device. - * @name The type of the device to be created. - */ -DeviceState *aux_create_slave(AUXBus *bus, const char *name); - /* aux_map_slave: Map the mmio for an AUX slave on the bus. * * @dev The AUX slave. diff --git a/hw/i386/vmport.h b/include/hw/misc/avr_power.h similarity index 69% rename from hw/i386/vmport.h rename to include/hw/misc/avr_power.h index 47eda7a22b54b832bb53376f3585f24dd6814827..707df030b1875f1fe2a203a72b98efeb6edbb2d3 100644 --- a/hw/i386/vmport.h +++ b/include/hw/misc/avr_power.h @@ -1,7 +1,7 @@ /* - * QEMU VMPort emulation + * AVR Power Reduction Management * - * Copyright (C) 2007 HervĂ© Poussineau + * Copyright (c) 2019-2020 Michael Rolnik * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,13 +22,26 @@ * THE SOFTWARE. */ -#ifndef HW_I386_VMPORT_H -#define HW_I386_VMPORT_H +#ifndef HW_MISC_AVR_POWER_H +#define HW_MISC_AVR_POWER_H -#define TYPE_VMPORT "vmport" +#include "hw/sysbus.h" +#include "hw/hw.h" +#include "qom/object.h" -typedef uint32_t (VMPortReadFunc)(void *opaque, uint32_t address); -void vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque); +#define TYPE_AVR_MASK "avr-power" +OBJECT_DECLARE_SIMPLE_TYPE(AVRMaskState, AVR_MASK) -#endif +struct AVRMaskState { + /* */ + SysBusDevice parent_obj; + + /* */ + MemoryRegion iomem; + + uint8_t val; + qemu_irq irq[8]; +}; + +#endif /* HW_MISC_AVR_POWER_H */ diff --git a/include/hw/misc/bcm2835_cprman.h b/include/hw/misc/bcm2835_cprman.h new file mode 100644 index 0000000000000000000000000000000000000000..3df4ceedd2eb500abb0f560a4ee568a19741c4f9 --- /dev/null +++ b/include/hw/misc/bcm2835_cprman.h @@ -0,0 +1,210 @@ +/* + * BCM2835 CPRMAN clock manager + * + * Copyright (c) 2020 Luc Michel + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_MISC_CPRMAN_H +#define HW_MISC_CPRMAN_H + +#include "hw/sysbus.h" +#include "hw/qdev-clock.h" + +#define TYPE_BCM2835_CPRMAN "bcm2835-cprman" + +typedef struct BCM2835CprmanState BCM2835CprmanState; + +DECLARE_INSTANCE_CHECKER(BCM2835CprmanState, CPRMAN, + TYPE_BCM2835_CPRMAN) + +#define CPRMAN_NUM_REGS (0x2000 / sizeof(uint32_t)) + +typedef enum CprmanPll { + CPRMAN_PLLA = 0, + CPRMAN_PLLC, + CPRMAN_PLLD, + CPRMAN_PLLH, + CPRMAN_PLLB, + + CPRMAN_NUM_PLL +} CprmanPll; + +typedef enum CprmanPllChannel { + CPRMAN_PLLA_CHANNEL_DSI0 = 0, + CPRMAN_PLLA_CHANNEL_CORE, + CPRMAN_PLLA_CHANNEL_PER, + CPRMAN_PLLA_CHANNEL_CCP2, + + CPRMAN_PLLC_CHANNEL_CORE2, + CPRMAN_PLLC_CHANNEL_CORE1, + CPRMAN_PLLC_CHANNEL_PER, + CPRMAN_PLLC_CHANNEL_CORE0, + + CPRMAN_PLLD_CHANNEL_DSI0, + CPRMAN_PLLD_CHANNEL_CORE, + CPRMAN_PLLD_CHANNEL_PER, + CPRMAN_PLLD_CHANNEL_DSI1, + + CPRMAN_PLLH_CHANNEL_AUX, + CPRMAN_PLLH_CHANNEL_RCAL, + CPRMAN_PLLH_CHANNEL_PIX, + + CPRMAN_PLLB_CHANNEL_ARM, + + CPRMAN_NUM_PLL_CHANNEL, + + /* Special values used when connecting clock sources to clocks */ + CPRMAN_CLOCK_SRC_NORMAL = -1, + CPRMAN_CLOCK_SRC_FORCE_GROUND = -2, + CPRMAN_CLOCK_SRC_DSI0HSCK = -3, +} CprmanPllChannel; + +typedef enum CprmanClockMux { + CPRMAN_CLOCK_GNRIC, + CPRMAN_CLOCK_VPU, + CPRMAN_CLOCK_SYS, + CPRMAN_CLOCK_PERIA, + CPRMAN_CLOCK_PERII, + CPRMAN_CLOCK_H264, + CPRMAN_CLOCK_ISP, + CPRMAN_CLOCK_V3D, + CPRMAN_CLOCK_CAM0, + CPRMAN_CLOCK_CAM1, + CPRMAN_CLOCK_CCP2, + CPRMAN_CLOCK_DSI0E, + CPRMAN_CLOCK_DSI0P, + CPRMAN_CLOCK_DPI, + CPRMAN_CLOCK_GP0, + CPRMAN_CLOCK_GP1, + CPRMAN_CLOCK_GP2, + CPRMAN_CLOCK_HSM, + CPRMAN_CLOCK_OTP, + CPRMAN_CLOCK_PCM, + CPRMAN_CLOCK_PWM, + CPRMAN_CLOCK_SLIM, + CPRMAN_CLOCK_SMI, + CPRMAN_CLOCK_TEC, + CPRMAN_CLOCK_TD0, + CPRMAN_CLOCK_TD1, + CPRMAN_CLOCK_TSENS, + CPRMAN_CLOCK_TIMER, + CPRMAN_CLOCK_UART, + CPRMAN_CLOCK_VEC, + CPRMAN_CLOCK_PULSE, + CPRMAN_CLOCK_SDC, + CPRMAN_CLOCK_ARM, + CPRMAN_CLOCK_AVEO, + CPRMAN_CLOCK_EMMC, + CPRMAN_CLOCK_EMMC2, + + CPRMAN_NUM_CLOCK_MUX +} CprmanClockMux; + +typedef enum CprmanClockMuxSource { + CPRMAN_CLOCK_SRC_GND = 0, + CPRMAN_CLOCK_SRC_XOSC, + CPRMAN_CLOCK_SRC_TD0, + CPRMAN_CLOCK_SRC_TD1, + CPRMAN_CLOCK_SRC_PLLA, + CPRMAN_CLOCK_SRC_PLLC, + CPRMAN_CLOCK_SRC_PLLD, + CPRMAN_CLOCK_SRC_PLLH, + CPRMAN_CLOCK_SRC_PLLC_CORE1, + CPRMAN_CLOCK_SRC_PLLC_CORE2, + + CPRMAN_NUM_CLOCK_MUX_SRC +} CprmanClockMuxSource; + +typedef struct CprmanPllState { + /*< private >*/ + DeviceState parent_obj; + + /*< public >*/ + CprmanPll id; + + uint32_t *reg_cm; + uint32_t *reg_a2w_ctrl; + uint32_t *reg_a2w_ana; /* ANA[0] .. ANA[3] */ + uint32_t prediv_mask; /* prediv bit in ana[1] */ + uint32_t *reg_a2w_frac; + + Clock *xosc_in; + Clock *out; +} CprmanPllState; + +typedef struct CprmanPllChannelState { + /*< private >*/ + DeviceState parent_obj; + + /*< public >*/ + CprmanPllChannel id; + CprmanPll parent; + + uint32_t *reg_cm; + uint32_t hold_mask; + uint32_t load_mask; + uint32_t *reg_a2w_ctrl; + int fixed_divider; + + Clock *pll_in; + Clock *out; +} CprmanPllChannelState; + +typedef struct CprmanClockMuxState { + /*< private >*/ + DeviceState parent_obj; + + /*< public >*/ + CprmanClockMux id; + + uint32_t *reg_ctl; + uint32_t *reg_div; + int int_bits; + int frac_bits; + + Clock *srcs[CPRMAN_NUM_CLOCK_MUX_SRC]; + Clock *out; + + /* + * Used by clock srcs update callback to retrieve both the clock and the + * source number. + */ + struct CprmanClockMuxState *backref[CPRMAN_NUM_CLOCK_MUX_SRC]; +} CprmanClockMuxState; + +typedef struct CprmanDsi0HsckMuxState { + /*< private >*/ + DeviceState parent_obj; + + /*< public >*/ + CprmanClockMux id; + + uint32_t *reg_cm; + + Clock *plla_in; + Clock *plld_in; + Clock *out; +} CprmanDsi0HsckMuxState; + +struct BCM2835CprmanState { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion iomem; + + CprmanPllState plls[CPRMAN_NUM_PLL]; + CprmanPllChannelState channels[CPRMAN_NUM_PLL_CHANNEL]; + CprmanClockMuxState clock_muxes[CPRMAN_NUM_CLOCK_MUX]; + CprmanDsi0HsckMuxState dsi0hsck_mux; + + uint32_t regs[CPRMAN_NUM_REGS]; + uint32_t xosc_freq; + + Clock *xosc; + Clock *gnd; +}; + +#endif diff --git a/include/hw/misc/bcm2835_cprman_internals.h b/include/hw/misc/bcm2835_cprman_internals.h new file mode 100644 index 0000000000000000000000000000000000000000..339759b3071d58891de81771711fcfe9a3824978 --- /dev/null +++ b/include/hw/misc/bcm2835_cprman_internals.h @@ -0,0 +1,1019 @@ +/* + * BCM2835 CPRMAN clock manager + * + * Copyright (c) 2020 Luc Michel + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_MISC_CPRMAN_INTERNALS_H +#define HW_MISC_CPRMAN_INTERNALS_H + +#include "hw/registerfields.h" +#include "hw/misc/bcm2835_cprman.h" + +#define TYPE_CPRMAN_PLL "bcm2835-cprman-pll" +#define TYPE_CPRMAN_PLL_CHANNEL "bcm2835-cprman-pll-channel" +#define TYPE_CPRMAN_CLOCK_MUX "bcm2835-cprman-clock-mux" +#define TYPE_CPRMAN_DSI0HSCK_MUX "bcm2835-cprman-dsi0hsck-mux" + +DECLARE_INSTANCE_CHECKER(CprmanPllState, CPRMAN_PLL, + TYPE_CPRMAN_PLL) +DECLARE_INSTANCE_CHECKER(CprmanPllChannelState, CPRMAN_PLL_CHANNEL, + TYPE_CPRMAN_PLL_CHANNEL) +DECLARE_INSTANCE_CHECKER(CprmanClockMuxState, CPRMAN_CLOCK_MUX, + TYPE_CPRMAN_CLOCK_MUX) +DECLARE_INSTANCE_CHECKER(CprmanDsi0HsckMuxState, CPRMAN_DSI0HSCK_MUX, + TYPE_CPRMAN_DSI0HSCK_MUX) + +/* Register map */ + +/* PLLs */ +REG32(CM_PLLA, 0x104) + FIELD(CM_PLLA, LOADDSI0, 0, 1) + FIELD(CM_PLLA, HOLDDSI0, 1, 1) + FIELD(CM_PLLA, LOADCCP2, 2, 1) + FIELD(CM_PLLA, HOLDCCP2, 3, 1) + FIELD(CM_PLLA, LOADCORE, 4, 1) + FIELD(CM_PLLA, HOLDCORE, 5, 1) + FIELD(CM_PLLA, LOADPER, 6, 1) + FIELD(CM_PLLA, HOLDPER, 7, 1) + FIELD(CM_PLLx, ANARST, 8, 1) +REG32(CM_PLLC, 0x108) + FIELD(CM_PLLC, LOADCORE0, 0, 1) + FIELD(CM_PLLC, HOLDCORE0, 1, 1) + FIELD(CM_PLLC, LOADCORE1, 2, 1) + FIELD(CM_PLLC, HOLDCORE1, 3, 1) + FIELD(CM_PLLC, LOADCORE2, 4, 1) + FIELD(CM_PLLC, HOLDCORE2, 5, 1) + FIELD(CM_PLLC, LOADPER, 6, 1) + FIELD(CM_PLLC, HOLDPER, 7, 1) +REG32(CM_PLLD, 0x10c) + FIELD(CM_PLLD, LOADDSI0, 0, 1) + FIELD(CM_PLLD, HOLDDSI0, 1, 1) + FIELD(CM_PLLD, LOADDSI1, 2, 1) + FIELD(CM_PLLD, HOLDDSI1, 3, 1) + FIELD(CM_PLLD, LOADCORE, 4, 1) + FIELD(CM_PLLD, HOLDCORE, 5, 1) + FIELD(CM_PLLD, LOADPER, 6, 1) + FIELD(CM_PLLD, HOLDPER, 7, 1) +REG32(CM_PLLH, 0x110) + FIELD(CM_PLLH, LOADPIX, 0, 1) + FIELD(CM_PLLH, LOADAUX, 1, 1) + FIELD(CM_PLLH, LOADRCAL, 2, 1) +REG32(CM_PLLB, 0x170) + FIELD(CM_PLLB, LOADARM, 0, 1) + FIELD(CM_PLLB, HOLDARM, 1, 1) + +REG32(A2W_PLLA_CTRL, 0x1100) + FIELD(A2W_PLLx_CTRL, NDIV, 0, 10) + FIELD(A2W_PLLx_CTRL, PDIV, 12, 3) + FIELD(A2W_PLLx_CTRL, PWRDN, 16, 1) + FIELD(A2W_PLLx_CTRL, PRST_DISABLE, 17, 1) +REG32(A2W_PLLC_CTRL, 0x1120) +REG32(A2W_PLLD_CTRL, 0x1140) +REG32(A2W_PLLH_CTRL, 0x1160) +REG32(A2W_PLLB_CTRL, 0x11e0) + +REG32(A2W_PLLA_ANA0, 0x1010) +REG32(A2W_PLLA_ANA1, 0x1014) + FIELD(A2W_PLLx_ANA1, FB_PREDIV, 14, 1) +REG32(A2W_PLLA_ANA2, 0x1018) +REG32(A2W_PLLA_ANA3, 0x101c) + +REG32(A2W_PLLC_ANA0, 0x1030) +REG32(A2W_PLLC_ANA1, 0x1034) +REG32(A2W_PLLC_ANA2, 0x1038) +REG32(A2W_PLLC_ANA3, 0x103c) + +REG32(A2W_PLLD_ANA0, 0x1050) +REG32(A2W_PLLD_ANA1, 0x1054) +REG32(A2W_PLLD_ANA2, 0x1058) +REG32(A2W_PLLD_ANA3, 0x105c) + +REG32(A2W_PLLH_ANA0, 0x1070) +REG32(A2W_PLLH_ANA1, 0x1074) + FIELD(A2W_PLLH_ANA1, FB_PREDIV, 11, 1) +REG32(A2W_PLLH_ANA2, 0x1078) +REG32(A2W_PLLH_ANA3, 0x107c) + +REG32(A2W_PLLB_ANA0, 0x10f0) +REG32(A2W_PLLB_ANA1, 0x10f4) +REG32(A2W_PLLB_ANA2, 0x10f8) +REG32(A2W_PLLB_ANA3, 0x10fc) + +REG32(A2W_PLLA_FRAC, 0x1200) + FIELD(A2W_PLLx_FRAC, FRAC, 0, 20) +REG32(A2W_PLLC_FRAC, 0x1220) +REG32(A2W_PLLD_FRAC, 0x1240) +REG32(A2W_PLLH_FRAC, 0x1260) +REG32(A2W_PLLB_FRAC, 0x12e0) + +/* PLL channels */ +REG32(A2W_PLLA_DSI0, 0x1300) + FIELD(A2W_PLLx_CHANNELy, DIV, 0, 8) + FIELD(A2W_PLLx_CHANNELy, DISABLE, 8, 1) +REG32(A2W_PLLA_CORE, 0x1400) +REG32(A2W_PLLA_PER, 0x1500) +REG32(A2W_PLLA_CCP2, 0x1600) + +REG32(A2W_PLLC_CORE2, 0x1320) +REG32(A2W_PLLC_CORE1, 0x1420) +REG32(A2W_PLLC_PER, 0x1520) +REG32(A2W_PLLC_CORE0, 0x1620) + +REG32(A2W_PLLD_DSI0, 0x1340) +REG32(A2W_PLLD_CORE, 0x1440) +REG32(A2W_PLLD_PER, 0x1540) +REG32(A2W_PLLD_DSI1, 0x1640) + +REG32(A2W_PLLH_AUX, 0x1360) +REG32(A2W_PLLH_RCAL, 0x1460) +REG32(A2W_PLLH_PIX, 0x1560) +REG32(A2W_PLLH_STS, 0x1660) + +REG32(A2W_PLLB_ARM, 0x13e0) + +/* Clock muxes */ +REG32(CM_GNRICCTL, 0x000) + FIELD(CM_CLOCKx_CTL, SRC, 0, 4) + FIELD(CM_CLOCKx_CTL, ENABLE, 4, 1) + FIELD(CM_CLOCKx_CTL, KILL, 5, 1) + FIELD(CM_CLOCKx_CTL, GATE, 6, 1) + FIELD(CM_CLOCKx_CTL, BUSY, 7, 1) + FIELD(CM_CLOCKx_CTL, BUSYD, 8, 1) + FIELD(CM_CLOCKx_CTL, MASH, 9, 2) + FIELD(CM_CLOCKx_CTL, FLIP, 11, 1) +REG32(CM_GNRICDIV, 0x004) + FIELD(CM_CLOCKx_DIV, FRAC, 0, 12) +REG32(CM_VPUCTL, 0x008) +REG32(CM_VPUDIV, 0x00c) +REG32(CM_SYSCTL, 0x010) +REG32(CM_SYSDIV, 0x014) +REG32(CM_PERIACTL, 0x018) +REG32(CM_PERIADIV, 0x01c) +REG32(CM_PERIICTL, 0x020) +REG32(CM_PERIIDIV, 0x024) +REG32(CM_H264CTL, 0x028) +REG32(CM_H264DIV, 0x02c) +REG32(CM_ISPCTL, 0x030) +REG32(CM_ISPDIV, 0x034) +REG32(CM_V3DCTL, 0x038) +REG32(CM_V3DDIV, 0x03c) +REG32(CM_CAM0CTL, 0x040) +REG32(CM_CAM0DIV, 0x044) +REG32(CM_CAM1CTL, 0x048) +REG32(CM_CAM1DIV, 0x04c) +REG32(CM_CCP2CTL, 0x050) +REG32(CM_CCP2DIV, 0x054) +REG32(CM_DSI0ECTL, 0x058) +REG32(CM_DSI0EDIV, 0x05c) +REG32(CM_DSI0PCTL, 0x060) +REG32(CM_DSI0PDIV, 0x064) +REG32(CM_DPICTL, 0x068) +REG32(CM_DPIDIV, 0x06c) +REG32(CM_GP0CTL, 0x070) +REG32(CM_GP0DIV, 0x074) +REG32(CM_GP1CTL, 0x078) +REG32(CM_GP1DIV, 0x07c) +REG32(CM_GP2CTL, 0x080) +REG32(CM_GP2DIV, 0x084) +REG32(CM_HSMCTL, 0x088) +REG32(CM_HSMDIV, 0x08c) +REG32(CM_OTPCTL, 0x090) +REG32(CM_OTPDIV, 0x094) +REG32(CM_PCMCTL, 0x098) +REG32(CM_PCMDIV, 0x09c) +REG32(CM_PWMCTL, 0x0a0) +REG32(CM_PWMDIV, 0x0a4) +REG32(CM_SLIMCTL, 0x0a8) +REG32(CM_SLIMDIV, 0x0ac) +REG32(CM_SMICTL, 0x0b0) +REG32(CM_SMIDIV, 0x0b4) +REG32(CM_TCNTCTL, 0x0c0) +REG32(CM_TCNTCNT, 0x0c4) +REG32(CM_TECCTL, 0x0c8) +REG32(CM_TECDIV, 0x0cc) +REG32(CM_TD0CTL, 0x0d0) +REG32(CM_TD0DIV, 0x0d4) +REG32(CM_TD1CTL, 0x0d8) +REG32(CM_TD1DIV, 0x0dc) +REG32(CM_TSENSCTL, 0x0e0) +REG32(CM_TSENSDIV, 0x0e4) +REG32(CM_TIMERCTL, 0x0e8) +REG32(CM_TIMERDIV, 0x0ec) +REG32(CM_UARTCTL, 0x0f0) +REG32(CM_UARTDIV, 0x0f4) +REG32(CM_VECCTL, 0x0f8) +REG32(CM_VECDIV, 0x0fc) +REG32(CM_PULSECTL, 0x190) +REG32(CM_PULSEDIV, 0x194) +REG32(CM_SDCCTL, 0x1a8) +REG32(CM_SDCDIV, 0x1ac) +REG32(CM_ARMCTL, 0x1b0) +REG32(CM_AVEOCTL, 0x1b8) +REG32(CM_AVEODIV, 0x1bc) +REG32(CM_EMMCCTL, 0x1c0) +REG32(CM_EMMCDIV, 0x1c4) +REG32(CM_EMMC2CTL, 0x1d0) +REG32(CM_EMMC2DIV, 0x1d4) + +/* misc registers */ +REG32(CM_LOCK, 0x114) + FIELD(CM_LOCK, FLOCKH, 12, 1) + FIELD(CM_LOCK, FLOCKD, 11, 1) + FIELD(CM_LOCK, FLOCKC, 10, 1) + FIELD(CM_LOCK, FLOCKB, 9, 1) + FIELD(CM_LOCK, FLOCKA, 8, 1) + +REG32(CM_DSI0HSCK, 0x120) + FIELD(CM_DSI0HSCK, SELPLLD, 0, 1) + +/* + * This field is common to all registers. Each register write value must match + * the CPRMAN_PASSWORD magic value in its 8 MSB. + */ +FIELD(CPRMAN, PASSWORD, 24, 8) +#define CPRMAN_PASSWORD 0x5a + +/* PLL init info */ +typedef struct PLLInitInfo { + const char *name; + size_t cm_offset; + size_t a2w_ctrl_offset; + size_t a2w_ana_offset; + uint32_t prediv_mask; /* Prediv bit in ana[1] */ + size_t a2w_frac_offset; +} PLLInitInfo; + +#define FILL_PLL_INIT_INFO(pll_) \ + .cm_offset = R_CM_ ## pll_, \ + .a2w_ctrl_offset = R_A2W_ ## pll_ ## _CTRL, \ + .a2w_ana_offset = R_A2W_ ## pll_ ## _ANA0, \ + .a2w_frac_offset = R_A2W_ ## pll_ ## _FRAC + +static const PLLInitInfo PLL_INIT_INFO[] = { + [CPRMAN_PLLA] = { + .name = "plla", + .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK, + FILL_PLL_INIT_INFO(PLLA), + }, + [CPRMAN_PLLC] = { + .name = "pllc", + .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK, + FILL_PLL_INIT_INFO(PLLC), + }, + [CPRMAN_PLLD] = { + .name = "plld", + .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK, + FILL_PLL_INIT_INFO(PLLD), + }, + [CPRMAN_PLLH] = { + .name = "pllh", + .prediv_mask = R_A2W_PLLH_ANA1_FB_PREDIV_MASK, + FILL_PLL_INIT_INFO(PLLH), + }, + [CPRMAN_PLLB] = { + .name = "pllb", + .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK, + FILL_PLL_INIT_INFO(PLLB), + }, +}; + +#undef FILL_PLL_CHANNEL_INIT_INFO + +static inline void set_pll_init_info(BCM2835CprmanState *s, + CprmanPllState *pll, + CprmanPll id) +{ + pll->id = id; + pll->reg_cm = &s->regs[PLL_INIT_INFO[id].cm_offset]; + pll->reg_a2w_ctrl = &s->regs[PLL_INIT_INFO[id].a2w_ctrl_offset]; + pll->reg_a2w_ana = &s->regs[PLL_INIT_INFO[id].a2w_ana_offset]; + pll->prediv_mask = PLL_INIT_INFO[id].prediv_mask; + pll->reg_a2w_frac = &s->regs[PLL_INIT_INFO[id].a2w_frac_offset]; +} + + +/* PLL channel init info */ +typedef struct PLLChannelInitInfo { + const char *name; + CprmanPll parent; + size_t cm_offset; + uint32_t cm_hold_mask; + uint32_t cm_load_mask; + size_t a2w_ctrl_offset; + unsigned int fixed_divider; +} PLLChannelInitInfo; + +#define FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_) \ + .parent = CPRMAN_ ## pll_, \ + .cm_offset = R_CM_ ## pll_, \ + .cm_load_mask = R_CM_ ## pll_ ## _ ## LOAD ## channel_ ## _MASK, \ + .a2w_ctrl_offset = R_A2W_ ## pll_ ## _ ## channel_ + +#define FILL_PLL_CHANNEL_INIT_INFO(pll_, channel_) \ + FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_), \ + .cm_hold_mask = R_CM_ ## pll_ ## _ ## HOLD ## channel_ ## _MASK, \ + .fixed_divider = 1 + +#define FILL_PLL_CHANNEL_INIT_INFO_nohold(pll_, channel_) \ + FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_), \ + .cm_hold_mask = 0 + +static PLLChannelInitInfo PLL_CHANNEL_INIT_INFO[] = { + [CPRMAN_PLLA_CHANNEL_DSI0] = { + .name = "plla-dsi0", + FILL_PLL_CHANNEL_INIT_INFO(PLLA, DSI0), + }, + [CPRMAN_PLLA_CHANNEL_CORE] = { + .name = "plla-core", + FILL_PLL_CHANNEL_INIT_INFO(PLLA, CORE), + }, + [CPRMAN_PLLA_CHANNEL_PER] = { + .name = "plla-per", + FILL_PLL_CHANNEL_INIT_INFO(PLLA, PER), + }, + [CPRMAN_PLLA_CHANNEL_CCP2] = { + .name = "plla-ccp2", + FILL_PLL_CHANNEL_INIT_INFO(PLLA, CCP2), + }, + + [CPRMAN_PLLC_CHANNEL_CORE2] = { + .name = "pllc-core2", + FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE2), + }, + [CPRMAN_PLLC_CHANNEL_CORE1] = { + .name = "pllc-core1", + FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE1), + }, + [CPRMAN_PLLC_CHANNEL_PER] = { + .name = "pllc-per", + FILL_PLL_CHANNEL_INIT_INFO(PLLC, PER), + }, + [CPRMAN_PLLC_CHANNEL_CORE0] = { + .name = "pllc-core0", + FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE0), + }, + + [CPRMAN_PLLD_CHANNEL_DSI0] = { + .name = "plld-dsi0", + FILL_PLL_CHANNEL_INIT_INFO(PLLD, DSI0), + }, + [CPRMAN_PLLD_CHANNEL_CORE] = { + .name = "plld-core", + FILL_PLL_CHANNEL_INIT_INFO(PLLD, CORE), + }, + [CPRMAN_PLLD_CHANNEL_PER] = { + .name = "plld-per", + FILL_PLL_CHANNEL_INIT_INFO(PLLD, PER), + }, + [CPRMAN_PLLD_CHANNEL_DSI1] = { + .name = "plld-dsi1", + FILL_PLL_CHANNEL_INIT_INFO(PLLD, DSI1), + }, + + [CPRMAN_PLLH_CHANNEL_AUX] = { + .name = "pllh-aux", + .fixed_divider = 1, + FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, AUX), + }, + [CPRMAN_PLLH_CHANNEL_RCAL] = { + .name = "pllh-rcal", + .fixed_divider = 10, + FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, RCAL), + }, + [CPRMAN_PLLH_CHANNEL_PIX] = { + .name = "pllh-pix", + .fixed_divider = 10, + FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, PIX), + }, + + [CPRMAN_PLLB_CHANNEL_ARM] = { + .name = "pllb-arm", + FILL_PLL_CHANNEL_INIT_INFO(PLLB, ARM), + }, +}; + +#undef FILL_PLL_CHANNEL_INIT_INFO_nohold +#undef FILL_PLL_CHANNEL_INIT_INFO +#undef FILL_PLL_CHANNEL_INIT_INFO_common + +static inline void set_pll_channel_init_info(BCM2835CprmanState *s, + CprmanPllChannelState *channel, + CprmanPllChannel id) +{ + channel->id = id; + channel->parent = PLL_CHANNEL_INIT_INFO[id].parent; + channel->reg_cm = &s->regs[PLL_CHANNEL_INIT_INFO[id].cm_offset]; + channel->hold_mask = PLL_CHANNEL_INIT_INFO[id].cm_hold_mask; + channel->load_mask = PLL_CHANNEL_INIT_INFO[id].cm_load_mask; + channel->reg_a2w_ctrl = &s->regs[PLL_CHANNEL_INIT_INFO[id].a2w_ctrl_offset]; + channel->fixed_divider = PLL_CHANNEL_INIT_INFO[id].fixed_divider; +} + +/* Clock mux init info */ +typedef struct ClockMuxInitInfo { + const char *name; + size_t cm_offset; /* cm_offset[0]->CM_CTL, cm_offset[1]->CM_DIV */ + int int_bits; + int frac_bits; + + CprmanPllChannel src_mapping[CPRMAN_NUM_CLOCK_MUX_SRC]; +} ClockMuxInitInfo; + +/* + * Each clock mux can have up to 10 sources. Sources 0 to 3 are always the + * same (ground, xosc, td0, td1). Sources 4 to 9 are mux specific, and are not + * always populated. The following macros catch all those cases. + */ + +/* Unknown mapping. Connect everything to ground */ +#define SRC_MAPPING_INFO_unknown \ + .src_mapping = { \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, /* gnd */ \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, /* xosc */ \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, /* test debug 0 */ \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, /* test debug 1 */ \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll a */ \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c */ \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll d */ \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll h */ \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c, core1 */ \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c, core2 */ \ + } + +/* Only the oscillator and the two test debug clocks */ +#define SRC_MAPPING_INFO_xosc \ + .src_mapping = { \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + } + +/* All the PLL "core" channels */ +#define SRC_MAPPING_INFO_core \ + .src_mapping = { \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_PLLA_CHANNEL_CORE, \ + CPRMAN_PLLC_CHANNEL_CORE0, \ + CPRMAN_PLLD_CHANNEL_CORE, \ + CPRMAN_PLLH_CHANNEL_AUX, \ + CPRMAN_PLLC_CHANNEL_CORE1, \ + CPRMAN_PLLC_CHANNEL_CORE2, \ + } + +/* All the PLL "per" channels */ +#define SRC_MAPPING_INFO_periph \ + .src_mapping = { \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_PLLA_CHANNEL_PER, \ + CPRMAN_PLLC_CHANNEL_PER, \ + CPRMAN_PLLD_CHANNEL_PER, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + } + +/* + * The DSI0 channels. This one got an intermediate mux between the PLL channels + * and the clock input. + */ +#define SRC_MAPPING_INFO_dsi0 \ + .src_mapping = { \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_CLOCK_SRC_DSI0HSCK, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + } + +/* The DSI1 channel */ +#define SRC_MAPPING_INFO_dsi1 \ + .src_mapping = { \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_CLOCK_SRC_NORMAL, \ + CPRMAN_PLLD_CHANNEL_DSI1, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + CPRMAN_CLOCK_SRC_FORCE_GROUND, \ + } + +#define FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO(kind_) \ + SRC_MAPPING_INFO_ ## kind_ + +#define FILL_CLOCK_MUX_INIT_INFO(clock_, kind_) \ + .cm_offset = R_CM_ ## clock_ ## CTL, \ + FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO(kind_) + +static ClockMuxInitInfo CLOCK_MUX_INIT_INFO[] = { + [CPRMAN_CLOCK_GNRIC] = { + .name = "gnric", + FILL_CLOCK_MUX_INIT_INFO(GNRIC, unknown), + }, + [CPRMAN_CLOCK_VPU] = { + .name = "vpu", + .int_bits = 12, + .frac_bits = 8, + FILL_CLOCK_MUX_INIT_INFO(VPU, core), + }, + [CPRMAN_CLOCK_SYS] = { + .name = "sys", + FILL_CLOCK_MUX_INIT_INFO(SYS, unknown), + }, + [CPRMAN_CLOCK_PERIA] = { + .name = "peria", + FILL_CLOCK_MUX_INIT_INFO(PERIA, unknown), + }, + [CPRMAN_CLOCK_PERII] = { + .name = "perii", + FILL_CLOCK_MUX_INIT_INFO(PERII, unknown), + }, + [CPRMAN_CLOCK_H264] = { + .name = "h264", + .int_bits = 4, + .frac_bits = 8, + FILL_CLOCK_MUX_INIT_INFO(H264, core), + }, + [CPRMAN_CLOCK_ISP] = { + .name = "isp", + .int_bits = 4, + .frac_bits = 8, + FILL_CLOCK_MUX_INIT_INFO(ISP, core), + }, + [CPRMAN_CLOCK_V3D] = { + .name = "v3d", + FILL_CLOCK_MUX_INIT_INFO(V3D, core), + }, + [CPRMAN_CLOCK_CAM0] = { + .name = "cam0", + .int_bits = 4, + .frac_bits = 8, + FILL_CLOCK_MUX_INIT_INFO(CAM0, periph), + }, + [CPRMAN_CLOCK_CAM1] = { + .name = "cam1", + .int_bits = 4, + .frac_bits = 8, + FILL_CLOCK_MUX_INIT_INFO(CAM1, periph), + }, + [CPRMAN_CLOCK_CCP2] = { + .name = "ccp2", + FILL_CLOCK_MUX_INIT_INFO(CCP2, unknown), + }, + [CPRMAN_CLOCK_DSI0E] = { + .name = "dsi0e", + .int_bits = 4, + .frac_bits = 8, + FILL_CLOCK_MUX_INIT_INFO(DSI0E, dsi0), + }, + [CPRMAN_CLOCK_DSI0P] = { + .name = "dsi0p", + .int_bits = 0, + .frac_bits = 0, + FILL_CLOCK_MUX_INIT_INFO(DSI0P, dsi0), + }, + [CPRMAN_CLOCK_DPI] = { + .name = "dpi", + .int_bits = 4, + .frac_bits = 8, + FILL_CLOCK_MUX_INIT_INFO(DPI, periph), + }, + [CPRMAN_CLOCK_GP0] = { + .name = "gp0", + .int_bits = 12, + .frac_bits = 12, + FILL_CLOCK_MUX_INIT_INFO(GP0, periph), + }, + [CPRMAN_CLOCK_GP1] = { + .name = "gp1", + .int_bits = 12, + .frac_bits = 12, + FILL_CLOCK_MUX_INIT_INFO(GP1, periph), + }, + [CPRMAN_CLOCK_GP2] = { + .name = "gp2", + .int_bits = 12, + .frac_bits = 12, + FILL_CLOCK_MUX_INIT_INFO(GP2, periph), + }, + [CPRMAN_CLOCK_HSM] = { + .name = "hsm", + .int_bits = 4, + .frac_bits = 8, + FILL_CLOCK_MUX_INIT_INFO(HSM, periph), + }, + [CPRMAN_CLOCK_OTP] = { + .name = "otp", + .int_bits = 4, + .frac_bits = 0, + FILL_CLOCK_MUX_INIT_INFO(OTP, xosc), + }, + [CPRMAN_CLOCK_PCM] = { + .name = "pcm", + .int_bits = 12, + .frac_bits = 12, + FILL_CLOCK_MUX_INIT_INFO(PCM, periph), + }, + [CPRMAN_CLOCK_PWM] = { + .name = "pwm", + .int_bits = 12, + .frac_bits = 12, + FILL_CLOCK_MUX_INIT_INFO(PWM, periph), + }, + [CPRMAN_CLOCK_SLIM] = { + .name = "slim", + .int_bits = 12, + .frac_bits = 12, + FILL_CLOCK_MUX_INIT_INFO(SLIM, periph), + }, + [CPRMAN_CLOCK_SMI] = { + .name = "smi", + .int_bits = 4, + .frac_bits = 8, + FILL_CLOCK_MUX_INIT_INFO(SMI, periph), + }, + [CPRMAN_CLOCK_TEC] = { + .name = "tec", + .int_bits = 6, + .frac_bits = 0, + FILL_CLOCK_MUX_INIT_INFO(TEC, xosc), + }, + [CPRMAN_CLOCK_TD0] = { + .name = "td0", + FILL_CLOCK_MUX_INIT_INFO(TD0, unknown), + }, + [CPRMAN_CLOCK_TD1] = { + .name = "td1", + FILL_CLOCK_MUX_INIT_INFO(TD1, unknown), + }, + [CPRMAN_CLOCK_TSENS] = { + .name = "tsens", + .int_bits = 5, + .frac_bits = 0, + FILL_CLOCK_MUX_INIT_INFO(TSENS, xosc), + }, + [CPRMAN_CLOCK_TIMER] = { + .name = "timer", + .int_bits = 6, + .frac_bits = 12, + FILL_CLOCK_MUX_INIT_INFO(TIMER, xosc), + }, + [CPRMAN_CLOCK_UART] = { + .name = "uart", + .int_bits = 10, + .frac_bits = 12, + FILL_CLOCK_MUX_INIT_INFO(UART, periph), + }, + [CPRMAN_CLOCK_VEC] = { + .name = "vec", + .int_bits = 4, + .frac_bits = 0, + FILL_CLOCK_MUX_INIT_INFO(VEC, periph), + }, + [CPRMAN_CLOCK_PULSE] = { + .name = "pulse", + FILL_CLOCK_MUX_INIT_INFO(PULSE, xosc), + }, + [CPRMAN_CLOCK_SDC] = { + .name = "sdram", + .int_bits = 6, + .frac_bits = 0, + FILL_CLOCK_MUX_INIT_INFO(SDC, core), + }, + [CPRMAN_CLOCK_ARM] = { + .name = "arm", + FILL_CLOCK_MUX_INIT_INFO(ARM, unknown), + }, + [CPRMAN_CLOCK_AVEO] = { + .name = "aveo", + .int_bits = 4, + .frac_bits = 0, + FILL_CLOCK_MUX_INIT_INFO(AVEO, periph), + }, + [CPRMAN_CLOCK_EMMC] = { + .name = "emmc", + .int_bits = 4, + .frac_bits = 8, + FILL_CLOCK_MUX_INIT_INFO(EMMC, periph), + }, + [CPRMAN_CLOCK_EMMC2] = { + .name = "emmc2", + .int_bits = 4, + .frac_bits = 8, + FILL_CLOCK_MUX_INIT_INFO(EMMC2, unknown), + }, +}; + +#undef FILL_CLOCK_MUX_INIT_INFO +#undef FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO +#undef SRC_MAPPING_INFO_dsi1 +#undef SRC_MAPPING_INFO_dsi0 +#undef SRC_MAPPING_INFO_periph +#undef SRC_MAPPING_INFO_core +#undef SRC_MAPPING_INFO_xosc +#undef SRC_MAPPING_INFO_unknown + +static inline void set_clock_mux_init_info(BCM2835CprmanState *s, + CprmanClockMuxState *mux, + CprmanClockMux id) +{ + mux->id = id; + mux->reg_ctl = &s->regs[CLOCK_MUX_INIT_INFO[id].cm_offset]; + mux->reg_div = &s->regs[CLOCK_MUX_INIT_INFO[id].cm_offset + 1]; + mux->int_bits = CLOCK_MUX_INIT_INFO[id].int_bits; + mux->frac_bits = CLOCK_MUX_INIT_INFO[id].frac_bits; +} + + +/* + * Object reset info + * Those values have been dumped from a Raspberry Pi 3 Model B v1.2 using the + * clk debugfs interface in Linux. + */ +typedef struct PLLResetInfo { + uint32_t cm; + uint32_t a2w_ctrl; + uint32_t a2w_ana[4]; + uint32_t a2w_frac; +} PLLResetInfo; + +static const PLLResetInfo PLL_RESET_INFO[] = { + [CPRMAN_PLLA] = { + .cm = 0x0000008a, + .a2w_ctrl = 0x0002103a, + .a2w_frac = 0x00098000, + .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 } + }, + + [CPRMAN_PLLC] = { + .cm = 0x00000228, + .a2w_ctrl = 0x0002103e, + .a2w_frac = 0x00080000, + .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 } + }, + + [CPRMAN_PLLD] = { + .cm = 0x0000020a, + .a2w_ctrl = 0x00021034, + .a2w_frac = 0x00015556, + .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 } + }, + + [CPRMAN_PLLH] = { + .cm = 0x00000000, + .a2w_ctrl = 0x0002102d, + .a2w_frac = 0x00000000, + .a2w_ana = { 0x00900000, 0x0000000c, 0x00000000, 0x00000000 } + }, + + [CPRMAN_PLLB] = { + /* unknown */ + .cm = 0x00000000, + .a2w_ctrl = 0x00000000, + .a2w_frac = 0x00000000, + .a2w_ana = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 } + } +}; + +typedef struct PLLChannelResetInfo { + /* + * Even though a PLL channel has a CM register, it shares it with its + * parent PLL. The parent already takes care of the reset value. + */ + uint32_t a2w_ctrl; +} PLLChannelResetInfo; + +static const PLLChannelResetInfo PLL_CHANNEL_RESET_INFO[] = { + [CPRMAN_PLLA_CHANNEL_DSI0] = { .a2w_ctrl = 0x00000100 }, + [CPRMAN_PLLA_CHANNEL_CORE] = { .a2w_ctrl = 0x00000003 }, + [CPRMAN_PLLA_CHANNEL_PER] = { .a2w_ctrl = 0x00000000 }, /* unknown */ + [CPRMAN_PLLA_CHANNEL_CCP2] = { .a2w_ctrl = 0x00000100 }, + + [CPRMAN_PLLC_CHANNEL_CORE2] = { .a2w_ctrl = 0x00000100 }, + [CPRMAN_PLLC_CHANNEL_CORE1] = { .a2w_ctrl = 0x00000100 }, + [CPRMAN_PLLC_CHANNEL_PER] = { .a2w_ctrl = 0x00000002 }, + [CPRMAN_PLLC_CHANNEL_CORE0] = { .a2w_ctrl = 0x00000002 }, + + [CPRMAN_PLLD_CHANNEL_DSI0] = { .a2w_ctrl = 0x00000100 }, + [CPRMAN_PLLD_CHANNEL_CORE] = { .a2w_ctrl = 0x00000004 }, + [CPRMAN_PLLD_CHANNEL_PER] = { .a2w_ctrl = 0x00000004 }, + [CPRMAN_PLLD_CHANNEL_DSI1] = { .a2w_ctrl = 0x00000100 }, + + [CPRMAN_PLLH_CHANNEL_AUX] = { .a2w_ctrl = 0x00000004 }, + [CPRMAN_PLLH_CHANNEL_RCAL] = { .a2w_ctrl = 0x00000000 }, + [CPRMAN_PLLH_CHANNEL_PIX] = { .a2w_ctrl = 0x00000000 }, + + [CPRMAN_PLLB_CHANNEL_ARM] = { .a2w_ctrl = 0x00000000 }, /* unknown */ +}; + +typedef struct ClockMuxResetInfo { + uint32_t cm_ctl; + uint32_t cm_div; +} ClockMuxResetInfo; + +static const ClockMuxResetInfo CLOCK_MUX_RESET_INFO[] = { + [CPRMAN_CLOCK_GNRIC] = { + .cm_ctl = 0, /* unknown */ + .cm_div = 0 + }, + + [CPRMAN_CLOCK_VPU] = { + .cm_ctl = 0x00000245, + .cm_div = 0x00003000, + }, + + [CPRMAN_CLOCK_SYS] = { + .cm_ctl = 0, /* unknown */ + .cm_div = 0 + }, + + [CPRMAN_CLOCK_PERIA] = { + .cm_ctl = 0, /* unknown */ + .cm_div = 0 + }, + + [CPRMAN_CLOCK_PERII] = { + .cm_ctl = 0, /* unknown */ + .cm_div = 0 + }, + + [CPRMAN_CLOCK_H264] = { + .cm_ctl = 0x00000244, + .cm_div = 0x00003000, + }, + + [CPRMAN_CLOCK_ISP] = { + .cm_ctl = 0x00000244, + .cm_div = 0x00003000, + }, + + [CPRMAN_CLOCK_V3D] = { + .cm_ctl = 0, /* unknown */ + .cm_div = 0 + }, + + [CPRMAN_CLOCK_CAM0] = { + .cm_ctl = 0x00000000, + .cm_div = 0x00000000, + }, + + [CPRMAN_CLOCK_CAM1] = { + .cm_ctl = 0x00000000, + .cm_div = 0x00000000, + }, + + [CPRMAN_CLOCK_CCP2] = { + .cm_ctl = 0, /* unknown */ + .cm_div = 0 + }, + + [CPRMAN_CLOCK_DSI0E] = { + .cm_ctl = 0x00000000, + .cm_div = 0x00000000, + }, + + [CPRMAN_CLOCK_DSI0P] = { + .cm_ctl = 0x00000000, + .cm_div = 0x00000000, + }, + + [CPRMAN_CLOCK_DPI] = { + .cm_ctl = 0x00000000, + .cm_div = 0x00000000, + }, + + [CPRMAN_CLOCK_GP0] = { + .cm_ctl = 0x00000200, + .cm_div = 0x00000000, + }, + + [CPRMAN_CLOCK_GP1] = { + .cm_ctl = 0x00000096, + .cm_div = 0x00014000, + }, + + [CPRMAN_CLOCK_GP2] = { + .cm_ctl = 0x00000291, + .cm_div = 0x00249f00, + }, + + [CPRMAN_CLOCK_HSM] = { + .cm_ctl = 0x00000000, + .cm_div = 0x00000000, + }, + + [CPRMAN_CLOCK_OTP] = { + .cm_ctl = 0x00000091, + .cm_div = 0x00004000, + }, + + [CPRMAN_CLOCK_PCM] = { + .cm_ctl = 0x00000200, + .cm_div = 0x00000000, + }, + + [CPRMAN_CLOCK_PWM] = { + .cm_ctl = 0x00000200, + .cm_div = 0x00000000, + }, + + [CPRMAN_CLOCK_SLIM] = { + .cm_ctl = 0x00000200, + .cm_div = 0x00000000, + }, + + [CPRMAN_CLOCK_SMI] = { + .cm_ctl = 0x00000000, + .cm_div = 0x00000000, + }, + + [CPRMAN_CLOCK_TEC] = { + .cm_ctl = 0x00000000, + .cm_div = 0x00000000, + }, + + [CPRMAN_CLOCK_TD0] = { + .cm_ctl = 0, /* unknown */ + .cm_div = 0 + }, + + [CPRMAN_CLOCK_TD1] = { + .cm_ctl = 0, /* unknown */ + .cm_div = 0 + }, + + [CPRMAN_CLOCK_TSENS] = { + .cm_ctl = 0x00000091, + .cm_div = 0x0000a000, + }, + + [CPRMAN_CLOCK_TIMER] = { + .cm_ctl = 0x00000291, + .cm_div = 0x00013333, + }, + + [CPRMAN_CLOCK_UART] = { + .cm_ctl = 0x00000296, + .cm_div = 0x0000a6ab, + }, + + [CPRMAN_CLOCK_VEC] = { + .cm_ctl = 0x00000097, + .cm_div = 0x00002000, + }, + + [CPRMAN_CLOCK_PULSE] = { + .cm_ctl = 0, /* unknown */ + .cm_div = 0 + }, + + [CPRMAN_CLOCK_SDC] = { + .cm_ctl = 0x00004006, + .cm_div = 0x00003000, + }, + + [CPRMAN_CLOCK_ARM] = { + .cm_ctl = 0, /* unknown */ + .cm_div = 0 + }, + + [CPRMAN_CLOCK_AVEO] = { + .cm_ctl = 0x00000000, + .cm_div = 0x00000000, + }, + + [CPRMAN_CLOCK_EMMC] = { + .cm_ctl = 0x00000295, + .cm_div = 0x00006000, + }, + + [CPRMAN_CLOCK_EMMC2] = { + .cm_ctl = 0, /* unknown */ + .cm_div = 0 + }, +}; + +#endif diff --git a/include/hw/misc/bcm2835_mbox.h b/include/hw/misc/bcm2835_mbox.h index 57f95cc35eab150d78be5efb040ae5fc489d70df..ade27af25d02d3c5fe3e914d53771f71f10ee0fb 100644 --- a/include/hw/misc/bcm2835_mbox.h +++ b/include/hw/misc/bcm2835_mbox.h @@ -10,10 +10,10 @@ #include "bcm2835_mbox_defs.h" #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_BCM2835_MBOX "bcm2835-mbox" -#define BCM2835_MBOX(obj) \ - OBJECT_CHECK(BCM2835MboxState, (obj), TYPE_BCM2835_MBOX) +OBJECT_DECLARE_SIMPLE_TYPE(BCM2835MboxState, BCM2835_MBOX) typedef struct { uint32_t reg[MBOX_SIZE]; @@ -22,7 +22,7 @@ typedef struct { uint32_t config; } BCM2835Mbox; -typedef struct { +struct BCM2835MboxState { /*< private >*/ SysBusDevice busdev; /*< public >*/ @@ -34,6 +34,6 @@ typedef struct { bool mbox_irq_disabled; bool available[MBOX_CHAN_COUNT]; BCM2835Mbox mbox[2]; -} BCM2835MboxState; +}; #endif diff --git a/include/hw/misc/bcm2835_mphi.h b/include/hw/misc/bcm2835_mphi.h new file mode 100644 index 0000000000000000000000000000000000000000..751363f496cf19f42638679c102d58f24d97ca3b --- /dev/null +++ b/include/hw/misc/bcm2835_mphi.h @@ -0,0 +1,44 @@ +/* + * BCM2835 SOC MPHI state definitions + * + * Copyright (c) 2020 Paul Zimmerman + * + * 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. + */ + +#ifndef HW_MISC_BCM2835_MPHI_H +#define HW_MISC_BCM2835_MPHI_H + +#include "hw/irq.h" +#include "hw/sysbus.h" +#include "qom/object.h" + +#define MPHI_MMIO_SIZE 0x1000 + +typedef struct BCM2835MphiState BCM2835MphiState; + +struct BCM2835MphiState { + SysBusDevice parent_obj; + qemu_irq irq; + MemoryRegion iomem; + + uint32_t outdda; + uint32_t outddb; + uint32_t ctrl; + uint32_t intstat; + uint32_t swirq; +}; + +#define TYPE_BCM2835_MPHI "bcm2835-mphi" + +OBJECT_DECLARE_SIMPLE_TYPE(BCM2835MphiState, BCM2835_MPHI) + +#endif diff --git a/include/hw/misc/bcm2835_property.h b/include/hw/misc/bcm2835_property.h index b321f22499039a75936b5e29cc283b869300d801..712b76b7a322bf056741233c5bf98cccc5fa0f0a 100644 --- a/include/hw/misc/bcm2835_property.h +++ b/include/hw/misc/bcm2835_property.h @@ -11,12 +11,12 @@ #include "hw/sysbus.h" #include "net/net.h" #include "hw/display/bcm2835_fb.h" +#include "qom/object.h" #define TYPE_BCM2835_PROPERTY "bcm2835-property" -#define BCM2835_PROPERTY(obj) \ - OBJECT_CHECK(BCM2835PropertyState, (obj), TYPE_BCM2835_PROPERTY) +OBJECT_DECLARE_SIMPLE_TYPE(BCM2835PropertyState, BCM2835_PROPERTY) -typedef struct { +struct BCM2835PropertyState { /*< private >*/ SysBusDevice busdev; /*< public >*/ @@ -31,6 +31,6 @@ typedef struct { uint32_t board_rev; uint32_t addr; bool pending; -} BCM2835PropertyState; +}; #endif diff --git a/include/hw/misc/bcm2835_rng.h b/include/hw/misc/bcm2835_rng.h index 41a531bce776cb84d400eda198eae824831bc5fb..7c1fb3ef405df7c830ca2c05191157e69edc4493 100644 --- a/include/hw/misc/bcm2835_rng.h +++ b/include/hw/misc/bcm2835_rng.h @@ -11,17 +11,17 @@ #define BCM2835_RNG_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_BCM2835_RNG "bcm2835-rng" -#define BCM2835_RNG(obj) \ - OBJECT_CHECK(BCM2835RngState, (obj), TYPE_BCM2835_RNG) +OBJECT_DECLARE_SIMPLE_TYPE(BCM2835RngState, BCM2835_RNG) -typedef struct { +struct BCM2835RngState { SysBusDevice busdev; MemoryRegion iomem; uint32_t rng_ctrl; uint32_t rng_status; -} BCM2835RngState; +}; #endif diff --git a/include/hw/misc/bcm2835_thermal.h b/include/hw/misc/bcm2835_thermal.h index c3651b27ec60193a5573e2dbe7c9ce2205778983..f90f9e487cecf56b6abc61cc5f9f914364a1ed95 100644 --- a/include/hw/misc/bcm2835_thermal.h +++ b/include/hw/misc/bcm2835_thermal.h @@ -10,18 +10,18 @@ #define HW_MISC_BCM2835_THERMAL_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_BCM2835_THERMAL "bcm2835-thermal" -#define BCM2835_THERMAL(obj) \ - OBJECT_CHECK(Bcm2835ThermalState, (obj), TYPE_BCM2835_THERMAL) +OBJECT_DECLARE_SIMPLE_TYPE(Bcm2835ThermalState, BCM2835_THERMAL) -typedef struct { +struct Bcm2835ThermalState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ MemoryRegion iomem; uint32_t ctl; -} Bcm2835ThermalState; +}; #endif diff --git a/include/hw/misc/empty_slot.h b/include/hw/misc/empty_slot.h new file mode 100644 index 0000000000000000000000000000000000000000..dec56e56ae434214b7b743474312ab54c056f9ab --- /dev/null +++ b/include/hw/misc/empty_slot.h @@ -0,0 +1,19 @@ +/* + * QEMU Empty Slot + * + * The empty_slot device emulates known to a bus but not connected devices. + * + * Copyright (c) 2010 Artyom Tarasenko + * + * This code is licensed under the GNU GPL v2 or (at your option) any later + * version. + */ + +#ifndef HW_EMPTY_SLOT_H +#define HW_EMPTY_SLOT_H + +#include "exec/hwaddr.h" + +void empty_slot_init(const char *name, hwaddr addr, uint64_t slot_size); + +#endif diff --git a/include/hw/misc/grlib_ahb_apb_pnp.h b/include/hw/misc/grlib_ahb_apb_pnp.h index a0f6dcfda7c039697ecd3be16ee1d2dc9bda360e..341451bff62cf03e78f6669830a0e276c97d5ff9 100644 --- a/include/hw/misc/grlib_ahb_apb_pnp.h +++ b/include/hw/misc/grlib_ahb_apb_pnp.h @@ -23,16 +23,13 @@ #ifndef GRLIB_AHB_APB_PNP_H #define GRLIB_AHB_APB_PNP_H +#include "qom/object.h" #define TYPE_GRLIB_AHB_PNP "grlib,ahbpnp" -#define GRLIB_AHB_PNP(obj) \ - OBJECT_CHECK(AHBPnp, (obj), TYPE_GRLIB_AHB_PNP) -typedef struct AHBPnp AHBPnp; +OBJECT_DECLARE_SIMPLE_TYPE(AHBPnp, GRLIB_AHB_PNP) #define TYPE_GRLIB_APB_PNP "grlib,apbpnp" -#define GRLIB_APB_PNP(obj) \ - OBJECT_CHECK(APBPnp, (obj), TYPE_GRLIB_APB_PNP) -typedef struct APBPnp APBPnp; +OBJECT_DECLARE_SIMPLE_TYPE(APBPnp, GRLIB_APB_PNP) void grlib_ahb_pnp_add_entry(AHBPnp *dev, uint32_t address, uint32_t mask, uint8_t vendor, uint16_t device, int slave, diff --git a/include/hw/misc/imx25_ccm.h b/include/hw/misc/imx25_ccm.h index 296321c61219a14b131c517523f728c31dc04777..c3b89018c651c3740675ae771fba206097c0c184 100644 --- a/include/hw/misc/imx25_ccm.h +++ b/include/hw/misc/imx25_ccm.h @@ -12,6 +12,7 @@ #define IMX25_CCM_H #include "hw/misc/imx_ccm.h" +#include "qom/object.h" #define IMX25_CCM_MPCTL_REG 0 #define IMX25_CCM_UPCTL_REG 1 @@ -63,9 +64,9 @@ CCTL_##name##_SHIFT) #define TYPE_IMX25_CCM "imx25.ccm" -#define IMX25_CCM(obj) OBJECT_CHECK(IMX25CCMState, (obj), TYPE_IMX25_CCM) +OBJECT_DECLARE_SIMPLE_TYPE(IMX25CCMState, IMX25_CCM) -typedef struct IMX25CCMState { +struct IMX25CCMState { /* */ IMXCCMState parent_obj; @@ -74,6 +75,6 @@ typedef struct IMX25CCMState { uint32_t reg[IMX25_CCM_MAX_REG]; -} IMX25CCMState; +}; #endif /* IMX25_CCM_H */ diff --git a/include/hw/misc/imx31_ccm.h b/include/hw/misc/imx31_ccm.h index c376fad14c11fed7480d56729005c8d7c9510012..18e08ee84f998284b8357752e137379418b73f56 100644 --- a/include/hw/misc/imx31_ccm.h +++ b/include/hw/misc/imx31_ccm.h @@ -12,6 +12,7 @@ #define IMX31_CCM_H #include "hw/misc/imx_ccm.h" +#include "qom/object.h" #define IMX31_CCM_CCMR_REG 0 #define IMX31_CCM_PDR0_REG 1 @@ -72,9 +73,9 @@ PDR0_##name##_PODF_SHIFT) #define TYPE_IMX31_CCM "imx31.ccm" -#define IMX31_CCM(obj) OBJECT_CHECK(IMX31CCMState, (obj), TYPE_IMX31_CCM) +OBJECT_DECLARE_SIMPLE_TYPE(IMX31CCMState, IMX31_CCM) -typedef struct IMX31CCMState { +struct IMX31CCMState { /* */ IMXCCMState parent_obj; @@ -83,6 +84,6 @@ typedef struct IMX31CCMState { uint32_t reg[IMX31_CCM_MAX_REG]; -} IMX31CCMState; +}; #endif /* IMX31_CCM_H */ diff --git a/include/hw/misc/imx6_ccm.h b/include/hw/misc/imx6_ccm.h index 80505809b4244c40ff89b3a7186a2c8a3594e254..ccf46d735356a6dd2735b2508c52328dd337d781 100644 --- a/include/hw/misc/imx6_ccm.h +++ b/include/hw/misc/imx6_ccm.h @@ -13,6 +13,7 @@ #include "hw/misc/imx_ccm.h" #include "qemu/bitops.h" +#include "qom/object.h" #define CCM_CCR 0 #define CCM_CCDR 1 @@ -178,9 +179,9 @@ #define EXTRACT(value, name) extract32(value, name##_SHIFT, name##_LENGTH) #define TYPE_IMX6_CCM "imx6.ccm" -#define IMX6_CCM(obj) OBJECT_CHECK(IMX6CCMState, (obj), TYPE_IMX6_CCM) +OBJECT_DECLARE_SIMPLE_TYPE(IMX6CCMState, IMX6_CCM) -typedef struct IMX6CCMState { +struct IMX6CCMState { /* */ IMXCCMState parent_obj; @@ -192,6 +193,6 @@ typedef struct IMX6CCMState { uint32_t ccm[CCM_MAX]; uint32_t analog[CCM_ANALOG_MAX]; -} IMX6CCMState; +}; #endif /* IMX6_CCM_H */ diff --git a/include/hw/misc/imx6_src.h b/include/hw/misc/imx6_src.h index eb3640732e732be951084a9577a2e431710254ff..f380da3810f8097687c5ac5c9e311a9b4a581f42 100644 --- a/include/hw/misc/imx6_src.h +++ b/include/hw/misc/imx6_src.h @@ -13,6 +13,7 @@ #include "hw/sysbus.h" #include "qemu/bitops.h" +#include "qom/object.h" #define SRC_SCR 0 #define SRC_SBMR1 1 @@ -57,9 +58,9 @@ #define EXTRACT(value, name) extract32(value, name##_SHIFT, name##_LENGTH) #define TYPE_IMX6_SRC "imx6.src" -#define IMX6_SRC(obj) OBJECT_CHECK(IMX6SRCState, (obj), TYPE_IMX6_SRC) +OBJECT_DECLARE_SIMPLE_TYPE(IMX6SRCState, IMX6_SRC) -typedef struct IMX6SRCState { +struct IMX6SRCState { /* */ SysBusDevice parent_obj; @@ -68,6 +69,6 @@ typedef struct IMX6SRCState { uint32_t regs[SRC_MAX]; -} IMX6SRCState; +}; #endif /* IMX6_SRC_H */ diff --git a/include/hw/misc/imx6ul_ccm.h b/include/hw/misc/imx6ul_ccm.h index 377ddca2442a724eadcbcaa2d26f3699891ea3e3..edb5f784d5fc51506b6ad9ec79d52d21a4293da3 100644 --- a/include/hw/misc/imx6ul_ccm.h +++ b/include/hw/misc/imx6ul_ccm.h @@ -12,6 +12,7 @@ #include "hw/misc/imx_ccm.h" #include "qemu/bitops.h" +#include "qom/object.h" #define CCM_CCR 0 #define CCM_CCDR 1 @@ -207,9 +208,9 @@ #define CCM_ANALOG_PLL_LOCK (1 << 31); #define TYPE_IMX6UL_CCM "imx6ul.ccm" -#define IMX6UL_CCM(obj) OBJECT_CHECK(IMX6ULCCMState, (obj), TYPE_IMX6UL_CCM) +OBJECT_DECLARE_SIMPLE_TYPE(IMX6ULCCMState, IMX6UL_CCM) -typedef struct IMX6ULCCMState { +struct IMX6ULCCMState { /* */ IMXCCMState parent_obj; @@ -221,6 +222,6 @@ typedef struct IMX6ULCCMState { uint32_t ccm[CCM_MAX]; uint32_t analog[CCM_ANALOG_MAX]; -} IMX6ULCCMState; +}; #endif /* IMX6UL_CCM_H */ diff --git a/include/hw/misc/imx7_ccm.h b/include/hw/misc/imx7_ccm.h index 9538f37d98ef275dcccd7148004da1979c14beb4..dcaebfb4efdd6712c3d5fa9df8936290ef0692cb 100644 --- a/include/hw/misc/imx7_ccm.h +++ b/include/hw/misc/imx7_ccm.h @@ -14,6 +14,7 @@ #include "hw/misc/imx_ccm.h" #include "qemu/bitops.h" +#include "qom/object.h" enum IMX7AnalogRegisters { ANALOG_PLL_ARM, @@ -104,9 +105,9 @@ enum IMX7PMURegisters { }; #define TYPE_IMX7_CCM "imx7.ccm" -#define IMX7_CCM(obj) OBJECT_CHECK(IMX7CCMState, (obj), TYPE_IMX7_CCM) +OBJECT_DECLARE_SIMPLE_TYPE(IMX7CCMState, IMX7_CCM) -typedef struct IMX7CCMState { +struct IMX7CCMState { /* */ IMXCCMState parent_obj; @@ -114,13 +115,13 @@ typedef struct IMX7CCMState { MemoryRegion iomem; uint32_t ccm[CCM_MAX]; -} IMX7CCMState; +}; #define TYPE_IMX7_ANALOG "imx7.analog" -#define IMX7_ANALOG(obj) OBJECT_CHECK(IMX7AnalogState, (obj), TYPE_IMX7_ANALOG) +OBJECT_DECLARE_SIMPLE_TYPE(IMX7AnalogState, IMX7_ANALOG) -typedef struct IMX7AnalogState { +struct IMX7AnalogState { /* */ IMXCCMState parent_obj; @@ -134,6 +135,6 @@ typedef struct IMX7AnalogState { uint32_t analog[ANALOG_MAX]; uint32_t pmu[PMU_MAX]; -} IMX7AnalogState; +}; #endif /* IMX7_CCM_H */ diff --git a/include/hw/misc/imx7_gpr.h b/include/hw/misc/imx7_gpr.h index e19373d2745fc8d68f73b9164d98fa70e90a0b88..df364bd8f09309e6d260447cb07f08d9fca3e5d7 100644 --- a/include/hw/misc/imx7_gpr.h +++ b/include/hw/misc/imx7_gpr.h @@ -14,15 +14,16 @@ #include "qemu/bitops.h" #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_IMX7_GPR "imx7.gpr" -#define IMX7_GPR(obj) OBJECT_CHECK(IMX7GPRState, (obj), TYPE_IMX7_GPR) +OBJECT_DECLARE_SIMPLE_TYPE(IMX7GPRState, IMX7_GPR) -typedef struct IMX7GPRState { +struct IMX7GPRState { /* */ SysBusDevice parent_obj; MemoryRegion mmio; -} IMX7GPRState; +}; #endif /* IMX7_GPR_H */ diff --git a/include/hw/misc/imx7_snvs.h b/include/hw/misc/imx7_snvs.h index 255f8f26f90ff172bc585c66a9118a9c2d1cacd0..14a1d6fe6b03b451c84f3b48c9242c8ae94c1ab6 100644 --- a/include/hw/misc/imx7_snvs.h +++ b/include/hw/misc/imx7_snvs.h @@ -14,6 +14,7 @@ #include "qemu/bitops.h" #include "hw/sysbus.h" +#include "qom/object.h" enum IMX7SNVSRegisters { @@ -23,13 +24,13 @@ enum IMX7SNVSRegisters { }; #define TYPE_IMX7_SNVS "imx7.snvs" -#define IMX7_SNVS(obj) OBJECT_CHECK(IMX7SNVSState, (obj), TYPE_IMX7_SNVS) +OBJECT_DECLARE_SIMPLE_TYPE(IMX7SNVSState, IMX7_SNVS) -typedef struct IMX7SNVSState { +struct IMX7SNVSState { /* */ SysBusDevice parent_obj; MemoryRegion mmio; -} IMX7SNVSState; +}; #endif /* IMX7_SNVS_H */ diff --git a/include/hw/misc/imx_ccm.h b/include/hw/misc/imx_ccm.h index 33cbc099526837d8b5c186593ab710c7ba9138f3..7e5678e9726045e39de5f4b0e35de131f7eeeff6 100644 --- a/include/hw/misc/imx_ccm.h +++ b/include/hw/misc/imx_ccm.h @@ -12,6 +12,7 @@ #define IMX_CCM_H #include "hw/sysbus.h" +#include "qom/object.h" #define CKIL_FREQ 32768 /* nominal 32khz clock */ @@ -27,20 +28,15 @@ #define PLL_MFN(x) (((x) & 0x3ff) << 0) #define TYPE_IMX_CCM "imx.ccm" -#define IMX_CCM(obj) \ - OBJECT_CHECK(IMXCCMState, (obj), TYPE_IMX_CCM) -#define IMX_CCM_CLASS(klass) \ - OBJECT_CLASS_CHECK(IMXCCMClass, (klass), TYPE_IMX_CCM) -#define IMX_GET_CLASS(obj) \ - OBJECT_GET_CLASS(IMXCCMClass, (obj), TYPE_IMX_CCM) +OBJECT_DECLARE_TYPE(IMXCCMState, IMXCCMClass, IMX_CCM) -typedef struct IMXCCMState { +struct IMXCCMState { /* */ SysBusDevice parent_obj; /* */ -} IMXCCMState; +}; typedef enum { CLK_NONE, @@ -52,13 +48,13 @@ typedef enum { CLK_HIGH, } IMXClk; -typedef struct IMXCCMClass { +struct IMXCCMClass { /* */ SysBusDeviceClass parent_class; /* */ uint32_t (*get_clock_frequency)(IMXCCMState *s, IMXClk clk); -} IMXCCMClass; +}; uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq); diff --git a/include/hw/misc/imx_rngc.h b/include/hw/misc/imx_rngc.h index f0d2b44d4f63b438ff522f7c75aef988b0b0e2fa..34ad699225966e31e3d070ad969f55bbedb44263 100644 --- a/include/hw/misc/imx_rngc.h +++ b/include/hw/misc/imx_rngc.h @@ -11,11 +11,12 @@ #define IMX_RNGC_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_IMX_RNGC "imx.rngc" -#define IMX_RNGC(obj) OBJECT_CHECK(IMXRNGCState, (obj), TYPE_IMX_RNGC) +OBJECT_DECLARE_SIMPLE_TYPE(IMXRNGCState, IMX_RNGC) -typedef struct IMXRNGCState { +struct IMXRNGCState { /*< private >*/ SysBusDevice parent_obj; @@ -30,6 +31,6 @@ typedef struct IMXRNGCState { QEMUBH *self_test_bh; QEMUBH *seed_bh; qemu_irq irq; -} IMXRNGCState; +}; #endif /* IMX_RNGC_H */ diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h index bcb0437be5bd47a7007b7dea331a90da62c56942..54c212b515ce8f2d12216dcdaa422a909ace582e 100644 --- a/include/hw/misc/iotkit-secctl.h +++ b/include/hw/misc/iotkit-secctl.h @@ -56,9 +56,10 @@ #define IOTKIT_SECCTL_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_IOTKIT_SECCTL "iotkit-secctl" -#define IOTKIT_SECCTL(obj) OBJECT_CHECK(IoTKitSecCtl, (obj), TYPE_IOTKIT_SECCTL) +OBJECT_DECLARE_SIMPLE_TYPE(IoTKitSecCtl, IOTKIT_SECCTL) #define IOTS_APB_PPC0_NUM_PORTS 3 #define IOTS_APB_PPC1_NUM_PORTS 1 @@ -70,7 +71,6 @@ #define IOTS_NUM_MPC 4 #define IOTS_NUM_EXP_MSC 16 -typedef struct IoTKitSecCtl IoTKitSecCtl; /* State and IRQ lines relating to a PPC. For the * PPCs in the IoTKit not all the IRQ lines are used. diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h index 601c8ecc0d00685a173d2b5c607f57bf49f4cea9..2b5636b218c26e22cadd09e959a1f159649c94d7 100644 --- a/include/hw/misc/iotkit-sysctl.h +++ b/include/hw/misc/iotkit-sysctl.h @@ -28,12 +28,12 @@ #define HW_MISC_IOTKIT_SYSCTL_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_IOTKIT_SYSCTL "iotkit-sysctl" -#define IOTKIT_SYSCTL(obj) OBJECT_CHECK(IoTKitSysCtl, (obj), \ - TYPE_IOTKIT_SYSCTL) +OBJECT_DECLARE_SIMPLE_TYPE(IoTKitSysCtl, IOTKIT_SYSCTL) -typedef struct IoTKitSysCtl { +struct IoTKitSysCtl { /*< private >*/ SysBusDevice parent_obj; @@ -67,6 +67,6 @@ typedef struct IoTKitSysCtl { uint32_t initsvtor1_rst; bool is_sse200; -} IoTKitSysCtl; +}; #endif diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h index d84eb203b90fb6359bd9dadd4d04fa558f350250..7e620e2eafe1692f9e01b6951c79c2ac6c532601 100644 --- a/include/hw/misc/iotkit-sysinfo.h +++ b/include/hw/misc/iotkit-sysinfo.h @@ -23,12 +23,12 @@ #define HW_MISC_IOTKIT_SYSINFO_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_IOTKIT_SYSINFO "iotkit-sysinfo" -#define IOTKIT_SYSINFO(obj) OBJECT_CHECK(IoTKitSysInfo, (obj), \ - TYPE_IOTKIT_SYSINFO) +OBJECT_DECLARE_SIMPLE_TYPE(IoTKitSysInfo, IOTKIT_SYSINFO) -typedef struct IoTKitSysInfo { +struct IoTKitSysInfo { /*< private >*/ SysBusDevice parent_obj; @@ -38,6 +38,6 @@ typedef struct IoTKitSysInfo { /* Properties */ uint32_t sys_version; uint32_t sys_config; -} IoTKitSysInfo; +}; #endif diff --git a/include/hw/misc/led.h b/include/hw/misc/led.h new file mode 100644 index 0000000000000000000000000000000000000000..aa359b87c20e0b6a10d5d905769d69f315d2f866 --- /dev/null +++ b/include/hw/misc/led.h @@ -0,0 +1,97 @@ +/* + * QEMU single LED device + * + * Copyright (C) 2020 Philippe Mathieu-DaudĂ© + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef HW_MISC_LED_H +#define HW_MISC_LED_H + +#include "qom/object.h" +#include "hw/qdev-core.h" + +#define TYPE_LED "led" + +/** + * LEDColor: Color of a LED + * + * This set is restricted to physically available LED colors. + * + * LED colors from 'Table 1. Product performance of LUXEON Rebel Color + * Line' of the 'DS68 LUXEON Rebel Color Line' datasheet available at: + * https://www.lumileds.com/products/color-leds/luxeon-rebel-color/ + */ +typedef enum { /* Coarse wavelength range */ + LED_COLOR_VIOLET, /* 425 nm */ + LED_COLOR_BLUE, /* 475 nm */ + LED_COLOR_CYAN, /* 500 nm */ + LED_COLOR_GREEN, /* 535 nm */ + LED_COLOR_AMBER, /* 590 nm */ + LED_COLOR_ORANGE, /* 615 nm */ + LED_COLOR_RED, /* 630 nm */ +} LEDColor; + +struct LEDState { + /* Private */ + DeviceState parent_obj; + /* Public */ + + uint8_t intensity_percent; + qemu_irq irq; + + /* Properties */ + char *description; + char *color; + /* + * Determines whether a GPIO is using a positive (active-high) + * logic (when used with GPIO, the intensity at reset is related + * to the GPIO polarity). + */ + bool gpio_active_high; +}; +typedef struct LEDState LEDState; +DECLARE_INSTANCE_CHECKER(LEDState, LED, TYPE_LED) + +/** + * led_set_intensity: Set the intensity of a LED device + * @s: the LED object + * @intensity_percent: intensity as percentage in range 0 to 100. + */ +void led_set_intensity(LEDState *s, unsigned intensity_percent); + +/** + * led_get_intensity: + * @s: the LED object + * + * Returns: The LED intensity as percentage in range 0 to 100. + */ +unsigned led_get_intensity(LEDState *s); + +/** + * led_set_state: Set the state of a LED device + * @s: the LED object + * @is_emitting: boolean indicating whether the LED is emitting + * + * This utility is meant for LED connected to GPIO. + */ +void led_set_state(LEDState *s, bool is_emitting); + +/** + * led_create_simple: Create and realize a LED device + * @parentobj: the parent object + * @gpio_polarity: GPIO polarity + * @color: color of the LED + * @description: description of the LED (optional) + * + * Create the device state structure, initialize it, and + * drop the reference to it (the device is realized). + * + * Returns: The newly allocated and instantiated LED object. + */ +LEDState *led_create_simple(Object *parentobj, + GpioPolarity gpio_polarity, + LEDColor color, + const char *description); + +#endif /* HW_MISC_LED_H */ diff --git a/include/hw/misc/mac_via.h b/include/hw/misc/mac_via.h index e74f85be0f12bfea2189be630d04bd7c62583764..a59f0bd422358b71160627eadc020cb0f3b0ceab 100644 --- a/include/hw/misc/mac_via.h +++ b/include/hw/misc/mac_via.h @@ -12,6 +12,7 @@ #include "exec/memory.h" #include "hw/sysbus.h" #include "hw/misc/mos6522.h" +#include "qom/object.h" /* VIA 1 */ @@ -31,10 +32,9 @@ #define TYPE_MOS6522_Q800_VIA1 "mos6522-q800-via1" -#define MOS6522_Q800_VIA1(obj) OBJECT_CHECK(MOS6522Q800VIA1State, (obj), \ - TYPE_MOS6522_Q800_VIA1) +OBJECT_DECLARE_SIMPLE_TYPE(MOS6522Q800VIA1State, MOS6522_Q800_VIA1) -typedef struct MOS6522Q800VIA1State { +struct MOS6522Q800VIA1State { /*< private >*/ MOS6522State parent_obj; @@ -47,7 +47,7 @@ typedef struct MOS6522Q800VIA1State { int64_t next_second; QEMUTimer *VBL_timer; int64_t next_VBL; -} MOS6522Q800VIA1State; +}; /* VIA 2 */ @@ -66,19 +66,18 @@ typedef struct MOS6522Q800VIA1State { #define VIA2_IRQ_ASC (1 << VIA2_IRQ_ASC_BIT) #define TYPE_MOS6522_Q800_VIA2 "mos6522-q800-via2" -#define MOS6522_Q800_VIA2(obj) OBJECT_CHECK(MOS6522Q800VIA2State, (obj), \ - TYPE_MOS6522_Q800_VIA2) +OBJECT_DECLARE_SIMPLE_TYPE(MOS6522Q800VIA2State, MOS6522_Q800_VIA2) -typedef struct MOS6522Q800VIA2State { +struct MOS6522Q800VIA2State { /*< private >*/ MOS6522State parent_obj; -} MOS6522Q800VIA2State; +}; #define TYPE_MAC_VIA "mac_via" -#define MAC_VIA(obj) OBJECT_CHECK(MacVIAState, (obj), TYPE_MAC_VIA) +OBJECT_DECLARE_SIMPLE_TYPE(MacVIAState, MAC_VIA) -typedef struct MacVIAState { +struct MacVIAState { SysBusDevice busdev; VMChangeStateEntry *vmstate; @@ -106,13 +105,13 @@ typedef struct MacVIAState { /* ADB */ ADBBusState adb_bus; - QEMUTimer *adb_poll_timer; qemu_irq adb_data_ready; int adb_data_in_size; int adb_data_in_index; int adb_data_out_index; uint8_t adb_data_in[128]; uint8_t adb_data_out[16]; -} MacVIAState; + uint8_t adb_autopoll_cmd; +}; #endif diff --git a/include/hw/misc/macio/cuda.h b/include/hw/misc/macio/cuda.h index 5768075ac5d3b5ddc81c5fe1e4b35a010984821d..a71deec9680e64d48af901e348e9fe9d1bdd01a7 100644 --- a/include/hw/misc/macio/cuda.h +++ b/include/hw/misc/macio/cuda.h @@ -27,6 +27,7 @@ #define CUDA_H #include "hw/misc/mos6522.h" +#include "qom/object.h" /* CUDA commands (2nd byte) */ #define CUDA_WARM_START 0x0 @@ -58,20 +59,19 @@ /* MOS6522 CUDA */ -typedef struct MOS6522CUDAState { +struct MOS6522CUDAState { /*< private >*/ MOS6522State parent_obj; -} MOS6522CUDAState; +}; #define TYPE_MOS6522_CUDA "mos6522-cuda" -#define MOS6522_CUDA(obj) OBJECT_CHECK(MOS6522CUDAState, (obj), \ - TYPE_MOS6522_CUDA) +OBJECT_DECLARE_SIMPLE_TYPE(MOS6522CUDAState, MOS6522_CUDA) /* Cuda */ #define TYPE_CUDA "cuda" -#define CUDA(obj) OBJECT_CHECK(CUDAState, (obj), TYPE_CUDA) +OBJECT_DECLARE_SIMPLE_TYPE(CUDAState, CUDA) -typedef struct CUDAState { +struct CUDAState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -95,12 +95,8 @@ typedef struct CUDAState { int data_out_index; qemu_irq irq; - uint16_t adb_poll_mask; - uint8_t autopoll_rate_ms; - uint8_t autopoll; uint8_t data_in[128]; uint8_t data_out[16]; - QEMUTimer *adb_poll_timer; -} CUDAState; +}; #endif /* CUDA_H */ diff --git a/include/hw/misc/macio/gpio.h b/include/hw/misc/macio/gpio.h index 24a4364b39e70ac69b556195b39f5bd70a50c327..4dee09a9dd2e3120f687fb76bf6873d2026ac8ca 100644 --- a/include/hw/misc/macio/gpio.h +++ b/include/hw/misc/macio/gpio.h @@ -28,11 +28,12 @@ #include "hw/ppc/openpic.h" #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_MACIO_GPIO "macio-gpio" -#define MACIO_GPIO(obj) OBJECT_CHECK(MacIOGPIOState, (obj), TYPE_MACIO_GPIO) +OBJECT_DECLARE_SIMPLE_TYPE(MacIOGPIOState, MACIO_GPIO) -typedef struct MacIOGPIOState { +struct MacIOGPIOState { /*< private >*/ SysBusDevice parent; /*< public >*/ @@ -43,7 +44,7 @@ typedef struct MacIOGPIOState { qemu_irq gpio_extirqs[10]; uint8_t gpio_levels[8]; uint8_t gpio_regs[36]; /* XXX Check count */ -} MacIOGPIOState; +}; void macio_set_gpio(MacIOGPIOState *s, uint32_t gpio, bool state); diff --git a/include/hw/misc/macio/macio.h b/include/hw/misc/macio/macio.h index 87335a991c57cd5ef861327871d65c6b6ead5cee..22b4e64b2c4608dd9a42ea2d7954e924252749d0 100644 --- a/include/hw/misc/macio/macio.h +++ b/include/hw/misc/macio/macio.h @@ -36,21 +36,22 @@ #include "hw/ppc/mac.h" #include "hw/ppc/mac_dbdma.h" #include "hw/ppc/openpic.h" +#include "qom/object.h" /* MacIO virtual bus */ #define TYPE_MACIO_BUS "macio-bus" -#define MACIO_BUS(obj) OBJECT_CHECK(MacIOBusState, (obj), TYPE_MACIO_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(MacIOBusState, MACIO_BUS) -typedef struct MacIOBusState { +struct MacIOBusState { /*< private >*/ BusState parent_obj; -} MacIOBusState; +}; /* MacIO IDE */ #define TYPE_MACIO_IDE "macio-ide" -#define MACIO_IDE(obj) OBJECT_CHECK(MACIOIDEState, (obj), TYPE_MACIO_IDE) +OBJECT_DECLARE_SIMPLE_TYPE(MACIOIDEState, MACIO_IDE) -typedef struct MACIOIDEState { +struct MACIOIDEState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -68,15 +69,15 @@ typedef struct MACIOIDEState { bool dma_active; uint32_t timing_reg; uint32_t irq_reg; -} MACIOIDEState; +}; void macio_ide_init_drives(MACIOIDEState *ide, DriveInfo **hd_table); void macio_ide_register_dma(MACIOIDEState *ide); #define TYPE_MACIO "macio" -#define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO) +OBJECT_DECLARE_SIMPLE_TYPE(MacIOState, MACIO) -typedef struct MacIOState { +struct MacIOState { /*< private >*/ PCIDevice parent; /*< public >*/ @@ -88,13 +89,12 @@ typedef struct MacIOState { DBDMAState dbdma; ESCCState escc; uint64_t frequency; -} MacIOState; +}; #define TYPE_OLDWORLD_MACIO "macio-oldworld" -#define OLDWORLD_MACIO(obj) \ - OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO) +OBJECT_DECLARE_SIMPLE_TYPE(OldWorldMacIOState, OLDWORLD_MACIO) -typedef struct OldWorldMacIOState { +struct OldWorldMacIOState { /*< private >*/ MacIOState parent_obj; /*< public >*/ @@ -103,13 +103,12 @@ typedef struct OldWorldMacIOState { MacIONVRAMState nvram; MACIOIDEState ide[2]; -} OldWorldMacIOState; +}; #define TYPE_NEWWORLD_MACIO "macio-newworld" -#define NEWWORLD_MACIO(obj) \ - OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO) +OBJECT_DECLARE_SIMPLE_TYPE(NewWorldMacIOState, NEWWORLD_MACIO) -typedef struct NewWorldMacIOState { +struct NewWorldMacIOState { /*< private >*/ MacIOState parent_obj; /*< public >*/ @@ -119,6 +118,6 @@ typedef struct NewWorldMacIOState { OpenPICState *pic; MACIOIDEState ide[2]; MacIOGPIOState gpio; -} NewWorldMacIOState; +}; #endif /* MACIO_H */ diff --git a/include/hw/misc/macio/pmu.h b/include/hw/misc/macio/pmu.h index 7ef83dee4c5772b6d7cbbd250ddf7601eafc3e7e..78237d99a2383be17f9ddd1611bd475fa8914101 100644 --- a/include/hw/misc/macio/pmu.h +++ b/include/hw/misc/macio/pmu.h @@ -12,6 +12,7 @@ #include "hw/misc/mos6522.h" #include "hw/misc/macio/gpio.h" +#include "qom/object.h" /* * PMU commands @@ -173,20 +174,19 @@ typedef enum { } PMUCmdState; /* MOS6522 PMU */ -typedef struct MOS6522PMUState { +struct MOS6522PMUState { /*< private >*/ MOS6522State parent_obj; -} MOS6522PMUState; +}; #define TYPE_MOS6522_PMU "mos6522-pmu" -#define MOS6522_PMU(obj) OBJECT_CHECK(MOS6522PMUState, (obj), \ - TYPE_MOS6522_PMU) +OBJECT_DECLARE_SIMPLE_TYPE(MOS6522PMUState, MOS6522_PMU) /** * PMUState: * @last_b: last value of B register */ -typedef struct PMUState { +struct PMUState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -218,10 +218,6 @@ typedef struct PMUState { /* ADB */ bool has_adb; ADBBusState adb_bus; - uint16_t adb_poll_mask; - uint8_t autopoll_rate_ms; - uint8_t autopoll_mask; - QEMUTimer *adb_poll_timer; uint8_t adb_reply_size; uint8_t adb_reply[ADB_MAX_OUT_LEN]; @@ -232,9 +228,9 @@ typedef struct PMUState { /* GPIO */ MacIOGPIOState *gpio; -} PMUState; +}; #define TYPE_VIA_PMU "via-pmu" -#define VIA_PMU(obj) OBJECT_CHECK(PMUState, (obj), TYPE_VIA_PMU) +OBJECT_DECLARE_SIMPLE_TYPE(PMUState, VIA_PMU) #endif /* PMU_H */ diff --git a/include/hw/misc/max111x.h b/include/hw/misc/max111x.h new file mode 100644 index 0000000000000000000000000000000000000000..606cf1e0a2a1eaf9f25c0146f45f3eeed3da6d28 --- /dev/null +++ b/include/hw/misc/max111x.h @@ -0,0 +1,56 @@ +/* + * Maxim MAX1110/1111 ADC chip emulation. + * + * Copyright (c) 2006 Openedhand Ltd. + * Written by Andrzej Zaborowski + * + * This code is licensed under the GNU GPLv2. + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ + +#ifndef HW_MISC_MAX111X_H +#define HW_MISC_MAX111X_H + +#include "hw/ssi/ssi.h" +#include "qom/object.h" + +/* + * This is a model of the Maxim MAX1110/1111 ADC chip, which for QEMU + * is an SSI slave device. It has either 4 (max1110) or 8 (max1111) + * 8-bit ADC channels. + * + * QEMU interface: + * + GPIO inputs 0..3 (for max1110) or 0..7 (for max1111): set the value + * of each ADC input, as an unsigned 8-bit value + * + GPIO output 0: interrupt line + * + Properties "input0" to "input3" (max1110) or "input0" to "input7" + * (max1111): initial reset values for ADC inputs. + * + * Known bugs: + * + the interrupt line is not correctly implemented, and will never + * be lowered once it has been asserted. + */ +struct MAX111xState { + SSISlave parent_obj; + + qemu_irq interrupt; + /* Values of inputs at system reset (settable by QOM property) */ + uint8_t reset_input[8]; + + uint8_t tb1, rb2, rb3; + int cycle; + + uint8_t input[8]; + int inputs, com; +}; + +#define TYPE_MAX_111X "max111x" + +OBJECT_DECLARE_SIMPLE_TYPE(MAX111xState, MAX_111X) + +#define TYPE_MAX_1110 "max1110" +#define TYPE_MAX_1111 "max1111" + +#endif diff --git a/include/hw/misc/mchp_pfsoc_dmc.h b/include/hw/misc/mchp_pfsoc_dmc.h new file mode 100644 index 0000000000000000000000000000000000000000..2baa1413b0c2b6fa2f2bb716ffe3c0004a60c892 --- /dev/null +++ b/include/hw/misc/mchp_pfsoc_dmc.h @@ -0,0 +1,56 @@ +/* + * Microchip PolarFire SoC DDR Memory Controller module emulation + * + * Copyright (c) 2020 Wind River Systems, Inc. + * + * Author: + * Bin Meng + * + * 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 or + * (at your option) version 3 of the License. + * + * 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 . + */ + +#ifndef MCHP_PFSOC_DMC_H +#define MCHP_PFSOC_DMC_H + +/* DDR SGMII PHY module */ + +#define MCHP_PFSOC_DDR_SGMII_PHY_REG_SIZE 0x1000 + +typedef struct MchpPfSoCDdrSgmiiPhyState { + SysBusDevice parent; + MemoryRegion sgmii_phy; +} MchpPfSoCDdrSgmiiPhyState; + +#define TYPE_MCHP_PFSOC_DDR_SGMII_PHY "mchp.pfsoc.ddr_sgmii_phy" + +#define MCHP_PFSOC_DDR_SGMII_PHY(obj) \ + OBJECT_CHECK(MchpPfSoCDdrSgmiiPhyState, (obj), \ + TYPE_MCHP_PFSOC_DDR_SGMII_PHY) + +/* DDR CFG module */ + +#define MCHP_PFSOC_DDR_CFG_REG_SIZE 0x40000 + +typedef struct MchpPfSoCDdrCfgState { + SysBusDevice parent; + MemoryRegion cfg; +} MchpPfSoCDdrCfgState; + +#define TYPE_MCHP_PFSOC_DDR_CFG "mchp.pfsoc.ddr_cfg" + +#define MCHP_PFSOC_DDR_CFG(obj) \ + OBJECT_CHECK(MchpPfSoCDdrCfgState, (obj), \ + TYPE_MCHP_PFSOC_DDR_CFG) + +#endif /* MCHP_PFSOC_DMC_H */ diff --git a/include/hw/misc/mchp_pfsoc_ioscb.h b/include/hw/misc/mchp_pfsoc_ioscb.h new file mode 100644 index 0000000000000000000000000000000000000000..9235523e33403dc694b838f9324ffcb5baabb6b0 --- /dev/null +++ b/include/hw/misc/mchp_pfsoc_ioscb.h @@ -0,0 +1,50 @@ +/* + * Microchip PolarFire SoC IOSCB module emulation + * + * Copyright (c) 2020 Wind River Systems, Inc. + * + * Author: + * Bin Meng + * + * 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 or + * (at your option) version 3 of the License. + * + * 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 . + */ + +#ifndef MCHP_PFSOC_IOSCB_H +#define MCHP_PFSOC_IOSCB_H + +typedef struct MchpPfSoCIoscbState { + SysBusDevice parent; + MemoryRegion container; + MemoryRegion lane01; + MemoryRegion lane23; + MemoryRegion ctrl; + MemoryRegion cfg; + MemoryRegion pll_mss; + MemoryRegion cfm_mss; + MemoryRegion pll_ddr; + MemoryRegion bc_ddr; + MemoryRegion io_calib_ddr; + MemoryRegion pll_sgmii; + MemoryRegion dll_sgmii; + MemoryRegion cfm_sgmii; + MemoryRegion bc_sgmii; + MemoryRegion io_calib_sgmii; +} MchpPfSoCIoscbState; + +#define TYPE_MCHP_PFSOC_IOSCB "mchp.pfsoc.ioscb" + +#define MCHP_PFSOC_IOSCB(obj) \ + OBJECT_CHECK(MchpPfSoCIoscbState, (obj), TYPE_MCHP_PFSOC_IOSCB) + +#endif /* MCHP_PFSOC_IOSCB_H */ diff --git a/include/hw/misc/mchp_pfsoc_sysreg.h b/include/hw/misc/mchp_pfsoc_sysreg.h new file mode 100644 index 0000000000000000000000000000000000000000..546ba68f6a182fee949cf392ba14d3a998a27719 --- /dev/null +++ b/include/hw/misc/mchp_pfsoc_sysreg.h @@ -0,0 +1,39 @@ +/* + * Microchip PolarFire SoC SYSREG module emulation + * + * Copyright (c) 2020 Wind River Systems, Inc. + * + * Author: + * Bin Meng + * + * 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 or + * (at your option) version 3 of the License. + * + * 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 . + */ + +#ifndef MCHP_PFSOC_SYSREG_H +#define MCHP_PFSOC_SYSREG_H + +#define MCHP_PFSOC_SYSREG_REG_SIZE 0x2000 + +typedef struct MchpPfSoCSysregState { + SysBusDevice parent; + MemoryRegion sysreg; +} MchpPfSoCSysregState; + +#define TYPE_MCHP_PFSOC_SYSREG "mchp.pfsoc.sysreg" + +#define MCHP_PFSOC_SYSREG(obj) \ + OBJECT_CHECK(MchpPfSoCSysregState, (obj), \ + TYPE_MCHP_PFSOC_SYSREG) + +#endif /* MCHP_PFSOC_SYSREG_H */ diff --git a/include/hw/misc/mips_cmgcr.h b/include/hw/misc/mips_cmgcr.h index 3e6e22327381d24669ef5ffd4c11e3479d4b2113..9fa58942d7362d83e79c23badc59a3b38554000f 100644 --- a/include/hw/misc/mips_cmgcr.h +++ b/include/hw/misc/mips_cmgcr.h @@ -11,9 +11,10 @@ #define MIPS_CMGCR_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_MIPS_GCR "mips-gcr" -#define MIPS_GCR(obj) OBJECT_CHECK(MIPSGCRState, (obj), TYPE_MIPS_GCR) +OBJECT_DECLARE_SIMPLE_TYPE(MIPSGCRState, MIPS_GCR) #define GCR_BASE_ADDR 0x1fbf8000ULL #define GCR_ADDRSPACE_SZ 0x8000 @@ -70,7 +71,6 @@ struct MIPSGCRVPState { uint64_t reset_base; }; -typedef struct MIPSGCRState MIPSGCRState; struct MIPSGCRState { SysBusDevice parent_obj; diff --git a/include/hw/misc/mips_cpc.h b/include/hw/misc/mips_cpc.h index 3f670578b05b366efe9a2da6ae33048d91e4522f..fcafbd5e002367787bc5f6802bbfe5d1d6975947 100644 --- a/include/hw/misc/mips_cpc.h +++ b/include/hw/misc/mips_cpc.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -21,6 +21,7 @@ #define MIPS_CPC_H #include "hw/sysbus.h" +#include "qom/object.h" #define CPC_ADDRSPACE_SZ 0x6000 @@ -34,9 +35,9 @@ #define CPC_VP_RUNNING_OFS 0x30 #define TYPE_MIPS_CPC "mips-cpc" -#define MIPS_CPC(obj) OBJECT_CHECK(MIPSCPCState, (obj), TYPE_MIPS_CPC) +OBJECT_DECLARE_SIMPLE_TYPE(MIPSCPCState, MIPS_CPC) -typedef struct MIPSCPCState { +struct MIPSCPCState { SysBusDevice parent_obj; uint32_t num_vp; @@ -44,6 +45,6 @@ typedef struct MIPSCPCState { MemoryRegion mr; uint64_t vp_running; /* Indicates which VPs are in the run state */ -} MIPSCPCState; +}; #endif /* MIPS_CPC_H */ diff --git a/include/hw/misc/mips_itu.h b/include/hw/misc/mips_itu.h index c44e7672b694233da2357a5cff45a41a798ca763..50d961106da41f9062843a5538e5b593e97c94ee 100644 --- a/include/hw/misc/mips_itu.h +++ b/include/hw/misc/mips_itu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -21,9 +21,10 @@ #define MIPS_ITU_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_MIPS_ITU "mips-itu" -#define MIPS_ITU(obj) OBJECT_CHECK(MIPSITUState, (obj), TYPE_MIPS_ITU) +OBJECT_DECLARE_SIMPLE_TYPE(MIPSITUState, MIPS_ITU) #define ITC_CELL_DEPTH_SHIFT 2 #define ITC_CELL_DEPTH (1u << ITC_CELL_DEPTH_SHIFT) @@ -51,7 +52,7 @@ typedef struct ITCStorageCell { #define ITC_ADDRESSMAP_NUM 2 -typedef struct MIPSITUState { +struct MIPSITUState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -74,7 +75,7 @@ typedef struct MIPSITUState { bool saar_present; void *saar; -} MIPSITUState; +}; /* Get ITC Configuration Tag memory region. */ MemoryRegion *mips_itu_get_tag_region(MIPSITUState *itu); diff --git a/include/hw/misc/mos6522.h b/include/hw/misc/mos6522.h index 97384c6e02cd261963826dd50eed07798c3b8ef9..fc95d22b0fd04bf46ae0b6ce87f11323d6128324 100644 --- a/include/hw/misc/mos6522.h +++ b/include/hw/misc/mos6522.h @@ -30,6 +30,7 @@ #include "exec/memory.h" #include "hw/sysbus.h" #include "hw/input/adb.h" +#include "qom/object.h" /* Bits in ACR */ #define SR_CTRL 0x1c /* Shift register control bits */ @@ -99,7 +100,7 @@ typedef struct MOS6522Timer { * @last_b: last value of B register * @last_acr: last value of ACR register */ -typedef struct MOS6522State { +struct MOS6522State { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -120,12 +121,12 @@ typedef struct MOS6522State { uint64_t frequency; qemu_irq irq; -} MOS6522State; +}; #define TYPE_MOS6522 "mos6522" -#define MOS6522(obj) OBJECT_CHECK(MOS6522State, (obj), TYPE_MOS6522) +OBJECT_DECLARE_TYPE(MOS6522State, MOS6522DeviceClass, MOS6522) -typedef struct MOS6522DeviceClass { +struct MOS6522DeviceClass { DeviceClass parent_class; DeviceReset parent_reset; @@ -138,12 +139,8 @@ typedef struct MOS6522DeviceClass { uint64_t (*get_timer2_counter_value)(MOS6522State *dev, MOS6522Timer *ti); uint64_t (*get_timer1_load_time)(MOS6522State *dev, MOS6522Timer *ti); uint64_t (*get_timer2_load_time)(MOS6522State *dev, MOS6522Timer *ti); -} MOS6522DeviceClass; +}; -#define MOS6522_DEVICE_CLASS(cls) \ - OBJECT_CLASS_CHECK(MOS6522DeviceClass, (cls), TYPE_MOS6522) -#define MOS6522_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(MOS6522DeviceClass, (obj), TYPE_MOS6522) extern const VMStateDescription vmstate_mos6522; diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h index 69e265cd4b234f9ea8fc51e307a4ce529ff950b2..a010fdb2b6d11941e8a0c38219947bc19ec8eefc 100644 --- a/include/hw/misc/mps2-fpgaio.h +++ b/include/hw/misc/mps2-fpgaio.h @@ -22,16 +22,19 @@ #define MPS2_FPGAIO_H #include "hw/sysbus.h" +#include "hw/misc/led.h" +#include "qom/object.h" #define TYPE_MPS2_FPGAIO "mps2-fpgaio" -#define MPS2_FPGAIO(obj) OBJECT_CHECK(MPS2FPGAIO, (obj), TYPE_MPS2_FPGAIO) +OBJECT_DECLARE_SIMPLE_TYPE(MPS2FPGAIO, MPS2_FPGAIO) -typedef struct { +struct MPS2FPGAIO { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ MemoryRegion iomem; + LEDState *led[2]; uint32_t led0; uint32_t prescale; @@ -48,6 +51,6 @@ typedef struct { /* These hold the CLOCK_VIRTUAL ns tick when the CLK1HZ/CLK100HZ was zero */ int64_t clk1hz_tick_offset; int64_t clk100hz_tick_offset; -} MPS2FPGAIO; +}; #endif diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h index 7045473788b711d202e5b2784ab74f95f41f91e8..f65d87320316151b6637b273bd67c596c735f898 100644 --- a/include/hw/misc/mps2-scc.h +++ b/include/hw/misc/mps2-scc.h @@ -13,18 +13,21 @@ #define MPS2_SCC_H #include "hw/sysbus.h" +#include "hw/misc/led.h" +#include "qom/object.h" #define TYPE_MPS2_SCC "mps2-scc" -#define MPS2_SCC(obj) OBJECT_CHECK(MPS2SCC, (obj), TYPE_MPS2_SCC) +OBJECT_DECLARE_SIMPLE_TYPE(MPS2SCC, MPS2_SCC) #define NUM_OSCCLK 3 -typedef struct { +struct MPS2SCC { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ MemoryRegion iomem; + LEDState *led[8]; uint32_t cfg0; uint32_t cfg1; @@ -38,6 +41,6 @@ typedef struct { uint32_t id; uint32_t oscclk[NUM_OSCCLK]; uint32_t oscclk_reset[NUM_OSCCLK]; -} MPS2SCC; +}; #endif diff --git a/include/hw/misc/msf2-sysreg.h b/include/hw/misc/msf2-sysreg.h index 5993f67b4e543b391d204bde3873fdebd9a0936f..fc1890e710df58378a99604477b67965fbbeb463 100644 --- a/include/hw/misc/msf2-sysreg.h +++ b/include/hw/misc/msf2-sysreg.h @@ -26,6 +26,7 @@ #define HW_MSF2_SYSREG_H #include "hw/sysbus.h" +#include "qom/object.h" enum { ESRAM_CR = 0x00 / 4, @@ -61,9 +62,9 @@ enum { #define MSF2_SYSREG_MMIO_SIZE 0x300 #define TYPE_MSF2_SYSREG "msf2-sysreg" -#define MSF2_SYSREG(obj) OBJECT_CHECK(MSF2SysregState, (obj), TYPE_MSF2_SYSREG) +OBJECT_DECLARE_SIMPLE_TYPE(MSF2SysregState, MSF2_SYSREG) -typedef struct MSF2SysregState { +struct MSF2SysregState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -72,6 +73,6 @@ typedef struct MSF2SysregState { uint8_t apb1div; uint32_t regs[MSF2_SYSREG_MMIO_SIZE / 4]; -} MSF2SysregState; +}; #endif /* HW_MSF2_SYSREG_H */ diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h new file mode 100644 index 0000000000000000000000000000000000000000..2338fbbdb5d5e63f9d7bc6c72087f9bcdd6b8aac --- /dev/null +++ b/include/hw/misc/npcm7xx_clk.h @@ -0,0 +1,50 @@ +/* + * Nuvoton NPCM7xx Clock Control Registers. + * + * Copyright 2020 Google LLC + * + * 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. + */ +#ifndef NPCM7XX_CLK_H +#define NPCM7XX_CLK_H + +#include "exec/memory.h" +#include "hw/sysbus.h" + +/* + * The reference clock frequency for the timer modules, and the SECCNT and + * CNTR25M registers in this module, is always 25 MHz. + */ +#define NPCM7XX_TIMER_REF_HZ (25000000) + +/* + * Number of registers in our device state structure. Don't change this without + * incrementing the version_id in the vmstate. + */ +#define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t)) + +#define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in" + +typedef struct NPCM7xxCLKState { + SysBusDevice parent; + + MemoryRegion iomem; + + uint32_t regs[NPCM7XX_CLK_NR_REGS]; + + /* Time reference for SECCNT and CNTR25M, initialized by power on reset */ + int64_t ref_ns; +} NPCM7xxCLKState; + +#define TYPE_NPCM7XX_CLK "npcm7xx-clk" +#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK) + +#endif /* NPCM7XX_CLK_H */ diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h new file mode 100644 index 0000000000000000000000000000000000000000..13109d9d324770893defc8b53e3f760e8ec726c6 --- /dev/null +++ b/include/hw/misc/npcm7xx_gcr.h @@ -0,0 +1,43 @@ +/* + * Nuvoton NPCM7xx System Global Control Registers. + * + * Copyright 2020 Google LLC + * + * 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. + */ +#ifndef NPCM7XX_GCR_H +#define NPCM7XX_GCR_H + +#include "exec/memory.h" +#include "hw/sysbus.h" + +/* + * Number of registers in our device state structure. Don't change this without + * incrementing the version_id in the vmstate. + */ +#define NPCM7XX_GCR_NR_REGS (0x148 / sizeof(uint32_t)) + +typedef struct NPCM7xxGCRState { + SysBusDevice parent; + + MemoryRegion iomem; + + uint32_t regs[NPCM7XX_GCR_NR_REGS]; + + uint32_t reset_pwron; + uint32_t reset_mdlr; + uint32_t reset_intcr3; +} NPCM7xxGCRState; + +#define TYPE_NPCM7XX_GCR "npcm7xx-gcr" +#define NPCM7XX_GCR(obj) OBJECT_CHECK(NPCM7xxGCRState, (obj), TYPE_NPCM7XX_GCR) + +#endif /* NPCM7XX_GCR_H */ diff --git a/include/hw/misc/npcm7xx_rng.h b/include/hw/misc/npcm7xx_rng.h new file mode 100644 index 0000000000000000000000000000000000000000..5e85fd439d8ac0ea1966001c2b4b9e03c4e69b35 --- /dev/null +++ b/include/hw/misc/npcm7xx_rng.h @@ -0,0 +1,34 @@ +/* + * Nuvoton NPCM7xx Random Number Generator. + * + * Copyright 2020 Google LLC + * + * 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. + */ +#ifndef NPCM7XX_RNG_H +#define NPCM7XX_RNG_H + +#include "hw/sysbus.h" + +typedef struct NPCM7xxRNGState { + SysBusDevice parent; + + MemoryRegion iomem; + + uint8_t rngcs; + uint8_t rngd; + uint8_t rngmode; +} NPCM7xxRNGState; + +#define TYPE_NPCM7XX_RNG "npcm7xx-rng" +#define NPCM7XX_RNG(obj) OBJECT_CHECK(NPCM7xxRNGState, (obj), TYPE_NPCM7XX_RNG) + +#endif /* NPCM7XX_RNG_H */ diff --git a/include/hw/misc/nrf51_rng.h b/include/hw/misc/nrf51_rng.h index b0133bf6652c35709eacdd1634172b8244f650b7..9aff9a76f891e7801c23f981b0e7106b16fa9e52 100644 --- a/include/hw/misc/nrf51_rng.h +++ b/include/hw/misc/nrf51_rng.h @@ -36,8 +36,9 @@ #include "hw/sysbus.h" #include "qemu/timer.h" +#include "qom/object.h" #define TYPE_NRF51_RNG "nrf51_soc.rng" -#define NRF51_RNG(obj) OBJECT_CHECK(NRF51RNGState, (obj), TYPE_NRF51_RNG) +OBJECT_DECLARE_SIMPLE_TYPE(NRF51RNGState, NRF51_RNG) #define NRF51_RNG_SIZE 0x1000 @@ -54,7 +55,7 @@ #define NRF51_RNG_REG_CONFIG_DECEN 0 #define NRF51_RNG_REG_VALUE 0x508 -typedef struct { +struct NRF51RNGState { SysBusDevice parent_obj; MemoryRegion mmio; @@ -78,7 +79,7 @@ typedef struct { uint32_t interrupt_enabled; uint32_t filter_enabled; -} NRF51RNGState; +}; #endif /* NRF51_RNG_H */ diff --git a/include/hw/misc/pca9552.h b/include/hw/misc/pca9552.h index ebb43c63fe110085b3b18c631feaa0472aedac88..b6f4e264fedbb5cc39b11e5438799cf4b16c173c 100644 --- a/include/hw/misc/pca9552.h +++ b/include/hw/misc/pca9552.h @@ -10,13 +10,18 @@ #define PCA9552_H #include "hw/i2c/i2c.h" +#include "qom/object.h" #define TYPE_PCA9552 "pca9552" -#define PCA9552(obj) OBJECT_CHECK(PCA9552State, (obj), TYPE_PCA9552) +#define TYPE_PCA955X "pca955x" +typedef struct PCA955xState PCA955xState; +DECLARE_INSTANCE_CHECKER(PCA955xState, PCA955X, + TYPE_PCA955X) -#define PCA9552_NR_REGS 10 +#define PCA955X_NR_REGS 10 +#define PCA955X_PIN_COUNT_MAX 16 -typedef struct PCA9552State { +struct PCA955xState { /*< private >*/ I2CSlave i2c; /*< public >*/ @@ -24,9 +29,9 @@ typedef struct PCA9552State { uint8_t len; uint8_t pointer; - uint8_t regs[PCA9552_NR_REGS]; - uint8_t max_reg; - uint8_t nr_leds; -} PCA9552State; + uint8_t regs[PCA955X_NR_REGS]; + qemu_irq gpio[PCA955X_PIN_COUNT_MAX]; + char *description; /* For debugging purpose only */ +}; #endif diff --git a/include/hw/riscv/sifive_e_prci.h b/include/hw/misc/sifive_e_prci.h similarity index 89% rename from include/hw/riscv/sifive_e_prci.h rename to include/hw/misc/sifive_e_prci.h index 698b0b451c16fa672427a84dd75fbd031e52e93a..262ca16181b748b5ce9aad9b1d4e46275aa1db53 100644 --- a/include/hw/riscv/sifive_e_prci.h +++ b/include/hw/misc/sifive_e_prci.h @@ -18,6 +18,7 @@ #ifndef HW_SIFIVE_E_PRCI_H #define HW_SIFIVE_E_PRCI_H +#include "qom/object.h" enum { SIFIVE_E_PRCI_HFROSCCFG = 0x0, @@ -51,10 +52,11 @@ enum { #define TYPE_SIFIVE_E_PRCI "riscv.sifive.e.prci" -#define SIFIVE_E_PRCI(obj) \ - OBJECT_CHECK(SiFiveEPRCIState, (obj), TYPE_SIFIVE_E_PRCI) +typedef struct SiFiveEPRCIState SiFiveEPRCIState; +DECLARE_INSTANCE_CHECKER(SiFiveEPRCIState, SIFIVE_E_PRCI, + TYPE_SIFIVE_E_PRCI) -typedef struct SiFiveEPRCIState { +struct SiFiveEPRCIState { /*< private >*/ SysBusDevice parent_obj; @@ -64,7 +66,7 @@ typedef struct SiFiveEPRCIState { uint32_t hfxosccfg; uint32_t pllcfg; uint32_t plloutdiv; -} SiFiveEPRCIState; +}; DeviceState *sifive_e_prci_create(hwaddr addr); diff --git a/include/hw/riscv/sifive_test.h b/include/hw/misc/sifive_test.h similarity index 84% rename from include/hw/riscv/sifive_test.h rename to include/hw/misc/sifive_test.h index 1ec416ac1ba98edec06720e68e3a4d9a69cf17f9..88a38d00c59149e32180aa4e9e7309c7e686ca5f 100644 --- a/include/hw/riscv/sifive_test.h +++ b/include/hw/misc/sifive_test.h @@ -20,19 +20,21 @@ #define HW_SIFIVE_TEST_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_SIFIVE_TEST "riscv.sifive.test" -#define SIFIVE_TEST(obj) \ - OBJECT_CHECK(SiFiveTestState, (obj), TYPE_SIFIVE_TEST) +typedef struct SiFiveTestState SiFiveTestState; +DECLARE_INSTANCE_CHECKER(SiFiveTestState, SIFIVE_TEST, + TYPE_SIFIVE_TEST) -typedef struct SiFiveTestState { +struct SiFiveTestState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ MemoryRegion mmio; -} SiFiveTestState; +}; enum { FINISHER_FAIL = 0x3333, diff --git a/include/hw/riscv/sifive_u_otp.h b/include/hw/misc/sifive_u_otp.h similarity index 86% rename from include/hw/riscv/sifive_u_otp.h rename to include/hw/misc/sifive_u_otp.h index 639297564ad1aab61edd4988433ee80f84f8d4aa..5d0d7df455f40677a69c6611c9851798bf8e556f 100644 --- a/include/hw/riscv/sifive_u_otp.h +++ b/include/hw/misc/sifive_u_otp.h @@ -18,6 +18,7 @@ #ifndef HW_SIFIVE_U_OTP_H #define HW_SIFIVE_U_OTP_H +#include "qom/object.h" #define SIFIVE_U_OTP_PA 0x00 #define SIFIVE_U_OTP_PAIO 0x04 @@ -35,6 +36,8 @@ #define SIFIVE_U_OTP_PTRIM 0x34 #define SIFIVE_U_OTP_PWE 0x38 +#define SIFIVE_U_OTP_PWE_EN (1 << 0) + #define SIFIVE_U_OTP_PCE_EN (1 << 0) #define SIFIVE_U_OTP_PDSTB_EN (1 << 0) @@ -43,16 +46,18 @@ #define SIFIVE_U_OTP_PA_MASK 0xfff #define SIFIVE_U_OTP_NUM_FUSES 0x1000 +#define SIFIVE_U_OTP_FUSE_WORD 4 #define SIFIVE_U_OTP_SERIAL_ADDR 0xfc #define SIFIVE_U_OTP_REG_SIZE 0x1000 #define TYPE_SIFIVE_U_OTP "riscv.sifive.u.otp" -#define SIFIVE_U_OTP(obj) \ - OBJECT_CHECK(SiFiveUOTPState, (obj), TYPE_SIFIVE_U_OTP) +typedef struct SiFiveUOTPState SiFiveUOTPState; +DECLARE_INSTANCE_CHECKER(SiFiveUOTPState, SIFIVE_U_OTP, + TYPE_SIFIVE_U_OTP) -typedef struct SiFiveUOTPState { +struct SiFiveUOTPState { /*< private >*/ SysBusDevice parent_obj; @@ -73,8 +78,10 @@ typedef struct SiFiveUOTPState { uint32_t ptrim; uint32_t pwe; uint32_t fuse[SIFIVE_U_OTP_NUM_FUSES]; + uint32_t fuse_wo[SIFIVE_U_OTP_NUM_FUSES]; /* config */ uint32_t serial; -} SiFiveUOTPState; + BlockBackend *blk; +}; #endif /* HW_SIFIVE_U_OTP_H */ diff --git a/include/hw/riscv/sifive_u_prci.h b/include/hw/misc/sifive_u_prci.h similarity index 92% rename from include/hw/riscv/sifive_u_prci.h rename to include/hw/misc/sifive_u_prci.h index 0a531fdadc7f70178e758cf6b1befbee6fdebd36..d9ebf40b7fa4aad5a93aad68a58efa2d1fb0fa83 100644 --- a/include/hw/riscv/sifive_u_prci.h +++ b/include/hw/misc/sifive_u_prci.h @@ -18,6 +18,7 @@ #ifndef HW_SIFIVE_U_PRCI_H #define HW_SIFIVE_U_PRCI_H +#include "qom/object.h" #define SIFIVE_U_PRCI_HFXOSCCFG 0x00 #define SIFIVE_U_PRCI_COREPLLCFG0 0x04 @@ -58,10 +59,11 @@ #define TYPE_SIFIVE_U_PRCI "riscv.sifive.u.prci" -#define SIFIVE_U_PRCI(obj) \ - OBJECT_CHECK(SiFiveUPRCIState, (obj), TYPE_SIFIVE_U_PRCI) +typedef struct SiFiveUPRCIState SiFiveUPRCIState; +DECLARE_INSTANCE_CHECKER(SiFiveUPRCIState, SIFIVE_U_PRCI, + TYPE_SIFIVE_U_PRCI) -typedef struct SiFiveUPRCIState { +struct SiFiveUPRCIState { /*< private >*/ SysBusDevice parent_obj; @@ -76,7 +78,7 @@ typedef struct SiFiveUPRCIState { uint32_t coreclksel; uint32_t devicesreset; uint32_t clkmuxstatus; -} SiFiveUPRCIState; +}; /* * Clock indexes for use by Device Tree data and the PRCI driver. diff --git a/include/hw/misc/stm32f2xx_syscfg.h b/include/hw/misc/stm32f2xx_syscfg.h index 84e06fdecf06fe212a692b6a20ae508e76f485a0..8595a3b31b068d5bacc094e0b48042ec28d4b1ba 100644 --- a/include/hw/misc/stm32f2xx_syscfg.h +++ b/include/hw/misc/stm32f2xx_syscfg.h @@ -26,6 +26,7 @@ #define HW_STM32F2XX_SYSCFG_H #include "hw/sysbus.h" +#include "qom/object.h" #define SYSCFG_MEMRMP 0x00 #define SYSCFG_PMC 0x04 @@ -36,10 +37,9 @@ #define SYSCFG_CMPCR 0x20 #define TYPE_STM32F2XX_SYSCFG "stm32f2xx-syscfg" -#define STM32F2XX_SYSCFG(obj) \ - OBJECT_CHECK(STM32F2XXSyscfgState, (obj), TYPE_STM32F2XX_SYSCFG) +OBJECT_DECLARE_SIMPLE_TYPE(STM32F2XXSyscfgState, STM32F2XX_SYSCFG) -typedef struct { +struct STM32F2XXSyscfgState { /* */ SysBusDevice parent_obj; @@ -53,8 +53,6 @@ typedef struct { uint32_t syscfg_exticr3; uint32_t syscfg_exticr4; uint32_t syscfg_cmpcr; - - qemu_irq irq; -} STM32F2XXSyscfgState; +}; #endif /* HW_STM32F2XX_SYSCFG_H */ diff --git a/include/hw/misc/stm32f4xx_exti.h b/include/hw/misc/stm32f4xx_exti.h index 707036a41b1822cf09634699092b743ec9f481ac..24b6fa7724b1a693677be69497d427b40fdd0389 100644 --- a/include/hw/misc/stm32f4xx_exti.h +++ b/include/hw/misc/stm32f4xx_exti.h @@ -27,6 +27,7 @@ #include "hw/sysbus.h" #include "hw/hw.h" +#include "qom/object.h" #define EXTI_IMR 0x00 #define EXTI_EMR 0x04 @@ -36,13 +37,12 @@ #define EXTI_PR 0x14 #define TYPE_STM32F4XX_EXTI "stm32f4xx-exti" -#define STM32F4XX_EXTI(obj) \ - OBJECT_CHECK(STM32F4xxExtiState, (obj), TYPE_STM32F4XX_EXTI) +OBJECT_DECLARE_SIMPLE_TYPE(STM32F4xxExtiState, STM32F4XX_EXTI) #define NUM_GPIO_EVENT_IN_LINES 16 #define NUM_INTERRUPT_OUT_LINES 16 -typedef struct { +struct STM32F4xxExtiState { SysBusDevice parent_obj; MemoryRegion mmio; @@ -55,6 +55,6 @@ typedef struct { uint32_t exti_pr; qemu_irq irq[NUM_INTERRUPT_OUT_LINES]; -} STM32F4xxExtiState; +}; #endif diff --git a/include/hw/misc/stm32f4xx_syscfg.h b/include/hw/misc/stm32f4xx_syscfg.h index c62c6629e544584622e56043ba22aeb386bd373d..8c31feccd37969f8cdbab1855e952851c975b850 100644 --- a/include/hw/misc/stm32f4xx_syscfg.h +++ b/include/hw/misc/stm32f4xx_syscfg.h @@ -27,6 +27,7 @@ #include "hw/sysbus.h" #include "hw/hw.h" +#include "qom/object.h" #define SYSCFG_MEMRMP 0x00 #define SYSCFG_PMC 0x04 @@ -37,12 +38,11 @@ #define SYSCFG_CMPCR 0x20 #define TYPE_STM32F4XX_SYSCFG "stm32f4xx-syscfg" -#define STM32F4XX_SYSCFG(obj) \ - OBJECT_CHECK(STM32F4xxSyscfgState, (obj), TYPE_STM32F4XX_SYSCFG) +OBJECT_DECLARE_SIMPLE_TYPE(STM32F4xxSyscfgState, STM32F4XX_SYSCFG) #define SYSCFG_NUM_EXTICR 4 -typedef struct { +struct STM32F4xxSyscfgState { /* */ SysBusDevice parent_obj; @@ -56,6 +56,6 @@ typedef struct { qemu_irq irq; qemu_irq gpio_out[16]; -} STM32F4xxSyscfgState; +}; #endif diff --git a/include/hw/misc/tz-mpc.h b/include/hw/misc/tz-mpc.h index 6f15945410d0fc5a6525abb0a28882a3330160a0..74d5d822cf336f6912cddd1c0ba28f23d188c3f0 100644 --- a/include/hw/misc/tz-mpc.h +++ b/include/hw/misc/tz-mpc.h @@ -32,15 +32,15 @@ #define TZ_MPC_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_TZ_MPC "tz-mpc" -#define TZ_MPC(obj) OBJECT_CHECK(TZMPC, (obj), TYPE_TZ_MPC) +OBJECT_DECLARE_SIMPLE_TYPE(TZMPC, TZ_MPC) #define TZ_NUM_PORTS 16 #define TYPE_TZ_MPC_IOMMU_MEMORY_REGION "tz-mpc-iommu-memory-region" -typedef struct TZMPC TZMPC; struct TZMPC { /*< private >*/ diff --git a/include/hw/misc/tz-msc.h b/include/hw/misc/tz-msc.h index 116b96ae9b85562e044dede97a039d8b76fd4fba..77cc7f240483652002acb42abe7b03d2076aeb7c 100644 --- a/include/hw/misc/tz-msc.h +++ b/include/hw/misc/tz-msc.h @@ -52,11 +52,12 @@ #include "hw/sysbus.h" #include "target/arm/idau.h" +#include "qom/object.h" #define TYPE_TZ_MSC "tz-msc" -#define TZ_MSC(obj) OBJECT_CHECK(TZMSC, (obj), TYPE_TZ_MSC) +OBJECT_DECLARE_SIMPLE_TYPE(TZMSC, TZ_MSC) -typedef struct TZMSC { +struct TZMSC { /*< private >*/ SysBusDevice parent_obj; @@ -74,6 +75,6 @@ typedef struct TZMSC { AddressSpace downstream_as; MemoryRegion upstream; IDAUInterface *idau; -} TZMSC; +}; #endif diff --git a/include/hw/misc/tz-ppc.h b/include/hw/misc/tz-ppc.h index 080d6e2ec17e531b837bc1ae404d6a778b15a876..021d671b29b66888d5eabfca26b25d41ff281c66 100644 --- a/include/hw/misc/tz-ppc.h +++ b/include/hw/misc/tz-ppc.h @@ -66,13 +66,13 @@ #define TZ_PPC_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_TZ_PPC "tz-ppc" -#define TZ_PPC(obj) OBJECT_CHECK(TZPPC, (obj), TYPE_TZ_PPC) +OBJECT_DECLARE_SIMPLE_TYPE(TZPPC, TZ_PPC) #define TZ_NUM_PORTS 16 -typedef struct TZPPC TZPPC; typedef struct TZPPCPort { TZPPC *ppc; diff --git a/include/hw/misc/unimp.h b/include/hw/misc/unimp.h index 44d87be9032e3b744a20077c6368713b870bf1c3..518d627dc5dc8dda55894f1dba33ea5a87bb688a 100644 --- a/include/hw/misc/unimp.h +++ b/include/hw/misc/unimp.h @@ -10,18 +10,20 @@ #include "hw/qdev-properties.h" #include "hw/sysbus.h" +#include "qapi/error.h" +#include "qom/object.h" #define TYPE_UNIMPLEMENTED_DEVICE "unimplemented-device" -#define UNIMPLEMENTED_DEVICE(obj) \ - OBJECT_CHECK(UnimplementedDeviceState, (obj), TYPE_UNIMPLEMENTED_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(UnimplementedDeviceState, UNIMPLEMENTED_DEVICE) -typedef struct { +struct UnimplementedDeviceState { SysBusDevice parent_obj; MemoryRegion iomem; + unsigned offset_fmt_width; char *name; uint64_t size; -} UnimplementedDeviceState; +}; /** * create_unimplemented_device: create and map a dummy device @@ -40,11 +42,11 @@ static inline void create_unimplemented_device(const char *name, hwaddr base, hwaddr size) { - DeviceState *dev = qdev_create(NULL, TYPE_UNIMPLEMENTED_DEVICE); + DeviceState *dev = qdev_new(TYPE_UNIMPLEMENTED_DEVICE); qdev_prop_set_string(dev, "name", name); qdev_prop_set_uint64(dev, "size", size); - qdev_init_nofail(dev); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map_overlap(SYS_BUS_DEVICE(dev), 0, base, -1000); } diff --git a/include/hw/misc/vmcoreinfo.h b/include/hw/misc/vmcoreinfo.h index d4f3d3a91cb06fbb26af21cb8e342747f0eddd98..0b7b55d400a009c535eb8887526efd9f7c58260e 100644 --- a/include/hw/misc/vmcoreinfo.h +++ b/include/hw/misc/vmcoreinfo.h @@ -14,18 +14,21 @@ #include "hw/qdev-core.h" #include "standard-headers/linux/qemu_fw_cfg.h" +#include "qom/object.h" #define VMCOREINFO_DEVICE "vmcoreinfo" -#define VMCOREINFO(obj) OBJECT_CHECK(VMCoreInfoState, (obj), VMCOREINFO_DEVICE) +typedef struct VMCoreInfoState VMCoreInfoState; +DECLARE_INSTANCE_CHECKER(VMCoreInfoState, VMCOREINFO, + VMCOREINFO_DEVICE) typedef struct fw_cfg_vmcoreinfo FWCfgVMCoreInfo; -typedef struct VMCoreInfoState { - DeviceClass parent_obj; +struct VMCoreInfoState { + DeviceState parent_obj; bool has_vmcoreinfo; FWCfgVMCoreInfo vmcoreinfo; -} VMCoreInfoState; +}; /* returns NULL unless there is exactly one device */ static inline VMCoreInfoState *vmcoreinfo_find(void) diff --git a/include/hw/misc/zynq-xadc.h b/include/hw/misc/zynq-xadc.h index f1a410a3767d84fa0d4b9b3867ec1a4af6cda7fb..602bfb4ab1a2bff48903d4c3562d955ce84156ca 100644 --- a/include/hw/misc/zynq-xadc.h +++ b/include/hw/misc/zynq-xadc.h @@ -16,6 +16,7 @@ #define ZYNQ_XADC_H #include "hw/sysbus.h" +#include "qom/object.h" #define ZYNQ_XADC_MMIO_SIZE 0x0020 #define ZYNQ_XADC_NUM_IO_REGS (ZYNQ_XADC_MMIO_SIZE / 4) @@ -23,10 +24,9 @@ #define ZYNQ_XADC_FIFO_DEPTH 15 #define TYPE_ZYNQ_XADC "xlnx,zynq-xadc" -#define ZYNQ_XADC(obj) \ - OBJECT_CHECK(ZynqXADCState, (obj), TYPE_ZYNQ_XADC) +OBJECT_DECLARE_SIMPLE_TYPE(ZynqXADCState, ZYNQ_XADC) -typedef struct ZynqXADCState { +struct ZynqXADCState { /*< private >*/ SysBusDevice parent_obj; @@ -41,6 +41,6 @@ typedef struct ZynqXADCState { struct IRQState *qemu_irq; -} ZynqXADCState; +}; #endif /* ZYNQ_XADC_H */ diff --git a/include/hw/net/allwinner-sun8i-emac.h b/include/hw/net/allwinner-sun8i-emac.h index eda034e96b2715e874ab09cfe4e6b81b59985e06..460a58f1ca7aa7b184c7b4a7c6a294fb0ac4b355 100644 --- a/include/hw/net/allwinner-sun8i-emac.h +++ b/include/hw/net/allwinner-sun8i-emac.h @@ -30,15 +30,14 @@ */ #define TYPE_AW_SUN8I_EMAC "allwinner-sun8i-emac" -#define AW_SUN8I_EMAC(obj) \ - OBJECT_CHECK(AwSun8iEmacState, (obj), TYPE_AW_SUN8I_EMAC) +OBJECT_DECLARE_SIMPLE_TYPE(AwSun8iEmacState, AW_SUN8I_EMAC) /** @} */ /** * Allwinner Sun8i EMAC object instance state */ -typedef struct AwSun8iEmacState { +struct AwSun8iEmacState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -49,6 +48,12 @@ typedef struct AwSun8iEmacState { /** Interrupt output signal to notify CPU */ qemu_irq irq; + /** Memory region where DMA transfers are done */ + MemoryRegion *dma_mr; + + /** Address space used internally for DMA transfers */ + AddressSpace dma_as; + /** Generic Network Interface Controller (NIC) for networking API */ NICState *nic; @@ -94,6 +99,6 @@ typedef struct AwSun8iEmacState { /** @} */ -} AwSun8iEmacState; +}; #endif /* HW_NET_ALLWINNER_SUN8I_H */ diff --git a/include/hw/net/allwinner_emac.h b/include/hw/net/allwinner_emac.h index 5013207d158aa9d426b0f1d0cf0466bd0a0daf7e..534e748982f876e1b479565555e12e197b1c5e0e 100644 --- a/include/hw/net/allwinner_emac.h +++ b/include/hw/net/allwinner_emac.h @@ -28,9 +28,10 @@ #include "qemu/fifo8.h" #include "hw/net/mii.h" #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_AW_EMAC "allwinner-emac" -#define AW_EMAC(obj) OBJECT_CHECK(AwEmacState, (obj), TYPE_AW_EMAC) +OBJECT_DECLARE_SIMPLE_TYPE(AwEmacState, AW_EMAC) /* * Allwinner EMAC register list @@ -144,7 +145,7 @@ typedef struct RTL8201CPState { uint16_t anlpar; } RTL8201CPState; -typedef struct AwEmacState { +struct AwEmacState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -171,6 +172,6 @@ typedef struct AwEmacState { Fifo8 tx_fifo[NUM_TX_FIFOS]; uint32_t tx_length[NUM_TX_FIFOS]; uint32_t tx_channel; -} AwEmacState; +}; #endif diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h index 5c83036ade1c13663375a23e19c1f9462ade7042..91ebb5c8ae3ae7dcb0248d34e4367528c9571cc2 100644 --- a/include/hw/net/cadence_gem.h +++ b/include/hw/net/cadence_gem.h @@ -24,9 +24,10 @@ #ifndef CADENCE_GEM_H #define CADENCE_GEM_H +#include "qom/object.h" #define TYPE_CADENCE_GEM "cadence_gem" -#define CADENCE_GEM(obj) OBJECT_CHECK(CadenceGEMState, (obj), TYPE_CADENCE_GEM) +OBJECT_DECLARE_SIMPLE_TYPE(CadenceGEMState, CADENCE_GEM) #include "net/net.h" #include "hw/sysbus.h" @@ -40,7 +41,10 @@ #define MAX_TYPE1_SCREENERS 16 #define MAX_TYPE2_SCREENERS 16 -typedef struct CadenceGEMState { +#define MAX_JUMBO_FRAME_SIZE_MASK 0x3FFF +#define MAX_FRAME_SIZE MAX_JUMBO_FRAME_SIZE_MASK + +struct CadenceGEMState { /*< private >*/ SysBusDevice parent_obj; @@ -57,6 +61,7 @@ typedef struct CadenceGEMState { uint8_t num_type1_screeners; uint8_t num_type2_screeners; uint32_t revision; + uint16_t jumbo_max_len; /* GEM registers backing store */ uint32_t regs[CADENCE_GEM_MAXREG]; @@ -69,6 +74,8 @@ typedef struct CadenceGEMState { /* Mask of register bits which are write 1 to clear */ uint32_t regs_w1c[CADENCE_GEM_MAXREG]; + /* PHY address */ + uint8_t phy_addr; /* PHY registers backing store */ uint16_t phy_regs[32]; @@ -80,9 +87,11 @@ typedef struct CadenceGEMState { uint8_t can_rx_state; /* Debug only */ + uint8_t tx_packet[MAX_FRAME_SIZE]; + uint8_t rx_packet[MAX_FRAME_SIZE]; uint32_t rx_desc[MAX_PRIORITY_QUEUES][DESC_MAX_NUM_WORDS]; bool sar_active[4]; -} CadenceGEMState; +}; #endif diff --git a/include/hw/net/ftgmac100.h b/include/hw/net/ftgmac100.h index ab37e7b2b8ae9b1f0acf2f5674ba21813446dd3e..765d1538a49f7e28709fa890f084c454a7f5ac94 100644 --- a/include/hw/net/ftgmac100.h +++ b/include/hw/net/ftgmac100.h @@ -9,9 +9,10 @@ #ifndef FTGMAC100_H #define FTGMAC100_H +#include "qom/object.h" #define TYPE_FTGMAC100 "ftgmac100" -#define FTGMAC100(obj) OBJECT_CHECK(FTGMAC100State, (obj), TYPE_FTGMAC100) +OBJECT_DECLARE_SIMPLE_TYPE(FTGMAC100State, FTGMAC100) #include "hw/sysbus.h" #include "net/net.h" @@ -21,7 +22,7 @@ */ #define FTGMAC100_MAX_FRAME_SIZE 9220 -typedef struct FTGMAC100State { +struct FTGMAC100State { /*< private >*/ SysBusDevice parent_obj; @@ -64,15 +65,15 @@ typedef struct FTGMAC100State { bool aspeed; uint32_t txdes0_edotr; uint32_t rxdes0_edorr; -} FTGMAC100State; +}; #define TYPE_ASPEED_MII "aspeed-mmi" -#define ASPEED_MII(obj) OBJECT_CHECK(AspeedMiiState, (obj), TYPE_ASPEED_MII) +OBJECT_DECLARE_SIMPLE_TYPE(AspeedMiiState, ASPEED_MII) /* * AST2600 MII controller */ -typedef struct AspeedMiiState { +struct AspeedMiiState { /*< private >*/ SysBusDevice parent_obj; @@ -81,6 +82,6 @@ typedef struct AspeedMiiState { MemoryRegion iomem; uint32_t phycr; uint32_t phydata; -} AspeedMiiState; +}; #endif diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h index 7b3faa4019495e785cf80e9178ec2026f4f211a9..e3a8755db92c5d4857f3acbe680224627a25f635 100644 --- a/include/hw/net/imx_fec.h +++ b/include/hw/net/imx_fec.h @@ -23,9 +23,10 @@ #ifndef IMX_FEC_H #define IMX_FEC_H +#include "qom/object.h" #define TYPE_IMX_FEC "imx.fec" -#define IMX_FEC(obj) OBJECT_CHECK(IMXFECState, (obj), TYPE_IMX_FEC) +OBJECT_DECLARE_SIMPLE_TYPE(IMXFECState, IMX_FEC) #define TYPE_IMX_ENET "imx.enet" @@ -247,7 +248,7 @@ typedef struct { #define FSL_IMX25_FEC_SIZE 0x4000 -typedef struct IMXFECState { +struct IMXFECState { /*< private >*/ SysBusDevice parent_obj; @@ -268,11 +269,12 @@ typedef struct IMXFECState { uint32_t phy_advertise; uint32_t phy_int; uint32_t phy_int_mask; + uint32_t phy_num; bool is_fec; /* Buffer used to assemble a Tx frame */ uint8_t frame[ENET_MAX_FRAME_SIZE]; -} IMXFECState; +}; #endif diff --git a/include/hw/net/lance.h b/include/hw/net/lance.h index 0357f5f65c1b3fc5a2a55fdf60ff585ed782ef96..f645d6af67fd82a7daff4a180fdb02ac0b42c9e0 100644 --- a/include/hw/net/lance.h +++ b/include/hw/net/lance.h @@ -32,15 +32,17 @@ #include "net/net.h" #include "hw/net/pcnet.h" #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_LANCE "lance" -#define SYSBUS_PCNET(obj) \ - OBJECT_CHECK(SysBusPCNetState, (obj), TYPE_LANCE) +typedef struct SysBusPCNetState SysBusPCNetState; +DECLARE_INSTANCE_CHECKER(SysBusPCNetState, SYSBUS_PCNET, + TYPE_LANCE) -typedef struct { +struct SysBusPCNetState { SysBusDevice parent_obj; PCNetState state; -} SysBusPCNetState; +}; #endif diff --git a/include/hw/net/lasi_82596.h b/include/hw/net/lasi_82596.h index e76ef8308e6ceab5223e7e3fcbf073507bb6ab44..7b62b048336ce8f1d64d0a8ad445ecd625655e62 100644 --- a/include/hw/net/lasi_82596.h +++ b/include/hw/net/lasi_82596.h @@ -10,18 +10,20 @@ #include "net/net.h" #include "hw/net/i82596.h" +#include "qom/object.h" #define TYPE_LASI_82596 "lasi_82596" -#define SYSBUS_I82596(obj) \ - OBJECT_CHECK(SysBusI82596State, (obj), TYPE_LASI_82596) +typedef struct SysBusI82596State SysBusI82596State; +DECLARE_INSTANCE_CHECKER(SysBusI82596State, SYSBUS_I82596, + TYPE_LASI_82596) -typedef struct { +struct SysBusI82596State { SysBusDevice parent_obj; I82596State state; uint16_t last_val; int val_index:1; -} SysBusI82596State; +}; SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space, hwaddr hpa, qemu_irq irq); diff --git a/include/hw/net/msf2-emac.h b/include/hw/net/msf2-emac.h index 37966d3a81315705cefa8e0124bccb0b57e370e9..846ba6e6dce8add8cc33cc00b397318e14fc83b7 100644 --- a/include/hw/net/msf2-emac.h +++ b/include/hw/net/msf2-emac.h @@ -26,15 +26,15 @@ #include "exec/memory.h" #include "net/net.h" #include "net/eth.h" +#include "qom/object.h" #define TYPE_MSS_EMAC "msf2-emac" -#define MSS_EMAC(obj) \ - OBJECT_CHECK(MSF2EmacState, (obj), TYPE_MSS_EMAC) +OBJECT_DECLARE_SIMPLE_TYPE(MSF2EmacState, MSS_EMAC) #define R_MAX (0x1a0 / 4) #define PHY_MAX_REGS 32 -typedef struct MSF2EmacState { +struct MSF2EmacState { SysBusDevice parent; MemoryRegion mmio; @@ -50,4 +50,4 @@ typedef struct MSF2EmacState { uint16_t phy_regs[PHY_MAX_REGS]; uint32_t regs[R_MAX]; -} MSF2EmacState; +}; diff --git a/include/hw/net/ne2000-isa.h b/include/hw/net/ne2000-isa.h index eef17a680d0e131c4487f756e19a5ad5ad30ef9c..af59ee0b028ba980c8ffa3aa326105b7f0ee03ee 100644 --- a/include/hw/net/ne2000-isa.h +++ b/include/hw/net/ne2000-isa.h @@ -13,6 +13,7 @@ #include "hw/isa/isa.h" #include "hw/qdev-properties.h" #include "net/net.h" +#include "qapi/error.h" #define TYPE_ISA_NE2000 "ne2k_isa" @@ -23,14 +24,14 @@ static inline ISADevice *isa_ne2000_init(ISABus *bus, int base, int irq, qemu_check_nic_model(nd, "ne2k_isa"); - d = isa_try_create(bus, TYPE_ISA_NE2000); + d = isa_try_new(TYPE_ISA_NE2000); if (d) { DeviceState *dev = DEVICE(d); qdev_prop_set_uint32(dev, "iobase", base); qdev_prop_set_uint32(dev, "irq", irq); qdev_set_nic_properties(dev, nd); - qdev_init_nofail(dev); + isa_realize_and_unref(d, bus, &error_fatal); } return d; } diff --git a/include/hw/nmi.h b/include/hw/nmi.h index fe37ce3ad83368e9f34b979f7fe23b121586c7b5..fff41bebc69a245a7f13685139234b690ab28ebd 100644 --- a/include/hw/nmi.h +++ b/include/hw/nmi.h @@ -26,20 +26,19 @@ #define TYPE_NMI "nmi" -#define NMI_CLASS(klass) \ - OBJECT_CLASS_CHECK(NMIClass, (klass), TYPE_NMI) -#define NMI_GET_CLASS(obj) \ - OBJECT_GET_CLASS(NMIClass, (obj), TYPE_NMI) +typedef struct NMIClass NMIClass; +DECLARE_CLASS_CHECKERS(NMIClass, NMI, + TYPE_NMI) #define NMI(obj) \ INTERFACE_CHECK(NMIState, (obj), TYPE_NMI) typedef struct NMIState NMIState; -typedef struct NMIClass { +struct NMIClass { InterfaceClass parent_class; void (*nmi_monitor_handler)(NMIState *n, int cpu_index, Error **errp); -} NMIClass; +}; void nmi_monitor_handle(int cpu_index, Error **errp); diff --git a/include/hw/nubus/mac-nubus-bridge.h b/include/hw/nubus/mac-nubus-bridge.h index ce9c789d999a6fba0f4f3fa5e4210aa915f0aa57..36aa098dd4bffd92f54cc137f803edba17d8ba6d 100644 --- a/include/hw/nubus/mac-nubus-bridge.h +++ b/include/hw/nubus/mac-nubus-bridge.h @@ -10,15 +10,15 @@ #define HW_NUBUS_MAC_H #include "hw/nubus/nubus.h" +#include "qom/object.h" #define TYPE_MAC_NUBUS_BRIDGE "mac-nubus-bridge" -#define MAC_NUBUS_BRIDGE(obj) OBJECT_CHECK(MacNubusState, (obj), \ - TYPE_MAC_NUBUS_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(MacNubusState, MAC_NUBUS_BRIDGE) -typedef struct MacNubusState { +struct MacNubusState { SysBusDevice sysbus_dev; NubusBus *bus; -} MacNubusState; +}; #endif diff --git a/include/hw/nubus/nubus.h b/include/hw/nubus/nubus.h index a8634e54c5c0ff2877e2ba2bde48f4dc869d2986..e2b5cf260ba9eec0a019e90d39dc8b3b8b601ab0 100644 --- a/include/hw/nubus/nubus.h +++ b/include/hw/nubus/nubus.h @@ -11,6 +11,7 @@ #include "hw/qdev-properties.h" #include "exec/address-spaces.h" +#include "qom/object.h" #define NUBUS_SUPER_SLOT_SIZE 0x10000000U #define NUBUS_SUPER_SLOT_NB 0x9 @@ -22,25 +23,23 @@ #define NUBUS_LAST_SLOT 0xF #define TYPE_NUBUS_DEVICE "nubus-device" -#define NUBUS_DEVICE(obj) \ - OBJECT_CHECK(NubusDevice, (obj), TYPE_NUBUS_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(NubusDevice, NUBUS_DEVICE) #define TYPE_NUBUS_BUS "nubus-bus" -#define NUBUS_BUS(obj) OBJECT_CHECK(NubusBus, (obj), TYPE_NUBUS_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(NubusBus, NUBUS_BUS) #define TYPE_NUBUS_BRIDGE "nubus-bridge" -#define NUBUS_BRIDGE(obj) OBJECT_CHECK(NubusBridge, (obj), TYPE_NUBUS_BRIDGE) -typedef struct NubusBus { +struct NubusBus { BusState qbus; MemoryRegion super_slot_io; MemoryRegion slot_io; int current_slot; -} NubusBus; +}; -typedef struct NubusDevice { +struct NubusDevice { DeviceState qdev; int slot_nb; @@ -61,7 +60,7 @@ typedef struct NubusDevice { MemoryRegion rom_io; const uint8_t *rom; -} NubusDevice; +}; void nubus_register_rom(NubusDevice *dev, const uint8_t *rom, uint32_t size, int revision, int format, uint8_t byte_lanes); diff --git a/include/hw/nvram/chrp_nvram.h b/include/hw/nvram/chrp_nvram.h index 09941a9be454e1fc6af79e2eb27f01706ff4f825..4a0f5c21b8848d2a919fecdea1f9d58428c17bc8 100644 --- a/include/hw/nvram/chrp_nvram.h +++ b/include/hw/nvram/chrp_nvram.h @@ -50,7 +50,8 @@ chrp_nvram_finish_partition(ChrpNvramPartHdr *header, uint32_t size) header->checksum = sum & 0xff; } -int chrp_nvram_create_system_partition(uint8_t *data, int min_len); +/* chrp_nvram_create_system_partition() failure is fatal */ +int chrp_nvram_create_system_partition(uint8_t *data, int min_len, int max_len); int chrp_nvram_create_free_partition(uint8_t *data, int len); #endif diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h index 25d93070186fb5c24a039ee753eb978100a614fe..8a9f5738bfa7cd4fc80e52393f2a10616b0e771f 100644 --- a/include/hw/nvram/fw_cfg.h +++ b/include/hw/nvram/fw_cfg.h @@ -5,14 +5,39 @@ #include "standard-headers/linux/qemu_fw_cfg.h" #include "hw/sysbus.h" #include "sysemu/dma.h" +#include "qom/object.h" #define TYPE_FW_CFG "fw_cfg" #define TYPE_FW_CFG_IO "fw_cfg_io" #define TYPE_FW_CFG_MEM "fw_cfg_mem" +#define TYPE_FW_CFG_DATA_GENERATOR_INTERFACE "fw_cfg-data-generator" -#define FW_CFG(obj) OBJECT_CHECK(FWCfgState, (obj), TYPE_FW_CFG) -#define FW_CFG_IO(obj) OBJECT_CHECK(FWCfgIoState, (obj), TYPE_FW_CFG_IO) -#define FW_CFG_MEM(obj) OBJECT_CHECK(FWCfgMemState, (obj), TYPE_FW_CFG_MEM) +OBJECT_DECLARE_SIMPLE_TYPE(FWCfgState, FW_CFG) +OBJECT_DECLARE_SIMPLE_TYPE(FWCfgIoState, FW_CFG_IO) +OBJECT_DECLARE_SIMPLE_TYPE(FWCfgMemState, FW_CFG_MEM) + +typedef struct FWCfgDataGeneratorClass FWCfgDataGeneratorClass; +DECLARE_CLASS_CHECKERS(FWCfgDataGeneratorClass, FW_CFG_DATA_GENERATOR, + TYPE_FW_CFG_DATA_GENERATOR_INTERFACE) + +struct FWCfgDataGeneratorClass { + /*< private >*/ + InterfaceClass parent_class; + /*< public >*/ + + /** + * get_data: + * @obj: the object implementing this interface + * @errp: pointer to a NULL-initialized error object + * + * Returns: reference to a byte array containing the data on success, + * or NULL on error. + * + * The caller should release the reference when no longer + * required. + */ + GByteArray *(*get_data)(Object *obj, Error **errp); +}; typedef struct fw_cfg_file FWCfgFile; @@ -263,6 +288,26 @@ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename, void *fw_cfg_modify_file(FWCfgState *s, const char *filename, void *data, size_t len); +/** + * fw_cfg_add_from_generator: + * @s: fw_cfg device being modified + * @filename: name of new fw_cfg file item + * @gen_id: name of object implementing FW_CFG_DATA_GENERATOR interface + * @errp: pointer to a NULL initialized error object + * + * Add a new NAMED fw_cfg item with the content generated from the + * @gen_id object. The data generated by the @gen_id object is copied + * into the data structure of the fw_cfg device. + * The next available (unused) selector key starting at FW_CFG_FILE_FIRST + * will be used; also, a new entry will be added to the file directory + * structure residing at key value FW_CFG_FILE_DIR, containing the item name, + * data size, and assigned selector key value. + * + * Returns: %true on success, %false on error. + */ +bool fw_cfg_add_from_generator(FWCfgState *s, const char *filename, + const char *gen_id, Error **errp); + FWCfgState *fw_cfg_init_io_dma(uint32_t iobase, uint32_t dma_iobase, AddressSpace *dma_as); FWCfgState *fw_cfg_init_io(uint32_t iobase); diff --git a/include/hw/nvram/npcm7xx_otp.h b/include/hw/nvram/npcm7xx_otp.h new file mode 100644 index 0000000000000000000000000000000000000000..156bbd151ab7558c0a347ae50978a7bddcef62d5 --- /dev/null +++ b/include/hw/nvram/npcm7xx_otp.h @@ -0,0 +1,79 @@ +/* + * Nuvoton NPCM7xx OTP (Fuse Array) Interface + * + * Copyright 2020 Google LLC + * + * 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. + */ +#ifndef NPCM7XX_OTP_H +#define NPCM7XX_OTP_H + +#include "exec/memory.h" +#include "hw/sysbus.h" + +/* Each OTP module holds 8192 bits of one-time programmable storage */ +#define NPCM7XX_OTP_ARRAY_BITS (8192) +#define NPCM7XX_OTP_ARRAY_BYTES (NPCM7XX_OTP_ARRAY_BITS / BITS_PER_BYTE) + +/* Fuse array offsets */ +#define NPCM7XX_FUSE_FUSTRAP (0) +#define NPCM7XX_FUSE_CP_FUSTRAP (12) +#define NPCM7XX_FUSE_DAC_CALIB (16) +#define NPCM7XX_FUSE_ADC_CALIB (24) +#define NPCM7XX_FUSE_DERIVATIVE (64) +#define NPCM7XX_FUSE_TEST_SIG (72) +#define NPCM7XX_FUSE_DIE_LOCATION (74) +#define NPCM7XX_FUSE_GP1 (80) +#define NPCM7XX_FUSE_GP2 (128) + +/* + * Number of registers in our device state structure. Don't change this without + * incrementing the version_id in the vmstate. + */ +#define NPCM7XX_OTP_NR_REGS (0x18 / sizeof(uint32_t)) + +/** + * struct NPCM7xxOTPState - Device state for one OTP module. + * @parent: System bus device. + * @mmio: Memory region through which registers are accessed. + * @regs: Register contents. + * @array: OTP storage array. + */ +typedef struct NPCM7xxOTPState { + SysBusDevice parent; + + MemoryRegion mmio; + uint32_t regs[NPCM7XX_OTP_NR_REGS]; + uint8_t array[NPCM7XX_OTP_ARRAY_BYTES]; +} NPCM7xxOTPState; + +#define TYPE_NPCM7XX_OTP "npcm7xx-otp" +#define NPCM7XX_OTP(obj) OBJECT_CHECK(NPCM7xxOTPState, (obj), TYPE_NPCM7XX_OTP) + +#define TYPE_NPCM7XX_KEY_STORAGE "npcm7xx-key-storage" +#define TYPE_NPCM7XX_FUSE_ARRAY "npcm7xx-fuse-array" + +typedef struct NPCM7xxOTPClass NPCM7xxOTPClass; + +/** + * npcm7xx_otp_array_write - ECC encode and write data to OTP array. + * @s: OTP module. + * @data: Data to be encoded and written. + * @offset: Offset of first byte to be written in the OTP array. + * @len: Number of bytes before ECC encoding. + * + * Each nibble of data is encoded into a byte, so the number of bytes written + * to the array will be @len * 2. + */ +extern void npcm7xx_otp_array_write(NPCM7xxOTPState *s, const void *data, + unsigned int offset, unsigned int len); + +#endif /* NPCM7XX_OTP_H */ diff --git a/include/hw/nvram/nrf51_nvm.h b/include/hw/nvram/nrf51_nvm.h index 3792e4a9fec9ee09ae5b9e6c8b1efad666d1591a..d85e788df5d93dc5196a3eec22414fc5eb9b86f2 100644 --- a/include/hw/nvram/nrf51_nvm.h +++ b/include/hw/nvram/nrf51_nvm.h @@ -23,8 +23,9 @@ #define NRF51_NVM_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_NRF51_NVM "nrf51_soc.nvm" -#define NRF51_NVM(obj) OBJECT_CHECK(NRF51NVMState, (obj), TYPE_NRF51_NVM) +OBJECT_DECLARE_SIMPLE_TYPE(NRF51NVMState, NRF51_NVM) #define NRF51_UICR_FIXTURE_SIZE 64 @@ -44,7 +45,7 @@ #define NRF51_UICR_SIZE 0x100 -typedef struct NRF51NVMState { +struct NRF51NVMState { SysBusDevice parent_obj; MemoryRegion mmio; @@ -58,7 +59,7 @@ typedef struct NRF51NVMState { uint32_t config; -} NRF51NVMState; +}; #endif diff --git a/include/hw/or-irq.h b/include/hw/or-irq.h index 0038bfbe3d643bee26837500a42fd9d02b9140e1..f2f0a27381065df9ce69bf3d785a7dace608eeac 100644 --- a/include/hw/or-irq.h +++ b/include/hw/or-irq.h @@ -37,7 +37,8 @@ typedef struct OrIRQState qemu_or_irq; -#define OR_IRQ(obj) OBJECT_CHECK(qemu_or_irq, (obj), TYPE_OR_IRQ) +DECLARE_INSTANCE_CHECKER(qemu_or_irq, OR_IRQ, + TYPE_OR_IRQ) struct OrIRQState { DeviceState parent_obj; diff --git a/include/hw/pci-bridge/simba.h b/include/hw/pci-bridge/simba.h index d8649973ee17936226f52f7388ccde46c41325b8..979cb17435d04e3c024237c25e326a703dfaaae8 100644 --- a/include/hw/pci-bridge/simba.h +++ b/include/hw/pci-bridge/simba.h @@ -28,15 +28,15 @@ #define HW_PCI_BRIDGE_SIMBA_H #include "hw/pci/pci_bridge.h" +#include "qom/object.h" -typedef struct SimbaPCIBridge { +struct SimbaPCIBridge { /*< private >*/ PCIBridge parent_obj; -} SimbaPCIBridge; +}; #define TYPE_SIMBA_PCI_BRIDGE "pbm-bridge" -#define SIMBA_PCI_BRIDGE(obj) \ - OBJECT_CHECK(SimbaPCIBridge, (obj), TYPE_SIMBA_PCI_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(SimbaPCIBridge, SIMBA_PCI_BRIDGE) #endif diff --git a/include/hw/pci-host/designware.h b/include/hw/pci-host/designware.h index 31c41231b14e704868c8fb5173a6fdbed8e678d0..6d9b51ae67cd9bf52c2338842955eaf2f349dedf 100644 --- a/include/hw/pci-host/designware.h +++ b/include/hw/pci-host/designware.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -26,17 +26,15 @@ #include "hw/pci/pci_bus.h" #include "hw/pci/pcie_host.h" #include "hw/pci/pci_bridge.h" +#include "qom/object.h" #define TYPE_DESIGNWARE_PCIE_HOST "designware-pcie-host" -#define DESIGNWARE_PCIE_HOST(obj) \ - OBJECT_CHECK(DesignwarePCIEHost, (obj), TYPE_DESIGNWARE_PCIE_HOST) +OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIEHost, DESIGNWARE_PCIE_HOST) #define TYPE_DESIGNWARE_PCIE_ROOT "designware-pcie-root" -#define DESIGNWARE_PCIE_ROOT(obj) \ - OBJECT_CHECK(DesignwarePCIERoot, (obj), TYPE_DESIGNWARE_PCIE_ROOT) +OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIERoot, DESIGNWARE_PCIE_ROOT) struct DesignwarePCIERoot; -typedef struct DesignwarePCIERoot DesignwarePCIERoot; typedef struct DesignwarePCIEViewport { DesignwarePCIERoot *root; @@ -80,7 +78,7 @@ struct DesignwarePCIERoot { DesignwarePCIEMSI msi; }; -typedef struct DesignwarePCIEHost { +struct DesignwarePCIEHost { PCIHostState parent_obj; DesignwarePCIERoot root; @@ -96,6 +94,6 @@ typedef struct DesignwarePCIEHost { } pci; MemoryRegion mmio; -} DesignwarePCIEHost; +}; #endif /* DESIGNWARE_H */ diff --git a/include/hw/pci-host/gpex.h b/include/hw/pci-host/gpex.h index faea040a9347f6e2ee7db9295070b0e0c6b906a4..d52ea80d4e04b2c60050c62055c246441a5ab1c3 100644 --- a/include/hw/pci-host/gpex.h +++ b/include/hw/pci-host/gpex.h @@ -20,27 +20,27 @@ #ifndef HW_GPEX_H #define HW_GPEX_H +#include "exec/hwaddr.h" #include "hw/sysbus.h" #include "hw/pci/pci.h" #include "hw/pci/pcie_host.h" +#include "qom/object.h" #define TYPE_GPEX_HOST "gpex-pcihost" -#define GPEX_HOST(obj) \ - OBJECT_CHECK(GPEXHost, (obj), TYPE_GPEX_HOST) +OBJECT_DECLARE_SIMPLE_TYPE(GPEXHost, GPEX_HOST) #define TYPE_GPEX_ROOT_DEVICE "gpex-root" -#define MCH_PCI_DEVICE(obj) \ - OBJECT_CHECK(GPEXRootState, (obj), TYPE_GPEX_ROOT_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(GPEXRootState, GPEX_ROOT_DEVICE) #define GPEX_NUM_IRQS 4 -typedef struct GPEXRootState { +struct GPEXRootState { /*< private >*/ PCIDevice parent_obj; /*< public >*/ -} GPEXRootState; +}; -typedef struct GPEXHost { +struct GPEXHost { /*< private >*/ PCIExpressHost parent_obj; /*< public >*/ @@ -51,8 +51,18 @@ typedef struct GPEXHost { MemoryRegion io_mmio; qemu_irq irq[GPEX_NUM_IRQS]; int irq_num[GPEX_NUM_IRQS]; -} GPEXHost; +}; + +struct GPEXConfig { + MemMapEntry ecam; + MemMapEntry mmio32; + MemMapEntry mmio64; + MemMapEntry pio; + int irq; +}; int gpex_set_irq_num(GPEXHost *s, int index, int gsi); +void acpi_dsdt_add_gpex(Aml *scope, struct GPEXConfig *cfg); + #endif /* HW_GPEX_H */ diff --git a/include/hw/pci-host/i440fx.h b/include/hw/pci-host/i440fx.h index cc58d82ed475a4ed80e909102ae275fd50813bf8..6c16eaf876dd29c49b6c2a98aa155a12656611af 100644 --- a/include/hw/pci-host/i440fx.h +++ b/include/hw/pci-host/i440fx.h @@ -14,14 +14,14 @@ #include "hw/hw.h" #include "hw/pci/pci_bus.h" #include "hw/pci-host/pam.h" +#include "qom/object.h" #define TYPE_I440FX_PCI_HOST_BRIDGE "i440FX-pcihost" #define TYPE_I440FX_PCI_DEVICE "i440FX" -#define I440FX_PCI_DEVICE(obj) \ - OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(PCII440FXState, I440FX_PCI_DEVICE) -typedef struct PCII440FXState { +struct PCII440FXState { /*< private >*/ PCIDevice parent_obj; /*< public >*/ @@ -32,7 +32,7 @@ typedef struct PCII440FXState { PAMMemoryRegion pam_regions[13]; MemoryRegion smram_region; MemoryRegion smram, low_smram; -} PCII440FXState; +}; #define TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE "igd-passthrough-i440FX" diff --git a/include/hw/pci-host/pnv_phb3.h b/include/hw/pci-host/pnv_phb3.h index 75b787867a57f6696743c71411865bf071347b96..e2a2e3624532d5db52ea61a1261a5710cc19626f 100644 --- a/include/hw/pci-host/pnv_phb3.h +++ b/include/hw/pci-host/pnv_phb3.h @@ -13,6 +13,7 @@ #include "hw/pci/pcie_host.h" #include "hw/pci/pcie_port.h" #include "hw/ppc/xics.h" +#include "qom/object.h" typedef struct PnvPHB3 PnvPHB3; @@ -20,18 +21,20 @@ typedef struct PnvPHB3 PnvPHB3; * PHB3 XICS Source for MSIs */ #define TYPE_PHB3_MSI "phb3-msi" -#define PHB3_MSI(obj) OBJECT_CHECK(Phb3MsiState, (obj), TYPE_PHB3_MSI) +typedef struct Phb3MsiState Phb3MsiState; +DECLARE_INSTANCE_CHECKER(Phb3MsiState, PHB3_MSI, + TYPE_PHB3_MSI) #define PHB3_MAX_MSI 2048 -typedef struct Phb3MsiState { +struct Phb3MsiState { ICSState ics; qemu_irq *qirqs; PnvPHB3 *phb; uint64_t rba[PHB3_MAX_MSI / 64]; uint32_t rba_sum; -} Phb3MsiState; +}; void pnv_phb3_msi_update_config(Phb3MsiState *msis, uint32_t base, uint32_t count); @@ -69,9 +72,9 @@ typedef struct PnvPhb3DMASpace { * PHB3 Power Bus Common Queue */ #define TYPE_PNV_PBCQ "pnv-pbcq" -#define PNV_PBCQ(obj) OBJECT_CHECK(PnvPBCQState, (obj), TYPE_PNV_PBCQ) +OBJECT_DECLARE_SIMPLE_TYPE(PnvPBCQState, PNV_PBCQ) -typedef struct PnvPBCQState { +struct PnvPBCQState { DeviceState parent; uint32_t nest_xbase; @@ -96,7 +99,7 @@ typedef struct PnvPBCQState { MemoryRegion xscom_nest_regs; MemoryRegion xscom_pci_regs; MemoryRegion xscom_spci_regs; -} PnvPBCQState; +}; /* * PHB3 PCIe Root port @@ -113,7 +116,7 @@ typedef struct PnvPHB3RootPort { * PHB3 PCIe Host Bridge for PowerNV machines (POWER8) */ #define TYPE_PNV_PHB3 "pnv-phb3" -#define PNV_PHB3(obj) OBJECT_CHECK(PnvPHB3, (obj), TYPE_PNV_PHB3) +OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB3, PNV_PHB3) #define PNV_PHB3_NUM_M64 16 #define PNV_PHB3_NUM_REGS (0x1000 >> 3) diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index c882bfd0aa231a9764a1f74f145daf84feee5543..27556ae5342574859929f288c164736676c7c51d 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -13,8 +13,8 @@ #include "hw/pci/pcie_host.h" #include "hw/pci/pcie_port.h" #include "hw/ppc/xive.h" +#include "qom/object.h" -typedef struct PnvPhb4PecState PnvPhb4PecState; typedef struct PnvPhb4PecStack PnvPhb4PecStack; typedef struct PnvPHB4 PnvPHB4; typedef struct PnvChip PnvChip; @@ -57,7 +57,7 @@ typedef struct PnvPHB4RootPort { * PHB4 PCIe Host Bridge for PowerNV machines (POWER9) */ #define TYPE_PNV_PHB4 "pnv-phb4" -#define PNV_PHB4(obj) OBJECT_CHECK(PnvPHB4, (obj), TYPE_PNV_PHB4) +OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4, PNV_PHB4) #define PNV_PHB4_MAX_LSIs 8 #define PNV_PHB4_MAX_INTs 4096 @@ -140,12 +140,10 @@ extern const MemoryRegionOps pnv_phb4_xscom_ops; * PHB4 PEC (PCI Express Controller) */ #define TYPE_PNV_PHB4_PEC "pnv-phb4-pec" -#define PNV_PHB4_PEC(obj) \ - OBJECT_CHECK(PnvPhb4PecState, (obj), TYPE_PNV_PHB4_PEC) +OBJECT_DECLARE_TYPE(PnvPhb4PecState, PnvPhb4PecClass, PNV_PHB4_PEC) #define TYPE_PNV_PHB4_PEC_STACK "pnv-phb4-pec-stack" -#define PNV_PHB4_PEC_STACK(obj) \ - OBJECT_CHECK(PnvPhb4PecStack, (obj), TYPE_PNV_PHB4_PEC_STACK) +OBJECT_DECLARE_SIMPLE_TYPE(PnvPhb4PecStack, PNV_PHB4_PEC_STACK) /* Per-stack data */ struct PnvPhb4PecStack { @@ -209,12 +207,8 @@ struct PnvPhb4PecState { PnvPhb4PecStack stacks[PHB4_PEC_MAX_STACKS]; }; -#define PNV_PHB4_PEC_CLASS(klass) \ - OBJECT_CLASS_CHECK(PnvPhb4PecClass, (klass), TYPE_PNV_PHB4_PEC) -#define PNV_PHB4_PEC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PnvPhb4PecClass, (obj), TYPE_PNV_PHB4_PEC) -typedef struct PnvPhb4PecClass { +struct PnvPhb4PecClass { DeviceClass parent_class; uint32_t (*xscom_nest_base)(PnvPhb4PecState *pec); @@ -225,6 +219,6 @@ typedef struct PnvPhb4PecClass { int compat_size; const char *stk_compat; int stk_compat_size; -} PnvPhb4PecClass; +}; #endif /* PCI_HOST_PNV_PHB4_H */ diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h index 070305f83dfd9dca2f15934ba094299b6d8c2563..bbb958176565d5898aeaa11f4e2fd84da3aa56ca 100644 --- a/include/hw/pci-host/q35.h +++ b/include/hw/pci-host/q35.h @@ -27,16 +27,15 @@ #include "hw/pci-host/pam.h" #include "qemu/units.h" #include "qemu/range.h" +#include "qom/object.h" #define TYPE_Q35_HOST_DEVICE "q35-pcihost" -#define Q35_HOST_DEVICE(obj) \ - OBJECT_CHECK(Q35PCIHost, (obj), TYPE_Q35_HOST_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(Q35PCIHost, Q35_HOST_DEVICE) #define TYPE_MCH_PCI_DEVICE "mch" -#define MCH_PCI_DEVICE(obj) \ - OBJECT_CHECK(MCHPCIState, (obj), TYPE_MCH_PCI_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(MCHPCIState, MCH_PCI_DEVICE) -typedef struct MCHPCIState { +struct MCHPCIState { /*< private >*/ PCIDevice parent_obj; /*< public >*/ @@ -57,16 +56,16 @@ typedef struct MCHPCIState { uint64_t pci_hole64_size; uint32_t short_root_bus; uint16_t ext_tseg_mbytes; -} MCHPCIState; +}; -typedef struct Q35PCIHost { +struct Q35PCIHost { /*< private >*/ PCIExpressHost parent_obj; /*< public >*/ bool pci_hole64_fix; MCHPCIState mch; -} Q35PCIHost; +}; #define Q35_MASK(bit, ms_bit, ls_bit) \ ((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1))) diff --git a/include/hw/pci-host/sabre.h b/include/hw/pci-host/sabre.h index 99b5aefbecdda2dd170ac2bfdb0a62c220a05456..01190241bbdefc310ce2ea3a65171fd4f18e0d4d 100644 --- a/include/hw/pci-host/sabre.h +++ b/include/hw/pci-host/sabre.h @@ -4,6 +4,7 @@ #include "hw/pci/pci.h" #include "hw/pci/pci_host.h" #include "hw/sparc/sun4u_iommu.h" +#include "qom/object.h" #define MAX_IVEC 0x40 @@ -16,15 +17,14 @@ #define OBIO_MSE_IRQ 0x2a #define OBIO_SER_IRQ 0x2b -typedef struct SabrePCIState { +struct SabrePCIState { PCIDevice parent_obj; -} SabrePCIState; +}; #define TYPE_SABRE_PCI_DEVICE "sabre-pci" -#define SABRE_PCI_DEVICE(obj) \ - OBJECT_CHECK(SabrePCIState, (obj), TYPE_SABRE_PCI_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(SabrePCIState, SABRE_PCI_DEVICE) -typedef struct SabreState { +struct SabreState { PCIHostState parent_obj; hwaddr special_base; @@ -45,10 +45,9 @@ typedef struct SabreState { unsigned int irq_request; uint32_t reset_control; unsigned int nr_resets; -} SabreState; +}; #define TYPE_SABRE "sabre" -#define SABRE_DEVICE(obj) \ - OBJECT_CHECK(SabreState, (obj), TYPE_SABRE) +OBJECT_DECLARE_SIMPLE_TYPE(SabreState, SABRE) #endif diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h index 8877ff51fbf7e6fdb383dfcc09ac786485f0c695..4f58f0223b56c8f4aac9bdccf80dfb303a7c4a7f 100644 --- a/include/hw/pci-host/spapr.h +++ b/include/hw/pci-host/spapr.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -24,15 +24,14 @@ #include "hw/pci/pci.h" #include "hw/pci/pci_host.h" #include "hw/ppc/xics.h" +#include "qom/object.h" #define TYPE_SPAPR_PCI_HOST_BRIDGE "spapr-pci-host-bridge" -#define SPAPR_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(SpaprPhbState, (obj), TYPE_SPAPR_PCI_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(SpaprPhbState, SPAPR_PCI_HOST_BRIDGE) #define SPAPR_PCI_DMA_MAX_WINDOWS 2 -typedef struct SpaprPhbState SpaprPhbState; typedef struct SpaprPciMsi { uint32_t first_irq; @@ -94,6 +93,7 @@ struct SpaprPhbState { hwaddr nv2_gpa_win_addr; hwaddr nv2_atsd_win_addr; SpaprPhbPciNvGpuConfig *nvgpus; + bool pre_5_1_assoc; }; #define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL diff --git a/include/hw/pci-host/uninorth.h b/include/hw/pci-host/uninorth.h index 72d2a97355195f35690388c3d5de1ad5ae754949..62bd81e72106f06833ae6d70853692109aa84811 100644 --- a/include/hw/pci-host/uninorth.h +++ b/include/hw/pci-host/uninorth.h @@ -26,7 +26,7 @@ #define UNINORTH_H #include "hw/pci/pci_host.h" -#include "hw/ppc/openpic.h" +#include "qom/object.h" /* UniNorth version */ #define UNINORTH_VERSION_10A 0x7 @@ -36,34 +36,33 @@ #define TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE "uni-north-internal-pci-pcihost" #define TYPE_U3_AGP_HOST_BRIDGE "u3-agp-pcihost" -#define UNI_NORTH_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(UNINHostState, (obj), TYPE_UNI_NORTH_PCI_HOST_BRIDGE) -#define UNI_NORTH_AGP_HOST_BRIDGE(obj) \ - OBJECT_CHECK(UNINHostState, (obj), TYPE_UNI_NORTH_AGP_HOST_BRIDGE) -#define UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(UNINHostState, (obj), TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE) -#define U3_AGP_HOST_BRIDGE(obj) \ - OBJECT_CHECK(UNINHostState, (obj), TYPE_U3_AGP_HOST_BRIDGE) +typedef struct UNINHostState UNINHostState; +DECLARE_INSTANCE_CHECKER(UNINHostState, UNI_NORTH_PCI_HOST_BRIDGE, + TYPE_UNI_NORTH_PCI_HOST_BRIDGE) +DECLARE_INSTANCE_CHECKER(UNINHostState, UNI_NORTH_AGP_HOST_BRIDGE, + TYPE_UNI_NORTH_AGP_HOST_BRIDGE) +DECLARE_INSTANCE_CHECKER(UNINHostState, UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE, + TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE) +DECLARE_INSTANCE_CHECKER(UNINHostState, U3_AGP_HOST_BRIDGE, + TYPE_U3_AGP_HOST_BRIDGE) -typedef struct UNINHostState { +struct UNINHostState { PCIHostState parent_obj; uint32_t ofw_addr; - OpenPICState *pic; qemu_irq irqs[4]; MemoryRegion pci_mmio; MemoryRegion pci_hole; MemoryRegion pci_io; -} UNINHostState; +}; -typedef struct UNINState { +struct UNINState { SysBusDevice parent_obj; MemoryRegion mem; -} UNINState; +}; #define TYPE_UNI_NORTH "uni-north" -#define UNI_NORTH(obj) \ - OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH) +OBJECT_DECLARE_SIMPLE_TYPE(UNINState, UNI_NORTH) #endif /* UNINORTH_H */ diff --git a/include/hw/pci-host/xilinx-pcie.h b/include/hw/pci-host/xilinx-pcie.h index c0f15314be2b73b22a106ce082d56fc4a4ec779e..89be88d87fdd5328527c5e1583dec59baa892d86 100644 --- a/include/hw/pci-host/xilinx-pcie.h +++ b/include/hw/pci-host/xilinx-pcie.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -24,25 +24,24 @@ #include "hw/pci/pci.h" #include "hw/pci/pci_bridge.h" #include "hw/pci/pcie_host.h" +#include "qom/object.h" #define TYPE_XILINX_PCIE_HOST "xilinx-pcie-host" -#define XILINX_PCIE_HOST(obj) \ - OBJECT_CHECK(XilinxPCIEHost, (obj), TYPE_XILINX_PCIE_HOST) +OBJECT_DECLARE_SIMPLE_TYPE(XilinxPCIEHost, XILINX_PCIE_HOST) #define TYPE_XILINX_PCIE_ROOT "xilinx-pcie-root" -#define XILINX_PCIE_ROOT(obj) \ - OBJECT_CHECK(XilinxPCIERoot, (obj), TYPE_XILINX_PCIE_ROOT) +OBJECT_DECLARE_SIMPLE_TYPE(XilinxPCIERoot, XILINX_PCIE_ROOT) -typedef struct XilinxPCIERoot { +struct XilinxPCIERoot { PCIBridge parent_obj; -} XilinxPCIERoot; +}; typedef struct XilinxPCIEInt { uint32_t fifo_reg1; uint32_t fifo_reg2; } XilinxPCIEInt; -typedef struct XilinxPCIEHost { +struct XilinxPCIEHost { PCIExpressHost parent_obj; char name[16]; @@ -62,6 +61,6 @@ typedef struct XilinxPCIEHost { XilinxPCIEInt intr_fifo[16]; unsigned int intr_fifo_r, intr_fifo_w; uint32_t rpscr; -} XilinxPCIEHost; +}; #endif /* HW_XILINX_PCIE_H */ diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index cfedf5a995d76362548924d5692234508aa2a970..72ce649eee3604c003dc6dab2d2e728aac93e7f7 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -8,6 +8,7 @@ #include "hw/isa/isa.h" #include "hw/pci/pcie.h" +#include "qom/object.h" extern bool pci_available; @@ -87,6 +88,7 @@ extern bool pci_available; #define PCI_DEVICE_ID_VIRTIO_VSOCK 0x1012 #define PCI_DEVICE_ID_VIRTIO_PMEM 0x1013 #define PCI_DEVICE_ID_VIRTIO_IOMMU 0x1014 +#define PCI_DEVICE_ID_VIRTIO_MEM 0x1015 #define PCI_VENDOR_ID_REDHAT 0x1b36 #define PCI_DEVICE_ID_REDHAT_BRIDGE 0x0001 @@ -104,6 +106,7 @@ extern bool pci_available; #define PCI_DEVICE_ID_REDHAT_XHCI 0x000d #define PCI_DEVICE_ID_REDHAT_PCIE_BRIDGE 0x000e #define PCI_DEVICE_ID_REDHAT_MDPY 0x000f +#define PCI_DEVICE_ID_REDHAT_NVME 0x0010 #define PCI_DEVICE_ID_REDHAT_QXL 0x0100 #define FMT_PCIBUS PRIx64 @@ -194,12 +197,9 @@ enum { }; #define TYPE_PCI_DEVICE "pci-device" -#define PCI_DEVICE(obj) \ - OBJECT_CHECK(PCIDevice, (obj), TYPE_PCI_DEVICE) -#define PCI_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(PCIDeviceClass, (klass), TYPE_PCI_DEVICE) -#define PCI_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE) +typedef struct PCIDeviceClass PCIDeviceClass; +DECLARE_OBJ_CHECKERS(PCIDevice, PCIDeviceClass, + PCI_DEVICE, TYPE_PCI_DEVICE) /* Implemented by devices that can be plugged on PCI Express buses */ #define INTERFACE_PCIE_DEVICE "pci-express-device" @@ -216,7 +216,7 @@ typedef struct PCIINTxRoute { int irq; } PCIINTxRoute; -typedef struct PCIDeviceClass { +struct PCIDeviceClass { DeviceClass parent_class; void (*realize)(PCIDevice *dev, Error **errp); @@ -240,7 +240,7 @@ typedef struct PCIDeviceClass { /* rom bar */ const char *romfile; -} PCIDeviceClass; +}; typedef void (*PCIINTxRoutingNotifier)(PCIDevice *dev); typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector, @@ -395,9 +395,7 @@ typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num); typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin); #define TYPE_PCI_BUS "PCI" -#define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS) -#define PCI_BUS_CLASS(klass) OBJECT_CLASS_CHECK(PCIBusClass, (klass), TYPE_PCI_BUS) -#define PCI_BUS_GET_CLASS(obj) OBJECT_GET_CLASS(PCIBusClass, (obj), TYPE_PCI_BUS) +OBJECT_DECLARE_TYPE(PCIBus, PCIBusClass, PCI_BUS) #define TYPE_PCIE_BUS "PCIE" bool pci_bus_is_express(PCIBus *bus); @@ -712,12 +710,14 @@ pci_get_quad_by_mask(uint8_t *config, uint64_t mask) return (val & mask) >> ctz32(mask); } -PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction, +PCIDevice *pci_new_multifunction(int devfn, bool multifunction, const char *name); +PCIDevice *pci_new(int devfn, const char *name); +bool pci_realize_and_unref(PCIDevice *dev, PCIBus *bus, Error **errp); + PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn, bool multifunction, const char *name); -PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name); PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name); void lsi53c8xx_handle_legacy_cmdline(DeviceState *lsi_dev); @@ -784,8 +784,7 @@ static inline AddressSpace *pci_get_address_space(PCIDevice *dev) static inline int pci_dma_rw(PCIDevice *dev, dma_addr_t addr, void *buf, dma_addr_t len, DMADirection dir) { - dma_memory_rw(pci_get_address_space(dev), addr, buf, len, dir); - return 0; + return dma_memory_rw(pci_get_address_space(dev), addr, buf, len, dir); } static inline int pci_dma_read(PCIDevice *dev, dma_addr_t addr, diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h index 99c674e949544885b14bed5eefdc6b959287ec66..a94d350034bfad910adfaa157ca2f2dc5067fdd6 100644 --- a/include/hw/pci/pci_bridge.h +++ b/include/hw/pci/pci_bridge.h @@ -28,6 +28,7 @@ #include "hw/pci/pci.h" #include "hw/pci/pci_bus.h" +#include "qom/object.h" typedef struct PCIBridgeWindows PCIBridgeWindows; @@ -50,7 +51,7 @@ struct PCIBridgeWindows { }; #define TYPE_PCI_BRIDGE "base-pci-bridge" -#define PCI_BRIDGE(obj) OBJECT_CHECK(PCIBridge, (obj), TYPE_PCI_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(PCIBridge, PCI_BRIDGE) struct PCIBridge { /*< private >*/ diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h index 0714f578afe6c0e581223e0c0d01cb6b887859ff..347440d42ca19b3bffbc62126e60bc60c986c222 100644 --- a/include/hw/pci/pci_bus.h +++ b/include/hw/pci/pci_bus.h @@ -10,14 +10,14 @@ * use accessor functions in pci.h */ -typedef struct PCIBusClass { +struct PCIBusClass { /*< private >*/ BusClass parent_class; /*< public >*/ int (*bus_num)(PCIBus *bus); uint16_t (*numa_node)(PCIBus *bus); -} PCIBusClass; +}; enum PCIBusFlags { /* This bus is the root of a PCI domain */ diff --git a/include/hw/pci/pci_host.h b/include/hw/pci/pci_host.h index 9ce088bd135463e995d31a7851c59798a9b5ba54..52e038c0196fd6dcc5f5dc115a268e9796ebcdcf 100644 --- a/include/hw/pci/pci_host.h +++ b/include/hw/pci/pci_host.h @@ -29,14 +29,10 @@ #define PCI_HOST_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_PCI_HOST_BRIDGE "pci-host-bridge" -#define PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(PCIHostState, (obj), TYPE_PCI_HOST_BRIDGE) -#define PCI_HOST_BRIDGE_CLASS(klass) \ - OBJECT_CLASS_CHECK(PCIHostBridgeClass, (klass), TYPE_PCI_HOST_BRIDGE) -#define PCI_HOST_BRIDGE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PCIHostBridgeClass, (obj), TYPE_PCI_HOST_BRIDGE) +OBJECT_DECLARE_TYPE(PCIHostState, PCIHostBridgeClass, PCI_HOST_BRIDGE) struct PCIHostState { SysBusDevice busdev; @@ -45,16 +41,17 @@ struct PCIHostState { MemoryRegion data_mem; MemoryRegion mmcfg; uint32_t config_reg; + bool mig_enabled; PCIBus *bus; QLIST_ENTRY(PCIHostState) next; }; -typedef struct PCIHostBridgeClass { +struct PCIHostBridgeClass { SysBusDeviceClass parent_class; const char *(*root_bus_path)(PCIHostState *, PCIBus *); -} PCIHostBridgeClass; +}; /* common internal helpers for PCI/PCIe hosts, cut off overflows */ void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr, diff --git a/include/hw/pci/pcie_host.h b/include/hw/pci/pcie_host.h index 3f7b9886d14dd2629caa0f0d318a73aa596ccfdd..076457b270e2eba6d2f70cfe844da1b1398f6475 100644 --- a/include/hw/pci/pcie_host.h +++ b/include/hw/pci/pcie_host.h @@ -23,10 +23,10 @@ #include "hw/pci/pci_host.h" #include "exec/memory.h" +#include "qom/object.h" #define TYPE_PCIE_HOST_BRIDGE "pcie-host-bridge" -#define PCIE_HOST_BRIDGE(obj) \ - OBJECT_CHECK(PCIExpressHost, (obj), TYPE_PCIE_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(PCIExpressHost, PCIE_HOST_BRIDGE) #define PCIE_HOST_MCFG_BASE "MCFG" #define PCIE_HOST_MCFG_SIZE "mcfg_size" diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h index caae57573bf688fcbf2f7e6e033f1de8360cbf27..bea8ecad0fdb044111094fb269b983c46b547622 100644 --- a/include/hw/pci/pcie_port.h +++ b/include/hw/pci/pcie_port.h @@ -23,9 +23,10 @@ #include "hw/pci/pci_bridge.h" #include "hw/pci/pci_bus.h" +#include "qom/object.h" #define TYPE_PCIE_PORT "pcie-port" -#define PCIE_PORT(obj) OBJECT_CHECK(PCIEPort, (obj), TYPE_PCIE_PORT) +OBJECT_DECLARE_SIMPLE_TYPE(PCIEPort, PCIE_PORT) struct PCIEPort { /*< private >*/ @@ -39,7 +40,7 @@ struct PCIEPort { void pcie_port_init_reg(PCIDevice *d); #define TYPE_PCIE_SLOT "pcie-slot" -#define PCIE_SLOT(obj) OBJECT_CHECK(PCIESlot, (obj), TYPE_PCIE_SLOT) +OBJECT_DECLARE_SIMPLE_TYPE(PCIESlot, PCIE_SLOT) struct PCIESlot { /*< private >*/ @@ -67,12 +68,11 @@ int pcie_chassis_add_slot(struct PCIESlot *slot); void pcie_chassis_del_slot(PCIESlot *s); #define TYPE_PCIE_ROOT_PORT "pcie-root-port-base" -#define PCIE_ROOT_PORT_CLASS(klass) \ - OBJECT_CLASS_CHECK(PCIERootPortClass, (klass), TYPE_PCIE_ROOT_PORT) -#define PCIE_ROOT_PORT_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PCIERootPortClass, (obj), TYPE_PCIE_ROOT_PORT) +typedef struct PCIERootPortClass PCIERootPortClass; +DECLARE_CLASS_CHECKERS(PCIERootPortClass, PCIE_ROOT_PORT, + TYPE_PCIE_ROOT_PORT) -typedef struct PCIERootPortClass { +struct PCIERootPortClass { PCIDeviceClass parent_class; DeviceRealize parent_realize; DeviceReset parent_reset; @@ -86,6 +86,6 @@ typedef struct PCIERootPortClass { int ssvid_offset; int acs_offset; /* If nonzero, optional ACS capability offset */ int ssid; -} PCIERootPortClass; +}; #endif /* QEMU_PCIE_PORT_H */ diff --git a/include/hw/pcmcia.h b/include/hw/pcmcia.h index ebad7bc5040d01df51f26ef5d08b0c7cae0279f3..e3ba44e0bf69f9a1a8124f7c26df7c50fba957e8 100644 --- a/include/hw/pcmcia.h +++ b/include/hw/pcmcia.h @@ -4,6 +4,7 @@ /* PCMCIA/Cardbus */ #include "hw/qdev-core.h" +#include "qom/object.h" typedef struct PCMCIASocket { qemu_irq irq; @@ -11,22 +12,17 @@ typedef struct PCMCIASocket { } PCMCIASocket; #define TYPE_PCMCIA_CARD "pcmcia-card" -#define PCMCIA_CARD(obj) \ - OBJECT_CHECK(PCMCIACardState, (obj), TYPE_PCMCIA_CARD) -#define PCMCIA_CARD_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PCMCIACardClass, obj, TYPE_PCMCIA_CARD) -#define PCMCIA_CARD_CLASS(cls) \ - OBJECT_CLASS_CHECK(PCMCIACardClass, cls, TYPE_PCMCIA_CARD) +OBJECT_DECLARE_TYPE(PCMCIACardState, PCMCIACardClass, PCMCIA_CARD) -typedef struct PCMCIACardState { +struct PCMCIACardState { /*< private >*/ DeviceState parent_obj; /*< public >*/ PCMCIASocket *slot; -} PCMCIACardState; +}; -typedef struct PCMCIACardClass { +struct PCMCIACardClass { /*< private >*/ DeviceClass parent_class; /*< public >*/ @@ -45,7 +41,7 @@ typedef struct PCMCIACardClass { uint32_t address, uint16_t value); uint16_t (*io_read)(PCMCIACardState *card, uint32_t address); void (*io_write)(PCMCIACardState *card, uint32_t address, uint16_t value); -} PCMCIACardClass; +}; #define CISTPL_DEVICE 0x01 /* 5V Device Information Tuple */ #define CISTPL_NO_LINK 0x14 /* No Link Tuple */ diff --git a/include/hw/platform-bus.h b/include/hw/platform-bus.h index 19e20c57ce77871bdebb862e6ff303eabd739bc2..44f30c5353f792cdc77a6eb59a999b9758fedbf7 100644 --- a/include/hw/platform-bus.h +++ b/include/hw/platform-bus.h @@ -11,7 +11,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -23,16 +23,11 @@ */ #include "hw/sysbus.h" +#include "qom/object.h" -typedef struct PlatformBusDevice PlatformBusDevice; #define TYPE_PLATFORM_BUS_DEVICE "platform-bus-device" -#define PLATFORM_BUS_DEVICE(obj) \ - OBJECT_CHECK(PlatformBusDevice, (obj), TYPE_PLATFORM_BUS_DEVICE) -#define PLATFORM_BUS_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(PlatformBusDeviceClass, (klass), TYPE_PLATFORM_BUS_DEVICE) -#define PLATFORM_BUS_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PlatformBusDeviceClass, (obj), TYPE_PLATFORM_BUS_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(PlatformBusDevice, PLATFORM_BUS_DEVICE) struct PlatformBusDevice { /*< private >*/ diff --git a/include/hw/ppc/mac_dbdma.h b/include/hw/ppc/mac_dbdma.h index 26cc469de483a9632946912bd722ec79441ccd63..4a3f644516b3bbbb12d5b8b42d9b1b078d68e051 100644 --- a/include/hw/ppc/mac_dbdma.h +++ b/include/hw/ppc/mac_dbdma.h @@ -27,6 +27,7 @@ #include "qemu/iov.h" #include "sysemu/dma.h" #include "hw/sysbus.h" +#include "qom/object.h" typedef struct DBDMA_io DBDMA_io; @@ -160,13 +161,14 @@ typedef struct DBDMA_channel { dbdma_cmd current; } DBDMA_channel; -typedef struct { +struct DBDMAState { SysBusDevice parent_obj; MemoryRegion mem; DBDMA_channel channels[DBDMA_CHANNELS]; QEMUBH *bh; -} DBDMAState; +}; +typedef struct DBDMAState DBDMAState; /* Externally callable functions */ @@ -176,6 +178,6 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, void DBDMA_kick(DBDMAState *dbdma); #define TYPE_MAC_DBDMA "mac-dbdma" -#define MAC_DBDMA(obj) OBJECT_CHECK(DBDMAState, (obj), TYPE_MAC_DBDMA) +OBJECT_DECLARE_SIMPLE_TYPE(DBDMAState, MAC_DBDMA) #endif diff --git a/include/hw/ppc/openpic.h b/include/hw/ppc/openpic.h index db0d29e6c289c9522024e83f57aa6699efe0a66a..74ff44bff0a9d9bb4fb3435ab8068294b64e5511 100644 --- a/include/hw/ppc/openpic.h +++ b/include/hw/ppc/openpic.h @@ -3,6 +3,7 @@ #include "hw/sysbus.h" #include "hw/core/cpu.h" +#include "qom/object.h" #define MAX_CPU 32 #define MAX_MSI 8 @@ -136,9 +137,9 @@ typedef struct IRQDest { } IRQDest; #define TYPE_OPENPIC "openpic" -#define OPENPIC(obj) OBJECT_CHECK(OpenPICState, (obj), TYPE_OPENPIC) +OBJECT_DECLARE_SIMPLE_TYPE(OpenPICState, OPENPIC) -typedef struct OpenPICState { +struct OpenPICState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -183,6 +184,6 @@ typedef struct OpenPICState { uint32_t irq_ipi0; uint32_t irq_tim0; uint32_t irq_msi; -} OpenPICState; +}; #endif /* OPENPIC_H */ diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index d4b0b0e2ff7173ba5dd5e17d9c2a3b8bd75d21d4..ee7eda3e0102308ea729d58715cff88ce8772083 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -32,15 +32,13 @@ #include "hw/ppc/pnv_core.h" #include "hw/pci-host/pnv_phb3.h" #include "hw/pci-host/pnv_phb4.h" +#include "qom/object.h" #define TYPE_PNV_CHIP "pnv-chip" -#define PNV_CHIP(obj) OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP) -#define PNV_CHIP_CLASS(klass) \ - OBJECT_CLASS_CHECK(PnvChipClass, (klass), TYPE_PNV_CHIP) -#define PNV_CHIP_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PnvChipClass, (obj), TYPE_PNV_CHIP) +OBJECT_DECLARE_TYPE(PnvChip, PnvChipClass, + PNV_CHIP) -typedef struct PnvChip { +struct PnvChip { /*< private >*/ SysBusDevice parent_obj; @@ -61,12 +59,14 @@ typedef struct PnvChip { AddressSpace xscom_as; gchar *dt_isa_nodename; -} PnvChip; +}; #define TYPE_PNV8_CHIP "pnv8-chip" -#define PNV8_CHIP(obj) OBJECT_CHECK(Pnv8Chip, (obj), TYPE_PNV8_CHIP) +typedef struct Pnv8Chip Pnv8Chip; +DECLARE_INSTANCE_CHECKER(Pnv8Chip, PNV8_CHIP, + TYPE_PNV8_CHIP) -typedef struct Pnv8Chip { +struct Pnv8Chip { /*< private >*/ PnvChip parent_obj; @@ -82,12 +82,14 @@ typedef struct Pnv8Chip { PnvPHB3 phbs[PNV8_CHIP_PHB3_MAX]; XICSFabric *xics; -} Pnv8Chip; +}; #define TYPE_PNV9_CHIP "pnv9-chip" -#define PNV9_CHIP(obj) OBJECT_CHECK(Pnv9Chip, (obj), TYPE_PNV9_CHIP) +typedef struct Pnv9Chip Pnv9Chip; +DECLARE_INSTANCE_CHECKER(Pnv9Chip, PNV9_CHIP, + TYPE_PNV9_CHIP) -typedef struct Pnv9Chip { +struct Pnv9Chip { /*< private >*/ PnvChip parent_obj; @@ -103,7 +105,7 @@ typedef struct Pnv9Chip { #define PNV9_CHIP_MAX_PEC 3 PnvPhb4PecState pecs[PNV9_CHIP_MAX_PEC]; -} Pnv9Chip; +}; /* * A SMT8 fused core is a pair of SMT4 cores. @@ -112,18 +114,20 @@ typedef struct Pnv9Chip { #define PNV9_PIR2CHIP(pir) (((pir) >> 8) & 0x7f) #define TYPE_PNV10_CHIP "pnv10-chip" -#define PNV10_CHIP(obj) OBJECT_CHECK(Pnv10Chip, (obj), TYPE_PNV10_CHIP) +typedef struct Pnv10Chip Pnv10Chip; +DECLARE_INSTANCE_CHECKER(Pnv10Chip, PNV10_CHIP, + TYPE_PNV10_CHIP) -typedef struct Pnv10Chip { +struct Pnv10Chip { /*< private >*/ PnvChip parent_obj; /*< public >*/ Pnv9Psi psi; PnvLpcController lpc; -} Pnv10Chip; +}; -typedef struct PnvChipClass { +struct PnvChipClass { /*< private >*/ SysBusDeviceClass parent_class; @@ -144,30 +148,30 @@ typedef struct PnvChipClass { void (*pic_print_info)(PnvChip *chip, Monitor *mon); uint64_t (*xscom_core_base)(PnvChip *chip, uint32_t core_id); uint32_t (*xscom_pcba)(PnvChip *chip, uint64_t addr); -} PnvChipClass; +}; #define PNV_CHIP_TYPE_SUFFIX "-" TYPE_PNV_CHIP #define PNV_CHIP_TYPE_NAME(cpu_model) cpu_model PNV_CHIP_TYPE_SUFFIX #define TYPE_PNV_CHIP_POWER8E PNV_CHIP_TYPE_NAME("power8e_v2.1") -#define PNV_CHIP_POWER8E(obj) \ - OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER8E) +DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER8E, + TYPE_PNV_CHIP_POWER8E) #define TYPE_PNV_CHIP_POWER8 PNV_CHIP_TYPE_NAME("power8_v2.0") -#define PNV_CHIP_POWER8(obj) \ - OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER8) +DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER8, + TYPE_PNV_CHIP_POWER8) #define TYPE_PNV_CHIP_POWER8NVL PNV_CHIP_TYPE_NAME("power8nvl_v1.0") -#define PNV_CHIP_POWER8NVL(obj) \ - OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER8NVL) +DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER8NVL, + TYPE_PNV_CHIP_POWER8NVL) #define TYPE_PNV_CHIP_POWER9 PNV_CHIP_TYPE_NAME("power9_v2.0") -#define PNV_CHIP_POWER9(obj) \ - OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER9) +DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER9, + TYPE_PNV_CHIP_POWER9) #define TYPE_PNV_CHIP_POWER10 PNV_CHIP_TYPE_NAME("power10_v1.0") -#define PNV_CHIP_POWER10(obj) \ - OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER10) +DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10, + TYPE_PNV_CHIP_POWER10) /* * This generates a HW chip id depending on an index, as found on a @@ -191,16 +195,13 @@ typedef struct PnvChipClass { PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir); #define TYPE_PNV_MACHINE MACHINE_TYPE_NAME("powernv") -#define PNV_MACHINE(obj) \ - OBJECT_CHECK(PnvMachineState, (obj), TYPE_PNV_MACHINE) -#define PNV_MACHINE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PnvMachineClass, obj, TYPE_PNV_MACHINE) -#define PNV_MACHINE_CLASS(klass) \ - OBJECT_CLASS_CHECK(PnvMachineClass, klass, TYPE_PNV_MACHINE) - +typedef struct PnvMachineClass PnvMachineClass; typedef struct PnvMachineState PnvMachineState; +DECLARE_OBJ_CHECKERS(PnvMachineState, PnvMachineClass, + PNV_MACHINE, TYPE_PNV_MACHINE) -typedef struct PnvMachineClass { + +struct PnvMachineClass { /*< private >*/ MachineClass parent_class; @@ -209,7 +210,7 @@ typedef struct PnvMachineClass { int compat_size; void (*dt_power_mgt)(PnvMachineState *pnv, void *fdt); -} PnvMachineClass; +}; struct PnvMachineState { /*< private >*/ diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index 113550eb7ffbf902480cdaebfb59ec1b6560dbce..6ecee98a76ed73100c59b325ac182e7e5ef6bdb2 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2 of + * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but @@ -22,18 +22,15 @@ #include "hw/cpu/core.h" #include "target/ppc/cpu.h" +#include "qom/object.h" #define TYPE_PNV_CORE "powernv-cpu-core" -#define PNV_CORE(obj) \ - OBJECT_CHECK(PnvCore, (obj), TYPE_PNV_CORE) -#define PNV_CORE_CLASS(klass) \ - OBJECT_CLASS_CHECK(PnvCoreClass, (klass), TYPE_PNV_CORE) -#define PNV_CORE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PnvCoreClass, (obj), TYPE_PNV_CORE) +OBJECT_DECLARE_TYPE(PnvCore, PnvCoreClass, + PNV_CORE) typedef struct PnvChip PnvChip; -typedef struct PnvCore { +struct PnvCore { /*< private >*/ CPUCore parent_obj; @@ -44,13 +41,13 @@ typedef struct PnvCore { PnvChip *chip; MemoryRegion xscom_regs; -} PnvCore; +}; -typedef struct PnvCoreClass { +struct PnvCoreClass { DeviceClass parent_class; const MemoryRegionOps *xscom_ops; -} PnvCoreClass; +}; #define PNV_CORE_TYPE_SUFFIX "-" TYPE_PNV_CORE #define PNV_CORE_TYPE_NAME(cpu_model) cpu_model PNV_CORE_TYPE_SUFFIX @@ -65,13 +62,12 @@ static inline PnvCPUState *pnv_cpu_state(PowerPCCPU *cpu) } #define TYPE_PNV_QUAD "powernv-cpu-quad" -#define PNV_QUAD(obj) \ - OBJECT_CHECK(PnvQuad, (obj), TYPE_PNV_QUAD) +OBJECT_DECLARE_SIMPLE_TYPE(PnvQuad, PNV_QUAD) -typedef struct PnvQuad { +struct PnvQuad { DeviceState parent_obj; uint32_t id; MemoryRegion xscom_regs; -} PnvQuad; +}; #endif /* PPC_PNV_CORE_H */ diff --git a/include/hw/ppc/pnv_homer.h b/include/hw/ppc/pnv_homer.h index 1e91c950f691413dc7921683a0eda2ad1ed32d2b..1889e3083c57c877ff2303dc21e937d4931bedbf 100644 --- a/include/hw/ppc/pnv_homer.h +++ b/include/hw/ppc/pnv_homer.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -21,28 +21,28 @@ #define PPC_PNV_HOMER_H #include "hw/ppc/pnv.h" +#include "qom/object.h" #define TYPE_PNV_HOMER "pnv-homer" -#define PNV_HOMER(obj) OBJECT_CHECK(PnvHomer, (obj), TYPE_PNV_HOMER) +OBJECT_DECLARE_TYPE(PnvHomer, PnvHomerClass, + PNV_HOMER) #define TYPE_PNV8_HOMER TYPE_PNV_HOMER "-POWER8" -#define PNV8_HOMER(obj) OBJECT_CHECK(PnvHomer, (obj), TYPE_PNV8_HOMER) +DECLARE_INSTANCE_CHECKER(PnvHomer, PNV8_HOMER, + TYPE_PNV8_HOMER) #define TYPE_PNV9_HOMER TYPE_PNV_HOMER "-POWER9" -#define PNV9_HOMER(obj) OBJECT_CHECK(PnvHomer, (obj), TYPE_PNV9_HOMER) +DECLARE_INSTANCE_CHECKER(PnvHomer, PNV9_HOMER, + TYPE_PNV9_HOMER) -typedef struct PnvHomer { +struct PnvHomer { DeviceState parent; struct PnvChip *chip; MemoryRegion pba_regs; MemoryRegion regs; -} PnvHomer; +}; -#define PNV_HOMER_CLASS(klass) \ - OBJECT_CLASS_CHECK(PnvHomerClass, (klass), TYPE_PNV_HOMER) -#define PNV_HOMER_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PnvHomerClass, (obj), TYPE_PNV_HOMER) -typedef struct PnvHomerClass { +struct PnvHomerClass { DeviceClass parent_class; int pba_size; @@ -51,6 +51,6 @@ typedef struct PnvHomerClass { const MemoryRegionOps *homer_ops; hwaddr core_max_base; -} PnvHomerClass; +}; #endif /* PPC_PNV_HOMER_H */ diff --git a/include/hw/ppc/pnv_lpc.h b/include/hw/ppc/pnv_lpc.h index c1ec85d5e2c514f0997ad5d50ff56be96b497f95..e893e763dd5f6589438ce337ad2d8018de635ed5 100644 --- a/include/hw/ppc/pnv_lpc.h +++ b/include/hw/ppc/pnv_lpc.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -21,20 +21,26 @@ #define PPC_PNV_LPC_H #include "hw/ppc/pnv_psi.h" +#include "qom/object.h" #define TYPE_PNV_LPC "pnv-lpc" -#define PNV_LPC(obj) \ - OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV_LPC) +typedef struct PnvLpcClass PnvLpcClass; +typedef struct PnvLpcController PnvLpcController; +DECLARE_OBJ_CHECKERS(PnvLpcController, PnvLpcClass, + PNV_LPC, TYPE_PNV_LPC) #define TYPE_PNV8_LPC TYPE_PNV_LPC "-POWER8" -#define PNV8_LPC(obj) OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV8_LPC) +DECLARE_INSTANCE_CHECKER(PnvLpcController, PNV8_LPC, + TYPE_PNV8_LPC) #define TYPE_PNV9_LPC TYPE_PNV_LPC "-POWER9" -#define PNV9_LPC(obj) OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV9_LPC) +DECLARE_INSTANCE_CHECKER(PnvLpcController, PNV9_LPC, + TYPE_PNV9_LPC) #define TYPE_PNV10_LPC TYPE_PNV_LPC "-POWER10" -#define PNV10_LPC(obj) OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV10_LPC) +DECLARE_INSTANCE_CHECKER(PnvLpcController, PNV10_LPC, + TYPE_PNV10_LPC) -typedef struct PnvLpcController { +struct PnvLpcController { DeviceState parent; uint64_t eccb_stat_reg; @@ -79,20 +85,16 @@ typedef struct PnvLpcController { /* PSI to generate interrupts */ PnvPsi *psi; -} PnvLpcController; +}; -#define PNV_LPC_CLASS(klass) \ - OBJECT_CLASS_CHECK(PnvLpcClass, (klass), TYPE_PNV_LPC) -#define PNV_LPC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PnvLpcClass, (obj), TYPE_PNV_LPC) -typedef struct PnvLpcClass { +struct PnvLpcClass { DeviceClass parent_class; int psi_irq; DeviceRealize parent_realize; -} PnvLpcClass; +}; /* * Old compilers error on typdef forward declarations. Keep them happy. diff --git a/include/hw/ppc/pnv_occ.h b/include/hw/ppc/pnv_occ.h index f8d3061419dc932a1f201a8d7bd13631af8b3e73..b78185aecaf2fbdd86cadc1ad0970a1369c63e6b 100644 --- a/include/hw/ppc/pnv_occ.h +++ b/include/hw/ppc/pnv_occ.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -21,18 +21,22 @@ #define PPC_PNV_OCC_H #include "hw/ppc/pnv_psi.h" +#include "qom/object.h" #define TYPE_PNV_OCC "pnv-occ" -#define PNV_OCC(obj) OBJECT_CHECK(PnvOCC, (obj), TYPE_PNV_OCC) +OBJECT_DECLARE_TYPE(PnvOCC, PnvOCCClass, + PNV_OCC) #define TYPE_PNV8_OCC TYPE_PNV_OCC "-POWER8" -#define PNV8_OCC(obj) OBJECT_CHECK(PnvOCC, (obj), TYPE_PNV8_OCC) +DECLARE_INSTANCE_CHECKER(PnvOCC, PNV8_OCC, + TYPE_PNV8_OCC) #define TYPE_PNV9_OCC TYPE_PNV_OCC "-POWER9" -#define PNV9_OCC(obj) OBJECT_CHECK(PnvOCC, (obj), TYPE_PNV9_OCC) +DECLARE_INSTANCE_CHECKER(PnvOCC, PNV9_OCC, + TYPE_PNV9_OCC) #define PNV_OCC_SENSOR_DATA_BLOCK_OFFSET 0x00580000 #define PNV_OCC_SENSOR_DATA_BLOCK_SIZE 0x00025800 -typedef struct PnvOCC { +struct PnvOCC { DeviceState xd; /* OCC Misc interrupt */ @@ -42,20 +46,16 @@ typedef struct PnvOCC { MemoryRegion xscom_regs; MemoryRegion sram_regs; -} PnvOCC; +}; -#define PNV_OCC_CLASS(klass) \ - OBJECT_CLASS_CHECK(PnvOCCClass, (klass), TYPE_PNV_OCC) -#define PNV_OCC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PnvOCCClass, (obj), TYPE_PNV_OCC) -typedef struct PnvOCCClass { +struct PnvOCCClass { DeviceClass parent_class; int xscom_size; const MemoryRegionOps *xscom_ops; int psi_irq; -} PnvOCCClass; +}; #define PNV_OCC_SENSOR_DATA_BLOCK_BASE(i) \ (PNV_OCC_SENSOR_DATA_BLOCK_OFFSET + (i) * PNV_OCC_SENSOR_DATA_BLOCK_SIZE) diff --git a/include/hw/ppc/pnv_pnor.h b/include/hw/ppc/pnv_pnor.h index 4f96abdfb402c480c48586e98ab3f3494fe1e07b..99f9a3adfb54140226fdf27ba2aa3704899b8030 100644 --- a/include/hw/ppc/pnv_pnor.h +++ b/include/hw/ppc/pnv_pnor.h @@ -8,6 +8,7 @@ */ #ifndef _PPC_PNV_PNOR_H #define _PPC_PNV_PNOR_H +#include "qom/object.h" /* * PNOR offset on the LPC FW address space @@ -15,9 +16,9 @@ #define PNOR_SPI_OFFSET 0x0c000000UL #define TYPE_PNV_PNOR "pnv-pnor" -#define PNV_PNOR(obj) OBJECT_CHECK(PnvPnor, (obj), TYPE_PNV_PNOR) +OBJECT_DECLARE_SIMPLE_TYPE(PnvPnor, PNV_PNOR) -typedef struct PnvPnor { +struct PnvPnor { SysBusDevice parent_obj; BlockBackend *blk; @@ -25,6 +26,6 @@ typedef struct PnvPnor { uint8_t *storage; int64_t size; MemoryRegion mmio; -} PnvPnor; +}; #endif /* _PPC_PNV_PNOR_H */ diff --git a/include/hw/ppc/pnv_psi.h b/include/hw/ppc/pnv_psi.h index f0f5b5519767725e5c4cfb9a09324a8483dd1cbf..eb841b34a1f7800776c3506bfe7c03d2e45ad671 100644 --- a/include/hw/ppc/pnv_psi.h +++ b/include/hw/ppc/pnv_psi.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -23,15 +23,16 @@ #include "hw/sysbus.h" #include "hw/ppc/xics.h" #include "hw/ppc/xive.h" +#include "qom/object.h" #define TYPE_PNV_PSI "pnv-psi" -#define PNV_PSI(obj) \ - OBJECT_CHECK(PnvPsi, (obj), TYPE_PNV_PSI) +OBJECT_DECLARE_TYPE(PnvPsi, PnvPsiClass, + PNV_PSI) #define PSIHB_XSCOM_MAX 0x20 -typedef struct PnvPsi { - SysBusDevice parent; +struct PnvPsi { + DeviceState parent; MemoryRegion regs_mr; uint64_t bar; @@ -47,36 +48,30 @@ typedef struct PnvPsi { uint64_t regs[PSIHB_XSCOM_MAX]; MemoryRegion xscom_regs; -} PnvPsi; +}; #define TYPE_PNV8_PSI TYPE_PNV_PSI "-POWER8" -#define PNV8_PSI(obj) \ - OBJECT_CHECK(Pnv8Psi, (obj), TYPE_PNV8_PSI) +OBJECT_DECLARE_SIMPLE_TYPE(Pnv8Psi, PNV8_PSI) -typedef struct Pnv8Psi { +struct Pnv8Psi { PnvPsi parent; ICSState ics; -} Pnv8Psi; +}; #define TYPE_PNV9_PSI TYPE_PNV_PSI "-POWER9" -#define PNV9_PSI(obj) \ - OBJECT_CHECK(Pnv9Psi, (obj), TYPE_PNV9_PSI) +OBJECT_DECLARE_SIMPLE_TYPE(Pnv9Psi, PNV9_PSI) -typedef struct Pnv9Psi { +struct Pnv9Psi { PnvPsi parent; XiveSource source; -} Pnv9Psi; +}; #define TYPE_PNV10_PSI TYPE_PNV_PSI "-POWER10" -#define PNV_PSI_CLASS(klass) \ - OBJECT_CLASS_CHECK(PnvPsiClass, (klass), TYPE_PNV_PSI) -#define PNV_PSI_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PnvPsiClass, (obj), TYPE_PNV_PSI) -typedef struct PnvPsiClass { +struct PnvPsiClass { SysBusDeviceClass parent_class; uint32_t xscom_pcba; @@ -86,7 +81,7 @@ typedef struct PnvPsiClass { int compat_size; void (*irq_set)(PnvPsi *psi, int, bool state); -} PnvPsiClass; +}; /* The PSI and FSP interrupts are muxed on the same IRQ number */ typedef enum PnvPsiIrq { diff --git a/include/hw/ppc/pnv_xive.h b/include/hw/ppc/pnv_xive.h index 76cf16f644721be406fe32b8f01b397d436e51f9..7928e279639adb4a1d454983e9ef04749882f1f9 100644 --- a/include/hw/ppc/pnv_xive.h +++ b/include/hw/ppc/pnv_xive.h @@ -11,15 +11,13 @@ #define PPC_PNV_XIVE_H #include "hw/ppc/xive.h" +#include "qom/object.h" struct PnvChip; #define TYPE_PNV_XIVE "pnv-xive" -#define PNV_XIVE(obj) OBJECT_CHECK(PnvXive, (obj), TYPE_PNV_XIVE) -#define PNV_XIVE_CLASS(klass) \ - OBJECT_CLASS_CHECK(PnvXiveClass, (klass), TYPE_PNV_XIVE) -#define PNV_XIVE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PnvXiveClass, (obj), TYPE_PNV_XIVE) +OBJECT_DECLARE_TYPE(PnvXive, PnvXiveClass, + PNV_XIVE) #define XIVE_BLOCK_MAX 16 @@ -28,7 +26,7 @@ struct PnvChip; #define XIVE_TABLE_VDT_MAX 16 /* VDT Domain Table (0-15) */ #define XIVE_TABLE_EDT_MAX 64 /* EDT Domain Table (0-63) */ -typedef struct PnvXive { +struct PnvXive { XiveRouter parent_obj; /* Owning chip */ @@ -87,13 +85,13 @@ typedef struct PnvXive { uint64_t mig[XIVE_TABLE_MIG_MAX]; uint64_t vdt[XIVE_TABLE_VDT_MAX]; uint64_t edt[XIVE_TABLE_EDT_MAX]; -} PnvXive; +}; -typedef struct PnvXiveClass { +struct PnvXiveClass { XiveRouterClass parent_class; DeviceRealize parent_realize; -} PnvXiveClass; +}; void pnv_xive_pic_print_info(PnvXive *xive, Monitor *mon); diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h index 09156a5a7a6f4445d113bfa59b1baa364b80ceac..8578f5a207df61892aa4836f18815a6d54c9c273 100644 --- a/include/hw/ppc/pnv_xscom.h +++ b/include/hw/ppc/pnv_xscom.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -27,16 +27,14 @@ typedef struct PnvXScomInterface PnvXScomInterface; #define TYPE_PNV_XSCOM_INTERFACE "pnv-xscom-interface" #define PNV_XSCOM_INTERFACE(obj) \ INTERFACE_CHECK(PnvXScomInterface, (obj), TYPE_PNV_XSCOM_INTERFACE) -#define PNV_XSCOM_INTERFACE_CLASS(klass) \ - OBJECT_CLASS_CHECK(PnvXScomInterfaceClass, (klass), \ +typedef struct PnvXScomInterfaceClass PnvXScomInterfaceClass; +DECLARE_CLASS_CHECKERS(PnvXScomInterfaceClass, PNV_XSCOM_INTERFACE, TYPE_PNV_XSCOM_INTERFACE) -#define PNV_XSCOM_INTERFACE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PnvXScomInterfaceClass, (obj), TYPE_PNV_XSCOM_INTERFACE) -typedef struct PnvXScomInterfaceClass { +struct PnvXScomInterfaceClass { InterfaceClass parent; int (*dt_xscom)(PnvXScomInterface *dev, void *fdt, int offset); -} PnvXScomInterfaceClass; +}; /* * Layout of the XSCOM PCB addresses of EX core 1 (POWER 8) diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index d2533e7264ae69adfcafbb63623ca979644c499f..2e89e36cfbdc58bac75ac947cedfd60fcb69cac3 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -8,6 +8,7 @@ #include "hw/mem/pc-dimm.h" #include "hw/ppc/spapr_ovec.h" #include "hw/ppc/spapr_irq.h" +#include "qom/object.h" #include "hw/ppc/spapr_xive.h" /* For SpaprXive */ #include "hw/ppc/xics.h" /* For ICSState */ #include "hw/ppc/spapr_tpm_proxy.h" @@ -27,10 +28,8 @@ typedef struct SpaprPendingHpt SpaprPendingHpt; #define TYPE_SPAPR_RTC "spapr-rtc" -#define SPAPR_RTC(obj) \ - OBJECT_CHECK(SpaprRtcState, (obj), TYPE_SPAPR_RTC) +OBJECT_DECLARE_SIMPLE_TYPE(SpaprRtcState, SPAPR_RTC) -typedef struct SpaprRtcState SpaprRtcState; struct SpaprRtcState { /*< private >*/ DeviceState parent_obj; @@ -38,15 +37,9 @@ struct SpaprRtcState { }; typedef struct SpaprDimmState SpaprDimmState; -typedef struct SpaprMachineClass SpaprMachineClass; #define TYPE_SPAPR_MACHINE "spapr-machine" -#define SPAPR_MACHINE(obj) \ - OBJECT_CHECK(SpaprMachineState, (obj), TYPE_SPAPR_MACHINE) -#define SPAPR_MACHINE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SpaprMachineClass, obj, TYPE_SPAPR_MACHINE) -#define SPAPR_MACHINE_CLASS(klass) \ - OBJECT_CLASS_CHECK(SpaprMachineClass, klass, TYPE_SPAPR_MACHINE) +OBJECT_DECLARE_TYPE(SpaprMachineState, SpaprMachineClass, SPAPR_MACHINE) typedef enum { SPAPR_RESIZE_HPT_DEFAULT = 0, @@ -104,6 +97,21 @@ typedef enum { #define FDT_MAX_SIZE 0x100000 +/* + * NUMA related macros. MAX_DISTANCE_REF_POINTS was taken + * from Linux kernel arch/powerpc/mm/numa.h. It represents the + * amount of associativity domains for non-CPU resources. + * + * NUMA_ASSOC_SIZE is the base array size of an ibm,associativity + * array for any non-CPU resource. + * + * VCPU_ASSOC_SIZE represents the size of ibm,associativity array + * for CPUs, which has an extra element (vcpu_id) in the end. + */ +#define MAX_DISTANCE_REF_POINTS 4 +#define NUMA_ASSOC_SIZE (MAX_DISTANCE_REF_POINTS + 1) +#define VCPU_ASSOC_SIZE (NUMA_ASSOC_SIZE + 1) + typedef struct SpaprCapabilities SpaprCapabilities; struct SpaprCapabilities { uint8_t caps[SPAPR_CAP_NUM]; @@ -129,6 +137,8 @@ struct SpaprMachineClass { bool linux_pci_probe; bool smp_threads_vsmt; /* set VSMT to smp_threads by default */ hwaddr rma_limit; /* clamp the RMA to this size */ + bool pre_5_1_assoc_refpoints; + bool pre_5_2_numa_associativity; void (*phb_placement)(SpaprMachineState *spapr, uint32_t index, uint64_t *buid, hwaddr *pio, @@ -229,6 +239,8 @@ struct SpaprMachineState { unsigned gpu_numa_id; SpaprTpmProxy *tpm_proxy; + uint32_t numa_assoc_array[MAX_NODES][NUMA_ASSOC_SIZE]; + Error *fwnmi_migration_blocker; }; @@ -768,15 +780,13 @@ static inline void spapr_dt_irq(uint32_t *intspec, int irq, bool is_lsi) intspec[1] = is_lsi ? cpu_to_be32(1) : 0; } -typedef struct SpaprTceTable SpaprTceTable; #define TYPE_SPAPR_TCE_TABLE "spapr-tce-table" -#define SPAPR_TCE_TABLE(obj) \ - OBJECT_CHECK(SpaprTceTable, (obj), TYPE_SPAPR_TCE_TABLE) +OBJECT_DECLARE_SIMPLE_TYPE(SpaprTceTable, SPAPR_TCE_TABLE) #define TYPE_SPAPR_IOMMU_MEMORY_REGION "spapr-iommu-memory-region" -#define SPAPR_IOMMU_MEMORY_REGION(obj) \ - OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_SPAPR_IOMMU_MEMORY_REGION) +DECLARE_INSTANCE_CHECKER(IOMMUMemoryRegion, SPAPR_IOMMU_MEMORY_REGION, + TYPE_SPAPR_IOMMU_MEMORY_REGION) struct SpaprTceTable { DeviceState parent; @@ -836,14 +846,14 @@ void spapr_hotplug_req_add_by_count_indexed(SpaprDrcType drc_type, void spapr_hotplug_req_remove_by_count_indexed(SpaprDrcType drc_type, uint32_t count, uint32_t index); int spapr_hpt_shift_for_ramsize(uint64_t ramsize); -void spapr_reallocate_hpt(SpaprMachineState *spapr, int shift, - Error **errp); +int spapr_reallocate_hpt(SpaprMachineState *spapr, int shift, Error **errp); void spapr_clear_pending_events(SpaprMachineState *spapr); void spapr_clear_pending_hotplug_events(SpaprMachineState *spapr); int spapr_max_server_number(SpaprMachineState *spapr); void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte0, uint64_t pte1); void spapr_mce_req_event(PowerPCCPU *cpu, bool recovered); +bool spapr_machine_using_legacy_numa(SpaprMachineState *spapr); /* DRC callbacks. */ void spapr_core_release(DeviceState *dev); @@ -886,13 +896,14 @@ int spapr_rtc_import_offset(SpaprRtcState *rtc, int64_t legacy_offset); #define SPAPR_LMB_FLAGS_ASSIGNED 0x00000008 #define SPAPR_LMB_FLAGS_DRC_INVALID 0x00000020 #define SPAPR_LMB_FLAGS_RESERVED 0x00000080 +#define SPAPR_LMB_FLAGS_HOTREMOVABLE 0x00000100 void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg); #define HTAB_SIZE(spapr) (1ULL << ((spapr)->htab_shift)) int spapr_get_vcpu_id(PowerPCCPU *cpu); -void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp); +bool spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp); PowerPCCPU *spapr_find_cpu(int vcpu_id); int spapr_caps_pre_load(void *opaque); @@ -924,7 +935,7 @@ void spapr_caps_cpu_apply(SpaprMachineState *spapr, PowerPCCPU *cpu); void spapr_caps_add_properties(SpaprMachineClass *smc); int spapr_caps_post_migration(SpaprMachineState *spapr); -void spapr_check_pagesize(SpaprMachineState *spapr, hwaddr pagesize, +bool spapr_check_pagesize(SpaprMachineState *spapr, hwaddr pagesize, Error **errp); /* * XIVE definitions diff --git a/include/hw/ppc/spapr_cpu_core.h b/include/hw/ppc/spapr_cpu_core.h index 7aed8f555b4f227795d5b9972b06858eb3bd9e79..dab3dfc76c0ae0016632be234e580fb83bcbe111 100644 --- a/include/hw/ppc/spapr_cpu_core.h +++ b/include/hw/ppc/spapr_cpu_core.h @@ -13,18 +13,15 @@ #include "hw/qdev-core.h" #include "target/ppc/cpu-qom.h" #include "target/ppc/cpu.h" +#include "qom/object.h" #define TYPE_SPAPR_CPU_CORE "spapr-cpu-core" -#define SPAPR_CPU_CORE(obj) \ - OBJECT_CHECK(SpaprCpuCore, (obj), TYPE_SPAPR_CPU_CORE) -#define SPAPR_CPU_CORE_CLASS(klass) \ - OBJECT_CLASS_CHECK(SpaprCpuCoreClass, (klass), TYPE_SPAPR_CPU_CORE) -#define SPAPR_CPU_CORE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SpaprCpuCoreClass, (obj), TYPE_SPAPR_CPU_CORE) +OBJECT_DECLARE_TYPE(SpaprCpuCore, SpaprCpuCoreClass, + SPAPR_CPU_CORE) #define SPAPR_CPU_CORE_TYPE_NAME(model) model "-" TYPE_SPAPR_CPU_CORE -typedef struct SpaprCpuCore { +struct SpaprCpuCore { /*< private >*/ CPUCore parent_obj; @@ -32,12 +29,12 @@ typedef struct SpaprCpuCore { PowerPCCPU **threads; int node_id; bool pre_3_0_migration; /* older machine don't know about SpaprCpuState */ -} SpaprCpuCore; +}; -typedef struct SpaprCpuCoreClass { +struct SpaprCpuCoreClass { DeviceClass parent_class; const char *cpu_type; -} SpaprCpuCoreClass; +}; const char *spapr_get_cpu_core_type(const char *cpu_type); void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip, diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h index 21af8deac13f68fdaa47c6b092a681243428b9fa..165b281496bb76d9cd49aba1681622364b3c505a 100644 --- a/include/hw/ppc/spapr_drc.h +++ b/include/hw/ppc/spapr_drc.h @@ -29,62 +29,21 @@ TYPE_SPAPR_DR_CONNECTOR) #define TYPE_SPAPR_DRC_PHYSICAL "spapr-drc-physical" -#define SPAPR_DRC_PHYSICAL_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_PHYSICAL) -#define SPAPR_DRC_PHYSICAL_CLASS(klass) \ - OBJECT_CLASS_CHECK(SpaprDrcClass, klass, \ - TYPE_SPAPR_DRC_PHYSICAL) #define SPAPR_DRC_PHYSICAL(obj) OBJECT_CHECK(SpaprDrcPhysical, (obj), \ TYPE_SPAPR_DRC_PHYSICAL) #define TYPE_SPAPR_DRC_LOGICAL "spapr-drc-logical" -#define SPAPR_DRC_LOGICAL_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_LOGICAL) -#define SPAPR_DRC_LOGICAL_CLASS(klass) \ - OBJECT_CLASS_CHECK(SpaprDrcClass, klass, \ - TYPE_SPAPR_DRC_LOGICAL) -#define SPAPR_DRC_LOGICAL(obj) OBJECT_CHECK(SpaprDrc, (obj), \ - TYPE_SPAPR_DRC_LOGICAL) #define TYPE_SPAPR_DRC_CPU "spapr-drc-cpu" -#define SPAPR_DRC_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_CPU) -#define SPAPR_DRC_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(SpaprDrcClass, klass, TYPE_SPAPR_DRC_CPU) -#define SPAPR_DRC_CPU(obj) OBJECT_CHECK(SpaprDrc, (obj), \ - TYPE_SPAPR_DRC_CPU) #define TYPE_SPAPR_DRC_PCI "spapr-drc-pci" -#define SPAPR_DRC_PCI_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_PCI) -#define SPAPR_DRC_PCI_CLASS(klass) \ - OBJECT_CLASS_CHECK(SpaprDrcClass, klass, TYPE_SPAPR_DRC_PCI) -#define SPAPR_DRC_PCI(obj) OBJECT_CHECK(SpaprDrc, (obj), \ - TYPE_SPAPR_DRC_PCI) #define TYPE_SPAPR_DRC_LMB "spapr-drc-lmb" -#define SPAPR_DRC_LMB_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_LMB) -#define SPAPR_DRC_LMB_CLASS(klass) \ - OBJECT_CLASS_CHECK(SpaprDrcClass, klass, TYPE_SPAPR_DRC_LMB) -#define SPAPR_DRC_LMB(obj) OBJECT_CHECK(SpaprDrc, (obj), \ - TYPE_SPAPR_DRC_LMB) #define TYPE_SPAPR_DRC_PHB "spapr-drc-phb" -#define SPAPR_DRC_PHB_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_PHB) -#define SPAPR_DRC_PHB_CLASS(klass) \ - OBJECT_CLASS_CHECK(SpaprDrcClass, klass, TYPE_SPAPR_DRC_PHB) -#define SPAPR_DRC_PHB(obj) OBJECT_CHECK(SpaprDrc, (obj), \ - TYPE_SPAPR_DRC_PHB) #define TYPE_SPAPR_DRC_PMEM "spapr-drc-pmem" -#define SPAPR_DRC_PMEM_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_PMEM) -#define SPAPR_DRC_PMEM_CLASS(klass) \ - OBJECT_CLASS_CHECK(SpaprDrcClass, klass, TYPE_SPAPR_DRC_PMEM) -#define SPAPR_DRC_PMEM(obj) OBJECT_CHECK(SpaprDrc, (obj), \ - TYPE_SPAPR_DRC_PMEM) + /* * Various hotplug types managed by SpaprDrc * @@ -276,7 +235,7 @@ SpaprDrc *spapr_drc_by_index(uint32_t index); SpaprDrc *spapr_drc_by_id(const char *type, uint32_t id); int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask); -void spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp); +bool spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp); void spapr_drc_detach(SpaprDrc *drc); /* Returns true if a hot plug/unplug request is pending */ diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h index ca8cb442137455ae92a6c0bbad73b380288de3a3..c22a72c9e27050c294230c44763c855b174815e6 100644 --- a/include/hw/ppc/spapr_irq.h +++ b/include/hw/ppc/spapr_irq.h @@ -11,6 +11,7 @@ #define HW_SPAPR_IRQ_H #include "target/ppc/cpu-qom.h" +#include "qom/object.h" /* * IRQ range offsets per device type @@ -28,19 +29,18 @@ #define SPAPR_NR_XIRQS 0x1000 -typedef struct SpaprMachineState SpaprMachineState; +struct SpaprMachineState; typedef struct SpaprInterruptController SpaprInterruptController; #define TYPE_SPAPR_INTC "spapr-interrupt-controller" #define SPAPR_INTC(obj) \ INTERFACE_CHECK(SpaprInterruptController, (obj), TYPE_SPAPR_INTC) -#define SPAPR_INTC_CLASS(klass) \ - OBJECT_CLASS_CHECK(SpaprInterruptControllerClass, (klass), TYPE_SPAPR_INTC) -#define SPAPR_INTC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SpaprInterruptControllerClass, (obj), TYPE_SPAPR_INTC) +typedef struct SpaprInterruptControllerClass SpaprInterruptControllerClass; +DECLARE_CLASS_CHECKERS(SpaprInterruptControllerClass, SPAPR_INTC, + TYPE_SPAPR_INTC) -typedef struct SpaprInterruptControllerClass { +struct SpaprInterruptControllerClass { InterfaceClass parent; int (*activate)(SpaprInterruptController *intc, uint32_t nr_servers, @@ -65,22 +65,22 @@ typedef struct SpaprInterruptControllerClass { void (*dt)(SpaprInterruptController *intc, uint32_t nr_servers, void *fdt, uint32_t phandle); int (*post_load)(SpaprInterruptController *intc, int version_id); -} SpaprInterruptControllerClass; +}; -void spapr_irq_update_active_intc(SpaprMachineState *spapr); +void spapr_irq_update_active_intc(struct SpaprMachineState *spapr); -int spapr_irq_cpu_intc_create(SpaprMachineState *spapr, +int spapr_irq_cpu_intc_create(struct SpaprMachineState *spapr, PowerPCCPU *cpu, Error **errp); -void spapr_irq_cpu_intc_reset(SpaprMachineState *spapr, PowerPCCPU *cpu); -void spapr_irq_cpu_intc_destroy(SpaprMachineState *spapr, PowerPCCPU *cpu); -void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon); -void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers, +void spapr_irq_cpu_intc_reset(struct SpaprMachineState *spapr, PowerPCCPU *cpu); +void spapr_irq_cpu_intc_destroy(struct SpaprMachineState *spapr, PowerPCCPU *cpu); +void spapr_irq_print_info(struct SpaprMachineState *spapr, Monitor *mon); +void spapr_irq_dt(struct SpaprMachineState *spapr, uint32_t nr_servers, void *fdt, uint32_t phandle); -uint32_t spapr_irq_nr_msis(SpaprMachineState *spapr); -int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align, +uint32_t spapr_irq_nr_msis(struct SpaprMachineState *spapr); +int spapr_irq_msi_alloc(struct SpaprMachineState *spapr, uint32_t num, bool align, Error **errp); -void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num); +void spapr_irq_msi_free(struct SpaprMachineState *spapr, int irq, uint32_t num); typedef struct SpaprIrq { bool xics; @@ -92,13 +92,13 @@ extern SpaprIrq spapr_irq_xics_legacy; extern SpaprIrq spapr_irq_xive; extern SpaprIrq spapr_irq_dual; -void spapr_irq_init(SpaprMachineState *spapr, Error **errp); -int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp); -void spapr_irq_free(SpaprMachineState *spapr, int irq, int num); -qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq); -int spapr_irq_post_load(SpaprMachineState *spapr, int version_id); -void spapr_irq_reset(SpaprMachineState *spapr, Error **errp); -int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp); +void spapr_irq_init(struct SpaprMachineState *spapr, Error **errp); +int spapr_irq_claim(struct SpaprMachineState *spapr, int irq, bool lsi, Error **errp); +void spapr_irq_free(struct SpaprMachineState *spapr, int irq, int num); +qemu_irq spapr_qirq(struct SpaprMachineState *spapr, int irq); +int spapr_irq_post_load(struct SpaprMachineState *spapr, int version_id); +void spapr_irq_reset(struct SpaprMachineState *spapr, Error **errp); +int spapr_irq_get_phandle(struct SpaprMachineState *spapr, void *fdt, Error **errp); typedef int (*SpaprInterruptControllerInitKvm)(SpaprInterruptController *, uint32_t, Error **); @@ -111,7 +111,7 @@ int spapr_irq_init_kvm(SpaprInterruptControllerInitKvm fn, /* * XICS legacy routines */ -int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp); +int spapr_irq_find(struct SpaprMachineState *spapr, int num, bool align, Error **errp); #define spapr_irq_findone(spapr, errp) spapr_irq_find(spapr, 1, false, errp) #endif diff --git a/include/hw/ppc/spapr_numa.h b/include/hw/ppc/spapr_numa.h new file mode 100644 index 0000000000000000000000000000000000000000..b3fd950634225acc2df2ea16f423be881f9ce1e4 --- /dev/null +++ b/include/hw/ppc/spapr_numa.h @@ -0,0 +1,35 @@ +/* + * QEMU PowerPC pSeries Logical Partition NUMA associativity handling + * + * Copyright IBM Corp. 2020 + * + * Authors: + * Daniel Henrique Barboza + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_SPAPR_NUMA_H +#define HW_SPAPR_NUMA_H + +#include "hw/boards.h" +#include "hw/ppc/spapr.h" + +/* + * Having both SpaprMachineState and MachineState as arguments + * feels odd, but it will spare a MACHINE() call inside the + * function. spapr_machine_init() is the only caller for it, and + * it has both pointers resolved already. + */ +void spapr_numa_associativity_init(SpaprMachineState *spapr, + MachineState *machine); +void spapr_numa_write_rtas_dt(SpaprMachineState *spapr, void *fdt, int rtas); +void spapr_numa_write_associativity_dt(SpaprMachineState *spapr, void *fdt, + int offset, int nodeid); +int spapr_numa_fixup_cpu_dt(SpaprMachineState *spapr, void *fdt, + int offset, PowerPCCPU *cpu); +int spapr_numa_write_assoc_lookup_arrays(SpaprMachineState *spapr, void *fdt, + int offset); + +#endif /* HW_SPAPR_NUMA_H */ diff --git a/include/hw/ppc/spapr_nvdimm.h b/include/hw/ppc/spapr_nvdimm.h index b3330cc485d27d8604ed6ba7614285255e110b7a..344582d2f5f78d56fa4367a52b73fe6fe8587557 100644 --- a/include/hw/ppc/spapr_nvdimm.h +++ b/include/hw/ppc/spapr_nvdimm.h @@ -27,11 +27,9 @@ QEMU_BUILD_BUG_ON(SPAPR_MINIMUM_SCM_BLOCK_SIZE % SPAPR_MEMORY_BLOCK_SIZE); int spapr_pmem_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, void *fdt, int *fdt_start_offset, Error **errp); -int spapr_dt_nvdimm(void *fdt, int parent_offset, NVDIMMDevice *nvdimm); -void spapr_dt_persistent_memory(void *fdt); -void spapr_nvdimm_validate_opts(NVDIMMDevice *nvdimm, uint64_t size, - Error **errp); -void spapr_add_nvdimm(DeviceState *dev, uint64_t slot, Error **errp); -void spapr_create_nvdimm_dr_connectors(SpaprMachineState *spapr); +void spapr_dt_persistent_memory(SpaprMachineState *spapr, void *fdt); +bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm, + uint64_t size, Error **errp); +bool spapr_add_nvdimm(DeviceState *dev, uint64_t slot, Error **errp); #endif diff --git a/include/hw/ppc/spapr_tpm_proxy.h b/include/hw/ppc/spapr_tpm_proxy.h index c574e22ba4b6675fcb91f2d3ef078098e774be3f..96d2a9697e50051f797d7ba0bac16cab66c64a6c 100644 --- a/include/hw/ppc/spapr_tpm_proxy.h +++ b/include/hw/ppc/spapr_tpm_proxy.h @@ -17,15 +17,14 @@ #include "hw/qdev-core.h" #define TYPE_SPAPR_TPM_PROXY "spapr-tpm-proxy" -#define SPAPR_TPM_PROXY(obj) OBJECT_CHECK(SpaprTpmProxy, (obj), \ - TYPE_SPAPR_TPM_PROXY) +OBJECT_DECLARE_SIMPLE_TYPE(SpaprTpmProxy, SPAPR_TPM_PROXY) -typedef struct SpaprTpmProxy { +struct SpaprTpmProxy { /*< private >*/ DeviceState parent; char *host_path; int host_fd; -} SpaprTpmProxy; +}; #endif /* HW_SPAPR_TPM_PROXY_H */ diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h index bed7df60e35c89e9824b3ba067c3acc5d017389b..4bea87f39cc4ee100da1e6454276becbf300b449 100644 --- a/include/hw/ppc/spapr_vio.h +++ b/include/hw/ppc/spapr_vio.h @@ -11,7 +11,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,17 +25,14 @@ #include "hw/ppc/spapr.h" #include "sysemu/dma.h" #include "hw/irq.h" +#include "qom/object.h" #define TYPE_VIO_SPAPR_DEVICE "vio-spapr-device" -#define VIO_SPAPR_DEVICE(obj) \ - OBJECT_CHECK(SpaprVioDevice, (obj), TYPE_VIO_SPAPR_DEVICE) -#define VIO_SPAPR_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(SpaprVioDeviceClass, (klass), TYPE_VIO_SPAPR_DEVICE) -#define VIO_SPAPR_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SpaprVioDeviceClass, (obj), TYPE_VIO_SPAPR_DEVICE) +OBJECT_DECLARE_TYPE(SpaprVioDevice, SpaprVioDeviceClass, + VIO_SPAPR_DEVICE) #define TYPE_SPAPR_VIO_BUS "spapr-vio-bus" -#define SPAPR_VIO_BUS(obj) OBJECT_CHECK(SpaprVioBus, (obj), TYPE_SPAPR_VIO_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(SpaprVioBus, SPAPR_VIO_BUS) #define TYPE_SPAPR_VIO_BRIDGE "spapr-vio-bridge" @@ -46,10 +43,8 @@ typedef struct SpaprVioCrq { int(*SendFunc)(struct SpaprVioDevice *vdev, uint8_t *crq); } SpaprVioCrq; -typedef struct SpaprVioDevice SpaprVioDevice; -typedef struct SpaprVioBus SpaprVioBus; -typedef struct SpaprVioDeviceClass { +struct SpaprVioDeviceClass { DeviceClass parent_class; const char *dt_name, *dt_type, *dt_compatible; @@ -59,7 +54,7 @@ typedef struct SpaprVioDeviceClass { void (*reset)(SpaprVioDevice *dev); int (*devnode)(SpaprVioDevice *dev, void *fdt, int node_off); const char *(*get_dt_compatible)(SpaprVioDevice *dev); -} SpaprVioDeviceClass; +}; struct SpaprVioDevice { DeviceState qdev; diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h index 93d09d68deb7e8b0e03a1a0446168a2ce77c8b2f..26c8d90d7196c0983d0d6f8a0557289734433dac 100644 --- a/include/hw/ppc/spapr_xive.h +++ b/include/hw/ppc/spapr_xive.h @@ -49,6 +49,8 @@ typedef struct SpaprXive { void *tm_mmap; MemoryRegion tm_mmio_kvm; VMChangeStateEntry *change; + + uint8_t hv_prio; } SpaprXive; typedef struct SpaprXiveClass { @@ -66,7 +68,8 @@ typedef struct SpaprXiveClass { void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon); -void spapr_xive_hcall_init(SpaprMachineState *spapr); +struct SpaprMachineState; +void spapr_xive_hcall_init(struct SpaprMachineState *spapr); void spapr_xive_mmio_set_enabled(SpaprXive *xive, bool enable); void spapr_xive_map_mmio(SpaprXive *xive); @@ -80,15 +83,15 @@ int kvmppc_xive_connect(SpaprInterruptController *intc, uint32_t nr_servers, Error **errp); void kvmppc_xive_disconnect(SpaprInterruptController *intc); void kvmppc_xive_reset(SpaprXive *xive, Error **errp); -void kvmppc_xive_set_source_config(SpaprXive *xive, uint32_t lisn, XiveEAS *eas, - Error **errp); +int kvmppc_xive_set_source_config(SpaprXive *xive, uint32_t lisn, XiveEAS *eas, + Error **errp); void kvmppc_xive_sync_source(SpaprXive *xive, uint32_t lisn, Error **errp); uint64_t kvmppc_xive_esb_rw(XiveSource *xsrc, int srcno, uint32_t offset, uint64_t data, bool write); -void kvmppc_xive_set_queue_config(SpaprXive *xive, uint8_t end_blk, +int kvmppc_xive_set_queue_config(SpaprXive *xive, uint8_t end_blk, uint32_t end_idx, XiveEND *end, Error **errp); -void kvmppc_xive_get_queue_config(SpaprXive *xive, uint8_t end_blk, +int kvmppc_xive_get_queue_config(SpaprXive *xive, uint8_t end_blk, uint32_t end_idx, XiveEND *end, Error **errp); void kvmppc_xive_synchronize_state(SpaprXive *xive, Error **errp); diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h index 9ed58ec7e910dff222d414bb69dfb6723560dae6..00b80b08c272007e42bd91a321ad120138d599d3 100644 --- a/include/hw/ppc/xics.h +++ b/include/hw/ppc/xics.h @@ -30,6 +30,7 @@ #include "exec/memory.h" #include "hw/qdev-core.h" +#include "qom/object.h" #define XICS_IPI 0x2 #define XICS_BUID 0x1 @@ -40,8 +41,6 @@ * (the kernel implementation supports more but we don't exploit * that yet) */ -typedef struct ICPStateClass ICPStateClass; -typedef struct ICPState ICPState; typedef struct PnvICPState PnvICPState; typedef struct ICSStateClass ICSStateClass; typedef struct ICSState ICSState; @@ -49,15 +48,13 @@ typedef struct ICSIRQState ICSIRQState; typedef struct XICSFabric XICSFabric; #define TYPE_ICP "icp" -#define ICP(obj) OBJECT_CHECK(ICPState, (obj), TYPE_ICP) +OBJECT_DECLARE_TYPE(ICPState, ICPStateClass, + ICP) #define TYPE_PNV_ICP "pnv-icp" -#define PNV_ICP(obj) OBJECT_CHECK(PnvICPState, (obj), TYPE_PNV_ICP) +DECLARE_INSTANCE_CHECKER(PnvICPState, PNV_ICP, + TYPE_PNV_ICP) -#define ICP_CLASS(klass) \ - OBJECT_CLASS_CHECK(ICPStateClass, (klass), TYPE_ICP) -#define ICP_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ICPStateClass, (obj), TYPE_ICP) struct ICPStateClass { DeviceClass parent_class; @@ -90,12 +87,9 @@ struct PnvICPState { }; #define TYPE_ICS "ics" -#define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS) +DECLARE_OBJ_CHECKERS(ICSState, ICSStateClass, + ICS, TYPE_ICS) -#define ICS_CLASS(klass) \ - OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS) -#define ICS_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS) struct ICSStateClass { DeviceClass parent_class; @@ -145,17 +139,16 @@ struct ICSIRQState { #define TYPE_XICS_FABRIC "xics-fabric" #define XICS_FABRIC(obj) \ INTERFACE_CHECK(XICSFabric, (obj), TYPE_XICS_FABRIC) -#define XICS_FABRIC_CLASS(klass) \ - OBJECT_CLASS_CHECK(XICSFabricClass, (klass), TYPE_XICS_FABRIC) -#define XICS_FABRIC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(XICSFabricClass, (obj), TYPE_XICS_FABRIC) +typedef struct XICSFabricClass XICSFabricClass; +DECLARE_CLASS_CHECKERS(XICSFabricClass, XICS_FABRIC, + TYPE_XICS_FABRIC) -typedef struct XICSFabricClass { +struct XICSFabricClass { InterfaceClass parent; ICSState *(*ics_get)(XICSFabric *xi, int irq); void (*ics_resend)(XICSFabric *xi); ICPState *(*icp_get)(XICSFabric *xi, int server); -} XICSFabricClass; +}; ICPState *xics_icp_get(XICSFabric *xi, int server); diff --git a/include/hw/ppc/xics_spapr.h b/include/hw/ppc/xics_spapr.h index 1c65c96e3c7a9652318db823c34cb38f9c1f4d69..0b8182e40b33e07d074ba9948039f3a203e4d27c 100644 --- a/include/hw/ppc/xics_spapr.h +++ b/include/hw/ppc/xics_spapr.h @@ -28,9 +28,12 @@ #define XICS_SPAPR_H #include "hw/ppc/spapr.h" +#include "qom/object.h" #define TYPE_ICS_SPAPR "ics-spapr" -#define ICS_SPAPR(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SPAPR) +/* This is reusing the ICSState typedef from TYPE_ICS */ +DECLARE_INSTANCE_CHECKER(ICSState, ICS_SPAPR, + TYPE_ICS_SPAPR) int xics_kvm_connect(SpaprInterruptController *intc, uint32_t nr_servers, Error **errp); diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h index 705cf48176fc5031931382a0ec508848383aa9cb..445eccfe6b7326af086738de914280937a16a003 100644 --- a/include/hw/ppc/xive.h +++ b/include/hw/ppc/xive.h @@ -143,6 +143,7 @@ #include "sysemu/kvm.h" #include "hw/sysbus.h" #include "hw/ppc/xive_regs.h" +#include "qom/object.h" /* * XIVE Notifier (Interface between Source and Router) @@ -153,22 +154,21 @@ typedef struct XiveNotifier XiveNotifier; #define TYPE_XIVE_NOTIFIER "xive-notifier" #define XIVE_NOTIFIER(obj) \ INTERFACE_CHECK(XiveNotifier, (obj), TYPE_XIVE_NOTIFIER) -#define XIVE_NOTIFIER_CLASS(klass) \ - OBJECT_CLASS_CHECK(XiveNotifierClass, (klass), TYPE_XIVE_NOTIFIER) -#define XIVE_NOTIFIER_GET_CLASS(obj) \ - OBJECT_GET_CLASS(XiveNotifierClass, (obj), TYPE_XIVE_NOTIFIER) +typedef struct XiveNotifierClass XiveNotifierClass; +DECLARE_CLASS_CHECKERS(XiveNotifierClass, XIVE_NOTIFIER, + TYPE_XIVE_NOTIFIER) -typedef struct XiveNotifierClass { +struct XiveNotifierClass { InterfaceClass parent; void (*notify)(XiveNotifier *xn, uint32_t lisn); -} XiveNotifierClass; +}; /* * XIVE Interrupt Source */ #define TYPE_XIVE_SOURCE "xive-source" -#define XIVE_SOURCE(obj) OBJECT_CHECK(XiveSource, (obj), TYPE_XIVE_SOURCE) +OBJECT_DECLARE_SIMPLE_TYPE(XiveSource, XIVE_SOURCE) /* * XIVE Interrupt Source characteristics, which define how the ESB are @@ -177,7 +177,7 @@ typedef struct XiveNotifierClass { #define XIVE_SRC_H_INT_ESB 0x1 /* ESB managed with hcall H_INT_ESB */ #define XIVE_SRC_STORE_EOI 0x2 /* Store EOI supported */ -typedef struct XiveSource { +struct XiveSource { DeviceState parent; /* IRQs */ @@ -191,13 +191,14 @@ typedef struct XiveSource { uint64_t esb_flags; uint32_t esb_shift; MemoryRegion esb_mmio; + MemoryRegion esb_mmio_emulated; /* KVM support */ void *esb_mmap; MemoryRegion esb_mmio_kvm; XiveNotifier *xive; -} XiveSource; +}; /* * ESB MMIO setting. Can be one page, for both source triggering and @@ -215,6 +216,11 @@ static inline bool xive_source_esb_has_2page(XiveSource *xsrc) xsrc->esb_shift == XIVE_ESB_4K_2PAGE; } +static inline size_t xive_source_esb_len(XiveSource *xsrc) +{ + return (1ull << xsrc->esb_shift) * xsrc->nr_irqs; +} + /* The trigger page is always the first/even page */ static inline hwaddr xive_source_esb_page(XiveSource *xsrc, uint32_t srcno) { @@ -298,7 +304,7 @@ void xive_source_set_irq(void *opaque, int srcno, int val); */ #define TYPE_XIVE_TCTX "xive-tctx" -#define XIVE_TCTX(obj) OBJECT_CHECK(XiveTCTX, (obj), TYPE_XIVE_TCTX) +OBJECT_DECLARE_SIMPLE_TYPE(XiveTCTX, XIVE_TCTX) /* * XIVE Thread interrupt Management register rings : @@ -313,7 +319,7 @@ void xive_source_set_irq(void *opaque, int srcno, int val); typedef struct XivePresenter XivePresenter; -typedef struct XiveTCTX { +struct XiveTCTX { DeviceState parent_obj; CPUState *cs; @@ -323,28 +329,24 @@ typedef struct XiveTCTX { uint8_t regs[XIVE_TM_RING_COUNT * XIVE_TM_RING_SIZE]; XivePresenter *xptr; -} XiveTCTX; +}; /* * XIVE Router */ typedef struct XiveFabric XiveFabric; -typedef struct XiveRouter { +struct XiveRouter { SysBusDevice parent; XiveFabric *xfb; -} XiveRouter; +}; #define TYPE_XIVE_ROUTER "xive-router" -#define XIVE_ROUTER(obj) \ - OBJECT_CHECK(XiveRouter, (obj), TYPE_XIVE_ROUTER) -#define XIVE_ROUTER_CLASS(klass) \ - OBJECT_CLASS_CHECK(XiveRouterClass, (klass), TYPE_XIVE_ROUTER) -#define XIVE_ROUTER_GET_CLASS(obj) \ - OBJECT_GET_CLASS(XiveRouterClass, (obj), TYPE_XIVE_ROUTER) - -typedef struct XiveRouterClass { +OBJECT_DECLARE_TYPE(XiveRouter, XiveRouterClass, + XIVE_ROUTER) + +struct XiveRouterClass { SysBusDeviceClass parent; /* XIVE table accessors */ @@ -359,7 +361,7 @@ typedef struct XiveRouterClass { int (*write_nvt)(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, XiveNVT *nvt, uint8_t word_number); uint8_t (*get_block_id)(XiveRouter *xrtr); -} XiveRouterClass; +}; int xive_router_get_eas(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx, XiveEAS *eas); @@ -385,18 +387,18 @@ typedef struct XiveTCTXMatch { #define TYPE_XIVE_PRESENTER "xive-presenter" #define XIVE_PRESENTER(obj) \ INTERFACE_CHECK(XivePresenter, (obj), TYPE_XIVE_PRESENTER) -#define XIVE_PRESENTER_CLASS(klass) \ - OBJECT_CLASS_CHECK(XivePresenterClass, (klass), TYPE_XIVE_PRESENTER) -#define XIVE_PRESENTER_GET_CLASS(obj) \ - OBJECT_GET_CLASS(XivePresenterClass, (obj), TYPE_XIVE_PRESENTER) +typedef struct XivePresenterClass XivePresenterClass; +DECLARE_CLASS_CHECKERS(XivePresenterClass, XIVE_PRESENTER, + TYPE_XIVE_PRESENTER) -typedef struct XivePresenterClass { +struct XivePresenterClass { InterfaceClass parent; int (*match_nvt)(XivePresenter *xptr, uint8_t format, uint8_t nvt_blk, uint32_t nvt_idx, bool cam_ignore, uint8_t priority, uint32_t logic_serv, XiveTCTXMatch *match); -} XivePresenterClass; + bool (*in_kernel)(const XivePresenter *xptr); +}; int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx, uint8_t format, @@ -410,28 +412,26 @@ int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx, #define TYPE_XIVE_FABRIC "xive-fabric" #define XIVE_FABRIC(obj) \ INTERFACE_CHECK(XiveFabric, (obj), TYPE_XIVE_FABRIC) -#define XIVE_FABRIC_CLASS(klass) \ - OBJECT_CLASS_CHECK(XiveFabricClass, (klass), TYPE_XIVE_FABRIC) -#define XIVE_FABRIC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(XiveFabricClass, (obj), TYPE_XIVE_FABRIC) +typedef struct XiveFabricClass XiveFabricClass; +DECLARE_CLASS_CHECKERS(XiveFabricClass, XIVE_FABRIC, + TYPE_XIVE_FABRIC) -typedef struct XiveFabricClass { +struct XiveFabricClass { InterfaceClass parent; int (*match_nvt)(XiveFabric *xfb, uint8_t format, uint8_t nvt_blk, uint32_t nvt_idx, bool cam_ignore, uint8_t priority, uint32_t logic_serv, XiveTCTXMatch *match); -} XiveFabricClass; +}; /* * XIVE END ESBs */ #define TYPE_XIVE_END_SOURCE "xive-end-source" -#define XIVE_END_SOURCE(obj) \ - OBJECT_CHECK(XiveENDSource, (obj), TYPE_XIVE_END_SOURCE) +OBJECT_DECLARE_SIMPLE_TYPE(XiveENDSource, XIVE_END_SOURCE) -typedef struct XiveENDSource { +struct XiveENDSource { DeviceState parent; uint32_t nr_ends; @@ -441,7 +441,7 @@ typedef struct XiveENDSource { MemoryRegion esb_mmio; XiveRouter *xrtr; -} XiveENDSource; +}; /* * For legacy compatibility, the exceptions define up to 256 different @@ -480,9 +480,9 @@ void xive_tctx_ipb_update(XiveTCTX *tctx, uint8_t ring, uint8_t ipb); int kvmppc_xive_source_reset_one(XiveSource *xsrc, int srcno, Error **errp); void kvmppc_xive_source_set_irq(void *opaque, int srcno, int val); -void kvmppc_xive_cpu_connect(XiveTCTX *tctx, Error **errp); -void kvmppc_xive_cpu_synchronize_state(XiveTCTX *tctx, Error **errp); -void kvmppc_xive_cpu_get_state(XiveTCTX *tctx, Error **errp); -void kvmppc_xive_cpu_set_state(XiveTCTX *tctx, Error **errp); +int kvmppc_xive_cpu_connect(XiveTCTX *tctx, Error **errp); +int kvmppc_xive_cpu_synchronize_state(XiveTCTX *tctx, Error **errp); +int kvmppc_xive_cpu_get_state(XiveTCTX *tctx, Error **errp); +int kvmppc_xive_cpu_set_state(XiveTCTX *tctx, Error **errp); #endif /* PPC_XIVE_H */ diff --git a/include/hw/ppc/xive_regs.h b/include/hw/ppc/xive_regs.h index 09f243600c5dca9cb2f8f4a1c55e038c261fbd0d..7879692825934fb0eeb2c823d9b8c28c0a78638b 100644 --- a/include/hw/ppc/xive_regs.h +++ b/include/hw/ppc/xive_regs.h @@ -71,7 +71,7 @@ * QW word 2 contains the valid bit at the top and other fields * depending on the QW. */ -#define TM_WORD2 0x8 +#define TM_WORD2 0x8 #define TM_QW0W2_VU PPC_BIT32(0) #define TM_QW0W2_LOGIC_SERV PPC_BITMASK32(1, 31) /* XX 2,31 ? */ #define TM_QW1W2_VO PPC_BIT32(0) diff --git a/include/hw/qdev-clock.h b/include/hw/qdev-clock.h index a340f65ff9091d2f70772dda9bd73e7fbf959c8b..64ca4d266f2205b1ff4091b1b5bceabb7595f381 100644 --- a/include/hw/qdev-clock.h +++ b/include/hw/qdev-clock.h @@ -70,12 +70,10 @@ Clock *qdev_get_clock_out(DeviceState *dev, const char *name); * * Set the source clock of input clock @name of device @dev to @source. * @source period update will be propagated to @name clock. + * + * Must be called before @dev is realized. */ -static inline void qdev_connect_clock_in(DeviceState *dev, const char *name, - Clock *source) -{ - clock_set_source(qdev_get_clock_in(dev, name), source); -} +void qdev_connect_clock_in(DeviceState *dev, const char *name, Clock *source); /** * qdev_alias_clock: diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index b870b279661af20346c02662617dfb29bdc5403f..5e737195b59f2dc8beeaa95b5a5623b5574f72a8 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -3,6 +3,8 @@ #include "qemu/queue.h" #include "qemu/bitmap.h" +#include "qemu/rcu.h" +#include "qemu/rcu_queue.h" #include "qom/object.h" #include "hw/hotplug.h" #include "hw/resettable.h" @@ -12,9 +14,7 @@ enum { }; #define TYPE_DEVICE "device" -#define DEVICE(obj) OBJECT_CHECK(DeviceState, (obj), TYPE_DEVICE) -#define DEVICE_CLASS(klass) OBJECT_CLASS_CHECK(DeviceClass, (klass), TYPE_DEVICE) -#define DEVICE_GET_CLASS(obj) OBJECT_GET_CLASS(DeviceClass, (obj), TYPE_DEVICE) +OBJECT_DECLARE_TYPE(DeviceState, DeviceClass, DEVICE) typedef enum DeviceCategory { DEVICE_CATEGORY_BRIDGE, @@ -57,7 +57,7 @@ typedef void (*BusUnrealize)(BusState *bus); * After successful realization, setting static properties will fail. * * As an interim step, the #DeviceState:realized property can also be - * set with qdev_init_nofail(). + * set with qdev_realize(). * In the future, devices will propagate this state change to their children * and along busses they expose. * The point in time will be deferred to machine creation, so that values @@ -93,7 +93,7 @@ typedef void (*BusUnrealize)(BusState *bus); * until it was marked don't hide and qdev_device_add called again. * */ -typedef struct DeviceClass { +struct DeviceClass { /*< private >*/ ObjectClass parent_class; /*< public >*/ @@ -137,7 +137,7 @@ typedef struct DeviceClass { /* Private to qdev / bus. */ const char *bus_type; -} DeviceClass; +}; typedef struct NamedGPIOList NamedGPIOList; @@ -163,6 +163,8 @@ struct NamedClockList { /** * DeviceState: * @realized: Indicates whether the device has been fully constructed. + * When accessed outside big qemu lock, must be accessed with + * qatomic_load_acquire() * @reset: ResettableState for the device; handled by Resettable interface. * * This structure should not be accessed directly. We declare it here @@ -203,9 +205,8 @@ struct DeviceListener { }; #define TYPE_BUS "bus" -#define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS) -#define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS) -#define BUS_GET_CLASS(obj) OBJECT_GET_CLASS(BusClass, (obj), TYPE_BUS) +DECLARE_OBJ_CHECKERS(BusState, BusClass, + BUS, TYPE_BUS) struct BusClass { ObjectClass parent_class; @@ -213,13 +214,24 @@ struct BusClass { /* FIXME first arg should be BusState */ void (*print_dev)(Monitor *mon, DeviceState *dev, int indent); char *(*get_dev_path)(DeviceState *dev); + /* * This callback is used to create Open Firmware device path in accordance * with OF spec http://forthworks.com/standards/of1275.pdf. Individual bus * bindings can be found at http://playground.sun.com/1275/bindings/. */ char *(*get_fw_dev_path)(DeviceState *dev); + void (*reset)(BusState *bus); + + /* + * Return whether the device can be added to @bus, + * based on the address that was set (via device properties) + * before realize. If not, on return @errp contains the + * human-readable error message. + */ + bool (*check_address)(BusState *bus, DeviceState *dev, Error **errp); + BusRealize realize; BusUnrealize unrealize; @@ -230,6 +242,7 @@ struct BusClass { }; typedef struct BusChild { + struct rcu_head rcu; DeviceState *child; int index; QTAILQ_ENTRY(BusChild) sibling; @@ -250,6 +263,12 @@ struct BusState { int max_index; bool realized; int num_children; + + /* + * children is a RCU QTAILQ, thus readers must use RCU to access it, + * and writers must hold the big qemu lock + */ + QTAILQ_HEAD(, BusChild) children; QLIST_ENTRY(BusState) sibling; ResettableState reset; @@ -320,9 +339,87 @@ compat_props_add(GPtrArray *arr, /*** Board API. This should go away once we have a machine config file. ***/ -DeviceState *qdev_create(BusState *bus, const char *name); -DeviceState *qdev_try_create(BusState *bus, const char *name); -void qdev_init_nofail(DeviceState *dev); +/** + * qdev_new: Create a device on the heap + * @name: device type to create (we assert() that this type exists) + * + * This only allocates the memory and initializes the device state + * structure, ready for the caller to set properties if they wish. + * The device still needs to be realized. + * The returned object has a reference count of 1. + */ +DeviceState *qdev_new(const char *name); +/** + * qdev_try_new: Try to create a device on the heap + * @name: device type to create + * + * This is like qdev_new(), except it returns %NULL when type @name + * does not exist, rather than asserting. + */ +DeviceState *qdev_try_new(const char *name); +/** + * qdev_realize: Realize @dev. + * @dev: device to realize + * @bus: bus to plug it into (may be NULL) + * @errp: pointer to error object + * + * "Realize" the device, i.e. perform the second phase of device + * initialization. + * @dev must not be plugged into a bus already. + * If @bus, plug @dev into @bus. This takes a reference to @dev. + * If @dev has no QOM parent, make one up, taking another reference. + * On success, return true. + * On failure, store an error through @errp and return false. + * + * If you created @dev using qdev_new(), you probably want to use + * qdev_realize_and_unref() instead. + */ +bool qdev_realize(DeviceState *dev, BusState *bus, Error **errp); +/** + * qdev_realize_and_unref: Realize @dev and drop a reference + * @dev: device to realize + * @bus: bus to plug it into (may be NULL) + * @errp: pointer to error object + * + * Realize @dev and drop a reference. + * This is like qdev_realize(), except the caller must hold a + * (private) reference, which is dropped on return regardless of + * success or failure. Intended use:: + * + * dev = qdev_new(); + * [...] + * qdev_realize_and_unref(dev, bus, errp); + * + * Now @dev can go away without further ado. + * + * If you are embedding the device into some other QOM device and + * initialized it via some variant on object_initialize_child() then + * do not use this function, because that family of functions arrange + * for the only reference to the child device to be held by the parent + * via the child<> property, and so the reference-count-drop done here + * would be incorrect. For that use case you want qdev_realize(). + */ +bool qdev_realize_and_unref(DeviceState *dev, BusState *bus, Error **errp); +/** + * qdev_unrealize: Unrealize a device + * @dev: device to unrealize + * + * This function will "unrealize" a device, which is the first phase + * of correctly destroying a device that has been realized. It will: + * + * - unrealize any child buses by calling qbus_unrealize() + * (this will recursively unrealize any devices on those buses) + * - call the the unrealize method of @dev + * + * The device can then be freed by causing its reference count to go + * to zero. + * + * Warning: most devices in QEMU do not expect to be unrealized. Only + * devices which are hot-unpluggable should be unrealized (as part of + * the unplugging process); all other devices are expected to last for + * the life of the simulation and should not be unrealized and freed. + */ +void qdev_unrealize(DeviceState *dev); void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, int required_for_version); HotplugHandler *qdev_get_bus_hotplug_handler(DeviceState *dev); @@ -346,13 +443,148 @@ void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, void qdev_machine_creation_done(void); bool qdev_machine_modified(void); +/** + * GpioPolarity: Polarity of a GPIO line + * + * GPIO lines use either positive (active-high) logic, + * or negative (active-low) logic. + * + * In active-high logic (%GPIO_POLARITY_ACTIVE_HIGH), a pin is + * active when the voltage on the pin is high (relative to ground); + * whereas in active-low logic (%GPIO_POLARITY_ACTIVE_LOW), a pin + * is active when the voltage on the pin is low (or grounded). + */ +typedef enum { + GPIO_POLARITY_ACTIVE_LOW, + GPIO_POLARITY_ACTIVE_HIGH +} GpioPolarity; + +/** + * qdev_get_gpio_in: Get one of a device's anonymous input GPIO lines + * @dev: Device whose GPIO we want + * @n: Number of the anonymous GPIO line (which must be in range) + * + * Returns the qemu_irq corresponding to an anonymous input GPIO line + * (which the device has set up with qdev_init_gpio_in()). The index + * @n of the GPIO line must be valid (i.e. be at least 0 and less than + * the total number of anonymous input GPIOs the device has); this + * function will assert() if passed an invalid index. + * + * This function is intended to be used by board code or SoC "container" + * device models to wire up the GPIO lines; usually the return value + * will be passed to qdev_connect_gpio_out() or a similar function to + * connect another device's output GPIO line to this input. + * + * For named input GPIO lines, use qdev_get_gpio_in_named(). + */ qemu_irq qdev_get_gpio_in(DeviceState *dev, int n); +/** + * qdev_get_gpio_in_named: Get one of a device's named input GPIO lines + * @dev: Device whose GPIO we want + * @name: Name of the input GPIO array + * @n: Number of the GPIO line in that array (which must be in range) + * + * Returns the qemu_irq corresponding to a named input GPIO line + * (which the device has set up with qdev_init_gpio_in_named()). + * The @name string must correspond to an input GPIO array which exists on + * the device, and the index @n of the GPIO line must be valid (i.e. + * be at least 0 and less than the total number of input GPIOs in that + * array); this function will assert() if passed an invalid name or index. + * + * For anonymous input GPIO lines, use qdev_get_gpio_in(). + */ qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n); +/** + * qdev_connect_gpio_out: Connect one of a device's anonymous output GPIO lines + * @dev: Device whose GPIO to connect + * @n: Number of the anonymous output GPIO line (which must be in range) + * @pin: qemu_irq to connect the output line to + * + * This function connects an anonymous output GPIO line on a device + * up to an arbitrary qemu_irq, so that when the device asserts that + * output GPIO line, the qemu_irq's callback is invoked. + * The index @n of the GPIO line must be valid (i.e. be at least 0 and + * less than the total number of anonymous output GPIOs the device has + * created with qdev_init_gpio_out()); otherwise this function will assert(). + * + * Outbound GPIO lines can be connected to any qemu_irq, but the common + * case is connecting them to another device's inbound GPIO line, using + * the qemu_irq returned by qdev_get_gpio_in() or qdev_get_gpio_in_named(). + * + * It is not valid to try to connect one outbound GPIO to multiple + * qemu_irqs at once, or to connect multiple outbound GPIOs to the + * same qemu_irq. (Warning: there is no assertion or other guard to + * catch this error: the model will just not do the right thing.) + * Instead, for fan-out you can use the TYPE_IRQ_SPLIT device: connect + * a device's outbound GPIO to the splitter's input, and connect each + * of the splitter's outputs to a different device. For fan-in you + * can use the TYPE_OR_IRQ device, which is a model of a logical OR + * gate with multiple inputs and one output. + * + * For named output GPIO lines, use qdev_connect_gpio_out_named(). + */ void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); +/** + * qdev_connect_gpio_out: Connect one of a device's anonymous output GPIO lines + * @dev: Device whose GPIO to connect + * @name: Name of the output GPIO array + * @n: Number of the anonymous output GPIO line (which must be in range) + * @pin: qemu_irq to connect the output line to + * + * This function connects an anonymous output GPIO line on a device + * up to an arbitrary qemu_irq, so that when the device asserts that + * output GPIO line, the qemu_irq's callback is invoked. + * The @name string must correspond to an output GPIO array which exists on + * the device, and the index @n of the GPIO line must be valid (i.e. + * be at least 0 and less than the total number of input GPIOs in that + * array); this function will assert() if passed an invalid name or index. + * + * Outbound GPIO lines can be connected to any qemu_irq, but the common + * case is connecting them to another device's inbound GPIO line, using + * the qemu_irq returned by qdev_get_gpio_in() or qdev_get_gpio_in_named(). + * + * It is not valid to try to connect one outbound GPIO to multiple + * qemu_irqs at once, or to connect multiple outbound GPIOs to the + * same qemu_irq; see qdev_connect_gpio_out() for details. + * + * For named output GPIO lines, use qdev_connect_gpio_out_named(). + */ void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, qemu_irq pin); +/** + * qdev_get_gpio_out_connector: Get the qemu_irq connected to an output GPIO + * @dev: Device whose output GPIO we are interested in + * @name: Name of the output GPIO array + * @n: Number of the output GPIO line within that array + * + * Returns whatever qemu_irq is currently connected to the specified + * output GPIO line of @dev. This will be NULL if the output GPIO line + * has never been wired up to the anything. Note that the qemu_irq + * returned does not belong to @dev -- it will be the input GPIO or + * IRQ of whichever device the board code has connected up to @dev's + * output GPIO. + * + * You probably don't need to use this function -- it is used only + * by the platform-bus subsystem. + */ qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int n); +/** + * qdev_intercept_gpio_out: Intercept an existing GPIO connection + * @dev: Device to intercept the outbound GPIO line from + * @icpt: New qemu_irq to connect instead + * @name: Name of the output GPIO array + * @n: Number of the GPIO line in the array + * + * This function is provided only for use by the qtest testing framework + * and is not suitable for use in non-testing parts of QEMU. + * + * This function breaks an existing connection of an outbound GPIO + * line from @dev, and replaces it with the new qemu_irq @icpt, as if + * ``qdev_connect_gpio_out_named(dev, icpt, name, n)`` had been called. + * The previously connected qemu_irq is returned, so it can be restored + * by a second call to qdev_intercept_gpio_out() if desired. + */ qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt, const char *name, int n); @@ -360,10 +592,59 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name); /*** Device API. ***/ -/* Register device properties. */ -/* GPIO inputs also double as IRQ sinks. */ +/** + * qdev_init_gpio_in: create an array of anonymous input GPIO lines + * @dev: Device to create input GPIOs for + * @handler: Function to call when GPIO line value is set + * @n: Number of GPIO lines to create + * + * Devices should use functions in the qdev_init_gpio_in* family in + * their instance_init or realize methods to create any input GPIO + * lines they need. There is no functional difference between + * anonymous and named GPIO lines. Stylistically, named GPIOs are + * preferable (easier to understand at callsites) unless a device + * has exactly one uniform kind of GPIO input whose purpose is obvious. + * Note that input GPIO lines can serve as 'sinks' for IRQ lines. + * + * See qdev_get_gpio_in() for how code that uses such a device can get + * hold of an input GPIO line to manipulate it. + */ void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n); +/** + * qdev_init_gpio_out: create an array of anonymous output GPIO lines + * @dev: Device to create output GPIOs for + * @pins: Pointer to qemu_irq or qemu_irq array for the GPIO lines + * @n: Number of GPIO lines to create + * + * Devices should use functions in the qdev_init_gpio_out* family + * in their instance_init or realize methods to create any output + * GPIO lines they need. There is no functional difference between + * anonymous and named GPIO lines. Stylistically, named GPIOs are + * preferable (easier to understand at callsites) unless a device + * has exactly one uniform kind of GPIO output whose purpose is obvious. + * + * The @pins argument should be a pointer to either a "qemu_irq" + * (if @n == 1) or a "qemu_irq []" array (if @n > 1) in the device's + * state structure. The device implementation can then raise and + * lower the GPIO line by calling qemu_set_irq(). (If anything is + * connected to the other end of the GPIO this will cause the handler + * function for that input GPIO to be called.) + * + * See qdev_connect_gpio_out() for how code that uses such a device + * can connect to one of its output GPIO lines. + */ void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n); +/** + * qdev_init_gpio_out: create an array of named output GPIO lines + * @dev: Device to create output GPIOs for + * @pins: Pointer to qemu_irq or qemu_irq array for the GPIO lines + * @name: Name to give this array of GPIO lines + * @n: Number of GPIO lines to create + * + * Like qdev_init_gpio_out(), but creates an array of GPIO output lines + * with a name. Code using the device can then connect these GPIO lines + * using qdev_connect_gpio_out_named(). + */ void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, const char *name, int n); /** @@ -395,6 +676,25 @@ static inline void qdev_init_gpio_in_named(DeviceState *dev, qdev_init_gpio_in_named_with_opaque(dev, handler, dev, name, n); } +/** + * qdev_pass_gpios: create GPIO lines on container which pass through to device + * @dev: Device which has GPIO lines + * @container: Container device which needs to expose them + * @name: Name of GPIO array to pass through (NULL for the anonymous GPIO array) + * + * In QEMU, complicated devices like SoCs are often modelled with a + * "container" QOM device which itself contains other QOM devices and + * which wires them up appropriately. This function allows the container + * to create GPIO arrays on itself which simply pass through to a GPIO + * array of one of its internal devices. + * + * If @dev has both input and output GPIOs named @name then both will + * be passed through. It is not possible to pass a subset of the array + * with this function. + * + * To users of the container device, the GPIO array created on @container + * behaves exactly like any other. + */ void qdev_pass_gpios(DeviceState *dev, DeviceState *container, const char *name); @@ -411,6 +711,9 @@ typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque); void qbus_create_inplace(void *bus, size_t size, const char *typename, DeviceState *parent, const char *name); BusState *qbus_create(const char *typename, DeviceState *parent, const char *name); +bool qbus_realize(BusState *bus, Error **errp); +void qbus_unrealize(BusState *bus); + /* Returns > 0 if either devfn or busfn skip walk somewhere in cursion, * < 0 if either devfn or busfn terminate walk somewhere in cursion, * 0 otherwise. */ @@ -523,16 +826,15 @@ const char *qdev_fw_name(DeviceState *dev); Object *qdev_get_machine(void); /* FIXME: make this a link<> */ -void qdev_set_parent_bus(DeviceState *dev, BusState *bus); +bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp); extern bool qdev_hotplug; extern bool qdev_hot_removed; char *qdev_get_dev_path(DeviceState *dev); -void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp); - -void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp); +void qbus_set_hotplug_handler(BusState *bus, Object *handler); +void qbus_set_bus_hotplug_handler(BusState *bus); static inline bool qbus_is_hotpluggable(BusState *bus) { diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index f161604fb6b3a4f00363c055af523e1959048c92..44374500659d4964368d7a7be6153ca89cc6be5b 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -8,6 +8,7 @@ extern const PropertyInfo qdev_prop_bit; extern const PropertyInfo qdev_prop_bit64; extern const PropertyInfo qdev_prop_bool; +extern const PropertyInfo qdev_prop_enum; extern const PropertyInfo qdev_prop_uint8; extern const PropertyInfo qdev_prop_uint16; extern const PropertyInfo qdev_prop_uint32; @@ -19,6 +20,7 @@ extern const PropertyInfo qdev_prop_string; extern const PropertyInfo qdev_prop_chr; extern const PropertyInfo qdev_prop_tpm; extern const PropertyInfo qdev_prop_macaddr; +extern const PropertyInfo qdev_prop_reserved_region; extern const PropertyInfo qdev_prop_on_off_auto; extern const PropertyInfo qdev_prop_multifd_compression; extern const PropertyInfo qdev_prop_losttickpolicy; @@ -29,6 +31,7 @@ extern const PropertyInfo qdev_prop_drive; extern const PropertyInfo qdev_prop_drive_iothread; extern const PropertyInfo qdev_prop_netdev; extern const PropertyInfo qdev_prop_pci_devfn; +extern const PropertyInfo qdev_prop_size32; extern const PropertyInfo qdev_prop_blocksize; extern const PropertyInfo qdev_prop_pci_host_devaddr; extern const PropertyInfo qdev_prop_uuid; @@ -183,6 +186,8 @@ extern const PropertyInfo qdev_prop_pcie_link_width; DEFINE_PROP(_n, _s, _f, qdev_prop_drive_iothread, BlockBackend *) #define DEFINE_PROP_MACADDR(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr) +#define DEFINE_PROP_RESERVED_REGION(_n, _s, _f) \ + DEFINE_PROP(_n, _s, _f, qdev_prop_reserved_region, ReservedRegion) #define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_on_off_auto, OnOffAuto) #define DEFINE_PROP_MULTIFD_COMPRESSION(_n, _s, _f, _d) \ @@ -196,8 +201,10 @@ extern const PropertyInfo qdev_prop_pcie_link_width; BlockdevOnError) #define DEFINE_PROP_BIOS_CHS_TRANS(_n, _s, _f, _d) \ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int) +#define DEFINE_PROP_SIZE32(_n, _s, _f, _d) \ + DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_size32, uint32_t) #define DEFINE_PROP_BLOCKSIZE(_n, _s, _f) \ - DEFINE_PROP_UNSIGNED(_n, _s, _f, 0, qdev_prop_blocksize, uint16_t) + DEFINE_PROP_UNSIGNED(_n, _s, _f, 0, qdev_prop_blocksize, uint32_t) #define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress) #define DEFINE_PROP_OFF_AUTO_PCIBAR(_n, _s, _f, _d) \ @@ -230,8 +237,18 @@ extern const PropertyInfo qdev_prop_pcie_link_width; #define DEFINE_PROP_END_OF_LIST() \ {} -/* Set properties between creation and init. */ -void *qdev_get_prop_ptr(DeviceState *dev, Property *prop); +/* + * Set properties between creation and realization. + * + * Returns: %true on success, %false on error. + */ +bool qdev_prop_set_drive_err(DeviceState *dev, const char *name, + BlockBackend *value, Error **errp); + +/* + * Set properties between creation and realization. + * @value must be valid. Each property may be set at most once. + */ void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value); void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value); void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value); @@ -242,12 +259,16 @@ void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value) void qdev_prop_set_chr(DeviceState *dev, const char *name, Chardev *value); void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value); void qdev_prop_set_drive(DeviceState *dev, const char *name, - BlockBackend *value, Error **errp); + BlockBackend *value); void qdev_prop_set_macaddr(DeviceState *dev, const char *name, const uint8_t *value); void qdev_prop_set_enum(DeviceState *dev, const char *name, int value); +void *qdev_get_prop_ptr(DeviceState *dev, Property *prop); + void qdev_prop_register_global(GlobalProperty *prop); +const GlobalProperty *qdev_find_global_prop(DeviceState *dev, + const char *name); int qdev_prop_check_globals(void); void qdev_prop_set_globals(DeviceState *dev); void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, @@ -264,6 +285,19 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, */ void qdev_property_add_static(DeviceState *dev, Property *prop); +/** + * qdev_alias_all_properties: Create aliases on source for all target properties + * @target: Device which has properties to be aliased + * @source: Object to add alias properties to + * + * Add alias properties to the @source object for all qdev properties on + * the @target DeviceState. + * + * This is useful when @target is an internal implementation object + * owned by @source, and you want to expose all the properties of that + * implementation object as properties on the @source object so that users + * of @source can set them. + */ void qdev_alias_all_properties(DeviceState *target, Object *source); /** diff --git a/include/hw/rdma/rdma.h b/include/hw/rdma/rdma.h index 68290fb58cc80d72f0d93d90029b2f2d7f5c30d0..e77e43a1709f7cce96f47834707f448dcbc4fb94 100644 --- a/include/hw/rdma/rdma.h +++ b/include/hw/rdma/rdma.h @@ -19,22 +19,19 @@ #define INTERFACE_RDMA_PROVIDER "rdma" -#define INTERFACE_RDMA_PROVIDER_CLASS(klass) \ - OBJECT_CLASS_CHECK(RdmaProviderClass, (klass), \ +typedef struct RdmaProviderClass RdmaProviderClass; +DECLARE_CLASS_CHECKERS(RdmaProviderClass, RDMA_PROVIDER, INTERFACE_RDMA_PROVIDER) -#define RDMA_PROVIDER_GET_CLASS(obj) \ - OBJECT_GET_CLASS(RdmaProviderClass, (obj), \ - INTERFACE_RDMA_PROVIDER) #define RDMA_PROVIDER(obj) \ INTERFACE_CHECK(RdmaProvider, (obj), \ INTERFACE_RDMA_PROVIDER) typedef struct RdmaProvider RdmaProvider; -typedef struct RdmaProviderClass { +struct RdmaProviderClass { InterfaceClass parent; void (*print_statistics)(Monitor *mon, RdmaProvider *obj); -} RdmaProviderClass; +}; #endif diff --git a/include/hw/register.h b/include/hw/register.h index 5d2c565ae02eb3d776f97ffadd0af7efcf27f545..03c8926d275acb95bdc9ad8f5b6869a817939e69 100644 --- a/include/hw/register.h +++ b/include/hw/register.h @@ -14,6 +14,7 @@ #include "hw/qdev-core.h" #include "exec/memory.h" #include "hw/registerfields.h" +#include "qom/object.h" typedef struct RegisterInfo RegisterInfo; typedef struct RegisterAccessInfo RegisterAccessInfo; @@ -87,7 +88,8 @@ struct RegisterInfo { }; #define TYPE_REGISTER "qemu,register" -#define REGISTER(obj) OBJECT_CHECK(RegisterInfo, (obj), TYPE_REGISTER) +DECLARE_INSTANCE_CHECKER(RegisterInfo, REGISTER, + TYPE_REGISTER) /** * This structure is used to group all of the individual registers which are @@ -181,6 +183,7 @@ uint64_t register_read_memory(void *opaque, hwaddr addr, unsigned size); * @data: Array to use for register data, must already be allocated * @ops: Memory region ops to access registers. * @debug enabled: turn on/off verbose debug information + * @memory_size: Size of the memory region * returns: A structure containing all of the registers and an initialized * memory region (r_array->mem) the caller should add to a container. */ diff --git a/include/hw/registerfields.h b/include/hw/registerfields.h index 0407edb7ecf95fe292313260ad6692d2e345d9ee..93fa4a84c22b363dc552be0f114c7c3f1e020534 100644 --- a/include/hw/registerfields.h +++ b/include/hw/registerfields.h @@ -66,35 +66,35 @@ #define FIELD_DP8(storage, reg, field, val) ({ \ struct { \ unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \ - } v = { .v = val }; \ - uint8_t d; \ - d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ - R_ ## reg ## _ ## field ## _LENGTH, v.v); \ - d; }) + } _v = { .v = val }; \ + uint8_t _d; \ + _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ + R_ ## reg ## _ ## field ## _LENGTH, _v.v); \ + _d; }) #define FIELD_DP16(storage, reg, field, val) ({ \ struct { \ unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \ - } v = { .v = val }; \ - uint16_t d; \ - d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ - R_ ## reg ## _ ## field ## _LENGTH, v.v); \ - d; }) + } _v = { .v = val }; \ + uint16_t _d; \ + _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ + R_ ## reg ## _ ## field ## _LENGTH, _v.v); \ + _d; }) #define FIELD_DP32(storage, reg, field, val) ({ \ struct { \ unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \ - } v = { .v = val }; \ - uint32_t d; \ - d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ - R_ ## reg ## _ ## field ## _LENGTH, v.v); \ - d; }) + } _v = { .v = val }; \ + uint32_t _d; \ + _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ + R_ ## reg ## _ ## field ## _LENGTH, _v.v); \ + _d; }) #define FIELD_DP64(storage, reg, field, val) ({ \ struct { \ unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \ - } v = { .v = val }; \ - uint64_t d; \ - d = deposit64((storage), R_ ## reg ## _ ## field ## _SHIFT, \ - R_ ## reg ## _ ## field ## _LENGTH, v.v); \ - d; }) + } _v = { .v = val }; \ + uint64_t _d; \ + _d = deposit64((storage), R_ ## reg ## _ ## field ## _SHIFT, \ + R_ ## reg ## _ ## field ## _LENGTH, _v.v); \ + _d; }) /* Deposit a field to array of registers. */ #define ARRAY_FIELD_DP32(regs, reg, field, val) \ diff --git a/include/hw/resettable.h b/include/hw/resettable.h index f4c4bab0effb761f2ccd6ba1c97fde446ad42e96..bdcd1276b695ad648f641ae7e9c747189710a38d 100644 --- a/include/hw/resettable.h +++ b/include/hw/resettable.h @@ -17,11 +17,10 @@ #define TYPE_RESETTABLE_INTERFACE "resettable" -#define RESETTABLE_CLASS(class) \ - OBJECT_CLASS_CHECK(ResettableClass, (class), TYPE_RESETTABLE_INTERFACE) +typedef struct ResettableClass ResettableClass; +DECLARE_CLASS_CHECKERS(ResettableClass, RESETTABLE, + TYPE_RESETTABLE_INTERFACE) -#define RESETTABLE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ResettableClass, (obj), TYPE_RESETTABLE_INTERFACE) typedef struct ResettableState ResettableState; @@ -119,7 +118,7 @@ typedef struct ResettablePhases { ResettableHoldPhase hold; ResettableExitPhase exit; } ResettablePhases; -typedef struct ResettableClass { +struct ResettableClass { InterfaceClass parent_class; /* Phase methods */ @@ -133,7 +132,7 @@ typedef struct ResettableClass { /* Hierarchy handling method */ ResettableChildForeach child_foreach; -} ResettableClass; +}; /** * ResettableState: diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h index 474a940ad5289c87418aff333cf0d438dabf6b33..0b019887274da86cfc6ce6da713bf396df0e2553 100644 --- a/include/hw/riscv/boot.h +++ b/include/hw/riscv/boot.h @@ -21,18 +21,31 @@ #define RISCV_BOOT_H #include "exec/cpu-defs.h" +#include "hw/loader.h" -void riscv_find_and_load_firmware(MachineState *machine, - const char *default_machine_firmware, - hwaddr firmware_load_addr, - symbol_fn_t sym_cb); +bool riscv_is_32_bit(MachineState *machine); + +target_ulong riscv_calc_kernel_start_addr(MachineState *machine, + target_ulong firmware_end_addr); +target_ulong riscv_find_and_load_firmware(MachineState *machine, + const char *default_machine_firmware, + hwaddr firmware_load_addr, + symbol_fn_t sym_cb); char *riscv_find_firmware(const char *firmware_filename); target_ulong riscv_load_firmware(const char *firmware_filename, hwaddr firmware_load_addr, symbol_fn_t sym_cb); target_ulong riscv_load_kernel(const char *kernel_filename, + target_ulong firmware_end_addr, symbol_fn_t sym_cb); hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size, uint64_t kernel_entry, hwaddr *start); +uint32_t riscv_load_fdt(hwaddr dram_start, uint64_t dram_size, void *fdt); +void riscv_setup_rom_reset_vec(hwaddr saddr, hwaddr rom_base, + hwaddr rom_size, uint64_t kernel_entry, + uint32_t fdt_load_addr, void *fdt); +void riscv_rom_copy_firmware_info(hwaddr rom_base, hwaddr rom_size, + uint32_t reset_vec_size, + uint64_t kernel_entry); #endif /* RISCV_BOOT_H */ diff --git a/include/hw/riscv/boot_opensbi.h b/include/hw/riscv/boot_opensbi.h new file mode 100644 index 0000000000000000000000000000000000000000..0d5ddd6c3daf66f8ed342d729582793f082ca28b --- /dev/null +++ b/include/hw/riscv/boot_opensbi.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Based on include/sbi/{fw_dynamic.h,sbi_scratch.h} from the OpenSBI project. + */ +#ifndef OPENSBI_H +#define OPENSBI_H + +/** Expected value of info magic ('OSBI' ascii string in hex) */ +#define FW_DYNAMIC_INFO_MAGIC_VALUE 0x4942534f + +/** Maximum supported info version */ +#define FW_DYNAMIC_INFO_VERSION 0x2 + +/** Possible next mode values */ +#define FW_DYNAMIC_INFO_NEXT_MODE_U 0x0 +#define FW_DYNAMIC_INFO_NEXT_MODE_S 0x1 +#define FW_DYNAMIC_INFO_NEXT_MODE_M 0x3 + +enum sbi_scratch_options { + /** Disable prints during boot */ + SBI_SCRATCH_NO_BOOT_PRINTS = (1 << 0), + /** Enable runtime debug prints */ + SBI_SCRATCH_DEBUG_PRINTS = (1 << 1), +}; + +/** Representation dynamic info passed by previous booting stage */ +struct fw_dynamic_info { + /** Info magic */ + target_long magic; + /** Info version */ + target_long version; + /** Next booting stage address */ + target_long next_addr; + /** Next booting stage mode */ + target_long next_mode; + /** Options for OpenSBI library */ + target_long options; + /** + * Preferred boot HART id + * + * It is possible that the previous booting stage uses same link + * address as the FW_DYNAMIC firmware. In this case, the relocation + * lottery mechanism can potentially overwrite the previous booting + * stage while other HARTs are still running in the previous booting + * stage leading to boot-time crash. To avoid this boot-time crash, + * the previous booting stage can specify last HART that will jump + * to the FW_DYNAMIC firmware as the preferred boot HART. + * + * To avoid specifying a preferred boot HART, the previous booting + * stage can set it to -1UL which will force the FW_DYNAMIC firmware + * to use the relocation lottery mechanism. + */ + target_long boot_hart; +}; + +#endif diff --git a/include/hw/riscv/microchip_pfsoc.h b/include/hw/riscv/microchip_pfsoc.h new file mode 100644 index 0000000000000000000000000000000000000000..51d44637db607dcb5126a6b8a925b0358e2b6f04 --- /dev/null +++ b/include/hw/riscv/microchip_pfsoc.h @@ -0,0 +1,147 @@ +/* + * Microchip PolarFire SoC machine interface + * + * Copyright (c) 2020 Wind River Systems, Inc. + * + * Author: + * Bin Meng + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#ifndef HW_MICROCHIP_PFSOC_H +#define HW_MICROCHIP_PFSOC_H + +#include "hw/char/mchp_pfsoc_mmuart.h" +#include "hw/dma/sifive_pdma.h" +#include "hw/misc/mchp_pfsoc_dmc.h" +#include "hw/misc/mchp_pfsoc_ioscb.h" +#include "hw/misc/mchp_pfsoc_sysreg.h" +#include "hw/net/cadence_gem.h" +#include "hw/sd/cadence_sdhci.h" + +typedef struct MicrochipPFSoCState { + /*< private >*/ + DeviceState parent_obj; + + /*< public >*/ + CPUClusterState e_cluster; + CPUClusterState u_cluster; + RISCVHartArrayState e_cpus; + RISCVHartArrayState u_cpus; + DeviceState *plic; + MchpPfSoCDdrSgmiiPhyState ddr_sgmii_phy; + MchpPfSoCDdrCfgState ddr_cfg; + MchpPfSoCIoscbState ioscb; + MchpPfSoCMMUartState *serial0; + MchpPfSoCMMUartState *serial1; + MchpPfSoCMMUartState *serial2; + MchpPfSoCMMUartState *serial3; + MchpPfSoCMMUartState *serial4; + MchpPfSoCSysregState sysreg; + SiFivePDMAState dma; + CadenceGEMState gem0; + CadenceGEMState gem1; + CadenceSDHCIState sdhci; +} MicrochipPFSoCState; + +#define TYPE_MICROCHIP_PFSOC "microchip.pfsoc" +#define MICROCHIP_PFSOC(obj) \ + OBJECT_CHECK(MicrochipPFSoCState, (obj), TYPE_MICROCHIP_PFSOC) + +typedef struct MicrochipIcicleKitState { + /*< private >*/ + MachineState parent_obj; + + /*< public >*/ + MicrochipPFSoCState soc; +} MicrochipIcicleKitState; + +#define TYPE_MICROCHIP_ICICLE_KIT_MACHINE \ + MACHINE_TYPE_NAME("microchip-icicle-kit") +#define MICROCHIP_ICICLE_KIT_MACHINE(obj) \ + OBJECT_CHECK(MicrochipIcicleKitState, (obj), \ + TYPE_MICROCHIP_ICICLE_KIT_MACHINE) + +enum { + MICROCHIP_PFSOC_RSVD0, + MICROCHIP_PFSOC_DEBUG, + MICROCHIP_PFSOC_E51_DTIM, + MICROCHIP_PFSOC_BUSERR_UNIT0, + MICROCHIP_PFSOC_BUSERR_UNIT1, + MICROCHIP_PFSOC_BUSERR_UNIT2, + MICROCHIP_PFSOC_BUSERR_UNIT3, + MICROCHIP_PFSOC_BUSERR_UNIT4, + MICROCHIP_PFSOC_CLINT, + MICROCHIP_PFSOC_L2CC, + MICROCHIP_PFSOC_DMA, + MICROCHIP_PFSOC_L2LIM, + MICROCHIP_PFSOC_PLIC, + MICROCHIP_PFSOC_MMUART0, + MICROCHIP_PFSOC_SYSREG, + MICROCHIP_PFSOC_MPUCFG, + MICROCHIP_PFSOC_DDR_SGMII_PHY, + MICROCHIP_PFSOC_EMMC_SD, + MICROCHIP_PFSOC_DDR_CFG, + MICROCHIP_PFSOC_MMUART1, + MICROCHIP_PFSOC_MMUART2, + MICROCHIP_PFSOC_MMUART3, + MICROCHIP_PFSOC_MMUART4, + MICROCHIP_PFSOC_I2C1, + MICROCHIP_PFSOC_GEM0, + MICROCHIP_PFSOC_GEM1, + MICROCHIP_PFSOC_GPIO0, + MICROCHIP_PFSOC_GPIO1, + MICROCHIP_PFSOC_GPIO2, + MICROCHIP_PFSOC_ENVM_CFG, + MICROCHIP_PFSOC_ENVM_DATA, + MICROCHIP_PFSOC_IOSCB, + MICROCHIP_PFSOC_DRAM_LO, + MICROCHIP_PFSOC_DRAM_LO_ALIAS, + MICROCHIP_PFSOC_DRAM_HI, + MICROCHIP_PFSOC_DRAM_HI_ALIAS +}; + +enum { + MICROCHIP_PFSOC_DMA_IRQ0 = 5, + MICROCHIP_PFSOC_DMA_IRQ1 = 6, + MICROCHIP_PFSOC_DMA_IRQ2 = 7, + MICROCHIP_PFSOC_DMA_IRQ3 = 8, + MICROCHIP_PFSOC_DMA_IRQ4 = 9, + MICROCHIP_PFSOC_DMA_IRQ5 = 10, + MICROCHIP_PFSOC_DMA_IRQ6 = 11, + MICROCHIP_PFSOC_DMA_IRQ7 = 12, + MICROCHIP_PFSOC_GEM0_IRQ = 64, + MICROCHIP_PFSOC_GEM1_IRQ = 70, + MICROCHIP_PFSOC_EMMC_SD_IRQ = 88, + MICROCHIP_PFSOC_MMUART0_IRQ = 90, + MICROCHIP_PFSOC_MMUART1_IRQ = 91, + MICROCHIP_PFSOC_MMUART2_IRQ = 92, + MICROCHIP_PFSOC_MMUART3_IRQ = 93, + MICROCHIP_PFSOC_MMUART4_IRQ = 94, +}; + +#define MICROCHIP_PFSOC_MANAGEMENT_CPU_COUNT 1 +#define MICROCHIP_PFSOC_COMPUTE_CPU_COUNT 4 + +#define MICROCHIP_PFSOC_PLIC_HART_CONFIG "MS" +#define MICROCHIP_PFSOC_PLIC_NUM_SOURCES 185 +#define MICROCHIP_PFSOC_PLIC_NUM_PRIORITIES 7 +#define MICROCHIP_PFSOC_PLIC_PRIORITY_BASE 0x04 +#define MICROCHIP_PFSOC_PLIC_PENDING_BASE 0x1000 +#define MICROCHIP_PFSOC_PLIC_ENABLE_BASE 0x2000 +#define MICROCHIP_PFSOC_PLIC_ENABLE_STRIDE 0x80 +#define MICROCHIP_PFSOC_PLIC_CONTEXT_BASE 0x200000 +#define MICROCHIP_PFSOC_PLIC_CONTEXT_STRIDE 0x1000 + +#endif /* HW_MICROCHIP_PFSOC_H */ diff --git a/include/hw/riscv/numa.h b/include/hw/riscv/numa.h index fd9517a3157105cb0892abfe09e53a2810230eb9..fcce942ceecade0f850b73c5904fffe90ff47b4a 100644 --- a/include/hw/riscv/numa.h +++ b/include/hw/riscv/numa.h @@ -22,23 +22,85 @@ #include "hw/sysbus.h" #include "sysemu/numa.h" +/** + * riscv_socket_count: + * @ms: pointer to machine state + * + * Returns: number of sockets for a numa system and 1 for a non-numa system + */ int riscv_socket_count(const MachineState *ms); +/** + * riscv_socket_first_hartid: + * @ms: pointer to machine state + * @socket_id: socket index + * + * Returns: first hartid for a valid socket and -1 for an invalid socket + */ int riscv_socket_first_hartid(const MachineState *ms, int socket_id); +/** + * riscv_socket_last_hartid: + * @ms: pointer to machine state + * @socket_id: socket index + * + * Returns: last hartid for a valid socket and -1 for an invalid socket + */ int riscv_socket_last_hartid(const MachineState *ms, int socket_id); +/** + * riscv_socket_hart_count: + * @ms: pointer to machine state + * @socket_id: socket index + * + * Returns: number of harts for a valid socket and -1 for an invalid socket + */ int riscv_socket_hart_count(const MachineState *ms, int socket_id); +/** + * riscv_socket_mem_offset: + * @ms: pointer to machine state + * @socket_id: socket index + * + * Returns: offset of ram belonging to given socket + */ uint64_t riscv_socket_mem_offset(const MachineState *ms, int socket_id); +/** + * riscv_socket_mem_size: + * @ms: pointer to machine state + * @socket_id: socket index + * + * Returns: size of ram belonging to given socket + */ uint64_t riscv_socket_mem_size(const MachineState *ms, int socket_id); +/** + * riscv_socket_check_hartids: + * @ms: pointer to machine state + * @socket_id: socket index + * + * Returns: true if hardids belonging to given socket are contiguous else false + */ bool riscv_socket_check_hartids(const MachineState *ms, int socket_id); +/** + * riscv_socket_fdt_write_id: + * @ms: pointer to machine state + * @socket_id: socket index + * + * Write NUMA node-id FDT property for given FDT node + */ void riscv_socket_fdt_write_id(const MachineState *ms, void *fdt, const char *node_name, int socket_id); +/** + * riscv_socket_fdt_write_distance_matrix: + * @ms: pointer to machine state + * @socket_id: socket index + * + * Write NUMA distance matrix in FDT for given machine + */ void riscv_socket_fdt_write_distance_matrix(const MachineState *ms, void *fdt); CpuInstanceProperties diff --git a/include/hw/riscv/opentitan.h b/include/hw/riscv/opentitan.h new file mode 100644 index 0000000000000000000000000000000000000000..5ff0c0f85eff6b5237c2a70845c2e02005aac2e5 --- /dev/null +++ b/include/hw/riscv/opentitan.h @@ -0,0 +1,84 @@ +/* + * QEMU RISC-V Board Compatible with OpenTitan FPGA platform + * + * Copyright (c) 2020 Western Digital + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#ifndef HW_OPENTITAN_H +#define HW_OPENTITAN_H + +#include "hw/riscv/riscv_hart.h" +#include "hw/intc/ibex_plic.h" +#include "hw/char/ibex_uart.h" +#include "qom/object.h" + +#define TYPE_RISCV_IBEX_SOC "riscv.lowrisc.ibex.soc" +OBJECT_DECLARE_SIMPLE_TYPE(LowRISCIbexSoCState, RISCV_IBEX_SOC) + +struct LowRISCIbexSoCState { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + RISCVHartArrayState cpus; + IbexPlicState plic; + IbexUartState uart; + + MemoryRegion flash_mem; + MemoryRegion rom; +}; + +typedef struct OpenTitanState { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + LowRISCIbexSoCState soc; +} OpenTitanState; + +enum { + IBEX_DEV_ROM, + IBEX_DEV_RAM, + IBEX_DEV_FLASH, + IBEX_DEV_UART, + IBEX_DEV_GPIO, + IBEX_DEV_SPI, + IBEX_DEV_FLASH_CTRL, + IBEX_DEV_RV_TIMER, + IBEX_DEV_AES, + IBEX_DEV_HMAC, + IBEX_DEV_PLIC, + IBEX_DEV_PWRMGR, + IBEX_DEV_RSTMGR, + IBEX_DEV_CLKMGR, + IBEX_DEV_PINMUX, + IBEX_DEV_ALERT_HANDLER, + IBEX_DEV_NMI_GEN, + IBEX_DEV_USBDEV, + IBEX_DEV_PADCTRL, +}; + +enum { + IBEX_UART_RX_PARITY_ERR_IRQ = 0x28, + IBEX_UART_RX_TIMEOUT_IRQ = 0x27, + IBEX_UART_RX_BREAK_ERR_IRQ = 0x26, + IBEX_UART_RX_FRAME_ERR_IRQ = 0x25, + IBEX_UART_RX_OVERFLOW_IRQ = 0x24, + IBEX_UART_TX_EMPTY_IRQ = 0x23, + IBEX_UART_RX_WATERMARK_IRQ = 0x22, + IBEX_UART_TX_WATERMARK_IRQ = 0x21, +}; + +#endif diff --git a/include/hw/riscv/riscv_hart.h b/include/hw/riscv/riscv_hart.h index c75856fa7386f74b33aee23dd7914a603b3d823b..bbc21cdc9a6de5b209db3394091f72c6f0304cb2 100644 --- a/include/hw/riscv/riscv_hart.h +++ b/include/hw/riscv/riscv_hart.h @@ -23,13 +23,13 @@ #include "hw/sysbus.h" #include "target/riscv/cpu.h" +#include "qom/object.h" #define TYPE_RISCV_HART_ARRAY "riscv.hart_array" -#define RISCV_HART_ARRAY(obj) \ - OBJECT_CHECK(RISCVHartArrayState, (obj), TYPE_RISCV_HART_ARRAY) +OBJECT_DECLARE_SIMPLE_TYPE(RISCVHartArrayState, RISCV_HART_ARRAY) -typedef struct RISCVHartArrayState { +struct RISCVHartArrayState { /*< private >*/ SysBusDevice parent_obj; @@ -37,7 +37,8 @@ typedef struct RISCVHartArrayState { uint32_t num_harts; uint32_t hartid_base; char *cpu_type; + uint64_t resetvec; RISCVCPU *harts; -} RISCVHartArrayState; +}; #endif diff --git a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h index 25ce7aa9d50660ef0120421c5aa62524552a93d0..83604da805c32561ed6d8164bab4c998d3ba545f 100644 --- a/include/hw/riscv/sifive_e.h +++ b/include/hw/riscv/sifive_e.h @@ -21,7 +21,7 @@ #include "hw/riscv/riscv_hart.h" #include "hw/riscv/sifive_cpu.h" -#include "hw/riscv/sifive_gpio.h" +#include "hw/gpio/sifive_gpio.h" #define TYPE_RISCV_E_SOC "riscv.sifive.e.soc" #define RISCV_E_SOC(obj) \ @@ -29,7 +29,7 @@ typedef struct SiFiveESoCState { /*< private >*/ - SysBusDevice parent_obj; + DeviceState parent_obj; /*< public >*/ RISCVHartArrayState cpus; @@ -45,28 +45,33 @@ typedef struct SiFiveEState { /*< public >*/ SiFiveESoCState soc; + bool revb; } SiFiveEState; +#define TYPE_RISCV_E_MACHINE MACHINE_TYPE_NAME("sifive_e") +#define RISCV_E_MACHINE(obj) \ + OBJECT_CHECK(SiFiveEState, (obj), TYPE_RISCV_E_MACHINE) + enum { - SIFIVE_E_DEBUG, - SIFIVE_E_MROM, - SIFIVE_E_OTP, - SIFIVE_E_CLINT, - SIFIVE_E_PLIC, - SIFIVE_E_AON, - SIFIVE_E_PRCI, - SIFIVE_E_OTP_CTRL, - SIFIVE_E_GPIO0, - SIFIVE_E_UART0, - SIFIVE_E_QSPI0, - SIFIVE_E_PWM0, - SIFIVE_E_UART1, - SIFIVE_E_QSPI1, - SIFIVE_E_PWM1, - SIFIVE_E_QSPI2, - SIFIVE_E_PWM2, - SIFIVE_E_XIP, - SIFIVE_E_DTIM + SIFIVE_E_DEV_DEBUG, + SIFIVE_E_DEV_MROM, + SIFIVE_E_DEV_OTP, + SIFIVE_E_DEV_CLINT, + SIFIVE_E_DEV_PLIC, + SIFIVE_E_DEV_AON, + SIFIVE_E_DEV_PRCI, + SIFIVE_E_DEV_OTP_CTRL, + SIFIVE_E_DEV_GPIO0, + SIFIVE_E_DEV_UART0, + SIFIVE_E_DEV_QSPI0, + SIFIVE_E_DEV_PWM0, + SIFIVE_E_DEV_UART1, + SIFIVE_E_DEV_QSPI1, + SIFIVE_E_DEV_PWM1, + SIFIVE_E_DEV_QSPI2, + SIFIVE_E_DEV_PWM2, + SIFIVE_E_DEV_XIP, + SIFIVE_E_DEV_DTIM }; enum { diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h index 16c297ec5fe0bdf282d405003dc7b99614df5dd4..a9f7b4a0840ef0c2afb21e236e1454967e05f48b 100644 --- a/include/hw/riscv/sifive_u.h +++ b/include/hw/riscv/sifive_u.h @@ -19,11 +19,13 @@ #ifndef HW_SIFIVE_U_H #define HW_SIFIVE_U_H +#include "hw/dma/sifive_pdma.h" #include "hw/net/cadence_gem.h" #include "hw/riscv/riscv_hart.h" #include "hw/riscv/sifive_cpu.h" -#include "hw/riscv/sifive_u_prci.h" -#include "hw/riscv/sifive_u_otp.h" +#include "hw/gpio/sifive_gpio.h" +#include "hw/misc/sifive_u_otp.h" +#include "hw/misc/sifive_u_prci.h" #define TYPE_RISCV_U_SOC "riscv.sifive.u.soc" #define RISCV_U_SOC(obj) \ @@ -31,7 +33,7 @@ typedef struct SiFiveUSoCState { /*< private >*/ - SysBusDevice parent_obj; + DeviceState parent_obj; /*< public >*/ CPUClusterState e_cluster; @@ -40,10 +42,13 @@ typedef struct SiFiveUSoCState { RISCVHartArrayState u_cpus; DeviceState *plic; SiFiveUPRCIState prci; + SIFIVEGPIOState gpio; SiFiveUOTPState otp; + SiFivePDMAState dma; CadenceGEMState gem; uint32_t serial; + char *cpu_type; } SiFiveUSoCState; #define TYPE_RISCV_U_MACHINE MACHINE_TYPE_NAME("sifive_u") @@ -61,28 +66,60 @@ typedef struct SiFiveUState { int fdt_size; bool start_in_flash; + uint32_t msel; uint32_t serial; } SiFiveUState; enum { - SIFIVE_U_DEBUG, - SIFIVE_U_MROM, - SIFIVE_U_CLINT, - SIFIVE_U_L2LIM, - SIFIVE_U_PLIC, - SIFIVE_U_PRCI, - SIFIVE_U_UART0, - SIFIVE_U_UART1, - SIFIVE_U_OTP, - SIFIVE_U_FLASH0, - SIFIVE_U_DRAM, - SIFIVE_U_GEM, - SIFIVE_U_GEM_MGMT + SIFIVE_U_DEV_DEBUG, + SIFIVE_U_DEV_MROM, + SIFIVE_U_DEV_CLINT, + SIFIVE_U_DEV_L2CC, + SIFIVE_U_DEV_PDMA, + SIFIVE_U_DEV_L2LIM, + SIFIVE_U_DEV_PLIC, + SIFIVE_U_DEV_PRCI, + SIFIVE_U_DEV_UART0, + SIFIVE_U_DEV_UART1, + SIFIVE_U_DEV_GPIO, + SIFIVE_U_DEV_OTP, + SIFIVE_U_DEV_DMC, + SIFIVE_U_DEV_FLASH0, + SIFIVE_U_DEV_DRAM, + SIFIVE_U_DEV_GEM, + SIFIVE_U_DEV_GEM_MGMT }; enum { + SIFIVE_U_L2CC_IRQ0 = 1, + SIFIVE_U_L2CC_IRQ1 = 2, + SIFIVE_U_L2CC_IRQ2 = 3, SIFIVE_U_UART0_IRQ = 4, SIFIVE_U_UART1_IRQ = 5, + SIFIVE_U_GPIO_IRQ0 = 7, + SIFIVE_U_GPIO_IRQ1 = 8, + SIFIVE_U_GPIO_IRQ2 = 9, + SIFIVE_U_GPIO_IRQ3 = 10, + SIFIVE_U_GPIO_IRQ4 = 11, + SIFIVE_U_GPIO_IRQ5 = 12, + SIFIVE_U_GPIO_IRQ6 = 13, + SIFIVE_U_GPIO_IRQ7 = 14, + SIFIVE_U_GPIO_IRQ8 = 15, + SIFIVE_U_GPIO_IRQ9 = 16, + SIFIVE_U_GPIO_IRQ10 = 17, + SIFIVE_U_GPIO_IRQ11 = 18, + SIFIVE_U_GPIO_IRQ12 = 19, + SIFIVE_U_GPIO_IRQ13 = 20, + SIFIVE_U_GPIO_IRQ14 = 21, + SIFIVE_U_GPIO_IRQ15 = 22, + SIFIVE_U_PDMA_IRQ0 = 23, + SIFIVE_U_PDMA_IRQ1 = 24, + SIFIVE_U_PDMA_IRQ2 = 25, + SIFIVE_U_PDMA_IRQ3 = 26, + SIFIVE_U_PDMA_IRQ4 = 27, + SIFIVE_U_PDMA_IRQ5 = 28, + SIFIVE_U_PDMA_IRQ6 = 29, + SIFIVE_U_PDMA_IRQ7 = 30, SIFIVE_U_GEM_IRQ = 0x35 }; @@ -91,6 +128,12 @@ enum { SIFIVE_U_RTCCLK_FREQ = 1000000 }; +enum { + MSEL_MEMMAP_QSPI0_FLASH = 1, + MSEL_L2LIM_QSPI0_FLASH = 6, + MSEL_L2LIM_QSPI2_SD = 11 +}; + #define SIFIVE_U_MANAGEMENT_CPU_COUNT 1 #define SIFIVE_U_COMPUTE_CPU_COUNT 4 diff --git a/include/hw/riscv/spike.h b/include/hw/riscv/spike.h index b0a18a9c944e80696a15644ebe18c91f6cc25834..cddeca2e7728a62f7f1dce021822f584f3257483 100644 --- a/include/hw/riscv/spike.h +++ b/include/hw/riscv/spike.h @@ -21,15 +21,17 @@ #include "hw/riscv/riscv_hart.h" #include "hw/sysbus.h" +#include "qom/object.h" #define SPIKE_CPUS_MAX 8 #define SPIKE_SOCKETS_MAX 8 #define TYPE_SPIKE_MACHINE MACHINE_TYPE_NAME("spike") -#define SPIKE_MACHINE(obj) \ - OBJECT_CHECK(SpikeState, (obj), TYPE_SPIKE_MACHINE) +typedef struct SpikeState SpikeState; +DECLARE_INSTANCE_CHECKER(SpikeState, SPIKE_MACHINE, + TYPE_SPIKE_MACHINE) -typedef struct { +struct SpikeState { /*< private >*/ MachineState parent; @@ -37,7 +39,7 @@ typedef struct { RISCVHartArrayState soc[SPIKE_SOCKETS_MAX]; void *fdt; int fdt_size; -} SpikeState; +}; enum { SPIKE_MROM, diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h index 1beacd7666da1f7eecc39be04ac518c5a779f5ef..b4ed9a32ebd271a95d1047ec11c0ad208908332f 100644 --- a/include/hw/riscv/virt.h +++ b/include/hw/riscv/virt.h @@ -22,15 +22,17 @@ #include "hw/riscv/riscv_hart.h" #include "hw/sysbus.h" #include "hw/block/flash.h" +#include "qom/object.h" #define VIRT_CPUS_MAX 8 #define VIRT_SOCKETS_MAX 8 #define TYPE_RISCV_VIRT_MACHINE MACHINE_TYPE_NAME("virt") -#define RISCV_VIRT_MACHINE(obj) \ - OBJECT_CHECK(RISCVVirtState, (obj), TYPE_RISCV_VIRT_MACHINE) +typedef struct RISCVVirtState RISCVVirtState; +DECLARE_INSTANCE_CHECKER(RISCVVirtState, RISCV_VIRT_MACHINE, + TYPE_RISCV_VIRT_MACHINE) -typedef struct { +struct RISCVVirtState { /*< private >*/ MachineState parent; @@ -41,7 +43,7 @@ typedef struct { void *fdt; int fdt_size; -} RISCVVirtState; +}; enum { VIRT_DEBUG, diff --git a/include/hw/rtc/allwinner-rtc.h b/include/hw/rtc/allwinner-rtc.h index 7893f74795cf914bb88ee45e4c9e4459ab8ad50c..bf415431cd79250ef87f7ef445994aa9c1e901e6 100644 --- a/include/hw/rtc/allwinner-rtc.h +++ b/include/hw/rtc/allwinner-rtc.h @@ -60,19 +60,14 @@ * @{ */ -#define AW_RTC(obj) \ - OBJECT_CHECK(AwRtcState, (obj), TYPE_AW_RTC) -#define AW_RTC_CLASS(klass) \ - OBJECT_CLASS_CHECK(AwRtcClass, (klass), TYPE_AW_RTC) -#define AW_RTC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(AwRtcClass, (obj), TYPE_AW_RTC) +OBJECT_DECLARE_TYPE(AwRtcState, AwRtcClass, AW_RTC) /** @} */ /** * Allwinner RTC per-object instance state. */ -typedef struct AwRtcState { +struct AwRtcState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -92,7 +87,7 @@ typedef struct AwRtcState { /** Array of hardware registers */ uint32_t regs[AW_RTC_REGS_NUM]; -} AwRtcState; +}; /** * Allwinner RTC class-level struct. @@ -101,7 +96,7 @@ typedef struct AwRtcState { * such that the generic code can use this struct to support * all devices. */ -typedef struct AwRtcClass { +struct AwRtcClass { /*< private >*/ SysBusDeviceClass parent_class; /*< public >*/ @@ -129,6 +124,6 @@ typedef struct AwRtcClass { */ bool (*write)(AwRtcState *s, uint32_t offset, uint32_t data); -} AwRtcClass; +}; #endif /* HW_MISC_ALLWINNER_RTC_H */ diff --git a/include/hw/rtc/aspeed_rtc.h b/include/hw/rtc/aspeed_rtc.h index b94a7102688a82fabc84652b6b2732d5938f1f2a..df61e46059ecb7219775e2cdb0405e3b5bc7f071 100644 --- a/include/hw/rtc/aspeed_rtc.h +++ b/include/hw/rtc/aspeed_rtc.h @@ -9,8 +9,9 @@ #define HW_RTC_ASPEED_RTC_H #include "hw/sysbus.h" +#include "qom/object.h" -typedef struct AspeedRtcState { +struct AspeedRtcState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -19,9 +20,9 @@ typedef struct AspeedRtcState { uint32_t reg[0x18]; int offset; -} AspeedRtcState; +}; #define TYPE_ASPEED_RTC "aspeed.rtc" -#define ASPEED_RTC(obj) OBJECT_CHECK(AspeedRtcState, (obj), TYPE_ASPEED_RTC) +OBJECT_DECLARE_SIMPLE_TYPE(AspeedRtcState, ASPEED_RTC) #endif /* HW_RTC_ASPEED_RTC_H */ diff --git a/include/hw/rtc/goldfish_rtc.h b/include/hw/rtc/goldfish_rtc.h index 16f9f9e29de80804feefbcd3543c655a2293f2a9..79ca7daf5dd53c5864437ee64bdd7f25ea1afb14 100644 --- a/include/hw/rtc/goldfish_rtc.h +++ b/include/hw/rtc/goldfish_rtc.h @@ -23,12 +23,12 @@ #define HW_RTC_GOLDFISH_RTC_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_GOLDFISH_RTC "goldfish_rtc" -#define GOLDFISH_RTC(obj) \ - OBJECT_CHECK(GoldfishRTCState, (obj), TYPE_GOLDFISH_RTC) +OBJECT_DECLARE_SIMPLE_TYPE(GoldfishRTCState, GOLDFISH_RTC) -typedef struct GoldfishRTCState { +struct GoldfishRTCState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -41,6 +41,7 @@ typedef struct GoldfishRTCState { uint32_t alarm_running; uint32_t irq_pending; uint32_t irq_enabled; -} GoldfishRTCState; + uint32_t time_high; +}; #endif diff --git a/include/hw/rtc/m48t59.h b/include/hw/rtc/m48t59.h index e7ea4e8761b9c07ecba6015443855229ddeb4e7d..d9b45eb16128aa3067805c6d6d1cdc460fc665d8 100644 --- a/include/hw/rtc/m48t59.h +++ b/include/hw/rtc/m48t59.h @@ -31,27 +31,20 @@ #define TYPE_NVRAM "nvram" -#define NVRAM_CLASS(klass) \ - OBJECT_CLASS_CHECK(NvramClass, (klass), TYPE_NVRAM) -#define NVRAM_GET_CLASS(obj) \ - OBJECT_GET_CLASS(NvramClass, (obj), TYPE_NVRAM) +typedef struct NvramClass NvramClass; +DECLARE_CLASS_CHECKERS(NvramClass, NVRAM, + TYPE_NVRAM) #define NVRAM(obj) \ INTERFACE_CHECK(Nvram, (obj), TYPE_NVRAM) typedef struct Nvram Nvram; -typedef struct NvramClass { +struct NvramClass { InterfaceClass parent; uint32_t (*read)(Nvram *obj, uint32_t addr); void (*write)(Nvram *obj, uint32_t addr, uint32_t val); void (*toggle_lock)(Nvram *obj, int lock); -} NvramClass; - -Nvram *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size, - int base_year, int type); -Nvram *m48t59_init(qemu_irq IRQ, hwaddr mem_base, - uint32_t io_base, uint16_t size, int base_year, - int type); +}; #endif /* HW_M48T59_H */ diff --git a/include/hw/rtc/mc146818rtc.h b/include/hw/rtc/mc146818rtc.h index 3713181b56feab8ffdb70296e6763d2830462aab..5b45b229244c4b33d6eda20a44cbeb8ca91fb271 100644 --- a/include/hw/rtc/mc146818rtc.h +++ b/include/hw/rtc/mc146818rtc.h @@ -9,15 +9,16 @@ #ifndef HW_RTC_MC146818RTC_H #define HW_RTC_MC146818RTC_H -#include "qapi/qapi-types-misc.h" +#include "qapi/qapi-types-machine.h" #include "qemu/queue.h" #include "qemu/timer.h" #include "hw/isa/isa.h" +#include "qom/object.h" #define TYPE_MC146818_RTC "mc146818rtc" -#define MC146818_RTC(obj) OBJECT_CHECK(RTCState, (obj), TYPE_MC146818_RTC) +OBJECT_DECLARE_SIMPLE_TYPE(RTCState, MC146818_RTC) -typedef struct RTCState { +struct RTCState { ISADevice parent_obj; MemoryRegion io; @@ -44,7 +45,7 @@ typedef struct RTCState { LostTickPolicy lost_tick_policy; Notifier suspend_notifier; QLIST_ENTRY(RTCState) link; -} RTCState; +}; #define RTC_ISA_IRQ 8 #define RTC_ISA_BASE 0x70 diff --git a/include/hw/rtc/pl031.h b/include/hw/rtc/pl031.h index e3cb1d646fc47ff2a76d79941fe79e9cbc83da74..9fd4be1abba06dcfc5666fbb618c481f14d6ff70 100644 --- a/include/hw/rtc/pl031.h +++ b/include/hw/rtc/pl031.h @@ -16,11 +16,12 @@ #include "hw/sysbus.h" #include "qemu/timer.h" +#include "qom/object.h" #define TYPE_PL031 "pl031" -#define PL031(obj) OBJECT_CHECK(PL031State, (obj), TYPE_PL031) +OBJECT_DECLARE_SIMPLE_TYPE(PL031State, PL031) -typedef struct PL031State { +struct PL031State { SysBusDevice parent_obj; MemoryRegion iomem; @@ -42,6 +43,6 @@ typedef struct PL031State { uint32_t cr; uint32_t im; uint32_t is; -} PL031State; +}; #endif diff --git a/include/hw/rtc/xlnx-zynqmp-rtc.h b/include/hw/rtc/xlnx-zynqmp-rtc.h index 6fa1cb2f43f81ca6920579b188d880ac54748db2..5f1ad0a9462fa7fa0b691b671e7f29ad72cedced 100644 --- a/include/hw/rtc/xlnx-zynqmp-rtc.h +++ b/include/hw/rtc/xlnx-zynqmp-rtc.h @@ -29,11 +29,11 @@ #include "hw/register.h" #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_XLNX_ZYNQMP_RTC "xlnx-zynmp.rtc" -#define XLNX_ZYNQMP_RTC(obj) \ - OBJECT_CHECK(XlnxZynqMPRTC, (obj), TYPE_XLNX_ZYNQMP_RTC) +OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPRTC, XLNX_ZYNQMP_RTC) REG32(SET_TIME_WRITE, 0x0) REG32(SET_TIME_READ, 0x4) @@ -77,7 +77,7 @@ REG32(SAFETY_CHK, 0x50) #define XLNX_ZYNQMP_RTC_R_MAX (R_SAFETY_CHK + 1) -typedef struct XlnxZynqMPRTC { +struct XlnxZynqMPRTC { SysBusDevice parent_obj; MemoryRegion iomem; qemu_irq irq_rtc_int; @@ -87,6 +87,6 @@ typedef struct XlnxZynqMPRTC { uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX]; RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX]; -} XlnxZynqMPRTC; +}; #endif diff --git a/include/hw/rx/rx62n.h b/include/hw/rx/rx62n.h new file mode 100644 index 0000000000000000000000000000000000000000..3ed80dba0dd34d76eeaca8bf0b585ced3124e841 --- /dev/null +++ b/include/hw/rx/rx62n.h @@ -0,0 +1,79 @@ +/* + * RX62N MCU Object + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * + * Copyright (c) 2019 Yoshinori Sato + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#ifndef HW_RX_RX62N_MCU_H +#define HW_RX_RX62N_MCU_H + +#include "target/rx/cpu.h" +#include "hw/intc/rx_icu.h" +#include "hw/timer/renesas_tmr.h" +#include "hw/timer/renesas_cmt.h" +#include "hw/char/renesas_sci.h" +#include "qemu/units.h" +#include "qom/object.h" + +#define TYPE_RX62N_MCU "rx62n-mcu" +typedef struct RX62NState RX62NState; +DECLARE_INSTANCE_CHECKER(RX62NState, RX62N_MCU, + TYPE_RX62N_MCU) + +#define TYPE_R5F562N7_MCU "r5f562n7-mcu" +#define TYPE_R5F562N8_MCU "r5f562n8-mcu" + +#define EXT_CS_BASE 0x01000000 +#define VECTOR_TABLE_BASE 0xffffff80 +#define RX62N_CFLASH_BASE 0xfff80000 + +#define RX62N_NR_TMR 2 +#define RX62N_NR_CMT 2 +#define RX62N_NR_SCI 6 + +struct RX62NState { + /*< private >*/ + DeviceState parent_obj; + /*< public >*/ + + RXCPU cpu; + RXICUState icu; + RTMRState tmr[RX62N_NR_TMR]; + RCMTState cmt[RX62N_NR_CMT]; + RSCIState sci[RX62N_NR_SCI]; + + MemoryRegion *sysmem; + bool kernel; + + MemoryRegion iram; + MemoryRegion iomem1; + MemoryRegion d_flash; + MemoryRegion iomem2; + MemoryRegion iomem3; + MemoryRegion c_flash; + qemu_irq irq[NR_IRQS]; + + /* Input Clock (XTAL) frequency */ + uint32_t xtal_freq_hz; + /* Peripheral Module Clock frequency */ + uint32_t pclk_freq_hz; +}; + +#endif diff --git a/include/hw/s390x/3270-ccw.h b/include/hw/s390x/3270-ccw.h index 9d1d18e2bd245e7117654fdd9facc3f583d8bde9..14398822944213b04a3f45f51276afe8604aee10 100644 --- a/include/hw/s390x/3270-ccw.h +++ b/include/hw/s390x/3270-ccw.h @@ -16,6 +16,7 @@ #include "hw/sysbus.h" #include "hw/s390x/css.h" #include "hw/s390x/ccw-device.h" +#include "qom/object.h" #define EMULATED_CCW_3270_CU_TYPE 0x3270 #define EMULATED_CCW_3270_CHPID_TYPE 0x1a @@ -30,23 +31,18 @@ #define TC_EWRITEA 0x0d /* Erase write alternate */ #define TC_WRITESF 0x11 /* Write structured field */ -#define EMULATED_CCW_3270(obj) \ - OBJECT_CHECK(EmulatedCcw3270Device, (obj), TYPE_EMULATED_CCW_3270) -#define EMULATED_CCW_3270_CLASS(klass) \ - OBJECT_CLASS_CHECK(EmulatedCcw3270Class, (klass), TYPE_EMULATED_CCW_3270) -#define EMULATED_CCW_3270_GET_CLASS(obj) \ - OBJECT_GET_CLASS(EmulatedCcw3270Class, (obj), TYPE_EMULATED_CCW_3270) +OBJECT_DECLARE_TYPE(EmulatedCcw3270Device, EmulatedCcw3270Class, EMULATED_CCW_3270) -typedef struct EmulatedCcw3270Device { +struct EmulatedCcw3270Device { CcwDevice parent_obj; -} EmulatedCcw3270Device; +}; -typedef struct EmulatedCcw3270Class { +struct EmulatedCcw3270Class { CCWDeviceClass parent_class; void (*init)(EmulatedCcw3270Device *, Error **); int (*read_payload_3270)(EmulatedCcw3270Device *); int (*write_payload_3270)(EmulatedCcw3270Device *, uint8_t); -} EmulatedCcw3270Class; +}; #endif diff --git a/include/hw/s390x/ap-device.h b/include/hw/s390x/ap-device.h index 8df9cd29542f290a50f2a68622c96a73b3ed3008..e502745de5ea5045f4475a1f3962b77ff6a22415 100644 --- a/include/hw/s390x/ap-device.h +++ b/include/hw/s390x/ap-device.h @@ -12,14 +12,16 @@ #define HW_S390X_AP_DEVICE_H #include "hw/qdev-core.h" +#include "qom/object.h" -#define AP_DEVICE_TYPE "ap-device" +#define TYPE_AP_DEVICE "ap-device" -typedef struct APDevice { +struct APDevice { DeviceState parent_obj; -} APDevice; +}; +typedef struct APDevice APDevice; -#define AP_DEVICE(obj) \ - OBJECT_CHECK(APDevice, (obj), AP_DEVICE_TYPE) +DECLARE_INSTANCE_CHECKER(APDevice, AP_DEVICE, + TYPE_AP_DEVICE) #endif /* HW_S390X_AP_DEVICE_H */ diff --git a/include/hw/s390x/css-bridge.h b/include/hw/s390x/css-bridge.h index f7ed2d9a03e4d6021f29387f2317c6a32faaa7fc..deb606d71f1157fa3484b32b0273c8182b7e8b99 100644 --- a/include/hw/s390x/css-bridge.h +++ b/include/hw/s390x/css-bridge.h @@ -17,23 +17,21 @@ #include "hw/sysbus.h" /* virtual css bridge */ -typedef struct VirtualCssBridge { +struct VirtualCssBridge { SysBusDevice sysbus_dev; bool css_dev_path; -} VirtualCssBridge; +}; #define TYPE_VIRTUAL_CSS_BRIDGE "virtual-css-bridge" -#define VIRTUAL_CSS_BRIDGE(obj) \ - OBJECT_CHECK(VirtualCssBridge, (obj), TYPE_VIRTUAL_CSS_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(VirtualCssBridge, VIRTUAL_CSS_BRIDGE) /* virtual css bus type */ -typedef struct VirtualCssBus { +struct VirtualCssBus { BusState parent_obj; -} VirtualCssBus; +}; #define TYPE_VIRTUAL_CSS_BUS "virtual-css-bus" -#define VIRTUAL_CSS_BUS(obj) \ - OBJECT_CHECK(VirtualCssBus, (obj), TYPE_VIRTUAL_CSS_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(VirtualCssBus, VIRTUAL_CSS_BUS) VirtualCssBus *virtual_css_bus_init(void); #endif diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h index f46bcafb16c3f8c80ed967e8901f211d34e17496..08c869ab0afc18f34fb28056ce29c6ac87bae4d4 100644 --- a/include/hw/s390x/css.h +++ b/include/hw/s390x/css.h @@ -205,6 +205,7 @@ void copy_scsw_to_guest(SCSW *dest, const SCSW *src); void css_inject_io_interrupt(SubchDev *sch); void css_reset(void); void css_reset_sch(SubchDev *sch); +void css_crw_add_to_queue(CRW crw); void css_queue_crw(uint8_t rsc, uint8_t erc, int solicited, int chain, uint16_t rsid); void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, @@ -218,6 +219,7 @@ IOInstEnding do_subchannel_work_passthrough(SubchDev *sub); int s390_ccw_halt(SubchDev *sch); int s390_ccw_clear(SubchDev *sch); +IOInstEnding s390_ccw_store(SubchDev *sch); typedef enum { CSS_IO_ADAPTER_VIRTIO = 0, @@ -242,7 +244,7 @@ SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid, uint16_t schid); bool css_subch_visible(SubchDev *sch); void css_conditional_io_interrupt(SubchDev *sch); -int css_do_stsch(SubchDev *sch, SCHIB *schib); +IOInstEnding css_do_stsch(SubchDev *sch, SCHIB *schib); bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid); IOInstEnding css_do_msch(SubchDev *sch, const SCHIB *schib); IOInstEnding css_do_xsch(SubchDev *sch); diff --git a/include/hw/s390x/event-facility.h b/include/hw/s390x/event-facility.h index 700a610f33c032b005411a6a708e2983409978ee..3ffd575d8ff09863e17f96d1bdb56a2ca6c2aa56 100644 --- a/include/hw/s390x/event-facility.h +++ b/include/hw/s390x/event-facility.h @@ -18,6 +18,7 @@ #include "qemu/thread.h" #include "hw/qdev-core.h" #include "hw/s390x/sclp.h" +#include "qom/object.h" /* SCLP event types */ #define SCLP_EVENT_OPRTNS_COMMAND 0x01 @@ -41,12 +42,8 @@ #define SCLP_SELECTIVE_READ 0x01 #define TYPE_SCLP_EVENT "s390-sclp-event-type" -#define SCLP_EVENT(obj) \ - OBJECT_CHECK(SCLPEvent, (obj), TYPE_SCLP_EVENT) -#define SCLP_EVENT_CLASS(klass) \ - OBJECT_CLASS_CHECK(SCLPEventClass, (klass), TYPE_SCLP_EVENT) -#define SCLP_EVENT_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SCLPEventClass, (obj), TYPE_SCLP_EVENT) +OBJECT_DECLARE_TYPE(SCLPEvent, SCLPEventClass, + SCLP_EVENT) #define TYPE_SCLP_CPU_HOTPLUG "sclp-cpu-hotplug" #define TYPE_SCLP_QUIESCE "sclpquiesce" @@ -169,13 +166,13 @@ typedef struct ReadEventData { }; } QEMU_PACKED ReadEventData; -typedef struct SCLPEvent { +struct SCLPEvent { DeviceState qdev; bool event_pending; char *name; -} SCLPEvent; +}; -typedef struct SCLPEventClass { +struct SCLPEventClass { DeviceClass parent_class; int (*init)(SCLPEvent *event); @@ -192,23 +189,19 @@ typedef struct SCLPEventClass { /* can we handle this event type? */ bool (*can_handle_event)(uint8_t type); -} SCLPEventClass; +}; #define TYPE_SCLP_EVENT_FACILITY "s390-sclp-event-facility" -#define EVENT_FACILITY(obj) \ - OBJECT_CHECK(SCLPEventFacility, (obj), TYPE_SCLP_EVENT_FACILITY) -#define EVENT_FACILITY_CLASS(klass) \ - OBJECT_CLASS_CHECK(SCLPEventFacilityClass, (klass), \ - TYPE_SCLP_EVENT_FACILITY) -#define EVENT_FACILITY_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SCLPEventFacilityClass, (obj), \ - TYPE_SCLP_EVENT_FACILITY) - -typedef struct SCLPEventFacilityClass { +typedef struct SCLPEventFacility SCLPEventFacility; +typedef struct SCLPEventFacilityClass SCLPEventFacilityClass; +DECLARE_OBJ_CHECKERS(SCLPEventFacility, SCLPEventFacilityClass, + EVENT_FACILITY, TYPE_SCLP_EVENT_FACILITY) + +struct SCLPEventFacilityClass { SysBusDeviceClass parent_class; void (*command_handler)(SCLPEventFacility *ef, SCCB *sccb, uint64_t code); bool (*event_pending)(SCLPEventFacility *ef); -} SCLPEventFacilityClass; +}; BusState *sclp_get_event_facility_bus(void); diff --git a/include/hw/s390x/pv.h b/include/hw/s390x/pv.h index 522ca6a04ee877940ff1de9f410b5c5349ae8775..aee758bc2d34ba554789483fec7b3029df74b4c9 100644 --- a/include/hw/s390x/pv.h +++ b/include/hw/s390x/pv.h @@ -39,7 +39,7 @@ int s390_pv_vm_enable(void); void s390_pv_vm_disable(void); int s390_pv_set_sec_parms(uint64_t origin, uint64_t length); int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak); -void s390_pv_perf_clear_reset(void); +void s390_pv_prep_reset(void); int s390_pv_verify(void); void s390_pv_unshare(void); void s390_pv_inject_reset_error(CPUState *cs); @@ -49,7 +49,7 @@ static inline int s390_pv_vm_enable(void) { return 0; } static inline void s390_pv_vm_disable(void) {} static inline int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) { return 0; } static inline int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) { return 0; } -static inline void s390_pv_perf_clear_reset(void) {} +static inline void s390_pv_prep_reset(void) {} static inline int s390_pv_verify(void) { return 0; } static inline void s390_pv_unshare(void) {} static inline void s390_pv_inject_reset_error(CPUState *cs) {}; diff --git a/include/hw/s390x/s390-ccw.h b/include/hw/s390x/s390-ccw.h index 7f27bc2f53144d6707036dc33eb8775956c66d0e..2c807ee3a1ae8d85460fe65be8a62c64f212fe4b 100644 --- a/include/hw/s390x/s390-ccw.h +++ b/include/hw/s390x/s390-ccw.h @@ -14,29 +14,29 @@ #define HW_S390_CCW_H #include "hw/s390x/ccw-device.h" +#include "qom/object.h" #define TYPE_S390_CCW "s390-ccw" -#define S390_CCW_DEVICE(obj) \ - OBJECT_CHECK(S390CCWDevice, (obj), TYPE_S390_CCW) -#define S390_CCW_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(S390CCWDeviceClass, (klass), TYPE_S390_CCW) -#define S390_CCW_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(S390CCWDeviceClass, (obj), TYPE_S390_CCW) +typedef struct S390CCWDevice S390CCWDevice; +typedef struct S390CCWDeviceClass S390CCWDeviceClass; +DECLARE_OBJ_CHECKERS(S390CCWDevice, S390CCWDeviceClass, + S390_CCW_DEVICE, TYPE_S390_CCW) -typedef struct S390CCWDevice { +struct S390CCWDevice { CcwDevice parent_obj; CssDevId hostid; char *mdevid; int32_t bootindex; -} S390CCWDevice; +}; -typedef struct S390CCWDeviceClass { +struct S390CCWDeviceClass { CCWDeviceClass parent_class; void (*realize)(S390CCWDevice *dev, char *sysfsdev, Error **errp); void (*unrealize)(S390CCWDevice *dev); IOInstEnding (*handle_request) (SubchDev *sch); int (*handle_halt) (SubchDev *sch); int (*handle_clear) (SubchDev *sch); -} S390CCWDeviceClass; + IOInstEnding (*handle_store) (SubchDev *sch); +}; #endif diff --git a/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h similarity index 92% rename from hw/s390x/s390-pci-bus.h rename to include/hw/s390x/s390-pci-bus.h index 550f3cc5e92076cdb8a28b9322659c0ff8a1ea29..49ae9f03d310e67504e4051ba56d60d7d6c22cbd 100644 --- a/hw/s390x/s390-pci-bus.h +++ b/include/hw/s390x/s390-pci-bus.h @@ -19,6 +19,8 @@ #include "hw/s390x/sclp.h" #include "hw/s390x/s390_flic.h" #include "hw/s390x/css.h" +#include "hw/s390x/s390-pci-clp.h" +#include "qom/object.h" #define TYPE_S390_PCI_HOST_BRIDGE "s390-pcihost" #define TYPE_S390_PCI_BUS "s390-pcibus" @@ -36,14 +38,10 @@ #define UID_UNDEFINED 0 #define UID_CHECKING_ENABLED 0x01 -#define S390_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(S390pciState, (obj), TYPE_S390_PCI_HOST_BRIDGE) -#define S390_PCI_BUS(obj) \ - OBJECT_CHECK(S390PCIBus, (obj), TYPE_S390_PCI_BUS) -#define S390_PCI_DEVICE(obj) \ - OBJECT_CHECK(S390PCIBusDevice, (obj), TYPE_S390_PCI_DEVICE) -#define S390_PCI_IOMMU(obj) \ - OBJECT_CHECK(S390PCIIOMMU, (obj), TYPE_S390_PCI_IOMMU) +OBJECT_DECLARE_SIMPLE_TYPE(S390pciState, S390_PCI_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(S390PCIBus, S390_PCI_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(S390PCIBusDevice, S390_PCI_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(S390PCIIOMMU, S390_PCI_IOMMU) #define HP_EVENT_TO_CONFIGURED 0x0301 #define HP_EVENT_RESERVED_TO_STANDBY 0x0302 @@ -265,8 +263,14 @@ typedef struct S390IOTLBEntry { uint64_t perm; } S390IOTLBEntry; -typedef struct S390PCIBusDevice S390PCIBusDevice; -typedef struct S390PCIIOMMU { +typedef struct S390PCIDMACount { + int id; + int users; + uint32_t avail; + QTAILQ_ENTRY(S390PCIDMACount) link; +} S390PCIDMACount; + +struct S390PCIIOMMU { Object parent_obj; S390PCIBusDevice *pbdev; AddressSpace as; @@ -277,7 +281,8 @@ typedef struct S390PCIIOMMU { uint64_t pba; uint64_t pal; GHashTable *iotlb; -} S390PCIIOMMU; + S390PCIDMACount *dma_limit; +}; typedef struct S390PCIIOMMUTable { uint64_t key; @@ -311,6 +316,15 @@ typedef struct ZpciFmb { } ZpciFmb; QEMU_BUILD_BUG_MSG(offsetof(ZpciFmb, fmt0) != 48, "padding in ZpciFmb"); +#define ZPCI_DEFAULT_FN_GRP 0x20 +typedef struct S390PCIGroup { + ClpRspQueryPciGrp zpci_group; + int id; + QTAILQ_ENTRY(S390PCIGroup) link; +} S390PCIGroup; +S390PCIGroup *s390_group_create(int id); +S390PCIGroup *s390_group_find(int id); + struct S390PCIBusDevice { DeviceState qdev; PCIDevice *pdev; @@ -328,6 +342,8 @@ struct S390PCIBusDevice { uint16_t noi; uint16_t maxstbl; uint8_t sum; + S390PCIGroup *pci_group; + ClpRspQueryPci zpci_fn; S390MsixInfo msix; AdapterRoutes routes; S390PCIIOMMU *iommu; @@ -339,11 +355,11 @@ struct S390PCIBusDevice { QTAILQ_ENTRY(S390PCIBusDevice) link; }; -typedef struct S390PCIBus { +struct S390PCIBus { BusState qbus; -} S390PCIBus; +}; -typedef struct S390pciState { +struct S390pciState { PCIHostState parent_obj; uint32_t next_idx; int bus_no; @@ -352,7 +368,9 @@ typedef struct S390pciState { GHashTable *zpci_table; QTAILQ_HEAD(, SeiContainer) pending_sei; QTAILQ_HEAD(, S390PCIBusDevice) zpci_devs; -} S390pciState; + QTAILQ_HEAD(, S390PCIDMACount) zpci_dma_limit; + QTAILQ_HEAD(, S390PCIGroup) zpci_groups; +}; S390pciState *s390_get_phb(void); int pci_chsc_sei_nt2_get_event(void *res); diff --git a/hw/s390x/s390-pci-inst.h b/include/hw/s390x/s390-pci-clp.h similarity index 58% rename from hw/s390x/s390-pci-inst.h rename to include/hw/s390x/s390-pci-clp.h index fa3bf8b5aad11e03376774f8fa4151ef1177d6bb..96b8e3f1331bf0a92603f75b9e3a2a47de757b33 100644 --- a/hw/s390x/s390-pci-inst.h +++ b/include/hw/s390x/s390-pci-clp.h @@ -1,21 +1,16 @@ /* - * s390 PCI instruction definitions + * s390 CLP instruction definitions * - * Copyright 2014 IBM Corp. - * Author(s): Frank Blaschka - * Hong Bo Li - * Yi Min Zhao + * Copyright 2019 IBM Corp. + * Author(s): Pierre Morel * * This work is licensed under the terms of the GNU GPL, version 2 or (at * your option) any later version. See the COPYING file in the top-level * directory. */ -#ifndef HW_S390_PCI_INST_H -#define HW_S390_PCI_INST_H - -#include "s390-pci-bus.h" -#include "sysemu/dma.h" +#ifndef HW_S390_PCI_CLP +#define HW_S390_PCI_CLP /* CLP common request & response block size */ #define CLP_BLK_SIZE 4096 @@ -84,6 +79,7 @@ typedef struct ClpFhListEntry { #define CLP_SET_DISABLE_PCI_FN 1 /* Yes, 1 disables it */ #define CLP_UTIL_STR_LEN 64 +#define CLP_PFIP_NR_SEGMENTS 4 #define CLP_MASK_FMT 0xf0000000 @@ -125,14 +121,17 @@ typedef struct ClpRspQueryPci { uint32_t fmt; uint64_t reserved1; uint16_t vfn; /* virtual fn number */ -#define CLP_RSP_QPCI_MASK_UTIL 0x100 -#define CLP_RSP_QPCI_MASK_PFGID 0xff - uint16_t ug; +#define CLP_RSP_QPCI_MASK_UTIL 0x01 + uint8_t flags; + uint8_t pfgid; uint32_t fid; /* pci function id */ uint8_t bar_size[PCI_BAR_COUNT]; uint16_t pchid; uint32_t bar[PCI_BAR_COUNT]; - uint64_t reserved2; + uint8_t pfip[CLP_PFIP_NR_SEGMENTS]; + uint16_t reserved2; + uint8_t fmbl; + uint8_t pft; uint64_t sdma; /* start dma as */ uint64_t edma; /* end dma as */ uint32_t reserved3[11]; @@ -145,10 +144,10 @@ typedef struct ClpReqQueryPciGrp { ClpReqHdr hdr; uint32_t fmt; uint64_t reserved1; -#define CLP_REQ_QPCIG_MASK_PFGID 0xff - uint32_t g; - uint32_t reserved2; - uint64_t reserved3; + uint8_t reserved2[3]; + uint8_t g; + uint32_t reserved3; + uint64_t reserved4; } QEMU_PACKED ClpReqQueryPciGrp; /* Query PCI function group response */ @@ -213,100 +212,4 @@ typedef struct ClpReqRspQueryPciGrp { ClpRspQueryPciGrp response; } QEMU_PACKED ClpReqRspQueryPciGrp; -/* Load/Store status codes */ -#define ZPCI_PCI_ST_FUNC_NOT_ENABLED 4 -#define ZPCI_PCI_ST_FUNC_IN_ERR 8 -#define ZPCI_PCI_ST_BLOCKED 12 -#define ZPCI_PCI_ST_INSUF_RES 16 -#define ZPCI_PCI_ST_INVAL_AS 20 -#define ZPCI_PCI_ST_FUNC_ALREADY_ENABLED 24 -#define ZPCI_PCI_ST_DMA_AS_NOT_ENABLED 28 -#define ZPCI_PCI_ST_2ND_OP_IN_INV_AS 36 -#define ZPCI_PCI_ST_FUNC_NOT_AVAIL 40 -#define ZPCI_PCI_ST_ALREADY_IN_RQ_STATE 44 - -/* Load/Store return codes */ -#define ZPCI_PCI_LS_OK 0 -#define ZPCI_PCI_LS_ERR 1 -#define ZPCI_PCI_LS_BUSY 2 -#define ZPCI_PCI_LS_INVAL_HANDLE 3 - -/* Modify PCI status codes */ -#define ZPCI_MOD_ST_RES_NOT_AVAIL 4 -#define ZPCI_MOD_ST_INSUF_RES 16 -#define ZPCI_MOD_ST_SEQUENCE 24 -#define ZPCI_MOD_ST_DMAAS_INVAL 28 -#define ZPCI_MOD_ST_FRAME_INVAL 32 -#define ZPCI_MOD_ST_ERROR_RECOVER 40 - -/* Modify PCI Function Controls */ -#define ZPCI_MOD_FC_REG_INT 2 -#define ZPCI_MOD_FC_DEREG_INT 3 -#define ZPCI_MOD_FC_REG_IOAT 4 -#define ZPCI_MOD_FC_DEREG_IOAT 5 -#define ZPCI_MOD_FC_REREG_IOAT 6 -#define ZPCI_MOD_FC_RESET_ERROR 7 -#define ZPCI_MOD_FC_RESET_BLOCK 9 -#define ZPCI_MOD_FC_SET_MEASURE 10 - -/* Store PCI Function Controls status codes */ -#define ZPCI_STPCIFC_ST_PERM_ERROR 8 -#define ZPCI_STPCIFC_ST_INVAL_DMAAS 28 -#define ZPCI_STPCIFC_ST_ERROR_RECOVER 40 - -/* FIB function controls */ -#define ZPCI_FIB_FC_ENABLED 0x80 -#define ZPCI_FIB_FC_ERROR 0x40 -#define ZPCI_FIB_FC_LS_BLOCKED 0x20 -#define ZPCI_FIB_FC_DMAAS_REG 0x10 - -/* FIB function controls */ -#define ZPCI_FIB_FC_ENABLED 0x80 -#define ZPCI_FIB_FC_ERROR 0x40 -#define ZPCI_FIB_FC_LS_BLOCKED 0x20 -#define ZPCI_FIB_FC_DMAAS_REG 0x10 - -/* Function Information Block */ -typedef struct ZpciFib { - uint8_t fmt; /* format */ - uint8_t reserved1[7]; - uint8_t fc; /* function controls */ - uint8_t reserved2; - uint16_t reserved3; - uint32_t reserved4; - uint64_t pba; /* PCI base address */ - uint64_t pal; /* PCI address limit */ - uint64_t iota; /* I/O Translation Anchor */ -#define FIB_DATA_ISC(x) (((x) >> 28) & 0x7) -#define FIB_DATA_NOI(x) (((x) >> 16) & 0xfff) -#define FIB_DATA_AIBVO(x) (((x) >> 8) & 0x3f) -#define FIB_DATA_SUM(x) (((x) >> 7) & 0x1) -#define FIB_DATA_AISBO(x) ((x) & 0x3f) - uint32_t data; - uint32_t reserved5; - uint64_t aibv; /* Adapter int bit vector address */ - uint64_t aisb; /* Adapter int summary bit address */ - uint64_t fmb_addr; /* Function measurement address and key */ - uint32_t reserved6; - uint32_t gd; -} QEMU_PACKED ZpciFib; - -int pci_dereg_irqs(S390PCIBusDevice *pbdev); -void pci_dereg_ioat(S390PCIIOMMU *iommu); -int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra); -int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra); -int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra); -int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra); -int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, - uint8_t ar, uintptr_t ra); -int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, - uintptr_t ra); -int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, - uintptr_t ra); -void fmb_timer_free(S390PCIBusDevice *pbdev); - -#define ZPCI_IO_BAR_MIN 0 -#define ZPCI_IO_BAR_MAX 5 -#define ZPCI_CONFIG_BAR 15 - #endif diff --git a/include/hw/s390x/s390-pci-inst.h b/include/hw/s390x/s390-pci-inst.h new file mode 100644 index 0000000000000000000000000000000000000000..a55c448aad24fa98fd4edf667b6cbe99414e8b03 --- /dev/null +++ b/include/hw/s390x/s390-pci-inst.h @@ -0,0 +1,119 @@ +/* + * s390 PCI instruction definitions + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka + * Hong Bo Li + * Yi Min Zhao + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef HW_S390_PCI_INST_H +#define HW_S390_PCI_INST_H + +#include "s390-pci-bus.h" +#include "sysemu/dma.h" + +/* Load/Store status codes */ +#define ZPCI_PCI_ST_FUNC_NOT_ENABLED 4 +#define ZPCI_PCI_ST_FUNC_IN_ERR 8 +#define ZPCI_PCI_ST_BLOCKED 12 +#define ZPCI_PCI_ST_INSUF_RES 16 +#define ZPCI_PCI_ST_INVAL_AS 20 +#define ZPCI_PCI_ST_FUNC_ALREADY_ENABLED 24 +#define ZPCI_PCI_ST_DMA_AS_NOT_ENABLED 28 +#define ZPCI_PCI_ST_2ND_OP_IN_INV_AS 36 +#define ZPCI_PCI_ST_FUNC_NOT_AVAIL 40 +#define ZPCI_PCI_ST_ALREADY_IN_RQ_STATE 44 + +/* Load/Store return codes */ +#define ZPCI_PCI_LS_OK 0 +#define ZPCI_PCI_LS_ERR 1 +#define ZPCI_PCI_LS_BUSY 2 +#define ZPCI_PCI_LS_INVAL_HANDLE 3 + +/* Modify PCI status codes */ +#define ZPCI_MOD_ST_RES_NOT_AVAIL 4 +#define ZPCI_MOD_ST_INSUF_RES 16 +#define ZPCI_MOD_ST_SEQUENCE 24 +#define ZPCI_MOD_ST_DMAAS_INVAL 28 +#define ZPCI_MOD_ST_FRAME_INVAL 32 +#define ZPCI_MOD_ST_ERROR_RECOVER 40 + +/* Modify PCI Function Controls */ +#define ZPCI_MOD_FC_REG_INT 2 +#define ZPCI_MOD_FC_DEREG_INT 3 +#define ZPCI_MOD_FC_REG_IOAT 4 +#define ZPCI_MOD_FC_DEREG_IOAT 5 +#define ZPCI_MOD_FC_REREG_IOAT 6 +#define ZPCI_MOD_FC_RESET_ERROR 7 +#define ZPCI_MOD_FC_RESET_BLOCK 9 +#define ZPCI_MOD_FC_SET_MEASURE 10 + +/* Store PCI Function Controls status codes */ +#define ZPCI_STPCIFC_ST_PERM_ERROR 8 +#define ZPCI_STPCIFC_ST_INVAL_DMAAS 28 +#define ZPCI_STPCIFC_ST_ERROR_RECOVER 40 + +/* Refresh PCI Translations status codes */ +#define ZPCI_RPCIT_ST_INSUFF_RES 16 + +/* FIB function controls */ +#define ZPCI_FIB_FC_ENABLED 0x80 +#define ZPCI_FIB_FC_ERROR 0x40 +#define ZPCI_FIB_FC_LS_BLOCKED 0x20 +#define ZPCI_FIB_FC_DMAAS_REG 0x10 + +/* FIB function controls */ +#define ZPCI_FIB_FC_ENABLED 0x80 +#define ZPCI_FIB_FC_ERROR 0x40 +#define ZPCI_FIB_FC_LS_BLOCKED 0x20 +#define ZPCI_FIB_FC_DMAAS_REG 0x10 + +/* Function Information Block */ +typedef struct ZpciFib { + uint8_t fmt; /* format */ + uint8_t reserved1[7]; + uint8_t fc; /* function controls */ + uint8_t reserved2; + uint16_t reserved3; + uint32_t reserved4; + uint64_t pba; /* PCI base address */ + uint64_t pal; /* PCI address limit */ + uint64_t iota; /* I/O Translation Anchor */ +#define FIB_DATA_ISC(x) (((x) >> 28) & 0x7) +#define FIB_DATA_NOI(x) (((x) >> 16) & 0xfff) +#define FIB_DATA_AIBVO(x) (((x) >> 8) & 0x3f) +#define FIB_DATA_SUM(x) (((x) >> 7) & 0x1) +#define FIB_DATA_AISBO(x) ((x) & 0x3f) + uint32_t data; + uint32_t reserved5; + uint64_t aibv; /* Adapter int bit vector address */ + uint64_t aisb; /* Adapter int summary bit address */ + uint64_t fmb_addr; /* Function measurement address and key */ + uint32_t reserved6; + uint32_t gd; +} QEMU_PACKED ZpciFib; + +int pci_dereg_irqs(S390PCIBusDevice *pbdev); +void pci_dereg_ioat(S390PCIIOMMU *iommu); +int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra); +int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra); +int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra); +int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra); +int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, + uint8_t ar, uintptr_t ra); +int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, + uintptr_t ra); +int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, + uintptr_t ra); +void fmb_timer_free(S390PCIBusDevice *pbdev); + +#define ZPCI_IO_BAR_MIN 0 +#define ZPCI_IO_BAR_MAX 5 +#define ZPCI_CONFIG_BAR 15 + +#endif diff --git a/include/hw/s390x/s390-pci-vfio.h b/include/hw/s390x/s390-pci-vfio.h new file mode 100644 index 0000000000000000000000000000000000000000..ff708aef500fcea9b5de66201aec27860b3cdab4 --- /dev/null +++ b/include/hw/s390x/s390-pci-vfio.h @@ -0,0 +1,39 @@ +/* + * s390 vfio-pci interfaces + * + * Copyright 2020 IBM Corp. + * Author(s): Matthew Rosato + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef HW_S390_PCI_VFIO_H +#define HW_S390_PCI_VFIO_H + +#include "hw/s390x/s390-pci-bus.h" +#include CONFIG_DEVICES + +#ifdef CONFIG_VFIO +bool s390_pci_update_dma_avail(int fd, unsigned int *avail); +S390PCIDMACount *s390_pci_start_dma_count(S390pciState *s, + S390PCIBusDevice *pbdev); +void s390_pci_end_dma_count(S390pciState *s, S390PCIDMACount *cnt); +void s390_pci_get_clp_info(S390PCIBusDevice *pbdev); +#else +static inline bool s390_pci_update_dma_avail(int fd, unsigned int *avail) +{ + return false; +} +static inline S390PCIDMACount *s390_pci_start_dma_count(S390pciState *s, + S390PCIBusDevice *pbdev) +{ + return NULL; +} +static inline void s390_pci_end_dma_count(S390pciState *s, + S390PCIDMACount *cnt) { } +static inline void s390_pci_get_clp_info(S390PCIBusDevice *pbdev) { } +#endif + +#endif diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h index cd1dccc6e3ba86455a9de5eb41cb04ee28083690..3331990e02bf42017fb1fb6e8d12568211844931 100644 --- a/include/hw/s390x/s390-virtio-ccw.h +++ b/include/hw/s390x/s390-virtio-ccw.h @@ -12,16 +12,14 @@ #define HW_S390X_S390_VIRTIO_CCW_H #include "hw/boards.h" +#include "qom/object.h" #define TYPE_S390_CCW_MACHINE "s390-ccw-machine" -#define S390_CCW_MACHINE(obj) \ - OBJECT_CHECK(S390CcwMachineState, (obj), TYPE_S390_CCW_MACHINE) +OBJECT_DECLARE_TYPE(S390CcwMachineState, S390CcwMachineClass, S390_CCW_MACHINE) -#define S390_MACHINE_CLASS(klass) \ - OBJECT_CLASS_CHECK(S390CcwMachineClass, (klass), TYPE_S390_CCW_MACHINE) -typedef struct S390CcwMachineState { +struct S390CcwMachineState { /*< private >*/ MachineState parent_obj; @@ -30,9 +28,9 @@ typedef struct S390CcwMachineState { bool dea_key_wrap; bool pv; uint8_t loadparm[8]; -} S390CcwMachineState; +}; -typedef struct S390CcwMachineClass { +struct S390CcwMachineClass { /*< private >*/ MachineClass parent_class; @@ -41,7 +39,7 @@ typedef struct S390CcwMachineClass { bool cpu_model_allowed; bool css_migration_enabled; bool hpage_1m_allowed; -} S390CcwMachineClass; +}; /* runtime-instrumentation allowed by the machine */ bool ri_allowed(void); diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h index 4687ecfe83957900e390709525204a16c6e8ad7f..e91b15d2d6af5feb2e7e7284bfbd698d313fefd3 100644 --- a/include/hw/s390x/s390_flic.h +++ b/include/hw/s390x/s390_flic.h @@ -17,6 +17,7 @@ #include "hw/s390x/adapter.h" #include "hw/virtio/virtio.h" #include "qemu/queue.h" +#include "qom/object.h" /* * Reserve enough gsis to accommodate all virtio devices. @@ -38,22 +39,18 @@ extern const VMStateDescription vmstate_adapter_routes; VMSTATE_STRUCT(_f, _s, 1, vmstate_adapter_routes, AdapterRoutes) #define TYPE_S390_FLIC_COMMON "s390-flic" -#define S390_FLIC_COMMON(obj) \ - OBJECT_CHECK(S390FLICState, (obj), TYPE_S390_FLIC_COMMON) +OBJECT_DECLARE_TYPE(S390FLICState, S390FLICStateClass, + S390_FLIC_COMMON) -typedef struct S390FLICState { +struct S390FLICState { SysBusDevice parent_obj; /* to limit AdapterRoutes.num_routes for compat */ uint32_t adapter_routes_max_batch; bool ais_supported; -} S390FLICState; +}; -#define S390_FLIC_COMMON_CLASS(klass) \ - OBJECT_CLASS_CHECK(S390FLICStateClass, (klass), TYPE_S390_FLIC_COMMON) -#define S390_FLIC_COMMON_GET_CLASS(obj) \ - OBJECT_GET_CLASS(S390FLICStateClass, (obj), TYPE_S390_FLIC_COMMON) -typedef struct S390FLICStateClass { +struct S390FLICStateClass { DeviceClass parent_class; int (*register_io_adapter)(S390FLICState *fs, uint32_t id, uint8_t isc, @@ -72,15 +69,15 @@ typedef struct S390FLICStateClass { uint16_t subchannel_nr, uint32_t io_int_parm, uint32_t io_int_word); void (*inject_crw_mchk)(S390FLICState *fs); -} S390FLICStateClass; +}; #define TYPE_KVM_S390_FLIC "s390-flic-kvm" -#define KVM_S390_FLIC(obj) \ - OBJECT_CHECK(KVMS390FLICState, (obj), TYPE_KVM_S390_FLIC) +typedef struct KVMS390FLICState KVMS390FLICState; +DECLARE_INSTANCE_CHECKER(KVMS390FLICState, KVM_S390_FLIC, + TYPE_KVM_S390_FLIC) #define TYPE_QEMU_S390_FLIC "s390-flic-qemu" -#define QEMU_S390_FLIC(obj) \ - OBJECT_CHECK(QEMUS390FLICState, (obj), TYPE_QEMU_S390_FLIC) +OBJECT_DECLARE_SIMPLE_TYPE(QEMUS390FLICState, QEMU_S390_FLIC) #define SIC_IRQ_MODE_ALL 0 #define SIC_IRQ_MODE_SINGLE 1 @@ -114,14 +111,14 @@ typedef struct QEMUS390FlicIO { QLIST_ENTRY(QEMUS390FlicIO) next; } QEMUS390FlicIO; -typedef struct QEMUS390FLICState { +struct QEMUS390FLICState { S390FLICState parent_obj; uint32_t pending; uint32_t service_param; uint8_t simm; uint8_t nimm; QLIST_HEAD(, QEMUS390FlicIO) io[8]; -} QEMUS390FLICState; +}; uint32_t qemu_s390_flic_dequeue_service(QEMUS390FLICState *flic); QEMUS390FlicIO *qemu_s390_flic_dequeue_io(QEMUS390FLICState *flic, diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h index 822eff4396ff5dded7496e50575dd00f3ef6ffe5..d3ade40a5a8d1a1b630bf9a96257b00373faf6c3 100644 --- a/include/hw/s390x/sclp.h +++ b/include/hw/s390x/sclp.h @@ -16,6 +16,7 @@ #include "hw/sysbus.h" #include "target/s390x/cpu-qom.h" +#include "qom/object.h" #define SCLP_CMD_CODE_MASK 0xffff00ff @@ -110,6 +111,7 @@ typedef struct CPUEntry { uint8_t reserved1; } QEMU_PACKED CPUEntry; +#define SCLP_READ_SCP_INFO_FIXED_CPU_OFFSET 128 typedef struct ReadInfo { SCCBHeader h; uint16_t rnmax; @@ -132,7 +134,15 @@ typedef struct ReadInfo { uint16_t highest_cpu; uint8_t _reserved5[124 - 122]; /* 122-123 */ uint32_t hmfai; + uint8_t _reserved7[134 - 128]; /* 128-133 */ + uint8_t fac134; + uint8_t _reserved8[144 - 135]; /* 135-143 */ struct CPUEntry entries[]; + /* + * When the Extended-Length SCCB (ELS) feature is enabled the + * start of the entries field begins at an offset denoted by the + * offset_cpu field, otherwise it's at an offset of 128. + */ } QEMU_PACKED ReadInfo; typedef struct ReadCpuInfo { @@ -177,26 +187,25 @@ typedef struct IoaCfgSccb { typedef struct SCCB { SCCBHeader h; - char data[SCCB_DATA_LEN]; + char data[]; } QEMU_PACKED SCCB; #define TYPE_SCLP "sclp" -#define SCLP(obj) OBJECT_CHECK(SCLPDevice, (obj), TYPE_SCLP) -#define SCLP_CLASS(oc) OBJECT_CLASS_CHECK(SCLPDeviceClass, (oc), TYPE_SCLP) -#define SCLP_GET_CLASS(obj) OBJECT_GET_CLASS(SCLPDeviceClass, (obj), TYPE_SCLP) +OBJECT_DECLARE_TYPE(SCLPDevice, SCLPDeviceClass, + SCLP) -typedef struct SCLPEventFacility SCLPEventFacility; +struct SCLPEventFacility; -typedef struct SCLPDevice { +struct SCLPDevice { /* private */ DeviceState parent_obj; - SCLPEventFacility *event_facility; + struct SCLPEventFacility *event_facility; int increment_size; /* public */ -} SCLPDevice; +}; -typedef struct SCLPDeviceClass { +struct SCLPDeviceClass { /* private */ DeviceClass parent_class; void (*read_SCP_info)(SCLPDevice *sclp, SCCB *sccb); @@ -205,7 +214,7 @@ typedef struct SCLPDeviceClass { /* public */ void (*execute)(SCLPDevice *sclp, SCCB *sccb, uint32_t code); void (*service_interrupt)(SCLPDevice *sclp, uint32_t sccb); -} SCLPDeviceClass; +}; static inline int sccb_data_len(SCCB *sccb) { diff --git a/include/hw/s390x/storage-attributes.h b/include/hw/s390x/storage-attributes.h index 4f7c6c0877c3a117387325f44ae4659e3ad2bb3a..5239eb538c1b087797867a247abfc14551af6a4d 100644 --- a/include/hw/s390x/storage-attributes.h +++ b/include/hw/s390x/storage-attributes.h @@ -14,26 +14,22 @@ #include "hw/qdev-core.h" #include "monitor/monitor.h" +#include "qom/object.h" #define TYPE_S390_STATTRIB "s390-storage_attributes" #define TYPE_QEMU_S390_STATTRIB "s390-storage_attributes-qemu" #define TYPE_KVM_S390_STATTRIB "s390-storage_attributes-kvm" -#define S390_STATTRIB(obj) \ - OBJECT_CHECK(S390StAttribState, (obj), TYPE_S390_STATTRIB) +OBJECT_DECLARE_TYPE(S390StAttribState, S390StAttribClass, S390_STATTRIB) -typedef struct S390StAttribState { +struct S390StAttribState { DeviceState parent_obj; uint64_t migration_cur_gfn; bool migration_enabled; -} S390StAttribState; +}; -#define S390_STATTRIB_CLASS(klass) \ - OBJECT_CLASS_CHECK(S390StAttribClass, (klass), TYPE_S390_STATTRIB) -#define S390_STATTRIB_GET_CLASS(obj) \ - OBJECT_GET_CLASS(S390StAttribClass, (obj), TYPE_S390_STATTRIB) -typedef struct S390StAttribClass { +struct S390StAttribClass { DeviceClass parent_class; /* Return value: < 0 on error, or new count */ int (*get_stattr)(S390StAttribState *sa, uint64_t *start_gfn, @@ -46,23 +42,25 @@ typedef struct S390StAttribClass { int (*set_migrationmode)(S390StAttribState *sa, bool value); int (*get_active)(S390StAttribState *sa); long long (*get_dirtycount)(S390StAttribState *sa); -} S390StAttribClass; +}; -#define QEMU_S390_STATTRIB(obj) \ - OBJECT_CHECK(QEMUS390StAttribState, (obj), TYPE_QEMU_S390_STATTRIB) +typedef struct QEMUS390StAttribState QEMUS390StAttribState; +DECLARE_INSTANCE_CHECKER(QEMUS390StAttribState, QEMU_S390_STATTRIB, + TYPE_QEMU_S390_STATTRIB) -typedef struct QEMUS390StAttribState { +struct QEMUS390StAttribState { S390StAttribState parent_obj; -} QEMUS390StAttribState; +}; -#define KVM_S390_STATTRIB(obj) \ - OBJECT_CHECK(KVMS390StAttribState, (obj), TYPE_KVM_S390_STATTRIB) +typedef struct KVMS390StAttribState KVMS390StAttribState; +DECLARE_INSTANCE_CHECKER(KVMS390StAttribState, KVM_S390_STATTRIB, + TYPE_KVM_S390_STATTRIB) -typedef struct KVMS390StAttribState { +struct KVMS390StAttribState { S390StAttribState parent_obj; uint64_t still_dirty; uint8_t *incoming_buffer; -} KVMS390StAttribState; +}; void s390_stattrib_init(void); diff --git a/include/hw/s390x/storage-keys.h b/include/hw/s390x/storage-keys.h index 3f1ae7e7789bc5b4c33aef14adf3de2d6c4aa1e8..2888d42d0b4a3d12e65057abd139a3f490d6a518 100644 --- a/include/hw/s390x/storage-keys.h +++ b/include/hw/s390x/storage-keys.h @@ -14,41 +14,38 @@ #include "hw/qdev-core.h" #include "monitor/monitor.h" +#include "qom/object.h" #define TYPE_S390_SKEYS "s390-skeys" -#define S390_SKEYS(obj) \ - OBJECT_CHECK(S390SKeysState, (obj), TYPE_S390_SKEYS) +OBJECT_DECLARE_TYPE(S390SKeysState, S390SKeysClass, S390_SKEYS) -typedef struct S390SKeysState { +struct S390SKeysState { DeviceState parent_obj; bool migration_enabled; -} S390SKeysState; +}; -#define S390_SKEYS_CLASS(klass) \ - OBJECT_CLASS_CHECK(S390SKeysClass, (klass), TYPE_S390_SKEYS) -#define S390_SKEYS_GET_CLASS(obj) \ - OBJECT_GET_CLASS(S390SKeysClass, (obj), TYPE_S390_SKEYS) -typedef struct S390SKeysClass { +struct S390SKeysClass { DeviceClass parent_class; int (*skeys_enabled)(S390SKeysState *ks); int (*get_skeys)(S390SKeysState *ks, uint64_t start_gfn, uint64_t count, uint8_t *keys); int (*set_skeys)(S390SKeysState *ks, uint64_t start_gfn, uint64_t count, uint8_t *keys); -} S390SKeysClass; +}; #define TYPE_KVM_S390_SKEYS "s390-skeys-kvm" #define TYPE_QEMU_S390_SKEYS "s390-skeys-qemu" -#define QEMU_S390_SKEYS(obj) \ - OBJECT_CHECK(QEMUS390SKeysState, (obj), TYPE_QEMU_S390_SKEYS) +typedef struct QEMUS390SKeysState QEMUS390SKeysState; +DECLARE_INSTANCE_CHECKER(QEMUS390SKeysState, QEMU_S390_SKEYS, + TYPE_QEMU_S390_SKEYS) -typedef struct QEMUS390SKeysState { +struct QEMUS390SKeysState { S390SKeysState parent_obj; uint8_t *keydata; uint32_t key_count; -} QEMUS390SKeysState; +}; void s390_skeys_init(void); diff --git a/include/hw/s390x/tod.h b/include/hw/s390x/tod.h index 4251623f7f1fe0cd2d299e50ba4928072c446ecd..ff3195a4bf8a584f2c25a0758570d437ddd02708 100644 --- a/include/hw/s390x/tod.h +++ b/include/hw/s390x/tod.h @@ -13,6 +13,7 @@ #include "hw/qdev-core.h" #include "target/s390x/s390-tod.h" +#include "qom/object.h" typedef struct S390TOD { uint8_t high; @@ -20,15 +21,11 @@ typedef struct S390TOD { } S390TOD; #define TYPE_S390_TOD "s390-tod" -#define S390_TOD(obj) OBJECT_CHECK(S390TODState, (obj), TYPE_S390_TOD) -#define S390_TOD_CLASS(oc) OBJECT_CLASS_CHECK(S390TODClass, (oc), \ - TYPE_S390_TOD) -#define S390_TOD_GET_CLASS(obj) OBJECT_GET_CLASS(S390TODClass, (obj), \ - TYPE_S390_TOD) +OBJECT_DECLARE_TYPE(S390TODState, S390TODClass, S390_TOD) #define TYPE_KVM_S390_TOD TYPE_S390_TOD "-kvm" #define TYPE_QEMU_S390_TOD TYPE_S390_TOD "-qemu" -typedef struct S390TODState { +struct S390TODState { /* private */ DeviceState parent_obj; @@ -39,9 +36,9 @@ typedef struct S390TODState { S390TOD base; /* Used by KVM to remember if the TOD is stopped and base is valid. */ bool stopped; -} S390TODState; +}; -typedef struct S390TODClass { +struct S390TODClass { /* private */ DeviceClass parent_class; void (*parent_realize)(DeviceState *dev, Error **errp); @@ -49,7 +46,7 @@ typedef struct S390TODClass { /* public */ void (*get)(const S390TODState *td, S390TOD *tod, Error **errp); void (*set)(S390TODState *td, const S390TOD *tod, Error **errp); -} S390TODClass; +}; void s390_init_tod(void); S390TODState *s390_get_todstate(void); diff --git a/include/hw/s390x/vfio-ccw.h b/include/hw/s390x/vfio-ccw.h index ee5250d0d7886922455fb0e54d9e60ec22e0f332..63a909eb7e91ac0d59913d566e536845a43b889b 100644 --- a/include/hw/s390x/vfio-ccw.h +++ b/include/hw/s390x/vfio-ccw.h @@ -17,12 +17,11 @@ #include "hw/vfio/vfio-common.h" #include "hw/s390x/s390-ccw.h" #include "hw/s390x/ccw-device.h" +#include "qom/object.h" #define TYPE_VFIO_CCW "vfio-ccw" -#define VFIO_CCW(obj) \ - OBJECT_CHECK(VFIOCCWDevice, (obj), TYPE_VFIO_CCW) +OBJECT_DECLARE_SIMPLE_TYPE(VFIOCCWDevice, VFIO_CCW) #define TYPE_VFIO_CCW "vfio-ccw" -typedef struct VFIOCCWDevice VFIOCCWDevice; #endif diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h index 6ba47dac416b882aaa5d0b877b5bdf9c0b645dc7..60cc3047a5d0906e6501ef9e5dbbaff5fd94f2ba 100644 --- a/include/hw/scsi/esp.h +++ b/include/hw/scsi/esp.h @@ -3,6 +3,7 @@ #include "hw/scsi/scsi.h" #include "hw/sysbus.h" +#include "qom/object.h" /* esp.c */ #define ESP_MAX_DEVS 7 @@ -65,9 +66,9 @@ struct ESPState { }; #define TYPE_ESP "esp" -#define ESP_STATE(obj) OBJECT_CHECK(SysBusESPState, (obj), TYPE_ESP) +OBJECT_DECLARE_SIMPLE_TYPE(SysBusESPState, ESP) -typedef struct { +struct SysBusESPState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -76,7 +77,7 @@ typedef struct { MemoryRegion pdma; uint32_t it_shift; ESPState esp; -} SysBusESPState; +}; #define ESP_TCLO 0x0 #define ESP_TCMID 0x1 diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index 2fc23e44baf4e294e766866d6a3aac360c373cb8..09fa5c9d2a03f35f876e83f21373c273a5a3a62f 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -6,6 +6,7 @@ #include "hw/qdev-core.h" #include "scsi/utils.h" #include "qemu/notify.h" +#include "qom/object.h" #define MAX_SCSI_DEVS 255 @@ -49,14 +50,9 @@ struct SCSIRequest { }; #define TYPE_SCSI_DEVICE "scsi-device" -#define SCSI_DEVICE(obj) \ - OBJECT_CHECK(SCSIDevice, (obj), TYPE_SCSI_DEVICE) -#define SCSI_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(SCSIDeviceClass, (klass), TYPE_SCSI_DEVICE) -#define SCSI_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SCSIDeviceClass, (obj), TYPE_SCSI_DEVICE) - -typedef struct SCSIDeviceClass { +OBJECT_DECLARE_TYPE(SCSIDevice, SCSIDeviceClass, SCSI_DEVICE) + +struct SCSIDeviceClass { DeviceClass parent_class; void (*realize)(SCSIDevice *dev, Error **errp); void (*unrealize)(SCSIDevice *dev); @@ -65,7 +61,7 @@ typedef struct SCSIDeviceClass { SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun, uint8_t *buf, void *hba_private); void (*unit_attention_reported)(SCSIDevice *s); -} SCSIDeviceClass; +}; struct SCSIDevice { @@ -136,7 +132,7 @@ struct SCSIBusInfo { }; #define TYPE_SCSI_BUS "SCSI" -#define SCSI_BUS(obj) OBJECT_CHECK(SCSIBus, (obj), TYPE_SCSI_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(SCSIBus, SCSI_BUS) struct SCSIBus { BusState qbus; @@ -194,6 +190,7 @@ int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed); int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size, uint8_t *buf, uint8_t buf_size); SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun); +SCSIDevice *scsi_device_get(SCSIBus *bus, int channel, int target, int lun); /* scsi-generic.c. */ extern const SCSIReqOps scsi_generic_req_ops; diff --git a/include/hw/sd/allwinner-sdhost.h b/include/hw/sd/allwinner-sdhost.h index d94606a8531a43d1c2c3519a2d5160f03a4283a0..bfe08ff4ef21db87906174473219c633f8ec03c3 100644 --- a/include/hw/sd/allwinner-sdhost.h +++ b/include/hw/sd/allwinner-sdhost.h @@ -45,19 +45,14 @@ * @{ */ -#define AW_SDHOST(obj) \ - OBJECT_CHECK(AwSdHostState, (obj), TYPE_AW_SDHOST) -#define AW_SDHOST_CLASS(klass) \ - OBJECT_CLASS_CHECK(AwSdHostClass, (klass), TYPE_AW_SDHOST) -#define AW_SDHOST_GET_CLASS(obj) \ - OBJECT_GET_CLASS(AwSdHostClass, (obj), TYPE_AW_SDHOST) +OBJECT_DECLARE_TYPE(AwSdHostState, AwSdHostClass, AW_SDHOST) /** @} */ /** * Allwinner SD Host Controller object instance state. */ -typedef struct AwSdHostState { +struct AwSdHostState { /*< private >*/ SysBusDevice busdev; /*< public >*/ @@ -71,6 +66,12 @@ typedef struct AwSdHostState { /** Interrupt output signal to notify CPU */ qemu_irq irq; + /** Memory region where DMA transfers are done */ + MemoryRegion *dma_mr; + + /** Address space used internally for DMA transfers */ + AddressSpace dma_as; + /** Number of bytes left in current DMA transfer */ uint32_t transfer_cnt; @@ -113,7 +114,7 @@ typedef struct AwSdHostState { /** @} */ -} AwSdHostState; +}; /** * Allwinner SD Host Controller class-level struct. @@ -122,7 +123,7 @@ typedef struct AwSdHostState { * such that the generic code can use this struct to support * all devices. */ -typedef struct AwSdHostClass { +struct AwSdHostClass { /*< private >*/ SysBusDeviceClass parent_class; /*< public >*/ @@ -130,6 +131,6 @@ typedef struct AwSdHostClass { /** Maximum buffer size in bytes per DMA descriptor */ size_t max_desc_size; -} AwSdHostClass; +}; #endif /* HW_SD_ALLWINNER_SDHOST_H */ diff --git a/include/hw/sd/aspeed_sdhci.h b/include/hw/sd/aspeed_sdhci.h index dffbb46946b9b4bbbead814bc0811c32179df64f..b093d1b861235befe48292543e827251c5cc4141 100644 --- a/include/hw/sd/aspeed_sdhci.h +++ b/include/hw/sd/aspeed_sdhci.h @@ -10,17 +10,17 @@ #define ASPEED_SDHCI_H #include "hw/sd/sdhci.h" +#include "qom/object.h" #define TYPE_ASPEED_SDHCI "aspeed.sdhci" -#define ASPEED_SDHCI(obj) OBJECT_CHECK(AspeedSDHCIState, (obj), \ - TYPE_ASPEED_SDHCI) +OBJECT_DECLARE_SIMPLE_TYPE(AspeedSDHCIState, ASPEED_SDHCI) #define ASPEED_SDHCI_CAPABILITIES 0x01E80080 #define ASPEED_SDHCI_NUM_SLOTS 2 #define ASPEED_SDHCI_NUM_REGS (ASPEED_SDHCI_REG_SIZE / sizeof(uint32_t)) #define ASPEED_SDHCI_REG_SIZE 0x100 -typedef struct AspeedSDHCIState { +struct AspeedSDHCIState { SysBusDevice parent; SDHCIState slots[ASPEED_SDHCI_NUM_SLOTS]; @@ -30,6 +30,6 @@ typedef struct AspeedSDHCIState { qemu_irq irq; uint32_t regs[ASPEED_SDHCI_NUM_REGS]; -} AspeedSDHCIState; +}; #endif /* ASPEED_SDHCI_H */ diff --git a/include/hw/sd/bcm2835_sdhost.h b/include/hw/sd/bcm2835_sdhost.h index 7520dd6507b9fd5a0ce597959843710f9fc1329a..f6bca5c3979fd86bb977129ee8d134ec70fcc98e 100644 --- a/include/hw/sd/bcm2835_sdhost.h +++ b/include/hw/sd/bcm2835_sdhost.h @@ -16,14 +16,14 @@ #include "hw/sysbus.h" #include "hw/sd/sd.h" +#include "qom/object.h" #define TYPE_BCM2835_SDHOST "bcm2835-sdhost" -#define BCM2835_SDHOST(obj) \ - OBJECT_CHECK(BCM2835SDHostState, (obj), TYPE_BCM2835_SDHOST) +OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SDHostState, BCM2835_SDHOST) #define BCM2835_SDHOST_FIFO_LEN 16 -typedef struct { +struct BCM2835SDHostState { SysBusDevice busdev; SDBus sdbus; MemoryRegion iomem; @@ -43,6 +43,6 @@ typedef struct { uint32_t datacnt; qemu_irq irq; -} BCM2835SDHostState; +}; #endif diff --git a/include/hw/sd/cadence_sdhci.h b/include/hw/sd/cadence_sdhci.h new file mode 100644 index 0000000000000000000000000000000000000000..cd8288b7d807066513937d2669e7efd99ecd79b4 --- /dev/null +++ b/include/hw/sd/cadence_sdhci.h @@ -0,0 +1,47 @@ +/* + * Cadence SDHCI emulation + * + * Copyright (c) 2020 Wind River Systems, Inc. + * + * Author: + * Bin Meng + * + * 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 or + * (at your option) version 3 of the License. + * + * 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 . + */ + +#ifndef CADENCE_SDHCI_H +#define CADENCE_SDHCI_H + +#include "hw/sd/sdhci.h" + +#define CADENCE_SDHCI_REG_SIZE 0x100 +#define CADENCE_SDHCI_NUM_REGS (CADENCE_SDHCI_REG_SIZE / sizeof(uint32_t)) + +typedef struct CadenceSDHCIState { + SysBusDevice parent; + + MemoryRegion container; + MemoryRegion iomem; + BusState *bus; + + uint32_t regs[CADENCE_SDHCI_NUM_REGS]; + + SDHCIState sdhci; +} CadenceSDHCIState; + +#define TYPE_CADENCE_SDHCI "cadence.sdhci" +#define CADENCE_SDHCI(obj) OBJECT_CHECK(CadenceSDHCIState, (obj), \ + TYPE_CADENCE_SDHCI) + +#endif /* CADENCE_SDHCI_H */ diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h index a84b8e274a32c09dcf7ee951989593e79ebc3a30..59d108d453534620ec95671b9c4100754f3dcc40 100644 --- a/include/hw/sd/sd.h +++ b/include/hw/sd/sd.h @@ -31,6 +31,7 @@ #define HW_SD_H #include "hw/qdev-core.h" +#include "qom/object.h" #define OUT_OF_RANGE (1 << 31) #define ADDRESS_ERROR (1 << 30) @@ -88,24 +89,33 @@ typedef struct { uint8_t crc; } SDRequest; -typedef struct SDState SDState; -typedef struct SDBus SDBus; #define TYPE_SD_CARD "sd-card" -#define SD_CARD(obj) OBJECT_CHECK(SDState, (obj), TYPE_SD_CARD) -#define SD_CARD_CLASS(klass) \ - OBJECT_CLASS_CHECK(SDCardClass, (klass), TYPE_SD_CARD) -#define SD_CARD_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SDCardClass, (obj), TYPE_SD_CARD) +OBJECT_DECLARE_TYPE(SDState, SDCardClass, SD_CARD) -typedef struct { +struct SDCardClass { /*< private >*/ DeviceClass parent_class; /*< public >*/ int (*do_command)(SDState *sd, SDRequest *req, uint8_t *response); - void (*write_data)(SDState *sd, uint8_t value); - uint8_t (*read_data)(SDState *sd); + /** + * Write a byte to a SD card. + * @sd: card + * @value: byte to write + * + * Write a byte on the data lines of a SD card. + */ + void (*write_byte)(SDState *sd, uint8_t value); + /** + * Read a byte from a SD card. + * @sd: card + * + * Read a byte from the data lines of a SD card. + * + * Return: byte value read + */ + uint8_t (*read_byte)(SDState *sd); bool (*data_ready)(SDState *sd); void (*set_voltage)(SDState *sd, uint16_t millivolts); uint8_t (*get_dat_lines)(SDState *sd); @@ -113,18 +123,17 @@ typedef struct { void (*enable)(SDState *sd, bool enable); bool (*get_inserted)(SDState *sd); bool (*get_readonly)(SDState *sd); -} SDCardClass; +}; #define TYPE_SD_BUS "sd-bus" -#define SD_BUS(obj) OBJECT_CHECK(SDBus, (obj), TYPE_SD_BUS) -#define SD_BUS_CLASS(klass) OBJECT_CLASS_CHECK(SDBusClass, (klass), TYPE_SD_BUS) -#define SD_BUS_GET_CLASS(obj) OBJECT_GET_CLASS(SDBusClass, (obj), TYPE_SD_BUS) +OBJECT_DECLARE_TYPE(SDBus, SDBusClass, + SD_BUS) struct SDBus { BusState qbus; }; -typedef struct { +struct SDBusClass { /*< private >*/ BusClass parent_class; /*< public >*/ @@ -134,24 +143,7 @@ typedef struct { */ void (*set_inserted)(DeviceState *dev, bool inserted); void (*set_readonly)(DeviceState *dev, bool readonly); -} SDBusClass; - -/* Legacy functions to be used only by non-qdevified callers */ -SDState *sd_init(BlockBackend *bs, bool is_spi); -int sd_do_command(SDState *sd, SDRequest *req, - uint8_t *response); -void sd_write_data(SDState *sd, uint8_t value); -uint8_t sd_read_data(SDState *sd); -void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert); -bool sd_data_ready(SDState *sd); -/* sd_enable should not be used -- it is only used on the nseries boards, - * where it is part of a broken implementation of the MMC card slot switch - * (there should be two card slots which are multiplexed to a single MMC - * controller, but instead we model it with one card and controller and - * disable the card when the second slot is selected, so it looks like the - * second slot is always empty). - */ -void sd_enable(SDState *sd, bool enable); +}; /* Functions to be used by qdevified callers (working via * an SDBus rather than directly with SDState) @@ -160,8 +152,41 @@ void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts); uint8_t sdbus_get_dat_lines(SDBus *sdbus); bool sdbus_get_cmd_line(SDBus *sdbus); int sdbus_do_command(SDBus *sd, SDRequest *req, uint8_t *response); -void sdbus_write_data(SDBus *sd, uint8_t value); -uint8_t sdbus_read_data(SDBus *sd); +/** + * Write a byte to a SD bus. + * @sd: bus + * @value: byte to write + * + * Write a byte on the data lines of a SD bus. + */ +void sdbus_write_byte(SDBus *sd, uint8_t value); +/** + * Read a byte from a SD bus. + * @sd: bus + * + * Read a byte from the data lines of a SD bus. + * + * Return: byte value read + */ +uint8_t sdbus_read_byte(SDBus *sd); +/** + * Write data to a SD bus. + * @sdbus: bus + * @buf: data to write + * @length: number of bytes to write + * + * Write multiple bytes of data on the data lines of a SD bus. + */ +void sdbus_write_data(SDBus *sdbus, const void *buf, size_t length); +/** + * Read data from a SD bus. + * @sdbus: bus + * @buf: buffer to read data into + * @length: number of bytes to read + * + * Read multiple bytes of data on the data lines of a SD bus. + */ +void sdbus_read_data(SDBus *sdbus, void *buf, size_t length); bool sdbus_data_ready(SDBus *sd); bool sdbus_get_inserted(SDBus *sd); bool sdbus_get_readonly(SDBus *sd); diff --git a/include/hw/sd/sdcard_legacy.h b/include/hw/sd/sdcard_legacy.h new file mode 100644 index 0000000000000000000000000000000000000000..0dc388955512cf5b5fa6a4f3fab2fe4c34068e10 --- /dev/null +++ b/include/hw/sd/sdcard_legacy.h @@ -0,0 +1,50 @@ +/* + * SD Memory Card emulation (deprecated legacy API) + * + * Copyright (c) 2006 Andrzej Zaborowski + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef HW_SDCARD_LEGACY_H +#define HW_SDCARD_LEGACY_H + +#include "hw/sd/sd.h" + +/* Legacy functions to be used only by non-qdevified callers */ +SDState *sd_init(BlockBackend *blk, bool is_spi); +int sd_do_command(SDState *card, SDRequest *request, uint8_t *response); +void sd_write_byte(SDState *card, uint8_t value); +uint8_t sd_read_byte(SDState *card); +void sd_set_cb(SDState *card, qemu_irq readonly, qemu_irq insert); + +/* sd_enable should not be used -- it is only used on the nseries boards, + * where it is part of a broken implementation of the MMC card slot switch + * (there should be two card slots which are multiplexed to a single MMC + * controller, but instead we model it with one card and controller and + * disable the card when the second slot is selected, so it looks like the + * second slot is always empty). + */ +void sd_enable(SDState *card, bool enable); + +#endif /* HW_SDCARD_LEGACY_H */ diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h index c6868c96994916dd3ee045c60a71e0c79bea1e63..01a64c5442bfb66874693b1b8430b01f28f7912f 100644 --- a/include/hw/sd/sdhci.h +++ b/include/hw/sd/sdhci.h @@ -28,9 +28,10 @@ #include "hw/pci/pci.h" #include "hw/sysbus.h" #include "hw/sd/sd.h" +#include "qom/object.h" /* SD/MMC host controller state */ -typedef struct SDHCIState { +struct SDHCIState { /*< private >*/ union { PCIDevice pcidev; @@ -74,6 +75,7 @@ typedef struct SDHCIState { uint16_t acmd12errsts; /* Auto CMD12 error status register */ uint16_t hostctl2; /* Host Control 2 */ uint64_t admasysaddr; /* ADMA System Address Register */ + uint16_t vendor_spec; /* Vendor specific register */ /* Read-only registers */ uint64_t capareg; /* Capabilities Register */ @@ -96,7 +98,12 @@ typedef struct SDHCIState { uint32_t quirks; uint8_t sd_spec_version; uint8_t uhs_mode; -} SDHCIState; + uint8_t vendor; /* For vendor specific functionality */ +}; +typedef struct SDHCIState SDHCIState; + +#define SDHCI_VENDOR_NONE 0 +#define SDHCI_VENDOR_IMX 1 /* * Controller does not provide transfer-complete interrupt when not @@ -108,11 +115,12 @@ typedef struct SDHCIState { #define SDHCI_QUIRK_NO_BUSY_IRQ BIT(14) #define TYPE_PCI_SDHCI "sdhci-pci" -#define PCI_SDHCI(obj) OBJECT_CHECK(SDHCIState, (obj), TYPE_PCI_SDHCI) +DECLARE_INSTANCE_CHECKER(SDHCIState, PCI_SDHCI, + TYPE_PCI_SDHCI) #define TYPE_SYSBUS_SDHCI "generic-sdhci" -#define SYSBUS_SDHCI(obj) \ - OBJECT_CHECK(SDHCIState, (obj), TYPE_SYSBUS_SDHCI) +DECLARE_INSTANCE_CHECKER(SDHCIState, SYSBUS_SDHCI, + TYPE_SYSBUS_SDHCI) #define TYPE_IMX_USDHC "imx-usdhc" diff --git a/include/hw/semihosting/semihost.h b/include/hw/semihosting/semihost.h index b8ce5117ae0102cc2a8dcb5bac3fbdd2d744a327..0c55ade3ac1c1d3513852f2b7b5d0632e4da3d91 100644 --- a/include/hw/semihosting/semihost.h +++ b/include/hw/semihosting/semihost.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/hw/sh4/sh.h b/include/hw/sh4/sh.h index 767a2df7e2df8ab887ce7a59756529fcd0514c76..93f464bf4cd608b2b39765159a507e0757ebda58 100644 --- a/include/hw/sh4/sh.h +++ b/include/hw/sh4/sh.h @@ -10,9 +10,8 @@ /* sh7750.c */ struct SH7750State; -struct MemoryRegion; -struct SH7750State *sh7750_init(SuperHCPU *cpu, struct MemoryRegion *sysmem); +struct SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem); typedef struct { /* The callback will be triggered if any of the designated lines change */ @@ -28,15 +27,6 @@ typedef struct { int sh7750_register_io_device(struct SH7750State *s, sh7750_io_device * device); -/* sh_timer.c */ -#define TMU012_FEAT_TOCR (1 << 0) -#define TMU012_FEAT_3CHAN (1 << 1) -#define TMU012_FEAT_EXTCLK (1 << 2) -void tmu012_init(struct MemoryRegion *sysmem, hwaddr base, - int feat, uint32_t freq, - qemu_irq ch0_irq, qemu_irq ch1_irq, - qemu_irq ch2_irq0, qemu_irq ch2_irq1); - /* sh_serial.c */ #define SH_SERIAL_FEAT_SCIF (1 << 0) diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h index 02bd7412096e03ed9e66706dc26108317f3c99d7..6387f2b612869e20b2ffe63fd6c4259e99073091 100644 --- a/include/hw/southbridge/piix.h +++ b/include/hw/southbridge/piix.h @@ -13,6 +13,7 @@ #define HW_SOUTHBRIDGE_PIIX_H #include "hw/pci/pci.h" +#include "qom/object.h" #define TYPE_PIIX4_PM "PIIX4_PM" @@ -35,7 +36,7 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, #define PIIX_NUM_PIC_IRQS 16 /* i8259 * 2 */ #define PIIX_NUM_PIRQS 4ULL /* PIRQ[A-D] */ -typedef struct PIIXState { +struct PIIXState { PCIDevice dev; /* @@ -62,7 +63,12 @@ typedef struct PIIXState { /* IO memory region for Reset Control Register (PIIX_RCR_IOPORT) */ MemoryRegion rcr_mem; -} PIIX3State; +}; +typedef struct PIIXState PIIX3State; + +#define TYPE_PIIX3_PCI_DEVICE "pci-piix3" +DECLARE_INSTANCE_CHECKER(PIIX3State, PIIX3_PCI_DEVICE, + TYPE_PIIX3_PCI_DEVICE) extern PCIDevice *piix4_dev; diff --git a/include/hw/sparc/sparc32_dma.h b/include/hw/sparc/sparc32_dma.h index ab42c5421bc3ebed76c866522d552158695208f2..cde8ec02cb6543afa131788588ee5258412bd8a6 100644 --- a/include/hw/sparc/sparc32_dma.h +++ b/include/hw/sparc/sparc32_dma.h @@ -4,14 +4,13 @@ #include "hw/sysbus.h" #include "hw/scsi/esp.h" #include "hw/net/lance.h" +#include "qom/object.h" #define DMA_REGS 4 #define TYPE_SPARC32_DMA_DEVICE "sparc32-dma-device" -#define SPARC32_DMA_DEVICE(obj) OBJECT_CHECK(DMADeviceState, (obj), \ - TYPE_SPARC32_DMA_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(DMADeviceState, SPARC32_DMA_DEVICE) -typedef struct DMADeviceState DMADeviceState; struct DMADeviceState { SysBusDevice parent_obj; @@ -24,37 +23,34 @@ struct DMADeviceState { }; #define TYPE_SPARC32_ESPDMA_DEVICE "sparc32-espdma" -#define SPARC32_ESPDMA_DEVICE(obj) OBJECT_CHECK(ESPDMADeviceState, (obj), \ - TYPE_SPARC32_ESPDMA_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(ESPDMADeviceState, SPARC32_ESPDMA_DEVICE) -typedef struct ESPDMADeviceState { +struct ESPDMADeviceState { DMADeviceState parent_obj; - SysBusESPState *esp; -} ESPDMADeviceState; + SysBusESPState esp; +}; #define TYPE_SPARC32_LEDMA_DEVICE "sparc32-ledma" -#define SPARC32_LEDMA_DEVICE(obj) OBJECT_CHECK(LEDMADeviceState, (obj), \ - TYPE_SPARC32_LEDMA_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(LEDMADeviceState, SPARC32_LEDMA_DEVICE) -typedef struct LEDMADeviceState { +struct LEDMADeviceState { DMADeviceState parent_obj; - SysBusPCNetState *lance; -} LEDMADeviceState; + SysBusPCNetState lance; +}; #define TYPE_SPARC32_DMA "sparc32-dma" -#define SPARC32_DMA(obj) OBJECT_CHECK(SPARC32DMAState, (obj), \ - TYPE_SPARC32_DMA) +OBJECT_DECLARE_SIMPLE_TYPE(SPARC32DMAState, SPARC32_DMA) -typedef struct SPARC32DMAState { +struct SPARC32DMAState { SysBusDevice parent_obj; MemoryRegion dmamem; MemoryRegion ledma_alias; - ESPDMADeviceState *espdma; - LEDMADeviceState *ledma; -} SPARC32DMAState; + ESPDMADeviceState espdma; + LEDMADeviceState ledma; +}; /* sparc32_dma.c */ void ledma_memory_read(void *opaque, hwaddr addr, diff --git a/include/hw/sparc/sun4m_iommu.h b/include/hw/sparc/sun4m_iommu.h index 482266c6a7af31bf4503a81e21eb138e6ffc6465..4e2ab34cdef33b40dcae7c11fa9f3cb5695345e9 100644 --- a/include/hw/sparc/sun4m_iommu.h +++ b/include/hw/sparc/sun4m_iommu.h @@ -26,10 +26,11 @@ #define SUN4M_IOMMU_H #include "hw/sysbus.h" +#include "qom/object.h" #define IOMMU_NREGS (4 * 4096 / 4) -typedef struct IOMMUState { +struct IOMMUState { SysBusDevice parent_obj; AddressSpace iommu_as; @@ -40,10 +41,12 @@ typedef struct IOMMUState { hwaddr iostart; qemu_irq irq; uint32_t version; -} IOMMUState; +}; +typedef struct IOMMUState IOMMUState; #define TYPE_SUN4M_IOMMU "sun4m-iommu" -#define SUN4M_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4M_IOMMU) +DECLARE_INSTANCE_CHECKER(IOMMUState, SUN4M_IOMMU, + TYPE_SUN4M_IOMMU) #define TYPE_SUN4M_IOMMU_MEMORY_REGION "sun4m-iommu-memory-region" diff --git a/include/hw/sparc/sun4u_iommu.h b/include/hw/sparc/sun4u_iommu.h index 5472d489cf3bd8bf550ee50ee5f147c865dbad4d..f94566a72c9cd1493e9a4ebe9a783a73c31338fa 100644 --- a/include/hw/sparc/sun4u_iommu.h +++ b/include/hw/sparc/sun4u_iommu.h @@ -28,10 +28,11 @@ #define SUN4U_IOMMU_H #include "hw/sysbus.h" +#include "qom/object.h" #define IOMMU_NREGS 3 -typedef struct IOMMUState { +struct IOMMUState { SysBusDevice parent_obj; AddressSpace iommu_as; @@ -39,10 +40,12 @@ typedef struct IOMMUState { MemoryRegion iomem; uint64_t regs[IOMMU_NREGS]; -} IOMMUState; +}; +typedef struct IOMMUState IOMMUState; #define TYPE_SUN4U_IOMMU "sun4u-iommu" -#define SUN4U_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4U_IOMMU) +DECLARE_INSTANCE_CHECKER(IOMMUState, SUN4U_IOMMU, + TYPE_SUN4U_IOMMU) #define TYPE_SUN4U_IOMMU_MEMORY_REGION "sun4u-iommu-memory-region" diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h index 6fbbb238f158c46b38dbd4370370173d75cd924b..3dd354b52ecc612a41c7f7afb1a9b9c7d5946624 100644 --- a/include/hw/ssi/aspeed_smc.h +++ b/include/hw/ssi/aspeed_smc.h @@ -27,6 +27,7 @@ #include "hw/ssi/ssi.h" #include "hw/sysbus.h" +#include "qom/object.h" typedef struct AspeedSegments { hwaddr addr; @@ -67,20 +68,16 @@ typedef struct AspeedSMCFlash { } AspeedSMCFlash; #define TYPE_ASPEED_SMC "aspeed.smc" -#define ASPEED_SMC(obj) OBJECT_CHECK(AspeedSMCState, (obj), TYPE_ASPEED_SMC) -#define ASPEED_SMC_CLASS(klass) \ - OBJECT_CLASS_CHECK(AspeedSMCClass, (klass), TYPE_ASPEED_SMC) -#define ASPEED_SMC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(AspeedSMCClass, (obj), TYPE_ASPEED_SMC) +OBJECT_DECLARE_TYPE(AspeedSMCState, AspeedSMCClass, ASPEED_SMC) -typedef struct AspeedSMCClass { +struct AspeedSMCClass { SysBusDevice parent_obj; const AspeedSMCController *ctrl; -} AspeedSMCClass; +}; #define ASPEED_SMC_R_MAX (0x100 / 4) -typedef struct AspeedSMCState { +struct AspeedSMCState { SysBusDevice parent_obj; const AspeedSMCController *ctrl; @@ -117,6 +114,6 @@ typedef struct AspeedSMCState { uint8_t snoop_index; uint8_t snoop_dummies; -} AspeedSMCState; +}; #endif /* ASPEED_SMC_H */ diff --git a/include/hw/ssi/imx_spi.h b/include/hw/ssi/imx_spi.h index 71039535816791505ef76c17115bf644b3f0d44c..b82b17f36435a378b660d7020ae375bb3603a803 100644 --- a/include/hw/ssi/imx_spi.h +++ b/include/hw/ssi/imx_spi.h @@ -14,6 +14,7 @@ #include "hw/ssi/ssi.h" #include "qemu/bitops.h" #include "qemu/fifo32.h" +#include "qom/object.h" #define ECSPI_FIFO_SIZE 64 @@ -77,9 +78,9 @@ #define EXTRACT(value, name) extract32(value, name##_SHIFT, name##_LENGTH) #define TYPE_IMX_SPI "imx.spi" -#define IMX_SPI(obj) OBJECT_CHECK(IMXSPIState, (obj), TYPE_IMX_SPI) +OBJECT_DECLARE_SIMPLE_TYPE(IMXSPIState, IMX_SPI) -typedef struct IMXSPIState { +struct IMXSPIState { /* */ SysBusDevice parent_obj; @@ -98,6 +99,6 @@ typedef struct IMXSPIState { Fifo32 tx_fifo; int16_t burst_length; -} IMXSPIState; +}; #endif /* IMX_SPI_H */ diff --git a/include/hw/ssi/mss-spi.h b/include/hw/ssi/mss-spi.h index f0cf3243e0f512fb2921e7976eb185ab1e715a0b..ce6279c431014b0f9aabed07a895725864b89e0d 100644 --- a/include/hw/ssi/mss-spi.h +++ b/include/hw/ssi/mss-spi.h @@ -28,13 +28,14 @@ #include "hw/sysbus.h" #include "hw/ssi/ssi.h" #include "qemu/fifo32.h" +#include "qom/object.h" #define TYPE_MSS_SPI "mss-spi" -#define MSS_SPI(obj) OBJECT_CHECK(MSSSpiState, (obj), TYPE_MSS_SPI) +OBJECT_DECLARE_SIMPLE_TYPE(MSSSpiState, MSS_SPI) #define R_SPI_MAX 16 -typedef struct MSSSpiState { +struct MSSSpiState { SysBusDevice parent_obj; MemoryRegion mmio; @@ -53,6 +54,6 @@ typedef struct MSSSpiState { bool enabled; uint32_t regs[R_SPI_MAX]; -} MSSSpiState; +}; #endif /* HW_MSS_SPI_H */ diff --git a/include/hw/ssi/npcm7xx_fiu.h b/include/hw/ssi/npcm7xx_fiu.h new file mode 100644 index 0000000000000000000000000000000000000000..a3a17042896271d00749ded9b0dfc93b2c50d9fd --- /dev/null +++ b/include/hw/ssi/npcm7xx_fiu.h @@ -0,0 +1,73 @@ +/* + * Nuvoton NPCM7xx Flash Interface Unit (FIU) + * + * Copyright 2020 Google LLC + * + * 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. + */ +#ifndef NPCM7XX_FIU_H +#define NPCM7XX_FIU_H + +#include "hw/ssi/ssi.h" +#include "hw/sysbus.h" + +/* + * Number of registers in our device state structure. Don't change this without + * incrementing the version_id in the vmstate. + */ +#define NPCM7XX_FIU_NR_REGS (0x7c / sizeof(uint32_t)) + +typedef struct NPCM7xxFIUState NPCM7xxFIUState; + +/** + * struct NPCM7xxFIUFlash - Per-chipselect flash controller state. + * @direct_access: Memory region for direct flash access. + * @fiu: Pointer to flash controller shared state. + */ +typedef struct NPCM7xxFIUFlash { + MemoryRegion direct_access; + NPCM7xxFIUState *fiu; +} NPCM7xxFIUFlash; + +/** + * NPCM7xxFIUState - Device state for one Flash Interface Unit. + * @parent: System bus device. + * @mmio: Memory region for register access. + * @cs_count: Number of flash chips that may be connected to this module. + * @active_cs: Currently active chip select, or -1 if no chip is selected. + * @cs_lines: GPIO lines that may be wired to flash chips. + * @flash: Array of @cs_count per-flash-chip state objects. + * @spi: The SPI bus mastered by this controller. + * @regs: Register contents. + * + * Each FIU has a shared bank of registers, and controls up to four chip + * selects. Each chip select has a dedicated memory region which may be used to + * read and write the flash connected to that chip select as if it were memory. + */ +struct NPCM7xxFIUState { + SysBusDevice parent; + + MemoryRegion mmio; + + int32_t cs_count; + int32_t active_cs; + qemu_irq *cs_lines; + NPCM7xxFIUFlash *flash; + + SSIBus *spi; + + uint32_t regs[NPCM7XX_FIU_NR_REGS]; +}; + +#define TYPE_NPCM7XX_FIU "npcm7xx-fiu" +#define NPCM7XX_FIU(obj) OBJECT_CHECK(NPCM7xxFIUState, (obj), TYPE_NPCM7XX_FIU) + +#endif /* NPCM7XX_FIU_H */ diff --git a/include/hw/ssi/pl022.h b/include/hw/ssi/pl022.h index a080519366d3006f95afc6ceb01ea7522dfef579..545b52689c157f8086d2ca0bb4516b7757cc2d0d 100644 --- a/include/hw/ssi/pl022.h +++ b/include/hw/ssi/pl022.h @@ -22,11 +22,12 @@ #define HW_SSI_PL022_H #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_PL022 "pl022" -#define PL022(obj) OBJECT_CHECK(PL022State, (obj), TYPE_PL022) +OBJECT_DECLARE_SIMPLE_TYPE(PL022State, PL022) -typedef struct PL022State { +struct PL022State { SysBusDevice parent_obj; MemoryRegion iomem; @@ -46,6 +47,6 @@ typedef struct PL022State { uint16_t rx_fifo[8]; qemu_irq irq; SSIBus *ssi; -} PL022State; +}; #endif diff --git a/include/hw/ssi/ssi.h b/include/hw/ssi/ssi.h index 1107cb89ee14d2989acc77e444885bfb9d060403..fe3028c39dc8485a4d4c689fd827830ec915c499 100644 --- a/include/hw/ssi/ssi.h +++ b/include/hw/ssi/ssi.h @@ -12,18 +12,13 @@ #define QEMU_SSI_H #include "hw/qdev-core.h" +#include "qom/object.h" -typedef struct SSISlave SSISlave; -typedef struct SSISlaveClass SSISlaveClass; typedef enum SSICSMode SSICSMode; #define TYPE_SSI_SLAVE "ssi-slave" -#define SSI_SLAVE(obj) \ - OBJECT_CHECK(SSISlave, (obj), TYPE_SSI_SLAVE) -#define SSI_SLAVE_CLASS(klass) \ - OBJECT_CLASS_CHECK(SSISlaveClass, (klass), TYPE_SSI_SLAVE) -#define SSI_SLAVE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SSISlaveClass, (obj), TYPE_SSI_SLAVE) +OBJECT_DECLARE_TYPE(SSISlave, SSISlaveClass, + SSI_SLAVE) #define SSI_GPIO_CS "ssi-gpio-cs" @@ -66,8 +61,6 @@ struct SSISlave { bool cs; }; -#define FROM_SSI_SLAVE(type, dev) DO_UPCAST(type, ssidev, dev) - extern const VMStateDescription vmstate_ssi_slave; #define VMSTATE_SSI_SLAVE(_field, _state) { \ @@ -79,18 +72,36 @@ extern const VMStateDescription vmstate_ssi_slave; } DeviceState *ssi_create_slave(SSIBus *bus, const char *name); -DeviceState *ssi_create_slave_no_init(SSIBus *bus, const char *name); +/** + * ssi_realize_and_unref: realize and unref an SSI slave device + * @dev: SSI slave device to realize + * @bus: SSI bus to put it on + * @errp: error pointer + * + * Call 'realize' on @dev, put it on the specified @bus, and drop the + * reference to it. Errors are reported via @errp and by returning + * false. + * + * This function is useful if you have created @dev via qdev_new() + * (which takes a reference to the device it returns to you), so that + * you can set properties on it before realizing it. If you don't need + * to set properties then ssi_create_slave() is probably better (as it + * does the create, init and realize in one step). + * + * If you are embedding the SSI slave into another QOM device and + * initialized it via some variant on object_initialize_child() then + * do not use this function, because that family of functions arrange + * for the only reference to the child device to be held by the parent + * via the child<> property, and so the reference-count-drop done here + * would be incorrect. (Instead you would want ssi_realize(), which + * doesn't currently exist but would be trivial to create if we had + * any code that wanted it.) + */ +bool ssi_realize_and_unref(DeviceState *dev, SSIBus *bus, Error **errp); /* Master interface. */ SSIBus *ssi_create_bus(DeviceState *parent, const char *name); uint32_t ssi_transfer(SSIBus *bus, uint32_t val); -/* Automatically connect all children nodes a spi controller as slaves */ -void ssi_auto_connect_slaves(DeviceState *parent, qemu_irq *cs_lines, - SSIBus *bus); - -/* max111x.c */ -void max111x_set_input(DeviceState *dev, int line, uint8_t value); - #endif diff --git a/include/hw/ssi/stm32f2xx_spi.h b/include/hw/ssi/stm32f2xx_spi.h index e24b007abfadcdbe76d8deb2076ea03b67ff53fa..3683b4ad3293536f0a03ae35e62e678835a09fd0 100644 --- a/include/hw/ssi/stm32f2xx_spi.h +++ b/include/hw/ssi/stm32f2xx_spi.h @@ -27,6 +27,7 @@ #include "hw/sysbus.h" #include "hw/ssi/ssi.h" +#include "qom/object.h" #define STM_SPI_CR1 0x00 #define STM_SPI_CR2 0x04 @@ -44,10 +45,9 @@ #define STM_SPI_SR_RXNE 1 #define TYPE_STM32F2XX_SPI "stm32f2xx-spi" -#define STM32F2XX_SPI(obj) \ - OBJECT_CHECK(STM32F2XXSPIState, (obj), TYPE_STM32F2XX_SPI) +OBJECT_DECLARE_SIMPLE_TYPE(STM32F2XXSPIState, STM32F2XX_SPI) -typedef struct { +struct STM32F2XXSPIState { /* */ SysBusDevice parent_obj; @@ -66,6 +66,6 @@ typedef struct { qemu_irq irq; SSIBus *ssi; -} STM32F2XXSPIState; +}; #endif /* HW_STM32F2XX_SPI_H */ diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h index 6a39b55a7bdcd14515ab44d0d80dc2c837fa562d..b96de21b3474fba28ff86fd86f13f50f245e0712 100644 --- a/include/hw/ssi/xilinx_spips.h +++ b/include/hw/ssi/xilinx_spips.h @@ -29,6 +29,7 @@ #include "qemu/fifo32.h" #include "hw/stream.h" #include "hw/sysbus.h" +#include "qom/object.h" typedef struct XilinxSPIPS XilinxSPIPS; @@ -85,16 +86,17 @@ struct XilinxSPIPS { bool man_start_com; }; -typedef struct { +struct XilinxQSPIPS { XilinxSPIPS parent_obj; uint8_t lqspi_buf[LQSPI_CACHE_SIZE]; hwaddr lqspi_cached_addr; Error *migration_blocker; bool mmio_execution_enabled; -} XilinxQSPIPS; +}; +typedef struct XilinxQSPIPS XilinxQSPIPS; -typedef struct { +struct XlnxZynqMPQSPIPS { XilinxQSPIPS parent_obj; StreamSlave *dma; @@ -117,32 +119,25 @@ typedef struct { bool man_start_com_g; uint32_t dma_burst_size; uint8_t dma_buf[QSPI_DMA_MAX_BURST_SIZE]; -} XlnxZynqMPQSPIPS; +}; -typedef struct XilinxSPIPSClass { +struct XilinxSPIPSClass { SysBusDeviceClass parent_class; const MemoryRegionOps *reg_ops; uint32_t rx_fifo_size; uint32_t tx_fifo_size; -} XilinxSPIPSClass; +}; #define TYPE_XILINX_SPIPS "xlnx.ps7-spi" #define TYPE_XILINX_QSPIPS "xlnx.ps7-qspi" #define TYPE_XLNX_ZYNQMP_QSPIPS "xlnx.usmp-gqspi" -#define XILINX_SPIPS(obj) \ - OBJECT_CHECK(XilinxSPIPS, (obj), TYPE_XILINX_SPIPS) -#define XILINX_SPIPS_CLASS(klass) \ - OBJECT_CLASS_CHECK(XilinxSPIPSClass, (klass), TYPE_XILINX_SPIPS) -#define XILINX_SPIPS_GET_CLASS(obj) \ - OBJECT_GET_CLASS(XilinxSPIPSClass, (obj), TYPE_XILINX_SPIPS) +OBJECT_DECLARE_TYPE(XilinxSPIPS, XilinxSPIPSClass, XILINX_SPIPS) -#define XILINX_QSPIPS(obj) \ - OBJECT_CHECK(XilinxQSPIPS, (obj), TYPE_XILINX_QSPIPS) +OBJECT_DECLARE_SIMPLE_TYPE(XilinxQSPIPS, XILINX_QSPIPS) -#define XLNX_ZYNQMP_QSPIPS(obj) \ - OBJECT_CHECK(XlnxZynqMPQSPIPS, (obj), TYPE_XLNX_ZYNQMP_QSPIPS) +OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPQSPIPS, XLNX_ZYNQMP_QSPIPS) #endif /* XILINX_SPIPS_H */ diff --git a/include/hw/stream.h b/include/hw/stream.h index ed09e83683dc8b62bff807065a47006cc5616dfa..e39d5a5b558458a5791e8f7f531fcc255d00ab60 100644 --- a/include/hw/stream.h +++ b/include/hw/stream.h @@ -6,10 +6,9 @@ /* stream slave. Used until qdev provides a generic way. */ #define TYPE_STREAM_SLAVE "stream-slave" -#define STREAM_SLAVE_CLASS(klass) \ - OBJECT_CLASS_CHECK(StreamSlaveClass, (klass), TYPE_STREAM_SLAVE) -#define STREAM_SLAVE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(StreamSlaveClass, (obj), TYPE_STREAM_SLAVE) +typedef struct StreamSlaveClass StreamSlaveClass; +DECLARE_CLASS_CHECKERS(StreamSlaveClass, STREAM_SLAVE, + TYPE_STREAM_SLAVE) #define STREAM_SLAVE(obj) \ INTERFACE_CHECK(StreamSlave, (obj), TYPE_STREAM_SLAVE) @@ -17,7 +16,7 @@ typedef struct StreamSlave StreamSlave; typedef void (*StreamCanPushNotifyFn)(void *opaque); -typedef struct StreamSlaveClass { +struct StreamSlaveClass { InterfaceClass parent; /** * can push - determine if a stream slave is capable of accepting at least @@ -42,7 +41,7 @@ typedef struct StreamSlaveClass { * @eop: End of packet flag */ size_t (*push)(StreamSlave *obj, unsigned char *buf, size_t len, bool eop); -} StreamSlaveClass; +}; size_t stream_push(StreamSlave *sink, uint8_t *buf, size_t len, bool eop); diff --git a/include/hw/sysbus.h b/include/hw/sysbus.h index c4a1c0adfa5a135bc51796eebf3dc31402959510..3564b7b6a22484276100d590a28578e0cb3a38f7 100644 --- a/include/hw/sysbus.h +++ b/include/hw/sysbus.h @@ -5,22 +5,19 @@ #include "hw/qdev-core.h" #include "exec/memory.h" +#include "qom/object.h" #define QDEV_MAX_MMIO 32 #define QDEV_MAX_PIO 32 #define TYPE_SYSTEM_BUS "System" -#define SYSTEM_BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_SYSTEM_BUS) +DECLARE_INSTANCE_CHECKER(BusState, SYSTEM_BUS, + TYPE_SYSTEM_BUS) -typedef struct SysBusDevice SysBusDevice; #define TYPE_SYS_BUS_DEVICE "sys-bus-device" -#define SYS_BUS_DEVICE(obj) \ - OBJECT_CHECK(SysBusDevice, (obj), TYPE_SYS_BUS_DEVICE) -#define SYS_BUS_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(SysBusDeviceClass, (klass), TYPE_SYS_BUS_DEVICE) -#define SYS_BUS_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SysBusDeviceClass, (obj), TYPE_SYS_BUS_DEVICE) +OBJECT_DECLARE_TYPE(SysBusDevice, SysBusDeviceClass, + SYS_BUS_DEVICE) /** * SysBusDeviceClass: @@ -31,7 +28,7 @@ typedef struct SysBusDevice SysBusDevice; #define SYSBUS_DEVICE_GPIO_IRQ "sysbus-irq" -typedef struct SysBusDeviceClass { +struct SysBusDeviceClass { /*< private >*/ DeviceClass parent_class; @@ -52,7 +49,7 @@ typedef struct SysBusDeviceClass { */ char *(*explicit_ofw_unit_address)(const SysBusDevice *dev); void (*connect_irq_notifier)(SysBusDevice *dev, qemu_irq irq); -} SysBusDeviceClass; +}; struct SysBusDevice { /*< private >*/ @@ -90,22 +87,8 @@ void sysbus_add_io(SysBusDevice *dev, hwaddr addr, MemoryRegion *mem); MemoryRegion *sysbus_address_space(SysBusDevice *dev); -/** - * sysbus_init_child_obj: - * @parent: The parent object - * @childname: Used as name of the "child<>" property in the parent - * @child: A pointer to the memory to be used for the object. - * @childsize: The maximum size available at @child for the object. - * @childtype: The name of the type of the object to instantiate. - * - * This function will initialize an object and attach it to the main system - * bus. The memory for the object should have already been allocated. The - * object will then be added as child to the given parent. The returned object - * has a reference count of 1 (for the "child<...>" property from the parent), - * so the object will be finalized automatically when the parent gets removed. - */ -void sysbus_init_child_obj(Object *parent, const char *childname, void *child, - size_t childsize, const char *childtype); +bool sysbus_realize(SysBusDevice *dev, Error **errp); +bool sysbus_realize_and_unref(SysBusDevice *dev, Error **errp); /* Call func for every dynamically created sysbus device in the system */ void foreach_dynamic_sysbus_device(FindSysbusDeviceFunc *func, void *opaque); @@ -121,5 +104,4 @@ static inline DeviceState *sysbus_create_simple(const char *name, return sysbus_create_varargs(name, addr, irq, NULL); } - #endif /* HW_SYSBUS_H */ diff --git a/include/hw/timer/a9gtimer.h b/include/hw/timer/a9gtimer.h index 81c4388784e00a12c4da2040eaef32b80b54cf18..6ae9122e4b69b5761314e5576da53b2d47fb52b1 100644 --- a/include/hw/timer/a9gtimer.h +++ b/include/hw/timer/a9gtimer.h @@ -24,11 +24,12 @@ #define A9GTIMER_H #include "hw/sysbus.h" +#include "qom/object.h" #define A9_GTIMER_MAX_CPUS 4 #define TYPE_A9_GTIMER "arm.cortex-a9-global-timer" -#define A9_GTIMER(obj) OBJECT_CHECK(A9GTimerState, (obj), TYPE_A9_GTIMER) +OBJECT_DECLARE_SIMPLE_TYPE(A9GTimerState, A9_GTIMER) #define R_COUNTER_LO 0x00 #define R_COUNTER_HI 0x04 @@ -55,7 +56,6 @@ #define R_AUTO_INCREMENT 0x18 typedef struct A9GTimerPerCPU A9GTimerPerCPU; -typedef struct A9GTimerState A9GTimerState; struct A9GTimerPerCPU { A9GTimerState *parent; diff --git a/include/hw/timer/allwinner-a10-pit.h b/include/hw/timer/allwinner-a10-pit.h index 871c95b5128018b60c37603b8ca2a08a46a5cbcc..8435758ad68ed1cd9cc38f148490aeafa3e980de 100644 --- a/include/hw/timer/allwinner-a10-pit.h +++ b/include/hw/timer/allwinner-a10-pit.h @@ -3,9 +3,10 @@ #include "hw/ptimer.h" #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_AW_A10_PIT "allwinner-A10-timer" -#define AW_A10_PIT(obj) OBJECT_CHECK(AwA10PITState, (obj), TYPE_AW_A10_PIT) +OBJECT_DECLARE_SIMPLE_TYPE(AwA10PITState, AW_A10_PIT) #define AW_A10_PIT_TIMER_NR 6 #define AW_A10_PIT_TIMER_IRQ 0x1 @@ -36,7 +37,6 @@ #define AW_A10_PIT_DEFAULT_CLOCK 0x4 -typedef struct AwA10PITState AwA10PITState; typedef struct AwA10TimerContext { AwA10PITState *container; diff --git a/include/hw/timer/arm_mptimer.h b/include/hw/timer/arm_mptimer.h index c46d8d230932c234e17f19d263c1fa5e5484a8db..65a96e2a0dc8a4001e0cd69959b4207f4a81bf89 100644 --- a/include/hw/timer/arm_mptimer.h +++ b/include/hw/timer/arm_mptimer.h @@ -22,6 +22,7 @@ #define HW_TIMER_ARM_MPTIMER_H #include "hw/sysbus.h" +#include "qom/object.h" #define ARM_MPTIMER_MAX_CPUS 4 @@ -35,10 +36,9 @@ typedef struct { } TimerBlock; #define TYPE_ARM_MPTIMER "arm_mptimer" -#define ARM_MPTIMER(obj) \ - OBJECT_CHECK(ARMMPTimerState, (obj), TYPE_ARM_MPTIMER) +OBJECT_DECLARE_SIMPLE_TYPE(ARMMPTimerState, ARM_MPTIMER) -typedef struct { +struct ARMMPTimerState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -46,6 +46,6 @@ typedef struct { uint32_t num_cpu; TimerBlock timerblock[ARM_MPTIMER_MAX_CPUS]; MemoryRegion iomem; -} ARMMPTimerState; +}; #endif diff --git a/include/hw/timer/armv7m_systick.h b/include/hw/timer/armv7m_systick.h index 25e5ceacc8541b74a606c806527bbf36b289d5ab..84496faaf969fd3232738a02797fce6be05dd708 100644 --- a/include/hw/timer/armv7m_systick.h +++ b/include/hw/timer/armv7m_systick.h @@ -13,12 +13,14 @@ #define HW_TIMER_ARMV7M_SYSTICK_H #include "hw/sysbus.h" +#include "qom/object.h" +#include "hw/ptimer.h" #define TYPE_SYSTICK "armv7m_systick" -#define SYSTICK(obj) OBJECT_CHECK(SysTickState, (obj), TYPE_SYSTICK) +OBJECT_DECLARE_SIMPLE_TYPE(SysTickState, SYSTICK) -typedef struct SysTickState { +struct SysTickState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -26,10 +28,10 @@ typedef struct SysTickState { uint32_t control; uint32_t reload; int64_t tick; - QEMUTimer *timer; + ptimer_state *ptimer; MemoryRegion iomem; qemu_irq irq; -} SysTickState; +}; /* * Multiplication factor to convert from system clock ticks to qemu timer diff --git a/include/hw/timer/aspeed_timer.h b/include/hw/timer/aspeed_timer.h index 948329893c0bb0508b20e7d75e705a340c109a13..d36034a10c209a4bde9b09c00b15921dd987ad3d 100644 --- a/include/hw/timer/aspeed_timer.h +++ b/include/hw/timer/aspeed_timer.h @@ -24,10 +24,10 @@ #include "qemu/timer.h" #include "hw/misc/aspeed_scu.h" +#include "qom/object.h" -#define ASPEED_TIMER(obj) \ - OBJECT_CHECK(AspeedTimerCtrlState, (obj), TYPE_ASPEED_TIMER); #define TYPE_ASPEED_TIMER "aspeed.timer" +OBJECT_DECLARE_TYPE(AspeedTimerCtrlState, AspeedTimerClass, ASPEED_TIMER) #define TYPE_ASPEED_2400_TIMER TYPE_ASPEED_TIMER "-ast2400" #define TYPE_ASPEED_2500_TIMER TYPE_ASPEED_TIMER "-ast2500" #define TYPE_ASPEED_2600_TIMER TYPE_ASPEED_TIMER "-ast2600" @@ -50,7 +50,7 @@ typedef struct AspeedTimer { uint64_t start; } AspeedTimer; -typedef struct AspeedTimerCtrlState { +struct AspeedTimerCtrlState { /*< private >*/ SysBusDevice parent; @@ -64,18 +64,14 @@ typedef struct AspeedTimerCtrlState { AspeedTimer timers[ASPEED_TIMER_NR_TIMERS]; AspeedSCUState *scu; -} AspeedTimerCtrlState; +}; -#define ASPEED_TIMER_CLASS(klass) \ - OBJECT_CLASS_CHECK(AspeedTimerClass, (klass), TYPE_ASPEED_TIMER) -#define ASPEED_TIMER_GET_CLASS(obj) \ - OBJECT_GET_CLASS(AspeedTimerClass, (obj), TYPE_ASPEED_TIMER) -typedef struct AspeedTimerClass { +struct AspeedTimerClass { SysBusDeviceClass parent_class; uint64_t (*read)(AspeedTimerCtrlState *s, hwaddr offset); void (*write)(AspeedTimerCtrlState *s, hwaddr offset, uint64_t value); -} AspeedTimerClass; +}; #endif /* ASPEED_TIMER_H */ diff --git a/include/hw/timer/avr_timer16.h b/include/hw/timer/avr_timer16.h new file mode 100644 index 0000000000000000000000000000000000000000..053625433789719b6695fa91add96abee1c51108 --- /dev/null +++ b/include/hw/timer/avr_timer16.h @@ -0,0 +1,94 @@ +/* + * AVR 16-bit timer + * + * Copyright (c) 2018 University of Kent + * Author: Ed Robbins + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * + */ + +/* + * Driver for 16 bit timers on 8 bit AVR devices. + * Note: + * On ATmega640/V-1280/V-1281/V-2560/V-2561/V timers 1, 3, 4 and 5 are 16 bit + */ + +#ifndef HW_TIMER_AVR_TIMER16_H +#define HW_TIMER_AVR_TIMER16_H + +#include "hw/sysbus.h" +#include "qemu/timer.h" +#include "hw/hw.h" +#include "qom/object.h" + +enum NextInterrupt { + OVERFLOW, + COMPA, + COMPB, + COMPC, + CAPT +}; + +#define TYPE_AVR_TIMER16 "avr-timer16" +OBJECT_DECLARE_SIMPLE_TYPE(AVRTimer16State, AVR_TIMER16) + +struct AVRTimer16State { + /* */ + SysBusDevice parent_obj; + + /* */ + MemoryRegion iomem; + MemoryRegion imsk_iomem; + MemoryRegion ifr_iomem; + QEMUTimer *timer; + qemu_irq capt_irq; + qemu_irq compa_irq; + qemu_irq compb_irq; + qemu_irq compc_irq; + qemu_irq ovf_irq; + + bool enabled; + + /* registers */ + uint8_t cra; + uint8_t crb; + uint8_t crc; + uint8_t cntl; + uint8_t cnth; + uint8_t icrl; + uint8_t icrh; + uint8_t ocral; + uint8_t ocrah; + uint8_t ocrbl; + uint8_t ocrbh; + uint8_t ocrcl; + uint8_t ocrch; + /* + * Reads and writes to CNT and ICR utilise a bizarre temporary + * register, which we emulate + */ + uint8_t rtmp; + uint8_t imsk; + uint8_t ifr; + + uint8_t id; + uint64_t cpu_freq_hz; + uint64_t freq_hz; + uint64_t period_ns; + uint64_t reset_time_ns; + enum NextInterrupt next_interrupt; +}; + +#endif /* HW_TIMER_AVR_TIMER16_H */ diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h index c0bc5c81270d087d00a3a6aa3af914afbc81caa7..bd3097d746b2d54f94ea7e792ec38d59eb80e0e1 100644 --- a/include/hw/timer/bcm2835_systmr.h +++ b/include/hw/timer/bcm2835_systmr.h @@ -11,23 +11,32 @@ #include "hw/sysbus.h" #include "hw/irq.h" +#include "qemu/timer.h" +#include "qom/object.h" #define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer" -#define BCM2835_SYSTIMER(obj) \ - OBJECT_CHECK(BCM2835SystemTimerState, (obj), TYPE_BCM2835_SYSTIMER) +OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER) + +#define BCM2835_SYSTIMER_COUNT 4 typedef struct { + unsigned id; + QEMUTimer timer; + qemu_irq irq; + BCM2835SystemTimerState *state; +} BCM2835SystemTimerCompare; + +struct BCM2835SystemTimerState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ MemoryRegion iomem; - qemu_irq irq; - struct { - uint32_t status; - uint32_t compare[4]; + uint32_t ctrl_status; + uint32_t compare[BCM2835_SYSTIMER_COUNT]; } reg; -} BCM2835SystemTimerState; + BCM2835SystemTimerCompare tmr[BCM2835_SYSTIMER_COUNT]; +}; #endif diff --git a/include/hw/timer/cmsdk-apb-dualtimer.h b/include/hw/timer/cmsdk-apb-dualtimer.h index 9843a9dbb1dea7ea37482083855ee6ff2567c778..08d9e6fa3d504f67f0ae47f80d38d748e2563466 100644 --- a/include/hw/timer/cmsdk-apb-dualtimer.h +++ b/include/hw/timer/cmsdk-apb-dualtimer.h @@ -28,12 +28,11 @@ #include "hw/sysbus.h" #include "hw/ptimer.h" +#include "qom/object.h" #define TYPE_CMSDK_APB_DUALTIMER "cmsdk-apb-dualtimer" -#define CMSDK_APB_DUALTIMER(obj) OBJECT_CHECK(CMSDKAPBDualTimer, (obj), \ - TYPE_CMSDK_APB_DUALTIMER) +OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBDualTimer, CMSDK_APB_DUALTIMER) -typedef struct CMSDKAPBDualTimer CMSDKAPBDualTimer; /* One of the two identical timer modules in the dual-timer module */ typedef struct CMSDKAPBDualTimerModule { diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h index e93caccc3c7339baffc3fac11338b6844bba8d14..0d80b2a48cd1ff0e909d75c0cd37ba2d3fcb72bc 100644 --- a/include/hw/timer/cmsdk-apb-timer.h +++ b/include/hw/timer/cmsdk-apb-timer.h @@ -15,12 +15,12 @@ #include "hw/qdev-properties.h" #include "hw/sysbus.h" #include "hw/ptimer.h" +#include "qom/object.h" #define TYPE_CMSDK_APB_TIMER "cmsdk-apb-timer" -#define CMSDK_APB_TIMER(obj) OBJECT_CHECK(CMSDKAPBTIMER, (obj), \ - TYPE_CMSDK_APB_TIMER) +OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBTIMER, CMSDK_APB_TIMER) -typedef struct { +struct CMSDKAPBTIMER { /*< private >*/ SysBusDevice parent_obj; @@ -34,7 +34,7 @@ typedef struct { uint32_t value; uint32_t reload; uint32_t intstatus; -} CMSDKAPBTIMER; +}; /** * cmsdk_apb_timer_create - convenience function to create TYPE_CMSDK_APB_TIMER @@ -48,10 +48,10 @@ static inline DeviceState *cmsdk_apb_timer_create(hwaddr addr, DeviceState *dev; SysBusDevice *s; - dev = qdev_create(NULL, TYPE_CMSDK_APB_TIMER); + dev = qdev_new(TYPE_CMSDK_APB_TIMER); s = SYS_BUS_DEVICE(dev); qdev_prop_set_uint32(dev, "pclk-frq", pclk_frq); - qdev_init_nofail(dev); + sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, addr); sysbus_connect_irq(s, 0, timerint); return dev; diff --git a/include/hw/timer/digic-timer.h b/include/hw/timer/digic-timer.h index d9e67fe291746f72570614d281761dcc2b918a40..da82fb466374a012cfaabc3c3fa854484715e9c9 100644 --- a/include/hw/timer/digic-timer.h +++ b/include/hw/timer/digic-timer.h @@ -20,9 +20,10 @@ #include "hw/sysbus.h" #include "hw/ptimer.h" +#include "qom/object.h" #define TYPE_DIGIC_TIMER "digic-timer" -#define DIGIC_TIMER(obj) OBJECT_CHECK(DigicTimerState, (obj), TYPE_DIGIC_TIMER) +OBJECT_DECLARE_SIMPLE_TYPE(DigicTimerState, DIGIC_TIMER) #define DIGIC_TIMER_CONTROL 0x00 #define DIGIC_TIMER_CONTROL_RST 0x80000000 @@ -30,7 +31,7 @@ #define DIGIC_TIMER_RELVALUE 0x08 #define DIGIC_TIMER_VALUE 0x0c -typedef struct DigicTimerState { +struct DigicTimerState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ @@ -40,6 +41,6 @@ typedef struct DigicTimerState { uint32_t control; uint32_t relvalue; -} DigicTimerState; +}; #endif /* HW_TIMER_DIGIC_TIMER_H */ diff --git a/include/hw/timer/i8254.h b/include/hw/timer/i8254.h index 45cb42571f61a415027dec0a5c78cac381daf983..3e569f42b635c9452646142d2964785efc772ec4 100644 --- a/include/hw/timer/i8254.h +++ b/include/hw/timer/i8254.h @@ -27,6 +27,8 @@ #include "hw/qdev-properties.h" #include "hw/isa/isa.h" +#include "qapi/error.h" +#include "qom/object.h" #define PIT_FREQ 1193182 @@ -38,12 +40,7 @@ typedef struct PITChannelInfo { } PITChannelInfo; #define TYPE_PIT_COMMON "pit-common" -#define PIT_COMMON(obj) \ - OBJECT_CHECK(PITCommonState, (obj), TYPE_PIT_COMMON) -#define PIT_COMMON_CLASS(klass) \ - OBJECT_CLASS_CHECK(PITCommonClass, (klass), TYPE_PIT_COMMON) -#define PIT_COMMON_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PITCommonClass, (obj), TYPE_PIT_COMMON) +OBJECT_DECLARE_TYPE(PITCommonState, PITCommonClass, PIT_COMMON) #define TYPE_I8254 "isa-pit" #define TYPE_KVM_I8254 "kvm-pit" @@ -54,10 +51,10 @@ static inline ISADevice *i8254_pit_init(ISABus *bus, int base, int isa_irq, DeviceState *dev; ISADevice *d; - d = isa_create(bus, TYPE_I8254); + d = isa_new(TYPE_I8254); dev = DEVICE(d); qdev_prop_set_uint32(dev, "iobase", base); - qdev_init_nofail(dev); + isa_realize_and_unref(d, bus, &error_fatal); qdev_connect_gpio_out(dev, 0, isa_irq >= 0 ? isa_get_irq(d, isa_irq) : alt_irq); @@ -69,10 +66,10 @@ static inline ISADevice *kvm_pit_init(ISABus *bus, int base) DeviceState *dev; ISADevice *d; - d = isa_create(bus, TYPE_KVM_I8254); + d = isa_new(TYPE_KVM_I8254); dev = DEVICE(d); qdev_prop_set_uint32(dev, "iobase", base); - qdev_init_nofail(dev); + isa_realize_and_unref(d, bus, &error_fatal); return d; } diff --git a/include/hw/timer/i8254_internal.h b/include/hw/timer/i8254_internal.h index 3db462aecd4b948b581cac344253b592145b055a..a9a600d941ae7c1a1ce9da71dc4e73222f01d3d4 100644 --- a/include/hw/timer/i8254_internal.h +++ b/include/hw/timer/i8254_internal.h @@ -50,14 +50,14 @@ typedef struct PITChannelState { uint32_t irq_disabled; } PITChannelState; -typedef struct PITCommonState { +struct PITCommonState { ISADevice dev; MemoryRegion ioports; uint32_t iobase; PITChannelState channels[3]; -} PITCommonState; +}; -typedef struct PITCommonClass { +struct PITCommonClass { ISADeviceClass parent_class; void (*set_channel_gate)(PITCommonState *s, PITChannelState *sc, int val); @@ -65,7 +65,7 @@ typedef struct PITCommonClass { PITChannelInfo *info); void (*pre_save)(PITCommonState *s); void (*post_load)(PITCommonState *s); -} PITCommonClass; +}; int pit_get_out(PITChannelState *s, int64_t current_time); int64_t pit_get_next_transition_time(PITChannelState *s, int64_t current_time); diff --git a/include/hw/timer/imx_epit.h b/include/hw/timer/imx_epit.h index 0730ac35e660cf30d568e98dc4c8f1d30129bc5a..2acc41e98220560874713a5d7004ff9e93f160b8 100644 --- a/include/hw/timer/imx_epit.h +++ b/include/hw/timer/imx_epit.h @@ -32,6 +32,7 @@ #include "hw/sysbus.h" #include "hw/ptimer.h" #include "hw/misc/imx_ccm.h" +#include "qom/object.h" /* * EPIT: Enhanced periodic interrupt timer @@ -55,9 +56,9 @@ #define EPIT_TIMER_MAX 0XFFFFFFFFUL #define TYPE_IMX_EPIT "imx.epit" -#define IMX_EPIT(obj) OBJECT_CHECK(IMXEPITState, (obj), TYPE_IMX_EPIT) +OBJECT_DECLARE_SIMPLE_TYPE(IMXEPITState, IMX_EPIT) -typedef struct IMXEPITState{ +struct IMXEPITState { /*< private >*/ SysBusDevice parent_obj; @@ -75,6 +76,6 @@ typedef struct IMXEPITState{ uint32_t freq; qemu_irq irq; -} IMXEPITState; +}; #endif /* IMX_EPIT_H */ diff --git a/include/hw/timer/imx_gpt.h b/include/hw/timer/imx_gpt.h index 20ccb327c4ae00595b4a8ec40c33a68bbadd541f..ff5c8a351a053cce9e95489cfead5a1f9f1fabb4 100644 --- a/include/hw/timer/imx_gpt.h +++ b/include/hw/timer/imx_gpt.h @@ -32,6 +32,7 @@ #include "hw/sysbus.h" #include "hw/ptimer.h" #include "hw/misc/imx_ccm.h" +#include "qom/object.h" /* * GPT : General purpose timer @@ -81,9 +82,11 @@ #define TYPE_IMX_GPT TYPE_IMX25_GPT -#define IMX_GPT(obj) OBJECT_CHECK(IMXGPTState, (obj), TYPE_IMX_GPT) +typedef struct IMXGPTState IMXGPTState; +DECLARE_INSTANCE_CHECKER(IMXGPTState, IMX_GPT, + TYPE_IMX_GPT) -typedef struct IMXGPTState{ +struct IMXGPTState { /*< private >*/ SysBusDevice parent_obj; @@ -111,6 +114,6 @@ typedef struct IMXGPTState{ qemu_irq irq; const IMXClk *clocks; -} IMXGPTState; +}; #endif /* IMX_GPT_H */ diff --git a/include/hw/timer/mss-timer.h b/include/hw/timer/mss-timer.h index e5a784b27e44eff9f1ce28c6296f8a4f182de663..da38512904e411333b9fa95e2ecfc65c1fd6850c 100644 --- a/include/hw/timer/mss-timer.h +++ b/include/hw/timer/mss-timer.h @@ -27,10 +27,10 @@ #include "hw/sysbus.h" #include "hw/ptimer.h" +#include "qom/object.h" #define TYPE_MSS_TIMER "mss-timer" -#define MSS_TIMER(obj) OBJECT_CHECK(MSSTimerState, \ - (obj), TYPE_MSS_TIMER) +OBJECT_DECLARE_SIMPLE_TYPE(MSSTimerState, MSS_TIMER) /* * There are two 32-bit down counting timers. @@ -52,12 +52,12 @@ struct Msf2Timer { qemu_irq irq; }; -typedef struct MSSTimerState { +struct MSSTimerState { SysBusDevice parent_obj; MemoryRegion mmio; uint32_t freq_hz; struct Msf2Timer timers[NUM_TIMERS]; -} MSSTimerState; +}; #endif /* HW_MSS_TIMER_H */ diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h new file mode 100644 index 0000000000000000000000000000000000000000..6993fd723a1082c4cea96f5ecc8bd06527e9d7fa --- /dev/null +++ b/include/hw/timer/npcm7xx_timer.h @@ -0,0 +1,112 @@ +/* + * Nuvoton NPCM7xx Timer Controller + * + * Copyright 2020 Google LLC + * + * 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. + */ +#ifndef NPCM7XX_TIMER_H +#define NPCM7XX_TIMER_H + +#include "exec/memory.h" +#include "hw/sysbus.h" +#include "qemu/timer.h" + +/* Each Timer Module (TIM) instance holds five 25 MHz timers. */ +#define NPCM7XX_TIMERS_PER_CTRL (5) + +/* + * Number of registers in our device state structure. Don't change this without + * incrementing the version_id in the vmstate. + */ +#define NPCM7XX_TIMER_NR_REGS (0x54 / sizeof(uint32_t)) + +/* The basic watchdog timer period is 2^14 clock cycles. */ +#define NPCM7XX_WATCHDOG_BASETIME_SHIFT 14 + +#define NPCM7XX_WATCHDOG_RESET_GPIO_OUT "npcm7xx-clk-watchdog-reset-gpio-out" + +typedef struct NPCM7xxTimerCtrlState NPCM7xxTimerCtrlState; + +/** + * struct NPCM7xxBaseTimer - Basic functionality that both regular timer and + * watchdog timer use. + * @qtimer: QEMU timer that notifies us on expiration. + * @expires_ns: Absolute virtual expiration time. + * @remaining_ns: Remaining time until expiration if timer is paused. + */ +typedef struct NPCM7xxBaseTimer { + QEMUTimer qtimer; + int64_t expires_ns; + int64_t remaining_ns; +} NPCM7xxBaseTimer; + +/** + * struct NPCM7xxTimer - Individual timer state. + * @ctrl: The timer module that owns this timer. + * @irq: GIC interrupt line to fire on expiration (if enabled). + * @base_timer: The basic timer functionality for this timer. + * @tcsr: The Timer Control and Status Register. + * @ticr: The Timer Initial Count Register. + */ +typedef struct NPCM7xxTimer { + NPCM7xxTimerCtrlState *ctrl; + + qemu_irq irq; + NPCM7xxBaseTimer base_timer; + + uint32_t tcsr; + uint32_t ticr; +} NPCM7xxTimer; + +/** + * struct NPCM7xxWatchdogTimer - The watchdog timer state. + * @ctrl: The timer module that owns this timer. + * @irq: GIC interrupt line to fire on expiration (if enabled). + * @reset_signal: The GPIO used to send a reset signal. + * @base_timer: The basic timer functionality for this timer. + * @wtcr: The Watchdog Timer Control Register. + */ +typedef struct NPCM7xxWatchdogTimer { + NPCM7xxTimerCtrlState *ctrl; + + qemu_irq irq; + qemu_irq reset_signal; + NPCM7xxBaseTimer base_timer; + + uint32_t wtcr; +} NPCM7xxWatchdogTimer; + +/** + * struct NPCM7xxTimerCtrlState - Timer Module device state. + * @parent: System bus device. + * @iomem: Memory region through which registers are accessed. + * @index: The index of this timer module. + * @tisr: The Timer Interrupt Status Register. + * @timer: The five individual timers managed by this module. + * @watchdog_timer: The watchdog timer managed by this module. + */ +struct NPCM7xxTimerCtrlState { + SysBusDevice parent; + + MemoryRegion iomem; + + uint32_t tisr; + + NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL]; + NPCM7xxWatchdogTimer watchdog_timer; +}; + +#define TYPE_NPCM7XX_TIMER "npcm7xx-timer" +#define NPCM7XX_TIMER(obj) \ + OBJECT_CHECK(NPCM7xxTimerCtrlState, (obj), TYPE_NPCM7XX_TIMER) + +#endif /* NPCM7XX_TIMER_H */ diff --git a/include/hw/timer/nrf51_timer.h b/include/hw/timer/nrf51_timer.h index eb6815f21d70f0058254cb78208d3d7ed3932e2e..76827c11dc790ee8f879488ad55346c5ca0cfa56 100644 --- a/include/hw/timer/nrf51_timer.h +++ b/include/hw/timer/nrf51_timer.h @@ -15,8 +15,9 @@ #include "hw/sysbus.h" #include "qemu/timer.h" +#include "qom/object.h" #define TYPE_NRF51_TIMER "nrf51_soc.timer" -#define NRF51_TIMER(obj) OBJECT_CHECK(NRF51TimerState, (obj), TYPE_NRF51_TIMER) +OBJECT_DECLARE_SIMPLE_TYPE(NRF51TimerState, NRF51_TIMER) #define NRF51_TIMER_REG_COUNT 4 @@ -53,7 +54,7 @@ #define NRF51_TIMER_REG_CC0 0x540 #define NRF51_TIMER_REG_CC3 0x54C -typedef struct NRF51TimerState { +struct NRF51TimerState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -75,7 +76,7 @@ typedef struct NRF51TimerState { uint32_t bitmode; uint32_t prescaler; -} NRF51TimerState; +}; #endif diff --git a/include/hw/timer/renesas_cmt.h b/include/hw/timer/renesas_cmt.h new file mode 100644 index 0000000000000000000000000000000000000000..1c0b65c1d5a702c4c18b48a5f37dd6c20f1db56b --- /dev/null +++ b/include/hw/timer/renesas_cmt.h @@ -0,0 +1,43 @@ +/* + * Renesas Compare-match timer Object + * + * Copyright (c) 2019 Yoshinori Sato + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_TIMER_RENESAS_CMT_H +#define HW_TIMER_RENESAS_CMT_H + +#include "qemu/timer.h" +#include "hw/sysbus.h" +#include "qom/object.h" + +#define TYPE_RENESAS_CMT "renesas-cmt" +typedef struct RCMTState RCMTState; +DECLARE_INSTANCE_CHECKER(RCMTState, RCMT, + TYPE_RENESAS_CMT) + +enum { + CMT_CH = 2, + CMT_NR_IRQ = 1 * CMT_CH +}; + +struct RCMTState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + uint64_t input_freq; + MemoryRegion memory; + + uint16_t cmstr; + uint16_t cmcr[CMT_CH]; + uint16_t cmcnt[CMT_CH]; + uint16_t cmcor[CMT_CH]; + int64_t tick[CMT_CH]; + qemu_irq cmi[CMT_CH]; + QEMUTimer timer[CMT_CH]; +}; + +#endif diff --git a/include/hw/timer/renesas_tmr.h b/include/hw/timer/renesas_tmr.h new file mode 100644 index 0000000000000000000000000000000000000000..caf7eec0dca527ecd97dc03600f91ef8ac02b363 --- /dev/null +++ b/include/hw/timer/renesas_tmr.h @@ -0,0 +1,58 @@ +/* + * Renesas 8bit timer Object + * + * Copyright (c) 2018 Yoshinori Sato + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_TIMER_RENESAS_TMR_H +#define HW_TIMER_RENESAS_TMR_H + +#include "qemu/timer.h" +#include "hw/sysbus.h" +#include "qom/object.h" + +#define TYPE_RENESAS_TMR "renesas-tmr" +typedef struct RTMRState RTMRState; +DECLARE_INSTANCE_CHECKER(RTMRState, RTMR, + TYPE_RENESAS_TMR) + +enum timer_event { + cmia = 0, + cmib = 1, + ovi = 2, + none = 3, + TMR_NR_EVENTS = 4 +}; + +enum { + TMR_CH = 2, + TMR_NR_IRQ = 3 * TMR_CH +}; + +struct RTMRState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + uint64_t input_freq; + MemoryRegion memory; + + int64_t tick; + uint8_t tcnt[TMR_CH]; + uint8_t tcora[TMR_CH]; + uint8_t tcorb[TMR_CH]; + uint8_t tcr[TMR_CH]; + uint8_t tccr[TMR_CH]; + uint8_t tcor[TMR_CH]; + uint8_t tcsr[TMR_CH]; + int64_t div_round[TMR_CH]; + uint8_t next[TMR_CH]; + qemu_irq cmia[TMR_CH]; + qemu_irq cmib[TMR_CH]; + qemu_irq ovi[TMR_CH]; + QEMUTimer timer[TMR_CH]; +}; + +#endif diff --git a/include/hw/timer/stm32f2xx_timer.h b/include/hw/timer/stm32f2xx_timer.h index a96bc08b1bbea950a5851ea53fbf89b0019e5cc0..90f40f1746f935d2657ca1ffc4c93615a64d3d71 100644 --- a/include/hw/timer/stm32f2xx_timer.h +++ b/include/hw/timer/stm32f2xx_timer.h @@ -27,6 +27,7 @@ #include "hw/sysbus.h" #include "qemu/timer.h" +#include "qom/object.h" #define TIM_CR1 0x00 #define TIM_CR2 0x04 @@ -61,10 +62,11 @@ #define TIM_DIER_UIE 1 #define TYPE_STM32F2XX_TIMER "stm32f2xx-timer" -#define STM32F2XXTIMER(obj) OBJECT_CHECK(STM32F2XXTimerState, \ - (obj), TYPE_STM32F2XX_TIMER) +typedef struct STM32F2XXTimerState STM32F2XXTimerState; +DECLARE_INSTANCE_CHECKER(STM32F2XXTimerState, STM32F2XXTIMER, + TYPE_STM32F2XX_TIMER) -typedef struct STM32F2XXTimerState { +struct STM32F2XXTimerState { /* */ SysBusDevice parent_obj; @@ -95,6 +97,6 @@ typedef struct STM32F2XXTimerState { uint32_t tim_dcr; uint32_t tim_dmar; uint32_t tim_or; -} STM32F2XXTimerState; +}; #endif /* HW_STM32F2XX_TIMER_H */ diff --git a/include/hw/timer/tmu012.h b/include/hw/timer/tmu012.h new file mode 100644 index 0000000000000000000000000000000000000000..808ed8de1d73bedc14ff0ecff66dc3352d1c0e44 --- /dev/null +++ b/include/hw/timer/tmu012.h @@ -0,0 +1,23 @@ +/* + * SuperH Timer + * + * Copyright (c) 2007 Magnus Damm + * + * This code is licensed under the GPL. + */ + +#ifndef HW_TIMER_TMU012_H +#define HW_TIMER_TMU012_H + +#include "exec/hwaddr.h" + +#define TMU012_FEAT_TOCR (1 << 0) +#define TMU012_FEAT_3CHAN (1 << 1) +#define TMU012_FEAT_EXTCLK (1 << 2) + +void tmu012_init(MemoryRegion *sysmem, hwaddr base, + int feat, uint32_t freq, + qemu_irq ch0_irq, qemu_irq ch1_irq, + qemu_irq ch2_irq0, qemu_irq ch2_irq1); + +#endif diff --git a/include/hw/usb.h b/include/hw/usb.h index 1cf1cd9584efc7948cd3bf9aa07d6d091688fdaa..a70a72e9177a9ac8a927c64c7e66135b35b5e15b 100644 --- a/include/hw/usb.h +++ b/include/hw/usb.h @@ -29,6 +29,7 @@ #include "hw/qdev-core.h" #include "qemu/iov.h" #include "qemu/queue.h" +#include "qom/object.h" /* Constants related to the USB / PCI interaction */ #define USB_SBRN 0x60 /* Serial Bus Release Number Register */ @@ -174,7 +175,6 @@ #define USB_INTERFACE_INVALID 255 -typedef struct USBBus USBBus; typedef struct USBBusOps USBBusOps; typedef struct USBPort USBPort; typedef struct USBDevice USBDevice; @@ -264,17 +264,12 @@ struct USBDevice { }; #define TYPE_USB_DEVICE "usb-device" -#define USB_DEVICE(obj) \ - OBJECT_CHECK(USBDevice, (obj), TYPE_USB_DEVICE) -#define USB_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(USBDeviceClass, (klass), TYPE_USB_DEVICE) -#define USB_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(USBDeviceClass, (obj), TYPE_USB_DEVICE) +OBJECT_DECLARE_TYPE(USBDevice, USBDeviceClass, USB_DEVICE) typedef void (*USBDeviceRealize)(USBDevice *dev, Error **errp); typedef void (*USBDeviceUnrealize)(USBDevice *dev); -typedef struct USBDeviceClass { +struct USBDeviceClass { DeviceClass parent_class; USBDeviceRealize realize; @@ -346,7 +341,7 @@ typedef struct USBDeviceClass { const char *product_desc; const USBDesc *usb_desc; bool attached_settable; -} USBDeviceClass; +}; typedef struct USBPortOps { void (*attach)(USBPort *port); @@ -474,40 +469,10 @@ bool usb_host_dev_is_scsi_storage(USBDevice *usbdev); #define VM_USB_HUB_SIZE 8 -/* hw/usb/hdc-musb.c */ - -enum musb_irq_source_e { - musb_irq_suspend = 0, - musb_irq_resume, - musb_irq_rst_babble, - musb_irq_sof, - musb_irq_connect, - musb_irq_disconnect, - musb_irq_vbus_request, - musb_irq_vbus_error, - musb_irq_rx, - musb_irq_tx, - musb_set_vbus, - musb_set_session, - /* Add new interrupts here */ - musb_irq_max, /* total number of interrupts defined */ -}; - -typedef struct MUSBState MUSBState; - -extern CPUReadMemoryFunc * const musb_read[]; -extern CPUWriteMemoryFunc * const musb_write[]; - -MUSBState *musb_init(DeviceState *parent_device, int gpio_base); -void musb_reset(MUSBState *s); -uint32_t musb_core_intr_get(MUSBState *s); -void musb_core_intr_clear(MUSBState *s, uint32_t mask); -void musb_set_size(MUSBState *s, int epnum, int size, int is_tx); - /* usb-bus.c */ #define TYPE_USB_BUS "usb-bus" -#define USB_BUS(obj) OBJECT_CHECK(USBBus, (obj), TYPE_USB_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(USBBus, USB_BUS) struct USBBus { BusState qbus; @@ -532,9 +497,9 @@ void usb_bus_new(USBBus *bus, size_t bus_size, void usb_bus_release(USBBus *bus); USBBus *usb_bus_find(int busnr); void usb_legacy_register(const char *typename, const char *usbdevice_name, - USBDevice *(*usbdevice_init)(USBBus *bus, - const char *params)); -USBDevice *usb_create(USBBus *bus, const char *name); + USBDevice *(*usbdevice_init)(const char *params)); +USBDevice *usb_new(const char *name); +bool usb_realize_and_unref(USBDevice *dev, USBBus *bus, Error **errp); USBDevice *usb_create_simple(USBBus *bus, const char *name); USBDevice *usbdevice_create(const char *cmdline); void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index, diff --git a/include/hw/usb/chipidea.h b/include/hw/usb/chipidea.h index 1ec2e9dbda49251c487865d5937b917315cc6085..fe4113ee01be0cb7e6301bd7f8532a174b987b61 100644 --- a/include/hw/usb/chipidea.h +++ b/include/hw/usb/chipidea.h @@ -2,15 +2,16 @@ #define CHIPIDEA_H #include "hw/usb/hcd-ehci.h" +#include "qom/object.h" -typedef struct ChipideaState { +struct ChipideaState { /*< private >*/ EHCISysBusState parent_obj; MemoryRegion iomem[3]; -} ChipideaState; +}; #define TYPE_CHIPIDEA "usb-chipidea" -#define CHIPIDEA(obj) OBJECT_CHECK(ChipideaState, (obj), TYPE_CHIPIDEA) +OBJECT_DECLARE_SIMPLE_TYPE(ChipideaState, CHIPIDEA) #endif /* CHIPIDEA_H */ diff --git a/include/hw/usb/dwc2-regs.h b/include/hw/usb/dwc2-regs.h new file mode 100644 index 0000000000000000000000000000000000000000..40af23a0bad8336c13656162de5f82d5b1e460f9 --- /dev/null +++ b/include/hw/usb/dwc2-regs.h @@ -0,0 +1,899 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * Imported from the Linux kernel file drivers/usb/dwc2/hw.h, commit + * a89bae709b3492b478480a2c9734e7e9393b279c ("usb: dwc2: Move + * UTMI_PHY_DATA defines closer") + * + * hw.h - DesignWare HS OTG Controller hardware definitions + * + * Copyright 2004-2013 Synopsys, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __DWC2_HW_H__ +#define __DWC2_HW_H__ + +#define HSOTG_REG(x) (x) + +#define GOTGCTL HSOTG_REG(0x000) +#define GOTGCTL_CHIRPEN BIT(27) +#define GOTGCTL_MULT_VALID_BC_MASK (0x1f << 22) +#define GOTGCTL_MULT_VALID_BC_SHIFT 22 +#define GOTGCTL_OTGVER BIT(20) +#define GOTGCTL_BSESVLD BIT(19) +#define GOTGCTL_ASESVLD BIT(18) +#define GOTGCTL_DBNC_SHORT BIT(17) +#define GOTGCTL_CONID_B BIT(16) +#define GOTGCTL_DBNCE_FLTR_BYPASS BIT(15) +#define GOTGCTL_DEVHNPEN BIT(11) +#define GOTGCTL_HSTSETHNPEN BIT(10) +#define GOTGCTL_HNPREQ BIT(9) +#define GOTGCTL_HSTNEGSCS BIT(8) +#define GOTGCTL_SESREQ BIT(1) +#define GOTGCTL_SESREQSCS BIT(0) + +#define GOTGINT HSOTG_REG(0x004) +#define GOTGINT_DBNCE_DONE BIT(19) +#define GOTGINT_A_DEV_TOUT_CHG BIT(18) +#define GOTGINT_HST_NEG_DET BIT(17) +#define GOTGINT_HST_NEG_SUC_STS_CHNG BIT(9) +#define GOTGINT_SES_REQ_SUC_STS_CHNG BIT(8) +#define GOTGINT_SES_END_DET BIT(2) + +#define GAHBCFG HSOTG_REG(0x008) +#define GAHBCFG_AHB_SINGLE BIT(23) +#define GAHBCFG_NOTI_ALL_DMA_WRIT BIT(22) +#define GAHBCFG_REM_MEM_SUPP BIT(21) +#define GAHBCFG_P_TXF_EMP_LVL BIT(8) +#define GAHBCFG_NP_TXF_EMP_LVL BIT(7) +#define GAHBCFG_DMA_EN BIT(5) +#define GAHBCFG_HBSTLEN_MASK (0xf << 1) +#define GAHBCFG_HBSTLEN_SHIFT 1 +#define GAHBCFG_HBSTLEN_SINGLE 0 +#define GAHBCFG_HBSTLEN_INCR 1 +#define GAHBCFG_HBSTLEN_INCR4 3 +#define GAHBCFG_HBSTLEN_INCR8 5 +#define GAHBCFG_HBSTLEN_INCR16 7 +#define GAHBCFG_GLBL_INTR_EN BIT(0) +#define GAHBCFG_CTRL_MASK (GAHBCFG_P_TXF_EMP_LVL | \ + GAHBCFG_NP_TXF_EMP_LVL | \ + GAHBCFG_DMA_EN | \ + GAHBCFG_GLBL_INTR_EN) + +#define GUSBCFG HSOTG_REG(0x00C) +#define GUSBCFG_FORCEDEVMODE BIT(30) +#define GUSBCFG_FORCEHOSTMODE BIT(29) +#define GUSBCFG_TXENDDELAY BIT(28) +#define GUSBCFG_ICTRAFFICPULLREMOVE BIT(27) +#define GUSBCFG_ICUSBCAP BIT(26) +#define GUSBCFG_ULPI_INT_PROT_DIS BIT(25) +#define GUSBCFG_INDICATORPASSTHROUGH BIT(24) +#define GUSBCFG_INDICATORCOMPLEMENT BIT(23) +#define GUSBCFG_TERMSELDLPULSE BIT(22) +#define GUSBCFG_ULPI_INT_VBUS_IND BIT(21) +#define GUSBCFG_ULPI_EXT_VBUS_DRV BIT(20) +#define GUSBCFG_ULPI_CLK_SUSP_M BIT(19) +#define GUSBCFG_ULPI_AUTO_RES BIT(18) +#define GUSBCFG_ULPI_FS_LS BIT(17) +#define GUSBCFG_OTG_UTMI_FS_SEL BIT(16) +#define GUSBCFG_PHY_LP_CLK_SEL BIT(15) +#define GUSBCFG_USBTRDTIM_MASK (0xf << 10) +#define GUSBCFG_USBTRDTIM_SHIFT 10 +#define GUSBCFG_HNPCAP BIT(9) +#define GUSBCFG_SRPCAP BIT(8) +#define GUSBCFG_DDRSEL BIT(7) +#define GUSBCFG_PHYSEL BIT(6) +#define GUSBCFG_FSINTF BIT(5) +#define GUSBCFG_ULPI_UTMI_SEL BIT(4) +#define GUSBCFG_PHYIF16 BIT(3) +#define GUSBCFG_PHYIF8 (0 << 3) +#define GUSBCFG_TOUTCAL_MASK (0x7 << 0) +#define GUSBCFG_TOUTCAL_SHIFT 0 +#define GUSBCFG_TOUTCAL_LIMIT 0x7 +#define GUSBCFG_TOUTCAL(_x) ((_x) << 0) + +#define GRSTCTL HSOTG_REG(0x010) +#define GRSTCTL_AHBIDLE BIT(31) +#define GRSTCTL_DMAREQ BIT(30) +#define GRSTCTL_TXFNUM_MASK (0x1f << 6) +#define GRSTCTL_TXFNUM_SHIFT 6 +#define GRSTCTL_TXFNUM_LIMIT 0x1f +#define GRSTCTL_TXFNUM(_x) ((_x) << 6) +#define GRSTCTL_TXFFLSH BIT(5) +#define GRSTCTL_RXFFLSH BIT(4) +#define GRSTCTL_IN_TKNQ_FLSH BIT(3) +#define GRSTCTL_FRMCNTRRST BIT(2) +#define GRSTCTL_HSFTRST BIT(1) +#define GRSTCTL_CSFTRST BIT(0) + +#define GINTSTS HSOTG_REG(0x014) +#define GINTMSK HSOTG_REG(0x018) +#define GINTSTS_WKUPINT BIT(31) +#define GINTSTS_SESSREQINT BIT(30) +#define GINTSTS_DISCONNINT BIT(29) +#define GINTSTS_CONIDSTSCHNG BIT(28) +#define GINTSTS_LPMTRANRCVD BIT(27) +#define GINTSTS_PTXFEMP BIT(26) +#define GINTSTS_HCHINT BIT(25) +#define GINTSTS_PRTINT BIT(24) +#define GINTSTS_RESETDET BIT(23) +#define GINTSTS_FET_SUSP BIT(22) +#define GINTSTS_INCOMPL_IP BIT(21) +#define GINTSTS_INCOMPL_SOOUT BIT(21) +#define GINTSTS_INCOMPL_SOIN BIT(20) +#define GINTSTS_OEPINT BIT(19) +#define GINTSTS_IEPINT BIT(18) +#define GINTSTS_EPMIS BIT(17) +#define GINTSTS_RESTOREDONE BIT(16) +#define GINTSTS_EOPF BIT(15) +#define GINTSTS_ISOUTDROP BIT(14) +#define GINTSTS_ENUMDONE BIT(13) +#define GINTSTS_USBRST BIT(12) +#define GINTSTS_USBSUSP BIT(11) +#define GINTSTS_ERLYSUSP BIT(10) +#define GINTSTS_I2CINT BIT(9) +#define GINTSTS_ULPI_CK_INT BIT(8) +#define GINTSTS_GOUTNAKEFF BIT(7) +#define GINTSTS_GINNAKEFF BIT(6) +#define GINTSTS_NPTXFEMP BIT(5) +#define GINTSTS_RXFLVL BIT(4) +#define GINTSTS_SOF BIT(3) +#define GINTSTS_OTGINT BIT(2) +#define GINTSTS_MODEMIS BIT(1) +#define GINTSTS_CURMODE_HOST BIT(0) + +#define GRXSTSR HSOTG_REG(0x01C) +#define GRXSTSP HSOTG_REG(0x020) +#define GRXSTS_FN_MASK (0x7f << 25) +#define GRXSTS_FN_SHIFT 25 +#define GRXSTS_PKTSTS_MASK (0xf << 17) +#define GRXSTS_PKTSTS_SHIFT 17 +#define GRXSTS_PKTSTS_GLOBALOUTNAK 1 +#define GRXSTS_PKTSTS_OUTRX 2 +#define GRXSTS_PKTSTS_HCHIN 2 +#define GRXSTS_PKTSTS_OUTDONE 3 +#define GRXSTS_PKTSTS_HCHIN_XFER_COMP 3 +#define GRXSTS_PKTSTS_SETUPDONE 4 +#define GRXSTS_PKTSTS_DATATOGGLEERR 5 +#define GRXSTS_PKTSTS_SETUPRX 6 +#define GRXSTS_PKTSTS_HCHHALTED 7 +#define GRXSTS_HCHNUM_MASK (0xf << 0) +#define GRXSTS_HCHNUM_SHIFT 0 +#define GRXSTS_DPID_MASK (0x3 << 15) +#define GRXSTS_DPID_SHIFT 15 +#define GRXSTS_BYTECNT_MASK (0x7ff << 4) +#define GRXSTS_BYTECNT_SHIFT 4 +#define GRXSTS_EPNUM_MASK (0xf << 0) +#define GRXSTS_EPNUM_SHIFT 0 + +#define GRXFSIZ HSOTG_REG(0x024) +#define GRXFSIZ_DEPTH_MASK (0xffff << 0) +#define GRXFSIZ_DEPTH_SHIFT 0 + +#define GNPTXFSIZ HSOTG_REG(0x028) +/* Use FIFOSIZE_* constants to access this register */ + +#define GNPTXSTS HSOTG_REG(0x02C) +#define GNPTXSTS_NP_TXQ_TOP_MASK (0x7f << 24) +#define GNPTXSTS_NP_TXQ_TOP_SHIFT 24 +#define GNPTXSTS_NP_TXQ_SPC_AVAIL_MASK (0xff << 16) +#define GNPTXSTS_NP_TXQ_SPC_AVAIL_SHIFT 16 +#define GNPTXSTS_NP_TXQ_SPC_AVAIL_GET(_v) (((_v) >> 16) & 0xff) +#define GNPTXSTS_NP_TXF_SPC_AVAIL_MASK (0xffff << 0) +#define GNPTXSTS_NP_TXF_SPC_AVAIL_SHIFT 0 +#define GNPTXSTS_NP_TXF_SPC_AVAIL_GET(_v) (((_v) >> 0) & 0xffff) + +#define GI2CCTL HSOTG_REG(0x0030) +#define GI2CCTL_BSYDNE BIT(31) +#define GI2CCTL_RW BIT(30) +#define GI2CCTL_I2CDATSE0 BIT(28) +#define GI2CCTL_I2CDEVADDR_MASK (0x3 << 26) +#define GI2CCTL_I2CDEVADDR_SHIFT 26 +#define GI2CCTL_I2CSUSPCTL BIT(25) +#define GI2CCTL_ACK BIT(24) +#define GI2CCTL_I2CEN BIT(23) +#define GI2CCTL_ADDR_MASK (0x7f << 16) +#define GI2CCTL_ADDR_SHIFT 16 +#define GI2CCTL_REGADDR_MASK (0xff << 8) +#define GI2CCTL_REGADDR_SHIFT 8 +#define GI2CCTL_RWDATA_MASK (0xff << 0) +#define GI2CCTL_RWDATA_SHIFT 0 + +#define GPVNDCTL HSOTG_REG(0x0034) +#define GGPIO HSOTG_REG(0x0038) +#define GGPIO_STM32_OTG_GCCFG_PWRDWN BIT(16) + +#define GUID HSOTG_REG(0x003c) +#define GSNPSID HSOTG_REG(0x0040) +#define GHWCFG1 HSOTG_REG(0x0044) +#define GSNPSID_ID_MASK GENMASK(31, 16) + +#define GHWCFG2 HSOTG_REG(0x0048) +#define GHWCFG2_OTG_ENABLE_IC_USB BIT(31) +#define GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK (0x1f << 26) +#define GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT 26 +#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK (0x3 << 24) +#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT 24 +#define GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK (0x3 << 22) +#define GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT 22 +#define GHWCFG2_MULTI_PROC_INT BIT(20) +#define GHWCFG2_DYNAMIC_FIFO BIT(19) +#define GHWCFG2_PERIO_EP_SUPPORTED BIT(18) +#define GHWCFG2_NUM_HOST_CHAN_MASK (0xf << 14) +#define GHWCFG2_NUM_HOST_CHAN_SHIFT 14 +#define GHWCFG2_NUM_DEV_EP_MASK (0xf << 10) +#define GHWCFG2_NUM_DEV_EP_SHIFT 10 +#define GHWCFG2_FS_PHY_TYPE_MASK (0x3 << 8) +#define GHWCFG2_FS_PHY_TYPE_SHIFT 8 +#define GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED 0 +#define GHWCFG2_FS_PHY_TYPE_DEDICATED 1 +#define GHWCFG2_FS_PHY_TYPE_SHARED_UTMI 2 +#define GHWCFG2_FS_PHY_TYPE_SHARED_ULPI 3 +#define GHWCFG2_HS_PHY_TYPE_MASK (0x3 << 6) +#define GHWCFG2_HS_PHY_TYPE_SHIFT 6 +#define GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0 +#define GHWCFG2_HS_PHY_TYPE_UTMI 1 +#define GHWCFG2_HS_PHY_TYPE_ULPI 2 +#define GHWCFG2_HS_PHY_TYPE_UTMI_ULPI 3 +#define GHWCFG2_POINT2POINT BIT(5) +#define GHWCFG2_ARCHITECTURE_MASK (0x3 << 3) +#define GHWCFG2_ARCHITECTURE_SHIFT 3 +#define GHWCFG2_SLAVE_ONLY_ARCH 0 +#define GHWCFG2_EXT_DMA_ARCH 1 +#define GHWCFG2_INT_DMA_ARCH 2 +#define GHWCFG2_OP_MODE_MASK (0x7 << 0) +#define GHWCFG2_OP_MODE_SHIFT 0 +#define GHWCFG2_OP_MODE_HNP_SRP_CAPABLE 0 +#define GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE 1 +#define GHWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE 2 +#define GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3 +#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4 +#define GHWCFG2_OP_MODE_SRP_CAPABLE_HOST 5 +#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6 +#define GHWCFG2_OP_MODE_UNDEFINED 7 + +#define GHWCFG3 HSOTG_REG(0x004c) +#define GHWCFG3_DFIFO_DEPTH_MASK (0xffff << 16) +#define GHWCFG3_DFIFO_DEPTH_SHIFT 16 +#define GHWCFG3_OTG_LPM_EN BIT(15) +#define GHWCFG3_BC_SUPPORT BIT(14) +#define GHWCFG3_OTG_ENABLE_HSIC BIT(13) +#define GHWCFG3_ADP_SUPP BIT(12) +#define GHWCFG3_SYNCH_RESET_TYPE BIT(11) +#define GHWCFG3_OPTIONAL_FEATURES BIT(10) +#define GHWCFG3_VENDOR_CTRL_IF BIT(9) +#define GHWCFG3_I2C BIT(8) +#define GHWCFG3_OTG_FUNC BIT(7) +#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK (0x7 << 4) +#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT 4 +#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK (0xf << 0) +#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT 0 + +#define GHWCFG4 HSOTG_REG(0x0050) +#define GHWCFG4_DESC_DMA_DYN BIT(31) +#define GHWCFG4_DESC_DMA BIT(30) +#define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26) +#define GHWCFG4_NUM_IN_EPS_SHIFT 26 +#define GHWCFG4_DED_FIFO_EN BIT(25) +#define GHWCFG4_DED_FIFO_SHIFT 25 +#define GHWCFG4_SESSION_END_FILT_EN BIT(24) +#define GHWCFG4_B_VALID_FILT_EN BIT(23) +#define GHWCFG4_A_VALID_FILT_EN BIT(22) +#define GHWCFG4_VBUS_VALID_FILT_EN BIT(21) +#define GHWCFG4_IDDIG_FILT_EN BIT(20) +#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_MASK (0xf << 16) +#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_SHIFT 16 +#define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14) +#define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT 14 +#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0 +#define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1 +#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2 +#define GHWCFG4_ACG_SUPPORTED BIT(12) +#define GHWCFG4_IPG_ISOC_SUPPORTED BIT(11) +#define GHWCFG4_SERVICE_INTERVAL_SUPPORTED BIT(10) +#define GHWCFG4_XHIBER BIT(7) +#define GHWCFG4_HIBER BIT(6) +#define GHWCFG4_MIN_AHB_FREQ BIT(5) +#define GHWCFG4_POWER_OPTIMIZ BIT(4) +#define GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK (0xf << 0) +#define GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT 0 + +#define GLPMCFG HSOTG_REG(0x0054) +#define GLPMCFG_INVSELHSIC BIT(31) +#define GLPMCFG_HSICCON BIT(30) +#define GLPMCFG_RSTRSLPSTS BIT(29) +#define GLPMCFG_ENBESL BIT(28) +#define GLPMCFG_LPM_RETRYCNT_STS_MASK (0x7 << 25) +#define GLPMCFG_LPM_RETRYCNT_STS_SHIFT 25 +#define GLPMCFG_SNDLPM BIT(24) +#define GLPMCFG_RETRY_CNT_MASK (0x7 << 21) +#define GLPMCFG_RETRY_CNT_SHIFT 21 +#define GLPMCFG_LPM_REJECT_CTRL_CONTROL BIT(21) +#define GLPMCFG_LPM_ACCEPT_CTRL_ISOC BIT(22) +#define GLPMCFG_LPM_CHNL_INDX_MASK (0xf << 17) +#define GLPMCFG_LPM_CHNL_INDX_SHIFT 17 +#define GLPMCFG_L1RESUMEOK BIT(16) +#define GLPMCFG_SLPSTS BIT(15) +#define GLPMCFG_COREL1RES_MASK (0x3 << 13) +#define GLPMCFG_COREL1RES_SHIFT 13 +#define GLPMCFG_HIRD_THRES_MASK (0x1f << 8) +#define GLPMCFG_HIRD_THRES_SHIFT 8 +#define GLPMCFG_HIRD_THRES_EN (0x10 << 8) +#define GLPMCFG_ENBLSLPM BIT(7) +#define GLPMCFG_BREMOTEWAKE BIT(6) +#define GLPMCFG_HIRD_MASK (0xf << 2) +#define GLPMCFG_HIRD_SHIFT 2 +#define GLPMCFG_APPL1RES BIT(1) +#define GLPMCFG_LPMCAP BIT(0) + +#define GPWRDN HSOTG_REG(0x0058) +#define GPWRDN_MULT_VAL_ID_BC_MASK (0x1f << 24) +#define GPWRDN_MULT_VAL_ID_BC_SHIFT 24 +#define GPWRDN_ADP_INT BIT(23) +#define GPWRDN_BSESSVLD BIT(22) +#define GPWRDN_IDSTS BIT(21) +#define GPWRDN_LINESTATE_MASK (0x3 << 19) +#define GPWRDN_LINESTATE_SHIFT 19 +#define GPWRDN_STS_CHGINT_MSK BIT(18) +#define GPWRDN_STS_CHGINT BIT(17) +#define GPWRDN_SRP_DET_MSK BIT(16) +#define GPWRDN_SRP_DET BIT(15) +#define GPWRDN_CONNECT_DET_MSK BIT(14) +#define GPWRDN_CONNECT_DET BIT(13) +#define GPWRDN_DISCONN_DET_MSK BIT(12) +#define GPWRDN_DISCONN_DET BIT(11) +#define GPWRDN_RST_DET_MSK BIT(10) +#define GPWRDN_RST_DET BIT(9) +#define GPWRDN_LNSTSCHG_MSK BIT(8) +#define GPWRDN_LNSTSCHG BIT(7) +#define GPWRDN_DIS_VBUS BIT(6) +#define GPWRDN_PWRDNSWTCH BIT(5) +#define GPWRDN_PWRDNRSTN BIT(4) +#define GPWRDN_PWRDNCLMP BIT(3) +#define GPWRDN_RESTORE BIT(2) +#define GPWRDN_PMUACTV BIT(1) +#define GPWRDN_PMUINTSEL BIT(0) + +#define GDFIFOCFG HSOTG_REG(0x005c) +#define GDFIFOCFG_EPINFOBASE_MASK (0xffff << 16) +#define GDFIFOCFG_EPINFOBASE_SHIFT 16 +#define GDFIFOCFG_GDFIFOCFG_MASK (0xffff << 0) +#define GDFIFOCFG_GDFIFOCFG_SHIFT 0 + +#define ADPCTL HSOTG_REG(0x0060) +#define ADPCTL_AR_MASK (0x3 << 27) +#define ADPCTL_AR_SHIFT 27 +#define ADPCTL_ADP_TMOUT_INT_MSK BIT(26) +#define ADPCTL_ADP_SNS_INT_MSK BIT(25) +#define ADPCTL_ADP_PRB_INT_MSK BIT(24) +#define ADPCTL_ADP_TMOUT_INT BIT(23) +#define ADPCTL_ADP_SNS_INT BIT(22) +#define ADPCTL_ADP_PRB_INT BIT(21) +#define ADPCTL_ADPENA BIT(20) +#define ADPCTL_ADPRES BIT(19) +#define ADPCTL_ENASNS BIT(18) +#define ADPCTL_ENAPRB BIT(17) +#define ADPCTL_RTIM_MASK (0x7ff << 6) +#define ADPCTL_RTIM_SHIFT 6 +#define ADPCTL_PRB_PER_MASK (0x3 << 4) +#define ADPCTL_PRB_PER_SHIFT 4 +#define ADPCTL_PRB_DELTA_MASK (0x3 << 2) +#define ADPCTL_PRB_DELTA_SHIFT 2 +#define ADPCTL_PRB_DSCHRG_MASK (0x3 << 0) +#define ADPCTL_PRB_DSCHRG_SHIFT 0 + +#define GREFCLK HSOTG_REG(0x0064) +#define GREFCLK_REFCLKPER_MASK (0x1ffff << 15) +#define GREFCLK_REFCLKPER_SHIFT 15 +#define GREFCLK_REF_CLK_MODE BIT(14) +#define GREFCLK_SOF_CNT_WKUP_ALERT_MASK (0x3ff) +#define GREFCLK_SOF_CNT_WKUP_ALERT_SHIFT 0 + +#define GINTMSK2 HSOTG_REG(0x0068) +#define GINTMSK2_WKUP_ALERT_INT_MSK BIT(0) + +#define GINTSTS2 HSOTG_REG(0x006c) +#define GINTSTS2_WKUP_ALERT_INT BIT(0) + +#define HPTXFSIZ HSOTG_REG(0x100) +/* Use FIFOSIZE_* constants to access this register */ + +#define DPTXFSIZN(_a) HSOTG_REG(0x104 + (((_a) - 1) * 4)) +/* Use FIFOSIZE_* constants to access this register */ + +/* These apply to the GNPTXFSIZ, HPTXFSIZ and DPTXFSIZN registers */ +#define FIFOSIZE_DEPTH_MASK (0xffff << 16) +#define FIFOSIZE_DEPTH_SHIFT 16 +#define FIFOSIZE_STARTADDR_MASK (0xffff << 0) +#define FIFOSIZE_STARTADDR_SHIFT 0 +#define FIFOSIZE_DEPTH_GET(_x) (((_x) >> 16) & 0xffff) + +/* Device mode registers */ + +#define DCFG HSOTG_REG(0x800) +#define DCFG_DESCDMA_EN BIT(23) +#define DCFG_EPMISCNT_MASK (0x1f << 18) +#define DCFG_EPMISCNT_SHIFT 18 +#define DCFG_EPMISCNT_LIMIT 0x1f +#define DCFG_EPMISCNT(_x) ((_x) << 18) +#define DCFG_IPG_ISOC_SUPPORDED BIT(17) +#define DCFG_PERFRINT_MASK (0x3 << 11) +#define DCFG_PERFRINT_SHIFT 11 +#define DCFG_PERFRINT_LIMIT 0x3 +#define DCFG_PERFRINT(_x) ((_x) << 11) +#define DCFG_DEVADDR_MASK (0x7f << 4) +#define DCFG_DEVADDR_SHIFT 4 +#define DCFG_DEVADDR_LIMIT 0x7f +#define DCFG_DEVADDR(_x) ((_x) << 4) +#define DCFG_NZ_STS_OUT_HSHK BIT(2) +#define DCFG_DEVSPD_MASK (0x3 << 0) +#define DCFG_DEVSPD_SHIFT 0 +#define DCFG_DEVSPD_HS 0 +#define DCFG_DEVSPD_FS 1 +#define DCFG_DEVSPD_LS 2 +#define DCFG_DEVSPD_FS48 3 + +#define DCTL HSOTG_REG(0x804) +#define DCTL_SERVICE_INTERVAL_SUPPORTED BIT(19) +#define DCTL_PWRONPRGDONE BIT(11) +#define DCTL_CGOUTNAK BIT(10) +#define DCTL_SGOUTNAK BIT(9) +#define DCTL_CGNPINNAK BIT(8) +#define DCTL_SGNPINNAK BIT(7) +#define DCTL_TSTCTL_MASK (0x7 << 4) +#define DCTL_TSTCTL_SHIFT 4 +#define DCTL_GOUTNAKSTS BIT(3) +#define DCTL_GNPINNAKSTS BIT(2) +#define DCTL_SFTDISCON BIT(1) +#define DCTL_RMTWKUPSIG BIT(0) + +#define DSTS HSOTG_REG(0x808) +#define DSTS_SOFFN_MASK (0x3fff << 8) +#define DSTS_SOFFN_SHIFT 8 +#define DSTS_SOFFN_LIMIT 0x3fff +#define DSTS_SOFFN(_x) ((_x) << 8) +#define DSTS_ERRATICERR BIT(3) +#define DSTS_ENUMSPD_MASK (0x3 << 1) +#define DSTS_ENUMSPD_SHIFT 1 +#define DSTS_ENUMSPD_HS 0 +#define DSTS_ENUMSPD_FS 1 +#define DSTS_ENUMSPD_LS 2 +#define DSTS_ENUMSPD_FS48 3 +#define DSTS_SUSPSTS BIT(0) + +#define DIEPMSK HSOTG_REG(0x810) +#define DIEPMSK_NAKMSK BIT(13) +#define DIEPMSK_BNAININTRMSK BIT(9) +#define DIEPMSK_TXFIFOUNDRNMSK BIT(8) +#define DIEPMSK_TXFIFOEMPTY BIT(7) +#define DIEPMSK_INEPNAKEFFMSK BIT(6) +#define DIEPMSK_INTKNEPMISMSK BIT(5) +#define DIEPMSK_INTKNTXFEMPMSK BIT(4) +#define DIEPMSK_TIMEOUTMSK BIT(3) +#define DIEPMSK_AHBERRMSK BIT(2) +#define DIEPMSK_EPDISBLDMSK BIT(1) +#define DIEPMSK_XFERCOMPLMSK BIT(0) + +#define DOEPMSK HSOTG_REG(0x814) +#define DOEPMSK_BNAMSK BIT(9) +#define DOEPMSK_BACK2BACKSETUP BIT(6) +#define DOEPMSK_STSPHSERCVDMSK BIT(5) +#define DOEPMSK_OUTTKNEPDISMSK BIT(4) +#define DOEPMSK_SETUPMSK BIT(3) +#define DOEPMSK_AHBERRMSK BIT(2) +#define DOEPMSK_EPDISBLDMSK BIT(1) +#define DOEPMSK_XFERCOMPLMSK BIT(0) + +#define DAINT HSOTG_REG(0x818) +#define DAINTMSK HSOTG_REG(0x81C) +#define DAINT_OUTEP_SHIFT 16 +#define DAINT_OUTEP(_x) (1 << ((_x) + 16)) +#define DAINT_INEP(_x) (1 << (_x)) + +#define DTKNQR1 HSOTG_REG(0x820) +#define DTKNQR2 HSOTG_REG(0x824) +#define DTKNQR3 HSOTG_REG(0x830) +#define DTKNQR4 HSOTG_REG(0x834) +#define DIEPEMPMSK HSOTG_REG(0x834) + +#define DVBUSDIS HSOTG_REG(0x828) +#define DVBUSPULSE HSOTG_REG(0x82C) + +#define DIEPCTL0 HSOTG_REG(0x900) +#define DIEPCTL(_a) HSOTG_REG(0x900 + ((_a) * 0x20)) + +#define DOEPCTL0 HSOTG_REG(0xB00) +#define DOEPCTL(_a) HSOTG_REG(0xB00 + ((_a) * 0x20)) + +/* EP0 specialness: + * bits[29..28] - reserved (no SetD0PID, SetD1PID) + * bits[25..22] - should always be zero, this isn't a periodic endpoint + * bits[10..0] - MPS setting different for EP0 + */ +#define D0EPCTL_MPS_MASK (0x3 << 0) +#define D0EPCTL_MPS_SHIFT 0 +#define D0EPCTL_MPS_64 0 +#define D0EPCTL_MPS_32 1 +#define D0EPCTL_MPS_16 2 +#define D0EPCTL_MPS_8 3 + +#define DXEPCTL_EPENA BIT(31) +#define DXEPCTL_EPDIS BIT(30) +#define DXEPCTL_SETD1PID BIT(29) +#define DXEPCTL_SETODDFR BIT(29) +#define DXEPCTL_SETD0PID BIT(28) +#define DXEPCTL_SETEVENFR BIT(28) +#define DXEPCTL_SNAK BIT(27) +#define DXEPCTL_CNAK BIT(26) +#define DXEPCTL_TXFNUM_MASK (0xf << 22) +#define DXEPCTL_TXFNUM_SHIFT 22 +#define DXEPCTL_TXFNUM_LIMIT 0xf +#define DXEPCTL_TXFNUM(_x) ((_x) << 22) +#define DXEPCTL_STALL BIT(21) +#define DXEPCTL_SNP BIT(20) +#define DXEPCTL_EPTYPE_MASK (0x3 << 18) +#define DXEPCTL_EPTYPE_CONTROL (0x0 << 18) +#define DXEPCTL_EPTYPE_ISO (0x1 << 18) +#define DXEPCTL_EPTYPE_BULK (0x2 << 18) +#define DXEPCTL_EPTYPE_INTERRUPT (0x3 << 18) + +#define DXEPCTL_NAKSTS BIT(17) +#define DXEPCTL_DPID BIT(16) +#define DXEPCTL_EOFRNUM BIT(16) +#define DXEPCTL_USBACTEP BIT(15) +#define DXEPCTL_NEXTEP_MASK (0xf << 11) +#define DXEPCTL_NEXTEP_SHIFT 11 +#define DXEPCTL_NEXTEP_LIMIT 0xf +#define DXEPCTL_NEXTEP(_x) ((_x) << 11) +#define DXEPCTL_MPS_MASK (0x7ff << 0) +#define DXEPCTL_MPS_SHIFT 0 +#define DXEPCTL_MPS_LIMIT 0x7ff +#define DXEPCTL_MPS(_x) ((_x) << 0) + +#define DIEPINT(_a) HSOTG_REG(0x908 + ((_a) * 0x20)) +#define DOEPINT(_a) HSOTG_REG(0xB08 + ((_a) * 0x20)) +#define DXEPINT_SETUP_RCVD BIT(15) +#define DXEPINT_NYETINTRPT BIT(14) +#define DXEPINT_NAKINTRPT BIT(13) +#define DXEPINT_BBLEERRINTRPT BIT(12) +#define DXEPINT_PKTDRPSTS BIT(11) +#define DXEPINT_BNAINTR BIT(9) +#define DXEPINT_TXFIFOUNDRN BIT(8) +#define DXEPINT_OUTPKTERR BIT(8) +#define DXEPINT_TXFEMP BIT(7) +#define DXEPINT_INEPNAKEFF BIT(6) +#define DXEPINT_BACK2BACKSETUP BIT(6) +#define DXEPINT_INTKNEPMIS BIT(5) +#define DXEPINT_STSPHSERCVD BIT(5) +#define DXEPINT_INTKNTXFEMP BIT(4) +#define DXEPINT_OUTTKNEPDIS BIT(4) +#define DXEPINT_TIMEOUT BIT(3) +#define DXEPINT_SETUP BIT(3) +#define DXEPINT_AHBERR BIT(2) +#define DXEPINT_EPDISBLD BIT(1) +#define DXEPINT_XFERCOMPL BIT(0) + +#define DIEPTSIZ0 HSOTG_REG(0x910) +#define DIEPTSIZ0_PKTCNT_MASK (0x3 << 19) +#define DIEPTSIZ0_PKTCNT_SHIFT 19 +#define DIEPTSIZ0_PKTCNT_LIMIT 0x3 +#define DIEPTSIZ0_PKTCNT(_x) ((_x) << 19) +#define DIEPTSIZ0_XFERSIZE_MASK (0x7f << 0) +#define DIEPTSIZ0_XFERSIZE_SHIFT 0 +#define DIEPTSIZ0_XFERSIZE_LIMIT 0x7f +#define DIEPTSIZ0_XFERSIZE(_x) ((_x) << 0) + +#define DOEPTSIZ0 HSOTG_REG(0xB10) +#define DOEPTSIZ0_SUPCNT_MASK (0x3 << 29) +#define DOEPTSIZ0_SUPCNT_SHIFT 29 +#define DOEPTSIZ0_SUPCNT_LIMIT 0x3 +#define DOEPTSIZ0_SUPCNT(_x) ((_x) << 29) +#define DOEPTSIZ0_PKTCNT BIT(19) +#define DOEPTSIZ0_XFERSIZE_MASK (0x7f << 0) +#define DOEPTSIZ0_XFERSIZE_SHIFT 0 + +#define DIEPTSIZ(_a) HSOTG_REG(0x910 + ((_a) * 0x20)) +#define DOEPTSIZ(_a) HSOTG_REG(0xB10 + ((_a) * 0x20)) +#define DXEPTSIZ_MC_MASK (0x3 << 29) +#define DXEPTSIZ_MC_SHIFT 29 +#define DXEPTSIZ_MC_LIMIT 0x3 +#define DXEPTSIZ_MC(_x) ((_x) << 29) +#define DXEPTSIZ_PKTCNT_MASK (0x3ff << 19) +#define DXEPTSIZ_PKTCNT_SHIFT 19 +#define DXEPTSIZ_PKTCNT_LIMIT 0x3ff +#define DXEPTSIZ_PKTCNT_GET(_v) (((_v) >> 19) & 0x3ff) +#define DXEPTSIZ_PKTCNT(_x) ((_x) << 19) +#define DXEPTSIZ_XFERSIZE_MASK (0x7ffff << 0) +#define DXEPTSIZ_XFERSIZE_SHIFT 0 +#define DXEPTSIZ_XFERSIZE_LIMIT 0x7ffff +#define DXEPTSIZ_XFERSIZE_GET(_v) (((_v) >> 0) & 0x7ffff) +#define DXEPTSIZ_XFERSIZE(_x) ((_x) << 0) + +#define DIEPDMA(_a) HSOTG_REG(0x914 + ((_a) * 0x20)) +#define DOEPDMA(_a) HSOTG_REG(0xB14 + ((_a) * 0x20)) + +#define DTXFSTS(_a) HSOTG_REG(0x918 + ((_a) * 0x20)) + +#define PCGCTL HSOTG_REG(0x0e00) +#define PCGCTL_IF_DEV_MODE BIT(31) +#define PCGCTL_P2HD_PRT_SPD_MASK (0x3 << 29) +#define PCGCTL_P2HD_PRT_SPD_SHIFT 29 +#define PCGCTL_P2HD_DEV_ENUM_SPD_MASK (0x3 << 27) +#define PCGCTL_P2HD_DEV_ENUM_SPD_SHIFT 27 +#define PCGCTL_MAC_DEV_ADDR_MASK (0x7f << 20) +#define PCGCTL_MAC_DEV_ADDR_SHIFT 20 +#define PCGCTL_MAX_TERMSEL BIT(19) +#define PCGCTL_MAX_XCVRSELECT_MASK (0x3 << 17) +#define PCGCTL_MAX_XCVRSELECT_SHIFT 17 +#define PCGCTL_PORT_POWER BIT(16) +#define PCGCTL_PRT_CLK_SEL_MASK (0x3 << 14) +#define PCGCTL_PRT_CLK_SEL_SHIFT 14 +#define PCGCTL_ESS_REG_RESTORED BIT(13) +#define PCGCTL_EXTND_HIBER_SWITCH BIT(12) +#define PCGCTL_EXTND_HIBER_PWRCLMP BIT(11) +#define PCGCTL_ENBL_EXTND_HIBER BIT(10) +#define PCGCTL_RESTOREMODE BIT(9) +#define PCGCTL_RESETAFTSUSP BIT(8) +#define PCGCTL_DEEP_SLEEP BIT(7) +#define PCGCTL_PHY_IN_SLEEP BIT(6) +#define PCGCTL_ENBL_SLEEP_GATING BIT(5) +#define PCGCTL_RSTPDWNMODULE BIT(3) +#define PCGCTL_PWRCLMP BIT(2) +#define PCGCTL_GATEHCLK BIT(1) +#define PCGCTL_STOPPCLK BIT(0) + +#define PCGCCTL1 HSOTG_REG(0xe04) +#define PCGCCTL1_TIMER (0x3 << 1) +#define PCGCCTL1_GATEEN BIT(0) + +#define EPFIFO(_a) HSOTG_REG(0x1000 + ((_a) * 0x1000)) + +/* Host Mode Registers */ + +#define HCFG HSOTG_REG(0x0400) +#define HCFG_MODECHTIMEN BIT(31) +#define HCFG_PERSCHEDENA BIT(26) +#define HCFG_FRLISTEN_MASK (0x3 << 24) +#define HCFG_FRLISTEN_SHIFT 24 +#define HCFG_FRLISTEN_8 (0 << 24) +#define FRLISTEN_8_SIZE 8 +#define HCFG_FRLISTEN_16 BIT(24) +#define FRLISTEN_16_SIZE 16 +#define HCFG_FRLISTEN_32 (2 << 24) +#define FRLISTEN_32_SIZE 32 +#define HCFG_FRLISTEN_64 (3 << 24) +#define FRLISTEN_64_SIZE 64 +#define HCFG_DESCDMA BIT(23) +#define HCFG_RESVALID_MASK (0xff << 8) +#define HCFG_RESVALID_SHIFT 8 +#define HCFG_ENA32KHZ BIT(7) +#define HCFG_FSLSSUPP BIT(2) +#define HCFG_FSLSPCLKSEL_MASK (0x3 << 0) +#define HCFG_FSLSPCLKSEL_SHIFT 0 +#define HCFG_FSLSPCLKSEL_30_60_MHZ 0 +#define HCFG_FSLSPCLKSEL_48_MHZ 1 +#define HCFG_FSLSPCLKSEL_6_MHZ 2 + +#define HFIR HSOTG_REG(0x0404) +#define HFIR_FRINT_MASK (0xffff << 0) +#define HFIR_FRINT_SHIFT 0 +#define HFIR_RLDCTRL BIT(16) + +#define HFNUM HSOTG_REG(0x0408) +#define HFNUM_FRREM_MASK (0xffff << 16) +#define HFNUM_FRREM_SHIFT 16 +#define HFNUM_FRNUM_MASK (0xffff << 0) +#define HFNUM_FRNUM_SHIFT 0 +#define HFNUM_MAX_FRNUM 0x3fff + +#define HPTXSTS HSOTG_REG(0x0410) +#define TXSTS_QTOP_ODD BIT(31) +#define TXSTS_QTOP_CHNEP_MASK (0xf << 27) +#define TXSTS_QTOP_CHNEP_SHIFT 27 +#define TXSTS_QTOP_TOKEN_MASK (0x3 << 25) +#define TXSTS_QTOP_TOKEN_SHIFT 25 +#define TXSTS_QTOP_TERMINATE BIT(24) +#define TXSTS_QSPCAVAIL_MASK (0xff << 16) +#define TXSTS_QSPCAVAIL_SHIFT 16 +#define TXSTS_FSPCAVAIL_MASK (0xffff << 0) +#define TXSTS_FSPCAVAIL_SHIFT 0 + +#define HAINT HSOTG_REG(0x0414) +#define HAINTMSK HSOTG_REG(0x0418) +#define HFLBADDR HSOTG_REG(0x041c) + +#define HPRT0 HSOTG_REG(0x0440) +#define HPRT0_SPD_MASK (0x3 << 17) +#define HPRT0_SPD_SHIFT 17 +#define HPRT0_SPD_HIGH_SPEED 0 +#define HPRT0_SPD_FULL_SPEED 1 +#define HPRT0_SPD_LOW_SPEED 2 +#define HPRT0_TSTCTL_MASK (0xf << 13) +#define HPRT0_TSTCTL_SHIFT 13 +#define HPRT0_PWR BIT(12) +#define HPRT0_LNSTS_MASK (0x3 << 10) +#define HPRT0_LNSTS_SHIFT 10 +#define HPRT0_RST BIT(8) +#define HPRT0_SUSP BIT(7) +#define HPRT0_RES BIT(6) +#define HPRT0_OVRCURRCHG BIT(5) +#define HPRT0_OVRCURRACT BIT(4) +#define HPRT0_ENACHG BIT(3) +#define HPRT0_ENA BIT(2) +#define HPRT0_CONNDET BIT(1) +#define HPRT0_CONNSTS BIT(0) + +#define HCCHAR(_ch) HSOTG_REG(0x0500 + 0x20 * (_ch)) +#define HCCHAR_CHENA BIT(31) +#define HCCHAR_CHDIS BIT(30) +#define HCCHAR_ODDFRM BIT(29) +#define HCCHAR_DEVADDR_MASK (0x7f << 22) +#define HCCHAR_DEVADDR_SHIFT 22 +#define HCCHAR_MULTICNT_MASK (0x3 << 20) +#define HCCHAR_MULTICNT_SHIFT 20 +#define HCCHAR_EPTYPE_MASK (0x3 << 18) +#define HCCHAR_EPTYPE_SHIFT 18 +#define HCCHAR_LSPDDEV BIT(17) +#define HCCHAR_EPDIR BIT(15) +#define HCCHAR_EPNUM_MASK (0xf << 11) +#define HCCHAR_EPNUM_SHIFT 11 +#define HCCHAR_MPS_MASK (0x7ff << 0) +#define HCCHAR_MPS_SHIFT 0 + +#define HCSPLT(_ch) HSOTG_REG(0x0504 + 0x20 * (_ch)) +#define HCSPLT_SPLTENA BIT(31) +#define HCSPLT_COMPSPLT BIT(16) +#define HCSPLT_XACTPOS_MASK (0x3 << 14) +#define HCSPLT_XACTPOS_SHIFT 14 +#define HCSPLT_XACTPOS_MID 0 +#define HCSPLT_XACTPOS_END 1 +#define HCSPLT_XACTPOS_BEGIN 2 +#define HCSPLT_XACTPOS_ALL 3 +#define HCSPLT_HUBADDR_MASK (0x7f << 7) +#define HCSPLT_HUBADDR_SHIFT 7 +#define HCSPLT_PRTADDR_MASK (0x7f << 0) +#define HCSPLT_PRTADDR_SHIFT 0 + +#define HCINT(_ch) HSOTG_REG(0x0508 + 0x20 * (_ch)) +#define HCINTMSK(_ch) HSOTG_REG(0x050c + 0x20 * (_ch)) +#define HCINTMSK_RESERVED14_31 (0x3ffff << 14) +#define HCINTMSK_FRM_LIST_ROLL BIT(13) +#define HCINTMSK_XCS_XACT BIT(12) +#define HCINTMSK_BNA BIT(11) +#define HCINTMSK_DATATGLERR BIT(10) +#define HCINTMSK_FRMOVRUN BIT(9) +#define HCINTMSK_BBLERR BIT(8) +#define HCINTMSK_XACTERR BIT(7) +#define HCINTMSK_NYET BIT(6) +#define HCINTMSK_ACK BIT(5) +#define HCINTMSK_NAK BIT(4) +#define HCINTMSK_STALL BIT(3) +#define HCINTMSK_AHBERR BIT(2) +#define HCINTMSK_CHHLTD BIT(1) +#define HCINTMSK_XFERCOMPL BIT(0) + +#define HCTSIZ(_ch) HSOTG_REG(0x0510 + 0x20 * (_ch)) +#define TSIZ_DOPNG BIT(31) +#define TSIZ_SC_MC_PID_MASK (0x3 << 29) +#define TSIZ_SC_MC_PID_SHIFT 29 +#define TSIZ_SC_MC_PID_DATA0 0 +#define TSIZ_SC_MC_PID_DATA2 1 +#define TSIZ_SC_MC_PID_DATA1 2 +#define TSIZ_SC_MC_PID_MDATA 3 +#define TSIZ_SC_MC_PID_SETUP 3 +#define TSIZ_PKTCNT_MASK (0x3ff << 19) +#define TSIZ_PKTCNT_SHIFT 19 +#define TSIZ_NTD_MASK (0xff << 8) +#define TSIZ_NTD_SHIFT 8 +#define TSIZ_SCHINFO_MASK (0xff << 0) +#define TSIZ_SCHINFO_SHIFT 0 +#define TSIZ_XFERSIZE_MASK (0x7ffff << 0) +#define TSIZ_XFERSIZE_SHIFT 0 + +#define HCDMA(_ch) HSOTG_REG(0x0514 + 0x20 * (_ch)) + +#define HCDMAB(_ch) HSOTG_REG(0x051c + 0x20 * (_ch)) + +#define HCFIFO(_ch) HSOTG_REG(0x1000 + 0x1000 * (_ch)) + +/** + * struct dwc2_dma_desc - DMA descriptor structure, + * used for both host and gadget modes + * + * @status: DMA descriptor status quadlet + * @buf: DMA descriptor data buffer pointer + * + * DMA Descriptor structure contains two quadlets: + * Status quadlet and Data buffer pointer. + */ +struct dwc2_dma_desc { + uint32_t status; + uint32_t buf; +} __packed; + +/* Host Mode DMA descriptor status quadlet */ + +#define HOST_DMA_A BIT(31) +#define HOST_DMA_STS_MASK (0x3 << 28) +#define HOST_DMA_STS_SHIFT 28 +#define HOST_DMA_STS_PKTERR BIT(28) +#define HOST_DMA_EOL BIT(26) +#define HOST_DMA_IOC BIT(25) +#define HOST_DMA_SUP BIT(24) +#define HOST_DMA_ALT_QTD BIT(23) +#define HOST_DMA_QTD_OFFSET_MASK (0x3f << 17) +#define HOST_DMA_QTD_OFFSET_SHIFT 17 +#define HOST_DMA_ISOC_NBYTES_MASK (0xfff << 0) +#define HOST_DMA_ISOC_NBYTES_SHIFT 0 +#define HOST_DMA_NBYTES_MASK (0x1ffff << 0) +#define HOST_DMA_NBYTES_SHIFT 0 +#define HOST_DMA_NBYTES_LIMIT 131071 + +/* Device Mode DMA descriptor status quadlet */ + +#define DEV_DMA_BUFF_STS_MASK (0x3 << 30) +#define DEV_DMA_BUFF_STS_SHIFT 30 +#define DEV_DMA_BUFF_STS_HREADY 0 +#define DEV_DMA_BUFF_STS_DMABUSY 1 +#define DEV_DMA_BUFF_STS_DMADONE 2 +#define DEV_DMA_BUFF_STS_HBUSY 3 +#define DEV_DMA_STS_MASK (0x3 << 28) +#define DEV_DMA_STS_SHIFT 28 +#define DEV_DMA_STS_SUCC 0 +#define DEV_DMA_STS_BUFF_FLUSH 1 +#define DEV_DMA_STS_BUFF_ERR 3 +#define DEV_DMA_L BIT(27) +#define DEV_DMA_SHORT BIT(26) +#define DEV_DMA_IOC BIT(25) +#define DEV_DMA_SR BIT(24) +#define DEV_DMA_MTRF BIT(23) +#define DEV_DMA_ISOC_PID_MASK (0x3 << 23) +#define DEV_DMA_ISOC_PID_SHIFT 23 +#define DEV_DMA_ISOC_PID_DATA0 0 +#define DEV_DMA_ISOC_PID_DATA2 1 +#define DEV_DMA_ISOC_PID_DATA1 2 +#define DEV_DMA_ISOC_PID_MDATA 3 +#define DEV_DMA_ISOC_FRNUM_MASK (0x7ff << 12) +#define DEV_DMA_ISOC_FRNUM_SHIFT 12 +#define DEV_DMA_ISOC_TX_NBYTES_MASK (0xfff << 0) +#define DEV_DMA_ISOC_TX_NBYTES_LIMIT 0xfff +#define DEV_DMA_ISOC_RX_NBYTES_MASK (0x7ff << 0) +#define DEV_DMA_ISOC_RX_NBYTES_LIMIT 0x7ff +#define DEV_DMA_ISOC_NBYTES_SHIFT 0 +#define DEV_DMA_NBYTES_MASK (0xffff << 0) +#define DEV_DMA_NBYTES_SHIFT 0 +#define DEV_DMA_NBYTES_LIMIT 0xffff + +#define MAX_DMA_DESC_NUM_GENERIC 64 +#define MAX_DMA_DESC_NUM_HS_ISOC 256 + +#endif /* __DWC2_HW_H__ */ diff --git a/include/hw/usb/hcd-musb.h b/include/hw/usb/hcd-musb.h new file mode 100644 index 0000000000000000000000000000000000000000..c874b9f292f97c16c12403d52226337be821e254 --- /dev/null +++ b/include/hw/usb/hcd-musb.h @@ -0,0 +1,47 @@ +/* + * "Inventra" High-speed Dual-Role Controller (MUSB-HDRC), Mentor Graphics, + * USB2.0 OTG compliant core used in various chips. + * + * Only host-mode and non-DMA accesses are currently supported. + * + * Copyright (C) 2008 Nokia Corporation + * Written by Andrzej Zaborowski + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_USB_MUSB_H +#define HW_USB_MUSB_H + +enum musb_irq_source_e { + musb_irq_suspend = 0, + musb_irq_resume, + musb_irq_rst_babble, + musb_irq_sof, + musb_irq_connect, + musb_irq_disconnect, + musb_irq_vbus_request, + musb_irq_vbus_error, + musb_irq_rx, + musb_irq_tx, + musb_set_vbus, + musb_set_session, + /* Add new interrupts here */ + musb_irq_max /* total number of interrupts defined */ +}; + +/* TODO convert hcd-musb to QOM/qdev and remove MUSBReadFunc/MUSBWriteFunc */ +typedef void MUSBWriteFunc(void *opaque, hwaddr addr, uint32_t value); +typedef uint32_t MUSBReadFunc(void *opaque, hwaddr addr); +extern MUSBReadFunc * const musb_read[]; +extern MUSBWriteFunc * const musb_write[]; + +typedef struct MUSBState MUSBState; + +MUSBState *musb_init(DeviceState *parent_device, int gpio_base); +void musb_reset(MUSBState *s); +uint32_t musb_core_intr_get(MUSBState *s); +void musb_core_intr_clear(MUSBState *s, uint32_t mask); +void musb_set_size(MUSBState *s, int epnum, int size, int is_tx); + +#endif diff --git a/include/hw/usb/hid.h b/include/hw/usb/hid.h new file mode 100644 index 0000000000000000000000000000000000000000..1c142584ffabbe9b94280bccc84ab9a725d81b7e --- /dev/null +++ b/include/hw/usb/hid.h @@ -0,0 +1,17 @@ +#ifndef HW_USB_HID_H +#define HW_USB_HID_H + +/* HID interface requests */ +#define HID_GET_REPORT 0xa101 +#define HID_GET_IDLE 0xa102 +#define HID_GET_PROTOCOL 0xa103 +#define HID_SET_REPORT 0x2109 +#define HID_SET_IDLE 0x210a +#define HID_SET_PROTOCOL 0x210b + +/* HID descriptor types */ +#define USB_DT_HID 0x21 +#define USB_DT_REPORT 0x22 +#define USB_DT_PHY 0x23 + +#endif diff --git a/include/hw/usb/imx-usb-phy.h b/include/hw/usb/imx-usb-phy.h index 07f0235d101f3772d7a2426bcb72555c76305b1e..d1e867b77a3b95ffc1072aa803b6a156cfd5a412 100644 --- a/include/hw/usb/imx-usb-phy.h +++ b/include/hw/usb/imx-usb-phy.h @@ -3,6 +3,7 @@ #include "hw/sysbus.h" #include "qemu/bitops.h" +#include "qom/object.h" enum IMXUsbPhyRegisters { USBPHY_PWD, @@ -38,9 +39,9 @@ enum IMXUsbPhyRegisters { #define USBPHY_CTRL_SFTRST BIT(31) #define TYPE_IMX_USBPHY "imx.usbphy" -#define IMX_USBPHY(obj) OBJECT_CHECK(IMXUSBPHYState, (obj), TYPE_IMX_USBPHY) +OBJECT_DECLARE_SIMPLE_TYPE(IMXUSBPHYState, IMX_USBPHY) -typedef struct IMXUSBPHYState { +struct IMXUSBPHYState { /* */ SysBusDevice parent_obj; @@ -48,6 +49,6 @@ typedef struct IMXUSBPHYState { MemoryRegion iomem; uint32_t usbphy[USBPHY_MAX]; -} IMXUSBPHYState; +}; #endif /* IMX_USB_PHY_H */ diff --git a/include/hw/usb/xhci.h b/include/hw/usb/xhci.h new file mode 100644 index 0000000000000000000000000000000000000000..5c90e1373e5554991ad61aff0e4ab534fe64c218 --- /dev/null +++ b/include/hw/usb/xhci.h @@ -0,0 +1,21 @@ +#ifndef HW_USB_XHCI_H +#define HW_USB_XHCI_H + +#define TYPE_XHCI "base-xhci" +#define TYPE_NEC_XHCI "nec-usb-xhci" +#define TYPE_QEMU_XHCI "qemu-xhci" +#define TYPE_XHCI_SYSBUS "sysbus-xhci" + +#define XHCI_MAXPORTS_2 15 +#define XHCI_MAXPORTS_3 15 + +#define XHCI_MAXPORTS (XHCI_MAXPORTS_2 + XHCI_MAXPORTS_3) +#define XHCI_MAXSLOTS 64 +#define XHCI_MAXINTRS 16 + +/* must be power of 2 */ +#define XHCI_LEN_REGS 0x4000 + +void xhci_sysbus_build_aml(Aml *scope, uint32_t mmio, unsigned int irq); + +#endif diff --git a/include/hw/vfio/vfio-amd-xgbe.h b/include/hw/vfio/vfio-amd-xgbe.h index 9fff65e99d480988bac4ca6f21cfc18f19a36032..a894546c02d140d2b689f09ace733c4d43019371 100644 --- a/include/hw/vfio/vfio-amd-xgbe.h +++ b/include/hw/vfio/vfio-amd-xgbe.h @@ -15,6 +15,7 @@ #define HW_VFIO_VFIO_AMD_XGBE_H #include "hw/vfio/vfio-platform.h" +#include "qom/object.h" #define TYPE_VFIO_AMD_XGBE "vfio-amd-xgbe" @@ -39,13 +40,7 @@ struct VFIOAmdXgbeDeviceClass { typedef struct VFIOAmdXgbeDeviceClass VFIOAmdXgbeDeviceClass; -#define VFIO_AMD_XGBE_DEVICE(obj) \ - OBJECT_CHECK(VFIOAmdXgbeDevice, (obj), TYPE_VFIO_AMD_XGBE) -#define VFIO_AMD_XGBE_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(VFIOAmdXgbeDeviceClass, (klass), \ - TYPE_VFIO_AMD_XGBE) -#define VFIO_AMD_XGBE_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VFIOAmdXgbeDeviceClass, (obj), \ - TYPE_VFIO_AMD_XGBE) +DECLARE_OBJ_CHECKERS(VFIOAmdXgbeDevice, VFIOAmdXgbeDeviceClass, + VFIO_AMD_XGBE_DEVICE, TYPE_VFIO_AMD_XGBE) #endif diff --git a/include/hw/vfio/vfio-calxeda-xgmac.h b/include/hw/vfio/vfio-calxeda-xgmac.h index f994775c093012a3520fac0127f1678cee418963..8482f151dd5ab8ca5f7e8f4300e67314604a68e3 100644 --- a/include/hw/vfio/vfio-calxeda-xgmac.h +++ b/include/hw/vfio/vfio-calxeda-xgmac.h @@ -15,6 +15,7 @@ #define HW_VFIO_VFIO_CALXEDA_XGMAC_H #include "hw/vfio/vfio-platform.h" +#include "qom/object.h" #define TYPE_VFIO_CALXEDA_XGMAC "vfio-calxeda-xgmac" @@ -23,24 +24,20 @@ * - a single MMIO region corresponding to its register space * - 3 IRQS (main and 2 power related IRQs) */ -typedef struct VFIOCalxedaXgmacDevice { +struct VFIOCalxedaXgmacDevice { VFIOPlatformDevice vdev; -} VFIOCalxedaXgmacDevice; +}; +typedef struct VFIOCalxedaXgmacDevice VFIOCalxedaXgmacDevice; -typedef struct VFIOCalxedaXgmacDeviceClass { +struct VFIOCalxedaXgmacDeviceClass { /*< private >*/ VFIOPlatformDeviceClass parent_class; /*< public >*/ DeviceRealize parent_realize; -} VFIOCalxedaXgmacDeviceClass; +}; +typedef struct VFIOCalxedaXgmacDeviceClass VFIOCalxedaXgmacDeviceClass; -#define VFIO_CALXEDA_XGMAC_DEVICE(obj) \ - OBJECT_CHECK(VFIOCalxedaXgmacDevice, (obj), TYPE_VFIO_CALXEDA_XGMAC) -#define VFIO_CALXEDA_XGMAC_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(VFIOCalxedaXgmacDeviceClass, (klass), \ - TYPE_VFIO_CALXEDA_XGMAC) -#define VFIO_CALXEDA_XGMAC_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VFIOCalxedaXgmacDeviceClass, (obj), \ - TYPE_VFIO_CALXEDA_XGMAC) +DECLARE_OBJ_CHECKERS(VFIOCalxedaXgmacDevice, VFIOCalxedaXgmacDeviceClass, + VFIO_CALXEDA_XGMAC_DEVICE, TYPE_VFIO_CALXEDA_XGMAC) #endif diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index fd564209ac710afb15325a452b8f79058033f998..6141162d7aeaee06ef2ff9210e55b508d9235f77 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -29,6 +29,7 @@ #ifdef CONFIG_LINUX #include #endif +#include "sysemu/sysemu.h" #define VFIO_MSG_PREFIX "vfio %s: " @@ -57,6 +58,16 @@ typedef struct VFIORegion { uint8_t nr; /* cache the region number for debug */ } VFIORegion; +typedef struct VFIOMigration { + struct VFIODevice *vbasedev; + VMChangeStateEntry *vm_state; + VFIORegion region; + uint32_t device_state; + int vm_running; + Notifier migration_state; + uint64_t pending_bytes; +} VFIOMigration; + typedef struct VFIOAddressSpace { AddressSpace *as; QLIST_HEAD(, VFIOContainer) containers; @@ -73,6 +84,9 @@ typedef struct VFIOContainer { unsigned iommu_type; Error *error; bool initialized; + bool dirty_pages_supported; + uint64_t dirty_pgsizes; + uint64_t max_dirty_bitmap_size; unsigned long pgsizes; QLIST_HEAD(, VFIOGuestIOMMU) giommu_list; QLIST_HEAD(, VFIOHostDMAWindow) hostwin_list; @@ -108,17 +122,24 @@ typedef struct VFIODevice { bool reset_works; bool needs_reset; bool no_mmap; - bool balloon_allowed; + bool ram_block_discard_allowed; + bool enable_migration; VFIODeviceOps *ops; unsigned int num_irqs; unsigned int num_regions; unsigned int flags; + VFIOMigration *migration; + Error *migration_blocker; + OnOffAuto pre_copy_dirty_page_tracking; } VFIODevice; struct VFIODeviceOps { void (*vfio_compute_needs_reset)(VFIODevice *vdev); int (*vfio_hot_reset_multi)(VFIODevice *vdev); void (*vfio_eoi)(VFIODevice *vdev); + Object *(*vfio_get_object)(VFIODevice *vdev); + void (*vfio_save_config)(VFIODevice *vdev, QEMUFile *f); + int (*vfio_load_config)(VFIODevice *vdev, QEMUFile *f); }; typedef struct VFIOGroup { @@ -128,7 +149,7 @@ typedef struct VFIOGroup { QLIST_HEAD(, VFIODevice) device_list; QLIST_ENTRY(VFIOGroup) next; QLIST_ENTRY(VFIOGroup) container_next; - bool balloon_allowed; + bool ram_block_discard_allowed; } VFIOGroup; typedef struct VFIODMABuf { @@ -171,6 +192,7 @@ int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region, int index, const char *name); int vfio_region_mmap(VFIORegion *region); void vfio_region_mmaps_set_enabled(VFIORegion *region, bool enabled); +void vfio_region_unmap(VFIORegion *region); void vfio_region_exit(VFIORegion *region); void vfio_region_finalize(VFIORegion *region); void vfio_reset_handler(void *opaque); @@ -183,6 +205,9 @@ extern const MemoryRegionOps vfio_region_ops; typedef QLIST_HEAD(VFIOGroupList, VFIOGroup) VFIOGroupList; extern VFIOGroupList vfio_group_list; +bool vfio_mig_active(void); +int64_t vfio_mig_bytes_transferred(void); + #ifdef CONFIG_LINUX int vfio_get_region_info(VFIODevice *vbasedev, int index, struct vfio_region_info **info); @@ -191,6 +216,10 @@ int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type); struct vfio_info_cap_header * vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id); +bool vfio_get_info_dma_avail(struct vfio_iommu_type1_info *info, + unsigned int *avail); +struct vfio_info_cap_header * +vfio_get_device_info_cap(struct vfio_device_info *info, uint16_t id); #endif extern const MemoryListener vfio_prereg_listener; @@ -200,4 +229,7 @@ int vfio_spapr_create_window(VFIOContainer *container, int vfio_spapr_remove_window(VFIOContainer *container, hwaddr offset_within_address_space); +int vfio_migration_probe(VFIODevice *vbasedev, Error **errp); +void vfio_migration_finalize(VFIODevice *vbasedev); + #endif /* HW_VFIO_VFIO_COMMON_H */ diff --git a/include/hw/vfio/vfio-platform.h b/include/hw/vfio/vfio-platform.h index 4ec70c813a2ce69cd543048de19df342427ce313..c414c3dffcc840a2f40a1b252d0f7b4e309c78d4 100644 --- a/include/hw/vfio/vfio-platform.h +++ b/include/hw/vfio/vfio-platform.h @@ -20,6 +20,7 @@ #include "hw/vfio/vfio-common.h" #include "qemu/event_notifier.h" #include "qemu/queue.h" +#include "qom/object.h" #define TYPE_VFIO_PLATFORM "vfio-platform" @@ -46,7 +47,7 @@ typedef struct VFIOINTp { /* function type for user side eventfd handler */ typedef void (*eventfd_user_side_handler_t)(VFIOINTp *intp); -typedef struct VFIOPlatformDevice { +struct VFIOPlatformDevice { SysBusDevice sbdev; VFIODevice vbasedev; /* not a QOM object */ VFIORegion **regions; @@ -59,19 +60,17 @@ typedef struct VFIOPlatformDevice { QEMUTimer *mmap_timer; /* allows fast-path resume after IRQ hit */ QemuMutex intp_mutex; /* protect the intp_list IRQ state */ bool irqfd_allowed; /* debug option to force irqfd on/off */ -} VFIOPlatformDevice; +}; +typedef struct VFIOPlatformDevice VFIOPlatformDevice; -typedef struct VFIOPlatformDeviceClass { +struct VFIOPlatformDeviceClass { /*< private >*/ SysBusDeviceClass parent_class; /*< public >*/ -} VFIOPlatformDeviceClass; +}; +typedef struct VFIOPlatformDeviceClass VFIOPlatformDeviceClass; -#define VFIO_PLATFORM_DEVICE(obj) \ - OBJECT_CHECK(VFIOPlatformDevice, (obj), TYPE_VFIO_PLATFORM) -#define VFIO_PLATFORM_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(VFIOPlatformDeviceClass, (klass), TYPE_VFIO_PLATFORM) -#define VFIO_PLATFORM_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VFIOPlatformDeviceClass, (obj), TYPE_VFIO_PLATFORM) +DECLARE_OBJ_CHECKERS(VFIOPlatformDevice, VFIOPlatformDeviceClass, + VFIO_PLATFORM_DEVICE, TYPE_VFIO_PLATFORM) #endif /* HW_VFIO_VFIO_PLATFORM_H */ diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h index 6f6670783f7a3c8c84842d90bfeba6877ddb0671..8a6f8e2a7a30c591c2233f6b4003c129804f0fa2 100644 --- a/include/hw/virtio/vhost-backend.h +++ b/include/hw/virtio/vhost-backend.h @@ -17,7 +17,8 @@ typedef enum VhostBackendType { VHOST_BACKEND_TYPE_NONE = 0, VHOST_BACKEND_TYPE_KERNEL = 1, VHOST_BACKEND_TYPE_USER = 2, - VHOST_BACKEND_TYPE_MAX = 3, + VHOST_BACKEND_TYPE_VDPA = 3, + VHOST_BACKEND_TYPE_MAX = 4, } VhostBackendType; typedef enum VhostSetConfigType { @@ -34,6 +35,7 @@ struct vhost_vring_state; struct vhost_vring_addr; struct vhost_scsi_target; struct vhost_iotlb_msg; +struct vhost_virtqueue; typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque); typedef int (*vhost_backend_cleanup)(struct vhost_dev *dev); @@ -72,6 +74,7 @@ typedef int (*vhost_set_features_op)(struct vhost_dev *dev, uint64_t features); typedef int (*vhost_get_features_op)(struct vhost_dev *dev, uint64_t *features); +typedef int (*vhost_set_backend_cap_op)(struct vhost_dev *dev); typedef int (*vhost_set_owner_op)(struct vhost_dev *dev); typedef int (*vhost_reset_device_op)(struct vhost_dev *dev); typedef int (*vhost_get_vq_index_op)(struct vhost_dev *dev, int idx); @@ -112,6 +115,16 @@ typedef int (*vhost_get_inflight_fd_op)(struct vhost_dev *dev, typedef int (*vhost_set_inflight_fd_op)(struct vhost_dev *dev, struct vhost_inflight *inflight); +typedef int (*vhost_dev_start_op)(struct vhost_dev *dev, bool started); + +typedef int (*vhost_vq_get_addr_op)(struct vhost_dev *dev, + struct vhost_vring_addr *addr, + struct vhost_virtqueue *vq); + +typedef int (*vhost_get_device_id_op)(struct vhost_dev *dev, uint32_t *dev_id); + +typedef bool (*vhost_force_iommu_op)(struct vhost_dev *dev); + typedef struct VhostOps { VhostBackendType backend_type; vhost_backend_init vhost_backend_init; @@ -134,6 +147,7 @@ typedef struct VhostOps { vhost_set_vring_busyloop_timeout_op vhost_set_vring_busyloop_timeout; vhost_set_features_op vhost_set_features; vhost_get_features_op vhost_get_features; + vhost_set_backend_cap_op vhost_set_backend_cap; vhost_set_owner_op vhost_set_owner; vhost_reset_device_op vhost_reset_device; vhost_get_vq_index_op vhost_get_vq_index; @@ -152,9 +166,14 @@ typedef struct VhostOps { vhost_backend_mem_section_filter_op vhost_backend_mem_section_filter; vhost_get_inflight_fd_op vhost_get_inflight_fd; vhost_set_inflight_fd_op vhost_set_inflight_fd; + vhost_dev_start_op vhost_dev_start; + vhost_vq_get_addr_op vhost_vq_get_addr; + vhost_get_device_id_op vhost_get_device_id; + vhost_force_iommu_op vhost_force_iommu; } VhostOps; extern const VhostOps user_ops; +extern const VhostOps vdpa_ops; int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type); diff --git a/include/hw/virtio/vhost-scsi-common.h b/include/hw/virtio/vhost-scsi-common.h index 16bf1a73c1675113023af7decaf8ac29e9f76c1d..18f115527ce46e7545cccbf5f997929e41542dc0 100644 --- a/include/hw/virtio/vhost-scsi-common.h +++ b/include/hw/virtio/vhost-scsi-common.h @@ -17,12 +17,12 @@ #include "hw/virtio/virtio-scsi.h" #include "hw/virtio/vhost.h" #include "hw/fw-path-provider.h" +#include "qom/object.h" #define TYPE_VHOST_SCSI_COMMON "vhost-scsi-common" -#define VHOST_SCSI_COMMON(obj) \ - OBJECT_CHECK(VHostSCSICommon, (obj), TYPE_VHOST_SCSI_COMMON) +OBJECT_DECLARE_SIMPLE_TYPE(VHostSCSICommon, VHOST_SCSI_COMMON) -typedef struct VHostSCSICommon { +struct VHostSCSICommon { VirtIOSCSICommon parent_obj; Error *migration_blocker; @@ -35,7 +35,9 @@ typedef struct VHostSCSICommon { int lun; uint64_t host_features; bool migratable; -} VHostSCSICommon; + + struct vhost_inflight *inflight; +}; int vhost_scsi_common_start(VHostSCSICommon *vsc); void vhost_scsi_common_stop(VHostSCSICommon *vsc); diff --git a/include/hw/virtio/vhost-scsi.h b/include/hw/virtio/vhost-scsi.h index 23252153ff6f4c93c9927fdee01ee5cd3155b2ab..7dc2bdd69d64ddf281d3e32561dbf63dd21cd1c8 100644 --- a/include/hw/virtio/vhost-scsi.h +++ b/include/hw/virtio/vhost-scsi.h @@ -17,6 +17,7 @@ #include "hw/virtio/virtio-scsi.h" #include "hw/virtio/vhost.h" #include "hw/virtio/vhost-scsi-common.h" +#include "qom/object.h" enum vhost_scsi_vq_list { VHOST_SCSI_VQ_CONTROL = 0, @@ -25,11 +26,10 @@ enum vhost_scsi_vq_list { }; #define TYPE_VHOST_SCSI "vhost-scsi" -#define VHOST_SCSI(obj) \ - OBJECT_CHECK(VHostSCSI, (obj), TYPE_VHOST_SCSI) +OBJECT_DECLARE_SIMPLE_TYPE(VHostSCSI, VHOST_SCSI) -typedef struct VHostSCSI { +struct VHostSCSI { VHostSCSICommon parent_obj; -} VHostSCSI; +}; #endif diff --git a/include/hw/virtio/vhost-user-blk.h b/include/hw/virtio/vhost-user-blk.h index 34ad6f0c0e2d967dec2dde3ebac5b99b6f89b71b..7c91f15040eba772efcc9c3345fe145393391526 100644 --- a/include/hw/virtio/vhost-user-blk.h +++ b/include/hw/virtio/vhost-user-blk.h @@ -20,12 +20,14 @@ #include "chardev/char-fe.h" #include "hw/virtio/vhost.h" #include "hw/virtio/vhost-user.h" +#include "qom/object.h" #define TYPE_VHOST_USER_BLK "vhost-user-blk" -#define VHOST_USER_BLK(obj) \ - OBJECT_CHECK(VHostUserBlk, (obj), TYPE_VHOST_USER_BLK) +OBJECT_DECLARE_SIMPLE_TYPE(VHostUserBlk, VHOST_USER_BLK) -typedef struct VHostUserBlk { +#define VHOST_USER_BLK_AUTO_NUM_QUEUES UINT16_MAX + +struct VHostUserBlk { VirtIODevice parent_obj; CharBackend chardev; int32_t bootindex; @@ -38,7 +40,17 @@ typedef struct VHostUserBlk { VhostUserState vhost_user; struct vhost_virtqueue *vhost_vqs; VirtQueue **virtqs; + + /* + * There are at least two steps of initialization of the + * vhost-user device. The first is a "connect" step and + * second is a "start" step. Make a separation between + * those initialization phases by using two fields. + */ + /* vhost_user_blk_connect/vhost_user_blk_disconnect */ bool connected; -} VHostUserBlk; + /* vhost_user_blk_start/vhost_user_blk_stop */ + bool started_vu; +}; #endif diff --git a/include/hw/virtio/vhost-user-fs.h b/include/hw/virtio/vhost-user-fs.h index 6f3030d28822262398b73575b28f563636ee92e9..69857527710117c1f019e6318b0848bf9c12df45 100644 --- a/include/hw/virtio/vhost-user-fs.h +++ b/include/hw/virtio/vhost-user-fs.h @@ -18,10 +18,10 @@ #include "hw/virtio/vhost.h" #include "hw/virtio/vhost-user.h" #include "chardev/char-fe.h" +#include "qom/object.h" #define TYPE_VHOST_USER_FS "vhost-user-fs-device" -#define VHOST_USER_FS(obj) \ - OBJECT_CHECK(VHostUserFS, (obj), TYPE_VHOST_USER_FS) +OBJECT_DECLARE_SIMPLE_TYPE(VHostUserFS, VHOST_USER_FS) typedef struct { CharBackend chardev; @@ -30,7 +30,7 @@ typedef struct { uint16_t queue_size; } VHostUserFSConf; -typedef struct { +struct VHostUserFS { /*< private >*/ VirtIODevice parent; VHostUserFSConf conf; @@ -41,6 +41,6 @@ typedef struct { VirtQueue *hiprio_vq; /*< public >*/ -} VHostUserFS; +}; #endif /* _QEMU_VHOST_USER_FS_H */ diff --git a/include/hw/virtio/vhost-user-scsi.h b/include/hw/virtio/vhost-user-scsi.h index 99ab2f2cc437cb776340fe5baa13f13e85682a68..521b08e5599b0a5f2ce858349fe42c6a4016af34 100644 --- a/include/hw/virtio/vhost-user-scsi.h +++ b/include/hw/virtio/vhost-user-scsi.h @@ -21,14 +21,14 @@ #include "hw/virtio/vhost.h" #include "hw/virtio/vhost-user.h" #include "hw/virtio/vhost-scsi-common.h" +#include "qom/object.h" #define TYPE_VHOST_USER_SCSI "vhost-user-scsi" -#define VHOST_USER_SCSI(obj) \ - OBJECT_CHECK(VHostUserSCSI, (obj), TYPE_VHOST_USER_SCSI) +OBJECT_DECLARE_SIMPLE_TYPE(VHostUserSCSI, VHOST_USER_SCSI) -typedef struct VHostUserSCSI { +struct VHostUserSCSI { VHostSCSICommon parent_obj; VhostUserState vhost_user; -} VHostUserSCSI; +}; #endif /* VHOST_USER_SCSI_H */ diff --git a/include/hw/virtio/vhost-user-vsock.h b/include/hw/virtio/vhost-user-vsock.h new file mode 100644 index 0000000000000000000000000000000000000000..4cfd558245508204579f7778369d31e160d4231e --- /dev/null +++ b/include/hw/virtio/vhost-user-vsock.h @@ -0,0 +1,36 @@ +/* + * Vhost-user vsock virtio device + * + * Copyright 2020 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version. See the COPYING file in the + * top-level directory. + */ + +#ifndef _QEMU_VHOST_USER_VSOCK_H +#define _QEMU_VHOST_USER_VSOCK_H + +#include "hw/virtio/vhost-vsock-common.h" +#include "hw/virtio/vhost-user.h" +#include "standard-headers/linux/virtio_vsock.h" +#include "qom/object.h" + +#define TYPE_VHOST_USER_VSOCK "vhost-user-vsock-device" +OBJECT_DECLARE_SIMPLE_TYPE(VHostUserVSock, VHOST_USER_VSOCK) + +typedef struct { + CharBackend chardev; +} VHostUserVSockConf; + +struct VHostUserVSock { + /*< private >*/ + VHostVSockCommon parent; + VhostUserState vhost_user; + VHostUserVSockConf conf; + struct virtio_vsock_config vsockcfg; + + /*< public >*/ +}; + +#endif /* _QEMU_VHOST_USER_VSOCK_H */ diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h index 811e325f429516be4e9b77a4a35b842196a067a3..a9abca3288db817410246725dc834f15a4b37497 100644 --- a/include/hw/virtio/vhost-user.h +++ b/include/hw/virtio/vhost-user.h @@ -20,6 +20,7 @@ typedef struct VhostUserHostNotifier { typedef struct VhostUserState { CharBackend *chr; VhostUserHostNotifier notifier[VIRTIO_QUEUE_MAX]; + int memory_slots; } VhostUserState; bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp); diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h new file mode 100644 index 0000000000000000000000000000000000000000..9b81a409da89f1c67252aa2e816f088a24a7c367 --- /dev/null +++ b/include/hw/virtio/vhost-vdpa.h @@ -0,0 +1,27 @@ +/* + * vhost-vdpa.h + * + * Copyright(c) 2017-2018 Intel Corporation. + * Copyright(c) 2020 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef HW_VIRTIO_VHOST_VDPA_H +#define HW_VIRTIO_VHOST_VDPA_H + +#include "hw/virtio/virtio.h" + +typedef struct vhost_vdpa { + int device_fd; + uint32_t msg_type; + MemoryListener listener; + struct vhost_dev *dev; +} VhostVDPA; + +extern AddressSpace address_space_memory; +extern int vhost_vdpa_get_device_id(struct vhost_dev *dev, + uint32_t *device_id); +#endif diff --git a/include/hw/virtio/vhost-vsock-common.h b/include/hw/virtio/vhost-vsock-common.h new file mode 100644 index 0000000000000000000000000000000000000000..e412b5ee982a808610b4032e90f607bc2a9224c5 --- /dev/null +++ b/include/hw/virtio/vhost-vsock-common.h @@ -0,0 +1,47 @@ +/* + * Parent class for vhost-vsock devices + * + * Copyright 2015-2020 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version. See the COPYING file in the + * top-level directory. + */ + +#ifndef _QEMU_VHOST_VSOCK_COMMON_H +#define _QEMU_VHOST_VSOCK_COMMON_H + +#include "hw/virtio/virtio.h" +#include "hw/virtio/vhost.h" +#include "qom/object.h" + +#define TYPE_VHOST_VSOCK_COMMON "vhost-vsock-common" +OBJECT_DECLARE_SIMPLE_TYPE(VHostVSockCommon, VHOST_VSOCK_COMMON) + +enum { + VHOST_VSOCK_SAVEVM_VERSION = 0, + + VHOST_VSOCK_QUEUE_SIZE = 128, +}; + +struct VHostVSockCommon { + VirtIODevice parent; + + struct vhost_virtqueue vhost_vqs[2]; + struct vhost_dev vhost_dev; + + VirtQueue *event_vq; + VirtQueue *recv_vq; + VirtQueue *trans_vq; + + QEMUTimer *post_load_timer; +}; + +int vhost_vsock_common_start(VirtIODevice *vdev); +void vhost_vsock_common_stop(VirtIODevice *vdev); +int vhost_vsock_common_pre_save(void *opaque); +int vhost_vsock_common_post_load(void *opaque, int version_id); +void vhost_vsock_common_realize(VirtIODevice *vdev, const char *name); +void vhost_vsock_common_unrealize(VirtIODevice *vdev); + +#endif /* _QEMU_VHOST_VSOCK_COMMON_H */ diff --git a/include/hw/virtio/vhost-vsock.h b/include/hw/virtio/vhost-vsock.h index bc5a988ee556044e0a2ace4401001aaed494ed4b..84f4e727c70fa7a00b68487e22f2b0201d94b021 100644 --- a/include/hw/virtio/vhost-vsock.h +++ b/include/hw/virtio/vhost-vsock.h @@ -14,30 +14,23 @@ #ifndef QEMU_VHOST_VSOCK_H #define QEMU_VHOST_VSOCK_H -#include "hw/virtio/virtio.h" -#include "hw/virtio/vhost.h" +#include "hw/virtio/vhost-vsock-common.h" +#include "qom/object.h" #define TYPE_VHOST_VSOCK "vhost-vsock-device" -#define VHOST_VSOCK(obj) \ - OBJECT_CHECK(VHostVSock, (obj), TYPE_VHOST_VSOCK) +OBJECT_DECLARE_SIMPLE_TYPE(VHostVSock, VHOST_VSOCK) typedef struct { uint64_t guest_cid; char *vhostfd; } VHostVSockConf; -typedef struct { +struct VHostVSock { /*< private >*/ - VirtIODevice parent; + VHostVSockCommon parent; VHostVSockConf conf; - struct vhost_virtqueue vhost_vqs[2]; - struct vhost_dev vhost_dev; - VirtQueue *event_vq; - VirtQueue *recv_vq; - VirtQueue *trans_vq; - QEMUTimer *post_load_timer; /*< public >*/ -} VHostVSock; +}; #endif /* QEMU_VHOST_VSOCK_H */ diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 085450c6f84064447444f71e905644ddd19138dc..4a8bc75415f6bba597c195e10a471efd7c60cb66 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -79,6 +79,7 @@ struct vhost_dev { uint64_t backend_features; uint64_t protocol_features; uint64_t max_queues; + uint64_t backend_cap; bool started; bool log_enabled; uint64_t log_size; @@ -92,6 +93,13 @@ struct vhost_dev { const VhostDevConfigOps *config_ops; }; +struct vhost_net { + struct vhost_dev dev; + struct vhost_virtqueue vqs[2]; + int backend; + NetClientState *nc; +}; + int vhost_dev_init(struct vhost_dev *hdev, void *opaque, VhostBackendType backend_type, uint32_t busyloop_timeout); @@ -133,6 +141,7 @@ void vhost_dev_reset_inflight(struct vhost_inflight *inflight); void vhost_dev_free_inflight(struct vhost_inflight *inflight); void vhost_dev_save_inflight(struct vhost_inflight *inflight, QEMUFile *f); int vhost_dev_load_inflight(struct vhost_inflight *inflight, QEMUFile *f); +int vhost_dev_prepare_inflight(struct vhost_dev *hdev, VirtIODevice *vdev); int vhost_dev_set_inflight(struct vhost_dev *dev, struct vhost_inflight *inflight); int vhost_dev_get_inflight(struct vhost_dev *dev, uint16_t queue_size, diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h index d1c968d2376eee7f5567420581c4a9387133ef46..5139cf8ab68dd18cab16ca24656cd119e5b9fe19 100644 --- a/include/hw/virtio/virtio-balloon.h +++ b/include/hw/virtio/virtio-balloon.h @@ -18,12 +18,12 @@ #include "standard-headers/linux/virtio_balloon.h" #include "hw/virtio/virtio.h" #include "sysemu/iothread.h" +#include "qom/object.h" #define TYPE_VIRTIO_BALLOON "virtio-balloon-device" -#define VIRTIO_BALLOON(obj) \ - OBJECT_CHECK(VirtIOBalloon, (obj), TYPE_VIRTIO_BALLOON) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOBalloon, VIRTIO_BALLOON) -#define VIRTIO_BALLOON_FREE_PAGE_REPORT_CMD_ID_MIN 0x80000000 +#define VIRTIO_BALLOON_FREE_PAGE_HINT_CMD_ID_MIN 0x80000000 typedef struct virtio_balloon_stat VirtIOBalloonStat; @@ -33,20 +33,20 @@ typedef struct virtio_balloon_stat_modern { uint64_t val; } VirtIOBalloonStatModern; -enum virtio_balloon_free_page_report_status { - FREE_PAGE_REPORT_S_STOP = 0, - FREE_PAGE_REPORT_S_REQUESTED = 1, - FREE_PAGE_REPORT_S_START = 2, - FREE_PAGE_REPORT_S_DONE = 3, +enum virtio_balloon_free_page_hint_status { + FREE_PAGE_HINT_S_STOP = 0, + FREE_PAGE_HINT_S_REQUESTED = 1, + FREE_PAGE_HINT_S_START = 2, + FREE_PAGE_HINT_S_DONE = 3, }; -typedef struct VirtIOBalloon { +struct VirtIOBalloon { VirtIODevice parent_obj; - VirtQueue *ivq, *dvq, *svq, *free_page_vq; - uint32_t free_page_report_status; + VirtQueue *ivq, *dvq, *svq, *free_page_vq, *reporting_vq; + uint32_t free_page_hint_status; uint32_t num_pages; uint32_t actual; - uint32_t free_page_report_cmd_id; + uint32_t free_page_hint_cmd_id; uint64_t stats[VIRTIO_BALLOON_S_NR]; VirtQueueElement *stats_vq_elem; size_t stats_vq_offset; @@ -55,7 +55,7 @@ typedef struct VirtIOBalloon { QEMUBH *free_page_bh; /* * Lock to synchronize threads to access the free page reporting related - * fields (e.g. free_page_report_status). + * fields (e.g. free_page_hint_status). */ QemuMutex free_page_lock; QemuCond free_page_cond; @@ -64,12 +64,13 @@ typedef struct VirtIOBalloon { * stopped. */ bool block_iothread; - NotifierWithReturn free_page_report_notify; + NotifierWithReturn free_page_hint_notify; int64_t stats_last_update; int64_t stats_poll_interval; uint32_t host_features; bool qemu_4_0_config_size; -} VirtIOBalloon; + uint32_t poison_val; +}; #endif diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h index 1e62f869b2e079e02dd7abcb4e0b8398b3600c9d..214ab74822925d3525f9c58b64ba82ad00a3c7cc 100644 --- a/include/hw/virtio/virtio-blk.h +++ b/include/hw/virtio/virtio-blk.h @@ -19,10 +19,10 @@ #include "hw/block/block.h" #include "sysemu/iothread.h" #include "sysemu/block-backend.h" +#include "qom/object.h" #define TYPE_VIRTIO_BLK "virtio-blk-device" -#define VIRTIO_BLK(obj) \ - OBJECT_CHECK(VirtIOBlock, (obj), TYPE_VIRTIO_BLK) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOBlock, VIRTIO_BLK) /* This is the last element of the write scatter-gather list */ struct virtio_blk_inhdr @@ -30,6 +30,8 @@ struct virtio_blk_inhdr unsigned char status; }; +#define VIRTIO_BLK_AUTO_NUM_QUEUES UINT16_MAX + struct VirtIOBlkConf { BlockConf conf; @@ -47,7 +49,7 @@ struct VirtIOBlkConf struct VirtIOBlockDataPlane; struct VirtIOBlockReq; -typedef struct VirtIOBlock { +struct VirtIOBlock { VirtIODevice parent_obj; BlockBackend *blk; void *rq; @@ -61,13 +63,15 @@ typedef struct VirtIOBlock { struct VirtIOBlockDataPlane *dataplane; uint64_t host_features; size_t config_size; -} VirtIOBlock; +}; typedef struct VirtIOBlockReq { VirtQueueElement elem; int64_t sector_num; VirtIOBlock *dev; VirtQueue *vq; + IOVDiscardUndo inhdr_undo; + IOVDiscardUndo outhdr_undo; struct virtio_blk_inhdr *in; struct virtio_blk_outhdr out; QEMUIOVector qiov; @@ -86,5 +90,6 @@ typedef struct MultiReqBuffer { } MultiReqBuffer; bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq); +void virtio_blk_process_queued_requests(VirtIOBlock *s, bool is_bh); #endif diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h index 38c9399cd45491618e0a0e3e8c65c14f2adf92a1..ef8abe49c5a160a078a50181cf8f82ff9af79858 100644 --- a/include/hw/virtio/virtio-bus.h +++ b/include/hw/virtio/virtio-bus.h @@ -27,17 +27,16 @@ #include "hw/qdev-core.h" #include "hw/virtio/virtio.h" +#include "qom/object.h" #define TYPE_VIRTIO_BUS "virtio-bus" -#define VIRTIO_BUS_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtioBusClass, obj, TYPE_VIRTIO_BUS) -#define VIRTIO_BUS_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtioBusClass, klass, TYPE_VIRTIO_BUS) -#define VIRTIO_BUS(obj) OBJECT_CHECK(VirtioBusState, (obj), TYPE_VIRTIO_BUS) - +typedef struct VirtioBusClass VirtioBusClass; typedef struct VirtioBusState VirtioBusState; +DECLARE_OBJ_CHECKERS(VirtioBusState, VirtioBusClass, + VIRTIO_BUS, TYPE_VIRTIO_BUS) + -typedef struct VirtioBusClass { +struct VirtioBusClass { /* This is what a VirtioBus must implement */ BusClass parent; void (*notify)(DeviceState *d, uint16_t vector); @@ -83,6 +82,10 @@ typedef struct VirtioBusClass { */ int (*ioeventfd_assign)(DeviceState *d, EventNotifier *notifier, int n, bool assign); + /* + * Whether queue number n is enabled. + */ + bool (*queue_enabled)(DeviceState *d, int n); /* * Does the transport have variable vring alignment? * (ie can it ever call virtio_queue_set_align()?) @@ -90,7 +93,7 @@ typedef struct VirtioBusClass { */ bool has_variable_vring_alignment; AddressSpace *(*get_dma_as)(DeviceState *d); -} VirtioBusClass; +}; struct VirtioBusState { BusState parent_obj; diff --git a/include/hw/virtio/virtio-crypto.h b/include/hw/virtio/virtio-crypto.h index ffe2391ece3cb1a6dfb3a2c87ea2ce39e774a2c9..a2228d7b2eb3889742c35982681f388cb2634f0b 100644 --- a/include/hw/virtio/virtio-crypto.h +++ b/include/hw/virtio/virtio-crypto.h @@ -18,6 +18,7 @@ #include "hw/virtio/virtio.h" #include "sysemu/iothread.h" #include "sysemu/cryptodev.h" +#include "qom/object.h" #define DEBUG_VIRTIO_CRYPTO 0 @@ -31,8 +32,7 @@ do { \ #define TYPE_VIRTIO_CRYPTO "virtio-crypto-device" -#define VIRTIO_CRYPTO(obj) \ - OBJECT_CHECK(VirtIOCrypto, (obj), TYPE_VIRTIO_CRYPTO) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOCrypto, VIRTIO_CRYPTO) #define VIRTIO_CRYPTO_GET_PARENT_CLASS(obj) \ OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_CRYPTO) @@ -82,7 +82,7 @@ typedef struct VirtIOCryptoQueue { struct VirtIOCrypto *vcrypto; } VirtIOCryptoQueue; -typedef struct VirtIOCrypto { +struct VirtIOCrypto { VirtIODevice parent_obj; VirtQueue *ctrl_vq; @@ -97,6 +97,6 @@ typedef struct VirtIOCrypto { uint32_t curr_queues; size_t config_size; uint8_t vhost_started; -} VirtIOCrypto; +}; #endif /* QEMU_VIRTIO_CRYPTO_H */ diff --git a/include/hw/virtio/virtio-gpu-pci.h b/include/hw/virtio/virtio-gpu-pci.h index 2f69b5a9ccec995932d15fd80da087bd1a03bf67..225cbbc2e459ceee111d20e28dd3956dc5af93a2 100644 --- a/include/hw/virtio/virtio-gpu-pci.h +++ b/include/hw/virtio/virtio-gpu-pci.h @@ -16,15 +16,14 @@ #include "hw/virtio/virtio-pci.h" #include "hw/virtio/virtio-gpu.h" +#include "qom/object.h" -typedef struct VirtIOGPUPCIBase VirtIOGPUPCIBase; /* * virtio-gpu-pci-base: This extends VirtioPCIProxy. */ #define TYPE_VIRTIO_GPU_PCI_BASE "virtio-gpu-pci-base" -#define VIRTIO_GPU_PCI_BASE(obj) \ - OBJECT_CHECK(VirtIOGPUPCIBase, (obj), TYPE_VIRTIO_GPU_PCI_BASE) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOGPUPCIBase, VIRTIO_GPU_PCI_BASE) struct VirtIOGPUPCIBase { VirtIOPCIProxy parent_obj; diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index 6dd57f2025ecca2103db03730916422a389a9ffe..1aed7275c82483adc8494892433dfa8409df68aa 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -22,20 +22,17 @@ #include "sysemu/vhost-user-backend.h" #include "standard-headers/linux/virtio_gpu.h" +#include "qom/object.h" #define TYPE_VIRTIO_GPU_BASE "virtio-gpu-base" -#define VIRTIO_GPU_BASE(obj) \ - OBJECT_CHECK(VirtIOGPUBase, (obj), TYPE_VIRTIO_GPU_BASE) -#define VIRTIO_GPU_BASE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtIOGPUBaseClass, obj, TYPE_VIRTIO_GPU_BASE) -#define VIRTIO_GPU_BASE_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtIOGPUBaseClass, klass, TYPE_VIRTIO_GPU_BASE) +OBJECT_DECLARE_TYPE(VirtIOGPUBase, VirtIOGPUBaseClass, + VIRTIO_GPU_BASE) #define TYPE_VIRTIO_GPU "virtio-gpu-device" -#define VIRTIO_GPU(obj) \ - OBJECT_CHECK(VirtIOGPU, (obj), TYPE_VIRTIO_GPU) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOGPU, VIRTIO_GPU) #define TYPE_VHOST_USER_GPU "vhost-user-gpu" +OBJECT_DECLARE_SIMPLE_TYPE(VhostUserGPU, VHOST_USER_GPU) #define VIRTIO_ID_GPU 16 @@ -65,6 +62,7 @@ struct virtio_gpu_scanout { }; struct virtio_gpu_requested_state { + uint16_t width_mm, height_mm; uint32_t width, height; int x, y; }; @@ -98,13 +96,14 @@ struct virtio_gpu_ctrl_command { QTAILQ_ENTRY(virtio_gpu_ctrl_command) next; }; -typedef struct VirtIOGPUBase { +struct VirtIOGPUBase { VirtIODevice parent_obj; Error *migration_blocker; struct virtio_gpu_base_conf conf; struct virtio_gpu_config virtio_config; + const GraphicHwOps *hw_ops; bool use_virgl_renderer; int renderer_blocked; @@ -114,13 +113,13 @@ typedef struct VirtIOGPUBase { int enabled_output_bitmask; struct virtio_gpu_requested_state req_state[VIRTIO_GPU_MAX_SCANOUTS]; -} VirtIOGPUBase; +}; -typedef struct VirtIOGPUBaseClass { +struct VirtIOGPUBaseClass { VirtioDeviceClass parent; void (*gl_unblock)(VirtIOGPUBase *g); -} VirtIOGPUBaseClass; +}; #define VIRTIO_GPU_BASE_PROPERTIES(_state, _conf) \ DEFINE_PROP_UINT32("max_outputs", _state, _conf.max_outputs, 1), \ @@ -129,7 +128,7 @@ typedef struct VirtIOGPUBaseClass { DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1024), \ DEFINE_PROP_UINT32("yres", _state, _conf.yres, 768) -typedef struct VirtIOGPU { +struct VirtIOGPU { VirtIOGPUBase parent_obj; uint64_t conf_max_hostmem; @@ -158,9 +157,9 @@ typedef struct VirtIOGPU { uint32_t req_3d; uint32_t bytes_3d; } stats; -} VirtIOGPU; +}; -typedef struct VhostUserGPU { +struct VhostUserGPU { VirtIOGPUBase parent_obj; VhostUserBackend *vhost; @@ -168,9 +167,7 @@ typedef struct VhostUserGPU { CharBackend vhost_chr; QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; bool backend_blocked; -} VhostUserGPU; - -extern const GraphicHwOps virtio_gpu_ops; +}; #define VIRTIO_GPU_FILL_CMD(out) do { \ size_t s; \ diff --git a/include/hw/virtio/virtio-input.h b/include/hw/virtio/virtio-input.h index 4fca03e7969ee1e78588a8c53605cc80f9f0ba13..f2da63d309ae1cbac400bda482bba2a2dc2e8560 100644 --- a/include/hw/virtio/virtio-input.h +++ b/include/hw/virtio/virtio-input.h @@ -9,6 +9,7 @@ #include "standard-headers/linux/virtio_ids.h" #include "standard-headers/linux/virtio_input.h" +#include "qom/object.h" typedef struct virtio_input_absinfo virtio_input_absinfo; typedef struct virtio_input_config virtio_input_config; @@ -18,43 +19,31 @@ typedef struct virtio_input_event virtio_input_event; /* qemu internals */ #define TYPE_VIRTIO_INPUT "virtio-input-device" -#define VIRTIO_INPUT(obj) \ - OBJECT_CHECK(VirtIOInput, (obj), TYPE_VIRTIO_INPUT) +OBJECT_DECLARE_TYPE(VirtIOInput, VirtIOInputClass, + VIRTIO_INPUT) #define VIRTIO_INPUT_GET_PARENT_CLASS(obj) \ OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT) -#define VIRTIO_INPUT_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtIOInputClass, obj, TYPE_VIRTIO_INPUT) -#define VIRTIO_INPUT_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtIOInputClass, klass, TYPE_VIRTIO_INPUT) #define TYPE_VIRTIO_INPUT_HID "virtio-input-hid-device" #define TYPE_VIRTIO_KEYBOARD "virtio-keyboard-device" #define TYPE_VIRTIO_MOUSE "virtio-mouse-device" #define TYPE_VIRTIO_TABLET "virtio-tablet-device" -#define VIRTIO_INPUT_HID(obj) \ - OBJECT_CHECK(VirtIOInputHID, (obj), TYPE_VIRTIO_INPUT_HID) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOInputHID, VIRTIO_INPUT_HID) #define VIRTIO_INPUT_HID_GET_PARENT_CLASS(obj) \ OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT_HID) #define TYPE_VIRTIO_INPUT_HOST "virtio-input-host-device" -#define VIRTIO_INPUT_HOST(obj) \ - OBJECT_CHECK(VirtIOInputHost, (obj), TYPE_VIRTIO_INPUT_HOST) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOInputHost, VIRTIO_INPUT_HOST) #define VIRTIO_INPUT_HOST_GET_PARENT_CLASS(obj) \ OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT_HOST) #define TYPE_VHOST_USER_INPUT "vhost-user-input" -#define VHOST_USER_INPUT(obj) \ - OBJECT_CHECK(VHostUserInput, (obj), TYPE_VHOST_USER_INPUT) +OBJECT_DECLARE_SIMPLE_TYPE(VHostUserInput, VHOST_USER_INPUT) #define VHOST_USER_INPUT_GET_PARENT_CLASS(obj) \ OBJECT_GET_PARENT_CLASS(obj, TYPE_VHOST_USER_INPUT) -typedef struct VirtIOInput VirtIOInput; -typedef struct VirtIOInputClass VirtIOInputClass; typedef struct VirtIOInputConfig VirtIOInputConfig; -typedef struct VirtIOInputHID VirtIOInputHID; -typedef struct VirtIOInputHost VirtIOInputHost; -typedef struct VHostUserInput VHostUserInput; struct VirtIOInputConfig { virtio_input_config config; diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-iommu.h index e653004d7ca21a43c9769b51e50aaaa88175741f..273e35c04bcbce9148ee7e9d598b1a59de6e5cea 100644 --- a/include/hw/virtio/virtio-iommu.h +++ b/include/hw/virtio/virtio-iommu.h @@ -23,11 +23,11 @@ #include "standard-headers/linux/virtio_iommu.h" #include "hw/virtio/virtio.h" #include "hw/pci/pci.h" +#include "qom/object.h" #define TYPE_VIRTIO_IOMMU "virtio-iommu-device" #define TYPE_VIRTIO_IOMMU_PCI "virtio-iommu-device-base" -#define VIRTIO_IOMMU(obj) \ - OBJECT_CHECK(VirtIOIOMMU, (obj), TYPE_VIRTIO_IOMMU) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOIOMMU, VIRTIO_IOMMU) #define TYPE_VIRTIO_IOMMU_MEMORY_REGION "virtio-iommu-memory-region" @@ -44,7 +44,7 @@ typedef struct IOMMUPciBus { IOMMUDevice *pbdev[]; /* Parent array is sparse, so dynamically alloc */ } IOMMUPciBus; -typedef struct VirtIOIOMMU { +struct VirtIOIOMMU { VirtIODevice parent_obj; VirtQueue *req_vq; VirtQueue *event_vq; @@ -53,9 +53,11 @@ typedef struct VirtIOIOMMU { GHashTable *as_by_busptr; IOMMUPciBus *iommu_pcibus_by_bus_num[PCI_BUS_MAX]; PCIBus *primary_bus; + ReservedRegion *reserved_regions; + uint32_t nb_reserved_regions; GTree *domains; QemuMutex mutex; GTree *endpoints; -} VirtIOIOMMU; +}; #endif diff --git a/include/hw/virtio/virtio-mem.h b/include/hw/virtio/virtio-mem.h new file mode 100644 index 0000000000000000000000000000000000000000..4eeb82d5ddb1a395d72c14fffced2e39b0011ba8 --- /dev/null +++ b/include/hw/virtio/virtio-mem.h @@ -0,0 +1,83 @@ +/* + * Virtio MEM device + * + * Copyright (C) 2020 Red Hat, Inc. + * + * Authors: + * David Hildenbrand + * + * This work is licensed under the terms of the GNU GPL, version 2. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_VIRTIO_MEM_H +#define HW_VIRTIO_MEM_H + +#include "standard-headers/linux/virtio_mem.h" +#include "hw/virtio/virtio.h" +#include "qapi/qapi-types-misc.h" +#include "sysemu/hostmem.h" +#include "qom/object.h" + +#define TYPE_VIRTIO_MEM "virtio-mem" + +OBJECT_DECLARE_TYPE(VirtIOMEM, VirtIOMEMClass, + VIRTIO_MEM) + +#define VIRTIO_MEM_MEMDEV_PROP "memdev" +#define VIRTIO_MEM_NODE_PROP "node" +#define VIRTIO_MEM_SIZE_PROP "size" +#define VIRTIO_MEM_REQUESTED_SIZE_PROP "requested-size" +#define VIRTIO_MEM_BLOCK_SIZE_PROP "block-size" +#define VIRTIO_MEM_ADDR_PROP "memaddr" + +struct VirtIOMEM { + VirtIODevice parent_obj; + + /* guest -> host request queue */ + VirtQueue *vq; + + /* bitmap used to track unplugged memory */ + int32_t bitmap_size; + unsigned long *bitmap; + + /* assigned memory backend and memory region */ + HostMemoryBackend *memdev; + + /* NUMA node */ + uint32_t node; + + /* assigned address of the region in guest physical memory */ + uint64_t addr; + + /* usable region size (<= region_size) */ + uint64_t usable_region_size; + + /* actual size (how much the guest plugged) */ + uint64_t size; + + /* requested size */ + uint64_t requested_size; + + /* block size and alignment */ + uint64_t block_size; + + /* notifiers to notify when "size" changes */ + NotifierList size_change_notifiers; + + /* don't migrate unplugged memory */ + NotifierWithReturn precopy_notifier; +}; + +struct VirtIOMEMClass { + /* private */ + VirtIODevice parent; + + /* public */ + void (*fill_device_info)(const VirtIOMEM *vmen, VirtioMEMDeviceInfo *vi); + MemoryRegion *(*get_memory_region)(VirtIOMEM *vmem, Error **errp); + void (*add_size_change_notifier)(VirtIOMEM *vmem, Notifier *notifier); + void (*remove_size_change_notifier)(VirtIOMEM *vmem, Notifier *notifier); +}; + +#endif diff --git a/include/hw/virtio/virtio-mmio.h b/include/hw/virtio/virtio-mmio.h index 7dbfd03dcff75e948f2ef0ad6b288a54a0ee999d..d4c4c386ab05b03a5826fbc6da99ddd23dc48121 100644 --- a/include/hw/virtio/virtio-mmio.h +++ b/include/hw/virtio/virtio-mmio.h @@ -23,21 +23,18 @@ #define HW_VIRTIO_MMIO_H #include "hw/virtio/virtio-bus.h" +#include "qom/object.h" /* QOM macros */ /* virtio-mmio-bus */ #define TYPE_VIRTIO_MMIO_BUS "virtio-mmio-bus" -#define VIRTIO_MMIO_BUS(obj) \ - OBJECT_CHECK(VirtioBusState, (obj), TYPE_VIRTIO_MMIO_BUS) -#define VIRTIO_MMIO_BUS_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtioBusClass, (obj), TYPE_VIRTIO_MMIO_BUS) -#define VIRTIO_MMIO_BUS_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtioBusClass, (klass), TYPE_VIRTIO_MMIO_BUS) +/* This is reusing the VirtioBusState typedef from TYPE_VIRTIO_BUS */ +DECLARE_OBJ_CHECKERS(VirtioBusState, VirtioBusClass, + VIRTIO_MMIO_BUS, TYPE_VIRTIO_MMIO_BUS) /* virtio-mmio */ #define TYPE_VIRTIO_MMIO "virtio-mmio" -#define VIRTIO_MMIO(obj) \ - OBJECT_CHECK(VirtIOMMIOProxy, (obj), TYPE_VIRTIO_MMIO) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOMMIOProxy, VIRTIO_MMIO) #define VIRT_MAGIC 0x74726976 /* 'virt' */ #define VIRT_VERSION 2 @@ -52,7 +49,7 @@ typedef struct VirtIOMMIOQueue { uint32_t used[2]; } VirtIOMMIOQueue; -typedef struct { +struct VirtIOMMIOProxy { /* Generic */ SysBusDevice parent_obj; MemoryRegion iomem; @@ -68,6 +65,6 @@ typedef struct { /* Fields only used for non-legacy (v2) devices */ uint32_t guest_features[2]; VirtIOMMIOQueue vqs[VIRTIO_QUEUE_MAX]; -} VirtIOMMIOProxy; +}; #endif diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index 96c68d4a927cf42185dfda1424246ce9fb14e837..f4852ac27be20a04960943072b0e9cca23c67fe7 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -19,10 +19,10 @@ #include "hw/virtio/virtio.h" #include "net/announce.h" #include "qemu/option_int.h" +#include "qom/object.h" #define TYPE_VIRTIO_NET "virtio-net-device" -#define VIRTIO_NET(obj) \ - OBJECT_CHECK(VirtIONet, (obj), TYPE_VIRTIO_NET) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIONet, VIRTIO_NET) #define TX_TIMER_INTERVAL 150000 /* 150 us */ @@ -109,7 +109,6 @@ typedef struct VirtioNetRscSeg { NetClientState *nc; } VirtioNetRscSeg; -typedef struct VirtIONet VirtIONet; /* Chain is divided by protocol(ipv4/v6) and NetClientInfo */ typedef struct VirtioNetRscChain { @@ -126,6 +125,20 @@ typedef struct VirtioNetRscChain { /* Maximum packet size we can receive from tap device: header + 64k */ #define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 * KiB)) +#define VIRTIO_NET_RSS_MAX_KEY_SIZE 40 +#define VIRTIO_NET_RSS_MAX_TABLE_LEN 128 + +typedef struct VirtioNetRssData { + bool enabled; + bool redirect; + bool populate_hash; + uint32_t hash_types; + uint8_t key[VIRTIO_NET_RSS_MAX_KEY_SIZE]; + uint16_t indirections_len; + uint16_t *indirections_table; + uint16_t default_queue; +} VirtioNetRssData; + typedef struct VirtIONetQueue { VirtQueue *rx_vq; VirtQueue *tx_vq; @@ -199,6 +212,8 @@ struct VirtIONet { bool failover; DeviceListener primary_listener; Notifier migration_state; + VirtioNetRssData rss_data; + struct NetRxPkt *rx_pkt; }; void virtio_net_set_netclient_name(VirtIONet *n, const char *name, diff --git a/include/hw/virtio/virtio-pmem.h b/include/hw/virtio/virtio-pmem.h index 33f1999320a5d88c12d7baa1cb423bce4d25a1d0..fc4fd1f7fe8745678d15f3f7116e7e6b92381aa2 100644 --- a/include/hw/virtio/virtio-pmem.h +++ b/include/hw/virtio/virtio-pmem.h @@ -15,35 +15,32 @@ #define HW_VIRTIO_PMEM_H #include "hw/virtio/virtio.h" -#include "qapi/qapi-types-misc.h" +#include "qapi/qapi-types-machine.h" +#include "qom/object.h" #define TYPE_VIRTIO_PMEM "virtio-pmem" -#define VIRTIO_PMEM(obj) \ - OBJECT_CHECK(VirtIOPMEM, (obj), TYPE_VIRTIO_PMEM) -#define VIRTIO_PMEM_CLASS(oc) \ - OBJECT_CLASS_CHECK(VirtIOPMEMClass, (oc), TYPE_VIRTIO_PMEM) -#define VIRTIO_PMEM_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtIOPMEMClass, (obj), TYPE_VIRTIO_PMEM) +OBJECT_DECLARE_TYPE(VirtIOPMEM, VirtIOPMEMClass, + VIRTIO_PMEM) #define VIRTIO_PMEM_ADDR_PROP "memaddr" #define VIRTIO_PMEM_MEMDEV_PROP "memdev" -typedef struct VirtIOPMEM { +struct VirtIOPMEM { VirtIODevice parent_obj; VirtQueue *rq_vq; uint64_t start; HostMemoryBackend *memdev; -} VirtIOPMEM; +}; -typedef struct VirtIOPMEMClass { +struct VirtIOPMEMClass { /* private */ VirtIODevice parent; /* public */ void (*fill_device_info)(const VirtIOPMEM *pmem, VirtioPMEMDeviceInfo *vi); MemoryRegion *(*get_memory_region)(VirtIOPMEM *pmem, Error **errp); -} VirtIOPMEMClass; +}; #endif diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h index bd05d734b87d88153ca2895dfec5f3d152cb99ff..82734255d993841ca18acd17cb465aa17f68c6e7 100644 --- a/include/hw/virtio/virtio-rng.h +++ b/include/hw/virtio/virtio-rng.h @@ -15,10 +15,10 @@ #include "hw/virtio/virtio.h" #include "sysemu/rng.h" #include "standard-headers/linux/virtio_rng.h" +#include "qom/object.h" #define TYPE_VIRTIO_RNG "virtio-rng-device" -#define VIRTIO_RNG(obj) \ - OBJECT_CHECK(VirtIORNG, (obj), TYPE_VIRTIO_RNG) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIORNG, VIRTIO_RNG) #define VIRTIO_RNG_GET_PARENT_CLASS(obj) \ OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_RNG) @@ -28,7 +28,7 @@ struct VirtIORNGConf { uint32_t period_ms; }; -typedef struct VirtIORNG { +struct VirtIORNG { VirtIODevice parent_obj; /* Only one vq - guest puts buffer(s) on it when it needs entropy */ @@ -46,6 +46,6 @@ typedef struct VirtIORNG { bool activate_timer; VMChangeStateEntry *vmstate; -} VirtIORNG; +}; #endif diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h index 24e768909dd40daf8a1d1b38b3b030daca19b80e..543681bc1838503cee4ef406b06535768a163b2a 100644 --- a/include/hw/virtio/virtio-scsi.h +++ b/include/hw/virtio/virtio-scsi.h @@ -13,6 +13,7 @@ #ifndef QEMU_VIRTIO_SCSI_H #define QEMU_VIRTIO_SCSI_H +#include "qom/object.h" /* Override CDB/sense data size: they are dynamic (guest controlled) in QEMU */ #define VIRTIO_SCSI_CDB_SIZE 0 @@ -25,17 +26,20 @@ #include "sysemu/iothread.h" #define TYPE_VIRTIO_SCSI_COMMON "virtio-scsi-common" -#define VIRTIO_SCSI_COMMON(obj) \ - OBJECT_CHECK(VirtIOSCSICommon, (obj), TYPE_VIRTIO_SCSI_COMMON) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOSCSICommon, VIRTIO_SCSI_COMMON) #define TYPE_VIRTIO_SCSI "virtio-scsi-device" -#define VIRTIO_SCSI(obj) \ - OBJECT_CHECK(VirtIOSCSI, (obj), TYPE_VIRTIO_SCSI) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOSCSI, VIRTIO_SCSI) #define VIRTIO_SCSI_MAX_CHANNEL 0 #define VIRTIO_SCSI_MAX_TARGET 255 #define VIRTIO_SCSI_MAX_LUN 16383 +/* Number of virtqueues that are always present */ +#define VIRTIO_SCSI_VQ_NUM_FIXED 2 + +#define VIRTIO_SCSI_AUTO_NUM_QUEUES UINT32_MAX + typedef struct virtio_scsi_cmd_req VirtIOSCSICmdReq; typedef struct virtio_scsi_cmd_resp VirtIOSCSICmdResp; typedef struct virtio_scsi_ctrl_tmf_req VirtIOSCSICtrlTMFReq; @@ -62,7 +66,7 @@ struct VirtIOSCSIConf { struct VirtIOSCSI; -typedef struct VirtIOSCSICommon { +struct VirtIOSCSICommon { VirtIODevice parent_obj; VirtIOSCSIConf conf; @@ -71,9 +75,9 @@ typedef struct VirtIOSCSICommon { VirtQueue *ctrl_vq; VirtQueue *event_vq; VirtQueue **cmd_vqs; -} VirtIOSCSICommon; +}; -typedef struct VirtIOSCSI { +struct VirtIOSCSI { VirtIOSCSICommon parent_obj; SCSIBus bus; @@ -88,7 +92,7 @@ typedef struct VirtIOSCSI { bool dataplane_stopping; bool dataplane_fenced; uint32_t host_features; -} VirtIOSCSI; +}; typedef struct VirtIOSCSIReq { /* Note: diff --git a/include/hw/virtio/virtio-serial.h b/include/hw/virtio/virtio-serial.h index ed3e916b68aafea569a7650ef01175710f780b1f..d87c62eab7a270809daf47f932a73dd1fa3d5a6e 100644 --- a/include/hw/virtio/virtio-serial.h +++ b/include/hw/virtio/virtio-serial.h @@ -18,6 +18,7 @@ #include "standard-headers/linux/virtio_console.h" #include "hw/virtio/virtio.h" +#include "qom/object.h" struct virtio_serial_conf { /* Max. number of ports we can have for a virtio-serial device */ @@ -25,18 +26,16 @@ struct virtio_serial_conf { }; #define TYPE_VIRTIO_SERIAL_PORT "virtio-serial-port" -#define VIRTIO_SERIAL_PORT(obj) \ - OBJECT_CHECK(VirtIOSerialPort, (obj), TYPE_VIRTIO_SERIAL_PORT) -#define VIRTIO_SERIAL_PORT_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtIOSerialPortClass, (klass), TYPE_VIRTIO_SERIAL_PORT) -#define VIRTIO_SERIAL_PORT_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtIOSerialPortClass, (obj), TYPE_VIRTIO_SERIAL_PORT) +OBJECT_DECLARE_TYPE(VirtIOSerialPort, VirtIOSerialPortClass, + VIRTIO_SERIAL_PORT) typedef struct VirtIOSerial VirtIOSerial; -typedef struct VirtIOSerialBus VirtIOSerialBus; -typedef struct VirtIOSerialPort VirtIOSerialPort; -typedef struct VirtIOSerialPortClass { +#define TYPE_VIRTIO_SERIAL_BUS "virtio-serial-bus" +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOSerialBus, VIRTIO_SERIAL_BUS) + + +struct VirtIOSerialPortClass { DeviceClass parent_class; /* Is this a device that binds with hvc in the guest? */ @@ -81,7 +80,7 @@ typedef struct VirtIOSerialPortClass { */ ssize_t (*have_data)(VirtIOSerialPort *port, const uint8_t *buf, ssize_t len); -} VirtIOSerialPortClass; +}; /* * This is the state that's shared between all the ports. Some of the @@ -223,7 +222,6 @@ size_t virtio_serial_guest_ready(VirtIOSerialPort *port); void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle); #define TYPE_VIRTIO_SERIAL "virtio-serial-device" -#define VIRTIO_SERIAL(obj) \ - OBJECT_CHECK(VirtIOSerial, (obj), TYPE_VIRTIO_SERIAL) +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOSerial, VIRTIO_SERIAL) #endif diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index b69d517496358d4dcba30eeb42c721e866798051..b7ece7a6a891adcbadba401a5207d60f843b8231 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -21,6 +21,7 @@ #include "qemu/event_notifier.h" #include "standard-headers/linux/virtio_config.h" #include "standard-headers/linux/virtio_ring.h" +#include "qom/object.h" /* A guest should never accept this. It implies negotiation is broken. */ #define VIRTIO_F_BAD_FEATURE 30 @@ -67,12 +68,7 @@ typedef struct VirtQueueElement #define VIRTIO_NO_VECTOR 0xffff #define TYPE_VIRTIO_DEVICE "virtio-device" -#define VIRTIO_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtioDeviceClass, obj, TYPE_VIRTIO_DEVICE) -#define VIRTIO_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtioDeviceClass, klass, TYPE_VIRTIO_DEVICE) -#define VIRTIO_DEVICE(obj) \ - OBJECT_CHECK(VirtIODevice, (obj), TYPE_VIRTIO_DEVICE) +OBJECT_DECLARE_TYPE(VirtIODevice, VirtioDeviceClass, VIRTIO_DEVICE) enum virtio_device_endian { VIRTIO_DEVICE_ENDIAN_UNKNOWN, @@ -105,6 +101,7 @@ struct VirtIODevice bool use_started; bool started; bool start_on_kick; /* when virtio 1.0 feature has not been negotiated */ + bool disable_legacy_check; VMChangeStateEntry *vmstate; char *bus_name; uint8_t device_endian; @@ -113,7 +110,7 @@ struct VirtIODevice QLIST_HEAD(, VirtQueue) *vector_queues; }; -typedef struct VirtioDeviceClass { +struct VirtioDeviceClass { /*< private >*/ DeviceClass parent; /*< public >*/ @@ -163,7 +160,7 @@ typedef struct VirtioDeviceClass { int (*post_load)(VirtIODevice *vdev); const VMStateDescription *vmsd; bool (*primary_unplug_pending)(void *opaque); -} VirtioDeviceClass; +}; void virtio_instance_init_common(Object *proxy_obj, void *data, size_t vdev_size, const char *vdev_name); @@ -295,6 +292,7 @@ typedef struct VirtIORNGConf VirtIORNGConf; VIRTIO_F_RING_PACKED, false) hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n); +bool virtio_queue_enabled_legacy(VirtIODevice *vdev, int n); bool virtio_queue_enabled(VirtIODevice *vdev, int n); hwaddr virtio_queue_get_avail_addr(VirtIODevice *vdev, int n); hwaddr virtio_queue_get_used_addr(VirtIODevice *vdev, int n); @@ -396,4 +394,7 @@ static inline bool virtio_device_disabled(VirtIODevice *vdev) return unlikely(vdev->disabled || vdev->broken); } +bool virtio_legacy_allowed(VirtIODevice *vdev); +bool virtio_legacy_check_disabled(VirtIODevice *vdev); + #endif diff --git a/include/hw/vmstate-if.h b/include/hw/vmstate-if.h index 8ff7f0f2929813f8b7cda82f6e4b877f82757b77..52df571d17abbe8734ebc9be320ce1da4c7a1c2d 100644 --- a/include/hw/vmstate-if.h +++ b/include/hw/vmstate-if.h @@ -13,20 +13,19 @@ #define TYPE_VMSTATE_IF "vmstate-if" -#define VMSTATE_IF_CLASS(klass) \ - OBJECT_CLASS_CHECK(VMStateIfClass, (klass), TYPE_VMSTATE_IF) -#define VMSTATE_IF_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VMStateIfClass, (obj), TYPE_VMSTATE_IF) +typedef struct VMStateIfClass VMStateIfClass; +DECLARE_CLASS_CHECKERS(VMStateIfClass, VMSTATE_IF, + TYPE_VMSTATE_IF) #define VMSTATE_IF(obj) \ INTERFACE_CHECK(VMStateIf, (obj), TYPE_VMSTATE_IF) typedef struct VMStateIf VMStateIf; -typedef struct VMStateIfClass { +struct VMStateIfClass { InterfaceClass parent_class; char * (*get_id)(VMStateIf *obj); -} VMStateIfClass; +}; static inline char *vmstate_if_get_id(VMStateIf *vmif) { diff --git a/include/hw/watchdog/cmsdk-apb-watchdog.h b/include/hw/watchdog/cmsdk-apb-watchdog.h index 6ae9531370f8a7b44c31bb4e49c8a59c690ab0ab..3da0d43e355b65df6d0397c830d9543602e02241 100644 --- a/include/hw/watchdog/cmsdk-apb-watchdog.h +++ b/include/hw/watchdog/cmsdk-apb-watchdog.h @@ -33,10 +33,10 @@ #include "hw/sysbus.h" #include "hw/ptimer.h" +#include "qom/object.h" #define TYPE_CMSDK_APB_WATCHDOG "cmsdk-apb-watchdog" -#define CMSDK_APB_WATCHDOG(obj) OBJECT_CHECK(CMSDKAPBWatchdog, (obj), \ - TYPE_CMSDK_APB_WATCHDOG) +OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBWatchdog, CMSDK_APB_WATCHDOG) /* * This shares the same struct (and cast macro) as the base @@ -44,7 +44,7 @@ */ #define TYPE_LUMINARY_WATCHDOG "luminary-watchdog" -typedef struct CMSDKAPBWatchdog { +struct CMSDKAPBWatchdog { /*< private >*/ SysBusDevice parent_obj; @@ -62,6 +62,6 @@ typedef struct CMSDKAPBWatchdog { uint32_t itop; uint32_t resetstatus; const uint32_t *id; -} CMSDKAPBWatchdog; +}; #endif diff --git a/include/hw/watchdog/sbsa_gwdt.h b/include/hw/watchdog/sbsa_gwdt.h new file mode 100644 index 0000000000000000000000000000000000000000..70b137de301669baec2cbf3ff3e40e7ccffcf1b9 --- /dev/null +++ b/include/hw/watchdog/sbsa_gwdt.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2020 Linaro Limited + * + * Authors: + * Shashi Mallela + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version. See the COPYING file in the top-level directory. + * + */ + +#ifndef WDT_SBSA_GWDT_H +#define WDT_SBSA_GWDT_H + +#include "qemu/bitops.h" +#include "hw/sysbus.h" +#include "hw/irq.h" + +#define TYPE_WDT_SBSA "sbsa_gwdt" +#define SBSA_GWDT(obj) \ + OBJECT_CHECK(SBSA_GWDTState, (obj), TYPE_WDT_SBSA) +#define SBSA_GWDT_CLASS(klass) \ + OBJECT_CLASS_CHECK(SBSA_GWDTClass, (klass), TYPE_WDT_SBSA) +#define SBSA_GWDT_GET_CLASS(obj) \ + OBJECT_GET_CLASS(SBSA_GWDTClass, (obj), TYPE_WDT_SBSA) + +/* SBSA Generic Watchdog register definitions */ +/* refresh frame */ +#define SBSA_GWDT_WRR 0x000 + +/* control frame */ +#define SBSA_GWDT_WCS 0x000 +#define SBSA_GWDT_WOR 0x008 +#define SBSA_GWDT_WORU 0x00C +#define SBSA_GWDT_WCV 0x010 +#define SBSA_GWDT_WCVU 0x014 + +/* Watchdog Interface Identification Register */ +#define SBSA_GWDT_W_IIDR 0xFCC + +/* Watchdog Control and Status Register Bits */ +#define SBSA_GWDT_WCS_EN BIT(0) +#define SBSA_GWDT_WCS_WS0 BIT(1) +#define SBSA_GWDT_WCS_WS1 BIT(2) + +#define SBSA_GWDT_WOR_MASK 0x0000FFFF + +/* + * Watchdog Interface Identification Register definition + * considering JEP106 code for ARM in Bits [11:0] + */ +#define SBSA_GWDT_ID 0x1043B + +/* 2 Separate memory regions for each of refresh & control register frames */ +#define SBSA_GWDT_RMMIO_SIZE 0x1000 +#define SBSA_GWDT_CMMIO_SIZE 0x1000 + +#define SBSA_TIMER_FREQ 62500000 /* Hz */ + +typedef struct SBSA_GWDTState { + /* */ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion rmmio; + MemoryRegion cmmio; + qemu_irq irq; + + QEMUTimer *timer; + + uint32_t id; + uint32_t wcs; + uint32_t worl; + uint32_t woru; + uint32_t wcvl; + uint32_t wcvu; +} SBSA_GWDTState; + +#endif /* WDT_SBSA_GWDT_H */ diff --git a/include/hw/watchdog/wdt_aspeed.h b/include/hw/watchdog/wdt_aspeed.h index 819c22993a6e40056b0ee2fd65a945fc4d0aa7ae..80b03661e303cc877ebc6581cb1e6f5a8b3f0a4d 100644 --- a/include/hw/watchdog/wdt_aspeed.h +++ b/include/hw/watchdog/wdt_aspeed.h @@ -12,17 +12,17 @@ #include "hw/misc/aspeed_scu.h" #include "hw/sysbus.h" +#include "qom/object.h" #define TYPE_ASPEED_WDT "aspeed.wdt" -#define ASPEED_WDT(obj) \ - OBJECT_CHECK(AspeedWDTState, (obj), TYPE_ASPEED_WDT) +OBJECT_DECLARE_TYPE(AspeedWDTState, AspeedWDTClass, ASPEED_WDT) #define TYPE_ASPEED_2400_WDT TYPE_ASPEED_WDT "-ast2400" #define TYPE_ASPEED_2500_WDT TYPE_ASPEED_WDT "-ast2500" #define TYPE_ASPEED_2600_WDT TYPE_ASPEED_WDT "-ast2600" #define ASPEED_WDT_REGS_MAX (0x20 / 4) -typedef struct AspeedWDTState { +struct AspeedWDTState { /*< private >*/ SysBusDevice parent_obj; QEMUTimer *timer; @@ -33,14 +33,10 @@ typedef struct AspeedWDTState { AspeedSCUState *scu; uint32_t pclk_freq; -} AspeedWDTState; +}; -#define ASPEED_WDT_CLASS(klass) \ - OBJECT_CLASS_CHECK(AspeedWDTClass, (klass), TYPE_ASPEED_WDT) -#define ASPEED_WDT_GET_CLASS(obj) \ - OBJECT_GET_CLASS(AspeedWDTClass, (obj), TYPE_ASPEED_WDT) -typedef struct AspeedWDTClass { +struct AspeedWDTClass { SysBusDeviceClass parent_class; uint32_t offset; @@ -48,6 +44,6 @@ typedef struct AspeedWDTClass { uint32_t reset_ctrl_reg; void (*reset_pulse)(AspeedWDTState *s, uint32_t property); void (*wdt_reload)(AspeedWDTState *s); -} AspeedWDTClass; +}; #endif /* WDT_ASPEED_H */ diff --git a/include/hw/watchdog/wdt_diag288.h b/include/hw/watchdog/wdt_diag288.h index 19d83a0937967d6614a6f57143b612e7ab5cb55c..f72c1d3318d3bb9d3e9a316dcf5cbe583814174c 100644 --- a/include/hw/watchdog/wdt_diag288.h +++ b/include/hw/watchdog/wdt_diag288.h @@ -2,35 +2,34 @@ #define WDT_DIAG288_H #include "hw/qdev-core.h" +#include "qom/object.h" #define TYPE_WDT_DIAG288 "diag288" -#define DIAG288(obj) \ - OBJECT_CHECK(DIAG288State, (obj), TYPE_WDT_DIAG288) -#define DIAG288_CLASS(klass) \ - OBJECT_CLASS_CHECK(DIAG288Class, (klass), TYPE_WDT_DIAG288) -#define DIAG288_GET_CLASS(obj) \ - OBJECT_GET_CLASS(DIAG288Class, (obj), TYPE_WDT_DIAG288) +typedef struct DIAG288Class DIAG288Class; +typedef struct DIAG288State DIAG288State; +DECLARE_OBJ_CHECKERS(DIAG288State, DIAG288Class, + DIAG288, TYPE_WDT_DIAG288) #define WDT_DIAG288_INIT 0 #define WDT_DIAG288_CHANGE 1 #define WDT_DIAG288_CANCEL 2 -typedef struct DIAG288State { +struct DIAG288State { /*< private >*/ DeviceState parent_obj; QEMUTimer *timer; bool enabled; /*< public >*/ -} DIAG288State; +}; -typedef struct DIAG288Class { +struct DIAG288Class { /*< private >*/ DeviceClass parent_class; /*< public >*/ int (*handle_timer)(DIAG288State *dev, uint64_t func, uint64_t timeout); -} DIAG288Class; +}; #endif /* WDT_DIAG288_H */ diff --git a/include/hw/watchdog/wdt_imx2.h b/include/hw/watchdog/wdt_imx2.h index f9af6be4b69dbe6097dc78847e6d90df4cb145a6..023d83f48f6d7e81750420ff6ffafeb455fda447 100644 --- a/include/hw/watchdog/wdt_imx2.h +++ b/include/hw/watchdog/wdt_imx2.h @@ -16,9 +16,10 @@ #include "hw/sysbus.h" #include "hw/irq.h" #include "hw/ptimer.h" +#include "qom/object.h" #define TYPE_IMX2_WDT "imx2.wdt" -#define IMX2_WDT(obj) OBJECT_CHECK(IMX2WdtState, (obj), TYPE_IMX2_WDT) +OBJECT_DECLARE_SIMPLE_TYPE(IMX2WdtState, IMX2_WDT) enum IMX2WdtRegisters { IMX2_WDT_WCR = 0x0000, /* Control Register */ @@ -62,7 +63,7 @@ enum IMX2WdtRegisters { /* Misc Control Register definitions */ #define IMX2_WDT_WMCR_PDE BIT(0) /* Power-Down Enable */ -typedef struct IMX2WdtState { +struct IMX2WdtState { /* */ SysBusDevice parent_obj; @@ -85,6 +86,6 @@ typedef struct IMX2WdtState { bool wcr_locked; /* affects WDZST, WDBG, and WDW */ bool wcr_wde_locked; /* affects WDE */ bool wcr_wdt_locked; /* affects WDT (never cleared) */ -} IMX2WdtState; +}; #endif /* IMX2_WDT_H */ diff --git a/include/hw/xen/xen-backend.h b/include/hw/xen/xen-backend.h index 010d712638766d4041cba8845c2d5cb9e0c74630..aac2fd454d449ee774ac3f52c6e60101b4b75c58 100644 --- a/include/hw/xen/xen-backend.h +++ b/include/hw/xen/xen-backend.h @@ -31,6 +31,7 @@ void xen_backend_set_device(XenBackendInstance *backend, XenDevice *xen_backend_get_device(XenBackendInstance *backend); void xen_backend_register(const XenBackendInfo *info); +const char **xen_backend_get_types(unsigned int *nr); void xen_backend_device_create(XenBus *xenbus, const char *type, const char *name, QDict *opts, Error **errp); diff --git a/include/hw/xen/xen-block.h b/include/hw/xen/xen-block.h index 2cd2fc2701128f3f2b25be44770b45e3f3af5bbb..d692ea7580255ddfe1f7fbcd1a444d4dfdcca278 100644 --- a/include/hw/xen/xen-block.h +++ b/include/hw/xen/xen-block.h @@ -12,6 +12,7 @@ #include "hw/block/block.h" #include "hw/block/dataplane/xen-block.h" #include "sysemu/iothread.h" +#include "qom/object.h" typedef enum XenBlockVdevType { XEN_BLOCK_VDEV_TYPE_INVALID, @@ -46,7 +47,7 @@ typedef struct XenBlockIOThread { char *id; } XenBlockIOThread; -typedef struct XenBlockDevice { +struct XenBlockDevice { XenDevice xendev; XenBlockProperties props; const char *device_type; @@ -54,41 +55,35 @@ typedef struct XenBlockDevice { XenBlockDataPlane *dataplane; XenBlockDrive *drive; XenBlockIOThread *iothread; -} XenBlockDevice; +}; +typedef struct XenBlockDevice XenBlockDevice; typedef void (*XenBlockDeviceRealize)(XenBlockDevice *blockdev, Error **errp); typedef void (*XenBlockDeviceUnrealize)(XenBlockDevice *blockdev); -typedef struct XenBlockDeviceClass { +struct XenBlockDeviceClass { /*< private >*/ XenDeviceClass parent_class; /*< public >*/ XenBlockDeviceRealize realize; XenBlockDeviceUnrealize unrealize; -} XenBlockDeviceClass; +}; #define TYPE_XEN_BLOCK_DEVICE "xen-block" -#define XEN_BLOCK_DEVICE(obj) \ - OBJECT_CHECK(XenBlockDevice, (obj), TYPE_XEN_BLOCK_DEVICE) -#define XEN_BLOCK_DEVICE_CLASS(class) \ - OBJECT_CLASS_CHECK(XenBlockDeviceClass, (class), TYPE_XEN_BLOCK_DEVICE) -#define XEN_BLOCK_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(XenBlockDeviceClass, (obj), TYPE_XEN_BLOCK_DEVICE) - -typedef struct XenDiskDevice { +OBJECT_DECLARE_TYPE(XenBlockDevice, XenBlockDeviceClass, XEN_BLOCK_DEVICE) + +struct XenDiskDevice { XenBlockDevice blockdev; -} XenDiskDevice; +}; #define TYPE_XEN_DISK_DEVICE "xen-disk" -#define XEN_DISK_DEVICE(obj) \ - OBJECT_CHECK(XenDiskDevice, (obj), TYPE_XEN_DISK_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(XenDiskDevice, XEN_DISK_DEVICE) -typedef struct XenCDRomDevice { +struct XenCDRomDevice { XenBlockDevice blockdev; -} XenCDRomDevice; +}; #define TYPE_XEN_CDROM_DEVICE "xen-cdrom" -#define XEN_CDROM_DEVICE(obj) \ - OBJECT_CHECK(XenCDRomDevice, (obj), TYPE_XEN_CDROM_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(XenCDRomDevice, XEN_CDROM_DEVICE) #endif /* HW_XEN_BLOCK_H */ diff --git a/include/hw/xen/xen-bus.h b/include/hw/xen/xen-bus.h index 4ec0bb072ff43458dff21c2910cbebdf54e7fe16..6bdbf3ff82209725c41fc390c4b324bcc4c6f82a 100644 --- a/include/hw/xen/xen-bus.h +++ b/include/hw/xen/xen-bus.h @@ -11,6 +11,7 @@ #include "hw/xen/xen_common.h" #include "hw/sysbus.h" #include "qemu/notify.h" +#include "qom/object.h" typedef void (*XenWatchHandler)(void *opaque); @@ -18,7 +19,7 @@ typedef struct XenWatchList XenWatchList; typedef struct XenWatch XenWatch; typedef struct XenEventChannel XenEventChannel; -typedef struct XenDevice { +struct XenDevice { DeviceState qdev; domid_t frontend_id; char *name; @@ -35,7 +36,8 @@ typedef struct XenDevice { bool inactive; QLIST_HEAD(, XenEventChannel) event_channels; QLIST_ENTRY(XenDevice) list; -} XenDevice; +}; +typedef struct XenDevice XenDevice; typedef char *(*XenDeviceGetName)(XenDevice *xendev, Error **errp); typedef void (*XenDeviceRealize)(XenDevice *xendev, Error **errp); @@ -44,7 +46,7 @@ typedef void (*XenDeviceFrontendChanged)(XenDevice *xendev, Error **errp); typedef void (*XenDeviceUnrealize)(XenDevice *xendev); -typedef struct XenDeviceClass { +struct XenDeviceClass { /*< private >*/ DeviceClass parent_class; /*< public >*/ @@ -54,37 +56,29 @@ typedef struct XenDeviceClass { XenDeviceRealize realize; XenDeviceFrontendChanged frontend_changed; XenDeviceUnrealize unrealize; -} XenDeviceClass; +}; #define TYPE_XEN_DEVICE "xen-device" -#define XEN_DEVICE(obj) \ - OBJECT_CHECK(XenDevice, (obj), TYPE_XEN_DEVICE) -#define XEN_DEVICE_CLASS(class) \ - OBJECT_CLASS_CHECK(XenDeviceClass, (class), TYPE_XEN_DEVICE) -#define XEN_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(XenDeviceClass, (obj), TYPE_XEN_DEVICE) - -typedef struct XenBus { +OBJECT_DECLARE_TYPE(XenDevice, XenDeviceClass, XEN_DEVICE) + +struct XenBus { BusState qbus; domid_t backend_id; struct xs_handle *xsh; XenWatchList *watch_list; - XenWatch *backend_watch; + unsigned int backend_types; + XenWatch **backend_watch; QLIST_HEAD(, XenDevice) inactive_devices; -} XenBus; +}; -typedef struct XenBusClass { +struct XenBusClass { /*< private >*/ BusClass parent_class; -} XenBusClass; +}; #define TYPE_XEN_BUS "xen-bus" -#define XEN_BUS(obj) \ - OBJECT_CHECK(XenBus, (obj), TYPE_XEN_BUS) -#define XEN_BUS_CLASS(class) \ - OBJECT_CLASS_CHECK(XenBusClass, (class), TYPE_XEN_BUS) -#define XEN_BUS_GET_CLASS(obj) \ - OBJECT_GET_CLASS(XenBusClass, (obj), TYPE_XEN_BUS) +OBJECT_DECLARE_TYPE(XenBus, XenBusClass, + XEN_BUS) void xen_bus_init(void); diff --git a/include/hw/xen/xen-legacy-backend.h b/include/hw/xen/xen-legacy-backend.h index 5e6c56c4d626aebeecc3b6769fa35f8a7bcee8aa..be281e1f38ebad79d50919cad58bd6b478ed0162 100644 --- a/include/hw/xen/xen-legacy-backend.h +++ b/include/hw/xen/xen-legacy-backend.h @@ -4,13 +4,15 @@ #include "hw/xen/xen_common.h" #include "hw/xen/xen_pvdev.h" #include "net/net.h" +#include "qom/object.h" #define TYPE_XENSYSDEV "xen-sysdev" #define TYPE_XENSYSBUS "xen-sysbus" #define TYPE_XENBACKEND "xen-backend" -#define XENBACKEND_DEVICE(obj) \ - OBJECT_CHECK(XenLegacyDevice, (obj), TYPE_XENBACKEND) +typedef struct XenLegacyDevice XenLegacyDevice; +DECLARE_INSTANCE_CHECKER(XenLegacyDevice, XENBACKEND, + TYPE_XENBACKEND) /* variables */ extern struct xs_handle *xenstore; diff --git a/include/hw/xen/xen-x86.h b/include/hw/xen/xen-x86.h new file mode 100644 index 0000000000000000000000000000000000000000..85e3db1b8de211b7f574b66dcba5045ad5234d25 --- /dev/null +++ b/include/hw/xen/xen-x86.h @@ -0,0 +1,15 @@ +/* + * Xen X86-specific + * + * Copyright 2020 Red Hat, Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef QEMU_HW_XEN_X86_H +#define QEMU_HW_XEN_X86_H + +#include "hw/i386/pc.h" + +void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion **ram_memory); + +#endif /* QEMU_HW_XEN_X86_H */ diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h index 5ac1c6dc5580a93f8fcdf38b8902a937baf310b4..0f9962b1c190d4c35f30f46ac76c8032d2fead29 100644 --- a/include/hw/xen/xen.h +++ b/include/hw/xen/xen.h @@ -20,13 +20,6 @@ extern uint32_t xen_domid; extern enum xen_mode xen_mode; extern bool xen_domid_restrict; -extern bool xen_allowed; - -static inline bool xen_enabled(void) -{ - return xen_allowed; -} - int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num); void xen_piix3_set_irq(void *opaque, int irq_num, int level); void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len); @@ -35,13 +28,7 @@ int xen_is_pirq_msi(uint32_t msi_data); qemu_irq *xen_interrupt_controller_init(void); -void xenstore_store_pv_console_info(int i, struct Chardev *chr); - -void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory); - -void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, - struct MemoryRegion *mr, Error **errp); -void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length); +void xenstore_store_pv_console_info(int i, Chardev *chr); void xen_register_framebuffer(struct MemoryRegion *mr); diff --git a/include/io/channel-buffer.h b/include/io/channel-buffer.h index 3f4b3f29e126029b172fa726a53b836310eba702..c9463ee6551be1631e0d489c7a1540e864ac0ba0 100644 --- a/include/io/channel-buffer.h +++ b/include/io/channel-buffer.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -22,12 +22,11 @@ #define QIO_CHANNEL_BUFFER_H #include "io/channel.h" +#include "qom/object.h" #define TYPE_QIO_CHANNEL_BUFFER "qio-channel-buffer" -#define QIO_CHANNEL_BUFFER(obj) \ - OBJECT_CHECK(QIOChannelBuffer, (obj), TYPE_QIO_CHANNEL_BUFFER) +OBJECT_DECLARE_SIMPLE_TYPE(QIOChannelBuffer, QIO_CHANNEL_BUFFER) -typedef struct QIOChannelBuffer QIOChannelBuffer; /** * QIOChannelBuffer: diff --git a/include/io/channel-command.h b/include/io/channel-command.h index 336d47fa5c878db28eff42fa29b082e4432ea098..27e42bdadc719d990310e4b1045f9034c3666e8c 100644 --- a/include/io/channel-command.h +++ b/include/io/channel-command.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -22,12 +22,11 @@ #define QIO_CHANNEL_COMMAND_H #include "io/channel.h" +#include "qom/object.h" #define TYPE_QIO_CHANNEL_COMMAND "qio-channel-command" -#define QIO_CHANNEL_COMMAND(obj) \ - OBJECT_CHECK(QIOChannelCommand, (obj), TYPE_QIO_CHANNEL_COMMAND) +OBJECT_DECLARE_SIMPLE_TYPE(QIOChannelCommand, QIO_CHANNEL_COMMAND) -typedef struct QIOChannelCommand QIOChannelCommand; /** diff --git a/include/io/channel-file.h b/include/io/channel-file.h index ebfe54ec70febc0d0a864f56769ee975b1b2cf59..50e8eb11386840bdceab555c5da87a8f0505ef91 100644 --- a/include/io/channel-file.h +++ b/include/io/channel-file.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -22,12 +22,11 @@ #define QIO_CHANNEL_FILE_H #include "io/channel.h" +#include "qom/object.h" #define TYPE_QIO_CHANNEL_FILE "qio-channel-file" -#define QIO_CHANNEL_FILE(obj) \ - OBJECT_CHECK(QIOChannelFile, (obj), TYPE_QIO_CHANNEL_FILE) +OBJECT_DECLARE_SIMPLE_TYPE(QIOChannelFile, QIO_CHANNEL_FILE) -typedef struct QIOChannelFile QIOChannelFile; /** * QIOChannelFile: diff --git a/include/io/channel-socket.h b/include/io/channel-socket.h index 777ff5954e6e0acceb4779c2ca858cb16a32d1b4..e747e635147ed62015a9a2b5337c5a3a21c41880 100644 --- a/include/io/channel-socket.h +++ b/include/io/channel-socket.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -24,12 +24,11 @@ #include "io/channel.h" #include "io/task.h" #include "qemu/sockets.h" +#include "qom/object.h" #define TYPE_QIO_CHANNEL_SOCKET "qio-channel-socket" -#define QIO_CHANNEL_SOCKET(obj) \ - OBJECT_CHECK(QIOChannelSocket, (obj), TYPE_QIO_CHANNEL_SOCKET) +OBJECT_DECLARE_SIMPLE_TYPE(QIOChannelSocket, QIO_CHANNEL_SOCKET) -typedef struct QIOChannelSocket QIOChannelSocket; /** * QIOChannelSocket: diff --git a/include/io/channel-tls.h b/include/io/channel-tls.h index fdbdf12feb1e73b020190d1867543ee2b42c2f5a..5672479e9eb60d6117592cc4a66e8329dbdf9e1c 100644 --- a/include/io/channel-tls.h +++ b/include/io/channel-tls.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -24,12 +24,11 @@ #include "io/channel.h" #include "io/task.h" #include "crypto/tlssession.h" +#include "qom/object.h" #define TYPE_QIO_CHANNEL_TLS "qio-channel-tls" -#define QIO_CHANNEL_TLS(obj) \ - OBJECT_CHECK(QIOChannelTLS, (obj), TYPE_QIO_CHANNEL_TLS) +OBJECT_DECLARE_SIMPLE_TYPE(QIOChannelTLS, QIO_CHANNEL_TLS) -typedef struct QIOChannelTLS QIOChannelTLS; /** * QIOChannelTLS diff --git a/include/io/channel-util.h b/include/io/channel-util.h index c0b79cf6036bd30af6fc29a6f363fe1297fb7652..a5d720d9a04bf48d13c6e7983bc45f23fe3b8f7b 100644 --- a/include/io/channel-util.h +++ b/include/io/channel-util.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/io/channel-watch.h b/include/io/channel-watch.h index 63bc4ae2d92a098135d9e97ee970c170be58d829..a36aab8f8f2f3f8185bb350935e605370a593f15 100644 --- a/include/io/channel-watch.h +++ b/include/io/channel-watch.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/io/channel-websock.h b/include/io/channel-websock.h index a7e5e92e61ee9cf0e1608eb3af7290909b13640d..e180827c57f1b73db7282e6020fe672b5953dd9f 100644 --- a/include/io/channel-websock.h +++ b/include/io/channel-websock.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -24,12 +24,11 @@ #include "io/channel.h" #include "qemu/buffer.h" #include "io/task.h" +#include "qom/object.h" #define TYPE_QIO_CHANNEL_WEBSOCK "qio-channel-websock" -#define QIO_CHANNEL_WEBSOCK(obj) \ - OBJECT_CHECK(QIOChannelWebsock, (obj), TYPE_QIO_CHANNEL_WEBSOCK) +OBJECT_DECLARE_SIMPLE_TYPE(QIOChannelWebsock, QIO_CHANNEL_WEBSOCK) -typedef struct QIOChannelWebsock QIOChannelWebsock; typedef union QIOChannelWebsockMask QIOChannelWebsockMask; union QIOChannelWebsockMask { diff --git a/include/io/channel.h b/include/io/channel.h index d4557f0930ae4cb02a4e58c9208e62bb60c919c1..4d6fe45f63d8f3d040ff4b845d2fa8f7919ee934 100644 --- a/include/io/channel.h +++ b/include/io/channel.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -26,15 +26,9 @@ #include "block/aio.h" #define TYPE_QIO_CHANNEL "qio-channel" -#define QIO_CHANNEL(obj) \ - OBJECT_CHECK(QIOChannel, (obj), TYPE_QIO_CHANNEL) -#define QIO_CHANNEL_CLASS(klass) \ - OBJECT_CLASS_CHECK(QIOChannelClass, klass, TYPE_QIO_CHANNEL) -#define QIO_CHANNEL_GET_CLASS(obj) \ - OBJECT_GET_CLASS(QIOChannelClass, obj, TYPE_QIO_CHANNEL) - -typedef struct QIOChannel QIOChannel; -typedef struct QIOChannelClass QIOChannelClass; +OBJECT_DECLARE_TYPE(QIOChannel, QIOChannelClass, + QIO_CHANNEL) + #define QIO_CHANNEL_ERR_BLOCK -2 diff --git a/include/io/dns-resolver.h b/include/io/dns-resolver.h index a475e978c87f3d90bfc536bd6fa66de0f730e03e..558ea517ded4cf55d2c4f9a9414cc3fd8229d91c 100644 --- a/include/io/dns-resolver.h +++ b/include/io/dns-resolver.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -26,15 +26,9 @@ #include "io/task.h" #define TYPE_QIO_DNS_RESOLVER "qio-dns-resolver" -#define QIO_DNS_RESOLVER(obj) \ - OBJECT_CHECK(QIODNSResolver, (obj), TYPE_QIO_DNS_RESOLVER) -#define QIO_DNS_RESOLVER_CLASS(klass) \ - OBJECT_CLASS_CHECK(QIODNSResolverClass, klass, TYPE_QIO_DNS_RESOLVER) -#define QIO_DNS_RESOLVER_GET_CLASS(obj) \ - OBJECT_GET_CLASS(QIODNSResolverClass, obj, TYPE_QIO_DNS_RESOLVER) +OBJECT_DECLARE_SIMPLE_TYPE(QIODNSResolver, + QIO_DNS_RESOLVER) -typedef struct QIODNSResolver QIODNSResolver; -typedef struct QIODNSResolverClass QIODNSResolverClass; /** * QIODNSResolver: @@ -139,9 +133,6 @@ struct QIODNSResolver { Object parent; }; -struct QIODNSResolverClass { - ObjectClass parent; -}; /** diff --git a/include/io/net-listener.h b/include/io/net-listener.h index fb101703e3ea07a9062b69a0fd658eb4d8dc4d92..ab9f291ed62e57462cc0703b1adf20d8c9ae38cc 100644 --- a/include/io/net-listener.h +++ b/include/io/net-listener.h @@ -22,17 +22,12 @@ #define QIO_NET_LISTENER_H #include "io/channel-socket.h" +#include "qom/object.h" #define TYPE_QIO_NET_LISTENER "qio-net-listener" -#define QIO_NET_LISTENER(obj) \ - OBJECT_CHECK(QIONetListener, (obj), TYPE_QIO_NET_LISTENER) -#define QIO_NET_LISTENER_CLASS(klass) \ - OBJECT_CLASS_CHECK(QIONetListenerClass, klass, TYPE_QIO_NET_LISTENER) -#define QIO_NET_LISTENER_GET_CLASS(obj) \ - OBJECT_GET_CLASS(QIONetListenerClass, obj, TYPE_QIO_NET_LISTENER) +OBJECT_DECLARE_SIMPLE_TYPE(QIONetListener, + QIO_NET_LISTENER) -typedef struct QIONetListener QIONetListener; -typedef struct QIONetListenerClass QIONetListenerClass; typedef void (*QIONetListenerClientFunc)(QIONetListener *listener, QIOChannelSocket *sioc, @@ -63,9 +58,6 @@ struct QIONetListener { GDestroyNotify io_notify; }; -struct QIONetListenerClass { - ObjectClass parent; -}; /** diff --git a/include/io/task.h b/include/io/task.h index 1abbfb8b654b56aaaff0884bba41e39e3585239e..beec4f5cfd1dc036e9c96fbd50e25cb948c138b5 100644 --- a/include/io/task.h +++ b/include/io/task.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -21,8 +21,6 @@ #ifndef QIO_TASK_H #define QIO_TASK_H -#include "qom/object.h" - typedef struct QIOTask QIOTask; typedef void (*QIOTaskFunc)(QIOTask *task, diff --git a/include/migration/colo.h b/include/migration/colo.h index 1636e6f907d0bd806e563ad6d1aedf862b03b565..768e1f04c3a60fc9ee98928333be46b6a10f5baa 100644 --- a/include/migration/colo.h +++ b/include/migration/colo.h @@ -25,7 +25,7 @@ void migrate_start_colo_process(MigrationState *s); bool migration_in_colo_state(void); /* loadvm */ -void migration_incoming_enable_colo(void); +int migration_incoming_enable_colo(void); void migration_incoming_disable_colo(void); bool migration_incoming_colo_enabled(void); void *colo_process_incoming_thread(void *opaque); diff --git a/include/migration/misc.h b/include/migration/misc.h index d2762257aa3d561ef847e5f302e9f9813d111b92..34e7d7571382d7b4cc043863a0e44d8fcc867ded 100644 --- a/include/migration/misc.h +++ b/include/migration/misc.h @@ -69,6 +69,8 @@ bool migration_has_failed(MigrationState *); /* ...and after the device transmission */ bool migration_in_postcopy_after_devices(MigrationState *); void migration_global_dump(Monitor *mon); +/* True if incomming migration entered POSTCOPY_INCOMING_DISCARD */ +bool migration_in_incoming_postcopy(void); /* migration/block-dirty-bitmap.c */ void dirty_bitmap_mig_init(void); diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index 30667631bc82e8d1577c11e8ad0d66477491a014..4d71dc8fbaa99c34979eaed8af335337639083f5 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -219,7 +219,6 @@ extern const VMStateInfo vmstate_info_uint64; #define VMS_NULLPTR_MARKER (0x30U) /* '0' */ extern const VMStateInfo vmstate_info_nullptr; -extern const VMStateInfo vmstate_info_float64; extern const VMStateInfo vmstate_info_cpudouble; extern const VMStateInfo vmstate_info_timer; @@ -432,6 +431,16 @@ extern const VMStateInfo vmstate_info_qlist; .offset = vmstate_offset_pointer(_state, _field, _type), \ } +#define VMSTATE_VARRAY_UINT16_ALLOC(_field, _state, _field_num, _version, _info, _type) {\ + .name = (stringify(_field)), \ + .version_id = (_version), \ + .num_offset = vmstate_offset_value(_state, _field_num, uint16_t),\ + .info = &(_info), \ + .size = sizeof(_type), \ + .flags = VMS_VARRAY_UINT16 | VMS_POINTER | VMS_ALLOC, \ + .offset = vmstate_offset_pointer(_state, _field, _type), \ +} + #define VMSTATE_VARRAY_UINT16_UNSAFE(_field, _state, _field_num, _version, _info, _type) {\ .name = (stringify(_field)), \ .version_id = (_version), \ @@ -987,12 +996,6 @@ extern const VMStateInfo vmstate_info_qlist; VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_uint64, uint64_t) -#define VMSTATE_FLOAT64_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, vmstate_info_float64, float64) - -#define VMSTATE_FLOAT64(_f, _s) \ - VMSTATE_FLOAT64_V(_f, _s, 0) - #define VMSTATE_TIMER_PTR_TEST(_f, _s, _test) \ VMSTATE_POINTER_TEST(_f, _s, _test, vmstate_info_timer, QEMUTimer *) @@ -1104,12 +1107,6 @@ extern const VMStateInfo vmstate_info_qlist; #define VMSTATE_INT64_ARRAY(_f, _s, _n) \ VMSTATE_INT64_ARRAY_V(_f, _s, _n, 0) -#define VMSTATE_FLOAT64_ARRAY_V(_f, _s, _n, _v) \ - VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_float64, float64) - -#define VMSTATE_FLOAT64_ARRAY(_f, _s, _n) \ - VMSTATE_FLOAT64_ARRAY_V(_f, _s, _n, 0) - #define VMSTATE_CPUDOUBLE_ARRAY_V(_f, _s, _n, _v) \ VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_cpudouble, CPU_DoubleU) @@ -1199,7 +1196,6 @@ static inline int vmstate_register(VMStateIf *obj, int instance_id, void vmstate_unregister(VMStateIf *obj, const VMStateDescription *vmsd, void *opaque); -struct MemoryRegion; void vmstate_register_ram(struct MemoryRegion *memory, DeviceState *dev); void vmstate_unregister_ram(struct MemoryRegion *memory, DeviceState *dev); void vmstate_register_ram_global(struct MemoryRegion *memory); diff --git a/include/monitor/hmp-target.h b/include/monitor/hmp-target.h index 8b7820a3ad53d53fdb737c3b5e31c67264793e92..60fc92722aed6defa0a6608e6b75ed9b0c4760d0 100644 --- a/include/monitor/hmp-target.h +++ b/include/monitor/hmp-target.h @@ -33,15 +33,16 @@ struct MonitorDef { const char *name; int offset; - target_long (*get_value)(const struct MonitorDef *md, int val); + target_long (*get_value)(Monitor *mon, const struct MonitorDef *md, + int val); int type; }; const MonitorDef *target_monitor_defs(void); int target_get_monitor_def(CPUState *cs, const char *name, uint64_t *pval); -CPUArchState *mon_get_cpu_env(void); -CPUState *mon_get_cpu(void); +CPUArchState *mon_get_cpu_env(Monitor *mon); +CPUState *mon_get_cpu(Monitor *mon); void hmp_info_mem(Monitor *mon, const QDict *qdict); void hmp_info_tlb(Monitor *mon, const QDict *qdict); diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h index e33ca5a911a5e5145e10ad4ea519906527c58666..ed2913fd18e801164c691e308aae6f27c03521da 100644 --- a/include/monitor/hmp.h +++ b/include/monitor/hmp.h @@ -89,13 +89,13 @@ void hmp_chardev_add(Monitor *mon, const QDict *qdict); void hmp_chardev_change(Monitor *mon, const QDict *qdict); void hmp_chardev_remove(Monitor *mon, const QDict *qdict); void hmp_chardev_send_break(Monitor *mon, const QDict *qdict); -void hmp_cpu_add(Monitor *mon, const QDict *qdict); void hmp_object_add(Monitor *mon, const QDict *qdict); void hmp_object_del(Monitor *mon, const QDict *qdict); void hmp_info_memdev(Monitor *mon, const QDict *qdict); void hmp_info_numa(Monitor *mon, const QDict *qdict); void hmp_info_memory_devices(Monitor *mon, const QDict *qdict); void hmp_qom_list(Monitor *mon, const QDict *qdict); +void hmp_qom_get(Monitor *mon, const QDict *qdict); void hmp_qom_set(Monitor *mon, const QDict *qdict); void hmp_info_qom_tree(Monitor *mon, const QDict *dict); void object_add_completion(ReadLineState *rs, int nb_args, const char *str); @@ -129,5 +129,9 @@ void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict); void hmp_info_vm_generation_id(Monitor *mon, const QDict *qdict); void hmp_info_memory_size_summary(Monitor *mon, const QDict *qdict); void hmp_info_sev(Monitor *mon, const QDict *qdict); +void hmp_info_replay(Monitor *mon, const QDict *qdict); +void hmp_replay_break(Monitor *mon, const QDict *qdict); +void hmp_replay_delete_break(Monitor *mon, const QDict *qdict); +void hmp_replay_seek(Monitor *mon, const QDict *qdict); #endif diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index 1018d754a6f981c2307ca93a7b92e200ee2b71b1..348bfad3d58e0ddd700bf41be61ff8f993b56453 100644 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -5,7 +5,6 @@ #include "qapi/qapi-types-misc.h" #include "qemu/readline.h" -extern __thread Monitor *cur_mon; typedef struct MonitorHMP MonitorHMP; typedef struct MonitorOptions MonitorOptions; @@ -13,6 +12,8 @@ typedef struct MonitorOptions MonitorOptions; extern QemuOptsList qemu_mon_opts; +Monitor *monitor_cur(void); +Monitor *monitor_set_cur(Coroutine *co, Monitor *mon); bool monitor_cur_is_qmp(void); void monitor_init_globals(void); @@ -33,8 +34,8 @@ int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) GCC_FMT_ATTR(2, 0); int monitor_printf(Monitor *mon, const char *fmt, ...) GCC_FMT_ATTR(2, 3); void monitor_flush(Monitor *mon); -int monitor_set_cpu(int cpu_index); -int monitor_get_cpu_index(void); +int monitor_set_cpu(Monitor *mon, int cpu_index); +int monitor_get_cpu_index(Monitor *mon); void monitor_read_command(MonitorHMP *mon, int show_prompt); int monitor_read_password(MonitorHMP *mon, ReadLineFunc *readline_func, @@ -43,8 +44,7 @@ int monitor_read_password(MonitorHMP *mon, ReadLineFunc *readline_func, AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id, bool has_opaque, const char *opaque, Error **errp); -int monitor_fdset_get_fd(int64_t fdset_id, int flags); -int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd); +int monitor_fdset_dup_fd_add(int64_t fdset_id, int flags); void monitor_fdset_dup_fd_remove(int dup_fd); int64_t monitor_fdset_dup_fd_find(int dup_fd); diff --git a/include/net/can_emu.h b/include/net/can_emu.h index fce97709287ecf112a6eaf58183f422f775d7225..6f9b206bb5f9d05f8d19ee12b69064c6e78551d9 100644 --- a/include/net/can_emu.h +++ b/include/net/can_emu.h @@ -46,7 +46,8 @@ typedef uint32_t qemu_canid_t; typedef struct qemu_can_frame { qemu_canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ uint8_t can_dlc; /* data length code: 0 .. 8 */ - uint8_t data[8] QEMU_ALIGNED(8); + uint8_t flags; + uint8_t data[64] QEMU_ALIGNED(8); } qemu_can_frame; /* Keep defines for QEMU separate from Linux ones for now */ @@ -58,6 +59,10 @@ typedef struct qemu_can_frame { #define QEMU_CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */ #define QEMU_CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */ +#define QEMU_CAN_FRMF_BRS 0x01 /* bit rate switch (2nd bitrate for data) */ +#define QEMU_CAN_FRMF_ESI 0x02 /* error state ind. of transmitting node */ +#define QEMU_CAN_FRMF_TYPE_FD 0x10 /* internal bit ind. of CAN FD frame */ + /** * struct qemu_can_filter - CAN ID based filter in can_register(). * @can_id: relevant bits of CAN ID which are not masked out. @@ -97,15 +102,11 @@ struct CanBusClientState { char *model; char *name; void (*destructor)(CanBusClientState *); + bool fd_mode; }; #define TYPE_CAN_BUS "can-bus" -#define CAN_BUS_CLASS(klass) \ - OBJECT_CLASS_CHECK(CanBusClass, (klass), TYPE_CAN_BUS) -#define CAN_BUS_GET_CLASS(obj) \ - OBJECT_GET_CLASS(CanBusClass, (obj), TYPE_CAN_BUS) -#define CAN_BUS(obj) \ - OBJECT_CHECK(CanBusState, (obj), TYPE_CAN_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(CanBusState, CAN_BUS) int can_bus_filter_match(struct qemu_can_filter *filter, qemu_canid_t can_id); @@ -121,4 +122,8 @@ int can_bus_client_set_filters(CanBusClientState *, const struct qemu_can_filter *filters, size_t filters_cnt); +uint8_t can_dlc2len(uint8_t can_dlc); + +uint8_t can_len2dlc(uint8_t len); + #endif diff --git a/include/net/can_host.h b/include/net/can_host.h index d79676746b0cdf956bc6596df2e094b24d369d11..caab71bdda8bb3365b84423e19ec915523344079 100644 --- a/include/net/can_host.h +++ b/include/net/can_host.h @@ -29,27 +29,23 @@ #define NET_CAN_HOST_H #include "net/can_emu.h" +#include "qom/object.h" #define TYPE_CAN_HOST "can-host" -#define CAN_HOST_CLASS(klass) \ - OBJECT_CLASS_CHECK(CanHostClass, (klass), TYPE_CAN_HOST) -#define CAN_HOST_GET_CLASS(obj) \ - OBJECT_GET_CLASS(CanHostClass, (obj), TYPE_CAN_HOST) -#define CAN_HOST(obj) \ - OBJECT_CHECK(CanHostState, (obj), TYPE_CAN_HOST) - -typedef struct CanHostState { - ObjectClass oc; +OBJECT_DECLARE_TYPE(CanHostState, CanHostClass, CAN_HOST) + +struct CanHostState { + Object oc; CanBusState *bus; CanBusClientState bus_client; -} CanHostState; +}; -typedef struct CanHostClass { +struct CanHostClass { ObjectClass oc; void (*connect)(CanHostState *ch, Error **errp); void (*disconnect)(CanHostState *ch); -} CanHostClass; +}; #endif diff --git a/include/net/eth.h b/include/net/eth.h index 7f45c678e752e5b4f1993586c367ee1b46115366..0671be69165c89827b8dac79817e3f131cc19ff1 100644 --- a/include/net/eth.h +++ b/include/net/eth.h @@ -186,6 +186,7 @@ struct tcp_hdr { #define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt #define ip6_ecn_acc ip6_ctlun.ip6_un3.ip6_un3_ecn +#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen #define PKT_GET_ETH_HDR(p) \ ((struct eth_header *)(p)) diff --git a/include/net/filter.h b/include/net/filter.h index 9393c591925d69d4e34cfad51510b34acb96d2ec..27ffc630df4225d85a00687aa1120f3100dee29a 100644 --- a/include/net/filter.h +++ b/include/net/filter.h @@ -15,12 +15,7 @@ #include "net/queue.h" #define TYPE_NETFILTER "netfilter" -#define NETFILTER(obj) \ - OBJECT_CHECK(NetFilterState, (obj), TYPE_NETFILTER) -#define NETFILTER_GET_CLASS(obj) \ - OBJECT_GET_CLASS(NetFilterClass, (obj), TYPE_NETFILTER) -#define NETFILTER_CLASS(klass) \ - OBJECT_CLASS_CHECK(NetFilterClass, (klass), TYPE_NETFILTER) +OBJECT_DECLARE_TYPE(NetFilterState, NetFilterClass, NETFILTER) typedef void (FilterSetup) (NetFilterState *nf, Error **errp); typedef void (FilterCleanup) (NetFilterState *nf); @@ -40,7 +35,7 @@ typedef void (FilterStatusChanged) (NetFilterState *nf, Error **errp); typedef void (FilterHandleEvent) (NetFilterState *nf, int event, Error **errp); -typedef struct NetFilterClass { +struct NetFilterClass { ObjectClass parent_class; /* optional */ @@ -50,7 +45,7 @@ typedef struct NetFilterClass { FilterHandleEvent *handle_event; /* mandatory */ FilterReceiveIOV *receive_iov; -} NetFilterClass; +}; struct NetFilterState { diff --git a/include/net/net.h b/include/net/net.h index 39085d94447596d9a5ab1ec929a5919afba8a0b8..778fc787ca14d3e1bc6f59d76cc61e562f588e60 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -176,6 +176,7 @@ void hmp_info_network(Monitor *mon, const QDict *qdict); void net_socket_rs_init(SocketReadState *rs, SocketReadStateFinalize *finalize, bool vnet_hdr); +NetClientState *qemu_get_peer(NetClientState *nc, int queue_index); /* NIC info */ @@ -198,6 +199,7 @@ extern const char *host_net_devices[]; /* from net.c */ int net_client_parse(QemuOptsList *opts_list, const char *str); +void show_netdevs(void); int net_init_clients(Error **errp); void net_check_clients(void); void net_cleanup(void); @@ -208,8 +210,8 @@ void netdev_add(QemuOpts *opts, Error **errp); int net_hub_id_for_client(NetClientState *nc, int *id); NetClientState *net_hub_port_find(int hub_id); -#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" -#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown" +#define DEFAULT_NETWORK_SCRIPT CONFIG_SYSCONFDIR "/qemu-ifup" +#define DEFAULT_NETWORK_DOWN_SCRIPT CONFIG_SYSCONFDIR "/qemu-ifdown" #define DEFAULT_BRIDGE_HELPER CONFIG_QEMU_HELPERDIR "/qemu-bridge-helper" #define DEFAULT_BRIDGE_INTERFACE "br0" diff --git a/include/net/vhost-vdpa.h b/include/net/vhost-vdpa.h new file mode 100644 index 0000000000000000000000000000000000000000..45e34b7cfcf60974ba8d41bbf806da8e29a9a190 --- /dev/null +++ b/include/net/vhost-vdpa.h @@ -0,0 +1,22 @@ +/* + * vhost-vdpa.h + * + * Copyright(c) 2017-2018 Intel Corporation. + * Copyright(c) 2020 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef VHOST_VDPA_H +#define VHOST_VDPA_H + +#define TYPE_VHOST_VDPA "vhost-vdpa" + +struct vhost_net *vhost_vdpa_get_vhost_net(NetClientState *nc); +uint64_t vhost_vdpa_get_acked_features(NetClientState *nc); + +extern const int vdpa_feature_bits[]; + +#endif /* VHOST_VDPA_H */ diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index 77e47398c4aeebce5a23e49085d368362aa61402..172b0051d8120cee3738e770e03cc330653ca0ad 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -28,6 +28,11 @@ void vhost_net_cleanup(VHostNetState *net); uint64_t vhost_net_get_features(VHostNetState *net, uint64_t features); void vhost_net_ack_features(VHostNetState *net, uint64_t features); +int vhost_net_get_config(struct vhost_net *net, uint8_t *config, + uint32_t config_len); + +int vhost_net_set_config(struct vhost_net *net, const uint8_t *data, + uint32_t offset, uint32_t size, uint32_t flags); bool vhost_net_virtqueue_pending(VHostNetState *net, int n); void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, int idx, bool mask); diff --git a/include/qapi/clone-visitor.h b/include/qapi/clone-visitor.h index 5b665ee38c6b0493f9067328efdb111803326c07..adf9a788e2320755f430f3981ff46728aed5d210 100644 --- a/include/qapi/clone-visitor.h +++ b/include/qapi/clone-visitor.h @@ -20,10 +20,10 @@ */ typedef struct QapiCloneVisitor QapiCloneVisitor; -void *qapi_clone(const void *src, void (*visit_type)(Visitor *, const char *, +void *qapi_clone(const void *src, bool (*visit_type)(Visitor *, const char *, void **, Error **)); void qapi_clone_members(void *dst, const void *src, size_t sz, - void (*visit_type_members)(Visitor *, void *, + bool (*visit_type_members)(Visitor *, void *, Error **)); /* @@ -34,7 +34,7 @@ void qapi_clone_members(void *dst, const void *src, size_t sz, */ #define QAPI_CLONE(type, src) \ ((type *)qapi_clone(src, \ - (void (*)(Visitor *, const char *, void**, \ + (bool (*)(Visitor *, const char *, void **, \ Error **))visit_type_ ## type)) /* @@ -45,7 +45,7 @@ void qapi_clone_members(void *dst, const void *src, size_t sz, */ #define QAPI_CLONE_MEMBERS(type, dst, src) \ qapi_clone_members(dst, src, sizeof(type), \ - (void (*)(Visitor *, void *, \ + (bool (*)(Visitor *, void *, \ Error **))visit_type_ ## type ## _members) #endif diff --git a/include/qapi/error.h b/include/qapi/error.h index ad5b6e896dedb28d26705c6a630b4303a358b1e9..eaa05c48374cb9aaa689f6984e56e8a1eb190da5 100644 --- a/include/qapi/error.h +++ b/include/qapi/error.h @@ -15,18 +15,55 @@ /* * Error reporting system loosely patterned after Glib's GError. * + * = Rules = + * + * - Functions that use Error to report errors have an Error **errp + * parameter. It should be the last parameter, except for functions + * taking variable arguments. + * + * - You may pass NULL to not receive the error, &error_abort to abort + * on error, &error_fatal to exit(1) on error, or a pointer to a + * variable containing NULL to receive the error. + * + * - Separation of concerns: the function is responsible for detecting + * errors and failing cleanly; handling the error is its caller's + * job. Since the value of @errp is about handling the error, the + * function should not examine it. + * + * - The function may pass @errp to functions it calls to pass on + * their errors to its caller. If it dereferences @errp to check + * for errors, it must use ERRP_GUARD(). + * + * - On success, the function should not touch *errp. On failure, it + * should set a new error, e.g. with error_setg(errp, ...), or + * propagate an existing one, e.g. with error_propagate(errp, ...). + * + * - Whenever practical, also return a value that indicates success / + * failure. This can make the error checking more concise, and can + * avoid useless error object creation and destruction. Note that + * we still have many functions returning void. We recommend + * ‱ bool-valued functions return true on success / false on failure, + * ‱ pointer-valued functions return non-null / null pointer, and + * ‱ integer-valued functions return non-negative / negative. + * + * = Creating errors = + * * Create an error: - * error_setg(&err, "situation normal, all fouled up"); + * error_setg(errp, "situation normal, all fouled up"); + * where @errp points to the location to receive the error. * * Create an error and add additional explanation: - * error_setg(&err, "invalid quark"); - * error_append_hint(&err, "Valid quarks are up, down, strange, " + * error_setg(errp, "invalid quark"); + * error_append_hint(errp, "Valid quarks are up, down, strange, " * "charm, top, bottom.\n"); + * This may require use of ERRP_GUARD(); more on that below. * * Do *not* contract this to - * error_setg(&err, "invalid quark\n" + * error_setg(errp, "invalid quark\n" // WRONG! * "Valid quarks are up, down, strange, charm, top, bottom."); * + * = Reporting and destroying errors = + * * Report an error to the current monitor if we have one, else stderr: * error_report_err(err); * This frees the error object. @@ -40,6 +77,30 @@ * error_free(err); * Note that this loses hints added with error_append_hint(). * + * Call a function ignoring errors: + * foo(arg, NULL); + * This is more concise than + * Error *err = NULL; + * foo(arg, &err); + * error_free(err); // don't do this + * + * Call a function aborting on errors: + * foo(arg, &error_abort); + * This is more concise and fails more nicely than + * Error *err = NULL; + * foo(arg, &err); + * assert(!err); // don't do this + * + * Call a function treating errors as fatal: + * foo(arg, &error_fatal); + * This is more concise than + * Error *err = NULL; + * foo(arg, &err); + * if (err) { // don't do this + * error_report_err(err); + * exit(1); + * } + * * Handle an error without reporting it (just for completeness): * error_free(err); * @@ -47,57 +108,73 @@ * reporting it (primarily useful in testsuites): * error_free_or_abort(&err); * - * Pass an existing error to the caller: - * error_propagate(errp, err); - * where Error **errp is a parameter, by convention the last one. + * = Passing errors around = * - * Pass an existing error to the caller with the message modified: - * error_propagate_prepend(errp, err); - * - * Avoid - * error_propagate(errp, err); - * error_prepend(errp, "Could not frobnicate '%s': ", name); - * because this fails to prepend when @errp is &error_fatal. + * Errors get passed to the caller through the conventional @errp + * parameter. * * Create a new error and pass it to the caller: * error_setg(errp, "situation normal, all fouled up"); * - * Call a function and receive an error from it: - * Error *err = NULL; - * foo(arg, &err); - * if (err) { + * Call a function, receive an error from it, and pass it to the caller + * - when the function returns a value that indicates failure, say + * false: + * if (!foo(arg, errp)) { * handle the error... * } + * - when it does not, say because it is a void function: + * ERRP_GUARD(); + * foo(arg, errp); + * if (*errp) { + * handle the error... + * } + * More on ERRP_GUARD() below. * - * Call a function ignoring errors: - * foo(arg, NULL); - * - * Call a function aborting on errors: - * foo(arg, &error_abort); - * - * Call a function treating errors as fatal: - * foo(arg, &error_fatal); - * - * Receive an error and pass it on to the caller: + * Code predating ERRP_GUARD() still exists, and looks like this: * Error *err = NULL; * foo(arg, &err); * if (err) { * handle the error... - * error_propagate(errp, err); + * error_propagate(errp, err); // deprecated * } - * where Error **errp is a parameter, by convention the last one. - * - * Do *not* "optimize" this to + * Avoid in new code. Do *not* "optimize" it to * foo(arg, errp); * if (*errp) { // WRONG! * handle the error... * } - * because errp may be NULL! + * because errp may be NULL without the ERRP_GUARD() guard. * * But when all you do with the error is pass it on, please use * foo(arg, errp); * for readability. * + * Receive an error, and handle it locally + * - when the function returns a value that indicates failure, say + * false: + * Error *err = NULL; + * if (!foo(arg, &err)) { + * handle the error... + * } + * - when it does not, say because it is a void function: + * Error *err = NULL; + * foo(arg, &err); + * if (err) { + * handle the error... + * } + * + * Pass an existing error to the caller: + * error_propagate(errp, err); + * This is rarely needed. When @err is a local variable, use of + * ERRP_GUARD() commonly results in more readable code. + * + * Pass an existing error to the caller with the message modified: + * error_propagate_prepend(errp, err, + * "Could not frobnicate '%s': ", name); + * This is more concise than + * error_propagate(errp, err); // don't do this + * error_prepend(errp, "Could not frobnicate '%s': ", name); + * and works even when @errp is &error_fatal. + * * Receive and accumulate multiple errors (first one wins): * Error *err = NULL, *local_err = NULL; * foo(arg, &err); @@ -108,12 +185,88 @@ * } * * Do *not* "optimize" this to + * Error *err = NULL; * foo(arg, &err); * bar(arg, &err); // WRONG! * if (err) { * handle the error... * } * because this may pass a non-null err to bar(). + * + * Likewise, do *not* + * Error *err = NULL; + * if (cond1) { + * error_setg(&err, ...); + * } + * if (cond2) { + * error_setg(&err, ...); // WRONG! + * } + * because this may pass a non-null err to error_setg(). + * + * = Why, when and how to use ERRP_GUARD() = + * + * Without ERRP_GUARD(), use of the @errp parameter is restricted: + * - It must not be dereferenced, because it may be null. + * - It should not be passed to error_prepend() or + * error_append_hint(), because that doesn't work with &error_fatal. + * ERRP_GUARD() lifts these restrictions. + * + * To use ERRP_GUARD(), add it right at the beginning of the function. + * @errp can then be used without worrying about the argument being + * NULL or &error_fatal. + * + * Using it when it's not needed is safe, but please avoid cluttering + * the source with useless code. + * + * = Converting to ERRP_GUARD() = + * + * To convert a function to use ERRP_GUARD(): + * + * 0. If the Error ** parameter is not named @errp, rename it to + * @errp. + * + * 1. Add an ERRP_GUARD() invocation, by convention right at the + * beginning of the function. This makes @errp safe to use. + * + * 2. Replace &err by errp, and err by *errp. Delete local variable + * @err. + * + * 3. Delete error_propagate(errp, *errp), replace + * error_propagate_prepend(errp, *errp, ...) by error_prepend(errp, ...) + * + * 4. Ensure @errp is valid at return: when you destroy *errp, set + * errp = NULL. + * + * Example: + * + * bool fn(..., Error **errp) + * { + * Error *err = NULL; + * + * foo(arg, &err); + * if (err) { + * handle the error... + * error_propagate(errp, err); + * return false; + * } + * ... + * } + * + * becomes + * + * bool fn(..., Error **errp) + * { + * ERRP_GUARD(); + * + * foo(arg, errp); + * if (*errp) { + * handle the error... + * return false; + * } + * ... + * } + * + * For mass-conversion, use scripts/coccinelle/errp-guard.cocci. */ #ifndef ERROR_H @@ -214,6 +367,7 @@ void error_setg_win32_internal(Error **errp, * the error object. * Else, move the error object from @local_err to *@dst_errp. * On return, @local_err is invalid. + * Please use ERRP_GUARD() instead when possible. * Please don't error_propagate(&error_fatal, ...), use * error_report_err() and exit(), because that's more obvious. */ @@ -225,15 +379,18 @@ void error_propagate(Error **dst_errp, Error *local_err); * Behaves like * error_prepend(&local_err, fmt, ...); * error_propagate(dst_errp, local_err); + * Please use ERRP_GUARD() and error_prepend() instead when possible. */ void error_propagate_prepend(Error **dst_errp, Error *local_err, - const char *fmt, ...); + const char *fmt, ...) + GCC_FMT_ATTR(3, 4); /* * Prepend some text to @errp's human-readable error message. * The text is made by formatting @fmt, @ap like vprintf(). */ -void error_vprepend(Error *const *errp, const char *fmt, va_list ap); +void error_vprepend(Error *const *errp, const char *fmt, va_list ap) + GCC_FMT_ATTR(2, 0); /* * Prepend some text to @errp's human-readable error message. @@ -322,6 +479,46 @@ void error_set_internal(Error **errp, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(6, 7); +/* + * Make @errp parameter easier to use regardless of argument value + * + * This macro is for use right at the beginning of a function that + * takes an Error **errp parameter to pass errors to its caller. The + * parameter must be named @errp. + * + * It must be used when the function dereferences @errp or passes + * @errp to error_prepend(), error_vprepend(), or error_append_hint(). + * It is safe to use even when it's not needed, but please avoid + * cluttering the source with useless code. + * + * If @errp is NULL or &error_fatal, rewrite it to point to a local + * Error variable, which will be automatically propagated to the + * original @errp on function exit. + * + * Note: &error_abort is not rewritten, because that would move the + * abort from the place where the error is created to the place where + * it's propagated. + */ +#define ERRP_GUARD() \ + g_auto(ErrorPropagator) _auto_errp_prop = {.errp = errp}; \ + do { \ + if (!errp || errp == &error_fatal) { \ + errp = &_auto_errp_prop.local_err; \ + } \ + } while (0) + +typedef struct ErrorPropagator { + Error *local_err; + Error **errp; +} ErrorPropagator; + +static inline void error_propagator_cleanup(ErrorPropagator *prop) +{ + error_propagate(prop->errp, prop->local_err); +} + +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ErrorPropagator, error_propagator_cleanup); + /* * Special error destination to abort on error. * See error_setg() and error_propagate() for details. diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 5a9cf8247230c0cbeef3d2f443f597fcbacbef42..af8d96c570ef5bc6997349f76529281be86e479c 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -14,6 +14,7 @@ #ifndef QAPI_QMP_DISPATCH_H #define QAPI_QMP_DISPATCH_H +#include "monitor/monitor.h" #include "qemu/queue.h" typedef void (QmpCommandFunc)(QDict *, QObject **, Error **); @@ -24,11 +25,13 @@ typedef enum QmpCommandOptions QCO_NO_SUCCESS_RESP = (1U << 0), QCO_ALLOW_OOB = (1U << 1), QCO_ALLOW_PRECONFIG = (1U << 2), + QCO_COROUTINE = (1U << 3), } QmpCommandOptions; typedef struct QmpCommand { const char *name; + /* Runs in coroutine context if QCO_COROUTINE is set */ QmpCommandFunc *fn; QmpCommandOptions options; QTAILQ_ENTRY(QmpCommand) node; @@ -49,7 +52,7 @@ const char *qmp_command_name(const QmpCommand *cmd); bool qmp_has_success_response(const QmpCommand *cmd); QDict *qmp_error_response(Error *err); QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request, - bool allow_oob); + bool allow_oob, Monitor *cur_mon); bool qmp_is_oob(const QDict *dict); typedef void (*qmp_cmd_callback_fn)(const QmpCommand *cmd, void *opaque); diff --git a/include/qapi/util.h b/include/qapi/util.h index a7c3c641487462c0945ab1ee71bb6fdf1adb33ed..6178e98e97a5a31c3551e0bce8a9c72d149d8d88 100644 --- a/include/qapi/util.h +++ b/include/qapi/util.h @@ -19,7 +19,22 @@ typedef struct QEnumLookup { const char *qapi_enum_lookup(const QEnumLookup *lookup, int val); int qapi_enum_parse(const QEnumLookup *lookup, const char *buf, int def, Error **errp); +bool qapi_bool_parse(const char *name, const char *value, bool *obj, + Error **errp); int parse_qapi_name(const char *name, bool complete); +/* + * For any GenericList @list, insert @element at the front. + * + * Note that this macro evaluates @element exactly once, so it is safe + * to have side-effects with that argument. + */ +#define QAPI_LIST_PREPEND(list, element) do { \ + typeof(list) _tmp = g_malloc(sizeof(*(list))); \ + _tmp->value = (element); \ + _tmp->next = (list); \ + (list) = _tmp; \ +} while (0) + #endif diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h index 98dc533d39df08dfe36820697d41f723e56df2d8..7362c043be8e4da1dc16696fb15870d5ec7428c4 100644 --- a/include/qapi/visitor-impl.h +++ b/include/qapi/visitor-impl.h @@ -48,31 +48,31 @@ struct Visitor */ /* Must be set to visit structs */ - void (*start_struct)(Visitor *v, const char *name, void **obj, + bool (*start_struct)(Visitor *v, const char *name, void **obj, size_t size, Error **errp); /* Optional; intended for input visitors */ - void (*check_struct)(Visitor *v, Error **errp); + bool (*check_struct)(Visitor *v, Error **errp); /* Must be set to visit structs */ void (*end_struct)(Visitor *v, void **obj); /* Must be set; implementations may require @list to be non-null, * but must document it. */ - void (*start_list)(Visitor *v, const char *name, GenericList **list, + bool (*start_list)(Visitor *v, const char *name, GenericList **list, size_t size, Error **errp); /* Must be set */ GenericList *(*next_list)(Visitor *v, GenericList *tail, size_t size); /* Optional; intended for input visitors */ - void (*check_list)(Visitor *v, Error **errp); + bool (*check_list)(Visitor *v, Error **errp); /* Must be set */ void (*end_list)(Visitor *v, void **list); /* Must be set by input and clone visitors to visit alternates */ - void (*start_alternate)(Visitor *v, const char *name, + bool (*start_alternate)(Visitor *v, const char *name, GenericAlternate **obj, size_t size, Error **errp); @@ -80,33 +80,33 @@ struct Visitor void (*end_alternate)(Visitor *v, void **obj); /* Must be set */ - void (*type_int64)(Visitor *v, const char *name, int64_t *obj, + bool (*type_int64)(Visitor *v, const char *name, int64_t *obj, Error **errp); /* Must be set */ - void (*type_uint64)(Visitor *v, const char *name, uint64_t *obj, + bool (*type_uint64)(Visitor *v, const char *name, uint64_t *obj, Error **errp); /* Optional; fallback is type_uint64() */ - void (*type_size)(Visitor *v, const char *name, uint64_t *obj, + bool (*type_size)(Visitor *v, const char *name, uint64_t *obj, Error **errp); /* Must be set */ - void (*type_bool)(Visitor *v, const char *name, bool *obj, Error **errp); + bool (*type_bool)(Visitor *v, const char *name, bool *obj, Error **errp); /* Must be set */ - void (*type_str)(Visitor *v, const char *name, char **obj, Error **errp); + bool (*type_str)(Visitor *v, const char *name, char **obj, Error **errp); /* Must be set to visit numbers */ - void (*type_number)(Visitor *v, const char *name, double *obj, + bool (*type_number)(Visitor *v, const char *name, double *obj, Error **errp); /* Must be set to visit arbitrary QTypes */ - void (*type_any)(Visitor *v, const char *name, QObject **obj, + bool (*type_any)(Visitor *v, const char *name, QObject **obj, Error **errp); /* Must be set to visit explicit null values. */ - void (*type_null)(Visitor *v, const char *name, QNull **obj, + bool (*type_null)(Visitor *v, const char *name, QNull **obj, Error **errp); /* Must be set for input visitors to visit structs, optional otherwise. diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index 55739069660d08e6229461ff595ac07a6bdb0649..ebc19ede7fff4cbae0ab7d968bec8ed6774f2896 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -60,7 +60,7 @@ * All QAPI types have a corresponding function with a signature * roughly compatible with this: * - * void visit_type_FOO(Visitor *v, const char *name, T obj, Error **errp); + * bool visit_type_FOO(Visitor *v, const char *name, T obj, Error **errp); * * where T is FOO for scalar types, and FOO * otherwise. The scalar * visitors are declared here; the remaining visitors are generated in @@ -95,14 +95,16 @@ * incomplete object, such an object is possible only by manual * construction. * + * visit_type_FOO() returns true on success, false on error. + * * For the QAPI object types (structs, unions, and alternates), there * is an additional generated function in qapi-visit-MODULE.h * compatible with: * - * void visit_type_FOO_members(Visitor *v, FOO *obj, Error **errp); + * bool visit_type_FOO_members(Visitor *v, FOO *obj, Error **errp); * * for visiting the members of a type without also allocating the QAPI - * struct. + * struct. It also returns true on success, false on error. * * Additionally, QAPI pointer types (structs, unions, alternates, and * lists) have a generated function in qapi-types-MODULE.h compatible @@ -131,8 +133,7 @@ * Visitor *v; * * v = FOO_visitor_new(...); - * visit_type_Foo(v, NULL, &f, &err); - * if (err) { + * if (!visit_type_Foo(v, NULL, &f, &err)) { * ...handle error... * } else { * ...use f... @@ -148,8 +149,7 @@ * Visitor *v; * * v = FOO_visitor_new(...); - * visit_type_FooList(v, NULL, &l, &err); - * if (err) { + * if (!visit_type_FooList(v, NULL, &l, &err)) { * ...handle error... * } else { * for ( ; l; l = l->next) { @@ -186,34 +186,32 @@ * * Visitor *v; * Error *err = NULL; + * bool ok = false; * int value; * * v = FOO_visitor_new(...); - * visit_start_struct(v, NULL, NULL, 0, &err); - * if (err) { + * if (!visit_start_struct(v, NULL, NULL, 0, &err)) { * goto out; * } - * visit_start_list(v, "list", NULL, 0, &err); - * if (err) { + * if (!visit_start_list(v, "list", NULL, 0, &err)) { * goto outobj; * } * value = 1; - * visit_type_int(v, NULL, &value, &err); - * if (err) { + * if (!visit_type_int(v, NULL, &value, &err)) { * goto outlist; * } * value = 2; - * visit_type_int(v, NULL, &value, &err); - * if (err) { + * if (!visit_type_int(v, NULL, &value, &err)) { * goto outlist; * } + * ok = true; * outlist: - * if (!err) { - * visit_check_list(v, &err); + * if (ok) { + * ok = visit_check_list(v, &err); * } * visit_end_list(v, NULL); - * if (!err) { - * visit_check_struct(v, &err); + * if (ok) { + * ok = visit_check_struct(v, &err); * } * outobj: * visit_end_struct(v, NULL); @@ -286,6 +284,8 @@ void visit_free(Visitor *v); * On failure, set *@obj to NULL and store an error through @errp. * Can happen only when @v is an input visitor. * + * Return true on success, false on failure. + * * After visit_start_struct() succeeds, the caller may visit its * members one after the other, passing the member's name and address * within the struct. Finally, visit_end_struct() needs to be called @@ -295,7 +295,7 @@ void visit_free(Visitor *v); * FIXME Should this be named visit_start_object, since it is also * used for QAPI unions, and maps to JSON objects? */ -void visit_start_struct(Visitor *v, const char *name, void **obj, +bool visit_start_struct(Visitor *v, const char *name, void **obj, size_t size, Error **errp); /* @@ -304,12 +304,14 @@ void visit_start_struct(Visitor *v, const char *name, void **obj, * On failure, store an error through @errp. Can happen only when @v * is an input visitor. * + * Return true on success, false on failure. + * * Should be called prior to visit_end_struct() if all other * intermediate visit steps were successful, to allow the visitor one * last chance to report errors. May be skipped on a cleanup path, * where there is no need to check for further errors. */ -void visit_check_struct(Visitor *v, Error **errp); +bool visit_check_struct(Visitor *v, Error **errp); /* * Complete an object visit started earlier. @@ -341,6 +343,8 @@ void visit_end_struct(Visitor *v, void **obj); * On failure, set *@list to NULL and store an error through @errp. * Can happen only when @v is an input visitor. * + * Return true on success, false on failure. + * * After visit_start_list() succeeds, the caller may visit its members * one after the other. A real visit (where @list is non-NULL) uses * visit_next_list() for traversing the linked list, while a virtual @@ -351,7 +355,7 @@ void visit_end_struct(Visitor *v, void **obj); * same @list to clean up, even if intermediate visits fail. See the * examples above. */ -void visit_start_list(Visitor *v, const char *name, GenericList **list, +bool visit_start_list(Visitor *v, const char *name, GenericList **list, size_t size, Error **errp); /* @@ -376,12 +380,14 @@ GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size); * On failure, store an error through @errp. Can happen only when @v * is an input visitor. * + * Return true on success, false on failure. + * * Should be called prior to visit_end_list() if all other * intermediate visit steps were successful, to allow the visitor one * last chance to report errors. May be skipped on a cleanup path, * where there is no need to check for further errors. */ -void visit_check_list(Visitor *v, Error **errp); +bool visit_check_list(Visitor *v, Error **errp); /* * Complete a list visit started earlier. @@ -412,11 +418,13 @@ void visit_end_list(Visitor *v, void **list); * On failure, set *@obj to NULL and store an error through @errp. * Can happen only when @v is an input visitor. * + * Return true on success, false on failure. + * * If successful, this must be paired with visit_end_alternate() with * the same @obj to clean up, even if visiting the contents of the * alternate fails. */ -void visit_start_alternate(Visitor *v, const char *name, +bool visit_start_alternate(Visitor *v, const char *name, GenericAlternate **obj, size_t size, Error **errp); @@ -468,12 +476,14 @@ bool visit_optional(Visitor *v, const char *name, bool *present); * On failure, store an error through @errp. Can happen only when @v * is an input visitor. * + * Return true on success, false on failure. + * * May call visit_type_str() under the hood, and the enum visit may * fail even if the corresponding string visit succeeded; this implies * that an input visitor's visit_type_str() must have no unwelcome * side effects. */ -void visit_type_enum(Visitor *v, const char *name, int *obj, +bool visit_type_enum(Visitor *v, const char *name, int *obj, const QEnumLookup *lookup, Error **errp); /* @@ -499,28 +509,30 @@ bool visit_is_dealloc(Visitor *v); * * On failure, store an error through @errp. Can happen only when @v * is an input visitor. + * + * Return true on success, false on failure. */ -void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp); +bool visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp); /* * Visit a uint8_t value. * Like visit_type_int(), except clamps the value to uint8_t range. */ -void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj, +bool visit_type_uint8(Visitor *v, const char *name, uint8_t *obj, Error **errp); /* * Visit a uint16_t value. * Like visit_type_int(), except clamps the value to uint16_t range. */ -void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj, +bool visit_type_uint16(Visitor *v, const char *name, uint16_t *obj, Error **errp); /* * Visit a uint32_t value. * Like visit_type_int(), except clamps the value to uint32_t range. */ -void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj, +bool visit_type_uint32(Visitor *v, const char *name, uint32_t *obj, Error **errp); /* @@ -528,34 +540,34 @@ void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj, * Like visit_type_int(), except clamps the value to uint64_t range, * that is, ensures it is unsigned. */ -void visit_type_uint64(Visitor *v, const char *name, uint64_t *obj, +bool visit_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp); /* * Visit an int8_t value. * Like visit_type_int(), except clamps the value to int8_t range. */ -void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp); +bool visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp); /* * Visit an int16_t value. * Like visit_type_int(), except clamps the value to int16_t range. */ -void visit_type_int16(Visitor *v, const char *name, int16_t *obj, +bool visit_type_int16(Visitor *v, const char *name, int16_t *obj, Error **errp); /* * Visit an int32_t value. * Like visit_type_int(), except clamps the value to int32_t range. */ -void visit_type_int32(Visitor *v, const char *name, int32_t *obj, +bool visit_type_int32(Visitor *v, const char *name, int32_t *obj, Error **errp); /* * Visit an int64_t value. * Identical to visit_type_int(). */ -void visit_type_int64(Visitor *v, const char *name, int64_t *obj, +bool visit_type_int64(Visitor *v, const char *name, int64_t *obj, Error **errp); /* @@ -564,7 +576,7 @@ void visit_type_int64(Visitor *v, const char *name, int64_t *obj, * recognize additional syntax, such as suffixes for easily scaling * values. */ -void visit_type_size(Visitor *v, const char *name, uint64_t *obj, +bool visit_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp); /* @@ -578,8 +590,10 @@ void visit_type_size(Visitor *v, const char *name, uint64_t *obj, * * On failure, store an error through @errp. Can happen only when @v * is an input visitor. + * + * Return true on success, false on failure. */ -void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp); +bool visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp); /* * Visit a string value. @@ -598,9 +612,11 @@ void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp); * On failure, set *@obj to NULL and store an error through @errp. * Can happen only when @v is an input visitor. * + * Return true on success, false on failure. + * * FIXME: Callers that try to output NULL *obj should not be allowed. */ -void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp); +bool visit_type_str(Visitor *v, const char *name, char **obj, Error **errp); /* * Visit a number (i.e. double) value. @@ -614,8 +630,10 @@ void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp); * * On failure, store an error through @errp. Can happen only when @v * is an input visitor. + * + * Return true on success, false on failure. */ -void visit_type_number(Visitor *v, const char *name, double *obj, +bool visit_type_number(Visitor *v, const char *name, double *obj, Error **errp); /* @@ -631,11 +649,13 @@ void visit_type_number(Visitor *v, const char *name, double *obj, * On failure, set *@obj to NULL and store an error through @errp. * Can happen only when @v is an input visitor. * + * Return true on success, false on failure. + * * Note that some kinds of input can't express arbitrary QObject. * E.g. the visitor returned by qobject_input_visitor_new_keyval() * can't create numbers or booleans, only strings. */ -void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp); +bool visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp); /* * Visit a JSON null value. @@ -648,8 +668,10 @@ void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp); * * On failure, set *@obj to NULL and store an error through @errp. * Can happen only when @v is an input visitor. + * + * Return true on success, false on failure. */ -void visit_type_null(Visitor *v, const char *name, QNull **obj, +bool visit_type_null(Visitor *v, const char *name, QNull **obj, Error **errp); #endif diff --git a/include/qemu-common.h b/include/qemu-common.h index d0142f29ac1a3a3a85d7d88b3dd9c2eaa6e75edd..fda7dc6ca77b88f4e381622e3a29e8e18fd1b90f 100644 --- a/include/qemu-common.h +++ b/include/qemu-common.h @@ -110,18 +110,43 @@ const char *qemu_get_vm_name(void); #define QEMU_FILE_TYPE_BIOS 0 #define QEMU_FILE_TYPE_KEYMAP 1 +/** + * qemu_find_file: + * @type: QEMU_FILE_TYPE_BIOS (for BIOS, VGA BIOS) + * or QEMU_FILE_TYPE_KEYMAP (for keymaps). + * @name: Relative or absolute file name + * + * If @name exists on disk as an absolute path, or a path relative + * to the current directory, then returns @name unchanged. + * Otherwise searches for @name file in the data directories, either + * configured at build time (DATADIR) or registered with the -L command + * line option. + * + * The caller must use g_free() to free the returned data when it is + * no longer required. + * + * Returns: a path that can access @name, or NULL if no matching file exists. + */ char *qemu_find_file(int type, const char *name); /* OS specific functions */ void os_setup_early_signal_handling(void); -char *os_find_datadir(void); int os_parse_cmd_args(int index, const char *optarg); +/* + * Hexdump a line of a byte buffer into a hexadecimal/ASCII buffer + */ +#define QEMU_HEXDUMP_LINE_BYTES 16 /* Number of bytes to dump */ +#define QEMU_HEXDUMP_LINE_LEN 75 /* Number of characters in line */ +void qemu_hexdump_line(char *line, unsigned int b, const void *bufptr, + unsigned int len, bool ascii); + /* * Hexdump a buffer to a file. An optional string prefix is added to every line */ -void qemu_hexdump(const char *buf, FILE *fp, const char *prefix, size_t size); +void qemu_hexdump(FILE *fp, const char *prefix, + const void *bufptr, size_t size); /* * helper to parse debug environment variables diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h index ff72db51154ca9aeab8e46cfb548d594ef9e95f8..c1d211a351998e67d00202b6c4bcf0f04d68c94a 100644 --- a/include/qemu/atomic.h +++ b/include/qemu/atomic.h @@ -125,49 +125,49 @@ * no effect on the generated code but not using the atomic primitives * will get flagged by sanitizers as a violation. */ -#define atomic_read__nocheck(ptr) \ +#define qatomic_read__nocheck(ptr) \ __atomic_load_n(ptr, __ATOMIC_RELAXED) -#define atomic_read(ptr) \ - ({ \ +#define qatomic_read(ptr) \ + ({ \ QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \ - atomic_read__nocheck(ptr); \ + qatomic_read__nocheck(ptr); \ }) -#define atomic_set__nocheck(ptr, i) \ +#define qatomic_set__nocheck(ptr, i) \ __atomic_store_n(ptr, i, __ATOMIC_RELAXED) -#define atomic_set(ptr, i) do { \ +#define qatomic_set(ptr, i) do { \ QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \ - atomic_set__nocheck(ptr, i); \ + qatomic_set__nocheck(ptr, i); \ } while(0) /* See above: most compilers currently treat consume and acquire the - * same, but this slows down atomic_rcu_read unnecessarily. + * same, but this slows down qatomic_rcu_read unnecessarily. */ #ifdef __SANITIZE_THREAD__ -#define atomic_rcu_read__nocheck(ptr, valptr) \ +#define qatomic_rcu_read__nocheck(ptr, valptr) \ __atomic_load(ptr, valptr, __ATOMIC_CONSUME); #else -#define atomic_rcu_read__nocheck(ptr, valptr) \ - __atomic_load(ptr, valptr, __ATOMIC_RELAXED); \ +#define qatomic_rcu_read__nocheck(ptr, valptr) \ + __atomic_load(ptr, valptr, __ATOMIC_RELAXED); \ smp_read_barrier_depends(); #endif -#define atomic_rcu_read(ptr) \ - ({ \ +#define qatomic_rcu_read(ptr) \ + ({ \ QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \ - typeof_strip_qual(*ptr) _val; \ - atomic_rcu_read__nocheck(ptr, &_val); \ - _val; \ + typeof_strip_qual(*ptr) _val; \ + qatomic_rcu_read__nocheck(ptr, &_val); \ + _val; \ }) -#define atomic_rcu_set(ptr, i) do { \ +#define qatomic_rcu_set(ptr, i) do { \ QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \ - __atomic_store_n(ptr, i, __ATOMIC_RELEASE); \ + __atomic_store_n(ptr, i, __ATOMIC_RELEASE); \ } while(0) -#define atomic_load_acquire(ptr) \ +#define qatomic_load_acquire(ptr) \ ({ \ QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \ typeof_strip_qual(*ptr) _val; \ @@ -175,7 +175,7 @@ _val; \ }) -#define atomic_store_release(ptr, i) do { \ +#define qatomic_store_release(ptr, i) do { \ QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \ __atomic_store_n(ptr, i, __ATOMIC_RELEASE); \ } while(0) @@ -183,56 +183,61 @@ /* All the remaining operations are fully sequentially consistent */ -#define atomic_xchg__nocheck(ptr, i) ({ \ +#define qatomic_xchg__nocheck(ptr, i) ({ \ __atomic_exchange_n(ptr, (i), __ATOMIC_SEQ_CST); \ }) -#define atomic_xchg(ptr, i) ({ \ +#define qatomic_xchg(ptr, i) ({ \ QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \ - atomic_xchg__nocheck(ptr, i); \ + qatomic_xchg__nocheck(ptr, i); \ }) /* Returns the eventual value, failed or not */ -#define atomic_cmpxchg__nocheck(ptr, old, new) ({ \ +#define qatomic_cmpxchg__nocheck(ptr, old, new) ({ \ typeof_strip_qual(*ptr) _old = (old); \ (void)__atomic_compare_exchange_n(ptr, &_old, new, false, \ __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); \ _old; \ }) -#define atomic_cmpxchg(ptr, old, new) ({ \ +#define qatomic_cmpxchg(ptr, old, new) ({ \ QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \ - atomic_cmpxchg__nocheck(ptr, old, new); \ + qatomic_cmpxchg__nocheck(ptr, old, new); \ }) /* Provide shorter names for GCC atomic builtins, return old value */ -#define atomic_fetch_inc(ptr) __atomic_fetch_add(ptr, 1, __ATOMIC_SEQ_CST) -#define atomic_fetch_dec(ptr) __atomic_fetch_sub(ptr, 1, __ATOMIC_SEQ_CST) - -#ifndef atomic_fetch_add -#define atomic_fetch_add(ptr, n) __atomic_fetch_add(ptr, n, __ATOMIC_SEQ_CST) -#define atomic_fetch_sub(ptr, n) __atomic_fetch_sub(ptr, n, __ATOMIC_SEQ_CST) -#define atomic_fetch_and(ptr, n) __atomic_fetch_and(ptr, n, __ATOMIC_SEQ_CST) -#define atomic_fetch_or(ptr, n) __atomic_fetch_or(ptr, n, __ATOMIC_SEQ_CST) -#define atomic_fetch_xor(ptr, n) __atomic_fetch_xor(ptr, n, __ATOMIC_SEQ_CST) -#endif - -#define atomic_inc_fetch(ptr) __atomic_add_fetch(ptr, 1, __ATOMIC_SEQ_CST) -#define atomic_dec_fetch(ptr) __atomic_sub_fetch(ptr, 1, __ATOMIC_SEQ_CST) -#define atomic_add_fetch(ptr, n) __atomic_add_fetch(ptr, n, __ATOMIC_SEQ_CST) -#define atomic_sub_fetch(ptr, n) __atomic_sub_fetch(ptr, n, __ATOMIC_SEQ_CST) -#define atomic_and_fetch(ptr, n) __atomic_and_fetch(ptr, n, __ATOMIC_SEQ_CST) -#define atomic_or_fetch(ptr, n) __atomic_or_fetch(ptr, n, __ATOMIC_SEQ_CST) -#define atomic_xor_fetch(ptr, n) __atomic_xor_fetch(ptr, n, __ATOMIC_SEQ_CST) +#define qatomic_fetch_inc(ptr) __atomic_fetch_add(ptr, 1, __ATOMIC_SEQ_CST) +#define qatomic_fetch_dec(ptr) __atomic_fetch_sub(ptr, 1, __ATOMIC_SEQ_CST) + +#define qatomic_fetch_add(ptr, n) __atomic_fetch_add(ptr, n, __ATOMIC_SEQ_CST) +#define qatomic_fetch_sub(ptr, n) __atomic_fetch_sub(ptr, n, __ATOMIC_SEQ_CST) +#define qatomic_fetch_and(ptr, n) __atomic_fetch_and(ptr, n, __ATOMIC_SEQ_CST) +#define qatomic_fetch_or(ptr, n) __atomic_fetch_or(ptr, n, __ATOMIC_SEQ_CST) +#define qatomic_fetch_xor(ptr, n) __atomic_fetch_xor(ptr, n, __ATOMIC_SEQ_CST) + +#define qatomic_inc_fetch(ptr) __atomic_add_fetch(ptr, 1, __ATOMIC_SEQ_CST) +#define qatomic_dec_fetch(ptr) __atomic_sub_fetch(ptr, 1, __ATOMIC_SEQ_CST) +#define qatomic_add_fetch(ptr, n) __atomic_add_fetch(ptr, n, __ATOMIC_SEQ_CST) +#define qatomic_sub_fetch(ptr, n) __atomic_sub_fetch(ptr, n, __ATOMIC_SEQ_CST) +#define qatomic_and_fetch(ptr, n) __atomic_and_fetch(ptr, n, __ATOMIC_SEQ_CST) +#define qatomic_or_fetch(ptr, n) __atomic_or_fetch(ptr, n, __ATOMIC_SEQ_CST) +#define qatomic_xor_fetch(ptr, n) __atomic_xor_fetch(ptr, n, __ATOMIC_SEQ_CST) /* And even shorter names that return void. */ -#define atomic_inc(ptr) ((void) __atomic_fetch_add(ptr, 1, __ATOMIC_SEQ_CST)) -#define atomic_dec(ptr) ((void) __atomic_fetch_sub(ptr, 1, __ATOMIC_SEQ_CST)) -#define atomic_add(ptr, n) ((void) __atomic_fetch_add(ptr, n, __ATOMIC_SEQ_CST)) -#define atomic_sub(ptr, n) ((void) __atomic_fetch_sub(ptr, n, __ATOMIC_SEQ_CST)) -#define atomic_and(ptr, n) ((void) __atomic_fetch_and(ptr, n, __ATOMIC_SEQ_CST)) -#define atomic_or(ptr, n) ((void) __atomic_fetch_or(ptr, n, __ATOMIC_SEQ_CST)) -#define atomic_xor(ptr, n) ((void) __atomic_fetch_xor(ptr, n, __ATOMIC_SEQ_CST)) +#define qatomic_inc(ptr) \ + ((void) __atomic_fetch_add(ptr, 1, __ATOMIC_SEQ_CST)) +#define qatomic_dec(ptr) \ + ((void) __atomic_fetch_sub(ptr, 1, __ATOMIC_SEQ_CST)) +#define qatomic_add(ptr, n) \ + ((void) __atomic_fetch_add(ptr, n, __ATOMIC_SEQ_CST)) +#define qatomic_sub(ptr, n) \ + ((void) __atomic_fetch_sub(ptr, n, __ATOMIC_SEQ_CST)) +#define qatomic_and(ptr, n) \ + ((void) __atomic_fetch_and(ptr, n, __ATOMIC_SEQ_CST)) +#define qatomic_or(ptr, n) \ + ((void) __atomic_fetch_or(ptr, n, __ATOMIC_SEQ_CST)) +#define qatomic_xor(ptr, n) \ + ((void) __atomic_fetch_xor(ptr, n, __ATOMIC_SEQ_CST)) #else /* __ATOMIC_RELAXED */ @@ -272,7 +277,7 @@ * but it is a full barrier at the hardware level. Add a compiler barrier * to make it a full barrier also at the compiler level. */ -#define atomic_xchg(ptr, i) (barrier(), __sync_lock_test_and_set(ptr, i)) +#define qatomic_xchg(ptr, i) (barrier(), __sync_lock_test_and_set(ptr, i)) #elif defined(_ARCH_PPC) @@ -325,14 +330,14 @@ /* These will only be atomic if the processor does the fetch or store * in a single issue memory operation */ -#define atomic_read__nocheck(p) (*(__typeof__(*(p)) volatile*) (p)) -#define atomic_set__nocheck(p, i) ((*(__typeof__(*(p)) volatile*) (p)) = (i)) +#define qatomic_read__nocheck(p) (*(__typeof__(*(p)) volatile*) (p)) +#define qatomic_set__nocheck(p, i) ((*(__typeof__(*(p)) volatile*) (p)) = (i)) -#define atomic_read(ptr) atomic_read__nocheck(ptr) -#define atomic_set(ptr, i) atomic_set__nocheck(ptr,i) +#define qatomic_read(ptr) qatomic_read__nocheck(ptr) +#define qatomic_set(ptr, i) qatomic_set__nocheck(ptr,i) /** - * atomic_rcu_read - reads a RCU-protected pointer to a local variable + * qatomic_rcu_read - reads a RCU-protected pointer to a local variable * into a RCU read-side critical section. The pointer can later be safely * dereferenced within the critical section. * @@ -342,21 +347,21 @@ * Inserts memory barriers on architectures that require them (currently only * Alpha) and documents which pointers are protected by RCU. * - * atomic_rcu_read also includes a compiler barrier to ensure that + * qatomic_rcu_read also includes a compiler barrier to ensure that * value-speculative optimizations (e.g. VSS: Value Speculation * Scheduling) does not perform the data read before the pointer read * by speculating the value of the pointer. * - * Should match atomic_rcu_set(), atomic_xchg(), atomic_cmpxchg(). + * Should match qatomic_rcu_set(), qatomic_xchg(), qatomic_cmpxchg(). */ -#define atomic_rcu_read(ptr) ({ \ - typeof(*ptr) _val = atomic_read(ptr); \ +#define qatomic_rcu_read(ptr) ({ \ + typeof(*ptr) _val = qatomic_read(ptr); \ smp_read_barrier_depends(); \ _val; \ }) /** - * atomic_rcu_set - assigns (publicizes) a pointer to a new data structure + * qatomic_rcu_set - assigns (publicizes) a pointer to a new data structure * meant to be read by RCU read-side critical sections. * * Documents which pointers will be dereferenced by RCU read-side critical @@ -364,65 +369,64 @@ * them. It also makes sure the compiler does not reorder code initializing the * data structure before its publication. * - * Should match atomic_rcu_read(). + * Should match qatomic_rcu_read(). */ -#define atomic_rcu_set(ptr, i) do { \ +#define qatomic_rcu_set(ptr, i) do { \ smp_wmb(); \ - atomic_set(ptr, i); \ + qatomic_set(ptr, i); \ } while (0) -#define atomic_load_acquire(ptr) ({ \ - typeof(*ptr) _val = atomic_read(ptr); \ +#define qatomic_load_acquire(ptr) ({ \ + typeof(*ptr) _val = qatomic_read(ptr); \ smp_mb_acquire(); \ _val; \ }) -#define atomic_store_release(ptr, i) do { \ +#define qatomic_store_release(ptr, i) do { \ smp_mb_release(); \ - atomic_set(ptr, i); \ + qatomic_set(ptr, i); \ } while (0) -#ifndef atomic_xchg +#ifndef qatomic_xchg #if defined(__clang__) -#define atomic_xchg(ptr, i) __sync_swap(ptr, i) +#define qatomic_xchg(ptr, i) __sync_swap(ptr, i) #else /* __sync_lock_test_and_set() is documented to be an acquire barrier only. */ -#define atomic_xchg(ptr, i) (smp_mb(), __sync_lock_test_and_set(ptr, i)) +#define qatomic_xchg(ptr, i) (smp_mb(), __sync_lock_test_and_set(ptr, i)) #endif #endif -#define atomic_xchg__nocheck atomic_xchg +#define qatomic_xchg__nocheck qatomic_xchg /* Provide shorter names for GCC atomic builtins. */ -#define atomic_fetch_inc(ptr) __sync_fetch_and_add(ptr, 1) -#define atomic_fetch_dec(ptr) __sync_fetch_and_add(ptr, -1) - -#ifndef atomic_fetch_add -#define atomic_fetch_add(ptr, n) __sync_fetch_and_add(ptr, n) -#define atomic_fetch_sub(ptr, n) __sync_fetch_and_sub(ptr, n) -#define atomic_fetch_and(ptr, n) __sync_fetch_and_and(ptr, n) -#define atomic_fetch_or(ptr, n) __sync_fetch_and_or(ptr, n) -#define atomic_fetch_xor(ptr, n) __sync_fetch_and_xor(ptr, n) -#endif - -#define atomic_inc_fetch(ptr) __sync_add_and_fetch(ptr, 1) -#define atomic_dec_fetch(ptr) __sync_add_and_fetch(ptr, -1) -#define atomic_add_fetch(ptr, n) __sync_add_and_fetch(ptr, n) -#define atomic_sub_fetch(ptr, n) __sync_sub_and_fetch(ptr, n) -#define atomic_and_fetch(ptr, n) __sync_and_and_fetch(ptr, n) -#define atomic_or_fetch(ptr, n) __sync_or_and_fetch(ptr, n) -#define atomic_xor_fetch(ptr, n) __sync_xor_and_fetch(ptr, n) - -#define atomic_cmpxchg(ptr, old, new) __sync_val_compare_and_swap(ptr, old, new) -#define atomic_cmpxchg__nocheck(ptr, old, new) atomic_cmpxchg(ptr, old, new) +#define qatomic_fetch_inc(ptr) __sync_fetch_and_add(ptr, 1) +#define qatomic_fetch_dec(ptr) __sync_fetch_and_add(ptr, -1) + +#define qatomic_fetch_add(ptr, n) __sync_fetch_and_add(ptr, n) +#define qatomic_fetch_sub(ptr, n) __sync_fetch_and_sub(ptr, n) +#define qatomic_fetch_and(ptr, n) __sync_fetch_and_and(ptr, n) +#define qatomic_fetch_or(ptr, n) __sync_fetch_and_or(ptr, n) +#define qatomic_fetch_xor(ptr, n) __sync_fetch_and_xor(ptr, n) + +#define qatomic_inc_fetch(ptr) __sync_add_and_fetch(ptr, 1) +#define qatomic_dec_fetch(ptr) __sync_add_and_fetch(ptr, -1) +#define qatomic_add_fetch(ptr, n) __sync_add_and_fetch(ptr, n) +#define qatomic_sub_fetch(ptr, n) __sync_sub_and_fetch(ptr, n) +#define qatomic_and_fetch(ptr, n) __sync_and_and_fetch(ptr, n) +#define qatomic_or_fetch(ptr, n) __sync_or_and_fetch(ptr, n) +#define qatomic_xor_fetch(ptr, n) __sync_xor_and_fetch(ptr, n) + +#define qatomic_cmpxchg(ptr, old, new) \ + __sync_val_compare_and_swap(ptr, old, new) +#define qatomic_cmpxchg__nocheck(ptr, old, new) qatomic_cmpxchg(ptr, old, new) /* And even shorter names that return void. */ -#define atomic_inc(ptr) ((void) __sync_fetch_and_add(ptr, 1)) -#define atomic_dec(ptr) ((void) __sync_fetch_and_add(ptr, -1)) -#define atomic_add(ptr, n) ((void) __sync_fetch_and_add(ptr, n)) -#define atomic_sub(ptr, n) ((void) __sync_fetch_and_sub(ptr, n)) -#define atomic_and(ptr, n) ((void) __sync_fetch_and_and(ptr, n)) -#define atomic_or(ptr, n) ((void) __sync_fetch_and_or(ptr, n)) -#define atomic_xor(ptr, n) ((void) __sync_fetch_and_xor(ptr, n)) +#define qatomic_inc(ptr) ((void) __sync_fetch_and_add(ptr, 1)) +#define qatomic_dec(ptr) ((void) __sync_fetch_and_add(ptr, -1)) +#define qatomic_add(ptr, n) ((void) __sync_fetch_and_add(ptr, n)) +#define qatomic_sub(ptr, n) ((void) __sync_fetch_and_sub(ptr, n)) +#define qatomic_and(ptr, n) ((void) __sync_fetch_and_and(ptr, n)) +#define qatomic_or(ptr, n) ((void) __sync_fetch_and_or(ptr, n)) +#define qatomic_xor(ptr, n) ((void) __sync_fetch_and_xor(ptr, n)) #endif /* __ATOMIC_RELAXED */ @@ -436,11 +440,11 @@ /* This is more efficient than a store plus a fence. */ #if !defined(__SANITIZE_THREAD__) #if defined(__i386__) || defined(__x86_64__) || defined(__s390x__) -#define atomic_mb_set(ptr, i) ((void)atomic_xchg(ptr, i)) +#define qatomic_mb_set(ptr, i) ((void)qatomic_xchg(ptr, i)) #endif #endif -/* atomic_mb_read/set semantics map Java volatile variables. They are +/* qatomic_mb_read/set semantics map Java volatile variables. They are * less expensive on some platforms (notably POWER) than fully * sequentially consistent operations. * @@ -448,58 +452,58 @@ * use. See docs/devel/atomics.txt for more discussion. */ -#ifndef atomic_mb_read -#define atomic_mb_read(ptr) \ - atomic_load_acquire(ptr) +#ifndef qatomic_mb_read +#define qatomic_mb_read(ptr) \ + qatomic_load_acquire(ptr) #endif -#ifndef atomic_mb_set -#define atomic_mb_set(ptr, i) do { \ - atomic_store_release(ptr, i); \ +#ifndef qatomic_mb_set +#define qatomic_mb_set(ptr, i) do { \ + qatomic_store_release(ptr, i); \ smp_mb(); \ } while(0) #endif -#define atomic_fetch_inc_nonzero(ptr) ({ \ - typeof_strip_qual(*ptr) _oldn = atomic_read(ptr); \ - while (_oldn && atomic_cmpxchg(ptr, _oldn, _oldn + 1) != _oldn) { \ - _oldn = atomic_read(ptr); \ +#define qatomic_fetch_inc_nonzero(ptr) ({ \ + typeof_strip_qual(*ptr) _oldn = qatomic_read(ptr); \ + while (_oldn && qatomic_cmpxchg(ptr, _oldn, _oldn + 1) != _oldn) { \ + _oldn = qatomic_read(ptr); \ } \ _oldn; \ }) /* Abstractions to access atomically (i.e. "once") i64/u64 variables */ #ifdef CONFIG_ATOMIC64 -static inline int64_t atomic_read_i64(const int64_t *ptr) +static inline int64_t qatomic_read_i64(const int64_t *ptr) { /* use __nocheck because sizeof(void *) might be < sizeof(u64) */ - return atomic_read__nocheck(ptr); + return qatomic_read__nocheck(ptr); } -static inline uint64_t atomic_read_u64(const uint64_t *ptr) +static inline uint64_t qatomic_read_u64(const uint64_t *ptr) { - return atomic_read__nocheck(ptr); + return qatomic_read__nocheck(ptr); } -static inline void atomic_set_i64(int64_t *ptr, int64_t val) +static inline void qatomic_set_i64(int64_t *ptr, int64_t val) { - atomic_set__nocheck(ptr, val); + qatomic_set__nocheck(ptr, val); } -static inline void atomic_set_u64(uint64_t *ptr, uint64_t val) +static inline void qatomic_set_u64(uint64_t *ptr, uint64_t val) { - atomic_set__nocheck(ptr, val); + qatomic_set__nocheck(ptr, val); } -static inline void atomic64_init(void) +static inline void qatomic64_init(void) { } #else /* !CONFIG_ATOMIC64 */ -int64_t atomic_read_i64(const int64_t *ptr); -uint64_t atomic_read_u64(const uint64_t *ptr); -void atomic_set_i64(int64_t *ptr, int64_t val); -void atomic_set_u64(uint64_t *ptr, uint64_t val); -void atomic64_init(void); +int64_t qatomic_read_i64(const int64_t *ptr); +uint64_t qatomic_read_u64(const uint64_t *ptr); +void qatomic_set_i64(int64_t *ptr, int64_t val); +void qatomic_set_u64(uint64_t *ptr, uint64_t val); +void qatomic64_init(void); #endif /* !CONFIG_ATOMIC64 */ #endif /* QEMU_ATOMIC_H */ diff --git a/include/qemu/atomic128.h b/include/qemu/atomic128.h index 6b34484e15ca88fb5dd70012c1d675a8d840d3dc..ad2bcf45b4f8c7c1ed18ae9b5f858c6861dc6454 100644 --- a/include/qemu/atomic128.h +++ b/include/qemu/atomic128.h @@ -44,7 +44,7 @@ #if defined(CONFIG_ATOMIC128) static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new) { - return atomic_cmpxchg__nocheck(ptr, cmp, new); + return qatomic_cmpxchg__nocheck(ptr, cmp, new); } # define HAVE_CMPXCHG128 1 #elif defined(CONFIG_CMPXCHG128) @@ -89,12 +89,12 @@ Int128 QEMU_ERROR("unsupported atomic") #if defined(CONFIG_ATOMIC128) static inline Int128 atomic16_read(Int128 *ptr) { - return atomic_read__nocheck(ptr); + return qatomic_read__nocheck(ptr); } static inline void atomic16_set(Int128 *ptr, Int128 val) { - atomic_set__nocheck(ptr, val); + qatomic_set__nocheck(ptr, val); } # define HAVE_ATOMIC128 1 diff --git a/include/qemu/base64.h b/include/qemu/base64.h index 0a3c5c9c5366a097077a6389f5632252e072d323..46a75fbbeb6645767bc4942317e36e5b2d231d0f 100644 --- a/include/qemu/base64.h +++ b/include/qemu/base64.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h index f55ce8b320b240aa29e727ecc674e1033f71e589..3acbf3384c63ce4f7d2a98db962ae999de3b2b63 100644 --- a/include/qemu/bitops.h +++ b/include/qemu/bitops.h @@ -51,7 +51,7 @@ static inline void set_bit_atomic(long nr, unsigned long *addr) unsigned long mask = BIT_MASK(nr); unsigned long *p = addr + BIT_WORD(nr); - atomic_or(p, mask); + qatomic_or(p, mask); } /** diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h index 2a9f3fe783e72b05e692bf271f2b85dbc05b50d3..8b01c38040c6ce0d3b121ef73696bceb6bde6a23 100644 --- a/include/qemu/bswap.h +++ b/include/qemu/bswap.h @@ -8,6 +8,8 @@ # include #elif defined(__FreeBSD__) # include +#elif defined(__HAIKU__) +# include #elif defined(CONFIG_BYTESWAP_H) # include @@ -167,12 +169,6 @@ CPU_CONVERT(le, 16, uint16_t) CPU_CONVERT(le, 32, uint32_t) CPU_CONVERT(le, 64, uint64_t) -/* len must be one of 1, 2, 4 */ -static inline uint32_t qemu_bswap_len(uint32_t value, int len) -{ - return bswap32(value) >> (32 - 8 * len); -} - /* * Same as cpu_to_le{16,32}, except that gcc will figure the result is * a compile-time constant if you pass in a constant. So this can be diff --git a/include/qemu/buffer.h b/include/qemu/buffer.h index 3a909aeca45e69c32d3a55868d853e4e9c6b4afb..d34d2c857ccc64cbc0780fa69e2858e234c1d7c2 100644 --- a/include/qemu/buffer.h +++ b/include/qemu/buffer.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h index dfd261c5b1f14683154ce8b0e5b937b320feaa49..84eab6e3bf7581d28083fce205c49462819bf43a 100644 --- a/include/qemu/coroutine.h +++ b/include/qemu/coroutine.h @@ -179,7 +179,7 @@ static inline coroutine_fn void qemu_co_mutex_assert_locked(CoMutex *mutex) * because the condition will be false no matter whether we read NULL or * the pointer for any other coroutine. */ - assert(atomic_read(&mutex->locked) && + assert(qatomic_read(&mutex->locked) && mutex->holder == qemu_coroutine_self()); } diff --git a/include/qemu/coroutine_int.h b/include/qemu/coroutine_int.h index bd6b0468e167ae6bf4b5e695ec30225ab7fb405f..1da148552f74b542959dd48448eb6bbc3aead935 100644 --- a/include/qemu/coroutine_int.h +++ b/include/qemu/coroutine_int.h @@ -28,6 +28,11 @@ #include "qemu/queue.h" #include "qemu/coroutine.h" +#ifdef CONFIG_SAFESTACK +/* Pointer to the unsafe stack, defined by the compiler */ +extern __thread void *__safestack_unsafe_stack_ptr; +#endif + #define COROUTINE_STACK_SIZE (1 << 20) typedef enum { diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h index eb59852dfdf2d25db25c89917ab3f79539b8c33d..986ed8e15f41248e3802b53cab08c8a939b957d6 100644 --- a/include/qemu/cutils.h +++ b/include/qemu/cutils.h @@ -158,6 +158,18 @@ int qemu_strtosz_metric(const char *nptr, const char **end, uint64_t *result); char *size_to_str(uint64_t val); +/** + * freq_to_str: + * @freq_hz: frequency to stringify + * + * Return human readable string for frequency @freq_hz. + * Use SI units like KHz, MHz, and so forth. + * + * The caller is responsible for releasing the value returned + * with g_free() after use. + */ +char *freq_to_str(uint64_t freq_hz); + /* used to print char* safely */ #define STR_OR_NULL(str) ((str) ? (str) : "null") @@ -184,4 +196,17 @@ int uleb128_decode_small(const uint8_t *in, uint32_t *n); */ int qemu_pstrcmp0(const char **str1, const char **str2); + +/** + * get_relocated_path: + * @dir: the directory (typically a `CONFIG_*DIR` variable) to be relocated. + * + * Returns a path for @dir that uses the directory of the running executable + * as the prefix. For example, if `bindir` is `/usr/bin` and @dir is + * `/usr/share/qemu`, the function will append `../share/qemu` to the + * directory that contains the running executable and return the result. + * The returned string should be freed by the caller. + */ +char *get_relocated_path(const char *dir); + #endif diff --git a/include/qemu/error-report.h b/include/qemu/error-report.h index 87532d859658db40e6a8d68b6b25f21f05021899..a5ad95ff1bb2cfbc3f0c0a0a5b9ec0a58105e136 100644 --- a/include/qemu/error-report.h +++ b/include/qemu/error-report.h @@ -75,5 +75,7 @@ void error_init(const char *argv0); const char *error_get_progname(void); extern bool error_with_timestamp; +extern bool error_with_guestname; +extern const char *error_guest_name; #endif diff --git a/include/qemu/filemonitor.h b/include/qemu/filemonitor.h index a41ceb02440e62044aab87006d122969cc79c365..8715d5c0484178a319c6c7994fc32ab24ebd94bd 100644 --- a/include/qemu/filemonitor.h +++ b/include/qemu/filemonitor.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/qemu/help_option.h b/include/qemu/help_option.h index 328d2a89fdab372493bac37813ccaecaa5ea5349..ca6389a15452aa4268e03eb671d65fa73d62ec1b 100644 --- a/include/qemu/help_option.h +++ b/include/qemu/help_option.h @@ -19,4 +19,15 @@ static inline bool is_help_option(const char *s) return !strcmp(s, "?") || !strcmp(s, "help"); } +static inline int starts_with_help_option(const char *s) +{ + if (*s == '?') { + return 1; + } + if (g_str_has_prefix(s, "help")) { + return 4; + } + return 0; +} + #endif diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h index 4cd170e6cd533fae0250ae3c9a933c3296dbf4cf..cdca2991d8a89774f3ef5f5c80e9c356519a6e8b 100644 --- a/include/qemu/host-utils.h +++ b/include/qemu/host-utils.h @@ -77,8 +77,8 @@ static inline int divs128(int64_t *plow, int64_t *phigh, int64_t divisor) } } #else -void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b); -void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b); +void muls64(uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b); +void mulu64(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b); int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor); int divs128(int64_t *plow, int64_t *phigh, int64_t divisor); diff --git a/include/qemu/int128.h b/include/qemu/int128.h index 5c9890db8b3947c1c3a2a484281ca32f2c095c02..76ea405922dc2347e02db8878e81924a1fc31375 100644 --- a/include/qemu/int128.h +++ b/include/qemu/int128.h @@ -63,6 +63,11 @@ static inline Int128 int128_rshift(Int128 a, int n) return a >> n; } +static inline Int128 int128_lshift(Int128 a, int n) +{ + return a << n; +} + static inline Int128 int128_add(Int128 a, Int128 b) { return a + b; @@ -217,6 +222,17 @@ static inline Int128 int128_rshift(Int128 a, int n) } } +static inline Int128 int128_lshift(Int128 a, int n) +{ + uint64_t l = a.lo << (n & 63); + if (n >= 64) { + return int128_make128(0, l); + } else if (n > 0) { + return int128_make128(l, (a.hi << n) | (a.lo >> (64 - n))); + } + return a; +} + static inline Int128 int128_add(Int128 a, Int128 b) { uint64_t lo = a.lo + b.lo; diff --git a/include/qemu/iov.h b/include/qemu/iov.h index bffc1512828dc161651f93d77d828a8f1637185a..b6b283a5e5c1f5b69baa2b958339fa08f5e8e734 100644 --- a/include/qemu/iov.h +++ b/include/qemu/iov.h @@ -130,6 +130,29 @@ size_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt, size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt, size_t bytes); +/* Information needed to undo an iov_discard_*() operation */ +typedef struct { + struct iovec *modified_iov; + struct iovec orig; +} IOVDiscardUndo; + +/* + * Undo an iov_discard_front_undoable() or iov_discard_back_undoable() + * operation. If multiple operations are made then each one needs a separate + * IOVDiscardUndo and iov_discard_undo() must be called in the reverse order + * that the operations were made. + */ +void iov_discard_undo(IOVDiscardUndo *undo); + +/* + * Undoable versions of iov_discard_front() and iov_discard_back(). Use + * iov_discard_undo() to reset to the state before the discard operations. + */ +size_t iov_discard_front_undoable(struct iovec **iov, unsigned int *iov_cnt, + size_t bytes, IOVDiscardUndo *undo); +size_t iov_discard_back_undoable(struct iovec *iov, unsigned int *iov_cnt, + size_t bytes, IOVDiscardUndo *undo); + typedef struct QEMUIOVector { struct iovec *iov; int niov; diff --git a/include/qemu/log.h b/include/qemu/log.h index f4724f7330116255c9d46a801c13b3ab10ef9dac..9b8066020729a7d027fd4eab9ab39de79ce7b5cc 100644 --- a/include/qemu/log.h +++ b/include/qemu/log.h @@ -36,7 +36,7 @@ static inline bool qemu_log_separate(void) bool res = false; rcu_read_lock(); - logfile = atomic_rcu_read(&qemu_logfile); + logfile = qatomic_rcu_read(&qemu_logfile); if (logfile && logfile->fd != stderr) { res = true; } @@ -75,7 +75,7 @@ static inline FILE *qemu_log_lock(void) { QemuLogFile *logfile; rcu_read_lock(); - logfile = atomic_rcu_read(&qemu_logfile); + logfile = qatomic_rcu_read(&qemu_logfile); if (logfile) { qemu_flockfile(logfile->fd); return logfile->fd; @@ -102,7 +102,7 @@ qemu_log_vprintf(const char *fmt, va_list va) QemuLogFile *logfile; rcu_read_lock(); - logfile = atomic_rcu_read(&qemu_logfile); + logfile = qatomic_rcu_read(&qemu_logfile); if (logfile) { vfprintf(logfile->fd, fmt, va); } diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h index a6d20b07197c7f216ddb116c0390772efd06332d..d6892fd2081a4774677fdb141e42aa1fef1827bc 100644 --- a/include/qemu/main-loop.h +++ b/include/qemu/main-loop.h @@ -52,7 +52,7 @@ int qemu_init_main_loop(Error **errp); * repeatedly calls main_loop_wait(false). * * Main loop services include file descriptor callbacks, bottom halves - * and timers (defined in qemu-timer.h). Bottom halves are similar to timers + * and timers (defined in qemu/timer.h). Bottom halves are similar to timers * that execute immediately, but have a lower overhead and scheduling them * is wait-free, thread-safe and signal-safe. * @@ -303,6 +303,11 @@ void qemu_mutex_unlock_iothread(void); */ void qemu_cond_wait_iothread(QemuCond *cond); +/* + * qemu_cond_timedwait_iothread: like the previous, but with timeout + */ +void qemu_cond_timedwait_iothread(QemuCond *cond, int ms); + /* internal interfaces */ void qemu_fd_register(int fd); diff --git a/include/qemu/module.h b/include/qemu/module.h index 011ae1ae76058da6a7d14cedd38bfd3ddb1d55b4..944d403cbd1535cc121af76a94f2a76ae8405c43 100644 --- a/include/qemu/module.h +++ b/include/qemu/module.h @@ -61,14 +61,16 @@ typedef enum { #define fuzz_target_init(function) module_init(function, \ MODULE_INIT_FUZZ_TARGET) #define migration_init(function) module_init(function, MODULE_INIT_MIGRATION) -#define block_module_load_one(lib) module_load_one("block-", lib) -#define ui_module_load_one(lib) module_load_one("ui-", lib) -#define audio_module_load_one(lib) module_load_one("audio-", lib) +#define block_module_load_one(lib) module_load_one("block-", lib, false) +#define ui_module_load_one(lib) module_load_one("ui-", lib, false) +#define audio_module_load_one(lib) module_load_one("audio-", lib, false) void register_module_init(void (*fn)(void), module_init_type type); void register_dso_module_init(void (*fn)(void), module_init_type type); void module_call_init(module_init_type type); -bool module_load_one(const char *prefix, const char *lib_name); +bool module_load_one(const char *prefix, const char *lib_name, bool mayfail); +void module_load_qom_one(const char *type); +void module_load_qom_all(void); #endif diff --git a/include/qemu/option.h b/include/qemu/option.h index eb4097889d527ad5beb1bd82c0465aebe554327a..ac69352e0eb080d06ff4633a5f9b4c0187621c21 100644 --- a/include/qemu/option.h +++ b/include/qemu/option.h @@ -28,9 +28,22 @@ #include "qemu/queue.h" +/** + * get_opt_value + * @p: a pointer to the option name, delimited by commas + * @value: a non-NULL pointer that will received the delimited options + * + * The @value char pointer will be allocated and filled with + * the delimited options. + * + * Returns the position of the comma delimiter/zero byte after the + * option name in @p. + * The memory pointer in @value must be released with a call to g_free() + * when no longer required. + */ const char *get_opt_value(const char *p, char **value); -void parse_option_size(const char *name, const char *value, +bool parse_option_size(const char *name, const char *value, uint64_t *ret, Error **errp); bool has_help_option(const char *param); @@ -80,11 +93,11 @@ uint64_t qemu_opt_get_number_del(QemuOpts *opts, const char *name, uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name, uint64_t defval); int qemu_opt_unset(QemuOpts *opts, const char *name); -void qemu_opt_set(QemuOpts *opts, const char *name, const char *value, +bool qemu_opt_set(QemuOpts *opts, const char *name, const char *value, Error **errp); -void qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val, +bool qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val, Error **errp); -void qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val, +bool qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val, Error **errp); typedef int (*qemu_opt_loopfunc)(void *opaque, const char *name, const char *value, @@ -106,13 +119,13 @@ QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists, Error **errp); void qemu_opts_reset(QemuOptsList *list); void qemu_opts_loc_restore(QemuOpts *opts); -void qemu_opts_set(QemuOptsList *list, const char *id, +bool qemu_opts_set(QemuOptsList *list, const char *id, const char *name, const char *value, Error **errp); const char *qemu_opts_id(QemuOpts *opts); void qemu_opts_set_id(QemuOpts *opts, char *id); void qemu_opts_del(QemuOpts *opts); -void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp); -void qemu_opts_do_parse(QemuOpts *opts, const char *params, +bool qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp); +bool qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname, Error **errp); QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params, bool permit_abbrev); @@ -125,7 +138,7 @@ QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict, QDict *qemu_opts_to_qdict_filtered(QemuOpts *opts, QDict *qdict, QemuOptsList *list, bool del); QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict); -void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp); +bool qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp); typedef int (*qemu_opts_loopfunc)(void *opaque, QemuOpts *opts, Error **errp); int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, @@ -136,6 +149,6 @@ void qemu_opts_free(QemuOptsList *list); QemuOptsList *qemu_opts_append(QemuOptsList *dst, QemuOptsList *list); QDict *keyval_parse(const char *params, const char *implied_key, - Error **errp); + bool *help, Error **errp); #endif diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index ff7c17b85735c8e5840858834a084618902e4bf3..f9ec8c84e903e4da4bc10844c87c364a0ba8843e 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -29,7 +29,7 @@ #include "config-host.h" #ifdef NEED_CPU_H -#include "config-target.h" +#include CONFIG_TARGET #else #include "exec/poison.h" #endif @@ -104,7 +104,7 @@ extern int daemon(int, int); #include #include -#ifdef __OpenBSD__ +#ifdef HAVE_SYS_SIGNAL_H #include #endif @@ -173,6 +173,9 @@ extern int daemon(int, int); #ifndef MAP_ANONYMOUS #define MAP_ANONYMOUS MAP_ANON #endif +#ifndef MAP_FIXED_NOREPLACE +#define MAP_FIXED_NOREPLACE 0 +#endif #ifndef ENOMEDIUM #define ENOMEDIUM ENODEV #endif @@ -236,18 +239,62 @@ extern int daemon(int, int); #define SIZE_MAX ((size_t)-1) #endif -#ifndef MIN -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif -#ifndef MAX -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +/* + * Two variations of MIN/MAX macros. The first is for runtime use, and + * evaluates arguments only once (so it is safe even with side + * effects), but will not work in constant contexts (such as array + * size declarations) because of the '{}'. The second is for constant + * expression use, where evaluating arguments twice is safe because + * the result is going to be constant anyway, but will not work in a + * runtime context because of a void expression where a value is + * expected. Thus, both gcc and clang will fail to compile if you use + * the wrong macro (even if the error may seem a bit cryptic). + * + * Note that neither form is usable as an #if condition; if you truly + * need to write conditional code that depends on a minimum or maximum + * determined by the pre-processor instead of the compiler, you'll + * have to open-code it. Sadly, Coverity is severely confused by the + * constant variants, so we have to dumb things down there. + */ +#undef MIN +#define MIN(a, b) \ + ({ \ + typeof(1 ? (a) : (b)) _a = (a), _b = (b); \ + _a < _b ? _a : _b; \ + }) +#undef MAX +#define MAX(a, b) \ + ({ \ + typeof(1 ? (a) : (b)) _a = (a), _b = (b); \ + _a > _b ? _a : _b; \ + }) + +#ifdef __COVERITY__ +# define MIN_CONST(a, b) ((a) < (b) ? (a) : (b)) +# define MAX_CONST(a, b) ((a) > (b) ? (a) : (b)) +#else +# define MIN_CONST(a, b) \ + __builtin_choose_expr( \ + __builtin_constant_p(a) && __builtin_constant_p(b), \ + (a) < (b) ? (a) : (b), \ + ((void)0)) +# define MAX_CONST(a, b) \ + __builtin_choose_expr( \ + __builtin_constant_p(a) && __builtin_constant_p(b), \ + (a) > (b) ? (a) : (b), \ + ((void)0)) #endif -/* Minimum function that returns zero only iff both values are zero. - * Intended for use with unsigned values only. */ +/* + * Minimum function that returns zero only if both values are zero. + * Intended for use with unsigned values only. + */ #ifndef MIN_NON_ZERO -#define MIN_NON_ZERO(a, b) ((a) == 0 ? (b) : \ - ((b) == 0 ? (a) : (MIN(a, b)))) +#define MIN_NON_ZERO(a, b) \ + ({ \ + typeof(1 ? (a) : (b)) _a = (a), _b = (b); \ + _a == 0 ? _b : (_b == 0 || _b > _a) ? _a : _b; \ + }) #endif /* Round number down to multiple */ @@ -388,6 +435,10 @@ void qemu_anon_ram_free(void *ptr, size_t size); #define HAVE_CHARDEV_PARPORT 1 #endif +#if defined(__HAIKU__) +#define SIGIO SIGPOLL +#endif + #if defined(CONFIG_LINUX) #ifndef BUS_MCEERR_AR #define BUS_MCEERR_AR 4 @@ -446,16 +497,23 @@ int qemu_madvise(void *addr, size_t len, int advice); int qemu_mprotect_rwx(void *addr, size_t size); int qemu_mprotect_none(void *addr, size_t size); -int qemu_open(const char *name, int flags, ...); +/* + * Don't introduce new usage of this function, prefer the following + * qemu_open/qemu_create that take an "Error **errp" + */ +int qemu_open_old(const char *name, int flags, ...); +int qemu_open(const char *name, int flags, Error **errp); +int qemu_create(const char *name, int flags, mode_t mode, Error **errp); int qemu_close(int fd); int qemu_unlink(const char *name); #ifndef _WIN32 +int qemu_dup_flags(int fd, int flags); int qemu_dup(int fd); -#endif int qemu_lock_fd(int fd, int64_t start, int64_t len, bool exclusive); int qemu_unlock_fd(int fd, int64_t start, int64_t len); int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive); bool qemu_has_ofd_lock(void); +#endif #if defined(__HAIKU__) && defined(__i386__) #define FMT_pid "%ld" @@ -539,9 +597,8 @@ char *qemu_get_local_state_pathname(const char *relative_pathname); * Try OS specific API first, if not working, parse from argv0. */ void qemu_init_exec_dir(const char *argv0); -/* Get the saved exec dir. - * Caller needs to release the returned string by g_free() */ -char *qemu_get_exec_dir(void); +/* Get the saved exec dir. */ +const char *qemu_get_exec_dir(void); /** * qemu_getauxval: @@ -607,4 +664,26 @@ static inline void qemu_reset_optind(void) #endif } +/** + * qemu_get_host_name: + * @errp: Error object + * + * Operating system agnostic way of querying host name. + * + * Returns allocated hostname (caller should free), NULL on failure. + */ +char *qemu_get_host_name(Error **errp); + +/** + * qemu_get_host_physmem: + * + * Operating system agnostic way of querying host memory. + * + * Returns amount of physical memory on the system. This is purely + * advisery and may return 0 if we can't work it out. At the other + * end we saturate to SIZE_MAX if you are lucky enough to have that + * much memory. + */ +size_t qemu_get_host_physmem(void); + #endif diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h index 89ed579f559398003036758b48d658b7d6e64b2d..bab8b0d4b3af9572b90c45300a916ba16993304a 100644 --- a/include/qemu/qemu-plugin.h +++ b/include/qemu/qemu-plugin.h @@ -12,6 +12,7 @@ #include #include +#include /* * For best performance, build the plugin with -fvisibility=hidden so that diff --git a/include/qemu/queue.h b/include/qemu/queue.h index 456a5b01eeda5cf8cc91b79a1ca12145b377c9ce..e029e7bf669e1591be84eb22950d6e6656dc7ef4 100644 --- a/include/qemu/queue.h +++ b/include/qemu/queue.h @@ -218,12 +218,12 @@ struct { \ typeof(elm) save_sle_next; \ do { \ save_sle_next = (elm)->field.sle_next = (head)->slh_first; \ - } while (atomic_cmpxchg(&(head)->slh_first, save_sle_next, (elm)) != \ + } while (qatomic_cmpxchg(&(head)->slh_first, save_sle_next, (elm)) !=\ save_sle_next); \ } while (/*CONSTCOND*/0) #define QSLIST_MOVE_ATOMIC(dest, src) do { \ - (dest)->slh_first = atomic_xchg(&(src)->slh_first, NULL); \ + (dest)->slh_first = qatomic_xchg(&(src)->slh_first, NULL); \ } while (/*CONSTCOND*/0) #define QSLIST_REMOVE_HEAD(head, field) do { \ @@ -376,7 +376,8 @@ struct { \ /* * Simple queue access methods. */ -#define QSIMPLEQ_EMPTY_ATOMIC(head) (atomic_read(&((head)->sqh_first)) == NULL) +#define QSIMPLEQ_EMPTY_ATOMIC(head) \ + (qatomic_read(&((head)->sqh_first)) == NULL) #define QSIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL) #define QSIMPLEQ_FIRST(head) ((head)->sqh_first) #define QSIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) diff --git a/include/qemu/rcu.h b/include/qemu/rcu.h index 570aa603eb6126d4bce8adcae8b3016364d6c968..515d327cf11cfdd69b7bf636e44f0a43bcc762f0 100644 --- a/include/qemu/rcu.h +++ b/include/qemu/rcu.h @@ -79,8 +79,8 @@ static inline void rcu_read_lock(void) return; } - ctr = atomic_read(&rcu_gp_ctr); - atomic_set(&p_rcu_reader->ctr, ctr); + ctr = qatomic_read(&rcu_gp_ctr); + qatomic_set(&p_rcu_reader->ctr, ctr); /* Write p_rcu_reader->ctr before reading RCU-protected pointers. */ smp_mb_placeholder(); @@ -100,12 +100,12 @@ static inline void rcu_read_unlock(void) * smp_mb_placeholder(), this ensures writes to p_rcu_reader->ctr * are sequentially consistent. */ - atomic_store_release(&p_rcu_reader->ctr, 0); + qatomic_store_release(&p_rcu_reader->ctr, 0); /* Write p_rcu_reader->ctr before reading p_rcu_reader->waiting. */ smp_mb_placeholder(); - if (unlikely(atomic_read(&p_rcu_reader->waiting))) { - atomic_set(&p_rcu_reader->waiting, false); + if (unlikely(qatomic_read(&p_rcu_reader->waiting))) { + qatomic_set(&p_rcu_reader->waiting, false); qemu_event_set(&rcu_gp_event); } } @@ -133,6 +133,7 @@ struct rcu_head { }; extern void call_rcu1(struct rcu_head *head, RCUCBFunc *func); +extern void drain_call_rcu(void); /* The operands of the minus operator must have the same type, * which must be the one that we specify in the cast. diff --git a/include/qemu/rcu_queue.h b/include/qemu/rcu_queue.h index 558961cc272a589f9f0a0a29084cedfd2bf04289..0e53ddd5305ec6345eb71e9d7e67f9b6b0b8a24f 100644 --- a/include/qemu/rcu_queue.h +++ b/include/qemu/rcu_queue.h @@ -36,9 +36,9 @@ extern "C" { /* * List access methods. */ -#define QLIST_EMPTY_RCU(head) (atomic_read(&(head)->lh_first) == NULL) -#define QLIST_FIRST_RCU(head) (atomic_rcu_read(&(head)->lh_first)) -#define QLIST_NEXT_RCU(elm, field) (atomic_rcu_read(&(elm)->field.le_next)) +#define QLIST_EMPTY_RCU(head) (qatomic_read(&(head)->lh_first) == NULL) +#define QLIST_FIRST_RCU(head) (qatomic_rcu_read(&(head)->lh_first)) +#define QLIST_NEXT_RCU(elm, field) (qatomic_rcu_read(&(elm)->field.le_next)) /* * List functions. @@ -46,7 +46,7 @@ extern "C" { /* - * The difference between atomic_read/set and atomic_rcu_read/set + * The difference between qatomic_read/set and qatomic_rcu_read/set * is in the including of a read/write memory barrier to the volatile * access. atomic_rcu_* macros include the memory barrier, the * plain atomic macros do not. Therefore, it should be correct to @@ -66,7 +66,7 @@ extern "C" { #define QLIST_INSERT_AFTER_RCU(listelm, elm, field) do { \ (elm)->field.le_next = (listelm)->field.le_next; \ (elm)->field.le_prev = &(listelm)->field.le_next; \ - atomic_rcu_set(&(listelm)->field.le_next, (elm)); \ + qatomic_rcu_set(&(listelm)->field.le_next, (elm)); \ if ((elm)->field.le_next != NULL) { \ (elm)->field.le_next->field.le_prev = \ &(elm)->field.le_next; \ @@ -82,7 +82,7 @@ extern "C" { #define QLIST_INSERT_BEFORE_RCU(listelm, elm, field) do { \ (elm)->field.le_prev = (listelm)->field.le_prev; \ (elm)->field.le_next = (listelm); \ - atomic_rcu_set((listelm)->field.le_prev, (elm)); \ + qatomic_rcu_set((listelm)->field.le_prev, (elm)); \ (listelm)->field.le_prev = &(elm)->field.le_next; \ } while (/*CONSTCOND*/0) @@ -95,7 +95,7 @@ extern "C" { #define QLIST_INSERT_HEAD_RCU(head, elm, field) do { \ (elm)->field.le_prev = &(head)->lh_first; \ (elm)->field.le_next = (head)->lh_first; \ - atomic_rcu_set((&(head)->lh_first), (elm)); \ + qatomic_rcu_set((&(head)->lh_first), (elm)); \ if ((elm)->field.le_next != NULL) { \ (elm)->field.le_next->field.le_prev = \ &(elm)->field.le_next; \ @@ -112,20 +112,20 @@ extern "C" { (elm)->field.le_next->field.le_prev = \ (elm)->field.le_prev; \ } \ - atomic_set((elm)->field.le_prev, (elm)->field.le_next); \ + qatomic_set((elm)->field.le_prev, (elm)->field.le_next); \ } while (/*CONSTCOND*/0) /* List traversal must occur within an RCU critical section. */ #define QLIST_FOREACH_RCU(var, head, field) \ - for ((var) = atomic_rcu_read(&(head)->lh_first); \ + for ((var) = qatomic_rcu_read(&(head)->lh_first); \ (var); \ - (var) = atomic_rcu_read(&(var)->field.le_next)) + (var) = qatomic_rcu_read(&(var)->field.le_next)) /* List traversal must occur within an RCU critical section. */ #define QLIST_FOREACH_SAFE_RCU(var, head, field, next_var) \ - for ((var) = (atomic_rcu_read(&(head)->lh_first)); \ + for ((var) = (qatomic_rcu_read(&(head)->lh_first)); \ (var) && \ - ((next_var) = atomic_rcu_read(&(var)->field.le_next), 1); \ + ((next_var) = qatomic_rcu_read(&(var)->field.le_next), 1); \ (var) = (next_var)) /* @@ -133,9 +133,10 @@ extern "C" { */ /* Simple queue access methods */ -#define QSIMPLEQ_EMPTY_RCU(head) (atomic_read(&(head)->sqh_first) == NULL) -#define QSIMPLEQ_FIRST_RCU(head) atomic_rcu_read(&(head)->sqh_first) -#define QSIMPLEQ_NEXT_RCU(elm, field) atomic_rcu_read(&(elm)->field.sqe_next) +#define QSIMPLEQ_EMPTY_RCU(head) \ + (qatomic_read(&(head)->sqh_first) == NULL) +#define QSIMPLEQ_FIRST_RCU(head) qatomic_rcu_read(&(head)->sqh_first) +#define QSIMPLEQ_NEXT_RCU(elm, field) qatomic_rcu_read(&(elm)->field.sqe_next) /* Simple queue functions */ #define QSIMPLEQ_INSERT_HEAD_RCU(head, elm, field) do { \ @@ -143,12 +144,12 @@ extern "C" { if ((elm)->field.sqe_next == NULL) { \ (head)->sqh_last = &(elm)->field.sqe_next; \ } \ - atomic_rcu_set(&(head)->sqh_first, (elm)); \ + qatomic_rcu_set(&(head)->sqh_first, (elm)); \ } while (/*CONSTCOND*/0) #define QSIMPLEQ_INSERT_TAIL_RCU(head, elm, field) do { \ (elm)->field.sqe_next = NULL; \ - atomic_rcu_set((head)->sqh_last, (elm)); \ + qatomic_rcu_set((head)->sqh_last, (elm)); \ (head)->sqh_last = &(elm)->field.sqe_next; \ } while (/*CONSTCOND*/0) @@ -157,11 +158,11 @@ extern "C" { if ((elm)->field.sqe_next == NULL) { \ (head)->sqh_last = &(elm)->field.sqe_next; \ } \ - atomic_rcu_set(&(listelm)->field.sqe_next, (elm)); \ + qatomic_rcu_set(&(listelm)->field.sqe_next, (elm)); \ } while (/*CONSTCOND*/0) #define QSIMPLEQ_REMOVE_HEAD_RCU(head, field) do { \ - atomic_set(&(head)->sqh_first, (head)->sqh_first->field.sqe_next); \ + qatomic_set(&(head)->sqh_first, (head)->sqh_first->field.sqe_next);\ if ((head)->sqh_first == NULL) { \ (head)->sqh_last = &(head)->sqh_first; \ } \ @@ -175,7 +176,7 @@ extern "C" { while (curr->field.sqe_next != (elm)) { \ curr = curr->field.sqe_next; \ } \ - atomic_set(&curr->field.sqe_next, \ + qatomic_set(&curr->field.sqe_next, \ curr->field.sqe_next->field.sqe_next); \ if (curr->field.sqe_next == NULL) { \ (head)->sqh_last = &(curr)->field.sqe_next; \ @@ -184,13 +185,13 @@ extern "C" { } while (/*CONSTCOND*/0) #define QSIMPLEQ_FOREACH_RCU(var, head, field) \ - for ((var) = atomic_rcu_read(&(head)->sqh_first); \ + for ((var) = qatomic_rcu_read(&(head)->sqh_first); \ (var); \ - (var) = atomic_rcu_read(&(var)->field.sqe_next)) + (var) = qatomic_rcu_read(&(var)->field.sqe_next)) #define QSIMPLEQ_FOREACH_SAFE_RCU(var, head, field, next) \ - for ((var) = atomic_rcu_read(&(head)->sqh_first); \ - (var) && ((next) = atomic_rcu_read(&(var)->field.sqe_next), 1); \ + for ((var) = qatomic_rcu_read(&(head)->sqh_first); \ + (var) && ((next) = qatomic_rcu_read(&(var)->field.sqe_next), 1);\ (var) = (next)) /* @@ -198,9 +199,9 @@ extern "C" { */ /* Tail queue access methods */ -#define QTAILQ_EMPTY_RCU(head) (atomic_read(&(head)->tqh_first) == NULL) -#define QTAILQ_FIRST_RCU(head) atomic_rcu_read(&(head)->tqh_first) -#define QTAILQ_NEXT_RCU(elm, field) atomic_rcu_read(&(elm)->field.tqe_next) +#define QTAILQ_EMPTY_RCU(head) (qatomic_read(&(head)->tqh_first) == NULL) +#define QTAILQ_FIRST_RCU(head) qatomic_rcu_read(&(head)->tqh_first) +#define QTAILQ_NEXT_RCU(elm, field) qatomic_rcu_read(&(elm)->field.tqe_next) /* Tail queue functions */ #define QTAILQ_INSERT_HEAD_RCU(head, elm, field) do { \ @@ -211,14 +212,14 @@ extern "C" { } else { \ (head)->tqh_circ.tql_prev = &(elm)->field.tqe_circ; \ } \ - atomic_rcu_set(&(head)->tqh_first, (elm)); \ + qatomic_rcu_set(&(head)->tqh_first, (elm)); \ (elm)->field.tqe_circ.tql_prev = &(head)->tqh_circ; \ } while (/*CONSTCOND*/0) #define QTAILQ_INSERT_TAIL_RCU(head, elm, field) do { \ (elm)->field.tqe_next = NULL; \ (elm)->field.tqe_circ.tql_prev = (head)->tqh_circ.tql_prev; \ - atomic_rcu_set(&(head)->tqh_circ.tql_prev->tql_next, (elm)); \ + qatomic_rcu_set(&(head)->tqh_circ.tql_prev->tql_next, (elm)); \ (head)->tqh_circ.tql_prev = &(elm)->field.tqe_circ; \ } while (/*CONSTCOND*/0) @@ -230,14 +231,14 @@ extern "C" { } else { \ (head)->tqh_circ.tql_prev = &(elm)->field.tqe_circ; \ } \ - atomic_rcu_set(&(listelm)->field.tqe_next, (elm)); \ + qatomic_rcu_set(&(listelm)->field.tqe_next, (elm)); \ (elm)->field.tqe_circ.tql_prev = &(listelm)->field.tqe_circ; \ } while (/*CONSTCOND*/0) #define QTAILQ_INSERT_BEFORE_RCU(listelm, elm, field) do { \ (elm)->field.tqe_circ.tql_prev = (listelm)->field.tqe_circ.tql_prev; \ (elm)->field.tqe_next = (listelm); \ - atomic_rcu_set(&(listelm)->field.tqe_circ.tql_prev->tql_next, (elm)); \ + qatomic_rcu_set(&(listelm)->field.tqe_circ.tql_prev->tql_next, (elm));\ (listelm)->field.tqe_circ.tql_prev = &(elm)->field.tqe_circ; \ } while (/*CONSTCOND*/0) @@ -248,18 +249,19 @@ extern "C" { } else { \ (head)->tqh_circ.tql_prev = (elm)->field.tqe_circ.tql_prev; \ } \ - atomic_set(&(elm)->field.tqe_circ.tql_prev->tql_next, (elm)->field.tqe_next); \ + qatomic_set(&(elm)->field.tqe_circ.tql_prev->tql_next, \ + (elm)->field.tqe_next); \ (elm)->field.tqe_circ.tql_prev = NULL; \ } while (/*CONSTCOND*/0) #define QTAILQ_FOREACH_RCU(var, head, field) \ - for ((var) = atomic_rcu_read(&(head)->tqh_first); \ + for ((var) = qatomic_rcu_read(&(head)->tqh_first); \ (var); \ - (var) = atomic_rcu_read(&(var)->field.tqe_next)) + (var) = qatomic_rcu_read(&(var)->field.tqe_next)) #define QTAILQ_FOREACH_SAFE_RCU(var, head, field, next) \ - for ((var) = atomic_rcu_read(&(head)->tqh_first); \ - (var) && ((next) = atomic_rcu_read(&(var)->field.tqe_next), 1); \ + for ((var) = qatomic_rcu_read(&(head)->tqh_first); \ + (var) && ((next) = qatomic_rcu_read(&(var)->field.tqe_next), 1);\ (var) = (next)) /* @@ -267,23 +269,23 @@ extern "C" { */ /* Singly-linked list access methods */ -#define QSLIST_EMPTY_RCU(head) (atomic_read(&(head)->slh_first) == NULL) -#define QSLIST_FIRST_RCU(head) atomic_rcu_read(&(head)->slh_first) -#define QSLIST_NEXT_RCU(elm, field) atomic_rcu_read(&(elm)->field.sle_next) +#define QSLIST_EMPTY_RCU(head) (qatomic_read(&(head)->slh_first) == NULL) +#define QSLIST_FIRST_RCU(head) qatomic_rcu_read(&(head)->slh_first) +#define QSLIST_NEXT_RCU(elm, field) qatomic_rcu_read(&(elm)->field.sle_next) /* Singly-linked list functions */ #define QSLIST_INSERT_HEAD_RCU(head, elm, field) do { \ (elm)->field.sle_next = (head)->slh_first; \ - atomic_rcu_set(&(head)->slh_first, (elm)); \ + qatomic_rcu_set(&(head)->slh_first, (elm)); \ } while (/*CONSTCOND*/0) #define QSLIST_INSERT_AFTER_RCU(head, listelm, elm, field) do { \ (elm)->field.sle_next = (listelm)->field.sle_next; \ - atomic_rcu_set(&(listelm)->field.sle_next, (elm)); \ + qatomic_rcu_set(&(listelm)->field.sle_next, (elm)); \ } while (/*CONSTCOND*/0) #define QSLIST_REMOVE_HEAD_RCU(head, field) do { \ - atomic_set(&(head)->slh_first, (head)->slh_first->field.sle_next); \ + qatomic_set(&(head)->slh_first, (head)->slh_first->field.sle_next);\ } while (/*CONSTCOND*/0) #define QSLIST_REMOVE_RCU(head, elm, type, field) do { \ @@ -294,19 +296,19 @@ extern "C" { while (curr->field.sle_next != (elm)) { \ curr = curr->field.sle_next; \ } \ - atomic_set(&curr->field.sle_next, \ + qatomic_set(&curr->field.sle_next, \ curr->field.sle_next->field.sle_next); \ } \ } while (/*CONSTCOND*/0) #define QSLIST_FOREACH_RCU(var, head, field) \ - for ((var) = atomic_rcu_read(&(head)->slh_first); \ - (var); \ - (var) = atomic_rcu_read(&(var)->field.sle_next)) + for ((var) = qatomic_rcu_read(&(head)->slh_first); \ + (var); \ + (var) = qatomic_rcu_read(&(var)->field.sle_next)) -#define QSLIST_FOREACH_SAFE_RCU(var, head, field, next) \ - for ((var) = atomic_rcu_read(&(head)->slh_first); \ - (var) && ((next) = atomic_rcu_read(&(var)->field.sle_next), 1); \ +#define QSLIST_FOREACH_SAFE_RCU(var, head, field, next) \ + for ((var) = qatomic_rcu_read(&(head)->slh_first); \ + (var) && ((next) = qatomic_rcu_read(&(var)->field.sle_next), 1); \ (var) = (next)) #ifdef __cplusplus diff --git a/include/qemu/seqlock.h b/include/qemu/seqlock.h index 8b6b4ee4bbcf6a80fee192125afdff21a358a7c5..ecb7d2c8645927528ab91067a34d1237195c1934 100644 --- a/include/qemu/seqlock.h +++ b/include/qemu/seqlock.h @@ -32,7 +32,7 @@ static inline void seqlock_init(QemuSeqLock *sl) /* Lock out other writers and update the count. */ static inline void seqlock_write_begin(QemuSeqLock *sl) { - atomic_set(&sl->sequence, sl->sequence + 1); + qatomic_set(&sl->sequence, sl->sequence + 1); /* Write sequence before updating other fields. */ smp_wmb(); @@ -43,7 +43,7 @@ static inline void seqlock_write_end(QemuSeqLock *sl) /* Write other fields before finalizing sequence. */ smp_wmb(); - atomic_set(&sl->sequence, sl->sequence + 1); + qatomic_set(&sl->sequence, sl->sequence + 1); } /* Lock out other writers and update the count. */ @@ -68,7 +68,7 @@ static inline void seqlock_write_unlock_impl(QemuSeqLock *sl, QemuLockable *lock static inline unsigned seqlock_read_begin(const QemuSeqLock *sl) { /* Always fail if a write is in progress. */ - unsigned ret = atomic_read(&sl->sequence); + unsigned ret = qatomic_read(&sl->sequence); /* Read sequence before reading other fields. */ smp_rmb(); @@ -79,7 +79,7 @@ static inline int seqlock_read_retry(const QemuSeqLock *sl, unsigned start) { /* Read other fields before reading final sequence. */ smp_rmb(); - return unlikely(atomic_read(&sl->sequence) != start); + return unlikely(qatomic_read(&sl->sequence) != start); } #endif diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h index 57cd049d6eddd51bec8b570846c87ef45e28cae5..7d1f8135767dafda528669d108e3b89ea08a9236 100644 --- a/include/qemu/sockets.h +++ b/include/qemu/sockets.h @@ -18,6 +18,7 @@ int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen); int socket_set_cork(int fd, int v); int socket_set_nodelay(int fd); void qemu_set_block(int fd); +int qemu_try_set_nonblock(int fd); void qemu_set_nonblock(int fd); int socket_set_fast_reuse(int fd); diff --git a/include/qemu/stats64.h b/include/qemu/stats64.h index 19a5ac4c56742a9e844dfb8dea168ab03496f681..fdd3d1b8f98fc0cdc1e189bcea7660eec32246f8 100644 --- a/include/qemu/stats64.h +++ b/include/qemu/stats64.h @@ -37,27 +37,27 @@ static inline void stat64_init(Stat64 *s, uint64_t value) static inline uint64_t stat64_get(const Stat64 *s) { - return atomic_read__nocheck(&s->value); + return qatomic_read__nocheck(&s->value); } static inline void stat64_add(Stat64 *s, uint64_t value) { - atomic_add(&s->value, value); + qatomic_add(&s->value, value); } static inline void stat64_min(Stat64 *s, uint64_t value) { - uint64_t orig = atomic_read__nocheck(&s->value); + uint64_t orig = qatomic_read__nocheck(&s->value); while (orig > value) { - orig = atomic_cmpxchg__nocheck(&s->value, orig, value); + orig = qatomic_cmpxchg__nocheck(&s->value, orig, value); } } static inline void stat64_max(Stat64 *s, uint64_t value) { - uint64_t orig = atomic_read__nocheck(&s->value); + uint64_t orig = qatomic_read__nocheck(&s->value); while (orig < value) { - orig = atomic_cmpxchg__nocheck(&s->value, orig, value); + orig = qatomic_cmpxchg__nocheck(&s->value, orig, value); } } #else @@ -79,7 +79,7 @@ static inline void stat64_add(Stat64 *s, uint64_t value) low = (uint32_t) value; if (!low) { if (high) { - atomic_add(&s->high, high); + qatomic_add(&s->high, high); } return; } @@ -101,7 +101,7 @@ static inline void stat64_add(Stat64 *s, uint64_t value) * the high 32 bits, so it can race just fine with stat64_add32_carry * and even stat64_get! */ - old = atomic_cmpxchg(&s->low, orig, result); + old = qatomic_cmpxchg(&s->low, orig, result); if (orig == old) { return; } @@ -116,7 +116,7 @@ static inline void stat64_min(Stat64 *s, uint64_t value) high = value >> 32; low = (uint32_t) value; do { - orig_high = atomic_read(&s->high); + orig_high = qatomic_read(&s->high); if (orig_high < high) { return; } @@ -128,7 +128,7 @@ static inline void stat64_min(Stat64 *s, uint64_t value) * the write barrier in stat64_min_slow. */ smp_rmb(); - orig_low = atomic_read(&s->low); + orig_low = qatomic_read(&s->low); if (orig_low <= low) { return; } @@ -138,7 +138,7 @@ static inline void stat64_min(Stat64 *s, uint64_t value) * we may miss being lucky. */ smp_rmb(); - orig_high = atomic_read(&s->high); + orig_high = qatomic_read(&s->high); if (orig_high < high) { return; } @@ -156,7 +156,7 @@ static inline void stat64_max(Stat64 *s, uint64_t value) high = value >> 32; low = (uint32_t) value; do { - orig_high = atomic_read(&s->high); + orig_high = qatomic_read(&s->high); if (orig_high > high) { return; } @@ -168,7 +168,7 @@ static inline void stat64_max(Stat64 *s, uint64_t value) * the write barrier in stat64_max_slow. */ smp_rmb(); - orig_low = atomic_read(&s->low); + orig_low = qatomic_read(&s->low); if (orig_low >= low) { return; } @@ -178,7 +178,7 @@ static inline void stat64_max(Stat64 *s, uint64_t value) * we may miss being lucky. */ smp_rmb(); - orig_high = atomic_read(&s->high); + orig_high = qatomic_read(&s->high); if (orig_high > high) { return; } diff --git a/include/qemu/thread.h b/include/qemu/thread.h index d22848138ea0711b78e7a1c7f5d6884bb7ce8833..54357631846fe6fbbe3b231e6e5d5a9c960549ac 100644 --- a/include/qemu/thread.h +++ b/include/qemu/thread.h @@ -70,33 +70,33 @@ extern QemuCondTimedWaitFunc qemu_cond_timedwait_func; qemu_cond_timedwait_impl(c, m, ms, __FILE__, __LINE__) #else #define qemu_mutex_lock(m) ({ \ - QemuMutexLockFunc _f = atomic_read(&qemu_mutex_lock_func); \ + QemuMutexLockFunc _f = qatomic_read(&qemu_mutex_lock_func); \ _f(m, __FILE__, __LINE__); \ }) -#define qemu_mutex_trylock(m) ({ \ - QemuMutexTrylockFunc _f = atomic_read(&qemu_mutex_trylock_func); \ - _f(m, __FILE__, __LINE__); \ +#define qemu_mutex_trylock(m) ({ \ + QemuMutexTrylockFunc _f = qatomic_read(&qemu_mutex_trylock_func); \ + _f(m, __FILE__, __LINE__); \ }) -#define qemu_rec_mutex_lock(m) ({ \ - QemuRecMutexLockFunc _f = atomic_read(&qemu_rec_mutex_lock_func); \ - _f(m, __FILE__, __LINE__); \ +#define qemu_rec_mutex_lock(m) ({ \ + QemuRecMutexLockFunc _f = qatomic_read(&qemu_rec_mutex_lock_func);\ + _f(m, __FILE__, __LINE__); \ }) #define qemu_rec_mutex_trylock(m) ({ \ QemuRecMutexTrylockFunc _f; \ - _f = atomic_read(&qemu_rec_mutex_trylock_func); \ + _f = qatomic_read(&qemu_rec_mutex_trylock_func); \ _f(m, __FILE__, __LINE__); \ }) #define qemu_cond_wait(c, m) ({ \ - QemuCondWaitFunc _f = atomic_read(&qemu_cond_wait_func); \ + QemuCondWaitFunc _f = qatomic_read(&qemu_cond_wait_func); \ _f(c, m, __FILE__, __LINE__); \ }) #define qemu_cond_timedwait(c, m, ms) ({ \ - QemuCondTimedWaitFunc _f = atomic_read(&qemu_cond_timedwait_func); \ + QemuCondTimedWaitFunc _f = qatomic_read(&qemu_cond_timedwait_func);\ _f(c, m, ms, __FILE__, __LINE__); \ }) #endif @@ -177,7 +177,7 @@ void qemu_thread_create(QemuThread *thread, const char *name, void *qemu_thread_join(QemuThread *thread); void qemu_thread_get_self(QemuThread *thread); bool qemu_thread_is_self(QemuThread *thread); -void qemu_thread_exit(void *retval); +void qemu_thread_exit(void *retval) QEMU_NORETURN; void qemu_thread_naming(bool enable); struct Notifier; @@ -206,6 +206,10 @@ void qemu_thread_atexit_add(struct Notifier *notifier); */ void qemu_thread_atexit_remove(struct Notifier *notifier); +#ifdef CONFIG_TSAN +#include +#endif + struct QemuSpin { int value; }; @@ -213,30 +217,62 @@ struct QemuSpin { static inline void qemu_spin_init(QemuSpin *spin) { __sync_lock_release(&spin->value); +#ifdef CONFIG_TSAN + __tsan_mutex_create(spin, __tsan_mutex_not_static); +#endif +} + +/* const parameter because the only purpose here is the TSAN annotation */ +static inline void qemu_spin_destroy(const QemuSpin *spin) +{ +#ifdef CONFIG_TSAN + __tsan_mutex_destroy((void *)spin, __tsan_mutex_not_static); +#endif } static inline void qemu_spin_lock(QemuSpin *spin) { +#ifdef CONFIG_TSAN + __tsan_mutex_pre_lock(spin, 0); +#endif while (unlikely(__sync_lock_test_and_set(&spin->value, true))) { - while (atomic_read(&spin->value)) { + while (qatomic_read(&spin->value)) { cpu_relax(); } } +#ifdef CONFIG_TSAN + __tsan_mutex_post_lock(spin, 0, 0); +#endif } static inline bool qemu_spin_trylock(QemuSpin *spin) { - return __sync_lock_test_and_set(&spin->value, true); +#ifdef CONFIG_TSAN + __tsan_mutex_pre_lock(spin, __tsan_mutex_try_lock); +#endif + bool busy = __sync_lock_test_and_set(&spin->value, true); +#ifdef CONFIG_TSAN + unsigned flags = __tsan_mutex_try_lock; + flags |= busy ? __tsan_mutex_try_lock_failed : 0; + __tsan_mutex_post_lock(spin, flags, 0); +#endif + return busy; } static inline bool qemu_spin_locked(QemuSpin *spin) { - return atomic_read(&spin->value); + return qatomic_read(&spin->value); } static inline void qemu_spin_unlock(QemuSpin *spin) { +#ifdef CONFIG_TSAN + __tsan_mutex_pre_unlock(spin, 0); +#endif __sync_lock_release(&spin->value); +#ifdef CONFIG_TSAN + __tsan_mutex_post_unlock(spin, 0); +#endif } struct QemuLockCnt { diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 6a8b48b5a9d893db828a3023b6d41c7bc002a2fa..bdecc5b41fe516d4931408b12dea3dee97f09f99 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -166,8 +166,8 @@ bool qemu_clock_expired(QEMUClockType type); * * Determine whether a clock should be used for deadline * calculations. Some clocks, for instance vm_clock with - * use_icount set, do not count in nanoseconds. Such clocks - * are not used for deadline calculations, and are presumed + * icount_enabled() set, do not count in nanoseconds. + * Such clocks are not used for deadline calculations, and are presumed * to interrupt any poll using qemu_notify/aio_notify * etc. * @@ -224,13 +224,6 @@ void qemu_clock_notify(QEMUClockType type); */ void qemu_clock_enable(QEMUClockType type, bool enabled); -/** - * qemu_start_warp_timer: - * - * Starts a timer for virtual clock update - */ -void qemu_start_warp_timer(void); - /** * qemu_clock_run_timers: * @type: clock on which to operate @@ -679,7 +672,7 @@ void timer_mod(QEMUTimer *ts, int64_t expire_timer); /** * timer_mod_anticipate: * @ts: the timer - * @expire_time: the expiry time in nanoseconds + * @expire_time: the expire time in the units associated with the timer * * Modify a timer to expire at @expire_time or the current time, whichever * comes earlier, taking into account the scale associated with the timer. @@ -791,12 +784,6 @@ static inline int64_t qemu_soonest_timeout(int64_t timeout1, int64_t timeout2) */ void init_clocks(QEMUTimerListNotifyCB *notify_cb); -int64_t cpu_get_ticks(void); -/* Caller must hold BQL */ -void cpu_enable_ticks(void); -/* Caller must hold BQL */ -void cpu_disable_ticks(void); - static inline int64_t get_max_clock_jump(void) { /* This should be small enough to prevent excessive interrupts from being @@ -850,13 +837,6 @@ static inline int64_t get_clock(void) } #endif -/* icount */ -int64_t cpu_get_icount_raw(void); -int64_t cpu_get_icount(void); -int64_t cpu_get_clock(void); -int64_t cpu_icount_to_ns(int64_t icount); -void cpu_update_icount(CPUState *cpu); - /*******************************************/ /* host CPU ticks (if available) */ diff --git a/include/qemu/tsan.h b/include/qemu/tsan.h new file mode 100644 index 0000000000000000000000000000000000000000..09cc665f91df84e19eb8f3543f7a3c261487eb23 --- /dev/null +++ b/include/qemu/tsan.h @@ -0,0 +1,71 @@ +#ifndef QEMU_TSAN_H +#define QEMU_TSAN_H +/* + * tsan.h + * + * This file defines macros used to give ThreadSanitizer + * additional information to help suppress warnings. + * This is necessary since TSan does not provide a header file + * for these annotations. The standard way to include these + * is via the below macros. + * + * Annotation examples can be found here: + * https://github.com/llvm/llvm-project/tree/master/compiler-rt/test/tsan + * annotate_happens_before.cpp or ignore_race.cpp are good places to start. + * + * The full set of annotations can be found here in tsan_interface_ann.cpp. + * https://github.com/llvm/llvm-project/blob/master/compiler-rt/lib/tsan/rtl/ + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifdef CONFIG_TSAN +/* + * Informs TSan of a happens before/after relationship. + */ +#define QEMU_TSAN_ANNOTATE_HAPPENS_BEFORE(addr) \ + AnnotateHappensBefore(__FILE__, __LINE__, (void *)(addr)) +#define QEMU_TSAN_ANNOTATE_HAPPENS_AFTER(addr) \ + AnnotateHappensAfter(__FILE__, __LINE__, (void *)(addr)) +/* + * Gives TSan more information about thread names it can report the + * name of the thread in the warning report. + */ +#define QEMU_TSAN_ANNOTATE_THREAD_NAME(name) \ + AnnotateThreadName(__FILE__, __LINE__, (void *)(name)) +/* + * Allows defining a region of code on which TSan will not record memory READS. + * This has the effect of disabling race detection for this section of code. + */ +#define QEMU_TSAN_ANNOTATE_IGNORE_READS_BEGIN() \ + AnnotateIgnoreReadsBegin(__FILE__, __LINE__) +#define QEMU_TSAN_ANNOTATE_IGNORE_READS_END() \ + AnnotateIgnoreReadsEnd(__FILE__, __LINE__) +/* + * Allows defining a region of code on which TSan will not record memory + * WRITES. This has the effect of disabling race detection for this + * section of code. + */ +#define QEMU_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN() \ + AnnotateIgnoreWritesBegin(__FILE__, __LINE__) +#define QEMU_TSAN_ANNOTATE_IGNORE_WRITES_END() \ + AnnotateIgnoreWritesEnd(__FILE__, __LINE__) +#else +#define QEMU_TSAN_ANNOTATE_HAPPENS_BEFORE(addr) +#define QEMU_TSAN_ANNOTATE_HAPPENS_AFTER(addr) +#define QEMU_TSAN_ANNOTATE_THREAD_NAME(name) +#define QEMU_TSAN_ANNOTATE_IGNORE_READS_BEGIN() +#define QEMU_TSAN_ANNOTATE_IGNORE_READS_END() +#define QEMU_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN() +#define QEMU_TSAN_ANNOTATE_IGNORE_WRITES_END() +#endif + +void AnnotateHappensBefore(const char *f, int l, void *addr); +void AnnotateHappensAfter(const char *f, int l, void *addr); +void AnnotateThreadName(const char *f, int l, char *name); +void AnnotateIgnoreReadsBegin(const char *f, int l); +void AnnotateIgnoreReadsEnd(const char *f, int l); +void AnnotateIgnoreWritesBegin(const char *f, int l); +void AnnotateIgnoreWritesEnd(const char *f, int l); +#endif diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index ecf3cde26c3c34d7987426ace92589f2c8cac442..6281eae3b55ddcf989c65f6326e09de1931e0c21 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -51,7 +51,6 @@ typedef struct FWCfgIoState FWCfgIoState; typedef struct FWCfgMemState FWCfgMemState; typedef struct FWCfgState FWCfgState; typedef struct HostMemoryBackend HostMemoryBackend; -typedef struct HVFX86EmulatorState HVFX86EmulatorState; typedef struct I2CBus I2CBus; typedef struct I2SCodec I2SCodec; typedef struct IOMMUMemoryRegion IOMMUMemoryRegion; @@ -59,6 +58,7 @@ typedef struct ISABus ISABus; typedef struct ISADevice ISADevice; typedef struct IsaDma IsaDma; typedef struct MACAddr MACAddr; +typedef struct ReservedRegion ReservedRegion; typedef struct MachineClass MachineClass; typedef struct MachineState MachineState; typedef struct MemoryListener MemoryListener; @@ -76,6 +76,7 @@ typedef struct NetFilterState NetFilterState; typedef struct NICInfo NICInfo; typedef struct NodeInfo NodeInfo; typedef struct NumaNodeMem NumaNodeMem; +typedef struct Object Object; typedef struct ObjectClass ObjectClass; typedef struct PCIBridge PCIBridge; typedef struct PCIBus PCIBus; @@ -89,7 +90,6 @@ typedef struct PCIExpressDevice PCIExpressDevice; typedef struct PCIExpressHost PCIExpressHost; typedef struct PCIHostDeviceAddress PCIHostDeviceAddress; typedef struct PCIHostState PCIHostState; -typedef struct PCMachineState PCMachineState; typedef struct PostcopyDiscardState PostcopyDiscardState; typedef struct Property Property; typedef struct PropertyInfo PropertyInfo; @@ -115,6 +115,7 @@ typedef struct QObject QObject; typedef struct QString QString; typedef struct RAMBlock RAMBlock; typedef struct Range Range; +typedef struct SavedIOTLB SavedIOTLB; typedef struct SHPCDevice SHPCDevice; typedef struct SSIBus SSIBus; typedef struct VirtIODevice VirtIODevice; diff --git a/include/qemu/vfio-helpers.h b/include/qemu/vfio-helpers.h index 1f057c2b9e402ade8bbe2aab44a0842b68f3240c..4491c8e1a6e9b5a0fc5a9d2bb185a9daccd9224b 100644 --- a/include/qemu/vfio-helpers.h +++ b/include/qemu/vfio-helpers.h @@ -22,7 +22,7 @@ int qemu_vfio_dma_map(QEMUVFIOState *s, void *host, size_t size, int qemu_vfio_dma_reset_temporary(QEMUVFIOState *s); void qemu_vfio_dma_unmap(QEMUVFIOState *s, void *host); void *qemu_vfio_pci_map_bar(QEMUVFIOState *s, int index, - uint64_t offset, uint64_t size, + uint64_t offset, uint64_t size, int prot, Error **errp); void qemu_vfio_pci_unmap_bar(QEMUVFIOState *s, int index, void *bar, uint64_t offset, uint64_t size); diff --git a/include/qemu/vhost-user-server.h b/include/qemu/vhost-user-server.h new file mode 100644 index 0000000000000000000000000000000000000000..0da4c2cc4ccc6545e459d4454277dfa963e9308d --- /dev/null +++ b/include/qemu/vhost-user-server.h @@ -0,0 +1,65 @@ +/* + * Sharing QEMU devices via vhost-user protocol + * + * Copyright (c) Coiby Xu . + * Copyright (c) 2020 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * later. See the COPYING file in the top-level directory. + */ + +#ifndef VHOST_USER_SERVER_H +#define VHOST_USER_SERVER_H + +#include "contrib/libvhost-user/libvhost-user.h" +#include "io/channel-socket.h" +#include "io/channel-file.h" +#include "io/net-listener.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "standard-headers/linux/virtio_blk.h" + +/* A kick fd that we monitor on behalf of libvhost-user */ +typedef struct VuFdWatch { + VuDev *vu_dev; + int fd; /*kick fd*/ + void *pvt; + vu_watch_cb cb; + QTAILQ_ENTRY(VuFdWatch) next; +} VuFdWatch; + +/** + * VuServer: + * A vhost-user server instance with user-defined VuDevIface callbacks. + * Vhost-user device backends can be implemented using VuServer. VuDevIface + * callbacks and virtqueue kicks run in the given AioContext. + */ +typedef struct { + QIONetListener *listener; + QEMUBH *restart_listener_bh; + AioContext *ctx; + int max_queues; + const VuDevIface *vu_iface; + + /* Protected by ctx lock */ + VuDev vu_dev; + QIOChannel *ioc; /* The I/O channel with the client */ + QIOChannelSocket *sioc; /* The underlying data channel with the client */ + QTAILQ_HEAD(, VuFdWatch) vu_fd_watches; + + Coroutine *co_trip; /* coroutine for processing VhostUserMsg */ +} VuServer; + +bool vhost_user_server_start(VuServer *server, + SocketAddress *unix_socket, + AioContext *ctx, + uint16_t max_queues, + const VuDevIface *vu_iface, + Error **errp); + +void vhost_user_server_stop(VuServer *server); + +void vhost_user_server_attach_aio_context(VuServer *server, AioContext *ctx); +void vhost_user_server_detach_aio_context(VuServer *server); + +#endif /* VHOST_USER_SERVER_H */ diff --git a/include/qom/object.h b/include/qom/object.h index fd453dc8d6827d1d0b593ca810ba059fcd2faee2..d378f13a116a6845966489e7436ee25329492743 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -16,12 +16,11 @@ #include "qapi/qapi-builtin-types.h" #include "qemu/module.h" +#include "qom/object.h" struct TypeImpl; typedef struct TypeImpl *Type; -typedef struct Object Object; - typedef struct TypeInfo TypeInfo; typedef struct InterfaceClass InterfaceClass; @@ -29,290 +28,10 @@ typedef struct InterfaceInfo InterfaceInfo; #define TYPE_OBJECT "object" -/** - * SECTION:object.h - * @title:Base Object Type System - * @short_description: interfaces for creating new types and objects - * - * The QEMU Object Model provides a framework for registering user creatable - * types and instantiating objects from those types. QOM provides the following - * features: - * - * - System for dynamically registering types - * - Support for single-inheritance of types - * - Multiple inheritance of stateless interfaces - * - * - * Creating a minimal type - * - * #include "qdev.h" - * - * #define TYPE_MY_DEVICE "my-device" - * - * // No new virtual functions: we can reuse the typedef for the - * // superclass. - * typedef DeviceClass MyDeviceClass; - * typedef struct MyDevice - * { - * DeviceState parent; - * - * int reg0, reg1, reg2; - * } MyDevice; - * - * static const TypeInfo my_device_info = { - * .name = TYPE_MY_DEVICE, - * .parent = TYPE_DEVICE, - * .instance_size = sizeof(MyDevice), - * }; - * - * static void my_device_register_types(void) - * { - * type_register_static(&my_device_info); - * } - * - * type_init(my_device_register_types) - * - * - * - * In the above example, we create a simple type that is described by #TypeInfo. - * #TypeInfo describes information about the type including what it inherits - * from, the instance and class size, and constructor/destructor hooks. - * - * Alternatively several static types could be registered using helper macro - * DEFINE_TYPES() - * - * - * - * static const TypeInfo device_types_info[] = { - * { - * .name = TYPE_MY_DEVICE_A, - * .parent = TYPE_DEVICE, - * .instance_size = sizeof(MyDeviceA), - * }, - * { - * .name = TYPE_MY_DEVICE_B, - * .parent = TYPE_DEVICE, - * .instance_size = sizeof(MyDeviceB), - * }, - * }; - * - * DEFINE_TYPES(device_types_info) - * - * - * - * Every type has an #ObjectClass associated with it. #ObjectClass derivatives - * are instantiated dynamically but there is only ever one instance for any - * given type. The #ObjectClass typically holds a table of function pointers - * for the virtual methods implemented by this type. - * - * Using object_new(), a new #Object derivative will be instantiated. You can - * cast an #Object to a subclass (or base-class) type using - * object_dynamic_cast(). You typically want to define macro wrappers around - * OBJECT_CHECK() and OBJECT_CLASS_CHECK() to make it easier to convert to a - * specific type: - * - * - * Typecasting macros - * - * #define MY_DEVICE_GET_CLASS(obj) \ - * OBJECT_GET_CLASS(MyDeviceClass, obj, TYPE_MY_DEVICE) - * #define MY_DEVICE_CLASS(klass) \ - * OBJECT_CLASS_CHECK(MyDeviceClass, klass, TYPE_MY_DEVICE) - * #define MY_DEVICE(obj) \ - * OBJECT_CHECK(MyDevice, obj, TYPE_MY_DEVICE) - * - * - * - * # Class Initialization # - * - * Before an object is initialized, the class for the object must be - * initialized. There is only one class object for all instance objects - * that is created lazily. - * - * Classes are initialized by first initializing any parent classes (if - * necessary). After the parent class object has initialized, it will be - * copied into the current class object and any additional storage in the - * class object is zero filled. - * - * The effect of this is that classes automatically inherit any virtual - * function pointers that the parent class has already initialized. All - * other fields will be zero filled. - * - * Once all of the parent classes have been initialized, #TypeInfo::class_init - * is called to let the class being instantiated provide default initialize for - * its virtual functions. Here is how the above example might be modified - * to introduce an overridden virtual function: - * - * - * Overriding a virtual function - * - * #include "qdev.h" - * - * void my_device_class_init(ObjectClass *klass, void *class_data) - * { - * DeviceClass *dc = DEVICE_CLASS(klass); - * dc->reset = my_device_reset; - * } - * - * static const TypeInfo my_device_info = { - * .name = TYPE_MY_DEVICE, - * .parent = TYPE_DEVICE, - * .instance_size = sizeof(MyDevice), - * .class_init = my_device_class_init, - * }; - * - * - * - * Introducing new virtual methods requires a class to define its own - * struct and to add a .class_size member to the #TypeInfo. Each method - * will also have a wrapper function to call it easily: - * - * - * Defining an abstract class - * - * #include "qdev.h" - * - * typedef struct MyDeviceClass - * { - * DeviceClass parent; - * - * void (*frobnicate) (MyDevice *obj); - * } MyDeviceClass; - * - * static const TypeInfo my_device_info = { - * .name = TYPE_MY_DEVICE, - * .parent = TYPE_DEVICE, - * .instance_size = sizeof(MyDevice), - * .abstract = true, // or set a default in my_device_class_init - * .class_size = sizeof(MyDeviceClass), - * }; - * - * void my_device_frobnicate(MyDevice *obj) - * { - * MyDeviceClass *klass = MY_DEVICE_GET_CLASS(obj); - * - * klass->frobnicate(obj); - * } - * - * - * - * # Interfaces # - * - * Interfaces allow a limited form of multiple inheritance. Instances are - * similar to normal types except for the fact that are only defined by - * their classes and never carry any state. As a consequence, a pointer to - * an interface instance should always be of incomplete type in order to be - * sure it cannot be dereferenced. That is, you should define the - * 'typedef struct SomethingIf SomethingIf' so that you can pass around - * 'SomethingIf *si' arguments, but not define a 'struct SomethingIf { ... }'. - * The only things you can validly do with a 'SomethingIf *' are to pass it as - * an argument to a method on its corresponding SomethingIfClass, or to - * dynamically cast it to an object that implements the interface. - * - * # Methods # - * - * A method is a function within the namespace scope of - * a class. It usually operates on the object instance by passing it as a - * strongly-typed first argument. - * If it does not operate on an object instance, it is dubbed - * class method. - * - * Methods cannot be overloaded. That is, the #ObjectClass and method name - * uniquely identity the function to be called; the signature does not vary - * except for trailing varargs. - * - * Methods are always virtual. Overriding a method in - * #TypeInfo.class_init of a subclass leads to any user of the class obtained - * via OBJECT_GET_CLASS() accessing the overridden function. - * The original function is not automatically invoked. It is the responsibility - * of the overriding class to determine whether and when to invoke the method - * being overridden. - * - * To invoke the method being overridden, the preferred solution is to store - * the original value in the overriding class before overriding the method. - * This corresponds to |[ {super,base}.method(...) ]| in Java and C# - * respectively; this frees the overriding class from hardcoding its parent - * class, which someone might choose to change at some point. - * - * - * Overriding a virtual method - * - * typedef struct MyState MyState; - * - * typedef void (*MyDoSomething)(MyState *obj); - * - * typedef struct MyClass { - * ObjectClass parent_class; - * - * MyDoSomething do_something; - * } MyClass; - * - * static void my_do_something(MyState *obj) - * { - * // do something - * } - * - * static void my_class_init(ObjectClass *oc, void *data) - * { - * MyClass *mc = MY_CLASS(oc); - * - * mc->do_something = my_do_something; - * } - * - * static const TypeInfo my_type_info = { - * .name = TYPE_MY, - * .parent = TYPE_OBJECT, - * .instance_size = sizeof(MyState), - * .class_size = sizeof(MyClass), - * .class_init = my_class_init, - * }; - * - * typedef struct DerivedClass { - * MyClass parent_class; - * - * MyDoSomething parent_do_something; - * } DerivedClass; - * - * static void derived_do_something(MyState *obj) - * { - * DerivedClass *dc = DERIVED_GET_CLASS(obj); - * - * // do something here - * dc->parent_do_something(obj); - * // do something else here - * } - * - * static void derived_class_init(ObjectClass *oc, void *data) - * { - * MyClass *mc = MY_CLASS(oc); - * DerivedClass *dc = DERIVED_CLASS(oc); - * - * dc->parent_do_something = mc->do_something; - * mc->do_something = derived_do_something; - * } - * - * static const TypeInfo derived_type_info = { - * .name = TYPE_DERIVED, - * .parent = TYPE_MY, - * .class_size = sizeof(DerivedClass), - * .class_init = derived_class_init, - * }; - * - * - * - * Alternatively, object_class_by_name() can be used to obtain the class and - * its non-overridden methods for a specific type. This would correspond to - * |[ MyClass::method(...) ]| in C++. - * - * The first example of such a QOM method was #CPUClass.reset, - * another example is #DeviceClass.realize. - */ - - typedef struct ObjectProperty ObjectProperty; /** - * ObjectPropertyAccessor: + * typedef ObjectPropertyAccessor: * @obj: the object that owns the property * @v: the visitor that contains the property data * @name: the name of the property @@ -328,7 +47,7 @@ typedef void (ObjectPropertyAccessor)(Object *obj, Error **errp); /** - * ObjectPropertyResolve: + * typedef ObjectPropertyResolve: * @obj: the object that owns the property * @opaque: the opaque registered with the property * @part: the name of the property @@ -347,7 +66,7 @@ typedef Object *(ObjectPropertyResolve)(Object *obj, const char *part); /** - * ObjectPropertyRelease: + * typedef ObjectPropertyRelease: * @obj: the object that owns the property * @name: the name of the property * @opaque: the opaque registered with the property @@ -359,7 +78,7 @@ typedef void (ObjectPropertyRelease)(Object *obj, void *opaque); /** - * ObjectPropertyInit: + * typedef ObjectPropertyInit: * @obj: the object that owns the property * @prop: the property to set * @@ -382,7 +101,7 @@ struct ObjectProperty }; /** - * ObjectUnparent: + * typedef ObjectUnparent: * @obj: the object that is being removed from the composition tree * * Called when an object is being removed from the QOM composition tree. @@ -391,7 +110,7 @@ struct ObjectProperty typedef void (ObjectUnparent)(Object *obj); /** - * ObjectFree: + * typedef ObjectFree: * @obj: the object being freed * * Called when an object's last reference is removed. @@ -401,14 +120,14 @@ typedef void (ObjectFree)(void *obj); #define OBJECT_CLASS_CAST_CACHE 4 /** - * ObjectClass: + * struct ObjectClass: * * The base for all classes. The only thing that #ObjectClass contains is an * integer type handle. */ struct ObjectClass { - /*< private >*/ + /* private: */ Type type; GSList *interfaces; @@ -421,7 +140,7 @@ struct ObjectClass }; /** - * Object: + * struct Object: * * The base for all objects. The first member of this object is a pointer to * a #ObjectClass. Since C guarantees that the first member of a structure @@ -434,7 +153,7 @@ struct ObjectClass */ struct Object { - /*< private >*/ + /* private: */ ObjectClass *class; ObjectFree *free; GHashTable *properties; @@ -443,12 +162,223 @@ struct Object }; /** - * TypeInfo: + * DECLARE_INSTANCE_CHECKER: + * @InstanceType: instance struct name + * @OBJ_NAME: the object name in uppercase with underscore separators + * @TYPENAME: type name + * + * Direct usage of this macro should be avoided, and the complete + * OBJECT_DECLARE_TYPE macro is recommended instead. + * + * This macro will provide the instance type cast functions for a + * QOM type. + */ +#define DECLARE_INSTANCE_CHECKER(InstanceType, OBJ_NAME, TYPENAME) \ + static inline G_GNUC_UNUSED InstanceType * \ + OBJ_NAME(const void *obj) \ + { return OBJECT_CHECK(InstanceType, obj, TYPENAME); } + +/** + * DECLARE_CLASS_CHECKERS: + * @ClassType: class struct name + * @OBJ_NAME: the object name in uppercase with underscore separators + * @TYPENAME: type name + * + * Direct usage of this macro should be avoided, and the complete + * OBJECT_DECLARE_TYPE macro is recommended instead. + * + * This macro will provide the class type cast functions for a + * QOM type. + */ +#define DECLARE_CLASS_CHECKERS(ClassType, OBJ_NAME, TYPENAME) \ + static inline G_GNUC_UNUSED ClassType * \ + OBJ_NAME##_GET_CLASS(const void *obj) \ + { return OBJECT_GET_CLASS(ClassType, obj, TYPENAME); } \ + \ + static inline G_GNUC_UNUSED ClassType * \ + OBJ_NAME##_CLASS(const void *klass) \ + { return OBJECT_CLASS_CHECK(ClassType, klass, TYPENAME); } + +/** + * DECLARE_OBJ_CHECKERS: + * @InstanceType: instance struct name + * @ClassType: class struct name + * @OBJ_NAME: the object name in uppercase with underscore separators + * @TYPENAME: type name + * + * Direct usage of this macro should be avoided, and the complete + * OBJECT_DECLARE_TYPE macro is recommended instead. + * + * This macro will provide the three standard type cast functions for a + * QOM type. + */ +#define DECLARE_OBJ_CHECKERS(InstanceType, ClassType, OBJ_NAME, TYPENAME) \ + DECLARE_INSTANCE_CHECKER(InstanceType, OBJ_NAME, TYPENAME) \ + \ + DECLARE_CLASS_CHECKERS(ClassType, OBJ_NAME, TYPENAME) + +/** + * OBJECT_DECLARE_TYPE: + * @InstanceType: instance struct name + * @ClassType: class struct name + * @MODULE_OBJ_NAME: the object name in uppercase with underscore separators + * + * This macro is typically used in a header file, and will: + * + * - create the typedefs for the object and class structs + * - register the type for use with g_autoptr + * - provide three standard type cast functions + * + * The object struct and class struct need to be declared manually. + */ +#define OBJECT_DECLARE_TYPE(InstanceType, ClassType, MODULE_OBJ_NAME) \ + typedef struct InstanceType InstanceType; \ + typedef struct ClassType ClassType; \ + \ + G_DEFINE_AUTOPTR_CLEANUP_FUNC(InstanceType, object_unref) \ + \ + DECLARE_OBJ_CHECKERS(InstanceType, ClassType, \ + MODULE_OBJ_NAME, TYPE_##MODULE_OBJ_NAME) + +/** + * OBJECT_DECLARE_SIMPLE_TYPE: + * @InstanceType: instance struct name + * @MODULE_OBJ_NAME: the object name in uppercase with underscore separators + * + * This does the same as OBJECT_DECLARE_TYPE(), but with no class struct + * declared. + * + * This macro should be used unless the class struct needs to have + * virtual methods declared. + */ +#define OBJECT_DECLARE_SIMPLE_TYPE(InstanceType, MODULE_OBJ_NAME) \ + typedef struct InstanceType InstanceType; \ + \ + G_DEFINE_AUTOPTR_CLEANUP_FUNC(InstanceType, object_unref) \ + \ + DECLARE_INSTANCE_CHECKER(InstanceType, MODULE_OBJ_NAME, TYPE_##MODULE_OBJ_NAME) + + +/** + * OBJECT_DEFINE_TYPE_EXTENDED: + * @ModuleObjName: the object name with initial caps + * @module_obj_name: the object name in lowercase with underscore separators + * @MODULE_OBJ_NAME: the object name in uppercase with underscore separators + * @PARENT_MODULE_OBJ_NAME: the parent object name in uppercase with underscore + * separators + * @ABSTRACT: boolean flag to indicate whether the object can be instantiated + * @...: list of initializers for "InterfaceInfo" to declare implemented interfaces + * + * This macro is typically used in a source file, and will: + * + * - declare prototypes for _finalize, _class_init and _init methods + * - declare the TypeInfo struct instance + * - provide the constructor to register the type + * + * After using this macro, implementations of the _finalize, _class_init, + * and _init methods need to be written. Any of these can be zero-line + * no-op impls if no special logic is required for a given type. + * + * This macro should rarely be used, instead one of the more specialized + * macros is usually a better choice. + */ +#define OBJECT_DEFINE_TYPE_EXTENDED(ModuleObjName, module_obj_name, \ + MODULE_OBJ_NAME, PARENT_MODULE_OBJ_NAME, \ + ABSTRACT, ...) \ + static void \ + module_obj_name##_finalize(Object *obj); \ + static void \ + module_obj_name##_class_init(ObjectClass *oc, void *data); \ + static void \ + module_obj_name##_init(Object *obj); \ + \ + static const TypeInfo module_obj_name##_info = { \ + .parent = TYPE_##PARENT_MODULE_OBJ_NAME, \ + .name = TYPE_##MODULE_OBJ_NAME, \ + .instance_size = sizeof(ModuleObjName), \ + .instance_align = __alignof__(ModuleObjName), \ + .instance_init = module_obj_name##_init, \ + .instance_finalize = module_obj_name##_finalize, \ + .class_size = sizeof(ModuleObjName##Class), \ + .class_init = module_obj_name##_class_init, \ + .abstract = ABSTRACT, \ + .interfaces = (InterfaceInfo[]) { __VA_ARGS__ } , \ + }; \ + \ + static void \ + module_obj_name##_register_types(void) \ + { \ + type_register_static(&module_obj_name##_info); \ + } \ + type_init(module_obj_name##_register_types); + +/** + * OBJECT_DEFINE_TYPE: + * @ModuleObjName: the object name with initial caps + * @module_obj_name: the object name in lowercase with underscore separators + * @MODULE_OBJ_NAME: the object name in uppercase with underscore separators + * @PARENT_MODULE_OBJ_NAME: the parent object name in uppercase with underscore + * separators + * + * This is a specialization of OBJECT_DEFINE_TYPE_EXTENDED, which is suitable + * for the common case of a non-abstract type, without any interfaces. + */ +#define OBJECT_DEFINE_TYPE(ModuleObjName, module_obj_name, MODULE_OBJ_NAME, \ + PARENT_MODULE_OBJ_NAME) \ + OBJECT_DEFINE_TYPE_EXTENDED(ModuleObjName, module_obj_name, \ + MODULE_OBJ_NAME, PARENT_MODULE_OBJ_NAME, \ + false, { NULL }) + +/** + * OBJECT_DEFINE_TYPE_WITH_INTERFACES: + * @ModuleObjName: the object name with initial caps + * @module_obj_name: the object name in lowercase with underscore separators + * @MODULE_OBJ_NAME: the object name in uppercase with underscore separators + * @PARENT_MODULE_OBJ_NAME: the parent object name in uppercase with underscore + * separators + * @...: list of initializers for "InterfaceInfo" to declare implemented interfaces + * + * This is a specialization of OBJECT_DEFINE_TYPE_EXTENDED, which is suitable + * for the common case of a non-abstract type, with one or more implemented + * interfaces. + * + * Note when passing the list of interfaces, be sure to include the final + * NULL entry, e.g. { TYPE_USER_CREATABLE }, { NULL } + */ +#define OBJECT_DEFINE_TYPE_WITH_INTERFACES(ModuleObjName, module_obj_name, \ + MODULE_OBJ_NAME, \ + PARENT_MODULE_OBJ_NAME, ...) \ + OBJECT_DEFINE_TYPE_EXTENDED(ModuleObjName, module_obj_name, \ + MODULE_OBJ_NAME, PARENT_MODULE_OBJ_NAME, \ + false, __VA_ARGS__) + +/** + * OBJECT_DEFINE_ABSTRACT_TYPE: + * @ModuleObjName: the object name with initial caps + * @module_obj_name: the object name in lowercase with underscore separators + * @MODULE_OBJ_NAME: the object name in uppercase with underscore separators + * @PARENT_MODULE_OBJ_NAME: the parent object name in uppercase with underscore + * separators + * + * This is a specialization of OBJECT_DEFINE_TYPE_EXTENDED, which is suitable + * for defining an abstract type, without any interfaces. + */ +#define OBJECT_DEFINE_ABSTRACT_TYPE(ModuleObjName, module_obj_name, \ + MODULE_OBJ_NAME, PARENT_MODULE_OBJ_NAME) \ + OBJECT_DEFINE_TYPE_EXTENDED(ModuleObjName, module_obj_name, \ + MODULE_OBJ_NAME, PARENT_MODULE_OBJ_NAME, \ + true, { NULL }) + +/** + * struct TypeInfo: * @name: The name of the type. * @parent: The name of the parent type. * @instance_size: The size of the object (derivative of #Object). If * @instance_size is 0, then the size of the object will be the size of the * parent object. + * @instance_align: The required alignment of the object. If @instance_align + * is 0, then normal malloc alignment is sufficient; if non-zero, then we + * must use qemu_memalign for allocation. * @instance_init: This function is called to initialize an object. The parent * class will have already been initialized so the type is only responsible * for initializing its own members. @@ -486,6 +416,7 @@ struct TypeInfo const char *parent; size_t instance_size; + size_t instance_align; void (*instance_init)(Object *obj); void (*instance_post_init)(Object *obj); void (*instance_finalize)(Object *obj); @@ -565,7 +496,7 @@ struct TypeInfo OBJECT_CLASS_CHECK(class, object_get_class(OBJECT(obj)), name) /** - * InterfaceInfo: + * struct InterfaceInfo: * @type: The name of the interface. * * The information associated with an interface. @@ -575,7 +506,7 @@ struct InterfaceInfo { }; /** - * InterfaceClass: + * struct InterfaceClass: * @parent_class: the base class * * The class for all interfaces. Subclasses of this class should only add @@ -584,7 +515,7 @@ struct InterfaceInfo { struct InterfaceClass { ObjectClass parent_class; - /*< private >*/ + /* private: */ ObjectClass *concrete_class; Type interface_type; }; @@ -656,28 +587,25 @@ Object *object_new(const char *typename); * object will be marked complete once all the properties have been * processed. * - * - * Creating an object with properties - * - * Error *err = NULL; - * Object *obj; - * - * obj = object_new_with_props(TYPE_MEMORY_BACKEND_FILE, - * object_get_objects_root(), - * "hostmem0", - * &err, - * "share", "yes", - * "mem-path", "/dev/shm/somefile", - * "prealloc", "yes", - * "size", "1048576", - * NULL); - * - * if (!obj) { - * g_printerr("Cannot create memory backend: %s\n", - * error_get_pretty(err)); - * } - * - * + * .. code-block:: c + * :caption: Creating an object with properties + * + * Error *err = NULL; + * Object *obj; + * + * obj = object_new_with_props(TYPE_MEMORY_BACKEND_FILE, + * object_get_objects_root(), + * "hostmem0", + * &err, + * "share", "yes", + * "mem-path", "/dev/shm/somefile", + * "prealloc", "yes", + * "size", "1048576", + * NULL); + * + * if (!obj) { + * error_reportf_err(err, "Cannot create memory backend: "); + * } * * The returned object will have one stable reference maintained * for as long as it is present in the object hierarchy. @@ -706,7 +634,7 @@ Object *object_new_with_propv(const char *typename, Error **errp, va_list vargs); -void object_apply_global_props(Object *obj, const GPtrArray *props, +bool object_apply_global_props(Object *obj, const GPtrArray *props, Error **errp); void object_set_machine_compat_props(GPtrArray *compat_props); void object_set_accelerator_compat_props(GPtrArray *compat_props); @@ -726,35 +654,28 @@ void object_apply_compat_props(Object *obj); * strings. The propname of %NULL indicates the end of the property * list. * - * - * Update an object's properties - * - * Error *err = NULL; - * Object *obj = ...get / create object...; - * - * obj = object_set_props(obj, - * &err, - * "share", "yes", - * "mem-path", "/dev/shm/somefile", - * "prealloc", "yes", - * "size", "1048576", - * NULL); - * - * if (!obj) { - * g_printerr("Cannot set properties: %s\n", - * error_get_pretty(err)); - * } - * - * + * .. code-block:: c + * :caption: Update an object's properties + * + * Error *err = NULL; + * Object *obj = ...get / create object...; + * + * if (!object_set_props(obj, + * &err, + * "share", "yes", + * "mem-path", "/dev/shm/somefile", + * "prealloc", "yes", + * "size", "1048576", + * NULL)) { + * error_reportf_err(err, "Cannot set properties: "); + * } * * The returned object will have one stable reference maintained * for as long as it is present in the object hierarchy. * - * Returns: -1 on error, 0 on success + * Returns: %true on success, %false on error. */ -int object_set_props(Object *obj, - Error **errp, - ...) QEMU_SENTINEL; +bool object_set_props(Object *obj, Error **errp, ...) QEMU_SENTINEL; /** * object_set_propv: @@ -764,11 +685,9 @@ int object_set_props(Object *obj, * * See object_set_props() for documentation. * - * Returns: -1 on error, 0 on success + * Returns: %true on success, %false on error. */ -int object_set_propv(Object *obj, - Error **errp, - va_list vargs); +bool object_set_propv(Object *obj, Error **errp, va_list vargs); /** * object_initialize: @@ -783,7 +702,7 @@ int object_set_propv(Object *obj, void object_initialize(void *obj, size_t size, const char *typename); /** - * object_initialize_child: + * object_initialize_child_with_props: * @parentobj: The parent object to add a property to * @propname: The name of the property * @childobj: A pointer to the memory to be used for the object. @@ -802,13 +721,16 @@ void object_initialize(void *obj, size_t size, const char *typename); * strings. The propname of %NULL indicates the end of the property list. * If the object implements the user creatable interface, the object will * be marked complete once all the properties have been processed. + * + * Returns: %true on success, %false on failure. */ -void object_initialize_child(Object *parentobj, const char *propname, +bool object_initialize_child_with_props(Object *parentobj, + const char *propname, void *childobj, size_t size, const char *type, Error **errp, ...) QEMU_SENTINEL; /** - * object_initialize_childv: + * object_initialize_child_with_propsv: * @parentobj: The parent object to add a property to * @propname: The name of the property * @childobj: A pointer to the memory to be used for the object. @@ -818,11 +740,35 @@ void object_initialize_child(Object *parentobj, const char *propname, * @vargs: list of property names and values * * See object_initialize_child() for documentation. + * + * Returns: %true on success, %false on failure. */ -void object_initialize_childv(Object *parentobj, const char *propname, +bool object_initialize_child_with_propsv(Object *parentobj, + const char *propname, void *childobj, size_t size, const char *type, Error **errp, va_list vargs); +/** + * object_initialize_child: + * @parent: The parent object to add a property to + * @propname: The name of the property + * @child: A precisely typed pointer to the memory to be used for the + * object. + * @type: The name of the type of the object to instantiate. + * + * This is like:: + * + * object_initialize_child_with_props(parent, propname, + * child, sizeof(*child), type, + * &error_abort, NULL) + */ +#define object_initialize_child(parent, propname, child, type) \ + object_initialize_child_internal((parent), (propname), \ + (child), sizeof(*(child)), (type)) +void object_initialize_child_internal(Object *parent, const char *propname, + void *child, size_t size, + const char *type); + /** * object_dynamic_cast: * @obj: The object to cast. @@ -837,6 +783,11 @@ Object *object_dynamic_cast(Object *obj, const char *typename); /** * object_dynamic_cast_assert: + * @obj: The object to cast. + * @typename: The @typename to cast to. + * @file: Source code file where function was called + * @line: Source code line where function was called + * @func: Name of function where this function was called * * See object_dynamic_cast() for a description of the parameters of this * function. The only difference in behavior is that this function asserts @@ -913,12 +864,15 @@ type_init(do_qemu_init_ ## type_array) * object_class_dynamic_cast_assert: * @klass: The #ObjectClass to attempt to cast. * @typename: The QOM typename of the class to cast to. + * @file: Source code file where function was called + * @line: Source code line where function was called + * @func: Name of function where this function was called * * See object_class_dynamic_cast() for a description of the parameters * of this function. The only difference in behavior is that this function * asserts instead of returning #NULL on failure if QOM cast debugging is * enabled. This function is not meant to be called directly, but only through - * the wrapper macros OBJECT_CLASS_CHECK and INTERFACE_CHECK. + * the wrapper macro OBJECT_CLASS_CHECK. */ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *klass, const char *typename, @@ -974,6 +928,18 @@ bool object_class_is_abstract(ObjectClass *klass); */ ObjectClass *object_class_by_name(const char *typename); +/** + * module_object_class_by_name: + * @typename: The QOM typename to obtain the class for. + * + * For objects which might be provided by a module. Behaves like + * object_class_by_name, but additionally tries to load the module + * needed in case the class is not available. + * + * Returns: The class for @typename or %NULL if not found. + */ +ObjectClass *module_object_class_by_name(const char *typename); + void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque), const char *implements_type, bool include_abstract, void *opaque); @@ -1007,7 +973,7 @@ GSList *object_class_get_list_sorted(const char *implements_type, * as its reference count is greater than zero. * Returns: @obj */ -Object *object_ref(Object *obj); +Object *object_ref(void *obj); /** * object_unref: @@ -1016,10 +982,10 @@ Object *object_ref(Object *obj); * Decrease the reference count of a object. A object cannot be freed as long * as its reference count is greater than zero. */ -void object_unref(Object *obj); +void object_unref(void *obj); /** - * object_property_add: + * object_property_try_add: * @obj: the object to add a property to * @name: the name of the property. This can contain any character except for * a forward slash. In general, you should use hyphens '-' instead of @@ -1036,10 +1002,40 @@ void object_unref(Object *obj); * meant to allow a property to free its opaque upon object * destruction. This may be NULL. * @opaque: an opaque pointer to pass to the callbacks for the property + * @errp: pointer to error object * * Returns: The #ObjectProperty; this can be used to set the @resolve * callback for child and link properties. */ +ObjectProperty *object_property_try_add(Object *obj, const char *name, + const char *type, + ObjectPropertyAccessor *get, + ObjectPropertyAccessor *set, + ObjectPropertyRelease *release, + void *opaque, Error **errp); + +/** + * object_property_add: + * Same as object_property_try_add() with @errp hardcoded to + * &error_abort. + * + * @obj: the object to add a property to + * @name: the name of the property. This can contain any character except for + * a forward slash. In general, you should use hyphens '-' instead of + * underscores '_' when naming properties. + * @type: the type name of the property. This namespace is pretty loosely + * defined. Sub namespaces are constructed by using a prefix and then + * to angle brackets. For instance, the type 'virtio-net-pci' in the + * 'link' namespace would be 'link'. + * @get: The getter to be called to read a property. If this is NULL, then + * the property cannot be read. + * @set: the setter to be called to write a property. If this is NULL, + * then the property cannot be written. + * @release: called when the property is removed from the object. This is + * meant to allow a property to free its opaque upon object + * destruction. This may be NULL. + * @opaque: an opaque pointer to pass to the callbacks for the property + */ ObjectProperty *object_property_add(Object *obj, const char *name, const char *type, ObjectPropertyAccessor *get, @@ -1096,14 +1092,52 @@ void object_property_set_default_uint(ObjectProperty *prop, uint64_t value); * object_property_find: * @obj: the object * @name: the name of the property + * + * Look up a property for an object. + * + * Return its #ObjectProperty if found, or NULL. + */ +ObjectProperty *object_property_find(Object *obj, const char *name); + +/** + * object_property_find_err: + * @obj: the object + * @name: the name of the property * @errp: returns an error if this function fails * - * Look up a property for an object and return its #ObjectProperty if found. + * Look up a property for an object. + * + * Return its #ObjectProperty if found, or NULL. */ -ObjectProperty *object_property_find(Object *obj, const char *name, - Error **errp); -ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name, - Error **errp); +ObjectProperty *object_property_find_err(Object *obj, + const char *name, + Error **errp); + +/** + * object_class_property_find: + * @klass: the object class + * @name: the name of the property + * + * Look up a property for an object class. + * + * Return its #ObjectProperty if found, or NULL. + */ +ObjectProperty *object_class_property_find(ObjectClass *klass, + const char *name); + +/** + * object_class_property_find_err: + * @klass: the object class + * @name: the name of the property + * @errp: returns an error if this function fails + * + * Look up a property for an object class. + * + * Return its #ObjectProperty if found, or NULL. + */ +ObjectProperty *object_class_property_find_err(ObjectClass *klass, + const char *name, + Error **errp); typedef struct ObjectPropertyIterator { ObjectClass *nextclass; @@ -1112,6 +1146,7 @@ typedef struct ObjectPropertyIterator { /** * object_property_iter_init: + * @iter: the iterator instance * @obj: the object * * Initializes an iterator for traversing all properties @@ -1122,24 +1157,23 @@ typedef struct ObjectPropertyIterator { * * Typical usage pattern would be * - * - * Using object property iterators - * - * ObjectProperty *prop; - * ObjectPropertyIterator iter; + * .. code-block:: c + * :caption: Using object property iterators + * + * ObjectProperty *prop; + * ObjectPropertyIterator iter; * - * object_property_iter_init(&iter, obj); - * while ((prop = object_property_iter_next(&iter))) { - * ... do something with prop ... - * } - * - * + * object_property_iter_init(&iter, obj); + * while ((prop = object_property_iter_next(&iter))) { + * ... do something with prop ... + * } */ void object_property_iter_init(ObjectPropertyIterator *iter, Object *obj); /** * object_class_property_iter_init: + * @iter: the iterator instance * @klass: the class * * Initializes an iterator for traversing all properties @@ -1173,26 +1207,31 @@ void object_unparent(Object *obj); /** * object_property_get: * @obj: the object + * @name: the name of the property * @v: the visitor that will receive the property value. This should be an * Output visitor and the data will be written with @name as the name. - * @name: the name of the property * @errp: returns an error if this function fails * * Reads a property from a object. + * + * Returns: %true on success, %false on failure. */ -void object_property_get(Object *obj, Visitor *v, const char *name, +bool object_property_get(Object *obj, const char *name, Visitor *v, Error **errp); /** * object_property_set_str: - * @value: the value to be written to the property + * @obj: the object * @name: the name of the property + * @value: the value to be written to the property * @errp: returns an error if this function fails * * Writes a string value to a property. + * + * Returns: %true on success, %false on failure. */ -void object_property_set_str(Object *obj, const char *value, - const char *name, Error **errp); +bool object_property_set_str(Object *obj, const char *name, + const char *value, Error **errp); /** * object_property_get_str: @@ -1209,19 +1248,21 @@ char *object_property_get_str(Object *obj, const char *name, /** * object_property_set_link: - * @value: the value to be written to the property + * @obj: the object * @name: the name of the property + * @value: the value to be written to the property * @errp: returns an error if this function fails * * Writes an object's canonical path to a property. * * If the link property was created with - * OBJ_PROP_LINK_STRONG bit, the old target object is + * %OBJ_PROP_LINK_STRONG bit, the old target object is * unreferenced, and a reference is added to the new target object. * + * Returns: %true on success, %false on failure. */ -void object_property_set_link(Object *obj, Object *value, - const char *name, Error **errp); +bool object_property_set_link(Object *obj, const char *name, + Object *value, Error **errp); /** * object_property_get_link: @@ -1238,14 +1279,17 @@ Object *object_property_get_link(Object *obj, const char *name, /** * object_property_set_bool: - * @value: the value to be written to the property + * @obj: the object * @name: the name of the property + * @value: the value to be written to the property * @errp: returns an error if this function fails * * Writes a bool value to a property. + * + * Returns: %true on success, %false on failure. */ -void object_property_set_bool(Object *obj, bool value, - const char *name, Error **errp); +bool object_property_set_bool(Object *obj, const char *name, + bool value, Error **errp); /** * object_property_get_bool: @@ -1253,7 +1297,7 @@ void object_property_set_bool(Object *obj, bool value, * @name: the name of the property * @errp: returns an error if this function fails * - * Returns: the value of the property, converted to a boolean, or NULL if + * Returns: the value of the property, converted to a boolean, or false if * an error occurs (including when the property value is not a bool). */ bool object_property_get_bool(Object *obj, const char *name, @@ -1261,14 +1305,17 @@ bool object_property_get_bool(Object *obj, const char *name, /** * object_property_set_int: - * @value: the value to be written to the property + * @obj: the object * @name: the name of the property + * @value: the value to be written to the property * @errp: returns an error if this function fails * * Writes an integer value to a property. + * + * Returns: %true on success, %false on failure. */ -void object_property_set_int(Object *obj, int64_t value, - const char *name, Error **errp); +bool object_property_set_int(Object *obj, const char *name, + int64_t value, Error **errp); /** * object_property_get_int: @@ -1276,7 +1323,7 @@ void object_property_set_int(Object *obj, int64_t value, * @name: the name of the property * @errp: returns an error if this function fails * - * Returns: the value of the property, converted to an integer, or negative if + * Returns: the value of the property, converted to an integer, or -1 if * an error occurs (including when the property value is not an integer). */ int64_t object_property_get_int(Object *obj, const char *name, @@ -1284,14 +1331,17 @@ int64_t object_property_get_int(Object *obj, const char *name, /** * object_property_set_uint: - * @value: the value to be written to the property + * @obj: the object * @name: the name of the property + * @value: the value to be written to the property * @errp: returns an error if this function fails * * Writes an unsigned integer value to a property. + * + * Returns: %true on success, %false on failure. */ -void object_property_set_uint(Object *obj, uint64_t value, - const char *name, Error **errp); +bool object_property_set_uint(Object *obj, const char *name, + uint64_t value, Error **errp); /** * object_property_get_uint: @@ -1312,9 +1362,9 @@ uint64_t object_property_get_uint(Object *obj, const char *name, * @typename: the name of the enum data type * @errp: returns an error if this function fails * - * Returns: the value of the property, converted to an integer, or - * undefined if an error occurs (including when the property value is not - * an enum). + * Returns: the value of the property, converted to an integer (which + * can't be negative), or -1 on error (including when the property + * value is not an enum). */ int object_property_get_enum(Object *obj, const char *name, const char *typename, Error **errp); @@ -1322,28 +1372,32 @@ int object_property_get_enum(Object *obj, const char *name, /** * object_property_set: * @obj: the object + * @name: the name of the property * @v: the visitor that will be used to write the property value. This should * be an Input visitor and the data will be first read with @name as the * name and then written as the property value. - * @name: the name of the property * @errp: returns an error if this function fails * * Writes a property to a object. + * + * Returns: %true on success, %false on failure. */ -void object_property_set(Object *obj, Visitor *v, const char *name, +bool object_property_set(Object *obj, const char *name, Visitor *v, Error **errp); /** * object_property_parse: * @obj: the object - * @string: the string that will be used to parse the property value. * @name: the name of the property + * @string: the string that will be used to parse the property value. * @errp: returns an error if this function fails * * Parses a string and writes the result into a property of an object. + * + * Returns: %true on success, %false on failure. */ -void object_property_parse(Object *obj, const char *string, - const char *name, Error **errp); +bool object_property_parse(Object *obj, const char *name, + const char *string, Error **errp); /** * object_property_print: @@ -1401,20 +1455,23 @@ Object *object_get_internal_root(void); /** * object_get_canonical_path_component: + * @obj: the object * * Returns: The final component in the object's canonical path. The canonical * path is the path within the composition tree starting from the root. * %NULL if the object doesn't have a parent (and thus a canonical path). */ -char *object_get_canonical_path_component(Object *obj); +const char *object_get_canonical_path_component(const Object *obj); /** * object_get_canonical_path: + * @obj: the object * - * Returns: The canonical path for a object. This is the path within the - * composition tree starting from the root. + * Returns: The canonical path for a object, newly allocated. This is + * the path within the composition tree starting from the root. Use + * g_free() to free it. */ -char *object_get_canonical_path(Object *obj); +char *object_get_canonical_path(const Object *obj); /** * object_resolve_path: @@ -1475,10 +1532,11 @@ Object *object_resolve_path_type(const char *path, const char *typename, Object *object_resolve_path_component(Object *parent, const char *part); /** - * object_property_add_child: + * object_property_try_add_child: * @obj: the object to add a property to * @name: the name of the property * @child: the child object + * @errp: pointer to error object * * Child properties form the composition tree. All objects need to be a child * of another object. Objects can only be a child of one object. @@ -1492,6 +1550,18 @@ Object *object_resolve_path_component(Object *parent, const char *part); * * Returns: The newly added property on success, or %NULL on failure. */ +ObjectProperty *object_property_try_add_child(Object *obj, const char *name, + Object *child, Error **errp); + +/** + * object_property_add_child: + * @obj: the object to add a property to + * @name: the name of the property + * @child: the child object + * + * Same as object_property_try_add_child() with @errp hardcoded to + * &error_abort + */ ObjectProperty *object_property_add_child(Object *obj, const char *name, Object *child); @@ -1506,13 +1576,17 @@ typedef enum { /** * object_property_allow_set_link: + * @obj: the object to add a property to + * @name: the name of the property + * @child: the child object + * @errp: pointer to error object * * The default implementation of the object_property_add_link() check() * callback function. It allows the link property to be set and never returns * an error. */ -void object_property_allow_set_link(const Object *, const char *, - Object *, Error **); +void object_property_allow_set_link(const Object *obj, const char *name, + Object *child, Error **errp); /** * object_property_add_link: @@ -1529,16 +1603,16 @@ void object_property_allow_set_link(const Object *, const char *, * * Links form the graph in the object model. * - * The @check() callback is invoked when + * The @check() callback is invoked when * object_property_set_link() is called and can raise an error to prevent the - * link being set. If @check is NULL, the property is read-only + * link being set. If @check is NULL, the property is read-only * and cannot be set. * * Ownership of the pointer that @child points to is transferred to the - * link property. The reference count for *@child is + * link property. The reference count for *@child is * managed by the property from after the function returns till the * property is deleted with object_property_del(). If the - * @flags OBJ_PROP_LINK_STRONG bit is set, + * @flags %OBJ_PROP_LINK_STRONG bit is set, * the reference count is decremented when the property is deleted or * modified. * @@ -1606,6 +1680,7 @@ ObjectProperty *object_class_property_add_bool(ObjectClass *klass, * @obj: the object to add a property to * @name: the name of the property * @typename: the name of the enum data type + * @lookup: enum value namelookup table * @get: the getter or %NULL if the property is write-only. * @set: the setter or %NULL if the property is read-only * @@ -1748,7 +1823,7 @@ ObjectProperty *object_class_property_add_uint64_ptr(ObjectClass *klass, * Add an alias for a property on an object. This function will add a property * of the same type as the forwarded property. * - * The caller must ensure that @target_obj stays alive as long as + * The caller must ensure that @target_obj stays alive as long as * this property exists. In the case of a child object or an alias on the same * object this will be the case. For aliases to other objects the caller is * responsible for taking a reference. @@ -1785,6 +1860,7 @@ ObjectProperty *object_property_add_const_link(Object *obj, const char *name, * * Set an object property's description. * + * Returns: %true on success, %false on failure. */ void object_property_set_description(Object *obj, const char *name, const char *description); diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h index 65172120fa47f492387e743e0098699970d55f23..07d5cc883299e1afa4058949958868af5c12f366 100644 --- a/include/qom/object_interfaces.h +++ b/include/qom/object_interfaces.h @@ -6,12 +6,9 @@ #define TYPE_USER_CREATABLE "user-creatable" -#define USER_CREATABLE_CLASS(klass) \ - OBJECT_CLASS_CHECK(UserCreatableClass, (klass), \ - TYPE_USER_CREATABLE) -#define USER_CREATABLE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(UserCreatableClass, (obj), \ - TYPE_USER_CREATABLE) +typedef struct UserCreatableClass UserCreatableClass; +DECLARE_CLASS_CHECKERS(UserCreatableClass, USER_CREATABLE, + TYPE_USER_CREATABLE) #define USER_CREATABLE(obj) \ INTERFACE_CHECK(UserCreatable, (obj), \ TYPE_USER_CREATABLE) @@ -40,14 +37,14 @@ typedef struct UserCreatable UserCreatable; * object's type implements USER_CREATABLE interface and needs * complete() callback to be called. */ -typedef struct UserCreatableClass { +struct UserCreatableClass { /* */ InterfaceClass parent_class; /* */ void (*complete)(UserCreatable *uc, Error **errp); bool (*can_be_deleted)(UserCreatable *uc); -} UserCreatableClass; +}; /** * user_creatable_complete: @@ -57,8 +54,10 @@ typedef struct UserCreatableClass { * Wrapper to call complete() method if one of types it's inherited * from implements USER_CREATABLE interface, otherwise the call does * nothing. + * + * Returns: %true on success, %false on failure. */ -void user_creatable_complete(UserCreatable *uc, Error **errp); +bool user_creatable_complete(UserCreatable *uc, Error **errp); /** * user_creatable_can_be_deleted: @@ -100,8 +99,10 @@ Object *user_creatable_add_type(const char *type, const char *id, * @qdict. The object type is taken from the QDict key 'qom-type', its * ID from the key 'id'. The remaining entries in @qdict are used to * initialize the object properties. + * + * Returns: %true on success, %false on failure. */ -void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp); +bool user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp); /** * user_creatable_add_opts: @@ -153,13 +154,28 @@ int user_creatable_add_opts_foreach(void *opaque, * @type: the QOM type to be added * @opts: options to create * - * Prints help if requested in @opts. + * Prints help if requested in @type or @opts. Note that if @type is neither + * "help"/"?" nor a valid user creatable type, no help will be printed + * regardless of @opts. * - * Returns: true if @opts contained a help option and help was printed, false - * if no help option was found. + * Returns: true if a help option was found and help was printed, false + * otherwise. */ bool user_creatable_print_help(const char *type, QemuOpts *opts); +/** + * user_creatable_print_help_from_qdict: + * @args: options to create + * + * Prints help considering the other options given in @args (if "qom-type" is + * given and valid, print properties for the type, otherwise print valid types) + * + * In contrast to user_creatable_print_help(), this function can't return that + * no help was requested. It should only be called if we know that help is + * requested and it will always print some help. + */ +void user_creatable_print_help_from_qdict(QDict *args); + /** * user_creatable_del: * @id: the unique ID for the object @@ -167,8 +183,10 @@ bool user_creatable_print_help(const char *type, QemuOpts *opts); * * Delete an instance of the user creatable object identified * by @id. + * + * Returns: %true on success, %false on failure. */ -void user_creatable_del(const char *id, Error **errp); +bool user_creatable_del(const char *id, Error **errp); /** * user_creatable_cleanup: diff --git a/include/qom/qom-qobject.h b/include/qom/qom-qobject.h index 77cd717e3faf465f40fbcf9fb55ea2a5e1409e6d..73e4e0e474c5fc481a696ca3b96731f09de1bd93 100644 --- a/include/qom/qom-qobject.h +++ b/include/qom/qom-qobject.h @@ -13,8 +13,6 @@ #ifndef QEMU_QOM_QOBJECT_H #define QEMU_QOM_QOBJECT_H -#include "qom/object.h" - /* * object_property_get_qobject: * @obj: the object @@ -30,13 +28,16 @@ struct QObject *object_property_get_qobject(Object *obj, const char *name, /** * object_property_set_qobject: * @obj: the object - * @ret: The value that will be written to the property. * @name: the name of the property + * @value: The value that will be written to the property. * @errp: returns an error if this function fails * * Writes a property to a object. + * + * Returns: %true on success, %false on failure. */ -void object_property_set_qobject(Object *obj, struct QObject *qobj, - const char *name, struct Error **errp); +bool object_property_set_qobject(Object *obj, + const char *name, struct QObject *value, + struct Error **errp); #endif diff --git a/include/scsi/constants.h b/include/scsi/constants.h index 874176019e61f48bf70c2778e1d19bbc0399690e..2a32c08b5e9c9f1006f525336d468523a2e2949e 100644 --- a/include/scsi/constants.h +++ b/include/scsi/constants.h @@ -218,6 +218,7 @@ #define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */ #define TYPE_RBC 0x0e /* Simplified Direct-Access Device */ #define TYPE_OSD 0x11 /* Object-storage Device */ +#define TYPE_ZBC 0x14 /* Host-managed Zoned SCSI Device */ #define TYPE_WLUN 0x1e /* Well known LUN */ #define TYPE_NOT_PRESENT 0x1f #define TYPE_INACTIVE 0x20 diff --git a/include/scsi/pr-manager.h b/include/scsi/pr-manager.h index 6ad5fd1ff7d57fd0d046c3cac8d11a2ca9933600..e4ecbe00f6f6276a8602cd32849e91dc94755533 100644 --- a/include/scsi/pr-manager.h +++ b/include/scsi/pr-manager.h @@ -9,33 +9,29 @@ #define TYPE_PR_MANAGER "pr-manager" -#define PR_MANAGER_CLASS(klass) \ - OBJECT_CLASS_CHECK(PRManagerClass, (klass), TYPE_PR_MANAGER) -#define PR_MANAGER_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PRManagerClass, (obj), TYPE_PR_MANAGER) -#define PR_MANAGER(obj) \ - OBJECT_CHECK(PRManager, (obj), TYPE_PR_MANAGER) +OBJECT_DECLARE_TYPE(PRManager, PRManagerClass, + PR_MANAGER) struct sg_io_hdr; -typedef struct PRManager { +struct PRManager { /* */ Object parent; -} PRManager; +}; /** * PRManagerClass: * @parent_class: the base class * @run: callback invoked in thread pool context */ -typedef struct PRManagerClass { +struct PRManagerClass { /* */ ObjectClass parent_class; /* */ int (*run)(PRManager *pr_mgr, int fd, struct sg_io_hdr *hdr); bool (*is_connected)(PRManager *pr_mgr); -} PRManagerClass; +}; bool pr_manager_is_connected(PRManager *pr_mgr); int coroutine_fn pr_manager_execute(PRManager *pr_mgr, AioContext *ctx, int fd, diff --git a/include/standard-headers/asm-x86/kvm_para.h b/include/standard-headers/asm-x86/kvm_para.h index 90604a8fb77b43ac0bdf48a9f459a6b7c85c0124..07877d3295f265760c6eddec2b5e77bc11c14221 100644 --- a/include/standard-headers/asm-x86/kvm_para.h +++ b/include/standard-headers/asm-x86/kvm_para.h @@ -31,6 +31,7 @@ #define KVM_FEATURE_PV_SEND_IPI 11 #define KVM_FEATURE_POLL_CONTROL 12 #define KVM_FEATURE_PV_SCHED_YIELD 13 +#define KVM_FEATURE_ASYNC_PF_INT 14 #define KVM_HINTS_REALTIME 0 @@ -50,6 +51,8 @@ #define MSR_KVM_STEAL_TIME 0x4b564d03 #define MSR_KVM_PV_EOI_EN 0x4b564d04 #define MSR_KVM_POLL_CONTROL 0x4b564d05 +#define MSR_KVM_ASYNC_PF_INT 0x4b564d06 +#define MSR_KVM_ASYNC_PF_ACK 0x4b564d07 struct kvm_steal_time { uint64_t steal; @@ -81,6 +84,11 @@ struct kvm_clock_pairing { #define KVM_ASYNC_PF_ENABLED (1 << 0) #define KVM_ASYNC_PF_SEND_ALWAYS (1 << 1) #define KVM_ASYNC_PF_DELIVERY_AS_PF_VMEXIT (1 << 2) +#define KVM_ASYNC_PF_DELIVERY_AS_INT (1 << 3) + +/* MSR_KVM_ASYNC_PF_INT */ +#define KVM_ASYNC_PF_VEC_MASK GENMASK(7, 0) + /* Operations for KVM_HC_MMU_OP */ #define KVM_MMU_OP_WRITE_PTE 1 @@ -112,8 +120,13 @@ struct kvm_mmu_op_release_pt { #define KVM_PV_REASON_PAGE_READY 2 struct kvm_vcpu_pv_apf_data { - uint32_t reason; - uint8_t pad[60]; + /* Used for 'page not present' events delivered via #PF */ + uint32_t flags; + + /* Used for 'page ready' events delivered via interrupt notification */ + uint32_t token; + + uint8_t pad[56]; uint32_t enabled; }; diff --git a/include/standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h b/include/standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h index acd4c8346d3b958f5137355379ad38fa01b9df14..7b4062a1a107449631fe11d3b30da9aaefa4c677 100644 --- a/include/standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h +++ b/include/standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h @@ -68,7 +68,7 @@ static inline int pvrdma_idx_valid(uint32_t idx, uint32_t max_elems) static inline int32_t pvrdma_idx(int *var, uint32_t max_elems) { - const unsigned int idx = atomic_read(var); + const unsigned int idx = qatomic_read(var); if (pvrdma_idx_valid(idx, max_elems)) return idx & (max_elems - 1); @@ -77,17 +77,17 @@ static inline int32_t pvrdma_idx(int *var, uint32_t max_elems) static inline void pvrdma_idx_ring_inc(int *var, uint32_t max_elems) { - uint32_t idx = atomic_read(var) + 1; /* Increment. */ + uint32_t idx = qatomic_read(var) + 1; /* Increment. */ idx &= (max_elems << 1) - 1; /* Modulo size, flip gen. */ - atomic_set(var, idx); + qatomic_set(var, idx); } static inline int32_t pvrdma_idx_ring_has_space(const struct pvrdma_ring *r, uint32_t max_elems, uint32_t *out_tail) { - const uint32_t tail = atomic_read(&r->prod_tail); - const uint32_t head = atomic_read(&r->cons_head); + const uint32_t tail = qatomic_read(&r->prod_tail); + const uint32_t head = qatomic_read(&r->cons_head); if (pvrdma_idx_valid(tail, max_elems) && pvrdma_idx_valid(head, max_elems)) { @@ -100,8 +100,8 @@ static inline int32_t pvrdma_idx_ring_has_space(const struct pvrdma_ring *r, static inline int32_t pvrdma_idx_ring_has_data(const struct pvrdma_ring *r, uint32_t max_elems, uint32_t *out_head) { - const uint32_t tail = atomic_read(&r->prod_tail); - const uint32_t head = atomic_read(&r->cons_head); + const uint32_t tail = qatomic_read(&r->prod_tail); + const uint32_t head = qatomic_read(&r->cons_head); if (pvrdma_idx_valid(tail, max_elems) && pvrdma_idx_valid(head, max_elems)) { diff --git a/include/standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h b/include/standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h index 1677208a411fa575d490de6cce15a312b68ac065..0a8c7c9311994e3a9c3fabdabea1a30979930127 100644 --- a/include/standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h +++ b/include/standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h @@ -176,7 +176,7 @@ struct pvrdma_port_attr { uint8_t subnet_timeout; uint8_t init_type_reply; uint8_t active_width; - uint8_t active_speed; + uint16_t active_speed; uint8_t phys_state; uint8_t reserved[2]; }; diff --git a/include/standard-headers/drm/drm_fourcc.h b/include/standard-headers/drm/drm_fourcc.h index 66e838074c81c64d1d38f3fb815da04b9b91ac77..0de1a552cab235c00ff21de583f0f6d5dc5f7c5b 100644 --- a/include/standard-headers/drm/drm_fourcc.h +++ b/include/standard-headers/drm/drm_fourcc.h @@ -235,6 +235,12 @@ extern "C" { #define DRM_FORMAT_NV61 fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */ #define DRM_FORMAT_NV24 fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */ #define DRM_FORMAT_NV42 fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */ +/* + * 2 plane YCbCr + * index 0 = Y plane, [39:0] Y3:Y2:Y1:Y0 little endian + * index 1 = Cr:Cb plane, [39:0] Cr1:Cb1:Cr0:Cb0 little endian + */ +#define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5') /* 2x2 subsampled Cr:Cb plane */ /* * 2 plane YCbCr MSB aligned @@ -264,6 +270,22 @@ extern "C" { */ #define DRM_FORMAT_P016 fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cr:Cb plane 16 bits per channel */ +/* 3 plane non-subsampled (444) YCbCr + * 16 bits per component, but only 10 bits are used and 6 bits are padded + * index 0: Y plane, [15:0] Y:x [10:6] little endian + * index 1: Cb plane, [15:0] Cb:x [10:6] little endian + * index 2: Cr plane, [15:0] Cr:x [10:6] little endian + */ +#define DRM_FORMAT_Q410 fourcc_code('Q', '4', '1', '0') + +/* 3 plane non-subsampled (444) YCrCb + * 16 bits per component, but only 10 bits are used and 6 bits are padded + * index 0: Y plane, [15:0] Y:x [10:6] little endian + * index 1: Cr plane, [15:0] Cr:x [10:6] little endian + * index 2: Cb plane, [15:0] Cb:x [10:6] little endian + */ +#define DRM_FORMAT_Q401 fourcc_code('Q', '4', '0', '1') + /* * 3 plane YCbCr * index 0: Y plane, [7:0] Y @@ -308,6 +330,7 @@ extern "C" { #define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07 #define DRM_FORMAT_MOD_VENDOR_ARM 0x08 #define DRM_FORMAT_MOD_VENDOR_ALLWINNER 0x09 +#define DRM_FORMAT_MOD_VENDOR_AMLOGIC 0x0a /* add more to the end as needed */ @@ -322,8 +345,33 @@ extern "C" { * When adding a new token please document the layout with a code comment, * similar to the fourcc codes above. drm_fourcc.h is considered the * authoritative source for all of these. + * + * Generic modifier names: + * + * DRM_FORMAT_MOD_GENERIC_* definitions are used to provide vendor-neutral names + * for layouts which are common across multiple vendors. To preserve + * compatibility, in cases where a vendor-specific definition already exists and + * a generic name for it is desired, the common name is a purely symbolic alias + * and must use the same numerical value as the original definition. + * + * Note that generic names should only be used for modifiers which describe + * generic layouts (such as pixel re-ordering), which may have + * independently-developed support across multiple vendors. + * + * In future cases where a generic layout is identified before merging with a + * vendor-specific modifier, a new 'GENERIC' vendor or modifier using vendor + * 'NONE' could be considered. This should only be for obvious, exceptional + * cases to avoid polluting the 'GENERIC' namespace with modifiers which only + * apply to a single vendor. + * + * Generic names should not be used for cases where multiple hardware vendors + * have implementations of the same standardised compression scheme (such as + * AFBC). In those cases, all implementations should use the same format + * modifier(s), reflecting the vendor of the standard. */ +#define DRM_FORMAT_MOD_GENERIC_16_16_TILE DRM_FORMAT_MOD_SAMSUNG_16_16_TILE + /* * Invalid Modifier * @@ -353,9 +401,12 @@ extern "C" { * a platform-dependent stride. On top of that the memory can apply * platform-depending swizzling of some higher address bits into bit6. * - * This format is highly platforms specific and not useful for cross-driver - * sharing. It exists since on a given platform it does uniquely identify the - * layout in a simple way for i915-specific userspace. + * Note that this layout is only accurate on intel gen 8+ or valleyview chipsets. + * On earlier platforms the is highly platforms specific and not useful for + * cross-driver sharing. It exists since on a given platform it does uniquely + * identify the layout in a simple way for i915-specific userspace, which + * facilitated conversion of userspace to modifiers. Additionally the exact + * format on some really old platforms is not known. */ #define I915_FORMAT_MOD_X_TILED fourcc_mod_code(INTEL, 1) @@ -368,9 +419,12 @@ extern "C" { * memory can apply platform-depending swizzling of some higher address bits * into bit6. * - * This format is highly platforms specific and not useful for cross-driver - * sharing. It exists since on a given platform it does uniquely identify the - * layout in a simple way for i915-specific userspace. + * Note that this layout is only accurate on intel gen 8+ or valleyview chipsets. + * On earlier platforms the is highly platforms specific and not useful for + * cross-driver sharing. It exists since on a given platform it does uniquely + * identify the layout in a simple way for i915-specific userspace, which + * facilitated conversion of userspace to modifiers. Additionally the exact + * format on some really old platforms is not known. */ #define I915_FORMAT_MOD_Y_TILED fourcc_mod_code(INTEL, 2) @@ -520,7 +574,113 @@ extern "C" { #define DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED fourcc_mod_code(NVIDIA, 1) /* - * 16Bx2 Block Linear layout, used by desktop GPUs, and Tegra K1 and later + * Generalized Block Linear layout, used by desktop GPUs starting with NV50/G80, + * and Tegra GPUs starting with Tegra K1. + * + * Pixels are arranged in Groups of Bytes (GOBs). GOB size and layout varies + * based on the architecture generation. GOBs themselves are then arranged in + * 3D blocks, with the block dimensions (in terms of GOBs) always being a power + * of two, and hence expressible as their log2 equivalent (E.g., "2" represents + * a block depth or height of "4"). + * + * Chapter 20 "Pixel Memory Formats" of the Tegra X1 TRM describes this format + * in full detail. + * + * Macro + * Bits Param Description + * ---- ----- ----------------------------------------------------------------- + * + * 3:0 h log2(height) of each block, in GOBs. Placed here for + * compatibility with the existing + * DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK()-based modifiers. + * + * 4:4 - Must be 1, to indicate block-linear layout. Necessary for + * compatibility with the existing + * DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK()-based modifiers. + * + * 8:5 - Reserved (To support 3D-surfaces with variable log2(depth) block + * size). Must be zero. + * + * Note there is no log2(width) parameter. Some portions of the + * hardware support a block width of two gobs, but it is impractical + * to use due to lack of support elsewhere, and has no known + * benefits. + * + * 11:9 - Reserved (To support 2D-array textures with variable array stride + * in blocks, specified via log2(tile width in blocks)). Must be + * zero. + * + * 19:12 k Page Kind. This value directly maps to a field in the page + * tables of all GPUs >= NV50. It affects the exact layout of bits + * in memory and can be derived from the tuple + * + * (format, GPU model, compression type, samples per pixel) + * + * Where compression type is defined below. If GPU model were + * implied by the format modifier, format, or memory buffer, page + * kind would not need to be included in the modifier itself, but + * since the modifier should define the layout of the associated + * memory buffer independent from any device or other context, it + * must be included here. + * + * 21:20 g GOB Height and Page Kind Generation. The height of a GOB changed + * starting with Fermi GPUs. Additionally, the mapping between page + * kind and bit layout has changed at various points. + * + * 0 = Gob Height 8, Fermi - Volta, Tegra K1+ Page Kind mapping + * 1 = Gob Height 4, G80 - GT2XX Page Kind mapping + * 2 = Gob Height 8, Turing+ Page Kind mapping + * 3 = Reserved for future use. + * + * 22:22 s Sector layout. On Tegra GPUs prior to Xavier, there is a further + * bit remapping step that occurs at an even lower level than the + * page kind and block linear swizzles. This causes the layout of + * surfaces mapped in those SOC's GPUs to be incompatible with the + * equivalent mapping on other GPUs in the same system. + * + * 0 = Tegra K1 - Tegra Parker/TX2 Layout. + * 1 = Desktop GPU and Tegra Xavier+ Layout + * + * 25:23 c Lossless Framebuffer Compression type. + * + * 0 = none + * 1 = ROP/3D, layout 1, exact compression format implied by Page + * Kind field + * 2 = ROP/3D, layout 2, exact compression format implied by Page + * Kind field + * 3 = CDE horizontal + * 4 = CDE vertical + * 5 = Reserved for future use + * 6 = Reserved for future use + * 7 = Reserved for future use + * + * 55:25 - Reserved for future use. Must be zero. + */ +#define DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(c, s, g, k, h) \ + fourcc_mod_code(NVIDIA, (0x10 | \ + ((h) & 0xf) | \ + (((k) & 0xff) << 12) | \ + (((g) & 0x3) << 20) | \ + (((s) & 0x1) << 22) | \ + (((c) & 0x7) << 23))) + +/* To grandfather in prior block linear format modifiers to the above layout, + * the page kind "0", which corresponds to "pitch/linear" and hence is unusable + * with block-linear layouts, is remapped within drivers to the value 0xfe, + * which corresponds to the "generic" kind used for simple single-sample + * uncompressed color formats on Fermi - Volta GPUs. + */ +static inline uint64_t +drm_fourcc_canonicalize_nvidia_format_mod(uint64_t modifier) +{ + if (!(modifier & 0x10) || (modifier & (0xff << 12))) + return modifier; + else + return modifier | (0xfe << 12); +} + +/* + * 16Bx2 Block Linear layout, used by Tegra K1 and later * * Pixels are arranged in 64x8 Groups Of Bytes (GOBs). GOBs are then stacked * vertically by a power of 2 (1 to 32 GOBs) to form a block. @@ -541,20 +701,20 @@ extern "C" { * in full detail. */ #define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(v) \ - fourcc_mod_code(NVIDIA, 0x10 | ((v) & 0xf)) + DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0, (v)) #define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB \ - fourcc_mod_code(NVIDIA, 0x10) + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0) #define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB \ - fourcc_mod_code(NVIDIA, 0x11) + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1) #define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB \ - fourcc_mod_code(NVIDIA, 0x12) + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2) #define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB \ - fourcc_mod_code(NVIDIA, 0x13) + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3) #define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB \ - fourcc_mod_code(NVIDIA, 0x14) + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4) #define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB \ - fourcc_mod_code(NVIDIA, 0x15) + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5) /* * Some Broadcom modifiers take parameters, for example the number of @@ -779,6 +939,18 @@ extern "C" { */ #define AFBC_FORMAT_MOD_BCH (1ULL << 11) +/* AFBC uncompressed storage mode + * + * Indicates that the buffer is using AFBC uncompressed storage mode. + * In this mode all superblock payloads in the buffer use the uncompressed + * storage mode, which is usually only used for data which cannot be compressed. + * The buffer layout is the same as for AFBC buffers without USM set, this only + * affects the storage mode of the individual superblocks. Note that even a + * buffer without USM set may use uncompressed storage mode for some or all + * superblocks, USM just guarantees it for all. + */ +#define AFBC_FORMAT_MOD_USM (1ULL << 12) + /* * Arm 16x16 Block U-Interleaved modifier * @@ -803,6 +975,86 @@ extern "C" { */ #define DRM_FORMAT_MOD_ALLWINNER_TILED fourcc_mod_code(ALLWINNER, 1) +/* + * Amlogic Video Framebuffer Compression modifiers + * + * Amlogic uses a proprietary lossless image compression protocol and format + * for their hardware video codec accelerators, either video decoders or + * video input encoders. + * + * It considerably reduces memory bandwidth while writing and reading + * frames in memory. + * + * The underlying storage is considered to be 3 components, 8bit or 10-bit + * per component YCbCr 420, single plane : + * - DRM_FORMAT_YUV420_8BIT + * - DRM_FORMAT_YUV420_10BIT + * + * The first 8 bits of the mode defines the layout, then the following 8 bits + * defines the options changing the layout. + * + * Not all combinations are valid, and different SoCs may support different + * combinations of layout and options. + */ +#define __fourcc_mod_amlogic_layout_mask 0xf +#define __fourcc_mod_amlogic_options_shift 8 +#define __fourcc_mod_amlogic_options_mask 0xf + +#define DRM_FORMAT_MOD_AMLOGIC_FBC(__layout, __options) \ + fourcc_mod_code(AMLOGIC, \ + ((__layout) & __fourcc_mod_amlogic_layout_mask) | \ + (((__options) & __fourcc_mod_amlogic_options_mask) \ + << __fourcc_mod_amlogic_options_shift)) + +/* Amlogic FBC Layouts */ + +/* + * Amlogic FBC Basic Layout + * + * The basic layout is composed of: + * - a body content organized in 64x32 superblocks with 4096 bytes per + * superblock in default mode. + * - a 32 bytes per 128x64 header block + * + * This layout is transferrable between Amlogic SoCs supporting this modifier. + */ +#define AMLOGIC_FBC_LAYOUT_BASIC (1ULL) + +/* + * Amlogic FBC Scatter Memory layout + * + * Indicates the header contains IOMMU references to the compressed + * frames content to optimize memory access and layout. + * + * In this mode, only the header memory address is needed, thus the + * content memory organization is tied to the current producer + * execution and cannot be saved/dumped neither transferrable between + * Amlogic SoCs supporting this modifier. + * + * Due to the nature of the layout, these buffers are not expected to + * be accessible by the user-space clients, but only accessible by the + * hardware producers and consumers. + * + * The user-space clients should expect a failure while trying to mmap + * the DMA-BUF handle returned by the producer. + */ +#define AMLOGIC_FBC_LAYOUT_SCATTER (2ULL) + +/* Amlogic FBC Layout Options Bit Mask */ + +/* + * Amlogic FBC Memory Saving mode + * + * Indicates the storage is packed when pixel size is multiple of word + * boudaries, i.e. 8bit should be stored in this mode to save allocation + * memory. + * + * This mode reduces body layout to 3072 bytes per 64x32 superblock with + * the basic layout and 3200 bytes per 64x32 superblock combined with + * the scatter layout. + */ +#define AMLOGIC_FBC_OPTION_MEM_SAVING (1ULL << 0) + #if defined(__cplusplus) } #endif diff --git a/include/standard-headers/linux/ethtool.h b/include/standard-headers/linux/ethtool.h index 1200890c86088cb3c83368f188274d11c84a7b09..0df22f7538e3227e9d2a07e5bca950046c62d00e 100644 --- a/include/standard-headers/linux/ethtool.h +++ b/include/standard-headers/linux/ethtool.h @@ -579,6 +579,76 @@ struct ethtool_pauseparam { uint32_t tx_pause; }; +/** + * enum ethtool_link_ext_state - link extended state + */ +enum ethtool_link_ext_state { + ETHTOOL_LINK_EXT_STATE_AUTONEG, + ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE, + ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH, + ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY, + ETHTOOL_LINK_EXT_STATE_NO_CABLE, + ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE, + ETHTOOL_LINK_EXT_STATE_EEPROM_ISSUE, + ETHTOOL_LINK_EXT_STATE_CALIBRATION_FAILURE, + ETHTOOL_LINK_EXT_STATE_POWER_BUDGET_EXCEEDED, + ETHTOOL_LINK_EXT_STATE_OVERHEAT, +}; + +/** + * enum ethtool_link_ext_substate_autoneg - more information in addition to + * ETHTOOL_LINK_EXT_STATE_AUTONEG. + */ +enum ethtool_link_ext_substate_autoneg { + ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED = 1, + ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED, + ETHTOOL_LINK_EXT_SUBSTATE_AN_NEXT_PAGE_EXCHANGE_FAILED, + ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED_FORCE_MODE, + ETHTOOL_LINK_EXT_SUBSTATE_AN_FEC_MISMATCH_DURING_OVERRIDE, + ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD, +}; + +/** + * enum ethtool_link_ext_substate_link_training - more information in addition to + * ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE. + */ +enum ethtool_link_ext_substate_link_training { + ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_FRAME_LOCK_NOT_ACQUIRED = 1, + ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_INHIBIT_TIMEOUT, + ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_PARTNER_DID_NOT_SET_RECEIVER_READY, + ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT, +}; + +/** + * enum ethtool_link_ext_substate_logical_mismatch - more information in addition + * to ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH. + */ +enum ethtool_link_ext_substate_link_logical_mismatch { + ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK = 1, + ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_AM_LOCK, + ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_GET_ALIGN_STATUS, + ETHTOOL_LINK_EXT_SUBSTATE_LLM_FC_FEC_IS_NOT_LOCKED, + ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED, +}; + +/** + * enum ethtool_link_ext_substate_bad_signal_integrity - more information in + * addition to ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY. + */ +enum ethtool_link_ext_substate_bad_signal_integrity { + ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS = 1, + ETHTOOL_LINK_EXT_SUBSTATE_BSI_UNSUPPORTED_RATE, +}; + +/** + * enum ethtool_link_ext_substate_cable_issue - more information in + * addition to ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE. + */ +enum ethtool_link_ext_substate_cable_issue { + ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE = 1, + ETHTOOL_LINK_EXT_SUBSTATE_CI_CABLE_TEST_FAILURE, +}; + #define ETH_GSTRING_LEN 32 /** @@ -599,6 +669,7 @@ struct ethtool_pauseparam { * @ETH_SS_SOF_TIMESTAMPING: SOF_TIMESTAMPING_* flags * @ETH_SS_TS_TX_TYPES: timestamping Tx types * @ETH_SS_TS_RX_FILTERS: timestamping Rx filters + * @ETH_SS_UDP_TUNNEL_TYPES: UDP tunnel types */ enum ethtool_stringset { ETH_SS_TEST = 0, @@ -616,6 +687,7 @@ enum ethtool_stringset { ETH_SS_SOF_TIMESTAMPING, ETH_SS_TS_TX_TYPES, ETH_SS_TS_RX_FILTERS, + ETH_SS_UDP_TUNNEL_TYPES, /* add new constants above here */ ETH_SS_COUNT @@ -1530,6 +1602,23 @@ enum ethtool_link_mode_bit_indices { ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT = 72, ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT = 73, ETHTOOL_LINK_MODE_FEC_LLRS_BIT = 74, + ETHTOOL_LINK_MODE_100000baseKR_Full_BIT = 75, + ETHTOOL_LINK_MODE_100000baseSR_Full_BIT = 76, + ETHTOOL_LINK_MODE_100000baseLR_ER_FR_Full_BIT = 77, + ETHTOOL_LINK_MODE_100000baseCR_Full_BIT = 78, + ETHTOOL_LINK_MODE_100000baseDR_Full_BIT = 79, + ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT = 80, + ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT = 81, + ETHTOOL_LINK_MODE_200000baseLR2_ER2_FR2_Full_BIT = 82, + ETHTOOL_LINK_MODE_200000baseDR2_Full_BIT = 83, + ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT = 84, + ETHTOOL_LINK_MODE_400000baseKR4_Full_BIT = 85, + ETHTOOL_LINK_MODE_400000baseSR4_Full_BIT = 86, + ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT = 87, + ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT = 88, + ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT = 89, + ETHTOOL_LINK_MODE_100baseFX_Half_BIT = 90, + ETHTOOL_LINK_MODE_100baseFX_Full_BIT = 91, /* must be last entry */ __ETHTOOL_LINK_MODE_MASK_NBITS }; @@ -1666,6 +1755,18 @@ static inline int ethtool_validate_duplex(uint8_t duplex) return 0; } +#define MASTER_SLAVE_CFG_UNSUPPORTED 0 +#define MASTER_SLAVE_CFG_UNKNOWN 1 +#define MASTER_SLAVE_CFG_MASTER_PREFERRED 2 +#define MASTER_SLAVE_CFG_SLAVE_PREFERRED 3 +#define MASTER_SLAVE_CFG_MASTER_FORCE 4 +#define MASTER_SLAVE_CFG_SLAVE_FORCE 5 +#define MASTER_SLAVE_STATE_UNSUPPORTED 0 +#define MASTER_SLAVE_STATE_UNKNOWN 1 +#define MASTER_SLAVE_STATE_MASTER 2 +#define MASTER_SLAVE_STATE_SLAVE 3 +#define MASTER_SLAVE_STATE_ERR 4 + /* Which connector port. */ #define PORT_TP 0x00 #define PORT_AUI 0x01 @@ -1904,7 +2005,9 @@ struct ethtool_link_settings { uint8_t eth_tp_mdix_ctrl; int8_t link_mode_masks_nwords; uint8_t transceiver; - uint8_t reserved1[3]; + uint8_t master_slave_cfg; + uint8_t master_slave_state; + uint8_t reserved1[1]; uint32_t reserved[7]; uint32_t link_mode_masks[0]; /* layout of link_mode_masks fields: diff --git a/include/standard-headers/linux/fuse.h b/include/standard-headers/linux/fuse.h index f4df0a40f60437c7bcbf83f7188fa302c6686d96..82c0a38b591ecf0685557bf57eac37c83a7e0512 100644 --- a/include/standard-headers/linux/fuse.h +++ b/include/standard-headers/linux/fuse.h @@ -172,6 +172,9 @@ * - add FUSE_WRITE_KILL_PRIV flag * - add FUSE_SETUPMAPPING and FUSE_REMOVEMAPPING * - add map_alignment to fuse_init_out, add FUSE_MAP_ALIGNMENT flag + * + * 7.32 + * - add flags to fuse_attr, add FUSE_ATTR_SUBMOUNT, add FUSE_SUBMOUNTS */ #ifndef _LINUX_FUSE_H @@ -203,7 +206,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 31 +#define FUSE_KERNEL_MINOR_VERSION 32 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 @@ -227,7 +230,7 @@ struct fuse_attr { uint32_t gid; uint32_t rdev; uint32_t blksize; - uint32_t padding; + uint32_t flags; }; struct fuse_kstatfs { @@ -309,7 +312,10 @@ struct fuse_file_lock { * FUSE_CACHE_SYMLINKS: cache READLINK responses * FUSE_NO_OPENDIR_SUPPORT: kernel supports zero-message opendir * FUSE_EXPLICIT_INVAL_DATA: only invalidate cached pages on explicit request - * FUSE_MAP_ALIGNMENT: map_alignment field is valid + * FUSE_MAP_ALIGNMENT: init_out.map_alignment contains log2(byte alignment) for + * foffset and moffset fields in struct + * fuse_setupmapping_out and fuse_removemapping_one. + * FUSE_SUBMOUNTS: kernel supports auto-mounting directory submounts */ #define FUSE_ASYNC_READ (1 << 0) #define FUSE_POSIX_LOCKS (1 << 1) @@ -338,6 +344,7 @@ struct fuse_file_lock { #define FUSE_NO_OPENDIR_SUPPORT (1 << 24) #define FUSE_EXPLICIT_INVAL_DATA (1 << 25) #define FUSE_MAP_ALIGNMENT (1 << 26) +#define FUSE_SUBMOUNTS (1 << 27) /** * CUSE INIT request/reply flags @@ -413,6 +420,13 @@ struct fuse_file_lock { */ #define FUSE_FSYNC_FDATASYNC (1 << 0) +/** + * fuse_attr flags + * + * FUSE_ATTR_SUBMOUNT: Object is a submount root + */ +#define FUSE_ATTR_SUBMOUNT (1 << 0) + enum fuse_opcode { FUSE_LOOKUP = 1, FUSE_FORGET = 2, /* no reply */ @@ -888,4 +902,34 @@ struct fuse_copy_file_range_in { uint64_t flags; }; +#define FUSE_SETUPMAPPING_FLAG_WRITE (1ull << 0) +#define FUSE_SETUPMAPPING_FLAG_READ (1ull << 1) +struct fuse_setupmapping_in { + /* An already open handle */ + uint64_t fh; + /* Offset into the file to start the mapping */ + uint64_t foffset; + /* Length of mapping required */ + uint64_t len; + /* Flags, FUSE_SETUPMAPPING_FLAG_* */ + uint64_t flags; + /* Offset in Memory Window */ + uint64_t moffset; +}; + +struct fuse_removemapping_in { + /* number of fuse_removemapping_one follows */ + uint32_t count; +}; + +struct fuse_removemapping_one { + /* Offset into the dax window start the unmapping */ + uint64_t moffset; + /* Length of mapping required */ + uint64_t len; +}; + +#define FUSE_REMOVEMAPPING_MAX_ENTRY \ + (PAGE_SIZE / sizeof(struct fuse_removemapping_one)) + #endif /* _LINUX_FUSE_H */ diff --git a/include/standard-headers/linux/input-event-codes.h b/include/standard-headers/linux/input-event-codes.h index ebf72c10317b48bb9dc151f20a5b6b3b1d04b595..c403b9cb0d4ed62fb0aedd2c1e7796ffc8d9d818 100644 --- a/include/standard-headers/linux/input-event-codes.h +++ b/include/standard-headers/linux/input-event-codes.h @@ -515,6 +515,9 @@ #define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */ #define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */ #define KEY_IMAGES 0x1ba /* AL Image Browser */ +#define KEY_NOTIFICATION_CENTER 0x1bc /* Show/hide the notification center */ +#define KEY_PICKUP_PHONE 0x1bd /* Answer incoming call */ +#define KEY_HANGUP_PHONE 0x1be /* Decline incoming call */ #define KEY_DEL_EOL 0x1c0 #define KEY_DEL_EOS 0x1c1 @@ -542,6 +545,7 @@ #define KEY_FN_F 0x1e2 #define KEY_FN_S 0x1e3 #define KEY_FN_B 0x1e4 +#define KEY_FN_RIGHT_SHIFT 0x1e5 #define KEY_BRL_DOT1 0x1f1 #define KEY_BRL_DOT2 0x1f2 @@ -888,7 +892,8 @@ #define SW_LINEIN_INSERT 0x0d /* set = inserted */ #define SW_MUTE_DEVICE 0x0e /* set = device disabled */ #define SW_PEN_INSERTED 0x0f /* set = pen inserted */ -#define SW_MAX_ 0x0f +#define SW_MACHINE_COVER 0x10 /* set = cover closed */ +#define SW_MAX_ 0x10 #define SW_CNT (SW_MAX_+1) /* diff --git a/include/standard-headers/linux/pci_regs.h b/include/standard-headers/linux/pci_regs.h index f9701410d3b52b7cfc549c50f08ab5478e04e385..a95d55f9f25761ab78c8ef529dc41f450f95339e 100644 --- a/include/standard-headers/linux/pci_regs.h +++ b/include/standard-headers/linux/pci_regs.h @@ -76,6 +76,7 @@ #define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */ #define PCI_LATENCY_TIMER 0x0d /* 8 bits */ #define PCI_HEADER_TYPE 0x0e /* 8 bits */ +#define PCI_HEADER_TYPE_MASK 0x7f #define PCI_HEADER_TYPE_NORMAL 0 #define PCI_HEADER_TYPE_BRIDGE 1 #define PCI_HEADER_TYPE_CARDBUS 2 @@ -246,7 +247,7 @@ #define PCI_PM_CAP_PME_D0 0x0800 /* PME# from D0 */ #define PCI_PM_CAP_PME_D1 0x1000 /* PME# from D1 */ #define PCI_PM_CAP_PME_D2 0x2000 /* PME# from D2 */ -#define PCI_PM_CAP_PME_D3 0x4000 /* PME# from D3 (hot) */ +#define PCI_PM_CAP_PME_D3hot 0x4000 /* PME# from D3 (hot) */ #define PCI_PM_CAP_PME_D3cold 0x8000 /* PME# from D3 (cold) */ #define PCI_PM_CAP_PME_SHIFT 11 /* Start of the PME Mask in PMC */ #define PCI_PM_CTRL 4 /* PM control and status register */ @@ -532,6 +533,8 @@ #define PCI_EXP_LNKCAP_SLS_32_0GB 0x00000005 /* LNKCAP2 SLS Vector bit 4 */ #define PCI_EXP_LNKCAP_MLW 0x000003f0 /* Maximum Link Width */ #define PCI_EXP_LNKCAP_ASPMS 0x00000c00 /* ASPM Support */ +#define PCI_EXP_LNKCAP_ASPM_L0S 0x00000400 /* ASPM L0s Support */ +#define PCI_EXP_LNKCAP_ASPM_L1 0x00000800 /* ASPM L1 Support */ #define PCI_EXP_LNKCAP_L0SEL 0x00007000 /* L0s Exit Latency */ #define PCI_EXP_LNKCAP_L1EL 0x00038000 /* L1 Exit Latency */ #define PCI_EXP_LNKCAP_CLKPM 0x00040000 /* Clock Power Management */ @@ -1056,6 +1059,7 @@ #define PCI_L1SS_CTL1_PCIPM_L1_1 0x00000002 /* PCI-PM L1.1 Enable */ #define PCI_L1SS_CTL1_ASPM_L1_2 0x00000004 /* ASPM L1.2 Enable */ #define PCI_L1SS_CTL1_ASPM_L1_1 0x00000008 /* ASPM L1.1 Enable */ +#define PCI_L1SS_CTL1_L1_2_MASK 0x00000005 #define PCI_L1SS_CTL1_L1SS_MASK 0x0000000f #define PCI_L1SS_CTL1_CM_RESTORE_TIME 0x0000ff00 /* Common_Mode_Restore_Time */ #define PCI_L1SS_CTL1_LTR_L12_TH_VALUE 0x03ff0000 /* LTR_L1.2_THRESHOLD_Value */ diff --git a/include/standard-headers/linux/vhost_types.h b/include/standard-headers/linux/vhost_types.h index a678d8fbaa92717b2a60329796f6111838b7ba41..486630b33287408183ce932564ad8a21095200ee 100644 --- a/include/standard-headers/linux/vhost_types.h +++ b/include/standard-headers/linux/vhost_types.h @@ -60,6 +60,17 @@ struct vhost_iotlb_msg { #define VHOST_IOTLB_UPDATE 2 #define VHOST_IOTLB_INVALIDATE 3 #define VHOST_IOTLB_ACCESS_FAIL 4 +/* + * VHOST_IOTLB_BATCH_BEGIN and VHOST_IOTLB_BATCH_END allow modifying + * multiple mappings in one go: beginning with + * VHOST_IOTLB_BATCH_BEGIN, followed by any number of + * VHOST_IOTLB_UPDATE messages, and ending with VHOST_IOTLB_BATCH_END. + * When one of these two values is used as the message type, the rest + * of the fields in the message are ignored. There's no guarantee that + * these changes take place automatically in the device. + */ +#define VHOST_IOTLB_BATCH_BEGIN 5 +#define VHOST_IOTLB_BATCH_END 6 uint8_t type; }; diff --git a/include/standard-headers/linux/virtio_9p.h b/include/standard-headers/linux/virtio_9p.h index e68f71dbe6f43942f70bbf0e26a5e7dfe19c1790..f5604fc5fb15acc1eef28cdbf58e6fe6a42fd161 100644 --- a/include/standard-headers/linux/virtio_9p.h +++ b/include/standard-headers/linux/virtio_9p.h @@ -25,7 +25,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include "standard-headers/linux/types.h" +#include "standard-headers/linux/virtio_types.h" #include "standard-headers/linux/virtio_ids.h" #include "standard-headers/linux/virtio_config.h" @@ -36,7 +36,7 @@ struct virtio_9p_config { /* length of the tag name */ - uint16_t tag_len; + __virtio16 tag_len; /* non-NULL terminated tag name */ uint8_t tag[0]; } QEMU_PACKED; diff --git a/include/standard-headers/linux/virtio_blk.h b/include/standard-headers/linux/virtio_blk.h index 0229b0fbe42b68f2cb20a9a9c2c035d11000855e..2dcc90826ae7d30ccc7169355b43800c21551214 100644 --- a/include/standard-headers/linux/virtio_blk.h +++ b/include/standard-headers/linux/virtio_blk.h @@ -55,20 +55,20 @@ struct virtio_blk_config { /* The capacity (in 512-byte sectors). */ - uint64_t capacity; + __virtio64 capacity; /* The maximum segment size (if VIRTIO_BLK_F_SIZE_MAX) */ - uint32_t size_max; + __virtio32 size_max; /* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */ - uint32_t seg_max; + __virtio32 seg_max; /* geometry of the device (if VIRTIO_BLK_F_GEOMETRY) */ struct virtio_blk_geometry { - uint16_t cylinders; + __virtio16 cylinders; uint8_t heads; uint8_t sectors; } geometry; /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */ - uint32_t blk_size; + __virtio32 blk_size; /* the next 4 entries are guarded by VIRTIO_BLK_F_TOPOLOGY */ /* exponent for physical block per logical block. */ @@ -76,42 +76,42 @@ struct virtio_blk_config { /* alignment offset in logical blocks. */ uint8_t alignment_offset; /* minimum I/O size without performance penalty in logical blocks. */ - uint16_t min_io_size; + __virtio16 min_io_size; /* optimal sustained I/O size in logical blocks. */ - uint32_t opt_io_size; + __virtio32 opt_io_size; /* writeback mode (if VIRTIO_BLK_F_CONFIG_WCE) */ uint8_t wce; uint8_t unused; /* number of vqs, only available when VIRTIO_BLK_F_MQ is set */ - uint16_t num_queues; + __virtio16 num_queues; /* the next 3 entries are guarded by VIRTIO_BLK_F_DISCARD */ /* * The maximum discard sectors (in 512-byte sectors) for * one segment. */ - uint32_t max_discard_sectors; + __virtio32 max_discard_sectors; /* * The maximum number of discard segments in a * discard command. */ - uint32_t max_discard_seg; + __virtio32 max_discard_seg; /* Discard commands must be aligned to this number of sectors. */ - uint32_t discard_sector_alignment; + __virtio32 discard_sector_alignment; /* the next 3 entries are guarded by VIRTIO_BLK_F_WRITE_ZEROES */ /* * The maximum number of write zeroes sectors (in 512-byte sectors) in * one segment. */ - uint32_t max_write_zeroes_sectors; + __virtio32 max_write_zeroes_sectors; /* * The maximum number of segments in a write zeroes * command. */ - uint32_t max_write_zeroes_seg; + __virtio32 max_write_zeroes_seg; /* * Set if a VIRTIO_BLK_T_WRITE_ZEROES request may result in the * deallocation of one or more of the sectors. diff --git a/include/standard-headers/linux/virtio_config.h b/include/standard-headers/linux/virtio_config.h index 9a69d9e2420b85d4e1cc5dd24303b9da08d9f732..22e3a85f6760920cb3d3b49d064a0b421b0e76cc 100644 --- a/include/standard-headers/linux/virtio_config.h +++ b/include/standard-headers/linux/virtio_config.h @@ -67,13 +67,15 @@ #define VIRTIO_F_VERSION_1 32 /* - * If clear - device has the IOMMU bypass quirk feature. - * If set - use platform tools to detect the IOMMU. + * If clear - device has the platform DMA (e.g. IOMMU) bypass quirk feature. + * If set - use platform DMA tools to access the memory. * * Note the reverse polarity (compared to most other features), * this is for compatibility with legacy systems. */ -#define VIRTIO_F_IOMMU_PLATFORM 33 +#define VIRTIO_F_ACCESS_PLATFORM 33 +/* Legacy name for VIRTIO_F_ACCESS_PLATFORM (for compatibility with old userspace) */ +#define VIRTIO_F_IOMMU_PLATFORM VIRTIO_F_ACCESS_PLATFORM /* This feature indicates support for the packed virtqueue layout. */ #define VIRTIO_F_RING_PACKED 34 diff --git a/include/standard-headers/linux/virtio_console.h b/include/standard-headers/linux/virtio_console.h index 0dedc9e6f5738a3924cd6ae52a9edee904724a80..71f5f648e3ceac58b80c67d236fbf09bcdc6390b 100644 --- a/include/standard-headers/linux/virtio_console.h +++ b/include/standard-headers/linux/virtio_console.h @@ -45,13 +45,13 @@ struct virtio_console_config { /* colums of the screens */ - uint16_t cols; + __virtio16 cols; /* rows of the screens */ - uint16_t rows; + __virtio16 rows; /* max. number of ports this device can hold */ - uint32_t max_nr_ports; + __virtio32 max_nr_ports; /* emergency write register */ - uint32_t emerg_wr; + __virtio32 emerg_wr; } QEMU_PACKED; /* diff --git a/include/standard-headers/linux/virtio_fs.h b/include/standard-headers/linux/virtio_fs.h index 9d88817a6b665193d3cf0c5faf936e23f895d7aa..a32fe8a64c76ccdef5c1057e39c89e5479d29e96 100644 --- a/include/standard-headers/linux/virtio_fs.h +++ b/include/standard-headers/linux/virtio_fs.h @@ -16,4 +16,7 @@ struct virtio_fs_config { uint32_t num_request_queues; } QEMU_PACKED; +/* For the id field in virtio_pci_shm_cap */ +#define VIRTIO_FS_SHMCAP_ID_CACHE 0 + #endif /* _LINUX_VIRTIO_FS_H */ diff --git a/include/standard-headers/linux/virtio_gpu.h b/include/standard-headers/linux/virtio_gpu.h index b8fa15f0ace75d207a098e1fb9d6ce91094850b4..4183cdc74b33fc510a83f3c472933105db6b6f59 100644 --- a/include/standard-headers/linux/virtio_gpu.h +++ b/include/standard-headers/linux/virtio_gpu.h @@ -50,6 +50,10 @@ * VIRTIO_GPU_CMD_GET_EDID */ #define VIRTIO_GPU_F_EDID 1 +/* + * VIRTIO_GPU_CMD_RESOURCE_ASSIGN_UUID + */ +#define VIRTIO_GPU_F_RESOURCE_UUID 2 enum virtio_gpu_ctrl_type { VIRTIO_GPU_UNDEFINED = 0, @@ -66,6 +70,7 @@ enum virtio_gpu_ctrl_type { VIRTIO_GPU_CMD_GET_CAPSET_INFO, VIRTIO_GPU_CMD_GET_CAPSET, VIRTIO_GPU_CMD_GET_EDID, + VIRTIO_GPU_CMD_RESOURCE_ASSIGN_UUID, /* 3d commands */ VIRTIO_GPU_CMD_CTX_CREATE = 0x0200, @@ -87,6 +92,7 @@ enum virtio_gpu_ctrl_type { VIRTIO_GPU_RESP_OK_CAPSET_INFO, VIRTIO_GPU_RESP_OK_CAPSET, VIRTIO_GPU_RESP_OK_EDID, + VIRTIO_GPU_RESP_OK_RESOURCE_UUID, /* error responses */ VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200, @@ -340,4 +346,17 @@ enum virtio_gpu_formats { VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM = 134, }; +/* VIRTIO_GPU_CMD_RESOURCE_ASSIGN_UUID */ +struct virtio_gpu_resource_assign_uuid { + struct virtio_gpu_ctrl_hdr hdr; + uint32_t resource_id; + uint32_t padding; +}; + +/* VIRTIO_GPU_RESP_OK_RESOURCE_UUID */ +struct virtio_gpu_resp_resource_uuid { + struct virtio_gpu_ctrl_hdr hdr; + uint8_t uuid[16]; +}; + #endif diff --git a/include/standard-headers/linux/virtio_ids.h b/include/standard-headers/linux/virtio_ids.h index ecc27a17401a76b8ae8a907859d1461bda26c881..b052355ac7a324e173f4ea44c48d8b757fa687cf 100644 --- a/include/standard-headers/linux/virtio_ids.h +++ b/include/standard-headers/linux/virtio_ids.h @@ -44,6 +44,7 @@ #define VIRTIO_ID_VSOCK 19 /* virtio vsock transport */ #define VIRTIO_ID_CRYPTO 20 /* virtio crypto */ #define VIRTIO_ID_IOMMU 23 /* virtio IOMMU */ +#define VIRTIO_ID_MEM 24 /* virtio mem */ #define VIRTIO_ID_FS 26 /* virtio filesystem */ #define VIRTIO_ID_PMEM 27 /* virtio pmem */ #define VIRTIO_ID_MAC80211_HWSIM 29 /* virtio mac80211-hwsim */ diff --git a/include/standard-headers/linux/virtio_mem.h b/include/standard-headers/linux/virtio_mem.h new file mode 100644 index 0000000000000000000000000000000000000000..05e5ade75d3d8d2533c63d4fb4fe1c9026d86751 --- /dev/null +++ b/include/standard-headers/linux/virtio_mem.h @@ -0,0 +1,211 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Virtio Mem Device + * + * Copyright Red Hat, Inc. 2020 + * + * Authors: + * David Hildenbrand + * + * This header is BSD licensed so anyone can use the definitions + * to implement compatible drivers/servers: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IBM OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUX_VIRTIO_MEM_H +#define _LINUX_VIRTIO_MEM_H + +#include "standard-headers/linux/types.h" +#include "standard-headers/linux/virtio_types.h" +#include "standard-headers/linux/virtio_ids.h" +#include "standard-headers/linux/virtio_config.h" + +/* + * Each virtio-mem device manages a dedicated region in physical address + * space. Each device can belong to a single NUMA node, multiple devices + * for a single NUMA node are possible. A virtio-mem device is like a + * "resizable DIMM" consisting of small memory blocks that can be plugged + * or unplugged. The device driver is responsible for (un)plugging memory + * blocks on demand. + * + * Virtio-mem devices can only operate on their assigned memory region in + * order to (un)plug memory. A device cannot (un)plug memory belonging to + * other devices. + * + * The "region_size" corresponds to the maximum amount of memory that can + * be provided by a device. The "size" corresponds to the amount of memory + * that is currently plugged. "requested_size" corresponds to a request + * from the device to the device driver to (un)plug blocks. The + * device driver should try to (un)plug blocks in order to reach the + * "requested_size". It is impossible to plug more memory than requested. + * + * The "usable_region_size" represents the memory region that can actually + * be used to (un)plug memory. It is always at least as big as the + * "requested_size" and will grow dynamically. It will only shrink when + * explicitly triggered (VIRTIO_MEM_REQ_UNPLUG). + * + * There are no guarantees what will happen if unplugged memory is + * read/written. Such memory should, in general, not be touched. E.g., + * even writing might succeed, but the values will simply be discarded at + * random points in time. + * + * It can happen that the device cannot process a request, because it is + * busy. The device driver has to retry later. + * + * Usually, during system resets all memory will get unplugged, so the + * device driver can start with a clean state. However, in specific + * scenarios (if the device is busy) it can happen that the device still + * has memory plugged. The device driver can request to unplug all memory + * (VIRTIO_MEM_REQ_UNPLUG) - which might take a while to succeed if the + * device is busy. + */ + +/* --- virtio-mem: feature bits --- */ + +/* node_id is an ACPI PXM and is valid */ +#define VIRTIO_MEM_F_ACPI_PXM 0 + + +/* --- virtio-mem: guest -> host requests --- */ + +/* request to plug memory blocks */ +#define VIRTIO_MEM_REQ_PLUG 0 +/* request to unplug memory blocks */ +#define VIRTIO_MEM_REQ_UNPLUG 1 +/* request to unplug all blocks and shrink the usable size */ +#define VIRTIO_MEM_REQ_UNPLUG_ALL 2 +/* request information about the plugged state of memory blocks */ +#define VIRTIO_MEM_REQ_STATE 3 + +struct virtio_mem_req_plug { + __virtio64 addr; + __virtio16 nb_blocks; + __virtio16 padding[3]; +}; + +struct virtio_mem_req_unplug { + __virtio64 addr; + __virtio16 nb_blocks; + __virtio16 padding[3]; +}; + +struct virtio_mem_req_state { + __virtio64 addr; + __virtio16 nb_blocks; + __virtio16 padding[3]; +}; + +struct virtio_mem_req { + __virtio16 type; + __virtio16 padding[3]; + + union { + struct virtio_mem_req_plug plug; + struct virtio_mem_req_unplug unplug; + struct virtio_mem_req_state state; + } u; +}; + + +/* --- virtio-mem: host -> guest response --- */ + +/* + * Request processed successfully, applicable for + * - VIRTIO_MEM_REQ_PLUG + * - VIRTIO_MEM_REQ_UNPLUG + * - VIRTIO_MEM_REQ_UNPLUG_ALL + * - VIRTIO_MEM_REQ_STATE + */ +#define VIRTIO_MEM_RESP_ACK 0 +/* + * Request denied - e.g. trying to plug more than requested, applicable for + * - VIRTIO_MEM_REQ_PLUG + */ +#define VIRTIO_MEM_RESP_NACK 1 +/* + * Request cannot be processed right now, try again later, applicable for + * - VIRTIO_MEM_REQ_PLUG + * - VIRTIO_MEM_REQ_UNPLUG + * - VIRTIO_MEM_REQ_UNPLUG_ALL + */ +#define VIRTIO_MEM_RESP_BUSY 2 +/* + * Error in request (e.g. addresses/alignment), applicable for + * - VIRTIO_MEM_REQ_PLUG + * - VIRTIO_MEM_REQ_UNPLUG + * - VIRTIO_MEM_REQ_STATE + */ +#define VIRTIO_MEM_RESP_ERROR 3 + + +/* State of memory blocks is "plugged" */ +#define VIRTIO_MEM_STATE_PLUGGED 0 +/* State of memory blocks is "unplugged" */ +#define VIRTIO_MEM_STATE_UNPLUGGED 1 +/* State of memory blocks is "mixed" */ +#define VIRTIO_MEM_STATE_MIXED 2 + +struct virtio_mem_resp_state { + __virtio16 state; +}; + +struct virtio_mem_resp { + __virtio16 type; + __virtio16 padding[3]; + + union { + struct virtio_mem_resp_state state; + } u; +}; + +/* --- virtio-mem: configuration --- */ + +struct virtio_mem_config { + /* Block size and alignment. Cannot change. */ + uint64_t block_size; + /* Valid with VIRTIO_MEM_F_ACPI_PXM. Cannot change. */ + uint16_t node_id; + uint8_t padding[6]; + /* Start address of the memory region. Cannot change. */ + uint64_t addr; + /* Region size (maximum). Cannot change. */ + uint64_t region_size; + /* + * Currently usable region size. Can grow up to region_size. Can + * shrink due to VIRTIO_MEM_REQ_UNPLUG_ALL (in which case no config + * update will be sent). + */ + uint64_t usable_region_size; + /* + * Currently used size. Changes due to plug/unplug requests, but no + * config updates will be sent. + */ + uint64_t plugged_size; + /* Requested size. New plug requests cannot exceed it. Can change. */ + uint64_t requested_size; +}; + +#endif /* _LINUX_VIRTIO_MEM_H */ diff --git a/include/standard-headers/linux/virtio_mmio.h b/include/standard-headers/linux/virtio_mmio.h index c4b09689ab644719d1aa28fdb9510dfe9c5a8b5b..0650f91bea6c70f935764070d825d181a2379afb 100644 --- a/include/standard-headers/linux/virtio_mmio.h +++ b/include/standard-headers/linux/virtio_mmio.h @@ -122,6 +122,17 @@ #define VIRTIO_MMIO_QUEUE_USED_LOW 0x0a0 #define VIRTIO_MMIO_QUEUE_USED_HIGH 0x0a4 +/* Shared memory region id */ +#define VIRTIO_MMIO_SHM_SEL 0x0ac + +/* Shared memory region length, 64 bits in two halves */ +#define VIRTIO_MMIO_SHM_LEN_LOW 0x0b0 +#define VIRTIO_MMIO_SHM_LEN_HIGH 0x0b4 + +/* Shared memory region base address, 64 bits in two halves */ +#define VIRTIO_MMIO_SHM_BASE_LOW 0x0b8 +#define VIRTIO_MMIO_SHM_BASE_HIGH 0x0bc + /* Configuration atomicity value */ #define VIRTIO_MMIO_CONFIG_GENERATION 0x0fc diff --git a/include/standard-headers/linux/virtio_net.h b/include/standard-headers/linux/virtio_net.h index a90f79e1b17a9228353eac109f55b3af8dcde270..e0a070518f39d2b4b227e1a38a285bd0f34b0a2c 100644 --- a/include/standard-headers/linux/virtio_net.h +++ b/include/standard-headers/linux/virtio_net.h @@ -87,14 +87,14 @@ struct virtio_net_config { /* The config defining mac address (if VIRTIO_NET_F_MAC) */ uint8_t mac[ETH_ALEN]; /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */ - uint16_t status; + __virtio16 status; /* Maximum number of each of transmit and receive queues; * see VIRTIO_NET_F_MQ and VIRTIO_NET_CTRL_MQ. * Legal values are between 1 and 0x8000 */ - uint16_t max_virtqueue_pairs; + __virtio16 max_virtqueue_pairs; /* Default maximum transmit unit advice */ - uint16_t mtu; + __virtio16 mtu; /* * speed, in units of 1Mb. All values 0 to INT_MAX are legal. * Any other value stands for unknown. diff --git a/include/standard-headers/linux/virtio_pci.h b/include/standard-headers/linux/virtio_pci.h index 9262acd130c38b874eddf9254382bdda5dfdbd34..db7a8e2fcbf2639bdafa15d78693ec339eb0c430 100644 --- a/include/standard-headers/linux/virtio_pci.h +++ b/include/standard-headers/linux/virtio_pci.h @@ -113,6 +113,8 @@ #define VIRTIO_PCI_CAP_DEVICE_CFG 4 /* PCI configuration access */ #define VIRTIO_PCI_CAP_PCI_CFG 5 +/* Additional shared memory capability */ +#define VIRTIO_PCI_CAP_SHARED_MEMORY_CFG 8 /* This is the PCI capability header: */ struct virtio_pci_cap { @@ -121,11 +123,18 @@ struct virtio_pci_cap { uint8_t cap_len; /* Generic PCI field: capability length */ uint8_t cfg_type; /* Identifies the structure. */ uint8_t bar; /* Where to find it. */ - uint8_t padding[3]; /* Pad to full dword. */ + uint8_t id; /* Multiple capabilities of the same type */ + uint8_t padding[2]; /* Pad to full dword. */ uint32_t offset; /* Offset within bar. */ uint32_t length; /* Length of the structure, in bytes. */ }; +struct virtio_pci_cap64 { + struct virtio_pci_cap cap; + uint32_t offset_hi; /* Most sig 32 bits of offset */ + uint32_t length_hi; /* Most sig 32 bits of length */ +}; + struct virtio_pci_notify_cap { struct virtio_pci_cap cap; uint32_t notify_off_multiplier; /* Multiplier for queue_notify_off. */ diff --git a/include/standard-headers/linux/virtio_ring.h b/include/standard-headers/linux/virtio_ring.h index f230fed479601c06c40b1a82aae1ede7ac82bd4e..0fa0e1067ffe56c40a4034ed036893146008f0f5 100644 --- a/include/standard-headers/linux/virtio_ring.h +++ b/include/standard-headers/linux/virtio_ring.h @@ -84,6 +84,13 @@ * at the end of the used ring. Guest should ignore the used->flags field. */ #define VIRTIO_RING_F_EVENT_IDX 29 +/* Alignment requirements for vring elements. + * When using pre-virtio 1.0 layout, these fall out naturally. + */ +#define VRING_AVAIL_ALIGN_SIZE 2 +#define VRING_USED_ALIGN_SIZE 4 +#define VRING_DESC_ALIGN_SIZE 16 + /* Virtio ring descriptors: 16 bytes. These can chain together via "next". */ struct vring_desc { /* Address (guest-physical). */ @@ -110,28 +117,47 @@ struct vring_used_elem { __virtio32 len; }; +typedef struct vring_used_elem __attribute__((aligned(VRING_USED_ALIGN_SIZE))) + vring_used_elem_t; + struct vring_used { __virtio16 flags; __virtio16 idx; - struct vring_used_elem ring[]; + vring_used_elem_t ring[]; }; +/* + * The ring element addresses are passed between components with different + * alignments assumptions. Thus, we might need to decrease the compiler-selected + * alignment, and so must use a typedef to make sure the aligned attribute + * actually takes hold: + * + * https://gcc.gnu.org/onlinedocs//gcc/Common-Type-Attributes.html#Common-Type-Attributes + * + * When used on a struct, or struct member, the aligned attribute can only + * increase the alignment; in order to decrease it, the packed attribute must + * be specified as well. When used as part of a typedef, the aligned attribute + * can both increase and decrease alignment, and specifying the packed + * attribute generates a warning. + */ +typedef struct vring_desc __attribute__((aligned(VRING_DESC_ALIGN_SIZE))) + vring_desc_t; +typedef struct vring_avail __attribute__((aligned(VRING_AVAIL_ALIGN_SIZE))) + vring_avail_t; +typedef struct vring_used __attribute__((aligned(VRING_USED_ALIGN_SIZE))) + vring_used_t; + struct vring { unsigned int num; - struct vring_desc *desc; + vring_desc_t *desc; - struct vring_avail *avail; + vring_avail_t *avail; - struct vring_used *used; + vring_used_t *used; }; -/* Alignment requirements for vring elements. - * When using pre-virtio 1.0 layout, these fall out naturally. - */ -#define VRING_AVAIL_ALIGN_SIZE 2 -#define VRING_USED_ALIGN_SIZE 4 -#define VRING_DESC_ALIGN_SIZE 16 +#ifndef VIRTIO_RING_NO_LEGACY /* The standard layout for the ring is a continuous chunk of memory which looks * like this. We assume num is a power of 2. @@ -179,6 +205,8 @@ static inline unsigned vring_size(unsigned int num, unsigned long align) + sizeof(__virtio16) * 3 + sizeof(struct vring_used_elem) * num; } +#endif /* VIRTIO_RING_NO_LEGACY */ + /* The following is used with USED_EVENT_IDX and AVAIL_EVENT_IDX */ /* Assuming a given event_idx value from the other side, if * we have just incremented index from old to new_idx, diff --git a/include/standard-headers/linux/virtio_scsi.h b/include/standard-headers/linux/virtio_scsi.h index ab66166b6a78c2be680b82bdffba49b4894c524e..663f36cbb769efae4408478d9d6ad0b5c57a2328 100644 --- a/include/standard-headers/linux/virtio_scsi.h +++ b/include/standard-headers/linux/virtio_scsi.h @@ -103,16 +103,16 @@ struct virtio_scsi_event { } QEMU_PACKED; struct virtio_scsi_config { - uint32_t num_queues; - uint32_t seg_max; - uint32_t max_sectors; - uint32_t cmd_per_lun; - uint32_t event_info_size; - uint32_t sense_size; - uint32_t cdb_size; - uint16_t max_channel; - uint16_t max_target; - uint32_t max_lun; + __virtio32 num_queues; + __virtio32 seg_max; + __virtio32 max_sectors; + __virtio32 cmd_per_lun; + __virtio32 event_info_size; + __virtio32 sense_size; + __virtio32 cdb_size; + __virtio16 max_channel; + __virtio16 max_target; + __virtio32 max_lun; } QEMU_PACKED; /* Feature Bits */ diff --git a/include/sysemu/accel.h b/include/sysemu/accel.h index 47e5788530cd80c3692407a03e171f75f68dcd27..e08b8ab8fa32aeaa85d7197c340ce3eeaec45a93 100644 --- a/include/sysemu/accel.h +++ b/include/sysemu/accel.h @@ -37,10 +37,12 @@ typedef struct AccelClass { /*< public >*/ const char *name; +#ifndef CONFIG_USER_ONLY int (*init_machine)(MachineState *ms); void (*setup_post)(MachineState *ms, AccelState *accel); bool (*has_memory)(MachineState *ms, AddressSpace *as, hwaddr start_addr, hwaddr size); +#endif bool *allowed; /* * Array of global properties that would be applied when specific diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h index 71a7a285ee69b7f23194c34547ed56bdb79dac82..54f069d49126c601117ffd2e1b9490d6632389ba 100644 --- a/include/sysemu/arch_init.h +++ b/include/sysemu/arch_init.h @@ -25,6 +25,7 @@ enum { QEMU_ARCH_HPPA = (1 << 18), QEMU_ARCH_RISCV = (1 << 19), QEMU_ARCH_RX = (1 << 20), + QEMU_ARCH_AVR = (1 << 21), QEMU_ARCH_NONE = (1 << 31), }; diff --git a/include/sysemu/balloon.h b/include/sysemu/balloon.h index aea0c449850e941d6e88893fed3fac31bcc55124..867687b73ac27e7aeddacf1ce59b31bc393b28bc 100644 --- a/include/sysemu/balloon.h +++ b/include/sysemu/balloon.h @@ -15,7 +15,7 @@ #define QEMU_BALLOON_H #include "exec/cpu-common.h" -#include "qapi/qapi-types-misc.h" +#include "qapi/qapi-types-machine.h" typedef void (QEMUBalloonEvent)(void *opaque, ram_addr_t target); typedef void (QEMUBalloonStatus)(void *opaque, BalloonInfo *info); @@ -23,7 +23,5 @@ typedef void (QEMUBalloonStatus)(void *opaque, BalloonInfo *info); int qemu_add_balloon_handler(QEMUBalloonEvent *event_func, QEMUBalloonStatus *stat_func, void *opaque); void qemu_remove_balloon_handler(void *opaque); -bool qemu_balloon_is_inhibited(void); -void qemu_balloon_inhibit(bool state); #endif diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index a86d99b3d8751b9c4eefa53dd895cfd28c1aa747..3b5fcda08d346a3d402637c20c745cbf3ff68157 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -35,6 +35,7 @@ struct DriveInfo { bool is_default; /* Added by default_drive() ? */ int media_cd; QemuOpts *opts; + bool claimed_by_board; QTAILQ_ENTRY(DriveInfo) next; }; @@ -45,6 +46,7 @@ BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo); void override_max_devs(BlockInterfaceType type, int max_devs); DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit); +void drive_mark_claimed_by_board(void); void drive_check_orphaned(void); DriveInfo *drive_get_by_index(BlockInterfaceType type, int index); int drive_get_max_bus(BlockInterfaceType type); diff --git a/include/sysemu/cpu-throttle.h b/include/sysemu/cpu-throttle.h new file mode 100644 index 0000000000000000000000000000000000000000..d65bdef6d030c19bed65a9ddab42df2be48fcd1e --- /dev/null +++ b/include/sysemu/cpu-throttle.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2012 SUSE LINUX Products GmbH + * + * 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 + * + */ + +#ifndef SYSEMU_CPU_THROTTLE_H +#define SYSEMU_CPU_THROTTLE_H + +#include "qemu/timer.h" + +/** + * cpu_throttle_init: + * + * Initialize the CPU throttling API. + */ +void cpu_throttle_init(void); + +/** + * cpu_throttle_set: + * @new_throttle_pct: Percent of sleep time. Valid range is 1 to 99. + * + * Throttles all vcpus by forcing them to sleep for the given percentage of + * time. A throttle_percentage of 25 corresponds to a 75% duty cycle roughly. + * (example: 10ms sleep for every 30ms awake). + * + * cpu_throttle_set can be called as needed to adjust new_throttle_pct. + * Once the throttling starts, it will remain in effect until cpu_throttle_stop + * is called. + */ +void cpu_throttle_set(int new_throttle_pct); + +/** + * cpu_throttle_stop: + * + * Stops the vcpu throttling started by cpu_throttle_set. + */ +void cpu_throttle_stop(void); + +/** + * cpu_throttle_active: + * + * Returns: %true if the vcpus are currently being throttled, %false otherwise. + */ +bool cpu_throttle_active(void); + +/** + * cpu_throttle_get_percentage: + * + * Returns the vcpu throttle percentage. See cpu_throttle_set for details. + * + * Returns: The throttle percentage in range 1 to 99. + */ +int cpu_throttle_get_percentage(void); + +#endif /* SYSEMU_CPU_THROTTLE_H */ diff --git a/include/sysemu/cpu-timers.h b/include/sysemu/cpu-timers.h new file mode 100644 index 0000000000000000000000000000000000000000..ed6ee5c46ccdc74428aa63b3e196138654dd2ef5 --- /dev/null +++ b/include/sysemu/cpu-timers.h @@ -0,0 +1,90 @@ +/* + * CPU timers state API + * + * Copyright 2020 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ +#ifndef SYSEMU_CPU_TIMERS_H +#define SYSEMU_CPU_TIMERS_H + +#include "qemu/timer.h" + +/* init the whole cpu timers API, including icount, ticks, and cpu_throttle */ +void cpu_timers_init(void); + +/* icount - Instruction Counter API */ + +/* + * icount enablement state: + * + * 0 = Disabled - Do not count executed instructions. + * 1 = Enabled - Fixed conversion of insn to ns via "shift" option + * 2 = Enabled - Runtime adaptive algorithm to compute shift + */ +#ifdef CONFIG_TCG +extern int use_icount; +#define icount_enabled() (use_icount) +#else +#define icount_enabled() 0 +#endif + +/* + * Update the icount with the executed instructions. Called by + * cpus-tcg vCPU thread so the main-loop can see time has moved forward. + */ +void icount_update(CPUState *cpu); + +/* get raw icount value */ +int64_t icount_get_raw(void); + +/* return the virtual CPU time in ns, based on the instruction counter. */ +int64_t icount_get(void); +/* + * convert an instruction counter value to ns, based on the icount shift. + * This shift is set as a fixed value with the icount "shift" option + * (precise mode), or it is constantly approximated and corrected at + * runtime in adaptive mode. + */ +int64_t icount_to_ns(int64_t icount); + +/* configure the icount options, including "shift" */ +void icount_configure(QemuOpts *opts, Error **errp); + +/* used by tcg vcpu thread to calc icount budget */ +int64_t icount_round(int64_t count); + +/* if the CPUs are idle, start accounting real time to virtual clock. */ +void icount_start_warp_timer(void); +void icount_account_warp_timer(void); + +/* + * CPU Ticks and Clock + */ + +/* Caller must hold BQL */ +void cpu_enable_ticks(void); +/* Caller must hold BQL */ +void cpu_disable_ticks(void); + +/* + * return the time elapsed in VM between vm_start and vm_stop. + * cpu_get_ticks() uses units of the host CPU cycle counter. + */ +int64_t cpu_get_ticks(void); + +/* + * Returns the monotonic time elapsed in VM, i.e., + * the time between vm_start and vm_stop + */ +int64_t cpu_get_clock(void); + +void qemu_timer_notify_cb(void *opaque, QEMUClockType type); + +/* get the VIRTUAL clock and VM elapsed ticks via the cpus accel interface */ +int64_t cpus_get_virtual_clock(void); +int64_t cpus_get_elapsed_ticks(void); + +#endif /* SYSEMU_CPU_TIMERS_H */ diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h index 3c1da6a0183d092c2578916633293e740043bc7b..e8156728c63d2689c96b4fb007a43a4cd2a6cb67 100644 --- a/include/sysemu/cpus.h +++ b/include/sysemu/cpus.h @@ -4,33 +4,64 @@ #include "qemu/timer.h" /* cpus.c */ + +/* CPU execution threads */ + +typedef struct CpusAccel { + void (*create_vcpu_thread)(CPUState *cpu); /* MANDATORY */ + void (*kick_vcpu_thread)(CPUState *cpu); + + void (*synchronize_post_reset)(CPUState *cpu); + void (*synchronize_post_init)(CPUState *cpu); + void (*synchronize_state)(CPUState *cpu); + void (*synchronize_pre_loadvm)(CPUState *cpu); + + void (*handle_interrupt)(CPUState *cpu, int mask); + + int64_t (*get_virtual_clock)(void); + int64_t (*get_elapsed_ticks)(void); +} CpusAccel; + +/* register accel-specific cpus interface implementation */ +void cpus_register_accel(const CpusAccel *i); + +/* Create a dummy vcpu for CpusAccel->create_vcpu_thread */ +void dummy_start_vcpu_thread(CPUState *); + +/* interface available for cpus accelerator threads */ + +/* For temporary buffers for forming a name */ +#define VCPU_THREAD_NAME_SIZE 16 + +void cpus_kick_thread(CPUState *cpu); +bool cpu_work_list_empty(CPUState *cpu); +bool cpu_thread_is_idle(CPUState *cpu); +bool all_cpu_threads_idle(void); +bool cpu_can_run(CPUState *cpu); +void qemu_wait_io_event_common(CPUState *cpu); +void qemu_wait_io_event(CPUState *cpu); +void cpu_thread_signal_created(CPUState *cpu); +void cpu_thread_signal_destroyed(CPUState *cpu); +void cpu_handle_guest_debug(CPUState *cpu); + +/* end interface for cpus accelerator threads */ + bool qemu_in_vcpu_thread(void); void qemu_init_cpu_loop(void); void resume_all_vcpus(void); void pause_all_vcpus(void); void cpu_stop_current(void); -void cpu_ticks_init(void); -void configure_icount(QemuOpts *opts, Error **errp); -extern int use_icount; extern int icount_align_option; -/* drift information for info jit command */ -extern int64_t max_delay; -extern int64_t max_advance; -void dump_drift_info(void); - /* Unblock cpu */ void qemu_cpu_kick_self(void); -void qemu_timer_notify_cb(void *opaque, QEMUClockType type); void cpu_synchronize_all_states(void); void cpu_synchronize_all_post_reset(void); void cpu_synchronize_all_post_init(void); void cpu_synchronize_all_pre_loadvm(void); -void qtest_clock_warp(int64_t dest); - #ifndef CONFIG_USER_ONLY /* vl.c */ /* *-user doesn't have configurable SMP topology */ diff --git a/include/sysemu/cryptodev-vhost-user.h b/include/sysemu/cryptodev-vhost-user.h index 0d3421e7e8ca2ec315d35d1bce62b8dd4e5014fd..60710502c2d177ccdf3cb32f8c001f1638b8607a 100644 --- a/include/sysemu/cryptodev-vhost-user.h +++ b/include/sysemu/cryptodev-vhost-user.h @@ -9,7 +9,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/sysemu/cryptodev-vhost.h b/include/sysemu/cryptodev-vhost.h index f42824fbde43cebbdd58ec8cef3c313d507367eb..e8cab1356e490a436e9f7ab729e3df9b9a0c6b7c 100644 --- a/include/sysemu/cryptodev-vhost.h +++ b/include/sysemu/cryptodev-vhost.h @@ -10,7 +10,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/include/sysemu/cryptodev.h b/include/sysemu/cryptodev.h index 35eab06d0e314513ada817a57065ee98069cc008..f4d4057d4da6009493e52cc04e7baf01373b9c8b 100644 --- a/include/sysemu/cryptodev.h +++ b/include/sysemu/cryptodev.h @@ -9,7 +9,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -37,15 +37,8 @@ #define TYPE_CRYPTODEV_BACKEND "cryptodev-backend" -#define CRYPTODEV_BACKEND(obj) \ - OBJECT_CHECK(CryptoDevBackend, \ - (obj), TYPE_CRYPTODEV_BACKEND) -#define CRYPTODEV_BACKEND_GET_CLASS(obj) \ - OBJECT_GET_CLASS(CryptoDevBackendClass, \ - (obj), TYPE_CRYPTODEV_BACKEND) -#define CRYPTODEV_BACKEND_CLASS(klass) \ - OBJECT_CLASS_CHECK(CryptoDevBackendClass, \ - (klass), TYPE_CRYPTODEV_BACKEND) +OBJECT_DECLARE_TYPE(CryptoDevBackend, CryptoDevBackendClass, + CRYPTODEV_BACKEND) #define MAX_CRYPTO_QUEUE_NUM 64 @@ -54,7 +47,6 @@ typedef struct CryptoDevBackendConf CryptoDevBackendConf; typedef struct CryptoDevBackendPeers CryptoDevBackendPeers; typedef struct CryptoDevBackendClient CryptoDevBackendClient; -typedef struct CryptoDevBackend CryptoDevBackend; enum CryptoDevBackendAlgType { CRYPTODEV_BACKEND_ALG_SYM, @@ -146,7 +138,7 @@ typedef struct CryptoDevBackendSymOpInfo { uint8_t data[]; } CryptoDevBackendSymOpInfo; -typedef struct CryptoDevBackendClass { +struct CryptoDevBackendClass { ObjectClass parent_class; void (*init)(CryptoDevBackend *backend, Error **errp); @@ -161,7 +153,7 @@ typedef struct CryptoDevBackendClass { int (*do_sym_op)(CryptoDevBackend *backend, CryptoDevBackendSymOpInfo *op_info, uint32_t queue_index, Error **errp); -} CryptoDevBackendClass; +}; typedef enum CryptoDevBackendOptionsType { CRYPTODEV_BACKEND_TYPE_NONE = 0, diff --git a/include/sysemu/hax.h b/include/sysemu/hax.h index 9b27e65cc70ec14c5422b9e7c68f79a7e640312b..12fb54f9902713443fa40e63cdf4d6b56e7b52ca 100644 --- a/include/sysemu/hax.h +++ b/include/sysemu/hax.h @@ -22,29 +22,12 @@ #ifndef QEMU_HAX_H #define QEMU_HAX_H - int hax_sync_vcpus(void); -int hax_init_vcpu(CPUState *cpu); -int hax_smp_cpu_exec(CPUState *cpu); -int hax_populate_ram(uint64_t va, uint64_t size); - -void hax_cpu_synchronize_state(CPUState *cpu); -void hax_cpu_synchronize_post_reset(CPUState *cpu); -void hax_cpu_synchronize_post_init(CPUState *cpu); -void hax_cpu_synchronize_pre_loadvm(CPUState *cpu); #ifdef CONFIG_HAX int hax_enabled(void); -#include "qemu/bitops.h" -#include "exec/memory.h" -int hax_vcpu_destroy(CPUState *cpu); -void hax_raise_event(CPUState *cpu); -void hax_reset_vcpu_state(void *opaque); -#include "target/i386/hax-interface.h" -#include "target/i386/hax-i386.h" - #else /* CONFIG_HAX */ #define hax_enabled() (0) diff --git a/include/sysemu/hostmem.h b/include/sysemu/hostmem.h index 8276e53683c86557fecac069763c60d8e28151e3..df5644723a39523a1a193a828909cfe148bcc1fc 100644 --- a/include/sysemu/hostmem.h +++ b/include/sysemu/hostmem.h @@ -20,12 +20,8 @@ #include "qemu/bitmap.h" #define TYPE_MEMORY_BACKEND "memory-backend" -#define MEMORY_BACKEND(obj) \ - OBJECT_CHECK(HostMemoryBackend, (obj), TYPE_MEMORY_BACKEND) -#define MEMORY_BACKEND_GET_CLASS(obj) \ - OBJECT_GET_CLASS(HostMemoryBackendClass, (obj), TYPE_MEMORY_BACKEND) -#define MEMORY_BACKEND_CLASS(klass) \ - OBJECT_CLASS_CHECK(HostMemoryBackendClass, (klass), TYPE_MEMORY_BACKEND) +OBJECT_DECLARE_TYPE(HostMemoryBackend, HostMemoryBackendClass, + MEMORY_BACKEND) /* hostmem-ram.c */ /** @@ -42,8 +38,6 @@ */ #define TYPE_MEMORY_BACKEND_FILE "memory-backend-file" -typedef struct HostMemoryBackend HostMemoryBackend; -typedef struct HostMemoryBackendClass HostMemoryBackendClass; /** * HostMemoryBackendClass: diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h index d211e808e9dfecbfcd099e41d091898e6a0c25a2..f893768df95397f8b104a1a5a16cf1c3aa84af68 100644 --- a/include/sysemu/hvf.h +++ b/include/sysemu/hvf.h @@ -13,93 +13,23 @@ #ifndef HVF_H #define HVF_H -#include "cpu.h" -#include "qemu/bitops.h" -#include "exec/memory.h" #include "sysemu/accel.h" +#include "qom/object.h" -extern bool hvf_allowed; #ifdef CONFIG_HVF -#include -#include -#include -#include "target/i386/cpu.h" uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx, int reg); +extern bool hvf_allowed; #define hvf_enabled() (hvf_allowed) -#else +#else /* !CONFIG_HVF */ #define hvf_enabled() 0 #define hvf_get_supported_cpuid(func, idx, reg) 0 -#endif - -/* hvf_slot flags */ -#define HVF_SLOT_LOG (1 << 0) - -typedef struct hvf_slot { - uint64_t start; - uint64_t size; - uint8_t *mem; - int slot_id; - uint32_t flags; - MemoryRegion *region; -} hvf_slot; - -typedef struct hvf_vcpu_caps { - uint64_t vmx_cap_pinbased; - uint64_t vmx_cap_procbased; - uint64_t vmx_cap_procbased2; - uint64_t vmx_cap_entry; - uint64_t vmx_cap_exit; - uint64_t vmx_cap_preemption_timer; -} hvf_vcpu_caps; - -typedef struct HVFState { - AccelState parent; - hvf_slot slots[32]; - int num_slots; - - hvf_vcpu_caps *hvf_caps; -} HVFState; -extern HVFState *hvf_state; - -void hvf_set_phys_mem(MemoryRegionSection *, bool); -void hvf_handle_io(CPUArchState *, uint16_t, void *, - int, int, int); -hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t); - -/* Disable HVF if |disable| is 1, otherwise, enable it iff it is supported by - * the host CPU. Use hvf_enabled() after this to get the result. */ -void hvf_disable(int disable); - -/* Returns non-0 if the host CPU supports the VMX "unrestricted guest" feature - * which allows the virtual CPU to directly run in "real mode". If true, this - * allows QEMU to run several vCPU threads in parallel (see cpus.c). Otherwise, - * only a a single TCG thread can run, and it will call HVF to run the current - * instructions, except in case of "real mode" (paging disabled, typically at - * boot time), or MMIO operations. */ - -int hvf_sync_vcpus(void); - -int hvf_init_vcpu(CPUState *); -int hvf_vcpu_exec(CPUState *); -int hvf_smp_cpu_exec(CPUState *); -void hvf_cpu_synchronize_state(CPUState *); -void hvf_cpu_synchronize_post_reset(CPUState *); -void hvf_cpu_synchronize_post_init(CPUState *); -void _hvf_cpu_synchronize_post_init(CPUState *, run_on_cpu_data); - -void hvf_vcpu_destroy(CPUState *); -void hvf_raise_event(CPUState *); -/* void hvf_reset_vcpu_state(void *opaque); */ -void hvf_reset_vcpu(CPUState *); -void vmx_update_tpr(CPUState *); -void update_apic_tpr(CPUState *); -int hvf_put_registers(CPUState *); -void vmx_clear_int_window_exiting(CPUState *cpu); +#endif /* !CONFIG_HVF */ #define TYPE_HVF_ACCEL ACCEL_CLASS_NAME("hvf") -#define HVF_STATE(obj) \ - OBJECT_CHECK(HVFState, (obj), TYPE_HVF_ACCEL) +typedef struct HVFState HVFState; +DECLARE_INSTANCE_CHECKER(HVFState, HVF_STATE, + TYPE_HVF_ACCEL) #endif diff --git a/include/sysemu/hw_accel.h b/include/sysemu/hw_accel.h index 0ec237247729e6108a0c995ed8e5c15bc01e1625..ffed6192a371a29fca9811660eece713698b8dc8 100644 --- a/include/sysemu/hw_accel.h +++ b/include/sysemu/hw_accel.h @@ -1,5 +1,5 @@ /* - * QEMU Hardware accelertors support + * QEMU Hardware accelerators support * * Copyright 2016 Google, Inc. * @@ -14,58 +14,12 @@ #include "hw/core/cpu.h" #include "sysemu/hax.h" #include "sysemu/kvm.h" +#include "sysemu/hvf.h" #include "sysemu/whpx.h" -static inline void cpu_synchronize_state(CPUState *cpu) -{ - if (kvm_enabled()) { - kvm_cpu_synchronize_state(cpu); - } - if (hax_enabled()) { - hax_cpu_synchronize_state(cpu); - } - if (whpx_enabled()) { - whpx_cpu_synchronize_state(cpu); - } -} - -static inline void cpu_synchronize_post_reset(CPUState *cpu) -{ - if (kvm_enabled()) { - kvm_cpu_synchronize_post_reset(cpu); - } - if (hax_enabled()) { - hax_cpu_synchronize_post_reset(cpu); - } - if (whpx_enabled()) { - whpx_cpu_synchronize_post_reset(cpu); - } -} - -static inline void cpu_synchronize_post_init(CPUState *cpu) -{ - if (kvm_enabled()) { - kvm_cpu_synchronize_post_init(cpu); - } - if (hax_enabled()) { - hax_cpu_synchronize_post_init(cpu); - } - if (whpx_enabled()) { - whpx_cpu_synchronize_post_init(cpu); - } -} - -static inline void cpu_synchronize_pre_loadvm(CPUState *cpu) -{ - if (kvm_enabled()) { - kvm_cpu_synchronize_pre_loadvm(cpu); - } - if (hax_enabled()) { - hax_cpu_synchronize_pre_loadvm(cpu); - } - if (whpx_enabled()) { - whpx_cpu_synchronize_pre_loadvm(cpu); - } -} +void cpu_synchronize_state(CPUState *cpu); +void cpu_synchronize_post_reset(CPUState *cpu); +void cpu_synchronize_post_init(CPUState *cpu); +void cpu_synchronize_pre_loadvm(CPUState *cpu); #endif /* QEMU_HW_ACCEL_H */ diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h index 61814864017476071fde1eca94ebd338757cc97e..0c5284dbbcf60dbea2035404f6baa2eb9fd127f5 100644 --- a/include/sysemu/iothread.h +++ b/include/sysemu/iothread.h @@ -20,7 +20,7 @@ #define TYPE_IOTHREAD "iothread" -typedef struct { +struct IOThread { Object parent_obj; QemuThread thread; @@ -37,10 +37,11 @@ typedef struct { int64_t poll_max_ns; int64_t poll_grow; int64_t poll_shrink; -} IOThread; +}; +typedef struct IOThread IOThread; -#define IOTHREAD(obj) \ - OBJECT_CHECK(IOThread, obj, TYPE_IOTHREAD) +DECLARE_INSTANCE_CHECKER(IOThread, IOTHREAD, + TYPE_IOTHREAD) char *iothread_get_id(IOThread *iothread); IOThread *iothread_by_id(const char *id); diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 3b2250471cacdd6e5169ed3a1733510253469352..bb5d5cf49710112779fd575e301ee7a24e1bc924 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -17,6 +17,8 @@ #include "qemu/queue.h" #include "hw/core/cpu.h" #include "exec/memattrs.h" +#include "sysemu/accel.h" +#include "qom/object.h" #ifdef NEED_CPU_H # ifdef CONFIG_KVM @@ -49,23 +51,22 @@ extern bool kvm_msi_use_devid; /** * kvm_irqchip_in_kernel: * - * Returns: true if the user asked us to create an in-kernel - * irqchip via the "kernel_irqchip=on" machine option. + * Returns: true if an in-kernel irqchip was created. * What this actually means is architecture and machine model - * specific: on PC, for instance, it means that the LAPIC, - * IOAPIC and PIT are all in kernel. This function should never - * be used from generic target-independent code: use one of the - * following functions or some other specific check instead. + * specific: on PC, for instance, it means that the LAPIC + * is in kernel. This function should never be used from generic + * target-independent code: use one of the following functions or + * some other specific check instead. */ #define kvm_irqchip_in_kernel() (kvm_kernel_irqchip) /** * kvm_irqchip_is_split: * - * Returns: true if the user asked us to split the irqchip - * implementation between user and kernel space. The details are - * architecture and machine specific. On PC, it means that the PIC, - * IOAPIC, and PIT are in user space while the LAPIC is in the kernel. + * Returns: true if the irqchip implementation is split between + * user and kernel space. The details are architecture and + * machine specific. On PC, it means that the PIC, IOAPIC, and + * PIT are in user space while the LAPIC is in the kernel. */ #define kvm_irqchip_is_split() (kvm_split_irqchip) @@ -199,7 +200,12 @@ typedef struct KVMCapabilityInfo { #define KVM_CAP_LAST_INFO { NULL, 0 } struct KVMState; + +#define TYPE_KVM_ACCEL ACCEL_CLASS_NAME("kvm") typedef struct KVMState KVMState; +DECLARE_INSTANCE_CHECKER(KVMState, KVM_STATE, + TYPE_KVM_ACCEL) + extern KVMState *kvm_state; typedef struct Notifier Notifier; @@ -216,10 +222,6 @@ int kvm_has_many_ioeventfds(void); int kvm_has_gsi_routing(void); int kvm_has_intx_set_mask(void); -int kvm_init_vcpu(CPUState *cpu); -int kvm_cpu_exec(CPUState *cpu); -int kvm_destroy_vcpu(CPUState *cpu); - /** * kvm_arm_supports_user_irq * @@ -479,9 +481,6 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr, #endif /* NEED_CPU_H */ void kvm_cpu_synchronize_state(CPUState *cpu); -void kvm_cpu_synchronize_post_reset(CPUState *cpu); -void kvm_cpu_synchronize_post_init(CPUState *cpu); -void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu); void kvm_init_cpu_signals(CPUState *cpu); @@ -554,4 +553,8 @@ int kvm_set_one_reg(CPUState *cs, uint64_t id, void *source); int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target); struct ppc_radix_page_info *kvm_get_radix_page_info(void); int kvm_get_max_memslots(void); + +/* Notify resamplefd for EOI of specific interrupts. */ +void kvm_resample_fd_notify(int gsi); + #endif diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h index c660a70c51a8558e964a4900c324ea67ff3fb92f..65740806dacaf5b9615f86d0baf4d5da1beb36b0 100644 --- a/include/sysemu/kvm_int.h +++ b/include/sysemu/kvm_int.h @@ -33,11 +33,6 @@ typedef struct KVMMemoryListener { int as_id; } KVMMemoryListener; -#define TYPE_KVM_ACCEL ACCEL_CLASS_NAME("kvm") - -#define KVM_STATE(obj) \ - OBJECT_CHECK(KVMState, (obj), TYPE_KVM_ACCEL) - void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml, AddressSpace *as, int as_id); diff --git a/include/sysemu/numa.h b/include/sysemu/numa.h index ad58ee88f7c42b2ffe8cc4125f220eb616d8d27f..4173ef2afa75baba7cb2f03f861a1edc6f78bc87 100644 --- a/include/sysemu/numa.h +++ b/include/sysemu/numa.h @@ -106,10 +106,6 @@ void parse_numa_hmat_cache(MachineState *ms, NumaHmatCacheOptions *node, void numa_complete_configuration(MachineState *ms); void query_numa_node_mem(NumaNodeMem node_mem[], MachineState *ms); extern QemuOptsList qemu_numa_opts; -void numa_legacy_auto_assign_ram(MachineClass *mc, NodeInfo *nodes, - int nb_nodes, ram_addr_t size); -void numa_default_auto_assign_ram(MachineClass *mc, NodeInfo *nodes, - int nb_nodes, ram_addr_t size); void numa_cpu_pre_plug(const struct CPUArchId *slot, DeviceState *dev, Error **errp); bool numa_uses_legacy_mem(void); diff --git a/include/sysemu/os-win32.h b/include/sysemu/os-win32.h index d8978e28c03f5a03bb9c9810a4b547ad8c74d734..5346d51e890eb1614bb040d725f0b90d7c9d3f66 100644 --- a/include/sysemu/os-win32.h +++ b/include/sysemu/os-win32.h @@ -48,12 +48,12 @@ #define siglongjmp(env, val) longjmp(env, val) /* Missing POSIX functions. Don't use MinGW-w64 macros. */ -#ifndef CONFIG_LOCALTIME_R +#ifndef _POSIX_THREAD_SAFE_FUNCTIONS #undef gmtime_r struct tm *gmtime_r(const time_t *timep, struct tm *result); #undef localtime_r struct tm *localtime_r(const time_t *timep, struct tm *result); -#endif /* CONFIG_LOCALTIME_R */ +#endif /* _POSIX_THREAD_SAFE_FUNCTIONS */ static inline void os_setup_signal_handling(void) {} static inline void os_daemonize(void) {} diff --git a/include/sysemu/qtest.h b/include/sysemu/qtest.h index eedd3664f0779f8d0661bbe8f8c9c8d30173dd1b..4c53537ef3d2107982fa7be87a5ea2c4eceae0b3 100644 --- a/include/sysemu/qtest.h +++ b/include/sysemu/qtest.h @@ -30,4 +30,6 @@ void qtest_server_set_send_handler(void (*send)(void *, const char *), void *opaque); void qtest_server_inproc_recv(void *opaque, const char *buf); +int64_t qtest_get_virtual_clock(void); + #endif diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h index 5471bb514dfac7b288e28ed5ac0a0433c84ba2b6..56c0c17c30b02a1280ea7f3d3b6782657a07439f 100644 --- a/include/sysemu/replay.h +++ b/include/sysemu/replay.h @@ -14,6 +14,7 @@ #include "qapi/qapi-types-misc.h" #include "qapi/qapi-types-run-state.h" +#include "qapi/qapi-types-replay.h" #include "qapi/qapi-types-ui.h" #include "block/aio.h" @@ -72,6 +73,29 @@ void replay_start(void); void replay_finish(void); /*! Adds replay blocker with the specified error description */ void replay_add_blocker(Error *reason); +/* Returns name of the replay log file */ +const char *replay_get_filename(void); +/* + * Start making one step in backward direction. + * Used by gdbstub for backwards debugging. + * Returns true on success. + */ +bool replay_reverse_step(void); +/* + * Start searching the last breakpoint/watchpoint. + * Used by gdbstub for backwards debugging. + * Returns true if the process successfully started. + */ +bool replay_reverse_continue(void); +/* + * Returns true if replay module is processing + * reverse_continue or reverse_step request + */ +bool replay_running_debug(void); +/* Called in reverse debugging mode to collect breakpoint information */ +void replay_breakpoint(void); +/* Called when gdb is attached to gdbstub */ +void replay_gdb_attached(void); /* Processing the instructions */ @@ -109,12 +133,12 @@ int64_t replay_read_clock(ReplayClockKind kind); #define REPLAY_CLOCK(clock, value) \ (replay_mode == REPLAY_MODE_PLAY ? replay_read_clock((clock)) \ : replay_mode == REPLAY_MODE_RECORD \ - ? replay_save_clock((clock), (value), cpu_get_icount_raw()) \ + ? replay_save_clock((clock), (value), icount_get_raw()) \ : (value)) #define REPLAY_CLOCK_LOCKED(clock, value) \ (replay_mode == REPLAY_MODE_PLAY ? replay_read_clock((clock)) \ : replay_mode == REPLAY_MODE_RECORD \ - ? replay_save_clock((clock), (value), cpu_get_icount_raw_locked()) \ + ? replay_save_clock((clock), (value), icount_get_raw_locked()) \ : (value)) /* Processing data from random generators */ @@ -146,6 +170,8 @@ void replay_disable_events(void); void replay_enable_events(void); /*! Returns true when saving events is enabled */ bool replay_events_enabled(void); +/* Flushes events queue */ +void replay_flush_events(void); /*! Adds bottom half event to the queue */ void replay_bh_schedule_event(QEMUBH *bh); /* Adds oneshot bottom half event to the queue */ diff --git a/include/sysemu/rng-random.h b/include/sysemu/rng-random.h index 38186fe83d5b45f79fbda64f021e5ff4a86b7319..0fdc6c69744abcaa04a5e8d38cb6ecc8d89b0c4d 100644 --- a/include/sysemu/rng-random.h +++ b/include/sysemu/rng-random.h @@ -15,8 +15,7 @@ #include "qom/object.h" #define TYPE_RNG_RANDOM "rng-random" -#define RNG_RANDOM(obj) OBJECT_CHECK(RngRandom, (obj), TYPE_RNG_RANDOM) +OBJECT_DECLARE_SIMPLE_TYPE(RngRandom, RNG_RANDOM) -typedef struct RngRandom RngRandom; #endif diff --git a/include/sysemu/rng.h b/include/sysemu/rng.h index fa6eada78cd7c2ff09bb36b5dd9aa0f06676fd4a..e383f87d20b2b7b472615171dc110839b3fc34a7 100644 --- a/include/sysemu/rng.h +++ b/include/sysemu/rng.h @@ -17,18 +17,12 @@ #include "qom/object.h" #define TYPE_RNG_BACKEND "rng-backend" -#define RNG_BACKEND(obj) \ - OBJECT_CHECK(RngBackend, (obj), TYPE_RNG_BACKEND) -#define RNG_BACKEND_GET_CLASS(obj) \ - OBJECT_GET_CLASS(RngBackendClass, (obj), TYPE_RNG_BACKEND) -#define RNG_BACKEND_CLASS(klass) \ - OBJECT_CLASS_CHECK(RngBackendClass, (klass), TYPE_RNG_BACKEND) +OBJECT_DECLARE_TYPE(RngBackend, RngBackendClass, + RNG_BACKEND) #define TYPE_RNG_BUILTIN "rng-builtin" typedef struct RngRequest RngRequest; -typedef struct RngBackendClass RngBackendClass; -typedef struct RngBackend RngBackend; typedef void (EntropyReceiveFunc)(void *opaque, const void *data, diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 26c0c802d1a2823657678aa08dd29addc3118e28..817ff4cf753fe95fb363ec0f8ed11f474274aa27 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -5,7 +5,6 @@ #include "qemu/timer.h" #include "qemu/notify.h" #include "qemu/uuid.h" -#include "qom/object.h" /* vl.c */ @@ -15,6 +14,8 @@ extern const char *qemu_name; extern QemuUUID qemu_uuid; extern bool qemu_uuid_set; +void qemu_add_data_dir(char *path); + void qemu_add_exit_notifier(Notifier *notify); void qemu_remove_exit_notifier(Notifier *notify); diff --git a/include/sysemu/tcg.h b/include/sysemu/tcg.h index 7d116d2e801a1c30d909adfe3aa4c03d68752dfe..d9d3ca85596f9aa93ae8470a931b8d0f76aa0a8a 100644 --- a/include/sysemu/tcg.h +++ b/include/sysemu/tcg.h @@ -8,9 +8,9 @@ #ifndef SYSEMU_TCG_H #define SYSEMU_TCG_H -extern bool tcg_allowed; void tcg_exec_init(unsigned long tb_size); #ifdef CONFIG_TCG +extern bool tcg_allowed; #define tcg_enabled() (tcg_allowed) #else #define tcg_enabled() 0 diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h index f37851b1aabe9cfc069b3286596b97277f29e6b9..1a85564e479deda8af0996c06a4175f57b2162c3 100644 --- a/include/sysemu/tpm.h +++ b/include/sysemu/tpm.h @@ -16,7 +16,7 @@ #include "qom/object.h" int tpm_config_parse(QemuOptsList *opts_list, const char *optarg); -void tpm_init(void); +int tpm_init(void); void tpm_cleanup(void); typedef enum TPMVersion { @@ -26,22 +26,21 @@ typedef enum TPMVersion { } TPMVersion; #define TYPE_TPM_IF "tpm-if" -#define TPM_IF_CLASS(klass) \ - OBJECT_CLASS_CHECK(TPMIfClass, (klass), TYPE_TPM_IF) -#define TPM_IF_GET_CLASS(obj) \ - OBJECT_GET_CLASS(TPMIfClass, (obj), TYPE_TPM_IF) +typedef struct TPMIfClass TPMIfClass; +DECLARE_CLASS_CHECKERS(TPMIfClass, TPM_IF, + TYPE_TPM_IF) #define TPM_IF(obj) \ INTERFACE_CHECK(TPMIf, (obj), TYPE_TPM_IF) typedef struct TPMIf TPMIf; -typedef struct TPMIfClass { +struct TPMIfClass { InterfaceClass parent_class; enum TpmModel model; void (*request_completed)(TPMIf *obj, int ret); enum TPMVersion (*get_version)(TPMIf *obj); -} TPMIfClass; +}; #define TYPE_TPM_TIS_ISA "tpm-tis" #define TYPE_TPM_TIS_SYSBUS "tpm-tis-device" @@ -50,6 +49,8 @@ typedef struct TPMIfClass { #define TPM_IS_TIS_ISA(chr) \ object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_ISA) +#define TPM_IS_TIS_SYSBUS(chr) \ + object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_SYSBUS) #define TPM_IS_CRB(chr) \ object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB) #define TPM_IS_SPAPR(chr) \ diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h index 9e7451fb52fc511b16fd6fffef5a2015c7851927..6f078f5f4829ff55af09b87aa48ddbe38a1ce2f1 100644 --- a/include/sysemu/tpm_backend.h +++ b/include/sysemu/tpm_backend.h @@ -19,15 +19,9 @@ #include "qapi/error.h" #define TYPE_TPM_BACKEND "tpm-backend" -#define TPM_BACKEND(obj) \ - OBJECT_CHECK(TPMBackend, (obj), TYPE_TPM_BACKEND) -#define TPM_BACKEND_GET_CLASS(obj) \ - OBJECT_GET_CLASS(TPMBackendClass, (obj), TYPE_TPM_BACKEND) -#define TPM_BACKEND_CLASS(klass) \ - OBJECT_CLASS_CHECK(TPMBackendClass, (klass), TYPE_TPM_BACKEND) - -typedef struct TPMBackendClass TPMBackendClass; -typedef struct TPMBackend TPMBackend; +OBJECT_DECLARE_TYPE(TPMBackend, TPMBackendClass, + TPM_BACKEND) + typedef struct TPMBackendCmd { uint8_t locty; diff --git a/hw/tpm/tpm_util.h b/include/sysemu/tpm_util.h similarity index 77% rename from hw/tpm/tpm_util.h rename to include/sysemu/tpm_util.h index 7889081fbab7f401203bcf298df5d03684150c44..08f05172a71766d72fb809c45023308cf9cba6c1 100644 --- a/hw/tpm/tpm_util.h +++ b/include/sysemu/tpm_util.h @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,8 +19,8 @@ * License along with this library; if not, see */ -#ifndef TPM_TPM_UTIL_H -#define TPM_TPM_UTIL_H +#ifndef SYSEMU_TPM_UTIL_H +#define SYSEMU_TPM_UTIL_H #include "sysemu/tpm.h" #include "qemu/bswap.h" @@ -66,20 +66,7 @@ static inline void tpm_cmd_set_error(void *b, uint32_t error) stl_be_p(b + 6, error); } -int tpm_util_get_buffer_size(int tpm_fd, TPMVersion tpm_version, - size_t *buffersize); - -#define DEFINE_PROP_TPMBE(_n, _s, _f) \ - DEFINE_PROP(_n, _s, _f, qdev_prop_tpm, TPMBackend *) - -typedef struct TPMSizedBuffer { - uint32_t size; - uint8_t *buffer; -} TPMSizedBuffer; - -void tpm_sized_buffer_reset(TPMSizedBuffer *tsb); - void tpm_util_show_buffer(const unsigned char *buffer, size_t buffer_size, const char *string); -#endif /* TPM_TPM_UTIL_H */ +#endif /* SYSEMU_TPM_UTIL_H */ diff --git a/include/sysemu/vhost-user-backend.h b/include/sysemu/vhost-user-backend.h index 9abf8f06a1b966482bdd60e8452b71195bf5776f..327b0b84f1f8e0708135e26283ecc2889efe0e7a 100644 --- a/include/sysemu/vhost-user-backend.h +++ b/include/sysemu/vhost-user-backend.h @@ -22,19 +22,10 @@ #include "io/channel.h" #define TYPE_VHOST_USER_BACKEND "vhost-user-backend" -#define VHOST_USER_BACKEND(obj) \ - OBJECT_CHECK(VhostUserBackend, (obj), TYPE_VHOST_USER_BACKEND) -#define VHOST_USER_BACKEND_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VhostUserBackendClass, (obj), TYPE_VHOST_USER_BACKEND) -#define VHOST_USER_BACKEND_CLASS(klass) \ - OBJECT_CLASS_CHECK(VhostUserBackendClass, (klass), TYPE_VHOST_USER_BACKEND) - -typedef struct VhostUserBackend VhostUserBackend; -typedef struct VhostUserBackendClass VhostUserBackendClass; - -struct VhostUserBackendClass { - ObjectClass parent_class; -}; +OBJECT_DECLARE_SIMPLE_TYPE(VhostUserBackend, + VHOST_USER_BACKEND) + + struct VhostUserBackend { /* private */ diff --git a/include/sysemu/whpx.h b/include/sysemu/whpx.h index a84b49e7494ba46363866295076827a6e35c7350..59edf1374270f42c7c3334d91357d4ab8e6e9d8f 100644 --- a/include/sysemu/whpx.h +++ b/include/sysemu/whpx.h @@ -13,18 +13,6 @@ #ifndef QEMU_WHPX_H #define QEMU_WHPX_H - -int whpx_init_vcpu(CPUState *cpu); -int whpx_vcpu_exec(CPUState *cpu); -void whpx_destroy_vcpu(CPUState *cpu); -void whpx_vcpu_kick(CPUState *cpu); - - -void whpx_cpu_synchronize_state(CPUState *cpu); -void whpx_cpu_synchronize_post_reset(CPUState *cpu); -void whpx_cpu_synchronize_post_init(CPUState *cpu); -void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu); - #ifdef CONFIG_WHPX int whpx_enabled(void); @@ -35,11 +23,4 @@ int whpx_enabled(void); #endif /* CONFIG_WHPX */ -/* state subset only touched by the VCPU itself during runtime */ -#define WHPX_SET_RUNTIME_STATE 1 -/* state subset modified during VCPU reset */ -#define WHPX_SET_RESET_STATE 2 -/* full state set, modified during initialization or on vmload */ -#define WHPX_SET_FULL_STATE 3 - #endif /* QEMU_WHPX_H */ diff --git a/include/sysemu/xen.h b/include/sysemu/xen.h new file mode 100644 index 0000000000000000000000000000000000000000..0ca25697e4f4f69c8a768c0343bad9a4800e63b0 --- /dev/null +++ b/include/sysemu/xen.h @@ -0,0 +1,50 @@ +/* + * QEMU Xen support + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef SYSEMU_XEN_H +#define SYSEMU_XEN_H + +#include "exec/cpu-common.h" + +#ifdef NEED_CPU_H +# ifdef CONFIG_XEN +# define CONFIG_XEN_IS_POSSIBLE +# endif +#else +# define CONFIG_XEN_IS_POSSIBLE +#endif + +#ifdef CONFIG_XEN_IS_POSSIBLE + +extern bool xen_allowed; + +#define xen_enabled() (xen_allowed) + +#ifndef CONFIG_USER_ONLY +void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length); +void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, + struct MemoryRegion *mr, Error **errp); +#endif + +#else /* !CONFIG_XEN_IS_POSSIBLE */ + +#define xen_enabled() 0 +#ifndef CONFIG_USER_ONLY +static inline void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length) +{ + /* nothing */ +} +static inline void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, + MemoryRegion *mr, Error **errp) +{ + g_assert_not_reached(); +} +#endif + +#endif /* CONFIG_XEN_IS_POSSIBLE */ + +#endif diff --git a/include/tcg/tcg-gvec-desc.h b/include/tcg/tcg-gvec-desc.h index 0224ac3e78dd53f18143f6d50e6a7b6e25a5d83f..704bd8645498fa0fd1a8b22ae465b322e77118c2 100644 --- a/include/tcg/tcg-gvec-desc.h +++ b/include/tcg/tcg-gvec-desc.h @@ -20,29 +20,41 @@ #ifndef TCG_TCG_GVEC_DESC_H #define TCG_TCG_GVEC_DESC_H -/* ??? These bit widths are set for ARM SVE, maxing out at 256 byte vectors. */ -#define SIMD_OPRSZ_SHIFT 0 -#define SIMD_OPRSZ_BITS 5 +/* + * This configuration allows MAXSZ to represent 2048 bytes, and + * OPRSZ to match MAXSZ, or represent the smaller values 8, 16, or 32. + * + * Encode this with: + * 0, 1, 3 -> 8, 16, 32 + * 2 -> maxsz + * + * This steals the input that would otherwise map to 24 to match maxsz. + */ +#define SIMD_MAXSZ_SHIFT 0 +#define SIMD_MAXSZ_BITS 8 -#define SIMD_MAXSZ_SHIFT (SIMD_OPRSZ_SHIFT + SIMD_OPRSZ_BITS) -#define SIMD_MAXSZ_BITS 5 +#define SIMD_OPRSZ_SHIFT (SIMD_MAXSZ_SHIFT + SIMD_MAXSZ_BITS) +#define SIMD_OPRSZ_BITS 2 -#define SIMD_DATA_SHIFT (SIMD_MAXSZ_SHIFT + SIMD_MAXSZ_BITS) +#define SIMD_DATA_SHIFT (SIMD_OPRSZ_SHIFT + SIMD_OPRSZ_BITS) #define SIMD_DATA_BITS (32 - SIMD_DATA_SHIFT) /* Create a descriptor from components. */ uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t data); -/* Extract the operation size from a descriptor. */ -static inline intptr_t simd_oprsz(uint32_t desc) +/* Extract the max vector size from a descriptor. */ +static inline intptr_t simd_maxsz(uint32_t desc) { - return (extract32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS) + 1) * 8; + return extract32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS) * 8 + 8; } -/* Extract the max vector size from a descriptor. */ -static inline intptr_t simd_maxsz(uint32_t desc) +/* Extract the operation size from a descriptor. */ +static inline intptr_t simd_oprsz(uint32_t desc) { - return (extract32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS) + 1) * 8; + uint32_t f = extract32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS); + intptr_t o = f * 8 + 8; + intptr_t m = simd_maxsz(desc); + return f == 2 ? m : o; } /* Extract the operation-specific data from a descriptor. */ diff --git a/include/tcg/tcg-op-gvec.h b/include/tcg/tcg-op-gvec.h index cea6497341c43f92f57f4b401d48d07d4a807cad..c69a7de984be598d2f80ff7f3a0403dec107b105 100644 --- a/include/tcg/tcg-op-gvec.h +++ b/include/tcg/tcg-op-gvec.h @@ -334,6 +334,10 @@ void tcg_gen_gvec_shri(unsigned vece, uint32_t dofs, uint32_t aofs, int64_t shift, uint32_t oprsz, uint32_t maxsz); void tcg_gen_gvec_sari(unsigned vece, uint32_t dofs, uint32_t aofs, int64_t shift, uint32_t oprsz, uint32_t maxsz); +void tcg_gen_gvec_rotli(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t shift, uint32_t oprsz, uint32_t maxsz); +void tcg_gen_gvec_rotri(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t shift, uint32_t oprsz, uint32_t maxsz); void tcg_gen_gvec_shls(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz); @@ -341,6 +345,8 @@ void tcg_gen_gvec_shrs(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz); void tcg_gen_gvec_sars(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz); +void tcg_gen_gvec_rotls(unsigned vece, uint32_t dofs, uint32_t aofs, + TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz); /* * Perform vector shift by vector element, modulo the element size. @@ -352,6 +358,10 @@ void tcg_gen_gvec_shrv(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); void tcg_gen_gvec_sarv(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); +void tcg_gen_gvec_rotlv(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz); +void tcg_gen_gvec_rotrv(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz); void tcg_gen_gvec_cmp(TCGCond cond, unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, @@ -388,5 +398,7 @@ void tcg_gen_vec_shr8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t); void tcg_gen_vec_shr16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t); void tcg_gen_vec_sar8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t); void tcg_gen_vec_sar16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t); +void tcg_gen_vec_rotl8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c); +void tcg_gen_vec_rotl16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c); #endif diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h index e3399d6a5e5f68e10fec911d47e4a8c25217399e..5abf17fecc06f9fd5118eca0f87cad3023344772 100644 --- a/include/tcg/tcg-op.h +++ b/include/tcg/tcg-op.h @@ -999,14 +999,19 @@ void tcg_gen_umax_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b); void tcg_gen_shli_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i); void tcg_gen_shri_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i); void tcg_gen_sari_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i); +void tcg_gen_rotli_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i); +void tcg_gen_rotri_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i); void tcg_gen_shls_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_i32 s); void tcg_gen_shrs_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_i32 s); void tcg_gen_sars_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_i32 s); +void tcg_gen_rotls_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_i32 s); void tcg_gen_shlv_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec s); void tcg_gen_shrv_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec s); void tcg_gen_sarv_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec s); +void tcg_gen_rotlv_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec s); +void tcg_gen_rotrv_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec s); void tcg_gen_cmp_vec(TCGCond cond, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b); diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h index 9288a049468925acfc5747641ac74687b2a95e88..67092e82c628a9cc93b701c3ffee0924429c5256 100644 --- a/include/tcg/tcg-opc.h +++ b/include/tcg/tcg-opc.h @@ -81,7 +81,7 @@ DEF(extract_i32, 1, 1, 2, IMPL(TCG_TARGET_HAS_extract_i32)) DEF(sextract_i32, 1, 1, 2, IMPL(TCG_TARGET_HAS_sextract_i32)) DEF(extract2_i32, 1, 2, 1, IMPL(TCG_TARGET_HAS_extract2_i32)) -DEF(brcond_i32, 0, 2, 2, TCG_OPF_BB_END) +DEF(brcond_i32, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_COND_BRANCH) DEF(add2_i32, 2, 4, 0, IMPL(TCG_TARGET_HAS_add2_i32)) DEF(sub2_i32, 2, 4, 0, IMPL(TCG_TARGET_HAS_sub2_i32)) @@ -89,7 +89,8 @@ DEF(mulu2_i32, 2, 2, 0, IMPL(TCG_TARGET_HAS_mulu2_i32)) DEF(muls2_i32, 2, 2, 0, IMPL(TCG_TARGET_HAS_muls2_i32)) DEF(muluh_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_muluh_i32)) DEF(mulsh_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_mulsh_i32)) -DEF(brcond2_i32, 0, 4, 2, TCG_OPF_BB_END | IMPL(TCG_TARGET_REG_BITS == 32)) +DEF(brcond2_i32, 0, 4, 2, + TCG_OPF_BB_END | TCG_OPF_COND_BRANCH | IMPL(TCG_TARGET_REG_BITS == 32)) DEF(setcond2_i32, 1, 4, 1, IMPL(TCG_TARGET_REG_BITS == 32)) DEF(ext8s_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext8s_i32)) @@ -159,7 +160,7 @@ DEF(extrh_i64_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_extrh_i64_i32) | (TCG_TARGET_REG_BITS == 32 ? TCG_OPF_NOT_PRESENT : 0)) -DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | IMPL64) +DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_COND_BRANCH | IMPL64) DEF(ext8s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext8s_i64)) DEF(ext16s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext16s_i64)) DEF(ext32s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext32s_i64)) @@ -248,14 +249,18 @@ DEF(not_vec, 1, 1, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_not_vec)) DEF(shli_vec, 1, 1, 1, IMPLVEC | IMPL(TCG_TARGET_HAS_shi_vec)) DEF(shri_vec, 1, 1, 1, IMPLVEC | IMPL(TCG_TARGET_HAS_shi_vec)) DEF(sari_vec, 1, 1, 1, IMPLVEC | IMPL(TCG_TARGET_HAS_shi_vec)) +DEF(rotli_vec, 1, 1, 1, IMPLVEC | IMPL(TCG_TARGET_HAS_roti_vec)) DEF(shls_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shs_vec)) DEF(shrs_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shs_vec)) DEF(sars_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shs_vec)) +DEF(rotls_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_rots_vec)) DEF(shlv_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shv_vec)) DEF(shrv_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shv_vec)) DEF(sarv_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shv_vec)) +DEF(rotlv_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_rotv_vec)) +DEF(rotrv_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_rotv_vec)) DEF(cmp_vec, 1, 2, 1, IMPLVEC) diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index c48bd76b0a988e14d0baf3658d3698a450dae4cd..8ff9dad4ef97acddaf43aef55ac58a6966d1fd59 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -182,6 +182,9 @@ typedef uint64_t TCGRegSet; #define TCG_TARGET_HAS_not_vec 0 #define TCG_TARGET_HAS_andc_vec 0 #define TCG_TARGET_HAS_orc_vec 0 +#define TCG_TARGET_HAS_roti_vec 0 +#define TCG_TARGET_HAS_rots_vec 0 +#define TCG_TARGET_HAS_rotv_vec 0 #define TCG_TARGET_HAS_shi_vec 0 #define TCG_TARGET_HAS_shs_vec 0 #define TCG_TARGET_HAS_shv_vec 0 @@ -633,7 +636,7 @@ struct TCGContext { /* Track which vCPU triggers events */ CPUState *cpu; /* *_trans */ - /* These structures are private to tcg-target.inc.c. */ + /* These structures are private to tcg-target.c.inc. */ #ifdef TCG_TARGET_NEED_LDST_LABELS QSIMPLEQ_HEAD(, TCGLabelQemuLdst) ldst_labels; #endif @@ -774,11 +777,26 @@ static inline TCGv_i32 TCGV_HIGH(TCGv_i64 t) } #endif +static inline TCGArg tcg_get_insn_param(TCGOp *op, int arg) +{ + return op->args[arg]; +} + static inline void tcg_set_insn_param(TCGOp *op, int arg, TCGArg v) { op->args[arg] = v; } +static inline target_ulong tcg_get_insn_start_param(TCGOp *op, int arg) +{ +#if TARGET_LONG_BITS <= TCG_TARGET_REG_BITS + return tcg_get_insn_param(op, arg); +#else + return tcg_get_insn_param(op, arg * 2) | + ((uint64_t)tcg_get_insn_param(op, arg * 2 + 1) << 32); +#endif +} + static inline void tcg_set_insn_start_param(TCGOp *op, int arg, target_ulong v) { #if TARGET_LONG_BITS <= TCG_TARGET_REG_BITS @@ -816,6 +834,7 @@ void tcg_pool_reset(TCGContext *s); TranslationBlock *tcg_tb_alloc(TCGContext *s); void tcg_region_init(void); +void tb_destroy(TranslationBlock *tb); void tcg_region_reset_all(void); size_t tcg_code_size(void); @@ -957,23 +976,21 @@ int64_t tcg_cpu_exec_time(void); void tcg_dump_info(void); void tcg_dump_op_count(void); -#define TCG_CT_ALIAS 0x80 -#define TCG_CT_IALIAS 0x40 -#define TCG_CT_NEWREG 0x20 /* output requires a new register */ -#define TCG_CT_REG 0x01 -#define TCG_CT_CONST 0x02 /* any constant of register size */ +#define TCG_CT_CONST 1 /* any constant of register size */ typedef struct TCGArgConstraint { - uint16_t ct; - uint8_t alias_index; - union { - TCGRegSet regs; - } u; + unsigned ct : 16; + unsigned alias_index : 4; + unsigned sort_index : 4; + bool oalias : 1; + bool ialias : 1; + bool newreg : 1; + TCGRegSet regs; } TCGArgConstraint; #define TCG_MAX_OP_ARGS 16 -/* Bits for TCGOpDef->flags, 8 bits available. */ +/* Bits for TCGOpDef->flags, 8 bits available, all used. */ enum { /* Instruction exits the translation block. */ TCG_OPF_BB_EXIT = 0x01, @@ -991,6 +1008,8 @@ enum { TCG_OPF_NOT_PRESENT = 0x20, /* Instruction operands are vectors. */ TCG_OPF_VECTOR = 0x40, + /* Instruction is a conditional branch. */ + TCG_OPF_COND_BRANCH = 0x80 }; typedef struct TCGOpDef { @@ -998,10 +1017,6 @@ typedef struct TCGOpDef { uint8_t nb_oargs, nb_iargs, nb_cargs, nb_args; uint8_t flags; TCGArgConstraint *args_ct; - int *sorted_args; -#if defined(CONFIG_DEBUG_TCG) - int used; -#endif } TCGOpDef; extern TCGOpDef tcg_op_defs[]; diff --git a/include/ui/console.h b/include/ui/console.h index f35b4fc082b4107db99c4d8b9fa6fbd1203bad18..e7303d8b98a895dcc0e842621d7d4e710f06f086 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -65,14 +65,6 @@ void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry); void kbd_put_ledstate(int ledstate); -typedef struct MouseTransformInfo { - /* Touchscreen resolution */ - int x; - int y; - /* Calibration values as used/generated by tslib */ - int a[7]; -} MouseTransformInfo; - void hmp_mouse_set(Monitor *mon, const QDict *qdict); /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx @@ -106,14 +98,8 @@ void kbd_put_keysym(int keysym); /* consoles */ #define TYPE_QEMU_CONSOLE "qemu-console" -#define QEMU_CONSOLE(obj) \ - OBJECT_CHECK(QemuConsole, (obj), TYPE_QEMU_CONSOLE) -#define QEMU_CONSOLE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(QemuConsoleClass, (obj), TYPE_QEMU_CONSOLE) -#define QEMU_CONSOLE_CLASS(klass) \ - OBJECT_CLASS_CHECK(QemuConsoleClass, (klass), TYPE_QEMU_CONSOLE) +OBJECT_DECLARE_TYPE(QemuConsole, QemuConsoleClass, QEMU_CONSOLE) -typedef struct QemuConsoleClass QemuConsoleClass; struct QemuConsoleClass { ObjectClass parent_class; @@ -133,6 +119,9 @@ typedef struct DisplaySurface { } DisplaySurface; typedef struct QemuUIInfo { + /* physical dimension */ + uint16_t width_mm; + uint16_t height_mm; /* geometry */ int xoff; int yoff; @@ -278,6 +267,7 @@ void update_displaychangelistener(DisplayChangeListener *dcl, void unregister_displaychangelistener(DisplayChangeListener *dcl); bool dpy_ui_info_supported(QemuConsole *con); +const QemuUIInfo *dpy_get_ui_info(const QemuConsole *con); int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info); void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h); diff --git a/include/ui/gtk.h b/include/ui/gtk.h index d1b230848a7b6f3668813b7f75d25f26f5432f5d..eaeb450f913e02b50c0a7c1e4e190da66ed1338e 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -1,15 +1,11 @@ #ifndef UI_GTK_H #define UI_GTK_H -#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE /* Work around an -Wstrict-prototypes warning in GTK headers */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-prototypes" -#endif #include -#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE #pragma GCC diagnostic pop -#endif #include diff --git a/include/ui/qemu-pixman.h b/include/ui/qemu-pixman.h index 3b7cf70157c1c425da266d7b4f0682b839a982e4..87737a6f1629771077a3479d6d0d8f08f9647cca 100644 --- a/include/ui/qemu-pixman.h +++ b/include/ui/qemu-pixman.h @@ -7,14 +7,10 @@ #define QEMU_PIXMAN_H /* pixman-0.16.0 headers have a redundant declaration */ -#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wredundant-decls" -#endif #include -#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE #pragma GCC diagnostic pop -#endif /* * pixman image formats are defined to be native endian, diff --git a/include/ui/qemu-spice-module.h b/include/ui/qemu-spice-module.h new file mode 100644 index 0000000000000000000000000000000000000000..1f22d557ea2fb9b82a4c8dd677d9fead2e22798d --- /dev/null +++ b/include/ui/qemu-spice-module.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2010 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 or + * (at your option) version 3 of the License. + * + * 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 . + */ + +#ifndef QEMU_SPICE_MODULE_H +#define QEMU_SPICE_MODULE_H + +#ifdef CONFIG_SPICE +#include +#endif + +typedef struct SpiceInfo SpiceInfo; + +struct QemuSpiceOps { + void (*init)(void); + void (*display_init)(void); + int (*migrate_info)(const char *h, int p, int t, const char *s); + int (*set_passwd)(const char *passwd, + bool fail_if_connected, bool disconnect_if_connected); + int (*set_pw_expire)(time_t expires); + int (*display_add_client)(int csock, int skipauth, int tls); +#ifdef CONFIG_SPICE + int (*add_interface)(SpiceBaseInstance *sin); + SpiceInfo* (*qmp_query)(Error **errp); +#endif +}; + +extern int using_spice; +extern struct QemuSpiceOps qemu_spice; + +#endif diff --git a/include/ui/qemu-spice.h b/include/ui/qemu-spice.h index 8c23dfe71797459ed659c623700855bf25b5cefe..2beb7929728c58eb79e9c8a4b6f7bcfaba74575e 100644 --- a/include/ui/qemu-spice.h +++ b/include/ui/qemu-spice.h @@ -19,25 +19,17 @@ #define QEMU_SPICE_H #include "qapi/error.h" +#include "ui/qemu-spice-module.h" #ifdef CONFIG_SPICE #include #include "qemu/config-file.h" -extern int using_spice; - -void qemu_spice_init(void); void qemu_spice_input_init(void); -void qemu_spice_audio_init(void); void qemu_spice_display_init(void); -int qemu_spice_display_add_client(int csock, int skipauth, int tls); -int qemu_spice_add_interface(SpiceBaseInstance *sin); bool qemu_spice_have_display_interface(QemuConsole *con); int qemu_spice_add_display_interface(QXLInstance *qxlin, QemuConsole *con); -int qemu_spice_set_passwd(const char *passwd, - bool fail_if_connected, bool disconnect_if_connected); -int qemu_spice_set_pw_expire(time_t expires); int qemu_spice_migrate_info(const char *hostname, int port, int tls_port, const char *subject); @@ -46,46 +38,12 @@ int qemu_spice_migrate_info(const char *hostname, int port, int tls_port, #else #define SPICE_NEEDS_SET_MM_TIME 0 #endif -void qemu_spice_register_ports(void); #else /* CONFIG_SPICE */ #include "qemu/error-report.h" -#define using_spice 0 #define spice_displays 0 -static inline int qemu_spice_set_passwd(const char *passwd, - bool fail_if_connected, - bool disconnect_if_connected) -{ - return -1; -} -static inline int qemu_spice_set_pw_expire(time_t expires) -{ - return -1; -} -static inline int qemu_spice_migrate_info(const char *h, int p, int t, - const char *s) -{ - return -1; -} - -static inline int qemu_spice_display_add_client(int csock, int skipauth, - int tls) -{ - return -1; -} - -static inline void qemu_spice_display_init(void) -{ - /* This must never be called if CONFIG_SPICE is disabled */ - error_report("spice support is disabled"); - abort(); -} - -static inline void qemu_spice_init(void) -{ -} #endif /* CONFIG_SPICE */ diff --git a/include/user/syscall-trace.h b/include/user/syscall-trace.h index 79fd3e5aa9c95ba44fed85118aa5e453607c54f2..42e3b48b032f4dfc0d9c3ae66885289ef0824e62 100644 --- a/include/user/syscall-trace.h +++ b/include/user/syscall-trace.h @@ -10,7 +10,7 @@ #ifndef _SYSCALL_TRACE_H_ #define _SYSCALL_TRACE_H_ -#include "trace-root.h" +#include "trace/trace-root.h" /* * These helpers just provide a common place for the various diff --git a/io/Makefile.objs b/io/Makefile.objs deleted file mode 100644 index 9a20fce4edc680ba9449430eb8f57113fcf862d1..0000000000000000000000000000000000000000 --- a/io/Makefile.objs +++ /dev/null @@ -1,12 +0,0 @@ -io-obj-y = channel.o -io-obj-y += channel-buffer.o -io-obj-y += channel-command.o -io-obj-y += channel-file.o -io-obj-y += channel-socket.o -io-obj-y += channel-tls.o -io-obj-y += channel-watch.o -io-obj-y += channel-websock.o -io-obj-y += channel-util.o -io-obj-y += dns-resolver.o -io-obj-y += net-listener.o -io-obj-y += task.o diff --git a/io/channel-buffer.c b/io/channel-buffer.c index 5402e0cced39522a05ecde7fa9c104a876aaf2a6..baa4e2b089f615d5b3b6d27d9d50827249371414 100644 --- a/io/channel-buffer.c +++ b/io/channel-buffer.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/io/channel-command.c b/io/channel-command.c index 368dd62b7eda2849d96b5fccee938e15bd540b1f..b2a9e271382a32a98f5df8acc6b8696c0f81b8fd 100644 --- a/io/channel-command.c +++ b/io/channel-command.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/io/channel-file.c b/io/channel-file.c index dac21f6012ae2c9b15f908502dafd8d15dd29f25..c4bf799a80233590bd27b9bd0d43310f1ad5cf12 100644 --- a/io/channel-file.c +++ b/io/channel-file.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -51,7 +51,7 @@ qio_channel_file_new_path(const char *path, ioc = QIO_CHANNEL_FILE(object_new(TYPE_QIO_CHANNEL_FILE)); - ioc->fd = qemu_open(path, flags, mode); + ioc->fd = qemu_open_old(path, flags, mode); if (ioc->fd < 0) { object_unref(OBJECT(ioc)); error_setg_errno(errp, errno, diff --git a/io/channel-socket.c b/io/channel-socket.c index e1b46670874f86391e644242a2e68530fb64cf1f..de259f7eed2752c92ec0b1b77e90896e8ea314e4 100644 --- a/io/channel-socket.c +++ b/io/channel-socket.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/io/channel-tls.c b/io/channel-tls.c index 7ec8ceff2f01744080126985c101621a1aa50e01..388f019977254ebb487fac109595894dd499ddcb 100644 --- a/io/channel-tls.c +++ b/io/channel-tls.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/io/channel-util.c b/io/channel-util.c index 423d79845a20a4e534c109f78889623348e42cb2..848a7a43d671daa6d7257e6fa525ea55a06ebc09 100644 --- a/io/channel-util.c +++ b/io/channel-util.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/io/channel-watch.c b/io/channel-watch.c index 8640d1c4640838ed752e2d4eb2f3db6144194ae8..0289b3647c278077fdfe6e0c99a0d11eeb5ac3ee 100644 --- a/io/channel-watch.c +++ b/io/channel-watch.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/io/channel-websock.c b/io/channel-websock.c index 47a0e941d9f6f9af92223b350e9b41a5a133befc..03c1f7cb62f77af2b0bef66207db5441cf9368c3 100644 --- a/io/channel-websock.c +++ b/io/channel-websock.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -746,7 +746,7 @@ static int qio_channel_websock_decode_header(QIOChannelWebsock *ioc, opcode != QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE && opcode != QIO_CHANNEL_WEBSOCK_OPCODE_PING && opcode != QIO_CHANNEL_WEBSOCK_OPCODE_PONG) { - error_setg(errp, "unsupported opcode: %#04x; only binary, close, " + error_setg(errp, "unsupported opcode: 0x%04x; only binary, close, " "ping, and pong websocket frames are supported", opcode); qio_channel_websock_write_close( ioc, QIO_CHANNEL_WEBSOCK_STATUS_INVALID_DATA , diff --git a/io/channel.c b/io/channel.c index e4376eb0bc405eadf7ff5785373ac4aed765e805..93d449dee261b9674493b6350d1583a46d87023a 100644 --- a/io/channel.c +++ b/io/channel.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/io/dns-resolver.c b/io/dns-resolver.c index 6ebe2a5650b19b7c442f2730b2415c17dee08b0a..743a0efc87670fa89f9becf7de783edb6ed59037 100644 --- a/io/dns-resolver.c +++ b/io/dns-resolver.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -267,7 +267,6 @@ static const TypeInfo qio_dns_resolver_info = { .parent = TYPE_OBJECT, .name = TYPE_QIO_DNS_RESOLVER, .instance_size = sizeof(QIODNSResolver), - .class_size = sizeof(QIODNSResolverClass), }; diff --git a/io/meson.build b/io/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..bcd8b1e7373ae9b4311951ca83e868165c32b6c5 --- /dev/null +++ b/io/meson.build @@ -0,0 +1,15 @@ +io_ss.add(genh) +io_ss.add(files( + 'channel-buffer.c', + 'channel-command.c', + 'channel-file.c', + 'channel-socket.c', + 'channel-tls.c', + 'channel-util.c', + 'channel-watch.c', + 'channel-websock.c', + 'channel.c', + 'dns-resolver.c', + 'net-listener.c', + 'task.c', +)) diff --git a/io/net-listener.c b/io/net-listener.c index 5d8a22687267c05f091dca0faa7ca26abb17e7f8..46c2643d005f92d96b206f594cf05d879b5075c8 100644 --- a/io/net-listener.c +++ b/io/net-listener.c @@ -307,7 +307,6 @@ static const TypeInfo qio_net_listener_info = { .name = TYPE_QIO_NET_LISTENER, .instance_size = sizeof(QIONetListener), .instance_finalize = qio_net_listener_finalize, - .class_size = sizeof(QIONetListenerClass), }; diff --git a/io/task.c b/io/task.c index 1ae7b864881a41669d4a3a924c418ed6f9107de1..451f26f8b4959eb1041cd7bc7d3e3803799a021c 100644 --- a/io/task.c +++ b/io/task.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -22,6 +22,7 @@ #include "io/task.h" #include "qapi/error.h" #include "qemu/thread.h" +#include "qom/object.h" #include "trace.h" struct QIOTaskThreadData { diff --git a/io/trace.h b/io/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..92d63a5bfc61b8c97b3e8380a0f66feaf0b30af3 --- /dev/null +++ b/io/trace.h @@ -0,0 +1 @@ +#include "trace/trace-io.h" diff --git a/iothread.c b/iothread.c index cb082b9b26246290ded0bc075c3d933d1d3b1f4a..69eff9efbc70834f62cd1b009962ee005d88199b 100644 --- a/iothread.c +++ b/iothread.c @@ -26,10 +26,8 @@ typedef ObjectClass IOThreadClass; -#define IOTHREAD_GET_CLASS(obj) \ - OBJECT_GET_CLASS(IOThreadClass, obj, TYPE_IOTHREAD) -#define IOTHREAD_CLASS(klass) \ - OBJECT_CLASS_CHECK(IOThreadClass, klass, TYPE_IOTHREAD) +DECLARE_CLASS_CHECKERS(IOThreadClass, IOTHREAD, + TYPE_IOTHREAD) #ifdef CONFIG_POSIX /* Benchmark results from 2016 on NVMe SSD drives show max polling times around @@ -78,7 +76,7 @@ static void *iothread_run(void *opaque) * We must check the running state again in case it was * changed in previous aio_poll() */ - if (iothread->running && atomic_read(&iothread->run_gcontext)) { + if (iothread->running && qatomic_read(&iothread->run_gcontext)) { g_main_loop_run(iothread->main_loop); } } @@ -118,7 +116,7 @@ static void iothread_instance_init(Object *obj) iothread->thread_id = -1; qemu_sem_init(&iothread->init_done_sem, 0); /* By default, we don't run gcontext */ - atomic_set(&iothread->run_gcontext, 0); + qatomic_set(&iothread->run_gcontext, 0); } static void iothread_instance_finalize(Object *obj) @@ -165,13 +163,12 @@ static void iothread_complete(UserCreatable *obj, Error **errp) { Error *local_error = NULL; IOThread *iothread = IOTHREAD(obj); - char *name, *thread_name; + char *thread_name; iothread->stopping = false; iothread->running = true; - iothread->ctx = aio_context_new(&local_error); + iothread->ctx = aio_context_new(errp); if (!iothread->ctx) { - error_propagate(errp, local_error); return; } @@ -196,12 +193,11 @@ static void iothread_complete(UserCreatable *obj, Error **errp) /* This assumes we are called from a thread with useful CPU affinity for us * to inherit. */ - name = object_get_canonical_path_component(OBJECT(obj)); - thread_name = g_strdup_printf("IO %s", name); + thread_name = g_strdup_printf("IO %s", + object_get_canonical_path_component(OBJECT(obj))); qemu_thread_create(&iothread->thread, thread_name, iothread_run, iothread, QEMU_THREAD_JOINABLE); g_free(thread_name); - g_free(name); /* Wait for initialization to complete */ while (iothread->thread_id == -1) { @@ -240,18 +236,16 @@ static void iothread_set_poll_param(Object *obj, Visitor *v, IOThread *iothread = IOTHREAD(obj); PollParamInfo *info = opaque; int64_t *field = (void *)iothread + info->offset; - Error *local_err = NULL; int64_t value; - visit_type_int64(v, name, &value, &local_err); - if (local_err) { - goto out; + if (!visit_type_int64(v, name, &value, errp)) { + return; } if (value < 0) { - error_setg(&local_err, "%s value must be in range [0, %"PRId64"]", + error_setg(errp, "%s value must be in range [0, %" PRId64 "]", info->name, INT64_MAX); - goto out; + return; } *field = value; @@ -261,11 +255,8 @@ static void iothread_set_poll_param(Object *obj, Visitor *v, iothread->poll_max_ns, iothread->poll_grow, iothread->poll_shrink, - &local_err); + errp); } - -out: - error_propagate(errp, local_err); } static void iothread_class_init(ObjectClass *klass, void *class_data) @@ -309,7 +300,7 @@ type_init(iothread_register_types) char *iothread_get_id(IOThread *iothread) { - return object_get_canonical_path_component(OBJECT(iothread)); + return g_strdup(object_get_canonical_path_component(OBJECT(iothread))); } AioContext *iothread_get_aio_context(IOThread *iothread) @@ -357,7 +348,7 @@ IOThreadInfoList *qmp_query_iothreads(Error **errp) GMainContext *iothread_get_g_main_context(IOThread *iothread) { - atomic_set(&iothread->run_gcontext, 1); + qatomic_set(&iothread->run_gcontext, 1); aio_notify(iothread->ctx); return iothread->worker_context; } diff --git a/job-qmp.c b/job-qmp.c index f9a58832e164bdd8a181c73fc618f2f5dc69d5c8..645601b2ccc1873b5fae2d97dbd8c34a68d42c90 100644 --- a/job-qmp.c +++ b/job-qmp.c @@ -27,7 +27,7 @@ #include "qemu/job.h" #include "qapi/qapi-commands-job.h" #include "qapi/error.h" -#include "trace-root.h" +#include "trace/trace-root.h" /* Get a job using its ID and acquire its AioContext */ static Job *find_job(const char *id, AioContext **aio_context, Error **errp) diff --git a/job.c b/job.c index 53be57a3a0b6d57d21e327d12a75acdfba40c67d..8fecf389609fe09c5f87d001ac7c83af5cde92d9 100644 --- a/job.c +++ b/job.c @@ -29,7 +29,7 @@ #include "qemu/id.h" #include "qemu/main-loop.h" #include "block/aio-wait.h" -#include "trace-root.h" +#include "trace/trace-root.h" #include "qapi/qapi-events-job.h" static QLIST_HEAD(, Job) jobs = QLIST_HEAD_INITIALIZER(jobs); diff --git a/libdecnumber/Makefile.objs b/libdecnumber/Makefile.objs deleted file mode 100644 index d81db0443a4504076d1e7fa5482ded1f6aba9cda..0000000000000000000000000000000000000000 --- a/libdecnumber/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -obj-y += decContext.o -obj-y += decNumber.o -obj-y += dpd/decimal32.o -obj-y += dpd/decimal64.o -obj-y += dpd/decimal128.o diff --git a/libdecnumber/decNumber.c b/libdecnumber/decNumber.c index 8c197023f45602484f3ec85c7b9a6f8eb8159826..1ffe458ad8377e38773d0b79f7d289f84c654fbe 100644 --- a/libdecnumber/decNumber.c +++ b/libdecnumber/decNumber.c @@ -5626,7 +5626,7 @@ static const uShort LNnn[90] = { /* would certainly save at least one if it were made ten times */ /* bigger, too (for truncated fractions 0.100 through 0.999). */ /* However, for most practical evaluations, at least four or five */ -/* iterations will be neede -- so this would only speed up by */ +/* iterations will be needed -- so this would only speed up by */ /* 20-25% and that probably does not justify increasing the table */ /* size. */ /* */ diff --git a/libdecnumber/meson.build b/libdecnumber/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..4d04139af41571772a67af2d12226170e22133f1 --- /dev/null +++ b/libdecnumber/meson.build @@ -0,0 +1,7 @@ +libdecnumber = files( + 'decContext.c', + 'decNumber.c', + 'dpd/decimal128.c', + 'dpd/decimal32.c', + 'dpd/decimal64.c', +) diff --git a/linux-headers/asm-arm/unistd-common.h b/linux-headers/asm-arm/unistd-common.h index 23de64e44c44fbf4e00ceef0f505ea6ad28e9d16..57cd1f21dbd5faf8f5a9a6e7e47253d09d6116a2 100644 --- a/linux-headers/asm-arm/unistd-common.h +++ b/linux-headers/asm-arm/unistd-common.h @@ -392,5 +392,6 @@ #define __NR_clone3 (__NR_SYSCALL_BASE + 435) #define __NR_openat2 (__NR_SYSCALL_BASE + 437) #define __NR_pidfd_getfd (__NR_SYSCALL_BASE + 438) +#define __NR_faccessat2 (__NR_SYSCALL_BASE + 439) #endif /* _ASM_ARM_UNISTD_COMMON_H */ diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h index 9e34f0f875a60a1dc7bb69e0db91d67f7688dbfd..a72de1ae4cb5638b42ea7057a9cca9a1208764d2 100644 --- a/linux-headers/asm-arm64/kvm.h +++ b/linux-headers/asm-arm64/kvm.h @@ -159,6 +159,21 @@ struct kvm_sync_regs { struct kvm_arch_memory_slot { }; +/* + * PMU filter structure. Describe a range of events with a particular + * action. To be used with KVM_ARM_VCPU_PMU_V3_FILTER. + */ +struct kvm_pmu_event_filter { + __u16 base_event; + __u16 nevents; + +#define KVM_PMU_EVENT_ALLOW 0 +#define KVM_PMU_EVENT_DENY 1 + + __u8 action; + __u8 pad[3]; +}; + /* for KVM_GET/SET_VCPU_EVENTS */ struct kvm_vcpu_events { struct { @@ -242,6 +257,15 @@ struct kvm_vcpu_events { #define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL 0 #define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL 1 #define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED 2 + +/* + * Only two states can be presented by the host kernel: + * - NOT_REQUIRED: the guest doesn't need to do anything + * - NOT_AVAIL: the guest isn't mitigated (it can still use SSBS if available) + * + * All the other values are deprecated. The host still accepts all + * values (they are ABI), but will narrow them to the above two. + */ #define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2 KVM_REG_ARM_FW_REG(2) #define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL 0 #define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN 1 @@ -329,6 +353,7 @@ struct kvm_vcpu_events { #define KVM_ARM_VCPU_PMU_V3_CTRL 0 #define KVM_ARM_VCPU_PMU_V3_IRQ 0 #define KVM_ARM_VCPU_PMU_V3_INIT 1 +#define KVM_ARM_VCPU_PMU_V3_FILTER 2 #define KVM_ARM_VCPU_TIMER_CTRL 1 #define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0 #define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1 diff --git a/linux-headers/asm-arm64/mman.h b/linux-headers/asm-arm64/mman.h index 8eebf89f5ab17884a98543f3b37a3b710355083b..d0dbfe958789062e3f56406078aac58710beec41 100644 --- a/linux-headers/asm-arm64/mman.h +++ b/linux-headers/asm-arm64/mman.h @@ -1 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __ASM_MMAN_H +#define __ASM_MMAN_H + #include + +#define PROT_BTI 0x10 /* BTI guarded page */ +#define PROT_MTE 0x20 /* Normal Tagged mapping */ + +#endif /* ! _UAPI__ASM_MMAN_H */ diff --git a/linux-headers/asm-generic/hugetlb_encode.h b/linux-headers/asm-generic/hugetlb_encode.h index b0f8e87235bdf4b599b52895637d9bd6329887fa..4f3d5aaa11f531164beab5a47bed8478e5f17546 100644 --- a/linux-headers/asm-generic/hugetlb_encode.h +++ b/linux-headers/asm-generic/hugetlb_encode.h @@ -20,6 +20,7 @@ #define HUGETLB_FLAG_ENCODE_SHIFT 26 #define HUGETLB_FLAG_ENCODE_MASK 0x3f +#define HUGETLB_FLAG_ENCODE_16KB (14 << HUGETLB_FLAG_ENCODE_SHIFT) #define HUGETLB_FLAG_ENCODE_64KB (16 << HUGETLB_FLAG_ENCODE_SHIFT) #define HUGETLB_FLAG_ENCODE_512KB (19 << HUGETLB_FLAG_ENCODE_SHIFT) #define HUGETLB_FLAG_ENCODE_1MB (20 << HUGETLB_FLAG_ENCODE_SHIFT) diff --git a/linux-headers/asm-generic/unistd.h b/linux-headers/asm-generic/unistd.h index 3a3201e4618ef8c7445895b26f6eebbaea1574f9..2056318988f774931c4e0a3104144bf4a75ff52f 100644 --- a/linux-headers/asm-generic/unistd.h +++ b/linux-headers/asm-generic/unistd.h @@ -140,7 +140,7 @@ __SYSCALL(__NR_renameat, sys_renameat) #define __NR_umount2 39 __SYSCALL(__NR_umount2, sys_umount) #define __NR_mount 40 -__SC_COMP(__NR_mount, sys_mount, compat_sys_mount) +__SYSCALL(__NR_mount, sys_mount) #define __NR_pivot_root 41 __SYSCALL(__NR_pivot_root, sys_pivot_root) @@ -207,9 +207,9 @@ __SYSCALL(__NR_read, sys_read) #define __NR_write 64 __SYSCALL(__NR_write, sys_write) #define __NR_readv 65 -__SC_COMP(__NR_readv, sys_readv, compat_sys_readv) +__SC_COMP(__NR_readv, sys_readv, sys_readv) #define __NR_writev 66 -__SC_COMP(__NR_writev, sys_writev, compat_sys_writev) +__SC_COMP(__NR_writev, sys_writev, sys_writev) #define __NR_pread64 67 __SC_COMP(__NR_pread64, sys_pread64, compat_sys_pread64) #define __NR_pwrite64 68 @@ -237,7 +237,7 @@ __SC_COMP(__NR_signalfd4, sys_signalfd4, compat_sys_signalfd4) /* fs/splice.c */ #define __NR_vmsplice 75 -__SC_COMP(__NR_vmsplice, sys_vmsplice, compat_sys_vmsplice) +__SYSCALL(__NR_vmsplice, sys_vmsplice) #define __NR_splice 76 __SYSCALL(__NR_splice, sys_splice) #define __NR_tee 77 @@ -606,9 +606,9 @@ __SYSCALL(__NR_sendto, sys_sendto) #define __NR_recvfrom 207 __SC_COMP(__NR_recvfrom, sys_recvfrom, compat_sys_recvfrom) #define __NR_setsockopt 208 -__SC_COMP(__NR_setsockopt, sys_setsockopt, compat_sys_setsockopt) +__SC_COMP(__NR_setsockopt, sys_setsockopt, sys_setsockopt) #define __NR_getsockopt 209 -__SC_COMP(__NR_getsockopt, sys_getsockopt, compat_sys_getsockopt) +__SC_COMP(__NR_getsockopt, sys_getsockopt, sys_getsockopt) #define __NR_shutdown 210 __SYSCALL(__NR_shutdown, sys_shutdown) #define __NR_sendmsg 211 @@ -727,11 +727,9 @@ __SYSCALL(__NR_setns, sys_setns) #define __NR_sendmmsg 269 __SC_COMP(__NR_sendmmsg, sys_sendmmsg, compat_sys_sendmmsg) #define __NR_process_vm_readv 270 -__SC_COMP(__NR_process_vm_readv, sys_process_vm_readv, \ - compat_sys_process_vm_readv) +__SYSCALL(__NR_process_vm_readv, sys_process_vm_readv) #define __NR_process_vm_writev 271 -__SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \ - compat_sys_process_vm_writev) +__SYSCALL(__NR_process_vm_writev, sys_process_vm_writev) #define __NR_kcmp 272 __SYSCALL(__NR_kcmp, sys_kcmp) #define __NR_finit_module 273 @@ -850,14 +848,20 @@ __SYSCALL(__NR_pidfd_open, sys_pidfd_open) #define __NR_clone3 435 __SYSCALL(__NR_clone3, sys_clone3) #endif +#define __NR_close_range 436 +__SYSCALL(__NR_close_range, sys_close_range) #define __NR_openat2 437 __SYSCALL(__NR_openat2, sys_openat2) #define __NR_pidfd_getfd 438 __SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd) +#define __NR_faccessat2 439 +__SYSCALL(__NR_faccessat2, sys_faccessat2) +#define __NR_process_madvise 440 +__SYSCALL(__NR_process_madvise, sys_process_madvise) #undef __NR_syscalls -#define __NR_syscalls 439 +#define __NR_syscalls 441 /* * 32 bit systems traditionally used different diff --git a/linux-headers/asm-mips/unistd_n32.h b/linux-headers/asm-mips/unistd_n32.h index aec9f6081af7974a2f8fc075a70fd57b4a7a2dd6..aba284d190a0f7b887943283bfb68ea6aa85aeb9 100644 --- a/linux-headers/asm-mips/unistd_n32.h +++ b/linux-headers/asm-mips/unistd_n32.h @@ -365,8 +365,11 @@ #define __NR_fspick (__NR_Linux + 433) #define __NR_pidfd_open (__NR_Linux + 434) #define __NR_clone3 (__NR_Linux + 435) +#define __NR_close_range (__NR_Linux + 436) #define __NR_openat2 (__NR_Linux + 437) #define __NR_pidfd_getfd (__NR_Linux + 438) +#define __NR_faccessat2 (__NR_Linux + 439) +#define __NR_process_madvise (__NR_Linux + 440) #endif /* _ASM_MIPS_UNISTD_N32_H */ diff --git a/linux-headers/asm-mips/unistd_n64.h b/linux-headers/asm-mips/unistd_n64.h index 1c75d83df53f90aa386b8b919a3df255da11821b..0465ab94db8966b453f1e1863e0096f9af576df8 100644 --- a/linux-headers/asm-mips/unistd_n64.h +++ b/linux-headers/asm-mips/unistd_n64.h @@ -341,8 +341,11 @@ #define __NR_fspick (__NR_Linux + 433) #define __NR_pidfd_open (__NR_Linux + 434) #define __NR_clone3 (__NR_Linux + 435) +#define __NR_close_range (__NR_Linux + 436) #define __NR_openat2 (__NR_Linux + 437) #define __NR_pidfd_getfd (__NR_Linux + 438) +#define __NR_faccessat2 (__NR_Linux + 439) +#define __NR_process_madvise (__NR_Linux + 440) #endif /* _ASM_MIPS_UNISTD_N64_H */ diff --git a/linux-headers/asm-mips/unistd_o32.h b/linux-headers/asm-mips/unistd_o32.h index 660716e240ec10f7ccf3e65239dd1ac512672b52..5222a0dd50e18b778dcc38f45af81b26cd072e7f 100644 --- a/linux-headers/asm-mips/unistd_o32.h +++ b/linux-headers/asm-mips/unistd_o32.h @@ -411,8 +411,11 @@ #define __NR_fspick (__NR_Linux + 433) #define __NR_pidfd_open (__NR_Linux + 434) #define __NR_clone3 (__NR_Linux + 435) +#define __NR_close_range (__NR_Linux + 436) #define __NR_openat2 (__NR_Linux + 437) #define __NR_pidfd_getfd (__NR_Linux + 438) +#define __NR_faccessat2 (__NR_Linux + 439) +#define __NR_process_madvise (__NR_Linux + 440) #endif /* _ASM_MIPS_UNISTD_O32_H */ diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h index 264e266a85bf6a99c5b27b47733ad5f11b5e02d5..c3af3f324c5ad14625baf14fa488b2aa104240c3 100644 --- a/linux-headers/asm-powerpc/kvm.h +++ b/linux-headers/asm-powerpc/kvm.h @@ -640,6 +640,11 @@ struct kvm_ppc_cpu_char { #define KVM_REG_PPC_ONLINE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbf) #define KVM_REG_PPC_PTCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc0) +/* POWER10 registers */ +#define KVM_REG_PPC_MMCR3 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc1) +#define KVM_REG_PPC_SIER2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc2) +#define KVM_REG_PPC_SIER3 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc3) + /* Transactional Memory checkpointed state: * This is all GPRs, all VSX regs and a subset of SPRs */ diff --git a/linux-headers/asm-powerpc/unistd_32.h b/linux-headers/asm-powerpc/unistd_32.h index 4ba8e32f734445f6107d45044d084081d83d6f4d..21066a3d5f4a65bd2a1e09c002a3db12e7045e15 100644 --- a/linux-headers/asm-powerpc/unistd_32.h +++ b/linux-headers/asm-powerpc/unistd_32.h @@ -418,8 +418,11 @@ #define __NR_fspick 433 #define __NR_pidfd_open 434 #define __NR_clone3 435 +#define __NR_close_range 436 #define __NR_openat2 437 #define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 +#define __NR_process_madvise 440 #endif /* _ASM_POWERPC_UNISTD_32_H */ diff --git a/linux-headers/asm-powerpc/unistd_64.h b/linux-headers/asm-powerpc/unistd_64.h index ac20bb4f95b207d4875613b54c45eaf40a1a4c70..c153da29f2362aa32b379a711ac883af2d8f0a5c 100644 --- a/linux-headers/asm-powerpc/unistd_64.h +++ b/linux-headers/asm-powerpc/unistd_64.h @@ -390,8 +390,11 @@ #define __NR_fspick 433 #define __NR_pidfd_open 434 #define __NR_clone3 435 +#define __NR_close_range 436 #define __NR_openat2 437 #define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 +#define __NR_process_madvise 440 #endif /* _ASM_POWERPC_UNISTD_64_H */ diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h index 0138ccb0d892b4e3cc0d5e9c6a607ecc723aad45..f053b8304a85ae57e3e8cdbf9f328d6e990063d9 100644 --- a/linux-headers/asm-s390/kvm.h +++ b/linux-headers/asm-s390/kvm.h @@ -231,11 +231,13 @@ struct kvm_guest_debug_arch { #define KVM_SYNC_GSCB (1UL << 9) #define KVM_SYNC_BPBC (1UL << 10) #define KVM_SYNC_ETOKEN (1UL << 11) +#define KVM_SYNC_DIAG318 (1UL << 12) #define KVM_SYNC_S390_VALID_FIELDS \ (KVM_SYNC_PREFIX | KVM_SYNC_GPRS | KVM_SYNC_ACRS | KVM_SYNC_CRS | \ KVM_SYNC_ARCH0 | KVM_SYNC_PFAULT | KVM_SYNC_VRS | KVM_SYNC_RICCB | \ - KVM_SYNC_FPRS | KVM_SYNC_GSCB | KVM_SYNC_BPBC | KVM_SYNC_ETOKEN) + KVM_SYNC_FPRS | KVM_SYNC_GSCB | KVM_SYNC_BPBC | KVM_SYNC_ETOKEN | \ + KVM_SYNC_DIAG318) /* length and alignment of the sdnx as a power of two */ #define SDNXC 8 @@ -264,7 +266,8 @@ struct kvm_sync_regs { __u8 reserved2 : 7; __u8 padding1[51]; /* riccb needs to be 64byte aligned */ __u8 riccb[64]; /* runtime instrumentation controls block */ - __u8 padding2[192]; /* sdnx needs to be 256byte aligned */ + __u64 diag318; /* diagnose 0x318 info */ + __u8 padding2[184]; /* sdnx needs to be 256byte aligned */ union { __u8 sdnx[SDNXL]; /* state description annex */ struct { diff --git a/linux-headers/asm-s390/unistd_32.h b/linux-headers/asm-s390/unistd_32.h index e4a6b654f10e1169e4fd6283828262a671ec760a..3b4f2dda6049767ea56e3a29ecf65ac65c15f42f 100644 --- a/linux-headers/asm-s390/unistd_32.h +++ b/linux-headers/asm-s390/unistd_32.h @@ -408,7 +408,10 @@ #define __NR_fspick 433 #define __NR_pidfd_open 434 #define __NR_clone3 435 +#define __NR_close_range 436 #define __NR_openat2 437 #define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 +#define __NR_process_madvise 440 #endif /* _ASM_S390_UNISTD_32_H */ diff --git a/linux-headers/asm-s390/unistd_64.h b/linux-headers/asm-s390/unistd_64.h index 472f732956e4d1047d95dd68c5de72a6cd9611fb..030a51fa3828b9a8ea64d42dc84b9dd0911a63fa 100644 --- a/linux-headers/asm-s390/unistd_64.h +++ b/linux-headers/asm-s390/unistd_64.h @@ -356,7 +356,10 @@ #define __NR_fspick 433 #define __NR_pidfd_open 434 #define __NR_clone3 435 +#define __NR_close_range 436 #define __NR_openat2 437 #define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 +#define __NR_process_madvise 440 #endif /* _ASM_S390_UNISTD_64_H */ diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h index 3f3f780c8c6500e1a1ea52bc0585af93699572fe..89e5f3d1bba86b8bbb0e7a80cbed2d1373d093af 100644 --- a/linux-headers/asm-x86/kvm.h +++ b/linux-headers/asm-x86/kvm.h @@ -192,6 +192,26 @@ struct kvm_msr_list { __u32 indices[0]; }; +/* Maximum size of any access bitmap in bytes */ +#define KVM_MSR_FILTER_MAX_BITMAP_SIZE 0x600 + +/* for KVM_X86_SET_MSR_FILTER */ +struct kvm_msr_filter_range { +#define KVM_MSR_FILTER_READ (1 << 0) +#define KVM_MSR_FILTER_WRITE (1 << 1) + __u32 flags; + __u32 nmsrs; /* number of msrs in bitmap */ + __u32 base; /* MSR index the bitmap starts at */ + __u8 *bitmap; /* a 1 bit allows the operations in flags, 0 denies */ +}; + +#define KVM_MSR_FILTER_MAX_RANGES 16 +struct kvm_msr_filter { +#define KVM_MSR_FILTER_DEFAULT_ALLOW (0 << 0) +#define KVM_MSR_FILTER_DEFAULT_DENY (1 << 0) + __u32 flags; + struct kvm_msr_filter_range ranges[KVM_MSR_FILTER_MAX_RANGES]; +}; struct kvm_cpuid_entry { __u32 function; @@ -385,18 +405,23 @@ struct kvm_sync_regs { #define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4) #define KVM_STATE_NESTED_FORMAT_VMX 0 -#define KVM_STATE_NESTED_FORMAT_SVM 1 /* unused */ +#define KVM_STATE_NESTED_FORMAT_SVM 1 #define KVM_STATE_NESTED_GUEST_MODE 0x00000001 #define KVM_STATE_NESTED_RUN_PENDING 0x00000002 #define KVM_STATE_NESTED_EVMCS 0x00000004 #define KVM_STATE_NESTED_MTF_PENDING 0x00000008 +#define KVM_STATE_NESTED_GIF_SET 0x00000100 #define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001 #define KVM_STATE_NESTED_SMM_VMXON 0x00000002 #define KVM_STATE_NESTED_VMX_VMCS_SIZE 0x1000 +#define KVM_STATE_NESTED_SVM_VMCB_SIZE 0x1000 + +#define KVM_STATE_VMX_PREEMPTION_TIMER_DEADLINE 0x00000001 + struct kvm_vmx_nested_state_data { __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE]; __u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE]; @@ -409,6 +434,18 @@ struct kvm_vmx_nested_state_hdr { struct { __u16 flags; } smm; + + __u32 flags; + __u64 preemption_timer_deadline; +}; + +struct kvm_svm_nested_state_data { + /* Save area only used if KVM_STATE_NESTED_RUN_PENDING. */ + __u8 vmcb12[KVM_STATE_NESTED_SVM_VMCB_SIZE]; +}; + +struct kvm_svm_nested_state_hdr { + __u64 vmcb_pa; }; /* for KVM_CAP_NESTED_STATE */ @@ -419,6 +456,7 @@ struct kvm_nested_state { union { struct kvm_vmx_nested_state_hdr vmx; + struct kvm_svm_nested_state_hdr svm; /* Pad the header to 128 bytes. */ __u8 pad[120]; @@ -431,6 +469,7 @@ struct kvm_nested_state { */ union { struct kvm_vmx_nested_state_data vmx[0]; + struct kvm_svm_nested_state_data svm[0]; } data; }; diff --git a/linux-headers/asm-x86/unistd.h b/linux-headers/asm-x86/unistd.h index 498d1515c616b2b41675b79270dcadfc779f4496..d2af42d61ded12e1f13748be46fab25b112025a4 100644 --- a/linux-headers/asm-x86/unistd.h +++ b/linux-headers/asm-x86/unistd.h @@ -2,8 +2,15 @@ #ifndef _ASM_X86_UNISTD_H #define _ASM_X86_UNISTD_H -/* x32 syscall flag bit */ -#define __X32_SYSCALL_BIT 0x40000000UL +/* + * x32 syscall flag bit. Some user programs expect syscall NR macros + * and __X32_SYSCALL_BIT to have type int, even though syscall numbers + * are, for practical purposes, unsigned long. + * + * Fortunately, expressions like (nr & ~__X32_SYSCALL_BIT) do the right + * thing regardless. + */ +#define __X32_SYSCALL_BIT 0x40000000 # ifdef __i386__ # include diff --git a/linux-headers/asm-x86/unistd_32.h b/linux-headers/asm-x86/unistd_32.h index 1e6c1a586776181a3caba2bbba1fe4c93a9c8108..cfba368f9dffa9ed90eeff56784996ff411071e0 100644 --- a/linux-headers/asm-x86/unistd_32.h +++ b/linux-headers/asm-x86/unistd_32.h @@ -426,8 +426,11 @@ #define __NR_fspick 433 #define __NR_pidfd_open 434 #define __NR_clone3 435 +#define __NR_close_range 436 #define __NR_openat2 437 #define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 +#define __NR_process_madvise 440 #endif /* _ASM_X86_UNISTD_32_H */ diff --git a/linux-headers/asm-x86/unistd_64.h b/linux-headers/asm-x86/unistd_64.h index 6daf0aecb2984b846595f8f3ea6ea608b96878bc..61af7250955feef3be80c70eeccce99c6145e7e8 100644 --- a/linux-headers/asm-x86/unistd_64.h +++ b/linux-headers/asm-x86/unistd_64.h @@ -348,8 +348,11 @@ #define __NR_fspick 433 #define __NR_pidfd_open 434 #define __NR_clone3 435 +#define __NR_close_range 436 #define __NR_openat2 437 #define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 +#define __NR_process_madvise 440 #endif /* _ASM_X86_UNISTD_64_H */ diff --git a/linux-headers/asm-x86/unistd_x32.h b/linux-headers/asm-x86/unistd_x32.h index e3f17ef370fcfd16d26ea2709d1645cd94909438..a6890cb1f5b534b152455e07e7074243f135ce51 100644 --- a/linux-headers/asm-x86/unistd_x32.h +++ b/linux-headers/asm-x86/unistd_x32.h @@ -301,8 +301,11 @@ #define __NR_fspick (__X32_SYSCALL_BIT + 433) #define __NR_pidfd_open (__X32_SYSCALL_BIT + 434) #define __NR_clone3 (__X32_SYSCALL_BIT + 435) +#define __NR_close_range (__X32_SYSCALL_BIT + 436) #define __NR_openat2 (__X32_SYSCALL_BIT + 437) #define __NR_pidfd_getfd (__X32_SYSCALL_BIT + 438) +#define __NR_faccessat2 (__X32_SYSCALL_BIT + 439) +#define __NR_process_madvise (__X32_SYSCALL_BIT + 440) #define __NR_rt_sigaction (__X32_SYSCALL_BIT + 512) #define __NR_rt_sigreturn (__X32_SYSCALL_BIT + 513) #define __NR_ioctl (__X32_SYSCALL_BIT + 514) diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index ff6fb2ff531f45a3e045cc7ec8d3199195dcaf09..ddeedcf3df9646486ac4e6f2557068a041f5e9bb 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -116,7 +116,7 @@ struct kvm_irq_level { * ACPI gsi notion of irq. * For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47.. * For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23.. - * For ARM: See Documentation/virt/kvm/api.txt + * For ARM: See Documentation/virt/kvm/api.rst */ union { __u32 irq; @@ -188,10 +188,13 @@ struct kvm_s390_cmma_log { struct kvm_hyperv_exit { #define KVM_EXIT_HYPERV_SYNIC 1 #define KVM_EXIT_HYPERV_HCALL 2 +#define KVM_EXIT_HYPERV_SYNDBG 3 __u32 type; + __u32 pad1; union { struct { __u32 msr; + __u32 pad2; __u64 control; __u64 evt_page; __u64 msg_page; @@ -201,6 +204,15 @@ struct kvm_hyperv_exit { __u64 result; __u64 params[2]; } hcall; + struct { + __u32 msr; + __u32 pad2; + __u64 control; + __u64 status; + __u64 send_page; + __u64 recv_page; + __u64 pending_page; + } syndbg; } u; }; @@ -236,7 +248,9 @@ struct kvm_hyperv_exit { #define KVM_EXIT_IOAPIC_EOI 26 #define KVM_EXIT_HYPERV 27 #define KVM_EXIT_ARM_NISV 28 -#define KVM_EXIT_RISCV_SBI 28 +#define KVM_EXIT_X86_RDMSR 29 +#define KVM_EXIT_X86_WRMSR 30 +#define KVM_EXIT_RISCV_SBI 31 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -278,6 +292,7 @@ struct kvm_run { /* KVM_EXIT_FAIL_ENTRY */ struct { __u64 hardware_entry_failure_reason; + __u32 cpu; } fail_entry; /* KVM_EXIT_EXCEPTION */ struct { @@ -401,6 +416,17 @@ struct kvm_run { __u64 esr_iss; __u64 fault_ipa; } arm_nisv; + /* KVM_EXIT_X86_RDMSR / KVM_EXIT_X86_WRMSR */ + struct { + __u8 error; /* user -> kernel */ + __u8 pad[7]; +#define KVM_MSR_EXIT_REASON_INVAL (1 << 0) +#define KVM_MSR_EXIT_REASON_UNKNOWN (1 << 1) +#define KVM_MSR_EXIT_REASON_FILTER (1 << 2) + __u32 reason; /* kernel -> user */ + __u32 index; /* kernel -> user */ + __u64 data; /* kernel <-> user */ + } msr; /* KVM_EXIT_RISCV_SBI */ struct { unsigned long extension_id; @@ -785,9 +811,10 @@ struct kvm_ppc_resize_hpt { #define KVM_VM_PPC_HV 1 #define KVM_VM_PPC_PR 2 -/* on MIPS, 0 forces trap & emulate, 1 forces VZ ASE */ -#define KVM_VM_MIPS_TE 0 +/* on MIPS, 0 indicates auto, 1 forces VZ ASE, 2 forces trap & emulate */ +#define KVM_VM_MIPS_AUTO 0 #define KVM_VM_MIPS_VZ 1 +#define KVM_VM_MIPS_TE 2 #define KVM_S390_SIE_PAGE_OFFSET 1 @@ -1025,6 +1052,15 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_S390_VCPU_RESETS 179 #define KVM_CAP_S390_PROTECTED 180 #define KVM_CAP_PPC_SECURE_GUEST 181 +#define KVM_CAP_HALT_POLL 182 +#define KVM_CAP_ASYNC_PF_INT 183 +#define KVM_CAP_LAST_CPU 184 +#define KVM_CAP_SMALLER_MAXPHYADDR 185 +#define KVM_CAP_S390_DIAG318 186 +#define KVM_CAP_STEAL_TIME 187 +#define KVM_CAP_X86_USER_SPACE_MSR 188 +#define KVM_CAP_X86_MSR_FILTER 189 +#define KVM_CAP_ENFORCE_PV_FEATURE_CPUID 190 #ifdef KVM_CAP_IRQ_ROUTING @@ -1115,7 +1151,7 @@ struct kvm_xen_hvm_config { * * KVM_IRQFD_FLAG_RESAMPLE indicates resamplefd is valid and specifies * the irqfd to operate in resampling mode for level triggered interrupt - * emulation. See Documentation/virt/kvm/api.txt. + * emulation. See Documentation/virt/kvm/api.rst. */ #define KVM_IRQFD_FLAG_RESAMPLE (1 << 1) @@ -1526,6 +1562,9 @@ struct kvm_pv_cmd { /* Available with KVM_CAP_S390_PROTECTED */ #define KVM_S390_PV_COMMAND _IOWR(KVMIO, 0xc5, struct kvm_pv_cmd) +/* Available with KVM_CAP_X86_MSR_FILTER */ +#define KVM_X86_SET_MSR_FILTER _IOW(KVMIO, 0xc6, struct kvm_msr_filter) + /* Secure Encrypted Virtualization command */ enum sev_cmd_id { /* Guest initialization commands */ diff --git a/linux-headers/linux/mman.h b/linux-headers/linux/mman.h index 51ea363759f021d964e23440cd82eda5ac95e625..434986fbe3071d1fd0c13d6a46a6b3c2473c9dfe 100644 --- a/linux-headers/linux/mman.h +++ b/linux-headers/linux/mman.h @@ -27,6 +27,7 @@ #define MAP_HUGE_SHIFT HUGETLB_FLAG_ENCODE_SHIFT #define MAP_HUGE_MASK HUGETLB_FLAG_ENCODE_MASK +#define MAP_HUGE_16KB HUGETLB_FLAG_ENCODE_16KB #define MAP_HUGE_64KB HUGETLB_FLAG_ENCODE_64KB #define MAP_HUGE_512KB HUGETLB_FLAG_ENCODE_512KB #define MAP_HUGE_1MB HUGETLB_FLAG_ENCODE_1MB diff --git a/linux-headers/linux/psp-sev.h b/linux-headers/linux/psp-sev.h index 31f971e89659b667eccc0d0895995ff8d6958a7f..51d8b3940e1448d1a3e2488279b19a300fd346e9 100644 --- a/linux-headers/linux/psp-sev.h +++ b/linux-headers/linux/psp-sev.h @@ -83,6 +83,8 @@ struct sev_user_data_status { __u32 guest_count; /* Out */ } __attribute__((packed)); +#define SEV_STATUS_FLAGS_CONFIG_ES 0x0100 + /** * struct sev_user_data_pek_csr - PEK_CSR command parameters * diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h index a41c45286511f083878c06b60d71d05e837b0e35..b92dcc4dafd5f00fd1ab89199aee0ac1c88477ea 100644 --- a/linux-headers/linux/vfio.h +++ b/linux-headers/linux/vfio.h @@ -201,8 +201,11 @@ struct vfio_device_info { #define VFIO_DEVICE_FLAGS_AMBA (1 << 3) /* vfio-amba device */ #define VFIO_DEVICE_FLAGS_CCW (1 << 4) /* vfio-ccw device */ #define VFIO_DEVICE_FLAGS_AP (1 << 5) /* vfio-ap device */ +#define VFIO_DEVICE_FLAGS_FSL_MC (1 << 6) /* vfio-fsl-mc device */ +#define VFIO_DEVICE_FLAGS_CAPS (1 << 7) /* Info supports caps */ __u32 num_regions; /* Max region index + 1 */ __u32 num_irqs; /* Max IRQ index + 1 */ + __u32 cap_offset; /* Offset within info struct of first cap */ }; #define VFIO_DEVICE_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 7) @@ -218,6 +221,15 @@ struct vfio_device_info { #define VFIO_DEVICE_API_CCW_STRING "vfio-ccw" #define VFIO_DEVICE_API_AP_STRING "vfio-ap" +/* + * The following capabilities are unique to s390 zPCI devices. Their contents + * are further-defined in vfio_zdev.h + */ +#define VFIO_DEVICE_INFO_CAP_ZPCI_BASE 1 +#define VFIO_DEVICE_INFO_CAP_ZPCI_GROUP 2 +#define VFIO_DEVICE_INFO_CAP_ZPCI_UTIL 3 +#define VFIO_DEVICE_INFO_CAP_ZPCI_PFIP 4 + /** * VFIO_DEVICE_GET_REGION_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 8, * struct vfio_region_info) @@ -305,6 +317,7 @@ struct vfio_region_info_cap_type { #define VFIO_REGION_TYPE_PCI_VENDOR_MASK (0xffff) #define VFIO_REGION_TYPE_GFX (1) #define VFIO_REGION_TYPE_CCW (2) +#define VFIO_REGION_TYPE_MIGRATION (3) /* sub-types for VFIO_REGION_TYPE_PCI_* */ @@ -378,6 +391,235 @@ struct vfio_region_gfx_edid { /* sub-types for VFIO_REGION_TYPE_CCW */ #define VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD (1) +#define VFIO_REGION_SUBTYPE_CCW_SCHIB (2) +#define VFIO_REGION_SUBTYPE_CCW_CRW (3) + +/* sub-types for VFIO_REGION_TYPE_MIGRATION */ +#define VFIO_REGION_SUBTYPE_MIGRATION (1) + +/* + * The structure vfio_device_migration_info is placed at the 0th offset of + * the VFIO_REGION_SUBTYPE_MIGRATION region to get and set VFIO device related + * migration information. Field accesses from this structure are only supported + * at their native width and alignment. Otherwise, the result is undefined and + * vendor drivers should return an error. + * + * device_state: (read/write) + * - The user application writes to this field to inform the vendor driver + * about the device state to be transitioned to. + * - The vendor driver should take the necessary actions to change the + * device state. After successful transition to a given state, the + * vendor driver should return success on write(device_state, state) + * system call. If the device state transition fails, the vendor driver + * should return an appropriate -errno for the fault condition. + * - On the user application side, if the device state transition fails, + * that is, if write(device_state, state) returns an error, read + * device_state again to determine the current state of the device from + * the vendor driver. + * - The vendor driver should return previous state of the device unless + * the vendor driver has encountered an internal error, in which case + * the vendor driver may report the device_state VFIO_DEVICE_STATE_ERROR. + * - The user application must use the device reset ioctl to recover the + * device from VFIO_DEVICE_STATE_ERROR state. If the device is + * indicated to be in a valid device state by reading device_state, the + * user application may attempt to transition the device to any valid + * state reachable from the current state or terminate itself. + * + * device_state consists of 3 bits: + * - If bit 0 is set, it indicates the _RUNNING state. If bit 0 is clear, + * it indicates the _STOP state. When the device state is changed to + * _STOP, driver should stop the device before write() returns. + * - If bit 1 is set, it indicates the _SAVING state, which means that the + * driver should start gathering device state information that will be + * provided to the VFIO user application to save the device's state. + * - If bit 2 is set, it indicates the _RESUMING state, which means that + * the driver should prepare to resume the device. Data provided through + * the migration region should be used to resume the device. + * Bits 3 - 31 are reserved for future use. To preserve them, the user + * application should perform a read-modify-write operation on this + * field when modifying the specified bits. + * + * +------- _RESUMING + * |+------ _SAVING + * ||+----- _RUNNING + * ||| + * 000b => Device Stopped, not saving or resuming + * 001b => Device running, which is the default state + * 010b => Stop the device & save the device state, stop-and-copy state + * 011b => Device running and save the device state, pre-copy state + * 100b => Device stopped and the device state is resuming + * 101b => Invalid state + * 110b => Error state + * 111b => Invalid state + * + * State transitions: + * + * _RESUMING _RUNNING Pre-copy Stop-and-copy _STOP + * (100b) (001b) (011b) (010b) (000b) + * 0. Running or default state + * | + * + * 1. Normal Shutdown (optional) + * |------------------------------------->| + * + * 2. Save the state or suspend + * |------------------------->|---------->| + * + * 3. Save the state during live migration + * |----------->|------------>|---------->| + * + * 4. Resuming + * |<---------| + * + * 5. Resumed + * |--------->| + * + * 0. Default state of VFIO device is _RUNNING when the user application starts. + * 1. During normal shutdown of the user application, the user application may + * optionally change the VFIO device state from _RUNNING to _STOP. This + * transition is optional. The vendor driver must support this transition but + * must not require it. + * 2. When the user application saves state or suspends the application, the + * device state transitions from _RUNNING to stop-and-copy and then to _STOP. + * On state transition from _RUNNING to stop-and-copy, driver must stop the + * device, save the device state and send it to the application through the + * migration region. The sequence to be followed for such transition is given + * below. + * 3. In live migration of user application, the state transitions from _RUNNING + * to pre-copy, to stop-and-copy, and to _STOP. + * On state transition from _RUNNING to pre-copy, the driver should start + * gathering the device state while the application is still running and send + * the device state data to application through the migration region. + * On state transition from pre-copy to stop-and-copy, the driver must stop + * the device, save the device state and send it to the user application + * through the migration region. + * Vendor drivers must support the pre-copy state even for implementations + * where no data is provided to the user before the stop-and-copy state. The + * user must not be required to consume all migration data before the device + * transitions to a new state, including the stop-and-copy state. + * The sequence to be followed for above two transitions is given below. + * 4. To start the resuming phase, the device state should be transitioned from + * the _RUNNING to the _RESUMING state. + * In the _RESUMING state, the driver should use the device state data + * received through the migration region to resume the device. + * 5. After providing saved device data to the driver, the application should + * change the state from _RESUMING to _RUNNING. + * + * reserved: + * Reads on this field return zero and writes are ignored. + * + * pending_bytes: (read only) + * The number of pending bytes still to be migrated from the vendor driver. + * + * data_offset: (read only) + * The user application should read data_offset field from the migration + * region. The user application should read the device data from this + * offset within the migration region during the _SAVING state or write + * the device data during the _RESUMING state. See below for details of + * sequence to be followed. + * + * data_size: (read/write) + * The user application should read data_size to get the size in bytes of + * the data copied in the migration region during the _SAVING state and + * write the size in bytes of the data copied in the migration region + * during the _RESUMING state. + * + * The format of the migration region is as follows: + * ------------------------------------------------------------------ + * |vfio_device_migration_info| data section | + * | | /////////////////////////////// | + * ------------------------------------------------------------------ + * ^ ^ + * offset 0-trapped part data_offset + * + * The structure vfio_device_migration_info is always followed by the data + * section in the region, so data_offset will always be nonzero. The offset + * from where the data is copied is decided by the kernel driver. The data + * section can be trapped, mmapped, or partitioned, depending on how the kernel + * driver defines the data section. The data section partition can be defined + * as mapped by the sparse mmap capability. If mmapped, data_offset must be + * page aligned, whereas initial section which contains the + * vfio_device_migration_info structure, might not end at the offset, which is + * page aligned. The user is not required to access through mmap regardless + * of the capabilities of the region mmap. + * The vendor driver should determine whether and how to partition the data + * section. The vendor driver should return data_offset accordingly. + * + * The sequence to be followed while in pre-copy state and stop-and-copy state + * is as follows: + * a. Read pending_bytes, indicating the start of a new iteration to get device + * data. Repeated read on pending_bytes at this stage should have no side + * effects. + * If pending_bytes == 0, the user application should not iterate to get data + * for that device. + * If pending_bytes > 0, perform the following steps. + * b. Read data_offset, indicating that the vendor driver should make data + * available through the data section. The vendor driver should return this + * read operation only after data is available from (region + data_offset) + * to (region + data_offset + data_size). + * c. Read data_size, which is the amount of data in bytes available through + * the migration region. + * Read on data_offset and data_size should return the offset and size of + * the current buffer if the user application reads data_offset and + * data_size more than once here. + * d. Read data_size bytes of data from (region + data_offset) from the + * migration region. + * e. Process the data. + * f. Read pending_bytes, which indicates that the data from the previous + * iteration has been read. If pending_bytes > 0, go to step b. + * + * The user application can transition from the _SAVING|_RUNNING + * (pre-copy state) to the _SAVING (stop-and-copy) state regardless of the + * number of pending bytes. The user application should iterate in _SAVING + * (stop-and-copy) until pending_bytes is 0. + * + * The sequence to be followed while _RESUMING device state is as follows: + * While data for this device is available, repeat the following steps: + * a. Read data_offset from where the user application should write data. + * b. Write migration data starting at the migration region + data_offset for + * the length determined by data_size from the migration source. + * c. Write data_size, which indicates to the vendor driver that data is + * written in the migration region. Vendor driver must return this write + * operations on consuming data. Vendor driver should apply the + * user-provided migration region data to the device resume state. + * + * If an error occurs during the above sequences, the vendor driver can return + * an error code for next read() or write() operation, which will terminate the + * loop. The user application should then take the next necessary action, for + * example, failing migration or terminating the user application. + * + * For the user application, data is opaque. The user application should write + * data in the same order as the data is received and the data should be of + * same transaction size at the source. + */ + +struct vfio_device_migration_info { + __u32 device_state; /* VFIO device state */ +#define VFIO_DEVICE_STATE_STOP (0) +#define VFIO_DEVICE_STATE_RUNNING (1 << 0) +#define VFIO_DEVICE_STATE_SAVING (1 << 1) +#define VFIO_DEVICE_STATE_RESUMING (1 << 2) +#define VFIO_DEVICE_STATE_MASK (VFIO_DEVICE_STATE_RUNNING | \ + VFIO_DEVICE_STATE_SAVING | \ + VFIO_DEVICE_STATE_RESUMING) + +#define VFIO_DEVICE_STATE_VALID(state) \ + (state & VFIO_DEVICE_STATE_RESUMING ? \ + (state & VFIO_DEVICE_STATE_MASK) == VFIO_DEVICE_STATE_RESUMING : 1) + +#define VFIO_DEVICE_STATE_IS_ERROR(state) \ + ((state & VFIO_DEVICE_STATE_MASK) == (VFIO_DEVICE_STATE_SAVING | \ + VFIO_DEVICE_STATE_RESUMING)) + +#define VFIO_DEVICE_STATE_SET_ERROR(state) \ + ((state & ~VFIO_DEVICE_STATE_MASK) | VFIO_DEVICE_SATE_SAVING | \ + VFIO_DEVICE_STATE_RESUMING) + + __u32 reserved; + __u64 pending_bytes; + __u64 data_offset; + __u64 data_size; +}; /* * The MSIX mappable capability informs that MSIX data of a BAR can be mmapped @@ -577,6 +819,7 @@ enum { enum { VFIO_CCW_IO_IRQ_INDEX, + VFIO_CCW_CRW_IRQ_INDEX, VFIO_CCW_NUM_IRQS }; @@ -785,6 +1028,44 @@ struct vfio_iommu_type1_info_cap_iova_range { struct vfio_iova_range iova_ranges[]; }; +/* + * The migration capability allows to report supported features for migration. + * + * The structures below define version 1 of this capability. + * + * The existence of this capability indicates that IOMMU kernel driver supports + * dirty page logging. + * + * pgsize_bitmap: Kernel driver returns bitmap of supported page sizes for dirty + * page logging. + * max_dirty_bitmap_size: Kernel driver returns maximum supported dirty bitmap + * size in bytes that can be used by user applications when getting the dirty + * bitmap. + */ +#define VFIO_IOMMU_TYPE1_INFO_CAP_MIGRATION 2 + +struct vfio_iommu_type1_info_cap_migration { + struct vfio_info_cap_header header; + __u32 flags; + __u64 pgsize_bitmap; + __u64 max_dirty_bitmap_size; /* in bytes */ +}; + +/* + * The DMA available capability allows to report the current number of + * simultaneously outstanding DMA mappings that are allowed. + * + * The structure below defines version 1 of this capability. + * + * avail: specifies the current number of outstanding DMA mappings allowed. + */ +#define VFIO_IOMMU_TYPE1_INFO_DMA_AVAIL 3 + +struct vfio_iommu_type1_info_dma_avail { + struct vfio_info_cap_header header; + __u32 avail; +}; + #define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12) /** @@ -805,6 +1086,12 @@ struct vfio_iommu_type1_dma_map { #define VFIO_IOMMU_MAP_DMA _IO(VFIO_TYPE, VFIO_BASE + 13) +struct vfio_bitmap { + __u64 pgsize; /* page size for bitmap in bytes */ + __u64 size; /* in bytes */ + __u64 *data; /* one bit per page */ +}; + /** * VFIO_IOMMU_UNMAP_DMA - _IOWR(VFIO_TYPE, VFIO_BASE + 14, * struct vfio_dma_unmap) @@ -814,12 +1101,23 @@ struct vfio_iommu_type1_dma_map { * field. No guarantee is made to the user that arbitrary unmaps of iova * or size different from those used in the original mapping call will * succeed. + * VFIO_DMA_UNMAP_FLAG_GET_DIRTY_BITMAP should be set to get the dirty bitmap + * before unmapping IO virtual addresses. When this flag is set, the user must + * provide a struct vfio_bitmap in data[]. User must provide zero-allocated + * memory via vfio_bitmap.data and its size in the vfio_bitmap.size field. + * A bit in the bitmap represents one page, of user provided page size in + * vfio_bitmap.pgsize field, consecutively starting from iova offset. Bit set + * indicates that the page at that offset from iova is dirty. A Bitmap of the + * pages in the range of unmapped size is returned in the user-provided + * vfio_bitmap.data. */ struct vfio_iommu_type1_dma_unmap { __u32 argsz; __u32 flags; +#define VFIO_DMA_UNMAP_FLAG_GET_DIRTY_BITMAP (1 << 0) __u64 iova; /* IO virtual address */ __u64 size; /* Size of mapping (bytes) */ + __u8 data[]; }; #define VFIO_IOMMU_UNMAP_DMA _IO(VFIO_TYPE, VFIO_BASE + 14) @@ -831,6 +1129,57 @@ struct vfio_iommu_type1_dma_unmap { #define VFIO_IOMMU_ENABLE _IO(VFIO_TYPE, VFIO_BASE + 15) #define VFIO_IOMMU_DISABLE _IO(VFIO_TYPE, VFIO_BASE + 16) +/** + * VFIO_IOMMU_DIRTY_PAGES - _IOWR(VFIO_TYPE, VFIO_BASE + 17, + * struct vfio_iommu_type1_dirty_bitmap) + * IOCTL is used for dirty pages logging. + * Caller should set flag depending on which operation to perform, details as + * below: + * + * Calling the IOCTL with VFIO_IOMMU_DIRTY_PAGES_FLAG_START flag set, instructs + * the IOMMU driver to log pages that are dirtied or potentially dirtied by + * the device; designed to be used when a migration is in progress. Dirty pages + * are logged until logging is disabled by user application by calling the IOCTL + * with VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP flag. + * + * Calling the IOCTL with VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP flag set, instructs + * the IOMMU driver to stop logging dirtied pages. + * + * Calling the IOCTL with VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP flag set + * returns the dirty pages bitmap for IOMMU container for a given IOVA range. + * The user must specify the IOVA range and the pgsize through the structure + * vfio_iommu_type1_dirty_bitmap_get in the data[] portion. This interface + * supports getting a bitmap of the smallest supported pgsize only and can be + * modified in future to get a bitmap of any specified supported pgsize. The + * user must provide a zeroed memory area for the bitmap memory and specify its + * size in bitmap.size. One bit is used to represent one page consecutively + * starting from iova offset. The user should provide page size in bitmap.pgsize + * field. A bit set in the bitmap indicates that the page at that offset from + * iova is dirty. The caller must set argsz to a value including the size of + * structure vfio_iommu_type1_dirty_bitmap_get, but excluding the size of the + * actual bitmap. If dirty pages logging is not enabled, an error will be + * returned. + * + * Only one of the flags _START, _STOP and _GET may be specified at a time. + * + */ +struct vfio_iommu_type1_dirty_bitmap { + __u32 argsz; + __u32 flags; +#define VFIO_IOMMU_DIRTY_PAGES_FLAG_START (1 << 0) +#define VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP (1 << 1) +#define VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP (1 << 2) + __u8 data[]; +}; + +struct vfio_iommu_type1_dirty_bitmap_get { + __u64 iova; /* IO virtual address */ + __u64 size; /* Size of iova range */ + struct vfio_bitmap bitmap; +}; + +#define VFIO_IOMMU_DIRTY_PAGES _IO(VFIO_TYPE, VFIO_BASE + 17) + /* -------- Additional API for SPAPR TCE (Server POWERPC) IOMMU -------- */ /* diff --git a/linux-headers/linux/vfio_ccw.h b/linux-headers/linux/vfio_ccw.h index fcc3e69ef526444601cb22d1765a9ae936690485..516496f1d482674a4a5f66133cb79f82ed7fa0c7 100644 --- a/linux-headers/linux/vfio_ccw.h +++ b/linux-headers/linux/vfio_ccw.h @@ -34,4 +34,23 @@ struct ccw_cmd_region { __u32 ret_code; } __attribute__((packed)); +/* + * Used for processing commands that read the subchannel-information block + * Reading this region triggers a stsch() to hardware + * Note: this is controlled by a capability + */ +struct ccw_schib_region { +#define SCHIB_AREA_SIZE 52 + __u8 schib_area[SCHIB_AREA_SIZE]; +} __attribute__((packed)); + +/* + * Used for returning a Channel Report Word to userspace. + * Note: this is controlled by a capability + */ +struct ccw_crw_region { + __u32 crw; + __u32 pad; +} __attribute__((packed)); + #endif diff --git a/linux-headers/linux/vfio_zdev.h b/linux-headers/linux/vfio_zdev.h new file mode 100644 index 0000000000000000000000000000000000000000..b4309397b6b273bb66e80cc53da769625cec939a --- /dev/null +++ b/linux-headers/linux/vfio_zdev.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * VFIO Region definitions for ZPCI devices + * + * Copyright IBM Corp. 2020 + * + * Author(s): Pierre Morel + * Matthew Rosato + */ + +#ifndef _VFIO_ZDEV_H_ +#define _VFIO_ZDEV_H_ + +#include +#include + +/** + * VFIO_DEVICE_INFO_CAP_ZPCI_BASE - Base PCI Function information + * + * This capability provides a set of descriptive information about the + * associated PCI function. + */ +struct vfio_device_info_cap_zpci_base { + struct vfio_info_cap_header header; + __u64 start_dma; /* Start of available DMA addresses */ + __u64 end_dma; /* End of available DMA addresses */ + __u16 pchid; /* Physical Channel ID */ + __u16 vfn; /* Virtual function number */ + __u16 fmb_length; /* Measurement Block Length (in bytes) */ + __u8 pft; /* PCI Function Type */ + __u8 gid; /* PCI function group ID */ +}; + +/** + * VFIO_DEVICE_INFO_CAP_ZPCI_GROUP - Base PCI Function Group information + * + * This capability provides a set of descriptive information about the group of + * PCI functions that the associated device belongs to. + */ +struct vfio_device_info_cap_zpci_group { + struct vfio_info_cap_header header; + __u64 dasm; /* DMA Address space mask */ + __u64 msi_addr; /* MSI address */ + __u64 flags; +#define VFIO_DEVICE_INFO_ZPCI_FLAG_REFRESH 1 /* Program-specified TLB refresh */ + __u16 mui; /* Measurement Block Update Interval */ + __u16 noi; /* Maximum number of MSIs */ + __u16 maxstbl; /* Maximum Store Block Length */ + __u8 version; /* Supported PCI Version */ +}; + +/** + * VFIO_DEVICE_INFO_CAP_ZPCI_UTIL - Utility String + * + * This capability provides the utility string for the associated device, which + * is a device identifier string made up of EBCDID characters. 'size' specifies + * the length of 'util_str'. + */ +struct vfio_device_info_cap_zpci_util { + struct vfio_info_cap_header header; + __u32 size; + __u8 util_str[]; +}; + +/** + * VFIO_DEVICE_INFO_CAP_ZPCI_PFIP - PCI Function Path + * + * This capability provides the PCI function path string, which is an identifier + * that describes the internal hardware path of the device. 'size' specifies + * the length of 'pfip'. + */ +struct vfio_device_info_cap_zpci_pfip { + struct vfio_info_cap_header header; + __u32 size; + __u8 pfip[]; +}; + +#endif diff --git a/linux-headers/linux/vhost.h b/linux-headers/linux/vhost.h index 9fe72e4b1373165d7a7aeff6141082dd0e8269e6..75232185324abb8bf16521b525ed007306ab582f 100644 --- a/linux-headers/linux/vhost.h +++ b/linux-headers/linux/vhost.h @@ -15,6 +15,8 @@ #include #include +#define VHOST_FILE_UNBIND -1 + /* ioctls */ #define VHOST_VIRTIO 0xAF @@ -89,6 +91,8 @@ /* Use message type V2 */ #define VHOST_BACKEND_F_IOTLB_MSG_V2 0x1 +/* IOTLB can accept batching hints */ +#define VHOST_BACKEND_F_IOTLB_BATCH 0x2 #define VHOST_SET_BACKEND_FEATURES _IOW(VHOST_VIRTIO, 0x25, __u64) #define VHOST_GET_BACKEND_FEATURES _IOR(VHOST_VIRTIO, 0x26, __u64) @@ -140,4 +144,6 @@ /* Get the max ring size. */ #define VHOST_VDPA_GET_VRING_NUM _IOR(VHOST_VIRTIO, 0x76, __u16) +/* Set event fd for config interrupt*/ +#define VHOST_VDPA_SET_CONFIG_CALL _IOW(VHOST_VIRTIO, 0x77, int) #endif diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs deleted file mode 100644 index 1940910a7321c5a44d29c2602f9eb64db4da2c1b..0000000000000000000000000000000000000000 --- a/linux-user/Makefile.objs +++ /dev/null @@ -1,25 +0,0 @@ -obj-y = main.o syscall.o strace.o mmap.o signal.o \ - elfload.o linuxload.o uaccess.o uname.o \ - safe-syscall.o $(TARGET_ABI_DIR)/signal.o \ - $(TARGET_ABI_DIR)/cpu_loop.o exit.o fd-trans.o - -obj-$(TARGET_HAS_BFLT) += flatload.o -obj-$(TARGET_I386) += vm86.o -obj-$(TARGET_AARCH64) += arm/semihost.o - -obj-$(TARGET_ALPHA) += alpha/ -obj-$(TARGET_ARM) += arm/ -obj-$(TARGET_HPPA) += hppa/ -obj-$(TARGET_I386) += i386/ -obj-$(TARGET_M68K) += m68k/ -obj-$(TARGET_MICROBLAZE) += microblaze/ -obj-$(TARGET_MIPS) += mips/ -obj-$(TARGET_MIPS64) += mips64/ -obj-$(TARGET_PPC) += ppc/ -obj-$(TARGET_PPC64) += ppc/ -obj-$(TARGET_S390X) += s390x/ -obj-$(TARGET_SH4) += sh4/ -obj-$(TARGET_SPARC) += sparc/ -obj-$(TARGET_SPARC64) += $(TARGET_ABI_DIR)/ -obj-$(TARGET_X86_64) += x86_64/ -obj-$(TARGET_XTENSA) += xtensa/ diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c index cd521ee42d1784bdac6469b2fc88a77498287feb..b591790c22ed76e4a92712872744f6c064482bf4 100644 --- a/linux-user/aarch64/signal.c +++ b/linux-user/aarch64/signal.c @@ -78,7 +78,7 @@ struct target_sve_context { struct target_aarch64_ctx head; uint16_t vl; uint16_t reserved[3]; - /* The actual SVE data immediately follows. It is layed out + /* The actual SVE data immediately follows. It is laid out * according to TARGET_SVE_SIG_{Z,P}REG_OFFSET, based off of * the original struct pointer. */ @@ -506,10 +506,16 @@ static void target_setup_frame(int usig, struct target_sigaction *ka, + offsetof(struct target_rt_frame_record, tramp); } env->xregs[0] = usig; - env->xregs[31] = frame_addr; env->xregs[29] = frame_addr + fr_ofs; - env->pc = ka->_sa_handler; env->xregs[30] = return_addr; + env->xregs[31] = frame_addr; + env->pc = ka->_sa_handler; + + /* Invoke the signal handler as if by indirect call. */ + if (cpu_isar_feature(aa64_bti, env_archcpu(env))) { + env->btype = 2; + } + if (info) { tswap_siginfo(&frame->info, info); env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info); diff --git a/linux-user/aarch64/syscall_nr.h b/linux-user/aarch64/syscall_nr.h index 85de000b2490abc609310bef817a07dda7a6bbed..6fd5b331e780af97e5a72d5c8bb0a2ec5c322174 100644 --- a/linux-user/aarch64/syscall_nr.h +++ b/linux-user/aarch64/syscall_nr.h @@ -298,7 +298,10 @@ #define TARGET_NR_fspick 433 #define TARGET_NR_pidfd_open 434 #define TARGET_NR_clone3 435 -#define TARGET_NR_syscalls 436 +#define TARGET_NR_close_range 436 +#define TARGET_NR_openat2 437 +#define TARGET_NR_pidfd_getfd 438 +#define TARGET_NR_faccessat2 439 +#define TARGET_NR_syscalls 440 #endif /* LINUX_USER_AARCH64_SYSCALL_NR_H */ - diff --git a/linux-user/aarch64/target_cpu.h b/linux-user/aarch64/target_cpu.h index 6cc02e7dcdfbce3f419e1928c5155071e1349fc0..97a477bd3e916fe186f91a4adad4fc0182f55827 100644 --- a/linux-user/aarch64/target_cpu.h +++ b/linux-user/aarch64/target_cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/aarch64/target_structs.h b/linux-user/aarch64/target_structs.h index a4998a749169401ecaebf4574057a8b1c068a56f..7c748344cabc6f6d51bc8ed51cf6bacd88368071 100644 --- a/linux-user/aarch64/target_structs.h +++ b/linux-user/aarch64/target_structs.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h index 995e475c73f88fffb1bcb214fd7616a87a1589c0..3194e6b0093c91ce09431228570395e38cc8787f 100644 --- a/linux-user/aarch64/target_syscall.h +++ b/linux-user/aarch64/target_syscall.h @@ -16,8 +16,9 @@ struct target_pt_regs { #define UNAME_MINIMUM_RELEASE "3.8.0" #define TARGET_CLONE_BACKWARDS #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 #define TARGET_PR_SVE_SET_VL 50 #define TARGET_PR_SVE_GET_VL 51 diff --git a/linux-user/aarch64/termbits.h b/linux-user/aarch64/termbits.h index 0ab448d090e764dab379072f94aa08ccbe0e7aa4..b1d4f4fedbcb9ab2ca1184280eb4a9e5b8a9d735 100644 --- a/linux-user/aarch64/termbits.h +++ b/linux-user/aarch64/termbits.h @@ -1,227 +1 @@ -/* from asm/termbits.h */ -/* NOTE: exactly the same as i386 */ - -#ifndef LINUX_USER_AARCH64_TERMBITS_H -#define LINUX_USER_AARCH64_TERMBITS_H - -#define TARGET_NCCS 19 - -struct target_termios { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ -}; - -/* c_iflag bits */ -#define TARGET_IGNBRK 0000001 -#define TARGET_BRKINT 0000002 -#define TARGET_IGNPAR 0000004 -#define TARGET_PARMRK 0000010 -#define TARGET_INPCK 0000020 -#define TARGET_ISTRIP 0000040 -#define TARGET_INLCR 0000100 -#define TARGET_IGNCR 0000200 -#define TARGET_ICRNL 0000400 -#define TARGET_IUCLC 0001000 -#define TARGET_IXON 0002000 -#define TARGET_IXANY 0004000 -#define TARGET_IXOFF 0010000 -#define TARGET_IMAXBEL 0020000 -#define TARGET_IUTF8 0040000 - -/* c_oflag bits */ -#define TARGET_OPOST 0000001 -#define TARGET_OLCUC 0000002 -#define TARGET_ONLCR 0000004 -#define TARGET_OCRNL 0000010 -#define TARGET_ONOCR 0000020 -#define TARGET_ONLRET 0000040 -#define TARGET_OFILL 0000100 -#define TARGET_OFDEL 0000200 -#define TARGET_NLDLY 0000400 -#define TARGET_NL0 0000000 -#define TARGET_NL1 0000400 -#define TARGET_CRDLY 0003000 -#define TARGET_CR0 0000000 -#define TARGET_CR1 0001000 -#define TARGET_CR2 0002000 -#define TARGET_CR3 0003000 -#define TARGET_TABDLY 0014000 -#define TARGET_TAB0 0000000 -#define TARGET_TAB1 0004000 -#define TARGET_TAB2 0010000 -#define TARGET_TAB3 0014000 -#define TARGET_XTABS 0014000 -#define TARGET_BSDLY 0020000 -#define TARGET_BS0 0000000 -#define TARGET_BS1 0020000 -#define TARGET_VTDLY 0040000 -#define TARGET_VT0 0000000 -#define TARGET_VT1 0040000 -#define TARGET_FFDLY 0100000 -#define TARGET_FF0 0000000 -#define TARGET_FF1 0100000 - -/* c_cflag bit meaning */ -#define TARGET_CBAUD 0010017 -#define TARGET_B0 0000000 /* hang up */ -#define TARGET_B50 0000001 -#define TARGET_B75 0000002 -#define TARGET_B110 0000003 -#define TARGET_B134 0000004 -#define TARGET_B150 0000005 -#define TARGET_B200 0000006 -#define TARGET_B300 0000007 -#define TARGET_B600 0000010 -#define TARGET_B1200 0000011 -#define TARGET_B1800 0000012 -#define TARGET_B2400 0000013 -#define TARGET_B4800 0000014 -#define TARGET_B9600 0000015 -#define TARGET_B19200 0000016 -#define TARGET_B38400 0000017 -#define TARGET_EXTA B19200 -#define TARGET_EXTB B38400 -#define TARGET_CSIZE 0000060 -#define TARGET_CS5 0000000 -#define TARGET_CS6 0000020 -#define TARGET_CS7 0000040 -#define TARGET_CS8 0000060 -#define TARGET_CSTOPB 0000100 -#define TARGET_CREAD 0000200 -#define TARGET_PARENB 0000400 -#define TARGET_PARODD 0001000 -#define TARGET_HUPCL 0002000 -#define TARGET_CLOCAL 0004000 -#define TARGET_CBAUDEX 0010000 -#define TARGET_B57600 0010001 -#define TARGET_B115200 0010002 -#define TARGET_B230400 0010003 -#define TARGET_B460800 0010004 -#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */ -#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ -#define TARGET_CRTSCTS 020000000000 /* flow control */ - -/* c_lflag bits */ -#define TARGET_ISIG 0000001 -#define TARGET_ICANON 0000002 -#define TARGET_XCASE 0000004 -#define TARGET_ECHO 0000010 -#define TARGET_ECHOE 0000020 -#define TARGET_ECHOK 0000040 -#define TARGET_ECHONL 0000100 -#define TARGET_NOFLSH 0000200 -#define TARGET_TOSTOP 0000400 -#define TARGET_ECHOCTL 0001000 -#define TARGET_ECHOPRT 0002000 -#define TARGET_ECHOKE 0004000 -#define TARGET_FLUSHO 0010000 -#define TARGET_PENDIN 0040000 -#define TARGET_IEXTEN 0100000 - -/* c_cc character offsets */ -#define TARGET_VINTR 0 -#define TARGET_VQUIT 1 -#define TARGET_VERASE 2 -#define TARGET_VKILL 3 -#define TARGET_VEOF 4 -#define TARGET_VTIME 5 -#define TARGET_VMIN 6 -#define TARGET_VSWTC 7 -#define TARGET_VSTART 8 -#define TARGET_VSTOP 9 -#define TARGET_VSUSP 10 -#define TARGET_VEOL 11 -#define TARGET_VREPRINT 12 -#define TARGET_VDISCARD 13 -#define TARGET_VWERASE 14 -#define TARGET_VLNEXT 15 -#define TARGET_VEOL2 16 - -/* ioctls */ - -#define TARGET_TCGETS 0x5401 -#define TARGET_TCSETS 0x5402 -#define TARGET_TCSETSW 0x5403 -#define TARGET_TCSETSF 0x5404 -#define TARGET_TCGETA 0x5405 -#define TARGET_TCSETA 0x5406 -#define TARGET_TCSETAW 0x5407 -#define TARGET_TCSETAF 0x5408 -#define TARGET_TCSBRK 0x5409 -#define TARGET_TCXONC 0x540A -#define TARGET_TCFLSH 0x540B - -#define TARGET_TIOCEXCL 0x540C -#define TARGET_TIOCNXCL 0x540D -#define TARGET_TIOCSCTTY 0x540E -#define TARGET_TIOCGPGRP 0x540F -#define TARGET_TIOCSPGRP 0x5410 -#define TARGET_TIOCOUTQ 0x5411 -#define TARGET_TIOCSTI 0x5412 -#define TARGET_TIOCGWINSZ 0x5413 -#define TARGET_TIOCSWINSZ 0x5414 -#define TARGET_TIOCMGET 0x5415 -#define TARGET_TIOCMBIS 0x5416 -#define TARGET_TIOCMBIC 0x5417 -#define TARGET_TIOCMSET 0x5418 -#define TARGET_TIOCGSOFTCAR 0x5419 -#define TARGET_TIOCSSOFTCAR 0x541A -#define TARGET_FIONREAD 0x541B -#define TARGET_TIOCINQ TARGET_FIONREAD -#define TARGET_TIOCLINUX 0x541C -#define TARGET_TIOCCONS 0x541D -#define TARGET_TIOCGSERIAL 0x541E -#define TARGET_TIOCSSERIAL 0x541F -#define TARGET_TIOCPKT 0x5420 -#define TARGET_FIONBIO 0x5421 -#define TARGET_TIOCNOTTY 0x5422 -#define TARGET_TIOCSETD 0x5423 -#define TARGET_TIOCGETD 0x5424 -#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ -#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */ -#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ -#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ -#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ -#define TARGET_TIOCGPTN TARGET_IOR('T', 0x30, unsigned int) - /* Get Pty Number (of pty-mux device) */ -#define TARGET_TIOCSPTLCK TARGET_IOW('T', 0x31, int) - /* Lock/unlock Pty */ -#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) - /* Safely open the slave */ - -#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */ -#define TARGET_FIOCLEX 0x5451 -#define TARGET_FIOASYNC 0x5452 -#define TARGET_TIOCSERCONFIG 0x5453 -#define TARGET_TIOCSERGWILD 0x5454 -#define TARGET_TIOCSERSWILD 0x5455 -#define TARGET_TIOCGLCKTRMIOS 0x5456 -#define TARGET_TIOCSLCKTRMIOS 0x5457 -#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ - -#define TARGET_TIOCMIWAIT 0x545C - /* wait for a change on serial input line(s) */ -#define TARGET_TIOCGICOUNT 0x545D - /* read serial port inline interrupt counts */ -#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ -#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ - -/* Used for packet mode */ -#define TARGET_TIOCPKT_DATA 0 -#define TARGET_TIOCPKT_FLUSHREAD 1 -#define TARGET_TIOCPKT_FLUSHWRITE 2 -#define TARGET_TIOCPKT_STOP 4 -#define TARGET_TIOCPKT_START 8 -#define TARGET_TIOCPKT_NOSTOP 16 -#define TARGET_TIOCPKT_DOSTOP 32 - -#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - -#endif +#include "../generic/termbits.h" diff --git a/linux-user/alpha/Makefile.objs b/linux-user/alpha/Makefile.objs deleted file mode 100644 index d6397a70abb2bfa526f9ad55827d674ae827a13b..0000000000000000000000000000000000000000 --- a/linux-user/alpha/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -generated-files-y += linux-user/alpha/syscall_nr.h - -syshdr := $(SRC_PATH)/linux-user/alpha/syscallhdr.sh -%/syscall_nr.h: $(SRC_PATH)/linux-user/alpha/syscall.tbl $(syshdr) - $(call quiet-command, sh $(syshdr) $< $@ $(TARGET_SYSTBL_ABI),"GEN","$@") diff --git a/linux-user/alpha/meson.build b/linux-user/alpha/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..a3cd22d2c4c553373430f62ab9e292facf62a43f --- /dev/null +++ b/linux-user/alpha/meson.build @@ -0,0 +1,5 @@ +syscall_nr_generators += { + 'alpha': generator(sh, + arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ], + output: '@BASENAME@_nr.h') +} diff --git a/linux-user/alpha/syscall.tbl b/linux-user/alpha/syscall.tbl index 36d42da7466aae5ccd8a8a70d0e70014ae63c2df..ec8bed9e7b75b6a9b22fd75a36d614c2712982cc 100644 --- a/linux-user/alpha/syscall.tbl +++ b/linux-user/alpha/syscall.tbl @@ -249,7 +249,7 @@ 316 common mlockall sys_mlockall 317 common munlockall sys_munlockall 318 common sysinfo sys_sysinfo -319 common _sysctl sys_sysctl +319 common _sysctl sys_ni_syscall # 320 was sys_idle 321 common oldumount sys_oldumount 322 common swapon sys_swapon @@ -475,5 +475,7 @@ 543 common fspick sys_fspick 544 common pidfd_open sys_pidfd_open # 545 reserved for clone3 +546 common close_range sys_close_range 547 common openat2 sys_openat2 548 common pidfd_getfd sys_pidfd_getfd +549 common faccessat2 sys_faccessat2 diff --git a/linux-user/alpha/target_cpu.h b/linux-user/alpha/target_cpu.h index ad408ab5cc8ed56048bb2f860f3838909cf7c35e..dc2dd651948e57af151a0307c124ec7d2b17d6b2 100644 --- a/linux-user/alpha/target_cpu.h +++ b/linux-user/alpha/target_cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/alpha/target_signal.h b/linux-user/alpha/target_signal.h index cd63d59fdec1e46b549deff4e5a2b8a4c9d4cfe8..b83797281c323278d3fcc2d5a88998bb2cc74894 100644 --- a/linux-user/alpha/target_signal.h +++ b/linux-user/alpha/target_signal.h @@ -42,8 +42,7 @@ typedef struct target_sigaltstack { abi_ulong ss_sp; - int32_t ss_flags; - int32_t dummy; + abi_int ss_flags; abi_ulong ss_size; } target_stack_t; diff --git a/linux-user/alpha/target_structs.h b/linux-user/alpha/target_structs.h index db2bfe28766a7bd658259e8a9aca44622634bc7d..d91cebdea8e8c2d3880d2badc1942343c8c7daa9 100644 --- a/linux-user/alpha/target_structs.h +++ b/linux-user/alpha/target_structs.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/alpha/target_syscall.h b/linux-user/alpha/target_syscall.h index 3426cc5b4e4f167699c2e028bb45dbba09d995b9..fd389422e31e762a316d0557097eb2f62ff7c601 100644 --- a/linux-user/alpha/target_syscall.h +++ b/linux-user/alpha/target_syscall.h @@ -258,7 +258,8 @@ struct target_pt_regs { #define TARGET_UAC_NOFIX 2 #define TARGET_UAC_SIGBUS 4 #define TARGET_MINSIGSTKSZ 4096 -#define TARGET_MLOCKALL_MCL_CURRENT 0x2000 -#define TARGET_MLOCKALL_MCL_FUTURE 0x4000 +#define TARGET_MCL_CURRENT 0x2000 +#define TARGET_MCL_FUTURE 0x4000 +#define TARGET_MCL_ONFAULT 0x8000 #endif /* ALPHA_TARGET_SYSCALL_H */ diff --git a/linux-user/alpha/termbits.h b/linux-user/alpha/termbits.h index a71425174a975c70ee8284b15a11d8aa539c9305..4a4b1e96f21c7f568f0eae3d9429f7042a52d77f 100644 --- a/linux-user/alpha/termbits.h +++ b/linux-user/alpha/termbits.h @@ -159,6 +159,7 @@ struct target_termios { #define TARGET_FLUSHO 0x00800000 #define TARGET_PENDIN 0x20000000 #define TARGET_IEXTEN 0x00000400 +#define TARGET_EXTPROC 0x10000000 #define TARGET_FIOCLEX TARGET_IO('f', 1) #define TARGET_FIONCLEX TARGET_IO('f', 2) diff --git a/linux-user/arm/Makefile.objs b/linux-user/arm/Makefile.objs deleted file mode 100644 index c7eb94dcba8ef86a4bd7a1a1521db6e31e27fe95..0000000000000000000000000000000000000000 --- a/linux-user/arm/Makefile.objs +++ /dev/null @@ -1,8 +0,0 @@ -obj-$(TARGET_ARM) += nwfpe/ -obj-$(TARGET_ARM) += semihost.o - -generated-files-y += linux-user/arm/syscall_nr.h - -syshdr := $(SRC_PATH)/linux-user/arm/syscallhdr.sh -%/syscall_nr.h: $(SRC_PATH)/linux-user/arm/syscall.tbl $(syshdr) - $(call quiet-command, sh $(syshdr) $< $@ $(TARGET_SYSTBL_ABI),"GEN","$@") diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c index 13629ee1f6a1ad4d6dfa8d1ae3d00c5f9a3ba33d..3d272b56ef0cda56e41372f603ef90bdc8296f4e 100644 --- a/linux-user/arm/cpu_loop.c +++ b/linux-user/arm/cpu_loop.c @@ -205,6 +205,24 @@ do_kernel_trap(CPUARMState *env) return 0; } +static bool insn_is_linux_bkpt(uint32_t opcode, bool is_thumb) +{ + /* + * Return true if this insn is one of the three magic UDF insns + * which the kernel treats as breakpoint insns. + */ + if (!is_thumb) { + return (opcode & 0x0fffffff) == 0x07f001f0; + } else { + /* + * Note that we get the two halves of the 32-bit T32 insn + * in the opposite order to the value the kernel uses in + * its undef_hook struct. + */ + return ((opcode & 0xffff) == 0xde01) || (opcode == 0xa000f7f0); + } +} + void cpu_loop(CPUARMState *env) { CPUState *cs = env_cpu(env); @@ -234,6 +252,16 @@ void cpu_loop(CPUARMState *env) /* FIXME - what to do if get_user() fails? */ get_user_code_u32(opcode, env->regs[15], env); + /* + * The Linux kernel treats some UDF patterns specially + * to use as breakpoints (instead of the architectural + * bkpt insn). These should trigger a SIGTRAP rather + * than SIGILL. + */ + if (insn_is_linux_bkpt(opcode, env->thumb)) { + goto excp_debug; + } + rc = EmulateAll(opcode, &ts->fpa, env); if (rc == 0) { /* illegal instruction */ info.si_signo = TARGET_SIGILL; diff --git a/linux-user/arm/meson.build b/linux-user/arm/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..432984b58e01bebbfaf65e6a0a61840bdd963b59 --- /dev/null +++ b/linux-user/arm/meson.build @@ -0,0 +1,10 @@ +linux_user_ss.add(when: 'TARGET_AARCH64', if_true: files('semihost.c')) +linux_user_ss.add(when: 'TARGET_ARM', if_true: files('semihost.c')) + +subdir('nwfpe') + +syscall_nr_generators += { + 'arm': generator(sh, + arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ], + output: '@BASENAME@_nr.h') +} diff --git a/linux-user/arm/nwfpe/Makefile.objs b/linux-user/arm/nwfpe/Makefile.objs deleted file mode 100644 index 51b0c32c2a93e54e4767bf618e2816c868a96f2b..0000000000000000000000000000000000000000 --- a/linux-user/arm/nwfpe/Makefile.objs +++ /dev/null @@ -1,2 +0,0 @@ -obj-y = fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o fpopcode.o -obj-y += single_cpdo.o double_cpdo.o extended_cpdo.o diff --git a/linux-user/arm/nwfpe/meson.build b/linux-user/arm/nwfpe/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..1c27e55f2ada6e01bd61ba86e34fdb7c52ba1954 --- /dev/null +++ b/linux-user/arm/nwfpe/meson.build @@ -0,0 +1,10 @@ +linux_user_ss.add(when: 'TARGET_ARM', if_true: files( + 'double_cpdo.c', + 'extended_cpdo.c', + 'fpa11.c', + 'fpa11_cpdo.c', + 'fpa11_cpdt.c', + 'fpa11_cprt.c', + 'fpopcode.c', + 'single_cpdo.c', +)) diff --git a/linux-user/arm/syscall.tbl b/linux-user/arm/syscall.tbl index 4d1cf74a2caac645c4b217134a066a12bcbe7056..171077cbf419b419ab7d906a23c7ed120a129ccb 100644 --- a/linux-user/arm/syscall.tbl +++ b/linux-user/arm/syscall.tbl @@ -162,7 +162,7 @@ 146 common writev sys_writev 147 common getsid sys_getsid 148 common fdatasync sys_fdatasync -149 common _sysctl sys_sysctl +149 common _sysctl sys_ni_syscall 150 common mlock sys_mlock 151 common munlock sys_munlock 152 common mlockall sys_mlockall @@ -449,5 +449,7 @@ 433 common fspick sys_fspick 434 common pidfd_open sys_pidfd_open 435 common clone3 sys_clone3 +436 common close_range sys_close_range 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd +439 common faccessat2 sys_faccessat2 diff --git a/linux-user/arm/target_cpu.h b/linux-user/arm/target_cpu.h index 2747211b24ab597f5caa274f6f3e98f1a181b8c9..709d19bc9e61fe738265cc33f7ea96846b48d713 100644 --- a/linux-user/arm/target_cpu.h +++ b/linux-user/arm/target_cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/arm/target_signal.h b/linux-user/arm/target_signal.h index ea123c40f38dab7f85d762d0c88b363bc6f1c6ca..0998dd6dfa75de03787fb67f5ddfd79dd29e3ae1 100644 --- a/linux-user/arm/target_signal.h +++ b/linux-user/arm/target_signal.h @@ -4,9 +4,9 @@ /* this struct defines a stack used during syscall handling */ typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_long ss_flags; - abi_ulong ss_size; + abi_ulong ss_sp; + abi_int ss_flags; + abi_ulong ss_size; } target_stack_t; diff --git a/linux-user/arm/target_structs.h b/linux-user/arm/target_structs.h index 9a3dbce03dd6b29cce09793a1af834ca4417fb9e..339b070bf1a5452d402e9eaabe92817603e4026a 100644 --- a/linux-user/arm/target_structs.h +++ b/linux-user/arm/target_structs.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/arm/target_syscall.h b/linux-user/arm/target_syscall.h index f85cbdaf56ffe0b70ce3a170b66b3ec3034e2baa..e870ed7a5468a894338724453560b497f318a581 100644 --- a/linux-user/arm/target_syscall.h +++ b/linux-user/arm/target_syscall.h @@ -28,8 +28,10 @@ struct target_pt_regs { #define TARGET_CLONE_BACKWARDS #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 + #define TARGET_WANT_OLD_SYS_SELECT #define TARGET_FORCE_SHMLBA diff --git a/linux-user/arm/termbits.h b/linux-user/arm/termbits.h index e555cff1058ccabbaf0184661b505baaaa9f6f10..b1d4f4fedbcb9ab2ca1184280eb4a9e5b8a9d735 100644 --- a/linux-user/arm/termbits.h +++ b/linux-user/arm/termbits.h @@ -1,222 +1 @@ -/* from asm/termbits.h */ -/* NOTE: exactly the same as i386 */ - -#ifndef LINUX_USER_ARM_TERMBITS_H -#define LINUX_USER_ARM_TERMBITS_H - -#define TARGET_NCCS 19 - -struct target_termios { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ -}; - -/* c_iflag bits */ -#define TARGET_IGNBRK 0000001 -#define TARGET_BRKINT 0000002 -#define TARGET_IGNPAR 0000004 -#define TARGET_PARMRK 0000010 -#define TARGET_INPCK 0000020 -#define TARGET_ISTRIP 0000040 -#define TARGET_INLCR 0000100 -#define TARGET_IGNCR 0000200 -#define TARGET_ICRNL 0000400 -#define TARGET_IUCLC 0001000 -#define TARGET_IXON 0002000 -#define TARGET_IXANY 0004000 -#define TARGET_IXOFF 0010000 -#define TARGET_IMAXBEL 0020000 -#define TARGET_IUTF8 0040000 - -/* c_oflag bits */ -#define TARGET_OPOST 0000001 -#define TARGET_OLCUC 0000002 -#define TARGET_ONLCR 0000004 -#define TARGET_OCRNL 0000010 -#define TARGET_ONOCR 0000020 -#define TARGET_ONLRET 0000040 -#define TARGET_OFILL 0000100 -#define TARGET_OFDEL 0000200 -#define TARGET_NLDLY 0000400 -#define TARGET_NL0 0000000 -#define TARGET_NL1 0000400 -#define TARGET_CRDLY 0003000 -#define TARGET_CR0 0000000 -#define TARGET_CR1 0001000 -#define TARGET_CR2 0002000 -#define TARGET_CR3 0003000 -#define TARGET_TABDLY 0014000 -#define TARGET_TAB0 0000000 -#define TARGET_TAB1 0004000 -#define TARGET_TAB2 0010000 -#define TARGET_TAB3 0014000 -#define TARGET_XTABS 0014000 -#define TARGET_BSDLY 0020000 -#define TARGET_BS0 0000000 -#define TARGET_BS1 0020000 -#define TARGET_VTDLY 0040000 -#define TARGET_VT0 0000000 -#define TARGET_VT1 0040000 -#define TARGET_FFDLY 0100000 -#define TARGET_FF0 0000000 -#define TARGET_FF1 0100000 - -/* c_cflag bit meaning */ -#define TARGET_CBAUD 0010017 -#define TARGET_B0 0000000 /* hang up */ -#define TARGET_B50 0000001 -#define TARGET_B75 0000002 -#define TARGET_B110 0000003 -#define TARGET_B134 0000004 -#define TARGET_B150 0000005 -#define TARGET_B200 0000006 -#define TARGET_B300 0000007 -#define TARGET_B600 0000010 -#define TARGET_B1200 0000011 -#define TARGET_B1800 0000012 -#define TARGET_B2400 0000013 -#define TARGET_B4800 0000014 -#define TARGET_B9600 0000015 -#define TARGET_B19200 0000016 -#define TARGET_B38400 0000017 -#define TARGET_EXTA B19200 -#define TARGET_EXTB B38400 -#define TARGET_CSIZE 0000060 -#define TARGET_CS5 0000000 -#define TARGET_CS6 0000020 -#define TARGET_CS7 0000040 -#define TARGET_CS8 0000060 -#define TARGET_CSTOPB 0000100 -#define TARGET_CREAD 0000200 -#define TARGET_PARENB 0000400 -#define TARGET_PARODD 0001000 -#define TARGET_HUPCL 0002000 -#define TARGET_CLOCAL 0004000 -#define TARGET_CBAUDEX 0010000 -#define TARGET_B57600 0010001 -#define TARGET_B115200 0010002 -#define TARGET_B230400 0010003 -#define TARGET_B460800 0010004 -#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */ -#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ -#define TARGET_CRTSCTS 020000000000 /* flow control */ - -/* c_lflag bits */ -#define TARGET_ISIG 0000001 -#define TARGET_ICANON 0000002 -#define TARGET_XCASE 0000004 -#define TARGET_ECHO 0000010 -#define TARGET_ECHOE 0000020 -#define TARGET_ECHOK 0000040 -#define TARGET_ECHONL 0000100 -#define TARGET_NOFLSH 0000200 -#define TARGET_TOSTOP 0000400 -#define TARGET_ECHOCTL 0001000 -#define TARGET_ECHOPRT 0002000 -#define TARGET_ECHOKE 0004000 -#define TARGET_FLUSHO 0010000 -#define TARGET_PENDIN 0040000 -#define TARGET_IEXTEN 0100000 - -/* c_cc character offsets */ -#define TARGET_VINTR 0 -#define TARGET_VQUIT 1 -#define TARGET_VERASE 2 -#define TARGET_VKILL 3 -#define TARGET_VEOF 4 -#define TARGET_VTIME 5 -#define TARGET_VMIN 6 -#define TARGET_VSWTC 7 -#define TARGET_VSTART 8 -#define TARGET_VSTOP 9 -#define TARGET_VSUSP 10 -#define TARGET_VEOL 11 -#define TARGET_VREPRINT 12 -#define TARGET_VDISCARD 13 -#define TARGET_VWERASE 14 -#define TARGET_VLNEXT 15 -#define TARGET_VEOL2 16 - -/* ioctls */ - -#define TARGET_TCGETS 0x5401 -#define TARGET_TCSETS 0x5402 -#define TARGET_TCSETSW 0x5403 -#define TARGET_TCSETSF 0x5404 -#define TARGET_TCGETA 0x5405 -#define TARGET_TCSETA 0x5406 -#define TARGET_TCSETAW 0x5407 -#define TARGET_TCSETAF 0x5408 -#define TARGET_TCSBRK 0x5409 -#define TARGET_TCXONC 0x540A -#define TARGET_TCFLSH 0x540B - -#define TARGET_TIOCEXCL 0x540C -#define TARGET_TIOCNXCL 0x540D -#define TARGET_TIOCSCTTY 0x540E -#define TARGET_TIOCGPGRP 0x540F -#define TARGET_TIOCSPGRP 0x5410 -#define TARGET_TIOCOUTQ 0x5411 -#define TARGET_TIOCSTI 0x5412 -#define TARGET_TIOCGWINSZ 0x5413 -#define TARGET_TIOCSWINSZ 0x5414 -#define TARGET_TIOCMGET 0x5415 -#define TARGET_TIOCMBIS 0x5416 -#define TARGET_TIOCMBIC 0x5417 -#define TARGET_TIOCMSET 0x5418 -#define TARGET_TIOCGSOFTCAR 0x5419 -#define TARGET_TIOCSSOFTCAR 0x541A -#define TARGET_FIONREAD 0x541B -#define TARGET_TIOCINQ TARGET_FIONREAD -#define TARGET_TIOCLINUX 0x541C -#define TARGET_TIOCCONS 0x541D -#define TARGET_TIOCGSERIAL 0x541E -#define TARGET_TIOCSSERIAL 0x541F -#define TARGET_TIOCPKT 0x5420 -#define TARGET_FIONBIO 0x5421 -#define TARGET_TIOCNOTTY 0x5422 -#define TARGET_TIOCSETD 0x5423 -#define TARGET_TIOCGETD 0x5424 -#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ -#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */ -#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ -#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ -#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ -#define TARGET_TIOCGPTN TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ -#define TARGET_TIOCSPTLCK TARGET_IOW('T',0x31, int) /* Lock/unlock Pty */ -#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) /* Safely open the slave */ - -#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */ -#define TARGET_FIOCLEX 0x5451 -#define TARGET_FIOASYNC 0x5452 -#define TARGET_TIOCSERCONFIG 0x5453 -#define TARGET_TIOCSERGWILD 0x5454 -#define TARGET_TIOCSERSWILD 0x5455 -#define TARGET_TIOCGLCKTRMIOS 0x5456 -#define TARGET_TIOCSLCKTRMIOS 0x5457 -#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ - -#define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ -#define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ -#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ -#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ - -/* Used for packet mode */ -#define TARGET_TIOCPKT_DATA 0 -#define TARGET_TIOCPKT_FLUSHREAD 1 -#define TARGET_TIOCPKT_FLUSHWRITE 2 -#define TARGET_TIOCPKT_STOP 4 -#define TARGET_TIOCPKT_START 8 -#define TARGET_TIOCPKT_NOSTOP 16 -#define TARGET_TIOCPKT_DOSTOP 32 - -#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - -#endif +#include "../generic/termbits.h" diff --git a/linux-user/cris/target_cpu.h b/linux-user/cris/target_cpu.h index 74ead55c8114af2c8e491309d870def4c789e0d8..7f6cade7b65058f5771ececf5d243cab46a2d3e1 100644 --- a/linux-user/cris/target_cpu.h +++ b/linux-user/cris/target_cpu.h @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/cris/target_signal.h b/linux-user/cris/target_signal.h index 1cb5548f85ea13bcf2a6310278c3490485718c10..495a1428968174184fa62d75e76d6a3ab02c3401 100644 --- a/linux-user/cris/target_signal.h +++ b/linux-user/cris/target_signal.h @@ -4,9 +4,9 @@ /* this struct defines a stack used during syscall handling */ typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_ulong ss_size; - abi_long ss_flags; + abi_ulong ss_sp; + abi_int ss_flags; + abi_ulong ss_size; } target_stack_t; diff --git a/linux-user/cris/target_structs.h b/linux-user/cris/target_structs.h index 76f965325c3f8f5194f46072272f1c1ea9fe99f8..f949d2331e6e5190b53042be149dc23b6a2393b0 100644 --- a/linux-user/cris/target_structs.h +++ b/linux-user/cris/target_structs.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/cris/target_syscall.h b/linux-user/cris/target_syscall.h index 29d69009ffe8b2c6de0b91f9c954b08ec65bbfa0..19e12814039c68cd48b9041b6bd1c63ea7797bf5 100644 --- a/linux-user/cris/target_syscall.h +++ b/linux-user/cris/target_syscall.h @@ -4,7 +4,7 @@ #define UNAME_MACHINE "cris" #define UNAME_MINIMUM_RELEASE "2.6.32" -/* pt_regs not only specifices the format in the user-struct during +/* pt_regs not only specifies the format in the user-struct during * ptrace but is also the frame format used in the kernel prologue/epilogues * themselves */ @@ -32,7 +32,7 @@ struct target_pt_regs { unsigned long spc; unsigned long ccs; unsigned long srp; - unsigned long erp; /* This is actually the debugged process' PC */ + unsigned long erp; /* This is actually the debugged process's PC */ /* For debugging purposes; saved only when needed. */ unsigned long exs; unsigned long eda; @@ -40,7 +40,8 @@ struct target_pt_regs { #define TARGET_CLONE_BACKWARDS2 #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 #endif diff --git a/linux-user/cris/termbits.h b/linux-user/cris/termbits.h index 475ee70fed370739c576037c1b83fbfd2c081208..0c8d8fc05164d7d72c177b4bbf635f6b1384c66d 100644 --- a/linux-user/cris/termbits.h +++ b/linux-user/cris/termbits.h @@ -5,13 +5,17 @@ #define TARGET_NCCS 19 +typedef unsigned char target_cc_t; /* cc_t */ +typedef unsigned int target_speed_t; /* speed_t */ +typedef unsigned int target_tcflag_t; /* tcflag_t */ + struct target_termios { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ + target_tcflag_t c_iflag; /* input mode flags */ + target_tcflag_t c_oflag; /* output mode flags */ + target_tcflag_t c_cflag; /* control mode flags */ + target_tcflag_t c_lflag; /* local mode flags */ + target_cc_t c_line; /* line discipline */ + target_cc_t c_cc[TARGET_NCCS]; /* control characters */ }; /* c_iflag bits */ @@ -29,6 +33,7 @@ struct target_termios { #define TARGET_IXANY 0004000 #define TARGET_IXOFF 0010000 #define TARGET_IMAXBEL 0020000 +#define TARGET_IUTF8 0040000 /* c_oflag bits */ #define TARGET_OPOST 0000001 @@ -118,6 +123,7 @@ struct target_termios { #define TARGET_FLUSHO 0010000 #define TARGET_PENDIN 0040000 #define TARGET_IEXTEN 0100000 +#define TARGET_EXTPROC 0200000 /* c_cc character offsets */ #define TARGET_VINTR 0 diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 01a9323a6377792c08e9faaafd39cdea2a7fa271..0b02a926025e2da079c456e2e21d24368cae5ebe 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -12,6 +12,7 @@ #include "qemu/guest-random.h" #include "qemu/units.h" #include "qemu/selfmap.h" +#include "qapi/error.h" #ifdef _ARCH_PPC64 #undef ARCH_DLINFO @@ -389,7 +390,7 @@ static bool init_guest_commpage(void) { void *want = g2h(ARM_COMMPAGE & -qemu_host_page_size); void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); if (addr == MAP_FAILED) { perror("Allocating guest commpage"); @@ -918,6 +919,12 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *en #define elf_check_arch(x) ((x) == EM_MIPS || (x) == EM_NANOMIPS) +#ifdef TARGET_ABI_MIPSN32 +#define elf_check_abi(x) ((x) & EF_MIPS_ABI2) +#else +#define elf_check_abi(x) (!((x) & EF_MIPS_ABI2)) +#endif + static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) { @@ -1032,9 +1039,12 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMBState *env (*regs)[pos++] = tswapreg(env->regs[i]); } - for (i = 0; i < 6; i++) { - (*regs)[pos++] = tswapreg(env->sregs[i]); - } + (*regs)[pos++] = tswapreg(env->pc); + (*regs)[pos++] = tswapreg(mb_cpu_read_msr(env)); + (*regs)[pos++] = 0; + (*regs)[pos++] = tswapreg(env->ear); + (*regs)[pos++] = 0; + (*regs)[pos++] = tswapreg(env->esr); } #endif /* TARGET_MICROBLAZE */ @@ -1487,6 +1497,10 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, #define elf_check_arch(x) ((x) == ELF_ARCH) #endif +#ifndef elf_check_abi +#define elf_check_abi(x) (1) +#endif + #ifndef ELF_HWCAP #define ELF_HWCAP 0 #endif @@ -1508,6 +1522,39 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, #include "elf.h" +/* We must delay the following stanzas until after "elf.h". */ +#if defined(TARGET_AARCH64) + +static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz, + const uint32_t *data, + struct image_info *info, + Error **errp) +{ + if (pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) { + if (pr_datasz != sizeof(uint32_t)) { + error_setg(errp, "Ill-formed GNU_PROPERTY_AARCH64_FEATURE_1_AND"); + return false; + } + /* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */ + info->note_flags = *data; + } + return true; +} +#define ARCH_USE_GNU_PROPERTY 1 + +#else + +static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz, + const uint32_t *data, + struct image_info *info, + Error **errp) +{ + g_assert_not_reached(); +} +#define ARCH_USE_GNU_PROPERTY 0 + +#endif + struct exec { unsigned int a_info; /* Use macros N_MAGIC, etc for access */ @@ -1644,6 +1691,7 @@ static bool elf_check_ident(struct elfhdr *ehdr) static bool elf_check_ehdr(struct elfhdr *ehdr) { return (elf_check_arch(ehdr->e_machine) + && elf_check_abi(ehdr->e_flags) && ehdr->e_ehsize == sizeof(struct elfhdr) && ehdr->e_phentsize == sizeof(struct elf_phdr) && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)); @@ -2073,12 +2121,14 @@ static void pgb_have_guest_base(const char *image_name, abi_ulong guest_loaddr, exit(EXIT_FAILURE); } } else { +#if HOST_LONG_BITS < TARGET_ABI_BITS if ((guest_hiaddr - guest_base) > ~(uintptr_t)0) { error_report("%s: requires more virtual address space " "than the host can provide (0x%" PRIx64 ")", image_name, (uint64_t)guest_hiaddr - guest_base); exit(EXIT_FAILURE); } +#endif } /* @@ -2099,9 +2149,58 @@ static void pgb_have_guest_base(const char *image_name, abi_ulong guest_loaddr, } } +/** + * pgd_find_hole_fallback: potential mmap address + * @guest_size: size of available space + * @brk: location of break + * @align: memory alignment + * + * This is a fallback method for finding a hole in the host address + * space if we don't have the benefit of being able to access + * /proc/self/map. It can potentially take a very long time as we can + * only dumbly iterate up the host address space seeing if the + * allocation would work. + */ +static uintptr_t pgd_find_hole_fallback(uintptr_t guest_size, uintptr_t brk, + long align, uintptr_t offset) +{ + uintptr_t base; + + /* Start (aligned) at the bottom and work our way up */ + base = ROUND_UP(mmap_min_addr, align); + + while (true) { + uintptr_t align_start, end; + align_start = ROUND_UP(base, align); + end = align_start + guest_size + offset; + + /* if brk is anywhere in the range give ourselves some room to grow. */ + if (align_start <= brk && brk < end) { + base = brk + (16 * MiB); + continue; + } else if (align_start + guest_size < align_start) { + /* we have run out of space */ + return -1; + } else { + int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE | + MAP_FIXED_NOREPLACE; + void * mmap_start = mmap((void *) align_start, guest_size, + PROT_NONE, flags, -1, 0); + if (mmap_start != MAP_FAILED) { + munmap((void *) align_start, guest_size); + if (MAP_FIXED_NOREPLACE != 0 || + mmap_start == (void *) align_start) { + return (uintptr_t) mmap_start + offset; + } + } + base += qemu_host_page_size; + } + } +} + /* Return value for guest_base, or -1 if no hole found. */ static uintptr_t pgb_find_hole(uintptr_t guest_loaddr, uintptr_t guest_size, - long align) + long align, uintptr_t offset) { GSList *maps, *iter; uintptr_t this_start, this_end, next_start, brk; @@ -2114,6 +2213,10 @@ static uintptr_t pgb_find_hole(uintptr_t guest_loaddr, uintptr_t guest_size, /* Read brk after we've read the maps, which will malloc. */ brk = (uintptr_t)sbrk(0); + if (!maps) { + return pgd_find_hole_fallback(guest_size, brk, align, offset); + } + /* The first hole is before the first map entry. */ this_start = mmap_min_addr; @@ -2123,7 +2226,7 @@ static uintptr_t pgb_find_hole(uintptr_t guest_loaddr, uintptr_t guest_size, this_end = ((MapInfo *)iter->data)->start; next_start = ((MapInfo *)iter->data)->end; - align_start = ROUND_UP(this_start, align); + align_start = ROUND_UP(this_start + offset, align); /* Skip holes that are too small. */ if (align_start >= this_end) { @@ -2173,6 +2276,7 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr, { uintptr_t loaddr = orig_loaddr; uintptr_t hiaddr = orig_hiaddr; + uintptr_t offset = 0; uintptr_t addr; if (hiaddr != orig_hiaddr) { @@ -2186,18 +2290,19 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr, if (ARM_COMMPAGE) { /* * Extend the allocation to include the commpage. - * For a 64-bit host, this is just 4GiB; for a 32-bit host, - * the address arithmetic will wrap around, but the difference - * will produce the correct allocation size. + * For a 64-bit host, this is just 4GiB; for a 32-bit host we + * need to ensure there is space bellow the guest_base so we + * can map the commpage in the place needed when the address + * arithmetic wraps around. */ if (sizeof(uintptr_t) == 8 || loaddr >= 0x80000000u) { - hiaddr = (uintptr_t)4 << 30; + hiaddr = (uintptr_t) 4 << 30; } else { - loaddr = ARM_COMMPAGE & -align; + offset = -(ARM_COMMPAGE & -align); } } - addr = pgb_find_hole(loaddr, hiaddr - loaddr, align); + addr = pgb_find_hole(loaddr, hiaddr - loaddr, align, offset); if (addr == -1) { /* * If ARM_COMMPAGE, there *might* be a non-consecutive allocation @@ -2232,7 +2337,7 @@ static void pgb_dynamic(const char *image_name, long align) * just above that, and maximises the positive guest addresses. */ commpage = ARM_COMMPAGE & -align; - addr = pgb_find_hole(commpage, -commpage, align); + addr = pgb_find_hole(commpage, -commpage, align, 0); assert(addr != -1); guest_base = addr; } @@ -2241,7 +2346,7 @@ static void pgb_dynamic(const char *image_name, long align) static void pgb_reserved_va(const char *image_name, abi_ulong guest_loaddr, abi_ulong guest_hiaddr, long align) { - const int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE; + int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE; void *addr, *test; if (guest_hiaddr > reserved_va) { @@ -2254,18 +2359,20 @@ static void pgb_reserved_va(const char *image_name, abi_ulong guest_loaddr, /* Widen the "image" to the entire reserved address space. */ pgb_static(image_name, 0, reserved_va, align); + /* osdep.h defines this as 0 if it's missing */ + flags |= MAP_FIXED_NOREPLACE; + /* Reserve the memory on the host. */ assert(guest_base != 0); test = g2h(0); addr = mmap(test, reserved_va, PROT_NONE, flags, -1, 0); - if (addr == MAP_FAILED) { + if (addr == MAP_FAILED || addr != test) { error_report("Unable to reserve 0x%lx bytes of virtual address " - "space for use as guest address space (check your " - "virtual memory ulimit setting or reserve less " - "using -R option)", reserved_va); + "space at %p (%s) for use as guest address space (check your" + "virtual memory ulimit setting, min_mmap_addr or reserve less " + "using -R option)", reserved_va, test, strerror(errno)); exit(EXIT_FAILURE); } - assert(addr == test); } void probe_guest_base(const char *image_name, abi_ulong guest_loaddr, @@ -2300,6 +2407,150 @@ void probe_guest_base(const char *image_name, abi_ulong guest_loaddr, "@ 0x%" PRIx64 "\n", (uint64_t)guest_base); } +enum { + /* The string "GNU\0" as a magic number. */ + GNU0_MAGIC = const_le32('G' | 'N' << 8 | 'U' << 16), + NOTE_DATA_SZ = 1 * KiB, + NOTE_NAME_SZ = 4, + ELF_GNU_PROPERTY_ALIGN = ELF_CLASS == ELFCLASS32 ? 4 : 8, +}; + +/* + * Process a single gnu_property entry. + * Return false for error. + */ +static bool parse_elf_property(const uint32_t *data, int *off, int datasz, + struct image_info *info, bool have_prev_type, + uint32_t *prev_type, Error **errp) +{ + uint32_t pr_type, pr_datasz, step; + + if (*off > datasz || !QEMU_IS_ALIGNED(*off, ELF_GNU_PROPERTY_ALIGN)) { + goto error_data; + } + datasz -= *off; + data += *off / sizeof(uint32_t); + + if (datasz < 2 * sizeof(uint32_t)) { + goto error_data; + } + pr_type = data[0]; + pr_datasz = data[1]; + data += 2; + datasz -= 2 * sizeof(uint32_t); + step = ROUND_UP(pr_datasz, ELF_GNU_PROPERTY_ALIGN); + if (step > datasz) { + goto error_data; + } + + /* Properties are supposed to be unique and sorted on pr_type. */ + if (have_prev_type && pr_type <= *prev_type) { + if (pr_type == *prev_type) { + error_setg(errp, "Duplicate property in PT_GNU_PROPERTY"); + } else { + error_setg(errp, "Unsorted property in PT_GNU_PROPERTY"); + } + return false; + } + *prev_type = pr_type; + + if (!arch_parse_elf_property(pr_type, pr_datasz, data, info, errp)) { + return false; + } + + *off += 2 * sizeof(uint32_t) + step; + return true; + + error_data: + error_setg(errp, "Ill-formed property in PT_GNU_PROPERTY"); + return false; +} + +/* Process NT_GNU_PROPERTY_TYPE_0. */ +static bool parse_elf_properties(int image_fd, + struct image_info *info, + const struct elf_phdr *phdr, + char bprm_buf[BPRM_BUF_SIZE], + Error **errp) +{ + union { + struct elf_note nhdr; + uint32_t data[NOTE_DATA_SZ / sizeof(uint32_t)]; + } note; + + int n, off, datasz; + bool have_prev_type; + uint32_t prev_type; + + /* Unless the arch requires properties, ignore them. */ + if (!ARCH_USE_GNU_PROPERTY) { + return true; + } + + /* If the properties are crazy large, that's too bad. */ + n = phdr->p_filesz; + if (n > sizeof(note)) { + error_setg(errp, "PT_GNU_PROPERTY too large"); + return false; + } + if (n < sizeof(note.nhdr)) { + error_setg(errp, "PT_GNU_PROPERTY too small"); + return false; + } + + if (phdr->p_offset + n <= BPRM_BUF_SIZE) { + memcpy(¬e, bprm_buf + phdr->p_offset, n); + } else { + ssize_t len = pread(image_fd, ¬e, n, phdr->p_offset); + if (len != n) { + error_setg_errno(errp, errno, "Error reading file header"); + return false; + } + } + + /* + * The contents of a valid PT_GNU_PROPERTY is a sequence + * of uint32_t -- swap them all now. + */ +#ifdef BSWAP_NEEDED + for (int i = 0; i < n / 4; i++) { + bswap32s(note.data + i); + } +#endif + + /* + * Note that nhdr is 3 words, and that the "name" described by namesz + * immediately follows nhdr and is thus at the 4th word. Further, all + * of the inputs to the kernel's round_up are multiples of 4. + */ + if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 || + note.nhdr.n_namesz != NOTE_NAME_SZ || + note.data[3] != GNU0_MAGIC) { + error_setg(errp, "Invalid note in PT_GNU_PROPERTY"); + return false; + } + off = sizeof(note.nhdr) + NOTE_NAME_SZ; + + datasz = note.nhdr.n_descsz + off; + if (datasz > n) { + error_setg(errp, "Invalid note size in PT_GNU_PROPERTY"); + return false; + } + + have_prev_type = false; + prev_type = 0; + while (1) { + if (off == datasz) { + return true; /* end, exit ok */ + } + if (!parse_elf_property(note.data, &off, datasz, info, + have_prev_type, &prev_type, errp)) { + return false; + } + have_prev_type = true; + } +} + /* Load an ELF image into the address space. IMAGE_NAME is the filename of the image, to use in error messages. @@ -2319,16 +2570,17 @@ static void load_elf_image(const char *image_name, int image_fd, struct elfhdr *ehdr = (struct elfhdr *)bprm_buf; struct elf_phdr *phdr; abi_ulong load_addr, load_bias, loaddr, hiaddr, error; - int i, retval; - const char *errmsg; + int i, retval, prot_exec; + Error *err = NULL; /* First of all, some simple consistency checks */ - errmsg = "Invalid ELF image for this architecture"; if (!elf_check_ident(ehdr)) { + error_setg(&err, "Invalid ELF image for this architecture"); goto exit_errmsg; } bswap_ehdr(ehdr); if (!elf_check_ehdr(ehdr)) { + error_setg(&err, "Invalid ELF image for this architecture"); goto exit_errmsg; } @@ -2349,22 +2601,54 @@ static void load_elf_image(const char *image_name, int image_fd, mmap_lock(); - /* Find the maximum size of the image and allocate an appropriate - amount of memory to handle that. */ + /* + * Find the maximum size of the image and allocate an appropriate + * amount of memory to handle that. Locate the interpreter, if any. + */ loaddr = -1, hiaddr = 0; info->alignment = 0; for (i = 0; i < ehdr->e_phnum; ++i) { - if (phdr[i].p_type == PT_LOAD) { - abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset; + struct elf_phdr *eppnt = phdr + i; + if (eppnt->p_type == PT_LOAD) { + abi_ulong a = eppnt->p_vaddr - eppnt->p_offset; if (a < loaddr) { loaddr = a; } - a = phdr[i].p_vaddr + phdr[i].p_memsz; + a = eppnt->p_vaddr + eppnt->p_memsz; if (a > hiaddr) { hiaddr = a; } ++info->nsegs; - info->alignment |= phdr[i].p_align; + info->alignment |= eppnt->p_align; + } else if (eppnt->p_type == PT_INTERP && pinterp_name) { + g_autofree char *interp_name = NULL; + + if (*pinterp_name) { + error_setg(&err, "Multiple PT_INTERP entries"); + goto exit_errmsg; + } + + interp_name = g_malloc(eppnt->p_filesz); + + if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) { + memcpy(interp_name, bprm_buf + eppnt->p_offset, + eppnt->p_filesz); + } else { + retval = pread(image_fd, interp_name, eppnt->p_filesz, + eppnt->p_offset); + if (retval != eppnt->p_filesz) { + goto exit_read; + } + } + if (interp_name[eppnt->p_filesz - 1] != 0) { + error_setg(&err, "Invalid PT_INTERP entry"); + goto exit_errmsg; + } + *pinterp_name = g_steal_pointer(&interp_name); + } else if (eppnt->p_type == PT_GNU_PROPERTY) { + if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) { + goto exit_errmsg; + } } } @@ -2418,7 +2702,7 @@ static void load_elf_image(const char *image_name, int image_fd, (ehdr->e_type == ET_EXEC ? MAP_FIXED : 0), -1, 0); if (load_addr == -1) { - goto exit_perror; + goto exit_mmap; } load_bias = load_addr - loaddr; @@ -2453,15 +2737,41 @@ static void load_elf_image(const char *image_name, int image_fd, info->brk = 0; info->elf_flags = ehdr->e_flags; + prot_exec = PROT_EXEC; +#ifdef TARGET_AARCH64 + /* + * If the BTI feature is present, this indicates that the executable + * pages of the startup binary should be mapped with PROT_BTI, so that + * branch targets are enforced. + * + * The startup binary is either the interpreter or the static executable. + * The interpreter is responsible for all pages of a dynamic executable. + * + * Elf notes are backward compatible to older cpus. + * Do not enable BTI unless it is supported. + */ + if ((info->note_flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) + && (pinterp_name == NULL || *pinterp_name == 0) + && cpu_isar_feature(aa64_bti, ARM_CPU(thread_cpu))) { + prot_exec |= TARGET_PROT_BTI; + } +#endif + for (i = 0; i < ehdr->e_phnum; i++) { struct elf_phdr *eppnt = phdr + i; if (eppnt->p_type == PT_LOAD) { abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len; int elf_prot = 0; - if (eppnt->p_flags & PF_R) elf_prot = PROT_READ; - if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; - if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; + if (eppnt->p_flags & PF_R) { + elf_prot |= PROT_READ; + } + if (eppnt->p_flags & PF_W) { + elf_prot |= PROT_WRITE; + } + if (eppnt->p_flags & PF_X) { + elf_prot |= prot_exec; + } vaddr = load_bias + eppnt->p_vaddr; vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr); @@ -2479,7 +2789,7 @@ static void load_elf_image(const char *image_name, int image_fd, image_fd, eppnt->p_offset - vaddr_po); if (error == -1) { - goto exit_perror; + goto exit_mmap; } } @@ -2507,42 +2817,15 @@ static void load_elf_image(const char *image_name, int image_fd, if (vaddr_ef > info->end_data) { info->end_data = vaddr_ef; } - if (vaddr_em > info->brk) { - info->brk = vaddr_em; - } - } - } else if (eppnt->p_type == PT_INTERP && pinterp_name) { - char *interp_name; - - if (*pinterp_name) { - errmsg = "Multiple PT_INTERP entries"; - goto exit_errmsg; - } - interp_name = malloc(eppnt->p_filesz); - if (!interp_name) { - goto exit_perror; - } - - if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) { - memcpy(interp_name, bprm_buf + eppnt->p_offset, - eppnt->p_filesz); - } else { - retval = pread(image_fd, interp_name, eppnt->p_filesz, - eppnt->p_offset); - if (retval != eppnt->p_filesz) { - goto exit_perror; - } } - if (interp_name[eppnt->p_filesz - 1] != 0) { - errmsg = "Invalid PT_INTERP entry"; - goto exit_errmsg; + if (vaddr_em > info->brk) { + info->brk = vaddr_em; } - *pinterp_name = interp_name; #ifdef TARGET_MIPS } else if (eppnt->p_type == PT_MIPS_ABIFLAGS) { Mips_elf_abiflags_v0 abiflags; if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) { - errmsg = "Invalid PT_MIPS_ABIFLAGS entry"; + error_setg(&err, "Invalid PT_MIPS_ABIFLAGS entry"); goto exit_errmsg; } if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) { @@ -2552,7 +2835,7 @@ static void load_elf_image(const char *image_name, int image_fd, retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0), eppnt->p_offset); if (retval != sizeof(Mips_elf_abiflags_v0)) { - goto exit_perror; + goto exit_read; } } bswap_mips_abiflags(&abiflags); @@ -2564,7 +2847,6 @@ static void load_elf_image(const char *image_name, int image_fd, if (info->end_data == 0) { info->start_data = info->end_code; info->end_data = info->end_code; - info->brk = info->end_code; } if (qemu_log_enabled()) { @@ -2578,13 +2860,16 @@ static void load_elf_image(const char *image_name, int image_fd, exit_read: if (retval >= 0) { - errmsg = "Incomplete read of file header"; - goto exit_errmsg; + error_setg(&err, "Incomplete read of file header"); + } else { + error_setg_errno(&err, errno, "Error reading file header"); } - exit_perror: - errmsg = strerror(errno); + goto exit_errmsg; + exit_mmap: + error_setg_errno(&err, errno, "Error mapping file"); + goto exit_errmsg; exit_errmsg: - fprintf(stderr, "%s: %s\n", image_name, errmsg); + error_reportf_err(err, "%s: ", image_name); exit(-1); } @@ -2592,26 +2877,27 @@ static void load_elf_interp(const char *filename, struct image_info *info, char bprm_buf[BPRM_BUF_SIZE]) { int fd, retval; + Error *err = NULL; fd = open(path(filename), O_RDONLY); if (fd < 0) { - goto exit_perror; + error_setg_file_open(&err, errno, filename); + error_report_err(err); + exit(-1); } retval = read(fd, bprm_buf, BPRM_BUF_SIZE); if (retval < 0) { - goto exit_perror; + error_setg_errno(&err, errno, "Error reading file header"); + error_reportf_err(err, "%s: ", filename); + exit(-1); } + if (retval < BPRM_BUF_SIZE) { memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval); } load_elf_image(filename, fd, info, NULL, bprm_buf); - return; - - exit_perror: - fprintf(stderr, "%s: %s\n", filename, strerror(errno)); - exit(-1); } static int symfind(const void *s0, const void *s1) @@ -2890,7 +3176,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) if (elf_interpreter) { info->load_bias = interp_info.load_bias; info->entry = interp_info.entry; - free(elf_interpreter); + g_free(elf_interpreter); } #ifdef USE_ELF_CORE_DUMP @@ -3199,7 +3485,9 @@ static abi_ulong vma_dump_size(const struct vm_area_struct *vma) if (vma->vma_flags & PROT_EXEC) { char page[TARGET_PAGE_SIZE]; - copy_from_user(page, vma->vma_start, sizeof (page)); + if (copy_from_user(page, vma->vma_start, sizeof (page))) { + return 0; + } if ((page[EI_MAG0] == ELFMAG0) && (page[EI_MAG1] == ELFMAG1) && (page[EI_MAG2] == ELFMAG2) && diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c index c0687c52e62b117ad9794399aacbe3c5efa024d9..23adaca83639a93cf9dff3cead2cba7bdb9904f9 100644 --- a/linux-user/fd-trans.c +++ b/linux-user/fd-trans.c @@ -133,6 +133,9 @@ enum { QEMU_IFLA_NEW_IFINDEX, QEMU_IFLA_MIN_MTU, QEMU_IFLA_MAX_MTU, + QEMU_IFLA_PROP_LIST, + QEMU_IFLA_ALT_IFNAME, + QEMU_IFLA_PERM_ADDRESS, QEMU___IFLA_MAX }; @@ -172,6 +175,8 @@ enum { QEMU_IFLA_BRPORT_NEIGH_SUPPRESS, QEMU_IFLA_BRPORT_ISOLATED, QEMU_IFLA_BRPORT_BACKUP_PORT, + QEMU_IFLA_BRPORT_MRP_RING_OPEN, + QEMU_IFLA_BRPORT_MRP_IN_OPEN, QEMU___IFLA_BRPORT_MAX }; @@ -549,6 +554,8 @@ static abi_long host_to_target_slave_data_bridge_nlattr(struct nlattr *nlattr, case QEMU_IFLA_BRPORT_BCAST_FLOOD: case QEMU_IFLA_BRPORT_NEIGH_SUPPRESS: case QEMU_IFLA_BRPORT_ISOLATED: + case QEMU_IFLA_BRPORT_MRP_RING_OPEN: + case QEMU_IFLA_BRPORT_MRP_IN_OPEN: break; /* uint16_t */ case QEMU_IFLA_BRPORT_PRIORITY: @@ -807,6 +814,7 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr) /* binary stream */ case QEMU_IFLA_ADDRESS: case QEMU_IFLA_BROADCAST: + case QEMU_IFLA_PERM_ADDRESS: /* string */ case QEMU_IFLA_IFNAME: case QEMU_IFLA_QDISC: @@ -1121,7 +1129,14 @@ static abi_long target_to_host_for_each_rtattr(struct rtattr *rtattr, static abi_long target_to_host_data_link_rtattr(struct rtattr *rtattr) { + uint32_t *u32; + switch (rtattr->rta_type) { + /* uint32_t */ + case QEMU_IFLA_EXT_MASK: + u32 = RTA_DATA(rtattr); + *u32 = tswap32(*u32); + break; default: qemu_log_mask(LOG_UNIMP, "Unknown target QEMU_IFLA type: %d\n", rtattr->rta_type); @@ -1156,6 +1171,7 @@ static abi_long target_to_host_data_route_rtattr(struct rtattr *rtattr) break; /* u32 */ case QEMU_RTA_PRIORITY: + case QEMU_RTA_TABLE: case QEMU_RTA_OIF: u32 = RTA_DATA(rtattr); *u32 = tswap32(*u32); @@ -1196,10 +1212,10 @@ static abi_long target_to_host_data_route(struct nlmsghdr *nlh) struct rtmsg *rtm; switch (nlh->nlmsg_type) { - case RTM_GETLINK: - break; case RTM_NEWLINK: case RTM_DELLINK: + case RTM_SETLINK: + case RTM_GETLINK: if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifi))) { ifi = NLMSG_DATA(nlh); ifi->ifi_type = tswap16(ifi->ifi_type); @@ -1220,10 +1236,9 @@ static abi_long target_to_host_data_route(struct nlmsghdr *nlh) NLMSG_LENGTH(sizeof(*ifa))); } break; - case RTM_GETROUTE: - break; case RTM_NEWROUTE: case RTM_DELROUTE: + case RTM_GETROUTE: if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*rtm))) { rtm = NLMSG_DATA(nlh); rtm->rtm_flags = tswap32(rtm->rtm_flags); diff --git a/linux-user/flat.h b/linux-user/flat.h index 1e44b334432002f38a443c5ad0bac2eb70578c34..ed518e2013b168a0b536c617f6439cc140c888f9 100644 --- a/linux-user/flat.h +++ b/linux-user/flat.h @@ -43,7 +43,7 @@ struct flat_hdr { abi_ulong reloc_count; /* Number of relocation records */ abi_ulong flags; abi_ulong build_date; /* When the program/library was built */ - abi_ulong filler[5]; /* Reservered, set to zero */ + abi_ulong filler[5]; /* Reserved, set to zero */ }; #define FLAT_FLAG_RAM 0x0001 /* load program entirely into RAM */ diff --git a/linux-user/flatload.c b/linux-user/flatload.c index 8fb448f0bf065e2e7fbcf00db06e6cbaf0c66300..14d2999d1537572f13972c562ab2b3d66c793595 100644 --- a/linux-user/flatload.c +++ b/linux-user/flatload.c @@ -442,7 +442,7 @@ static int load_flat_file(struct linux_binprm * bprm, indx_len = (indx_len + 15) & ~(abi_ulong)15; /* - * Alloate the address space. + * Allocate the address space. */ probe_guest_base(bprm->filename, 0, text_len + data_len + extra + indx_len); @@ -794,7 +794,7 @@ int load_flt_binary(struct linux_binprm *bprm, struct image_info *info) #error here for (i = MAX_SHARED_LIBS-1; i>0; i--) { if (libinfo[i].loaded) { - /* Push previos first to call address */ + /* Push previous first to call address */ --sp; if (put_user_ual(start_addr, sp)) return -EFAULT; diff --git a/linux-user/generic/fcntl.h b/linux-user/generic/fcntl.h index 9f727d4df2c8e9a4ec9d20535a69e98c6a9157c0..c85c5b9fed65b7a7d02e2465792886e2809340c5 100644 --- a/linux-user/generic/fcntl.h +++ b/linux-user/generic/fcntl.h @@ -99,6 +99,10 @@ #define TARGET_F_SETLKW64 14 #endif +#define TARGET_F_OFD_GETLK 36 +#define TARGET_F_OFD_SETLK 37 +#define TARGET_F_OFD_SETLKW 38 + #ifndef TARGET_F_SETOWN_EX #define TARGET_F_SETOWN_EX 15 #define TARGET_F_GETOWN_EX 16 diff --git a/linux-user/generic/termbits.h b/linux-user/generic/termbits.h new file mode 100644 index 0000000000000000000000000000000000000000..6675e0d1abab1ef259ae049bf82301957de4dee2 --- /dev/null +++ b/linux-user/generic/termbits.h @@ -0,0 +1,318 @@ +/* Derived from asm-generic/termbits.h */ + +#ifndef GENERIC_TERMBITS_H +#define GENERIC_TERMBITS_H + +typedef unsigned char target_cc_t; /* cc_t */ +typedef unsigned int target_speed_t; /* speed_t */ +typedef unsigned int target_tcflag_t; /* tcflag_t */ + +#define TARGET_NCCS 19 + +struct target_termios { + target_tcflag_t c_iflag; /* input mode flags */ + target_tcflag_t c_oflag; /* output mode flags */ + target_tcflag_t c_cflag; /* control mode flags */ + target_tcflag_t c_lflag; /* local mode flags */ + target_cc_t c_line; /* line discipline */ + target_cc_t c_cc[TARGET_NCCS]; /* control characters */ +}; + +struct target_termios2 { + target_tcflag_t c_iflag; /* input mode flags */ + target_tcflag_t c_oflag; /* output mode flags */ + target_tcflag_t c_cflag; /* control mode flags */ + target_tcflag_t c_lflag; /* local mode flags */ + target_cc_t c_line; /* line discipline */ + target_cc_t c_cc[TARGET_NCCS]; /* control characters */ + target_speed_t c_ispeed; /* input speed */ + target_speed_t c_ospeed; /* output speed */ +}; + +struct target_ktermios { + target_tcflag_t c_iflag; /* input mode flags */ + target_tcflag_t c_oflag; /* output mode flags */ + target_tcflag_t c_cflag; /* control mode flags */ + target_tcflag_t c_lflag; /* local mode flags */ + target_cc_t c_line; /* line discipline */ + target_cc_t c_cc[TARGET_NCCS]; /* control characters */ + target_speed_t c_ispeed; /* input speed */ + target_speed_t c_ospeed; /* output speed */ +}; + +/* c_cc character offsets */ +#define TARGET_VINTR 0 +#define TARGET_VQUIT 1 +#define TARGET_VERASE 2 +#define TARGET_VKILL 3 +#define TARGET_VEOF 4 +#define TARGET_VTIME 5 +#define TARGET_VMIN 6 +#define TARGET_VSWTC 7 +#define TARGET_VSTART 8 +#define TARGET_VSTOP 9 +#define TARGET_VSUSP 10 +#define TARGET_VEOL 11 +#define TARGET_VREPRINT 12 +#define TARGET_VDISCARD 13 +#define TARGET_VWERASE 14 +#define TARGET_VLNEXT 15 +#define TARGET_VEOL2 16 + +/* c_iflag bits */ +#define TARGET_IGNBRK 0000001 +#define TARGET_BRKINT 0000002 +#define TARGET_IGNPAR 0000004 +#define TARGET_PARMRK 0000010 +#define TARGET_INPCK 0000020 +#define TARGET_ISTRIP 0000040 +#define TARGET_INLCR 0000100 +#define TARGET_IGNCR 0000200 +#define TARGET_ICRNL 0000400 +#define TARGET_IUCLC 0001000 +#define TARGET_IXON 0002000 +#define TARGET_IXANY 0004000 +#define TARGET_IXOFF 0010000 +#define TARGET_IMAXBEL 0020000 +#define TARGET_IUTF8 0040000 + +/* c_oflag bits */ +#define TARGET_OPOST 0000001 +#define TARGET_OLCUC 0000002 +#define TARGET_ONLCR 0000004 +#define TARGET_OCRNL 0000010 +#define TARGET_ONOCR 0000020 +#define TARGET_ONLRET 0000040 +#define TARGET_OFILL 0000100 +#define TARGET_OFDEL 0000200 +#define TARGET_NLDLY 0000400 +#define TARGET_NL0 0000000 +#define TARGET_NL1 0000400 +#define TARGET_CRDLY 0003000 +#define TARGET_CR0 0000000 +#define TARGET_CR1 0001000 +#define TARGET_CR2 0002000 +#define TARGET_CR3 0003000 +#define TARGET_TABDLY 0014000 +#define TARGET_TAB0 0000000 +#define TARGET_TAB1 0004000 +#define TARGET_TAB2 0010000 +#define TARGET_TAB3 0014000 +#define TARGET_XTABS 0014000 +#define TARGET_BSDLY 0020000 +#define TARGET_BS0 0000000 +#define TARGET_BS1 0020000 +#define TARGET_VTDLY 0040000 +#define TARGET_VT0 0000000 +#define TARGET_VT1 0040000 +#define TARGET_FFDLY 0100000 +#define TARGET_FF0 0000000 +#define TARGET_FF1 0100000 + +/* c_cflag bit meaning */ +#define TARGET_CBAUD 0010017 +#define TARGET_B0 0000000 /* hang up */ +#define TARGET_B50 0000001 +#define TARGET_B75 0000002 +#define TARGET_B110 0000003 +#define TARGET_B134 0000004 +#define TARGET_B150 0000005 +#define TARGET_B200 0000006 +#define TARGET_B300 0000007 +#define TARGET_B600 0000010 +#define TARGET_B1200 0000011 +#define TARGET_B1800 0000012 +#define TARGET_B2400 0000013 +#define TARGET_B4800 0000014 +#define TARGET_B9600 0000015 +#define TARGET_B19200 0000016 +#define TARGET_B38400 0000017 +#define TARGET_EXTA TARGET_B19200 +#define TARGET_EXTB TARGET_B38400 +#define TARGET_CSIZE 0000060 +#define TARGET_CS5 0000000 +#define TARGET_CS6 0000020 +#define TARGET_CS7 0000040 +#define TARGET_CS8 0000060 +#define TARGET_CSTOPB 0000100 +#define TARGET_CREAD 0000200 +#define TARGET_PARENB 0000400 +#define TARGET_PARODD 0001000 +#define TARGET_HUPCL 0002000 +#define TARGET_CLOCAL 0004000 +#define TARGET_CBAUDEX 0010000 +#define TARGET_BOTHER 0010000 +#define TARGET_B57600 0010001 +#define TARGET_B115200 0010002 +#define TARGET_B230400 0010003 +#define TARGET_B460800 0010004 +#define TARGET_B500000 0010005 +#define TARGET_B576000 0010006 +#define TARGET_B921600 0010007 +#define TARGET_B1000000 0010010 +#define TARGET_B1152000 0010011 +#define TARGET_B1500000 0010012 +#define TARGET_B2000000 0010013 +#define TARGET_B2500000 0010014 +#define TARGET_B3000000 0010015 +#define TARGET_B3500000 0010016 +#define TARGET_B4000000 0010017 +#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */ +#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ +#define TARGET_CRTSCTS 020000000000 /* flow control */ + +#define TARGET_IBSHIFT 16 /* Shift from CBAUD to CIBAUD */ + +/* c_lflag bits */ +#define TARGET_ISIG 0000001 +#define TARGET_ICANON 0000002 +#define TARGET_XCASE 0000004 +#define TARGET_ECHO 0000010 +#define TARGET_ECHOE 0000020 +#define TARGET_ECHOK 0000040 +#define TARGET_ECHONL 0000100 +#define TARGET_NOFLSH 0000200 +#define TARGET_TOSTOP 0000400 +#define TARGET_ECHOCTL 0001000 +#define TARGET_ECHOPRT 0002000 +#define TARGET_ECHOKE 0004000 +#define TARGET_FLUSHO 0010000 +#define TARGET_PENDIN 0040000 +#define TARGET_IEXTEN 0100000 +#define TARGET_EXTPROC 0200000 + +/* tcflow() and TCXONC use these */ +#define TARGET_TCOOFF 0 +#define TARGET_TCOON 1 +#define TARGET_TCIOFF 2 +#define TARGET_TCION 3 + +/* tcflush() and TCFLSH use these */ +#define TARGET_TCIFLUSH 0 +#define TARGET_TCOFLUSH 1 +#define TARGET_TCIOFLUSH 2 + +/* tcsetattr uses these */ +#define TARGET_TCSANOW 0 +#define TARGET_TCSADRAIN 1 +#define TARGET_TCSAFLUSH 2 + +/* Derived from include/uapi/asm-generic/ioctls.h */ + +#define TARGET_TCGETS 0x5401 +#define TARGET_TCSETS 0x5402 +#define TARGET_TCSETSW 0x5403 +#define TARGET_TCSETSF 0x5404 +#define TARGET_TCGETA 0x5405 +#define TARGET_TCSETA 0x5406 +#define TARGET_TCSETAW 0x5407 +#define TARGET_TCSETAF 0x5408 +#define TARGET_TCSBRK 0x5409 +#define TARGET_TCXONC 0x540A +#define TARGET_TCFLSH 0x540B + +#define TARGET_TIOCEXCL 0x540C +#define TARGET_TIOCNXCL 0x540D +#define TARGET_TIOCSCTTY 0x540E +#define TARGET_TIOCGPGRP 0x540F +#define TARGET_TIOCSPGRP 0x5410 +#define TARGET_TIOCOUTQ 0x5411 +#define TARGET_TIOCSTI 0x5412 +#define TARGET_TIOCGWINSZ 0x5413 +#define TARGET_TIOCSWINSZ 0x5414 +#define TARGET_TIOCMGET 0x5415 +#define TARGET_TIOCMBIS 0x5416 +#define TARGET_TIOCMBIC 0x5417 +#define TARGET_TIOCMSET 0x5418 +#define TARGET_TIOCGSOFTCAR 0x5419 +#define TARGET_TIOCSSOFTCAR 0x541A +#define TARGET_FIONREAD 0x541B +#define TARGET_TIOCINQ TARGET_FIONREAD +#define TARGET_TIOCLINUX 0x541C +#define TARGET_TIOCCONS 0x541D +#define TARGET_TIOCGSERIAL 0x541E +#define TARGET_TIOCSSERIAL 0x541F +#define TARGET_TIOCPKT 0x5420 +#define TARGET_FIONBIO 0x5421 +#define TARGET_TIOCNOTTY 0x5422 +#define TARGET_TIOCSETD 0x5423 +#define TARGET_TIOCGETD 0x5424 +#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ +#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */ +#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ +#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ +#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ +#define TARGET_TCGETS2 TARGET_IOR('T', 0x2A, struct target_termios2) +#define TARGET_TCSETS2 TARGET_IOW('T', 0x2B, struct target_termios2) +#define TARGET_TCSETSW2 TARGET_IOW('T', 0x2C, struct target_termios2) +#define TARGET_TCSETSF2 TARGET_IOW('T', 0x2D, struct target_termios2) +#define TARGET_TIOCGRS485 0x542E +#ifndef TARGET_TIOCSRS485 +#define TARGET_TIOCSRS485 0x542F +#endif +/* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCGPTN TARGET_IOR('T', 0x30, unsigned int) +/* Lock/unlock Pty */ +#define TARGET_TIOCSPTLCK TARGET_IOW('T', 0x31, int) + +/* Get primary device node of /dev/console */ +#define TARGET_TIOCGDEV TARGET_IOR('T', 0x32, unsigned int) +#define TARGET_TCGETX 0x5432 /* SYS5 TCGETX compatibility */ +#define TARGET_TCSETX 0x5433 +#define TARGET_TCSETXF 0x5434 +#define TARGET_TCSETXW 0x5435 +/* pty: generate signal */ +#define TARGET_TIOCSIG TARGET_IOW('T', 0x36, int) +#define TARGET_TIOCVHANGUP 0x5437 +/* Get packet mode state */ +#define TARGET_TIOCGPKT TARGET_IOR('T', 0x38, int) +/* Get Pty lock state */ +#define TARGET_TIOCGPTLCK TARGET_IOR('T', 0x39, int) +/* Get exclusive mode state */ +#define TARGET_TIOCGEXCL TARGET_IOR('T', 0x40, int) +/* Safely open the slave */ +#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) +#define TARGET_TIOCGISO7816 TARGET_IOR('T', 0x42, struct serial_iso7816) +#define TARGET_TIOCSISO7816 TARGET_IOWR('T', 0x43, struct serial_iso7816) + +#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted */ +#define TARGET_FIOCLEX 0x5451 +#define TARGET_FIOASYNC 0x5452 +#define TARGET_TIOCSERCONFIG 0x5453 +#define TARGET_TIOCSERGWILD 0x5454 +#define TARGET_TIOCSERSWILD 0x5455 +#define TARGET_TIOCGLCKTRMIOS 0x5456 +#define TARGET_TIOCSLCKTRMIOS 0x5457 +#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ +#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ +#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ +#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ + +/* wait for a change on serial input line(s) */ +#define TARGET_TIOCMIWAIT 0x545C +/* read serial port inline interrupt counts */ +#define TARGET_TIOCGICOUNT 0x545D +#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ +#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ + +/* + * Some arches already define TARGET_FIOQSIZE due to a historical + * conflict with a Hayes modem-specific ioctl value. + */ +#ifndef TARGET_FIOQSIZE +# define TARGET_FIOQSIZE 0x5460 +#endif + +/* Used for packet mode */ +#define TARGET_TIOCPKT_DATA 0 +#define TARGET_TIOCPKT_FLUSHREAD 1 +#define TARGET_TIOCPKT_FLUSHWRITE 2 +#define TARGET_TIOCPKT_STOP 4 +#define TARGET_TIOCPKT_START 8 +#define TARGET_TIOCPKT_NOSTOP 16 +#define TARGET_TIOCPKT_DOSTOP 32 +#define TARGET_TIOCPKT_IOCTL 64 + +#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + +#endif diff --git a/linux-user/host/ppc64/safe-syscall.inc.S b/linux-user/host/ppc64/safe-syscall.inc.S index 8ed73a5b8683d9f7a3dfeeca5eef9831d10f5b95..875133173bb699870db75144b5d1541c570f3863 100644 --- a/linux-user/host/ppc64/safe-syscall.inc.S +++ b/linux-user/host/ppc64/safe-syscall.inc.S @@ -84,7 +84,7 @@ safe_syscall_end: /* code path when we didn't execute the syscall */ 0: addi 3, 0, -TARGET_ERESTARTSYS - ld 14, 16(1) /* restore r14 to its orginal value */ + ld 14, 16(1) /* restore r14 to its original value */ blr .cfi_endproc diff --git a/linux-user/hppa/Makefile.objs b/linux-user/hppa/Makefile.objs deleted file mode 100644 index f8368be6f314c2046b6a484d97b99ba9123c00f8..0000000000000000000000000000000000000000 --- a/linux-user/hppa/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -generated-files-y += linux-user/hppa/syscall_nr.h - -syshdr := $(SRC_PATH)/linux-user/hppa/syscallhdr.sh -%/syscall_nr.h: $(SRC_PATH)/linux-user/hppa/syscall.tbl $(syshdr) - $(call quiet-command, sh $(syshdr) $< $@ $(TARGET_SYSTBL_ABI),"GEN","$@") diff --git a/linux-user/hppa/cpu_loop.c b/linux-user/hppa/cpu_loop.c index 9915456a1dc09879d41930c6c1614e017daa8f33..d7e1ec7722031c6ce614d7ec46ddfba0cbe7da55 100644 --- a/linux-user/hppa/cpu_loop.c +++ b/linux-user/hppa/cpu_loop.c @@ -39,7 +39,7 @@ static abi_ulong hppa_lws(CPUHPPAState *env) } old = tswap32(old); new = tswap32(new); - ret = atomic_cmpxchg((uint32_t *)g2h(addr), old, new); + ret = qatomic_cmpxchg((uint32_t *)g2h(addr), old, new); ret = tswap32(ret); break; @@ -60,19 +60,19 @@ static abi_ulong hppa_lws(CPUHPPAState *env) case 0: old = *(uint8_t *)g2h(old); new = *(uint8_t *)g2h(new); - ret = atomic_cmpxchg((uint8_t *)g2h(addr), old, new); + ret = qatomic_cmpxchg((uint8_t *)g2h(addr), old, new); ret = ret != old; break; case 1: old = *(uint16_t *)g2h(old); new = *(uint16_t *)g2h(new); - ret = atomic_cmpxchg((uint16_t *)g2h(addr), old, new); + ret = qatomic_cmpxchg((uint16_t *)g2h(addr), old, new); ret = ret != old; break; case 2: old = *(uint32_t *)g2h(old); new = *(uint32_t *)g2h(new); - ret = atomic_cmpxchg((uint32_t *)g2h(addr), old, new); + ret = qatomic_cmpxchg((uint32_t *)g2h(addr), old, new); ret = ret != old; break; case 3: @@ -81,7 +81,8 @@ static abi_ulong hppa_lws(CPUHPPAState *env) o64 = *(uint64_t *)g2h(old); n64 = *(uint64_t *)g2h(new); #ifdef CONFIG_ATOMIC64 - r64 = atomic_cmpxchg__nocheck((uint64_t *)g2h(addr), o64, n64); + r64 = qatomic_cmpxchg__nocheck((uint64_t *)g2h(addr), + o64, n64); ret = r64 != o64; #else start_exclusive(); diff --git a/linux-user/hppa/meson.build b/linux-user/hppa/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..4709508a098e6335676dd8c9419467cfd4147cbb --- /dev/null +++ b/linux-user/hppa/meson.build @@ -0,0 +1,5 @@ +syscall_nr_generators += { + 'hppa': generator(sh, + arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ], + output: '@BASENAME@_nr.h') +} diff --git a/linux-user/hppa/syscall.tbl b/linux-user/hppa/syscall.tbl index 52a15f5cd1308d222a821a231244d0471ab7be07..def64d221cd4fb2e22fa541aa130198cc7a3fa9b 100644 --- a/linux-user/hppa/syscall.tbl +++ b/linux-user/hppa/syscall.tbl @@ -163,7 +163,7 @@ 146 common writev sys_writev compat_sys_writev 147 common getsid sys_getsid 148 common fdatasync sys_fdatasync -149 common _sysctl sys_sysctl compat_sys_sysctl +149 common _sysctl sys_ni_syscall 150 common mlock sys_mlock 151 common munlock sys_munlock 152 common mlockall sys_mlockall @@ -198,8 +198,8 @@ 178 common rt_sigqueueinfo sys_rt_sigqueueinfo compat_sys_rt_sigqueueinfo 179 common rt_sigsuspend sys_rt_sigsuspend compat_sys_rt_sigsuspend 180 common chown sys_chown -181 common setsockopt sys_setsockopt compat_sys_setsockopt -182 common getsockopt sys_getsockopt compat_sys_getsockopt +181 common setsockopt sys_setsockopt sys_setsockopt +182 common getsockopt sys_getsockopt sys_getsockopt 183 common sendmsg sys_sendmsg compat_sys_sendmsg 184 common recvmsg sys_recvmsg compat_sys_recvmsg 185 common semop sys_semop @@ -433,5 +433,7 @@ 433 common fspick sys_fspick 434 common pidfd_open sys_pidfd_open 435 common clone3 sys_clone3_wrapper +436 common close_range sys_close_range 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd +439 common faccessat2 sys_faccessat2 diff --git a/linux-user/hppa/target_cpu.h b/linux-user/hppa/target_cpu.h index 71654b3cd4c0ba8a39062b45a0f6a960a23c89a3..aacf3e9e024aeea3642318fc61a74a53ec56ab7e 100644 --- a/linux-user/hppa/target_cpu.h +++ b/linux-user/hppa/target_cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/hppa/target_signal.h b/linux-user/hppa/target_signal.h index c2a0102ed73d126b10554a2330b2e2c1a51793cb..c52a3ea5794bdc4e1eb8ce632b43460dd8956928 100644 --- a/linux-user/hppa/target_signal.h +++ b/linux-user/hppa/target_signal.h @@ -44,7 +44,7 @@ typedef struct target_sigaltstack { abi_ulong ss_sp; - int32_t ss_flags; + abi_int ss_flags; abi_ulong ss_size; } target_stack_t; diff --git a/linux-user/hppa/target_structs.h b/linux-user/hppa/target_structs.h index b560b1872bdb7defa59a7f1112924cdbd815f5d7..b7cf4a3b0f44545f42d2b53d6a048c17f53c540f 100644 --- a/linux-user/hppa/target_structs.h +++ b/linux-user/hppa/target_structs.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/hppa/target_syscall.h b/linux-user/hppa/target_syscall.h index e2f366839d809789cb2a3a95fb67306b3f8eca45..f34e05edb57b176e2a9b7ebae3616c0674fbaf72 100644 --- a/linux-user/hppa/target_syscall.h +++ b/linux-user/hppa/target_syscall.h @@ -23,8 +23,9 @@ struct target_pt_regs { #define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_CLONE_BACKWARDS #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 #undef TARGET_ENOMSG #define TARGET_ENOMSG 35 diff --git a/linux-user/hppa/termbits.h b/linux-user/hppa/termbits.h index 8fba839dd4e6fa29662760808506fe620a074b8d..11fd4eed6232c95433c076bb775c3c0f84ec92e5 100644 --- a/linux-user/hppa/termbits.h +++ b/linux-user/hppa/termbits.h @@ -5,13 +5,17 @@ #define TARGET_NCCS 19 +typedef unsigned char target_cc_t; /* cc_t */ +typedef unsigned int target_speed_t; /* speed_t */ +typedef unsigned int target_tcflag_t; /* tcflag_t */ + struct target_termios { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ + target_tcflag_t c_iflag; /* input mode flags */ + target_tcflag_t c_oflag; /* output mode flags */ + target_tcflag_t c_cflag; /* control mode flags */ + target_tcflag_t c_lflag; /* local mode flags */ + target_cc_t c_line; /* line discipline */ + target_cc_t c_cc[TARGET_NCCS]; /* control characters */ }; /* c_iflag bits */ @@ -120,6 +124,7 @@ struct target_termios { #define TARGET_FLUSHO 0010000 #define TARGET_PENDIN 0040000 #define TARGET_IEXTEN 0100000 +#define TARGET_EXTPROC 0200000 /* c_cc character offsets */ #define TARGET_VINTR 0 diff --git a/linux-user/i386/Makefile.objs b/linux-user/i386/Makefile.objs deleted file mode 100644 index c25cf17bfb6401880a2c4b7c64653ba06c79e531..0000000000000000000000000000000000000000 --- a/linux-user/i386/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -generated-files-y += linux-user/i386/syscall_nr.h - -syshdr := $(SRC_PATH)/linux-user/i386/syscallhdr.sh -%/syscall_nr.h: $(SRC_PATH)/linux-user/i386/syscall_32.tbl $(syshdr) - $(call quiet-command, sh $(syshdr) $< $@ $(TARGET_SYSTBL_ABI),"GEN","$@") diff --git a/linux-user/i386/meson.build b/linux-user/i386/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..ee523019a578da6b2bd0a0c0931c4f16b97a169c --- /dev/null +++ b/linux-user/i386/meson.build @@ -0,0 +1,5 @@ +syscall_nr_generators += { + 'i386': generator(sh, + arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ], + output: '@BASENAME@_nr.h') +} diff --git a/linux-user/i386/syscall_32.tbl b/linux-user/i386/syscall_32.tbl index c17cb77eb15093ea0c6e34f293a7214fcd75da61..9d11028736661bc5ed583eb7ed5e89c1c3ef2753 100644 --- a/linux-user/i386/syscall_32.tbl +++ b/linux-user/i386/syscall_32.tbl @@ -11,434 +11,436 @@ # # The abi is always "i386" for this file. # -0 i386 restart_syscall sys_restart_syscall __ia32_sys_restart_syscall -1 i386 exit sys_exit __ia32_sys_exit -2 i386 fork sys_fork __ia32_sys_fork -3 i386 read sys_read __ia32_sys_read -4 i386 write sys_write __ia32_sys_write -5 i386 open sys_open __ia32_compat_sys_open -6 i386 close sys_close __ia32_sys_close -7 i386 waitpid sys_waitpid __ia32_sys_waitpid -8 i386 creat sys_creat __ia32_sys_creat -9 i386 link sys_link __ia32_sys_link -10 i386 unlink sys_unlink __ia32_sys_unlink -11 i386 execve sys_execve __ia32_compat_sys_execve -12 i386 chdir sys_chdir __ia32_sys_chdir -13 i386 time sys_time32 __ia32_sys_time32 -14 i386 mknod sys_mknod __ia32_sys_mknod -15 i386 chmod sys_chmod __ia32_sys_chmod -16 i386 lchown sys_lchown16 __ia32_sys_lchown16 +0 i386 restart_syscall sys_restart_syscall +1 i386 exit sys_exit +2 i386 fork sys_fork +3 i386 read sys_read +4 i386 write sys_write +5 i386 open sys_open compat_sys_open +6 i386 close sys_close +7 i386 waitpid sys_waitpid +8 i386 creat sys_creat +9 i386 link sys_link +10 i386 unlink sys_unlink +11 i386 execve sys_execve compat_sys_execve +12 i386 chdir sys_chdir +13 i386 time sys_time32 +14 i386 mknod sys_mknod +15 i386 chmod sys_chmod +16 i386 lchown sys_lchown16 17 i386 break -18 i386 oldstat sys_stat __ia32_sys_stat -19 i386 lseek sys_lseek __ia32_compat_sys_lseek -20 i386 getpid sys_getpid __ia32_sys_getpid -21 i386 mount sys_mount __ia32_compat_sys_mount -22 i386 umount sys_oldumount __ia32_sys_oldumount -23 i386 setuid sys_setuid16 __ia32_sys_setuid16 -24 i386 getuid sys_getuid16 __ia32_sys_getuid16 -25 i386 stime sys_stime32 __ia32_sys_stime32 -26 i386 ptrace sys_ptrace __ia32_compat_sys_ptrace -27 i386 alarm sys_alarm __ia32_sys_alarm -28 i386 oldfstat sys_fstat __ia32_sys_fstat -29 i386 pause sys_pause __ia32_sys_pause -30 i386 utime sys_utime32 __ia32_sys_utime32 +18 i386 oldstat sys_stat +19 i386 lseek sys_lseek compat_sys_lseek +20 i386 getpid sys_getpid +21 i386 mount sys_mount compat_sys_mount +22 i386 umount sys_oldumount +23 i386 setuid sys_setuid16 +24 i386 getuid sys_getuid16 +25 i386 stime sys_stime32 +26 i386 ptrace sys_ptrace compat_sys_ptrace +27 i386 alarm sys_alarm +28 i386 oldfstat sys_fstat +29 i386 pause sys_pause +30 i386 utime sys_utime32 31 i386 stty 32 i386 gtty -33 i386 access sys_access __ia32_sys_access -34 i386 nice sys_nice __ia32_sys_nice +33 i386 access sys_access +34 i386 nice sys_nice 35 i386 ftime -36 i386 sync sys_sync __ia32_sys_sync -37 i386 kill sys_kill __ia32_sys_kill -38 i386 rename sys_rename __ia32_sys_rename -39 i386 mkdir sys_mkdir __ia32_sys_mkdir -40 i386 rmdir sys_rmdir __ia32_sys_rmdir -41 i386 dup sys_dup __ia32_sys_dup -42 i386 pipe sys_pipe __ia32_sys_pipe -43 i386 times sys_times __ia32_compat_sys_times +36 i386 sync sys_sync +37 i386 kill sys_kill +38 i386 rename sys_rename +39 i386 mkdir sys_mkdir +40 i386 rmdir sys_rmdir +41 i386 dup sys_dup +42 i386 pipe sys_pipe +43 i386 times sys_times compat_sys_times 44 i386 prof -45 i386 brk sys_brk __ia32_sys_brk -46 i386 setgid sys_setgid16 __ia32_sys_setgid16 -47 i386 getgid sys_getgid16 __ia32_sys_getgid16 -48 i386 signal sys_signal __ia32_sys_signal -49 i386 geteuid sys_geteuid16 __ia32_sys_geteuid16 -50 i386 getegid sys_getegid16 __ia32_sys_getegid16 -51 i386 acct sys_acct __ia32_sys_acct -52 i386 umount2 sys_umount __ia32_sys_umount +45 i386 brk sys_brk +46 i386 setgid sys_setgid16 +47 i386 getgid sys_getgid16 +48 i386 signal sys_signal +49 i386 geteuid sys_geteuid16 +50 i386 getegid sys_getegid16 +51 i386 acct sys_acct +52 i386 umount2 sys_umount 53 i386 lock -54 i386 ioctl sys_ioctl __ia32_compat_sys_ioctl -55 i386 fcntl sys_fcntl __ia32_compat_sys_fcntl64 +54 i386 ioctl sys_ioctl compat_sys_ioctl +55 i386 fcntl sys_fcntl compat_sys_fcntl64 56 i386 mpx -57 i386 setpgid sys_setpgid __ia32_sys_setpgid +57 i386 setpgid sys_setpgid 58 i386 ulimit -59 i386 oldolduname sys_olduname __ia32_sys_olduname -60 i386 umask sys_umask __ia32_sys_umask -61 i386 chroot sys_chroot __ia32_sys_chroot -62 i386 ustat sys_ustat __ia32_compat_sys_ustat -63 i386 dup2 sys_dup2 __ia32_sys_dup2 -64 i386 getppid sys_getppid __ia32_sys_getppid -65 i386 getpgrp sys_getpgrp __ia32_sys_getpgrp -66 i386 setsid sys_setsid __ia32_sys_setsid -67 i386 sigaction sys_sigaction __ia32_compat_sys_sigaction -68 i386 sgetmask sys_sgetmask __ia32_sys_sgetmask -69 i386 ssetmask sys_ssetmask __ia32_sys_ssetmask -70 i386 setreuid sys_setreuid16 __ia32_sys_setreuid16 -71 i386 setregid sys_setregid16 __ia32_sys_setregid16 -72 i386 sigsuspend sys_sigsuspend __ia32_sys_sigsuspend -73 i386 sigpending sys_sigpending __ia32_compat_sys_sigpending -74 i386 sethostname sys_sethostname __ia32_sys_sethostname -75 i386 setrlimit sys_setrlimit __ia32_compat_sys_setrlimit -76 i386 getrlimit sys_old_getrlimit __ia32_compat_sys_old_getrlimit -77 i386 getrusage sys_getrusage __ia32_compat_sys_getrusage -78 i386 gettimeofday sys_gettimeofday __ia32_compat_sys_gettimeofday -79 i386 settimeofday sys_settimeofday __ia32_compat_sys_settimeofday -80 i386 getgroups sys_getgroups16 __ia32_sys_getgroups16 -81 i386 setgroups sys_setgroups16 __ia32_sys_setgroups16 -82 i386 select sys_old_select __ia32_compat_sys_old_select -83 i386 symlink sys_symlink __ia32_sys_symlink -84 i386 oldlstat sys_lstat __ia32_sys_lstat -85 i386 readlink sys_readlink __ia32_sys_readlink -86 i386 uselib sys_uselib __ia32_sys_uselib -87 i386 swapon sys_swapon __ia32_sys_swapon -88 i386 reboot sys_reboot __ia32_sys_reboot -89 i386 readdir sys_old_readdir __ia32_compat_sys_old_readdir -90 i386 mmap sys_old_mmap __ia32_compat_sys_x86_mmap -91 i386 munmap sys_munmap __ia32_sys_munmap -92 i386 truncate sys_truncate __ia32_compat_sys_truncate -93 i386 ftruncate sys_ftruncate __ia32_compat_sys_ftruncate -94 i386 fchmod sys_fchmod __ia32_sys_fchmod -95 i386 fchown sys_fchown16 __ia32_sys_fchown16 -96 i386 getpriority sys_getpriority __ia32_sys_getpriority -97 i386 setpriority sys_setpriority __ia32_sys_setpriority +59 i386 oldolduname sys_olduname +60 i386 umask sys_umask +61 i386 chroot sys_chroot +62 i386 ustat sys_ustat compat_sys_ustat +63 i386 dup2 sys_dup2 +64 i386 getppid sys_getppid +65 i386 getpgrp sys_getpgrp +66 i386 setsid sys_setsid +67 i386 sigaction sys_sigaction compat_sys_sigaction +68 i386 sgetmask sys_sgetmask +69 i386 ssetmask sys_ssetmask +70 i386 setreuid sys_setreuid16 +71 i386 setregid sys_setregid16 +72 i386 sigsuspend sys_sigsuspend +73 i386 sigpending sys_sigpending compat_sys_sigpending +74 i386 sethostname sys_sethostname +75 i386 setrlimit sys_setrlimit compat_sys_setrlimit +76 i386 getrlimit sys_old_getrlimit compat_sys_old_getrlimit +77 i386 getrusage sys_getrusage compat_sys_getrusage +78 i386 gettimeofday sys_gettimeofday compat_sys_gettimeofday +79 i386 settimeofday sys_settimeofday compat_sys_settimeofday +80 i386 getgroups sys_getgroups16 +81 i386 setgroups sys_setgroups16 +82 i386 select sys_old_select compat_sys_old_select +83 i386 symlink sys_symlink +84 i386 oldlstat sys_lstat +85 i386 readlink sys_readlink +86 i386 uselib sys_uselib +87 i386 swapon sys_swapon +88 i386 reboot sys_reboot +89 i386 readdir sys_old_readdir compat_sys_old_readdir +90 i386 mmap sys_old_mmap compat_sys_ia32_mmap +91 i386 munmap sys_munmap +92 i386 truncate sys_truncate compat_sys_truncate +93 i386 ftruncate sys_ftruncate compat_sys_ftruncate +94 i386 fchmod sys_fchmod +95 i386 fchown sys_fchown16 +96 i386 getpriority sys_getpriority +97 i386 setpriority sys_setpriority 98 i386 profil -99 i386 statfs sys_statfs __ia32_compat_sys_statfs -100 i386 fstatfs sys_fstatfs __ia32_compat_sys_fstatfs -101 i386 ioperm sys_ioperm __ia32_sys_ioperm -102 i386 socketcall sys_socketcall __ia32_compat_sys_socketcall -103 i386 syslog sys_syslog __ia32_sys_syslog -104 i386 setitimer sys_setitimer __ia32_compat_sys_setitimer -105 i386 getitimer sys_getitimer __ia32_compat_sys_getitimer -106 i386 stat sys_newstat __ia32_compat_sys_newstat -107 i386 lstat sys_newlstat __ia32_compat_sys_newlstat -108 i386 fstat sys_newfstat __ia32_compat_sys_newfstat -109 i386 olduname sys_uname __ia32_sys_uname -110 i386 iopl sys_iopl __ia32_sys_iopl -111 i386 vhangup sys_vhangup __ia32_sys_vhangup +99 i386 statfs sys_statfs compat_sys_statfs +100 i386 fstatfs sys_fstatfs compat_sys_fstatfs +101 i386 ioperm sys_ioperm +102 i386 socketcall sys_socketcall compat_sys_socketcall +103 i386 syslog sys_syslog +104 i386 setitimer sys_setitimer compat_sys_setitimer +105 i386 getitimer sys_getitimer compat_sys_getitimer +106 i386 stat sys_newstat compat_sys_newstat +107 i386 lstat sys_newlstat compat_sys_newlstat +108 i386 fstat sys_newfstat compat_sys_newfstat +109 i386 olduname sys_uname +110 i386 iopl sys_iopl +111 i386 vhangup sys_vhangup 112 i386 idle -113 i386 vm86old sys_vm86old __ia32_sys_ni_syscall -114 i386 wait4 sys_wait4 __ia32_compat_sys_wait4 -115 i386 swapoff sys_swapoff __ia32_sys_swapoff -116 i386 sysinfo sys_sysinfo __ia32_compat_sys_sysinfo -117 i386 ipc sys_ipc __ia32_compat_sys_ipc -118 i386 fsync sys_fsync __ia32_sys_fsync -119 i386 sigreturn sys_sigreturn __ia32_compat_sys_sigreturn -120 i386 clone sys_clone __ia32_compat_sys_x86_clone -121 i386 setdomainname sys_setdomainname __ia32_sys_setdomainname -122 i386 uname sys_newuname __ia32_sys_newuname -123 i386 modify_ldt sys_modify_ldt __ia32_sys_modify_ldt -124 i386 adjtimex sys_adjtimex_time32 __ia32_sys_adjtimex_time32 -125 i386 mprotect sys_mprotect __ia32_sys_mprotect -126 i386 sigprocmask sys_sigprocmask __ia32_compat_sys_sigprocmask +113 i386 vm86old sys_vm86old sys_ni_syscall +114 i386 wait4 sys_wait4 compat_sys_wait4 +115 i386 swapoff sys_swapoff +116 i386 sysinfo sys_sysinfo compat_sys_sysinfo +117 i386 ipc sys_ipc compat_sys_ipc +118 i386 fsync sys_fsync +119 i386 sigreturn sys_sigreturn compat_sys_sigreturn +120 i386 clone sys_clone compat_sys_ia32_clone +121 i386 setdomainname sys_setdomainname +122 i386 uname sys_newuname +123 i386 modify_ldt sys_modify_ldt +124 i386 adjtimex sys_adjtimex_time32 +125 i386 mprotect sys_mprotect +126 i386 sigprocmask sys_sigprocmask compat_sys_sigprocmask 127 i386 create_module -128 i386 init_module sys_init_module __ia32_sys_init_module -129 i386 delete_module sys_delete_module __ia32_sys_delete_module +128 i386 init_module sys_init_module +129 i386 delete_module sys_delete_module 130 i386 get_kernel_syms -131 i386 quotactl sys_quotactl __ia32_compat_sys_quotactl32 -132 i386 getpgid sys_getpgid __ia32_sys_getpgid -133 i386 fchdir sys_fchdir __ia32_sys_fchdir -134 i386 bdflush sys_bdflush __ia32_sys_bdflush -135 i386 sysfs sys_sysfs __ia32_sys_sysfs -136 i386 personality sys_personality __ia32_sys_personality +131 i386 quotactl sys_quotactl compat_sys_quotactl32 +132 i386 getpgid sys_getpgid +133 i386 fchdir sys_fchdir +134 i386 bdflush sys_bdflush +135 i386 sysfs sys_sysfs +136 i386 personality sys_personality 137 i386 afs_syscall -138 i386 setfsuid sys_setfsuid16 __ia32_sys_setfsuid16 -139 i386 setfsgid sys_setfsgid16 __ia32_sys_setfsgid16 -140 i386 _llseek sys_llseek __ia32_sys_llseek -141 i386 getdents sys_getdents __ia32_compat_sys_getdents -142 i386 _newselect sys_select __ia32_compat_sys_select -143 i386 flock sys_flock __ia32_sys_flock -144 i386 msync sys_msync __ia32_sys_msync -145 i386 readv sys_readv __ia32_compat_sys_readv -146 i386 writev sys_writev __ia32_compat_sys_writev -147 i386 getsid sys_getsid __ia32_sys_getsid -148 i386 fdatasync sys_fdatasync __ia32_sys_fdatasync -149 i386 _sysctl sys_sysctl __ia32_compat_sys_sysctl -150 i386 mlock sys_mlock __ia32_sys_mlock -151 i386 munlock sys_munlock __ia32_sys_munlock -152 i386 mlockall sys_mlockall __ia32_sys_mlockall -153 i386 munlockall sys_munlockall __ia32_sys_munlockall -154 i386 sched_setparam sys_sched_setparam __ia32_sys_sched_setparam -155 i386 sched_getparam sys_sched_getparam __ia32_sys_sched_getparam -156 i386 sched_setscheduler sys_sched_setscheduler __ia32_sys_sched_setscheduler -157 i386 sched_getscheduler sys_sched_getscheduler __ia32_sys_sched_getscheduler -158 i386 sched_yield sys_sched_yield __ia32_sys_sched_yield -159 i386 sched_get_priority_max sys_sched_get_priority_max __ia32_sys_sched_get_priority_max -160 i386 sched_get_priority_min sys_sched_get_priority_min __ia32_sys_sched_get_priority_min -161 i386 sched_rr_get_interval sys_sched_rr_get_interval_time32 __ia32_sys_sched_rr_get_interval_time32 -162 i386 nanosleep sys_nanosleep_time32 __ia32_sys_nanosleep_time32 -163 i386 mremap sys_mremap __ia32_sys_mremap -164 i386 setresuid sys_setresuid16 __ia32_sys_setresuid16 -165 i386 getresuid sys_getresuid16 __ia32_sys_getresuid16 -166 i386 vm86 sys_vm86 __ia32_sys_ni_syscall +138 i386 setfsuid sys_setfsuid16 +139 i386 setfsgid sys_setfsgid16 +140 i386 _llseek sys_llseek +141 i386 getdents sys_getdents compat_sys_getdents +142 i386 _newselect sys_select compat_sys_select +143 i386 flock sys_flock +144 i386 msync sys_msync +145 i386 readv sys_readv compat_sys_readv +146 i386 writev sys_writev compat_sys_writev +147 i386 getsid sys_getsid +148 i386 fdatasync sys_fdatasync +149 i386 _sysctl sys_ni_syscall +150 i386 mlock sys_mlock +151 i386 munlock sys_munlock +152 i386 mlockall sys_mlockall +153 i386 munlockall sys_munlockall +154 i386 sched_setparam sys_sched_setparam +155 i386 sched_getparam sys_sched_getparam +156 i386 sched_setscheduler sys_sched_setscheduler +157 i386 sched_getscheduler sys_sched_getscheduler +158 i386 sched_yield sys_sched_yield +159 i386 sched_get_priority_max sys_sched_get_priority_max +160 i386 sched_get_priority_min sys_sched_get_priority_min +161 i386 sched_rr_get_interval sys_sched_rr_get_interval_time32 +162 i386 nanosleep sys_nanosleep_time32 +163 i386 mremap sys_mremap +164 i386 setresuid sys_setresuid16 +165 i386 getresuid sys_getresuid16 +166 i386 vm86 sys_vm86 sys_ni_syscall 167 i386 query_module -168 i386 poll sys_poll __ia32_sys_poll +168 i386 poll sys_poll 169 i386 nfsservctl -170 i386 setresgid sys_setresgid16 __ia32_sys_setresgid16 -171 i386 getresgid sys_getresgid16 __ia32_sys_getresgid16 -172 i386 prctl sys_prctl __ia32_sys_prctl -173 i386 rt_sigreturn sys_rt_sigreturn __ia32_compat_sys_rt_sigreturn -174 i386 rt_sigaction sys_rt_sigaction __ia32_compat_sys_rt_sigaction -175 i386 rt_sigprocmask sys_rt_sigprocmask __ia32_compat_sys_rt_sigprocmask -176 i386 rt_sigpending sys_rt_sigpending __ia32_compat_sys_rt_sigpending -177 i386 rt_sigtimedwait sys_rt_sigtimedwait_time32 __ia32_compat_sys_rt_sigtimedwait_time32 -178 i386 rt_sigqueueinfo sys_rt_sigqueueinfo __ia32_compat_sys_rt_sigqueueinfo -179 i386 rt_sigsuspend sys_rt_sigsuspend __ia32_compat_sys_rt_sigsuspend -180 i386 pread64 sys_pread64 __ia32_compat_sys_x86_pread -181 i386 pwrite64 sys_pwrite64 __ia32_compat_sys_x86_pwrite -182 i386 chown sys_chown16 __ia32_sys_chown16 -183 i386 getcwd sys_getcwd __ia32_sys_getcwd -184 i386 capget sys_capget __ia32_sys_capget -185 i386 capset sys_capset __ia32_sys_capset -186 i386 sigaltstack sys_sigaltstack __ia32_compat_sys_sigaltstack -187 i386 sendfile sys_sendfile __ia32_compat_sys_sendfile +170 i386 setresgid sys_setresgid16 +171 i386 getresgid sys_getresgid16 +172 i386 prctl sys_prctl +173 i386 rt_sigreturn sys_rt_sigreturn compat_sys_rt_sigreturn +174 i386 rt_sigaction sys_rt_sigaction compat_sys_rt_sigaction +175 i386 rt_sigprocmask sys_rt_sigprocmask compat_sys_rt_sigprocmask +176 i386 rt_sigpending sys_rt_sigpending compat_sys_rt_sigpending +177 i386 rt_sigtimedwait sys_rt_sigtimedwait_time32 compat_sys_rt_sigtimedwait_time32 +178 i386 rt_sigqueueinfo sys_rt_sigqueueinfo compat_sys_rt_sigqueueinfo +179 i386 rt_sigsuspend sys_rt_sigsuspend compat_sys_rt_sigsuspend +180 i386 pread64 sys_ia32_pread64 +181 i386 pwrite64 sys_ia32_pwrite64 +182 i386 chown sys_chown16 +183 i386 getcwd sys_getcwd +184 i386 capget sys_capget +185 i386 capset sys_capset +186 i386 sigaltstack sys_sigaltstack compat_sys_sigaltstack +187 i386 sendfile sys_sendfile compat_sys_sendfile 188 i386 getpmsg 189 i386 putpmsg -190 i386 vfork sys_vfork __ia32_sys_vfork -191 i386 ugetrlimit sys_getrlimit __ia32_compat_sys_getrlimit -192 i386 mmap2 sys_mmap_pgoff __ia32_sys_mmap_pgoff -193 i386 truncate64 sys_truncate64 __ia32_compat_sys_x86_truncate64 -194 i386 ftruncate64 sys_ftruncate64 __ia32_compat_sys_x86_ftruncate64 -195 i386 stat64 sys_stat64 __ia32_compat_sys_x86_stat64 -196 i386 lstat64 sys_lstat64 __ia32_compat_sys_x86_lstat64 -197 i386 fstat64 sys_fstat64 __ia32_compat_sys_x86_fstat64 -198 i386 lchown32 sys_lchown __ia32_sys_lchown -199 i386 getuid32 sys_getuid __ia32_sys_getuid -200 i386 getgid32 sys_getgid __ia32_sys_getgid -201 i386 geteuid32 sys_geteuid __ia32_sys_geteuid -202 i386 getegid32 sys_getegid __ia32_sys_getegid -203 i386 setreuid32 sys_setreuid __ia32_sys_setreuid -204 i386 setregid32 sys_setregid __ia32_sys_setregid -205 i386 getgroups32 sys_getgroups __ia32_sys_getgroups -206 i386 setgroups32 sys_setgroups __ia32_sys_setgroups -207 i386 fchown32 sys_fchown __ia32_sys_fchown -208 i386 setresuid32 sys_setresuid __ia32_sys_setresuid -209 i386 getresuid32 sys_getresuid __ia32_sys_getresuid -210 i386 setresgid32 sys_setresgid __ia32_sys_setresgid -211 i386 getresgid32 sys_getresgid __ia32_sys_getresgid -212 i386 chown32 sys_chown __ia32_sys_chown -213 i386 setuid32 sys_setuid __ia32_sys_setuid -214 i386 setgid32 sys_setgid __ia32_sys_setgid -215 i386 setfsuid32 sys_setfsuid __ia32_sys_setfsuid -216 i386 setfsgid32 sys_setfsgid __ia32_sys_setfsgid -217 i386 pivot_root sys_pivot_root __ia32_sys_pivot_root -218 i386 mincore sys_mincore __ia32_sys_mincore -219 i386 madvise sys_madvise __ia32_sys_madvise -220 i386 getdents64 sys_getdents64 __ia32_sys_getdents64 -221 i386 fcntl64 sys_fcntl64 __ia32_compat_sys_fcntl64 +190 i386 vfork sys_vfork +191 i386 ugetrlimit sys_getrlimit compat_sys_getrlimit +192 i386 mmap2 sys_mmap_pgoff +193 i386 truncate64 sys_ia32_truncate64 +194 i386 ftruncate64 sys_ia32_ftruncate64 +195 i386 stat64 sys_stat64 compat_sys_ia32_stat64 +196 i386 lstat64 sys_lstat64 compat_sys_ia32_lstat64 +197 i386 fstat64 sys_fstat64 compat_sys_ia32_fstat64 +198 i386 lchown32 sys_lchown +199 i386 getuid32 sys_getuid +200 i386 getgid32 sys_getgid +201 i386 geteuid32 sys_geteuid +202 i386 getegid32 sys_getegid +203 i386 setreuid32 sys_setreuid +204 i386 setregid32 sys_setregid +205 i386 getgroups32 sys_getgroups +206 i386 setgroups32 sys_setgroups +207 i386 fchown32 sys_fchown +208 i386 setresuid32 sys_setresuid +209 i386 getresuid32 sys_getresuid +210 i386 setresgid32 sys_setresgid +211 i386 getresgid32 sys_getresgid +212 i386 chown32 sys_chown +213 i386 setuid32 sys_setuid +214 i386 setgid32 sys_setgid +215 i386 setfsuid32 sys_setfsuid +216 i386 setfsgid32 sys_setfsgid +217 i386 pivot_root sys_pivot_root +218 i386 mincore sys_mincore +219 i386 madvise sys_madvise +220 i386 getdents64 sys_getdents64 +221 i386 fcntl64 sys_fcntl64 compat_sys_fcntl64 # 222 is unused # 223 is unused -224 i386 gettid sys_gettid __ia32_sys_gettid -225 i386 readahead sys_readahead __ia32_compat_sys_x86_readahead -226 i386 setxattr sys_setxattr __ia32_sys_setxattr -227 i386 lsetxattr sys_lsetxattr __ia32_sys_lsetxattr -228 i386 fsetxattr sys_fsetxattr __ia32_sys_fsetxattr -229 i386 getxattr sys_getxattr __ia32_sys_getxattr -230 i386 lgetxattr sys_lgetxattr __ia32_sys_lgetxattr -231 i386 fgetxattr sys_fgetxattr __ia32_sys_fgetxattr -232 i386 listxattr sys_listxattr __ia32_sys_listxattr -233 i386 llistxattr sys_llistxattr __ia32_sys_llistxattr -234 i386 flistxattr sys_flistxattr __ia32_sys_flistxattr -235 i386 removexattr sys_removexattr __ia32_sys_removexattr -236 i386 lremovexattr sys_lremovexattr __ia32_sys_lremovexattr -237 i386 fremovexattr sys_fremovexattr __ia32_sys_fremovexattr -238 i386 tkill sys_tkill __ia32_sys_tkill -239 i386 sendfile64 sys_sendfile64 __ia32_sys_sendfile64 -240 i386 futex sys_futex_time32 __ia32_sys_futex_time32 -241 i386 sched_setaffinity sys_sched_setaffinity __ia32_compat_sys_sched_setaffinity -242 i386 sched_getaffinity sys_sched_getaffinity __ia32_compat_sys_sched_getaffinity -243 i386 set_thread_area sys_set_thread_area __ia32_sys_set_thread_area -244 i386 get_thread_area sys_get_thread_area __ia32_sys_get_thread_area -245 i386 io_setup sys_io_setup __ia32_compat_sys_io_setup -246 i386 io_destroy sys_io_destroy __ia32_sys_io_destroy -247 i386 io_getevents sys_io_getevents_time32 __ia32_sys_io_getevents_time32 -248 i386 io_submit sys_io_submit __ia32_compat_sys_io_submit -249 i386 io_cancel sys_io_cancel __ia32_sys_io_cancel -250 i386 fadvise64 sys_fadvise64 __ia32_compat_sys_x86_fadvise64 +224 i386 gettid sys_gettid +225 i386 readahead sys_ia32_readahead +226 i386 setxattr sys_setxattr +227 i386 lsetxattr sys_lsetxattr +228 i386 fsetxattr sys_fsetxattr +229 i386 getxattr sys_getxattr +230 i386 lgetxattr sys_lgetxattr +231 i386 fgetxattr sys_fgetxattr +232 i386 listxattr sys_listxattr +233 i386 llistxattr sys_llistxattr +234 i386 flistxattr sys_flistxattr +235 i386 removexattr sys_removexattr +236 i386 lremovexattr sys_lremovexattr +237 i386 fremovexattr sys_fremovexattr +238 i386 tkill sys_tkill +239 i386 sendfile64 sys_sendfile64 +240 i386 futex sys_futex_time32 +241 i386 sched_setaffinity sys_sched_setaffinity compat_sys_sched_setaffinity +242 i386 sched_getaffinity sys_sched_getaffinity compat_sys_sched_getaffinity +243 i386 set_thread_area sys_set_thread_area +244 i386 get_thread_area sys_get_thread_area +245 i386 io_setup sys_io_setup compat_sys_io_setup +246 i386 io_destroy sys_io_destroy +247 i386 io_getevents sys_io_getevents_time32 +248 i386 io_submit sys_io_submit compat_sys_io_submit +249 i386 io_cancel sys_io_cancel +250 i386 fadvise64 sys_ia32_fadvise64 # 251 is available for reuse (was briefly sys_set_zone_reclaim) -252 i386 exit_group sys_exit_group __ia32_sys_exit_group -253 i386 lookup_dcookie sys_lookup_dcookie __ia32_compat_sys_lookup_dcookie -254 i386 epoll_create sys_epoll_create __ia32_sys_epoll_create -255 i386 epoll_ctl sys_epoll_ctl __ia32_sys_epoll_ctl -256 i386 epoll_wait sys_epoll_wait __ia32_sys_epoll_wait -257 i386 remap_file_pages sys_remap_file_pages __ia32_sys_remap_file_pages -258 i386 set_tid_address sys_set_tid_address __ia32_sys_set_tid_address -259 i386 timer_create sys_timer_create __ia32_compat_sys_timer_create -260 i386 timer_settime sys_timer_settime32 __ia32_sys_timer_settime32 -261 i386 timer_gettime sys_timer_gettime32 __ia32_sys_timer_gettime32 -262 i386 timer_getoverrun sys_timer_getoverrun __ia32_sys_timer_getoverrun -263 i386 timer_delete sys_timer_delete __ia32_sys_timer_delete -264 i386 clock_settime sys_clock_settime32 __ia32_sys_clock_settime32 -265 i386 clock_gettime sys_clock_gettime32 __ia32_sys_clock_gettime32 -266 i386 clock_getres sys_clock_getres_time32 __ia32_sys_clock_getres_time32 -267 i386 clock_nanosleep sys_clock_nanosleep_time32 __ia32_sys_clock_nanosleep_time32 -268 i386 statfs64 sys_statfs64 __ia32_compat_sys_statfs64 -269 i386 fstatfs64 sys_fstatfs64 __ia32_compat_sys_fstatfs64 -270 i386 tgkill sys_tgkill __ia32_sys_tgkill -271 i386 utimes sys_utimes_time32 __ia32_sys_utimes_time32 -272 i386 fadvise64_64 sys_fadvise64_64 __ia32_compat_sys_x86_fadvise64_64 +252 i386 exit_group sys_exit_group +253 i386 lookup_dcookie sys_lookup_dcookie compat_sys_lookup_dcookie +254 i386 epoll_create sys_epoll_create +255 i386 epoll_ctl sys_epoll_ctl +256 i386 epoll_wait sys_epoll_wait +257 i386 remap_file_pages sys_remap_file_pages +258 i386 set_tid_address sys_set_tid_address +259 i386 timer_create sys_timer_create compat_sys_timer_create +260 i386 timer_settime sys_timer_settime32 +261 i386 timer_gettime sys_timer_gettime32 +262 i386 timer_getoverrun sys_timer_getoverrun +263 i386 timer_delete sys_timer_delete +264 i386 clock_settime sys_clock_settime32 +265 i386 clock_gettime sys_clock_gettime32 +266 i386 clock_getres sys_clock_getres_time32 +267 i386 clock_nanosleep sys_clock_nanosleep_time32 +268 i386 statfs64 sys_statfs64 compat_sys_statfs64 +269 i386 fstatfs64 sys_fstatfs64 compat_sys_fstatfs64 +270 i386 tgkill sys_tgkill +271 i386 utimes sys_utimes_time32 +272 i386 fadvise64_64 sys_ia32_fadvise64_64 273 i386 vserver -274 i386 mbind sys_mbind __ia32_sys_mbind -275 i386 get_mempolicy sys_get_mempolicy __ia32_compat_sys_get_mempolicy -276 i386 set_mempolicy sys_set_mempolicy __ia32_sys_set_mempolicy -277 i386 mq_open sys_mq_open __ia32_compat_sys_mq_open -278 i386 mq_unlink sys_mq_unlink __ia32_sys_mq_unlink -279 i386 mq_timedsend sys_mq_timedsend_time32 __ia32_sys_mq_timedsend_time32 -280 i386 mq_timedreceive sys_mq_timedreceive_time32 __ia32_sys_mq_timedreceive_time32 -281 i386 mq_notify sys_mq_notify __ia32_compat_sys_mq_notify -282 i386 mq_getsetattr sys_mq_getsetattr __ia32_compat_sys_mq_getsetattr -283 i386 kexec_load sys_kexec_load __ia32_compat_sys_kexec_load -284 i386 waitid sys_waitid __ia32_compat_sys_waitid +274 i386 mbind sys_mbind +275 i386 get_mempolicy sys_get_mempolicy compat_sys_get_mempolicy +276 i386 set_mempolicy sys_set_mempolicy +277 i386 mq_open sys_mq_open compat_sys_mq_open +278 i386 mq_unlink sys_mq_unlink +279 i386 mq_timedsend sys_mq_timedsend_time32 +280 i386 mq_timedreceive sys_mq_timedreceive_time32 +281 i386 mq_notify sys_mq_notify compat_sys_mq_notify +282 i386 mq_getsetattr sys_mq_getsetattr compat_sys_mq_getsetattr +283 i386 kexec_load sys_kexec_load compat_sys_kexec_load +284 i386 waitid sys_waitid compat_sys_waitid # 285 sys_setaltroot -286 i386 add_key sys_add_key __ia32_sys_add_key -287 i386 request_key sys_request_key __ia32_sys_request_key -288 i386 keyctl sys_keyctl __ia32_compat_sys_keyctl -289 i386 ioprio_set sys_ioprio_set __ia32_sys_ioprio_set -290 i386 ioprio_get sys_ioprio_get __ia32_sys_ioprio_get -291 i386 inotify_init sys_inotify_init __ia32_sys_inotify_init -292 i386 inotify_add_watch sys_inotify_add_watch __ia32_sys_inotify_add_watch -293 i386 inotify_rm_watch sys_inotify_rm_watch __ia32_sys_inotify_rm_watch -294 i386 migrate_pages sys_migrate_pages __ia32_sys_migrate_pages -295 i386 openat sys_openat __ia32_compat_sys_openat -296 i386 mkdirat sys_mkdirat __ia32_sys_mkdirat -297 i386 mknodat sys_mknodat __ia32_sys_mknodat -298 i386 fchownat sys_fchownat __ia32_sys_fchownat -299 i386 futimesat sys_futimesat_time32 __ia32_sys_futimesat_time32 -300 i386 fstatat64 sys_fstatat64 __ia32_compat_sys_x86_fstatat -301 i386 unlinkat sys_unlinkat __ia32_sys_unlinkat -302 i386 renameat sys_renameat __ia32_sys_renameat -303 i386 linkat sys_linkat __ia32_sys_linkat -304 i386 symlinkat sys_symlinkat __ia32_sys_symlinkat -305 i386 readlinkat sys_readlinkat __ia32_sys_readlinkat -306 i386 fchmodat sys_fchmodat __ia32_sys_fchmodat -307 i386 faccessat sys_faccessat __ia32_sys_faccessat -308 i386 pselect6 sys_pselect6_time32 __ia32_compat_sys_pselect6_time32 -309 i386 ppoll sys_ppoll_time32 __ia32_compat_sys_ppoll_time32 -310 i386 unshare sys_unshare __ia32_sys_unshare -311 i386 set_robust_list sys_set_robust_list __ia32_compat_sys_set_robust_list -312 i386 get_robust_list sys_get_robust_list __ia32_compat_sys_get_robust_list -313 i386 splice sys_splice __ia32_sys_splice -314 i386 sync_file_range sys_sync_file_range __ia32_compat_sys_x86_sync_file_range -315 i386 tee sys_tee __ia32_sys_tee -316 i386 vmsplice sys_vmsplice __ia32_compat_sys_vmsplice -317 i386 move_pages sys_move_pages __ia32_compat_sys_move_pages -318 i386 getcpu sys_getcpu __ia32_sys_getcpu -319 i386 epoll_pwait sys_epoll_pwait __ia32_sys_epoll_pwait -320 i386 utimensat sys_utimensat_time32 __ia32_sys_utimensat_time32 -321 i386 signalfd sys_signalfd __ia32_compat_sys_signalfd -322 i386 timerfd_create sys_timerfd_create __ia32_sys_timerfd_create -323 i386 eventfd sys_eventfd __ia32_sys_eventfd -324 i386 fallocate sys_fallocate __ia32_compat_sys_x86_fallocate -325 i386 timerfd_settime sys_timerfd_settime32 __ia32_sys_timerfd_settime32 -326 i386 timerfd_gettime sys_timerfd_gettime32 __ia32_sys_timerfd_gettime32 -327 i386 signalfd4 sys_signalfd4 __ia32_compat_sys_signalfd4 -328 i386 eventfd2 sys_eventfd2 __ia32_sys_eventfd2 -329 i386 epoll_create1 sys_epoll_create1 __ia32_sys_epoll_create1 -330 i386 dup3 sys_dup3 __ia32_sys_dup3 -331 i386 pipe2 sys_pipe2 __ia32_sys_pipe2 -332 i386 inotify_init1 sys_inotify_init1 __ia32_sys_inotify_init1 -333 i386 preadv sys_preadv __ia32_compat_sys_preadv -334 i386 pwritev sys_pwritev __ia32_compat_sys_pwritev -335 i386 rt_tgsigqueueinfo sys_rt_tgsigqueueinfo __ia32_compat_sys_rt_tgsigqueueinfo -336 i386 perf_event_open sys_perf_event_open __ia32_sys_perf_event_open -337 i386 recvmmsg sys_recvmmsg_time32 __ia32_compat_sys_recvmmsg_time32 -338 i386 fanotify_init sys_fanotify_init __ia32_sys_fanotify_init -339 i386 fanotify_mark sys_fanotify_mark __ia32_compat_sys_fanotify_mark -340 i386 prlimit64 sys_prlimit64 __ia32_sys_prlimit64 -341 i386 name_to_handle_at sys_name_to_handle_at __ia32_sys_name_to_handle_at -342 i386 open_by_handle_at sys_open_by_handle_at __ia32_compat_sys_open_by_handle_at -343 i386 clock_adjtime sys_clock_adjtime32 __ia32_sys_clock_adjtime32 -344 i386 syncfs sys_syncfs __ia32_sys_syncfs -345 i386 sendmmsg sys_sendmmsg __ia32_compat_sys_sendmmsg -346 i386 setns sys_setns __ia32_sys_setns -347 i386 process_vm_readv sys_process_vm_readv __ia32_compat_sys_process_vm_readv -348 i386 process_vm_writev sys_process_vm_writev __ia32_compat_sys_process_vm_writev -349 i386 kcmp sys_kcmp __ia32_sys_kcmp -350 i386 finit_module sys_finit_module __ia32_sys_finit_module -351 i386 sched_setattr sys_sched_setattr __ia32_sys_sched_setattr -352 i386 sched_getattr sys_sched_getattr __ia32_sys_sched_getattr -353 i386 renameat2 sys_renameat2 __ia32_sys_renameat2 -354 i386 seccomp sys_seccomp __ia32_sys_seccomp -355 i386 getrandom sys_getrandom __ia32_sys_getrandom -356 i386 memfd_create sys_memfd_create __ia32_sys_memfd_create -357 i386 bpf sys_bpf __ia32_sys_bpf -358 i386 execveat sys_execveat __ia32_compat_sys_execveat -359 i386 socket sys_socket __ia32_sys_socket -360 i386 socketpair sys_socketpair __ia32_sys_socketpair -361 i386 bind sys_bind __ia32_sys_bind -362 i386 connect sys_connect __ia32_sys_connect -363 i386 listen sys_listen __ia32_sys_listen -364 i386 accept4 sys_accept4 __ia32_sys_accept4 -365 i386 getsockopt sys_getsockopt __ia32_compat_sys_getsockopt -366 i386 setsockopt sys_setsockopt __ia32_compat_sys_setsockopt -367 i386 getsockname sys_getsockname __ia32_sys_getsockname -368 i386 getpeername sys_getpeername __ia32_sys_getpeername -369 i386 sendto sys_sendto __ia32_sys_sendto -370 i386 sendmsg sys_sendmsg __ia32_compat_sys_sendmsg -371 i386 recvfrom sys_recvfrom __ia32_compat_sys_recvfrom -372 i386 recvmsg sys_recvmsg __ia32_compat_sys_recvmsg -373 i386 shutdown sys_shutdown __ia32_sys_shutdown -374 i386 userfaultfd sys_userfaultfd __ia32_sys_userfaultfd -375 i386 membarrier sys_membarrier __ia32_sys_membarrier -376 i386 mlock2 sys_mlock2 __ia32_sys_mlock2 -377 i386 copy_file_range sys_copy_file_range __ia32_sys_copy_file_range -378 i386 preadv2 sys_preadv2 __ia32_compat_sys_preadv2 -379 i386 pwritev2 sys_pwritev2 __ia32_compat_sys_pwritev2 -380 i386 pkey_mprotect sys_pkey_mprotect __ia32_sys_pkey_mprotect -381 i386 pkey_alloc sys_pkey_alloc __ia32_sys_pkey_alloc -382 i386 pkey_free sys_pkey_free __ia32_sys_pkey_free -383 i386 statx sys_statx __ia32_sys_statx -384 i386 arch_prctl sys_arch_prctl __ia32_compat_sys_arch_prctl -385 i386 io_pgetevents sys_io_pgetevents_time32 __ia32_compat_sys_io_pgetevents -386 i386 rseq sys_rseq __ia32_sys_rseq -393 i386 semget sys_semget __ia32_sys_semget -394 i386 semctl sys_semctl __ia32_compat_sys_semctl -395 i386 shmget sys_shmget __ia32_sys_shmget -396 i386 shmctl sys_shmctl __ia32_compat_sys_shmctl -397 i386 shmat sys_shmat __ia32_compat_sys_shmat -398 i386 shmdt sys_shmdt __ia32_sys_shmdt -399 i386 msgget sys_msgget __ia32_sys_msgget -400 i386 msgsnd sys_msgsnd __ia32_compat_sys_msgsnd -401 i386 msgrcv sys_msgrcv __ia32_compat_sys_msgrcv -402 i386 msgctl sys_msgctl __ia32_compat_sys_msgctl -403 i386 clock_gettime64 sys_clock_gettime __ia32_sys_clock_gettime -404 i386 clock_settime64 sys_clock_settime __ia32_sys_clock_settime -405 i386 clock_adjtime64 sys_clock_adjtime __ia32_sys_clock_adjtime -406 i386 clock_getres_time64 sys_clock_getres __ia32_sys_clock_getres -407 i386 clock_nanosleep_time64 sys_clock_nanosleep __ia32_sys_clock_nanosleep -408 i386 timer_gettime64 sys_timer_gettime __ia32_sys_timer_gettime -409 i386 timer_settime64 sys_timer_settime __ia32_sys_timer_settime -410 i386 timerfd_gettime64 sys_timerfd_gettime __ia32_sys_timerfd_gettime -411 i386 timerfd_settime64 sys_timerfd_settime __ia32_sys_timerfd_settime -412 i386 utimensat_time64 sys_utimensat __ia32_sys_utimensat -413 i386 pselect6_time64 sys_pselect6 __ia32_compat_sys_pselect6_time64 -414 i386 ppoll_time64 sys_ppoll __ia32_compat_sys_ppoll_time64 -416 i386 io_pgetevents_time64 sys_io_pgetevents __ia32_sys_io_pgetevents -417 i386 recvmmsg_time64 sys_recvmmsg __ia32_compat_sys_recvmmsg_time64 -418 i386 mq_timedsend_time64 sys_mq_timedsend __ia32_sys_mq_timedsend -419 i386 mq_timedreceive_time64 sys_mq_timedreceive __ia32_sys_mq_timedreceive -420 i386 semtimedop_time64 sys_semtimedop __ia32_sys_semtimedop -421 i386 rt_sigtimedwait_time64 sys_rt_sigtimedwait __ia32_compat_sys_rt_sigtimedwait_time64 -422 i386 futex_time64 sys_futex __ia32_sys_futex -423 i386 sched_rr_get_interval_time64 sys_sched_rr_get_interval __ia32_sys_sched_rr_get_interval -424 i386 pidfd_send_signal sys_pidfd_send_signal __ia32_sys_pidfd_send_signal -425 i386 io_uring_setup sys_io_uring_setup __ia32_sys_io_uring_setup -426 i386 io_uring_enter sys_io_uring_enter __ia32_sys_io_uring_enter -427 i386 io_uring_register sys_io_uring_register __ia32_sys_io_uring_register -428 i386 open_tree sys_open_tree __ia32_sys_open_tree -429 i386 move_mount sys_move_mount __ia32_sys_move_mount -430 i386 fsopen sys_fsopen __ia32_sys_fsopen -431 i386 fsconfig sys_fsconfig __ia32_sys_fsconfig -432 i386 fsmount sys_fsmount __ia32_sys_fsmount -433 i386 fspick sys_fspick __ia32_sys_fspick -434 i386 pidfd_open sys_pidfd_open __ia32_sys_pidfd_open -435 i386 clone3 sys_clone3 __ia32_sys_clone3 -437 i386 openat2 sys_openat2 __ia32_sys_openat2 -438 i386 pidfd_getfd sys_pidfd_getfd __ia32_sys_pidfd_getfd +286 i386 add_key sys_add_key +287 i386 request_key sys_request_key +288 i386 keyctl sys_keyctl compat_sys_keyctl +289 i386 ioprio_set sys_ioprio_set +290 i386 ioprio_get sys_ioprio_get +291 i386 inotify_init sys_inotify_init +292 i386 inotify_add_watch sys_inotify_add_watch +293 i386 inotify_rm_watch sys_inotify_rm_watch +294 i386 migrate_pages sys_migrate_pages +295 i386 openat sys_openat compat_sys_openat +296 i386 mkdirat sys_mkdirat +297 i386 mknodat sys_mknodat +298 i386 fchownat sys_fchownat +299 i386 futimesat sys_futimesat_time32 +300 i386 fstatat64 sys_fstatat64 compat_sys_ia32_fstatat64 +301 i386 unlinkat sys_unlinkat +302 i386 renameat sys_renameat +303 i386 linkat sys_linkat +304 i386 symlinkat sys_symlinkat +305 i386 readlinkat sys_readlinkat +306 i386 fchmodat sys_fchmodat +307 i386 faccessat sys_faccessat +308 i386 pselect6 sys_pselect6_time32 compat_sys_pselect6_time32 +309 i386 ppoll sys_ppoll_time32 compat_sys_ppoll_time32 +310 i386 unshare sys_unshare +311 i386 set_robust_list sys_set_robust_list compat_sys_set_robust_list +312 i386 get_robust_list sys_get_robust_list compat_sys_get_robust_list +313 i386 splice sys_splice +314 i386 sync_file_range sys_ia32_sync_file_range +315 i386 tee sys_tee +316 i386 vmsplice sys_vmsplice compat_sys_vmsplice +317 i386 move_pages sys_move_pages compat_sys_move_pages +318 i386 getcpu sys_getcpu +319 i386 epoll_pwait sys_epoll_pwait +320 i386 utimensat sys_utimensat_time32 +321 i386 signalfd sys_signalfd compat_sys_signalfd +322 i386 timerfd_create sys_timerfd_create +323 i386 eventfd sys_eventfd +324 i386 fallocate sys_ia32_fallocate +325 i386 timerfd_settime sys_timerfd_settime32 +326 i386 timerfd_gettime sys_timerfd_gettime32 +327 i386 signalfd4 sys_signalfd4 compat_sys_signalfd4 +328 i386 eventfd2 sys_eventfd2 +329 i386 epoll_create1 sys_epoll_create1 +330 i386 dup3 sys_dup3 +331 i386 pipe2 sys_pipe2 +332 i386 inotify_init1 sys_inotify_init1 +333 i386 preadv sys_preadv compat_sys_preadv +334 i386 pwritev sys_pwritev compat_sys_pwritev +335 i386 rt_tgsigqueueinfo sys_rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo +336 i386 perf_event_open sys_perf_event_open +337 i386 recvmmsg sys_recvmmsg_time32 compat_sys_recvmmsg_time32 +338 i386 fanotify_init sys_fanotify_init +339 i386 fanotify_mark sys_fanotify_mark compat_sys_fanotify_mark +340 i386 prlimit64 sys_prlimit64 +341 i386 name_to_handle_at sys_name_to_handle_at +342 i386 open_by_handle_at sys_open_by_handle_at compat_sys_open_by_handle_at +343 i386 clock_adjtime sys_clock_adjtime32 +344 i386 syncfs sys_syncfs +345 i386 sendmmsg sys_sendmmsg compat_sys_sendmmsg +346 i386 setns sys_setns +347 i386 process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv +348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev +349 i386 kcmp sys_kcmp +350 i386 finit_module sys_finit_module +351 i386 sched_setattr sys_sched_setattr +352 i386 sched_getattr sys_sched_getattr +353 i386 renameat2 sys_renameat2 +354 i386 seccomp sys_seccomp +355 i386 getrandom sys_getrandom +356 i386 memfd_create sys_memfd_create +357 i386 bpf sys_bpf +358 i386 execveat sys_execveat compat_sys_execveat +359 i386 socket sys_socket +360 i386 socketpair sys_socketpair +361 i386 bind sys_bind +362 i386 connect sys_connect +363 i386 listen sys_listen +364 i386 accept4 sys_accept4 +365 i386 getsockopt sys_getsockopt sys_getsockopt +366 i386 setsockopt sys_setsockopt sys_setsockopt +367 i386 getsockname sys_getsockname +368 i386 getpeername sys_getpeername +369 i386 sendto sys_sendto +370 i386 sendmsg sys_sendmsg compat_sys_sendmsg +371 i386 recvfrom sys_recvfrom compat_sys_recvfrom +372 i386 recvmsg sys_recvmsg compat_sys_recvmsg +373 i386 shutdown sys_shutdown +374 i386 userfaultfd sys_userfaultfd +375 i386 membarrier sys_membarrier +376 i386 mlock2 sys_mlock2 +377 i386 copy_file_range sys_copy_file_range +378 i386 preadv2 sys_preadv2 compat_sys_preadv2 +379 i386 pwritev2 sys_pwritev2 compat_sys_pwritev2 +380 i386 pkey_mprotect sys_pkey_mprotect +381 i386 pkey_alloc sys_pkey_alloc +382 i386 pkey_free sys_pkey_free +383 i386 statx sys_statx +384 i386 arch_prctl sys_arch_prctl compat_sys_arch_prctl +385 i386 io_pgetevents sys_io_pgetevents_time32 compat_sys_io_pgetevents +386 i386 rseq sys_rseq +393 i386 semget sys_semget +394 i386 semctl sys_semctl compat_sys_semctl +395 i386 shmget sys_shmget +396 i386 shmctl sys_shmctl compat_sys_shmctl +397 i386 shmat sys_shmat compat_sys_shmat +398 i386 shmdt sys_shmdt +399 i386 msgget sys_msgget +400 i386 msgsnd sys_msgsnd compat_sys_msgsnd +401 i386 msgrcv sys_msgrcv compat_sys_msgrcv +402 i386 msgctl sys_msgctl compat_sys_msgctl +403 i386 clock_gettime64 sys_clock_gettime +404 i386 clock_settime64 sys_clock_settime +405 i386 clock_adjtime64 sys_clock_adjtime +406 i386 clock_getres_time64 sys_clock_getres +407 i386 clock_nanosleep_time64 sys_clock_nanosleep +408 i386 timer_gettime64 sys_timer_gettime +409 i386 timer_settime64 sys_timer_settime +410 i386 timerfd_gettime64 sys_timerfd_gettime +411 i386 timerfd_settime64 sys_timerfd_settime +412 i386 utimensat_time64 sys_utimensat +413 i386 pselect6_time64 sys_pselect6 compat_sys_pselect6_time64 +414 i386 ppoll_time64 sys_ppoll compat_sys_ppoll_time64 +416 i386 io_pgetevents_time64 sys_io_pgetevents +417 i386 recvmmsg_time64 sys_recvmmsg compat_sys_recvmmsg_time64 +418 i386 mq_timedsend_time64 sys_mq_timedsend +419 i386 mq_timedreceive_time64 sys_mq_timedreceive +420 i386 semtimedop_time64 sys_semtimedop +421 i386 rt_sigtimedwait_time64 sys_rt_sigtimedwait compat_sys_rt_sigtimedwait_time64 +422 i386 futex_time64 sys_futex +423 i386 sched_rr_get_interval_time64 sys_sched_rr_get_interval +424 i386 pidfd_send_signal sys_pidfd_send_signal +425 i386 io_uring_setup sys_io_uring_setup +426 i386 io_uring_enter sys_io_uring_enter +427 i386 io_uring_register sys_io_uring_register +428 i386 open_tree sys_open_tree +429 i386 move_mount sys_move_mount +430 i386 fsopen sys_fsopen +431 i386 fsconfig sys_fsconfig +432 i386 fsmount sys_fsmount +433 i386 fspick sys_fspick +434 i386 pidfd_open sys_pidfd_open +435 i386 clone3 sys_clone3 +436 i386 close_range sys_close_range +437 i386 openat2 sys_openat2 +438 i386 pidfd_getfd sys_pidfd_getfd +439 i386 faccessat2 sys_faccessat2 diff --git a/linux-user/i386/syscall_nr.h b/linux-user/i386/syscall_nr.h new file mode 100644 index 0000000000000000000000000000000000000000..976caab67fc15285d031d9b50fdbedd0387f6dc3 --- /dev/null +++ b/linux-user/i386/syscall_nr.h @@ -0,0 +1 @@ +#include "syscall_32_nr.h" diff --git a/linux-user/i386/target_cpu.h b/linux-user/i386/target_cpu.h index 2207d24c2eb059f8ad069d3487a4817c6c59b14e..52caf788cc319e03a3a4348712caf479635e3c96 100644 --- a/linux-user/i386/target_cpu.h +++ b/linux-user/i386/target_cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/i386/target_signal.h b/linux-user/i386/target_signal.h index f55e78fd33e7c4419bdb0f53f7c2fca67f83c8e5..50361af8746e7e3ccac98c1d42761667ae80f33b 100644 --- a/linux-user/i386/target_signal.h +++ b/linux-user/i386/target_signal.h @@ -4,9 +4,9 @@ /* this struct defines a stack used during syscall handling */ typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_long ss_flags; - abi_ulong ss_size; + abi_ulong ss_sp; + abi_int ss_flags; + abi_ulong ss_size; } target_stack_t; diff --git a/linux-user/i386/target_structs.h b/linux-user/i386/target_structs.h index 25388a7fd24470905fa7db52170e90585ba5cc48..e22847fd203b4d73601397409b3894272cc833b0 100644 --- a/linux-user/i386/target_structs.h +++ b/linux-user/i386/target_structs.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/i386/target_syscall.h b/linux-user/i386/target_syscall.h index 2854758134d703f965ac4d4de23f10ce868873f0..ed356b3908dc10127e68a7d7ca68da695f27eed8 100644 --- a/linux-user/i386/target_syscall.h +++ b/linux-user/i386/target_syscall.h @@ -151,8 +151,9 @@ struct target_vm86plus_struct { #define TARGET_CLONE_BACKWARDS #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 #define TARGET_WANT_OLD_SYS_SELECT #endif /* I386_TARGET_SYSCALL_H */ diff --git a/linux-user/i386/termbits.h b/linux-user/i386/termbits.h index 88264bbde721f1ae14f0c4c37b1584d36620fa55..b1d4f4fedbcb9ab2ca1184280eb4a9e5b8a9d735 100644 --- a/linux-user/i386/termbits.h +++ b/linux-user/i386/termbits.h @@ -1,232 +1 @@ -/* from asm/termbits.h */ - -#ifndef LINUX_USER_I386_TERMBITS_H -#define LINUX_USER_I386_TERMBITS_H - -#define TARGET_NCCS 19 - -struct target_termios { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ -}; - -/* c_iflag bits */ -#define TARGET_IGNBRK 0000001 -#define TARGET_BRKINT 0000002 -#define TARGET_IGNPAR 0000004 -#define TARGET_PARMRK 0000010 -#define TARGET_INPCK 0000020 -#define TARGET_ISTRIP 0000040 -#define TARGET_INLCR 0000100 -#define TARGET_IGNCR 0000200 -#define TARGET_ICRNL 0000400 -#define TARGET_IUCLC 0001000 -#define TARGET_IXON 0002000 -#define TARGET_IXANY 0004000 -#define TARGET_IXOFF 0010000 -#define TARGET_IMAXBEL 0020000 -#define TARGET_IUTF8 0040000 - -/* c_oflag bits */ -#define TARGET_OPOST 0000001 -#define TARGET_OLCUC 0000002 -#define TARGET_ONLCR 0000004 -#define TARGET_OCRNL 0000010 -#define TARGET_ONOCR 0000020 -#define TARGET_ONLRET 0000040 -#define TARGET_OFILL 0000100 -#define TARGET_OFDEL 0000200 -#define TARGET_NLDLY 0000400 -#define TARGET_NL0 0000000 -#define TARGET_NL1 0000400 -#define TARGET_CRDLY 0003000 -#define TARGET_CR0 0000000 -#define TARGET_CR1 0001000 -#define TARGET_CR2 0002000 -#define TARGET_CR3 0003000 -#define TARGET_TABDLY 0014000 -#define TARGET_TAB0 0000000 -#define TARGET_TAB1 0004000 -#define TARGET_TAB2 0010000 -#define TARGET_TAB3 0014000 -#define TARGET_XTABS 0014000 -#define TARGET_BSDLY 0020000 -#define TARGET_BS0 0000000 -#define TARGET_BS1 0020000 -#define TARGET_VTDLY 0040000 -#define TARGET_VT0 0000000 -#define TARGET_VT1 0040000 -#define TARGET_FFDLY 0100000 -#define TARGET_FF0 0000000 -#define TARGET_FF1 0100000 - -/* c_cflag bit meaning */ -#define TARGET_CBAUD 0010017 -#define TARGET_B0 0000000 /* hang up */ -#define TARGET_B50 0000001 -#define TARGET_B75 0000002 -#define TARGET_B110 0000003 -#define TARGET_B134 0000004 -#define TARGET_B150 0000005 -#define TARGET_B200 0000006 -#define TARGET_B300 0000007 -#define TARGET_B600 0000010 -#define TARGET_B1200 0000011 -#define TARGET_B1800 0000012 -#define TARGET_B2400 0000013 -#define TARGET_B4800 0000014 -#define TARGET_B9600 0000015 -#define TARGET_B19200 0000016 -#define TARGET_B38400 0000017 -#define TARGET_EXTA B19200 -#define TARGET_EXTB B38400 -#define TARGET_CSIZE 0000060 -#define TARGET_CS5 0000000 -#define TARGET_CS6 0000020 -#define TARGET_CS7 0000040 -#define TARGET_CS8 0000060 -#define TARGET_CSTOPB 0000100 -#define TARGET_CREAD 0000200 -#define TARGET_PARENB 0000400 -#define TARGET_PARODD 0001000 -#define TARGET_HUPCL 0002000 -#define TARGET_CLOCAL 0004000 -#define TARGET_CBAUDEX 0010000 -#define TARGET_B57600 0010001 -#define TARGET_B115200 0010002 -#define TARGET_B230400 0010003 -#define TARGET_B460800 0010004 -#define TARGET_B500000 0010005 -#define TARGET_B576000 0010006 -#define TARGET_B921600 0010007 -#define TARGET_B1000000 0010010 -#define TARGET_B1152000 0010011 -#define TARGET_B1500000 0010012 -#define TARGET_B2000000 0010013 -#define TARGET_B2500000 0010014 -#define TARGET_B3000000 0010015 -#define TARGET_B3500000 0010016 -#define TARGET_B4000000 0010017 -#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */ -#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ -#define TARGET_CRTSCTS 020000000000 /* flow control */ - -/* c_lflag bits */ -#define TARGET_ISIG 0000001 -#define TARGET_ICANON 0000002 -#define TARGET_XCASE 0000004 -#define TARGET_ECHO 0000010 -#define TARGET_ECHOE 0000020 -#define TARGET_ECHOK 0000040 -#define TARGET_ECHONL 0000100 -#define TARGET_NOFLSH 0000200 -#define TARGET_TOSTOP 0000400 -#define TARGET_ECHOCTL 0001000 -#define TARGET_ECHOPRT 0002000 -#define TARGET_ECHOKE 0004000 -#define TARGET_FLUSHO 0010000 -#define TARGET_PENDIN 0040000 -#define TARGET_IEXTEN 0100000 - -/* c_cc character offsets */ -#define TARGET_VINTR 0 -#define TARGET_VQUIT 1 -#define TARGET_VERASE 2 -#define TARGET_VKILL 3 -#define TARGET_VEOF 4 -#define TARGET_VTIME 5 -#define TARGET_VMIN 6 -#define TARGET_VSWTC 7 -#define TARGET_VSTART 8 -#define TARGET_VSTOP 9 -#define TARGET_VSUSP 10 -#define TARGET_VEOL 11 -#define TARGET_VREPRINT 12 -#define TARGET_VDISCARD 13 -#define TARGET_VWERASE 14 -#define TARGET_VLNEXT 15 -#define TARGET_VEOL2 16 - -/* ioctls */ - -#define TARGET_TCGETS 0x5401 -#define TARGET_TCSETS 0x5402 -#define TARGET_TCSETSW 0x5403 -#define TARGET_TCSETSF 0x5404 -#define TARGET_TCGETA 0x5405 -#define TARGET_TCSETA 0x5406 -#define TARGET_TCSETAW 0x5407 -#define TARGET_TCSETAF 0x5408 -#define TARGET_TCSBRK 0x5409 -#define TARGET_TCXONC 0x540A -#define TARGET_TCFLSH 0x540B - -#define TARGET_TIOCEXCL 0x540C -#define TARGET_TIOCNXCL 0x540D -#define TARGET_TIOCSCTTY 0x540E -#define TARGET_TIOCGPGRP 0x540F -#define TARGET_TIOCSPGRP 0x5410 -#define TARGET_TIOCOUTQ 0x5411 -#define TARGET_TIOCSTI 0x5412 -#define TARGET_TIOCGWINSZ 0x5413 -#define TARGET_TIOCSWINSZ 0x5414 -#define TARGET_TIOCMGET 0x5415 -#define TARGET_TIOCMBIS 0x5416 -#define TARGET_TIOCMBIC 0x5417 -#define TARGET_TIOCMSET 0x5418 -#define TARGET_TIOCGSOFTCAR 0x5419 -#define TARGET_TIOCSSOFTCAR 0x541A -#define TARGET_FIONREAD 0x541B -#define TARGET_TIOCINQ TARGET_FIONREAD -#define TARGET_TIOCLINUX 0x541C -#define TARGET_TIOCCONS 0x541D -#define TARGET_TIOCGSERIAL 0x541E -#define TARGET_TIOCSSERIAL 0x541F -#define TARGET_TIOCPKT 0x5420 -#define TARGET_FIONBIO 0x5421 -#define TARGET_TIOCNOTTY 0x5422 -#define TARGET_TIOCSETD 0x5423 -#define TARGET_TIOCGETD 0x5424 -#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ -#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */ -#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ -#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ -#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ -#define TARGET_TIOCGPTN TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ -#define TARGET_TIOCSPTLCK TARGET_IOW('T',0x31, int) /* Lock/unlock Pty */ -#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) /* Safely open the slave */ - -#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */ -#define TARGET_FIOCLEX 0x5451 -#define TARGET_FIOASYNC 0x5452 -#define TARGET_TIOCSERCONFIG 0x5453 -#define TARGET_TIOCSERGWILD 0x5454 -#define TARGET_TIOCSERSWILD 0x5455 -#define TARGET_TIOCGLCKTRMIOS 0x5456 -#define TARGET_TIOCSLCKTRMIOS 0x5457 -#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ - -#define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ -#define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ -#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ -#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ - -/* Used for packet mode */ -#define TARGET_TIOCPKT_DATA 0 -#define TARGET_TIOCPKT_FLUSHREAD 1 -#define TARGET_TIOCPKT_FLUSHWRITE 2 -#define TARGET_TIOCPKT_STOP 4 -#define TARGET_TIOCPKT_START 8 -#define TARGET_TIOCPKT_NOSTOP 16 -#define TARGET_TIOCPKT_DOSTOP 32 - -#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - -#endif +#include "../generic/termbits.h" diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 0defa1d8c18d23a0c0e574b3ec930476c45c6cd7..585874f090ff540b44e36e046946bcd6cfd547b8 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -174,6 +174,130 @@ IOCTL(FS_IOC32_GETVERSION, IOC_R, MK_PTR(TYPE_INT)) IOCTL(FS_IOC32_SETVERSION, IOC_W, MK_PTR(TYPE_INT)) +#ifdef BTRFS_IOC_SNAP_CREATE + IOCTL(BTRFS_IOC_SNAP_CREATE, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) +#endif +#ifdef BTRFS_IOC_SCAN_DEV + IOCTL(BTRFS_IOC_SCAN_DEV, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) +#endif +#ifdef BTRFS_IOC_FORGET_DEV + IOCTL(BTRFS_IOC_FORGET_DEV, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) +#endif +#ifdef BTRFS_IOC_ADD_DEV + IOCTL(BTRFS_IOC_ADD_DEV, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) +#endif +#ifdef BTRFS_IOC_RM_DEV + IOCTL(BTRFS_IOC_RM_DEV, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) +#endif +#ifdef BTRFS_IOC_SUBVOL_CREATE + IOCTL(BTRFS_IOC_SUBVOL_CREATE, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) +#endif +#ifdef BTRFS_IOC_SNAP_DESTROY + IOCTL(BTRFS_IOC_SNAP_DESTROY, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) +#endif +#ifdef BTRFS_IOC_INO_LOOKUP + IOCTL(BTRFS_IOC_INO_LOOKUP, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_lookup_args))) +#endif +#ifdef BTRFS_IOC_DEFAULT_SUBVOL + IOCTL(BTRFS_IOC_DEFAULT_SUBVOL, IOC_W, MK_PTR(TYPE_ULONGLONG)) +#endif +#ifdef BTRFS_IOC_SUBVOL_GETFLAGS + IOCTL(BTRFS_IOC_SUBVOL_GETFLAGS, IOC_R, MK_PTR(TYPE_ULONGLONG)) +#endif +#ifdef BTRFS_IOC_SUBVOL_SETFLAGS + IOCTL(BTRFS_IOC_SUBVOL_SETFLAGS, IOC_W, MK_PTR(TYPE_ULONGLONG)) +#endif +#ifdef BTRFS_IOC_SCRUB + IOCTL(BTRFS_IOC_SCRUB, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_scrub_args))) +#endif +#ifdef BTRFS_IOC_SCRUB_CANCEL + IOCTL(BTRFS_IOC_SCRUB_CANCEL, 0, TYPE_NULL) +#endif +#ifdef BTRFS_IOC_SCRUB_PROGRESS + IOCTL(BTRFS_IOC_SCRUB_PROGRESS, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_scrub_args))) +#endif +#ifdef BTRFS_IOC_DEV_INFO + IOCTL(BTRFS_IOC_DEV_INFO, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_dev_info_args))) +#endif +#ifdef BTRFS_IOC_INO_PATHS + IOCTL(BTRFS_IOC_INO_PATHS, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_path_args))) +#endif +#ifdef BTRFS_IOC_LOGICAL_INO + IOCTL(BTRFS_IOC_LOGICAL_INO, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_logical_ino_args))) +#endif +#ifdef BTRFS_IOC_QUOTA_CTL + IOCTL(BTRFS_IOC_QUOTA_CTL, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_quota_ctl_args))) +#endif +#ifdef BTRFS_IOC_QGROUP_ASSIGN + IOCTL(BTRFS_IOC_QGROUP_ASSIGN, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_qgroup_assign_args))) +#endif +#ifdef BTRFS_IOC_QGROUP_CREATE + IOCTL(BTRFS_IOC_QGROUP_CREATE, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_qgroup_create_args))) +#endif +#ifdef BTRFS_IOC_QGROUP_LIMIT + IOCTL(BTRFS_IOC_QGROUP_LIMIT, IOC_R, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_qgroup_limit_args))) +#endif +#ifdef BTRFS_IOC_QUOTA_RESCAN + IOCTL(BTRFS_IOC_QUOTA_RESCAN, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_quota_rescan_args))) +#endif +#ifdef BTRFS_IOC_QUOTA_RESCAN_STATUS + IOCTL(BTRFS_IOC_QUOTA_RESCAN_STATUS, IOC_R, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_quota_rescan_args))) +#endif +#ifdef BTRFS_IOC_QUOTA_RESCAN_WAIT + IOCTL(BTRFS_IOC_QUOTA_RESCAN_WAIT, 0, TYPE_NULL) +#endif +#ifdef BTRFS_IOC_GET_DEV_STATS + IOCTL(BTRFS_IOC_GET_DEV_STATS, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_get_dev_stats))) +#endif +#ifdef BTRFS_IOC_GET_FEATURES + IOCTL(BTRFS_IOC_GET_FEATURES, IOC_R, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_feature_flags))) +#endif +#ifdef BTRFS_IOC_SET_FEATURES + IOCTL(BTRFS_IOC_SET_FEATURES, IOC_W, + MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_btrfs_ioctl_feature_flags), 2))) +#endif +#ifdef BTRFS_IOC_GET_SUPPORTED_FEATURES + IOCTL(BTRFS_IOC_GET_SUPPORTED_FEATURES, IOC_R, + MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_btrfs_ioctl_feature_flags), 3))) +#endif +#ifdef BTRFS_IOC_LOGICAL_INO_V2 + IOCTL(BTRFS_IOC_LOGICAL_INO_V2, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_logical_ino_args))) +#endif +#ifdef BTRFS_IOC_GET_SUBVOL_INFO + IOCTL(BTRFS_IOC_GET_SUBVOL_INFO, IOC_R, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_get_subvol_info_args))) +#endif +#ifdef BTRFS_IOC_GET_SUBVOL_ROOTREF + IOCTL(BTRFS_IOC_GET_SUBVOL_ROOTREF, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_get_subvol_rootref_args))) +#endif +#ifdef BTRFS_IOC_INO_LOOKUP_USER + IOCTL(BTRFS_IOC_INO_LOOKUP_USER, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_lookup_user_args))) +#endif + #ifdef CONFIG_USBFS /* USB ioctls */ IOCTL(USBDEVFS_CONTROL, IOC_RW, @@ -279,13 +403,17 @@ * FIXME: create a macro to define this kind of entry */ { TARGET_SIOCGSTAMP_OLD, TARGET_SIOCGSTAMP_OLD, - "SIOCGSTAMP_OLD", IOC_R, do_ioctl_SIOCGSTAMP }, + "SIOCGSTAMP_OLD", IOC_R, do_ioctl_SIOCGSTAMP, + { MK_PTR(MK_STRUCT(STRUCT_timeval)) } }, { TARGET_SIOCGSTAMPNS_OLD, TARGET_SIOCGSTAMPNS_OLD, - "SIOCGSTAMPNS_OLD", IOC_R, do_ioctl_SIOCGSTAMPNS }, + "SIOCGSTAMPNS_OLD", IOC_R, do_ioctl_SIOCGSTAMPNS, + { MK_PTR(MK_STRUCT(STRUCT_timespec)) } }, { TARGET_SIOCGSTAMP_NEW, TARGET_SIOCGSTAMP_NEW, - "SIOCGSTAMP_NEW", IOC_R, do_ioctl_SIOCGSTAMP }, + "SIOCGSTAMP_NEW", IOC_R, do_ioctl_SIOCGSTAMP, + { MK_PTR(MK_STRUCT(STRUCT__kernel_sock_timeval)) } }, { TARGET_SIOCGSTAMPNS_NEW, TARGET_SIOCGSTAMPNS_NEW, - "SIOCGSTAMPNS_NEW", IOC_R, do_ioctl_SIOCGSTAMPNS }, + "SIOCGSTAMPNS_NEW", IOC_R, do_ioctl_SIOCGSTAMPNS, + { MK_PTR(MK_STRUCT(STRUCT__kernel_timespec)) } }, IOCTL(RNDGETENTCNT, IOC_R, MK_PTR(TYPE_INT)) IOCTL(RNDADDTOENTCNT, IOC_W, MK_PTR(TYPE_INT)) @@ -574,6 +702,14 @@ IOCTL_SPECIAL(SIOCDELRT, IOC_W, do_ioctl_rt, MK_PTR(MK_STRUCT(STRUCT_rtentry))) +#ifdef HAVE_DRM_H + IOCTL_SPECIAL(DRM_IOCTL_VERSION, IOC_RW, do_ioctl_drm, + MK_PTR(MK_STRUCT(STRUCT_drm_version))) + + IOCTL_SPECIAL(DRM_IOCTL_I915_GETPARAM, IOC_RW, do_ioctl_drm_i915, + MK_PTR(MK_STRUCT(STRUCT_drm_i915_getparam))) +#endif + #ifdef TARGET_TIOCSTART IOCTL_IGNORE(TIOCSTART) IOCTL_IGNORE(TIOCSTOP) diff --git a/linux-user/m68k/Makefile.objs b/linux-user/m68k/Makefile.objs deleted file mode 100644 index 961bd05c237fc3e32d5c5f81e6926de76341d5e3..0000000000000000000000000000000000000000 --- a/linux-user/m68k/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -generated-files-y += linux-user/m68k/syscall_nr.h - -syshdr := $(SRC_PATH)/linux-user/m68k/syscallhdr.sh -%/syscall_nr.h: $(SRC_PATH)/linux-user/m68k/syscall.tbl $(syshdr) - $(call quiet-command, sh $(syshdr) $< $@ $(TARGET_SYSTBL_ABI),"GEN","$@") diff --git a/linux-user/m68k/meson.build b/linux-user/m68k/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..c0f436fe50defc8e25169bd8455664a4b2c1b774 --- /dev/null +++ b/linux-user/m68k/meson.build @@ -0,0 +1,5 @@ +syscall_nr_generators += { + 'm68k': generator(sh, + arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ], + output: '@BASENAME@_nr.h') +} diff --git a/linux-user/m68k/syscall.tbl b/linux-user/m68k/syscall.tbl index f4f49fcb76d0fe3e7107cc9e68a70aabf34ccb27..81fc799d839234f00c0b13e56959f5f165827a97 100644 --- a/linux-user/m68k/syscall.tbl +++ b/linux-user/m68k/syscall.tbl @@ -156,7 +156,7 @@ 146 common writev sys_writev 147 common getsid sys_getsid 148 common fdatasync sys_fdatasync -149 common _sysctl sys_sysctl +149 common _sysctl sys_ni_syscall 150 common mlock sys_mlock 151 common munlock sys_munlock 152 common mlockall sys_mlockall @@ -435,5 +435,7 @@ 433 common fspick sys_fspick 434 common pidfd_open sys_pidfd_open 435 common clone3 __sys_clone3 +436 common close_range sys_close_range 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd +439 common faccessat2 sys_faccessat2 diff --git a/linux-user/m68k/target_signal.h b/linux-user/m68k/target_signal.h index 314e808844a4f5c6f327cdf20e89a4359af33552..d096544ef8420c706ed1c56e2a6747beb0c8d719 100644 --- a/linux-user/m68k/target_signal.h +++ b/linux-user/m68k/target_signal.h @@ -4,9 +4,9 @@ /* this struct defines a stack used during syscall handling */ typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_long ss_flags; - abi_ulong ss_size; + abi_ulong ss_sp; + abi_int ss_flags; + abi_ulong ss_size; } target_stack_t; diff --git a/linux-user/m68k/target_syscall.h b/linux-user/m68k/target_syscall.h index c0366b1c622d5843afe4c363ff02caee3eab548d..23359a6299dd035be00f0ded3550b49a42cc158f 100644 --- a/linux-user/m68k/target_syscall.h +++ b/linux-user/m68k/target_syscall.h @@ -21,9 +21,9 @@ struct target_pt_regs { #define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 - +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 #define TARGET_WANT_OLD_SYS_SELECT #endif /* M68K_TARGET_SYSCALL_H */ diff --git a/linux-user/m68k/termbits.h b/linux-user/m68k/termbits.h index 23840aa9688ceaead451cfc67825bb3dab44db25..b1d4f4fedbcb9ab2ca1184280eb4a9e5b8a9d735 100644 --- a/linux-user/m68k/termbits.h +++ b/linux-user/m68k/termbits.h @@ -1,233 +1 @@ -/* from asm/termbits.h */ -/* NOTE: exactly the same as i386 */ - -#ifndef LINUX_USER_M68K_TERMBITS_H -#define LINUX_USER_M68K_TERMBITS_H - -#define TARGET_NCCS 19 - -struct target_termios { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ -}; - -/* c_iflag bits */ -#define TARGET_IGNBRK 0000001 -#define TARGET_BRKINT 0000002 -#define TARGET_IGNPAR 0000004 -#define TARGET_PARMRK 0000010 -#define TARGET_INPCK 0000020 -#define TARGET_ISTRIP 0000040 -#define TARGET_INLCR 0000100 -#define TARGET_IGNCR 0000200 -#define TARGET_ICRNL 0000400 -#define TARGET_IUCLC 0001000 -#define TARGET_IXON 0002000 -#define TARGET_IXANY 0004000 -#define TARGET_IXOFF 0010000 -#define TARGET_IMAXBEL 0020000 -#define TARGET_IUTF8 0040000 - -/* c_oflag bits */ -#define TARGET_OPOST 0000001 -#define TARGET_OLCUC 0000002 -#define TARGET_ONLCR 0000004 -#define TARGET_OCRNL 0000010 -#define TARGET_ONOCR 0000020 -#define TARGET_ONLRET 0000040 -#define TARGET_OFILL 0000100 -#define TARGET_OFDEL 0000200 -#define TARGET_NLDLY 0000400 -#define TARGET_NL0 0000000 -#define TARGET_NL1 0000400 -#define TARGET_CRDLY 0003000 -#define TARGET_CR0 0000000 -#define TARGET_CR1 0001000 -#define TARGET_CR2 0002000 -#define TARGET_CR3 0003000 -#define TARGET_TABDLY 0014000 -#define TARGET_TAB0 0000000 -#define TARGET_TAB1 0004000 -#define TARGET_TAB2 0010000 -#define TARGET_TAB3 0014000 -#define TARGET_XTABS 0014000 -#define TARGET_BSDLY 0020000 -#define TARGET_BS0 0000000 -#define TARGET_BS1 0020000 -#define TARGET_VTDLY 0040000 -#define TARGET_VT0 0000000 -#define TARGET_VT1 0040000 -#define TARGET_FFDLY 0100000 -#define TARGET_FF0 0000000 -#define TARGET_FF1 0100000 - -/* c_cflag bit meaning */ -#define TARGET_CBAUD 0010017 -#define TARGET_B0 0000000 /* hang up */ -#define TARGET_B50 0000001 -#define TARGET_B75 0000002 -#define TARGET_B110 0000003 -#define TARGET_B134 0000004 -#define TARGET_B150 0000005 -#define TARGET_B200 0000006 -#define TARGET_B300 0000007 -#define TARGET_B600 0000010 -#define TARGET_B1200 0000011 -#define TARGET_B1800 0000012 -#define TARGET_B2400 0000013 -#define TARGET_B4800 0000014 -#define TARGET_B9600 0000015 -#define TARGET_B19200 0000016 -#define TARGET_B38400 0000017 -#define TARGET_EXTA B19200 -#define TARGET_EXTB B38400 -#define TARGET_CSIZE 0000060 -#define TARGET_CS5 0000000 -#define TARGET_CS6 0000020 -#define TARGET_CS7 0000040 -#define TARGET_CS8 0000060 -#define TARGET_CSTOPB 0000100 -#define TARGET_CREAD 0000200 -#define TARGET_PARENB 0000400 -#define TARGET_PARODD 0001000 -#define TARGET_HUPCL 0002000 -#define TARGET_CLOCAL 0004000 -#define TARGET_CBAUDEX 0010000 -#define TARGET_B57600 0010001 -#define TARGET_B115200 0010002 -#define TARGET_B230400 0010003 -#define TARGET_B460800 0010004 -#define TARGET_B500000 0010005 -#define TARGET_B576000 0010006 -#define TARGET_B921600 0010007 -#define TARGET_B1000000 0010010 -#define TARGET_B1152000 0010011 -#define TARGET_B1500000 0010012 -#define TARGET_B2000000 0010013 -#define TARGET_B2500000 0010014 -#define TARGET_B3000000 0010015 -#define TARGET_B3500000 0010016 -#define TARGET_B4000000 0010017 -#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */ -#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ -#define TARGET_CRTSCTS 020000000000 /* flow control */ - -/* c_lflag bits */ -#define TARGET_ISIG 0000001 -#define TARGET_ICANON 0000002 -#define TARGET_XCASE 0000004 -#define TARGET_ECHO 0000010 -#define TARGET_ECHOE 0000020 -#define TARGET_ECHOK 0000040 -#define TARGET_ECHONL 0000100 -#define TARGET_NOFLSH 0000200 -#define TARGET_TOSTOP 0000400 -#define TARGET_ECHOCTL 0001000 -#define TARGET_ECHOPRT 0002000 -#define TARGET_ECHOKE 0004000 -#define TARGET_FLUSHO 0010000 -#define TARGET_PENDIN 0040000 -#define TARGET_IEXTEN 0100000 - -/* c_cc character offsets */ -#define TARGET_VINTR 0 -#define TARGET_VQUIT 1 -#define TARGET_VERASE 2 -#define TARGET_VKILL 3 -#define TARGET_VEOF 4 -#define TARGET_VTIME 5 -#define TARGET_VMIN 6 -#define TARGET_VSWTC 7 -#define TARGET_VSTART 8 -#define TARGET_VSTOP 9 -#define TARGET_VSUSP 10 -#define TARGET_VEOL 11 -#define TARGET_VREPRINT 12 -#define TARGET_VDISCARD 13 -#define TARGET_VWERASE 14 -#define TARGET_VLNEXT 15 -#define TARGET_VEOL2 16 - -/* ioctls */ - -#define TARGET_TCGETS 0x5401 -#define TARGET_TCSETS 0x5402 -#define TARGET_TCSETSW 0x5403 -#define TARGET_TCSETSF 0x5404 -#define TARGET_TCGETA 0x5405 -#define TARGET_TCSETA 0x5406 -#define TARGET_TCSETAW 0x5407 -#define TARGET_TCSETAF 0x5408 -#define TARGET_TCSBRK 0x5409 -#define TARGET_TCXONC 0x540A -#define TARGET_TCFLSH 0x540B - -#define TARGET_TIOCEXCL 0x540C -#define TARGET_TIOCNXCL 0x540D -#define TARGET_TIOCSCTTY 0x540E -#define TARGET_TIOCGPGRP 0x540F -#define TARGET_TIOCSPGRP 0x5410 -#define TARGET_TIOCOUTQ 0x5411 -#define TARGET_TIOCSTI 0x5412 -#define TARGET_TIOCGWINSZ 0x5413 -#define TARGET_TIOCSWINSZ 0x5414 -#define TARGET_TIOCMGET 0x5415 -#define TARGET_TIOCMBIS 0x5416 -#define TARGET_TIOCMBIC 0x5417 -#define TARGET_TIOCMSET 0x5418 -#define TARGET_TIOCGSOFTCAR 0x5419 -#define TARGET_TIOCSSOFTCAR 0x541A -#define TARGET_FIONREAD 0x541B -#define TARGET_TIOCINQ TARGET_FIONREAD -#define TARGET_TIOCLINUX 0x541C -#define TARGET_TIOCCONS 0x541D -#define TARGET_TIOCGSERIAL 0x541E -#define TARGET_TIOCSSERIAL 0x541F -#define TARGET_TIOCPKT 0x5420 -#define TARGET_FIONBIO 0x5421 -#define TARGET_TIOCNOTTY 0x5422 -#define TARGET_TIOCSETD 0x5423 -#define TARGET_TIOCGETD 0x5424 -#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ -#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */ -#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ -#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ -#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ -#define TARGET_TIOCGPTN TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ -#define TARGET_TIOCSPTLCK TARGET_IOW('T',0x31, int) /* Lock/unlock Pty */ -#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) /* Safely open the slave */ - -#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */ -#define TARGET_FIOCLEX 0x5451 -#define TARGET_FIOASYNC 0x5452 -#define TARGET_TIOCSERCONFIG 0x5453 -#define TARGET_TIOCSERGWILD 0x5454 -#define TARGET_TIOCSERSWILD 0x5455 -#define TARGET_TIOCGLCKTRMIOS 0x5456 -#define TARGET_TIOCSLCKTRMIOS 0x5457 -#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ - -#define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ -#define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ -#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ -#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ - -/* Used for packet mode */ -#define TARGET_TIOCPKT_DATA 0 -#define TARGET_TIOCPKT_FLUSHREAD 1 -#define TARGET_TIOCPKT_FLUSHWRITE 2 -#define TARGET_TIOCPKT_STOP 4 -#define TARGET_TIOCPKT_START 8 -#define TARGET_TIOCPKT_NOSTOP 16 -#define TARGET_TIOCPKT_DOSTOP 32 - -#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - -#endif +#include "../generic/termbits.h" diff --git a/linux-user/main.c b/linux-user/main.c index 3597e99bb10a8e2ff1ababbe204813178e3c45f1..24d1eb73ad1904a131f77f79cdfca486db23eddf 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -386,11 +386,9 @@ static void handle_arg_version(const char *arg) exit(EXIT_SUCCESS); } -static char *trace_file; static void handle_arg_trace(const char *arg) { - g_free(trace_file); - trace_file = trace_opt_parse(arg); + trace_opt_parse(arg); } #if defined(TARGET_XTENSA) @@ -672,7 +670,7 @@ int main(int argc, char **argv, char **envp) if (!trace_init_backends()) { exit(1); } - trace_init_file(trace_file); + trace_init_file(); if (qemu_plugin_load_list(&plugins)) { exit(1); } @@ -758,14 +756,26 @@ int main(int argc, char **argv, char **envp) if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) { unsigned long tmp; - if (fscanf(fp, "%lu", &tmp) == 1) { + if (fscanf(fp, "%lu", &tmp) == 1 && tmp != 0) { mmap_min_addr = tmp; - qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n", mmap_min_addr); + qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n", + mmap_min_addr); } fclose(fp); } } + /* + * We prefer to not make NULL pointers accessible to QEMU. + * If we're in a chroot with no /proc, fall back to 1 page. + */ + if (mmap_min_addr == 0) { + mmap_min_addr = qemu_host_page_size; + qemu_log_mask(CPU_LOG_PAGE, + "host mmap_min_addr=0x%lx (fallback)\n", + mmap_min_addr); + } + /* * Prepare copy of argv vector for target. */ diff --git a/linux-user/meson.build b/linux-user/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..2b94e4ba24a218007af540ae99243a08bdde02d0 --- /dev/null +++ b/linux-user/meson.build @@ -0,0 +1,37 @@ +linux_user_ss.add(files( + 'elfload.c', + 'exit.c', + 'fd-trans.c', + 'linuxload.c', + 'main.c', + 'mmap.c', + 'safe-syscall.S', + 'signal.c', + 'strace.c', + 'syscall.c', + 'uaccess.c', + 'uname.c', +)) +linux_user_ss.add(rt) + +linux_user_ss.add(when: 'TARGET_HAS_BFLT', if_true: files('flatload.c')) +linux_user_ss.add(when: 'TARGET_I386', if_true: files('vm86.c')) + + +syscall_nr_generators = {} + +subdir('alpha') +subdir('arm') +subdir('hppa') +subdir('i386') +subdir('m68k') +subdir('microblaze') +subdir('mips64') +subdir('mips') +subdir('ppc') +subdir('s390x') +subdir('sh4') +subdir('sparc64') +subdir('sparc') +subdir('x86_64') +subdir('xtensa') diff --git a/linux-user/microblaze/Makefile.objs b/linux-user/microblaze/Makefile.objs deleted file mode 100644 index bb8b318dda7f3d57659b1f500e5ee7941c048a8c..0000000000000000000000000000000000000000 --- a/linux-user/microblaze/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -generated-files-y += linux-user/microblaze/syscall_nr.h - -syshdr := $(SRC_PATH)/linux-user/microblaze/syscallhdr.sh -%/syscall_nr.h: $(SRC_PATH)/linux-user/microblaze/syscall.tbl $(syshdr) - $(call quiet-command, sh $(syshdr) $< $@ $(TARGET_SYSTBL_ABI),"GEN","$@") diff --git a/linux-user/microblaze/cpu_loop.c b/linux-user/microblaze/cpu_loop.c index 3e0a7f730b154a5c40a2c042c1bcbce1259284c6..c3396a6e09bd1dfe58c3f12d5b470ac746995b4c 100644 --- a/linux-user/microblaze/cpu_loop.c +++ b/linux-user/microblaze/cpu_loop.c @@ -48,10 +48,10 @@ void cpu_loop(CPUMBState *env) case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ break; - case EXCP_BREAK: + case EXCP_SYSCALL: /* Return address is 4 bytes after the call. */ env->regs[14] += 4; - env->sregs[SR_PC] = env->regs[14]; + env->pc = env->regs[14]; ret = do_syscall(env, env->regs[12], env->regs[5], @@ -63,7 +63,7 @@ void cpu_loop(CPUMBState *env) 0, 0); if (ret == -TARGET_ERESTARTSYS) { /* Wind back to before the syscall. */ - env->sregs[SR_PC] -= 4; + env->pc -= 4; } else if (ret != -TARGET_QEMU_ESIGRETURN) { env->regs[3] = ret; } @@ -73,19 +73,19 @@ void cpu_loop(CPUMBState *env) * not a userspace-usable register, as the kernel may clobber it * at any point.) */ - env->regs[14] = env->sregs[SR_PC]; + env->regs[14] = env->pc; break; case EXCP_HW_EXCP: - env->regs[17] = env->sregs[SR_PC] + 4; + env->regs[17] = env->pc + 4; if (env->iflags & D_FLAG) { - env->sregs[SR_ESR] |= 1 << 12; - env->sregs[SR_PC] -= 4; + env->esr |= 1 << 12; + env->pc -= 4; /* FIXME: if branch was immed, replay the imm as well. */ } env->iflags &= ~(IMM_FLAG | D_FLAG); - switch (env->sregs[SR_ESR] & 31) { + switch (env->esr & 31) { case ESR_EC_DIVZERO: info.si_signo = TARGET_SIGFPE; info.si_errno = 0; @@ -96,18 +96,18 @@ void cpu_loop(CPUMBState *env) case ESR_EC_FPU: info.si_signo = TARGET_SIGFPE; info.si_errno = 0; - if (env->sregs[SR_FSR] & FSR_IO) { + if (env->fsr & FSR_IO) { info.si_code = TARGET_FPE_FLTINV; } - if (env->sregs[SR_FSR] & FSR_DZ) { + if (env->fsr & FSR_DZ) { info.si_code = TARGET_FPE_FLTDIV; } info._sifields._sigfault._addr = 0; queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); break; default: - fprintf(stderr, "Unhandled hw-exception: 0x%" PRIx64 "\n", - env->sregs[SR_ESR] & ESR_EC_MASK); + fprintf(stderr, "Unhandled hw-exception: 0x%x\n", + env->esr & ESR_EC_MASK); cpu_dump_state(cs, stderr, 0); exit(EXIT_FAILURE); break; @@ -165,5 +165,5 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) env->regs[29] = regs->r29; env->regs[30] = regs->r30; env->regs[31] = regs->r31; - env->sregs[SR_PC] = regs->pc; + env->pc = regs->pc; } diff --git a/linux-user/microblaze/meson.build b/linux-user/microblaze/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..f749d89418bdf62d2540198202509e874ed98d87 --- /dev/null +++ b/linux-user/microblaze/meson.build @@ -0,0 +1,5 @@ +syscall_nr_generators += { + 'microblaze': generator(sh, + arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ], + output: '@BASENAME@_nr.h') +} diff --git a/linux-user/microblaze/signal.c b/linux-user/microblaze/signal.c index 80950c2181e3c512ea3051d16ae23df75f50085a..cf0707b5564bdd2ff3adf2c53b64839f32ab8a6c 100644 --- a/linux-user/microblaze/signal.c +++ b/linux-user/microblaze/signal.c @@ -35,21 +35,15 @@ struct target_stack_t { struct target_ucontext { abi_ulong tuc_flags; abi_ulong tuc_link; - struct target_stack_t tuc_stack; + target_stack_t tuc_stack; struct target_sigcontext tuc_mcontext; - uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1]; + target_sigset_t tuc_sigmask; }; /* Signal frames. */ -struct target_signal_frame { +struct target_rt_sigframe { + target_siginfo_t info; struct target_ucontext uc; - uint32_t extramask[TARGET_NSIG_WORDS - 1]; - uint32_t tramp[2]; -}; - -struct rt_signal_frame { - siginfo_t info; - ucontext_t uc; uint32_t tramp[2]; }; @@ -87,7 +81,7 @@ static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env) __put_user(env->regs[29], &sc->regs.r29); __put_user(env->regs[30], &sc->regs.r30); __put_user(env->regs[31], &sc->regs.r31); - __put_user(env->sregs[SR_PC], &sc->regs.pc); + __put_user(env->pc, &sc->regs.pc); } static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env) @@ -124,7 +118,7 @@ static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env) __get_user(env->regs[29], &sc->regs.r29); __get_user(env->regs[30], &sc->regs.r30); __get_user(env->regs[31], &sc->regs.r31); - __get_user(env->sregs[SR_PC], &sc->regs.pc); + __get_user(env->pc, &sc->regs.pc); } static abi_ulong get_sigframe(struct target_sigaction *ka, @@ -137,109 +131,95 @@ static abi_ulong get_sigframe(struct target_sigaction *ka, return ((sp - frame_size) & -8UL); } -void setup_frame(int sig, struct target_sigaction *ka, - target_sigset_t *set, CPUMBState *env) +void setup_rt_frame(int sig, struct target_sigaction *ka, + target_siginfo_t *info, + target_sigset_t *set, CPUMBState *env) { - struct target_signal_frame *frame; + struct target_rt_sigframe *frame; abi_ulong frame_addr; - int i; frame_addr = get_sigframe(ka, env, sizeof *frame); - trace_user_setup_frame(env, frame_addr); - if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) - goto badframe; + trace_user_setup_rt_frame(env, frame_addr); - /* Save the mask. */ - __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask); - - for(i = 1; i < TARGET_NSIG_WORDS; i++) { - __put_user(set->sig[i], &frame->extramask[i - 1]); + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { + force_sigsegv(sig); + return; } + tswap_siginfo(&frame->info, info); + + __put_user(0, &frame->uc.tuc_flags); + __put_user(0, &frame->uc.tuc_link); + + target_save_altstack(&frame->uc.tuc_stack, env); setup_sigcontext(&frame->uc.tuc_mcontext, env); - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ - /* minus 8 is offset to cater for "rtsd r15,8" offset */ - if (ka->sa_flags & TARGET_SA_RESTORER) { - env->regs[15] = ((unsigned long)ka->sa_restorer)-8; - } else { - uint32_t t; - /* Note, these encodings are _big endian_! */ - /* addi r12, r0, __NR_sigreturn */ - t = 0x31800000UL | TARGET_NR_sigreturn; - __put_user(t, frame->tramp + 0); - /* brki r14, 0x8 */ - t = 0xb9cc0008UL; - __put_user(t, frame->tramp + 1); - - /* Return from sighandler will jump to the tramp. - Negative 8 offset because return is rtsd r15, 8 */ - env->regs[15] = frame_addr + offsetof(struct target_signal_frame, tramp) - - 8; + for (int i = 0; i < TARGET_NSIG_WORDS; i++) { + __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); } + /* Kernel does not use SA_RESTORER. */ + + /* addi r12, r0, __NR_sigreturn */ + __put_user(0x31800000U | TARGET_NR_rt_sigreturn, frame->tramp + 0); + /* brki r14, 0x8 */ + __put_user(0xb9cc0008U, frame->tramp + 1); + + /* + * Return from sighandler will jump to the tramp. + * Negative 8 offset because return is rtsd r15, 8 + */ + env->regs[15] = + frame_addr + offsetof(struct target_rt_sigframe, tramp) - 8; + /* Set up registers for signal handler */ env->regs[1] = frame_addr; + /* Signal handler args: */ - env->regs[5] = sig; /* Arg 0: signum */ - env->regs[6] = 0; - /* arg 1: sigcontext */ - env->regs[7] = frame_addr += offsetof(typeof(*frame), uc); + env->regs[5] = sig; + env->regs[6] = frame_addr + offsetof(struct target_rt_sigframe, info); + env->regs[7] = frame_addr + offsetof(struct target_rt_sigframe, uc); - /* Offset of 4 to handle microblaze rtid r14, 0 */ - env->sregs[SR_PC] = (unsigned long)ka->_sa_handler; + /* Offset to handle microblaze rtid r14, 0 */ + env->pc = (unsigned long)ka->_sa_handler; unlock_user_struct(frame, frame_addr, 1); - return; -badframe: - force_sigsegv(sig); } -void setup_rt_frame(int sig, struct target_sigaction *ka, - target_siginfo_t *info, - target_sigset_t *set, CPUMBState *env) + +long do_sigreturn(CPUMBState *env) { - qemu_log_mask(LOG_UNIMP, "setup_rt_frame: not implemented\n"); + return -TARGET_ENOSYS; } -long do_sigreturn(CPUMBState *env) +long do_rt_sigreturn(CPUMBState *env) { - struct target_signal_frame *frame; - abi_ulong frame_addr; - target_sigset_t target_set; + struct target_rt_sigframe *frame = NULL; + abi_ulong frame_addr = env->regs[1]; sigset_t set; - int i; - frame_addr = env->regs[R_SP]; - trace_user_do_sigreturn(env, frame_addr); - /* Make sure the guest isn't playing games. */ - if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) - goto badframe; + trace_user_do_rt_sigreturn(env, frame_addr); - /* Restore blocked signals */ - __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask); - for(i = 1; i < TARGET_NSIG_WORDS; i++) { - __get_user(target_set.sig[i], &frame->extramask[i - 1]); + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { + goto badframe; } - target_to_host_sigset_internal(&set, &target_set); + + target_to_host_sigset(&set, &frame->uc.tuc_sigmask); set_sigmask(&set); restore_sigcontext(&frame->uc.tuc_mcontext, env); - /* We got here through a sigreturn syscall, our path back is via an - rtb insn so setup r14 for that. */ - env->regs[14] = env->sregs[SR_PC]; + + if (do_sigaltstack(frame_addr + + offsetof(struct target_rt_sigframe, uc.tuc_stack), + 0, get_sp_from_cpustate(env)) == -EFAULT) { + goto badframe; + } unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; -badframe: + + badframe: + unlock_user_struct(frame, frame_addr, 0); force_sig(TARGET_SIGSEGV); return -TARGET_QEMU_ESIGRETURN; } - -long do_rt_sigreturn(CPUMBState *env) -{ - trace_user_do_rt_sigreturn(env, 0); - qemu_log_mask(LOG_UNIMP, "do_rt_sigreturn: not implemented\n"); - return -TARGET_ENOSYS; -} diff --git a/linux-user/microblaze/syscall.tbl b/linux-user/microblaze/syscall.tbl index 4c67b11f9c9ef83f70fb3b7cb891dbe81e271564..b4e263916f4132a9a710f4f6fc4f604f675d9e3a 100644 --- a/linux-user/microblaze/syscall.tbl +++ b/linux-user/microblaze/syscall.tbl @@ -156,7 +156,7 @@ 146 common writev sys_writev 147 common getsid sys_getsid 148 common fdatasync sys_fdatasync -149 common _sysctl sys_sysctl +149 common _sysctl sys_ni_syscall 150 common mlock sys_mlock 151 common munlock sys_munlock 152 common mlockall sys_mlockall @@ -441,5 +441,7 @@ 433 common fspick sys_fspick 434 common pidfd_open sys_pidfd_open 435 common clone3 sys_clone3 +436 common close_range sys_close_range 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd +439 common faccessat2 sys_faccessat2 diff --git a/linux-user/microblaze/target_cpu.h b/linux-user/microblaze/target_cpu.h index ce7b22ece7c4891a0c04cf0dea68b1ca32f9df51..dcae2ab94bf61d80b77e065fc4168bf4e2013984 100644 --- a/linux-user/microblaze/target_cpu.h +++ b/linux-user/microblaze/target_cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/microblaze/target_signal.h b/linux-user/microblaze/target_signal.h index 35efd5e928ae1c93e8a272cbd5e56dc4f8cdd476..1c326296de42c76efb43a676a725835664050f00 100644 --- a/linux-user/microblaze/target_signal.h +++ b/linux-user/microblaze/target_signal.h @@ -4,9 +4,9 @@ /* this struct defines a stack used during syscall handling */ typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_ulong ss_size; - abi_long ss_flags; + abi_ulong ss_sp; + abi_int ss_flags; + abi_ulong ss_size; } target_stack_t; @@ -21,5 +21,4 @@ typedef struct target_sigaltstack { #include "../generic/signal.h" -#define TARGET_ARCH_HAS_SETUP_FRAME #endif /* MICROBLAZE_TARGET_SIGNAL_H */ diff --git a/linux-user/microblaze/target_structs.h b/linux-user/microblaze/target_structs.h index 70dbdb6101f0d52a66c6db460ecfaf9e7c53cb10..d08f6a53a8d70a483bb555e4b23edc578b3b1473 100644 --- a/linux-user/microblaze/target_structs.h +++ b/linux-user/microblaze/target_structs.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/microblaze/target_syscall.h b/linux-user/microblaze/target_syscall.h index 4141cbaa5ec27bd66ed3b24e74af64c27b0d0a56..7f653db34f87bbbab5bc8605e16a585d5ba3ef0a 100644 --- a/linux-user/microblaze/target_syscall.h +++ b/linux-user/microblaze/target_syscall.h @@ -50,8 +50,9 @@ struct target_pt_regs { #define TARGET_CLONE_BACKWARDS #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 #define TARGET_WANT_NI_OLD_SELECT diff --git a/linux-user/microblaze/termbits.h b/linux-user/microblaze/termbits.h index 17db8a4473692c3853417bf1d35eba4c5def89bc..b1d4f4fedbcb9ab2ca1184280eb4a9e5b8a9d735 100644 --- a/linux-user/microblaze/termbits.h +++ b/linux-user/microblaze/termbits.h @@ -1,219 +1 @@ -/* from asm/termbits.h */ - -#ifndef LINUX_USER_MICROBLAZE_TERMBITS_H -#define LINUX_USER_MICROBLAZE_TERMBITS_H - -#define TARGET_NCCS 19 - -struct target_termios { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ -}; - -/* c_iflag bits */ -#define TARGET_IGNBRK 0000001 -#define TARGET_BRKINT 0000002 -#define TARGET_IGNPAR 0000004 -#define TARGET_PARMRK 0000010 -#define TARGET_INPCK 0000020 -#define TARGET_ISTRIP 0000040 -#define TARGET_INLCR 0000100 -#define TARGET_IGNCR 0000200 -#define TARGET_ICRNL 0000400 -#define TARGET_IUCLC 0001000 -#define TARGET_IXON 0002000 -#define TARGET_IXANY 0004000 -#define TARGET_IXOFF 0010000 -#define TARGET_IMAXBEL 0020000 - -/* c_oflag bits */ -#define TARGET_OPOST 0000001 -#define TARGET_OLCUC 0000002 -#define TARGET_ONLCR 0000004 -#define TARGET_OCRNL 0000010 -#define TARGET_ONOCR 0000020 -#define TARGET_ONLRET 0000040 -#define TARGET_OFILL 0000100 -#define TARGET_OFDEL 0000200 -#define TARGET_NLDLY 0000400 -#define TARGET_NL0 0000000 -#define TARGET_NL1 0000400 -#define TARGET_CRDLY 0003000 -#define TARGET_CR0 0000000 -#define TARGET_CR1 0001000 -#define TARGET_CR2 0002000 -#define TARGET_CR3 0003000 -#define TARGET_TABDLY 0014000 -#define TARGET_TAB0 0000000 -#define TARGET_TAB1 0004000 -#define TARGET_TAB2 0010000 -#define TARGET_TAB3 0014000 -#define TARGET_XTABS 0014000 -#define TARGET_BSDLY 0020000 -#define TARGET_BS0 0000000 -#define TARGET_BS1 0020000 -#define TARGET_VTDLY 0040000 -#define TARGET_VT0 0000000 -#define TARGET_VT1 0040000 -#define TARGET_FFDLY 0100000 -#define TARGET_FF0 0000000 -#define TARGET_FF1 0100000 - -/* c_cflag bit meaning */ -#define TARGET_CBAUD 0010017 -#define TARGET_B0 0000000 /* hang up */ -#define TARGET_B50 0000001 -#define TARGET_B75 0000002 -#define TARGET_B110 0000003 -#define TARGET_B134 0000004 -#define TARGET_B150 0000005 -#define TARGET_B200 0000006 -#define TARGET_B300 0000007 -#define TARGET_B600 0000010 -#define TARGET_B1200 0000011 -#define TARGET_B1800 0000012 -#define TARGET_B2400 0000013 -#define TARGET_B4800 0000014 -#define TARGET_B9600 0000015 -#define TARGET_B19200 0000016 -#define TARGET_B38400 0000017 -#define TARGET_EXTA B19200 -#define TARGET_EXTB B38400 -#define TARGET_CSIZE 0000060 -#define TARGET_CS5 0000000 -#define TARGET_CS6 0000020 -#define TARGET_CS7 0000040 -#define TARGET_CS8 0000060 -#define TARGET_CSTOPB 0000100 -#define TARGET_CREAD 0000200 -#define TARGET_PARENB 0000400 -#define TARGET_PARODD 0001000 -#define TARGET_HUPCL 0002000 -#define TARGET_CLOCAL 0004000 -#define TARGET_CBAUDEX 0010000 -#define TARGET_B57600 0010001 -#define TARGET_B115200 0010002 -#define TARGET_B230400 0010003 -#define TARGET_B460800 0010004 -#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */ -#define TARGET_CRTSCTS 020000000000 /* flow control */ - -/* c_lflag bits */ -#define TARGET_ISIG 0000001 -#define TARGET_ICANON 0000002 -#define TARGET_XCASE 0000004 -#define TARGET_ECHO 0000010 -#define TARGET_ECHOE 0000020 -#define TARGET_ECHOK 0000040 -#define TARGET_ECHONL 0000100 -#define TARGET_NOFLSH 0000200 -#define TARGET_TOSTOP 0000400 -#define TARGET_ECHOCTL 0001000 -#define TARGET_ECHOPRT 0002000 -#define TARGET_ECHOKE 0004000 -#define TARGET_FLUSHO 0010000 -#define TARGET_PENDIN 0040000 -#define TARGET_IEXTEN 0100000 - -/* c_cc character offsets */ -#define TARGET_VINTR 0 -#define TARGET_VQUIT 1 -#define TARGET_VERASE 2 -#define TARGET_VKILL 3 -#define TARGET_VEOF 4 -#define TARGET_VTIME 5 -#define TARGET_VMIN 6 -#define TARGET_VSWTC 7 -#define TARGET_VSTART 8 -#define TARGET_VSTOP 9 -#define TARGET_VSUSP 10 -#define TARGET_VEOL 11 -#define TARGET_VREPRINT 12 -#define TARGET_VDISCARD 13 -#define TARGET_VWERASE 14 -#define TARGET_VLNEXT 15 -#define TARGET_VEOL2 16 - -/* ioctls */ - -#define TARGET_TCGETS 0x5401 -#define TARGET_TCSETS 0x5402 -#define TARGET_TCSETSW 0x5403 -#define TARGET_TCSETSF 0x5404 -#define TARGET_TCGETA 0x5405 -#define TARGET_TCSETA 0x5406 -#define TARGET_TCSETAW 0x5407 -#define TARGET_TCSETAF 0x5408 -#define TARGET_TCSBRK 0x5409 -#define TARGET_TCXONC 0x540A -#define TARGET_TCFLSH 0x540B - -#define TARGET_TIOCEXCL 0x540C -#define TARGET_TIOCNXCL 0x540D -#define TARGET_TIOCSCTTY 0x540E -#define TARGET_TIOCGPGRP 0x540F -#define TARGET_TIOCSPGRP 0x5410 -#define TARGET_TIOCOUTQ 0x5411 -#define TARGET_TIOCSTI 0x5412 -#define TARGET_TIOCGWINSZ 0x5413 -#define TARGET_TIOCSWINSZ 0x5414 -#define TARGET_TIOCMGET 0x5415 -#define TARGET_TIOCMBIS 0x5416 -#define TARGET_TIOCMBIC 0x5417 -#define TARGET_TIOCMSET 0x5418 -#define TARGET_TIOCGSOFTCAR 0x5419 -#define TARGET_TIOCSSOFTCAR 0x541A -#define TARGET_FIONREAD 0x541B -#define TARGET_TIOCINQ TARGET_FIONREAD -#define TARGET_TIOCLINUX 0x541C -#define TARGET_TIOCCONS 0x541D -#define TARGET_TIOCGSERIAL 0x541E -#define TARGET_TIOCSSERIAL 0x541F -#define TARGET_TIOCPKT 0x5420 -#define TARGET_FIONBIO 0x5421 -#define TARGET_TIOCNOTTY 0x5422 -#define TARGET_TIOCSETD 0x5423 -#define TARGET_TIOCGETD 0x5424 -#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ -#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */ -#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ -#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ -#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ -#define TARGET_TIOCGPTN TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ -#define TARGET_TIOCSPTLCK TARGET_IOW('T',0x31, int) /* Lock/unlock Pty */ -#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) /* Safely open the slave */ - -#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */ -#define TARGET_FIOCLEX 0x5451 -#define TARGET_FIOASYNC 0x5452 -#define TARGET_TIOCSERCONFIG 0x5453 -#define TARGET_TIOCSERGWILD 0x5454 -#define TARGET_TIOCSERSWILD 0x5455 -#define TARGET_TIOCGLCKTRMIOS 0x5456 -#define TARGET_TIOCSLCKTRMIOS 0x5457 -#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ - -#define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ -#define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ -#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ -#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ - -/* Used for packet mode */ -#define TARGET_TIOCPKT_DATA 0 -#define TARGET_TIOCPKT_FLUSHREAD 1 -#define TARGET_TIOCPKT_FLUSHWRITE 2 -#define TARGET_TIOCPKT_STOP 4 -#define TARGET_TIOCPKT_START 8 -#define TARGET_TIOCPKT_NOSTOP 16 -#define TARGET_TIOCPKT_DOSTOP 32 - -#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - -#endif +#include "../generic/termbits.h" diff --git a/linux-user/mips/Makefile.objs b/linux-user/mips/Makefile.objs deleted file mode 100644 index 9be4de07d99aaef069468a1fd93996b71c79b594..0000000000000000000000000000000000000000 --- a/linux-user/mips/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -generated-files-y += linux-user/mips/syscall_nr.h - -syshdr := $(SRC_PATH)/linux-user/mips/syscallhdr.sh -%/syscall_nr.h: $(SRC_PATH)/linux-user/mips/syscall_o32.tbl $(syshdr) - $(call quiet-command, sh $(syshdr) $< $@ $(TARGET_SYSTBL_ABI) "" 4000,"GEN","$@") diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c index 553e8ca7f576467e54d7b23f3d2d836062645d37..cfe7ba5c47d888856d2e5691deb3828ded0fe70c 100644 --- a/linux-user/mips/cpu_loop.c +++ b/linux-user/mips/cpu_loop.c @@ -104,18 +104,22 @@ void cpu_loop(CPUMIPSState *env) if ((ret = get_user_ual(arg8, sp_reg + 28)) != 0) { goto done_syscall; } + /* fall through */ case 7: if ((ret = get_user_ual(arg7, sp_reg + 24)) != 0) { goto done_syscall; } + /* fall through */ case 6: if ((ret = get_user_ual(arg6, sp_reg + 20)) != 0) { goto done_syscall; } + /* fall through */ case 5: if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) { goto done_syscall; } + /* fall through */ default: break; } diff --git a/linux-user/mips/meson.build b/linux-user/mips/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..262a35703b827346f4689967a0d10d06f59f1dda --- /dev/null +++ b/linux-user/mips/meson.build @@ -0,0 +1,6 @@ +syscall_nr_generators += { + 'mips': generator(sh, + arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@', + '', '4000' ], + output: '@BASENAME@_nr.h') +} diff --git a/linux-user/mips/syscall-args-o32.c.inc b/linux-user/mips/syscall-args-o32.c.inc index 0ad35857b4e4c64fec0afa119c6cc20ac35aeb6c..92ee4f921ec75cae925c182f203d0b25bf7cdf29 100644 --- a/linux-user/mips/syscall-args-o32.c.inc +++ b/linux-user/mips/syscall-args-o32.c.inc @@ -434,3 +434,7 @@ [ 433] = 3, /* fspick */ [ 434] = 2, /* pidfd_open */ [ 435] = 2, /* clone3 */ + [ 436] = 3, /* close_range */ + [ 437] = 4, /* openat2 */ + [ 438] = 3, /* pidfd_getfd */ + [ 439] = 4, /* faccessat2 */ diff --git a/linux-user/mips/syscall_nr.h b/linux-user/mips/syscall_nr.h new file mode 100644 index 0000000000000000000000000000000000000000..45d133c6f914bdd1b806f934d3cee267f9009347 --- /dev/null +++ b/linux-user/mips/syscall_nr.h @@ -0,0 +1 @@ +#include "syscall_o32_nr.h" diff --git a/linux-user/mips/syscall_o32.tbl b/linux-user/mips/syscall_o32.tbl index ac586774c980537ed69d85ab4850adb79cd2c9e8..195b43cf27c84812e16b3214c9a9ea41de2d913a 100644 --- a/linux-user/mips/syscall_o32.tbl +++ b/linux-user/mips/syscall_o32.tbl @@ -164,7 +164,7 @@ 150 o32 unused150 sys_ni_syscall 151 o32 getsid sys_getsid 152 o32 fdatasync sys_fdatasync -153 o32 _sysctl sys_sysctl compat_sys_sysctl +153 o32 _sysctl sys_ni_syscall 154 o32 mlock sys_mlock 155 o32 munlock sys_munlock 156 o32 mlockall sys_mlockall @@ -184,7 +184,7 @@ 170 o32 connect sys_connect 171 o32 getpeername sys_getpeername 172 o32 getsockname sys_getsockname -173 o32 getsockopt sys_getsockopt compat_sys_getsockopt +173 o32 getsockopt sys_getsockopt sys_getsockopt 174 o32 listen sys_listen 175 o32 recv sys_recv compat_sys_recv 176 o32 recvfrom sys_recvfrom compat_sys_recvfrom @@ -192,7 +192,7 @@ 178 o32 send sys_send 179 o32 sendmsg sys_sendmsg compat_sys_sendmsg 180 o32 sendto sys_sendto -181 o32 setsockopt sys_setsockopt compat_sys_setsockopt +181 o32 setsockopt sys_setsockopt sys_setsockopt 182 o32 shutdown sys_shutdown 183 o32 socket sys_socket 184 o32 socketpair sys_socketpair @@ -423,5 +423,7 @@ 433 o32 fspick sys_fspick 434 o32 pidfd_open sys_pidfd_open 435 o32 clone3 __sys_clone3 +436 o32 close_range sys_close_range 437 o32 openat2 sys_openat2 438 o32 pidfd_getfd sys_pidfd_getfd +439 o32 faccessat2 sys_faccessat2 diff --git a/linux-user/mips/target_cpu.h b/linux-user/mips/target_cpu.h index 758ae4d933fe6f5be510d79ccf804b3ce2e4dcfc..c375616c557945ee1b506d6bcba0554c18419ba4 100644 --- a/linux-user/mips/target_cpu.h +++ b/linux-user/mips/target_cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/mips/target_signal.h b/linux-user/mips/target_signal.h index 66e1ad44a64ef0547920a6d8ce1844f6b251fda8..fa4084a99dcdab739fa4a144027578afac8c8d3a 100644 --- a/linux-user/mips/target_signal.h +++ b/linux-user/mips/target_signal.h @@ -45,9 +45,9 @@ /* this struct defines a stack used during syscall handling */ typedef struct target_sigaltstack { - abi_long ss_sp; - abi_ulong ss_size; - abi_long ss_flags; + abi_ulong ss_sp; + abi_ulong ss_size; + abi_int ss_flags; } target_stack_t; diff --git a/linux-user/mips/target_structs.h b/linux-user/mips/target_structs.h index 909ba897089f93f544227726368dbc89de8897dc..c1150fd9f2237f84aaa8ab0ace454f653ff52383 100644 --- a/linux-user/mips/target_structs.h +++ b/linux-user/mips/target_structs.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/mips/target_syscall.h b/linux-user/mips/target_syscall.h index d5509a34a7e240fc5d15ba1aafa743f7c4255e40..dd6fd7af8eac2fe1bde8e861796e19d1bd6a5239 100644 --- a/linux-user/mips/target_syscall.h +++ b/linux-user/mips/target_syscall.h @@ -234,8 +234,9 @@ struct target_pt_regs { #define TARGET_CLONE_BACKWARDS #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 #define TARGET_FORCE_SHMLBA diff --git a/linux-user/mips/termbits.h b/linux-user/mips/termbits.h index 3287cf6df8b8f6a60e71ba48188e97792adb0680..e8b4b58d878d4bba46aaced850a1d1bba4d426d1 100644 --- a/linux-user/mips/termbits.h +++ b/linux-user/mips/termbits.h @@ -5,13 +5,17 @@ #define TARGET_NCCS 23 +typedef unsigned char target_cc_t; /* cc_t */ +typedef unsigned int target_speed_t; /* speed_t */ +typedef unsigned int target_tcflag_t; /* tcflag_t */ + struct target_termios { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ + target_tcflag_t c_iflag; /* input mode flags */ + target_tcflag_t c_oflag; /* output mode flags */ + target_tcflag_t c_cflag; /* control mode flags */ + target_tcflag_t c_lflag; /* local mode flags */ + target_cc_t c_line; /* line discipline */ + target_cc_t c_cc[TARGET_NCCS]; /* control characters */ }; /* c_iflag bits */ @@ -133,6 +137,7 @@ struct target_termios { #define TARGET_PENDIN 0040000 #define TARGET_TOSTOP 0100000 #define TARGET_ITOSTOP TARGET_TOSTOP +#define TARGET_EXTPROC 0200000 /* c_cc character offsets */ #define TARGET_VINTR 0 diff --git a/linux-user/mips64/Makefile.objs b/linux-user/mips64/Makefile.objs deleted file mode 100644 index 573448f9568acb93a50a9f97716e18a4ad6eac91..0000000000000000000000000000000000000000 --- a/linux-user/mips64/Makefile.objs +++ /dev/null @@ -1,12 +0,0 @@ -generated-files-y += linux-user/$(TARGET_ABI_DIR)/syscall_nr.h - -syshdr := $(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)/syscallhdr.sh - -ifeq ($(TARGET_SYSTBL_ABI),n32) -%/syscall_nr.h: $(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)/syscall_n32.tbl $(syshdr) - $(call quiet-command, sh $(syshdr) $< $@ n32 "" 6000,"GEN","$@") -endif -ifeq ($(TARGET_SYSTBL_ABI),n64) -%/syscall_nr.h: $(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)/syscall_n64.tbl $(syshdr) - $(call quiet-command, sh $(syshdr) $< $@ n64 "" 5000,"GEN","$@") -endif diff --git a/linux-user/mips64/meson.build b/linux-user/mips64/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..0caab5fabda76674828fdd6a7ddd30a0865f7cf9 --- /dev/null +++ b/linux-user/mips64/meson.build @@ -0,0 +1,6 @@ +syscall_nr_generators += { + 'mips64': generator(sh, + arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@', + '', 'TARGET_SYSCALL_OFFSET' ], + output: '@BASENAME@_nr.h') +} diff --git a/linux-user/mips64/syscall_n32.tbl b/linux-user/mips64/syscall_n32.tbl index 1f9e8ad636cce34a128d143e604b6847caae0438..f9df9edb67a4077eea652097a5b3a50f6fa546ec 100644 --- a/linux-user/mips64/syscall_n32.tbl +++ b/linux-user/mips64/syscall_n32.tbl @@ -60,8 +60,8 @@ 50 n32 getsockname sys_getsockname 51 n32 getpeername sys_getpeername 52 n32 socketpair sys_socketpair -53 n32 setsockopt compat_sys_setsockopt -54 n32 getsockopt compat_sys_getsockopt +53 n32 setsockopt sys_setsockopt +54 n32 getsockopt sys_getsockopt 55 n32 clone __sys_clone 56 n32 fork __sys_fork 57 n32 execve compat_sys_execve @@ -159,7 +159,7 @@ 149 n32 munlockall sys_munlockall 150 n32 vhangup sys_vhangup 151 n32 pivot_root sys_pivot_root -152 n32 _sysctl compat_sys_sysctl +152 n32 _sysctl sys_ni_syscall 153 n32 prctl sys_prctl 154 n32 adjtimex sys_adjtimex_time32 155 n32 setrlimit compat_sys_setrlimit @@ -374,5 +374,7 @@ 433 n32 fspick sys_fspick 434 n32 pidfd_open sys_pidfd_open 435 n32 clone3 __sys_clone3 +436 n32 close_range sys_close_range 437 n32 openat2 sys_openat2 438 n32 pidfd_getfd sys_pidfd_getfd +439 n32 faccessat2 sys_faccessat2 diff --git a/linux-user/mips64/syscall_n64.tbl b/linux-user/mips64/syscall_n64.tbl index c0b9d802dbf6dd82c9b4be2a799871a5df8ef3db..557f9954a2b9a8fd66179f572d0fcffb63638bcd 100644 --- a/linux-user/mips64/syscall_n64.tbl +++ b/linux-user/mips64/syscall_n64.tbl @@ -159,7 +159,7 @@ 149 n64 munlockall sys_munlockall 150 n64 vhangup sys_vhangup 151 n64 pivot_root sys_pivot_root -152 n64 _sysctl sys_sysctl +152 n64 _sysctl sys_ni_syscall 153 n64 prctl sys_prctl 154 n64 adjtimex sys_adjtimex 155 n64 setrlimit sys_setrlimit @@ -350,5 +350,7 @@ 433 n64 fspick sys_fspick 434 n64 pidfd_open sys_pidfd_open 435 n64 clone3 __sys_clone3 +436 n64 close_range sys_close_range 437 n64 openat2 sys_openat2 438 n64 pidfd_getfd sys_pidfd_getfd +439 n64 faccessat2 sys_faccessat2 diff --git a/linux-user/mips64/syscall_nr.h b/linux-user/mips64/syscall_nr.h new file mode 100644 index 0000000000000000000000000000000000000000..672f2fa51cbaf280cce7bd789cd68ae1e9cd4ea8 --- /dev/null +++ b/linux-user/mips64/syscall_nr.h @@ -0,0 +1,7 @@ +#ifdef TARGET_ABI_MIPSN32 +#define TARGET_SYSCALL_OFFSET 6000 +#include "syscall_n32_nr.h" +#else +#define TARGET_SYSCALL_OFFSET 5000 +#include "syscall_n64_nr.h" +#endif diff --git a/linux-user/mips64/target_cpu.h b/linux-user/mips64/target_cpu.h index f16991b4ef83f3c89d04c264666cfdbd58dd149d..2857a76afda3074e757a9c25d44e2bedaf329854 100644 --- a/linux-user/mips64/target_cpu.h +++ b/linux-user/mips64/target_cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/mips64/target_signal.h b/linux-user/mips64/target_signal.h index 753e91fbd695f859f20c42fab238dc9a4c473d3b..799f7a668cd0f63808dd4f1f51b9adbef4840ae7 100644 --- a/linux-user/mips64/target_signal.h +++ b/linux-user/mips64/target_signal.h @@ -45,12 +45,11 @@ /* this struct defines a stack used during syscall handling */ typedef struct target_sigaltstack { - abi_long ss_sp; - abi_ulong ss_size; - abi_int ss_flags; + abi_ulong ss_sp; + abi_ulong ss_size; + abi_int ss_flags; } target_stack_t; - /* * sigaltstack controls */ diff --git a/linux-user/mips64/target_syscall.h b/linux-user/mips64/target_syscall.h index 8ccc46822c1122d31fad07ca6e768867c5870477..8594955eec260f5fcbbd69bdbf9ded58e50612ea 100644 --- a/linux-user/mips64/target_syscall.h +++ b/linux-user/mips64/target_syscall.h @@ -231,8 +231,9 @@ struct target_pt_regs { #define TARGET_CLONE_BACKWARDS #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 #define TARGET_FORCE_SHMLBA diff --git a/linux-user/mmap.c b/linux-user/mmap.c index e37803379747cfdfc905e6a922039cfb72fce9b2..00c05e6a0f198507344dcddf1a40d37c8518dc1c 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -59,64 +59,116 @@ void mmap_fork_end(int child) pthread_mutex_unlock(&mmap_mutex); } +/* + * Validate target prot bitmask. + * Return the prot bitmask for the host in *HOST_PROT. + * Return 0 if the target prot bitmask is invalid, otherwise + * the internal qemu page_flags (which will include PAGE_VALID). + */ +static int validate_prot_to_pageflags(int *host_prot, int prot) +{ + int valid = PROT_READ | PROT_WRITE | PROT_EXEC | TARGET_PROT_SEM; + int page_flags = (prot & PAGE_BITS) | PAGE_VALID; + + /* + * For the host, we need not pass anything except read/write/exec. + * While PROT_SEM is allowed by all hosts, it is also ignored, so + * don't bother transforming guest bit to host bit. Any other + * target-specific prot bits will not be understood by the host + * and will need to be encoded into page_flags for qemu emulation. + * + * Pages that are executable by the guest will never be executed + * by the host, but the host will need to be able to read them. + */ + *host_prot = (prot & (PROT_READ | PROT_WRITE)) + | (prot & PROT_EXEC ? PROT_READ : 0); + +#ifdef TARGET_AARCH64 + /* + * The PROT_BTI bit is only accepted if the cpu supports the feature. + * Since this is the unusual case, don't bother checking unless + * the bit has been requested. If set and valid, record the bit + * within QEMU's page_flags. + */ + if (prot & TARGET_PROT_BTI) { + ARMCPU *cpu = ARM_CPU(thread_cpu); + if (cpu_isar_feature(aa64_bti, cpu)) { + valid |= TARGET_PROT_BTI; + page_flags |= PAGE_BTI; + } + } +#endif + + return prot & ~valid ? 0 : page_flags; +} + /* NOTE: all the constants are the HOST ones, but addresses are target. */ -int target_mprotect(abi_ulong start, abi_ulong len, int prot) +int target_mprotect(abi_ulong start, abi_ulong len, int target_prot) { abi_ulong end, host_start, host_end, addr; - int prot1, ret; + int prot1, ret, page_flags, host_prot; - trace_target_mprotect(start, len, prot); + trace_target_mprotect(start, len, target_prot); - if ((start & ~TARGET_PAGE_MASK) != 0) + if ((start & ~TARGET_PAGE_MASK) != 0) { return -TARGET_EINVAL; + } + page_flags = validate_prot_to_pageflags(&host_prot, target_prot); + if (!page_flags) { + return -TARGET_EINVAL; + } len = TARGET_PAGE_ALIGN(len); end = start + len; if (!guest_range_valid(start, len)) { return -TARGET_ENOMEM; } - prot &= PROT_READ | PROT_WRITE | PROT_EXEC; - if (len == 0) + if (len == 0) { return 0; + } mmap_lock(); host_start = start & qemu_host_page_mask; host_end = HOST_PAGE_ALIGN(end); if (start > host_start) { /* handle host page containing start */ - prot1 = prot; - for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) { + prot1 = host_prot; + for (addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) { prot1 |= page_get_flags(addr); } if (host_end == host_start + qemu_host_page_size) { - for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { + for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { prot1 |= page_get_flags(addr); } end = host_end; } - ret = mprotect(g2h(host_start), qemu_host_page_size, prot1 & PAGE_BITS); - if (ret != 0) + ret = mprotect(g2h(host_start), qemu_host_page_size, + prot1 & PAGE_BITS); + if (ret != 0) { goto error; + } host_start += qemu_host_page_size; } if (end < host_end) { - prot1 = prot; - for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { + prot1 = host_prot; + for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { prot1 |= page_get_flags(addr); } - ret = mprotect(g2h(host_end - qemu_host_page_size), qemu_host_page_size, - prot1 & PAGE_BITS); - if (ret != 0) + ret = mprotect(g2h(host_end - qemu_host_page_size), + qemu_host_page_size, prot1 & PAGE_BITS); + if (ret != 0) { goto error; + } host_end -= qemu_host_page_size; } /* handle the pages in the middle */ if (host_start < host_end) { - ret = mprotect(g2h(host_start), host_end - host_start, prot); - if (ret != 0) + ret = mprotect(g2h(host_start), host_end - host_start, host_prot); + if (ret != 0) { goto error; + } } - page_set_flags(start, start + len, prot | PAGE_VALID); + page_set_flags(start, start + len, page_flags); mmap_unlock(); return 0; error: @@ -360,19 +412,26 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong align) } /* NOTE: all the constants are the HOST ones */ -abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, +abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot, int flags, int fd, abi_ulong offset) { abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len; + int page_flags, host_prot; mmap_lock(); - trace_target_mmap(start, len, prot, flags, fd, offset); + trace_target_mmap(start, len, target_prot, flags, fd, offset); if (!len) { errno = EINVAL; goto fail; } + page_flags = validate_prot_to_pageflags(&host_prot, target_prot); + if (!page_flags) { + errno = EINVAL; + goto fail; + } + /* Also check for overflows... */ len = TARGET_PAGE_ALIGN(len); if (!len) { @@ -438,14 +497,15 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, /* Note: we prefer to control the mapping address. It is especially important if qemu_host_page_size > qemu_real_host_page_size */ - p = mmap(g2h(start), host_len, prot, + p = mmap(g2h(start), host_len, host_prot, flags | MAP_FIXED | MAP_ANONYMOUS, -1, 0); - if (p == MAP_FAILED) + if (p == MAP_FAILED) { goto fail; + } /* update start so that it points to the file position at 'offset' */ host_start = (unsigned long)p; if (!(flags & MAP_ANONYMOUS)) { - p = mmap(g2h(start), len, prot, + p = mmap(g2h(start), len, host_prot, flags | MAP_FIXED, fd, host_offset); if (p == MAP_FAILED) { munmap(g2h(start), host_len); @@ -467,7 +527,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, * It can fail only on 64-bit host with 32-bit target. * On any other target/host host mmap() handles this error correctly. */ - if (!guest_range_valid(start, len)) { + if (end < start || !guest_range_valid(start, len)) { errno = ENOMEM; goto fail; } @@ -479,19 +539,19 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, /* msync() won't work here, so we return an error if write is possible while it is a shared mapping */ if ((flags & MAP_TYPE) == MAP_SHARED && - (prot & PROT_WRITE)) { + (host_prot & PROT_WRITE)) { errno = EINVAL; goto fail; } - retaddr = target_mmap(start, len, prot | PROT_WRITE, + retaddr = target_mmap(start, len, target_prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (retaddr == -1) goto fail; if (pread(fd, g2h(start), len, offset) == -1) goto fail; - if (!(prot & PROT_WRITE)) { - ret = target_mprotect(start, len, prot); + if (!(host_prot & PROT_WRITE)) { + ret = target_mprotect(start, len, target_prot); assert(ret == 0); } goto the_end; @@ -502,13 +562,13 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, if (real_end == real_start + qemu_host_page_size) { /* one single host page */ ret = mmap_frag(real_start, start, end, - prot, flags, fd, offset); + host_prot, flags, fd, offset); if (ret == -1) goto fail; goto the_end1; } ret = mmap_frag(real_start, start, real_start + qemu_host_page_size, - prot, flags, fd, offset); + host_prot, flags, fd, offset); if (ret == -1) goto fail; real_start += qemu_host_page_size; @@ -517,7 +577,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, if (end < real_end) { ret = mmap_frag(real_end - qemu_host_page_size, real_end - qemu_host_page_size, end, - prot, flags, fd, + host_prot, flags, fd, offset + real_end - qemu_host_page_size - start); if (ret == -1) goto fail; @@ -533,13 +593,13 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, else offset1 = offset + real_start - start; p = mmap(g2h(real_start), real_end - real_start, - prot, flags, fd, offset1); + host_prot, flags, fd, offset1); if (p == MAP_FAILED) goto fail; } } the_end1: - page_set_flags(start, start + len, prot | PAGE_VALID); + page_set_flags(start, start + len, page_flags); the_end: trace_target_mmap_complete(start); if (qemu_loglevel_mask(CPU_LOG_PAGE)) { @@ -708,7 +768,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size, if (prot == 0) { host_addr = mremap(g2h(old_addr), old_size, new_size, flags); if (host_addr != MAP_FAILED && reserved_va && old_size > new_size) { - mmap_reserve(old_addr + old_size, new_size - old_size); + mmap_reserve(old_addr + old_size, old_size - new_size); } } else { errno = ENOMEM; diff --git a/linux-user/nios2/syscall_nr.h b/linux-user/nios2/syscall_nr.h index 32d485dc9ae8453a850ba5d13183e328458e3bec..e37f40179bf3b016894cac436fb8a73ee704c398 100644 --- a/linux-user/nios2/syscall_nr.h +++ b/linux-user/nios2/syscall_nr.h @@ -318,7 +318,10 @@ #define TARGET_NR_fsmount 432 #define TARGET_NR_fspick 433 #define TARGET_NR_pidfd_open 434 -#define TARGET_NR_syscalls 436 +#define TARGET_NR_close_range 436 +#define TARGET_NR_openat2 437 +#define TARGET_NR_pidfd_getfd 438 +#define TARGET_NR_faccessat2 439 +#define TARGET_NR_syscalls 440 #endif /* LINUX_USER_NIOS2_SYSCALL_NR_H */ - diff --git a/linux-user/nios2/target_cpu.h b/linux-user/nios2/target_cpu.h index 50f03810675afbc7743892558faee0b1fbd548e4..2d2008f0026bea4919a2bdd5d07c430595561374 100644 --- a/linux-user/nios2/target_cpu.h +++ b/linux-user/nios2/target_cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/nios2/target_signal.h b/linux-user/nios2/target_signal.h index fe48721b3db07809a7eb58fc257f7b458a950c99..aebf749f1278f2221d2a9c8d99ab3e78177332f3 100644 --- a/linux-user/nios2/target_signal.h +++ b/linux-user/nios2/target_signal.h @@ -4,11 +4,12 @@ /* this struct defines a stack used during syscall handling */ typedef struct target_sigaltstack { - abi_long ss_sp; + abi_ulong ss_sp; + abi_int ss_flags; abi_ulong ss_size; - abi_long ss_flags; } target_stack_t; + /* sigaltstack controls */ #define TARGET_SS_ONSTACK 1 #define TARGET_SS_DISABLE 2 diff --git a/linux-user/nios2/target_structs.h b/linux-user/nios2/target_structs.h index 714525170663cfdd137ca102fd241b21ad60a357..daa2886f98d336312e2c8a93c27f1ef65b9f8fbd 100644 --- a/linux-user/nios2/target_structs.h +++ b/linux-user/nios2/target_structs.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/nios2/target_syscall.h b/linux-user/nios2/target_syscall.h index f3b2a500f43075c33af960dcba1892eecee0bf49..78006c24d479b589d401e6af66cef96e3a8f72a7 100644 --- a/linux-user/nios2/target_syscall.h +++ b/linux-user/nios2/target_syscall.h @@ -31,7 +31,8 @@ struct target_pt_regs { }; #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 #endif /* NIOS2_TARGET_SYSCALL_H */ diff --git a/linux-user/nios2/termbits.h b/linux-user/nios2/termbits.h index 425a2fe6ef600312f287d53d2da45b63bdb4b2f7..b1d4f4fedbcb9ab2ca1184280eb4a9e5b8a9d735 100644 --- a/linux-user/nios2/termbits.h +++ b/linux-user/nios2/termbits.h @@ -1,227 +1 @@ -/* from asm/termbits.h */ -/* NOTE: exactly the same as i386 */ - -#ifndef LINUX_USER_NIOS2_TERMBITS_H -#define LINUX_USER_NIOS2_TERMBITS_H - -#define TARGET_NCCS 19 - -struct target_termios { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ -}; - -/* c_iflag bits */ -#define TARGET_IGNBRK 0000001 -#define TARGET_BRKINT 0000002 -#define TARGET_IGNPAR 0000004 -#define TARGET_PARMRK 0000010 -#define TARGET_INPCK 0000020 -#define TARGET_ISTRIP 0000040 -#define TARGET_INLCR 0000100 -#define TARGET_IGNCR 0000200 -#define TARGET_ICRNL 0000400 -#define TARGET_IUCLC 0001000 -#define TARGET_IXON 0002000 -#define TARGET_IXANY 0004000 -#define TARGET_IXOFF 0010000 -#define TARGET_IMAXBEL 0020000 -#define TARGET_IUTF8 0040000 - -/* c_oflag bits */ -#define TARGET_OPOST 0000001 -#define TARGET_OLCUC 0000002 -#define TARGET_ONLCR 0000004 -#define TARGET_OCRNL 0000010 -#define TARGET_ONOCR 0000020 -#define TARGET_ONLRET 0000040 -#define TARGET_OFILL 0000100 -#define TARGET_OFDEL 0000200 -#define TARGET_NLDLY 0000400 -#define TARGET_NL0 0000000 -#define TARGET_NL1 0000400 -#define TARGET_CRDLY 0003000 -#define TARGET_CR0 0000000 -#define TARGET_CR1 0001000 -#define TARGET_CR2 0002000 -#define TARGET_CR3 0003000 -#define TARGET_TABDLY 0014000 -#define TARGET_TAB0 0000000 -#define TARGET_TAB1 0004000 -#define TARGET_TAB2 0010000 -#define TARGET_TAB3 0014000 -#define TARGET_XTABS 0014000 -#define TARGET_BSDLY 0020000 -#define TARGET_BS0 0000000 -#define TARGET_BS1 0020000 -#define TARGET_VTDLY 0040000 -#define TARGET_VT0 0000000 -#define TARGET_VT1 0040000 -#define TARGET_FFDLY 0100000 -#define TARGET_FF0 0000000 -#define TARGET_FF1 0100000 - -/* c_cflag bit meaning */ -#define TARGET_CBAUD 0010017 -#define TARGET_B0 0000000 /* hang up */ -#define TARGET_B50 0000001 -#define TARGET_B75 0000002 -#define TARGET_B110 0000003 -#define TARGET_B134 0000004 -#define TARGET_B150 0000005 -#define TARGET_B200 0000006 -#define TARGET_B300 0000007 -#define TARGET_B600 0000010 -#define TARGET_B1200 0000011 -#define TARGET_B1800 0000012 -#define TARGET_B2400 0000013 -#define TARGET_B4800 0000014 -#define TARGET_B9600 0000015 -#define TARGET_B19200 0000016 -#define TARGET_B38400 0000017 -#define TARGET_EXTA B19200 -#define TARGET_EXTB B38400 -#define TARGET_CSIZE 0000060 -#define TARGET_CS5 0000000 -#define TARGET_CS6 0000020 -#define TARGET_CS7 0000040 -#define TARGET_CS8 0000060 -#define TARGET_CSTOPB 0000100 -#define TARGET_CREAD 0000200 -#define TARGET_PARENB 0000400 -#define TARGET_PARODD 0001000 -#define TARGET_HUPCL 0002000 -#define TARGET_CLOCAL 0004000 -#define TARGET_CBAUDEX 0010000 -#define TARGET_B57600 0010001 -#define TARGET_B115200 0010002 -#define TARGET_B230400 0010003 -#define TARGET_B460800 0010004 -#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */ -#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ -#define TARGET_CRTSCTS 020000000000 /* flow control */ - -/* c_lflag bits */ -#define TARGET_ISIG 0000001 -#define TARGET_ICANON 0000002 -#define TARGET_XCASE 0000004 -#define TARGET_ECHO 0000010 -#define TARGET_ECHOE 0000020 -#define TARGET_ECHOK 0000040 -#define TARGET_ECHONL 0000100 -#define TARGET_NOFLSH 0000200 -#define TARGET_TOSTOP 0000400 -#define TARGET_ECHOCTL 0001000 -#define TARGET_ECHOPRT 0002000 -#define TARGET_ECHOKE 0004000 -#define TARGET_FLUSHO 0010000 -#define TARGET_PENDIN 0040000 -#define TARGET_IEXTEN 0100000 - -/* c_cc character offsets */ -#define TARGET_VINTR 0 -#define TARGET_VQUIT 1 -#define TARGET_VERASE 2 -#define TARGET_VKILL 3 -#define TARGET_VEOF 4 -#define TARGET_VTIME 5 -#define TARGET_VMIN 6 -#define TARGET_VSWTC 7 -#define TARGET_VSTART 8 -#define TARGET_VSTOP 9 -#define TARGET_VSUSP 10 -#define TARGET_VEOL 11 -#define TARGET_VREPRINT 12 -#define TARGET_VDISCARD 13 -#define TARGET_VWERASE 14 -#define TARGET_VLNEXT 15 -#define TARGET_VEOL2 16 - -/* ioctls */ - -#define TARGET_TCGETS 0x5401 -#define TARGET_TCSETS 0x5402 -#define TARGET_TCSETSW 0x5403 -#define TARGET_TCSETSF 0x5404 -#define TARGET_TCGETA 0x5405 -#define TARGET_TCSETA 0x5406 -#define TARGET_TCSETAW 0x5407 -#define TARGET_TCSETAF 0x5408 -#define TARGET_TCSBRK 0x5409 -#define TARGET_TCXONC 0x540A -#define TARGET_TCFLSH 0x540B - -#define TARGET_TIOCEXCL 0x540C -#define TARGET_TIOCNXCL 0x540D -#define TARGET_TIOCSCTTY 0x540E -#define TARGET_TIOCGPGRP 0x540F -#define TARGET_TIOCSPGRP 0x5410 -#define TARGET_TIOCOUTQ 0x5411 -#define TARGET_TIOCSTI 0x5412 -#define TARGET_TIOCGWINSZ 0x5413 -#define TARGET_TIOCSWINSZ 0x5414 -#define TARGET_TIOCMGET 0x5415 -#define TARGET_TIOCMBIS 0x5416 -#define TARGET_TIOCMBIC 0x5417 -#define TARGET_TIOCMSET 0x5418 -#define TARGET_TIOCGSOFTCAR 0x5419 -#define TARGET_TIOCSSOFTCAR 0x541A -#define TARGET_FIONREAD 0x541B -#define TARGET_TIOCINQ TARGET_FIONREAD -#define TARGET_TIOCLINUX 0x541C -#define TARGET_TIOCCONS 0x541D -#define TARGET_TIOCGSERIAL 0x541E -#define TARGET_TIOCSSERIAL 0x541F -#define TARGET_TIOCPKT 0x5420 -#define TARGET_FIONBIO 0x5421 -#define TARGET_TIOCNOTTY 0x5422 -#define TARGET_TIOCSETD 0x5423 -#define TARGET_TIOCGETD 0x5424 -#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ -#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */ -#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ -#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ -#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ -#define TARGET_TIOCGPTN TARGET_IOR('T', 0x30, unsigned int) - /* Get Pty Number (of pty-mux device) */ -#define TARGET_TIOCSPTLCK TARGET_IOW('T', 0x31, int) - /* Lock/unlock Pty */ -#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) - /* Safely open the slave */ - -#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */ -#define TARGET_FIOCLEX 0x5451 -#define TARGET_FIOASYNC 0x5452 -#define TARGET_TIOCSERCONFIG 0x5453 -#define TARGET_TIOCSERGWILD 0x5454 -#define TARGET_TIOCSERSWILD 0x5455 -#define TARGET_TIOCGLCKTRMIOS 0x5456 -#define TARGET_TIOCSLCKTRMIOS 0x5457 -#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ - -#define TARGET_TIOCMIWAIT 0x545C - /* wait for a change on serial input line(s) */ -#define TARGET_TIOCGICOUNT 0x545D - /* read serial port inline interrupt counts */ -#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ -#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ - -/* Used for packet mode */ -#define TARGET_TIOCPKT_DATA 0 -#define TARGET_TIOCPKT_FLUSHREAD 1 -#define TARGET_TIOCPKT_FLUSHWRITE 2 -#define TARGET_TIOCPKT_STOP 4 -#define TARGET_TIOCPKT_START 8 -#define TARGET_TIOCPKT_NOSTOP 16 -#define TARGET_TIOCPKT_DOSTOP 32 - -#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - -#endif +#include "../generic/termbits.h" diff --git a/linux-user/openrisc/syscall_nr.h b/linux-user/openrisc/syscall_nr.h index 340383beb2c662c120a8fc586205939e8675752f..a8fc0295109ada1609885e964af2205a2114845d 100644 --- a/linux-user/openrisc/syscall_nr.h +++ b/linux-user/openrisc/syscall_nr.h @@ -318,7 +318,11 @@ #define TARGET_NR_fsmount 432 #define TARGET_NR_fspick 433 #define TARGET_NR_pidfd_open 434 -#define TARGET_NR_syscalls 436 +#define TARGET_NR_clone3 435 +#define TARGET_NR_close_range 436 +#define TARGET_NR_openat2 437 +#define TARGET_NR_pidfd_getfd 438 +#define TARGET_NR_faccessat2 439 +#define TARGET_NR_syscalls 440 #endif /* LINUX_USER_OPENRISC_SYSCALL_NR_H */ - diff --git a/linux-user/openrisc/target_syscall.h b/linux-user/openrisc/target_syscall.h index d586d2a018a5ce3720d5166894a1140680c6655a..ef0d89a551d57551e77a9a7ae1ce5682c6fe299a 100644 --- a/linux-user/openrisc/target_syscall.h +++ b/linux-user/openrisc/target_syscall.h @@ -16,8 +16,9 @@ struct target_pt_regs { #define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 #define MMAP_SHIFT TARGET_PAGE_BITS diff --git a/linux-user/openrisc/termbits.h b/linux-user/openrisc/termbits.h index 7a635ffbc6feb17727f6a93969a5ece310680e67..b1d4f4fedbcb9ab2ca1184280eb4a9e5b8a9d735 100644 --- a/linux-user/openrisc/termbits.h +++ b/linux-user/openrisc/termbits.h @@ -1,301 +1 @@ -#ifndef LINUX_USER_OPENRISC_TERMBITS_H -#define LINUX_USER_OPENRISC_TERMBITS_H - -typedef unsigned char target_openrisc_cc; /*cc_t*/ -typedef unsigned int target_openrisc_speed; /*speed_t*/ -typedef unsigned int target_openrisc_tcflag; /*tcflag_t*/ - -#define TARGET_NCCS 19 -struct target_termios { - target_openrisc_tcflag c_iflag; /* input mode flags */ - target_openrisc_tcflag c_oflag; /* output mode flags */ - target_openrisc_tcflag c_cflag; /* control mode flags */ - target_openrisc_tcflag c_lflag; /* local mode flags */ - target_openrisc_cc c_line; /* line discipline */ - target_openrisc_cc c_cc[TARGET_NCCS]; /* control characters */ -}; - -struct target_termios2 { - target_openrisc_tcflag c_iflag; /* input mode flags */ - target_openrisc_tcflag c_oflag; /* output mode flags */ - target_openrisc_tcflag c_cflag; /* control mode flags */ - target_openrisc_tcflag c_lflag; /* local mode flags */ - target_openrisc_cc c_line; /* line discipline */ - target_openrisc_cc c_cc[TARGET_NCCS]; /* control characters */ - target_openrisc_speed c_ispeed; /* input speed */ - target_openrisc_speed c_ospeed; /* output speed */ -}; - -struct target_termios3 { - target_openrisc_tcflag c_iflag; /* input mode flags */ - target_openrisc_tcflag c_oflag; /* output mode flags */ - target_openrisc_tcflag c_cflag; /* control mode flags */ - target_openrisc_tcflag c_lflag; /* local mode flags */ - target_openrisc_cc c_line; /* line discipline */ - target_openrisc_cc c_cc[TARGET_NCCS]; /* control characters */ - target_openrisc_speed c_ispeed; /* input speed */ - target_openrisc_speed c_ospeed; /* output speed */ -}; - -/* c_cc characters */ -#define TARGET_VINTR 0 -#define TARGET_VQUIT 1 -#define TARGET_VERASE 2 -#define TARGET_VKILL 3 -#define TARGET_VEOF 4 -#define TARGET_VTIME 5 -#define TARGET_VMIN 6 -#define TARGET_VSWTC 7 -#define TARGET_VSTART 8 -#define TARGET_VSTOP 9 -#define TARGET_VSUSP 10 -#define TARGET_VEOL 11 -#define TARGET_VREPRINT 12 -#define TARGET_VDISCARD 13 -#define TARGET_VWERASE 14 -#define TARGET_VLNEXT 15 -#define TARGET_VEOL2 16 - -/* c_iflag bits */ -#define TARGET_IGNBRK 0000001 -#define TARGET_BRKINT 0000002 -#define TARGET_IGNPAR 0000004 -#define TARGET_PARMRK 0000010 -#define TARGET_INPCK 0000020 -#define TARGET_ISTRIP 0000040 -#define TARGET_INLCR 0000100 -#define TARGET_IGNCR 0000200 -#define TARGET_ICRNL 0000400 -#define TARGET_IUCLC 0001000 -#define TARGET_IXON 0002000 -#define TARGET_IXANY 0004000 -#define TARGET_IXOFF 0010000 -#define TARGET_IMAXBEL 0020000 -#define TARGET_IUTF8 0040000 - -/* c_oflag bits */ -#define TARGET_OPOST 0000001 -#define TARGET_OLCUC 0000002 -#define TARGET_ONLCR 0000004 -#define TARGET_OCRNL 0000010 -#define TARGET_ONOCR 0000020 -#define TARGET_ONLRET 0000040 -#define TARGET_OFILL 0000100 -#define TARGET_OFDEL 0000200 -#define TARGET_NLDLY 0000400 -#define TARGET_NL0 0000000 -#define TARGET_NL1 0000400 -#define TARGET_CRDLY 0003000 -#define TARGET_CR0 0000000 -#define TARGET_CR1 0001000 -#define TARGET_CR2 0002000 -#define TARGET_CR3 0003000 -#define TARGET_TABDLY 0014000 -#define TARGET_TAB0 0000000 -#define TARGET_TAB1 0004000 -#define TARGET_TAB2 0010000 -#define TARGET_TAB3 0014000 -#define TARGET_XTABS 0014000 -#define TARGET_BSDLY 0020000 -#define TARGET_BS0 0000000 -#define TARGET_BS1 0020000 -#define TARGET_VTDLY 0040000 -#define TARGET_VT0 0000000 -#define TARGET_VT1 0040000 -#define TARGET_FFDLY 0100000 -#define TARGET_FF0 0000000 -#define TARGET_FF1 0100000 - -/* c_cflag bit meaning */ -#define TARGET_CBAUD 0010017 -#define TARGET_B0 0000000 /* hang up */ -#define TARGET_B50 0000001 -#define TARGET_B75 0000002 -#define TARGET_B110 0000003 -#define TARGET_B134 0000004 -#define TARGET_B150 0000005 -#define TARGET_B200 0000006 -#define TARGET_B300 0000007 -#define TARGET_B600 0000010 -#define TARGET_B1200 0000011 -#define TARGET_B1800 0000012 -#define TARGET_B2400 0000013 -#define TARGET_B4800 0000014 -#define TARGET_B9600 0000015 -#define TARGET_B19200 0000016 -#define TARGET_B38400 0000017 -#define TARGET_EXTA B19200 -#define TARGET_EXTB B38400 -#define TARGET_CSIZE 0000060 -#define TARGET_CS5 0000000 -#define TARGET_CS6 0000020 -#define TARGET_CS7 0000040 -#define TARGET_CS8 0000060 -#define TARGET_CSTOPB 0000100 -#define TARGET_CREAD 0000200 -#define TARGET_PARENB 0000400 -#define TARGET_PARODD 0001000 -#define TARGET_HUPCL 0002000 -#define TARGET_CLOCAL 0004000 -#define TARGET_CBAUDEX 0010000 -#define TARGET_BOTHER 0010000 -#define TARGET_B57600 0010001 -#define TARGET_B115200 0010002 -#define TARGET_B230400 0010003 -#define TARGET_B460800 0010004 -#define TARGET_B500000 0010005 -#define TARGET_B576000 0010006 -#define TARGET_B921600 0010007 -#define TARGET_B1000000 0010010 -#define TARGET_B1152000 0010011 -#define TARGET_B1500000 0010012 -#define TARGET_B2000000 0010013 -#define TARGET_B2500000 0010014 -#define TARGET_B3000000 0010015 -#define TARGET_B3500000 0010016 -#define TARGET_B4000000 0010017 -#define TARGET_CIBAUD 002003600000 /* input baud rate */ -#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ -#define TARGET_CRTSCTS 020000000000 /* flow control */ - -#define TARGET_IBSHIFT 16 /* Shift from CBAUD to CIBAUD */ - -/* c_lflag bits */ -#define TARGET_ISIG 0000001 -#define TARGET_ICANON 0000002 -#define TARGET_XCASE 0000004 -#define TARGET_ECHO 0000010 -#define TARGET_ECHOE 0000020 -#define TARGET_ECHOK 0000040 -#define TARGET_ECHONL 0000100 -#define TARGET_NOFLSH 0000200 -#define TARGET_TOSTOP 0000400 -#define TARGET_ECHOCTL 0001000 -#define TARGET_ECHOPRT 0002000 -#define TARGET_ECHOKE 0004000 -#define TARGET_FLUSHO 0010000 -#define TARGET_PENDIN 0040000 -#define TARGET_IEXTEN 0100000 -#define TARGET_EXTPROC 0200000 - -/* tcflow() and TCXONC use these */ -#define TARGET_TCOOFF 0 -#define TARGET_TCOON 1 -#define TARGET_TCIOFF 2 -#define TARGET_TCION 3 - -/* tcflush() and TCFLSH use these */ -#define TARGET_TCIFLUSH 0 -#define TARGET_TCOFLUSH 1 -#define TARGET_TCIOFLUSH 2 - -/* tcsetattr uses these */ -#define TARGET_TCSANOW 0 -#define TARGET_TCSADRAIN 1 -#define TARGET_TCSAFLUSH 2 - -/* ioctls */ -#define TARGET_TCGETS 0x5401 -#define TARGET_TCSETS 0x5402 -#define TARGET_TCSETSW 0x5403 -#define TARGET_TCSETSF 0x5404 -#define TARGET_TCGETA 0x5405 -#define TARGET_TCSETA 0x5406 -#define TARGET_TCSETAW 0x5407 -#define TARGET_TCSETAF 0x5408 -#define TARGET_TCSBRK 0x5409 -#define TARGET_TCXONC 0x540A -#define TARGET_TCFLSH 0x540B -#define TARGET_TIOCEXCL 0x540C -#define TARGET_TIOCNXCL 0x540D -#define TARGET_TIOCSCTTY 0x540E -#define TARGET_TIOCGPGRP 0x540F -#define TARGET_TIOCSPGRP 0x5410 -#define TARGET_TIOCOUTQ 0x5411 -#define TARGET_TIOCSTI 0x5412 -#define TARGET_TIOCGWINSZ 0x5413 -#define TARGET_TIOCSWINSZ 0x5414 -#define TARGET_TIOCMGET 0x5415 -#define TARGET_TIOCMBIS 0x5416 -#define TARGET_TIOCMBIC 0x5417 -#define TARGET_TIOCMSET 0x5418 -#define TARGET_TIOCGSOFTCAR 0x5419 -#define TARGET_TIOCSSOFTCAR 0x541A -#define TARGET_FIONREAD 0x541B -#define TARGET_TIOCINQ FIONREAD -#define TARGET_TIOCLINUX 0x541C -#define TARGET_TIOCCONS 0x541D -#define TARGET_TIOCGSERIAL 0x541E -#define TARGET_TIOCSSERIAL 0x541F -#define TARGET_TIOCPKT 0x5420 -#define TARGET_FIONBIO 0x5421 -#define TARGET_TIOCNOTTY 0x5422 -#define TARGET_TIOCSETD 0x5423 -#define TARGET_TIOCGETD 0x5424 -#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ -#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ -#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ -#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ -#define TARGET_TCGETS2 TARGET_IOR('T', 0x2A, struct termios2) -#define TARGET_TCSETS2 TARGET_IOW('T', 0x2B, struct termios2) -#define TARGET_TCSETSW2 TARGET_IOW('T', 0x2C, struct termios2) -#define TARGET_TCSETSF2 TARGET_IOW('T', 0x2D, struct termios2) -#define TARGET_TIOCGRS485 0x542E -#ifndef TARGET_TIOCSRS485 -#define TARGET_TIOCSRS485 0x542F -#endif -/* Get Pty Number (of pty-mux device) */ -#define TARGET_TIOCGPTN TARGET_IOR('T', 0x30, unsigned int) -/* Lock/unlock Pty */ -#define TARGET_TIOCSPTLCK TARGET_IOW('T', 0x31, int) -/* Safely open the slave */ -#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) -/* Get primary device node of /dev/console */ -#define TARGET_TIOCGDEV TARGET_IOR('T', 0x32, unsigned int) -#define TARGET_TCGETX 0x5432 /* SYS5 TCGETX compatibility */ -#define TARGET_TCSETX 0x5433 -#define TARGET_TCSETXF 0x5434 -#define TARGET_TCSETXW 0x5435 -/* pty: generate signal */ -#define TARGET_TIOCSIG TARGET_IOW('T', 0x36, int) -#define TARGET_TIOCVHANGUP 0x5437 - -#define TARGET_FIONCLEX 0x5450 -#define TARGET_FIOCLEX 0x5451 -#define TARGET_FIOASYNC 0x5452 -#define TARGET_TIOCSERCONFIG 0x5453 -#define TARGET_TIOCSERGWILD 0x5454 -#define TARGET_TIOCSERSWILD 0x5455 -#define TARGET_TIOCGLCKTRMIOS 0x5456 -#define TARGET_TIOCSLCKTRMIOS 0x5457 -#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ - -/* wait for a change on serial input line(s) */ -#define TARGET_TIOCMIWAIT 0x545C -/* read serial port inline interrupt counts */ -#define TARGET_TIOCGICOUNT 0x545D - -/* - * Some arches already define TARGET_FIOQSIZE due to a historical - * conflict with a Hayes modem-specific ioctl value. - */ -#ifndef TARGET_FIOQSIZE -#define TARGET_FIOQSIZE 0x5460 -#endif - -/* Used for packet mode */ -#define TARGET_TIOCPKT_DATA 0 -#define TARGET_TIOCPKT_FLUSHREAD 1 -#define TARGET_TIOCPKT_FLUSHWRITE 2 -#define TARGET_TIOCPKT_STOP 4 -#define TARGET_TIOCPKT_START 8 -#define TARGET_TIOCPKT_NOSTOP 16 -#define TARGET_TIOCPKT_DOSTOP 32 -#define TARGET_TIOCPKT_IOCTL 64 - -#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - -#endif +#include "../generic/termbits.h" diff --git a/linux-user/ppc/Makefile.objs b/linux-user/ppc/Makefile.objs deleted file mode 100644 index be92e67eb160d0fd0b2e00e9d4701e3cedbcb6b5..0000000000000000000000000000000000000000 --- a/linux-user/ppc/Makefile.objs +++ /dev/null @@ -1,6 +0,0 @@ -generated-files-y += linux-user/$(TARGET_ABI_DIR)/syscall_nr.h - -syshdr := $(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)/syscallhdr.sh - -%/syscall_nr.h: $(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)/syscall.tbl $(syshdr) - $(call quiet-command, sh $(syshdr) $< $@ $(TARGET_SYSTBL_ABI),"GEN","$@") diff --git a/linux-user/ppc/cpu_loop.c b/linux-user/ppc/cpu_loop.c index 5b27f8603e339ebffcc41baad6df763c4c4d5839..df71e15a25677b39a3ef31b424a1c509c61afd5d 100644 --- a/linux-user/ppc/cpu_loop.c +++ b/linux-user/ppc/cpu_loop.c @@ -267,6 +267,7 @@ void cpu_loop(CPUPPCState *env) queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); break; case POWERPC_EXCP_SYSCALL: /* System call exception */ + case POWERPC_EXCP_SYSCALL_VECTORED: cpu_abort(cs, "Syscall exception while in user mode. " "Aborting\n"); break; diff --git a/linux-user/ppc/meson.build b/linux-user/ppc/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..19fead7bc83b22839701ed5e0953b36efd6dad19 --- /dev/null +++ b/linux-user/ppc/meson.build @@ -0,0 +1,5 @@ +syscall_nr_generators += { + 'ppc': generator(sh, + arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ], + output: '@BASENAME@_nr.h') +} diff --git a/linux-user/ppc/syscall.tbl b/linux-user/ppc/syscall.tbl index 35b61bfc1b1ae928158dee422a150c19c8d30e4e..c2d737ff2e7bec276dfa2b68cf766de454c648c6 100644 --- a/linux-user/ppc/syscall.tbl +++ b/linux-user/ppc/syscall.tbl @@ -9,7 +9,9 @@ # 0 nospu restart_syscall sys_restart_syscall 1 nospu exit sys_exit -2 nospu fork ppc_fork +2 32 fork ppc_fork sys_fork +2 64 fork sys_fork +2 spu fork sys_ni_syscall 3 common read sys_read 4 common write sys_write 5 common open sys_open compat_sys_open @@ -158,7 +160,9 @@ 119 32 sigreturn sys_sigreturn compat_sys_sigreturn 119 64 sigreturn sys_ni_syscall 119 spu sigreturn sys_ni_syscall -120 nospu clone ppc_clone +120 32 clone ppc_clone sys_clone +120 64 clone sys_clone +120 spu clone sys_ni_syscall 121 common setdomainname sys_setdomainname 122 common uname sys_newuname 123 common modify_ldt sys_ni_syscall @@ -193,7 +197,7 @@ 146 common writev sys_writev compat_sys_writev 147 common getsid sys_getsid 148 common fdatasync sys_fdatasync -149 nospu _sysctl sys_sysctl compat_sys_sysctl +149 nospu _sysctl sys_ni_syscall 150 common mlock sys_mlock 151 common munlock sys_munlock 152 common mlockall sys_mlockall @@ -240,7 +244,9 @@ 186 spu sendfile sys_sendfile64 187 common getpmsg sys_ni_syscall 188 common putpmsg sys_ni_syscall -189 nospu vfork ppc_vfork +189 32 vfork ppc_vfork sys_vfork +189 64 vfork sys_vfork +189 spu vfork sys_ni_syscall 190 common ugetrlimit sys_getrlimit compat_sys_getrlimit 191 common readahead sys_readahead compat_sys_readahead 192 32 mmap2 sys_mmap2 compat_sys_mmap2 @@ -316,8 +322,8 @@ 248 32 clock_nanosleep sys_clock_nanosleep_time32 248 64 clock_nanosleep sys_clock_nanosleep 248 spu clock_nanosleep sys_clock_nanosleep -249 32 swapcontext ppc_swapcontext ppc32_swapcontext -249 64 swapcontext ppc64_swapcontext +249 32 swapcontext ppc_swapcontext compat_sys_swapcontext +249 64 swapcontext sys_swapcontext 249 spu swapcontext sys_ni_syscall 250 common tgkill sys_tgkill 251 32 utimes sys_utimes_time32 @@ -427,8 +433,8 @@ 336 common recv sys_recv compat_sys_recv 337 common recvfrom sys_recvfrom compat_sys_recvfrom 338 common shutdown sys_shutdown -339 common setsockopt sys_setsockopt compat_sys_setsockopt -340 common getsockopt sys_getsockopt compat_sys_getsockopt +339 common setsockopt sys_setsockopt sys_setsockopt +340 common getsockopt sys_getsockopt sys_getsockopt 341 common sendmsg sys_sendmsg compat_sys_sendmsg 342 common recvmsg sys_recvmsg compat_sys_recvmsg 343 32 recvmmsg sys_recvmmsg_time32 compat_sys_recvmmsg_time32 @@ -456,7 +462,7 @@ 361 common bpf sys_bpf 362 nospu execveat sys_execveat compat_sys_execveat 363 32 switch_endian sys_ni_syscall -363 64 switch_endian ppc_switch_endian +363 64 switch_endian sys_switch_endian 363 spu switch_endian sys_ni_syscall 364 common userfaultfd sys_userfaultfd 365 common membarrier sys_membarrier @@ -516,6 +522,10 @@ 432 common fsmount sys_fsmount 433 common fspick sys_fspick 434 common pidfd_open sys_pidfd_open -435 nospu clone3 ppc_clone3 +435 32 clone3 ppc_clone3 sys_clone3 +435 64 clone3 sys_clone3 +435 spu clone3 sys_ni_syscall +436 common close_range sys_close_range 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd +439 common faccessat2 sys_faccessat2 diff --git a/linux-user/ppc/target_cpu.h b/linux-user/ppc/target_cpu.h index 76b67d2882bf7ab7e1b1436ccb8cc31e7e210cfe..51ee1481b5ccb63a78e444fe4d124f32e6b745af 100644 --- a/linux-user/ppc/target_cpu.h +++ b/linux-user/ppc/target_cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/ppc/target_signal.h b/linux-user/ppc/target_signal.h index 4453e2e7efd7dee2a0a44420ef80ec497e22bb1a..72fcdd9bfa20ccf9185283017dffb85246a022bf 100644 --- a/linux-user/ppc/target_signal.h +++ b/linux-user/ppc/target_signal.h @@ -4,9 +4,9 @@ /* this struct defines a stack used during syscall handling */ typedef struct target_sigaltstack { - abi_ulong ss_sp; - int ss_flags; - abi_ulong ss_size; + abi_ulong ss_sp; + abi_int ss_flags; + abi_ulong ss_size; } target_stack_t; diff --git a/linux-user/ppc/target_structs.h b/linux-user/ppc/target_structs.h index 6b1f5791a95718ffceb2f162a2676f91fa7b3919..520e32664f010122cfc3288e7720ed5a201d3b5c 100644 --- a/linux-user/ppc/target_structs.h +++ b/linux-user/ppc/target_structs.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/ppc/target_syscall.h b/linux-user/ppc/target_syscall.h index afc0570410d849b82e6096ea9bb9168658785954..b9c4b813d3e4093f2ad75f16a35aeb10c81774a2 100644 --- a/linux-user/ppc/target_syscall.h +++ b/linux-user/ppc/target_syscall.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -72,8 +72,9 @@ struct target_revectored_struct { #define TARGET_CLONE_BACKWARDS #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 0x2000 -#define TARGET_MLOCKALL_MCL_FUTURE 0x4000 +#define TARGET_MCL_CURRENT 0x2000 +#define TARGET_MCL_FUTURE 0x4000 +#define TARGET_MCL_ONFAULT 0x8000 #define TARGET_WANT_NI_OLD_SELECT #endif /* PPC_TARGET_SYSCALL_H */ diff --git a/linux-user/ppc/termbits.h b/linux-user/ppc/termbits.h index 19e4c6eda86c2529c992389baab3f5fd306554c3..eb226e099980b3e6731b05e75e757ab4c85ad9a8 100644 --- a/linux-user/ppc/termbits.h +++ b/linux-user/ppc/termbits.h @@ -5,15 +5,19 @@ #define TARGET_NCCS 19 +typedef unsigned char target_cc_t; /* cc_t */ +typedef unsigned int target_speed_t; /* speed_t */ +typedef unsigned int target_tcflag_t; /* tcflag_t */ + struct target_termios { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ - unsigned char c_line; /* line discipline */ - unsigned int c_ispeed; /* input speed */ - unsigned int c_ospeed; /* output speed */ + target_tcflag_t c_iflag; /* input mode flags */ + target_tcflag_t c_oflag; /* output mode flags */ + target_tcflag_t c_cflag; /* control mode flags */ + target_tcflag_t c_lflag; /* local mode flags */ + target_cc_t c_cc[TARGET_NCCS]; /* control characters */ + target_cc_t c_line; /* line discipline */ + target_speed_t c_ispeed; /* input speed */ + target_speed_t c_ospeed; /* output speed */ }; /* c_cc character offsets */ @@ -158,6 +162,7 @@ struct target_termios { #define TARGET_FLUSHO 0x00800000 #define TARGET_PENDIN 0x20000000 #define TARGET_IEXTEN 0x00000400 +#define TARGET_EXTPROC 0x10000000 /* ioctls */ diff --git a/linux-user/qemu.h b/linux-user/qemu.h index ce902f5132a688601b5097680b8f38641fe7143f..534753ca12542383002cbf5544ac5027c02938cf 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -61,6 +61,10 @@ struct image_info { abi_ulong interpreter_loadmap_addr; abi_ulong interpreter_pt_dynamic_addr; struct image_info *other_info; + + /* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */ + uint32_t note_flags; + #ifdef TARGET_MIPS int fp_abi; int interp_fp_abi; @@ -146,7 +150,7 @@ typedef struct TaskState { /* Nonzero if process_pending_signals() needs to do something (either * handle a pending signal or unblock signals). * This flag is written from a signal handler so should be accessed via - * the atomic_read() and atomic_set() functions. (It is not accessed + * the qatomic_read() and qatomic_set() functions. (It is not accessed * from multiple threads.) */ int signal_pending; @@ -184,6 +188,26 @@ struct linux_binprm { int (*core_dump)(int, const CPUArchState *); /* coredump routine */ }; +typedef struct IOCTLEntry IOCTLEntry; + +typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp, + int fd, int cmd, abi_long arg); + +struct IOCTLEntry { + int target_cmd; + unsigned int host_cmd; + const char *name; + int access; + do_ioctl_fn *do_ioctl; + const argtype arg_type[5]; +}; + +extern IOCTLEntry ioctl_entries[]; + +#define IOC_R 0x0001 +#define IOC_W 0x0002 +#define IOC_RW (IOC_R | IOC_W) + void do_init_thread(struct target_pt_regs *regs, struct image_info *infop); abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, abi_ulong stringp, int push_ptr); @@ -380,10 +404,12 @@ extern long safe_syscall_base(int *pending, long number, ...); int host_to_target_waitstatus(int status); /* strace.c */ -void print_syscall(int num, +void print_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6); -void print_syscall_ret(int num, abi_long arg1); +void print_syscall_ret(void *cpu_env, int num, abi_long ret, + abi_long arg1, abi_long arg2, abi_long arg3, + abi_long arg4, abi_long arg5, abi_long arg6); /** * print_taken_signal: * @target_signum: target signal being taken @@ -668,6 +694,58 @@ static inline int is_error(abi_long ret) return (abi_ulong)ret >= (abi_ulong)(-4096); } +#if TARGET_ABI_BITS == 32 +static inline uint64_t target_offset64(uint32_t word0, uint32_t word1) +{ +#ifdef TARGET_WORDS_BIGENDIAN + return ((uint64_t)word0 << 32) | word1; +#else + return ((uint64_t)word1 << 32) | word0; +#endif +} +#else /* TARGET_ABI_BITS == 32 */ +static inline uint64_t target_offset64(uint64_t word0, uint64_t word1) +{ + return word0; +} +#endif /* TARGET_ABI_BITS != 32 */ + +void print_termios(void *arg); + +/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */ +#ifdef TARGET_ARM +static inline int regpairs_aligned(void *cpu_env, int num) +{ + return ((((CPUARMState *)cpu_env)->eabi) == 1) ; +} +#elif defined(TARGET_MIPS) && (TARGET_ABI_BITS == 32) +static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } +#elif defined(TARGET_PPC) && !defined(TARGET_PPC64) +/* + * SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs + * of registers which translates to the same as ARM/MIPS, because we start with + * r3 as arg1 + */ +static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } +#elif defined(TARGET_SH4) +/* SH4 doesn't align register pairs, except for p{read,write}64 */ +static inline int regpairs_aligned(void *cpu_env, int num) +{ + switch (num) { + case TARGET_NR_pread64: + case TARGET_NR_pwrite64: + return 1; + + default: + return 0; + } +} +#elif defined(TARGET_XTENSA) +static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } +#else +static inline int regpairs_aligned(void *cpu_env, int num) { return 0; } +#endif + /** * preexit_cleanup: housekeeping before the guest exits * diff --git a/linux-user/riscv/syscall32_nr.h b/linux-user/riscv/syscall32_nr.h index 4fef73e954da9d1e9c5c07b16606f19c51df7f92..079b804daef5b3c13785053a8b605d9312b8befb 100644 --- a/linux-user/riscv/syscall32_nr.h +++ b/linux-user/riscv/syscall32_nr.h @@ -1,5 +1,7 @@ /* * This file contains the system call numbers. + * Do not modify. + * This file is generated by scripts/gensyscalls.sh */ #ifndef LINUX_USER_RISCV_SYSCALL32_NR_H #define LINUX_USER_RISCV_SYSCALL32_NR_H @@ -290,6 +292,10 @@ #define TARGET_NR_fspick 433 #define TARGET_NR_pidfd_open 434 #define TARGET_NR_clone3 435 -#define TARGET_NR_syscalls 436 +#define TARGET_NR_close_range 436 +#define TARGET_NR_openat2 437 +#define TARGET_NR_pidfd_getfd 438 +#define TARGET_NR_faccessat2 439 +#define TARGET_NR_syscalls 440 #endif /* LINUX_USER_RISCV_SYSCALL32_NR_H */ diff --git a/linux-user/riscv/syscall64_nr.h b/linux-user/riscv/syscall64_nr.h index cc82f3244f55aec73a986e3c374f72927c613ea0..d54224ccec64a734be56e0e26583250260eeb43b 100644 --- a/linux-user/riscv/syscall64_nr.h +++ b/linux-user/riscv/syscall64_nr.h @@ -1,5 +1,7 @@ /* * This file contains the system call numbers. + * Do not modify. + * This file is generated by scripts/gensyscalls.sh */ #ifndef LINUX_USER_RISCV_SYSCALL64_NR_H #define LINUX_USER_RISCV_SYSCALL64_NR_H @@ -296,6 +298,10 @@ #define TARGET_NR_fspick 433 #define TARGET_NR_pidfd_open 434 #define TARGET_NR_clone3 435 -#define TARGET_NR_syscalls 436 +#define TARGET_NR_close_range 436 +#define TARGET_NR_openat2 437 +#define TARGET_NR_pidfd_getfd 438 +#define TARGET_NR_faccessat2 439 +#define TARGET_NR_syscalls 440 #endif /* LINUX_USER_RISCV_SYSCALL64_NR_H */ diff --git a/linux-user/riscv/target_syscall.h b/linux-user/riscv/target_syscall.h index a88e821f733ddabff62a91ead66d4677a92c7e33..dc597c897222bb7ad5d7a61cc5518b63e1c5169b 100644 --- a/linux-user/riscv/target_syscall.h +++ b/linux-user/riscv/target_syscall.h @@ -51,8 +51,9 @@ struct target_pt_regs { #define UNAME_MINIMUM_RELEASE "4.15.0" #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 /* clone(flags, newsp, ptidptr, tls, ctidptr) for RISC-V */ /* This comes from linux/kernel/fork.c, CONFIG_CLONE_BACKWARDS */ diff --git a/linux-user/riscv/termbits.h b/linux-user/riscv/termbits.h index 5e0af0dd3f5cbbf0b17a5a9b7deebb1b2746e843..b1d4f4fedbcb9ab2ca1184280eb4a9e5b8a9d735 100644 --- a/linux-user/riscv/termbits.h +++ b/linux-user/riscv/termbits.h @@ -1,227 +1 @@ -/* from asm/termbits.h */ -/* NOTE: exactly the same as i386 */ - -#ifndef LINUX_USER_RISCV_TERMBITS_H -#define LINUX_USER_RISCV_TERMBITS_H - -#define TARGET_NCCS 19 - -struct target_termios { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ -}; - -/* c_iflag bits */ -#define TARGET_IGNBRK 0000001 -#define TARGET_BRKINT 0000002 -#define TARGET_IGNPAR 0000004 -#define TARGET_PARMRK 0000010 -#define TARGET_INPCK 0000020 -#define TARGET_ISTRIP 0000040 -#define TARGET_INLCR 0000100 -#define TARGET_IGNCR 0000200 -#define TARGET_ICRNL 0000400 -#define TARGET_IUCLC 0001000 -#define TARGET_IXON 0002000 -#define TARGET_IXANY 0004000 -#define TARGET_IXOFF 0010000 -#define TARGET_IMAXBEL 0020000 -#define TARGET_IUTF8 0040000 - -/* c_oflag bits */ -#define TARGET_OPOST 0000001 -#define TARGET_OLCUC 0000002 -#define TARGET_ONLCR 0000004 -#define TARGET_OCRNL 0000010 -#define TARGET_ONOCR 0000020 -#define TARGET_ONLRET 0000040 -#define TARGET_OFILL 0000100 -#define TARGET_OFDEL 0000200 -#define TARGET_NLDLY 0000400 -#define TARGET_NL0 0000000 -#define TARGET_NL1 0000400 -#define TARGET_CRDLY 0003000 -#define TARGET_CR0 0000000 -#define TARGET_CR1 0001000 -#define TARGET_CR2 0002000 -#define TARGET_CR3 0003000 -#define TARGET_TABDLY 0014000 -#define TARGET_TAB0 0000000 -#define TARGET_TAB1 0004000 -#define TARGET_TAB2 0010000 -#define TARGET_TAB3 0014000 -#define TARGET_XTABS 0014000 -#define TARGET_BSDLY 0020000 -#define TARGET_BS0 0000000 -#define TARGET_BS1 0020000 -#define TARGET_VTDLY 0040000 -#define TARGET_VT0 0000000 -#define TARGET_VT1 0040000 -#define TARGET_FFDLY 0100000 -#define TARGET_FF0 0000000 -#define TARGET_FF1 0100000 - -/* c_cflag bit meaning */ -#define TARGET_CBAUD 0010017 -#define TARGET_B0 0000000 /* hang up */ -#define TARGET_B50 0000001 -#define TARGET_B75 0000002 -#define TARGET_B110 0000003 -#define TARGET_B134 0000004 -#define TARGET_B150 0000005 -#define TARGET_B200 0000006 -#define TARGET_B300 0000007 -#define TARGET_B600 0000010 -#define TARGET_B1200 0000011 -#define TARGET_B1800 0000012 -#define TARGET_B2400 0000013 -#define TARGET_B4800 0000014 -#define TARGET_B9600 0000015 -#define TARGET_B19200 0000016 -#define TARGET_B38400 0000017 -#define TARGET_EXTA B19200 -#define TARGET_EXTB B38400 -#define TARGET_CSIZE 0000060 -#define TARGET_CS5 0000000 -#define TARGET_CS6 0000020 -#define TARGET_CS7 0000040 -#define TARGET_CS8 0000060 -#define TARGET_CSTOPB 0000100 -#define TARGET_CREAD 0000200 -#define TARGET_PARENB 0000400 -#define TARGET_PARODD 0001000 -#define TARGET_HUPCL 0002000 -#define TARGET_CLOCAL 0004000 -#define TARGET_CBAUDEX 0010000 -#define TARGET_B57600 0010001 -#define TARGET_B115200 0010002 -#define TARGET_B230400 0010003 -#define TARGET_B460800 0010004 -#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */ -#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ -#define TARGET_CRTSCTS 020000000000 /* flow control */ - -/* c_lflag bits */ -#define TARGET_ISIG 0000001 -#define TARGET_ICANON 0000002 -#define TARGET_XCASE 0000004 -#define TARGET_ECHO 0000010 -#define TARGET_ECHOE 0000020 -#define TARGET_ECHOK 0000040 -#define TARGET_ECHONL 0000100 -#define TARGET_NOFLSH 0000200 -#define TARGET_TOSTOP 0000400 -#define TARGET_ECHOCTL 0001000 -#define TARGET_ECHOPRT 0002000 -#define TARGET_ECHOKE 0004000 -#define TARGET_FLUSHO 0010000 -#define TARGET_PENDIN 0040000 -#define TARGET_IEXTEN 0100000 - -/* c_cc character offsets */ -#define TARGET_VINTR 0 -#define TARGET_VQUIT 1 -#define TARGET_VERASE 2 -#define TARGET_VKILL 3 -#define TARGET_VEOF 4 -#define TARGET_VTIME 5 -#define TARGET_VMIN 6 -#define TARGET_VSWTC 7 -#define TARGET_VSTART 8 -#define TARGET_VSTOP 9 -#define TARGET_VSUSP 10 -#define TARGET_VEOL 11 -#define TARGET_VREPRINT 12 -#define TARGET_VDISCARD 13 -#define TARGET_VWERASE 14 -#define TARGET_VLNEXT 15 -#define TARGET_VEOL2 16 - -/* ioctls */ - -#define TARGET_TCGETS 0x5401 -#define TARGET_TCSETS 0x5402 -#define TARGET_TCSETSW 0x5403 -#define TARGET_TCSETSF 0x5404 -#define TARGET_TCGETA 0x5405 -#define TARGET_TCSETA 0x5406 -#define TARGET_TCSETAW 0x5407 -#define TARGET_TCSETAF 0x5408 -#define TARGET_TCSBRK 0x5409 -#define TARGET_TCXONC 0x540A -#define TARGET_TCFLSH 0x540B - -#define TARGET_TIOCEXCL 0x540C -#define TARGET_TIOCNXCL 0x540D -#define TARGET_TIOCSCTTY 0x540E -#define TARGET_TIOCGPGRP 0x540F -#define TARGET_TIOCSPGRP 0x5410 -#define TARGET_TIOCOUTQ 0x5411 -#define TARGET_TIOCSTI 0x5412 -#define TARGET_TIOCGWINSZ 0x5413 -#define TARGET_TIOCSWINSZ 0x5414 -#define TARGET_TIOCMGET 0x5415 -#define TARGET_TIOCMBIS 0x5416 -#define TARGET_TIOCMBIC 0x5417 -#define TARGET_TIOCMSET 0x5418 -#define TARGET_TIOCGSOFTCAR 0x5419 -#define TARGET_TIOCSSOFTCAR 0x541A -#define TARGET_FIONREAD 0x541B -#define TARGET_TIOCINQ TARGET_FIONREAD -#define TARGET_TIOCLINUX 0x541C -#define TARGET_TIOCCONS 0x541D -#define TARGET_TIOCGSERIAL 0x541E -#define TARGET_TIOCSSERIAL 0x541F -#define TARGET_TIOCPKT 0x5420 -#define TARGET_FIONBIO 0x5421 -#define TARGET_TIOCNOTTY 0x5422 -#define TARGET_TIOCSETD 0x5423 -#define TARGET_TIOCGETD 0x5424 -#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ -#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */ -#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ -#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ -#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ -#define TARGET_TIOCGPTN TARGET_IOR('T', 0x30, unsigned int) - /* Get Pty Number (of pty-mux device) */ -#define TARGET_TIOCSPTLCK TARGET_IOW('T', 0x31, int) - /* Lock/unlock Pty */ -#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) - /* Safely open the slave */ - -#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */ -#define TARGET_FIOCLEX 0x5451 -#define TARGET_FIOASYNC 0x5452 -#define TARGET_TIOCSERCONFIG 0x5453 -#define TARGET_TIOCSERGWILD 0x5454 -#define TARGET_TIOCSERSWILD 0x5455 -#define TARGET_TIOCGLCKTRMIOS 0x5456 -#define TARGET_TIOCSLCKTRMIOS 0x5457 -#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ - -#define TARGET_TIOCMIWAIT 0x545C - /* wait for a change on serial input line(s) */ -#define TARGET_TIOCGICOUNT 0x545D - /* read serial port inline interrupt counts */ -#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ -#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ - -/* Used for packet mode */ -#define TARGET_TIOCPKT_DATA 0 -#define TARGET_TIOCPKT_FLUSHREAD 1 -#define TARGET_TIOCPKT_FLUSHWRITE 2 -#define TARGET_TIOCPKT_STOP 4 -#define TARGET_TIOCPKT_START 8 -#define TARGET_TIOCPKT_NOSTOP 16 -#define TARGET_TIOCPKT_DOSTOP 32 - -#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - -#endif +#include "../generic/termbits.h" diff --git a/linux-user/s390x/Makefile.objs b/linux-user/s390x/Makefile.objs deleted file mode 100644 index f30f1625ccff4a09871a697fa51fcaec3c66dfdb..0000000000000000000000000000000000000000 --- a/linux-user/s390x/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -generated-files-y += linux-user/s390x/syscall_nr.h - -syshdr := $(SRC_PATH)/linux-user/s390x/syscallhdr.sh -%/syscall_nr.h: $(SRC_PATH)/linux-user/s390x/syscall.tbl $(syshdr) - $(call quiet-command, sh $(syshdr) $< $@ $(TARGET_SYSTBL_ABI),"GEN","$@") diff --git a/linux-user/s390x/meson.build b/linux-user/s390x/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..0781ccea1dcde333dee7c56c867f44ffa8897696 --- /dev/null +++ b/linux-user/s390x/meson.build @@ -0,0 +1,5 @@ +syscall_nr_generators += { + 's390x': generator(sh, + arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ], + output: '@BASENAME@_nr.h') +} diff --git a/linux-user/s390x/syscall.tbl b/linux-user/s390x/syscall.tbl index bd7bd3581a0fcd4f830d774c8fb98b53fa0066db..10456bc936fb09d87afee4fae97fc75ac2ea0b06 100644 --- a/linux-user/s390x/syscall.tbl +++ b/linux-user/s390x/syscall.tbl @@ -138,7 +138,7 @@ 146 common writev sys_writev compat_sys_writev 147 common getsid sys_getsid sys_getsid 148 common fdatasync sys_fdatasync sys_fdatasync -149 common _sysctl sys_sysctl compat_sys_sysctl +149 common _sysctl - - 150 common mlock sys_mlock sys_mlock 151 common munlock sys_munlock sys_munlock 152 common mlockall sys_mlockall sys_mlockall @@ -372,8 +372,8 @@ 362 common connect sys_connect sys_connect 363 common listen sys_listen sys_listen 364 common accept4 sys_accept4 sys_accept4 -365 common getsockopt sys_getsockopt compat_sys_getsockopt -366 common setsockopt sys_setsockopt compat_sys_setsockopt +365 common getsockopt sys_getsockopt sys_getsockopt +366 common setsockopt sys_setsockopt sys_setsockopt 367 common getsockname sys_getsockname sys_getsockname 368 common getpeername sys_getpeername sys_getpeername 369 common sendto sys_sendto sys_sendto @@ -438,5 +438,7 @@ 433 common fspick sys_fspick sys_fspick 434 common pidfd_open sys_pidfd_open sys_pidfd_open 435 common clone3 sys_clone3 sys_clone3 +436 common close_range sys_close_range sys_close_range 437 common openat2 sys_openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd sys_pidfd_getfd +439 common faccessat2 sys_faccessat2 sys_faccessat2 diff --git a/linux-user/s390x/target_signal.h b/linux-user/s390x/target_signal.h index b58bc7c20f63c5bf49d75a550bc5190c43e0d739..bbfc464d4417ee0d2fcd2e4a30238c95c8f0d26c 100644 --- a/linux-user/s390x/target_signal.h +++ b/linux-user/s390x/target_signal.h @@ -3,7 +3,7 @@ typedef struct target_sigaltstack { abi_ulong ss_sp; - int ss_flags; + abi_int ss_flags; abi_ulong ss_size; } target_stack_t; diff --git a/linux-user/s390x/target_structs.h b/linux-user/s390x/target_structs.h index cadff6db3d0caf2244bf2b764c891782b37aaae1..aab716e5a265d07b63115fd7254ad3e48996da16 100644 --- a/linux-user/s390x/target_structs.h +++ b/linux-user/s390x/target_structs.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/s390x/target_syscall.h b/linux-user/s390x/target_syscall.h index 8d4f609eaa5d8698fa03c50cd2458f0fd58f4fce..94f84178db799a6667c97486d94289199f14d064 100644 --- a/linux-user/s390x/target_syscall.h +++ b/linux-user/s390x/target_syscall.h @@ -28,7 +28,8 @@ struct target_pt_regs { #define TARGET_CLONE_BACKWARDS2 #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 #endif /* S390X_TARGET_SYSCALL_H */ diff --git a/linux-user/s390x/termbits.h b/linux-user/s390x/termbits.h index 9affa8f41a70b728decc809d9d7f7f4045064084..b1d4f4fedbcb9ab2ca1184280eb4a9e5b8a9d735 100644 --- a/linux-user/s390x/termbits.h +++ b/linux-user/s390x/termbits.h @@ -1,288 +1 @@ -/* - * include/asm-s390/termbits.h - * - * S390 version - * - * Derived from "include/asm-i386/termbits.h" - */ - -#ifndef LINUX_USER_S390X_TERMBITS_H -#define LINUX_USER_S390X_TERMBITS_H - -#define TARGET_NCCS 19 -struct target_termios { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ -}; - -struct target_termios2 { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ - unsigned int c_ispeed; /* input speed */ - unsigned int c_ospeed; /* output speed */ -}; - -struct target_ktermios { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ - unsigned int c_ispeed; /* input speed */ - unsigned int c_ospeed; /* output speed */ -}; - -/* c_cc characters */ -#define TARGET_VINTR 0 -#define TARGET_VQUIT 1 -#define TARGET_VERASE 2 -#define TARGET_VKILL 3 -#define TARGET_VEOF 4 -#define TARGET_VTIME 5 -#define TARGET_VMIN 6 -#define TARGET_VSWTC 7 -#define TARGET_VSTART 8 -#define TARGET_VSTOP 9 -#define TARGET_VSUSP 10 -#define TARGET_VEOL 11 -#define TARGET_VREPRINT 12 -#define TARGET_VDISCARD 13 -#define TARGET_VWERASE 14 -#define TARGET_VLNEXT 15 -#define TARGET_VEOL2 16 - -/* c_iflag bits */ -#define TARGET_IGNBRK 0000001 -#define TARGET_BRKINT 0000002 -#define TARGET_IGNPAR 0000004 -#define TARGET_PARMRK 0000010 -#define TARGET_INPCK 0000020 -#define TARGET_ISTRIP 0000040 -#define TARGET_INLCR 0000100 -#define TARGET_IGNCR 0000200 -#define TARGET_ICRNL 0000400 -#define TARGET_IUCLC 0001000 -#define TARGET_IXON 0002000 -#define TARGET_IXANY 0004000 -#define TARGET_IXOFF 0010000 -#define TARGET_IMAXBEL 0020000 -#define TARGET_IUTF8 0040000 - -/* c_oflag bits */ -#define TARGET_OPOST 0000001 -#define TARGET_OLCUC 0000002 -#define TARGET_ONLCR 0000004 -#define TARGET_OCRNL 0000010 -#define TARGET_ONOCR 0000020 -#define TARGET_ONLRET 0000040 -#define TARGET_OFILL 0000100 -#define TARGET_OFDEL 0000200 -#define TARGET_NLDLY 0000400 -#define TARGET_NL0 0000000 -#define TARGET_NL1 0000400 -#define TARGET_CRDLY 0003000 -#define TARGET_CR0 0000000 -#define TARGET_CR1 0001000 -#define TARGET_CR2 0002000 -#define TARGET_CR3 0003000 -#define TARGET_TABDLY 0014000 -#define TARGET_TAB0 0000000 -#define TARGET_TAB1 0004000 -#define TARGET_TAB2 0010000 -#define TARGET_TAB3 0014000 -#define TARGET_XTABS 0014000 -#define TARGET_BSDLY 0020000 -#define TARGET_BS0 0000000 -#define TARGET_BS1 0020000 -#define TARGET_VTDLY 0040000 -#define TARGET_VT0 0000000 -#define TARGET_VT1 0040000 -#define TARGET_FFDLY 0100000 -#define TARGET_FF0 0000000 -#define TARGET_FF1 0100000 - -/* c_cflag bit meaning */ -#define TARGET_CBAUD 0010017 -#define TARGET_B0 0000000 /* hang up */ -#define TARGET_B50 0000001 -#define TARGET_B75 0000002 -#define TARGET_B110 0000003 -#define TARGET_B134 0000004 -#define TARGET_B150 0000005 -#define TARGET_B200 0000006 -#define TARGET_B300 0000007 -#define TARGET_B600 0000010 -#define TARGET_B1200 0000011 -#define TARGET_B1800 0000012 -#define TARGET_B2400 0000013 -#define TARGET_B4800 0000014 -#define TARGET_B9600 0000015 -#define TARGET_B19200 0000016 -#define TARGET_B38400 0000017 -#define TARGET_EXTA B19200 -#define TARGET_EXTB B38400 -#define TARGET_CSIZE 0000060 -#define TARGET_CS5 0000000 -#define TARGET_CS6 0000020 -#define TARGET_CS7 0000040 -#define TARGET_CS8 0000060 -#define TARGET_CSTOPB 0000100 -#define TARGET_CREAD 0000200 -#define TARGET_PARENB 0000400 -#define TARGET_PARODD 0001000 -#define TARGET_HUPCL 0002000 -#define TARGET_CLOCAL 0004000 -#define TARGET_CBAUDEX 0010000 -#define TARGET_BOTHER 0010000 -#define TARGET_B57600 0010001 -#define TARGET_B115200 0010002 -#define TARGET_B230400 0010003 -#define TARGET_B460800 0010004 -#define TARGET_B500000 0010005 -#define TARGET_B576000 0010006 -#define TARGET_B921600 0010007 -#define TARGET_B1000000 0010010 -#define TARGET_B1152000 0010011 -#define TARGET_B1500000 0010012 -#define TARGET_B2000000 0010013 -#define TARGET_B2500000 0010014 -#define TARGET_B3000000 0010015 -#define TARGET_B3500000 0010016 -#define TARGET_B4000000 0010017 -#define TARGET_CIBAUD 002003600000 /* input baud rate */ -#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ -#define TARGET_CRTSCTS 020000000000 /* flow control */ - -#define TARGET_IBSHIFT 16 /* Shift from CBAUD to CIBAUD */ - -/* c_lflag bits */ -#define TARGET_ISIG 0000001 -#define TARGET_ICANON 0000002 -#define TARGET_XCASE 0000004 -#define TARGET_ECHO 0000010 -#define TARGET_ECHOE 0000020 -#define TARGET_ECHOK 0000040 -#define TARGET_ECHONL 0000100 -#define TARGET_NOFLSH 0000200 -#define TARGET_TOSTOP 0000400 -#define TARGET_ECHOCTL 0001000 -#define TARGET_ECHOPRT 0002000 -#define TARGET_ECHOKE 0004000 -#define TARGET_FLUSHO 0010000 -#define TARGET_PENDIN 0040000 -#define TARGET_IEXTEN 0100000 - -/* tcflow() and TCXONC use these */ -#define TARGET_TCOOFF 0 -#define TARGET_TCOON 1 -#define TARGET_TCIOFF 2 -#define TARGET_TCION 3 - -/* tcflush() and TCFLSH use these */ -#define TARGET_TCIFLUSH 0 -#define TARGET_TCOFLUSH 1 -#define TARGET_TCIOFLUSH 2 - -/* tcsetattr uses these */ -#define TARGET_TCSANOW 0 -#define TARGET_TCSADRAIN 1 -#define TARGET_TCSAFLUSH 2 - -/* - * include/asm-s390/ioctls.h - * - * S390 version - * - * Derived from "include/asm-i386/ioctls.h" - */ - -/* 0x54 is just a magic number to make these relatively unique ('T') */ - -#define TARGET_TCGETS 0x5401 -#define TARGET_TCSETS 0x5402 -#define TARGET_TCSETSW 0x5403 -#define TARGET_TCSETSF 0x5404 -#define TARGET_TCGETA 0x5405 -#define TARGET_TCSETA 0x5406 -#define TARGET_TCSETAW 0x5407 -#define TARGET_TCSETAF 0x5408 -#define TARGET_TCSBRK 0x5409 -#define TARGET_TCXONC 0x540A -#define TARGET_TCFLSH 0x540B -#define TARGET_TIOCEXCL 0x540C -#define TARGET_TIOCNXCL 0x540D -#define TARGET_TIOCSCTTY 0x540E -#define TARGET_TIOCGPGRP 0x540F -#define TARGET_TIOCSPGRP 0x5410 -#define TARGET_TIOCOUTQ 0x5411 -#define TARGET_TIOCSTI 0x5412 -#define TARGET_TIOCGWINSZ 0x5413 -#define TARGET_TIOCSWINSZ 0x5414 -#define TARGET_TIOCMGET 0x5415 -#define TARGET_TIOCMBIS 0x5416 -#define TARGET_TIOCMBIC 0x5417 -#define TARGET_TIOCMSET 0x5418 -#define TARGET_TIOCGSOFTCAR 0x5419 -#define TARGET_TIOCSSOFTCAR 0x541A -#define TARGET_FIONREAD 0x541B -#define TARGET_TIOCINQ FIONREAD -#define TARGET_TIOCLINUX 0x541C -#define TARGET_TIOCCONS 0x541D -#define TARGET_TIOCGSERIAL 0x541E -#define TARGET_TIOCSSERIAL 0x541F -#define TARGET_TIOCPKT 0x5420 -#define TARGET_FIONBIO 0x5421 -#define TARGET_TIOCNOTTY 0x5422 -#define TARGET_TIOCSETD 0x5423 -#define TARGET_TIOCGETD 0x5424 -#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ -#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ -#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ -#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ -#define TARGET_TCGETS2 _IOR('T',0x2A, struct termios2) -#define TARGET_TCSETS2 _IOW('T',0x2B, struct termios2) -#define TARGET_TCSETSW2 _IOW('T',0x2C, struct termios2) -#define TARGET_TCSETSF2 _IOW('T',0x2D, struct termios2) -#define TARGET_TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ -#define TARGET_TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ -#define TARGET_TIOCGDEV _IOR('T',0x32, unsigned int) /* Get real dev no below /dev/console */ -#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) /* Safely open the slave */ - -#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */ -#define TARGET_FIOCLEX 0x5451 -#define TARGET_FIOASYNC 0x5452 -#define TARGET_TIOCSERCONFIG 0x5453 -#define TARGET_TIOCSERGWILD 0x5454 -#define TARGET_TIOCSERSWILD 0x5455 -#define TARGET_TIOCGLCKTRMIOS 0x5456 -#define TARGET_TIOCSLCKTRMIOS 0x5457 -#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ - -#define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ -#define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ -#define TARGET_FIOQSIZE 0x545E - -/* Used for packet mode */ -#define TARGET_TIOCPKT_DATA 0 -#define TARGET_TIOCPKT_FLUSHREAD 1 -#define TARGET_TIOCPKT_FLUSHWRITE 2 -#define TARGET_TIOCPKT_STOP 4 -#define TARGET_TIOCPKT_START 8 -#define TARGET_TIOCPKT_NOSTOP 16 -#define TARGET_TIOCPKT_DOSTOP 32 - -#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - -#endif +#include "../generic/termbits.h" diff --git a/linux-user/sh4/Makefile.objs b/linux-user/sh4/Makefile.objs deleted file mode 100644 index 83fc939570d52a279e73c3c459b354c674b29f34..0000000000000000000000000000000000000000 --- a/linux-user/sh4/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -generated-files-y += linux-user/sh4/syscall_nr.h - -syshdr := $(SRC_PATH)/linux-user/sh4/syscallhdr.sh -%/syscall_nr.h: $(SRC_PATH)/linux-user/sh4/syscall.tbl $(syshdr) - $(call quiet-command, sh $(syshdr) $< $@ $(TARGET_SYSTBL_ABI),"GEN","$@") diff --git a/linux-user/sh4/meson.build b/linux-user/sh4/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..3bc3a6924a7915a1dce20d6a81399d6fb7df4e3d --- /dev/null +++ b/linux-user/sh4/meson.build @@ -0,0 +1,5 @@ +syscall_nr_generators += { + 'sh4': generator(sh, + arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ], + output: '@BASENAME@_nr.h') +} diff --git a/linux-user/sh4/syscall.tbl b/linux-user/sh4/syscall.tbl index c7a30fcd135f89cc4882ed67e8c6bf5a4ea54347..ae0a00beea5f2e8f2b8335c634a5f7341323c345 100644 --- a/linux-user/sh4/syscall.tbl +++ b/linux-user/sh4/syscall.tbl @@ -156,7 +156,7 @@ 146 common writev sys_writev 147 common getsid sys_getsid 148 common fdatasync sys_fdatasync -149 common _sysctl sys_sysctl +149 common _sysctl sys_ni_syscall 150 common mlock sys_mlock 151 common munlock sys_munlock 152 common mlockall sys_mlockall @@ -438,5 +438,7 @@ 433 common fspick sys_fspick 434 common pidfd_open sys_pidfd_open # 435 reserved for clone3 +436 common close_range sys_close_range 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd +439 common faccessat2 sys_faccessat2 diff --git a/linux-user/sh4/target_signal.h b/linux-user/sh4/target_signal.h index 434970a9900a1c4eeb50513489c2ffce2db49d40..d7309b7136d76eecb36f3de692835b3af30b7a9a 100644 --- a/linux-user/sh4/target_signal.h +++ b/linux-user/sh4/target_signal.h @@ -4,9 +4,9 @@ /* this struct defines a stack used during syscall handling */ typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_long ss_flags; - abi_ulong ss_size; + abi_ulong ss_sp; + abi_int ss_flags; + abi_ulong ss_size; } target_stack_t; diff --git a/linux-user/sh4/target_syscall.h b/linux-user/sh4/target_syscall.h index 2b5f75be13d6ba671b15409ad0203b3aeb2e02f8..c1437adafefac725000cb506265eafe57c6597e2 100644 --- a/linux-user/sh4/target_syscall.h +++ b/linux-user/sh4/target_syscall.h @@ -16,8 +16,9 @@ struct target_pt_regs { #define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 #define TARGET_FORCE_SHMLBA diff --git a/linux-user/sh4/termbits.h b/linux-user/sh4/termbits.h index dd125b6a2b2aaf3ccef0d868c641456692f920f6..f91b5c51cf83811540a3f553a178394548e5cbf4 100644 --- a/linux-user/sh4/termbits.h +++ b/linux-user/sh4/termbits.h @@ -5,15 +5,20 @@ #define TARGET_NCCS 19 +typedef unsigned char target_cc_t; /* cc_t */ +typedef unsigned int target_speed_t; /* speed_t */ +typedef unsigned int target_tcflag_t; /* tcflag_t */ + struct target_termios { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ + target_tcflag_t c_iflag; /* input mode flags */ + target_tcflag_t c_oflag; /* output mode flags */ + target_tcflag_t c_cflag; /* control mode flags */ + target_tcflag_t c_lflag; /* local mode flags */ + target_cc_t c_line; /* line discipline */ + target_cc_t c_cc[TARGET_NCCS]; /* control characters */ }; + /* c_cc characters */ #define TARGET_VINTR 0 #define TARGET_VQUIT 1 @@ -150,6 +155,8 @@ struct target_termios { #define TARGET_FLUSHO 0010000 #define TARGET_PENDIN 0040000 #define TARGET_IEXTEN 0100000 +#define TARGET_EXTPROC 0200000 + /* tcflow() and TCXONC use these */ #define TARGET_TCOOFF 0 diff --git a/linux-user/signal.c b/linux-user/signal.c index 8cf51ffecde659742b7aac6dfaae99ab6fc82b67..73de934c65117c5caa0f2dabe8e29786397fee37 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -195,7 +195,7 @@ int block_signals(void) sigfillset(&set); sigprocmask(SIG_SETMASK, &set, 0); - return atomic_xchg(&ts->signal_pending, 1); + return qatomic_xchg(&ts->signal_pending, 1); } /* Wrapper for sigprocmask function @@ -688,7 +688,7 @@ int queue_signal(CPUArchState *env, int sig, int si_type, ts->sync_signal.info = *info; ts->sync_signal.pending = sig; /* signal that a new signal is pending */ - atomic_set(&ts->signal_pending, 1); + qatomic_set(&ts->signal_pending, 1); return 1; /* indicates that the signal was queued */ } @@ -1005,7 +1005,7 @@ void process_pending_signals(CPUArchState *cpu_env) sigset_t set; sigset_t *blocked_set; - while (atomic_read(&ts->signal_pending)) { + while (qatomic_read(&ts->signal_pending)) { /* FIXME: This is not threadsafe. */ sigfillset(&set); sigprocmask(SIG_SETMASK, &set, 0); @@ -1049,7 +1049,7 @@ void process_pending_signals(CPUArchState *cpu_env) * of unblocking might cause us to take another host signal which * will set signal_pending again). */ - atomic_set(&ts->signal_pending, 0); + qatomic_set(&ts->signal_pending, 0); ts->in_sigsuspend = 0; set = ts->signal_mask; sigdelset(&set, SIGSEGV); diff --git a/linux-user/sparc/Makefile.objs b/linux-user/sparc/Makefile.objs deleted file mode 100644 index 29d3f066cbab5b72c757bcf9d2f7cf3733ffff02..0000000000000000000000000000000000000000 --- a/linux-user/sparc/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -generated-files-y += linux-user/sparc/syscall_nr.h - -syshdr := $(SRC_PATH)/linux-user/sparc/syscallhdr.sh -%/syscall_nr.h: $(SRC_PATH)/linux-user/sparc/syscall.tbl $(syshdr) - $(call quiet-command, sh $(syshdr) $< $@ $(TARGET_SYSTBL_ABI),"GEN","$@") diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index 7645cc04ca7322e00ed8557079679c834bfdd006..02532f198df83c5cd83b9f0bc7bea63e82c03c8c 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -69,7 +69,11 @@ static void save_window(CPUSPARCState *env) save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); env->wim = new_wim; #else - save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); + /* + * cansave is zero if the spill trap handler is triggered by `save` and + * nonzero if triggered by a `flushw` + */ + save_window_offset(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2)); env->cansave++; env->canrestore--; #endif diff --git a/linux-user/sparc/meson.build b/linux-user/sparc/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..51a9c7795c755f78c06eb43dff4fe316bfeb4166 --- /dev/null +++ b/linux-user/sparc/meson.build @@ -0,0 +1,5 @@ +syscall_nr_generators += { + 'sparc': generator(sh, + arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ], + output: '@BASENAME@_nr.h') +} diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index d796f50f665ba1ef5cafc6992e4b8f72fe7b44d1..d12adc8e6ff98eef7fa816ecf6d5fb1029da2b60 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -247,7 +247,7 @@ long do_sigreturn(CPUSPARCState *env) { abi_ulong sf_addr; struct target_signal_frame *sf; - uint32_t up_psr, pc, npc; + abi_ulong up_psr, pc, npc; target_sigset_t set; sigset_t host_set; int i; @@ -349,10 +349,15 @@ typedef abi_ulong target_mc_greg_t; typedef target_mc_greg_t target_mc_gregset_t[SPARC_MC_NGREG]; struct target_mc_fq { - abi_ulong *mcfq_addr; + abi_ulong mcfq_addr; uint32_t mcfq_insn; }; +/* + * Note the manual 16-alignment; the kernel gets this because it + * includes a "long double qregs[16]" in the mcpu_fregs union, + * which we can't do. + */ struct target_mc_fpu { union { uint32_t sregs[32]; @@ -362,11 +367,11 @@ struct target_mc_fpu { abi_ulong mcfpu_fsr; abi_ulong mcfpu_fprs; abi_ulong mcfpu_gsr; - struct target_mc_fq *mcfpu_fq; + abi_ulong mcfpu_fq; unsigned char mcfpu_qcnt; unsigned char mcfpu_qentsz; unsigned char mcfpu_enab; -}; +} __attribute__((aligned(16))); typedef struct target_mc_fpu target_mc_fpu_t; typedef struct { @@ -377,7 +382,7 @@ typedef struct { } target_mcontext_t; struct target_ucontext { - struct target_ucontext *tuc_link; + abi_ulong tuc_link; abi_ulong tuc_flags; target_sigset_t tuc_sigmask; target_mcontext_t tuc_mcontext; @@ -398,7 +403,6 @@ void sparc64_set_context(CPUSPARCState *env) struct target_ucontext *ucp; target_mc_gregset_t *grp; abi_ulong pc, npc, tstate; - abi_ulong fp, i7, w_addr; unsigned int i; ucp_addr = env->regwptr[WREG_O0]; @@ -442,6 +446,15 @@ void sparc64_set_context(CPUSPARCState *env) __get_user(env->gregs[5], (&(*grp)[SPARC_MC_G5])); __get_user(env->gregs[6], (&(*grp)[SPARC_MC_G6])); __get_user(env->gregs[7], (&(*grp)[SPARC_MC_G7])); + + /* + * Note that unlike the kernel, we didn't need to mess with the + * guest register window state to save it into a pt_regs to run + * the kernel. So for us the guest's O regs are still in WREG_O* + * (unlike the kernel which has put them in UREG_I* in a pt_regs) + * and the fp and i7 are still in WREG_I6 and WREG_I7 and don't + * need to be written back to userspace memory. + */ __get_user(env->regwptr[WREG_O0], (&(*grp)[SPARC_MC_O0])); __get_user(env->regwptr[WREG_O1], (&(*grp)[SPARC_MC_O1])); __get_user(env->regwptr[WREG_O2], (&(*grp)[SPARC_MC_O2])); @@ -451,18 +464,9 @@ void sparc64_set_context(CPUSPARCState *env) __get_user(env->regwptr[WREG_O6], (&(*grp)[SPARC_MC_O6])); __get_user(env->regwptr[WREG_O7], (&(*grp)[SPARC_MC_O7])); - __get_user(fp, &(ucp->tuc_mcontext.mc_fp)); - __get_user(i7, &(ucp->tuc_mcontext.mc_i7)); + __get_user(env->regwptr[WREG_FP], &(ucp->tuc_mcontext.mc_fp)); + __get_user(env->regwptr[WREG_I7], &(ucp->tuc_mcontext.mc_i7)); - w_addr = TARGET_STACK_BIAS + env->regwptr[WREG_O6]; - if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), - abi_ulong) != 0) { - goto do_sigsegv; - } - if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), - abi_ulong) != 0) { - goto do_sigsegv; - } /* FIXME this does not match how the kernel handles the FPU in * its sparc64_set_context implementation. In particular the FPU * is only restored if fenab is non-zero in: @@ -496,7 +500,6 @@ void sparc64_get_context(CPUSPARCState *env) struct target_ucontext *ucp; target_mc_gregset_t *grp; target_mcontext_t *mcp; - abi_ulong fp, i7, w_addr; int err; unsigned int i; target_sigset_t target_set; @@ -548,6 +551,15 @@ void sparc64_get_context(CPUSPARCState *env) __put_user(env->gregs[5], &((*grp)[SPARC_MC_G5])); __put_user(env->gregs[6], &((*grp)[SPARC_MC_G6])); __put_user(env->gregs[7], &((*grp)[SPARC_MC_G7])); + + /* + * Note that unlike the kernel, we didn't need to mess with the + * guest register window state to save it into a pt_regs to run + * the kernel. So for us the guest's O regs are still in WREG_O* + * (unlike the kernel which has put them in UREG_I* in a pt_regs) + * and the fp and i7 are still in WREG_I6 and WREG_I7 and don't + * need to be fished out of userspace memory. + */ __put_user(env->regwptr[WREG_O0], &((*grp)[SPARC_MC_O0])); __put_user(env->regwptr[WREG_O1], &((*grp)[SPARC_MC_O1])); __put_user(env->regwptr[WREG_O2], &((*grp)[SPARC_MC_O2])); @@ -557,18 +569,8 @@ void sparc64_get_context(CPUSPARCState *env) __put_user(env->regwptr[WREG_O6], &((*grp)[SPARC_MC_O6])); __put_user(env->regwptr[WREG_O7], &((*grp)[SPARC_MC_O7])); - w_addr = TARGET_STACK_BIAS + env->regwptr[WREG_O6]; - fp = i7 = 0; - if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), - abi_ulong) != 0) { - goto do_sigsegv; - } - if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), - abi_ulong) != 0) { - goto do_sigsegv; - } - __put_user(fp, &(mcp->mc_fp)); - __put_user(i7, &(mcp->mc_i7)); + __put_user(env->regwptr[WREG_FP], &(mcp->mc_fp)); + __put_user(env->regwptr[WREG_I7], &(mcp->mc_i7)); { uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs; diff --git a/linux-user/sparc/syscall.tbl b/linux-user/sparc/syscall.tbl index f13615ecdecce2f69adbd13576b03a6aa4d8fbef..4af114e84f2022157afdf7d6dc76c61fa2be4e34 100644 --- a/linux-user/sparc/syscall.tbl +++ b/linux-user/sparc/syscall.tbl @@ -147,7 +147,7 @@ 115 32 getgroups32 sys_getgroups 116 common gettimeofday sys_gettimeofday compat_sys_gettimeofday 117 common getrusage sys_getrusage compat_sys_getrusage -118 common getsockopt sys_getsockopt compat_sys_getsockopt +118 common getsockopt sys_getsockopt sys_getsockopt 119 common getcwd sys_getcwd 120 common readv sys_readv compat_sys_readv 121 common writev sys_writev compat_sys_writev @@ -300,7 +300,7 @@ 249 64 nanosleep sys_nanosleep 250 32 mremap sys_mremap 250 64 mremap sys_64_mremap -251 common _sysctl sys_sysctl compat_sys_sysctl +251 common _sysctl sys_ni_syscall 252 common getsid sys_getsid 253 common fdatasync sys_fdatasync 254 32 nfsservctl sys_ni_syscall sys_nis_syscall @@ -425,7 +425,7 @@ 352 common userfaultfd sys_userfaultfd 353 common bind sys_bind 354 common listen sys_listen -355 common setsockopt sys_setsockopt compat_sys_setsockopt +355 common setsockopt sys_setsockopt sys_setsockopt 356 common mlock2 sys_mlock2 357 common copy_file_range sys_copy_file_range 358 common preadv2 sys_preadv2 compat_sys_preadv2 @@ -481,5 +481,7 @@ 433 common fspick sys_fspick 434 common pidfd_open sys_pidfd_open # 435 reserved for clone3 +436 common close_range sys_close_range 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd +439 common faccessat2 sys_faccessat2 diff --git a/linux-user/sparc/target_cpu.h b/linux-user/sparc/target_cpu.h index 14b21589699b085100b5395a00cc0828a71d7369..1fa1011775a1ea95b108ce97e15710a9bd2fa78f 100644 --- a/linux-user/sparc/target_cpu.h +++ b/linux-user/sparc/target_cpu.h @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/sparc/target_signal.h b/linux-user/sparc/target_signal.h index 5cc40327d2c2400ee1b44d0abb121b18a0afdddf..1b10d1490fc9a046e14d3d4777746b074988f6a8 100644 --- a/linux-user/sparc/target_signal.h +++ b/linux-user/sparc/target_signal.h @@ -42,9 +42,9 @@ /* this struct defines a stack used during syscall handling */ typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_long ss_flags; - abi_ulong ss_size; + abi_ulong ss_sp; + abi_int ss_flags; + abi_ulong ss_size; } target_stack_t; diff --git a/linux-user/sparc/target_structs.h b/linux-user/sparc/target_structs.h index ee24c3b5fc98759a8585bbc1ee0ea712b25b7a28..995354075950ee1595c1cb61eae1cc8b05945215 100644 --- a/linux-user/sparc/target_structs.h +++ b/linux-user/sparc/target_structs.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/sparc/target_syscall.h b/linux-user/sparc/target_syscall.h index b9160a771baac3abf7f578d943974ab468a9ca4b..d8ea04ea837ae88332f61d5e2728cb8394fca61c 100644 --- a/linux-user/sparc/target_syscall.h +++ b/linux-user/sparc/target_syscall.h @@ -21,8 +21,9 @@ struct target_pt_regs { */ #define TARGET_CLONE_BACKWARDS #define TARGET_MINSIGSTKSZ 4096 -#define TARGET_MLOCKALL_MCL_CURRENT 0x2000 -#define TARGET_MLOCKALL_MCL_FUTURE 0x4000 +#define TARGET_MCL_CURRENT 0x2000 +#define TARGET_MCL_FUTURE 0x4000 +#define TARGET_MCL_ONFAULT 0x8000 /* For SPARC SHMLBA is determined at runtime in the kernel, and * libc has to runtime-detect it using the hwcaps (see glibc diff --git a/linux-user/sparc/termbits.h b/linux-user/sparc/termbits.h index f85219ed7112baa37ef31c5128e080e96911028b..704bee1c427e2fcc508e48256e5dad1dd586d794 100644 --- a/linux-user/sparc/termbits.h +++ b/linux-user/sparc/termbits.h @@ -5,15 +5,20 @@ #define TARGET_NCCS 19 +typedef unsigned char target_cc_t; /* cc_t */ +typedef unsigned int target_speed_t; /* speed_t */ +typedef unsigned int target_tcflag_t; /* tcflag_t */ + struct target_termios { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ + target_tcflag_t c_iflag; /* input mode flags */ + target_tcflag_t c_oflag; /* output mode flags */ + target_tcflag_t c_cflag; /* control mode flags */ + target_tcflag_t c_lflag; /* local mode flags */ + target_cc_t c_line; /* line discipline */ + target_cc_t c_cc[TARGET_NCCS]; /* control characters */ }; + /* c_cc characters */ #define TARGET_VINTR 0 #define TARGET_VQUIT 1 @@ -170,6 +175,7 @@ struct target_termios { #define TARGET_FLUSHO 0x00002000 #define TARGET_PENDIN 0x00004000 #define TARGET_IEXTEN 0x00008000 +#define TARGET_EXTPROC 0x00010000 /* ioctls */ diff --git a/linux-user/sparc64/Makefile.objs b/linux-user/sparc64/Makefile.objs deleted file mode 100644 index afcd535bc4a4fc52e19be9f6e8b4f84001905bd3..0000000000000000000000000000000000000000 --- a/linux-user/sparc64/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -generated-files-y += linux-user/sparc64/syscall_nr.h - -syshdr := $(SRC_PATH)/linux-user/sparc64/syscallhdr.sh -%/syscall_nr.h: $(SRC_PATH)/linux-user/sparc/syscall.tbl $(syshdr) - $(call quiet-command, sh $(syshdr) $< $@ $(TARGET_SYSTBL_ABI),"GEN","$@") diff --git a/linux-user/sparc64/meson.build b/linux-user/sparc64/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..9527a40ed4401285c72246633480c799b43fda35 --- /dev/null +++ b/linux-user/sparc64/meson.build @@ -0,0 +1,5 @@ +syscall_nr_generators += { + 'sparc64': generator(sh, + arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ], + output: '@BASENAME@_nr.h') +} diff --git a/linux-user/sparc64/syscall.tbl b/linux-user/sparc64/syscall.tbl index f13615ecdecce2f69adbd13576b03a6aa4d8fbef..4af114e84f2022157afdf7d6dc76c61fa2be4e34 100644 --- a/linux-user/sparc64/syscall.tbl +++ b/linux-user/sparc64/syscall.tbl @@ -147,7 +147,7 @@ 115 32 getgroups32 sys_getgroups 116 common gettimeofday sys_gettimeofday compat_sys_gettimeofday 117 common getrusage sys_getrusage compat_sys_getrusage -118 common getsockopt sys_getsockopt compat_sys_getsockopt +118 common getsockopt sys_getsockopt sys_getsockopt 119 common getcwd sys_getcwd 120 common readv sys_readv compat_sys_readv 121 common writev sys_writev compat_sys_writev @@ -300,7 +300,7 @@ 249 64 nanosleep sys_nanosleep 250 32 mremap sys_mremap 250 64 mremap sys_64_mremap -251 common _sysctl sys_sysctl compat_sys_sysctl +251 common _sysctl sys_ni_syscall 252 common getsid sys_getsid 253 common fdatasync sys_fdatasync 254 32 nfsservctl sys_ni_syscall sys_nis_syscall @@ -425,7 +425,7 @@ 352 common userfaultfd sys_userfaultfd 353 common bind sys_bind 354 common listen sys_listen -355 common setsockopt sys_setsockopt compat_sys_setsockopt +355 common setsockopt sys_setsockopt sys_setsockopt 356 common mlock2 sys_mlock2 357 common copy_file_range sys_copy_file_range 358 common preadv2 sys_preadv2 compat_sys_preadv2 @@ -481,5 +481,7 @@ 433 common fspick sys_fspick 434 common pidfd_open sys_pidfd_open # 435 reserved for clone3 +436 common close_range sys_close_range 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd +439 common faccessat2 sys_faccessat2 diff --git a/linux-user/sparc64/target_structs.h b/linux-user/sparc64/target_structs.h index 1808132b18c7ec955fd9a2c47961d42898b9fe85..4a8ed48df742b309ddf37979a7d1f625407e603c 100644 --- a/linux-user/sparc64/target_structs.h +++ b/linux-user/sparc64/target_structs.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/sparc64/target_syscall.h b/linux-user/sparc64/target_syscall.h index 3073a23e03ae8f38e09717d3164a93b85a426c18..696a68b1ed4ed063ea0d728c2cec60d2aa6cfaf9 100644 --- a/linux-user/sparc64/target_syscall.h +++ b/linux-user/sparc64/target_syscall.h @@ -22,8 +22,9 @@ struct target_pt_regs { */ #define TARGET_CLONE_BACKWARDS #define TARGET_MINSIGSTKSZ 4096 -#define TARGET_MLOCKALL_MCL_CURRENT 0x2000 -#define TARGET_MLOCKALL_MCL_FUTURE 0x4000 +#define TARGET_MCL_CURRENT 0x2000 +#define TARGET_MCL_FUTURE 0x4000 +#define TARGET_MCL_ONFAULT 0x8000 #define TARGET_FORCE_SHMLBA diff --git a/linux-user/sparc64/termbits.h b/linux-user/sparc64/termbits.h index 11b5abcf84391df04e21f50494a0108b299348a1..1ab1e80db548d2107620963bba15648410859a82 100644 --- a/linux-user/sparc64/termbits.h +++ b/linux-user/sparc64/termbits.h @@ -5,15 +5,20 @@ #define TARGET_NCCS 19 +typedef unsigned char target_cc_t; /* cc_t */ +typedef unsigned int target_speed_t; /* speed_t */ +typedef unsigned int target_tcflag_t; /* tcflag_t */ + struct target_termios { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ + target_tcflag_t c_iflag; /* input mode flags */ + target_tcflag_t c_oflag; /* output mode flags */ + target_tcflag_t c_cflag; /* control mode flags */ + target_tcflag_t c_lflag; /* local mode flags */ + target_cc_t c_line; /* line discipline */ + target_cc_t c_cc[TARGET_NCCS]; /* control characters */ }; + /* c_cc characters */ #define TARGET_VINTR 0 #define TARGET_VQUIT 1 @@ -170,6 +175,7 @@ struct target_termios { #define TARGET_FLUSHO 0x00002000 #define TARGET_PENDIN 0x00004000 #define TARGET_IEXTEN 0x00008000 +#define TARGET_EXTPROC 0x00010000 /* ioctls */ diff --git a/linux-user/strace.c b/linux-user/strace.c index 0d9095c674f4dc8ca10f7a64d8fac6e942be94ae..11fea14fba2ed8d31040b96411b17e321259322f 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -16,10 +16,12 @@ struct syscallname { int nr; const char *name; const char *format; - void (*call)(const struct syscallname *, + void (*call)(void *, const struct syscallname *, abi_long, abi_long, abi_long, abi_long, abi_long, abi_long); - void (*result)(const struct syscallname *, abi_long); + void (*result)(void *, const struct syscallname *, abi_long, + abi_long, abi_long, abi_long, + abi_long, abi_long, abi_long); }; #ifdef __GNUC__ @@ -50,9 +52,23 @@ struct flags { /* end of flags array */ #define FLAG_END { 0, NULL } +/* Structure used to translate enumerated values into strings */ +struct enums { + abi_long e_value; /* enum value */ + const char *e_string; /* stringified enum */ +}; + +/* common enums for all architectures */ +#define ENUM_GENERIC(name) { name, #name } +/* target specific enums */ +#define ENUM_TARGET(name) { TARGET_ ## name, #name } +/* end of enums array */ +#define ENUM_END { 0, NULL } + UNUSED static const char *get_comma(int); UNUSED static void print_pointer(abi_long, int); UNUSED static void print_flags(const struct flags *, abi_long, int); +UNUSED static void print_enums(const struct enums *, abi_long, int); UNUSED static void print_at_dirfd(abi_long, int); UNUSED static void print_file_mode(abi_long, int); UNUSED static void print_open_flags(abi_long, int); @@ -62,7 +78,9 @@ UNUSED static void print_string(abi_long, int); UNUSED static void print_buf(abi_long addr, abi_long len, int last); UNUSED static void print_raw_param(const char *, abi_long, int); UNUSED static void print_timeval(abi_ulong, int); +UNUSED static void print_timespec(abi_ulong, int); UNUSED static void print_timezone(abi_ulong, int); +UNUSED static void print_itimerval(abi_ulong, int); UNUSED static void print_number(abi_long, int); UNUSED static void print_signal(abi_ulong, int); UNUSED static void print_sockaddr(abi_ulong, abi_long, int); @@ -539,6 +557,7 @@ static void print_fdset(int n, abi_ulong target_fds_addr) { int i; + int first = 1; qemu_log("["); if( target_fds_addr ) { @@ -553,96 +572,30 @@ print_fdset(int n, abi_ulong target_fds_addr) return; for (i=n; i>=0; i--) { - if ((tswapal(target_fds[i / TARGET_ABI_BITS]) >> (i & (TARGET_ABI_BITS - 1))) & 1) - qemu_log("%d,", i); + if ((tswapal(target_fds[i / TARGET_ABI_BITS]) >> + (i & (TARGET_ABI_BITS - 1))) & 1) { + qemu_log("%s%d", get_comma(first), i); + first = 0; } + } unlock_user(target_fds, target_fds_addr, 0); } qemu_log("]"); } #endif -#ifdef TARGET_NR_clock_adjtime -/* IDs of the various system clocks */ -#define TARGET_CLOCK_REALTIME 0 -#define TARGET_CLOCK_MONOTONIC 1 -#define TARGET_CLOCK_PROCESS_CPUTIME_ID 2 -#define TARGET_CLOCK_THREAD_CPUTIME_ID 3 -#define TARGET_CLOCK_MONOTONIC_RAW 4 -#define TARGET_CLOCK_REALTIME_COARSE 5 -#define TARGET_CLOCK_MONOTONIC_COARSE 6 -#define TARGET_CLOCK_BOOTTIME 7 -#define TARGET_CLOCK_REALTIME_ALARM 8 -#define TARGET_CLOCK_BOOTTIME_ALARM 9 -#define TARGET_CLOCK_SGI_CYCLE 10 -#define TARGET_CLOCK_TAI 11 - -static void -print_clockid(int clockid, int last) -{ - switch (clockid) { - case TARGET_CLOCK_REALTIME: - qemu_log("CLOCK_REALTIME"); - break; - case TARGET_CLOCK_MONOTONIC: - qemu_log("CLOCK_MONOTONIC"); - break; - case TARGET_CLOCK_PROCESS_CPUTIME_ID: - qemu_log("CLOCK_PROCESS_CPUTIME_ID"); - break; - case TARGET_CLOCK_THREAD_CPUTIME_ID: - qemu_log("CLOCK_THREAD_CPUTIME_ID"); - break; - case TARGET_CLOCK_MONOTONIC_RAW: - qemu_log("CLOCK_MONOTONIC_RAW"); - break; - case TARGET_CLOCK_REALTIME_COARSE: - qemu_log("CLOCK_REALTIME_COARSE"); - break; - case TARGET_CLOCK_MONOTONIC_COARSE: - qemu_log("CLOCK_MONOTONIC_COARSE"); - break; - case TARGET_CLOCK_BOOTTIME: - qemu_log("CLOCK_BOOTTIME"); - break; - case TARGET_CLOCK_REALTIME_ALARM: - qemu_log("CLOCK_REALTIME_ALARM"); - break; - case TARGET_CLOCK_BOOTTIME_ALARM: - qemu_log("CLOCK_BOOTTIME_ALARM"); - break; - case TARGET_CLOCK_SGI_CYCLE: - qemu_log("CLOCK_SGI_CYCLE"); - break; - case TARGET_CLOCK_TAI: - qemu_log("CLOCK_TAI"); - break; - default: - qemu_log("%d", clockid); - break; - } - qemu_log("%s", get_comma(last)); -} -#endif - /* * Sysycall specific output functions */ /* select */ #ifdef TARGET_NR__newselect -static long newselect_arg1 = 0; -static long newselect_arg2 = 0; -static long newselect_arg3 = 0; -static long newselect_arg4 = 0; -static long newselect_arg5 = 0; - static void -print_newselect(const struct syscallname *name, +print_newselect(void *cpu_env, const struct syscallname *name, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { - qemu_log("%s(" TARGET_ABI_FMT_ld ",", name->name, arg1); + print_syscall_prologue(name); print_fdset(arg1, arg2); qemu_log(","); print_fdset(arg1, arg3); @@ -650,20 +603,13 @@ print_newselect(const struct syscallname *name, print_fdset(arg1, arg4); qemu_log(","); print_timeval(arg5, 1); - qemu_log(")"); - - /* save for use in the return output function below */ - newselect_arg1=arg1; - newselect_arg2=arg2; - newselect_arg3=arg3; - newselect_arg4=arg4; - newselect_arg5=arg5; + print_syscall_epilogue(name); } #endif #ifdef TARGET_NR_semctl static void -print_semctl(const struct syscallname *name, +print_semctl(void *cpu_env, const struct syscallname *name, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { @@ -675,7 +621,7 @@ print_semctl(const struct syscallname *name, #endif static void -print_execve(const struct syscallname *name, +print_execve(void *cpu_env, const struct syscallname *name, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { @@ -708,7 +654,7 @@ print_execve(const struct syscallname *name, #ifdef TARGET_NR_ipc static void -print_ipc(const struct syscallname *name, +print_ipc(void *cpu_env, const struct syscallname *name, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { @@ -735,19 +681,32 @@ print_ipc(const struct syscallname *name, * Variants for the return value output function */ -static void -print_syscall_ret_addr(const struct syscallname *name, abi_long ret) +static bool +print_syscall_err(abi_long ret) { - const char *errstr = NULL; + const char *errstr; + qemu_log(" = "); if (ret < 0) { errstr = target_strerror(-ret); + if (errstr) { + qemu_log("-1 errno=%d (%s)", (int)-ret, errstr); + return true; + } } - if (errstr) { - qemu_log(" = -1 errno=%d (%s)\n", (int)-ret, errstr); - } else { - qemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret); + return false; +} + +static void +print_syscall_ret_addr(void *cpu_env, const struct syscallname *name, + abi_long ret, abi_long arg0, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5) +{ + if (!print_syscall_err(ret)) { + qemu_log("0x" TARGET_ABI_FMT_lx, ret); } + qemu_log("\n"); } #if 0 /* currently unused */ @@ -760,17 +719,24 @@ print_syscall_ret_raw(struct syscallname *name, abi_long ret) #ifdef TARGET_NR__newselect static void -print_syscall_ret_newselect(const struct syscallname *name, abi_long ret) -{ - qemu_log(" = 0x" TARGET_ABI_FMT_lx " (", ret); - print_fdset(newselect_arg1,newselect_arg2); - qemu_log(","); - print_fdset(newselect_arg1,newselect_arg3); - qemu_log(","); - print_fdset(newselect_arg1,newselect_arg4); - qemu_log(","); - print_timeval(newselect_arg5, 1); - qemu_log(")\n"); +print_syscall_ret_newselect(void *cpu_env, const struct syscallname *name, + abi_long ret, abi_long arg0, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5) +{ + if (!print_syscall_err(ret)) { + qemu_log(" = 0x" TARGET_ABI_FMT_lx " (", ret); + print_fdset(arg0, arg1); + qemu_log(","); + print_fdset(arg0, arg2); + qemu_log(","); + print_fdset(arg0, arg3); + qemu_log(","); + print_timeval(arg4, 1); + qemu_log(")"); + } + + qemu_log("\n"); } #endif @@ -783,18 +749,12 @@ print_syscall_ret_newselect(const struct syscallname *name, abi_long ret) #define TARGET_TIME_ERROR 5 /* clock not synchronized */ #ifdef TARGET_NR_adjtimex static void -print_syscall_ret_adjtimex(const struct syscallname *name, abi_long ret) +print_syscall_ret_adjtimex(void *cpu_env, const struct syscallname *name, + abi_long ret, abi_long arg0, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5) { - const char *errstr = NULL; - - qemu_log(" = "); - if (ret < 0) { - qemu_log("-1 errno=%d", errno); - errstr = target_strerror(-ret); - if (errstr) { - qemu_log(" (%s)", errstr); - } - } else { + if (!print_syscall_err(ret)) { qemu_log(TARGET_ABI_FMT_ld, ret); switch (ret) { case TARGET_TIME_OK: @@ -822,6 +782,155 @@ print_syscall_ret_adjtimex(const struct syscallname *name, abi_long ret) } #endif +#if defined(TARGET_NR_clock_gettime) || defined(TARGET_NR_clock_getres) +static void +print_syscall_ret_clock_gettime(void *cpu_env, const struct syscallname *name, + abi_long ret, abi_long arg0, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5) +{ + if (!print_syscall_err(ret)) { + qemu_log(TARGET_ABI_FMT_ld, ret); + qemu_log(" ("); + print_timespec(arg1, 1); + qemu_log(")"); + } + + qemu_log("\n"); +} +#define print_syscall_ret_clock_getres print_syscall_ret_clock_gettime +#endif + +#ifdef TARGET_NR_gettimeofday +static void +print_syscall_ret_gettimeofday(void *cpu_env, const struct syscallname *name, + abi_long ret, abi_long arg0, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5) +{ + if (!print_syscall_err(ret)) { + qemu_log(TARGET_ABI_FMT_ld, ret); + qemu_log(" ("); + print_timeval(arg0, 0); + print_timezone(arg1, 1); + qemu_log(")"); + } + + qemu_log("\n"); +} +#endif + +#ifdef TARGET_NR_getitimer +static void +print_syscall_ret_getitimer(void *cpu_env, const struct syscallname *name, + abi_long ret, abi_long arg0, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5) +{ + if (!print_syscall_err(ret)) { + qemu_log(TARGET_ABI_FMT_ld, ret); + qemu_log(" ("); + print_itimerval(arg1, 1); + qemu_log(")"); + } + + qemu_log("\n"); +} +#endif + + +#ifdef TARGET_NR_getitimer +static void +print_syscall_ret_setitimer(void *cpu_env, const struct syscallname *name, + abi_long ret, abi_long arg0, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5) +{ + if (!print_syscall_err(ret)) { + qemu_log(TARGET_ABI_FMT_ld, ret); + qemu_log(" (old_value = "); + print_itimerval(arg2, 1); + qemu_log(")"); + } + + qemu_log("\n"); +} +#endif + +#if defined(TARGET_NR_listxattr) || defined(TARGET_NR_llistxattr) \ + || defined(TARGGET_NR_flistxattr) +static void +print_syscall_ret_listxattr(void *cpu_env, const struct syscallname *name, + abi_long ret, abi_long arg0, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5) +{ + if (!print_syscall_err(ret)) { + qemu_log(TARGET_ABI_FMT_ld, ret); + qemu_log(" (list = "); + if (arg1 != 0) { + abi_long attr = arg1; + while (ret) { + if (attr != arg1) { + qemu_log(","); + } + print_string(attr, 1); + ret -= target_strlen(attr) + 1; + attr += target_strlen(attr) + 1; + } + } else { + qemu_log("NULL"); + } + qemu_log(")"); + } + + qemu_log("\n"); +} +#define print_syscall_ret_llistxattr print_syscall_ret_listxattr +#define print_syscall_ret_flistxattr print_syscall_ret_listxattr +#endif + +#ifdef TARGET_NR_ioctl +static void +print_syscall_ret_ioctl(void *cpu_env, const struct syscallname *name, + abi_long ret, abi_long arg0, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5) +{ + if (!print_syscall_err(ret)) { + qemu_log(TARGET_ABI_FMT_ld, ret); + + const IOCTLEntry *ie; + const argtype *arg_type; + void *argptr; + int target_size; + + for (ie = ioctl_entries; ie->target_cmd != 0; ie++) { + if (ie->target_cmd == arg1) { + break; + } + } + + if (ie->target_cmd == arg1 && + (ie->access == IOC_R || ie->access == IOC_RW)) { + arg_type = ie->arg_type; + qemu_log(" ("); + arg_type++; + target_size = thunk_type_size(arg_type, 0); + argptr = lock_user(VERIFY_READ, arg2, target_size, 1); + if (argptr) { + thunk_print(argptr, arg_type); + unlock_user(argptr, arg2, target_size); + } else { + print_pointer(arg2, 1); + } + qemu_log(")"); + } + } + qemu_log("\n"); +} +#endif + UNUSED static struct flags access_flags[] = { FLAG_GENERIC(F_OK), FLAG_GENERIC(R_OK), @@ -1097,6 +1206,206 @@ UNUSED static struct flags statx_mask[] = { FLAG_END, }; +UNUSED static struct flags falloc_flags[] = { + FLAG_GENERIC(FALLOC_FL_KEEP_SIZE), + FLAG_GENERIC(FALLOC_FL_PUNCH_HOLE), +#ifdef FALLOC_FL_NO_HIDE_STALE + FLAG_GENERIC(FALLOC_FL_NO_HIDE_STALE), +#endif +#ifdef FALLOC_FL_COLLAPSE_RANGE + FLAG_GENERIC(FALLOC_FL_COLLAPSE_RANGE), +#endif +#ifdef FALLOC_FL_ZERO_RANGE + FLAG_GENERIC(FALLOC_FL_ZERO_RANGE), +#endif +#ifdef FALLOC_FL_INSERT_RANGE + FLAG_GENERIC(FALLOC_FL_INSERT_RANGE), +#endif +#ifdef FALLOC_FL_UNSHARE_RANGE + FLAG_GENERIC(FALLOC_FL_UNSHARE_RANGE), +#endif +}; + +UNUSED static struct flags termios_iflags[] = { + FLAG_TARGET(IGNBRK), + FLAG_TARGET(BRKINT), + FLAG_TARGET(IGNPAR), + FLAG_TARGET(PARMRK), + FLAG_TARGET(INPCK), + FLAG_TARGET(ISTRIP), + FLAG_TARGET(INLCR), + FLAG_TARGET(IGNCR), + FLAG_TARGET(ICRNL), + FLAG_TARGET(IUCLC), + FLAG_TARGET(IXON), + FLAG_TARGET(IXANY), + FLAG_TARGET(IXOFF), + FLAG_TARGET(IMAXBEL), + FLAG_TARGET(IUTF8), + FLAG_END, +}; + +UNUSED static struct flags termios_oflags[] = { + FLAG_TARGET(OPOST), + FLAG_TARGET(OLCUC), + FLAG_TARGET(ONLCR), + FLAG_TARGET(OCRNL), + FLAG_TARGET(ONOCR), + FLAG_TARGET(ONLRET), + FLAG_TARGET(OFILL), + FLAG_TARGET(OFDEL), + FLAG_END, +}; + +UNUSED static struct enums termios_oflags_NLDLY[] = { + ENUM_TARGET(NL0), + ENUM_TARGET(NL1), + ENUM_END, +}; + +UNUSED static struct enums termios_oflags_CRDLY[] = { + ENUM_TARGET(CR0), + ENUM_TARGET(CR1), + ENUM_TARGET(CR2), + ENUM_TARGET(CR3), + ENUM_END, +}; + +UNUSED static struct enums termios_oflags_TABDLY[] = { + ENUM_TARGET(TAB0), + ENUM_TARGET(TAB1), + ENUM_TARGET(TAB2), + ENUM_TARGET(TAB3), + ENUM_END, +}; + +UNUSED static struct enums termios_oflags_VTDLY[] = { + ENUM_TARGET(VT0), + ENUM_TARGET(VT1), + ENUM_END, +}; + +UNUSED static struct enums termios_oflags_FFDLY[] = { + ENUM_TARGET(FF0), + ENUM_TARGET(FF1), + ENUM_END, +}; + +UNUSED static struct enums termios_oflags_BSDLY[] = { + ENUM_TARGET(BS0), + ENUM_TARGET(BS1), + ENUM_END, +}; + +UNUSED static struct enums termios_cflags_CBAUD[] = { + ENUM_TARGET(B0), + ENUM_TARGET(B50), + ENUM_TARGET(B75), + ENUM_TARGET(B110), + ENUM_TARGET(B134), + ENUM_TARGET(B150), + ENUM_TARGET(B200), + ENUM_TARGET(B300), + ENUM_TARGET(B600), + ENUM_TARGET(B1200), + ENUM_TARGET(B1800), + ENUM_TARGET(B2400), + ENUM_TARGET(B4800), + ENUM_TARGET(B9600), + ENUM_TARGET(B19200), + ENUM_TARGET(B38400), + ENUM_TARGET(B57600), + ENUM_TARGET(B115200), + ENUM_TARGET(B230400), + ENUM_TARGET(B460800), + ENUM_END, +}; + +UNUSED static struct enums termios_cflags_CSIZE[] = { + ENUM_TARGET(CS5), + ENUM_TARGET(CS6), + ENUM_TARGET(CS7), + ENUM_TARGET(CS8), + ENUM_END, +}; + +UNUSED static struct flags termios_cflags[] = { + FLAG_TARGET(CSTOPB), + FLAG_TARGET(CREAD), + FLAG_TARGET(PARENB), + FLAG_TARGET(PARODD), + FLAG_TARGET(HUPCL), + FLAG_TARGET(CLOCAL), + FLAG_TARGET(CRTSCTS), + FLAG_END, +}; + +UNUSED static struct flags termios_lflags[] = { + FLAG_TARGET(ISIG), + FLAG_TARGET(ICANON), + FLAG_TARGET(XCASE), + FLAG_TARGET(ECHO), + FLAG_TARGET(ECHOE), + FLAG_TARGET(ECHOK), + FLAG_TARGET(ECHONL), + FLAG_TARGET(NOFLSH), + FLAG_TARGET(TOSTOP), + FLAG_TARGET(ECHOCTL), + FLAG_TARGET(ECHOPRT), + FLAG_TARGET(ECHOKE), + FLAG_TARGET(FLUSHO), + FLAG_TARGET(PENDIN), + FLAG_TARGET(IEXTEN), + FLAG_TARGET(EXTPROC), + FLAG_END, +}; + +UNUSED static struct flags mlockall_flags[] = { + FLAG_TARGET(MCL_CURRENT), + FLAG_TARGET(MCL_FUTURE), +#ifdef MCL_ONFAULT + FLAG_TARGET(MCL_ONFAULT), +#endif + FLAG_END, +}; + +/* IDs of the various system clocks */ +#define TARGET_CLOCK_REALTIME 0 +#define TARGET_CLOCK_MONOTONIC 1 +#define TARGET_CLOCK_PROCESS_CPUTIME_ID 2 +#define TARGET_CLOCK_THREAD_CPUTIME_ID 3 +#define TARGET_CLOCK_MONOTONIC_RAW 4 +#define TARGET_CLOCK_REALTIME_COARSE 5 +#define TARGET_CLOCK_MONOTONIC_COARSE 6 +#define TARGET_CLOCK_BOOTTIME 7 +#define TARGET_CLOCK_REALTIME_ALARM 8 +#define TARGET_CLOCK_BOOTTIME_ALARM 9 +#define TARGET_CLOCK_SGI_CYCLE 10 +#define TARGET_CLOCK_TAI 11 + +UNUSED static struct enums clockids[] = { + ENUM_TARGET(CLOCK_REALTIME), + ENUM_TARGET(CLOCK_MONOTONIC), + ENUM_TARGET(CLOCK_PROCESS_CPUTIME_ID), + ENUM_TARGET(CLOCK_THREAD_CPUTIME_ID), + ENUM_TARGET(CLOCK_MONOTONIC_RAW), + ENUM_TARGET(CLOCK_REALTIME_COARSE), + ENUM_TARGET(CLOCK_MONOTONIC_COARSE), + ENUM_TARGET(CLOCK_BOOTTIME), + ENUM_TARGET(CLOCK_REALTIME_ALARM), + ENUM_TARGET(CLOCK_BOOTTIME_ALARM), + ENUM_TARGET(CLOCK_SGI_CYCLE), + ENUM_TARGET(CLOCK_TAI), + ENUM_END, +}; + +UNUSED static struct enums itimer_types[] = { + ENUM_GENERIC(ITIMER_REAL), + ENUM_GENERIC(ITIMER_VIRTUAL), + ENUM_GENERIC(ITIMER_PROF), + ENUM_END, +}; + /* * print_xxx utility functions. These are used to print syscall * parameters in certain format. All of these have parameter @@ -1142,6 +1451,23 @@ print_flags(const struct flags *f, abi_long flags, int last) } } +static void +print_enums(const struct enums *e, abi_long enum_arg, int last) +{ + for (; e->e_string != NULL; e++) { + if (e->e_value == enum_arg) { + qemu_log("%s", e->e_string); + break; + } + } + + if (e->e_string == NULL) { + qemu_log("%#x", (unsigned int)enum_arg); + } + + qemu_log("%s", get_comma(last)); +} + static void print_at_dirfd(abi_long dirfd, int last) { @@ -1298,13 +1624,34 @@ print_timeval(abi_ulong tv_addr, int last) print_pointer(tv_addr, last); return; } - qemu_log("{" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "}%s", - tswapal(tv->tv_sec), tswapal(tv->tv_usec), get_comma(last)); + qemu_log("{tv_sec = " TARGET_ABI_FMT_ld + ",tv_usec = " TARGET_ABI_FMT_ld "}%s", + tswapal(tv->tv_sec), tswapal(tv->tv_usec), get_comma(last)); unlock_user(tv, tv_addr, 0); } else qemu_log("NULL%s", get_comma(last)); } +static void +print_timespec(abi_ulong ts_addr, int last) +{ + if (ts_addr) { + struct target_timespec *ts; + + ts = lock_user(VERIFY_READ, ts_addr, sizeof(*ts), 1); + if (!ts) { + print_pointer(ts_addr, last); + return; + } + qemu_log("{tv_sec = " TARGET_ABI_FMT_ld + ",tv_nsec = " TARGET_ABI_FMT_ld "}%s", + tswapal(ts->tv_sec), tswapal(ts->tv_nsec), get_comma(last)); + unlock_user(ts, ts_addr, 0); + } else { + qemu_log("NULL%s", get_comma(last)); + } +} + static void print_timezone(abi_ulong tz_addr, int last) { @@ -1324,13 +1671,90 @@ print_timezone(abi_ulong tz_addr, int last) } } +static void +print_itimerval(abi_ulong it_addr, int last) +{ + if (it_addr) { + qemu_log("{it_interval="); + print_timeval(it_addr + + offsetof(struct target_itimerval, it_interval), 0); + qemu_log("it_value="); + print_timeval(it_addr + + offsetof(struct target_itimerval, it_value), 0); + qemu_log("}%s", get_comma(last)); + } else { + qemu_log("NULL%s", get_comma(last)); + } +} + +void +print_termios(void *arg) +{ + const struct target_termios *target = arg; + + target_tcflag_t iflags = tswap32(target->c_iflag); + target_tcflag_t oflags = tswap32(target->c_oflag); + target_tcflag_t cflags = tswap32(target->c_cflag); + target_tcflag_t lflags = tswap32(target->c_lflag); + + qemu_log("{"); + + qemu_log("c_iflag = "); + print_flags(termios_iflags, iflags, 0); + + qemu_log("c_oflag = "); + target_tcflag_t oflags_clean = oflags & ~(TARGET_NLDLY | TARGET_CRDLY | + TARGET_TABDLY | TARGET_BSDLY | + TARGET_VTDLY | TARGET_FFDLY); + print_flags(termios_oflags, oflags_clean, 0); + if (oflags & TARGET_NLDLY) { + print_enums(termios_oflags_NLDLY, oflags & TARGET_NLDLY, 0); + } + if (oflags & TARGET_CRDLY) { + print_enums(termios_oflags_CRDLY, oflags & TARGET_CRDLY, 0); + } + if (oflags & TARGET_TABDLY) { + print_enums(termios_oflags_TABDLY, oflags & TARGET_TABDLY, 0); + } + if (oflags & TARGET_BSDLY) { + print_enums(termios_oflags_BSDLY, oflags & TARGET_BSDLY, 0); + } + if (oflags & TARGET_VTDLY) { + print_enums(termios_oflags_VTDLY, oflags & TARGET_VTDLY, 0); + } + if (oflags & TARGET_FFDLY) { + print_enums(termios_oflags_FFDLY, oflags & TARGET_FFDLY, 0); + } + + qemu_log("c_cflag = "); + if (cflags & TARGET_CBAUD) { + print_enums(termios_cflags_CBAUD, cflags & TARGET_CBAUD, 0); + } + if (cflags & TARGET_CSIZE) { + print_enums(termios_cflags_CSIZE, cflags & TARGET_CSIZE, 0); + } + target_tcflag_t cflags_clean = cflags & ~(TARGET_CBAUD | TARGET_CSIZE); + print_flags(termios_cflags, cflags_clean, 0); + + qemu_log("c_lflag = "); + print_flags(termios_lflags, lflags, 0); + + qemu_log("c_cc = "); + qemu_log("\"%s\",", target->c_cc); + + qemu_log("c_line = "); + print_raw_param("\'%c\'", target->c_line, 1); + + qemu_log("}"); +} + #undef UNUSED #ifdef TARGET_NR_accept static void -print_accept(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_accept(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_raw_param("%d", arg0, 0); @@ -1342,9 +1766,9 @@ print_accept(const struct syscallname *name, #ifdef TARGET_NR_access static void -print_access(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_access(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -1353,11 +1777,23 @@ print_access(const struct syscallname *name, } #endif +#ifdef TARGET_NR_acct +static void +print_acct(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_string(arg0, 1); + print_syscall_epilogue(name); +} +#endif + #ifdef TARGET_NR_brk static void -print_brk(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_brk(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_pointer(arg0, 1); @@ -1367,9 +1803,9 @@ print_brk(const struct syscallname *name, #ifdef TARGET_NR_chdir static void -print_chdir(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_chdir(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 1); @@ -1379,9 +1815,9 @@ print_chdir(const struct syscallname *name, #ifdef TARGET_NR_chroot static void -print_chroot(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_chroot(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 1); @@ -1391,9 +1827,9 @@ print_chroot(const struct syscallname *name, #ifdef TARGET_NR_chmod static void -print_chmod(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_chmod(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -1402,14 +1838,29 @@ print_chmod(const struct syscallname *name, } #endif +#if defined(TARGET_NR_chown) || defined(TARGET_NR_lchown) +static void +print_chown(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_string(arg0, 0); + print_raw_param("%d", arg1, 0); + print_raw_param("%d", arg2, 1); + print_syscall_epilogue(name); +} +#define print_lchown print_chown +#endif + #ifdef TARGET_NR_clock_adjtime static void -print_clock_adjtime(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_clock_adjtime(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); - print_clockid(arg0, 0); + print_enums(clockids, arg0, 0); print_pointer(arg1, 1); print_syscall_epilogue(name); } @@ -1428,9 +1879,9 @@ static void do_print_clone(unsigned int flags, abi_ulong newsp, } static void -print_clone(const struct syscallname *name, - abi_long arg1, abi_long arg2, abi_long arg3, - abi_long arg4, abi_long arg5, abi_long arg6) +print_clone(void *cpu_env, const struct syscallname *name, + abi_long arg1, abi_long arg2, abi_long arg3, + abi_long arg4, abi_long arg5, abi_long arg6) { print_syscall_prologue(name); #if defined(TARGET_MICROBLAZE) @@ -1448,9 +1899,9 @@ print_clone(const struct syscallname *name, #ifdef TARGET_NR_creat static void -print_creat(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_creat(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -1461,9 +1912,9 @@ print_creat(const struct syscallname *name, #ifdef TARGET_NR_execv static void -print_execv(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_execv(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -1474,9 +1925,9 @@ print_execv(const struct syscallname *name, #ifdef TARGET_NR_faccessat static void -print_faccessat(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_faccessat(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_at_dirfd(arg0, 0); @@ -1487,11 +1938,31 @@ print_faccessat(const struct syscallname *name, } #endif +#ifdef TARGET_NR_fallocate +static void +print_fallocate(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_raw_param("%d", arg0, 0); + print_flags(falloc_flags, arg1, 0); +#if TARGET_ABI_BITS == 32 + print_raw_param("%" PRIu64, target_offset64(arg2, arg3), 0); + print_raw_param("%" PRIu64, target_offset64(arg4, arg5), 1); +#else + print_raw_param(TARGET_ABI_FMT_ld, arg2, 0); + print_raw_param(TARGET_ABI_FMT_ld, arg3, 1); +#endif + print_syscall_epilogue(name); +} +#endif + #ifdef TARGET_NR_fchmodat static void -print_fchmodat(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_fchmodat(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_at_dirfd(arg0, 0); @@ -1504,9 +1975,9 @@ print_fchmodat(const struct syscallname *name, #ifdef TARGET_NR_fchownat static void -print_fchownat(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_fchownat(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_at_dirfd(arg0, 0); @@ -1520,9 +1991,9 @@ print_fchownat(const struct syscallname *name, #if defined(TARGET_NR_fcntl) || defined(TARGET_NR_fcntl64) static void -print_fcntl(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_fcntl(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_raw_param("%d", arg0, 0); @@ -1585,6 +2056,18 @@ print_fcntl(const struct syscallname *name, print_pointer(arg2, 1); break; #endif + case TARGET_F_OFD_GETLK: + qemu_log("F_OFD_GETLK,"); + print_pointer(arg2, 1); + break; + case TARGET_F_OFD_SETLK: + qemu_log("F_OFD_SETLK,"); + print_pointer(arg2, 1); + break; + case TARGET_F_OFD_SETLKW: + qemu_log("F_OFD_SETLKW,"); + print_pointer(arg2, 1); + break; case TARGET_F_SETLEASE: qemu_log("F_SETLEASE,"); print_raw_param(TARGET_ABI_FMT_ld, arg2, 0); @@ -1617,12 +2100,98 @@ print_fcntl(const struct syscallname *name, #define print_fcntl64 print_fcntl #endif +#ifdef TARGET_NR_fgetxattr +static void +print_fgetxattr(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_raw_param("%d", arg0, 0); + print_string(arg1, 0); + print_pointer(arg2, 0); + print_raw_param(TARGET_FMT_lu, arg3, 1); + print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_flistxattr +static void +print_flistxattr(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_raw_param("%d", arg0, 0); + print_pointer(arg1, 0); + print_raw_param(TARGET_FMT_lu, arg2, 1); + print_syscall_epilogue(name); +} +#endif + +#if defined(TARGET_NR_getxattr) || defined(TARGET_NR_lgetxattr) +static void +print_getxattr(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_string(arg0, 0); + print_string(arg1, 0); + print_pointer(arg2, 0); + print_raw_param(TARGET_FMT_lu, arg3, 1); + print_syscall_epilogue(name); +} +#define print_lgetxattr print_getxattr +#endif + +#if defined(TARGET_NR_listxattr) || defined(TARGET_NR_llistxattr) +static void +print_listxattr(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_string(arg0, 0); + print_pointer(arg1, 0); + print_raw_param(TARGET_FMT_lu, arg2, 1); + print_syscall_epilogue(name); +} +#define print_llistxattr print_listxattr +#endif + +#if defined(TARGET_NR_fremovexattr) +static void +print_fremovexattr(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_raw_param("%d", arg0, 0); + print_string(arg1, 1); + print_syscall_epilogue(name); +} +#endif + +#if defined(TARGET_NR_removexattr) || defined(TARGET_NR_lremovexattr) +static void +print_removexattr(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_string(arg0, 0); + print_string(arg1, 1); + print_syscall_epilogue(name); +} +#define print_lremovexattr print_removexattr +#endif #ifdef TARGET_NR_futimesat static void -print_futimesat(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_futimesat(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_at_dirfd(arg0, 0); @@ -1633,11 +2202,24 @@ print_futimesat(const struct syscallname *name, } #endif +#ifdef TARGET_NR_gettimeofday +static void +print_gettimeofday(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_pointer(arg0, 0); + print_pointer(arg1, 1); + print_syscall_epilogue(name); +} +#endif + #ifdef TARGET_NR_settimeofday static void -print_settimeofday(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_settimeofday(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_timeval(arg0, 0); @@ -1646,11 +2228,65 @@ print_settimeofday(const struct syscallname *name, } #endif +#if defined(TARGET_NR_clock_gettime) || defined(TARGET_NR_clock_getres) +static void +print_clock_gettime(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_enums(clockids, arg0, 0); + print_pointer(arg1, 1); + print_syscall_epilogue(name); +} +#define print_clock_getres print_clock_gettime +#endif + +#ifdef TARGET_NR_clock_settime +static void +print_clock_settime(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_enums(clockids, arg0, 0); + print_timespec(arg1, 1); + print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_getitimer +static void +print_getitimer(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_enums(itimer_types, arg0, 0); + print_pointer(arg1, 1); + print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_setitimer +static void +print_setitimer(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_enums(itimer_types, arg0, 0); + print_itimerval(arg1, 0); + print_pointer(arg2, 1); + print_syscall_epilogue(name); +} +#endif + #ifdef TARGET_NR_link static void -print_link(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_link(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -1661,9 +2297,9 @@ print_link(const struct syscallname *name, #ifdef TARGET_NR_linkat static void -print_linkat(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_linkat(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_at_dirfd(arg0, 0); @@ -1677,9 +2313,9 @@ print_linkat(const struct syscallname *name, #ifdef TARGET_NR__llseek static void -print__llseek(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print__llseek(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { const char *whence = "UNKNOWN"; print_syscall_prologue(name); @@ -1697,9 +2333,99 @@ print__llseek(const struct syscallname *name, } #endif +#ifdef TARGET_NR_lseek +static void +print_lseek(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_raw_param("%d", arg0, 0); + print_raw_param(TARGET_ABI_FMT_ld, arg1, 0); + switch (arg2) { + case SEEK_SET: + qemu_log("SEEK_SET"); break; + case SEEK_CUR: + qemu_log("SEEK_CUR"); break; + case SEEK_END: + qemu_log("SEEK_END"); break; +#ifdef SEEK_DATA + case SEEK_DATA: + qemu_log("SEEK_DATA"); break; +#endif +#ifdef SEEK_HOLE + case SEEK_HOLE: + qemu_log("SEEK_HOLE"); break; +#endif + default: + print_raw_param("%#x", arg2, 1); + } + print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_truncate +static void +print_truncate(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_string(arg0, 0); + print_raw_param(TARGET_ABI_FMT_ld, arg1, 1); + print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_truncate64 +static void +print_truncate64(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_string(arg0, 0); + if (regpairs_aligned(cpu_env, TARGET_NR_truncate64)) { + arg1 = arg2; + arg2 = arg3; + } + print_raw_param("%" PRIu64, target_offset64(arg1, arg2), 1); + print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_ftruncate64 +static void +print_ftruncate64(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_raw_param("%d", arg0, 0); + if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64)) { + arg1 = arg2; + arg2 = arg3; + } + print_raw_param("%" PRIu64, target_offset64(arg1, arg2), 1); + print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_mlockall +static void +print_mlockall(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_flags(mlockall_flags, arg0, 1); + print_syscall_epilogue(name); +} +#endif + #if defined(TARGET_NR_socket) static void -print_socket(const struct syscallname *name, +print_socket(void *cpu_env, const struct syscallname *name, abi_long arg0, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) { @@ -2048,7 +2774,7 @@ static struct { }; static void -print_socketcall(const struct syscallname *name, +print_socketcall(void *cpu_env, const struct syscallname *name, abi_long arg0, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) { @@ -2069,7 +2795,7 @@ print_socketcall(const struct syscallname *name, #if defined(TARGET_NR_bind) static void -print_bind(const struct syscallname *name, +print_bind(void *cpu_env, const struct syscallname *name, abi_long arg0, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) { @@ -2083,9 +2809,9 @@ print_bind(const struct syscallname *name, #if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) || \ defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) static void -print_stat(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_stat(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -2099,9 +2825,9 @@ print_stat(const struct syscallname *name, #if defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) static void -print_fstat(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_fstat(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_raw_param("%d", arg0, 0); @@ -2113,9 +2839,9 @@ print_fstat(const struct syscallname *name, #ifdef TARGET_NR_mkdir static void -print_mkdir(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_mkdir(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -2126,9 +2852,9 @@ print_mkdir(const struct syscallname *name, #ifdef TARGET_NR_mkdirat static void -print_mkdirat(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_mkdirat(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_at_dirfd(arg0, 0); @@ -2140,9 +2866,9 @@ print_mkdirat(const struct syscallname *name, #ifdef TARGET_NR_rmdir static void -print_rmdir(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_rmdir(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -2152,9 +2878,9 @@ print_rmdir(const struct syscallname *name, #ifdef TARGET_NR_rt_sigaction static void -print_rt_sigaction(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_rt_sigaction(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_signal(arg0, 0); @@ -2166,9 +2892,9 @@ print_rt_sigaction(const struct syscallname *name, #ifdef TARGET_NR_rt_sigprocmask static void -print_rt_sigprocmask(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_rt_sigprocmask(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { const char *how = "UNKNOWN"; print_syscall_prologue(name); @@ -2186,9 +2912,9 @@ print_rt_sigprocmask(const struct syscallname *name, #ifdef TARGET_NR_rt_sigqueueinfo static void -print_rt_sigqueueinfo(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_rt_sigqueueinfo(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { void *p; target_siginfo_t uinfo; @@ -2211,9 +2937,9 @@ print_rt_sigqueueinfo(const struct syscallname *name, #ifdef TARGET_NR_rt_tgsigqueueinfo static void -print_rt_tgsigqueueinfo(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_rt_tgsigqueueinfo(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { void *p; target_siginfo_t uinfo; @@ -2295,9 +3021,9 @@ print_syslog_action(abi_ulong arg, int last) } static void -print_syslog(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_syslog(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_syslog_action(arg0, 0); @@ -2309,9 +3035,9 @@ print_syslog(const struct syscallname *name, #ifdef TARGET_NR_mknod static void -print_mknod(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_mknod(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { int hasdev = (arg1 & (S_IFCHR|S_IFBLK)); @@ -2328,9 +3054,9 @@ print_mknod(const struct syscallname *name, #ifdef TARGET_NR_mknodat static void -print_mknodat(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_mknodat(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { int hasdev = (arg2 & (S_IFCHR|S_IFBLK)); @@ -2348,9 +3074,9 @@ print_mknodat(const struct syscallname *name, #ifdef TARGET_NR_mq_open static void -print_mq_open(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_mq_open(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { int is_creat = (arg1 & TARGET_O_CREAT); @@ -2367,9 +3093,9 @@ print_mq_open(const struct syscallname *name, #ifdef TARGET_NR_open static void -print_open(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_open(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { int is_creat = (arg1 & TARGET_O_CREAT); @@ -2384,9 +3110,9 @@ print_open(const struct syscallname *name, #ifdef TARGET_NR_openat static void -print_openat(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_openat(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { int is_creat = (arg2 & TARGET_O_CREAT); @@ -2402,9 +3128,9 @@ print_openat(const struct syscallname *name, #ifdef TARGET_NR_mq_unlink static void -print_mq_unlink(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_mq_unlink(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 1); @@ -2414,9 +3140,9 @@ print_mq_unlink(const struct syscallname *name, #if defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat) static void -print_fstatat64(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_fstatat64(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_at_dirfd(arg0, 0); @@ -2430,9 +3156,9 @@ print_fstatat64(const struct syscallname *name, #ifdef TARGET_NR_readlink static void -print_readlink(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_readlink(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -2444,9 +3170,9 @@ print_readlink(const struct syscallname *name, #ifdef TARGET_NR_readlinkat static void -print_readlinkat(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_readlinkat(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_at_dirfd(arg0, 0); @@ -2459,9 +3185,9 @@ print_readlinkat(const struct syscallname *name, #ifdef TARGET_NR_rename static void -print_rename(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_rename(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -2472,9 +3198,9 @@ print_rename(const struct syscallname *name, #ifdef TARGET_NR_renameat static void -print_renameat(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_renameat(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_at_dirfd(arg0, 0); @@ -2487,9 +3213,9 @@ print_renameat(const struct syscallname *name, #ifdef TARGET_NR_statfs static void -print_statfs(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_statfs(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -2500,9 +3226,9 @@ print_statfs(const struct syscallname *name, #ifdef TARGET_NR_statfs64 static void -print_statfs64(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_statfs64(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -2513,9 +3239,9 @@ print_statfs64(const struct syscallname *name, #ifdef TARGET_NR_symlink static void -print_symlink(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_symlink(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -2526,9 +3252,9 @@ print_symlink(const struct syscallname *name, #ifdef TARGET_NR_symlinkat static void -print_symlinkat(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_symlinkat(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -2540,9 +3266,9 @@ print_symlinkat(const struct syscallname *name, #ifdef TARGET_NR_mount static void -print_mount(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_mount(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -2556,9 +3282,9 @@ print_mount(const struct syscallname *name, #ifdef TARGET_NR_umount static void -print_umount(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_umount(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 1); @@ -2568,9 +3294,9 @@ print_umount(const struct syscallname *name, #ifdef TARGET_NR_umount2 static void -print_umount2(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_umount2(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -2581,9 +3307,9 @@ print_umount2(const struct syscallname *name, #ifdef TARGET_NR_unlink static void -print_unlink(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_unlink(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 1); @@ -2593,9 +3319,9 @@ print_unlink(const struct syscallname *name, #ifdef TARGET_NR_unlinkat static void -print_unlinkat(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_unlinkat(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_at_dirfd(arg0, 0); @@ -2607,9 +3333,9 @@ print_unlinkat(const struct syscallname *name, #ifdef TARGET_NR_utime static void -print_utime(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_utime(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -2620,9 +3346,9 @@ print_utime(const struct syscallname *name, #ifdef TARGET_NR_utimes static void -print_utimes(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_utimes(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_string(arg0, 0); @@ -2633,9 +3359,9 @@ print_utimes(const struct syscallname *name, #ifdef TARGET_NR_utimensat static void -print_utimensat(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_utimensat(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_at_dirfd(arg0, 0); @@ -2648,9 +3374,9 @@ print_utimensat(const struct syscallname *name, #if defined(TARGET_NR_mmap) || defined(TARGET_NR_mmap2) static void -print_mmap(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_mmap(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_pointer(arg0, 0); @@ -2666,9 +3392,9 @@ print_mmap(const struct syscallname *name, #ifdef TARGET_NR_mprotect static void -print_mprotect(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_mprotect(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_pointer(arg0, 0); @@ -2680,9 +3406,9 @@ print_mprotect(const struct syscallname *name, #ifdef TARGET_NR_munmap static void -print_munmap(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_munmap(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_pointer(arg0, 0); @@ -2733,9 +3459,9 @@ if( cmd == val ) { \ } static void -print_futex(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_futex(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_pointer(arg0, 0); @@ -2750,9 +3476,9 @@ print_futex(const struct syscallname *name, #ifdef TARGET_NR_kill static void -print_kill(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_kill(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_raw_param("%d", arg0, 0); @@ -2763,9 +3489,9 @@ print_kill(const struct syscallname *name, #ifdef TARGET_NR_tkill static void -print_tkill(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_tkill(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_raw_param("%d", arg0, 0); @@ -2776,9 +3502,9 @@ print_tkill(const struct syscallname *name, #ifdef TARGET_NR_tgkill static void -print_tgkill(const struct syscallname *name, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_tgkill(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); print_raw_param("%d", arg0, 0); @@ -2790,7 +3516,7 @@ print_tgkill(const struct syscallname *name, #ifdef TARGET_NR_statx static void -print_statx(const struct syscallname *name, +print_statx(void *cpu_env, const struct syscallname *name, abi_long arg0, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) { @@ -2804,6 +3530,79 @@ print_statx(const struct syscallname *name, } #endif +#ifdef TARGET_NR_ioctl +static void +print_ioctl(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_raw_param("%d", arg0, 0); + + const IOCTLEntry *ie; + const argtype *arg_type; + void *argptr; + int target_size; + + for (ie = ioctl_entries; ie->target_cmd != 0; ie++) { + if (ie->target_cmd == arg1) { + break; + } + } + + if (ie->target_cmd == 0) { + print_raw_param("%#x", arg1, 0); + print_raw_param("%#x", arg2, 1); + } else { + qemu_log("%s", ie->name); + arg_type = ie->arg_type; + + if (arg_type[0] != TYPE_NULL) { + qemu_log(","); + + switch (arg_type[0]) { + case TYPE_PTRVOID: + print_pointer(arg2, 1); + break; + case TYPE_CHAR: + case TYPE_SHORT: + case TYPE_INT: + print_raw_param("%d", arg2, 1); + break; + case TYPE_LONG: + print_raw_param(TARGET_ABI_FMT_ld, arg2, 1); + break; + case TYPE_ULONG: + print_raw_param(TARGET_ABI_FMT_lu, arg2, 1); + break; + case TYPE_PTR: + switch (ie->access) { + case IOC_R: + print_pointer(arg2, 1); + break; + case IOC_W: + case IOC_RW: + arg_type++; + target_size = thunk_type_size(arg_type, 0); + argptr = lock_user(VERIFY_READ, arg2, target_size, 1); + if (argptr) { + thunk_print(argptr, arg_type); + unlock_user(argptr, arg2, target_size); + } else { + print_pointer(arg2, 1); + } + break; + } + break; + default: + g_assert_not_reached(); + } + } + } + print_syscall_epilogue(name); +} +#endif + /* * An array of all of the syscalls we know about */ @@ -2818,7 +3617,7 @@ static int nsyscalls = ARRAY_SIZE(scnames); * The public interface to this module. */ void -print_syscall(int num, +print_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { @@ -2831,7 +3630,7 @@ print_syscall(int num, if( scnames[i].nr == num ) { if( scnames[i].call != NULL ) { scnames[i].call( - &scnames[i], arg1, arg2, arg3, arg4, arg5, arg6); + cpu_env, &scnames[i], arg1, arg2, arg3, arg4, arg5, arg6); } else { /* XXX: this format system is broken because it uses host types and host pointers for strings */ @@ -2847,25 +3646,23 @@ print_syscall(int num, void -print_syscall_ret(int num, abi_long ret) +print_syscall_ret(void *cpu_env, int num, abi_long ret, + abi_long arg1, abi_long arg2, abi_long arg3, + abi_long arg4, abi_long arg5, abi_long arg6) { int i; - const char *errstr = NULL; for(i=0;i #include #include +#ifdef CONFIG_BTRFS +#include +#endif +#ifdef HAVE_DRM_H +#include +#include +#endif #include "linux_loop.h" #include "uname.h" @@ -385,16 +392,9 @@ static bitmask_transtbl fcntl_flags_tbl[] = { { 0, 0, 0, 0 } }; -static int sys_getcwd1(char *buf, size_t size) -{ - if (getcwd(buf, size) == NULL) { - /* getcwd() sets errno */ - return (-1); - } - return strlen(buf)+1; -} +_syscall2(int, sys_getcwd1, char *, buf, size_t, size) -#ifdef TARGET_NR_utimensat +#if defined(TARGET_NR_utimensat) || defined(TARGET_NR_utimensat_time64) #if defined(__NR_utimensat) #define __NR_sys_utimensat __NR_utimensat _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname, @@ -481,7 +481,7 @@ _syscall4(int, sys_prlimit64, pid_t, pid, int, resource, #if defined(TARGET_NR_timer_create) -/* Maxiumum of 32 active POSIX timers allowed at any one time. */ +/* Maximum of 32 active POSIX timers allowed at any one time. */ static timer_t g_posix_timers[32] = { 0, } ; static inline int next_free_host_timer(void) @@ -498,38 +498,6 @@ static inline int next_free_host_timer(void) } #endif -/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */ -#ifdef TARGET_ARM -static inline int regpairs_aligned(void *cpu_env, int num) -{ - return ((((CPUARMState *)cpu_env)->eabi) == 1) ; -} -#elif defined(TARGET_MIPS) && (TARGET_ABI_BITS == 32) -static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } -#elif defined(TARGET_PPC) && !defined(TARGET_PPC64) -/* SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs - * of registers which translates to the same as ARM/MIPS, because we start with - * r3 as arg1 */ -static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } -#elif defined(TARGET_SH4) -/* SH4 doesn't align register pairs, except for p{read,write}64 */ -static inline int regpairs_aligned(void *cpu_env, int num) -{ - switch (num) { - case TARGET_NR_pread64: - case TARGET_NR_pwrite64: - return 1; - - default: - return 0; - } -} -#elif defined(TARGET_XTENSA) -static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } -#else -static inline int regpairs_aligned(void *cpu_env, int num) { return 0; } -#endif - #define ERRNO_TABLE_SIZE 1200 /* target_to_host_errno_table[] is initialized from @@ -760,11 +728,11 @@ safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \ int, options, struct rusage *, rusage) safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp) #if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \ - defined(TARGET_NR_pselect6) + defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64) safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \ fd_set *, exceptfds, struct timespec *, timeout, void *, sig) #endif -#if defined(TARGET_NR_ppoll) || defined(TARGET_NR_poll) +#if defined(TARGET_NR_ppoll) || defined(TARGET_NR_ppoll_time64) safe_syscall5(int, ppoll, struct pollfd *, ufds, unsigned int, nfds, struct timespec *, tsp, const sigset_t *, sigmask, size_t, sigsetsize) @@ -799,7 +767,7 @@ safe_syscall6(ssize_t, recvfrom, int, fd, void *, buf, size_t, len, safe_syscall3(ssize_t, sendmsg, int, fd, const struct msghdr *, msg, int, flags) safe_syscall3(ssize_t, recvmsg, int, fd, struct msghdr *, msg, int, flags) safe_syscall2(int, flock, int, fd, int, operation) -#ifdef TARGET_NR_rt_sigtimedwait +#if defined(TARGET_NR_rt_sigtimedwait) || defined(TARGET_NR_rt_sigtimedwait_time64) safe_syscall4(int, rt_sigtimedwait, const sigset_t *, these, siginfo_t *, uinfo, const struct timespec *, uts, size_t, sigsetsize) #endif @@ -809,14 +777,20 @@ safe_syscall4(int, accept4, int, fd, struct sockaddr *, addr, socklen_t *, len, safe_syscall2(int, nanosleep, const struct timespec *, req, struct timespec *, rem) #endif -#ifdef TARGET_NR_clock_nanosleep +#if defined(TARGET_NR_clock_nanosleep) || \ + defined(TARGET_NR_clock_nanosleep_time64) safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags, const struct timespec *, req, struct timespec *, rem) #endif #ifdef __NR_ipc +#ifdef __s390x__ +safe_syscall5(int, ipc, int, call, long, first, long, second, long, third, + void *, ptr) +#else safe_syscall6(int, ipc, int, call, long, first, long, second, long, third, void *, ptr, long, fifth) #endif +#endif #ifdef __NR_msgsnd safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz, int, flags) @@ -829,11 +803,13 @@ safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz, safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops, unsigned, nsops, const struct timespec *, timeout) #endif -#ifdef TARGET_NR_mq_timedsend +#if defined(TARGET_NR_mq_timedsend) || \ + defined(TARGET_NR_mq_timedsend_time64) safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr, size_t, len, unsigned, prio, const struct timespec *, timeout) #endif -#ifdef TARGET_NR_mq_timedreceive +#if defined(TARGET_NR_mq_timedreceive) || \ + defined(TARGET_NR_mq_timedreceive_time64) safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr, size_t, len, unsigned *, prio, const struct timespec *, timeout) #endif @@ -976,7 +952,7 @@ abi_long do_brk(abi_ulong new_brk) } #if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \ - defined(TARGET_NR_pselect6) + defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64) static inline abi_long copy_from_user_fdset(fd_set *fds, abi_ulong target_fds_addr, int n) @@ -1205,8 +1181,27 @@ static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr, return 0; } +#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME) +static inline abi_long copy_from_user_timeval64(struct timeval *tv, + abi_ulong target_tv_addr) +{ + struct target__kernel_sock_timeval *target_tv; + + if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) { + return -TARGET_EFAULT; + } + + __get_user(tv->tv_sec, &target_tv->tv_sec); + __get_user(tv->tv_usec, &target_tv->tv_usec); + + unlock_user_struct(target_tv, target_tv_addr, 0); + + return 0; +} +#endif + static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr, - const struct timeval *tv) + const struct timeval *tv) { struct target__kernel_sock_timeval *target_tv; @@ -1227,7 +1222,10 @@ static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr, defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6) || \ defined(TARGET_NR_nanosleep) || defined(TARGET_NR_clock_settime) || \ defined(TARGET_NR_utimensat) || defined(TARGET_NR_mq_timedsend) || \ - defined(TARGET_NR_mq_timedreceive) + defined(TARGET_NR_mq_timedreceive) || defined(TARGET_NR_ipc) || \ + defined(TARGET_NR_semop) || defined(TARGET_NR_semtimedop) || \ + defined(TARGET_NR_timer_settime) || \ + (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)) static inline abi_long target_to_host_timespec(struct timespec *host_ts, abi_ulong target_addr) { @@ -1243,7 +1241,17 @@ static inline abi_long target_to_host_timespec(struct timespec *host_ts, } #endif -#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) +#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \ + defined(TARGET_NR_timer_settime64) || \ + defined(TARGET_NR_mq_timedsend_time64) || \ + defined(TARGET_NR_mq_timedreceive_time64) || \ + (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) || \ + defined(TARGET_NR_clock_nanosleep_time64) || \ + defined(TARGET_NR_rt_sigtimedwait_time64) || \ + defined(TARGET_NR_utimensat) || \ + defined(TARGET_NR_utimensat_time64) || \ + defined(TARGET_NR_semtimedop_time64) || \ + defined(TARGET_NR_pselect6_time64) || defined(TARGET_NR_ppoll_time64) static inline abi_long target_to_host_timespec64(struct timespec *host_ts, abi_ulong target_addr) { @@ -1254,6 +1262,8 @@ static inline abi_long target_to_host_timespec64(struct timespec *host_ts, } __get_user(host_ts->tv_sec, &target_ts->tv_sec); __get_user(host_ts->tv_nsec, &target_ts->tv_nsec); + /* in 32bit mode, this drops the padding */ + host_ts->tv_nsec = (long)(abi_long)host_ts->tv_nsec; unlock_user_struct(target_ts, target_addr, 0); return 0; } @@ -1449,6 +1459,237 @@ static abi_long do_old_select(abi_ulong arg1) #endif #endif +#if defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64) +static abi_long do_pselect6(abi_long arg1, abi_long arg2, abi_long arg3, + abi_long arg4, abi_long arg5, abi_long arg6, + bool time64) +{ + abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr; + fd_set rfds, wfds, efds; + fd_set *rfds_ptr, *wfds_ptr, *efds_ptr; + struct timespec ts, *ts_ptr; + abi_long ret; + + /* + * The 6th arg is actually two args smashed together, + * so we cannot use the C library. + */ + sigset_t set; + struct { + sigset_t *set; + size_t size; + } sig, *sig_ptr; + + abi_ulong arg_sigset, arg_sigsize, *arg7; + target_sigset_t *target_sigset; + + n = arg1; + rfd_addr = arg2; + wfd_addr = arg3; + efd_addr = arg4; + ts_addr = arg5; + + ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n); + if (ret) { + return ret; + } + ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n); + if (ret) { + return ret; + } + ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n); + if (ret) { + return ret; + } + + /* + * This takes a timespec, and not a timeval, so we cannot + * use the do_select() helper ... + */ + if (ts_addr) { + if (time64) { + if (target_to_host_timespec64(&ts, ts_addr)) { + return -TARGET_EFAULT; + } + } else { + if (target_to_host_timespec(&ts, ts_addr)) { + return -TARGET_EFAULT; + } + } + ts_ptr = &ts; + } else { + ts_ptr = NULL; + } + + /* Extract the two packed args for the sigset */ + if (arg6) { + sig_ptr = &sig; + sig.size = SIGSET_T_SIZE; + + arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1); + if (!arg7) { + return -TARGET_EFAULT; + } + arg_sigset = tswapal(arg7[0]); + arg_sigsize = tswapal(arg7[1]); + unlock_user(arg7, arg6, 0); + + if (arg_sigset) { + sig.set = &set; + if (arg_sigsize != sizeof(*target_sigset)) { + /* Like the kernel, we enforce correct size sigsets */ + return -TARGET_EINVAL; + } + target_sigset = lock_user(VERIFY_READ, arg_sigset, + sizeof(*target_sigset), 1); + if (!target_sigset) { + return -TARGET_EFAULT; + } + target_to_host_sigset(&set, target_sigset); + unlock_user(target_sigset, arg_sigset, 0); + } else { + sig.set = NULL; + } + } else { + sig_ptr = NULL; + } + + ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr, + ts_ptr, sig_ptr)); + + if (!is_error(ret)) { + if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) { + return -TARGET_EFAULT; + } + if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) { + return -TARGET_EFAULT; + } + if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) { + return -TARGET_EFAULT; + } + if (time64) { + if (ts_addr && host_to_target_timespec64(ts_addr, &ts)) { + return -TARGET_EFAULT; + } + } else { + if (ts_addr && host_to_target_timespec(ts_addr, &ts)) { + return -TARGET_EFAULT; + } + } + } + return ret; +} +#endif + +#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll) || \ + defined(TARGET_NR_ppoll_time64) +static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3, + abi_long arg4, abi_long arg5, bool ppoll, bool time64) +{ + struct target_pollfd *target_pfd; + unsigned int nfds = arg2; + struct pollfd *pfd; + unsigned int i; + abi_long ret; + + pfd = NULL; + target_pfd = NULL; + if (nfds) { + if (nfds > (INT_MAX / sizeof(struct target_pollfd))) { + return -TARGET_EINVAL; + } + target_pfd = lock_user(VERIFY_WRITE, arg1, + sizeof(struct target_pollfd) * nfds, 1); + if (!target_pfd) { + return -TARGET_EFAULT; + } + + pfd = alloca(sizeof(struct pollfd) * nfds); + for (i = 0; i < nfds; i++) { + pfd[i].fd = tswap32(target_pfd[i].fd); + pfd[i].events = tswap16(target_pfd[i].events); + } + } + if (ppoll) { + struct timespec _timeout_ts, *timeout_ts = &_timeout_ts; + target_sigset_t *target_set; + sigset_t _set, *set = &_set; + + if (arg3) { + if (time64) { + if (target_to_host_timespec64(timeout_ts, arg3)) { + unlock_user(target_pfd, arg1, 0); + return -TARGET_EFAULT; + } + } else { + if (target_to_host_timespec(timeout_ts, arg3)) { + unlock_user(target_pfd, arg1, 0); + return -TARGET_EFAULT; + } + } + } else { + timeout_ts = NULL; + } + + if (arg4) { + if (arg5 != sizeof(target_sigset_t)) { + unlock_user(target_pfd, arg1, 0); + return -TARGET_EINVAL; + } + + target_set = lock_user(VERIFY_READ, arg4, + sizeof(target_sigset_t), 1); + if (!target_set) { + unlock_user(target_pfd, arg1, 0); + return -TARGET_EFAULT; + } + target_to_host_sigset(set, target_set); + } else { + set = NULL; + } + + ret = get_errno(safe_ppoll(pfd, nfds, timeout_ts, + set, SIGSET_T_SIZE)); + + if (!is_error(ret) && arg3) { + if (time64) { + if (host_to_target_timespec64(arg3, timeout_ts)) { + return -TARGET_EFAULT; + } + } else { + if (host_to_target_timespec(arg3, timeout_ts)) { + return -TARGET_EFAULT; + } + } + } + if (arg4) { + unlock_user(target_set, arg4, 0); + } + } else { + struct timespec ts, *pts; + + if (arg3 >= 0) { + /* Convert ms to secs, ns */ + ts.tv_sec = arg3 / 1000; + ts.tv_nsec = (arg3 % 1000) * 1000000LL; + pts = &ts; + } else { + /* -ve poll() timeout means "infinite" */ + pts = NULL; + } + ret = get_errno(safe_ppoll(pfd, nfds, pts, NULL, 0)); + } + + if (!is_error(ret)) { + for (i = 0; i < nfds; i++) { + target_pfd[i].revents = tswap16(pfd[i].revents); + } + } + unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds); + return ret; +} +#endif + static abi_long do_pipe2(int host_pipe[], int flags) { #ifdef CONFIG_PIPE2 @@ -2987,7 +3228,7 @@ static abi_long do_socket(int domain, int type, int protocol) #endif protocol == NETLINK_KOBJECT_UEVENT || protocol == NETLINK_AUDIT)) { - return -EPFNOSUPPORT; + return -TARGET_EPROTONOSUPPORT; } if (domain == AF_PACKET || @@ -3250,16 +3491,16 @@ static abi_long do_accept4(int fd, abi_ulong target_addr, return get_errno(safe_accept4(fd, NULL, NULL, host_flags)); } - /* linux returns EINVAL if addrlen pointer is invalid */ + /* linux returns EFAULT if addrlen pointer is invalid */ if (get_user_u32(addrlen, target_addrlen_addr)) - return -TARGET_EINVAL; + return -TARGET_EFAULT; if ((int)addrlen < 0) { return -TARGET_EINVAL; } if (!access_ok(VERIFY_WRITE, target_addr, addrlen)) - return -TARGET_EINVAL; + return -TARGET_EFAULT; addr = alloca(addrlen); @@ -3875,25 +4116,68 @@ static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf, return 0; } -static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops) +#if defined(TARGET_NR_ipc) || defined(TARGET_NR_semop) || \ + defined(TARGET_NR_semtimedop) || defined(TARGET_NR_semtimedop_time64) + +/* + * This macro is required to handle the s390 variants, which passes the + * arguments in a different order than default. + */ +#ifdef __s390x__ +#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \ + (__nsops), (__timeout), (__sops) +#else +#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \ + (__nsops), 0, (__sops), (__timeout) +#endif + +static inline abi_long do_semtimedop(int semid, + abi_long ptr, + unsigned nsops, + abi_long timeout, bool time64) { - struct sembuf sops[nsops]; + struct sembuf *sops; + struct timespec ts, *pts = NULL; abi_long ret; - if (target_to_host_sembuf(sops, ptr, nsops)) + if (timeout) { + pts = &ts; + if (time64) { + if (target_to_host_timespec64(pts, timeout)) { + return -TARGET_EFAULT; + } + } else { + if (target_to_host_timespec(pts, timeout)) { + return -TARGET_EFAULT; + } + } + } + + if (nsops > TARGET_SEMOPM) { + return -TARGET_E2BIG; + } + + sops = g_new(struct sembuf, nsops); + + if (target_to_host_sembuf(sops, ptr, nsops)) { + g_free(sops); return -TARGET_EFAULT; + } ret = -TARGET_ENOSYS; #ifdef __NR_semtimedop - ret = get_errno(safe_semtimedop(semid, sops, nsops, NULL)); + ret = get_errno(safe_semtimedop(semid, sops, nsops, pts)); #endif #ifdef __NR_ipc if (ret == -TARGET_ENOSYS) { - ret = get_errno(safe_ipc(IPCOP_semtimedop, semid, nsops, 0, sops, 0)); + ret = get_errno(safe_ipc(IPCOP_semtimedop, semid, + SEMTIMEDOP_IPC_ARGS(nsops, sops, (long)pts))); } #endif + g_free(sops); return ret; } +#endif struct target_msqid_ds { @@ -4053,8 +4337,13 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp, #endif #ifdef __NR_ipc if (ret == -TARGET_ENOSYS) { +#ifdef __s390x__ + ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg, + host_mb)); +#else ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg, host_mb, 0)); +#endif } #endif g_free(host_mb); @@ -4063,6 +4352,20 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp, return ret; } +#ifdef __NR_ipc +#if defined(__sparc__) +/* SPARC for msgrcv it does not use the kludge on final 2 arguments. */ +#define MSGRCV_ARGS(__msgp, __msgtyp) __msgp, __msgtyp +#elif defined(__s390x__) +/* The s390 sys_ipc variant has only five parameters. */ +#define MSGRCV_ARGS(__msgp, __msgtyp) \ + ((long int[]){(long int)__msgp, __msgtyp}) +#else +#define MSGRCV_ARGS(__msgp, __msgtyp) \ + ((long int[]){(long int)__msgp, __msgtyp}), 0 +#endif +#endif + static inline abi_long do_msgrcv(int msqid, abi_long msgp, ssize_t msgsz, abi_long msgtyp, int msgflg) @@ -4091,7 +4394,7 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp, #ifdef __NR_ipc if (ret == -TARGET_ENOSYS) { ret = get_errno(safe_ipc(IPCOP_CALL(1, IPCOP_msgrcv), msqid, msgsz, - msgflg, host_mb, msgtyp)); + msgflg, MSGRCV_ARGS(host_mb, msgtyp))); } #endif @@ -4369,7 +4672,20 @@ static abi_long do_ipc(CPUArchState *cpu_env, switch (call) { case IPCOP_semop: - ret = do_semop(first, ptr, second); + ret = do_semtimedop(first, ptr, second, 0, false); + break; + case IPCOP_semtimedop: + /* + * The s390 sys_ipc variant has only five parameters instead of six + * (as for default variant) and the only difference is the handling of + * SEMTIMEDOP where on s390 the third parameter is used as a pointer + * to a struct timespec where the generic variant uses fifth parameter. + */ +#if defined(TARGET_S390X) + ret = do_semtimedop(first, ptr, second, third, TARGET_ABI_BITS == 64); +#else + ret = do_semtimedop(first, ptr, second, fifth, TARGET_ABI_BITS == 64); +#endif break; case IPCOP_semget: @@ -4478,24 +4794,6 @@ STRUCT_MAX #undef STRUCT #undef STRUCT_SPECIAL -typedef struct IOCTLEntry IOCTLEntry; - -typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp, - int fd, int cmd, abi_long arg); - -struct IOCTLEntry { - int target_cmd; - unsigned int host_cmd; - const char *name; - int access; - do_ioctl_fn *do_ioctl; - const argtype arg_type[5]; -}; - -#define IOC_R 0x0001 -#define IOC_W 0x0002 -#define IOC_RW (IOC_R | IOC_W) - #define MAX_STRUCT_SIZE 4096 #ifdef CONFIG_FIEMAP @@ -5276,60 +5574,189 @@ static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp, } #endif -static IOCTLEntry ioctl_entries[] = { -#define IOCTL(cmd, access, ...) \ - { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } }, -#define IOCTL_SPECIAL(cmd, access, dofn, ...) \ - { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } }, -#define IOCTL_IGNORE(cmd) \ - { TARGET_ ## cmd, 0, #cmd }, -#include "ioctls.h" - { 0, 0, }, -}; +#ifdef HAVE_DRM_H -/* ??? Implement proper locking for ioctls. */ -/* do_ioctl() Must return target values and target errnos. */ -static abi_long do_ioctl(int fd, int cmd, abi_long arg) +static void unlock_drm_version(struct drm_version *host_ver, + struct target_drm_version *target_ver, + bool copy) { - const IOCTLEntry *ie; - const argtype *arg_type; - abi_long ret; - uint8_t buf_temp[MAX_STRUCT_SIZE]; - int target_size; - void *argptr; + unlock_user(host_ver->name, target_ver->name, + copy ? host_ver->name_len : 0); + unlock_user(host_ver->date, target_ver->date, + copy ? host_ver->date_len : 0); + unlock_user(host_ver->desc, target_ver->desc, + copy ? host_ver->desc_len : 0); +} - ie = ioctl_entries; - for(;;) { - if (ie->target_cmd == 0) { - qemu_log_mask( - LOG_UNIMP, "Unsupported ioctl: cmd=0x%04lx\n", (long)cmd); - return -TARGET_ENOSYS; +static inline abi_long target_to_host_drmversion(struct drm_version *host_ver, + struct target_drm_version *target_ver) +{ + memset(host_ver, 0, sizeof(*host_ver)); + + __get_user(host_ver->name_len, &target_ver->name_len); + if (host_ver->name_len) { + host_ver->name = lock_user(VERIFY_WRITE, target_ver->name, + target_ver->name_len, 0); + if (!host_ver->name) { + return -EFAULT; } - if (ie->target_cmd == cmd) - break; - ie++; } - arg_type = ie->arg_type; - if (ie->do_ioctl) { - return ie->do_ioctl(ie, buf_temp, fd, cmd, arg); - } else if (!ie->host_cmd) { - /* Some architectures define BSD ioctls in their headers - that are not implemented in Linux. */ - return -TARGET_ENOSYS; + + __get_user(host_ver->date_len, &target_ver->date_len); + if (host_ver->date_len) { + host_ver->date = lock_user(VERIFY_WRITE, target_ver->date, + target_ver->date_len, 0); + if (!host_ver->date) { + goto err; + } } - switch(arg_type[0]) { - case TYPE_NULL: - /* no argument */ - ret = get_errno(safe_ioctl(fd, ie->host_cmd)); - break; - case TYPE_PTRVOID: - case TYPE_INT: - case TYPE_LONG: - case TYPE_ULONG: - ret = get_errno(safe_ioctl(fd, ie->host_cmd, arg)); - break; - case TYPE_PTR: + __get_user(host_ver->desc_len, &target_ver->desc_len); + if (host_ver->desc_len) { + host_ver->desc = lock_user(VERIFY_WRITE, target_ver->desc, + target_ver->desc_len, 0); + if (!host_ver->desc) { + goto err; + } + } + + return 0; +err: + unlock_drm_version(host_ver, target_ver, false); + return -EFAULT; +} + +static inline void host_to_target_drmversion( + struct target_drm_version *target_ver, + struct drm_version *host_ver) +{ + __put_user(host_ver->version_major, &target_ver->version_major); + __put_user(host_ver->version_minor, &target_ver->version_minor); + __put_user(host_ver->version_patchlevel, &target_ver->version_patchlevel); + __put_user(host_ver->name_len, &target_ver->name_len); + __put_user(host_ver->date_len, &target_ver->date_len); + __put_user(host_ver->desc_len, &target_ver->desc_len); + unlock_drm_version(host_ver, target_ver, true); +} + +static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp, + int fd, int cmd, abi_long arg) +{ + struct drm_version *ver; + struct target_drm_version *target_ver; + abi_long ret; + + switch (ie->host_cmd) { + case DRM_IOCTL_VERSION: + if (!lock_user_struct(VERIFY_WRITE, target_ver, arg, 0)) { + return -TARGET_EFAULT; + } + ver = (struct drm_version *)buf_temp; + ret = target_to_host_drmversion(ver, target_ver); + if (!is_error(ret)) { + ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver)); + if (is_error(ret)) { + unlock_drm_version(ver, target_ver, false); + } else { + host_to_target_drmversion(target_ver, ver); + } + } + unlock_user_struct(target_ver, arg, 0); + return ret; + } + return -TARGET_ENOSYS; +} + +static abi_long do_ioctl_drm_i915_getparam(const IOCTLEntry *ie, + struct drm_i915_getparam *gparam, + int fd, abi_long arg) +{ + abi_long ret; + int value; + struct target_drm_i915_getparam *target_gparam; + + if (!lock_user_struct(VERIFY_READ, target_gparam, arg, 0)) { + return -TARGET_EFAULT; + } + + __get_user(gparam->param, &target_gparam->param); + gparam->value = &value; + ret = get_errno(safe_ioctl(fd, ie->host_cmd, gparam)); + put_user_s32(value, target_gparam->value); + + unlock_user_struct(target_gparam, arg, 0); + return ret; +} + +static abi_long do_ioctl_drm_i915(const IOCTLEntry *ie, uint8_t *buf_temp, + int fd, int cmd, abi_long arg) +{ + switch (ie->host_cmd) { + case DRM_IOCTL_I915_GETPARAM: + return do_ioctl_drm_i915_getparam(ie, + (struct drm_i915_getparam *)buf_temp, + fd, arg); + default: + return -TARGET_ENOSYS; + } +} + +#endif + +IOCTLEntry ioctl_entries[] = { +#define IOCTL(cmd, access, ...) \ + { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } }, +#define IOCTL_SPECIAL(cmd, access, dofn, ...) \ + { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } }, +#define IOCTL_IGNORE(cmd) \ + { TARGET_ ## cmd, 0, #cmd }, +#include "ioctls.h" + { 0, 0, }, +}; + +/* ??? Implement proper locking for ioctls. */ +/* do_ioctl() Must return target values and target errnos. */ +static abi_long do_ioctl(int fd, int cmd, abi_long arg) +{ + const IOCTLEntry *ie; + const argtype *arg_type; + abi_long ret; + uint8_t buf_temp[MAX_STRUCT_SIZE]; + int target_size; + void *argptr; + + ie = ioctl_entries; + for(;;) { + if (ie->target_cmd == 0) { + qemu_log_mask( + LOG_UNIMP, "Unsupported ioctl: cmd=0x%04lx\n", (long)cmd); + return -TARGET_ENOSYS; + } + if (ie->target_cmd == cmd) + break; + ie++; + } + arg_type = ie->arg_type; + if (ie->do_ioctl) { + return ie->do_ioctl(ie, buf_temp, fd, cmd, arg); + } else if (!ie->host_cmd) { + /* Some architectures define BSD ioctls in their headers + that are not implemented in Linux. */ + return -TARGET_ENOSYS; + } + + switch(arg_type[0]) { + case TYPE_NULL: + /* no argument */ + ret = get_errno(safe_ioctl(fd, ie->host_cmd)); + break; + case TYPE_PTRVOID: + case TYPE_INT: + case TYPE_LONG: + case TYPE_ULONG: + ret = get_errno(safe_ioctl(fd, ie->host_cmd, arg)); + break; + case TYPE_PTR: arg_type++; target_size = thunk_type_size(arg_type, 0); switch(ie->access) { @@ -5394,6 +5821,7 @@ static const bitmask_transtbl iflag_tbl[] = { { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY }, { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF }, { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL }, + { TARGET_IUTF8, TARGET_IUTF8, IUTF8, IUTF8}, { 0, 0, 0, 0 } }; @@ -5461,22 +5889,23 @@ static const bitmask_transtbl cflag_tbl[] = { }; static const bitmask_transtbl lflag_tbl[] = { - { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG }, - { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON }, - { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE }, - { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO }, - { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE }, - { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK }, - { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL }, - { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH }, - { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP }, - { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL }, - { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT }, - { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE }, - { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO }, - { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN }, - { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN }, - { 0, 0, 0, 0 } + { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG }, + { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON }, + { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE }, + { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO }, + { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE }, + { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK }, + { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL }, + { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH }, + { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP }, + { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL }, + { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT }, + { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE }, + { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO }, + { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN }, + { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN }, + { TARGET_EXTPROC, TARGET_EXTPROC, EXTPROC, EXTPROC}, + { 0, 0, 0, 0 } }; static void target_to_host_termios (void *dst, const void *src) @@ -5553,6 +5982,7 @@ static const StructEntry struct_termios_def = { .convert = { host_to_target_termios, target_to_host_termios }, .size = { sizeof(struct target_termios), sizeof(struct host_termios) }, .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) }, + .print = print_termios, }; static bitmask_transtbl mmap_flags_tbl[] = { @@ -5856,7 +6286,7 @@ static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr) abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr) { - return -ENOSYS; + return -TARGET_ENOSYS; } #else abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr) @@ -6098,6 +6528,9 @@ static int target_to_host_fcntl_cmd(int cmd) case TARGET_F_SETFD: case TARGET_F_GETFL: case TARGET_F_SETFL: + case TARGET_F_OFD_GETLK: + case TARGET_F_OFD_SETLK: + case TARGET_F_OFD_SETLKW: ret = cmd; break; case TARGET_F_GETLK: @@ -6383,6 +6816,7 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) break; case TARGET_F_GETLK64: + case TARGET_F_OFD_GETLK: ret = copy_from_user_flock64(&fl64, arg); if (ret) { return ret; @@ -6394,6 +6828,8 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) break; case TARGET_F_SETLK64: case TARGET_F_SETLKW64: + case TARGET_F_OFD_SETLK: + case TARGET_F_OFD_SETLKW: ret = copy_from_user_flock64(&fl64, arg); if (ret) { return ret; @@ -6438,10 +6874,16 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) break; #endif - case TARGET_F_SETOWN: - case TARGET_F_GETOWN: case TARGET_F_SETSIG: + ret = get_errno(safe_fcntl(fd, host_cmd, target_to_host_signal(arg))); + break; + case TARGET_F_GETSIG: + ret = host_to_target_signal(get_errno(safe_fcntl(fd, host_cmd, arg))); + break; + + case TARGET_F_SETOWN: + case TARGET_F_GETOWN: case TARGET_F_SETLEASE: case TARGET_F_GETLEASE: case TARGET_F_SETPIPE_SZ: @@ -6608,22 +7050,6 @@ void syscall_init(void) } } -#if TARGET_ABI_BITS == 32 -static inline uint64_t target_offset64(uint32_t word0, uint32_t word1) -{ -#ifdef TARGET_WORDS_BIGENDIAN - return ((uint64_t)word0 << 32) | word1; -#else - return ((uint64_t)word1 << 32) | word0; -#endif -} -#else /* TARGET_ABI_BITS == 32 */ -static inline uint64_t target_offset64(uint64_t word0, uint64_t word1) -{ - return word0; -} -#endif /* TARGET_ABI_BITS != 32 */ - #ifdef TARGET_NR_truncate64 static inline abi_long target_truncate64(void *cpu_env, const char *arg1, abi_long arg2, @@ -6654,46 +7080,74 @@ static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1, #if defined(TARGET_NR_timer_settime) || \ (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)) -static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec, +static inline abi_long target_to_host_itimerspec(struct itimerspec *host_its, abi_ulong target_addr) { - struct target_itimerspec *target_itspec; - - if (!lock_user_struct(VERIFY_READ, target_itspec, target_addr, 1)) { + if (target_to_host_timespec(&host_its->it_interval, target_addr + + offsetof(struct target_itimerspec, + it_interval)) || + target_to_host_timespec(&host_its->it_value, target_addr + + offsetof(struct target_itimerspec, + it_value))) { return -TARGET_EFAULT; } - host_itspec->it_interval.tv_sec = - tswapal(target_itspec->it_interval.tv_sec); - host_itspec->it_interval.tv_nsec = - tswapal(target_itspec->it_interval.tv_nsec); - host_itspec->it_value.tv_sec = tswapal(target_itspec->it_value.tv_sec); - host_itspec->it_value.tv_nsec = tswapal(target_itspec->it_value.tv_nsec); + return 0; +} +#endif + +#if defined(TARGET_NR_timer_settime64) || \ + (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) +static inline abi_long target_to_host_itimerspec64(struct itimerspec *host_its, + abi_ulong target_addr) +{ + if (target_to_host_timespec64(&host_its->it_interval, target_addr + + offsetof(struct target__kernel_itimerspec, + it_interval)) || + target_to_host_timespec64(&host_its->it_value, target_addr + + offsetof(struct target__kernel_itimerspec, + it_value))) { + return -TARGET_EFAULT; + } - unlock_user_struct(target_itspec, target_addr, 1); return 0; } #endif #if ((defined(TARGET_NR_timerfd_gettime) || \ defined(TARGET_NR_timerfd_settime)) && defined(CONFIG_TIMERFD)) || \ - defined(TARGET_NR_timer_gettime) || defined(TARGET_NR_timer_settime) + defined(TARGET_NR_timer_gettime) || defined(TARGET_NR_timer_settime) static inline abi_long host_to_target_itimerspec(abi_ulong target_addr, - struct itimerspec *host_its) -{ - struct target_itimerspec *target_itspec; - - if (!lock_user_struct(VERIFY_WRITE, target_itspec, target_addr, 0)) { + struct itimerspec *host_its) +{ + if (host_to_target_timespec(target_addr + offsetof(struct target_itimerspec, + it_interval), + &host_its->it_interval) || + host_to_target_timespec(target_addr + offsetof(struct target_itimerspec, + it_value), + &host_its->it_value)) { return -TARGET_EFAULT; } + return 0; +} +#endif - target_itspec->it_interval.tv_sec = tswapal(host_its->it_interval.tv_sec); - target_itspec->it_interval.tv_nsec = tswapal(host_its->it_interval.tv_nsec); - - target_itspec->it_value.tv_sec = tswapal(host_its->it_value.tv_sec); - target_itspec->it_value.tv_nsec = tswapal(host_its->it_value.tv_nsec); - - unlock_user_struct(target_itspec, target_addr, 0); +#if ((defined(TARGET_NR_timerfd_gettime64) || \ + defined(TARGET_NR_timerfd_settime64)) && defined(CONFIG_TIMERFD)) || \ + defined(TARGET_NR_timer_gettime64) || defined(TARGET_NR_timer_settime64) +static inline abi_long host_to_target_itimerspec64(abi_ulong target_addr, + struct itimerspec *host_its) +{ + if (host_to_target_timespec64(target_addr + + offsetof(struct target__kernel_itimerspec, + it_interval), + &host_its->it_interval) || + host_to_target_timespec64(target_addr + + offsetof(struct target__kernel_itimerspec, + it_value), + &host_its->it_value)) { + return -TARGET_EFAULT; + } return 0; } #endif @@ -6771,6 +7225,87 @@ static inline abi_long host_to_target_timex(abi_long target_addr, } #endif + +#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME) +static inline abi_long target_to_host_timex64(struct timex *host_tx, + abi_long target_addr) +{ + struct target__kernel_timex *target_tx; + + if (copy_from_user_timeval64(&host_tx->time, target_addr + + offsetof(struct target__kernel_timex, + time))) { + return -TARGET_EFAULT; + } + + if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) { + return -TARGET_EFAULT; + } + + __get_user(host_tx->modes, &target_tx->modes); + __get_user(host_tx->offset, &target_tx->offset); + __get_user(host_tx->freq, &target_tx->freq); + __get_user(host_tx->maxerror, &target_tx->maxerror); + __get_user(host_tx->esterror, &target_tx->esterror); + __get_user(host_tx->status, &target_tx->status); + __get_user(host_tx->constant, &target_tx->constant); + __get_user(host_tx->precision, &target_tx->precision); + __get_user(host_tx->tolerance, &target_tx->tolerance); + __get_user(host_tx->tick, &target_tx->tick); + __get_user(host_tx->ppsfreq, &target_tx->ppsfreq); + __get_user(host_tx->jitter, &target_tx->jitter); + __get_user(host_tx->shift, &target_tx->shift); + __get_user(host_tx->stabil, &target_tx->stabil); + __get_user(host_tx->jitcnt, &target_tx->jitcnt); + __get_user(host_tx->calcnt, &target_tx->calcnt); + __get_user(host_tx->errcnt, &target_tx->errcnt); + __get_user(host_tx->stbcnt, &target_tx->stbcnt); + __get_user(host_tx->tai, &target_tx->tai); + + unlock_user_struct(target_tx, target_addr, 0); + return 0; +} + +static inline abi_long host_to_target_timex64(abi_long target_addr, + struct timex *host_tx) +{ + struct target__kernel_timex *target_tx; + + if (copy_to_user_timeval64(target_addr + + offsetof(struct target__kernel_timex, time), + &host_tx->time)) { + return -TARGET_EFAULT; + } + + if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) { + return -TARGET_EFAULT; + } + + __put_user(host_tx->modes, &target_tx->modes); + __put_user(host_tx->offset, &target_tx->offset); + __put_user(host_tx->freq, &target_tx->freq); + __put_user(host_tx->maxerror, &target_tx->maxerror); + __put_user(host_tx->esterror, &target_tx->esterror); + __put_user(host_tx->status, &target_tx->status); + __put_user(host_tx->constant, &target_tx->constant); + __put_user(host_tx->precision, &target_tx->precision); + __put_user(host_tx->tolerance, &target_tx->tolerance); + __put_user(host_tx->tick, &target_tx->tick); + __put_user(host_tx->ppsfreq, &target_tx->ppsfreq); + __put_user(host_tx->jitter, &target_tx->jitter); + __put_user(host_tx->shift, &target_tx->shift); + __put_user(host_tx->stabil, &target_tx->stabil); + __put_user(host_tx->jitcnt, &target_tx->jitcnt); + __put_user(host_tx->calcnt, &target_tx->calcnt); + __put_user(host_tx->errcnt, &target_tx->errcnt); + __put_user(host_tx->stbcnt, &target_tx->stbcnt); + __put_user(host_tx->tai, &target_tx->tai); + + unlock_user_struct(target_tx, target_addr, 1); + return 0; +} +#endif + static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp, abi_ulong target_addr) { @@ -6802,12 +7337,18 @@ static inline int target_to_host_mlockall_arg(int arg) { int result = 0; - if (arg & TARGET_MLOCKALL_MCL_CURRENT) { + if (arg & TARGET_MCL_CURRENT) { result |= MCL_CURRENT; } - if (arg & TARGET_MLOCKALL_MCL_FUTURE) { + if (arg & TARGET_MCL_FUTURE) { result |= MCL_FUTURE; } +#ifdef MCL_ONFAULT + if (arg & TARGET_MCL_ONFAULT) { + result |= MCL_ONFAULT; + } +#endif + return result; } #endif @@ -7051,7 +7592,9 @@ static int do_futex_time64(target_ulong uaddr, int op, int val, target_ulong tim case FUTEX_WAIT_BITSET: if (timeout) { pts = &ts; - target_to_host_timespec64(pts, timeout); + if (target_to_host_timespec64(pts, timeout)) { + return -TARGET_EFAULT; + } } else { pts = NULL; } @@ -7378,7 +7921,7 @@ static int is_proc_myself(const char *filename, const char *entry) } #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) || \ - defined(TARGET_SPARC) || defined(TARGET_M68K) + defined(TARGET_SPARC) || defined(TARGET_M68K) || defined(TARGET_HPPA) static int is_proc(const char *filename, const char *entry) { return strcmp(filename, entry) == 0; @@ -7438,6 +7981,18 @@ static int open_cpuinfo(void *cpu_env, int fd) } #endif +#if defined(TARGET_HPPA) +static int open_cpuinfo(void *cpu_env, int fd) +{ + dprintf(fd, "cpu family\t: PA-RISC 1.1e\n"); + dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n"); + dprintf(fd, "capabilities\t: os32\n"); + dprintf(fd, "model\t\t: 9000/778/B160L\n"); + dprintf(fd, "model name\t: Merlin L2 160 QEMU (9000/778/B160L)\n"); + return 0; +} +#endif + #if defined(TARGET_M68K) static int open_hardware(void *cpu_env, int fd) { @@ -7462,7 +8017,7 @@ static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) { "/proc/net/route", open_net_route, is_proc }, #endif -#if defined(TARGET_SPARC) +#if defined(TARGET_SPARC) || defined(TARGET_HPPA) { "/proc/cpuinfo", open_cpuinfo, is_proc }, #endif #if defined(TARGET_M68K) @@ -7627,7 +8182,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, switch(num) { case TARGET_NR_exit: /* In old applications this may be used to implement _exit(2). - However in threaded applictions it is used for thread termination, + However in threaded applications it is used for thread termination, and _exit_group is used for application termination. Do thread termination if we have more then one thread. */ @@ -7635,30 +8190,33 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return -TARGET_ERESTARTSYS; } - cpu_list_lock(); + pthread_mutex_lock(&clone_lock); if (CPU_NEXT(first_cpu)) { - TaskState *ts; + TaskState *ts = cpu->opaque; - /* Remove the CPU from the list. */ - QTAILQ_REMOVE_RCU(&cpus, cpu, node); + object_property_set_bool(OBJECT(cpu), "realized", false, NULL); + object_unref(OBJECT(cpu)); + /* + * At this point the CPU should be unrealized and removed + * from cpu lists. We can clean-up the rest of the thread + * data without the lock held. + */ - cpu_list_unlock(); + pthread_mutex_unlock(&clone_lock); - ts = cpu->opaque; if (ts->child_tidptr) { put_user_u32(0, ts->child_tidptr); do_sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX, NULL, NULL, 0); } thread_cpu = NULL; - object_unref(OBJECT(cpu)); g_free(ts); rcu_unregister_thread(); pthread_exit(NULL); } - cpu_list_unlock(); + pthread_mutex_unlock(&clone_lock); preexit_cleanup(cpu_env, arg1); _exit(arg1); return 0; /* avoid warning */ @@ -8028,8 +8586,13 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } } return ret; -#ifdef TARGET_NR_umount +#if defined(TARGET_NR_umount) || defined(TARGET_NR_oldumount) +#if defined(TARGET_NR_umount) case TARGET_NR_umount: +#endif +#if defined(TARGET_NR_oldumount) + case TARGET_NR_oldumount: +#endif if (!(p = lock_user_string(arg1))) return -TARGET_EFAULT; ret = get_errno(umount(p)); @@ -8712,7 +9275,9 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, unlock_user(p, arg1, 0); if (arg3) { puts = &uts; - target_to_host_timespec(puts, arg3); + if (target_to_host_timespec(puts, arg3)) { + return -TARGET_EFAULT; + } } else { puts = NULL; } @@ -8733,39 +9298,81 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif - case TARGET_NR_rt_sigqueueinfo: +#ifdef TARGET_NR_rt_sigtimedwait_time64 + case TARGET_NR_rt_sigtimedwait_time64: { + sigset_t set; + struct timespec uts, *puts; siginfo_t uinfo; - p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1); - if (!p) { - return -TARGET_EFAULT; + if (arg4 != sizeof(target_sigset_t)) { + return -TARGET_EINVAL; } - target_to_host_siginfo(&uinfo, p); - unlock_user(p, arg3, 0); - ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo)); - } - return ret; - case TARGET_NR_rt_tgsigqueueinfo: - { - siginfo_t uinfo; - p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1); + p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1); if (!p) { return -TARGET_EFAULT; } - target_to_host_siginfo(&uinfo, p); - unlock_user(p, arg4, 0); - ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo)); - } - return ret; -#ifdef TARGET_NR_sigreturn - case TARGET_NR_sigreturn: - if (block_signals()) { - return -TARGET_ERESTARTSYS; - } - return do_sigreturn(cpu_env); -#endif + target_to_host_sigset(&set, p); + unlock_user(p, arg1, 0); + if (arg3) { + puts = &uts; + if (target_to_host_timespec64(puts, arg3)) { + return -TARGET_EFAULT; + } + } else { + puts = NULL; + } + ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts, + SIGSET_T_SIZE)); + if (!is_error(ret)) { + if (arg2) { + p = lock_user(VERIFY_WRITE, arg2, + sizeof(target_siginfo_t), 0); + if (!p) { + return -TARGET_EFAULT; + } + host_to_target_siginfo(p, &uinfo); + unlock_user(p, arg2, sizeof(target_siginfo_t)); + } + ret = host_to_target_signal(ret); + } + } + return ret; +#endif + case TARGET_NR_rt_sigqueueinfo: + { + siginfo_t uinfo; + + p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1); + if (!p) { + return -TARGET_EFAULT; + } + target_to_host_siginfo(&uinfo, p); + unlock_user(p, arg3, 0); + ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo)); + } + return ret; + case TARGET_NR_rt_tgsigqueueinfo: + { + siginfo_t uinfo; + + p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1); + if (!p) { + return -TARGET_EFAULT; + } + target_to_host_siginfo(&uinfo, p); + unlock_user(p, arg4, 0); + ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo)); + } + return ret; +#ifdef TARGET_NR_sigreturn + case TARGET_NR_sigreturn: + if (block_signals()) { + return -TARGET_ERESTARTSYS; + } + return do_sigreturn(cpu_env); +#endif case TARGET_NR_rt_sigreturn: if (block_signals()) { return -TARGET_ERESTARTSYS; @@ -8889,106 +9496,11 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_pselect6 case TARGET_NR_pselect6: - { - abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr; - fd_set rfds, wfds, efds; - fd_set *rfds_ptr, *wfds_ptr, *efds_ptr; - struct timespec ts, *ts_ptr; - - /* - * The 6th arg is actually two args smashed together, - * so we cannot use the C library. - */ - sigset_t set; - struct { - sigset_t *set; - size_t size; - } sig, *sig_ptr; - - abi_ulong arg_sigset, arg_sigsize, *arg7; - target_sigset_t *target_sigset; - - n = arg1; - rfd_addr = arg2; - wfd_addr = arg3; - efd_addr = arg4; - ts_addr = arg5; - - ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n); - if (ret) { - return ret; - } - ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n); - if (ret) { - return ret; - } - ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n); - if (ret) { - return ret; - } - - /* - * This takes a timespec, and not a timeval, so we cannot - * use the do_select() helper ... - */ - if (ts_addr) { - if (target_to_host_timespec(&ts, ts_addr)) { - return -TARGET_EFAULT; - } - ts_ptr = &ts; - } else { - ts_ptr = NULL; - } - - /* Extract the two packed args for the sigset */ - if (arg6) { - sig_ptr = &sig; - sig.size = SIGSET_T_SIZE; - - arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1); - if (!arg7) { - return -TARGET_EFAULT; - } - arg_sigset = tswapal(arg7[0]); - arg_sigsize = tswapal(arg7[1]); - unlock_user(arg7, arg6, 0); - - if (arg_sigset) { - sig.set = &set; - if (arg_sigsize != sizeof(*target_sigset)) { - /* Like the kernel, we enforce correct size sigsets */ - return -TARGET_EINVAL; - } - target_sigset = lock_user(VERIFY_READ, arg_sigset, - sizeof(*target_sigset), 1); - if (!target_sigset) { - return -TARGET_EFAULT; - } - target_to_host_sigset(&set, target_sigset); - unlock_user(target_sigset, arg_sigset, 0); - } else { - sig.set = NULL; - } - } else { - sig_ptr = NULL; - } - - ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr, - ts_ptr, sig_ptr)); - - if (!is_error(ret)) { - if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) - return -TARGET_EFAULT; - if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) - return -TARGET_EFAULT; - if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) - return -TARGET_EFAULT; - - if (ts_addr && host_to_target_timespec(ts_addr, &ts)) - return -TARGET_EFAULT; - } - } - return ret; + return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, false); +#endif +#ifdef TARGET_NR_pselect6_time64 + case TARGET_NR_pselect6_time64: + return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, true); #endif #ifdef TARGET_NR_symlink case TARGET_NR_symlink: @@ -9277,6 +9789,11 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]); __put_user(stfs.f_namelen, &target_stfs->f_namelen); __put_user(stfs.f_frsize, &target_stfs->f_frsize); +#ifdef _STATFS_F_FLAGS + __put_user(stfs.f_flags, &target_stfs->f_flags); +#else + __put_user(0, &target_stfs->f_flags); +#endif memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare)); unlock_user_struct(target_stfs, arg3, 1); } @@ -9594,7 +10111,15 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_semop case TARGET_NR_semop: - return do_semop(arg1, arg2, arg3); + return do_semtimedop(arg1, arg2, arg3, 0, false); +#endif +#ifdef TARGET_NR_semtimedop + case TARGET_NR_semtimedop: + return do_semtimedop(arg1, arg2, arg3, arg4, false); +#endif +#ifdef TARGET_NR_semtimedop_time64 + case TARGET_NR_semtimedop_time64: + return do_semtimedop(arg1, arg2, arg3, arg4, true); #endif #ifdef TARGET_NR_semctl case TARGET_NR_semctl: @@ -9726,6 +10251,21 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } } return ret; +#endif +#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME) + case TARGET_NR_clock_adjtime64: + { + struct timex htx; + + if (target_to_host_timex64(&htx, arg2) != 0) { + return -TARGET_EFAULT; + } + ret = get_errno(clock_adjtime(arg1, &htx)); + if (!is_error(ret) && host_to_target_timex64(arg2, &htx)) { + return -TARGET_EFAULT; + } + } + return ret; #endif case TARGET_NR_getpgid: return get_errno(getpgid(arg1)); @@ -9916,114 +10456,17 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, case TARGET_NR__newselect: return do_select(arg1, arg2, arg3, arg4, arg5); #endif -#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll) -# ifdef TARGET_NR_poll +#ifdef TARGET_NR_poll case TARGET_NR_poll: -# endif -# ifdef TARGET_NR_ppoll + return do_ppoll(arg1, arg2, arg3, arg4, arg5, false, false); +#endif +#ifdef TARGET_NR_ppoll case TARGET_NR_ppoll: -# endif - { - struct target_pollfd *target_pfd; - unsigned int nfds = arg2; - struct pollfd *pfd; - unsigned int i; - - pfd = NULL; - target_pfd = NULL; - if (nfds) { - if (nfds > (INT_MAX / sizeof(struct target_pollfd))) { - return -TARGET_EINVAL; - } - - target_pfd = lock_user(VERIFY_WRITE, arg1, - sizeof(struct target_pollfd) * nfds, 1); - if (!target_pfd) { - return -TARGET_EFAULT; - } - - pfd = alloca(sizeof(struct pollfd) * nfds); - for (i = 0; i < nfds; i++) { - pfd[i].fd = tswap32(target_pfd[i].fd); - pfd[i].events = tswap16(target_pfd[i].events); - } - } - - switch (num) { -# ifdef TARGET_NR_ppoll - case TARGET_NR_ppoll: - { - struct timespec _timeout_ts, *timeout_ts = &_timeout_ts; - target_sigset_t *target_set; - sigset_t _set, *set = &_set; - - if (arg3) { - if (target_to_host_timespec(timeout_ts, arg3)) { - unlock_user(target_pfd, arg1, 0); - return -TARGET_EFAULT; - } - } else { - timeout_ts = NULL; - } - - if (arg4) { - if (arg5 != sizeof(target_sigset_t)) { - unlock_user(target_pfd, arg1, 0); - return -TARGET_EINVAL; - } - - target_set = lock_user(VERIFY_READ, arg4, sizeof(target_sigset_t), 1); - if (!target_set) { - unlock_user(target_pfd, arg1, 0); - return -TARGET_EFAULT; - } - target_to_host_sigset(set, target_set); - } else { - set = NULL; - } - - ret = get_errno(safe_ppoll(pfd, nfds, timeout_ts, - set, SIGSET_T_SIZE)); - - if (!is_error(ret) && arg3) { - host_to_target_timespec(arg3, timeout_ts); - } - if (arg4) { - unlock_user(target_set, arg4, 0); - } - break; - } -# endif -# ifdef TARGET_NR_poll - case TARGET_NR_poll: - { - struct timespec ts, *pts; - - if (arg3 >= 0) { - /* Convert ms to secs, ns */ - ts.tv_sec = arg3 / 1000; - ts.tv_nsec = (arg3 % 1000) * 1000000LL; - pts = &ts; - } else { - /* -ve poll() timeout means "infinite" */ - pts = NULL; - } - ret = get_errno(safe_ppoll(pfd, nfds, pts, NULL, 0)); - break; - } -# endif - default: - g_assert_not_reached(); - } - - if (!is_error(ret)) { - for(i = 0; i < nfds; i++) { - target_pfd[i].revents = tswap16(pfd[i].revents); - } - } - unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds); - } - return ret; + return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, false); +#endif +#ifdef TARGET_NR_ppoll_time64 + case TARGET_NR_ppoll_time64: + return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, true); #endif case TARGET_NR_flock: /* NOTE: the flock constant seems to be the same for every @@ -10088,12 +10531,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */ case TARGET_NR_fdatasync: return get_errno(fdatasync(arg1)); -#endif -#ifdef TARGET_NR__sysctl - case TARGET_NR__sysctl: - /* We don't implement this, but ENOTDIR is always a safe - return value. */ - return -TARGET_ENOTDIR; #endif case TARGET_NR_sched_getaffinity: { @@ -10237,6 +10674,17 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif +#ifdef TARGET_NR_sched_rr_get_interval_time64 + case TARGET_NR_sched_rr_get_interval_time64: + { + struct timespec ts; + ret = get_errno(sched_rr_get_interval(arg1, &ts)); + if (!is_error(ret)) { + ret = host_to_target_timespec64(arg2, &ts); + } + } + return ret; +#endif #if defined(TARGET_NR_nanosleep) case TARGET_NR_nanosleep: { @@ -10256,7 +10704,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, int deathsig; ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5)); if (!is_error(ret) && arg2 - && put_user_ual(deathsig, arg2)) { + && put_user_s32(deathsig, arg2)) { return -TARGET_EFAULT; } return ret; @@ -11664,23 +12112,55 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return ret; } #endif +#ifdef TARGET_NR_clock_getres_time64 + case TARGET_NR_clock_getres_time64: + { + struct timespec ts; + ret = get_errno(clock_getres(arg1, &ts)); + if (!is_error(ret)) { + host_to_target_timespec64(arg2, &ts); + } + return ret; + } +#endif #ifdef TARGET_NR_clock_nanosleep case TARGET_NR_clock_nanosleep: { struct timespec ts; - target_to_host_timespec(&ts, arg3); + if (target_to_host_timespec(&ts, arg3)) { + return -TARGET_EFAULT; + } ret = get_errno(safe_clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL)); - if (arg4) - host_to_target_timespec(arg4, &ts); - -#if defined(TARGET_PPC) - /* clock_nanosleep is odd in that it returns positive errno values. - * On PPC, CR0 bit 3 should be set in such a situation. */ - if (ret && ret != -TARGET_ERESTARTSYS) { - ((CPUPPCState *)cpu_env)->crf[0] |= 1; + /* + * if the call is interrupted by a signal handler, it fails + * with error -TARGET_EINTR and if arg4 is not NULL and arg2 is not + * TIMER_ABSTIME, it returns the remaining unslept time in arg4. + */ + if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME && + host_to_target_timespec(arg4, &ts)) { + return -TARGET_EFAULT; } + + return ret; + } #endif +#ifdef TARGET_NR_clock_nanosleep_time64 + case TARGET_NR_clock_nanosleep_time64: + { + struct timespec ts; + + if (target_to_host_timespec64(&ts, arg3)) { + return -TARGET_EFAULT; + } + + ret = get_errno(safe_clock_nanosleep(arg1, arg2, + &ts, arg4 ? &ts : NULL)); + + if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME && + host_to_target_timespec64(arg4, &ts)) { + return -TARGET_EFAULT; + } return ret; } #endif @@ -11722,8 +12202,13 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, if (!arg3) { tsp = NULL; } else { - target_to_host_timespec(ts, arg3); - target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec)); + if (target_to_host_timespec(ts, arg3)) { + return -TARGET_EFAULT; + } + if (target_to_host_timespec(ts + 1, arg3 + + sizeof(struct target_timespec))) { + return -TARGET_EFAULT; + } tsp = ts; } if (!arg2) @@ -11738,6 +12223,35 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif +#ifdef TARGET_NR_utimensat_time64 + case TARGET_NR_utimensat_time64: + { + struct timespec *tsp, ts[2]; + if (!arg3) { + tsp = NULL; + } else { + if (target_to_host_timespec64(ts, arg3)) { + return -TARGET_EFAULT; + } + if (target_to_host_timespec64(ts + 1, arg3 + + sizeof(struct target__kernel_timespec))) { + return -TARGET_EFAULT; + } + tsp = ts; + } + if (!arg2) + ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4)); + else { + p = lock_user_string(arg2); + if (!p) { + return -TARGET_EFAULT; + } + ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4)); + unlock_user(p, arg2, 0); + } + } + return ret; +#endif #ifdef TARGET_NR_futex case TARGET_NR_futex: return do_futex(arg1, arg2, arg3, arg4, arg5, arg6); @@ -11817,9 +12331,13 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, p = lock_user (VERIFY_READ, arg2, arg3, 1); if (arg5 != 0) { - target_to_host_timespec(&ts, arg5); + if (target_to_host_timespec(&ts, arg5)) { + return -TARGET_EFAULT; + } ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts)); - host_to_target_timespec(arg5, &ts); + if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) { + return -TARGET_EFAULT; + } } else { ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL)); } @@ -11827,6 +12345,27 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif +#ifdef TARGET_NR_mq_timedsend_time64 + case TARGET_NR_mq_timedsend_time64: + { + struct timespec ts; + + p = lock_user(VERIFY_READ, arg2, arg3, 1); + if (arg5 != 0) { + if (target_to_host_timespec64(&ts, arg5)) { + return -TARGET_EFAULT; + } + ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts)); + if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) { + return -TARGET_EFAULT; + } + } else { + ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL)); + } + unlock_user(p, arg2, arg3); + } + return ret; +#endif #ifdef TARGET_NR_mq_timedreceive case TARGET_NR_mq_timedreceive: @@ -11836,10 +12375,14 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, p = lock_user (VERIFY_READ, arg2, arg3, 1); if (arg5 != 0) { - target_to_host_timespec(&ts, arg5); + if (target_to_host_timespec(&ts, arg5)) { + return -TARGET_EFAULT; + } ret = get_errno(safe_mq_timedreceive(arg1, p, arg3, &prio, &ts)); - host_to_target_timespec(arg5, &ts); + if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) { + return -TARGET_EFAULT; + } } else { ret = get_errno(safe_mq_timedreceive(arg1, p, arg3, &prio, NULL)); @@ -11850,6 +12393,33 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif +#ifdef TARGET_NR_mq_timedreceive_time64 + case TARGET_NR_mq_timedreceive_time64: + { + struct timespec ts; + unsigned int prio; + + p = lock_user(VERIFY_READ, arg2, arg3, 1); + if (arg5 != 0) { + if (target_to_host_timespec64(&ts, arg5)) { + return -TARGET_EFAULT; + } + ret = get_errno(safe_mq_timedreceive(arg1, p, arg3, + &prio, &ts)); + if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) { + return -TARGET_EFAULT; + } + } else { + ret = get_errno(safe_mq_timedreceive(arg1, p, arg3, + &prio, NULL)); + } + unlock_user(p, arg2, arg3); + if (arg4 != 0) { + put_user_u32(prio, arg4); + } + } + return ret; +#endif /* Not implemented for now... */ /* case TARGET_NR_mq_notify: */ @@ -12020,17 +12590,25 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, struct epoll_event ep; struct epoll_event *epp = 0; if (arg4) { - struct target_epoll_event *target_ep; - if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) { - return -TARGET_EFAULT; + if (arg2 != EPOLL_CTL_DEL) { + struct target_epoll_event *target_ep; + if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) { + return -TARGET_EFAULT; + } + ep.events = tswap32(target_ep->events); + /* + * The epoll_data_t union is just opaque data to the kernel, + * so we transfer all 64 bits across and need not worry what + * actual data type it is. + */ + ep.data.u64 = tswap64(target_ep->data.u64); + unlock_user_struct(target_ep, arg4, 0); } - ep.events = tswap32(target_ep->events); - /* The epoll_data_t union is just opaque data to the kernel, - * so we transfer all 64 bits across and need not worry what - * actual data type it is. + /* + * before kernel 2.6.9, EPOLL_CTL_DEL operation required a + * non-null pointer, even though this argument is ignored. + * */ - ep.data.u64 = tswap64(target_ep->data.u64); - unlock_user_struct(target_ep, arg4, 0); epp = &ep; } return get_errno(epoll_ctl(arg1, arg2, arg3, epp)); @@ -12259,6 +12837,32 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } #endif +#ifdef TARGET_NR_timer_settime64 + case TARGET_NR_timer_settime64: + { + target_timer_t timerid = get_timer_id(arg1); + + if (timerid < 0) { + ret = timerid; + } else if (arg3 == 0) { + ret = -TARGET_EINVAL; + } else { + timer_t htimer = g_posix_timers[timerid]; + struct itimerspec hspec_new = {{0},}, hspec_old = {{0},}; + + if (target_to_host_itimerspec64(&hspec_new, arg3)) { + return -TARGET_EFAULT; + } + ret = get_errno( + timer_settime(htimer, arg2, &hspec_new, &hspec_old)); + if (arg4 && host_to_target_itimerspec64(arg4, &hspec_old)) { + return -TARGET_EFAULT; + } + } + return ret; + } +#endif + #ifdef TARGET_NR_timer_gettime case TARGET_NR_timer_gettime: { @@ -12282,6 +12886,29 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } #endif +#ifdef TARGET_NR_timer_gettime64 + case TARGET_NR_timer_gettime64: + { + /* args: timer_t timerid, struct itimerspec64 *curr_value */ + target_timer_t timerid = get_timer_id(arg1); + + if (timerid < 0) { + ret = timerid; + } else if (!arg2) { + ret = -TARGET_EFAULT; + } else { + timer_t htimer = g_posix_timers[timerid]; + struct itimerspec hspec; + ret = get_errno(timer_gettime(htimer, &hspec)); + + if (host_to_target_itimerspec64(arg2, &hspec)) { + ret = -TARGET_EFAULT; + } + } + return ret; + } +#endif + #ifdef TARGET_NR_timer_getoverrun case TARGET_NR_timer_getoverrun: { @@ -12335,6 +12962,20 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return ret; #endif +#if defined(TARGET_NR_timerfd_gettime64) && defined(CONFIG_TIMERFD) + case TARGET_NR_timerfd_gettime64: + { + struct itimerspec its_curr; + + ret = get_errno(timerfd_gettime(arg1, &its_curr)); + + if (arg2 && host_to_target_itimerspec64(arg2, &its_curr)) { + return -TARGET_EFAULT; + } + } + return ret; +#endif + #if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD) case TARGET_NR_timerfd_settime: { @@ -12358,6 +12999,29 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return ret; #endif +#if defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD) + case TARGET_NR_timerfd_settime64: + { + struct itimerspec its_new, its_old, *p_new; + + if (arg3) { + if (target_to_host_itimerspec64(&its_new, arg3)) { + return -TARGET_EFAULT; + } + p_new = &its_new; + } else { + p_new = NULL; + } + + ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old)); + + if (arg4 && host_to_target_itimerspec64(arg4, &its_old)) { + return -TARGET_EFAULT; + } + } + return ret; +#endif + #if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get) case TARGET_NR_ioprio_get: return get_errno(ioprio_get(arg1, arg2)); @@ -12434,14 +13098,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); if (unlikely(qemu_loglevel_mask(LOG_STRACE))) { - print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); + print_syscall(cpu_env, num, arg1, arg2, arg3, arg4, arg5, arg6); } ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); if (unlikely(qemu_loglevel_mask(LOG_STRACE))) { - print_syscall_ret(num, ret); + print_syscall_ret(cpu_env, num, ret, arg1, arg2, + arg3, arg4, arg5, arg6); } record_syscall_return(cpu, num, ret); diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 152ec637cba6d01b2216bd403c5266820628016f..cabbfb762dd90533e53057208a17bb1d5122181a 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -46,6 +46,8 @@ #define IPCOP_shmget 23 #define IPCOP_shmctl 24 +#define TARGET_SEMOPM 500 + /* * The following is for compatibility across the various Linux * platforms. The i386 ioctl numbering scheme doesn't really enforce @@ -259,6 +261,11 @@ struct target_itimerspec { struct target_timespec it_value; }; +struct target__kernel_itimerspec { + struct target__kernel_timespec it_interval; + struct target__kernel_timespec it_value; +}; + struct target_timex { abi_uint modes; /* Mode selector */ abi_long offset; /* Time offset */ @@ -287,6 +294,37 @@ struct target_timex { abi_int:32; abi_int:32; abi_int:32; }; +struct target__kernel_timex { + abi_uint modes; /* Mode selector */ + abi_int: 32; /* pad */ + abi_llong offset; /* Time offset */ + abi_llong freq; /* Frequency offset */ + abi_llong maxerror; /* Maximum error (microseconds) */ + abi_llong esterror; /* Estimated error (microseconds) */ + abi_int status; /* Clock command/status */ + abi_int: 32; /* pad */ + abi_llong constant; /* PLL (phase-locked loop) time constant */ + abi_llong precision; /* Clock precision (microseconds, ro) */ + abi_llong tolerance; /* Clock freq. tolerance (ppm, ro) */ + struct target__kernel_sock_timeval time; /* Current time */ + abi_llong tick; /* Microseconds between clock ticks */ + abi_llong ppsfreq; /* PPS (pulse per second) frequency */ + abi_llong jitter; /* PPS jitter (ro); nanoseconds */ + abi_int shift; /* PPS interval duration (seconds) */ + abi_int: 32; /* pad */ + abi_llong stabil; /* PPS stability */ + abi_llong jitcnt; /* PPS jitter limit exceeded (ro) */ + abi_llong calcnt; /* PPS calibration intervals */ + abi_llong errcnt; /* PPS calibration errors */ + abi_llong stbcnt; /* PPS stability limit exceeded */ + abi_int tai; /* TAI offset */ + + /* Further padding bytes to allow for future expansion */ + abi_int:32; abi_int:32; abi_int:32; abi_int:32; + abi_int:32; abi_int:32; abi_int:32; abi_int:32; + abi_int:32; abi_int:32; abi_int:32; +}; + typedef abi_long target_clock_t; #define TARGET_HZ 100 @@ -967,6 +1005,45 @@ struct target_rtc_pll_info { #define TARGET_FS_IOC32_GETVERSION TARGET_IOR('v', 1, int) #define TARGET_FS_IOC32_SETVERSION TARGET_IOW('v', 2, int) +/* btrfs ioctls */ +#ifdef CONFIG_BTRFS +#define TARGET_BTRFS_IOC_SNAP_CREATE TARGET_IOWU(BTRFS_IOCTL_MAGIC, 1) +#define TARGET_BTRFS_IOC_SCAN_DEV TARGET_IOWU(BTRFS_IOCTL_MAGIC, 4) +#define TARGET_BTRFS_IOC_FORGET_DEV TARGET_IOWU(BTRFS_IOCTL_MAGIC, 5) +#define TARGET_BTRFS_IOC_ADD_DEV TARGET_IOWU(BTRFS_IOCTL_MAGIC, 10) +#define TARGET_BTRFS_IOC_RM_DEV TARGET_IOWU(BTRFS_IOCTL_MAGIC, 11) +#define TARGET_BTRFS_IOC_SUBVOL_CREATE TARGET_IOWU(BTRFS_IOCTL_MAGIC, 14) +#define TARGET_BTRFS_IOC_SNAP_DESTROY TARGET_IOWU(BTRFS_IOCTL_MAGIC, 15) +#define TARGET_BTRFS_IOC_INO_LOOKUP TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 18) +#define TARGET_BTRFS_IOC_DEFAULT_SUBVOL TARGET_IOW(BTRFS_IOCTL_MAGIC, 19,\ + abi_ullong) +#define TARGET_BTRFS_IOC_SUBVOL_GETFLAGS TARGET_IOR(BTRFS_IOCTL_MAGIC, 25,\ + abi_ullong) +#define TARGET_BTRFS_IOC_SUBVOL_SETFLAGS TARGET_IOW(BTRFS_IOCTL_MAGIC, 26,\ + abi_ullong) +#define TARGET_BTRFS_IOC_SCRUB TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 27) +#define TARGET_BTRFS_IOC_SCRUB_CANCEL TARGET_IO(BTRFS_IOCTL_MAGIC, 28) +#define TARGET_BTRFS_IOC_SCRUB_PROGRESS TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 29) +#define TARGET_BTRFS_IOC_DEV_INFO TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 30) +#define TARGET_BTRFS_IOC_INO_PATHS TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 35) +#define TARGET_BTRFS_IOC_LOGICAL_INO TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 36) +#define TARGET_BTRFS_IOC_QUOTA_CTL TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 40) +#define TARGET_BTRFS_IOC_QGROUP_ASSIGN TARGET_IOWU(BTRFS_IOCTL_MAGIC, 41) +#define TARGET_BTRFS_IOC_QGROUP_CREATE TARGET_IOWU(BTRFS_IOCTL_MAGIC, 42) +#define TARGET_BTRFS_IOC_QGROUP_LIMIT TARGET_IORU(BTRFS_IOCTL_MAGIC, 43) +#define TARGET_BTRFS_IOC_QUOTA_RESCAN TARGET_IOWU(BTRFS_IOCTL_MAGIC, 44) +#define TARGET_BTRFS_IOC_QUOTA_RESCAN_STATUS TARGET_IORU(BTRFS_IOCTL_MAGIC, 45) +#define TARGET_BTRFS_IOC_QUOTA_RESCAN_WAIT TARGET_IO(BTRFS_IOCTL_MAGIC, 46) +#define TARGET_BTRFS_IOC_GET_DEV_STATS TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 52) +#define TARGET_BTRFS_IOC_GET_FEATURES TARGET_IORU(BTRFS_IOCTL_MAGIC, 57) +#define TARGET_BTRFS_IOC_SET_FEATURES TARGET_IOWU(BTRFS_IOCTL_MAGIC, 57) +#define TARGET_BTRFS_IOC_GET_SUPPORTED_FEATURES TARGET_IORU(BTRFS_IOCTL_MAGIC, 57) +#define TARGET_BTRFS_IOC_LOGICAL_INO_V2 TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 59) +#define TARGET_BTRFS_IOC_GET_SUBVOL_INFO TARGET_IORU(BTRFS_IOCTL_MAGIC, 60) +#define TARGET_BTRFS_IOC_GET_SUBVOL_ROOTREF TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 61) +#define TARGET_BTRFS_IOC_INO_LOOKUP_USER TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 62) +#endif + /* usb ioctls */ #define TARGET_USBDEVFS_CONTROL TARGET_IOWRU('U', 0) #define TARGET_USBDEVFS_BULK TARGET_IOWRU('U', 2) @@ -1167,6 +1244,12 @@ struct target_rtc_pll_info { #define TARGET_DM_TARGET_MSG TARGET_IOWRU(0xfd, 0x0e) #define TARGET_DM_DEV_SET_GEOMETRY TARGET_IOWRU(0xfd, 0x0f) +/* drm ioctls */ +#define TARGET_DRM_IOCTL_VERSION TARGET_IOWRU('d', 0x00) + +/* drm i915 ioctls */ +#define TARGET_DRM_IOCTL_I915_GETPARAM TARGET_IOWRU('d', 0x46) + /* from asm/termbits.h */ #define TARGET_NCC 8 @@ -1194,6 +1277,10 @@ struct target_winsize { #define TARGET_PROT_SEM 0x08 #endif +#ifdef TARGET_AARCH64 +#define TARGET_PROT_BTI 0x10 +#endif + /* Common */ #define TARGET_MAP_SHARED 0x01 /* Share changes */ #define TARGET_MAP_PRIVATE 0x02 /* Changes are private */ @@ -2598,6 +2685,23 @@ struct target_mq_attr { abi_long mq_curmsgs; }; +struct target_drm_version { + int version_major; + int version_minor; + int version_patchlevel; + abi_ulong name_len; + abi_ulong name; + abi_ulong date_len; + abi_ulong date; + abi_ulong desc_len; + abi_ulong desc; +}; + +struct target_drm_i915_getparam { + int param; + abi_ulong value; +}; + #include "socket.h" #include "errno_defs.h" diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index 4e12c1661ea61c7617828ecdd8d429a32db63ee3..ba2c1518eb5c7b46727ed2fbdabd5446fb2ec3f0 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -137,10 +137,32 @@ STRUCT(snd_timer_params, TYPE_INT, /* filter */ MK_ARRAY(TYPE_CHAR, 60)) /* reserved */ +#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) +STRUCT(timeval, + TYPE_LONG, /* tv_sec */ + TYPE_INT) /* tv_usec */ + +STRUCT(_kernel_sock_timeval, + TYPE_LONG, /* tv_sec */ + TYPE_INT) /* tv_usec */ +#else +STRUCT(timeval, + TYPE_LONG, /* tv_sec */ + TYPE_LONG) /* tv_usec */ + +STRUCT(_kernel_sock_timeval, + TYPE_LONGLONG, /* tv_sec */ + TYPE_LONGLONG) /* tv_usec */ +#endif + STRUCT(timespec, TYPE_LONG, /* tv_sec */ TYPE_LONG) /* tv_nsec */ +STRUCT(_kernel_timespec, + TYPE_LONGLONG, /* tv_sec */ + TYPE_LONGLONG) /* tv_nsec */ + STRUCT(snd_timer_status, MK_STRUCT(STRUCT_timespec), /* tstamp */ TYPE_INT, /* resolution */ @@ -292,6 +314,21 @@ STRUCT(dm_target_versions, STRUCT(dm_target_msg, TYPE_ULONGLONG) /* sector */ +STRUCT(drm_version, + TYPE_INT, /* version_major */ + TYPE_INT, /* version_minor */ + TYPE_INT, /* version_patchlevel */ + TYPE_ULONG, /* name_len */ + TYPE_PTRVOID, /* name */ + TYPE_ULONG, /* date_len */ + TYPE_PTRVOID, /* date */ + TYPE_ULONG, /* desc_len */ + TYPE_PTRVOID) /* desc */ + +STRUCT(drm_i915_getparam, + TYPE_INT, /* param */ + TYPE_PTRVOID) /* value */ + STRUCT(file_clone_range, TYPE_LONGLONG, /* src_fd */ TYPE_ULONGLONG, /* src_offset */ @@ -321,6 +358,169 @@ STRUCT(blkpg_partition, MK_ARRAY(TYPE_CHAR, BLKPG_DEVNAMELTH), /* devname */ MK_ARRAY(TYPE_CHAR, BLKPG_VOLNAMELTH)) /* volname */ +#if defined(BTRFS_IOC_SUBVOL_CREATE) || defined(BTRFS_IOC_SNAP_CREATE) || \ + defined(BTRFS_IOC_SNAP_DESTROY) || defined(BTRFS_IOC_SCAN_DEV) || \ + defined(BTRFS_IOC_FORGET_DEV) || defined(BTRFS_IOC_ADD_DEV) || \ + defined(BTRFS_IOC_RM_DEV) || defined(BTRFS_IOC_DEV_INFO) +STRUCT(btrfs_ioctl_vol_args, + TYPE_LONGLONG, /* fd */ + MK_ARRAY(TYPE_CHAR, BTRFS_PATH_NAME_MAX + 1)) /* name */ +#endif + +#ifdef BTRFS_IOC_GET_SUBVOL_INFO +STRUCT(btrfs_ioctl_timespec, + TYPE_ULONGLONG, /* sec */ + TYPE_INT) /* nsec */ + +STRUCT(btrfs_ioctl_get_subvol_info_args, + TYPE_ULONGLONG, /* treeid */ + MK_ARRAY(TYPE_CHAR, BTRFS_VOL_NAME_MAX + 1), + TYPE_ULONGLONG, /* parentid */ + TYPE_ULONGLONG, /* dirid */ + TYPE_ULONGLONG, /* generation */ + TYPE_ULONGLONG, /* flags */ + MK_ARRAY(TYPE_CHAR, BTRFS_UUID_SIZE), /* uuid */ + MK_ARRAY(TYPE_CHAR, BTRFS_UUID_SIZE), /* parent_uuid */ + MK_ARRAY(TYPE_CHAR, BTRFS_UUID_SIZE), /* received_uuid */ + TYPE_ULONGLONG, /* ctransid */ + TYPE_ULONGLONG, /* otransid */ + TYPE_ULONGLONG, /* stransid */ + TYPE_ULONGLONG, /* rtransid */ + MK_STRUCT(STRUCT_btrfs_ioctl_timespec), /* ctime */ + MK_STRUCT(STRUCT_btrfs_ioctl_timespec), /* otime */ + MK_STRUCT(STRUCT_btrfs_ioctl_timespec), /* stime */ + MK_STRUCT(STRUCT_btrfs_ioctl_timespec), /* rtime */ + MK_ARRAY(TYPE_ULONGLONG, 8)) /* reserved */ +#endif + +#ifdef BTRFS_IOC_INO_LOOKUP +STRUCT(btrfs_ioctl_ino_lookup_args, + TYPE_ULONGLONG, /* treeid */ + TYPE_ULONGLONG, /* objectid */ + MK_ARRAY(TYPE_CHAR, BTRFS_INO_LOOKUP_PATH_MAX)) /* name */ +#endif + +#ifdef BTRFS_IOC_INO_PATHS +STRUCT(btrfs_ioctl_ino_path_args, + TYPE_ULONGLONG, /* inum */ + TYPE_ULONGLONG, /* size */ + MK_ARRAY(TYPE_ULONGLONG, 4), /* reserved */ + TYPE_ULONGLONG) /* fspath */ +#endif + +#if defined(BTRFS_IOC_LOGICAL_INO) || defined(BTRFS_IOC_LOGICAL_INO_V2) +STRUCT(btrfs_ioctl_logical_ino_args, + TYPE_ULONGLONG, /* logical */ + TYPE_ULONGLONG, /* size */ + MK_ARRAY(TYPE_ULONGLONG, 3), /* reserved */ + TYPE_ULONGLONG, /* flags */ + TYPE_ULONGLONG) /* inodes */ +#endif + +#ifdef BTRFS_IOC_INO_LOOKUP_USER +STRUCT(btrfs_ioctl_ino_lookup_user_args, + TYPE_ULONGLONG, /* dirid */ + TYPE_ULONGLONG, /* treeid */ + MK_ARRAY(TYPE_CHAR, BTRFS_VOL_NAME_MAX + 1), /* name */ + MK_ARRAY(TYPE_CHAR, BTRFS_INO_LOOKUP_USER_PATH_MAX)) /* path */ +#endif + +#if defined(BTRFS_IOC_SCRUB) || defined(BTRFS_IOC_SCRUB_PROGRESS) +STRUCT(btrfs_scrub_progress, + TYPE_ULONGLONG, /* data_extents_scrubbed */ + TYPE_ULONGLONG, /* tree_extents_scrubbed */ + TYPE_ULONGLONG, /* data_bytes_scrubbed */ + TYPE_ULONGLONG, /* tree_bytes_scrubbed */ + TYPE_ULONGLONG, /* read_errors */ + TYPE_ULONGLONG, /* csum_errors */ + TYPE_ULONGLONG, /* verify_errors */ + TYPE_ULONGLONG, /* no_csum */ + TYPE_ULONGLONG, /* csum_discards */ + TYPE_ULONGLONG, /* super_errors */ + TYPE_ULONGLONG, /* malloc_errors */ + TYPE_ULONGLONG, /* uncorrectable_errors */ + TYPE_ULONGLONG, /* corrected_er */ + TYPE_ULONGLONG, /* last_physical */ + TYPE_ULONGLONG) /* unverified_errors */ + +STRUCT(btrfs_ioctl_scrub_args, + TYPE_ULONGLONG, /* devid */ + TYPE_ULONGLONG, /* start */ + TYPE_ULONGLONG, /* end */ + TYPE_ULONGLONG, /* flags */ + MK_STRUCT(STRUCT_btrfs_scrub_progress), /* progress */ + MK_ARRAY(TYPE_ULONGLONG, + (1024 - 32 - + sizeof(struct btrfs_scrub_progress)) / 8)) /* unused */ +#endif + +#ifdef BTRFS_IOC_DEV_INFO +STRUCT(btrfs_ioctl_dev_info_args, + TYPE_ULONGLONG, /* devid */ + MK_ARRAY(TYPE_CHAR, BTRFS_UUID_SIZE), /* uuid */ + TYPE_ULONGLONG, /* bytes_used */ + TYPE_ULONGLONG, /* total_bytes */ + MK_ARRAY(TYPE_ULONGLONG, 379), /* unused */ + MK_ARRAY(TYPE_CHAR, BTRFS_DEVICE_PATH_NAME_MAX)) /* path */ +#endif + +#ifdef BTRFS_IOC_GET_SUBVOL_ROOTREF +STRUCT(rootref, + TYPE_ULONGLONG, /* treeid */ + TYPE_ULONGLONG) /* dirid */ + +STRUCT(btrfs_ioctl_get_subvol_rootref_args, + TYPE_ULONGLONG, /* min_treeid */ + MK_ARRAY(MK_STRUCT(STRUCT_rootref), + BTRFS_MAX_ROOTREF_BUFFER_NUM), /* rootref */ + TYPE_CHAR, /* num_items */ + MK_ARRAY(TYPE_CHAR, 7)) /* align */ +#endif + +#ifdef BTRFS_IOC_GET_DEV_STATS +STRUCT(btrfs_ioctl_get_dev_stats, + TYPE_ULONGLONG, /* devid */ + TYPE_ULONGLONG, /* nr_items */ + TYPE_ULONGLONG, /* flags */ + MK_ARRAY(TYPE_ULONGLONG, BTRFS_DEV_STAT_VALUES_MAX), /* values */ + MK_ARRAY(TYPE_ULONGLONG, + 128 - 2 - BTRFS_DEV_STAT_VALUES_MAX)) /* unused */ +#endif + +STRUCT(btrfs_ioctl_quota_ctl_args, + TYPE_ULONGLONG, /* cmd */ + TYPE_ULONGLONG) /* status */ + +STRUCT(btrfs_ioctl_quota_rescan_args, + TYPE_ULONGLONG, /* flags */ + TYPE_ULONGLONG, /* progress */ + MK_ARRAY(TYPE_ULONGLONG, 6)) /* reserved */ + +STRUCT(btrfs_ioctl_qgroup_assign_args, + TYPE_ULONGLONG, /* assign */ + TYPE_ULONGLONG, /* src */ + TYPE_ULONGLONG) /* dst */ + +STRUCT(btrfs_ioctl_qgroup_create_args, + TYPE_ULONGLONG, /* create */ + TYPE_ULONGLONG) /* qgroupid */ + +STRUCT(btrfs_qgroup_limit, + TYPE_ULONGLONG, /* flags */ + TYPE_ULONGLONG, /* max_rfer */ + TYPE_ULONGLONG, /* max_excl */ + TYPE_ULONGLONG, /* rsv_rfer */ + TYPE_ULONGLONG) /* rsv_excl */ + +STRUCT(btrfs_ioctl_qgroup_limit_args, + TYPE_ULONGLONG, /* qgroupid */ + MK_STRUCT(STRUCT_btrfs_qgroup_limit)) /* lim */ + +STRUCT(btrfs_ioctl_feature_flags, + TYPE_ULONGLONG, /* compat_flags */ + TYPE_ULONGLONG, /* compat_ro_flags */ + TYPE_ULONGLONG) /* incompat_flags */ + STRUCT(rtc_time, TYPE_INT, /* tm_sec */ TYPE_INT, /* tm_min */ diff --git a/linux-user/tilegx/target_cpu.h b/linux-user/tilegx/target_cpu.h index 316b7a639c3d557343d57c03ff21b39f3162c980..5fa9e2a9a403c06eb88ebfb3d1d1799e14df8b23 100644 --- a/linux-user/tilegx/target_cpu.h +++ b/linux-user/tilegx/target_cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/tilegx/target_structs.h b/linux-user/tilegx/target_structs.h index de8b1f2f458d155fcde2612dff8b793a256197c4..1df000cc96b7f7dd111aec3b1b38ac940de721e0 100644 --- a/linux-user/tilegx/target_structs.h +++ b/linux-user/tilegx/target_structs.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/tilegx/target_syscall.h b/linux-user/tilegx/target_syscall.h index d731acdafaa08cc0a896d3187fcb1b459765b8e4..8e9db734b88b7c2c5d2b98ea8f9d19f93c25421b 100644 --- a/linux-user/tilegx/target_syscall.h +++ b/linux-user/tilegx/target_syscall.h @@ -34,8 +34,9 @@ struct target_pt_regs { tilegx_reg_t pad[2]; }; -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 /* For faultnum */ #define TARGET_INT_SWINT_1 14 diff --git a/linux-user/tilegx/termbits.h b/linux-user/tilegx/termbits.h index 966daec0880f1f3dea7685a3a42f87268c02b930..b1d4f4fedbcb9ab2ca1184280eb4a9e5b8a9d735 100644 --- a/linux-user/tilegx/termbits.h +++ b/linux-user/tilegx/termbits.h @@ -1,275 +1 @@ -#ifndef TILEGX_TERMBITS_H -#define TILEGX_TERMBITS_H - -/* From asm-generic/termbits.h, which is used by tilegx */ - -#define TARGET_NCCS 19 -struct target_termios { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ -}; - -struct target_termios2 { - unsigned int c_iflag; /* input mode flags */ - unsigned int c_oflag; /* output mode flags */ - unsigned int c_cflag; /* control mode flags */ - unsigned int c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[TARGET_NCCS]; /* control characters */ - unsigned int c_ispeed; /* input speed */ - unsigned int c_ospeed; /* output speed */ -}; - -/* c_cc characters */ -#define TARGET_VINTR 0 -#define TARGET_VQUIT 1 -#define TARGET_VERASE 2 -#define TARGET_VKILL 3 -#define TARGET_VEOF 4 -#define TARGET_VTIME 5 -#define TARGET_VMIN 6 -#define TARGET_VSWTC 7 -#define TARGET_VSTART 8 -#define TARGET_VSTOP 9 -#define TARGET_VSUSP 10 -#define TARGET_VEOL 11 -#define TARGET_VREPRINT 12 -#define TARGET_VDISCARD 13 -#define TARGET_VWERASE 14 -#define TARGET_VLNEXT 15 -#define TARGET_VEOL2 16 - -/* c_iflag bits */ -#define TARGET_IGNBRK 0000001 -#define TARGET_BRKINT 0000002 -#define TARGET_IGNPAR 0000004 -#define TARGET_PARMRK 0000010 -#define TARGET_INPCK 0000020 -#define TARGET_ISTRIP 0000040 -#define TARGET_INLCR 0000100 -#define TARGET_IGNCR 0000200 -#define TARGET_ICRNL 0000400 -#define TARGET_IUCLC 0001000 -#define TARGET_IXON 0002000 -#define TARGET_IXANY 0004000 -#define TARGET_IXOFF 0010000 -#define TARGET_IMAXBEL 0020000 -#define TARGET_IUTF8 0040000 - -/* c_oflag bits */ -#define TARGET_OPOST 0000001 -#define TARGET_OLCUC 0000002 -#define TARGET_ONLCR 0000004 -#define TARGET_OCRNL 0000010 -#define TARGET_ONOCR 0000020 -#define TARGET_ONLRET 0000040 -#define TARGET_OFILL 0000100 -#define TARGET_OFDEL 0000200 -#define TARGET_NLDLY 0000400 -#define TARGET_NL0 0000000 -#define TARGET_NL1 0000400 -#define TARGET_CRDLY 0003000 -#define TARGET_CR0 0000000 -#define TARGET_CR1 0001000 -#define TARGET_CR2 0002000 -#define TARGET_CR3 0003000 -#define TARGET_TABDLY 0014000 -#define TARGET_TAB0 0000000 -#define TARGET_TAB1 0004000 -#define TARGET_TAB2 0010000 -#define TARGET_TAB3 0014000 -#define TARGET_XTABS 0014000 -#define TARGET_BSDLY 0020000 -#define TARGET_BS0 0000000 -#define TARGET_BS1 0020000 -#define TARGET_VTDLY 0040000 -#define TARGET_VT0 0000000 -#define TARGET_VT1 0040000 -#define TARGET_FFDLY 0100000 -#define TARGET_FF0 0000000 -#define TARGET_FF1 0100000 - -/* c_cflag bit meaning */ -#define TARGET_CBAUD 0010017 -#define TARGET_B0 0000000 /* hang up */ -#define TARGET_B50 0000001 -#define TARGET_B75 0000002 -#define TARGET_B110 0000003 -#define TARGET_B134 0000004 -#define TARGET_B150 0000005 -#define TARGET_B200 0000006 -#define TARGET_B300 0000007 -#define TARGET_B600 0000010 -#define TARGET_B1200 0000011 -#define TARGET_B1800 0000012 -#define TARGET_B2400 0000013 -#define TARGET_B4800 0000014 -#define TARGET_B9600 0000015 -#define TARGET_B19200 0000016 -#define TARGET_B38400 0000017 -#define TARGET_EXTA TARGET_B19200 -#define TARGET_EXTB TARGET_B38400 -#define TARGET_CSIZE 0000060 -#define TARGET_CS5 0000000 -#define TARGET_CS6 0000020 -#define TARGET_CS7 0000040 -#define TARGET_CS8 0000060 -#define TARGET_CSTOPB 0000100 -#define TARGET_CREAD 0000200 -#define TARGET_PARENB 0000400 -#define TARGET_PARODD 0001000 -#define TARGET_HUPCL 0002000 -#define TARGET_CLOCAL 0004000 -#define TARGET_CBAUDEX 0010000 -#define TARGET_BOTHER 0010000 -#define TARGET_B57600 0010001 -#define TARGET_B115200 0010002 -#define TARGET_B230400 0010003 -#define TARGET_B460800 0010004 -#define TARGET_B500000 0010005 -#define TARGET_B576000 0010006 -#define TARGET_B921600 0010007 -#define TARGET_B1000000 0010010 -#define TARGET_B1152000 0010011 -#define TARGET_B1500000 0010012 -#define TARGET_B2000000 0010013 -#define TARGET_B2500000 0010014 -#define TARGET_B3000000 0010015 -#define TARGET_B3500000 0010016 -#define TARGET_B4000000 0010017 -#define TARGET_CIBAUD 002003600000 /* input baud rate */ -#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ -#define TARGET_CRTSCTS 020000000000 /* flow control */ - -#define TARGET_IBSHIFT 16 /* Shift from CBAUD to CIBAUD */ - -/* c_lflag bits */ -#define TARGET_ISIG 0000001 -#define TARGET_ICANON 0000002 -#define TARGET_XCASE 0000004 -#define TARGET_ECHO 0000010 -#define TARGET_ECHOE 0000020 -#define TARGET_ECHOK 0000040 -#define TARGET_ECHONL 0000100 -#define TARGET_NOFLSH 0000200 -#define TARGET_TOSTOP 0000400 -#define TARGET_ECHOCTL 0001000 -#define TARGET_ECHOPRT 0002000 -#define TARGET_ECHOKE 0004000 -#define TARGET_FLUSHO 0010000 -#define TARGET_PENDIN 0040000 -#define TARGET_IEXTEN 0100000 -#define TARGET_EXTPROC 0200000 - -/* tcflow() and TCXONC use these */ -#define TARGET_TCOOFF 0 -#define TARGET_TCOON 1 -#define TARGET_TCIOFF 2 -#define TARGET_TCION 3 - -/* tcflush() and TCFLSH use these */ -#define TARGET_TCIFLUSH 0 -#define TARGET_TCOFLUSH 1 -#define TARGET_TCIOFLUSH 2 - -/* tcsetattr uses these */ -#define TARGET_TCSANOW 0 -#define TARGET_TCSADRAIN 1 -#define TARGET_TCSAFLUSH 2 - -/* From asm-generic/ioctls.h, which is used by tilegx */ - -#define TARGET_TCGETS 0x5401 -#define TARGET_TCSETS 0x5402 -#define TARGET_TCSETSW 0x5403 -#define TARGET_TCSETSF 0x5404 -#define TARGET_TCGETA 0x5405 -#define TARGET_TCSETA 0x5406 -#define TARGET_TCSETAW 0x5407 -#define TARGET_TCSETAF 0x5408 -#define TARGET_TCSBRK 0x5409 -#define TARGET_TCXONC 0x540A -#define TARGET_TCFLSH 0x540B -#define TARGET_TIOCEXCL 0x540C -#define TARGET_TIOCNXCL 0x540D -#define TARGET_TIOCSCTTY 0x540E -#define TARGET_TIOCGPGRP 0x540F -#define TARGET_TIOCSPGRP 0x5410 -#define TARGET_TIOCOUTQ 0x5411 -#define TARGET_TIOCSTI 0x5412 -#define TARGET_TIOCGWINSZ 0x5413 -#define TARGET_TIOCSWINSZ 0x5414 -#define TARGET_TIOCMGET 0x5415 -#define TARGET_TIOCMBIS 0x5416 -#define TARGET_TIOCMBIC 0x5417 -#define TARGET_TIOCMSET 0x5418 -#define TARGET_TIOCGSOFTCAR 0x5419 -#define TARGET_TIOCSSOFTCAR 0x541A -#define TARGET_FIONREAD 0x541B -#define TARGET_TIOCINQ TARGET_FIONREAD -#define TARGET_TIOCLINUX 0x541C -#define TARGET_TIOCCONS 0x541D -#define TARGET_TIOCGSERIAL 0x541E -#define TARGET_TIOCSSERIAL 0x541F -#define TARGET_TIOCPKT 0x5420 -#define TARGET_FIONBIO 0x5421 -#define TARGET_TIOCNOTTY 0x5422 -#define TARGET_TIOCSETD 0x5423 -#define TARGET_TIOCGETD 0x5424 -#define TARGET_TCSBRKP 0x5425 -#define TARGET_TIOCSBRK 0x5427 -#define TARGET_TIOCCBRK 0x5428 -#define TARGET_TIOCGSID 0x5429 -#define TARGET_TCGETS2 TARGET_IOR('T', 0x2A, struct termios2) -#define TARGET_TCSETS2 TARGET_IOW('T', 0x2B, struct termios2) -#define TARGET_TCSETSW2 TARGET_IOW('T', 0x2C, struct termios2) -#define TARGET_TCSETSF2 TARGET_IOW('T', 0x2D, struct termios2) -#define TARGET_TIOCGRS485 0x542E -#define TARGET_TIOCSRS485 0x542F -#define TARGET_TIOCGPTN TARGET_IOR('T', 0x30, unsigned int) -#define TARGET_TIOCSPTLCK TARGET_IOW('T', 0x31, int) -#define TARGET_TIOCGDEV TARGET_IOR('T', 0x32, unsigned int) -#define TARGET_TCGETX 0x5432 -#define TARGET_TCSETX 0x5433 -#define TARGET_TCSETXF 0x5434 -#define TARGET_TCSETXW 0x5435 -#define TARGET_TIOCSIG TARGET_IOW('T', 0x36, int) -#define TARGET_TIOCVHANGUP 0x5437 -#define TARGET_TIOCGPKT TARGET_IOR('T', 0x38, int) -#define TARGET_TIOCGPTLCK TARGET_IOR('T', 0x39, int) -#define TARGET_TIOCGEXCL TARGET_IOR('T', 0x40, int) -#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) - -#define TARGET_FIONCLEX 0x5450 -#define TARGET_FIOCLEX 0x5451 -#define TARGET_FIOASYNC 0x5452 -#define TARGET_TIOCSERCONFIG 0x5453 -#define TARGET_TIOCSERGWILD 0x5454 -#define TARGET_TIOCSERSWILD 0x5455 -#define TARGET_TIOCGLCKTRMIOS 0x5456 -#define TARGET_TIOCSLCKTRMIOS 0x5457 -#define TARGET_TIOCSERGSTRUCT 0x5458 -#define TARGET_TIOCSERGETLSR 0x5459 -#define TARGET_TIOCSERGETMULTI 0x545A -#define TARGET_TIOCSERSETMULTI 0x545B - -#define TARGET_TIOCMIWAIT 0x545C -#define TARGET_TIOCGICOUNT 0x545D -#define TARGET_FIOQSIZE 0x5460 - -#define TARGET_TIOCPKT_DATA 0 -#define TARGET_TIOCPKT_FLUSHREAD 1 -#define TARGET_TIOCPKT_FLUSHWRITE 2 -#define TARGET_TIOCPKT_STOP 4 -#define TARGET_TIOCPKT_START 8 -#define TARGET_TIOCPKT_NOSTOP 16 -#define TARGET_TIOCPKT_DOSTOP 32 -#define TARGET_TIOCPKT_IOCTL 64 - -#define TARGET_TIOCSER_TEMT 0x01 - -#endif +#include "../generic/termbits.h" diff --git a/linux-user/trace.h b/linux-user/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..05518e4694c738bf27d68366776dc38c292c62c2 --- /dev/null +++ b/linux-user/trace.h @@ -0,0 +1 @@ +#include "trace/trace-linux_user.h" diff --git a/linux-user/x86_64/Makefile.objs b/linux-user/x86_64/Makefile.objs deleted file mode 100644 index 2cef1d48becc7dc4342d0a23b87d6df9ec65ae90..0000000000000000000000000000000000000000 --- a/linux-user/x86_64/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -generated-files-y += linux-user/x86_64/syscall_nr.h - -syshdr := $(SRC_PATH)/linux-user/x86_64/syscallhdr.sh -%/syscall_nr.h: $(SRC_PATH)/linux-user/x86_64/syscall_64.tbl $(syshdr) - $(call quiet-command, sh $(syshdr) $< $@ $(TARGET_SYSTBL_ABI),"GEN","$@") diff --git a/linux-user/x86_64/meson.build b/linux-user/x86_64/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..203af9a60cc2ff3aff87489e5b408afb2c13afef --- /dev/null +++ b/linux-user/x86_64/meson.build @@ -0,0 +1,5 @@ +syscall_nr_generators += { + 'x86_64': generator(sh, + arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ], + output: '@BASENAME@_nr.h') +} diff --git a/linux-user/x86_64/syscall_64.tbl b/linux-user/x86_64/syscall_64.tbl index 44d510bc9b7877a18c082ceb168f01e94db0417b..f30d6ae9a6883c510eb07f821675b460a3fd8754 100644 --- a/linux-user/x86_64/syscall_64.tbl +++ b/linux-user/x86_64/syscall_64.tbl @@ -8,357 +8,359 @@ # # The abi is "common", "64" or "x32" for this file. # -0 common read __x64_sys_read -1 common write __x64_sys_write -2 common open __x64_sys_open -3 common close __x64_sys_close -4 common stat __x64_sys_newstat -5 common fstat __x64_sys_newfstat -6 common lstat __x64_sys_newlstat -7 common poll __x64_sys_poll -8 common lseek __x64_sys_lseek -9 common mmap __x64_sys_mmap -10 common mprotect __x64_sys_mprotect -11 common munmap __x64_sys_munmap -12 common brk __x64_sys_brk -13 64 rt_sigaction __x64_sys_rt_sigaction -14 common rt_sigprocmask __x64_sys_rt_sigprocmask -15 64 rt_sigreturn __x64_sys_rt_sigreturn/ptregs -16 64 ioctl __x64_sys_ioctl -17 common pread64 __x64_sys_pread64 -18 common pwrite64 __x64_sys_pwrite64 -19 64 readv __x64_sys_readv -20 64 writev __x64_sys_writev -21 common access __x64_sys_access -22 common pipe __x64_sys_pipe -23 common select __x64_sys_select -24 common sched_yield __x64_sys_sched_yield -25 common mremap __x64_sys_mremap -26 common msync __x64_sys_msync -27 common mincore __x64_sys_mincore -28 common madvise __x64_sys_madvise -29 common shmget __x64_sys_shmget -30 common shmat __x64_sys_shmat -31 common shmctl __x64_sys_shmctl -32 common dup __x64_sys_dup -33 common dup2 __x64_sys_dup2 -34 common pause __x64_sys_pause -35 common nanosleep __x64_sys_nanosleep -36 common getitimer __x64_sys_getitimer -37 common alarm __x64_sys_alarm -38 common setitimer __x64_sys_setitimer -39 common getpid __x64_sys_getpid -40 common sendfile __x64_sys_sendfile64 -41 common socket __x64_sys_socket -42 common connect __x64_sys_connect -43 common accept __x64_sys_accept -44 common sendto __x64_sys_sendto -45 64 recvfrom __x64_sys_recvfrom -46 64 sendmsg __x64_sys_sendmsg -47 64 recvmsg __x64_sys_recvmsg -48 common shutdown __x64_sys_shutdown -49 common bind __x64_sys_bind -50 common listen __x64_sys_listen -51 common getsockname __x64_sys_getsockname -52 common getpeername __x64_sys_getpeername -53 common socketpair __x64_sys_socketpair -54 64 setsockopt __x64_sys_setsockopt -55 64 getsockopt __x64_sys_getsockopt -56 common clone __x64_sys_clone/ptregs -57 common fork __x64_sys_fork/ptregs -58 common vfork __x64_sys_vfork/ptregs -59 64 execve __x64_sys_execve/ptregs -60 common exit __x64_sys_exit -61 common wait4 __x64_sys_wait4 -62 common kill __x64_sys_kill -63 common uname __x64_sys_newuname -64 common semget __x64_sys_semget -65 common semop __x64_sys_semop -66 common semctl __x64_sys_semctl -67 common shmdt __x64_sys_shmdt -68 common msgget __x64_sys_msgget -69 common msgsnd __x64_sys_msgsnd -70 common msgrcv __x64_sys_msgrcv -71 common msgctl __x64_sys_msgctl -72 common fcntl __x64_sys_fcntl -73 common flock __x64_sys_flock -74 common fsync __x64_sys_fsync -75 common fdatasync __x64_sys_fdatasync -76 common truncate __x64_sys_truncate -77 common ftruncate __x64_sys_ftruncate -78 common getdents __x64_sys_getdents -79 common getcwd __x64_sys_getcwd -80 common chdir __x64_sys_chdir -81 common fchdir __x64_sys_fchdir -82 common rename __x64_sys_rename -83 common mkdir __x64_sys_mkdir -84 common rmdir __x64_sys_rmdir -85 common creat __x64_sys_creat -86 common link __x64_sys_link -87 common unlink __x64_sys_unlink -88 common symlink __x64_sys_symlink -89 common readlink __x64_sys_readlink -90 common chmod __x64_sys_chmod -91 common fchmod __x64_sys_fchmod -92 common chown __x64_sys_chown -93 common fchown __x64_sys_fchown -94 common lchown __x64_sys_lchown -95 common umask __x64_sys_umask -96 common gettimeofday __x64_sys_gettimeofday -97 common getrlimit __x64_sys_getrlimit -98 common getrusage __x64_sys_getrusage -99 common sysinfo __x64_sys_sysinfo -100 common times __x64_sys_times -101 64 ptrace __x64_sys_ptrace -102 common getuid __x64_sys_getuid -103 common syslog __x64_sys_syslog -104 common getgid __x64_sys_getgid -105 common setuid __x64_sys_setuid -106 common setgid __x64_sys_setgid -107 common geteuid __x64_sys_geteuid -108 common getegid __x64_sys_getegid -109 common setpgid __x64_sys_setpgid -110 common getppid __x64_sys_getppid -111 common getpgrp __x64_sys_getpgrp -112 common setsid __x64_sys_setsid -113 common setreuid __x64_sys_setreuid -114 common setregid __x64_sys_setregid -115 common getgroups __x64_sys_getgroups -116 common setgroups __x64_sys_setgroups -117 common setresuid __x64_sys_setresuid -118 common getresuid __x64_sys_getresuid -119 common setresgid __x64_sys_setresgid -120 common getresgid __x64_sys_getresgid -121 common getpgid __x64_sys_getpgid -122 common setfsuid __x64_sys_setfsuid -123 common setfsgid __x64_sys_setfsgid -124 common getsid __x64_sys_getsid -125 common capget __x64_sys_capget -126 common capset __x64_sys_capset -127 64 rt_sigpending __x64_sys_rt_sigpending -128 64 rt_sigtimedwait __x64_sys_rt_sigtimedwait -129 64 rt_sigqueueinfo __x64_sys_rt_sigqueueinfo -130 common rt_sigsuspend __x64_sys_rt_sigsuspend -131 64 sigaltstack __x64_sys_sigaltstack -132 common utime __x64_sys_utime -133 common mknod __x64_sys_mknod +0 common read sys_read +1 common write sys_write +2 common open sys_open +3 common close sys_close +4 common stat sys_newstat +5 common fstat sys_newfstat +6 common lstat sys_newlstat +7 common poll sys_poll +8 common lseek sys_lseek +9 common mmap sys_mmap +10 common mprotect sys_mprotect +11 common munmap sys_munmap +12 common brk sys_brk +13 64 rt_sigaction sys_rt_sigaction +14 common rt_sigprocmask sys_rt_sigprocmask +15 64 rt_sigreturn sys_rt_sigreturn +16 64 ioctl sys_ioctl +17 common pread64 sys_pread64 +18 common pwrite64 sys_pwrite64 +19 64 readv sys_readv +20 64 writev sys_writev +21 common access sys_access +22 common pipe sys_pipe +23 common select sys_select +24 common sched_yield sys_sched_yield +25 common mremap sys_mremap +26 common msync sys_msync +27 common mincore sys_mincore +28 common madvise sys_madvise +29 common shmget sys_shmget +30 common shmat sys_shmat +31 common shmctl sys_shmctl +32 common dup sys_dup +33 common dup2 sys_dup2 +34 common pause sys_pause +35 common nanosleep sys_nanosleep +36 common getitimer sys_getitimer +37 common alarm sys_alarm +38 common setitimer sys_setitimer +39 common getpid sys_getpid +40 common sendfile sys_sendfile64 +41 common socket sys_socket +42 common connect sys_connect +43 common accept sys_accept +44 common sendto sys_sendto +45 64 recvfrom sys_recvfrom +46 64 sendmsg sys_sendmsg +47 64 recvmsg sys_recvmsg +48 common shutdown sys_shutdown +49 common bind sys_bind +50 common listen sys_listen +51 common getsockname sys_getsockname +52 common getpeername sys_getpeername +53 common socketpair sys_socketpair +54 64 setsockopt sys_setsockopt +55 64 getsockopt sys_getsockopt +56 common clone sys_clone +57 common fork sys_fork +58 common vfork sys_vfork +59 64 execve sys_execve +60 common exit sys_exit +61 common wait4 sys_wait4 +62 common kill sys_kill +63 common uname sys_newuname +64 common semget sys_semget +65 common semop sys_semop +66 common semctl sys_semctl +67 common shmdt sys_shmdt +68 common msgget sys_msgget +69 common msgsnd sys_msgsnd +70 common msgrcv sys_msgrcv +71 common msgctl sys_msgctl +72 common fcntl sys_fcntl +73 common flock sys_flock +74 common fsync sys_fsync +75 common fdatasync sys_fdatasync +76 common truncate sys_truncate +77 common ftruncate sys_ftruncate +78 common getdents sys_getdents +79 common getcwd sys_getcwd +80 common chdir sys_chdir +81 common fchdir sys_fchdir +82 common rename sys_rename +83 common mkdir sys_mkdir +84 common rmdir sys_rmdir +85 common creat sys_creat +86 common link sys_link +87 common unlink sys_unlink +88 common symlink sys_symlink +89 common readlink sys_readlink +90 common chmod sys_chmod +91 common fchmod sys_fchmod +92 common chown sys_chown +93 common fchown sys_fchown +94 common lchown sys_lchown +95 common umask sys_umask +96 common gettimeofday sys_gettimeofday +97 common getrlimit sys_getrlimit +98 common getrusage sys_getrusage +99 common sysinfo sys_sysinfo +100 common times sys_times +101 64 ptrace sys_ptrace +102 common getuid sys_getuid +103 common syslog sys_syslog +104 common getgid sys_getgid +105 common setuid sys_setuid +106 common setgid sys_setgid +107 common geteuid sys_geteuid +108 common getegid sys_getegid +109 common setpgid sys_setpgid +110 common getppid sys_getppid +111 common getpgrp sys_getpgrp +112 common setsid sys_setsid +113 common setreuid sys_setreuid +114 common setregid sys_setregid +115 common getgroups sys_getgroups +116 common setgroups sys_setgroups +117 common setresuid sys_setresuid +118 common getresuid sys_getresuid +119 common setresgid sys_setresgid +120 common getresgid sys_getresgid +121 common getpgid sys_getpgid +122 common setfsuid sys_setfsuid +123 common setfsgid sys_setfsgid +124 common getsid sys_getsid +125 common capget sys_capget +126 common capset sys_capset +127 64 rt_sigpending sys_rt_sigpending +128 64 rt_sigtimedwait sys_rt_sigtimedwait +129 64 rt_sigqueueinfo sys_rt_sigqueueinfo +130 common rt_sigsuspend sys_rt_sigsuspend +131 64 sigaltstack sys_sigaltstack +132 common utime sys_utime +133 common mknod sys_mknod 134 64 uselib -135 common personality __x64_sys_personality -136 common ustat __x64_sys_ustat -137 common statfs __x64_sys_statfs -138 common fstatfs __x64_sys_fstatfs -139 common sysfs __x64_sys_sysfs -140 common getpriority __x64_sys_getpriority -141 common setpriority __x64_sys_setpriority -142 common sched_setparam __x64_sys_sched_setparam -143 common sched_getparam __x64_sys_sched_getparam -144 common sched_setscheduler __x64_sys_sched_setscheduler -145 common sched_getscheduler __x64_sys_sched_getscheduler -146 common sched_get_priority_max __x64_sys_sched_get_priority_max -147 common sched_get_priority_min __x64_sys_sched_get_priority_min -148 common sched_rr_get_interval __x64_sys_sched_rr_get_interval -149 common mlock __x64_sys_mlock -150 common munlock __x64_sys_munlock -151 common mlockall __x64_sys_mlockall -152 common munlockall __x64_sys_munlockall -153 common vhangup __x64_sys_vhangup -154 common modify_ldt __x64_sys_modify_ldt -155 common pivot_root __x64_sys_pivot_root -156 64 _sysctl __x64_sys_sysctl -157 common prctl __x64_sys_prctl -158 common arch_prctl __x64_sys_arch_prctl -159 common adjtimex __x64_sys_adjtimex -160 common setrlimit __x64_sys_setrlimit -161 common chroot __x64_sys_chroot -162 common sync __x64_sys_sync -163 common acct __x64_sys_acct -164 common settimeofday __x64_sys_settimeofday -165 common mount __x64_sys_mount -166 common umount2 __x64_sys_umount -167 common swapon __x64_sys_swapon -168 common swapoff __x64_sys_swapoff -169 common reboot __x64_sys_reboot -170 common sethostname __x64_sys_sethostname -171 common setdomainname __x64_sys_setdomainname -172 common iopl __x64_sys_iopl/ptregs -173 common ioperm __x64_sys_ioperm +135 common personality sys_personality +136 common ustat sys_ustat +137 common statfs sys_statfs +138 common fstatfs sys_fstatfs +139 common sysfs sys_sysfs +140 common getpriority sys_getpriority +141 common setpriority sys_setpriority +142 common sched_setparam sys_sched_setparam +143 common sched_getparam sys_sched_getparam +144 common sched_setscheduler sys_sched_setscheduler +145 common sched_getscheduler sys_sched_getscheduler +146 common sched_get_priority_max sys_sched_get_priority_max +147 common sched_get_priority_min sys_sched_get_priority_min +148 common sched_rr_get_interval sys_sched_rr_get_interval +149 common mlock sys_mlock +150 common munlock sys_munlock +151 common mlockall sys_mlockall +152 common munlockall sys_munlockall +153 common vhangup sys_vhangup +154 common modify_ldt sys_modify_ldt +155 common pivot_root sys_pivot_root +156 64 _sysctl sys_ni_syscall +157 common prctl sys_prctl +158 common arch_prctl sys_arch_prctl +159 common adjtimex sys_adjtimex +160 common setrlimit sys_setrlimit +161 common chroot sys_chroot +162 common sync sys_sync +163 common acct sys_acct +164 common settimeofday sys_settimeofday +165 common mount sys_mount +166 common umount2 sys_umount +167 common swapon sys_swapon +168 common swapoff sys_swapoff +169 common reboot sys_reboot +170 common sethostname sys_sethostname +171 common setdomainname sys_setdomainname +172 common iopl sys_iopl +173 common ioperm sys_ioperm 174 64 create_module -175 common init_module __x64_sys_init_module -176 common delete_module __x64_sys_delete_module +175 common init_module sys_init_module +176 common delete_module sys_delete_module 177 64 get_kernel_syms 178 64 query_module -179 common quotactl __x64_sys_quotactl +179 common quotactl sys_quotactl 180 64 nfsservctl 181 common getpmsg 182 common putpmsg 183 common afs_syscall 184 common tuxcall 185 common security -186 common gettid __x64_sys_gettid -187 common readahead __x64_sys_readahead -188 common setxattr __x64_sys_setxattr -189 common lsetxattr __x64_sys_lsetxattr -190 common fsetxattr __x64_sys_fsetxattr -191 common getxattr __x64_sys_getxattr -192 common lgetxattr __x64_sys_lgetxattr -193 common fgetxattr __x64_sys_fgetxattr -194 common listxattr __x64_sys_listxattr -195 common llistxattr __x64_sys_llistxattr -196 common flistxattr __x64_sys_flistxattr -197 common removexattr __x64_sys_removexattr -198 common lremovexattr __x64_sys_lremovexattr -199 common fremovexattr __x64_sys_fremovexattr -200 common tkill __x64_sys_tkill -201 common time __x64_sys_time -202 common futex __x64_sys_futex -203 common sched_setaffinity __x64_sys_sched_setaffinity -204 common sched_getaffinity __x64_sys_sched_getaffinity +186 common gettid sys_gettid +187 common readahead sys_readahead +188 common setxattr sys_setxattr +189 common lsetxattr sys_lsetxattr +190 common fsetxattr sys_fsetxattr +191 common getxattr sys_getxattr +192 common lgetxattr sys_lgetxattr +193 common fgetxattr sys_fgetxattr +194 common listxattr sys_listxattr +195 common llistxattr sys_llistxattr +196 common flistxattr sys_flistxattr +197 common removexattr sys_removexattr +198 common lremovexattr sys_lremovexattr +199 common fremovexattr sys_fremovexattr +200 common tkill sys_tkill +201 common time sys_time +202 common futex sys_futex +203 common sched_setaffinity sys_sched_setaffinity +204 common sched_getaffinity sys_sched_getaffinity 205 64 set_thread_area -206 64 io_setup __x64_sys_io_setup -207 common io_destroy __x64_sys_io_destroy -208 common io_getevents __x64_sys_io_getevents -209 64 io_submit __x64_sys_io_submit -210 common io_cancel __x64_sys_io_cancel +206 64 io_setup sys_io_setup +207 common io_destroy sys_io_destroy +208 common io_getevents sys_io_getevents +209 64 io_submit sys_io_submit +210 common io_cancel sys_io_cancel 211 64 get_thread_area -212 common lookup_dcookie __x64_sys_lookup_dcookie -213 common epoll_create __x64_sys_epoll_create +212 common lookup_dcookie sys_lookup_dcookie +213 common epoll_create sys_epoll_create 214 64 epoll_ctl_old 215 64 epoll_wait_old -216 common remap_file_pages __x64_sys_remap_file_pages -217 common getdents64 __x64_sys_getdents64 -218 common set_tid_address __x64_sys_set_tid_address -219 common restart_syscall __x64_sys_restart_syscall -220 common semtimedop __x64_sys_semtimedop -221 common fadvise64 __x64_sys_fadvise64 -222 64 timer_create __x64_sys_timer_create -223 common timer_settime __x64_sys_timer_settime -224 common timer_gettime __x64_sys_timer_gettime -225 common timer_getoverrun __x64_sys_timer_getoverrun -226 common timer_delete __x64_sys_timer_delete -227 common clock_settime __x64_sys_clock_settime -228 common clock_gettime __x64_sys_clock_gettime -229 common clock_getres __x64_sys_clock_getres -230 common clock_nanosleep __x64_sys_clock_nanosleep -231 common exit_group __x64_sys_exit_group -232 common epoll_wait __x64_sys_epoll_wait -233 common epoll_ctl __x64_sys_epoll_ctl -234 common tgkill __x64_sys_tgkill -235 common utimes __x64_sys_utimes +216 common remap_file_pages sys_remap_file_pages +217 common getdents64 sys_getdents64 +218 common set_tid_address sys_set_tid_address +219 common restart_syscall sys_restart_syscall +220 common semtimedop sys_semtimedop +221 common fadvise64 sys_fadvise64 +222 64 timer_create sys_timer_create +223 common timer_settime sys_timer_settime +224 common timer_gettime sys_timer_gettime +225 common timer_getoverrun sys_timer_getoverrun +226 common timer_delete sys_timer_delete +227 common clock_settime sys_clock_settime +228 common clock_gettime sys_clock_gettime +229 common clock_getres sys_clock_getres +230 common clock_nanosleep sys_clock_nanosleep +231 common exit_group sys_exit_group +232 common epoll_wait sys_epoll_wait +233 common epoll_ctl sys_epoll_ctl +234 common tgkill sys_tgkill +235 common utimes sys_utimes 236 64 vserver -237 common mbind __x64_sys_mbind -238 common set_mempolicy __x64_sys_set_mempolicy -239 common get_mempolicy __x64_sys_get_mempolicy -240 common mq_open __x64_sys_mq_open -241 common mq_unlink __x64_sys_mq_unlink -242 common mq_timedsend __x64_sys_mq_timedsend -243 common mq_timedreceive __x64_sys_mq_timedreceive -244 64 mq_notify __x64_sys_mq_notify -245 common mq_getsetattr __x64_sys_mq_getsetattr -246 64 kexec_load __x64_sys_kexec_load -247 64 waitid __x64_sys_waitid -248 common add_key __x64_sys_add_key -249 common request_key __x64_sys_request_key -250 common keyctl __x64_sys_keyctl -251 common ioprio_set __x64_sys_ioprio_set -252 common ioprio_get __x64_sys_ioprio_get -253 common inotify_init __x64_sys_inotify_init -254 common inotify_add_watch __x64_sys_inotify_add_watch -255 common inotify_rm_watch __x64_sys_inotify_rm_watch -256 common migrate_pages __x64_sys_migrate_pages -257 common openat __x64_sys_openat -258 common mkdirat __x64_sys_mkdirat -259 common mknodat __x64_sys_mknodat -260 common fchownat __x64_sys_fchownat -261 common futimesat __x64_sys_futimesat -262 common newfstatat __x64_sys_newfstatat -263 common unlinkat __x64_sys_unlinkat -264 common renameat __x64_sys_renameat -265 common linkat __x64_sys_linkat -266 common symlinkat __x64_sys_symlinkat -267 common readlinkat __x64_sys_readlinkat -268 common fchmodat __x64_sys_fchmodat -269 common faccessat __x64_sys_faccessat -270 common pselect6 __x64_sys_pselect6 -271 common ppoll __x64_sys_ppoll -272 common unshare __x64_sys_unshare -273 64 set_robust_list __x64_sys_set_robust_list -274 64 get_robust_list __x64_sys_get_robust_list -275 common splice __x64_sys_splice -276 common tee __x64_sys_tee -277 common sync_file_range __x64_sys_sync_file_range -278 64 vmsplice __x64_sys_vmsplice -279 64 move_pages __x64_sys_move_pages -280 common utimensat __x64_sys_utimensat -281 common epoll_pwait __x64_sys_epoll_pwait -282 common signalfd __x64_sys_signalfd -283 common timerfd_create __x64_sys_timerfd_create -284 common eventfd __x64_sys_eventfd -285 common fallocate __x64_sys_fallocate -286 common timerfd_settime __x64_sys_timerfd_settime -287 common timerfd_gettime __x64_sys_timerfd_gettime -288 common accept4 __x64_sys_accept4 -289 common signalfd4 __x64_sys_signalfd4 -290 common eventfd2 __x64_sys_eventfd2 -291 common epoll_create1 __x64_sys_epoll_create1 -292 common dup3 __x64_sys_dup3 -293 common pipe2 __x64_sys_pipe2 -294 common inotify_init1 __x64_sys_inotify_init1 -295 64 preadv __x64_sys_preadv -296 64 pwritev __x64_sys_pwritev -297 64 rt_tgsigqueueinfo __x64_sys_rt_tgsigqueueinfo -298 common perf_event_open __x64_sys_perf_event_open -299 64 recvmmsg __x64_sys_recvmmsg -300 common fanotify_init __x64_sys_fanotify_init -301 common fanotify_mark __x64_sys_fanotify_mark -302 common prlimit64 __x64_sys_prlimit64 -303 common name_to_handle_at __x64_sys_name_to_handle_at -304 common open_by_handle_at __x64_sys_open_by_handle_at -305 common clock_adjtime __x64_sys_clock_adjtime -306 common syncfs __x64_sys_syncfs -307 64 sendmmsg __x64_sys_sendmmsg -308 common setns __x64_sys_setns -309 common getcpu __x64_sys_getcpu -310 64 process_vm_readv __x64_sys_process_vm_readv -311 64 process_vm_writev __x64_sys_process_vm_writev -312 common kcmp __x64_sys_kcmp -313 common finit_module __x64_sys_finit_module -314 common sched_setattr __x64_sys_sched_setattr -315 common sched_getattr __x64_sys_sched_getattr -316 common renameat2 __x64_sys_renameat2 -317 common seccomp __x64_sys_seccomp -318 common getrandom __x64_sys_getrandom -319 common memfd_create __x64_sys_memfd_create -320 common kexec_file_load __x64_sys_kexec_file_load -321 common bpf __x64_sys_bpf -322 64 execveat __x64_sys_execveat/ptregs -323 common userfaultfd __x64_sys_userfaultfd -324 common membarrier __x64_sys_membarrier -325 common mlock2 __x64_sys_mlock2 -326 common copy_file_range __x64_sys_copy_file_range -327 64 preadv2 __x64_sys_preadv2 -328 64 pwritev2 __x64_sys_pwritev2 -329 common pkey_mprotect __x64_sys_pkey_mprotect -330 common pkey_alloc __x64_sys_pkey_alloc -331 common pkey_free __x64_sys_pkey_free -332 common statx __x64_sys_statx -333 common io_pgetevents __x64_sys_io_pgetevents -334 common rseq __x64_sys_rseq +237 common mbind sys_mbind +238 common set_mempolicy sys_set_mempolicy +239 common get_mempolicy sys_get_mempolicy +240 common mq_open sys_mq_open +241 common mq_unlink sys_mq_unlink +242 common mq_timedsend sys_mq_timedsend +243 common mq_timedreceive sys_mq_timedreceive +244 64 mq_notify sys_mq_notify +245 common mq_getsetattr sys_mq_getsetattr +246 64 kexec_load sys_kexec_load +247 64 waitid sys_waitid +248 common add_key sys_add_key +249 common request_key sys_request_key +250 common keyctl sys_keyctl +251 common ioprio_set sys_ioprio_set +252 common ioprio_get sys_ioprio_get +253 common inotify_init sys_inotify_init +254 common inotify_add_watch sys_inotify_add_watch +255 common inotify_rm_watch sys_inotify_rm_watch +256 common migrate_pages sys_migrate_pages +257 common openat sys_openat +258 common mkdirat sys_mkdirat +259 common mknodat sys_mknodat +260 common fchownat sys_fchownat +261 common futimesat sys_futimesat +262 common newfstatat sys_newfstatat +263 common unlinkat sys_unlinkat +264 common renameat sys_renameat +265 common linkat sys_linkat +266 common symlinkat sys_symlinkat +267 common readlinkat sys_readlinkat +268 common fchmodat sys_fchmodat +269 common faccessat sys_faccessat +270 common pselect6 sys_pselect6 +271 common ppoll sys_ppoll +272 common unshare sys_unshare +273 64 set_robust_list sys_set_robust_list +274 64 get_robust_list sys_get_robust_list +275 common splice sys_splice +276 common tee sys_tee +277 common sync_file_range sys_sync_file_range +278 64 vmsplice sys_vmsplice +279 64 move_pages sys_move_pages +280 common utimensat sys_utimensat +281 common epoll_pwait sys_epoll_pwait +282 common signalfd sys_signalfd +283 common timerfd_create sys_timerfd_create +284 common eventfd sys_eventfd +285 common fallocate sys_fallocate +286 common timerfd_settime sys_timerfd_settime +287 common timerfd_gettime sys_timerfd_gettime +288 common accept4 sys_accept4 +289 common signalfd4 sys_signalfd4 +290 common eventfd2 sys_eventfd2 +291 common epoll_create1 sys_epoll_create1 +292 common dup3 sys_dup3 +293 common pipe2 sys_pipe2 +294 common inotify_init1 sys_inotify_init1 +295 64 preadv sys_preadv +296 64 pwritev sys_pwritev +297 64 rt_tgsigqueueinfo sys_rt_tgsigqueueinfo +298 common perf_event_open sys_perf_event_open +299 64 recvmmsg sys_recvmmsg +300 common fanotify_init sys_fanotify_init +301 common fanotify_mark sys_fanotify_mark +302 common prlimit64 sys_prlimit64 +303 common name_to_handle_at sys_name_to_handle_at +304 common open_by_handle_at sys_open_by_handle_at +305 common clock_adjtime sys_clock_adjtime +306 common syncfs sys_syncfs +307 64 sendmmsg sys_sendmmsg +308 common setns sys_setns +309 common getcpu sys_getcpu +310 64 process_vm_readv sys_process_vm_readv +311 64 process_vm_writev sys_process_vm_writev +312 common kcmp sys_kcmp +313 common finit_module sys_finit_module +314 common sched_setattr sys_sched_setattr +315 common sched_getattr sys_sched_getattr +316 common renameat2 sys_renameat2 +317 common seccomp sys_seccomp +318 common getrandom sys_getrandom +319 common memfd_create sys_memfd_create +320 common kexec_file_load sys_kexec_file_load +321 common bpf sys_bpf +322 64 execveat sys_execveat +323 common userfaultfd sys_userfaultfd +324 common membarrier sys_membarrier +325 common mlock2 sys_mlock2 +326 common copy_file_range sys_copy_file_range +327 64 preadv2 sys_preadv2 +328 64 pwritev2 sys_pwritev2 +329 common pkey_mprotect sys_pkey_mprotect +330 common pkey_alloc sys_pkey_alloc +331 common pkey_free sys_pkey_free +332 common statx sys_statx +333 common io_pgetevents sys_io_pgetevents +334 common rseq sys_rseq # don't use numbers 387 through 423, add new calls after the last # 'common' entry -424 common pidfd_send_signal __x64_sys_pidfd_send_signal -425 common io_uring_setup __x64_sys_io_uring_setup -426 common io_uring_enter __x64_sys_io_uring_enter -427 common io_uring_register __x64_sys_io_uring_register -428 common open_tree __x64_sys_open_tree -429 common move_mount __x64_sys_move_mount -430 common fsopen __x64_sys_fsopen -431 common fsconfig __x64_sys_fsconfig -432 common fsmount __x64_sys_fsmount -433 common fspick __x64_sys_fspick -434 common pidfd_open __x64_sys_pidfd_open -435 common clone3 __x64_sys_clone3/ptregs -437 common openat2 __x64_sys_openat2 -438 common pidfd_getfd __x64_sys_pidfd_getfd +424 common pidfd_send_signal sys_pidfd_send_signal +425 common io_uring_setup sys_io_uring_setup +426 common io_uring_enter sys_io_uring_enter +427 common io_uring_register sys_io_uring_register +428 common open_tree sys_open_tree +429 common move_mount sys_move_mount +430 common fsopen sys_fsopen +431 common fsconfig sys_fsconfig +432 common fsmount sys_fsmount +433 common fspick sys_fspick +434 common pidfd_open sys_pidfd_open +435 common clone3 sys_clone3 +436 common close_range sys_close_range +437 common openat2 sys_openat2 +438 common pidfd_getfd sys_pidfd_getfd +439 common faccessat2 sys_faccessat2 # # x32-specific system call numbers start at 512 to avoid cache impact @@ -366,39 +368,39 @@ # on-the-fly for compat_sys_*() compatibility system calls if X86_X32 # is defined. # -512 x32 rt_sigaction __x32_compat_sys_rt_sigaction -513 x32 rt_sigreturn sys32_x32_rt_sigreturn -514 x32 ioctl __x32_compat_sys_ioctl -515 x32 readv __x32_compat_sys_readv -516 x32 writev __x32_compat_sys_writev -517 x32 recvfrom __x32_compat_sys_recvfrom -518 x32 sendmsg __x32_compat_sys_sendmsg -519 x32 recvmsg __x32_compat_sys_recvmsg -520 x32 execve __x32_compat_sys_execve/ptregs -521 x32 ptrace __x32_compat_sys_ptrace -522 x32 rt_sigpending __x32_compat_sys_rt_sigpending -523 x32 rt_sigtimedwait __x32_compat_sys_rt_sigtimedwait_time64 -524 x32 rt_sigqueueinfo __x32_compat_sys_rt_sigqueueinfo -525 x32 sigaltstack __x32_compat_sys_sigaltstack -526 x32 timer_create __x32_compat_sys_timer_create -527 x32 mq_notify __x32_compat_sys_mq_notify -528 x32 kexec_load __x32_compat_sys_kexec_load -529 x32 waitid __x32_compat_sys_waitid -530 x32 set_robust_list __x32_compat_sys_set_robust_list -531 x32 get_robust_list __x32_compat_sys_get_robust_list -532 x32 vmsplice __x32_compat_sys_vmsplice -533 x32 move_pages __x32_compat_sys_move_pages -534 x32 preadv __x32_compat_sys_preadv64 -535 x32 pwritev __x32_compat_sys_pwritev64 -536 x32 rt_tgsigqueueinfo __x32_compat_sys_rt_tgsigqueueinfo -537 x32 recvmmsg __x32_compat_sys_recvmmsg_time64 -538 x32 sendmmsg __x32_compat_sys_sendmmsg -539 x32 process_vm_readv __x32_compat_sys_process_vm_readv -540 x32 process_vm_writev __x32_compat_sys_process_vm_writev -541 x32 setsockopt __x32_compat_sys_setsockopt -542 x32 getsockopt __x32_compat_sys_getsockopt -543 x32 io_setup __x32_compat_sys_io_setup -544 x32 io_submit __x32_compat_sys_io_submit -545 x32 execveat __x32_compat_sys_execveat/ptregs -546 x32 preadv2 __x32_compat_sys_preadv64v2 -547 x32 pwritev2 __x32_compat_sys_pwritev64v2 +512 x32 rt_sigaction compat_sys_rt_sigaction +513 x32 rt_sigreturn compat_sys_x32_rt_sigreturn +514 x32 ioctl compat_sys_ioctl +515 x32 readv compat_sys_readv +516 x32 writev compat_sys_writev +517 x32 recvfrom compat_sys_recvfrom +518 x32 sendmsg compat_sys_sendmsg +519 x32 recvmsg compat_sys_recvmsg +520 x32 execve compat_sys_execve +521 x32 ptrace compat_sys_ptrace +522 x32 rt_sigpending compat_sys_rt_sigpending +523 x32 rt_sigtimedwait compat_sys_rt_sigtimedwait_time64 +524 x32 rt_sigqueueinfo compat_sys_rt_sigqueueinfo +525 x32 sigaltstack compat_sys_sigaltstack +526 x32 timer_create compat_sys_timer_create +527 x32 mq_notify compat_sys_mq_notify +528 x32 kexec_load compat_sys_kexec_load +529 x32 waitid compat_sys_waitid +530 x32 set_robust_list compat_sys_set_robust_list +531 x32 get_robust_list compat_sys_get_robust_list +532 x32 vmsplice compat_sys_vmsplice +533 x32 move_pages compat_sys_move_pages +534 x32 preadv compat_sys_preadv64 +535 x32 pwritev compat_sys_pwritev64 +536 x32 rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo +537 x32 recvmmsg compat_sys_recvmmsg_time64 +538 x32 sendmmsg compat_sys_sendmmsg +539 x32 process_vm_readv compat_sys_process_vm_readv +540 x32 process_vm_writev compat_sys_process_vm_writev +541 x32 setsockopt sys_setsockopt +542 x32 getsockopt sys_getsockopt +543 x32 io_setup compat_sys_io_setup +544 x32 io_submit compat_sys_io_submit +545 x32 execveat compat_sys_execveat +546 x32 preadv2 compat_sys_preadv64v2 +547 x32 pwritev2 compat_sys_pwritev64v2 diff --git a/linux-user/x86_64/syscall_nr.h b/linux-user/x86_64/syscall_nr.h new file mode 100644 index 0000000000000000000000000000000000000000..760302cb3efe38683a7c90d691fce067cb6549ca --- /dev/null +++ b/linux-user/x86_64/syscall_nr.h @@ -0,0 +1 @@ +#include "syscall_64_nr.h" diff --git a/linux-user/x86_64/target_signal.h b/linux-user/x86_64/target_signal.h index 4c4380f7b94922bd435b7368ee51e5a91444f75a..4ea74f20dd42a32eebcd5f0b6f7d0ca327924e79 100644 --- a/linux-user/x86_64/target_signal.h +++ b/linux-user/x86_64/target_signal.h @@ -4,9 +4,9 @@ /* this struct defines a stack used during syscall handling */ typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_long ss_flags; - abi_ulong ss_size; + abi_ulong ss_sp; + abi_int ss_flags; + abi_ulong ss_size; } target_stack_t; diff --git a/linux-user/x86_64/target_structs.h b/linux-user/x86_64/target_structs.h index b6e82a822cb8c794fe80040e1fb1c6a6927cd8d4..ce367b253ba195c810bc6dad6ac0ec778da14096 100644 --- a/linux-user/x86_64/target_structs.h +++ b/linux-user/x86_64/target_structs.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/linux-user/x86_64/target_syscall.h b/linux-user/x86_64/target_syscall.h index 5e221e1d9ddc529e3230ef6a2b7cff90c9381873..3ecccb72be2dfb7f18dff6dbe3a727f7c49da7cb 100644 --- a/linux-user/x86_64/target_syscall.h +++ b/linux-user/x86_64/target_syscall.h @@ -101,7 +101,8 @@ struct target_msqid64_ds { #define TARGET_ARCH_GET_FS 0x1003 #define TARGET_ARCH_GET_GS 0x1004 #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 #endif /* X86_64_TARGET_SYSCALL_H */ diff --git a/linux-user/x86_64/termbits.h b/linux-user/x86_64/termbits.h index c8bb5996b1eb8135c4921284ab5b1b056a2ab52b..b1d4f4fedbcb9ab2ca1184280eb4a9e5b8a9d735 100644 --- a/linux-user/x86_64/termbits.h +++ b/linux-user/x86_64/termbits.h @@ -1,253 +1 @@ -#ifndef LINUX_USER_X86_64_TERMBITS_H -#define LINUX_USER_X86_64_TERMBITS_H - -#define TARGET_NCCS 19 - -typedef unsigned char target_cc_t; -typedef unsigned int target_speed_t; -typedef unsigned int target_tcflag_t; -struct target_termios { - target_tcflag_t c_iflag; /* input mode flags */ - target_tcflag_t c_oflag; /* output mode flags */ - target_tcflag_t c_cflag; /* control mode flags */ - target_tcflag_t c_lflag; /* local mode flags */ - target_cc_t c_line; /* line discipline */ - target_cc_t c_cc[TARGET_NCCS]; /* control characters */ -}; - -/* c_cc characters */ -#define TARGET_VINTR 0 -#define TARGET_VQUIT 1 -#define TARGET_VERASE 2 -#define TARGET_VKILL 3 -#define TARGET_VEOF 4 -#define TARGET_VTIME 5 -#define TARGET_VMIN 6 -#define TARGET_VSWTC 7 -#define TARGET_VSTART 8 -#define TARGET_VSTOP 9 -#define TARGET_VSUSP 10 -#define TARGET_VEOL 11 -#define TARGET_VREPRINT 12 -#define TARGET_VDISCARD 13 -#define TARGET_VWERASE 14 -#define TARGET_VLNEXT 15 -#define TARGET_VEOL2 16 - -/* c_iflag bits */ -#define TARGET_IGNBRK 0000001 -#define TARGET_BRKINT 0000002 -#define TARGET_IGNPAR 0000004 -#define TARGET_PARMRK 0000010 -#define TARGET_INPCK 0000020 -#define TARGET_ISTRIP 0000040 -#define TARGET_INLCR 0000100 -#define TARGET_IGNCR 0000200 -#define TARGET_ICRNL 0000400 -#define TARGET_IUCLC 0001000 -#define TARGET_IXON 0002000 -#define TARGET_IXANY 0004000 -#define TARGET_IXOFF 0010000 -#define TARGET_IMAXBEL 0020000 -#define TARGET_IUTF8 0040000 - -/* c_oflag bits */ -#define TARGET_OPOST 0000001 -#define TARGET_OLCUC 0000002 -#define TARGET_ONLCR 0000004 -#define TARGET_OCRNL 0000010 -#define TARGET_ONOCR 0000020 -#define TARGET_ONLRET 0000040 -#define TARGET_OFILL 0000100 -#define TARGET_OFDEL 0000200 -#define TARGET_NLDLY 0000400 -#define TARGET_NL0 0000000 -#define TARGET_NL1 0000400 -#define TARGET_CRDLY 0003000 -#define TARGET_CR0 0000000 -#define TARGET_CR1 0001000 -#define TARGET_CR2 0002000 -#define TARGET_CR3 0003000 -#define TARGET_TABDLY 0014000 -#define TARGET_TAB0 0000000 -#define TARGET_TAB1 0004000 -#define TARGET_TAB2 0010000 -#define TARGET_TAB3 0014000 -#define TARGET_XTABS 0014000 -#define TARGET_BSDLY 0020000 -#define TARGET_BS0 0000000 -#define TARGET_BS1 0020000 -#define TARGET_VTDLY 0040000 -#define TARGET_VT0 0000000 -#define TARGET_VT1 0040000 -#define TARGET_FFDLY 0100000 -#define TARGET_FF0 0000000 -#define TARGET_FF1 0100000 - -/* c_cflag bit meaning */ -#define TARGET_CBAUD 0010017 -#define TARGET_B0 0000000 /* hang up */ -#define TARGET_B50 0000001 -#define TARGET_B75 0000002 -#define TARGET_B110 0000003 -#define TARGET_B134 0000004 -#define TARGET_B150 0000005 -#define TARGET_B200 0000006 -#define TARGET_B300 0000007 -#define TARGET_B600 0000010 -#define TARGET_B1200 0000011 -#define TARGET_B1800 0000012 -#define TARGET_B2400 0000013 -#define TARGET_B4800 0000014 -#define TARGET_B9600 0000015 -#define TARGET_B19200 0000016 -#define TARGET_B38400 0000017 -#define TARGET_EXTA B19200 -#define TARGET_EXTB B38400 -#define TARGET_CSIZE 0000060 -#define TARGET_CS5 0000000 -#define TARGET_CS6 0000020 -#define TARGET_CS7 0000040 -#define TARGET_CS8 0000060 -#define TARGET_CSTOPB 0000100 -#define TARGET_CREAD 0000200 -#define TARGET_PARENB 0000400 -#define TARGET_PARODD 0001000 -#define TARGET_HUPCL 0002000 -#define TARGET_CLOCAL 0004000 -#define TARGET_CBAUDEX 0010000 -#define TARGET_BOTHER 0010000 /* non standard rate */ -#define TARGET_B57600 0010001 -#define TARGET_B115200 0010002 -#define TARGET_B230400 0010003 -#define TARGET_B460800 0010004 -#define TARGET_B500000 0010005 -#define TARGET_B576000 0010006 -#define TARGET_B921600 0010007 -#define TARGET_B1000000 0010010 -#define TARGET_B1152000 0010011 -#define TARGET_B1500000 0010012 -#define TARGET_B2000000 0010013 -#define TARGET_B2500000 0010014 -#define TARGET_B3000000 0010015 -#define TARGET_B3500000 0010016 -#define TARGET_B4000000 0010017 -#define TARGET_CIBAUD 002003600000 /* input baud rate */ -#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ -#define TARGET_CRTSCTS 020000000000 /* flow control */ - -#define TARGET_IBSHIFT 8 /* Shift from CBAUD to CIBAUD */ - -/* c_lflag bits */ -#define TARGET_ISIG 0000001 -#define TARGET_ICANON 0000002 -#define TARGET_XCASE 0000004 -#define TARGET_ECHO 0000010 -#define TARGET_ECHOE 0000020 -#define TARGET_ECHOK 0000040 -#define TARGET_ECHONL 0000100 -#define TARGET_NOFLSH 0000200 -#define TARGET_TOSTOP 0000400 -#define TARGET_ECHOCTL 0001000 -#define TARGET_ECHOPRT 0002000 -#define TARGET_ECHOKE 0004000 -#define TARGET_FLUSHO 0010000 -#define TARGET_PENDIN 0040000 -#define TARGET_IEXTEN 0100000 - -/* tcflow() and TCXONC use these */ -#define TARGET_TCOOFF 0 -#define TARGET_TCOON 1 -#define TARGET_TCIOFF 2 -#define TARGET_TCION 3 - -/* tcflush() and TCFLSH use these */ -#define TARGET_TCIFLUSH 0 -#define TARGET_TCOFLUSH 1 -#define TARGET_TCIOFLUSH 2 - -/* tcsetattr uses these */ -#define TARGET_TCSANOW 0 -#define TARGET_TCSADRAIN 1 -#define TARGET_TCSAFLUSH 2 - -#define TARGET_TCGETS 0x5401 -#define TARGET_TCSETS 0x5402 -#define TARGET_TCSETSW 0x5403 -#define TARGET_TCSETSF 0x5404 -#define TARGET_TCGETA 0x5405 -#define TARGET_TCSETA 0x5406 -#define TARGET_TCSETAW 0x5407 -#define TARGET_TCSETAF 0x5408 -#define TARGET_TCSBRK 0x5409 -#define TARGET_TCXONC 0x540A -#define TARGET_TCFLSH 0x540B -#define TARGET_TIOCEXCL 0x540C -#define TARGET_TIOCNXCL 0x540D -#define TARGET_TIOCSCTTY 0x540E -#define TARGET_TIOCGPGRP 0x540F -#define TARGET_TIOCSPGRP 0x5410 -#define TARGET_TIOCOUTQ 0x5411 -#define TARGET_TIOCSTI 0x5412 -#define TARGET_TIOCGWINSZ 0x5413 -#define TARGET_TIOCSWINSZ 0x5414 -#define TARGET_TIOCMGET 0x5415 -#define TARGET_TIOCMBIS 0x5416 -#define TARGET_TIOCMBIC 0x5417 -#define TARGET_TIOCMSET 0x5418 -#define TARGET_TIOCGSOFTCAR 0x5419 -#define TARGET_TIOCSSOFTCAR 0x541A -#define TARGET_FIONREAD 0x541B -#define TARGET_TIOCINQ FIONREAD -#define TARGET_TIOCLINUX 0x541C -#define TARGET_TIOCCONS 0x541D -#define TARGET_TIOCGSERIAL 0x541E -#define TARGET_TIOCSSERIAL 0x541F -#define TARGET_TIOCPKT 0x5420 -#define TARGET_FIONBIO 0x5421 -#define TARGET_TIOCNOTTY 0x5422 -#define TARGET_TIOCSETD 0x5423 -#define TARGET_TIOCGETD 0x5424 -#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ -#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ -#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ -#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ -#define TARGET_TCGETS2 TARGET_IOR('T',0x2A, struct termios2) -#define TARGET_TCSETS2 TARGET_IOW('T',0x2B, struct termios2) -#define TARGET_TCSETSW2 TARGET_IOW('T',0x2C, struct termios2) -#define TARGET_TCSETSF2 TARGET_IOW('T',0x2D, struct termios2) -#define TARGET_TIOCGPTN TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ -#define TARGET_TIOCSPTLCK TARGET_IOW('T',0x31, int) /* Lock/unlock Pty */ -#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) /* Safely open the slave */ - -#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */ -#define TARGET_FIOCLEX 0x5451 -#define TARGET_FIOASYNC 0x5452 -#define TARGET_TIOCSERCONFIG 0x5453 -#define TARGET_TIOCSERGWILD 0x5454 -#define TARGET_TIOCSERSWILD 0x5455 -#define TARGET_TIOCGLCKTRMIOS 0x5456 -#define TARGET_TIOCSLCKTRMIOS 0x5457 -#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ - -#define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ -#define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ -#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ -#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ -#define TARGET_FIOQSIZE 0x5460 - -/* Used for packet mode */ -#define TARGET_TIOCPKT_DATA 0 -#define TARGET_TIOCPKT_FLUSHREAD 1 -#define TARGET_TIOCPKT_FLUSHWRITE 2 -#define TARGET_TIOCPKT_STOP 4 -#define TARGET_TIOCPKT_START 8 -#define TARGET_TIOCPKT_NOSTOP 16 -#define TARGET_TIOCPKT_DOSTOP 32 - -#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - -#endif +#include "../generic/termbits.h" diff --git a/linux-user/xtensa/Makefile.objs b/linux-user/xtensa/Makefile.objs deleted file mode 100644 index d4be1b74554461b394a419543d5732c352ce67e2..0000000000000000000000000000000000000000 --- a/linux-user/xtensa/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -generated-files-y += linux-user/xtensa/syscall_nr.h - -syshdr := $(SRC_PATH)/linux-user/xtensa/syscallhdr.sh -%/syscall_nr.h: $(SRC_PATH)/linux-user/xtensa/syscall.tbl $(syshdr) - $(call quiet-command, sh $(syshdr) $< $@ $(TARGET_SYSTBL_ABI),"GEN","$@") diff --git a/linux-user/xtensa/meson.build b/linux-user/xtensa/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..de77f3b66a9c3bbff19b60b1139b021acd001809 --- /dev/null +++ b/linux-user/xtensa/meson.build @@ -0,0 +1,5 @@ +syscall_nr_generators += { + 'xtensa': generator(sh, + arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ], + output: '@BASENAME@_nr.h') +} diff --git a/linux-user/xtensa/syscall.tbl b/linux-user/xtensa/syscall.tbl index 85a9ab1bc04dab5cae943dbe168aedfe452fa6de..6276e3c2d3fc0d82ac59907e43c3895f42f54a74 100644 --- a/linux-user/xtensa/syscall.tbl +++ b/linux-user/xtensa/syscall.tbl @@ -222,7 +222,7 @@ 204 common quotactl sys_quotactl # 205 was old nfsservctl 205 common nfsservctl sys_ni_syscall -206 common _sysctl sys_sysctl +206 common _sysctl sys_ni_syscall 207 common bdflush sys_bdflush 208 common uname sys_newuname 209 common sysinfo sys_sysinfo @@ -406,5 +406,7 @@ 433 common fspick sys_fspick 434 common pidfd_open sys_pidfd_open 435 common clone3 sys_clone3 +436 common close_range sys_close_range 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd +439 common faccessat2 sys_faccessat2 diff --git a/linux-user/xtensa/target_syscall.h b/linux-user/xtensa/target_syscall.h index 3866dad8493028ee9f527d916909141d0221972f..afc86a153fc04a4113a7324118d3f78b29bb6917 100644 --- a/linux-user/xtensa/target_syscall.h +++ b/linux-user/xtensa/target_syscall.h @@ -43,7 +43,8 @@ struct target_pt_regs { xtensa_reg_t areg[16]; }; -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 #endif diff --git a/linux-user/xtensa/termbits.h b/linux-user/xtensa/termbits.h index d1e09e61a69b3014c21c2b14573b688bb865f613..ce6fb081e355a32620189469dd24a4a3e643d3c0 100644 --- a/linux-user/xtensa/termbits.h +++ b/linux-user/xtensa/termbits.h @@ -15,40 +15,42 @@ #include -typedef unsigned char cc_t; -typedef unsigned int speed_t; -typedef unsigned int tcflag_t; - #define TARGET_NCCS 19 + +typedef unsigned char target_cc_t; /* cc_t */ +typedef unsigned int target_speed_t; /* speed_t */ +typedef unsigned int target_tcflag_t; /* tcflag_t */ + struct target_termios { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[TARGET_NCCS]; /* control characters */ + target_tcflag_t c_iflag; /* input mode flags */ + target_tcflag_t c_oflag; /* output mode flags */ + target_tcflag_t c_cflag; /* control mode flags */ + target_tcflag_t c_lflag; /* local mode flags */ + target_cc_t c_line; /* line discipline */ + target_cc_t c_cc[TARGET_NCCS]; /* control characters */ }; + struct target_termios2 { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[TARGET_NCCS]; /* control characters */ - speed_t c_ispeed; /* input speed */ - speed_t c_ospeed; /* output speed */ + target_tcflag_t c_iflag; /* input mode flags */ + target_tcflag_t c_oflag; /* output mode flags */ + target_tcflag_t c_cflag; /* control mode flags */ + target_tcflag_t c_lflag; /* local mode flags */ + target_cc_t c_line; /* line discipline */ + target_cc_t c_cc[TARGET_NCCS]; /* control characters */ + target_speed_t c_ispeed; /* input speed */ + target_speed_t c_ospeed; /* output speed */ }; struct target_ktermios { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[TARGET_NCCS]; /* control characters */ - speed_t c_ispeed; /* input speed */ - speed_t c_ospeed; /* output speed */ + target_tcflag_t c_iflag; /* input mode flags */ + target_tcflag_t c_oflag; /* output mode flags */ + target_tcflag_t c_cflag; /* control mode flags */ + target_tcflag_t c_lflag; /* local mode flags */ + target_cc_t c_line; /* line discipline */ + target_cc_t c_cc[TARGET_NCCS]; /* control characters */ + target_speed_t c_ispeed; /* input speed */ + target_speed_t c_ospeed; /* output speed */ }; /* c_cc characters */ @@ -195,6 +197,7 @@ struct target_ktermios { #define TARGET_FLUSHO 0010000 #define TARGET_PENDIN 0040000 #define TARGET_IEXTEN 0100000 +#define TARGET_EXTPROC 0200000 /* tcflow() and TCXONC use these */ diff --git a/memory_ldst.inc.c b/memory_ldst.c.inc similarity index 98% rename from memory_ldst.inc.c rename to memory_ldst.c.inc index c54aee4a951fcd4c0b00e23faf9224b42e8f0370..2fed2de18e4b625253ca02a535594cdebfbbca39 100644 --- a/memory_ldst.inc.c +++ b/memory_ldst.c.inc @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -42,6 +42,7 @@ static inline uint32_t glue(address_space_ldl_internal, SUFFIX)(ARG1_DECL, MO_32 | devend_memop(endian), attrs); } else { /* RAM case */ + fuzz_dma_read_cb(addr, 4, mr, false); ptr = qemu_map_ram_ptr(mr->ram_block, addr1); switch (endian) { case DEVICE_LITTLE_ENDIAN: @@ -110,6 +111,7 @@ static inline uint64_t glue(address_space_ldq_internal, SUFFIX)(ARG1_DECL, MO_64 | devend_memop(endian), attrs); } else { /* RAM case */ + fuzz_dma_read_cb(addr, 8, mr, false); ptr = qemu_map_ram_ptr(mr->ram_block, addr1); switch (endian) { case DEVICE_LITTLE_ENDIAN: @@ -175,6 +177,7 @@ uint32_t glue(address_space_ldub, SUFFIX)(ARG1_DECL, r = memory_region_dispatch_read(mr, addr1, &val, MO_8, attrs); } else { /* RAM case */ + fuzz_dma_read_cb(addr, 1, mr, false); ptr = qemu_map_ram_ptr(mr->ram_block, addr1); val = ldub_p(ptr); r = MEMTX_OK; @@ -212,6 +215,7 @@ static inline uint32_t glue(address_space_lduw_internal, SUFFIX)(ARG1_DECL, MO_16 | devend_memop(endian), attrs); } else { /* RAM case */ + fuzz_dma_read_cb(addr, 2, mr, false); ptr = qemu_map_ram_ptr(mr->ram_block, addr1); switch (endian) { case DEVICE_LITTLE_ENDIAN: diff --git a/meson b/meson new file mode 160000 index 0000000000000000000000000000000000000000..776acd2a805c9b42b4f0375150977df42130317f --- /dev/null +++ b/meson @@ -0,0 +1 @@ +Subproject commit 776acd2a805c9b42b4f0375150977df42130317f diff --git a/meson.build b/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..14728b77ab0ef81145b0de8dbdaf4b2fd522b2b2 --- /dev/null +++ b/meson.build @@ -0,0 +1,2233 @@ +project('qemu', ['c'], meson_version: '>=0.55.0', + default_options: ['warning_level=1', 'c_std=gnu99', 'cpp_std=gnu++11', 'b_colorout=auto'] + + (meson.version().version_compare('>=0.56.0') ? [ 'b_staticpic=false' ] : []), + version: run_command('head', meson.source_root() / 'VERSION').stdout().strip()) + +not_found = dependency('', required: false) +if meson.version().version_compare('>=0.56.0') + keyval = import('keyval') +else + keyval = import('unstable-keyval') +endif +ss = import('sourceset') +fs = import('fs') + +sh = find_program('sh') +cc = meson.get_compiler('c') +config_host = keyval.load(meson.current_build_dir() / 'config-host.mak') +enable_modules = 'CONFIG_MODULES' in config_host +enable_static = 'CONFIG_STATIC' in config_host + +# Temporary directory used for files created while +# configure runs. Since it is in the build directory +# we can safely blow away any previous version of it +# (and we need not jump through hoops to try to delete +# it when configure exits.) +tmpdir = meson.current_build_dir() / 'meson-private/temp' + +if get_option('qemu_suffix').startswith('/') + error('qemu_suffix cannot start with a /') +endif + +qemu_confdir = get_option('sysconfdir') / get_option('qemu_suffix') +qemu_datadir = get_option('datadir') / get_option('qemu_suffix') +qemu_docdir = get_option('docdir') / get_option('qemu_suffix') +qemu_moddir = get_option('libdir') / get_option('qemu_suffix') + +qemu_desktopdir = get_option('datadir') / 'applications' +qemu_icondir = get_option('datadir') / 'icons' + +config_host_data = configuration_data() +genh = [] + +target_dirs = config_host['TARGET_DIRS'].split() +have_user = false +have_system = false +foreach target : target_dirs + have_user = have_user or target.endswith('-user') + have_system = have_system or target.endswith('-softmmu') +endforeach +have_tools = 'CONFIG_TOOLS' in config_host +have_block = have_system or have_tools + +python = import('python').find_installation() + +supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux'] +supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 'x86_64', + 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64'] + +cpu = host_machine.cpu_family() +targetos = host_machine.system() + +if cpu in ['x86', 'x86_64'] + kvm_targets = ['i386-softmmu', 'x86_64-softmmu'] +elif cpu == 'aarch64' + kvm_targets = ['aarch64-softmmu'] +elif cpu == 's390x' + kvm_targets = ['s390x-softmmu'] +elif cpu in ['ppc', 'ppc64'] + kvm_targets = ['ppc-softmmu', 'ppc64-softmmu'] +elif cpu in ['mips', 'mips64'] + kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu'] +elif cpu in ['riscv32', 'riscv64'] + kvm_targets = ['riscv32-softmmu', 'riscv64-softmmu'] +else + kvm_targets = [] +endif + +accelerator_targets = { 'CONFIG_KVM': kvm_targets } +if cpu in ['x86', 'x86_64', 'arm', 'aarch64'] + # i368 emulator provides xenpv machine type for multiple architectures + accelerator_targets += { + 'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu'], + } +endif +if cpu in ['x86', 'x86_64'] + accelerator_targets += { + 'CONFIG_HAX': ['i386-softmmu', 'x86_64-softmmu'], + 'CONFIG_HVF': ['x86_64-softmmu'], + 'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'], + } +endif + +################## +# Compiler flags # +################## + +# Specify linker-script with add_project_link_arguments so that it is not placed +# within a linker --start-group/--end-group pair +if 'CONFIG_FUZZ' in config_host + add_project_link_arguments(['-Wl,-T,', + (meson.current_source_dir() / 'tests/qtest/fuzz/fork_fuzz.ld')], + native: false, language: ['c', 'cpp', 'objc']) +endif + +add_project_arguments(config_host['QEMU_CFLAGS'].split(), + native: false, language: ['c', 'objc']) +add_project_arguments(config_host['QEMU_CXXFLAGS'].split(), + native: false, language: 'cpp') +add_project_link_arguments(config_host['QEMU_LDFLAGS'].split(), + native: false, language: ['c', 'cpp', 'objc']) + +if targetos == 'linux' + add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers', + '-isystem', 'linux-headers', + language: ['c', 'cpp']) +endif + +if 'CONFIG_TCG_INTERPRETER' in config_host + tcg_arch = 'tci' +elif config_host['ARCH'] == 'sparc64' + tcg_arch = 'sparc' +elif config_host['ARCH'] == 's390x' + tcg_arch = 's390' +elif config_host['ARCH'] in ['x86_64', 'x32'] + tcg_arch = 'i386' +elif config_host['ARCH'] == 'ppc64' + tcg_arch = 'ppc' +elif config_host['ARCH'] in ['riscv32', 'riscv64'] + tcg_arch = 'riscv' +else + tcg_arch = config_host['ARCH'] +endif +add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch, + '-iquote', '.', + '-iquote', meson.current_source_dir(), + '-iquote', meson.current_source_dir() / 'accel/tcg', + '-iquote', meson.current_source_dir() / 'include', + '-iquote', meson.current_source_dir() / 'disas/libvixl', + language: ['c', 'cpp', 'objc']) + +link_language = meson.get_external_property('link_language', 'cpp') +if link_language == 'cpp' + add_languages('cpp', required: true, native: false) +endif +if host_machine.system() == 'darwin' + add_languages('objc', required: false, native: false) +endif + +sparse = find_program('cgcc', required: get_option('sparse')) +if sparse.found() + run_target('sparse', + command: [find_program('scripts/check_sparse.py'), + 'compile_commands.json', sparse.full_path(), '-Wbitwise', + '-Wno-transparent-union', '-Wno-old-initializer', + '-Wno-non-pointer-null']) +endif + +########################################### +# Target-specific checks and dependencies # +########################################### + +if targetos != 'linux' and get_option('mpath').enabled() + error('Multipath is supported only on Linux') +endif + +m = cc.find_library('m', required: false) +util = cc.find_library('util', required: false) +winmm = [] +socket = [] +version_res = [] +coref = [] +iokit = [] +emulator_link_args = [] +cocoa = not_found +hvf = not_found +if targetos == 'windows' + socket = cc.find_library('ws2_32') + winmm = cc.find_library('winmm') + + win = import('windows') + version_res = win.compile_resources('version.rc', + depend_files: files('pc-bios/qemu-nsis.ico'), + include_directories: include_directories('.')) +elif targetos == 'darwin' + coref = dependency('appleframeworks', modules: 'CoreFoundation') + iokit = dependency('appleframeworks', modules: 'IOKit') + cocoa = dependency('appleframeworks', modules: 'Cocoa', required: get_option('cocoa')) +elif targetos == 'sunos' + socket = [cc.find_library('socket'), + cc.find_library('nsl'), + cc.find_library('resolv')] +elif targetos == 'haiku' + socket = [cc.find_library('posix_error_mapper'), + cc.find_library('network'), + cc.find_library('bsd')] +elif targetos == 'openbsd' + if not get_option('tcg').disabled() and target_dirs.length() > 0 + # Disable OpenBSD W^X if available + emulator_link_args = cc.get_supported_link_arguments('-Wl,-z,wxneeded') + endif +endif + +accelerators = [] +if not get_option('kvm').disabled() and targetos == 'linux' + accelerators += 'CONFIG_KVM' +endif +if not get_option('xen').disabled() and 'CONFIG_XEN_BACKEND' in config_host + accelerators += 'CONFIG_XEN' + have_xen_pci_passthrough = not get_option('xen_pci_passthrough').disabled() and targetos == 'linux' +else + have_xen_pci_passthrough = false +endif +if not get_option('whpx').disabled() and targetos == 'windows' + if get_option('whpx').enabled() and host_machine.cpu() != 'x86_64' + error('WHPX requires 64-bit host') + elif cc.has_header('WinHvPlatform.h', required: get_option('whpx')) and \ + cc.has_header('WinHvEmulation.h', required: get_option('whpx')) + accelerators += 'CONFIG_WHPX' + endif +endif +if not get_option('hvf').disabled() + hvf = dependency('appleframeworks', modules: 'Hypervisor', + required: get_option('hvf')) + if hvf.found() + accelerators += 'CONFIG_HVF' + endif +endif +if not get_option('hax').disabled() + if get_option('hax').enabled() or targetos in ['windows', 'darwin', 'netbsd'] + accelerators += 'CONFIG_HAX' + endif +endif +if not get_option('tcg').disabled() + if cpu not in supported_cpus + if 'CONFIG_TCG_INTERPRETER' in config_host + warning('Unsupported CPU @0@, will use TCG with TCI (experimental)'.format(cpu)) + else + error('Unsupported CPU @0@, try --enable-tcg-interpreter'.format(cpu)) + endif + endif + accelerators += 'CONFIG_TCG' + config_host += { 'CONFIG_TCG': 'y' } +endif + +if 'CONFIG_KVM' not in accelerators and get_option('kvm').enabled() + error('KVM not available on this platform') +endif +if 'CONFIG_HVF' not in accelerators and get_option('hvf').enabled() + error('HVF not available on this platform') +endif +if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled() + error('WHPX not available on this platform') +endif +if not have_xen_pci_passthrough and get_option('xen_pci_passthrough').enabled() + if 'CONFIG_XEN' in accelerators + error('Xen PCI passthrough not available on this platform') + else + error('Xen PCI passthrough requested but Xen not enabled') + endif +endif +if not cocoa.found() and get_option('cocoa').enabled() + error('Cocoa not available on this platform') +endif + +################ +# Dependencies # +################ + +# The path to glib.h is added to all compilation commands. This was +# grandfathered in from the QEMU Makefiles. +add_project_arguments(config_host['GLIB_CFLAGS'].split(), + native: false, language: ['c', 'cpp', 'objc']) +glib = declare_dependency(link_args: config_host['GLIB_LIBS'].split()) +gio = not_found +if 'CONFIG_GIO' in config_host + gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(), + link_args: config_host['GIO_LIBS'].split()) +endif +lttng = not_found +if 'CONFIG_TRACE_UST' in config_host + lttng = declare_dependency(link_args: config_host['LTTNG_UST_LIBS'].split()) +endif +urcubp = not_found +if 'CONFIG_TRACE_UST' in config_host + urcubp = declare_dependency(link_args: config_host['URCU_BP_LIBS'].split()) +endif +gcrypt = not_found +if 'CONFIG_GCRYPT' in config_host + gcrypt = declare_dependency(compile_args: config_host['GCRYPT_CFLAGS'].split(), + link_args: config_host['GCRYPT_LIBS'].split()) +endif +nettle = not_found +if 'CONFIG_NETTLE' in config_host + nettle = declare_dependency(compile_args: config_host['NETTLE_CFLAGS'].split(), + link_args: config_host['NETTLE_LIBS'].split()) +endif +gnutls = not_found +if 'CONFIG_GNUTLS' in config_host + gnutls = declare_dependency(compile_args: config_host['GNUTLS_CFLAGS'].split(), + link_args: config_host['GNUTLS_LIBS'].split()) +endif +pixman = not_found +if have_system or have_tools + pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8', + method: 'pkg-config', static: enable_static) +endif +pam = not_found +if 'CONFIG_AUTH_PAM' in config_host + pam = cc.find_library('pam') +endif +libaio = cc.find_library('aio', required: false) +zlib = dependency('zlib', required: true, static: enable_static) +linux_io_uring = not_found +if 'CONFIG_LINUX_IO_URING' in config_host + linux_io_uring = declare_dependency(compile_args: config_host['LINUX_IO_URING_CFLAGS'].split(), + link_args: config_host['LINUX_IO_URING_LIBS'].split()) +endif +libxml2 = not_found +if 'CONFIG_LIBXML2' in config_host + libxml2 = declare_dependency(compile_args: config_host['LIBXML2_CFLAGS'].split(), + link_args: config_host['LIBXML2_LIBS'].split()) +endif +libnfs = not_found +if 'CONFIG_LIBNFS' in config_host + libnfs = declare_dependency(link_args: config_host['LIBNFS_LIBS'].split()) +endif +libattr = not_found +if 'CONFIG_ATTR' in config_host + libattr = declare_dependency(link_args: config_host['LIBATTR_LIBS'].split()) +endif +seccomp = not_found +if 'CONFIG_SECCOMP' in config_host + seccomp = declare_dependency(compile_args: config_host['SECCOMP_CFLAGS'].split(), + link_args: config_host['SECCOMP_LIBS'].split()) +endif +libcap_ng = not_found +if 'CONFIG_LIBCAP_NG' in config_host + libcap_ng = declare_dependency(link_args: config_host['LIBCAP_NG_LIBS'].split()) +endif +if get_option('xkbcommon').auto() and not have_system and not have_tools + xkbcommon = not_found +else + xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'), + method: 'pkg-config', static: enable_static) +endif +vde = not_found +if config_host.has_key('CONFIG_VDE') + vde = declare_dependency(link_args: config_host['VDE_LIBS'].split()) +endif +pulse = not_found +if 'CONFIG_LIBPULSE' in config_host + pulse = declare_dependency(compile_args: config_host['PULSE_CFLAGS'].split(), + link_args: config_host['PULSE_LIBS'].split()) +endif +alsa = not_found +if 'CONFIG_ALSA' in config_host + alsa = declare_dependency(compile_args: config_host['ALSA_CFLAGS'].split(), + link_args: config_host['ALSA_LIBS'].split()) +endif +jack = not_found +if 'CONFIG_LIBJACK' in config_host + jack = declare_dependency(link_args: config_host['JACK_LIBS'].split()) +endif +spice = not_found +spice_headers = not_found +if 'CONFIG_SPICE' in config_host + spice = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split(), + link_args: config_host['SPICE_LIBS'].split()) + spice_headers = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split()) +endif +rt = cc.find_library('rt', required: false) +libdl = not_found +if 'CONFIG_PLUGIN' in config_host + libdl = cc.find_library('dl', required: true) +endif +libiscsi = not_found +if 'CONFIG_LIBISCSI' in config_host + libiscsi = declare_dependency(compile_args: config_host['LIBISCSI_CFLAGS'].split(), + link_args: config_host['LIBISCSI_LIBS'].split()) +endif +zstd = not_found +if 'CONFIG_ZSTD' in config_host + zstd = declare_dependency(compile_args: config_host['ZSTD_CFLAGS'].split(), + link_args: config_host['ZSTD_LIBS'].split()) +endif +gbm = not_found +if 'CONFIG_GBM' in config_host + gbm = declare_dependency(compile_args: config_host['GBM_CFLAGS'].split(), + link_args: config_host['GBM_LIBS'].split()) +endif +virgl = not_found +if 'CONFIG_VIRGL' in config_host + virgl = declare_dependency(compile_args: config_host['VIRGL_CFLAGS'].split(), + link_args: config_host['VIRGL_LIBS'].split()) +endif +curl = not_found +if 'CONFIG_CURL' in config_host + curl = declare_dependency(compile_args: config_host['CURL_CFLAGS'].split(), + link_args: config_host['CURL_LIBS'].split()) +endif +libudev = not_found +if targetos == 'linux' and (have_system or have_tools) + libudev = dependency('libudev', + required: get_option('libudev'), + static: enable_static) +endif + +mpathlibs = [libudev] +mpathpersist = not_found +mpathpersist_new_api = false +if targetos == 'linux' and have_tools and not get_option('mpath').disabled() + mpath_test_source_new = ''' + #include + #include + unsigned mpath_mx_alloc_len = 1024; + int logsink; + static struct config *multipath_conf; + extern struct udev *udev; + extern struct config *get_multipath_config(void); + extern void put_multipath_config(struct config *conf); + struct udev *udev; + struct config *get_multipath_config(void) { return multipath_conf; } + void put_multipath_config(struct config *conf) { } + int main(void) { + udev = udev_new(); + multipath_conf = mpath_lib_init(); + return 0; + }''' + mpath_test_source_old = ''' + #include + #include + unsigned mpath_mx_alloc_len = 1024; + int logsink; + int main(void) { + struct udev *udev = udev_new(); + mpath_lib_init(udev); + return 0; + }''' + libmpathpersist = cc.find_library('mpathpersist', + required: get_option('mpath'), + static: enable_static) + if libmpathpersist.found() + mpathlibs += libmpathpersist + if enable_static + mpathlibs += cc.find_library('devmapper', + required: get_option('mpath'), + static: enable_static) + endif + mpathlibs += cc.find_library('multipath', + required: get_option('mpath'), + static: enable_static) + foreach lib: mpathlibs + if not lib.found() + mpathlibs = [] + break + endif + endforeach + if mpathlibs.length() == 0 + msg = 'Dependencies missing for libmpathpersist' + elif cc.links(mpath_test_source_new, dependencies: mpathlibs) + mpathpersist = declare_dependency(dependencies: mpathlibs) + mpathpersist_new_api = true + elif cc.links(mpath_test_source_old, dependencies: mpathlibs) + mpathpersist = declare_dependency(dependencies: mpathlibs) + else + msg = 'Cannot detect libmpathpersist API' + endif + if not mpathpersist.found() + if get_option('mpath').enabled() + error(msg) + else + warning(msg + ', disabling') + endif + endif + endif +endif + +iconv = not_found +curses = not_found +if have_system and not get_option('curses').disabled() + curses_test = ''' + #include + #include + #include + int main(void) { + wchar_t wch = L'w'; + setlocale(LC_ALL, ""); + resize_term(0, 0); + addwstr(L"wide chars\n"); + addnwstr(&wch, 1); + add_wch(WACS_DEGREE); + return 0; + }''' + + curses_dep_list = targetos == 'windows' ? ['ncurses', 'ncursesw'] : ['ncursesw'] + foreach curses_dep : curses_dep_list + if not curses.found() + curses = dependency(curses_dep, + required: false, + method: 'pkg-config', + static: enable_static) + endif + endforeach + msg = get_option('curses').enabled() ? 'curses library not found' : '' + if curses.found() + if cc.links(curses_test, dependencies: [curses]) + curses = declare_dependency(compile_args: '-DNCURSES_WIDECHAR', dependencies: [curses]) + else + msg = 'curses package not usable' + curses = not_found + endif + endif + if not curses.found() + curses_compile_args = ['-DNCURSES_WIDECHAR'] + has_curses_h = cc.has_header('curses.h', args: curses_compile_args) + if targetos != 'windows' and not has_curses_h + message('Trying with /usr/include/ncursesw') + curses_compile_args += ['-I/usr/include/ncursesw'] + has_curses_h = cc.has_header('curses.h', args: curses_compile_args) + endif + if has_curses_h + curses_libname_list = (targetos == 'windows' ? ['pdcurses'] : ['ncursesw', 'cursesw']) + foreach curses_libname : curses_libname_list + libcurses = cc.find_library(curses_libname, + required: false, + static: enable_static) + if libcurses.found() + if cc.links(curses_test, args: curses_compile_args, dependencies: libcurses) + curses = declare_dependency(compile_args: curses_compile_args, + dependencies: [libcurses]) + break + else + msg = 'curses library not usable' + endif + endif + endforeach + endif + endif + if not get_option('iconv').disabled() + foreach link_args : [ ['-liconv'], [] ] + # Programs will be linked with glib and this will bring in libiconv on FreeBSD. + # We need to use libiconv if available because mixing libiconv's headers with + # the system libc does not work. + # However, without adding glib to the dependencies -L/usr/local/lib will not be + # included in the command line and libiconv will not be found. + if cc.links(''' + #include + int main(void) { + iconv_t conv = iconv_open("WCHAR_T", "UCS-2"); + return conv != (iconv_t) -1; + }''', args: config_host['GLIB_CFLAGS'].split() + config_host['GLIB_LIBS'].split() + link_args) + iconv = declare_dependency(link_args: link_args, dependencies: glib) + break + endif + endforeach + endif + if curses.found() and not iconv.found() + if get_option('iconv').enabled() + error('iconv not available') + endif + msg = 'iconv required for curses UI but not available' + curses = not_found + endif + if not curses.found() and msg != '' + if get_option('curses').enabled() + error(msg) + else + warning(msg + ', disabling') + endif + endif +endif + +brlapi = not_found +if 'CONFIG_BRLAPI' in config_host + brlapi = declare_dependency(link_args: config_host['BRLAPI_LIBS'].split()) +endif + +sdl = not_found +if have_system + sdl = dependency('sdl2', required: get_option('sdl'), static: enable_static) + sdl_image = not_found +endif +if sdl.found() + # work around 2.0.8 bug + sdl = declare_dependency(compile_args: '-Wno-undef', + dependencies: sdl) + sdl_image = dependency('SDL2_image', required: get_option('sdl_image'), + method: 'pkg-config', static: enable_static) +else + if get_option('sdl_image').enabled() + error('sdl-image required, but SDL was @0@'.format( + get_option('sdl').disabled() ? 'disabled' : 'not found')) + endif + sdl_image = not_found +endif + +rbd = not_found +if 'CONFIG_RBD' in config_host + rbd = declare_dependency(link_args: config_host['RBD_LIBS'].split()) +endif +glusterfs = not_found +if 'CONFIG_GLUSTERFS' in config_host + glusterfs = declare_dependency(compile_args: config_host['GLUSTERFS_CFLAGS'].split(), + link_args: config_host['GLUSTERFS_LIBS'].split()) +endif +libssh = not_found +if 'CONFIG_LIBSSH' in config_host + libssh = declare_dependency(compile_args: config_host['LIBSSH_CFLAGS'].split(), + link_args: config_host['LIBSSH_LIBS'].split()) +endif +libbzip2 = not_found +if 'CONFIG_BZIP2' in config_host + libbzip2 = declare_dependency(link_args: config_host['BZIP2_LIBS'].split()) +endif +liblzfse = not_found +if 'CONFIG_LZFSE' in config_host + liblzfse = declare_dependency(link_args: config_host['LZFSE_LIBS'].split()) +endif +oss = not_found +if 'CONFIG_AUDIO_OSS' in config_host + oss = declare_dependency(link_args: config_host['OSS_LIBS'].split()) +endif +dsound = not_found +if 'CONFIG_AUDIO_DSOUND' in config_host + dsound = declare_dependency(link_args: config_host['DSOUND_LIBS'].split()) +endif +coreaudio = not_found +if 'CONFIG_AUDIO_COREAUDIO' in config_host + coreaudio = declare_dependency(link_args: config_host['COREAUDIO_LIBS'].split()) +endif +opengl = not_found +if 'CONFIG_OPENGL' in config_host + opengl = declare_dependency(compile_args: config_host['OPENGL_CFLAGS'].split(), + link_args: config_host['OPENGL_LIBS'].split()) +endif +gtk = not_found +if 'CONFIG_GTK' in config_host + gtk = declare_dependency(compile_args: config_host['GTK_CFLAGS'].split(), + link_args: config_host['GTK_LIBS'].split()) +endif +vte = not_found +if 'CONFIG_VTE' in config_host + vte = declare_dependency(compile_args: config_host['VTE_CFLAGS'].split(), + link_args: config_host['VTE_LIBS'].split()) +endif +x11 = not_found +if 'CONFIG_X11' in config_host + x11 = declare_dependency(compile_args: config_host['X11_CFLAGS'].split(), + link_args: config_host['X11_LIBS'].split()) +endif +vnc = not_found +png = not_found +jpeg = not_found +sasl = not_found +if get_option('vnc').enabled() + vnc = declare_dependency() # dummy dependency + png = dependency('libpng', required: get_option('vnc_png'), + method: 'pkg-config', static: enable_static) + jpeg = dependency('libjpeg', required: get_option('vnc_jpeg'), + method: 'pkg-config', static: enable_static) + sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'], + required: get_option('vnc_sasl'), + static: enable_static) + if sasl.found() + sasl = declare_dependency(dependencies: sasl, + compile_args: '-DSTRUCT_IOVEC_DEFINED') + endif +endif +snappy = not_found +if 'CONFIG_SNAPPY' in config_host + snappy = declare_dependency(link_args: config_host['SNAPPY_LIBS'].split()) +endif +lzo = not_found +if 'CONFIG_LZO' in config_host + lzo = declare_dependency(link_args: config_host['LZO_LIBS'].split()) +endif +rdma = not_found +if 'CONFIG_RDMA' in config_host + rdma = declare_dependency(link_args: config_host['RDMA_LIBS'].split()) +endif +numa = not_found +if 'CONFIG_NUMA' in config_host + numa = declare_dependency(link_args: config_host['NUMA_LIBS'].split()) +endif +xen = not_found +if 'CONFIG_XEN_BACKEND' in config_host + xen = declare_dependency(compile_args: config_host['XEN_CFLAGS'].split(), + link_args: config_host['XEN_LIBS'].split()) +endif +cacard = not_found +if 'CONFIG_SMARTCARD' in config_host + cacard = declare_dependency(compile_args: config_host['SMARTCARD_CFLAGS'].split(), + link_args: config_host['SMARTCARD_LIBS'].split()) +endif +u2f = not_found +if have_system + u2f = dependency('u2f-emu', required: get_option('u2f'), + method: 'pkg-config', + static: enable_static) +endif +usbredir = not_found +if 'CONFIG_USB_REDIR' in config_host + usbredir = declare_dependency(compile_args: config_host['USB_REDIR_CFLAGS'].split(), + link_args: config_host['USB_REDIR_LIBS'].split()) +endif +libusb = not_found +if 'CONFIG_USB_LIBUSB' in config_host + libusb = declare_dependency(compile_args: config_host['LIBUSB_CFLAGS'].split(), + link_args: config_host['LIBUSB_LIBS'].split()) +endif +libpmem = not_found +if 'CONFIG_LIBPMEM' in config_host + libpmem = declare_dependency(compile_args: config_host['LIBPMEM_CFLAGS'].split(), + link_args: config_host['LIBPMEM_LIBS'].split()) +endif +libdaxctl = not_found +if 'CONFIG_LIBDAXCTL' in config_host + libdaxctl = declare_dependency(link_args: config_host['LIBDAXCTL_LIBS'].split()) +endif +tasn1 = not_found +if 'CONFIG_TASN1' in config_host + tasn1 = declare_dependency(compile_args: config_host['TASN1_CFLAGS'].split(), + link_args: config_host['TASN1_LIBS'].split()) +endif +keyutils = dependency('libkeyutils', required: false, + method: 'pkg-config', static: enable_static) + +has_gettid = cc.has_function('gettid') + +# Malloc tests + +malloc = [] +if get_option('malloc') == 'system' + has_malloc_trim = \ + not get_option('malloc_trim').disabled() and \ + cc.links('''#include + int main(void) { malloc_trim(0); return 0; }''') +else + has_malloc_trim = false + malloc = cc.find_library(get_option('malloc'), required: true) +endif +if not has_malloc_trim and get_option('malloc_trim').enabled() + if get_option('malloc') == 'system' + error('malloc_trim not available on this platform.') + else + error('malloc_trim not available with non-libc memory allocator') + endif +endif + +# Check whether the glibc provides statx() + +statx_test = ''' + #ifndef _GNU_SOURCE + #define _GNU_SOURCE + #endif + #include + int main(void) { + struct statx statxbuf; + statx(0, "", 0, STATX_BASIC_STATS, &statxbuf); + return 0; + }''' + +has_statx = cc.links(statx_test) + +have_vhost_user_blk_server = (targetos == 'linux' and + 'CONFIG_VHOST_USER' in config_host) + +if get_option('vhost_user_blk_server').enabled() + if targetos != 'linux' + error('vhost_user_blk_server requires linux') + elif 'CONFIG_VHOST_USER' not in config_host + error('vhost_user_blk_server requires vhost-user support') + endif +elif get_option('vhost_user_blk_server').disabled() or not have_system + have_vhost_user_blk_server = false +endif + +################# +# config-host.h # +################# + +config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir')) +config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix')) +config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir) +config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir) +config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir) +config_host_data.set_quoted('CONFIG_QEMU_FIRMWAREPATH', get_option('qemu_firmwarepath')) +config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir')) +config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir) +config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir')) +config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir')) +config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir) +config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir')) + +config_host_data.set('CONFIG_COCOA', cocoa.found()) +config_host_data.set('CONFIG_LIBUDEV', libudev.found()) +config_host_data.set('CONFIG_MPATH', mpathpersist.found()) +config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api) +config_host_data.set('CONFIG_CURSES', curses.found()) +config_host_data.set('CONFIG_SDL', sdl.found()) +config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found()) +config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server) +config_host_data.set('CONFIG_VNC', vnc.found()) +config_host_data.set('CONFIG_VNC_JPEG', jpeg.found()) +config_host_data.set('CONFIG_VNC_PNG', png.found()) +config_host_data.set('CONFIG_VNC_SASL', sasl.found()) +config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found()) +config_host_data.set('CONFIG_KEYUTILS', keyutils.found()) +config_host_data.set('CONFIG_GETTID', has_gettid) +config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim) +config_host_data.set('CONFIG_STATX', has_statx) +config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version())) +config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0]) +config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1]) +config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2]) + +config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h')) + +ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target +arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST'] +strings = ['HOST_DSOSUF', 'CONFIG_IASL'] +foreach k, v: config_host + if ignored.contains(k) + # do nothing + elif arrays.contains(k) + if v != '' + v = '"' + '", "'.join(v.split()) + '", ' + endif + config_host_data.set(k, v) + elif k == 'ARCH' + config_host_data.set('HOST_' + v.to_upper(), 1) + elif strings.contains(k) + if not k.startswith('CONFIG_') + k = 'CONFIG_' + k.to_upper() + endif + config_host_data.set_quoted(k, v) + elif k.startswith('CONFIG_') or k.startswith('HAVE_') or k.startswith('HOST_') + config_host_data.set(k, v == 'y' ? 1 : v) + endif +endforeach + +######################## +# Target configuration # +######################## + +minikconf = find_program('scripts/minikconf.py') +config_all = {} +config_all_devices = {} +config_all_disas = {} +config_devices_mak_list = [] +config_devices_h = {} +config_target_h = {} +config_target_mak = {} + +disassemblers = { + 'alpha' : ['CONFIG_ALPHA_DIS'], + 'arm' : ['CONFIG_ARM_DIS'], + 'avr' : ['CONFIG_AVR_DIS'], + 'cris' : ['CONFIG_CRIS_DIS'], + 'hppa' : ['CONFIG_HPPA_DIS'], + 'i386' : ['CONFIG_I386_DIS'], + 'x86_64' : ['CONFIG_I386_DIS'], + 'x32' : ['CONFIG_I386_DIS'], + 'lm32' : ['CONFIG_LM32_DIS'], + 'm68k' : ['CONFIG_M68K_DIS'], + 'microblaze' : ['CONFIG_MICROBLAZE_DIS'], + 'mips' : ['CONFIG_MIPS_DIS'], + 'moxie' : ['CONFIG_MOXIE_DIS'], + 'nios2' : ['CONFIG_NIOS2_DIS'], + 'or1k' : ['CONFIG_OPENRISC_DIS'], + 'ppc' : ['CONFIG_PPC_DIS'], + 'riscv' : ['CONFIG_RISCV_DIS'], + 'rx' : ['CONFIG_RX_DIS'], + 's390' : ['CONFIG_S390_DIS'], + 'sh4' : ['CONFIG_SH4_DIS'], + 'sparc' : ['CONFIG_SPARC_DIS'], + 'xtensa' : ['CONFIG_XTENSA_DIS'], +} +if link_language == 'cpp' + disassemblers += { + 'aarch64' : [ 'CONFIG_ARM_A64_DIS'], + 'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'], + 'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'], + } +endif + +kconfig_external_symbols = [ + 'CONFIG_KVM', + 'CONFIG_XEN', + 'CONFIG_TPM', + 'CONFIG_SPICE', + 'CONFIG_IVSHMEM', + 'CONFIG_OPENGL', + 'CONFIG_X11', + 'CONFIG_VHOST_USER', + 'CONFIG_VHOST_VDPA', + 'CONFIG_VHOST_KERNEL', + 'CONFIG_VIRTFS', + 'CONFIG_LINUX', + 'CONFIG_PVRDMA', +] +ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ] + +default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host +actual_target_dirs = [] +fdt_required = [] +foreach target : target_dirs + config_target = { 'TARGET_NAME': target.split('-')[0] } + if target.endswith('linux-user') + if targetos != 'linux' + if default_targets + continue + endif + error('Target @0@ is only available on a Linux host'.format(target)) + endif + config_target += { 'CONFIG_LINUX_USER': 'y' } + elif target.endswith('bsd-user') + if 'CONFIG_BSD' not in config_host + if default_targets + continue + endif + error('Target @0@ is only available on a BSD host'.format(target)) + endif + config_target += { 'CONFIG_BSD_USER': 'y' } + elif target.endswith('softmmu') + config_target += { 'CONFIG_SOFTMMU': 'y' } + endif + if target.endswith('-user') + config_target += { + 'CONFIG_USER_ONLY': 'y', + 'CONFIG_QEMU_INTERP_PREFIX': + config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME']) + } + endif + + have_accel = false + foreach sym: accelerators + if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, []) + config_target += { sym: 'y' } + config_all += { sym: 'y' } + if sym == 'CONFIG_XEN' and have_xen_pci_passthrough + config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' } + endif + have_accel = true + endif + endforeach + if not have_accel + if default_targets + continue + endif + error('No accelerator available for target @0@'.format(target)) + endif + + actual_target_dirs += target + config_target += keyval.load('default-configs/targets' / target + '.mak') + config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' } + + if 'TARGET_NEED_FDT' in config_target + fdt_required += target + endif + + # Add default keys + if 'TARGET_BASE_ARCH' not in config_target + config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']} + endif + if 'TARGET_ABI_DIR' not in config_target + config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']} + endif + + foreach k, v: disassemblers + if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k) + foreach sym: v + config_target += { sym: 'y' } + config_all_disas += { sym: 'y' } + endforeach + endif + endforeach + + config_target_data = configuration_data() + foreach k, v: config_target + if not k.startswith('TARGET_') and not k.startswith('CONFIG_') + # do nothing + elif ignored.contains(k) + # do nothing + elif k == 'TARGET_BASE_ARCH' + # Note that TARGET_BASE_ARCH ends up in config-target.h but it is + # not used to select files from sourcesets. + config_target_data.set('TARGET_' + v.to_upper(), 1) + elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX' + config_target_data.set_quoted(k, v) + elif v == 'y' + config_target_data.set(k, 1) + else + config_target_data.set(k, v) + endif + endforeach + config_target_h += {target: configure_file(output: target + '-config-target.h', + configuration: config_target_data)} + + if target.endswith('-softmmu') + base_kconfig = [] + foreach sym : kconfig_external_symbols + if sym in config_target or sym in config_host + base_kconfig += '@0@=y'.format(sym) + endif + endforeach + + config_devices_mak = target + '-config-devices.mak' + config_devices_mak = configure_file( + input: ['default-configs/devices' / target + '.mak', 'Kconfig'], + output: config_devices_mak, + depfile: config_devices_mak + '.d', + capture: true, + command: [minikconf, config_host['CONFIG_MINIKCONF_MODE'], + config_devices_mak, '@DEPFILE@', '@INPUT@', + base_kconfig]) + + config_devices_data = configuration_data() + config_devices = keyval.load(config_devices_mak) + foreach k, v: config_devices + config_devices_data.set(k, 1) + endforeach + config_devices_mak_list += config_devices_mak + config_devices_h += {target: configure_file(output: target + '-config-devices.h', + configuration: config_devices_data)} + config_target += config_devices + config_all_devices += config_devices + endif + config_target_mak += {target: config_target} +endforeach +target_dirs = actual_target_dirs + +# This configuration is used to build files that are shared by +# multiple binaries, and then extracted out of the "common" +# static_library target. +# +# We do not use all_sources()/all_dependencies(), because it would +# build literally all source files, including devices only used by +# targets that are not built for this compilation. The CONFIG_ALL +# pseudo symbol replaces it. + +config_all += config_all_devices +config_all += config_host +config_all += config_all_disas +config_all += { + 'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'), + 'CONFIG_SOFTMMU': have_system, + 'CONFIG_USER_ONLY': have_user, + 'CONFIG_ALL': true, +} + +############## +# Submodules # +############## + +capstone = not_found +capstone_opt = get_option('capstone') +if capstone_opt in ['enabled', 'auto', 'system'] + have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile') + capstone = dependency('capstone', version: '>=4.0', + static: enable_static, method: 'pkg-config', + required: capstone_opt == 'system' or + capstone_opt == 'enabled' and not have_internal) + if capstone.found() + capstone_opt = 'system' + elif have_internal + capstone_opt = 'internal' + else + capstone_opt = 'disabled' + endif +endif +if capstone_opt == 'internal' + capstone_data = configuration_data() + capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1') + + capstone_files = files( + 'capstone/cs.c', + 'capstone/MCInst.c', + 'capstone/MCInstrDesc.c', + 'capstone/MCRegisterInfo.c', + 'capstone/SStream.c', + 'capstone/utils.c' + ) + + if 'CONFIG_ARM_DIS' in config_all_disas + capstone_data.set('CAPSTONE_HAS_ARM', '1') + capstone_files += files( + 'capstone/arch/ARM/ARMDisassembler.c', + 'capstone/arch/ARM/ARMInstPrinter.c', + 'capstone/arch/ARM/ARMMapping.c', + 'capstone/arch/ARM/ARMModule.c' + ) + endif + + # FIXME: This config entry currently depends on a c++ compiler. + # Which is needed for building libvixl, but not for capstone. + if 'CONFIG_ARM_A64_DIS' in config_all_disas + capstone_data.set('CAPSTONE_HAS_ARM64', '1') + capstone_files += files( + 'capstone/arch/AArch64/AArch64BaseInfo.c', + 'capstone/arch/AArch64/AArch64Disassembler.c', + 'capstone/arch/AArch64/AArch64InstPrinter.c', + 'capstone/arch/AArch64/AArch64Mapping.c', + 'capstone/arch/AArch64/AArch64Module.c' + ) + endif + + if 'CONFIG_PPC_DIS' in config_all_disas + capstone_data.set('CAPSTONE_HAS_POWERPC', '1') + capstone_files += files( + 'capstone/arch/PowerPC/PPCDisassembler.c', + 'capstone/arch/PowerPC/PPCInstPrinter.c', + 'capstone/arch/PowerPC/PPCMapping.c', + 'capstone/arch/PowerPC/PPCModule.c' + ) + endif + + if 'CONFIG_S390_DIS' in config_all_disas + capstone_data.set('CAPSTONE_HAS_SYSZ', '1') + capstone_files += files( + 'capstone/arch/SystemZ/SystemZDisassembler.c', + 'capstone/arch/SystemZ/SystemZInstPrinter.c', + 'capstone/arch/SystemZ/SystemZMapping.c', + 'capstone/arch/SystemZ/SystemZModule.c', + 'capstone/arch/SystemZ/SystemZMCTargetDesc.c' + ) + endif + + if 'CONFIG_I386_DIS' in config_all_disas + capstone_data.set('CAPSTONE_HAS_X86', 1) + capstone_files += files( + 'capstone/arch/X86/X86Disassembler.c', + 'capstone/arch/X86/X86DisassemblerDecoder.c', + 'capstone/arch/X86/X86ATTInstPrinter.c', + 'capstone/arch/X86/X86IntelInstPrinter.c', + 'capstone/arch/X86/X86InstPrinterCommon.c', + 'capstone/arch/X86/X86Mapping.c', + 'capstone/arch/X86/X86Module.c' + ) + endif + + configure_file(output: 'capstone-defs.h', configuration: capstone_data) + + capstone_cargs = [ + # FIXME: There does not seem to be a way to completely replace the c_args + # that come from add_project_arguments() -- we can only add to them. + # So: disable all warnings with a big hammer. + '-Wno-error', '-w', + + # Include all configuration defines via a header file, which will wind up + # as a dependency on the object file, and thus changes here will result + # in a rebuild. + '-include', 'capstone-defs.h' + ] + + libcapstone = static_library('capstone', + sources: capstone_files, + c_args: capstone_cargs, + include_directories: 'capstone/include') + capstone = declare_dependency(link_with: libcapstone, + include_directories: 'capstone/include/capstone') +endif + +slirp = not_found +slirp_opt = 'disabled' +if have_system + slirp_opt = get_option('slirp') + if slirp_opt in ['enabled', 'auto', 'system'] + have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build') + slirp = dependency('slirp', static: enable_static, + method: 'pkg-config', + required: slirp_opt == 'system' or + slirp_opt == 'enabled' and not have_internal) + if slirp.found() + slirp_opt = 'system' + elif have_internal + slirp_opt = 'internal' + else + slirp_opt = 'disabled' + endif + endif + if slirp_opt == 'internal' + slirp_deps = [] + if targetos == 'windows' + slirp_deps = cc.find_library('iphlpapi') + endif + slirp_conf = configuration_data() + slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0]) + slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1]) + slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2]) + slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version()) + slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"'] + slirp_files = [ + 'slirp/src/arp_table.c', + 'slirp/src/bootp.c', + 'slirp/src/cksum.c', + 'slirp/src/dhcpv6.c', + 'slirp/src/dnssearch.c', + 'slirp/src/if.c', + 'slirp/src/ip6_icmp.c', + 'slirp/src/ip6_input.c', + 'slirp/src/ip6_output.c', + 'slirp/src/ip_icmp.c', + 'slirp/src/ip_input.c', + 'slirp/src/ip_output.c', + 'slirp/src/mbuf.c', + 'slirp/src/misc.c', + 'slirp/src/ncsi.c', + 'slirp/src/ndp_table.c', + 'slirp/src/sbuf.c', + 'slirp/src/slirp.c', + 'slirp/src/socket.c', + 'slirp/src/state.c', + 'slirp/src/stream.c', + 'slirp/src/tcp_input.c', + 'slirp/src/tcp_output.c', + 'slirp/src/tcp_subr.c', + 'slirp/src/tcp_timer.c', + 'slirp/src/tftp.c', + 'slirp/src/udp.c', + 'slirp/src/udp6.c', + 'slirp/src/util.c', + 'slirp/src/version.c', + 'slirp/src/vmstate.c', + ] + + configure_file( + input : 'slirp/src/libslirp-version.h.in', + output : 'libslirp-version.h', + configuration: slirp_conf) + + slirp_inc = include_directories('slirp', 'slirp/src') + libslirp = static_library('slirp', + sources: slirp_files, + c_args: slirp_cargs, + include_directories: slirp_inc) + slirp = declare_dependency(link_with: libslirp, + dependencies: slirp_deps, + include_directories: slirp_inc) + endif +endif + +fdt = not_found +fdt_opt = get_option('fdt') +if have_system + if fdt_opt in ['enabled', 'auto', 'system'] + have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt') + fdt = cc.find_library('fdt', static: enable_static, + required: fdt_opt == 'system' or + fdt_opt == 'enabled' and not have_internal) + if fdt.found() and cc.links(''' + #include + #include + int main(void) { fdt_check_full(NULL, 0); return 0; }''', + dependencies: fdt) + fdt_opt = 'system' + elif have_internal + fdt_opt = 'internal' + else + fdt_opt = 'disabled' + endif + endif + if fdt_opt == 'internal' + fdt_files = files( + 'dtc/libfdt/fdt.c', + 'dtc/libfdt/fdt_ro.c', + 'dtc/libfdt/fdt_wip.c', + 'dtc/libfdt/fdt_sw.c', + 'dtc/libfdt/fdt_rw.c', + 'dtc/libfdt/fdt_strerror.c', + 'dtc/libfdt/fdt_empty_tree.c', + 'dtc/libfdt/fdt_addresses.c', + 'dtc/libfdt/fdt_overlay.c', + 'dtc/libfdt/fdt_check.c', + ) + + fdt_inc = include_directories('dtc/libfdt') + libfdt = static_library('fdt', + sources: fdt_files, + include_directories: fdt_inc) + fdt = declare_dependency(link_with: libfdt, + include_directories: fdt_inc) + endif +endif +if not fdt.found() and fdt_required.length() > 0 + error('fdt not available but required by targets ' + ', '.join(fdt_required)) +endif + +config_host_data.set('CONFIG_CAPSTONE', capstone.found()) +config_host_data.set('CONFIG_FDT', fdt.found()) +config_host_data.set('CONFIG_SLIRP', slirp.found()) + +##################### +# Generated sources # +##################### + +genh += configure_file(output: 'config-host.h', configuration: config_host_data) + +hxtool = find_program('scripts/hxtool') +shaderinclude = find_program('scripts/shaderinclude.pl') +qapi_gen = find_program('scripts/qapi-gen.py') +qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py', + meson.source_root() / 'scripts/qapi/commands.py', + meson.source_root() / 'scripts/qapi/common.py', + meson.source_root() / 'scripts/qapi/error.py', + meson.source_root() / 'scripts/qapi/events.py', + meson.source_root() / 'scripts/qapi/expr.py', + meson.source_root() / 'scripts/qapi/gen.py', + meson.source_root() / 'scripts/qapi/introspect.py', + meson.source_root() / 'scripts/qapi/parser.py', + meson.source_root() / 'scripts/qapi/schema.py', + meson.source_root() / 'scripts/qapi/source.py', + meson.source_root() / 'scripts/qapi/types.py', + meson.source_root() / 'scripts/qapi/visit.py', + meson.source_root() / 'scripts/qapi/common.py', + meson.source_root() / 'scripts/qapi-gen.py' +] + +tracetool = [ + python, files('scripts/tracetool.py'), + '--backend=' + config_host['TRACE_BACKENDS'] +] + +qemu_version_cmd = [find_program('scripts/qemu-version.sh'), + meson.current_source_dir(), + config_host['PKGVERSION'], meson.project_version()] +qemu_version = custom_target('qemu-version.h', + output: 'qemu-version.h', + command: qemu_version_cmd, + capture: true, + build_by_default: true, + build_always_stale: true) +genh += qemu_version + +hxdep = [] +hx_headers = [ + ['qemu-options.hx', 'qemu-options.def'], + ['qemu-img-cmds.hx', 'qemu-img-cmds.h'], +] +if have_system + hx_headers += [ + ['hmp-commands.hx', 'hmp-commands.h'], + ['hmp-commands-info.hx', 'hmp-commands-info.h'], + ] +endif +foreach d : hx_headers + hxdep += custom_target(d[1], + input: files(d[0]), + output: d[1], + capture: true, + build_by_default: true, # to be removed when added to a target + command: [hxtool, '-h', '@INPUT0@']) +endforeach +genh += hxdep + +################### +# Collect sources # +################### + +authz_ss = ss.source_set() +blockdev_ss = ss.source_set() +block_ss = ss.source_set() +bsd_user_ss = ss.source_set() +chardev_ss = ss.source_set() +common_ss = ss.source_set() +crypto_ss = ss.source_set() +io_ss = ss.source_set() +linux_user_ss = ss.source_set() +qmp_ss = ss.source_set() +qom_ss = ss.source_set() +softmmu_ss = ss.source_set() +specific_fuzz_ss = ss.source_set() +specific_ss = ss.source_set() +stub_ss = ss.source_set() +trace_ss = ss.source_set() +user_ss = ss.source_set() +util_ss = ss.source_set() + +modules = {} +hw_arch = {} +target_arch = {} +target_softmmu_arch = {} + +############### +# Trace files # +############### + +# TODO: add each directory to the subdirs from its own meson.build, once +# we have those +trace_events_subdirs = [ + 'accel/kvm', + 'accel/tcg', + 'crypto', + 'monitor', +] +if have_user + trace_events_subdirs += [ 'linux-user' ] +endif +if have_block + trace_events_subdirs += [ + 'authz', + 'block', + 'io', + 'nbd', + 'scsi', + ] +endif +if have_system + trace_events_subdirs += [ + 'audio', + 'backends', + 'backends/tpm', + 'chardev', + 'hw/9pfs', + 'hw/acpi', + 'hw/alpha', + 'hw/arm', + 'hw/audio', + 'hw/block', + 'hw/block/dataplane', + 'hw/char', + 'hw/display', + 'hw/dma', + 'hw/hppa', + 'hw/hyperv', + 'hw/i2c', + 'hw/i386', + 'hw/i386/xen', + 'hw/ide', + 'hw/input', + 'hw/intc', + 'hw/isa', + 'hw/mem', + 'hw/mips', + 'hw/misc', + 'hw/misc/macio', + 'hw/net', + 'hw/nvram', + 'hw/pci', + 'hw/pci-host', + 'hw/ppc', + 'hw/rdma', + 'hw/rdma/vmw', + 'hw/rtc', + 'hw/s390x', + 'hw/scsi', + 'hw/sd', + 'hw/sparc', + 'hw/sparc64', + 'hw/ssi', + 'hw/timer', + 'hw/tpm', + 'hw/usb', + 'hw/vfio', + 'hw/virtio', + 'hw/watchdog', + 'hw/xen', + 'hw/gpio', + 'migration', + 'net', + 'softmmu', + 'ui', + ] +endif +trace_events_subdirs += [ + 'hw/core', + 'qapi', + 'qom', + 'target/arm', + 'target/hppa', + 'target/i386', + 'target/mips', + 'target/ppc', + 'target/riscv', + 'target/s390x', + 'target/sparc', + 'util', +] + +subdir('contrib/libvhost-user') +subdir('qapi') +subdir('qobject') +subdir('stubs') +subdir('trace') +subdir('util') +subdir('qom') +subdir('authz') +subdir('crypto') +subdir('ui') + + +if enable_modules + libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO') + modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO') +endif + +stub_ss = stub_ss.apply(config_all, strict: false) + +util_ss.add_all(trace_ss) +util_ss = util_ss.apply(config_all, strict: false) +libqemuutil = static_library('qemuutil', + sources: util_ss.sources() + stub_ss.sources() + genh, + dependencies: [util_ss.dependencies(), m, glib, socket, malloc]) +qemuutil = declare_dependency(link_with: libqemuutil, + sources: genh + version_res) + +decodetree = generator(find_program('scripts/decodetree.py'), + output: 'decode-@BASENAME@.c.inc', + arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@']) + +subdir('audio') +subdir('io') +subdir('chardev') +subdir('fsdev') +subdir('libdecnumber') +subdir('target') +subdir('dump') + +block_ss.add(files( + 'block.c', + 'blockjob.c', + 'job.c', + 'qemu-io-cmds.c', +)) +block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c')) + +subdir('nbd') +subdir('scsi') +subdir('block') + +blockdev_ss.add(files( + 'blockdev.c', + 'blockdev-nbd.c', + 'iothread.c', + 'job-qmp.c', +)) + +# os-posix.c contains POSIX-specific functions used by qemu-storage-daemon, +# os-win32.c does not +blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c')) +softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')]) + +common_ss.add(files('cpus-common.c')) + +subdir('softmmu') + +common_ss.add(capstone) +specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone) +specific_ss.add(files('exec-vary.c')) +specific_ss.add(when: 'CONFIG_TCG', if_true: files( + 'fpu/softfloat.c', + 'tcg/optimize.c', + 'tcg/tcg-common.c', + 'tcg/tcg-op-gvec.c', + 'tcg/tcg-op-vec.c', + 'tcg/tcg-op.c', + 'tcg/tcg.c', +)) +specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c')) + +subdir('backends') +subdir('disas') +subdir('migration') +subdir('monitor') +subdir('net') +subdir('replay') +subdir('hw') +subdir('accel') +subdir('plugins') +subdir('bsd-user') +subdir('linux-user') + +bsd_user_ss.add(files('gdbstub.c')) +specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss) + +linux_user_ss.add(files('gdbstub.c', 'thunk.c')) +specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss) + +# needed for fuzzing binaries +subdir('tests/qtest/libqos') +subdir('tests/qtest/fuzz') + +######################## +# Library dependencies # +######################## + +block_mods = [] +softmmu_mods = [] +foreach d, list : modules + foreach m, module_ss : list + if enable_modules and targetos != 'windows' + module_ss = module_ss.apply(config_all, strict: false) + sl = static_library(d + '-' + m, [genh, module_ss.sources()], + dependencies: [modulecommon, module_ss.dependencies()], pic: true) + if d == 'block' + block_mods += sl + else + softmmu_mods += sl + endif + else + if d == 'block' + block_ss.add_all(module_ss) + else + softmmu_ss.add_all(module_ss) + endif + endif + endforeach +endforeach + +nm = find_program('nm') +undefsym = find_program('scripts/undefsym.py') +block_syms = custom_target('block.syms', output: 'block.syms', + input: [libqemuutil, block_mods], + capture: true, + command: [undefsym, nm, '@INPUT@']) +qemu_syms = custom_target('qemu.syms', output: 'qemu.syms', + input: [libqemuutil, softmmu_mods], + capture: true, + command: [undefsym, nm, '@INPUT@']) + +qom_ss = qom_ss.apply(config_host, strict: false) +libqom = static_library('qom', qom_ss.sources() + genh, + dependencies: [qom_ss.dependencies()], + name_suffix: 'fa') + +qom = declare_dependency(link_whole: libqom) + +authz_ss = authz_ss.apply(config_host, strict: false) +libauthz = static_library('authz', authz_ss.sources() + genh, + dependencies: [authz_ss.dependencies()], + name_suffix: 'fa', + build_by_default: false) + +authz = declare_dependency(link_whole: libauthz, + dependencies: qom) + +crypto_ss = crypto_ss.apply(config_host, strict: false) +libcrypto = static_library('crypto', crypto_ss.sources() + genh, + dependencies: [crypto_ss.dependencies()], + name_suffix: 'fa', + build_by_default: false) + +crypto = declare_dependency(link_whole: libcrypto, + dependencies: [authz, qom]) + +io_ss = io_ss.apply(config_host, strict: false) +libio = static_library('io', io_ss.sources() + genh, + dependencies: [io_ss.dependencies()], + link_with: libqemuutil, + name_suffix: 'fa', + build_by_default: false) + +io = declare_dependency(link_whole: libio, dependencies: [crypto, qom]) + +libmigration = static_library('migration', sources: migration_files + genh, + name_suffix: 'fa', + build_by_default: false) +migration = declare_dependency(link_with: libmigration, + dependencies: [zlib, qom, io]) +softmmu_ss.add(migration) + +block_ss = block_ss.apply(config_host, strict: false) +libblock = static_library('block', block_ss.sources() + genh, + dependencies: block_ss.dependencies(), + link_depends: block_syms, + name_suffix: 'fa', + build_by_default: false) + +block = declare_dependency(link_whole: [libblock], + link_args: '@block.syms', + dependencies: [crypto, io]) + +blockdev_ss = blockdev_ss.apply(config_host, strict: false) +libblockdev = static_library('blockdev', blockdev_ss.sources() + genh, + dependencies: blockdev_ss.dependencies(), + name_suffix: 'fa', + build_by_default: false) + +blockdev = declare_dependency(link_whole: [libblockdev], + dependencies: [block]) + +qmp_ss = qmp_ss.apply(config_host, strict: false) +libqmp = static_library('qmp', qmp_ss.sources() + genh, + dependencies: qmp_ss.dependencies(), + name_suffix: 'fa', + build_by_default: false) + +qmp = declare_dependency(link_whole: [libqmp]) + +libchardev = static_library('chardev', chardev_ss.sources() + genh, + name_suffix: 'fa', + build_by_default: false) + +chardev = declare_dependency(link_whole: libchardev) + +libhwcore = static_library('hwcore', sources: hwcore_files + genh, + name_suffix: 'fa', + build_by_default: false) +hwcore = declare_dependency(link_whole: libhwcore) +common_ss.add(hwcore) + +########### +# Targets # +########### + +foreach m : block_mods + softmmu_mods + shared_module(m.name(), + name_prefix: '', + link_whole: m, + install: true, + install_dir: qemu_moddir) +endforeach + +softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp) +common_ss.add(qom, qemuutil) + +common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss]) +common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss) + +common_all = common_ss.apply(config_all, strict: false) +common_all = static_library('common', + build_by_default: false, + sources: common_all.sources() + genh, + dependencies: common_all.dependencies(), + name_suffix: 'fa') + +feature_to_c = find_program('scripts/feature_to_c.sh') + +emulators = {} +foreach target : target_dirs + config_target = config_target_mak[target] + target_name = config_target['TARGET_NAME'] + arch = config_target['TARGET_BASE_ARCH'] + arch_srcs = [config_target_h[target]] + arch_deps = [] + c_args = ['-DNEED_CPU_H', + '-DCONFIG_TARGET="@0@-config-target.h"'.format(target), + '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)] + link_args = emulator_link_args + + config_target += config_host + target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])] + if targetos == 'linux' + target_inc += include_directories('linux-headers', is_system: true) + endif + if target.endswith('-softmmu') + qemu_target_name = 'qemu-system-' + target_name + target_type='system' + t = target_softmmu_arch[arch].apply(config_target, strict: false) + arch_srcs += t.sources() + arch_deps += t.dependencies() + + hw_dir = target_name == 'sparc64' ? 'sparc64' : arch + hw = hw_arch[hw_dir].apply(config_target, strict: false) + arch_srcs += hw.sources() + arch_deps += hw.dependencies() + + arch_srcs += config_devices_h[target] + link_args += ['@block.syms', '@qemu.syms'] + else + abi = config_target['TARGET_ABI_DIR'] + target_type='user' + qemu_target_name = 'qemu-' + target_name + if 'CONFIG_LINUX_USER' in config_target + base_dir = 'linux-user' + target_inc += include_directories('linux-user/host/' / config_host['ARCH']) + else + base_dir = 'bsd-user' + endif + target_inc += include_directories( + base_dir, + base_dir / abi, + ) + if 'CONFIG_LINUX_USER' in config_target + dir = base_dir / abi + arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c') + if config_target.has_key('TARGET_SYSTBL_ABI') + arch_srcs += \ + syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'], + extra_args : config_target['TARGET_SYSTBL_ABI']) + endif + endif + endif + + if 'TARGET_XML_FILES' in config_target + gdbstub_xml = custom_target(target + '-gdbstub-xml.c', + output: target + '-gdbstub-xml.c', + input: files(config_target['TARGET_XML_FILES'].split()), + command: [feature_to_c, '@INPUT@'], + capture: true) + arch_srcs += gdbstub_xml + endif + + t = target_arch[arch].apply(config_target, strict: false) + arch_srcs += t.sources() + arch_deps += t.dependencies() + + target_common = common_ss.apply(config_target, strict: false) + objects = common_all.extract_objects(target_common.sources()) + deps = target_common.dependencies() + + target_specific = specific_ss.apply(config_target, strict: false) + arch_srcs += target_specific.sources() + arch_deps += target_specific.dependencies() + + lib = static_library('qemu-' + target, + sources: arch_srcs + genh, + dependencies: arch_deps, + objects: objects, + include_directories: target_inc, + c_args: c_args, + build_by_default: false, + name_suffix: 'fa') + + if target.endswith('-softmmu') + execs = [{ + 'name': 'qemu-system-' + target_name, + 'gui': false, + 'sources': files('softmmu/main.c'), + 'dependencies': [] + }] + if targetos == 'windows' and (sdl.found() or gtk.found()) + execs += [{ + 'name': 'qemu-system-' + target_name + 'w', + 'gui': true, + 'sources': files('softmmu/main.c'), + 'dependencies': [] + }] + endif + if config_host.has_key('CONFIG_FUZZ') + specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false) + execs += [{ + 'name': 'qemu-fuzz-' + target_name, + 'gui': false, + 'sources': specific_fuzz.sources(), + 'dependencies': specific_fuzz.dependencies(), + }] + endif + else + execs = [{ + 'name': 'qemu-' + target_name, + 'gui': false, + 'sources': [], + 'dependencies': [] + }] + endif + foreach exe: execs + emulators += {exe['name']: + executable(exe['name'], exe['sources'], + install: true, + c_args: c_args, + dependencies: arch_deps + deps + exe['dependencies'], + objects: lib.extract_all_objects(recursive: true), + link_language: link_language, + link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []), + link_args: link_args, + gui_app: exe['gui']) + } + + if 'CONFIG_TRACE_SYSTEMTAP' in config_host + foreach stp: [ + {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false}, + {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true}, + {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true}, + {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true}, + ] + custom_target(exe['name'] + stp['ext'], + input: trace_events_all, + output: exe['name'] + stp['ext'], + capture: true, + install: stp['install'], + install_dir: get_option('datadir') / 'systemtap/tapset', + command: [ + tracetool, '--group=all', '--format=' + stp['fmt'], + '--binary=' + stp['bin'], + '--target-name=' + target_name, + '--target-type=' + target_type, + '--probe-prefix=qemu.' + target_type + '.' + target_name, + '@INPUT@', + ]) + endforeach + endif + endforeach +endforeach + +# Other build targets + +if 'CONFIG_PLUGIN' in config_host + install_headers('include/qemu/qemu-plugin.h') +endif + +if 'CONFIG_GUEST_AGENT' in config_host + subdir('qga') +endif + +# Don't build qemu-keymap if xkbcommon is not explicitly enabled +# when we don't build tools or system +if xkbcommon.found() + # used for the update-keymaps target, so include rules even if !have_tools + qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh, + dependencies: [qemuutil, xkbcommon], install: have_tools) +endif + +if have_tools + qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep], + dependencies: [authz, block, crypto, io, qom, qemuutil], install: true) + qemu_io = executable('qemu-io', files('qemu-io.c'), + dependencies: [block, qemuutil], install: true) + qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'), + dependencies: [blockdev, qemuutil], install: true) + + subdir('storage-daemon') + subdir('contrib/rdmacm-mux') + subdir('contrib/elf2dmp') + + executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'), + dependencies: qemuutil, + install: true) + + if 'CONFIG_VHOST_USER' in config_host + subdir('contrib/vhost-user-blk') + subdir('contrib/vhost-user-gpu') + subdir('contrib/vhost-user-input') + subdir('contrib/vhost-user-scsi') + endif + + if targetos == 'linux' + executable('qemu-bridge-helper', files('qemu-bridge-helper.c'), + dependencies: [qemuutil, libcap_ng], + install: true, + install_dir: get_option('libexecdir')) + + executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'), + dependencies: [authz, crypto, io, qom, qemuutil, + libcap_ng, mpathpersist], + install: true) + endif + + if 'CONFIG_IVSHMEM' in config_host + subdir('contrib/ivshmem-client') + subdir('contrib/ivshmem-server') + endif +endif + +subdir('scripts') +subdir('tools') +subdir('pc-bios') +subdir('docs') +subdir('tests') +if 'CONFIG_GTK' in config_host + subdir('po') +endif + +if host_machine.system() == 'windows' + nsis_cmd = [ + find_program('scripts/nsis.py'), + '@OUTPUT@', + get_option('prefix'), + meson.current_source_dir(), + host_machine.cpu(), + '--', + '-DDISPLAYVERSION=' + meson.project_version(), + ] + if build_docs + nsis_cmd += '-DCONFIG_DOCUMENTATION=y' + endif + if 'CONFIG_GTK' in config_host + nsis_cmd += '-DCONFIG_GTK=y' + endif + + nsis = custom_target('nsis', + output: 'qemu-setup-' + meson.project_version() + '.exe', + input: files('qemu.nsi'), + build_always_stale: true, + command: nsis_cmd + ['@INPUT@']) + alias_target('installer', nsis) +endif + +######################### +# Configuration summary # +######################### + +summary_info = {} +summary_info += {'Install prefix': get_option('prefix')} +summary_info += {'BIOS directory': qemu_datadir} +summary_info += {'firmware path': get_option('qemu_firmwarepath')} +summary_info += {'binary directory': get_option('bindir')} +summary_info += {'library directory': get_option('libdir')} +summary_info += {'module directory': qemu_moddir} +summary_info += {'libexec directory': get_option('libexecdir')} +summary_info += {'include directory': get_option('includedir')} +summary_info += {'config directory': get_option('sysconfdir')} +if targetos != 'windows' + summary_info += {'local state directory': get_option('localstatedir')} + summary_info += {'Manual directory': get_option('mandir')} +else + summary_info += {'local state directory': 'queried at runtime'} +endif +summary_info += {'Doc directory': get_option('docdir')} +summary_info += {'Build directory': meson.current_build_dir()} +summary_info += {'Source path': meson.current_source_dir()} +summary_info += {'GIT binary': config_host['GIT']} +summary_info += {'GIT submodules': config_host['GIT_SUBMODULES']} +summary_info += {'C compiler': meson.get_compiler('c').cmd_array()[0]} +summary_info += {'Host C compiler': meson.get_compiler('c', native: true).cmd_array()[0]} +if link_language == 'cpp' + summary_info += {'C++ compiler': meson.get_compiler('cpp').cmd_array()[0]} +else + summary_info += {'C++ compiler': false} +endif +if targetos == 'darwin' + summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]} +endif +summary_info += {'ARFLAGS': config_host['ARFLAGS']} +summary_info += {'CFLAGS': ' '.join(get_option('c_args') + + ['-O' + get_option('optimization')] + + (get_option('debug') ? ['-g'] : []))} +if link_language == 'cpp' + summary_info += {'CXXFLAGS': ' '.join(get_option('cpp_args') + + ['-O' + get_option('optimization')] + + (get_option('debug') ? ['-g'] : []))} +endif +link_args = get_option(link_language + '_link_args') +if link_args.length() > 0 + summary_info += {'LDFLAGS': ' '.join(link_args)} +endif +summary_info += {'QEMU_CFLAGS': config_host['QEMU_CFLAGS']} +summary_info += {'QEMU_LDFLAGS': config_host['QEMU_LDFLAGS']} +summary_info += {'make': config_host['MAKE']} +summary_info += {'python': '@0@ (version: @1@)'.format(python.full_path(), python.language_version())} +summary_info += {'sphinx-build': sphinx_build.found()} +summary_info += {'genisoimage': config_host['GENISOIMAGE']} +# TODO: add back version +summary_info += {'slirp support': slirp_opt == 'disabled' ? false : slirp_opt} +if slirp_opt != 'disabled' + summary_info += {'smbd': config_host['CONFIG_SMBD_COMMAND']} +endif +summary_info += {'module support': config_host.has_key('CONFIG_MODULES')} +if config_host.has_key('CONFIG_MODULES') + summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')} +endif +summary_info += {'host CPU': cpu} +summary_info += {'host endianness': build_machine.endian()} +summary_info += {'target list': ' '.join(target_dirs)} +summary_info += {'gprof enabled': config_host.has_key('CONFIG_GPROF')} +summary_info += {'sparse enabled': sparse.found()} +summary_info += {'strip binaries': get_option('strip')} +summary_info += {'profiler': config_host.has_key('CONFIG_PROFILER')} +summary_info += {'static build': config_host.has_key('CONFIG_STATIC')} +if targetos == 'darwin' + summary_info += {'Cocoa support': config_host.has_key('CONFIG_COCOA')} +endif +# TODO: add back version +summary_info += {'SDL support': sdl.found()} +summary_info += {'SDL image support': sdl_image.found()} +# TODO: add back version +summary_info += {'GTK support': config_host.has_key('CONFIG_GTK')} +summary_info += {'GTK GL support': config_host.has_key('CONFIG_GTK_GL')} +summary_info += {'pixman': pixman.found()} +# TODO: add back version +summary_info += {'VTE support': config_host.has_key('CONFIG_VTE')} +summary_info += {'TLS priority': config_host['CONFIG_TLS_PRIORITY']} +summary_info += {'GNUTLS support': config_host.has_key('CONFIG_GNUTLS')} +# TODO: add back version +summary_info += {'libgcrypt': config_host.has_key('CONFIG_GCRYPT')} +if config_host.has_key('CONFIG_GCRYPT') + summary_info += {' hmac': config_host.has_key('CONFIG_GCRYPT_HMAC')} + summary_info += {' XTS': not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')} +endif +# TODO: add back version +summary_info += {'nettle': config_host.has_key('CONFIG_NETTLE')} +if config_host.has_key('CONFIG_NETTLE') + summary_info += {' XTS': not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')} +endif +summary_info += {'libtasn1': config_host.has_key('CONFIG_TASN1')} +summary_info += {'PAM': config_host.has_key('CONFIG_AUTH_PAM')} +summary_info += {'iconv support': iconv.found()} +summary_info += {'curses support': curses.found()} +# TODO: add back version +summary_info += {'virgl support': config_host.has_key('CONFIG_VIRGL')} +summary_info += {'curl support': config_host.has_key('CONFIG_CURL')} +summary_info += {'mingw32 support': targetos == 'windows'} +summary_info += {'Audio drivers': config_host['CONFIG_AUDIO_DRIVERS']} +summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']} +summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']} +summary_info += {'VirtFS support': config_host.has_key('CONFIG_VIRTFS')} +summary_info += {'build virtiofs daemon': have_virtiofsd} +summary_info += {'Multipath support': mpathpersist.found()} +summary_info += {'VNC support': vnc.found()} +if vnc.found() + summary_info += {'VNC SASL support': sasl.found()} + summary_info += {'VNC JPEG support': jpeg.found()} + summary_info += {'VNC PNG support': png.found()} +endif +summary_info += {'xen support': config_host.has_key('CONFIG_XEN_BACKEND')} +if config_host.has_key('CONFIG_XEN_BACKEND') + summary_info += {'xen ctrl version': config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']} +endif +summary_info += {'brlapi support': config_host.has_key('CONFIG_BRLAPI')} +summary_info += {'Documentation': build_docs} +summary_info += {'PIE': get_option('b_pie')} +summary_info += {'vde support': config_host.has_key('CONFIG_VDE')} +summary_info += {'netmap support': config_host.has_key('CONFIG_NETMAP')} +summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')} +summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')} +summary_info += {'ATTR/XATTR support': config_host.has_key('CONFIG_ATTR')} +summary_info += {'Install blobs': get_option('install_blobs')} +summary_info += {'KVM support': config_all.has_key('CONFIG_KVM')} +summary_info += {'HAX support': config_all.has_key('CONFIG_HAX')} +summary_info += {'HVF support': config_all.has_key('CONFIG_HVF')} +summary_info += {'WHPX support': config_all.has_key('CONFIG_WHPX')} +summary_info += {'TCG support': config_all.has_key('CONFIG_TCG')} +if config_all.has_key('CONFIG_TCG') + summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')} + summary_info += {'TCG interpreter': config_host.has_key('CONFIG_TCG_INTERPRETER')} +endif +summary_info += {'malloc trim support': has_malloc_trim} +summary_info += {'RDMA support': config_host.has_key('CONFIG_RDMA')} +summary_info += {'PVRDMA support': config_host.has_key('CONFIG_PVRDMA')} +summary_info += {'fdt support': fdt_opt == 'disabled' ? false : fdt_opt} +summary_info += {'membarrier': config_host.has_key('CONFIG_MEMBARRIER')} +summary_info += {'preadv support': config_host.has_key('CONFIG_PREADV')} +summary_info += {'fdatasync': config_host.has_key('CONFIG_FDATASYNC')} +summary_info += {'madvise': config_host.has_key('CONFIG_MADVISE')} +summary_info += {'posix_madvise': config_host.has_key('CONFIG_POSIX_MADVISE')} +summary_info += {'posix_memalign': config_host.has_key('CONFIG_POSIX_MEMALIGN')} +summary_info += {'libcap-ng support': config_host.has_key('CONFIG_LIBCAP_NG')} +summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')} +summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')} +summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')} +summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')} +summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')} +summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')} +summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server} +summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')} +summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')} +summary_info += {'Trace backends': config_host['TRACE_BACKENDS']} +if config_host['TRACE_BACKENDS'].split().contains('simple') + summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-'} +endif +# TODO: add back protocol and server version +summary_info += {'spice support': config_host.has_key('CONFIG_SPICE')} +summary_info += {'rbd support': config_host.has_key('CONFIG_RBD')} +summary_info += {'xfsctl support': config_host.has_key('CONFIG_XFS')} +summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')} +summary_info += {'U2F support': u2f.found()} +summary_info += {'libusb': config_host.has_key('CONFIG_USB_LIBUSB')} +summary_info += {'usb net redir': config_host.has_key('CONFIG_USB_REDIR')} +summary_info += {'OpenGL support': config_host.has_key('CONFIG_OPENGL')} +summary_info += {'OpenGL dmabufs': config_host.has_key('CONFIG_OPENGL_DMABUF')} +summary_info += {'libiscsi support': config_host.has_key('CONFIG_LIBISCSI')} +summary_info += {'libnfs support': config_host.has_key('CONFIG_LIBNFS')} +summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')} +if targetos == 'windows' + if 'WIN_SDK' in config_host + summary_info += {'Windows SDK': config_host['WIN_SDK']} + endif + summary_info += {'QGA VSS support': config_host.has_key('CONFIG_QGA_VSS')} + summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')} + summary_info += {'QGA MSI support': config_host.has_key('CONFIG_QGA_MSI')} +endif +summary_info += {'seccomp support': config_host.has_key('CONFIG_SECCOMP')} +summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']} +summary_info += {'coroutine pool': config_host['CONFIG_COROUTINE_POOL'] == '1'} +summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')} +summary_info += {'mutex debugging': config_host.has_key('CONFIG_DEBUG_MUTEX')} +summary_info += {'crypto afalg': config_host.has_key('CONFIG_AF_ALG')} +summary_info += {'GlusterFS support': config_host.has_key('CONFIG_GLUSTERFS')} +summary_info += {'gcov': get_option('b_coverage')} +summary_info += {'TPM support': config_host.has_key('CONFIG_TPM')} +summary_info += {'libssh support': config_host.has_key('CONFIG_LIBSSH')} +summary_info += {'QOM debugging': config_host.has_key('CONFIG_QOM_CAST_DEBUG')} +summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')} +summary_info += {'lzo support': config_host.has_key('CONFIG_LZO')} +summary_info += {'snappy support': config_host.has_key('CONFIG_SNAPPY')} +summary_info += {'bzip2 support': config_host.has_key('CONFIG_BZIP2')} +summary_info += {'lzfse support': config_host.has_key('CONFIG_LZFSE')} +summary_info += {'zstd support': config_host.has_key('CONFIG_ZSTD')} +summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')} +summary_info += {'libxml2': config_host.has_key('CONFIG_LIBXML2')} +summary_info += {'memory allocator': get_option('malloc')} +summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')} +summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')} +summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')} +summary_info += {'bochs support': config_host.has_key('CONFIG_BOCHS')} +summary_info += {'cloop support': config_host.has_key('CONFIG_CLOOP')} +summary_info += {'dmg support': config_host.has_key('CONFIG_DMG')} +summary_info += {'qcow v1 support': config_host.has_key('CONFIG_QCOW1')} +summary_info += {'vdi support': config_host.has_key('CONFIG_VDI')} +summary_info += {'vvfat support': config_host.has_key('CONFIG_VVFAT')} +summary_info += {'qed support': config_host.has_key('CONFIG_QED')} +summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')} +summary_info += {'sheepdog support': config_host.has_key('CONFIG_SHEEPDOG')} +summary_info += {'capstone': capstone_opt == 'disabled' ? false : capstone_opt} +summary_info += {'libpmem support': config_host.has_key('CONFIG_LIBPMEM')} +summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')} +summary_info += {'libudev': libudev.found()} +summary_info += {'default devices': config_host['CONFIG_MINIKCONF_MODE'] == '--defconfig'} +summary_info += {'plugin support': config_host.has_key('CONFIG_PLUGIN')} +summary_info += {'fuzzing support': config_host.has_key('CONFIG_FUZZ')} +if config_host.has_key('HAVE_GDB_BIN') + summary_info += {'gdb': config_host['HAVE_GDB_BIN']} +endif +summary_info += {'thread sanitizer': config_host.has_key('CONFIG_TSAN')} +summary_info += {'rng-none': config_host.has_key('CONFIG_RNG_NONE')} +summary_info += {'Linux keyring': config_host.has_key('CONFIG_SECRET_KEYRING')} +summary(summary_info, bool_yn: true) + +if not supported_cpus.contains(cpu) + message() + warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!') + message() + message('CPU host architecture ' + cpu + ' support is not currently maintained.') + message('The QEMU project intends to remove support for this host CPU in') + message('a future release if nobody volunteers to maintain it and to') + message('provide a build host for our continuous integration setup.') + message('configure has succeeded and you can continue to build, but') + message('if you care about QEMU on this platform you should contact') + message('us upstream at qemu-devel@nongnu.org.') +endif + +if not supported_oses.contains(targetos) + message() + warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!') + message() + message('Host OS ' + targetos + 'support is not currently maintained.') + message('The QEMU project intends to remove support for this host OS in') + message('a future release if nobody volunteers to maintain it and to') + message('provide a build host for our continuous integration setup.') + message('configure has succeeded and you can continue to build, but') + message('if you care about QEMU on this platform you should contact') + message('us upstream at qemu-devel@nongnu.org.') +endif diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000000000000000000000000000000000000..f6f64785fe799fc925e824e38b9429c7443291ea --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,78 @@ +option('qemu_suffix', type : 'string', value: 'qemu', + description: 'Suffix for QEMU data/modules/config directories (can be empty)') +option('docdir', type : 'string', value : 'doc', + description: 'Base directory for documentation installation (can be empty)') +option('qemu_firmwarepath', type : 'string', value : '', + description: 'search PATH for firmware files') +option('sphinx_build', type : 'string', value : '', + description: 'Use specified sphinx-build [$sphinx_build] for building document (default to be empty)') + +option('docs', type : 'feature', value : 'auto', + description: 'Documentations build support') +option('gettext', type : 'boolean', value : true, + description: 'Localization of the GTK+ user interface') +option('install_blobs', type : 'boolean', value : true, + description: 'install provided firmware blobs') +option('sparse', type : 'feature', value : 'auto', + description: 'sparse checker') + +option('malloc_trim', type : 'feature', value : 'auto', + description: 'enable libc malloc_trim() for memory optimization') +option('malloc', type : 'combo', choices : ['system', 'tcmalloc', 'jemalloc'], + value: 'system', description: 'choose memory allocator to use') + +option('kvm', type: 'feature', value: 'auto', + description: 'KVM acceleration support') +option('hax', type: 'feature', value: 'auto', + description: 'HAX acceleration support') +option('whpx', type: 'feature', value: 'auto', + description: 'WHPX acceleration support') +option('hvf', type: 'feature', value: 'auto', + description: 'HVF acceleration support') +option('xen', type: 'feature', value: 'auto', + description: 'Xen backend support') +option('xen_pci_passthrough', type: 'feature', value: 'auto', + description: 'Xen PCI passthrough support') +option('tcg', type: 'feature', value: 'auto', + description: 'TCG support') + +option('cocoa', type : 'feature', value : 'auto', + description: 'Cocoa user interface (macOS only)') +option('mpath', type : 'feature', value : 'auto', + description: 'Multipath persistent reservation passthrough') +option('iconv', type : 'feature', value : 'auto', + description: 'Font glyph conversion support') +option('curses', type : 'feature', value : 'auto', + description: 'curses UI') +option('libudev', type : 'feature', value : 'auto', + description: 'Use libudev to enumerate host devices') +option('sdl', type : 'feature', value : 'auto', + description: 'SDL user interface') +option('sdl_image', type : 'feature', value : 'auto', + description: 'SDL Image support for icons') +option('u2f', type : 'feature', value : 'auto', + description: 'U2F emulation support') +option('vnc', type : 'feature', value : 'enabled', + description: 'VNC server') +option('vnc_jpeg', type : 'feature', value : 'auto', + description: 'JPEG lossy compression for VNC server') +option('vnc_png', type : 'feature', value : 'auto', + description: 'PNG compression for VNC server') +option('vnc_sasl', type : 'feature', value : 'auto', + description: 'SASL authentication for VNC server') +option('xkbcommon', type : 'feature', value : 'auto', + description: 'xkbcommon support') +option('virtiofsd', type: 'feature', value: 'auto', + description: 'build virtiofs daemon (virtiofsd)') +option('vhost_user_blk_server', type: 'feature', value: 'auto', + description: 'build vhost-user-blk server') + +option('capstone', type: 'combo', value: 'auto', + choices: ['disabled', 'enabled', 'auto', 'system', 'internal'], + description: 'Whether and how to find the capstone library') +option('slirp', type: 'combo', value: 'auto', + choices: ['disabled', 'enabled', 'auto', 'system', 'internal'], + description: 'Whether and how to find the slirp library') +option('fdt', type: 'combo', value: 'auto', + choices: ['disabled', 'enabled', 'auto', 'system', 'internal'], + description: 'Whether and how to find the libfdt library') diff --git a/migration/Makefile.objs b/migration/Makefile.objs deleted file mode 100644 index 0fc619e380d9c931ac1b2c71687511a39de0d981..0000000000000000000000000000000000000000 --- a/migration/Makefile.objs +++ /dev/null @@ -1,18 +0,0 @@ -common-obj-y += migration.o socket.o fd.o exec.o -common-obj-y += tls.o channel.o savevm.o -common-obj-y += colo.o colo-failover.o -common-obj-y += vmstate.o vmstate-types.o page_cache.o -common-obj-y += qemu-file.o global_state.o -common-obj-y += qemu-file-channel.o -common-obj-y += xbzrle.o postcopy-ram.o -common-obj-y += qjson.o -common-obj-y += block-dirty-bitmap.o -common-obj-y += multifd.o -common-obj-y += multifd-zlib.o -common-obj-$(CONFIG_ZSTD) += multifd-zstd.o - -common-obj-$(CONFIG_RDMA) += rdma.o - -common-obj-$(CONFIG_LIVE_BLOCK_MIGRATION) += block.o - -rdma.o-libs := $(RDMA_LIBS) diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c index 7eafface614970606965e3545a599316eb20a5aa..c61d382be87c88420aade1942a6e53101aabb2f8 100644 --- a/migration/block-dirty-bitmap.c +++ b/migration/block-dirty-bitmap.c @@ -29,10 +29,10 @@ * * # Header (shared for different chunk types) * 1, 2 or 4 bytes: flags (see qemu_{put,put}_flags) - * [ 1 byte: node name size ] \ flags & DEVICE_NAME - * [ n bytes: node name ] / - * [ 1 byte: bitmap name size ] \ flags & BITMAP_NAME - * [ n bytes: bitmap name ] / + * [ 1 byte: node alias size ] \ flags & DEVICE_NAME + * [ n bytes: node alias ] / + * [ 1 byte: bitmap alias size ] \ flags & BITMAP_NAME + * [ n bytes: bitmap alias ] / * * # Start of bitmap migration (flags & START) * header @@ -72,7 +72,9 @@ #include "migration/register.h" #include "qemu/hbitmap.h" #include "qemu/cutils.h" +#include "qemu/id.h" #include "qapi/error.h" +#include "qapi/qapi-commands-migration.h" #include "trace.h" #define CHUNK_SIZE (1 << 10) @@ -97,26 +99,29 @@ #define DIRTY_BITMAP_MIG_START_FLAG_ENABLED 0x01 #define DIRTY_BITMAP_MIG_START_FLAG_PERSISTENT 0x02 -/* 0x04 was "AUTOLOAD" flags on elder versions, no it is ignored */ +/* 0x04 was "AUTOLOAD" flags on older versions, now it is ignored */ #define DIRTY_BITMAP_MIG_START_FLAG_RESERVED_MASK 0xf8 -typedef struct DirtyBitmapMigBitmapState { +/* State of one bitmap during save process */ +typedef struct SaveBitmapState { /* Written during setup phase. */ BlockDriverState *bs; - const char *node_name; + char *node_alias; + char *bitmap_alias; BdrvDirtyBitmap *bitmap; uint64_t total_sectors; uint64_t sectors_per_chunk; - QSIMPLEQ_ENTRY(DirtyBitmapMigBitmapState) entry; + QSIMPLEQ_ENTRY(SaveBitmapState) entry; uint8_t flags; /* For bulk phase. */ bool bulk_completed; uint64_t cur_sector; -} DirtyBitmapMigBitmapState; +} SaveBitmapState; -typedef struct DirtyBitmapMigState { - QSIMPLEQ_HEAD(, DirtyBitmapMigBitmapState) dbms_list; +/* State of the dirty bitmap migration (DBM) during save process */ +typedef struct DBMSaveState { + QSIMPLEQ_HEAD(, SaveBitmapState) dbms_list; bool bulk_completed; bool no_bitmaps; @@ -124,29 +129,226 @@ typedef struct DirtyBitmapMigState { /* for send_bitmap_bits() */ BlockDriverState *prev_bs; BdrvDirtyBitmap *prev_bitmap; -} DirtyBitmapMigState; +} DBMSaveState; -typedef struct DirtyBitmapLoadState { - uint32_t flags; - char node_name[256]; - char bitmap_name[256]; +typedef struct LoadBitmapState { BlockDriverState *bs; BdrvDirtyBitmap *bitmap; -} DirtyBitmapLoadState; - -static DirtyBitmapMigState dirty_bitmap_mig_state; + bool migrated; + bool enabled; +} LoadBitmapState; -typedef struct DirtyBitmapLoadBitmapState { +/* State of the dirty bitmap migration (DBM) during load process */ +typedef struct DBMLoadState { + uint32_t flags; + char node_alias[256]; + char bitmap_alias[256]; + char bitmap_name[BDRV_BITMAP_MAX_NAME_SIZE + 1]; BlockDriverState *bs; BdrvDirtyBitmap *bitmap; - bool migrated; -} DirtyBitmapLoadBitmapState; -static GSList *enabled_bitmaps; -QemuMutex finish_lock; -void init_dirty_bitmap_incoming_migration(void) + bool before_vm_start_handled; /* set in dirty_bitmap_mig_before_vm_start */ + + /* + * cancelled + * Incoming migration is cancelled for some reason. That means that we + * still should read our chunks from migration stream, to not affect other + * migration objects (like RAM), but just ignore them and do not touch any + * bitmaps or nodes. + */ + bool cancelled; + + GSList *bitmaps; + QemuMutex lock; /* protect bitmaps */ +} DBMLoadState; + +typedef struct DBMState { + DBMSaveState save; + DBMLoadState load; +} DBMState; + +static DBMState dbm_state; + +/* For hash tables that map node/bitmap names to aliases */ +typedef struct AliasMapInnerNode { + char *string; + GHashTable *subtree; +} AliasMapInnerNode; + +static void free_alias_map_inner_node(void *amin_ptr) { - qemu_mutex_init(&finish_lock); + AliasMapInnerNode *amin = amin_ptr; + + g_free(amin->string); + g_hash_table_unref(amin->subtree); + g_free(amin); +} + +/** + * Construct an alias map based on the given QMP structure. + * + * (Note that we cannot store such maps in the MigrationParameters + * object, because that struct is defined by the QAPI schema, which + * makes it basically impossible to have dicts with arbitrary keys. + * Therefore, we instead have to construct these maps when migration + * starts.) + * + * @bbm is the block_bitmap_mapping from the migration parameters. + * + * If @name_to_alias is true, the returned hash table will map node + * and bitmap names to their respective aliases (for outgoing + * migration). + * + * If @name_to_alias is false, the returned hash table will map node + * and bitmap aliases to their respective names (for incoming + * migration). + * + * The hash table maps node names/aliases to AliasMapInnerNode + * objects, whose .string is the respective node alias/name, and whose + * .subtree table maps bitmap names/aliases to the respective bitmap + * alias/name. + */ +static GHashTable *construct_alias_map(const BitmapMigrationNodeAliasList *bbm, + bool name_to_alias, + Error **errp) +{ + GHashTable *alias_map; + size_t max_node_name_len = sizeof_field(BlockDriverState, node_name) - 1; + + alias_map = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, free_alias_map_inner_node); + + for (; bbm; bbm = bbm->next) { + const BitmapMigrationNodeAlias *bmna = bbm->value; + const BitmapMigrationBitmapAliasList *bmbal; + AliasMapInnerNode *amin; + GHashTable *bitmaps_map; + const char *node_map_from, *node_map_to; + + if (!id_wellformed(bmna->alias)) { + error_setg(errp, "The node alias '%s' is not well-formed", + bmna->alias); + goto fail; + } + + if (strlen(bmna->alias) > UINT8_MAX) { + error_setg(errp, "The node alias '%s' is longer than %u bytes", + bmna->alias, UINT8_MAX); + goto fail; + } + + if (strlen(bmna->node_name) > max_node_name_len) { + error_setg(errp, "The node name '%s' is longer than %zu bytes", + bmna->node_name, max_node_name_len); + goto fail; + } + + if (name_to_alias) { + if (g_hash_table_contains(alias_map, bmna->node_name)) { + error_setg(errp, "The node name '%s' is mapped twice", + bmna->node_name); + goto fail; + } + + node_map_from = bmna->node_name; + node_map_to = bmna->alias; + } else { + if (g_hash_table_contains(alias_map, bmna->alias)) { + error_setg(errp, "The node alias '%s' is used twice", + bmna->alias); + goto fail; + } + + node_map_from = bmna->alias; + node_map_to = bmna->node_name; + } + + bitmaps_map = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); + + amin = g_new(AliasMapInnerNode, 1); + *amin = (AliasMapInnerNode){ + .string = g_strdup(node_map_to), + .subtree = bitmaps_map, + }; + + g_hash_table_insert(alias_map, g_strdup(node_map_from), amin); + + for (bmbal = bmna->bitmaps; bmbal; bmbal = bmbal->next) { + const BitmapMigrationBitmapAlias *bmba = bmbal->value; + const char *bmap_map_from, *bmap_map_to; + + if (strlen(bmba->alias) > UINT8_MAX) { + error_setg(errp, + "The bitmap alias '%s' is longer than %u bytes", + bmba->alias, UINT8_MAX); + goto fail; + } + + if (strlen(bmba->name) > BDRV_BITMAP_MAX_NAME_SIZE) { + error_setg(errp, "The bitmap name '%s' is longer than %d bytes", + bmba->name, BDRV_BITMAP_MAX_NAME_SIZE); + goto fail; + } + + if (name_to_alias) { + bmap_map_from = bmba->name; + bmap_map_to = bmba->alias; + + if (g_hash_table_contains(bitmaps_map, bmba->name)) { + error_setg(errp, "The bitmap '%s'/'%s' is mapped twice", + bmna->node_name, bmba->name); + goto fail; + } + } else { + bmap_map_from = bmba->alias; + bmap_map_to = bmba->name; + + if (g_hash_table_contains(bitmaps_map, bmba->alias)) { + error_setg(errp, "The bitmap alias '%s'/'%s' is used twice", + bmna->alias, bmba->alias); + goto fail; + } + } + + g_hash_table_insert(bitmaps_map, + g_strdup(bmap_map_from), g_strdup(bmap_map_to)); + } + } + + return alias_map; + +fail: + g_hash_table_destroy(alias_map); + return NULL; +} + +/** + * Run construct_alias_map() in both directions to check whether @bbm + * is valid. + * (This function is to be used by migration/migration.c to validate + * the user-specified block-bitmap-mapping migration parameter.) + * + * Returns true if and only if the mapping is valid. + */ +bool check_dirty_bitmap_mig_alias_map(const BitmapMigrationNodeAliasList *bbm, + Error **errp) +{ + GHashTable *alias_map; + + alias_map = construct_alias_map(bbm, true, errp); + if (!alias_map) { + return false; + } + g_hash_table_destroy(alias_map); + + alias_map = construct_alias_map(bbm, false, errp); + if (!alias_map) { + return false; + } + g_hash_table_destroy(alias_map); + + return true; } static uint32_t qemu_get_bitmap_flags(QEMUFile *f) @@ -164,54 +366,57 @@ static uint32_t qemu_get_bitmap_flags(QEMUFile *f) static void qemu_put_bitmap_flags(QEMUFile *f, uint32_t flags) { - /* The code currently do not send flags more than one byte */ + /* The code currently does not send flags as more than one byte */ assert(!(flags & (0xffffff00 | DIRTY_BITMAP_MIG_EXTRA_FLAGS))); qemu_put_byte(f, flags); } -static void send_bitmap_header(QEMUFile *f, DirtyBitmapMigBitmapState *dbms, - uint32_t additional_flags) +static void send_bitmap_header(QEMUFile *f, DBMSaveState *s, + SaveBitmapState *dbms, uint32_t additional_flags) { BlockDriverState *bs = dbms->bs; BdrvDirtyBitmap *bitmap = dbms->bitmap; uint32_t flags = additional_flags; trace_send_bitmap_header_enter(); - if (bs != dirty_bitmap_mig_state.prev_bs) { - dirty_bitmap_mig_state.prev_bs = bs; + if (bs != s->prev_bs) { + s->prev_bs = bs; flags |= DIRTY_BITMAP_MIG_FLAG_DEVICE_NAME; } - if (bitmap != dirty_bitmap_mig_state.prev_bitmap) { - dirty_bitmap_mig_state.prev_bitmap = bitmap; + if (bitmap != s->prev_bitmap) { + s->prev_bitmap = bitmap; flags |= DIRTY_BITMAP_MIG_FLAG_BITMAP_NAME; } qemu_put_bitmap_flags(f, flags); if (flags & DIRTY_BITMAP_MIG_FLAG_DEVICE_NAME) { - qemu_put_counted_string(f, dbms->node_name); + qemu_put_counted_string(f, dbms->node_alias); } if (flags & DIRTY_BITMAP_MIG_FLAG_BITMAP_NAME) { - qemu_put_counted_string(f, bdrv_dirty_bitmap_name(bitmap)); + qemu_put_counted_string(f, dbms->bitmap_alias); } } -static void send_bitmap_start(QEMUFile *f, DirtyBitmapMigBitmapState *dbms) +static void send_bitmap_start(QEMUFile *f, DBMSaveState *s, + SaveBitmapState *dbms) { - send_bitmap_header(f, dbms, DIRTY_BITMAP_MIG_FLAG_START); + send_bitmap_header(f, s, dbms, DIRTY_BITMAP_MIG_FLAG_START); qemu_put_be32(f, bdrv_dirty_bitmap_granularity(dbms->bitmap)); qemu_put_byte(f, dbms->flags); } -static void send_bitmap_complete(QEMUFile *f, DirtyBitmapMigBitmapState *dbms) +static void send_bitmap_complete(QEMUFile *f, DBMSaveState *s, + SaveBitmapState *dbms) { - send_bitmap_header(f, dbms, DIRTY_BITMAP_MIG_FLAG_COMPLETE); + send_bitmap_header(f, s, dbms, DIRTY_BITMAP_MIG_FLAG_COMPLETE); } -static void send_bitmap_bits(QEMUFile *f, DirtyBitmapMigBitmapState *dbms, +static void send_bitmap_bits(QEMUFile *f, DBMSaveState *s, + SaveBitmapState *dbms, uint64_t start_sector, uint32_t nr_sectors) { /* align for buffer_is_zero() */ @@ -236,7 +441,7 @@ static void send_bitmap_bits(QEMUFile *f, DirtyBitmapMigBitmapState *dbms, trace_send_bitmap_bits(flags, start_sector, nr_sectors, buf_size); - send_bitmap_header(f, dbms, flags); + send_bitmap_header(f, s, dbms, flags); qemu_put_be64(f, start_sector); qemu_put_be32(f, nr_sectors); @@ -255,97 +460,218 @@ static void send_bitmap_bits(QEMUFile *f, DirtyBitmapMigBitmapState *dbms, } /* Called with iothread lock taken. */ -static void dirty_bitmap_mig_cleanup(void) +static void dirty_bitmap_do_save_cleanup(DBMSaveState *s) { - DirtyBitmapMigBitmapState *dbms; + SaveBitmapState *dbms; - while ((dbms = QSIMPLEQ_FIRST(&dirty_bitmap_mig_state.dbms_list)) != NULL) { - QSIMPLEQ_REMOVE_HEAD(&dirty_bitmap_mig_state.dbms_list, entry); + while ((dbms = QSIMPLEQ_FIRST(&s->dbms_list)) != NULL) { + QSIMPLEQ_REMOVE_HEAD(&s->dbms_list, entry); bdrv_dirty_bitmap_set_busy(dbms->bitmap, false); bdrv_unref(dbms->bs); + g_free(dbms->node_alias); + g_free(dbms->bitmap_alias); g_free(dbms); } } /* Called with iothread lock taken. */ -static int init_dirty_bitmap_migration(void) +static int add_bitmaps_to_list(DBMSaveState *s, BlockDriverState *bs, + const char *bs_name, GHashTable *alias_map) { - BlockDriverState *bs; BdrvDirtyBitmap *bitmap; - DirtyBitmapMigBitmapState *dbms; + SaveBitmapState *dbms; + GHashTable *bitmap_aliases; + const char *node_alias, *bitmap_name, *bitmap_alias; Error *local_err = NULL; - dirty_bitmap_mig_state.bulk_completed = false; - dirty_bitmap_mig_state.prev_bs = NULL; - dirty_bitmap_mig_state.prev_bitmap = NULL; - dirty_bitmap_mig_state.no_bitmaps = false; + /* When an alias map is given, @bs_name must be @bs's node name */ + assert(!alias_map || !strcmp(bs_name, bdrv_get_node_name(bs))); - for (bs = bdrv_next_all_states(NULL); bs; bs = bdrv_next_all_states(bs)) { - const char *name = bdrv_get_device_or_node_name(bs); + FOR_EACH_DIRTY_BITMAP(bs, bitmap) { + if (bdrv_dirty_bitmap_name(bitmap)) { + break; + } + } + if (!bitmap) { + return 0; + } + + bitmap_name = bdrv_dirty_bitmap_name(bitmap); + + if (!bs_name || strcmp(bs_name, "") == 0) { + error_report("Bitmap '%s' in unnamed node can't be migrated", + bitmap_name); + return -1; + } + + if (alias_map) { + const AliasMapInnerNode *amin = g_hash_table_lookup(alias_map, bs_name); + + if (!amin) { + /* Skip bitmaps on nodes with no alias */ + return 0; + } + + node_alias = amin->string; + bitmap_aliases = amin->subtree; + } else { + node_alias = bs_name; + bitmap_aliases = NULL; + } + + if (node_alias[0] == '#') { + error_report("Bitmap '%s' in a node with auto-generated " + "name '%s' can't be migrated", + bitmap_name, node_alias); + return -1; + } + + FOR_EACH_DIRTY_BITMAP(bs, bitmap) { + bitmap_name = bdrv_dirty_bitmap_name(bitmap); + if (!bitmap_name) { + continue; + } - FOR_EACH_DIRTY_BITMAP(bs, bitmap) { - if (!bdrv_dirty_bitmap_name(bitmap)) { + if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, &local_err)) { + error_report_err(local_err); + return -1; + } + + if (bitmap_aliases) { + bitmap_alias = g_hash_table_lookup(bitmap_aliases, bitmap_name); + if (!bitmap_alias) { + /* Skip bitmaps with no alias */ continue; } + } else { + if (strlen(bitmap_name) > UINT8_MAX) { + error_report("Cannot migrate bitmap '%s' on node '%s': " + "Name is longer than %u bytes", + bitmap_name, bs_name, UINT8_MAX); + return -1; + } + bitmap_alias = bitmap_name; + } + + bdrv_ref(bs); + bdrv_dirty_bitmap_set_busy(bitmap, true); + + dbms = g_new0(SaveBitmapState, 1); + dbms->bs = bs; + dbms->node_alias = g_strdup(node_alias); + dbms->bitmap_alias = g_strdup(bitmap_alias); + dbms->bitmap = bitmap; + dbms->total_sectors = bdrv_nb_sectors(bs); + dbms->sectors_per_chunk = CHUNK_SIZE * 8LLU * + (bdrv_dirty_bitmap_granularity(bitmap) >> BDRV_SECTOR_BITS); + assert(dbms->sectors_per_chunk != 0); + if (bdrv_dirty_bitmap_enabled(bitmap)) { + dbms->flags |= DIRTY_BITMAP_MIG_START_FLAG_ENABLED; + } + if (bdrv_dirty_bitmap_get_persistence(bitmap)) { + dbms->flags |= DIRTY_BITMAP_MIG_START_FLAG_PERSISTENT; + } + + QSIMPLEQ_INSERT_TAIL(&s->dbms_list, dbms, entry); + } + + return 0; +} + +/* Called with iothread lock taken. */ +static int init_dirty_bitmap_migration(DBMSaveState *s) +{ + BlockDriverState *bs; + SaveBitmapState *dbms; + GHashTable *handled_by_blk = g_hash_table_new(NULL, NULL); + BlockBackend *blk; + const MigrationParameters *mig_params = &migrate_get_current()->parameters; + GHashTable *alias_map = NULL; + + if (mig_params->has_block_bitmap_mapping) { + alias_map = construct_alias_map(mig_params->block_bitmap_mapping, true, + &error_abort); + } + + s->bulk_completed = false; + s->prev_bs = NULL; + s->prev_bitmap = NULL; + s->no_bitmaps = false; + + if (!alias_map) { + /* + * Use blockdevice name for direct (or filtered) children of named block + * backends. + */ + for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { + const char *name = blk_name(blk); if (!name || strcmp(name, "") == 0) { - error_report("Found bitmap '%s' in unnamed node %p. It can't " - "be migrated", bdrv_dirty_bitmap_name(bitmap), bs); - goto fail; + continue; } - if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, - &local_err)) { - error_report_err(local_err); - goto fail; - } + bs = blk_bs(blk); - bdrv_ref(bs); - bdrv_dirty_bitmap_set_busy(bitmap, true); - - dbms = g_new0(DirtyBitmapMigBitmapState, 1); - dbms->bs = bs; - dbms->node_name = name; - dbms->bitmap = bitmap; - dbms->total_sectors = bdrv_nb_sectors(bs); - dbms->sectors_per_chunk = CHUNK_SIZE * 8 * - bdrv_dirty_bitmap_granularity(bitmap) >> BDRV_SECTOR_BITS; - if (bdrv_dirty_bitmap_enabled(bitmap)) { - dbms->flags |= DIRTY_BITMAP_MIG_START_FLAG_ENABLED; + /* Skip filters without bitmaps */ + while (bs && bs->drv && bs->drv->is_filter && + !bdrv_has_named_bitmaps(bs)) + { + bs = bdrv_filter_bs(bs); } - if (bdrv_dirty_bitmap_get_persistence(bitmap)) { - dbms->flags |= DIRTY_BITMAP_MIG_START_FLAG_PERSISTENT; + + if (bs && bs->drv && !bs->drv->is_filter) { + if (add_bitmaps_to_list(s, bs, name, NULL)) { + goto fail; + } + g_hash_table_add(handled_by_blk, bs); } + } + } + + for (bs = bdrv_next_all_states(NULL); bs; bs = bdrv_next_all_states(bs)) { + if (g_hash_table_contains(handled_by_blk, bs)) { + continue; + } - QSIMPLEQ_INSERT_TAIL(&dirty_bitmap_mig_state.dbms_list, - dbms, entry); + if (add_bitmaps_to_list(s, bs, bdrv_get_node_name(bs), alias_map)) { + goto fail; } } /* unset migration flags here, to not roll back it */ - QSIMPLEQ_FOREACH(dbms, &dirty_bitmap_mig_state.dbms_list, entry) { + QSIMPLEQ_FOREACH(dbms, &s->dbms_list, entry) { bdrv_dirty_bitmap_skip_store(dbms->bitmap, true); } - if (QSIMPLEQ_EMPTY(&dirty_bitmap_mig_state.dbms_list)) { - dirty_bitmap_mig_state.no_bitmaps = true; + if (QSIMPLEQ_EMPTY(&s->dbms_list)) { + s->no_bitmaps = true; + } + + g_hash_table_destroy(handled_by_blk); + if (alias_map) { + g_hash_table_destroy(alias_map); } return 0; fail: - dirty_bitmap_mig_cleanup(); + g_hash_table_destroy(handled_by_blk); + if (alias_map) { + g_hash_table_destroy(alias_map); + } + dirty_bitmap_do_save_cleanup(s); return -1; } /* Called with no lock taken. */ -static void bulk_phase_send_chunk(QEMUFile *f, DirtyBitmapMigBitmapState *dbms) +static void bulk_phase_send_chunk(QEMUFile *f, DBMSaveState *s, + SaveBitmapState *dbms) { uint32_t nr_sectors = MIN(dbms->total_sectors - dbms->cur_sector, dbms->sectors_per_chunk); - send_bitmap_bits(f, dbms, dbms->cur_sector, nr_sectors); + send_bitmap_bits(f, s, dbms, dbms->cur_sector, nr_sectors); dbms->cur_sector += nr_sectors; if (dbms->cur_sector >= dbms->total_sectors) { @@ -354,61 +680,66 @@ static void bulk_phase_send_chunk(QEMUFile *f, DirtyBitmapMigBitmapState *dbms) } /* Called with no lock taken. */ -static void bulk_phase(QEMUFile *f, bool limit) +static void bulk_phase(QEMUFile *f, DBMSaveState *s, bool limit) { - DirtyBitmapMigBitmapState *dbms; + SaveBitmapState *dbms; - QSIMPLEQ_FOREACH(dbms, &dirty_bitmap_mig_state.dbms_list, entry) { + QSIMPLEQ_FOREACH(dbms, &s->dbms_list, entry) { while (!dbms->bulk_completed) { - bulk_phase_send_chunk(f, dbms); + bulk_phase_send_chunk(f, s, dbms); if (limit && qemu_file_rate_limit(f)) { return; } } } - dirty_bitmap_mig_state.bulk_completed = true; + s->bulk_completed = true; } /* for SaveVMHandlers */ static void dirty_bitmap_save_cleanup(void *opaque) { - dirty_bitmap_mig_cleanup(); + DBMSaveState *s = &((DBMState *)opaque)->save; + + dirty_bitmap_do_save_cleanup(s); } static int dirty_bitmap_save_iterate(QEMUFile *f, void *opaque) { + DBMSaveState *s = &((DBMState *)opaque)->save; + trace_dirty_bitmap_save_iterate(migration_in_postcopy()); - if (migration_in_postcopy() && !dirty_bitmap_mig_state.bulk_completed) { - bulk_phase(f, true); + if (migration_in_postcopy() && !s->bulk_completed) { + bulk_phase(f, s, true); } qemu_put_bitmap_flags(f, DIRTY_BITMAP_MIG_FLAG_EOS); - return dirty_bitmap_mig_state.bulk_completed; + return s->bulk_completed; } /* Called with iothread lock taken. */ static int dirty_bitmap_save_complete(QEMUFile *f, void *opaque) { - DirtyBitmapMigBitmapState *dbms; + DBMSaveState *s = &((DBMState *)opaque)->save; + SaveBitmapState *dbms; trace_dirty_bitmap_save_complete_enter(); - if (!dirty_bitmap_mig_state.bulk_completed) { - bulk_phase(f, false); + if (!s->bulk_completed) { + bulk_phase(f, s, false); } - QSIMPLEQ_FOREACH(dbms, &dirty_bitmap_mig_state.dbms_list, entry) { - send_bitmap_complete(f, dbms); + QSIMPLEQ_FOREACH(dbms, &s->dbms_list, entry) { + send_bitmap_complete(f, s, dbms); } qemu_put_bitmap_flags(f, DIRTY_BITMAP_MIG_FLAG_EOS); trace_dirty_bitmap_save_complete_finish(); - dirty_bitmap_mig_cleanup(); + dirty_bitmap_save_cleanup(opaque); return 0; } @@ -418,12 +749,13 @@ static void dirty_bitmap_save_pending(QEMUFile *f, void *opaque, uint64_t *res_compatible, uint64_t *res_postcopy_only) { - DirtyBitmapMigBitmapState *dbms; + DBMSaveState *s = &((DBMState *)opaque)->save; + SaveBitmapState *dbms; uint64_t pending = 0; qemu_mutex_lock_iothread(); - QSIMPLEQ_FOREACH(dbms, &dirty_bitmap_mig_state.dbms_list, entry) { + QSIMPLEQ_FOREACH(dbms, &s->dbms_list, entry) { uint64_t gran = bdrv_dirty_bitmap_granularity(dbms->bitmap); uint64_t sectors = dbms->bulk_completed ? 0 : dbms->total_sectors - dbms->cur_sector; @@ -439,11 +771,16 @@ static void dirty_bitmap_save_pending(QEMUFile *f, void *opaque, } /* First occurrence of this bitmap. It should be created if doesn't exist */ -static int dirty_bitmap_load_start(QEMUFile *f, DirtyBitmapLoadState *s) +static int dirty_bitmap_load_start(QEMUFile *f, DBMLoadState *s) { Error *local_err = NULL; uint32_t granularity = qemu_get_be32(f); uint8_t flags = qemu_get_byte(f); + LoadBitmapState *b; + + if (s->cancelled) { + return 0; + } if (s->bitmap) { error_report("Bitmap with the same name ('%s') already exists on " @@ -470,90 +807,140 @@ static int dirty_bitmap_load_start(QEMUFile *f, DirtyBitmapLoadState *s) bdrv_disable_dirty_bitmap(s->bitmap); if (flags & DIRTY_BITMAP_MIG_START_FLAG_ENABLED) { - DirtyBitmapLoadBitmapState *b; - bdrv_dirty_bitmap_create_successor(s->bitmap, &local_err); if (local_err) { error_report_err(local_err); return -EINVAL; } - - b = g_new(DirtyBitmapLoadBitmapState, 1); - b->bs = s->bs; - b->bitmap = s->bitmap; - b->migrated = false; - enabled_bitmaps = g_slist_prepend(enabled_bitmaps, b); } + b = g_new(LoadBitmapState, 1); + b->bs = s->bs; + b->bitmap = s->bitmap; + b->migrated = false; + b->enabled = flags & DIRTY_BITMAP_MIG_START_FLAG_ENABLED; + + s->bitmaps = g_slist_prepend(s->bitmaps, b); + return 0; } -void dirty_bitmap_mig_before_vm_start(void) +/* + * before_vm_start_handle_item + * + * g_slist_foreach helper + * + * item is LoadBitmapState* + * opaque is DBMLoadState* + */ +static void before_vm_start_handle_item(void *item, void *opaque) { - GSList *item; - - qemu_mutex_lock(&finish_lock); - - for (item = enabled_bitmaps; item; item = g_slist_next(item)) { - DirtyBitmapLoadBitmapState *b = item->data; + DBMLoadState *s = opaque; + LoadBitmapState *b = item; + if (b->enabled) { if (b->migrated) { - bdrv_enable_dirty_bitmap_locked(b->bitmap); + bdrv_enable_dirty_bitmap(b->bitmap); } else { bdrv_dirty_bitmap_enable_successor(b->bitmap); } + } + if (b->migrated) { + s->bitmaps = g_slist_remove(s->bitmaps, b); g_free(b); } +} - g_slist_free(enabled_bitmaps); - enabled_bitmaps = NULL; +void dirty_bitmap_mig_before_vm_start(void) +{ + DBMLoadState *s = &dbm_state.load; + qemu_mutex_lock(&s->lock); + + assert(!s->before_vm_start_handled); + g_slist_foreach(s->bitmaps, before_vm_start_handle_item, s); + s->before_vm_start_handled = true; - qemu_mutex_unlock(&finish_lock); + qemu_mutex_unlock(&s->lock); } -static void dirty_bitmap_load_complete(QEMUFile *f, DirtyBitmapLoadState *s) +static void cancel_incoming_locked(DBMLoadState *s) +{ + GSList *item; + + if (s->cancelled) { + return; + } + + s->cancelled = true; + s->bs = NULL; + s->bitmap = NULL; + + /* Drop all unfinished bitmaps */ + for (item = s->bitmaps; item; item = g_slist_next(item)) { + LoadBitmapState *b = item->data; + + /* + * Bitmap must be unfinished, as finished bitmaps should already be + * removed from the list. + */ + assert(!s->before_vm_start_handled || !b->migrated); + if (bdrv_dirty_bitmap_has_successor(b->bitmap)) { + bdrv_reclaim_dirty_bitmap(b->bitmap, &error_abort); + } + bdrv_release_dirty_bitmap(b->bitmap); + } + + g_slist_free_full(s->bitmaps, g_free); + s->bitmaps = NULL; +} + +void dirty_bitmap_mig_cancel_outgoing(void) +{ + dirty_bitmap_do_save_cleanup(&dbm_state.save); +} + +void dirty_bitmap_mig_cancel_incoming(void) +{ + DBMLoadState *s = &dbm_state.load; + + qemu_mutex_lock(&s->lock); + + cancel_incoming_locked(s); + + qemu_mutex_unlock(&s->lock); +} + +static void dirty_bitmap_load_complete(QEMUFile *f, DBMLoadState *s) { GSList *item; trace_dirty_bitmap_load_complete(); + + if (s->cancelled) { + return; + } + bdrv_dirty_bitmap_deserialize_finish(s->bitmap); - qemu_mutex_lock(&finish_lock); + if (bdrv_dirty_bitmap_has_successor(s->bitmap)) { + bdrv_reclaim_dirty_bitmap(s->bitmap, &error_abort); + } - for (item = enabled_bitmaps; item; item = g_slist_next(item)) { - DirtyBitmapLoadBitmapState *b = item->data; + for (item = s->bitmaps; item; item = g_slist_next(item)) { + LoadBitmapState *b = item->data; if (b->bitmap == s->bitmap) { b->migrated = true; + if (s->before_vm_start_handled) { + s->bitmaps = g_slist_remove(s->bitmaps, b); + g_free(b); + } break; } } - - if (bdrv_dirty_bitmap_has_successor(s->bitmap)) { - bdrv_dirty_bitmap_lock(s->bitmap); - if (enabled_bitmaps == NULL) { - /* in postcopy */ - bdrv_reclaim_dirty_bitmap_locked(s->bitmap, &error_abort); - bdrv_enable_dirty_bitmap_locked(s->bitmap); - } else { - /* target not started, successor must be empty */ - int64_t count = bdrv_get_dirty_count(s->bitmap); - BdrvDirtyBitmap *ret = bdrv_reclaim_dirty_bitmap_locked(s->bitmap, - NULL); - /* bdrv_reclaim_dirty_bitmap can fail only on no successor (it - * must be) or on merge fail, but merge can't fail when second - * bitmap is empty - */ - assert(ret == s->bitmap && - count == bdrv_get_dirty_count(s->bitmap)); - } - bdrv_dirty_bitmap_unlock(s->bitmap); - } - - qemu_mutex_unlock(&finish_lock); } -static int dirty_bitmap_load_bits(QEMUFile *f, DirtyBitmapLoadState *s) +static int dirty_bitmap_load_bits(QEMUFile *f, DBMLoadState *s) { uint64_t first_byte = qemu_get_be64(f) << BDRV_SECTOR_BITS; uint64_t nr_bytes = (uint64_t)qemu_get_be32(f) << BDRV_SECTOR_BITS; @@ -562,15 +949,46 @@ static int dirty_bitmap_load_bits(QEMUFile *f, DirtyBitmapLoadState *s) if (s->flags & DIRTY_BITMAP_MIG_FLAG_ZEROES) { trace_dirty_bitmap_load_bits_zeroes(); - bdrv_dirty_bitmap_deserialize_zeroes(s->bitmap, first_byte, nr_bytes, - false); + if (!s->cancelled) { + bdrv_dirty_bitmap_deserialize_zeroes(s->bitmap, first_byte, + nr_bytes, false); + } } else { size_t ret; - uint8_t *buf; + g_autofree uint8_t *buf = NULL; uint64_t buf_size = qemu_get_be64(f); - uint64_t needed_size = - bdrv_dirty_bitmap_serialization_size(s->bitmap, - first_byte, nr_bytes); + uint64_t needed_size; + + /* + * The actual check for buf_size is done a bit later. We can't do it in + * cancelled mode as we don't have the bitmap to check the constraints + * (so, we allocate a buffer and read prior to the check). On the other + * hand, we shouldn't blindly g_malloc the number from the stream. + * Actually one chunk should not be larger than CHUNK_SIZE. Let's allow + * a bit larger (which means that bitmap migration will fail anyway and + * the whole migration will most probably fail soon due to broken + * stream). + */ + if (buf_size > 10 * CHUNK_SIZE) { + error_report("Bitmap migration stream buffer allocation request " + "is too large"); + return -EIO; + } + + buf = g_malloc(buf_size); + ret = qemu_get_buffer(f, buf, buf_size); + if (ret != buf_size) { + error_report("Failed to read bitmap bits"); + return -EIO; + } + + if (s->cancelled) { + return 0; + } + + needed_size = bdrv_dirty_bitmap_serialization_size(s->bitmap, + first_byte, + nr_bytes); if (needed_size > buf_size || buf_size > QEMU_ALIGN_UP(needed_size, 4 * sizeof(long)) @@ -579,27 +997,21 @@ static int dirty_bitmap_load_bits(QEMUFile *f, DirtyBitmapLoadState *s) error_report("Migrated bitmap granularity doesn't " "match the destination bitmap '%s' granularity", bdrv_dirty_bitmap_name(s->bitmap)); - return -EINVAL; - } - - buf = g_malloc(buf_size); - ret = qemu_get_buffer(f, buf, buf_size); - if (ret != buf_size) { - error_report("Failed to read bitmap bits"); - g_free(buf); - return -EIO; + cancel_incoming_locked(s); + return 0; } bdrv_dirty_bitmap_deserialize_part(s->bitmap, buf, first_byte, nr_bytes, false); - g_free(buf); } return 0; } -static int dirty_bitmap_load_header(QEMUFile *f, DirtyBitmapLoadState *s) +static int dirty_bitmap_load_header(QEMUFile *f, DBMLoadState *s, + GHashTable *alias_map) { + GHashTable *bitmap_alias_map = NULL; Error *local_err = NULL; bool nothing; s->flags = qemu_get_bitmap_flags(f); @@ -608,66 +1020,138 @@ static int dirty_bitmap_load_header(QEMUFile *f, DirtyBitmapLoadState *s) nothing = s->flags == (s->flags & DIRTY_BITMAP_MIG_FLAG_EOS); if (s->flags & DIRTY_BITMAP_MIG_FLAG_DEVICE_NAME) { - if (!qemu_get_counted_string(f, s->node_name)) { - error_report("Unable to read node name string"); + if (!qemu_get_counted_string(f, s->node_alias)) { + error_report("Unable to read node alias string"); return -EINVAL; } - s->bs = bdrv_lookup_bs(s->node_name, s->node_name, &local_err); - if (!s->bs) { - error_report_err(local_err); - return -EINVAL; + + if (!s->cancelled) { + if (alias_map) { + const AliasMapInnerNode *amin; + + amin = g_hash_table_lookup(alias_map, s->node_alias); + if (!amin) { + error_setg(&local_err, "Error: Unknown node alias '%s'", + s->node_alias); + s->bs = NULL; + } else { + bitmap_alias_map = amin->subtree; + s->bs = bdrv_lookup_bs(NULL, amin->string, &local_err); + } + } else { + s->bs = bdrv_lookup_bs(s->node_alias, s->node_alias, + &local_err); + } + if (!s->bs) { + error_report_err(local_err); + cancel_incoming_locked(s); + } } - } else if (!s->bs && !nothing) { + } else if (s->bs) { + if (alias_map) { + const AliasMapInnerNode *amin; + + /* Must be present in the map, or s->bs would not be set */ + amin = g_hash_table_lookup(alias_map, s->node_alias); + assert(amin != NULL); + + bitmap_alias_map = amin->subtree; + } + } else if (!nothing && !s->cancelled) { error_report("Error: block device name is not set"); - return -EINVAL; + cancel_incoming_locked(s); } + assert(nothing || s->cancelled || !!alias_map == !!bitmap_alias_map); + if (s->flags & DIRTY_BITMAP_MIG_FLAG_BITMAP_NAME) { - if (!qemu_get_counted_string(f, s->bitmap_name)) { - error_report("Unable to read bitmap name string"); + const char *bitmap_name; + + if (!qemu_get_counted_string(f, s->bitmap_alias)) { + error_report("Unable to read bitmap alias string"); return -EINVAL; } - s->bitmap = bdrv_find_dirty_bitmap(s->bs, s->bitmap_name); - /* bitmap may be NULL here, it wouldn't be an error if it is the - * first occurrence of the bitmap */ - if (!s->bitmap && !(s->flags & DIRTY_BITMAP_MIG_FLAG_START)) { - error_report("Error: unknown dirty bitmap " - "'%s' for block device '%s'", - s->bitmap_name, s->node_name); - return -EINVAL; + bitmap_name = s->bitmap_alias; + if (!s->cancelled && bitmap_alias_map) { + bitmap_name = g_hash_table_lookup(bitmap_alias_map, + s->bitmap_alias); + if (!bitmap_name) { + error_report("Error: Unknown bitmap alias '%s' on node " + "'%s' (alias '%s')", s->bitmap_alias, + s->bs->node_name, s->node_alias); + cancel_incoming_locked(s); + } + } + + if (!s->cancelled) { + g_strlcpy(s->bitmap_name, bitmap_name, sizeof(s->bitmap_name)); + s->bitmap = bdrv_find_dirty_bitmap(s->bs, s->bitmap_name); + + /* + * bitmap may be NULL here, it wouldn't be an error if it is the + * first occurrence of the bitmap + */ + if (!s->bitmap && !(s->flags & DIRTY_BITMAP_MIG_FLAG_START)) { + error_report("Error: unknown dirty bitmap " + "'%s' for block device '%s'", + s->bitmap_name, s->bs->node_name); + cancel_incoming_locked(s); + } } - } else if (!s->bitmap && !nothing) { + } else if (!s->bitmap && !nothing && !s->cancelled) { error_report("Error: block device name is not set"); - return -EINVAL; + cancel_incoming_locked(s); } return 0; } +/* + * dirty_bitmap_load + * + * Load sequence of dirty bitmap chunks. Return error only on fatal io stream + * violations. On other errors just cancel bitmaps incoming migration and return + * 0. + * + * Note, than when incoming bitmap migration is canceled, we still must read all + * our chunks (and just ignore them), to not affect other migration objects. + */ static int dirty_bitmap_load(QEMUFile *f, void *opaque, int version_id) { - static DirtyBitmapLoadState s; + GHashTable *alias_map = NULL; + const MigrationParameters *mig_params = &migrate_get_current()->parameters; + DBMLoadState *s = &((DBMState *)opaque)->load; int ret = 0; trace_dirty_bitmap_load_enter(); if (version_id != 1) { + QEMU_LOCK_GUARD(&s->lock); + cancel_incoming_locked(s); return -EINVAL; } + if (mig_params->has_block_bitmap_mapping) { + alias_map = construct_alias_map(mig_params->block_bitmap_mapping, + false, &error_abort); + } + do { - ret = dirty_bitmap_load_header(f, &s); + QEMU_LOCK_GUARD(&s->lock); + + ret = dirty_bitmap_load_header(f, s, alias_map); if (ret < 0) { - return ret; + cancel_incoming_locked(s); + goto fail; } - if (s.flags & DIRTY_BITMAP_MIG_FLAG_START) { - ret = dirty_bitmap_load_start(f, &s); - } else if (s.flags & DIRTY_BITMAP_MIG_FLAG_COMPLETE) { - dirty_bitmap_load_complete(f, &s); - } else if (s.flags & DIRTY_BITMAP_MIG_FLAG_BITS) { - ret = dirty_bitmap_load_bits(f, &s); + if (s->flags & DIRTY_BITMAP_MIG_FLAG_START) { + ret = dirty_bitmap_load_start(f, s); + } else if (s->flags & DIRTY_BITMAP_MIG_FLAG_COMPLETE) { + dirty_bitmap_load_complete(f, s); + } else if (s->flags & DIRTY_BITMAP_MIG_FLAG_BITS) { + ret = dirty_bitmap_load_bits(f, s); } if (!ret) { @@ -675,23 +1159,30 @@ static int dirty_bitmap_load(QEMUFile *f, void *opaque, int version_id) } if (ret) { - return ret; + cancel_incoming_locked(s); + goto fail; } - } while (!(s.flags & DIRTY_BITMAP_MIG_FLAG_EOS)); + } while (!(s->flags & DIRTY_BITMAP_MIG_FLAG_EOS)); trace_dirty_bitmap_load_success(); - return 0; + ret = 0; +fail: + if (alias_map) { + g_hash_table_destroy(alias_map); + } + return ret; } static int dirty_bitmap_save_setup(QEMUFile *f, void *opaque) { - DirtyBitmapMigBitmapState *dbms = NULL; - if (init_dirty_bitmap_migration() < 0) { + DBMSaveState *s = &((DBMState *)opaque)->save; + SaveBitmapState *dbms = NULL; + if (init_dirty_bitmap_migration(s) < 0) { return -1; } - QSIMPLEQ_FOREACH(dbms, &dirty_bitmap_mig_state.dbms_list, entry) { - send_bitmap_start(f, dbms); + QSIMPLEQ_FOREACH(dbms, &s->dbms_list, entry) { + send_bitmap_start(f, s, dbms); } qemu_put_bitmap_flags(f, DIRTY_BITMAP_MIG_FLAG_EOS); @@ -700,7 +1191,9 @@ static int dirty_bitmap_save_setup(QEMUFile *f, void *opaque) static bool dirty_bitmap_is_active(void *opaque) { - return migrate_dirty_bitmaps() && !dirty_bitmap_mig_state.no_bitmaps; + DBMSaveState *s = &((DBMState *)opaque)->save; + + return migrate_dirty_bitmaps() && !s->no_bitmaps; } static bool dirty_bitmap_is_active_iterate(void *opaque) @@ -728,9 +1221,10 @@ static SaveVMHandlers savevm_dirty_bitmap_handlers = { void dirty_bitmap_mig_init(void) { - QSIMPLEQ_INIT(&dirty_bitmap_mig_state.dbms_list); + QSIMPLEQ_INIT(&dbm_state.save.dbms_list); + qemu_mutex_init(&dbm_state.load.lock); register_savevm_live("dirty-bitmap", 0, 1, &savevm_dirty_bitmap_handlers, - &dirty_bitmap_mig_state); + &dbm_state); } diff --git a/migration/block.c b/migration/block.c index 737b6499f9534a55dbbf17e7628a2774972b0f6f..a950977855281bb0b3de321f1432462485a9d62f 100644 --- a/migration/block.c +++ b/migration/block.c @@ -26,6 +26,7 @@ #include "qemu-file.h" #include "migration/vmstate.h" #include "sysemu/block-backend.h" +#include "trace.h" #define BLK_MIG_BLOCK_SIZE (1 << 20) #define BDRV_SECTORS_PER_DIRTY_CHUNK (BLK_MIG_BLOCK_SIZE >> BDRV_SECTOR_BITS) @@ -40,7 +41,7 @@ #define MAX_IO_BUFFERS 512 #define MAX_PARALLEL_IO 16 -//#define DEBUG_BLK_MIGRATION +/* #define DEBUG_BLK_MIGRATION */ #ifdef DEBUG_BLK_MIGRATION #define DPRINTF(fmt, ...) \ @@ -434,10 +435,9 @@ static int init_blk_migration(QEMUFile *f) block_mig_state.total_sector_sum += sectors; if (bmds->shared_base) { - DPRINTF("Start migration for %s with shared base image\n", - bdrv_get_device_name(bs)); + trace_migration_block_init_shared(bdrv_get_device_name(bs)); } else { - DPRINTF("Start full migration for %s\n", bdrv_get_device_name(bs)); + trace_migration_block_init_full(bdrv_get_device_name(bs)); } QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry); @@ -592,7 +592,7 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds, return (bmds->cur_dirty >= bmds->total_sectors); error: - DPRINTF("Error reading sector %" PRId64 "\n", sector); + trace_migration_block_save_device_dirty(sector); g_free(blk->buf); g_free(blk); return ret; @@ -628,9 +628,9 @@ static int flush_blks(QEMUFile *f) BlkMigBlock *blk; int ret = 0; - DPRINTF("%s Enter submitted %d read_done %d transferred %d\n", - __func__, block_mig_state.submitted, block_mig_state.read_done, - block_mig_state.transferred); + trace_migration_block_flush_blks("Enter", block_mig_state.submitted, + block_mig_state.read_done, + block_mig_state.transferred); blk_mig_lock(); while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) { @@ -656,9 +656,9 @@ static int flush_blks(QEMUFile *f) } blk_mig_unlock(); - DPRINTF("%s Exit submitted %d read_done %d transferred %d\n", __func__, - block_mig_state.submitted, block_mig_state.read_done, - block_mig_state.transferred); + trace_migration_block_flush_blks("Exit", block_mig_state.submitted, + block_mig_state.read_done, + block_mig_state.transferred); return ret; } @@ -727,8 +727,8 @@ static int block_save_setup(QEMUFile *f, void *opaque) { int ret; - DPRINTF("Enter save live setup submitted %d transferred %d\n", - block_mig_state.submitted, block_mig_state.transferred); + trace_migration_block_save("setup", block_mig_state.submitted, + block_mig_state.transferred); qemu_mutex_lock_iothread(); ret = init_blk_migration(f); @@ -759,8 +759,8 @@ static int block_save_iterate(QEMUFile *f, void *opaque) int64_t last_ftell = qemu_ftell(f); int64_t delta_ftell; - DPRINTF("Enter save live iterate submitted %d transferred %d\n", - block_mig_state.submitted, block_mig_state.transferred); + trace_migration_block_save("iterate", block_mig_state.submitted, + block_mig_state.transferred); ret = flush_blks(f); if (ret) { @@ -825,8 +825,8 @@ static int block_save_complete(QEMUFile *f, void *opaque) { int ret; - DPRINTF("Enter save live complete submitted %d transferred %d\n", - block_mig_state.submitted, block_mig_state.transferred); + trace_migration_block_save("complete", block_mig_state.submitted, + block_mig_state.transferred); ret = flush_blks(f); if (ret) { @@ -851,7 +851,7 @@ static int block_save_complete(QEMUFile *f, void *opaque) /* report completion */ qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS); - DPRINTF("Block migration completed\n"); + trace_migration_block_save_complete(); qemu_put_be64(f, BLK_MIG_FLAG_EOS); @@ -884,7 +884,7 @@ static void block_save_pending(QEMUFile *f, void *opaque, uint64_t max_size, pending = max_size + BLK_MIG_BLOCK_SIZE; } - DPRINTF("Enter save live pending %" PRIu64 "\n", pending); + trace_migration_block_save_pending(pending); /* We don't do postcopy */ *res_precopy_only += pending; } @@ -998,7 +998,7 @@ static int block_load(QEMUFile *f, void *opaque, int version_id) (addr == 100) ? '\n' : '\r'); fflush(stdout); } else if (!(flags & BLK_MIG_FLAG_EOS)) { - fprintf(stderr, "Unknown block migration flags: %#x\n", flags); + fprintf(stderr, "Unknown block migration flags: 0x%x\n", flags); return -EINVAL; } ret = qemu_file_get_error(f); diff --git a/migration/channel.c b/migration/channel.c index 20e4c8e2dc84c90d48e01c8add803b71c5e1e941..8a783baa0becdbda75991ade8938f6fdb2282a34 100644 --- a/migration/channel.c +++ b/migration/channel.c @@ -90,5 +90,6 @@ void migration_channel_connect(MigrationState *s, } } migrate_fd_connect(s, error); + g_free(s->hostname); error_free(error); } diff --git a/migration/colo-failover.c b/migration/colo-failover.c index e9ca0b47744b73f20707b105300733f2f0640b69..42453481c41aec7d2b27a2ed699035cb007af253 100644 --- a/migration/colo-failover.c +++ b/migration/colo-failover.c @@ -46,7 +46,7 @@ void failover_request_active(Error **errp) { if (failover_set_state(FAILOVER_STATUS_NONE, FAILOVER_STATUS_REQUIRE) != FAILOVER_STATUS_NONE) { - error_setg(errp, "COLO failover is already actived"); + error_setg(errp, "COLO failover is already activated"); return; } failover_bh = qemu_bh_new(colo_failover_bh, NULL); @@ -63,7 +63,7 @@ FailoverStatus failover_set_state(FailoverStatus old_state, { FailoverStatus old; - old = atomic_cmpxchg(&failover_state, old_state, new_state); + old = qatomic_cmpxchg(&failover_state, old_state, new_state); if (old == old_state) { trace_colo_failover_set_state(FailoverStatus_str(new_state)); } @@ -72,7 +72,7 @@ FailoverStatus failover_set_state(FailoverStatus old_state, FailoverStatus failover_get_state(void) { - return atomic_read(&failover_state); + return qatomic_read(&failover_state); } void qmp_x_colo_lost_heartbeat(Error **errp) diff --git a/migration/colo.c b/migration/colo.c index d015d4f84e2fd709096aa79981966f8aaa47b0c3..3f1d3dfd956122632b42d74e63b030362e27f761 100644 --- a/migration/colo.c +++ b/migration/colo.c @@ -436,11 +436,6 @@ static int colo_do_checkpoint_transaction(MigrationState *s, goto out; } - colo_notify_compares_event(NULL, COLO_EVENT_CHECKPOINT, &local_err); - if (local_err) { - goto out; - } - /* Disable block migration */ migrate_set_block_enabled(false, &local_err); if (local_err) { @@ -502,6 +497,12 @@ static int colo_do_checkpoint_transaction(MigrationState *s, goto out; } + qemu_event_reset(&s->colo_checkpoint_event); + colo_notify_compares_event(NULL, COLO_EVENT_CHECKPOINT, &local_err); + if (local_err) { + goto out; + } + colo_receive_check_message(s->rp_state.from_dst_file, COLO_MESSAGE_VMSTATE_LOADED, &local_err); if (local_err) { @@ -589,7 +590,7 @@ static void colo_process_checkpoint(MigrationState *s) goto out; } - qemu_sem_wait(&s->colo_checkpoint_sem); + qemu_event_wait(&s->colo_checkpoint_event); if (s->state != MIGRATION_STATUS_COLO) { goto out; @@ -631,13 +632,13 @@ out: /* * It is safe to unregister notifier after failover finished. * Besides, colo_delay_timer and colo_checkpoint_sem can't be - * released befor unregister notifier, or there will be use-after-free + * released before unregister notifier, or there will be use-after-free * error. */ colo_compare_unregister_notifier(&packets_compare_notifier); timer_del(s->colo_delay_timer); timer_free(s->colo_delay_timer); - qemu_sem_destroy(&s->colo_checkpoint_sem); + qemu_event_destroy(&s->colo_checkpoint_event); /* * Must be called after failover BH is completed, @@ -654,7 +655,7 @@ void colo_checkpoint_notify(void *opaque) MigrationState *s = opaque; int64_t next_notify_time; - qemu_sem_post(&s->colo_checkpoint_sem); + qemu_event_set(&s->colo_checkpoint_event); s->colo_checkpoint_time = qemu_clock_get_ms(QEMU_CLOCK_HOST); next_notify_time = s->colo_checkpoint_time + s->parameters.x_checkpoint_delay; @@ -664,7 +665,7 @@ void colo_checkpoint_notify(void *opaque) void migrate_start_colo_process(MigrationState *s) { qemu_mutex_unlock_iothread(); - qemu_sem_init(&s->colo_checkpoint_sem, 0); + qemu_event_init(&s->colo_checkpoint_event, false); s->colo_delay_timer = timer_new_ms(QEMU_CLOCK_HOST, colo_checkpoint_notify, s); @@ -704,7 +705,7 @@ static void colo_incoming_process_checkpoint(MigrationIncomingState *mis, } qemu_mutex_lock_iothread(); - cpu_synchronize_all_pre_loadvm(); + cpu_synchronize_all_states(); ret = qemu_loadvm_state_main(mis->from_src_file, mis); qemu_mutex_unlock_iothread(); @@ -747,9 +748,11 @@ static void colo_incoming_process_checkpoint(MigrationIncomingState *mis, qemu_mutex_lock_iothread(); vmstate_loading = true; + colo_flush_ram_cache(); ret = qemu_load_device_state(fb); if (ret < 0) { error_setg(errp, "COLO: load device state failed"); + vmstate_loading = false; qemu_mutex_unlock_iothread(); return; } @@ -758,6 +761,7 @@ static void colo_incoming_process_checkpoint(MigrationIncomingState *mis, replication_get_error_all(&local_err); if (local_err) { error_propagate(errp, local_err); + vmstate_loading = false; qemu_mutex_unlock_iothread(); return; } @@ -766,6 +770,7 @@ static void colo_incoming_process_checkpoint(MigrationIncomingState *mis, replication_do_checkpoint_all(&local_err); if (local_err) { error_propagate(errp, local_err); + vmstate_loading = false; qemu_mutex_unlock_iothread(); return; } @@ -777,6 +782,7 @@ static void colo_incoming_process_checkpoint(MigrationIncomingState *mis, if (local_err) { error_propagate(errp, local_err); + vmstate_loading = false; qemu_mutex_unlock_iothread(); return; } @@ -787,17 +793,12 @@ static void colo_incoming_process_checkpoint(MigrationIncomingState *mis, qemu_mutex_unlock_iothread(); if (failover_get_state() == FAILOVER_STATUS_RELAUNCH) { - failover_set_state(FAILOVER_STATUS_RELAUNCH, - FAILOVER_STATUS_NONE); - failover_request_active(NULL); return; } colo_send_message(mis->to_src_file, COLO_MESSAGE_VMSTATE_LOADED, &local_err); - if (local_err) { - error_propagate(errp, local_err); - } + error_propagate(errp, local_err); } static void colo_wait_handle_message(MigrationIncomingState *mis, @@ -888,6 +889,14 @@ void *colo_process_incoming_thread(void *opaque) error_report_err(local_err); break; } + + if (failover_get_state() == FAILOVER_STATUS_RELAUNCH) { + failover_set_state(FAILOVER_STATUS_RELAUNCH, + FAILOVER_STATUS_NONE); + failover_request_active(NULL); + break; + } + if (failover_get_state() != FAILOVER_STATUS_NONE) { error_report("failover request"); break; @@ -895,8 +904,6 @@ void *colo_process_incoming_thread(void *opaque) } out: - vmstate_loading = false; - /* * There are only two reasons we can get here, some error happened * or the user triggered failover. diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c new file mode 100644 index 0000000000000000000000000000000000000000..ccb98147e8918d58c0da80695fa41844326a0621 --- /dev/null +++ b/migration/dirtyrate.c @@ -0,0 +1,426 @@ +/* + * Dirtyrate implement code + * + * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO.,LTD. + * + * Authors: + * Chuan Zheng + * + * 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 +#include "qapi/error.h" +#include "cpu.h" +#include "exec/ramblock.h" +#include "qemu/rcu_queue.h" +#include "qapi/qapi-commands-migration.h" +#include "ram.h" +#include "trace.h" +#include "dirtyrate.h" + +static int CalculatingState = DIRTY_RATE_STATUS_UNSTARTED; +static struct DirtyRateStat DirtyStat; + +static int64_t set_sample_page_period(int64_t msec, int64_t initial_time) +{ + int64_t current_time; + + current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); + if ((current_time - initial_time) >= msec) { + msec = current_time - initial_time; + } else { + g_usleep((msec + initial_time - current_time) * 1000); + } + + return msec; +} + +static bool is_sample_period_valid(int64_t sec) +{ + if (sec < MIN_FETCH_DIRTYRATE_TIME_SEC || + sec > MAX_FETCH_DIRTYRATE_TIME_SEC) { + return false; + } + + return true; +} + +static int dirtyrate_set_state(int *state, int old_state, int new_state) +{ + assert(new_state < DIRTY_RATE_STATUS__MAX); + trace_dirtyrate_set_state(DirtyRateStatus_str(new_state)); + if (qatomic_cmpxchg(state, old_state, new_state) == old_state) { + return 0; + } else { + return -1; + } +} + +static struct DirtyRateInfo *query_dirty_rate_info(void) +{ + int64_t dirty_rate = DirtyStat.dirty_rate; + struct DirtyRateInfo *info = g_malloc0(sizeof(DirtyRateInfo)); + + if (qatomic_read(&CalculatingState) == DIRTY_RATE_STATUS_MEASURED) { + info->has_dirty_rate = true; + info->dirty_rate = dirty_rate; + } + + info->status = CalculatingState; + info->start_time = DirtyStat.start_time; + info->calc_time = DirtyStat.calc_time; + + trace_query_dirty_rate_info(DirtyRateStatus_str(CalculatingState)); + + return info; +} + +static void init_dirtyrate_stat(int64_t start_time, int64_t calc_time) +{ + DirtyStat.total_dirty_samples = 0; + DirtyStat.total_sample_count = 0; + DirtyStat.total_block_mem_MB = 0; + DirtyStat.dirty_rate = -1; + DirtyStat.start_time = start_time; + DirtyStat.calc_time = calc_time; +} + +static void update_dirtyrate_stat(struct RamblockDirtyInfo *info) +{ + DirtyStat.total_dirty_samples += info->sample_dirty_count; + DirtyStat.total_sample_count += info->sample_pages_count; + /* size of total pages in MB */ + DirtyStat.total_block_mem_MB += (info->ramblock_pages * + TARGET_PAGE_SIZE) >> 20; +} + +static void update_dirtyrate(uint64_t msec) +{ + uint64_t dirtyrate; + uint64_t total_dirty_samples = DirtyStat.total_dirty_samples; + uint64_t total_sample_count = DirtyStat.total_sample_count; + uint64_t total_block_mem_MB = DirtyStat.total_block_mem_MB; + + dirtyrate = total_dirty_samples * total_block_mem_MB * + 1000 / (total_sample_count * msec); + + DirtyStat.dirty_rate = dirtyrate; +} + +/* + * get hash result for the sampled memory with length of TARGET_PAGE_SIZE + * in ramblock, which starts from ramblock base address. + */ +static uint32_t get_ramblock_vfn_hash(struct RamblockDirtyInfo *info, + uint64_t vfn) +{ + uint32_t crc; + + crc = crc32(0, (info->ramblock_addr + + vfn * TARGET_PAGE_SIZE), TARGET_PAGE_SIZE); + + trace_get_ramblock_vfn_hash(info->idstr, vfn, crc); + return crc; +} + +static bool save_ramblock_hash(struct RamblockDirtyInfo *info) +{ + unsigned int sample_pages_count; + int i; + GRand *rand; + + sample_pages_count = info->sample_pages_count; + + /* ramblock size less than one page, return success to skip this ramblock */ + if (unlikely(info->ramblock_pages == 0 || sample_pages_count == 0)) { + return true; + } + + info->hash_result = g_try_malloc0_n(sample_pages_count, + sizeof(uint32_t)); + if (!info->hash_result) { + return false; + } + + info->sample_page_vfn = g_try_malloc0_n(sample_pages_count, + sizeof(uint64_t)); + if (!info->sample_page_vfn) { + g_free(info->hash_result); + return false; + } + + rand = g_rand_new(); + for (i = 0; i < sample_pages_count; i++) { + info->sample_page_vfn[i] = g_rand_int_range(rand, 0, + info->ramblock_pages - 1); + info->hash_result[i] = get_ramblock_vfn_hash(info, + info->sample_page_vfn[i]); + } + g_rand_free(rand); + + return true; +} + +static void get_ramblock_dirty_info(RAMBlock *block, + struct RamblockDirtyInfo *info, + struct DirtyRateConfig *config) +{ + uint64_t sample_pages_per_gigabytes = config->sample_pages_per_gigabytes; + + /* Right shift 30 bits to calc ramblock size in GB */ + info->sample_pages_count = (qemu_ram_get_used_length(block) * + sample_pages_per_gigabytes) >> 30; + /* Right shift TARGET_PAGE_BITS to calc page count */ + info->ramblock_pages = qemu_ram_get_used_length(block) >> + TARGET_PAGE_BITS; + info->ramblock_addr = qemu_ram_get_host_addr(block); + strcpy(info->idstr, qemu_ram_get_idstr(block)); +} + +static void free_ramblock_dirty_info(struct RamblockDirtyInfo *infos, int count) +{ + int i; + + if (!infos) { + return; + } + + for (i = 0; i < count; i++) { + g_free(infos[i].sample_page_vfn); + g_free(infos[i].hash_result); + } + g_free(infos); +} + +static bool skip_sample_ramblock(RAMBlock *block) +{ + /* + * Sample only blocks larger than MIN_RAMBLOCK_SIZE. + */ + if (qemu_ram_get_used_length(block) < (MIN_RAMBLOCK_SIZE << 10)) { + trace_skip_sample_ramblock(block->idstr, + qemu_ram_get_used_length(block)); + return true; + } + + return false; +} + +static bool record_ramblock_hash_info(struct RamblockDirtyInfo **block_dinfo, + struct DirtyRateConfig config, + int *block_count) +{ + struct RamblockDirtyInfo *info = NULL; + struct RamblockDirtyInfo *dinfo = NULL; + RAMBlock *block = NULL; + int total_count = 0; + int index = 0; + bool ret = false; + + RAMBLOCK_FOREACH_MIGRATABLE(block) { + if (skip_sample_ramblock(block)) { + continue; + } + total_count++; + } + + dinfo = g_try_malloc0_n(total_count, sizeof(struct RamblockDirtyInfo)); + if (dinfo == NULL) { + goto out; + } + + RAMBLOCK_FOREACH_MIGRATABLE(block) { + if (skip_sample_ramblock(block)) { + continue; + } + if (index >= total_count) { + break; + } + info = &dinfo[index]; + get_ramblock_dirty_info(block, info, &config); + if (!save_ramblock_hash(info)) { + goto out; + } + index++; + } + ret = true; + +out: + *block_count = index; + *block_dinfo = dinfo; + return ret; +} + +static void calc_page_dirty_rate(struct RamblockDirtyInfo *info) +{ + uint32_t crc; + int i; + + for (i = 0; i < info->sample_pages_count; i++) { + crc = get_ramblock_vfn_hash(info, info->sample_page_vfn[i]); + if (crc != info->hash_result[i]) { + trace_calc_page_dirty_rate(info->idstr, crc, info->hash_result[i]); + info->sample_dirty_count++; + } + } +} + +static struct RamblockDirtyInfo * +find_block_matched(RAMBlock *block, int count, + struct RamblockDirtyInfo *infos) +{ + int i; + struct RamblockDirtyInfo *matched; + + for (i = 0; i < count; i++) { + if (!strcmp(infos[i].idstr, qemu_ram_get_idstr(block))) { + break; + } + } + + if (i == count) { + return NULL; + } + + if (infos[i].ramblock_addr != qemu_ram_get_host_addr(block) || + infos[i].ramblock_pages != + (qemu_ram_get_used_length(block) >> TARGET_PAGE_BITS)) { + trace_find_page_matched(block->idstr); + return NULL; + } + + matched = &infos[i]; + + return matched; +} + +static bool compare_page_hash_info(struct RamblockDirtyInfo *info, + int block_count) +{ + struct RamblockDirtyInfo *block_dinfo = NULL; + RAMBlock *block = NULL; + + RAMBLOCK_FOREACH_MIGRATABLE(block) { + if (skip_sample_ramblock(block)) { + continue; + } + block_dinfo = find_block_matched(block, block_count, info); + if (block_dinfo == NULL) { + continue; + } + calc_page_dirty_rate(block_dinfo); + update_dirtyrate_stat(block_dinfo); + } + + if (DirtyStat.total_sample_count == 0) { + return false; + } + + return true; +} + +static void calculate_dirtyrate(struct DirtyRateConfig config) +{ + struct RamblockDirtyInfo *block_dinfo = NULL; + int block_count = 0; + int64_t msec = 0; + int64_t initial_time; + + rcu_register_thread(); + rcu_read_lock(); + initial_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); + if (!record_ramblock_hash_info(&block_dinfo, config, &block_count)) { + goto out; + } + rcu_read_unlock(); + + msec = config.sample_period_seconds * 1000; + msec = set_sample_page_period(msec, initial_time); + DirtyStat.start_time = initial_time / 1000; + DirtyStat.calc_time = msec / 1000; + + rcu_read_lock(); + if (!compare_page_hash_info(block_dinfo, block_count)) { + goto out; + } + + update_dirtyrate(msec); + +out: + rcu_read_unlock(); + free_ramblock_dirty_info(block_dinfo, block_count); + rcu_unregister_thread(); +} + +void *get_dirtyrate_thread(void *arg) +{ + struct DirtyRateConfig config = *(struct DirtyRateConfig *)arg; + int ret; + int64_t start_time; + int64_t calc_time; + + ret = dirtyrate_set_state(&CalculatingState, DIRTY_RATE_STATUS_UNSTARTED, + DIRTY_RATE_STATUS_MEASURING); + if (ret == -1) { + error_report("change dirtyrate state failed."); + return NULL; + } + + start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000; + calc_time = config.sample_period_seconds; + init_dirtyrate_stat(start_time, calc_time); + + calculate_dirtyrate(config); + + ret = dirtyrate_set_state(&CalculatingState, DIRTY_RATE_STATUS_MEASURING, + DIRTY_RATE_STATUS_MEASURED); + if (ret == -1) { + error_report("change dirtyrate state failed."); + } + return NULL; +} + +void qmp_calc_dirty_rate(int64_t calc_time, Error **errp) +{ + static struct DirtyRateConfig config; + QemuThread thread; + int ret; + + /* + * If the dirty rate is already being measured, don't attempt to start. + */ + if (qatomic_read(&CalculatingState) == DIRTY_RATE_STATUS_MEASURING) { + error_setg(errp, "the dirty rate is already being measured."); + return; + } + + if (!is_sample_period_valid(calc_time)) { + error_setg(errp, "calc-time is out of range[%d, %d].", + MIN_FETCH_DIRTYRATE_TIME_SEC, + MAX_FETCH_DIRTYRATE_TIME_SEC); + return; + } + + /* + * Init calculation state as unstarted. + */ + ret = dirtyrate_set_state(&CalculatingState, CalculatingState, + DIRTY_RATE_STATUS_UNSTARTED); + if (ret == -1) { + error_setg(errp, "init dirty rate calculation state failed."); + return; + } + + config.sample_period_seconds = calc_time; + config.sample_pages_per_gigabytes = DIRTYRATE_DEFAULT_SAMPLE_PAGES; + qemu_thread_create(&thread, "get_dirtyrate", get_dirtyrate_thread, + (void *)&config, QEMU_THREAD_DETACHED); +} + +struct DirtyRateInfo *qmp_query_dirty_rate(Error **errp) +{ + return query_dirty_rate_info(); +} diff --git a/migration/dirtyrate.h b/migration/dirtyrate.h new file mode 100644 index 0000000000000000000000000000000000000000..6ec429534d75fdf74f8b5947fd10bb88647d3caf --- /dev/null +++ b/migration/dirtyrate.h @@ -0,0 +1,69 @@ +/* + * Dirtyrate common functions + * + * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD. + * + * Authors: + * Chuan Zheng + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef QEMU_MIGRATION_DIRTYRATE_H +#define QEMU_MIGRATION_DIRTYRATE_H + +/* + * Sample 512 pages per GB as default. + * TODO: Make it configurable. + */ +#define DIRTYRATE_DEFAULT_SAMPLE_PAGES 512 + +/* + * Record ramblock idstr + */ +#define RAMBLOCK_INFO_MAX_LEN 256 + +/* + * Minimum RAMBlock size to sample, in megabytes. + */ +#define MIN_RAMBLOCK_SIZE 128 + +/* + * Take 1s as minimum time for calculation duration + */ +#define MIN_FETCH_DIRTYRATE_TIME_SEC 1 +#define MAX_FETCH_DIRTYRATE_TIME_SEC 60 + +struct DirtyRateConfig { + uint64_t sample_pages_per_gigabytes; /* sample pages per GB */ + int64_t sample_period_seconds; /* time duration between two sampling */ +}; + +/* + * Store dirtypage info for each ramblock. + */ +struct RamblockDirtyInfo { + char idstr[RAMBLOCK_INFO_MAX_LEN]; /* idstr for each ramblock */ + uint8_t *ramblock_addr; /* base address of ramblock we measure */ + uint64_t ramblock_pages; /* ramblock size in TARGET_PAGE_SIZE */ + uint64_t *sample_page_vfn; /* relative offset address for sampled page */ + uint64_t sample_pages_count; /* count of sampled pages */ + uint64_t sample_dirty_count; /* count of dirty pages we measure */ + uint32_t *hash_result; /* array of hash result for sampled pages */ +}; + +/* + * Store calculation statistics for each measure. + */ +struct DirtyRateStat { + uint64_t total_dirty_samples; /* total dirty sampled page */ + uint64_t total_sample_count; /* total sampled pages */ + uint64_t total_block_mem_MB; /* size of total sampled pages in MB */ + int64_t dirty_rate; /* dirty rate in MB/s */ + int64_t start_time; /* calculation start time in units of second */ + int64_t calc_time; /* time duration of two sampling in units of second */ +}; + +void *get_dirtyrate_thread(void *arg); +#endif diff --git a/migration/fd.c b/migration/fd.c index 0a29ecdebf88cbafe6a2041f20864fe65d1f83bb..6f2f50475f445407e6e1f6d55a00131a97f3066c 100644 --- a/migration/fd.c +++ b/migration/fd.c @@ -26,7 +26,7 @@ void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp) { QIOChannel *ioc; - int fd = monitor_get_fd(cur_mon, fdname, errp); + int fd = monitor_get_fd(monitor_cur(), fdname, errp); if (fd == -1) { return; } @@ -55,7 +55,7 @@ static gboolean fd_accept_incoming_migration(QIOChannel *ioc, void fd_start_incoming_migration(const char *fdname, Error **errp) { QIOChannel *ioc; - int fd = monitor_fd_param(cur_mon, fdname, errp); + int fd = monitor_fd_param(monitor_cur(), fdname, errp); if (fd == -1) { return; } diff --git a/migration/global_state.c b/migration/global_state.c index 25311479a4bd4e91f9fff2ecc328a4d8e262aedd..a33947ca32b56378c2d3aceccafe4b1e5aea7389 100644 --- a/migration/global_state.c +++ b/migration/global_state.c @@ -44,8 +44,8 @@ void global_state_store_running(void) { const char *state = RunState_str(RUN_STATE_RUNNING); assert(strlen(state) < sizeof(global_state.runstate)); - strncpy((char *)global_state.runstate, - state, sizeof(global_state.runstate)); + strpadcpy((char *)global_state.runstate, sizeof(global_state.runstate), + state, '\0'); } bool global_state_received(void) diff --git a/migration/meson.build b/migration/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..980e37865c1a29b6400ccbac8810bb3a8ee83bfe --- /dev/null +++ b/migration/meson.build @@ -0,0 +1,34 @@ +# Files needed by unit tests +migration_files = files( + 'page_cache.c', + 'xbzrle.c', + 'vmstate-types.c', + 'vmstate.c', + 'qemu-file-channel.c', + 'qemu-file.c', + 'qjson.c', +) +softmmu_ss.add(migration_files) + +softmmu_ss.add(files( + 'block-dirty-bitmap.c', + 'channel.c', + 'colo-failover.c', + 'colo.c', + 'exec.c', + 'fd.c', + 'global_state.c', + 'migration.c', + 'multifd.c', + 'multifd-zlib.c', + 'postcopy-ram.c', + 'savevm.c', + 'socket.c', + 'tls.c', +)) + +softmmu_ss.add(when: ['CONFIG_RDMA', rdma], if_true: files('rdma.c')) +softmmu_ss.add(when: 'CONFIG_LIVE_BLOCK_MIGRATION', if_true: files('block.c')) +softmmu_ss.add(when: 'CONFIG_ZSTD', if_true: [files('multifd-zstd.c'), zstd]) + +specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: files('dirtyrate.c', 'ram.c')) diff --git a/migration/migration.c b/migration/migration.c index 0bb042a0f78bf9b748f7ef9e0fc956fd93c090e3..87a9b59f83f4677308ab184ad56f922c19a4a2b9 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -23,6 +23,7 @@ #include "socket.h" #include "sysemu/runstate.h" #include "sysemu/sysemu.h" +#include "sysemu/cpu-throttle.h" #include "rdma.h" #include "ram.h" #include "migration/global_state.h" @@ -35,6 +36,7 @@ #include "block/block.h" #include "qapi/error.h" #include "qapi/clone-visitor.h" +#include "qapi/qapi-visit-migration.h" #include "qapi/qapi-visit-sockets.h" #include "qapi/qapi-commands-migration.h" #include "qapi/qapi-events-migration.h" @@ -55,7 +57,11 @@ #include "qemu/queue.h" #include "multifd.h" -#define MAX_THROTTLE (32 << 20) /* Migration transfer speed throttling */ +#ifdef CONFIG_VFIO +#include "hw/vfio/vfio-common.h" +#endif + +#define MAX_THROTTLE (128 << 20) /* Migration transfer speed throttling */ /* Amount of time to allocate to each "chunk" of bandwidth-throttled * data. */ @@ -141,9 +147,15 @@ static int migration_maybe_pause(MigrationState *s, int new_state); static void migrate_fd_cancel(MigrationState *s); +static gint page_request_addr_cmp(gconstpointer ap, gconstpointer bp) +{ + uintptr_t a = (uintptr_t) ap, b = (uintptr_t) bp; + + return (a > b) - (a < b); +} + void migration_object_init(void) { - MachineState *ms = MACHINE(qdev_get_machine()); Error *err = NULL; /* This can only be called once. */ @@ -163,22 +175,13 @@ void migration_object_init(void) qemu_event_init(¤t_incoming->main_thread_load_event, false); qemu_sem_init(¤t_incoming->postcopy_pause_sem_dst, 0); qemu_sem_init(¤t_incoming->postcopy_pause_sem_fault, 0); - - init_dirty_bitmap_incoming_migration(); + qemu_mutex_init(¤t_incoming->page_request_mutex); + current_incoming->page_requested = g_tree_new(page_request_addr_cmp); if (!migration_object_check(current_migration, &err)) { error_report_err(err); exit(1); } - - /* - * We cannot really do this in migration_instance_init() since at - * that time global properties are not yet applied, then this - * value will be definitely replaced by something else. - */ - if (ms->enforce_config_section) { - current_migration->send_configuration = true; - } } void migration_shutdown(void) @@ -189,6 +192,19 @@ void migration_shutdown(void) */ migrate_fd_cancel(current_migration); object_unref(OBJECT(current_migration)); + + /* + * Cancel outgoing migration of dirty bitmaps. It should + * at least unref used block nodes. + */ + dirty_bitmap_mig_cancel_outgoing(); + + /* + * Cancel incoming migration of dirty bitmaps. Dirty bitmaps + * are non-critical data, and their loss never considered as + * something serious. + */ + dirty_bitmap_mig_cancel_incoming(); } /* For outgoing */ @@ -227,6 +243,11 @@ void migration_incoming_state_destroy(void) qemu_event_reset(&mis->main_thread_load_event); + if (mis->page_requested) { + g_tree_destroy(mis->page_requested); + mis->page_requested = NULL; + } + if (mis->socket_address_list) { qapi_free_SocketAddressList(mis->socket_address_list); mis->socket_address_list = NULL; @@ -298,25 +319,35 @@ error: return ret; } -/* Request a range of pages from the source VM at the given - * start address. - * rbname: Name of the RAMBlock to request the page in, if NULL it's the same - * as the last request (a name must have been given previously) +/* Request one page from the source VM at the given start address. + * rb: the RAMBlock to request the page in * Start: Address offset within the RB * Len: Length in bytes required - must be a multiple of pagesize */ -int migrate_send_rp_req_pages(MigrationIncomingState *mis, const char *rbname, - ram_addr_t start, size_t len) +int migrate_send_rp_message_req_pages(MigrationIncomingState *mis, + RAMBlock *rb, ram_addr_t start) { uint8_t bufc[12 + 1 + 255]; /* start (8), len (4), rbname up to 256 */ size_t msglen = 12; /* start + len */ + size_t len = qemu_ram_pagesize(rb); enum mig_rp_message_type msg_type; + const char *rbname; + int rbname_len; *(uint64_t *)bufc = cpu_to_be64((uint64_t)start); *(uint32_t *)(bufc + 8) = cpu_to_be32((uint32_t)len); - if (rbname) { - int rbname_len = strlen(rbname); + /* + * We maintain the last ramblock that we requested for page. Note that we + * don't need locking because this function will only be called within the + * postcopy ram fault thread. + */ + if (rb != mis->last_rb) { + mis->last_rb = rb; + + rbname = qemu_ram_get_idstr(rb); + rbname_len = strlen(rbname); + assert(rbname_len < 256); bufc[msglen++] = rbname_len; @@ -330,6 +361,37 @@ int migrate_send_rp_req_pages(MigrationIncomingState *mis, const char *rbname, return migrate_send_rp_message(mis, msg_type, msglen, bufc); } +int migrate_send_rp_req_pages(MigrationIncomingState *mis, + RAMBlock *rb, ram_addr_t start, uint64_t haddr) +{ + void *aligned = (void *)(uintptr_t)(haddr & (-qemu_ram_pagesize(rb))); + bool received = false; + + WITH_QEMU_LOCK_GUARD(&mis->page_request_mutex) { + received = ramblock_recv_bitmap_test_byte_offset(rb, start); + if (!received && !g_tree_lookup(mis->page_requested, aligned)) { + /* + * The page has not been received, and it's not yet in the page + * request list. Queue it. Set the value of element to 1, so that + * things like g_tree_lookup() will return TRUE (1) when found. + */ + g_tree_insert(mis->page_requested, aligned, (gpointer)1); + mis->page_requested_count++; + trace_postcopy_page_req_add(aligned, mis->page_requested_count); + } + } + + /* + * If the page is there, skip sending the message. We don't even need the + * lock because as long as the page arrived, it'll be there forever. + */ + if (received) { + return 0; + } + + return migrate_send_rp_message_req_pages(mis, rb, start); +} + static bool migration_colo_enabled; bool migration_incoming_colo_enabled(void) { @@ -338,12 +400,18 @@ bool migration_incoming_colo_enabled(void) void migration_incoming_disable_colo(void) { + ram_block_discard_disable(false); migration_colo_enabled = false; } -void migration_incoming_enable_colo(void) +int migration_incoming_enable_colo(void) { + if (ram_block_discard_disable(true)) { + error_report("COLO: cannot disable RAM discard"); + return -EBUSY; + } migration_colo_enabled = true; + return 0; } void migrate_add_address(SocketAddress *address) @@ -359,21 +427,21 @@ void migrate_add_address(SocketAddress *address) void qemu_start_incoming_migration(const char *uri, Error **errp) { - const char *p; + const char *p = NULL; qapi_event_send_migration(MIGRATION_STATUS_SETUP); if (!strcmp(uri, "defer")) { deferred_incoming_migration(errp); - } else if (strstart(uri, "tcp:", &p)) { - tcp_start_incoming_migration(p, errp); + } else if (strstart(uri, "tcp:", &p) || + strstart(uri, "unix:", NULL) || + strstart(uri, "vsock:", NULL)) { + socket_start_incoming_migration(p ? p : uri, errp); #ifdef CONFIG_RDMA } else if (strstart(uri, "rdma:", &p)) { rdma_start_incoming_migration(p, errp); #endif } else if (strstart(uri, "exec:", &p)) { exec_start_incoming_migration(p, errp); - } else if (strstart(uri, "unix:", &p)) { - unix_start_incoming_migration(p, errp); } else if (strstart(uri, "fd:", &p)) { fd_start_incoming_migration(p, errp); } else { @@ -594,9 +662,7 @@ void migration_fd_process_incoming(QEMUFile *f, Error **errp) } if (migration_incoming_setup(f, &local_err)) { - if (local_err) { - error_propagate(errp, local_err); - } + error_propagate(errp, local_err); return; } migration_incoming_process(); @@ -618,9 +684,7 @@ void migration_ioc_process_incoming(QIOChannel *ioc, Error **errp) } if (migration_incoming_setup(f, &local_err)) { - if (local_err) { - error_propagate(errp, local_err); - } + error_propagate(errp, local_err); return; } @@ -825,6 +889,13 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) params->has_announce_step = true; params->announce_step = s->parameters.announce_step; + if (s->parameters.has_block_bitmap_mapping) { + params->has_block_bitmap_mapping = true; + params->block_bitmap_mapping = + QAPI_CLONE(BitmapMigrationNodeAliasList, + s->parameters.block_bitmap_mapping); + } + return params; } @@ -970,6 +1041,17 @@ static void populate_disk_info(MigrationInfo *info) } } +static void populate_vfio_info(MigrationInfo *info) +{ +#ifdef CONFIG_VFIO + if (vfio_mig_active()) { + info->has_vfio = true; + info->vfio = g_malloc0(sizeof(*info->vfio)); + info->vfio->transferred = vfio_mig_bytes_transferred(); + } +#endif +} + static void fill_source_migration_info(MigrationInfo *info) { MigrationState *s = migrate_get_current(); @@ -979,7 +1061,6 @@ static void fill_source_migration_info(MigrationInfo *info) /* no migration has happened ever */ /* do not overwrite destination migration status */ return; - break; case MIGRATION_STATUS_SETUP: info->has_status = true; info->has_total_time = false; @@ -995,6 +1076,7 @@ static void fill_source_migration_info(MigrationInfo *info) populate_time_info(info, s); populate_ram_info(info, s); populate_disk_info(info); + populate_vfio_info(info); break; case MIGRATION_STATUS_COLO: info->has_status = true; @@ -1003,6 +1085,7 @@ static void fill_source_migration_info(MigrationInfo *info) case MIGRATION_STATUS_COMPLETED: populate_time_info(info, s); populate_ram_info(info, s); + populate_vfio_info(info); break; case MIGRATION_STATUS_FAILED: info->has_status = true; @@ -1098,7 +1181,6 @@ static void fill_destination_migration_info(MigrationInfo *info) switch (mis->state) { case MIGRATION_STATUS_NONE: return; - break; case MIGRATION_STATUS_SETUP: case MIGRATION_STATUS_CANCELLING: case MIGRATION_STATUS_CANCELLED: @@ -1292,6 +1374,13 @@ static bool migrate_params_check(MigrationParameters *params, Error **errp) "is invalid, it must be in the range of 1 to 10000 ms"); return false; } + + if (params->has_block_bitmap_mapping && + !check_dirty_bitmap_mig_alias_map(params->block_bitmap_mapping, errp)) { + error_prepend(errp, "Invalid mapping given for block-bitmap-mapping: "); + return false; + } + return true; } @@ -1336,12 +1425,12 @@ static void migrate_params_test_apply(MigrateSetParameters *params, if (params->has_tls_creds) { assert(params->tls_creds->type == QTYPE_QSTRING); - dest->tls_creds = g_strdup(params->tls_creds->u.s); + dest->tls_creds = params->tls_creds->u.s; } if (params->has_tls_hostname) { assert(params->tls_hostname->type == QTYPE_QSTRING); - dest->tls_hostname = g_strdup(params->tls_hostname->u.s); + dest->tls_hostname = params->tls_hostname->u.s; } if (params->has_max_bandwidth) { @@ -1386,6 +1475,11 @@ static void migrate_params_test_apply(MigrateSetParameters *params, if (params->has_announce_step) { dest->announce_step = params->announce_step; } + + if (params->has_block_bitmap_mapping) { + dest->has_block_bitmap_mapping = true; + dest->block_bitmap_mapping = params->block_bitmap_mapping; + } } static void migrate_params_apply(MigrateSetParameters *params, Error **errp) @@ -1498,6 +1592,16 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp) if (params->has_announce_step) { s->parameters.announce_step = params->announce_step; } + + if (params->has_block_bitmap_mapping) { + qapi_free_BitmapMigrationNodeAliasList( + s->parameters.block_bitmap_mapping); + + s->parameters.has_block_bitmap_mapping = true; + s->parameters.block_bitmap_mapping = + QAPI_CLONE(BitmapMigrationNodeAliasList, + params->block_bitmap_mapping); + } } void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp) @@ -1549,7 +1653,7 @@ void qmp_migrate_start_postcopy(Error **errp) * we don't error if migration has finished since that would be racy * with issuing this command. */ - atomic_set(&s->start_postcopy, true); + qatomic_set(&s->start_postcopy, true); } /* shared migration helpers */ @@ -1557,7 +1661,7 @@ void qmp_migrate_start_postcopy(Error **errp) void migrate_set_state(int *state, int old_state, int new_state) { assert(new_state < MIGRATION_STATUS__MAX); - if (atomic_cmpxchg(state, old_state, new_state) == old_state) { + if (qatomic_cmpxchg(state, old_state, new_state) == old_state) { trace_migrate_set_state(MigrationStatus_str(new_state)); migrate_generate_event(new_state); } @@ -1772,6 +1876,13 @@ bool migration_in_postcopy_after_devices(MigrationState *s) return migration_in_postcopy() && s->postcopy_after_devices; } +bool migration_in_incoming_postcopy(void) +{ + PostcopyState ps = postcopy_state_get(); + + return ps >= POSTCOPY_INCOMING_DISCARD && ps < POSTCOPY_INCOMING_END; +} + bool migration_is_idle(void) { MigrationState *s = current_migration; @@ -1830,6 +1941,7 @@ void migrate_init(MigrationState *s) s->migration_thread_running = false; error_free(s->error); s->error = NULL; + s->hostname = NULL; migrate_set_state(&s->state, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP); @@ -1901,7 +2013,7 @@ void qmp_migrate_recover(const char *uri, Error **errp) return; } - if (atomic_cmpxchg(&mis->postcopy_recover_triggered, + if (qatomic_cmpxchg(&mis->postcopy_recover_triggered, false, true) == true) { error_setg(errp, "Migrate recovery is triggered already"); return; @@ -2041,7 +2153,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, { Error *local_err = NULL; MigrationState *s = migrate_get_current(); - const char *p; + const char *p = NULL; if (!migrate_prepare(s, has_blk && blk, has_inc && inc, has_resume && resume, errp)) { @@ -2049,16 +2161,16 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, return; } - if (strstart(uri, "tcp:", &p)) { - tcp_start_outgoing_migration(s, p, &local_err); + if (strstart(uri, "tcp:", &p) || + strstart(uri, "unix:", NULL) || + strstart(uri, "vsock:", NULL)) { + socket_start_outgoing_migration(s, p ? p : uri, &local_err); #ifdef CONFIG_RDMA } else if (strstart(uri, "rdma:", &p)) { rdma_start_outgoing_migration(s, p, &local_err); #endif } else if (strstart(uri, "exec:", &p)) { exec_start_outgoing_migration(s, p, &local_err); - } else if (strstart(uri, "unix:", &p)) { - unix_start_outgoing_migration(s, p, &local_err); } else if (strstart(uri, "fd:", &p)) { fd_start_outgoing_migration(s, p, &local_err); } else { @@ -2418,8 +2530,8 @@ static void migrate_handle_rp_req_pages(MigrationState *ms, const char* rbname, * Since we currently insist on matching page sizes, just sanity check * we're being asked for whole host pages. */ - if (start & (our_host_ps-1) || - (len & (our_host_ps-1))) { + if (start & (our_host_ps - 1) || + (len & (our_host_ps - 1))) { error_report("%s: Misaligned page request, start: " RAM_ADDR_FMT " len: %zd", __func__, start, len); mark_source_rp_bad(ms); @@ -2949,6 +3061,8 @@ static void migration_completion(MigrationState *s) qemu_savevm_state_complete_postcopy(s->to_dst_file); trace_migration_completion_postcopy_end_after_complete(); + } else if (s->state == MIGRATION_STATUS_CANCELLING) { + goto fail; } /* @@ -3073,9 +3187,6 @@ static MigThrError postcopy_pause(MigrationState *s) while (true) { QEMUFile *file; - migrate_set_state(&s->state, s->state, - MIGRATION_STATUS_POSTCOPY_PAUSED); - /* Current channel is possibly broken. Release it. */ assert(s->to_dst_file); qemu_mutex_lock(&s->qemu_file_lock); @@ -3086,6 +3197,9 @@ static MigThrError postcopy_pause(MigrationState *s) qemu_file_shutdown(file); qemu_fclose(file); + migrate_set_state(&s->state, s->state, + MIGRATION_STATUS_POSTCOPY_PAUSED); + error_report("Detected IO failure for postcopy. " "Migration paused."); @@ -3276,7 +3390,7 @@ static MigIterateState migration_iteration_run(MigrationState *s) if (pending_size && pending_size >= s->threshold_size) { /* Still a significant amount to transfer */ if (!in_postcopy && pend_pre <= s->threshold_size && - atomic_read(&s->start_postcopy)) { + qatomic_read(&s->start_postcopy)) { if (postcopy_start(s)) { error_report("%s: postcopy failed to start", __func__); } @@ -3361,6 +3475,10 @@ bool migration_rate_limit(void) bool urgent = false; migration_update_counters(s, now); if (qemu_file_rate_limit(s->to_dst_file)) { + + if (qemu_file_get_error(s->to_dst_file)) { + return false; + } /* * Wait for a delay to do rate limiting OR * something urgent to post the semaphore. @@ -3774,7 +3892,7 @@ static const TypeInfo migration_type = { .name = TYPE_MIGRATION, /* * NOTE: TYPE_MIGRATION is not really a device, as the object is - * not created using qdev_create(), it is not attached to the qdev + * not created using qdev_new(), it is not attached to the qdev * device tree, and it is never realized. * * TODO: Make this TYPE_OBJECT once QOM provides something like diff --git a/migration/migration.h b/migration/migration.h index 507284e563463490efdfcbc6057bb64ccac78e12..d096b77f7469a52f0ef7ed3debb506338ceffa8a 100644 --- a/migration/migration.h +++ b/migration/migration.h @@ -21,6 +21,7 @@ #include "qemu/coroutine_int.h" #include "io/channel.h" #include "net/announce.h" +#include "qom/object.h" struct PostcopyBlocktimeContext; @@ -103,6 +104,23 @@ struct MigrationIncomingState { /* List of listening socket addresses */ SocketAddressList *socket_address_list; + + /* A tree of pages that we requested to the source VM */ + GTree *page_requested; + /* For debugging purpose only, but would be nice to keep */ + int page_requested_count; + /* + * The mutex helps to maintain the requested pages that we sent to the + * source, IOW, to guarantee coherent between the page_requests tree and + * the per-ramblock receivedmap. Note! This does not guarantee consistency + * of the real page copy procedures (using UFFDIO_[ZERO]COPY). E.g., even + * if one bit in receivedmap is cleared, UFFDIO_COPY could have happened + * for that page already. This is intended so that the mutex won't + * serialize and blocked by slow operations like UFFDIO_* ioctls. However + * this should be enough to make sure the page_requested tree always + * contains valid information. + */ + QemuMutex page_request_mutex; }; MigrationIncomingState *migration_incoming_get_current(void); @@ -114,20 +132,16 @@ void fill_destination_postcopy_migration_info(MigrationInfo *info); #define TYPE_MIGRATION "migration" -#define MIGRATION_CLASS(klass) \ - OBJECT_CLASS_CHECK(MigrationClass, (klass), TYPE_MIGRATION) -#define MIGRATION_OBJ(obj) \ - OBJECT_CHECK(MigrationState, (obj), TYPE_MIGRATION) -#define MIGRATION_GET_CLASS(obj) \ - OBJECT_GET_CLASS(MigrationClass, (obj), TYPE_MIGRATION) +typedef struct MigrationClass MigrationClass; +DECLARE_OBJ_CHECKERS(MigrationState, MigrationClass, + MIGRATION_OBJ, TYPE_MIGRATION) -typedef struct MigrationClass { +struct MigrationClass { /*< private >*/ DeviceClass parent_class; -} MigrationClass; +}; -struct MigrationState -{ +struct MigrationState { /*< private >*/ DeviceState parent_obj; @@ -215,8 +229,8 @@ struct MigrationState /* The semaphore is used to notify COLO thread that failover is finished */ QemuSemaphore colo_exit_sem; - /* The semaphore is used to notify COLO thread to do checkpoint */ - QemuSemaphore colo_checkpoint_sem; + /* The event is used to notify COLO thread to do checkpoint */ + QemuEvent colo_checkpoint_event; int64_t colo_checkpoint_time; QEMUTimer *colo_delay_timer; @@ -261,6 +275,11 @@ struct MigrationState * (which is in 4M chunk). */ uint8_t clear_bitmap_shift; + + /* + * This save hostname when out-going migration starts + */ + char *hostname; }; void migrate_set_state(int *state, int old_state, int new_state); @@ -328,14 +347,20 @@ void migrate_send_rp_shut(MigrationIncomingState *mis, uint32_t value); void migrate_send_rp_pong(MigrationIncomingState *mis, uint32_t value); -int migrate_send_rp_req_pages(MigrationIncomingState *mis, const char* rbname, - ram_addr_t start, size_t len); +int migrate_send_rp_req_pages(MigrationIncomingState *mis, RAMBlock *rb, + ram_addr_t start, uint64_t haddr); +int migrate_send_rp_message_req_pages(MigrationIncomingState *mis, + RAMBlock *rb, ram_addr_t start); void migrate_send_rp_recv_bitmap(MigrationIncomingState *mis, char *block_name); void migrate_send_rp_resume_ack(MigrationIncomingState *mis, uint32_t value); void dirty_bitmap_mig_before_vm_start(void); -void init_dirty_bitmap_incoming_migration(void); +void dirty_bitmap_mig_cancel_outgoing(void); +void dirty_bitmap_mig_cancel_incoming(void); +bool check_dirty_bitmap_mig_alias_map(const BitmapMigrationNodeAliasList *bbm, + Error **errp); + void migrate_add_address(SocketAddress *address); int foreach_not_ignored_block(RAMBlockIterFunc func, void *opaque); diff --git a/migration/multifd.c b/migration/multifd.c index 5a3e4d0d46d110301b4a472117997b0fbcfa55c5..45c690aa1136b9802c9c5695446fc835a29f9c26 100644 --- a/migration/multifd.c +++ b/migration/multifd.c @@ -20,6 +20,7 @@ #include "ram.h" #include "migration.h" #include "socket.h" +#include "tls.h" #include "qemu-file.h" #include "trace.h" #include "multifd.h" @@ -410,11 +411,17 @@ static int multifd_send_pages(QEMUFile *f) MultiFDPages_t *pages = multifd_send_state->pages; uint64_t transferred; - if (atomic_read(&multifd_send_state->exiting)) { + if (qatomic_read(&multifd_send_state->exiting)) { return -1; } qemu_sem_wait(&multifd_send_state->channels_ready); + /* + * next_channel can remain from a previous migration that was + * using more channels, so ensure it doesn't overflow if the + * limit is lower now. + */ + next_channel %= migrate_multifd_channels(); for (i = next_channel;; i = (i + 1) % migrate_multifd_channels()) { p = &multifd_send_state->params[i]; @@ -441,7 +448,7 @@ static int multifd_send_pages(QEMUFile *f) + p->packet_len; qemu_file_update_transfer(f, transferred); ram_counters.multifd_bytes += transferred; - ram_counters.transferred += transferred;; + ram_counters.transferred += transferred; qemu_mutex_unlock(&p->mutex); qemu_sem_post(&p->sem); @@ -502,7 +509,7 @@ static void multifd_send_terminate_threads(Error *err) * threads at the same time, we can end calling this function * twice. */ - if (atomic_xchg(&multifd_send_state->exiting, 1)) { + if (qatomic_xchg(&multifd_send_state->exiting, 1)) { return; } @@ -542,6 +549,8 @@ void multifd_save_cleanup(void) qemu_sem_destroy(&p->sem_sync); g_free(p->name); p->name = NULL; + g_free(p->tls_hostname); + p->tls_hostname = NULL; multifd_pages_clear(p->pages); p->pages = NULL; p->packet_len = 0; @@ -626,7 +635,7 @@ static void *multifd_send_thread(void *opaque) while (true) { qemu_sem_wait(&p->sem); - if (atomic_read(&multifd_send_state->exiting)) { + if (qatomic_read(&multifd_send_state->exiting)) { break; } qemu_mutex_lock(&p->mutex); @@ -711,6 +720,114 @@ out: return NULL; } +static bool multifd_channel_connect(MultiFDSendParams *p, + QIOChannel *ioc, + Error *error); + +static void multifd_tls_outgoing_handshake(QIOTask *task, + gpointer opaque) +{ + MultiFDSendParams *p = opaque; + QIOChannel *ioc = QIO_CHANNEL(qio_task_get_source(task)); + Error *err = NULL; + + if (qio_task_propagate_error(task, &err)) { + trace_multifd_tls_outgoing_handshake_error(ioc, error_get_pretty(err)); + } else { + trace_multifd_tls_outgoing_handshake_complete(ioc); + } + multifd_channel_connect(p, ioc, err); +} + +static void *multifd_tls_handshake_thread(void *opaque) +{ + MultiFDSendParams *p = opaque; + QIOChannelTLS *tioc = QIO_CHANNEL_TLS(p->c); + + qio_channel_tls_handshake(tioc, + multifd_tls_outgoing_handshake, + p, + NULL, + NULL); + return NULL; +} + +static void multifd_tls_channel_connect(MultiFDSendParams *p, + QIOChannel *ioc, + Error **errp) +{ + MigrationState *s = migrate_get_current(); + const char *hostname = p->tls_hostname; + QIOChannelTLS *tioc; + + tioc = migration_tls_client_create(s, ioc, hostname, errp); + if (!tioc) { + return; + } + + object_unref(OBJECT(ioc)); + trace_multifd_tls_outgoing_handshake_start(ioc, tioc, hostname); + qio_channel_set_name(QIO_CHANNEL(tioc), "multifd-tls-outgoing"); + p->c = QIO_CHANNEL(tioc); + qemu_thread_create(&p->thread, "multifd-tls-handshake-worker", + multifd_tls_handshake_thread, p, + QEMU_THREAD_JOINABLE); +} + +static bool multifd_channel_connect(MultiFDSendParams *p, + QIOChannel *ioc, + Error *error) +{ + MigrationState *s = migrate_get_current(); + + trace_multifd_set_outgoing_channel( + ioc, object_get_typename(OBJECT(ioc)), p->tls_hostname, error); + + if (!error) { + if (s->parameters.tls_creds && + *s->parameters.tls_creds && + !object_dynamic_cast(OBJECT(ioc), + TYPE_QIO_CHANNEL_TLS)) { + multifd_tls_channel_connect(p, ioc, &error); + if (!error) { + /* + * tls_channel_connect will call back to this + * function after the TLS handshake, + * so we mustn't call multifd_send_thread until then + */ + return false; + } else { + return true; + } + } else { + /* update for tls qio channel */ + p->c = ioc; + qemu_thread_create(&p->thread, p->name, multifd_send_thread, p, + QEMU_THREAD_JOINABLE); + } + return false; + } + + return true; +} + +static void multifd_new_send_channel_cleanup(MultiFDSendParams *p, + QIOChannel *ioc, Error *err) +{ + migrate_set_error(migrate_get_current(), err); + /* Error happen, we need to tell who pay attention to me */ + qemu_sem_post(&multifd_send_state->channels_ready); + qemu_sem_post(&p->sem_sync); + /* + * Although multifd_send_thread is not created, but main migration + * thread neet to judge whether it is running, so we need to mark + * its status. + */ + p->quit = true; + object_unref(OBJECT(ioc)); + error_free(err); +} + static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque) { MultiFDSendParams *p = opaque; @@ -719,25 +836,19 @@ static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque) trace_multifd_new_send_channel_async(p->id); if (qio_task_propagate_error(task, &local_err)) { - migrate_set_error(migrate_get_current(), local_err); - /* Error happen, we need to tell who pay attention to me */ - qemu_sem_post(&multifd_send_state->channels_ready); - qemu_sem_post(&p->sem_sync); - /* - * Although multifd_send_thread is not created, but main migration - * thread neet to judge whether it is running, so we need to mark - * its status. - */ - p->quit = true; - object_unref(OBJECT(sioc)); - error_free(local_err); + goto cleanup; } else { p->c = QIO_CHANNEL(sioc); qio_channel_set_delay(p->c, false); p->running = true; - qemu_thread_create(&p->thread, p->name, multifd_send_thread, p, - QEMU_THREAD_JOINABLE); + if (multifd_channel_connect(p, sioc, local_err)) { + goto cleanup; + } + return; } + +cleanup: + multifd_new_send_channel_cleanup(p, sioc, local_err); } int multifd_save_setup(Error **errp) @@ -745,16 +856,18 @@ int multifd_save_setup(Error **errp) int thread_count; uint32_t page_count = MULTIFD_PACKET_SIZE / qemu_target_page_size(); uint8_t i; + MigrationState *s; if (!migrate_use_multifd()) { return 0; } + s = migrate_get_current(); thread_count = migrate_multifd_channels(); multifd_send_state = g_malloc0(sizeof(*multifd_send_state)); multifd_send_state->params = g_new0(MultiFDSendParams, thread_count); multifd_send_state->pages = multifd_pages_init(page_count); qemu_sem_init(&multifd_send_state->channels_ready, 0); - atomic_set(&multifd_send_state->exiting, 0); + qatomic_set(&multifd_send_state->exiting, 0); multifd_send_state->ops = multifd_ops[migrate_multifd_compression()]; for (i = 0; i < thread_count; i++) { @@ -773,6 +886,7 @@ int multifd_save_setup(Error **errp) p->packet->magic = cpu_to_be32(MULTIFD_MAGIC); p->packet->version = cpu_to_be32(MULTIFD_VERSION); p->name = g_strdup_printf("multifdsend_%d", i); + p->tls_hostname = g_strdup(s->hostname); socket_send_channel_create(multifd_new_send_channel_async, p); } @@ -991,7 +1105,7 @@ int multifd_load_setup(Error **errp) thread_count = migrate_multifd_channels(); multifd_recv_state = g_malloc0(sizeof(*multifd_recv_state)); multifd_recv_state->params = g_new0(MultiFDRecvParams, thread_count); - atomic_set(&multifd_recv_state->count, 0); + qatomic_set(&multifd_recv_state->count, 0); qemu_sem_init(&multifd_recv_state->sem_sync, 0); multifd_recv_state->ops = multifd_ops[migrate_multifd_compression()]; @@ -1031,12 +1145,12 @@ bool multifd_recv_all_channels_created(void) return true; } - return thread_count == atomic_read(&multifd_recv_state->count); + return thread_count == qatomic_read(&multifd_recv_state->count); } /* * Try to receive all multifd channels to get ready for the migration. - * - Return true and do not set @errp when correctly receving all channels; + * - Return true and do not set @errp when correctly receiving all channels; * - Return false and do not set @errp when correctly receiving the current one; * - Return false and set @errp when failing to receive the current channel. */ @@ -1052,7 +1166,7 @@ bool multifd_recv_new_channel(QIOChannel *ioc, Error **errp) error_propagate_prepend(errp, local_err, "failed to receive packet" " via multifd channel %d: ", - atomic_read(&multifd_recv_state->count)); + qatomic_read(&multifd_recv_state->count)); return false; } trace_multifd_recv_new_channel(id); @@ -1073,7 +1187,7 @@ bool multifd_recv_new_channel(QIOChannel *ioc, Error **errp) p->running = true; qemu_thread_create(&p->thread, p->name, multifd_recv_thread, p, QEMU_THREAD_JOINABLE); - atomic_inc(&multifd_recv_state->count); - return atomic_read(&multifd_recv_state->count) == + qatomic_inc(&multifd_recv_state->count); + return qatomic_read(&multifd_recv_state->count) == migrate_multifd_channels(); } diff --git a/migration/multifd.h b/migration/multifd.h index 448a03d89a9a45c834e490441eb4eee1e9e2bb7c..8d6751f5ed85e1f7019cfce27c737eb380a026ad 100644 --- a/migration/multifd.h +++ b/migration/multifd.h @@ -71,6 +71,8 @@ typedef struct { uint8_t id; /* channel thread name */ char *name; + /* tls hostname */ + char *tls_hostname; /* channel thread id */ QemuThread thread; /* communication channel */ diff --git a/migration/page_cache.c b/migration/page_cache.c index 775582f453e968c352af3096b0ab0a7e50adfffa..098b4362239ce1eb4fffb40beb3268bc82feb07a 100644 --- a/migration/page_cache.c +++ b/migration/page_cache.c @@ -18,14 +18,7 @@ #include "qapi/error.h" #include "qemu/host-utils.h" #include "page_cache.h" - -#ifdef DEBUG_CACHE -#define DPRINTF(fmt, ...) \ - do { fprintf(stdout, "cache: " fmt, ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) \ - do { } while (0) -#endif +#include "trace.h" /* the page in cache will not be replaced in two cycles */ #define CACHED_PAGE_LIFETIME 2 @@ -75,7 +68,7 @@ PageCache *cache_init(int64_t new_size, size_t page_size, Error **errp) cache->num_items = 0; cache->max_num_items = num_pages; - DPRINTF("Setting cache buckets to %" PRId64 "\n", cache->max_num_items); + trace_migration_pagecache_init(cache->max_num_items); /* We prefer not to abort if there is no memory */ cache->page_cache = g_try_malloc((cache->max_num_items) * @@ -169,7 +162,7 @@ int cache_insert(PageCache *cache, uint64_t addr, const uint8_t *pdata, if (!it->it_data) { it->it_data = g_try_malloc(cache->page_size); if (!it->it_data) { - DPRINTF("Error allocating page\n"); + trace_migration_pagecache_insert(); return -1; } cache->num_items++; diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index a36402722b975bfd32a96d0d9c6ddc1f2af22f87..d99842eb1be86b603fa17f46b68b5b3bf3d486f2 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -27,7 +27,6 @@ #include "qemu/notify.h" #include "qemu/rcu.h" #include "sysemu/sysemu.h" -#include "sysemu/balloon.h" #include "qemu/error-report.h" #include "trace.h" #include "hw/boards.h" @@ -238,7 +237,7 @@ release_ufd: * request_ufd_features: this function should be called only once on a newly * opened ufd, subsequent calls will lead to error. * - * Returns: true on succes + * Returns: true on success * * @ufd: fd obtained from userfaultfd syscall * @features: bit mask see UFFD_API_FEATURES @@ -389,7 +388,7 @@ bool postcopy_ram_supported_by_host(MigrationIncomingState *mis) */ if (munlockall()) { error_report("%s: munlockall: %s", __func__, strerror(errno)); - return -1; + goto out; } /* @@ -404,7 +403,7 @@ bool postcopy_ram_supported_by_host(MigrationIncomingState *mis) strerror(errno)); goto out; } - g_assert(((size_t)testarea & (pagesize-1)) == 0); + g_assert(((size_t)testarea & (pagesize - 1)) == 0); reg_struct.range.start = (uintptr_t)testarea; reg_struct.range.len = pagesize; @@ -520,20 +519,6 @@ int postcopy_ram_incoming_init(MigrationIncomingState *mis) return 0; } -/* - * Manage a single vote to the QEMU balloon inhibitor for all postcopy usage, - * last caller wins. - */ -static void postcopy_balloon_inhibit(bool state) -{ - static bool cur_state = false; - - if (state != cur_state) { - qemu_balloon_inhibit(state); - cur_state = state; - } -} - /* * At the end of a migration where postcopy_ram_incoming_init was called. */ @@ -545,7 +530,7 @@ int postcopy_ram_incoming_cleanup(MigrationIncomingState *mis) Error *local_err = NULL; /* Let the fault thread quit */ - atomic_set(&mis->fault_thread_quit, 1); + qatomic_set(&mis->fault_thread_quit, 1); postcopy_fault_thread_notify(mis); trace_postcopy_ram_incoming_cleanup_join(); qemu_thread_join(&mis->fault_thread); @@ -565,8 +550,6 @@ int postcopy_ram_incoming_cleanup(MigrationIncomingState *mis) mis->have_fault_thread = false; } - postcopy_balloon_inhibit(false); - if (enable_mlock) { if (os_mlock() < 0) { error_report("mlock: %s", strerror(errno)); @@ -701,14 +684,7 @@ int postcopy_request_shared_page(struct PostCopyFD *pcfd, RAMBlock *rb, qemu_ram_get_idstr(rb), rb_offset); return postcopy_wake_shared(pcfd, client_addr, rb); } - if (rb != mis->last_rb) { - mis->last_rb = rb; - migrate_send_rp_req_pages(mis, qemu_ram_get_idstr(rb), - aligned_rbo, pagesize); - } else { - /* Save some space */ - migrate_send_rp_req_pages(mis, NULL, aligned_rbo, pagesize); - } + migrate_send_rp_req_pages(mis, rb, aligned_rbo, client_addr); return 0; } @@ -759,12 +735,12 @@ static void mark_postcopy_blocktime_begin(uintptr_t addr, uint32_t ptid, low_time_offset = get_low_time_offset(dc); if (dc->vcpu_addr[cpu] == 0) { - atomic_inc(&dc->smp_cpus_down); + qatomic_inc(&dc->smp_cpus_down); } - atomic_xchg(&dc->last_begin, low_time_offset); - atomic_xchg(&dc->page_fault_vcpu_time[cpu], low_time_offset); - atomic_xchg(&dc->vcpu_addr[cpu], addr); + qatomic_xchg(&dc->last_begin, low_time_offset); + qatomic_xchg(&dc->page_fault_vcpu_time[cpu], low_time_offset); + qatomic_xchg(&dc->vcpu_addr[cpu], addr); /* * check it here, not at the beginning of the function, @@ -773,9 +749,9 @@ static void mark_postcopy_blocktime_begin(uintptr_t addr, uint32_t ptid, */ already_received = ramblock_recv_bitmap_test(rb, (void *)addr); if (already_received) { - atomic_xchg(&dc->vcpu_addr[cpu], 0); - atomic_xchg(&dc->page_fault_vcpu_time[cpu], 0); - atomic_dec(&dc->smp_cpus_down); + qatomic_xchg(&dc->vcpu_addr[cpu], 0); + qatomic_xchg(&dc->page_fault_vcpu_time[cpu], 0); + qatomic_dec(&dc->smp_cpus_down); } trace_mark_postcopy_blocktime_begin(addr, dc, dc->page_fault_vcpu_time[cpu], cpu, already_received); @@ -824,34 +800,34 @@ static void mark_postcopy_blocktime_end(uintptr_t addr) low_time_offset = get_low_time_offset(dc); /* lookup cpu, to clear it, - * that algorithm looks straighforward, but it's not + * that algorithm looks straightforward, but it's not * optimal, more optimal algorithm is keeping tree or hash * where key is address value is a list of */ for (i = 0; i < smp_cpus; i++) { uint32_t vcpu_blocktime = 0; - read_vcpu_time = atomic_fetch_add(&dc->page_fault_vcpu_time[i], 0); - if (atomic_fetch_add(&dc->vcpu_addr[i], 0) != addr || + read_vcpu_time = qatomic_fetch_add(&dc->page_fault_vcpu_time[i], 0); + if (qatomic_fetch_add(&dc->vcpu_addr[i], 0) != addr || read_vcpu_time == 0) { continue; } - atomic_xchg(&dc->vcpu_addr[i], 0); + qatomic_xchg(&dc->vcpu_addr[i], 0); vcpu_blocktime = low_time_offset - read_vcpu_time; affected_cpu += 1; /* we need to know is that mark_postcopy_end was due to * faulted page, another possible case it's prefetched * page and in that case we shouldn't be here */ if (!vcpu_total_blocktime && - atomic_fetch_add(&dc->smp_cpus_down, 0) == smp_cpus) { + qatomic_fetch_add(&dc->smp_cpus_down, 0) == smp_cpus) { vcpu_total_blocktime = true; } /* continue cycle, due to one page could affect several vCPUs */ dc->vcpu_blocktime[i] += vcpu_blocktime; } - atomic_sub(&dc->smp_cpus_down, affected_cpu); + qatomic_sub(&dc->smp_cpus_down, affected_cpu); if (vcpu_total_blocktime) { - dc->total_blocktime += low_time_offset - atomic_fetch_add( + dc->total_blocktime += low_time_offset - qatomic_fetch_add( &dc->last_begin, 0); } trace_mark_postcopy_blocktime_end(addr, dc, dc->total_blocktime, @@ -927,7 +903,6 @@ static void *postcopy_ram_fault_thread(void *opaque) * the channel is rebuilt. */ if (postcopy_pause_fault_thread(mis)) { - mis->last_rb = NULL; /* Continue to read the userfaultfd */ } else { error_report("%s: paused but don't allow to continue", @@ -945,7 +920,7 @@ static void *postcopy_ram_fault_thread(void *opaque) error_report("%s: read() failed", __func__); } - if (atomic_read(&mis->fault_thread_quit)) { + if (qatomic_read(&mis->fault_thread_quit)) { trace_postcopy_ram_fault_thread_quit(); break; } @@ -1003,25 +978,12 @@ retry: * Send the request to the source - we want to request one * of our host page sizes (which is >= TPS) */ - if (rb != mis->last_rb) { - mis->last_rb = rb; - ret = migrate_send_rp_req_pages(mis, - qemu_ram_get_idstr(rb), - rb_offset, - qemu_ram_pagesize(rb)); - } else { - /* Save some space */ - ret = migrate_send_rp_req_pages(mis, - NULL, - rb_offset, - qemu_ram_pagesize(rb)); - } - + ret = migrate_send_rp_req_pages(mis, rb, rb_offset, + msg.arg.pagefault.address); if (ret) { /* May be network failure, try to wait for recovery */ if (ret == -EIO && postcopy_pause_fault_thread(mis)) { /* We got reconnected somehow, try to continue */ - mis->last_rb = NULL; goto retry; } else { /* This is a unavoidable fault */ @@ -1160,21 +1122,17 @@ int postcopy_ram_incoming_setup(MigrationIncomingState *mis) } memset(mis->postcopy_tmp_zero_page, '\0', mis->largest_page_size); - /* - * Ballooning can mark pages as absent while we're postcopying - * that would cause false userfaults. - */ - postcopy_balloon_inhibit(true); - trace_postcopy_ram_enable_notify(); return 0; } -static int qemu_ufd_copy_ioctl(int userfault_fd, void *host_addr, +static int qemu_ufd_copy_ioctl(MigrationIncomingState *mis, void *host_addr, void *from_addr, uint64_t pagesize, RAMBlock *rb) { + int userfault_fd = mis->userfault_fd; int ret; + if (from_addr) { struct uffdio_copy copy_struct; copy_struct.dst = (uint64_t)(uintptr_t)host_addr; @@ -1190,10 +1148,20 @@ static int qemu_ufd_copy_ioctl(int userfault_fd, void *host_addr, ret = ioctl(userfault_fd, UFFDIO_ZEROPAGE, &zero_struct); } if (!ret) { + qemu_mutex_lock(&mis->page_request_mutex); ramblock_recv_bitmap_set_range(rb, host_addr, pagesize / qemu_target_page_size()); + /* + * If this page resolves a page fault for a previous recorded faulted + * address, take a special note to maintain the requested page list. + */ + if (g_tree_lookup(mis->page_requested, host_addr)) { + g_tree_remove(mis->page_requested, host_addr); + mis->page_requested_count--; + trace_postcopy_page_req_del(host_addr, mis->page_requested_count); + } + qemu_mutex_unlock(&mis->page_request_mutex); mark_postcopy_blocktime_end((uintptr_t)host_addr); - } return ret; } @@ -1228,7 +1196,7 @@ int postcopy_place_page(MigrationIncomingState *mis, void *host, void *from, * which would be slightly cheaper, but we'd have to be careful * of the order of updating our page state. */ - if (qemu_ufd_copy_ioctl(mis->userfault_fd, host, from, pagesize, rb)) { + if (qemu_ufd_copy_ioctl(mis, host, from, pagesize, rb)) { int e = errno; error_report("%s: %s copy host: %p from: %p (size: %zd)", __func__, strerror(e), host, from, pagesize); @@ -1255,7 +1223,7 @@ int postcopy_place_page_zero(MigrationIncomingState *mis, void *host, * but it's not available for everything (e.g. hugetlbpages) */ if (qemu_ram_is_uf_zeroable(rb)) { - if (qemu_ufd_copy_ioctl(mis->userfault_fd, host, NULL, pagesize, rb)) { + if (qemu_ufd_copy_ioctl(mis, host, NULL, pagesize, rb)) { int e = errno; error_report("%s: %s zero host: %p", __func__, strerror(e), host); @@ -1433,13 +1401,13 @@ static PostcopyState incoming_postcopy_state; PostcopyState postcopy_state_get(void) { - return atomic_mb_read(&incoming_postcopy_state); + return qatomic_mb_read(&incoming_postcopy_state); } /* Set the state and return the old state */ PostcopyState postcopy_state_set(PostcopyState new_state) { - return atomic_xchg(&incoming_postcopy_state, new_state); + return qatomic_xchg(&incoming_postcopy_state, new_state); } /* Register a handler for external shared memory postcopy diff --git a/migration/postcopy-ram.h b/migration/postcopy-ram.h index 9941feb63aa710c3ae0dc1f9af0368951ccfb960..6d2b3cf124e880447dfc5ddc8d8250608c5c8042 100644 --- a/migration/postcopy-ram.h +++ b/migration/postcopy-ram.h @@ -161,7 +161,7 @@ struct PostCopyFD { */ void postcopy_register_shared_ufd(struct PostCopyFD *pcfd); void postcopy_unregister_shared_ufd(struct PostCopyFD *pcfd); -/* Call each of the shared 'waker's registerd telling them of +/* Call each of the shared 'waker's registered telling them of * availability of a block. */ int postcopy_notify_shared_wake(RAMBlock *rb, uint64_t offset); diff --git a/migration/qemu-file.c b/migration/qemu-file.c index 1c3a358a140d83de6709ddadf7e3ec6e2d7bfbb8..be21518c5708e6f720c15757a870f11c5d342402 100644 --- a/migration/qemu-file.c +++ b/migration/qemu-file.c @@ -31,7 +31,7 @@ #include "qapi/error.h" #define IO_BUF_SIZE 32768 -#define MAX_IOV_SIZE MIN(IOV_MAX, 64) +#define MAX_IOV_SIZE MIN_CONST(IOV_MAX, 64) struct QEMUFile { const QEMUFileOps *ops; diff --git a/migration/ram.c b/migration/ram.c index 859f835f1a552972373462725b64de42451a1433..7811cde643a1f0ebf12e870373ba5eef07a6436d 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -52,6 +52,7 @@ #include "migration/colo.h" #include "block.h" #include "sysemu/sysemu.h" +#include "sysemu/cpu-throttle.h" #include "savevm.h" #include "qemu/iov.h" #include "multifd.h" @@ -100,14 +101,16 @@ static struct { static void XBZRLE_cache_lock(void) { - if (migrate_use_xbzrle()) + if (migrate_use_xbzrle()) { qemu_mutex_lock(&XBZRLE.lock); + } } static void XBZRLE_cache_unlock(void) { - if (migrate_use_xbzrle()) + if (migrate_use_xbzrle()) { qemu_mutex_unlock(&XBZRLE.lock); + } } /** @@ -157,21 +160,12 @@ out: return ret; } -static bool ramblock_is_ignored(RAMBlock *block) +bool ramblock_is_ignored(RAMBlock *block) { return !qemu_ram_is_migratable(block) || (migrate_ignore_shared() && qemu_ram_is_shared(block)); } -/* Should be holding either ram_list.mutex, or the RCU lock. */ -#define RAMBLOCK_FOREACH_NOT_IGNORED(block) \ - INTERNAL_RAMBLOCK_FOREACH(block) \ - if (ramblock_is_ignored(block)) {} else - -#define RAMBLOCK_FOREACH_MIGRATABLE(block) \ - INTERNAL_RAMBLOCK_FOREACH(block) \ - if (!qemu_ram_is_migratable(block)) {} else - #undef RAMBLOCK_FOREACH int foreach_not_ignored_block(RAMBlockIterFunc func, void *opaque) @@ -255,7 +249,7 @@ int64_t ramblock_recv_bitmap_send(QEMUFile *file, /* * Always use little endian when sending the bitmap. This is * required that when source and destination VMs are not using the - * same endianess. (Note: big endian won't work.) + * same endianness. (Note: big endian won't work.) */ bitmap_to_le(le_bitmap, block->receivedmap, nbits); @@ -274,7 +268,7 @@ int64_t ramblock_recv_bitmap_send(QEMUFile *file, qemu_put_buffer(file, (const uint8_t *)le_bitmap, size); /* * Mark as an end, in case the middle part is screwed up due to - * some "misterious" reason. + * some "mysterious" reason. */ qemu_put_be64(file, RAMBLOCK_RECV_BITMAP_ENDING); qemu_fflush(file); @@ -717,7 +711,7 @@ static int save_xbzrle_page(RAMState *rs, uint8_t **current_data, /* * Reaching here means the page has hit the xbzrle cache, no matter what * encoding result it is (normal encoding, overflow or skipping the page), - * count the page as encoded. This is used to caculate the encoding rate. + * count the page as encoded. This is used to calculate the encoding rate. * * Example: 2 pages (8KB) being encoded, first page encoding generates 2KB, * 2nd page turns out to be skipped (i.e. no new bytes written to the @@ -859,9 +853,11 @@ static inline bool migration_bitmap_clear_dirty(RAMState *rs, /* Called with RCU critical section */ static void ramblock_sync_dirty_bitmap(RAMState *rs, RAMBlock *rb) { - rs->migration_dirty_pages += - cpu_physical_memory_sync_dirty_bitmap(rb, 0, rb->used_length, - &rs->num_dirty_pages_period); + uint64_t new_dirty_pages = + cpu_physical_memory_sync_dirty_bitmap(rb, 0, rb->used_length); + + rs->migration_dirty_pages += new_dirty_pages; + rs->num_dirty_pages_period += new_dirty_pages; } /** @@ -913,10 +909,8 @@ static void migration_update_rates(RAMState *rs, int64_t end_time) unencoded_size = (xbzrle_counters.pages - rs->xbzrle_pages_prev) * TARGET_PAGE_SIZE; encoded_size = xbzrle_counters.bytes - rs->xbzrle_bytes_prev; - if (xbzrle_counters.pages == rs->xbzrle_pages_prev) { + if (xbzrle_counters.pages == rs->xbzrle_pages_prev || !encoded_size) { xbzrle_counters.encoding_rate = 0; - } else if (!encoded_size) { - xbzrle_counters.encoding_rate = UINT64_MAX; } else { xbzrle_counters.encoding_rate = unencoded_size / encoded_size; } @@ -1571,7 +1565,7 @@ int ram_save_queue_pages(const char *rbname, ram_addr_t start, ram_addr_t len) rs->last_req_rb = ramblock; } trace_ram_save_queue_pages(ramblock->idstr, start, len); - if (start+len > ramblock->used_length) { + if (start + len > ramblock->used_length) { error_report("%s request overrun start=" RAM_ADDR_FMT " len=" RAM_ADDR_FMT " blocklen=" RAM_ADDR_FMT, __func__, start, len, ramblock->used_length); @@ -2749,7 +2743,7 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host) */ static inline RAMBlock *ram_block_from_stream(QEMUFile *f, int flags) { - static RAMBlock *block = NULL; + static RAMBlock *block; char id[256]; uint8_t len; @@ -3017,6 +3011,18 @@ static void decompress_data_with_multi_threads(QEMUFile *f, qemu_mutex_unlock(&decomp_done_lock); } + /* + * we must set ram_bulk_stage to false, otherwise in + * migation_bitmap_find_dirty the bitmap will be unused and + * all the pages in ram cache wil be flushed to the ram of + * secondary VM. + */ +static void colo_init_ram_state(void) +{ + ram_state_init(&ram_state); + ram_state->ram_bulk_stage = false; +} + /* * colo cache: this is for secondary VM, we cache the whole * memory of the secondary VM, it is need to hold the global lock @@ -3060,7 +3066,7 @@ int colo_init_ram_cache(void) } } - ram_state_init(&ram_state); + colo_init_ram_state(); return 0; } @@ -3306,7 +3312,7 @@ static int ram_load_postcopy(QEMUFile *f) multifd_recv_sync_main(); break; default: - error_report("Unknown combination of migration flags: %#x" + error_report("Unknown combination of migration flags: 0x%x" " (postcopy mode)", flags); ret = -EINVAL; break; @@ -3360,7 +3366,7 @@ static bool postcopy_is_running(void) * Flush content of RAM cache into SVM's memory. * Only flush the pages that be dirtied by PVM or SVM or both. */ -static void colo_flush_ram_cache(void) +void colo_flush_ram_cache(void) { RAMBlock *block = NULL; void *dst_host; @@ -3584,7 +3590,7 @@ static int ram_load_precopy(QEMUFile *f) if (flags & RAM_SAVE_FLAG_HOOK) { ram_control_load_hook(f, RAM_CONTROL_HOOK, NULL); } else { - error_report("Unknown combination of migration flags: %#x", + error_report("Unknown combination of migration flags: 0x%x", flags); ret = -EINVAL; } @@ -3632,9 +3638,6 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) } trace_ram_load_complete(ret, seq_iter); - if (!ret && migration_incoming_in_colo_state()) { - colo_flush_ram_cache(); - } return ret; } @@ -3707,7 +3710,7 @@ int ram_dirty_bitmap_reload(MigrationState *s, RAMBlock *block) /* * Note: see comments in ramblock_recv_bitmap_send() on why we - * need the endianess convertion, and the paddings. + * need the endianness conversion, and the paddings. */ local_size = ROUND_UP(local_size, 8); @@ -3738,14 +3741,14 @@ int ram_dirty_bitmap_reload(MigrationState *s, RAMBlock *block) } if (end_mark != RAMBLOCK_RECV_BITMAP_ENDING) { - error_report("%s: ramblock '%s' end mark incorrect: 0x%"PRIu64, + error_report("%s: ramblock '%s' end mark incorrect: 0x%"PRIx64, __func__, block->idstr, end_mark); ret = -EINVAL; goto out; } /* - * Endianess convertion. We are during postcopy (though paused). + * Endianness conversion. We are during postcopy (though paused). * The dirty bitmap won't change. We can directly modify it. */ bitmap_from_le(block->bmap, le_bitmap, nbits); diff --git a/migration/ram.h b/migration/ram.h index 5ceaff7cb4d740bdcd4d6a8143fff5c7d59ee0d9..011e85414ec77edd0db7b28b334ae7ed0be0697d 100644 --- a/migration/ram.h +++ b/migration/ram.h @@ -37,6 +37,16 @@ extern MigrationStats ram_counters; extern XBZRLECacheStats xbzrle_counters; extern CompressionStats compression_counters; +bool ramblock_is_ignored(RAMBlock *block); +/* Should be holding either ram_list.mutex, or the RCU lock. */ +#define RAMBLOCK_FOREACH_NOT_IGNORED(block) \ + INTERNAL_RAMBLOCK_FOREACH(block) \ + if (ramblock_is_ignored(block)) {} else + +#define RAMBLOCK_FOREACH_MIGRATABLE(block) \ + INTERNAL_RAMBLOCK_FOREACH(block) \ + if (!qemu_ram_is_migratable(block)) {} else + int xbzrle_cache_resize(int64_t new_size, Error **errp); uint64_t ram_bytes_remaining(void); uint64_t ram_bytes_total(void); @@ -65,6 +75,7 @@ int ram_dirty_bitmap_reload(MigrationState *s, RAMBlock *rb); /* ram cache */ int colo_init_ram_cache(void); +void colo_flush_ram_cache(void); void colo_release_ram_cache(void); void colo_incoming_start_dirty_log(void); diff --git a/migration/rdma.c b/migration/rdma.c index 967fda5b0c75a5e0ce2d70eed1a719d5d22d2c5c..00eac34232ec4458ef1c0ecaac57130414890f52 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -29,11 +29,13 @@ #include "qemu/sockets.h" #include "qemu/bitmap.h" #include "qemu/coroutine.h" +#include "exec/memory.h" #include #include #include #include #include "trace.h" +#include "qom/object.h" /* * Print and error on both the Monitor and the Log file. @@ -271,7 +273,8 @@ static uint64_t htonll(uint64_t v) return u.llv; } -static uint64_t ntohll(uint64_t v) { +static uint64_t ntohll(uint64_t v) +{ union { uint32_t lv[2]; uint64_t llv; } u; u.llv = v; return ((uint64_t)ntohl(u.lv[0]) << 32) | (uint64_t) ntohl(u.lv[1]); @@ -396,10 +399,8 @@ typedef struct RDMAContext { } RDMAContext; #define TYPE_QIO_CHANNEL_RDMA "qio-channel-rdma" -#define QIO_CHANNEL_RDMA(obj) \ - OBJECT_CHECK(QIOChannelRDMA, (obj), TYPE_QIO_CHANNEL_RDMA) +OBJECT_DECLARE_SIMPLE_TYPE(QIOChannelRDMA, QIO_CHANNEL_RDMA) -typedef struct QIOChannelRDMA QIOChannelRDMA; struct QIOChannelRDMA { @@ -854,7 +855,7 @@ static int qemu_rdma_broken_ipv6_kernel(struct ibv_context *verbs, Error **errp) */ if (!verbs) { int num_devices, x; - struct ibv_device ** dev_list = ibv_get_device_list(&num_devices); + struct ibv_device **dev_list = ibv_get_device_list(&num_devices); bool roce_found = false; bool ib_found = false; @@ -1288,7 +1289,7 @@ const char *print_wrid(int wrid) * workload information or LRU information is available, do not attempt to use * this feature except for basic testing. */ -//#define RDMA_UNREGISTRATION_EXAMPLE +/* #define RDMA_UNREGISTRATION_EXAMPLE */ /* * Perform a non-optimized memory unregistration after every transfer @@ -1509,7 +1510,7 @@ static int qemu_rdma_wait_comp_channel(RDMAContext *rdma) } else { /* This is the source side, we're in a separate thread * or destination prior to migration_fd_process_incoming() - * after postcopy, the destination also in a seprate thread. + * after postcopy, the destination also in a separate thread. * we can't yield; so we have to poll the fd. * But we need to be able to handle 'cancel' or an error * without hanging forever. @@ -2266,7 +2267,7 @@ static inline int qemu_rdma_buffer_mergable(RDMAContext *rdma, * chunk, then start a new chunk and flush() the old chunk. * 3. To keep the hardware busy, we also group chunks into batches * and only require that a batch gets acknowledged in the completion - * qeueue instead of each individual chunk. + * queue instead of each individual chunk. */ static int qemu_rdma_write(QEMUFile *f, RDMAContext *rdma, uint64_t block_offset, uint64_t offset, @@ -2678,7 +2679,7 @@ static ssize_t qio_channel_rdma_writev(QIOChannel *ioc, size_t len = 0; RCU_READ_LOCK_GUARD(); - rdma = atomic_rcu_read(&rioc->rdmaout); + rdma = qatomic_rcu_read(&rioc->rdmaout); if (!rdma) { return -EIO; @@ -2760,7 +2761,7 @@ static ssize_t qio_channel_rdma_readv(QIOChannel *ioc, size_t done = 0; RCU_READ_LOCK_GUARD(); - rdma = atomic_rcu_read(&rioc->rdmain); + rdma = qatomic_rcu_read(&rioc->rdmain); if (!rdma) { return -EIO; @@ -2875,9 +2876,9 @@ qio_channel_rdma_source_prepare(GSource *source, RCU_READ_LOCK_GUARD(); if (rsource->condition == G_IO_IN) { - rdma = atomic_rcu_read(&rsource->rioc->rdmain); + rdma = qatomic_rcu_read(&rsource->rioc->rdmain); } else { - rdma = atomic_rcu_read(&rsource->rioc->rdmaout); + rdma = qatomic_rcu_read(&rsource->rioc->rdmaout); } if (!rdma) { @@ -2902,9 +2903,9 @@ qio_channel_rdma_source_check(GSource *source) RCU_READ_LOCK_GUARD(); if (rsource->condition == G_IO_IN) { - rdma = atomic_rcu_read(&rsource->rioc->rdmain); + rdma = qatomic_rcu_read(&rsource->rioc->rdmain); } else { - rdma = atomic_rcu_read(&rsource->rioc->rdmaout); + rdma = qatomic_rcu_read(&rsource->rioc->rdmaout); } if (!rdma) { @@ -2932,9 +2933,9 @@ qio_channel_rdma_source_dispatch(GSource *source, RCU_READ_LOCK_GUARD(); if (rsource->condition == G_IO_IN) { - rdma = atomic_rcu_read(&rsource->rioc->rdmain); + rdma = qatomic_rcu_read(&rsource->rioc->rdmain); } else { - rdma = atomic_rcu_read(&rsource->rioc->rdmaout); + rdma = qatomic_rcu_read(&rsource->rioc->rdmaout); } if (!rdma) { @@ -3035,12 +3036,12 @@ static int qio_channel_rdma_close(QIOChannel *ioc, rdmain = rioc->rdmain; if (rdmain) { - atomic_rcu_set(&rioc->rdmain, NULL); + qatomic_rcu_set(&rioc->rdmain, NULL); } rdmaout = rioc->rdmaout; if (rdmaout) { - atomic_rcu_set(&rioc->rdmaout, NULL); + qatomic_rcu_set(&rioc->rdmaout, NULL); } rcu->rdmain = rdmain; @@ -3060,8 +3061,8 @@ qio_channel_rdma_shutdown(QIOChannel *ioc, RCU_READ_LOCK_GUARD(); - rdmain = atomic_rcu_read(&rioc->rdmain); - rdmaout = atomic_rcu_read(&rioc->rdmain); + rdmain = qatomic_rcu_read(&rioc->rdmain); + rdmaout = qatomic_rcu_read(&rioc->rdmain); switch (how) { case QIO_CHANNEL_SHUTDOWN_READ: @@ -3131,7 +3132,7 @@ static size_t qemu_rdma_save_page(QEMUFile *f, void *opaque, int ret; RCU_READ_LOCK_GUARD(); - rdma = atomic_rcu_read(&rioc->rdmaout); + rdma = qatomic_rcu_read(&rioc->rdmaout); if (!rdma) { return -EIO; @@ -3148,7 +3149,7 @@ static size_t qemu_rdma_save_page(QEMUFile *f, void *opaque, if (size > 0) { /* * Add this page to the current 'chunk'. If the chunk - * is full, or the page doen't belong to the current chunk, + * is full, or the page doesn't belong to the current chunk, * an actual RDMA write will occur and a new chunk will be formed. */ ret = qemu_rdma_write(f, rdma, block_offset, offset, size); @@ -3451,7 +3452,7 @@ static int qemu_rdma_registration_handle(QEMUFile *f, void *opaque) int i = 0; RCU_READ_LOCK_GUARD(); - rdma = atomic_rcu_read(&rioc->rdmain); + rdma = qatomic_rcu_read(&rioc->rdmain); if (!rdma) { return -EIO; @@ -3714,7 +3715,7 @@ rdma_block_notification_handle(QIOChannelRDMA *rioc, const char *name) int found = -1; RCU_READ_LOCK_GUARD(); - rdma = atomic_rcu_read(&rioc->rdmain); + rdma = qatomic_rcu_read(&rioc->rdmain); if (!rdma) { return -EIO; @@ -3762,7 +3763,7 @@ static int qemu_rdma_registration_start(QEMUFile *f, void *opaque, RDMAContext *rdma; RCU_READ_LOCK_GUARD(); - rdma = atomic_rcu_read(&rioc->rdmaout); + rdma = qatomic_rcu_read(&rioc->rdmaout); if (!rdma) { return -EIO; } @@ -3787,14 +3788,13 @@ static int qemu_rdma_registration_start(QEMUFile *f, void *opaque, static int qemu_rdma_registration_stop(QEMUFile *f, void *opaque, uint64_t flags, void *data) { - Error *local_err = NULL, **errp = &local_err; QIOChannelRDMA *rioc = QIO_CHANNEL_RDMA(opaque); RDMAContext *rdma; RDMAControlHeader head = { .len = 0, .repeat = 1 }; int ret = 0; RCU_READ_LOCK_GUARD(); - rdma = atomic_rcu_read(&rioc->rdmaout); + rdma = qatomic_rcu_read(&rioc->rdmaout); if (!rdma) { return -EIO; } @@ -3832,7 +3832,7 @@ static int qemu_rdma_registration_stop(QEMUFile *f, void *opaque, ®_result_idx, rdma->pin_all ? qemu_rdma_reg_whole_ram_blocks : NULL); if (ret < 0) { - ERROR(errp, "receiving remote info!"); + fprintf(stderr, "receiving remote info!"); return ret; } @@ -3851,10 +3851,10 @@ static int qemu_rdma_registration_stop(QEMUFile *f, void *opaque, */ if (local->nb_blocks != nb_dest_blocks) { - ERROR(errp, "ram blocks mismatch (Number of blocks %d vs %d) " - "Your QEMU command line parameters are probably " - "not identical on both the source and destination.", - local->nb_blocks, nb_dest_blocks); + fprintf(stderr, "ram blocks mismatch (Number of blocks %d vs %d) " + "Your QEMU command line parameters are probably " + "not identical on both the source and destination.", + local->nb_blocks, nb_dest_blocks); rdma->error_state = -EINVAL; return -EINVAL; } @@ -3867,10 +3867,10 @@ static int qemu_rdma_registration_stop(QEMUFile *f, void *opaque, /* We require that the blocks are in the same order */ if (rdma->dest_blocks[i].length != local->block[i].length) { - ERROR(errp, "Block %s/%d has a different length %" PRIu64 - "vs %" PRIu64, local->block[i].block_name, i, - local->block[i].length, - rdma->dest_blocks[i].length); + fprintf(stderr, "Block %s/%d has a different length %" PRIu64 + "vs %" PRIu64, local->block[i].block_name, i, + local->block[i].length, + rdma->dest_blocks[i].length); rdma->error_state = -EINVAL; return -EINVAL; } @@ -4017,8 +4017,14 @@ void rdma_start_incoming_migration(const char *host_port, Error **errp) Error *local_err = NULL; trace_rdma_start_incoming_migration(); - rdma = qemu_rdma_data_init(host_port, &local_err); + /* Avoid ram_block_discard_disable(), cannot change during migration. */ + if (ram_block_discard_is_required()) { + error_setg(errp, "RDMA: cannot disable RAM discard"); + return; + } + + rdma = qemu_rdma_data_init(host_port, &local_err); if (rdma == NULL) { goto err; } @@ -4056,7 +4062,9 @@ void rdma_start_incoming_migration(const char *host_port, Error **errp) return; err: error_propagate(errp, local_err); - g_free(rdma->host); + if (rdma) { + g_free(rdma->host); + } g_free(rdma); g_free(rdma_return_path); } @@ -4065,10 +4073,17 @@ void rdma_start_outgoing_migration(void *opaque, const char *host_port, Error **errp) { MigrationState *s = opaque; - RDMAContext *rdma = qemu_rdma_data_init(host_port, errp); RDMAContext *rdma_return_path = NULL; + RDMAContext *rdma; int ret = 0; + /* Avoid ram_block_discard_disable(), cannot change during migration. */ + if (ram_block_discard_is_required()) { + error_setg(errp, "RDMA: cannot disable RAM discard"); + return; + } + + rdma = qemu_rdma_data_init(host_port, errp); if (rdma == NULL) { goto err; } @@ -4087,25 +4102,25 @@ void rdma_start_outgoing_migration(void *opaque, goto err; } - /* RDMA postcopy need a seprate queue pair for return path */ + /* RDMA postcopy need a separate queue pair for return path */ if (migrate_postcopy()) { rdma_return_path = qemu_rdma_data_init(host_port, errp); if (rdma_return_path == NULL) { - goto err; + goto return_path_err; } ret = qemu_rdma_source_init(rdma_return_path, s->enabled_capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL], errp); if (ret) { - goto err; + goto return_path_err; } ret = qemu_rdma_connect(rdma_return_path, errp); if (ret) { - goto err; + goto return_path_err; } rdma->return_path = rdma_return_path; @@ -4118,6 +4133,8 @@ void rdma_start_outgoing_migration(void *opaque, s->to_dst_file = qemu_fopen_rdma(rdma, "wb"); migrate_fd_connect(s, NULL); return; +return_path_err: + qemu_rdma_cleanup(rdma); err: g_free(rdma); g_free(rdma_return_path); diff --git a/migration/savevm.c b/migration/savevm.c index c00a6807d92371380208762dc440fd21f273902a..5f937a2762793f2cc48bcd40a42369a9f60858c4 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -28,7 +28,6 @@ #include "qemu/osdep.h" #include "hw/boards.h" -#include "hw/xen/xen.h" #include "net/net.h" #include "migration.h" #include "migration/snapshot.h" @@ -43,7 +42,6 @@ #include "postcopy-ram.h" #include "qapi/error.h" #include "qapi/qapi-commands-migration.h" -#include "qapi/qapi-commands-misc.h" #include "qapi/qmp/qerror.h" #include "qemu/error-report.h" #include "sysemu/cpus.h" @@ -59,12 +57,13 @@ #include "sysemu/replay.h" #include "sysemu/runstate.h" #include "sysemu/sysemu.h" +#include "sysemu/xen.h" #include "qjson.h" #include "migration/colo.h" #include "qemu/bitmap.h" #include "net/announce.h" -const unsigned int postcopy_ram_discard_version = 0; +const unsigned int postcopy_ram_discard_version; /* Subcommands for QEMU_VM_COMMAND */ enum qemu_vm_cmd { @@ -521,7 +520,7 @@ static const VMStateDescription vmstate_configuration = { VMSTATE_VBUFFER_ALLOC_UINT32(name, SaveState, 0, NULL, len), VMSTATE_END_OF_LIST() }, - .subsections = (const VMStateDescription*[]) { + .subsections = (const VMStateDescription *[]) { &vmstate_target_page_bits, &vmstate_capabilites, &vmstate_uuid, @@ -1813,6 +1812,9 @@ static void *postcopy_ram_listen_thread(void *opaque) MigrationIncomingState *mis = migration_incoming_get_current(); QEMUFile *f = mis->from_src_file; int load_res; + MigrationState *migr = migrate_get_current(); + + object_ref(OBJECT(migr)); migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE, MIGRATION_STATUS_POSTCOPY_ACTIVE); @@ -1839,11 +1841,24 @@ static void *postcopy_ram_listen_thread(void *opaque) trace_postcopy_ram_listen_thread_exit(); if (load_res < 0) { - error_report("%s: loadvm failed: %d", __func__, load_res); qemu_file_set_error(f, load_res); - migrate_set_state(&mis->state, MIGRATION_STATUS_POSTCOPY_ACTIVE, - MIGRATION_STATUS_FAILED); - } else { + dirty_bitmap_mig_cancel_incoming(); + if (postcopy_state_get() == POSTCOPY_INCOMING_RUNNING && + !migrate_postcopy_ram() && migrate_dirty_bitmaps()) + { + error_report("%s: loadvm failed during postcopy: %d. All states " + "are migrated except dirty bitmaps. Some dirty " + "bitmaps may be lost, and present migrated dirty " + "bitmaps are correctly migrated and valid.", + __func__, load_res); + load_res = 0; /* prevent further exit() */ + } else { + error_report("%s: loadvm failed: %d", __func__, load_res); + migrate_set_state(&mis->state, MIGRATION_STATUS_POSTCOPY_ACTIVE, + MIGRATION_STATUS_FAILED); + } + } + if (load_res >= 0) { /* * This looks good, but it's possible that the device loading in the * main thread hasn't finished yet, and so we might not be in 'RUN' @@ -1879,6 +1894,8 @@ static void *postcopy_ram_listen_thread(void *opaque) mis->have_listen_thread = false; postcopy_state_set(POSTCOPY_INCOMING_END); + object_unref(OBJECT(migr)); + return NULL; } @@ -1993,6 +2010,49 @@ static int loadvm_postcopy_handle_run(MigrationIncomingState *mis) return LOADVM_QUIT; } +/* We must be with page_request_mutex held */ +static gboolean postcopy_sync_page_req(gpointer key, gpointer value, + gpointer data) +{ + MigrationIncomingState *mis = data; + void *host_addr = (void *) key; + ram_addr_t rb_offset; + RAMBlock *rb; + int ret; + + rb = qemu_ram_block_from_host(host_addr, true, &rb_offset); + if (!rb) { + /* + * This should _never_ happen. However be nice for a migrating VM to + * not crash/assert. Post an error (note: intended to not use *_once + * because we do want to see all the illegal addresses; and this can + * never be triggered by the guest so we're safe) and move on next. + */ + error_report("%s: illegal host addr %p", __func__, host_addr); + /* Try the next entry */ + return FALSE; + } + + ret = migrate_send_rp_message_req_pages(mis, rb, rb_offset); + if (ret) { + /* Please refer to above comment. */ + error_report("%s: send rp message failed for addr %p", + __func__, host_addr); + return FALSE; + } + + trace_postcopy_page_req_sync(host_addr); + + return FALSE; +} + +static void migrate_send_rp_req_pages_pending(MigrationIncomingState *mis) +{ + WITH_QEMU_LOCK_GUARD(&mis->page_request_mutex) { + g_tree_foreach(mis->page_requested, postcopy_sync_page_req, mis); + } +} + static int loadvm_postcopy_handle_resume(MigrationIncomingState *mis) { if (mis->state != MIGRATION_STATUS_POSTCOPY_RECOVER) { @@ -2001,20 +2061,45 @@ static int loadvm_postcopy_handle_resume(MigrationIncomingState *mis) return 0; } + /* + * Reset the last_rb before we resend any page req to source again, since + * the source should have it reset already. + */ + mis->last_rb = NULL; + /* * This means source VM is ready to resume the postcopy migration. - * It's time to switch state and release the fault thread to - * continue service page faults. */ migrate_set_state(&mis->state, MIGRATION_STATUS_POSTCOPY_RECOVER, MIGRATION_STATUS_POSTCOPY_ACTIVE); - qemu_sem_post(&mis->postcopy_pause_sem_fault); trace_loadvm_postcopy_handle_resume(); /* Tell source that "we are ready" */ migrate_send_rp_resume_ack(mis, MIGRATION_RESUME_ACK_VALUE); + /* + * After a postcopy recovery, the source should have lost the postcopy + * queue, or potentially the requested pages could have been lost during + * the network down phase. Let's re-sync with the source VM by re-sending + * all the pending pages that we eagerly need, so these threads won't get + * blocked too long due to the recovery. + * + * Without this procedure, the faulted destination VM threads (waiting for + * page requests right before the postcopy is interrupted) can keep hanging + * until the pages are sent by the source during the background copying of + * pages, or another thread faulted on the same address accidentally. + */ + migrate_send_rp_req_pages_pending(mis); + + /* + * It's time to switch state and release the fault thread to continue + * service page faults. Note that this should be explicitly after the + * above call to migrate_send_rp_req_pages_pending(). In short: + * migrate_send_rp_message_req_pages() is not thread safe, yet. + */ + qemu_sem_post(&mis->postcopy_pause_sem_fault); + return 0; } @@ -2111,8 +2196,15 @@ static int loadvm_handle_recv_bitmap(MigrationIncomingState *mis, static int loadvm_process_enable_colo(MigrationIncomingState *mis) { - migration_incoming_enable_colo(); - return colo_init_ram_cache(); + int ret = migration_incoming_enable_colo(); + + if (!ret) { + ret = colo_init_ram_cache(); + if (ret) { + migration_incoming_disable_colo(); + } + } + return ret; } /* @@ -2430,6 +2522,8 @@ static bool postcopy_pause_incoming(MigrationIncomingState *mis) { trace_postcopy_pause_incoming(); + assert(migrate_postcopy_ram()); + /* Clear the triggered bit to allow one recovery */ mis->postcopy_recover_triggered = false; @@ -2514,15 +2608,22 @@ out: if (ret < 0) { qemu_file_set_error(f, ret); + /* Cancel bitmaps incoming regardless of recovery */ + dirty_bitmap_mig_cancel_incoming(); + /* * If we are during an active postcopy, then we pause instead * of bail out to at least keep the VM's dirty data. Note * that POSTCOPY_INCOMING_LISTENING stage is still not enough, * during which we're still receiving device states and we * still haven't yet started the VM on destination. + * + * Only RAM postcopy supports recovery. Still, if RAM postcopy is + * enabled, canceled bitmaps postcopy will not affect RAM postcopy + * recovering. */ if (postcopy_state_get() == POSTCOPY_INCOMING_RUNNING && - postcopy_pause_incoming(mis)) { + migrate_postcopy_ram() && postcopy_pause_incoming(mis)) { /* Reset f to point to the newly created channel */ f = mis->from_src_file; goto retry; @@ -2628,7 +2729,7 @@ int save_snapshot(const char *name, Error **errp) { BlockDriverState *bs, *bs1; QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1; - int ret = -1; + int ret = -1, ret2; QEMUFile *f; int saved_vm_running; uint64_t vm_state_size; @@ -2648,7 +2749,7 @@ int save_snapshot(const char *name, Error **errp) if (!bdrv_all_can_snapshot(&bs)) { error_setg(errp, "Device '%s' is writable but does not support " - "snapshots", bdrv_get_device_name(bs)); + "snapshots", bdrv_get_device_or_node_name(bs)); return ret; } @@ -2657,7 +2758,7 @@ int save_snapshot(const char *name, Error **errp) ret = bdrv_all_delete_snapshot(name, &bs1, errp); if (ret < 0) { error_prepend(errp, "Error while deleting snapshot on device " - "'%s': ", bdrv_get_device_name(bs1)); + "'%s': ", bdrv_get_device_or_node_name(bs1)); return ret; } } @@ -2689,6 +2790,11 @@ int save_snapshot(const char *name, Error **errp) sn->date_sec = tv.tv_sec; sn->date_nsec = tv.tv_usec * 1000; sn->vm_clock_nsec = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + if (replay_mode != REPLAY_MODE_NONE) { + sn->icount = replay_get_current_icount(); + } else { + sn->icount = -1ULL; + } if (name) { ret = bdrv_snapshot_find(bs, old_sn, name); @@ -2712,10 +2818,14 @@ int save_snapshot(const char *name, Error **errp) } ret = qemu_savevm_state(f, errp); vm_state_size = qemu_ftell(f); - qemu_fclose(f); + ret2 = qemu_fclose(f); if (ret < 0) { goto the_end; } + if (ret2 < 0) { + ret = ret2; + goto the_end; + } /* The bdrv_all_create_snapshot() call that follows acquires the AioContext * for itself. BDRV_POLL_WHILE() does not support nested locking because @@ -2728,7 +2838,7 @@ int save_snapshot(const char *name, Error **errp) ret = bdrv_all_create_snapshot(sn, bs, vm_state_size, &bs); if (ret < 0) { error_setg(errp, "Error while creating snapshot on '%s'", - bdrv_get_device_name(bs)); + bdrv_get_device_or_node_name(bs)); goto the_end; } @@ -2757,7 +2867,7 @@ void qmp_xen_save_devices_state(const char *filename, bool has_live, bool live, if (!has_live) { /* live default to true so old version of Xen tool stack can have a - * successfull live migration */ + * successful live migration */ live = true; } @@ -2765,7 +2875,8 @@ void qmp_xen_save_devices_state(const char *filename, bool has_live, bool live, vm_stop(RUN_STATE_SAVE_VM); global_state_store_running(); - ioc = qio_channel_file_new_path(filename, O_WRONLY | O_CREAT, 0660, errp); + ioc = qio_channel_file_new_path(filename, O_WRONLY | O_CREAT | O_TRUNC, + 0660, errp); if (!ioc) { goto the_end; } @@ -2780,7 +2891,7 @@ void qmp_xen_save_devices_state(const char *filename, bool has_live, bool live, * "xen-save-devices-state" and in case of migration failure, libxl * would call "cont". * So call bdrv_inactivate_all (release locks) here to let the other - * side of the migration take controle of the images. + * side of the migration take control of the images. */ if (live && !saved_vm_running) { ret = bdrv_inactivate_all(); @@ -2837,23 +2948,17 @@ int load_snapshot(const char *name, Error **errp) AioContext *aio_context; MigrationIncomingState *mis = migration_incoming_get_current(); - if (!replay_can_snapshot()) { - error_setg(errp, "Record/replay does not allow loading snapshot " - "right now. Try once more later."); - return -EINVAL; - } - if (!bdrv_all_can_snapshot(&bs)) { error_setg(errp, "Device '%s' is writable but does not support snapshots", - bdrv_get_device_name(bs)); + bdrv_get_device_or_node_name(bs)); return -ENOTSUP; } ret = bdrv_all_find_snapshot(name, &bs); if (ret < 0) { error_setg(errp, "Device '%s' does not have the requested snapshot '%s'", - bdrv_get_device_name(bs), name); + bdrv_get_device_or_node_name(bs), name); return ret; } @@ -2876,13 +2981,19 @@ int load_snapshot(const char *name, Error **errp) return -EINVAL; } + /* + * Flush the record/replay queue. Now the VM state is going + * to change. Therefore we don't need to preserve its consistency + */ + replay_flush_events(); + /* Flush all IO requests so they don't interfere with the new state. */ bdrv_drain_all_begin(); ret = bdrv_all_goto_snapshot(name, &bs, errp); if (ret < 0) { error_prepend(errp, "Could not load snapshot '%s' on '%s': ", - name, bdrv_get_device_name(bs)); + name, bdrv_get_device_or_node_name(bs)); goto err_drain; } diff --git a/migration/socket.c b/migration/socket.c index 97c9efde5969de73ca504a26f654707a587be0d7..6016642e0402e5221501cc3c88247149c860be86 100644 --- a/migration/socket.c +++ b/migration/socket.c @@ -50,34 +50,6 @@ int socket_send_channel_destroy(QIOChannel *send) return 0; } -static SocketAddress *tcp_build_address(const char *host_port, Error **errp) -{ - SocketAddress *saddr; - - saddr = g_new0(SocketAddress, 1); - saddr->type = SOCKET_ADDRESS_TYPE_INET; - - if (inet_parse(&saddr->u.inet, host_port, errp)) { - qapi_free_SocketAddress(saddr); - return NULL; - } - - return saddr; -} - - -static SocketAddress *unix_build_address(const char *path) -{ - SocketAddress *saddr; - - saddr = g_new0(SocketAddress, 1); - saddr->type = SOCKET_ADDRESS_TYPE_UNIX; - saddr->u.q_unix.path = g_strdup(path); - - return saddr; -} - - struct SocketConnectData { MigrationState *s; char *hostname; @@ -109,9 +81,10 @@ static void socket_outgoing_migration(QIOTask *task, object_unref(OBJECT(sioc)); } -static void socket_start_outgoing_migration(MigrationState *s, - SocketAddress *saddr, - Error **errp) +static void +socket_start_outgoing_migration_internal(MigrationState *s, + SocketAddress *saddr, + Error **errp) { QIOChannelSocket *sioc = qio_channel_socket_new(); struct SocketConnectData *data = g_new0(struct SocketConnectData, 1); @@ -135,27 +108,18 @@ static void socket_start_outgoing_migration(MigrationState *s, NULL); } -void tcp_start_outgoing_migration(MigrationState *s, - const char *host_port, - Error **errp) +void socket_start_outgoing_migration(MigrationState *s, + const char *str, + Error **errp) { Error *err = NULL; - SocketAddress *saddr = tcp_build_address(host_port, &err); + SocketAddress *saddr = socket_parse(str, &err); if (!err) { - socket_start_outgoing_migration(s, saddr, &err); + socket_start_outgoing_migration_internal(s, saddr, &err); } error_propagate(errp, err); } -void unix_start_outgoing_migration(MigrationState *s, - const char *path, - Error **errp) -{ - SocketAddress *saddr = unix_build_address(path); - socket_start_outgoing_migration(s, saddr, errp); -} - - static void socket_accept_incoming_migration(QIONetListener *listener, QIOChannelSocket *cioc, gpointer opaque) @@ -173,8 +137,9 @@ static void socket_accept_incoming_migration(QIONetListener *listener, } -static void socket_start_incoming_migration(SocketAddress *saddr, - Error **errp) +static void +socket_start_incoming_migration_internal(SocketAddress *saddr, + Error **errp) { QIONetListener *listener = qio_net_listener_new(); size_t i; @@ -207,20 +172,13 @@ static void socket_start_incoming_migration(SocketAddress *saddr, } } -void tcp_start_incoming_migration(const char *host_port, Error **errp) +void socket_start_incoming_migration(const char *str, Error **errp) { Error *err = NULL; - SocketAddress *saddr = tcp_build_address(host_port, &err); + SocketAddress *saddr = socket_parse(str, &err); if (!err) { - socket_start_incoming_migration(saddr, &err); + socket_start_incoming_migration_internal(saddr, &err); } qapi_free_SocketAddress(saddr); error_propagate(errp, err); } - -void unix_start_incoming_migration(const char *path, Error **errp) -{ - SocketAddress *saddr = unix_build_address(path); - socket_start_incoming_migration(saddr, errp); - qapi_free_SocketAddress(saddr); -} diff --git a/migration/socket.h b/migration/socket.h index 528c3b020270c38d2fb272c1e5d2f1a878b5fd96..891dbcccebbb421ca9bd9d9af01834e1fef8c220 100644 --- a/migration/socket.h +++ b/migration/socket.h @@ -23,13 +23,8 @@ void socket_send_channel_create(QIOTaskFunc f, void *data); int socket_send_channel_destroy(QIOChannel *send); -void tcp_start_incoming_migration(const char *host_port, Error **errp); +void socket_start_incoming_migration(const char *str, Error **errp); -void tcp_start_outgoing_migration(MigrationState *s, const char *host_port, - Error **errp); - -void unix_start_incoming_migration(const char *path, Error **errp); - -void unix_start_outgoing_migration(MigrationState *s, const char *path, - Error **errp); +void socket_start_outgoing_migration(MigrationState *s, const char *str, + Error **errp); #endif diff --git a/migration/tls.c b/migration/tls.c index 5171afc6c481d96121e5d0cffaf842be3f852f85..abb149d8325304ba36b1910dd06255af1128ce2a 100644 --- a/migration/tls.c +++ b/migration/tls.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -22,7 +22,6 @@ #include "channel.h" #include "migration.h" #include "tls.h" -#include "io/channel-tls.h" #include "crypto/tlscreds.h" #include "qemu/error-report.h" #include "qapi/error.h" @@ -58,7 +57,6 @@ migration_tls_get_creds(MigrationState *s, return NULL; } - object_ref(OBJECT(ret)); return ret; } @@ -126,11 +124,10 @@ static void migration_tls_outgoing_handshake(QIOTask *task, object_unref(OBJECT(ioc)); } - -void migration_tls_channel_connect(MigrationState *s, - QIOChannel *ioc, - const char *hostname, - Error **errp) +QIOChannelTLS *migration_tls_client_create(MigrationState *s, + QIOChannel *ioc, + const char *hostname, + Error **errp) { QCryptoTLSCreds *creds; QIOChannelTLS *tioc; @@ -138,7 +135,7 @@ void migration_tls_channel_connect(MigrationState *s, creds = migration_tls_get_creds( s, QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT, errp); if (!creds) { - return; + return NULL; } if (s->parameters.tls_hostname && *s->parameters.tls_hostname) { @@ -146,15 +143,29 @@ void migration_tls_channel_connect(MigrationState *s, } if (!hostname) { error_setg(errp, "No hostname available for TLS"); - return; + return NULL; } tioc = qio_channel_tls_new_client( ioc, creds, hostname, errp); + + return tioc; +} + +void migration_tls_channel_connect(MigrationState *s, + QIOChannel *ioc, + const char *hostname, + Error **errp) +{ + QIOChannelTLS *tioc; + + tioc = migration_tls_client_create(s, ioc, hostname, errp); if (!tioc) { return; } + /* Save hostname into MigrationState for handshake */ + s->hostname = g_strdup(hostname); trace_migration_tls_outgoing_handshake_start(hostname); qio_channel_set_name(QIO_CHANNEL(tioc), "migration-tls-outgoing"); qio_channel_tls_handshake(tioc, diff --git a/migration/tls.h b/migration/tls.h index cdd70001ed3656368dd9c347c7ed4c3132ec88cc..de4fe2cafd71e199ced0b89bcb3ff86ca24b2b28 100644 --- a/migration/tls.h +++ b/migration/tls.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -22,11 +22,17 @@ #define QEMU_MIGRATION_TLS_H #include "io/channel.h" +#include "io/channel-tls.h" void migration_tls_channel_process_incoming(MigrationState *s, QIOChannel *ioc, Error **errp); +QIOChannelTLS *migration_tls_client_create(MigrationState *s, + QIOChannel *ioc, + const char *hostname, + Error **errp); + void migration_tls_channel_connect(MigrationState *s, QIOChannel *ioc, const char *hostname, diff --git a/migration/trace-events b/migration/trace-events index 4ab0a503d21b249d034925806bfcab07a2cf4fd4..75de5004ac85e9c611a6f01ed05a1001bf1a6d3f 100644 --- a/migration/trace-events +++ b/migration/trace-events @@ -49,6 +49,7 @@ vmstate_save(const char *idstr, const char *vmsd_name) "%s, %s" vmstate_load(const char *idstr, const char *vmsd_name) "%s, %s" postcopy_pause_incoming(void) "" postcopy_pause_incoming_continued(void) "" +postcopy_page_req_sync(void *host_addr) "sync page req %p" # vmstate.c vmstate_load_field_error(const char *field, int ret) "field \"%s\" load failed, ret = %d" @@ -91,24 +92,6 @@ migration_bitmap_sync_start(void) "" migration_bitmap_sync_end(uint64_t dirty_pages) "dirty_pages %" PRIu64 migration_bitmap_clear_dirty(char *str, uint64_t start, uint64_t size, unsigned long page) "rb %s start 0x%"PRIx64" size 0x%"PRIx64" page 0x%lx" migration_throttle(void) "" -multifd_new_send_channel_async(uint8_t id) "channel %d" -multifd_recv(uint8_t id, uint64_t packet_num, uint32_t used, uint32_t flags, uint32_t next_packet_size) "channel %d packet_num %" PRIu64 " pages %d flags 0x%x next packet size %d" -multifd_recv_new_channel(uint8_t id) "channel %d" -multifd_recv_sync_main(long packet_num) "packet num %ld" -multifd_recv_sync_main_signal(uint8_t id) "channel %d" -multifd_recv_sync_main_wait(uint8_t id) "channel %d" -multifd_recv_terminate_threads(bool error) "error %d" -multifd_recv_thread_end(uint8_t id, uint64_t packets, uint64_t pages) "channel %d packets %" PRIu64 " pages %" PRIu64 -multifd_recv_thread_start(uint8_t id) "%d" -multifd_save_setup_wait(uint8_t id) "%d" -multifd_send(uint8_t id, uint64_t packet_num, uint32_t used, uint32_t flags, uint32_t next_packet_size) "channel %d packet_num %" PRIu64 " pages %d flags 0x%x next packet size %d" -multifd_send_error(uint8_t id) "channel %d" -multifd_send_sync_main(long packet_num) "packet num %ld" -multifd_send_sync_main_signal(uint8_t id) "channel %d" -multifd_send_sync_main_wait(uint8_t id) "channel %d" -multifd_send_terminate_threads(bool error) "error %d" -multifd_send_thread_end(uint8_t id, uint64_t packets, uint64_t pages) "channel %d packets %" PRIu64 " pages %" PRIu64 -multifd_send_thread_start(uint8_t id) "%d" ram_discard_range(const char *rbname, uint64_t start, size_t len) "%s: start: %" PRIx64 " %zx" ram_load_loop(const char *rbname, uint64_t addr, int flags, void *host) "%s: addr: 0x%" PRIx64 " flags: 0x%x host: %p" ram_load_postcopy_loop(uint64_t addr, int flags) "@%" PRIx64 " %x" @@ -129,6 +112,29 @@ save_xbzrle_page_overflow(void) "" ram_save_iterate_big_wait(uint64_t milliconds, int iterations) "big wait: %" PRIu64 " milliseconds, %d iterations" ram_load_complete(int ret, uint64_t seq_iter) "exit_code %d seq iteration %" PRIu64 +# multifd.c +multifd_new_send_channel_async(uint8_t id) "channel %d" +multifd_recv(uint8_t id, uint64_t packet_num, uint32_t used, uint32_t flags, uint32_t next_packet_size) "channel %d packet_num %" PRIu64 " pages %d flags 0x%x next packet size %d" +multifd_recv_new_channel(uint8_t id) "channel %d" +multifd_recv_sync_main(long packet_num) "packet num %ld" +multifd_recv_sync_main_signal(uint8_t id) "channel %d" +multifd_recv_sync_main_wait(uint8_t id) "channel %d" +multifd_recv_terminate_threads(bool error) "error %d" +multifd_recv_thread_end(uint8_t id, uint64_t packets, uint64_t pages) "channel %d packets %" PRIu64 " pages %" PRIu64 +multifd_recv_thread_start(uint8_t id) "%d" +multifd_send(uint8_t id, uint64_t packet_num, uint32_t used, uint32_t flags, uint32_t next_packet_size) "channel %d packet_num %" PRIu64 " pages %d flags 0x%x next packet size %d" +multifd_send_error(uint8_t id) "channel %d" +multifd_send_sync_main(long packet_num) "packet num %ld" +multifd_send_sync_main_signal(uint8_t id) "channel %d" +multifd_send_sync_main_wait(uint8_t id) "channel %d" +multifd_send_terminate_threads(bool error) "error %d" +multifd_send_thread_end(uint8_t id, uint64_t packets, uint64_t pages) "channel %d packets %" PRIu64 " pages %" PRIu64 +multifd_send_thread_start(uint8_t id) "%d" +multifd_tls_outgoing_handshake_start(void *ioc, void *tioc, const char *hostname) "ioc=%p tioc=%p hostname=%s" +multifd_tls_outgoing_handshake_error(void *ioc, const char *err) "ioc=%p err=%s" +multifd_tls_outgoing_handshake_complete(void *ioc) "ioc=%p" +multifd_set_outgoing_channel(void *ioc, const char *ioctype, const char *hostname, void *err) "ioc=%p ioctype=%s hostname=%s err=%p" + # migration.c await_return_path_close_on_source_close(void) "" await_return_path_close_on_source_joining(void) "" @@ -157,6 +163,7 @@ postcopy_pause_return_path(void) "" postcopy_pause_return_path_continued(void) "" postcopy_pause_continued(void) "" postcopy_start_set_run(void) "" +postcopy_page_req_add(void *addr, int count) "new page req %p total %d" source_return_path_thread_bad_end(void) "" source_return_path_thread_end(void) "" source_return_path_thread_entry(void) "" @@ -267,6 +274,7 @@ postcopy_ram_incoming_cleanup_blocktime(uint64_t total) "total blocktime %" PRIu postcopy_request_shared_page(const char *sharer, const char *rb, uint64_t rb_offset) "for %s in %s offset 0x%"PRIx64 postcopy_request_shared_page_present(const char *sharer, const char *rb, uint64_t rb_offset) "%s already %s offset 0x%"PRIx64 postcopy_wake_shared(uint64_t client_addr, const char *rb) "at 0x%"PRIx64" in %s" +postcopy_page_req_del(void *addr, int count) "resolved page req %p total %d" get_mem_fault_cpu_index(int cpu, uint32_t pid) "cpu: %d, pid: %u" @@ -312,3 +320,24 @@ dirty_bitmap_load_bits_zeroes(void) "" dirty_bitmap_load_header(uint32_t flags) "flags 0x%x" dirty_bitmap_load_enter(void) "" dirty_bitmap_load_success(void) "" + +# dirtyrate.c +dirtyrate_set_state(const char *new_state) "new state %s" +query_dirty_rate_info(const char *new_state) "current state %s" +get_ramblock_vfn_hash(const char *idstr, uint64_t vfn, uint32_t crc) "ramblock name: %s, vfn: %"PRIu64 ", crc: %" PRIu32 +calc_page_dirty_rate(const char *idstr, uint32_t new_crc, uint32_t old_crc) "ramblock name: %s, new crc: %" PRIu32 ", old crc: %" PRIu32 +skip_sample_ramblock(const char *idstr, uint64_t ramblock_size) "ramblock name: %s, ramblock size: %" PRIu64 +find_page_matched(const char *idstr) "ramblock %s addr or size changed" + +# block.c +migration_block_init_shared(const char *blk_device_name) "Start migration for %s with shared base image" +migration_block_init_full(const char *blk_device_name) "Start full migration for %s" +migration_block_save_device_dirty(int64_t sector) "Error reading sector %" PRId64 +migration_block_flush_blks(const char *action, int submitted, int read_done, int transferred) "%s submitted %d read_done %d transferred %d" +migration_block_save(const char *mig_stage, int submitted, int transferred) "Enter save live %s submitted %d transferred %d" +migration_block_save_complete(void) "Block migration completed" +migration_block_save_pending(uint64_t pending) "Enter save live pending %" PRIu64 + +# page_cache.c +migration_pagecache_init(int64_t max_num_items) "Setting cache buckets to %" PRId64 +migration_pagecache_insert(void) "Error allocating page" diff --git a/migration/trace.h b/migration/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..e1a0f4fb74bd60337d95937187bb29b2ec6e745f --- /dev/null +++ b/migration/trace.h @@ -0,0 +1 @@ +#include "trace/trace-migration.h" diff --git a/migration/vmstate-types.c b/migration/vmstate-types.c index 35e784c9d938f2120ddf04972dfcaeba151ec05d..e22d41d73d65b7e4b1be3b855643f364ff78fa09 100644 --- a/migration/vmstate-types.c +++ b/migration/vmstate-types.c @@ -420,32 +420,6 @@ const VMStateInfo vmstate_info_uint16_equal = { .put = put_uint16, }; -/* floating point */ - -static int get_float64(QEMUFile *f, void *pv, size_t size, - const VMStateField *field) -{ - float64 *v = pv; - - *v = make_float64(qemu_get_be64(f)); - return 0; -} - -static int put_float64(QEMUFile *f, void *pv, size_t size, - const VMStateField *field, QJSON *vmdesc) -{ - uint64_t *v = pv; - - qemu_put_be64(f, float64_val(*v)); - return 0; -} - -const VMStateInfo vmstate_info_float64 = { - .name = "float64", - .get = get_float64, - .put = put_float64, -}; - /* CPU_DoubleU type */ static int get_cpudouble(QEMUFile *f, void *pv, size_t size, diff --git a/migration/vmstate.c b/migration/vmstate.c index bafa890384317604824dc20c4e8efa97d230d874..e9d2aef66b70947c26218baedd942e4ccf135f3a 100644 --- a/migration/vmstate.c +++ b/migration/vmstate.c @@ -32,13 +32,13 @@ static int vmstate_n_elems(void *opaque, const VMStateField *field) if (field->flags & VMS_ARRAY) { n_elems = field->num; } else if (field->flags & VMS_VARRAY_INT32) { - n_elems = *(int32_t *)(opaque+field->num_offset); + n_elems = *(int32_t *)(opaque + field->num_offset); } else if (field->flags & VMS_VARRAY_UINT32) { - n_elems = *(uint32_t *)(opaque+field->num_offset); + n_elems = *(uint32_t *)(opaque + field->num_offset); } else if (field->flags & VMS_VARRAY_UINT16) { - n_elems = *(uint16_t *)(opaque+field->num_offset); + n_elems = *(uint16_t *)(opaque + field->num_offset); } else if (field->flags & VMS_VARRAY_UINT8) { - n_elems = *(uint8_t *)(opaque+field->num_offset); + n_elems = *(uint8_t *)(opaque + field->num_offset); } if (field->flags & VMS_MULTIPLY_ELEMENTS) { @@ -54,7 +54,7 @@ static int vmstate_size(void *opaque, const VMStateField *field) int size = field->size; if (field->flags & VMS_VBUFFER) { - size = *(int32_t *)(opaque+field->size_offset); + size = *(int32_t *)(opaque + field->size_offset); if (field->flags & VMS_MULTIPLY) { size *= field->size; } diff --git a/monitor/Makefile.objs b/monitor/Makefile.objs deleted file mode 100644 index a8533c9dd7d5613cdd9c635ccfcedc6921109fb8..0000000000000000000000000000000000000000 --- a/monitor/Makefile.objs +++ /dev/null @@ -1,6 +0,0 @@ -obj-y += misc.o -common-obj-y += monitor.o qmp.o hmp.o -common-obj-y += qmp-cmds.o qmp-cmds-control.o -common-obj-y += hmp-cmds.o - -storage-daemon-obj-y += monitor.o qmp.o qmp-cmds-control.o diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index 9c61e769ca9a4a74de2e7e918cd868698fefcda4..65d8ff48494be8eaa38df989b63dd0df6f4d84e1 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -24,6 +24,7 @@ #include "qemu/option.h" #include "qemu/timer.h" #include "qemu/sockets.h" +#include "qemu/help_option.h" #include "monitor/monitor-internal.h" #include "qapi/error.h" #include "qapi/clone-visitor.h" @@ -32,9 +33,11 @@ #include "qapi/qapi-commands-block.h" #include "qapi/qapi-commands-char.h" #include "qapi/qapi-commands-control.h" +#include "qapi/qapi-commands-machine.h" #include "qapi/qapi-commands-migration.h" #include "qapi/qapi-commands-misc.h" #include "qapi/qapi-commands-net.h" +#include "qapi/qapi-commands-pci.h" #include "qapi/qapi-commands-rocker.h" #include "qapi/qapi-commands-run-state.h" #include "qapi/qapi-commands-tpm.h" @@ -299,7 +302,7 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) info->xbzrle_cache->bytes >> 10); monitor_printf(mon, "xbzrle pages: %" PRIu64 " pages\n", info->xbzrle_cache->pages); - monitor_printf(mon, "xbzrle cache miss: %" PRIu64 "\n", + monitor_printf(mon, "xbzrle cache miss: %" PRIu64 " pages\n", info->xbzrle_cache->cache_miss); monitor_printf(mon, "xbzrle cache miss rate: %0.2f\n", info->xbzrle_cache->cache_miss_rate); @@ -316,8 +319,8 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) info->compression->busy); monitor_printf(mon, "compression busy rate: %0.2f\n", info->compression->busy_rate); - monitor_printf(mon, "compressed size: %" PRIu64 "\n", - info->compression->compressed_size); + monitor_printf(mon, "compressed size: %" PRIu64 " kbytes\n", + info->compression->compressed_size >> 10); monitor_printf(mon, "compression rate: %0.2f\n", info->compression->compression_rate); } @@ -355,6 +358,12 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) } monitor_printf(mon, "]\n"); } + + if (info->has_vfio) { + monitor_printf(mon, "vfio device transferred: %" PRIu64 " kbytes\n", + info->vfio->transferred >> 10); + } + qapi_free_MigrationInfo(info); } @@ -443,11 +452,11 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict) MigrationParameter_str(MIGRATION_PARAMETER_MAX_BANDWIDTH), params->max_bandwidth); assert(params->has_downtime_limit); - monitor_printf(mon, "%s: %" PRIu64 " milliseconds\n", + monitor_printf(mon, "%s: %" PRIu64 " ms\n", MigrationParameter_str(MIGRATION_PARAMETER_DOWNTIME_LIMIT), params->downtime_limit); assert(params->has_x_checkpoint_delay); - monitor_printf(mon, "%s: %u\n", + monitor_printf(mon, "%s: %u ms\n", MigrationParameter_str(MIGRATION_PARAMETER_X_CHECKPOINT_DELAY), params->x_checkpoint_delay); assert(params->has_block_incremental); @@ -460,7 +469,7 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict) monitor_printf(mon, "%s: %s\n", MigrationParameter_str(MIGRATION_PARAMETER_MULTIFD_COMPRESSION), MultiFDCompression_str(params->multifd_compression)); - monitor_printf(mon, "%s: %" PRIu64 "\n", + monitor_printf(mon, "%s: %" PRIu64 " bytes\n", MigrationParameter_str(MIGRATION_PARAMETER_XBZRLE_CACHE_SIZE), params->xbzrle_cache_size); monitor_printf(mon, "%s: %" PRIu64 "\n", @@ -469,6 +478,32 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict) monitor_printf(mon, "%s: '%s'\n", MigrationParameter_str(MIGRATION_PARAMETER_TLS_AUTHZ), params->tls_authz); + + if (params->has_block_bitmap_mapping) { + const BitmapMigrationNodeAliasList *bmnal; + + monitor_printf(mon, "%s:\n", + MigrationParameter_str( + MIGRATION_PARAMETER_BLOCK_BITMAP_MAPPING)); + + for (bmnal = params->block_bitmap_mapping; + bmnal; + bmnal = bmnal->next) + { + const BitmapMigrationNodeAlias *bmna = bmnal->value; + const BitmapMigrationBitmapAliasList *bmbal; + + monitor_printf(mon, " '%s' -> '%s'\n", + bmna->node_name, bmna->alias); + + for (bmbal = bmna->bitmaps; bmbal; bmbal = bmbal->next) { + const BitmapMigrationBitmapAlias *bmba = bmbal->value; + + monitor_printf(mon, " '%s' -> '%s'\n", + bmba->name, bmba->alias); + } + } + } } qapi_free_MigrationParameters(params); @@ -688,7 +723,8 @@ static void hmp_info_pci_device(Monitor *mon, const PciDeviceInfo *dev) } if (dev->has_irq) { - monitor_printf(mon, " IRQ %" PRId64 ".\n", dev->irq); + monitor_printf(mon, " IRQ %" PRId64 ", pin %c\n", + dev->irq, (char)('A' + dev->irq_pin - 1)); } if (dev->has_pci_bridge) { @@ -969,7 +1005,7 @@ void hmp_cpu(Monitor *mon, const QDict *qdict) /* XXX: drop the monitor_set_cpu() usage when all HMP commands that use it are converted to the QAPI */ cpu_index = qdict_get_int(qdict, "index"); - if (monitor_set_cpu(cpu_index) < 0) { + if (monitor_set_cpu(mon, cpu_index) < 0) { monitor_printf(mon, "invalid CPU index\n"); } } @@ -980,7 +1016,7 @@ void hmp_memsave(Monitor *mon, const QDict *qdict) const char *filename = qdict_get_str(qdict, "filename"); uint64_t addr = qdict_get_int(qdict, "val"); Error *err = NULL; - int cpu_index = monitor_get_cpu_index(); + int cpu_index = monitor_get_cpu_index(mon); if (cpu_index < 0) { monitor_printf(mon, "No CPU available\n"); @@ -1188,8 +1224,11 @@ void hmp_migrate_pause(Monitor *mon, const QDict *qdict) /* Kept for backwards compatibility */ void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict) { + Error *err = NULL; + double value = qdict_get_double(qdict, "value"); - qmp_migrate_set_downtime(value, NULL); + qmp_migrate_set_downtime(value, &err); + hmp_handle_error(mon, err); } void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict) @@ -1243,7 +1282,6 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) MigrateSetParameters *p = g_new0(MigrateSetParameters, 1); uint64_t valuebw = 0; uint64_t cache_size; - MultiFDCompression compress_type; Error *err = NULL; int val, ret; @@ -1339,11 +1377,8 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) break; case MIGRATION_PARAMETER_MULTIFD_COMPRESSION: p->has_multifd_compression = true; - visit_type_MultiFDCompression(v, param, &compress_type, &err); - if (err) { - break; - } - p->multifd_compression = compress_type; + visit_type_MultiFDCompression(v, param, &p->multifd_compression, + &err); break; case MIGRATION_PARAMETER_MULTIFD_ZLIB_LEVEL: p->has_multifd_zlib_level = true; @@ -1355,8 +1390,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) break; case MIGRATION_PARAMETER_XBZRLE_CACHE_SIZE: p->has_xbzrle_cache_size = true; - visit_type_size(v, param, &cache_size, &err); - if (err) { + if (!visit_type_size(v, param, &cache_size, &err)) { break; } if (cache_size > INT64_MAX || (size_t)cache_size != cache_size) { @@ -1385,6 +1419,10 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) p->has_announce_step = true; visit_type_size(v, param, &p->announce_step, &err); break; + case MIGRATION_PARAMETER_BLOCK_BITMAP_MAPPING: + error_setg(&err, "The block-bitmap-mapping parameter can only be set " + "through QMP"); + break; default: assert(0); } @@ -1498,8 +1536,7 @@ void hmp_change(Monitor *mon, const QDict *qdict) read_only, BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN, &err); if (err) { - hmp_handle_error(mon, err); - return; + goto end; } } @@ -1508,6 +1545,7 @@ void hmp_change(Monitor *mon, const QDict *qdict) &err); } +end: hmp_handle_error(mon, err); } @@ -1594,7 +1632,12 @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict) { Error *err = NULL; QemuOpts *opts; + const char *type = qdict_get_try_str(qdict, "type"); + if (type && is_help_option(type)) { + show_netdevs(); + return; + } opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &err); if (err) { goto out; @@ -1626,16 +1669,15 @@ void hmp_object_add(Monitor *mon, const QDict *qdict) opts = qemu_opts_from_qdict(qemu_find_opts("object"), qdict, &err); if (err) { - hmp_handle_error(mon, err); - return; + goto end; } obj = user_creatable_add_opts(opts, &err); qemu_opts_del(opts); - if (err) { - hmp_handle_error(mon, err); - } +end: + hmp_handle_error(mon, err); + if (obj) { object_unref(obj); } @@ -1726,7 +1768,8 @@ err_out: goto out; } -void hmp_screendump(Monitor *mon, const QDict *qdict) +void coroutine_fn +hmp_screendump(Monitor *mon, const QDict *qdict) { const char *filename = qdict_get_str(qdict, "filename"); const char *id = qdict_get_try_str(qdict, "device"); @@ -1818,6 +1861,7 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict) MemoryDeviceInfoList *info_list = qmp_query_memory_devices(&err); MemoryDeviceInfoList *info; VirtioPMEMDeviceInfo *vpi; + VirtioMEMDeviceInfo *vmi; MemoryDeviceInfo *value; PCDIMMDeviceInfo *di; @@ -1852,6 +1896,21 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict) monitor_printf(mon, " size: %" PRIu64 "\n", vpi->size); monitor_printf(mon, " memdev: %s\n", vpi->memdev); break; + case MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM: + vmi = value->u.virtio_mem.data; + monitor_printf(mon, "Memory device [%s]: \"%s\"\n", + MemoryDeviceInfoKind_str(value->type), + vmi->id ? vmi->id : ""); + monitor_printf(mon, " memaddr: 0x%" PRIx64 "\n", vmi->memaddr); + monitor_printf(mon, " node: %" PRId64 "\n", vmi->node); + monitor_printf(mon, " requested-size: %" PRIu64 "\n", + vmi->requested_size); + monitor_printf(mon, " size: %" PRIu64 "\n", vmi->size); + monitor_printf(mon, " max-size: %" PRIu64 "\n", vmi->max_size); + monitor_printf(mon, " block-size: %" PRIu64 "\n", + vmi->block_size); + monitor_printf(mon, " memdev: %s\n", vmi->memdev); + break; default: g_assert_not_reached(); } diff --git a/monitor/hmp.c b/monitor/hmp.c index d598dd02bb0bd7d2bafee0e2617da6b874d0d30e..1204233999fbdfb020cf0669dcb56cf8fc601d76 100644 --- a/monitor/hmp.c +++ b/monitor/hmp.c @@ -384,7 +384,7 @@ static int64_t expr_unary(Monitor *mon) pch++; } *q = 0; - ret = get_monitor_def(®, buf); + ret = get_monitor_def(mon, ®, buf); if (ret < 0) { expr_error(mon, "unknown register"); } @@ -1056,6 +1056,21 @@ fail: return NULL; } +typedef struct HandleHmpCommandCo { + Monitor *mon; + const HMPCommand *cmd; + QDict *qdict; + bool done; +} HandleHmpCommandCo; + +static void handle_hmp_command_co(void *opaque) +{ + HandleHmpCommandCo *data = opaque; + data->cmd->cmd(data->mon, data->qdict); + monitor_set_cur(qemu_coroutine_self(), NULL); + data->done = true; +} + void handle_hmp_command(MonitorHMP *mon, const char *cmdline) { QDict *qdict; @@ -1079,7 +1094,24 @@ void handle_hmp_command(MonitorHMP *mon, const char *cmdline) return; } - cmd->cmd(&mon->common, qdict); + if (!cmd->coroutine) { + /* old_mon is non-NULL when called from qmp_human_monitor_command() */ + Monitor *old_mon = monitor_set_cur(qemu_coroutine_self(), &mon->common); + cmd->cmd(&mon->common, qdict); + monitor_set_cur(qemu_coroutine_self(), old_mon); + } else { + HandleHmpCommandCo data = { + .mon = &mon->common, + .cmd = cmd, + .qdict = qdict, + .done = false, + }; + Coroutine *co = qemu_coroutine_create(handle_hmp_command_co, &data); + monitor_set_cur(co, &mon->common); + aio_co_enter(qemu_get_aio_context(), co); + AIO_WAIT_WHILE(qemu_get_aio_context(), !data.done); + } + qobject_unref(qdict); } @@ -1300,26 +1332,20 @@ cleanup: static void monitor_read(void *opaque, const uint8_t *buf, int size) { - MonitorHMP *mon; - Monitor *old_mon = cur_mon; + MonitorHMP *mon = container_of(opaque, MonitorHMP, common); int i; - cur_mon = opaque; - mon = container_of(cur_mon, MonitorHMP, common); - if (mon->rs) { for (i = 0; i < size; i++) { readline_handle_byte(mon->rs, buf[i]); } } else { if (size == 0 || buf[size - 1] != 0) { - monitor_printf(cur_mon, "corrupted command\n"); + monitor_printf(&mon->common, "corrupted command\n"); } else { handle_hmp_command(mon, (char *)buf); } } - - cur_mon = old_mon; } static void monitor_event(void *opaque, QEMUChrEvent event) @@ -1337,19 +1363,19 @@ static void monitor_event(void *opaque, QEMUChrEvent event) monitor_resume(mon); monitor_flush(mon); } else { - atomic_mb_set(&mon->suspend_cnt, 0); + qatomic_mb_set(&mon->suspend_cnt, 0); } break; case CHR_EVENT_MUX_OUT: if (mon->reset_seen) { - if (atomic_mb_read(&mon->suspend_cnt) == 0) { + if (qatomic_mb_read(&mon->suspend_cnt) == 0) { monitor_printf(mon, "\n"); } monitor_flush(mon); monitor_suspend(mon); } else { - atomic_inc(&mon->suspend_cnt); + qatomic_inc(&mon->suspend_cnt); } qemu_mutex_lock(&mon->mon_lock); mon->mux_out = 1; diff --git a/monitor/meson.build b/monitor/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..6d00985ace7a4456d4214199f112d45107b06f38 --- /dev/null +++ b/monitor/meson.build @@ -0,0 +1,9 @@ +qmp_ss.add(files('monitor.c', 'qmp.c', 'qmp-cmds-control.c')) + +softmmu_ss.add(files( + 'hmp-cmds.c', + 'hmp.c', +)) +softmmu_ss.add([spice_headers, files('qmp-cmds.c')]) + +specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files('misc.c'), spice]) diff --git a/monitor/misc.c b/monitor/misc.c index f5207cd24284cb7b752ee01bdca7a8b8563c5ff2..398211a03404fcacf682017ebf2c03c199a17a1e 100644 --- a/monitor/misc.c +++ b/monitor/misc.c @@ -33,7 +33,6 @@ #include "exec/gdbstub.h" #include "net/net.h" #include "net/slirp.h" -#include "chardev/char-mux.h" #include "ui/qemu-spice.h" #include "qemu/config-file.h" #include "qemu/ctype.h" @@ -121,18 +120,13 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index, int64_t cpu_index, Error **errp) { char *output = NULL; - Monitor *old_mon; MonitorHMP hmp = {}; monitor_data_init(&hmp.common, false, true, false); - old_mon = cur_mon; - cur_mon = &hmp.common; - if (has_cpu_index) { - int ret = monitor_set_cpu(cpu_index); + int ret = monitor_set_cpu(&hmp.common, cpu_index); if (ret < 0) { - cur_mon = old_mon; error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index", "a CPU number"); goto out; @@ -140,15 +134,14 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index, } handle_hmp_command(&hmp, command_line); - cur_mon = old_mon; - qemu_mutex_lock(&hmp.common.mon_lock); - if (qstring_get_length(hmp.common.outbuf) > 0) { - output = g_strdup(qstring_get_str(hmp.common.outbuf)); - } else { - output = g_strdup(""); + WITH_QEMU_LOCK_GUARD(&hmp.common.mon_lock) { + if (qstring_get_length(hmp.common.outbuf) > 0) { + output = g_strdup(qstring_get_str(hmp.common.outbuf)); + } else { + output = g_strdup(""); + } } - qemu_mutex_unlock(&hmp.common.mon_lock); out: monitor_data_destroy(&hmp.common); @@ -256,7 +249,7 @@ static void monitor_init_qmp_commands(void) } /* Set the current CPU defined by the user. Callers must hold BQL. */ -int monitor_set_cpu(int cpu_index) +int monitor_set_cpu(Monitor *mon, int cpu_index) { CPUState *cpu; @@ -264,29 +257,29 @@ int monitor_set_cpu(int cpu_index) if (cpu == NULL) { return -1; } - g_free(cur_mon->mon_cpu_path); - cur_mon->mon_cpu_path = object_get_canonical_path(OBJECT(cpu)); + g_free(mon->mon_cpu_path); + mon->mon_cpu_path = object_get_canonical_path(OBJECT(cpu)); return 0; } /* Callers must hold BQL. */ -static CPUState *mon_get_cpu_sync(bool synchronize) +static CPUState *mon_get_cpu_sync(Monitor *mon, bool synchronize) { CPUState *cpu = NULL; - if (cur_mon->mon_cpu_path) { - cpu = (CPUState *) object_resolve_path_type(cur_mon->mon_cpu_path, + if (mon->mon_cpu_path) { + cpu = (CPUState *) object_resolve_path_type(mon->mon_cpu_path, TYPE_CPU, NULL); if (!cpu) { - g_free(cur_mon->mon_cpu_path); - cur_mon->mon_cpu_path = NULL; + g_free(mon->mon_cpu_path); + mon->mon_cpu_path = NULL; } } - if (!cur_mon->mon_cpu_path) { + if (!mon->mon_cpu_path) { if (!first_cpu) { return NULL; } - monitor_set_cpu(first_cpu->cpu_index); + monitor_set_cpu(mon, first_cpu->cpu_index); cpu = first_cpu; } assert(cpu != NULL); @@ -296,21 +289,21 @@ static CPUState *mon_get_cpu_sync(bool synchronize) return cpu; } -CPUState *mon_get_cpu(void) +CPUState *mon_get_cpu(Monitor *mon) { - return mon_get_cpu_sync(true); + return mon_get_cpu_sync(mon, true); } -CPUArchState *mon_get_cpu_env(void) +CPUArchState *mon_get_cpu_env(Monitor *mon) { - CPUState *cs = mon_get_cpu(); + CPUState *cs = mon_get_cpu(mon); return cs ? cs->env_ptr : NULL; } -int monitor_get_cpu_index(void) +int monitor_get_cpu_index(Monitor *mon) { - CPUState *cs = mon_get_cpu_sync(false); + CPUState *cs = mon_get_cpu_sync(mon, false); return cs ? cs->cpu_index : UNASSIGNED_CPU_INDEX; } @@ -326,7 +319,7 @@ static void hmp_info_registers(Monitor *mon, const QDict *qdict) cpu_dump_state(cs, NULL, CPU_DUMP_FPU); } } else { - cs = mon_get_cpu(); + cs = mon_get_cpu(mon); if (!cs) { monitor_printf(mon, "No CPU available\n"); @@ -388,7 +381,7 @@ static void hmp_info_history(Monitor *mon, const QDict *qdict) static void hmp_info_cpustats(Monitor *mon, const QDict *qdict) { - CPUState *cs = mon_get_cpu(); + CPUState *cs = mon_get_cpu(mon); if (!cs) { monitor_printf(mon, "No CPU available\n"); @@ -444,7 +437,7 @@ void qmp_client_migrate_info(const char *protocol, const char *hostname, return; } - if (qemu_spice_migrate_info(hostname, + if (qemu_spice.migrate_info(hostname, has_port ? port : -1, has_tls_port ? tls_port : -1, cert_subject)) { @@ -553,7 +546,7 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize, int l, line_size, i, max_digits, len; uint8_t buf[16]; uint64_t v; - CPUState *cs = mon_get_cpu(); + CPUState *cs = mon_get_cpu(mon); if (!cs && (format == 'i' || !is_physical)) { monitor_printf(mon, "Can not dump without CPU\n"); @@ -718,7 +711,7 @@ static void hmp_gva2gpa(Monitor *mon, const QDict *qdict) { target_ulong addr = qdict_get_int(qdict, "addr"); MemTxAttrs attrs; - CPUState *cs = mon_get_cpu(); + CPUState *cs = mon_get_cpu(mon); hwaddr gpa; if (!cs) { @@ -752,7 +745,7 @@ static uint64_t vtop(void *ptr, Error **errp) } /* Force copy-on-write if necessary. */ - atomic_add((uint8_t *)ptr, 0); + qatomic_add((uint8_t *)ptr, 0); if (pread(fd, &pinfo, sizeof(pinfo), offset) != sizeof(pinfo)) { error_setg_errno(errp, errno, "Cannot read pagemap"); @@ -957,8 +950,9 @@ static void hmp_info_mtree(Monitor *mon, const QDict *qdict) bool flatview = qdict_get_try_bool(qdict, "flatview", false); bool dispatch_tree = qdict_get_try_bool(qdict, "dispatch_tree", false); bool owner = qdict_get_try_bool(qdict, "owner", false); + bool disabled = qdict_get_try_bool(qdict, "disabled", false); - mtree_info(flatview, dispatch_tree, owner); + mtree_info(flatview, dispatch_tree, owner, disabled); } #ifdef CONFIG_PROFILER @@ -1232,6 +1226,7 @@ static void hmp_acl_remove(Monitor *mon, const QDict *qdict) void qmp_getfd(const char *fdname, Error **errp) { + Monitor *cur_mon = monitor_cur(); mon_fd_t *monfd; int fd, tmp_fd; @@ -1248,7 +1243,7 @@ void qmp_getfd(const char *fdname, Error **errp) return; } - qemu_mutex_lock(&cur_mon->mon_lock); + QEMU_LOCK_GUARD(&cur_mon->mon_lock); QLIST_FOREACH(monfd, &cur_mon->fds, next) { if (strcmp(monfd->name, fdname) != 0) { continue; @@ -1256,7 +1251,6 @@ void qmp_getfd(const char *fdname, Error **errp) tmp_fd = monfd->fd; monfd->fd = fd; - qemu_mutex_unlock(&cur_mon->mon_lock); /* Make sure close() is outside critical section */ close(tmp_fd); return; @@ -1267,11 +1261,11 @@ void qmp_getfd(const char *fdname, Error **errp) monfd->fd = fd; QLIST_INSERT_HEAD(&cur_mon->fds, monfd, next); - qemu_mutex_unlock(&cur_mon->mon_lock); } void qmp_closefd(const char *fdname, Error **errp) { + Monitor *cur_mon = monitor_cur(); mon_fd_t *monfd; int tmp_fd; @@ -1299,7 +1293,7 @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp) { mon_fd_t *monfd; - qemu_mutex_lock(&mon->mon_lock); + QEMU_LOCK_GUARD(&mon->mon_lock); QLIST_FOREACH(monfd, &mon->fds, next) { int fd; @@ -1313,12 +1307,10 @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp) QLIST_REMOVE(monfd, next); g_free(monfd->name); g_free(monfd); - qemu_mutex_unlock(&mon->mon_lock); return fd; } - qemu_mutex_unlock(&mon->mon_lock); error_setg(errp, "File descriptor named '%s' has not been found", fdname); return -1; } @@ -1350,18 +1342,17 @@ void monitor_fdsets_cleanup(void) MonFdset *mon_fdset; MonFdset *mon_fdset_next; - qemu_mutex_lock(&mon_fdsets_lock); + QEMU_LOCK_GUARD(&mon_fdsets_lock); QLIST_FOREACH_SAFE(mon_fdset, &mon_fdsets, next, mon_fdset_next) { monitor_fdset_cleanup(mon_fdset); } - qemu_mutex_unlock(&mon_fdsets_lock); } AddfdInfo *qmp_add_fd(bool has_fdset_id, int64_t fdset_id, bool has_opaque, const char *opaque, Error **errp) { int fd; - Monitor *mon = cur_mon; + Monitor *mon = monitor_cur(); AddfdInfo *fdinfo; fd = qemu_chr_fe_get_msgfd(&mon->chr); @@ -1389,7 +1380,7 @@ void qmp_remove_fd(int64_t fdset_id, bool has_fd, int64_t fd, Error **errp) MonFdsetFd *mon_fdset_fd; char fd_str[60]; - qemu_mutex_lock(&mon_fdsets_lock); + QEMU_LOCK_GUARD(&mon_fdsets_lock); QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { if (mon_fdset->id != fdset_id) { continue; @@ -1409,12 +1400,10 @@ void qmp_remove_fd(int64_t fdset_id, bool has_fd, int64_t fd, Error **errp) goto error; } monitor_fdset_cleanup(mon_fdset); - qemu_mutex_unlock(&mon_fdsets_lock); return; } error: - qemu_mutex_unlock(&mon_fdsets_lock); if (has_fd) { snprintf(fd_str, sizeof(fd_str), "fdset-id:%" PRId64 ", fd:%" PRId64, fdset_id, fd); @@ -1430,7 +1419,7 @@ FdsetInfoList *qmp_query_fdsets(Error **errp) MonFdsetFd *mon_fdset_fd; FdsetInfoList *fdset_list = NULL; - qemu_mutex_lock(&mon_fdsets_lock); + QEMU_LOCK_GUARD(&mon_fdsets_lock); QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { FdsetInfoList *fdset_info = g_malloc0(sizeof(*fdset_info)); FdsetFdInfoList *fdsetfd_list = NULL; @@ -1460,7 +1449,6 @@ FdsetInfoList *qmp_query_fdsets(Error **errp) fdset_info->next = fdset_list; fdset_list = fdset_info; } - qemu_mutex_unlock(&mon_fdsets_lock); return fdset_list; } @@ -1547,69 +1535,56 @@ AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id, return fdinfo; } -int monitor_fdset_get_fd(int64_t fdset_id, int flags) +int monitor_fdset_dup_fd_add(int64_t fdset_id, int flags) { #ifdef _WIN32 return -ENOENT; #else MonFdset *mon_fdset; - MonFdsetFd *mon_fdset_fd; - int mon_fd_flags; - int ret; - qemu_mutex_lock(&mon_fdsets_lock); + QEMU_LOCK_GUARD(&mon_fdsets_lock); QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { + MonFdsetFd *mon_fdset_fd; + MonFdsetFd *mon_fdset_fd_dup; + int fd = -1; + int dup_fd; + int mon_fd_flags; + if (mon_fdset->id != fdset_id) { continue; } + QLIST_FOREACH(mon_fdset_fd, &mon_fdset->fds, next) { mon_fd_flags = fcntl(mon_fdset_fd->fd, F_GETFL); if (mon_fd_flags == -1) { - ret = -errno; - goto out; + return -1; } if ((flags & O_ACCMODE) == (mon_fd_flags & O_ACCMODE)) { - ret = mon_fdset_fd->fd; - goto out; + fd = mon_fdset_fd->fd; + break; } } - ret = -EACCES; - goto out; - } - ret = -ENOENT; -out: - qemu_mutex_unlock(&mon_fdsets_lock); - return ret; -#endif -} - -int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd) -{ - MonFdset *mon_fdset; - MonFdsetFd *mon_fdset_fd_dup; - - qemu_mutex_lock(&mon_fdsets_lock); - QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { - if (mon_fdset->id != fdset_id) { - continue; + if (fd == -1) { + errno = EACCES; + return -1; } - QLIST_FOREACH(mon_fdset_fd_dup, &mon_fdset->dup_fds, next) { - if (mon_fdset_fd_dup->fd == dup_fd) { - goto err; - } + + dup_fd = qemu_dup_flags(fd, flags); + if (dup_fd == -1) { + return -1; } + mon_fdset_fd_dup = g_malloc0(sizeof(*mon_fdset_fd_dup)); mon_fdset_fd_dup->fd = dup_fd; QLIST_INSERT_HEAD(&mon_fdset->dup_fds, mon_fdset_fd_dup, next); - qemu_mutex_unlock(&mon_fdsets_lock); - return 0; + return dup_fd; } -err: - qemu_mutex_unlock(&mon_fdsets_lock); + errno = ENOENT; return -1; +#endif } static int64_t monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove) @@ -1617,7 +1592,7 @@ static int64_t monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove) MonFdset *mon_fdset; MonFdsetFd *mon_fdset_fd_dup; - qemu_mutex_lock(&mon_fdsets_lock); + QEMU_LOCK_GUARD(&mon_fdsets_lock); QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { QLIST_FOREACH(mon_fdset_fd_dup, &mon_fdset->dup_fds, next) { if (mon_fdset_fd_dup->fd == dup_fd) { @@ -1627,17 +1602,14 @@ static int64_t monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove) if (QLIST_EMPTY(&mon_fdset->dup_fds)) { monitor_fdset_cleanup(mon_fdset); } - goto err; + return -1; } else { - qemu_mutex_unlock(&mon_fdsets_lock); return mon_fdset->id; } } } } -err: - qemu_mutex_unlock(&mon_fdsets_lock); return -1; } @@ -1691,10 +1663,10 @@ HMPCommand hmp_cmds[] = { * Set @pval to the value in the register identified by @name. * return 0 if OK, -1 if not found */ -int get_monitor_def(int64_t *pval, const char *name) +int get_monitor_def(Monitor *mon, int64_t *pval, const char *name) { const MonitorDef *md = target_monitor_defs(); - CPUState *cs = mon_get_cpu(); + CPUState *cs = mon_get_cpu(mon); void *ptr; uint64_t tmp = 0; int ret; @@ -1706,9 +1678,9 @@ int get_monitor_def(int64_t *pval, const char *name) for(; md->name != NULL; md++) { if (hmp_compare_cmd(name, md->name)) { if (md->get_value) { - *pval = md->get_value(md, md->offset); + *pval = md->get_value(mon, md, md->offset); } else { - CPUArchState *env = mon_get_cpu_env(); + CPUArchState *env = mon_get_cpu_env(mon); ptr = (uint8_t *)env + md->offset; switch(md->type) { case MD_I32: diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h index b39e03b744ecd3c936e89e7f1f21f4fd2dd5948c..a6131554da37cb49170fb9778e94337207e8cb93 100644 --- a/monitor/monitor-internal.h +++ b/monitor/monitor-internal.h @@ -74,6 +74,7 @@ typedef struct HMPCommand { const char *help; const char *flags; /* p=preconfig */ void (*cmd)(Monitor *mon, const QDict *qdict); + bool coroutine; /* * @sub_table is a list of 2nd level of commands. If it does not exist, * cmd should be used. If it exists, sub_table[?].cmd should be @@ -155,7 +156,9 @@ static inline bool monitor_is_qmp(const Monitor *mon) typedef QTAILQ_HEAD(MonitorList, Monitor) MonitorList; extern IOThread *mon_iothread; -extern QEMUBH *qmp_dispatcher_bh; +extern Coroutine *qmp_dispatcher_co; +extern bool qmp_dispatcher_co_shutdown; +extern bool qmp_dispatcher_co_busy; extern QmpCommandList qmp_commands, qmp_cap_negotiation_commands; extern QemuMutex monitor_lock; extern MonitorList mon_list; @@ -173,9 +176,9 @@ void monitor_fdsets_cleanup(void); void qmp_send_response(MonitorQMP *mon, const QDict *rsp); void monitor_data_destroy_qmp(MonitorQMP *mon); -void monitor_qmp_bh_dispatcher(void *data); +void coroutine_fn monitor_qmp_dispatcher_co(void *data); -int get_monitor_def(int64_t *pval, const char *name); +int get_monitor_def(Monitor *mon, int64_t *pval, const char *name); void help_cmd(Monitor *mon, const char *name); void handle_hmp_command(MonitorHMP *mon, const char *cmdline); int hmp_compare_cmd(const char *name, const char *list); diff --git a/monitor/monitor.c b/monitor/monitor.c index 125494410ad64e2f9792e3be7b16d356c4fdda10..84222cd130043fd618bd403438296ef997ef25e0 100644 --- a/monitor/monitor.c +++ b/monitor/monitor.c @@ -55,24 +55,85 @@ typedef struct { /* Shared monitor I/O thread */ IOThread *mon_iothread; -/* Bottom half to dispatch the requests received from I/O thread */ -QEMUBH *qmp_dispatcher_bh; +/* Coroutine to dispatch the requests received from I/O thread */ +Coroutine *qmp_dispatcher_co; -/* Protects mon_list, monitor_qapi_event_state, monitor_destroyed. */ +/* Set to true when the dispatcher coroutine should terminate */ +bool qmp_dispatcher_co_shutdown; + +/* + * qmp_dispatcher_co_busy is used for synchronisation between the + * monitor thread and the main thread to ensure that the dispatcher + * coroutine never gets scheduled a second time when it's already + * scheduled (scheduling the same coroutine twice is forbidden). + * + * It is true if the coroutine is active and processing requests. + * Additional requests may then be pushed onto mon->qmp_requests, + * and @qmp_dispatcher_co_shutdown may be set without further ado. + * @qmp_dispatcher_co_busy must not be woken up in this case. + * + * If false, you also have to set @qmp_dispatcher_co_busy to true and + * wake up @qmp_dispatcher_co after pushing the new requests. + * + * The coroutine will automatically change this variable back to false + * before it yields. Nobody else may set the variable to false. + * + * Access must be atomic for thread safety. + */ +bool qmp_dispatcher_co_busy; + +/* + * Protects mon_list, monitor_qapi_event_state, coroutine_mon, + * monitor_destroyed. + */ QemuMutex monitor_lock; static GHashTable *monitor_qapi_event_state; +static GHashTable *coroutine_mon; /* Maps Coroutine* to Monitor* */ MonitorList mon_list; int mon_refcount; static bool monitor_destroyed; -__thread Monitor *cur_mon; +Monitor *monitor_cur(void) +{ + Monitor *mon; + + qemu_mutex_lock(&monitor_lock); + mon = g_hash_table_lookup(coroutine_mon, qemu_coroutine_self()); + qemu_mutex_unlock(&monitor_lock); + + return mon; +} + +/** + * Sets a new current monitor and returns the old one. + * + * If a non-NULL monitor is set for a coroutine, another call + * resetting it to NULL is required before the coroutine terminates, + * otherwise a stale entry would remain in the hash table. + */ +Monitor *monitor_set_cur(Coroutine *co, Monitor *mon) +{ + Monitor *old_monitor = monitor_cur(); + + qemu_mutex_lock(&monitor_lock); + if (mon) { + g_hash_table_replace(coroutine_mon, co, mon); + } else { + g_hash_table_remove(coroutine_mon, co); + } + qemu_mutex_unlock(&monitor_lock); + + return old_monitor; +} /** * Is the current monitor, if any, a QMP monitor? */ bool monitor_cur_is_qmp(void) { + Monitor *cur_mon = monitor_cur(); + return cur_mon && monitor_is_qmp(cur_mon); } @@ -209,6 +270,8 @@ int monitor_printf(Monitor *mon, const char *fmt, ...) */ int error_vprintf(const char *fmt, va_list ap) { + Monitor *cur_mon = monitor_cur(); + if (cur_mon && !monitor_cur_is_qmp()) { return monitor_vprintf(cur_mon, fmt, ap); } @@ -217,6 +280,8 @@ int error_vprintf(const char *fmt, va_list ap) int error_vprintf_unless_qmp(const char *fmt, va_list ap) { + Monitor *cur_mon = monitor_cur(); + if (!cur_mon) { return vfprintf(stderr, fmt, ap); } @@ -235,6 +300,7 @@ static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] = { [QAPI_EVENT_QUORUM_REPORT_BAD] = { 1000 * SCALE_MS }, [QAPI_EVENT_QUORUM_FAILURE] = { 1000 * SCALE_MS }, [QAPI_EVENT_VSERPORT_CHANGE] = { 1000 * SCALE_MS }, + [QAPI_EVENT_MEMORY_DEVICE_SIZE_CHANGE] = { 1000 * SCALE_MS }, }; /* @@ -448,7 +514,7 @@ int monitor_suspend(Monitor *mon) return -ENOTTY; } - atomic_inc(&mon->suspend_cnt); + qatomic_inc(&mon->suspend_cnt); if (mon->use_io_thread) { /* @@ -475,7 +541,7 @@ void monitor_resume(Monitor *mon) return; } - if (atomic_dec_fetch(&mon->suspend_cnt) == 0) { + if (qatomic_dec_fetch(&mon->suspend_cnt) == 0) { AioContext *ctx; if (mon->use_io_thread) { @@ -500,7 +566,7 @@ int monitor_can_read(void *opaque) { Monitor *mon = opaque; - return !atomic_mb_read(&mon->suspend_cnt); + return !qatomic_mb_read(&mon->suspend_cnt); } void monitor_list_append(Monitor *mon) @@ -566,6 +632,25 @@ void monitor_cleanup(void) iothread_stop(mon_iothread); } + /* + * The dispatcher needs to stop before destroying the monitor and + * the I/O thread. + * + * We need to poll both qemu_aio_context and iohandler_ctx to make + * sure that the dispatcher coroutine keeps making progress and + * eventually terminates. qemu_aio_context is automatically + * polled by calling AIO_WAIT_WHILE on it, but we must poll + * iohandler_ctx manually. + */ + qmp_dispatcher_co_shutdown = true; + if (!qatomic_xchg(&qmp_dispatcher_co_busy, true)) { + aio_co_wake(qmp_dispatcher_co); + } + + AIO_WAIT_WHILE(qemu_get_aio_context(), + (aio_poll(iohandler_get_aio_context(), false), + qatomic_mb_read(&qmp_dispatcher_co_busy))); + /* Flush output buffers and destroy monitors */ qemu_mutex_lock(&monitor_lock); monitor_destroyed = true; @@ -581,9 +666,6 @@ void monitor_cleanup(void) } qemu_mutex_unlock(&monitor_lock); - /* QEMUBHs needs to be deleted before destroying the I/O thread */ - qemu_bh_delete(qmp_dispatcher_bh); - qmp_dispatcher_bh = NULL; if (mon_iothread) { iothread_destroy(mon_iothread); mon_iothread = NULL; @@ -600,15 +682,16 @@ void monitor_init_globals_core(void) { monitor_qapi_event_init(); qemu_mutex_init(&monitor_lock); + coroutine_mon = g_hash_table_new(NULL, NULL); /* * The dispatcher BH must run in the main loop thread, since we * have commands assuming that context. It would be nice to get * rid of those assumptions. */ - qmp_dispatcher_bh = aio_bh_new(iohandler_get_aio_context(), - monitor_qmp_bh_dispatcher, - NULL); + qmp_dispatcher_co = qemu_coroutine_create(monitor_qmp_dispatcher_co, NULL); + qatomic_mb_set(&qmp_dispatcher_co_busy, true); + aio_co_schedule(iohandler_get_aio_context(), qmp_dispatcher_co); } int monitor_init(MonitorOptions *opts, bool allow_hmp, Error **errp) @@ -656,25 +739,18 @@ int monitor_init_opts(QemuOpts *opts, Error **errp) { Visitor *v; MonitorOptions *options; - Error *local_err = NULL; + int ret; v = opts_visitor_new(opts); - visit_type_MonitorOptions(v, NULL, &options, &local_err); + visit_type_MonitorOptions(v, NULL, &options, errp); visit_free(v); - - if (local_err) { - goto out; + if (!options) { + return -1; } - monitor_init(options, true, &local_err); + ret = monitor_init(options, true, errp); qapi_free_MonitorOptions(options); - -out: - if (local_err) { - error_propagate(errp, local_err); - return -1; - } - return 0; + return ret; } QemuOptsList qemu_mon_opts = { diff --git a/monitor/qmp-cmds-control.c b/monitor/qmp-cmds-control.c index 8f04cfa6e6f50783ba4bb0d0d9e5882b1deb3404..a456762f6a840c9e733a8dc51aa1ea7771b652a4 100644 --- a/monitor/qmp-cmds-control.c +++ b/monitor/qmp-cmds-control.c @@ -69,6 +69,7 @@ static bool qmp_caps_accept(MonitorQMP *mon, QMPCapabilityList *list, void qmp_qmp_capabilities(bool has_enable, QMPCapabilityList *enable, Error **errp) { + Monitor *cur_mon = monitor_cur(); MonitorQMP *mon; assert(monitor_is_qmp(cur_mon)); @@ -119,6 +120,7 @@ static void query_commands_cb(const QmpCommand *cmd, void *opaque) CommandInfoList *qmp_query_commands(Error **errp) { CommandInfoList *list = NULL; + Monitor *cur_mon = monitor_cur(); MonitorQMP *mon; assert(monitor_is_qmp(cur_mon)); diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c index 864cbfa32e6bcfaae37057c1f36a542abe4f860f..a08143b32335b602f89d77de2a89b2e1651895d5 100644 --- a/monitor/qmp-cmds.c +++ b/monitor/qmp-cmds.c @@ -30,6 +30,7 @@ #include "sysemu/blockdev.h" #include "sysemu/block-backend.h" #include "qapi/error.h" +#include "qapi/qapi-commands-acpi.h" #include "qapi/qapi-commands-block.h" #include "qapi/qapi-commands-control.h" #include "qapi/qapi-commands-machine.h" @@ -196,7 +197,7 @@ void qmp_set_password(const char *protocol, const char *password, if (!qemu_using_spice(errp)) { return; } - rc = qemu_spice_set_passwd(password, fail_if_connected, + rc = qemu_spice.set_passwd(password, fail_if_connected, disconnect_if_connected); if (rc != 0) { error_setg(errp, QERR_SET_PASSWD_FAILED); @@ -242,7 +243,7 @@ void qmp_expire_password(const char *protocol, const char *whenstr, if (!qemu_using_spice(errp)) { return; } - rc = qemu_spice_set_pw_expire(when); + rc = qemu_spice.set_pw_expire(when); if (rc != 0) { error_setg(errp, QERR_SET_PASSWD_FAILED); } @@ -327,7 +328,7 @@ void qmp_add_client(const char *protocol, const char *fdname, Chardev *s; int fd; - fd = monitor_get_fd(cur_mon, fdname, errp); + fd = monitor_get_fd(monitor_cur(), fdname, errp); if (fd < 0) { return; } @@ -339,7 +340,7 @@ void qmp_add_client(const char *protocol, const char *fdname, } skipauth = has_skipauth ? skipauth : false; tls = has_tls ? tls : false; - if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) { + if (qemu_spice.display_add_client(fd, skipauth, tls) < 0) { error_setg(errp, "spice failed to add client"); close(fd); } diff --git a/monitor/qmp.c b/monitor/qmp.c index d433ceae5b1952430fa8a1995ea42cd704d724bf..b42f8c6af3759d909d1e9570bc7a784453cb337d 100644 --- a/monitor/qmp.c +++ b/monitor/qmp.c @@ -133,18 +133,17 @@ static void monitor_qmp_respond(MonitorQMP *mon, QDict *rsp) } } +/* + * Runs outside of coroutine context for OOB commands, but in + * coroutine context for everything else. + */ static void monitor_qmp_dispatch(MonitorQMP *mon, QObject *req) { - Monitor *old_mon; QDict *rsp; QDict *error; - old_mon = cur_mon; - cur_mon = &mon->common; - - rsp = qmp_dispatch(mon->commands, req, qmp_oob_enabled(mon)); - - cur_mon = old_mon; + rsp = qmp_dispatch(mon->commands, req, qmp_oob_enabled(mon), + &mon->common); if (mon->commands == &qmp_cap_negotiation_commands) { error = qdict_get_qdict(rsp, "error"); @@ -211,43 +210,99 @@ static QMPRequest *monitor_qmp_requests_pop_any_with_lock(void) return req_obj; } -void monitor_qmp_bh_dispatcher(void *data) +void coroutine_fn monitor_qmp_dispatcher_co(void *data) { - QMPRequest *req_obj = monitor_qmp_requests_pop_any_with_lock(); + QMPRequest *req_obj = NULL; QDict *rsp; bool need_resume; MonitorQMP *mon; - if (!req_obj) { - return; - } + while (true) { + assert(qatomic_mb_read(&qmp_dispatcher_co_busy) == true); - mon = req_obj->mon; - /* qmp_oob_enabled() might change after "qmp_capabilities" */ - need_resume = !qmp_oob_enabled(mon) || - mon->qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1; - qemu_mutex_unlock(&mon->qmp_queue_lock); - if (req_obj->req) { - QDict *qdict = qobject_to(QDict, req_obj->req); - QObject *id = qdict ? qdict_get(qdict, "id") : NULL; - trace_monitor_qmp_cmd_in_band(qobject_get_try_str(id) ?: ""); - monitor_qmp_dispatch(mon, req_obj->req); - } else { - assert(req_obj->err); - rsp = qmp_error_response(req_obj->err); - req_obj->err = NULL; - monitor_qmp_respond(mon, rsp); - qobject_unref(rsp); - } + /* + * Mark the dispatcher as not busy already here so that we + * don't miss any new requests coming in the middle of our + * processing. + */ + qatomic_mb_set(&qmp_dispatcher_co_busy, false); + + while (!(req_obj = monitor_qmp_requests_pop_any_with_lock())) { + /* + * No more requests to process. Wait to be reentered from + * handle_qmp_command() when it pushes more requests, or + * from monitor_cleanup() when it requests shutdown. + */ + if (!qmp_dispatcher_co_shutdown) { + qemu_coroutine_yield(); + + /* + * busy must be set to true again by whoever + * rescheduled us to avoid double scheduling + */ + assert(qatomic_xchg(&qmp_dispatcher_co_busy, false) == true); + } + + /* + * qmp_dispatcher_co_shutdown may have changed if we + * yielded and were reentered from monitor_cleanup() + */ + if (qmp_dispatcher_co_shutdown) { + return; + } + } - if (need_resume) { - /* Pairs with the monitor_suspend() in handle_qmp_command() */ - monitor_resume(&mon->common); - } - qmp_request_free(req_obj); + if (qatomic_xchg(&qmp_dispatcher_co_busy, true) == true) { + /* + * Someone rescheduled us (probably because a new requests + * came in), but we didn't actually yield. Do that now, + * only to be immediately reentered and removed from the + * list of scheduled coroutines. + */ + qemu_coroutine_yield(); + } + + /* + * Move the coroutine from iohandler_ctx to qemu_aio_context for + * executing the command handler so that it can make progress if it + * involves an AIO_WAIT_WHILE(). + */ + aio_co_schedule(qemu_get_aio_context(), qmp_dispatcher_co); + qemu_coroutine_yield(); + + mon = req_obj->mon; + /* qmp_oob_enabled() might change after "qmp_capabilities" */ + need_resume = !qmp_oob_enabled(mon) || + mon->qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1; + qemu_mutex_unlock(&mon->qmp_queue_lock); + if (req_obj->req) { + QDict *qdict = qobject_to(QDict, req_obj->req); + QObject *id = qdict ? qdict_get(qdict, "id") : NULL; + trace_monitor_qmp_cmd_in_band(qobject_get_try_str(id) ?: ""); + monitor_qmp_dispatch(mon, req_obj->req); + } else { + assert(req_obj->err); + rsp = qmp_error_response(req_obj->err); + req_obj->err = NULL; + monitor_qmp_respond(mon, rsp); + qobject_unref(rsp); + } - /* Reschedule instead of looping so the main loop stays responsive */ - qemu_bh_schedule(qmp_dispatcher_bh); + if (need_resume) { + /* Pairs with the monitor_suspend() in handle_qmp_command() */ + monitor_resume(&mon->common); + } + qmp_request_free(req_obj); + + /* + * Yield and reschedule so the main loop stays responsive. + * + * Move back to iohandler_ctx so that nested event loops for + * qemu_aio_context don't start new monitor commands. + */ + aio_co_schedule(iohandler_get_aio_context(), qmp_dispatcher_co); + qemu_coroutine_yield(); + } } static void handle_qmp_command(void *opaque, QObject *req, Error *err) @@ -308,7 +363,9 @@ static void handle_qmp_command(void *opaque, QObject *req, Error *err) qemu_mutex_unlock(&mon->qmp_queue_lock); /* Kick the dispatcher routine */ - qemu_bh_schedule(qmp_dispatcher_bh); + if (!qatomic_xchg(&qmp_dispatcher_co_busy, true)) { + aio_co_wake(qmp_dispatcher_co); + } } static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size) diff --git a/monitor/trace.h b/monitor/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..f216e31be52f66986aaec1616a3712df42ab21fb --- /dev/null +++ b/monitor/trace.h @@ -0,0 +1 @@ +#include "trace/trace-monitor.h" diff --git a/nbd/Makefile.objs b/nbd/Makefile.objs deleted file mode 100644 index eb3dd4461da61a18dc1e23ac4c42a064f4cd52b1..0000000000000000000000000000000000000000 --- a/nbd/Makefile.objs +++ /dev/null @@ -1 +0,0 @@ -block-obj-y += server.o client.o common.o diff --git a/nbd/client.c b/nbd/client.c index ba173108baab2906b62a6ca5d8f0e01e16e58bb8..0c2db4bcba9f7a501e29a67bdae2dceb04d3b32e 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -68,6 +68,7 @@ static int nbd_send_option_request(QIOChannel *ioc, uint32_t opt, uint32_t len, const char *data, Error **errp) { + ERRP_GUARD(); NBDOption req; QEMU_BUILD_BUG_ON(sizeof(req) != 16); @@ -153,6 +154,7 @@ static int nbd_receive_option_reply(QIOChannel *ioc, uint32_t opt, static int nbd_handle_reply_err(QIOChannel *ioc, NBDOptionReply *reply, bool strict, Error **errp) { + ERRP_GUARD(); g_autofree char *msg = NULL; if (!(reply->type & (1 << 31))) { @@ -337,6 +339,7 @@ static int nbd_receive_list(QIOChannel *ioc, char **name, char **description, static int nbd_opt_info_or_go(QIOChannel *ioc, uint32_t opt, NBDExportInfo *info, Error **errp) { + ERRP_GUARD(); NBDOptionReply reply; uint32_t len = strlen(info->name); uint16_t type; @@ -882,6 +885,7 @@ static int nbd_start_negotiate(AioContext *aio_context, QIOChannel *ioc, bool structured_reply, bool *zeroes, Error **errp) { + ERRP_GUARD(); uint64_t magic; trace_nbd_start_negotiate(tlscreds, hostname ? hostname : ""); @@ -1017,6 +1021,7 @@ int nbd_receive_negotiate(AioContext *aio_context, QIOChannel *ioc, const char *hostname, QIOChannel **outioc, NBDExportInfo *info, Error **errp) { + ERRP_GUARD(); int result; bool zeroes; bool base_allocation = info->base_allocation; diff --git a/nbd/meson.build b/nbd/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..2baaa3694801ebbe7fe7e9c5b794a2bc01e1bb57 --- /dev/null +++ b/nbd/meson.build @@ -0,0 +1,7 @@ +block_ss.add(files( + 'client.c', + 'common.c', +)) +blockdev_ss.add(files( + 'server.c', +)) diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h index 60629ef1602d8d5c2dbc6af536793fdac241480b..1b2141ab4b2dc4880640384e804605149a925e25 100644 --- a/nbd/nbd-internal.h +++ b/nbd/nbd-internal.h @@ -19,7 +19,7 @@ #ifndef _WIN32 #include #endif -#if defined(__sun__) || defined(__HAIKU__) +#ifdef HAVE_SYS_IOCCOM_H #include #endif diff --git a/nbd/server.c b/nbd/server.c index 02b1ed080145b3f99979887d4268b4838caad43a..613ed2634ada0e629a4ec087d4591fbdf7d14658 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2018 Red Hat, Inc. + * Copyright (C) 2016-2020 Red Hat, Inc. * Copyright (C) 2005 Anthony Liguori * * Network Block Device Server Side @@ -18,6 +18,8 @@ */ #include "qemu/osdep.h" + +#include "block/export.h" #include "qapi/error.h" #include "qemu/queue.h" #include "trace.h" @@ -25,7 +27,9 @@ #include "qemu/units.h" #define NBD_META_ID_BASE_ALLOCATION 0 -#define NBD_META_ID_DIRTY_BITMAP 1 +#define NBD_META_ID_ALLOCATION_DEPTH 1 +/* Dirty bitmaps use 'NBD_META_ID_DIRTY_BITMAP + i', so keep this id last. */ +#define NBD_META_ID_DIRTY_BITMAP 2 /* * NBD_MAX_BLOCK_STATUS_EXTENTS: 1 MiB of extents data. An empirical @@ -80,25 +84,21 @@ struct NBDRequestData { }; struct NBDExport { - int refcount; - void (*close)(NBDExport *exp); + BlockExport common; - BlockBackend *blk; char *name; char *description; - uint64_t dev_offset; uint64_t size; uint16_t nbdflags; QTAILQ_HEAD(, NBDClient) clients; QTAILQ_ENTRY(NBDExport) next; - AioContext *ctx; - BlockBackend *eject_notifier_blk; Notifier eject_notifier; - BdrvDirtyBitmap *export_bitmap; - char *export_bitmap_context; + bool allocation_depth; + BdrvDirtyBitmap **export_bitmaps; + size_t nr_export_bitmaps; }; static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports); @@ -108,10 +108,13 @@ static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports); * NBD_OPT_LIST_META_CONTEXT. */ typedef struct NBDExportMetaContexts { NBDExport *exp; - bool valid; /* means that negotiation of the option finished without - errors */ + size_t count; /* number of negotiated contexts */ bool base_allocation; /* export base:allocation context (block status) */ - bool bitmap; /* export qemu:dirty-bitmap: */ + bool allocation_depth; /* export qemu:allocation-depth */ + bool *bitmaps; /* + * export qemu:dirty-bitmap:, + * sized by exp->nr_export_bitmaps + */ } NBDExportMetaContexts; struct NBDClient { @@ -211,13 +214,14 @@ static int GCC_FMT_ATTR(4, 0) nbd_negotiate_send_rep_verr(NBDClient *client, uint32_t type, Error **errp, const char *fmt, va_list va) { + ERRP_GUARD(); g_autofree char *msg = NULL; int ret; size_t len; msg = g_strdup_vprintf(fmt, va); len = strlen(msg); - assert(len < 4096); + assert(len < NBD_MAX_STRING_SIZE); trace_nbd_negotiate_send_rep_err(msg); ret = nbd_negotiate_send_rep_len(client, type, len, errp); if (ret < 0) { @@ -231,6 +235,19 @@ nbd_negotiate_send_rep_verr(NBDClient *client, uint32_t type, return 0; } +/* + * Return a malloc'd copy of @name suitable for use in an error reply. + */ +static char * +nbd_sanitize_name(const char *name) +{ + if (strnlen(name, 80) < 80) { + return g_strdup(name); + } + /* XXX Should we also try to sanitize any control characters? */ + return g_strdup_printf("%.80s...", name); +} + /* Send an error reply. * Return -errno on error, 0 on success. */ static int GCC_FMT_ATTR(4, 5) @@ -290,10 +307,11 @@ nbd_opt_invalid(NBDClient *client, Error **errp, const char *fmt, ...) } /* Read size bytes from the unparsed payload of the current option. + * If @check_nul, require that no NUL bytes appear in buffer. * Return -errno on I/O error, 0 if option was completely handled by * sending a reply about inconsistent lengths, or 1 on success. */ static int nbd_opt_read(NBDClient *client, void *buffer, size_t size, - Error **errp) + bool check_nul, Error **errp) { if (size > client->optlen) { return nbd_opt_invalid(client, errp, @@ -301,7 +319,16 @@ static int nbd_opt_read(NBDClient *client, void *buffer, size_t size, nbd_opt_lookup(client->opt)); } client->optlen -= size; - return qio_channel_read_all(client->ioc, buffer, size, errp) < 0 ? -EIO : 1; + if (qio_channel_read_all(client->ioc, buffer, size, errp) < 0) { + return -EIO; + } + + if (check_nul && strnlen(buffer, size) != size) { + return nbd_opt_invalid(client, errp, + "Unexpected embedded NUL in option %s", + nbd_opt_lookup(client->opt)); + } + return 1; } /* Drop size bytes from the unparsed payload of the current option. @@ -338,7 +365,7 @@ static int nbd_opt_read_name(NBDClient *client, char **name, uint32_t *length, g_autofree char *local_name = NULL; *name = NULL; - ret = nbd_opt_read(client, &len, sizeof(len), errp); + ret = nbd_opt_read(client, &len, sizeof(len), false, errp); if (ret <= 0) { return ret; } @@ -350,7 +377,7 @@ static int nbd_opt_read_name(NBDClient *client, char **name, uint32_t *length, } local_name = g_malloc(len + 1); - ret = nbd_opt_read(client, local_name, len, errp); + ret = nbd_opt_read(client, local_name, len, true, errp); if (ret <= 0) { return ret; } @@ -369,6 +396,7 @@ static int nbd_opt_read_name(NBDClient *client, char **name, uint32_t *length, static int nbd_negotiate_send_rep_list(NBDClient *client, NBDExport *exp, Error **errp) { + ERRP_GUARD(); size_t name_len, desc_len; uint32_t len; const char *name = exp->name ? exp->name : ""; @@ -424,7 +452,9 @@ static int nbd_negotiate_handle_list(NBDClient *client, Error **errp) static void nbd_check_meta_export(NBDClient *client) { - client->export_meta.valid &= client->exp == client->export_meta.exp; + if (client->exp != client->export_meta.exp) { + client->export_meta.count = 0; + } } /* Send a reply to NBD_OPT_EXPORT_NAME. @@ -432,6 +462,7 @@ static void nbd_check_meta_export(NBDClient *client) static int nbd_negotiate_handle_export_name(NBDClient *client, bool no_zeroes, Error **errp) { + ERRP_GUARD(); g_autofree char *name = NULL; char buf[NBD_REPLY_EXPORT_NAME_SIZE] = ""; size_t len; @@ -480,7 +511,7 @@ static int nbd_negotiate_handle_export_name(NBDClient *client, bool no_zeroes, } QTAILQ_INSERT_TAIL(&client->exp->clients, client, next); - nbd_export_get(client->exp); + blk_exp_ref(&client->exp->common); nbd_check_meta_export(client); return 0; @@ -543,7 +574,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, Error **errp) NBDExport *exp; uint16_t requests; uint16_t request; - uint32_t namelen; + uint32_t namelen = 0; bool sendname = false; bool blocksize = false; uint32_t sizes[3]; @@ -563,14 +594,14 @@ static int nbd_negotiate_handle_info(NBDClient *client, Error **errp) } trace_nbd_negotiate_handle_export_name_request(name); - rc = nbd_opt_read(client, &requests, sizeof(requests), errp); + rc = nbd_opt_read(client, &requests, sizeof(requests), false, errp); if (rc <= 0) { return rc; } requests = be16_to_cpu(requests); trace_nbd_negotiate_handle_info_requests(requests); while (requests--) { - rc = nbd_opt_read(client, &request, sizeof(request), errp); + rc = nbd_opt_read(client, &request, sizeof(request), false, errp); if (rc <= 0) { return rc; } @@ -595,9 +626,11 @@ static int nbd_negotiate_handle_info(NBDClient *client, Error **errp) exp = nbd_export_find(name); if (!exp) { + g_autofree char *sane_name = nbd_sanitize_name(name); + return nbd_negotiate_send_rep_err(client, NBD_REP_ERR_UNKNOWN, errp, "export '%s' not present", - name); + sane_name); } /* Don't bother sending NBD_INFO_NAME unless client requested it */ @@ -627,7 +660,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, Error **errp) * whether this is OPT_INFO or OPT_GO. */ /* minimum - 1 for back-compat, or actual if client will obey it. */ if (client->opt == NBD_OPT_INFO || blocksize) { - check_align = sizes[0] = blk_get_request_alignment(exp->blk); + check_align = sizes[0] = blk_get_request_alignment(exp->common.blk); } else { sizes[0] = 1; } @@ -636,7 +669,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, Error **errp) * TODO: is blk_bs(blk)->bl.opt_transfer appropriate? */ sizes[1] = MAX(4096, sizes[0]); /* maximum - At most 32M, but smaller as appropriate. */ - sizes[2] = MIN(blk_get_max_transfer(exp->blk), NBD_MAX_BUFFER_SIZE); + sizes[2] = MIN(blk_get_max_transfer(exp->common.blk), NBD_MAX_BUFFER_SIZE); trace_nbd_negotiate_handle_info_block_size(sizes[0], sizes[1], sizes[2]); sizes[0] = cpu_to_be32(sizes[0]); sizes[1] = cpu_to_be32(sizes[1]); @@ -668,7 +701,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, Error **errp) * tolerate all clients, regardless of alignments. */ if (client->opt == NBD_OPT_INFO && !blocksize && - blk_get_request_alignment(exp->blk) > 1) { + blk_get_request_alignment(exp->common.blk) > 1) { return nbd_negotiate_send_rep_err(client, NBD_REP_ERR_BLOCK_SIZE_REQD, errp, @@ -686,7 +719,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, Error **errp) client->exp = exp; client->check_align = check_align; QTAILQ_INSERT_TAIL(&client->exp->clients, client, next); - nbd_export_get(client->exp); + blk_exp_ref(&client->exp->common); nbd_check_meta_export(client); rc = 1; } @@ -772,135 +805,115 @@ static int nbd_negotiate_send_meta_context(NBDClient *client, return qio_channel_writev_all(client->ioc, iov, 2, errp) < 0 ? -EIO : 0; } -/* Read strlen(@pattern) bytes, and set @match to true if they match @pattern. - * @match is never set to false. - * - * Return -errno on I/O error, 0 if option was completely handled by - * sending a reply about inconsistent lengths, or 1 on success. - * - * Note: return code = 1 doesn't mean that we've read exactly @pattern. - * It only means that there are no errors. +/* + * Return true if @query matches @pattern, or if @query is empty when + * the @client is performing _LIST_. */ -static int nbd_meta_pattern(NBDClient *client, const char *pattern, bool *match, - Error **errp) +static bool nbd_meta_empty_or_pattern(NBDClient *client, const char *pattern, + const char *query) { - int ret; - char *query; - size_t len = strlen(pattern); - - assert(len); - - query = g_malloc(len); - ret = nbd_opt_read(client, query, len, errp); - if (ret <= 0) { - g_free(query); - return ret; + if (!*query) { + trace_nbd_negotiate_meta_query_parse("empty"); + return client->opt == NBD_OPT_LIST_META_CONTEXT; } - - if (strncmp(query, pattern, len) == 0) { + if (strcmp(query, pattern) == 0) { trace_nbd_negotiate_meta_query_parse(pattern); - *match = true; - } else { - trace_nbd_negotiate_meta_query_skip("pattern not matched"); + return true; } - g_free(query); - - return 1; + trace_nbd_negotiate_meta_query_skip("pattern not matched"); + return false; } /* - * Read @len bytes, and set @match to true if they match @pattern, or if @len - * is 0 and the client is performing _LIST_. @match is never set to false. - * - * Return -errno on I/O error, 0 if option was completely handled by - * sending a reply about inconsistent lengths, or 1 on success. - * - * Note: return code = 1 doesn't mean that we've read exactly @pattern. - * It only means that there are no errors. + * Return true and adjust @str in place if it begins with @prefix. */ -static int nbd_meta_empty_or_pattern(NBDClient *client, const char *pattern, - uint32_t len, bool *match, Error **errp) +static bool nbd_strshift(const char **str, const char *prefix) { - if (len == 0) { - if (client->opt == NBD_OPT_LIST_META_CONTEXT) { - *match = true; - } - trace_nbd_negotiate_meta_query_parse("empty"); - return 1; - } + size_t len = strlen(prefix); - if (len != strlen(pattern)) { - trace_nbd_negotiate_meta_query_skip("different lengths"); - return nbd_opt_skip(client, len, errp); + if (strncmp(*str, prefix, len) == 0) { + *str += len; + return true; } - - return nbd_meta_pattern(client, pattern, match, errp); + return false; } /* nbd_meta_base_query * * Handle queries to 'base' namespace. For now, only the base:allocation - * context is available. 'len' is the amount of text remaining to be read from - * the current name, after the 'base:' portion has been stripped. - * - * Return -errno on I/O error, 0 if option was completely handled by - * sending a reply about inconsistent lengths, or 1 on success. + * context is available. Return true if @query has been handled. */ -static int nbd_meta_base_query(NBDClient *client, NBDExportMetaContexts *meta, - uint32_t len, Error **errp) +static bool nbd_meta_base_query(NBDClient *client, NBDExportMetaContexts *meta, + const char *query) { - return nbd_meta_empty_or_pattern(client, "allocation", len, - &meta->base_allocation, errp); + if (!nbd_strshift(&query, "base:")) { + return false; + } + trace_nbd_negotiate_meta_query_parse("base:"); + + if (nbd_meta_empty_or_pattern(client, "allocation", query)) { + meta->base_allocation = true; + } + return true; } -/* nbd_meta_bitmap_query - * - * Handle query to 'qemu:' namespace. - * @len is the amount of text remaining to be read from the current name, after - * the 'qemu:' portion has been stripped. +/* nbd_meta_qemu_query * - * Return -errno on I/O error, 0 if option was completely handled by - * sending a reply about inconsistent lengths, or 1 on success. */ -static int nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta, - uint32_t len, Error **errp) + * Handle queries to 'qemu' namespace. For now, only the qemu:dirty-bitmap: + * and qemu:allocation-depth contexts are available. Return true if @query + * has been handled. + */ +static bool nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta, + const char *query) { - bool dirty_bitmap = false; - size_t dirty_bitmap_len = strlen("dirty-bitmap:"); - int ret; + size_t i; - if (!meta->exp->export_bitmap) { - trace_nbd_negotiate_meta_query_skip("no dirty-bitmap exported"); - return nbd_opt_skip(client, len, errp); + if (!nbd_strshift(&query, "qemu:")) { + return false; } + trace_nbd_negotiate_meta_query_parse("qemu:"); - if (len == 0) { + if (!*query) { if (client->opt == NBD_OPT_LIST_META_CONTEXT) { - meta->bitmap = true; + meta->allocation_depth = meta->exp->allocation_depth; + memset(meta->bitmaps, 1, meta->exp->nr_export_bitmaps); } trace_nbd_negotiate_meta_query_parse("empty"); - return 1; + return true; } - if (len < dirty_bitmap_len) { - trace_nbd_negotiate_meta_query_skip("not dirty-bitmap:"); - return nbd_opt_skip(client, len, errp); + if (strcmp(query, "allocation-depth") == 0) { + trace_nbd_negotiate_meta_query_parse("allocation-depth"); + meta->allocation_depth = meta->exp->allocation_depth; + return true; } - len -= dirty_bitmap_len; - ret = nbd_meta_pattern(client, "dirty-bitmap:", &dirty_bitmap, errp); - if (ret <= 0) { - return ret; - } - if (!dirty_bitmap) { - trace_nbd_negotiate_meta_query_skip("not dirty-bitmap:"); - return nbd_opt_skip(client, len, errp); - } + if (nbd_strshift(&query, "dirty-bitmap:")) { + trace_nbd_negotiate_meta_query_parse("dirty-bitmap:"); + if (!*query) { + if (client->opt == NBD_OPT_LIST_META_CONTEXT) { + memset(meta->bitmaps, 1, meta->exp->nr_export_bitmaps); + } + trace_nbd_negotiate_meta_query_parse("empty"); + return true; + } + + for (i = 0; i < meta->exp->nr_export_bitmaps; i++) { + const char *bm_name; - trace_nbd_negotiate_meta_query_parse("dirty-bitmap:"); + bm_name = bdrv_dirty_bitmap_name(meta->exp->export_bitmaps[i]); + if (strcmp(bm_name, query) == 0) { + meta->bitmaps[i] = true; + trace_nbd_negotiate_meta_query_parse(query); + return true; + } + } + trace_nbd_negotiate_meta_query_skip("no dirty-bitmap match"); + return true; + } - return nbd_meta_empty_or_pattern( - client, meta->exp->export_bitmap_context + - strlen("qemu:dirty_bitmap:"), len, &meta->bitmap, errp); + trace_nbd_negotiate_meta_query_skip("unknown qemu context"); + return true; } /* nbd_negotiate_meta_query @@ -910,25 +923,16 @@ static int nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta, * * The only supported namespaces are 'base' and 'qemu'. * - * The function aims not wasting time and memory to read long unknown namespace - * names. - * * Return -errno on I/O error, 0 if option was completely handled by * sending a reply about inconsistent lengths, or 1 on success. */ static int nbd_negotiate_meta_query(NBDClient *client, NBDExportMetaContexts *meta, Error **errp) { - /* - * Both 'qemu' and 'base' namespaces have length = 5 including a - * colon. If another length namespace is later introduced, this - * should certainly be refactored. - */ int ret; - size_t ns_len = 5; - char ns[5]; + g_autofree char *query = NULL; uint32_t len; - ret = nbd_opt_read(client, &len, sizeof(len), errp); + ret = nbd_opt_read(client, &len, sizeof(len), false, errp); if (ret <= 0) { return ret; } @@ -938,27 +942,23 @@ static int nbd_negotiate_meta_query(NBDClient *client, trace_nbd_negotiate_meta_query_skip("length too long"); return nbd_opt_skip(client, len, errp); } - if (len < ns_len) { - trace_nbd_negotiate_meta_query_skip("length too short"); - return nbd_opt_skip(client, len, errp); - } - len -= ns_len; - ret = nbd_opt_read(client, ns, ns_len, errp); + query = g_malloc(len + 1); + ret = nbd_opt_read(client, query, len, true, errp); if (ret <= 0) { return ret; } + query[len] = '\0'; - if (!strncmp(ns, "base:", ns_len)) { - trace_nbd_negotiate_meta_query_parse("base:"); - return nbd_meta_base_query(client, meta, len, errp); - } else if (!strncmp(ns, "qemu:", ns_len)) { - trace_nbd_negotiate_meta_query_parse("qemu:"); - return nbd_meta_qemu_query(client, meta, len, errp); + if (nbd_meta_base_query(client, meta, query)) { + return 1; + } + if (nbd_meta_qemu_query(client, meta, query)) { + return 1; } trace_nbd_negotiate_meta_query_skip("unknown namespace"); - return nbd_opt_skip(client, len, errp); + return 1; } /* nbd_negotiate_meta_queries @@ -970,9 +970,11 @@ static int nbd_negotiate_meta_queries(NBDClient *client, { int ret; g_autofree char *export_name = NULL; - NBDExportMetaContexts local_meta; + g_autofree bool *bitmaps = NULL; + NBDExportMetaContexts local_meta = {0}; uint32_t nb_queries; - int i; + size_t i; + size_t count = 0; if (!client->structured_reply) { return nbd_opt_invalid(client, errp, @@ -986,6 +988,7 @@ static int nbd_negotiate_meta_queries(NBDClient *client, meta = &local_meta; } + g_free(meta->bitmaps); memset(meta, 0, sizeof(*meta)); ret = nbd_opt_read_name(client, &export_name, NULL, errp); @@ -995,11 +998,17 @@ static int nbd_negotiate_meta_queries(NBDClient *client, meta->exp = nbd_export_find(export_name); if (meta->exp == NULL) { + g_autofree char *sane_name = nbd_sanitize_name(export_name); + return nbd_opt_drop(client, NBD_REP_ERR_UNKNOWN, errp, - "export '%s' not present", export_name); + "export '%s' not present", sane_name); + } + meta->bitmaps = g_new0(bool, meta->exp->nr_export_bitmaps); + if (client->opt == NBD_OPT_LIST_META_CONTEXT) { + bitmaps = meta->bitmaps; } - ret = nbd_opt_read(client, &nb_queries, sizeof(nb_queries), errp); + ret = nbd_opt_read(client, &nb_queries, sizeof(nb_queries), false, errp); if (ret <= 0) { return ret; } @@ -1010,7 +1019,8 @@ static int nbd_negotiate_meta_queries(NBDClient *client, if (client->opt == NBD_OPT_LIST_META_CONTEXT && !nb_queries) { /* enable all known contexts */ meta->base_allocation = true; - meta->bitmap = !!meta->exp->export_bitmap; + meta->allocation_depth = meta->exp->allocation_depth; + memset(meta->bitmaps, 1, meta->exp->nr_export_bitmaps); } else { for (i = 0; i < nb_queries; ++i) { ret = nbd_negotiate_meta_query(client, meta, errp); @@ -1027,21 +1037,42 @@ static int nbd_negotiate_meta_queries(NBDClient *client, if (ret < 0) { return ret; } + count++; } - if (meta->bitmap) { - ret = nbd_negotiate_send_meta_context(client, - meta->exp->export_bitmap_context, - NBD_META_ID_DIRTY_BITMAP, + if (meta->allocation_depth) { + ret = nbd_negotiate_send_meta_context(client, "qemu:allocation-depth", + NBD_META_ID_ALLOCATION_DEPTH, + errp); + if (ret < 0) { + return ret; + } + count++; + } + + for (i = 0; i < meta->exp->nr_export_bitmaps; i++) { + const char *bm_name; + g_autofree char *context = NULL; + + if (!meta->bitmaps[i]) { + continue; + } + + bm_name = bdrv_dirty_bitmap_name(meta->exp->export_bitmaps[i]); + context = g_strdup_printf("qemu:dirty-bitmap:%s", bm_name); + + ret = nbd_negotiate_send_meta_context(client, context, + NBD_META_ID_DIRTY_BITMAP + i, errp); if (ret < 0) { return ret; } + count++; } ret = nbd_negotiate_send_rep(client, NBD_REP_ACK, errp); if (ret == 0) { - meta->valid = true; + meta->count = count; } return ret; @@ -1272,6 +1303,7 @@ static int nbd_negotiate_options(NBDClient *client, Error **errp) */ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp) { + ERRP_GUARD(); char buf[NBD_OLDSTYLE_NEGOTIATE_SIZE] = ""; int ret; @@ -1310,8 +1342,8 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp) } /* Attach the channel to the same AioContext as the export */ - if (client->exp && client->exp->ctx) { - qio_channel_attach_aio_context(client->ioc, client->exp->ctx); + if (client->exp && client->exp->common.ctx) { + qio_channel_attach_aio_context(client->ioc, client->exp->common.ctx); } assert(!client->optlen); @@ -1382,8 +1414,9 @@ void nbd_client_put(NBDClient *client) g_free(client->tlsauthz); if (client->exp) { QTAILQ_REMOVE(&client->exp->clients, client, next); - nbd_export_put(client->exp); + blk_exp_unref(&client->exp->common); } + g_free(client->export_meta.bitmaps); g_free(client); } } @@ -1443,7 +1476,7 @@ static void blk_aio_attached(AioContext *ctx, void *opaque) trace_nbd_blk_aio_attached(exp->name, ctx); - exp->ctx = ctx; + exp->common.ctx = ctx; QTAILQ_FOREACH(client, &exp->clients, next) { qio_channel_attach_aio_context(client->ioc, ctx); @@ -1461,72 +1494,92 @@ static void blk_aio_detach(void *opaque) NBDExport *exp = opaque; NBDClient *client; - trace_nbd_blk_aio_detach(exp->name, exp->ctx); + trace_nbd_blk_aio_detach(exp->name, exp->common.ctx); QTAILQ_FOREACH(client, &exp->clients, next) { qio_channel_detach_aio_context(client->ioc); } - exp->ctx = NULL; + exp->common.ctx = NULL; } static void nbd_eject_notifier(Notifier *n, void *data) { NBDExport *exp = container_of(n, NBDExport, eject_notifier); - AioContext *aio_context; - aio_context = exp->ctx; - aio_context_acquire(aio_context); - nbd_export_close(exp); - aio_context_release(aio_context); + blk_exp_request_shutdown(&exp->common); } -NBDExport *nbd_export_new(BlockDriverState *bs, uint64_t dev_offset, - uint64_t size, const char *name, const char *desc, - const char *bitmap, bool readonly, bool shared, - void (*close)(NBDExport *), bool writethrough, - BlockBackend *on_eject_blk, Error **errp) +void nbd_export_set_on_eject_blk(BlockExport *exp, BlockBackend *blk) { - AioContext *ctx; - BlockBackend *blk; - NBDExport *exp = g_new0(NBDExport, 1); - uint64_t perm; + NBDExport *nbd_exp = container_of(exp, NBDExport, common); + assert(exp->drv == &blk_exp_nbd); + assert(nbd_exp->eject_notifier_blk == NULL); + + blk_ref(blk); + nbd_exp->eject_notifier_blk = blk; + nbd_exp->eject_notifier.notify = nbd_eject_notifier; + blk_add_remove_bs_notifier(blk, &nbd_exp->eject_notifier); +} + +static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args, + Error **errp) +{ + NBDExport *exp = container_of(blk_exp, NBDExport, common); + BlockExportOptionsNbd *arg = &exp_args->u.nbd; + BlockBackend *blk = blk_exp->blk; + int64_t size; + uint64_t perm, shared_perm; + bool readonly = !exp_args->writable; + bool shared = !exp_args->writable; + strList *bitmaps; + size_t i; int ret; - /* - * NBD exports are used for non-shared storage migration. Make sure - * that BDRV_O_INACTIVE is cleared and the image is ready for write - * access since the export could be available before migration handover. - * ctx was acquired in the caller. - */ - assert(name && strlen(name) <= NBD_MAX_STRING_SIZE); - ctx = bdrv_get_aio_context(bs); - bdrv_invalidate_cache(bs, NULL); + assert(exp_args->type == BLOCK_EXPORT_TYPE_NBD); + + if (!nbd_server_is_running()) { + error_setg(errp, "NBD server not running"); + return -EINVAL; + } + + if (!arg->has_name) { + arg->name = exp_args->node_name; + } + + if (strlen(arg->name) > NBD_MAX_STRING_SIZE) { + error_setg(errp, "export name '%s' too long", arg->name); + return -EINVAL; + } + + if (arg->description && strlen(arg->description) > NBD_MAX_STRING_SIZE) { + error_setg(errp, "description '%s' too long", arg->description); + return -EINVAL; + } + + if (nbd_export_find(arg->name)) { + error_setg(errp, "NBD server already has export named '%s'", arg->name); + return -EEXIST; + } + + size = blk_getlength(blk); + if (size < 0) { + error_setg_errno(errp, -size, + "Failed to determine the NBD export's length"); + return size; + } /* Don't allow resize while the NBD server is running, otherwise we don't * care what happens with the node. */ - perm = BLK_PERM_CONSISTENT_READ; - if (!readonly) { - perm |= BLK_PERM_WRITE; - } - blk = blk_new(ctx, perm, - BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED | - BLK_PERM_WRITE | BLK_PERM_GRAPH_MOD); - ret = blk_insert_bs(blk, bs, errp); + blk_get_perm(blk, &perm, &shared_perm); + ret = blk_set_perm(blk, perm, shared_perm & ~BLK_PERM_RESIZE, errp); if (ret < 0) { - goto fail; + return ret; } - blk_set_enable_write_cache(blk, !writethrough); - blk_set_allow_aio_context_change(blk, true); - exp->refcount = 1; QTAILQ_INIT(&exp->clients); - exp->blk = blk; - assert(dev_offset <= INT64_MAX); - exp->dev_offset = dev_offset; - exp->name = g_strdup(name); - assert(!desc || strlen(desc) <= NBD_MAX_STRING_SIZE); - exp->description = g_strdup(desc); + exp->name = g_strdup(arg->name); + exp->description = g_strdup(arg->description); exp->nbdflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA | NBD_FLAG_SEND_CACHE); if (readonly) { @@ -1538,66 +1591,69 @@ NBDExport *nbd_export_new(BlockDriverState *bs, uint64_t dev_offset, exp->nbdflags |= (NBD_FLAG_SEND_TRIM | NBD_FLAG_SEND_WRITE_ZEROES | NBD_FLAG_SEND_FAST_ZERO); } - assert(size <= INT64_MAX - dev_offset); exp->size = QEMU_ALIGN_DOWN(size, BDRV_SECTOR_SIZE); - if (bitmap) { + for (bitmaps = arg->bitmaps; bitmaps; bitmaps = bitmaps->next) { + exp->nr_export_bitmaps++; + } + exp->export_bitmaps = g_new0(BdrvDirtyBitmap *, exp->nr_export_bitmaps); + for (i = 0, bitmaps = arg->bitmaps; bitmaps; + i++, bitmaps = bitmaps->next) { + const char *bitmap = bitmaps->value; + BlockDriverState *bs = blk_bs(blk); BdrvDirtyBitmap *bm = NULL; - while (true) { + while (bs) { bm = bdrv_find_dirty_bitmap(bs, bitmap); - if (bm != NULL || bs->backing == NULL) { + if (bm != NULL) { break; } - bs = bs->backing->bs; + bs = bdrv_filter_or_cow_bs(bs); } if (bm == NULL) { + ret = -ENOENT; error_setg(errp, "Bitmap '%s' is not found", bitmap); goto fail; } if (bdrv_dirty_bitmap_check(bm, BDRV_BITMAP_ALLOW_RO, errp)) { + ret = -EINVAL; goto fail; } if (readonly && bdrv_is_writable(bs) && bdrv_dirty_bitmap_enabled(bm)) { + ret = -EINVAL; error_setg(errp, "Enabled bitmap '%s' incompatible with readonly export", bitmap); goto fail; } - bdrv_dirty_bitmap_set_busy(bm, true); - exp->export_bitmap = bm; + exp->export_bitmaps[i] = bm; assert(strlen(bitmap) <= BDRV_BITMAP_MAX_NAME_SIZE); - exp->export_bitmap_context = g_strdup_printf("qemu:dirty-bitmap:%s", - bitmap); - assert(strlen(exp->export_bitmap_context) < NBD_MAX_STRING_SIZE); } - exp->close = close; - exp->ctx = ctx; + /* Mark bitmaps busy in a separate loop, to simplify roll-back concerns. */ + for (i = 0; i < exp->nr_export_bitmaps; i++) { + bdrv_dirty_bitmap_set_busy(exp->export_bitmaps[i], true); + } + + exp->allocation_depth = arg->allocation_depth; + blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, exp); - if (on_eject_blk) { - blk_ref(on_eject_blk); - exp->eject_notifier_blk = on_eject_blk; - exp->eject_notifier.notify = nbd_eject_notifier; - blk_add_remove_bs_notifier(on_eject_blk, &exp->eject_notifier); - } QTAILQ_INSERT_TAIL(&exports, exp, next); - nbd_export_get(exp); - return exp; + + return 0; fail: - blk_unref(blk); + g_free(exp->export_bitmaps); g_free(exp->name); g_free(exp->description); - g_free(exp); - return NULL; + return ret; } NBDExport *nbd_export_find(const char *name) @@ -1615,14 +1671,15 @@ NBDExport *nbd_export_find(const char *name) AioContext * nbd_export_aio_context(NBDExport *exp) { - return exp->ctx; + return exp->common.ctx; } -void nbd_export_close(NBDExport *exp) +static void nbd_export_request_shutdown(BlockExport *blk_exp) { + NBDExport *exp = container_of(blk_exp, NBDExport, common); NBDClient *client, *next; - nbd_export_get(exp); + blk_exp_ref(&exp->common); /* * TODO: Should we expand QMP NbdServerRemoveNode enum to allow a * close mode that stops advertising the export to new clients but @@ -1634,94 +1691,46 @@ void nbd_export_close(NBDExport *exp) client_close(client, true); } if (exp->name) { - nbd_export_put(exp); g_free(exp->name); exp->name = NULL; QTAILQ_REMOVE(&exports, exp, next); } - g_free(exp->description); - exp->description = NULL; - nbd_export_put(exp); + blk_exp_unref(&exp->common); } -void nbd_export_remove(NBDExport *exp, NbdServerRemoveMode mode, Error **errp) +static void nbd_export_delete(BlockExport *blk_exp) { - if (mode == NBD_SERVER_REMOVE_MODE_HARD || QTAILQ_EMPTY(&exp->clients)) { - nbd_export_close(exp); - return; - } + size_t i; + NBDExport *exp = container_of(blk_exp, NBDExport, common); - assert(mode == NBD_SERVER_REMOVE_MODE_SAFE); + assert(exp->name == NULL); + assert(QTAILQ_EMPTY(&exp->clients)); - error_setg(errp, "export '%s' still in use", exp->name); - error_append_hint(errp, "Use mode='hard' to force client disconnect\n"); -} - -void nbd_export_get(NBDExport *exp) -{ - assert(exp->refcount > 0); - exp->refcount++; -} - -void nbd_export_put(NBDExport *exp) -{ - assert(exp->refcount > 0); - if (exp->refcount == 1) { - nbd_export_close(exp); - } - - /* nbd_export_close() may theoretically reduce refcount to 0. It may happen - * if someone calls nbd_export_put() on named export not through - * nbd_export_set_name() when refcount is 1. So, let's assert that - * it is > 0. - */ - assert(exp->refcount > 0); - if (--exp->refcount == 0) { - assert(exp->name == NULL); - assert(exp->description == NULL); - - if (exp->close) { - exp->close(exp); - } - - if (exp->blk) { - if (exp->eject_notifier_blk) { - notifier_remove(&exp->eject_notifier); - blk_unref(exp->eject_notifier_blk); - } - blk_remove_aio_context_notifier(exp->blk, blk_aio_attached, - blk_aio_detach, exp); - blk_unref(exp->blk); - exp->blk = NULL; - } + g_free(exp->description); + exp->description = NULL; - if (exp->export_bitmap) { - bdrv_dirty_bitmap_set_busy(exp->export_bitmap, false); - g_free(exp->export_bitmap_context); + if (exp->common.blk) { + if (exp->eject_notifier_blk) { + notifier_remove(&exp->eject_notifier); + blk_unref(exp->eject_notifier_blk); } - - g_free(exp); + blk_remove_aio_context_notifier(exp->common.blk, blk_aio_attached, + blk_aio_detach, exp); } -} - -BlockBackend *nbd_export_get_blockdev(NBDExport *exp) -{ - return exp->blk; -} - -void nbd_export_close_all(void) -{ - NBDExport *exp, *next; - AioContext *aio_context; - QTAILQ_FOREACH_SAFE(exp, &exports, next, next) { - aio_context = exp->ctx; - aio_context_acquire(aio_context); - nbd_export_close(exp); - aio_context_release(aio_context); + for (i = 0; i < exp->nr_export_bitmaps; i++) { + bdrv_dirty_bitmap_set_busy(exp->export_bitmaps[i], false); } } +const BlockExportDriver blk_exp_nbd = { + .type = BLOCK_EXPORT_TYPE_NBD, + .instance_size = sizeof(NBDExport), + .create = nbd_export_create, + .delete = nbd_export_delete, + .request_shutdown = nbd_export_request_shutdown, +}; + static int coroutine_fn nbd_co_send_iov(NBDClient *client, struct iovec *iov, unsigned niov, Error **errp) { @@ -1858,7 +1867,7 @@ static int coroutine_fn nbd_co_send_sparse_read(NBDClient *client, while (progress < size) { int64_t pnum; - int status = bdrv_block_status_above(blk_bs(exp->blk), NULL, + int status = bdrv_block_status_above(blk_bs(exp->common.blk), NULL, offset + progress, size - progress, &pnum, NULL, NULL); @@ -1890,7 +1899,7 @@ static int coroutine_fn nbd_co_send_sparse_read(NBDClient *client, stl_be_p(&chunk.length, pnum); ret = nbd_co_send_iov(client, iov, 1, errp); } else { - ret = blk_pread(exp->blk, offset + progress + exp->dev_offset, + ret = blk_pread(exp->common.blk, offset + progress, data + progress, pnum); if (ret < 0) { error_setg_errno(errp, -ret, "reading from file failed"); @@ -2020,6 +2029,29 @@ static int blockstatus_to_extents(BlockDriverState *bs, uint64_t offset, return 0; } +static int blockalloc_to_extents(BlockDriverState *bs, uint64_t offset, + uint64_t bytes, NBDExtentArray *ea) +{ + while (bytes) { + int64_t num; + int ret = bdrv_is_allocated_above(bs, NULL, false, offset, bytes, + &num); + + if (ret < 0) { + return ret; + } + + if (nbd_extent_array_add(ea, num, ret) < 0) { + return 0; + } + + offset += num; + bytes -= num; + } + + return 0; +} + /* * nbd_co_send_extents * @@ -2059,7 +2091,11 @@ static int nbd_co_send_block_status(NBDClient *client, uint64_t handle, unsigned int nb_extents = dont_fragment ? 1 : NBD_MAX_BLOCK_STATUS_EXTENTS; g_autoptr(NBDExtentArray) ea = nbd_extent_array_new(nb_extents); - ret = blockstatus_to_extents(bs, offset, length, ea); + if (context_id == NBD_META_ID_BASE_ALLOCATION) { + ret = blockstatus_to_extents(bs, offset, length, ea); + } else { + ret = blockalloc_to_extents(bs, offset, length, ea); + } if (ret < 0) { return nbd_co_send_structured_error( client, handle, -ret, "can't get block status", errp); @@ -2093,8 +2129,8 @@ static void bitmap_to_extents(BdrvDirtyBitmap *bitmap, } if (!full) { - /* last non dirty extent */ - nbd_extent_array_add(es, end - start, 0); + /* last non dirty extent, nothing to do if array is now full */ + (void) nbd_extent_array_add(es, end - start, 0); } bdrv_dirty_bitmap_unlock(bitmap); @@ -2155,7 +2191,8 @@ static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request, } if (request->type != NBD_CMD_CACHE) { - req->data = blk_try_blockalign(client->exp->blk, request->len); + req->data = blk_try_blockalign(client->exp->common.blk, + request->len); if (req->data == NULL) { error_setg(errp, "No memory"); return -ENOMEM; @@ -2251,7 +2288,7 @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request, /* XXX: NBD Protocol only documents use of FUA with WRITE */ if (request->flags & NBD_CMD_FLAG_FUA) { - ret = blk_co_flush(exp->blk); + ret = blk_co_flush(exp->common.blk); if (ret < 0) { return nbd_send_generic_reply(client, request->handle, ret, "flush failed", errp); @@ -2265,8 +2302,7 @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request, data, request->len, errp); } - ret = blk_pread(exp->blk, request->from + exp->dev_offset, data, - request->len); + ret = blk_pread(exp->common.blk, request->from, data, request->len); if (ret < 0) { return nbd_send_generic_reply(client, request->handle, ret, "reading from file failed", errp); @@ -2301,7 +2337,7 @@ static coroutine_fn int nbd_do_cmd_cache(NBDClient *client, NBDRequest *request, assert(request->type == NBD_CMD_CACHE); - ret = blk_co_preadv(exp->blk, request->from + exp->dev_offset, request->len, + ret = blk_co_preadv(exp->common.blk, request->from, request->len, NULL, BDRV_REQ_COPY_ON_READ | BDRV_REQ_PREFETCH); return nbd_send_generic_reply(client, request->handle, ret, @@ -2319,6 +2355,7 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, int flags; NBDExport *exp = client->exp; char *msg; + size_t i; switch (request->type) { case NBD_CMD_CACHE: @@ -2332,8 +2369,8 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, if (request->flags & NBD_CMD_FLAG_FUA) { flags |= BDRV_REQ_FUA; } - ret = blk_pwrite(exp->blk, request->from + exp->dev_offset, - data, request->len, flags); + ret = blk_pwrite(exp->common.blk, request->from, data, request->len, + flags); return nbd_send_generic_reply(client, request->handle, ret, "writing to file failed", errp); @@ -2348,8 +2385,16 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, if (request->flags & NBD_CMD_FLAG_FAST_ZERO) { flags |= BDRV_REQ_NO_FALLBACK; } - ret = blk_pwrite_zeroes(exp->blk, request->from + exp->dev_offset, - request->len, flags); + ret = 0; + /* FIXME simplify this when blk_pwrite_zeroes switches to 64-bit */ + while (ret >= 0 && request->len) { + int align = client->check_align ?: 1; + int len = MIN(request->len, QEMU_ALIGN_DOWN(BDRV_REQUEST_MAX_BYTES, + align)); + ret = blk_pwrite_zeroes(exp->common.blk, request->from, len, flags); + request->len -= len; + request->from += len; + } return nbd_send_generic_reply(client, request->handle, ret, "writing to file failed", errp); @@ -2358,15 +2403,23 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, abort(); case NBD_CMD_FLUSH: - ret = blk_co_flush(exp->blk); + ret = blk_co_flush(exp->common.blk); return nbd_send_generic_reply(client, request->handle, ret, "flush failed", errp); case NBD_CMD_TRIM: - ret = blk_co_pdiscard(exp->blk, request->from + exp->dev_offset, - request->len); - if (ret == 0 && request->flags & NBD_CMD_FLAG_FUA) { - ret = blk_co_flush(exp->blk); + ret = 0; + /* FIXME simplify this when blk_co_pdiscard switches to 64-bit */ + while (ret >= 0 && request->len) { + int align = client->check_align ?: 1; + int len = MIN(request->len, QEMU_ALIGN_DOWN(BDRV_REQUEST_MAX_BYTES, + align)); + ret = blk_co_pdiscard(exp->common.blk, request->from, len); + request->len -= len; + request->from += len; + } + if (ret >= 0 && request->flags & NBD_CMD_FLAG_FUA) { + ret = blk_co_flush(exp->common.blk); } return nbd_send_generic_reply(client, request->handle, ret, "discard failed", errp); @@ -2376,17 +2429,16 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, return nbd_send_generic_reply(client, request->handle, -EINVAL, "need non-zero length", errp); } - if (client->export_meta.valid && - (client->export_meta.base_allocation || - client->export_meta.bitmap)) - { + if (client->export_meta.count) { bool dont_fragment = request->flags & NBD_CMD_FLAG_REQ_ONE; + int contexts_remaining = client->export_meta.count; if (client->export_meta.base_allocation) { ret = nbd_co_send_block_status(client, request->handle, - blk_bs(exp->blk), request->from, + blk_bs(exp->common.blk), + request->from, request->len, dont_fragment, - !client->export_meta.bitmap, + !--contexts_remaining, NBD_META_ID_BASE_ALLOCATION, errp); if (ret < 0) { @@ -2394,17 +2446,35 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, } } - if (client->export_meta.bitmap) { + if (client->export_meta.allocation_depth) { + ret = nbd_co_send_block_status(client, request->handle, + blk_bs(exp->common.blk), + request->from, request->len, + dont_fragment, + !--contexts_remaining, + NBD_META_ID_ALLOCATION_DEPTH, + errp); + if (ret < 0) { + return ret; + } + } + + for (i = 0; i < client->exp->nr_export_bitmaps; i++) { + if (!client->export_meta.bitmaps[i]) { + continue; + } ret = nbd_co_send_bitmap(client, request->handle, - client->exp->export_bitmap, + client->exp->export_bitmaps[i], request->from, request->len, - dont_fragment, - true, NBD_META_ID_DIRTY_BITMAP, errp); + dont_fragment, !--contexts_remaining, + NBD_META_ID_DIRTY_BITMAP + i, errp); if (ret < 0) { return ret; } } + assert(!contexts_remaining); + return 0; } else { return nbd_send_generic_reply(client, request->handle, -EINVAL, @@ -2498,7 +2568,7 @@ static void nbd_client_receive_next_request(NBDClient *client) if (!client->recv_coroutine && client->nb_requests < MAX_NBD_REQUESTS) { nbd_client_get(client); client->recv_coroutine = qemu_coroutine_create(nbd_trip, client); - aio_co_schedule(client->exp->ctx, client->recv_coroutine); + aio_co_schedule(client->exp->common.ctx, client->recv_coroutine); } } diff --git a/nbd/trace.h b/nbd/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..233d08fdd10c27bfcebc43c006abe20be12fa736 --- /dev/null +++ b/nbd/trace.h @@ -0,0 +1 @@ +#include "trace/trace-nbd.h" diff --git a/net/Makefile.objs b/net/Makefile.objs deleted file mode 100644 index c5d076d19c9e20c6ce996ab31154f460d0d10270..0000000000000000000000000000000000000000 --- a/net/Makefile.objs +++ /dev/null @@ -1,32 +0,0 @@ -common-obj-y = net.o queue.o checksum.o util.o hub.o -common-obj-y += socket.o -common-obj-y += dump.o -common-obj-y += eth.o -common-obj-y += announce.o -common-obj-$(CONFIG_L2TPV3) += l2tpv3.o -common-obj-$(call land,$(CONFIG_VIRTIO_NET),$(CONFIG_VHOST_NET_USER)) += vhost-user.o -common-obj-$(call land,$(call lnot,$(CONFIG_VIRTIO_NET)),$(CONFIG_VHOST_NET_USER)) += vhost-user-stub.o -common-obj-$(CONFIG_ALL) += vhost-user-stub.o -common-obj-$(CONFIG_SLIRP) += slirp.o -slirp.o-cflags := $(SLIRP_CFLAGS) -slirp.o-libs := $(SLIRP_LIBS) -common-obj-$(CONFIG_VDE) += vde.o -common-obj-$(CONFIG_NETMAP) += netmap.o -common-obj-y += filter.o -common-obj-y += filter-buffer.o -common-obj-y += filter-mirror.o -common-obj-y += colo-compare.o -common-obj-y += colo.o -common-obj-y += filter-rewriter.o -common-obj-y += filter-replay.o - -tap-obj-$(CONFIG_LINUX) = tap-linux.o -tap-obj-$(CONFIG_BSD) = tap-bsd.o -tap-obj-$(CONFIG_SOLARIS) = tap-solaris.o -tap-obj-y ?= tap-stub.o -common-obj-$(CONFIG_POSIX) += tap.o $(tap-obj-y) -common-obj-$(CONFIG_WIN32) += tap-win32.o - -vde.o-libs = $(VDE_LIBS) - -common-obj-$(CONFIG_CAN_BUS) += can/ diff --git a/net/can/Makefile.objs b/net/can/Makefile.objs deleted file mode 100644 index 9f35dc5c87389cca9bb7216bf0b0e0cb245be9ec..0000000000000000000000000000000000000000 --- a/net/can/Makefile.objs +++ /dev/null @@ -1,2 +0,0 @@ -common-obj-y += can_core.o can_host.o -common-obj-$(CONFIG_LINUX) += can_socketcan.o diff --git a/net/can/can_core.c b/net/can/can_core.c index 90f4d8576ac8bc82412bc903f87e70b316075537..0115d787941ee6d8a8175a5efb28510f58bfdc22 100644 --- a/net/can/can_core.c +++ b/net/can/can_core.c @@ -33,6 +33,42 @@ #include "net/can_emu.h" #include "qom/object_interfaces.h" +/* CAN DLC to real data length conversion helpers */ + +static const uint8_t dlc2len[] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 12, 16, 20, 24, 32, 48, 64 +}; + +/* get data length from can_dlc with sanitized can_dlc */ +uint8_t can_dlc2len(uint8_t can_dlc) +{ + return dlc2len[can_dlc & 0x0F]; +} + +static const uint8_t len2dlc[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, /* 0 - 8 */ + 9, 9, 9, 9, /* 9 - 12 */ + 10, 10, 10, 10, /* 13 - 16 */ + 11, 11, 11, 11, /* 17 - 20 */ + 12, 12, 12, 12, /* 21 - 24 */ + 13, 13, 13, 13, 13, 13, 13, 13, /* 25 - 32 */ + 14, 14, 14, 14, 14, 14, 14, 14, /* 33 - 40 */ + 14, 14, 14, 14, 14, 14, 14, 14, /* 41 - 48 */ + 15, 15, 15, 15, 15, 15, 15, 15, /* 49 - 56 */ + 15, 15, 15, 15, 15, 15, 15, 15 /* 57 - 64 */ +}; + +/* map the sanitized data length to an appropriate data length code */ +uint8_t can_len2dlc(uint8_t len) +{ + if (unlikely(len > 64)) { + return 0xF; + } + + return len2dlc[len]; +} + struct CanBusState { Object object; diff --git a/net/can/can_socketcan.c b/net/can/can_socketcan.c index b7ef63ec0e4e34749f0672af5e68fd071a4661af..4b68f60c6b663afed4e94be80fa6bea7ef566849 100644 --- a/net/can/can_socketcan.c +++ b/net/can/can_socketcan.c @@ -40,17 +40,17 @@ #include #include #include +#include "qom/object.h" #ifndef DEBUG_CAN #define DEBUG_CAN 0 #endif /*DEBUG_CAN*/ #define TYPE_CAN_HOST_SOCKETCAN "can-host-socketcan" -#define CAN_HOST_SOCKETCAN(obj) \ - OBJECT_CHECK(CanHostSocketCAN, (obj), TYPE_CAN_HOST_SOCKETCAN) +OBJECT_DECLARE_SIMPLE_TYPE(CanHostSocketCAN, CAN_HOST_SOCKETCAN) #define CAN_READ_BUF_LEN 5 -typedef struct CanHostSocketCAN { +struct CanHostSocketCAN { CanHostState parent; char *ifname; @@ -63,7 +63,7 @@ typedef struct CanHostSocketCAN { int bufptr; int fd; -} CanHostSocketCAN; +}; /* Check that QEMU and Linux kernel flags encoding and structure matches */ QEMU_BUILD_BUG_ON(QEMU_CAN_EFF_FLAG != CAN_EFF_FLAG); @@ -103,6 +103,14 @@ static void can_host_socketcan_read(void *opaque) return; } + if (!ch->bus_client.fd_mode) { + c->buf[0].flags = 0; + } else { + if (c->bufcnt > CAN_MTU) { + c->buf[0].flags |= QEMU_CAN_FRMF_TYPE_FD; + } + } + can_bus_client_send(&ch->bus_client, c->buf, 1); if (DEBUG_CAN) { @@ -121,12 +129,21 @@ static ssize_t can_host_socketcan_receive(CanBusClientState *client, CanHostState *ch = container_of(client, CanHostState, bus_client); CanHostSocketCAN *c = CAN_HOST_SOCKETCAN(ch); - size_t len = sizeof(qemu_can_frame); + size_t len; int res; if (c->fd < 0) { return -1; } + if (frames->flags & QEMU_CAN_FRMF_TYPE_FD) { + if (!ch->bus_client.fd_mode) { + return 0; + } + len = CANFD_MTU; + } else { + len = CAN_MTU; + + } res = write(c->fd, frames, len); @@ -172,9 +189,16 @@ static void can_host_socketcan_connect(CanHostState *ch, Error **errp) { CanHostSocketCAN *c = CAN_HOST_SOCKETCAN(ch); int s; /* can raw socket */ + int mtu; + int enable_canfd = 1; struct sockaddr_can addr; struct ifreq ifr; + if (!c->ifname) { + error_setg(errp, "'if' property not set"); + return; + } + /* open socket */ s = qemu_socket(PF_CAN, SOCK_RAW, CAN_RAW); if (s < 0) { @@ -185,13 +209,34 @@ static void can_host_socketcan_connect(CanHostState *ch, Error **errp) addr.can_family = AF_CAN; memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name)); strcpy(ifr.ifr_name, c->ifname); + /* check if the frame fits into the CAN netdevice */ if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { error_setg_errno(errp, errno, - "SocketCAN host interface %s not available", c->ifname); + "SocketCAN host interface %s not available", + c->ifname); goto fail; } addr.can_ifindex = ifr.ifr_ifindex; + if (ioctl(s, SIOCGIFMTU, &ifr) < 0) { + error_setg_errno(errp, errno, + "SocketCAN host interface %s SIOCGIFMTU failed", + c->ifname); + goto fail; + } + mtu = ifr.ifr_mtu; + + if (mtu >= CANFD_MTU) { + /* interface is ok - try to switch the socket into CAN FD mode */ + if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, + &enable_canfd, sizeof(enable_canfd))) { + warn_report("SocketCAN host interface %s enabling CAN FD failed", + c->ifname); + } else { + c->parent.bus_client.fd_mode = true; + } + } + c->err_mask = 0xffffffff; /* Receive error frame. */ setsockopt(s, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &c->err_mask, sizeof(c->err_mask)); @@ -232,7 +277,8 @@ static char *can_host_socketcan_get_if(Object *obj, Error **errp) return g_strdup(c->ifname); } -static void can_host_socketcan_set_if(Object *obj, const char *value, Error **errp) +static void can_host_socketcan_set_if(Object *obj, const char *value, + Error **errp) { CanHostSocketCAN *c = CAN_HOST_SOCKETCAN(obj); struct ifreq ifr; diff --git a/net/can/meson.build b/net/can/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..f53d9ec54f3e381aff36d2cfb0b40134978338a2 --- /dev/null +++ b/net/can/meson.build @@ -0,0 +1,5 @@ +can_ss = ss.source_set() +can_ss.add(files('can_core.c', 'can_host.c')) +can_ss.add(when: 'CONFIG_LINUX', if_true: files('can_socketcan.c')) + +softmmu_ss.add_all(when: 'CONFIG_CAN_BUS', if_true: can_ss) diff --git a/net/clients.h b/net/clients.h index a6ef267e198a4cf1ebbec744dcb60107be3e418e..92f9b59aedce424c64db345f1d524c83e5103c27 100644 --- a/net/clients.h +++ b/net/clients.h @@ -61,4 +61,6 @@ int net_init_netmap(const Netdev *netdev, const char *name, int net_init_vhost_user(const Netdev *netdev, const char *name, NetClientState *peer, Error **errp); +int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + NetClientState *peer, Error **errp); #endif /* QEMU_NET_CLIENTS_H */ diff --git a/net/colo-compare.c b/net/colo-compare.c index c07e7c1c0911aaadd9ee900ed432770f2aa19d59..337025b44f8afe5d72b5d0d5075f0242e4430045 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -32,9 +32,13 @@ #include "migration/migration.h" #include "util.h" +#include "block/aio-wait.h" +#include "qemu/coroutine.h" + #define TYPE_COLO_COMPARE "colo-compare" -#define COLO_COMPARE(obj) \ - OBJECT_CHECK(CompareState, (obj), TYPE_COLO_COMPARE) +typedef struct CompareState CompareState; +DECLARE_INSTANCE_CHECKER(CompareState, COLO_COMPARE, + TYPE_COLO_COMPARE) static QTAILQ_HEAD(, CompareState) net_compares = QTAILQ_HEAD_INITIALIZER(net_compares); @@ -48,12 +52,17 @@ static NotifierList colo_compare_notifiers = #define COLO_COMPARE_FREE_PRIMARY 0x01 #define COLO_COMPARE_FREE_SECONDARY 0x02 -#define REGULAR_PACKET_CHECK_MS 3000 +#define REGULAR_PACKET_CHECK_MS 1000 #define DEFAULT_TIME_OUT_MS 3000 +/* #define DEBUG_COLO_PACKETS */ + +static QemuMutex colo_compare_mutex; +static bool colo_compare_active; static QemuMutex event_mtx; static QemuCond event_complete_cond; static int event_unhandled_count; +static uint32_t max_queue_size; /* * + CompareState ++ @@ -77,7 +86,24 @@ static int event_unhandled_count; * |packet | |packet + |packet | |packet + * +--------+ +--------+ +--------+ +--------+ */ -typedef struct CompareState { + +typedef struct SendCo { + Coroutine *co; + struct CompareState *s; + CharBackend *chr; + GQueue send_list; + bool notify_remote_frame; + bool done; + int ret; +} SendCo; + +typedef struct SendEntry { + uint32_t size; + uint32_t vnet_hdr_len; + uint8_t *buf; +} SendEntry; + +struct CompareState { Object parent; char *pri_indev; @@ -91,8 +117,10 @@ typedef struct CompareState { SocketReadState pri_rs; SocketReadState sec_rs; SocketReadState notify_rs; + SendCo out_sendco; + SendCo notify_sendco; bool vnet_hdr; - uint32_t compare_timeout; + uint64_t compare_timeout; uint32_t expired_scan_cycle; /* @@ -111,7 +139,7 @@ typedef struct CompareState { enum colo_event event; QTAILQ_ENTRY(CompareState) next; -} CompareState; +}; typedef struct CompareClass { ObjectClass parent_class; @@ -122,12 +150,17 @@ enum { SECONDARY_IN, }; +static const char *colo_mode[] = { + [PRIMARY_IN] = "primary", + [SECONDARY_IN] = "secondary", +}; static int compare_chr_send(CompareState *s, - const uint8_t *buf, + uint8_t *buf, uint32_t size, uint32_t vnet_hdr_len, - bool notify_remote_frame); + bool notify_remote_frame, + bool zero_copy); static bool packet_matches_str(const char *str, const uint8_t *buf, @@ -145,7 +178,7 @@ static void notify_remote_frame(CompareState *s) char msg[] = "DO_CHECKPOINT"; int ret = 0; - ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true); + ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true, false); if (ret < 0) { error_report("Notify Xen COLO-frame failed"); } @@ -161,13 +194,10 @@ static void colo_compare_inconsistency_notify(CompareState *s) } } +/* Use restricted to colo_insert_packet() */ static gint seq_sorter(Packet *a, Packet *b, gpointer data) { - struct tcp_hdr *atcp, *btcp; - - atcp = (struct tcp_hdr *)(a->transport_header); - btcp = (struct tcp_hdr *)(b->transport_header); - return ntohl(atcp->th_seq) - ntohl(btcp->th_seq); + return a->tcp_seq - b->tcp_seq; } static void fill_pkt_tcp_info(void *data, uint32_t *max_ack) @@ -193,7 +223,7 @@ static void fill_pkt_tcp_info(void *data, uint32_t *max_ack) */ static int colo_insert_packet(GQueue *queue, Packet *pkt, uint32_t *max_ack) { - if (g_queue_get_length(queue) <= MAX_QUEUE_SIZE) { + if (g_queue_get_length(queue) <= max_queue_size) { if (pkt->ip->ip_p == IPPROTO_TCP) { fill_pkt_tcp_info(pkt, max_ack); g_queue_insert_sorted(queue, @@ -217,6 +247,7 @@ static int packet_enqueue(CompareState *s, int mode, Connection **con) ConnectionKey key; Packet *pkt = NULL; Connection *conn; + int ret; if (mode == PRIMARY_IN) { pkt = packet_new(s->pri_rs.buf, @@ -245,16 +276,18 @@ static int packet_enqueue(CompareState *s, int mode, Connection **con) } if (mode == PRIMARY_IN) { - if (!colo_insert_packet(&conn->primary_list, pkt, &conn->pack)) { - error_report("colo compare primary queue size too big," - "drop packet"); - } + ret = colo_insert_packet(&conn->primary_list, pkt, &conn->pack); } else { - if (!colo_insert_packet(&conn->secondary_list, pkt, &conn->sack)) { - error_report("colo compare secondary queue size too big," - "drop packet"); - } + ret = colo_insert_packet(&conn->secondary_list, pkt, &conn->sack); } + + if (!ret) { + trace_colo_compare_drop_packet(colo_mode[mode], + "queue size too big, drop packet"); + packet_destroy(pkt, NULL); + pkt = NULL; + } + *con = conn; return 0; @@ -272,12 +305,13 @@ static void colo_release_primary_pkt(CompareState *s, Packet *pkt) pkt->data, pkt->size, pkt->vnet_hdr_len, - false); + false, + true); if (ret < 0) { error_report("colo send primary packet failed"); } trace_colo_compare_main("packet same and release packet"); - packet_destroy(pkt, NULL); + packet_destroy_partial(pkt, NULL); } /* @@ -294,7 +328,7 @@ static int colo_compare_packet_payload(Packet *ppkt, uint16_t len) { - if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) { + if (trace_event_get_state_backends(TRACE_COLO_COMPARE_IP_INFO)) { char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20]; strcpy(pri_ip_src, inet_ntoa(ppkt->ip->ip_src)); @@ -443,13 +477,11 @@ sec: colo_release_primary_pkt(s, ppkt); g_queue_push_head(&conn->secondary_list, spkt); goto pri; - } - if (mark == COLO_COMPARE_FREE_SECONDARY) { + } else if (mark == COLO_COMPARE_FREE_SECONDARY) { conn->compare_seq = spkt->seq_end; packet_destroy(spkt, NULL); goto sec; - } - if (mark == (COLO_COMPARE_FREE_PRIMARY | COLO_COMPARE_FREE_SECONDARY)) { + } else if (mark == (COLO_COMPARE_FREE_PRIMARY | COLO_COMPARE_FREE_SECONDARY)) { conn->compare_seq = ppkt->seq_end; colo_release_primary_pkt(s, ppkt); packet_destroy(spkt, NULL); @@ -459,10 +491,10 @@ sec: g_queue_push_head(&conn->primary_list, ppkt); g_queue_push_head(&conn->secondary_list, spkt); - qemu_hexdump((char *)ppkt->data, stderr, - "colo-compare ppkt", ppkt->size); - qemu_hexdump((char *)spkt->data, stderr, - "colo-compare spkt", spkt->size); +#ifdef DEBUG_COLO_PACKETS + qemu_hexdump(stderr, "colo-compare ppkt", ppkt->data, ppkt->size); + qemu_hexdump(stderr, "colo-compare spkt", spkt->data, spkt->size); +#endif colo_compare_inconsistency_notify(s); } @@ -498,12 +530,10 @@ static int colo_packet_compare_udp(Packet *spkt, Packet *ppkt) ppkt->size - offset)) { trace_colo_compare_udp_miscompare("primary pkt size", ppkt->size); trace_colo_compare_udp_miscompare("Secondary pkt size", spkt->size); - if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) { - qemu_hexdump((char *)ppkt->data, stderr, "colo-compare pri pkt", - ppkt->size); - qemu_hexdump((char *)spkt->data, stderr, "colo-compare sec pkt", - spkt->size); - } +#ifdef DEBUG_COLO_PACKETS + qemu_hexdump(stderr, "colo-compare pri pkt", ppkt->data, ppkt->size); + qemu_hexdump(stderr, "colo-compare sec pkt", spkt->data, spkt->size); +#endif return -1; } else { return 0; @@ -541,12 +571,10 @@ static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt) ppkt->size); trace_colo_compare_icmp_miscompare("Secondary pkt size", spkt->size); - if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) { - qemu_hexdump((char *)ppkt->data, stderr, "colo-compare pri pkt", - ppkt->size); - qemu_hexdump((char *)spkt->data, stderr, "colo-compare sec pkt", - spkt->size); - } +#ifdef DEBUG_COLO_PACKETS + qemu_hexdump(stderr, "colo-compare pri pkt", ppkt->data, ppkt->size); + qemu_hexdump(stderr, "colo-compare sec pkt", spkt->data, spkt->size); +#endif return -1; } else { return 0; @@ -562,7 +590,7 @@ static int colo_packet_compare_other(Packet *spkt, Packet *ppkt) uint16_t offset = ppkt->vnet_hdr_len; trace_colo_compare_main("compare other"); - if (trace_event_get_state_backends(TRACE_COLO_COMPARE_MISCOMPARE)) { + if (trace_event_get_state_backends(TRACE_COLO_COMPARE_IP_INFO)) { char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20]; strcpy(pri_ip_src, inet_ntoa(ppkt->ip->ip_src)); @@ -608,19 +636,26 @@ void colo_compare_unregister_notifier(Notifier *notify) static int colo_old_packet_check_one_conn(Connection *conn, CompareState *s) { - GList *result = NULL; - - result = g_queue_find_custom(&conn->primary_list, - &s->compare_timeout, - (GCompareFunc)colo_old_packet_check_one); + if (!g_queue_is_empty(&conn->primary_list)) { + if (g_queue_find_custom(&conn->primary_list, + &s->compare_timeout, + (GCompareFunc)colo_old_packet_check_one)) + goto out; + } - if (result) { - /* Do checkpoint will flush old packet */ - colo_compare_inconsistency_notify(s); - return 0; + if (!g_queue_is_empty(&conn->secondary_list)) { + if (g_queue_find_custom(&conn->secondary_list, + &s->compare_timeout, + (GCompareFunc)colo_old_packet_check_one)) + goto out; } return 1; + +out: + /* Do checkpoint will flush old packet */ + colo_compare_inconsistency_notify(s); + return 0; } /* @@ -699,65 +734,115 @@ static void colo_compare_connection(void *opaque, void *user_data) } } -static int compare_chr_send(CompareState *s, - const uint8_t *buf, - uint32_t size, - uint32_t vnet_hdr_len, - bool notify_remote_frame) +static void coroutine_fn _compare_chr_send(void *opaque) { + SendCo *sendco = opaque; + CompareState *s = sendco->s; int ret = 0; - uint32_t len = htonl(size); - if (!size) { - return 0; - } + while (!g_queue_is_empty(&sendco->send_list)) { + SendEntry *entry = g_queue_pop_tail(&sendco->send_list); + uint32_t len = htonl(entry->size); - if (notify_remote_frame) { - ret = qemu_chr_fe_write_all(&s->chr_notify_dev, - (uint8_t *)&len, - sizeof(len)); - } else { - ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len)); - } + ret = qemu_chr_fe_write_all(sendco->chr, (uint8_t *)&len, sizeof(len)); - if (ret != sizeof(len)) { - goto err; - } + if (ret != sizeof(len)) { + g_free(entry->buf); + g_slice_free(SendEntry, entry); + goto err; + } - if (s->vnet_hdr) { - /* - * We send vnet header len make other module(like filter-redirector) - * know how to parse net packet correctly. - */ - len = htonl(vnet_hdr_len); + if (!sendco->notify_remote_frame && s->vnet_hdr) { + /* + * We send vnet header len make other module(like filter-redirector) + * know how to parse net packet correctly. + */ + len = htonl(entry->vnet_hdr_len); - if (!notify_remote_frame) { - ret = qemu_chr_fe_write_all(&s->chr_out, + ret = qemu_chr_fe_write_all(sendco->chr, (uint8_t *)&len, sizeof(len)); + + if (ret != sizeof(len)) { + g_free(entry->buf); + g_slice_free(SendEntry, entry); + goto err; + } } - if (ret != sizeof(len)) { + ret = qemu_chr_fe_write_all(sendco->chr, + (uint8_t *)entry->buf, + entry->size); + + if (ret != entry->size) { + g_free(entry->buf); + g_slice_free(SendEntry, entry); goto err; } + + g_free(entry->buf); + g_slice_free(SendEntry, entry); } + sendco->ret = 0; + goto out; + +err: + while (!g_queue_is_empty(&sendco->send_list)) { + SendEntry *entry = g_queue_pop_tail(&sendco->send_list); + g_free(entry->buf); + g_slice_free(SendEntry, entry); + } + sendco->ret = ret < 0 ? ret : -EIO; +out: + sendco->co = NULL; + sendco->done = true; + aio_wait_kick(); +} + +static int compare_chr_send(CompareState *s, + uint8_t *buf, + uint32_t size, + uint32_t vnet_hdr_len, + bool notify_remote_frame, + bool zero_copy) +{ + SendCo *sendco; + SendEntry *entry; + if (notify_remote_frame) { - ret = qemu_chr_fe_write_all(&s->chr_notify_dev, - (uint8_t *)buf, - size); + sendco = &s->notify_sendco; } else { - ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size); + sendco = &s->out_sendco; } - if (ret != size) { - goto err; + if (!size) { + return 0; } - return 0; + entry = g_slice_new(SendEntry); + entry->size = size; + entry->vnet_hdr_len = vnet_hdr_len; + if (zero_copy) { + entry->buf = buf; + } else { + entry->buf = g_malloc(size); + memcpy(entry->buf, buf, size); + } + g_queue_push_head(&sendco->send_list, entry); + + if (sendco->done) { + sendco->co = qemu_coroutine_create(_compare_chr_send, sendco); + sendco->done = false; + qemu_coroutine_enter(sendco->co); + if (sendco->done) { + /* report early errors */ + return sendco->ret; + } + } -err: - return ret < 0 ? ret : -EIO; + /* assume success */ + return 0; } static int compare_chr_can_read(void *opaque) @@ -822,7 +907,7 @@ static void check_old_packet_regular(void *opaque) /* if have old packet we will notify checkpoint */ colo_old_packet_check(s); - timer_mod(s->packet_check_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + + timer_mod(s->packet_check_timer, qemu_clock_get_ms(QEMU_CLOCK_HOST) + s->expired_scan_cycle); } @@ -830,6 +915,12 @@ static void check_old_packet_regular(void *opaque) void colo_notify_compares_event(void *opaque, int event, Error **errp) { CompareState *s; + qemu_mutex_lock(&colo_compare_mutex); + + if (!colo_compare_active) { + qemu_mutex_unlock(&colo_compare_mutex); + return; + } qemu_mutex_lock(&event_mtx); QTAILQ_FOREACH(s, &net_compares, next) { @@ -843,16 +934,17 @@ void colo_notify_compares_event(void *opaque, int event, Error **errp) } qemu_mutex_unlock(&event_mtx); + qemu_mutex_unlock(&colo_compare_mutex); } static void colo_compare_timer_init(CompareState *s) { AioContext *ctx = iothread_get_aio_context(s->iothread); - s->packet_check_timer = aio_timer_new(ctx, QEMU_CLOCK_VIRTUAL, + s->packet_check_timer = aio_timer_new(ctx, QEMU_CLOCK_HOST, SCALE_MS, check_old_packet_regular, s); - timer_mod(s->packet_check_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + + timer_mod(s->packet_check_timer, qemu_clock_get_ms(QEMU_CLOCK_HOST) + s->expired_scan_cycle); } @@ -890,6 +982,7 @@ static void colo_compare_handle_event(void *opaque) static void colo_compare_iothread(CompareState *s) { + AioContext *ctx = iothread_get_aio_context(s->iothread); object_ref(OBJECT(s->iothread)); s->worker_context = iothread_get_g_main_context(s->iothread); @@ -906,7 +999,7 @@ static void colo_compare_iothread(CompareState *s) } colo_compare_timer_init(s); - s->event_bh = qemu_bh_new(colo_compare_handle_event, s); + s->event_bh = aio_bh_new(ctx, colo_compare_handle_event, s); } static char *compare_get_pri_indev(Object *obj, Error **errp) @@ -990,9 +1083,9 @@ static void compare_get_timeout(Object *obj, Visitor *v, Error **errp) { CompareState *s = COLO_COMPARE(obj); - uint32_t value = s->compare_timeout; + uint64_t value = s->compare_timeout; - visit_type_uint32(v, name, &value, errp); + visit_type_uint64(v, name, &value, errp); } static void compare_set_timeout(Object *obj, Visitor *v, @@ -1000,22 +1093,17 @@ static void compare_set_timeout(Object *obj, Visitor *v, Error **errp) { CompareState *s = COLO_COMPARE(obj); - Error *local_err = NULL; uint32_t value; - visit_type_uint32(v, name, &value, &local_err); - if (local_err) { - goto out; + if (!visit_type_uint32(v, name, &value, errp)) { + return; } if (!value) { - error_setg(&local_err, "Property '%s.%s' requires a positive value", + error_setg(errp, "Property '%s.%s' requires a positive value", object_get_typename(obj), name); - goto out; + return; } s->compare_timeout = value; - -out: - error_propagate(errp, local_err); } static void compare_get_expired_scan_cycle(Object *obj, Visitor *v, @@ -1033,10 +1121,36 @@ static void compare_set_expired_scan_cycle(Object *obj, Visitor *v, Error **errp) { CompareState *s = COLO_COMPARE(obj); - Error *local_err = NULL; uint32_t value; - visit_type_uint32(v, name, &value, &local_err); + if (!visit_type_uint32(v, name, &value, errp)) { + return; + } + if (!value) { + error_setg(errp, "Property '%s.%s' requires a positive value", + object_get_typename(obj), name); + return; + } + s->expired_scan_cycle = value; +} + +static void get_max_queue_size(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + uint32_t value = max_queue_size; + + visit_type_uint32(v, name, &value, errp); +} + +static void set_max_queue_size(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + Error *local_err = NULL; + uint64_t value; + + visit_type_uint64(v, name, &value, &local_err); if (local_err) { goto out; } @@ -1045,7 +1159,7 @@ static void compare_set_expired_scan_cycle(Object *obj, Visitor *v, object_get_typename(obj), name); goto out; } - s->expired_scan_cycle = value; + max_queue_size = value; out: error_propagate(errp, local_err); @@ -1062,6 +1176,7 @@ static void compare_pri_rs_finalize(SocketReadState *pri_rs) pri_rs->buf, pri_rs->packet_len, pri_rs->vnet_hdr_len, + false, false); } else { /* compare packet in the specified connection */ @@ -1092,7 +1207,7 @@ static void compare_notify_rs_finalize(SocketReadState *notify_rs) if (packet_matches_str("COLO_USERSPACE_PROXY_INIT", notify_rs->buf, notify_rs->packet_len)) { - ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true); + ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true, false); if (ret < 0) { error_report("Notify Xen COLO-frame INIT failed"); } @@ -1167,6 +1282,11 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp) s->expired_scan_cycle = REGULAR_PACKET_CHECK_MS; } + if (!max_queue_size) { + /* Set default queue size to 1024 */ + max_queue_size = MAX_QUEUE_SIZE; + } + if (find_and_check_chardev(&chr, s->pri_indev, errp) || !qemu_chr_fe_init(&s->chr_pri_in, chr, errp)) { return; @@ -1196,12 +1316,21 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp) s->vnet_hdr); } - QTAILQ_INSERT_TAIL(&net_compares, s, next); + s->out_sendco.s = s; + s->out_sendco.chr = &s->chr_out; + s->out_sendco.notify_remote_frame = false; + s->out_sendco.done = true; + g_queue_init(&s->out_sendco.send_list); - g_queue_init(&s->conn_list); + if (s->notify_dev) { + s->notify_sendco.s = s; + s->notify_sendco.chr = &s->chr_notify_dev; + s->notify_sendco.notify_remote_frame = true; + s->notify_sendco.done = true; + g_queue_init(&s->notify_sendco.send_list); + } - qemu_mutex_init(&event_mtx); - qemu_cond_init(&event_complete_cond); + g_queue_init(&s->conn_list); s->connection_track_table = g_hash_table_new_full(connection_key_hash, connection_key_equal, @@ -1209,6 +1338,16 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp) connection_destroy); colo_compare_iothread(s); + + qemu_mutex_lock(&colo_compare_mutex); + if (!colo_compare_active) { + qemu_mutex_init(&event_mtx); + qemu_cond_init(&event_complete_cond); + colo_compare_active = true; + } + QTAILQ_INSERT_TAIL(&net_compares, s, next); + qemu_mutex_unlock(&colo_compare_mutex); + return; } @@ -1224,8 +1363,9 @@ static void colo_flush_packets(void *opaque, void *user_data) pkt->data, pkt->size, pkt->vnet_hdr_len, - false); - packet_destroy(pkt, NULL); + false, + true); + packet_destroy_partial(pkt, NULL); } while (!g_queue_is_empty(&conn->secondary_list)) { pkt = g_queue_pop_head(&conn->secondary_list); @@ -1258,7 +1398,7 @@ static void colo_compare_init(Object *obj) object_property_add_str(obj, "notify_dev", compare_get_notify_dev, compare_set_notify_dev); - object_property_add(obj, "compare_timeout", "uint32", + object_property_add(obj, "compare_timeout", "uint64", compare_get_timeout, compare_set_timeout, NULL, NULL); @@ -1266,6 +1406,10 @@ static void colo_compare_init(Object *obj) compare_get_expired_scan_cycle, compare_set_expired_scan_cycle, NULL, NULL); + object_property_add(obj, "max_queue_size", "uint32", + get_max_queue_size, + set_max_queue_size, NULL, NULL); + s->vnet_hdr = false; object_property_add_bool(obj, "vnet_hdr_support", compare_get_vnet_hdr, compare_set_vnet_hdr); @@ -1276,6 +1420,20 @@ static void colo_compare_finalize(Object *obj) CompareState *s = COLO_COMPARE(obj); CompareState *tmp = NULL; + qemu_mutex_lock(&colo_compare_mutex); + QTAILQ_FOREACH(tmp, &net_compares, next) { + if (tmp == s) { + QTAILQ_REMOVE(&net_compares, s, next); + break; + } + } + if (QTAILQ_EMPTY(&net_compares)) { + colo_compare_active = false; + qemu_mutex_destroy(&event_mtx); + qemu_cond_destroy(&event_complete_cond); + } + qemu_mutex_unlock(&colo_compare_mutex); + qemu_chr_fe_deinit(&s->chr_pri_in, false); qemu_chr_fe_deinit(&s->chr_sec_in, false); qemu_chr_fe_deinit(&s->chr_out, false); @@ -1283,34 +1441,33 @@ static void colo_compare_finalize(Object *obj) qemu_chr_fe_deinit(&s->chr_notify_dev, false); } - if (s->iothread) { - colo_compare_timer_del(s); - } + colo_compare_timer_del(s); qemu_bh_delete(s->event_bh); - QTAILQ_FOREACH(tmp, &net_compares, next) { - if (tmp == s) { - QTAILQ_REMOVE(&net_compares, s, next); - break; - } + AioContext *ctx = iothread_get_aio_context(s->iothread); + aio_context_acquire(ctx); + AIO_WAIT_WHILE(ctx, !s->out_sendco.done); + if (s->notify_dev) { + AIO_WAIT_WHILE(ctx, !s->notify_sendco.done); } + aio_context_release(ctx); /* Release all unhandled packets after compare thead exited */ g_queue_foreach(&s->conn_list, colo_flush_packets, s); + AIO_WAIT_WHILE(NULL, !s->out_sendco.done); g_queue_clear(&s->conn_list); + g_queue_clear(&s->out_sendco.send_list); + if (s->notify_dev) { + g_queue_clear(&s->notify_sendco.send_list); + } if (s->connection_track_table) { g_hash_table_destroy(s->connection_track_table); } - if (s->iothread) { - object_unref(OBJECT(s->iothread)); - } - - qemu_mutex_destroy(&event_mtx); - qemu_cond_destroy(&event_complete_cond); + object_unref(OBJECT(s->iothread)); g_free(s->pri_indev); g_free(s->sec_indev); @@ -1318,6 +1475,12 @@ static void colo_compare_finalize(Object *obj) g_free(s->notify_dev); } +static void __attribute__((__constructor__)) colo_compare_init_globals(void) +{ + colo_compare_active = false; + qemu_mutex_init(&colo_compare_mutex); +} + static const TypeInfo colo_compare_info = { .name = TYPE_COLO_COMPARE, .parent = TYPE_OBJECT, diff --git a/net/colo.c b/net/colo.c index 8196b358370c721af4f14ae852874c50d7e1e29d..ef00609848a9ceebfa09dd7c4e4d1adb0b1be53e 100644 --- a/net/colo.c +++ b/net/colo.c @@ -133,14 +133,11 @@ void reverse_connection_key(ConnectionKey *key) Connection *connection_new(ConnectionKey *key) { - Connection *conn = g_slice_new(Connection); + Connection *conn = g_slice_new0(Connection); conn->ip_proto = key->ip_proto; conn->processing = false; - conn->offset = 0; conn->tcp_state = TCPS_CLOSED; - conn->pack = 0; - conn->sack = 0; g_queue_init(&conn->primary_list); g_queue_init(&conn->secondary_list); @@ -185,6 +182,13 @@ void packet_destroy(void *opaque, void *user_data) g_slice_free(Packet, pkt); } +void packet_destroy_partial(void *opaque, void *user_data) +{ + Packet *pkt = opaque; + + g_slice_free(Packet, pkt); +} + /* * Clear hashtable, stop this hash growing really huge */ diff --git a/net/colo.h b/net/colo.h index 679314b1cadd747b83ea3ce5281dc758930346c4..573ab91785d205debe231ac8739b62141389643a 100644 --- a/net/colo.h +++ b/net/colo.h @@ -102,5 +102,6 @@ bool connection_has_tracked(GHashTable *connection_track_table, void connection_hashtable_reset(GHashTable *connection_track_table); Packet *packet_new(const void *data, int size, int vnet_hdr_len); void packet_destroy(void *opaque, void *user_data); +void packet_destroy_partial(void *opaque, void *user_data); #endif /* NET_COLO_H */ diff --git a/net/dump.c b/net/dump.c index 61389e7dadf024412bbf60dbb6d821544e5d79b6..7fd448d2e1fe9e882b35270493e6d89611f0344b 100644 --- a/net/dump.c +++ b/net/dump.c @@ -33,6 +33,7 @@ #include "qemu/timer.h" #include "qapi/visitor.h" #include "net/filter.h" +#include "qom/object.h" typedef struct DumpState { int64_t start_ts; @@ -139,8 +140,7 @@ static int net_dump_state_init(DumpState *s, const char *filename, #define TYPE_FILTER_DUMP "filter-dump" -#define FILTER_DUMP(obj) \ - OBJECT_CHECK(NetFilterDumpState, (obj), TYPE_FILTER_DUMP) +OBJECT_DECLARE_SIMPLE_TYPE(NetFilterDumpState, FILTER_DUMP) struct NetFilterDumpState { NetFilterState nfs; @@ -148,7 +148,6 @@ struct NetFilterDumpState { char *filename; uint32_t maxlen; }; -typedef struct NetFilterDumpState NetFilterDumpState; static ssize_t filter_dump_receive_iov(NetFilterState *nf, NetClientState *sndr, unsigned flags, const struct iovec *iov, @@ -192,22 +191,17 @@ static void filter_dump_set_maxlen(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { NetFilterDumpState *nfds = FILTER_DUMP(obj); - Error *local_err = NULL; uint32_t value; - visit_type_uint32(v, name, &value, &local_err); - if (local_err) { - goto out; + if (!visit_type_uint32(v, name, &value, errp)) { + return; } if (value == 0) { - error_setg(&local_err, "Property '%s.%s' doesn't take value '%u'", + error_setg(errp, "Property '%s.%s' doesn't take value '%u'", object_get_typename(obj), name, value); - goto out; + return; } nfds->maxlen = value; - -out: - error_propagate(errp, local_err); } static char *file_dump_get_filename(Object *obj, Error **errp) diff --git a/net/eth.c b/net/eth.c index 0c1d413ee26e31d4ac6b622a9aa9b61d35356765..1e0821c5f81b59536edc5ef498e99c40f9bea319 100644 --- a/net/eth.c +++ b/net/eth.c @@ -16,6 +16,7 @@ */ #include "qemu/osdep.h" +#include "qemu/log.h" #include "net/eth.h" #include "net/checksum.h" #include "net/tap.h" @@ -71,9 +72,8 @@ eth_get_gso_type(uint16_t l3_proto, uint8_t *l3_hdr, uint8_t l4proto) return VIRTIO_NET_HDR_GSO_TCPV6 | ecn_state; } } - - /* Unsupported offload */ - g_assert_not_reached(); + qemu_log_mask(LOG_UNIMP, "%s: probably not GSO frame, " + "unknown L3 protocol: 0x%04"PRIx16"\n", __func__, l3_proto); return VIRTIO_NET_HDR_GSO_NONE | ecn_state; } diff --git a/net/filter-buffer.c b/net/filter-buffer.c index 93050f86cf34054e6e038a4b3fc62e7cc528b1df..d8392be53c7a323fb057b21c45a8178c412d5d75 100644 --- a/net/filter-buffer.c +++ b/net/filter-buffer.c @@ -18,16 +18,15 @@ #define TYPE_FILTER_BUFFER "filter-buffer" -#define FILTER_BUFFER(obj) \ - OBJECT_CHECK(FilterBufferState, (obj), TYPE_FILTER_BUFFER) +OBJECT_DECLARE_SIMPLE_TYPE(FilterBufferState, FILTER_BUFFER) -typedef struct FilterBufferState { +struct FilterBufferState { NetFilterState parent_obj; NetQueue *incoming_queue; uint32_t interval; QEMUTimer release_timer; -} FilterBufferState; +}; static void filter_buffer_flush(NetFilterState *nf) { @@ -170,22 +169,17 @@ static void filter_buffer_set_interval(Object *obj, Visitor *v, Error **errp) { FilterBufferState *s = FILTER_BUFFER(obj); - Error *local_err = NULL; uint32_t value; - visit_type_uint32(v, name, &value, &local_err); - if (local_err) { - goto out; + if (!visit_type_uint32(v, name, &value, errp)) { + return; } if (!value) { - error_setg(&local_err, "Property '%s.%s' requires a positive value", + error_setg(errp, "Property '%s.%s' requires a positive value", object_get_typename(obj), name); - goto out; + return; } s->interval = value; - -out: - error_propagate(errp, local_err); } static void filter_buffer_init(Object *obj) diff --git a/net/filter-mirror.c b/net/filter-mirror.c index e9379ce24871ac4d5ce4ee162e53678d5efb25ac..088d4dcaceb2576f5513f2fceba3131b7ae67aa8 100644 --- a/net/filter-mirror.c +++ b/net/filter-mirror.c @@ -21,17 +21,18 @@ #include "qemu/iov.h" #include "qemu/sockets.h" -#define FILTER_MIRROR(obj) \ - OBJECT_CHECK(MirrorState, (obj), TYPE_FILTER_MIRROR) - -#define FILTER_REDIRECTOR(obj) \ - OBJECT_CHECK(MirrorState, (obj), TYPE_FILTER_REDIRECTOR) - #define TYPE_FILTER_MIRROR "filter-mirror" +typedef struct MirrorState MirrorState; +DECLARE_INSTANCE_CHECKER(MirrorState, FILTER_MIRROR, + TYPE_FILTER_MIRROR) + #define TYPE_FILTER_REDIRECTOR "filter-redirector" +DECLARE_INSTANCE_CHECKER(MirrorState, FILTER_REDIRECTOR, + TYPE_FILTER_REDIRECTOR) + #define REDIRECTOR_MAX_LEN NET_BUFSIZE -typedef struct MirrorState { +struct MirrorState { NetFilterState parent_obj; char *indev; char *outdev; @@ -39,7 +40,7 @@ typedef struct MirrorState { CharBackend chr_out; SocketReadState rs; bool vnet_hdr; -} MirrorState; +}; static int filter_send(MirrorState *s, const struct iovec *iov, diff --git a/net/filter-replay.c b/net/filter-replay.c index 9dda1939283cfc117076a126f238e681e97d4e55..eef8443059b5fe3523a02a4c3e6530f0654b6453 100644 --- a/net/filter-replay.c +++ b/net/filter-replay.c @@ -19,17 +19,16 @@ #include "qapi/visitor.h" #include "net/filter.h" #include "sysemu/replay.h" +#include "qom/object.h" #define TYPE_FILTER_REPLAY "filter-replay" -#define FILTER_REPLAY(obj) \ - OBJECT_CHECK(NetFilterReplayState, (obj), TYPE_FILTER_REPLAY) +OBJECT_DECLARE_SIMPLE_TYPE(NetFilterReplayState, FILTER_REPLAY) struct NetFilterReplayState { NetFilterState nfs; ReplayNetState *rns; }; -typedef struct NetFilterReplayState NetFilterReplayState; static ssize_t filter_replay_receive_iov(NetFilterState *nf, NetClientState *sndr, diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c index 1aaad101b6a6668375173ec2990b5bc451d0d00b..e063a818b7e46eb5935ffbf0e174e61b5848d739 100644 --- a/net/filter-rewriter.c +++ b/net/filter-rewriter.c @@ -23,21 +23,20 @@ #include "migration/colo.h" #include "util.h" -#define FILTER_COLO_REWRITER(obj) \ - OBJECT_CHECK(RewriterState, (obj), TYPE_FILTER_REWRITER) - #define TYPE_FILTER_REWRITER "filter-rewriter" +OBJECT_DECLARE_SIMPLE_TYPE(RewriterState, FILTER_REWRITER) + #define FAILOVER_MODE_ON true #define FAILOVER_MODE_OFF false -typedef struct RewriterState { +struct RewriterState { NetFilterState parent_obj; NetQueue *incoming_queue; /* hashtable to save connection */ GHashTable *connection_track_table; bool vnet_hdr; bool failover_mode; -} RewriterState; +}; static void filter_rewriter_failover_mode(RewriterState *s) { @@ -46,7 +45,7 @@ static void filter_rewriter_failover_mode(RewriterState *s) static void filter_rewriter_flush(NetFilterState *nf) { - RewriterState *s = FILTER_COLO_REWRITER(nf); + RewriterState *s = FILTER_REWRITER(nf); if (!qemu_net_queue_flush(s->incoming_queue)) { /* Unable to empty the queue, purge remaining packets */ @@ -76,11 +75,14 @@ static int handle_primary_tcp_pkt(RewriterState *rf, struct tcp_hdr *tcp_pkt; tcp_pkt = (struct tcp_hdr *)pkt->transport_header; - if (trace_event_get_state_backends(TRACE_COLO_FILTER_REWRITER_DEBUG)) { + if (trace_event_get_state_backends(TRACE_COLO_FILTER_REWRITER_PKT_INFO)) { trace_colo_filter_rewriter_pkt_info(__func__, inet_ntoa(pkt->ip->ip_src), inet_ntoa(pkt->ip->ip_dst), ntohl(tcp_pkt->th_seq), ntohl(tcp_pkt->th_ack), tcp_pkt->th_flags); + } + if (trace_event_get_state_backends( + TRACE_COLO_FILTER_REWRITER_CONN_OFFSET)) { trace_colo_filter_rewriter_conn_offset(conn->offset); } @@ -180,11 +182,14 @@ static int handle_secondary_tcp_pkt(RewriterState *rf, tcp_pkt = (struct tcp_hdr *)pkt->transport_header; - if (trace_event_get_state_backends(TRACE_COLO_FILTER_REWRITER_DEBUG)) { + if (trace_event_get_state_backends(TRACE_COLO_FILTER_REWRITER_PKT_INFO)) { trace_colo_filter_rewriter_pkt_info(__func__, inet_ntoa(pkt->ip->ip_src), inet_ntoa(pkt->ip->ip_dst), ntohl(tcp_pkt->th_seq), ntohl(tcp_pkt->th_ack), tcp_pkt->th_flags); + } + if (trace_event_get_state_backends( + TRACE_COLO_FILTER_REWRITER_CONN_OFFSET)) { trace_colo_filter_rewriter_conn_offset(conn->offset); } @@ -251,7 +256,7 @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf, int iovcnt, NetPacketSent *sent_cb) { - RewriterState *s = FILTER_COLO_REWRITER(nf); + RewriterState *s = FILTER_REWRITER(nf); Connection *conn; ConnectionKey key; Packet *pkt; @@ -349,7 +354,7 @@ static gboolean offset_is_nonzero(gpointer key, static void colo_rewriter_handle_event(NetFilterState *nf, int event, Error **errp) { - RewriterState *rs = FILTER_COLO_REWRITER(nf); + RewriterState *rs = FILTER_REWRITER(nf); switch (event) { case COLO_EVENT_CHECKPOINT: @@ -369,18 +374,20 @@ static void colo_rewriter_handle_event(NetFilterState *nf, int event, static void colo_rewriter_cleanup(NetFilterState *nf) { - RewriterState *s = FILTER_COLO_REWRITER(nf); + RewriterState *s = FILTER_REWRITER(nf); /* flush packets */ if (s->incoming_queue) { filter_rewriter_flush(nf); g_free(s->incoming_queue); } + + g_hash_table_destroy(s->connection_track_table); } static void colo_rewriter_setup(NetFilterState *nf, Error **errp) { - RewriterState *s = FILTER_COLO_REWRITER(nf); + RewriterState *s = FILTER_REWRITER(nf); s->connection_track_table = g_hash_table_new_full(connection_key_hash, connection_key_equal, @@ -391,7 +398,7 @@ static void colo_rewriter_setup(NetFilterState *nf, Error **errp) static bool filter_rewriter_get_vnet_hdr(Object *obj, Error **errp) { - RewriterState *s = FILTER_COLO_REWRITER(obj); + RewriterState *s = FILTER_REWRITER(obj); return s->vnet_hdr; } @@ -400,14 +407,14 @@ static void filter_rewriter_set_vnet_hdr(Object *obj, bool value, Error **errp) { - RewriterState *s = FILTER_COLO_REWRITER(obj); + RewriterState *s = FILTER_REWRITER(obj); s->vnet_hdr = value; } static void filter_rewriter_init(Object *obj) { - RewriterState *s = FILTER_COLO_REWRITER(obj); + RewriterState *s = FILTER_REWRITER(obj); s->vnet_hdr = false; s->failover_mode = FAILOVER_MODE_OFF; diff --git a/net/filter.c b/net/filter.c index caf64436554708c4ee5321825a38d9d7a164bff1..eac8ba1e9c896ce1afb1705db19187fa39fa09ec 100644 --- a/net/filter.c +++ b/net/filter.c @@ -338,7 +338,7 @@ static void default_handle_event(NetFilterState *nf, int event, Error **errp) case COLO_EVENT_CHECKPOINT: break; case COLO_EVENT_FAILOVER: - object_property_set_str(OBJECT(nf), "off", "status", errp); + object_property_set_str(OBJECT(nf), "status", "off", errp); break; default: break; diff --git a/net/l2tpv3.c b/net/l2tpv3.c index 55fea17c0f0dfd6fe308efe730fedd711e72fd09..e4d4218db6984ce9aa940100582ca7971180336f 100644 --- a/net/l2tpv3.c +++ b/net/l2tpv3.c @@ -655,9 +655,8 @@ int net_init_l2tpv3(const Netdev *netdev, error_setg(errp, "could not bind socket err=%i", errno); goto outerr; } - if (result) { - freeaddrinfo(result); - } + + freeaddrinfo(result); memset(&hints, 0, sizeof(hints)); @@ -686,9 +685,7 @@ int net_init_l2tpv3(const Netdev *netdev, memcpy(s->dgram_dst, result->ai_addr, result->ai_addrlen); s->dst_size = result->ai_addrlen; - if (result) { - freeaddrinfo(result); - } + freeaddrinfo(result); if (l2tpv3->has_counter && l2tpv3->counter) { s->has_counter = true; diff --git a/net/meson.build b/net/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..1076b0a7ab43a86718d3e0da05d418d5544bb6bf --- /dev/null +++ b/net/meson.build @@ -0,0 +1,41 @@ +softmmu_ss.add(files( + 'announce.c', + 'checksum.c', + 'colo-compare.c', + 'colo.c', + 'dump.c', + 'eth.c', + 'filter-buffer.c', + 'filter-mirror.c', + 'filter-rewriter.c', + 'filter.c', + 'hub.c', + 'net.c', + 'queue.c', + 'socket.c', + 'util.c', +)) + +softmmu_ss.add(when: 'CONFIG_TCG', if_true: files('filter-replay.c')) + +softmmu_ss.add(when: 'CONFIG_L2TPV3', if_true: files('l2tpv3.c')) +softmmu_ss.add(when: slirp, if_true: files('slirp.c')) +softmmu_ss.add(when: ['CONFIG_VDE', vde], if_true: files('vde.c')) +softmmu_ss.add(when: 'CONFIG_NETMAP', if_true: files('netmap.c')) +vhost_user_ss = ss.source_set() +vhost_user_ss.add(when: 'CONFIG_VIRTIO_NET', if_true: files('vhost-user.c'), if_false: files('vhost-user-stub.c')) +softmmu_ss.add_all(when: 'CONFIG_VHOST_NET_USER', if_true: vhost_user_ss) +softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('vhost-user-stub.c')) + +softmmu_ss.add(when: 'CONFIG_LINUX', if_true: files('tap-linux.c')) +softmmu_ss.add(when: 'CONFIG_BSD', if_true: files('tap-bsd.c')) +softmmu_ss.add(when: 'CONFIG_SOLARIS', if_true: files('tap-solaris.c')) +tap_posix = ['tap.c'] +if not config_host.has_key('CONFIG_LINUX') and not config_host.has_key('CONFIG_BSD') and not config_host.has_key('CONFIG_SOLARIS') + tap_posix += 'tap-stub.c' +endif +softmmu_ss.add(when: 'CONFIG_POSIX', if_true: files(tap_posix)) +softmmu_ss.add(when: 'CONFIG_WIN32', if_true: files('tap-win32.c')) +softmmu_ss.add(when: 'CONFIG_VHOST_NET_VDPA', if_true: files('vhost-vdpa.c')) + +subdir('can') diff --git a/net/net.c b/net/net.c index 38778e831da2a3b3483c6a55abfdc46a236ccd30..6a2c3d95670ed5fec780782763011b71ca9a949d 100644 --- a/net/net.c +++ b/net/net.c @@ -44,6 +44,7 @@ #include "qemu/config-file.h" #include "qemu/ctype.h" #include "qemu/iov.h" +#include "qemu/qemu-print.h" #include "qemu/main-loop.h" #include "qemu/option.h" #include "qapi/error.h" @@ -325,6 +326,13 @@ void *qemu_get_nic_opaque(NetClientState *nc) return nic->opaque; } +NetClientState *qemu_get_peer(NetClientState *nc, int queue_index) +{ + assert(nc != NULL); + NetClientState *ncs = nc + queue_index; + return ncs->peer; +} + static void qemu_cleanup_net_client(NetClientState *nc) { QTAILQ_REMOVE(&net_clients, nc, next); @@ -404,10 +412,14 @@ void qemu_del_nic(NICState *nic) qemu_macaddr_set_free(&nic->conf->macaddr); - /* If this is a peer NIC and peer has already been deleted, free it now. */ - if (nic->peer_deleted) { - for (i = 0; i < queues; i++) { - qemu_free_net_client(qemu_get_subqueue(nic, i)->peer); + for (i = 0; i < queues; i++) { + NetClientState *nc = qemu_get_subqueue(nic, i); + /* If this is a peer NIC and peer has already been deleted, free it now. */ + if (nic->peer_deleted) { + qemu_free_net_client(nc->peer); + } else if (nc->peer) { + /* if there are RX packets pending, complete them */ + qemu_purge_queued_packets(nc->peer); } } @@ -610,7 +622,7 @@ void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge) qemu_notify_event(); } else if (purge) { /* Unable to empty the queue, purge remaining packets */ - qemu_net_queue_purge(nc->incoming_queue, nc); + qemu_net_queue_purge(nc->incoming_queue, nc->peer); } } @@ -629,7 +641,7 @@ static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender, #ifdef DEBUG_NET printf("qemu_send_packet_async:\n"); - qemu_hexdump((const char *)buf, stdout, "net", size); + qemu_hexdump(stdout, "net", buf, size); #endif if (sender->link_down || !sender->peer) { @@ -959,23 +971,20 @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])( #ifdef CONFIG_VHOST_NET_USER [NET_CLIENT_DRIVER_VHOST_USER] = net_init_vhost_user, #endif +#ifdef CONFIG_VHOST_NET_VDPA + [NET_CLIENT_DRIVER_VHOST_VDPA] = net_init_vhost_vdpa, +#endif #ifdef CONFIG_L2TPV3 [NET_CLIENT_DRIVER_L2TPV3] = net_init_l2tpv3, #endif }; -static int net_client_init1(const void *object, bool is_netdev, Error **errp) +static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp) { - Netdev legacy = {0}; - const Netdev *netdev; - const char *name; NetClientState *peer = NULL; if (is_netdev) { - netdev = object; - name = netdev->id; - if (netdev->type == NET_CLIENT_DRIVER_NIC || !net_client_init_fun[netdev->type]) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type", @@ -983,62 +992,11 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp) return -1; } } else { - const NetLegacy *net = object; - const NetLegacyOptions *opts = net->opts; - legacy.id = net->id; - netdev = &legacy; - /* missing optional values have been initialized to "all bits zero" */ - name = net->has_id ? net->id : net->name; - - if (net->has_name) { - warn_report("The 'name' parameter is deprecated, use 'id' instead"); - } - - /* Map the old options to the new flat type */ - switch (opts->type) { - case NET_LEGACY_OPTIONS_TYPE_NONE: + if (netdev->type == NET_CLIENT_DRIVER_NONE) { return 0; /* nothing to do */ - case NET_LEGACY_OPTIONS_TYPE_NIC: - legacy.type = NET_CLIENT_DRIVER_NIC; - legacy.u.nic = opts->u.nic; - break; - case NET_LEGACY_OPTIONS_TYPE_USER: - legacy.type = NET_CLIENT_DRIVER_USER; - legacy.u.user = opts->u.user; - break; - case NET_LEGACY_OPTIONS_TYPE_TAP: - legacy.type = NET_CLIENT_DRIVER_TAP; - legacy.u.tap = opts->u.tap; - break; - case NET_LEGACY_OPTIONS_TYPE_L2TPV3: - legacy.type = NET_CLIENT_DRIVER_L2TPV3; - legacy.u.l2tpv3 = opts->u.l2tpv3; - break; - case NET_LEGACY_OPTIONS_TYPE_SOCKET: - legacy.type = NET_CLIENT_DRIVER_SOCKET; - legacy.u.socket = opts->u.socket; - break; - case NET_LEGACY_OPTIONS_TYPE_VDE: - legacy.type = NET_CLIENT_DRIVER_VDE; - legacy.u.vde = opts->u.vde; - break; - case NET_LEGACY_OPTIONS_TYPE_BRIDGE: - legacy.type = NET_CLIENT_DRIVER_BRIDGE; - legacy.u.bridge = opts->u.bridge; - break; - case NET_LEGACY_OPTIONS_TYPE_NETMAP: - legacy.type = NET_CLIENT_DRIVER_NETMAP; - legacy.u.netmap = opts->u.netmap; - break; - case NET_LEGACY_OPTIONS_TYPE_VHOST_USER: - legacy.type = NET_CLIENT_DRIVER_VHOST_USER; - legacy.u.vhost_user = opts->u.vhost_user; - break; - default: - abort(); } - - if (!net_client_init_fun[netdev->type]) { + if (netdev->type == NET_CLIENT_DRIVER_HUBPORT || + !net_client_init_fun[netdev->type]) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type", "a net backend type (maybe it is not compiled " "into this binary)"); @@ -1047,12 +1005,12 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp) /* Do not add to a hub if it's a nic with a netdev= parameter. */ if (netdev->type != NET_CLIENT_DRIVER_NIC || - !opts->u.nic.has_netdev) { + !netdev->u.nic.has_netdev) { peer = net_hub_add_port(0, NULL, NULL); } } - if (net_client_init_fun[netdev->type](netdev, name, peer, errp) < 0) { + if (net_client_init_fun[netdev->type](netdev, netdev->id, peer, errp) < 0) { /* FIXME drop when all init functions store an Error */ if (errp && !*errp) { error_setg(errp, QERR_DEVICE_INIT_FAILED, @@ -1072,7 +1030,7 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp) return 0; } -static void show_netdevs(void) +void show_netdevs(void) { int idx; const char *available_netdevs[] = { @@ -1096,79 +1054,69 @@ static void show_netdevs(void) #endif #ifdef CONFIG_POSIX "vhost-user", +#endif +#ifdef CONFIG_VHOST_VDPA + "vhost-vdpa", #endif }; - printf("Available netdev backend types:\n"); + qemu_printf("Available netdev backend types:\n"); for (idx = 0; idx < ARRAY_SIZE(available_netdevs); idx++) { - puts(available_netdevs[idx]); + qemu_printf("%s\n", available_netdevs[idx]); } } static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) { gchar **substrings = NULL; - void *object = NULL; - Error *err = NULL; + Netdev *object = NULL; int ret = -1; Visitor *v = opts_visitor_new(opts); - const char *type = qemu_opt_get(opts, "type"); - - if (is_netdev && type && is_help_option(type)) { - show_netdevs(); - exit(0); - } else { - /* Parse convenience option format ip6-net=fec0::0[/64] */ - const char *ip6_net = qemu_opt_get(opts, "ipv6-net"); - - if (ip6_net) { - char *prefix_addr; - unsigned long prefix_len = 64; /* Default 64bit prefix length. */ + /* Parse convenience option format ip6-net=fec0::0[/64] */ + const char *ip6_net = qemu_opt_get(opts, "ipv6-net"); - substrings = g_strsplit(ip6_net, "/", 2); - if (!substrings || !substrings[0]) { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net", - "a valid IPv6 prefix"); - goto out; - } + if (ip6_net) { + char *prefix_addr; + unsigned long prefix_len = 64; /* Default 64bit prefix length. */ - prefix_addr = substrings[0]; + substrings = g_strsplit(ip6_net, "/", 2); + if (!substrings || !substrings[0]) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net", + "a valid IPv6 prefix"); + goto out; + } - /* Handle user-specified prefix length. */ - if (substrings[1] && - qemu_strtoul(substrings[1], NULL, 10, &prefix_len)) - { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, - "ipv6-prefixlen", "a number"); - goto out; - } + prefix_addr = substrings[0]; - qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort); - qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len, - &error_abort); - qemu_opt_unset(opts, "ipv6-net"); + /* Handle user-specified prefix length. */ + if (substrings[1] && + qemu_strtoul(substrings[1], NULL, 10, &prefix_len)) + { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + "ipv6-prefixlen", "a number"); + goto out; } - } - if (is_netdev) { - visit_type_Netdev(v, NULL, (Netdev **)&object, &err); - } else { - visit_type_NetLegacy(v, NULL, (NetLegacy **)&object, &err); + qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort); + qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len, + &error_abort); + qemu_opt_unset(opts, "ipv6-net"); } - if (!err) { - ret = net_client_init1(object, is_netdev, &err); + /* Create an ID for -net if the user did not specify one */ + if (!is_netdev && !qemu_opts_id(opts)) { + static int idx; + qemu_opts_set_id(opts, g_strdup_printf("__org.qemu.net%i", idx++)); } - if (is_netdev) { - qapi_free_Netdev(object); - } else { - qapi_free_NetLegacy(object); + if (visit_type_Netdev(v, NULL, &object, errp)) { + ret = net_client_init1(object, is_netdev, errp); } + qapi_free_Netdev(object); + out: - error_propagate(errp, err); g_strfreev(substrings); visit_free(v); return ret; @@ -1217,7 +1165,7 @@ static void netfilter_print_info(Monitor *mon, NetFilterState *nf) continue; } v = string_output_visitor_new(false, &str); - object_property_get(OBJECT(nf), v, prop->name, NULL); + object_property_get(OBJECT(nf), prop->name, v, NULL); visit_complete(v, &str); visit_free(v); monitor_printf(mon, ",%s=%s", prop->name, str); @@ -1238,12 +1186,10 @@ void print_net_client(Monitor *mon, NetClientState *nc) monitor_printf(mon, "filters:\n"); } QTAILQ_FOREACH(nf, &nc->filters, next) { - char *path = object_get_canonical_path_component(OBJECT(nf)); - - monitor_printf(mon, " - %s: type=%s", path, + monitor_printf(mon, " - %s: type=%s", + object_get_canonical_path_component(OBJECT(nf)), object_get_typename(OBJECT(nf))); netfilter_print_info(mon, nf); - g_free(path); } } @@ -1473,6 +1419,12 @@ static int net_init_client(void *dummy, QemuOpts *opts, Error **errp) static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp) { + const char *type = qemu_opt_get(opts, "type"); + + if (type && is_help_option(type)) { + show_netdevs(); + exit(0); + } return net_client_init(opts, true, errp); } @@ -1506,7 +1458,7 @@ static int net_param_nic(void *dummy, QemuOpts *opts, Error **errp) /* Create an ID if the user did not specify one */ nd_id = g_strdup(qemu_opts_id(opts)); if (!nd_id) { - nd_id = g_strdup_printf("__org.qemu.nic%i\n", idx); + nd_id = g_strdup_printf("__org.qemu.nic%i", idx); qemu_opts_set_id(opts, nd_id); } diff --git a/net/queue.c b/net/queue.c index 0164727e39ad507857225d93a0886f5c24dfaad3..19e32c80fda730604fe7febf421f53cfdece567a 100644 --- a/net/queue.c +++ b/net/queue.c @@ -250,6 +250,9 @@ void qemu_net_queue_purge(NetQueue *queue, NetClientState *from) bool qemu_net_queue_flush(NetQueue *queue) { + if (queue->delivering) + return false; + while (!QTAILQ_EMPTY(&queue->packets)) { NetPacket *packet; int ret; diff --git a/net/socket.c b/net/socket.c index c92354049bcaee7581045174a503365eb27a4c40..15b410e8d82541ae86b980e4f0d68ddd06334541 100644 --- a/net/socket.c +++ b/net/socket.c @@ -725,13 +725,18 @@ int net_init_socket(const Netdev *netdev, const char *name, } if (sock->has_fd) { - int fd; + int fd, ret; - fd = monitor_fd_param(cur_mon, sock->fd, errp); + fd = monitor_fd_param(monitor_cur(), sock->fd, errp); if (fd == -1) { return -1; } - qemu_set_nonblock(fd); + ret = qemu_try_set_nonblock(fd); + if (ret < 0) { + error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", + name, fd); + return -1; + } if (!net_socket_fd_init(peer, "socket", name, fd, 1, sock->mcast, errp)) { return -1; diff --git a/net/tap-bsd.c b/net/tap-bsd.c index a5c3707f806d7699e2a552b771b77c3dedd66269..77aaf674b19dd498ba607045594dc869947c7c50 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -211,7 +211,7 @@ void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp) { } -int tap_probe_vnet_hdr(int fd) +int tap_probe_vnet_hdr(int fd, Error **errp) { return 0; } diff --git a/net/tap-linux.c b/net/tap-linux.c index e0dd442ee34fe51e7c3c072f8bfc4a5d5286c862..b0635e9e32cea525bdca424aa21a28b66056e2a1 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -147,13 +147,15 @@ void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp) } } -int tap_probe_vnet_hdr(int fd) +int tap_probe_vnet_hdr(int fd, Error **errp) { struct ifreq ifr; if (ioctl(fd, TUNGETIFF, &ifr) != 0) { - error_report("TUNGETIFF ioctl() failed: %s", strerror(errno)); - return 0; + /* TUNGETIFF is available since kernel v2.6.27 */ + error_setg_errno(errp, errno, + "Unable to query TUNGETIFF on FD %d", fd); + return -1; } return ifr.ifr_flags & IFF_VNET_HDR; diff --git a/net/tap-solaris.c b/net/tap-solaris.c index 4725d2314eef709f2156300a7bb7973144524301..0475a58207b1bae1d5d3987c466acf1864afb11a 100644 --- a/net/tap-solaris.c +++ b/net/tap-solaris.c @@ -27,6 +27,7 @@ #include "tap_int.h" #include "qemu/ctype.h" #include "qemu/cutils.h" +#include "qemu-common.h" #include #include @@ -206,7 +207,7 @@ void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp) { } -int tap_probe_vnet_hdr(int fd) +int tap_probe_vnet_hdr(int fd, Error **errp) { return 0; } diff --git a/net/tap-stub.c b/net/tap-stub.c index a9ab8f8293620644d603f49a14067763b71bfb89..de525a2e69d4b61258d884815fa55b4a4fcc96e7 100644 --- a/net/tap-stub.c +++ b/net/tap-stub.c @@ -37,7 +37,7 @@ void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp) { } -int tap_probe_vnet_hdr(int fd) +int tap_probe_vnet_hdr(int fd, Error **errp) { return 0; } diff --git a/net/tap.c b/net/tap.c index 6207f61f84abd7735723adec4ad0f71fafe5fa10..b7512853f46c07b3a5b13d52418c2ce28da3db85 100644 --- a/net/tap.c +++ b/net/tap.c @@ -254,7 +254,8 @@ static void tap_set_vnet_hdr_len(NetClientState *nc, int len) assert(nc->info->type == NET_CLIENT_DRIVER_TAP); assert(len == sizeof(struct virtio_net_hdr_mrg_rxbuf) || - len == sizeof(struct virtio_net_hdr)); + len == sizeof(struct virtio_net_hdr) || + len == sizeof(struct virtio_net_hdr_v1_hash)); tap_fd_set_vnet_hdr_len(s->fd, len); s->host_vnet_hdr_len = len; @@ -477,6 +478,7 @@ static int net_bridge_run_helper(const char *helper, const char *bridge, Error **errp) { sigset_t oldmask, mask; + g_autofree char *default_helper = NULL; int pid, status; char *args[5]; char **parg; @@ -486,6 +488,10 @@ static int net_bridge_run_helper(const char *helper, const char *bridge, sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, &oldmask); + if (!helper) { + helper = default_helper = get_relocated_path(DEFAULT_BRIDGE_HELPER); + } + if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) { error_setg_errno(errp, errno, "socketpair() failed"); return -1; @@ -587,8 +593,7 @@ int net_init_bridge(const Netdev *netdev, const char *name, assert(netdev->type == NET_CLIENT_DRIVER_BRIDGE); bridge = &netdev->u.bridge; - - helper = bridge->has_helper ? bridge->helper : DEFAULT_BRIDGE_HELPER; + helper = bridge->has_helper ? bridge->helper : NULL; br = bridge->has_br ? bridge->br : DEFAULT_BRIDGE_INTERFACE; fd = net_bridge_run_helper(helper, br, errp); @@ -597,7 +602,11 @@ int net_init_bridge(const Netdev *netdev, const char *name, } qemu_set_nonblock(fd); - vnet_hdr = tap_probe_vnet_hdr(fd); + vnet_hdr = tap_probe_vnet_hdr(fd, errp); + if (vnet_hdr < 0) { + close(fd); + return -1; + } s = net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr); snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s,br=%s", helper, @@ -689,7 +698,9 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, } if (vhostfdname) { - vhostfd = monitor_fd_param(cur_mon, vhostfdname, &err); + int ret; + + vhostfd = monitor_fd_param(monitor_cur(), vhostfdname, &err); if (vhostfd == -1) { if (tap->has_vhostforce && tap->vhostforce) { error_propagate(errp, err); @@ -698,7 +709,12 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, } return; } - qemu_set_nonblock(vhostfd); + ret = qemu_try_set_nonblock(vhostfd); + if (ret < 0) { + error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", + name, fd); + return; + } } else { vhostfd = open("/dev/vhost-net", O_RDWR); if (vhostfd < 0) { @@ -761,16 +777,19 @@ int net_init_tap(const Netdev *netdev, const char *name, const NetdevTapOptions *tap; int fd, vnet_hdr = 0, i = 0, queues; /* for the no-fd, no-helper case */ - const char *script = NULL; /* suppress wrong "uninit'd use" gcc warning */ - const char *downscript = NULL; + const char *script; + const char *downscript; Error *err = NULL; const char *vhostfdname; char ifname[128]; + int ret = 0; assert(netdev->type == NET_CLIENT_DRIVER_TAP); tap = &netdev->u.tap; queues = tap->has_queues ? tap->queues : 1; vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL; + script = tap->has_script ? tap->script : NULL; + downscript = tap->has_downscript ? tap->downscript : NULL; /* QEMU hubs do not support multiqueue tap, in this case peer is set. * For -netdev, peer is always NULL. */ @@ -789,28 +808,37 @@ int net_init_tap(const Netdev *netdev, const char *name, return -1; } - fd = monitor_fd_param(cur_mon, tap->fd, &err); + fd = monitor_fd_param(monitor_cur(), tap->fd, errp); if (fd == -1) { - error_propagate(errp, err); return -1; } - qemu_set_nonblock(fd); + ret = qemu_try_set_nonblock(fd); + if (ret < 0) { + error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", + name, fd); + close(fd); + return -1; + } - vnet_hdr = tap_probe_vnet_hdr(fd); + vnet_hdr = tap_probe_vnet_hdr(fd, errp); + if (vnet_hdr < 0) { + close(fd); + return -1; + } net_init_tap_one(tap, peer, "tap", name, NULL, script, downscript, vhostfdname, vnet_hdr, fd, &err); if (err) { error_propagate(errp, err); + close(fd); return -1; } } else if (tap->has_fds) { char **fds; char **vhost_fds; int nfds = 0, nvhosts = 0; - int ret = 0; if (tap->has_ifname || tap->has_script || tap->has_downscript || tap->has_vnet_hdr || tap->has_helper || tap->has_queues || @@ -836,18 +864,25 @@ int net_init_tap(const Netdev *netdev, const char *name, } for (i = 0; i < nfds; i++) { - fd = monitor_fd_param(cur_mon, fds[i], &err); + fd = monitor_fd_param(monitor_cur(), fds[i], errp); if (fd == -1) { - error_propagate(errp, err); ret = -1; goto free_fail; } - qemu_set_nonblock(fd); + ret = qemu_try_set_nonblock(fd); + if (ret < 0) { + error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", + name, fd); + goto free_fail; + } if (i == 0) { - vnet_hdr = tap_probe_vnet_hdr(fd); - } else if (vnet_hdr != tap_probe_vnet_hdr(fd)) { + vnet_hdr = tap_probe_vnet_hdr(fd, errp); + if (vnet_hdr < 0) { + goto free_fail; + } + } else if (vnet_hdr != tap_probe_vnet_hdr(fd, NULL)) { error_setg(errp, "vnet_hdr not consistent across given tap fds"); ret = -1; @@ -892,7 +927,11 @@ free_fail: } qemu_set_nonblock(fd); - vnet_hdr = tap_probe_vnet_hdr(fd); + vnet_hdr = tap_probe_vnet_hdr(fd, errp); + if (vnet_hdr < 0) { + close(fd); + return -1; + } net_init_tap_one(tap, peer, "bridge", name, ifname, script, downscript, vhostfdname, @@ -903,13 +942,20 @@ free_fail: return -1; } } else { + g_autofree char *default_script = NULL; + g_autofree char *default_downscript = NULL; if (tap->has_vhostfds) { error_setg(errp, "vhostfds= is invalid if fds= wasn't specified"); return -1; } - script = tap->has_script ? tap->script : DEFAULT_NETWORK_SCRIPT; - downscript = tap->has_downscript ? tap->downscript : - DEFAULT_NETWORK_DOWN_SCRIPT; + + if (!script) { + script = default_script = get_relocated_path(DEFAULT_NETWORK_SCRIPT); + } + if (!downscript) { + downscript = default_downscript = + get_relocated_path(DEFAULT_NETWORK_DOWN_SCRIPT); + } if (tap->has_ifname) { pstrcpy(ifname, sizeof ifname, tap->ifname); diff --git a/net/tap_int.h b/net/tap_int.h index e3194b23f47d7c29919b5ac69c5af3fa3b514175..225a49ea484382d4d166804bc6feb42711e1949b 100644 --- a/net/tap_int.h +++ b/net/tap_int.h @@ -34,7 +34,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen); void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp); -int tap_probe_vnet_hdr(int fd); +int tap_probe_vnet_hdr(int fd, Error **errp); int tap_probe_vnet_hdr_len(int fd, int len); int tap_probe_has_ufo(int fd); void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo); diff --git a/net/trace-events b/net/trace-events index 02c13fd0babeb87aac39afb29c640e2852b85389..bfaff7891d47478454b82f1c61cf681eb58251b3 100644 --- a/net/trace-events +++ b/net/trace-events @@ -12,14 +12,13 @@ colo_proxy_main(const char *chr) ": %s" # colo-compare.c colo_compare_main(const char *chr) ": %s" +colo_compare_drop_packet(const char *queue, const char *chr) ": %s: %s" colo_compare_udp_miscompare(const char *sta, int size) ": %s = %d" colo_compare_icmp_miscompare(const char *sta, int size) ": %s = %d" colo_compare_ip_info(int psize, const char *sta, const char *stb, int ssize, const char *stc, const char *std) "ppkt size = %d, ip_src = %s, ip_dst = %s, spkt size = %d, ip_src = %s, ip_dst = %s" colo_old_packet_check_found(int64_t old_time) "%" PRId64 -colo_compare_miscompare(void) "" colo_compare_tcp_info(const char *pkt, uint32_t seq, uint32_t ack, int hdlen, int pdlen, int offset, int flags) "%s: seq/ack= %u/%u hdlen= %d pdlen= %d offset= %d flags=%d" # filter-rewriter.c -colo_filter_rewriter_debug(void) "" colo_filter_rewriter_pkt_info(const char *func, const char *src, const char *dst, uint32_t seq, uint32_t ack, uint32_t flag) "%s: src/dst: %s/%s p: seq/ack=%u/%u flags=0x%x" colo_filter_rewriter_conn_offset(uint32_t offset) ": offset=%u" diff --git a/net/trace.h b/net/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..18d42c29b626583d315a3606c04ec9830f20988b --- /dev/null +++ b/net/trace.h @@ -0,0 +1 @@ +#include "trace/trace-net.h" diff --git a/net/vhost-user.c b/net/vhost-user.c index 17532daaf32e31392c1036ffad3dde0532899192..ffbd94d944faa08ad8ffc91a548661a653fd0470 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -226,7 +226,7 @@ static void chr_closed_bh(void *opaque) NetClientState *ncs[MAX_QUEUE_NUM]; NetVhostUserState *s; Error *err = NULL; - int queues; + int queues, i; queues = qemu_find_net_clients_except(name, ncs, NET_CLIENT_DRIVER_NIC, @@ -235,8 +235,12 @@ static void chr_closed_bh(void *opaque) s = DO_UPCAST(NetVhostUserState, nc, ncs[0]); - if (s->vhost_net) { - s->acked_features = vhost_net_get_acked_features(s->vhost_net); + for (i = queues -1; i >= 0; i--) { + s = DO_UPCAST(NetVhostUserState, nc, ncs[i]); + + if (s->vhost_net) { + s->acked_features = vhost_net_get_acked_features(s->vhost_net); + } } qmp_set_link(name, false, &err); diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c new file mode 100644 index 0000000000000000000000000000000000000000..fe659ec9e2422811c557d456913e99a62438c152 --- /dev/null +++ b/net/vhost-vdpa.c @@ -0,0 +1,233 @@ +/* + * vhost-vdpa.c + * + * Copyright(c) 2017-2018 Intel Corporation. + * Copyright(c) 2020 Red Hat, Inc. + * + * 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 "clients.h" +#include "net/vhost_net.h" +#include "net/vhost-vdpa.h" +#include "hw/virtio/vhost-vdpa.h" +#include "qemu/config-file.h" +#include "qemu/error-report.h" +#include "qemu/option.h" +#include "qapi/error.h" +#include +#include +#include "standard-headers/linux/virtio_net.h" +#include "monitor/monitor.h" +#include "hw/virtio/vhost.h" + +/* Todo:need to add the multiqueue support here */ +typedef struct VhostVDPAState { + NetClientState nc; + struct vhost_vdpa vhost_vdpa; + VHostNetState *vhost_net; + uint64_t acked_features; + bool started; +} VhostVDPAState; + +const int vdpa_feature_bits[] = { + VIRTIO_F_NOTIFY_ON_EMPTY, + VIRTIO_RING_F_INDIRECT_DESC, + VIRTIO_RING_F_EVENT_IDX, + VIRTIO_F_ANY_LAYOUT, + VIRTIO_F_VERSION_1, + VIRTIO_NET_F_CSUM, + VIRTIO_NET_F_GUEST_CSUM, + VIRTIO_NET_F_GSO, + VIRTIO_NET_F_GUEST_TSO4, + VIRTIO_NET_F_GUEST_TSO6, + VIRTIO_NET_F_GUEST_ECN, + VIRTIO_NET_F_GUEST_UFO, + VIRTIO_NET_F_HOST_TSO4, + VIRTIO_NET_F_HOST_TSO6, + VIRTIO_NET_F_HOST_ECN, + VIRTIO_NET_F_HOST_UFO, + VIRTIO_NET_F_MRG_RXBUF, + VIRTIO_NET_F_MTU, + VIRTIO_F_IOMMU_PLATFORM, + VIRTIO_F_RING_PACKED, + VIRTIO_NET_F_GUEST_ANNOUNCE, + VIRTIO_NET_F_STATUS, + VHOST_INVALID_FEATURE_BIT +}; + +VHostNetState *vhost_vdpa_get_vhost_net(NetClientState *nc) +{ + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); + return s->vhost_net; +} + +uint64_t vhost_vdpa_get_acked_features(NetClientState *nc) +{ + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); + s->acked_features = vhost_net_get_acked_features(s->vhost_net); + + return s->acked_features; +} + +static int vhost_vdpa_net_check_device_id(struct vhost_net *net) +{ + uint32_t device_id; + int ret; + struct vhost_dev *hdev; + + hdev = (struct vhost_dev *)&net->dev; + ret = hdev->vhost_ops->vhost_get_device_id(hdev, &device_id); + if (device_id != VIRTIO_ID_NET) { + return -ENOTSUP; + } + return ret; +} + +static void vhost_vdpa_del(NetClientState *ncs) +{ + VhostVDPAState *s; + assert(ncs->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); + s = DO_UPCAST(VhostVDPAState, nc, ncs); + if (s->vhost_net) { + vhost_net_cleanup(s->vhost_net); + } +} + +static int vhost_vdpa_add(NetClientState *ncs, void *be) +{ + VhostNetOptions options; + struct vhost_net *net = NULL; + VhostVDPAState *s; + int ret; + + options.backend_type = VHOST_BACKEND_TYPE_VDPA; + assert(ncs->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); + s = DO_UPCAST(VhostVDPAState, nc, ncs); + options.net_backend = ncs; + options.opaque = be; + options.busyloop_timeout = 0; + + net = vhost_net_init(&options); + if (!net) { + error_report("failed to init vhost_net for queue"); + goto err; + } + if (s->vhost_net) { + vhost_net_cleanup(s->vhost_net); + g_free(s->vhost_net); + } + s->vhost_net = net; + ret = vhost_vdpa_net_check_device_id(net); + if (ret) { + goto err; + } + return 0; +err: + if (net) { + vhost_net_cleanup(net); + } + vhost_vdpa_del(ncs); + return -1; +} + +static void vhost_vdpa_cleanup(NetClientState *nc) +{ + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); + + if (s->vhost_net) { + vhost_net_cleanup(s->vhost_net); + g_free(s->vhost_net); + s->vhost_net = NULL; + } + if (s->vhost_vdpa.device_fd >= 0) { + qemu_close(s->vhost_vdpa.device_fd); + s->vhost_vdpa.device_fd = -1; + } +} + +static bool vhost_vdpa_has_vnet_hdr(NetClientState *nc) +{ + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); + + return true; +} + +static bool vhost_vdpa_has_ufo(NetClientState *nc) +{ + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); + uint64_t features = 0; + features |= (1ULL << VIRTIO_NET_F_HOST_UFO); + features = vhost_net_get_features(s->vhost_net, features); + return !!(features & (1ULL << VIRTIO_NET_F_HOST_UFO)); + +} + +static NetClientInfo net_vhost_vdpa_info = { + .type = NET_CLIENT_DRIVER_VHOST_VDPA, + .size = sizeof(VhostVDPAState), + .cleanup = vhost_vdpa_cleanup, + .has_vnet_hdr = vhost_vdpa_has_vnet_hdr, + .has_ufo = vhost_vdpa_has_ufo, +}; + +static int net_vhost_vdpa_init(NetClientState *peer, const char *device, + const char *name, const char *vhostdev) +{ + NetClientState *nc = NULL; + VhostVDPAState *s; + int vdpa_device_fd = -1; + int ret = 0; + assert(name); + nc = qemu_new_net_client(&net_vhost_vdpa_info, peer, device, name); + snprintf(nc->info_str, sizeof(nc->info_str), TYPE_VHOST_VDPA); + nc->queue_index = 0; + s = DO_UPCAST(VhostVDPAState, nc, nc); + vdpa_device_fd = qemu_open_old(vhostdev, O_RDWR); + if (vdpa_device_fd == -1) { + return -errno; + } + s->vhost_vdpa.device_fd = vdpa_device_fd; + ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa); + assert(s->vhost_net); + return ret; +} + +static int net_vhost_check_net(void *opaque, QemuOpts *opts, Error **errp) +{ + const char *name = opaque; + const char *driver, *netdev; + + driver = qemu_opt_get(opts, "driver"); + netdev = qemu_opt_get(opts, "netdev"); + if (!driver || !netdev) { + return 0; + } + if (strcmp(netdev, name) == 0 && + !g_str_has_prefix(driver, "virtio-net-")) { + error_setg(errp, "vhost-vdpa requires frontend driver virtio-net-*"); + return -1; + } + return 0; +} + +int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + NetClientState *peer, Error **errp) +{ + const NetdevVhostVDPAOptions *opts; + + assert(netdev->type == NET_CLIENT_DRIVER_VHOST_VDPA); + opts = &netdev->u.vhost_vdpa; + /* verify net frontend */ + if (qemu_opts_foreach(qemu_find_opts("device"), net_vhost_check_net, + (char *)name, errp)) { + return -1; + } + return net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name, opts->vhostdev); +} diff --git a/os-posix.c b/os-posix.c index 3cd52e1e7004f61b3362f3d3c5d10ef7cbbec397..1de2839554ccefc124767dd894f5a0671c563062 100644 --- a/os-posix.c +++ b/os-posix.c @@ -80,27 +80,6 @@ void os_setup_signal_handling(void) sigaction(SIGTERM, &act, NULL); } -/* - * Find a likely location for support files using the location of the binary. - * When running from the build tree this will be "$bindir/../pc-bios". - * Otherwise, this is CONFIG_QEMU_DATADIR. - */ -char *os_find_datadir(void) -{ - g_autofree char *exec_dir = NULL; - g_autofree char *dir = NULL; - - exec_dir = qemu_get_exec_dir(); - g_return_val_if_fail(exec_dir != NULL, NULL); - - dir = g_build_filename(exec_dir, "..", "pc-bios", NULL); - if (g_file_test(dir, G_FILE_TEST_IS_DIR)) { - return g_steal_pointer(&dir); - } - - return g_strdup(CONFIG_QEMU_DATADIR); -} - void os_set_proc_name(const char *s) { #if defined(PR_SET_NAME) @@ -294,7 +273,7 @@ void os_setup_post(void) error_report("not able to chdir to /: %s", strerror(errno)); exit(1); } - TFR(fd = qemu_open("/dev/null", O_RDWR)); + TFR(fd = qemu_open_old("/dev/null", O_RDWR)); if (fd == -1) { exit(1); } @@ -337,6 +316,7 @@ bool is_daemonized(void) int os_mlock(void) { +#ifdef HAVE_MLOCKALL int ret = 0; ret = mlockall(MCL_CURRENT | MCL_FUTURE); @@ -345,4 +325,7 @@ int os_mlock(void) } return ret; +#else + return -ENOSYS; +#endif } diff --git a/os-win32.c b/os-win32.c index 6b86e022f0e9c9e34c1e3fa3c668aa9c964721e2..fd1137bab1fab40057df048acbfcaf64d496eb29 100644 --- a/os-win32.c +++ b/os-win32.c @@ -57,12 +57,6 @@ void os_setup_early_signal_handling(void) atexit(os_undo_timer_resolution); } -/* Look for support files in the same directory as the executable. */ -char *os_find_datadir(void) -{ - return qemu_get_exec_dir(); -} - void os_set_line_buffering(void) { setbuf(stdout, NULL); diff --git a/pc-bios/README b/pc-bios/README index a5a770f06643edbe160da2318bdbbae5b2f19111..33f9754ad30ff579ba649c9dac3b7d189c121a74 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -14,7 +14,7 @@ - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at https://github.com/aik/SLOF, and the image currently in qemu is - built from git tag qemu-slof-20200327. + built from git tag qemu-slof-20200717. - sgabios (the Serial Graphics Adapter option ROM) provides a means for legacy x86 software to communicate with an attached serial console as @@ -52,8 +52,8 @@ variable store templates built from the TianoCore community's EFI Development Kit II project . The images - were built at git tag "edk2-stable201905". The firmware binaries bundle parts - of the OpenSSL project, at git tag "OpenSSL_1_1_1b" (the OpenSSL tag is a + were built at git tag "edk2-stable202008". The firmware binaries bundle parts + of the OpenSSL project, at git tag "OpenSSL_1_1_1g" (the OpenSSL tag is a function of the edk2 tag). Parts of the Berkeley SoftFloat library are bundled as well, at Release 3e plus a subsequent typo fix (commit b64af41c3276f97f0e181920400ee056b9c88037), as an OpenSSL dependency on 32-bit @@ -71,3 +71,9 @@ ("Simplified BSD License" or "FreeBSD License", SPDX: BSD-2-Clause). OpenSBI source code also contains code reused from other projects desribed here: https://github.com/riscv/opensbi/blob/master/ThirdPartyNotices.md. + +- npcm7xx_bootrom.bin is a simplified, free (Apache 2.0) boot ROM for Nuvoton + NPCM7xx BMC devices. It currently implements the bare minimum to load, parse, + initialize and run boot images stored in SPI flash, but may grow more + features over time as needed. The source code is available at: + https://github.com/google/vbootrom diff --git a/pc-bios/bios-256k.bin b/pc-bios/bios-256k.bin index 4af7f7d5a91bcc19905e1742b0706e034e2a655c..96bdeaa487daef197cee02655116518baba34f67 100644 Binary files a/pc-bios/bios-256k.bin and b/pc-bios/bios-256k.bin differ diff --git a/pc-bios/bios-microvm.bin b/pc-bios/bios-microvm.bin index 45eabc516692e2d134bbb630d133c7c2dcc9a9b6..eefd32197e8d637be0266e3410551f711728c6d0 100644 Binary files a/pc-bios/bios-microvm.bin and b/pc-bios/bios-microvm.bin differ diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin index 67874c31b8b0284eb292deb2c9ebc191fa2d73b6..3ecaf4a7094b556f821e08901df19b280b8bf4c1 100644 Binary files a/pc-bios/bios.bin and b/pc-bios/bios.bin differ diff --git a/pc-bios/descriptors/meson.build b/pc-bios/descriptors/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..7040834573d764aa518c9c6eecc8a55ad9188a9a --- /dev/null +++ b/pc-bios/descriptors/meson.build @@ -0,0 +1,14 @@ +foreach f: [ + '50-edk2-i386-secure.json', + '50-edk2-x86_64-secure.json', + '60-edk2-aarch64.json', + '60-edk2-arm.json', + '60-edk2-i386.json', + '60-edk2-x86_64.json' +] + configure_file(input: files(f), + output: f, + configuration: {'DATADIR': qemu_datadir}, + install: get_option('install_blobs'), + install_dir: qemu_datadir / 'firmware') +endforeach diff --git a/pc-bios/edk2-aarch64-code.fd.bz2 b/pc-bios/edk2-aarch64-code.fd.bz2 index a074085b224febf1c466e583dd10f72f1ed38d6b..5bf311464a79a0fc72d021b1a4a3faff2d31bf46 100644 Binary files a/pc-bios/edk2-aarch64-code.fd.bz2 and b/pc-bios/edk2-aarch64-code.fd.bz2 differ diff --git a/pc-bios/edk2-arm-code.fd.bz2 b/pc-bios/edk2-arm-code.fd.bz2 index 42453cd1f273029ad21fa1a85323df45d2a4efbc..7a98069814dc1f4255eed8c3be98453b3df5f249 100644 Binary files a/pc-bios/edk2-arm-code.fd.bz2 and b/pc-bios/edk2-arm-code.fd.bz2 differ diff --git a/pc-bios/edk2-i386-code.fd.bz2 b/pc-bios/edk2-i386-code.fd.bz2 index 633759688e32a47bc154dc089a06f50bcb366add..e7b1befe2cfe73df331a39c85e54c6f048a1f22e 100644 Binary files a/pc-bios/edk2-i386-code.fd.bz2 and b/pc-bios/edk2-i386-code.fd.bz2 differ diff --git a/pc-bios/edk2-i386-secure-code.fd.bz2 b/pc-bios/edk2-i386-secure-code.fd.bz2 index df27bdd2ddbd29df0f62c61509b02c27beb0178f..b5df5bed3086b1e74500de90312dfbae1d33f784 100644 Binary files a/pc-bios/edk2-i386-secure-code.fd.bz2 and b/pc-bios/edk2-i386-secure-code.fd.bz2 differ diff --git a/pc-bios/edk2-x86_64-code.fd.bz2 b/pc-bios/edk2-x86_64-code.fd.bz2 index 0e108fc68a917e1656dcd54bfc6d78007969554c..e1654d4003b77ed1f9530d30138fed6d847cdf6b 100644 Binary files a/pc-bios/edk2-x86_64-code.fd.bz2 and b/pc-bios/edk2-x86_64-code.fd.bz2 differ diff --git a/pc-bios/edk2-x86_64-secure-code.fd.bz2 b/pc-bios/edk2-x86_64-secure-code.fd.bz2 index 522f8376aabee4c6bc74a8043a7d0566e669fe83..767274c38c7f56069c64a068c1896acb62480a5a 100644 Binary files a/pc-bios/edk2-x86_64-secure-code.fd.bz2 and b/pc-bios/edk2-x86_64-secure-code.fd.bz2 differ diff --git a/pc-bios/efi-e1000.rom b/pc-bios/efi-e1000.rom index 6f088d41ddebb07eeb70a20dd46eee3693a67779..6312b11c2f5868bb6e5f0f15dfa31ad7dbda0a02 100644 Binary files a/pc-bios/efi-e1000.rom and b/pc-bios/efi-e1000.rom differ diff --git a/pc-bios/efi-e1000e.rom b/pc-bios/efi-e1000e.rom index f536bdbd45a26d095b597b1caa817bd8d5dad45d..1f9e0e9dd8d4a0a2fdcfb74fcd8fe0c73d22018e 100644 Binary files a/pc-bios/efi-e1000e.rom and b/pc-bios/efi-e1000e.rom differ diff --git a/pc-bios/efi-eepro100.rom b/pc-bios/efi-eepro100.rom index 64d8891485530c4715a8ad0299f33c0ef018b1a5..c7ccfc4fd73cc85f2f31a18a0ec61bd03c302d5a 100644 Binary files a/pc-bios/efi-eepro100.rom and b/pc-bios/efi-eepro100.rom differ diff --git a/pc-bios/efi-ne2k_pci.rom b/pc-bios/efi-ne2k_pci.rom index 02ad0cb505214461787b07df0ee7fc5217617673..93d5b45d371f3417f1ecd20f0e31df8fe2c83075 100644 Binary files a/pc-bios/efi-ne2k_pci.rom and b/pc-bios/efi-ne2k_pci.rom differ diff --git a/pc-bios/efi-pcnet.rom b/pc-bios/efi-pcnet.rom index 88d25fa6255e458ab9f9b6655b066a7c678cae7c..783bf5b3049d7551d157c94cb9c448d1aa30533f 100644 Binary files a/pc-bios/efi-pcnet.rom and b/pc-bios/efi-pcnet.rom differ diff --git a/pc-bios/efi-rtl8139.rom b/pc-bios/efi-rtl8139.rom index 53f125e3bb5b7e8447bd8529485585a0a8291ff0..debcf30acd0dfbfc0b67175eacf8b9af20dae62e 100644 Binary files a/pc-bios/efi-rtl8139.rom and b/pc-bios/efi-rtl8139.rom differ diff --git a/pc-bios/efi-virtio.rom b/pc-bios/efi-virtio.rom index a87321e9285a2aa115a86e605231e38c952cac53..70e8588ccdc6e0e25eedfc8611f2183a55112ddb 100644 Binary files a/pc-bios/efi-virtio.rom and b/pc-bios/efi-virtio.rom differ diff --git a/pc-bios/efi-vmxnet3.rom b/pc-bios/efi-vmxnet3.rom index d017cafe2264c00a8f6216bda8aed5205883ba89..ebf59ef737d48d8bd10644b61e38d585b47ec804 100644 Binary files a/pc-bios/efi-vmxnet3.rom and b/pc-bios/efi-vmxnet3.rom differ diff --git a/pc-bios/hppa-firmware.img b/pc-bios/hppa-firmware.img index 82d98b13536cdc9830edfec5caa33bc5b09ca912..4ba8c7f8b8d4187271e958f5b1f6d7f2a099e0d8 100644 Binary files a/pc-bios/hppa-firmware.img and b/pc-bios/hppa-firmware.img differ diff --git a/pc-bios/keymaps/Makefile b/pc-bios/keymaps/Makefile deleted file mode 100644 index 76217b0689613409b32359dd508e2fdcaf285161..0000000000000000000000000000000000000000 --- a/pc-bios/keymaps/Makefile +++ /dev/null @@ -1,56 +0,0 @@ - -KEYMAP := $(shell which qemu-keymap 2>/dev/null) - -MAPS := ar bepo cz da de de-ch en-us en-gb es et fi fo \ - fr fr-be fr-ca fr-ch \ - hr hu is it ja lt lv mk nl no pl pt pt-br ru th tr - -ar : MAP_FLAGS := -l ar -bepo : MAP_FLAGS := -l fr -v dvorak -cz : MAP_FLAGS := -l cz -da : MAP_FLAGS := -l dk -de : MAP_FLAGS := -l de -v nodeadkeys -de-ch : MAP_FLAGS := -l ch -en-us : MAP_FLAGS := -l us -en-gb : MAP_FLAGS := -l gb -es : MAP_FLAGS := -l es -et : MAP_FLAGS := -l et -fi : MAP_FLAGS := -l fi -fo : MAP_FLAGS := -l fo -fr : MAP_FLAGS := -l fr -v nodeadkeys -fr-be : MAP_FLAGS := -l be -fr-ca : MAP_FLAGS := -l ca -v fr -fr-ch : MAP_FLAGS := -l ch -v fr -hr : MAP_FLAGS := -l hr -hu : MAP_FLAGS := -l hu -is : MAP_FLAGS := -l is -it : MAP_FLAGS := -l it -ja : MAP_FLAGS := -l jp -m jp106 -lt : MAP_FLAGS := -l lt -lv : MAP_FLAGS := -l lv -mk : MAP_FLAGS := -l mk -nl : MAP_FLAGS := -l nl -no : MAP_FLAGS := -l no -pl : MAP_FLAGS := -l pl -pt : MAP_FLAGS := -l pt -pt-br : MAP_FLAGS := -l br -ru : MAP_FLAGS := -l ru -th : MAP_FLAGS := -l th -tr : MAP_FLAGS := -l tr - -ifeq ($(KEYMAP),) - -all: - @echo "nothing to do (qemu-keymap not found)" - -else - -all: $(MAPS) - -clean: - rm -f $(MAPS) - -$(MAPS): $(KEYMAP) Makefile - $(KEYMAP) -f $@ $(MAP_FLAGS) - -endif diff --git a/pc-bios/keymaps/ar b/pc-bios/keymaps/ar index f62b297c54f4614d6bec99b919d674489da23d29..32049d86e9948c644765ab73f39dbaecd70ffbb0 100644 --- a/pc-bios/keymaps/ar +++ b/pc-bios/keymaps/ar @@ -772,9 +772,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/bepo b/pc-bios/keymaps/bepo index 2292cbc499be25abc3f2e0272c38760649afbc33..99d280ca74f2a153ef1b82018547faa4fc163216 100644 --- a/pc-bios/keymaps/bepo +++ b/pc-bios/keymaps/bepo @@ -763,9 +763,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/cz b/pc-bios/keymaps/cz index 29cf2b05d8b6bddf7e2fc53f866036ed135ef737..60ac603489a041d6c1fe01262bea8f72a74d2846 100644 --- a/pc-bios/keymaps/cz +++ b/pc-bios/keymaps/cz @@ -819,9 +819,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/da b/pc-bios/keymaps/da index 547d8c716b94822efcac9285ffe8713f94b6c46b..4e42d9ece2b54e27cdfb00995c5a310c72153b9e 100644 --- a/pc-bios/keymaps/da +++ b/pc-bios/keymaps/da @@ -818,9 +818,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym 0x0edd0160) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym 0x0edd0270) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/de b/pc-bios/keymaps/de index 261243edbc5dcbba02422852275b6c2cc645eed0..7be0030dde146f349ee500f270922f53b35f70e4 100644 --- a/pc-bios/keymaps/de +++ b/pc-bios/keymaps/de @@ -816,9 +816,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/de-ch b/pc-bios/keymaps/de-ch index ed3da058e4841e2e006d348ad83a0b257057884c..4aad3129226cbac66d0a4292ded7e29fb6b1fe83 100644 --- a/pc-bios/keymaps/de-ch +++ b/pc-bios/keymaps/de-ch @@ -818,9 +818,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/en-gb b/pc-bios/keymaps/en-gb index 18d8fce4d453ec71fef90bd494eebade0af55c55..0fd8198b3e2326d952caf2d37c3719a11392b1d9 100644 --- a/pc-bios/keymaps/en-gb +++ b/pc-bios/keymaps/en-gb @@ -817,9 +817,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/en-us b/pc-bios/keymaps/en-us index 06762cfc6c0cb877a47f360c0b8a61df5691dc0f..70cc7a2e62568913518f21ab499d92b031dfcc11 100644 --- a/pc-bios/keymaps/en-us +++ b/pc-bios/keymaps/en-us @@ -729,9 +729,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/es b/pc-bios/keymaps/es index fde441492dbb56a670e6ab9a666d300388dd027c..b8fe3dc90f1a6d31a6b4b8e57220a27ecfd040ef 100644 --- a/pc-bios/keymaps/es +++ b/pc-bios/keymaps/es @@ -817,9 +817,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/et b/pc-bios/keymaps/et index a5dcbd18abde1344d5ae773be1cecf06e53e26e9..946e3888362244463027bb167385ac0303367e17 100644 --- a/pc-bios/keymaps/et +++ b/pc-bios/keymaps/et @@ -727,9 +727,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/fi b/pc-bios/keymaps/fi index 816749421e4380d15b18cb5b5eaedcd664c81aff..c8e943b8e7864794841505c15aaae4326207fddc 100644 --- a/pc-bios/keymaps/fi +++ b/pc-bios/keymaps/fi @@ -792,9 +792,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/fo b/pc-bios/keymaps/fo index 8bb6f97bbad74882ffb58a89749dde9d00da65be..20791e1f1f68bf40c7fb85d7b27379420b427282 100644 --- a/pc-bios/keymaps/fo +++ b/pc-bios/keymaps/fo @@ -819,9 +819,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/fr b/pc-bios/keymaps/fr index 82ca812c7e2de222fc03e7fe9be8f0d9b18bfbfe..f8655127587bca7c5c9dc7ccf3d828b226c07288 100644 --- a/pc-bios/keymaps/fr +++ b/pc-bios/keymaps/fr @@ -819,9 +819,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/fr-be b/pc-bios/keymaps/fr-be index f225f179a25ae356441dbdf1c27be2d5af04e868..e680abb319650094269968d2b578e8d2808454c2 100644 --- a/pc-bios/keymaps/fr-be +++ b/pc-bios/keymaps/fr-be @@ -818,9 +818,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/fr-ca b/pc-bios/keymaps/fr-ca index f264d0a9c35b7b4b7ee6e1dfb6698c9da9238a6c..e0b741adc3a6b1ff39aca6783964fd132a7d7044 100644 --- a/pc-bios/keymaps/fr-ca +++ b/pc-bios/keymaps/fr-ca @@ -750,9 +750,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/fr-ch b/pc-bios/keymaps/fr-ch index bdd944da1c07bb31e851f55d8a69612a5e8e819f..fe200ea39c606e7bbbe8c352bdc20ee818f3a8fd 100644 --- a/pc-bios/keymaps/fr-ch +++ b/pc-bios/keymaps/fr-ch @@ -818,9 +818,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/hr b/pc-bios/keymaps/hr index 252936c3ae1a3721e451e017681c457b8ad59620..f936a256e4e5b7e40f970b6feb9362aba30b800e 100644 --- a/pc-bios/keymaps/hr +++ b/pc-bios/keymaps/hr @@ -819,9 +819,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/hu b/pc-bios/keymaps/hu index 853147610a7c7df7e7c5af56e7272ab5fae65cf3..bef6c19f9093e29c3620fa8dbdb2996b2a11c2c8 100644 --- a/pc-bios/keymaps/hu +++ b/pc-bios/keymaps/hu @@ -818,9 +818,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym 0x0a865600) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym 0x0a865710) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/is b/pc-bios/keymaps/is index c88fa603aa4f0ff350a8009329d16dff442e8f73..115c2d09bbde30be1a7655bde5cf660b01ca54da 100644 --- a/pc-bios/keymaps/is +++ b/pc-bios/keymaps/is @@ -819,9 +819,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/it b/pc-bios/keymaps/it index df00156cf88f993a7b712d7c5c255c30d51bf5e0..66f46e7ae3451df422d1bbfb39a09824e95800f1 100644 --- a/pc-bios/keymaps/it +++ b/pc-bios/keymaps/it @@ -822,9 +822,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/ja b/pc-bios/keymaps/ja index 6eb2e7bc208d00eb19978268378d4abef6f3c3eb..4589dd29b7bba215c2c5b6b665a26544672d0b59 100644 --- a/pc-bios/keymaps/ja +++ b/pc-bios/keymaps/ja @@ -733,9 +733,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/lt b/pc-bios/keymaps/lt index db9b24f611c396380dc22bc2efeed054176732c2..141286f0af06b9f92a947e0bbf6f9e5edc5abbbe 100644 --- a/pc-bios/keymaps/lt +++ b/pc-bios/keymaps/lt @@ -817,9 +817,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/lv b/pc-bios/keymaps/lv index 54997ce0922cf6c2099860363ebca424e78691d5..240d8d3e85761b919335e7e35390dfe3e2d0bd82 100644 --- a/pc-bios/keymaps/lv +++ b/pc-bios/keymaps/lv @@ -792,9 +792,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/meson.build b/pc-bios/keymaps/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..05eda6c0d26df5f2c875bae3fc075d499e8cf4d2 --- /dev/null +++ b/pc-bios/keymaps/meson.build @@ -0,0 +1,68 @@ +keymaps = { + 'ar': '-l ar', + 'bepo': '-l fr -v dvorak', + 'cz': '-l cz', + 'da': '-l dk', + 'de': '-l de -v nodeadkeys', + 'de-ch': '-l ch', + 'en-gb': '-l gb', + 'en-us': '-l us', + 'es': '-l es', + 'et': '-l et', + 'fi': '-l fi', + 'fo': '-l fo', + 'fr': '-l fr -v nodeadkeys', + 'fr-be': '-l be', + 'fr-ca': '-l ca -v fr', + 'fr-ch': '-l ch -v fr', + 'hr': '-l hr', + 'hu': '-l hu', + 'is': '-l is', + 'it': '-l it', + 'ja': '-l jp -m jp106', + 'lt': '-l lt', + 'lv': '-l lv', + 'mk': '-l mk', + 'nl': '-l nl', + 'no': '-l no', + 'pl': '-l pl', + 'pt': '-l pt', + 'pt-br': '-l br', + 'ru': '-l ru', + 'th': '-l th', + 'tr': '-l tr', +} + +if meson.is_cross_build() or 'CONFIG_XKBCOMMON' not in config_host + native_qemu_keymap = find_program('qemu-keymap', required: false, disabler: true) +else + native_qemu_keymap = qemu_keymap +endif + +t = [] +foreach km, args: keymaps + if native_qemu_keymap.found() + # generate with qemu-kvm + t += custom_target(km, + build_by_default: true, + output: km, + command: [native_qemu_keymap, '-f', '@OUTPUT@', args.split()], + install: true, + install_dir: qemu_datadir / 'keymaps') + else + # copy from source tree + t += custom_target(km, + build_by_default: true, + input: km, + output: km, + command: ['cp', '@INPUT@', '@OUTPUT@'], + install: true, + install_dir: qemu_datadir / 'keymaps') + endif +endforeach + +if native_qemu_keymap.found() + alias_target('update-keymaps', t) +endif + +install_data(['sl', 'sv'], install_dir: qemu_datadir / 'keymaps') diff --git a/pc-bios/keymaps/mk b/pc-bios/keymaps/mk index cb362b6d39c2260ed57189bf47dac0af7391e77b..d331b23bbaf007ef9855133131066265700c5430 100644 --- a/pc-bios/keymaps/mk +++ b/pc-bios/keymaps/mk @@ -729,9 +729,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/nl b/pc-bios/keymaps/nl index 1579829eefacfe3748f08579426cb13e4cd26b7f..d6522d117b525ffa6c9e314d0339701ff766bdf7 100644 --- a/pc-bios/keymaps/nl +++ b/pc-bios/keymaps/nl @@ -819,9 +819,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/no b/pc-bios/keymaps/no index cd634e7b903c9610617e711aa4f8020a26a404ea..631f4dc1a7e3656ca0b415a1413a1f12226d45ad 100644 --- a/pc-bios/keymaps/no +++ b/pc-bios/keymaps/no @@ -833,9 +833,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym 0x00408160) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym 0x00408270) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/pl b/pc-bios/keymaps/pl index 30d93ca72727b17d256412047e7d9cefa8bee976..6a966f539229213cdd1c06be903004b60fc8cc84 100644 --- a/pc-bios/keymaps/pl +++ b/pc-bios/keymaps/pl @@ -823,9 +823,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/pt b/pc-bios/keymaps/pt index c34d6e3761bf60a6c9f41184cfdef4457593bb1e..31c1dccc2c619392ec065677936d2b07d980aa27 100644 --- a/pc-bios/keymaps/pt +++ b/pc-bios/keymaps/pt @@ -816,9 +816,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/pt-br b/pc-bios/keymaps/pt-br index 2d409c0bc02d2cca492f3afc2e83c828c4f8c273..0bac9e34a341aacdaa969df7281f6bfc097c25e0 100644 --- a/pc-bios/keymaps/pt-br +++ b/pc-bios/keymaps/pt-br @@ -816,9 +816,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/ru b/pc-bios/keymaps/ru index 9502ba1269e57a62ad1ba03f67e3e7c67b5ccb3e..9f3492ef5db86a59ff2fdfc3f0a399d4ede1d196 100644 --- a/pc-bios/keymaps/ru +++ b/pc-bios/keymaps/ru @@ -730,9 +730,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/th b/pc-bios/keymaps/th index b8298d902b1753b1f38dda0ed7400ecf2ff1f73d..2c4a17f0e562b4fb623d199d76e5c296a992cb0b 100644 --- a/pc-bios/keymaps/th +++ b/pc-bios/keymaps/th @@ -729,9 +729,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/keymaps/tr b/pc-bios/keymaps/tr index 8ef60a60c1da47c2cc1f209701e4ea807318a532..2f5bd621a334bf1bd71138a66346e6337c97efe7 100644 --- a/pc-bios/keymaps/tr +++ b/pc-bios/keymaps/tr @@ -812,9 +812,247 @@ XF86AudioMedia 0xed # evdev 245 (0xf5): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) -# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 246 (0xf6): no evdev -> QKeyCode mapping (xkb keysym XF86WWAN) -# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym Invalid) +# evdev 247 (0xf7): no evdev -> QKeyCode mapping (xkb keysym XF86RFKill) + +# evdev 248 (0xf8): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 249 (0xf9): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 250 (0xfa): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 251 (0xfb): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 252 (0xfc): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 253 (0xfd): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 254 (0xfe): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 255 (0xff): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 256 (0x100): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 257 (0x101): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 258 (0x102): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 259 (0x103): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 260 (0x104): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 261 (0x105): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 262 (0x106): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 263 (0x107): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 264 (0x108): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 265 (0x109): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 266 (0x10a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 267 (0x10b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 268 (0x10c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 269 (0x10d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 270 (0x10e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 271 (0x10f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 272 (0x110): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 273 (0x111): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 274 (0x112): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 275 (0x113): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 276 (0x114): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 277 (0x115): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 278 (0x116): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 279 (0x117): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 280 (0x118): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 281 (0x119): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 282 (0x11a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 283 (0x11b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 284 (0x11c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 285 (0x11d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 286 (0x11e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 287 (0x11f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 288 (0x120): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 289 (0x121): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 290 (0x122): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 291 (0x123): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 292 (0x124): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 293 (0x125): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 294 (0x126): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 295 (0x127): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 296 (0x128): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 297 (0x129): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 298 (0x12a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 299 (0x12b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 300 (0x12c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 301 (0x12d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 302 (0x12e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 303 (0x12f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 304 (0x130): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 305 (0x131): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 306 (0x132): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 307 (0x133): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 308 (0x134): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 309 (0x135): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 310 (0x136): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 311 (0x137): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 312 (0x138): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 313 (0x139): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 314 (0x13a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 315 (0x13b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 316 (0x13c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 317 (0x13d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 318 (0x13e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 319 (0x13f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 320 (0x140): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 321 (0x141): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 322 (0x142): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 323 (0x143): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 324 (0x144): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 325 (0x145): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 326 (0x146): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 327 (0x147): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 328 (0x148): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 329 (0x149): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 330 (0x14a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 331 (0x14b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 332 (0x14c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 333 (0x14d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 334 (0x14e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 335 (0x14f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 336 (0x150): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 337 (0x151): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 338 (0x152): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 339 (0x153): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 340 (0x154): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 341 (0x155): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 342 (0x156): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 343 (0x157): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 344 (0x158): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 345 (0x159): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 346 (0x15a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 347 (0x15b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 348 (0x15c): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 349 (0x15d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 350 (0x15e): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 351 (0x15f): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 352 (0x160): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 353 (0x161): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 354 (0x162): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 355 (0x163): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 356 (0x164): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 357 (0x165): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 358 (0x166): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 359 (0x167): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 360 (0x168): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 361 (0x169): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 362 (0x16a): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 363 (0x16b): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 364 (0x16c): no evdev -> QKeyCode mapping (xkb keysym XF86Favorites) + +# evdev 365 (0x16d): no evdev -> QKeyCode mapping (xkb keysym NoSymbol) + +# evdev 366 (0x16e): no evdev -> QKeyCode mapping (xkb keysym XF86Keyboard) # # quirks section start diff --git a/pc-bios/meson.build b/pc-bios/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..fab323af84e73288cb85ee4f822f8cad589f78de --- /dev/null +++ b/pc-bios/meson.build @@ -0,0 +1,94 @@ +if 'arm-softmmu' in target_dirs or \ + 'aarch64-softmmu' in target_dirs or \ + 'i386-softmmu' in target_dirs or \ + 'x86_64-softmmu' in target_dirs + bzip2 = find_program('bzip2', required: true) + fds = [ + 'edk2-aarch64-code.fd', + 'edk2-arm-code.fd', + 'edk2-arm-vars.fd', + 'edk2-i386-code.fd', + 'edk2-i386-secure-code.fd', + 'edk2-i386-vars.fd', + 'edk2-x86_64-code.fd', + 'edk2-x86_64-secure-code.fd', + ] + + foreach f : fds + custom_target(f, + output: f, + input: '@0@.bz2'.format(f), + capture: true, + install: get_option('install_blobs'), + install_dir: qemu_datadir, + command: [ bzip2, '-dc', '@INPUT0@' ]) + endforeach +endif + +blobs = files( + 'bios.bin', + 'bios-256k.bin', + 'bios-microvm.bin', + 'qboot.rom', + 'sgabios.bin', + 'vgabios.bin', + 'vgabios-cirrus.bin', + 'vgabios-stdvga.bin', + 'vgabios-vmware.bin', + 'vgabios-qxl.bin', + 'vgabios-virtio.bin', + 'vgabios-ramfb.bin', + 'vgabios-bochs-display.bin', + 'vgabios-ati.bin', + 'openbios-sparc32', + 'openbios-sparc64', + 'openbios-ppc', + 'QEMU,tcx.bin', + 'QEMU,cgthree.bin', + 'pxe-e1000.rom', + 'pxe-eepro100.rom', + 'pxe-ne2k_pci.rom', + 'pxe-pcnet.rom', + 'pxe-rtl8139.rom', + 'pxe-virtio.rom', + 'efi-e1000.rom', + 'efi-eepro100.rom', + 'efi-ne2k_pci.rom', + 'efi-pcnet.rom', + 'efi-rtl8139.rom', + 'efi-virtio.rom', + 'efi-e1000e.rom', + 'efi-vmxnet3.rom', + 'qemu-nsis.bmp', + 'bamboo.dtb', + 'canyonlands.dtb', + 'petalogix-s3adsp1800.dtb', + 'petalogix-ml605.dtb', + 'multiboot.bin', + 'linuxboot.bin', + 'linuxboot_dma.bin', + 'kvmvapic.bin', + 'pvh.bin', + 's390-ccw.img', + 's390-netboot.img', + 'slof.bin', + 'skiboot.lid', + 'palcode-clipper', + 'u-boot.e500', + 'u-boot-sam460-20100605.bin', + 'qemu_vga.ndrv', + 'edk2-licenses.txt', + 'hppa-firmware.img', + 'opensbi-riscv32-generic-fw_dynamic.bin', + 'opensbi-riscv64-generic-fw_dynamic.bin', + 'opensbi-riscv32-generic-fw_dynamic.elf', + 'opensbi-riscv64-generic-fw_dynamic.elf', + 'npcm7xx_bootrom.bin', +) + +if get_option('install_blobs') + install_data(blobs, install_dir: qemu_datadir) +endif + +subdir('descriptors') +subdir('keymaps') diff --git a/pc-bios/npcm7xx_bootrom.bin b/pc-bios/npcm7xx_bootrom.bin new file mode 100644 index 0000000000000000000000000000000000000000..38f89d1b97b0c2e133af2a9fbed0521be132065b Binary files /dev/null and b/pc-bios/npcm7xx_bootrom.bin differ diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc index 5da9363bff64e21ab61ecf70d571855a3714843f..def6d4cf63380d2601f35e2320b38055b8c4d6f1 100644 Binary files a/pc-bios/openbios-ppc and b/pc-bios/openbios-ppc differ diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32 index d68b5e5d30961f8b796d06e1e17374f310e201d5..67b8b83d984a3f4f804dab117b54b89783579824 100644 Binary files a/pc-bios/openbios-sparc32 and b/pc-bios/openbios-sparc32 differ diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64 index 26d631ea64c501927c417cf4c5352808dbb1f7ca..dfa1f10bbc140d78d56451fd4e5c73da13898d5e 100644 Binary files a/pc-bios/openbios-sparc64 and b/pc-bios/openbios-sparc64 differ diff --git a/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin b/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin new file mode 100644 index 0000000000000000000000000000000000000000..23b4dfb3b941b030ffefe8ef5c8b4ef77b35c51d Binary files /dev/null and b/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin differ diff --git a/pc-bios/opensbi-riscv32-generic-fw_dynamic.elf b/pc-bios/opensbi-riscv32-generic-fw_dynamic.elf new file mode 100644 index 0000000000000000000000000000000000000000..eb9ebf5674d3953ab25de6bf4db134abe904eb20 Binary files /dev/null and b/pc-bios/opensbi-riscv32-generic-fw_dynamic.elf differ diff --git a/pc-bios/opensbi-riscv32-sifive_u-fw_jump.bin b/pc-bios/opensbi-riscv32-sifive_u-fw_jump.bin deleted file mode 100644 index 3e0da54080ef4dbf3fbde6205c983fb25c82e114..0000000000000000000000000000000000000000 Binary files a/pc-bios/opensbi-riscv32-sifive_u-fw_jump.bin and /dev/null differ diff --git a/pc-bios/opensbi-riscv32-virt-fw_jump.bin b/pc-bios/opensbi-riscv32-virt-fw_jump.bin deleted file mode 100644 index bc56ed61fd9620880a5d04f6e01d48c83a96a74c..0000000000000000000000000000000000000000 Binary files a/pc-bios/opensbi-riscv32-virt-fw_jump.bin and /dev/null differ diff --git a/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin b/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin new file mode 100644 index 0000000000000000000000000000000000000000..16c0cf4d0a7c9bb2e7f0f1c03d4e56d529290b8b Binary files /dev/null and b/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin differ diff --git a/pc-bios/opensbi-riscv64-generic-fw_dynamic.elf b/pc-bios/opensbi-riscv64-generic-fw_dynamic.elf new file mode 100644 index 0000000000000000000000000000000000000000..642a64e240d09b2ddb9fc12c74718ae8d386b9d3 Binary files /dev/null and b/pc-bios/opensbi-riscv64-generic-fw_dynamic.elf differ diff --git a/pc-bios/opensbi-riscv64-sifive_u-fw_jump.bin b/pc-bios/opensbi-riscv64-sifive_u-fw_jump.bin deleted file mode 100644 index 1acee86dc7cabc1437018a69900b1c3e7f7a7d2b..0000000000000000000000000000000000000000 Binary files a/pc-bios/opensbi-riscv64-sifive_u-fw_jump.bin and /dev/null differ diff --git a/pc-bios/opensbi-riscv64-virt-fw_jump.bin b/pc-bios/opensbi-riscv64-virt-fw_jump.bin deleted file mode 100644 index c62f2b449b9ae552e708389bc12d5b8569162889..0000000000000000000000000000000000000000 Binary files a/pc-bios/opensbi-riscv64-virt-fw_jump.bin and /dev/null differ diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile index e33a24da0d0ca125aef84351a4a689726d482056..084fc10f0540b62df06c476bb11c21cdb5dd8564 100644 --- a/pc-bios/optionrom/Makefile +++ b/pc-bios/optionrom/Makefile @@ -1,62 +1,73 @@ -all: build-all +CURRENT_MAKEFILE := $(realpath $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))) +SRC_DIR := $(dir $(CURRENT_MAKEFILE)) +TOPSRC_DIR := $(SRC_DIR)/../.. +VPATH = $(SRC_DIR) + +all: multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin pvh.bin # Dummy command so that make thinks it has done something @true include ../../config-host.mak -include $(SRC_PATH)/rules.mak +CFLAGS = -O2 -g -$(call set-vpath, $(SRC_PATH)/pc-bios/optionrom) +quiet-command = $(if $(V),$1,$(if $(2),@printf " %-7s %s\n" $2 $3 && $1, @$1)) +cc-option = $(if $(shell $(CC) $1 -c -o /dev/null -xc /dev/null >/dev/null 2>&1 && echo OK), $1, $2) -.PHONY : all clean build-all +override CFLAGS += -march=i486 -Wall -# Compiling with no optimization creates ROMs that are too large -ifeq ($(lastword $(filter -O%, -O0 $(CFLAGS))),-O0) -override CFLAGS += -O2 -endif -override CFLAGS += -march=i486 +# Flags for dependency generation +override CPPFLAGS += -MMD -MP -MT $@ -MF $(@D)/$(*F).d -# Drop -fstack-protector and the like -QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS)) $(CFLAGS_NOPIE) -ffreestanding -QEMU_CFLAGS += $(call cc-option, $(QEMU_CFLAGS), -fno-stack-protector) -QEMU_CFLAGS += $(call cc-option, $(QEMU_CFLAGS), -m16) -ifeq ($(filter -m16, $(QEMU_CFLAGS)),) +override CFLAGS += $(filter -W%, $(QEMU_CFLAGS)) +override CFLAGS += $(CFLAGS_NOPIE) -ffreestanding -I$(TOPSRC_DIR)/include +override CFLAGS += $(call cc-option, -fno-stack-protector) +override CFLAGS += $(call cc-option, -m16) + +ifeq ($(filter -m16, $(CFLAGS)),) # Attempt to work around compilers that lack -m16 (GCC <= 4.8, clang <= ??) # On GCC we add -fno-toplevel-reorder to keep the order of asm blocks with # respect to the rest of the code. clang does not have -fno-toplevel-reorder, # but it places all asm blocks at the beginning and we're relying on it for # the option ROM header. So just force clang not to use the integrated # assembler, which doesn't support .code16gcc. -QEMU_CFLAGS += $(call cc-option, $(QEMU_CFLAGS), -fno-toplevel-reorder) -QEMU_CFLAGS += $(call cc-option, $(QEMU_CFLAGS), -no-integrated-as) -QEMU_CFLAGS += -m32 -include $(SRC_PATH)/pc-bios/optionrom/code16gcc.h +override CFLAGS += $(call cc-option, -fno-toplevel-reorder) +override CFLAGS += $(call cc-option, -no-integrated-as) +override CFLAGS += -m32 -include $(SRC_DIR)/code16gcc.h endif -QEMU_INCLUDES += -I$(SRC_PATH) - Wa = -Wa, -ASFLAGS += -32 -QEMU_CFLAGS += $(call cc-c-option, $(QEMU_CFLAGS), $(Wa)-32) +override ASFLAGS += -32 +override CFLAGS += $(call cc-option, $(Wa)-32) -build-all: multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin pvh.bin +LD_I386_EMULATION ?= elf_i386 +override LDFLAGS = -m $(LD_I386_EMULATION) -T $(SRC_DIR)/flat.lds +override LDFLAGS += $(LDFLAGS_NOPIE) -# suppress auto-removal of intermediate files -.SECONDARY: +all: multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin pvh.bin +pvh.img: pvh.o pvh_main.o %.o: %.S - $(call quiet-command,$(CPP) $(QEMU_INCLUDES) $(QEMU_DGFLAGS) -c -o - $< | $(AS) $(ASFLAGS) -o $@,"AS","$(TARGET_DIR)$@") + $(call quiet-command,$(CPP) $(CPPFLAGS) -c -o - $< | $(AS) $(ASFLAGS) -o $@,"AS","$@") -pvh.img: pvh.o pvh_main.o - $(call quiet-command,$(LD) $(LDFLAGS_NOPIE) -m $(LD_I386_EMULATION) -T $(SRC_PATH)/pc-bios/optionrom/flat.lds -s -o $@ $^,"BUILD","$(TARGET_DIR)$@") +%.o: %.c + $(call quiet-command,$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@,"CC","$@") %.img: %.o - $(call quiet-command,$(LD) $(LDFLAGS_NOPIE) -m $(LD_I386_EMULATION) -T $(SRC_PATH)/pc-bios/optionrom/flat.lds -s -o $@ $<,"BUILD","$(TARGET_DIR)$@") + $(call quiet-command,$(LD) $(LDFLAGS) -s -o $@ $^,"BUILD","$@") %.raw: %.img - $(call quiet-command,$(OBJCOPY) -O binary -j .text $< $@,"BUILD","$(TARGET_DIR)$@") + $(call quiet-command,$(OBJCOPY) -O binary -j .text $< $@,"BUILD","$@") %.bin: %.raw - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/signrom.py $< $@,"SIGN","$(TARGET_DIR)$@") + $(call quiet-command,$(PYTHON) $(TOPSRC_DIR)/scripts/signrom.py $< $@,"SIGN","$@") + +include $(wildcard *.d) clean: rm -f *.o *.d *.raw *.img *.bin *~ + +# suppress auto-removal of intermediate files +.SECONDARY: + +.PHONY: all clean diff --git a/pc-bios/petalogix-ml605.dtb b/pc-bios/petalogix-ml605.dtb index fbbd45fdad06489c6333b6de868f44dfaed405bf..9a05434db7f622d1b598d2cf1415c867cf7f5cc6 100644 Binary files a/pc-bios/petalogix-ml605.dtb and b/pc-bios/petalogix-ml605.dtb differ diff --git a/pc-bios/petalogix-ml605.dts b/pc-bios/petalogix-ml605.dts new file mode 100644 index 0000000000000000000000000000000000000000..b307a29279e72b9c3a8d548033100364904d793c --- /dev/null +++ b/pc-bios/petalogix-ml605.dts @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2020 Xilinx Inc. + * Written by Edgar E. Iglesias . + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; + +/ { + #address-cells = < 0x01 >; + #size-cells = < 0x01 >; + compatible = "xlnx,microblaze"; + model = "edk131"; + + memory@50000000 { + device_type = "memory"; + reg = < 0x50000000 0x10000000 >; + }; + + aliases { + ethernet0 = "/axi/axi-ethernet@82780000"; + serial0 = "/axi/serial@83e00000"; + }; + + chosen { + bootargs = " console=ttyS0,115200 "; + stdout-path = "/axi/serial@83e00000"; + }; + + cpus { + #address-cells = < 0x01 >; + #cpus = < 0x01 >; + #size-cells = < 0x00 >; + + cpu@0 { + clock-frequency = < 0xbebc200 >; + compatible = "xlnx,microblaze-8.10.a"; + d-cache-baseaddr = < 0x50000000 >; + d-cache-highaddr = < 0x5fffffff >; + d-cache-line-size = < 0x20 >; + d-cache-size = < 0x800 >; + device_type = "cpu"; + i-cache-baseaddr = < 0x50000000 >; + i-cache-highaddr = < 0x5fffffff >; + i-cache-line-size = < 0x20 >; + i-cache-size = < 0x800 >; + model = "microblaze,8.10.a"; + reg = < 0x00 >; + timebase-frequency = < 0xbebc200 >; + xlnx,addr-tag-bits = < 0x11 >; + xlnx,allow-dcache-wr = < 0x01 >; + xlnx,allow-icache-wr = < 0x01 >; + xlnx,area-optimized = < 0x00 >; + xlnx,branch-target-cache-size = < 0x00 >; + xlnx,cache-byte-size = < 0x800 >; + xlnx,d-axi = < 0x01 >; + xlnx,d-lmb = < 0x01 >; + xlnx,d-plb = < 0x00 >; + xlnx,data-size = < 0x20 >; + xlnx,dcache-addr-tag = < 0x11 >; + xlnx,dcache-always-used = < 0x01 >; + xlnx,dcache-byte-size = < 0x800 >; + xlnx,dcache-data-width = < 0x00 >; + xlnx,dcache-force-tag-lutram = < 0x00 >; + xlnx,dcache-interface = < 0x01 >; + xlnx,dcache-line-len = < 0x08 >; + xlnx,dcache-use-fsl = < 0x00 >; + xlnx,dcache-use-writeback = < 0x01 >; + xlnx,dcache-victims = < 0x00 >; + xlnx,debug-enabled = < 0x01 >; + xlnx,div-zero-exception = < 0x01 >; + xlnx,dynamic-bus-sizing = < 0x01 >; + xlnx,ecc-use-ce-exception = < 0x00 >; + xlnx,edge-is-positive = < 0x01 >; + xlnx,endianness = < 0x01 >; + xlnx,family = "virtex6"; + xlnx,fault-tolerant = < 0x00 >; + xlnx,fpu-exception = < 0x01 >; + xlnx,freq = < 0xbebc200 >; + xlnx,fsl-data-size = < 0x20 >; + xlnx,fsl-exception = < 0x00 >; + xlnx,fsl-links = < 0x00 >; + xlnx,i-axi = < 0x01 >; + xlnx,i-lmb = < 0x01 >; + xlnx,i-plb = < 0x00 >; + xlnx,icache-always-used = < 0x01 >; + xlnx,icache-data-width = < 0x00 >; + xlnx,icache-force-tag-lutram = < 0x00 >; + xlnx,icache-interface = < 0x00 >; + xlnx,icache-line-len = < 0x08 >; + xlnx,icache-streams = < 0x00 >; + xlnx,icache-use-fsl = < 0x00 >; + xlnx,icache-victims = < 0x00 >; + xlnx,ill-opcode-exception = < 0x01 >; + xlnx,instance = "microblaze_0"; + xlnx,interconnect = < 0x02 >; + xlnx,interrupt-is-edge = < 0x00 >; + xlnx,mmu-dtlb-size = < 0x04 >; + xlnx,mmu-itlb-size = < 0x02 >; + xlnx,mmu-privileged-instr = < 0x00 >; + xlnx,mmu-tlb-access = < 0x03 >; + xlnx,mmu-zones = < 0x02 >; + xlnx,number-of-pc-brk = < 0x01 >; + xlnx,number-of-rd-addr-brk = < 0x00 >; + xlnx,number-of-wr-addr-brk = < 0x00 >; + xlnx,opcode-0x0-illegal = < 0x01 >; + xlnx,optimization = < 0x00 >; + xlnx,pvr = < 0x02 >; + xlnx,pvr-user1 = < 0x00 >; + xlnx,pvr-user2 = < 0x00 >; + xlnx,reset-msr = < 0x00 >; + xlnx,sco = < 0x00 >; + xlnx,stream-interconnect = < 0x00 >; + xlnx,unaligned-exceptions = < 0x01 >; + xlnx,use-barrel = < 0x01 >; + xlnx,use-branch-target-cache = < 0x00 >; + xlnx,use-dcache = < 0x01 >; + xlnx,use-div = < 0x01 >; + xlnx,use-ext-brk = < 0x01 >; + xlnx,use-ext-nm-brk = < 0x01 >; + xlnx,use-extended-fsl-instr = < 0x00 >; + xlnx,use-fpu = < 0x01 >; + xlnx,use-hw-mul = < 0x02 >; + xlnx,use-icache = < 0x01 >; + xlnx,use-interrupt = < 0x01 >; + xlnx,use-mmu = < 0x03 >; + xlnx,use-msr-instr = < 0x01 >; + xlnx,use-pcmp-instr = < 0x01 >; + xlnx,use-stack-protection = < 0x00 >; + }; + }; + + axi { + #address-cells = < 0x01 >; + #size-cells = < 0x01 >; + compatible = "xlnx,axi-interconnect-1.02.a\0simple-bus"; + ranges; + + axi-ethernet@82780000 { + axistream-connected = < &axi_dma >; + compatible = "xlnx,axi-ethernet-2.01.a\0xlnx,axi-ethernet-1.00.a"; + device_type = "network"; + interrupt-parent = < &intc >; + interrupts = < 0x03 0x02 >; + local-mac-address = [ 00 0a 35 00 22 01 ]; + phy-handle = < &phy7 >; + reg = < 0x82780000 0x40000 >; + xlnx,avb = < 0x00 >; + xlnx,halfdup = < 0x00 >; + xlnx,include-io = < 0x01 >; + xlnx,mcast-extend = < 0x00 >; + xlnx,phy-type = < 0x01 >; + xlnx,phyaddr = "0B00001"; + xlnx,rxcsum = < 0x00 >; + xlnx,rxmem = < 0x1000 >; + xlnx,rxvlan-strp = < 0x00 >; + xlnx,rxvlan-tag = < 0x00 >; + xlnx,rxvlan-tran = < 0x00 >; + xlnx,stats = < 0x00 >; + xlnx,txcsum = < 0x00 >; + xlnx,txmem = < 0x1000 >; + xlnx,txvlan-strp = < 0x00 >; + xlnx,txvlan-tag = < 0x00 >; + xlnx,txvlan-tran = < 0x00 >; + xlnx,type = < 0x02 >; + + mdio { + #address-cells = < 0x01 >; + #size-cells = < 0x00 >; + + phy7: phy@7 { + compatible = "marvell,88e1111"; + device_type = "ethernet-phy"; + reg = < 0x07 >; + }; + }; + }; + + axi_dma: axi-dma@84600000 { + compatible = "xlnx,axi-dma-3.00.a"; + interrupt-parent = < &intc >; + interrupts = < 0x01 0x02 0x00 0x02 >; + reg = < 0x84600000 0x10000 >; + xlnx,dlytmr-resolution = < 0x4e2 >; + xlnx,family = "virtex6"; + xlnx,include-mm2s = < 0x01 >; + xlnx,include-mm2s-dre = < 0x01 >; + xlnx,include-s2mm = < 0x01 >; + xlnx,include-s2mm-dre = < 0x01 >; + xlnx,mm2s-burst-size = < 0x10 >; + xlnx,prmry-is-aclk-async = < 0x00 >; + xlnx,s2mm-burst-size = < 0x10 >; + xlnx,sg-include-desc-queue = < 0x01 >; + xlnx,sg-include-stscntrl-strm = < 0x01 >; + xlnx,sg-length-width = < 0x10 >; + xlnx,sg-use-stsapp-length = < 0x01 >; + }; + + serial@83e00000 { + clock-frequency = < 0x5f5e100 >; + compatible = "xlnx,axi-uart16550-1.01.a\0xlnx,xps-uart16550-2.00.a\0ns16550a"; + current-speed = < 0x2580 >; + device_type = "serial"; + interrupt-parent = < &intc >; + interrupts = < 0x05 0x02 >; + reg = < 0x83e00000 0x10000 >; + reg-offset = < 0x1000 >; + reg-shift = < 0x02 >; + xlnx,external-xin-clk-hz = < 0x17d7840 >; + xlnx,family = "virtex6"; + xlnx,has-external-rclk = < 0x00 >; + xlnx,has-external-xin = < 0x00 >; + xlnx,is-a-16550 = < 0x01 >; + xlnx,use-modem-ports = < 0x00 >; + xlnx,use-user-ports = < 0x00 >; + }; + + system-timer@83c00000 { + clock-frequency = < 0x5f5e100 >; + compatible = "xlnx,axi-timer-1.01.a\0xlnx,xps-timer-1.00.a"; + interrupt-parent = < &intc >; + interrupts = < 0x02 0x00 >; + reg = < 0x83c00000 0x10000 >; + xlnx,count-width = < 0x20 >; + xlnx,family = "virtex6"; + xlnx,gen0-assert = < 0x01 >; + xlnx,gen1-assert = < 0x01 >; + xlnx,one-timer-only = < 0x00 >; + xlnx,trig0-assert = < 0x01 >; + xlnx,trig1-assert = < 0x01 >; + }; + + intc: interrupt-controller@81800000 { + #interrupt-cells = < 0x02 >; + compatible = "xlnx,axi-intc-1.01.a\0xlnx,xps-intc-1.00.a"; + interrupt-controller; + reg = < 0x81800000 0x10000 >; + xlnx,kind-of-intr = < 0x04 >; + xlnx,num-intr-inputs = < 0x06 >; + }; + + flash@86000000 { + #address-cells = < 0x01 >; + #size-cells = < 0x01 >; + bank-width = < 0x02 >; + compatible = "xlnx,axi-emc-1.01.a\0cfi-flash"; + reg = < 0x86000000 0x2000000 >; + xlnx,axi-clk-period-ps = < 0x2710 >; + xlnx,family = "virtex6"; + xlnx,include-datawidth-matching-0 = < 0x01 >; + xlnx,include-datawidth-matching-1 = < 0x00 >; + xlnx,include-datawidth-matching-2 = < 0x00 >; + xlnx,include-datawidth-matching-3 = < 0x00 >; + xlnx,include-negedge-ioregs = < 0x00 >; + xlnx,max-mem-width = < 0x10 >; + xlnx,mem0-type = < 0x02 >; + xlnx,mem0-width = < 0x10 >; + xlnx,mem1-type = < 0x00 >; + xlnx,mem1-width = < 0x20 >; + xlnx,mem2-type = < 0x00 >; + xlnx,mem2-width = < 0x20 >; + xlnx,mem3-type = < 0x00 >; + xlnx,mem3-width = < 0x20 >; + xlnx,num-banks-mem = < 0x01 >; + xlnx,parity-type-mem-0 = < 0x00 >; + xlnx,parity-type-mem-1 = < 0x00 >; + xlnx,parity-type-mem-2 = < 0x00 >; + xlnx,parity-type-mem-3 = < 0x00 >; + xlnx,s-axi-en-reg = < 0x00 >; + xlnx,s-axi-mem-addr-width = < 0x20 >; + xlnx,s-axi-mem-data-width = < 0x20 >; + xlnx,s-axi-mem-id-width = < 0x01 >; + xlnx,s-axi-mem-protocol = "AXI4LITE"; + xlnx,s-axi-reg-addr-width = < 0x20 >; + xlnx,s-axi-reg-data-width = < 0x20 >; + xlnx,s-axi-reg-protocol = "axi4"; + xlnx,synch-pipedelay-0 = < 0x02 >; + xlnx,synch-pipedelay-1 = < 0x02 >; + xlnx,synch-pipedelay-2 = < 0x02 >; + xlnx,synch-pipedelay-3 = < 0x02 >; + xlnx,tavdv-ps-mem-0 = < 0x1fbd0 >; + xlnx,tavdv-ps-mem-1 = < 0x3a98 >; + xlnx,tavdv-ps-mem-2 = < 0x3a98 >; + xlnx,tavdv-ps-mem-3 = < 0x3a98 >; + xlnx,tcedv-ps-mem-0 = < 0x1fbd0 >; + xlnx,tcedv-ps-mem-1 = < 0x3a98 >; + xlnx,tcedv-ps-mem-2 = < 0x3a98 >; + xlnx,tcedv-ps-mem-3 = < 0x3a98 >; + xlnx,thzce-ps-mem-0 = < 0x88b8 >; + xlnx,thzce-ps-mem-1 = < 0x1b58 >; + xlnx,thzce-ps-mem-2 = < 0x1b58 >; + xlnx,thzce-ps-mem-3 = < 0x1b58 >; + xlnx,thzoe-ps-mem-0 = < 0x1b58 >; + xlnx,thzoe-ps-mem-1 = < 0x1b58 >; + xlnx,thzoe-ps-mem-2 = < 0x1b58 >; + xlnx,thzoe-ps-mem-3 = < 0x1b58 >; + xlnx,tlzwe-ps-mem-0 = < 0x88b8 >; + xlnx,tlzwe-ps-mem-1 = < 0x00 >; + xlnx,tlzwe-ps-mem-2 = < 0x00 >; + xlnx,tlzwe-ps-mem-3 = < 0x00 >; + xlnx,tpacc-ps-flash-0 = < 0x61a8 >; + xlnx,tpacc-ps-flash-1 = < 0x61a8 >; + xlnx,tpacc-ps-flash-2 = < 0x61a8 >; + xlnx,tpacc-ps-flash-3 = < 0x61a8 >; + xlnx,twc-ps-mem-0 = < 0x32c8 >; + xlnx,twc-ps-mem-1 = < 0x3a98 >; + xlnx,twc-ps-mem-2 = < 0x3a98 >; + xlnx,twc-ps-mem-3 = < 0x3a98 >; + xlnx,twp-ps-mem-0 = < 0x11170 >; + xlnx,twp-ps-mem-1 = < 0x2ee0 >; + xlnx,twp-ps-mem-2 = < 0x2ee0 >; + xlnx,twp-ps-mem-3 = < 0x2ee0 >; + xlnx,twph-ps-mem-0 = < 0x2ee0 >; + xlnx,twph-ps-mem-1 = < 0x2ee0 >; + xlnx,twph-ps-mem-2 = < 0x2ee0 >; + xlnx,twph-ps-mem-3 = < 0x2ee0 >; + + partition@0 { + label = "fpga"; + reg = < 0x00 0x100000 >; + }; + + partition@100000 { + label = "boot"; + reg = < 0x100000 0x40000 >; + }; + + partition@140000 { + label = "bootenv"; + reg = < 0x140000 0x20000 >; + }; + + partition@160000 { + label = "config"; + reg = < 0x160000 0x20000 >; + }; + + partition@180000 { + label = "image"; + reg = < 0x180000 0xa00000 >; + }; + + partition@b80000 { + label = "spare"; + reg = < 0xb80000 0x00 >; + }; + }; + }; +}; diff --git a/pc-bios/petalogix-s3adsp1800.dtb b/pc-bios/petalogix-s3adsp1800.dtb index 8ac80f2f2d191a8491b71182be50b3df2989551d..2513599438bffca96a93e877a1981efdd1a91115 100644 Binary files a/pc-bios/petalogix-s3adsp1800.dtb and b/pc-bios/petalogix-s3adsp1800.dtb differ diff --git a/pc-bios/petalogix-s3adsp1800.dts b/pc-bios/petalogix-s3adsp1800.dts new file mode 100644 index 0000000000000000000000000000000000000000..f53c36f870804dfef1f9dbdfd86c1b1f0a41fddd --- /dev/null +++ b/pc-bios/petalogix-s3adsp1800.dts @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2020 Xilinx Inc. + * Written by Edgar E. Iglesias . + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; + +/ { + #address-cells = <0x01>; + #size-cells = <0x01>; + compatible = "xlnx,microblaze"; + model = "testing"; + + memory@90000000 { + device_type = "memory"; + reg = <0x90000000 0x8000000>; + }; + + chosen { + bootargs = "console=ttyUL0,115200"; + stdout-path = "/plb/serial@84000000"; + }; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + #cpus = <0x01>; + + cpu@0 { + clock-frequency = <0x3b9aca0>; + compatible = "xlnx,microblaze-7.10.d"; + d-cache-baseaddr = <0x90000000>; + d-cache-highaddr = <0x97ffffff>; + d-cache-line-size = <0x10>; + d-cache-size = <0x800>; + device_type = "cpu"; + i-cache-baseaddr = <0x90000000>; + i-cache-highaddr = <0x97ffffff>; + i-cache-line-size = <0x10>; + i-cache-size = <0x800>; + model = "microblaze,7.10.d"; + reg = <0x00>; + timebase-frequency = <0x3b9aca0>; + xlnx,addr-tag-bits = <0x10>; + xlnx,allow-dcache-wr = <0x01>; + xlnx,allow-icache-wr = <0x01>; + xlnx,area-optimized = <0x00>; + xlnx,cache-byte-size = <0x800>; + xlnx,d-lmb = <0x01>; + xlnx,d-opb = <0x00>; + xlnx,d-plb = <0x01>; + xlnx,data-size = <0x20>; + xlnx,dcache-addr-tag = <0x10>; + xlnx,dcache-always-used = <0x00>; + xlnx,dcache-byte-size = <0x800>; + xlnx,dcache-line-len = <0x04>; + xlnx,dcache-use-fsl = <0x01>; + xlnx,debug-enabled = <0x01>; + xlnx,div-zero-exception = <0x00>; + xlnx,dopb-bus-exception = <0x00>; + xlnx,dynamic-bus-sizing = <0x01>; + xlnx,edge-is-positive = <0x01>; + xlnx,family = "spartan3adsp"; + xlnx,fpu-exception = <0x00>; + xlnx,fsl-data-size = <0x20>; + xlnx,fsl-exception = <0x00>; + xlnx,fsl-links = <0x00>; + xlnx,i-lmb = <0x01>; + xlnx,i-opb = <0x00>; + xlnx,i-plb = <0x01>; + xlnx,icache-always-used = <0x00>; + xlnx,icache-line-len = <0x04>; + xlnx,icache-use-fsl = <0x01>; + xlnx,ill-opcode-exception = <0x00>; + xlnx,instance = "microblaze_0"; + xlnx,interconnect = <0x01>; + xlnx,interrupt-is-edge = <0x00>; + xlnx,iopb-bus-exception = <0x00>; + xlnx,mmu-dtlb-size = <0x04>; + xlnx,mmu-itlb-size = <0x02>; + xlnx,mmu-tlb-access = <0x03>; + xlnx,mmu-zones = <0x10>; + xlnx,number-of-pc-brk = <0x03>; + xlnx,number-of-rd-addr-brk = <0x02>; + xlnx,number-of-wr-addr-brk = <0x02>; + xlnx,opcode-0x0-illegal = <0x00>; + xlnx,pvr = <0x01>; + xlnx,pvr-user1 = <0x00>; + xlnx,pvr-user2 = <0x00>; + xlnx,reset-msr = <0x00>; + xlnx,sco = <0x00>; + xlnx,unaligned-exceptions = <0x01>; + xlnx,use-barrel = <0x01>; + xlnx,use-dcache = <0x01>; + xlnx,use-div = <0x00>; + xlnx,use-ext-brk = <0x01>; + xlnx,use-ext-nm-brk = <0x01>; + xlnx,use-extended-fsl-instr = <0x00>; + xlnx,use-fpu = <0x00>; + xlnx,use-hw-mul = <0x01>; + xlnx,use-icache = <0x01>; + xlnx,use-interrupt = <0x01>; + xlnx,use-mmu = <0x03>; + xlnx,use-msr-instr = <0x01>; + xlnx,use-pcmp-instr = <0x01>; + }; + }; + + plb { + #address-cells = <0x01>; + #size-cells = <0x01>; + compatible = "xlnx,plb-v46-1.03.a\0simple-bus"; + ranges; + + ethernet@81000000 { + compatible = "xlnx,xps-ethernetlite-2.00.a"; + device_type = "network"; + interrupt-parent = <0x01>; + interrupts = <0x01 0x00>; + local-mac-address = [02 00 00 00 00 00]; + reg = <0x81000000 0x10000>; + xlnx,duplex = <0x01>; + xlnx,family = "spartan3adsp"; + xlnx,rx-ping-pong = <0x00>; + xlnx,tx-ping-pong = <0x00>; + }; + + flash@a0000000 { + bank-width = <0x01>; + compatible = "xlnx,xps-mch-emc-2.00.a\0cfi-flash"; + reg = <0xa0000000 0x1000000>; + xlnx,family = "spartan3adsp"; + xlnx,include-datawidth-matching-0 = <0x01>; + xlnx,include-datawidth-matching-1 = <0x00>; + xlnx,include-datawidth-matching-2 = <0x00>; + xlnx,include-datawidth-matching-3 = <0x00>; + xlnx,include-negedge-ioregs = <0x00>; + xlnx,include-plb-ipif = <0x01>; + xlnx,include-wrbuf = <0x01>; + xlnx,max-mem-width = <0x08>; + xlnx,mch-native-dwidth = <0x20>; + xlnx,mch-plb-clk-period-ps = <0x3e80>; + xlnx,mch-splb-awidth = <0x20>; + xlnx,mch0-accessbuf-depth = <0x10>; + xlnx,mch0-protocol = <0x00>; + xlnx,mch0-rddatabuf-depth = <0x10>; + xlnx,mch1-accessbuf-depth = <0x10>; + xlnx,mch1-protocol = <0x00>; + xlnx,mch1-rddatabuf-depth = <0x10>; + xlnx,mch2-accessbuf-depth = <0x10>; + xlnx,mch2-protocol = <0x00>; + xlnx,mch2-rddatabuf-depth = <0x10>; + xlnx,mch3-accessbuf-depth = <0x10>; + xlnx,mch3-protocol = <0x00>; + xlnx,mch3-rddatabuf-depth = <0x10>; + xlnx,mem0-width = <0x08>; + xlnx,mem1-width = <0x20>; + xlnx,mem2-width = <0x20>; + xlnx,mem3-width = <0x20>; + xlnx,num-banks-mem = <0x01>; + xlnx,num-channels = <0x00>; + xlnx,priority-mode = <0x00>; + xlnx,synch-mem-0 = <0x00>; + xlnx,synch-mem-1 = <0x00>; + xlnx,synch-mem-2 = <0x00>; + xlnx,synch-mem-3 = <0x00>; + xlnx,synch-pipedelay-0 = <0x02>; + xlnx,synch-pipedelay-1 = <0x02>; + xlnx,synch-pipedelay-2 = <0x02>; + xlnx,synch-pipedelay-3 = <0x02>; + xlnx,tavdv-ps-mem-0 = <0x11170>; + xlnx,tavdv-ps-mem-1 = <0x3a98>; + xlnx,tavdv-ps-mem-2 = <0x3a98>; + xlnx,tavdv-ps-mem-3 = <0x3a98>; + xlnx,tcedv-ps-mem-0 = <0x11170>; + xlnx,tcedv-ps-mem-1 = <0x3a98>; + xlnx,tcedv-ps-mem-2 = <0x3a98>; + xlnx,tcedv-ps-mem-3 = <0x3a98>; + xlnx,thzce-ps-mem-0 = <0x61a8>; + xlnx,thzce-ps-mem-1 = <0x1b58>; + xlnx,thzce-ps-mem-2 = <0x1b58>; + xlnx,thzce-ps-mem-3 = <0x1b58>; + xlnx,thzoe-ps-mem-0 = <0x61a8>; + xlnx,thzoe-ps-mem-1 = <0x1b58>; + xlnx,thzoe-ps-mem-2 = <0x1b58>; + xlnx,thzoe-ps-mem-3 = <0x1b58>; + xlnx,tlzwe-ps-mem-0 = <0x1388>; + xlnx,tlzwe-ps-mem-1 = <0x00>; + xlnx,tlzwe-ps-mem-2 = <0x00>; + xlnx,tlzwe-ps-mem-3 = <0x00>; + xlnx,twc-ps-mem-0 = <0x11170>; + xlnx,twc-ps-mem-1 = <0x3a98>; + xlnx,twc-ps-mem-2 = <0x3a98>; + xlnx,twc-ps-mem-3 = <0x3a98>; + xlnx,twp-ps-mem-0 = <0xafc8>; + xlnx,twp-ps-mem-1 = <0x2ee0>; + xlnx,twp-ps-mem-2 = <0x2ee0>; + xlnx,twp-ps-mem-3 = <0x2ee0>; + xlnx,xcl0-linesize = <0x04>; + xlnx,xcl0-writexfer = <0x01>; + xlnx,xcl1-linesize = <0x04>; + xlnx,xcl1-writexfer = <0x01>; + xlnx,xcl2-linesize = <0x04>; + xlnx,xcl2-writexfer = <0x01>; + xlnx,xcl3-linesize = <0x04>; + xlnx,xcl3-writexfer = <0x01>; + }; + + gpio@81400000 { + compatible = "xlnx,xps-gpio-1.00.a"; + interrupt-parent = <0x01>; + interrupts = <0x02 0x02>; + reg = <0x81400000 0x10000>; + xlnx,all-inputs = <0x00>; + xlnx,all-inputs-2 = <0x00>; + xlnx,dout-default = <0x00>; + xlnx,dout-default-2 = <0x00>; + xlnx,family = "spartan3adsp"; + xlnx,gpio-width = <0x08>; + xlnx,interrupt-present = <0x01>; + xlnx,is-bidir = <0x00>; + xlnx,is-bidir-2 = <0x01>; + xlnx,is-dual = <0x00>; + xlnx,tri-default = <0xffffffff>; + xlnx,tri-default-2 = <0xffffffff>; + }; + + serial@84000000 { + clock-frequency = <0x3b9aca0>; + compatible = "xlnx,xps-uartlite-1.00.a"; + current-speed = <0x1c200>; + device_type = "serial"; + interrupt-parent = <0x01>; + interrupts = <0x03 0x00>; + port-number = <0x00>; + reg = <0x84000000 0x10000>; + xlnx,baudrate = <0x1c200>; + xlnx,data-bits = <0x08>; + xlnx,family = "spartan3adsp"; + xlnx,odd-parity = <0x00>; + xlnx,use-parity = <0x00>; + }; + + debug@84400000 { + compatible = "xlnx,mdm-1.00.d"; + reg = <0x84400000 0x10000>; + xlnx,family = "spartan3adsp"; + xlnx,interconnect = <0x01>; + xlnx,jtag-chain = <0x02>; + xlnx,mb-dbg-ports = <0x01>; + xlnx,uart-width = <0x08>; + xlnx,use-uart = <0x01>; + xlnx,write-fsl-ports = <0x00>; + }; + + interrupt-controller@81800000 { + #interrupt-cells = <0x02>; + compatible = "xlnx,xps-intc-1.00.a"; + interrupt-controller; + reg = <0x81800000 0x10000>; + xlnx,kind-of-intr = <0x0a>; + xlnx,num-intr-inputs = <0x04>; + linux,phandle = <0x01>; + }; + + timer@83c00000 { + compatible = "xlnx,xps-timer-1.00.a"; + interrupt-parent = <0x01>; + interrupts = <0x00 0x02>; + reg = <0x83c00000 0x10000>; + xlnx,count-width = <0x20>; + xlnx,family = "spartan3adsp"; + xlnx,gen0-assert = <0x01>; + xlnx,gen1-assert = <0x01>; + xlnx,one-timer-only = <0x00>; + xlnx,trig0-assert = <0x01>; + xlnx,trig1-assert = <0x01>; + }; + }; +}; diff --git a/pc-bios/qboot.rom b/pc-bios/qboot.rom new file mode 100644 index 0000000000000000000000000000000000000000..7634106a0766913077e88dfcb1021c1168dcad3c Binary files /dev/null and b/pc-bios/qboot.rom differ diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img index b9da9d8ecb10faa484a9a524a202f1f69cb59ad6..5aaeac9f79c018110a885552e18e8911bd16aa98 100644 Binary files a/pc-bios/s390-ccw.img and b/pc-bios/s390-ccw.img differ diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile index a048b6b077a94a41f9fa41e3860bc44795fc3eee..29fd9019b839e482a3c5c45a52e9d5022724541f 100644 --- a/pc-bios/s390-ccw/Makefile +++ b/pc-bios/s390-ccw/Makefile @@ -3,20 +3,38 @@ all: build-all @true include ../../config-host.mak -include $(SRC_PATH)/rules.mak +CFLAGS = -O2 -g +quiet-command = $(if $(V),$1,$(if $(2),@printf " %-7s %s\n" $2 $3 && $1, @$1)) +cc-option = $(if $(shell $(CC) $1 -S -o /dev/null -xc /dev/null > /dev/null \ + 2>&1 && echo OK), $1, $2) + +VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.sh %.rc Kconfig% %.json.in +set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1))) $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw) +# Flags for dependency generation +QEMU_DGFLAGS = -MMD -MP -MT $@ -MF $(@D)/$(*F).d + +%.o: %.c + $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) \ + -c -o $@ $<,"CC","$(TARGET_DIR)$@") + +%.o: %.S + $(call quiet-command,$(CCAS) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) \ + -c -o $@ $<,"CCAS","$(TARGET_DIR)$@") + .PHONY : all clean build-all OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \ virtio.o virtio-scsi.o virtio-blkdev.o libc.o cio.o dasd-ipl.o -QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS)) -QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float -QEMU_CFLAGS += -march=z900 -fPIE -fno-strict-aliasing -QEMU_CFLAGS += -fno-asynchronous-unwind-tables +QEMU_CFLAGS := -Wall $(filter -W%, $(QEMU_CFLAGS)) +QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -fno-common -fPIE +QEMU_CFLAGS += -fwrapv -fno-strict-aliasing -fno-asynchronous-unwind-tables QEMU_CFLAGS += $(call cc-option, $(QEMU_CFLAGS), -fno-stack-protector) +QEMU_CFLAGS += -msoft-float -march=z900 +QEMU_CFLAGS += -std=gnu99 LDFLAGS += -Wl,-pie -nostdlib build-all: s390-ccw.img s390-netboot.img @@ -38,5 +56,8 @@ s390-netboot.img: @echo "s390-netboot.img not built since roms/SLOF/ is not available." endif +ALL_OBJS = $(sort $(OBJECTS) $(NETOBJS) $(LIBCOBJS) $(LIBNETOBJS)) +-include $(ALL_OBJS:%.o=%.d) + clean: rm -f *.o *.d *.img *.elf *~ *.a diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c index d13b7cbd1597bf2e531efcf8f54e70fcdbe387e9..44df7d16afcac32f0bf8af9e04bff3f2b9bc767d 100644 --- a/pc-bios/s390-ccw/bootmap.c +++ b/pc-bios/s390-ccw/bootmap.c @@ -10,6 +10,7 @@ #include "libc.h" #include "s390-ccw.h" +#include "s390-arch.h" #include "bootmap.h" #include "virtio.h" #include "bswap.h" @@ -163,7 +164,7 @@ static bool find_zipl_boot_menu_banner(int *offset) int i; /* Menu banner starts with "zIPL" */ - for (i = 0; i < virtio_get_block_size() - 4; i++) { + for (i = 0; i <= virtio_get_block_size() - 4; i++) { if (magic_match(s2_cur_blk + i, ZIPL_MAGIC_EBCDIC)) { *offset = i; return true; @@ -192,7 +193,7 @@ static int eckd_get_boot_menu_index(block_number_t s1b_block_nr) for (i = 0; i < STAGE2_BLK_CNT_MAX; i++) { cur_block_nr = eckd_block_num(&s1b->seek[i].chs); - if (!cur_block_nr) { + if (!cur_block_nr || is_null_block_number(cur_block_nr)) { break; } @@ -272,7 +273,8 @@ static void run_eckd_boot_script(block_number_t bmt_block_nr, IPL_assert(bms->entry[i].type == BOOT_SCRIPT_EXEC, "Unknown script entry type"); - jump_to_IPL_code(bms->entry[i].address.load_address); /* no return */ + write_reset_psw(bms->entry[i].address.load_address); /* no return */ + jump_to_IPL_code(0); /* no return */ } static void ipl_eckd_cdl(void) @@ -289,11 +291,18 @@ static void ipl_eckd_cdl(void) read_block(1, ipl2, "Cannot read IPL2 record at block 1"); mbr = &ipl2->mbr; - IPL_assert(magic_match(mbr, ZIPL_MAGIC), "No zIPL section in IPL2 record."); - IPL_assert(block_size_ok(mbr->blockptr.xeckd.bptr.size), - "Bad block size in zIPL section of IPL2 record."); - IPL_assert(mbr->dev_type == DEV_TYPE_ECKD, - "Non-ECKD device type in zIPL section of IPL2 record."); + if (!magic_match(mbr, ZIPL_MAGIC)) { + sclp_print("No zIPL section in IPL2 record.\n"); + return; + } + if (!block_size_ok(mbr->blockptr.xeckd.bptr.size)) { + sclp_print("Bad block size in zIPL section of IPL2 record.\n"); + return; + } + if (!mbr->dev_type == DEV_TYPE_ECKD) { + sclp_print("Non-ECKD device type in zIPL section of IPL2 record.\n"); + return; + } /* save pointer to Boot Map Table */ bmt_block_nr = eckd_block_num(&mbr->blockptr.xeckd.bptr.chs); @@ -303,10 +312,14 @@ static void ipl_eckd_cdl(void) memset(sec, FREE_SPACE_FILLER, sizeof(sec)); read_block(2, vlbl, "Cannot read Volume Label at block 2"); - IPL_assert(magic_match(vlbl->key, VOL1_MAGIC), - "Invalid magic of volume label block"); - IPL_assert(magic_match(vlbl->f.key, VOL1_MAGIC), - "Invalid magic of volser block"); + if (!magic_match(vlbl->key, VOL1_MAGIC)) { + sclp_print("Invalid magic of volume label block.\n"); + return; + } + if (!magic_match(vlbl->f.key, VOL1_MAGIC)) { + sclp_print("Invalid magic of volser block.\n"); + return; + } print_volser(vlbl->f.volser); run_eckd_boot_script(bmt_block_nr, s1b_block_nr); @@ -328,9 +341,7 @@ static void print_eckd_ldl_msg(ECKD_IPL_mode_t mode) msg[0] = '2'; break; default: - msg[0] = vlbl->LDL_version; - msg[0] &= 0x0f; /* convert EBCDIC */ - msg[0] |= 0x30; /* to ASCII (digit) */ + msg[0] = ebc2asc[vlbl->LDL_version]; msg[1] = '?'; break; } @@ -400,7 +411,8 @@ static void ipl_eckd(void) read_block(0, mbr, "Cannot read block 0 on DASD"); if (magic_match(mbr->magic, IPL1_MAGIC)) { - ipl_eckd_cdl(); /* no return */ + ipl_eckd_cdl(); /* only returns in case of error */ + return; } /* LDL/CMS? */ @@ -438,7 +450,7 @@ static void zipl_load_segment(ComponentEntry *entry) char *blk_no = &err_msg[30]; /* where to print blockno in (those ZZs) */ blockno = entry->data.blockno; - address = entry->load_address; + address = entry->compdat.load_addr; debug_print_int("loading segment at block", blockno); debug_print_int("addr", address); @@ -516,7 +528,8 @@ static void zipl_run(ScsiBlockPtr *pte) IPL_assert(entry->component_type == ZIPL_COMP_ENTRY_EXEC, "No EXEC entry"); /* should not return */ - jump_to_IPL_code(entry->load_address); + write_reset_psw(entry->compdat.load_psw); + jump_to_IPL_code(0); } static void ipl_scsi(void) @@ -827,5 +840,5 @@ void zipl_load(void) panic("\n! Unknown IPL device type !\n"); } - panic("\n* this can never happen *\n"); + sclp_print("zIPL load failed.\n"); } diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h index 12a0166aae0b6e2df4522f5b6e4119ff68e622a6..3946aa3f8d2cdbe76511fa00e231052016453228 100644 --- a/pc-bios/s390-ccw/bootmap.h +++ b/pc-bios/s390-ccw/bootmap.h @@ -64,11 +64,16 @@ typedef struct BootMapTable { BootMapPointer entry[]; } __attribute__ ((packed)) BootMapTable; +typedef union ComponentEntryData { + uint64_t load_psw; + uint64_t load_addr; +} ComponentEntryData; + typedef struct ComponentEntry { ScsiBlockPtr data; uint8_t pad[7]; uint8_t component_type; - uint64_t load_address; + ComponentEntryData compdat; } __attribute((packed)) ComponentEntry; typedef struct ComponentHeader { diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c index 339ec5fbe7a47330b3872d56d2a5bce5137b30f0..83ca27ab41d20cf47c07f3af1d7d88149cc291af 100644 --- a/pc-bios/s390-ccw/cio.c +++ b/pc-bios/s390-ccw/cio.c @@ -49,13 +49,13 @@ void enable_subchannel(SubChannelId schid) uint16_t cu_type(SubChannelId schid) { - Ccw1 sense_id_ccw; SenseId sense_data; - - sense_id_ccw.cmd_code = CCW_CMD_SENSE_ID; - sense_id_ccw.cda = ptr2u32(&sense_data); - sense_id_ccw.count = sizeof(sense_data); - sense_id_ccw.flags |= CCW_FLAG_SLI; + Ccw1 sense_id_ccw = { + .cmd_code = CCW_CMD_SENSE_ID, + .flags = CCW_FLAG_SLI, + .count = sizeof(sense_data), + .cda = ptr2u32(&sense_data), + }; if (do_cio(schid, CU_TYPE_UNKNOWN, ptr2u32(&sense_id_ccw), CCW_FMT1)) { panic("Failed to run SenseID CCw\n"); @@ -67,13 +67,13 @@ uint16_t cu_type(SubChannelId schid) int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data, uint16_t data_size) { - Ccw1 senseCcw; + Ccw1 senseCcw = { + .cmd_code = CCW_CMD_BASIC_SENSE, + .count = data_size, + .cda = ptr2u32(sense_data), + }; Irb irb; - senseCcw.cmd_code = CCW_CMD_BASIC_SENSE; - senseCcw.cda = ptr2u32(sense_data); - senseCcw.count = data_size; - return __do_cio(schid, ptr2u32(&senseCcw), CCW_FMT1, &irb); } @@ -314,7 +314,17 @@ static void print_irb_err(Irb *irb) */ static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb) { - CmdOrb orb = {}; + /* + * QEMU's CIO implementation requires prefetch and 64-bit idaws. We + * allow all paths. + */ + CmdOrb orb = { + .fmt = fmt, + .pfch = 1, + .c64 = 1, + .lpm = 0xFF, + .cpa = ccw_addr, + }; int rc; IPL_assert(fmt == 0 || fmt == 1, "Invalid ccw format"); @@ -324,12 +334,6 @@ static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb) IPL_assert(ccw_addr <= 0xFFFFFF - 8, "Invalid ccw address"); } - orb.fmt = fmt; - orb.pfch = 1; /* QEMU's cio implementation requires prefetch */ - orb.c64 = 1; /* QEMU's cio implementation requires 64-bit idaws */ - orb.lpm = 0xFF; /* All paths allowed */ - orb.cpa = ccw_addr; - rc = ssch(schid, &orb); if (rc == 1 || rc == 2) { /* Subchannel status pending or busy. Eat status and ask for retry. */ diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h index aaa432deddb9242e406422b895fb28e98ecc6f21..1e5d4e92e12c418289d27c160c7c0d8e8b2e7c07 100644 --- a/pc-bios/s390-ccw/cio.h +++ b/pc-bios/s390-ccw/cio.h @@ -122,12 +122,17 @@ typedef struct schib { } __attribute__ ((packed, aligned(4))) Schib; typedef struct subchannel_id { - __u32 cssid:8; - __u32:4; - __u32 m:1; - __u32 ssid:2; - __u32 one:1; - __u32 sch_no:16; + union { + struct { + __u16 cssid:8; + __u16 reserved:4; + __u16 m:1; + __u16 ssid:2; + __u16 one:1; + }; + __u16 sch_id; + }; + __u16 sch_no; } __attribute__ ((packed, aligned(4))) SubChannelId; struct chsc_header { diff --git a/pc-bios/s390-ccw/dasd-ipl.c b/pc-bios/s390-ccw/dasd-ipl.c index 0fc879bb8e8faac7e56c41c37dcf330f09e4bbbc..71cbae2f16e17818b8884eb1b65f16551bb468af 100644 --- a/pc-bios/s390-ccw/dasd-ipl.c +++ b/pc-bios/s390-ccw/dasd-ipl.c @@ -100,6 +100,9 @@ static void make_readipl(void) { Ccw0 *ccwIplRead = (Ccw0 *)0x00; + /* Clear out any existing data */ + memset(ccwIplRead, 0, sizeof(Ccw0)); + /* Create Read IPL ccw at address 0 */ ccwIplRead->cmd_code = CCW_CMD_READ_IPL; ccwIplRead->cda = 0x00; /* Read into address 0x00 in main memory */ diff --git a/pc-bios/s390-ccw/helper.h b/pc-bios/s390-ccw/helper.h index 78d5bc74421b4173f5e9de6d80d7a974a1be75e3..dfcfea0ff0cbb8e42eafa55c28857f7bd01cc7d2 100644 --- a/pc-bios/s390-ccw/helper.h +++ b/pc-bios/s390-ccw/helper.h @@ -14,11 +14,12 @@ #define S390_CCW_HELPER_H #include "s390-ccw.h" +#include "s390-time.h" /* Avoids compiler warnings when casting a pointer to a u32 */ static inline uint32_t ptr2u32(void *ptr) { - IPL_assert((uint64_t)ptr <= 0xffffffff, "ptr2u32: ptr too large"); + IPL_assert((uint64_t)ptr <= 0xffffffffull, "ptr2u32: ptr too large"); return (uint32_t)(uint64_t)ptr; } @@ -28,4 +29,20 @@ static inline void *u32toptr(uint32_t n) return (void *)(uint64_t)n; } +static inline void yield(void) +{ + asm volatile ("diag 0,0,0x44" + : : + : "memory", "cc"); +} + +static inline void sleep(unsigned int seconds) +{ + ulong target = get_time_seconds() + seconds; + + while (get_time_seconds() < target) { + yield(); + } +} + #endif diff --git a/pc-bios/s390-ccw/jump2ipl.c b/pc-bios/s390-ccw/jump2ipl.c index 4eba2510b045ff06157ca550285605768a3b372a..b9c70d64a5dce5465c3967bb5994dbb324925936 100644 --- a/pc-bios/s390-ccw/jump2ipl.c +++ b/pc-bios/s390-ccw/jump2ipl.c @@ -8,27 +8,28 @@ #include "libc.h" #include "s390-ccw.h" +#include "s390-arch.h" #define KERN_IMAGE_START 0x010000UL -#define PSW_MASK_64 0x0000000100000000ULL -#define PSW_MASK_32 0x0000000080000000ULL -#define PSW_MASK_SHORTPSW 0x0008000000000000ULL -#define RESET_PSW_MASK (PSW_MASK_SHORTPSW | PSW_MASK_32 | PSW_MASK_64) +#define RESET_PSW_MASK (PSW_MASK_SHORTPSW | PSW_MASK_64) +#define RESET_PSW ((uint64_t)&jump_to_IPL_addr | RESET_PSW_MASK) -typedef struct ResetInfo { - uint64_t ipl_psw; - uint32_t ipl_continue; -} ResetInfo; +static uint64_t *reset_psw = 0, save_psw, ipl_continue; -static ResetInfo save; +void write_reset_psw(uint64_t psw) +{ + *reset_psw = psw; +} -static void jump_to_IPL_2(void) +static void jump_to_IPL_addr(void) { - ResetInfo *current = 0; + __attribute__((noreturn)) void (*ipl)(void) = (void *)ipl_continue; - void (*ipl)(void) = (void *) (uint64_t) current->ipl_continue; - *current = save; - ipl(); /* should not return */ + /* Restore reset PSW */ + write_reset_psw(save_psw); + + ipl(); + /* should not return */ } void jump_to_IPL_code(uint64_t address) @@ -48,15 +49,12 @@ void jump_to_IPL_code(uint64_t address) * content of non-BIOS memory after we loaded the guest, so we * save the original content and restore it in jump_to_IPL_2. */ - ResetInfo *current = 0; - - save = *current; - - current->ipl_psw = (uint64_t) &jump_to_IPL_2; - current->ipl_psw |= RESET_PSW_MASK; - current->ipl_continue = address & 0x7fffffff; - - debug_print_int("set IPL addr to", current->ipl_continue); + if (address) { + save_psw = *reset_psw; + write_reset_psw(RESET_PSW); + ipl_continue = address; + } + debug_print_int("set IPL addr to", address ?: *reset_psw & PSW_MASK_SHORT_ADDR); /* Ensure the guest output starts fresh */ sclp_print("\n"); @@ -80,13 +78,18 @@ void jump_to_low_kernel(void) * kernel start address (when jumping to the PSW-at-zero address instead, * the kernel startup code fails when we booted from a network device). */ - if (!memcmp((char *)0x10008, "S390EP", 6)) { + if (!memcmp((char *)S390EP, "S390EP", 6)) { jump_to_IPL_code(KERN_IMAGE_START); } /* Trying to get PSW at zero address */ if (*((uint64_t *)0) & RESET_PSW_MASK) { - jump_to_IPL_code((*((uint64_t *)0)) & 0x7fffffff); + /* + * Surely nobody will try running directly from lowcore, so + * let's use 0 as an indication that we want to load the reset + * psw at 0x0 and not jump to the entry. + */ + jump_to_IPL_code(0); } /* No other option left, so use the Linux kernel start address */ diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c index 4e65b411e1d890ba7f8536d7b99f1962782eca15..5d2b7ba94de4f9afcd70d3465f4d0a4ccc83780b 100644 --- a/pc-bios/s390-ccw/main.c +++ b/pc-bios/s390-ccw/main.c @@ -36,28 +36,75 @@ LowCore *lowcore; /* Yes, this *is* a pointer to address 0 */ */ void write_subsystem_identification(void) { - SubChannelId *schid = (SubChannelId *) 184; - uint32_t *zeroes = (uint32_t *) 188; - - *schid = blk_schid; - *zeroes = 0; + lowcore->subchannel_id = blk_schid.sch_id; + lowcore->subchannel_nr = blk_schid.sch_no; + lowcore->io_int_parm = 0; } void write_iplb_location(void) { - lowcore->ptr_iplb = ptr2u32(&iplb); + if (cutype == CU_TYPE_VIRTIO && virtio_get_device_type() != VIRTIO_ID_NET) { + lowcore->ptr_iplb = ptr2u32(&iplb); + } } -void panic(const char *string) +unsigned int get_loadparm_index(void) { - sclp_print(string); - disabled_wait(); - while (1) { } + return atoui(loadparm_str); } -unsigned int get_loadparm_index(void) +static int is_dev_possibly_bootable(int dev_no, int sch_no) { - return atoui(loadparm_str); + bool is_virtio; + Schib schib; + int r; + + blk_schid.sch_no = sch_no; + r = stsch_err(blk_schid, &schib); + if (r == 3 || r == -EIO) { + return -ENODEV; + } + if (!schib.pmcw.dnv) { + return false; + } + + enable_subchannel(blk_schid); + cutype = cu_type(blk_schid); + + /* + * Note: we always have to run virtio_is_supported() here to make + * sure that the vdev.senseid data gets pre-initialized correctly + */ + is_virtio = virtio_is_supported(blk_schid); + + /* No specific devno given, just return whether the device is possibly bootable */ + if (dev_no < 0) { + switch (cutype) { + case CU_TYPE_VIRTIO: + if (is_virtio) { + /* + * Skip net devices since no IPLB is created and therefore + * no network bootloader has been loaded + */ + if (virtio_get_device_type() != VIRTIO_ID_NET) { + return true; + } + } + return false; + case CU_TYPE_DASD_3990: + case CU_TYPE_DASD_2107: + return true; + default: + return false; + } + } + + /* Caller asked for a specific devno */ + if (schib.pmcw.dev == dev_no) { + return true; + } + + return false; } /* @@ -71,53 +118,14 @@ unsigned int get_loadparm_index(void) */ static bool find_subch(int dev_no) { - Schib schib; int i, r; - bool is_virtio; for (i = 0; i < 0x10000; i++) { - blk_schid.sch_no = i; - r = stsch_err(blk_schid, &schib); - if ((r == 3) || (r == -EIO)) { + r = is_dev_possibly_bootable(dev_no, i); + if (r < 0) { break; } - if (!schib.pmcw.dnv) { - continue; - } - - enable_subchannel(blk_schid); - cutype = cu_type(blk_schid); - - /* - * Note: we always have to run virtio_is_supported() here to make - * sure that the vdev.senseid data gets pre-initialized correctly - */ - is_virtio = virtio_is_supported(blk_schid); - - /* No specific devno given, just return 1st possibly bootable device */ - if (dev_no < 0) { - switch (cutype) { - case CU_TYPE_VIRTIO: - if (is_virtio) { - /* - * Skip net devices since no IPLB is created and therefore - * no network bootloader has been loaded - */ - if (virtio_get_device_type() != VIRTIO_ID_NET) { - return true; - } - } - continue; - case CU_TYPE_DASD_3990: - case CU_TYPE_DASD_2107: - return true; - default: - continue; - } - } - - /* Caller asked for a specific devno */ - if (schib.pmcw.dev == dev_no) { + if (r == true) { return true; } } @@ -170,26 +178,20 @@ static void boot_setup(void) memcpy(lpmsg + 10, loadparm_str, 8); sclp_print(lpmsg); + /* + * Clear out any potential S390EP magic (see jump_to_low_kernel()), + * so we don't taint our decision-making process during a reboot. + */ + memset((char *)S390EP, 0, 6); + have_iplb = store_iplb(&iplb); } static void find_boot_device(void) { VDev *vdev = virtio_get_device(); - int ssid; bool found; - if (!have_iplb) { - for (ssid = 0; ssid < 0x3; ssid++) { - blk_schid.ssid = ssid; - found = find_subch(-1); - if (found) { - return; - } - } - panic("Could not find a suitable boot device (none specified)\n"); - } - switch (iplb.pbt) { case S390_IPL_TYPE_CCW: debug_print_int("device no. ", iplb.ccw.devno); @@ -212,7 +214,7 @@ static void find_boot_device(void) IPL_assert(found, "Boot device not found\n"); } -static void virtio_setup(void) +static int virtio_setup(void) { VDev *vdev = virtio_get_device(); QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; @@ -227,31 +229,68 @@ static void virtio_setup(void) sclp_print("Network boot device detected\n"); vdev->netboot_start_addr = qipl.netboot_start_addr; } else { - virtio_blk_setup_device(blk_schid); + int ret = virtio_blk_setup_device(blk_schid); + if (ret) { + return ret; + } IPL_assert(virtio_ipl_disk_is_valid(), "No valid IPL device detected"); } + + return 0; } -int main(void) +static void ipl_boot_device(void) { - sclp_setup(); - css_setup(); - boot_setup(); - find_boot_device(); - enable_subchannel(blk_schid); - switch (cutype) { case CU_TYPE_DASD_3990: case CU_TYPE_DASD_2107: dasd_ipl(blk_schid, cutype); /* no return */ break; case CU_TYPE_VIRTIO: - virtio_setup(); - zipl_load(); /* no return */ + if (virtio_setup() == 0) { + zipl_load(); /* Only returns in case of errors */ + } break; default: print_int("Attempting to boot from unexpected device type", cutype); - panic(""); + panic("\nBoot failed.\n"); + } +} + +/* + * No boot device has been specified, so we have to scan through the + * channels to find one. + */ +static void probe_boot_device(void) +{ + int ssid, sch_no, ret; + + for (ssid = 0; ssid < 0x3; ssid++) { + blk_schid.ssid = ssid; + for (sch_no = 0; sch_no < 0x10000; sch_no++) { + ret = is_dev_possibly_bootable(-1, sch_no); + if (ret < 0) { + break; + } + if (ret == true) { + ipl_boot_device(); /* Only returns if unsuccessful */ + } + } + } + + sclp_print("Could not find a suitable boot device (none specified)\n"); +} + +int main(void) +{ + sclp_setup(); + css_setup(); + boot_setup(); + if (have_iplb) { + find_boot_device(); + ipl_boot_device(); + } else { + probe_boot_device(); } panic("Failed to load OS from hard disk\n"); diff --git a/pc-bios/s390-ccw/menu.c b/pc-bios/s390-ccw/menu.c index ce3815b2010d20cb5304d920d1b9dba12588364b..de8260a5d6cf3290eba00ed9e5a7edb4105b4170 100644 --- a/pc-bios/s390-ccw/menu.c +++ b/pc-bios/s390-ccw/menu.c @@ -12,6 +12,7 @@ #include "libc.h" #include "s390-ccw.h" #include "sclp.h" +#include "s390-time.h" #define KEYCODE_NO_INP '\0' #define KEYCODE_ESCAPE '\033' diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak index 5eefb7c289395ca37fcd241ce53d40cca73bd855..577c023afe3db17ada307b2abbcc27f8ea9c03aa 100644 --- a/pc-bios/s390-ccw/netboot.mak +++ b/pc-bios/s390-ccw/netboot.mak @@ -1,8 +1,7 @@ SLOF_DIR := $(SRC_PATH)/roms/SLOF -NETOBJS := start.o sclp.o cio.o virtio.o virtio-net.o jump2ipl.o netmain.o \ - libnet.a libc.a +NETOBJS := start.o sclp.o cio.o virtio.o virtio-net.o jump2ipl.o netmain.o LIBC_INC := -nostdinc -I$(SLOF_DIR)/lib/libc/include LIBNET_INC := -I$(SLOF_DIR)/lib/libnet @@ -11,15 +10,16 @@ NETLDFLAGS := $(LDFLAGS) -Ttext=0x7800000 $(NETOBJS): QEMU_CFLAGS += $(LIBC_INC) $(LIBNET_INC) -s390-netboot.elf: $(NETOBJS) - $(call quiet-command,$(CC) $(NETLDFLAGS) -o $@ $(NETOBJS),"BUILD","$(TARGET_DIR)$@") +s390-netboot.elf: $(NETOBJS) libnet.a libc.a + $(call quiet-command,$(CC) $(NETLDFLAGS) -o $@ $^,"BUILD","$(TARGET_DIR)$@") s390-netboot.img: s390-netboot.elf $(call quiet-command,$(STRIP) --strip-unneeded $< -o $@,"STRIP","$(TARGET_DIR)$@") # libc files: -LIBC_CFLAGS := $(QEMU_CFLAGS) $(CFLAGS) $(LIBC_INC) $(LIBNET_INC) +LIBC_CFLAGS = $(QEMU_CFLAGS) $(CFLAGS) $(LIBC_INC) $(LIBNET_INC) \ + -MMD -MP -MT $@ -MF $(@:%.o=%.d) CTYPE_OBJS = isdigit.o isxdigit.o toupper.o %.o : $(SLOF_DIR)/lib/libc/ctype/%.c @@ -52,7 +52,8 @@ libc.a: $(LIBCOBJS) LIBNETOBJS := args.o dhcp.o dns.o icmpv6.o ipv6.o tcp.o udp.o bootp.o \ dhcpv6.o ethernet.o ipv4.o ndp.o tftp.o pxelinux.o -LIBNETCFLAGS := $(QEMU_CFLAGS) $(CFLAGS) -DDHCPARCH=0x1F $(LIBC_INC) $(LIBNET_INC) +LIBNETCFLAGS = $(QEMU_CFLAGS) $(CFLAGS) $(LIBC_INC) $(LIBNET_INC) \ + -DDHCPARCH=0x1F -MMD -MP -MT $@ -MF $(@:%.o=%.d) %.o : $(SLOF_DIR)/lib/libnet/%.c $(call quiet-command,$(CC) $(LIBNETCFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c index 309ffa30d992207770d51ffc7d9a2dc46dd2aa7e..056e93a818fd482afd8cc8e64cdd27ef0b2ef36b 100644 --- a/pc-bios/s390-ccw/netmain.c +++ b/pc-bios/s390-ccw/netmain.c @@ -35,6 +35,7 @@ #include "s390-ccw.h" #include "cio.h" #include "virtio.h" +#include "s390-time.h" #define DEFAULT_BOOT_RETRIES 10 #define DEFAULT_TFTP_RETRIES 20 @@ -57,24 +58,14 @@ static SubChannelId net_schid = { .one = 1 }; static uint8_t mac[6]; static uint64_t dest_timer; -static uint64_t get_timer_ms(void) -{ - uint64_t clk; - - asm volatile(" stck %0 " : : "Q"(clk) : "memory"); - - /* Bit 51 is incremented each microsecond */ - return (clk >> (63 - 51)) / 1000; -} - void set_timer(int val) { - dest_timer = get_timer_ms() + val; + dest_timer = get_time_ms() + val; } int get_timer(void) { - return dest_timer - get_timer_ms(); + return dest_timer - get_time_ms(); } int get_sec_ticks(void) @@ -448,14 +439,6 @@ static int net_try_direct_tftp_load(filename_ip_t *fn_ip) return rc; } -void panic(const char *string) -{ - sclp_print(string); - for (;;) { - disabled_wait(); - } -} - void write_subsystem_identification(void) { SubChannelId *schid = (SubChannelId *) 184; diff --git a/pc-bios/s390-ccw/s390-arch.h b/pc-bios/s390-ccw/s390-arch.h index 5f36361c0223d43439a249e84040ea9b5accea8c..a741488aaa17673315234f2d837c5022b7896dbd 100644 --- a/pc-bios/s390-ccw/s390-arch.h +++ b/pc-bios/s390-ccw/s390-arch.h @@ -26,10 +26,12 @@ _Static_assert(sizeof(struct PSWLegacy) == 8, "PSWLegacy size incorrect"); /* s390 psw bit masks */ #define PSW_MASK_IOINT 0x0200000000000000ULL +#define PSW_MASK_SHORTPSW 0x0008000000000000ULL #define PSW_MASK_WAIT 0x0002000000000000ULL #define PSW_MASK_EAMODE 0x0000000100000000ULL #define PSW_MASK_BAMODE 0x0000000080000000ULL -#define PSW_MASK_ZMODE (PSW_MASK_EAMODE | PSW_MASK_BAMODE) +#define PSW_MASK_SHORT_ADDR 0x000000007fffffffULL +#define PSW_MASK_64 (PSW_MASK_EAMODE | PSW_MASK_BAMODE) /* Low core mapping */ typedef struct LowCore { @@ -93,6 +95,9 @@ typedef struct LowCore { extern LowCore *lowcore; +/* Location of "S390EP" in a Linux binary (see arch/s390/boot/head.S) */ +#define S390EP 0x10008 + static inline void set_prefix(uint32_t address) { asm volatile("spx %0" : : "m" (address) : "memory"); diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h index 21f27e79906ea297c4480eeaee2ea939c792ccfd..6cd92669e96688674416381aea446cf0cdd7e951 100644 --- a/pc-bios/s390-ccw/s390-ccw.h +++ b/pc-bios/s390-ccw/s390-ccw.h @@ -27,12 +27,10 @@ typedef unsigned long long __u64; #define false 0 #define PAGE_SIZE 4096 -#ifndef EIO #define EIO 1 -#endif -#ifndef EBUSY #define EBUSY 2 -#endif +#define ENODEV 3 + #ifndef NULL #define NULL 0 #endif @@ -50,12 +48,11 @@ typedef unsigned long long __u64; #include "iplb.h" /* start.s */ -void disabled_wait(void); +void disabled_wait(void) __attribute__ ((__noreturn__)); void consume_sclp_int(void); void consume_io_int(void); /* main.c */ -void panic(const char *string); void write_subsystem_identification(void); void write_iplb_location(void); extern char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE))); @@ -72,15 +69,14 @@ int sclp_read(char *str, size_t count); unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2, ulong subchan_id, void *load_addr); bool virtio_is_supported(SubChannelId schid); -void virtio_blk_setup_device(SubChannelId schid); +int virtio_blk_setup_device(SubChannelId schid); int virtio_read(ulong sector, void *load_addr); -u64 get_clock(void); -ulong get_second(void); /* bootmap.c */ void zipl_load(void); /* jump2ipl.c */ +void write_reset_psw(uint64_t psw); void jump_to_IPL_code(uint64_t address); void jump_to_low_kernel(void); @@ -93,6 +89,12 @@ bool menu_is_enabled_enum(void); #define MAX_BOOT_ENTRIES 31 +static inline void panic(const char *string) +{ + sclp_print(string); + disabled_wait(); +} + static inline void fill_hex(char *out, unsigned char val) { const char hex[] = "0123456789abcdef"; @@ -144,24 +146,8 @@ static inline void debug_print_addr(const char *desc, void *p) #define KVM_S390_VIRTIO_SET_STATUS 2 #define KVM_S390_VIRTIO_CCW_NOTIFY 3 -static inline void yield(void) -{ - asm volatile ("diag 0,0,0x44" - : : - : "memory", "cc"); -} - #define MAX_SECTOR_SIZE 4096 -static inline void sleep(unsigned int seconds) -{ - ulong target = get_second() + seconds; - - while (get_second() < target) { - yield(); - } -} - static inline void IPL_assert(bool term, const char *message) { if (!term) { diff --git a/pc-bios/s390-ccw/s390-time.h b/pc-bios/s390-ccw/s390-time.h new file mode 100644 index 0000000000000000000000000000000000000000..ed6d982371855a79d5e3e4a061e358164fd11f3c --- /dev/null +++ b/pc-bios/s390-ccw/s390-time.h @@ -0,0 +1,23 @@ +#ifndef TIME_H +#define TIME_H + +static inline u64 get_clock(void) +{ + u64 r; + + asm volatile("stck %0" : "=Q" (r) : : "cc"); + return r; +} + +static inline u64 get_time_ms(void) +{ + /* Bit 51 is incremented each microsecond */ + return (get_clock() >> 12) / 1000; +} + +static inline u64 get_time_seconds(void) +{ + return get_time_ms() / 1000; +} + +#endif diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S index aa8fceb19da2164aeedb3ab9009845bfaa9828ed..4d5ad21653d0992d4e65847258167d7aa419d46d 100644 --- a/pc-bios/s390-ccw/start.S +++ b/pc-bios/s390-ccw/start.S @@ -34,7 +34,10 @@ remainder: larl %r2,memsetxc ex %r3,0(%r2) done: - j main /* And call C */ + /* set up a pgm exception disabled wait psw */ + larl %r2, disabled_wait_psw + mvc 0x01d0(16), 0(%r2) + j main /* And call C */ memsetxc: xc 0(1,%r1),0(%r1) @@ -47,8 +50,9 @@ memsetxc: */ .globl disabled_wait disabled_wait: - larl %r1,disabled_wait_psw - lpswe 0(%r1) + larl %r1,disabled_wait_psw + lpswe 0(%r1) +1: j 1b /* diff --git a/pc-bios/s390-ccw/virtio-blkdev.c b/pc-bios/s390-ccw/virtio-blkdev.c index 11c56261cadec4d4be7409b595ba82ea626782cb..7d35050292dea3befb9a14c88af417252cf81d71 100644 --- a/pc-bios/s390-ccw/virtio-blkdev.c +++ b/pc-bios/s390-ccw/virtio-blkdev.c @@ -263,9 +263,10 @@ uint64_t virtio_get_blocks(void) return 0; } -void virtio_blk_setup_device(SubChannelId schid) +int virtio_blk_setup_device(SubChannelId schid) { VDev *vdev = virtio_get_device(); + int ret = 0; vdev->schid = schid; virtio_setup_ccw(vdev); @@ -288,9 +289,11 @@ void virtio_blk_setup_device(SubChannelId schid) "Config: CDB size mismatch"); sclp_print("Using virtio-scsi.\n"); - virtio_scsi_setup(vdev); + ret = virtio_scsi_setup(vdev); break; default: panic("\n! No IPL device available !\n"); } + + return ret; } diff --git a/pc-bios/s390-ccw/virtio-net.c b/pc-bios/s390-ccw/virtio-net.c index ff7f4dad2597eeae9f98d0abeae9dccbe1ce63ea..2fcb0a58c5b03de108342d00c189caf4d331dfed 100644 --- a/pc-bios/s390-ccw/virtio-net.c +++ b/pc-bios/s390-ccw/virtio-net.c @@ -19,6 +19,8 @@ #include #include "s390-ccw.h" #include "virtio.h" +#include "s390-time.h" +#include "helper.h" #ifndef DEBUG_VIRTIO_NET #define DEBUG_VIRTIO_NET 0 diff --git a/pc-bios/s390-ccw/virtio-scsi.c b/pc-bios/s390-ccw/virtio-scsi.c index 4fe4b9d261a6c88dada4df3bfde3093cdd2f7e07..2c8d0f30970a5155db0b82e449fd4841bbefef2c 100644 --- a/pc-bios/s390-ccw/virtio-scsi.c +++ b/pc-bios/s390-ccw/virtio-scsi.c @@ -14,6 +14,8 @@ #include "virtio.h" #include "scsi.h" #include "virtio-scsi.h" +#include "s390-time.h" +#include "helper.h" static ScsiDevice default_scsi_device; static VirtioScsiCmdReq req; @@ -192,7 +194,12 @@ static bool scsi_read_capacity(VDev *vdev, /* virtio-scsi routines */ -static void virtio_scsi_locate_device(VDev *vdev) +/* + * Tries to locate a SCSI device and and adds the information for the found + * device to the vdev->scsi_device structure. + * Returns 0 if SCSI device could be located, or a error code < 0 otherwise + */ +static int virtio_scsi_locate_device(VDev *vdev) { const uint16_t channel = 0; /* again, it's what QEMU does */ uint16_t target; @@ -218,7 +225,7 @@ static void virtio_scsi_locate_device(VDev *vdev) IPL_check(sdev->channel == 0, "non-zero channel requested"); IPL_check(sdev->target <= vdev->config.scsi.max_target, "target# high"); IPL_check(sdev->lun <= vdev->config.scsi.max_lun, "LUN# high"); - return; + return 0; } for (target = 0; target <= vdev->config.scsi.max_target; target++) { @@ -245,18 +252,20 @@ static void virtio_scsi_locate_device(VDev *vdev) */ sdev->lun = r->lun[0].v16[0]; /* it's returned this way */ debug_print_int("Have to use LUN", sdev->lun); - return; /* we have to use this device */ + return 0; /* we have to use this device */ } for (i = 0; i < luns; i++) { if (r->lun[i].v64) { /* Look for non-zero LUN - we have where to choose from */ sdev->lun = r->lun[i].v16[0]; debug_print_int("Will use LUN", sdev->lun); - return; /* we have found a device */ + return 0; /* we have found a device */ } } } - panic("\n! Cannot locate virtio-scsi device !\n"); + + sclp_print("Warning: Could not locate a usable virtio-scsi device\n"); + return -ENODEV; } int virtio_scsi_read_many(VDev *vdev, @@ -320,17 +329,20 @@ static void scsi_parse_capacity_report(void *data, } } -void virtio_scsi_setup(VDev *vdev) +int virtio_scsi_setup(VDev *vdev) { int retry_test_unit_ready = 3; uint8_t data[256]; uint32_t data_size = sizeof(data); ScsiInquiryEvpdPages *evpd = &scsi_inquiry_evpd_pages_response; ScsiInquiryEvpdBl *evpd_bl = &scsi_inquiry_evpd_bl_response; - int i; + int i, ret; vdev->scsi_device = &default_scsi_device; - virtio_scsi_locate_device(vdev); + ret = virtio_scsi_locate_device(vdev); + if (ret < 0) { + return ret; + } /* We have to "ping" the device before it becomes readable */ while (!scsi_test_unit_ready(vdev)) { @@ -415,4 +427,6 @@ void virtio_scsi_setup(VDev *vdev) } scsi_parse_capacity_report(data, &vdev->scsi_last_block, (uint32_t *) &vdev->scsi_block_size); + + return 0; } diff --git a/pc-bios/s390-ccw/virtio-scsi.h b/pc-bios/s390-ccw/virtio-scsi.h index 4c4f4bbc31ce64d4b93bfa2b0d2b3fe83e9969ea..4b14c2c2f909095404d7878fc4873b25315b16fa 100644 --- a/pc-bios/s390-ccw/virtio-scsi.h +++ b/pc-bios/s390-ccw/virtio-scsi.h @@ -67,7 +67,7 @@ static inline bool virtio_scsi_response_ok(const VirtioScsiCmdResp *r) return r->response == VIRTIO_SCSI_S_OK && r->status == CDB_STATUS_GOOD; } -void virtio_scsi_setup(VDev *vdev); +int virtio_scsi_setup(VDev *vdev); int virtio_scsi_read_many(VDev *vdev, ulong sector, void *load_addr, int sec_num); diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c index fb40ca982853a8d7ac5afd2f403c818f4d90be3f..ab49840db853160c82de46a7065b86b3d5bf0eac 100644 --- a/pc-bios/s390-ccw/virtio.c +++ b/pc-bios/s390-ccw/virtio.c @@ -15,6 +15,7 @@ #include "virtio-scsi.h" #include "bswap.h" #include "helper.h" +#include "s390-time.h" #define VRING_WAIT_REPLY_TIMEOUT 30 @@ -157,19 +158,6 @@ void vring_send_buf(VRing *vr, void *p, int len, int flags) } } -u64 get_clock(void) -{ - u64 r; - - asm volatile("stck %0" : "=Q" (r) : : "cc"); - return r; -} - -ulong get_second(void) -{ - return (get_clock() >> 12) / 1000000; -} - int vr_poll(VRing *vr) { if (vr->used->idx == vr->used_idx) { @@ -194,7 +182,7 @@ int vr_poll(VRing *vr) */ int vring_wait_reply(void) { - ulong target_second = get_second() + vdev.wait_reply_timeout; + ulong target_second = get_time_seconds() + vdev.wait_reply_timeout; /* Wait for any queue to be updated by the host */ do { @@ -207,7 +195,7 @@ int vring_wait_reply(void) if (r) { return 0; } - } while (!vdev.wait_reply_timeout || (get_second() < target_second)); + } while (!vdev.wait_reply_timeout || (get_time_seconds() < target_second)); return 1; } diff --git a/pc-bios/s390-netboot.img b/pc-bios/s390-netboot.img index 6bb5c86eb086a6b06e3f1a42664cdbd27366f992..120bd40ca907f2e9f7830ad07899a4ed22bc8512 100644 Binary files a/pc-bios/s390-netboot.img and b/pc-bios/s390-netboot.img differ diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin index 80bbf91a186c7eec76af3ae6af50c2c841a77579..448dcada367f32130ff6ccc6dcb482dcc3fa853e 100644 Binary files a/pc-bios/slof.bin and b/pc-bios/slof.bin differ diff --git a/pc-bios/vgabios-ati.bin b/pc-bios/vgabios-ati.bin index 6202cf73e254ccac67b3289230a23f3f45f6b41f..118caacde6af3f4b0e06851fb3ab85aa14c7c687 100644 Binary files a/pc-bios/vgabios-ati.bin and b/pc-bios/vgabios-ati.bin differ diff --git a/pc-bios/vgabios-bochs-display.bin b/pc-bios/vgabios-bochs-display.bin index b675f86bc622b77afd8b24a50948663aeae2c2ce..d79124b76010580a220fc6a92df7c83350ac5a58 100644 Binary files a/pc-bios/vgabios-bochs-display.bin and b/pc-bios/vgabios-bochs-display.bin differ diff --git a/pc-bios/vgabios-cirrus.bin b/pc-bios/vgabios-cirrus.bin index 63fde14fea4a2d4873b6efc02b0437c1802625ea..37bf5e7fe72d5e9f4ecc2747cd5eb9d1eb8d9f41 100644 Binary files a/pc-bios/vgabios-cirrus.bin and b/pc-bios/vgabios-cirrus.bin differ diff --git a/pc-bios/vgabios-qxl.bin b/pc-bios/vgabios-qxl.bin index 80168826e2e5cdba8fb6a7805adf061f3cf38685..0ff8ff21f00582e1738b052e0bf959be3aeafcae 100644 Binary files a/pc-bios/vgabios-qxl.bin and b/pc-bios/vgabios-qxl.bin differ diff --git a/pc-bios/vgabios-ramfb.bin b/pc-bios/vgabios-ramfb.bin index 1dc413dcd2ab1720a46d0e7ee7abca46469200b5..df5e9d615a2b2f706bcc4a7be1cc4050d6b4ceeb 100644 Binary files a/pc-bios/vgabios-ramfb.bin and b/pc-bios/vgabios-ramfb.bin differ diff --git a/pc-bios/vgabios-stdvga.bin b/pc-bios/vgabios-stdvga.bin index f92b9a664dfbdbf953efddbba2250d7556c6b53a..70f60941533d7e8567a0d107f6e671c8b5635ca8 100644 Binary files a/pc-bios/vgabios-stdvga.bin and b/pc-bios/vgabios-stdvga.bin differ diff --git a/pc-bios/vgabios-virtio.bin b/pc-bios/vgabios-virtio.bin index b0d2f70670303c9d0daafea45e9bbf7473ec127e..65af5be59d17c764c3ae5d7527a824b153765312 100644 Binary files a/pc-bios/vgabios-virtio.bin and b/pc-bios/vgabios-virtio.bin differ diff --git a/pc-bios/vgabios-vmware.bin b/pc-bios/vgabios-vmware.bin index 1c2776e8cf6b02f4e01a4c4f1616cdc190417a34..89d42b32c1f3dda0a489f1e2f8d5246b8f6342cb 100644 Binary files a/pc-bios/vgabios-vmware.bin and b/pc-bios/vgabios-vmware.bin differ diff --git a/pc-bios/vgabios.bin b/pc-bios/vgabios.bin index c5aad8f3a99f9be693b008fd921f50a601c41be8..320471e18d34b9398b503af0df932a55e39eed4c 100644 Binary files a/pc-bios/vgabios.bin and b/pc-bios/vgabios.bin differ diff --git a/plugins/.gitignore b/plugins/.gitignore deleted file mode 100644 index 7b8aaa1f109854c0ac7985bbde223b39df36ff82..0000000000000000000000000000000000000000 --- a/plugins/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -qemu-plugins-ld.symbols -qemu-plugins-ld64.symbols diff --git a/plugins/Makefile.objs b/plugins/Makefile.objs deleted file mode 100644 index 6f14d91ccb9099383ccb4765678de24f7ffa05e2..0000000000000000000000000000000000000000 --- a/plugins/Makefile.objs +++ /dev/null @@ -1,21 +0,0 @@ -# -# Plugin Support -# - -obj-y += loader.o -obj-y += core.o -obj-y += api.o - -# Abuse -libs suffix to only link with --dynamic-list/-exported_symbols_list -# when the final binary includes the plugin object. -# -# Note that simply setting LDFLAGS is not enough: we build binaries that -# never link plugin.o, and the linker might fail (at least ld64 does) -# if the symbols in the list are not in the output binary. -ifdef CONFIG_HAS_LD_DYNAMIC_LIST -api.o-libs := -Wl,--dynamic-list=$(BUILD_DIR)/qemu-plugins-ld.symbols -else -ifdef CONFIG_HAS_LD_EXPORTED_SYMBOLS_LIST -api.o-libs := -Wl,-exported_symbols_list,$(BUILD_DIR)/qemu-plugins-ld64.symbols -endif -endif diff --git a/plugins/loader.c b/plugins/loader.c index 685d334e1a16852f82ca605832a15248939e7414..8ac5dbc20f01554147d2cbc1d8acef51567eb9ce 100644 --- a/plugins/loader.c +++ b/plugins/loader.c @@ -235,6 +235,7 @@ static int plugin_load(struct qemu_plugin_desc *desc, const qemu_info_t *info) return rc; err_symbol: + g_module_close(ctx->handle); err_dlopen: qemu_vfree(ctx); return 1; diff --git a/plugins/meson.build b/plugins/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..e77723010e6ebbed7b4cdaca6207d869f6e00edd --- /dev/null +++ b/plugins/meson.build @@ -0,0 +1,13 @@ +if 'CONFIG_HAS_LD_DYNAMIC_LIST' in config_host + plugin_ldflags = ['-Wl,--dynamic-list=' + (meson.build_root() / 'qemu-plugins-ld.symbols')] +elif 'CONFIG_HAS_LD_EXPORTED_SYMBOLS_LIST' in config_host + plugin_ldflags = ['-Wl,-exported_symbols_list,' + (meson.build_root() / 'qemu-plugins-ld64.symbols')] +else + plugin_ldflags = [] +endif + +specific_ss.add(when: 'CONFIG_PLUGIN', if_true: [files( + 'loader.c', + 'core.c', + 'api.c', +), declare_dependency(link_args: plugin_ldflags)]) diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 0000000000000000000000000000000000000000..cc4b5c3b36c51e5837cd07a1b6af762f96aa0fb6 --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1,8 @@ +bg +de_DE +fr_FR +hu +it +sv +tr +zh_CN diff --git a/po/Makefile b/po/Makefile deleted file mode 100644 index c041f4c858ee26866d2a20e67e200fd5e79b4e3b..0000000000000000000000000000000000000000 --- a/po/Makefile +++ /dev/null @@ -1,52 +0,0 @@ -# This makefile is very special as it's meant to build as part of the build -# process and also within the source tree to update the translation files. - -# Set SRC_PATH for in-tree builds without configuration. -SRC_PATH=.. - -# The default target must come before any include statements. -all: - -.PHONY: all build clean install update - -%.mo: %.po - $(call quiet-command, msgfmt -o $@ $<,"GEN","$@") - --include ../config-host.mak -include $(SRC_PATH)/rules.mak - -PO_PATH=$(SRC_PATH)/po - -VERSION=$(shell cat $(SRC_PATH)/VERSION) -SRCS=$(filter-out $(PO_PATH)/messages.po,$(wildcard $(PO_PATH)/*.po)) -OBJS=$(patsubst $(PO_PATH)/%.po,%.mo,$(SRCS)) - -vpath %.po $(PO_PATH) - -all: - @echo "Use 'make update' to update translation files or use 'make build'" - @echo "or 'make install' to build and install the translation files." - -update: $(SRCS) - -build: $(OBJS) - -clean: - rm -f $(OBJS) - -install: $(OBJS) - for obj in $(OBJS); do \ - base=$$(basename $$obj .mo); \ - $(INSTALL) -d $(DESTDIR)$(prefix)/share/locale/$$base/LC_MESSAGES; \ - $(INSTALL) -m644 $$obj $(DESTDIR)$(prefix)/share/locale/$$base/LC_MESSAGES/qemu.mo; \ - done - -$(PO_PATH)/messages.po: $(SRC_PATH)/ui/gtk.c - $(call quiet-command, ( cd $(SRC_PATH) && \ - xgettext -o - --from-code=UTF-8 --foreign-user --no-location \ - --package-name=QEMU --package-version=$(VERSION) \ - --msgid-bugs-address=qemu-devel@nongnu.org -k_ -C ui/gtk.c | \ - sed -e s/CHARSET/UTF-8/) >$@,"GEN","$@") - -$(PO_PATH)/%.po: $(PO_PATH)/messages.po - $(call quiet-command, msgmerge -q $@ $< > $@.bak && mv $@.bak $@,"GEN","$@") diff --git a/po/POTFILES b/po/POTFILES new file mode 100644 index 0000000000000000000000000000000000000000..d34d5ed9aabfc5fd7bfb92a9c9370fa1e126d79b --- /dev/null +++ b/po/POTFILES @@ -0,0 +1 @@ +ui/gtk.c diff --git a/po/meson.build b/po/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..1387fd979aa3df7abb8e33743f3de19570fc05fb --- /dev/null +++ b/po/meson.build @@ -0,0 +1,7 @@ +i18n = import('i18n') + +if get_option('gettext') + i18n.gettext(meson.project_name(), + args: '--msgid-bugs-address=qemu-devel@nongnu.org', + preset: 'glib') +endif diff --git a/po/messages.po b/po/sv.po similarity index 46% rename from po/messages.po rename to po/sv.po index 065bd459a04ad6b96ef69514026ae1efac0cdce0..1e430edd65ad14e7c9355f93dc3f61193e173df0 100644 --- a/po/messages.po +++ b/po/sv.po @@ -1,74 +1,75 @@ -# SOME DESCRIPTIVE TITLE. +# Swedish translation of qemu po-file. # This file is put in the public domain. -# FIRST AUTHOR , YEAR. +# Sebastian Rasmussen , 2019. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: QEMU 2.12.91\n" "Report-Msgid-Bugs-To: qemu-devel@nongnu.org\n" "POT-Creation-Date: 2018-07-18 07:56+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" +"PO-Revision-Date: 2019-08-16 21:19+0200\n" +"Last-Translator: Sebastian Rasmussen \n" +"Language-Team: Swedish \n" +"Language: sv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.2.3\n" msgid " - Press Ctrl+Alt+G to release grab" -msgstr "" +msgstr " - Tryck Ctrl+Alt+G för att sluta fĂ„nga" msgid " [Paused]" -msgstr "" +msgstr " [Pausad]" msgid "_Pause" -msgstr "" +msgstr "_Paus" msgid "_Reset" -msgstr "" +msgstr "_Starta om" msgid "Power _Down" -msgstr "" +msgstr "StĂ€ng _ner" msgid "_Quit" -msgstr "" +msgstr "_Avsluta" msgid "_Fullscreen" -msgstr "" +msgstr "_HelskĂ€rm" msgid "_Copy" -msgstr "" +msgstr "_Kopiera" msgid "Zoom _In" -msgstr "" +msgstr "Zooma _in" msgid "Zoom _Out" -msgstr "" +msgstr "Zooma _ut" msgid "Best _Fit" -msgstr "" +msgstr "Anpassad _storlek" msgid "Zoom To _Fit" -msgstr "" +msgstr "Zooma ti_ll anpassad storlek" msgid "Grab On _Hover" -msgstr "" +msgstr "FĂ„nga vi_d hovring" msgid "_Grab Input" -msgstr "" +msgstr "FĂ„n_ga inmatning" msgid "Show _Tabs" -msgstr "" +msgstr "Visa _flika" msgid "Detach Tab" -msgstr "" +msgstr "Frigör flik" msgid "Show Menubar" -msgstr "" +msgstr "Visa menyrad" msgid "_Machine" -msgstr "" +msgstr "_Maskin" msgid "_View" -msgstr "" +msgstr "_Visa" diff --git a/python/mypy.ini b/python/mypy.ini new file mode 100644 index 0000000000000000000000000000000000000000..1a581c5f1eace4d6ad66c49db0dde6c3772f94b7 --- /dev/null +++ b/python/mypy.ini @@ -0,0 +1,4 @@ +[mypy] +strict = True +python_version = 3.6 +warn_unused_configs = True diff --git a/python/qemu/.flake8 b/python/qemu/.flake8 new file mode 100644 index 0000000000000000000000000000000000000000..45d8146f3f50b8bbc83aa6ad9255874f38bc1bbf --- /dev/null +++ b/python/qemu/.flake8 @@ -0,0 +1,2 @@ +[flake8] +extend-ignore = E722 # Pylint handles this, but smarter. \ No newline at end of file diff --git a/python/qemu/.isort.cfg b/python/qemu/.isort.cfg new file mode 100644 index 0000000000000000000000000000000000000000..6d0fd6cc0d3d02028e3ff55ba0d2e7f4cb606fe2 --- /dev/null +++ b/python/qemu/.isort.cfg @@ -0,0 +1,7 @@ +[settings] +force_grid_wrap=4 +force_sort_within_sections=True +include_trailing_comma=True +line_length=72 +lines_after_imports=2 +multi_line_output=3 \ No newline at end of file diff --git a/python/qemu/accel.py b/python/qemu/accel.py index 36ae85791eed8b905567d028fa3db8d0ab3bc0cc..297933df2a316475f49bdf320c88d535d96ce945 100644 --- a/python/qemu/accel.py +++ b/python/qemu/accel.py @@ -17,18 +17,21 @@ import logging import os import subprocess +from typing import List, Optional + LOG = logging.getLogger(__name__) # Mapping host architecture to any additional architectures it can # support which often includes its 32 bit cousin. ADDITIONAL_ARCHES = { - "x86_64" : "i386", - "aarch64" : "armhf", - "ppc64le" : "ppc64", + "x86_64": "i386", + "aarch64": "armhf", + "ppc64le": "ppc64", } -def list_accel(qemu_bin): + +def list_accel(qemu_bin: str) -> List[str]: """ List accelerators enabled in the QEMU binary. @@ -47,7 +50,9 @@ def list_accel(qemu_bin): # Skip the first line which is the header. return [acc.strip() for acc in out.splitlines()[1:]] -def kvm_available(target_arch=None, qemu_bin=None): + +def kvm_available(target_arch: Optional[str] = None, + qemu_bin: Optional[str] = None) -> bool: """ Check if KVM is available using the following heuristic: - Kernel module is present in the host; @@ -69,7 +74,8 @@ def kvm_available(target_arch=None, qemu_bin=None): return False return True -def tcg_available(qemu_bin): + +def tcg_available(qemu_bin: str) -> bool: """ Check if TCG is available. diff --git a/python/qemu/console_socket.py b/python/qemu/console_socket.py new file mode 100644 index 0000000000000000000000000000000000000000..f060d79e06da671a34ad575220d3bcbedf58f77a --- /dev/null +++ b/python/qemu/console_socket.py @@ -0,0 +1,121 @@ +""" +QEMU Console Socket Module: + +This python module implements a ConsoleSocket object, +which can drain a socket and optionally dump the bytes to file. +""" +# Copyright 2020 Linaro +# +# Authors: +# Robert Foley +# +# This code is licensed under the GPL version 2 or later. See +# the COPYING file in the top-level directory. +# + +from collections import deque +import socket +import threading +import time +from typing import Deque, Optional + + +class ConsoleSocket(socket.socket): + """ + ConsoleSocket represents a socket attached to a char device. + + Optionally (if drain==True), drains the socket and places the bytes + into an in memory buffer for later processing. + + Optionally a file path can be passed in and we will also + dump the characters to this file for debugging purposes. + """ + def __init__(self, address: str, file: Optional[str] = None, + drain: bool = False): + self._recv_timeout_sec = 300.0 + self._sleep_time = 0.5 + self._buffer: Deque[int] = deque() + socket.socket.__init__(self, socket.AF_UNIX, socket.SOCK_STREAM) + self.connect(address) + self._logfile = None + if file: + self._logfile = open(file, "bw") + self._open = True + self._drain_thread = None + if drain: + self._drain_thread = self._thread_start() + + def _drain_fn(self) -> None: + """Drains the socket and runs while the socket is open.""" + while self._open: + try: + self._drain_socket() + except socket.timeout: + # The socket is expected to timeout since we set a + # short timeout to allow the thread to exit when + # self._open is set to False. + time.sleep(self._sleep_time) + + def _thread_start(self) -> threading.Thread: + """Kick off a thread to drain the socket.""" + # Configure socket to not block and timeout. + # This allows our drain thread to not block + # on recieve and exit smoothly. + socket.socket.setblocking(self, False) + socket.socket.settimeout(self, 1) + drain_thread = threading.Thread(target=self._drain_fn) + drain_thread.daemon = True + drain_thread.start() + return drain_thread + + def close(self) -> None: + """Close the base object and wait for the thread to terminate""" + if self._open: + self._open = False + if self._drain_thread is not None: + thread, self._drain_thread = self._drain_thread, None + thread.join() + socket.socket.close(self) + if self._logfile: + self._logfile.close() + self._logfile = None + + def _drain_socket(self) -> None: + """process arriving characters into in memory _buffer""" + data = socket.socket.recv(self, 1) + if self._logfile: + self._logfile.write(data) + self._logfile.flush() + self._buffer.extend(data) + + def recv(self, bufsize: int = 1, flags: int = 0) -> bytes: + """Return chars from in memory buffer. + Maintains the same API as socket.socket.recv. + """ + if self._drain_thread is None: + # Not buffering the socket, pass thru to socket. + return socket.socket.recv(self, bufsize, flags) + assert not flags, "Cannot pass flags to recv() in drained mode" + start_time = time.time() + while len(self._buffer) < bufsize: + time.sleep(self._sleep_time) + elapsed_sec = time.time() - start_time + if elapsed_sec > self._recv_timeout_sec: + raise socket.timeout + return bytes((self._buffer.popleft() for i in range(bufsize))) + + def setblocking(self, value: bool) -> None: + """When not draining we pass thru to the socket, + since when draining we control socket blocking. + """ + if self._drain_thread is None: + socket.socket.setblocking(self, value) + + def settimeout(self, value: Optional[float]) -> None: + """When not draining we pass thru to the socket, + since when draining we control the timeout. + """ + if value is not None: + self._recv_timeout_sec = value + if self._drain_thread is None: + socket.socket.settimeout(self, value) diff --git a/python/qemu/machine.py b/python/qemu/machine.py index b9a98e2c862767a3e639fbb359cf9fa9b7b2d221..64d966aeeb8ac3322b3ae78a5ec729c54b035ebb 100644 --- a/python/qemu/machine.py +++ b/python/qemu/machine.py @@ -18,17 +18,33 @@ # import errno +from itertools import chain import logging import os -import subprocess import shutil +import signal import socket +import subprocess import tempfile +from types import TracebackType +from typing import ( + Any, + BinaryIO, + Dict, + List, + Optional, + Sequence, + Tuple, + Type, +) + +from . import console_socket, qmp +from .qmp import QMPMessage, QMPReturnValue, SocketAddrT -from . import qmp LOG = logging.getLogger(__name__) + class QEMUMachineError(Exception): """ Exception called when an error in QEMUMachine happens. @@ -45,33 +61,35 @@ class QEMUMachineAddDeviceError(QEMUMachineError): """ -class MonitorResponseError(qmp.QMPError): +class AbnormalShutdown(QEMUMachineError): """ - Represents erroneous QMP monitor reply + Exception raised when a graceful shutdown was requested, but not performed. """ - def __init__(self, reply): - try: - desc = reply["error"]["desc"] - except KeyError: - desc = reply - super(MonitorResponseError, self).__init__(desc) - self.reply = reply -class QEMUMachine(object): +class QEMUMachine: """ - A QEMU VM + A QEMU VM. - Use this object as a context manager to ensure the QEMU process terminates:: + Use this object as a context manager to ensure + the QEMU process terminates:: with VM(binary) as vm: ... # vm is guaranteed to be shut down here """ - def __init__(self, binary, args=None, wrapper=None, name=None, - test_dir="/var/tmp", monitor_address=None, - socket_scm_helper=None, sock_dir=None): + def __init__(self, + binary: str, + args: Sequence[str] = (), + wrapper: Sequence[str] = (), + name: Optional[str] = None, + test_dir: str = "/var/tmp", + monitor_address: Optional[SocketAddrT] = None, + socket_scm_helper: Optional[str] = None, + sock_dir: Optional[str] = None, + drain_console: bool = False, + console_log: Optional[str] = None): ''' Initialize a QEMUMachine @@ -82,61 +100,78 @@ def __init__(self, binary, args=None, wrapper=None, name=None, @param test_dir: where to create socket and log file @param monitor_address: address for QMP monitor @param socket_scm_helper: helper program, required for send_fd_scm() + @param sock_dir: where to create socket (overrides test_dir for sock) + @param drain_console: (optional) True to drain console socket to buffer + @param console_log: (optional) path to console log file @note: Qemu process is not started until launch() is used. ''' - if args is None: - args = [] - if wrapper is None: - wrapper = [] - if name is None: - name = "qemu-%d" % os.getpid() - if sock_dir is None: - sock_dir = test_dir - self._name = name - self._monitor_address = monitor_address - self._vm_monitor = None - self._qemu_log_path = None - self._qemu_log_file = None - self._popen = None + # Direct user configuration + self._binary = binary - self._args = list(args) # Force copy args in case we modify them + self._args = list(args) self._wrapper = wrapper - self._events = [] - self._iolog = None + + self._name = name or "qemu-%d" % os.getpid() + self._test_dir = test_dir + self._sock_dir = sock_dir or self._test_dir self._socket_scm_helper = socket_scm_helper + + if monitor_address is not None: + self._monitor_address = monitor_address + self._remove_monitor_sockfile = False + else: + self._monitor_address = os.path.join( + self._sock_dir, f"{self._name}-monitor.sock" + ) + self._remove_monitor_sockfile = True + + self._console_log_path = console_log + if self._console_log_path: + # In order to log the console, buffering needs to be enabled. + self._drain_console = True + else: + self._drain_console = drain_console + + # Runstate + self._qemu_log_path: Optional[str] = None + self._qemu_log_file: Optional[BinaryIO] = None + self._popen: Optional['subprocess.Popen[bytes]'] = None + self._events: List[QMPMessage] = [] + self._iolog: Optional[str] = None self._qmp_set = True # Enable QMP monitor by default. - self._qmp = None - self._qemu_full_args = None - self._test_dir = test_dir - self._temp_dir = None - self._sock_dir = sock_dir + self._qmp_connection: Optional[qmp.QEMUMonitorProtocol] = None + self._qemu_full_args: Tuple[str, ...] = () + self._temp_dir: Optional[str] = None self._launched = False - self._machine = None + self._machine: Optional[str] = None self._console_index = 0 self._console_set = False - self._console_device_type = None - self._console_address = None - self._console_socket = None - self._remove_files = [] - - # just in case logging wasn't configured by the main script: - logging.basicConfig() - - def __enter__(self): + self._console_device_type: Optional[str] = None + self._console_address = os.path.join( + self._sock_dir, f"{self._name}-console.sock" + ) + self._console_socket: Optional[socket.socket] = None + self._remove_files: List[str] = [] + self._user_killed = False + + def __enter__(self) -> 'QEMUMachine': return self - def __exit__(self, exc_type, exc_val, exc_tb): + def __exit__(self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType]) -> None: self.shutdown() - return False - def add_monitor_null(self): + def add_monitor_null(self) -> None: """ This can be used to add an unused monitor instance. """ self._args.append('-monitor') self._args.append('null') - def add_fd(self, fd, fdset, opaque, opts=''): + def add_fd(self, fd: int, fdset: int, + opaque: str, opts: str = '') -> 'QEMUMachine': """ Pass a file descriptor to the VM """ @@ -155,7 +190,8 @@ def add_fd(self, fd, fdset, opaque, opts=''): self._args.append(','.join(options)) return self - def send_fd_scm(self, fd=None, file_path=None): + def send_fd_scm(self, fd: Optional[int] = None, + file_path: Optional[str] = None) -> int: """ Send an fd or file_path to socket_scm_helper. @@ -188,8 +224,10 @@ def send_fd_scm(self, fd=None, file_path=None): fd_param.append(str(fd)) devnull = open(os.path.devnull, 'rb') - proc = subprocess.Popen(fd_param, stdin=devnull, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, close_fds=False) + proc = subprocess.Popen( + fd_param, stdin=devnull, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, close_fds=False + ) output = proc.communicate()[0] if output: LOG.debug(output) @@ -197,7 +235,7 @@ def send_fd_scm(self, fd=None, file_path=None): return proc.returncode @staticmethod - def _remove_if_exists(path): + def _remove_if_exists(path: str) -> None: """ Remove file object at path if it exists """ @@ -208,46 +246,52 @@ def _remove_if_exists(path): return raise - def is_running(self): + def is_running(self) -> bool: """Returns true if the VM is running.""" return self._popen is not None and self._popen.poll() is None - def exitcode(self): + @property + def _subp(self) -> 'subprocess.Popen[bytes]': + if self._popen is None: + raise QEMUMachineError('Subprocess pipe not present') + return self._popen + + def exitcode(self) -> Optional[int]: """Returns the exit code if possible, or None.""" if self._popen is None: return None return self._popen.poll() - def get_pid(self): + def get_pid(self) -> Optional[int]: """Returns the PID of the running process, or None.""" if not self.is_running(): return None - return self._popen.pid + return self._subp.pid - def _load_io_log(self): + def _load_io_log(self) -> None: if self._qemu_log_path is not None: with open(self._qemu_log_path, "r") as iolog: self._iolog = iolog.read() - def _base_args(self): + @property + def _base_args(self) -> List[str]: args = ['-display', 'none', '-vga', 'none'] + if self._qmp_set: if isinstance(self._monitor_address, tuple): - moncdev = "socket,id=mon,host=%s,port=%s" % ( - self._monitor_address[0], - self._monitor_address[1]) + moncdev = "socket,id=mon,host={},port={}".format( + *self._monitor_address + ) else: - moncdev = 'socket,id=mon,path=%s' % self._vm_monitor + moncdev = f"socket,id=mon,path={self._monitor_address}" args.extend(['-chardev', moncdev, '-mon', 'chardev=mon,mode=control']) + if self._machine is not None: args.extend(['-machine', self._machine]) - for i in range(self._console_index): + for _ in range(self._console_index): args.extend(['-serial', 'null']) if self._console_set: - self._console_address = os.path.join(self._sock_dir, - self._name + "-console.sock") - self._remove_files.append(self._console_address) chardev = ('socket,id=console,path=%s,server,nowait' % self._console_address) args.extend(['-chardev', chardev]) @@ -258,26 +302,43 @@ def _base_args(self): args.extend(['-device', device]) return args - def _pre_launch(self): - self._temp_dir = tempfile.mkdtemp(dir=self._test_dir) + def _pre_launch(self) -> None: + self._temp_dir = tempfile.mkdtemp(prefix="qemu-machine-", + dir=self._test_dir) self._qemu_log_path = os.path.join(self._temp_dir, self._name + ".log") self._qemu_log_file = open(self._qemu_log_path, 'wb') + if self._console_set: + self._remove_files.append(self._console_address) + if self._qmp_set: - if self._monitor_address is not None: - self._vm_monitor = self._monitor_address - else: - self._vm_monitor = os.path.join(self._sock_dir, - self._name + "-monitor.sock") - self._remove_files.append(self._vm_monitor) - self._qmp = qmp.QEMUMonitorProtocol(self._vm_monitor, server=True, - nickname=self._name) - - def _post_launch(self): - if self._qmp: + if self._remove_monitor_sockfile: + assert isinstance(self._monitor_address, str) + self._remove_files.append(self._monitor_address) + self._qmp_connection = qmp.QEMUMonitorProtocol( + self._monitor_address, + server=True, + nickname=self._name + ) + + def _post_launch(self) -> None: + if self._qmp_connection: self._qmp.accept() - def _post_shutdown(self): + def _post_shutdown(self) -> None: + """ + Called to cleanup the VM instance after the process has exited. + May also be called after a failed launch. + """ + # Comprehensive reset for the failed launch case: + self._early_cleanup() + + if self._qmp_connection: + self._qmp.close() + self._qmp_connection = None + + self._load_io_log() + if self._qemu_log_file is not None: self._qemu_log_file.close() self._qemu_log_file = None @@ -291,7 +352,20 @@ def _post_shutdown(self): while len(self._remove_files) > 0: self._remove_if_exists(self._remove_files.pop()) - def launch(self): + exitcode = self.exitcode() + if (exitcode is not None and exitcode < 0 + and not (self._user_killed and exitcode == -signal.SIGKILL)): + msg = 'qemu received signal %i; command: "%s"' + if self._qemu_full_args: + command = ' '.join(self._qemu_full_args) + else: + command = '' + LOG.warning(msg, -int(exitcode), command) + + self._user_killed = False + self._launched = False + + def launch(self) -> None: """ Launch the VM and make sure we cleanup and expose the command line/output in case of exception @@ -301,12 +375,12 @@ def launch(self): raise QEMUMachineError('VM already launched') self._iolog = None - self._qemu_full_args = None + self._qemu_full_args = () try: self._launch() self._launched = True except: - self.shutdown() + self._post_shutdown() LOG.debug('Error launching VM') if self._qemu_full_args: @@ -315,14 +389,18 @@ def launch(self): LOG.debug('Output: %r', self._iolog) raise - def _launch(self): + def _launch(self) -> None: """ Launch the VM and establish a QMP connection """ devnull = open(os.path.devnull, 'rb') self._pre_launch() - self._qemu_full_args = (self._wrapper + [self._binary] + - self._base_args() + self._args) + self._qemu_full_args = tuple( + chain(self._wrapper, + [self._binary], + self._base_args, + self._args) + ) LOG.debug('VM launch command: %r', ' '.join(self._qemu_full_args)) self._popen = subprocess.Popen(self._qemu_full_args, stdin=devnull, @@ -332,19 +410,12 @@ def _launch(self): close_fds=False) self._post_launch() - def wait(self): - """ - Wait for the VM to power off + def _early_cleanup(self) -> None: """ - self._popen.wait() - if self._qmp: - self._qmp.close() - self._load_io_log() - self._post_shutdown() + Perform any cleanup that needs to happen before the VM exits. - def shutdown(self, has_quit=False): - """ - Terminate the VM and clean up + May be invoked by both soft and hard shutdown in failover scenarios. + Called additionally by _post_shutdown for comprehensive cleanup. """ # If we keep the console socket open, we may deadlock waiting # for QEMU to exit, while QEMU is waiting for the socket to @@ -353,32 +424,106 @@ def shutdown(self, has_quit=False): self._console_socket.close() self._console_socket = None - if self.is_running(): - if self._qmp: - try: - if not has_quit: - self._qmp.cmd('quit') - self._qmp.close() - self._popen.wait(timeout=3) - except: - self._popen.kill() - self._popen.wait() + def _hard_shutdown(self) -> None: + """ + Perform early cleanup, kill the VM, and wait for it to terminate. - self._load_io_log() - self._post_shutdown() + :raise subprocess.Timeout: When timeout is exceeds 60 seconds + waiting for the QEMU process to terminate. + """ + self._early_cleanup() + self._subp.kill() + self._subp.wait(timeout=60) - exitcode = self.exitcode() - if exitcode is not None and exitcode < 0: - msg = 'qemu received signal %i: %s' - if self._qemu_full_args: - command = ' '.join(self._qemu_full_args) + def _soft_shutdown(self, timeout: Optional[int], + has_quit: bool = False) -> None: + """ + Perform early cleanup, attempt to gracefully shut down the VM, and wait + for it to terminate. + + :param timeout: Timeout in seconds for graceful shutdown. + A value of None is an infinite wait. + :param has_quit: When True, don't attempt to issue 'quit' QMP command + + :raise ConnectionReset: On QMP communication errors + :raise subprocess.TimeoutExpired: When timeout is exceeded waiting for + the QEMU process to terminate. + """ + self._early_cleanup() + + if self._qmp_connection: + if not has_quit: + # Might raise ConnectionReset + self._qmp.cmd('quit') + + # May raise subprocess.TimeoutExpired + self._subp.wait(timeout=timeout) + + def _do_shutdown(self, timeout: Optional[int], + has_quit: bool = False) -> None: + """ + Attempt to shutdown the VM gracefully; fallback to a hard shutdown. + + :param timeout: Timeout in seconds for graceful shutdown. + A value of None is an infinite wait. + :param has_quit: When True, don't attempt to issue 'quit' QMP command + + :raise AbnormalShutdown: When the VM could not be shut down gracefully. + The inner exception will likely be ConnectionReset or + subprocess.TimeoutExpired. In rare cases, non-graceful termination + may result in its own exceptions, likely subprocess.TimeoutExpired. + """ + try: + self._soft_shutdown(timeout, has_quit) + except Exception as exc: + self._hard_shutdown() + raise AbnormalShutdown("Could not perform graceful shutdown") \ + from exc + + def shutdown(self, has_quit: bool = False, + hard: bool = False, + timeout: Optional[int] = 30) -> None: + """ + Terminate the VM (gracefully if possible) and perform cleanup. + Cleanup will always be performed. + + If the VM has not yet been launched, or shutdown(), wait(), or kill() + have already been called, this method does nothing. + + :param has_quit: When true, do not attempt to issue 'quit' QMP command. + :param hard: When true, do not attempt graceful shutdown, and + suppress the SIGKILL warning log message. + :param timeout: Optional timeout in seconds for graceful shutdown. + Default 30 seconds, A `None` value is an infinite wait. + """ + if not self._launched: + return + + try: + if hard: + self._user_killed = True + self._hard_shutdown() else: - command = '' - LOG.warning(msg, -exitcode, command) + self._do_shutdown(timeout, has_quit) + finally: + self._post_shutdown() - self._launched = False + def kill(self) -> None: + """ + Terminate the VM forcefully, wait for it to exit, and perform cleanup. + """ + self.shutdown(hard=True) - def set_qmp_monitor(self, enabled=True): + def wait(self, timeout: Optional[int] = 30) -> None: + """ + Wait for the VM to power off and perform post-shutdown cleanup. + + :param timeout: Optional timeout in seconds. Default 30 seconds. + A value of `None` is an infinite wait. + """ + self.shutdown(has_quit=True, timeout=timeout) + + def set_qmp_monitor(self, enabled: bool = True) -> None: """ Set the QMP monitor. @@ -387,39 +532,45 @@ def set_qmp_monitor(self, enabled=True): line. Default is True. @note: call this function before launch(). """ - if enabled: - self._qmp_set = True - else: - self._qmp_set = False - self._qmp = None + self._qmp_set = enabled - def qmp(self, cmd, conv_keys=True, **args): - """ - Invoke a QMP command and return the response dict - """ + @property + def _qmp(self) -> qmp.QEMUMonitorProtocol: + if self._qmp_connection is None: + raise QEMUMachineError("Attempt to access QMP with no connection") + return self._qmp_connection + + @classmethod + def _qmp_args(cls, _conv_keys: bool = True, **args: Any) -> Dict[str, Any]: qmp_args = dict() for key, value in args.items(): - if conv_keys: + if _conv_keys: qmp_args[key.replace('_', '-')] = value else: qmp_args[key] = value + return qmp_args + def qmp(self, cmd: str, + conv_keys: bool = True, + **args: Any) -> QMPMessage: + """ + Invoke a QMP command and return the response dict + """ + qmp_args = self._qmp_args(conv_keys, **args) return self._qmp.cmd(cmd, args=qmp_args) - def command(self, cmd, conv_keys=True, **args): + def command(self, cmd: str, + conv_keys: bool = True, + **args: Any) -> QMPReturnValue: """ Invoke a QMP command. On success return the response dict. On failure raise an exception. """ - reply = self.qmp(cmd, conv_keys, **args) - if reply is None: - raise qmp.QMPError("Monitor is closed") - if "error" in reply: - raise MonitorResponseError(reply) - return reply["return"] + qmp_args = self._qmp_args(conv_keys, **args) + return self._qmp.command(cmd, **qmp_args) - def get_qmp_event(self, wait=False): + def get_qmp_event(self, wait: bool = False) -> Optional[QMPMessage]: """ Poll for one queued QMP events and return it """ @@ -427,7 +578,7 @@ def get_qmp_event(self, wait=False): return self._events.pop(0) return self._qmp.pull_event(wait=wait) - def get_qmp_events(self, wait=False): + def get_qmp_events(self, wait: bool = False) -> List[QMPMessage]: """ Poll for queued QMP events and return a list of dicts """ @@ -438,7 +589,7 @@ def get_qmp_events(self, wait=False): return events @staticmethod - def event_match(event, match=None): + def event_match(event: Any, match: Optional[Any]) -> bool: """ Check if an event matches optional match criteria. @@ -468,9 +619,11 @@ def event_match(event, match=None): return True except TypeError: # either match or event wasn't iterable (not a dict) - return match == event + return bool(match == event) - def event_wait(self, name, timeout=60.0, match=None): + def event_wait(self, name: str, + timeout: float = 60.0, + match: Optional[QMPMessage] = None) -> Optional[QMPMessage]: """ event_wait waits for and returns a named event from QMP with a timeout. @@ -480,21 +633,33 @@ def event_wait(self, name, timeout=60.0, match=None): """ return self.events_wait([(name, match)], timeout) - def events_wait(self, events, timeout=60.0): + def events_wait(self, + events: Sequence[Tuple[str, Any]], + timeout: float = 60.0) -> Optional[QMPMessage]: """ - events_wait waits for and returns a named event from QMP with a timeout. + events_wait waits for and returns a single named event from QMP. + In the case of multiple qualifying events, this function returns the + first one. - events: a sequence of (name, match_criteria) tuples. - The match criteria are optional and may be None. - See event_match for details. - timeout: QEMUMonitorProtocol.pull_event timeout parameter. + :param events: A sequence of (name, match_criteria) tuples. + The match criteria are optional and may be None. + See event_match for details. + :param timeout: Optional timeout, in seconds. + See QEMUMonitorProtocol.pull_event. + + :raise QMPTimeoutError: If timeout was non-zero and no matching events + were found. + :return: A QMP event matching the filter criteria. + If timeout was 0 and no event matched, None. """ - def _match(event): + def _match(event: QMPMessage) -> bool: for name, match in events: if event['event'] == name and self.event_match(event, match): return True return False + event: Optional[QMPMessage] + # Search cached events for event in self._events: if _match(event): @@ -504,26 +669,30 @@ def _match(event): # Poll for new events while True: event = self._qmp.pull_event(wait=timeout) + if event is None: + # NB: None is only returned when timeout is false-ish. + # Timeouts raise QMPTimeoutError instead! + break if _match(event): return event self._events.append(event) return None - def get_log(self): + def get_log(self) -> Optional[str]: """ After self.shutdown or failed qemu execution, this returns the output of the qemu process. """ return self._iolog - def add_args(self, *args): + def add_args(self, *args: str) -> None: """ Adds to the list of extra arguments to be given to the QEMU binary """ self._args.extend(args) - def set_machine(self, machine_type): + def set_machine(self, machine_type: str) -> None: """ Sets the machine type @@ -532,7 +701,9 @@ def set_machine(self, machine_type): """ self._machine = machine_type - def set_console(self, device_type=None, console_index=0): + def set_console(self, + device_type: Optional[str] = None, + console_index: int = 0) -> None: """ Sets the device type for a console device @@ -563,12 +734,13 @@ def set_console(self, device_type=None, console_index=0): self._console_index = console_index @property - def console_socket(self): + def console_socket(self) -> socket.socket: """ Returns a socket connected to the console """ if self._console_socket is None: - self._console_socket = socket.socket(socket.AF_UNIX, - socket.SOCK_STREAM) - self._console_socket.connect(self._console_address) + self._console_socket = console_socket.ConsoleSocket( + self._console_address, + file=self._console_log_path, + drain=self._drain_console) return self._console_socket diff --git a/python/qemu/pylintrc b/python/qemu/pylintrc new file mode 100644 index 0000000000000000000000000000000000000000..3f69205000d46b5630678315ffd9a80d368f563a --- /dev/null +++ b/python/qemu/pylintrc @@ -0,0 +1,58 @@ +[MASTER] + +[MESSAGES CONTROL] + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once). You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use "--disable=all --enable=classes +# --disable=W". +disable=too-many-arguments, + too-many-instance-attributes, + too-many-public-methods, + +[REPORTS] + +[REFACTORING] + +[MISCELLANEOUS] + +[LOGGING] + +[BASIC] + +# Good variable names which should always be accepted, separated by a comma. +good-names=i, + j, + k, + ex, + Run, + _, + fd, + c, +[VARIABLES] + +[STRING] + +[SPELLING] + +[FORMAT] + +[SIMILARITIES] + +# Ignore imports when computing similarities. +ignore-imports=yes + +[TYPECHECK] + +[CLASSES] + +[IMPORTS] + +[DESIGN] + +[EXCEPTIONS] diff --git a/python/qemu/qmp.py b/python/qemu/qmp.py index d6c9b2f4b12bfd08ff14e65d52671ddc849b9fb7..2cd4d43036c5e582b03057d029d801a4f2665b1f 100644 --- a/python/qemu/qmp.py +++ b/python/qemu/qmp.py @@ -7,10 +7,36 @@ # This work is licensed under the terms of the GNU GPL, version 2. See # the COPYING file in the top-level directory. -import json import errno -import socket +import json import logging +import socket +from types import TracebackType +from typing import ( + Any, + Dict, + List, + Optional, + TextIO, + Tuple, + Type, + Union, + cast, +) + + +# QMPMessage is a QMP Message of any kind. +# e.g. {'yee': 'haw'} +# +# QMPReturnValue is the inner value of return values only. +# {'return': {}} is the QMPMessage, +# {} is the QMPReturnValue. +QMPMessage = Dict[str, Any] +QMPReturnValue = Dict[str, Any] + +InternetAddrT = Tuple[str, str] +UnixAddrT = str +SocketAddrT = Union[InternetAddrT, UnixAddrT] class QMPError(Exception): @@ -37,6 +63,25 @@ class QMPTimeoutError(QMPError): """ +class QMPProtocolError(QMPError): + """ + QMP protocol error; unexpected response + """ + + +class QMPResponseError(QMPError): + """ + Represents erroneous QMP monitor reply + """ + def __init__(self, reply: QMPMessage): + try: + desc = reply['error']['desc'] + except KeyError: + desc = reply + super().__init__(desc) + self.reply = reply + + class QEMUMonitorProtocol: """ Provide an API to connect to QEMU via QEMU Monitor Protocol (QMP) and then @@ -46,7 +91,9 @@ class QEMUMonitorProtocol: #: Logger object for debugging messages logger = logging.getLogger('QMP') - def __init__(self, address, server=False, nickname=None): + def __init__(self, address: SocketAddrT, + server: bool = False, + nickname: Optional[str] = None): """ Create a QEMUMonitorProtocol class. @@ -58,10 +105,10 @@ def __init__(self, address, server=False, nickname=None): @note No connection is established, this is done by the connect() or accept() methods """ - self.__events = [] + self.__events: List[QMPMessage] = [] self.__address = address self.__sock = self.__get_sock() - self.__sockfile = None + self.__sockfile: Optional[TextIO] = None self._nickname = nickname if self._nickname: self.logger = logging.getLogger('QMP').getChild(self._nickname) @@ -70,14 +117,14 @@ def __init__(self, address, server=False, nickname=None): self.__sock.bind(self.__address) self.__sock.listen(1) - def __get_sock(self): + def __get_sock(self) -> socket.socket: if isinstance(self.__address, tuple): family = socket.AF_INET else: family = socket.AF_UNIX return socket.socket(family, socket.SOCK_STREAM) - def __negotiate_capabilities(self): + def __negotiate_capabilities(self) -> QMPMessage: greeting = self.__json_read() if greeting is None or "QMP" not in greeting: raise QMPConnectError @@ -87,12 +134,16 @@ def __negotiate_capabilities(self): return greeting raise QMPCapabilitiesError - def __json_read(self, only_event=False): + def __json_read(self, only_event: bool = False) -> Optional[QMPMessage]: + assert self.__sockfile is not None while True: data = self.__sockfile.readline() if not data: return None - resp = json.loads(data) + # By definition, any JSON received from QMP is a QMPMessage, + # and we are asserting only at static analysis time that it + # has a particular shape. + resp: QMPMessage = json.loads(data) if 'event' in resp: self.logger.debug("<<< %s", resp) self.__events.append(resp) @@ -100,7 +151,7 @@ def __json_read(self, only_event=False): continue return resp - def __get_events(self, wait=False): + def __get_events(self, wait: Union[bool, float] = False) -> None: """ Check for new events in the stream and cache them in __events. @@ -113,15 +164,19 @@ def __get_events(self, wait=False): retrieved or if some other error occurred. """ + # Current timeout and blocking status + current_timeout = self.__sock.gettimeout() + # Check for new events regardless and pull them into the cache: - self.__sock.setblocking(0) + self.__sock.settimeout(0) # i.e. setblocking(False) try: self.__json_read() except OSError as err: - if err.errno == errno.EAGAIN: - # No data available - pass - self.__sock.setblocking(1) + # EAGAIN: No data available; not critical + if err.errno != errno.EAGAIN: + raise + finally: + self.__sock.settimeout(current_timeout) # Wait for new events, if needed. # if wait is 0.0, this means "no wait" and is also implicitly false. @@ -130,24 +185,31 @@ def __get_events(self, wait=False): self.__sock.settimeout(wait) try: ret = self.__json_read(only_event=True) - except socket.timeout: - raise QMPTimeoutError("Timeout waiting for event") - except: - raise QMPConnectError("Error while reading from socket") + except socket.timeout as err: + raise QMPTimeoutError("Timeout waiting for event") from err + except Exception as err: + msg = "Error while reading from socket" + raise QMPConnectError(msg) from err + finally: + self.__sock.settimeout(current_timeout) + if ret is None: raise QMPConnectError("Error while reading from socket") - self.__sock.settimeout(None) - def __enter__(self): + def __enter__(self) -> 'QEMUMonitorProtocol': # Implement context manager enter function. return self - def __exit__(self, exc_type, exc_value, exc_traceback): + def __exit__(self, + # pylint: disable=duplicate-code + # see https://github.com/PyCQA/pylint/issues/3619 + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType]) -> None: # Implement context manager exit function. self.close() - return False - def connect(self, negotiate=True): + def connect(self, negotiate: bool = True) -> Optional[QMPMessage]: """ Connect to the QMP Monitor and perform capabilities negotiation. @@ -157,19 +219,19 @@ def connect(self, negotiate=True): @raise QMPCapabilitiesError if fails to negotiate capabilities """ self.__sock.connect(self.__address) - self.__sockfile = self.__sock.makefile() + self.__sockfile = self.__sock.makefile(mode='r') if negotiate: return self.__negotiate_capabilities() return None - def accept(self, timeout=15.0): + def accept(self, timeout: Optional[float] = 15.0) -> QMPMessage: """ Await connection from QMP Monitor and perform capabilities negotiation. @param timeout: timeout in seconds (nonnegative float number, or None). The value passed will set the behavior of the - underneath QMP socket as described in [1]. Default value - is set to 15.0. + underneath QMP socket as described in [1]. + Default value is set to 15.0. @return QMP greeting dict @raise OSError on socket connection errors @raise QMPConnectError if the greeting is not received @@ -180,29 +242,27 @@ def accept(self, timeout=15.0): """ self.__sock.settimeout(timeout) self.__sock, _ = self.__sock.accept() - self.__sockfile = self.__sock.makefile() + self.__sockfile = self.__sock.makefile(mode='r') return self.__negotiate_capabilities() - def cmd_obj(self, qmp_cmd): + def cmd_obj(self, qmp_cmd: QMPMessage) -> QMPMessage: """ Send a QMP command to the QMP Monitor. @param qmp_cmd: QMP command to be sent as a Python dict - @return QMP response as a Python dict or None if the connection has - been closed + @return QMP response as a Python dict """ self.logger.debug(">>> %s", qmp_cmd) - try: - self.__sock.sendall(json.dumps(qmp_cmd).encode('utf-8')) - except OSError as err: - if err.errno == errno.EPIPE: - return None - raise err + self.__sock.sendall(json.dumps(qmp_cmd).encode('utf-8')) resp = self.__json_read() + if resp is None: + raise QMPConnectError("Unexpected empty reply from server") self.logger.debug("<<< %s", resp) return resp - def cmd(self, name, args=None, cmd_id=None): + def cmd(self, name: str, + args: Optional[Dict[str, Any]] = None, + cmd_id: Optional[Any] = None) -> QMPMessage: """ Build a QMP command and send it to the QMP Monitor. @@ -210,23 +270,28 @@ def cmd(self, name, args=None, cmd_id=None): @param args: command arguments (dict) @param cmd_id: command id (dict, list, string or int) """ - qmp_cmd = {'execute': name} + qmp_cmd: QMPMessage = {'execute': name} if args: qmp_cmd['arguments'] = args if cmd_id: qmp_cmd['id'] = cmd_id return self.cmd_obj(qmp_cmd) - def command(self, cmd, **kwds): + def command(self, cmd: str, **kwds: Any) -> QMPReturnValue: """ Build and send a QMP command to the monitor, report errors if any """ ret = self.cmd(cmd, kwds) - if "error" in ret: - raise Exception(ret['error']['desc']) - return ret['return'] - - def pull_event(self, wait=False): + if 'error' in ret: + raise QMPResponseError(ret) + if 'return' not in ret: + raise QMPProtocolError( + "'return' key not found in QMP response '{}'".format(str(ret)) + ) + return cast(QMPReturnValue, ret['return']) + + def pull_event(self, + wait: Union[bool, float] = False) -> Optional[QMPMessage]: """ Pulls a single event. @@ -246,7 +311,7 @@ def pull_event(self, wait=False): return self.__events.pop(0) return None - def get_events(self, wait=False): + def get_events(self, wait: bool = False) -> List[QMPMessage]: """ Get a list of available QMP events. @@ -263,13 +328,13 @@ def get_events(self, wait=False): self.__get_events(wait) return self.__events - def clear_events(self): + def clear_events(self) -> None: """ Clear current list of pending events. """ self.__events = [] - def close(self): + def close(self) -> None: """ Close the socket and socket file. """ @@ -278,16 +343,22 @@ def close(self): if self.__sockfile: self.__sockfile.close() - def settimeout(self, timeout): + def settimeout(self, timeout: Optional[float]) -> None: """ Set the socket timeout. - @param timeout (float): timeout in seconds, or None. + @param timeout (float): timeout in seconds (non-zero), or None. @note This is a wrap around socket.settimeout + + @raise ValueError: if timeout was set to 0. """ + if timeout == 0: + msg = "timeout cannot be 0; this engages non-blocking mode." + msg += " Use 'None' instead to disable timeouts." + raise ValueError(msg) self.__sock.settimeout(timeout) - def get_sock_fd(self): + def get_sock_fd(self) -> int: """ Get the socket file descriptor. @@ -295,7 +366,7 @@ def get_sock_fd(self): """ return self.__sock.fileno() - def is_scm_available(self): + def is_scm_available(self) -> bool: """ Check if the socket allows for SCM_RIGHTS. diff --git a/python/qemu/qtest.py b/python/qemu/qtest.py index d24ad04256b7dd5889fbe7da1814ec1cfe15fa6a..39a0cf62fe99d7c445ab9d6afa7ac85a65bddd42 100644 --- a/python/qemu/qtest.py +++ b/python/qemu/qtest.py @@ -1,5 +1,11 @@ -# QEMU qtest library -# +""" +QEMU qtest library + +qtest offers the QEMUQtestProtocol and QEMUQTestMachine classes, which +offer a connection to QEMU's qtest protocol socket, and a qtest-enabled +subclass of QEMUMachine, respectively. +""" + # Copyright (C) 2015 Red Hat Inc. # # Authors: @@ -11,109 +17,143 @@ # Based on qmp.py. # -import socket import os +import socket +from typing import ( + List, + Optional, + Sequence, + TextIO, +) from .machine import QEMUMachine +from .qmp import SocketAddrT -class QEMUQtestProtocol(object): - def __init__(self, address, server=False): - """ - Create a QEMUQtestProtocol object. +class QEMUQtestProtocol: + """ + QEMUQtestProtocol implements a connection to a qtest socket. - @param address: QEMU address, can be either a unix socket path (string) - or a tuple in the form ( address, port ) for a TCP - connection - @param server: server mode, listens on the socket (bool) - @raise socket.error on socket connection errors - @note No connection is established, this is done by the connect() or - accept() methods - """ + :param address: QEMU address, can be either a unix socket path (string) + or a tuple in the form ( address, port ) for a TCP + connection + :param server: server mode, listens on the socket (bool) + :raise socket.error: on socket connection errors + + .. note:: + No conection is estabalished by __init__(), this is done + by the connect() or accept() methods. + """ + def __init__(self, address: SocketAddrT, + server: bool = False): self._address = address self._sock = self._get_sock() - self._sockfile = None + self._sockfile: Optional[TextIO] = None if server: self._sock.bind(self._address) self._sock.listen(1) - def _get_sock(self): + def _get_sock(self) -> socket.socket: if isinstance(self._address, tuple): family = socket.AF_INET else: family = socket.AF_UNIX return socket.socket(family, socket.SOCK_STREAM) - def connect(self): + def connect(self) -> None: """ Connect to the qtest socket. @raise socket.error on socket connection errors """ self._sock.connect(self._address) - self._sockfile = self._sock.makefile() + self._sockfile = self._sock.makefile(mode='r') - def accept(self): + def accept(self) -> None: """ Await connection from QEMU. @raise socket.error on socket connection errors """ self._sock, _ = self._sock.accept() - self._sockfile = self._sock.makefile() + self._sockfile = self._sock.makefile(mode='r') - def cmd(self, qtest_cmd): + def cmd(self, qtest_cmd: str) -> str: """ Send a qtest command on the wire. @param qtest_cmd: qtest command text to be sent """ + assert self._sockfile is not None self._sock.sendall((qtest_cmd + "\n").encode('utf-8')) resp = self._sockfile.readline() return resp - def close(self): + def close(self) -> None: + """ + Close this socket. + """ self._sock.close() - self._sockfile.close() + if self._sockfile: + self._sockfile.close() + self._sockfile = None - def settimeout(self, timeout): + def settimeout(self, timeout: Optional[float]) -> None: + """Set a timeout, in seconds.""" self._sock.settimeout(timeout) class QEMUQtestMachine(QEMUMachine): - '''A QEMU VM''' - - def __init__(self, binary, args=None, name=None, test_dir="/var/tmp", - socket_scm_helper=None, sock_dir=None): + """ + A QEMU VM, with a qtest socket available. + """ + + def __init__(self, + binary: str, + args: Sequence[str] = (), + name: Optional[str] = None, + test_dir: str = "/var/tmp", + socket_scm_helper: Optional[str] = None, + sock_dir: Optional[str] = None): if name is None: name = "qemu-%d" % os.getpid() if sock_dir is None: sock_dir = test_dir - super(QEMUQtestMachine, - self).__init__(binary, args, name=name, test_dir=test_dir, - socket_scm_helper=socket_scm_helper, - sock_dir=sock_dir) - self._qtest = None + super().__init__(binary, args, name=name, test_dir=test_dir, + socket_scm_helper=socket_scm_helper, + sock_dir=sock_dir) + self._qtest: Optional[QEMUQtestProtocol] = None self._qtest_path = os.path.join(sock_dir, name + "-qtest.sock") - def _base_args(self): - args = super(QEMUQtestMachine, self)._base_args() - args.extend(['-qtest', 'unix:path=' + self._qtest_path, - '-accel', 'qtest']) + @property + def _base_args(self) -> List[str]: + args = super()._base_args + args.extend([ + '-qtest', f"unix:path={self._qtest_path}", + '-accel', 'qtest' + ]) return args - def _pre_launch(self): - super(QEMUQtestMachine, self)._pre_launch() + def _pre_launch(self) -> None: + super()._pre_launch() self._qtest = QEMUQtestProtocol(self._qtest_path, server=True) - def _post_launch(self): - super(QEMUQtestMachine, self)._post_launch() + def _post_launch(self) -> None: + assert self._qtest is not None + super()._post_launch() self._qtest.accept() - def _post_shutdown(self): - super(QEMUQtestMachine, self)._post_shutdown() + def _post_shutdown(self) -> None: + super()._post_shutdown() self._remove_if_exists(self._qtest_path) - def qtest(self, cmd): - '''Send a qtest command to guest''' + def qtest(self, cmd: str) -> str: + """ + Send a qtest command to the guest. + + :param cmd: qtest command to send + :return: qtest server response + """ + if self._qtest is None: + raise RuntimeError("qtest socket not available") return self._qtest.cmd(cmd) diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs deleted file mode 100644 index 4673ab7490df4ab4dd79bde5c24ffe912d591760..0000000000000000000000000000000000000000 --- a/qapi/Makefile.objs +++ /dev/null @@ -1,38 +0,0 @@ -util-obj-y = qapi-visit-core.o qapi-dealloc-visitor.o qobject-input-visitor.o -util-obj-y += qobject-output-visitor.o qmp-registry.o qmp-dispatch.o -util-obj-y += string-input-visitor.o string-output-visitor.o -util-obj-y += opts-visitor.o qapi-clone-visitor.o -util-obj-y += qmp-event.o -util-obj-y += qapi-util.o - -QAPI_COMMON_MODULES = audio authz block-core block char common control crypto -QAPI_COMMON_MODULES += dump error introspect job machine migration misc -QAPI_COMMON_MODULES += net pragma qdev qom rdma rocker run-state sockets tpm -QAPI_COMMON_MODULES += trace transaction ui -QAPI_TARGET_MODULES = machine-target misc-target -QAPI_MODULES = $(QAPI_COMMON_MODULES) $(QAPI_TARGET_MODULES) - -util-obj-y += qapi-builtin-types.o -util-obj-y += $(QAPI_COMMON_MODULES:%=qapi-types-%.o) -util-obj-y += qapi-builtin-visit.o -util-obj-y += $(QAPI_COMMON_MODULES:%=qapi-visit-%.o) -util-obj-y += qapi-emit-events.o -util-obj-y += $(QAPI_COMMON_MODULES:%=qapi-events-%.o) - -common-obj-y = $(QAPI_COMMON_MODULES:%=qapi-commands-%.o) - -obj-y = qapi-introspect.o -obj-y += $(QAPI_TARGET_MODULES:%=qapi-types-%.o) -obj-y += qapi-types.o -obj-y += $(QAPI_TARGET_MODULES:%=qapi-visit-%.o) -obj-y += qapi-visit.o -obj-y += $(QAPI_TARGET_MODULES:%=qapi-events-%.o) -obj-y += qapi-events.o -obj-y += $(QAPI_TARGET_MODULES:%=qapi-commands-%.o) -obj-y += qapi-commands.o -obj-y += qapi-init-commands.o - -QAPI_MODULES_STORAGE_DAEMON = block-core char common control crypto -QAPI_MODULES_STORAGE_DAEMON += introspect job qom sockets pragma transaction - -storage-daemon-obj-y += $(QAPI_MODULES_STORAGE_DAEMON:%=qapi-commands-%.o) diff --git a/qapi/acpi.json b/qapi/acpi.json new file mode 100644 index 0000000000000000000000000000000000000000..51f0d55db735ba5106a9c46b649c574aae28cd25 --- /dev/null +++ b/qapi/acpi.json @@ -0,0 +1,141 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. +# SPDX-License-Identifier: GPL-2.0-or-later + +## +# = ACPI +## + +## +# @AcpiTableOptions: +# +# Specify an ACPI table on the command line to load. +# +# At most one of @file and @data can be specified. The list of files specified +# by any one of them is loaded and concatenated in order. If both are omitted, +# @data is implied. +# +# Other fields / optargs can be used to override fields of the generic ACPI +# table header; refer to the ACPI specification 5.0, section 5.2.6 System +# Description Table Header. If a header field is not overridden, then the +# corresponding value from the concatenated blob is used (in case of @file), or +# it is filled in with a hard-coded value (in case of @data). +# +# String fields are copied into the matching ACPI member from lowest address +# upwards, and silently truncated / NUL-padded to length. +# +# @sig: table signature / identifier (4 bytes) +# +# @rev: table revision number (dependent on signature, 1 byte) +# +# @oem_id: OEM identifier (6 bytes) +# +# @oem_table_id: OEM table identifier (8 bytes) +# +# @oem_rev: OEM-supplied revision number (4 bytes) +# +# @asl_compiler_id: identifier of the utility that created the table +# (4 bytes) +# +# @asl_compiler_rev: revision number of the utility that created the +# table (4 bytes) +# +# @file: colon (:) separated list of pathnames to load and +# concatenate as table data. The resultant binary blob is expected to +# have an ACPI table header. At least one file is required. This field +# excludes @data. +# +# @data: colon (:) separated list of pathnames to load and +# concatenate as table data. The resultant binary blob must not have an +# ACPI table header. At least one file is required. This field excludes +# @file. +# +# Since: 1.5 +## +{ 'struct': 'AcpiTableOptions', + 'data': { + '*sig': 'str', + '*rev': 'uint8', + '*oem_id': 'str', + '*oem_table_id': 'str', + '*oem_rev': 'uint32', + '*asl_compiler_id': 'str', + '*asl_compiler_rev': 'uint32', + '*file': 'str', + '*data': 'str' }} + +## +# @ACPISlotType: +# +# @DIMM: memory slot +# @CPU: logical CPU slot (since 2.7) +## +{ 'enum': 'ACPISlotType', 'data': [ 'DIMM', 'CPU' ] } + +## +# @ACPIOSTInfo: +# +# OSPM Status Indication for a device +# For description of possible values of @source and @status fields +# see "_OST (OSPM Status Indication)" chapter of ACPI5.0 spec. +# +# @device: device ID associated with slot +# +# @slot: slot ID, unique per slot of a given @slot-type +# +# @slot-type: type of the slot +# +# @source: an integer containing the source event +# +# @status: an integer containing the status code +# +# Since: 2.1 +## +{ 'struct': 'ACPIOSTInfo', + 'data' : { '*device': 'str', + 'slot': 'str', + 'slot-type': 'ACPISlotType', + 'source': 'int', + 'status': 'int' } } + +## +# @query-acpi-ospm-status: +# +# Return a list of ACPIOSTInfo for devices that support status +# reporting via ACPI _OST method. +# +# Since: 2.1 +# +# Example: +# +# -> { "execute": "query-acpi-ospm-status" } +# <- { "return": [ { "device": "d1", "slot": "0", "slot-type": "DIMM", "source": 1, "status": 0}, +# { "slot": "1", "slot-type": "DIMM", "source": 0, "status": 0}, +# { "slot": "2", "slot-type": "DIMM", "source": 0, "status": 0}, +# { "slot": "3", "slot-type": "DIMM", "source": 0, "status": 0} +# ]} +# +## +{ 'command': 'query-acpi-ospm-status', 'returns': ['ACPIOSTInfo'] } + +## +# @ACPI_DEVICE_OST: +# +# Emitted when guest executes ACPI _OST method. +# +# @info: OSPM Status Indication +# +# Since: 2.1 +# +# Example: +# +# <- { "event": "ACPI_DEVICE_OST", +# "data": { "device": "d1", "slot": "0", +# "slot-type": "DIMM", "source": 1, "status": 0 } } +# +## +{ 'event': 'ACPI_DEVICE_OST', + 'data': { 'info': 'ACPIOSTInfo' } } diff --git a/qapi/audio.json b/qapi/audio.json index f62bd0d7f6eca2b2b0ba31a040013690264a7c48..072ed79def503fcbe09247e6a230be197d31759c 100644 --- a/qapi/audio.json +++ b/qapi/audio.json @@ -5,6 +5,10 @@ # This work is licensed under the terms of the GNU GPL, version 2 or later. # See the COPYING file in the top-level directory. +## +# = Audio +## + ## # @AudiodevPerDirectionOptions: # @@ -159,20 +163,20 @@ # recording. # # @server-name: select from among several possible concurrent server instances -# (default: environment variable $JACK_DEFAULT_SERVER if set, else "default") +# (default: environment variable $JACK_DEFAULT_SERVER if set, else "default") # # @client-name: the client name to use. The server will modify this name to -# create a unique variant, if needed unless @exact-name is true (default: the -# guest's name) +# create a unique variant, if needed unless @exact-name is true (default: the +# guest's name) # # @connect-ports: if set, a regular expression of JACK client port name(s) to -# monitor for and automatically connect to +# monitor for and automatically connect to # # @start-server: start a jack server process if one is not already present -# (default: false) +# (default: false) # # @exact-name: use the exact name requested otherwise JACK automatically -# generates a unique one, if needed (default: false) +# generates a unique one, if needed (default: false) # # Since: 5.1 ## diff --git a/qapi/authz.json b/qapi/authz.json index 1c836a3abdfe58744cb188099fffc2e66c0a289e..42afe752d1c18d8d2f46aefd0e6790e3fec41265 100644 --- a/qapi/authz.json +++ b/qapi/authz.json @@ -1,6 +1,9 @@ # -*- Mode: Python -*- -# -# QAPI authz definitions +# vim: filetype=python + +## +# = User authorization +## ## # @QAuthZListPolicy: diff --git a/qapi/block-core.json b/qapi/block-core.json index 6fbacddab2cc8e059e684a5dab5f91781a4cd88d..04ad80bc1e51bb0913bc5a6153cff2bfdae517f8 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python ## # == Block core (VM unrelated) @@ -26,13 +27,19 @@ # # @vm-clock-nsec: fractional part in nano seconds to be used with vm-clock-sec # +# @icount: Current instruction count. Appears when execution record/replay +# is enabled. Used for "time-traveling" to match the moment +# in the recorded execution with the snapshots. This counter may +# be obtained through @query-replay command (since 5.2) +# # Since: 1.3 # ## { 'struct': 'SnapshotInfo', 'data': { 'id': 'str', 'name': 'str', 'vm-state-size': 'int', 'date-sec': 'int', 'date-nsec': 'int', - 'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } } + 'vm-clock-sec': 'int', 'vm-clock-nsec': 'int', + '*icount': 'int' } } ## # @ImageInfoSpecificQCow2EncryptionBase: @@ -66,6 +73,9 @@ # standalone (read-only) raw image without looking at qcow2 # metadata (since: 4.0) # +# @extended-l2: true if the image has extended L2 entries; only valid for +# compat >= 1.1 (since 5.2) +# # @lazy-refcounts: on or off; only valid for compat >= 1.1 # # @corrupt: true if the image has been marked corrupt; only valid for @@ -87,6 +97,7 @@ 'compat': 'str', '*data-file': 'str', '*data-file-raw': 'bool', + '*extended-l2': 'bool', '*lazy-refcounts': 'bool', '*corrupt': 'bool', 'refcount-bits': 'int', @@ -233,17 +244,25 @@ # # Mapping information from a virtual block range to a host file range # -# @start: the start byte of the mapped virtual range +# @start: virtual (guest) offset of the first byte described by this +# entry # # @length: the number of bytes of the mapped virtual range # -# @data: whether the mapped range has data +# @data: reading the image will actually read data from a file (in +# particular, if @offset is present this means that the sectors +# are not simply preallocated, but contain actual data in raw +# format) # -# @zero: whether the virtual blocks are zeroed +# @zero: whether the virtual blocks read as zeroes # -# @depth: the depth of the mapping +# @depth: number of layers (0 = top image, 1 = top image's backing +# file, ..., n - 1 = bottom image (where n is the number of +# images in the chain)) before reaching one for which the +# range is allocated # -# @offset: the offset in file that the virtual sectors are mapped to +# @offset: if present, the image file stores the data for this range +# in raw format at the given (host) offset # # @filename: filename that is referred to by @offset # @@ -368,7 +387,7 @@ # # Features: # @deprecated: Member @encryption_key_missing is deprecated. It is -# always false. +# always false. # # Since: 0.14.0 # @@ -407,35 +426,6 @@ ## { 'enum': 'BlockDeviceIoStatus', 'data': [ 'ok', 'failed', 'nospace' ] } -## -# @BlockDeviceMapEntry: -# -# Entry in the metadata map of the device (returned by "qemu-img map") -# -# @start: Offset in the image of the first byte described by this entry -# (in bytes) -# -# @length: Length of the range described by this entry (in bytes) -# -# @depth: Number of layers (0 = top image, 1 = top image's backing file, etc.) -# before reaching one for which the range is allocated. The value is -# in the range 0 to the depth of the image chain - 1. -# -# @zero: the sectors in this range read as zeros -# -# @data: reading the image will actually read data from a file (in particular, -# if @offset is present this means that the sectors are not simply -# preallocated, but contain actual data in raw format) -# -# @offset: if present, the image file stores the data for this range in -# raw format at the given offset. -# -# Since: 1.7 -## -{ 'struct': 'BlockDeviceMapEntry', - 'data': { 'start': 'int', 'length': 'int', 'depth': 'int', 'zero': 'bool', - 'data': 'bool', '*offset': 'int' } } - ## # @DirtyBitmapStatus: # @@ -503,7 +493,7 @@ # # Features: # @deprecated: Member @status is deprecated. Use @recording and -# @locked instead. +# @locked instead. # # Since: 1.3 ## @@ -565,13 +555,15 @@ # For the example above, @bins may be something like [3, 1, 5, 2], # and corresponding histogram looks like: # -# | 5| * -# | 4| * -# | 3| * * -# | 2| * * * -# | 1| * * * * -# | +------------------ -# | 10 50 100 +# :: +# +# 5| * +# 4| * +# 3| * * +# 2| * * * +# 1| * * * * +# +------------------ +# 10 50 100 # # Since: 4.0 ## @@ -613,7 +605,7 @@ # # Features: # @deprecated: Member @dirty-bitmaps is deprecated. Use @inserted -# member @dirty-bitmaps instead. +# member @dirty-bitmaps instead. # # Since: 0.14.0 ## @@ -636,18 +628,24 @@ # efficiently so file size may be smaller than virtual disk size. # # The values are upper bounds that are guaranteed to fit the new image file. -# Subsequent modification, such as internal snapshot or bitmap creation, may -# require additional space and is not covered here. +# Subsequent modification, such as internal snapshot or further bitmap +# creation, may require additional space and is not covered here. # -# @required: Size required for a new image file, in bytes. +# @required: Size required for a new image file, in bytes, when copying just +# allocated guest-visible contents. # # @fully-allocated: Image file size, in bytes, once data has been written -# to all sectors. +# to all sectors, when copying just guest-visible contents. +# +# @bitmaps: Additional size required if all the top-level bitmap metadata +# in the source image were to be copied to the destination, +# present only when source and destination both support +# persistent bitmaps. (since 5.1) # # Since: 2.10 ## { 'struct': 'BlockMeasureInfo', - 'data': {'required': 'int', 'fully-allocated': 'int'} } + 'data': {'required': 'int', 'fully-allocated': 'int', '*bitmaps': 'int'} } ## # @query-block: @@ -928,6 +926,27 @@ 'discard-nb-failed': 'uint64', 'discard-bytes-ok': 'uint64' } } +## +# @BlockStatsSpecificNvme: +# +# NVMe driver statistics +# +# @completion-errors: The number of completion errors. +# +# @aligned-accesses: The number of aligned accesses performed by +# the driver. +# +# @unaligned-accesses: The number of unaligned accesses performed by +# the driver. +# +# Since: 5.2 +## +{ 'struct': 'BlockStatsSpecificNvme', + 'data': { + 'completion-errors': 'uint64', + 'aligned-accesses': 'uint64', + 'unaligned-accesses': 'uint64' } } + ## # @BlockStatsSpecific: # @@ -940,7 +959,8 @@ 'discriminator': 'driver', 'data': { 'file': 'BlockStatsSpecificFile', - 'host_device': 'BlockStatsSpecificFile' } } + 'host_device': 'BlockStatsSpecificFile', + 'nvme': 'BlockStatsSpecificNvme' } } ## # @BlockStats: @@ -1291,7 +1311,8 @@ { 'command': 'block_resize', 'data': { '*device': 'str', '*node-name': 'str', - 'size': 'int' } } + 'size': 'int' }, + 'coroutine': true } ## # @NewImageMode: @@ -1558,6 +1579,18 @@ # Live commit of data from overlay image nodes into backing nodes - i.e., # writes data between 'top' and 'base' into 'base'. # +# If top == base, that is an error. +# If top has no overlays on top of it, or if it is in use by a writer, +# the job will not be completed by itself. The user needs to complete +# the job with the block-job-complete command after getting the ready +# event. (Since 2.0) +# +# If the base image is smaller than top, then the base image will be +# resized to be the same size as top. If top is smaller than the base +# image, the base will not be truncated. If you want the base image +# size to match the size of the smaller top, you can safely truncate +# it yourself once the commit operation successfully completes. +# # @job-id: identifier for the newly-created block job. If # omitted, the device name will be used. (Since 2.7) # @@ -1582,14 +1615,15 @@ # accepted # # @backing-file: The backing file string to write into the overlay -# image of 'top'. If 'top' is the active layer, -# specifying a backing file string is an error. This -# filename is not validated. +# image of 'top'. If 'top' does not have an overlay +# image, or if 'top' is in use by a writer, specifying +# a backing file string is an error. # -# If a pathname string is such that it cannot be -# resolved by QEMU, that means that subsequent QMP or -# HMP commands must use node-names for the image in -# question, as filename lookup methods will fail. +# This filename is not validated. If a pathname string +# is such that it cannot be resolved by QEMU, that +# means that subsequent QMP or HMP commands must use +# node-names for the image in question, as filename +# lookup methods will fail. # # If not specified, QEMU will automatically determine # the backing file string to use, or error out if @@ -1598,18 +1632,6 @@ # filename or protocol. # (Since 2.1) # -# If top == base, that is an error. -# If top == active, the job will not be completed by itself, -# user needs to complete the job with the block-job-complete -# command after getting the ready event. (Since 2.0) -# -# If the base image is smaller than top, then the base image -# will be resized to be the same size as top. If top is -# smaller than the base image, the base will not be -# truncated. If you want the base image size to match the -# size of the smaller top, you can safely truncate it -# yourself once the commit operation successfully completes. -# # @speed: the maximum speed, in bytes per second # # @on-error: the action to take on an error. 'ignore' means that the request @@ -1635,7 +1657,7 @@ # # Features: # @deprecated: Members @base and @top are deprecated. Use @base-node -# and @top-node instead. +# and @top-node instead. # # Returns: - Nothing on success # - If @device does not exist, DeviceNotFound @@ -1783,7 +1805,7 @@ # # @block-backend: corresponds to BlockBackend # -# @block-job: corresonds to BlockJob +# @block-job: corresponds to BlockJob # # @block-driver: corresponds to BlockDriverState # @@ -1841,9 +1863,9 @@ # # Since: 4.0 ## - { 'enum': 'BlockPermission', - 'data': [ 'consistent-read', 'write', 'write-unchanged', 'resize', - 'graph-mod' ] } +{ 'enum': 'BlockPermission', + 'data': [ 'consistent-read', 'write', 'write-unchanged', 'resize', + 'graph-mod' ] } ## # @XDbgBlockGraphEdge: # @@ -1937,7 +1959,8 @@ # # @replaces: with sync=full graph node name to be replaced by the new # image when a whole image copy is done. This can be used to repair -# broken Quorum files. (Since 2.1) +# broken Quorum files. By default, @device is replaced, although +# implicitly created filters on it are kept. (Since 2.1) # # @mode: whether and how QEMU should create a new image, default is # 'absolute-paths'. @@ -2054,7 +2077,7 @@ # @target: name of the destination dirty bitmap # # @bitmaps: name(s) of the source dirty bitmap(s) at @node and/or fully -# specifed BlockDirtyBitmap elements. The latter are supported +# specified BlockDirtyBitmap elements. The latter are supported # since 4.1. # # Since: 4.0 @@ -2149,8 +2172,8 @@ # <- { "return": {} } # ## - { 'command': 'block-dirty-bitmap-enable', - 'data': 'BlockDirtyBitmap' } +{ 'command': 'block-dirty-bitmap-enable', + 'data': 'BlockDirtyBitmap' } ## # @block-dirty-bitmap-disable: @@ -2170,8 +2193,8 @@ # <- { "return": {} } # ## - { 'command': 'block-dirty-bitmap-disable', - 'data': 'BlockDirtyBitmap' } +{ 'command': 'block-dirty-bitmap-disable', + 'data': 'BlockDirtyBitmap' } ## # @block-dirty-bitmap-merge: @@ -2202,8 +2225,8 @@ # <- { "return": {} } # ## - { 'command': 'block-dirty-bitmap-merge', - 'data': 'BlockDirtyBitmapMerge' } +{ 'command': 'block-dirty-bitmap-merge', + 'data': 'BlockDirtyBitmapMerge' } ## # @BlockDirtyBitmapSha256: @@ -2214,8 +2237,8 @@ # # Since: 2.10 ## - { 'struct': 'BlockDirtyBitmapSha256', - 'data': {'sha256': 'str'} } +{ 'struct': 'BlockDirtyBitmapSha256', + 'data': {'sha256': 'str'} } ## # @x-debug-block-dirty-bitmap-sha256: @@ -2229,8 +2252,8 @@ # # Since: 2.10 ## - { 'command': 'x-debug-block-dirty-bitmap-sha256', - 'data': 'BlockDirtyBitmap', 'returns': 'BlockDirtyBitmapSha256' } +{ 'command': 'x-debug-block-dirty-bitmap-sha256', + 'data': 'BlockDirtyBitmap', 'returns': 'BlockDirtyBitmapSha256' } ## # @blockdev-mirror: @@ -2248,7 +2271,8 @@ # # @replaces: with sync=full graph node name to be replaced by the new # image when a whole image copy is done. This can be used to repair -# broken Quorum files. +# broken Quorum files. By default, @device is replaced, although +# implicitly created filters on it are kept. # # @speed: the maximum speed, in bytes per second # @@ -2473,13 +2497,20 @@ # of 'device'. # # If a base file is specified then sectors are not copied from that base file and -# its backing chain. When streaming completes the image file will have the base -# file as its backing file. This can be used to stream a subset of the backing -# file chain instead of flattening the entire image. +# its backing chain. This can be used to stream a subset of the backing file +# chain instead of flattening the entire image. +# When streaming completes the image file will have the base file as its backing +# file, unless that node was changed while the job was running. In that case, +# base's parent's backing (or filtered, whichever exists) child (i.e., base at +# the beginning of the job) will be the new backing file. # # On successful completion the image file is updated to drop the backing file # and the BLOCK_JOB_COMPLETED event is emitted. # +# In case @device is a filter node, block-stream modifies the first non-filter +# overlay node below it to point to the new backing node instead of modifying +# @device itself. +# # @job-id: identifier for the newly-created block job. If # omitted, the device name will be used. (Since 2.7) # @@ -2784,7 +2815,6 @@ # # Drivers that are supported in block device operations. # -# @vxhs: Since 2.10 # @throttle: Since 2.11 # @nvme: Since 2.12 # @copy-on-read: Since 3.0 @@ -2802,7 +2832,7 @@ 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'rbd', { 'name': 'replication', 'if': 'defined(CONFIG_REPLICATION)' }, 'sheepdog', - 'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] } + 'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] } ## # @BlockdevOptionsFile: @@ -3854,9 +3884,12 @@ # # @tls-creds: TLS credentials ID # -# @x-dirty-bitmap: A "qemu:dirty-bitmap:NAME" string to query in place of +# @x-dirty-bitmap: A metadata context name such as "qemu:dirty-bitmap:NAME" +# or "qemu:allocation-depth" to query in place of the # traditional "base:allocation" block status (see -# NBD_OPT_LIST_META_CONTEXT in the NBD protocol) (since 3.0) +# NBD_OPT_LIST_META_CONTEXT in the NBD protocol; and +# yes, naming this option x-context would have made +# more sense) (since 3.0) # # @reconnect-delay: On an unexpected disconnect, the nbd client tries to # connect again until succeeding or encountering a serious @@ -3889,22 +3922,6 @@ 'base': 'BlockdevOptionsGenericFormat', 'data': { '*offset': 'int', '*size': 'int' } } -## -# @BlockdevOptionsVxHS: -# -# Driver specific block device options for VxHS -# -# @vdisk-id: UUID of VxHS volume -# @server: vxhs server IP, port -# @tls-creds: TLS credentials ID -# -# Since: 2.10 -## -{ 'struct': 'BlockdevOptionsVxHS', - 'data': { 'vdisk-id': 'str', - 'server': 'InetSocketAddressBase', - '*tls-creds': 'str' } } - ## # @BlockdevOptionsThrottle: # @@ -4004,8 +4021,7 @@ 'vhdx': 'BlockdevOptionsGenericFormat', 'vmdk': 'BlockdevOptionsGenericCOWFormat', 'vpc': 'BlockdevOptionsGenericFormat', - 'vvfat': 'BlockdevOptionsVVFAT', - 'vxhs': 'BlockdevOptionsVxHS' + 'vvfat': 'BlockdevOptionsVVFAT' } } ## @@ -4043,9 +4059,7 @@ ## # @blockdev-add: # -# Creates a new block device. If the @id option is given at the top level, a -# BlockBackend will be created; otherwise, @node-name is mandatory at the top -# level and no BlockBackend will be created. +# Creates a new block device. # # Since: 2.9 # @@ -4179,14 +4193,17 @@ # falloc (if defined CONFIG_POSIX_FALLOCATE), # full (if defined CONFIG_POSIX)) # @nocow: Turn off copy-on-write (valid only on btrfs; default: off) +# @extent-size-hint: Extent size hint to add to the image file; 0 for not +# adding an extent size hint (default: 1 MB, since 5.1) # # Since: 2.12 ## { 'struct': 'BlockdevCreateOptionsFile', - 'data': { 'filename': 'str', - 'size': 'size', - '*preallocation': 'PreallocMode', - '*nocow': 'bool' } } + 'data': { 'filename': 'str', + 'size': 'size', + '*preallocation': 'PreallocMode', + '*nocow': 'bool', + '*extent-size-hint': 'size'} } ## # @BlockdevCreateOptionsGluster: @@ -4312,6 +4329,8 @@ # @data-file-raw: True if the external data file must stay valid as a # standalone (read-only) raw image without looking at qcow2 # metadata (default: false; since: 4.0) +# @extended-l2: True to make the image have extended L2 entries +# (default: false; since 5.2) # @size: Size of the virtual disk in bytes # @version: Compatibility level (default: v3) # @backing-file: File name of the backing file if a backing file @@ -4332,6 +4351,7 @@ 'data': { 'file': 'BlockdevRef', '*data-file': 'BlockdevRef', '*data-file-raw': 'bool', + '*extended-l2': 'bool', 'size': 'size', '*version': 'BlockdevQcow2Version', '*backing-file': 'str', @@ -4668,6 +4688,74 @@ 'data': { 'job-id': 'str', 'options': 'BlockdevCreateOptions' } } +## +# @BlockdevAmendOptionsLUKS: +# +# Driver specific image amend options for LUKS. +# +# Since: 5.1 +## +{ 'struct': 'BlockdevAmendOptionsLUKS', + 'base': 'QCryptoBlockAmendOptionsLUKS', + 'data': { } +} + +## +# @BlockdevAmendOptionsQcow2: +# +# Driver specific image amend options for qcow2. +# For now, only encryption options can be amended +# +# @encrypt Encryption options to be amended +# +# Since: 5.1 +## +{ 'struct': 'BlockdevAmendOptionsQcow2', + 'data': { '*encrypt': 'QCryptoBlockAmendOptions' } } + +## +# @BlockdevAmendOptions: +# +# Options for amending an image format +# +# @driver: Block driver of the node to amend. +# +# Since: 5.1 +## +{ 'union': 'BlockdevAmendOptions', + 'base': { + 'driver': 'BlockdevDriver' }, + 'discriminator': 'driver', + 'data': { + 'luks': 'BlockdevAmendOptionsLUKS', + 'qcow2': 'BlockdevAmendOptionsQcow2' } } + +## +# @x-blockdev-amend: +# +# Starts a job to amend format specific options of an existing open block device +# The job is automatically finalized, but a manual job-dismiss is required. +# +# @job-id: Identifier for the newly created job. +# +# @node-name: Name of the block node to work on +# +# @options: Options (driver specific) +# +# @force: Allow unsafe operations, format specific +# For luks that allows erase of the last active keyslot +# (permanent loss of data), +# and replacement of an active keyslot +# (possible loss of data if IO error happens) +# +# Since: 5.1 +## +{ 'command': 'x-blockdev-amend', + 'data': { 'job-id': 'str', + 'node-name': 'str', + 'options': 'BlockdevAmendOptions', + '*force': 'bool' } } + ## # @BlockErrorAction: # @@ -5117,172 +5205,6 @@ 'iothread': 'StrOrNull', '*force': 'bool' } } -## -# @NbdServerOptions: -# -# @addr: Address on which to listen. -# @tls-creds: ID of the TLS credentials object (since 2.6). -# @tls-authz: ID of the QAuthZ authorization object used to validate -# the client's x509 distinguished name. This object is -# is only resolved at time of use, so can be deleted and -# recreated on the fly while the NBD server is active. -# If missing, it will default to denying access (since 4.0). -# -# Keep this type consistent with the nbd-server-start arguments. The only -# intended difference is using SocketAddress instead of SocketAddressLegacy. -# -# Since: 4.2 -## -{ 'struct': 'NbdServerOptions', - 'data': { 'addr': 'SocketAddress', - '*tls-creds': 'str', - '*tls-authz': 'str'} } - -## -# @nbd-server-start: -# -# Start an NBD server listening on the given host and port. Block -# devices can then be exported using @nbd-server-add. The NBD -# server will present them as named exports; for example, another -# QEMU instance could refer to them as "nbd:HOST:PORT:exportname=NAME". -# -# @addr: Address on which to listen. -# @tls-creds: ID of the TLS credentials object (since 2.6). -# @tls-authz: ID of the QAuthZ authorization object used to validate -# the client's x509 distinguished name. This object is -# is only resolved at time of use, so can be deleted and -# recreated on the fly while the NBD server is active. -# If missing, it will default to denying access (since 4.0). -# -# Returns: error if the server is already running. -# -# Keep this type consistent with the NbdServerOptions type. The only intended -# difference is using SocketAddressLegacy instead of SocketAddress. -# -# Since: 1.3.0 -## -{ 'command': 'nbd-server-start', - 'data': { 'addr': 'SocketAddressLegacy', - '*tls-creds': 'str', - '*tls-authz': 'str'} } - -## -# @BlockExportNbd: -# -# An NBD block export. -# -# @device: The device name or node name of the node to be exported -# -# @name: Export name. If unspecified, the @device parameter is used as the -# export name. (Since 2.12) -# -# @description: Free-form description of the export, up to 4096 bytes. -# (Since 5.0) -# -# @writable: Whether clients should be able to write to the device via the -# NBD connection (default false). -# -# @bitmap: Also export the dirty bitmap reachable from @device, so the -# NBD client can use NBD_OPT_SET_META_CONTEXT with -# "qemu:dirty-bitmap:NAME" to inspect the bitmap. (since 4.0) -# -# Since: 5.0 -## -{ 'struct': 'BlockExportNbd', - 'data': {'device': 'str', '*name': 'str', '*description': 'str', - '*writable': 'bool', '*bitmap': 'str' } } - -## -# @nbd-server-add: -# -# Export a block node to QEMU's embedded NBD server. -# -# Returns: error if the server is not running, or export with the same name -# already exists. -# -# Since: 1.3.0 -## -{ 'command': 'nbd-server-add', - 'data': 'BlockExportNbd', 'boxed': true } - -## -# @NbdServerRemoveMode: -# -# Mode for removing an NBD export. -# -# @safe: Remove export if there are no existing connections, fail otherwise. -# -# @hard: Drop all connections immediately and remove export. -# -# Potential additional modes to be added in the future: -# -# hide: Just hide export from new clients, leave existing connections as is. -# Remove export after all clients are disconnected. -# -# soft: Hide export from new clients, answer with ESHUTDOWN for all further -# requests from existing clients. -# -# Since: 2.12 -## -{'enum': 'NbdServerRemoveMode', 'data': ['safe', 'hard']} - -## -# @nbd-server-remove: -# -# Remove NBD export by name. -# -# @name: Export name. -# -# @mode: Mode of command operation. See @NbdServerRemoveMode description. -# Default is 'safe'. -# -# Returns: error if -# - the server is not running -# - export is not found -# - mode is 'safe' and there are existing connections -# -# Since: 2.12 -## -{ 'command': 'nbd-server-remove', - 'data': {'name': 'str', '*mode': 'NbdServerRemoveMode'} } - -## -# @nbd-server-stop: -# -# Stop QEMU's embedded NBD server, and unregister all devices previously -# added via @nbd-server-add. -# -# Since: 1.3.0 -## -{ 'command': 'nbd-server-stop' } - -## -# @BlockExportType: -# -# An enumeration of block export types -# -# @nbd: NBD export -# -# Since: 4.2 -## -{ 'enum': 'BlockExportType', - 'data': [ 'nbd' ] } - -## -# @BlockExport: -# -# Describes a block export, i.e. how single node should be exported on an -# external interface. -# -# Since: 4.2 -## -{ 'union': 'BlockExport', - 'base': { 'type': 'BlockExportType' }, - 'discriminator': 'type', - 'data': { - 'nbd': 'BlockExportNbd' - } } - ## # @QuorumOpType: # @@ -5452,7 +5374,8 @@ # "date-sec": 1000012, # "date-nsec": 10, # "vm-clock-sec": 100, -# "vm-clock-nsec": 20 +# "vm-clock-nsec": 20, +# "icount": 220414 # } # } # diff --git a/qapi/block-export.json b/qapi/block-export.json new file mode 100644 index 0000000000000000000000000000000000000000..a9f488f99c1acf8f3accaa0048ebe9d599afb142 --- /dev/null +++ b/qapi/block-export.json @@ -0,0 +1,345 @@ +# -*- Mode: Python -*- +# vim: filetype=python + +## +# == Block device exports +## + +{ 'include': 'sockets.json' } + +## +# @NbdServerOptions: +# +# Keep this type consistent with the nbd-server-start arguments. The only +# intended difference is using SocketAddress instead of SocketAddressLegacy. +# +# @addr: Address on which to listen. +# @tls-creds: ID of the TLS credentials object (since 2.6). +# @tls-authz: ID of the QAuthZ authorization object used to validate +# the client's x509 distinguished name. This object is +# is only resolved at time of use, so can be deleted and +# recreated on the fly while the NBD server is active. +# If missing, it will default to denying access (since 4.0). +# @max-connections: The maximum number of connections to allow at the same +# time, 0 for unlimited. (since 5.2; default: 0) +# +# Since: 4.2 +## +{ 'struct': 'NbdServerOptions', + 'data': { 'addr': 'SocketAddress', + '*tls-creds': 'str', + '*tls-authz': 'str', + '*max-connections': 'uint32' } } + +## +# @nbd-server-start: +# +# Start an NBD server listening on the given host and port. Block +# devices can then be exported using @nbd-server-add. The NBD +# server will present them as named exports; for example, another +# QEMU instance could refer to them as "nbd:HOST:PORT:exportname=NAME". +# +# Keep this type consistent with the NbdServerOptions type. The only intended +# difference is using SocketAddressLegacy instead of SocketAddress. +# +# @addr: Address on which to listen. +# @tls-creds: ID of the TLS credentials object (since 2.6). +# @tls-authz: ID of the QAuthZ authorization object used to validate +# the client's x509 distinguished name. This object is +# is only resolved at time of use, so can be deleted and +# recreated on the fly while the NBD server is active. +# If missing, it will default to denying access (since 4.0). +# @max-connections: The maximum number of connections to allow at the same +# time, 0 for unlimited. (since 5.2; default: 0) +# +# Returns: error if the server is already running. +# +# Since: 1.3.0 +## +{ 'command': 'nbd-server-start', + 'data': { 'addr': 'SocketAddressLegacy', + '*tls-creds': 'str', + '*tls-authz': 'str', + '*max-connections': 'uint32' } } + +## +# @BlockExportOptionsNbdBase: +# +# An NBD block export (common options shared between nbd-server-add and +# the NBD branch of block-export-add). +# +# @name: Export name. If unspecified, the @device parameter is used as the +# export name. (Since 2.12) +# +# @description: Free-form description of the export, up to 4096 bytes. +# (Since 5.0) +# +# Since: 5.0 +## +{ 'struct': 'BlockExportOptionsNbdBase', + 'data': { '*name': 'str', '*description': 'str' } } + +## +# @BlockExportOptionsNbd: +# +# An NBD block export (distinct options used in the NBD branch of +# block-export-add). +# +# @bitmaps: Also export each of the named dirty bitmaps reachable from +# @device, so the NBD client can use NBD_OPT_SET_META_CONTEXT with +# the metadata context name "qemu:dirty-bitmap:BITMAP" to inspect +# each bitmap. +# +# @allocation-depth: Also export the allocation depth map for @device, so +# the NBD client can use NBD_OPT_SET_META_CONTEXT with +# the metadata context name "qemu:allocation-depth" to +# inspect allocation details. (since 5.2) +# +# Since: 5.2 +## +{ 'struct': 'BlockExportOptionsNbd', + 'base': 'BlockExportOptionsNbdBase', + 'data': { '*bitmaps': ['str'], '*allocation-depth': 'bool' } } + +## +# @BlockExportOptionsVhostUserBlk: +# +# A vhost-user-blk block export. +# +# @addr: The vhost-user socket on which to listen. Both 'unix' and 'fd' +# SocketAddress types are supported. Passed fds must be UNIX domain +# sockets. +# @logical-block-size: Logical block size in bytes. Defaults to 512 bytes. +# @num-queues: Number of request virtqueues. Must be greater than 0. Defaults +# to 1. +# +# Since: 5.2 +## +{ 'struct': 'BlockExportOptionsVhostUserBlk', + 'data': { 'addr': 'SocketAddress', + '*logical-block-size': 'size', + '*num-queues': 'uint16'} } + +## +# @NbdServerAddOptions: +# +# An NBD block export, per legacy nbd-server-add command. +# +# @device: The device name or node name of the node to be exported +# +# @writable: Whether clients should be able to write to the device via the +# NBD connection (default false). +# +# @bitmap: Also export a single dirty bitmap reachable from @device, so the +# NBD client can use NBD_OPT_SET_META_CONTEXT with the metadata +# context name "qemu:dirty-bitmap:BITMAP" to inspect the bitmap +# (since 4.0). +# +# Since: 5.0 +## +{ 'struct': 'NbdServerAddOptions', + 'base': 'BlockExportOptionsNbdBase', + 'data': { 'device': 'str', + '*writable': 'bool', '*bitmap': 'str' } } + +## +# @nbd-server-add: +# +# Export a block node to QEMU's embedded NBD server. +# +# The export name will be used as the id for the resulting block export. +# +# Features: +# @deprecated: This command is deprecated. Use @block-export-add instead. +# +# Returns: error if the server is not running, or export with the same name +# already exists. +# +# Since: 1.3.0 +## +{ 'command': 'nbd-server-add', + 'data': 'NbdServerAddOptions', 'boxed': true, 'features': ['deprecated'] } + +## +# @BlockExportRemoveMode: +# +# Mode for removing a block export. +# +# @safe: Remove export if there are no existing connections, fail otherwise. +# +# @hard: Drop all connections immediately and remove export. +# +# Potential additional modes to be added in the future: +# +# hide: Just hide export from new clients, leave existing connections as is. +# Remove export after all clients are disconnected. +# +# soft: Hide export from new clients, answer with ESHUTDOWN for all further +# requests from existing clients. +# +# Since: 2.12 +## +{'enum': 'BlockExportRemoveMode', 'data': ['safe', 'hard']} + +## +# @nbd-server-remove: +# +# Remove NBD export by name. +# +# @name: Block export id. +# +# @mode: Mode of command operation. See @BlockExportRemoveMode description. +# Default is 'safe'. +# +# Features: +# @deprecated: This command is deprecated. Use @block-export-del instead. +# +# Returns: error if +# - the server is not running +# - export is not found +# - mode is 'safe' and there are existing connections +# +# Since: 2.12 +## +{ 'command': 'nbd-server-remove', + 'data': {'name': 'str', '*mode': 'BlockExportRemoveMode'}, + 'features': ['deprecated'] } + +## +# @nbd-server-stop: +# +# Stop QEMU's embedded NBD server, and unregister all devices previously +# added via @nbd-server-add. +# +# Since: 1.3.0 +## +{ 'command': 'nbd-server-stop' } + +## +# @BlockExportType: +# +# An enumeration of block export types +# +# @nbd: NBD export +# @vhost-user-blk: vhost-user-blk export (since 5.2) +# +# Since: 4.2 +## +{ 'enum': 'BlockExportType', + 'data': [ 'nbd', 'vhost-user-blk' ] } + +## +# @BlockExportOptions: +# +# Describes a block export, i.e. how single node should be exported on an +# external interface. +# +# @id: A unique identifier for the block export (across all export types) +# +# @node-name: The node name of the block node to be exported (since: 5.2) +# +# @writable: True if clients should be able to write to the export +# (default false) +# +# @writethrough: If true, caches are flushed after every write request to the +# export before completion is signalled. (since: 5.2; +# default: false) +# +# @iothread: The name of the iothread object where the export will run. The +# default is to use the thread currently associated with the +# block node. (since: 5.2) +# +# @fixed-iothread: True prevents the block node from being moved to another +# thread while the export is active. If true and @iothread is +# given, export creation fails if the block node cannot be +# moved to the iothread. The default is false. (since: 5.2) +# +# Since: 4.2 +## +{ 'union': 'BlockExportOptions', + 'base': { 'type': 'BlockExportType', + 'id': 'str', + '*fixed-iothread': 'bool', + '*iothread': 'str', + 'node-name': 'str', + '*writable': 'bool', + '*writethrough': 'bool' }, + 'discriminator': 'type', + 'data': { + 'nbd': 'BlockExportOptionsNbd', + 'vhost-user-blk': 'BlockExportOptionsVhostUserBlk' + } } + +## +# @block-export-add: +# +# Creates a new block export. +# +# Since: 5.2 +## +{ 'command': 'block-export-add', + 'data': 'BlockExportOptions', 'boxed': true } + +## +# @block-export-del: +# +# Request to remove a block export. This drops the user's reference to the +# export, but the export may still stay around after this command returns until +# the shutdown of the export has completed. +# +# @id: Block export id. +# +# @mode: Mode of command operation. See @BlockExportRemoveMode description. +# Default is 'safe'. +# +# Returns: Error if the export is not found or @mode is 'safe' and the export +# is still in use (e.g. by existing client connections) +# +# Since: 5.2 +## +{ 'command': 'block-export-del', + 'data': { 'id': 'str', '*mode': 'BlockExportRemoveMode' } } + +## +# @BLOCK_EXPORT_DELETED: +# +# Emitted when a block export is removed and its id can be reused. +# +# @id: Block export id. +# +# Since: 5.2 +## +{ 'event': 'BLOCK_EXPORT_DELETED', + 'data': { 'id': 'str' } } + +## +# @BlockExportInfo: +# +# Information about a single block export. +# +# @id: The unique identifier for the block export +# +# @type: The block export type +# +# @node-name: The node name of the block node that is exported +# +# @shutting-down: True if the export is shutting down (e.g. after a +# block-export-del command, but before the shutdown has +# completed) +# +# Since: 5.2 +## +{ 'struct': 'BlockExportInfo', + 'data': { 'id': 'str', + 'type': 'BlockExportType', + 'node-name': 'str', + 'shutting-down': 'bool' } } + +## +# @query-block-exports: +# +# Returns: A list of BlockExportInfo describing all block exports +# +# Since: 5.2 +## +{ 'command': 'query-block-exports', 'returns': ['BlockExportInfo'] } diff --git a/qapi/block.json b/qapi/block.json index 2ddbfa8306aad1c2818e6d9a60381675ffc214ec..a009f7d3a2de7b129839cdcd84bb67c336c7660f 100644 --- a/qapi/block.json +++ b/qapi/block.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python ## # = Block devices @@ -527,7 +528,8 @@ # # Since: 4.0 # -# Example: set new histograms for all io types with intervals +# Example: +# set new histograms for all io types with intervals # [0, 10), [10, 50), [50, 100), [100, +inf): # # -> { "execute": "block-latency-histogram-set", @@ -535,7 +537,8 @@ # "boundaries": [10, 50, 100] } } # <- { "return": {} } # -# Example: set new histogram only for write, other histograms will remain +# Example: +# set new histogram only for write, other histograms will remain # not changed (or not created): # # -> { "execute": "block-latency-histogram-set", @@ -543,7 +546,8 @@ # "boundaries-write": [10, 50, 100] } } # <- { "return": {} } # -# Example: set new histograms with the following intervals: +# Example: +# set new histograms with the following intervals: # read, flush: [0, 10), [10, 50), [50, 100), [100, +inf) # write: [0, 1000), [1000, 5000), [5000, +inf) # @@ -553,7 +557,8 @@ # "boundaries-write": [1000, 5000] } } # <- { "return": {} } # -# Example: remove all latency histograms: +# Example: +# remove all latency histograms: # # -> { "execute": "block-latency-histogram-set", # "arguments": { "id": "drive0" } } diff --git a/qapi/char.json b/qapi/char.json index daceb20f84989acf8ad5a7010cc89c6667490637..43486d1daa93a9b612545cce27d6063daf63e537 100644 --- a/qapi/char.json +++ b/qapi/char.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # ## @@ -320,8 +321,7 @@ # Configuration info for stdio chardevs. # # @signal: Allow signals (such as SIGINT triggered by ^C) -# be delivered to qemu. Default: true in -nographic mode, -# false otherwise. +# be delivered to qemu. Default: true. # # Since: 1.5 ## @@ -561,6 +561,8 @@ # # @open: true if the guest has opened the virtio-serial port # +# Note: This event is rate-limited. +# # Since: 2.1 # # Example: diff --git a/qapi/common.json b/qapi/common.json index 7b9cbcd97b4b517e5ecb77c1793b25e2485556f2..716712d4b317e81c926bf4f308e869b651c05330 100644 --- a/qapi/common.json +++ b/qapi/common.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python ## # = Common data types diff --git a/qapi/control.json b/qapi/control.json index 6b816bb61fccf415ee913230c0f568686c530327..134f842bafa52c2db9436591a3244c4d5222e39a 100644 --- a/qapi/control.json +++ b/qapi/control.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # ## @@ -176,8 +177,8 @@ # # Features: # @deprecated: This command is deprecated, because its output doesn't -# reflect compile-time configuration. Use 'query-qmp-schema' -# instead. +# reflect compile-time configuration. Use 'query-qmp-schema' +# instead. # # Returns: A list of @EventInfo. # diff --git a/qapi/crypto.json b/qapi/crypto.json index b2a4cff683ff62a208c269630212a9a4c1198495..2aebe6fa20fd8051667a2e57d8ce37eec4c4de13 100644 --- a/qapi/crypto.json +++ b/qapi/crypto.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # ## @@ -297,7 +298,6 @@ 'uuid': 'str', 'slots': [ 'QCryptoBlockInfoLUKSSlot' ] }} - ## # @QCryptoBlockInfo: # @@ -309,3 +309,75 @@ 'base': 'QCryptoBlockInfoBase', 'discriminator': 'format', 'data': { 'luks': 'QCryptoBlockInfoLUKS' } } + +## +# @QCryptoBlockLUKSKeyslotState: +# +# Defines state of keyslots that are affected by the update +# +# @active: The slots contain the given password and marked as active +# @inactive: The slots are erased (contain garbage) and marked as inactive +# +# Since: 5.1 +## +{ 'enum': 'QCryptoBlockLUKSKeyslotState', + 'data': [ 'active', 'inactive' ] } + + +## +# @QCryptoBlockAmendOptionsLUKS: +# +# This struct defines the update parameters that activate/de-activate set +# of keyslots +# +# @state: the desired state of the keyslots +# +# @new-secret: The ID of a QCryptoSecret object providing the password to be +# written into added active keyslots +# +# @old-secret: Optional (for deactivation only) +# If given will deactivate all keyslots that +# match password located in QCryptoSecret with this ID +# +# @iter-time: Optional (for activation only) +# Number of milliseconds to spend in +# PBKDF passphrase processing for the newly activated keyslot. +# Currently defaults to 2000. +# +# @keyslot: Optional. ID of the keyslot to activate/deactivate. +# For keyslot activation, keyslot should not be active already +# (this is unsafe to update an active keyslot), +# but possible if 'force' parameter is given. +# If keyslot is not given, first free keyslot will be written. +# +# For keyslot deactivation, this parameter specifies the exact +# keyslot to deactivate +# +# @secret: Optional. The ID of a QCryptoSecret object providing the +# password to use to retrieve current master key. +# Defaults to the same secret that was used to open the image +# +# +# Since 5.1 +## +{ 'struct': 'QCryptoBlockAmendOptionsLUKS', + 'data': { 'state': 'QCryptoBlockLUKSKeyslotState', + '*new-secret': 'str', + '*old-secret': 'str', + '*keyslot': 'int', + '*iter-time': 'int', + '*secret': 'str' } } + +## +# @QCryptoBlockAmendOptions: +# +# The options that are available for all encryption formats +# when amending encryption settings +# +# Since: 5.1 +## +{ 'union': 'QCryptoBlockAmendOptions', + 'base': 'QCryptoBlockOptionsBase', + 'discriminator': 'format', + 'data': { + 'luks': 'QCryptoBlockAmendOptionsLUKS' } } diff --git a/qapi/dump.json b/qapi/dump.json index a1eed7b15c54eab8d95e6c7b4b722efee1523c93..f7c4267e3fcd4eeb34aa8957547b05c1462d60ab 100644 --- a/qapi/dump.json +++ b/qapi/dump.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # # This work is licensed under the terms of the GNU GPL, version 2 or later. # See the COPYING file in the top-level directory. diff --git a/qapi/error.json b/qapi/error.json index 3fad08f5060a86df86d82e07b1a1e5294a9bf64a..94a6502de9d2a6e4bb5f768408044e649cc74b1e 100644 --- a/qapi/error.json +++ b/qapi/error.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python ## # = QMP errors diff --git a/qapi/introspect.json b/qapi/introspect.json index b1aabd4cfd4f1c600a3406fd810eaf83eb784c75..944bb87a20df019bf9cc2976c6b6be96fa49e7b2 100644 --- a/qapi/introspect.json +++ b/qapi/introspect.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # # Copyright (C) 2015 Red Hat, Inc. # diff --git a/qapi/job.json b/qapi/job.json index 5e658281f5c4e4bbb484bea99fb46236a21657ca..280c2f76f136dc66446863fdb1a5a95a1bd1d846 100644 --- a/qapi/job.json +++ b/qapi/job.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python ## # == Background jobs @@ -19,10 +20,12 @@ # # @create: image creation job type, see "blockdev-create" (since 3.0) # +# @amend: image options amend job type, see "x-blockdev-amend" (since 5.1) +# # Since: 1.7 ## { 'enum': 'JobType', - 'data': ['commit', 'stream', 'mirror', 'backup', 'create'] } + 'data': ['commit', 'stream', 'mirror', 'backup', 'create', 'amend'] } ## # @JobStatus: diff --git a/qapi/machine-target.json b/qapi/machine-target.json index f2c82949d80b6d63c373d84b3d3c136a6af020f9..fec3bb8679fc303fed314c1e35a8b01bf9b7cec1 100644 --- a/qapi/machine-target.json +++ b/qapi/machine-target.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # # This work is licensed under the terms of the GNU GPL, version 2 or later. # See the COPYING file in the top-level directory. @@ -285,6 +286,10 @@ # in the VM configuration, because aliases may stop being # migration-safe in the future (since 4.1) # +# @deprecated: If true, this CPU model is deprecated and may be removed in +# in some future version of QEMU according to the QEMU deprecation +# policy. (since 5.2) +# # @unavailable-features is a list of QOM property names that # represent CPU model attributes that prevent the CPU from running. # If the QOM property is read-only, that means there's no known @@ -309,7 +314,8 @@ 'static': 'bool', '*unavailable-features': [ 'str' ], 'typename': 'str', - '*alias-of' : 'str' }, + '*alias-of' : 'str', + 'deprecated' : 'bool' }, 'if': 'defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_I386) || defined(TARGET_S390X) || defined(TARGET_MIPS)' } ## diff --git a/qapi/machine.json b/qapi/machine.json index ff7b5032e3aa66cca811905e6b14537035e3460a..7c9a263778d8b5757d828f7f833de517ea3c5ffc 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # # This work is licensed under the terms of the GNU GPL, version 2 or later. # See the COPYING file in the top-level directory. @@ -12,11 +13,12 @@ # # The comprehensive enumeration of QEMU system emulation ("softmmu") # targets. Run "./configure --help" in the project root directory, and -# look for the *-softmmu targets near the "--target-list" option. The +# look for the \*-softmmu targets near the "--target-list" option. The # individual target constants are not documented here, for the time # being. # # @rx: since 5.0 +# @avr: since 5.1 # # Notes: The resulting QMP strings can be appended to the "qemu-system-" # prefix to produce the corresponding QEMU executable name. This @@ -25,7 +27,7 @@ # Since: 3.0 ## { 'enum' : 'SysEmuTarget', - 'data' : [ 'aarch64', 'alpha', 'arm', 'cris', 'hppa', 'i386', 'lm32', + 'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'cris', 'hppa', 'i386', 'lm32', 'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64', 'mips64el', 'mipsel', 'moxie', 'nios2', 'or1k', 'ppc', 'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4', @@ -189,8 +191,8 @@ # # Features: # @deprecated: This command is deprecated, because it interferes with -# the guest. Use 'query-cpus-fast' instead to avoid the vCPU -# interruption. +# the guest. Use 'query-cpus-fast' instead to avoid the vCPU +# interruption. # # Returns: a list of @CpuInfo for each virtual CPU # @@ -305,30 +307,6 @@ ## { 'command': 'query-cpus-fast', 'returns': [ 'CpuInfoFast' ] } -## -# @cpu-add: -# -# Adds CPU with specified ID. -# -# @id: ID of CPU to be created, valid values [0..max_cpus) -# -# Features: -# @deprecated: This command is deprecated. Use `device_add` instead. -# See the `query-hotpluggable-cpus` command for details. -# -# Returns: Nothing on success -# -# Since: 1.5 -# -# Example: -# -# -> { "execute": "cpu-add", "arguments": { "id": 2 } } -# <- { "return": {} } -# -## -{ 'command': 'cpu-add', 'data': {'id': 'int'}, - 'features': [ 'deprecated' ] } - ## # @MachineInfo: # @@ -355,13 +333,16 @@ # @default-cpu-type: default CPU model typename if none is requested via # the -cpu argument. (since 4.2) # +# @default-ram-id: the default ID of initial RAM memory backend (since 5.2) +# # Since: 1.2.0 ## { 'struct': 'MachineInfo', 'data': { 'name': 'str', '*alias': 'str', '*is-default': 'bool', 'cpu-max': 'int', 'hotpluggable-cpus': 'bool', 'numa-mem-supported': 'bool', - 'deprecated': 'bool', '*default-cpu-type': 'str' } } + 'deprecated': 'bool', '*default-cpu-type': 'str', + '*default-ram-id': 'str' } } ## # @query-machines: @@ -421,6 +402,195 @@ ## { 'command': 'query-target', 'returns': 'TargetInfo' } +## +# @UuidInfo: +# +# Guest UUID information (Universally Unique Identifier). +# +# @UUID: the UUID of the guest +# +# Since: 0.14.0 +# +# Notes: If no UUID was specified for the guest, a null UUID is returned. +## +{ 'struct': 'UuidInfo', 'data': {'UUID': 'str'} } + +## +# @query-uuid: +# +# Query the guest UUID information. +# +# Returns: The @UuidInfo for the guest +# +# Since: 0.14.0 +# +# Example: +# +# -> { "execute": "query-uuid" } +# <- { "return": { "UUID": "550e8400-e29b-41d4-a716-446655440000" } } +# +## +{ 'command': 'query-uuid', 'returns': 'UuidInfo', 'allow-preconfig': true } + +## +# @GuidInfo: +# +# GUID information. +# +# @guid: the globally unique identifier +# +# Since: 2.9 +## +{ 'struct': 'GuidInfo', 'data': {'guid': 'str'} } + +## +# @query-vm-generation-id: +# +# Show Virtual Machine Generation ID +# +# Since: 2.9 +## +{ 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' } + +## +# @system_reset: +# +# Performs a hard reset of a guest. +# +# Since: 0.14.0 +# +# Example: +# +# -> { "execute": "system_reset" } +# <- { "return": {} } +# +## +{ 'command': 'system_reset' } + +## +# @system_powerdown: +# +# Requests that a guest perform a powerdown operation. +# +# Since: 0.14.0 +# +# Notes: A guest may or may not respond to this command. This command +# returning does not indicate that a guest has accepted the request or +# that it has shut down. Many guests will respond to this command by +# prompting the user in some way. +# Example: +# +# -> { "execute": "system_powerdown" } +# <- { "return": {} } +# +## +{ 'command': 'system_powerdown' } + +## +# @system_wakeup: +# +# Wake up guest from suspend. If the guest has wake-up from suspend +# support enabled (wakeup-suspend-support flag from +# query-current-machine), wake-up guest from suspend if the guest is +# in SUSPENDED state. Return an error otherwise. +# +# Since: 1.1 +# +# Returns: nothing. +# +# Note: prior to 4.0, this command does nothing in case the guest +# isn't suspended. +# +# Example: +# +# -> { "execute": "system_wakeup" } +# <- { "return": {} } +# +## +{ 'command': 'system_wakeup' } + +## +# @LostTickPolicy: +# +# Policy for handling lost ticks in timer devices. Ticks end up getting +# lost when, for example, the guest is paused. +# +# @discard: throw away the missed ticks and continue with future injection +# normally. The guest OS will see the timer jump ahead by a +# potentially quite significant amount all at once, as if the +# intervening chunk of time had simply not existed; needless to +# say, such a sudden jump can easily confuse a guest OS which is +# not specifically prepared to deal with it. Assuming the guest +# OS can deal correctly with the time jump, the time in the guest +# and in the host should now match. +# +# @delay: continue to deliver ticks at the normal rate. The guest OS will +# not notice anything is amiss, as from its point of view time will +# have continued to flow normally. The time in the guest should now +# be behind the time in the host by exactly the amount of time during +# which ticks have been missed. +# +# @slew: deliver ticks at a higher rate to catch up with the missed ticks. +# The guest OS will not notice anything is amiss, as from its point +# of view time will have continued to flow normally. Once the timer +# has managed to catch up with all the missing ticks, the time in +# the guest and in the host should match. +# +# Since: 2.0 +## +{ 'enum': 'LostTickPolicy', + 'data': ['discard', 'delay', 'slew' ] } + +## +# @inject-nmi: +# +# Injects a Non-Maskable Interrupt into the default CPU (x86/s390) or all CPUs (ppc64). +# The command fails when the guest doesn't support injecting. +# +# Returns: If successful, nothing +# +# Since: 0.14.0 +# +# Note: prior to 2.1, this command was only supported for x86 and s390 VMs +# +# Example: +# +# -> { "execute": "inject-nmi" } +# <- { "return": {} } +# +## +{ 'command': 'inject-nmi' } + +## +# @KvmInfo: +# +# Information about support for KVM acceleration +# +# @enabled: true if KVM acceleration is active +# +# @present: true if KVM acceleration is built into this executable +# +# Since: 0.14.0 +## +{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} } + +## +# @query-kvm: +# +# Returns information about KVM acceleration +# +# Returns: @KvmInfo +# +# Since: 0.14.0 +# +# Example: +# +# -> { "execute": "query-kvm" } +# <- { "return": { "enabled": true, "present": true } } +# +## +{ 'command': 'query-kvm', 'returns': 'KvmInfo' } + ## # @NumaOptionsType: # @@ -747,6 +917,67 @@ { 'enum': 'HostMemPolicy', 'data': [ 'default', 'preferred', 'bind', 'interleave' ] } +## +# @memsave: +# +# Save a portion of guest memory to a file. +# +# @val: the virtual address of the guest to start from +# +# @size: the size of memory region to save +# +# @filename: the file to save the memory to as binary data +# +# @cpu-index: the index of the virtual CPU to use for translating the +# virtual address (defaults to CPU 0) +# +# Returns: Nothing on success +# +# Since: 0.14.0 +# +# Notes: Errors were not reliably returned until 1.1 +# +# Example: +# +# -> { "execute": "memsave", +# "arguments": { "val": 10, +# "size": 100, +# "filename": "/tmp/virtual-mem-dump" } } +# <- { "return": {} } +# +## +{ 'command': 'memsave', + 'data': {'val': 'int', 'size': 'int', 'filename': 'str', '*cpu-index': 'int'} } + +## +# @pmemsave: +# +# Save a portion of guest physical memory to a file. +# +# @val: the physical address of the guest to start from +# +# @size: the size of memory region to save +# +# @filename: the file to save the memory to as binary data +# +# Returns: Nothing on success +# +# Since: 0.14.0 +# +# Notes: Errors were not reliably returned until 1.1 +# +# Example: +# +# -> { "execute": "pmemsave", +# "arguments": { "val": 10, +# "size": 100, +# "filename": "/tmp/physical-mem-dump" } } +# <- { "return": {} } +# +## +{ 'command': 'pmemsave', + 'data': {'val': 'int', 'size': 'int', 'filename': 'str'} } + ## # @Memdev: # @@ -824,7 +1055,8 @@ # @node-id: NUMA node ID the CPU belongs to # @socket-id: socket number within node/board the CPU belongs to # @die-id: die number within node/board the CPU belongs to (Since 4.1) -# @core-id: core number within die the CPU belongs to# @thread-id: thread number within core the CPU belongs to +# @core-id: core number within die the CPU belongs to +# @thread-id: thread number within core the CPU belongs to # # Note: currently there are 5 properties that could be present # but management should be prepared to pass through other @@ -931,3 +1163,311 @@ 'data': 'NumaOptions', 'allow-preconfig': true } + +## +# @balloon: +# +# Request the balloon driver to change its balloon size. +# +# @value: the target logical size of the VM in bytes. +# We can deduce the size of the balloon using this formula: +# +# logical_vm_size = vm_ram_size - balloon_size +# +# From it we have: balloon_size = vm_ram_size - @value +# +# Returns: - Nothing on success +# - If the balloon driver is enabled but not functional because the KVM +# kernel module cannot support it, KvmMissingCap +# - If no balloon device is present, DeviceNotActive +# +# Notes: This command just issues a request to the guest. When it returns, +# the balloon size may not have changed. A guest can change the balloon +# size independent of this command. +# +# Since: 0.14.0 +# +# Example: +# +# -> { "execute": "balloon", "arguments": { "value": 536870912 } } +# <- { "return": {} } +# +# With a 2.5GiB guest this command inflated the ballon to 3GiB. +# +## +{ 'command': 'balloon', 'data': {'value': 'int'} } + +## +# @BalloonInfo: +# +# Information about the guest balloon device. +# +# @actual: the logical size of the VM in bytes +# Formula used: logical_vm_size = vm_ram_size - balloon_size +# +# Since: 0.14.0 +# +## +{ 'struct': 'BalloonInfo', 'data': {'actual': 'int' } } + +## +# @query-balloon: +# +# Return information about the balloon device. +# +# Returns: - @BalloonInfo on success +# - If the balloon driver is enabled but not functional because the KVM +# kernel module cannot support it, KvmMissingCap +# - If no balloon device is present, DeviceNotActive +# +# Since: 0.14.0 +# +# Example: +# +# -> { "execute": "query-balloon" } +# <- { "return": { +# "actual": 1073741824, +# } +# } +# +## +{ 'command': 'query-balloon', 'returns': 'BalloonInfo' } + +## +# @BALLOON_CHANGE: +# +# Emitted when the guest changes the actual BALLOON level. This value is +# equivalent to the @actual field return by the 'query-balloon' command +# +# @actual: the logical size of the VM in bytes +# Formula used: logical_vm_size = vm_ram_size - balloon_size +# +# Note: this event is rate-limited. +# +# Since: 1.2 +# +# Example: +# +# <- { "event": "BALLOON_CHANGE", +# "data": { "actual": 944766976 }, +# "timestamp": { "seconds": 1267020223, "microseconds": 435656 } } +# +## +{ 'event': 'BALLOON_CHANGE', + 'data': { 'actual': 'int' } } + +## +# @MemoryInfo: +# +# Actual memory information in bytes. +# +# @base-memory: size of "base" memory specified with command line +# option -m. +# +# @plugged-memory: size of memory that can be hot-unplugged. This field +# is omitted if target doesn't support memory hotplug +# (i.e. CONFIG_MEM_DEVICE not defined at build time). +# +# Since: 2.11.0 +## +{ 'struct': 'MemoryInfo', + 'data' : { 'base-memory': 'size', '*plugged-memory': 'size' } } + +## +# @query-memory-size-summary: +# +# Return the amount of initially allocated and present hotpluggable (if +# enabled) memory in bytes. +# +# Example: +# +# -> { "execute": "query-memory-size-summary" } +# <- { "return": { "base-memory": 4294967296, "plugged-memory": 0 } } +# +# Since: 2.11.0 +## +{ 'command': 'query-memory-size-summary', 'returns': 'MemoryInfo' } + +## +# @PCDIMMDeviceInfo: +# +# PCDIMMDevice state information +# +# @id: device's ID +# +# @addr: physical address, where device is mapped +# +# @size: size of memory that the device provides +# +# @slot: slot number at which device is plugged in +# +# @node: NUMA node number where device is plugged in +# +# @memdev: memory backend linked with device +# +# @hotplugged: true if device was hotplugged +# +# @hotpluggable: true if device if could be added/removed while machine is running +# +# Since: 2.1 +## +{ 'struct': 'PCDIMMDeviceInfo', + 'data': { '*id': 'str', + 'addr': 'int', + 'size': 'int', + 'slot': 'int', + 'node': 'int', + 'memdev': 'str', + 'hotplugged': 'bool', + 'hotpluggable': 'bool' + } +} + +## +# @VirtioPMEMDeviceInfo: +# +# VirtioPMEM state information +# +# @id: device's ID +# +# @memaddr: physical address in memory, where device is mapped +# +# @size: size of memory that the device provides +# +# @memdev: memory backend linked with device +# +# Since: 4.1 +## +{ 'struct': 'VirtioPMEMDeviceInfo', + 'data': { '*id': 'str', + 'memaddr': 'size', + 'size': 'size', + 'memdev': 'str' + } +} + +## +# @VirtioMEMDeviceInfo: +# +# VirtioMEMDevice state information +# +# @id: device's ID +# +# @memaddr: physical address in memory, where device is mapped +# +# @requested-size: the user requested size of the device +# +# @size: the (current) size of memory that the device provides +# +# @max-size: the maximum size of memory that the device can provide +# +# @block-size: the block size of memory that the device provides +# +# @node: NUMA node number where device is assigned to +# +# @memdev: memory backend linked with the region +# +# Since: 5.1 +## +{ 'struct': 'VirtioMEMDeviceInfo', + 'data': { '*id': 'str', + 'memaddr': 'size', + 'requested-size': 'size', + 'size': 'size', + 'max-size': 'size', + 'block-size': 'size', + 'node': 'int', + 'memdev': 'str' + } +} + +## +# @MemoryDeviceInfo: +# +# Union containing information about a memory device +# +# nvdimm is included since 2.12. virtio-pmem is included since 4.1. +# virtio-mem is included since 5.1. +# +# Since: 2.1 +## +{ 'union': 'MemoryDeviceInfo', + 'data': { 'dimm': 'PCDIMMDeviceInfo', + 'nvdimm': 'PCDIMMDeviceInfo', + 'virtio-pmem': 'VirtioPMEMDeviceInfo', + 'virtio-mem': 'VirtioMEMDeviceInfo' + } +} + +## +# @query-memory-devices: +# +# Lists available memory devices and their state +# +# Since: 2.1 +# +# Example: +# +# -> { "execute": "query-memory-devices" } +# <- { "return": [ { "data": +# { "addr": 5368709120, +# "hotpluggable": true, +# "hotplugged": true, +# "id": "d1", +# "memdev": "/objects/memX", +# "node": 0, +# "size": 1073741824, +# "slot": 0}, +# "type": "dimm" +# } ] } +# +## +{ 'command': 'query-memory-devices', 'returns': ['MemoryDeviceInfo'] } + +## +# @MEMORY_DEVICE_SIZE_CHANGE: +# +# Emitted when the size of a memory device changes. Only emitted for memory +# devices that can actually change the size (e.g., virtio-mem due to guest +# action). +# +# @id: device's ID +# @size: the new size of memory that the device provides +# +# Note: this event is rate-limited. +# +# Since: 5.1 +# +# Example: +# +# <- { "event": "MEMORY_DEVICE_SIZE_CHANGE", +# "data": { "id": "vm0", "size": 1073741824}, +# "timestamp": { "seconds": 1588168529, "microseconds": 201316 } } +# +## +{ 'event': 'MEMORY_DEVICE_SIZE_CHANGE', + 'data': { '*id': 'str', 'size': 'size' } } + + +## +# @MEM_UNPLUG_ERROR: +# +# Emitted when memory hot unplug error occurs. +# +# @device: device name +# +# @msg: Informative message +# +# Since: 2.4 +# +# Example: +# +# <- { "event": "MEM_UNPLUG_ERROR" +# "data": { "device": "dimm1", +# "msg": "acpi: device unplug for unsupported device" +# }, +# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +## +{ 'event': 'MEM_UNPLUG_ERROR', + 'data': { 'device': 'str', 'msg': 'str' } } diff --git a/qapi/meson.build b/qapi/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..0e98146f1fcd1fc5e28c43b2ccf899e86209a02a --- /dev/null +++ b/qapi/meson.build @@ -0,0 +1,128 @@ +util_ss.add(files( + 'opts-visitor.c', + 'qapi-clone-visitor.c', + 'qapi-dealloc-visitor.c', + 'qapi-util.c', + 'qapi-visit-core.c', + 'qmp-dispatch.c', + 'qmp-event.c', + 'qmp-registry.c', + 'qobject-input-visitor.c', + 'qobject-output-visitor.c', + 'string-input-visitor.c', + 'string-output-visitor.c', +)) + +qapi_all_modules = [ + 'acpi', + 'audio', + 'authz', + 'block', + 'block-core', + 'block-export', + 'char', + 'common', + 'control', + 'crypto', + 'dump', + 'error', + 'introspect', + 'job', + 'machine', + 'machine-target', + 'migration', + 'misc', + 'misc-target', + 'net', + 'pragma', + 'qdev', + 'pci', + 'qom', + 'rdma', + 'replay', + 'rocker', + 'run-state', + 'sockets', + 'tpm', + 'trace', + 'transaction', + 'ui', +] + +qapi_storage_daemon_modules = [ + 'block-core', + 'block-export', + 'char', + 'common', + 'control', + 'crypto', + 'introspect', + 'job', + 'qom', + 'sockets', + 'pragma', + 'transaction', +] + +qapi_nonmodule_outputs = [ + 'qapi-introspect.c', 'qapi-introspect.h', + 'qapi-types.c', 'qapi-types.h', + 'qapi-visit.h', 'qapi-visit.c', + 'qapi-commands.h', 'qapi-commands.c', + 'qapi-init-commands.h', 'qapi-init-commands.c', + 'qapi-events.h', 'qapi-events.c', + 'qapi-emit-events.c', 'qapi-emit-events.h', +] + +# First build all sources +qapi_util_outputs = [ + 'qapi-builtin-types.c', 'qapi-builtin-visit.c', + 'qapi-builtin-types.h', 'qapi-builtin-visit.h', +] + +qapi_inputs = [] +qapi_specific_outputs = [] +foreach module : qapi_all_modules + qapi_inputs += [ files(module + '.json') ] + qapi_module_outputs = [ + 'qapi-types-@0@.c'.format(module), + 'qapi-types-@0@.h'.format(module), + 'qapi-visit-@0@.c'.format(module), + 'qapi-visit-@0@.h'.format(module), + 'qapi-events-@0@.c'.format(module), + 'qapi-events-@0@.h'.format(module), + 'qapi-commands-@0@.c'.format(module), + 'qapi-commands-@0@.h'.format(module), + ] + if module.endswith('-target') + qapi_specific_outputs += qapi_module_outputs + else + qapi_util_outputs += qapi_module_outputs + endif +endforeach + +qapi_files = custom_target('shared QAPI source files', + output: qapi_util_outputs + qapi_specific_outputs + qapi_nonmodule_outputs, + input: [ files('qapi-schema.json') ], + command: [ qapi_gen, '-o', 'qapi', '-b', '@INPUT0@' ], + depend_files: [ qapi_inputs, qapi_gen_depends ]) + +# Now go through all the outputs and add them to the right sourceset. +# These loops must be synchronized with the output of the above custom target. + +i = 0 +foreach output : qapi_util_outputs + if output.endswith('.h') + genh += qapi_files[i] + endif + util_ss.add(qapi_files[i]) + i = i + 1 +endforeach + +foreach output : qapi_specific_outputs + qapi_nonmodule_outputs + if output.endswith('.h') + genh += qapi_files[i] + endif + specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: qapi_files[i]) + i = i + 1 +endforeach diff --git a/qapi/migration.json b/qapi/migration.json index d5000558c6c940aa6e4b590c92f614139c0374b0..3c75820527259562bb6ed5db540e0d9d7a95e071 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # ## @@ -146,6 +147,18 @@ 'active', 'postcopy-active', 'postcopy-paused', 'postcopy-recover', 'completed', 'failed', 'colo', 'pre-switchover', 'device', 'wait-unplug' ] } +## +# @VfioStats: +# +# Detailed VFIO devices migration statistics +# +# @transferred: amount of bytes transferred to the target VM by VFIO devices +# +# Since: 5.2 +# +## +{ 'struct': 'VfioStats', + 'data': {'transferred': 'int' } } ## # @MigrationInfo: @@ -207,11 +220,16 @@ # # @socket-address: Only used for tcp, to know what the real port is (Since 4.0) # +# @vfio: @VfioStats containing detailed VFIO devices migration statistics, +# only returned if VFIO device is present, migration is supported by all +# VFIO devices and status is 'active' or 'completed' (since 5.2) +# # Since: 0.14.0 ## { 'struct': 'MigrationInfo', 'data': {'*status': 'MigrationStatus', '*ram': 'MigrationStats', '*disk': 'MigrationStats', + '*vfio': 'VfioStats', '*xbzrle-cache': 'XBZRLECacheStats', '*total-time': 'int', '*expected-downtime': 'int', @@ -507,6 +525,44 @@ 'data': [ 'none', 'zlib', { 'name': 'zstd', 'if': 'defined(CONFIG_ZSTD)' } ] } +## +# @BitmapMigrationBitmapAlias: +# +# @name: The name of the bitmap. +# +# @alias: An alias name for migration (for example the bitmap name on +# the opposite site). +# +# Since: 5.2 +## +{ 'struct': 'BitmapMigrationBitmapAlias', + 'data': { + 'name': 'str', + 'alias': 'str' + } } + +## +# @BitmapMigrationNodeAlias: +# +# Maps a block node name and the bitmaps it has to aliases for dirty +# bitmap migration. +# +# @node-name: A block node name. +# +# @alias: An alias block node name for migration (for example the +# node name on the opposite site). +# +# @bitmaps: Mappings for the bitmaps on this node. +# +# Since: 5.2 +## +{ 'struct': 'BitmapMigrationNodeAlias', + 'data': { + 'node-name': 'str', + 'alias': 'str', + 'bitmaps': [ 'BitmapMigrationBitmapAlias' ] + } } + ## # @MigrationParameter: # @@ -628,18 +684,37 @@ # Defaults to none. (Since 5.0) # # @multifd-zlib-level: Set the compression level to be used in live -# migration, the compression level is an integer between 0 -# and 9, where 0 means no compression, 1 means the best -# compression speed, and 9 means best compression ratio which -# will consume more CPU. -# Defaults to 1. (Since 5.0) +# migration, the compression level is an integer between 0 +# and 9, where 0 means no compression, 1 means the best +# compression speed, and 9 means best compression ratio which +# will consume more CPU. +# Defaults to 1. (Since 5.0) # # @multifd-zstd-level: Set the compression level to be used in live -# migration, the compression level is an integer between 0 -# and 20, where 0 means no compression, 1 means the best -# compression speed, and 20 means best compression ratio which -# will consume more CPU. -# Defaults to 1. (Since 5.0) +# migration, the compression level is an integer between 0 +# and 20, where 0 means no compression, 1 means the best +# compression speed, and 20 means best compression ratio which +# will consume more CPU. +# Defaults to 1. (Since 5.0) +# +# @block-bitmap-mapping: Maps block nodes and bitmaps on them to +# aliases for the purpose of dirty bitmap migration. Such +# aliases may for example be the corresponding names on the +# opposite site. +# The mapping must be one-to-one, but not necessarily +# complete: On the source, unmapped bitmaps and all bitmaps +# on unmapped nodes will be ignored. On the destination, +# encountering an unmapped alias in the incoming migration +# stream will result in a report, and all further bitmap +# migration data will then be discarded. +# Note that the destination does not know about bitmaps it +# does not receive, so there is no limitation or requirement +# regarding the number of bitmaps received, or how they are +# named, or on which nodes they are placed. +# By default (when this parameter has never been set), bitmap +# names are mapped to themselves. Nodes are mapped to their +# block device name if there is one, and to their node name +# otherwise. (Since 5.2) # # Since: 2.4 ## @@ -655,7 +730,8 @@ 'multifd-channels', 'xbzrle-cache-size', 'max-postcopy-bandwidth', 'max-cpu-throttle', 'multifd-compression', - 'multifd-zlib-level' ,'multifd-zstd-level' ] } + 'multifd-zlib-level' ,'multifd-zstd-level', + 'block-bitmap-mapping' ] } ## # @MigrateSetParameters: @@ -768,18 +844,37 @@ # Defaults to none. (Since 5.0) # # @multifd-zlib-level: Set the compression level to be used in live -# migration, the compression level is an integer between 0 -# and 9, where 0 means no compression, 1 means the best -# compression speed, and 9 means best compression ratio which -# will consume more CPU. -# Defaults to 1. (Since 5.0) +# migration, the compression level is an integer between 0 +# and 9, where 0 means no compression, 1 means the best +# compression speed, and 9 means best compression ratio which +# will consume more CPU. +# Defaults to 1. (Since 5.0) # # @multifd-zstd-level: Set the compression level to be used in live -# migration, the compression level is an integer between 0 -# and 20, where 0 means no compression, 1 means the best -# compression speed, and 20 means best compression ratio which -# will consume more CPU. -# Defaults to 1. (Since 5.0) +# migration, the compression level is an integer between 0 +# and 20, where 0 means no compression, 1 means the best +# compression speed, and 20 means best compression ratio which +# will consume more CPU. +# Defaults to 1. (Since 5.0) +# +# @block-bitmap-mapping: Maps block nodes and bitmaps on them to +# aliases for the purpose of dirty bitmap migration. Such +# aliases may for example be the corresponding names on the +# opposite site. +# The mapping must be one-to-one, but not necessarily +# complete: On the source, unmapped bitmaps and all bitmaps +# on unmapped nodes will be ignored. On the destination, +# encountering an unmapped alias in the incoming migration +# stream will result in a report, and all further bitmap +# migration data will then be discarded. +# Note that the destination does not know about bitmaps it +# does not receive, so there is no limitation or requirement +# regarding the number of bitmaps received, or how they are +# named, or on which nodes they are placed. +# By default (when this parameter has never been set), bitmap +# names are mapped to themselves. Nodes are mapped to their +# block device name if there is one, and to their node name +# otherwise. (Since 5.2) # # Since: 2.4 ## @@ -811,7 +906,8 @@ '*max-cpu-throttle': 'int', '*multifd-compression': 'MultiFDCompression', '*multifd-zlib-level': 'int', - '*multifd-zstd-level': 'int' } } + '*multifd-zstd-level': 'int', + '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ] } } ## # @migrate-set-parameters: @@ -944,18 +1040,37 @@ # Defaults to none. (Since 5.0) # # @multifd-zlib-level: Set the compression level to be used in live -# migration, the compression level is an integer between 0 -# and 9, where 0 means no compression, 1 means the best -# compression speed, and 9 means best compression ratio which -# will consume more CPU. -# Defaults to 1. (Since 5.0) +# migration, the compression level is an integer between 0 +# and 9, where 0 means no compression, 1 means the best +# compression speed, and 9 means best compression ratio which +# will consume more CPU. +# Defaults to 1. (Since 5.0) # # @multifd-zstd-level: Set the compression level to be used in live -# migration, the compression level is an integer between 0 -# and 20, where 0 means no compression, 1 means the best -# compression speed, and 20 means best compression ratio which -# will consume more CPU. -# Defaults to 1. (Since 5.0) +# migration, the compression level is an integer between 0 +# and 20, where 0 means no compression, 1 means the best +# compression speed, and 20 means best compression ratio which +# will consume more CPU. +# Defaults to 1. (Since 5.0) +# +# @block-bitmap-mapping: Maps block nodes and bitmaps on them to +# aliases for the purpose of dirty bitmap migration. Such +# aliases may for example be the corresponding names on the +# opposite site. +# The mapping must be one-to-one, but not necessarily +# complete: On the source, unmapped bitmaps and all bitmaps +# on unmapped nodes will be ignored. On the destination, +# encountering an unmapped alias in the incoming migration +# stream will result in a report, and all further bitmap +# migration data will then be discarded. +# Note that the destination does not know about bitmaps it +# does not receive, so there is no limitation or requirement +# regarding the number of bitmaps received, or how they are +# named, or on which nodes they are placed. +# By default (when this parameter has never been set), bitmap +# names are mapped to themselves. Nodes are mapped to their +# block device name if there is one, and to their node name +# otherwise. (Since 5.2) # # Since: 2.4 ## @@ -985,7 +1100,8 @@ '*max-cpu-throttle': 'uint8', '*multifd-compression': 'MultiFDCompression', '*multifd-zlib-level': 'uint8', - '*multifd-zstd-level': 'uint8' } } + '*multifd-zstd-level': 'uint8', + '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ] } } ## # @query-migrate-parameters: @@ -1263,7 +1379,7 @@ # # Features: # @deprecated: This command is deprecated. Use -# 'migrate-set-parameters' instead. +# 'migrate-set-parameters' instead. # # Returns: nothing on success # @@ -1287,7 +1403,7 @@ # # Features: # @deprecated: This command is deprecated. Use -# 'migrate-set-parameters' instead. +# 'migrate-set-parameters' instead. # # Returns: nothing on success # @@ -1311,7 +1427,7 @@ # # Features: # @deprecated: This command is deprecated. Use -# 'migrate-set-parameters' instead. +# 'migrate-set-parameters' instead. # # The size will be rounded down to the nearest power of 2. # The cache size can be modified before and during ongoing migration @@ -1337,7 +1453,7 @@ # # Features: # @deprecated: This command is deprecated. Use -# 'query-migrate-parameters' instead. +# 'query-migrate-parameters' instead. # # Returns: XBZRLE cache size in bytes # @@ -1452,6 +1568,47 @@ { 'command': 'xen-save-devices-state', 'data': {'filename': 'str', '*live':'bool' } } +## +# @xen-set-global-dirty-log: +# +# Enable or disable the global dirty log mode. +# +# @enable: true to enable, false to disable. +# +# Returns: nothing +# +# Since: 1.3 +# +# Example: +# +# -> { "execute": "xen-set-global-dirty-log", +# "arguments": { "enable": true } } +# <- { "return": {} } +# +## +{ 'command': 'xen-set-global-dirty-log', 'data': { 'enable': 'bool' } } + +## +# @xen-load-devices-state: +# +# Load the state of all devices from file. The RAM and the block devices +# of the VM are not loaded by this command. +# +# @filename: the file to load the state of the devices from as binary +# data. See xen-save-devices-state.txt for a description of the binary +# format. +# +# Since: 2.7 +# +# Example: +# +# -> { "execute": "xen-load-devices-state", +# "arguments": { "filename": "/tmp/resume" } } +# <- { "return": {} } +# +## +{ 'command': 'xen-load-devices-state', 'data': {'filename': 'str'} } + ## # @xen-set-replication: # @@ -1621,3 +1778,68 @@ ## { 'event': 'UNPLUG_PRIMARY', 'data': { 'device-id': 'str' } } + +## +# @DirtyRateStatus: +# +# An enumeration of dirtyrate status. +# +# @unstarted: the dirtyrate thread has not been started. +# +# @measuring: the dirtyrate thread is measuring. +# +# @measured: the dirtyrate thread has measured and results are available. +# +# Since: 5.2 +# +## +{ 'enum': 'DirtyRateStatus', + 'data': [ 'unstarted', 'measuring', 'measured'] } + +## +# @DirtyRateInfo: +# +# Information about current dirty page rate of vm. +# +# @dirty-rate: an estimate of the dirty page rate of the VM in units of +# MB/s, present only when estimating the rate has completed. +# +# @status: status containing dirtyrate query status includes +# 'unstarted' or 'measuring' or 'measured' +# +# @start-time: start time in units of second for calculation +# +# @calc-time: time in units of second for sample dirty pages +# +# Since: 5.2 +# +## +{ 'struct': 'DirtyRateInfo', + 'data': {'*dirty-rate': 'int64', + 'status': 'DirtyRateStatus', + 'start-time': 'int64', + 'calc-time': 'int64'} } + +## +# @calc-dirty-rate: +# +# start calculating dirty page rate for vm +# +# @calc-time: time in units of second for sample dirty pages +# +# Since: 5.2 +# +# Example: +# {"command": "calc-dirty-rate", "data": {"calc-time": 1} } +# +## +{ 'command': 'calc-dirty-rate', 'data': {'calc-time': 'int64'} } + +## +# @query-dirty-rate: +# +# query dirty page rate in units of MB/s for vm +# +# Since: 5.2 +## +{ 'command': 'query-dirty-rate', 'returns': 'DirtyRateInfo' } diff --git a/qapi/misc-target.json b/qapi/misc-target.json index dee3b45930143c552fb29f36363fcd0ed0c8c582..1e561fa97ba239a3b8428fd868726de85f9828ce 100644 --- a/qapi/misc-target.json +++ b/qapi/misc-target.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # ## diff --git a/qapi/misc.json b/qapi/misc.json index 99b90ac80b834ed84c691868ae424df750b66194..40df513856e7b8c00b68c1ead2c04272e471a27e 100644 --- a/qapi/misc.json +++ b/qapi/misc.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # ## @@ -7,38 +8,6 @@ { 'include': 'common.json' } -## -# @LostTickPolicy: -# -# Policy for handling lost ticks in timer devices. Ticks end up getting -# lost when, for example, the guest is paused. -# -# @discard: throw away the missed ticks and continue with future injection -# normally. The guest OS will see the timer jump ahead by a -# potentially quite significant amount all at once, as if the -# intervening chunk of time had simply not existed; needless to -# say, such a sudden jump can easily confuse a guest OS which is -# not specifically prepared to deal with it. Assuming the guest -# OS can deal correctly with the time jump, the time in the guest -# and in the host should now match. -# -# @delay: continue to deliver ticks at the normal rate. The guest OS will -# not notice anything is amiss, as from its point of view time will -# have continued to flow normally. The time in the guest should now -# be behind the time in the host by exactly the amount of time during -# which ticks have been missed. -# -# @slew: deliver ticks at a higher rate to catch up with the missed ticks. -# The guest OS will not notice anything is amiss, as from its point -# of view time will have continued to flow normally. Once the timer -# has managed to catch up with all the missing ticks, the time in -# the guest and in the host should match. -# -# Since: 2.0 -## -{ 'enum': 'LostTickPolicy', - 'data': ['discard', 'delay', 'slew' ] } - ## # @add_client: # @@ -99,66 +68,6 @@ ## { 'command': 'query-name', 'returns': 'NameInfo', 'allow-preconfig': true } -## -# @KvmInfo: -# -# Information about support for KVM acceleration -# -# @enabled: true if KVM acceleration is active -# -# @present: true if KVM acceleration is built into this executable -# -# Since: 0.14.0 -## -{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} } - -## -# @query-kvm: -# -# Returns information about KVM acceleration -# -# Returns: @KvmInfo -# -# Since: 0.14.0 -# -# Example: -# -# -> { "execute": "query-kvm" } -# <- { "return": { "enabled": true, "present": true } } -# -## -{ 'command': 'query-kvm', 'returns': 'KvmInfo' } - -## -# @UuidInfo: -# -# Guest UUID information (Universally Unique Identifier). -# -# @UUID: the UUID of the guest -# -# Since: 0.14.0 -# -# Notes: If no UUID was specified for the guest, a null UUID is returned. -## -{ 'struct': 'UuidInfo', 'data': {'UUID': 'str'} } - -## -# @query-uuid: -# -# Query the guest UUID information. -# -# Returns: The @UuidInfo for the guest -# -# Since: 0.14.0 -# -# Example: -# -# -> { "execute": "query-uuid" } -# <- { "return": { "UUID": "550e8400-e29b-41d4-a716-446655440000" } } -# -## -{ 'command': 'query-uuid', 'returns': 'UuidInfo', 'allow-preconfig': true } - ## # @IOThreadInfo: # @@ -218,367 +127,6 @@ { 'command': 'query-iothreads', 'returns': ['IOThreadInfo'], 'allow-preconfig': true } -## -# @BalloonInfo: -# -# Information about the guest balloon device. -# -# @actual: the number of bytes the balloon currently contains -# -# Since: 0.14.0 -# -## -{ 'struct': 'BalloonInfo', 'data': {'actual': 'int' } } - -## -# @query-balloon: -# -# Return information about the balloon device. -# -# Returns: - @BalloonInfo on success -# - If the balloon driver is enabled but not functional because the KVM -# kernel module cannot support it, KvmMissingCap -# - If no balloon device is present, DeviceNotActive -# -# Since: 0.14.0 -# -# Example: -# -# -> { "execute": "query-balloon" } -# <- { "return": { -# "actual": 1073741824, -# } -# } -# -## -{ 'command': 'query-balloon', 'returns': 'BalloonInfo' } - -## -# @BALLOON_CHANGE: -# -# Emitted when the guest changes the actual BALLOON level. This value is -# equivalent to the @actual field return by the 'query-balloon' command -# -# @actual: actual level of the guest memory balloon in bytes -# -# Note: this event is rate-limited. -# -# Since: 1.2 -# -# Example: -# -# <- { "event": "BALLOON_CHANGE", -# "data": { "actual": 944766976 }, -# "timestamp": { "seconds": 1267020223, "microseconds": 435656 } } -# -## -{ 'event': 'BALLOON_CHANGE', - 'data': { 'actual': 'int' } } - -## -# @PciMemoryRange: -# -# A PCI device memory region -# -# @base: the starting address (guest physical) -# -# @limit: the ending address (guest physical) -# -# Since: 0.14.0 -## -{ 'struct': 'PciMemoryRange', 'data': {'base': 'int', 'limit': 'int'} } - -## -# @PciMemoryRegion: -# -# Information about a PCI device I/O region. -# -# @bar: the index of the Base Address Register for this region -# -# @type: - 'io' if the region is a PIO region -# - 'memory' if the region is a MMIO region -# -# @size: memory size -# -# @prefetch: if @type is 'memory', true if the memory is prefetchable -# -# @mem_type_64: if @type is 'memory', true if the BAR is 64-bit -# -# Since: 0.14.0 -## -{ 'struct': 'PciMemoryRegion', - 'data': {'bar': 'int', 'type': 'str', 'address': 'int', 'size': 'int', - '*prefetch': 'bool', '*mem_type_64': 'bool' } } - -## -# @PciBusInfo: -# -# Information about a bus of a PCI Bridge device -# -# @number: primary bus interface number. This should be the number of the -# bus the device resides on. -# -# @secondary: secondary bus interface number. This is the number of the -# main bus for the bridge -# -# @subordinate: This is the highest number bus that resides below the -# bridge. -# -# @io_range: The PIO range for all devices on this bridge -# -# @memory_range: The MMIO range for all devices on this bridge -# -# @prefetchable_range: The range of prefetchable MMIO for all devices on -# this bridge -# -# Since: 2.4 -## -{ 'struct': 'PciBusInfo', - 'data': {'number': 'int', 'secondary': 'int', 'subordinate': 'int', - 'io_range': 'PciMemoryRange', - 'memory_range': 'PciMemoryRange', - 'prefetchable_range': 'PciMemoryRange' } } - -## -# @PciBridgeInfo: -# -# Information about a PCI Bridge device -# -# @bus: information about the bus the device resides on -# -# @devices: a list of @PciDeviceInfo for each device on this bridge -# -# Since: 0.14.0 -## -{ 'struct': 'PciBridgeInfo', - 'data': {'bus': 'PciBusInfo', '*devices': ['PciDeviceInfo']} } - -## -# @PciDeviceClass: -# -# Information about the Class of a PCI device -# -# @desc: a string description of the device's class -# -# @class: the class code of the device -# -# Since: 2.4 -## -{ 'struct': 'PciDeviceClass', - 'data': {'*desc': 'str', 'class': 'int'} } - -## -# @PciDeviceId: -# -# Information about the Id of a PCI device -# -# @device: the PCI device id -# -# @vendor: the PCI vendor id -# -# @subsystem: the PCI subsystem id (since 3.1) -# -# @subsystem-vendor: the PCI subsystem vendor id (since 3.1) -# -# Since: 2.4 -## -{ 'struct': 'PciDeviceId', - 'data': {'device': 'int', 'vendor': 'int', '*subsystem': 'int', - '*subsystem-vendor': 'int'} } - -## -# @PciDeviceInfo: -# -# Information about a PCI device -# -# @bus: the bus number of the device -# -# @slot: the slot the device is located in -# -# @function: the function of the slot used by the device -# -# @class_info: the class of the device -# -# @id: the PCI device id -# -# @irq: if an IRQ is assigned to the device, the IRQ number -# -# @qdev_id: the device name of the PCI device -# -# @pci_bridge: if the device is a PCI bridge, the bridge information -# -# @regions: a list of the PCI I/O regions associated with the device -# -# Notes: the contents of @class_info.desc are not stable and should only be -# treated as informational. -# -# Since: 0.14.0 -## -{ 'struct': 'PciDeviceInfo', - 'data': {'bus': 'int', 'slot': 'int', 'function': 'int', - 'class_info': 'PciDeviceClass', 'id': 'PciDeviceId', - '*irq': 'int', 'qdev_id': 'str', '*pci_bridge': 'PciBridgeInfo', - 'regions': ['PciMemoryRegion']} } - -## -# @PciInfo: -# -# Information about a PCI bus -# -# @bus: the bus index -# -# @devices: a list of devices on this bus -# -# Since: 0.14.0 -## -{ 'struct': 'PciInfo', 'data': {'bus': 'int', 'devices': ['PciDeviceInfo']} } - -## -# @query-pci: -# -# Return information about the PCI bus topology of the guest. -# -# Returns: a list of @PciInfo for each PCI bus. Each bus is -# represented by a json-object, which has a key with a json-array of -# all PCI devices attached to it. Each device is represented by a -# json-object. -# -# Since: 0.14.0 -# -# Example: -# -# -> { "execute": "query-pci" } -# <- { "return": [ -# { -# "bus": 0, -# "devices": [ -# { -# "bus": 0, -# "qdev_id": "", -# "slot": 0, -# "class_info": { -# "class": 1536, -# "desc": "Host bridge" -# }, -# "id": { -# "device": 32902, -# "vendor": 4663 -# }, -# "function": 0, -# "regions": [ -# ] -# }, -# { -# "bus": 0, -# "qdev_id": "", -# "slot": 1, -# "class_info": { -# "class": 1537, -# "desc": "ISA bridge" -# }, -# "id": { -# "device": 32902, -# "vendor": 28672 -# }, -# "function": 0, -# "regions": [ -# ] -# }, -# { -# "bus": 0, -# "qdev_id": "", -# "slot": 1, -# "class_info": { -# "class": 257, -# "desc": "IDE controller" -# }, -# "id": { -# "device": 32902, -# "vendor": 28688 -# }, -# "function": 1, -# "regions": [ -# { -# "bar": 4, -# "size": 16, -# "address": 49152, -# "type": "io" -# } -# ] -# }, -# { -# "bus": 0, -# "qdev_id": "", -# "slot": 2, -# "class_info": { -# "class": 768, -# "desc": "VGA controller" -# }, -# "id": { -# "device": 4115, -# "vendor": 184 -# }, -# "function": 0, -# "regions": [ -# { -# "prefetch": true, -# "mem_type_64": false, -# "bar": 0, -# "size": 33554432, -# "address": 4026531840, -# "type": "memory" -# }, -# { -# "prefetch": false, -# "mem_type_64": false, -# "bar": 1, -# "size": 4096, -# "address": 4060086272, -# "type": "memory" -# }, -# { -# "prefetch": false, -# "mem_type_64": false, -# "bar": 6, -# "size": 65536, -# "address": -1, -# "type": "memory" -# } -# ] -# }, -# { -# "bus": 0, -# "qdev_id": "", -# "irq": 11, -# "slot": 4, -# "class_info": { -# "class": 1280, -# "desc": "RAM controller" -# }, -# "id": { -# "device": 6900, -# "vendor": 4098 -# }, -# "function": 0, -# "regions": [ -# { -# "bar": 0, -# "size": 32, -# "address": 49280, -# "type": "io" -# } -# ] -# } -# ] -# } -# ] -# } -# -# Note: This example has been shortened as the real response is too long. -# -## -{ 'command': 'query-pci', 'returns': ['PciInfo'] } - ## # @stop: # @@ -599,101 +147,6 @@ ## { 'command': 'stop' } -## -# @system_reset: -# -# Performs a hard reset of a guest. -# -# Since: 0.14.0 -# -# Example: -# -# -> { "execute": "system_reset" } -# <- { "return": {} } -# -## -{ 'command': 'system_reset' } - -## -# @system_powerdown: -# -# Requests that a guest perform a powerdown operation. -# -# Since: 0.14.0 -# -# Notes: A guest may or may not respond to this command. This command -# returning does not indicate that a guest has accepted the request or -# that it has shut down. Many guests will respond to this command by -# prompting the user in some way. -# Example: -# -# -> { "execute": "system_powerdown" } -# <- { "return": {} } -# -## -{ 'command': 'system_powerdown' } - -## -# @memsave: -# -# Save a portion of guest memory to a file. -# -# @val: the virtual address of the guest to start from -# -# @size: the size of memory region to save -# -# @filename: the file to save the memory to as binary data -# -# @cpu-index: the index of the virtual CPU to use for translating the -# virtual address (defaults to CPU 0) -# -# Returns: Nothing on success -# -# Since: 0.14.0 -# -# Notes: Errors were not reliably returned until 1.1 -# -# Example: -# -# -> { "execute": "memsave", -# "arguments": { "val": 10, -# "size": 100, -# "filename": "/tmp/virtual-mem-dump" } } -# <- { "return": {} } -# -## -{ 'command': 'memsave', - 'data': {'val': 'int', 'size': 'int', 'filename': 'str', '*cpu-index': 'int'} } - -## -# @pmemsave: -# -# Save a portion of guest physical memory to a file. -# -# @val: the physical address of the guest to start from -# -# @size: the size of memory region to save -# -# @filename: the file to save the memory to as binary data -# -# Returns: Nothing on success -# -# Since: 0.14.0 -# -# Notes: Errors were not reliably returned until 1.1 -# -# Example: -# -# -> { "execute": "pmemsave", -# "arguments": { "val": 10, -# "size": 100, -# "filename": "/tmp/physical-mem-dump" } } -# <- { "return": {} } -# -## -{ 'command': 'pmemsave', - 'data': {'val': 'int', 'size': 'int', 'filename': 'str'} } - ## # @cont: # @@ -740,75 +193,6 @@ ## { 'command': 'x-exit-preconfig', 'allow-preconfig': true } -## -# @system_wakeup: -# -# Wake up guest from suspend. If the guest has wake-up from suspend -# support enabled (wakeup-suspend-support flag from -# query-current-machine), wake-up guest from suspend if the guest is -# in SUSPENDED state. Return an error otherwise. -# -# Since: 1.1 -# -# Returns: nothing. -# -# Note: prior to 4.0, this command does nothing in case the guest -# isn't suspended. -# -# Example: -# -# -> { "execute": "system_wakeup" } -# <- { "return": {} } -# -## -{ 'command': 'system_wakeup' } - -## -# @inject-nmi: -# -# Injects a Non-Maskable Interrupt into the default CPU (x86/s390) or all CPUs (ppc64). -# The command fails when the guest doesn't support injecting. -# -# Returns: If successful, nothing -# -# Since: 0.14.0 -# -# Note: prior to 2.1, this command was only supported for x86 and s390 VMs -# -# Example: -# -# -> { "execute": "inject-nmi" } -# <- { "return": {} } -# -## -{ 'command': 'inject-nmi' } - -## -# @balloon: -# -# Request the balloon driver to change its balloon size. -# -# @value: the target size of the balloon in bytes -# -# Returns: - Nothing on success -# - If the balloon driver is enabled but not functional because the KVM -# kernel module cannot support it, KvmMissingCap -# - If no balloon device is present, DeviceNotActive -# -# Notes: This command just issues a request to the guest. When it returns, -# the balloon size may not have changed. A guest can change the balloon -# size independent of this command. -# -# Since: 0.14.0 -# -# Example: -# -# -> { "execute": "balloon", "arguments": { "value": 536870912 } } -# <- { "return": {} } -# -## -{ 'command': 'balloon', 'data': {'value': 'int'} } - ## # @human-monitor-command: # @@ -874,8 +258,8 @@ # # Features: # @deprecated: This command is deprecated. For changing block -# devices, use 'blockdev-change-medium' instead; for changing VNC -# parameters, use 'change-vnc-password' instead. +# devices, use 'blockdev-change-medium' instead; for changing VNC +# parameters, use 'change-vnc-password' instead. # # Returns: - Nothing on success. # - If @device is not a valid block device, DeviceNotFound @@ -903,26 +287,6 @@ 'data': {'device': 'str', 'target': 'str', '*arg': 'str'}, 'features': [ 'deprecated' ] } -## -# @xen-set-global-dirty-log: -# -# Enable or disable the global dirty log mode. -# -# @enable: true to enable, false to disable. -# -# Returns: nothing -# -# Since: 1.3 -# -# Example: -# -# -> { "execute": "xen-set-global-dirty-log", -# "arguments": { "enable": true } } -# <- { "return": {} } -# -## -{ 'command': 'xen-set-global-dirty-log', 'data': { 'enable': 'bool' } } - ## # @getfd: # @@ -968,39 +332,6 @@ ## { 'command': 'closefd', 'data': {'fdname': 'str'} } -## -# @MemoryInfo: -# -# Actual memory information in bytes. -# -# @base-memory: size of "base" memory specified with command line -# option -m. -# -# @plugged-memory: size of memory that can be hot-unplugged. This field -# is omitted if target doesn't support memory hotplug -# (i.e. CONFIG_MEM_DEVICE not defined at build time). -# -# Since: 2.11.0 -## -{ 'struct': 'MemoryInfo', - 'data' : { 'base-memory': 'size', '*plugged-memory': 'size' } } - -## -# @query-memory-size-summary: -# -# Return the amount of initially allocated and present hotpluggable (if -# enabled) memory in bytes. -# -# Example: -# -# -> { "execute": "query-memory-size-summary" } -# <- { "return": { "base-memory": 4294967296, "plugged-memory": 0 } } -# -# Since: 2.11.0 -## -{ 'command': 'query-memory-size-summary', 'returns': 'MemoryInfo' } - - ## # @AddfdInfo: # @@ -1145,64 +476,6 @@ ## { 'command': 'query-fdsets', 'returns': ['FdsetInfo'] } -## -# @AcpiTableOptions: -# -# Specify an ACPI table on the command line to load. -# -# At most one of @file and @data can be specified. The list of files specified -# by any one of them is loaded and concatenated in order. If both are omitted, -# @data is implied. -# -# Other fields / optargs can be used to override fields of the generic ACPI -# table header; refer to the ACPI specification 5.0, section 5.2.6 System -# Description Table Header. If a header field is not overridden, then the -# corresponding value from the concatenated blob is used (in case of @file), or -# it is filled in with a hard-coded value (in case of @data). -# -# String fields are copied into the matching ACPI member from lowest address -# upwards, and silently truncated / NUL-padded to length. -# -# @sig: table signature / identifier (4 bytes) -# -# @rev: table revision number (dependent on signature, 1 byte) -# -# @oem_id: OEM identifier (6 bytes) -# -# @oem_table_id: OEM table identifier (8 bytes) -# -# @oem_rev: OEM-supplied revision number (4 bytes) -# -# @asl_compiler_id: identifier of the utility that created the table -# (4 bytes) -# -# @asl_compiler_rev: revision number of the utility that created the -# table (4 bytes) -# -# @file: colon (:) separated list of pathnames to load and -# concatenate as table data. The resultant binary blob is expected to -# have an ACPI table header. At least one file is required. This field -# excludes @data. -# -# @data: colon (:) separated list of pathnames to load and -# concatenate as table data. The resultant binary blob must not have an -# ACPI table header. At least one file is required. This field excludes -# @file. -# -# Since: 1.5 -## -{ 'struct': 'AcpiTableOptions', - 'data': { - '*sig': 'str', - '*rev': 'uint8', - '*oem_id': 'str', - '*oem_table_id': 'str', - '*oem_rev': 'uint32', - '*asl_compiler_id': 'str', - '*asl_compiler_rev': 'uint32', - '*file': 'str', - '*data': 'str' }} - ## # @CommandLineParameterType: # @@ -1295,258 +568,3 @@ 'data': { '*option': 'str' }, 'returns': ['CommandLineOptionInfo'], 'allow-preconfig': true } - -## -# @PCDIMMDeviceInfo: -# -# PCDIMMDevice state information -# -# @id: device's ID -# -# @addr: physical address, where device is mapped -# -# @size: size of memory that the device provides -# -# @slot: slot number at which device is plugged in -# -# @node: NUMA node number where device is plugged in -# -# @memdev: memory backend linked with device -# -# @hotplugged: true if device was hotplugged -# -# @hotpluggable: true if device if could be added/removed while machine is running -# -# Since: 2.1 -## -{ 'struct': 'PCDIMMDeviceInfo', - 'data': { '*id': 'str', - 'addr': 'int', - 'size': 'int', - 'slot': 'int', - 'node': 'int', - 'memdev': 'str', - 'hotplugged': 'bool', - 'hotpluggable': 'bool' - } -} - -## -# @VirtioPMEMDeviceInfo: -# -# VirtioPMEM state information -# -# @id: device's ID -# -# @memaddr: physical address in memory, where device is mapped -# -# @size: size of memory that the device provides -# -# @memdev: memory backend linked with device -# -# Since: 4.1 -## -{ 'struct': 'VirtioPMEMDeviceInfo', - 'data': { '*id': 'str', - 'memaddr': 'size', - 'size': 'size', - 'memdev': 'str' - } -} - -## -# @MemoryDeviceInfo: -# -# Union containing information about a memory device -# -# nvdimm is included since 2.12. virtio-pmem is included since 4.1. -# -# Since: 2.1 -## -{ 'union': 'MemoryDeviceInfo', - 'data': { 'dimm': 'PCDIMMDeviceInfo', - 'nvdimm': 'PCDIMMDeviceInfo', - 'virtio-pmem': 'VirtioPMEMDeviceInfo' - } -} - -## -# @query-memory-devices: -# -# Lists available memory devices and their state -# -# Since: 2.1 -# -# Example: -# -# -> { "execute": "query-memory-devices" } -# <- { "return": [ { "data": -# { "addr": 5368709120, -# "hotpluggable": true, -# "hotplugged": true, -# "id": "d1", -# "memdev": "/objects/memX", -# "node": 0, -# "size": 1073741824, -# "slot": 0}, -# "type": "dimm" -# } ] } -# -## -{ 'command': 'query-memory-devices', 'returns': ['MemoryDeviceInfo'] } - -## -# @MEM_UNPLUG_ERROR: -# -# Emitted when memory hot unplug error occurs. -# -# @device: device name -# -# @msg: Informative message -# -# Since: 2.4 -# -# Example: -# -# <- { "event": "MEM_UNPLUG_ERROR" -# "data": { "device": "dimm1", -# "msg": "acpi: device unplug for unsupported device" -# }, -# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } -# -## -{ 'event': 'MEM_UNPLUG_ERROR', - 'data': { 'device': 'str', 'msg': 'str' } } - -## -# @ACPISlotType: -# -# @DIMM: memory slot -# @CPU: logical CPU slot (since 2.7) -## -{ 'enum': 'ACPISlotType', 'data': [ 'DIMM', 'CPU' ] } - -## -# @ACPIOSTInfo: -# -# OSPM Status Indication for a device -# For description of possible values of @source and @status fields -# see "_OST (OSPM Status Indication)" chapter of ACPI5.0 spec. -# -# @device: device ID associated with slot -# -# @slot: slot ID, unique per slot of a given @slot-type -# -# @slot-type: type of the slot -# -# @source: an integer containing the source event -# -# @status: an integer containing the status code -# -# Since: 2.1 -## -{ 'struct': 'ACPIOSTInfo', - 'data' : { '*device': 'str', - 'slot': 'str', - 'slot-type': 'ACPISlotType', - 'source': 'int', - 'status': 'int' } } - -## -# @query-acpi-ospm-status: -# -# Return a list of ACPIOSTInfo for devices that support status -# reporting via ACPI _OST method. -# -# Since: 2.1 -# -# Example: -# -# -> { "execute": "query-acpi-ospm-status" } -# <- { "return": [ { "device": "d1", "slot": "0", "slot-type": "DIMM", "source": 1, "status": 0}, -# { "slot": "1", "slot-type": "DIMM", "source": 0, "status": 0}, -# { "slot": "2", "slot-type": "DIMM", "source": 0, "status": 0}, -# { "slot": "3", "slot-type": "DIMM", "source": 0, "status": 0} -# ]} -# -## -{ 'command': 'query-acpi-ospm-status', 'returns': ['ACPIOSTInfo'] } - -## -# @ACPI_DEVICE_OST: -# -# Emitted when guest executes ACPI _OST method. -# -# @info: OSPM Status Indication -# -# Since: 2.1 -# -# Example: -# -# <- { "event": "ACPI_DEVICE_OST", -# "data": { "device": "d1", "slot": "0", -# "slot-type": "DIMM", "source": 1, "status": 0 } } -# -## -{ 'event': 'ACPI_DEVICE_OST', - 'data': { 'info': 'ACPIOSTInfo' } } - -## -# @ReplayMode: -# -# Mode of the replay subsystem. -# -# @none: normal execution mode. Replay or record are not enabled. -# -# @record: record mode. All non-deterministic data is written into the -# replay log. -# -# @play: replay mode. Non-deterministic data required for system execution -# is read from the log. -# -# Since: 2.5 -## -{ 'enum': 'ReplayMode', - 'data': [ 'none', 'record', 'play' ] } - -## -# @xen-load-devices-state: -# -# Load the state of all devices from file. The RAM and the block devices -# of the VM are not loaded by this command. -# -# @filename: the file to load the state of the devices from as binary -# data. See xen-save-devices-state.txt for a description of the binary -# format. -# -# Since: 2.7 -# -# Example: -# -# -> { "execute": "xen-load-devices-state", -# "arguments": { "filename": "/tmp/resume" } } -# <- { "return": {} } -# -## -{ 'command': 'xen-load-devices-state', 'data': {'filename': 'str'} } - -## -# @GuidInfo: -# -# GUID information. -# -# @guid: the globally unique identifier -# -# Since: 2.9 -## -{ 'struct': 'GuidInfo', 'data': {'guid': 'str'} } - -## -# @query-vm-generation-id: -# -# Show Virtual Machine Generation ID -# -# Since: 2.9 -## -{ 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' } - diff --git a/qapi/net.json b/qapi/net.json index cebb1b52e3b1824326ecc0d3cd70a3afa0d632c8..a3a13360018d477d736e6bc05377f7bf92ff6ad3 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # ## @@ -428,16 +429,39 @@ '*vhostforce': 'bool', '*queues': 'int' } } +## +# @NetdevVhostVDPAOptions: +# +# Vhost-vdpa network backend +# +# vDPA device is a device that uses a datapath which complies with the virtio +# specifications with a vendor specific control path. +# +# @vhostdev: path of vhost-vdpa device +# (default:'/dev/vhost-vdpa-0') +# +# @queues: number of queues to be created for multiqueue vhost-vdpa +# (default: 1) +# +# Since: 5.1 +## +{ 'struct': 'NetdevVhostVDPAOptions', + 'data': { + '*vhostdev': 'str', + '*queues': 'int' } } + ## # @NetClientDriver: # # Available netdev drivers. # # Since: 2.7 +# +# @vhost-vdpa since 5.1 ## { 'enum': 'NetClientDriver', 'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde', - 'bridge', 'hubport', 'netmap', 'vhost-user' ] } + 'bridge', 'hubport', 'netmap', 'vhost-user', 'vhost-vdpa' ] } ## # @Netdev: @@ -465,56 +489,8 @@ 'bridge': 'NetdevBridgeOptions', 'hubport': 'NetdevHubPortOptions', 'netmap': 'NetdevNetmapOptions', - 'vhost-user': 'NetdevVhostUserOptions' } } - -## -# @NetLegacy: -# -# Captures the configuration of a network device; legacy. -# -# @id: identifier for monitor commands -# -# @name: identifier for monitor commands, ignored if @id is present -# -# @opts: device type specific properties (legacy) -# -# Since: 1.2 -## -{ 'struct': 'NetLegacy', - 'data': { - '*id': 'str', - '*name': 'str', - 'opts': 'NetLegacyOptions' } } - -## -# @NetLegacyOptionsType: -# -# Since: 1.2 -## -{ 'enum': 'NetLegacyOptionsType', - 'data': ['none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde', - 'bridge', 'netmap', 'vhost-user'] } - -## -# @NetLegacyOptions: -# -# Like Netdev, but for use only by the legacy command line options -# -# Since: 1.2 -## -{ 'union': 'NetLegacyOptions', - 'base': { 'type': 'NetLegacyOptionsType' }, - 'discriminator': 'type', - 'data': { - 'nic': 'NetLegacyNicOptions', - 'user': 'NetdevUserOptions', - 'tap': 'NetdevTapOptions', - 'l2tpv3': 'NetdevL2TPv3Options', - 'socket': 'NetdevSocketOptions', - 'vde': 'NetdevVdeOptions', - 'bridge': 'NetdevBridgeOptions', - 'netmap': 'NetdevNetmapOptions', - 'vhost-user': 'NetdevVhostUserOptions' } } + 'vhost-user': 'NetdevVhostUserOptions', + 'vhost-vdpa': 'NetdevVhostVDPAOptions' } } ## # @NetFilterDirection: diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index 5fe0276c1cc8f6cc079424a0d09f57fb0bf244cc..587f31baf6b8bd3f53c69a4d1f61979b073eb39d 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -133,7 +133,7 @@ opts_visitor_insert(GHashTable *unprocessed_opts, const QemuOpt *opt) } -static void +static bool opts_start_struct(Visitor *v, const char *name, void **obj, size_t size, Error **errp) { @@ -144,7 +144,7 @@ opts_start_struct(Visitor *v, const char *name, void **obj, *obj = g_malloc0(size); } if (ov->depth++ > 0) { - return; + return true; } ov->unprocessed_opts = g_hash_table_new_full(&g_str_hash, &g_str_equal, @@ -163,10 +163,11 @@ opts_start_struct(Visitor *v, const char *name, void **obj, ov->fake_id_opt->str = g_strdup(ov->opts_root->id); opts_visitor_insert(ov->unprocessed_opts, ov->fake_id_opt); } + return true; } -static void +static bool opts_check_struct(Visitor *v, Error **errp) { OptsVisitor *ov = to_ov(v); @@ -174,7 +175,7 @@ opts_check_struct(Visitor *v, Error **errp) GQueue *any; if (ov->depth > 1) { - return; + return true; } /* we should have processed all (distinct) QemuOpt instances */ @@ -184,7 +185,9 @@ opts_check_struct(Visitor *v, Error **errp) first = g_queue_peek_head(any); error_setg(errp, QERR_INVALID_PARAMETER, first->name); + return false; } + return true; } @@ -221,7 +224,7 @@ lookup_distinct(const OptsVisitor *ov, const char *name, Error **errp) } -static void +static bool opts_start_list(Visitor *v, const char *name, GenericList **list, size_t size, Error **errp) { @@ -232,12 +235,13 @@ opts_start_list(Visitor *v, const char *name, GenericList **list, size_t size, /* we don't support visits without a list */ assert(list); ov->repeated_opts = lookup_distinct(ov, name, errp); - if (ov->repeated_opts) { - ov->list_mode = LM_IN_PROGRESS; - *list = g_malloc0(size); - } else { + if (!ov->repeated_opts) { *list = NULL; + return false; } + ov->list_mode = LM_IN_PROGRESS; + *list = g_malloc0(size); + return true; } @@ -285,13 +289,14 @@ opts_next_list(Visitor *v, GenericList *tail, size_t size) } -static void +static bool opts_check_list(Visitor *v, Error **errp) { /* * Unvisited list elements will be reported later when checking * whether unvisited struct members remain. */ + return true; } @@ -341,7 +346,7 @@ processed(OptsVisitor *ov, const char *name) } -static void +static bool opts_type_str(Visitor *v, const char *name, char **obj, Error **errp) { OptsVisitor *ov = to_ov(v); @@ -350,7 +355,7 @@ opts_type_str(Visitor *v, const char *name, char **obj, Error **errp) opt = lookup_scalar(ov, name, errp); if (!opt) { *obj = NULL; - return; + return false; } *obj = g_strdup(opt->str ? opt->str : ""); /* Note that we consume a string even if this is called as part of @@ -359,11 +364,11 @@ opts_type_str(Visitor *v, const char *name, char **obj, Error **errp) * consumed only matters to visit_end_struct() as the final error * check if there were no other failures during the visit. */ processed(ov, name); + return true; } -/* mimics qemu-option.c::parse_option_bool() */ -static void +static bool opts_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) { OptsVisitor *ov = to_ov(v); @@ -371,32 +376,22 @@ opts_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) opt = lookup_scalar(ov, name, errp); if (!opt) { - return; + return false; } - if (opt->str) { - if (strcmp(opt->str, "on") == 0 || - strcmp(opt->str, "yes") == 0 || - strcmp(opt->str, "y") == 0) { - *obj = true; - } else if (strcmp(opt->str, "off") == 0 || - strcmp(opt->str, "no") == 0 || - strcmp(opt->str, "n") == 0) { - *obj = false; - } else { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name, - "on|yes|y|off|no|n"); - return; + if (!qapi_bool_parse(opt->name, opt->str, obj, errp)) { + return false; } } else { *obj = true; } processed(ov, name); + return true; } -static void +static bool opts_type_int64(Visitor *v, const char *name, int64_t *obj, Error **errp) { OptsVisitor *ov = to_ov(v); @@ -407,12 +402,12 @@ opts_type_int64(Visitor *v, const char *name, int64_t *obj, Error **errp) if (ov->list_mode == LM_SIGNED_INTERVAL) { *obj = ov->range_next.s; - return; + return true; } opt = lookup_scalar(ov, name, errp); if (!opt) { - return; + return false; } str = opt->str ? opt->str : ""; @@ -425,7 +420,7 @@ opts_type_int64(Visitor *v, const char *name, int64_t *obj, Error **errp) if (*endptr == '\0') { *obj = val; processed(ov, name); - return; + return true; } if (*endptr == '-' && ov->list_mode == LM_IN_PROGRESS) { long long val2; @@ -442,17 +437,18 @@ opts_type_int64(Visitor *v, const char *name, int64_t *obj, Error **errp) /* as if entering on the top */ *obj = ov->range_next.s; - return; + return true; } } } error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name, (ov->list_mode == LM_NONE) ? "an int64 value" : "an int64 value or range"); + return false; } -static void +static bool opts_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp) { OptsVisitor *ov = to_ov(v); @@ -463,12 +459,12 @@ opts_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp) if (ov->list_mode == LM_UNSIGNED_INTERVAL) { *obj = ov->range_next.u; - return; + return true; } opt = lookup_scalar(ov, name, errp); if (!opt) { - return; + return false; } str = opt->str; @@ -479,7 +475,7 @@ opts_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp) if (*endptr == '\0') { *obj = val; processed(ov, name); - return; + return true; } if (*endptr == '-' && ov->list_mode == LM_IN_PROGRESS) { unsigned long long val2; @@ -494,17 +490,18 @@ opts_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp) /* as if entering on the top */ *obj = ov->range_next.u; - return; + return true; } } } error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name, (ov->list_mode == LM_NONE) ? "a uint64 value" : "a uint64 value or range"); + return false; } -static void +static bool opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp) { OptsVisitor *ov = to_ov(v); @@ -513,17 +510,18 @@ opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp) opt = lookup_scalar(ov, name, errp); if (!opt) { - return; + return false; } err = qemu_strtosz(opt->str ? opt->str : "", NULL, obj); if (err < 0) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name, "a size value"); - return; + return false; } processed(ov, name); + return true; } diff --git a/qapi/pci.json b/qapi/pci.json new file mode 100644 index 0000000000000000000000000000000000000000..b79cbd787bee6fe5a649d9d0227ff204c0cc8a61 --- /dev/null +++ b/qapi/pci.json @@ -0,0 +1,316 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. +# SPDX-License-Identifier: GPL-2.0-or-later + +## +# = PCI +## + +## +# @PciMemoryRange: +# +# A PCI device memory region +# +# @base: the starting address (guest physical) +# +# @limit: the ending address (guest physical) +# +# Since: 0.14.0 +## +{ 'struct': 'PciMemoryRange', 'data': {'base': 'int', 'limit': 'int'} } + +## +# @PciMemoryRegion: +# +# Information about a PCI device I/O region. +# +# @bar: the index of the Base Address Register for this region +# +# @type: - 'io' if the region is a PIO region +# - 'memory' if the region is a MMIO region +# +# @size: memory size +# +# @prefetch: if @type is 'memory', true if the memory is prefetchable +# +# @mem_type_64: if @type is 'memory', true if the BAR is 64-bit +# +# Since: 0.14.0 +## +{ 'struct': 'PciMemoryRegion', + 'data': {'bar': 'int', 'type': 'str', 'address': 'int', 'size': 'int', + '*prefetch': 'bool', '*mem_type_64': 'bool' } } + +## +# @PciBusInfo: +# +# Information about a bus of a PCI Bridge device +# +# @number: primary bus interface number. This should be the number of the +# bus the device resides on. +# +# @secondary: secondary bus interface number. This is the number of the +# main bus for the bridge +# +# @subordinate: This is the highest number bus that resides below the +# bridge. +# +# @io_range: The PIO range for all devices on this bridge +# +# @memory_range: The MMIO range for all devices on this bridge +# +# @prefetchable_range: The range of prefetchable MMIO for all devices on +# this bridge +# +# Since: 2.4 +## +{ 'struct': 'PciBusInfo', + 'data': {'number': 'int', 'secondary': 'int', 'subordinate': 'int', + 'io_range': 'PciMemoryRange', + 'memory_range': 'PciMemoryRange', + 'prefetchable_range': 'PciMemoryRange' } } + +## +# @PciBridgeInfo: +# +# Information about a PCI Bridge device +# +# @bus: information about the bus the device resides on +# +# @devices: a list of @PciDeviceInfo for each device on this bridge +# +# Since: 0.14.0 +## +{ 'struct': 'PciBridgeInfo', + 'data': {'bus': 'PciBusInfo', '*devices': ['PciDeviceInfo']} } + +## +# @PciDeviceClass: +# +# Information about the Class of a PCI device +# +# @desc: a string description of the device's class +# +# @class: the class code of the device +# +# Since: 2.4 +## +{ 'struct': 'PciDeviceClass', + 'data': {'*desc': 'str', 'class': 'int'} } + +## +# @PciDeviceId: +# +# Information about the Id of a PCI device +# +# @device: the PCI device id +# +# @vendor: the PCI vendor id +# +# @subsystem: the PCI subsystem id (since 3.1) +# +# @subsystem-vendor: the PCI subsystem vendor id (since 3.1) +# +# Since: 2.4 +## +{ 'struct': 'PciDeviceId', + 'data': {'device': 'int', 'vendor': 'int', '*subsystem': 'int', + '*subsystem-vendor': 'int'} } + +## +# @PciDeviceInfo: +# +# Information about a PCI device +# +# @bus: the bus number of the device +# +# @slot: the slot the device is located in +# +# @function: the function of the slot used by the device +# +# @class_info: the class of the device +# +# @id: the PCI device id +# +# @irq: if an IRQ is assigned to the device, the IRQ number +# +# @irq_pin: the IRQ pin, zero means no IRQ (since 5.1) +# +# @qdev_id: the device name of the PCI device +# +# @pci_bridge: if the device is a PCI bridge, the bridge information +# +# @regions: a list of the PCI I/O regions associated with the device +# +# Notes: the contents of @class_info.desc are not stable and should only be +# treated as informational. +# +# Since: 0.14.0 +## +{ 'struct': 'PciDeviceInfo', + 'data': {'bus': 'int', 'slot': 'int', 'function': 'int', + 'class_info': 'PciDeviceClass', 'id': 'PciDeviceId', + '*irq': 'int', 'irq_pin': 'int', 'qdev_id': 'str', + '*pci_bridge': 'PciBridgeInfo', 'regions': ['PciMemoryRegion'] }} + +## +# @PciInfo: +# +# Information about a PCI bus +# +# @bus: the bus index +# +# @devices: a list of devices on this bus +# +# Since: 0.14.0 +## +{ 'struct': 'PciInfo', 'data': {'bus': 'int', 'devices': ['PciDeviceInfo']} } + +## +# @query-pci: +# +# Return information about the PCI bus topology of the guest. +# +# Returns: a list of @PciInfo for each PCI bus. Each bus is +# represented by a json-object, which has a key with a json-array of +# all PCI devices attached to it. Each device is represented by a +# json-object. +# +# Since: 0.14.0 +# +# Example: +# +# -> { "execute": "query-pci" } +# <- { "return": [ +# { +# "bus": 0, +# "devices": [ +# { +# "bus": 0, +# "qdev_id": "", +# "slot": 0, +# "class_info": { +# "class": 1536, +# "desc": "Host bridge" +# }, +# "id": { +# "device": 32902, +# "vendor": 4663 +# }, +# "function": 0, +# "regions": [ +# ] +# }, +# { +# "bus": 0, +# "qdev_id": "", +# "slot": 1, +# "class_info": { +# "class": 1537, +# "desc": "ISA bridge" +# }, +# "id": { +# "device": 32902, +# "vendor": 28672 +# }, +# "function": 0, +# "regions": [ +# ] +# }, +# { +# "bus": 0, +# "qdev_id": "", +# "slot": 1, +# "class_info": { +# "class": 257, +# "desc": "IDE controller" +# }, +# "id": { +# "device": 32902, +# "vendor": 28688 +# }, +# "function": 1, +# "regions": [ +# { +# "bar": 4, +# "size": 16, +# "address": 49152, +# "type": "io" +# } +# ] +# }, +# { +# "bus": 0, +# "qdev_id": "", +# "slot": 2, +# "class_info": { +# "class": 768, +# "desc": "VGA controller" +# }, +# "id": { +# "device": 4115, +# "vendor": 184 +# }, +# "function": 0, +# "regions": [ +# { +# "prefetch": true, +# "mem_type_64": false, +# "bar": 0, +# "size": 33554432, +# "address": 4026531840, +# "type": "memory" +# }, +# { +# "prefetch": false, +# "mem_type_64": false, +# "bar": 1, +# "size": 4096, +# "address": 4060086272, +# "type": "memory" +# }, +# { +# "prefetch": false, +# "mem_type_64": false, +# "bar": 6, +# "size": 65536, +# "address": -1, +# "type": "memory" +# } +# ] +# }, +# { +# "bus": 0, +# "qdev_id": "", +# "irq": 11, +# "slot": 4, +# "class_info": { +# "class": 1280, +# "desc": "RAM controller" +# }, +# "id": { +# "device": 6900, +# "vendor": 4098 +# }, +# "function": 0, +# "regions": [ +# { +# "bar": 0, +# "size": 32, +# "address": 49280, +# "type": "io" +# } +# ] +# } +# ] +# } +# ] +# } +# +# Note: This example has been shortened as the real response is too long. +# +## +{ 'command': 'query-pci', 'returns': ['PciInfo'] } diff --git a/qapi/qapi-clone-visitor.c b/qapi/qapi-clone-visitor.c index daab6819b486fa2e37ad55dcd85e390f9b9d4075..c45c5caa3b89aa7fc0c93ecb2ab8d70251dd7e06 100644 --- a/qapi/qapi-clone-visitor.c +++ b/qapi/qapi-clone-visitor.c @@ -24,7 +24,7 @@ static QapiCloneVisitor *to_qcv(Visitor *v) return container_of(v, QapiCloneVisitor, visitor); } -static void qapi_clone_start_struct(Visitor *v, const char *name, void **obj, +static bool qapi_clone_start_struct(Visitor *v, const char *name, void **obj, size_t size, Error **errp) { QapiCloneVisitor *qcv = to_qcv(v); @@ -34,11 +34,12 @@ static void qapi_clone_start_struct(Visitor *v, const char *name, void **obj, /* Only possible when visiting an alternate's object * branch. Nothing further to do here, since the earlier * visit_start_alternate() already copied memory. */ - return; + return true; } *obj = g_memdup(*obj, size); qcv->depth++; + return true; } static void qapi_clone_end(Visitor *v, void **obj) @@ -51,11 +52,11 @@ static void qapi_clone_end(Visitor *v, void **obj) } } -static void qapi_clone_start_list(Visitor *v, const char *name, +static bool qapi_clone_start_list(Visitor *v, const char *name, GenericList **listp, size_t size, Error **errp) { - qapi_clone_start_struct(v, name, (void **)listp, size, errp); + return qapi_clone_start_struct(v, name, (void **)listp, size, errp); } static GenericList *qapi_clone_next_list(Visitor *v, GenericList *tail, @@ -69,42 +70,45 @@ static GenericList *qapi_clone_next_list(Visitor *v, GenericList *tail, return tail->next; } -static void qapi_clone_start_alternate(Visitor *v, const char *name, +static bool qapi_clone_start_alternate(Visitor *v, const char *name, GenericAlternate **obj, size_t size, Error **errp) { - qapi_clone_start_struct(v, name, (void **)obj, size, errp); + return qapi_clone_start_struct(v, name, (void **)obj, size, errp); } -static void qapi_clone_type_int64(Visitor *v, const char *name, int64_t *obj, - Error **errp) +static bool qapi_clone_type_int64(Visitor *v, const char *name, int64_t *obj, + Error **errp) { QapiCloneVisitor *qcv = to_qcv(v); assert(qcv->depth); /* Value was already cloned by g_memdup() */ + return true; } -static void qapi_clone_type_uint64(Visitor *v, const char *name, - uint64_t *obj, Error **errp) +static bool qapi_clone_type_uint64(Visitor *v, const char *name, + uint64_t *obj, Error **errp) { QapiCloneVisitor *qcv = to_qcv(v); assert(qcv->depth); /* Value was already cloned by g_memdup() */ + return true; } -static void qapi_clone_type_bool(Visitor *v, const char *name, bool *obj, - Error **errp) +static bool qapi_clone_type_bool(Visitor *v, const char *name, bool *obj, + Error **errp) { QapiCloneVisitor *qcv = to_qcv(v); assert(qcv->depth); /* Value was already cloned by g_memdup() */ + return true; } -static void qapi_clone_type_str(Visitor *v, const char *name, char **obj, - Error **errp) +static bool qapi_clone_type_str(Visitor *v, const char *name, char **obj, + Error **errp) { QapiCloneVisitor *qcv = to_qcv(v); @@ -117,24 +121,27 @@ static void qapi_clone_type_str(Visitor *v, const char *name, char **obj, * string is intended. */ *obj = g_strdup(*obj ?: ""); + return true; } -static void qapi_clone_type_number(Visitor *v, const char *name, double *obj, - Error **errp) +static bool qapi_clone_type_number(Visitor *v, const char *name, double *obj, + Error **errp) { QapiCloneVisitor *qcv = to_qcv(v); assert(qcv->depth); /* Value was already cloned by g_memdup() */ + return true; } -static void qapi_clone_type_null(Visitor *v, const char *name, QNull **obj, +static bool qapi_clone_type_null(Visitor *v, const char *name, QNull **obj, Error **errp) { QapiCloneVisitor *qcv = to_qcv(v); assert(qcv->depth); *obj = qnull(); + return true; } static void qapi_clone_free(Visitor *v) @@ -167,7 +174,7 @@ static Visitor *qapi_clone_visitor_new(void) return &v->visitor; } -void *qapi_clone(const void *src, void (*visit_type)(Visitor *, const char *, +void *qapi_clone(const void *src, bool (*visit_type)(Visitor *, const char *, void **, Error **)) { Visitor *v; @@ -184,7 +191,7 @@ void *qapi_clone(const void *src, void (*visit_type)(Visitor *, const char *, } void qapi_clone_members(void *dst, const void *src, size_t sz, - void (*visit_type_members)(Visitor *, void *, + bool (*visit_type_members)(Visitor *, void *, Error **)) { Visitor *v; diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c index 2239fc6417bd86065c34768cd02fab4d58e0a695..ef283f296601a20365e9fb80baa005c83a6e0933 100644 --- a/qapi/qapi-dealloc-visitor.c +++ b/qapi/qapi-dealloc-visitor.c @@ -22,9 +22,10 @@ struct QapiDeallocVisitor Visitor visitor; }; -static void qapi_dealloc_start_struct(Visitor *v, const char *name, void **obj, +static bool qapi_dealloc_start_struct(Visitor *v, const char *name, void **obj, size_t unused, Error **errp) { + return true; } static void qapi_dealloc_end_struct(Visitor *v, void **obj) @@ -41,10 +42,11 @@ static void qapi_dealloc_end_alternate(Visitor *v, void **obj) } } -static void qapi_dealloc_start_list(Visitor *v, const char *name, +static bool qapi_dealloc_start_list(Visitor *v, const char *name, GenericList **list, size_t size, Error **errp) { + return true; } static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList *tail, @@ -59,48 +61,55 @@ static void qapi_dealloc_end_list(Visitor *v, void **obj) { } -static void qapi_dealloc_type_str(Visitor *v, const char *name, char **obj, +static bool qapi_dealloc_type_str(Visitor *v, const char *name, char **obj, Error **errp) { if (obj) { g_free(*obj); } + return true; } -static void qapi_dealloc_type_int64(Visitor *v, const char *name, int64_t *obj, +static bool qapi_dealloc_type_int64(Visitor *v, const char *name, int64_t *obj, Error **errp) { + return true; } -static void qapi_dealloc_type_uint64(Visitor *v, const char *name, +static bool qapi_dealloc_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp) { + return true; } -static void qapi_dealloc_type_bool(Visitor *v, const char *name, bool *obj, +static bool qapi_dealloc_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) { + return true; } -static void qapi_dealloc_type_number(Visitor *v, const char *name, double *obj, +static bool qapi_dealloc_type_number(Visitor *v, const char *name, double *obj, Error **errp) { + return true; } -static void qapi_dealloc_type_anything(Visitor *v, const char *name, +static bool qapi_dealloc_type_anything(Visitor *v, const char *name, QObject **obj, Error **errp) { if (obj) { qobject_unref(*obj); } + return true; } -static void qapi_dealloc_type_null(Visitor *v, const char *name, +static bool qapi_dealloc_type_null(Visitor *v, const char *name, QNull **obj, Error **errp) { if (obj) { qobject_unref(*obj); } + return true; } static void qapi_dealloc_free(Visitor *v) diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json index 43b0ba0dea22fe626f105cd2b7808ad6d5d2229c..0b444b76d2d14c2b298a31bff00f5d0b50405fd6 100644 --- a/qapi/qapi-schema.json +++ b/qapi/qapi-schema.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python ## # = Introduction # @@ -20,8 +21,10 @@ # # Example: # -# | -> data issued by the Client -# | <- Server data response +# :: +# +# -> data issued by the Client +# <- Server data response # # Please, refer to the QMP specification (docs/interop/qmp-spec.txt) for # detailed information on the Server command and response formats. @@ -63,6 +66,7 @@ { 'include': 'run-state.json' } { 'include': 'crypto.json' } { 'include': 'block.json' } +{ 'include': 'block-export.json' } { 'include': 'char.json' } { 'include': 'dump.json' } { 'include': 'job.json' } @@ -81,6 +85,9 @@ { 'include': 'qdev.json' } { 'include': 'machine.json' } { 'include': 'machine-target.json' } +{ 'include': 'replay.json' } { 'include': 'misc.json' } { 'include': 'misc-target.json' } { 'include': 'audio.json' } +{ 'include': 'acpi.json' } +{ 'include': 'pci.json' } diff --git a/qapi/qapi-util.c b/qapi/qapi-util.c index 29a6c98b53882ee8df978feec1d608ecef1a9fa9..3c24bb3d4548c2f1740078dea3bf5b7cb3f5cf16 100644 --- a/qapi/qapi-util.c +++ b/qapi/qapi-util.c @@ -13,6 +13,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/ctype.h" +#include "qapi/qmp/qerror.h" const char *qapi_enum_lookup(const QEnumLookup *lookup, int val) { @@ -40,6 +41,28 @@ int qapi_enum_parse(const QEnumLookup *lookup, const char *buf, return def; } +bool qapi_bool_parse(const char *name, const char *value, bool *obj, Error **errp) +{ + if (g_str_equal(value, "on") || + g_str_equal(value, "yes") || + g_str_equal(value, "true") || + g_str_equal(value, "y")) { + *obj = true; + return true; + } + if (g_str_equal(value, "off") || + g_str_equal(value, "no") || + g_str_equal(value, "false") || + g_str_equal(value, "n")) { + *obj = false; + return true; + } + + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, + "'on' or 'off'"); + return false; +} + /* * Parse a valid QAPI name from @str. * A valid name consists of letters, digits, hyphen and underscore. diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c index 74aa9c04bd3daa359270ea68e56d77a996444995..7e5f40e7f01a4c95e3706c082b3b7a88d428ec54 100644 --- a/qapi/qapi-visit-core.c +++ b/qapi/qapi-visit-core.c @@ -36,29 +36,27 @@ void visit_free(Visitor *v) } } -void visit_start_struct(Visitor *v, const char *name, void **obj, +bool visit_start_struct(Visitor *v, const char *name, void **obj, size_t size, Error **errp) { - Error *err = NULL; + bool ok; trace_visit_start_struct(v, name, obj, size); if (obj) { assert(size); assert(!(v->type & VISITOR_OUTPUT) || *obj); } - v->start_struct(v, name, obj, size, &err); + ok = v->start_struct(v, name, obj, size, errp); if (obj && (v->type & VISITOR_INPUT)) { - assert(!err != !*obj); + assert(ok != !*obj); } - error_propagate(errp, err); + return ok; } -void visit_check_struct(Visitor *v, Error **errp) +bool visit_check_struct(Visitor *v, Error **errp) { trace_visit_check_struct(v); - if (v->check_struct) { - v->check_struct(v, errp); - } + return v->check_struct ? v->check_struct(v, errp) : true; } void visit_end_struct(Visitor *v, void **obj) @@ -67,18 +65,18 @@ void visit_end_struct(Visitor *v, void **obj) v->end_struct(v, obj); } -void visit_start_list(Visitor *v, const char *name, GenericList **list, +bool visit_start_list(Visitor *v, const char *name, GenericList **list, size_t size, Error **errp) { - Error *err = NULL; + bool ok; assert(!list || size >= sizeof(GenericList)); trace_visit_start_list(v, name, list, size); - v->start_list(v, name, list, size, &err); + ok = v->start_list(v, name, list, size, errp); if (list && (v->type & VISITOR_INPUT)) { - assert(!(err && *list)); + assert(ok || !*list); } - error_propagate(errp, err); + return ok; } GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size) @@ -88,12 +86,10 @@ GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size) return v->next_list(v, tail, size); } -void visit_check_list(Visitor *v, Error **errp) +bool visit_check_list(Visitor *v, Error **errp) { trace_visit_check_list(v); - if (v->check_list) { - v->check_list(v, errp); - } + return v->check_list ? v->check_list(v, errp) : true; } void visit_end_list(Visitor *v, void **obj) @@ -102,22 +98,24 @@ void visit_end_list(Visitor *v, void **obj) v->end_list(v, obj); } -void visit_start_alternate(Visitor *v, const char *name, +bool visit_start_alternate(Visitor *v, const char *name, GenericAlternate **obj, size_t size, Error **errp) { - Error *err = NULL; + bool ok; assert(obj && size >= sizeof(GenericAlternate)); assert(!(v->type & VISITOR_OUTPUT) || *obj); trace_visit_start_alternate(v, name, obj, size); - if (v->start_alternate) { - v->start_alternate(v, name, obj, size, &err); + if (!v->start_alternate) { + assert(!(v->type & VISITOR_INPUT)); + return true; } + ok = v->start_alternate(v, name, obj, size, errp); if (v->type & VISITOR_INPUT) { - assert(v->start_alternate && !err != !*obj); + assert(ok != !*obj); } - error_propagate(errp, err); + return ok; } void visit_end_alternate(Visitor *v, void **obj) @@ -147,157 +145,170 @@ bool visit_is_dealloc(Visitor *v) return v->type == VISITOR_DEALLOC; } -void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp) +bool visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp) { assert(obj); trace_visit_type_int(v, name, obj); - v->type_int64(v, name, obj, errp); + return v->type_int64(v, name, obj, errp); } -static void visit_type_uintN(Visitor *v, uint64_t *obj, const char *name, +static bool visit_type_uintN(Visitor *v, uint64_t *obj, const char *name, uint64_t max, const char *type, Error **errp) { - Error *err = NULL; uint64_t value = *obj; assert(v->type == VISITOR_INPUT || value <= max); - v->type_uint64(v, name, &value, &err); - if (err) { - error_propagate(errp, err); - } else if (value > max) { + if (!v->type_uint64(v, name, &value, errp)) { + return false; + } + if (value > max) { assert(v->type == VISITOR_INPUT); error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null", type); - } else { - *obj = value; + return false; } + *obj = value; + return true; } -void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj, +bool visit_type_uint8(Visitor *v, const char *name, uint8_t *obj, Error **errp) { uint64_t value; + bool ok; trace_visit_type_uint8(v, name, obj); value = *obj; - visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp); + ok = visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp); *obj = value; + return ok; } -void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj, +bool visit_type_uint16(Visitor *v, const char *name, uint16_t *obj, Error **errp) { uint64_t value; + bool ok; trace_visit_type_uint16(v, name, obj); value = *obj; - visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp); + ok = visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp); *obj = value; + return ok; } -void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj, +bool visit_type_uint32(Visitor *v, const char *name, uint32_t *obj, Error **errp) { uint64_t value; + bool ok; trace_visit_type_uint32(v, name, obj); value = *obj; - visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp); + ok = visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp); *obj = value; + return ok; } -void visit_type_uint64(Visitor *v, const char *name, uint64_t *obj, +bool visit_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp) { assert(obj); trace_visit_type_uint64(v, name, obj); - v->type_uint64(v, name, obj, errp); + return v->type_uint64(v, name, obj, errp); } -static void visit_type_intN(Visitor *v, int64_t *obj, const char *name, +static bool visit_type_intN(Visitor *v, int64_t *obj, const char *name, int64_t min, int64_t max, const char *type, Error **errp) { - Error *err = NULL; int64_t value = *obj; assert(v->type == VISITOR_INPUT || (value >= min && value <= max)); - v->type_int64(v, name, &value, &err); - if (err) { - error_propagate(errp, err); - } else if (value < min || value > max) { + if (!v->type_int64(v, name, &value, errp)) { + return false; + } + if (value < min || value > max) { assert(v->type == VISITOR_INPUT); error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null", type); - } else { - *obj = value; + return false; } + *obj = value; + return true; } -void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp) +bool visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp) { int64_t value; + bool ok; trace_visit_type_int8(v, name, obj); value = *obj; - visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp); + ok = visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp); *obj = value; + return ok; } -void visit_type_int16(Visitor *v, const char *name, int16_t *obj, +bool visit_type_int16(Visitor *v, const char *name, int16_t *obj, Error **errp) { int64_t value; + bool ok; trace_visit_type_int16(v, name, obj); value = *obj; - visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t", errp); + ok = visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t", + errp); *obj = value; + return ok; } -void visit_type_int32(Visitor *v, const char *name, int32_t *obj, +bool visit_type_int32(Visitor *v, const char *name, int32_t *obj, Error **errp) { int64_t value; + bool ok; trace_visit_type_int32(v, name, obj); value = *obj; - visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t", errp); + ok = visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t", + errp); *obj = value; + return ok; } -void visit_type_int64(Visitor *v, const char *name, int64_t *obj, +bool visit_type_int64(Visitor *v, const char *name, int64_t *obj, Error **errp) { assert(obj); trace_visit_type_int64(v, name, obj); - v->type_int64(v, name, obj, errp); + return v->type_int64(v, name, obj, errp); } -void visit_type_size(Visitor *v, const char *name, uint64_t *obj, +bool visit_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp) { assert(obj); trace_visit_type_size(v, name, obj); if (v->type_size) { - v->type_size(v, name, obj, errp); - } else { - v->type_uint64(v, name, obj, errp); + return v->type_size(v, name, obj, errp); } + return v->type_uint64(v, name, obj, errp); } -void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) +bool visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) { assert(obj); trace_visit_type_bool(v, name, obj); - v->type_bool(v, name, obj, errp); + return v->type_bool(v, name, obj, errp); } -void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp) +bool visit_type_str(Visitor *v, const char *name, char **obj, Error **errp) { - Error *err = NULL; + bool ok; assert(obj); /* TODO: Fix callers to not pass NULL when they mean "", so that we @@ -305,94 +316,92 @@ void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp) assert(!(v->type & VISITOR_OUTPUT) || *obj); */ trace_visit_type_str(v, name, obj); - v->type_str(v, name, obj, &err); + ok = v->type_str(v, name, obj, errp); if (v->type & VISITOR_INPUT) { - assert(!err != !*obj); + assert(ok != !*obj); } - error_propagate(errp, err); + return ok; } -void visit_type_number(Visitor *v, const char *name, double *obj, +bool visit_type_number(Visitor *v, const char *name, double *obj, Error **errp) { assert(obj); trace_visit_type_number(v, name, obj); - v->type_number(v, name, obj, errp); + return v->type_number(v, name, obj, errp); } -void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp) +bool visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp) { - Error *err = NULL; + bool ok; assert(obj); assert(v->type != VISITOR_OUTPUT || *obj); trace_visit_type_any(v, name, obj); - v->type_any(v, name, obj, &err); + ok = v->type_any(v, name, obj, errp); if (v->type == VISITOR_INPUT) { - assert(!err != !*obj); + assert(ok != !*obj); } - error_propagate(errp, err); + return ok; } -void visit_type_null(Visitor *v, const char *name, QNull **obj, +bool visit_type_null(Visitor *v, const char *name, QNull **obj, Error **errp) { trace_visit_type_null(v, name, obj); - v->type_null(v, name, obj, errp); + return v->type_null(v, name, obj, errp); } -static void output_type_enum(Visitor *v, const char *name, int *obj, +static bool output_type_enum(Visitor *v, const char *name, int *obj, const QEnumLookup *lookup, Error **errp) { int value = *obj; char *enum_str; enum_str = (char *)qapi_enum_lookup(lookup, value); - visit_type_str(v, name, &enum_str, errp); + return visit_type_str(v, name, &enum_str, errp); } -static void input_type_enum(Visitor *v, const char *name, int *obj, +static bool input_type_enum(Visitor *v, const char *name, int *obj, const QEnumLookup *lookup, Error **errp) { - Error *local_err = NULL; int64_t value; char *enum_str; - visit_type_str(v, name, &enum_str, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; + if (!visit_type_str(v, name, &enum_str, errp)) { + return false; } value = qapi_enum_parse(lookup, enum_str, -1, NULL); if (value < 0) { error_setg(errp, QERR_INVALID_PARAMETER, enum_str); g_free(enum_str); - return; + return false; } g_free(enum_str); *obj = value; + return true; } -void visit_type_enum(Visitor *v, const char *name, int *obj, +bool visit_type_enum(Visitor *v, const char *name, int *obj, const QEnumLookup *lookup, Error **errp) { assert(obj && lookup); trace_visit_type_enum(v, name, obj); switch (v->type) { case VISITOR_INPUT: - input_type_enum(v, name, obj, lookup, errp); - break; + return input_type_enum(v, name, obj, lookup, errp); case VISITOR_OUTPUT: - output_type_enum(v, name, obj, lookup, errp); - break; + return output_type_enum(v, name, obj, lookup, errp); case VISITOR_CLONE: /* nothing further to do, scalar value was already copied by * g_memdup() during visit_start_*() */ - break; + return true; case VISITOR_DEALLOC: /* nothing to deallocate for a scalar */ - break; + return true; + default: + abort(); } } diff --git a/qapi/qdev.json b/qapi/qdev.json index f4ed9735c434486331d7b76592967cf180d397c9..13254529bfabd726b6bcf0bfe3590419ebe34bbf 100644 --- a/qapi/qdev.json +++ b/qapi/qdev.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # # This work is licensed under the terms of the GNU GPL, version 2 or later. # See the COPYING file in the top-level directory. diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 79347e086452ef316490b47fa5df2d32b2b6245e..9a2d7dd29a931f0fa53917295a1c671c68141ea8 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -12,12 +12,16 @@ */ #include "qemu/osdep.h" + +#include "block/aio.h" #include "qapi/error.h" #include "qapi/qmp/dispatch.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qjson.h" #include "sysemu/runstate.h" #include "qapi/qmp/qbool.h" +#include "qemu/coroutine.h" +#include "qemu/main-loop.h" static QDict *qmp_dispatch_check_obj(QDict *dict, bool allow_oob, Error **errp) @@ -88,8 +92,32 @@ bool qmp_is_oob(const QDict *dict) && !qdict_haskey(dict, "execute"); } +typedef struct QmpDispatchBH { + const QmpCommand *cmd; + Monitor *cur_mon; + QDict *args; + QObject **ret; + Error **errp; + Coroutine *co; +} QmpDispatchBH; + +static void do_qmp_dispatch_bh(void *opaque) +{ + QmpDispatchBH *data = opaque; + + assert(monitor_cur() == NULL); + monitor_set_cur(qemu_coroutine_self(), data->cur_mon); + data->cmd->fn(data->args, data->ret, data->errp); + monitor_set_cur(qemu_coroutine_self(), NULL); + aio_co_wake(data->co); +} + +/* + * Runs outside of coroutine context for OOB commands, but in coroutine + * context for everything else. + */ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request, - bool allow_oob) + bool allow_oob, Monitor *cur_mon) { Error *err = NULL; bool oob; @@ -152,7 +180,40 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request, args = qdict_get_qdict(dict, "arguments"); qobject_ref(args); } - cmd->fn(args, &ret, &err); + + assert(!(oob && qemu_in_coroutine())); + assert(monitor_cur() == NULL); + if (!!(cmd->options & QCO_COROUTINE) == qemu_in_coroutine()) { + monitor_set_cur(qemu_coroutine_self(), cur_mon); + cmd->fn(args, &ret, &err); + monitor_set_cur(qemu_coroutine_self(), NULL); + } else { + /* + * Actual context doesn't match the one the command needs. + * + * Case 1: we are in coroutine context, but command does not + * have QCO_COROUTINE. We need to drop out of coroutine + * context for executing it. + * + * Case 2: we are outside coroutine context, but command has + * QCO_COROUTINE. Can't actually happen, because we get here + * outside coroutine context only when executing a command + * out of band, and OOB commands never have QCO_COROUTINE. + */ + assert(!oob && qemu_in_coroutine() && !(cmd->options & QCO_COROUTINE)); + + QmpDispatchBH data = { + .cur_mon = cur_mon, + .cmd = cmd, + .args = args, + .ret = &ret, + .errp = &err, + .co = qemu_coroutine_self(), + }; + aio_bh_schedule_oneshot(qemu_get_aio_context(), do_qmp_dispatch_bh, + &data); + qemu_coroutine_yield(); + } qobject_unref(args); if (err) { /* or assert(!ret) after reviewing all handlers: */ diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c index d0f9a1d3e37457c51298441c314aa2aeb01965b7..58c65b5052e54ea797aff868ead18088ae1e85e1 100644 --- a/qapi/qmp-registry.c +++ b/qapi/qmp-registry.c @@ -20,6 +20,9 @@ void qmp_register_command(QmpCommandList *cmds, const char *name, { QmpCommand *cmd = g_malloc0(sizeof(*cmd)); + /* QCO_COROUTINE and QCO_ALLOW_OOB are incompatible for now */ + assert(!((options & QCO_COROUTINE) && (options & QCO_ALLOW_OOB))); + cmd->name = name; cmd->fn = fn; cmd->enabled = true; diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index 5ce3ec2e5f8c53c91bedf75ae559f34ac3e5ee91..23843b242e8a5cd32f5b02c0e59839f750eebc40 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -237,7 +237,7 @@ static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv, } -static void qobject_input_check_struct(Visitor *v, Error **errp) +static bool qobject_input_check_struct(Visitor *v, Error **errp) { QObjectInputVisitor *qiv = to_qiv(v); StackObject *tos = QSLIST_FIRST(&qiv->stack); @@ -250,7 +250,9 @@ static void qobject_input_check_struct(Visitor *v, Error **errp) if (g_hash_table_iter_next(&iter, (void **)&key, NULL)) { error_setg(errp, "Parameter '%s' is unexpected", full_name(qiv, key)); + return false; } + return true; } static void qobject_input_stack_object_free(StackObject *tos) @@ -272,7 +274,7 @@ static void qobject_input_pop(Visitor *v, void **obj) qobject_input_stack_object_free(tos); } -static void qobject_input_start_struct(Visitor *v, const char *name, void **obj, +static bool qobject_input_start_struct(Visitor *v, const char *name, void **obj, size_t size, Error **errp) { QObjectInputVisitor *qiv = to_qiv(v); @@ -282,12 +284,12 @@ static void qobject_input_start_struct(Visitor *v, const char *name, void **obj, *obj = NULL; } if (!qobj) { - return; + return false; } if (qobject_type(qobj) != QTYPE_QDICT) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, full_name(qiv, name), "object"); - return; + return false; } qobject_input_push(qiv, name, qobj, obj); @@ -295,6 +297,7 @@ static void qobject_input_start_struct(Visitor *v, const char *name, void **obj, if (obj) { *obj = g_malloc0(size); } + return true; } static void qobject_input_end_struct(Visitor *v, void **obj) @@ -307,7 +310,7 @@ static void qobject_input_end_struct(Visitor *v, void **obj) } -static void qobject_input_start_list(Visitor *v, const char *name, +static bool qobject_input_start_list(Visitor *v, const char *name, GenericList **list, size_t size, Error **errp) { @@ -319,18 +322,19 @@ static void qobject_input_start_list(Visitor *v, const char *name, *list = NULL; } if (!qobj) { - return; + return false; } if (qobject_type(qobj) != QTYPE_QLIST) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, full_name(qiv, name), "array"); - return; + return false; } entry = qobject_input_push(qiv, name, qobj, list); if (entry && list) { *list = g_malloc0(size); } + return true; } static GenericList *qobject_input_next_list(Visitor *v, GenericList *tail, @@ -348,7 +352,7 @@ static GenericList *qobject_input_next_list(Visitor *v, GenericList *tail, return tail->next; } -static void qobject_input_check_list(Visitor *v, Error **errp) +static bool qobject_input_check_list(Visitor *v, Error **errp) { QObjectInputVisitor *qiv = to_qiv(v); StackObject *tos = QSLIST_FIRST(&qiv->stack); @@ -358,7 +362,9 @@ static void qobject_input_check_list(Visitor *v, Error **errp) if (tos->entry) { error_setg(errp, "Only %u list elements expected in %s", tos->index + 1, full_name_nth(qiv, NULL, 1)); + return false; } + return true; } static void qobject_input_end_list(Visitor *v, void **obj) @@ -370,7 +376,7 @@ static void qobject_input_end_list(Visitor *v, void **obj) qobject_input_pop(v, obj); } -static void qobject_input_start_alternate(Visitor *v, const char *name, +static bool qobject_input_start_alternate(Visitor *v, const char *name, GenericAlternate **obj, size_t size, Error **errp) { @@ -379,13 +385,14 @@ static void qobject_input_start_alternate(Visitor *v, const char *name, if (!qobj) { *obj = NULL; - return; + return false; } *obj = g_malloc0(size); (*obj)->type = qobject_type(qobj); + return true; } -static void qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj, +static bool qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj, Error **errp) { QObjectInputVisitor *qiv = to_qiv(v); @@ -393,33 +400,37 @@ static void qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj, QNum *qnum; if (!qobj) { - return; + return false; } qnum = qobject_to(QNum, qobj); if (!qnum || !qnum_get_try_int(qnum, obj)) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, full_name(qiv, name), "integer"); + return false; } + return true; } -static void qobject_input_type_int64_keyval(Visitor *v, const char *name, +static bool qobject_input_type_int64_keyval(Visitor *v, const char *name, int64_t *obj, Error **errp) { QObjectInputVisitor *qiv = to_qiv(v); const char *str = qobject_input_get_keyval(qiv, name, errp); if (!str) { - return; + return false; } if (qemu_strtoi64(str, NULL, 0, obj) < 0) { /* TODO report -ERANGE more nicely */ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, full_name(qiv, name), "integer"); + return false; } + return true; } -static void qobject_input_type_uint64(Visitor *v, const char *name, +static bool qobject_input_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp) { QObjectInputVisitor *qiv = to_qiv(v); @@ -428,7 +439,7 @@ static void qobject_input_type_uint64(Visitor *v, const char *name, int64_t val; if (!qobj) { - return; + return false; } qnum = qobject_to(QNum, qobj); if (!qnum) { @@ -436,38 +447,41 @@ static void qobject_input_type_uint64(Visitor *v, const char *name, } if (qnum_get_try_uint(qnum, obj)) { - return; + return true; } /* Need to accept negative values for backward compatibility */ if (qnum_get_try_int(qnum, &val)) { *obj = val; - return; + return true; } err: error_setg(errp, QERR_INVALID_PARAMETER_VALUE, full_name(qiv, name), "uint64"); + return false; } -static void qobject_input_type_uint64_keyval(Visitor *v, const char *name, +static bool qobject_input_type_uint64_keyval(Visitor *v, const char *name, uint64_t *obj, Error **errp) { QObjectInputVisitor *qiv = to_qiv(v); const char *str = qobject_input_get_keyval(qiv, name, errp); if (!str) { - return; + return false; } if (qemu_strtou64(str, NULL, 0, obj) < 0) { /* TODO report -ERANGE more nicely */ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, full_name(qiv, name), "integer"); + return false; } + return true; } -static void qobject_input_type_bool(Visitor *v, const char *name, bool *obj, +static bool qobject_input_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) { QObjectInputVisitor *qiv = to_qiv(v); @@ -475,39 +489,38 @@ static void qobject_input_type_bool(Visitor *v, const char *name, bool *obj, QBool *qbool; if (!qobj) { - return; + return false; } qbool = qobject_to(QBool, qobj); if (!qbool) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, full_name(qiv, name), "boolean"); - return; + return false; } *obj = qbool_get_bool(qbool); + return true; } -static void qobject_input_type_bool_keyval(Visitor *v, const char *name, +static bool qobject_input_type_bool_keyval(Visitor *v, const char *name, bool *obj, Error **errp) { QObjectInputVisitor *qiv = to_qiv(v); const char *str = qobject_input_get_keyval(qiv, name, errp); if (!str) { - return; + return false; } - if (!strcmp(str, "on")) { - *obj = true; - } else if (!strcmp(str, "off")) { - *obj = false; - } else { + if (!qapi_bool_parse(name, str, obj, NULL)) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, full_name(qiv, name), "'on' or 'off'"); + return false; } + return true; } -static void qobject_input_type_str(Visitor *v, const char *name, char **obj, +static bool qobject_input_type_str(Visitor *v, const char *name, char **obj, Error **errp) { QObjectInputVisitor *qiv = to_qiv(v); @@ -516,28 +529,30 @@ static void qobject_input_type_str(Visitor *v, const char *name, char **obj, *obj = NULL; if (!qobj) { - return; + return false; } qstr = qobject_to(QString, qobj); if (!qstr) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, full_name(qiv, name), "string"); - return; + return false; } *obj = g_strdup(qstring_get_str(qstr)); + return true; } -static void qobject_input_type_str_keyval(Visitor *v, const char *name, +static bool qobject_input_type_str_keyval(Visitor *v, const char *name, char **obj, Error **errp) { QObjectInputVisitor *qiv = to_qiv(v); const char *str = qobject_input_get_keyval(qiv, name, errp); *obj = g_strdup(str); + return !!str; } -static void qobject_input_type_number(Visitor *v, const char *name, double *obj, +static bool qobject_input_type_number(Visitor *v, const char *name, double *obj, Error **errp) { QObjectInputVisitor *qiv = to_qiv(v); @@ -545,19 +560,20 @@ static void qobject_input_type_number(Visitor *v, const char *name, double *obj, QNum *qnum; if (!qobj) { - return; + return false; } qnum = qobject_to(QNum, qobj); if (!qnum) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, full_name(qiv, name), "number"); - return; + return false; } *obj = qnum_get_double(qnum); + return true; } -static void qobject_input_type_number_keyval(Visitor *v, const char *name, +static bool qobject_input_type_number_keyval(Visitor *v, const char *name, double *obj, Error **errp) { QObjectInputVisitor *qiv = to_qiv(v); @@ -565,20 +581,21 @@ static void qobject_input_type_number_keyval(Visitor *v, const char *name, double val; if (!str) { - return; + return false; } if (qemu_strtod_finite(str, NULL, &val)) { /* TODO report -ERANGE more nicely */ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, full_name(qiv, name), "number"); - return; + return false; } *obj = val; + return true; } -static void qobject_input_type_any(Visitor *v, const char *name, QObject **obj, +static bool qobject_input_type_any(Visitor *v, const char *name, QObject **obj, Error **errp) { QObjectInputVisitor *qiv = to_qiv(v); @@ -586,13 +603,14 @@ static void qobject_input_type_any(Visitor *v, const char *name, QObject **obj, *obj = NULL; if (!qobj) { - return; + return false; } *obj = qobject_ref(qobj); + return true; } -static void qobject_input_type_null(Visitor *v, const char *name, +static bool qobject_input_type_null(Visitor *v, const char *name, QNull **obj, Error **errp) { QObjectInputVisitor *qiv = to_qiv(v); @@ -600,32 +618,35 @@ static void qobject_input_type_null(Visitor *v, const char *name, *obj = NULL; if (!qobj) { - return; + return false; } if (qobject_type(qobj) != QTYPE_QNULL) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, full_name(qiv, name), "null"); - return; + return false; } *obj = qnull(); + return true; } -static void qobject_input_type_size_keyval(Visitor *v, const char *name, +static bool qobject_input_type_size_keyval(Visitor *v, const char *name, uint64_t *obj, Error **errp) { QObjectInputVisitor *qiv = to_qiv(v); const char *str = qobject_input_get_keyval(qiv, name, errp); if (!str) { - return; + return false; } if (qemu_strtosz(str, NULL, obj) < 0) { /* TODO report -ERANGE more nicely */ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, full_name(qiv, name), "size"); + return false; } + return true; } static void qobject_input_optional(Visitor *v, const char *name, bool *present) @@ -732,7 +753,7 @@ Visitor *qobject_input_visitor_new_str(const char *str, assert(args); v = qobject_input_visitor_new(QOBJECT(args)); } else { - args = keyval_parse(str, implied_key, errp); + args = keyval_parse(str, implied_key, NULL, errp); if (!args) { return NULL; } diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c index 26d7be5ec99e2d41c53bbad1d676104f2abeac7f..ba6f6ac8a72a422c0235751a4befe7429530ab1d 100644 --- a/qapi/qobject-output-visitor.c +++ b/qapi/qobject-output-visitor.c @@ -103,7 +103,7 @@ static void qobject_output_add_obj(QObjectOutputVisitor *qov, const char *name, } } -static void qobject_output_start_struct(Visitor *v, const char *name, +static bool qobject_output_start_struct(Visitor *v, const char *name, void **obj, size_t unused, Error **errp) { QObjectOutputVisitor *qov = to_qov(v); @@ -111,6 +111,7 @@ static void qobject_output_start_struct(Visitor *v, const char *name, qobject_output_add(qov, name, dict); qobject_output_push(qov, dict, obj); + return true; } static void qobject_output_end_struct(Visitor *v, void **obj) @@ -120,7 +121,7 @@ static void qobject_output_end_struct(Visitor *v, void **obj) assert(qobject_type(value) == QTYPE_QDICT); } -static void qobject_output_start_list(Visitor *v, const char *name, +static bool qobject_output_start_list(Visitor *v, const char *name, GenericList **listp, size_t size, Error **errp) { @@ -129,6 +130,7 @@ static void qobject_output_start_list(Visitor *v, const char *name, qobject_output_add(qov, name, list); qobject_output_push(qov, list, listp); + return true; } static GenericList *qobject_output_next_list(Visitor *v, GenericList *tail, @@ -144,28 +146,31 @@ static void qobject_output_end_list(Visitor *v, void **obj) assert(qobject_type(value) == QTYPE_QLIST); } -static void qobject_output_type_int64(Visitor *v, const char *name, +static bool qobject_output_type_int64(Visitor *v, const char *name, int64_t *obj, Error **errp) { QObjectOutputVisitor *qov = to_qov(v); qobject_output_add(qov, name, qnum_from_int(*obj)); + return true; } -static void qobject_output_type_uint64(Visitor *v, const char *name, +static bool qobject_output_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp) { QObjectOutputVisitor *qov = to_qov(v); qobject_output_add(qov, name, qnum_from_uint(*obj)); + return true; } -static void qobject_output_type_bool(Visitor *v, const char *name, bool *obj, +static bool qobject_output_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) { QObjectOutputVisitor *qov = to_qov(v); qobject_output_add(qov, name, qbool_from_bool(*obj)); + return true; } -static void qobject_output_type_str(Visitor *v, const char *name, char **obj, +static bool qobject_output_type_str(Visitor *v, const char *name, char **obj, Error **errp) { QObjectOutputVisitor *qov = to_qov(v); @@ -174,28 +179,32 @@ static void qobject_output_type_str(Visitor *v, const char *name, char **obj, } else { qobject_output_add(qov, name, qstring_from_str("")); } + return true; } -static void qobject_output_type_number(Visitor *v, const char *name, +static bool qobject_output_type_number(Visitor *v, const char *name, double *obj, Error **errp) { QObjectOutputVisitor *qov = to_qov(v); qobject_output_add(qov, name, qnum_from_double(*obj)); + return true; } -static void qobject_output_type_any(Visitor *v, const char *name, +static bool qobject_output_type_any(Visitor *v, const char *name, QObject **obj, Error **errp) { QObjectOutputVisitor *qov = to_qov(v); qobject_output_add_obj(qov, name, qobject_ref(*obj)); + return true; } -static void qobject_output_type_null(Visitor *v, const char *name, +static bool qobject_output_type_null(Visitor *v, const char *name, QNull **obj, Error **errp) { QObjectOutputVisitor *qov = to_qov(v); qobject_output_add(qov, name, qnull()); + return true; } /* Finish building, and return the root object. diff --git a/qapi/qom.json b/qapi/qom.json index 8abe998962b369c390e41706126a4b4bc07843e5..0b0b92944ba0376a79adce0a17b5b761df80c3db 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # # This work is licensed under the terms of the GNU GPL, version 2 or later. # See the COPYING file in the top-level directory. diff --git a/qapi/rdma.json b/qapi/rdma.json index b58105b1b6d7945d05dc8363ce5a78d72e2c0494..a1d2175a8b3614d237f0cfb0a57f2f680a57cff9 100644 --- a/qapi/rdma.json +++ b/qapi/rdma.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # ## diff --git a/qapi/replay.json b/qapi/replay.json new file mode 100644 index 0000000000000000000000000000000000000000..bfd83d7591446363468dbf61cc8b6fb445f0d2fb --- /dev/null +++ b/qapi/replay.json @@ -0,0 +1,121 @@ +# -*- Mode: Python -*- +# + +## +# = Record/replay +## + +{ 'include': 'common.json' } + +## +# @ReplayMode: +# +# Mode of the replay subsystem. +# +# @none: normal execution mode. Replay or record are not enabled. +# +# @record: record mode. All non-deterministic data is written into the +# replay log. +# +# @play: replay mode. Non-deterministic data required for system execution +# is read from the log. +# +# Since: 2.5 +## +{ 'enum': 'ReplayMode', + 'data': [ 'none', 'record', 'play' ] } + +## +# @ReplayInfo: +# +# Record/replay information. +# +# @mode: current mode. +# +# @filename: name of the record/replay log file. +# It is present only in record or replay modes, when the log +# is recorded or replayed. +# +# @icount: current number of executed instructions. +# +# Since: 5.2 +# +## +{ 'struct': 'ReplayInfo', + 'data': { 'mode': 'ReplayMode', '*filename': 'str', 'icount': 'int' } } + +## +# @query-replay: +# +# Retrieve the record/replay information. +# It includes current instruction count which may be used for +# @replay-break and @replay-seek commands. +# +# Returns: record/replay information. +# +# Since: 5.2 +# +# Example: +# +# -> { "execute": "query-replay" } +# <- { "return": { "mode": "play", "filename": "log.rr", "icount": 220414 } } +# +## +{ 'command': 'query-replay', + 'returns': 'ReplayInfo' } + +## +# @replay-break: +# +# Set replay breakpoint at instruction count @icount. +# Execution stops when the specified instruction is reached. +# There can be at most one breakpoint. When breakpoint is set, any prior +# one is removed. The breakpoint may be set only in replay mode and only +# "in the future", i.e. at instruction counts greater than the current one. +# The current instruction count can be observed with @query-replay. +# +# @icount: instruction count to stop at +# +# Since: 5.2 +# +# Example: +# +# -> { "execute": "replay-break", "data": { "icount": 220414 } } +# +## +{ 'command': 'replay-break', 'data': { 'icount': 'int' } } + +## +# @replay-delete-break: +# +# Remove replay breakpoint which was set with @replay-break. +# The command is ignored when there are no replay breakpoints. +# +# Since: 5.2 +# +# Example: +# +# -> { "execute": "replay-delete-break" } +# +## +{ 'command': 'replay-delete-break' } + +## +# @replay-seek: +# +# Automatically proceed to the instruction count @icount, when +# replaying the execution. The command automatically loads nearest +# snapshot and replays the execution to find the desired instruction. +# When there is no preceding snapshot or the execution is not replayed, +# then the command fails. +# icount for the reference may be obtained with @query-replay command. +# +# @icount: target instruction count +# +# Since: 5.2 +# +# Example: +# +# -> { "execute": "replay-seek", "data": { "icount": 220414 } } +## +{ 'command': 'replay-seek', 'data': { 'icount': 'int' } } diff --git a/qapi/rocker.json b/qapi/rocker.json index 52597db491a8082306b389defb78a31778619f69..b48e49a89bb3a4741621281b938dd121cc9ce7d0 100644 --- a/qapi/rocker.json +++ b/qapi/rocker.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python ## # = Rocker switch device diff --git a/qapi/run-state.json b/qapi/run-state.json index 2e2290774007dfc78a1adeec806107dafbd54b4c..964c8ef3916c43046ea6cc6ffcb875987d071eb7 100644 --- a/qapi/run-state.json +++ b/qapi/run-state.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # ## @@ -474,3 +475,93 @@ 'psw-mask': 'uint64', 'psw-addr': 'uint64', 'reason': 'S390CrashReason' } } + +## +# @MEMORY_FAILURE: +# +# Emitted when a memory failure occurs on host side. +# +# @recipient: recipient is defined as @MemoryFailureRecipient. +# +# @action: action that has been taken. action is defined as @MemoryFailureAction. +# +# @flags: flags for MemoryFailureAction. action is defined as @MemoryFailureFlags. +# +# Since: 5.2 +# +# Example: +# +# <- { "event": "MEMORY_FAILURE", +# "data": { "recipient": "hypervisor", +# "action": "fatal", +# "flags": { 'action-required': false } } +# +## +{ 'event': 'MEMORY_FAILURE', + 'data': { 'recipient': 'MemoryFailureRecipient', + 'action': 'MemoryFailureAction', + 'flags': 'MemoryFailureFlags'} } + +## +# @MemoryFailureRecipient: +# +# Hardware memory failure occurs, handled by recipient. +# +# @hypervisor: memory failure at QEMU process address space. +# (none guest memory, but used by QEMU itself). +# +# @guest: memory failure at guest memory, +# +# Since: 5.2 +# +## +{ 'enum': 'MemoryFailureRecipient', + 'data': [ 'hypervisor', + 'guest' ] } + + +## +# @MemoryFailureAction: +# +# Actions taken by QEMU in response to a hardware memory failure. +# +# @ignore: the memory failure could be ignored. This will only be the case +# for action-optional failures. +# +# @inject: memory failure occurred in guest memory, the guest enabled MCE +# handling mechanism, and QEMU could inject the MCE into the guest +# successfully. +# +# @fatal: the failure is unrecoverable. This occurs for action-required +# failures if the recipient is the hypervisor; QEMU will exit. +# +# @reset: the failure is unrecoverable but confined to the guest. This +# occurs if the recipient is a guest guest which is not ready +# to handle memory failures. +# +# Since: 5.2 +# +## +{ 'enum': 'MemoryFailureAction', + 'data': [ 'ignore', + 'inject', + 'fatal', + 'reset' ] } + +## +# @MemoryFailureFlags: +# +# Additional information on memory failures. +# +# @action-required: whether a memory failure event is action-required +# or action-optional (e.g. a failure during memory scrub). +# +# @recursive: whether the failure occurred while the previous +# failure was still in progress. +# +# Since: 5.2 +# +## +{ 'struct': 'MemoryFailureFlags', + 'data': { 'action-required': 'bool', + 'recursive': 'bool'} } diff --git a/qapi/sockets.json b/qapi/sockets.json index cbd6ef35d0afad6fa5f67c0a955571a1b0787853..2e83452797f81f30dee300f58241b3a15f9120ca 100644 --- a/qapi/sockets.json +++ b/qapi/sockets.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python ## # = Socket data types @@ -73,18 +74,20 @@ # Captures a socket address in the local ("Unix socket") namespace. # # @path: filesystem path to use -# @tight: pass a socket address length confined to the minimum length of the -# abstract string, rather than the full sockaddr_un record length -# (only matters for abstract sockets, default true). (Since 5.1) -# @abstract: whether this is an abstract address, default false. (Since 5.1) +# @abstract: if true, this is a Linux abstract socket address. @path +# will be prefixed by a null byte, and optionally padded +# with null bytes. Defaults to false. (Since 5.1) +# @tight: if false, pad an abstract socket address with enough null +# bytes to make it fill struct sockaddr_un member sun_path. +# Defaults to true. (Since 5.1) # # Since: 1.3 ## { 'struct': 'UnixSocketAddress', 'data': { 'path': 'str', - '*tight': 'bool', - '*abstract': 'bool' } } + '*abstract': { 'type': 'bool', 'if': 'defined(CONFIG_LINUX)' }, + '*tight': { 'type': 'bool', 'if': 'defined(CONFIG_LINUX)' } } } ## # @VsockSocketAddress: diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c index 9be418b6d61c078cc882686d197c1238bf02e4c0..197139c1c0c8740ba5a08af38f93411a420bc7c4 100644 --- a/qapi/string-input-visitor.c +++ b/qapi/string-input-visitor.c @@ -60,7 +60,7 @@ static StringInputVisitor *to_siv(Visitor *v) return container_of(v, StringInputVisitor, visitor); } -static void start_list(Visitor *v, const char *name, GenericList **list, +static bool start_list(Visitor *v, const char *name, GenericList **list, size_t size, Error **errp) { StringInputVisitor *siv = to_siv(v); @@ -80,6 +80,7 @@ static void start_list(Visitor *v, const char *name, GenericList **list, } siv->lm = LM_UNPARSED; } + return true; } static GenericList *next_list(Visitor *v, GenericList *tail, size_t size) @@ -102,7 +103,7 @@ static GenericList *next_list(Visitor *v, GenericList *tail, size_t size) return tail->next; } -static void check_list(Visitor *v, Error **errp) +static bool check_list(Visitor *v, Error **errp) { const StringInputVisitor *siv = to_siv(v); @@ -111,9 +112,9 @@ static void check_list(Visitor *v, Error **errp) case LM_UINT64_RANGE: case LM_UNPARSED: error_setg(errp, "Fewer list elements expected"); - return; + return false; case LM_END: - return; + return true; default: abort(); } @@ -178,7 +179,7 @@ static int try_parse_int64_list_entry(StringInputVisitor *siv, int64_t *obj) return 0; } -static void parse_type_int64(Visitor *v, const char *name, int64_t *obj, +static bool parse_type_int64(Visitor *v, const char *name, int64_t *obj, Error **errp) { StringInputVisitor *siv = to_siv(v); @@ -188,17 +189,17 @@ static void parse_type_int64(Visitor *v, const char *name, int64_t *obj, case LM_NONE: /* just parse a simple int64, bail out if not completely consumed */ if (qemu_strtoi64(siv->string, NULL, 0, &val)) { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, - name ? name : "null", "int64"); - return; + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + name ? name : "null", "int64"); + return false; } *obj = val; - return; + return true; case LM_UNPARSED: if (try_parse_int64_list_entry(siv, obj)) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null", "list of int64 values or ranges"); - return; + return false; } assert(siv->lm == LM_INT64_RANGE); /* fall through */ @@ -211,10 +212,10 @@ static void parse_type_int64(Visitor *v, const char *name, int64_t *obj, /* end of range, check if there is more to parse */ siv->lm = siv->unparsed_string[0] ? LM_UNPARSED : LM_END; } - return; + return true; case LM_END: error_setg(errp, "Fewer list elements expected"); - return; + return false; default: abort(); } @@ -268,7 +269,7 @@ static int try_parse_uint64_list_entry(StringInputVisitor *siv, uint64_t *obj) return 0; } -static void parse_type_uint64(Visitor *v, const char *name, uint64_t *obj, +static bool parse_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp) { StringInputVisitor *siv = to_siv(v); @@ -280,15 +281,15 @@ static void parse_type_uint64(Visitor *v, const char *name, uint64_t *obj, if (qemu_strtou64(siv->string, NULL, 0, &val)) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null", "uint64"); - return; + return false; } *obj = val; - return; + return true; case LM_UNPARSED: if (try_parse_uint64_list_entry(siv, obj)) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null", "list of uint64 values or ranges"); - return; + return false; } assert(siv->lm == LM_UINT64_RANGE); /* fall through */ @@ -301,65 +302,50 @@ static void parse_type_uint64(Visitor *v, const char *name, uint64_t *obj, /* end of range, check if there is more to parse */ siv->lm = siv->unparsed_string[0] ? LM_UNPARSED : LM_END; } - return; + return true; case LM_END: error_setg(errp, "Fewer list elements expected"); - return; + return false; default: abort(); } } -static void parse_type_size(Visitor *v, const char *name, uint64_t *obj, +static bool parse_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp) { StringInputVisitor *siv = to_siv(v); - Error *err = NULL; uint64_t val; assert(siv->lm == LM_NONE); - parse_option_size(name, siv->string, &val, &err); - if (err) { - error_propagate(errp, err); - return; + if (!parse_option_size(name, siv->string, &val, errp)) { + return false; } *obj = val; + return true; } -static void parse_type_bool(Visitor *v, const char *name, bool *obj, +static bool parse_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) { StringInputVisitor *siv = to_siv(v); assert(siv->lm == LM_NONE); - if (!strcasecmp(siv->string, "on") || - !strcasecmp(siv->string, "yes") || - !strcasecmp(siv->string, "true")) { - *obj = true; - return; - } - if (!strcasecmp(siv->string, "off") || - !strcasecmp(siv->string, "no") || - !strcasecmp(siv->string, "false")) { - *obj = false; - return; - } - - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", - "boolean"); + return qapi_bool_parse(name ? name : "null", siv->string, obj, errp); } -static void parse_type_str(Visitor *v, const char *name, char **obj, +static bool parse_type_str(Visitor *v, const char *name, char **obj, Error **errp) { StringInputVisitor *siv = to_siv(v); assert(siv->lm == LM_NONE); *obj = g_strdup(siv->string); + return true; } -static void parse_type_number(Visitor *v, const char *name, double *obj, +static bool parse_type_number(Visitor *v, const char *name, double *obj, Error **errp) { StringInputVisitor *siv = to_siv(v); @@ -369,13 +355,14 @@ static void parse_type_number(Visitor *v, const char *name, double *obj, if (qemu_strtod_finite(siv->string, NULL, &val)) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "number"); - return; + return false; } *obj = val; + return true; } -static void parse_type_null(Visitor *v, const char *name, QNull **obj, +static bool parse_type_null(Visitor *v, const char *name, QNull **obj, Error **errp) { StringInputVisitor *siv = to_siv(v); @@ -386,10 +373,11 @@ static void parse_type_null(Visitor *v, const char *name, QNull **obj, if (siv->string[0]) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "null"); - return; + return false; } *obj = qnull(); + return true; } static void string_input_free(Visitor *v) diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c index 0d93605d77a7a7852b556242a8b937b99322d54b..b74aa4d44c46abbe326c384c12ac7b71963ca25f 100644 --- a/qapi/string-output-visitor.c +++ b/qapi/string-output-visitor.c @@ -123,7 +123,7 @@ static void format_string(StringOutputVisitor *sov, Range *r, bool next, } } -static void print_type_int64(Visitor *v, const char *name, int64_t *obj, +static bool print_type_int64(Visitor *v, const char *name, int64_t *obj, Error **errp) { StringOutputVisitor *sov = to_sov(v); @@ -138,7 +138,7 @@ static void print_type_int64(Visitor *v, const char *name, int64_t *obj, sov->range_start.s = *obj; sov->range_end.s = *obj; sov->list_mode = LM_IN_PROGRESS; - return; + return true; case LM_IN_PROGRESS: if (sov->range_end.s + 1 == *obj) { @@ -155,7 +155,7 @@ static void print_type_int64(Visitor *v, const char *name, int64_t *obj, sov->range_start.s = *obj; sov->range_end.s = *obj; } - return; + return true; case LM_END: if (sov->range_end.s + 1 == *obj) { @@ -197,17 +197,19 @@ static void print_type_int64(Visitor *v, const char *name, int64_t *obj, } g_string_append(sov->string, ")"); } + + return true; } -static void print_type_uint64(Visitor *v, const char *name, uint64_t *obj, +static bool print_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp) { /* FIXME: print_type_int64 mishandles values over INT64_MAX */ int64_t i = *obj; - print_type_int64(v, name, &i, errp); + return print_type_int64(v, name, &i, errp); } -static void print_type_size(Visitor *v, const char *name, uint64_t *obj, +static bool print_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp) { StringOutputVisitor *sov = to_sov(v); @@ -217,7 +219,7 @@ static void print_type_size(Visitor *v, const char *name, uint64_t *obj, if (!sov->human) { out = g_strdup_printf("%"PRIu64, *obj); string_output_set(sov, out); - return; + return true; } val = *obj; @@ -226,16 +228,18 @@ static void print_type_size(Visitor *v, const char *name, uint64_t *obj, string_output_set(sov, out); g_free(psize); + return true; } -static void print_type_bool(Visitor *v, const char *name, bool *obj, +static bool print_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) { StringOutputVisitor *sov = to_sov(v); string_output_set(sov, g_strdup(*obj ? "true" : "false")); + return true; } -static void print_type_str(Visitor *v, const char *name, char **obj, +static bool print_type_str(Visitor *v, const char *name, char **obj, Error **errp) { StringOutputVisitor *sov = to_sov(v); @@ -247,16 +251,18 @@ static void print_type_str(Visitor *v, const char *name, char **obj, out = g_strdup(*obj ? *obj : ""); } string_output_set(sov, out); + return true; } -static void print_type_number(Visitor *v, const char *name, double *obj, +static bool print_type_number(Visitor *v, const char *name, double *obj, Error **errp) { StringOutputVisitor *sov = to_sov(v); string_output_set(sov, g_strdup_printf("%f", *obj)); + return true; } -static void print_type_null(Visitor *v, const char *name, QNull **obj, +static bool print_type_null(Visitor *v, const char *name, QNull **obj, Error **errp) { StringOutputVisitor *sov = to_sov(v); @@ -268,9 +274,10 @@ static void print_type_null(Visitor *v, const char *name, QNull **obj, out = g_strdup(""); } string_output_set(sov, out); + return true; } -static void +static bool start_list(Visitor *v, const char *name, GenericList **list, size_t size, Error **errp) { @@ -285,6 +292,7 @@ start_list(Visitor *v, const char *name, GenericList **list, size_t size, if (*list && (*list)->next) { sov->list_mode = LM_STARTED; } + return true; } static GenericList *next_list(Visitor *v, GenericList *tail, size_t size) diff --git a/qapi/tpm.json b/qapi/tpm.json index dc1f081739988697b1a9c1a1cec736ba2234efb7..6a10c9ed8d27023eacfc48499c534920582820f9 100644 --- a/qapi/tpm.json +++ b/qapi/tpm.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # ## diff --git a/qapi/trace.h b/qapi/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..5c3fb674d85504b89fc56c17584a8c8b83693574 --- /dev/null +++ b/qapi/trace.h @@ -0,0 +1 @@ +#include "trace/trace-qapi.h" diff --git a/qapi/transaction.json b/qapi/transaction.json index b6c11158f0b63f847ecb6cd655f8a79d593a8cf9..15ddebdbc360b79d4663d96c10e2df00cdace52d 100644 --- a/qapi/transaction.json +++ b/qapi/transaction.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # ## diff --git a/qapi/ui.json b/qapi/ui.json index e16e98a060d8f1de42d4baa8034038850a66e532..6c7b33cb72389988ce71f291c863430ec4e32335 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # ## @@ -97,7 +98,8 @@ # ## { 'command': 'screendump', - 'data': {'filename': 'str', '*device': 'str', '*head': 'int'} } + 'data': {'filename': 'str', '*device': 'str', '*head': 'int'}, + 'coroutine': true } ## # == Spice @@ -1081,8 +1083,8 @@ # Since: 3.0 # ## - { 'enum' : 'DisplayGLMode', - 'data' : [ 'off', 'on', 'core', 'es' ] } +{ 'enum' : 'DisplayGLMode', + 'data' : [ 'off', 'on', 'core', 'es' ] } ## # @DisplayCurses: diff --git a/qemu-bridge-helper.c b/qemu-bridge-helper.c index 88b26747fc866116637716264dea3ce4631a4b11..a26e1663f02de3c99198df6e2080d52c051f1ac1 100644 --- a/qemu-bridge-helper.c +++ b/qemu-bridge-helper.c @@ -40,6 +40,7 @@ #endif #include "qemu/queue.h" +#include "qemu/cutils.h" #include "net/tap-linux.h" @@ -245,6 +246,7 @@ int main(int argc, char **argv) ACLList acl_list; int access_allowed, access_denied; int ret = EXIT_SUCCESS; + g_autofree char *acl_file = NULL; #ifdef CONFIG_LIBCAP_NG /* if we're run from an suid binary, immediately drop privileges preserving @@ -257,6 +259,8 @@ int main(int argc, char **argv) } #endif + qemu_init_exec_dir(argv[0]); + /* parse arguments */ for (index = 1; index < argc; index++) { if (strcmp(argv[index], "--use-vnet") == 0) { @@ -282,9 +286,10 @@ int main(int argc, char **argv) /* parse default acl file */ QSIMPLEQ_INIT(&acl_list); - if (parse_acl_file(DEFAULT_ACL_FILE, &acl_list) == -1) { + acl_file = get_relocated_path(DEFAULT_ACL_FILE); + if (parse_acl_file(acl_file, &acl_list) == -1) { fprintf(stderr, "failed to parse default acl file `%s'\n", - DEFAULT_ACL_FILE); + acl_file); ret = EXIT_FAILURE; goto cleanup; } diff --git a/qemu-edid.c b/qemu-edid.c index 46eef7049803c0ae6145dc6cf45d29ceeefde519..1cd6a95172388924c87d00446fd234e6cf8c2a6a 100644 --- a/qemu-edid.c +++ b/qemu-edid.c @@ -9,7 +9,10 @@ #include "qemu/cutils.h" #include "hw/display/edid.h" -static qemu_edid_info info; +static qemu_edid_info info = { + .prefx = 1024, + .prefy = 768, +}; static void usage(FILE *out) { @@ -39,6 +42,7 @@ int main(int argc, char *argv[]) { FILE *outfile = NULL; uint8_t blob[256]; + uint32_t dpi = 100; int rc; for (;;) { @@ -83,7 +87,7 @@ int main(int argc, char *argv[]) } break; case 'd': - if (qemu_strtoui(optarg, NULL, 10, &info.dpi) < 0) { + if (qemu_strtoui(optarg, NULL, 10, &dpi) < 0) { fprintf(stderr, "not a number: %s\n", optarg); exit(1); } @@ -110,6 +114,9 @@ int main(int argc, char *argv[]) outfile = stdout; } + info.width_mm = qemu_edid_dpi_to_mm(dpi, info.prefx); + info.height_mm = qemu_edid_dpi_to_mm(dpi, info.prefy); + memset(blob, 0, sizeof(blob)); qemu_edid_generate(blob, sizeof(blob), &info); fwrite(blob, sizeof(blob), 1, outfile); diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx index a87d3cb264cefdda5b079b867e46b9a95557e04d..b3620f29e50c3e34c151563759c52c872b90abd6 100644 --- a/qemu-img-cmds.hx +++ b/qemu-img-cmds.hx @@ -1,5 +1,5 @@ HXCOMM Keep the list of subcommands sorted by name. -HXCOMM Use DEFHEADING() to define headings in both help text and texi +HXCOMM Use DEFHEADING() to define headings in both help text and rST HXCOMM Text between SRST and ERST are copied to rST version and HXCOMM discarded from C version HXCOMM DEF(command, callback, arg_string) is used to construct @@ -10,9 +10,9 @@ HXCOMM When amending the rST sections, please remember to copy the usage HXCOMM over to the per-command sections in docs/tools/qemu-img.rst. DEF("amend", img_amend, - "amend [--object objectdef] [--image-opts] [-p] [-q] [-f fmt] [-t cache] -o options filename") + "amend [--object objectdef] [--image-opts] [-p] [-q] [-f fmt] [-t cache] [--force] -o options filename") SRST -.. option:: amend [--object OBJECTDEF] [--image-opts] [-p] [-q] [-f FMT] [-t CACHE] -o OPTIONS FILENAME +.. option:: amend [--object OBJECTDEF] [--image-opts] [-p] [-q] [-f FMT] [-t CACHE] [--force] -o OPTIONS FILENAME ERST DEF("bench", img_bench, @@ -34,9 +34,9 @@ SRST ERST DEF("commit", img_commit, - "commit [--object objectdef] [--image-opts] [-q] [-f fmt] [-t cache] [-b base] [-d] [-p] filename") + "commit [--object objectdef] [--image-opts] [-q] [-f fmt] [-t cache] [-b base] [-r rate_limit] [-d] [-p] filename") SRST -.. option:: commit [--object OBJECTDEF] [--image-opts] [-q] [-f FMT] [-t CACHE] [-b BASE] [-d] [-p] FILENAME +.. option:: commit [--object OBJECTDEF] [--image-opts] [-q] [-f FMT] [-t CACHE] [-b BASE] [-r RATE_LIMIT] [-d] [-p] FILENAME ERST DEF("compare", img_compare, @@ -46,9 +46,9 @@ SRST ERST DEF("convert", img_convert, - "convert [--object objectdef] [--image-opts] [--target-image-opts] [--target-is-zero] [-U] [-C] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] [--salvage] filename [filename2 [...]] output_filename") + "convert [--object objectdef] [--image-opts] [--target-image-opts] [--target-is-zero] [--bitmaps] [-U] [-C] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-l snapshot_param] [-S sparse_size] [-r rate_limit] [-m num_coroutines] [-W] [--salvage] filename [filename2 [...]] output_filename") SRST -.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-m NUM_COROUTINES] [-W] [--salvage] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME +.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [--bitmaps] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-r RATE_LIMIT] [-m NUM_COROUTINES] [-W] [--salvage] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME ERST DEF("create", img_create, diff --git a/qemu-img.c b/qemu-img.c index 2d30682f129fb8a2b808b8cd56426d30457b35d2..8bdea40b58d18ee91217374bf85cd0602470f255 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -41,6 +41,7 @@ #include "qemu/log.h" #include "qemu/main-loop.h" #include "qemu/module.h" +#include "qemu/sockets.h" #include "qemu/units.h" #include "qom/object_interfaces.h" #include "sysemu/block-backend.h" @@ -49,6 +50,8 @@ #include "block/qapi.h" #include "crypto/init.h" #include "trace/control.h" +#include "qemu/throttle.h" +#include "block/throttle-groups.h" #define QEMU_IMG_VERSION "qemu-img version " QEMU_FULL_VERSION \ "\n" QEMU_COPYRIGHT "\n" @@ -78,6 +81,8 @@ enum { OPTION_ENABLE = 272, OPTION_DISABLE = 273, OPTION_MERGE = 274, + OPTION_BITMAPS = 275, + OPTION_FORCE = 276, }; typedef enum OutputFormat { @@ -191,6 +196,7 @@ static void QEMU_NORETURN help(void) " hiding corruption that has already occurred.\n" "\n" "Parameters to convert subcommand:\n" + " '--bitmaps' copies all top-level persistent bitmaps to destination\n" " '-m' specifies how many coroutines work in parallel during the convert\n" " process (defaults to 8)\n" " '-W' allow to write to the target out of order rather than sequential\n" @@ -462,23 +468,18 @@ static int add_old_style_options(const char *fmt, QemuOpts *opts, const char *base_filename, const char *base_fmt) { - Error *err = NULL; - if (base_filename) { - qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, base_filename, &err); - if (err) { + if (!qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, base_filename, + NULL)) { error_report("Backing file not supported for file format '%s'", fmt); - error_free(err); return -1; } } if (base_fmt) { - qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, base_fmt, &err); - if (err) { + if (!qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, base_fmt, NULL)) { error_report("Backing file format not supported for file " "format '%s'", fmt); - error_free(err); return -1; } } @@ -981,6 +982,7 @@ static int img_commit(int argc, char **argv) CommonBlockJobCBInfo cbi; bool image_opts = false; AioContext *aio_context; + int64_t rate_limit = 0; fmt = NULL; cache = BDRV_DEFAULT_CACHE; @@ -992,7 +994,7 @@ static int img_commit(int argc, char **argv) {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, ":f:ht:b:dpq", + c = getopt_long(argc, argv, ":f:ht:b:dpqr:", long_options, NULL); if (c == -1) { break; @@ -1027,6 +1029,12 @@ static int img_commit(int argc, char **argv) case 'q': quiet = true; break; + case 'r': + rate_limit = cvtnum("rate limit", optarg); + if (rate_limit < 0) { + return 1; + } + break; case OPTION_OBJECT: { QemuOpts *opts; opts = qemu_opts_parse_noisily(&qemu_object_opts, @@ -1086,7 +1094,7 @@ static int img_commit(int argc, char **argv) /* This is different from QMP, which by default uses the deepest file in * the backing chain (i.e., the very base); however, the traditional * behavior of qemu-img commit is using the immediate backing file. */ - base_bs = backing_bs(bs); + base_bs = bdrv_backing_chain_next(bs); if (!base_bs) { error_setg(&local_err, "Image does not have a backing file"); goto done; @@ -1100,7 +1108,7 @@ static int img_commit(int argc, char **argv) aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); - commit_active_start("commit", bs, base_bs, JOB_DEFAULT, 0, + commit_active_start("commit", bs, base_bs, JOB_DEFAULT, rate_limit, BLOCKDEV_ON_ERROR_REPORT, NULL, common_block_job_cb, &cbi, false, &local_err); aio_context_release(aio_context); @@ -1189,7 +1197,7 @@ static int64_t find_nonzero(const uint8_t *buf, int64_t n) * 'pnum' is set to the number of sectors (including and immediately following * the first one) that are known to be in the same allocated/unallocated state. * The function will try to align the end offset to alignment boundaries so - * that the request will at least end aligned and consequtive requests will + * that the request will at least end aligned and consecutive requests will * also start at an aligned offset. */ static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum, @@ -1202,10 +1210,10 @@ static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum, *pnum = 0; return 0; } - is_zero = buffer_is_zero(buf, 512); + is_zero = buffer_is_zero(buf, BDRV_SECTOR_SIZE); for(i = 1; i < n; i++) { - buf += 512; - if (is_zero != buffer_is_zero(buf, 512)) { + buf += BDRV_SECTOR_SIZE; + if (is_zero != buffer_is_zero(buf, BDRV_SECTOR_SIZE)) { break; } } @@ -1638,6 +1646,24 @@ out4: return ret; } +/* Convenience wrapper around qmp_block_dirty_bitmap_merge */ +static void do_dirty_bitmap_merge(const char *dst_node, const char *dst_name, + const char *src_node, const char *src_name, + Error **errp) +{ + BlockDirtyBitmapMergeSource *merge_src; + BlockDirtyBitmapMergeSourceList *list; + + merge_src = g_new0(BlockDirtyBitmapMergeSource, 1); + merge_src->type = QTYPE_QDICT; + merge_src->u.external.node = g_strdup(src_node); + merge_src->u.external.name = g_strdup(src_name); + list = g_new0(BlockDirtyBitmapMergeSourceList, 1); + list->value = merge_src; + qmp_block_dirty_bitmap_merge(dst_node, dst_name, list, errp); + qapi_free_BlockDirtyBitmapMergeSourceList(list); +} + enum ImgConvertBlockStatus { BLK_DATA, BLK_ZERO, @@ -1645,10 +1671,12 @@ enum ImgConvertBlockStatus { }; #define MAX_COROUTINES 16 +#define CONVERT_THROTTLE_GROUP "img_convert" typedef struct ImgConvertState { BlockBackend **src; int64_t *src_sectors; + int *src_alignment; int src_num; int64_t total_sectors; int64_t allocated_sectors; @@ -1660,7 +1688,6 @@ typedef struct ImgConvertState { BlockBackend *target; bool has_zero_init; bool compressed; - bool unallocated_blocks_are_zero; bool target_is_new; bool target_has_backing; int64_t target_backing_sectors; /* negative if unknown */ @@ -1705,7 +1732,7 @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num) if (s->target_backing_sectors >= 0) { if (sector_num >= s->target_backing_sectors) { - post_backing_zero = s->unallocated_blocks_are_zero; + post_backing_zero = true; } else if (sector_num + n > s->target_backing_sectors) { /* Split requests around target_backing_sectors (because * starting from there, zeros are handled differently) */ @@ -1716,18 +1743,21 @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num) if (s->sector_next_status <= sector_num) { uint64_t offset = (sector_num - src_cur_offset) * BDRV_SECTOR_SIZE; int64_t count; + int tail; + BlockDriverState *src_bs = blk_bs(s->src[src_cur]); + BlockDriverState *base; + + if (s->target_has_backing) { + base = bdrv_cow_bs(bdrv_skip_filters(src_bs)); + } else { + base = NULL; + } do { count = n * BDRV_SECTOR_SIZE; - if (s->target_has_backing) { - ret = bdrv_block_status(blk_bs(s->src[src_cur]), offset, - count, &count, NULL, NULL); - } else { - ret = bdrv_block_status_above(blk_bs(s->src[src_cur]), NULL, - offset, count, &count, NULL, - NULL); - } + ret = bdrv_block_status_above(src_bs, base, offset, count, &count, + NULL, NULL); if (ret < 0) { if (s->salvage) { @@ -1754,6 +1784,16 @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num) n = DIV_ROUND_UP(count, BDRV_SECTOR_SIZE); + /* + * Avoid that s->sector_next_status becomes unaligned to the source + * request alignment and/or cluster size to avoid unnecessary read + * cycles. + */ + tail = (sector_num - src_cur_offset + n) % s->src_alignment[src_cur]; + if (n > tail) { + n -= tail; + } + if (ret & BDRV_BLOCK_ZERO) { s->status = post_backing_zero ? BLK_BACKING_FILE : BLK_ZERO; } else if (ret & BDRV_BLOCK_DATA) { @@ -2064,15 +2104,6 @@ static int convert_do_copy(ImgConvertState *s) s->has_zero_init = bdrv_has_zero_init(blk_bs(s->target)); } - if (!s->has_zero_init && !s->target_has_backing && - bdrv_can_write_zeroes_with_unmap(blk_bs(s->target))) - { - ret = blk_make_zero(s->target, BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK); - if (ret == 0) { - s->has_zero_init = true; - } - } - /* Allocate buffer for copied data. For compressed images, only one cluster * can be copied at a time. */ if (s->compressed) { @@ -2121,8 +2152,52 @@ static int convert_do_copy(ImgConvertState *s) return s->ret; } +static int convert_copy_bitmaps(BlockDriverState *src, BlockDriverState *dst) +{ + BdrvDirtyBitmap *bm; + Error *err = NULL; + + FOR_EACH_DIRTY_BITMAP(src, bm) { + const char *name; + + if (!bdrv_dirty_bitmap_get_persistence(bm)) { + continue; + } + name = bdrv_dirty_bitmap_name(bm); + qmp_block_dirty_bitmap_add(dst->node_name, name, + true, bdrv_dirty_bitmap_granularity(bm), + true, true, + true, !bdrv_dirty_bitmap_enabled(bm), + &err); + if (err) { + error_reportf_err(err, "Failed to create bitmap %s: ", name); + return -1; + } + + do_dirty_bitmap_merge(dst->node_name, name, src->node_name, name, + &err); + if (err) { + error_reportf_err(err, "Failed to populate bitmap %s: ", name); + return -1; + } + } + + return 0; +} + #define MAX_BUF_SECTORS 32768 +static void set_rate_limit(BlockBackend *blk, int64_t rate_limit) +{ + ThrottleConfig cfg; + + throttle_config_init(&cfg); + cfg.buckets[THROTTLE_BPS_WRITE].avg = rate_limit; + + blk_io_limits_enable(blk, CONVERT_THROTTLE_GROUP); + blk_set_io_limits(blk, &cfg); +} + static int img_convert(int argc, char **argv) { int c, bs_i, flags, src_flags = 0; @@ -2142,6 +2217,8 @@ static int img_convert(int argc, char **argv) int64_t ret = -EINVAL; bool force_share = false; bool explict_min_sparse = false; + bool bitmaps = false; + int64_t rate_limit = 0; ImgConvertState s = (ImgConvertState) { /* Need at least 4k of zeros for sparse detection */ @@ -2161,9 +2238,10 @@ static int img_convert(int argc, char **argv) {"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS}, {"salvage", no_argument, 0, OPTION_SALVAGE}, {"target-is-zero", no_argument, 0, OPTION_TARGET_IS_ZERO}, + {"bitmaps", no_argument, 0, OPTION_BITMAPS}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, ":hf:O:B:Cco:l:S:pt:T:qnm:WU", + c = getopt_long(argc, argv, ":hf:O:B:Cco:l:S:pt:T:qnm:WUr:", long_options, NULL); if (c == -1) { break; @@ -2260,6 +2338,12 @@ static int img_convert(int argc, char **argv) case 'U': force_share = true; break; + case 'r': + rate_limit = cvtnum("rate limit", optarg); + if (rate_limit < 0) { + goto fail_getopt; + } + break; case OPTION_OBJECT: { QemuOpts *object_opts; object_opts = qemu_opts_parse_noisily(&qemu_object_opts, @@ -2286,6 +2370,9 @@ static int img_convert(int argc, char **argv) */ s.has_zero_init = true; break; + case OPTION_BITMAPS: + bitmaps = true; + break; } } @@ -2320,8 +2407,8 @@ static int img_convert(int argc, char **argv) } if (skip_create && options) { - warn_report("-o has no effect when skipping image creation"); - warn_report("This will become an error in future QEMU versions."); + error_report("-o has no effect when skipping image creation"); + goto fail_getopt; } if (s.has_zero_init && !skip_create) { @@ -2347,7 +2434,6 @@ static int img_convert(int argc, char **argv) goto fail_getopt; } - /* ret is still -EINVAL until here */ ret = bdrv_parse_cache_mode(src_cache, &src_flags, &src_writethrough); if (ret < 0) { @@ -2364,8 +2450,10 @@ static int img_convert(int argc, char **argv) s.src = g_new0(BlockBackend *, s.src_num); s.src_sectors = g_new(int64_t, s.src_num); + s.src_alignment = g_new(int, s.src_num); for (bs_i = 0; bs_i < s.src_num; bs_i++) { + BlockDriverState *src_bs; s.src[bs_i] = img_open(image_opts, argv[optind + bs_i], fmt, src_flags, src_writethrough, s.quiet, force_share); @@ -2380,6 +2468,13 @@ static int img_convert(int argc, char **argv) ret = -1; goto out; } + src_bs = blk_bs(s.src[bs_i]); + s.src_alignment[bs_i] = DIV_ROUND_UP(src_bs->bl.request_alignment, + BDRV_SECTOR_SIZE); + if (!bdrv_get_info(src_bs, &bdi)) { + s.src_alignment[bs_i] = MAX(s.src_alignment[bs_i], + bdi.cluster_size / BDRV_SECTOR_SIZE); + } s.total_sectors += s.src_sectors[bs_i]; } @@ -2439,16 +2534,15 @@ static int img_convert(int argc, char **argv) opts = qemu_opts_create(create_opts, NULL, 0, &error_abort); if (options) { - qemu_opts_do_parse(opts, options, NULL, &local_err); - if (local_err) { + if (!qemu_opts_do_parse(opts, options, NULL, &local_err)) { error_report_err(local_err); ret = -1; goto out; } } - qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s.total_sectors * 512, - &error_abort); + qemu_opt_set_number(opts, BLOCK_OPT_SIZE, + s.total_sectors * BDRV_SECTOR_SIZE, &error_abort); ret = add_old_style_options(out_fmt, opts, out_baseimg, NULL); if (ret < 0) { goto out; @@ -2475,6 +2569,13 @@ static int img_convert(int argc, char **argv) goto out; } + if (out_baseimg_param) { + if (!qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT)) { + warn_report("Deprecated use of backing file without explicit " + "backing format"); + } + } + /* Check if compression is supported */ if (s.compressed) { bool encryption = @@ -2507,6 +2608,20 @@ static int img_convert(int argc, char **argv) } } + /* Determine if bitmaps need copying */ + if (bitmaps) { + if (s.src_num > 1) { + error_report("Copying bitmaps only possible with single source"); + ret = -1; + goto out; + } + if (!bdrv_supports_persistent_dirty_bitmap(blk_bs(s.src[0]))) { + error_report("Source lacks bitmap support"); + ret = -1; + goto out; + } + } + /* * The later open call will need any decryption secrets, and * bdrv_create() will purge "opts", so extract them now before @@ -2515,9 +2630,7 @@ static int img_convert(int argc, char **argv) if (!skip_create) { open_opts = qdict_new(); qemu_opt_foreach(opts, img_add_key_secrets, open_opts, &error_abort); - } - if (!skip_create) { /* Create the new image */ ret = bdrv_create(drv, out_filename, opts, &local_err); if (ret < 0) { @@ -2555,6 +2668,13 @@ static int img_convert(int argc, char **argv) } out_bs = blk_bs(s.target); + if (bitmaps && !bdrv_supports_persistent_dirty_bitmap(out_bs)) { + error_report("Format driver '%s' does not support bitmaps", + out_bs->drv->format_name); + ret = -1; + goto out; + } + if (s.compressed && !block_driver_can_compress(out_bs->drv)) { error_report("Compression not supported for this file format"); ret = -1; @@ -2596,7 +2716,8 @@ static int img_convert(int argc, char **argv) * s.target_backing_sectors has to be negative, which it will * be automatically). The backing file length is used only * for optimizations, so such a case is not fatal. */ - s.target_backing_sectors = bdrv_nb_sectors(out_bs->backing->bs); + s.target_backing_sectors = + bdrv_nb_sectors(bdrv_backing_chain_next(out_bs)); } else { s.target_backing_sectors = -1; } @@ -2610,10 +2731,19 @@ static int img_convert(int argc, char **argv) } else { s.compressed = s.compressed || bdi.needs_compressed_writes; s.cluster_sectors = bdi.cluster_size / BDRV_SECTOR_SIZE; - s.unallocated_blocks_are_zero = bdi.unallocated_blocks_are_zero; + } + + if (rate_limit) { + set_rate_limit(s.target, rate_limit); } ret = convert_do_copy(&s); + + /* Now copy the bitmaps */ + if (bitmaps && ret == 0) { + ret = convert_copy_bitmaps(blk_bs(s.src[0]), out_bs); + } + out: if (!ret) { qemu_progress_print(100, 0); @@ -2621,7 +2751,6 @@ out: qemu_progress_end(); qemu_opts_del(opts); qemu_opts_free(create_opts); - qemu_opts_del(sn_opts); qobject_unref(open_opts); blk_unref(s.target); if (s.src) { @@ -2631,7 +2760,9 @@ out: g_free(s.src); } g_free(s.src_sectors); + g_free(s.src_alignment); fail_getopt: + qemu_opts_del(sn_opts); g_free(options); return !!ret; @@ -2961,6 +3092,7 @@ static int get_block_status(BlockDriverState *bs, int64_t offset, depth = 0; for (;;) { + bs = bdrv_skip_filters(bs); ret = bdrv_block_status(bs, offset, bytes, &bytes, &map, &file); if (ret < 0) { return ret; @@ -2969,7 +3101,7 @@ static int get_block_status(BlockDriverState *bs, int64_t offset, if (ret & (BDRV_BLOCK_ZERO|BDRV_BLOCK_DATA)) { break; } - bs = backing_bs(bs); + bs = bdrv_cow_bs(bs); if (bs == NULL) { ret = 0; break; @@ -3144,12 +3276,9 @@ static int img_map(int argc, char **argv) curr.start = start_offset; while (curr.start + curr.length < length) { int64_t offset = curr.start + curr.length; - int64_t n; + int64_t n = length - offset; - /* Probe up to 1 GiB at a time. */ - n = MIN(1 * GiB, length - offset); ret = get_block_status(bs, offset, n, &next); - if (ret < 0) { error_report("Could not read file metadata: %s", strerror(-ret)); goto out; @@ -3354,6 +3483,7 @@ static int img_rebase(int argc, char **argv) uint8_t *buf_old = NULL; uint8_t *buf_new = NULL; BlockDriverState *bs = NULL, *prefix_chain_bs = NULL; + BlockDriverState *unfiltered_bs; char *filename; const char *fmt, *cache, *src_cache, *out_basefmt, *out_baseimg; int c, flags, src_flags, ret; @@ -3488,6 +3618,8 @@ static int img_rebase(int argc, char **argv) } bs = blk_bs(blk); + unfiltered_bs = bdrv_skip_filters(bs); + if (out_basefmt != NULL) { if (bdrv_find_format(out_basefmt) == NULL) { error_report("Invalid format name: '%s'", out_basefmt); @@ -3499,7 +3631,7 @@ static int img_rebase(int argc, char **argv) /* For safe rebasing we need to compare old and new backing file */ if (!unsafe) { QDict *options = NULL; - BlockDriverState *base_bs = backing_bs(bs); + BlockDriverState *base_bs = bdrv_cow_bs(unfiltered_bs); if (base_bs) { blk_old_backing = blk_new(qemu_get_aio_context(), @@ -3640,7 +3772,7 @@ static int img_rebase(int argc, char **argv) n = MIN(IO_BUF_SIZE, size - offset); /* If the cluster is allocated, we don't need to take action */ - ret = bdrv_is_allocated(bs, offset, n, &n); + ret = bdrv_is_allocated(unfiltered_bs, offset, n, &n); if (ret < 0) { error_report("error while reading image metadata: %s", strerror(-ret)); @@ -3655,8 +3787,9 @@ static int img_rebase(int argc, char **argv) * If cluster wasn't changed since prefix_chain, we don't need * to take action */ - ret = bdrv_is_allocated_above(backing_bs(bs), prefix_chain_bs, - false, offset, n, &n); + ret = bdrv_is_allocated_above(bdrv_cow_bs(unfiltered_bs), + prefix_chain_bs, false, + offset, n, &n); if (ret < 0) { error_report("error while reading image metadata: %s", strerror(-ret)); @@ -3734,9 +3867,10 @@ static int img_rebase(int argc, char **argv) * doesn't change when we switch the backing file. */ if (out_baseimg && *out_baseimg) { - ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt); + ret = bdrv_change_backing_file(unfiltered_bs, out_baseimg, out_basefmt, + true); } else { - ret = bdrv_change_backing_file(bs, NULL, NULL); + ret = bdrv_change_backing_file(unfiltered_bs, NULL, NULL, false); } if (ret == -ENOSPC) { @@ -3891,8 +4025,7 @@ static int img_resize(int argc, char **argv) /* Parse size */ param = qemu_opts_create(&resize_options, NULL, 0, &error_abort); - qemu_opt_set(param, BLOCK_OPT_SIZE, size, &err); - if (err) { + if (!qemu_opt_set(param, BLOCK_OPT_SIZE, size, &err)) { error_report_err(err); ret = -1; qemu_opts_del(param); @@ -3935,20 +4068,12 @@ static int img_resize(int argc, char **argv) } if (total_size < current_size && !shrink) { + error_report("Use the --shrink option to perform a shrink operation."); warn_report("Shrinking an image will delete all data beyond the " "shrunken image's end. Before performing such an " "operation, make sure there is no important data there."); - - if (g_strcmp0(bdrv_get_format_name(blk_bs(blk)), "raw") != 0) { - error_report( - "Use the --shrink option to perform a shrink operation."); - ret = -1; - goto out; - } else { - warn_report("Using the --shrink option will suppress this message. " - "Note that future versions of qemu-img may refuse to " - "shrink images without this option."); - } + ret = -1; + goto out; } /* @@ -3994,12 +4119,11 @@ static int print_amend_option_help(const char *format) return 1; } - /* Every driver supporting amendment must have create_opts */ - assert(drv->create_opts); + /* Every driver supporting amendment must have amend_opts */ + assert(drv->amend_opts); - printf("Creation options for '%s':\n", format); - qemu_opts_print_help(drv->create_opts, false); - printf("\nNote that not all of these options may be amendable.\n"); + printf("Amend options for '%s':\n", format); + qemu_opts_print_help(drv->amend_opts, false); return 0; } @@ -4008,7 +4132,7 @@ static int img_amend(int argc, char **argv) Error *err = NULL; int c, ret = 0; char *options = NULL; - QemuOptsList *create_opts = NULL; + QemuOptsList *amend_opts = NULL; QemuOpts *opts = NULL; const char *fmt = NULL, *filename, *cache; int flags; @@ -4017,6 +4141,7 @@ static int img_amend(int argc, char **argv) BlockBackend *blk = NULL; BlockDriverState *bs = NULL; bool image_opts = false; + bool force = false; cache = BDRV_DEFAULT_CACHE; for (;;) { @@ -4024,6 +4149,7 @@ static int img_amend(int argc, char **argv) {"help", no_argument, 0, 'h'}, {"object", required_argument, 0, OPTION_OBJECT}, {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, + {"force", no_argument, 0, OPTION_FORCE}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, ":ho:f:t:pq", @@ -4071,6 +4197,9 @@ static int img_amend(int argc, char **argv) case OPTION_IMAGE_OPTS: image_opts = true; break; + case OPTION_FORCE: + force = true; + break; } } @@ -4134,13 +4263,21 @@ static int img_amend(int argc, char **argv) goto out; } - /* Every driver supporting amendment must have create_opts */ - assert(bs->drv->create_opts); + /* Every driver supporting amendment must have amend_opts */ + assert(bs->drv->amend_opts); + + amend_opts = qemu_opts_append(amend_opts, bs->drv->amend_opts); + opts = qemu_opts_create(amend_opts, NULL, 0, &error_abort); + if (!qemu_opts_do_parse(opts, options, NULL, &err)) { + /* Try to parse options using the create options */ + amend_opts = qemu_opts_append(amend_opts, bs->drv->create_opts); + qemu_opts_del(opts); + opts = qemu_opts_create(amend_opts, NULL, 0, &error_abort); + if (qemu_opts_do_parse(opts, options, NULL, NULL)) { + error_append_hint(&err, + "This option is only supported for image creation\n"); + } - create_opts = qemu_opts_append(create_opts, bs->drv->create_opts); - opts = qemu_opts_create(create_opts, NULL, 0, &error_abort); - qemu_opts_do_parse(opts, options, NULL, &err); - if (err) { error_report_err(err); ret = -1; goto out; @@ -4148,7 +4285,7 @@ static int img_amend(int argc, char **argv) /* In case the driver does not call amend_status_cb() */ qemu_progress_print(0.f, 0); - ret = bdrv_amend_options(bs, opts, &amend_status_cb, NULL, &err); + ret = bdrv_amend_options(bs, opts, &amend_status_cb, NULL, force, &err); qemu_progress_print(100.f, 0); if (ret < 0) { error_report_err(err); @@ -4161,7 +4298,7 @@ out: out_no_progress: blk_unref(blk); qemu_opts_del(opts); - qemu_opts_free(create_opts); + qemu_opts_free(amend_opts); g_free(options); if (ret) { @@ -4674,14 +4811,19 @@ static int img_bitmap(int argc, char **argv) filename = argv[optind]; bitmap = argv[optind + 1]; - blk = img_open(image_opts, filename, fmt, BDRV_O_RDWR, false, false, - false); + /* + * No need to open backing chains; we will be manipulating bitmaps + * directly in this image without reference to image contents. + */ + blk = img_open(image_opts, filename, fmt, BDRV_O_RDWR | BDRV_O_NO_BACKING, + false, false, false); if (!blk) { goto out; } bs = blk_bs(blk); if (src_filename) { - src = img_open(false, src_filename, src_fmt, 0, false, false, false); + src = img_open(false, src_filename, src_fmt, BDRV_O_NO_BACKING, + false, false, false); if (!src) { goto out; } @@ -4714,21 +4856,11 @@ static int img_bitmap(int argc, char **argv) qmp_block_dirty_bitmap_disable(bs->node_name, bitmap, &err); op = "disable"; break; - case BITMAP_MERGE: { - BlockDirtyBitmapMergeSource *merge_src; - BlockDirtyBitmapMergeSourceList *list; - - merge_src = g_new0(BlockDirtyBitmapMergeSource, 1); - merge_src->type = QTYPE_QDICT; - merge_src->u.external.node = g_strdup(src_bs->node_name); - merge_src->u.external.name = g_strdup(act->src); - list = g_new0(BlockDirtyBitmapMergeSourceList, 1); - list->value = merge_src; - qmp_block_dirty_bitmap_merge(bs->node_name, bitmap, list, &err); - qapi_free_BlockDirtyBitmapMergeSourceList(list); + case BITMAP_MERGE: + do_dirty_bitmap_merge(bs->node_name, bitmap, src_bs->node_name, + act->src, &err); op = "merge"; break; - } default: g_assert_not_reached(); } @@ -5282,8 +5414,7 @@ static int img_measure(int argc, char **argv) create_opts = qemu_opts_append(create_opts, bdrv_file.create_opts); opts = qemu_opts_create(create_opts, NULL, 0, &error_abort); if (options) { - qemu_opts_do_parse(opts, options, NULL, &local_err); - if (local_err) { + if (!qemu_opts_do_parse(opts, options, NULL, &local_err)) { error_report_err(local_err); error_report("Invalid options for file format '%s'", out_fmt); goto out; @@ -5302,6 +5433,9 @@ static int img_measure(int argc, char **argv) if (output_format == OFORMAT_HUMAN) { printf("required size: %" PRIu64 "\n", info->required); printf("fully allocated size: %" PRIu64 "\n", info->fully_allocated); + if (info->has_bitmaps) { + printf("bitmaps size: %" PRIu64 "\n", info->bitmaps); + } } else { dump_json_block_measure_info(info); } @@ -5332,7 +5466,6 @@ int main(int argc, char **argv) const img_cmd_t *cmd; const char *cmdname; Error *local_error = NULL; - char *trace_file = NULL; int c; static const struct option long_options[] = { {"help", no_argument, 0, 'h'}, @@ -5345,6 +5478,7 @@ int main(int argc, char **argv) signal(SIGPIPE, SIG_IGN); #endif + socket_init(); error_init(argv[0]); module_call_init(MODULE_INIT_TRACE); qemu_init_exec_dir(argv[0]); @@ -5381,8 +5515,7 @@ int main(int argc, char **argv) printf(QEMU_IMG_VERSION); return 0; case 'T': - g_free(trace_file); - trace_file = trace_opt_parse(optarg); + trace_opt_parse(optarg); break; } } @@ -5400,7 +5533,7 @@ int main(int argc, char **argv) if (!trace_init_backends()) { exit(1); } - trace_init_file(trace_file); + trace_init_file(); qemu_set_log(LOG_TRACE); /* find the command */ diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index 851f07e8f8b9bcb460d4bcfb7ea231e41b82797b..4153f1c0b02605cdc4af9cff54009b9e48307d92 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -1715,7 +1715,7 @@ static int truncate_f(BlockBackend *blk, int argc, char **argv) * exact=true. It is better to err on the "emit more errors" side * than to be overly permissive. */ - ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, 0, &local_err); + ret = blk_truncate(blk, offset, false, PREALLOC_MODE_OFF, 0, &local_err); if (ret < 0) { error_report_err(local_err); return ret; @@ -2383,14 +2383,7 @@ static const cmdinfo_t sleep_cmd = { static void help_oneline(const char *cmd, const cmdinfo_t *ct) { - if (cmd) { - printf("%s ", cmd); - } else { - printf("%s ", ct->name); - if (ct->altname) { - printf("(or %s) ", ct->altname); - } - } + printf("%s ", cmd); if (ct->args) { printf("%s ", ct->args); @@ -2420,7 +2413,7 @@ static int help_f(BlockBackend *blk, int argc, char **argv) { const cmdinfo_t *ct; - if (argc == 1) { + if (argc < 2) { help_all(); return 0; } diff --git a/qemu-io.c b/qemu-io.c index 3adc5a7d0d3f77073f4a95684fcec58ad015a289..ac88d8bd40f7c1b4b8e3a48cb0b9784b6848ff86 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -25,6 +25,7 @@ #include "qemu/config-file.h" #include "qemu/readline.h" #include "qemu/log.h" +#include "qemu/sockets.h" #include "qapi/qmp/qstring.h" #include "qapi/qmp/qdict.h" #include "qom/object_interfaces.h" @@ -535,13 +536,13 @@ int main(int argc, char **argv) Error *local_error = NULL; QDict *opts = NULL; const char *format = NULL; - char *trace_file = NULL; bool force_share = false; #ifdef CONFIG_POSIX signal(SIGPIPE, SIG_IGN); #endif + socket_init(); error_init(argv[0]); module_call_init(MODULE_INIT_TRACE); qemu_init_exec_dir(argv[0]); @@ -599,8 +600,7 @@ int main(int argc, char **argv) } break; case 'T': - g_free(trace_file); - trace_file = trace_opt_parse(optarg); + trace_opt_parse(optarg); break; case 'V': printf("%s version " QEMU_FULL_VERSION "\n" @@ -651,7 +651,7 @@ int main(int argc, char **argv) if (!trace_init_backends()) { exit(1); } - trace_init_file(trace_file); + trace_init_file(); qemu_set_log(LOG_TRACE); /* initialize commands */ diff --git a/qemu-nbd.c b/qemu-nbd.c index 306e44fb0a4b0d5ed60c10fdf3ca78daa2bfbfaa..a7075c5419d710d773a5c5ed749f9e75f32c4aed 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -25,6 +25,7 @@ #include "qapi/error.h" #include "qemu/cutils.h" #include "sysemu/block-backend.h" +#include "sysemu/runstate.h" /* for qemu_system_killed() prototype */ #include "block/block_int.h" #include "block/nbd.h" #include "qemu/main-loop.h" @@ -65,12 +66,11 @@ #define MBR_SIZE 512 -static NBDExport *export; static int verbose; static char *srcpath; static SocketAddress *saddr; static int persistent = 0; -static enum { RUNNING, TERMINATE, TERMINATING, TERMINATED } state; +static enum { RUNNING, TERMINATE, TERMINATED } state; static int shared = 1; static int nb_fds; static QIONetListener *server; @@ -100,6 +100,7 @@ static void usage(const char *name) "\n" "Exposing part of the image:\n" " -o, --offset=OFFSET offset into the image\n" +" -A, --allocation-depth expose the allocation depth\n" " -B, --bitmap=NAME expose a persistent dirty bitmap\n" "\n" "General purpose options:\n" @@ -155,12 +156,17 @@ QEMU_COPYRIGHT "\n" , name); } -static void termsig_handler(int signum) +#ifdef CONFIG_POSIX +/* + * The client thread uses SIGTERM to interrupt the server. A signal + * handler ensures that "qemu-nbd -v -c" exits with a nice status code. + */ +void qemu_system_killed(int signum, pid_t pid) { - atomic_cmpxchg(&state, RUNNING, TERMINATE); + qatomic_cmpxchg(&state, RUNNING, TERMINATE); qemu_notify_event(); } - +#endif /* CONFIG_POSIX */ static int qemu_nbd_client_list(SocketAddress *saddr, QCryptoTLSCreds *tls, const char *hostname) @@ -331,12 +337,6 @@ static int nbd_can_accept(void) return state == RUNNING && nb_fds < shared; } -static void nbd_export_closed(NBDExport *export) -{ - assert(state == TERMINATING); - state = TERMINATED; -} - static void nbd_update_server_watch(void); static void nbd_client_closed(NBDClient *client, bool negotiated) @@ -523,10 +523,9 @@ int main(int argc, char **argv) const char *port = NULL; char *sockpath = NULL; char *device = NULL; - int64_t fd_size; QemuOpts *sn_opts = NULL; const char *sn_id_or_name = NULL; - const char *sopt = "hVb:o:p:rsnc:dvk:e:f:tl:x:T:D:B:L"; + const char *sopt = "hVb:o:p:rsnc:dvk:e:f:tl:x:T:D:AB:L"; struct option lopt[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, @@ -535,6 +534,7 @@ int main(int argc, char **argv) { "socket", required_argument, NULL, 'k' }, { "offset", required_argument, NULL, 'o' }, { "read-only", no_argument, NULL, 'r' }, + { "allocation-depth", no_argument, NULL, 'A' }, { "bitmap", required_argument, NULL, 'B' }, { "connect", required_argument, NULL, 'c' }, { "disconnect", no_argument, NULL, 'd' }, @@ -576,29 +576,24 @@ int main(int argc, char **argv) QDict *options = NULL; const char *export_name = NULL; /* defaults to "" later for server mode */ const char *export_description = NULL; - const char *bitmap = NULL; + strList *bitmaps = NULL; + bool alloc_depth = false; const char *tlscredsid = NULL; bool imageOpts = false; bool writethrough = true; - char *trace_file = NULL; bool fork_process = false; bool list = false; int old_stderr = -1; unsigned socket_activation; const char *pid_file_name = NULL; - - /* The client thread uses SIGTERM to interrupt the server. A signal - * handler ensures that "qemu-nbd -v -c" exits with a nice status code. - */ - struct sigaction sa_sigterm; - memset(&sa_sigterm, 0, sizeof(sa_sigterm)); - sa_sigterm.sa_handler = termsig_handler; - sigaction(SIGTERM, &sa_sigterm, NULL); + BlockExportOptions *export_opts; #ifdef CONFIG_POSIX - signal(SIGPIPE, SIG_IGN); + os_setup_early_signal_handling(); + os_setup_signal_handling(); #endif + socket_init(); error_init(argv[0]); module_call_init(MODULE_INIT_TRACE); qcrypto_init(&error_fatal); @@ -696,8 +691,11 @@ int main(int argc, char **argv) readonly = true; flags &= ~BDRV_O_RDWR; break; + case 'A': + alloc_depth = true; + break; case 'B': - bitmap = optarg; + QAPI_LIST_PREPEND(bitmaps, g_strdup(optarg)); break; case 'k': sockpath = optarg; @@ -769,8 +767,7 @@ int main(int argc, char **argv) imageOpts = true; break; case 'T': - g_free(trace_file); - trace_file = trace_opt_parse(optarg); + trace_opt_parse(optarg); break; case QEMU_NBD_OPT_TLSAUTHZ: tlsauthz = optarg; @@ -793,8 +790,8 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } if (export_name || export_description || dev_offset || - device || disconnect || fmt || sn_id_or_name || bitmap || - seen_aio || seen_discard || seen_cache) { + device || disconnect || fmt || sn_id_or_name || bitmaps || + alloc_depth || seen_aio || seen_discard || seen_cache) { error_report("List mode is incompatible with per-device settings"); exit(EXIT_FAILURE); } @@ -817,7 +814,7 @@ int main(int argc, char **argv) if (!trace_init_backends()) { exit(1); } - trace_init_file(trace_file); + trace_init_file(); qemu_set_log(LOG_TRACE); socket_activation = check_socket_activation(); @@ -856,8 +853,7 @@ int main(int argc, char **argv) } tlscreds = nbd_get_tls_creds(tlscredsid, list, &local_err); if (local_err) { - error_report("Failed to get TLS creds %s", - error_get_pretty(local_err)); + error_reportf_err(local_err, "Failed to get TLS creds: "); exit(EXIT_FAILURE); } } else { @@ -896,6 +892,7 @@ int main(int argc, char **argv) #endif if ((device && !verbose) || fork_process) { +#ifndef WIN32 int stderr_fd[2]; pid_t pid; int ret; @@ -959,6 +956,10 @@ int main(int argc, char **argv) */ exit(errors); } +#else /* WIN32 */ + error_report("Unable to fork into background on Windows hosts"); + exit(EXIT_FAILURE); +#endif /* WIN32 */ } if (device != NULL && sockpath == NULL) { @@ -983,8 +984,8 @@ int main(int argc, char **argv) &local_err); if (sioc == NULL) { object_unref(OBJECT(server)); - error_report("Failed to use socket activation: %s", - error_get_pretty(local_err)); + error_reportf_err(local_err, + "Failed to use socket activation: "); exit(EXIT_FAILURE); } qio_net_listener_add(server, sioc); @@ -1029,6 +1030,17 @@ int main(int argc, char **argv) } bs = blk_bs(blk); + if (dev_offset) { + QDict *raw_opts = qdict_new(); + qdict_put_str(raw_opts, "driver", "raw"); + qdict_put_str(raw_opts, "file", bs->node_name); + qdict_put_int(raw_opts, "offset", dev_offset); + bs = bdrv_open(NULL, NULL, raw_opts, flags, &error_fatal); + blk_remove_bs(blk); + blk_insert_bs(blk, bs, &error_fatal); + bdrv_unref(bs); + } + blk_set_enable_write_cache(blk, !writethrough); if (sn_opts) { @@ -1046,24 +1058,31 @@ int main(int argc, char **argv) } bs->detect_zeroes = detect_zeroes; - fd_size = blk_getlength(blk); - if (fd_size < 0) { - error_report("Failed to determine the image length: %s", - strerror(-fd_size)); - exit(EXIT_FAILURE); - } - if (dev_offset >= fd_size) { - error_report("Offset (%" PRIu64 ") has to be smaller than the image " - "size (%" PRId64 ")", dev_offset, fd_size); - exit(EXIT_FAILURE); - } - fd_size -= dev_offset; - - export = nbd_export_new(bs, dev_offset, fd_size, export_name, - export_description, bitmap, readonly, shared > 1, - nbd_export_closed, writethrough, NULL, - &error_fatal); + nbd_server_is_qemu_nbd(true); + + export_opts = g_new(BlockExportOptions, 1); + *export_opts = (BlockExportOptions) { + .type = BLOCK_EXPORT_TYPE_NBD, + .id = g_strdup("qemu-nbd-export"), + .node_name = g_strdup(bdrv_get_node_name(bs)), + .has_writethrough = true, + .writethrough = writethrough, + .has_writable = true, + .writable = !readonly, + .u.nbd = { + .has_name = true, + .name = g_strdup(export_name), + .has_description = !!export_description, + .description = g_strdup(export_description), + .has_bitmaps = !!bitmaps, + .bitmaps = bitmaps, + .has_allocation_depth = alloc_depth, + .allocation_depth = alloc_depth, + }, + }; + blk_exp_add(export_opts, &error_fatal); + qapi_free_BlockExportOptions(export_opts); if (device) { #if HAVE_NBD_DEVICE @@ -1103,10 +1122,8 @@ int main(int argc, char **argv) do { main_loop_wait(false); if (state == TERMINATE) { - state = TERMINATING; - nbd_export_close(export); - nbd_export_put(export); - export = NULL; + blk_exp_close_all(); + state = TERMINATED; } } while (state != TERMINATED); diff --git a/qemu-options.hx b/qemu-options.hx index 93bde2bbc8b27479ac4cd82a7fdedb144f96b61e..104632ea3431886172bfa0c4e0e05d402bf8e2c4 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -34,7 +34,6 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \ " dea-key-wrap=on|off controls support for DEA key wrapping (default=on)\n" " suppress-vmdesc=on|off disables self-describing migration (default=off)\n" " nvdimm=on|off controls NVDIMM support (default=off)\n" - " enforce-config-section=on|off enforce configuration section migration (default=off)\n" " memory-encryption=@var{} memory encryption object to use (default=none)\n" " hmat=on|off controls ACPI HMAT support (default=off)\n", QEMU_ARCH_ALL) @@ -91,13 +90,6 @@ SRST ``nvdimm=on|off`` Enables or disables NVDIMM support. The default is off. - ``enforce-config-section=on|off`` - If ``enforce-config-section`` is set to on, force migration code - to send configuration section even if the machine-type sets the - ``migration.send-configuration`` property to off. NOTE: this - parameter is deprecated. Please use ``-global`` - ``migration.send-configuration``\ =on\|off instead. - ``memory-encryption=`` Memory encryption object to use. The default is none. @@ -239,10 +231,11 @@ SRST -numa node,nodeid=0 -numa node,nodeid=1 \ -numa cpu,node-id=0,socket-id=0 -numa cpu,node-id=1,socket-id=1 - '\ ``mem``\ ' assigns a given RAM amount to a node. '\ ``memdev``\ ' - assigns RAM from a given memory backend device to a node. If - '\ ``mem``\ ' and '\ ``memdev``\ ' are omitted in all nodes, RAM is - split equally between them. + Legacy '\ ``mem``\ ' assigns a given RAM amount to a node (not supported + for 5.1 and newer machine types). '\ ``memdev``\ ' assigns RAM from + a given memory backend device to a node. If '\ ``mem``\ ' and + '\ ``memdev``\ ' are omitted in all nodes, RAM is split equally between them. + '\ ``mem``\ ' and '\ ``memdev``\ ' are mutually exclusive. Furthermore, if one node uses '\ ``memdev``\ ', all of them have to @@ -372,9 +365,9 @@ SRST .. parsed-literal:: - |qemu_system| \ - -add-fd fd=3,set=2,opaque="rdwr:/path/to/file" \ - -add-fd fd=4,set=2,opaque="rdonly:/path/to/file" \ + |qemu_system| \\ + -add-fd fd=3,set=2,opaque="rdwr:/path/to/file" \\ + -add-fd fd=4,set=2,opaque="rdonly:/path/to/file" \\ -drive file=/dev/fdset/2,index=0,media=disk ERST @@ -805,7 +798,7 @@ SRST Some drivers are: -``-device ipmi-bmc-sim,id=id[,slave_addr=val][,sdrfile=file][,furareasize=val][,furdatafile=file][,guid=uuid]`` +``-device ipmi-bmc-sim,id=id[,prop[=value][,...]]`` Add an IPMI BMC. This is a simulation of a hardware management interface processor that normally sits on a system. It provides a watchdog and the ability to reset and power control the system. You @@ -875,6 +868,15 @@ SRST ``-device isa-ipmi-bt,bmc=id[,ioport=val][,irq=val]`` Like the KCS interface, but defines a BT interface. The default port is 0xe4 and the default interrupt is 5. + +``-device pci-ipmi-kcs,bmc=id`` + Add a KCS IPMI interafce on the PCI bus. + + ``bmc=id`` + The BMC to connect to, one of ipmi-bmc-sim or ipmi-bmc-extern above. + +``-device pci-ipmi-bt,bmc=id`` + Like the KCS interface, but defines a BT interface on the PCI bus. ERST DEF("name", HAS_ARG, QEMU_OPTION_name, @@ -911,8 +913,8 @@ SRST ``-fda file`` \ ``-fdb file`` - Use file as floppy disk 0/1 image (see - :ref:`disk_005fimages`). + Use file as floppy disk 0/1 image (see the :ref:`disk images` chapter in + the System Emulation Users Guide). ERST DEF("hda", HAS_ARG, QEMU_OPTION_hda, @@ -929,8 +931,8 @@ SRST ``-hdc file`` \ ``-hdd file`` - Use file as hard disk 0, 1, 2 or 3 image (see - :ref:`disk_005fimages`). + Use file as hard disk 0, 1, 2 or 3 image (see the :ref:`disk images` + chapter in the System Emulation Users Guide). ERST DEF("cdrom", HAS_ARG, QEMU_OPTION_cdrom, @@ -1043,7 +1045,8 @@ SRST The path to the image file in the local filesystem ``aio`` - Specifies the AIO backend (threads/native, default: threads) + Specifies the AIO backend (threads/native/io_uring, + default: threads) ``locking`` Specifies whether the image file is protected with Linux OFD @@ -1165,7 +1168,8 @@ DEF("drive", HAS_ARG, QEMU_OPTION_drive, "-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n" " [,cache=writethrough|writeback|none|directsync|unsafe][,format=f]\n" " [,snapshot=on|off][,rerror=ignore|stop|report]\n" - " [,werror=ignore|stop|report|enospc][,id=name][,aio=threads|native]\n" + " [,werror=ignore|stop|report|enospc][,id=name]\n" + " [,aio=threads|native|io_uring]\n" " [,readonly=on|off][,copy-on-read=on|off]\n" " [,discard=ignore|unmap][,detect-zeroes=on|off|unmap]\n" " [[,bps=b]|[[,bps_rd=r][,bps_wr=w]]]\n" @@ -1185,9 +1189,9 @@ SRST In addition, it knows the following options: ``file=file`` - This option defines which disk image (see - :ref:`disk_005fimages`) to use with this drive. If - the filename contains comma, you must double it (for instance, + This option defines which disk image (see the :ref:`disk images` + chapter in the System Emulation Users Guide) to use with this drive. + If the filename contains comma, you must double it (for instance, "file=my,,file" to use file "my,file"). Special files such as iSCSI devices can be specified using @@ -1237,8 +1241,8 @@ SRST The default mode is ``cache=writeback``. ``aio=aio`` - aio is "threads", or "native" and selects between pthread based - disk I/O and native Linux AIO. + aio is "threads", "native", or "io_uring" and selects between pthread + based disk I/O, native Linux AIO, or Linux io_uring API. ``format=format`` Specify which disk format will be used rather than detecting the @@ -1328,9 +1332,9 @@ SRST .. parsed-literal:: - |qemu_system| \ - -add-fd fd=3,set=2,opaque="rdwr:/path/to/file" \ - -add-fd fd=4,set=2,opaque="rdonly:/path/to/file" \ + |qemu_system| \\ + -add-fd fd=3,set=2,opaque="rdwr:/path/to/file" \\ + -add-fd fd=4,set=2,opaque="rdonly:/path/to/file" \\ -drive file=/dev/fdset/2,index=0,media=disk You can connect a CDROM to the slave of ide0: @@ -1396,8 +1400,8 @@ SRST ``-snapshot`` Write to temporary files instead of disk image files. In this case, the raw disk image you use is not written back. You can however - force the write back by pressing C-a s (see - :ref:`disk_005fimages`). + force the write back by pressing C-a s (see the :ref:`disk images` + chapter in the System Emulation Users Guide). ERST DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev, @@ -1683,8 +1687,8 @@ DEF("usbdevice", HAS_ARG, QEMU_OPTION_usbdevice, SRST ``-usbdevice devname`` Add the USB device devname. Note that this option is deprecated, - please use ``-device usb-...`` instead. See - :ref:`usb_005fdevices`. + please use ``-device usb-...`` instead. See the chapter about + :ref:`Connecting USB devices` in the System Emulation Users Guide. ``mouse`` Virtual Mouse. This will override the PS/2 mouse emulation when @@ -2106,7 +2110,7 @@ SRST connections. The password must be set separately using the ``set_password`` - command in the :ref:`pcsys_005fmonitor`. The + command in the :ref:`QEMU monitor`. The syntax to change your password is: ``set_password `` where could be either "vnc" or "spice". @@ -2151,8 +2155,8 @@ SRST and 'x509' settings to enable use of SSL and server certificates. This ensures a data encryption preventing compromise of authentication credentials. See the - :ref:`vnc_005fsecurity` section for details on - using SASL authentication. + :ref:`VNC security` section in the System Emulation Users Guide + for details on using SASL authentication. ``sasl-authz=ID`` Provides the ID of the QAuthZ authorization object against which @@ -2284,8 +2288,10 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios, " [,sku=str]\n" " specify SMBIOS type 3 fields\n" "-smbios type=4[,sock_pfx=str][,manufacturer=str][,version=str][,serial=str]\n" - " [,asset=str][,part=str]\n" + " [,asset=str][,part=str][,max-speed=%d][,current-speed=%d]\n" " specify SMBIOS type 4 fields\n" + "-smbios type=11[,value=str][,path=filename]\n" + " specify SMBIOS type 11 fields\n" "-smbios type=17[,loc_pfx=str][,bank=str][,manufacturer=str][,serial=str]\n" " [,asset=str][,part=str][,speed=%d]\n" " specify SMBIOS type 17 fields\n", @@ -2309,6 +2315,45 @@ SRST ``-smbios type=4[,sock_pfx=str][,manufacturer=str][,version=str][,serial=str][,asset=str][,part=str]`` Specify SMBIOS type 4 fields +``-smbios type=11[,value=str][,path=filename]`` + Specify SMBIOS type 11 fields + + This argument can be repeated multiple times, and values are added in the order they are parsed. + Applications intending to use OEM strings data are encouraged to use their application name as + a prefix for the value string. This facilitates passing information for multiple applications + concurrently. + + The ``value=str`` syntax provides the string data inline, while the ``path=filename`` syntax + loads data from a file on disk. Note that the file is not permitted to contain any NUL bytes. + + Both the ``value`` and ``path`` options can be repeated multiple times and will be added to + the SMBIOS table in the order in which they appear. + + Note that on the x86 architecture, the total size of all SMBIOS tables is limited to 65535 + bytes. Thus the OEM strings data is not suitable for passing large amounts of data into the + guest. Instead it should be used as a indicator to inform the guest where to locate the real + data set, for example, by specifying the serial ID of a block device. + + An example passing three strings is + + .. parsed-literal:: + + -smbios type=11,value=cloud-init:ds=nocloud-net;s=http://10.10.0.1:8000/,\\ + value=anaconda:method=http://dl.fedoraproject.org/pub/fedora/linux/releases/25/x86_64/os,\\ + path=/some/file/with/oemstringsdata.txt + + In the guest OS this is visible with the ``dmidecode`` command + + .. parsed-literal:: + + $ dmidecode -t 11 + Handle 0x0E00, DMI type 11, 5 bytes + OEM Strings + String 1: cloud-init:ds=nocloud-net;s=http://10.10.0.1:8000/ + String 2: anaconda:method=http://dl.fedoraproject.org/pub/fedora/linux/releases/25/x86_64/os + String 3: myapp:some extra data + + ``-smbios type=17[,loc_pfx=str][,bank=str][,manufacturer=str][,serial=str][,asset=str][,part=str][,speed=%d]`` Specify SMBIOS type 17 fields ERST @@ -2417,6 +2462,10 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, #ifdef CONFIG_POSIX "-netdev vhost-user,id=str,chardev=dev[,vhostforce=on|off]\n" " configure a vhost-user network, backed by a chardev 'dev'\n" +#endif +#ifdef __linux__ + "-netdev vhost-vdpa,id=str,vhostdev=/path/to/dev\n" + " configure a vhost-vdpa network,Establish a vhost-vdpa netdev\n" #endif "-netdev hubport,id=str,hubid=n[,netdev=nd]\n" " configure a hub port on the hub with ID 'n'\n", QEMU_ARCH_ALL) @@ -2579,7 +2628,7 @@ SRST .. parsed-literal:: - |qemu_system| -hda linux.img -boot n -device e1000,netdev=n1 \ + |qemu_system| -hda linux.img -boot n -device e1000,netdev=n1 \\ -netdev user,id=n1,tftp=/path/to/tftp/files,bootfile=/pxelinux.0 ``smb=dir[,smbserver=addr]`` @@ -2670,7 +2719,7 @@ SRST disable script execution. If running QEMU as an unprivileged user, use the network helper - helper to configure the TAP interface and attach it to the bridge. + to configure the TAP interface and attach it to the bridge. The default network helper executable is ``/path/to/qemu-bridge-helper`` and the default bridge device is ``br0``. @@ -2689,15 +2738,15 @@ SRST #launch a QEMU instance with two NICs, each one connected #to a TAP device - |qemu_system| linux.img \ - -netdev tap,id=nd0,ifname=tap0 -device e1000,netdev=nd0 \ + |qemu_system| linux.img \\ + -netdev tap,id=nd0,ifname=tap0 -device e1000,netdev=nd0 \\ -netdev tap,id=nd1,ifname=tap1 -device rtl8139,netdev=nd1 .. parsed-literal:: #launch a QEMU instance with the default network helper to #connect a TAP device to bridge br0 - |qemu_system| linux.img -device virtio-net-pci,netdev=n1 \ + |qemu_system| linux.img -device virtio-net-pci,netdev=n1 \\ -netdev tap,id=n1,"helper=/path/to/qemu-bridge-helper" ``-netdev bridge,id=id[,br=bridge][,helper=helper]`` @@ -2735,12 +2784,12 @@ SRST .. parsed-literal:: # launch a first QEMU instance - |qemu_system| linux.img \ - -device e1000,netdev=n1,mac=52:54:00:12:34:56 \ + |qemu_system| linux.img \\ + -device e1000,netdev=n1,mac=52:54:00:12:34:56 \\ -netdev socket,id=n1,listen=:1234 # connect the network of this instance to the network of the first instance - |qemu_system| linux.img \ - -device e1000,netdev=n2,mac=52:54:00:12:34:57 \ + |qemu_system| linux.img \\ + -device e1000,netdev=n2,mac=52:54:00:12:34:57 \\ -netdev socket,id=n2,connect=127.0.0.1:1234 ``-netdev socket,id=id[,fd=h][,mcast=maddr:port[,localaddr=addr]]`` @@ -2762,16 +2811,16 @@ SRST .. parsed-literal:: # launch one QEMU instance - |qemu_system| linux.img \ - -device e1000,netdev=n1,mac=52:54:00:12:34:56 \ + |qemu_system| linux.img \\ + -device e1000,netdev=n1,mac=52:54:00:12:34:56 \\ -netdev socket,id=n1,mcast=230.0.0.1:1234 # launch another QEMU instance on same "bus" - |qemu_system| linux.img \ - -device e1000,netdev=n2,mac=52:54:00:12:34:57 \ + |qemu_system| linux.img \\ + -device e1000,netdev=n2,mac=52:54:00:12:34:57 \\ -netdev socket,id=n2,mcast=230.0.0.1:1234 # launch yet another QEMU instance on same "bus" - |qemu_system| linux.img \ - -device e1000,netdev=n3,mac=52:54:00:12:34:58 \ + |qemu_system| linux.img \\ + -device e1000,netdev=n3,mac=52:54:00:12:34:58 \\ -netdev socket,id=n3,mcast=230.0.0.1:1234 Example (User Mode Linux compat.): @@ -2779,8 +2828,8 @@ SRST .. parsed-literal:: # launch QEMU instance (note mcast address selected is UML's default) - |qemu_system| linux.img \ - -device e1000,netdev=n1,mac=52:54:00:12:34:56 \ + |qemu_system| linux.img \\ + -device e1000,netdev=n1,mac=52:54:00:12:34:56 \\ -netdev socket,id=n1,mcast=239.192.168.1:1102 # launch UML /path/to/linux ubd0=/path/to/root_fs eth0=mcast @@ -2789,8 +2838,8 @@ SRST .. parsed-literal:: - |qemu_system| linux.img \ - -device e1000,netdev=n1,mac=52:54:00:12:34:56 \ + |qemu_system| linux.img \\ + -device e1000,netdev=n1,mac=52:54:00:12:34:56 \\ -netdev socket,id=n1,mcast=239.192.168.1:1102,localaddr=1.2.3.4 ``-netdev l2tpv3,id=id,src=srcaddr,dst=dstaddr[,srcport=srcport][,dstport=dstport],txsession=txsession[,rxsession=rxsession][,ipv6][,udp][,cookie64][,counter][,pincounter][,txcookie=txcookie][,rxcookie=rxcookie][,offset=offset]`` @@ -2846,9 +2895,9 @@ SRST # Setup tunnel on linux host using raw ip as encapsulation # on 1.2.3.4 - ip l2tp add tunnel remote 4.3.2.1 local 1.2.3.4 tunnel_id 1 peer_tunnel_id 1 \ + ip l2tp add tunnel remote 4.3.2.1 local 1.2.3.4 tunnel_id 1 peer_tunnel_id 1 \\ encap udp udp_sport 16384 udp_dport 16384 - ip l2tp add session tunnel_id 1 name vmtunnel0 session_id \ + ip l2tp add session tunnel_id 1 name vmtunnel0 session_id \\ 0xFFFFFFFF peer_session_id 0xFFFFFFFF ifconfig vmtunnel0 mtu 1500 ifconfig vmtunnel0 up @@ -2858,7 +2907,7 @@ SRST # on 4.3.2.1 # launch QEMU instance - if your network has reorder or is very lossy add ,pincounter - |qemu_system| linux.img -device e1000,netdev=n1 \ + |qemu_system| linux.img -device e1000,netdev=n1 \\ -netdev l2tpv3,id=n1,src=4.2.3.1,dst=1.2.3.4,udp,srcport=16384,dstport=16384,rxsession=0xffffffff,txsession=0xffffffff,counter ``-netdev vde,id=id[,sock=socketpath][,port=n][,group=groupname][,mode=octalmode]`` @@ -2896,6 +2945,14 @@ SRST -netdev type=vhost-user,id=net0,chardev=chr0 \ -device virtio-net-pci,netdev=net0 +``-netdev vhost-vdpa,vhostdev=/path/to/dev`` + Establish a vhost-vdpa netdev. + + vDPA device is a device that uses a datapath which complies with + the virtio specifications with a vendor specific control path. + vDPA devices can be both physically located on the hardware or + emulated by software. + ``-netdev hubport,id=id,hubid=hubid[,netdev=nd]`` Create a hub port on the emulated hub with ID hubid. @@ -3025,7 +3082,9 @@ The general form of a character device option is: -serial chardev:char1 When you're using a multiplexed character device, some escape - sequences are interpreted in the input. See :ref:`mux_005fkeys`. + sequences are interpreted in the input. See the chapter about + :ref:`keys in the character backend multiplexer` in the + System Emulation Users Guide for more details. Note that some other command line options may implicitly create multiplexed character backends; for instance ``-serial mon:stdio`` @@ -3698,8 +3757,8 @@ DEF("gdb", HAS_ARG, QEMU_OPTION_gdb, \ QEMU_ARCH_ALL) SRST ``-gdb dev`` - Accept a gdb connection on device dev (see - :ref:`gdb_005fusage`). Note that this option does not pause QEMU + Accept a gdb connection on device dev (see the :ref:`GDB usage` chapter + in the System Emulation Users Guide). Note that this option does not pause QEMU execution -- if you want QEMU to not start the guest until you connect with gdb and issue a ``continue`` command, you will need to also pass the ``-S`` option to QEMU. @@ -3724,7 +3783,7 @@ DEF("s", 0, QEMU_OPTION_s, \ SRST ``-s`` Shorthand for -gdb tcp::1234, i.e. open a gdbserver on TCP port 1234 - (see :ref:`gdb_005fusage`). + (see the :ref:`GDB usage` chapter in the System Emulation Users Guide). ERST DEF("d", HAS_ARG, QEMU_OPTION_d, \ @@ -4286,20 +4345,23 @@ SRST Enable FIPS 140-2 compliance mode. ERST -HXCOMM Deprecated by -accel tcg -DEF("no-kvm", 0, QEMU_OPTION_no_kvm, "", QEMU_ARCH_I386) - DEF("msg", HAS_ARG, QEMU_OPTION_msg, - "-msg timestamp[=on|off]\n" + "-msg [timestamp[=on|off]][,guest-name=[on|off]]\n" " control error message format\n" - " timestamp=on enables timestamps (default: off)\n", + " timestamp=on enables timestamps (default: off)\n" + " guest-name=on enables guest name prefix but only if\n" + " -name guest option is set (default: off)\n", QEMU_ARCH_ALL) SRST -``-msg timestamp[=on|off]`` +``-msg [timestamp[=on|off]][,guest-name[=on|off]]`` Control error message format. ``timestamp=on|off`` Prefix messages with a timestamp. Default is off. + + ``guest-name=on|off`` + Prefix messages with guest name but only if -name guest option is set + otherwise the option is ignored. Default is off. ERST DEF("dump-vmstate", HAS_ARG, QEMU_OPTION_dump_vmstate, @@ -4566,6 +4628,43 @@ SRST string as described at https://gnutls.org/manual/html_node/Priority-Strings.html. + ``-object tls-cipher-suites,id=id,priority=priority`` + Creates a TLS cipher suites object, which can be used to control + the TLS cipher/protocol algorithms that applications are permitted + to use. + + The ``id`` parameter is a unique ID which frontends will use to + access the ordered list of permitted TLS cipher suites from the + host. + + The ``priority`` parameter allows to override the global default + priority used by gnutls. This can be useful if the system + administrator needs to use a weaker set of crypto priorities for + QEMU without potentially forcing the weakness onto all + applications. Or conversely if one wants wants a stronger + default for QEMU than for all other applications, they can do + this through this parameter. Its format is a gnutls priority + string as described at + https://gnutls.org/manual/html_node/Priority-Strings.html. + + An example of use of this object is to control UEFI HTTPS Boot. + The tls-cipher-suites object exposes the ordered list of permitted + TLS cipher suites from the host side to the guest firmware, via + fw_cfg. The list is represented as an array of IANA_TLS_CIPHER + objects. The firmware uses the IANA_TLS_CIPHER array for configuring + guest-side TLS. + + In the following example, the priority at which the host-side policy + is retrieved is given by the ``priority`` property. + Given that QEMU uses GNUTLS, ``priority=@SYSTEM`` may be used to + refer to /etc/crypto-policies/back-ends/gnutls.config. + + .. parsed-literal:: + + # |qemu_system| \\ + -object tls-cipher-suites,id=mysuite0,priority=@SYSTEM \\ + -fw_cfg name=etc/edk2/https/ciphers,gen_id=mysuite0 + ``-object filter-buffer,id=id,netdev=netdevid,interval=t[,queue=all|rx|tx][,status=on|off][,position=head|tail|id=][,insert=behind|before]`` Interval t can't be 0, this filter batches the packet delivery: all packets arriving in a given interval on netdev netdevid are @@ -4639,24 +4738,25 @@ SRST stored. The file format is libpcap, so it can be analyzed with tools such as tcpdump or Wireshark. - ``-object colo-compare,id=id,primary_in=chardevid,secondary_in=chardevid,outdev=chardevid,iothread=id[,vnet_hdr_support][,notify_dev=id][,compare_timeout=@var{ms}][,expired_scan_cycle=@var{ms}`` - Colo-compare gets packet from primary\_inchardevid and - secondary\_inchardevid, than compare primary packet with - secondary packet. If the packets are same, we will output - primary packet to outdevchardevid, else we will notify - colo-frame do checkpoint and send primary packet to - outdevchardevid. In order to improve efficiency, we need to put - the task of comparison in another thread. If it has the - vnet\_hdr\_support flag, colo compare will send/recv packet with - vnet\_hdr\_len. Then compare\_timeout=@var{ms} determines the - maximum delay colo-compare wait for the packet. - The expired\_scan\_cycle=@var{ms} to set the period of scanning - expired primary node network packets. - If you want to use Xen COLO, will need the notify\_dev to + ``-object colo-compare,id=id,primary_in=chardevid,secondary_in=chardevid,outdev=chardevid,iothread=id[,vnet_hdr_support][,notify_dev=id][,compare_timeout=@var{ms}][,expired_scan_cycle=@var{ms}][,max_queue_size=@var{size}]`` + Colo-compare gets packet from primary\_in chardevid and + secondary\_in, then compare whether the payload of primary packet + and secondary packet are the same. If same, it will output + primary packet to out\_dev, else it will notify COLO-framework to do + checkpoint and send primary packet to out\_dev. In order to + improve efficiency, we need to put the task of comparison in + another iothread. If it has the vnet\_hdr\_support flag, + colo compare will send/recv packet with vnet\_hdr\_len. + The compare\_timeout=@var{ms} determines the maximum time of the + colo-compare hold the packet. The expired\_scan\_cycle=@var{ms} + is to set the period of scanning expired primary node network packets. + The max\_queue\_size=@var{size} is to set the max compare queue + size depend on user environment. + If user want to use Xen COLO, need to add the notify\_dev to notify Xen colo-frame to do checkpoint. - we must use it with the help of filter-mirror and - filter-redirector. + COLO-compare must be used with the help of filter-mirror, + filter-redirector and filter-rewriter. :: @@ -4725,10 +4825,10 @@ SRST .. parsed-literal:: - # |qemu_system| \ - [...] \ - -object cryptodev-backend-builtin,id=cryptodev0 \ - -device virtio-crypto-pci,id=crypto0,cryptodev=cryptodev0 \ + # |qemu_system| \\ + [...] \\ + -object cryptodev-backend-builtin,id=cryptodev0 \\ + -device virtio-crypto-pci,id=crypto0,cryptodev=cryptodev0 \\ [...] ``-object cryptodev-vhost-user,id=id,chardev=chardevid[,queues=queues]`` @@ -4744,11 +4844,11 @@ SRST .. parsed-literal:: - # |qemu_system| \ - [...] \ - -chardev socket,id=chardev0,path=/path/to/socket \ - -object cryptodev-vhost-user,id=cryptodev0,chardev=chardev0 \ - -device virtio-crypto-pci,id=crypto0,cryptodev=cryptodev0 \ + # |qemu_system| \\ + [...] \\ + -chardev socket,id=chardev0,path=/path/to/socket \\ + -object cryptodev-vhost-user,id=cryptodev0,chardev=chardev0 \\ + -device virtio-crypto-pci,id=crypto0,cryptodev=cryptodev0 \\ [...] ``-object secret,id=id,data=string,format=raw|base64[,keyid=secretid,iv=string]`` @@ -4826,9 +4926,9 @@ SRST .. parsed-literal:: - # |qemu_system| \ - -object secret,id=secmaster0,format=base64,file=key.b64 \ - -object secret,id=sec0,keyid=secmaster0,format=base64,\ + # |qemu_system| \\ + -object secret,id=secmaster0,format=base64,file=key.b64 \\ + -object secret,id=sec0,keyid=secmaster0,format=base64,\\ data=$SECRET,iv=$(method) { case GA_CHANNEL_VIRTIO_SERIAL: { assert(fd < 0); - fd = qemu_open(path, O_RDWR | O_NONBLOCK + fd = qemu_open_old(path, O_RDWR | O_NONBLOCK #ifndef CONFIG_SOLARIS | O_ASYNC #endif @@ -157,7 +157,7 @@ static gboolean ga_channel_open(GAChannel *c, const gchar *path, struct termios tio; assert(fd < 0); - fd = qemu_open(path, O_RDWR | O_NOCTTY | O_NONBLOCK); + fd = qemu_open_old(path, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd == -1) { g_critical("error opening channel: %s", strerror(errno)); return false; diff --git a/qga/commands-posix-ssh.c b/qga/commands-posix-ssh.c new file mode 100644 index 0000000000000000000000000000000000000000..749167e82d4f9778fb2e8ac5b68fa688cf18a9be --- /dev/null +++ b/qga/commands-posix-ssh.c @@ -0,0 +1,516 @@ + /* + * 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 +#include +#include +#include + +#include "qapi/error.h" +#include "qga-qapi-commands.h" + +#ifdef QGA_BUILD_UNIT_TEST +static struct passwd * +test_get_passwd_entry(const gchar *user_name, GError **error) +{ + struct passwd *p; + int ret; + + if (!user_name || g_strcmp0(user_name, g_get_user_name())) { + g_set_error(error, G_UNIX_ERROR, 0, "Invalid user name"); + return NULL; + } + + p = g_new0(struct passwd, 1); + p->pw_dir = (char *)g_get_home_dir(); + p->pw_uid = geteuid(); + p->pw_gid = getegid(); + + ret = g_mkdir_with_parents(p->pw_dir, 0700); + g_assert(ret == 0); + + return p; +} + +#define g_unix_get_passwd_entry_qemu(username, err) \ + test_get_passwd_entry(username, err) +#endif + +static struct passwd * +get_passwd_entry(const char *username, Error **errp) +{ + g_autoptr(GError) err = NULL; + struct passwd *p; + + ERRP_GUARD(); + + p = g_unix_get_passwd_entry_qemu(username, &err); + if (p == NULL) { + error_setg(errp, "failed to lookup user '%s': %s", + username, err->message); + return NULL; + } + + return p; +} + +static bool +mkdir_for_user(const char *path, const struct passwd *p, + mode_t mode, Error **errp) +{ + ERRP_GUARD(); + + if (g_mkdir(path, mode) == -1) { + error_setg(errp, "failed to create directory '%s': %s", + path, g_strerror(errno)); + return false; + } + + if (chown(path, p->pw_uid, p->pw_gid) == -1) { + error_setg(errp, "failed to set ownership of directory '%s': %s", + path, g_strerror(errno)); + return false; + } + + if (chmod(path, mode) == -1) { + error_setg(errp, "failed to set permissions of directory '%s': %s", + path, g_strerror(errno)); + return false; + } + + return true; +} + +static bool +check_openssh_pub_key(const char *key, Error **errp) +{ + ERRP_GUARD(); + + /* simple sanity-check, we may want more? */ + if (!key || key[0] == '#' || strchr(key, '\n')) { + error_setg(errp, "invalid OpenSSH public key: '%s'", key); + return false; + } + + return true; +} + +static bool +check_openssh_pub_keys(strList *keys, size_t *nkeys, Error **errp) +{ + size_t n = 0; + strList *k; + + ERRP_GUARD(); + + for (k = keys; k != NULL; k = k->next) { + if (!check_openssh_pub_key(k->value, errp)) { + return false; + } + n++; + } + + if (nkeys) { + *nkeys = n; + } + return true; +} + +static bool +write_authkeys(const char *path, const GStrv keys, + const struct passwd *p, Error **errp) +{ + g_autofree char *contents = NULL; + g_autoptr(GError) err = NULL; + + ERRP_GUARD(); + + contents = g_strjoinv("\n", keys); + if (!g_file_set_contents(path, contents, -1, &err)) { + error_setg(errp, "failed to write to '%s': %s", path, err->message); + return false; + } + + if (chown(path, p->pw_uid, p->pw_gid) == -1) { + error_setg(errp, "failed to set ownership of directory '%s': %s", + path, g_strerror(errno)); + return false; + } + + if (chmod(path, 0600) == -1) { + error_setg(errp, "failed to set permissions of '%s': %s", + path, g_strerror(errno)); + return false; + } + + return true; +} + +static GStrv +read_authkeys(const char *path, Error **errp) +{ + g_autoptr(GError) err = NULL; + g_autofree char *contents = NULL; + + ERRP_GUARD(); + + if (!g_file_get_contents(path, &contents, NULL, &err)) { + error_setg(errp, "failed to read '%s': %s", path, err->message); + return NULL; + } + + return g_strsplit(contents, "\n", -1); + +} + +void +qmp_guest_ssh_add_authorized_keys(const char *username, strList *keys, + bool has_reset, bool reset, + Error **errp) +{ + g_autofree struct passwd *p = NULL; + g_autofree char *ssh_path = NULL; + g_autofree char *authkeys_path = NULL; + g_auto(GStrv) authkeys = NULL; + strList *k; + size_t nkeys, nauthkeys; + + ERRP_GUARD(); + reset = has_reset && reset; + + if (!check_openssh_pub_keys(keys, &nkeys, errp)) { + return; + } + + p = get_passwd_entry(username, errp); + if (p == NULL) { + return; + } + + ssh_path = g_build_filename(p->pw_dir, ".ssh", NULL); + authkeys_path = g_build_filename(ssh_path, "authorized_keys", NULL); + + if (!reset) { + authkeys = read_authkeys(authkeys_path, NULL); + } + if (authkeys == NULL) { + if (!g_file_test(ssh_path, G_FILE_TEST_IS_DIR) && + !mkdir_for_user(ssh_path, p, 0700, errp)) { + return; + } + } + + nauthkeys = authkeys ? g_strv_length(authkeys) : 0; + authkeys = g_realloc_n(authkeys, nauthkeys + nkeys + 1, sizeof(char *)); + memset(authkeys + nauthkeys, 0, (nkeys + 1) * sizeof(char *)); + + for (k = keys; k != NULL; k = k->next) { + if (g_strv_contains((const gchar * const *)authkeys, k->value)) { + continue; + } + authkeys[nauthkeys++] = g_strdup(k->value); + } + + write_authkeys(authkeys_path, authkeys, p, errp); +} + +void +qmp_guest_ssh_remove_authorized_keys(const char *username, strList *keys, + Error **errp) +{ + g_autofree struct passwd *p = NULL; + g_autofree char *authkeys_path = NULL; + g_autofree GStrv new_keys = NULL; /* do not own the strings */ + g_auto(GStrv) authkeys = NULL; + GStrv a; + size_t nkeys = 0; + + ERRP_GUARD(); + + if (!check_openssh_pub_keys(keys, NULL, errp)) { + return; + } + + p = get_passwd_entry(username, errp); + if (p == NULL) { + return; + } + + authkeys_path = g_build_filename(p->pw_dir, ".ssh", + "authorized_keys", NULL); + if (!g_file_test(authkeys_path, G_FILE_TEST_EXISTS)) { + return; + } + authkeys = read_authkeys(authkeys_path, errp); + if (authkeys == NULL) { + return; + } + + new_keys = g_new0(char *, g_strv_length(authkeys) + 1); + for (a = authkeys; *a != NULL; a++) { + strList *k; + + for (k = keys; k != NULL; k = k->next) { + if (g_str_equal(k->value, *a)) { + break; + } + } + if (k != NULL) { + continue; + } + + new_keys[nkeys++] = *a; + } + + write_authkeys(authkeys_path, new_keys, p, errp); +} + +GuestAuthorizedKeys * +qmp_guest_ssh_get_authorized_keys(const char *username, Error **errp) +{ + g_autofree struct passwd *p = NULL; + g_autofree char *authkeys_path = NULL; + g_auto(GStrv) authkeys = NULL; + g_autoptr(GuestAuthorizedKeys) ret = NULL; + int i; + + ERRP_GUARD(); + + p = get_passwd_entry(username, errp); + if (p == NULL) { + return NULL; + } + + authkeys_path = g_build_filename(p->pw_dir, ".ssh", + "authorized_keys", NULL); + authkeys = read_authkeys(authkeys_path, errp); + if (authkeys == NULL) { + return NULL; + } + + ret = g_new0(GuestAuthorizedKeys, 1); + for (i = 0; authkeys[i] != NULL; i++) { + strList *new; + + g_strstrip(authkeys[i]); + if (!authkeys[i][0] || authkeys[i][0] == '#') { + continue; + } + + new = g_new0(strList, 1); + new->value = g_strdup(authkeys[i]); + new->next = ret->keys; + ret->keys = new; + } + + return g_steal_pointer(&ret); +} + +#ifdef QGA_BUILD_UNIT_TEST +#if GLIB_CHECK_VERSION(2, 60, 0) +static const strList test_key2 = { + .value = (char *)"algo key2 comments" +}; + +static const strList test_key1_2 = { + .value = (char *)"algo key1 comments", + .next = (strList *)&test_key2, +}; + +static char * +test_get_authorized_keys_path(void) +{ + return g_build_filename(g_get_home_dir(), ".ssh", "authorized_keys", NULL); +} + +static void +test_authorized_keys_set(const char *contents) +{ + g_autoptr(GError) err = NULL; + g_autofree char *path = NULL; + int ret; + + path = g_build_filename(g_get_home_dir(), ".ssh", NULL); + ret = g_mkdir_with_parents(path, 0700); + g_assert(ret == 0); + g_free(path); + + path = test_get_authorized_keys_path(); + g_file_set_contents(path, contents, -1, &err); + g_assert(err == NULL); +} + +static void +test_authorized_keys_equal(const char *expected) +{ + g_autoptr(GError) err = NULL; + g_autofree char *path = NULL; + g_autofree char *contents = NULL; + + path = test_get_authorized_keys_path(); + g_file_get_contents(path, &contents, NULL, &err); + g_assert(err == NULL); + + g_assert(g_strcmp0(contents, expected) == 0); +} + +static void +test_invalid_user(void) +{ + Error *err = NULL; + + qmp_guest_ssh_add_authorized_keys("", NULL, FALSE, FALSE, &err); + error_free_or_abort(&err); + + qmp_guest_ssh_remove_authorized_keys("", NULL, &err); + error_free_or_abort(&err); +} + +static void +test_invalid_key(void) +{ + strList key = { + .value = (char *)"not a valid\nkey" + }; + Error *err = NULL; + + qmp_guest_ssh_add_authorized_keys(g_get_user_name(), &key, + FALSE, FALSE, &err); + error_free_or_abort(&err); + + qmp_guest_ssh_remove_authorized_keys(g_get_user_name(), &key, &err); + error_free_or_abort(&err); +} + +static void +test_add_keys(void) +{ + Error *err = NULL; + + qmp_guest_ssh_add_authorized_keys(g_get_user_name(), + (strList *)&test_key2, + FALSE, FALSE, + &err); + g_assert(err == NULL); + + test_authorized_keys_equal("algo key2 comments"); + + qmp_guest_ssh_add_authorized_keys(g_get_user_name(), + (strList *)&test_key1_2, + FALSE, FALSE, + &err); + g_assert(err == NULL); + + /* key2 came first, and should'nt be duplicated */ + test_authorized_keys_equal("algo key2 comments\n" + "algo key1 comments"); +} + +static void +test_add_reset_keys(void) +{ + Error *err = NULL; + + qmp_guest_ssh_add_authorized_keys(g_get_user_name(), + (strList *)&test_key1_2, + FALSE, FALSE, + &err); + g_assert(err == NULL); + + /* reset with key2 only */ + test_authorized_keys_equal("algo key1 comments\n" + "algo key2 comments"); + + qmp_guest_ssh_add_authorized_keys(g_get_user_name(), + (strList *)&test_key2, + TRUE, TRUE, + &err); + g_assert(err == NULL); + + test_authorized_keys_equal("algo key2 comments"); + + /* empty should clear file */ + qmp_guest_ssh_add_authorized_keys(g_get_user_name(), + (strList *)NULL, + TRUE, TRUE, + &err); + g_assert(err == NULL); + + test_authorized_keys_equal(""); +} + +static void +test_remove_keys(void) +{ + Error *err = NULL; + static const char *authkeys = + "algo key1 comments\n" + /* originally duplicated */ + "algo key1 comments\n" + "# a commented line\n" + "algo some-key another\n"; + + test_authorized_keys_set(authkeys); + qmp_guest_ssh_remove_authorized_keys(g_get_user_name(), + (strList *)&test_key2, &err); + g_assert(err == NULL); + test_authorized_keys_equal(authkeys); + + qmp_guest_ssh_remove_authorized_keys(g_get_user_name(), + (strList *)&test_key1_2, &err); + g_assert(err == NULL); + test_authorized_keys_equal("# a commented line\n" + "algo some-key another\n"); +} + +static void +test_get_keys(void) +{ + Error *err = NULL; + static const char *authkeys = + "algo key1 comments\n" + "# a commented line\n" + "algo some-key another\n"; + g_autoptr(GuestAuthorizedKeys) ret = NULL; + strList *k; + size_t len = 0; + + test_authorized_keys_set(authkeys); + + ret = qmp_guest_ssh_get_authorized_keys(g_get_user_name(), &err); + g_assert(err == NULL); + + for (len = 0, k = ret->keys; k != NULL; k = k->next) { + g_assert(g_str_has_prefix(k->value, "algo ")); + len++; + } + + g_assert(len == 2); +} + +int main(int argc, char *argv[]) +{ + setlocale(LC_ALL, ""); + + g_test_init(&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL); + + g_test_add_func("/qga/ssh/invalid_user", test_invalid_user); + g_test_add_func("/qga/ssh/invalid_key", test_invalid_key); + g_test_add_func("/qga/ssh/add_keys", test_add_keys); + g_test_add_func("/qga/ssh/add_reset_keys", test_add_reset_keys); + g_test_add_func("/qga/ssh/remove_keys", test_remove_keys); + g_test_add_func("/qga/ssh/get_keys", test_get_keys); + + return g_test_run(); +} +#else +int main(int argc, char *argv[]) +{ + g_test_message("test skipped, needs glib >= 2.60"); + return 0; +} +#endif /* GLIB_2_60 */ +#endif /* BUILD_UNIT_TEST */ diff --git a/qga/commands-posix.c b/qga/commands-posix.c index ae1348dc8f7d2beb44b7f4d9e446bddbde372032..c089e3812006b97b70d56070b3dfedb4b7a28d96 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -861,28 +861,26 @@ static int build_hosts(char const *syspath, char const *host, bool ata, return i; } -/* Store disk device info specified by @sysfs into @fs */ -static void build_guest_fsinfo_for_real_device(char const *syspath, - GuestFilesystemInfo *fs, - Error **errp) +/* + * Store disk device info for devices on the PCI bus. + * Returns true if information has been stored, or false for failure. + */ +static bool build_guest_fsinfo_for_pci_dev(char const *syspath, + GuestDiskAddress *disk, + Error **errp) { unsigned int pci[4], host, hosts[8], tgt[3]; int i, nhosts = 0, pcilen; - GuestDiskAddress *disk; - GuestPCIAddress *pciaddr; - GuestDiskAddressList *list = NULL; + GuestPCIAddress *pciaddr = disk->pci_controller; bool has_ata = false, has_host = false, has_tgt = false; char *p, *q, *driver = NULL; -#ifdef CONFIG_LIBUDEV - struct udev *udev = NULL; - struct udev_device *udevice = NULL; -#endif + bool ret = false; p = strstr(syspath, "/devices/pci"); if (!p || sscanf(p + 12, "%*x:%*x/%x:%x:%x.%x%n", pci, pci + 1, pci + 2, pci + 3, &pcilen) < 4) { g_debug("only pci device is supported: sysfs path '%s'", syspath); - return; + return false; } p += 12 + pcilen; @@ -903,7 +901,7 @@ static void build_guest_fsinfo_for_real_device(char const *syspath, } g_debug("unsupported driver or sysfs path '%s'", syspath); - return; + return false; } p = strstr(syspath, "/target"); @@ -929,38 +927,11 @@ static void build_guest_fsinfo_for_real_device(char const *syspath, } } - pciaddr = g_malloc0(sizeof(*pciaddr)); pciaddr->domain = pci[0]; pciaddr->bus = pci[1]; pciaddr->slot = pci[2]; pciaddr->function = pci[3]; - disk = g_malloc0(sizeof(*disk)); - disk->pci_controller = pciaddr; - - list = g_malloc0(sizeof(*list)); - list->value = disk; - -#ifdef CONFIG_LIBUDEV - udev = udev_new(); - udevice = udev_device_new_from_syspath(udev, syspath); - if (udev == NULL || udevice == NULL) { - g_debug("failed to query udev"); - } else { - const char *devnode, *serial; - devnode = udev_device_get_devnode(udevice); - if (devnode != NULL) { - disk->dev = g_strdup(devnode); - disk->has_dev = true; - } - serial = udev_device_get_property_value(udevice, "ID_SERIAL"); - if (serial != NULL && *serial != 0) { - disk->serial = g_strdup(serial); - disk->has_serial = true; - } - } -#endif - if (strcmp(driver, "ata_piix") == 0) { /* a host per ide bus, target*:0::0 */ if (!has_host || !has_tgt) { @@ -1018,21 +989,111 @@ static void build_guest_fsinfo_for_real_device(char const *syspath, goto cleanup; } - list->next = fs->disk; - fs->disk = list; - goto out; + ret = true; cleanup: - if (list) { - qapi_free_GuestDiskAddressList(list); - } -out: g_free(driver); + return ret; +} + +/* + * Store disk device info for non-PCI virtio devices (for example s390x + * channel I/O devices). Returns true if information has been stored, or + * false for failure. + */ +static bool build_guest_fsinfo_for_nonpci_virtio(char const *syspath, + GuestDiskAddress *disk, + Error **errp) +{ + unsigned int tgt[3]; + char *p; + + if (!strstr(syspath, "/virtio") || !strstr(syspath, "/block")) { + g_debug("Unsupported virtio device '%s'", syspath); + return false; + } + + p = strstr(syspath, "/target"); + if (p && sscanf(p + 7, "%*u:%*u:%*u/%*u:%u:%u:%u", + &tgt[0], &tgt[1], &tgt[2]) == 3) { + /* virtio-scsi: target*:0:: */ + disk->bus_type = GUEST_DISK_BUS_TYPE_SCSI; + disk->bus = tgt[0]; + disk->target = tgt[1]; + disk->unit = tgt[2]; + } else { + /* virtio-blk: 1 disk per 1 device */ + disk->bus_type = GUEST_DISK_BUS_TYPE_VIRTIO; + } + + return true; +} + +/* Store disk device info specified by @sysfs into @fs */ +static void build_guest_fsinfo_for_real_device(char const *syspath, + GuestFilesystemInfo *fs, + Error **errp) +{ + GuestDiskAddress *disk; + GuestPCIAddress *pciaddr; + GuestDiskAddressList *list = NULL; + bool has_hwinf; #ifdef CONFIG_LIBUDEV + struct udev *udev = NULL; + struct udev_device *udevice = NULL; +#endif + + pciaddr = g_new0(GuestPCIAddress, 1); + pciaddr->domain = -1; /* -1 means field is invalid */ + pciaddr->bus = -1; + pciaddr->slot = -1; + pciaddr->function = -1; + + disk = g_new0(GuestDiskAddress, 1); + disk->pci_controller = pciaddr; + disk->bus_type = GUEST_DISK_BUS_TYPE_UNKNOWN; + + list = g_new0(GuestDiskAddressList, 1); + list->value = disk; + +#ifdef CONFIG_LIBUDEV + udev = udev_new(); + udevice = udev_device_new_from_syspath(udev, syspath); + if (udev == NULL || udevice == NULL) { + g_debug("failed to query udev"); + } else { + const char *devnode, *serial; + devnode = udev_device_get_devnode(udevice); + if (devnode != NULL) { + disk->dev = g_strdup(devnode); + disk->has_dev = true; + } + serial = udev_device_get_property_value(udevice, "ID_SERIAL"); + if (serial != NULL && *serial != 0) { + disk->serial = g_strdup(serial); + disk->has_serial = true; + } + } + udev_unref(udev); udev_device_unref(udevice); #endif - return; + + if (strstr(syspath, "/devices/pci")) { + has_hwinf = build_guest_fsinfo_for_pci_dev(syspath, disk, errp); + } else if (strstr(syspath, "/virtio")) { + has_hwinf = build_guest_fsinfo_for_nonpci_virtio(syspath, disk, errp); + } else { + g_debug("Unsupported device type for '%s'", syspath); + has_hwinf = false; + } + + if (has_hwinf || disk->has_dev || disk->has_serial) { + list->next = fs->disk; + fs->disk = list; + } else { + qapi_free_GuestDiskAddressList(list); + } } static void build_guest_fsinfo_for_device(char const *devpath, @@ -1089,13 +1150,27 @@ static void build_guest_fsinfo_for_virtual_device(char const *syspath, closedir(dir); } +static bool is_disk_virtual(const char *devpath, Error **errp) +{ + g_autofree char *syspath = realpath(devpath, NULL); + + if (!syspath) { + error_setg_errno(errp, errno, "realpath(\"%s\")", devpath); + return false; + } + return strstr(syspath, "/devices/virtual/block/") != NULL; +} + /* Dispatch to functions for virtual/real device */ static void build_guest_fsinfo_for_device(char const *devpath, GuestFilesystemInfo *fs, Error **errp) { - char *syspath = realpath(devpath, NULL); + ERRP_GUARD(); + g_autofree char *syspath = NULL; + bool is_virtual = false; + syspath = realpath(devpath, NULL); if (!syspath) { error_setg_errno(errp, errno, "realpath(\"%s\")", devpath); return; @@ -1106,16 +1181,286 @@ static void build_guest_fsinfo_for_device(char const *devpath, } g_debug(" parse sysfs path '%s'", syspath); - - if (strstr(syspath, "/devices/virtual/block/")) { + is_virtual = is_disk_virtual(syspath, errp); + if (*errp != NULL) { + return; + } + if (is_virtual) { build_guest_fsinfo_for_virtual_device(syspath, fs, errp); } else { build_guest_fsinfo_for_real_device(syspath, fs, errp); } +} + +#ifdef CONFIG_LIBUDEV + +/* + * Wrapper around build_guest_fsinfo_for_device() for getting just + * the disk address. + */ +static GuestDiskAddress *get_disk_address(const char *syspath, Error **errp) +{ + g_autoptr(GuestFilesystemInfo) fs = NULL; + + fs = g_new0(GuestFilesystemInfo, 1); + build_guest_fsinfo_for_device(syspath, fs, errp); + if (fs->disk != NULL) { + return g_steal_pointer(&fs->disk->value); + } + return NULL; +} + +static char *get_alias_for_syspath(const char *syspath) +{ + struct udev *udev = NULL; + struct udev_device *udevice = NULL; + char *ret = NULL; + + udev = udev_new(); + if (udev == NULL) { + g_debug("failed to query udev"); + goto out; + } + udevice = udev_device_new_from_syspath(udev, syspath); + if (udevice == NULL) { + g_debug("failed to query udev for path: %s", syspath); + goto out; + } else { + const char *alias = udev_device_get_property_value( + udevice, "DM_NAME"); + /* + * NULL means there was an error and empty string means there is no + * alias. In case of no alias we return NULL instead of empty string. + */ + if (alias == NULL) { + g_debug("failed to query udev for device alias for: %s", + syspath); + } else if (*alias != 0) { + ret = g_strdup(alias); + } + } + +out: + udev_unref(udev); + udev_device_unref(udevice); + return ret; +} + +static char *get_device_for_syspath(const char *syspath) +{ + struct udev *udev = NULL; + struct udev_device *udevice = NULL; + char *ret = NULL; + + udev = udev_new(); + if (udev == NULL) { + g_debug("failed to query udev"); + goto out; + } + udevice = udev_device_new_from_syspath(udev, syspath); + if (udevice == NULL) { + g_debug("failed to query udev for path: %s", syspath); + goto out; + } else { + ret = g_strdup(udev_device_get_devnode(udevice)); + } + +out: + udev_unref(udev); + udev_device_unref(udevice); + return ret; +} + +static void get_disk_deps(const char *disk_dir, GuestDiskInfo *disk) +{ + g_autofree char *deps_dir = NULL; + const gchar *dep; + GDir *dp_deps = NULL; + + /* List dependent disks */ + deps_dir = g_strdup_printf("%s/slaves", disk_dir); + g_debug(" listing entries in: %s", deps_dir); + dp_deps = g_dir_open(deps_dir, 0, NULL); + if (dp_deps == NULL) { + g_debug("failed to list entries in %s", deps_dir); + return; + } + disk->has_dependencies = true; + while ((dep = g_dir_read_name(dp_deps)) != NULL) { + g_autofree char *dep_dir = NULL; + strList *dep_item = NULL; + char *dev_name; + + /* Add dependent disks */ + dep_dir = g_strdup_printf("%s/%s", deps_dir, dep); + dev_name = get_device_for_syspath(dep_dir); + if (dev_name != NULL) { + g_debug(" adding dependent device: %s", dev_name); + dep_item = g_new0(strList, 1); + dep_item->value = dev_name; + dep_item->next = disk->dependencies; + disk->dependencies = dep_item; + } + } + g_dir_close(dp_deps); +} + +/* + * Detect partitions subdirectory, name is "" or + * "p" + * + * @disk_name -- last component of /sys path (e.g. sda) + * @disk_dir -- sys path of the disk (e.g. /sys/block/sda) + * @disk_dev -- device node of the disk (e.g. /dev/sda) + */ +static GuestDiskInfoList *get_disk_partitions( + GuestDiskInfoList *list, + const char *disk_name, const char *disk_dir, + const char *disk_dev) +{ + GuestDiskInfoList *item, *ret = list; + struct dirent *de_disk; + DIR *dp_disk = NULL; + size_t len = strlen(disk_name); + + dp_disk = opendir(disk_dir); + while ((de_disk = readdir(dp_disk)) != NULL) { + g_autofree char *partition_dir = NULL; + char *dev_name; + GuestDiskInfo *partition; + + if (!(de_disk->d_type & DT_DIR)) { + continue; + } + + if (!(strncmp(disk_name, de_disk->d_name, len) == 0 && + ((*(de_disk->d_name + len) == 'p' && + isdigit(*(de_disk->d_name + len + 1))) || + isdigit(*(de_disk->d_name + len))))) { + continue; + } + + partition_dir = g_strdup_printf("%s/%s", + disk_dir, de_disk->d_name); + dev_name = get_device_for_syspath(partition_dir); + if (dev_name == NULL) { + g_debug("Failed to get device name for syspath: %s", + disk_dir); + continue; + } + partition = g_new0(GuestDiskInfo, 1); + partition->name = dev_name; + partition->partition = true; + /* Add parent disk as dependent for easier tracking of hierarchy */ + partition->dependencies = g_new0(strList, 1); + partition->dependencies->value = g_strdup(disk_dev); + partition->has_dependencies = true; + + item = g_new0(GuestDiskInfoList, 1); + item->value = partition; + item->next = ret; + ret = item; + + } + closedir(dp_disk); + + return ret; +} + +GuestDiskInfoList *qmp_guest_get_disks(Error **errp) +{ + GuestDiskInfoList *item, *ret = NULL; + GuestDiskInfo *disk; + DIR *dp = NULL; + struct dirent *de = NULL; + + g_debug("listing /sys/block directory"); + dp = opendir("/sys/block"); + if (dp == NULL) { + error_setg_errno(errp, errno, "Can't open directory \"/sys/block\""); + return NULL; + } + while ((de = readdir(dp)) != NULL) { + g_autofree char *disk_dir = NULL, *line = NULL, + *size_path = NULL; + char *dev_name; + Error *local_err = NULL; + if (de->d_type != DT_LNK) { + g_debug(" skipping entry: %s", de->d_name); + continue; + } + + /* Check size and skip zero-sized disks */ + g_debug(" checking disk size"); + size_path = g_strdup_printf("/sys/block/%s/size", de->d_name); + if (!g_file_get_contents(size_path, &line, NULL, NULL)) { + g_debug(" failed to read disk size"); + continue; + } + if (g_strcmp0(line, "0\n") == 0) { + g_debug(" skipping zero-sized disk"); + continue; + } + + g_debug(" adding %s", de->d_name); + disk_dir = g_strdup_printf("/sys/block/%s", de->d_name); + dev_name = get_device_for_syspath(disk_dir); + if (dev_name == NULL) { + g_debug("Failed to get device name for syspath: %s", + disk_dir); + continue; + } + disk = g_new0(GuestDiskInfo, 1); + disk->name = dev_name; + disk->partition = false; + disk->alias = get_alias_for_syspath(disk_dir); + disk->has_alias = (disk->alias != NULL); + item = g_new0(GuestDiskInfoList, 1); + item->value = disk; + item->next = ret; + ret = item; + + /* Get address for non-virtual devices */ + bool is_virtual = is_disk_virtual(disk_dir, &local_err); + if (local_err != NULL) { + g_debug(" failed to check disk path, ignoring error: %s", + error_get_pretty(local_err)); + error_free(local_err); + local_err = NULL; + /* Don't try to get the address */ + is_virtual = true; + } + if (!is_virtual) { + disk->address = get_disk_address(disk_dir, &local_err); + if (local_err != NULL) { + g_debug(" failed to get device info, ignoring error: %s", + error_get_pretty(local_err)); + error_free(local_err); + local_err = NULL; + } else if (disk->address != NULL) { + disk->has_address = true; + } + } + + get_disk_deps(disk_dir, disk); + ret = get_disk_partitions(ret, de->d_name, disk_dir, dev_name); + } + + closedir(dp); + + return ret; +} + +#else - free(syspath); +GuestDiskInfoList *qmp_guest_get_disks(Error **errp) +{ + error_setg(errp, QERR_UNSUPPORTED); + return NULL; } +#endif + /* Return a list of the disk device(s)' info which @mount lies on */ static GuestFilesystemInfo *build_guest_fsinfo(struct FsMount *mount, Error **errp) @@ -1304,7 +1649,7 @@ int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, } } - fd = qemu_open(mount->dirname, O_RDONLY); + fd = qemu_open_old(mount->dirname, O_RDONLY); if (fd == -1) { error_setg_errno(errp, errno, "failed to open %s", mount->dirname); goto error; @@ -1371,7 +1716,7 @@ int64_t qmp_guest_fsfreeze_thaw(Error **errp) QTAILQ_FOREACH(mount, &mounts, next) { logged = false; - fd = qemu_open(mount->dirname, O_RDONLY); + fd = qemu_open_old(mount->dirname, O_RDONLY); if (fd == -1) { continue; } @@ -1461,7 +1806,7 @@ qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp) list->next = response->paths; response->paths = list; - fd = qemu_open(mount->dirname, O_RDONLY); + fd = qemu_open_old(mount->dirname, O_RDONLY); if (fd == -1) { result->error = g_strdup_printf("failed to open: %s", strerror(errno)); @@ -1552,13 +1897,12 @@ static int run_process_child(const char *command[], Error **errp) static bool systemd_supports_mode(SuspendMode mode, Error **errp) { - Error *local_err = NULL; const char *systemctl_args[3] = {"systemd-hibernate", "systemd-suspend", "systemd-hybrid-sleep"}; const char *cmd[4] = {"systemctl", "status", systemctl_args[mode], NULL}; int status; - status = run_process_child(cmd, &local_err); + status = run_process_child(cmd, errp); /* * systemctl status uses LSB return codes so we can expect @@ -1572,7 +1916,6 @@ static bool systemd_supports_mode(SuspendMode mode, Error **errp) return true; } - error_propagate(errp, local_err); return false; } @@ -2421,6 +2764,7 @@ static void transfer_memory_block(GuestMemoryBlock *mem_blk, bool sys2memblk, if (sys2memblk) { error_propagate(errp, local_err); } else { + error_free(local_err); result->response = GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED; } @@ -2713,6 +3057,13 @@ int64_t qmp_guest_fsfreeze_thaw(Error **errp) return 0; } + +GuestDiskInfoList *qmp_guest_get_disks(Error **errp) +{ + error_setg(errp, QERR_UNSUPPORTED); + return NULL; +} + #endif /* CONFIG_FSFREEZE */ #if !defined(CONFIG_FSTRIM) @@ -2749,7 +3100,8 @@ GList *ga_command_blacklist_init(GList *blacklist) const char *list[] = { "guest-get-fsinfo", "guest-fsfreeze-status", "guest-fsfreeze-freeze", "guest-fsfreeze-freeze-list", - "guest-fsfreeze-thaw", "guest-get-fsinfo", NULL}; + "guest-fsfreeze-thaw", "guest-get-fsinfo", + "guest-get-disks", NULL}; char **p = (char **)list; while (*p) { @@ -2762,6 +3114,8 @@ GList *ga_command_blacklist_init(GList *blacklist) blacklist = g_list_append(blacklist, g_strdup("guest-fstrim")); #endif + blacklist = g_list_append(blacklist, g_strdup("guest-get-devices")); + return blacklist; } @@ -2982,3 +3336,10 @@ GuestOSInfo *qmp_guest_get_osinfo(Error **errp) return info; } + +GuestDeviceInfoList *qmp_guest_get_devices(Error **errp) +{ + error_setg(errp, QERR_UNSUPPORTED); + + return NULL; +} diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 5ba56327dda5f6a9f0ef73006be7c9bc355ae659..300b87c859af3155cf84136b925e1cbd2fb5fc8c 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -21,10 +21,11 @@ #ifdef CONFIG_QGA_NTDDSCSI #include #include +#endif #include #include #include -#endif +#include #include #include #include @@ -39,6 +40,39 @@ #include "qemu/base64.h" #include "commands-common.h" +/* + * The following should be in devpkey.h, but it isn't. The key names were + * prefixed to avoid (future) name clashes. Once the definitions get into + * mingw the following lines can be removed. + */ +DEFINE_DEVPROPKEY(qga_DEVPKEY_NAME, 0xb725f130, 0x47ef, 0x101a, 0xa5, + 0xf1, 0x02, 0x60, 0x8c, 0x9e, 0xeb, 0xac, 10); + /* DEVPROP_TYPE_STRING */ +DEFINE_DEVPROPKEY(qga_DEVPKEY_Device_HardwareIds, 0xa45c254e, 0xdf1c, + 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 3); + /* DEVPROP_TYPE_STRING_LIST */ +DEFINE_DEVPROPKEY(qga_DEVPKEY_Device_DriverDate, 0xa8b865dd, 0x2e3d, + 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 2); + /* DEVPROP_TYPE_FILETIME */ +DEFINE_DEVPROPKEY(qga_DEVPKEY_Device_DriverVersion, 0xa8b865dd, 0x2e3d, + 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 3); + /* DEVPROP_TYPE_STRING */ +/* The CM_Get_DevNode_PropertyW prototype is only sometimes in cfgmgr32.h */ +#ifndef CM_Get_DevNode_Property +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +CMAPI CONFIGRET WINAPI CM_Get_DevNode_PropertyW( + DEVINST dnDevInst, + CONST DEVPROPKEY * PropertyKey, + DEVPROPTYPE * PropertyType, + PBYTE PropertyBuffer, + PULONG PropertyBufferSize, + ULONG ulFlags +); +#define CM_Get_DevNode_Property CM_Get_DevNode_PropertyW +#pragma GCC diagnostic pop +#endif + #ifndef SHTDN_REASON_FLAG_PLANNED #define SHTDN_REASON_FLAG_PLANNED 0x80000000 #endif @@ -278,13 +312,10 @@ out: static void execute_async(DWORD WINAPI (*func)(LPVOID), LPVOID opaque, Error **errp) { - Error *local_err = NULL; - HANDLE thread = CreateThread(NULL, 0, func, opaque, 0, NULL); if (!thread) { - error_setg(&local_err, QERR_QGA_COMMAND_FAILED, + error_setg(errp, QERR_QGA_COMMAND_FAILED, "failed to dispatch asynchronous command"); - error_propagate(errp, local_err); } } @@ -948,6 +979,101 @@ out: return list; } +GuestDiskInfoList *qmp_guest_get_disks(Error **errp) +{ + ERRP_GUARD(); + GuestDiskInfoList *new = NULL, *ret = NULL; + HDEVINFO dev_info; + SP_DEVICE_INTERFACE_DATA dev_iface_data; + int i; + + dev_info = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, 0, 0, + DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + if (dev_info == INVALID_HANDLE_VALUE) { + error_setg_win32(errp, GetLastError(), "failed to get device tree"); + return NULL; + } + + g_debug("enumerating devices"); + dev_iface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + for (i = 0; + SetupDiEnumDeviceInterfaces(dev_info, NULL, &GUID_DEVINTERFACE_DISK, + i, &dev_iface_data); + i++) { + GuestDiskAddress *address = NULL; + GuestDiskInfo *disk = NULL; + Error *local_err = NULL; + g_autofree PSP_DEVICE_INTERFACE_DETAIL_DATA + pdev_iface_detail_data = NULL; + STORAGE_DEVICE_NUMBER sdn; + HANDLE dev_file; + DWORD size = 0; + BOOL result; + int attempt; + + g_debug(" getting device path"); + for (attempt = 0, result = FALSE; attempt < 2 && !result; attempt++) { + result = SetupDiGetDeviceInterfaceDetail(dev_info, + &dev_iface_data, pdev_iface_detail_data, size, &size, NULL); + if (result) { + break; + } + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + pdev_iface_detail_data = g_realloc(pdev_iface_detail_data, + size); + pdev_iface_detail_data->cbSize = + sizeof(*pdev_iface_detail_data); + } else { + g_debug("failed to get device interface details"); + break; + } + } + if (!result) { + g_debug("skipping device"); + continue; + } + + g_debug(" device: %s", pdev_iface_detail_data->DevicePath); + dev_file = CreateFile(pdev_iface_detail_data->DevicePath, 0, + FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (!DeviceIoControl(dev_file, IOCTL_STORAGE_GET_DEVICE_NUMBER, + NULL, 0, &sdn, sizeof(sdn), &size, NULL)) { + CloseHandle(dev_file); + debug_error("failed to get storage device number"); + continue; + } + CloseHandle(dev_file); + + disk = g_new0(GuestDiskInfo, 1); + disk->name = g_strdup_printf("\\\\.\\PhysicalDrive%lu", + sdn.DeviceNumber); + + g_debug(" number: %lu", sdn.DeviceNumber); + address = g_malloc0(sizeof(GuestDiskAddress)); + address->has_dev = true; + address->dev = g_strdup(disk->name); + get_single_disk_info(sdn.DeviceNumber, address, &local_err); + if (local_err) { + g_debug("failed to get disk info: %s", + error_get_pretty(local_err)); + error_free(local_err); + qapi_free_GuestDiskAddress(address); + address = NULL; + } else { + disk->address = address; + disk->has_address = true; + } + + new = g_malloc0(sizeof(GuestDiskInfoList)); + new->value = disk; + new->next = ret; + ret = new; + } + + SetupDiDestroyDeviceInfoList(dev_info); + return ret; +} + #else static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp) @@ -955,17 +1081,25 @@ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp) return NULL; } +GuestDiskInfoList *qmp_guest_get_disks(Error **errp) +{ + error_setg(errp, QERR_UNSUPPORTED); + return NULL; +} + #endif /* CONFIG_QGA_NTDDSCSI */ static GuestFilesystemInfo *build_guest_fsinfo(char *guid, Error **errp) { DWORD info_size; char mnt, *mnt_point; + wchar_t wfs_name[32]; char fs_name[32]; - char vol_info[MAX_PATH+1]; + wchar_t vol_info[MAX_PATH + 1]; size_t len; uint64_t i64FreeBytesToCaller, i64TotalBytes, i64FreeBytes; GuestFilesystemInfo *fs = NULL; + HANDLE hLocalDiskHandle = NULL; GetVolumePathNamesForVolumeName(guid, (LPCH)&mnt, 0, &info_size); if (GetLastError() != ERROR_MORE_DATA) { @@ -980,18 +1114,27 @@ static GuestFilesystemInfo *build_guest_fsinfo(char *guid, Error **errp) goto free; } + hLocalDiskHandle = CreateFile(guid, 0 , 0, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | + FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (INVALID_HANDLE_VALUE == hLocalDiskHandle) { + error_setg_win32(errp, GetLastError(), "failed to get handle for volume"); + goto free; + } + len = strlen(mnt_point); mnt_point[len] = '\\'; mnt_point[len+1] = 0; - if (!GetVolumeInformation(mnt_point, vol_info, sizeof(vol_info), NULL, NULL, - NULL, (LPSTR)&fs_name, sizeof(fs_name))) { + + if (!GetVolumeInformationByHandleW(hLocalDiskHandle, vol_info, + sizeof(vol_info), NULL, NULL, NULL, + (LPWSTR) & wfs_name, sizeof(wfs_name))) { if (GetLastError() != ERROR_NOT_READY) { error_setg_win32(errp, GetLastError(), "failed to get volume info"); } goto free; } - fs_name[sizeof(fs_name) - 1] = 0; fs = g_malloc(sizeof(*fs)); fs->name = g_strdup(guid); fs->has_total_bytes = false; @@ -1010,9 +1153,11 @@ static GuestFilesystemInfo *build_guest_fsinfo(char *guid, Error **errp) fs->has_used_bytes = true; } } + wcstombs(fs_name, wfs_name, sizeof(wfs_name)); fs->type = g_strdup(fs_name); fs->disk = build_guest_disk_info(guid, errp); free: + CloseHandle(hLocalDiskHandle); g_free(mnt_point); return fs; } @@ -1030,8 +1175,12 @@ GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp) } do { - GuestFilesystemInfo *info = build_guest_fsinfo(guid, errp); - if (info == NULL) { + Error *local_err = NULL; + GuestFilesystemInfo *info = build_guest_fsinfo(guid, &local_err); + if (local_err) { + g_debug("failed to get filesystem info, ignoring error: %s", + error_get_pretty(local_err)); + error_free(local_err); continue; } new = g_malloc(sizeof(*ret)); @@ -1270,35 +1419,31 @@ typedef enum { static void check_suspend_mode(GuestSuspendMode mode, Error **errp) { SYSTEM_POWER_CAPABILITIES sys_pwr_caps; - Error *local_err = NULL; ZeroMemory(&sys_pwr_caps, sizeof(sys_pwr_caps)); if (!GetPwrCapabilities(&sys_pwr_caps)) { - error_setg(&local_err, QERR_QGA_COMMAND_FAILED, + error_setg(errp, QERR_QGA_COMMAND_FAILED, "failed to determine guest suspend capabilities"); - goto out; + return; } switch (mode) { case GUEST_SUSPEND_MODE_DISK: if (!sys_pwr_caps.SystemS4) { - error_setg(&local_err, QERR_QGA_COMMAND_FAILED, + error_setg(errp, QERR_QGA_COMMAND_FAILED, "suspend-to-disk not supported by OS"); } break; case GUEST_SUSPEND_MODE_RAM: if (!sys_pwr_caps.SystemS3) { - error_setg(&local_err, QERR_QGA_COMMAND_FAILED, + error_setg(errp, QERR_QGA_COMMAND_FAILED, "suspend-to-ram not supported by OS"); } break; default: - error_setg(&local_err, QERR_INVALID_PARAMETER_VALUE, "mode", + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "mode", "GuestSuspendMode"); } - -out: - error_propagate(errp, local_err); } static DWORD WINAPI do_suspend(LPVOID opaque) @@ -1597,6 +1742,12 @@ out: return head; } +static int64_t filetime_to_ns(const FILETIME *tf) +{ + return ((((int64_t)tf->dwHighDateTime << 32) | tf->dwLowDateTime) + - W32_FT_OFFSET) * 100; +} + int64_t qmp_guest_get_time(Error **errp) { SYSTEMTIME ts = {0}; @@ -1613,8 +1764,7 @@ int64_t qmp_guest_get_time(Error **errp) return -1; } - return ((((int64_t)tf.dwHighDateTime << 32) | tf.dwLowDateTime) - - W32_FT_OFFSET) * 100; + return filetime_to_ns(&tf); } void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp) @@ -2202,9 +2352,8 @@ GuestOSInfo *qmp_guest_get_osinfo(Error **errp) } server = os_version.wProductType != VER_NT_WORKSTATION; - product_name = ga_get_win_product_name(&local_err); + product_name = ga_get_win_product_name(errp); if (product_name == NULL) { - error_propagate(errp, local_err); return NULL; } @@ -2237,3 +2386,176 @@ GuestOSInfo *qmp_guest_get_osinfo(Error **errp) return info; } + +/* + * Safely get device property. Returned strings are using wide characters. + * Caller is responsible for freeing the buffer. + */ +static LPBYTE cm_get_property(DEVINST devInst, const DEVPROPKEY *propName, + PDEVPROPTYPE propType) +{ + CONFIGRET cr; + g_autofree LPBYTE buffer = NULL; + ULONG buffer_len = 0; + + /* First query for needed space */ + cr = CM_Get_DevNode_PropertyW(devInst, propName, propType, + buffer, &buffer_len, 0); + if (cr != CR_SUCCESS && cr != CR_BUFFER_SMALL) { + + slog("failed to get property size, error=0x%lx", cr); + return NULL; + } + buffer = g_new0(BYTE, buffer_len + 1); + cr = CM_Get_DevNode_PropertyW(devInst, propName, propType, + buffer, &buffer_len, 0); + if (cr != CR_SUCCESS) { + slog("failed to get device property, error=0x%lx", cr); + return NULL; + } + return g_steal_pointer(&buffer); +} + +static GStrv ga_get_hardware_ids(DEVINST devInstance) +{ + GArray *values = NULL; + DEVPROPTYPE cm_type; + LPWSTR id; + g_autofree LPWSTR property = (LPWSTR)cm_get_property(devInstance, + &qga_DEVPKEY_Device_HardwareIds, &cm_type); + if (property == NULL) { + slog("failed to get hardware IDs"); + return NULL; + } + if (*property == '\0') { + /* empty list */ + return NULL; + } + values = g_array_new(TRUE, TRUE, sizeof(gchar *)); + for (id = property; '\0' != *id; id += lstrlenW(id) + 1) { + gchar *id8 = g_utf16_to_utf8(id, -1, NULL, NULL, NULL); + g_array_append_val(values, id8); + } + return (GStrv)g_array_free(values, FALSE); +} + +/* + * https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-pci-devices + */ +#define DEVICE_PCI_RE "PCI\\\\VEN_(1AF4|1B36)&DEV_([0-9A-B]{4})(&|$)" + +GuestDeviceInfoList *qmp_guest_get_devices(Error **errp) +{ + GuestDeviceInfoList *head = NULL, *cur_item = NULL, *item = NULL; + HDEVINFO dev_info = INVALID_HANDLE_VALUE; + SP_DEVINFO_DATA dev_info_data; + int i, j; + GError *gerr = NULL; + g_autoptr(GRegex) device_pci_re = NULL; + DEVPROPTYPE cm_type; + + device_pci_re = g_regex_new(DEVICE_PCI_RE, + G_REGEX_ANCHORED | G_REGEX_OPTIMIZE, 0, + &gerr); + g_assert(device_pci_re != NULL); + + dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA); + dev_info = SetupDiGetClassDevs(0, 0, 0, DIGCF_PRESENT | DIGCF_ALLCLASSES); + if (dev_info == INVALID_HANDLE_VALUE) { + error_setg(errp, "failed to get device tree"); + return NULL; + } + + slog("enumerating devices"); + for (i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) { + bool skip = true; + g_autofree LPWSTR name = NULL; + g_autofree LPFILETIME date = NULL; + g_autofree LPWSTR version = NULL; + g_auto(GStrv) hw_ids = NULL; + g_autoptr(GuestDeviceInfo) device = g_new0(GuestDeviceInfo, 1); + g_autofree char *vendor_id = NULL; + g_autofree char *device_id = NULL; + + name = (LPWSTR)cm_get_property(dev_info_data.DevInst, + &qga_DEVPKEY_NAME, &cm_type); + if (name == NULL) { + slog("failed to get device description"); + continue; + } + device->driver_name = g_utf16_to_utf8(name, -1, NULL, NULL, NULL); + if (device->driver_name == NULL) { + error_setg(errp, "conversion to utf8 failed (driver name)"); + return NULL; + } + slog("querying device: %s", device->driver_name); + hw_ids = ga_get_hardware_ids(dev_info_data.DevInst); + if (hw_ids == NULL) { + continue; + } + for (j = 0; hw_ids[j] != NULL; j++) { + GMatchInfo *match_info; + GuestDeviceIdPCI *id; + if (!g_regex_match(device_pci_re, hw_ids[j], 0, &match_info)) { + continue; + } + skip = false; + + vendor_id = g_match_info_fetch(match_info, 1); + device_id = g_match_info_fetch(match_info, 2); + + device->id = g_new0(GuestDeviceId, 1); + device->has_id = true; + device->id->type = GUEST_DEVICE_TYPE_PCI; + id = &device->id->u.pci; + id->vendor_id = g_ascii_strtoull(vendor_id, NULL, 16); + id->device_id = g_ascii_strtoull(device_id, NULL, 16); + + g_match_info_free(match_info); + break; + } + if (skip) { + continue; + } + + version = (LPWSTR)cm_get_property(dev_info_data.DevInst, + &qga_DEVPKEY_Device_DriverVersion, &cm_type); + if (version == NULL) { + slog("failed to get driver version"); + continue; + } + device->driver_version = g_utf16_to_utf8(version, -1, NULL, + NULL, NULL); + if (device->driver_version == NULL) { + error_setg(errp, "conversion to utf8 failed (driver version)"); + return NULL; + } + device->has_driver_version = true; + + date = (LPFILETIME)cm_get_property(dev_info_data.DevInst, + &qga_DEVPKEY_Device_DriverDate, &cm_type); + if (date == NULL) { + slog("failed to get driver date"); + continue; + } + device->driver_date = filetime_to_ns(date); + device->has_driver_date = true; + + slog("driver: %s\ndriver version: %" PRId64 ",%s\n", + device->driver_name, device->driver_date, + device->driver_version); + item = g_new0(GuestDeviceInfoList, 1); + item->value = g_steal_pointer(&device); + if (!cur_item) { + head = cur_item = item; + } else { + cur_item->next = item; + cur_item = item; + } + } + + if (dev_info != INVALID_HANDLE_VALUE) { + SetupDiDestroyDeviceInfoList(dev_info); + } + return head; +} diff --git a/qga/commands.c b/qga/commands.c index efc8b902813cd3f2c345f41797c897e4f3e6c189..3dcd5fbe5c4ddbed672d1c33560700ee8946424b 100644 --- a/qga/commands.c +++ b/qga/commands.c @@ -166,13 +166,13 @@ GuestExecStatus *qmp_guest_exec_status(int64_t pid, Error **errp) ges = g_new0(GuestExecStatus, 1); - bool finished = atomic_mb_read(&gei->finished); + bool finished = qatomic_mb_read(&gei->finished); /* need to wait till output channels are closed * to be sure we captured all output at this point */ if (gei->has_output) { - finished = finished && atomic_mb_read(&gei->out.closed); - finished = finished && atomic_mb_read(&gei->err.closed); + finished = finished && qatomic_mb_read(&gei->out.closed); + finished = finished && qatomic_mb_read(&gei->err.closed); } ges->exited = finished; @@ -274,7 +274,7 @@ static void guest_exec_child_watch(GPid pid, gint status, gpointer data) (int32_t)gpid_to_int64(pid), (uint32_t)status); gei->status = status; - atomic_mb_set(&gei->finished, true); + qatomic_mb_set(&gei->finished, true); g_spawn_close_pid(pid); } @@ -330,7 +330,7 @@ static gboolean guest_exec_input_watch(GIOChannel *ch, done: g_io_channel_shutdown(ch, true, NULL); g_io_channel_unref(ch); - atomic_mb_set(&p->closed, true); + qatomic_mb_set(&p->closed, true); g_free(p->data); return false; @@ -384,7 +384,7 @@ static gboolean guest_exec_output_watch(GIOChannel *ch, close: g_io_channel_shutdown(ch, true, NULL); g_io_channel_unref(ch); - atomic_mb_set(&p->closed, true); + qatomic_mb_set(&p->closed, true); return false; } @@ -515,11 +515,20 @@ int ga_parse_whence(GuestFileWhence *whence, Error **errp) GuestHostName *qmp_guest_get_host_name(Error **errp) { GuestHostName *result = NULL; - gchar const *hostname = g_get_host_name(); - if (hostname != NULL) { - result = g_new0(GuestHostName, 1); - result->host_name = g_strdup(hostname); + g_autofree char *hostname = qemu_get_host_name(errp); + + /* + * We want to avoid using g_get_host_name() because that + * caches the result and we wouldn't reflect changes in the + * host name. + */ + + if (!hostname) { + hostname = g_strdup("localhost"); } + + result = g_new0(GuestHostName, 1); + result->host_name = g_steal_pointer(&hostname); return result; } diff --git a/qga/installer/qemu-ga.wxs b/qga/installer/qemu-ga.wxs index f6781752e6cd48480737ec87a12687a4b4e6782a..9cb4c3d733020a8a5eafafe9831f6742712d2cd3 100644 --- a/qga/installer/qemu-ga.wxs +++ b/qga/installer/qemu-ga.wxs @@ -66,7 +66,7 @@ - + channel); + g_assert(s->channel); + + if (!rsp) { + return 0; + } payload_qstr = qobject_to_json(QOBJECT(rsp)); if (!payload_qstr) { @@ -574,7 +579,7 @@ static void process_event(void *opaque, QObject *obj, Error *err) } g_debug("processing command"); - rsp = qmp_dispatch(&ga_commands, obj, false); + rsp = qmp_dispatch(&ga_commands, obj, false, NULL); end: ret = send_response(s, rsp); @@ -964,7 +969,7 @@ static void config_load(GAConfig *config) { GError *gerr = NULL; GKeyFile *keyfile; - const char *conf = g_getenv("QGA_CONF") ?: QGA_CONF_DEFAULT; + g_autofree char *conf = g_strdup(g_getenv("QGA_CONF")) ?: get_relocated_path(QGA_CONF_DEFAULT); /* read system config */ keyfile = g_key_file_new(); @@ -1023,7 +1028,7 @@ end: if (gerr && !(gerr->domain == G_FILE_ERROR && gerr->code == G_FILE_ERROR_NOENT)) { g_critical("error loading configuration from path: %s, %s", - QGA_CONF_DEFAULT, gerr->message); + conf, gerr->message); exit(EXIT_FAILURE); } g_clear_error(&gerr); @@ -1137,7 +1142,7 @@ static void config_parse(GAConfig *config, int argc, char **argv) #ifdef CONFIG_FSFREEZE case 'F': g_free(config->fsfreeze_hook); - config->fsfreeze_hook = g_strdup(optarg ?: QGA_FSFREEZE_HOOK_DEFAULT); + config->fsfreeze_hook = optarg ? g_strdup(optarg) : get_relocated_path(QGA_FSFREEZE_HOOK_DEFAULT); break; #endif case 't': @@ -1459,6 +1464,7 @@ int main(int argc, char **argv) config->log_level = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL; + qemu_init_exec_dir(argv[0]); qga_qmp_init_marshal(&ga_commands); init_dfl_pathnames(); diff --git a/qga/meson.build b/qga/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..520af6ce9bb7ba29684b653ff696907819d57d56 --- /dev/null +++ b/qga/meson.build @@ -0,0 +1,116 @@ +qga_qapi_outputs = [ + 'qga-qapi-commands.c', + 'qga-qapi-commands.h', + 'qga-qapi-emit-events.c', + 'qga-qapi-emit-events.h', + 'qga-qapi-events.c', + 'qga-qapi-events.h', + 'qga-qapi-init-commands.c', + 'qga-qapi-init-commands.h', + 'qga-qapi-introspect.c', + 'qga-qapi-introspect.h', + 'qga-qapi-types.c', + 'qga-qapi-types.h', + 'qga-qapi-visit.c', + 'qga-qapi-visit.h', +] + +qga_qapi_files = custom_target('QGA QAPI files', + output: qga_qapi_outputs, + input: 'qapi-schema.json', + command: [ qapi_gen, '-o', 'qga', '-p', 'qga-', '@INPUT0@' ], + depend_files: qapi_gen_depends) + +qga_ss = ss.source_set() +qga_ss.add(qga_qapi_files.to_list()) +qga_ss.add(files( + 'commands.c', + 'guest-agent-command-state.c', + 'main.c', +)) +qga_ss.add(when: 'CONFIG_POSIX', if_true: files( + 'channel-posix.c', + 'commands-posix.c', + 'commands-posix-ssh.c', +)) +qga_ss.add(when: 'CONFIG_WIN32', if_true: files( + 'channel-win32.c', + 'commands-win32.c', + 'service-win32.c', + 'vss-win32.c' +)) + +qga_ss = qga_ss.apply(config_host, strict: false) + +qga = executable('qemu-ga', qga_ss.sources(), + link_args: config_host['LIBS_QGA'].split(), + dependencies: [qemuutil, libudev], + install: true) +all_qga = [qga] + +if targetos == 'windows' + if 'CONFIG_QGA_VSS' in config_host + subdir('vss-win32') + else + gen_tlb = [] + endif + + wixl = find_program('wixl', required: false) + if wixl.found() + deps = [gen_tlb, qga] + if 'CONFIG_QGA_VSS' in config_host and 'QEMU_GA_MSI_WITH_VSS' in config_host + deps += qga_vss + endif + if 'CONFIG_QGA_MSI' in config_host + qga_msi = custom_target('QGA MSI', + input: files('installer/qemu-ga.wxs'), + output: 'qemu-ga-@0@.msi'.format(config_host['ARCH']), + depends: deps, + command: [ + find_program('env'), + 'QEMU_GA_VERSION=' + config_host['QEMU_GA_VERSION'], + 'QEMU_GA_MANUFACTURER=' + config_host['QEMU_GA_MANUFACTURER'], + 'QEMU_GA_DISTRO=' + config_host['QEMU_GA_DISTRO'], + 'BUILD_DIR=' + meson.build_root(), + wixl, '-o', '@OUTPUT0@', '@INPUT0@', + config_host['QEMU_GA_MSI_ARCH'].split(), + config_host['QEMU_GA_MSI_WITH_VSS'].split(), + config_host['QEMU_GA_MSI_MINGW_DLL_PATH'].split(), + ]) + all_qga += [qga_msi] + alias_target('msi', qga_msi) + endif + endif +else + install_subdir('run', install_dir: get_option('localstatedir')) +endif + +alias_target('qemu-ga', all_qga) + +test_env = environment() +test_env.set('G_TEST_SRCDIR', meson.current_source_dir()) +test_env.set('G_TEST_BUILDDIR', meson.current_build_dir()) + +# disable qga-ssh-test for now. glib's G_TEST_OPTION_ISOLATE_DIRS triggers +# the leak detector in build-oss-fuzz Gitlab CI test. we should re-enable +# this when an alternative is implemented or when the underlying glib +# issue is identified/fix +#if 'CONFIG_POSIX' in config_host +if false + srcs = [files('commands-posix-ssh.c')] + i = 0 + foreach output: qga_qapi_outputs + if output.startswith('qga-qapi-types') or output.startswith('qga-qapi-visit') + srcs += qga_qapi_files[i] + endif + i = i + 1 + endforeach + qga_ssh_test = executable('qga-ssh-test', srcs, + dependencies: [qemuutil], + c_args: ['-DQGA_BUILD_UNIT_TEST']) + + test('qga-ssh-test', + qga_ssh_test, + env: test_env, + suite: ['unit', 'qga']) +endif diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index 4be9aad48e26931022663801e0123f479792e899..3b3d1d0bd9d267dd71d6f64c8bce7dd33b39031c 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -1,14 +1,17 @@ # *-*- Mode: Python -*-* +# vim: filetype=python ## -# -# General note concerning the use of guest agent interfaces: +# = General note concerning the use of guest agent interfaces # # "unsupported" is a higher-level error than the errors that individual # commands might document. The caller should always be prepared to receive # QERR_UNSUPPORTED, even if the given command doesn't specify it, or doesn't # document any failure mode at all. -# +## + +## +# = QEMU guest agent protocol commands and structs ## { 'pragma': { 'doc-required': true } } @@ -846,7 +849,7 @@ ## # @GuestDiskAddress: # -# @pci-controller: controller's PCI address +# @pci-controller: controller's PCI address (fields are set to -1 if invalid) # @bus-type: bus type # @bus: bus id # @target: target id @@ -862,6 +865,37 @@ 'bus': 'int', 'target': 'int', 'unit': 'int', '*serial': 'str', '*dev': 'str'} } +## +# @GuestDiskInfo: +# +# @name: device node (Linux) or device UNC (Windows) +# @partition: whether this is a partition or disk +# @dependencies: list of device dependencies; e.g. for LVs of the LVM this will +# hold the list of PVs, for LUKS encrypted volume this will +# contain the disk where the volume is placed. (Linux) +# @address: disk address information (only for non-virtual devices) +# @alias: optional alias assigned to the disk, on Linux this is a name assigned +# by device mapper +# +# Since 5.2 +## +{ 'struct': 'GuestDiskInfo', + 'data': {'name': 'str', 'partition': 'bool', '*dependencies': ['str'], + '*address': 'GuestDiskAddress', '*alias': 'str'} } + +## +# @guest-get-disks: +# +# Returns: The list of disks in the guest. For Windows these are only the +# physical disks. On Linux these are all root block devices of +# non-zero size including e.g. removable devices, loop devices, +# NBD, etc. +# +# Since: 5.2 +## +{ 'command': 'guest-get-disks', + 'returns': ['GuestDiskInfo'] } + ## # @GuestFilesystemInfo: # @@ -1252,3 +1286,130 @@ ## { 'command': 'guest-get-osinfo', 'returns': 'GuestOSInfo' } + +## +# @GuestDeviceType: +## +{ 'enum': 'GuestDeviceType', + 'data': [ 'pci' ] } + +## +# @GuestDeviceIdPCI: +# +# @vendor-id: vendor ID +# @device-id: device ID +# +# Since: 5.2 +## +{ 'struct': 'GuestDeviceIdPCI', + 'data': { 'vendor-id': 'uint16', 'device-id': 'uint16' } } + +## +# @GuestDeviceId: +# +# Id of the device +# - @pci: PCI ID, since: 5.2 +# +# Since: 5.2 +## +{ 'union': 'GuestDeviceId', + 'base': { 'type': 'GuestDeviceType' }, + 'discriminator': 'type', + 'data': { 'pci': 'GuestDeviceIdPCI' } } + +## +# @GuestDeviceInfo: +# +# @driver-name: name of the associated driver +# @driver-date: driver release date, in nanoseconds since the epoch +# @driver-version: driver version +# @id: device ID +# +# Since: 5.2 +## +{ 'struct': 'GuestDeviceInfo', + 'data': { + 'driver-name': 'str', + '*driver-date': 'int', + '*driver-version': 'str', + '*id': 'GuestDeviceId' + } } + +## +# @guest-get-devices: +# +# Retrieve information about device drivers in Windows guest +# +# Returns: @GuestDeviceInfo +# +# Since: 5.2 +## +{ 'command': 'guest-get-devices', + 'returns': ['GuestDeviceInfo'] } + +## +# @GuestAuthorizedKeys: +# +# @keys: public keys (in OpenSSH/sshd(8) authorized_keys format) +# +# Since: 5.2 +## +{ 'struct': 'GuestAuthorizedKeys', + 'data': { + 'keys': ['str'] + }, + 'if': 'defined(CONFIG_POSIX)' } + + +## +# @guest-ssh-get-authorized-keys: +# +# @username: the user account to add the authorized keys +# +# Return the public keys from user .ssh/authorized_keys on Unix systems (not +# implemented for other systems). +# +# Returns: @GuestAuthorizedKeys +# +# Since: 5.2 +## +{ 'command': 'guest-ssh-get-authorized-keys', + 'data': { 'username': 'str' }, + 'returns': 'GuestAuthorizedKeys', + 'if': 'defined(CONFIG_POSIX)' } + +## +# @guest-ssh-add-authorized-keys: +# +# @username: the user account to add the authorized keys +# @keys: the public keys to add (in OpenSSH/sshd(8) authorized_keys format) +# @reset: ignore the existing content, set it with the given keys only +# +# Append public keys to user .ssh/authorized_keys on Unix systems (not +# implemented for other systems). +# +# Returns: Nothing on success. +# +# Since: 5.2 +## +{ 'command': 'guest-ssh-add-authorized-keys', + 'data': { 'username': 'str', 'keys': ['str'], '*reset': 'bool' }, + 'if': 'defined(CONFIG_POSIX)' } + +## +# @guest-ssh-remove-authorized-keys: +# +# @username: the user account to remove the authorized keys +# @keys: the public keys to remove (in OpenSSH/sshd(8) authorized_keys format) +# +# Remove public keys from the user .ssh/authorized_keys on Unix systems (not +# implemented for other systems). It's not an error if the key is already +# missing. +# +# Returns: Nothing on success. +# +# Since: 5.2 +## +{ 'command': 'guest-ssh-remove-authorized-keys', + 'data': { 'username': 'str', 'keys': ['str'] }, + 'if': 'defined(CONFIG_POSIX)' } diff --git a/qga/vss-win32/Makefile.objs b/qga/vss-win32/Makefile.objs deleted file mode 100644 index c82676aeb88a903e4011d74109df2a9d92b7b945..0000000000000000000000000000000000000000 --- a/qga/vss-win32/Makefile.objs +++ /dev/null @@ -1,23 +0,0 @@ -# rules to build qga-vss.dll - -qga-vss-dll-obj-y += requester.o provider.o install.o - -obj-qga-vss-dll-obj-y = $(addprefix $(obj)/, $(qga-vss-dll-obj-y)) -$(obj-qga-vss-dll-obj-y): QEMU_CXXFLAGS := $(filter-out -fstack-protector-all -fstack-protector-strong, $(QEMU_CXXFLAGS)) -Wno-unknown-pragmas -Wno-delete-non-virtual-dtor - -QGA_VSS_LDFLAGS = -shared -Wl,--add-stdcall-alias,--enable-stdcall-fixup -lglib-2.0 -lole32 -loleaut32 -lshlwapi -luuid -lintl -lws2_32 -static -$(obj)/qga-vss.dll: $(obj-qga-vss-dll-obj-y) $(SRC_PATH)/$(obj)/qga-vss.def - $(call quiet-command,$(CXX) -o $@ $(qga-vss-dll-obj-y) $(SRC_PATH)/qga/vss-win32/qga-vss.def $(CXXFLAGS) $(QGA_VSS_LDFLAGS),"LINK","$(TARGET_DIR)$@") - - -# rules to build qga-provider.tlb -# Currently, only native build is supported because building .tlb -# (TypeLibrary) from .idl requires WindowsSDK and MIDL (and cl.exe in VC++). -MIDL=$(WIN_SDK)/Bin/midl - -$(obj)/qga-vss.tlb: $(SRC_PATH)/$(obj)/qga-vss.idl -ifeq ($(WIN_SDK),"") - $(call quiet-command,cp $(dir $<)qga-vss.tlb $@,"COPY","$(TARGET_DIR)$@") -else - $(call quiet-command,$(MIDL) -tlb $@ -I $(WIN_SDK)/Include $<,"MIDL","$(TARGET_DIR)$@") -endif diff --git a/qga/vss-win32/install.cpp b/qga/vss-win32/install.cpp index a4568413601e6f2b765c8c530f869bfd1b6f704c..40de1337744b9aef6423f2c8c3fda89f46a46642 100644 --- a/qga/vss-win32/install.cpp +++ b/qga/vss-win32/install.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #define BUFFER_SIZE 1024 @@ -509,26 +510,32 @@ namespace _com_util } } -/* Stop QGA VSS provider service from COM+ Application Admin Catalog */ - +/* Stop QGA VSS provider service using Winsvc API */ STDAPI StopService(void) { HRESULT hr; - COMInitializer initializer; - COMPointer pUnknown; - COMPointer pCatalog; + SC_HANDLE manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + SC_HANDLE service = NULL; - int count = 0; + if (!manager) { + errmsg(E_FAIL, "Failed to open service manager"); + hr = E_FAIL; + goto out; + } + service = OpenService(manager, QGA_PROVIDER_NAME, SC_MANAGER_ALL_ACCESS); - chk(QGAProviderFind(QGAProviderCount, (void *)&count)); - if (count) { - chk(CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_INPROC_SERVER, - IID_IUnknown, (void **)pUnknown.replace())); - chk(pUnknown->QueryInterface(IID_ICOMAdminCatalog2, - (void **)pCatalog.replace())); - chk(pCatalog->ShutdownApplication(_bstr_t(QGA_PROVIDER_LNAME))); + if (!service) { + errmsg(E_FAIL, "Failed to open service"); + hr = E_FAIL; + goto out; + } + if (!(ControlService(service, SERVICE_CONTROL_STOP, NULL))) { + errmsg(E_FAIL, "Failed to stop service"); + hr = E_FAIL; } out: + CloseServiceHandle(service); + CloseServiceHandle(manager); return hr; } diff --git a/qga/vss-win32/meson.build b/qga/vss-win32/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..780c4614322af5e6676e96a24cdb594d7955126f --- /dev/null +++ b/qga/vss-win32/meson.build @@ -0,0 +1,36 @@ +if add_languages('cpp', required: false) + glib_static = dependency('glib-2.0', static: true) + link_args = cc.get_supported_link_arguments(['-fstack-protector-all', '-fstack-protector-strong', + '-Wl,--add-stdcall-alias', '-Wl,--enable-stdcall-fixup']) + + qga_vss = shared_module('qga-vss', ['requester.cpp', 'provider.cpp', 'install.cpp'], + name_prefix: '', + cpp_args: ['-Wno-unknown-pragmas', '-Wno-delete-non-virtual-dtor', '-Wno-non-virtual-dtor'], + link_args: link_args, + vs_module_defs: 'qga-vss.def', + dependencies: [glib_static, socket, + cc.find_library('ole32'), + cc.find_library('oleaut32'), + cc.find_library('shlwapi'), + cc.find_library('uuid'), + cc.find_library('intl')]) + + all_qga += qga_vss +endif + +# rules to build qga-vss.tlb +# Currently, only native build is supported because building .tlb +# (TypeLibrary) from .idl requires WindowsSDK and MIDL (and cl.exe in VC++). +midl = find_program('midl', required: false) +if midl.found() + gen_tlb = custom_target('gen-tlb', + input: 'qga-vss.idl', + output: 'qga-vss.tlb', + command: [midl, '-tlb', '-I' + config_host['WIN_SDK'], + '@INPUT@', '@OUTPUT@']) +else + gen_tlb = custom_target('gen-tlb', + input: 'qga-vss.tlb', + output: 'qga-vss.tlb', + command: ['cp', '@INPUT@', '@OUTPUT@']) +endif diff --git a/qobject/Makefile.objs b/qobject/Makefile.objs deleted file mode 100644 index 7b12c9cacfcf3242a444c6362c7f63620f871cad..0000000000000000000000000000000000000000 --- a/qobject/Makefile.objs +++ /dev/null @@ -1,3 +0,0 @@ -util-obj-y = qnull.o qnum.o qstring.o qdict.o qlist.o qbool.o qlit.o -util-obj-y += qjson.o qobject.o json-lexer.o json-streamer.o json-parser.o -util-obj-y += block-qdict.o diff --git a/qobject/json-parser.c b/qobject/json-parser.c index d083810d3782c728e93a1e8aecf866e95e9c7c9b..c0f521b56b108554d642b9a1c7d224a6d2b1d83b 100644 --- a/qobject/json-parser.c +++ b/qobject/json-parser.c @@ -257,8 +257,9 @@ static JSONToken *parser_context_peek_token(JSONParserContext *ctxt) */ static int parse_pair(JSONParserContext *ctxt, QDict *dict) { + QObject *key_obj = NULL; + QString *key; QObject *value; - QString *key = NULL; JSONToken *peek, *token; peek = parser_context_peek_token(ctxt); @@ -267,7 +268,8 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict) goto out; } - key = qobject_to(QString, parse_value(ctxt)); + key_obj = parse_value(ctxt); + key = qobject_to(QString, key_obj); if (!key) { parse_error(ctxt, peek, "key is not a string in object"); goto out; @@ -297,13 +299,11 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict) qdict_put_obj(dict, qstring_get_str(key), value); - qobject_unref(key); - + qobject_unref(key_obj); return 0; out: - qobject_unref(key); - + qobject_unref(key_obj); return -1; } diff --git a/qobject/meson.build b/qobject/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..bb63c06b638cc5d0f789230b6a1e1cc56c416417 --- /dev/null +++ b/qobject/meson.build @@ -0,0 +1,3 @@ +util_ss.add(files('qnull.c', 'qnum.c', 'qstring.c', 'qdict.c', 'qlist.c', 'qbool.c', + 'qlit.c', 'qjson.c', 'qobject.c', 'json-lexer.c', 'json-streamer.c', 'json-parser.c', + 'block-qdict.c')) diff --git a/qobject/qdict.c b/qobject/qdict.c index 526de54ceba99a6f1a2da0711d14d5f61cace90f..1079bd3f6f68844e24a28b9fd35ed5fd00c75580 100644 --- a/qobject/qdict.c +++ b/qobject/qdict.c @@ -33,7 +33,7 @@ QDict *qdict_new(void) } /** - * tdb_hash(): based on the hash agorithm from gdbm, via tdb + * tdb_hash(): based on the hash algorithm from gdbm, via tdb * (from module-init-tools) */ static unsigned int tdb_hash(const char *name) diff --git a/qom/Makefile.objs b/qom/Makefile.objs deleted file mode 100644 index 1b45d104ba64971f1f2e5d1441693344849f866c..0000000000000000000000000000000000000000 --- a/qom/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -qom-obj-y = object.o container.o qom-qobject.o -qom-obj-y += object_interfaces.o - -common-obj-$(CONFIG_SOFTMMU) += qom-hmp-cmds.o qom-qmp-cmds.o -storage-daemon-obj-y += qom-qmp-cmds.o diff --git a/qom/container.c b/qom/container.c index 14e7ae485bb859eb2250796a019218fd92b38b4c..455e8410c66dad02eee86ff94f3a77ed26216295 100644 --- a/qom/container.c +++ b/qom/container.c @@ -16,7 +16,6 @@ static const TypeInfo container_info = { .name = "container", - .instance_size = sizeof(Object), .parent = TYPE_OBJECT, }; diff --git a/qom/meson.build b/qom/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..062a3789d877fd21632a3151d72baf83dfb6f92c --- /dev/null +++ b/qom/meson.build @@ -0,0 +1,10 @@ +qom_ss.add(genh) +qom_ss.add(files( + 'container.c', + 'object.c', + 'object_interfaces.c', + 'qom-qobject.c', +)) + +qmp_ss.add(files('qom-qmp-cmds.c')) +softmmu_ss.add(files('qom-hmp-cmds.c')) diff --git a/qom/object.c b/qom/object.c index d0be42c8d682397f0eaf98d2de8c1ce19f9588be..10653552334549241cd5672d7a027ad57432c482 100644 --- a/qom/object.c +++ b/qom/object.c @@ -50,6 +50,7 @@ struct TypeImpl size_t class_size; size_t instance_size; + size_t instance_align; void (*class_init)(ObjectClass *klass, void *data); void (*class_base_init)(ObjectClass *klass, void *data); @@ -114,6 +115,7 @@ static TypeImpl *type_new(const TypeInfo *info) ti->class_size = info->class_size; ti->instance_size = info->instance_size; + ti->instance_align = info->instance_align; ti->class_init = info->class_init; ti->class_base_init = info->class_base_init; @@ -262,8 +264,7 @@ static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type, new_iface->concrete_class = ti->class; new_iface->interface_type = interface_type; - ti->class->interfaces = g_slist_append(ti->class->interfaces, - iface_impl->class); + ti->class->interfaces = g_slist_append(ti->class->interfaces, new_iface); } static void object_property_free(gpointer data) @@ -316,8 +317,6 @@ static void type_initialize(TypeImpl *ti) g_assert(parent->instance_size <= ti->instance_size); memcpy(ti->class, parent->class, parent->class_size); ti->class->interfaces = NULL; - ti->class->properties = g_hash_table_new_full( - g_str_hash, g_str_equal, NULL, object_property_free); for (e = parent->class->interfaces; e; e = e->next) { InterfaceClass *iface = e->data; @@ -347,11 +346,11 @@ static void type_initialize(TypeImpl *ti) type_initialize_interface(ti, t, t); } - } else { - ti->class->properties = g_hash_table_new_full( - g_str_hash, g_str_equal, NULL, object_property_free); } + ti->class->properties = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, + object_property_free); + ti->class->type = ti; while (parent) { @@ -388,12 +387,13 @@ static void object_post_init_with_type(Object *obj, TypeImpl *ti) } } -void object_apply_global_props(Object *obj, const GPtrArray *props, Error **errp) +bool object_apply_global_props(Object *obj, const GPtrArray *props, + Error **errp) { int i; if (!props) { - return; + return true; } for (i = 0; i < props->len; i++) { @@ -403,12 +403,11 @@ void object_apply_global_props(Object *obj, const GPtrArray *props, Error **errp if (object_dynamic_cast(obj, p->driver) == NULL) { continue; } - if (p->optional && !object_property_find(obj, p->property, NULL)) { + if (p->optional && !object_property_find(obj, p->property)) { continue; } p->used = true; - object_property_parse(obj, p->value, p->property, &err); - if (err != NULL) { + if (!object_property_parse(obj, p->property, p->value, &err)) { error_prepend(&err, "can't apply global %s.%s=%s: ", p->driver, p->property, p->value); /* @@ -418,12 +417,14 @@ void object_apply_global_props(Object *obj, const GPtrArray *props, Error **errp */ if (errp) { error_propagate(errp, err); - return; + return false; } else { warn_report_err(err); } } } + + return true; } /* @@ -497,10 +498,8 @@ static void object_class_property_init_all(Object *obj) } } -static void object_initialize_with_type(void *data, size_t size, TypeImpl *type) +static void object_initialize_with_type(Object *obj, size_t size, TypeImpl *type) { - Object *obj = data; - type_initialize(type); g_assert(type->instance_size >= sizeof(Object)); @@ -521,6 +520,12 @@ void object_initialize(void *data, size_t size, const char *typename) { TypeImpl *type = type_get_by_name(typename); +#ifdef CONFIG_MODULES + if (!type) { + module_load_qom_one(typename); + type = type_get_by_name(typename); + } +#endif if (!type) { error_report("missing object type '%s'", typename); abort(); @@ -529,31 +534,37 @@ void object_initialize(void *data, size_t size, const char *typename) object_initialize_with_type(data, size, type); } -void object_initialize_child(Object *parentobj, const char *propname, - void *childobj, size_t size, const char *type, - Error **errp, ...) +bool object_initialize_child_with_props(Object *parentobj, + const char *propname, + void *childobj, size_t size, + const char *type, + Error **errp, ...) { va_list vargs; + bool ok; va_start(vargs, errp); - object_initialize_childv(parentobj, propname, childobj, size, type, errp, - vargs); + ok = object_initialize_child_with_propsv(parentobj, propname, + childobj, size, type, errp, + vargs); va_end(vargs); + return ok; } -void object_initialize_childv(Object *parentobj, const char *propname, - void *childobj, size_t size, const char *type, - Error **errp, va_list vargs) +bool object_initialize_child_with_propsv(Object *parentobj, + const char *propname, + void *childobj, size_t size, + const char *type, + Error **errp, va_list vargs) { - Error *local_err = NULL; + bool ok = false; Object *obj; UserCreatable *uc; object_initialize(childobj, size, type); obj = OBJECT(childobj); - object_set_propv(obj, &local_err, vargs); - if (local_err) { + if (!object_set_propv(obj, errp, vargs)) { goto out; } @@ -561,13 +572,14 @@ void object_initialize_childv(Object *parentobj, const char *propname, uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE); if (uc) { - user_creatable_complete(uc, &local_err); - if (local_err) { + if (!user_creatable_complete(uc, errp)) { object_unparent(obj); goto out; } } + ok = true; + out: /* * We want @obj's reference to be 1 on success, 0 on failure. @@ -578,8 +590,16 @@ out: * the reference taken by object_property_add_child(). */ object_unref(obj); + return ok; +} - error_propagate(errp, local_err); +void object_initialize_child_internal(Object *parent, + const char *propname, + void *child, size_t size, + const char *type) +{ + object_initialize_child_with_props(parent, propname, child, size, type, + &error_abort, NULL); } static inline bool object_property_is_child(ObjectProperty *prop) @@ -670,16 +690,44 @@ static void object_finalize(void *data) } } +/* Find the minimum alignment guaranteed by the system malloc. */ +#if __STDC_VERSION__ >= 201112L +typddef max_align_t qemu_max_align_t; +#else +typedef union { + long l; + void *p; + double d; + long double ld; +} qemu_max_align_t; +#endif + static Object *object_new_with_type(Type type) { Object *obj; + size_t size, align; + void (*obj_free)(void *); g_assert(type != NULL); type_initialize(type); - obj = g_malloc(type->instance_size); - object_initialize_with_type(obj, type->instance_size, type); - obj->free = g_free; + size = type->instance_size; + align = type->instance_align; + + /* + * Do not use qemu_memalign unless required. Depending on the + * implementation, extra alignment implies extra overhead. + */ + if (likely(align <= __alignof__(qemu_max_align_t))) { + obj = g_malloc(size); + obj_free = g_free; + } else { + obj = qemu_memalign(align, size); + obj_free = qemu_vfree; + } + + object_initialize_with_type(obj, size, type); + obj->free = obj_free; return obj; } @@ -722,7 +770,6 @@ Object *object_new_with_propv(const char *typename, { Object *obj; ObjectClass *klass; - Error *local_err = NULL; UserCreatable *uc; klass = object_class_by_name(typename); @@ -737,7 +784,7 @@ Object *object_new_with_propv(const char *typename, } obj = object_new_with_type(klass->type); - if (object_set_propv(obj, &local_err, vargs) < 0) { + if (!object_set_propv(obj, errp, vargs)) { goto error; } @@ -747,8 +794,7 @@ Object *object_new_with_propv(const char *typename, uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE); if (uc) { - user_creatable_complete(uc, &local_err); - if (local_err) { + if (!user_creatable_complete(uc, errp)) { if (id != NULL) { object_unparent(obj); } @@ -760,18 +806,17 @@ Object *object_new_with_propv(const char *typename, return obj; error: - error_propagate(errp, local_err); object_unref(obj); return NULL; } -int object_set_props(Object *obj, +bool object_set_props(Object *obj, Error **errp, ...) { va_list vargs; - int ret; + bool ret; va_start(vargs, errp); ret = object_set_propv(obj, errp, vargs); @@ -781,27 +826,24 @@ int object_set_props(Object *obj, } -int object_set_propv(Object *obj, +bool object_set_propv(Object *obj, Error **errp, va_list vargs) { const char *propname; - Error *local_err = NULL; propname = va_arg(vargs, char *); while (propname != NULL) { const char *value = va_arg(vargs, char *); g_assert(value != NULL); - object_property_parse(obj, value, propname, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return -1; + if (!object_property_parse(obj, propname, value, errp)) { + return false; } propname = va_arg(vargs, char *); } - return 0; + return true; } @@ -825,7 +867,7 @@ Object *object_dynamic_cast_assert(Object *obj, const char *typename, Object *inst; for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) { - if (atomic_read(&obj->class->object_cast_cache[i]) == typename) { + if (qatomic_read(&obj->class->object_cast_cache[i]) == typename) { goto out; } } @@ -842,10 +884,10 @@ Object *object_dynamic_cast_assert(Object *obj, const char *typename, if (obj && obj == inst) { for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) { - atomic_set(&obj->class->object_cast_cache[i - 1], - atomic_read(&obj->class->object_cast_cache[i])); + qatomic_set(&obj->class->object_cast_cache[i - 1], + qatomic_read(&obj->class->object_cast_cache[i])); } - atomic_set(&obj->class->object_cast_cache[i - 1], typename); + qatomic_set(&obj->class->object_cast_cache[i - 1], typename); } out: @@ -915,7 +957,7 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class, int i; for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) { - if (atomic_read(&class->class_cast_cache[i]) == typename) { + if (qatomic_read(&class->class_cast_cache[i]) == typename) { ret = class; goto out; } @@ -936,10 +978,10 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class, #ifdef CONFIG_QOM_CAST_DEBUG if (class && ret == class) { for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) { - atomic_set(&class->class_cast_cache[i - 1], - atomic_read(&class->class_cast_cache[i])); + qatomic_set(&class->class_cast_cache[i - 1], + qatomic_read(&class->class_cast_cache[i])); } - atomic_set(&class->class_cast_cache[i - 1], typename); + qatomic_set(&class->class_cast_cache[i - 1], typename); } out: #endif @@ -979,6 +1021,20 @@ ObjectClass *object_class_by_name(const char *typename) return type->class; } +ObjectClass *module_object_class_by_name(const char *typename) +{ + ObjectClass *oc; + + oc = object_class_by_name(typename); +#ifdef CONFIG_MODULES + if (!oc) { + module_load_qom_one(typename); + oc = object_class_by_name(typename); + } +#endif + return oc; +} + ObjectClass *object_class_get_parent(ObjectClass *class) { TypeImpl *type = type_get_parent(class->type); @@ -1051,7 +1107,10 @@ static int do_object_child_foreach(Object *obj, break; } if (recurse) { - do_object_child_foreach(child, fn, opaque, true); + ret = do_object_child_foreach(child, fn, opaque, true); + if (ret != 0) { + break; + } } } } @@ -1101,29 +1160,31 @@ GSList *object_class_get_list_sorted(const char *implements_type, object_class_cmp); } -Object *object_ref(Object *obj) +Object *object_ref(void *objptr) { + Object *obj = OBJECT(objptr); if (!obj) { return NULL; } - atomic_inc(&obj->ref); + qatomic_inc(&obj->ref); return obj; } -void object_unref(Object *obj) +void object_unref(void *objptr) { + Object *obj = OBJECT(objptr); if (!obj) { return; } g_assert(obj->ref > 0); /* parent always holds a reference to its children */ - if (atomic_fetch_dec(&obj->ref) == 1) { + if (qatomic_fetch_dec(&obj->ref) == 1) { object_finalize(obj); } } -static ObjectProperty * +ObjectProperty * object_property_try_add(Object *obj, const char *name, const char *type, ObjectPropertyAccessor *get, ObjectPropertyAccessor *set, @@ -1153,7 +1214,7 @@ object_property_try_add(Object *obj, const char *name, const char *type, return ret; } - if (object_property_find(obj, name, NULL) != NULL) { + if (object_property_find(obj, name) != NULL) { error_setg(errp, "attempt to add duplicate property '%s' to object (type '%s')", name, object_get_typename(obj)); return NULL; @@ -1195,7 +1256,7 @@ object_class_property_add(ObjectClass *klass, { ObjectProperty *prop; - assert(!object_class_property_find(klass, name, NULL)); + assert(!object_class_property_find(klass, name)); prop = g_malloc0(sizeof(*prop)); @@ -1212,24 +1273,28 @@ object_class_property_add(ObjectClass *klass, return prop; } -ObjectProperty *object_property_find(Object *obj, const char *name, - Error **errp) +ObjectProperty *object_property_find(Object *obj, const char *name) { ObjectProperty *prop; ObjectClass *klass = object_get_class(obj); - prop = object_class_property_find(klass, name, NULL); + prop = object_class_property_find(klass, name); if (prop) { return prop; } - prop = g_hash_table_lookup(obj->properties, name); - if (prop) { - return prop; - } + return g_hash_table_lookup(obj->properties, name); +} - error_setg(errp, "Property '.%s' not found", name); - return NULL; +ObjectProperty *object_property_find_err(Object *obj, const char *name, + Error **errp) +{ + ObjectProperty *prop = object_property_find(obj, name); + if (!prop) { + error_setg(errp, "Property '%s.%s' not found", + object_get_typename(obj), name); + } + return prop; } void object_property_iter_init(ObjectPropertyIterator *iter, @@ -1259,27 +1324,34 @@ void object_class_property_iter_init(ObjectPropertyIterator *iter, iter->nextclass = object_class_get_parent(klass); } -ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name, - Error **errp) +ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name) { - ObjectProperty *prop; ObjectClass *parent_klass; parent_klass = object_class_get_parent(klass); if (parent_klass) { - prop = object_class_property_find(parent_klass, name, NULL); + ObjectProperty *prop = + object_class_property_find(parent_klass, name); if (prop) { return prop; } } - prop = g_hash_table_lookup(klass->properties, name); + return g_hash_table_lookup(klass->properties, name); +} + +ObjectProperty *object_class_property_find_err(ObjectClass *klass, + const char *name, + Error **errp) +{ + ObjectProperty *prop = object_class_property_find(klass, name); if (!prop) { error_setg(errp, "Property '.%s' not found", name); } return prop; } + void object_property_del(Object *obj, const char *name) { ObjectProperty *prop = g_hash_table_lookup(obj->properties, name); @@ -1290,43 +1362,52 @@ void object_property_del(Object *obj, const char *name) g_hash_table_remove(obj->properties, name); } -void object_property_get(Object *obj, Visitor *v, const char *name, +bool object_property_get(Object *obj, const char *name, Visitor *v, Error **errp) { - ObjectProperty *prop = object_property_find(obj, name, errp); + Error *err = NULL; + ObjectProperty *prop = object_property_find_err(obj, name, errp); + if (prop == NULL) { - return; + return false; } if (!prop->get) { error_setg(errp, QERR_PERMISSION_DENIED); - } else { - prop->get(obj, v, name, prop->opaque, errp); + return false; } + prop->get(obj, v, name, prop->opaque, &err); + error_propagate(errp, err); + return !err; } -void object_property_set(Object *obj, Visitor *v, const char *name, +bool object_property_set(Object *obj, const char *name, Visitor *v, Error **errp) { - ObjectProperty *prop = object_property_find(obj, name, errp); + Error *err = NULL; + ObjectProperty *prop = object_property_find_err(obj, name, errp); + if (prop == NULL) { - return; + return false; } if (!prop->set) { error_setg(errp, QERR_PERMISSION_DENIED); - } else { - prop->set(obj, v, name, prop->opaque, errp); + return false; } + prop->set(obj, v, name, prop->opaque, &err); + error_propagate(errp, err); + return !err; } -void object_property_set_str(Object *obj, const char *value, - const char *name, Error **errp) +bool object_property_set_str(Object *obj, const char *name, + const char *value, Error **errp) { QString *qstr = qstring_from_str(value); - object_property_set_qobject(obj, QOBJECT(qstr), name, errp); + bool ok = object_property_set_qobject(obj, name, QOBJECT(qstr), errp); qobject_unref(qstr); + return ok; } char *object_property_get_str(Object *obj, const char *name, @@ -1348,16 +1429,15 @@ char *object_property_get_str(Object *obj, const char *name, return retval; } -void object_property_set_link(Object *obj, Object *value, - const char *name, Error **errp) +bool object_property_set_link(Object *obj, const char *name, + Object *value, Error **errp) { + g_autofree char *path = NULL; + if (value) { - char *path = object_get_canonical_path(value); - object_property_set_str(obj, path, name, errp); - g_free(path); - } else { - object_property_set_str(obj, "", name, errp); + path = object_get_canonical_path(value); } + return object_property_set_str(obj, name, path ?: "", errp); } Object *object_property_get_link(Object *obj, const char *name, @@ -1378,13 +1458,14 @@ Object *object_property_get_link(Object *obj, const char *name, return target; } -void object_property_set_bool(Object *obj, bool value, - const char *name, Error **errp) +bool object_property_set_bool(Object *obj, const char *name, + bool value, Error **errp) { QBool *qbool = qbool_from_bool(value); - object_property_set_qobject(obj, QOBJECT(qbool), name, errp); + bool ok = object_property_set_qobject(obj, name, QOBJECT(qbool), errp); qobject_unref(qbool); + return ok; } bool object_property_get_bool(Object *obj, const char *name, @@ -1409,13 +1490,14 @@ bool object_property_get_bool(Object *obj, const char *name, return retval; } -void object_property_set_int(Object *obj, int64_t value, - const char *name, Error **errp) +bool object_property_set_int(Object *obj, const char *name, + int64_t value, Error **errp) { QNum *qnum = qnum_from_int(value); - object_property_set_qobject(obj, QOBJECT(qnum), name, errp); + bool ok = object_property_set_qobject(obj, name, QOBJECT(qnum), errp); qobject_unref(qnum); + return ok; } int64_t object_property_get_int(Object *obj, const char *name, @@ -1478,13 +1560,14 @@ void object_property_set_default_uint(ObjectProperty *prop, uint64_t value) object_property_set_default(prop, QOBJECT(qnum_from_uint(value))); } -void object_property_set_uint(Object *obj, uint64_t value, - const char *name, Error **errp) +bool object_property_set_uint(Object *obj, const char *name, + uint64_t value, Error **errp) { QNum *qnum = qnum_from_uint(value); + bool ok = object_property_set_qobject(obj, name, QOBJECT(qnum), errp); - object_property_set_qobject(obj, QOBJECT(qnum), name, errp); qobject_unref(qnum); + return ok; } uint64_t object_property_get_uint(Object *obj, const char *name, @@ -1518,25 +1601,25 @@ int object_property_get_enum(Object *obj, const char *name, { char *str; int ret; - ObjectProperty *prop = object_property_find(obj, name, errp); + ObjectProperty *prop = object_property_find_err(obj, name, errp); EnumProperty *enumprop; if (prop == NULL) { - return 0; + return -1; } if (!g_str_equal(prop->type, typename)) { error_setg(errp, "Property %s on %s is not '%s' enum type", name, object_class_get_name( object_get_class(obj)), typename); - return 0; + return -1; } enumprop = prop->opaque; str = object_property_get_str(obj, name, errp); if (!str) { - return 0; + return -1; } ret = qapi_enum_parse(enumprop->lookup, str, -1, errp); @@ -1545,12 +1628,14 @@ int object_property_get_enum(Object *obj, const char *name, return ret; } -void object_property_parse(Object *obj, const char *string, - const char *name, Error **errp) +bool object_property_parse(Object *obj, const char *name, + const char *string, Error **errp) { Visitor *v = string_input_visitor_new(string); - object_property_set(obj, v, name, errp); + bool ok = object_property_set(obj, name, v, errp); + visit_free(v); + return ok; } char *object_property_print(Object *obj, const char *name, bool human, @@ -1558,12 +1643,9 @@ char *object_property_print(Object *obj, const char *name, bool human, { Visitor *v; char *string = NULL; - Error *local_err = NULL; v = string_output_visitor_new(human, &string); - object_property_get(obj, v, name, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!object_property_get(obj, name, v, errp)) { goto out; } @@ -1576,7 +1658,7 @@ out: const char *object_property_get_type(Object *obj, const char *name, Error **errp) { - ObjectProperty *prop = object_property_find(obj, name, errp); + ObjectProperty *prop = object_property_find_err(obj, name, errp); if (prop == NULL) { return NULL; } @@ -1642,8 +1724,8 @@ static void object_finalize_child_property(Object *obj, const char *name, } ObjectProperty * -object_property_add_child(Object *obj, const char *name, - Object *child) +object_property_try_add_child(Object *obj, const char *name, + Object *child, Error **errp) { g_autofree char *type = NULL; ObjectProperty *op; @@ -1652,14 +1734,25 @@ object_property_add_child(Object *obj, const char *name, type = g_strdup_printf("child<%s>", object_get_typename(child)); - op = object_property_add(obj, name, type, object_get_child_property, NULL, - object_finalize_child_property, child); + op = object_property_try_add(obj, name, type, object_get_child_property, + NULL, object_finalize_child_property, + child, errp); + if (!op) { + return NULL; + } op->resolve = object_resolve_child_property; object_ref(child); child->parent = obj; return op; } +ObjectProperty * +object_property_add_child(Object *obj, const char *name, + Object *child) +{ + return object_property_try_add_child(obj, name, child, &error_abort); +} + void object_property_allow_set_link(const Object *obj, const char *name, Object *val, Error **errp) { @@ -1754,20 +1847,24 @@ static void object_set_link_property(Object *obj, Visitor *v, LinkProperty *prop = opaque; Object **targetp = object_link_get_targetp(obj, prop); Object *old_target = *targetp; - Object *new_target = NULL; + Object *new_target; char *path = NULL; - visit_type_str(v, name, &path, &local_err); + if (!visit_type_str(v, name, &path, errp)) { + return; + } - if (!local_err && strcmp(path, "") != 0) { - new_target = object_resolve_link(obj, name, path, &local_err); + if (*path) { + new_target = object_resolve_link(obj, name, path, errp); + if (!new_target) { + g_free(path); + return; + } + } else { + new_target = NULL; } g_free(path); - if (local_err) { - error_propagate(errp, local_err); - return; - } prop->check(obj, name, new_target, &local_err); if (local_err) { @@ -1883,7 +1980,7 @@ object_property_add_const_link(Object *obj, const char *name, NULL, OBJ_PROP_LINK_DIRECT); } -char *object_get_canonical_path_component(Object *obj) +const char *object_get_canonical_path_component(const Object *obj) { ObjectProperty *prop = NULL; GHashTableIter iter; @@ -1899,7 +1996,7 @@ char *object_get_canonical_path_component(Object *obj) } if (prop->opaque == obj) { - return g_strdup(prop->name); + return prop->name; } } @@ -1908,7 +2005,7 @@ char *object_get_canonical_path_component(Object *obj) return NULL; } -char *object_get_canonical_path(Object *obj) +char *object_get_canonical_path(const Object *obj) { Object *root = object_get_root(); char *newpath, *path = NULL; @@ -1918,7 +2015,7 @@ char *object_get_canonical_path(Object *obj) } do { - char *component = object_get_canonical_path_component(obj); + const char *component = object_get_canonical_path_component(obj); if (!component) { /* A canonical path must be complete, so discard what was @@ -1930,7 +2027,6 @@ char *object_get_canonical_path(Object *obj) newpath = g_strdup_printf("/%s%s", component, path ? path : ""); g_free(path); - g_free(component); path = newpath; obj = obj->parent; } while (obj != root); @@ -1940,7 +2036,7 @@ char *object_get_canonical_path(Object *obj) Object *object_resolve_path_component(Object *parent, const char *part) { - ObjectProperty *prop = object_property_find(parent, part, NULL); + ObjectProperty *prop = object_property_find(parent, part); if (prop == NULL) { return NULL; } @@ -1953,26 +2049,25 @@ Object *object_resolve_path_component(Object *parent, const char *part) } static Object *object_resolve_abs_path(Object *parent, - char **parts, - const char *typename, - int index) + char **parts, + const char *typename) { Object *child; - if (parts[index] == NULL) { + if (*parts == NULL) { return object_dynamic_cast(parent, typename); } - if (strcmp(parts[index], "") == 0) { - return object_resolve_abs_path(parent, parts, typename, index + 1); + if (strcmp(*parts, "") == 0) { + return object_resolve_abs_path(parent, parts + 1, typename); } - child = object_resolve_path_component(parent, parts[index]); + child = object_resolve_path_component(parent, *parts); if (!child) { return NULL; } - return object_resolve_abs_path(child, parts, typename, index + 1); + return object_resolve_abs_path(child, parts + 1, typename); } static Object *object_resolve_partial_path(Object *parent, @@ -1984,7 +2079,7 @@ static Object *object_resolve_partial_path(Object *parent, GHashTableIter iter; ObjectProperty *prop; - obj = object_resolve_abs_path(parent, parts, typename, 0); + obj = object_resolve_abs_path(parent, parts, typename); g_hash_table_iter_init(&iter, parent->properties); while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { @@ -2029,7 +2124,7 @@ Object *object_resolve_path_type(const char *path, const char *typename, *ambiguousp = ambiguous; } } else { - obj = object_resolve_abs_path(object_get_root(), parts, typename, 1); + obj = object_resolve_abs_path(object_get_root(), parts + 1, typename); } g_strfreev(parts); @@ -2070,11 +2165,8 @@ static void property_set_str(Object *obj, Visitor *v, const char *name, { StringProperty *prop = opaque; char *value; - Error *local_err = NULL; - visit_type_str(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_str(v, name, &value, errp)) { return; } @@ -2151,11 +2243,8 @@ static void property_set_bool(Object *obj, Visitor *v, const char *name, { BoolProperty *prop = opaque; bool value; - Error *local_err = NULL; - visit_type_bool(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_bool(v, name, &value, errp)) { return; } @@ -2224,11 +2313,8 @@ static void property_set_enum(Object *obj, Visitor *v, const char *name, { EnumProperty *prop = opaque; int value; - Error *err = NULL; - visit_type_enum(v, name, &value, prop->lookup, &err); - if (err) { - error_propagate(errp, err); + if (!visit_type_enum(v, name, &value, prop->lookup, errp)) { return; } prop->set(obj, value, errp); @@ -2294,43 +2380,34 @@ static void property_get_tm(Object *obj, Visitor *v, const char *name, prop->get(obj, &value, &err); if (err) { - goto out; + error_propagate(errp, err); + return; } - visit_start_struct(v, name, NULL, 0, &err); - if (err) { - goto out; + if (!visit_start_struct(v, name, NULL, 0, errp)) { + return; } - visit_type_int32(v, "tm_year", &value.tm_year, &err); - if (err) { + if (!visit_type_int32(v, "tm_year", &value.tm_year, errp)) { goto out_end; } - visit_type_int32(v, "tm_mon", &value.tm_mon, &err); - if (err) { + if (!visit_type_int32(v, "tm_mon", &value.tm_mon, errp)) { goto out_end; } - visit_type_int32(v, "tm_mday", &value.tm_mday, &err); - if (err) { + if (!visit_type_int32(v, "tm_mday", &value.tm_mday, errp)) { goto out_end; } - visit_type_int32(v, "tm_hour", &value.tm_hour, &err); - if (err) { + if (!visit_type_int32(v, "tm_hour", &value.tm_hour, errp)) { goto out_end; } - visit_type_int32(v, "tm_min", &value.tm_min, &err); - if (err) { + if (!visit_type_int32(v, "tm_min", &value.tm_min, errp)) { goto out_end; } - visit_type_int32(v, "tm_sec", &value.tm_sec, &err); - if (err) { + if (!visit_type_int32(v, "tm_sec", &value.tm_sec, errp)) { goto out_end; } - visit_check_struct(v, &err); + visit_check_struct(v, errp); out_end: visit_end_struct(v, NULL); -out: - error_propagate(errp, err); - } static void property_release_tm(Object *obj, const char *name, @@ -2367,7 +2444,7 @@ object_class_property_add_tm(ObjectClass *klass, const char *name, NULL, NULL, prop); } -static char *qdev_get_type(Object *obj, Error **errp) +static char *object_get_type(Object *obj, Error **errp) { return g_strdup(object_get_typename(obj)); } @@ -2384,11 +2461,8 @@ static void property_set_uint8_ptr(Object *obj, Visitor *v, const char *name, { uint8_t *field = opaque; uint8_t value; - Error *local_err = NULL; - visit_type_uint8(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_uint8(v, name, &value, errp)) { return; } @@ -2407,11 +2481,8 @@ static void property_set_uint16_ptr(Object *obj, Visitor *v, const char *name, { uint16_t *field = opaque; uint16_t value; - Error *local_err = NULL; - visit_type_uint16(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_uint16(v, name, &value, errp)) { return; } @@ -2430,11 +2501,8 @@ static void property_set_uint32_ptr(Object *obj, Visitor *v, const char *name, { uint32_t *field = opaque; uint32_t value; - Error *local_err = NULL; - visit_type_uint32(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_uint32(v, name, &value, errp)) { return; } @@ -2453,11 +2521,8 @@ static void property_set_uint64_ptr(Object *obj, Visitor *v, const char *name, { uint64_t *field = opaque; uint64_t value; - Error *local_err = NULL; - visit_type_uint64(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_uint64(v, name, &value, errp)) { return; } @@ -2634,7 +2699,7 @@ static void property_get_alias(Object *obj, Visitor *v, const char *name, { AliasProperty *prop = opaque; - object_property_get(prop->target_obj, v, prop->target_name, errp); + object_property_get(prop->target_obj, prop->target_name, v, errp); } static void property_set_alias(Object *obj, Visitor *v, const char *name, @@ -2642,7 +2707,7 @@ static void property_set_alias(Object *obj, Visitor *v, const char *name, { AliasProperty *prop = opaque; - object_property_set(prop->target_obj, v, prop->target_name, errp); + object_property_set(prop->target_obj, prop->target_name, v, errp); } static Object *property_resolve_alias(Object *obj, void *opaque, @@ -2670,8 +2735,8 @@ object_property_add_alias(Object *obj, const char *name, ObjectProperty *target_prop; g_autofree char *prop_type = NULL; - target_prop = object_property_find(target_obj, target_name, - &error_abort); + target_prop = object_property_find_err(target_obj, target_name, + &error_abort); if (object_property_is_child(target_prop)) { prop_type = g_strdup_printf("link%s", @@ -2704,7 +2769,7 @@ void object_property_set_description(Object *obj, const char *name, { ObjectProperty *op; - op = object_property_find(obj, name, &error_abort); + op = object_property_find_err(obj, name, &error_abort); g_free(op->description); op->description = g_strdup(description); } @@ -2722,7 +2787,7 @@ void object_class_property_set_description(ObjectClass *klass, static void object_class_init(ObjectClass *klass, void *data) { - object_class_property_add_str(klass, "type", qdev_get_type, + object_class_property_add_str(klass, "type", object_get_type, NULL); } diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c index 7e26f86fa696a2fefb7e1197a97340c930cf07ba..ed896fe764ccf45de570d5da241936dcb8cf0fe4 100644 --- a/qom/object_interfaces.c +++ b/qom/object_interfaces.c @@ -14,13 +14,16 @@ #include "qapi/opts-visitor.h" #include "qemu/config-file.h" -void user_creatable_complete(UserCreatable *uc, Error **errp) +bool user_creatable_complete(UserCreatable *uc, Error **errp) { UserCreatableClass *ucc = USER_CREATABLE_GET_CLASS(uc); + Error *err = NULL; if (ucc->complete) { - ucc->complete(uc, errp); + ucc->complete(uc, &err); + error_propagate(errp, err); } + return !err; } bool user_creatable_can_be_deleted(UserCreatable *uc) @@ -63,13 +66,11 @@ Object *user_creatable_add_type(const char *type, const char *id, assert(qdict); obj = object_new(type); - visit_start_struct(v, NULL, NULL, 0, &local_err); - if (local_err) { + if (!visit_start_struct(v, NULL, NULL, 0, &local_err)) { goto out; } for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) { - object_property_set(obj, v, e->key, &local_err); - if (local_err) { + if (!object_property_set(obj, e->key, v, &local_err)) { break; } } @@ -82,12 +83,14 @@ Object *user_creatable_add_type(const char *type, const char *id, } if (id != NULL) { - object_property_add_child(object_get_objects_root(), - id, obj); + object_property_try_add_child(object_get_objects_root(), + id, obj, &local_err); + if (local_err) { + goto out; + } } - user_creatable_complete(USER_CREATABLE(obj), &local_err); - if (local_err) { + if (!user_creatable_complete(USER_CREATABLE(obj), &local_err)) { if (id != NULL) { object_property_del(object_get_objects_root(), id); } @@ -102,7 +105,7 @@ out: return obj; } -void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp) +bool user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp) { Visitor *v; Object *obj; @@ -112,14 +115,14 @@ void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp) type = g_strdup(qdict_get_try_str(qdict, "qom-type")); if (!type) { error_setg(errp, QERR_MISSING_PARAMETER, "qom-type"); - return; + return false; } qdict_del(qdict, "qom-type"); id = g_strdup(qdict_get_try_str(qdict, "id")); if (!id) { error_setg(errp, QERR_MISSING_PARAMETER, "id"); - return; + return false; } qdict_del(qdict, "id"); @@ -131,6 +134,7 @@ void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp) obj = user_creatable_add_type(type, id, qdict, v, errp); visit_free(v); object_unref(obj); + return !!obj; } Object *user_creatable_add_opts(QemuOpts *opts, Error **errp) @@ -210,58 +214,81 @@ char *object_property_help(const char *name, const char *type, return g_string_free(str, false); } -bool user_creatable_print_help(const char *type, QemuOpts *opts) +static void user_creatable_print_types(void) +{ + GSList *l, *list; + + printf("List of user creatable objects:\n"); + list = object_class_get_list_sorted(TYPE_USER_CREATABLE, false); + for (l = list; l != NULL; l = l->next) { + ObjectClass *oc = OBJECT_CLASS(l->data); + printf(" %s\n", object_class_get_name(oc)); + } + g_slist_free(list); +} + +static bool user_creatable_print_type_properites(const char *type) { ObjectClass *klass; + ObjectPropertyIterator iter; + ObjectProperty *prop; + GPtrArray *array; + int i; - if (is_help_option(type)) { - GSList *l, *list; + klass = object_class_by_name(type); + if (!klass) { + return false; + } - printf("List of user creatable objects:\n"); - list = object_class_get_list_sorted(TYPE_USER_CREATABLE, false); - for (l = list; l != NULL; l = l->next) { - ObjectClass *oc = OBJECT_CLASS(l->data); - printf(" %s\n", object_class_get_name(oc)); + array = g_ptr_array_new(); + object_class_property_iter_init(&iter, klass); + while ((prop = object_property_iter_next(&iter))) { + if (!prop->set) { + continue; } - g_slist_free(list); - return true; + + g_ptr_array_add(array, + object_property_help(prop->name, prop->type, + prop->defval, prop->description)); } + g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0); + if (array->len > 0) { + printf("%s options:\n", type); + } else { + printf("There are no options for %s.\n", type); + } + for (i = 0; i < array->len; i++) { + printf("%s\n", (char *)array->pdata[i]); + } + g_ptr_array_set_free_func(array, g_free); + g_ptr_array_free(array, true); + return true; +} - klass = object_class_by_name(type); - if (klass && qemu_opt_has_help_opt(opts)) { - ObjectPropertyIterator iter; - ObjectProperty *prop; - GPtrArray *array = g_ptr_array_new(); - int i; - - object_class_property_iter_init(&iter, klass); - while ((prop = object_property_iter_next(&iter))) { - if (!prop->set) { - continue; - } - - g_ptr_array_add(array, - object_property_help(prop->name, prop->type, - prop->defval, prop->description)); - } - g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0); - if (array->len > 0) { - printf("%s options:\n", type); - } else { - printf("There are no options for %s.\n", type); - } - for (i = 0; i < array->len; i++) { - printf("%s\n", (char *)array->pdata[i]); - } - g_ptr_array_set_free_func(array, g_free); - g_ptr_array_free(array, true); +bool user_creatable_print_help(const char *type, QemuOpts *opts) +{ + if (is_help_option(type)) { + user_creatable_print_types(); return true; } + if (qemu_opt_has_help_opt(opts)) { + return user_creatable_print_type_properites(type); + } + return false; } -void user_creatable_del(const char *id, Error **errp) +void user_creatable_print_help_from_qdict(QDict *args) +{ + const char *type = qdict_get_try_str(args, "qom-type"); + + if (!type || !user_creatable_print_type_properites(type)) { + user_creatable_print_types(); + } +} + +bool user_creatable_del(const char *id, Error **errp) { Object *container; Object *obj; @@ -270,12 +297,12 @@ void user_creatable_del(const char *id, Error **errp) obj = object_resolve_path_component(container, id); if (!obj) { error_setg(errp, "object '%s' not found", id); - return; + return false; } if (!user_creatable_can_be_deleted(USER_CREATABLE(obj))) { error_setg(errp, "object '%s' is in use, can not be deleted", id); - return; + return false; } /* @@ -286,6 +313,7 @@ void user_creatable_del(const char *id, Error **errp) id)); object_unparent(obj); + return true; } void user_creatable_cleanup(void) diff --git a/qom/qom-hmp-cmds.c b/qom/qom-hmp-cmds.c index cd08233a4cfe882a1e2de880a1e27bdd4fffdb2c..8861a109d5d35239ab943f00c58233937ecc14ae 100644 --- a/qom/qom-hmp-cmds.c +++ b/qom/qom-hmp-cmds.c @@ -12,6 +12,8 @@ #include "qapi/error.h" #include "qapi/qapi-commands-qom.h" #include "qapi/qmp/qdict.h" +#include "qapi/qmp/qjson.h" +#include "qapi/qmp/qstring.h" #include "qom/object.h" void hmp_qom_list(Monitor *mon, const QDict *qdict) @@ -42,23 +44,46 @@ void hmp_qom_list(Monitor *mon, const QDict *qdict) void hmp_qom_set(Monitor *mon, const QDict *qdict) { + const bool json = qdict_get_try_bool(qdict, "json", false); const char *path = qdict_get_str(qdict, "path"); const char *property = qdict_get_str(qdict, "property"); const char *value = qdict_get_str(qdict, "value"); Error *err = NULL; - bool ambiguous = false; - Object *obj; - obj = object_resolve_path(path, &ambiguous); - if (obj == NULL) { - error_set(&err, ERROR_CLASS_DEVICE_NOT_FOUND, - "Device '%s' not found", path); + if (!json) { + Object *obj = object_resolve_path(path, NULL); + + if (!obj) { + error_set(&err, ERROR_CLASS_DEVICE_NOT_FOUND, + "Device '%s' not found", path); + } else { + object_property_parse(obj, property, value, &err); + } } else { - if (ambiguous) { - monitor_printf(mon, "Warning: Path '%s' is ambiguous\n", path); + QObject *obj = qobject_from_json(value, &err); + + if (!err) { + qmp_qom_set(path, property, obj, &err); } - object_property_parse(obj, value, property, &err); } + + hmp_handle_error(mon, err); +} + +void hmp_qom_get(Monitor *mon, const QDict *qdict) +{ + const char *path = qdict_get_str(qdict, "path"); + const char *property = qdict_get_str(qdict, "property"); + Error *err = NULL; + QObject *obj = qmp_qom_get(path, property, &err); + + if (err == NULL) { + QString *str = qobject_to_json_pretty(obj); + monitor_printf(mon, "%s\n", qstring_get_str(str)); + qobject_unref(str); + } + + qobject_unref(obj); hmp_handle_error(mon, err); } @@ -69,32 +94,40 @@ typedef struct QOMCompositionState { static void print_qom_composition(Monitor *mon, Object *obj, int indent); -static int print_qom_composition_child(Object *obj, void *opaque) +static int qom_composition_compare(const void *a, const void *b) { - QOMCompositionState *s = opaque; - - print_qom_composition(s->mon, obj, s->indent); + return g_strcmp0(object_get_canonical_path_component(*(Object **)a), + object_get_canonical_path_component(*(Object **)b)); +} +static int insert_qom_composition_child(Object *obj, void *opaque) +{ + g_array_append_val(opaque, obj); return 0; } static void print_qom_composition(Monitor *mon, Object *obj, int indent) { - QOMCompositionState s = { - .mon = mon, - .indent = indent + 2, - }; - char *name; + GArray *children = g_array_new(false, false, sizeof(Object *)); + const char *name; + int i; if (obj == object_get_root()) { - name = g_strdup(""); + name = ""; } else { name = object_get_canonical_path_component(obj); } monitor_printf(mon, "%*s/%s (%s)\n", indent, "", name, object_get_typename(obj)); - g_free(name); - object_child_foreach(obj, print_qom_composition_child, &s); + + object_child_foreach(obj, insert_qom_composition_child, children); + g_array_sort(children, qom_composition_compare); + + for (i = 0; i < children->len; i++) { + print_qom_composition(mon, g_array_index(children, Object *, i), + indent + 2); + } + g_array_free(children, TRUE); } void hmp_info_qom_tree(Monitor *mon, const QDict *dict) diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c index c5249e44d020c99df52485527e1b3b29acd47415..310ab2d0481d1517b0432be23256c898aa7eb137 100644 --- a/qom/qom-qmp-cmds.c +++ b/qom/qom-qmp-cmds.c @@ -71,7 +71,7 @@ void qmp_qom_set(const char *path, const char *property, QObject *value, return; } - object_property_set_qobject(obj, value, property, errp); + object_property_set_qobject(obj, property, value, errp); } QObject *qmp_qom_get(const char *path, const char *property, Error **errp) @@ -116,6 +116,7 @@ ObjectTypeInfoList *qmp_qom_list_types(bool has_implements, { ObjectTypeInfoList *ret = NULL; + module_load_qom_all(); object_class_foreach(qom_list_types_tramp, implements, abstract, &ret); return ret; @@ -130,7 +131,7 @@ ObjectPropertyInfoList *qmp_device_list_properties(const char *typename, ObjectPropertyIterator iter; ObjectPropertyInfoList *prop_list = NULL; - klass = object_class_by_name(typename); + klass = module_object_class_by_name(typename); if (klass == NULL) { error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, "Device '%s' not found", typename); diff --git a/qom/qom-qobject.c b/qom/qom-qobject.c index c3b95aa354da8838fa7c68a2242be8bd8e1b943d..21ce22de94b71ac98ef9ac7f9b8747a8a64c91f7 100644 --- a/qom/qom-qobject.c +++ b/qom/qom-qobject.c @@ -17,29 +17,29 @@ #include "qapi/qobject-input-visitor.h" #include "qapi/qobject-output-visitor.h" -void object_property_set_qobject(Object *obj, QObject *value, - const char *name, Error **errp) +bool object_property_set_qobject(Object *obj, + const char *name, QObject *value, + Error **errp) { Visitor *v; + bool ok; v = qobject_input_visitor_new(value); - object_property_set(obj, v, name, errp); + ok = object_property_set(obj, name, v, errp); visit_free(v); + return ok; } QObject *object_property_get_qobject(Object *obj, const char *name, Error **errp) { QObject *ret = NULL; - Error *local_err = NULL; Visitor *v; v = qobject_output_visitor_new(&ret); - object_property_get(obj, v, name, &local_err); - if (!local_err) { + if (object_property_get(obj, name, v, errp)) { visit_complete(v, &ret); } - error_propagate(errp, local_err); visit_free(v); return ret; } diff --git a/qom/trace.h b/qom/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..f2895e699ba8bb1310fa1b2b2dfa7326f323a142 --- /dev/null +++ b/qom/trace.h @@ -0,0 +1 @@ +#include "trace/trace-qom.h" diff --git a/replay/Makefile.objs b/replay/Makefile.objs deleted file mode 100644 index 939be964a91ee3b40073878bd2952ae2bece2667..0000000000000000000000000000000000000000 --- a/replay/Makefile.objs +++ /dev/null @@ -1,10 +0,0 @@ -common-obj-y += replay.o -common-obj-y += replay-internal.o -common-obj-y += replay-events.o -common-obj-y += replay-time.o -common-obj-y += replay-input.o -common-obj-y += replay-char.o -common-obj-y += replay-snapshot.o -common-obj-y += replay-net.o -common-obj-y += replay-audio.o -common-obj-y += replay-random.o diff --git a/replay/meson.build b/replay/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..21aefad220c82a7e915c9adeb51dde959ef61504 --- /dev/null +++ b/replay/meson.build @@ -0,0 +1,13 @@ +softmmu_ss.add(when: 'CONFIG_TCG', if_true: files( + 'replay.c', + 'replay-internal.c', + 'replay-events.c', + 'replay-time.c', + 'replay-input.c', + 'replay-char.c', + 'replay-snapshot.c', + 'replay-net.c', + 'replay-audio.c', + 'replay-random.c', + 'replay-debugging.c', +), if_false: files('stubs-system.c')) diff --git a/replay/replay-debugging.c b/replay/replay-debugging.c new file mode 100644 index 0000000000000000000000000000000000000000..1d6a968406037d5bb401c7a110c9770f7f794c82 --- /dev/null +++ b/replay/replay-debugging.c @@ -0,0 +1,331 @@ +/* + * replay-debugging.c + * + * Copyright (c) 2010-2020 Institute for System Programming + * of the Russian Academy of Sciences. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "sysemu/replay.h" +#include "sysemu/runstate.h" +#include "replay-internal.h" +#include "monitor/hmp.h" +#include "monitor/monitor.h" +#include "qapi/qapi-commands-replay.h" +#include "qapi/qmp/qdict.h" +#include "qemu/timer.h" +#include "block/snapshot.h" +#include "migration/snapshot.h" + +static bool replay_is_debugging; +static int64_t replay_last_breakpoint; +static int64_t replay_last_snapshot; + +bool replay_running_debug(void) +{ + return replay_is_debugging; +} + +void hmp_info_replay(Monitor *mon, const QDict *qdict) +{ + if (replay_mode == REPLAY_MODE_NONE) { + monitor_printf(mon, "Record/replay is not active\n"); + } else { + monitor_printf(mon, + "%s execution '%s': instruction count = %"PRId64"\n", + replay_mode == REPLAY_MODE_RECORD ? "Recording" : "Replaying", + replay_get_filename(), replay_get_current_icount()); + } +} + +ReplayInfo *qmp_query_replay(Error **errp) +{ + ReplayInfo *retval = g_new0(ReplayInfo, 1); + + retval->mode = replay_mode; + if (replay_get_filename()) { + retval->filename = g_strdup(replay_get_filename()); + retval->has_filename = true; + } + retval->icount = replay_get_current_icount(); + return retval; +} + +static void replay_break(uint64_t icount, QEMUTimerCB callback, void *opaque) +{ + assert(replay_mode == REPLAY_MODE_PLAY); + assert(replay_mutex_locked()); + assert(replay_break_icount >= replay_get_current_icount()); + assert(callback); + + replay_break_icount = icount; + + if (replay_break_timer) { + timer_del(replay_break_timer); + } + replay_break_timer = timer_new_ns(QEMU_CLOCK_REALTIME, + callback, opaque); +} + +static void replay_delete_break(void) +{ + assert(replay_mode == REPLAY_MODE_PLAY); + assert(replay_mutex_locked()); + + if (replay_break_timer) { + timer_del(replay_break_timer); + timer_free(replay_break_timer); + replay_break_timer = NULL; + } + replay_break_icount = -1ULL; +} + +static void replay_stop_vm(void *opaque) +{ + vm_stop(RUN_STATE_PAUSED); + replay_delete_break(); +} + +void qmp_replay_break(int64_t icount, Error **errp) +{ + if (replay_mode == REPLAY_MODE_PLAY) { + if (icount >= replay_get_current_icount()) { + replay_break(icount, replay_stop_vm, NULL); + } else { + error_setg(errp, + "cannot set breakpoint at the instruction in the past"); + } + } else { + error_setg(errp, "setting the breakpoint is allowed only in play mode"); + } +} + +void hmp_replay_break(Monitor *mon, const QDict *qdict) +{ + int64_t icount = qdict_get_try_int(qdict, "icount", -1LL); + Error *err = NULL; + + qmp_replay_break(icount, &err); + if (err) { + error_report_err(err); + return; + } +} + +void qmp_replay_delete_break(Error **errp) +{ + if (replay_mode == REPLAY_MODE_PLAY) { + replay_delete_break(); + } else { + error_setg(errp, "replay breakpoints are allowed only in play mode"); + } +} + +void hmp_replay_delete_break(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + + qmp_replay_delete_break(&err); + if (err) { + error_report_err(err); + return; + } +} + +static char *replay_find_nearest_snapshot(int64_t icount, + int64_t *snapshot_icount) +{ + BlockDriverState *bs; + QEMUSnapshotInfo *sn_tab; + QEMUSnapshotInfo *nearest = NULL; + char *ret = NULL; + int nb_sns, i; + AioContext *aio_context; + + *snapshot_icount = -1; + + bs = bdrv_all_find_vmstate_bs(); + if (!bs) { + goto fail; + } + aio_context = bdrv_get_aio_context(bs); + + aio_context_acquire(aio_context); + nb_sns = bdrv_snapshot_list(bs, &sn_tab); + aio_context_release(aio_context); + + for (i = 0; i < nb_sns; i++) { + if (bdrv_all_find_snapshot(sn_tab[i].name, &bs) == 0) { + if (sn_tab[i].icount != -1ULL + && sn_tab[i].icount <= icount + && (!nearest || nearest->icount < sn_tab[i].icount)) { + nearest = &sn_tab[i]; + } + } + } + if (nearest) { + ret = g_strdup(nearest->name); + *snapshot_icount = nearest->icount; + } + g_free(sn_tab); + +fail: + return ret; +} + +static void replay_seek(int64_t icount, QEMUTimerCB callback, Error **errp) +{ + char *snapshot = NULL; + int64_t snapshot_icount; + + if (replay_mode != REPLAY_MODE_PLAY) { + error_setg(errp, "replay must be enabled to seek"); + return; + } + + snapshot = replay_find_nearest_snapshot(icount, &snapshot_icount); + if (snapshot) { + if (icount < replay_get_current_icount() + || replay_get_current_icount() < snapshot_icount) { + vm_stop(RUN_STATE_RESTORE_VM); + load_snapshot(snapshot, errp); + } + g_free(snapshot); + } + if (replay_get_current_icount() <= icount) { + replay_break(icount, callback, NULL); + vm_start(); + } else { + error_setg(errp, "cannot seek to the specified instruction count"); + } +} + +void qmp_replay_seek(int64_t icount, Error **errp) +{ + replay_seek(icount, replay_stop_vm, errp); +} + +void hmp_replay_seek(Monitor *mon, const QDict *qdict) +{ + int64_t icount = qdict_get_try_int(qdict, "icount", -1LL); + Error *err = NULL; + + qmp_replay_seek(icount, &err); + if (err) { + error_report_err(err); + return; + } +} + +static void replay_stop_vm_debug(void *opaque) +{ + replay_is_debugging = false; + vm_stop(RUN_STATE_DEBUG); + replay_delete_break(); +} + +bool replay_reverse_step(void) +{ + Error *err = NULL; + + assert(replay_mode == REPLAY_MODE_PLAY); + + if (replay_get_current_icount() != 0) { + replay_seek(replay_get_current_icount() - 1, + replay_stop_vm_debug, &err); + if (err) { + error_free(err); + return false; + } + replay_is_debugging = true; + return true; + } + + return false; +} + +static void replay_continue_end(void) +{ + replay_is_debugging = false; + vm_stop(RUN_STATE_DEBUG); + replay_delete_break(); +} + +static void replay_continue_stop(void *opaque) +{ + Error *err = NULL; + if (replay_last_breakpoint != -1LL) { + replay_seek(replay_last_breakpoint, replay_stop_vm_debug, &err); + if (err) { + error_free(err); + replay_continue_end(); + } + return; + } + /* + * No breakpoints since the last snapshot. + * Find previous snapshot and try again. + */ + if (replay_last_snapshot != 0) { + replay_seek(replay_last_snapshot - 1, replay_continue_stop, &err); + if (err) { + error_free(err); + replay_continue_end(); + } + replay_last_snapshot = replay_get_current_icount(); + } else { + /* Seek to the very first step */ + replay_seek(0, replay_stop_vm_debug, &err); + if (err) { + error_free(err); + replay_continue_end(); + } + } +} + +bool replay_reverse_continue(void) +{ + Error *err = NULL; + + assert(replay_mode == REPLAY_MODE_PLAY); + + if (replay_get_current_icount() != 0) { + replay_seek(replay_get_current_icount() - 1, + replay_continue_stop, &err); + if (err) { + error_free(err); + return false; + } + replay_last_breakpoint = -1LL; + replay_is_debugging = true; + replay_last_snapshot = replay_get_current_icount(); + return true; + } + + return false; +} + +void replay_breakpoint(void) +{ + assert(replay_mode == REPLAY_MODE_PLAY); + replay_last_breakpoint = replay_get_current_icount(); +} + +void replay_gdb_attached(void) +{ + /* + * Create VM snapshot on temporary overlay to allow reverse + * debugging even if snapshots were not enabled. + */ + if (replay_mode == REPLAY_MODE_PLAY + && !replay_snapshot) { + if (save_snapshot("start_debugging", NULL) != 0) { + /* Can't create the snapshot. Continue conventional debugging. */ + } + } +} diff --git a/replay/replay-events.c b/replay/replay-events.c index 302b84043af2643c7ab41f6d13794fe9e56c045d..a1c6bb934e78ef3471631230cee4162d94243cd7 100644 --- a/replay/replay-events.c +++ b/replay/replay-events.c @@ -77,6 +77,10 @@ bool replay_has_events(void) void replay_flush_events(void) { + if (replay_mode == REPLAY_MODE_NONE) { + return; + } + g_assert(replay_mutex_locked()); while (!QTAILQ_EMPTY(&events_list)) { diff --git a/replay/replay-internal.c b/replay/replay-internal.c index eba8246aae976b5dcc729f8eb9ffdddbd2155da8..2e8a3e947a5b22faaae14ca8c1c85439dafce720 100644 --- a/replay/replay-internal.c +++ b/replay/replay-internal.c @@ -22,6 +22,9 @@ It also protects replay events queue which stores events to be written or read to the log. */ static QemuMutex lock; +/* Condition and queue for fair ordering of mutex lock requests. */ +static QemuCond mutex_cond; +static unsigned long mutex_head, mutex_tail; /* File for replay writing */ static bool write_error; @@ -197,9 +200,10 @@ static __thread bool replay_locked; void replay_mutex_init(void) { qemu_mutex_init(&lock); + qemu_cond_init(&mutex_cond); /* Hold the mutex while we start-up */ - qemu_mutex_lock(&lock); replay_locked = true; + ++mutex_tail; } bool replay_mutex_locked(void) @@ -211,10 +215,16 @@ bool replay_mutex_locked(void) void replay_mutex_lock(void) { if (replay_mode != REPLAY_MODE_NONE) { + unsigned long id; g_assert(!qemu_mutex_iothread_locked()); g_assert(!replay_mutex_locked()); qemu_mutex_lock(&lock); + id = mutex_tail++; + while (id != mutex_head) { + qemu_cond_wait(&mutex_cond, &lock); + } replay_locked = true; + qemu_mutex_unlock(&lock); } } @@ -222,7 +232,10 @@ void replay_mutex_unlock(void) { if (replay_mode != REPLAY_MODE_NONE) { g_assert(replay_mutex_locked()); + qemu_mutex_lock(&lock); + ++mutex_head; replay_locked = false; + qemu_cond_broadcast(&mutex_cond); qemu_mutex_unlock(&lock); } } diff --git a/replay/replay-internal.h b/replay/replay-internal.h index 33ac551e78ea92a6e3897531d26a01ae25140874..97649ed8d77b0d8785f498c5ae4a26596764e402 100644 --- a/replay/replay-internal.h +++ b/replay/replay-internal.h @@ -94,6 +94,10 @@ extern ReplayState replay_state; /* File for replay writing */ extern FILE *replay_file; +/* Instruction count of the replay breakpoint */ +extern uint64_t replay_break_icount; +/* Timer for the replay breakpoint callback */ +extern QEMUTimer *replay_break_timer; void replay_put_byte(uint8_t byte); void replay_put_event(uint8_t event); @@ -145,8 +149,6 @@ void replay_read_next_clock(unsigned int kind); void replay_init_events(void); /*! Clears internal data structures for events handling */ void replay_finish_events(void); -/*! Flushes events queue */ -void replay_flush_events(void); /*! Returns true if there are any unsaved events in the queue */ bool replay_has_events(void); /*! Saves events from queue into the file */ diff --git a/replay/replay.c b/replay/replay.c index 706c7b4f4b1f2c794bc1aa190d542b77d8d8d399..d4c228ab28b02ffff45bacb5892143510e8375c3 100644 --- a/replay/replay.c +++ b/replay/replay.c @@ -11,10 +11,10 @@ #include "qemu/osdep.h" #include "qapi/error.h" +#include "sysemu/cpu-timers.h" #include "sysemu/replay.h" #include "sysemu/runstate.h" #include "replay-internal.h" -#include "qemu/timer.h" #include "qemu/main-loop.h" #include "qemu/option.h" #include "sysemu/cpus.h" @@ -22,7 +22,7 @@ /* Current version of the replay mechanism. Increase it when file format changes. */ -#define REPLAY_VERSION 0xe02009 +#define REPLAY_VERSION 0xe0200a /* Size of replay log header */ #define HEADER_SIZE (sizeof(uint32_t) + sizeof(uint64_t)) @@ -34,6 +34,10 @@ static char *replay_filename; ReplayState replay_state; static GSList *replay_blockers; +/* Replay breakpoints */ +uint64_t replay_break_icount = -1ULL; +QEMUTimer *replay_break_timer; + bool replay_next_event_is(int event) { bool res = false; @@ -64,7 +68,7 @@ bool replay_next_event_is(int event) uint64_t replay_get_current_icount(void) { - return cpu_get_icount_raw(); + return icount_get_raw(); } int replay_get_instructions(void) @@ -73,6 +77,13 @@ int replay_get_instructions(void) replay_mutex_lock(); if (replay_next_event_is(EVENT_INSTRUCTION)) { res = replay_state.instruction_count; + if (replay_break_icount != -1LL) { + uint64_t current = replay_get_current_icount(); + assert(replay_break_icount >= current); + if (current + res > replay_break_icount) { + res = replay_break_icount - current; + } + } } replay_mutex_unlock(); return res; @@ -99,6 +110,12 @@ void replay_account_executed_instructions(void) will be read from the log. */ qemu_notify_event(); } + /* Execution reached the break step */ + if (replay_break_icount == replay_state.current_icount) { + /* Cannot make callback directly from the vCPU thread */ + timer_mod_ns(replay_break_timer, + qemu_clock_get_ns(QEMU_CLOCK_REALTIME)); + } } } } @@ -345,7 +362,7 @@ void replay_start(void) error_reportf_err(replay_blockers->data, "Record/replay: "); exit(1); } - if (!use_icount) { + if (!icount_enabled()) { error_report("Please enable icount to use record/replay"); exit(1); } @@ -366,6 +383,11 @@ void replay_finish(void) /* finalize the file */ if (replay_file) { if (replay_mode == REPLAY_MODE_RECORD) { + /* + * Can't do it in the signal handler, therefore + * add shutdown event here for the case of Ctrl-C. + */ + replay_shutdown_request(SHUTDOWN_CAUSE_HOST_SIGNAL); /* write end event */ replay_put_event(EVENT_END); @@ -394,3 +416,8 @@ void replay_add_blocker(Error *reason) { replay_blockers = g_slist_prepend(replay_blockers, reason); } + +const char *replay_get_filename(void) +{ + return replay_filename; +} diff --git a/replay/stubs-system.c b/replay/stubs-system.c new file mode 100644 index 0000000000000000000000000000000000000000..5c262b08f156fc28ef3f9cb98f42b23db4edea67 --- /dev/null +++ b/replay/stubs-system.c @@ -0,0 +1,96 @@ +#include "qemu/osdep.h" +#include "sysemu/replay.h" +#include "ui/input.h" + +void replay_input_event(QemuConsole *src, InputEvent *evt) +{ + qemu_input_event_send_impl(src, evt); +} + +void replay_input_sync_event(void) +{ + qemu_input_event_sync_impl(); +} + +void replay_add_blocker(Error *reason) +{ +} +void replay_audio_in(size_t *recorded, void *samples, size_t *wpos, size_t size) +{ +} +void replay_audio_out(size_t *played) +{ +} +void replay_breakpoint(void) +{ +} +bool replay_can_snapshot(void) +{ + return true; +} +void replay_configure(struct QemuOpts *opts) +{ +} +void replay_flush_events(void) +{ +} +void replay_gdb_attached(void) +{ +} +bool replay_running_debug(void) +{ + return false; +} +void replay_shutdown_request(ShutdownCause cause) +{ +} +void replay_start(void) +{ +} +void replay_vmstate_init(void) +{ +} + +#include "monitor/monitor.h" +#include "monitor/hmp.h" +#include "qapi/qapi-commands-replay.h" +#include "qapi/error.h" +#include "qemu/error-report.h" + +void hmp_info_replay(Monitor *mon, const QDict *qdict) +{ + error_report("replay support not available"); +} +void hmp_replay_break(Monitor *mon, const QDict *qdict) +{ + error_report("replay support not available"); +} +void hmp_replay_delete_break(Monitor *mon, const QDict *qdict) +{ + error_report("replay support not available"); +} +void hmp_replay_seek(Monitor *mon, const QDict *qdict) +{ + error_report("replay support not available"); +} +ReplayInfo *qmp_query_replay(Error **errp) +{ + error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, + "replay support not available"); + return NULL; +} +void qmp_replay_break(int64_t icount, Error **errp) +{ + error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, + "replay support not available"); +} +void qmp_replay_delete_break(Error **errp) +{ + error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, + "replay support not available"); +} +void qmp_replay_seek(int64_t icount, Error **errp) +{ + error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, + "replay support not available"); +} diff --git a/roms/Makefile b/roms/Makefile index f9acf39954dcf96618fab21cafe76fcbb487964f..5ffe3317acd233586e1a2f87bddd6c8f9c3e38df 100644 --- a/roms/Makefile +++ b/roms/Makefile @@ -34,6 +34,7 @@ find-cross-gcc = $(firstword $(wildcard $(patsubst %ld,%gcc,$(call find-cross-ld # finally strip off path + toolname so we get the prefix find-cross-prefix = $(subst gcc,,$(notdir $(call find-cross-gcc,$(1)))) +arm_cross_prefix := $(call find-cross-prefix,arm) powerpc64_cross_prefix := $(call find-cross-prefix,powerpc64) powerpc_cross_prefix := $(call find-cross-prefix,powerpc) x86_64_cross_prefix := $(call find-cross-prefix,x86_64) @@ -63,18 +64,20 @@ default help: @echo " skiboot -- update skiboot.lid" @echo " u-boot.e500 -- update u-boot.e500" @echo " u-boot.sam460 -- update u-boot.sam460" + @echo " npcm7xx_bootrom -- update vbootrom for npcm7xx" @echo " efi -- update UEFI (edk2) platform firmware" - @echo " opensbi32-virt -- update OpenSBI for 32-bit virt machine" - @echo " opensbi64-virt -- update OpenSBI for 64-bit virt machine" - @echo " opensbi32-sifive_u -- update OpenSBI for 32-bit sifive_u machine" - @echo " opensbi64-sifive_u -- update OpenSBI for 64-bit sifive_u machine" - @echo " bios-microvm -- update bios-microvm.bin (qboot)" + @echo " opensbi32-generic -- update OpenSBI for 32-bit generic machine" + @echo " opensbi64-generic -- update OpenSBI for 64-bit generic machine" + @echo " qboot -- update qboot" @echo " clean -- delete the files generated by the previous" \ "build targets" -bios: build-seabios-config-seabios-128k build-seabios-config-seabios-256k +bios: build-seabios-config-seabios-128k \ + build-seabios-config-seabios-256k \ + build-seabios-config-seabios-microvm cp seabios/builds/seabios-128k/bios.bin ../pc-bios/bios.bin cp seabios/builds/seabios-256k/bios.bin ../pc-bios/bios-256k.bin + cp seabios/builds/seabios-microvm/bios.bin ../pc-bios/bios-microvm.bin vgabios seavgabios: $(patsubst %,seavgabios-%,$(vgabios_variants)) @@ -99,7 +102,7 @@ build-seabios-config-%: config.% OUT=$(CURDIR)/seabios/builds/$*/ all -.PHONY: sgabios skiboot +.PHONY: sgabios skiboot qboot sgabios: $(MAKE) -C sgabios cp sgabios/sgabios.bin ../pc-bios @@ -115,7 +118,6 @@ efirom: $(patsubst %,efi-rom-%,$(pxerom_variants)) efi-rom-%: build-pxe-roms build-efi-roms edk2-basetools $(EDK2_EFIROM) -f "0x$(VID)" -i "0x$(DID)" -l 0x02 \ -b ipxe/src/bin/$(VID)$(DID).rom \ - -ec ipxe/src/bin-i386-efi/$(VID)$(DID).efidrv \ -ec ipxe/src/bin-x86_64-efi/$(VID)$(DID).efidrv \ -o ../pc-bios/efi-$*.rom @@ -127,7 +129,6 @@ build-pxe-roms: build-efi-roms: build-pxe-roms $(MAKE) -C ipxe/src CONFIG=qemu \ CROSS_COMPILE=$(x86_64_cross_prefix) \ - $(patsubst %,bin-i386-efi/%.efidrv,$(pxerom_targets)) \ $(patsubst %,bin-x86_64-efi/%.efidrv,$(pxerom_targets)) # Build scripts can pass compiler/linker flags to the EDK2 @@ -142,6 +143,7 @@ build-efi-roms: build-pxe-roms # efirom # edk2-basetools: + cd edk2/BaseTools && git submodule update --init --force $(MAKE) -C edk2/BaseTools \ PYTHON_COMMAND=$${EDK2_PYTHON_COMMAND:-python3} \ EXTRA_OPTFLAGS='$(EDK2_BASETOOLS_OPTFLAGS)' \ @@ -170,33 +172,31 @@ skiboot: efi: edk2-basetools $(MAKE) -f Makefile.edk2 -opensbi32-virt: +opensbi32-generic: $(MAKE) -C opensbi \ CROSS_COMPILE=$(riscv32_cross_prefix) \ - PLATFORM="qemu/virt" - cp opensbi/build/platform/qemu/virt/firmware/fw_jump.bin ../pc-bios/opensbi-riscv32-virt-fw_jump.bin + PLATFORM="generic" + cp opensbi/build/platform/generic/firmware/fw_dynamic.bin ../pc-bios/opensbi-riscv32-generic-fw_dynamic.bin + cp opensbi/build/platform/generic/firmware/fw_dynamic.elf ../pc-bios/opensbi-riscv32-generic-fw_dynamic.elf -opensbi64-virt: +opensbi64-generic: $(MAKE) -C opensbi \ CROSS_COMPILE=$(riscv64_cross_prefix) \ - PLATFORM="qemu/virt" - cp opensbi/build/platform/qemu/virt/firmware/fw_jump.bin ../pc-bios/opensbi-riscv64-virt-fw_jump.bin - -opensbi32-sifive_u: - $(MAKE) -C opensbi \ - CROSS_COMPILE=$(riscv32_cross_prefix) \ - PLATFORM="sifive/fu540" - cp opensbi/build/platform/sifive/fu540/firmware/fw_jump.bin ../pc-bios/opensbi-riscv32-sifive_u-fw_jump.bin - -opensbi64-sifive_u: - $(MAKE) -C opensbi \ - CROSS_COMPILE=$(riscv64_cross_prefix) \ - PLATFORM="sifive/fu540" - cp opensbi/build/platform/sifive/fu540/firmware/fw_jump.bin ../pc-bios/opensbi-riscv64-sifive_u-fw_jump.bin - -bios-microvm: - $(MAKE) -C qboot - cp qboot/bios.bin ../pc-bios/bios-microvm.bin + PLATFORM="generic" + cp opensbi/build/platform/generic/firmware/fw_dynamic.bin ../pc-bios/opensbi-riscv64-generic-fw_dynamic.bin + cp opensbi/build/platform/generic/firmware/fw_dynamic.elf ../pc-bios/opensbi-riscv64-generic-fw_dynamic.elf + +MESON = meson +NINJA = ninja +qboot: + mkdir -p qboot/build + $(MESON) setup $(if $(wildcard qboot/build/meson-private),--wipe,) qboot qboot/build + $(NINJA) -C qboot/build + cp qboot/build/bios.bin ../pc-bios/qboot.rom + +npcm7xx_bootrom: + $(MAKE) -C vbootrom CROSS_COMPILE=$(arm_cross_prefix) + cp vbootrom/npcm7xx_bootrom.bin ../pc-bios/npcm7xx_bootrom.bin clean: rm -rf seabios/.config seabios/out seabios/builds @@ -211,3 +211,4 @@ clean: $(MAKE) -f Makefile.edk2 clean $(MAKE) -C opensbi clean $(MAKE) -C qboot clean + $(MAKE) -C vbootrom clean diff --git a/roms/Makefile.edk2 b/roms/Makefile.edk2 index 33a074d3a4c21b5460d98bbc7d4a64cf492fd059..a8ed3255757fa4e57f3a53376ab6045ceb77e82f 100644 --- a/roms/Makefile.edk2 +++ b/roms/Makefile.edk2 @@ -64,7 +64,10 @@ submodules: --arch=AARCH64 \ --platform=ArmVirtPkg/ArmVirtQemu.dsc \ -D NETWORK_IP6_ENABLE \ - -D NETWORK_HTTP_BOOT_ENABLE + -D NETWORK_HTTP_BOOT_ENABLE \ + -D NETWORK_TLS_ENABLE \ + -D TPM2_ENABLE \ + -D TPM2_CONFIG_ENABLE cp edk2/Build/ArmVirtQemu-AARCH64/DEBUG_$(call toolchain,aarch64)/FV/QEMU_EFI.fd \ $@ truncate --size=64M $@ @@ -75,7 +78,10 @@ submodules: --arch=ARM \ --platform=ArmVirtPkg/ArmVirtQemu.dsc \ -D NETWORK_IP6_ENABLE \ - -D NETWORK_HTTP_BOOT_ENABLE + -D NETWORK_HTTP_BOOT_ENABLE \ + -D NETWORK_TLS_ENABLE \ + -D TPM2_ENABLE \ + -D TPM2_CONFIG_ENABLE cp edk2/Build/ArmVirtQemu-ARM/DEBUG_$(call toolchain,arm)/FV/QEMU_EFI.fd \ $@ truncate --size=64M $@ @@ -88,8 +94,8 @@ submodules: -D NETWORK_IP6_ENABLE \ -D NETWORK_HTTP_BOOT_ENABLE \ -D NETWORK_TLS_ENABLE \ - -D TPM2_ENABLE \ - -D TPM2_CONFIG_ENABLE + -D TPM_ENABLE \ + -D TPM_CONFIG_ENABLE cp edk2/Build/OvmfIa32/DEBUG_$(call toolchain,i386)/FV/OVMF_CODE.fd $@ ../pc-bios/edk2-i386-secure-code.fd: submodules @@ -100,8 +106,8 @@ submodules: -D NETWORK_IP6_ENABLE \ -D NETWORK_HTTP_BOOT_ENABLE \ -D NETWORK_TLS_ENABLE \ - -D TPM2_ENABLE \ - -D TPM2_CONFIG_ENABLE \ + -D TPM_ENABLE \ + -D TPM_CONFIG_ENABLE \ -D SECURE_BOOT_ENABLE \ -D SMM_REQUIRE cp edk2/Build/OvmfIa32/DEBUG_$(call toolchain,i386)/FV/OVMF_CODE.fd $@ @@ -114,8 +120,8 @@ submodules: -D NETWORK_IP6_ENABLE \ -D NETWORK_HTTP_BOOT_ENABLE \ -D NETWORK_TLS_ENABLE \ - -D TPM2_ENABLE \ - -D TPM2_CONFIG_ENABLE + -D TPM_ENABLE \ + -D TPM_CONFIG_ENABLE cp edk2/Build/OvmfX64/DEBUG_$(call toolchain,x86_64)/FV/OVMF_CODE.fd $@ ../pc-bios/edk2-x86_64-secure-code.fd: submodules @@ -127,8 +133,8 @@ submodules: -D NETWORK_IP6_ENABLE \ -D NETWORK_HTTP_BOOT_ENABLE \ -D NETWORK_TLS_ENABLE \ - -D TPM2_ENABLE \ - -D TPM2_CONFIG_ENABLE \ + -D TPM_ENABLE \ + -D TPM_CONFIG_ENABLE \ -D SECURE_BOOT_ENABLE \ -D SMM_REQUIRE cp edk2/Build/Ovmf3264/DEBUG_$(call toolchain,x86_64)/FV/OVMF_CODE.fd $@ diff --git a/roms/SLOF b/roms/SLOF index 8e012d6fddb62be833d746cef3f03e6c8beecde0..e18ddad8516ff2cfe36ec130200318f7251aa78c 160000 --- a/roms/SLOF +++ b/roms/SLOF @@ -1 +1 @@ -Subproject commit 8e012d6fddb62be833d746cef3f03e6c8beecde0 +Subproject commit e18ddad8516ff2cfe36ec130200318f7251aa78c diff --git a/roms/config.seabios-128k b/roms/config.seabios-128k index c43912bf9de4edf317da662ade1d55096b639abd..d18c802c46e984441241817121498ead6aa0bd49 100644 --- a/roms/config.seabios-128k +++ b/roms/config.seabios-128k @@ -11,8 +11,11 @@ CONFIG_USB_UAS=n CONFIG_SDCARD=n CONFIG_TCGBIOS=n CONFIG_MPT_SCSI=n +CONFIG_ESP_SCSI=n +CONFIG_MEGASAS=n CONFIG_PVSCSI=n CONFIG_NVME=n CONFIG_USE_SMM=n CONFIG_VGAHOOKS=n CONFIG_HOST_BIOS_GEOMETRY=n +CONFIG_ACPI_PARSE=n diff --git a/roms/config.seabios-microvm b/roms/config.seabios-microvm new file mode 100644 index 0000000000000000000000000000000000000000..a253e2edc6ec41a5f98c4a6085d3bbdffd7d43a0 --- /dev/null +++ b/roms/config.seabios-microvm @@ -0,0 +1,26 @@ +CONFIG_QEMU=y +CONFIG_QEMU_HARDWARE=y +CONFIG_PERMIT_UNALIGNED_PCIROM=y +CONFIG_ROM_SIZE=128 +CONFIG_XEN=n +CONFIG_BOOTSPLASH=n +CONFIG_ATA=n +CONFIG_AHCI=n +CONFIG_SDCARD=n +CONFIG_PVSCSI=n +CONFIG_ESP_SCSI=n +CONFIG_LSI_SCSI=n +CONFIG_MEGASAS=n +CONFIG_MPT_SCSI=n +CONFIG_FLOPPY=n +CONFIG_FLASH_FLOPPY=n +CONFIG_NVME=n +CONFIG_PS2PORT=n +CONFIG_USB=n +CONFIG_LPT=n +CONFIG_RTC_TIMER=n +CONFIG_USE_SMM=n +CONFIG_PMTIMER=n +CONFIG_TCGBIOS=n +CONFIG_HARDWARE_IRQ=n +CONFIG_ACPI_PARSE=y diff --git a/roms/edk2 b/roms/edk2 index 20d2e5a125e34fc8501026613a71549b2a1a3e54..06dc822d045c2bb42e497487935485302486e151 160000 --- a/roms/edk2 +++ b/roms/edk2 @@ -1 +1 @@ -Subproject commit 20d2e5a125e34fc8501026613a71549b2a1a3e54 +Subproject commit 06dc822d045c2bb42e497487935485302486e151 diff --git a/roms/ipxe b/roms/ipxe index de4565cbe76ea9f7913a01f331be3ee901bb6e17..4bd064de239dab2426b31c9789a1f4d78087dc63 160000 --- a/roms/ipxe +++ b/roms/ipxe @@ -1 +1 @@ -Subproject commit de4565cbe76ea9f7913a01f331be3ee901bb6e17 +Subproject commit 4bd064de239dab2426b31c9789a1f4d78087dc63 diff --git a/roms/openbios b/roms/openbios index 4704d9eba6d8017dc694c077ca4205ffd8becad8..7f28286f5cb1ca682e3ba0a8706d8884f12bc49e 160000 --- a/roms/openbios +++ b/roms/openbios @@ -1 +1 @@ -Subproject commit 4704d9eba6d8017dc694c077ca4205ffd8becad8 +Subproject commit 7f28286f5cb1ca682e3ba0a8706d8884f12bc49e diff --git a/roms/opensbi b/roms/opensbi index 9f1b72ce66d659e91013b358939e832fb27223f5..a98258d0b537a295f517bbc8d813007336731fa9 160000 --- a/roms/opensbi +++ b/roms/opensbi @@ -1 +1 @@ -Subproject commit 9f1b72ce66d659e91013b358939e832fb27223f5 +Subproject commit a98258d0b537a295f517bbc8d813007336731fa9 diff --git a/roms/qboot b/roms/qboot index cb1c49e0cfac99b9961d136ac0194da62c28cf64..a5300c4949b8d4de2d34bedfaed66793f48ec948 160000 --- a/roms/qboot +++ b/roms/qboot @@ -1 +1 @@ -Subproject commit cb1c49e0cfac99b9961d136ac0194da62c28cf64 +Subproject commit a5300c4949b8d4de2d34bedfaed66793f48ec948 diff --git a/roms/seabios b/roms/seabios index f21b5a4aeb020f2a5e2c6503f906a9349dd2f069..155821a1990b6de78dde5f98fa5ab90e802021e0 160000 --- a/roms/seabios +++ b/roms/seabios @@ -1 +1 @@ -Subproject commit f21b5a4aeb020f2a5e2c6503f906a9349dd2f069 +Subproject commit 155821a1990b6de78dde5f98fa5ab90e802021e0 diff --git a/roms/seabios-hppa b/roms/seabios-hppa index 1630ac7d65c4a09218cc677f1fa56cd5b3140447..73b740f77190643b2ada5ee97a9a108c6ef2a37b 160000 --- a/roms/seabios-hppa +++ b/roms/seabios-hppa @@ -1 +1 @@ -Subproject commit 1630ac7d65c4a09218cc677f1fa56cd5b3140447 +Subproject commit 73b740f77190643b2ada5ee97a9a108c6ef2a37b diff --git a/roms/vbootrom b/roms/vbootrom new file mode 160000 index 0000000000000000000000000000000000000000..0c37a43527f0ee2b9584e7fb2fdc805e902635ac --- /dev/null +++ b/roms/vbootrom @@ -0,0 +1 @@ +Subproject commit 0c37a43527f0ee2b9584e7fb2fdc805e902635ac diff --git a/rules.mak b/rules.mak deleted file mode 100644 index 694865b63ee84f8b3e28f9b3bb233abb4015cd00..0000000000000000000000000000000000000000 --- a/rules.mak +++ /dev/null @@ -1,440 +0,0 @@ - -# These are used when we want to do substitutions without confusing Make -NULL := -SPACE := $(NULL) # -COMMA := , - -# Don't use implicit rules or variables -# we have explicit rules for everything -MAKEFLAGS += -rR - -# Files with this suffixes are final, don't try to generate them -# using implicit rules -%/trace-events: -%.hx: -%.py: -%.objs: -%.d: -%.h: -%.c: -%.cc: -%.cpp: -%.m: -%.mak: -clean-target: - -# Flags for dependency generation -QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(@D)/$(*F).d - -# Compiler searches the source file dir first, but in vpath builds -# we need to make it search the build dir too, before any other -# explicit search paths. There are two search locations in the build -# dir, one absolute and the other relative to the compiler working -# directory. These are the same for target-independent files, but -# different for target-dependent ones. -QEMU_LOCAL_INCLUDES = -iquote $(BUILD_DIR)/$(@D) -iquote $(@D) - -WL_U := -Wl,-u, -find-symbols = $(if $1, $(sort $(shell $(NM) -P -g $1 | $2))) -defined-symbols = $(call find-symbols,$1,awk '$$2!="U"{print $$1}') -undefined-symbols = $(call find-symbols,$1,awk '$$2=="U"{print $$1}') - -# All the .mo objects in -m variables are also added into corresponding -y -# variable in unnest-vars, but filtered out here, when LINK is called. -# -# The .mo objects are supposed to be linked as a DSO, for module build. So here -# they are only used as a placeholders to generate those "archive undefined" -# symbol options (-Wl,-u,$symbol_name), which are the archive functions -# referenced by the code in the DSO. -# -# Also the presence in -y variables will also guarantee they are built before -# linking executables that will load them. So we can look up symbol reference -# in LINK. -# -# This is necessary because the exectuable itself may not use the function, in -# which case the function would not be linked in. Then the DSO loading will -# fail because of the missing symbol. -process-archive-undefs = $(filter-out %.a %.mo,$1) \ - $(addprefix $(WL_U), \ - $(filter $(call defined-symbols,$(filter %.a, $1)), \ - $(call undefined-symbols,$(filter %.mo,$1)))) \ - $(filter %.a,$1) - -extract-libs = $(strip $(foreach o,$(filter-out %.mo,$1),$($o-libs))) -expand-objs = $(strip $(sort $(filter %.o,$1)) \ - $(foreach o,$(filter %.mo,$1),$($o-objs)) \ - $(filter-out %.o %.mo,$1)) - -%.o: %.c - $(call quiet-command,$(CC) $(QEMU_LOCAL_INCLUDES) $(QEMU_INCLUDES) \ - $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) \ - -c -o $@ $<,"CC","$(TARGET_DIR)$@") -%.o: %.rc - $(call quiet-command,$(WINDRES) -I. -o $@ $<,"RC","$(TARGET_DIR)$@") - -# If we have a CXX we might have some C++ objects, in which case we -# must link with the C++ compiler, not the plain C compiler. -LINKPROG = $(or $(CXX),$(CC)) - -LINK = $(call quiet-command, $(LINKPROG) $(CFLAGS) $(QEMU_LDFLAGS) -o $@ \ - $(call process-archive-undefs, $1) \ - $(version-obj-y) $(call extract-libs,$1) $(LIBS),"LINK","$(TARGET_DIR)$@") - -%.o: %.S - $(call quiet-command,$(CCAS) $(QEMU_LOCAL_INCLUDES) $(QEMU_INCLUDES) \ - $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) \ - -c -o $@ $<,"CCAS","$(TARGET_DIR)$@") - -%.o: %.cc - $(call quiet-command,$(CXX) $(QEMU_LOCAL_INCLUDES) $(QEMU_INCLUDES) \ - $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) \ - -c -o $@ $<,"CXX","$(TARGET_DIR)$@") - -%.o: %.cpp - $(call quiet-command,$(CXX) $(QEMU_LOCAL_INCLUDES) $(QEMU_INCLUDES) \ - $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) \ - -c -o $@ $<,"CXX","$(TARGET_DIR)$@") - -%.o: %.m - $(call quiet-command,$(OBJCC) $(QEMU_LOCAL_INCLUDES) $(QEMU_INCLUDES) \ - $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) \ - -c -o $@ $<,"OBJC","$(TARGET_DIR)$@") - -%.o: %.dtrace - $(call quiet-command,dtrace -o $@ -G -s $<,"GEN","$(TARGET_DIR)$@") - -DSO_OBJ_CFLAGS := -fPIC -DBUILD_DSO -module-common.o: CFLAGS += $(DSO_OBJ_CFLAGS) -%$(DSOSUF): QEMU_LDFLAGS += $(LDFLAGS_SHARED) -%$(DSOSUF): %.mo - $(call LINK,$^) - @# Copy to build root so modules can be loaded when program started without install - $(if $(findstring /,$@),$(call quiet-command,cp $@ $(subst /,-,$@),"CP","$(subst /,-,$@)")) - - -LD_REL := $(CC) -nostdlib $(LD_REL_FLAGS) - -%.mo: - $(call quiet-command,$(LD_REL) -o $@ $^,"LD","$(TARGET_DIR)$@") - -.PHONY: modules -modules: - -%$(EXESUF): %.o - $(call LINK,$(filter %.o %.a %.mo, $^)) - -%.a: - $(call quiet-command,rm -f $@ && $(AR) rcs $@ $^,"AR","$(TARGET_DIR)$@") - -# Usage: $(call quiet-command,command and args,"NAME","args to print") -# This will run "command and args", and either: -# if V=1 just print the whole command and args -# otherwise print the 'quiet' output in the format " NAME args to print" -# NAME should be a short name of the command, 7 letters or fewer. -# If called with only a single argument, will print nothing in quiet mode. -quiet-command-run = $(if $(V),,$(if $2,printf " %-7s %s\n" $2 $3 && ))$1 -quiet-@ = $(if $(V),,@) -quiet-command = $(quiet-@)$(call quiet-command-run,$1,$2,$3) - -# cc-option -# Usage: CFLAGS+=$(call cc-option, -falign-functions=0, -malign-functions=0) - -cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \ - >/dev/null 2>&1 && echo OK), $2, $3) -cc-c-option = $(if $(shell $(CC) $1 $2 -c -o /dev/null -xc /dev/null \ - >/dev/null 2>&1 && echo OK), $2, $3) - -VPATH_SUFFIXES = %.c %.h %.S %.cc %.cpp %.m %.mak %.texi %.sh %.rc Kconfig% %.json.in -set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1))) - -# install-prog list, dir -define install-prog - $(INSTALL_DIR) "$2" - $(INSTALL_PROG) $1 "$2" - $(if $(STRIP),$(STRIP) $(foreach T,$1,"$2/$(notdir $T)"),) -endef - -# find-in-path -# Usage: $(call find-in-path, prog) -# Looks in the PATH if the argument contains no slash, else only considers one -# specific directory. Returns an # empty string if the program doesn't exist -# there. -find-in-path = $(if $(findstring /, $1), \ - $(wildcard $1), \ - $(wildcard $(patsubst %, %/$1, $(subst :, ,$(PATH))))) - -# Logical functions (for operating on y/n values like CONFIG_FOO vars) -# Inputs to these must be either "y" (true) or "n" or "" (both false) -# Output is always either "y" or "n". -# Usage: $(call land,$(CONFIG_FOO),$(CONFIG_BAR)) -# Logical NOT -lnot = $(if $(subst n,,$1),n,y) -# Logical AND -land = $(if $(findstring yy,$1$2),y,n) -# Logical OR -lor = $(if $(findstring y,$1$2),y,n) -# Logical XOR (note that this is the inverse of leqv) -lxor = $(if $(filter $(call lnot,$1),$(call lnot,$2)),n,y) -# Logical equivalence (note that leqv "","n" is true) -leqv = $(if $(filter $(call lnot,$1),$(call lnot,$2)),y,n) -# Logical if: like make's $(if) but with an leqv-like test -lif = $(if $(subst n,,$1),$2,$3) - -# String testing functions: inputs to these can be any string; -# the output is always either "y" or "n". Leading and trailing whitespace -# is ignored when comparing strings. -# String equality -eq = $(if $(subst $2,,$1)$(subst $1,,$2),n,y) -# String inequality -ne = $(if $(subst $2,,$1)$(subst $1,,$2),y,n) -# Emptiness/non-emptiness tests: -isempty = $(if $1,n,y) -notempty = $(if $1,y,n) - -# Generate files with tracetool -TRACETOOL=$(PYTHON) $(SRC_PATH)/scripts/tracetool.py - -# Generate timestamp files for .h include files - -config-%.h: config-%.h-timestamp - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ - -config-%.h-timestamp: config-%.mak $(SRC_PATH)/scripts/create_config - $(call quiet-command, sh $(SRC_PATH)/scripts/create_config < $< > $@,"GEN","$(TARGET_DIR)config-$*.h") - -.PHONY: clean-timestamp -clean-timestamp: - rm -f *.timestamp -clean: clean-timestamp - -# will delete the target of a rule if commands exit with a nonzero exit status -.DELETE_ON_ERROR: - -# save-vars -# Usage: $(call save-vars, vars) -# Save each variable $v in $vars as save-vars-$v, save their object's -# variables, then clear $v. saved-vars-$v contains the variables that -# where saved for the objects, in order to speedup load-vars. -define save-vars - $(foreach v,$1, - $(eval save-vars-$v := $(value $v)) - $(eval saved-vars-$v := $(foreach o,$($v), \ - $(if $($o-cflags), $o-cflags $(eval save-vars-$o-cflags := $($o-cflags))$(eval $o-cflags := )) \ - $(if $($o-libs), $o-libs $(eval save-vars-$o-libs := $($o-libs))$(eval $o-libs := )) \ - $(if $($o-objs), $o-objs $(eval save-vars-$o-objs := $($o-objs))$(eval $o-objs := )))) - $(eval $v := )) -endef - -# load-vars -# Usage: $(call load-vars, vars, add_var) -# Load the saved value for each variable in @vars, and the per object -# variables. -# Append @add_var's current value to the loaded value. -define load-vars - $(eval $2-new-value := $(value $2)) - $(foreach v,$1, - $(eval $v := $(value save-vars-$v)) - $(foreach o,$(saved-vars-$v), - $(eval $o := $(save-vars-$o)) $(eval save-vars-$o := )) - $(eval save-vars-$v := ) - $(eval saved-vars-$v := )) - $(eval $2 := $(value $2) $($2-new-value)) -endef - -# fix-paths -# Usage: $(call fix-paths, obj_path, src_path, vars) -# Add prefix @obj_path to all objects in @vars, and add prefix @src_path to all -# directories in @vars. -define fix-paths - $(foreach v,$3, - $(foreach o,$($v), - $(if $($o-libs), - $(eval $1$o-libs := $($o-libs))) - $(if $($o-cflags), - $(eval $1$o-cflags := $($o-cflags))) - $(if $($o-objs), - $(eval $1$o-objs := $(addprefix $1,$($o-objs))))) - $(eval $v := $(addprefix $1,$(filter-out %/,$($v))) \ - $(addprefix $2,$(filter %/,$($v))))) -endef - -# unnest-var-recursive -# Usage: $(call unnest-var-recursive, obj_prefix, vars, var) -# -# Unnest @var by including subdir Makefile.objs, while protect others in @vars -# unchanged. -# -# @obj_prefix is the starting point of object path prefix. -# -define unnest-var-recursive - $(eval dirs := $(sort $(filter %/,$($3)))) - $(eval $3 := $(filter-out %/,$($3))) - $(foreach d,$(dirs:%/=%), - $(call save-vars,$2) - $(eval obj := $(if $1,$1/)$d) - $(eval -include $(SRC_PATH)/$d/Makefile.objs) - $(call fix-paths,$(if $1,$1/)$d/,$d/,$2) - $(call load-vars,$2,$3) - $(call unnest-var-recursive,$1,$2,$3)) -endef - -# unnest-vars -# Usage: $(call unnest-vars, obj_prefix, vars) -# -# @obj_prefix: object path prefix, can be empty, or '..', etc. Don't include -# ending '/'. -# -# @vars: the list of variable names to unnest. -# -# This macro will scan subdirectories's Makefile.objs, include them, to build -# up each variable listed in @vars. -# -# Per object and per module cflags and libs are saved with relative path fixed -# as well, those variables include -libs, -cflags and -objs. Items in -objs are -# also fixed to relative path against SRC_PATH plus the prefix @obj_prefix. -# -# All nested variables postfixed by -m in names are treated as DSO variables, -# and will be built as modules, if enabled. -# -# A simple example of the unnest: -# -# obj_prefix = .. -# vars = hot cold -# hot = fire.o sun.o season/ -# cold = snow.o water/ season/ -# -# Unnest through a faked source directory structure: -# -# SRC_PATH -# ├── water -# │ └── Makefile.objs──────────────────┐ -# │ │ hot += steam.o │ -# │ │ cold += ice.mo │ -# │ │ ice.mo-libs := -licemaker │ -# │ │ ice.mo-objs := ice1.o ice2.o │ -# │ └──────────────────────────────┘ -# │ -# └── season -# └── Makefile.objs──────┐ -# │ hot += summer.o │ -# │ cold += winter.o │ -# └──────────────────┘ -# -# In the end, the result will be: -# -# hot = ../fire.o ../sun.o ../season/summer.o -# cold = ../snow.o ../water/ice.mo ../season/winter.o -# ../water/ice.mo-libs = -licemaker -# ../water/ice.mo-objs = ../water/ice1.o ../water/ice2.o -# -# Note that 'hot' didn't include 'water/' in the input, so 'steam.o' is not -# included. -# -define unnest-vars - # In the case of target build (i.e. $1 == ..), fix path for top level - # Makefile.objs objects - $(if $1,$(call fix-paths,$1/,,$2)) - - # Descend and include every subdir Makefile.objs - $(foreach v, $2, - $(call unnest-var-recursive,$1,$2,$v) - # Pass the .mo-cflags and .mo-libs along to its member objects - $(foreach o, $(filter %.mo,$($v)), - $(foreach p,$($o-objs), - $(if $($o-cflags), $(eval $p-cflags += $($o-cflags))) - $(if $($o-libs), $(eval $p-libs += $($o-libs)))))) - - # For all %.mo objects that are directly added into -y, just expand them - $(foreach v,$(filter %-y,$2), - $(eval $v := $(foreach o,$($v),$(if $($o-objs),$($o-objs),$o)))) - - $(foreach v,$(filter %-m,$2), - # All .o found in *-m variables are single object modules, create .mo - # for them - $(foreach o,$(filter %.o,$($v)), - $(eval $(o:%.o=%.mo)-objs := $o)) - # Now unify .o in -m variable to .mo - $(eval $v := $($v:%.o=%.mo)) - $(eval modules-m += $($v)) - - # For module build, build shared libraries during "make modules" - # For non-module build, add -m to -y - $(if $(CONFIG_MODULES), - $(foreach o,$($v), - $(eval $($o-objs): CFLAGS += $(DSO_OBJ_CFLAGS)) - $(eval $o: $($o-objs))) - $(eval $(patsubst %-m,%-y,$v) += $($v)) - $(eval modules: $($v:%.mo=%$(DSOSUF))), - $(eval $(patsubst %-m,%-y,$v) += $(call expand-objs, $($v))))) - - # Post-process all the unnested vars - $(foreach v,$2, - $(foreach o, $(filter %.mo,$($v)), - # Find all the .mo objects in variables and add dependency rules - # according to .mo-objs. Report error if not set - $(if $($o-objs), - $(eval $(o:%.mo=%$(DSOSUF)): module-common.o $($o-objs)), - $(error $o added in $v but $o-objs is not set))) - $(shell mkdir -p ./ $(sort $(dir $($v)))) - # Include all the .d files - $(eval -include $(patsubst %.o,%.d,$(patsubst %.mo,%.d,$($v)))) - $(eval $v := $(filter-out %/,$($v)))) -endef - -TEXI2MAN = $(call quiet-command, \ - perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $(TEXI2PODFLAGS) $< $@.pod && \ - $(POD2MAN) --section=$(subst .,,$(suffix $@)) --center=" " --release=" " $@.pod > $@, \ - "GEN","$@") - -%.1: - $(call TEXI2MAN) -%.7: - $(call TEXI2MAN) -%.8: - $(call TEXI2MAN) - -GEN_SUBST = $(call quiet-command, \ - sed -e "s!@libexecdir@!$(libexecdir)!g" < $< > $@, \ - "GEN","$@") - -%.json: %.json.in - $(call GEN_SUBST) - -# Support for building multiple output files by atomically executing -# a single rule which depends on several input files (so the rule -# will be executed exactly once, not once per output file, and -# not multiple times in parallel.) For more explanation see: -# https://www.cmcrossroads.com/article/atomic-rules-gnu-make - -# Given a space-separated list of filenames, create the name of -# a 'sentinel' file to use to indicate that they have been built. -# We use fixed text on the end to avoid accidentally triggering -# automatic pattern rules, and . on the start to make the file -# not show up in ls output. -sentinel = .$(subst $(SPACE),_,$(subst /,_,$1)).sentinel. - -# Define an atomic rule that builds multiple outputs from multiple inputs. -# To use: -# $(call atomic,out1 out2 ...,in1 in2 ...) -# rule to do the operation -# -# Make 4.3 will have native support for this, and you would be able -# to instead write: -# out1 out2 ... &: in1 in2 ... -# rule to do the operation -# -# The way this works is that it creates a make rule -# "out1 out2 ... : sentinel-file ; @:" which says that the sentinel -# depends on the dependencies, and the rule to do that is "do nothing". -# Then we have a rule -# "sentinel-file : in1 in2 ..." -# whose commands start with "touch sentinel-file" and then continue -# with the rule text provided by the user of this 'atomic' function. -# The foreach... is there to delete the sentinel file if any of the -# output files don't exist, so that we correctly rebuild in that situation. -atomic = $(eval $1: $(call sentinel,$1) ; @:) \ - $(call sentinel,$1) : $2 ; @touch $$@ \ - $(foreach t,$1,$(if $(wildcard $t),,$(shell rm -f $(call sentinel,$1)))) - -print-%: - @echo '$*=$($*)' diff --git a/scripts/analyze-migration.py b/scripts/analyze-migration.py index 96a31d3974ba2af13d419b71c409876b6eb9fc89..d7177b212c86e826303bd93e74cb2578a2d768fa 100755 --- a/scripts/analyze-migration.py +++ b/scripts/analyze-migration.py @@ -7,7 +7,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,11 +25,6 @@ import sys -MIN_PYTHON = (3, 2) -if sys.version_info < MIN_PYTHON: - sys.exit("Python %s.%s or later is required.\n" % MIN_PYTHON) - - def mkdir_p(path): try: os.makedirs(path) @@ -102,7 +97,8 @@ def read_migration_debug_json(self): # Seek back to where we were at the beginning self.file.seek(entrypos, 0) - return data[jsonpos:jsonpos + jsonlen] + # explicit decode() needed for Python 3.5 compatibility + return data[jsonpos:jsonpos + jsonlen].decode("utf-8") def close(self): self.file.close() diff --git a/scripts/archive-source.sh b/scripts/archive-source.sh index fb5d6b3918d058b355cf496825ba87783d4af2e5..c6169db69f51cdd39fc40e89231abd844751dab5 100755 --- a/scripts/archive-source.sh +++ b/scripts/archive-source.sh @@ -26,7 +26,8 @@ sub_file="${sub_tdir}/submodule.tar" # independent of what the developer currently has initialized # in their checkout, because the build environment is completely # different to the host OS. -submodules="dtc slirp ui/keycodemapdb tests/fp/berkeley-softfloat-3 tests/fp/berkeley-testfloat-3" +submodules="dtc slirp meson ui/keycodemapdb" +submodules="$submodules tests/fp/berkeley-softfloat-3 tests/fp/berkeley-testfloat-3" sub_deinit="" function cleanup() { diff --git a/scripts/block-coroutine-wrapper.py b/scripts/block-coroutine-wrapper.py new file mode 100644 index 0000000000000000000000000000000000000000..0461fd1c459cf2df41db093d5ac01879b0d853d1 --- /dev/null +++ b/scripts/block-coroutine-wrapper.py @@ -0,0 +1,167 @@ +#! /usr/bin/env python3 +"""Generate coroutine wrappers for block subsystem. + +The program parses one or several concatenated c files from stdin, +searches for functions with the 'generated_co_wrapper' specifier +and generates corresponding wrappers on stdout. + +Usage: block-coroutine-wrapper.py generated-file.c FILE.[ch]... + +Copyright (c) 2020 Virtuozzo International GmbH. + +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 . +""" + +import sys +import re +from typing import Iterator + + +def gen_header(): + copyright = re.sub('^.*Copyright', 'Copyright', __doc__, flags=re.DOTALL) + copyright = re.sub('^(?=.)', ' * ', copyright.strip(), flags=re.MULTILINE) + copyright = re.sub('^$', ' *', copyright, flags=re.MULTILINE) + return f"""\ +/* + * File is generated by scripts/block-coroutine-wrapper.py + * +{copyright} + */ + +#include "qemu/osdep.h" +#include "block/coroutines.h" +#include "block/block-gen.h" +#include "block/block_int.h"\ +""" + + +class ParamDecl: + param_re = re.compile(r'(?P' + r'(?P.*[ *])' + r'(?P[a-z][a-z0-9_]*)' + r')') + + def __init__(self, param_decl: str) -> None: + m = self.param_re.match(param_decl.strip()) + if m is None: + raise ValueError(f'Wrong parameter declaration: "{param_decl}"') + self.decl = m.group('decl') + self.type = m.group('type') + self.name = m.group('name') + + +class FuncDecl: + def __init__(self, return_type: str, name: str, args: str) -> None: + self.return_type = return_type.strip() + self.name = name.strip() + self.args = [ParamDecl(arg.strip()) for arg in args.split(',')] + + def gen_list(self, format: str) -> str: + return ', '.join(format.format_map(arg.__dict__) for arg in self.args) + + def gen_block(self, format: str) -> str: + return '\n'.join(format.format_map(arg.__dict__) for arg in self.args) + + +# Match wrappers declared with a generated_co_wrapper mark +func_decl_re = re.compile(r'^int\s*generated_co_wrapper\s*' + r'(?P[a-z][a-z0-9_]*)' + r'\((?P[^)]*)\);$', re.MULTILINE) + + +def func_decl_iter(text: str) -> Iterator: + for m in func_decl_re.finditer(text): + yield FuncDecl(return_type='int', + name=m.group('wrapper_name'), + args=m.group('args')) + + +def snake_to_camel(func_name: str) -> str: + """ + Convert underscore names like 'some_function_name' to camel-case like + 'SomeFunctionName' + """ + words = func_name.split('_') + words = [w[0].upper() + w[1:] for w in words] + return ''.join(words) + + +def gen_wrapper(func: FuncDecl) -> str: + assert func.name.startswith('bdrv_') + assert not func.name.startswith('bdrv_co_') + assert func.return_type == 'int' + assert func.args[0].type in ['BlockDriverState *', 'BdrvChild *'] + + name = 'bdrv_co_' + func.name[5:] + bs = 'bs' if func.args[0].type == 'BlockDriverState *' else 'child->bs' + struct_name = snake_to_camel(name) + + return f"""\ +/* + * Wrappers for {name} + */ + +typedef struct {struct_name} {{ + BdrvPollCo poll_state; +{ func.gen_block(' {decl};') } +}} {struct_name}; + +static void coroutine_fn {name}_entry(void *opaque) +{{ + {struct_name} *s = opaque; + + s->poll_state.ret = {name}({ func.gen_list('s->{name}') }); + s->poll_state.in_progress = false; + + aio_wait_kick(); +}} + +int {func.name}({ func.gen_list('{decl}') }) +{{ + if (qemu_in_coroutine()) {{ + return {name}({ func.gen_list('{name}') }); + }} else {{ + {struct_name} s = {{ + .poll_state.bs = {bs}, + .poll_state.in_progress = true, + +{ func.gen_block(' .{name} = {name},') } + }}; + + s.poll_state.co = qemu_coroutine_create({name}_entry, &s); + + return bdrv_poll_co(&s.poll_state); + }} +}}""" + + +def gen_wrappers(input_code: str) -> str: + res = '' + for func in func_decl_iter(input_code): + res += '\n\n\n' + res += gen_wrapper(func) + + return res + + +if __name__ == '__main__': + if len(sys.argv) < 3: + exit(f'Usage: {sys.argv[0]} OUT_FILE.c IN_FILE.[ch]...') + + with open(sys.argv[1], 'w', encoding='utf-8') as f_out: + f_out.write(gen_header()) + for fname in sys.argv[2:]: + with open(fname, encoding='utf-8') as f_in: + f_out.write(gen_wrappers(f_in.read())) + f_out.write('\n') diff --git a/scripts/check_sparse.py b/scripts/check_sparse.py new file mode 100644 index 0000000000000000000000000000000000000000..2956124442300db515391791e64527d816c3bc72 --- /dev/null +++ b/scripts/check_sparse.py @@ -0,0 +1,59 @@ +#! /usr/bin/env python3 + +# Invoke sparse based on the contents of compile_commands.json, +# also working around several deficiencies in cgcc's command line +# parsing + +import json +import subprocess +import os +import sys +import shlex + +def cmdline_for_sparse(sparse, cmdline): + # Do not include the C compiler executable + skip = True + arg = False + out = sparse + ['-no-compile'] + for x in cmdline: + if arg: + out.append(x) + arg = False + continue + if skip: + skip = False + continue + # prevent sparse from treating output files as inputs + if x == '-MF' or x == '-MQ' or x == '-o': + skip = True + continue + # cgcc ignores -no-compile if it sees -M or -MM? + if x.startswith('-M'): + continue + # sparse does not understand these! + if x == '-iquote' or x == '-isystem': + x = '-I' + if x == '-I': + arg = True + out.append(x) + return out + +root_path = os.getenv('MESON_BUILD_ROOT') +def build_path(s): + return s if not root_path else os.path.join(root_path, s) + +ccjson_path = build_path(sys.argv[1]) +with open(ccjson_path, 'r') as fd: + compile_commands = json.load(fd) + +sparse = sys.argv[2:] +sparse_env = os.environ.copy() +for cmd in compile_commands: + cmdline = shlex.split(cmd['command']) + cmd = cmdline_for_sparse(sparse, cmdline) + print('REAL_CC=%s' % shlex.quote(cmdline[0]), + ' '.join((shlex.quote(x) for x in cmd))) + sparse_env['REAL_CC'] = cmdline[0] + r = subprocess.run(cmd, env=sparse_env, cwd=root_path) + if r.returncode != 0: + sys.exit(r.returncode) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 0ba213e9f27c80994d3281bd2f7fb25e7c864444..88c858f67cbb13de1c87adafb08a4f02d2d2f92f 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -49,7 +49,7 @@ Version: $V Options: -q, --quiet quiet - --no-tree run without a kernel tree + --no-tree run without a qemu tree --no-signoff do not check for 'Signed-off-by' line --patch treat FILE as patchfile --branch treat args as GIT revision list @@ -57,7 +57,7 @@ Options: --terse one line per report -f, --file treat FILE as regular source file --strict fail if only warnings are found - --root=PATH PATH to the kernel tree root + --root=PATH PATH to the qemu tree root --no-summary suppress the per-file summary --mailback only produce a report in case of warnings/errors --summary-file include the filename in summary @@ -203,7 +203,7 @@ if ($tree) { } if (!defined $root) { - print "Must be run from the top-level dir. of a kernel tree\n"; + print "Must be run from the top-level dir. of a qemu tree\n"; exit(2); } } @@ -392,7 +392,7 @@ if ($chk_branch) { close $HASH; - die "$P: no revisions returned for revlist '$chk_branch'\n" + die "$P: no revisions returned for revlist '$ARGV[0]'\n" unless @patches; my $i = 1; @@ -1267,7 +1267,7 @@ sub checkfilename { # files and when changing tests. if ($name =~ m#^tests/data/acpi/# and not $name =~ m#^\.sh$#) { $$acpi_testexpected = $name; - } elsif ($name =~ m#^tests/qtest/bios-tables-test-allowed-diff.h$#) { + } elsif ($name !~ m#^tests/qtest/bios-tables-test-allowed-diff.h$#) { $$acpi_nontestexpected = $name; } if (defined $$acpi_testexpected and defined $$acpi_nontestexpected) { @@ -1659,7 +1659,7 @@ sub process { # tabs are only allowed in assembly source code, and in # some scripts we imported from other projects. next if ($realfile =~ /\.(s|S)$/); - next if ($realfile =~ /(checkpatch|get_maintainer|texi2pod)\.pl$/); + next if ($realfile =~ /(checkpatch|get_maintainer)\.pl$/); if ($rawline =~ /^\+.*\t/) { my $herevet = "$here\n" . cat_vet($rawline) . "\n"; @@ -1870,7 +1870,7 @@ sub process { substr($s, 0, length($c), ''); # Make sure we remove the line prefixes as we have - # none on the first line, and are going to readd them + # none on the first line, and are going to re-add them # where necessary. $s =~ s/\n./\n/gs; @@ -2880,14 +2880,20 @@ sub process { $herecurr); } -# check for %L{u,d,i} in strings +# format strings checks my $string; while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) { $string = substr($rawline, $-[1], $+[1] - $-[1]); $string =~ s/%%/__/g; + # check for %L{u,d,i} in strings if ($string =~ /(? +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +""" +Checks the GitLab pipeline status for a given commit ID +""" + +# pylint: disable=C0103 + +import argparse +import http.client +import json +import os +import subprocess +import time +import sys + + +class CommunicationFailure(Exception): + """Failed to communicate to gitlab.com APIs.""" + + +class NoPipelineFound(Exception): + """Communication is successfull but pipeline is not found.""" + + +def get_local_branch_commit(branch): + """ + Returns the commit sha1 for the *local* branch named "staging" + """ + result = subprocess.run(['git', 'rev-parse', branch], + stdin=subprocess.DEVNULL, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, + cwd=os.path.dirname(__file__), + universal_newlines=True).stdout.strip() + if result == branch: + raise ValueError("There's no local branch named '%s'" % branch) + if len(result) != 40: + raise ValueError("Branch '%s' HEAD doesn't look like a sha1" % branch) + return result + + +def get_pipeline_status(project_id, commit_sha1): + """ + Returns the JSON content of the pipeline status API response + """ + url = '/api/v4/projects/{}/pipelines?sha={}'.format(project_id, + commit_sha1) + connection = http.client.HTTPSConnection('gitlab.com') + connection.request('GET', url=url) + response = connection.getresponse() + if response.code != http.HTTPStatus.OK: + raise CommunicationFailure("Failed to receive a successful response") + json_response = json.loads(response.read()) + + # As far as I can tell, there should be only one pipeline for the same + # project + commit. If this assumption is false, we can add further + # filters to the url, such as username, and order_by. + if not json_response: + raise NoPipelineFound("No pipeline found") + return json_response[0] + + +def wait_on_pipeline_success(timeout, interval, + project_id, commit_sha): + """ + Waits for the pipeline to finish within the given timeout + """ + start = time.time() + while True: + if time.time() >= (start + timeout): + msg = ("Timeout (-t/--timeout) of %i seconds reached, " + "won't wait any longer for the pipeline to complete") + msg %= timeout + print(msg) + return False + + try: + status = get_pipeline_status(project_id, commit_sha) + except NoPipelineFound: + print('Pipeline has not been found, it may not have been created yet.') + time.sleep(1) + continue + + pipeline_status = status['status'] + status_to_wait = ('created', 'waiting_for_resource', 'preparing', + 'pending', 'running') + if pipeline_status in status_to_wait: + print('%s...' % pipeline_status) + time.sleep(interval) + continue + + if pipeline_status == 'success': + return True + + msg = "Pipeline failed, check: %s" % status['web_url'] + print(msg) + return False + + +def create_parser(): + parser = argparse.ArgumentParser( + prog='pipeline-status', + description='check or wait on a pipeline status') + + parser.add_argument('-t', '--timeout', type=int, default=7200, + help=('Amount of time (in seconds) to wait for the ' + 'pipeline to complete. Defaults to ' + '%(default)s')) + parser.add_argument('-i', '--interval', type=int, default=60, + help=('Amount of time (in seconds) to wait between ' + 'checks of the pipeline status. Defaults ' + 'to %(default)s')) + parser.add_argument('-w', '--wait', action='store_true', default=False, + help=('Wether to wait, instead of checking only once ' + 'the status of a pipeline')) + parser.add_argument('-p', '--project-id', type=int, default=11167699, + help=('The GitLab project ID. Defaults to the project ' + 'for https://gitlab.com/qemu-project/qemu, that ' + 'is, "%(default)s"')) + parser.add_argument('-b', '--branch', type=str, default="staging", + help=('Specify the branch to check. ' + 'Use HEAD for your current branch. ' + 'Otherwise looks at "%(default)s"')) + parser.add_argument('-c', '--commit', + default=None, + help=('Look for a pipeline associated with the given ' + 'commit. If one is not explicitly given, the ' + 'commit associated with the default branch ' + 'is used.')) + parser.add_argument('--verbose', action='store_true', default=False, + help=('A minimal verbosity level that prints the ' + 'overall result of the check/wait')) + return parser + +def main(): + """ + Script entry point + """ + parser = create_parser() + args = parser.parse_args() + + if not args.commit: + args.commit = get_local_branch_commit(args.branch) + + success = False + try: + if args.wait: + success = wait_on_pipeline_success( + args.timeout, + args.interval, + args.project_id, + args.commit) + else: + status = get_pipeline_status(args.project_id, + args.commit) + success = status['status'] == 'success' + except Exception as error: # pylint: disable=W0703 + if args.verbose: + print("ERROR: %s" % error.args[0]) + except KeyboardInterrupt: + if args.verbose: + print("Exiting on user's request") + + if success: + if args.verbose: + print('success') + sys.exit(0) + else: + if args.verbose: + print('failure') + sys.exit(1) + + +if __name__ == '__main__': + main() diff --git a/scripts/clean-header-guards.pl b/scripts/clean-header-guards.pl index f47d673ad5c51c95d8b1974bb8094c3f21ee396e..a6680253b1faf0094d9a25ddd16667657f198da1 100755 --- a/scripts/clean-header-guards.pl +++ b/scripts/clean-header-guards.pl @@ -19,7 +19,7 @@ # Does the following: # - Header files without a recognizable header guard are skipped. # - Clean up any untidy header guards in-place. Warn if the cleanup -# renames guard symbols, and explain how to find occurences of these +# renames guard symbols, and explain how to find occurrences of these # symbols that may have to be updated manually. # - Warn about duplicate header guard symbols. To make full use of # this warning, you should clean up *all* headers in one run. diff --git a/scripts/clean-includes b/scripts/clean-includes index dd938daa3eccf900b43c7bcb93a87ff2fdf4e8bf..aaa7d4ceb3891a4fce7e286452c842b24514e62c 100755 --- a/scripts/clean-includes +++ b/scripts/clean-includes @@ -113,7 +113,7 @@ EOT for f in "$@"; do case "$f" in - *.inc.c) + *.c.inc) # These aren't standalone C source files echo "SKIPPING $f (not a standalone source file)" continue @@ -123,6 +123,7 @@ for f in "$@"; do ;; *include/qemu/osdep.h | \ *include/qemu/compiler.h | \ + *include/qemu/qemu-plugin.h | \ *include/glib-compat.h | \ *include/sysemu/os-posix.h | \ *include/sysemu/os-win32.h | \ diff --git a/scripts/cleanup-trace-events.pl b/scripts/cleanup-trace-events.pl index d4f0e4cab53019e56f86b92c97e0e081ddb8a216..c40d2fcc5016d6acd2caa7f7a8677220fac2ca65 100755 --- a/scripts/cleanup-trace-events.pl +++ b/scripts/cleanup-trace-events.pl @@ -15,12 +15,15 @@ use warnings; use strict; use File::Basename; -my $buf = ''; +my @files = (); +my $events = ''; my %seen = (); sub out { - print $buf; - $buf = ''; + print sort @files; + print $events; + @files = (); + $events = ''; %seen = (); } @@ -31,16 +34,18 @@ open(IN, $in) or die "open $in: $!"; chdir($dir) or die "chdir $dir: $!"; while () { - if (/^(disable |(tcg) |vcpu )*([a-z_0-9]+)\(/i) { - my $pat = "trace_$3"; - $pat .= '_tcg' if (defined $2); - open GREP, '-|', 'git', 'grep', '-lw', '--max-depth', '1', $pat + if (/^(disable |(tcg) |(vcpu) )*([a-z_0-9]+)\(/i) { + my $pat = "trace_$4"; + $pat .= '_tcg' if defined $2; + open GREP, '-|', 'git', 'grep', '-lw', + defined $3 ? () : ('--max-depth', '1'), + $pat or die "run git grep: $!"; while (my $fname = ) { chomp $fname; next if $seen{$fname} || $fname eq 'trace-events'; $seen{$fname} = 1; - $buf = "# $fname\n" . $buf; + push @files, "# $fname\n"; } unless (close GREP) { die "close git grep: $!" @@ -53,7 +58,7 @@ while () { } elsif (!/^#|^$/) { warn "unintelligible line"; } - $buf .= $_; + $events .= $_; } out; diff --git a/scripts/coccinelle/err-bad-newline.cocci b/scripts/coccinelle/err-bad-newline.cocci index 1316cc86a651a5a35eccd2d6e8fdf96d8e447a69..53944218738c36eb040e439e376c732343fddf99 100644 --- a/scripts/coccinelle/err-bad-newline.cocci +++ b/scripts/coccinelle/err-bad-newline.cocci @@ -1,22 +1,42 @@ // Error messages should not contain newlines. This script finds // messages that do. Fixing them is manual. @r@ -expression errp, eno, cls, fmt; +expression errp, err, eno, cls, fmt, ap; position p; @@ ( +error_vreport(fmt, ap)@p +| +warn_vreport(fmt, ap)@p +| +info_vreport(fmt, ap)@p +| error_report(fmt, ...)@p | +warn_report(fmt, ...)@p +| +info_report(fmt, ...)@p +| +error_report_once(fmt, ...)@p +| +warn_report_once(fmt, ...)@p +| error_setg(errp, fmt, ...)@p | error_setg_errno(errp, eno, fmt, ...)@p | error_setg_win32(errp, eno, cls, fmt, ...)@p | +error_propagate_prepend(errp, err, fmt, ...)@p +| +error_vprepend(errp, fmt, ap)@p +| error_prepend(errp, fmt, ...)@p | error_setg_file_open(errp, eno, cls, fmt, ...)@p | +warn_reportf_err(errp, fmt, ...)@p +| error_reportf_err(errp, fmt, ...)@p | error_set(errp, cls, fmt, ...)@p @@ -26,4 +46,4 @@ fmt << r.fmt; p << r.p; @@ if "\\n" in str(fmt): - print "%s:%s:%s:%s" % (p[0].file, p[0].line, p[0].column, fmt) + print("%s:%s:%s:%s" % (p[0].file, p[0].line, p[0].column, fmt)) diff --git a/scripts/coccinelle/errp-guard.cocci b/scripts/coccinelle/errp-guard.cocci new file mode 100644 index 0000000000000000000000000000000000000000..6e789acf2d772ff6798dcc1bdb025efea3845e15 --- /dev/null +++ b/scripts/coccinelle/errp-guard.cocci @@ -0,0 +1,336 @@ +// Use ERRP_GUARD() (see include/qapi/error.h) +// +// Copyright (c) 2020 Virtuozzo International GmbH. +// +// 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 +// . +// +// Usage example: +// spatch --sp-file scripts/coccinelle/errp-guard.cocci \ +// --macro-file scripts/cocci-macro-file.h --in-place \ +// --no-show-diff --max-width 80 FILES... +// +// Note: --max-width 80 is needed because coccinelle default is less +// than 80, and without this parameter coccinelle may reindent some +// lines which fit into 80 characters but not to coccinelle default, +// which in turn produces extra patch hunks for no reason. + +// Switch unusual Error ** parameter names to errp +// (this is necessary to use ERRP_GUARD). +// +// Disable optional_qualifier to skip functions with +// "Error *const *errp" parameter. +// +// Skip functions with "assert(_errp && *_errp)" statement, because +// that signals unusual semantics, and the parameter name may well +// serve a purpose. (like nbd_iter_channel_error()). +// +// Skip util/error.c to not touch, for example, error_propagate() and +// error_propagate_prepend(). +@ depends on !(file in "util/error.c") disable optional_qualifier@ +identifier fn; +identifier _errp != errp; +@@ + + fn(..., +- Error **_errp ++ Error **errp + ,...) + { +( + ... when != assert(_errp && *_errp) +& + <... +- _errp ++ errp + ...> +) + } + +// Add invocation of ERRP_GUARD() to errp-functions where // necessary +// +// Note, that without "when any" the final "..." does not mach +// something matched by previous pattern, i.e. the rule will not match +// double error_prepend in control flow like in +// vfio_set_irq_signaling(). +// +// Note, "exists" says that we want apply rule even if it does not +// match on all possible control flows (otherwise, it will not match +// standard pattern when error_propagate() call is in if branch). +@ disable optional_qualifier exists@ +identifier fn, local_err; +symbol errp; +@@ + + fn(..., Error **errp, ...) + { ++ ERRP_GUARD(); + ... when != ERRP_GUARD(); +( +( + error_append_hint(errp, ...); +| + error_prepend(errp, ...); +| + error_vprepend(errp, ...); +) + ... when any +| + Error *local_err = NULL; + ... +( + error_propagate_prepend(errp, local_err, ...); +| + error_propagate(errp, local_err); +) + ... +) + } + +// Warn when several Error * definitions are in the control flow. +// This rule is not chained to rule1 and less restrictive, to cover more +// functions to warn (even those we are not going to convert). +// +// Note, that even with one (or zero) Error * definition in the each +// control flow we may have several (in total) Error * definitions in +// the function. This case deserves attention too, but I don't see +// simple way to match with help of coccinelle. +@check1 disable optional_qualifier exists@ +identifier fn, _errp, local_err, local_err2; +position p1, p2; +@@ + + fn(..., Error **_errp, ...) + { + ... + Error *local_err = NULL;@p1 + ... when any + Error *local_err2 = NULL;@p2 + ... when any + } + +@ script:python @ +fn << check1.fn; +p1 << check1.p1; +p2 << check1.p2; +@@ + +print('Warning: function {} has several definitions of ' + 'Error * local variable: at {}:{} and then at {}:{}'.format( + fn, p1[0].file, p1[0].line, p2[0].file, p2[0].line)) + +// Warn when several propagations are in the control flow. +@check2 disable optional_qualifier exists@ +identifier fn, _errp; +position p1, p2; +@@ + + fn(..., Error **_errp, ...) + { + ... +( + error_propagate_prepend(_errp, ...);@p1 +| + error_propagate(_errp, ...);@p1 +) + ... +( + error_propagate_prepend(_errp, ...);@p2 +| + error_propagate(_errp, ...);@p2 +) + ... when any + } + +@ script:python @ +fn << check2.fn; +p1 << check2.p1; +p2 << check2.p2; +@@ + +print('Warning: function {} propagates to errp several times in ' + 'one control flow: at {}:{} and then at {}:{}'.format( + fn, p1[0].file, p1[0].line, p2[0].file, p2[0].line)) + +// Match functions with propagation of local error to errp. +// We want to refer these functions in several following rules, but I +// don't know a proper way to inherit a function, not just its name +// (to not match another functions with same name in following rules). +// Not-proper way is as follows: rename errp parameter in functions +// header and match it in following rules. Rename it back after all +// transformations. +// +// The common case is a single definition of local_err with at most one +// error_propagate_prepend() or error_propagate() on each control-flow +// path. Functions with multiple definitions or propagates we want to +// examine manually. Rules check1 and check2 emit warnings to guide us +// to them. +// +// Note that we match not only this "common case", but any function, +// which has the "common case" on at least one control-flow path. +@rule1 disable optional_qualifier exists@ +identifier fn, local_err; +symbol errp; +@@ + + fn(..., Error ** +- errp ++ ____ + , ...) + { + ... + Error *local_err = NULL; + ... +( + error_propagate_prepend(errp, local_err, ...); +| + error_propagate(errp, local_err); +) + ... + } + +// Convert special case with goto separately. +// I tried merging this into the following rule the obvious way, but +// it made Coccinelle hang on block.c +// +// Note interesting thing: if we don't do it here, and try to fixup +// "out: }" things later after all transformations (the rule will be +// the same, just without error_propagate() call), coccinelle fails to +// match this "out: }". +@ disable optional_qualifier@ +identifier rule1.fn, rule1.local_err, out; +symbol errp; +@@ + + fn(..., Error ** ____, ...) + { + <... +- goto out; ++ return; + ...> +- out: +- error_propagate(errp, local_err); + } + +// Convert most of local_err related stuff. +// +// Note, that we inherit rule1.fn and rule1.local_err names, not +// objects themselves. We may match something not related to the +// pattern matched by rule1. For example, local_err may be defined with +// the same name in different blocks inside one function, and in one +// block follow the propagation pattern and in other block doesn't. +// +// Note also that errp-cleaning functions +// error_free_errp +// error_report_errp +// error_reportf_errp +// warn_report_errp +// warn_reportf_errp +// are not yet implemented. They must call corresponding Error* - +// freeing function and then set *errp to NULL, to avoid further +// propagation to original errp (consider ERRP_GUARD in use). +// For example, error_free_errp may look like this: +// +// void error_free_errp(Error **errp) +// { +// error_free(*errp); +// *errp = NULL; +// } +@ disable optional_qualifier exists@ +identifier rule1.fn, rule1.local_err; +expression list args; +symbol errp; +@@ + + fn(..., Error ** ____, ...) + { + <... +( +- Error *local_err = NULL; +| + +// Convert error clearing functions +( +- error_free(local_err); ++ error_free_errp(errp); +| +- error_report_err(local_err); ++ error_report_errp(errp); +| +- error_reportf_err(local_err, args); ++ error_reportf_errp(errp, args); +| +- warn_report_err(local_err); ++ warn_report_errp(errp); +| +- warn_reportf_err(local_err, args); ++ warn_reportf_errp(errp, args); +) +?- local_err = NULL; + +| +- error_propagate_prepend(errp, local_err, args); ++ error_prepend(errp, args); +| +- error_propagate(errp, local_err); +| +- &local_err ++ errp +) + ...> + } + +// Convert remaining local_err usage. For example, different kinds of +// error checking in if conditionals. We can't merge this into +// previous hunk, as this conflicts with other substitutions in it (at +// least with "- local_err = NULL"). +@ disable optional_qualifier@ +identifier rule1.fn, rule1.local_err; +symbol errp; +@@ + + fn(..., Error ** ____, ...) + { + <... +- local_err ++ *errp + ...> + } + +// Always use the same pattern for checking error +@ disable optional_qualifier@ +identifier rule1.fn; +symbol errp; +@@ + + fn(..., Error ** ____, ...) + { + <... +- *errp != NULL ++ *errp + ...> + } + +// Revert temporary ___ identifier. +@ disable optional_qualifier@ +identifier rule1.fn; +@@ + + fn(..., Error ** +- ____ ++ errp + , ...) + { + ... + } diff --git a/scripts/coccinelle/qom-parent-type.cocci b/scripts/coccinelle/qom-parent-type.cocci new file mode 100644 index 0000000000000000000000000000000000000000..9afb3edd97fb447d10fd79be8766c3745f40fe04 --- /dev/null +++ b/scripts/coccinelle/qom-parent-type.cocci @@ -0,0 +1,26 @@ +// Highlight object declarations that don't look like object class but +// accidentally inherit from it. + +@match@ +identifier obj_t, fld; +type parent_t =~ ".*Class$"; +@@ +struct obj_t { + parent_t fld; + ... +}; + +@script:python filter depends on match@ +obj_t << match.obj_t; +@@ +is_class_obj = obj_t.endswith('Class') +cocci.include_match(not is_class_obj) + +@replacement depends on filter@ +identifier match.obj_t, match.fld; +type match.parent_t; +@@ +struct obj_t { +* parent_t fld; + ... +}; diff --git a/COVER b/scripts/codeconverter/codeconverter/__init__.py similarity index 100% rename from COVER rename to scripts/codeconverter/codeconverter/__init__.py diff --git a/scripts/codeconverter/codeconverter/patching.py b/scripts/codeconverter/codeconverter/patching.py new file mode 100644 index 0000000000000000000000000000000000000000..9e92505d394adcb3257688bd8f1596c87037dc9b --- /dev/null +++ b/scripts/codeconverter/codeconverter/patching.py @@ -0,0 +1,466 @@ +# Copyright (C) 2020 Red Hat Inc. +# +# Authors: +# Eduardo Habkost +# +# This work is licensed under the terms of the GNU GPL, version 2. See +# the COPYING file in the top-level directory. +from typing import IO, Match, NamedTuple, Optional, Literal, Iterable, Type, Dict, List, Any, TypeVar, NewType, Tuple, Union +from pathlib import Path +from itertools import chain +from tempfile import NamedTemporaryFile +import os +import re +import subprocess +from io import StringIO + +import logging +logger = logging.getLogger(__name__) +DBG = logger.debug +INFO = logger.info +WARN = logger.warning +ERROR = logger.error + +from .utils import * + +T = TypeVar('T') + +class Patch(NamedTuple): + # start inside file.original_content + start: int + # end position inside file.original_content + end: int + # replacement string for file.original_content[start:end] + replacement: str + +IdentifierType = Literal['type', 'symbol', 'include', 'constant'] +class RequiredIdentifier(NamedTuple): + type: IdentifierType + name: str + +class FileMatch: + """Base class for regex matches + + Subclasses just need to set the `regexp` class attribute + """ + regexp: Optional[str] = None + + def __init__(self, f: 'FileInfo', m: Match) -> None: + self.file: 'FileInfo' = f + self.match: Match[str] = m + + @property + def name(self) -> str: + if 'name' not in self.match.groupdict(): + return '[no name]' + return self.group('name') + + @classmethod + def compiled_re(klass): + return re.compile(klass.regexp, re.MULTILINE) + + def start(self) -> int: + return self.match.start() + + def end(self) -> int: + return self.match.end() + + def line_col(self) -> LineAndColumn: + return self.file.line_col(self.start()) + + def group(self, group: Union[int, str]) -> str: + return self.match.group(group) + + def getgroup(self, group: str) -> Optional[str]: + if group not in self.match.groupdict(): + return None + return self.match.group(group) + + def log(self, level, fmt, *args) -> None: + pos = self.line_col() + logger.log(level, '%s:%d:%d: '+fmt, self.file.filename, pos.line, pos.col, *args) + + def debug(self, fmt, *args) -> None: + self.log(logging.DEBUG, fmt, *args) + + def info(self, fmt, *args) -> None: + self.log(logging.INFO, fmt, *args) + + def warn(self, fmt, *args) -> None: + self.log(logging.WARNING, fmt, *args) + + def error(self, fmt, *args) -> None: + self.log(logging.ERROR, fmt, *args) + + def sub(self, original: str, replacement: str) -> str: + """Replace content + + XXX: this won't use the match position, but will just + replace all strings that look like the original match. + This should be enough for all the patterns used in this + script. + """ + return original.replace(self.group(0), replacement) + + def sanity_check(self) -> None: + """Sanity check match, and print warnings if necessary""" + pass + + def replacement(self) -> Optional[str]: + """Return replacement text for pattern, to use new code conventions""" + return None + + def make_patch(self, replacement: str) -> 'Patch': + """Make patch replacing the content of this match""" + return Patch(self.start(), self.end(), replacement) + + def make_subpatch(self, start: int, end: int, replacement: str) -> 'Patch': + return Patch(self.start() + start, self.start() + end, replacement) + + def make_removal_patch(self) -> 'Patch': + """Make patch removing contents of match completely""" + return self.make_patch('') + + def append(self, s: str) -> 'Patch': + """Make patch appending string after this match""" + return Patch(self.end(), self.end(), s) + + def prepend(self, s: str) -> 'Patch': + """Make patch prepending string before this match""" + return Patch(self.start(), self.start(), s) + + def gen_patches(self) -> Iterable['Patch']: + """Patch source code contents to use new code patterns""" + replacement = self.replacement() + if replacement is not None: + yield self.make_patch(replacement) + + @classmethod + def has_replacement_rule(klass) -> bool: + return (klass.gen_patches is not FileMatch.gen_patches + or klass.replacement is not FileMatch.replacement) + + def contains(self, other: 'FileMatch') -> bool: + return other.start() >= self.start() and other.end() <= self.end() + + def __repr__(self) -> str: + start = self.file.line_col(self.start()) + end = self.file.line_col(self.end() - 1) + return '<%s %s at %d:%d-%d:%d: %r>' % (self.__class__.__name__, + self.name, + start.line, start.col, + end.line, end.col, self.group(0)[:100]) + + def required_identifiers(self) -> Iterable[RequiredIdentifier]: + """Can be implemented by subclasses to keep track of identifier references + + This method will be used by the code that moves declarations around the file, + to make sure we find the right spot for them. + """ + raise NotImplementedError() + + def provided_identifiers(self) -> Iterable[RequiredIdentifier]: + """Can be implemented by subclasses to keep track of identifier references + + This method will be used by the code that moves declarations around the file, + to make sure we find the right spot for them. + """ + raise NotImplementedError() + + @classmethod + def finditer(klass, content: str, pos=0, endpos=-1) -> Iterable[Match]: + """Helper for re.finditer()""" + if endpos >= 0: + content = content[:endpos] + return klass.compiled_re().finditer(content, pos) + + @classmethod + def domatch(klass, content: str, pos=0, endpos=-1) -> Optional[Match]: + """Helper for re.match()""" + if endpos >= 0: + content = content[:endpos] + return klass.compiled_re().match(content, pos) + + def group_finditer(self, klass: Type['FileMatch'], group: Union[str, int]) -> Iterable['FileMatch']: + assert self.file.original_content + return (klass(self.file, m) + for m in klass.finditer(self.file.original_content, + self.match.start(group), + self.match.end(group))) + + def try_group_match(self, klass: Type['FileMatch'], group: Union[str, int]) -> Optional['FileMatch']: + assert self.file.original_content + m = klass.domatch(self.file.original_content, + self.match.start(group), + self.match.end(group)) + if not m: + return None + else: + return klass(self.file, m) + + def group_match(self, group: Union[str, int]) -> 'FileMatch': + m = self.try_group_match(FullMatch, group) + assert m + return m + + @property + def allfiles(self) -> 'FileList': + return self.file.allfiles + +class FullMatch(FileMatch): + """Regexp that will match all contents of string + Useful when used with group_match() + """ + regexp = r'(?s).*' # (?s) is re.DOTALL + +def all_subclasses(c: Type[FileMatch]) -> Iterable[Type[FileMatch]]: + for sc in c.__subclasses__(): + yield sc + yield from all_subclasses(sc) + +def match_class_dict() -> Dict[str, Type[FileMatch]]: + d = dict((t.__name__, t) for t in all_subclasses(FileMatch)) + return d + +def names(matches: Iterable[FileMatch]) -> Iterable[str]: + return [m.name for m in matches] + +class PatchingError(Exception): + pass + +class OverLappingPatchesError(PatchingError): + pass + +def apply_patches(s: str, patches: Iterable[Patch]) -> str: + """Apply a sequence of patches to string + + >>> apply_patches('abcdefg', [Patch(2,2,'xxx'), Patch(0, 1, 'yy')]) + 'yybxxxcdefg' + """ + r = StringIO() + last = 0 + def patch_sort_key(item: Tuple[int, Patch]) -> Tuple[int, int, int]: + """Patches are sorted by byte position, + patches at the same byte position are applied in the order + they were generated. + """ + i,p = item + return (p.start, p.end, i) + + for i,p in sorted(enumerate(patches), key=patch_sort_key): + DBG("Applying patch at position %d (%s) - %d (%s): %r", + p.start, line_col(s, p.start), + p.end, line_col(s, p.end), + p.replacement) + if last > p.start: + raise OverLappingPatchesError("Overlapping patch at position %d (%s), last patch at %d (%s)" % \ + (p.start, line_col(s, p.start), last, line_col(s, last))) + r.write(s[last:p.start]) + r.write(p.replacement) + last = p.end + r.write(s[last:]) + return r.getvalue() + +class RegexpScanner: + def __init__(self) -> None: + self.match_index: Dict[Type[Any], List[FileMatch]] = {} + self.match_name_index: Dict[Tuple[Type[Any], str, str], Optional[FileMatch]] = {} + + def _matches_of_type(self, klass: Type[Any]) -> Iterable[FileMatch]: + raise NotImplementedError() + + def matches_of_type(self, t: Type[T]) -> List[T]: + if t not in self.match_index: + self.match_index[t] = list(self._matches_of_type(t)) + return self.match_index[t] # type: ignore + + def find_matches(self, t: Type[T], name: str, group: str='name') -> List[T]: + indexkey = (t, name, group) + if indexkey in self.match_name_index: + return self.match_name_index[indexkey] # type: ignore + r: List[T] = [] + for m in self.matches_of_type(t): + assert isinstance(m, FileMatch) + if m.getgroup(group) == name: + r.append(m) # type: ignore + self.match_name_index[indexkey] = r # type: ignore + return r + + def find_match(self, t: Type[T], name: str, group: str='name') -> Optional[T]: + l = self.find_matches(t, name, group) + if not l: + return None + if len(l) > 1: + logger.warn("multiple matches found for %r (%s=%r)", t, group, name) + return None + return l[0] + + def reset_index(self) -> None: + self.match_index.clear() + self.match_name_index.clear() + +class FileInfo(RegexpScanner): + filename: Path + original_content: Optional[str] = None + + def __init__(self, files: 'FileList', filename: os.PathLike, force:bool=False) -> None: + super().__init__() + self.allfiles = files + self.filename = Path(filename) + self.patches: List[Patch] = [] + self.force = force + + def __repr__(self) -> str: + return f'' + + def filename_matches(self, name: str) -> bool: + nameparts = Path(name).parts + return self.filename.parts[-len(nameparts):] == nameparts + + def line_col(self, start: int) -> LineAndColumn: + """Return line and column for a match object inside original_content""" + return line_col(self.original_content, start) + + def _matches_of_type(self, klass: Type[Any]) -> List[FileMatch]: + """Build FileMatch objects for each match of regexp""" + if not hasattr(klass, 'regexp') or klass.regexp is None: + return [] + assert hasattr(klass, 'regexp') + DBG("%s: scanning for %s", self.filename, klass.__name__) + DBG("regexp: %s", klass.regexp) + matches = [klass(self, m) for m in klass.finditer(self.original_content)] + DBG('%s: %d matches found for %s: %s', self.filename, len(matches), + klass.__name__,' '.join(names(matches))) + return matches + + def find_match(self, t: Type[T], name: str, group: str='name') -> Optional[T]: + for m in self.matches_of_type(t): + assert isinstance(m, FileMatch) + if m.getgroup(group) == name: + return m # type: ignore + return None + + def reset_content(self, s:str): + self.original_content = s + self.patches.clear() + self.reset_index() + self.allfiles.reset_index() + + def load(self) -> None: + if self.original_content is not None: + return + with open(self.filename, 'rt') as f: + self.reset_content(f.read()) + + @property + def all_matches(self) -> Iterable[FileMatch]: + lists = list(self.match_index.values()) + return (m for l in lists + for m in l) + + def gen_patches(self, matches: List[FileMatch]) -> None: + for m in matches: + DBG("Generating patches for %r", m) + for i,p in enumerate(m.gen_patches()): + DBG("patch %d generated by %r:", i, m) + DBG("replace contents at %s-%s with %r", + self.line_col(p.start), self.line_col(p.end), p.replacement) + self.patches.append(p) + + def scan_for_matches(self, class_names: Optional[List[str]]=None) -> Iterable[FileMatch]: + DBG("class names: %r", class_names) + class_dict = match_class_dict() + if class_names is None: + DBG("default class names") + class_names = list(name for name,klass in class_dict.items() + if klass.has_replacement_rule()) + DBG("class_names: %r", class_names) + for cn in class_names: + matches = self.matches_of_type(class_dict[cn]) + DBG('%d matches found for %s: %s', + len(matches), cn, ' '.join(names(matches))) + yield from matches + + def apply_patches(self) -> None: + """Replace self.original_content after applying patches from self.patches""" + self.reset_content(self.get_patched_content()) + + def get_patched_content(self) -> str: + assert self.original_content is not None + return apply_patches(self.original_content, self.patches) + + def write_to_file(self, f: IO[str]) -> None: + f.write(self.get_patched_content()) + + def write_to_filename(self, filename: os.PathLike) -> None: + with open(filename, 'wt') as of: + self.write_to_file(of) + + def patch_inplace(self) -> None: + newfile = self.filename.with_suffix('.changed') + self.write_to_filename(newfile) + os.rename(newfile, self.filename) + + def show_diff(self) -> None: + with NamedTemporaryFile('wt') as f: + self.write_to_file(f) + f.flush() + subprocess.call(['diff', '-u', self.filename, f.name]) + + def ref(self): + return TypeInfoReference + +class FileList(RegexpScanner): + def __init__(self): + super().__init__() + self.files: List[FileInfo] = [] + + def extend(self, *args, **kwargs): + self.files.extend(*args, **kwargs) + + def __iter__(self): + return iter(self.files) + + def _matches_of_type(self, klass: Type[Any]) -> Iterable[FileMatch]: + return chain(*(f._matches_of_type(klass) for f in self.files)) + + def find_file(self, name: str) -> Optional[FileInfo]: + """Get file with path ending with @name""" + for f in self.files: + if f.filename_matches(name): + return f + else: + return None + + def one_pass(self, class_names: List[str]) -> int: + total_patches = 0 + for f in self.files: + INFO("Scanning file %s", f.filename) + matches = list(f.scan_for_matches(class_names)) + INFO("Generating patches for file %s", f.filename) + f.gen_patches(matches) + total_patches += len(f.patches) + if total_patches: + for f in self.files: + try: + f.apply_patches() + except PatchingError: + logger.exception("%s: failed to patch file", f.filename) + return total_patches + + def patch_content(self, max_passes, class_names: List[str]) -> None: + """Multi-pass content patching loop + + We run multiple passes because there are rules that will + delete init functions once they become empty. + """ + passes = 0 + total_patches = 0 + DBG("max_passes: %r", max_passes) + while not max_passes or max_passes <= 0 or passes < max_passes: + passes += 1 + INFO("Running pass: %d", passes) + count = self.one_pass(class_names) + DBG("patch content: pass %d: %d patches generated", passes, count) + total_patches += count + DBG("%d patches applied total in %d passes", total_patches, passes) diff --git a/scripts/codeconverter/codeconverter/qom_macros.py b/scripts/codeconverter/codeconverter/qom_macros.py new file mode 100644 index 0000000000000000000000000000000000000000..2d2f2055a3da7d72a884d3e67db7ba43207c70cd --- /dev/null +++ b/scripts/codeconverter/codeconverter/qom_macros.py @@ -0,0 +1,861 @@ +# Copyright (C) 2020 Red Hat Inc. +# +# Authors: +# Eduardo Habkost +# +# This work is licensed under the terms of the GNU GPL, version 2. See +# the COPYING file in the top-level directory. +import re +from itertools import chain +from typing import * + +from .regexps import * +from .patching import * +from .utils import * + +import logging +logger = logging.getLogger(__name__) +DBG = logger.debug +INFO = logger.info +WARN = logger.warning + +# simple expressions: + +RE_CONSTANT = OR(RE_STRING, RE_NUMBER) + +class DefineDirective(FileMatch): + """Match any #define directive""" + regexp = S(r'^[ \t]*#[ \t]*define', CPP_SPACE, NAMED('name', RE_IDENTIFIER), r'\b') + +class ExpressionDefine(FileMatch): + """Simple #define preprocessor directive for an expression""" + regexp = S(r'^[ \t]*#[ \t]*define', CPP_SPACE, NAMED('name', RE_IDENTIFIER), + CPP_SPACE, NAMED('value', RE_EXPRESSION), r'[ \t]*\n') + + def provided_identifiers(self) -> Iterable[RequiredIdentifier]: + yield RequiredIdentifier('constant', self.group('name')) + +class ConstantDefine(ExpressionDefine): + """Simple #define preprocessor directive for a number or string constant""" + regexp = S(r'^[ \t]*#[ \t]*define', CPP_SPACE, NAMED('name', RE_IDENTIFIER), + CPP_SPACE, NAMED('value', RE_CONSTANT), r'[ \t]*\n') + + +class TypeIdentifiers(NamedTuple): + """Type names found in type declarations""" + # TYPE_MYDEVICE + typename: Optional[str] + # MYDEVICE + uppercase: Optional[str] = None + # MyDevice + instancetype: Optional[str] = None + # MyDeviceClass + classtype: Optional[str] = None + # my_device + lowercase: Optional[str] = None + + def allfields(self): + return tuple(getattr(self, f) for f in self._fields) + + def merge(self, other: 'TypeIdentifiers') -> Optional['TypeIdentifiers']: + """Check if identifiers match, return new identifier with complete list""" + if any(not opt_compare(a, b) for a,b in zip(self, other)): + return None + return TypeIdentifiers(*(merge(a, b) for a,b in zip(self, other))) + + def __str__(self) -> str: + values = ((f, getattr(self, f)) for f in self._fields) + s = ', '.join('%s=%s' % (f,v) for f,v in values if v is not None) + return f'{s}' + + def check_consistency(self) -> List[str]: + """Check if identifiers are consistent with each other, + return list of problems (or empty list if everything seems consistent) + """ + r = [] + if self.typename is None: + r.append("typename (TYPE_MYDEVICE) is unavailable") + + if self.uppercase is None: + r.append("uppercase name is unavailable") + + if (self.instancetype is not None + and self.classtype is not None + and self.classtype != f'{self.instancetype}Class'): + r.append("class typedef %s doesn't match instance typedef %s" % + (self.classtype, self.instancetype)) + + if (self.uppercase is not None + and self.typename is not None + and f'TYPE_{self.uppercase}' != self.typename): + r.append("uppercase name (%s) doesn't match type name (%s)" % + (self.uppercase, self.typename)) + + return r + +class TypedefMatch(FileMatch): + """typedef declaration""" + def provided_identifiers(self) -> Iterable[RequiredIdentifier]: + yield RequiredIdentifier('type', self.group('name')) + +class SimpleTypedefMatch(TypedefMatch): + """Simple typedef declaration + (no replacement rules)""" + regexp = S(r'^[ \t]*typedef', SP, + NAMED('typedef_type', RE_TYPE), SP, + NAMED('name', RE_IDENTIFIER), r'\s*;[ \t]*\n') + +RE_MACRO_DEFINE = S(r'^[ \t]*#\s*define\s+', NAMED('name', RE_IDENTIFIER), + r'\s*\(\s*', RE_IDENTIFIER, r'\s*\)', CPP_SPACE) + +RE_STRUCT_ATTRIBUTE = r'QEMU_PACKED' + +# This doesn't parse the struct definitions completely, it just assumes +# the closing brackets are going to be in an unindented line: +RE_FULL_STRUCT = S('struct', SP, M(RE_IDENTIFIER, n='?', name='structname'), SP, + NAMED('body', r'{\n', + # acceptable inside the struct body: + # - lines starting with space or tab + # - empty lines + # - preprocessor directives + # - comments + OR(r'[ \t][^\n]*\n', + r'#[^\n]*\n', + r'\n', + S(r'[ \t]*', RE_COMMENT, r'[ \t]*\n'), + repeat='*?'), + r'}', M(RE_STRUCT_ATTRIBUTE, SP, n='*'))) +RE_STRUCT_TYPEDEF = S(r'^[ \t]*typedef', SP, RE_FULL_STRUCT, SP, + NAMED('name', RE_IDENTIFIER), r'\s*;[ \t]*\n') + +class FullStructTypedefMatch(TypedefMatch): + """typedef struct [SomeStruct] { ...} SomeType + Will be replaced by separate struct declaration + typedef + """ + regexp = RE_STRUCT_TYPEDEF + + def make_structname(self) -> str: + """Make struct name for struct+typedef split""" + name = self.group('structname') + if not name: + name = self.name + return name + + def strip_typedef(self) -> Patch: + """generate patch that will strip typedef from the struct declartion + + The caller is responsible for readding the typedef somewhere else. + """ + name = self.make_structname() + body = self.group('body') + return self.make_patch(f'struct {name} {body};\n') + + def make_simple_typedef(self) -> str: + structname = self.make_structname() + name = self.name + return f'typedef struct {structname} {name};\n' + + def move_typedef(self, position) -> Iterator[Patch]: + """Generate patches to move typedef elsewhere""" + yield self.strip_typedef() + yield Patch(position, position, self.make_simple_typedef()) + + def split_typedef(self) -> Iterator[Patch]: + """Split into struct definition + typedef in-place""" + yield self.strip_typedef() + yield self.append(self.make_simple_typedef()) + +class StructTypedefSplit(FullStructTypedefMatch): + """split struct+typedef declaration""" + def gen_patches(self) -> Iterator[Patch]: + if self.group('structname'): + yield from self.split_typedef() + +class DuplicatedTypedefs(SimpleTypedefMatch): + """Delete ALL duplicate typedefs (unsafe)""" + def gen_patches(self) -> Iterable[Patch]: + other_td = [td for td in chain(self.file.matches_of_type(SimpleTypedefMatch), + self.file.matches_of_type(FullStructTypedefMatch)) + if td.name == self.name] + DBG("other_td: %r", other_td) + if any(td.start() < self.start() for td in other_td): + # patch only if handling the first typedef + return + for td in other_td: + if isinstance(td, SimpleTypedefMatch): + DBG("other td: %r", td.match.groupdict()) + if td.group('typedef_type') != self.group('typedef_type'): + yield td.make_removal_patch() + elif isinstance(td, FullStructTypedefMatch): + DBG("other td: %r", td.match.groupdict()) + if self.group('typedef_type') == 'struct '+td.group('structname'): + yield td.strip_typedef() + +class QOMDuplicatedTypedefs(DuplicatedTypedefs): + """Delete duplicate typedefs if used by QOM type""" + def gen_patches(self) -> Iterable[Patch]: + qom_macros = [TypeCheckMacro, DeclareInstanceChecker, DeclareClassCheckers, DeclareObjCheckers] + qom_matches = chain(*(self.file.matches_of_type(t) for t in qom_macros)) + in_use = any(RequiredIdentifier('type', self.name) in m.required_identifiers() + for m in qom_matches) + if in_use: + yield from DuplicatedTypedefs.gen_patches(self) + +class QOMStructTypedefSplit(FullStructTypedefMatch): + """split struct+typedef declaration if used by QOM type""" + def gen_patches(self) -> Iterator[Patch]: + qom_macros = [TypeCheckMacro, DeclareInstanceChecker, DeclareClassCheckers, DeclareObjCheckers] + qom_matches = chain(*(self.file.matches_of_type(t) for t in qom_macros)) + in_use = any(RequiredIdentifier('type', self.name) in m.required_identifiers() + for m in qom_matches) + if in_use: + yield from self.split_typedef() + +def typedefs(file: FileInfo) -> Iterable[TypedefMatch]: + return (cast(TypedefMatch, m) + for m in chain(file.matches_of_type(SimpleTypedefMatch), + file.matches_of_type(FullStructTypedefMatch))) + +def find_typedef(f: FileInfo, name: Optional[str]) -> Optional[TypedefMatch]: + if not name: + return None + for td in typedefs(f): + if td.name == name: + return td + return None + +CHECKER_MACROS = ['OBJECT_CHECK', 'OBJECT_CLASS_CHECK', 'OBJECT_GET_CLASS'] +CheckerMacroName = Literal['OBJECT_CHECK', 'OBJECT_CLASS_CHECK', 'OBJECT_GET_CLASS'] + +RE_CHECK_MACRO = \ + S(RE_MACRO_DEFINE, + OR(*CHECKER_MACROS, name='checker'), + M(r'\s*\(\s*', OR(NAMED('typedefname', RE_IDENTIFIER), RE_TYPE, name='c_type'), r'\s*,', CPP_SPACE, + OPTIONAL_PARS(RE_IDENTIFIER), r',', CPP_SPACE, + NAMED('qom_typename', RE_IDENTIFIER), r'\s*\)\n', + n='?', name='check_args')) + +EXPECTED_CHECKER_SUFFIXES: List[Tuple[CheckerMacroName, str]] = [ + ('OBJECT_GET_CLASS', '_GET_CLASS'), + ('OBJECT_CLASS_CHECK', '_CLASS'), +] + +class TypeCheckMacro(FileMatch): + """OBJECT_CHECK/OBJECT_CLASS_CHECK/OBJECT_GET_CLASS macro definitions + Will be replaced by DECLARE_*_CHECKERS macro + """ + regexp = RE_CHECK_MACRO + + @property + def checker(self) -> CheckerMacroName: + """Name of checker macro being used""" + return self.group('checker') # type: ignore + + @property + def typedefname(self) -> Optional[str]: + return self.group('typedefname') + + def find_typedef(self) -> Optional[TypedefMatch]: + return find_typedef(self.file, self.typedefname) + + def sanity_check(self) -> None: + DBG("groups: %r", self.match.groups()) + if not self.group('check_args'): + self.warn("type check macro not parsed completely: %s", self.name) + return + DBG("type identifiers: %r", self.type_identifiers) + if self.typedefname and self.find_typedef() is None: + self.warn("typedef used by %s not found", self.name) + + def find_matching_macros(self) -> List['TypeCheckMacro']: + """Find other check macros that generate the same macro names + + The returned list will always be sorted. + """ + my_ids = self.type_identifiers + assert my_ids + return [m for m in self.file.matches_of_type(TypeCheckMacro) + if m.type_identifiers is not None + and my_ids.uppercase is not None + and (my_ids.uppercase == m.type_identifiers.uppercase + or my_ids.typename == m.type_identifiers.typename)] + + def merge_ids(self, matches: List['TypeCheckMacro']) -> Optional[TypeIdentifiers]: + """Try to merge info about type identifiers from all matches in a list""" + if not matches: + return None + r = matches[0].type_identifiers + if r is None: + return None + for m in matches[1:]: + assert m.type_identifiers + new = r.merge(m.type_identifiers) + if new is None: + self.warn("macro %s identifiers (%s) don't match macro %s (%s)", + matches[0].name, r, m.name, m.type_identifiers) + return None + r = new + return r + + def required_identifiers(self) -> Iterable[RequiredIdentifier]: + yield RequiredIdentifier('include', '"qom/object.h"') + if self.type_identifiers is None: + return + # to make sure typedefs will be moved above all related macros, + # return dependencies from all of them, not just this match + for m in self.find_matching_macros(): + yield RequiredIdentifier('type', m.group('c_type')) + yield RequiredIdentifier('constant', m.group('qom_typename')) + + @property + def type_identifiers(self) -> Optional[TypeIdentifiers]: + """Extract type identifier information from match""" + typename = self.group('qom_typename') + c_type = self.group('c_type') + if not typename or not c_type: + return None + typedef = self.group('typedefname') + classtype = None + instancetype = None + uppercase = None + expected_suffix = dict(EXPECTED_CHECKER_SUFFIXES).get(self.checker) + + # here the available data depends on the checker macro being called: + # - we need to remove the suffix from the macro name + # - depending on the macro type, we know the class type name, or + # the instance type name + if self.checker in ('OBJECT_GET_CLASS', 'OBJECT_CLASS_CHECK'): + classtype = c_type + elif self.checker == 'OBJECT_CHECK': + instancetype = c_type + uppercase = self.name + else: + assert False + if expected_suffix and self.name.endswith(expected_suffix): + uppercase = self.name[:-len(expected_suffix)] + return TypeIdentifiers(typename=typename, classtype=classtype, + instancetype=instancetype, uppercase=uppercase) + + def gen_patches(self) -> Iterable[Patch]: + # the implementation is a bit tricky because we need to group + # macros dealing with the same type into a single declaration + if self.type_identifiers is None: + self.warn("couldn't extract type information from macro %s", self.name) + return + + if self.name == 'INTERFACE_CLASS': + # INTERFACE_CLASS is special and won't be patched + return + + for checker,suffix in EXPECTED_CHECKER_SUFFIXES: + if self.name.endswith(suffix): + if self.checker != checker: + self.warn("macro %s is using macro %s instead of %s", self.name, self.checker, checker) + return + break + + matches = self.find_matching_macros() + DBG("found %d matching macros: %s", len(matches), ' '.join(m.name for m in matches)) + # we will generate patches only when processing the first macro: + if matches[0].start != self.start: + DBG("skipping %s (will patch when handling %s)", self.name, matches[0].name) + return + + + ids = self.merge_ids(matches) + if ids is None: + DBG("type identifier mismatch, won't patch %s", self.name) + return + + if not ids.uppercase: + self.warn("macro %s doesn't follow the expected name pattern", self.name) + return + if not ids.typename: + self.warn("macro %s: couldn't extract type name", self.name) + return + + #issues = ids.check_consistency() + #if issues: + # for i in issues: + # self.warn("inconsistent identifiers: %s", i) + + names = [n for n in (ids.instancetype, ids.classtype, ids.uppercase, ids.typename) + if n is not None] + if len(set(names)) != len(names): + self.warn("duplicate names used by macro: %r", ids) + return + + assert ids.classtype or ids.instancetype + assert ids.typename + assert ids.uppercase + if ids.classtype and ids.instancetype: + new_decl = (f'DECLARE_OBJ_CHECKERS({ids.instancetype}, {ids.classtype},\n' + f' {ids.uppercase}, {ids.typename})\n') + elif ids.classtype: + new_decl = (f'DECLARE_CLASS_CHECKERS({ids.classtype}, {ids.uppercase},\n' + f' {ids.typename})\n') + elif ids.instancetype: + new_decl = (f'DECLARE_INSTANCE_CHECKER({ids.instancetype}, {ids.uppercase},\n' + f' {ids.typename})\n') + else: + assert False + + # we need to ensure the typedefs are already available + issues = [] + for t in [ids.instancetype, ids.classtype]: + if not t: + continue + if re.fullmatch(RE_STRUCT_TYPE, t): + self.info("type %s is not a typedef", t) + continue + td = find_typedef(self.file, t) + #if not td and self.allfiles.find_file('include/qemu/typedefs.h'): + # + if not td: + # it is OK if the typedef is in typedefs.h + f = self.allfiles.find_file('include/qemu/typedefs.h') + if f and find_typedef(f, t): + self.info("typedef %s found in typedefs.h", t) + continue + + issues.append("couldn't find typedef %s" % (t)) + elif td.start() > self.start(): + issues.append("typedef %s need to be moved earlier in the file" % (td.name)) + + for issue in issues: + self.warn(issue) + + if issues and not self.file.force: + return + + # delete all matching macros and add new declaration: + for m in matches: + yield m.make_patch('') + for issue in issues: + yield self.prepend("/* FIXME: %s */\n" % (issue)) + yield self.append(new_decl) + +class InterfaceCheckMacro(FileMatch): + """Type checking macro using INTERFACE_CHECK + Will be replaced by DECLARE_INTERFACE_CHECKER + """ + regexp = S(RE_MACRO_DEFINE, + 'INTERFACE_CHECK', + r'\s*\(\s*', OR(NAMED('instancetype', RE_IDENTIFIER), RE_TYPE, name='c_type'), + r'\s*,', CPP_SPACE, + OPTIONAL_PARS(RE_IDENTIFIER), r',', CPP_SPACE, + NAMED('qom_typename', RE_IDENTIFIER), r'\s*\)\n') + + def required_identifiers(self) -> Iterable[RequiredIdentifier]: + yield RequiredIdentifier('include', '"qom/object.h"') + yield RequiredIdentifier('type', self.group('instancetype')) + yield RequiredIdentifier('constant', self.group('qom_typename')) + + def gen_patches(self) -> Iterable[Patch]: + if self.file.filename_matches('qom/object.h'): + self.debug("skipping object.h") + return + + typename = self.group('qom_typename') + uppercase = self.name + instancetype = self.group('instancetype') + c = f"DECLARE_INTERFACE_CHECKER({instancetype}, {uppercase},\n"+\ + f" {typename})\n" + yield self.make_patch(c) + + +class TypeDeclaration(FileMatch): + """Parent class to all type declarations""" + @property + def instancetype(self) -> Optional[str]: + return self.getgroup('instancetype') + + @property + def classtype(self) -> Optional[str]: + return self.getgroup('classtype') + + @property + def typename(self) -> Optional[str]: + return self.getgroup('typename') + +class TypeCheckerDeclaration(TypeDeclaration): + """Parent class to all type checker declarations""" + @property + def typename(self) -> str: + return self.group('typename') + + @property + def uppercase(self) -> str: + return self.group('uppercase') + +class DeclareInstanceChecker(TypeCheckerDeclaration): + """DECLARE_INSTANCE_CHECKER use""" + #TODO: replace lonely DECLARE_INSTANCE_CHECKER with DECLARE_OBJ_CHECKERS + # if all types are found. + # This will require looking up the correct class type in the TypeInfo + # structs in another file + regexp = S(r'^[ \t]*DECLARE_INSTANCE_CHECKER\s*\(\s*', + NAMED('instancetype', RE_TYPE), r'\s*,\s*', + NAMED('uppercase', RE_IDENTIFIER), r'\s*,\s*', + OR(RE_IDENTIFIER, RE_STRING, RE_MACRO_CONCAT, RE_FUN_CALL, name='typename'), SP, + r'\)[ \t]*;?[ \t]*\n') + + def required_identifiers(self) -> Iterable[RequiredIdentifier]: + yield RequiredIdentifier('include', '"qom/object.h"') + yield RequiredIdentifier('constant', self.group('typename')) + yield RequiredIdentifier('type', self.group('instancetype')) + +class DeclareInterfaceChecker(TypeCheckerDeclaration): + """DECLARE_INTERFACE_CHECKER use""" + regexp = S(r'^[ \t]*DECLARE_INTERFACE_CHECKER\s*\(\s*', + NAMED('instancetype', RE_TYPE), r'\s*,\s*', + NAMED('uppercase', RE_IDENTIFIER), r'\s*,\s*', + OR(RE_IDENTIFIER, RE_STRING, RE_MACRO_CONCAT, RE_FUN_CALL, name='typename'), SP, + r'\)[ \t]*;?[ \t]*\n') + + def required_identifiers(self) -> Iterable[RequiredIdentifier]: + yield RequiredIdentifier('include', '"qom/object.h"') + yield RequiredIdentifier('constant', self.group('typename')) + yield RequiredIdentifier('type', self.group('instancetype')) + +class DeclareInstanceType(TypeDeclaration): + """DECLARE_INSTANCE_TYPE use""" + regexp = S(r'^[ \t]*DECLARE_INSTANCE_TYPE\s*\(\s*', + NAMED('uppercase', RE_IDENTIFIER), r'\s*,\s*', + NAMED('instancetype', RE_TYPE), SP, + r'\)[ \t]*;?[ \t]*\n') + + def required_identifiers(self) -> Iterable[RequiredIdentifier]: + yield RequiredIdentifier('include', '"qom/object.h"') + yield RequiredIdentifier('type', self.group('instancetype')) + +class DeclareClassType(TypeDeclaration): + """DECLARE_CLASS_TYPE use""" + regexp = S(r'^[ \t]*DECLARE_CLASS_TYPE\s*\(\s*', + NAMED('uppercase', RE_IDENTIFIER), r'\s*,\s*', + NAMED('classtype', RE_TYPE), SP, + r'\)[ \t]*;?[ \t]*\n') + + def required_identifiers(self) -> Iterable[RequiredIdentifier]: + yield RequiredIdentifier('include', '"qom/object.h"') + yield RequiredIdentifier('type', self.group('classtype')) + + + +class DeclareClassCheckers(TypeCheckerDeclaration): + """DECLARE_CLASS_CHECKER use""" + regexp = S(r'^[ \t]*DECLARE_CLASS_CHECKERS\s*\(\s*', + NAMED('classtype', RE_TYPE), r'\s*,\s*', + NAMED('uppercase', RE_IDENTIFIER), r'\s*,\s*', + OR(RE_IDENTIFIER, RE_STRING, RE_MACRO_CONCAT, RE_FUN_CALL, name='typename'), SP, + r'\)[ \t]*;?[ \t]*\n') + + def required_identifiers(self) -> Iterable[RequiredIdentifier]: + yield RequiredIdentifier('include', '"qom/object.h"') + yield RequiredIdentifier('constant', self.group('typename')) + yield RequiredIdentifier('type', self.group('classtype')) + +class DeclareObjCheckers(TypeCheckerDeclaration): + """DECLARE_OBJ_CHECKERS use""" + #TODO: detect when OBJECT_DECLARE_SIMPLE_TYPE can be used + regexp = S(r'^[ \t]*DECLARE_OBJ_CHECKERS\s*\(\s*', + NAMED('instancetype', RE_TYPE), r'\s*,\s*', + NAMED('classtype', RE_TYPE), r'\s*,\s*', + NAMED('uppercase', RE_IDENTIFIER), r'\s*,\s*', + OR(RE_IDENTIFIER, RE_STRING, RE_MACRO_CONCAT, RE_FUN_CALL, name='typename'), SP, + r'\)[ \t]*;?[ \t]*\n') + + def required_identifiers(self) -> Iterable[RequiredIdentifier]: + yield RequiredIdentifier('include', '"qom/object.h"') + yield RequiredIdentifier('constant', self.group('typename')) + yield RequiredIdentifier('type', self.group('classtype')) + yield RequiredIdentifier('type', self.group('instancetype')) + +class TypeDeclarationFixup(FileMatch): + """Common base class for code that will look at a set of type declarations""" + regexp = RE_FILE_BEGIN + def gen_patches(self) -> Iterable[Patch]: + if self.file.filename_matches('qom/object.h'): + self.debug("skipping object.h") + return + + # group checkers by uppercase name: + decl_types: List[Type[TypeDeclaration]] = [DeclareInstanceChecker, DeclareInstanceType, + DeclareClassCheckers, DeclareClassType, + DeclareObjCheckers] + checker_dict: Dict[str, List[TypeDeclaration]] = {} + for t in decl_types: + for m in self.file.matches_of_type(t): + checker_dict.setdefault(m.group('uppercase'), []).append(m) + self.debug("checker_dict: %r", checker_dict) + for uppercase,checkers in checker_dict.items(): + fields = ('instancetype', 'classtype', 'uppercase', 'typename') + fvalues = dict((field, set(getattr(m, field) for m in checkers + if getattr(m, field, None) is not None)) + for field in fields) + for field,values in fvalues.items(): + if len(values) > 1: + for c in checkers: + c.warn("%s mismatch (%s)", field, ' '.join(values)) + return + + field_dict = dict((f, v.pop() if v else None) for f,v in fvalues.items()) + yield from self.gen_patches_for_type(uppercase, checkers, field_dict) + + def find_conflicts(self, uppercase: str, checkers: List[TypeDeclaration]) -> bool: + """Look for conflicting declarations that would make it unsafe to add new ones""" + conflicting: List[FileMatch] = [] + # conflicts in the same file: + conflicting.extend(chain(self.file.find_matches(DefineDirective, uppercase), + self.file.find_matches(DeclareInterfaceChecker, uppercase, 'uppercase'), + self.file.find_matches(DeclareClassType, uppercase, 'uppercase'), + self.file.find_matches(DeclareInstanceType, uppercase, 'uppercase'))) + + # conflicts in another file: + conflicting.extend(o for o in chain(self.allfiles.find_matches(DeclareInstanceChecker, uppercase, 'uppercase'), + self.allfiles.find_matches(DeclareClassCheckers, uppercase, 'uppercase'), + self.allfiles.find_matches(DeclareInterfaceChecker, uppercase, 'uppercase'), + self.allfiles.find_matches(DefineDirective, uppercase)) + if o is not None and o.file != self.file + # if both are .c files, there's no conflict at all: + and not (o.file.filename.suffix == '.c' and + self.file.filename.suffix == '.c')) + + if conflicting: + for c in checkers: + c.warn("skipping due to conflicting %s macro", uppercase) + for o in conflicting: + if o is None: + continue + o.warn("conflicting %s macro is here", uppercase) + return True + + return False + + def gen_patches_for_type(self, uppercase: str, + checkers: List[TypeDeclaration], + fields: Dict[str, Optional[str]]) -> Iterable[Patch]: + """Should be reimplemented by subclasses""" + return + yield + +class DeclareVoidTypes(TypeDeclarationFixup): + """Add DECLARE_*_TYPE(..., void) when there's no declared type""" + regexp = RE_FILE_BEGIN + def gen_patches_for_type(self, uppercase: str, + checkers: List[TypeDeclaration], + fields: Dict[str, Optional[str]]) -> Iterable[Patch]: + if self.find_conflicts(uppercase, checkers): + return + + #_,last_checker = max((m.start(), m) for m in checkers) + _,first_checker = min((m.start(), m) for m in checkers) + + if not any(m.instancetype for m in checkers): + yield first_checker.prepend(f'DECLARE_INSTANCE_TYPE({uppercase}, void)\n') + if not any(m.classtype for m in checkers): + yield first_checker.prepend(f'DECLARE_CLASS_TYPE({uppercase}, void)\n') + + #if not all(len(v) == 1 for v in fvalues.values()): + # return + # + #final_values = dict((field, values.pop()) + # for field,values in fvalues.items()) + #s = (f"DECLARE_OBJ_CHECKERS({final_values['instancetype']}, {final_values['classtype']},\n"+ + # f" {final_values['uppercase']}, {final_values['typename']})\n") + #for c in checkers: + # yield c.make_removal_patch() + #yield last_checker.append(s) + + +class AddDeclareTypeName(TypeDeclarationFixup): + """Add DECLARE_TYPE_NAME declarations if necessary""" + def gen_patches_for_type(self, uppercase: str, + checkers: List[TypeDeclaration], + fields: Dict[str, Optional[str]]) -> Iterable[Patch]: + typename = fields.get('typename') + if typename is None: + self.warn("typename unavailable") + return + if typename == f'TYPE_{uppercase}': + self.info("already using TYPE_%s as type name", uppercase) + return + if self.file.find_match(DeclareTypeName, uppercase, 'uppercase'): + self.info("type name for %s already declared", uppercase) + return + _,first_checker = min((m.start(), m) for m in checkers) + s = f'DECLARE_TYPE_NAME({uppercase}, {typename})\n' + yield first_checker.prepend(s) + +class TrivialClassStruct(FileMatch): + """Trivial class struct""" + regexp = S(r'^[ \t]*struct\s*', NAMED('name', RE_IDENTIFIER), + r'\s*{\s*', NAMED('parent_struct', RE_IDENTIFIER), r'\s*parent(_class)?\s*;\s*};\n') + +class DeclareTypeName(FileMatch): + """DECLARE_TYPE_NAME usage""" + regexp = S(r'^[ \t]*DECLARE_TYPE_NAME\s*\(', + NAMED('uppercase', RE_IDENTIFIER), r'\s*,\s*', + OR(RE_IDENTIFIER, RE_STRING, RE_MACRO_CONCAT, RE_FUN_CALL, name='typename'), + r'\s*\);?[ \t]*\n') + +class ObjectDeclareType(TypeCheckerDeclaration): + """OBJECT_DECLARE_TYPE usage + Will be replaced with OBJECT_DECLARE_SIMPLE_TYPE if possible + """ + regexp = S(r'^[ \t]*OBJECT_DECLARE_TYPE\s*\(', + NAMED('instancetype', RE_TYPE), r'\s*,\s*', + NAMED('classtype', RE_TYPE), r'\s*,\s*', + NAMED('uppercase', RE_IDENTIFIER), SP, + r'\)[ \t]*;?[ \t]*\n') + + def gen_patches(self): + DBG("groups: %r", self.match.groupdict()) + trivial_struct = self.file.find_match(TrivialClassStruct, self.group('classtype')) + if trivial_struct: + d = self.match.groupdict().copy() + d['parent_struct'] = trivial_struct.group("parent_struct") + yield trivial_struct.make_removal_patch() + c = ("OBJECT_DECLARE_SIMPLE_TYPE(%(instancetype)s, %(lowercase)s,\n" + " %(uppercase)s, %(parent_struct)s)\n" % d) + yield self.make_patch(c) + +class ObjectDeclareSimpleType(TypeCheckerDeclaration): + """OBJECT_DECLARE_SIMPLE_TYPE usage""" + regexp = S(r'^[ \t]*OBJECT_DECLARE_SIMPLE_TYPE\s*\(', + NAMED('instancetype', RE_TYPE), r'\s*,\s*', + NAMED('uppercase', RE_IDENTIFIER), SP, + r'\)[ \t]*;?[ \t]*\n') + +class OldStyleObjectDeclareSimpleType(TypeCheckerDeclaration): + """OBJECT_DECLARE_SIMPLE_TYPE usage (old API)""" + regexp = S(r'^[ \t]*OBJECT_DECLARE_SIMPLE_TYPE\s*\(', + NAMED('instancetype', RE_TYPE), r'\s*,\s*', + NAMED('lowercase', RE_IDENTIFIER), r'\s*,\s*', + NAMED('uppercase', RE_IDENTIFIER), r'\s*,\s*', + NAMED('parent_classtype', RE_TYPE), SP, + r'\)[ \t]*;?[ \t]*\n') + + @property + def classtype(self) -> Optional[str]: + instancetype = self.instancetype + assert instancetype + return f"{instancetype}Class" + +def find_typename_uppercase(files: FileList, typename: str) -> Optional[str]: + """Try to find what's the right MODULE_OBJ_NAME for a given type name""" + decl = files.find_match(DeclareTypeName, name=typename, group='typename') + if decl: + return decl.group('uppercase') + if typename.startswith('TYPE_'): + return typename[len('TYPE_'):] + return None + +def find_type_checkers(files:FileList, name:str, group:str='uppercase') -> Iterable[TypeCheckerDeclaration]: + """Find usage of DECLARE*CHECKER macro""" + c: Type[TypeCheckerDeclaration] + for c in (DeclareInstanceChecker, DeclareClassCheckers, DeclareObjCheckers, ObjectDeclareType, ObjectDeclareSimpleType): + yield from files.find_matches(c, name=name, group=group) + +class Include(FileMatch): + """#include directive""" + regexp = RE_INCLUDE + def provided_identifiers(self) -> Iterable[RequiredIdentifier]: + yield RequiredIdentifier('include', self.group('includepath')) + +class InitialIncludes(FileMatch): + """Initial #include block""" + regexp = S(RE_FILE_BEGIN, + M(SP, RE_COMMENTS, + r'^[ \t]*#[ \t]*ifndef[ \t]+', RE_IDENTIFIER, r'[ \t]*\n', + n='?', name='ifndef_block'), + M(SP, RE_COMMENTS, + OR(RE_INCLUDE, RE_SIMPLEDEFINE), + n='*', name='includes')) + +class SymbolUserList(NamedTuple): + definitions: List[FileMatch] + users: List[FileMatch] + +class MoveSymbols(FileMatch): + """Handle missing symbols + - Move typedefs and defines when necessary + - Add missing #include lines when necessary + """ + regexp = RE_FILE_BEGIN + + def gen_patches(self) -> Iterator[Patch]: + if self.file.filename_matches('qom/object.h'): + self.debug("skipping object.h") + return + + index: Dict[RequiredIdentifier, SymbolUserList] = {} + definition_classes = [SimpleTypedefMatch, FullStructTypedefMatch, ConstantDefine, Include] + user_classes = [TypeCheckMacro, DeclareObjCheckers, DeclareInstanceChecker, DeclareClassCheckers, InterfaceCheckMacro] + + # first we scan for all symbol definitions and usage: + for dc in definition_classes: + defs = self.file.matches_of_type(dc) + for d in defs: + DBG("scanning %r", d) + for i in d.provided_identifiers(): + index.setdefault(i, SymbolUserList([], [])).definitions.append(d) + DBG("index: %r", list(index.keys())) + for uc in user_classes: + users = self.file.matches_of_type(uc) + for u in users: + for i in u.required_identifiers(): + index.setdefault(i, SymbolUserList([], [])).users.append(u) + + # validate all symbols: + for i,ul in index.items(): + if not ul.users: + # unused symbol + continue + + # symbol not defined + if len(ul.definitions) == 0: + if i.type == 'include': + includes, = self.file.matches_of_type(InitialIncludes) + #FIXME: don't do this if we're already inside qom/object.h + yield includes.append(f'#include {i.name}\n') + else: + u.warn("definition of %s %s not found in file", i.type, i.name) + continue + + # symbol defined twice: + if len(ul.definitions) > 1: + ul.definitions[1].warn("%s defined twice", i.name) + ul.definitions[0].warn("previously defined here") + continue + + # symbol defined. check if all users are after its definition: + assert len(ul.definitions) == 1 + definition = ul.definitions[0] + DBG("handling repositioning of %r", definition) + earliest = min(ul.users, key=lambda u: u.start()) + if earliest.start() > definition.start(): + DBG("%r is OK", definition) + continue + + DBG("%r needs to be moved", definition) + if isinstance(definition, SimpleTypedefMatch) \ + or isinstance(definition, ConstantDefine): + # simple typedef or define can be moved directly: + yield definition.make_removal_patch() + yield earliest.prepend(definition.group(0)) + elif isinstance(definition, FullStructTypedefMatch) \ + and definition.group('structname'): + # full struct typedef is more complex: we need to remove + # the typedef + yield from definition.move_typedef(earliest.start()) + else: + definition.warn("definition of %s %s needs to be moved earlier in the file", i.type, i.name) + earliest.warn("definition of %s %s is used here", i.type, i.name) + + +class EmptyPreprocessorConditional(FileMatch): + """Delete empty preprocessor conditionals""" + regexp = r'^[ \t]*#(if|ifdef)[ \t].*\n+[ \t]*#endif[ \t]*\n' + def gen_patches(self) -> Iterable[Patch]: + yield self.make_removal_patch() diff --git a/scripts/codeconverter/codeconverter/qom_type_info.py b/scripts/codeconverter/codeconverter/qom_type_info.py new file mode 100644 index 0000000000000000000000000000000000000000..255cb59923da78e60dd3c73277419fd3ab9f4a47 --- /dev/null +++ b/scripts/codeconverter/codeconverter/qom_type_info.py @@ -0,0 +1,969 @@ +# Copyright (C) 2020 Red Hat Inc. +# +# Authors: +# Eduardo Habkost +# +# This work is licensed under the terms of the GNU GPL, version 2. See +# the COPYING file in the top-level directory. +import re +from .regexps import * +from .patching import * +from .utils import * +from .qom_macros import * + +TI_FIELDS = [ 'name', 'parent', 'abstract', 'interfaces', + 'instance_size', 'instance_init', 'instance_post_init', 'instance_finalize', + 'class_size', 'class_init', 'class_base_init', 'class_data'] + +RE_TI_FIELD_NAME = OR(*TI_FIELDS) + +RE_TI_FIELD_INIT = S(r'[ \t]*', NAMED('comments', RE_COMMENTS), + r'\.', NAMED('field', RE_TI_FIELD_NAME), r'\s*=\s*', + NAMED('value', RE_EXPRESSION), r'[ \t]*,?[ \t]*\n') +RE_TI_FIELDS = M(RE_TI_FIELD_INIT) + +RE_TYPEINFO_START = S(r'^[ \t]*', M(r'(static|const)\s+', name='modifiers'), r'TypeInfo\s+', + NAMED('name', RE_IDENTIFIER), r'\s*=\s*{[ \t]*\n') + +ParsedArray = List[str] +ParsedInitializerValue = Union[str, ParsedArray] +class InitializerValue(NamedTuple): + raw: str + parsed: Optional[ParsedInitializerValue] + match: Optional[Match] + +class ArrayItem(FileMatch): + regexp = RE_ARRAY_ITEM + +class ArrayInitializer(FileMatch): + regexp = RE_ARRAY + + def parsed(self) -> ParsedArray: + #DBG('parse_array: %r', m.group(0)) + return [m.group('arrayitem') for m in self.group_finditer(ArrayItem, 'arrayitems')] + +class FieldInitializer(FileMatch): + regexp = RE_TI_FIELD_INIT + + @property + def raw(self) -> str: + return self.group('value') + + @property + def parsed(self) -> ParsedInitializerValue: + parsed: ParsedInitializerValue = self.raw + #DBG("parse_initializer_value: %r", s) + array = self.try_group_match(ArrayInitializer, 'value') + if array: + assert isinstance(array, ArrayInitializer) + return array.parsed() + return parsed + +TypeInfoInitializers = Dict[str, FieldInitializer] + +class TypeDefinition(FileMatch): + """ + Common base class for type definitions (TypeInfo variables or OBJECT_DEFINE* macros) + """ + @property + def instancetype(self) -> Optional[str]: + return self.group('instancetype') + + @property + def classtype(self) -> Optional[str]: + return self.group('classtype') + + @property + def uppercase(self) -> Optional[str]: + return self.group('uppercase') + + @property + def parent_uppercase(self) -> str: + return self.group('parent_uppercase') + + @property + def initializers(self) -> Optional[TypeInfoInitializers]: + if getattr(self, '_inititalizers', None): + self._initializers: TypeInfoInitializers + return self._initializers + fields = self.group('fields') + if fields is None: + return None + d = dict((fm.group('field'), fm) + for fm in self.group_finditer(FieldInitializer, 'fields')) + self._initializers = d # type: ignore + return self._initializers + + +class TypeInfoVar(TypeDefinition): + """TypeInfo variable declaration with initializer""" + regexp = S(NAMED('begin', RE_TYPEINFO_START), + M(NAMED('fields', RE_TI_FIELDS), + NAMED('endcomments', SP, RE_COMMENTS), + NAMED('end', r'};?\n'), + n='?', name='fullspec')) + + def is_static(self) -> bool: + return 'static' in self.group('modifiers') + + def is_const(self) -> bool: + return 'const' in self.group('modifiers') + + def is_full(self) -> bool: + return bool(self.group('fullspec')) + + def get_initializers(self) -> TypeInfoInitializers: + """Helper for code that needs to deal with missing initializer info""" + if self.initializers is None: + return {} + return self.initializers + + def get_raw_initializer_value(self, field: str, default: str = '') -> str: + initializers = self.get_initializers() + if field in initializers: + return initializers[field].raw + else: + return default + + @property + def typename(self) -> Optional[str]: + return self.get_raw_initializer_value('name') + + @property + def uppercase(self) -> Optional[str]: + typename = self.typename + if not typename: + return None + if not typename.startswith('TYPE_'): + return None + return typename[len('TYPE_'):] + + @property + def classtype(self) -> Optional[str]: + class_size = self.get_raw_initializer_value('class_size') + if not class_size: + return None + m = re.fullmatch(RE_SIZEOF, class_size) + if not m: + return None + return m.group('sizeoftype') + + @property + def instancetype(self) -> Optional[str]: + instance_size = self.get_raw_initializer_value('instance_size') + if not instance_size: + return None + m = re.fullmatch(RE_SIZEOF, instance_size) + if not m: + return None + return m.group('sizeoftype') + + + #def extract_identifiers(self) -> Optional[TypeIdentifiers]: + # """Try to extract identifiers from names being used""" + # DBG("extracting idenfiers from %s", self.name) + #uppercase = None + #if typename and re.fullmatch(RE_IDENTIFIER, typename) and typename.startswith("TYPE_"): + # uppercase = typename[len('TYPE_'):] + #lowercase = None + #funcs = set() + #prefixes = set() + #for field,suffix in [('instance_init', '_init'), + # ('instance_finalize', '_finalize'), + # ('class_init', '_class_init')]: + # if field not in values: + # continue + # func = values[field].raw + # funcs.add(func) + # if func.endswith(suffix): + # prefixes.add(func[:-len(suffix)]) + # else: + # self.warn("function name %s doesn't have expected %s suffix", + # func, suffix) + #if len(prefixes) == 1: + # lowercase = prefixes.pop() + #elif len(prefixes) > 1: + # self.warn("inconsistent function names: %s", ' '.join(funcs)) + + #.parent = TYPE_##PARENT_MODULE_OBJ_NAME, \ + #return TypeIdentifiers(typename=typename, + # uppercase=uppercase, lowercase=lowercase, + # instancetype=instancetype, classtype=classtype) + + def append_field(self, field: str, value: str) -> Patch: + """Generate patch appending a field initializer""" + content = f' .{field} = {value},\n' + fm = self.group_match('fields') + assert fm + return fm.append(content) + + def patch_field(self, field: str, replacement: str) -> Patch: + """Generate patch replacing a field initializer""" + initializers = self.initializers + assert initializers + value = initializers.get(field) + assert value + return value.make_patch(replacement) + + def remove_field(self, field: str) -> Iterable[Patch]: + initializers = self.initializers + assert initializers + if field in initializers: + yield self.patch_field(field, '') + + def remove_fields(self, *fields: str) -> Iterable[Patch]: + for f in fields: + yield from self.remove_field(f) + + def patch_field_value(self, field: str, replacement: str) -> Patch: + """Replace just the value of a field initializer""" + initializers = self.initializers + assert initializers + value = initializers.get(field) + assert value + vm = value.group_match('value') + assert vm + return vm.make_patch(replacement) + + +class RemoveRedundantClassSize(TypeInfoVar): + """Remove class_size when using OBJECT_DECLARE_SIMPLE_TYPE""" + def gen_patches(self) -> Iterable[Patch]: + initializers = self.initializers + if initializers is None: + return + if 'class_size' not in initializers: + return + + self.debug("Handling %s", self.name) + m = re.fullmatch(RE_SIZEOF, initializers['class_size'].raw) + if not m: + self.warn("%s class_size is not sizeof?", self.name) + return + classtype = m.group('sizeoftype') + if not classtype.endswith('Class'): + self.warn("%s class size type (%s) is not *Class?", self.name, classtype) + return + self.debug("classtype is %s", classtype) + instancetype = classtype[:-len('Class')] + self.debug("intanceypte is %s", instancetype) + self.debug("searching for simpletype declaration using %s as InstanceType", instancetype) + decl = self.allfiles.find_match(OldStyleObjectDeclareSimpleType, + instancetype, 'instancetype') + if not decl: + self.debug("No simpletype declaration found for %s", instancetype) + return + self.debug("Found simple type declaration") + decl.debug("declaration is here") + yield from self.remove_field('class_size') + +class RemoveDeclareSimpleTypeArg(OldStyleObjectDeclareSimpleType): + """Remove class_size when using OBJECT_DECLARE_SIMPLE_TYPE""" + def gen_patches(self) -> Iterable[Patch]: + c = (f'OBJECT_DECLARE_SIMPLE_TYPE({self.group("instancetype")}, {self.group("lowercase")},\n' + f' {self.group("uppercase")})\n') + yield self.make_patch(c) + +class UseDeclareTypeExtended(TypeInfoVar): + """Replace TypeInfo variable with OBJECT_DEFINE_TYPE_EXTENDED""" + def gen_patches(self) -> Iterable[Patch]: + # this will just ensure the caches for find_match() and matches_for_type() + # will be loaded in advance: + find_type_checkers(self.allfiles, 'xxxxxxxxxxxxxxxxx') + + if not self.is_static(): + self.info("Skipping non-static TypeInfo variable") + return + + type_info_macro = self.file.find_match(TypeInfoMacro, self.name) + if not type_info_macro: + self.warn("TYPE_INFO(%s) line not found", self.name) + return + + values = self.initializers + if values is None: + return + if 'name' not in values: + self.warn("name not set in TypeInfo variable %s", self.name) + return + + typename = values['name'].raw + + if 'parent' not in values: + self.warn("parent not set in TypeInfo variable %s", self.name) + return + parent_typename = values['parent'].raw + + instancetype = None + if 'instance_size' in values: + m = re.fullmatch(RE_SIZEOF, values['instance_size'].raw) + if m: + instancetype = m.group('sizeoftype') + else: + self.warn("can't extract instance type in TypeInfo variable %s", self.name) + self.warn("instance_size is set to: %r", values['instance_size'].raw) + return + + classtype = None + if 'class_size' in values: + m = re.fullmatch(RE_SIZEOF, values['class_size'].raw) + if m: + classtype = m.group('sizeoftype') + else: + self.warn("can't extract class type in TypeInfo variable %s", self.name) + self.warn("class_size is set to: %r", values['class_size'].raw) + return + + #for t in (typename, parent_typename): + # if not re.fullmatch(RE_IDENTIFIER, t): + # self.info("type name is not a macro/constant") + # if instancetype or classtype: + # self.warn("macro/constant type name is required for instance/class type") + # if not self.file.force: + # return + + # Now, the challenge is to find out the right MODULE_OBJ_NAME for the + # type and for the parent type + self.info("TypeInfo variable for %s is here", typename) + uppercase = find_typename_uppercase(self.allfiles, typename) + if not uppercase: + self.info("Can't find right uppercase name for %s", typename) + if instancetype or classtype: + self.warn("Can't find right uppercase name for %s", typename) + self.warn("This will make type validation difficult in the future") + return + + parent_uppercase = find_typename_uppercase(self.allfiles, parent_typename) + if not parent_uppercase: + self.info("Can't find right uppercase name for parent type (%s)", parent_typename) + if instancetype or classtype: + self.warn("Can't find right uppercase name for parent type (%s)", parent_typename) + self.warn("This will make type validation difficult in the future") + return + + ok = True + + #checkers: List[TypeCheckerDeclaration] = list(find_type_checkers(self.allfiles, uppercase)) + #for c in checkers: + # c.info("instance type checker declaration (%s) is here", c.group('uppercase')) + #if not checkers: + # self.info("No type checkers declared for %s", uppercase) + # if instancetype or classtype: + # self.warn("Can't find where type checkers for %s (%s) are declared. We will need them to validate sizes of %s", + # typename, uppercase, self.name) + + if not instancetype: + instancetype = 'void' + if not classtype: + classtype = 'void' + + #checker_instancetypes = set(c.instancetype for c in checkers + # if c.instancetype is not None) + #if len(checker_instancetypes) > 1: + # self.warn("ambiguous set of type checkers") + # for c in checkers: + # c.warn("instancetype is %s here", c.instancetype) + # ok = False + #elif len(checker_instancetypes) == 1: + # checker_instancetype = checker_instancetypes.pop() + # DBG("checker instance type: %r", checker_instancetype) + # if instancetype != checker_instancetype: + # self.warn("type at instance_size is %r. Should instance_size be set to sizeof(%s) ?", + # instancetype, checker_instancetype) + # ok = False + #else: + # if instancetype != 'void': + # self.warn("instance type checker for %s (%s) not found", typename, instancetype) + # ok = False + + #checker_classtypes = set(c.classtype for c in checkers + # if c.classtype is not None) + #if len(checker_classtypes) > 1: + # self.warn("ambiguous set of type checkers") + # for c in checkers: + # c.warn("classtype is %s here", c.classtype) + # ok = False + #elif len(checker_classtypes) == 1: + # checker_classtype = checker_classtypes.pop() + # DBG("checker class type: %r", checker_classtype) + # if classtype != checker_classtype: + # self.warn("type at class_size is %r. Should class_size be set to sizeof(%s) ?", + # classtype, checker_classtype) + # ok = False + #else: + # if classtype != 'void': + # self.warn("class type checker for %s (%s) not found", typename, classtype) + # ok = False + + #if not ok: + # for c in checkers: + # c.warn("Type checker declaration for %s (%s) is here", + # typename, type(c).__name__) + # return + + #if parent_decl is None: + # self.warn("Can't find where parent type %s is declared", parent_typename) + + #yield self.prepend(f'DECLARE_TYPE_NAME({uppercase}, {typename})\n') + #if not instancetype: + # yield self.prepend(f'DECLARE_INSTANCE_TYPE({uppercase}, void)\n') + #if not classtype: + # yield self.prepend(f'DECLARE_CLASS_TYPE({uppercase}, void)\n') + self.info("%s can be patched!", self.name) + replaced_fields = ['name', 'parent', 'instance_size', 'class_size'] + begin = self.group_match('begin') + newbegin = f'OBJECT_DEFINE_TYPE_EXTENDED({self.name},\n' + newbegin += f' {instancetype}, {classtype},\n' + newbegin += f' {uppercase}, {parent_uppercase}' + if set(values.keys()) - set(replaced_fields): + newbegin += ',\n' + yield begin.make_patch(newbegin) + yield from self.remove_fields(*replaced_fields) + end = self.group_match('end') + yield end.make_patch(')\n') + yield type_info_macro.make_removal_patch() + +class ObjectDefineTypeExtended(TypeDefinition): + """OBJECT_DEFINE_TYPE_EXTENDED usage""" + regexp = S(r'^[ \t]*OBJECT_DEFINE_TYPE_EXTENDED\s*\(\s*', + NAMED('name', RE_IDENTIFIER), r'\s*,\s*', + NAMED('instancetype', RE_IDENTIFIER), r'\s*,\s*', + NAMED('classtype', RE_IDENTIFIER), r'\s*,\s*', + NAMED('uppercase', RE_IDENTIFIER), r'\s*,\s*', + NAMED('parent_uppercase', RE_IDENTIFIER), + M(r',\s*\n', + NAMED('fields', RE_TI_FIELDS), + n='?'), + r'\s*\);?\n?') + +class ObjectDefineType(TypeDefinition): + """OBJECT_DEFINE_TYPE usage""" + regexp = S(r'^[ \t]*OBJECT_DEFINE_TYPE\s*\(\s*', + NAMED('lowercase', RE_IDENTIFIER), r'\s*,\s*', + NAMED('uppercase', RE_IDENTIFIER), r'\s*,\s*', + NAMED('parent_uppercase', RE_IDENTIFIER), + M(r',\s*\n', + NAMED('fields', RE_TI_FIELDS), + n='?'), + r'\s*\);?\n?') + +def find_type_definitions(files: FileList, uppercase: str) -> Iterable[TypeDefinition]: + types: List[Type[TypeDefinition]] = [TypeInfoVar, ObjectDefineType, ObjectDefineTypeExtended] + for t in types: + for m in files.matches_of_type(t): + m.debug("uppercase: %s", m.uppercase) + yield from (m for t in types + for m in files.matches_of_type(t) + if m.uppercase == uppercase) + +class AddDeclareVoidClassType(TypeDeclarationFixup): + """Will add DECLARE_CLASS_TYPE(..., void) if possible""" + def gen_patches_for_type(self, uppercase: str, + checkers: List[TypeDeclaration], + fields: Dict[str, Optional[str]]) -> Iterable[Patch]: + defs = list(find_type_definitions(self.allfiles, uppercase)) + if len(defs) > 1: + self.warn("multiple definitions for %s", uppercase) + for d in defs: + d.warn("definition found here") + return + elif len(defs) == 0: + self.warn("type definition for %s not found", uppercase) + return + d = defs[0] + if d.classtype is None: + d.info("definition for %s has classtype, skipping", uppercase) + return + class_type_checkers = [c for c in checkers + if c.classtype is not None] + if class_type_checkers: + for c in class_type_checkers: + c.warn("class type checker for %s is present here", uppercase) + return + + _,last_checker = max((m.start(), m) for m in checkers) + s = f'DECLARE_CLASS_TYPE({uppercase}, void)\n' + yield last_checker.append(s) + +class AddDeclareVoidInstanceType(FileMatch): + """Will add DECLARE_INSTANCE_TYPE(..., void) if possible""" + regexp = S(r'^[ \t]*#[ \t]*define', CPP_SPACE, + NAMED('name', r'TYPE_[a-zA-Z0-9_]+\b'), + CPP_SPACE, r'.*\n') + + def gen_patches(self) -> Iterable[Patch]: + assert self.name.startswith('TYPE_') + uppercase = self.name[len('TYPE_'):] + defs = list(find_type_definitions(self.allfiles, uppercase)) + if len(defs) > 1: + self.warn("multiple definitions for %s", uppercase) + for d in defs: + d.warn("definition found here") + return + elif len(defs) == 0: + self.warn("type definition for %s not found", uppercase) + return + d = defs[0] + instancetype = d.instancetype + if instancetype is not None and instancetype != 'void': + return + + instance_checkers = [c for c in find_type_checkers(self.allfiles, uppercase) + if c.instancetype] + if instance_checkers: + d.warn("instance type checker for %s already declared", uppercase) + for c in instance_checkers: + c.warn("instance checker for %s is here", uppercase) + return + + s = f'DECLARE_INSTANCE_TYPE({uppercase}, void)\n' + yield self.append(s) + +class AddObjectDeclareType(DeclareObjCheckers): + """Will add OBJECT_DECLARE_TYPE(...) if possible""" + def gen_patches(self) -> Iterable[Patch]: + uppercase = self.uppercase + typename = self.group('typename') + instancetype = self.group('instancetype') + classtype = self.group('classtype') + + if typename != f'TYPE_{uppercase}': + self.warn("type name mismatch: %s vs %s", typename, uppercase) + return + + typedefs = [(t,self.allfiles.find_matches(SimpleTypedefMatch, t)) + for t in (instancetype, classtype)] + for t,tds in typedefs: + if not tds: + self.warn("typedef %s not found", t) + return + for td in tds: + td_type = td.group('typedef_type') + if td_type != f'struct {t}': + self.warn("typedef mismatch: %s is defined as %s", t, td_type) + td.warn("typedef is here") + return + + # look for reuse of same struct type + other_instance_checkers = [c for c in find_type_checkers(self.allfiles, instancetype, 'instancetype') + if c.uppercase != uppercase] + if other_instance_checkers: + self.warn("typedef %s is being reused", instancetype) + for ic in other_instance_checkers: + ic.warn("%s is reused here", instancetype) + if not self.file.force: + return + + decl_types: List[Type[TypeDeclaration]] = [DeclareClassCheckers, DeclareObjCheckers] + class_decls = [m for t in decl_types + for m in self.allfiles.find_matches(t, uppercase, 'uppercase')] + + defs = list(find_type_definitions(self.allfiles, uppercase)) + if len(defs) > 1: + self.warn("multiple definitions for %s", uppercase) + for d in defs: + d.warn("definition found here") + if not self.file.force: + return + elif len(defs) == 0: + self.warn("type definition for %s not found", uppercase) + if not self.file.force: + return + else: + d = defs[0] + if d.instancetype != instancetype: + self.warn("mismatching instance type for %s (%s)", uppercase, instancetype) + d.warn("instance type declared here (%s)", d.instancetype) + if not self.file.force: + return + if d.classtype != classtype: + self.warn("mismatching class type for %s (%s)", uppercase, classtype) + d.warn("class type declared here (%s)", d.classtype) + if not self.file.force: + return + + assert self.file.original_content + for t,tds in typedefs: + assert tds + for td in tds: + if td.file is not self.file: + continue + + # delete typedefs that are truly redundant: + # 1) defined after DECLARE_OBJ_CHECKERS + if td.start() > self.start(): + yield td.make_removal_patch() + # 2) defined before DECLARE_OBJ_CHECKERS, but unused + elif not re.search(r'\b'+t+r'\b', self.file.original_content[td.end():self.start()]): + yield td.make_removal_patch() + + c = (f'OBJECT_DECLARE_TYPE({instancetype}, {classtype}, {uppercase})\n') + yield self.make_patch(c) + +class AddObjectDeclareSimpleType(DeclareInstanceChecker): + """Will add OBJECT_DECLARE_SIMPLE_TYPE(...) if possible""" + def gen_patches(self) -> Iterable[Patch]: + uppercase = self.uppercase + typename = self.group('typename') + instancetype = self.group('instancetype') + + if typename != f'TYPE_{uppercase}': + self.warn("type name mismatch: %s vs %s", typename, uppercase) + return + + typedefs = [(t,self.allfiles.find_matches(SimpleTypedefMatch, t)) + for t in (instancetype,)] + for t,tds in typedefs: + if not tds: + self.warn("typedef %s not found", t) + return + for td in tds: + td_type = td.group('typedef_type') + if td_type != f'struct {t}': + self.warn("typedef mismatch: %s is defined as %s", t, td_type) + td.warn("typedef is here") + return + + # look for reuse of same struct type + other_instance_checkers = [c for c in find_type_checkers(self.allfiles, instancetype, 'instancetype') + if c.uppercase != uppercase] + if other_instance_checkers: + self.warn("typedef %s is being reused", instancetype) + for ic in other_instance_checkers: + ic.warn("%s is reused here", instancetype) + if not self.file.force: + return + + decl_types: List[Type[TypeDeclaration]] = [DeclareClassCheckers, DeclareObjCheckers] + class_decls = [m for t in decl_types + for m in self.allfiles.find_matches(t, uppercase, 'uppercase')] + if class_decls: + self.warn("class type declared for %s", uppercase) + for cd in class_decls: + cd.warn("class declaration found here") + return + + defs = list(find_type_definitions(self.allfiles, uppercase)) + if len(defs) > 1: + self.warn("multiple definitions for %s", uppercase) + for d in defs: + d.warn("definition found here") + if not self.file.force: + return + elif len(defs) == 0: + self.warn("type definition for %s not found", uppercase) + if not self.file.force: + return + else: + d = defs[0] + if d.instancetype != instancetype: + self.warn("mismatching instance type for %s (%s)", uppercase, instancetype) + d.warn("instance type declared here (%s)", d.instancetype) + if not self.file.force: + return + if d.classtype: + self.warn("class type set for %s", uppercase) + d.warn("class type declared here") + if not self.file.force: + return + + assert self.file.original_content + for t,tds in typedefs: + assert tds + for td in tds: + if td.file is not self.file: + continue + + # delete typedefs that are truly redundant: + # 1) defined after DECLARE_OBJ_CHECKERS + if td.start() > self.start(): + yield td.make_removal_patch() + # 2) defined before DECLARE_OBJ_CHECKERS, but unused + elif not re.search(r'\b'+t+r'\b', self.file.original_content[td.end():self.start()]): + yield td.make_removal_patch() + + c = (f'OBJECT_DECLARE_SIMPLE_TYPE({instancetype}, {uppercase})\n') + yield self.make_patch(c) + + +class TypeInfoStringName(TypeInfoVar): + """Replace hardcoded type names with TYPE_ constant""" + def gen_patches(self) -> Iterable[Patch]: + values = self.initializers + if values is None: + return + if 'name' not in values: + self.warn("name not set in TypeInfo variable %s", self.name) + return + typename = values['name'].raw + if re.fullmatch(RE_IDENTIFIER, typename): + return + + self.warn("name %s is not an identifier", typename) + #all_defines = [m for m in self.allfiles.matches_of_type(ExpressionDefine)] + #self.debug("all_defines: %r", all_defines) + constants = [m for m in self.allfiles.matches_of_type(ExpressionDefine) + if m.group('value').strip() == typename.strip()] + if not constants: + self.warn("No macro for %s found", typename) + return + if len(constants) > 1: + self.warn("I don't know which macro to use: %r", constants) + return + yield self.patch_field_value('name', constants[0].name) + +class RedundantTypeSizes(TypeInfoVar): + """Remove redundant instance_size/class_size from TypeInfo vars""" + def gen_patches(self) -> Iterable[Patch]: + values = self.initializers + if values is None: + return + if 'name' not in values: + self.warn("name not set in TypeInfo variable %s", self.name) + return + typename = values['name'].raw + if 'parent' not in values: + self.warn("parent not set in TypeInfo variable %s", self.name) + return + parent_typename = values['parent'].raw + + if 'instance_size' not in values and 'class_size' not in values: + self.debug("no need to validate %s", self.name) + return + + instance_decls = find_type_checkers(self.allfiles, typename) + if instance_decls: + self.debug("won't touch TypeInfo var that has type checkers") + return + + parent = find_type_info(self.allfiles, parent_typename) + if not parent: + self.warn("Can't find TypeInfo for %s", parent_typename) + return + + if 'instance_size' in values and parent.get_raw_initializer_value('instance_size') != values['instance_size'].raw: + self.info("instance_size mismatch") + parent.info("parent type declared here") + return + + if 'class_size' in values and parent.get_raw_initializer_value('class_size') != values['class_size'].raw: + self.info("class_size mismatch") + parent.info("parent type declared here") + return + + self.debug("will patch variable %s", self.name) + + if 'instance_size' in values: + self.debug("deleting instance_size") + yield self.patch_field('instance_size', '') + + if 'class_size' in values: + self.debug("deleting class_size") + yield self.patch_field('class_size', '') + + +#class TypeInfoVarInitFuncs(TypeInfoVar): +# """TypeInfo variable +# Will create missing init functions +# """ +# def gen_patches(self) -> Iterable[Patch]: +# values = self.initializers +# if values is None: +# self.warn("type not parsed completely: %s", self.name) +# return +# +# macro = self.file.find_match(TypeInfoVar, self.name) +# if macro is None: +# self.warn("No TYPE_INFO macro for %s", self.name) +# return +# +# ids = self.extract_identifiers() +# if ids is None: +# return +# +# DBG("identifiers extracted: %r", ids) +# fields = set(values.keys()) +# if ids.lowercase: +# if 'instance_init' not in fields: +# yield self.prepend(('static void %s_init(Object *obj)\n' +# '{\n' +# '}\n\n') % (ids.lowercase)) +# yield self.append_field('instance_init', ids.lowercase+'_init') +# +# if 'instance_finalize' not in fields: +# yield self.prepend(('static void %s_finalize(Object *obj)\n' +# '{\n' +# '}\n\n') % (ids.lowercase)) +# yield self.append_field('instance_finalize', ids.lowercase+'_finalize') +# +# +# if 'class_init' not in fields: +# yield self.prepend(('static void %s_class_init(ObjectClass *oc, void *data)\n' +# '{\n' +# '}\n\n') % (ids.lowercase)) +# yield self.append_field('class_init', ids.lowercase+'_class_init') + +class TypeInitMacro(FileMatch): + """Use of type_init(...) macro""" + regexp = S(r'^[ \t]*type_init\s*\(\s*', NAMED('name', RE_IDENTIFIER), r'\s*\);?[ \t]*\n') + +class DeleteEmptyTypeInitFunc(TypeInitMacro): + """Delete empty function declared using type_init(...)""" + def gen_patches(self) -> Iterable[Patch]: + fn = self.file.find_match(StaticVoidFunction, self.name) + DBG("function for %s: %s", self.name, fn) + if fn and fn.body == '': + yield fn.make_patch('') + yield self.make_patch('') + +class StaticVoidFunction(FileMatch): + """simple static void function + (no replacement rules) + """ + #NOTE: just like RE_FULL_STRUCT, this doesn't parse any of the body contents + # of the function. Tt will just look for "}" in the beginning of a line + regexp = S(r'static\s+void\s+', NAMED('name', RE_IDENTIFIER), r'\s*\(\s*void\s*\)\n', + r'{\n', + NAMED('body', + # acceptable inside the function body: + # - lines starting with space or tab + # - empty lines + # - preprocessor directives + OR(r'[ \t][^\n]*\n', + r'#[^\n]*\n', + r'\n', + repeat='*')), + r'};?\n') + + @property + def body(self) -> str: + return self.group('body') + + def has_preprocessor_directive(self) -> bool: + return bool(re.search(r'^[ \t]*#', self.body, re.MULTILINE)) + +def find_containing_func(m: FileMatch) -> Optional['StaticVoidFunction']: + """Return function containing this match""" + for fn in m.file.matches_of_type(StaticVoidFunction): + if fn.contains(m): + return fn + return None + +class TypeRegisterStaticCall(FileMatch): + """type_register_static() call + Will be replaced by TYPE_INFO() macro + """ + regexp = S(r'^[ \t]*', NAMED('func_name', 'type_register_static'), + r'\s*\(&\s*', NAMED('name', RE_IDENTIFIER), r'\s*\);[ \t]*\n') + +class UseTypeInfo(TypeRegisterStaticCall): + """Replace type_register_static() call with TYPE_INFO declaration""" + def gen_patches(self) -> Iterable[Patch]: + fn = find_containing_func(self) + if fn: + DBG("%r is inside %r", self, fn) + type_init = self.file.find_match(TypeInitMacro, fn.name) + if type_init is None: + self.warn("can't find type_init(%s) line", fn.name) + if not self.file.force: + return + else: + self.warn("can't identify the function where type_register_static(&%s) is called", self.name) + if not self.file.force: + return + + #if fn.has_preprocessor_directive() and not self.file.force: + # self.warn("function %s has preprocessor directives, this requires --force", fn.name) + # return + + var = self.file.find_match(TypeInfoVar, self.name) + if var is None: + self.warn("can't find TypeInfo var declaration for %s", self.name) + return + + if not var.is_full(): + self.warn("variable declaration %s wasn't parsed fully", var.name) + if not self.file.force: + return + + if fn and fn.contains(var): + self.warn("TypeInfo %s variable is inside a function", self.name) + if not self.file.force: + return + + # delete type_register_static() call: + yield self.make_patch('') + # append TYPE_REGISTER(...) after variable declaration: + yield var.append(f'TYPE_INFO({self.name})\n') + +class TypeRegisterCall(FileMatch): + """type_register_static() call""" + regexp = S(r'^[ \t]*', NAMED('func_name', 'type_register'), + r'\s*\(&\s*', NAMED('name', RE_IDENTIFIER), r'\s*\);[ \t]*\n') + +class MakeTypeRegisterStatic(TypeRegisterCall): + """Make type_register() call static if variable is static const""" + def gen_patches(self): + var = self.file.find_match(TypeInfoVar, self.name) + if var is None: + self.warn("can't find TypeInfo var declaration for %s", self.name) + return + if var.is_static() and var.is_const(): + yield self.group_match('func_name').make_patch('type_register_static') + +class MakeTypeRegisterNotStatic(TypeRegisterStaticCall): + """Make type_register() call static if variable is static const""" + def gen_patches(self): + var = self.file.find_match(TypeInfoVar, self.name) + if var is None: + self.warn("can't find TypeInfo var declaration for %s", self.name) + return + if not var.is_static() or not var.is_const(): + yield self.group_match('func_name').make_patch('type_register') + +class TypeInfoMacro(FileMatch): + """TYPE_INFO macro usage""" + regexp = S(r'^[ \t]*TYPE_INFO\s*\(\s*', NAMED('name', RE_IDENTIFIER), r'\s*\)[ \t]*;?[ \t]*\n') + +def find_type_info(files: RegexpScanner, name: str) -> Optional[TypeInfoVar]: + ti = [ti for ti in files.matches_of_type(TypeInfoVar) + if ti.get_raw_initializer_value('name') == name] + DBG("type info vars: %r", ti) + if len(ti) > 1: + DBG("multiple TypeInfo vars found for %s", name) + return None + if len(ti) == 0: + DBG("no TypeInfo var found for %s", name) + return None + return ti[0] + +class CreateClassStruct(DeclareInstanceChecker): + """Replace DECLARE_INSTANCE_CHECKER with OBJECT_DECLARE_SIMPLE_TYPE""" + def gen_patches(self) -> Iterable[Patch]: + typename = self.group('typename') + DBG("looking for TypeInfo variable for %s", typename) + var = find_type_info(self.allfiles, typename) + if var is None: + self.warn("no TypeInfo var found for %s", typename) + return + assert var.initializers + if 'class_size' in var.initializers: + self.warn("class size already set for TypeInfo %s", var.name) + return + classtype = self.group('instancetype')+'Class' + return + yield + #TODO: need to find out what's the parent class type... + #yield var.append_field('class_size', f'sizeof({classtype})') + #c = (f'OBJECT_DECLARE_SIMPLE_TYPE({instancetype}, {lowercase},\n' + # f' MODULE_OBJ_NAME, ParentClassType)\n') + #yield self.make_patch(c) + +def type_infos(file: FileInfo) -> Iterable[TypeInfoVar]: + return file.matches_of_type(TypeInfoVar) + +def full_types(file: FileInfo) -> Iterable[TypeInfoVar]: + return [t for t in type_infos(file) if t.is_full()] + +def partial_types(file: FileInfo) -> Iterable[TypeInfoVar]: + return [t for t in type_infos(file) if not t.is_full()] diff --git a/scripts/codeconverter/codeconverter/regexps.py b/scripts/codeconverter/codeconverter/regexps.py new file mode 100644 index 0000000000000000000000000000000000000000..77993cc3b9759d1d35495ff4f212f0dd2fb44e4d --- /dev/null +++ b/scripts/codeconverter/codeconverter/regexps.py @@ -0,0 +1,118 @@ +# Copyright (C) 2020 Red Hat Inc. +# +# Authors: +# Eduardo Habkost +# +# This work is licensed under the terms of the GNU GPL, version 2. See +# the COPYING file in the top-level directory. +"""Helpers for creation of regular expressions""" +import re + +import logging +logger = logging.getLogger(__name__) +DBG = logger.debug +INFO = logger.info +WARN = logger.warning + +def S(*regexps) -> str: + """Just a shortcut to concatenate multiple regexps more easily""" + return ''.join(regexps) + +def P(*regexps, name=None, capture=False, repeat='') -> str: + """Just add parenthesis around regexp(s), with optional name or repeat suffix""" + s = S(*regexps) + if name: + return f'(?P<{name}>{s}){repeat}' + elif capture: + return f'({s}){repeat}' + else: + return f'(?:{s}){repeat}' + +def NAMED(name, *regexps) -> str: + """Make named group using ...) syntax + + >>> NAMED('mygroup', 'xyz', 'abc') + '(?Pxyzabc)' + """ + return P(*regexps, name=name) + +def OR(*regexps, **kwargs) -> str: + """Build (a|b|c) regexp""" + return P('|'.join(regexps), **kwargs) + +def M(*regexps, n='*', name=None) -> str: + """Add repetition qualifier to regexp(s) + + >>> M('a', 'b') + '(?:ab)*' + >>> M('a' , 'b', n='+') + '(?:ab)+' + >>> M('a' , 'b', n='{2,3}', name='name') + '(?P(?:ab){2,3})' + """ + r = P(*regexps, repeat=n) + if name: + r = NAMED(name, r) + return r + +# helper to make parenthesis optional around regexp +OPTIONAL_PARS = lambda R: OR(S(r'\(\s*', R, r'\s*\)'), R) +def test_optional_pars(): + r = OPTIONAL_PARS('abc')+'$' + assert re.match(r, 'abc') + assert re.match(r, '(abc)') + assert not re.match(r, '(abcd)') + assert not re.match(r, '(abc') + assert not re.match(r, 'abc)') + + +# this disables the MULTILINE flag, so it will match at the +# beginning of the file: +RE_FILE_BEGIN = r'(?-m:^)' + +# C primitives: + +SP = r'\s*' + +RE_COMMENT = r'//[^\n]*$|/\*([^*]|\*[^/])*\*/' +RE_COMMENTS = M(RE_COMMENT + SP) + +RE_IDENTIFIER = r'[a-zA-Z_][a-zA-Z0-9_]*(?![a-zA-Z0-9])' +RE_STRING = r'\"([^\"\\]|\\[a-z\"])*\"' +RE_NUMBER = r'[0-9]+|0x[0-9a-fA-F]+' + +# space or escaped newlines: +CPP_SPACE = OR(r'\s', r'\\\n', repeat='+') + +RE_PATH = '[a-zA-Z0-9/_.-]+' + +RE_INCLUDEPATH = OR(S(r'\"', RE_PATH, r'\"'), + S(r'<', RE_PATH, r'>')) + +RE_INCLUDE = S(r'^[ \t]*#[ \t]*include[ \t]+', NAMED('includepath', RE_INCLUDEPATH), r'[ \t]*\n') +RE_SIMPLEDEFINE = S(r'^[ \t]*#[ \t]*define[ \t]+', RE_IDENTIFIER, r'[ \t]*\n') + +RE_STRUCT_TYPE = S(r'struct\s+', RE_IDENTIFIER) +RE_TYPE = OR(RE_IDENTIFIER, RE_STRUCT_TYPE) + +RE_MACRO_CONCAT = M(S(OR(RE_IDENTIFIER, RE_STRING), SP), n='{2,}') + +RE_SIMPLE_VALUE = OR(RE_IDENTIFIER, RE_STRING, RE_NUMBER) + +RE_FUN_CALL = S(RE_IDENTIFIER, r'\s*\(\s*', RE_SIMPLE_VALUE, r'\s*\)') +RE_SIZEOF = S(r'sizeof\s*\(\s*', NAMED('sizeoftype', RE_TYPE), r'\s*\)') + +RE_ADDRESS = S(r'&\s*', RE_IDENTIFIER) + +RE_ARRAY_ITEM = S(r'{\s*', NAMED('arrayitem', M(RE_SIMPLE_VALUE, n='?')), r'\s*}\s*,?') +RE_ARRAY_CAST = S(r'\(\s*', RE_IDENTIFIER, r'\s*\[\s*\]\)') +RE_ARRAY_ITEMS = M(S(RE_ARRAY_ITEM, SP)) +RE_ARRAY = S(M(RE_ARRAY_CAST, n='?'), r'\s*{\s*', + NAMED('arrayitems', RE_ARRAY_ITEMS), + r'}') + +# NOTE: this covers a very small subset of valid expressions + +RE_EXPRESSION = OR(RE_SIZEOF, RE_FUN_CALL, RE_MACRO_CONCAT, RE_SIMPLE_VALUE, + RE_ARRAY, RE_ADDRESS) + diff --git a/scripts/codeconverter/codeconverter/test_patching.py b/scripts/codeconverter/codeconverter/test_patching.py new file mode 100644 index 0000000000000000000000000000000000000000..71dfbd47e154641ea34b44a5f3aa8459312d608f --- /dev/null +++ b/scripts/codeconverter/codeconverter/test_patching.py @@ -0,0 +1,104 @@ +# Copyright (C) 2020 Red Hat Inc. +# +# Authors: +# Eduardo Habkost +# +# This work is licensed under the terms of the GNU GPL, version 2. See +# the COPYING file in the top-level directory. +from tempfile import NamedTemporaryFile +from .patching import FileInfo, FileMatch, Patch, FileList +from .regexps import * + +class BasicPattern(FileMatch): + regexp = '[abc]{3}' + + @property + def name(self): + return self.group(0) + + def replacement(self) -> str: + # replace match with the middle character repeated 5 times + return self.group(0)[1].upper()*5 + +def test_pattern_patching(): + of = NamedTemporaryFile('wt') + of.writelines(['one line\n', + 'this pattern will be patched: defbbahij\n', + 'third line\n', + 'another pattern: jihaabfed']) + of.flush() + + files = FileList() + f = FileInfo(files, of.name) + f.load() + matches = f.matches_of_type(BasicPattern) + assert len(matches) == 2 + p2 = matches[1] + + # manually add patch, to see if .append() works: + f.patches.append(p2.append('XXX')) + + # apply all patches: + f.gen_patches(matches) + patched = f.get_patched_content() + assert patched == ('one line\n'+ + 'this pattern will be patched: defBBBBBhij\n'+ + 'third line\n'+ + 'another pattern: jihAAAAAXXXfed') + +class Function(FileMatch): + regexp = S(r'BEGIN\s+', NAMED('name', RE_IDENTIFIER), r'\n', + r'(.*\n)*?END\n') + +class Statement(FileMatch): + regexp = S(r'^\s*', NAMED('name', RE_IDENTIFIER), r'\(\)\n') + +def test_container_match(): + of = NamedTemporaryFile('wt') + of.writelines(['statement1()\n', + 'statement2()\n', + 'BEGIN function1\n', + ' statement3()\n', + ' statement4()\n', + 'END\n', + 'BEGIN function2\n', + ' statement5()\n', + ' statement6()\n', + 'END\n', + 'statement7()\n']) + of.flush() + + files = FileList() + f = FileInfo(files, of.name) + f.load() + assert len(f.matches_of_type(Function)) == 2 + print(' '.join(m.name for m in f.matches_of_type(Statement))) + assert len(f.matches_of_type(Statement)) == 7 + + f1 = f.find_match(Function, 'function1') + f2 = f.find_match(Function, 'function2') + st1 = f.find_match(Statement, 'statement1') + st2 = f.find_match(Statement, 'statement2') + st3 = f.find_match(Statement, 'statement3') + st4 = f.find_match(Statement, 'statement4') + st5 = f.find_match(Statement, 'statement5') + st6 = f.find_match(Statement, 'statement6') + st7 = f.find_match(Statement, 'statement7') + + assert not f1.contains(st1) + assert not f1.contains(st2) + assert not f1.contains(st2) + assert f1.contains(st3) + assert f1.contains(st4) + assert not f1.contains(st5) + assert not f1.contains(st6) + assert not f1.contains(st7) + + assert not f2.contains(st1) + assert not f2.contains(st2) + assert not f2.contains(st2) + assert not f2.contains(st3) + assert not f2.contains(st4) + assert f2.contains(st5) + assert f2.contains(st6) + assert not f2.contains(st7) diff --git a/scripts/codeconverter/codeconverter/test_regexps.py b/scripts/codeconverter/codeconverter/test_regexps.py new file mode 100644 index 0000000000000000000000000000000000000000..a445634d88ac90ad45a65790988efee94bbfabc4 --- /dev/null +++ b/scripts/codeconverter/codeconverter/test_regexps.py @@ -0,0 +1,282 @@ +# Copyright (C) 2020 Red Hat Inc. +# +# Authors: +# Eduardo Habkost +# +# This work is licensed under the terms of the GNU GPL, version 2. See +# the COPYING file in the top-level directory. +from .regexps import * +from .qom_macros import * +from .qom_type_info import * + +def test_res() -> None: + def fullmatch(regexp, s): + return re.fullmatch(regexp, s, re.MULTILINE) + + assert fullmatch(RE_IDENTIFIER, 'sizeof') + assert fullmatch(RE_IDENTIFIER, 'X86CPU') + assert fullmatch(RE_FUN_CALL, 'sizeof(X86CPU)') + assert fullmatch(RE_IDENTIFIER, 'X86_CPU_TYPE_NAME') + assert fullmatch(RE_SIMPLE_VALUE, '"base"') + print(RE_FUN_CALL) + assert fullmatch(RE_FUN_CALL, 'X86_CPU_TYPE_NAME("base")') + print(RE_TI_FIELD_INIT) + assert fullmatch(RE_TI_FIELD_INIT, '.name = X86_CPU_TYPE_NAME("base"),\n') + + + assert fullmatch(RE_MACRO_CONCAT, 'TYPE_ASPEED_GPIO "-ast2600"') + assert fullmatch(RE_EXPRESSION, 'TYPE_ASPEED_GPIO "-ast2600"') + + print(RE_MACRO_DEFINE) + assert re.search(RE_MACRO_DEFINE, r''' + #define OFFSET_CHECK(c) \ + do { \ + if (!(c)) { \ + goto bad_offset; \ + } \ + } while (0) + ''', re.MULTILINE) + + print(RE_CHECK_MACRO) + print(CPP_SPACE) + assert not re.match(RE_CHECK_MACRO, r''' + #define OFFSET_CHECK(c) \ + do { \ + if (!(c)) { \ + goto bad_offset; \ + } \ + } while (0)''', re.MULTILINE) + + print(RE_CHECK_MACRO) + assert fullmatch(RE_CHECK_MACRO, r'''#define PCI_DEVICE(obj) \ + OBJECT_CHECK(PCIDevice, (obj), TYPE_PCI_DEVICE) +''') + assert fullmatch(RE_CHECK_MACRO, r'''#define COLLIE_MACHINE(obj) \ + OBJECT_CHECK(CollieMachineState, obj, TYPE_COLLIE_MACHINE) +''') + + print(RE_TYPEINFO_START) + assert re.search(RE_TYPEINFO_START, r''' + cc->open = qmp_chardev_open_file; +} + +static const TypeInfo char_file_type_info = { + .name = TYPE_CHARDEV_FILE, +#ifdef _WIN32 + .parent = TYPE_CHARDEV_WIN, +''', re.MULTILINE) + assert re.search(RE_TYPEINFO_START, r''' + TypeInfo ti = { + .name = armsse_variants[i].name, + .parent = TYPE_ARMSSE, + .class_init = armsse_class_init, + .class_data = (void *)&armsse_variants[i], + };''', re.MULTILINE) + + print(RE_ARRAY_ITEM) + assert fullmatch(RE_ARRAY_ITEM, '{ TYPE_HOTPLUG_HANDLER },') + assert fullmatch(RE_ARRAY_ITEM, '{ TYPE_ACPI_DEVICE_IF },') + assert fullmatch(RE_ARRAY_ITEM, '{ }') + assert fullmatch(RE_ARRAY_CAST, '(InterfaceInfo[])') + assert fullmatch(RE_ARRAY, '''(InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { TYPE_ACPI_DEVICE_IF }, + { } + }''') + print(RE_COMMENT) + assert fullmatch(RE_COMMENT, r'''/* multi-line + * comment + */''') + + print(RE_TI_FIELDS) + assert fullmatch(RE_TI_FIELDS, + r'''/* could be TYPE_SYS_BUS_DEVICE (or LPC etc) */ + .parent = TYPE_DEVICE, +''') + assert fullmatch(RE_TI_FIELDS, r'''.name = TYPE_TPM_CRB, + /* could be TYPE_SYS_BUS_DEVICE (or LPC etc) */ + .parent = TYPE_DEVICE, + .instance_size = sizeof(CRBState), + .class_init = tpm_crb_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_TPM_IF }, + { } + } +''') + assert fullmatch(RE_TI_FIELDS + SP + RE_COMMENTS, + r'''.name = TYPE_PALM_MISC_GPIO, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(PalmMiscGPIOState), + .instance_init = palm_misc_gpio_init, + /* + * No class init required: device has no internal state so does not + * need to set up reset or vmstate, and has no realize method. + */''') + + print(TypeInfoVar.regexp) + test_empty = 'static const TypeInfo x86_base_cpu_type_info = {\n'+\ + '};\n'; + assert fullmatch(TypeInfoVar.regexp, test_empty) + + test_simple = r''' + static const TypeInfo x86_base_cpu_type_info = { + .name = X86_CPU_TYPE_NAME("base"), + .parent = TYPE_X86_CPU, + .class_init = x86_cpu_base_class_init, + }; + ''' + assert re.search(TypeInfoVar.regexp, test_simple, re.MULTILINE) + + test_interfaces = r''' + static const TypeInfo acpi_ged_info = { + .name = TYPE_ACPI_GED, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AcpiGedState), + .instance_init = acpi_ged_initfn, + .class_init = acpi_ged_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { TYPE_ACPI_DEVICE_IF }, + { } + } + }; + ''' + assert re.search(TypeInfoVar.regexp, test_interfaces, re.MULTILINE) + + test_comments = r''' + static const TypeInfo palm_misc_gpio_info = { + .name = TYPE_PALM_MISC_GPIO, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(PalmMiscGPIOState), + .instance_init = palm_misc_gpio_init, + /* + * No class init required: device has no internal state so does not + * need to set up reset or vmstate, and has no realize method. + */ + }; + ''' + assert re.search(TypeInfoVar.regexp, test_comments, re.MULTILINE) + + test_comments = r''' + static const TypeInfo tpm_crb_info = { + .name = TYPE_TPM_CRB, + /* could be TYPE_SYS_BUS_DEVICE (or LPC etc) */ + .parent = TYPE_DEVICE, + .instance_size = sizeof(CRBState), + .class_init = tpm_crb_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_TPM_IF }, + { } + } + }; + ''' + assert re.search(TypeInfoVar.regexp, test_comments, re.MULTILINE) + +def test_struct_re(): + print('---') + print(RE_STRUCT_TYPEDEF) + assert re.search(RE_STRUCT_TYPEDEF, r''' +typedef struct TCGState { + AccelState parent_obj; + + bool mttcg_enabled; + unsigned long tb_size; +} TCGState; +''', re.MULTILINE) + + assert re.search(RE_STRUCT_TYPEDEF, r''' +typedef struct { + ISADevice parent_obj; + + QEMUSoundCard card; + uint32_t freq; + uint32_t port; + int ticking[2]; + int enabled; + int active; + int bufpos; +#ifdef DEBUG + int64_t exp[2]; +#endif + int16_t *mixbuf; + uint64_t dexp[2]; + SWVoiceOut *voice; + int left, pos, samples; + QEMUAudioTimeStamp ats; + FM_OPL *opl; + PortioList port_list; +} AdlibState; +''', re.MULTILINE) + + false_positive = r''' +typedef struct dma_pagetable_entry { + int32_t frame; + int32_t owner; +} A B C D E; +struct foo { + int x; +} some_variable; +''' + assert not re.search(RE_STRUCT_TYPEDEF, false_positive, re.MULTILINE) + +def test_initial_includes(): + print(InitialIncludes.regexp) + c = ''' +#ifndef HW_FLASH_H +#define HW_FLASH_H + +/* NOR flash devices */ + +#include "qom/object.h" +#include "exec/hwaddr.h" + +/* pflash_cfi01.c */ +''' + print(repr(list(m.groupdict() for m in InitialIncludes.finditer(c)))) + m = InitialIncludes.domatch(c) + assert m + print(repr(m.group(0))) + assert m.group(0).endswith('#include "exec/hwaddr.h"\n') + + c = '''#ifndef QEMU_VIRTIO_9P_H +#define QEMU_VIRTIO_9P_H + +#include "standard-headers/linux/virtio_9p.h" +#include "hw/virtio/virtio.h" +#include "9p.h" + + +''' + print(repr(list(m.groupdict() for m in InitialIncludes.finditer(c)))) + m = InitialIncludes.domatch(c) + assert m + print(repr(m.group(0))) + assert m.group(0).endswith('#include "9p.h"\n') + + c = '''#include "qom/object.h" +/* + * QEMU ES1370 emulation +... + */ + +/* #define DEBUG_ES1370 */ +/* #define VERBOSE_ES1370 */ +#define SILENT_ES1370 + +#include "qemu/osdep.h" +#include "hw/audio/soundhw.h" +#include "audio/audio.h" +#include "hw/pci/pci.h" +#include "migration/vmstate.h" +#include "qemu/module.h" +#include "sysemu/dma.h" + +/* Missing stuff: + SCTRL_P[12](END|ST)INC +''' + print(repr(list(m.groupdict() for m in InitialIncludes.finditer(c)))) + m = InitialIncludes.domatch(c) + assert m + print(repr(m.group(0))) + assert m.group(0).endswith('#include "sysemu/dma.h"\n') + diff --git a/scripts/codeconverter/codeconverter/utils.py b/scripts/codeconverter/codeconverter/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..760ab7eecd21e7e7f996d74a60bc2ee5f993c62d --- /dev/null +++ b/scripts/codeconverter/codeconverter/utils.py @@ -0,0 +1,72 @@ +# Copyright (C) 2020 Red Hat Inc. +# +# Authors: +# Eduardo Habkost +# +# This work is licensed under the terms of the GNU GPL, version 2. See +# the COPYING file in the top-level directory. +from typing import * + +import logging +logger = logging.getLogger(__name__) +DBG = logger.debug +INFO = logger.info +WARN = logger.warning + +T = TypeVar('T') +def opt_compare(a: T, b: T) -> bool: + """Compare two values, ignoring mismatches if one of them is None""" + return (a is None) or (b is None) or (a == b) + +def merge(a: T, b: T) -> T: + """Merge two values if they matched using opt_compare()""" + assert opt_compare(a, b) + if a is None: + return b + else: + return a + +def test_comp_merge(): + assert opt_compare(None, 1) == True + assert opt_compare(2, None) == True + assert opt_compare(1, 1) == True + assert opt_compare(1, 2) == False + + assert merge(None, None) is None + assert merge(None, 10) == 10 + assert merge(10, None) == 10 + assert merge(10, 10) == 10 + + +LineNumber = NewType('LineNumber', int) +ColumnNumber = NewType('ColumnNumber', int) +class LineAndColumn(NamedTuple): + line: int + col: int + + def __str__(self): + return '%d:%d' % (self.line, self.col) + +def line_col(s, position: int) -> LineAndColumn: + """Return line and column for a char position in string + + Character position starts in 0, but lines and columns start in 1. + """ + before = s[:position] + lines = before.split('\n') + line = len(lines) + col = len(lines[-1]) + 1 + return LineAndColumn(line, col) + +def test_line_col(): + assert line_col('abc\ndefg\nhijkl', 0) == (1, 1) + assert line_col('abc\ndefg\nhijkl', 2) == (1, 3) + assert line_col('abc\ndefg\nhijkl', 3) == (1, 4) + assert line_col('abc\ndefg\nhijkl', 4) == (2, 1) + assert line_col('abc\ndefg\nhijkl', 10) == (3, 2) + +def not_optional(arg: Optional[T]) -> T: + assert arg is not None + return arg + +__all__ = ['not_optional', 'opt_compare', 'merge', 'line_col', 'LineAndColumn'] \ No newline at end of file diff --git a/scripts/codeconverter/converter.py b/scripts/codeconverter/converter.py new file mode 100755 index 0000000000000000000000000000000000000000..75cb515d935042cc02b90021de677e4dc2d633cb --- /dev/null +++ b/scripts/codeconverter/converter.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 +# QEMU library +# +# Copyright (C) 2020 Red Hat Inc. +# +# Authors: +# Eduardo Habkost +# +# This work is licensed under the terms of the GNU GPL, version 2. See +# the COPYING file in the top-level directory. +# +import sys +import argparse +import os +import os.path +import re +from typing import * + +from codeconverter.patching import FileInfo, match_class_dict, FileList +import codeconverter.qom_macros +from codeconverter.qom_type_info import TI_FIELDS, type_infos, TypeInfoVar + +import logging +logger = logging.getLogger(__name__) +DBG = logger.debug +INFO = logger.info +WARN = logger.warning + +def process_all_files(parser: argparse.ArgumentParser, args: argparse.Namespace) -> None: + DBG("filenames: %r", args.filenames) + + files = FileList() + files.extend(FileInfo(files, fn, args.force) for fn in args.filenames) + for f in files: + DBG('opening %s', f.filename) + f.load() + + if args.table: + fields = ['filename', 'variable_name'] + TI_FIELDS + print('\t'.join(fields)) + for f in files: + for t in f.matches_of_type(TypeInfoVar): + assert isinstance(t, TypeInfoVar) + values = [f.filename, t.name] + \ + [t.get_raw_initializer_value(f) + for f in TI_FIELDS] + DBG('values: %r', values) + assert all('\t' not in v for v in values) + values = [v.replace('\n', ' ').replace('"', '') for v in values] + print('\t'.join(values)) + return + + match_classes = match_class_dict() + if not args.patterns: + parser.error("--pattern is required") + + classes = [p for arg in args.patterns + for p in re.split(r'[\s,]', arg) + if p.strip()] + for c in classes: + if c not in match_classes \ + or not match_classes[c].regexp: + print("Invalid pattern name: %s" % (c), file=sys.stderr) + print("Valid patterns:", file=sys.stderr) + print(PATTERN_HELP, file=sys.stderr) + sys.exit(1) + + DBG("classes: %r", classes) + files.patch_content(max_passes=args.passes, class_names=classes) + + for f in files: + #alltypes.extend(f.type_infos) + #full_types.extend(f.full_types()) + + if not args.dry_run: + if args.inplace: + f.patch_inplace() + if args.diff: + f.show_diff() + if not args.diff and not args.inplace: + f.write_to_file(sys.stdout) + sys.stdout.flush() + + +PATTERN_HELP = ('\n'.join(" %s: %s" % (n, str(c.__doc__).strip()) + for (n,c) in sorted(match_class_dict().items()) + if c.has_replacement_rule())) + +def main() -> None: + p = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter) + p.add_argument('filenames', nargs='+') + p.add_argument('--passes', type=int, default=1, + help="Number of passes (0 means unlimited)") + p.add_argument('--pattern', required=True, action='append', + default=[], dest='patterns', + help="Pattern to scan for") + p.add_argument('--inplace', '-i', action='store_true', + help="Patch file in place") + p.add_argument('--dry-run', action='store_true', + help="Don't patch files or print patching results") + p.add_argument('--force', '-f', action='store_true', + help="Perform changes even if not completely safe") + p.add_argument('--diff', action='store_true', + help="Print diff output on stdout") + p.add_argument('--debug', '-d', action='store_true', + help="Enable debugging") + p.add_argument('--verbose', '-v', action='store_true', + help="Verbose logging on stderr") + p.add_argument('--table', action='store_true', + help="Print CSV table of type information") + p.add_argument_group("Valid pattern names", + PATTERN_HELP) + args = p.parse_args() + + loglevel = (logging.DEBUG if args.debug + else logging.INFO if args.verbose + else logging.WARN) + logging.basicConfig(format='%(levelname)s: %(message)s', level=loglevel) + DBG("args: %r", args) + process_all_files(p, args) + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/scripts/coverity-scan/coverity-scan.docker b/scripts/coverity-scan/coverity-scan.docker index a4f64d12834b125303c531c87f7b67c5edacaa0b..501ac6723323e5bafcd09189fb141040bce0cefa 100644 --- a/scripts/coverity-scan/coverity-scan.docker +++ b/scripts/coverity-scan/coverity-scan.docker @@ -19,7 +19,6 @@ FROM fedora:30 ENV PACKAGES \ alsa-lib-devel \ bc \ - bison \ brlapi-devel \ bzip2 \ bzip2-devel \ @@ -30,7 +29,6 @@ ENV PACKAGES \ dbus-daemon \ device-mapper-multipath-devel \ findutils \ - flex \ gcc \ gcc-c++ \ gettext \ @@ -112,7 +110,6 @@ ENV PACKAGES \ systemd-devel \ systemtap-sdt-devel \ tar \ - texinfo \ usbredir-devel \ virglrenderer-devel \ vte291-devel \ @@ -127,5 +124,6 @@ RUN dnf install -y $PACKAGES RUN rpm -q $PACKAGES | sort > /packages.txt ENV PATH $PATH:/usr/libexec/python3-sphinx/ ENV COVERITY_TOOL_BASE=/coverity-tools +COPY coverity_tool.tgz coverity_tool.tgz +RUN mkdir -p /coverity-tools/coverity_tool && cd /coverity-tools/coverity_tool && tar xf /coverity_tool.tgz COPY run-coverity-scan run-coverity-scan -RUN --mount=type=secret,id=coverity.token,required ./run-coverity-scan --update-tools-only --tokenfile /run/secrets/coverity.token diff --git a/scripts/coverity-scan/run-coverity-scan b/scripts/coverity-scan/run-coverity-scan index 2e067ef5cfca6928517882f495bf6c2136dfd68f..6eefb4b558d4fa7b148e530ec1b8259ff6f1c892 100755 --- a/scripts/coverity-scan/run-coverity-scan +++ b/scripts/coverity-scan/run-coverity-scan @@ -29,8 +29,11 @@ # Command line options: # --dry-run : run the tools, but don't actually do the upload -# --docker : create and work inside a docker container +# --docker : create and work inside a container +# --docker-engine : specify the container engine to use (docker/podman/auto); +# implies --docker # --update-tools-only : update the cached copy of the tools, but don't run them +# --no-update-tools : do not update the cached copy of the tools # --tokenfile : file to read Coverity token from # --version ver : specify version being analyzed (default: ask git) # --description desc : specify description of this version (default: ask git) @@ -41,9 +44,10 @@ # is intended mainly for internal use by the Docker support # # User-specifiable environment variables: -# COVERITY_TOKEN -- Coverity token +# COVERITY_TOKEN -- Coverity token (default: looks at your +# coverity.token config) # COVERITY_EMAIL -- the email address to use for uploads (default: -# looks at your git user.email config) +# looks at your git coverity.email or user.email config) # COVERITY_BUILD_CMD -- make command (default: 'make -jN' where N is # number of CPUs as determined by 'nproc') # COVERITY_TOOL_BASE -- set to directory to put coverity tools @@ -58,11 +62,11 @@ check_upload_permissions() { # with status 1 if the check failed (usually a bad token); # will exit the script with status 0 if the check indicated that we # can't upload yet (ie we are at quota) - # Assumes that PROJTOKEN, PROJNAME and DRYRUN have been initialized. + # Assumes that COVERITY_TOKEN, PROJNAME and DRYRUN have been initialized. echo "Checking upload permissions..." - if ! up_perm="$(wget https://scan.coverity.com/api/upload_permitted --post-data "token=$PROJTOKEN&project=$PROJNAME" -q -O -)"; then + if ! up_perm="$(wget https://scan.coverity.com/api/upload_permitted --post-data "token=$COVERITY_TOKEN&project=$PROJNAME" -q -O -)"; then echo "Coverity Scan API access denied: bad token?" exit 1 fi @@ -91,43 +95,62 @@ check_upload_permissions() { } +build_docker_image() { + # build docker container including the coverity-scan tools + echo "Building docker container..." + # TODO: This re-unpacks the tools every time, rather than caching + # and reusing the image produced by the COPY of the .tgz file. + # Not sure why. + tests/docker/docker.py --engine ${DOCKER_ENGINE} build \ + -t coverity-scanner -f scripts/coverity-scan/coverity-scan.docker \ + --extra-files scripts/coverity-scan/run-coverity-scan \ + "$COVERITY_TOOL_BASE"/coverity_tool.tgz +} + update_coverity_tools () { # Check for whether we need to download the Coverity tools # (either because we don't have a copy, or because it's out of date) - # Assumes that COVERITY_TOOL_BASE, PROJTOKEN and PROJNAME are set. + # Assumes that COVERITY_TOOL_BASE, COVERITY_TOKEN and PROJNAME are set. mkdir -p "$COVERITY_TOOL_BASE" cd "$COVERITY_TOOL_BASE" echo "Checking for new version of coverity build tools..." - wget https://scan.coverity.com/download/linux64 --post-data "token=$PROJTOKEN&project=$PROJNAME&md5=1" -O coverity_tool.md5.new + wget https://scan.coverity.com/download/linux64 --post-data "token=$COVERITY_TOKEN&project=$PROJNAME&md5=1" -O coverity_tool.md5.new if ! cmp -s coverity_tool.md5 coverity_tool.md5.new; then # out of date md5 or no md5: download new build tool # blow away the old build tool echo "Downloading coverity build tools..." rm -rf coverity_tool coverity_tool.tgz - wget https://scan.coverity.com/download/linux64 --post-data "token=$PROJTOKEN&project=$PROJNAME" -O coverity_tool.tgz + wget https://scan.coverity.com/download/linux64 --post-data "token=$COVERITY_TOKEN&project=$PROJNAME" -O coverity_tool.tgz if ! (cat coverity_tool.md5.new; echo " coverity_tool.tgz") | md5sum -c --status; then echo "Downloaded tarball didn't match md5sum!" exit 1 fi - # extract the new one, keeping it corralled in a 'coverity_tool' directory - echo "Unpacking coverity build tools..." - mkdir -p coverity_tool - cd coverity_tool - tar xf ../coverity_tool.tgz - cd .. - mv coverity_tool.md5.new coverity_tool.md5 - fi + if [ "$DOCKER" != yes ]; then + # extract the new one, keeping it corralled in a 'coverity_tool' directory + echo "Unpacking coverity build tools..." + mkdir -p coverity_tool + cd coverity_tool + tar xf ../coverity_tool.tgz + cd .. + mv coverity_tool.md5.new coverity_tool.md5 + fi + fi rm -f coverity_tool.md5.new + cd "$SRCDIR" + + if [ "$DOCKER" = yes ]; then + build_docker_image + fi } # Check user-provided environment variables and arguments DRYRUN=no -UPDATE_ONLY=no +UPDATE=yes DOCKER=no while [ "$#" -ge 1 ]; do @@ -136,9 +159,13 @@ while [ "$#" -ge 1 ]; do shift DRYRUN=yes ;; + --no-update-tools) + shift + UPDATE=no + ;; --update-tools-only) shift - UPDATE_ONLY=yes + UPDATE=only ;; --version) shift @@ -196,6 +223,17 @@ while [ "$#" -ge 1 ]; do ;; --docker) DOCKER=yes + DOCKER_ENGINE=auto + shift + ;; + --docker-engine) + shift + if [ $# -eq 0 ]; then + echo "--docker-engine needs an argument" + exit 1 + fi + DOCKER=yes + DOCKER_ENGINE="$1" shift ;; *) @@ -205,6 +243,9 @@ while [ "$#" -ge 1 ]; do esac done +if [ -z "$COVERITY_TOKEN" ]; then + COVERITY_TOKEN="$(git config coverity.token)" +fi if [ -z "$COVERITY_TOKEN" ]; then echo "COVERITY_TOKEN environment variable not set" exit 1 @@ -225,19 +266,19 @@ if [ -z "$SRCDIR" ]; then SRCDIR="$PWD" fi -PROJTOKEN="$COVERITY_TOKEN" PROJNAME=QEMU TARBALL=cov-int.tar.xz -if [ "$UPDATE_ONLY" = yes ] && [ "$DOCKER" = yes ]; then - echo "Combining --docker and --update-only is not supported" - exit 1 -fi - -if [ "$UPDATE_ONLY" = yes ]; then +if [ "$UPDATE" = only ]; then # Just do the tools update; we don't need to check whether # we are in a source tree or have upload rights for this, # so do it before some of the command line and source tree checks. + + if [ "$DOCKER" = yes ] && [ ! -z "$SRCTARBALL" ]; then + echo --update-tools-only --docker is incompatible with --src-tarball. + exit 1 + fi + update_coverity_tools exit 0 fi @@ -268,18 +309,27 @@ if [ -z "$DESCRIPTION" ]; then DESCRIPTION="$(git rev-parse HEAD)" fi +if [ -z "$COVERITY_EMAIL" ]; then + COVERITY_EMAIL="$(git config coverity.email)" +fi if [ -z "$COVERITY_EMAIL" ]; then COVERITY_EMAIL="$(git config user.email)" fi +# Otherwise, continue with the full build and upload process. + +check_upload_permissions + +if [ "$UPDATE" != no ]; then + update_coverity_tools +fi + # Run ourselves inside docker if that's what the user wants if [ "$DOCKER" = yes ]; then - # build docker container including the coverity-scan tools # Put the Coverity token into a temporary file that only # we have read access to, and then pass it to docker build - # using --secret. This requires at least Docker 18.09. - # Mostly what we are trying to do here is ensure we don't leak - # the token into the Docker image. + # using a volume. A volume is enough for the token not to + # leak into the Docker image. umask 077 SECRETDIR=$(mktemp -d) if [ -z "$SECRETDIR" ]; then @@ -290,38 +340,27 @@ if [ "$DOCKER" = yes ]; then echo "Created temporary directory $SECRETDIR" SECRET="$SECRETDIR/token" echo "$COVERITY_TOKEN" > "$SECRET" - echo "Building docker container..." - # TODO: This re-downloads the tools every time, rather than - # caching and reusing the image produced with the downloaded tools. - # Not sure why. - # TODO: how do you get 'docker build' to print the output of the - # commands it is running to its stdout? This would be useful for debug. - DOCKER_BUILDKIT=1 docker build -t coverity-scanner \ - --secret id=coverity.token,src="$SECRET" \ - -f scripts/coverity-scan/coverity-scan.docker \ - scripts/coverity-scan echo "Archiving sources to be analyzed..." ./scripts/archive-source.sh "$SECRETDIR/qemu-sources.tgz" + ARGS="--no-update-tools" if [ "$DRYRUN" = yes ]; then - DRYRUNARG=--dry-run + ARGS="$ARGS --dry-run" fi echo "Running scanner..." # If we need to capture the output tarball, get the inner run to # save it to the secrets directory so we can copy it out before the # directory is cleaned up. if [ ! -z "$RESULTSTARBALL" ]; then - RTARGS="--results-tarball /work/cov-int.tar.xz" - else - RTARGS="" + ARGS="$ARGS --results-tarball /work/cov-int.tar.xz" fi # Arrange for this docker run to get access to the sources with -v. # We pass through all the configuration from the outer script to the inner. export COVERITY_EMAIL COVERITY_BUILD_CMD - docker run -it --env COVERITY_EMAIL --env COVERITY_BUILD_CMD \ + tests/docker/docker.py run -it --env COVERITY_EMAIL --env COVERITY_BUILD_CMD \ -v "$SECRETDIR:/work" coverity-scanner \ ./run-coverity-scan --version "$VERSION" \ - --description "$DESCRIPTION" $DRYRUNARG --tokenfile /work/token \ - --srcdir /qemu --src-tarball /work/qemu-sources.tgz $RTARGS + --description "$DESCRIPTION" $ARGS --tokenfile /work/token \ + --srcdir /qemu --src-tarball /work/qemu-sources.tgz if [ ! -z "$RESULTSTARBALL" ]; then echo "Copying results tarball to $RESULTSTARBALL..." cp "$SECRETDIR/cov-int.tar.xz" "$RESULTSTARBALL" @@ -330,12 +369,6 @@ if [ "$DOCKER" = yes ]; then exit 0 fi -# Otherwise, continue with the full build and upload process. - -check_upload_permissions - -update_coverity_tools - TOOLBIN="$(cd "$COVERITY_TOOL_BASE" && echo $PWD/coverity_tool/cov-analysis-*/bin)" if ! test -x "$TOOLBIN/cov-build"; then @@ -370,9 +403,6 @@ echo "Configuring..." --enable-mpath --enable-libxml2 --enable-glusterfs \ --enable-virtfs --enable-zstd -echo "Making libqemustub.a..." -make libqemustub.a - echo "Running cov-build..." rm -rf cov-int mkdir cov-int @@ -393,7 +423,7 @@ if [ "$DRYRUN" = yes ]; then exit 0 fi -curl --form token="$PROJTOKEN" --form email="$COVERITY_EMAIL" \ +curl --form token="$COVERITY_TOKEN" --form email="$COVERITY_EMAIL" \ --form file=@"$TARBALL" --form version="$VERSION" \ --form description="$DESCRIPTION" \ https://scan.coverity.com/builds?project="$PROJNAME" diff --git a/scripts/create_config b/scripts/create_config deleted file mode 100755 index 6d8f08b39daea1e2f0654f83d4fd1e599068ddeb..0000000000000000000000000000000000000000 --- a/scripts/create_config +++ /dev/null @@ -1,129 +0,0 @@ -#!/bin/sh - -echo "/* Automatically generated by create_config - do not modify */" - -while read line; do - -case $line in - VERSION=*) # configuration - version=${line#*=} - major=$(echo "$version" | cut -d. -f1) - minor=$(echo "$version" | cut -d. -f2) - micro=$(echo "$version" | cut -d. -f3) - echo "#define QEMU_VERSION \"$version\"" - echo "#define QEMU_VERSION_MAJOR $major" - echo "#define QEMU_VERSION_MINOR $minor" - echo "#define QEMU_VERSION_MICRO $micro" - ;; - qemu_*dir=* | qemu_*path=*) # qemu-specific directory configuration - name=${line%=*} - value=${line#*=} - define_name=$(echo $name | LC_ALL=C tr '[a-z]' '[A-Z]') - eval "define_value=\"$value\"" - echo "#define CONFIG_$define_name \"$define_value\"" - # save for the next definitions - eval "$name=\$define_value" - ;; - prefix=*) - # save for the next definitions - prefix=${line#*=} - ;; - IASL=*) # iasl executable - value=${line#*=} - echo "#define CONFIG_IASL $value" - ;; - CONFIG_AUDIO_DRIVERS=*) - drivers=${line#*=} - echo "#define CONFIG_AUDIO_DRIVERS \\" - for drv in $drivers; do - echo " \"${drv}\",\\" - done - echo "" - ;; - CONFIG_BDRV_RW_WHITELIST=*) - echo "#define CONFIG_BDRV_RW_WHITELIST\\" - for drv in ${line#*=}; do - echo " \"${drv}\",\\" - done - echo " NULL" - ;; - CONFIG_BDRV_RO_WHITELIST=*) - echo "#define CONFIG_BDRV_RO_WHITELIST\\" - for drv in ${line#*=}; do - echo " \"${drv}\",\\" - done - echo " NULL" - ;; - CONFIG_*=y) # configuration - name=${line%=*} - echo "#define $name 1" - ;; - CONFIG_*=n) # configuration - ;; - CONFIG_*=*) # configuration - name=${line%=*} - value=${line#*=} - echo "#define $name $value" - ;; - HAVE_*=y) # configuration - name=${line%=*} - echo "#define $name 1" - ;; - HAVE_*=*) # configuration - name=${line%=*} - value=${line#*=} - echo "#define $name $value" - ;; - ARCH=*) # configuration - arch=${line#*=} - arch_name=$(echo $arch | LC_ALL=C tr '[a-z]' '[A-Z]') - echo "#define HOST_$arch_name 1" - ;; - HOST_USB=*) - # do nothing - ;; - HOST_CC=*) - # do nothing - ;; - HOST_*=y) # configuration - name=${line%=*} - echo "#define $name 1" - ;; - HOST_*=*) # configuration - name=${line%=*} - value=${line#*=} - echo "#define $name $value" - ;; - TARGET_BASE_ARCH=*) # configuration - target_base_arch=${line#*=} - base_arch_name=$(echo $target_base_arch | LC_ALL=C tr '[a-z]' '[A-Z]') - echo "#define TARGET_$base_arch_name 1" - ;; - TARGET_XML_FILES=*) - # do nothing - ;; - TARGET_ABI_DIR=*) - # do nothing - ;; - TARGET_NAME=*) - target_name=${line#*=} - echo "#define TARGET_NAME \"$target_name\"" - ;; - TARGET_DIRS=*) - # do nothing - ;; - TARGET_*=y) # configuration - name=${line%=*} - echo "#define $name 1" - ;; - TARGET_*=*) # configuration - name=${line%=*} - value=${line#*=} - echo "#define $name $value" - ;; - DSOSUF=*) - echo "#define HOST_DSOSUF \"${line#*=}\"" - ;; -esac - -done # read diff --git a/scripts/decodetree.py b/scripts/decodetree.py old mode 100755 new mode 100644 index 46ab9178077de23e5ced0672cb53152adffa79fd..47aa9caf6d15c55a78acf80d0dfcedea941871b9 --- a/scripts/decodetree.py +++ b/scripts/decodetree.py @@ -4,7 +4,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,7 +31,6 @@ fields = {} arguments = {} formats = {} -patterns = [] allpatterns = [] anyextern = False @@ -43,31 +42,41 @@ insntype = 'uint32_t' decode_function = 'decode' -re_ident = '[a-zA-Z][a-zA-Z0-9_]*' +# An identifier for C. +re_C_ident = '[a-zA-Z][a-zA-Z0-9_]*' +# Identifiers for Arguments, Fields, Formats and Patterns. +re_arg_ident = '&[a-zA-Z0-9_]*' +re_fld_ident = '%[a-zA-Z0-9_]*' +re_fmt_ident = '@[a-zA-Z0-9_]*' +re_pat_ident = '[a-zA-Z0-9_]*' def error_with_file(file, lineno, *args): """Print an error message from file:line and args and exit.""" global output_file global output_fd + prefix = '' + if file: + prefix += '{0}:'.format(file) if lineno: - r = '{0}:{1}: error:'.format(file, lineno) - elif input_file: - r = '{0}: error:'.format(file) - else: - r = 'error:' - for a in args: - r += ' ' + str(a) - r += '\n' - sys.stderr.write(r) + prefix += '{0}:'.format(lineno) + if prefix: + prefix += ' ' + print(prefix, end='error: ', file=sys.stderr) + print(*args, file=sys.stderr) + if output_file and output_fd: output_fd.close() os.remove(output_file) exit(1) +# end error_with_file + def error(lineno, *args): - error_with_file(input_file, lineno, args) + error_with_file(input_file, lineno, *args) +# end error + def output(*args): global output_fd @@ -75,13 +84,6 @@ def output(*args): output_fd.write(a) -if sys.version_info >= (3, 4): - re_fullmatch = re.fullmatch -else: - def re_fullmatch(pat, str): - return re.match('^' + pat + '$', str) - - def output_autogen(): output('/* This file is autogenerated by scripts/decodetree.py. */\n\n') @@ -92,7 +94,7 @@ def str_indent(c): def str_fields(fields): - """Return a string uniquely identifing FIELDS""" + """Return a string uniquely identifying FIELDS""" r = '' for n in sorted(fields.keys()): r += '_' + n @@ -127,6 +129,7 @@ def is_pow2(x): def ctz(x): """Return the number of times 2 factors into X.""" + assert x != 0 r = 0 while ((x >> r) & 1) == 0: r += 1 @@ -134,6 +137,8 @@ def ctz(x): def is_contiguous(bits): + if bits == 0: + return -1 shift = ctz(bits) if is_pow2((bits >> shift) + 1): return shift @@ -371,32 +376,99 @@ def output_code(self, i, extracted, outerbits, outermask): output(ind, 'u.f_', arg, '.', n, ' = ', f.str_extract(), ';\n') output(ind, 'if (', translate_prefix, '_', self.name, '(ctx, &u.f_', arg, ')) return true;\n') + + # Normal patterns do not have children. + def build_tree(self): + return + def prop_masks(self): + return + def prop_format(self): + return + def prop_width(self): + return + # end Pattern class MultiPattern(General): - """Class representing an overlapping set of instruction patterns""" + """Class representing a set of instruction patterns""" - def __init__(self, lineno, pats, fixb, fixm, udfm, w): + def __init__(self, lineno): self.file = input_file self.lineno = lineno - self.pats = pats + self.pats = [] self.base = None - self.fixedbits = fixb - self.fixedmask = fixm - self.undefmask = udfm - self.width = w + self.fixedbits = 0 + self.fixedmask = 0 + self.undefmask = 0 + self.width = None def __str__(self): - r = "{" - for p in self.pats: - r = r + ' ' + str(p) - return r + "}" + r = 'group' + if self.fixedbits is not None: + r += ' ' + str_match_bits(self.fixedbits, self.fixedmask) + return r def output_decl(self): for p in self.pats: p.output_decl() + def prop_masks(self): + global insnmask + + fixedmask = insnmask + undefmask = insnmask + + # Collect fixedmask/undefmask for all of the children. + for p in self.pats: + p.prop_masks() + fixedmask &= p.fixedmask + undefmask &= p.undefmask + + # Widen fixedmask until all fixedbits match + repeat = True + fixedbits = 0 + while repeat and fixedmask != 0: + fixedbits = None + for p in self.pats: + thisbits = p.fixedbits & fixedmask + if fixedbits is None: + fixedbits = thisbits + elif fixedbits != thisbits: + fixedmask &= ~(fixedbits ^ thisbits) + break + else: + repeat = False + + self.fixedbits = fixedbits + self.fixedmask = fixedmask + self.undefmask = undefmask + + def build_tree(self): + for p in self.pats: + p.build_tree() + + def prop_format(self): + for p in self.pats: + p.build_tree() + + def prop_width(self): + width = None + for p in self.pats: + p.prop_width() + if width is None: + width = p.width + elif width != p.width: + error_with_file(self.file, self.lineno, + 'width mismatch in patterns within braces') + self.width = width + +# end MultiPattern + + +class IncMultiPattern(MultiPattern): + """Class representing an overlapping set of instruction patterns""" + def output_code(self, i, extracted, outerbits, outermask): global translate_prefix ind = str_indent(i) @@ -413,13 +485,159 @@ def output_code(self, i, extracted, outerbits, outermask): output(ind, '}\n') else: p.output_code(i, extracted, p.fixedbits, p.fixedmask) -#end MultiPattern +#end IncMultiPattern + + +class Tree: + """Class representing a node in a decode tree""" + + def __init__(self, fm, tm): + self.fixedmask = fm + self.thismask = tm + self.subs = [] + self.base = None + + def str1(self, i): + ind = str_indent(i) + r = '{0}{1:08x}'.format(ind, self.fixedmask) + if self.format: + r += ' ' + self.format.name + r += ' [\n' + for (b, s) in self.subs: + r += '{0} {1:08x}:\n'.format(ind, b) + r += s.str1(i + 4) + '\n' + r += ind + ']' + return r + + def __str__(self): + return self.str1(0) + + def output_code(self, i, extracted, outerbits, outermask): + ind = str_indent(i) + + # If we identified all nodes below have the same format, + # extract the fields now. + if not extracted and self.base: + output(ind, self.base.extract_name(), + '(ctx, &u.f_', self.base.base.name, ', insn);\n') + extracted = True + + # Attempt to aid the compiler in producing compact switch statements. + # If the bits in the mask are contiguous, extract them. + sh = is_contiguous(self.thismask) + if sh > 0: + # Propagate SH down into the local functions. + def str_switch(b, sh=sh): + return '(insn >> {0}) & 0x{1:x}'.format(sh, b >> sh) + + def str_case(b, sh=sh): + return '0x{0:x}'.format(b >> sh) + else: + def str_switch(b): + return 'insn & 0x{0:08x}'.format(b) + + def str_case(b): + return '0x{0:08x}'.format(b) + + output(ind, 'switch (', str_switch(self.thismask), ') {\n') + for b, s in sorted(self.subs): + assert (self.thismask & ~s.fixedmask) == 0 + innermask = outermask | self.thismask + innerbits = outerbits | b + output(ind, 'case ', str_case(b), ':\n') + output(ind, ' /* ', + str_match_bits(innerbits, innermask), ' */\n') + s.output_code(i + 4, extracted, innerbits, innermask) + output(ind, ' break;\n') + output(ind, '}\n') +# end Tree + + +class ExcMultiPattern(MultiPattern): + """Class representing a non-overlapping set of instruction patterns""" + + def output_code(self, i, extracted, outerbits, outermask): + # Defer everything to our decomposed Tree node + self.tree.output_code(i, extracted, outerbits, outermask) + + @staticmethod + def __build_tree(pats, outerbits, outermask): + # Find the intersection of all remaining fixedmask. + innermask = ~outermask & insnmask + for i in pats: + innermask &= i.fixedmask + + if innermask == 0: + # Edge condition: One pattern covers the entire insnmask + if len(pats) == 1: + t = Tree(outermask, innermask) + t.subs.append((0, pats[0])) + return t + + text = 'overlapping patterns:' + for p in pats: + text += '\n' + p.file + ':' + str(p.lineno) + ': ' + str(p) + error_with_file(pats[0].file, pats[0].lineno, text) + + fullmask = outermask | innermask + + # Sort each element of pats into the bin selected by the mask. + bins = {} + for i in pats: + fb = i.fixedbits & innermask + if fb in bins: + bins[fb].append(i) + else: + bins[fb] = [i] + + # We must recurse if any bin has more than one element or if + # the single element in the bin has not been fully matched. + t = Tree(fullmask, innermask) + + for b, l in bins.items(): + s = l[0] + if len(l) > 1 or s.fixedmask & ~fullmask != 0: + s = ExcMultiPattern.__build_tree(l, b | outerbits, fullmask) + t.subs.append((b, s)) + + return t + + def build_tree(self): + super().prop_format() + self.tree = self.__build_tree(self.pats, self.fixedbits, + self.fixedmask) + + @staticmethod + def __prop_format(tree): + """Propagate Format objects into the decode tree""" + + # Depth first search. + for (b, s) in tree.subs: + if isinstance(s, Tree): + ExcMultiPattern.__prop_format(s) + + # If all entries in SUBS have the same format, then + # propagate that into the tree. + f = None + for (b, s) in tree.subs: + if f is None: + f = s.base + if f is None: + return + if f is not s.base: + return + tree.base = f + + def prop_format(self): + super().prop_format() + self.__prop_format(self.tree) + +# end ExcMultiPattern def parse_field(lineno, name, toks): """Parse one instruction field from TOKS at LINENO""" global fields - global re_ident global insnwidth # A "simple" field will have only one entry; @@ -428,18 +646,18 @@ def parse_field(lineno, name, toks): width = 0 func = None for t in toks: - if re_fullmatch('!function=' + re_ident, t): + if re.match('^!function=', t): if func: error(lineno, 'duplicate function') func = t.split('=') func = func[1] continue - if re_fullmatch('[0-9]+:s[0-9]+', t): + if re.fullmatch('[0-9]+:s[0-9]+', t): # Signed field extract subtoks = t.split(':s') sign = True - elif re_fullmatch('[0-9]+:[0-9]+', t): + elif re.fullmatch('[0-9]+:[0-9]+', t): # Unsigned field extract subtoks = t.split(':') sign = False @@ -482,17 +700,17 @@ def parse_field(lineno, name, toks): def parse_arguments(lineno, name, toks): """Parse one argument set from TOKS at LINENO""" global arguments - global re_ident + global re_C_ident global anyextern flds = [] extern = False for t in toks: - if re_fullmatch('!extern', t): + if re.fullmatch('!extern', t): extern = True anyextern = True continue - if not re_fullmatch(re_ident, t): + if not re.fullmatch(re_C_ident, t): error(lineno, 'invalid argument set token "{0}"'.format(t)) if t in flds: error(lineno, 'duplicate argument "{0}"'.format(t)) @@ -572,18 +790,22 @@ def infer_format(arg, fieldmask, flds, width): # end infer_format -def parse_generic(lineno, is_format, name, toks): +def parse_generic(lineno, parent_pat, name, toks): """Parse one instruction format from TOKS at LINENO""" global fields global arguments global formats - global patterns global allpatterns - global re_ident + global re_arg_ident + global re_fld_ident + global re_fmt_ident + global re_C_ident global insnwidth global insnmask global variablewidth + is_format = parent_pat is None + fixedmask = 0 fixedbits = 0 undefmask = 0 @@ -592,8 +814,8 @@ def parse_generic(lineno, is_format, name, toks): arg = None fmt = None for t in toks: - # '&Foo' gives a format an explcit argument set. - if t[0] == '&': + # '&Foo' gives a format an explicit argument set. + if re.fullmatch(re_arg_ident, t): tt = t[1:] if arg: error(lineno, 'multiple argument sets') @@ -604,7 +826,7 @@ def parse_generic(lineno, is_format, name, toks): continue # '@Foo' gives a pattern an explicit format. - if t[0] == '@': + if re.fullmatch(re_fmt_ident, t): tt = t[1:] if fmt: error(lineno, 'multiple formats') @@ -615,19 +837,19 @@ def parse_generic(lineno, is_format, name, toks): continue # '%Foo' imports a field. - if t[0] == '%': + if re.fullmatch(re_fld_ident, t): tt = t[1:] flds = add_field_byname(lineno, flds, tt, tt) continue # 'Foo=%Bar' imports a field with a different name. - if re_fullmatch(re_ident + '=%' + re_ident, t): + if re.fullmatch(re_C_ident + '=' + re_fld_ident, t): (fname, iname) = t.split('=%') flds = add_field_byname(lineno, flds, fname, iname) continue # 'Foo=number' sets an argument field to a constant value - if re_fullmatch(re_ident + '=[+-]?[0-9]+', t): + if re.fullmatch(re_C_ident + '=[+-]?[0-9]+', t): (fname, value) = t.split('=') value = int(value) flds = add_field(lineno, flds, fname, ConstField(value)) @@ -635,7 +857,7 @@ def parse_generic(lineno, is_format, name, toks): # Pattern of 0s, 1s, dots and dashes indicate required zeros, # required ones, or dont-cares. - if re_fullmatch('[01.-]+', t): + if re.fullmatch('[01.-]+', t): shift = len(t) fms = t.replace('0', '1') fms = fms.replace('.', '0') @@ -652,7 +874,7 @@ def parse_generic(lineno, is_format, name, toks): fixedmask = (fixedmask << shift) | fms undefmask = (undefmask << shift) | ubm # Otherwise, fieldname:fieldwidth - elif re_fullmatch(re_ident + ':s?[0-9]+', t): + elif re.fullmatch(re_C_ident + ':s?[0-9]+', t): (fname, flen) = t.split(':') sign = False if flen[0] == 's': @@ -681,7 +903,7 @@ def parse_generic(lineno, is_format, name, toks): elif not (is_format and width == 0) and width != insnwidth: error(lineno, 'definition has {0} bits'.format(width)) - # Do not check for fields overlaping fields; one valid usage + # Do not check for fields overlapping fields; one valid usage # is to be able to duplicate fields via import. fieldmask = 0 for f in flds.values(): @@ -734,7 +956,7 @@ def parse_generic(lineno, is_format, name, toks): error(lineno, 'field {0} not initialized'.format(f)) pat = Pattern(name, lineno, fmt, fixedbits, fixedmask, undefmask, fieldmask, flds, width) - patterns.append(pat) + parent_pat.pats.append(pat) allpatterns.append(pat) # Validate the masks that we have assembled. @@ -754,62 +976,20 @@ def parse_generic(lineno, is_format, name, toks): .format(allbits ^ insnmask)) # end parse_general -def build_multi_pattern(lineno, pats): - """Validate the Patterns going into a MultiPattern.""" - global patterns - global insnmask - - if len(pats) < 2: - error(lineno, 'less than two patterns within braces') - - fixedmask = insnmask - undefmask = insnmask - - # Collect fixed/undefmask for all of the children. - # Move the defining lineno back to that of the first child. - for p in pats: - fixedmask &= p.fixedmask - undefmask &= p.undefmask - if p.lineno < lineno: - lineno = p.lineno - - width = None - for p in pats: - if width is None: - width = p.width - elif width != p.width: - error(lineno, 'width mismatch in patterns within braces') - - repeat = True - while repeat: - if fixedmask == 0: - error(lineno, 'no overlap in patterns within braces') - fixedbits = None - for p in pats: - thisbits = p.fixedbits & fixedmask - if fixedbits is None: - fixedbits = thisbits - elif fixedbits != thisbits: - fixedmask &= ~(fixedbits ^ thisbits) - break - else: - repeat = False - mp = MultiPattern(lineno, pats, fixedbits, fixedmask, undefmask, width) - patterns.append(mp) -# end build_multi_pattern - -def parse_file(f): +def parse_file(f, parent_pat): """Parse all of the patterns within a file""" - - global patterns + global re_arg_ident + global re_fld_ident + global re_fmt_ident + global re_pat_ident # Read all of the lines of the file. Concatenate lines # ending in backslash; discard empty lines and comments. toks = [] lineno = 0 nesting = 0 - saved_pats = [] + nesting_pats = [] for line in f: lineno += 1 @@ -853,17 +1033,23 @@ def parse_file(f): del toks[0] # End nesting? - if name == '}': - if nesting == 0: - error(start_lineno, 'mismatched close brace') + if name == '}' or name == ']': if len(toks) != 0: error(start_lineno, 'extra tokens after close brace') + + # Make sure { } and [ ] nest properly. + if (name == '}') != isinstance(parent_pat, IncMultiPattern): + error(lineno, 'mismatched close brace') + + try: + parent_pat = nesting_pats.pop() + except: + error(lineno, 'extra close brace') + nesting -= 2 if indent != nesting: - error(start_lineno, 'indentation ', indent, ' != ', nesting) - pats = patterns - patterns = saved_pats.pop() - build_multi_pattern(lineno, pats) + error(lineno, 'indentation ', indent, ' != ', nesting) + toks = [] continue @@ -872,128 +1058,38 @@ def parse_file(f): error(start_lineno, 'indentation ', indent, ' != ', nesting) # Start nesting? - if name == '{': + if name == '{' or name == '[': if len(toks) != 0: error(start_lineno, 'extra tokens after open brace') - saved_pats.append(patterns) - patterns = [] + + if name == '{': + nested_pat = IncMultiPattern(start_lineno) + else: + nested_pat = ExcMultiPattern(start_lineno) + parent_pat.pats.append(nested_pat) + nesting_pats.append(parent_pat) + parent_pat = nested_pat + nesting += 2 toks = [] continue # Determine the type of object needing to be parsed. - if name[0] == '%': + if re.fullmatch(re_fld_ident, name): parse_field(start_lineno, name[1:], toks) - elif name[0] == '&': + elif re.fullmatch(re_arg_ident, name): parse_arguments(start_lineno, name[1:], toks) - elif name[0] == '@': - parse_generic(start_lineno, True, name[1:], toks) + elif re.fullmatch(re_fmt_ident, name): + parse_generic(start_lineno, None, name[1:], toks) + elif re.fullmatch(re_pat_ident, name): + parse_generic(start_lineno, parent_pat, name, toks) else: - parse_generic(start_lineno, False, name, toks) + error(lineno, 'invalid token "{0}"'.format(name)) toks = [] -# end parse_file - - -class Tree: - """Class representing a node in a decode tree""" - - def __init__(self, fm, tm): - self.fixedmask = fm - self.thismask = tm - self.subs = [] - self.base = None - def str1(self, i): - ind = str_indent(i) - r = '{0}{1:08x}'.format(ind, self.fixedmask) - if self.format: - r += ' ' + self.format.name - r += ' [\n' - for (b, s) in self.subs: - r += '{0} {1:08x}:\n'.format(ind, b) - r += s.str1(i + 4) + '\n' - r += ind + ']' - return r - - def __str__(self): - return self.str1(0) - - def output_code(self, i, extracted, outerbits, outermask): - ind = str_indent(i) - - # If we identified all nodes below have the same format, - # extract the fields now. - if not extracted and self.base: - output(ind, self.base.extract_name(), - '(ctx, &u.f_', self.base.base.name, ', insn);\n') - extracted = True - - # Attempt to aid the compiler in producing compact switch statements. - # If the bits in the mask are contiguous, extract them. - sh = is_contiguous(self.thismask) - if sh > 0: - # Propagate SH down into the local functions. - def str_switch(b, sh=sh): - return '(insn >> {0}) & 0x{1:x}'.format(sh, b >> sh) - - def str_case(b, sh=sh): - return '0x{0:x}'.format(b >> sh) - else: - def str_switch(b): - return 'insn & 0x{0:08x}'.format(b) - - def str_case(b): - return '0x{0:08x}'.format(b) - - output(ind, 'switch (', str_switch(self.thismask), ') {\n') - for b, s in sorted(self.subs): - assert (self.thismask & ~s.fixedmask) == 0 - innermask = outermask | self.thismask - innerbits = outerbits | b - output(ind, 'case ', str_case(b), ':\n') - output(ind, ' /* ', - str_match_bits(innerbits, innermask), ' */\n') - s.output_code(i + 4, extracted, innerbits, innermask) - output(ind, ' return false;\n') - output(ind, '}\n') -# end Tree - - -def build_tree(pats, outerbits, outermask): - # Find the intersection of all remaining fixedmask. - innermask = ~outermask & insnmask - for i in pats: - innermask &= i.fixedmask - - if innermask == 0: - text = 'overlapping patterns:' - for p in pats: - text += '\n' + p.file + ':' + str(p.lineno) + ': ' + str(p) - error_with_file(pats[0].file, pats[0].lineno, text) - - fullmask = outermask | innermask - - # Sort each element of pats into the bin selected by the mask. - bins = {} - for i in pats: - fb = i.fixedbits & innermask - if fb in bins: - bins[fb].append(i) - else: - bins[fb] = [i] - - # We must recurse if any bin has more than one element or if - # the single element in the bin has not been fully matched. - t = Tree(fullmask, innermask) - - for b, l in bins.items(): - s = l[0] - if len(l) > 1 or s.fixedmask & ~fullmask != 0: - s = build_tree(l, b | outerbits, fullmask) - t.subs.append((b, s)) - - return t -# end build_tree + if nesting != 0: + error(lineno, 'missing close brace') +# end parse_file class SizeTree: @@ -1137,28 +1233,6 @@ def build_size_tree(pats, width, outerbits, outermask): # end build_size_tree -def prop_format(tree): - """Propagate Format objects into the decode tree""" - - # Depth first search. - for (b, s) in tree.subs: - if isinstance(s, Tree): - prop_format(s) - - # If all entries in SUBS have the same format, then - # propagate that into the tree. - f = None - for (b, s) in tree.subs: - if f is None: - f = s.base - if f is None: - return - if f is not s.base: - return - tree.base = f -# end prop_format - - def prop_size(tree): """Propagate minimum widths up the decode size tree""" @@ -1179,7 +1253,6 @@ def prop_size(tree): def main(): global arguments global formats - global patterns global allpatterns global translate_scope global translate_prefix @@ -1198,7 +1271,7 @@ def main(): long_opts = ['decode=', 'translate=', 'output=', 'insnwidth=', 'static-decode=', 'varinsnwidth='] try: - (opts, args) = getopt.getopt(sys.argv[1:], 'o:vw:', long_opts) + (opts, args) = getopt.gnu_getopt(sys.argv[1:], 'o:vw:', long_opts) except getopt.GetoptError as err: error(0, err) for o, a in opts: @@ -1226,19 +1299,30 @@ def main(): if len(args) < 1: error(0, 'missing input file') + + toppat = ExcMultiPattern(0) + for filename in args: input_file = filename f = open(filename, 'r') - parse_file(f) + parse_file(f, toppat) f.close() + # We do not want to compute masks for toppat, because those masks + # are used as a starting point for build_tree. For toppat, we must + # insist that decode begins from naught. + for i in toppat.pats: + i.prop_masks() + + toppat.build_tree() + toppat.prop_format() + if variablewidth: - stree = build_size_tree(patterns, 8, 0, 0) + for i in toppat.pats: + i.prop_width() + stree = build_size_tree(toppat.pats, 8, 0, 0) prop_size(stree) - dtree = build_tree(patterns, 0, 0) - prop_format(dtree) - if output_file: output_fd = open(output_file, 'w') else: @@ -1257,12 +1341,10 @@ def main(): # but we can't tell which ones. Prevent issues from the compiler by # suppressing redundant declaration warnings. if anyextern: - output("#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE\n", - "# pragma GCC diagnostic push\n", - "# pragma GCC diagnostic ignored \"-Wredundant-decls\"\n", - "# ifdef __clang__\n" + output("#pragma GCC diagnostic push\n", + "#pragma GCC diagnostic ignored \"-Wredundant-decls\"\n", + "#ifdef __clang__\n" "# pragma GCC diagnostic ignored \"-Wtypedef-redefinition\"\n", - "# endif\n", "#endif\n\n") out_pats = {} @@ -1277,9 +1359,7 @@ def main(): output('\n') if anyextern: - output("#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE\n", - "# pragma GCC diagnostic pop\n", - "#endif\n\n") + output("#pragma GCC diagnostic pop\n\n") for n in sorted(formats.keys()): f = formats[n] @@ -1296,7 +1376,7 @@ def main(): f = arguments[n] output(i4, i4, f.struct_name(), ' f_', f.name, ';\n') output(i4, '} u;\n\n') - dtree.output_code(4, False, 0, 0) + toppat.output_code(4, False, 0, 0) output(i4, 'return false;\n') output('}\n') diff --git a/scripts/device-crash-test b/scripts/device-crash-test index 305d0427af61430dfe920c597e4d0bed36018369..04118669ba77b926eb619ade149c2731a22b4305 100755 --- a/scripts/device-crash-test +++ b/scripts/device-crash-test @@ -383,7 +383,9 @@ def binariesToTest(args, testcase): if args.qemu: r = args.qemu else: - r = glob.glob('./*-softmmu/qemu-system-*') + r = [f.path for f in os.scandir('.') + if f.name.startswith('qemu-system-') and + f.is_file() and os.access(f, os.X_OK)] return r diff --git a/scripts/feature_to_c.sh b/scripts/feature_to_c.sh index c8ce9b88f6d910632f8112f49c47324bb7724a21..b1169899c19d0a7860e3da995e7f68a7812aac6a 100644 --- a/scripts/feature_to_c.sh +++ b/scripts/feature_to_c.sh @@ -19,16 +19,8 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, see . -output=$1 -shift - -if test -z "$output" || test -z "$1"; then - echo "Usage: $0 OUTPUTFILE INPUTFILE..." - exit 1 -fi - -if test -e "$output"; then - echo "Output file \"$output\" already exists; refusing to overwrite." +if test -z "$1"; then + echo "Usage: $0 INPUTFILE..." exit 1 fi @@ -60,17 +52,17 @@ for input; do printf "'\''\\n'\'', \n" } END { print " 0 };" - }' < $input >> $output + }' < $input done -echo >> $output -echo "const char *const xml_builtin[][2] = {" >> $output +echo +echo "const char *const xml_builtin[][2] = {" for input; do basename=$(echo $input | sed 's,.*/,,') arrayname=xml_feature_$(echo $input | sed 's,.*/,,; s/[-.]/_/g') - echo " { \"$basename\", $arrayname }," >> $output + echo " { \"$basename\", $arrayname }," done -echo " { (char *)0, (char *)0 }" >> $output -echo "};" >> $output +echo " { (char *)0, (char *)0 }" +echo "};" diff --git a/scripts/gensyscalls.sh b/scripts/gensyscalls.sh index b7b8456f63122f7eeedd2d403b3012c5b8b1027b..bba9fb052c47a50eebd10e6dcc0b814251890e76 100755 --- a/scripts/gensyscalls.sh +++ b/scripts/gensyscalls.sh @@ -86,8 +86,7 @@ generate_syscall_nr() read_includes $arch $bits | filter_defines | rename_defines | \ evaluate_values | sort -n -k 3 echo - echo "#endif /* ${guard} */" - echo) > "$file" + echo "#endif /* ${guard} */") > "$file" } mkdir "$TMP/asm" diff --git a/scripts/git.orderfile b/scripts/git.orderfile index 73fd818d7f3ee19a7a79c93221fcd4ddf026dbfd..3736c1d6afff598e1040bff60cadd415c25baaf4 100644 --- a/scripts/git.orderfile +++ b/scripts/git.orderfile @@ -12,12 +12,12 @@ # Documentation docs/* *.rst -*.texi # build system configure Makefile* *.mak +meson.build # qapi schema qapi/*.json diff --git a/scripts/hxtool b/scripts/hxtool old mode 100644 new mode 100755 index 7b1452f3cf1588cc8fd4053f53dc733adb99b52b..80516b9437506c6ee091956d6044fcab16146d58 --- a/scripts/hxtool +++ b/scripts/hxtool @@ -19,6 +19,6 @@ hxtoh() case "$1" in "-h") hxtoh ;; *) exit 1 ;; -esac +esac < "$2" exit 0 diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 030b5c8691f0b7ed93a3ec591e955f69a508b1d4..4fbaaa05e3853b8466ac15cbf963791b1f8d3265 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -839,7 +839,23 @@ sub output_function_rst(%) { output_highlight_rst($args{'purpose'}); $start = "\n\n**Syntax**\n\n ``"; } else { - print ".. c:function:: "; + if ((split(/\./, $sphinx_version))[0] >= 3) { + # Sphinx 3 and later distinguish macros and functions and + # complain if you use c:function with something that's not + # syntactically valid as a function declaration. + # We assume that anything with a return type is a function + # and anything without is a macro. + if ($args{'functiontype'} ne "") { + print ".. c:function:: "; + } else { + print ".. c:macro:: "; + } + } else { + # Older Sphinx don't support documenting macros that take + # arguments with c:macro, and don't complain about the use + # of c:function for this. + print ".. c:function:: "; + } } if ($args{'functiontype'} ne "") { $start .= $args{'functiontype'} . " " . $args{'function'} . " ("; @@ -1064,14 +1080,6 @@ sub output_blockhead { sub dump_declaration($$) { no strict 'refs'; my ($prototype, $file) = @_; - if ($decl_type eq 'type name') { - if ($prototype =~ /^(enum|struct|union)\s+/) { - $decl_type = $1; - } else { - return; - } - } - my $func = "dump_" . $decl_type; &$func(@_); } @@ -1318,8 +1326,8 @@ sub dump_typedef($$) { $x =~ s@/\*.*?\*/@@gos; # strip comments. # Parse function prototypes - if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ || - $x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) { + if ($x =~ /typedef\s+(\w+\s*\**)\s*\(\*?\s*(\w\S+)\s*\)\s*\((.*)\);/ || + $x =~ /typedef\s+(\w+\s*\**)\s*(\w\S+)\s*\s*\((.*)\);/) { # Function typedefs $return_type = $1; @@ -1625,7 +1633,7 @@ sub dump_function($$) { # If you mess with these regexps, it's a good idea to check that # the following functions' documentation still comes out right: # - parport_register_device (function pointer parameters) - # - atomic_set (macro) + # - qatomic_set (macro) # - pci_match_device, __copy_to_user (long return type) if ($define && $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s+/) { @@ -1928,9 +1936,7 @@ sub process_name($$) { ++$warnings; } - if ($identifier =~ m/^[A-Z]/) { - $decl_type = 'type name'; - } elsif ($identifier =~ m/^struct\b/) { + if ($identifier =~ m/^struct\b/) { $decl_type = 'struct'; } elsif ($identifier =~ m/^union\b/) { $decl_type = 'union'; diff --git a/scripts/kvm/vmxcap b/scripts/kvm/vmxcap index 971ed0e72170ff066379025fb6bb20a159ff9f6e..6fe66d5f5753af5a86dd992ba4347c79d44862d2 100755 --- a/scripts/kvm/vmxcap +++ b/scripts/kvm/vmxcap @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # # tool for querying VMX capabilities # @@ -275,5 +275,6 @@ controls = [ ), ] -for c in controls: - c.show() +if __name__ == '__main__': + for c in controls: + c.show() diff --git a/scripts/meson.build b/scripts/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..e8cc63896d8799ea97fe593aa5815c183dee9030 --- /dev/null +++ b/scripts/meson.build @@ -0,0 +1,3 @@ +if 'CONFIG_TRACE_SYSTEMTAP' in config_host + install_data('qemu-trace-stap', install_dir: get_option('bindir')) +endif diff --git a/scripts/minikconf.py b/scripts/minikconf.py old mode 100755 new mode 100644 index 90b99517c1162db0524b8f2d798424fc6c08bae4..bcd91015d34a69f793efab42c6915d6348e30abb --- a/scripts/minikconf.py +++ b/scripts/minikconf.py @@ -402,7 +402,7 @@ def do_include(self, include): if incl_abs_fname in self.data.previously_included: return try: - fp = open(incl_abs_fname, 'r') + fp = open(incl_abs_fname, 'rt', encoding='utf-8') except IOError as e: raise KconfigParserError(self, '%s: %s' % (e.strerror, include)) @@ -696,7 +696,7 @@ def scan_token(self): parser.do_assignment(name, value == 'y') external_vars.add(name[7:]) else: - fp = open(arg, 'r') + fp = open(arg, 'rt', encoding='utf-8') parser.parse_file(fp) fp.close() @@ -705,7 +705,7 @@ def scan_token(self): if key not in external_vars and config[key]: print ('CONFIG_%s=y' % key) - deps = open(argv[2], 'w') + deps = open(argv[2], 'wt', encoding='utf-8') for fname in data.previously_included: print ('%s: %s' % (argv[1], fname), file=deps) deps.close() diff --git a/scripts/modules/module_block.py b/scripts/modules/module_block.py index f23191fac19ceaced421992c28c3f523be8471bc..1109df827d5f222fe78463379c6a7ff0db08e1c6 100644 --- a/scripts/modules/module_block.py +++ b/scripts/modules/module_block.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # # Module information generator # @@ -80,19 +80,20 @@ def print_bottom(fheader): #endif ''') -# First argument: output file -# All other arguments: modules source files (.c) -output_file = sys.argv[1] -with open(output_file, 'w') as fheader: - print_top(fheader) +if __name__ == '__main__': + # First argument: output file + # All other arguments: modules source files (.c) + output_file = sys.argv[1] + with open(output_file, 'w') as fheader: + print_top(fheader) - for filename in sys.argv[2:]: - if os.path.isfile(filename): - process_file(fheader, filename) - else: - print("File " + filename + " does not exist.", file=sys.stderr) - sys.exit(1) + for filename in sys.argv[2:]: + if os.path.isfile(filename): + process_file(fheader, filename) + else: + print("File " + filename + " does not exist.", file=sys.stderr) + sys.exit(1) - print_bottom(fheader) + print_bottom(fheader) -sys.exit(0) + sys.exit(0) diff --git a/scripts/mtest2make.py b/scripts/mtest2make.py new file mode 100644 index 0000000000000000000000000000000000000000..25ee6887cf324626b71a6d48d31263ad8cb4edd9 --- /dev/null +++ b/scripts/mtest2make.py @@ -0,0 +1,131 @@ +#! /usr/bin/env python3 + +# Create Makefile targets to run tests, from Meson's test introspection data. +# +# Author: Paolo Bonzini + +from collections import defaultdict +import itertools +import json +import os +import shlex +import sys + +class Suite(object): + def __init__(self): + self.tests = list() + self.slow_tests = list() + self.executables = set() + +print(''' +SPEED = quick + +# $1 = environment, $2 = test command, $3 = test name, $4 = dir +.test-human-tap = $1 $(if $4,(cd $4 && $2),$2) < /dev/null | ./scripts/tap-driver.pl --test-name="$3" $(if $(V),,--show-failures-only) +.test-human-exitcode = $1 $(PYTHON) scripts/test-driver.py $(if $4,-C$4) $(if $(V),--verbose) -- $2 < /dev/null +.test-tap-tap = $1 $(if $4,(cd $4 && $2),$2) < /dev/null | sed "s/^[a-z][a-z]* [0-9]*/& $3/" || true +.test-tap-exitcode = printf "%s\\n" 1..1 "`$1 $(if $4,(cd $4 && $2),$2) < /dev/null > /dev/null || echo "not "`ok 1 $3" +.test.human-print = echo $(if $(V),'$1 $2','Running test $3') && +.test.env = MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$(( $${RANDOM:-0} % 255 + 1))} + +# $1 = test name, $2 = test target (human or tap) +.test.run = $(call .test.$2-print,$(.test.env.$1),$(.test.cmd.$1),$(.test.name.$1)) $(call .test-$2-$(.test.driver.$1),$(.test.env.$1),$(.test.cmd.$1),$(.test.name.$1),$(.test.dir.$1)) + +.test.output-format = human +''') + +introspect = json.load(sys.stdin) +i = 0 + +def process_tests(test, targets, suites): + global i + env = ' '.join(('%s=%s' % (shlex.quote(k), shlex.quote(v)) + for k, v in test['env'].items())) + executable = test['cmd'][0] + try: + executable = os.path.relpath(executable) + except: + pass + if test['workdir'] is not None: + try: + test['cmd'][0] = os.path.relpath(executable, test['workdir']) + except: + test['cmd'][0] = executable + else: + test['cmd'][0] = executable + cmd = ' '.join((shlex.quote(x) for x in test['cmd'])) + driver = test['protocol'] if 'protocol' in test else 'exitcode' + + i += 1 + if test['workdir'] is not None: + print('.test.dir.%d := %s' % (i, shlex.quote(test['workdir']))) + + if 'depends' in test: + deps = (targets.get(x, []) for x in test['depends']) + deps = itertools.chain.from_iterable(deps) + else: + deps = ['all'] + + print('.test.name.%d := %s' % (i, test['name'])) + print('.test.driver.%d := %s' % (i, driver)) + print('.test.env.%d := $(.test.env) %s' % (i, env)) + print('.test.cmd.%d := %s' % (i, cmd)) + print('.test.deps.%d := %s' % (i, ' '.join(deps))) + print('.PHONY: run-test-%d' % (i,)) + print('run-test-%d: $(.test.deps.%d)' % (i,i)) + print('\t@$(call .test.run,%d,$(.test.output-format))' % (i,)) + + test_suites = test['suite'] or ['default'] + is_slow = any(s.endswith('-slow') for s in test_suites) + for s in test_suites: + # The suite name in the introspection info is "PROJECT:SUITE" + s = s.split(':')[1] + if s.endswith('-slow'): + s = s[:-5] + if is_slow: + suites[s].slow_tests.append(i) + else: + suites[s].tests.append(i) + suites[s].executables.add(executable) + +def emit_prolog(suites, prefix): + all_tap = ' '.join(('%s-report-%s.tap' % (prefix, k) for k in suites.keys())) + print('.PHONY: %s %s-report.tap %s' % (prefix, prefix, all_tap)) + print('%s: run-tests' % (prefix,)) + print('%s-report.tap %s: %s-report%%.tap: all' % (prefix, all_tap, prefix)) + print('''\t$(MAKE) .test.output-format=tap --quiet -Otarget V=1 %s$* | ./scripts/tap-merge.pl | tee "$@" \\ + | ./scripts/tap-driver.pl $(if $(V),, --show-failures-only)''' % (prefix, )) + +def emit_suite(name, suite, prefix): + executables = ' '.join(suite.executables) + slow_test_numbers = ' '.join((str(x) for x in suite.slow_tests)) + test_numbers = ' '.join((str(x) for x in suite.tests)) + target = '%s-%s' % (prefix, name) + print('.test.quick.%s := %s' % (target, test_numbers)) + print('.test.slow.%s := $(.test.quick.%s) %s' % (target, target, slow_test_numbers)) + print('%s-build: %s' % (prefix, executables)) + print('.PHONY: %s' % (target, )) + print('.PHONY: %s-report-%s.tap' % (prefix, name)) + print('%s: run-tests' % (target, )) + print('ifneq ($(filter %s %s, $(MAKECMDGOALS)),)' % (target, prefix)) + print('.tests += $(.test.$(SPEED).%s)' % (target, )) + print('endif') + +targets = {t['id']: [os.path.relpath(f) for f in t['filename']] + for t in introspect['targets']} + +testsuites = defaultdict(Suite) +for test in introspect['tests']: + process_tests(test, targets, testsuites) +emit_prolog(testsuites, 'check') +for name, suite in testsuites.items(): + emit_suite(name, suite, 'check') + +benchsuites = defaultdict(Suite) +for test in introspect['benchmarks']: + process_tests(test, targets, benchsuites) +emit_prolog(benchsuites, 'bench') +for name, suite in benchsuites.items(): + emit_suite(name, suite, 'bench') + +print('run-tests: $(patsubst %, run-test-%, $(.tests))') diff --git a/scripts/nsis.py b/scripts/nsis.py new file mode 100644 index 0000000000000000000000000000000000000000..5135a0583167ea8a386a97f160e5350611e48d7c --- /dev/null +++ b/scripts/nsis.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 Red Hat, Inc. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import argparse +import glob +import os +import shutil +import subprocess +import tempfile + + +def signcode(path): + cmd = os.environ.get("SIGNCODE") + if not cmd: + return + subprocess.run([cmd, path]) + + +def main(): + parser = argparse.ArgumentParser(description="QEMU NSIS build helper.") + parser.add_argument("outfile") + parser.add_argument("prefix") + parser.add_argument("srcdir") + parser.add_argument("cpu") + parser.add_argument("nsisargs", nargs="*") + args = parser.parse_args() + + destdir = tempfile.mkdtemp() + try: + subprocess.run(["make", "install", "DESTDIR=" + destdir + os.path.sep]) + with open( + os.path.join(destdir + args.prefix, "system-emulations.nsh"), "w" + ) as nsh: + for exe in glob.glob( + os.path.join(destdir + args.prefix, "qemu-system-*.exe") + ): + exe = os.path.basename(exe) + arch = exe[12:-4] + nsh.write( + """ + Section "{0}" Section_{0} + SetOutPath "$INSTDIR" + File "${{BINDIR}}\\{1}" + SectionEnd + """.format( + arch, exe + ) + ) + + for exe in glob.glob(os.path.join(destdir + args.prefix, "*.exe")): + signcode(exe) + + makensis = [ + "makensis", + "-V2", + "-NOCD", + "-DSRCDIR=" + args.srcdir, + "-DBINDIR=" + destdir + args.prefix, + ] + dlldir = "w32" + if args.cpu == "x86_64": + dlldir = "w64" + makensis += ["-DW64"] + if os.path.exists(os.path.join(args.srcdir, "dll")): + makensis += ["-DDLLDIR={0}/dll/{1}".format(args.srcdir, dlldir)] + + makensis += ["-DOUTFILE=" + args.outfile] + args.nsisargs + subprocess.run(makensis) + signcode(args.outfile) + finally: + shutil.rmtree(destdir) + + +if __name__ == "__main__": + main() diff --git a/scripts/oss-fuzz/build.sh b/scripts/oss-fuzz/build.sh new file mode 100755 index 0000000000000000000000000000000000000000..c1af43fded15b0e51c03dd179f823af4c9612374 --- /dev/null +++ b/scripts/oss-fuzz/build.sh @@ -0,0 +1,113 @@ +#!/bin/sh -e +# +# OSS-Fuzz build script. See: +# https://google.github.io/oss-fuzz/getting-started/new-project-guide/#buildsh +# +# The file is consumed by: +# https://github.com/google/oss-fuzz/blob/master/projects/qemu/Dockerfiles +# +# This code is licensed under the GPL version 2 or later. See +# the COPYING file in the top-level directory. +# + +# build project +# e.g. +# ./autogen.sh +# ./configure +# make -j$(nproc) all + +# build fuzzers +# e.g. +# $CXX $CXXFLAGS -std=c++11 -Iinclude \ +# /path/to/name_of_fuzzer.cc -o $OUT/name_of_fuzzer \ +# -fsanitize=fuzzer /path/to/library.a + +fatal () { + echo "Error : ${*}, exiting." + exit 1 +} + +OSS_FUZZ_BUILD_DIR="./build-oss-fuzz/" + +# There seems to be a bug in clang-11 (used for builds on oss-fuzz) : +# accel/tcg/cputlb.o: In function `load_memop': +# accel/tcg/cputlb.c:1505: undefined reference to `qemu_build_not_reached' +# +# When building with optimization, the compiler is expected to prove that the +# statement cannot be reached, and remove it. For some reason clang-11 doesn't +# remove it, resulting in an unresolved reference to qemu_build_not_reached +# Undefine the __OPTIMIZE__ macro which compiler.h relies on to choose whether +# to " #define qemu_build_not_reached() g_assert_not_reached() " +EXTRA_CFLAGS="$CFLAGS -U __OPTIMIZE__" + +if ! { [ -e "./COPYING" ] && + [ -e "./MAINTAINERS" ] && + [ -e "./Makefile" ] && + [ -e "./docs" ] && + [ -e "./VERSION" ] && + [ -e "./linux-user" ] && + [ -e "./softmmu" ];} ; then + fatal "Please run the script from the top of the QEMU tree" +fi + +mkdir -p $OSS_FUZZ_BUILD_DIR || fatal "mkdir $OSS_FUZZ_BUILD_DIR failed" +cd $OSS_FUZZ_BUILD_DIR || fatal "cd $OSS_FUZZ_BUILD_DIR failed" + + +if [ -z ${OUT+x} ]; then + DEST_DIR=$(realpath "./DEST_DIR") +else + DEST_DIR=$OUT +fi + +mkdir -p "$DEST_DIR/lib/" # Copy the shared libraries here + +# Build once to get the list of dynamic lib paths, and copy them over +../configure --disable-werror --cc="$CC" --cxx="$CXX" --enable-fuzzing \ + --prefix="$DEST_DIR" --bindir="$DEST_DIR" --datadir="$DEST_DIR/data/" \ + --extra-cflags="$EXTRA_CFLAGS" --target-list="i386-softmmu" + +if ! make "-j$(nproc)" qemu-fuzz-i386; then + fatal "Build failed. Please specify a compiler with fuzzing support"\ + "using the \$CC and \$CXX environment variables"\ + "\nFor example: CC=clang CXX=clang++ $0" +fi + +for i in $(ldd ./qemu-fuzz-i386 | cut -f3 -d' '); do + cp "$i" "$DEST_DIR/lib/" +done +rm qemu-fuzz-i386 + +# Build a second time to build the final binary with correct rpath +../configure --disable-werror --cc="$CC" --cxx="$CXX" --enable-fuzzing \ + --prefix="$DEST_DIR" --bindir="$DEST_DIR" --datadir="$DEST_DIR/data/" \ + --extra-cflags="$EXTRA_CFLAGS" --extra-ldflags="-Wl,-rpath,\$ORIGIN/lib" \ + --target-list="i386-softmmu" +make "-j$(nproc)" qemu-fuzz-i386 V=1 + +# Copy over the datadir +cp -r ../pc-bios/ "$DEST_DIR/pc-bios" + +targets=$(./qemu-fuzz-i386 | awk '$1 ~ /\*/ {print $2}') +base_copy="$DEST_DIR/qemu-fuzz-i386-target-$(echo "$targets" | head -n 1)" + +cp "./qemu-fuzz-i386" "$base_copy" + +# Run the fuzzer with no arguments, to print the help-string and get the list +# of available fuzz-targets. Copy over the qemu-fuzz-i386, naming it according +# to each available fuzz target (See 05509c8e6d fuzz: select fuzz target using +# executable name) +for target in $(echo "$targets" | tail -n +2); +do + # Ignore the generic-fuzz target, as it requires some environment variables + # to be configured. We have some generic-fuzz-{pc-q35, floppy, ...} targets + # that are thin wrappers around this target that set the required + # environment variables according to predefined configs. + if [ "$target" != "generic-fuzz" ]; then + ln $base_copy \ + "$DEST_DIR/qemu-fuzz-i386-target-$target" + fi +done + +echo "Done. The fuzzers are located in $DEST_DIR" +exit 0 diff --git a/scripts/oss-fuzz/minimize_qtest_trace.py b/scripts/oss-fuzz/minimize_qtest_trace.py new file mode 100755 index 0000000000000000000000000000000000000000..5e405a0d5f0a9452255472fb391dbc225ff51c8a --- /dev/null +++ b/scripts/oss-fuzz/minimize_qtest_trace.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +This takes a crashing qtest trace and tries to remove superflous operations +""" + +import sys +import os +import subprocess +import time +import struct + +QEMU_ARGS = None +QEMU_PATH = None +TIMEOUT = 5 +CRASH_TOKEN = None + +write_suffix_lookup = {"b": (1, "B"), + "w": (2, "H"), + "l": (4, "L"), + "q": (8, "Q")} + +def usage(): + sys.exit("""\ +Usage: QEMU_PATH="/path/to/qemu" QEMU_ARGS="args" {} input_trace output_trace +By default, will try to use the second-to-last line in the output to identify +whether the crash occred. Optionally, manually set a string that idenitifes the +crash by setting CRASH_TOKEN= +""".format((sys.argv[0]))) + +def check_if_trace_crashes(trace, path): + global CRASH_TOKEN + with open(path, "w") as tracefile: + tracefile.write("".join(trace)) + + rc = subprocess.Popen("timeout -s 9 {timeout}s {qemu_path} {qemu_args} 2>&1\ + < {trace_path}".format(timeout=TIMEOUT, + qemu_path=QEMU_PATH, + qemu_args=QEMU_ARGS, + trace_path=path), + shell=True, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE) + stdo = rc.communicate()[0] + output = stdo.decode('unicode_escape') + if rc.returncode == 137: # Timed Out + return False + if len(output.splitlines()) < 2: + return False + + if CRASH_TOKEN is None: + CRASH_TOKEN = output.splitlines()[-2] + + return CRASH_TOKEN in output + + +def minimize_trace(inpath, outpath): + global TIMEOUT + with open(inpath) as f: + trace = f.readlines() + start = time.time() + if not check_if_trace_crashes(trace, outpath): + sys.exit("The input qtest trace didn't cause a crash...") + end = time.time() + print("Crashed in {} seconds".format(end-start)) + TIMEOUT = (end-start)*5 + print("Setting the timeout for {} seconds".format(TIMEOUT)) + print("Identifying Crashes by this string: {}".format(CRASH_TOKEN)) + + i = 0 + newtrace = trace[:] + # For each line + while i < len(newtrace): + # 1.) Try to remove it completely and reproduce the crash. If it works, + # we're done. + prior = newtrace[i] + print("Trying to remove {}".format(newtrace[i])) + # Try to remove the line completely + newtrace[i] = "" + if check_if_trace_crashes(newtrace, outpath): + i += 1 + continue + newtrace[i] = prior + + # 2.) Try to replace write{bwlq} commands with a write addr, len + # command. Since this can require swapping endianness, try both LE and + # BE options. We do this, so we can "trim" the writes in (3) + if (newtrace[i].startswith("write") and not + newtrace[i].startswith("write ")): + suffix = newtrace[i].split()[0][-1] + assert(suffix in write_suffix_lookup) + addr = int(newtrace[i].split()[1], 16) + value = int(newtrace[i].split()[2], 16) + for endianness in ['<', '>']: + data = struct.pack("{end}{size}".format(end=endianness, + size=write_suffix_lookup[suffix][1]), + value) + newtrace[i] = "write {addr} {size} 0x{data}\n".format( + addr=hex(addr), + size=hex(write_suffix_lookup[suffix][0]), + data=data.hex()) + if(check_if_trace_crashes(newtrace, outpath)): + break + else: + newtrace[i] = prior + + # 3.) If it is a qtest write command: write addr len data, try to split + # it into two separate write commands. If splitting the write down the + # middle does not work, try to move the pivot "left" and retry, until + # there is no space left. The idea is to prune unneccessary bytes from + # long writes, while accommodating arbitrary MemoryRegion access sizes + # and alignments. + if newtrace[i].startswith("write "): + addr = int(newtrace[i].split()[1], 16) + length = int(newtrace[i].split()[2], 16) + data = newtrace[i].split()[3][2:] + if length > 1: + leftlength = int(length/2) + rightlength = length - leftlength + newtrace.insert(i+1, "") + while leftlength > 0: + newtrace[i] = "write {addr} {size} 0x{data}\n".format( + addr=hex(addr), + size=hex(leftlength), + data=data[:leftlength*2]) + newtrace[i+1] = "write {addr} {size} 0x{data}\n".format( + addr=hex(addr+leftlength), + size=hex(rightlength), + data=data[leftlength*2:]) + if check_if_trace_crashes(newtrace, outpath): + break + else: + leftlength -= 1 + rightlength += 1 + if check_if_trace_crashes(newtrace, outpath): + i -= 1 + else: + newtrace[i] = prior + del newtrace[i+1] + i += 1 + check_if_trace_crashes(newtrace, outpath) + + +if __name__ == '__main__': + if len(sys.argv) < 3: + usage() + + QEMU_PATH = os.getenv("QEMU_PATH") + QEMU_ARGS = os.getenv("QEMU_ARGS") + if QEMU_PATH is None or QEMU_ARGS is None: + usage() + # if "accel" not in QEMU_ARGS: + # QEMU_ARGS += " -accel qtest" + CRASH_TOKEN = os.getenv("CRASH_TOKEN") + QEMU_ARGS += " -qtest stdio -monitor none -serial none " + minimize_trace(sys.argv[1], sys.argv[2]) diff --git a/scripts/oss-fuzz/reorder_fuzzer_qtest_trace.py b/scripts/oss-fuzz/reorder_fuzzer_qtest_trace.py new file mode 100755 index 0000000000000000000000000000000000000000..890e1def856bfe9db2d37a9e334550e41f9dde07 --- /dev/null +++ b/scripts/oss-fuzz/reorder_fuzzer_qtest_trace.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +Use this to convert qtest log info from a generic fuzzer input into a qtest +trace that you can feed into a standard qemu-system process. Example usage: + +QEMU_FUZZ_ARGS="-machine q35,accel=qtest" QEMU_FUZZ_OBJECTS="*" \ + ./i386-softmmu/qemu-fuzz-i386 --fuzz-target=generic-pci-fuzz +# .. Finds some crash +QTEST_LOG=1 FUZZ_SERIALIZE_QTEST=1 \ +QEMU_FUZZ_ARGS="-machine q35,accel=qtest" QEMU_FUZZ_OBJECTS="*" \ + ./i386-softmmu/qemu-fuzz-i386 --fuzz-target=generic-pci-fuzz + /path/to/crash 2> qtest_log_output +scripts/oss-fuzz/reorder_fuzzer_qtest_trace.py qtest_log_output > qtest_trace +./i386-softmmu/qemu-fuzz-i386 -machine q35,accel=qtest \ + -qtest stdin < qtest_trace + +### Details ### + +Some fuzzer make use of hooks that allow us to populate some memory range, just +before a DMA read from that range. This means that the fuzzer can produce +activity that looks like: + [start] read from mmio addr + [end] read from mmio addr + [start] write to pio addr + [start] fill a DMA buffer just in time + [end] fill a DMA buffer just in time + [start] fill a DMA buffer just in time + [end] fill a DMA buffer just in time + [end] write to pio addr + [start] read from mmio addr + [end] read from mmio addr + +We annotate these "nested" DMA writes, so with QTEST_LOG=1 the QTest trace +might look something like: +[R +0.028431] readw 0x10000 +[R +0.028434] outl 0xc000 0xbeef # Triggers a DMA read from 0xbeef and 0xbf00 +[DMA][R +0.034639] write 0xbeef 0x2 0xAAAA +[DMA][R +0.034639] write 0xbf00 0x2 0xBBBB +[R +0.028431] readw 0xfc000 + +This script would reorder the above trace so it becomes: +readw 0x10000 +write 0xbeef 0x2 0xAAAA +write 0xbf00 0x2 0xBBBB +outl 0xc000 0xbeef +readw 0xfc000 + +I.e. by the time, 0xc000 tries to read from DMA, those DMA buffers have already +been set up, removing the need for the DMA hooks. We can simply provide this +reordered trace via -qtest stdio to reproduce the input + +Note: this won't work for traces where the device tries to read from the same +DMA region twice in between MMIO/PIO commands. E.g: + [R +0.028434] outl 0xc000 0xbeef + [DMA][R +0.034639] write 0xbeef 0x2 0xAAAA + [DMA][R +0.034639] write 0xbeef 0x2 0xBBBB + +The fuzzer will annotate suspected double-fetches with [DOUBLE-FETCH]. This +script looks for these tags and warns the users that the resulting trace might +not reproduce the bug. +""" + +import sys + +__author__ = "Alexander Bulekov " +__copyright__ = "Copyright (C) 2020, Red Hat, Inc." +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Alexander Bulekov" +__email__ = "alxndr@bu.edu" + + +def usage(): + sys.exit("Usage: {} /path/to/qtest_log_output".format((sys.argv[0]))) + + +def main(filename): + with open(filename, "r") as f: + trace = f.readlines() + + # Leave only lines that look like logged qtest commands + trace[:] = [x.strip() for x in trace if "[R +" in x + or "[S +" in x and "CLOSED" not in x] + + for i in range(len(trace)): + if i+1 < len(trace): + if "[DMA]" in trace[i+1]: + if "[DOUBLE-FETCH]" in trace[i+1]: + sys.stderr.write("Warning: Likely double fetch on line" + "{}.\n There will likely be problems " + "reproducing behavior with the " + "resulting qtest trace\n\n".format(i+1)) + trace[i], trace[i+1] = trace[i+1], trace[i] + for line in trace: + print(line.split("]")[-1].strip()) + + +if __name__ == '__main__': + if len(sys.argv) == 1: + usage() + main(sys.argv[1]) diff --git a/scripts/performance/dissect.py b/scripts/performance/dissect.py new file mode 100755 index 0000000000000000000000000000000000000000..bf24f5092254ffee900bdfa7f2b3cf808da6402b --- /dev/null +++ b/scripts/performance/dissect.py @@ -0,0 +1,166 @@ +#!/usr/bin/env python3 + +# Print the percentage of instructions spent in each phase of QEMU +# execution. +# +# Syntax: +# dissect.py [-h] -- [] \ +# [] +# +# [-h] - Print the script arguments help message. +# +# Example of usage: +# dissect.py -- qemu-arm coulomb_double-arm +# +# This file is a part of the project "TCG Continuous Benchmarking". +# +# Copyright (C) 2020 Ahmed Karaman +# Copyright (C) 2020 Aleksandar Markovic +# +# 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 . + +import argparse +import os +import subprocess +import sys +import tempfile + + +def get_JIT_line(callgrind_data): + """ + Search for the first instance of the JIT call in + the callgrind_annotate output when ran using --tree=caller + This is equivalent to the self number of instructions of JIT. + + Parameters: + callgrind_data (list): callgrind_annotate output + + Returns: + (int): Line number + """ + line = -1 + for i in range(len(callgrind_data)): + if callgrind_data[i].strip('\n') and \ + callgrind_data[i].split()[-1] == "[???]": + line = i + break + if line == -1: + sys.exit("Couldn't locate the JIT call ... Exiting.") + return line + + +def main(): + # Parse the command line arguments + parser = argparse.ArgumentParser( + usage='dissect.py [-h] -- ' + ' [] ' + ' []') + + parser.add_argument('command', type=str, nargs='+', help=argparse.SUPPRESS) + + args = parser.parse_args() + + # Extract the needed variables from the args + command = args.command + + # Insure that valgrind is installed + check_valgrind = subprocess.run( + ["which", "valgrind"], stdout=subprocess.DEVNULL) + if check_valgrind.returncode: + sys.exit("Please install valgrind before running the script.") + + # Save all intermediate files in a temporary directory + with tempfile.TemporaryDirectory() as tmpdirname: + # callgrind output file path + data_path = os.path.join(tmpdirname, "callgrind.data") + # callgrind_annotate output file path + annotate_out_path = os.path.join(tmpdirname, "callgrind_annotate.out") + + # Run callgrind + callgrind = subprocess.run((["valgrind", + "--tool=callgrind", + "--callgrind-out-file=" + data_path] + + command), + stdout=subprocess.DEVNULL, + stderr=subprocess.PIPE) + if callgrind.returncode: + sys.exit(callgrind.stderr.decode("utf-8")) + + # Save callgrind_annotate output + with open(annotate_out_path, "w") as output: + callgrind_annotate = subprocess.run( + ["callgrind_annotate", data_path, "--tree=caller"], + stdout=output, + stderr=subprocess.PIPE) + if callgrind_annotate.returncode: + sys.exit(callgrind_annotate.stderr.decode("utf-8")) + + # Read the callgrind_annotate output to callgrind_data[] + callgrind_data = [] + with open(annotate_out_path, 'r') as data: + callgrind_data = data.readlines() + + # Line number with the total number of instructions + total_instructions_line_number = 20 + # Get the total number of instructions + total_instructions_line_data = \ + callgrind_data[total_instructions_line_number] + total_instructions = total_instructions_line_data.split()[0] + total_instructions = int(total_instructions.replace(',', '')) + + # Line number with the JIT self number of instructions + JIT_self_instructions_line_number = get_JIT_line(callgrind_data) + # Get the JIT self number of instructions + JIT_self_instructions_line_data = \ + callgrind_data[JIT_self_instructions_line_number] + JIT_self_instructions = JIT_self_instructions_line_data.split()[0] + JIT_self_instructions = int(JIT_self_instructions.replace(',', '')) + + # Line number with the JIT self + inclusive number of instructions + # It's the line above the first JIT call when running with --tree=caller + JIT_total_instructions_line_number = JIT_self_instructions_line_number-1 + # Get the JIT self + inclusive number of instructions + JIT_total_instructions_line_data = \ + callgrind_data[JIT_total_instructions_line_number] + JIT_total_instructions = JIT_total_instructions_line_data.split()[0] + JIT_total_instructions = int(JIT_total_instructions.replace(',', '')) + + # Calculate number of instructions in helpers and code generation + helpers_instructions = JIT_total_instructions-JIT_self_instructions + code_generation_instructions = total_instructions-JIT_total_instructions + + # Print results (Insert commas in large numbers) + # Print total number of instructions + print('{:<20}{:>20}\n'. + format("Total Instructions:", + format(total_instructions, ','))) + # Print code generation instructions and percentage + print('{:<20}{:>20}\t{:>6.3f}%'. + format("Code Generation:", + format(code_generation_instructions, ","), + (code_generation_instructions / total_instructions) * 100)) + # Print JIT instructions and percentage + print('{:<20}{:>20}\t{:>6.3f}%'. + format("JIT Execution:", + format(JIT_self_instructions, ","), + (JIT_self_instructions / total_instructions) * 100)) + # Print helpers instructions and percentage + print('{:<20}{:>20}\t{:>6.3f}%'. + format("Helpers:", + format(helpers_instructions, ","), + (helpers_instructions/total_instructions)*100)) + + +if __name__ == "__main__": + main() diff --git a/scripts/performance/topN_callgrind.py b/scripts/performance/topN_callgrind.py new file mode 100755 index 0000000000000000000000000000000000000000..67c59197af7c37947f3192d89d8dacda0c403b2f --- /dev/null +++ b/scripts/performance/topN_callgrind.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 + +# Print the top N most executed functions in QEMU using callgrind. +# Syntax: +# topN_callgrind.py [-h] [-n] -- \ +# [] \ +# [] +# +# [-h] - Print the script arguments help message. +# [-n] - Specify the number of top functions to print. +# - If this flag is not specified, the tool defaults to 25. +# +# Example of usage: +# topN_callgrind.py -n 20 -- qemu-arm coulomb_double-arm +# +# This file is a part of the project "TCG Continuous Benchmarking". +# +# Copyright (C) 2020 Ahmed Karaman +# Copyright (C) 2020 Aleksandar Markovic +# +# 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 . + +import argparse +import os +import subprocess +import sys + + +# Parse the command line arguments +parser = argparse.ArgumentParser( + usage='topN_callgrind.py [-h] [-n] -- ' + ' [] ' + ' []') + +parser.add_argument('-n', dest='top', type=int, default=25, + help='Specify the number of top functions to print.') + +parser.add_argument('command', type=str, nargs='+', help=argparse.SUPPRESS) + +args = parser.parse_args() + +# Extract the needed variables from the args +command = args.command +top = args.top + +# Insure that valgrind is installed +check_valgrind_presence = subprocess.run(["which", "valgrind"], + stdout=subprocess.DEVNULL) +if check_valgrind_presence.returncode: + sys.exit("Please install valgrind before running the script!") + +# Run callgrind +callgrind = subprocess.run(( + ["valgrind", "--tool=callgrind", "--callgrind-out-file=/tmp/callgrind.data"] + + command), + stdout=subprocess.DEVNULL, + stderr=subprocess.PIPE) +if callgrind.returncode: + sys.exit(callgrind.stderr.decode("utf-8")) + +# Save callgrind_annotate output to /tmp/callgrind_annotate.out +with open("/tmp/callgrind_annotate.out", "w") as output: + callgrind_annotate = subprocess.run(["callgrind_annotate", + "/tmp/callgrind.data"], + stdout=output, + stderr=subprocess.PIPE) + if callgrind_annotate.returncode: + os.unlink('/tmp/callgrind.data') + output.close() + os.unlink('/tmp/callgrind_annotate.out') + sys.exit(callgrind_annotate.stderr.decode("utf-8")) + +# Read the callgrind_annotate output to callgrind_data[] +callgrind_data = [] +with open('/tmp/callgrind_annotate.out', 'r') as data: + callgrind_data = data.readlines() + +# Line number with the total number of instructions +total_instructions_line_number = 20 + +# Get the total number of instructions +total_instructions_line_data = callgrind_data[total_instructions_line_number] +total_number_of_instructions = total_instructions_line_data.split(' ')[0] +total_number_of_instructions = int( + total_number_of_instructions.replace(',', '')) + +# Line number with the top function +first_func_line = 25 + +# Number of functions recorded by callgrind, last two lines are always empty +number_of_functions = len(callgrind_data) - first_func_line - 2 + +# Limit the number of top functions to "top" +number_of_top_functions = (top if number_of_functions > + top else number_of_functions) + +# Store the data of the top functions in top_functions[] +top_functions = callgrind_data[first_func_line: + first_func_line + number_of_top_functions] + +# Print table header +print('{:>4} {:>10} {:<30} {}\n{} {} {} {}'.format('No.', + 'Percentage', + 'Function Name', + 'Source File', + '-' * 4, + '-' * 10, + '-' * 30, + '-' * 30, + )) + +# Print top N functions +for (index, function) in enumerate(top_functions, start=1): + function_data = function.split() + # Calculate function percentage + function_instructions = float(function_data[0].replace(',', '')) + function_percentage = (function_instructions / + total_number_of_instructions)*100 + # Get function name and source files path + function_source_file, function_name = function_data[1].split(':') + # Print extracted data + print('{:>4} {:>9.3f}% {:<30} {}'.format(index, + round(function_percentage, 3), + function_name, + function_source_file)) + +# Remove intermediate files +os.unlink('/tmp/callgrind.data') +os.unlink('/tmp/callgrind_annotate.out') diff --git a/scripts/performance/topN_perf.py b/scripts/performance/topN_perf.py new file mode 100755 index 0000000000000000000000000000000000000000..07be195fc86773f64d13a85e828c491c2417bc80 --- /dev/null +++ b/scripts/performance/topN_perf.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python3 + +# Print the top N most executed functions in QEMU using perf. +# Syntax: +# topN_perf.py [-h] [-n] -- \ +# [] \ +# [] +# +# [-h] - Print the script arguments help message. +# [-n] - Specify the number of top functions to print. +# - If this flag is not specified, the tool defaults to 25. +# +# Example of usage: +# topN_perf.py -n 20 -- qemu-arm coulomb_double-arm +# +# This file is a part of the project "TCG Continuous Benchmarking". +# +# Copyright (C) 2020 Ahmed Karaman +# Copyright (C) 2020 Aleksandar Markovic +# +# 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 . + +import argparse +import os +import subprocess +import sys + + +# Parse the command line arguments +parser = argparse.ArgumentParser( + usage='topN_perf.py [-h] [-n] -- ' + ' [] ' + ' []') + +parser.add_argument('-n', dest='top', type=int, default=25, + help='Specify the number of top functions to print.') + +parser.add_argument('command', type=str, nargs='+', help=argparse.SUPPRESS) + +args = parser.parse_args() + +# Extract the needed variables from the args +command = args.command +top = args.top + +# Insure that perf is installed +check_perf_presence = subprocess.run(["which", "perf"], + stdout=subprocess.DEVNULL) +if check_perf_presence.returncode: + sys.exit("Please install perf before running the script!") + +# Insure user has previllage to run perf +check_perf_executability = subprocess.run(["perf", "stat", "ls", "/"], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) +if check_perf_executability.returncode: + sys.exit( +""" +Error: +You may not have permission to collect stats. + +Consider tweaking /proc/sys/kernel/perf_event_paranoid, +which controls use of the performance events system by +unprivileged users (without CAP_SYS_ADMIN). + + -1: Allow use of (almost) all events by all users + Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK + 0: Disallow ftrace function tracepoint by users without CAP_SYS_ADMIN + Disallow raw tracepoint access by users without CAP_SYS_ADMIN + 1: Disallow CPU event access by users without CAP_SYS_ADMIN + 2: Disallow kernel profiling by users without CAP_SYS_ADMIN + +To make this setting permanent, edit /etc/sysctl.conf too, e.g.: + kernel.perf_event_paranoid = -1 + +* Alternatively, you can run this script under sudo privileges. +""" +) + +# Run perf record +perf_record = subprocess.run((["perf", "record", "--output=/tmp/perf.data"] + + command), + stdout=subprocess.DEVNULL, + stderr=subprocess.PIPE) +if perf_record.returncode: + os.unlink('/tmp/perf.data') + sys.exit(perf_record.stderr.decode("utf-8")) + +# Save perf report output to /tmp/perf_report.out +with open("/tmp/perf_report.out", "w") as output: + perf_report = subprocess.run( + ["perf", "report", "--input=/tmp/perf.data", "--stdio"], + stdout=output, + stderr=subprocess.PIPE) + if perf_report.returncode: + os.unlink('/tmp/perf.data') + output.close() + os.unlink('/tmp/perf_report.out') + sys.exit(perf_report.stderr.decode("utf-8")) + +# Read the reported data to functions[] +functions = [] +with open("/tmp/perf_report.out", "r") as data: + # Only read lines that are not comments (comments start with #) + # Only read lines that are not empty + functions = [line for line in data.readlines() if line and line[0] + != '#' and line[0] != "\n"] + +# Limit the number of top functions to "top" +number_of_top_functions = top if len(functions) > top else len(functions) + +# Store the data of the top functions in top_functions[] +top_functions = functions[:number_of_top_functions] + +# Print table header +print('{:>4} {:>10} {:<30} {}\n{} {} {} {}'.format('No.', + 'Percentage', + 'Name', + 'Invoked by', + '-' * 4, + '-' * 10, + '-' * 30, + '-' * 25)) + +# Print top N functions +for (index, function) in enumerate(top_functions, start=1): + function_data = function.split() + function_percentage = function_data[0] + function_name = function_data[-1] + function_invoker = ' '.join(function_data[2:-2]) + print('{:>4} {:>10} {:<30} {}'.format(index, + function_percentage, + function_name, + function_invoker)) + +# Remove intermediate files +os.unlink('/tmp/perf.data') +os.unlink('/tmp/perf_report.out') diff --git a/scripts/qapi-gen.py b/scripts/qapi-gen.py old mode 100755 new mode 100644 index 4b03f7d53be73bdb43a4d92fe0333d916e4ef7b8..f3518d29a549ba5eff05186ad0c9720c6c11edfc --- a/scripts/qapi-gen.py +++ b/scripts/qapi-gen.py @@ -1,58 +1,19 @@ #!/usr/bin/env python3 -# QAPI generator -# + # This work is licensed under the terms of the GNU GPL, version 2 or later. # See the COPYING file in the top-level directory. +""" +QAPI code generation execution shim. -import argparse -import re -import sys - -from qapi.commands import gen_commands -from qapi.doc import gen_doc -from qapi.events import gen_events -from qapi.introspect import gen_introspect -from qapi.schema import QAPIError, QAPISchema -from qapi.types import gen_types -from qapi.visit import gen_visit - +This standalone script exists primarily to facilitate the running of the QAPI +code generator without needing to install the python module to the current +execution environment. +""" -def main(argv): - parser = argparse.ArgumentParser( - description='Generate code from a QAPI schema') - parser.add_argument('-b', '--builtins', action='store_true', - help="generate code for built-in types") - parser.add_argument('-o', '--output-dir', action='store', default='', - help="write output to directory OUTPUT_DIR") - parser.add_argument('-p', '--prefix', action='store', default='', - help="prefix for symbols") - parser.add_argument('-u', '--unmask-non-abi-names', action='store_true', - dest='unmask', - help="expose non-ABI names in introspection") - parser.add_argument('schema', action='store') - args = parser.parse_args() - - match = re.match(r'([A-Za-z_.-][A-Za-z0-9_.-]*)?', args.prefix) - if match.end() != len(args.prefix): - print("%s: 'funny character '%s' in argument of --prefix" - % (sys.argv[0], args.prefix[match.end()]), - file=sys.stderr) - sys.exit(1) - - try: - schema = QAPISchema(args.schema) - except QAPIError as err: - print(err, file=sys.stderr) - exit(1) - - gen_types(schema, args.output_dir, args.prefix, args.builtins) - gen_visit(schema, args.output_dir, args.prefix, args.builtins) - gen_commands(schema, args.output_dir, args.prefix) - gen_events(schema, args.output_dir, args.prefix) - gen_introspect(schema, args.output_dir, args.prefix, args.unmask) - gen_doc(schema, args.output_dir, args.prefix) +import sys +from qapi import main if __name__ == '__main__': - main(sys.argv) + sys.exit(main.main()) diff --git a/scripts/qapi/.flake8 b/scripts/qapi/.flake8 new file mode 100644 index 0000000000000000000000000000000000000000..6b158c68b84a4281ff7e5aadc2e6f84bd0df5198 --- /dev/null +++ b/scripts/qapi/.flake8 @@ -0,0 +1,2 @@ +[flake8] +extend-ignore = E722 # Prefer pylint's bare-except checks to flake8's diff --git a/scripts/qapi/.isort.cfg b/scripts/qapi/.isort.cfg new file mode 100644 index 0000000000000000000000000000000000000000..643caa1fbd672648568d3f4822a2e05796bcbd92 --- /dev/null +++ b/scripts/qapi/.isort.cfg @@ -0,0 +1,7 @@ +[settings] +force_grid_wrap=4 +force_sort_within_sections=True +include_trailing_comma=True +line_length=72 +lines_after_imports=2 +multi_line_output=3 diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index 6809b0fb6e10461d6ef8b7eb827f899ccbdc0c92..50978090b440c302a3348b10324c0bd2aa316452 100644 --- a/scripts/qapi/commands.py +++ b/scripts/qapi/commands.py @@ -13,11 +13,34 @@ See the COPYING file in the top-level directory. """ -from qapi.common import * -from qapi.gen import QAPIGenCCode, QAPISchemaModularCVisitor, ifcontext - - -def gen_command_decl(name, arg_type, boxed, ret_type): +from typing import ( + Dict, + List, + Optional, + Set, +) + +from .common import c_name, mcgen +from .gen import ( + QAPIGenC, + QAPIGenCCode, + QAPISchemaModularCVisitor, + build_params, + ifcontext, +) +from .schema import ( + QAPISchema, + QAPISchemaFeature, + QAPISchemaObjectType, + QAPISchemaType, +) +from .source import QAPISourceInfo + + +def gen_command_decl(name: str, + arg_type: Optional[QAPISchemaObjectType], + boxed: bool, + ret_type: Optional[QAPISchemaType]) -> str: return mcgen(''' %(c_type)s qmp_%(c_name)s(%(params)s); ''', @@ -26,7 +49,10 @@ def gen_command_decl(name, arg_type, boxed, ret_type): params=build_params(arg_type, boxed, 'Error **errp')) -def gen_call(name, arg_type, boxed, ret_type): +def gen_call(name: str, + arg_type: Optional[QAPISchemaObjectType], + boxed: bool, + ret_type: Optional[QAPISchemaType]) -> str: ret = '' argstr = '' @@ -47,6 +73,7 @@ def gen_call(name, arg_type, boxed, ret_type): ret = mcgen(''' %(lhs)sqmp_%(c_name)s(%(args)s&err); + error_propagate(errp, err); ''', c_name=c_name(name), args=argstr, lhs=lhs) if ret_type: @@ -55,26 +82,24 @@ def gen_call(name, arg_type, boxed, ret_type): goto out; } - qmp_marshal_output_%(c_name)s(retval, ret, &err); + qmp_marshal_output_%(c_name)s(retval, ret, errp); ''', c_name=ret_type.c_name()) return ret -def gen_marshal_output(ret_type): +def gen_marshal_output(ret_type: QAPISchemaType) -> str: return mcgen(''' -static void qmp_marshal_output_%(c_name)s(%(c_type)s ret_in, QObject **ret_out, Error **errp) +static void qmp_marshal_output_%(c_name)s(%(c_type)s ret_in, + QObject **ret_out, Error **errp) { - Error *err = NULL; Visitor *v; v = qobject_output_visitor_new(ret_out); - visit_type_%(c_name)s(v, "unused", &ret_in, &err); - if (!err) { + if (visit_type_%(c_name)s(v, "unused", &ret_in, errp)) { visit_complete(v, ret_out); } - error_propagate(errp, err); visit_free(v); v = qapi_dealloc_visitor_new(); visit_type_%(c_name)s(v, "unused", &ret_in, NULL); @@ -84,19 +109,22 @@ def gen_marshal_output(ret_type): c_type=ret_type.c_type(), c_name=ret_type.c_name()) -def build_marshal_proto(name): +def build_marshal_proto(name: str) -> str: return ('void qmp_marshal_%s(QDict *args, QObject **ret, Error **errp)' % c_name(name)) -def gen_marshal_decl(name): +def gen_marshal_decl(name: str) -> str: return mcgen(''' %(proto)s; ''', proto=build_marshal_proto(name)) -def gen_marshal(name, arg_type, boxed, ret_type): +def gen_marshal(name: str, + arg_type: Optional[QAPISchemaObjectType], + boxed: bool, + ret_type: Optional[QAPISchemaType]) -> str: have_args = boxed or (arg_type and not arg_type.is_empty()) ret = mcgen(''' @@ -104,6 +132,7 @@ def gen_marshal(name, arg_type, boxed, ret_type): %(proto)s { Error *err = NULL; + bool ok = false; Visitor *v; ''', proto=build_marshal_proto(name)) @@ -123,28 +152,26 @@ def gen_marshal(name, arg_type, boxed, ret_type): ret += mcgen(''' v = qobject_input_visitor_new(QOBJECT(args)); - visit_start_struct(v, NULL, NULL, 0, &err); - if (err) { + if (!visit_start_struct(v, NULL, NULL, 0, errp)) { goto out; } ''') if have_args: ret += mcgen(''' - visit_type_%(c_arg_type)s_members(v, &arg, &err); - if (!err) { - visit_check_struct(v, &err); + if (visit_type_%(c_arg_type)s_members(v, &arg, errp)) { + ok = visit_check_struct(v, errp); } ''', c_arg_type=arg_type.c_name()) else: ret += mcgen(''' - visit_check_struct(v, &err); + ok = visit_check_struct(v, errp); ''') ret += mcgen(''' visit_end_struct(v, NULL); - if (err) { + if (!ok) { goto out; } ''') @@ -154,7 +181,6 @@ def gen_marshal(name, arg_type, boxed, ret_type): ret += mcgen(''' out: - error_propagate(errp, err); visit_free(v); ''') @@ -180,7 +206,11 @@ def gen_marshal(name, arg_type, boxed, ret_type): return ret -def gen_register_command(name, success_response, allow_oob, allow_preconfig): +def gen_register_command(name: str, + success_response: bool, + allow_oob: bool, + allow_preconfig: bool, + coroutine: bool) -> str: options = [] if not success_response: @@ -189,22 +219,22 @@ def gen_register_command(name, success_response, allow_oob, allow_preconfig): options += ['QCO_ALLOW_OOB'] if allow_preconfig: options += ['QCO_ALLOW_PRECONFIG'] + if coroutine: + options += ['QCO_COROUTINE'] if not options: options = ['QCO_NO_OPTIONS'] - options = " | ".join(options) - ret = mcgen(''' qmp_register_command(cmds, "%(name)s", qmp_marshal_%(c_name)s, %(opts)s); ''', name=name, c_name=c_name(name), - opts=options) + opts=" | ".join(options)) return ret -def gen_registry(registry, prefix): +def gen_registry(registry: str, prefix: str) -> str: ret = mcgen(''' void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds) @@ -221,15 +251,14 @@ def gen_registry(registry, prefix): class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor): - - def __init__(self, prefix): + def __init__(self, prefix: str): super().__init__( prefix, 'qapi-commands', ' * Schema-defined QAPI/QMP commands', None, __doc__) self._regy = QAPIGenCCode(None) - self._visited_ret_types = {} + self._visited_ret_types: Dict[QAPIGenC, Set[QAPISchemaType]] = {} - def _begin_user_module(self, name): + def _begin_user_module(self, name: str) -> None: self._visited_ret_types[self._genc] = set() commands = self._module_basename('qapi-commands', name) types = self._module_basename('qapi-types', name) @@ -253,7 +282,7 @@ def _begin_user_module(self, name): ''', types=types)) - def visit_end(self): + def visit_end(self) -> None: self._add_system_module('init', ' * QAPI Commands initialization') self._genh.add(mcgen(''' #include "qapi/qmp/dispatch.h" @@ -269,9 +298,19 @@ def visit_end(self): prefix=self._prefix)) self._genc.add(gen_registry(self._regy.get_content(), self._prefix)) - def visit_command(self, name, info, ifcond, features, - arg_type, ret_type, gen, success_response, boxed, - allow_oob, allow_preconfig): + def visit_command(self, + name: str, + info: QAPISourceInfo, + ifcond: List[str], + features: List[QAPISchemaFeature], + arg_type: Optional[QAPISchemaObjectType], + ret_type: Optional[QAPISchemaType], + gen: bool, + success_response: bool, + boxed: bool, + allow_oob: bool, + allow_preconfig: bool, + coroutine: bool) -> None: if not gen: return # FIXME: If T is a user-defined type, the user is responsible @@ -289,10 +328,13 @@ def visit_command(self, name, info, ifcond, features, self._genh.add(gen_marshal_decl(name)) self._genc.add(gen_marshal(name, arg_type, boxed, ret_type)) self._regy.add(gen_register_command(name, success_response, - allow_oob, allow_preconfig)) + allow_oob, allow_preconfig, + coroutine)) -def gen_commands(schema, output_dir, prefix): +def gen_commands(schema: QAPISchema, + output_dir: str, + prefix: str) -> None: vis = QAPISchemaGenCommandVisitor(prefix) schema.visit(vis) vis.write(output_dir) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index ba35abea478e1647da077a2699bbf7455cead2f9..11b86beeabe6337ef2e35e78d1a1ac7363175651 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -12,12 +12,28 @@ # See the COPYING file in the top-level directory. import re +from typing import Optional, Sequence -# ENUMName -> ENUM_NAME, EnumName1 -> ENUM_NAME1 -# ENUM_NAME -> ENUM_NAME, ENUM_NAME1 -> ENUM_NAME1, ENUM_Name2 -> ENUM_NAME2 -# ENUM24_Name -> ENUM24_NAME -def camel_to_upper(value): +#: Magic string that gets removed along with all space to its right. +EATSPACE = '\033EATSPACE.' +POINTER_SUFFIX = ' *' + EATSPACE +_C_NAME_TRANS = str.maketrans('.-', '__') + + +def camel_to_upper(value: str) -> str: + """ + Converts CamelCase to CAMEL_CASE. + + Examples:: + + ENUMName -> ENUM_NAME + EnumName1 -> ENUM_NAME1 + ENUM_NAME -> ENUM_NAME + ENUM_NAME1 -> ENUM_NAME1 + ENUM_Name2 -> ENUM_NAME2 + ENUM24_Name -> ENUM24_NAME + """ c_fun_str = c_name(value, False) if value.isupper(): return c_fun_str @@ -25,36 +41,47 @@ def camel_to_upper(value): new_name = '' length = len(c_fun_str) for i in range(length): - c = c_fun_str[i] - # When c is upper and no '_' appears before, do more checks - if c.isupper() and (i > 0) and c_fun_str[i - 1] != '_': + char = c_fun_str[i] + # When char is upper case and no '_' appears before, do more checks + if char.isupper() and (i > 0) and c_fun_str[i - 1] != '_': if i < length - 1 and c_fun_str[i + 1].islower(): new_name += '_' elif c_fun_str[i - 1].isdigit(): new_name += '_' - new_name += c + new_name += char return new_name.lstrip('_').upper() -def c_enum_const(type_name, const_name, prefix=None): +def c_enum_const(type_name: str, + const_name: str, + prefix: Optional[str] = None) -> str: + """ + Generate a C enumeration constant name. + + :param type_name: The name of the enumeration. + :param const_name: The name of this constant. + :param prefix: Optional, prefix that overrides the type_name. + """ if prefix is not None: type_name = prefix return camel_to_upper(type_name) + '_' + c_name(const_name, False).upper() -c_name_trans = str.maketrans('.-', '__') +def c_name(name: str, protect: bool = True) -> str: + """ + Map ``name`` to a valid C identifier. + Used for converting 'name' from a 'name':'type' qapi definition + into a generated struct member, as well as converting type names + into substrings of a generated C function name. -# Map @name to a valid C identifier. -# If @protect, avoid returning certain ticklish identifiers (like -# C keywords) by prepending 'q_'. -# -# Used for converting 'name' from a 'name':'type' qapi definition -# into a generated struct member, as well as converting type names -# into substrings of a generated C function name. -# '__a.b_c' -> '__a_b_c', 'x-foo' -> 'x_foo' -# protect=True: 'int' -> 'q_int'; protect=False: 'int' -> 'int' -def c_name(name, protect=True): + '__a.b_c' -> '__a_b_c', 'x-foo' -> 'x_foo' + protect=True: 'int' -> 'q_int'; protect=False: 'int' -> 'int' + + :param name: The name to map. + :param protect: If true, avoid returning certain ticklish identifiers + (like C keywords) by prepending ``q_``. + """ # ANSI X3J11/88-090, 3.1.1 c89_words = set(['auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do', 'double', 'else', 'enum', 'extern', @@ -82,61 +109,75 @@ def c_name(name, protect=True): 'not_eq', 'or', 'or_eq', 'xor', 'xor_eq']) # namespace pollution: polluted_words = set(['unix', 'errno', 'mips', 'sparc', 'i386']) - name = name.translate(c_name_trans) + name = name.translate(_C_NAME_TRANS) if protect and (name in c89_words | c99_words | c11_words | gcc_words | cpp_words | polluted_words): return 'q_' + name return name -eatspace = '\033EATSPACE.' -pointer_suffix = ' *' + eatspace +class Indentation: + """ + Indentation level management. + :param initial: Initial number of spaces, default 0. + """ + def __init__(self, initial: int = 0) -> None: + self._level = initial -def genindent(count): - ret = '' - for _ in range(count): - ret += ' ' - return ret + def __int__(self) -> int: + return self._level + + def __repr__(self) -> str: + return "{}({:d})".format(type(self).__name__, self._level) + + def __str__(self) -> str: + """Return the current indentation as a string of spaces.""" + return ' ' * self._level + def __bool__(self) -> bool: + """True when there is a non-zero indentation.""" + return bool(self._level) -indent_level = 0 + def increase(self, amount: int = 4) -> None: + """Increase the indentation level by ``amount``, default 4.""" + self._level += amount + def decrease(self, amount: int = 4) -> None: + """Decrease the indentation level by ``amount``, default 4.""" + if self._level < amount: + raise ArithmeticError( + f"Can't remove {amount:d} spaces from {self!r}") + self._level -= amount -def push_indent(indent_amount=4): - global indent_level - indent_level += indent_amount +#: Global, current indent level for code generation. +indent = Indentation() -def pop_indent(indent_amount=4): - global indent_level - indent_level -= indent_amount +def cgen(code: str, **kwds: object) -> str: + """ + Generate ``code`` with ``kwds`` interpolated. -# Generate @code with @kwds interpolated. -# Obey indent_level, and strip eatspace. -def cgen(code, **kwds): + Obey `indent`, and strip `EATSPACE`. + """ raw = code % kwds - if indent_level: - indent = genindent(indent_level) - # re.subn() lacks flags support before Python 2.7, use re.compile() - raw = re.subn(re.compile(r'^(?!(#|$))', re.MULTILINE), - indent, raw) - raw = raw[0] - return re.sub(re.escape(eatspace) + r' *', '', raw) + if indent: + raw = re.sub(r'^(?!(#|$))', str(indent), raw, flags=re.MULTILINE) + return re.sub(re.escape(EATSPACE) + r' *', '', raw) -def mcgen(code, **kwds): +def mcgen(code: str, **kwds: object) -> str: if code[0] == '\n': code = code[1:] return cgen(code, **kwds) -def c_fname(filename): +def c_fname(filename: str) -> str: return re.sub(r'[^A-Za-z0-9_]', '_', filename) -def guardstart(name): +def guardstart(name: str) -> str: return mcgen(''' #ifndef %(name)s #define %(name)s @@ -145,7 +186,7 @@ def guardstart(name): name=c_fname(name).upper()) -def guardend(name): +def guardend(name: str) -> str: return mcgen(''' #endif /* %(name)s */ @@ -153,7 +194,7 @@ def guardend(name): name=c_fname(name).upper()) -def gen_if(ifcond): +def gen_if(ifcond: Sequence[str]) -> str: ret = '' for ifc in ifcond: ret += mcgen(''' @@ -162,31 +203,10 @@ def gen_if(ifcond): return ret -def gen_endif(ifcond): +def gen_endif(ifcond: Sequence[str]) -> str: ret = '' for ifc in reversed(ifcond): ret += mcgen(''' #endif /* %(cond)s */ ''', cond=ifc) return ret - - -def build_params(arg_type, boxed, extra=None): - ret = '' - sep = '' - if boxed: - assert arg_type - ret += '%s arg' % arg_type.c_param_type() - sep = ', ' - elif arg_type: - assert not arg_type.variants - for memb in arg_type.members: - ret += sep - sep = ', ' - if memb.optional: - ret += 'bool has_%s, ' % c_name(memb.name) - ret += '%s %s' % (memb.type.c_param_type(), - c_name(memb.name)) - if extra: - ret += sep + extra - return ret if ret else 'void' diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py deleted file mode 100644 index 92f584edcf15638fff20a8e3cf5b1fa525d5310a..0000000000000000000000000000000000000000 --- a/scripts/qapi/doc.py +++ /dev/null @@ -1,301 +0,0 @@ -# QAPI texi generator -# -# This work is licensed under the terms of the GNU LGPL, version 2+. -# See the COPYING file in the top-level directory. -"""This script produces the documentation of a qapi schema in texinfo format""" - -import re -from qapi.gen import QAPIGenDoc, QAPISchemaVisitor - - -MSG_FMT = """ -@deftypefn {type} {{}} {name} - -{body}{members}{features}{sections} -@end deftypefn - -""".format - -TYPE_FMT = """ -@deftp {{{type}}} {name} - -{body}{members}{features}{sections} -@end deftp - -""".format - -EXAMPLE_FMT = """@example -{code} -@end example -""".format - - -def subst_strong(doc): - """Replaces *foo* by @strong{foo}""" - return re.sub(r'\*([^*\n]+)\*', r'@strong{\1}', doc) - - -def subst_emph(doc): - """Replaces _foo_ by @emph{foo}""" - return re.sub(r'\b_([^_\n]+)_\b', r'@emph{\1}', doc) - - -def subst_vars(doc): - """Replaces @var by @code{var}""" - return re.sub(r'@([\w-]+)', r'@code{\1}', doc) - - -def subst_braces(doc): - """Replaces {} with @{ @}""" - return doc.replace('{', '@{').replace('}', '@}') - - -def texi_example(doc): - """Format @example""" - # TODO: Neglects to escape @ characters. - # We should probably escape them in subst_braces(), and rename the - # function to subst_special() or subs_texi_special(). If we do that, we - # need to delay it until after subst_vars() in texi_format(). - doc = subst_braces(doc).strip('\n') - return EXAMPLE_FMT(code=doc) - - -def texi_format(doc): - """ - Format documentation - - Lines starting with: - - |: generates an @example - - =: generates @section - - ==: generates @subsection - - 1. or 1): generates an @enumerate @item - - */-: generates an @itemize list - """ - ret = '' - doc = subst_braces(doc) - doc = subst_vars(doc) - doc = subst_emph(doc) - doc = subst_strong(doc) - inlist = '' - lastempty = False - for line in doc.split('\n'): - empty = line == '' - - # FIXME: Doing this in a single if / elif chain is - # problematic. For instance, a line without markup terminates - # a list if it follows a blank line (reaches the final elif), - # but a line with some *other* markup, such as a = title - # doesn't. - # - # Make sure to update section "Documentation markup" in - # docs/devel/qapi-code-gen.txt when fixing this. - if line.startswith('| '): - line = EXAMPLE_FMT(code=line[2:]) - elif line.startswith('= '): - line = '@section ' + line[2:] - elif line.startswith('== '): - line = '@subsection ' + line[3:] - elif re.match(r'^([0-9]*\.) ', line): - if not inlist: - ret += '@enumerate\n' - inlist = 'enumerate' - ret += '@item\n' - line = line[line.find(' ')+1:] - elif re.match(r'^[*-] ', line): - if not inlist: - ret += '@itemize %s\n' % {'*': '@bullet', - '-': '@minus'}[line[0]] - inlist = 'itemize' - ret += '@item\n' - line = line[2:] - elif lastempty and inlist: - ret += '@end %s\n\n' % inlist - inlist = '' - - lastempty = empty - ret += line + '\n' - - if inlist: - ret += '@end %s\n\n' % inlist - return ret - - -def texi_body(doc): - """Format the main documentation body""" - return texi_format(doc.body.text) - - -def texi_if(ifcond, prefix='\n', suffix='\n'): - """Format the #if condition""" - if not ifcond: - return '' - return '%s@b{If:} @code{%s}%s' % (prefix, ', '.join(ifcond), suffix) - - -def texi_enum_value(value, desc, suffix): - """Format a table of members item for an enumeration value""" - return '@item @code{%s}\n%s%s' % ( - value.name, desc, texi_if(value.ifcond, prefix='@*')) - - -def texi_member(member, desc, suffix): - """Format a table of members item for an object type member""" - typ = member.type.doc_type() - membertype = ': ' + typ if typ else '' - return '@item @code{%s%s}%s%s\n%s%s' % ( - member.name, membertype, - ' (optional)' if member.optional else '', - suffix, desc, texi_if(member.ifcond, prefix='@*')) - - -def texi_members(doc, what, base=None, variants=None, - member_func=texi_member): - """Format the table of members""" - items = '' - for section in doc.args.values(): - # TODO Drop fallbacks when undocumented members are outlawed - if section.text: - desc = texi_format(section.text) - elif (variants and variants.tag_member == section.member - and not section.member.type.doc_type()): - values = section.member.type.member_names() - members_text = ', '.join(['@t{"%s"}' % v for v in values]) - desc = 'One of ' + members_text + '\n' - else: - desc = 'Not documented\n' - items += member_func(section.member, desc, suffix='') - if base: - items += '@item The members of @code{%s}\n' % base.doc_type() - if variants: - for v in variants.variants: - when = ' when @code{%s} is @t{"%s"}%s' % ( - variants.tag_member.name, v.name, texi_if(v.ifcond, " (", ")")) - if v.type.is_implicit(): - assert not v.type.base and not v.type.variants - for m in v.type.local_members: - items += member_func(m, desc='', suffix=when) - else: - items += '@item The members of @code{%s}%s\n' % ( - v.type.doc_type(), when) - if not items: - return '' - return '\n@b{%s:}\n@table @asis\n%s@end table\n' % (what, items) - - -def texi_arguments(doc, boxed_arg_type): - if boxed_arg_type: - assert not doc.args - return ('\n@b{Arguments:} the members of @code{%s}\n' - % boxed_arg_type.name) - return texi_members(doc, 'Arguments') - - -def texi_features(doc): - """Format the table of features""" - items = '' - for section in doc.features.values(): - desc = texi_format(section.text) - items += '@item @code{%s}\n%s' % (section.name, desc) - if not items: - return '' - return '\n@b{Features:}\n@table @asis\n%s@end table\n' % (items) - - -def texi_sections(doc, ifcond): - """Format additional sections following arguments""" - body = '' - for section in doc.sections: - if section.name: - # prefer @b over @strong, so txt doesn't translate it to *Foo:* - body += '\n@b{%s:}\n' % section.name - if section.name and section.name.startswith('Example'): - body += texi_example(section.text) - else: - body += texi_format(section.text) - body += texi_if(ifcond, suffix='') - return body - - -def texi_type(typ, doc, ifcond, members): - return TYPE_FMT(type=typ, - name=doc.symbol, - body=texi_body(doc), - members=members, - features=texi_features(doc), - sections=texi_sections(doc, ifcond)) - - -def texi_msg(typ, doc, ifcond, members): - return MSG_FMT(type=typ, - name=doc.symbol, - body=texi_body(doc), - members=members, - features=texi_features(doc), - sections=texi_sections(doc, ifcond)) - - -class QAPISchemaGenDocVisitor(QAPISchemaVisitor): - def __init__(self, prefix): - self._prefix = prefix - self._gen = QAPIGenDoc(self._prefix + 'qapi-doc.texi') - self.cur_doc = None - - def write(self, output_dir): - self._gen.write(output_dir) - - def visit_enum_type(self, name, info, ifcond, features, members, prefix): - doc = self.cur_doc - self._gen.add(texi_type('Enum', doc, ifcond, - texi_members(doc, 'Values', - member_func=texi_enum_value))) - - def visit_object_type(self, name, info, ifcond, features, - base, members, variants): - doc = self.cur_doc - if base and base.is_implicit(): - base = None - self._gen.add(texi_type('Object', doc, ifcond, - texi_members(doc, 'Members', base, variants))) - - def visit_alternate_type(self, name, info, ifcond, features, variants): - doc = self.cur_doc - self._gen.add(texi_type('Alternate', doc, ifcond, - texi_members(doc, 'Members'))) - - def visit_command(self, name, info, ifcond, features, - arg_type, ret_type, gen, success_response, boxed, - allow_oob, allow_preconfig): - doc = self.cur_doc - self._gen.add(texi_msg('Command', doc, ifcond, - texi_arguments(doc, - arg_type if boxed else None))) - - def visit_event(self, name, info, ifcond, features, arg_type, boxed): - doc = self.cur_doc - self._gen.add(texi_msg('Event', doc, ifcond, - texi_arguments(doc, - arg_type if boxed else None))) - - def symbol(self, doc, entity): - if self._gen._body: - self._gen.add('\n') - self.cur_doc = doc - entity.visit(self) - self.cur_doc = None - - def freeform(self, doc): - assert not doc.args - if self._gen._body: - self._gen.add('\n') - self._gen.add(texi_body(doc) + texi_sections(doc, None)) - - -def gen_doc(schema, output_dir, prefix): - vis = QAPISchemaGenDocVisitor(prefix) - vis.visit_begin(schema) - for doc in schema.docs: - if doc.symbol: - vis.symbol(doc, schema.lookup_entity(doc.symbol)) - else: - vis.freeform(doc) - vis.write(output_dir) diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py index b544af5a1ce3a1c872391e3a2cc46e43b3eacc96..599f3d1f564bd389110b04506e09f1b4eb49dadb 100644 --- a/scripts/qapi/events.py +++ b/scripts/qapi/events.py @@ -12,19 +12,31 @@ See the COPYING file in the top-level directory. """ -from qapi.common import * -from qapi.gen import QAPISchemaModularCVisitor, ifcontext -from qapi.schema import QAPISchemaEnumMember -from qapi.types import gen_enum, gen_enum_lookup - - -def build_event_send_proto(name, arg_type, boxed): +from typing import List + +from .common import c_enum_const, c_name, mcgen +from .gen import QAPISchemaModularCVisitor, build_params, ifcontext +from .schema import ( + QAPISchema, + QAPISchemaEnumMember, + QAPISchemaFeature, + QAPISchemaObjectType, +) +from .source import QAPISourceInfo +from .types import gen_enum, gen_enum_lookup + + +def build_event_send_proto(name: str, + arg_type: QAPISchemaObjectType, + boxed: bool) -> str: return 'void qapi_event_send_%(c_name)s(%(param)s)' % { 'c_name': c_name(name.lower()), 'param': build_params(arg_type, boxed)} -def gen_event_send_decl(name, arg_type, boxed): +def gen_event_send_decl(name: str, + arg_type: QAPISchemaObjectType, + boxed: bool) -> str: return mcgen(''' %(proto)s; @@ -32,8 +44,12 @@ def gen_event_send_decl(name, arg_type, boxed): proto=build_event_send_proto(name, arg_type, boxed)) -# Declare and initialize an object 'qapi' using parameters from build_params() -def gen_param_var(typ): +def gen_param_var(typ: QAPISchemaObjectType) -> str: + """ + Generate a struct variable holding the event parameters. + + Initialize it with the function arguments defined in `gen_event_send`. + """ assert not typ.variants ret = mcgen(''' %(c_name)s param = { @@ -61,7 +77,11 @@ def gen_param_var(typ): return ret -def gen_event_send(name, arg_type, boxed, event_enum_name, event_emit): +def gen_event_send(name: str, + arg_type: QAPISchemaObjectType, + boxed: bool, + event_enum_name: str, + event_emit: str) -> str: # FIXME: Our declaration of local variables (and of 'errp' in the # parameter list) can collide with exploded members of the event's # data type passed in as parameters. If this collision ever hits in @@ -137,15 +157,15 @@ def gen_event_send(name, arg_type, boxed, event_enum_name, event_emit): class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor): - def __init__(self, prefix): + def __init__(self, prefix: str): super().__init__( prefix, 'qapi-events', ' * Schema-defined QAPI/QMP events', None, __doc__) self._event_enum_name = c_name(prefix + 'QAPIEvent', protect=False) - self._event_enum_members = [] + self._event_enum_members: List[QAPISchemaEnumMember] = [] self._event_emit_name = c_name(prefix + 'qapi_event_emit') - def _begin_user_module(self, name): + def _begin_user_module(self, name: str) -> None: events = self._module_basename('qapi-events', name) types = self._module_basename('qapi-types', name) visit = self._module_basename('qapi-visit', name) @@ -168,7 +188,7 @@ def _begin_user_module(self, name): ''', types=types)) - def visit_end(self): + def visit_end(self) -> None: self._add_system_module('emit', ' * QAPI Events emission') self._genc.preamble_add(mcgen(''' #include "qemu/osdep.h" @@ -189,7 +209,13 @@ def visit_end(self): event_emit=self._event_emit_name, event_enum=self._event_enum_name)) - def visit_event(self, name, info, ifcond, features, arg_type, boxed): + def visit_event(self, + name: str, + info: QAPISourceInfo, + ifcond: List[str], + features: List[QAPISchemaFeature], + arg_type: QAPISchemaObjectType, + boxed: bool) -> None: with ifcontext(ifcond, self._genh, self._genc): self._genh.add(gen_event_send_decl(name, arg_type, boxed)) self._genc.add(gen_event_send(name, arg_type, boxed, @@ -200,7 +226,9 @@ def visit_event(self, name, info, ifcond, features, arg_type, boxed): self._event_enum_members.append(QAPISchemaEnumMember(name, None)) -def gen_events(schema, output_dir, prefix): +def gen_events(schema: QAPISchema, + output_dir: str, + prefix: str) -> None: vis = QAPISchemaGenEventVisitor(prefix) schema.visit(vis) vis.write(output_dir) diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py index 2942520399a25f33a78fd20bc0f79c137db009b9..2fcaaa2497a89e1be3d1fc41d08a182d26d6f202 100644 --- a/scripts/qapi/expr.py +++ b/scripts/qapi/expr.py @@ -14,10 +14,11 @@ # This work is licensed under the terms of the GNU GPL, version 2. # See the COPYING file in the top-level directory. -import re from collections import OrderedDict -from qapi.common import c_name -from qapi.error import QAPISemError +import re + +from .common import c_name +from .error import QAPISemError # Names must be letters, numbers, -, and _. They must start with letter, @@ -88,10 +89,17 @@ def check_flags(expr, info): if key in expr and expr[key] is not False: raise QAPISemError( info, "flag '%s' may only use false value" % key) - for key in ['boxed', 'allow-oob', 'allow-preconfig']: + for key in ['boxed', 'allow-oob', 'allow-preconfig', 'coroutine']: if key in expr and expr[key] is not True: raise QAPISemError( info, "flag '%s' may only use true value" % key) + if 'allow-oob' in expr and 'coroutine' in expr: + # This is not necessarily a fundamental incompatibility, but + # we don't have a use case and the desired semantics isn't + # obvious. The simplest solution is to forbid it until we get + # a use case for it. + raise QAPISemError(info, "flags 'allow-oob' and 'coroutine' " + "are incompatible") def check_if(expr, info, source): @@ -342,7 +350,7 @@ def check_exprs(exprs): ['command'], ['data', 'returns', 'boxed', 'if', 'features', 'gen', 'success-response', 'allow-oob', - 'allow-preconfig']) + 'allow-preconfig', 'coroutine']) normalize_members(expr.get('data')) check_command(expr, info) elif meta == 'event': diff --git a/scripts/qapi/gen.py b/scripts/qapi/gen.py index bf5552a4e7f279c46924120fd157271b24d1c98b..b40f18eee3cdc7f199a67e91ca4718e3bec93579 100644 --- a/scripts/qapi/gen.py +++ b/scripts/qapi/gen.py @@ -2,7 +2,7 @@ # # QAPI code generation # -# Copyright (c) 2018-2019 Red Hat Inc. +# Copyright (c) 2015-2019 Red Hat Inc. # # Authors: # Markus Armbruster @@ -11,39 +11,54 @@ # This work is licensed under the terms of the GNU GPL, version 2. # See the COPYING file in the top-level directory. - -import errno +from contextlib import contextmanager import os import re -from contextlib import contextmanager - -from qapi.common import * -from qapi.schema import QAPISchemaVisitor +from typing import ( + Dict, + Iterator, + List, + Optional, + Tuple, +) + +from .common import ( + c_fname, + c_name, + gen_endif, + gen_if, + guardend, + guardstart, + mcgen, +) +from .schema import QAPISchemaObjectType, QAPISchemaVisitor +from .source import QAPISourceInfo class QAPIGen: - - def __init__(self, fname): + def __init__(self, fname: Optional[str]): self.fname = fname self._preamble = '' self._body = '' - def preamble_add(self, text): + def preamble_add(self, text: str) -> None: self._preamble += text - def add(self, text): + def add(self, text: str) -> None: self._body += text - def get_content(self): + def get_content(self) -> str: return self._top() + self._preamble + self._body + self._bottom() - def _top(self): + def _top(self) -> str: + # pylint: disable=no-self-use return '' - def _bottom(self): + def _bottom(self) -> str: + # pylint: disable=no-self-use return '' - def write(self, output_dir): + def write(self, output_dir: str) -> None: # Include paths starting with ../ are used to reuse modules of the main # schema in specialised schemas. Don't overwrite the files that are # already generated for the main schema. @@ -51,24 +66,22 @@ def write(self, output_dir): return pathname = os.path.join(output_dir, self.fname) odir = os.path.dirname(pathname) + if odir: - try: - os.makedirs(odir) - except os.error as e: - if e.errno != errno.EEXIST: - raise + os.makedirs(odir, exist_ok=True) + + # use os.open for O_CREAT to create and read a non-existant file fd = os.open(pathname, os.O_RDWR | os.O_CREAT, 0o666) - f = open(fd, 'r+', encoding='utf-8') - text = self.get_content() - oldtext = f.read(len(text) + 1) - if text != oldtext: - f.seek(0) - f.truncate(0) - f.write(text) - f.close() + with os.fdopen(fd, 'r+', encoding='utf-8') as fp: + text = self.get_content() + oldtext = fp.read(len(text) + 1) + if text != oldtext: + fp.seek(0) + fp.truncate(0) + fp.write(text) -def _wrap_ifcond(ifcond, before, after): +def _wrap_ifcond(ifcond: List[str], before: str, after: str) -> str: if before == after: return after # suppress empty #if ... #endif @@ -84,41 +97,62 @@ def _wrap_ifcond(ifcond, before, after): return out -class QAPIGenCCode(QAPIGen): +def build_params(arg_type: Optional[QAPISchemaObjectType], + boxed: bool, + extra: Optional[str] = None) -> str: + ret = '' + sep = '' + if boxed: + assert arg_type + ret += '%s arg' % arg_type.c_param_type() + sep = ', ' + elif arg_type: + assert not arg_type.variants + for memb in arg_type.members: + ret += sep + sep = ', ' + if memb.optional: + ret += 'bool has_%s, ' % c_name(memb.name) + ret += '%s %s' % (memb.type.c_param_type(), + c_name(memb.name)) + if extra: + ret += sep + extra + return ret if ret else 'void' - def __init__(self, fname): + +class QAPIGenCCode(QAPIGen): + def __init__(self, fname: Optional[str]): super().__init__(fname) - self._start_if = None + self._start_if: Optional[Tuple[List[str], str, str]] = None - def start_if(self, ifcond): + def start_if(self, ifcond: List[str]) -> None: assert self._start_if is None self._start_if = (ifcond, self._body, self._preamble) - def end_if(self): + def end_if(self) -> None: assert self._start_if self._wrap_ifcond() self._start_if = None - def _wrap_ifcond(self): + def _wrap_ifcond(self) -> None: self._body = _wrap_ifcond(self._start_if[0], self._start_if[1], self._body) self._preamble = _wrap_ifcond(self._start_if[0], self._start_if[2], self._preamble) - def get_content(self): + def get_content(self) -> str: assert self._start_if is None return super().get_content() class QAPIGenC(QAPIGenCCode): - - def __init__(self, fname, blurb, pydoc): + def __init__(self, fname: str, blurb: str, pydoc: str): super().__init__(fname) self._blurb = blurb self._copyright = '\n * '.join(re.findall(r'^Copyright .*', pydoc, re.MULTILINE)) - def _top(self): + def _top(self) -> str: return mcgen(''' /* AUTOMATICALLY GENERATED, DO NOT MODIFY */ @@ -134,7 +168,7 @@ def _top(self): ''', blurb=self._blurb, copyright=self._copyright) - def _bottom(self): + def _bottom(self) -> str: return mcgen(''' /* Dummy declaration to prevent empty .o file */ @@ -144,19 +178,20 @@ def _bottom(self): class QAPIGenH(QAPIGenC): - - def _top(self): + def _top(self) -> str: return super()._top() + guardstart(self.fname) - def _bottom(self): + def _bottom(self) -> str: return guardend(self.fname) @contextmanager -def ifcontext(ifcond, *args): - """A 'with' statement context manager to wrap with start_if()/end_if() +def ifcontext(ifcond: List[str], *args: QAPIGenCCode) -> Iterator[None]: + """ + A with-statement context manager that wraps with `start_if()` / `end_if()`. - *args: any number of QAPIGenCCode + :param ifcond: A list of conditionals, passed to `start_if()`. + :param args: any number of `QAPIGenCCode`. Example:: @@ -178,16 +213,12 @@ def ifcontext(ifcond, *args): arg.end_if() -class QAPIGenDoc(QAPIGen): - - def _top(self): - return (super()._top() - + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n') - - class QAPISchemaMonolithicCVisitor(QAPISchemaVisitor): - - def __init__(self, prefix, what, blurb, pydoc): + def __init__(self, + prefix: str, + what: str, + blurb: str, + pydoc: str): self._prefix = prefix self._what = what self._genc = QAPIGenC(self._prefix + self._what + '.c', @@ -195,38 +226,42 @@ def __init__(self, prefix, what, blurb, pydoc): self._genh = QAPIGenH(self._prefix + self._what + '.h', blurb, pydoc) - def write(self, output_dir): + def write(self, output_dir: str) -> None: self._genc.write(output_dir) self._genh.write(output_dir) class QAPISchemaModularCVisitor(QAPISchemaVisitor): - - def __init__(self, prefix, what, user_blurb, builtin_blurb, pydoc): + def __init__(self, + prefix: str, + what: str, + user_blurb: str, + builtin_blurb: Optional[str], + pydoc: str): self._prefix = prefix self._what = what self._user_blurb = user_blurb self._builtin_blurb = builtin_blurb self._pydoc = pydoc - self._genc = None - self._genh = None - self._module = {} - self._main_module = None + self._genc: Optional[QAPIGenC] = None + self._genh: Optional[QAPIGenH] = None + self._module: Dict[Optional[str], Tuple[QAPIGenC, QAPIGenH]] = {} + self._main_module: Optional[str] = None @staticmethod - def _is_user_module(name): - return name and not name.startswith('./') + def _is_user_module(name: Optional[str]) -> bool: + return bool(name and not name.startswith('./')) @staticmethod - def _is_builtin_module(name): + def _is_builtin_module(name: Optional[str]) -> bool: return not name - def _module_dirname(self, what, name): + def _module_dirname(self, name: Optional[str]) -> str: if self._is_user_module(name): return os.path.dirname(name) return '' - def _module_basename(self, what, name): + def _module_basename(self, what: str, name: Optional[str]) -> str: ret = '' if self._is_builtin_module(name) else self._prefix if self._is_user_module(name): basename = os.path.basename(name) @@ -238,27 +273,27 @@ def _module_basename(self, what, name): ret += re.sub(r'-', '-' + name + '-', what) return ret - def _module_filename(self, what, name): - return os.path.join(self._module_dirname(what, name), + def _module_filename(self, what: str, name: Optional[str]) -> str: + return os.path.join(self._module_dirname(name), self._module_basename(what, name)) - def _add_module(self, name, blurb): + def _add_module(self, name: Optional[str], blurb: str) -> None: basename = self._module_filename(self._what, name) genc = QAPIGenC(basename + '.c', blurb, self._pydoc) genh = QAPIGenH(basename + '.h', blurb, self._pydoc) self._module[name] = (genc, genh) self._genc, self._genh = self._module[name] - def _add_user_module(self, name, blurb): + def _add_user_module(self, name: str, blurb: str) -> None: assert self._is_user_module(name) if self._main_module is None: self._main_module = name self._add_module(name, blurb) - def _add_system_module(self, name, blurb): + def _add_system_module(self, name: Optional[str], blurb: str) -> None: self._add_module(name and './' + name, blurb) - def write(self, output_dir, opt_builtins=False): + def write(self, output_dir: str, opt_builtins: bool = False) -> None: for name in self._module: if self._is_builtin_module(name) and not opt_builtins: continue @@ -266,13 +301,13 @@ def write(self, output_dir, opt_builtins=False): genc.write(output_dir) genh.write(output_dir) - def _begin_system_module(self, name): + def _begin_system_module(self, name: None) -> None: pass - def _begin_user_module(self, name): + def _begin_user_module(self, name: str) -> None: pass - def visit_module(self, name): + def visit_module(self, name: Optional[str]) -> None: if name is None: if self._builtin_blurb: self._add_system_module(None, self._builtin_blurb) @@ -286,7 +321,7 @@ def visit_module(self, name): self._add_user_module(name, self._user_blurb) self._begin_user_module(name) - def visit_include(self, name, info): + def visit_include(self, name: str, info: QAPISourceInfo) -> None: relname = os.path.relpath(self._module_filename(self._what, name), os.path.dirname(self._genh.fname)) self._genh.preamble_add(mcgen(''' diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py index 23652be81023abbd786a8e4d68d08cc7aacc576b..fafec94e0229d5b2d504784d560d1a5465ebf40d 100644 --- a/scripts/qapi/introspect.py +++ b/scripts/qapi/introspect.py @@ -10,10 +10,18 @@ See the COPYING file in the top-level directory. """ -from qapi.common import * -from qapi.gen import QAPISchemaMonolithicCVisitor -from qapi.schema import (QAPISchemaArrayType, QAPISchemaBuiltinType, - QAPISchemaType) +from .common import ( + c_name, + gen_endif, + gen_if, + mcgen, +) +from .gen import QAPISchemaMonolithicCVisitor +from .schema import ( + QAPISchemaArrayType, + QAPISchemaBuiltinType, + QAPISchemaType, +) def _make_tree(obj, ifcond, features, extra=None): @@ -216,7 +224,7 @@ def visit_alternate_type(self, name, info, ifcond, features, variants): def visit_command(self, name, info, ifcond, features, arg_type, ret_type, gen, success_response, boxed, - allow_oob, allow_preconfig): + allow_oob, allow_preconfig, coroutine): arg_type = arg_type or self._schema.the_empty_object_type ret_type = ret_type or self._schema.the_empty_object_type obj = {'arg-type': self._use_type(arg_type), diff --git a/scripts/qapi/main.py b/scripts/qapi/main.py new file mode 100644 index 0000000000000000000000000000000000000000..42517210b80580937bcdd1f3737fac59a0aca868 --- /dev/null +++ b/scripts/qapi/main.py @@ -0,0 +1,95 @@ +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +""" +QAPI Generator + +This is the main entry point for generating C code from the QAPI schema. +""" + +import argparse +import re +import sys +from typing import Optional + +from .commands import gen_commands +from .error import QAPIError +from .events import gen_events +from .introspect import gen_introspect +from .schema import QAPISchema +from .types import gen_types +from .visit import gen_visit + + +def invalid_prefix_char(prefix: str) -> Optional[str]: + match = re.match(r'([A-Za-z_.-][A-Za-z0-9_.-]*)?', prefix) + if match.end() != len(prefix): + return prefix[match.end()] + return None + + +def generate(schema_file: str, + output_dir: str, + prefix: str, + unmask: bool = False, + builtins: bool = False) -> None: + """ + Generate C code for the given schema into the target directory. + + :param schema_file: The primary QAPI schema file. + :param output_dir: The output directory to store generated code. + :param prefix: Optional C-code prefix for symbol names. + :param unmask: Expose non-ABI names through introspection? + :param builtins: Generate code for built-in types? + + :raise QAPIError: On failures. + """ + assert invalid_prefix_char(prefix) is None + + schema = QAPISchema(schema_file) + gen_types(schema, output_dir, prefix, builtins) + gen_visit(schema, output_dir, prefix, builtins) + gen_commands(schema, output_dir, prefix) + gen_events(schema, output_dir, prefix) + gen_introspect(schema, output_dir, prefix, unmask) + + +def main() -> int: + """ + gapi-gen executable entry point. + Expects arguments via sys.argv, see --help for details. + + :return: int, 0 on success, 1 on failure. + """ + parser = argparse.ArgumentParser( + description='Generate code from a QAPI schema') + parser.add_argument('-b', '--builtins', action='store_true', + help="generate code for built-in types") + parser.add_argument('-o', '--output-dir', action='store', + default='', + help="write output to directory OUTPUT_DIR") + parser.add_argument('-p', '--prefix', action='store', + default='', + help="prefix for symbols") + parser.add_argument('-u', '--unmask-non-abi-names', action='store_true', + dest='unmask', + help="expose non-ABI names in introspection") + parser.add_argument('schema', action='store') + args = parser.parse_args() + + funny_char = invalid_prefix_char(args.prefix) + if funny_char: + msg = f"funny character '{funny_char}' in argument of --prefix" + print(f"{sys.argv[0]}: {msg}", file=sys.stderr) + return 1 + + try: + generate(args.schema, + output_dir=args.output_dir, + prefix=args.prefix, + unmask=args.unmask, + builtins=args.builtins) + except QAPIError as err: + print(f"{sys.argv[0]}: {str(err)}", file=sys.stderr) + return 1 + return 0 diff --git a/scripts/qapi/mypy.ini b/scripts/qapi/mypy.ini new file mode 100644 index 0000000000000000000000000000000000000000..74fc6c82153e35d6a3f53c6410660d7e289a78ad --- /dev/null +++ b/scripts/qapi/mypy.ini @@ -0,0 +1,30 @@ +[mypy] +strict = True +strict_optional = False +disallow_untyped_calls = False +python_version = 3.6 + +[mypy-qapi.error] +disallow_untyped_defs = False +disallow_incomplete_defs = False +check_untyped_defs = False + +[mypy-qapi.expr] +disallow_untyped_defs = False +disallow_incomplete_defs = False +check_untyped_defs = False + +[mypy-qapi.introspect] +disallow_untyped_defs = False +disallow_incomplete_defs = False +check_untyped_defs = False + +[mypy-qapi.parser] +disallow_untyped_defs = False +disallow_incomplete_defs = False +check_untyped_defs = False + +[mypy-qapi.schema] +disallow_untyped_defs = False +disallow_incomplete_defs = False +check_untyped_defs = False diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py index abadacbb0e8b43f06e9c5d3e949e1796f0b00751..e7b9d670ad6c154b9ec9250cf4a7312fef603039 100644 --- a/scripts/qapi/parser.py +++ b/scripts/qapi/parser.py @@ -14,12 +14,12 @@ # This work is licensed under the terms of the GNU GPL, version 2. # See the COPYING file in the top-level directory. +from collections import OrderedDict import os import re -from collections import OrderedDict -from qapi.error import QAPIParseError, QAPISemError -from qapi.source import QAPISourceInfo +from .error import QAPIParseError, QAPISemError +from .source import QAPISourceInfo class QAPISchemaParser: @@ -52,8 +52,8 @@ def __init__(self, fname, previously_included=None, incl_info=None): info = self.info if self.tok == '#': self.reject_expr_doc(cur_doc) - cur_doc = self.get_doc(info) - self.docs.append(cur_doc) + for cur_doc in self.get_doc(info): + self.docs.append(cur_doc) continue expr = self.get_expr(False) @@ -270,7 +270,8 @@ def get_doc(self, info): raise QAPIParseError( self, "junk after '##' at start of documentation comment") - doc = QAPIDoc(self, info) + docs = [] + cur_doc = QAPIDoc(self, info) self.accept(False) while self.tok == '#': if self.val.startswith('##'): @@ -279,10 +280,20 @@ def get_doc(self, info): raise QAPIParseError( self, "junk after '##' at end of documentation comment") - doc.end_comment() + cur_doc.end_comment() + docs.append(cur_doc) self.accept() - return doc - doc.append(self.val) + return docs + if self.val.startswith('# ='): + if cur_doc.symbol: + raise QAPIParseError( + self, + "unexpected '=' markup in definition documentation") + if cur_doc.body.text: + cur_doc.end_comment() + docs.append(cur_doc) + cur_doc = QAPIDoc(self, info) + cur_doc.append(self.val) self.accept(False) raise QAPIParseError(self, "documentation comment must end with '##'") @@ -308,18 +319,32 @@ class QAPIDoc: """ class Section: - def __init__(self, name=None): + def __init__(self, parser, name=None, indent=0): + # parser, for error messages about indentation + self._parser = parser # optional section name (argument/member or section name) self.name = name - # the list of lines for this section self.text = '' + # the expected indent level of the text of this section + self._indent = indent def append(self, line): + # Strip leading spaces corresponding to the expected indent level + # Blank lines are always OK. + if line: + indent = re.match(r'\s*', line).end() + if indent < self._indent: + raise QAPIParseError( + self._parser, + "unexpected de-indent (expected at least %d spaces)" % + self._indent) + line = line[self._indent:] + self.text += line.rstrip() + '\n' class ArgSection(Section): - def __init__(self, name): - super().__init__(name) + def __init__(self, parser, name, indent=0): + super().__init__(parser, name, indent) self.member = None def connect(self, member): @@ -333,7 +358,7 @@ def __init__(self, parser, info): self._parser = parser self.info = info self.symbol = None - self.body = QAPIDoc.Section() + self.body = QAPIDoc.Section(parser) # dict mapping parameter name to ArgSection self.args = OrderedDict() self.features = OrderedDict() @@ -417,10 +442,10 @@ def _append_body_line(self, line): self._append_line = self._append_various_line self._append_various_line(line) else: - self._append_freeform(line.strip()) + self._append_freeform(line) else: # This is a free-form documentation block - self._append_freeform(line.strip()) + self._append_freeform(line) def _append_args_line(self, line): """ @@ -437,8 +462,21 @@ def _append_args_line(self, line): name = line.split(' ', 1)[0] if name.startswith('@') and name.endswith(':'): - line = line[len(name)+1:] - self._start_args_section(name[1:-1]) + # If line is "@arg: first line of description", find + # the index of 'f', which is the indent we expect for any + # following lines. We then remove the leading "@arg:" + # from line and replace it with spaces so that 'f' has the + # same index as it did in the original line and can be + # handled the same way we will handle following lines. + indent = re.match(r'@\S*:\s*', line).end() + line = line[indent:] + if not line: + # Line was just the "@arg:" header; following lines + # are not indented + indent = 0 + else: + line = ' ' * indent + line + self._start_args_section(name[1:-1], indent) elif self._is_section_tag(name): self._append_line = self._append_various_line self._append_various_line(line) @@ -453,14 +491,27 @@ def _append_args_line(self, line): self._append_various_line(line) return - self._append_freeform(line.strip()) + self._append_freeform(line) def _append_features_line(self, line): name = line.split(' ', 1)[0] if name.startswith('@') and name.endswith(':'): - line = line[len(name)+1:] - self._start_features_section(name[1:-1]) + # If line is "@arg: first line of description", find + # the index of 'f', which is the indent we expect for any + # following lines. We then remove the leading "@arg:" + # from line and replace it with spaces so that 'f' has the + # same index as it did in the original line and can be + # handled the same way we will handle following lines. + indent = re.match(r'@\S*:\s*', line).end() + line = line[indent:] + if not line: + # Line was just the "@arg:" header; following lines + # are not indented + indent = 0 + else: + line = ' ' * indent + line + self._start_features_section(name[1:-1], indent) elif self._is_section_tag(name): self._append_line = self._append_various_line self._append_various_line(line) @@ -472,7 +523,7 @@ def _append_features_line(self, line): self._append_various_line(line) return - self._append_freeform(line.strip()) + self._append_freeform(line) def _append_various_line(self, line): """ @@ -492,16 +543,25 @@ def _append_various_line(self, line): "'%s' can't follow '%s' section" % (name, self.sections[0].name)) if self._is_section_tag(name): - line = line[len(name)+1:] - self._start_section(name[:-1]) - - if (not self._section.name or - not self._section.name.startswith('Example')): - line = line.strip() + # If line is "Section: first line of description", find + # the index of 'f', which is the indent we expect for any + # following lines. We then remove the leading "Section:" + # from line and replace it with spaces so that 'f' has the + # same index as it did in the original line and can be + # handled the same way we will handle following lines. + indent = re.match(r'\S*:\s*', line).end() + line = line[indent:] + if not line: + # Line was just the "Section:" header; following lines + # are not indented + indent = 0 + else: + line = ' ' * indent + line + self._start_section(name[:-1], indent) self._append_freeform(line) - def _start_symbol_section(self, symbols_dict, name): + def _start_symbol_section(self, symbols_dict, name, indent): # FIXME invalid names other than the empty string aren't flagged if not name: raise QAPIParseError(self._parser, "invalid parameter name") @@ -510,21 +570,21 @@ def _start_symbol_section(self, symbols_dict, name): "'%s' parameter name duplicated" % name) assert not self.sections self._end_section() - self._section = QAPIDoc.ArgSection(name) + self._section = QAPIDoc.ArgSection(self._parser, name, indent) symbols_dict[name] = self._section - def _start_args_section(self, name): - self._start_symbol_section(self.args, name) + def _start_args_section(self, name, indent): + self._start_symbol_section(self.args, name, indent) - def _start_features_section(self, name): - self._start_symbol_section(self.features, name) + def _start_features_section(self, name, indent): + self._start_symbol_section(self.features, name, indent) - def _start_section(self, name=None): + def _start_section(self, name=None, indent=0): if name in ('Returns', 'Since') and self.has_section(name): raise QAPIParseError(self._parser, "duplicated '%s' section" % name) self._end_section() - self._section = QAPIDoc.Section(name) + self._section = QAPIDoc.Section(self._parser, name, indent) self.sections.append(self._section) def _end_section(self): @@ -547,7 +607,8 @@ def _append_freeform(self, line): def connect_member(self, member): if member.name not in self.args: # Undocumented TODO outlaw - self.args[member.name] = QAPIDoc.ArgSection(member.name) + self.args[member.name] = QAPIDoc.ArgSection(self._parser, + member.name) self.args[member.name].connect(member) def connect_feature(self, feature): diff --git a/scripts/qapi/pylintrc b/scripts/qapi/pylintrc new file mode 100644 index 0000000000000000000000000000000000000000..b9e077a1642d10ce6fb7b857b394b812c5ac6dfc --- /dev/null +++ b/scripts/qapi/pylintrc @@ -0,0 +1,70 @@ +[MASTER] + +# Add files or directories matching the regex patterns to the ignore list. +# The regex matches against base names, not paths. +ignore-patterns=error.py, + expr.py, + parser.py, + schema.py, + + +[MESSAGES CONTROL] + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once). You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use "--disable=all --enable=classes +# --disable=W". +disable=fixme, + missing-docstring, + too-many-arguments, + too-many-branches, + too-many-statements, + too-many-instance-attributes, + +[REPORTS] + +[REFACTORING] + +[MISCELLANEOUS] + +[LOGGING] + +[BASIC] + +# Good variable names which should always be accepted, separated by a comma. +good-names=i, + j, + k, + ex, + Run, + _, + fp, # fp = open(...) + fd, # fd = os.open(...) + +[VARIABLES] + +[STRING] + +[SPELLING] + +[FORMAT] + +[SIMILARITIES] + +# Ignore import statements themselves when computing similarities. +ignore-imports=yes + +[TYPECHECK] + +[CLASSES] + +[IMPORTS] + +[DESIGN] + +[EXCEPTIONS] diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py index 78309a00f0a2a8acfac9f038e019ef72d158b3ca..720449feee4d861431b8cdaddd36bf06e6b9f20f 100644 --- a/scripts/qapi/schema.py +++ b/scripts/qapi/schema.py @@ -14,18 +14,19 @@ # TODO catching name collisions in generated code would be nice +from collections import OrderedDict import os import re -from collections import OrderedDict +from typing import Optional -from qapi.common import c_name, pointer_suffix -from qapi.error import QAPIError, QAPISemError -from qapi.expr import check_exprs -from qapi.parser import QAPISchemaParser +from .common import POINTER_SUFFIX, c_name +from .error import QAPIError, QAPISemError +from .expr import check_exprs +from .parser import QAPISchemaParser class QAPISchemaEntity: - meta = None + meta: Optional[str] = None def __init__(self, name, info, doc, ifcond=None, features=None): assert name is None or isinstance(name, str) @@ -128,7 +129,7 @@ def visit_alternate_type(self, name, info, ifcond, features, variants): def visit_command(self, name, info, ifcond, features, arg_type, ret_type, gen, success_response, boxed, - allow_oob, allow_preconfig): + allow_oob, allow_preconfig, coroutine): pass def visit_event(self, name, info, ifcond, features, arg_type, boxed): @@ -309,7 +310,7 @@ def is_implicit(self): return True def c_type(self): - return c_name(self.name) + pointer_suffix + return c_name(self.name) + POINTER_SUFFIX def json_type(self): return 'array' @@ -430,7 +431,7 @@ def c_name(self): def c_type(self): assert not self.is_implicit() - return c_name(self.name) + pointer_suffix + return c_name(self.name) + POINTER_SUFFIX def c_unboxed_type(self): return c_name(self.name) @@ -504,7 +505,7 @@ def connect_doc(self, doc=None): v.connect_doc(doc) def c_type(self): - return c_name(self.name) + pointer_suffix + return c_name(self.name) + POINTER_SUFFIX def json_type(self): return 'value' @@ -536,7 +537,7 @@ def set_defined_in(self, name): v.set_defined_in(name) def check(self, schema, seen): - if not self.tag_member: # flat union + if not self.tag_member: # flat union self.tag_member = seen.get(c_name(self._tag_name)) base = "'base'" # Pointing to the base type when not implicit would be @@ -713,7 +714,8 @@ class QAPISchemaCommand(QAPISchemaEntity): def __init__(self, name, info, doc, ifcond, features, arg_type, ret_type, - gen, success_response, boxed, allow_oob, allow_preconfig): + gen, success_response, boxed, allow_oob, allow_preconfig, + coroutine): super().__init__(name, info, doc, ifcond, features) assert not arg_type or isinstance(arg_type, str) assert not ret_type or isinstance(ret_type, str) @@ -726,6 +728,7 @@ def __init__(self, name, info, doc, ifcond, features, self.boxed = boxed self.allow_oob = allow_oob self.allow_preconfig = allow_preconfig + self.coroutine = coroutine def check(self, schema): super().check(schema) @@ -768,7 +771,8 @@ def visit(self, visitor): visitor.visit_command( self.name, self.info, self.ifcond, self.features, self.arg_type, self.ret_type, self.gen, self.success_response, - self.boxed, self.allow_oob, self.allow_preconfig) + self.boxed, self.allow_oob, self.allow_preconfig, + self.coroutine) class QAPISchemaEvent(QAPISchemaEntity): @@ -821,7 +825,7 @@ def __init__(self, fname): self._entity_dict = {} self._module_dict = OrderedDict() self._schema_dir = os.path.dirname(fname) - self._make_module(None) # built-ins + self._make_module(None) # built-ins self._make_module(fname) self._predefining = True self._def_predefineds() @@ -896,7 +900,7 @@ def _def_builtin_type(self, name, json_type, c_type): self._make_array_type(name, None) def _def_predefineds(self): - for t in [('str', 'string', 'char' + pointer_suffix), + for t in [('str', 'string', 'char' + POINTER_SUFFIX), ('number', 'number', 'double'), ('int', 'int', 'int64_t'), ('int8', 'int', 'int8_t'), @@ -909,8 +913,8 @@ def _def_predefineds(self): ('uint64', 'int', 'uint64_t'), ('size', 'int', 'uint64_t'), ('bool', 'boolean', 'bool'), - ('any', 'value', 'QObject' + pointer_suffix), - ('null', 'null', 'QNull' + pointer_suffix)]: + ('any', 'value', 'QObject' + POINTER_SUFFIX), + ('null', 'null', 'QNull' + POINTER_SUFFIX)]: self._def_builtin_type(*t) self.the_empty_object_type = QAPISchemaObjectType( 'q_empty', None, None, None, None, None, [], None) @@ -965,7 +969,9 @@ def _make_implicit_object_type(self, name, info, ifcond, role, members): # But it's not tight: the disjunction need not imply it. We # may end up compiling useless wrapper types. # TODO kill simple unions or implement the disjunction - assert (ifcond or []) == typ._ifcond # pylint: disable=protected-access + + # pylint: disable=protected-access + assert (ifcond or []) == typ._ifcond else: self._def_entity(QAPISchemaObjectType( name, info, None, ifcond, None, None, members, None)) @@ -1074,6 +1080,7 @@ def _def_command(self, expr, info, doc): boxed = expr.get('boxed', False) allow_oob = expr.get('allow-oob', False) allow_preconfig = expr.get('allow-preconfig', False) + coroutine = expr.get('coroutine', False) ifcond = expr.get('if') features = self._make_features(expr.get('features'), info) if isinstance(data, OrderedDict): @@ -1086,7 +1093,8 @@ def _def_command(self, expr, info, doc): self._def_entity(QAPISchemaCommand(name, info, doc, ifcond, features, data, rets, gen, success_response, - boxed, allow_oob, allow_preconfig)) + boxed, allow_oob, allow_preconfig, + coroutine)) def _def_event(self, expr, info, doc): name = expr['event'] diff --git a/scripts/qapi/source.py b/scripts/qapi/source.py index e97b9a8e15ef8892923d4545c62a521cfb86bfb7..d7a79a9b8aee77cd762fdc1557d4e425a8c6e3d3 100644 --- a/scripts/qapi/source.py +++ b/scripts/qapi/source.py @@ -11,37 +11,46 @@ import copy import sys +from typing import List, Optional, TypeVar class QAPISchemaPragma: - def __init__(self): + # Replace with @dataclass in Python 3.7+ + # pylint: disable=too-few-public-methods + + def __init__(self) -> None: # Are documentation comments required? self.doc_required = False # Whitelist of commands allowed to return a non-dictionary - self.returns_whitelist = [] + self.returns_whitelist: List[str] = [] # Whitelist of entities allowed to violate case conventions - self.name_case_whitelist = [] + self.name_case_whitelist: List[str] = [] class QAPISourceInfo: - def __init__(self, fname, line, parent): + T = TypeVar('T', bound='QAPISourceInfo') + + def __init__(self, fname: str, line: int, + parent: Optional['QAPISourceInfo']): self.fname = fname self.line = line self.parent = parent - self.pragma = parent.pragma if parent else QAPISchemaPragma() - self.defn_meta = None - self.defn_name = None + self.pragma: QAPISchemaPragma = ( + parent.pragma if parent else QAPISchemaPragma() + ) + self.defn_meta: Optional[str] = None + self.defn_name: Optional[str] = None - def set_defn(self, meta, name): + def set_defn(self, meta: str, name: str) -> None: self.defn_meta = meta self.defn_name = name - def next_line(self): + def next_line(self: T) -> T: info = copy.copy(self) info.line += 1 return info - def loc(self): + def loc(self) -> str: if self.fname is None: return sys.argv[0] ret = self.fname @@ -49,13 +58,13 @@ def loc(self): ret += ':%d' % self.line return ret - def in_defn(self): + def in_defn(self) -> str: if self.defn_name: return "%s: In %s '%s':\n" % (self.fname, self.defn_meta, self.defn_name) return '' - def include_path(self): + def include_path(self) -> str: ret = '' parent = self.parent while parent: @@ -63,5 +72,5 @@ def include_path(self): parent = parent.parent return ret - def __str__(self): + def __str__(self) -> str: return self.include_path() + self.in_defn() + self.loc() diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py index 3ad33af4ee3d43886c75a0085956d26afce08953..2b4916cdaa1bdeee46c5387fec20472127f47c3b 100644 --- a/scripts/qapi/types.py +++ b/scripts/qapi/types.py @@ -13,9 +13,26 @@ # See the COPYING file in the top-level directory. """ -from qapi.common import * -from qapi.gen import QAPISchemaModularCVisitor, ifcontext -from qapi.schema import QAPISchemaEnumMember, QAPISchemaObjectType +from typing import List, Optional + +from .common import ( + c_enum_const, + c_name, + gen_endif, + gen_if, + mcgen, +) +from .gen import QAPISchemaModularCVisitor, ifcontext +from .schema import ( + QAPISchema, + QAPISchemaEnumMember, + QAPISchemaFeature, + QAPISchemaObjectType, + QAPISchemaObjectTypeMember, + QAPISchemaType, + QAPISchemaVariants, +) +from .source import QAPISourceInfo # variants must be emitted before their container; track what has already @@ -23,21 +40,23 @@ objects_seen = set() -def gen_enum_lookup(name, members, prefix=None): +def gen_enum_lookup(name: str, + members: List[QAPISchemaEnumMember], + prefix: Optional[str] = None) -> str: ret = mcgen(''' const QEnumLookup %(c_name)s_lookup = { .array = (const char *const[]) { ''', c_name=c_name(name)) - for m in members: - ret += gen_if(m.ifcond) - index = c_enum_const(name, m.name, prefix) + for memb in members: + ret += gen_if(memb.ifcond) + index = c_enum_const(name, memb.name, prefix) ret += mcgen(''' [%(index)s] = "%(name)s", ''', - index=index, name=m.name) - ret += gen_endif(m.ifcond) + index=index, name=memb.name) + ret += gen_endif(memb.ifcond) ret += mcgen(''' }, @@ -48,7 +67,9 @@ def gen_enum_lookup(name, members, prefix=None): return ret -def gen_enum(name, members, prefix=None): +def gen_enum(name: str, + members: List[QAPISchemaEnumMember], + prefix: Optional[str] = None) -> str: # append automatically generated _MAX value enum_members = members + [QAPISchemaEnumMember('_MAX', None)] @@ -58,13 +79,13 @@ def gen_enum(name, members, prefix=None): ''', c_name=c_name(name)) - for m in enum_members: - ret += gen_if(m.ifcond) + for memb in enum_members: + ret += gen_if(memb.ifcond) ret += mcgen(''' %(c_enum)s, ''', - c_enum=c_enum_const(name, m.name, prefix)) - ret += gen_endif(m.ifcond) + c_enum=c_enum_const(name, memb.name, prefix)) + ret += gen_endif(memb.ifcond) ret += mcgen(''' } %(c_name)s; @@ -82,7 +103,7 @@ def gen_enum(name, members, prefix=None): return ret -def gen_fwd_object_or_array(name): +def gen_fwd_object_or_array(name: str) -> str: return mcgen(''' typedef struct %(c_name)s %(c_name)s; @@ -90,7 +111,7 @@ def gen_fwd_object_or_array(name): c_name=c_name(name)) -def gen_array(name, element_type): +def gen_array(name: str, element_type: QAPISchemaType) -> str: return mcgen(''' struct %(c_name)s { @@ -101,7 +122,7 @@ def gen_array(name, element_type): c_name=c_name(name), c_type=element_type.c_type()) -def gen_struct_members(members): +def gen_struct_members(members: List[QAPISchemaObjectTypeMember]) -> str: ret = '' for memb in members: ret += gen_if(memb.ifcond) @@ -118,17 +139,21 @@ def gen_struct_members(members): return ret -def gen_object(name, ifcond, base, members, variants): +def gen_object(name: str, ifcond: List[str], + base: Optional[QAPISchemaObjectType], + members: List[QAPISchemaObjectTypeMember], + variants: Optional[QAPISchemaVariants]) -> str: if name in objects_seen: return '' objects_seen.add(name) ret = '' - if variants: - for v in variants.variants: - if isinstance(v.type, QAPISchemaObjectType): - ret += gen_object(v.type.name, v.type.ifcond, v.type.base, - v.type.local_members, v.type.variants) + for var in variants.variants if variants else (): + obj = var.type + if not isinstance(obj, QAPISchemaObjectType): + continue + ret += gen_object(obj.name, obj.ifcond, obj.base, + obj.local_members, obj.variants) ret += mcgen(''' @@ -172,7 +197,7 @@ def gen_object(name, ifcond, base, members, variants): return ret -def gen_upcast(name, base): +def gen_upcast(name: str, base: QAPISchemaObjectType) -> str: # C makes const-correctness ugly. We have to cast away const to let # this function work for both const and non-const obj. return mcgen(''' @@ -185,7 +210,7 @@ def gen_upcast(name, base): c_name=c_name(name), base=base.c_name()) -def gen_variants(variants): +def gen_variants(variants: QAPISchemaVariants) -> str: ret = mcgen(''' union { /* union tag is @%(c_name)s */ ''', @@ -209,16 +234,17 @@ def gen_variants(variants): return ret -def gen_type_cleanup_decl(name): +def gen_type_cleanup_decl(name: str) -> str: ret = mcgen(''' void qapi_free_%(c_name)s(%(c_name)s *obj); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(%(c_name)s, qapi_free_%(c_name)s) ''', c_name=c_name(name)) return ret -def gen_type_cleanup(name): +def gen_type_cleanup(name: str) -> str: ret = mcgen(''' void qapi_free_%(c_name)s(%(c_name)s *obj) @@ -240,12 +266,12 @@ def gen_type_cleanup(name): class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor): - def __init__(self, prefix): + def __init__(self, prefix: str): super().__init__( prefix, 'qapi-types', ' * Schema-defined QAPI types', ' * Built-in QAPI types', __doc__) - def _begin_system_module(self, name): + def _begin_system_module(self, name: None) -> None: self._genc.preamble_add(mcgen(''' #include "qemu/osdep.h" #include "qapi/dealloc-visitor.h" @@ -256,7 +282,7 @@ def _begin_system_module(self, name): #include "qapi/util.h" ''')) - def _begin_user_module(self, name): + def _begin_user_module(self, name: str) -> None: types = self._module_basename('qapi-types', name) visit = self._module_basename('qapi-visit', name) self._genc.preamble_add(mcgen(''' @@ -270,27 +296,43 @@ def _begin_user_module(self, name): #include "qapi/qapi-builtin-types.h" ''')) - def visit_begin(self, schema): + def visit_begin(self, schema: QAPISchema) -> None: # gen_object() is recursive, ensure it doesn't visit the empty type objects_seen.add(schema.the_empty_object_type.name) - def _gen_type_cleanup(self, name): + def _gen_type_cleanup(self, name: str) -> None: self._genh.add(gen_type_cleanup_decl(name)) self._genc.add(gen_type_cleanup(name)) - def visit_enum_type(self, name, info, ifcond, features, members, prefix): + def visit_enum_type(self, + name: str, + info: Optional[QAPISourceInfo], + ifcond: List[str], + features: List[QAPISchemaFeature], + members: List[QAPISchemaEnumMember], + prefix: Optional[str]) -> None: with ifcontext(ifcond, self._genh, self._genc): self._genh.preamble_add(gen_enum(name, members, prefix)) self._genc.add(gen_enum_lookup(name, members, prefix)) - def visit_array_type(self, name, info, ifcond, element_type): + def visit_array_type(self, + name: str, + info: Optional[QAPISourceInfo], + ifcond: List[str], + element_type: QAPISchemaType) -> None: with ifcontext(ifcond, self._genh, self._genc): self._genh.preamble_add(gen_fwd_object_or_array(name)) self._genh.add(gen_array(name, element_type)) self._gen_type_cleanup(name) - def visit_object_type(self, name, info, ifcond, features, - base, members, variants): + def visit_object_type(self, + name: str, + info: Optional[QAPISourceInfo], + ifcond: List[str], + features: List[QAPISchemaFeature], + base: Optional[QAPISchemaObjectType], + members: List[QAPISchemaObjectTypeMember], + variants: Optional[QAPISchemaVariants]) -> None: # Nothing to do for the special empty builtin if name == 'q_empty': return @@ -306,7 +348,12 @@ def visit_object_type(self, name, info, ifcond, features, # implicit types won't be directly allocated/freed self._gen_type_cleanup(name) - def visit_alternate_type(self, name, info, ifcond, features, variants): + def visit_alternate_type(self, + name: str, + info: QAPISourceInfo, + ifcond: List[str], + features: List[QAPISchemaFeature], + variants: QAPISchemaVariants) -> None: with ifcontext(ifcond, self._genh): self._genh.preamble_add(gen_fwd_object_or_array(name)) self._genh.add(gen_object(name, ifcond, None, @@ -315,7 +362,10 @@ def visit_alternate_type(self, name, info, ifcond, features, variants): self._gen_type_cleanup(name) -def gen_types(schema, output_dir, prefix, opt_builtins): +def gen_types(schema: QAPISchema, + output_dir: str, + prefix: str, + opt_builtins: bool) -> None: vis = QAPISchemaGenTypeVisitor(prefix) schema.visit(vis) vis.write(output_dir, opt_builtins) diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py index d5d7a1031f3f03bc6561e066ef7f29f53075683a..339f1521524c89ed29008c435fa1a60c77660a1f 100644 --- a/scripts/qapi/visit.py +++ b/scripts/qapi/visit.py @@ -13,44 +13,65 @@ See the COPYING file in the top-level directory. """ -from qapi.common import * -from qapi.gen import QAPISchemaModularCVisitor, ifcontext -from qapi.schema import QAPISchemaObjectType - - -def gen_visit_decl(name, scalar=False): +from typing import List, Optional + +from .common import ( + c_enum_const, + c_name, + gen_endif, + gen_if, + indent, + mcgen, +) +from .gen import QAPISchemaModularCVisitor, ifcontext +from .schema import ( + QAPISchema, + QAPISchemaEnumMember, + QAPISchemaEnumType, + QAPISchemaFeature, + QAPISchemaObjectType, + QAPISchemaObjectTypeMember, + QAPISchemaType, + QAPISchemaVariants, +) +from .source import QAPISourceInfo + + +def gen_visit_decl(name: str, scalar: bool = False) -> str: c_type = c_name(name) + ' *' if not scalar: c_type += '*' return mcgen(''' -void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_type)sobj, Error **errp); + +bool visit_type_%(c_name)s(Visitor *v, const char *name, + %(c_type)sobj, Error **errp); ''', c_name=c_name(name), c_type=c_type) -def gen_visit_members_decl(name): +def gen_visit_members_decl(name: str) -> str: return mcgen(''' -void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp); +bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp); ''', c_name=c_name(name)) -def gen_visit_object_members(name, base, members, variants): +def gen_visit_object_members(name: str, + base: Optional[QAPISchemaObjectType], + members: List[QAPISchemaObjectTypeMember], + variants: Optional[QAPISchemaVariants]) -> str: ret = mcgen(''' -void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp) +bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp) { - Error *err = NULL; - ''', c_name=c_name(name)) if base: ret += mcgen(''' - visit_type_%(c_type)s_members(v, (%(c_type)s *)obj, &err); - if (err) { - goto out; + if (!visit_type_%(c_type)s_members(v, (%(c_type)s *)obj, errp)) { + return false; } ''', c_type=base.c_name()) @@ -62,32 +83,33 @@ def gen_visit_object_members(name, base, members, variants): if (visit_optional(v, "%(name)s", &obj->has_%(c_name)s)) { ''', name=memb.name, c_name=c_name(memb.name)) - push_indent() + indent.increase() ret += mcgen(''' - visit_type_%(c_type)s(v, "%(name)s", &obj->%(c_name)s, &err); - if (err) { - goto out; + if (!visit_type_%(c_type)s(v, "%(name)s", &obj->%(c_name)s, errp)) { + return false; } ''', c_type=memb.type.c_name(), name=memb.name, c_name=c_name(memb.name)) if memb.optional: - pop_indent() + indent.decrease() ret += mcgen(''' } ''') ret += gen_endif(memb.ifcond) if variants: + tag_member = variants.tag_member + assert isinstance(tag_member.type, QAPISchemaEnumType) + ret += mcgen(''' switch (obj->%(c_name)s) { ''', - c_name=c_name(variants.tag_member.name)) + c_name=c_name(tag_member.name)) for var in variants.variants: - case_str = c_enum_const(variants.tag_member.type.name, - var.name, - variants.tag_member.type.prefix) + case_str = c_enum_const(tag_member.type.name, var.name, + tag_member.type.prefix) ret += gen_if(var.ifcond) if var.type.name == 'q_empty': # valid variant and nothing to do @@ -99,8 +121,7 @@ def gen_visit_object_members(name, base, members, variants): else: ret += mcgen(''' case %(case)s: - visit_type_%(c_type)s_members(v, &obj->u.%(c_name)s, &err); - break; + return visit_type_%(c_type)s_members(v, &obj->u.%(c_name)s, errp); ''', case=case_str, c_type=var.type.c_name(), c_name=c_name(var.name)) @@ -112,85 +133,78 @@ def gen_visit_object_members(name, base, members, variants): } ''') - # 'goto out' produced for base, for each member, and if variants were - # present - if base or members or variants: - ret += mcgen(''' - -out: -''') ret += mcgen(''' - error_propagate(errp, err); + return true; } ''') return ret -def gen_visit_list(name, element_type): +def gen_visit_list(name: str, element_type: QAPISchemaType) -> str: return mcgen(''' -void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error **errp) +bool visit_type_%(c_name)s(Visitor *v, const char *name, + %(c_name)s **obj, Error **errp) { - Error *err = NULL; + bool ok = false; %(c_name)s *tail; size_t size = sizeof(**obj); - visit_start_list(v, name, (GenericList **)obj, size, &err); - if (err) { - goto out; + if (!visit_start_list(v, name, (GenericList **)obj, size, errp)) { + return false; } for (tail = *obj; tail; tail = (%(c_name)s *)visit_next_list(v, (GenericList *)tail, size)) { - visit_type_%(c_elt_type)s(v, NULL, &tail->value, &err); - if (err) { - break; + if (!visit_type_%(c_elt_type)s(v, NULL, &tail->value, errp)) { + goto out_obj; } } - if (!err) { - visit_check_list(v, &err); - } + ok = visit_check_list(v, errp); +out_obj: visit_end_list(v, (void **)obj); - if (err && visit_is_input(v)) { + if (!ok && visit_is_input(v)) { qapi_free_%(c_name)s(*obj); *obj = NULL; } -out: - error_propagate(errp, err); + return ok; } ''', c_name=c_name(name), c_elt_type=element_type.c_name()) -def gen_visit_enum(name): +def gen_visit_enum(name: str) -> str: return mcgen(''' -void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s *obj, Error **errp) +bool visit_type_%(c_name)s(Visitor *v, const char *name, + %(c_name)s *obj, Error **errp) { int value = *obj; - visit_type_enum(v, name, &value, &%(c_name)s_lookup, errp); + bool ok = visit_type_enum(v, name, &value, &%(c_name)s_lookup, errp); *obj = value; + return ok; } ''', c_name=c_name(name)) -def gen_visit_alternate(name, variants): +def gen_visit_alternate(name: str, variants: QAPISchemaVariants) -> str: ret = mcgen(''' -void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error **errp) +bool visit_type_%(c_name)s(Visitor *v, const char *name, + %(c_name)s **obj, Error **errp) { - Error *err = NULL; + bool ok = false; - visit_start_alternate(v, name, (GenericAlternate **)obj, sizeof(**obj), - &err); - if (err) { - goto out; + if (!visit_start_alternate(v, name, (GenericAlternate **)obj, + sizeof(**obj), errp)) { + return false; } if (!*obj) { /* incomplete */ assert(visit_is_dealloc(v)); + ok = true; goto out_obj; } switch ((*obj)->type) { @@ -205,13 +219,11 @@ def gen_visit_alternate(name, variants): case=var.type.alternate_qtype()) if isinstance(var.type, QAPISchemaObjectType): ret += mcgen(''' - visit_start_struct(v, name, NULL, 0, &err); - if (err) { + if (!visit_start_struct(v, name, NULL, 0, errp)) { break; } - visit_type_%(c_type)s_members(v, &(*obj)->u.%(c_name)s, &err); - if (!err) { - visit_check_struct(v, &err); + if (visit_type_%(c_type)s_members(v, &(*obj)->u.%(c_name)s, errp)) { + ok = visit_check_struct(v, errp); } visit_end_struct(v, NULL); ''', @@ -219,7 +231,7 @@ def gen_visit_alternate(name, variants): c_name=c_name(var.name)) else: ret += mcgen(''' - visit_type_%(c_type)s(v, name, &(*obj)->u.%(c_name)s, &err); + ok = visit_type_%(c_type)s(v, name, &(*obj)->u.%(c_name)s, errp); ''', c_type=var.type.c_name(), c_name=c_name(var.name)) @@ -233,7 +245,7 @@ def gen_visit_alternate(name, variants): abort(); default: assert(visit_is_input(v)); - error_setg(&err, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "%(name)s"); /* Avoid passing invalid *obj to qapi_free_%(c_name)s() */ g_free(*obj); @@ -241,12 +253,11 @@ def gen_visit_alternate(name, variants): } out_obj: visit_end_alternate(v, (void **)obj); - if (err && visit_is_input(v)) { + if (!ok && visit_is_input(v)) { qapi_free_%(c_name)s(*obj); *obj = NULL; } -out: - error_propagate(errp, err); + return ok; } ''', name=name, c_name=c_name(name)) @@ -254,35 +265,34 @@ def gen_visit_alternate(name, variants): return ret -def gen_visit_object(name, base, members, variants): +def gen_visit_object(name: str) -> str: return mcgen(''' -void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error **errp) +bool visit_type_%(c_name)s(Visitor *v, const char *name, + %(c_name)s **obj, Error **errp) { - Error *err = NULL; + bool ok = false; - visit_start_struct(v, name, (void **)obj, sizeof(%(c_name)s), &err); - if (err) { - goto out; + if (!visit_start_struct(v, name, (void **)obj, sizeof(%(c_name)s), errp)) { + return false; } if (!*obj) { /* incomplete */ assert(visit_is_dealloc(v)); + ok = true; goto out_obj; } - visit_type_%(c_name)s_members(v, *obj, &err); - if (err) { + if (!visit_type_%(c_name)s_members(v, *obj, errp)) { goto out_obj; } - visit_check_struct(v, &err); + ok = visit_check_struct(v, errp); out_obj: visit_end_struct(v, (void **)obj); - if (err && visit_is_input(v)) { + if (!ok && visit_is_input(v)) { qapi_free_%(c_name)s(*obj); *obj = NULL; } -out: - error_propagate(errp, err); + return ok; } ''', c_name=c_name(name)) @@ -290,12 +300,12 @@ def gen_visit_object(name, base, members, variants): class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor): - def __init__(self, prefix): + def __init__(self, prefix: str): super().__init__( prefix, 'qapi-visit', ' * Schema-defined QAPI visitors', ' * Built-in QAPI visitors', __doc__) - def _begin_system_module(self, name): + def _begin_system_module(self, name: None) -> None: self._genc.preamble_add(mcgen(''' #include "qemu/osdep.h" #include "qapi/error.h" @@ -307,7 +317,7 @@ def _begin_system_module(self, name): ''')) - def _begin_user_module(self, name): + def _begin_user_module(self, name: str) -> None: types = self._module_basename('qapi-types', name) visit = self._module_basename('qapi-visit', name) self._genc.preamble_add(mcgen(''' @@ -324,18 +334,34 @@ def _begin_user_module(self, name): ''', types=types)) - def visit_enum_type(self, name, info, ifcond, features, members, prefix): + def visit_enum_type(self, + name: str, + info: QAPISourceInfo, + ifcond: List[str], + features: List[QAPISchemaFeature], + members: List[QAPISchemaEnumMember], + prefix: Optional[str]) -> None: with ifcontext(ifcond, self._genh, self._genc): self._genh.add(gen_visit_decl(name, scalar=True)) self._genc.add(gen_visit_enum(name)) - def visit_array_type(self, name, info, ifcond, element_type): + def visit_array_type(self, + name: str, + info: Optional[QAPISourceInfo], + ifcond: List[str], + element_type: QAPISchemaType) -> None: with ifcontext(ifcond, self._genh, self._genc): self._genh.add(gen_visit_decl(name)) self._genc.add(gen_visit_list(name, element_type)) - def visit_object_type(self, name, info, ifcond, features, - base, members, variants): + def visit_object_type(self, + name: str, + info: Optional[QAPISourceInfo], + ifcond: List[str], + features: List[QAPISchemaFeature], + base: Optional[QAPISchemaObjectType], + members: List[QAPISchemaObjectTypeMember], + variants: Optional[QAPISchemaVariants]) -> None: # Nothing to do for the special empty builtin if name == 'q_empty': return @@ -348,15 +374,23 @@ def visit_object_type(self, name, info, ifcond, features, if not name.startswith('q_'): # only explicit types need an allocating visit self._genh.add(gen_visit_decl(name)) - self._genc.add(gen_visit_object(name, base, members, variants)) - - def visit_alternate_type(self, name, info, ifcond, features, variants): + self._genc.add(gen_visit_object(name)) + + def visit_alternate_type(self, + name: str, + info: QAPISourceInfo, + ifcond: List[str], + features: List[QAPISchemaFeature], + variants: QAPISchemaVariants) -> None: with ifcontext(ifcond, self._genh, self._genc): self._genh.add(gen_visit_decl(name)) self._genc.add(gen_visit_alternate(name, variants)) -def gen_visit(schema, output_dir, prefix, opt_builtins): +def gen_visit(schema: QAPISchema, + output_dir: str, + prefix: str, + opt_builtins: bool) -> None: vis = QAPISchemaGenVisitVisitor(prefix) schema.visit(vis) vis.write(output_dir, opt_builtins) diff --git a/scripts/qemu-gdb.py b/scripts/qemu-gdb.py index f2a305c42e568af2b8123075282faaefee10016c..e0bfa7b5a4e87ea069cffbf60e997e65b02f1859 100644 --- a/scripts/qemu-gdb.py +++ b/scripts/qemu-gdb.py @@ -1,5 +1,5 @@ -#!/usr/bin/python - +#!/usr/bin/env python3 +# # GDB debugging support # # Copyright 2012 Red Hat, Inc. and/or its affiliates diff --git a/scripts/qemu-version.sh b/scripts/qemu-version.sh new file mode 100755 index 0000000000000000000000000000000000000000..3f6e7e6d41d87b026a7a40681e2530e7c04bfc8a --- /dev/null +++ b/scripts/qemu-version.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +set -eu + +dir="$1" +pkgversion="$2" +version="$3" + +if [ -z "$pkgversion" ]; then + cd "$dir" + if [ -e .git ]; then + pkgversion=$(git describe --match 'v*' --dirty) || : + fi +fi + +if [ -n "$pkgversion" ]; then + fullversion="$version ($pkgversion)" +else + fullversion="$version" +fi + +cat < -# -# This work is licensed under the terms of the GNU GPLv2 or later. -# See the COPYING file in the top-level directory. -import sys, os -from qmp import QEMUMonitorProtocol +import sys -def print_response(rsp, prefix=[]): - if type(rsp) == list: - i = 0 - for item in rsp: - if prefix == []: - prefix = ['item'] - print_response(item, prefix[:-1] + ['%s[%d]' % (prefix[-1], i)]) - i += 1 - elif type(rsp) == dict: - for key in rsp.keys(): - print_response(rsp[key], prefix + [key]) - else: - if len(prefix): - print('%s: %s' % ('.'.join(prefix), rsp)) - else: - print('%s' % (rsp)) +print('''This unmaintained and undocumented script was removed in preference +for qmp-shell. The assumption is that most users are using either +qmp-shell, socat, or pasting/piping JSON into stdio. The duplication of +facilities here is unwanted, and the divergence of syntax harmful.''', + file=sys.stderr) -def main(args): - path = None - - # Use QMP_PATH if it's set - if 'QMP_PATH' in os.environ: - path = os.environ['QMP_PATH'] - - while len(args): - arg = args[0] - - if arg.startswith('--'): - arg = arg[2:] - if arg.find('=') == -1: - value = True - else: - arg, value = arg.split('=', 1) - - if arg in ['path']: - if type(value) == str: - path = value - elif arg in ['help']: - os.execlp('man', 'man', 'qmp') - else: - print('Unknown argument "%s"' % arg) - - args = args[1:] - else: - break - - if not path: - print("QMP path isn't set, use --path=qmp-monitor-address or set QMP_PATH") - return 1 - - if len(args): - command, args = args[0], args[1:] - else: - print('No command found') - print('Usage: "qmp [--path=qmp-monitor-address] qmp-cmd arguments"') - return 1 - - if command in ['help']: - os.execlp('man', 'man', 'qmp') - - srv = QEMUMonitorProtocol(path) - srv.connect() - - def do_command(srv, cmd, **kwds): - rsp = srv.cmd(cmd, kwds) - if 'error' in rsp: - raise Exception(rsp['error']['desc']) - return rsp['return'] - - commands = map(lambda x: x['name'], do_command(srv, 'query-commands')) - - srv.close() - - if command not in commands: - fullcmd = 'qmp-%s' % command - try: - os.environ['QMP_PATH'] = path - os.execvp(fullcmd, [fullcmd] + args) - except OSError as exc: - if exc.errno == 2: - print('Command "%s" not found.' % (fullcmd)) - return 1 - raise - return 0 - - srv = QEMUMonitorProtocol(path) - srv.connect() - - arguments = {} - for arg in args: - if not arg.startswith('--'): - print('Unknown argument "%s"' % arg) - return 1 - - arg = arg[2:] - if arg.find('=') == -1: - value = True - else: - arg, value = arg.split('=', 1) - - if arg in ['help']: - os.execlp('man', 'man', 'qmp-%s' % command) - return 1 - - arguments[arg] = value - - rsp = do_command(srv, command, **arguments) - print_response(rsp) - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) +sys.exit(1) diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell index a01d31de1e549c3706a7cb57632db87a5d9db938..b4d06096abd61151fe9e19285d969fcdf74a8fff 100755 --- a/scripts/qmp/qmp-shell +++ b/scripts/qmp/qmp-shell @@ -77,9 +77,6 @@ import re sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) from qemu import qmp -if sys.version_info[0] == 2: - input = raw_input - class QMPCompleter(list): def complete(self, text, state): for cmd in self: @@ -263,7 +260,7 @@ class QMPShell(qmp.QEMUMonitorProtocol): indent = None if self._pretty: indent = 4 - jsobj = json.dumps(qmp, indent=indent) + jsobj = json.dumps(qmp, indent=indent, sort_keys=self._pretty) print(str(jsobj)) def _execute_cmd(self, cmdline): diff --git a/scripts/qmp/qom-fuse b/scripts/qmp/qom-fuse index 6bada2c33d3414763bc1f4d3c1c4e140e140cf84..7c7cff8edfba1dd75aaf56f0b69c6341662f87e4 100755 --- a/scripts/qmp/qom-fuse +++ b/scripts/qmp/qom-fuse @@ -3,25 +3,28 @@ # QEMU Object Model test tools # # Copyright IBM, Corp. 2012 +# Copyright (C) 2020 Red Hat, Inc. # # Authors: # Anthony Liguori +# Markus Armbruster # # 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 fuse, stat -from fuse import Fuse -import os, posix +from fuse import FUSE, FuseOSError, Operations +import os, posix, sys from errno import * -from qmp import QEMUMonitorProtocol + +sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) +from qemu.qmp import QEMUMonitorProtocol fuse.fuse_python_api = (0, 2) -class QOMFS(Fuse): - def __init__(self, qmp, *args, **kwds): - Fuse.__init__(self, *args, **kwds) +class QOMFS(Operations): + def __init__(self, qmp): self.qmp = qmp self.qmp.connect() self.ino_map = {} @@ -42,8 +45,10 @@ class QOMFS(Fuse): return False def is_property(self, path): + path, prop = path.rsplit('/', 1) + if path == '': + path = '/' try: - path, prop = path.rsplit('/', 1) for item in self.qmp.command('qom-list', path=path): if item['name'] == prop: return True @@ -52,8 +57,10 @@ class QOMFS(Fuse): return False def is_link(self, path): + path, prop = path.rsplit('/', 1) + if path == '': + path = '/' try: - path, prop = path.rsplit('/', 1) for item in self.qmp.command('qom-list', path=path): if item['name'] == prop: if item['type'].startswith('link<'): @@ -63,21 +70,23 @@ class QOMFS(Fuse): except: return False - def read(self, path, length, offset): + def read(self, path, length, offset, fh): if not self.is_property(path): return -ENOENT path, prop = path.rsplit('/', 1) + if path == '': + path = '/' try: - data = str(self.qmp.command('qom-get', path=path, property=prop)) + data = self.qmp.command('qom-get', path=path, property=prop) data += '\n' # make values shell friendly except: - return -EPERM + raise FuseOSError(EPERM) if offset > len(data): return '' - return str(data[offset:][:length]) + return bytes(data[offset:][:length], encoding='utf-8') def readlink(self, path): if not self.is_link(path): @@ -87,52 +96,52 @@ class QOMFS(Fuse): return prefix + str(self.qmp.command('qom-get', path=path, property=prop)) - def getattr(self, path): + def getattr(self, path, fh=None): if self.is_link(path): - value = posix.stat_result((0o755 | stat.S_IFLNK, - self.get_ino(path), - 0, - 2, - 1000, - 1000, - 4096, - 0, - 0, - 0)) + value = { 'st_mode': 0o755 | stat.S_IFLNK, + 'st_ino': self.get_ino(path), + 'st_dev': 0, + 'st_nlink': 2, + 'st_uid': 1000, + 'st_gid': 1000, + 'st_size': 4096, + 'st_atime': 0, + 'st_mtime': 0, + 'st_ctime': 0 } elif self.is_object(path): - value = posix.stat_result((0o755 | stat.S_IFDIR, - self.get_ino(path), - 0, - 2, - 1000, - 1000, - 4096, - 0, - 0, - 0)) + value = { 'st_mode': 0o755 | stat.S_IFDIR, + 'st_ino': self.get_ino(path), + 'st_dev': 0, + 'st_nlink': 2, + 'st_uid': 1000, + 'st_gid': 1000, + 'st_size': 4096, + 'st_atime': 0, + 'st_mtime': 0, + 'st_ctime': 0 } elif self.is_property(path): - value = posix.stat_result((0o644 | stat.S_IFREG, - self.get_ino(path), - 0, - 1, - 1000, - 1000, - 4096, - 0, - 0, - 0)) + value = { 'st_mode': 0o644 | stat.S_IFREG, + 'st_ino': self.get_ino(path), + 'st_dev': 0, + 'st_nlink': 1, + 'st_uid': 1000, + 'st_gid': 1000, + 'st_size': 4096, + 'st_atime': 0, + 'st_mtime': 0, + 'st_ctime': 0 } else: - value = -ENOENT + raise FuseOSError(ENOENT) return value - def readdir(self, path, offset): - yield fuse.Direntry('.') - yield fuse.Direntry('..') + def readdir(self, path, fh): + yield '.' + yield '..' for item in self.qmp.command('qom-list', path=path): - yield fuse.Direntry(str(item['name'])) + yield str(item['name']) if __name__ == '__main__': - import sys, os + import os - fs = QOMFS(QEMUMonitorProtocol(os.environ['QMP_SOCKET'])) - fs.main(sys.argv) + fuse = FUSE(QOMFS(QEMUMonitorProtocol(os.environ['QMP_SOCKET'])), + sys.argv[1], foreground=True) diff --git a/scripts/qmp/qom-get b/scripts/qmp/qom-get index 007b4cd442ee5d2261a0ce51fd269ab79cf58cab..666df718320c2f241068493264a498b7c3063484 100755 --- a/scripts/qmp/qom-get +++ b/scripts/qmp/qom-get @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 ## # QEMU Object Model test tools # @@ -13,7 +13,9 @@ import sys import os -from qmp import QEMUMonitorProtocol + +sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) +from qemu.qmp import QEMUMonitorProtocol cmd, args = sys.argv[0], sys.argv[1:] socket_path = None diff --git a/scripts/qmp/qom-list b/scripts/qmp/qom-list index 03bda3446b783ac2415a02789e7fa2a59ed8ea5d..5074fd939f4a87aeb26efaf4493ad4278ed4e077 100755 --- a/scripts/qmp/qom-list +++ b/scripts/qmp/qom-list @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 ## # QEMU Object Model test tools # @@ -13,7 +13,9 @@ import sys import os -from qmp import QEMUMonitorProtocol + +sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) +from qemu.qmp import QEMUMonitorProtocol cmd, args = sys.argv[0], sys.argv[1:] socket_path = None diff --git a/scripts/qmp/qom-set b/scripts/qmp/qom-set index c37fe78b00008ad6e2777b717fd69195903eb645..240a78187f9b3c48db958fee3d0a4538818891e5 100755 --- a/scripts/qmp/qom-set +++ b/scripts/qmp/qom-set @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 ## # QEMU Object Model test tools # @@ -13,7 +13,9 @@ import sys import os -from qmp import QEMUMonitorProtocol + +sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) +from qemu.qmp import QEMUMonitorProtocol cmd, args = sys.argv[0], sys.argv[1:] socket_path = None diff --git a/scripts/qmp/qom-tree b/scripts/qmp/qom-tree index 1c8acf61e79f8c994311a8010ec479c16b25aa7f..25b0781323cc605394d40db669a75472d191c3db 100755 --- a/scripts/qmp/qom-tree +++ b/scripts/qmp/qom-tree @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 ## # QEMU Object Model test tools # @@ -15,7 +15,9 @@ import sys import os -from qmp import QEMUMonitorProtocol + +sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) +from qemu.qmp import QEMUMonitorProtocol cmd, args = sys.argv[0], sys.argv[1:] socket_path = None diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py index 409b4321f2e8fe9ea24c9958ff08a53d4bd5184d..da6acf050d12bf2c0ff8cd14fc712d48d6fd93a9 100755 --- a/scripts/render_block_graph.py +++ b/scripts/render_block_graph.py @@ -25,7 +25,10 @@ from graphviz import Digraph sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'python')) -from qemu.machine import MonitorResponseError +from qemu.qmp import ( + QEMUMonitorProtocol, + QMPResponseError, +) def perm(arr): @@ -102,7 +105,7 @@ def command(self, cmd): reply = json.loads(subprocess.check_output(ar)) if 'error' in reply: - raise MonitorResponseError(reply) + raise QMPResponseError(reply) return reply['return'] diff --git a/scripts/replay-dump.py b/scripts/replay-dump.py index 4cbc1e47c64cf7605af3cbb7bfe3a2fcbef73312..3ba97a6d30ea7df657584d578ba00418103b8648 100755 --- a/scripts/replay-dump.py +++ b/scripts/replay-dump.py @@ -8,7 +8,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/scripts/simplebench/bench_write_req.py b/scripts/simplebench/bench_write_req.py new file mode 100755 index 0000000000000000000000000000000000000000..ca1178fd689d7bc3a037b202b06a516c0a80b430 --- /dev/null +++ b/scripts/simplebench/bench_write_req.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python3 +# +# Test to compare performance of write requests for two qemu-img binary files. +# +# The idea of the test comes from intention to check the benefit of c8bb23cbdbe +# "qcow2: skip writing zero buffers to empty COW areas". +# +# Copyright (c) 2020 Virtuozzo International GmbH. +# +# 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 . +# + + +import sys +import os +import subprocess +import simplebench + + +def bench_func(env, case): + """ Handle one "cell" of benchmarking table. """ + return bench_write_req(env['qemu_img'], env['image_name'], + case['block_size'], case['block_offset'], + case['cluster_size']) + + +def qemu_img_pipe(*args): + '''Run qemu-img and return its output''' + subp = subprocess.Popen(list(args), + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True) + exitcode = subp.wait() + if exitcode < 0: + sys.stderr.write('qemu-img received signal %i: %s\n' + % (-exitcode, ' '.join(list(args)))) + return subp.communicate()[0] + + +def bench_write_req(qemu_img, image_name, block_size, block_offset, + cluster_size): + """Benchmark write requests + + The function creates a QCOW2 image with the given path/name. Then it runs + the 'qemu-img bench' command and makes series of write requests on the + image clusters. Finally, it returns the total time of the write operations + on the disk. + + qemu_img -- path to qemu_img executable file + image_name -- QCOW2 image name to create + block_size -- size of a block to write to clusters + block_offset -- offset of the block in clusters + cluster_size -- size of the image cluster + + Returns {'seconds': int} on success and {'error': str} on failure. + Return value is compatible with simplebench lib. + """ + + if not os.path.isfile(qemu_img): + print(f'File not found: {qemu_img}') + sys.exit(1) + + image_dir = os.path.dirname(os.path.abspath(image_name)) + if not os.path.isdir(image_dir): + print(f'Path not found: {image_name}') + sys.exit(1) + + image_size = 1024 * 1024 * 1024 + + args_create = [qemu_img, 'create', '-f', 'qcow2', '-o', + f'cluster_size={cluster_size}', + image_name, str(image_size)] + + count = int(image_size / cluster_size) - 1 + step = str(cluster_size) + + args_bench = [qemu_img, 'bench', '-w', '-n', '-t', 'none', '-c', + str(count), '-s', f'{block_size}', '-o', str(block_offset), + '-S', step, '-f', 'qcow2', image_name] + + try: + qemu_img_pipe(*args_create) + except OSError as e: + os.remove(image_name) + return {'error': 'qemu_img create failed: ' + str(e)} + + try: + ret = qemu_img_pipe(*args_bench) + except OSError as e: + os.remove(image_name) + return {'error': 'qemu_img bench failed: ' + str(e)} + + os.remove(image_name) + + if 'seconds' in ret: + ret_list = ret.split() + index = ret_list.index('seconds.') + return {'seconds': float(ret_list[index-1])} + else: + return {'error': 'qemu_img bench failed: ' + ret} + + +if __name__ == '__main__': + + if len(sys.argv) < 4: + program = os.path.basename(sys.argv[0]) + print(f'USAGE: {program} ' + ' ' + '') + exit(1) + + # Test-cases are "rows" in benchmark resulting table, 'id' is a caption + # for the row, other fields are handled by bench_func. + test_cases = [ + { + 'id': '', + 'block_size': 4096, + 'block_offset': 0, + 'cluster_size': 1048576 + }, + { + 'id': '', + 'block_size': 4096, + 'block_offset': 524288, + 'cluster_size': 1048576 + }, + { + 'id': '', + 'block_size': 1048576, + 'block_offset': 4096, + 'cluster_size': 1048576 + }, + { + 'id': '', + 'block_size': 4096, + 'block_offset': 0, + 'cluster_size': 65536 + }, + ] + + # Test-envs are "columns" in benchmark resulting table, 'id is a caption + # for the column, other fields are handled by bench_func. + # Set the paths below to desired values + test_envs = [ + { + 'id': '', + 'qemu_img': f'{sys.argv[1]}', + 'image_name': f'{sys.argv[3]}' + }, + { + 'id': '', + 'qemu_img': f'{sys.argv[2]}', + 'image_name': f'{sys.argv[3]}' + }, + ] + + result = simplebench.bench(bench_func, test_envs, test_cases, count=3, + initial_run=False) + print(simplebench.ascii(result)) diff --git a/scripts/tap-driver.pl b/scripts/tap-driver.pl index 6621a5cd6715f76820b19224b376fcd66dfbf165..b1d3880c5060683d00a4a8fbc7b3a40b6b7bb2d3 100755 --- a/scripts/tap-driver.pl +++ b/scripts/tap-driver.pl @@ -217,7 +217,7 @@ sub report ($;$) sub testsuite_error ($) { - report "ERROR", "- $_[0]"; + report "ERROR", "$test_name - $_[0]"; } sub handle_tap_result ($) diff --git a/scripts/test-driver.py b/scripts/test-driver.py new file mode 100644 index 0000000000000000000000000000000000000000..eef74b29a8feda0b197242990c2e83cd085602dc --- /dev/null +++ b/scripts/test-driver.py @@ -0,0 +1,35 @@ +#! /usr/bin/env python3 + +# Wrapper for tests that hides the output if they succeed. +# Used by "make check" +# +# Copyright (C) 2020 Red Hat, Inc. +# +# Author: Paolo Bonzini + +import subprocess +import sys +import os +import argparse + +parser = argparse.ArgumentParser(description='Test driver for QEMU') +parser.add_argument('-C', metavar='DIR', dest='dir', default='.', + help='change to DIR before doing anything else') +parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', + help='be more verbose') +parser.add_argument('test_args', nargs=argparse.REMAINDER) + +args = parser.parse_args() +os.chdir(args.dir) + +test_args = args.test_args +if test_args[0] == '--': + test_args = test_args[1:] + +if args.verbose: + result = subprocess.run(test_args, stdout=None, stderr=None) +else: + result = subprocess.run(test_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + if result.returncode: + sys.stdout.buffer.write(result.stdout) +sys.exit(result.returncode) diff --git a/scripts/texi2pod.pl b/scripts/texi2pod.pl deleted file mode 100755 index 8bfc6f6f4c47194889aec0cfe0ab0d76340ca33d..0000000000000000000000000000000000000000 --- a/scripts/texi2pod.pl +++ /dev/null @@ -1,536 +0,0 @@ -#! /usr/bin/env perl - -# Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc. - -# This file is part of GCC. - -# GCC 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, or (at your option) -# any later version. - -# GCC 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 GCC; see the file COPYING. If not, -# see . - -# This does trivial (and I mean _trivial_) conversion of Texinfo -# markup to Perl POD format. It's intended to be used to extract -# something suitable for a manpage from a Texinfo document. - -use warnings; - -$output = 0; -$skipping = 0; -%sects = (); -$section = ""; -@icstack = (); -@endwstack = (); -@skstack = (); -@instack = (); -$shift = ""; -%defs = (); -$fnno = 1; -$inf = ""; -$ibase = ""; -@ipath = (); -$encoding = undef; -@args = (); - -while ($_ = shift) { - if (/^-D(.*)$/) { - if ($1 ne "") { - $flag = $1; - } else { - $flag = shift; - } - $value = ""; - ($flag, $value) = ($flag =~ /^([^=]+)(?:=(.+))?/); - die "no flag specified for -D\n" - unless $flag ne ""; - die "flags may only contain letters, digits, hyphens, dashes and underscores\n" - unless $flag =~ /^[a-zA-Z0-9_-]+$/; - $defs{$flag} = $value; - } elsif (/^-I(.*)$/) { - if ($1 ne "") { - $flag = $1; - } else { - $flag = shift; - } - push (@ipath, $flag); - } elsif (/^-/) { - usage(); - } else { - $in = $_, next unless defined $in; - $out = $_, next unless defined $out; - usage(); - } -} - -if (defined $in) { - $inf = gensym(); - open($inf, "<$in") or die "opening \"$in\": $!\n"; - $ibase = $1 if $in =~ m|^(.+)/[^/]+$|; -} else { - $inf = \*STDIN; -} - -if (defined $out) { - open(STDOUT, ">$out") or die "opening \"$out\": $!\n"; -} - -while(defined $inf) { -while(<$inf>) { - # Certain commands are discarded without further processing. - /^\@(?: - [a-z]+index # @*index: useful only in complete manual - |need # @need: useful only in printed manual - |(?:end\s+)?group # @group .. @end group: ditto - |page # @page: ditto - |node # @node: useful only in .info file - |(?:end\s+)?ifnottex # @ifnottex .. @end ifnottex: use contents - )\b/x and next; - - chomp; - - # Look for filename and title markers. - /^\@setfilename\s+([^.]+)/ and $fn = $1, next; - /^\@settitle\s+([^.]+)/ and $tl = postprocess($1), next; - - # Look for document encoding - /^\@documentencoding\s+([^.]+)/ and do { - $encoding = $1 unless defined $encoding; - next; - }; - - # Identify a man title but keep only the one we are interested in. - /^\@c\s+man\s+title\s+([A-Za-z0-9-]+)\s+(.+)/ and do { - if (exists $defs{$1}) { - $fn = $1; - $tl = postprocess($2); - } - next; - }; - - # Look for blocks surrounded by @c man begin SECTION ... @c man end. - # This really oughta be @ifman ... @end ifman and the like, but such - # would require rev'ing all other Texinfo translators. - /^\@c\s+man\s+begin\s+([A-Z]+)\s+([A-Za-z0-9-]+)/ and do { - $output = 1 if exists $defs{$2}; - $sect = $1; - next; - }; - /^\@c\s+man\s+begin\s+([A-Z]+)/ and $sect = $1, $output = 1, next; - /^\@c\s+man\s+end/ and do { - $sects{$sect} = "" unless exists $sects{$sect}; - $sects{$sect} .= postprocess($section); - $section = ""; - $output = 0; - next; - }; - - # handle variables - /^\@set\s+([a-zA-Z0-9_-]+)\s*(.*)$/ and do { - $defs{$1} = $2; - next; - }; - /^\@clear\s+([a-zA-Z0-9_-]+)/ and do { - delete $defs{$1}; - next; - }; - - # Single line command handlers. - - /^\@include\s+(.+)$/ and do { - push @instack, $inf; - $inf = gensym(); - $file = postprocess($1); - - # Try cwd and $ibase, then explicit -I paths. - $done = 0; - foreach $path ("", $ibase, @ipath) { - $mypath = $file; - $mypath = $path . "/" . $mypath if ($path ne ""); - open($inf, "<" . $mypath) and ($done = 1, last); - } - die "cannot find $file" if !$done; - next; - }; - - next unless $output; - - # Discard comments. (Can't do it above, because then we'd never see - # @c man lines.) - /^\@c\b/ and next; - - # End-block handler goes up here because it needs to operate even - # if we are skipping. - /^\@end\s+([a-z]+)/ and do { - # Ignore @end foo, where foo is not an operation which may - # cause us to skip, if we are presently skipping. - my $ended = $1; - next if $skipping && $ended !~ /^(?:ifset|ifclear|ignore|menu|iftex|copying)$/; - - die "\@end $ended without \@$ended at line $.\n" unless defined $endw; - die "\@$endw ended by \@end $ended at line $.\n" unless $ended eq $endw; - - $endw = pop @endwstack; - - if ($ended =~ /^(?:ifset|ifclear|ignore|menu|iftex)$/) { - $skipping = pop @skstack; - next; - } elsif ($ended =~ /^(?:example|smallexample|display - |quotation|deftp|deftypefn)$/x) { - $shift = ""; - $_ = ""; # need a paragraph break - } elsif ($ended =~ /^(?:itemize|enumerate|[fv]?table)$/) { - $_ = "\n=back\n"; - $ic = pop @icstack; - } elsif ($ended eq "multitable") { - $_ = "\n=back\n"; - } else { - die "unknown command \@end $ended at line $.\n"; - } - }; - - # We must handle commands which can cause skipping even while we - # are skipping, otherwise we will not process nested conditionals - # correctly. - /^\@ifset\s+([a-zA-Z0-9_-]+)/ and do { - push @endwstack, $endw; - push @skstack, $skipping; - $endw = "ifset"; - $skipping = 1 unless exists $defs{$1}; - next; - }; - - /^\@ifclear\s+([a-zA-Z0-9_-]+)/ and do { - push @endwstack, $endw; - push @skstack, $skipping; - $endw = "ifclear"; - $skipping = 1 if exists $defs{$1}; - next; - }; - - /^\@(ignore|menu|iftex|copying)\b/ and do { - push @endwstack, $endw; - push @skstack, $skipping; - $endw = $1; - $skipping = 1; - next; - }; - - next if $skipping; - - # Character entities. First the ones that can be replaced by raw text - # or discarded outright: - s/\@copyright\{\}/(c)/g; - s/\@dots\{\}/.../g; - s/\@enddots\{\}/..../g; - s/\@([.!? ])/$1/g; - s/\@[:-]//g; - s/\@bullet(?:\{\})?/*/g; - s/\@TeX\{\}/TeX/g; - s/\@pounds\{\}/\#/g; - s/\@minus(?:\{\})?/-/g; - s/\\,/,/g; - - # Now the ones that have to be replaced by special escapes - # (which will be turned back into text by unmunge()) - s/&/&/g; - s/\@\{/{/g; - s/\@\}/}/g; - s/\@\@/&at;/g; - - # Inside a verbatim block, handle @var specially. - if ($shift ne "") { - s/\@var\{([^\}]*)\}/<$1>/g; - } - - # POD doesn't interpret E<> inside a verbatim block. - if ($shift eq "") { - s//>/g; - } else { - s//>/g; - } - - /^\@(?:section|unnumbered|unnumberedsec|center)\s+(.+)$/ - and $_ = "\n=head2 $1\n"; - /^\@subsection\s+(.+)$/ - and $_ = "\n=head3 $1\n"; - /^\@subsubsection\s+(.+)$/ - and $_ = "\n=head4 $1\n"; - - # Block command handlers: - /^\@itemize(?:\s+(\@[a-z]+|\*|-))?/ and do { - push @endwstack, $endw; - push @icstack, $ic; - if (defined $1) { - $ic = $1; - } else { - $ic = '*'; - } - $_ = "\n=over 4\n"; - $endw = "itemize"; - }; - - /^\@enumerate(?:\s+([a-zA-Z0-9]+))?/ and do { - push @endwstack, $endw; - push @icstack, $ic; - if (defined $1) { - $ic = $1 . "."; - } else { - $ic = "1."; - } - $_ = "\n=over 4\n"; - $endw = "enumerate"; - }; - - /^\@multitable\s.*/ and do { - push @endwstack, $endw; - $endw = "multitable"; - $_ = "\n=over 4\n"; - }; - - /^\@([fv]?table)\s+(\@[a-z]+)/ and do { - push @endwstack, $endw; - push @icstack, $ic; - $endw = $1; - $ic = $2; - $ic =~ s/\@(?:samp|strong|key|gcctabopt|option|env)/B/; - $ic =~ s/\@(?:code|kbd)/C/; - $ic =~ s/\@(?:dfn|var|emph|cite|i)/I/; - $ic =~ s/\@(?:file)/F/; - $ic =~ s/\@(?:asis)//; - $_ = "\n=over 4\n"; - }; - - /^\@((?:small)?example|display)/ and do { - push @endwstack, $endw; - $endw = $1; - $shift = "\t"; - $_ = ""; # need a paragraph break - }; - - /^\@item\s+(.*\S)\s*$/ and $endw eq "multitable" and do { - @columns = (); - for $column (split (/\s*\@tab\s*/, $1)) { - # @strong{...} is used a @headitem work-alike - $column =~ s/^\@strong\{(.*)\}$/$1/; - push @columns, $column; - } - $_ = "\n=item ".join (" : ", @columns)."\n"; - }; - - /^\@(quotation)\s*(.+)?$/ and do { - push @endwstack, $endw; - $endw = $1; - $_ = "\n$2:" - }; - - /^{(.*)}$|^(.*)$/ and $#args > 0 and do { - $kind = $args[0]; - $arguments = $1 // ""; - if ($endw eq "deftypefn") { - $ret = $args[1]; - $fname = "B<$args[2]>"; - $_ = $ret ? "$ret " : ""; - $_ .= "$fname $arguments ($kind)"; - } else { - $_ = "B<$args[1]> ($kind)\n\n$arguments"; - } - @args = (); - }; - - /^\@(deftp)\s*(.+)?$/ and do { - push @endwstack, $endw; - $endw = $1; - $arg = $2; - $arg =~ s/{([^}]*)}/$1/g; - $arg =~ s/\@$//; - @args = split (/ /, $arg); - $_ = ""; - }; - - /^\@(deftypefn)\s*(.+)?$/ and do { - push @endwstack, $endw; - $endw = $1; - $arg = $2; - $arg =~ s/{([^}]*)}/$1/g; - $arg =~ s/\@$//; - @args = split (/ /, $arg); - $_ = ""; - }; - - /^\@itemx?\s*(.+)?$/ and do { - if (defined $1) { - if ($ic eq "") { - $_ = "\n=item $1\n"; - } else { - # Entity escapes prevent munging by the <> processing below. - $_ = "\n=item $ic\<$1\>\n"; - } - } else { - $_ = "\n=item $ic\n"; - $ic =~ y/A-Ya-y/B-Zb-z/; - $ic =~ s/(\d+)/$1 + 1/eg; - } - }; - - $section .= $shift.$_."\n"; -} -# End of current file. -close($inf); -$inf = pop @instack; -} - -die "No filename or title\n" unless defined $fn && defined $tl; - -print "=encoding $encoding\n\n" if defined $encoding; - -$sects{NAME} = "$fn \- $tl\n"; -$sects{FOOTNOTES} .= "=back\n" if exists $sects{FOOTNOTES}; - -for $sect (qw(NAME SYNOPSIS DESCRIPTION OPTIONS ENVIRONMENT FILES - BUGS NOTES FOOTNOTES EXAMPLES SEEALSO AUTHOR COPYRIGHT)) { - if(exists $sects{$sect}) { - $head = $sect; - $head =~ s/SEEALSO/SEE ALSO/; - print "=head1 $head\n\n"; - print scalar unmunge ($sects{$sect}); - print "\n"; - } -} - -sub usage -{ - die "usage: $0 [-D toggle...] [infile [outfile]]\n"; -} - -sub postprocess -{ - local $_ = $_[0]; - - # @value{foo} is replaced by whatever 'foo' is defined as. - while (m/(\@value\{([a-zA-Z0-9_-]+)\})/g) { - if (! exists $defs{$2}) { - print STDERR "Option $2 not defined\n"; - s/\Q$1\E//; - } else { - $value = $defs{$2}; - s/\Q$1\E/$value/; - } - } - - # Formatting commands. - # Temporary escape for @r. - s/\@r\{([^\}]*)\}/R<$1>/g; - s/\@(?:dfn|var|emph|cite|i)\{([^\}]*)\}/I<$1>/g; - s/\@(?:code|kbd)\{([^\}]*)\}/C<$1>/g; - s/\@(?:gccoptlist|samp|strong|key|option|env|command|b)\{([^\}]*)\}/B<$1>/g; - s/\@sc\{([^\}]*)\}/\U$1/g; - s/\@file\{([^\}]*)\}/F<$1>/g; - s/\@w\{([^\}]*)\}/S<$1>/g; - s/\@t\{([^\}]*)\}/$1/g; - s/\@(?:dmn|math)\{([^\}]*)\}/$1/g; - - # keep references of the form @ref{...}, print them bold - s/\@(?:ref)\{([^\}]*)\}/B<$1>/g; - - # Change double single quotes to double quotes. - s/''/"/g; - s/``/"/g; - - # Cross references are thrown away, as are @noindent and @refill. - # (@noindent is impossible in .pod, and @refill is unnecessary.) - # @* is also impossible in .pod; we discard it and any newline that - # follows it. Similarly, our macro @gol must be discarded. - - s/\(?\@xref\{(?:[^\}]*)\}(?:[^.<]|(?:<[^<>]*>))*\.\)?//g; - s/\s+\(\@pxref\{(?:[^\}]*)\}\)//g; - s/;\s+\@pxref\{(?:[^\}]*)\}//g; - s/\@noindent\s*//g; - s/\@refill//g; - s/\@gol//g; - s/\@\*\s*\n?//g; - - # Anchors are thrown away - s/\@anchor\{(?:[^\}]*)\}//g; - - # @uref can take one, two, or three arguments, with different - # semantics each time. @url and @email are just like @uref with - # one argument, for our purposes. - s/\@(?:uref|url|email)\{([^\},]*)\}/<B<$1>>/g; - s/\@uref\{([^\},]*),([^\},]*)\}/$2 (C<$1>)/g; - s/\@uref\{([^\},]*),([^\},]*),([^\},]*)\}/$3/g; - - # Un-escape <> at this point. - s/<//g; - - # Now un-nest all B<>, I<>, R<>. Theoretically we could have - # indefinitely deep nesting; in practice, one level suffices. - 1 while s/([BIR])<([^<>]*)([BIR])<([^<>]*)>/$1<$2>$3<$4>$1 with bare ...; eliminate empty markup, B<>; - # shift white space at the ends of [BI]<...> expressions outside - # the expression. - s/R<([^<>]*)>/$1/g; - s/[BI]<>//g; - s/([BI])<(\s+)([^>]+)>/$2$1<$3>/g; - s/([BI])<([^>]+?)(\s+)>/$1<$2>$3/g; - - # Extract footnotes. This has to be done after all other - # processing because otherwise the regexp will choke on formatting - # inside @footnote. - while (/\@footnote/g) { - s/\@footnote\{([^\}]+)\}/[$fnno]/; - add_footnote($1, $fnno); - $fnno++; - } - - return $_; -} - -sub unmunge -{ - # Replace escaped symbols with their equivalents. - local $_ = $_[0]; - - s/</E/g; - s/>/E/g; - s/{/\{/g; - s/}/\}/g; - s/&at;/\@/g; - s/&/&/g; - return $_; -} - -sub add_footnote -{ - unless (exists $sects{FOOTNOTES}) { - $sects{FOOTNOTES} = "\n=over 4\n\n"; - } - - $sects{FOOTNOTES} .= "=item $fnno.\n\n"; $fnno++; - $sects{FOOTNOTES} .= $_[0]; - $sects{FOOTNOTES} .= "\n\n"; -} - -# stolen from Symbol.pm -{ - my $genseq = 0; - sub gensym - { - my $name = "GEN" . $genseq++; - my $ref = \*{$name}; - delete $::{$name}; - return $ref; - } -} diff --git a/scripts/tracetool.py b/scripts/tracetool.py index 264cc9eeccf80c6a37e37983aabe04aee9495217..31146242b77d6a6bf2a1c347a82eeec390b6e42a 100755 --- a/scripts/tracetool.py +++ b/scripts/tracetool.py @@ -10,7 +10,7 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" import sys diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py index 13d29f1e42faf25de738a7bc028893adbee5ff90..3ee54be223c6bfd1ba54988b1c1143a270c2fe42 100644 --- a/scripts/tracetool/__init__.py +++ b/scripts/tracetool/__init__.py @@ -9,7 +9,7 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" import re @@ -34,7 +34,7 @@ def error(*lines): def out(*lines, **kwargs): """Write a set of output lines. - You can use kwargs as a shorthand for mapping variables when formating all + You can use kwargs as a shorthand for mapping variables when formatting all the strings in lines. """ lines = [ l % kwargs for l in lines ] diff --git a/scripts/tracetool/backend/__init__.py b/scripts/tracetool/backend/__init__.py index 54cab2c4de58e7f9050e4323d182da05350ba03c..7bfcc86cc5366863a6842dea109e96fccc0eb099 100644 --- a/scripts/tracetool/backend/__init__.py +++ b/scripts/tracetool/backend/__init__.py @@ -50,7 +50,7 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" import os diff --git a/scripts/tracetool/backend/dtrace.py b/scripts/tracetool/backend/dtrace.py index 638990db790465af7350b9fd111cb4fd7be7967f..e17edc9b9d829a4dfc8d11d24a4fdcb465159992 100644 --- a/scripts/tracetool/backend/dtrace.py +++ b/scripts/tracetool/backend/dtrace.py @@ -9,7 +9,7 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" from tracetool import out @@ -38,11 +38,21 @@ def generate_h_begin(events, group): if group == "root": header = "trace-dtrace-root.h" else: - header = "trace-dtrace.h" + header = "trace-dtrace-%s.h" % group + + # Workaround for ust backend, which also includes and may + # require SDT_USE_VARIADIC to be defined. If dtrace includes + # first without defining SDT_USE_VARIADIC then ust breaks because the + # STAP_PROBEV() macro is not defined. + out('#ifndef SDT_USE_VARIADIC') + out('#define SDT_USE_VARIADIC 1') + out('#endif') out('#include "%s"' % header, '') + out('#undef SDT_USE_VARIADIC') + # SystemTap defines __ENABLED() but other DTrace # implementations might not. for e in events: diff --git a/scripts/tracetool/backend/log.py b/scripts/tracetool/backend/log.py index 23b274c0fd36411f30d102ced22064560455bfa7..877222bbe9b7093423d3c8d0be8e619fa2307982 100644 --- a/scripts/tracetool/backend/log.py +++ b/scripts/tracetool/backend/log.py @@ -9,7 +9,7 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" from tracetool import out diff --git a/scripts/tracetool/backend/simple.py b/scripts/tracetool/backend/simple.py index b650c262b5983390e2f252a0f5ba70d48d2ecc3b..a74d61fcd64d3d2379ea961061ee729ae17cbe19 100644 --- a/scripts/tracetool/backend/simple.py +++ b/scripts/tracetool/backend/simple.py @@ -9,7 +9,7 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" from tracetool import out diff --git a/scripts/tracetool/backend/ust.py b/scripts/tracetool/backend/ust.py index a772a3b53b3add99b56b73572af1772c906ef5a3..c857516f212617b6ff0f45df3101fe127f867ff7 100644 --- a/scripts/tracetool/backend/ust.py +++ b/scripts/tracetool/backend/ust.py @@ -9,7 +9,7 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" from tracetool import out @@ -19,11 +19,7 @@ def generate_h_begin(events, group): - if group == "root": - header = "trace-ust-root.h" - else: - header = "trace-ust.h" - + header = 'trace-ust-' + group + '.h' out('#include ', '#include "%s"' % header, '', diff --git a/scripts/tracetool/format/__init__.py b/scripts/tracetool/format/__init__.py index aba2f7a441f8013395ed6a842e565c6dfbd6079b..2dc46f3dd93e4d9fdd58a3cfa77efe6100a9adbe 100644 --- a/scripts/tracetool/format/__init__.py +++ b/scripts/tracetool/format/__init__.py @@ -32,7 +32,7 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" import os diff --git a/scripts/tracetool/format/c.py b/scripts/tracetool/format/c.py index 78af8aff7201439aad4ad2396136e97a2a5410ee..c390c1844af6d717d7c718bd8aaf268f7c4f9f74 100644 --- a/scripts/tracetool/format/c.py +++ b/scripts/tracetool/format/c.py @@ -9,7 +9,7 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" from tracetool import out @@ -19,10 +19,7 @@ def generate(events, backend, group): active_events = [e for e in events if "disable" not in e.properties] - if group == "root": - header = "trace-root.h" - else: - header = "trace.h" + header = "trace-" + group + ".h" out('/* This file is autogenerated by tracetool, do not edit. */', '', diff --git a/scripts/tracetool/format/d.py b/scripts/tracetool/format/d.py index d3980b914b111ab0395b11bc414e2d76cdef5f4a..ebfb7142002660527bfdc0476bc8cfb6713994ae 100644 --- a/scripts/tracetool/format/d.py +++ b/scripts/tracetool/format/d.py @@ -9,10 +9,11 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" from tracetool import out +from sys import platform # Reserved keywords from @@ -34,7 +35,8 @@ def generate(events, backend, group): # SystemTap's dtrace(1) warns about empty "provider qemu {}" but is happy # with an empty file. Avoid the warning. - if not events: + # But dtrace on macOS can't deal with empty files. + if not events and platform != "darwin": return out('/* This file is autogenerated by tracetool, do not edit. */' @@ -44,6 +46,23 @@ def generate(events, backend, group): for e in events: args = [] for type_, name in e.args: + if platform == "darwin": + # macOS dtrace accepts only C99 _Bool + if type_ == 'bool': + type_ = '_Bool' + if type_ == 'bool *': + type_ = '_Bool *' + # It converts int8_t * in probe points to char * in header + # files and introduces [-Wpointer-sign] warning. + # Avoid it by changing probe type to signed char * beforehand. + if type_ == 'int8_t *': + type_ = 'signed char *' + + # SystemTap dtrace(1) emits a warning when long long is used + type_ = type_.replace('unsigned long long', 'uint64_t') + type_ = type_.replace('signed long long', 'int64_t') + type_ = type_.replace('long long', 'int64_t') + if name in RESERVED_WORDS: name += '_' args.append(type_ + ' ' + name) diff --git a/scripts/tracetool/format/h.py b/scripts/tracetool/format/h.py index 83e1a2f355b454bf5d9f50a7856e564de53aa2c2..e94f0be7dafddd90d6f3757059937cc0b07f3984 100644 --- a/scripts/tracetool/format/h.py +++ b/scripts/tracetool/format/h.py @@ -9,7 +9,7 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" from tracetool import out diff --git a/scripts/tracetool/format/stap.py b/scripts/tracetool/format/stap.py index 8fc808f2efcc2fd97f3d9b1c55cf6523baaee2c9..a218b0445c9b1d724e941c80c82ee0f1cd70fbd1 100644 --- a/scripts/tracetool/format/stap.py +++ b/scripts/tracetool/format/stap.py @@ -9,7 +9,7 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" from tracetool import out diff --git a/scripts/tracetool/format/tcg_h.py b/scripts/tracetool/format/tcg_h.py index 0180e3d76cfb5aa1c3a603469aec455788f8d120..4d84440aff866603d0d2c6d195f4dad1f6fa99f9 100644 --- a/scripts/tracetool/format/tcg_h.py +++ b/scripts/tracetool/format/tcg_h.py @@ -9,7 +9,7 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" from tracetool import out, Arguments @@ -28,7 +28,7 @@ def vcpu_transform_args(args): def generate(events, backend, group): if group == "root": - header = "trace-root.h" + header = "trace/trace-root.h" else: header = "trace.h" diff --git a/scripts/tracetool/format/tcg_helper_c.py b/scripts/tracetool/format/tcg_helper_c.py index 6527b69afd2fd2d1336c429b4e9ba04e8df53c17..72576e67d1939e616e580738f8116cd89082f543 100644 --- a/scripts/tracetool/format/tcg_helper_c.py +++ b/scripts/tracetool/format/tcg_helper_c.py @@ -9,7 +9,7 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" from tracetool import Arguments, out @@ -41,7 +41,7 @@ def vcpu_transform_args(args, mode): def generate(events, backend, group): if group == "root": - header = "trace-root.h" + header = "trace/trace-root.h" else: header = "trace.h" diff --git a/scripts/tracetool/format/tcg_helper_h.py b/scripts/tracetool/format/tcg_helper_h.py index 98ebe52f1807e67f6253a8f2db2ffaf3a6691e96..08554fbc85d2ced6c4963fcd427e744dfe205716 100644 --- a/scripts/tracetool/format/tcg_helper_h.py +++ b/scripts/tracetool/format/tcg_helper_h.py @@ -9,7 +9,7 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" from tracetool import out diff --git a/scripts/tracetool/format/tcg_helper_wrapper_h.py b/scripts/tracetool/format/tcg_helper_wrapper_h.py index 6adeab74df0bf3e088172fc552afde6f83d10890..0c5a9797d1d1ef7f09ffdef4c8be38db8bcbb8e2 100644 --- a/scripts/tracetool/format/tcg_helper_wrapper_h.py +++ b/scripts/tracetool/format/tcg_helper_wrapper_h.py @@ -9,7 +9,7 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" from tracetool import out diff --git a/scripts/tracetool/transform.py b/scripts/tracetool/transform.py index 8fd4dcf20dc4500e94b49b8b1a62a903d7e98774..ea8b27799dcae5320ffcc1de7808a480e57a5f42 100644 --- a/scripts/tracetool/transform.py +++ b/scripts/tracetool/transform.py @@ -9,7 +9,7 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" def _transform_type(type_, trans): diff --git a/scripts/tracetool/vcpu.py b/scripts/tracetool/vcpu.py index 0b104e4f15c2f8e4541d3671cf1d5915177b3734..868b4cb04c457a7d47cddba7f7776067a350eb07 100644 --- a/scripts/tracetool/vcpu.py +++ b/scripts/tracetool/vcpu.py @@ -10,7 +10,7 @@ __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" -__email__ = "stefanha@linux.vnet.ibm.com" +__email__ = "stefanha@redhat.com" from tracetool import Arguments, try_import @@ -24,7 +24,7 @@ def transform_event(event): assert "tcg-trans" not in event.properties assert "tcg-exec" not in event.properties - event.args = Arguments([("CPUState *", "__cpu"), event.args]) + event.args = Arguments([("void *", "__cpu"), event.args]) if "tcg" in event.properties: fmt = "\"cpu=%p \"" event.fmt = [fmt + event.fmt[0], diff --git a/scripts/u2f-setup-gen.py b/scripts/u2f-setup-gen.py new file mode 100755 index 0000000000000000000000000000000000000000..2122598fed8e2028e44ef94bf06bec44636671e9 --- /dev/null +++ b/scripts/u2f-setup-gen.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python3 +# +# Libu2f-emu setup directory generator for USB U2F key emulation. +# +# Copyright (c) 2020 CĂ©sar Belley +# Written by CĂ©sar Belley +# +# This work is licensed under the terms of the GNU GPL, version 2 +# or, at your option, any later version. See the COPYING file in +# the top-level directory. + +import sys +import os +from random import randint +from typing import Tuple + +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.asymmetric import ec +from cryptography.hazmat.primitives.serialization import Encoding, \ + NoEncryption, PrivateFormat, PublicFormat +from OpenSSL import crypto + + +def write_setup_dir(dirpath: str, privkey_pem: bytes, cert_pem: bytes, + entropy: bytes, counter: int) -> None: + """ + Write the setup directory. + + Args: + dirpath: The directory path. + key_pem: The private key PEM. + cert_pem: The certificate PEM. + entropy: The 48 bytes of entropy. + counter: The counter value. + """ + # Directory + os.mkdir(dirpath) + + # Private key + with open(f'{dirpath}/private-key.pem', 'bw') as f: + f.write(privkey_pem) + + # Certificate + with open(f'{dirpath}/certificate.pem', 'bw') as f: + f.write(cert_pem) + + # Entropy + with open(f'{dirpath}/entropy', 'wb') as f: + f.write(entropy) + + # Counter + with open(f'{dirpath}/counter', 'w') as f: + f.write(f'{str(counter)}\n') + + +def generate_ec_key_pair() -> Tuple[str, str]: + """ + Generate an ec key pair. + + Returns: + The private and public key PEM. + """ + # Key generation + privkey = ec.generate_private_key(ec.SECP256R1, default_backend()) + pubkey = privkey.public_key() + + # PEM serialization + privkey_pem = privkey.private_bytes(encoding=Encoding.PEM, + format=PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=NoEncryption()) + pubkey_pem = pubkey.public_bytes(encoding=Encoding.PEM, + format=PublicFormat.SubjectPublicKeyInfo) + return privkey_pem, pubkey_pem + + +def generate_certificate(privkey_pem: str, pubkey_pem: str) -> str: + """ + Generate a x509 certificate from a key pair. + + Args: + privkey_pem: The private key PEM. + pubkey_pem: The public key PEM. + + Returns: + The certificate PEM. + """ + # Convert key pair + privkey = crypto.load_privatekey(crypto.FILETYPE_PEM, privkey_pem) + pubkey = crypto.load_publickey(crypto.FILETYPE_PEM, pubkey_pem) + + # New x509v3 certificate + cert = crypto.X509() + cert.set_version(0x2) + + # Serial number + cert.set_serial_number(randint(1, 2 ** 64)) + + # Before / After + cert.gmtime_adj_notBefore(0) + cert.gmtime_adj_notAfter(4 * (365 * 24 * 60 * 60)) + + # Public key + cert.set_pubkey(pubkey) + + # Subject name and issueer + cert.get_subject().CN = "U2F emulated" + cert.set_issuer(cert.get_subject()) + + # Extensions + cert.add_extensions([ + crypto.X509Extension(b"subjectKeyIdentifier", + False, b"hash", subject=cert), + ]) + cert.add_extensions([ + crypto.X509Extension(b"authorityKeyIdentifier", + False, b"keyid:always", issuer=cert), + ]) + cert.add_extensions([ + crypto.X509Extension(b"basicConstraints", True, b"CA:TRUE") + ]) + + # Signature + cert.sign(privkey, 'sha256') + + return crypto.dump_certificate(crypto.FILETYPE_PEM, cert) + + +def generate_setup_dir(dirpath: str) -> None: + """ + Generates the setup directory. + + Args: + dirpath: The directory path. + """ + # Key pair + privkey_pem, pubkey_pem = generate_ec_key_pair() + + # Certificate + certificate_pem = generate_certificate(privkey_pem, pubkey_pem) + + # Entropy + entropy = os.urandom(48) + + # Counter + counter = 0 + + # Write + write_setup_dir(dirpath, privkey_pem, certificate_pem, entropy, counter) + + +def main() -> None: + """ + Main function + """ + # Dir path + if len(sys.argv) != 2: + sys.stderr.write(f'Usage: {sys.argv[0]} \n') + exit(2) + dirpath = sys.argv[1] + + # Dir non existence + if os.path.exists(dirpath): + sys.stderr.write(f'Directory: {dirpath} already exists.\n') + exit(1) + + generate_setup_dir(dirpath) + + +if __name__ == '__main__': + main() diff --git a/scripts/undefsym.py b/scripts/undefsym.py new file mode 100644 index 0000000000000000000000000000000000000000..4b6a72d95f47dfe8eadef13700863857b42aa87b --- /dev/null +++ b/scripts/undefsym.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 + +# Before a shared module's DSO is produced, a static library is built for it +# and passed to this script. The script generates -Wl,-u options to force +# the inclusion of symbol from libqemuutil.a if the shared modules need them, +# This is necessary because the modules may use functions not needed by the +# executable itself, which would cause the function to not be linked in. +# Then the DSO loading would fail because of the missing symbol. + + +import sys +import subprocess + +def filter_lines_set(stdout, from_staticlib): + linesSet = set() + for line in stdout.splitlines(): + tokens = line.split(b' ') + if len(tokens) >= 2: + if from_staticlib and tokens[1] == b'U': + continue + if not from_staticlib and tokens[1] != b'U': + continue + new_line = b'-Wl,-u,' + tokens[0] + if not new_line in linesSet: + linesSet.add(new_line) + return linesSet + +def main(args): + if len(args) <= 3: + sys.exit(0) + + nm = args[1] + staticlib = args[2] + pc = subprocess.run([nm, "-P", "-g", staticlib], stdout=subprocess.PIPE) + if pc.returncode != 0: + sys.exit(1) + staticlib_syms = filter_lines_set(pc.stdout, True) + + shared_modules = args[3:] + pc = subprocess.run([nm, "-P", "-g"] + shared_modules, stdout=subprocess.PIPE) + if pc.returncode != 0: + sys.exit(1) + modules_undef_syms = filter_lines_set(pc.stdout, False) + lines = sorted(staticlib_syms.intersection(modules_undef_syms)) + sys.stdout.buffer.write(b'\n'.join(lines)) + +if __name__ == "__main__": + main(sys.argv) diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh index 29c27f46817750223bad3d98737e48f053c90aca..9efbaf2f84b38bee183517934b84fd5e05be9653 100755 --- a/scripts/update-linux-headers.sh +++ b/scripts/update-linux-headers.sh @@ -141,7 +141,7 @@ done rm -rf "$output/linux-headers/linux" mkdir -p "$output/linux-headers/linux" -for header in kvm.h vfio.h vfio_ccw.h vhost.h \ +for header in kvm.h vfio.h vfio_ccw.h vfio_zdev.h vhost.h \ psci.h psp-sev.h userfaultfd.h mman.h; do cp "$tmpdir/include/linux/$header" "$output/linux-headers/linux" done diff --git a/scsi/Makefile.objs b/scsi/Makefile.objs deleted file mode 100644 index bb8789cd8b3621c093430ed9c6b2d999b1d68fd6..0000000000000000000000000000000000000000 --- a/scsi/Makefile.objs +++ /dev/null @@ -1,4 +0,0 @@ -block-obj-y += utils.o - -block-obj-$(CONFIG_LINUX) += pr-manager.o pr-manager-helper.o -block-obj-$(call lnot,$(CONFIG_LINUX)) += pr-manager-stub.o diff --git a/scsi/meson.build b/scsi/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..53f3a1f71693c94d980b819a2e7ddb8887973128 --- /dev/null +++ b/scsi/meson.build @@ -0,0 +1,4 @@ +block_ss.add(files('utils.c')) +block_ss.add(when: 'CONFIG_LINUX', + if_true: files('pr-manager.c', 'pr-manager-helper.c'), + if_false: files('pr-manager-stub.c')) diff --git a/scsi/pr-manager-helper.c b/scsi/pr-manager-helper.c index bf62cbec11bf88e26ec7eee6b7ee1e20838373d7..451c7631b76f36b60e581c3e7edc60c1853d7854 100644 --- a/scsi/pr-manager-helper.c +++ b/scsi/pr-manager-helper.c @@ -21,16 +21,15 @@ #include "qemu/module.h" #include +#include "qom/object.h" #define PR_MAX_RECONNECT_ATTEMPTS 5 #define TYPE_PR_MANAGER_HELPER "pr-manager-helper" -#define PR_MANAGER_HELPER(obj) \ - OBJECT_CHECK(PRManagerHelper, (obj), \ - TYPE_PR_MANAGER_HELPER) +OBJECT_DECLARE_SIMPLE_TYPE(PRManagerHelper, PR_MANAGER_HELPER) -typedef struct PRManagerHelper { +struct PRManagerHelper { /* */ PRManager parent; @@ -38,15 +37,14 @@ typedef struct PRManagerHelper { QemuMutex lock; QIOChannel *ioc; -} PRManagerHelper; +}; static void pr_manager_send_status_changed_event(PRManagerHelper *pr_mgr) { - char *id = object_get_canonical_path_component(OBJECT(pr_mgr)); + const char *id = object_get_canonical_path_component(OBJECT(pr_mgr)); if (id) { qapi_event_send_pr_manager_status_changed(id, !!pr_mgr->ioc); - g_free(id); } } @@ -127,7 +125,7 @@ static int pr_manager_helper_initialize(PRManagerHelper *pr_mgr, qio_channel_set_delay(QIO_CHANNEL(sioc), false); pr_mgr->ioc = QIO_CHANNEL(sioc); - /* A simple feature negotation protocol, even though there is + /* A simple feature negotiation protocol, even though there is * no optional feature right now. */ r = pr_manager_helper_read(pr_mgr, &flags, sizeof(flags), errp); diff --git a/scsi/pr-manager.c b/scsi/pr-manager.c index 0c866e869835930767dacd3a0b218a75c2c16610..32b9287e680d7cdebf4f27ba9717126b8e6d97b9 100644 --- a/scsi/pr-manager.c +++ b/scsi/pr-manager.c @@ -128,7 +128,7 @@ static int query_one_pr_manager(Object *object, void *opaque) elem = g_new0(PRManagerInfoList, 1); info = g_new0(PRManagerInfo, 1); - info->id = object_get_canonical_path_component(object); + info->id = g_strdup(object_get_canonical_path_component(object)); info->connected = pr_manager_is_connected(pr_mgr); elem->value = info; elem->next = NULL; diff --git a/scsi/qemu-pr-helper.c b/scsi/qemu-pr-helper.c index 181ed4a186103bf15dc81ec98515595eabf74134..2733d92f2d814d42d91b25877d7dc03cee260b2e 100644 --- a/scsi/qemu-pr-helper.c +++ b/scsi/qemu-pr-helper.c @@ -747,7 +747,7 @@ static void coroutine_fn prh_co_entry(void *opaque) goto out; } - while (atomic_read(&state) == RUNNING) { + while (qatomic_read(&state) == RUNNING) { PRHelperRequest req; PRHelperResponse resp; int sz; @@ -816,7 +816,7 @@ static gboolean accept_client(QIOChannel *ioc, GIOCondition cond, gpointer opaqu static void termsig_handler(int signum) { - atomic_cmpxchg(&state, RUNNING, TERMINATE); + qatomic_cmpxchg(&state, RUNNING, TERMINATE); qemu_notify_event(); } @@ -884,7 +884,6 @@ int main(int argc, char **argv) int quiet = 0; int ch; Error *local_err = NULL; - char *trace_file = NULL; bool daemonize = false; bool pidfile_specified = false; bool socket_path_specified = false; @@ -968,8 +967,7 @@ int main(int argc, char **argv) ++loglevel; break; case 'T': - g_free(trace_file); - trace_file = trace_opt_parse(optarg); + trace_opt_parse(optarg); break; case 'V': version(argv[0]); @@ -992,7 +990,7 @@ int main(int argc, char **argv) if (!trace_init_backends()) { exit(EXIT_FAILURE); } - trace_init_file(trace_file); + trace_init_file(); qemu_set_log(LOG_TRACE); #ifdef CONFIG_MPATH @@ -1030,8 +1028,8 @@ int main(int argc, char **argv) server_ioc = qio_channel_socket_new_fd(FIRST_SOCKET_ACTIVATION_FD, &local_err); if (server_ioc == NULL) { - error_report("Failed to use socket activation: %s", - error_get_pretty(local_err)); + error_reportf_err(local_err, + "Failed to use socket activation: "); exit(EXIT_FAILURE); } } diff --git a/scsi/trace.h b/scsi/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..3e4d89a3a501a24b4e4a83325f6de507b611f8d7 --- /dev/null +++ b/scsi/trace.h @@ -0,0 +1 @@ +#include "trace/trace-scsi.h" diff --git a/scsi/utils.c b/scsi/utils.c index c50e81fdb87f535e6f49dd31699e0d4c6423c09f..b37c283014899c7b3a9ff98e04a0cdcca9ec6424 100644 --- a/scsi/utils.c +++ b/scsi/utils.c @@ -32,17 +32,13 @@ uint32_t scsi_cdb_xfer(uint8_t *buf) switch (buf[0] >> 5) { case 0: return buf[4]; - break; case 1: case 2: return lduw_be_p(&buf[7]); - break; case 4: return ldl_be_p(&buf[10]) & 0xffffffffULL; - break; case 5: return ldl_be_p(&buf[6]) & 0xffffffffULL; - break; default: return -1; } diff --git a/slirp b/slirp index 2faae0f778f818fadc873308f983289df697eb93..8f43a99191afb47ca3f3c6972f6306209f367ece 160000 --- a/slirp +++ b/slirp @@ -1 +1 @@ -Subproject commit 2faae0f778f818fadc873308f983289df697eb93 +Subproject commit 8f43a99191afb47ca3f3c6972f6306209f367ece diff --git a/softmmu/Makefile.objs b/softmmu/Makefile.objs deleted file mode 100644 index dd15c24346fb0483db716d7d751f548974e731b7..0000000000000000000000000000000000000000 --- a/softmmu/Makefile.objs +++ /dev/null @@ -1,3 +0,0 @@ -softmmu-main-y = softmmu/main.o -obj-y += vl.o -vl.o-cflags := $(GPROF_CFLAGS) $(SDL_CFLAGS) diff --git a/arch_init.c b/softmmu/arch_init.c similarity index 98% rename from arch_init.c rename to softmmu/arch_init.c index d9eb0ec1dd0382e03beac6bfaea6b2b69186a0fb..7fd5c09b2b93edd2fe66c9032e590c958111f671 100644 --- a/arch_init.c +++ b/softmmu/arch_init.c @@ -27,7 +27,6 @@ #include "sysemu/arch_init.h" #include "hw/pci/pci.h" #include "hw/audio/soundhw.h" -#include "qapi/qapi-commands-misc.h" #include "qapi/error.h" #include "qemu/config-file.h" #include "qemu/error-report.h" @@ -91,6 +90,8 @@ int graphic_depth = 32; #define QEMU_ARCH QEMU_ARCH_UNICORE32 #elif defined(TARGET_XTENSA) #define QEMU_ARCH QEMU_ARCH_XTENSA +#elif defined(TARGET_AVR) +#define QEMU_ARCH QEMU_ARCH_AVR #endif const uint32_t arch_type = QEMU_ARCH; diff --git a/balloon.c b/softmmu/balloon.c similarity index 88% rename from balloon.c rename to softmmu/balloon.c index f104b42961b08dc5c4407178ea20f5cc382fcc51..e0e8969a4b926a89f2cc9e2cae060bac63e62428 100644 --- a/balloon.c +++ b/softmmu/balloon.c @@ -28,31 +28,14 @@ #include "qemu/atomic.h" #include "sysemu/kvm.h" #include "sysemu/balloon.h" -#include "trace-root.h" #include "qapi/error.h" -#include "qapi/qapi-commands-misc.h" +#include "qapi/qapi-commands-machine.h" #include "qapi/qmp/qerror.h" +#include "trace.h" static QEMUBalloonEvent *balloon_event_fn; static QEMUBalloonStatus *balloon_stat_fn; static void *balloon_opaque; -static int balloon_inhibit_count; - -bool qemu_balloon_is_inhibited(void) -{ - return atomic_read(&balloon_inhibit_count) > 0; -} - -void qemu_balloon_inhibit(bool state) -{ - if (state) { - atomic_inc(&balloon_inhibit_count); - } else { - atomic_dec(&balloon_inhibit_count); - } - - assert(atomic_read(&balloon_inhibit_count) >= 0); -} static bool have_balloon(Error **errp) { diff --git a/bootdevice.c b/softmmu/bootdevice.c similarity index 98% rename from bootdevice.c rename to softmmu/bootdevice.c index 0ff55e2b79d9e010d7901c67f9db4d8820e22552..add4e3d2d1297f0f27c32643f364c1c6dd7ea7e7 100644 --- a/bootdevice.c +++ b/softmmu/bootdevice.c @@ -297,22 +297,19 @@ static void device_set_bootindex(Object *obj, Visitor *v, const char *name, int32_t boot_index; Error *local_err = NULL; - visit_type_int32(v, name, &boot_index, &local_err); - if (local_err) { - goto out; + if (!visit_type_int32(v, name, &boot_index, errp)) { + return; } /* check whether bootindex is present in fw_boot_order list */ check_boot_index(boot_index, &local_err); if (local_err) { - goto out; + error_propagate(errp, local_err); + return; } /* change bootindex to a new one */ *prop->bootindex = boot_index; add_boot_device_path(*prop->bootindex, prop->dev, prop->suffix); - -out: - error_propagate(errp, local_err); } static void property_release_bootindex(Object *obj, const char *name, @@ -342,7 +339,7 @@ void device_add_bootindex_property(Object *obj, int32_t *bootindex, prop); /* initialize devices' bootindex property to -1 */ - object_property_set_int(obj, -1, name, NULL); + object_property_set_int(obj, name, -1, NULL); } typedef struct FWLCHSEntry FWLCHSEntry; diff --git a/softmmu/cpu-throttle.c b/softmmu/cpu-throttle.c new file mode 100644 index 0000000000000000000000000000000000000000..2ec4b8e0bc13303681a1f20f876a0cee4eaa9893 --- /dev/null +++ b/softmmu/cpu-throttle.c @@ -0,0 +1,122 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/thread.h" +#include "hw/core/cpu.h" +#include "qemu/main-loop.h" +#include "sysemu/cpus.h" +#include "sysemu/cpu-throttle.h" + +/* vcpu throttling controls */ +static QEMUTimer *throttle_timer; +static unsigned int throttle_percentage; + +#define CPU_THROTTLE_PCT_MIN 1 +#define CPU_THROTTLE_PCT_MAX 99 +#define CPU_THROTTLE_TIMESLICE_NS 10000000 + +static void cpu_throttle_thread(CPUState *cpu, run_on_cpu_data opaque) +{ + double pct; + double throttle_ratio; + int64_t sleeptime_ns, endtime_ns; + + if (!cpu_throttle_get_percentage()) { + return; + } + + pct = (double)cpu_throttle_get_percentage() / 100; + throttle_ratio = pct / (1 - pct); + /* Add 1ns to fix double's rounding error (like 0.9999999...) */ + sleeptime_ns = (int64_t)(throttle_ratio * CPU_THROTTLE_TIMESLICE_NS + 1); + endtime_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + sleeptime_ns; + while (sleeptime_ns > 0 && !cpu->stop) { + if (sleeptime_ns > SCALE_MS) { + qemu_cond_timedwait_iothread(cpu->halt_cond, + sleeptime_ns / SCALE_MS); + } else { + qemu_mutex_unlock_iothread(); + g_usleep(sleeptime_ns / SCALE_US); + qemu_mutex_lock_iothread(); + } + sleeptime_ns = endtime_ns - qemu_clock_get_ns(QEMU_CLOCK_REALTIME); + } + qatomic_set(&cpu->throttle_thread_scheduled, 0); +} + +static void cpu_throttle_timer_tick(void *opaque) +{ + CPUState *cpu; + double pct; + + /* Stop the timer if needed */ + if (!cpu_throttle_get_percentage()) { + return; + } + CPU_FOREACH(cpu) { + if (!qatomic_xchg(&cpu->throttle_thread_scheduled, 1)) { + async_run_on_cpu(cpu, cpu_throttle_thread, + RUN_ON_CPU_NULL); + } + } + + pct = (double)cpu_throttle_get_percentage() / 100; + timer_mod(throttle_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT) + + CPU_THROTTLE_TIMESLICE_NS / (1 - pct)); +} + +void cpu_throttle_set(int new_throttle_pct) +{ + /* Ensure throttle percentage is within valid range */ + new_throttle_pct = MIN(new_throttle_pct, CPU_THROTTLE_PCT_MAX); + new_throttle_pct = MAX(new_throttle_pct, CPU_THROTTLE_PCT_MIN); + + qatomic_set(&throttle_percentage, new_throttle_pct); + + timer_mod(throttle_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT) + + CPU_THROTTLE_TIMESLICE_NS); +} + +void cpu_throttle_stop(void) +{ + qatomic_set(&throttle_percentage, 0); +} + +bool cpu_throttle_active(void) +{ + return (cpu_throttle_get_percentage() != 0); +} + +int cpu_throttle_get_percentage(void) +{ + return qatomic_read(&throttle_percentage); +} + +void cpu_throttle_init(void) +{ + throttle_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT, + cpu_throttle_timer_tick, NULL); +} diff --git a/softmmu/cpu-timers.c b/softmmu/cpu-timers.c new file mode 100644 index 0000000000000000000000000000000000000000..1eb7c675c18bda7773d4a9c549f0157c6e978a83 --- /dev/null +++ b/softmmu/cpu-timers.c @@ -0,0 +1,279 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/cutils.h" +#include "migration/vmstate.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "exec/exec-all.h" +#include "sysemu/cpus.h" +#include "sysemu/qtest.h" +#include "qemu/main-loop.h" +#include "qemu/option.h" +#include "qemu/seqlock.h" +#include "sysemu/replay.h" +#include "sysemu/runstate.h" +#include "hw/core/cpu.h" +#include "sysemu/cpu-timers.h" +#include "sysemu/cpu-throttle.h" +#include "timers-state.h" + +/* clock and ticks */ + +static int64_t cpu_get_ticks_locked(void) +{ + int64_t ticks = timers_state.cpu_ticks_offset; + if (timers_state.cpu_ticks_enabled) { + ticks += cpu_get_host_ticks(); + } + + if (timers_state.cpu_ticks_prev > ticks) { + /* Non increasing ticks may happen if the host uses software suspend. */ + timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks; + ticks = timers_state.cpu_ticks_prev; + } + + timers_state.cpu_ticks_prev = ticks; + return ticks; +} + +/* + * return the time elapsed in VM between vm_start and vm_stop. + * cpu_get_ticks() uses units of the host CPU cycle counter. + */ +int64_t cpu_get_ticks(void) +{ + int64_t ticks; + + qemu_spin_lock(&timers_state.vm_clock_lock); + ticks = cpu_get_ticks_locked(); + qemu_spin_unlock(&timers_state.vm_clock_lock); + return ticks; +} + +int64_t cpu_get_clock_locked(void) +{ + int64_t time; + + time = timers_state.cpu_clock_offset; + if (timers_state.cpu_ticks_enabled) { + time += get_clock(); + } + + return time; +} + +/* + * Return the monotonic time elapsed in VM, i.e., + * the time between vm_start and vm_stop + */ +int64_t cpu_get_clock(void) +{ + int64_t ti; + unsigned start; + + do { + start = seqlock_read_begin(&timers_state.vm_clock_seqlock); + ti = cpu_get_clock_locked(); + } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start)); + + return ti; +} + +/* + * enable cpu_get_ticks() + * Caller must hold BQL which serves as mutex for vm_clock_seqlock. + */ +void cpu_enable_ticks(void) +{ + seqlock_write_lock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + if (!timers_state.cpu_ticks_enabled) { + timers_state.cpu_ticks_offset -= cpu_get_host_ticks(); + timers_state.cpu_clock_offset -= get_clock(); + timers_state.cpu_ticks_enabled = 1; + } + seqlock_write_unlock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); +} + +/* + * disable cpu_get_ticks() : the clock is stopped. You must not call + * cpu_get_ticks() after that. + * Caller must hold BQL which serves as mutex for vm_clock_seqlock. + */ +void cpu_disable_ticks(void) +{ + seqlock_write_lock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + if (timers_state.cpu_ticks_enabled) { + timers_state.cpu_ticks_offset += cpu_get_host_ticks(); + timers_state.cpu_clock_offset = cpu_get_clock_locked(); + timers_state.cpu_ticks_enabled = 0; + } + seqlock_write_unlock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); +} + +static bool icount_state_needed(void *opaque) +{ + return icount_enabled(); +} + +static bool warp_timer_state_needed(void *opaque) +{ + TimersState *s = opaque; + return s->icount_warp_timer != NULL; +} + +static bool adjust_timers_state_needed(void *opaque) +{ + TimersState *s = opaque; + return s->icount_rt_timer != NULL; +} + +static bool icount_shift_state_needed(void *opaque) +{ + return icount_enabled() == 2; +} + +/* + * Subsection for warp timer migration is optional, because may not be created + */ +static const VMStateDescription icount_vmstate_warp_timer = { + .name = "timer/icount/warp_timer", + .version_id = 1, + .minimum_version_id = 1, + .needed = warp_timer_state_needed, + .fields = (VMStateField[]) { + VMSTATE_INT64(vm_clock_warp_start, TimersState), + VMSTATE_TIMER_PTR(icount_warp_timer, TimersState), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription icount_vmstate_adjust_timers = { + .name = "timer/icount/timers", + .version_id = 1, + .minimum_version_id = 1, + .needed = adjust_timers_state_needed, + .fields = (VMStateField[]) { + VMSTATE_TIMER_PTR(icount_rt_timer, TimersState), + VMSTATE_TIMER_PTR(icount_vm_timer, TimersState), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription icount_vmstate_shift = { + .name = "timer/icount/shift", + .version_id = 1, + .minimum_version_id = 1, + .needed = icount_shift_state_needed, + .fields = (VMStateField[]) { + VMSTATE_INT16(icount_time_shift, TimersState), + VMSTATE_END_OF_LIST() + } +}; + +/* + * This is a subsection for icount migration. + */ +static const VMStateDescription icount_vmstate_timers = { + .name = "timer/icount", + .version_id = 1, + .minimum_version_id = 1, + .needed = icount_state_needed, + .fields = (VMStateField[]) { + VMSTATE_INT64(qemu_icount_bias, TimersState), + VMSTATE_INT64(qemu_icount, TimersState), + VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription * []) { + &icount_vmstate_warp_timer, + &icount_vmstate_adjust_timers, + &icount_vmstate_shift, + NULL + } +}; + +static const VMStateDescription vmstate_timers = { + .name = "timer", + .version_id = 2, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_INT64(cpu_ticks_offset, TimersState), + VMSTATE_UNUSED(8), + VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2), + VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription * []) { + &icount_vmstate_timers, + NULL + } +}; + +static void do_nothing(CPUState *cpu, run_on_cpu_data unused) +{ +} + +void qemu_timer_notify_cb(void *opaque, QEMUClockType type) +{ + if (!icount_enabled() || type != QEMU_CLOCK_VIRTUAL) { + qemu_notify_event(); + return; + } + + if (qemu_in_vcpu_thread()) { + /* + * A CPU is currently running; kick it back out to the + * tcg_cpu_exec() loop so it will recalculate its + * icount deadline immediately. + */ + qemu_cpu_kick(current_cpu); + } else if (first_cpu) { + /* + * qemu_cpu_kick is not enough to kick a halted CPU out of + * qemu_tcg_wait_io_event. async_run_on_cpu, instead, + * causes cpu_thread_is_idle to return false. This way, + * handle_icount_deadline can run. + * If we have no CPUs at all for some reason, we don't + * need to do anything. + */ + async_run_on_cpu(first_cpu, do_nothing, RUN_ON_CPU_NULL); + } +} + +TimersState timers_state; + +/* initialize timers state and the cpu throttle for convenience */ +void cpu_timers_init(void) +{ + seqlock_init(&timers_state.vm_clock_seqlock); + qemu_spin_init(&timers_state.vm_clock_lock); + vmstate_register(NULL, 0, &vmstate_timers, &timers_state); + + cpu_throttle_init(); +} diff --git a/softmmu/cpus.c b/softmmu/cpus.c new file mode 100644 index 0000000000000000000000000000000000000000..e46ac68ad096fd082c261588e39775f334386ad0 --- /dev/null +++ b/softmmu/cpus.c @@ -0,0 +1,799 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "monitor/monitor.h" +#include "qapi/error.h" +#include "qapi/qapi-commands-machine.h" +#include "qapi/qapi-commands-misc.h" +#include "qapi/qapi-events-run-state.h" +#include "qapi/qmp/qerror.h" +#include "exec/gdbstub.h" +#include "sysemu/hw_accel.h" +#include "exec/exec-all.h" +#include "qemu/thread.h" +#include "qemu/plugin.h" +#include "sysemu/cpus.h" +#include "qemu/guest-random.h" +#include "hw/nmi.h" +#include "sysemu/replay.h" +#include "sysemu/runstate.h" +#include "sysemu/cpu-timers.h" +#include "hw/boards.h" +#include "hw/hw.h" + +#ifdef CONFIG_LINUX + +#include + +#ifndef PR_MCE_KILL +#define PR_MCE_KILL 33 +#endif + +#ifndef PR_MCE_KILL_SET +#define PR_MCE_KILL_SET 1 +#endif + +#ifndef PR_MCE_KILL_EARLY +#define PR_MCE_KILL_EARLY 1 +#endif + +#endif /* CONFIG_LINUX */ + +static QemuMutex qemu_global_mutex; + +bool cpu_is_stopped(CPUState *cpu) +{ + return cpu->stopped || !runstate_is_running(); +} + +bool cpu_work_list_empty(CPUState *cpu) +{ + bool ret; + + qemu_mutex_lock(&cpu->work_mutex); + ret = QSIMPLEQ_EMPTY(&cpu->work_list); + qemu_mutex_unlock(&cpu->work_mutex); + return ret; +} + +bool cpu_thread_is_idle(CPUState *cpu) +{ + if (cpu->stop || !cpu_work_list_empty(cpu)) { + return false; + } + if (cpu_is_stopped(cpu)) { + return true; + } + if (!cpu->halted || cpu_has_work(cpu) || + kvm_halt_in_kernel()) { + return false; + } + return true; +} + +bool all_cpu_threads_idle(void) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + if (!cpu_thread_is_idle(cpu)) { + return false; + } + } + return true; +} + +/***********************************************************/ +void hw_error(const char *fmt, ...) +{ + va_list ap; + CPUState *cpu; + + va_start(ap, fmt); + fprintf(stderr, "qemu: hardware error: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + CPU_FOREACH(cpu) { + fprintf(stderr, "CPU #%d:\n", cpu->cpu_index); + cpu_dump_state(cpu, stderr, CPU_DUMP_FPU); + } + va_end(ap); + abort(); +} + +/* + * The chosen accelerator is supposed to register this. + */ +static const CpusAccel *cpus_accel; + +void cpu_synchronize_all_states(void) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + cpu_synchronize_state(cpu); + } +} + +void cpu_synchronize_all_post_reset(void) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + cpu_synchronize_post_reset(cpu); + } +} + +void cpu_synchronize_all_post_init(void) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + cpu_synchronize_post_init(cpu); + } +} + +void cpu_synchronize_all_pre_loadvm(void) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + cpu_synchronize_pre_loadvm(cpu); + } +} + +void cpu_synchronize_state(CPUState *cpu) +{ + if (cpus_accel->synchronize_state) { + cpus_accel->synchronize_state(cpu); + } +} + +void cpu_synchronize_post_reset(CPUState *cpu) +{ + if (cpus_accel->synchronize_post_reset) { + cpus_accel->synchronize_post_reset(cpu); + } +} + +void cpu_synchronize_post_init(CPUState *cpu) +{ + if (cpus_accel->synchronize_post_init) { + cpus_accel->synchronize_post_init(cpu); + } +} + +void cpu_synchronize_pre_loadvm(CPUState *cpu) +{ + if (cpus_accel->synchronize_pre_loadvm) { + cpus_accel->synchronize_pre_loadvm(cpu); + } +} + +int64_t cpus_get_virtual_clock(void) +{ + /* + * XXX + * + * need to check that cpus_accel is not NULL, because qcow2 calls + * qemu_get_clock_ns(CLOCK_VIRTUAL) without any accel initialized and + * with ticks disabled in some io-tests: + * 030 040 041 060 099 120 127 140 156 161 172 181 191 192 195 203 229 249 256 267 + * + * is this expected? + * + * XXX + */ + if (cpus_accel && cpus_accel->get_virtual_clock) { + return cpus_accel->get_virtual_clock(); + } + return cpu_get_clock(); +} + +/* + * return the time elapsed in VM between vm_start and vm_stop. Unless + * icount is active, cpus_get_elapsed_ticks() uses units of the host CPU cycle + * counter. + */ +int64_t cpus_get_elapsed_ticks(void) +{ + if (cpus_accel->get_elapsed_ticks) { + return cpus_accel->get_elapsed_ticks(); + } + return cpu_get_ticks(); +} + +static void generic_handle_interrupt(CPUState *cpu, int mask) +{ + cpu->interrupt_request |= mask; + + if (!qemu_cpu_is_self(cpu)) { + qemu_cpu_kick(cpu); + } +} + +void cpu_interrupt(CPUState *cpu, int mask) +{ + if (cpus_accel->handle_interrupt) { + cpus_accel->handle_interrupt(cpu, mask); + } else { + generic_handle_interrupt(cpu, mask); + } +} + +static int do_vm_stop(RunState state, bool send_stop) +{ + int ret = 0; + + if (runstate_is_running()) { + runstate_set(state); + cpu_disable_ticks(); + pause_all_vcpus(); + vm_state_notify(0, state); + if (send_stop) { + qapi_event_send_stop(); + } + } + + bdrv_drain_all(); + ret = bdrv_flush_all(); + + return ret; +} + +/* Special vm_stop() variant for terminating the process. Historically clients + * did not expect a QMP STOP event and so we need to retain compatibility. + */ +int vm_shutdown(void) +{ + return do_vm_stop(RUN_STATE_SHUTDOWN, false); +} + +bool cpu_can_run(CPUState *cpu) +{ + if (cpu->stop) { + return false; + } + if (cpu_is_stopped(cpu)) { + return false; + } + return true; +} + +void cpu_handle_guest_debug(CPUState *cpu) +{ + if (replay_running_debug()) { + if (!cpu->singlestep_enabled) { + /* + * Report about the breakpoint and + * make a single step to skip it + */ + replay_breakpoint(); + cpu_single_step(cpu, SSTEP_ENABLE); + } else { + cpu_single_step(cpu, 0); + } + } else { + gdb_set_stop_cpu(cpu); + qemu_system_debug_request(); + cpu->stopped = true; + } +} + +#ifdef CONFIG_LINUX +static void sigbus_reraise(void) +{ + sigset_t set; + struct sigaction action; + + memset(&action, 0, sizeof(action)); + action.sa_handler = SIG_DFL; + if (!sigaction(SIGBUS, &action, NULL)) { + raise(SIGBUS); + sigemptyset(&set); + sigaddset(&set, SIGBUS); + pthread_sigmask(SIG_UNBLOCK, &set, NULL); + } + perror("Failed to re-raise SIGBUS!\n"); + abort(); +} + +static void sigbus_handler(int n, siginfo_t *siginfo, void *ctx) +{ + if (siginfo->si_code != BUS_MCEERR_AO && siginfo->si_code != BUS_MCEERR_AR) { + sigbus_reraise(); + } + + if (current_cpu) { + /* Called asynchronously in VCPU thread. */ + if (kvm_on_sigbus_vcpu(current_cpu, siginfo->si_code, siginfo->si_addr)) { + sigbus_reraise(); + } + } else { + /* Called synchronously (via signalfd) in main thread. */ + if (kvm_on_sigbus(siginfo->si_code, siginfo->si_addr)) { + sigbus_reraise(); + } + } +} + +static void qemu_init_sigbus(void) +{ + struct sigaction action; + + memset(&action, 0, sizeof(action)); + action.sa_flags = SA_SIGINFO; + action.sa_sigaction = sigbus_handler; + sigaction(SIGBUS, &action, NULL); + + prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0); +} +#else /* !CONFIG_LINUX */ +static void qemu_init_sigbus(void) +{ +} +#endif /* !CONFIG_LINUX */ + +static QemuThread io_thread; + +/* cpu creation */ +static QemuCond qemu_cpu_cond; +/* system init */ +static QemuCond qemu_pause_cond; + +void qemu_init_cpu_loop(void) +{ + qemu_init_sigbus(); + qemu_cond_init(&qemu_cpu_cond); + qemu_cond_init(&qemu_pause_cond); + qemu_mutex_init(&qemu_global_mutex); + + qemu_thread_get_self(&io_thread); +} + +void run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data) +{ + do_run_on_cpu(cpu, func, data, &qemu_global_mutex); +} + +static void qemu_cpu_stop(CPUState *cpu, bool exit) +{ + g_assert(qemu_cpu_is_self(cpu)); + cpu->stop = false; + cpu->stopped = true; + if (exit) { + cpu_exit(cpu); + } + qemu_cond_broadcast(&qemu_pause_cond); +} + +void qemu_wait_io_event_common(CPUState *cpu) +{ + qatomic_mb_set(&cpu->thread_kicked, false); + if (cpu->stop) { + qemu_cpu_stop(cpu, false); + } + process_queued_cpu_work(cpu); +} + +void qemu_wait_io_event(CPUState *cpu) +{ + bool slept = false; + + while (cpu_thread_is_idle(cpu)) { + if (!slept) { + slept = true; + qemu_plugin_vcpu_idle_cb(cpu); + } + qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex); + } + if (slept) { + qemu_plugin_vcpu_resume_cb(cpu); + } + +#ifdef _WIN32 + /* Eat dummy APC queued by cpus_kick_thread. */ + if (hax_enabled()) { + SleepEx(0, TRUE); + } +#endif + qemu_wait_io_event_common(cpu); +} + +void cpus_kick_thread(CPUState *cpu) +{ +#ifndef _WIN32 + int err; + + if (cpu->thread_kicked) { + return; + } + cpu->thread_kicked = true; + err = pthread_kill(cpu->thread->thread, SIG_IPI); + if (err && err != ESRCH) { + fprintf(stderr, "qemu:%s: %s", __func__, strerror(err)); + exit(1); + } +#endif +} + +void qemu_cpu_kick(CPUState *cpu) +{ + qemu_cond_broadcast(cpu->halt_cond); + if (cpus_accel->kick_vcpu_thread) { + cpus_accel->kick_vcpu_thread(cpu); + } else { /* default */ + cpus_kick_thread(cpu); + } +} + +void qemu_cpu_kick_self(void) +{ + assert(current_cpu); + cpus_kick_thread(current_cpu); +} + +bool qemu_cpu_is_self(CPUState *cpu) +{ + return qemu_thread_is_self(cpu->thread); +} + +bool qemu_in_vcpu_thread(void) +{ + return current_cpu && qemu_cpu_is_self(current_cpu); +} + +static __thread bool iothread_locked = false; + +bool qemu_mutex_iothread_locked(void) +{ + return iothread_locked; +} + +/* + * The BQL is taken from so many places that it is worth profiling the + * callers directly, instead of funneling them all through a single function. + */ +void qemu_mutex_lock_iothread_impl(const char *file, int line) +{ + QemuMutexLockFunc bql_lock = qatomic_read(&qemu_bql_mutex_lock_func); + + g_assert(!qemu_mutex_iothread_locked()); + bql_lock(&qemu_global_mutex, file, line); + iothread_locked = true; +} + +void qemu_mutex_unlock_iothread(void) +{ + g_assert(qemu_mutex_iothread_locked()); + iothread_locked = false; + qemu_mutex_unlock(&qemu_global_mutex); +} + +void qemu_cond_wait_iothread(QemuCond *cond) +{ + qemu_cond_wait(cond, &qemu_global_mutex); +} + +void qemu_cond_timedwait_iothread(QemuCond *cond, int ms) +{ + qemu_cond_timedwait(cond, &qemu_global_mutex, ms); +} + +/* signal CPU creation */ +void cpu_thread_signal_created(CPUState *cpu) +{ + cpu->created = true; + qemu_cond_signal(&qemu_cpu_cond); +} + +/* signal CPU destruction */ +void cpu_thread_signal_destroyed(CPUState *cpu) +{ + cpu->created = false; + qemu_cond_signal(&qemu_cpu_cond); +} + + +static bool all_vcpus_paused(void) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + if (!cpu->stopped) { + return false; + } + } + + return true; +} + +void pause_all_vcpus(void) +{ + CPUState *cpu; + + qemu_clock_enable(QEMU_CLOCK_VIRTUAL, false); + CPU_FOREACH(cpu) { + if (qemu_cpu_is_self(cpu)) { + qemu_cpu_stop(cpu, true); + } else { + cpu->stop = true; + qemu_cpu_kick(cpu); + } + } + + /* We need to drop the replay_lock so any vCPU threads woken up + * can finish their replay tasks + */ + replay_mutex_unlock(); + + while (!all_vcpus_paused()) { + qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex); + CPU_FOREACH(cpu) { + qemu_cpu_kick(cpu); + } + } + + qemu_mutex_unlock_iothread(); + replay_mutex_lock(); + qemu_mutex_lock_iothread(); +} + +void cpu_resume(CPUState *cpu) +{ + cpu->stop = false; + cpu->stopped = false; + qemu_cpu_kick(cpu); +} + +void resume_all_vcpus(void) +{ + CPUState *cpu; + + if (!runstate_is_running()) { + return; + } + + qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true); + CPU_FOREACH(cpu) { + cpu_resume(cpu); + } +} + +void cpu_remove_sync(CPUState *cpu) +{ + cpu->stop = true; + cpu->unplug = true; + qemu_cpu_kick(cpu); + qemu_mutex_unlock_iothread(); + qemu_thread_join(cpu->thread); + qemu_mutex_lock_iothread(); +} + +void cpus_register_accel(const CpusAccel *ca) +{ + assert(ca != NULL); + assert(ca->create_vcpu_thread != NULL); /* mandatory */ + cpus_accel = ca; +} + +void qemu_init_vcpu(CPUState *cpu) +{ + MachineState *ms = MACHINE(qdev_get_machine()); + + cpu->nr_cores = ms->smp.cores; + cpu->nr_threads = ms->smp.threads; + cpu->stopped = true; + cpu->random_seed = qemu_guest_random_seed_thread_part1(); + + if (!cpu->as) { + /* If the target cpu hasn't set up any address spaces itself, + * give it the default one. + */ + cpu->num_ases = 1; + cpu_address_space_init(cpu, 0, "cpu-memory", cpu->memory); + } + + /* accelerators all implement the CpusAccel interface */ + g_assert(cpus_accel != NULL && cpus_accel->create_vcpu_thread != NULL); + cpus_accel->create_vcpu_thread(cpu); + + while (!cpu->created) { + qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex); + } +} + +void cpu_stop_current(void) +{ + if (current_cpu) { + current_cpu->stop = true; + cpu_exit(current_cpu); + } +} + +int vm_stop(RunState state) +{ + if (qemu_in_vcpu_thread()) { + qemu_system_vmstop_request_prepare(); + qemu_system_vmstop_request(state); + /* + * FIXME: should not return to device code in case + * vm_stop() has been requested. + */ + cpu_stop_current(); + return 0; + } + + return do_vm_stop(state, true); +} + +/** + * Prepare for (re)starting the VM. + * Returns -1 if the vCPUs are not to be restarted (e.g. if they are already + * running or in case of an error condition), 0 otherwise. + */ +int vm_prepare_start(void) +{ + RunState requested; + + qemu_vmstop_requested(&requested); + if (runstate_is_running() && requested == RUN_STATE__MAX) { + return -1; + } + + /* Ensure that a STOP/RESUME pair of events is emitted if a + * vmstop request was pending. The BLOCK_IO_ERROR event, for + * example, according to documentation is always followed by + * the STOP event. + */ + if (runstate_is_running()) { + qapi_event_send_stop(); + qapi_event_send_resume(); + return -1; + } + + /* We are sending this now, but the CPUs will be resumed shortly later */ + qapi_event_send_resume(); + + cpu_enable_ticks(); + runstate_set(RUN_STATE_RUNNING); + vm_state_notify(1, RUN_STATE_RUNNING); + return 0; +} + +void vm_start(void) +{ + if (!vm_prepare_start()) { + resume_all_vcpus(); + } +} + +/* does a state transition even if the VM is already stopped, + current state is forgotten forever */ +int vm_stop_force_state(RunState state) +{ + if (runstate_is_running()) { + return vm_stop(state); + } else { + runstate_set(state); + + bdrv_drain_all(); + /* Make sure to return an error if the flush in a previous vm_stop() + * failed. */ + return bdrv_flush_all(); + } +} + +void list_cpus(const char *optarg) +{ + /* XXX: implement xxx_cpu_list for targets that still miss it */ +#if defined(cpu_list) + cpu_list(); +#endif +} + +void qmp_memsave(int64_t addr, int64_t size, const char *filename, + bool has_cpu, int64_t cpu_index, Error **errp) +{ + FILE *f; + uint32_t l; + CPUState *cpu; + uint8_t buf[1024]; + int64_t orig_addr = addr, orig_size = size; + + if (!has_cpu) { + cpu_index = 0; + } + + cpu = qemu_get_cpu(cpu_index); + if (cpu == NULL) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index", + "a CPU number"); + return; + } + + f = fopen(filename, "wb"); + if (!f) { + error_setg_file_open(errp, errno, filename); + return; + } + + while (size != 0) { + l = sizeof(buf); + if (l > size) + l = size; + if (cpu_memory_rw_debug(cpu, addr, buf, l, 0) != 0) { + error_setg(errp, "Invalid addr 0x%016" PRIx64 "/size %" PRId64 + " specified", orig_addr, orig_size); + goto exit; + } + if (fwrite(buf, 1, l, f) != l) { + error_setg(errp, QERR_IO_ERROR); + goto exit; + } + addr += l; + size -= l; + } + +exit: + fclose(f); +} + +void qmp_pmemsave(int64_t addr, int64_t size, const char *filename, + Error **errp) +{ + FILE *f; + uint32_t l; + uint8_t buf[1024]; + + f = fopen(filename, "wb"); + if (!f) { + error_setg_file_open(errp, errno, filename); + return; + } + + while (size != 0) { + l = sizeof(buf); + if (l > size) + l = size; + cpu_physical_memory_read(addr, buf, l); + if (fwrite(buf, 1, l, f) != l) { + error_setg(errp, QERR_IO_ERROR); + goto exit; + } + addr += l; + size -= l; + } + +exit: + fclose(f); +} + +void qmp_inject_nmi(Error **errp) +{ + nmi_monitor_handle(monitor_get_cpu_index(monitor_cur()), errp); +} + diff --git a/device_tree.c b/softmmu/device_tree.c similarity index 100% rename from device_tree.c rename to softmmu/device_tree.c diff --git a/dma-helpers.c b/softmmu/dma-helpers.c similarity index 89% rename from dma-helpers.c rename to softmmu/dma-helpers.c index e8a26e81e16703019e211a1ff0446d3b93b1f401..03c92e0cc6021db5821b1ffba31ae5005deeacf6 100644 --- a/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -10,9 +10,11 @@ #include "qemu/osdep.h" #include "sysemu/block-backend.h" #include "sysemu/dma.h" -#include "trace-root.h" +#include "trace/trace-root.h" #include "qemu/thread.h" #include "qemu/main-loop.h" +#include "sysemu/cpu-timers.h" +#include "qemu/range.h" /* #define DEBUG_IOMMU */ @@ -142,6 +144,26 @@ static void dma_blk_cb(void *opaque, int ret) cur_addr = dbs->sg->sg[dbs->sg_cur_index].base + dbs->sg_cur_byte; cur_len = dbs->sg->sg[dbs->sg_cur_index].len - dbs->sg_cur_byte; mem = dma_memory_map(dbs->sg->as, cur_addr, &cur_len, dbs->dir); + /* + * Make reads deterministic in icount mode. Windows sometimes issues + * disk read requests with overlapping SGs. It leads + * to non-determinism, because resulting buffer contents may be mixed + * from several sectors. This code splits all SGs into several + * groups. SGs in every group do not overlap. + */ + if (mem && icount_enabled() && dbs->dir == DMA_DIRECTION_FROM_DEVICE) { + int i; + for (i = 0 ; i < dbs->iov.niov ; ++i) { + if (ranges_overlap((intptr_t)dbs->iov.iov[i].iov_base, + dbs->iov.iov[i].iov_len, (intptr_t)mem, + cur_len)) { + dma_memory_unmap(dbs->sg->as, mem, cur_len, + dbs->dir, cur_len); + mem = NULL; + break; + } + } + } if (!mem) break; qemu_iovec_add(&dbs->iov, mem, cur_len); diff --git a/softmmu/icount.c b/softmmu/icount.c new file mode 100644 index 0000000000000000000000000000000000000000..020a201a01a4cbbbd05592efe7ff6062070c709d --- /dev/null +++ b/softmmu/icount.c @@ -0,0 +1,492 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/cutils.h" +#include "migration/vmstate.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "exec/exec-all.h" +#include "sysemu/cpus.h" +#include "sysemu/qtest.h" +#include "qemu/main-loop.h" +#include "qemu/option.h" +#include "qemu/seqlock.h" +#include "sysemu/replay.h" +#include "sysemu/runstate.h" +#include "hw/core/cpu.h" +#include "sysemu/cpu-timers.h" +#include "sysemu/cpu-throttle.h" +#include "timers-state.h" + +/* + * ICOUNT: Instruction Counter + * + * this module is split off from cpu-timers because the icount part + * is TCG-specific, and does not need to be built for other accels. + */ +static bool icount_sleep = true; +/* Arbitrarily pick 1MIPS as the minimum allowable speed. */ +#define MAX_ICOUNT_SHIFT 10 + +/* + * 0 = Do not count executed instructions. + * 1 = Fixed conversion of insn to ns via "shift" option + * 2 = Runtime adaptive algorithm to compute shift + */ +int use_icount; + +static void icount_enable_precise(void) +{ + use_icount = 1; +} + +static void icount_enable_adaptive(void) +{ + use_icount = 2; +} + +/* + * The current number of executed instructions is based on what we + * originally budgeted minus the current state of the decrementing + * icount counters in extra/u16.low. + */ +static int64_t icount_get_executed(CPUState *cpu) +{ + return (cpu->icount_budget - + (cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra)); +} + +/* + * Update the global shared timer_state.qemu_icount to take into + * account executed instructions. This is done by the TCG vCPU + * thread so the main-loop can see time has moved forward. + */ +static void icount_update_locked(CPUState *cpu) +{ + int64_t executed = icount_get_executed(cpu); + cpu->icount_budget -= executed; + + qatomic_set_i64(&timers_state.qemu_icount, + timers_state.qemu_icount + executed); +} + +/* + * Update the global shared timer_state.qemu_icount to take into + * account executed instructions. This is done by the TCG vCPU + * thread so the main-loop can see time has moved forward. + */ +void icount_update(CPUState *cpu) +{ + seqlock_write_lock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + icount_update_locked(cpu); + seqlock_write_unlock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); +} + +static int64_t icount_get_raw_locked(void) +{ + CPUState *cpu = current_cpu; + + if (cpu && cpu->running) { + if (!cpu->can_do_io) { + error_report("Bad icount read"); + exit(1); + } + /* Take into account what has run */ + icount_update_locked(cpu); + } + /* The read is protected by the seqlock, but needs atomic64 to avoid UB */ + return qatomic_read_i64(&timers_state.qemu_icount); +} + +static int64_t icount_get_locked(void) +{ + int64_t icount = icount_get_raw_locked(); + return qatomic_read_i64(&timers_state.qemu_icount_bias) + + icount_to_ns(icount); +} + +int64_t icount_get_raw(void) +{ + int64_t icount; + unsigned start; + + do { + start = seqlock_read_begin(&timers_state.vm_clock_seqlock); + icount = icount_get_raw_locked(); + } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start)); + + return icount; +} + +/* Return the virtual CPU time, based on the instruction counter. */ +int64_t icount_get(void) +{ + int64_t icount; + unsigned start; + + do { + start = seqlock_read_begin(&timers_state.vm_clock_seqlock); + icount = icount_get_locked(); + } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start)); + + return icount; +} + +int64_t icount_to_ns(int64_t icount) +{ + return icount << qatomic_read(&timers_state.icount_time_shift); +} + +/* + * Correlation between real and virtual time is always going to be + * fairly approximate, so ignore small variation. + * When the guest is idle real and virtual time will be aligned in + * the IO wait loop. + */ +#define ICOUNT_WOBBLE (NANOSECONDS_PER_SECOND / 10) + +static void icount_adjust(void) +{ + int64_t cur_time; + int64_t cur_icount; + int64_t delta; + + /* Protected by TimersState mutex. */ + static int64_t last_delta; + + /* If the VM is not running, then do nothing. */ + if (!runstate_is_running()) { + return; + } + + seqlock_write_lock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + cur_time = REPLAY_CLOCK_LOCKED(REPLAY_CLOCK_VIRTUAL_RT, + cpu_get_clock_locked()); + cur_icount = icount_get_locked(); + + delta = cur_icount - cur_time; + /* FIXME: This is a very crude algorithm, somewhat prone to oscillation. */ + if (delta > 0 + && last_delta + ICOUNT_WOBBLE < delta * 2 + && timers_state.icount_time_shift > 0) { + /* The guest is getting too far ahead. Slow time down. */ + qatomic_set(&timers_state.icount_time_shift, + timers_state.icount_time_shift - 1); + } + if (delta < 0 + && last_delta - ICOUNT_WOBBLE > delta * 2 + && timers_state.icount_time_shift < MAX_ICOUNT_SHIFT) { + /* The guest is getting too far behind. Speed time up. */ + qatomic_set(&timers_state.icount_time_shift, + timers_state.icount_time_shift + 1); + } + last_delta = delta; + qatomic_set_i64(&timers_state.qemu_icount_bias, + cur_icount - (timers_state.qemu_icount + << timers_state.icount_time_shift)); + seqlock_write_unlock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); +} + +static void icount_adjust_rt(void *opaque) +{ + timer_mod(timers_state.icount_rt_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) + 1000); + icount_adjust(); +} + +static void icount_adjust_vm(void *opaque) +{ + timer_mod(timers_state.icount_vm_timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + NANOSECONDS_PER_SECOND / 10); + icount_adjust(); +} + +int64_t icount_round(int64_t count) +{ + int shift = qatomic_read(&timers_state.icount_time_shift); + return (count + (1 << shift) - 1) >> shift; +} + +static void icount_warp_rt(void) +{ + unsigned seq; + int64_t warp_start; + + /* + * The icount_warp_timer is rescheduled soon after vm_clock_warp_start + * changes from -1 to another value, so the race here is okay. + */ + do { + seq = seqlock_read_begin(&timers_state.vm_clock_seqlock); + warp_start = timers_state.vm_clock_warp_start; + } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, seq)); + + if (warp_start == -1) { + return; + } + + seqlock_write_lock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + if (runstate_is_running()) { + int64_t clock = REPLAY_CLOCK_LOCKED(REPLAY_CLOCK_VIRTUAL_RT, + cpu_get_clock_locked()); + int64_t warp_delta; + + warp_delta = clock - timers_state.vm_clock_warp_start; + if (icount_enabled() == 2) { + /* + * In adaptive mode, do not let QEMU_CLOCK_VIRTUAL run too + * far ahead of real time. + */ + int64_t cur_icount = icount_get_locked(); + int64_t delta = clock - cur_icount; + warp_delta = MIN(warp_delta, delta); + } + qatomic_set_i64(&timers_state.qemu_icount_bias, + timers_state.qemu_icount_bias + warp_delta); + } + timers_state.vm_clock_warp_start = -1; + seqlock_write_unlock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + + if (qemu_clock_expired(QEMU_CLOCK_VIRTUAL)) { + qemu_clock_notify(QEMU_CLOCK_VIRTUAL); + } +} + +static void icount_timer_cb(void *opaque) +{ + /* + * No need for a checkpoint because the timer already synchronizes + * with CHECKPOINT_CLOCK_VIRTUAL_RT. + */ + icount_warp_rt(); +} + +void icount_start_warp_timer(void) +{ + int64_t clock; + int64_t deadline; + + assert(icount_enabled()); + + /* + * Nothing to do if the VM is stopped: QEMU_CLOCK_VIRTUAL timers + * do not fire, so computing the deadline does not make sense. + */ + if (!runstate_is_running()) { + return; + } + + if (replay_mode != REPLAY_MODE_PLAY) { + if (!all_cpu_threads_idle()) { + return; + } + + if (qtest_enabled()) { + /* When testing, qtest commands advance icount. */ + return; + } + + replay_checkpoint(CHECKPOINT_CLOCK_WARP_START); + } else { + /* warp clock deterministically in record/replay mode */ + if (!replay_checkpoint(CHECKPOINT_CLOCK_WARP_START)) { + /* + * vCPU is sleeping and warp can't be started. + * It is probably a race condition: notification sent + * to vCPU was processed in advance and vCPU went to sleep. + * Therefore we have to wake it up for doing someting. + */ + if (replay_has_checkpoint()) { + qemu_clock_notify(QEMU_CLOCK_VIRTUAL); + } + return; + } + } + + /* We want to use the earliest deadline from ALL vm_clocks */ + clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT); + deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, + ~QEMU_TIMER_ATTR_EXTERNAL); + if (deadline < 0) { + static bool notified; + if (!icount_sleep && !notified) { + warn_report("icount sleep disabled and no active timers"); + notified = true; + } + return; + } + + if (deadline > 0) { + /* + * Ensure QEMU_CLOCK_VIRTUAL proceeds even when the virtual CPU goes to + * sleep. Otherwise, the CPU might be waiting for a future timer + * interrupt to wake it up, but the interrupt never comes because + * the vCPU isn't running any insns and thus doesn't advance the + * QEMU_CLOCK_VIRTUAL. + */ + if (!icount_sleep) { + /* + * We never let VCPUs sleep in no sleep icount mode. + * If there is a pending QEMU_CLOCK_VIRTUAL timer we just advance + * to the next QEMU_CLOCK_VIRTUAL event and notify it. + * It is useful when we want a deterministic execution time, + * isolated from host latencies. + */ + seqlock_write_lock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + qatomic_set_i64(&timers_state.qemu_icount_bias, + timers_state.qemu_icount_bias + deadline); + seqlock_write_unlock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + qemu_clock_notify(QEMU_CLOCK_VIRTUAL); + } else { + /* + * We do stop VCPUs and only advance QEMU_CLOCK_VIRTUAL after some + * "real" time, (related to the time left until the next event) has + * passed. The QEMU_CLOCK_VIRTUAL_RT clock will do this. + * This avoids that the warps are visible externally; for example, + * you will not be sending network packets continuously instead of + * every 100ms. + */ + seqlock_write_lock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + if (timers_state.vm_clock_warp_start == -1 + || timers_state.vm_clock_warp_start > clock) { + timers_state.vm_clock_warp_start = clock; + } + seqlock_write_unlock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + timer_mod_anticipate(timers_state.icount_warp_timer, + clock + deadline); + } + } else if (deadline == 0) { + qemu_clock_notify(QEMU_CLOCK_VIRTUAL); + } +} + +void icount_account_warp_timer(void) +{ + if (!icount_enabled() || !icount_sleep) { + return; + } + + /* + * Nothing to do if the VM is stopped: QEMU_CLOCK_VIRTUAL timers + * do not fire, so computing the deadline does not make sense. + */ + if (!runstate_is_running()) { + return; + } + + /* warp clock deterministically in record/replay mode */ + if (!replay_checkpoint(CHECKPOINT_CLOCK_WARP_ACCOUNT)) { + return; + } + + timer_del(timers_state.icount_warp_timer); + icount_warp_rt(); +} + +void icount_configure(QemuOpts *opts, Error **errp) +{ + const char *option = qemu_opt_get(opts, "shift"); + bool sleep = qemu_opt_get_bool(opts, "sleep", true); + bool align = qemu_opt_get_bool(opts, "align", false); + long time_shift = -1; + + if (!option) { + if (qemu_opt_get(opts, "align") != NULL) { + error_setg(errp, "Please specify shift option when using align"); + } + return; + } + + if (align && !sleep) { + error_setg(errp, "align=on and sleep=off are incompatible"); + return; + } + + if (strcmp(option, "auto") != 0) { + if (qemu_strtol(option, NULL, 0, &time_shift) < 0 + || time_shift < 0 || time_shift > MAX_ICOUNT_SHIFT) { + error_setg(errp, "icount: Invalid shift value"); + return; + } + } else if (icount_align_option) { + error_setg(errp, "shift=auto and align=on are incompatible"); + return; + } else if (!icount_sleep) { + error_setg(errp, "shift=auto and sleep=off are incompatible"); + return; + } + + icount_sleep = sleep; + if (icount_sleep) { + timers_state.icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT, + icount_timer_cb, NULL); + } + + icount_align_option = align; + + if (time_shift >= 0) { + timers_state.icount_time_shift = time_shift; + icount_enable_precise(); + return; + } + + icount_enable_adaptive(); + + /* + * 125MIPS seems a reasonable initial guess at the guest speed. + * It will be corrected fairly quickly anyway. + */ + timers_state.icount_time_shift = 3; + + /* + * Have both realtime and virtual time triggers for speed adjustment. + * The realtime trigger catches emulated time passing too slowly, + * the virtual time trigger catches emulated time passing too fast. + * Realtime triggers occur even when idle, so use them less frequently + * than VM triggers. + */ + timers_state.vm_clock_warp_start = -1; + timers_state.icount_rt_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL_RT, + icount_adjust_rt, NULL); + timer_mod(timers_state.icount_rt_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) + 1000); + timers_state.icount_vm_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, + icount_adjust_vm, NULL); + timer_mod(timers_state.icount_vm_timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + NANOSECONDS_PER_SECOND / 10); +} diff --git a/ioport.c b/softmmu/ioport.c similarity index 99% rename from ioport.c rename to softmmu/ioport.c index 04e360e79a3dfdcaa51f1ae796967d4be9decddd..cb8adb0b9363c643b184322e5f26522a74605e1f 100644 --- a/ioport.c +++ b/softmmu/ioport.c @@ -28,9 +28,9 @@ #include "qemu/osdep.h" #include "cpu.h" #include "exec/ioport.h" -#include "trace-root.h" #include "exec/memory.h" #include "exec/address-spaces.h" +#include "trace.h" typedef struct MemoryRegionPortioList { MemoryRegion mr; diff --git a/softmmu/main.c b/softmmu/main.c index 7adc530c736029c1e9ceccce7154645f4983cecf..639c67ff489356d51534d16665d7a4cf46414b5f 100644 --- a/softmmu/main.c +++ b/softmmu/main.c @@ -29,6 +29,7 @@ #ifdef CONFIG_SDL #if defined(__APPLE__) || defined(main) #include +static int qemu_main(int argc, char **argv, char **envp); int main(int argc, char **argv) { return qemu_main(argc, argv, NULL); diff --git a/memory.c b/softmmu/memory.c similarity index 94% rename from memory.c rename to softmmu/memory.c index fd6f3d6aca18ee256cd6b1a6ff47adcf9b8aa075..11ca94d037414cfd05108516a9bb5e8f778e2a96 100644 --- a/memory.c +++ b/softmmu/memory.c @@ -14,6 +14,7 @@ */ #include "qemu/osdep.h" +#include "qemu/log.h" #include "qapi/error.h" #include "cpu.h" #include "exec/memory.h" @@ -24,7 +25,7 @@ #include "qemu/main-loop.h" #include "qemu/qemu-print.h" #include "qom/object.h" -#include "trace-root.h" +#include "trace.h" #include "exec/memory-internal.h" #include "exec/ram_addr.h" @@ -204,8 +205,15 @@ static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd *a, static bool memory_region_ioeventfd_equal(MemoryRegionIoeventfd *a, MemoryRegionIoeventfd *b) { - return !memory_region_ioeventfd_before(a, b) - && !memory_region_ioeventfd_before(b, a); + if (int128_eq(a->addr.start, b->addr.start) && + (!int128_nz(a->addr.size) || !int128_nz(b->addr.size) || + (int128_eq(a->addr.size, b->addr.size) && + (a->match_data == b->match_data) && + ((a->match_data && (a->data == b->data)) || !a->match_data) && + (a->e == b->e)))) + return true; + + return false; } /* Range of memory in the global map. Addresses are absolute. */ @@ -294,12 +302,12 @@ static void flatview_destroy(FlatView *view) static bool flatview_ref(FlatView *view) { - return atomic_fetch_inc_nonzero(&view->ref) > 0; + return qatomic_fetch_inc_nonzero(&view->ref) > 0; } void flatview_unref(FlatView *view) { - if (atomic_fetch_dec(&view->ref) == 1) { + if (qatomic_fetch_dec(&view->ref) == 1) { trace_flatview_destroy_rcu(view, view->root); assert(view->root); call_rcu(view, flatview_destroy, rcu); @@ -655,6 +663,19 @@ static void render_memory_region(FlatView *view, } } +void flatview_for_each_range(FlatView *fv, flatview_cb cb , void *opaque) +{ + FlatRange *fr; + + assert(fv); + assert(cb); + + FOR_EACH_FLAT_RANGE(fr, fv) { + if (cb(fr->addr.start, fr->addr.size, fr->mr, opaque)) + break; + } +} + static MemoryRegion *memory_region_get_flatview_root(MemoryRegion *mr) { while (mr->enabled) { @@ -1027,7 +1048,7 @@ static void address_space_set_flatview(AddressSpace *as) } /* Writes are protected by the BQL. */ - atomic_rcu_set(&as->current_map, new_view); + qatomic_rcu_set(&as->current_map, new_view); if (old_view) { flatview_unref(old_view); } @@ -1221,7 +1242,6 @@ static void memory_region_initfn(Object *obj) mr->ops = &unassigned_mem_ops; mr->enabled = true; mr->romd_mode = true; - mr->global_locking = true; mr->destructor = memory_region_destructor_none; QTAILQ_INIT(&mr->subregions); QTAILQ_INIT(&mr->coalesced); @@ -1352,35 +1372,39 @@ bool memory_region_access_valid(MemoryRegion *mr, bool is_write, MemTxAttrs attrs) { - int access_size_min, access_size_max; - int access_size, i; - - if (!mr->ops->valid.unaligned && (addr & (size - 1))) { + if (mr->ops->valid.accepts + && !mr->ops->valid.accepts(mr->opaque, addr, size, is_write, attrs)) { + qemu_log_mask(LOG_GUEST_ERROR, "Invalid access at addr " + "0x%" HWADDR_PRIX ", size %u, " + "region '%s', reason: rejected\n", + addr, size, memory_region_name(mr)); return false; } - if (!mr->ops->valid.accepts) { - return true; - } - - access_size_min = mr->ops->valid.min_access_size; - if (!mr->ops->valid.min_access_size) { - access_size_min = 1; + if (!mr->ops->valid.unaligned && (addr & (size - 1))) { + qemu_log_mask(LOG_GUEST_ERROR, "Invalid access at addr " + "0x%" HWADDR_PRIX ", size %u, " + "region '%s', reason: unaligned\n", + addr, size, memory_region_name(mr)); + return false; } - access_size_max = mr->ops->valid.max_access_size; + /* Treat zero as compatibility all valid */ if (!mr->ops->valid.max_access_size) { - access_size_max = 4; + return true; } - access_size = MAX(MIN(size, access_size_max), access_size_min); - for (i = 0; i < size; i += access_size) { - if (!mr->ops->valid.accepts(mr->opaque, addr + i, access_size, - is_write, attrs)) { - return false; - } + if (size > mr->ops->valid.max_access_size + || size < mr->ops->valid.min_access_size) { + qemu_log_mask(LOG_GUEST_ERROR, "Invalid access at addr " + "0x%" HWADDR_PRIX ", size %u, " + "region '%s', reason: invalid size " + "(min:%u max:%u)\n", + addr, size, memory_region_name(mr), + mr->ops->valid.min_access_size, + mr->ops->valid.max_access_size); + return false; } - return true; } @@ -1416,6 +1440,7 @@ MemTxResult memory_region_dispatch_read(MemoryRegion *mr, unsigned size = memop_size(op); MemTxResult r; + fuzz_dma_read_cb(addr, size, mr, false); if (!memory_region_access_valid(mr, addr, size, false, attrs)) { *pval = unassigned_mem_read(mr, addr, size); return MEMTX_DECODE_ERROR; @@ -1775,7 +1800,7 @@ const char *memory_region_name(const MemoryRegion *mr) { if (!mr->name) { ((MemoryRegion *)mr)->name = - object_get_canonical_path_component(OBJECT(mr)); + g_strdup(object_get_canonical_path_component(OBJECT(mr))); } return mr->name; } @@ -1788,7 +1813,10 @@ bool memory_region_is_ram_device(MemoryRegion *mr) uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr) { uint8_t mask = mr->dirty_log_mask; - if (global_dirty_log && mr->ram_block) { + RAMBlock *rb = mr->ram_block; + + if (global_dirty_log && ((rb && qemu_ram_is_migratable(rb)) || + memory_region_is_iommu(mr))) { mask |= (1 << DIRTY_MEMORY_MIGRATION); } return mask; @@ -1823,6 +1851,19 @@ static int memory_region_update_iommu_notify_flags(IOMMUMemoryRegion *iommu_mr, return ret; } +int memory_region_iommu_set_page_size_mask(IOMMUMemoryRegion *iommu_mr, + uint64_t page_size_mask, + Error **errp) +{ + IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr); + int ret = 0; + + if (imrc->iommu_set_page_size_mask) { + ret = imrc->iommu_set_page_size_mask(iommu_mr, page_size_mask, errp); + } + return ret; +} + int memory_region_register_iommu_notifier(MemoryRegion *mr, IOMMUNotifier *n, Error **errp) { @@ -2197,15 +2238,21 @@ void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize, Error **errp qemu_ram_resize(mr->ram_block, newsize, errp); } +void memory_region_msync(MemoryRegion *mr, hwaddr addr, hwaddr size) +{ + if (mr->ram_block) { + qemu_ram_msync(mr->ram_block, addr, size); + } +} -void memory_region_do_writeback(MemoryRegion *mr, hwaddr addr, hwaddr size) +void memory_region_writeback(MemoryRegion *mr, hwaddr addr, hwaddr size) { /* * Might be extended case needed to cover * different types of memory regions */ - if (mr->ram_block && mr->dirty_log_mask) { - qemu_ram_writeback(mr->ram_block, addr, size); + if (mr->dirty_log_mask) { + memory_region_msync(mr, addr, size); } } @@ -2282,11 +2329,6 @@ void memory_region_clear_flush_coalesced(MemoryRegion *mr) } } -void memory_region_clear_global_locking(MemoryRegion *mr) -{ - mr->global_locking = false; -} - static bool userspace_eventfd_warning; void memory_region_add_eventfd(MemoryRegion *mr, @@ -2876,7 +2918,7 @@ static void mtree_print_mr_owner(const MemoryRegion *mr) static void mtree_print_mr(const MemoryRegion *mr, unsigned int level, hwaddr base, MemoryRegionListHead *alias_print_queue, - bool owner) + bool owner, bool display_disabled) { MemoryRegionList *new_ml, *ml, *next_ml; MemoryRegionListHead submr_print_queue; @@ -2888,10 +2930,6 @@ static void mtree_print_mr(const MemoryRegion *mr, unsigned int level, return; } - for (i = 0; i < level; i++) { - qemu_printf(MTREE_INDENT); - } - cur_start = base + mr->addr; cur_end = cur_start + MR_SIZE(mr->size); @@ -2920,35 +2958,46 @@ static void mtree_print_mr(const MemoryRegion *mr, unsigned int level, ml->mr = mr->alias; QTAILQ_INSERT_TAIL(alias_print_queue, ml, mrqueue); } - qemu_printf(TARGET_FMT_plx "-" TARGET_FMT_plx - " (prio %d, %s%s): alias %s @%s " TARGET_FMT_plx - "-" TARGET_FMT_plx "%s", - cur_start, cur_end, - mr->priority, - mr->nonvolatile ? "nv-" : "", - memory_region_type((MemoryRegion *)mr), - memory_region_name(mr), - memory_region_name(mr->alias), - mr->alias_offset, - mr->alias_offset + MR_SIZE(mr->size), - mr->enabled ? "" : " [disabled]"); - if (owner) { - mtree_print_mr_owner(mr); + if (mr->enabled || display_disabled) { + for (i = 0; i < level; i++) { + qemu_printf(MTREE_INDENT); + } + qemu_printf(TARGET_FMT_plx "-" TARGET_FMT_plx + " (prio %d, %s%s): alias %s @%s " TARGET_FMT_plx + "-" TARGET_FMT_plx "%s", + cur_start, cur_end, + mr->priority, + mr->nonvolatile ? "nv-" : "", + memory_region_type((MemoryRegion *)mr), + memory_region_name(mr), + memory_region_name(mr->alias), + mr->alias_offset, + mr->alias_offset + MR_SIZE(mr->size), + mr->enabled ? "" : " [disabled]"); + if (owner) { + mtree_print_mr_owner(mr); + } + qemu_printf("\n"); } } else { - qemu_printf(TARGET_FMT_plx "-" TARGET_FMT_plx - " (prio %d, %s%s): %s%s", - cur_start, cur_end, - mr->priority, - mr->nonvolatile ? "nv-" : "", - memory_region_type((MemoryRegion *)mr), - memory_region_name(mr), - mr->enabled ? "" : " [disabled]"); - if (owner) { - mtree_print_mr_owner(mr); + if (mr->enabled || display_disabled) { + for (i = 0; i < level; i++) { + qemu_printf(MTREE_INDENT); + } + qemu_printf(TARGET_FMT_plx "-" TARGET_FMT_plx + " (prio %d, %s%s): %s%s", + cur_start, cur_end, + mr->priority, + mr->nonvolatile ? "nv-" : "", + memory_region_type((MemoryRegion *)mr), + memory_region_name(mr), + mr->enabled ? "" : " [disabled]"); + if (owner) { + mtree_print_mr_owner(mr); + } + qemu_printf("\n"); } } - qemu_printf("\n"); QTAILQ_INIT(&submr_print_queue); @@ -2971,7 +3020,7 @@ static void mtree_print_mr(const MemoryRegion *mr, unsigned int level, QTAILQ_FOREACH(ml, &submr_print_queue, mrqueue) { mtree_print_mr(ml->mr, level + 1, cur_start, - alias_print_queue, owner); + alias_print_queue, owner, display_disabled); } QTAILQ_FOREACH_SAFE(ml, &submr_print_queue, mrqueue, next_ml) { @@ -3082,7 +3131,7 @@ static gboolean mtree_info_flatview_free(gpointer key, gpointer value, return true; } -void mtree_info(bool flatview, bool dispatch_tree, bool owner) +void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled) { MemoryRegionListHead ml_head; MemoryRegionList *ml, *ml2; @@ -3130,14 +3179,14 @@ void mtree_info(bool flatview, bool dispatch_tree, bool owner) QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { qemu_printf("address-space: %s\n", as->name); - mtree_print_mr(as->root, 1, 0, &ml_head, owner); + mtree_print_mr(as->root, 1, 0, &ml_head, owner, disabled); qemu_printf("\n"); } /* print aliased regions */ QTAILQ_FOREACH(ml, &ml_head, mrqueue) { qemu_printf("memory-region: %s\n", memory_region_name(ml->mr)); - mtree_print_mr(ml->mr, 1, 0, &ml_head, owner); + mtree_print_mr(ml->mr, 1, 0, &ml_head, owner, disabled); qemu_printf("\n"); } @@ -3221,6 +3270,19 @@ void memory_region_init_rom_device(MemoryRegion *mr, vmstate_register_ram(mr, owner_dev); } +/* + * Support softmmu builds with CONFIG_FUZZ using a weak symbol and a stub for + * the fuzz_dma_read_cb callback + */ +#ifdef CONFIG_FUZZ +void __attribute__((weak)) fuzz_dma_read_cb(size_t addr, + size_t len, + MemoryRegion *mr, + bool is_write) +{ +} +#endif + static const TypeInfo memory_region_info = { .parent = TYPE_OBJECT, .name = TYPE_MEMORY_REGION, diff --git a/memory_mapping.c b/softmmu/memory_mapping.c similarity index 100% rename from memory_mapping.c rename to softmmu/memory_mapping.c diff --git a/softmmu/meson.build b/softmmu/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..8f7210b4f076a6568256644697552224a3fba5c3 --- /dev/null +++ b/softmmu/meson.build @@ -0,0 +1,27 @@ +specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files( + 'arch_init.c', + 'balloon.c', + 'cpus.c', + 'cpu-throttle.c', + 'physmem.c', + 'ioport.c', + 'memory.c', + 'memory_mapping.c', + 'qtest.c', + 'vl.c', + 'cpu-timers.c', +)]) + +specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: [files( + 'icount.c' +)]) + +softmmu_ss.add(files( + 'bootdevice.c', + 'dma-helpers.c', + 'qdev-monitor.c', +), sdl, libpmem, libdaxctl) + +softmmu_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c')) +softmmu_ss.add(when: 'CONFIG_SECCOMP', if_true: [files('qemu-seccomp.c'), seccomp]) +softmmu_ss.add(when: fdt, if_true: files('device_tree.c')) diff --git a/exec.c b/softmmu/physmem.c similarity index 88% rename from exec.c rename to softmmu/physmem.c index 5162f0d12f997804af14e8fd846f2a3b06043115..3027747c0302c0904db2568eabb86f8ed40e4221 100644 --- a/exec.c +++ b/softmmu/physmem.c @@ -1,12 +1,12 @@ /* - * Virtual page mapping + * RAM allocation and memory access * * Copyright (c) 2003 Fabrice Bellard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -28,10 +28,8 @@ #include "tcg/tcg.h" #include "hw/qdev-core.h" #include "hw/qdev-properties.h" -#if !defined(CONFIG_USER_ONLY) #include "hw/boards.h" #include "hw/xen/xen.h" -#endif #include "sysemu/kvm.h" #include "sysemu/sysemu.h" #include "sysemu/tcg.h" @@ -40,9 +38,6 @@ #include "qemu/config-file.h" #include "qemu/error-report.h" #include "qemu/qemu-print.h" -#if defined(CONFIG_USER_ONLY) -#include "qemu.h" -#else /* !CONFIG_USER_ONLY */ #include "exec/memory.h" #include "exec/ioport.h" #include "sysemu/dma.h" @@ -50,13 +45,12 @@ #include "sysemu/hw_accel.h" #include "exec/address-spaces.h" #include "sysemu/xen-mapcache.h" -#include "trace-root.h" +#include "trace/trace-root.h" #ifdef CONFIG_FALLOCATE_PUNCH_HOLE #include #endif -#endif #include "qemu/rcu_queue.h" #include "qemu/main-loop.h" #include "translate-all.h" @@ -77,9 +71,12 @@ #include "monitor/monitor.h" +#ifdef CONFIG_LIBDAXCTL +#include +#endif + //#define DEBUG_SUBPAGE -#if !defined(CONFIG_USER_ONLY) /* ram_list is read under rcu_read_lock()/rcu_read_unlock(). Writes * are protected by the ramlist lock. */ @@ -92,22 +89,6 @@ AddressSpace address_space_io; AddressSpace address_space_memory; static MemoryRegion io_mem_unassigned; -#endif - -CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus); - -/* current CPU in the current thread. It is only valid inside - cpu_exec() */ -__thread CPUState *current_cpu; - -uintptr_t qemu_host_page_size; -intptr_t qemu_host_page_mask; - -#if !defined(CONFIG_USER_ONLY) -/* 0 = Do not count executed instructions. - 1 = Precise instruction counting. - 2 = Adaptive rate instruction counting. */ -int use_icount; typedef struct PhysPageEntry PhysPageEntry; @@ -185,10 +166,6 @@ struct DirtyBitmapSnapshot { unsigned long dirty[]; }; -#endif - -#if !defined(CONFIG_USER_ONLY) - static void phys_map_node_reserve(PhysPageMap *map, unsigned nodes) { static unsigned alloc_hint = 16; @@ -355,13 +332,13 @@ static MemoryRegionSection *address_space_lookup_region(AddressSpaceDispatch *d, hwaddr addr, bool resolve_subpage) { - MemoryRegionSection *section = atomic_read(&d->mru_section); + MemoryRegionSection *section = qatomic_read(&d->mru_section); subpage_t *subpage; if (!section || section == &d->map.sections[PHYS_SECTION_UNASSIGNED] || !section_covers_addr(section, addr)) { section = phys_page_find(d, addr); - atomic_set(&d->mru_section, section); + qatomic_set(&d->mru_section, section); } if (resolve_subpage && section->mr->subpage) { subpage = container_of(section->mr, subpage_t, iomem); @@ -629,8 +606,7 @@ static void tcg_register_iommu_notifier(CPUState *cpu, */ MemoryRegion *mr = MEMORY_REGION(iommu_mr); TCGIOMMUNotifier *notifier; - Error *err = NULL; - int i, ret; + int i; for (i = 0; i < cpu->iommu_notifiers->len; i++) { notifier = g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i); @@ -659,12 +635,8 @@ static void tcg_register_iommu_notifier(CPUState *cpu, 0, HWADDR_MAX, iommu_idx); - ret = memory_region_register_iommu_notifier(notifier->mr, ¬ifier->n, - &err); - if (ret) { - error_report_err(err); - exit(1); - } + memory_region_register_iommu_notifier(notifier->mr, ¬ifier->n, + &error_fatal); } if (!notifier->active) { @@ -672,7 +644,7 @@ static void tcg_register_iommu_notifier(CPUState *cpu, } } -static void tcg_iommu_free_notifier_list(CPUState *cpu) +void tcg_iommu_free_notifier_list(CPUState *cpu) { /* Destroy the CPU's notifier list */ int i; @@ -686,6 +658,11 @@ static void tcg_iommu_free_notifier_list(CPUState *cpu) g_array_free(cpu->iommu_notifiers, true); } +void tcg_iommu_init_notifier_list(CPUState *cpu) +{ + cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier *)); +} + /* Called from RCU critical section */ MemoryRegionSection * address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr addr, @@ -697,7 +674,8 @@ address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr addr, IOMMUMemoryRegionClass *imrc; IOMMUTLBEntry iotlb; int iommu_idx; - AddressSpaceDispatch *d = atomic_rcu_read(&cpu->cpu_ases[asidx].memory_dispatch); + AddressSpaceDispatch *d = + qatomic_rcu_read(&cpu->cpu_ases[asidx].memory_dispatch); for (;;) { section = address_space_translate_internal(d, addr, &addr, plen, false); @@ -742,108 +720,7 @@ address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr addr, translate_fail: return &d->map.sections[PHYS_SECTION_UNASSIGNED]; } -#endif - -#if !defined(CONFIG_USER_ONLY) - -static int cpu_common_post_load(void *opaque, int version_id) -{ - CPUState *cpu = opaque; - - /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the - version_id is increased. */ - cpu->interrupt_request &= ~0x01; - tlb_flush(cpu); - - /* loadvm has just updated the content of RAM, bypassing the - * usual mechanisms that ensure we flush TBs for writes to - * memory we've translated code from. So we must flush all TBs, - * which will now be stale. - */ - tb_flush(cpu); - return 0; -} - -static int cpu_common_pre_load(void *opaque) -{ - CPUState *cpu = opaque; - - cpu->exception_index = -1; - - return 0; -} - -static bool cpu_common_exception_index_needed(void *opaque) -{ - CPUState *cpu = opaque; - - return tcg_enabled() && cpu->exception_index != -1; -} - -static const VMStateDescription vmstate_cpu_common_exception_index = { - .name = "cpu_common/exception_index", - .version_id = 1, - .minimum_version_id = 1, - .needed = cpu_common_exception_index_needed, - .fields = (VMStateField[]) { - VMSTATE_INT32(exception_index, CPUState), - VMSTATE_END_OF_LIST() - } -}; - -static bool cpu_common_crash_occurred_needed(void *opaque) -{ - CPUState *cpu = opaque; - - return cpu->crash_occurred; -} - -static const VMStateDescription vmstate_cpu_common_crash_occurred = { - .name = "cpu_common/crash_occurred", - .version_id = 1, - .minimum_version_id = 1, - .needed = cpu_common_crash_occurred_needed, - .fields = (VMStateField[]) { - VMSTATE_BOOL(crash_occurred, CPUState), - VMSTATE_END_OF_LIST() - } -}; - -const VMStateDescription vmstate_cpu_common = { - .name = "cpu_common", - .version_id = 1, - .minimum_version_id = 1, - .pre_load = cpu_common_pre_load, - .post_load = cpu_common_post_load, - .fields = (VMStateField[]) { - VMSTATE_UINT32(halted, CPUState), - VMSTATE_UINT32(interrupt_request, CPUState), - VMSTATE_END_OF_LIST() - }, - .subsections = (const VMStateDescription*[]) { - &vmstate_cpu_common_exception_index, - &vmstate_cpu_common_crash_occurred, - NULL - } -}; - -#endif - -CPUState *qemu_get_cpu(int index) -{ - CPUState *cpu; - - CPU_FOREACH(cpu) { - if (cpu->cpu_index == index) { - return cpu; - } - } - - return NULL; -} - -#if !defined(CONFIG_USER_ONLY) void cpu_address_space_init(CPUState *cpu, int asidx, const char *prefix, MemoryRegion *mr) { @@ -886,156 +763,13 @@ AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx) /* Return the AddressSpace corresponding to the specified index */ return cpu->cpu_ases[asidx].as; } -#endif - -void cpu_exec_unrealizefn(CPUState *cpu) -{ - CPUClass *cc = CPU_GET_CLASS(cpu); - cpu_list_remove(cpu); - - if (cc->vmsd != NULL) { - vmstate_unregister(NULL, cc->vmsd, cpu); - } - if (qdev_get_vmsd(DEVICE(cpu)) == NULL) { - vmstate_unregister(NULL, &vmstate_cpu_common, cpu); - } -#ifndef CONFIG_USER_ONLY - tcg_iommu_free_notifier_list(cpu); -#endif -} - -Property cpu_common_props[] = { -#ifndef CONFIG_USER_ONLY - /* Create a memory property for softmmu CPU object, - * so users can wire up its memory. (This can't go in hw/core/cpu.c - * because that file is compiled only once for both user-mode - * and system builds.) The default if no link is set up is to use - * the system address space. - */ - DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION, - MemoryRegion *), -#endif - DEFINE_PROP_END_OF_LIST(), -}; - -void cpu_exec_initfn(CPUState *cpu) -{ - cpu->as = NULL; - cpu->num_ases = 0; - -#ifndef CONFIG_USER_ONLY - cpu->thread_id = qemu_get_thread_id(); - cpu->memory = system_memory; - object_ref(OBJECT(cpu->memory)); -#endif -} - -void cpu_exec_realizefn(CPUState *cpu, Error **errp) -{ - CPUClass *cc = CPU_GET_CLASS(cpu); - static bool tcg_target_initialized; - - cpu_list_add(cpu); - - if (tcg_enabled() && !tcg_target_initialized) { - tcg_target_initialized = true; - cc->tcg_initialize(); - } - tlb_init(cpu); - - qemu_plugin_vcpu_init_hook(cpu); - -#ifndef CONFIG_USER_ONLY - if (qdev_get_vmsd(DEVICE(cpu)) == NULL) { - vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu); - } - if (cc->vmsd != NULL) { - vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu); - } - - cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier *)); -#endif -} - -const char *parse_cpu_option(const char *cpu_option) -{ - ObjectClass *oc; - CPUClass *cc; - gchar **model_pieces; - const char *cpu_type; - - model_pieces = g_strsplit(cpu_option, ",", 2); - if (!model_pieces[0]) { - error_report("-cpu option cannot be empty"); - exit(1); - } - - oc = cpu_class_by_name(CPU_RESOLVING_TYPE, model_pieces[0]); - if (oc == NULL) { - error_report("unable to find CPU model '%s'", model_pieces[0]); - g_strfreev(model_pieces); - exit(EXIT_FAILURE); - } - - cpu_type = object_class_get_name(oc); - cc = CPU_CLASS(oc); - cc->parse_features(cpu_type, model_pieces[1], &error_fatal); - g_strfreev(model_pieces); - return cpu_type; -} - -#if defined(CONFIG_USER_ONLY) -void tb_invalidate_phys_addr(target_ulong addr) -{ - mmap_lock(); - tb_invalidate_phys_page_range(addr, addr + 1); - mmap_unlock(); -} - -static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) -{ - tb_invalidate_phys_addr(pc); -} -#else -void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs) -{ - ram_addr_t ram_addr; - MemoryRegion *mr; - hwaddr l = 1; - - if (!tcg_enabled()) { - return; - } - - RCU_READ_LOCK_GUARD(); - mr = address_space_translate(as, addr, &addr, &l, false, attrs); - if (!(memory_region_is_ram(mr) - || memory_region_is_romd(mr))) { - return; - } - ram_addr = memory_region_get_ram_addr(mr) + addr; - tb_invalidate_phys_page_range(ram_addr, ram_addr + 1); -} - -static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) -{ - /* - * There may not be a virtual to physical translation for the pc - * right now, but there may exist cached TB for this pc. - * Flush the whole TB cache to force re-translation of such TBs. - * This is heavyweight, but we're debugging anyway. - */ - tb_flush(cpu); -} -#endif - -#ifndef CONFIG_USER_ONLY /* Add a watchpoint. */ int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len, int flags, CPUWatchpoint **watchpoint) { CPUWatchpoint *wp; + vaddr in_page; /* forbid ranges which are empty or run off the end of the address space */ if (len == 0 || (addr + len - 1) < addr) { @@ -1056,7 +790,12 @@ int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len, QTAILQ_INSERT_TAIL(&cpu->watchpoints, wp, entry); } - tlb_flush_page(cpu, addr); + in_page = -(addr | TARGET_PAGE_MASK); + if (len <= in_page) { + tlb_flush_page(cpu, addr); + } else { + tlb_flush(cpu); + } if (watchpoint) *watchpoint = wp; @@ -1133,129 +872,13 @@ int cpu_watchpoint_address_matches(CPUState *cpu, vaddr addr, vaddr len) } return ret; } -#endif /* !CONFIG_USER_ONLY */ - -/* Add a breakpoint. */ -int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, - CPUBreakpoint **breakpoint) -{ - CPUBreakpoint *bp; - - bp = g_malloc(sizeof(*bp)); - bp->pc = pc; - bp->flags = flags; - - /* keep all GDB-injected breakpoints in front */ - if (flags & BP_GDB) { - QTAILQ_INSERT_HEAD(&cpu->breakpoints, bp, entry); - } else { - QTAILQ_INSERT_TAIL(&cpu->breakpoints, bp, entry); - } - - breakpoint_invalidate(cpu, pc); - - if (breakpoint) { - *breakpoint = bp; - } - return 0; -} - -/* Remove a specific breakpoint. */ -int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags) -{ - CPUBreakpoint *bp; - - QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { - if (bp->pc == pc && bp->flags == flags) { - cpu_breakpoint_remove_by_ref(cpu, bp); - return 0; - } - } - return -ENOENT; -} - -/* Remove a specific breakpoint by reference. */ -void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint) -{ - QTAILQ_REMOVE(&cpu->breakpoints, breakpoint, entry); - - breakpoint_invalidate(cpu, breakpoint->pc); - - g_free(breakpoint); -} - -/* Remove all matching breakpoints. */ -void cpu_breakpoint_remove_all(CPUState *cpu, int mask) -{ - CPUBreakpoint *bp, *next; - - QTAILQ_FOREACH_SAFE(bp, &cpu->breakpoints, entry, next) { - if (bp->flags & mask) { - cpu_breakpoint_remove_by_ref(cpu, bp); - } - } -} - -/* enable or disable single step mode. EXCP_DEBUG is returned by the - CPU loop after each instruction */ -void cpu_single_step(CPUState *cpu, int enabled) -{ - if (cpu->singlestep_enabled != enabled) { - cpu->singlestep_enabled = enabled; - if (kvm_enabled()) { - kvm_update_guest_debug(cpu, 0); - } else { - /* must flush all the translated code to avoid inconsistencies */ - /* XXX: only flush what is necessary */ - tb_flush(cpu); - } - } -} - -void cpu_abort(CPUState *cpu, const char *fmt, ...) -{ - va_list ap; - va_list ap2; - - va_start(ap, fmt); - va_copy(ap2, ap); - fprintf(stderr, "qemu: fatal: "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - cpu_dump_state(cpu, stderr, CPU_DUMP_FPU | CPU_DUMP_CCOP); - if (qemu_log_separate()) { - FILE *logfile = qemu_log_lock(); - qemu_log("qemu: fatal: "); - qemu_log_vprintf(fmt, ap2); - qemu_log("\n"); - log_cpu_state(cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP); - qemu_log_flush(); - qemu_log_unlock(logfile); - qemu_log_close(); - } - va_end(ap2); - va_end(ap); - replay_finish(); -#if defined(CONFIG_USER_ONLY) - { - struct sigaction act; - sigfillset(&act.sa_mask); - act.sa_handler = SIG_DFL; - act.sa_flags = 0; - sigaction(SIGABRT, &act, NULL); - } -#endif - abort(); -} - -#if !defined(CONFIG_USER_ONLY) /* Called from RCU critical section */ static RAMBlock *qemu_get_ram_block(ram_addr_t addr) { RAMBlock *block; - block = atomic_rcu_read(&ram_list.mru_block); + block = qatomic_rcu_read(&ram_list.mru_block); if (block && addr - block->offset < block->max_length) { return block; } @@ -1281,7 +904,7 @@ found: * call_rcu(reclaim_ramblock, xxx); * rcu_read_unlock() * - * atomic_rcu_set is not needed here. The block was already published + * qatomic_rcu_set is not needed here. The block was already published * when it was placed into the list. Here we're just making an extra * copy of the pointer. */ @@ -1329,7 +952,7 @@ bool cpu_physical_memory_test_and_clear_dirty(ram_addr_t start, page = start_page; WITH_RCU_READ_LOCK_GUARD() { - blocks = atomic_rcu_read(&ram_list.dirty_memory[client]); + blocks = qatomic_rcu_read(&ram_list.dirty_memory[client]); ramblock = qemu_get_ram_block(start); /* Range sanity check on the ramblock */ assert(start >= ramblock->offset && @@ -1379,7 +1002,7 @@ DirtyBitmapSnapshot *cpu_physical_memory_snapshot_and_clear_dirty dest = 0; WITH_RCU_READ_LOCK_GUARD() { - blocks = atomic_rcu_read(&ram_list.dirty_memory[client]); + blocks = qatomic_rcu_read(&ram_list.dirty_memory[client]); while (page < end) { unsigned long idx = page / DIRTY_MEMORY_BLOCK_SIZE; @@ -1436,9 +1059,6 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu, AddressSpaceDispatch *d = flatview_to_dispatch(section->fv); return section - d->map.sections; } -#endif /* defined(CONFIG_USER_ONLY) */ - -#if !defined(CONFIG_USER_ONLY) static int subpage_register(subpage_t *mmio, uint32_t start, uint32_t end, uint16_t section); @@ -1736,6 +1356,46 @@ static int64_t get_file_size(int fd) return size; } +static int64_t get_file_align(int fd) +{ + int64_t align = -1; +#if defined(__linux__) && defined(CONFIG_LIBDAXCTL) + struct stat st; + + if (fstat(fd, &st) < 0) { + return -errno; + } + + /* Special handling for devdax character devices */ + if (S_ISCHR(st.st_mode)) { + g_autofree char *path = NULL; + g_autofree char *rpath = NULL; + struct daxctl_ctx *ctx; + struct daxctl_region *region; + int rc = 0; + + path = g_strdup_printf("/sys/dev/char/%d:%d", + major(st.st_rdev), minor(st.st_rdev)); + rpath = realpath(path, NULL); + + rc = daxctl_new(&ctx); + if (rc) { + return -1; + } + + daxctl_region_foreach(ctx, region) { + if (strstr(rpath, daxctl_region_get_path(region))) { + align = daxctl_region_get_align(region); + break; + } + } + daxctl_unref(ctx); + } +#endif /* defined(__linux__) && defined(CONFIG_LIBDAXCTL) */ + + return align; +} + static int file_ram_open(const char *path, const char *region_name, bool *created, @@ -2096,15 +1756,15 @@ int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp) if (!(block->flags & RAM_RESIZEABLE)) { error_setg_errno(errp, EINVAL, - "Length mismatch: %s: 0x" RAM_ADDR_FMT - " in != 0x" RAM_ADDR_FMT, block->idstr, + "Size mismatch: %s: 0x" RAM_ADDR_FMT + " != 0x" RAM_ADDR_FMT, block->idstr, newsize, block->used_length); return -EINVAL; } if (block->max_length < newsize) { error_setg_errno(errp, EINVAL, - "Length too large: %s: 0x" RAM_ADDR_FMT + "Size too large: %s: 0x" RAM_ADDR_FMT " > 0x" RAM_ADDR_FMT, block->idstr, newsize, block->max_length); return -EINVAL; @@ -2127,7 +1787,7 @@ int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp) * Otherwise no-op. * @Note: this is supposed to be a synchronous op. */ -void qemu_ram_writeback(RAMBlock *block, ram_addr_t start, ram_addr_t length) +void qemu_ram_msync(RAMBlock *block, ram_addr_t start, ram_addr_t length) { /* The requested range should fit in within the block range */ g_assert((start + length) <= block->used_length); @@ -2175,7 +1835,7 @@ static void dirty_memory_extend(ram_addr_t old_ram_size, DirtyMemoryBlocks *new_blocks; int j; - old_blocks = atomic_rcu_read(&ram_list.dirty_memory[i]); + old_blocks = qatomic_rcu_read(&ram_list.dirty_memory[i]); new_blocks = g_malloc(sizeof(*new_blocks) + sizeof(new_blocks->blocks[0]) * new_num_blocks); @@ -2188,7 +1848,7 @@ static void dirty_memory_extend(ram_addr_t old_ram_size, new_blocks->blocks[j] = bitmap_new(DIRTY_MEMORY_BLOCK_SIZE); } - atomic_rcu_set(&ram_list.dirty_memory[i], new_blocks); + qatomic_rcu_set(&ram_list.dirty_memory[i], new_blocks); if (old_blocks) { g_free_rcu(old_blocks, rcu); @@ -2287,7 +1947,7 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr, { RAMBlock *new_block; Error *local_err = NULL; - int64_t file_size; + int64_t file_size, file_align; /* Just support these ram flags by now. */ assert((ram_flags & ~(RAM_SHARED | RAM_PMEM)) == 0); @@ -2323,6 +1983,14 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr, return NULL; } + file_align = get_file_align(fd); + if (file_align > 0 && mr && file_align > mr->align) { + error_setg(errp, "backing store align 0x%" PRIx64 + " is larger than 'align' option 0x%" PRIx64, + file_align, mr->align); + return NULL; + } + new_block = g_malloc0(sizeof(*new_block)); new_block->mr = mr; new_block->used_length = size; @@ -2627,7 +2295,7 @@ RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset, } RCU_READ_LOCK_GUARD(); - block = atomic_rcu_read(&ram_list.mru_block); + block = qatomic_rcu_read(&ram_list.mru_block); if (block && block->host && host - block->host < block->max_length) { goto found; } @@ -2711,6 +2379,14 @@ void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len, QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { if (watchpoint_address_matches(wp, addr, len) && (wp->flags & flags)) { + if (replay_running_debug()) { + /* + * Don't process the watchpoints when we are + * in a reverse debugging operation. + */ + replay_breakpoint(); + return; + } if (flags == BP_MEM_READ) { wp->flags |= BP_WATCHPOINT_HIT_READ; } else { @@ -2872,7 +2548,7 @@ MemoryRegionSection *iotlb_to_section(CPUState *cpu, { int asidx = cpu_asidx_from_attrs(cpu, attrs); CPUAddressSpace *cpuas = &cpu->cpu_ases[asidx]; - AddressSpaceDispatch *d = atomic_rcu_read(&cpuas->memory_dispatch); + AddressSpaceDispatch *d = qatomic_rcu_read(&cpuas->memory_dispatch); MemoryRegionSection *sections = d->map.sections; return §ions[index & ~TARGET_PAGE_MASK]; @@ -2956,7 +2632,7 @@ static void tcg_commit(MemoryListener *listener) * may have split the RCU critical section. */ d = address_space_to_dispatch(cpuas->as); - atomic_rcu_set(&cpuas->memory_dispatch, d); + qatomic_rcu_set(&cpuas->memory_dispatch, d); tlb_flush(cpuas->cpu); } @@ -2983,52 +2659,6 @@ MemoryRegion *get_system_io(void) return system_io; } -#endif /* !defined(CONFIG_USER_ONLY) */ - -/* physical memory access (slow version, mainly for debug) */ -#if defined(CONFIG_USER_ONLY) -int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr, - void *ptr, target_ulong len, bool is_write) -{ - int flags; - target_ulong l, page; - void * p; - uint8_t *buf = ptr; - - while (len > 0) { - page = addr & TARGET_PAGE_MASK; - l = (page + TARGET_PAGE_SIZE) - addr; - if (l > len) - l = len; - flags = page_get_flags(page); - if (!(flags & PAGE_VALID)) - return -1; - if (is_write) { - if (!(flags & PAGE_WRITE)) - return -1; - /* XXX: this code should not depend on lock_user */ - if (!(p = lock_user(VERIFY_WRITE, addr, l, 0))) - return -1; - memcpy(p, buf, l); - unlock_user(p, addr, l); - } else { - if (!(flags & PAGE_READ)) - return -1; - /* XXX: this code should not depend on lock_user */ - if (!(p = lock_user(VERIFY_READ, addr, l, 1))) - return -1; - memcpy(buf, p, l); - unlock_user(p, addr, 0); - } - len -= l; - buf += l; - addr += l; - } - return 0; -} - -#else - static void invalidate_and_set_dirty(MemoryRegion *mr, hwaddr addr, hwaddr length) { @@ -3093,22 +2723,14 @@ static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr) static bool prepare_mmio_access(MemoryRegion *mr) { - bool unlocked = !qemu_mutex_iothread_locked(); bool release_lock = false; - if (unlocked && mr->global_locking) { + if (!qemu_mutex_iothread_locked()) { qemu_mutex_lock_iothread(); - unlocked = false; release_lock = true; } if (mr->flush_coalesced_mmio) { - if (unlocked) { - qemu_mutex_lock_iothread(); - } qemu_flush_coalesced_mmio_buffer(); - if (unlocked) { - qemu_mutex_unlock_iothread(); - } } return release_lock; @@ -3202,6 +2824,7 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr, stn_he_p(buf, l, val); } else { /* RAM case */ + fuzz_dma_read_cb(addr, len, mr, false); ram_ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false); memcpy(buf, ram_ptr, l); } @@ -3403,7 +3026,7 @@ void cpu_register_map_client(QEMUBH *bh) qemu_mutex_lock(&map_client_list_lock); client->bh = bh; QLIST_INSERT_HEAD(&map_client_list, client, link); - if (!atomic_read(&bounce.in_use)) { + if (!qatomic_read(&bounce.in_use)) { cpu_notify_map_clients_locked(); } qemu_mutex_unlock(&map_client_list_lock); @@ -3537,7 +3160,8 @@ void *address_space_map(AddressSpace *as, mr = flatview_translate(fv, addr, &xlat, &l, is_write, attrs); if (!memory_access_is_direct(mr, is_write)) { - if (atomic_xchg(&bounce.in_use, true)) { + if (qatomic_xchg(&bounce.in_use, true)) { + *plen = 0; return NULL; } /* Avoid unbounded allocations */ @@ -3561,6 +3185,7 @@ void *address_space_map(AddressSpace *as, memory_region_ref(mr); *plen = flatview_extend_translation(fv, addr, len, mr, xlat, l, is_write, attrs); + fuzz_dma_read_cb(addr, *plen, mr, is_write); ptr = qemu_ram_ptr_length(mr->ram_block, xlat, plen, true); return ptr; @@ -3595,7 +3220,7 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, qemu_vfree(bounce.buffer); bounce.buffer = NULL; memory_region_unref(bounce.mr); - atomic_mb_set(&bounce.in_use, false); + qatomic_mb_set(&bounce.in_use, false); cpu_notify_map_clients(); } @@ -3619,7 +3244,7 @@ void cpu_physical_memory_unmap(void *buffer, hwaddr len, #define TRANSLATE(...) address_space_translate(as, __VA_ARGS__) #define RCU_READ_LOCK(...) rcu_read_lock() #define RCU_READ_UNLOCK(...) rcu_read_unlock() -#include "memory_ldst.inc.c" +#include "memory_ldst.c.inc" int64_t address_space_cache_init(MemoryRegionCache *cache, AddressSpace *as, @@ -3716,7 +3341,7 @@ static inline MemoryRegion *address_space_translate_cached( /* Called from RCU critical section. address_space_read_cached uses this * out of line function when the target is an MMIO or IOMMU region. */ -void +MemTxResult address_space_read_cached_slow(MemoryRegionCache *cache, hwaddr addr, void *buf, hwaddr len) { @@ -3726,15 +3351,15 @@ address_space_read_cached_slow(MemoryRegionCache *cache, hwaddr addr, l = len; mr = address_space_translate_cached(cache, addr, &addr1, &l, false, MEMTXATTRS_UNSPECIFIED); - flatview_read_continue(cache->fv, - addr, MEMTXATTRS_UNSPECIFIED, buf, len, - addr1, l, mr); + return flatview_read_continue(cache->fv, + addr, MEMTXATTRS_UNSPECIFIED, buf, len, + addr1, l, mr); } /* Called from RCU critical section. address_space_write_cached uses this * out of line function when the target is an MMIO or IOMMU region. */ -void +MemTxResult address_space_write_cached_slow(MemoryRegionCache *cache, hwaddr addr, const void *buf, hwaddr len) { @@ -3744,9 +3369,9 @@ address_space_write_cached_slow(MemoryRegionCache *cache, hwaddr addr, l = len; mr = address_space_translate_cached(cache, addr, &addr1, &l, true, MEMTXATTRS_UNSPECIFIED); - flatview_write_continue(cache->fv, - addr, MEMTXATTRS_UNSPECIFIED, buf, len, - addr1, l, mr); + return flatview_write_continue(cache->fv, + addr, MEMTXATTRS_UNSPECIFIED, buf, len, + addr1, l, mr); } #define ARG1_DECL MemoryRegionCache *cache @@ -3755,7 +3380,7 @@ address_space_write_cached_slow(MemoryRegionCache *cache, hwaddr addr, #define TRANSLATE(...) address_space_translate_cached(cache, __VA_ARGS__) #define RCU_READ_LOCK() ((void)0) #define RCU_READ_UNLOCK() ((void)0) -#include "memory_ldst.inc.c" +#include "memory_ldst.c.inc" /* virtual memory access for debug (includes writing to ROM) */ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr, @@ -3769,6 +3394,7 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr, while (len > 0) { int asidx; MemTxAttrs attrs; + MemTxResult res; page = addr & TARGET_PAGE_MASK; phys_addr = cpu_get_phys_page_attrs_debug(cpu, page, &attrs); @@ -3781,11 +3407,14 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr, l = len; phys_addr += (addr & ~TARGET_PAGE_MASK); if (is_write) { - address_space_write_rom(cpu->cpu_ases[asidx].as, phys_addr, - attrs, buf, l); + res = address_space_write_rom(cpu->cpu_ases[asidx].as, phys_addr, + attrs, buf, l); } else { - address_space_read(cpu->cpu_ases[asidx].as, phys_addr, attrs, buf, - l); + res = address_space_read(cpu->cpu_ases[asidx].as, phys_addr, + attrs, buf, l); + } + if (res != MEMTX_OK) { + return -1; } len -= l; buf += l; @@ -3812,18 +3441,7 @@ int qemu_target_page_bits_min(void) { return TARGET_PAGE_BITS_MIN; } -#endif -bool target_words_bigendian(void) -{ -#if defined(TARGET_WORDS_BIGENDIAN) - return true; -#else - return false; -#endif -} - -#ifndef CONFIG_USER_ONLY bool cpu_physical_memory_is_io(hwaddr phys_addr) { MemoryRegion*mr; @@ -3953,23 +3571,6 @@ bool ramblock_is_pmem(RAMBlock *rb) return rb->flags & RAM_PMEM; } -#endif - -void page_size_init(void) -{ - /* NOTE: we can always suppose that qemu_host_page_size >= - TARGET_PAGE_SIZE */ - if (qemu_host_page_size == 0) { - qemu_host_page_size = qemu_real_host_page_size; - } - if (qemu_host_page_size < TARGET_PAGE_SIZE) { - qemu_host_page_size = TARGET_PAGE_SIZE; - } - qemu_host_page_mask = -(intptr_t)qemu_host_page_size; -} - -#if !defined(CONFIG_USER_ONLY) - static void mtree_print_phys_entries(int start, int end, int skip, int ptr) { if (start == end - 1) { @@ -4049,4 +3650,56 @@ void mtree_print_dispatch(AddressSpaceDispatch *d, MemoryRegion *root) } } -#endif +/* + * If positive, discarding RAM is disabled. If negative, discarding RAM is + * required to work and cannot be disabled. + */ +static int ram_block_discard_disabled; + +int ram_block_discard_disable(bool state) +{ + int old; + + if (!state) { + qatomic_dec(&ram_block_discard_disabled); + return 0; + } + + do { + old = qatomic_read(&ram_block_discard_disabled); + if (old < 0) { + return -EBUSY; + } + } while (qatomic_cmpxchg(&ram_block_discard_disabled, + old, old + 1) != old); + return 0; +} + +int ram_block_discard_require(bool state) +{ + int old; + + if (!state) { + qatomic_inc(&ram_block_discard_disabled); + return 0; + } + + do { + old = qatomic_read(&ram_block_discard_disabled); + if (old > 0) { + return -EBUSY; + } + } while (qatomic_cmpxchg(&ram_block_discard_disabled, + old, old - 1) != old); + return 0; +} + +bool ram_block_discard_is_disabled(void) +{ + return qatomic_read(&ram_block_discard_disabled) > 0; +} + +bool ram_block_discard_is_required(void) +{ + return qatomic_read(&ram_block_discard_disabled) < 0; +} diff --git a/qdev-monitor.c b/softmmu/qdev-monitor.c similarity index 95% rename from qdev-monitor.c rename to softmmu/qdev-monitor.c index a4735d3bb190041bea530d366ca3268f3ddd8ae4..bf79d0bbcd986320eb609f37253e214ffb17d5f8 100644 --- a/qdev-monitor.c +++ b/softmmu/qdev-monitor.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -53,7 +53,9 @@ typedef struct QDevAlias /* Please keep this table sorted by typename. */ static const QDevAlias qdev_alias_table[] = { + { "AC97", "ac97" }, /* -soundhw name */ { "e1000", "e1000-82540em" }, + { "ES1370", "es1370" }, /* -soundhw name */ { "ich9-ahci", "ahci" }, { "lsi53c895a", "lsi" }, { "virtio-9p-ccw", "virtio-9p", QEMU_ARCH_S390X }, @@ -147,6 +149,7 @@ static void qdev_print_devinfos(bool show_no_user) int i; bool cat_printed; + module_load_qom_all(); list = object_class_get_list_sorted(TYPE_DEVICE, false); for (i = 0; i <= DEVICE_CATEGORY_MAX; i++) { @@ -176,16 +179,13 @@ static int set_property(void *opaque, const char *name, const char *value, Error **errp) { Object *obj = opaque; - Error *err = NULL; if (strcmp(name, "driver") == 0) return 0; if (strcmp(name, "bus") == 0) return 0; - object_property_parse(obj, value, name, &err); - if (err != NULL) { - error_propagate(errp, err); + if (!object_property_parse(obj, name, value, errp)) { return -1; } return 0; @@ -215,13 +215,13 @@ static DeviceClass *qdev_get_device_class(const char **driver, Error **errp) DeviceClass *dc; const char *original_name = *driver; - oc = object_class_by_name(*driver); + oc = module_object_class_by_name(*driver); if (!oc) { const char *typename = find_typename_by_alias(*driver); if (typename) { *driver = typename; - oc = object_class_by_name(*driver); + oc = module_object_class_by_name(*driver); } } @@ -300,7 +300,7 @@ int qdev_device_help(QemuOpts *opts) } g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0); for (i = 0; i < array->len; i++) { - printf("%s\n", (char *)array->pdata[i]); + qemu_printf("%s\n", (char *)array->pdata[i]); } g_ptr_array_set_free_func(array, g_free); g_ptr_array_free(array, true); @@ -600,7 +600,6 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) const char *driver, *path; DeviceState *dev = NULL; BusState *bus = NULL; - Error *err = NULL; bool hide; driver = qemu_opt_get(opts, "driver"); @@ -652,20 +651,16 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) } /* create device */ - dev = DEVICE(object_new(driver)); + dev = qdev_new(driver); /* Check whether the hotplug is allowed by the machine */ - if (qdev_hotplug && !qdev_hotplug_allowed(dev, &err)) { - /* Error must be set in the machine hook */ - assert(err); + if (qdev_hotplug && !qdev_hotplug_allowed(dev, errp)) { goto err_del_dev; } - if (bus) { - qdev_set_parent_bus(dev, bus); - } else if (qdev_hotplug && !qdev_get_machine_hotplug_handler(dev)) { + if (!bus && qdev_hotplug && !qdev_get_machine_hotplug_handler(dev)) { /* No bus, no machine hotplug handler --> device is not hotpluggable */ - error_setg(&err, "Device '%s' can not be hotplugged on this machine", + error_setg(errp, "Device '%s' can not be hotplugged on this machine", driver); goto err_del_dev; } @@ -673,20 +668,18 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) qdev_set_id(dev, qemu_opts_id(opts)); /* set properties */ - if (qemu_opt_foreach(opts, set_property, dev, &err)) { + if (qemu_opt_foreach(opts, set_property, dev, errp)) { goto err_del_dev; } dev->opts = opts; - object_property_set_bool(OBJECT(dev), true, "realized", &err); - if (err != NULL) { + if (!qdev_realize(DEVICE(dev), bus, errp)) { dev->opts = NULL; goto err_del_dev; } return dev; err_del_dev: - error_propagate(errp, err); if (dev) { object_unparent(OBJECT(dev)); object_unref(OBJECT(dev)); @@ -704,22 +697,22 @@ static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props, if (!props) return; for (; props->name; props++) { - Error *err = NULL; char *value; char *legacy_name = g_strdup_printf("legacy-%s", props->name); + if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) { - value = object_property_get_str(OBJECT(dev), legacy_name, &err); + value = object_property_get_str(OBJECT(dev), legacy_name, NULL); } else { - value = object_property_print(OBJECT(dev), props->name, true, &err); + value = object_property_print(OBJECT(dev), props->name, true, + NULL); } g_free(legacy_name); - if (err) { - error_free(err); + if (!value) { continue; } qdev_printf("%s = %s\n", props->name, - value && *value ? value : ""); + *value ? value : ""); g_free(value); } } @@ -798,22 +791,31 @@ void hmp_info_qdm(Monitor *mon, const QDict *qdict) void qmp_device_add(QDict *qdict, QObject **ret_data, Error **errp) { - Error *local_err = NULL; QemuOpts *opts; DeviceState *dev; - opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_err); - if (local_err) { - error_propagate(errp, local_err); + opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, errp); + if (!opts) { return; } if (!monitor_cur_is_qmp() && qdev_device_help(opts)) { qemu_opts_del(opts); return; } - dev = qdev_device_add(opts, &local_err); + dev = qdev_device_add(opts, errp); + + /* + * Drain all pending RCU callbacks. This is done because + * some bus related operations can delay a device removal + * (in this case this can happen if device is added and then + * removed due to a configuration error) + * to a RCU callback, but user might expect that this interface + * will finish its job completely once qmp command returns result + * to the user + */ + drain_call_rcu(); + if (!dev) { - error_propagate(errp, local_err); qemu_opts_del(opts); return; } diff --git a/qemu-seccomp.c b/softmmu/qemu-seccomp.c similarity index 99% rename from qemu-seccomp.c rename to softmmu/qemu-seccomp.c index e0a1829b3ddc9732f357179b9c23ce4b48703efb..8325ecb766e0f3fb27ff85a84a301a66a0a7a0fd 100644 --- a/qemu-seccomp.c +++ b/softmmu/qemu-seccomp.c @@ -136,8 +136,9 @@ static uint32_t qemu_seccomp_get_action(int set) if (qemu_seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &action) == 0) { kill_process = 1; + } else { + kill_process = 0; } - kill_process = 0; } if (kill_process == 1) { return SCMP_ACT_KILL_PROCESS; diff --git a/qtest.c b/softmmu/qtest.c similarity index 90% rename from qtest.c rename to softmmu/qtest.c index 5672b75c354b6cdae5df0b0d49e0ba9da0b13faf..7965dc9a16ba88a479b34d1f4b19a9c71dc24583 100644 --- a/qtest.c +++ b/softmmu/qtest.c @@ -21,13 +21,13 @@ #include "exec/memory.h" #include "hw/irq.h" #include "sysemu/accel.h" -#include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" #include "qemu/config-file.h" #include "qemu/option.h" #include "qemu/error-report.h" #include "qemu/module.h" #include "qemu/cutils.h" -#include "config-devices.h" +#include CONFIG_DEVICES #ifdef CONFIG_PSERIES #include "hw/ppc/spapr_rtas.h" #endif @@ -49,92 +49,139 @@ static void *qtest_server_send_opaque; #define FMT_timeval "%ld.%06ld" /** - * QTest Protocol + * DOC: QTest Protocol * * Line based protocol, request/response based. Server can send async messages * so clients should always handle many async messages before the response * comes in. * * Valid requests + * ^^^^^^^^^^^^^^ * * Clock management: + * """"""""""""""""" * * The qtest client is completely in charge of the QEMU_CLOCK_VIRTUAL. qtest commands * let you adjust the value of the clock (monotonically). All the commands * return the current value of the clock in nanoseconds. * + * .. code-block:: none + * * > clock_step * < OK VALUE * - * Advance the clock to the next deadline. Useful when waiting for - * asynchronous events. + * Advance the clock to the next deadline. Useful when waiting for + * asynchronous events. + * + * .. code-block:: none * * > clock_step NS * < OK VALUE * - * Advance the clock by NS nanoseconds. + * Advance the clock by NS nanoseconds. + * + * .. code-block:: none * * > clock_set NS * < OK VALUE * - * Advance the clock to NS nanoseconds (do nothing if it's already past). + * Advance the clock to NS nanoseconds (do nothing if it's already past). * * PIO and memory access: + * """""""""""""""""""""" + * + * .. code-block:: none * * > outb ADDR VALUE * < OK * + * .. code-block:: none + * * > outw ADDR VALUE * < OK * + * .. code-block:: none + * * > outl ADDR VALUE * < OK * + * .. code-block:: none + * * > inb ADDR * < OK VALUE * + * .. code-block:: none + * * > inw ADDR * < OK VALUE * + * .. code-block:: none + * * > inl ADDR * < OK VALUE * + * .. code-block:: none + * * > writeb ADDR VALUE * < OK * + * .. code-block:: none + * * > writew ADDR VALUE * < OK * + * .. code-block:: none + * * > writel ADDR VALUE * < OK * + * .. code-block:: none + * * > writeq ADDR VALUE * < OK * + * .. code-block:: none + * * > readb ADDR * < OK VALUE * + * .. code-block:: none + * * > readw ADDR * < OK VALUE * + * .. code-block:: none + * * > readl ADDR * < OK VALUE * + * .. code-block:: none + * * > readq ADDR * < OK VALUE * + * .. code-block:: none + * * > read ADDR SIZE * < OK DATA * + * .. code-block:: none + * * > write ADDR SIZE DATA * < OK * + * .. code-block:: none + * * > b64read ADDR SIZE * < OK B64_DATA * + * .. code-block:: none + * * > b64write ADDR SIZE B64_DATA * < OK * + * .. code-block:: none + * * > memset ADDR SIZE VALUE * < OK * @@ -149,16 +196,21 @@ static void *qtest_server_send_opaque; * If the sizes do not match, the data will be truncated. * * IRQ management: + * """"""""""""""" + * + * .. code-block:: none * * > irq_intercept_in QOM-PATH * < OK * + * .. code-block:: none + * * > irq_intercept_out QOM-PATH * < OK * * Attach to the gpio-in (resp. gpio-out) pins exported by the device at * QOM-PATH. When the pin is triggered, one of the following async messages - * will be printed to the qtest stream: + * will be printed to the qtest stream:: * * IRQ raise NUM * IRQ lower NUM @@ -168,12 +220,15 @@ static void *qtest_server_send_opaque; * NUM=0 even though it is remapped to GSI 2). * * Setting interrupt level: + * """""""""""""""""""""""" + * + * .. code-block:: none * * > set_irq_in QOM-PATH NAME NUM LEVEL * < OK * - * where NAME is the name of the irq/gpio list, NUM is an IRQ number and - * LEVEL is an signed integer IRQ level. + * where NAME is the name of the irq/gpio list, NUM is an IRQ number and + * LEVEL is an signed integer IRQ level. * * Forcibly set the given interrupt pin to the given level. * @@ -273,6 +328,38 @@ static void qtest_irq_handler(void *opaque, int n, int level) } } +static int64_t qtest_clock_counter; + +int64_t qtest_get_virtual_clock(void) +{ + return qatomic_read_i64(&qtest_clock_counter); +} + +static void qtest_set_virtual_clock(int64_t count) +{ + qatomic_set_i64(&qtest_clock_counter, count); +} + +static void qtest_clock_warp(int64_t dest) +{ + int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + AioContext *aio_context; + assert(qtest_enabled()); + aio_context = qemu_get_aio_context(); + while (clock < dest) { + int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, + QEMU_TIMER_ATTR_ALL); + int64_t warp = qemu_soonest_timeout(dest - clock, deadline); + + qtest_set_virtual_clock(qtest_get_virtual_clock() + warp); + + qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL); + timerlist_run_timers(aio_context->tlg.tl[QEMU_CLOCK_VIRTUAL]); + clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + } + qemu_clock_notify(QEMU_CLOCK_VIRTUAL); +} + static void qtest_process_command(CharBackend *chr, gchar **words) { const gchar *command; @@ -670,7 +757,7 @@ static void qtest_process_command(CharBackend *chr, gchar **words) g_assert(words[1] && words[2]); qtest_send_prefix(chr); - if (module_load_one(words[1], words[2])) { + if (module_load_one(words[1], words[2], false)) { qtest_sendf(chr, "OK\n"); } else { qtest_sendf(chr, "FAIL\n"); diff --git a/softmmu/timers-state.h b/softmmu/timers-state.h new file mode 100644 index 0000000000000000000000000000000000000000..db4e60f18fd5470de54c0d5b428aaa7d347a5fad --- /dev/null +++ b/softmmu/timers-state.h @@ -0,0 +1,69 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef TIMERS_STATE_H +#define TIMERS_STATE_H + +/* timers state, for sharing between icount and cpu-timers */ + +typedef struct TimersState { + /* Protected by BQL. */ + int64_t cpu_ticks_prev; + int64_t cpu_ticks_offset; + + /* + * Protect fields that can be respectively read outside the + * BQL, and written from multiple threads. + */ + QemuSeqLock vm_clock_seqlock; + QemuSpin vm_clock_lock; + + int16_t cpu_ticks_enabled; + + /* Conversion factor from emulated instructions to virtual clock ticks. */ + int16_t icount_time_shift; + + /* Compensate for varying guest execution speed. */ + int64_t qemu_icount_bias; + + int64_t vm_clock_warp_start; + int64_t cpu_clock_offset; + + /* Only written by TCG thread */ + int64_t qemu_icount; + + /* for adjusting icount */ + QEMUTimer *icount_rt_timer; + QEMUTimer *icount_vm_timer; + QEMUTimer *icount_warp_timer; +} TimersState; + +extern TimersState timers_state; + +/* + * icount needs this internal from cpu-timers when adjusting the icount shift. + */ +int64_t cpu_get_clock_locked(void); + +#endif /* TIMERS_STATE_H */ diff --git a/tpm.c b/softmmu/tpm.c similarity index 81% rename from tpm.c rename to softmmu/tpm.c index 9c9e20bbb7e070e864d5d36e99bebafe0ee37dee..cab206355afdcb0a3cf1d36ca21aeb45a56f5232 100644 --- a/tpm.c +++ b/softmmu/tpm.c @@ -47,18 +47,23 @@ tpm_be_find_by_type(enum TpmType type) */ static void tpm_display_backend_drivers(void) { + bool got_one = false; int i; - fprintf(stderr, "Supported TPM types (choose only one):\n"); - for (i = 0; i < TPM_TYPE__MAX; i++) { const TPMBackendClass *bc = tpm_be_find_by_type(i); if (!bc) { continue; } - fprintf(stderr, "%12s %s\n", TpmType_str(i), bc->desc); + if (!got_one) { + error_printf("Supported TPM types (choose only one):\n"); + got_one = true; + } + error_printf("%12s %s\n", TpmType_str(i), bc->desc); + } + if (!got_one) { + error_printf("No TPM backend types are available\n"); } - fprintf(stderr, "\n"); } /* @@ -81,6 +86,12 @@ TPMBackend *qemu_find_tpm_be(const char *id) static int tpm_init_tpmdev(void *dummy, QemuOpts *opts, Error **errp) { + /* + * Use of error_report() in a function with an Error ** parameter + * is suspicious. It is okay here. The parameter only exists to + * make the function usable with qemu_opts_foreach(). It is not + * actually used. + */ const char *value; const char *id; const TPMBackendClass *be; @@ -89,19 +100,19 @@ static int tpm_init_tpmdev(void *dummy, QemuOpts *opts, Error **errp) int i; if (!QLIST_EMPTY(&tpm_backends)) { - error_setg(errp, "Only one TPM is allowed."); + error_report("Only one TPM is allowed."); return 1; } id = qemu_opts_id(opts); if (id == NULL) { - error_setg(errp, QERR_MISSING_PARAMETER, "id"); + error_report(QERR_MISSING_PARAMETER, "id"); return 1; } value = qemu_opt_get(opts, "type"); if (!value) { - error_setg(errp, QERR_MISSING_PARAMETER, "type"); + error_report(QERR_MISSING_PARAMETER, "type"); tpm_display_backend_drivers(); return 1; } @@ -109,16 +120,15 @@ static int tpm_init_tpmdev(void *dummy, QemuOpts *opts, Error **errp) i = qapi_enum_parse(&TpmType_lookup, value, -1, NULL); be = i >= 0 ? tpm_be_find_by_type(i) : NULL; if (be == NULL) { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type", - "a TPM backend type"); + error_report(QERR_INVALID_PARAMETER_VALUE, + "type", "a TPM backend type"); tpm_display_backend_drivers(); return 1; } /* validate backend specific opts */ - qemu_opts_validate(opts, be->opts, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_validate(opts, be->opts, &local_err)) { + error_report_err(local_err); return 1; } @@ -151,10 +161,14 @@ void tpm_cleanup(void) * Initialize the TPM. Process the tpmdev command line options describing the * TPM backend. */ -void tpm_init(void) +int tpm_init(void) { - qemu_opts_foreach(qemu_find_opts("tpmdev"), - tpm_init_tpmdev, NULL, &error_fatal); + if (qemu_opts_foreach(qemu_find_opts("tpmdev"), + tpm_init_tpmdev, NULL, NULL)) { + return -1; + } + + return 0; } /* diff --git a/softmmu/trace-events b/softmmu/trace-events new file mode 100644 index 0000000000000000000000000000000000000000..b80ca042e1ffc4f3166bc54d36a79098e04244bf --- /dev/null +++ b/softmmu/trace-events @@ -0,0 +1,28 @@ +# See docs/devel/tracing.txt for syntax documentation. + +# balloon.c +# Since requests are raised via monitor, not many tracepoints are needed. +balloon_event(void *opaque, unsigned long addr) "opaque %p addr %lu" + +# ioport.c +cpu_in(unsigned int addr, char size, unsigned int val) "addr 0x%x(%c) value %u" +cpu_out(unsigned int addr, char size, unsigned int val) "addr 0x%x(%c) value %u" + +# memory.c +memory_region_ops_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u" +memory_region_ops_write(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u" +memory_region_subpage_read(int cpu_index, void *mr, uint64_t offset, uint64_t value, unsigned size) "cpu %d mr %p offset 0x%"PRIx64" value 0x%"PRIx64" size %u" +memory_region_subpage_write(int cpu_index, void *mr, uint64_t offset, uint64_t value, unsigned size) "cpu %d mr %p offset 0x%"PRIx64" value 0x%"PRIx64" size %u" +memory_region_ram_device_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u" +memory_region_ram_device_write(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u" +flatview_new(void *view, void *root) "%p (root %p)" +flatview_destroy(void *view, void *root) "%p (root %p)" +flatview_destroy_rcu(void *view, void *root) "%p (root %p)" + +# vl.c +vm_state_notify(int running, int reason, const char *reason_str) "running %d reason %d (%s)" +load_file(const char *name, const char *path) "name %s location %s" +runstate_set(int current_state, const char *current_state_str, int new_state, const char *new_state_str) "current_run_state %d (%s) new_state %d (%s)" +system_wakeup_request(int reason) "reason=%d" +qemu_system_shutdown_request(int reason) "reason=%d" +qemu_system_powerdown_request(void) "" diff --git a/softmmu/trace.h b/softmmu/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..2ad10115726e5885f3895139155b087acb51c371 --- /dev/null +++ b/softmmu/trace.h @@ -0,0 +1 @@ +#include "trace/trace-softmmu.h" diff --git a/softmmu/vl.c b/softmmu/vl.c index ae5451bc2361d84aa2efa09fb72bb1ad5c7accbf..e6e0ad5a9259038413f855ef6374d4685ee156f8 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -36,6 +36,7 @@ #include "sysemu/runstate.h" #include "sysemu/seccomp.h" #include "sysemu/tcg.h" +#include "sysemu/xen.h" #include "qemu/error-report.h" #include "qemu/sockets.h" @@ -73,6 +74,7 @@ #include "hw/audio/soundhw.h" #include "audio/audio.h" #include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" #include "migration/colo.h" #include "migration/postcopy-ram.h" #include "sysemu/kvm.h" @@ -89,7 +91,7 @@ #include "disas/disas.h" -#include "trace-root.h" +#include "trace.h" #include "trace/control.h" #include "qemu/plugin.h" #include "qemu/queue.h" @@ -144,7 +146,6 @@ static Chardev **serial_hds; Chardev *parallel_hds[MAX_PARALLEL_PORTS]; int win2k_install_hack = 0; int singlestep = 0; -int no_hpet = 0; int fd_bootchk = 1; static int no_reboot; int no_shutdown = 0; @@ -163,8 +164,9 @@ bool boot_strict; uint8_t *boot_splash_filedata; int only_migratable; /* turn it off unless user states otherwise */ bool wakeup_suspend_enabled; - int icount_align_option; +static const char *qtest_chrdev; +static const char *qtest_log; /* The bytes in qemu_uuid are in the order specified by RFC4122, _not_ in the * little-endian "wire format" described in the SMBIOS 2.6 specification. @@ -178,7 +180,6 @@ static NotifierList exit_notifiers = static NotifierList machine_init_done_notifiers = NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers); -bool xen_allowed; uint32_t xen_domid; enum xen_mode xen_mode = XEN_EMULATE; bool xen_domid_restrict; @@ -389,6 +390,12 @@ static QemuOptsList qemu_msg_opts = { .name = "timestamp", .type = QEMU_OPT_BOOL, }, + { + .name = "guest-name", + .type = QEMU_OPT_BOOL, + .help = "Prepends guest name for error messages but only if " + "-name guest is set otherwise option is ignored\n", + }, { /* end of list */ } }, }; @@ -489,6 +496,11 @@ static QemuOptsList qemu_fw_cfg_opts = { .name = "string", .type = QEMU_OPT_STRING, .help = "Sets content of the blob to be inserted from a string", + }, { + .name = "gen_id", + .type = QEMU_OPT_STRING, + .help = "Sets id of the object generating the fw_cfg blob " + "to be inserted", }, { /* end of list */ } }, @@ -620,6 +632,7 @@ static const RunStateTransition runstate_transitions_def[] = { { RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED }, { RUN_STATE_SHUTDOWN, RUN_STATE_FINISH_MIGRATE }, { RUN_STATE_SHUTDOWN, RUN_STATE_PRELAUNCH }, + { RUN_STATE_SHUTDOWN, RUN_STATE_COLO }, { RUN_STATE_DEBUG, RUN_STATE_SUSPENDED }, { RUN_STATE_RUNNING, RUN_STATE_SUSPENDED }, @@ -1109,6 +1122,7 @@ static void realtime_init(void) static void configure_msg(QemuOpts *opts) { error_with_timestamp = qemu_opt_get_bool(opts, "timestamp", false); + error_with_guestname = qemu_opt_get_bool(opts, "guest-name", false); } @@ -1308,7 +1322,7 @@ ShutdownCause qemu_reset_requested_get(void) static int qemu_shutdown_requested(void) { - return atomic_xchg(&shutdown_requested, SHUTDOWN_CAUSE_NONE); + return qatomic_xchg(&shutdown_requested, SHUTDOWN_CAUSE_NONE); } static void qemu_kill_report(void) @@ -1772,8 +1786,8 @@ static bool vga_interface_available(VGAInterfaceType t) assert(t < VGA_TYPE_MAX); return !ti->class_names[0] || - object_class_by_name(ti->class_names[0]) || - object_class_by_name(ti->class_names[1]); + module_object_class_by_name(ti->class_names[0]) || + module_object_class_by_name(ti->class_names[1]); } static const char * @@ -1993,7 +2007,7 @@ char *qemu_find_file(int type, const char *name) return NULL; } -static void qemu_add_data_dir(const char *path) +void qemu_add_data_dir(char *path) { int i; @@ -2005,10 +2019,11 @@ static void qemu_add_data_dir(const char *path) } for (i = 0; i < data_dir_idx; i++) { if (strcmp(data_dir[i], path) == 0) { - return; /* duplicate */ + g_free(path); /* duplicate */ + return; } } - data_dir[data_dir_idx++] = g_strdup(path); + data_dir[data_dir_idx++] = path; } static inline bool nonempty_str(const char *str) @@ -2020,7 +2035,7 @@ static int parse_fw_cfg(void *opaque, QemuOpts *opts, Error **errp) { gchar *buf; size_t size; - const char *name, *file, *str; + const char *name, *file, *str, *gen_id; FWCfgState *fw_cfg = (FWCfgState *) opaque; if (fw_cfg == NULL) { @@ -2030,14 +2045,13 @@ static int parse_fw_cfg(void *opaque, QemuOpts *opts, Error **errp) name = qemu_opt_get(opts, "name"); file = qemu_opt_get(opts, "file"); str = qemu_opt_get(opts, "string"); + gen_id = qemu_opt_get(opts, "gen_id"); - /* we need name and either a file or the content string */ - if (!(nonempty_str(name) && (nonempty_str(file) || nonempty_str(str)))) { - error_setg(errp, "invalid argument(s)"); - return -1; - } - if (nonempty_str(file) && nonempty_str(str)) { - error_setg(errp, "file and string are mutually exclusive"); + /* we need the name, and exactly one of: file, content string, gen_id */ + if (!nonempty_str(name) || + nonempty_str(file) + nonempty_str(str) + nonempty_str(gen_id) != 1) { + error_setg(errp, "name, plus exactly one of file," + " string and gen_id, are needed"); return -1; } if (strlen(name) > FW_CFG_MAX_FILE_PATH - 1) { @@ -2045,13 +2059,24 @@ static int parse_fw_cfg(void *opaque, QemuOpts *opts, Error **errp) FW_CFG_MAX_FILE_PATH - 1); return -1; } - if (strncmp(name, "opt/", 4) != 0) { + if (nonempty_str(gen_id)) { + /* + * In this particular case where the content is populated + * internally, the "etc/" namespace protection is relaxed, + * so do not emit a warning. + */ + } else if (strncmp(name, "opt/", 4) != 0) { warn_report("externally provided fw_cfg item names " "should be prefixed with \"opt/\""); } if (nonempty_str(str)) { size = strlen(str); /* NUL terminator NOT included in fw_cfg blob */ buf = g_memdup(str, size); + } else if (nonempty_str(gen_id)) { + if (!fw_cfg_add_from_generator(fw_cfg, name, gen_id, errp)) { + return -1; + } + return 0; } else { GError *err = NULL; if (!g_file_get_contents(file, &buf, &size, &err)) { @@ -2444,16 +2469,11 @@ static int object_parse_property_opt(Object *obj, const char *name, const char *value, const char *skip, Error **errp) { - Error *local_err = NULL; - if (g_str_equal(name, skip)) { return 0; } - object_property_parse(obj, value, name, &local_err); - - if (local_err) { - error_propagate(errp, local_err); + if (!object_property_parse(obj, name, value, errp)) { return -1; } @@ -2520,6 +2540,10 @@ static bool object_create_initial(const char *type, QemuOpts *opts) } #endif + /* Reason: vhost-user-blk-server property "node-name" */ + if (g_str_equal(type, "vhost-user-blk-server")) { + return false; + } /* * Reason: filter-* property "netdev" etc. */ @@ -2658,8 +2682,9 @@ static int global_init_func(void *opaque, QemuOpts *opts, Error **errp) static int qemu_read_default_config_file(void) { int ret; + g_autofree char *file = get_relocated_path(CONFIG_QEMU_CONFDIR "/qemu.conf"); - ret = qemu_read_config_file(CONFIG_QEMU_CONFDIR "/qemu.conf"); + ret = qemu_read_config_file(file); if (ret < 0 && ret != -ENOENT) { return ret; } @@ -2675,7 +2700,7 @@ static void user_register_global_props(void) static int do_configure_icount(void *opaque, QemuOpts *opts, Error **errp) { - configure_icount(opts, errp); + icount_configure(opts, errp); return 0; } @@ -2693,10 +2718,15 @@ static int do_configure_accelerator(void *opaque, QemuOpts *opts, Error **errp) AccelClass *ac = accel_find(acc); AccelState *accel; int ret; + bool qtest_with_kvm; + + qtest_with_kvm = g_str_equal(acc, "kvm") && qtest_chrdev != NULL; if (!ac) { *p_init_failed = true; - error_report("invalid accelerator %s", acc); + if (!qtest_with_kvm) { + error_report("invalid accelerator %s", acc); + } return 0; } accel = ACCEL(object_new_with_class(OBJECT_CLASS(ac))); @@ -2708,8 +2738,9 @@ static int do_configure_accelerator(void *opaque, QemuOpts *opts, Error **errp) ret = accel_init_machine(accel, current_machine); if (ret < 0) { *p_init_failed = true; - error_report("failed to initialize %s: %s", - acc, strerror(-ret)); + if (!qtest_with_kvm || ret != -ENOENT) { + error_report("failed to initialize %s: %s", acc, strerror(-ret)); + } return 0; } @@ -2780,12 +2811,12 @@ static void configure_accelerators(const char *progname) exit(1); } - if (init_failed) { + if (init_failed && !qtest_chrdev) { AccelClass *ac = ACCEL_GET_CLASS(current_accel()); error_report("falling back to %s", ac->name); } - if (use_icount && !(tcg_enabled() || qtest_enabled())) { + if (icount_enabled() && !tcg_enabled()) { error_report("-icount is not allowed with hardware virtualization"); exit(1); } @@ -2798,20 +2829,40 @@ static void create_default_memdev(MachineState *ms, const char *path) obj = object_new(path ? TYPE_MEMORY_BACKEND_FILE : TYPE_MEMORY_BACKEND_RAM); if (path) { - object_property_set_str(obj, path, "mem-path", &error_fatal); + object_property_set_str(obj, "mem-path", path, &error_fatal); } - object_property_set_int(obj, ms->ram_size, "size", &error_fatal); + object_property_set_int(obj, "size", ms->ram_size, &error_fatal); object_property_add_child(object_get_objects_root(), mc->default_ram_id, obj); /* Ensure backend's memory region name is equal to mc->default_ram_id */ - object_property_set_bool(obj, false, "x-use-canonical-path-for-ramblock-id", - &error_fatal); + object_property_set_bool(obj, "x-use-canonical-path-for-ramblock-id", + false, &error_fatal); user_creatable_complete(USER_CREATABLE(obj), &error_fatal); object_unref(obj); - object_property_set_str(OBJECT(ms), mc->default_ram_id, "memory-backend", + object_property_set_str(OBJECT(ms), "memory-backend", mc->default_ram_id, &error_fatal); } +/* + * Find a likely location for support files using the location of the binary. + * When running from the build tree this will be "$bindir/pc-bios". + * Otherwise, this is CONFIG_QEMU_DATADIR (possibly relocated). + * + * The caller must use g_free() to free the returned data when it is + * no longer required. + */ +static char *find_datadir(void) +{ + g_autofree char *dir = NULL; + + dir = g_build_filename(qemu_get_exec_dir(), "pc-bios", NULL); + if (g_file_test(dir, G_FILE_TEST_IS_DIR)) { + return g_steal_pointer(&dir); + } + + return get_relocated_path(CONFIG_QEMU_DATADIR); +} + void qemu_init(int argc, char **argv, char **envp) { int i; @@ -2830,22 +2881,19 @@ void qemu_init(int argc, char **argv, char **envp) MachineClass *machine_class; const char *cpu_option; const char *vga_model = NULL; - const char *qtest_chrdev = NULL; - const char *qtest_log = NULL; const char *incoming = NULL; bool userconfig = true; bool nographic = false; int display_remote = 0; const char *log_mask = NULL; const char *log_file = NULL; - char *trace_file = NULL; ram_addr_t maxram_size; uint64_t ram_slots = 0; FILE *vmstate_dump_file = NULL; Error *main_loop_err = NULL; Error *err = NULL; bool list_data_dirs = false; - char *dir, **dirs; + char **dirs; const char *mem_path = NULL; bool have_custom_ram_size; BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); @@ -3178,7 +3226,7 @@ void qemu_init(int argc, char **argv, char **envp) if (is_help_option(optarg)) { list_data_dirs = true; } else { - qemu_add_data_dir(optarg); + qemu_add_data_dir(g_strdup(optarg)); } break; case QEMU_OPTION_bios: @@ -3457,10 +3505,6 @@ void qemu_init(int argc, char **argv, char **envp) exit(1); } break; - case QEMU_OPTION_no_kvm: - olist = qemu_find_opts("machine"); - qemu_opts_parse_noisily(olist, "accel=tcg", false); - break; case QEMU_OPTION_accel: accel_opts = qemu_opts_parse_noisily(qemu_find_opts("accel"), optarg, true); @@ -3485,11 +3529,6 @@ void qemu_init(int argc, char **argv, char **envp) g_slist_free(accel_list); exit(0); } - if (optarg && strchr(optarg, ':')) { - error_report("Don't use ':' with -accel, " - "use -M accel=... for now instead"); - exit(1); - } break; case QEMU_OPTION_usb: olist = qemu_find_opts("machine"); @@ -3522,7 +3561,8 @@ void qemu_init(int argc, char **argv, char **envp) qemu_opts_parse_noisily(olist, "acpi=off", false); break; case QEMU_OPTION_no_hpet: - no_hpet = 1; + olist = qemu_find_opts("machine"); + qemu_opts_parse_noisily(olist, "hpet=off", false); break; case QEMU_OPTION_no_reboot: no_reboot = 1; @@ -3578,6 +3618,8 @@ void qemu_init(int argc, char **argv, char **envp) if (!opts) { exit(1); } + /* Capture guest name if -msg guest-name is used later */ + error_guest_name = qemu_opt_get(opts, "guest"); break; case QEMU_OPTION_prom_env: if (nb_prom_envs >= MAX_PROM_ENVS) { @@ -3646,8 +3688,7 @@ void qemu_init(int argc, char **argv, char **envp) xen_domid_restrict = true; break; case QEMU_OPTION_trace: - g_free(trace_file); - trace_file = trace_opt_parse(optarg); + trace_opt_parse(optarg); break; case QEMU_OPTION_plugin: qemu_plugin_opt_parse(optarg, &plugin_list); @@ -3663,7 +3704,11 @@ void qemu_init(int argc, char **argv, char **envp) break; } case QEMU_OPTION_spice: - olist = qemu_find_opts("spice"); + olist = qemu_find_opts_err("spice", NULL); + if (!olist) { + ui_module_load_one("spice-core"); + olist = qemu_find_opts("spice"); + } if (!olist) { error_report("spice support is disabled"); exit(1); @@ -3832,17 +3877,7 @@ void qemu_init(int argc, char **argv, char **envp) machine_class); os_daemonize(); - - /* - * If QTest is enabled, keep the rcu_atfork enabled, since system processes - * may be forked testing purposes (e.g. fork-server based fuzzing) The fork - * should happen before a signle cpu instruction is executed, to prevent - * deadlocks. See commit 73c6e40, rcu: "completely disable pthread_atfork - * callbacks as soon as possible" - */ - if (!qtest_enabled()) { - rcu_disable_atfork(); - } + rcu_disable_atfork(); if (pid_file && !qemu_write_pidfile(pid_file, &err)) { error_reportf_err(err, "cannot create PID file: "); @@ -3903,7 +3938,7 @@ void qemu_init(int argc, char **argv, char **envp) if (!trace_init_backends()) { exit(1); } - trace_init_file(trace_file); + trace_init_file(); /* Open the logfile at this point and set the log mask if necessary. */ @@ -3923,17 +3958,12 @@ void qemu_init(int argc, char **argv, char **envp) /* add configured firmware directories */ dirs = g_strsplit(CONFIG_QEMU_FIRMWAREPATH, G_SEARCHPATH_SEPARATOR_S, 0); for (i = 0; dirs[i] != NULL; i++) { - qemu_add_data_dir(dirs[i]); + qemu_add_data_dir(get_relocated_path(dirs[i])); } g_strfreev(dirs); /* try to find datadir relative to the executable path */ - dir = os_find_datadir(); - qemu_add_data_dir(dir); - g_free(dir); - - /* add the datadir specified when building */ - qemu_add_data_dir(CONFIG_QEMU_DATADIR); + qemu_add_data_dir(find_datadir()); /* -L help lists the data directories and exits. */ if (list_data_dirs) { @@ -3943,18 +3973,6 @@ void qemu_init(int argc, char **argv, char **envp) exit(0); } - /* machine_class: default to UP */ - machine_class->max_cpus = machine_class->max_cpus ?: 1; - machine_class->min_cpus = machine_class->min_cpus ?: 1; - machine_class->default_cpus = machine_class->default_cpus ?: 1; - - /* default to machine_class->default_cpus */ - current_machine->smp.cpus = machine_class->default_cpus; - current_machine->smp.max_cpus = machine_class->default_cpus; - current_machine->smp.cores = 1; - current_machine->smp.threads = 1; - current_machine->smp.sockets = 1; - machine_class->smp_parse(current_machine, qemu_opts_find(qemu_find_opts("smp-opts"), NULL)); @@ -4121,10 +4139,13 @@ void qemu_init(int argc, char **argv, char **envp) user_creatable_add_opts_foreach, object_create_initial, &error_fatal); + /* spice needs the timers to be initialized by this point */ + /* spice must initialize before audio as it changes the default auiodev */ + /* spice must initialize before chardevs (for spicevmc and spiceport) */ + qemu_spice.init(); + qemu_opts_foreach(qemu_find_opts("chardev"), chardev_init_func, NULL, &error_fatal); - /* now chardevs have been created we may have semihosting to connect */ - qemu_semihosting_connect_chardevs(); #ifdef CONFIG_VIRTFS qemu_opts_foreach(qemu_find_opts("fsdev"), @@ -4132,11 +4153,12 @@ void qemu_init(int argc, char **argv, char **envp) #endif /* - * Note: we need to create block backends before + * Note: we need to create audio and block backends before * machine_set_property(), so machine properties can refer to * them. */ configure_blockdev(&bdo_queue, machine_class, snapshot); + audio_init_audiodevs(); machine_opts = qemu_get_machine_opts(); qemu_opt_foreach(machine_opts, machine_set_property, current_machine, @@ -4230,10 +4252,8 @@ void qemu_init(int argc, char **argv, char **envp) semihosting_arg_fallback(kernel_filename, kernel_cmdline); } - /* spice needs the timers to be initialized by this point */ - qemu_spice_init(); - - cpu_ticks_init(); + /* initialize cpu timers and VCPU throttle modules */ + cpu_timers_init(); if (default_net) { QemuOptsList *net = qemu_find_opts("net"); @@ -4252,7 +4272,9 @@ void qemu_init(int argc, char **argv, char **envp) user_creatable_add_opts_foreach, object_create_delayed, &error_fatal); - tpm_init(); + if (tpm_init() < 0) { + exit(1); + } blk_mig_init(); ram_mig_init(); @@ -4261,9 +4283,6 @@ void qemu_init(int argc, char **argv, char **envp) qemu_opts_foreach(qemu_find_opts("mon"), mon_init_func, NULL, &error_fatal); - /* connect semihosting console input if requested */ - qemu_semihosting_console_init(); - if (foreach_device_config(DEV_SERIAL, serial_parse) < 0) exit(1); if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0) @@ -4271,6 +4290,10 @@ void qemu_init(int argc, char **argv, char **envp) if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0) exit(1); + /* now chardevs have been created we may have semihosting to connect */ + qemu_semihosting_connect_chardevs(); + qemu_semihosting_console_init(); + /* If no default VGA is requested, the default is "none". */ if (default_vga) { vga_model = get_default_vga_model(machine_class); @@ -4334,18 +4357,25 @@ void qemu_init(int argc, char **argv, char **envp) parse_numa_opts(current_machine); + /* do monitor/qmp handling at preconfig state if requested */ + qemu_main_loop(); + if (machine_class->default_ram_id && current_machine->ram_size && numa_uses_legacy_mem() && !current_machine->ram_memdev_id) { create_default_memdev(current_machine, mem_path); } - /* do monitor/qmp handling at preconfig state if requested */ - qemu_main_loop(); - - audio_init_audiodevs(); /* from here on runstate is RUN_STATE_PRELAUNCH */ machine_run_board_init(current_machine); + /* + * TODO To drop support for deprecated bogus if=..., move + * drive_check_orphaned() here, replacing this call. Also drop + * its deprecation warning, along with DriveInfo member + * @claimed_by_board. + */ + drive_mark_claimed_by_board(); + realtime_init(); soundhw_init(); @@ -4406,7 +4436,7 @@ void qemu_init(int argc, char **argv, char **envp) #endif if (using_spice) { - qemu_spice_display_init(); + qemu_spice.display_init(); } if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { diff --git a/storage-daemon/Makefile.objs b/storage-daemon/Makefile.objs deleted file mode 100644 index cfe6beee523ec802a1bff0eb0810a99dffd01723..0000000000000000000000000000000000000000 --- a/storage-daemon/Makefile.objs +++ /dev/null @@ -1 +0,0 @@ -storage-daemon-obj-y += qapi/ diff --git a/storage-daemon/meson.build b/storage-daemon/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..c5adce81c3a63741f76dc55f40bb4e180f30a120 --- /dev/null +++ b/storage-daemon/meson.build @@ -0,0 +1,13 @@ +qsd_ss = ss.source_set() +qsd_ss.add(files('qemu-storage-daemon.c')) +qsd_ss.add(blockdev, chardev, qmp, qom, qemuutil) + +subdir('qapi') + +if have_tools + qsd_ss = qsd_ss.apply(config_host, strict: false) + executable('qemu-storage-daemon', + qsd_ss.sources(), + dependencies: qsd_ss.dependencies(), + install: true) +endif diff --git a/storage-daemon/qapi/Makefile.objs b/storage-daemon/qapi/Makefile.objs deleted file mode 100644 index 8a4b220c968613c7e455506f8204c40ccd1f226e..0000000000000000000000000000000000000000 --- a/storage-daemon/qapi/Makefile.objs +++ /dev/null @@ -1 +0,0 @@ -storage-daemon-obj-y += qapi-commands.o qapi-init-commands.o qapi-introspect.o diff --git a/storage-daemon/qapi/meson.build b/storage-daemon/qapi/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..cd064ac5780b5030c27c29f361a38a6ceb5d28fd --- /dev/null +++ b/storage-daemon/qapi/meson.build @@ -0,0 +1,7 @@ +qsd_qapi_files = custom_target('QAPI files for qemu-storage-daemon', + output: qapi_nonmodule_outputs, + input: [ files('qapi-schema.json') ], + command: [ qapi_gen, '-o', 'storage-daemon/qapi', '@INPUT@' ], + depend_files: [ qapi_inputs, qapi_gen_depends ]) + +qsd_ss.add(qsd_qapi_files.to_list()) diff --git a/storage-daemon/qapi/qapi-schema.json b/storage-daemon/qapi/qapi-schema.json index 14f4f8fe61195608da823e937babb248bf78f894..c6ad5ae1e397fe966c260387b70cd077616bec70 100644 --- a/storage-daemon/qapi/qapi-schema.json +++ b/storage-daemon/qapi/qapi-schema.json @@ -1,4 +1,5 @@ # -*- Mode: Python -*- +# vim: filetype=python # Note that modules are shared with the QEMU main schema under the assumption # that the storage daemon schema is a subset of the main schema. For the shared @@ -15,6 +16,7 @@ { 'include': '../../qapi/pragma.json' } { 'include': '../../qapi/block-core.json' } +{ 'include': '../../qapi/block-export.json' } { 'include': '../../qapi/char.json' } { 'include': '../../qapi/common.json' } { 'include': '../../qapi/control.json' } diff --git a/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c similarity index 87% rename from qemu-storage-daemon.c rename to storage-daemon/qemu-storage-daemon.c index 9e7adfe3a6389cc245114061ef8697483539aaf0..7c914b0dc1f851d6b6e72afd296c1a3be7c0c97a 100644 --- a/qemu-storage-daemon.c +++ b/storage-daemon/qemu-storage-daemon.c @@ -35,8 +35,8 @@ #include "monitor/monitor-internal.h" #include "qapi/error.h" -#include "qapi/qapi-visit-block.h" #include "qapi/qapi-visit-block-core.h" +#include "qapi/qapi-visit-block-export.h" #include "qapi/qapi-visit-control.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qstring.h" @@ -92,7 +92,7 @@ static void help(void) " --chardev configure a character device backend\n" " (see the qemu(1) man page for possible options)\n" "\n" -" --export [type=]nbd,device=[,name=]\n" +" --export [type=]nbd,id=,node-name=[,name=]\n" " [,writable=on|off][,bitmap=]\n" " export the specified block node over NBD\n" " (requires --nbd-server)\n" @@ -101,9 +101,9 @@ static void help(void) " configure a QMP monitor\n" "\n" " --nbd-server addr.type=inet,addr.host=,addr.port=\n" -" [,tls-creds=][,tls-authz=]\n" +" [,tls-creds=][,tls-authz=][,max-connections=]\n" " --nbd-server addr.type=unix,addr.path=\n" -" [,tls-creds=][,tls-authz=]\n" +" [,tls-creds=][,tls-authz=][,max-connections=]\n" " start an NBD server for exporting block nodes\n" "\n" " --object help list object types that can be added\n" @@ -150,17 +150,6 @@ static void init_qmp_commands(void) qmp_marshal_qmp_capabilities, QCO_ALLOW_PRECONFIG); } -static void init_export(BlockExport *export, Error **errp) -{ - switch (export->type) { - case BLOCK_EXPORT_TYPE_NBD: - qmp_nbd_server_add(&export->u.nbd, errp); - break; - default: - g_assert_not_reached(); - } -} - static void process_options(int argc, char *argv[]) { int c; @@ -191,12 +180,9 @@ static void process_options(int argc, char *argv[]) help(); exit(EXIT_SUCCESS); case 'T': - { - char *trace_file = trace_opt_parse(optarg); - trace_init_file(trace_file); - g_free(trace_file); - break; - } + trace_opt_parse(optarg); + trace_init_file(); + break; case 'V': printf("qemu-storage-daemon version " QEMU_FULL_VERSION "\n" QEMU_COPYRIGHT "\n"); @@ -235,14 +221,14 @@ static void process_options(int argc, char *argv[]) case OPTION_EXPORT: { Visitor *v; - BlockExport *export; + BlockExportOptions *export; v = qobject_input_visitor_new_str(optarg, "type", &error_fatal); - visit_type_BlockExport(v, NULL, &export, &error_fatal); + visit_type_BlockExportOptions(v, NULL, &export, &error_fatal); visit_free(v); - init_export(export, &error_fatal); - qapi_free_BlockExport(export); + qmp_block_export_add(export, &error_fatal); + qapi_free_BlockExportOptions(export); break; } case OPTION_MONITOR: @@ -275,21 +261,14 @@ static void process_options(int argc, char *argv[]) } case OPTION_OBJECT: { - QemuOpts *opts; - const char *type; QDict *args; + bool help; - /* FIXME The keyval parser rejects 'help' arguments, so we must - * unconditionall try QemuOpts first. */ - opts = qemu_opts_parse(&qemu_object_opts, - optarg, true, &error_fatal); - type = qemu_opt_get(opts, "qom-type"); - if (type && user_creatable_print_help(type, opts)) { + args = keyval_parse(optarg, "qom-type", &help, &error_fatal); + if (help) { + user_creatable_print_help_from_qdict(args); exit(EXIT_SUCCESS); } - qemu_opts_del(opts); - - args = keyval_parse(optarg, "qom-type", &error_fatal); user_creatable_add_dict(args, true, &error_fatal); qobject_unref(args); break; @@ -316,6 +295,7 @@ int main(int argc, char *argv[]) module_call_init(MODULE_INIT_QOM); module_call_init(MODULE_INIT_TRACE); + qemu_add_opts(&qemu_object_opts); qemu_add_opts(&qemu_trace_opts); qcrypto_init(&error_fatal); bdrv_init(); @@ -334,5 +314,9 @@ int main(int argc, char *argv[]) main_loop_wait(false); } + monitor_cleanup(); + qemu_chr_cleanup(); + user_creatable_cleanup(); + return EXIT_SUCCESS; } diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs deleted file mode 100644 index 6a9e3135e8f90d9f0504713d2720ef8035e7d442..0000000000000000000000000000000000000000 --- a/stubs/Makefile.objs +++ /dev/null @@ -1,47 +0,0 @@ -stub-obj-y += arch_type.o -stub-obj-y += bdrv-next-monitor-owned.o -stub-obj-y += blk-commit-all.o -stub-obj-y += blockdev-close-all-bdrv-states.o -stub-obj-y += clock-warp.o -stub-obj-y += cpu-get-clock.o -stub-obj-y += cpu-get-icount.o -stub-obj-y += dump.o -stub-obj-y += error-printf.o -stub-obj-y += fdset.o -stub-obj-y += gdbstub.o -stub-obj-y += get-vm-name.o -stub-obj-y += iothread.o -stub-obj-y += iothread-lock.o -stub-obj-y += is-daemonized.o -stub-obj-$(CONFIG_LINUX_AIO) += linux-aio.o -stub-obj-$(CONFIG_LINUX_IO_URING) += io_uring.o -stub-obj-y += machine-init-done.o -stub-obj-y += migr-blocker.o -stub-obj-y += change-state-handler.o -stub-obj-y += monitor.o -stub-obj-y += monitor-core.o -stub-obj-y += notify-event.o -stub-obj-y += qtest.o -stub-obj-y += replay.o -stub-obj-y += replay-user.o -stub-obj-y += runstate-check.o -stub-obj-y += set-fd-handler.o -stub-obj-y += sysbus.o -stub-obj-y += tpm.o -stub-obj-y += trace-control.o -stub-obj-y += uuid.o -stub-obj-y += vm-stop.o -stub-obj-y += vmstate.o -stub-obj-y += win32-kbd-hook.o -stub-obj-y += fd-register.o -stub-obj-y += qmp_memory_device.o -stub-obj-y += target-monitor-defs.o -stub-obj-y += target-get-monitor-def.o -stub-obj-y += vmgenid.o -stub-obj-y += xen-common.o -stub-obj-y += xen-hvm.o -stub-obj-y += pci-host-piix.o -stub-obj-y += ram-block.o -stub-obj-y += ramfb.o -stub-obj-y += fw_cfg.o -stub-obj-$(CONFIG_SOFTMMU) += semihost.o diff --git a/stubs/blk-exp-close-all.c b/stubs/blk-exp-close-all.c new file mode 100644 index 0000000000000000000000000000000000000000..1c713167639274cefa7dd85bbc69e56777ac3fe9 --- /dev/null +++ b/stubs/blk-exp-close-all.c @@ -0,0 +1,7 @@ +#include "qemu/osdep.h" +#include "block/export.h" + +/* Only used in programs that support block exports (libblockdev.fa) */ +void blk_exp_close_all(void) +{ +} diff --git a/stubs/clock-warp.c b/stubs/clock-warp.c deleted file mode 100644 index b53e5dd94c022a50451dfd87429c175097266a99..0000000000000000000000000000000000000000 --- a/stubs/clock-warp.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "qemu/osdep.h" -#include "qemu/timer.h" - -void qemu_start_warp_timer(void) -{ -} - diff --git a/stubs/cmos.c b/stubs/cmos.c new file mode 100644 index 0000000000000000000000000000000000000000..3fdbae2c69e88b5dfa457a8d1f8b676783038a29 --- /dev/null +++ b/stubs/cmos.c @@ -0,0 +1,7 @@ +#include "qemu/osdep.h" +#include "hw/block/fdc.h" + +int cmos_get_fd_drive_type(FloppyDriveType fd0) +{ + return 0; +} diff --git a/stubs/cpu-get-clock.c b/stubs/cpu-get-clock.c index 5a92810e87e6444f6fd74c3fe64872d7413f34c8..9e92404816901120e1b36d47f62e4065c8b5c34a 100644 --- a/stubs/cpu-get-clock.c +++ b/stubs/cpu-get-clock.c @@ -1,5 +1,6 @@ #include "qemu/osdep.h" -#include "qemu/timer.h" +#include "sysemu/cpu-timers.h" +#include "qemu/main-loop.h" int64_t cpu_get_clock(void) { diff --git a/stubs/cpu-synchronize-state.c b/stubs/cpu-synchronize-state.c new file mode 100644 index 0000000000000000000000000000000000000000..d9211da66cea09e4e30d378fa6ed520b268dd445 --- /dev/null +++ b/stubs/cpu-synchronize-state.c @@ -0,0 +1,9 @@ +#include "qemu/osdep.h" +#include "sysemu/hw_accel.h" + +void cpu_synchronize_state(CPUState *cpu) +{ +} +void cpu_synchronize_post_init(CPUState *cpu) +{ +} diff --git a/stubs/fd-register.c b/stubs/cpus-get-virtual-clock.c similarity index 37% rename from stubs/fd-register.c rename to stubs/cpus-get-virtual-clock.c index 63a4abdb20dc5aaf9cffd1b5f15b78a31124c726..fd447d53f3c47c1ce8e38b95db913cd6f2f51447 100644 --- a/stubs/fd-register.c +++ b/stubs/cpus-get-virtual-clock.c @@ -1,6 +1,8 @@ #include "qemu/osdep.h" +#include "sysemu/cpu-timers.h" #include "qemu/main-loop.h" -void qemu_fd_register(int fd) +int64_t cpus_get_virtual_clock(void) { + return cpu_get_clock(); } diff --git a/stubs/fdset.c b/stubs/fdset.c index 67dd5e1d347cac5567a9812242081b71b8e1f80b..56b3663d588d35d08eabaa7312624848a751b023 100644 --- a/stubs/fdset.c +++ b/stubs/fdset.c @@ -1,8 +1,9 @@ #include "qemu/osdep.h" #include "monitor/monitor.h" -int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd) +int monitor_fdset_dup_fd_add(int64_t fdset_id, int flags) { + errno = ENOSYS; return -1; } @@ -11,11 +12,6 @@ int64_t monitor_fdset_dup_fd_find(int dup_fd) return -1; } -int monitor_fdset_get_fd(int64_t fdset_id, int flags) -{ - return -ENOENT; -} - void monitor_fdset_dup_fd_remove(int dupfd) { } diff --git a/stubs/icount.c b/stubs/icount.c new file mode 100644 index 0000000000000000000000000000000000000000..f13c43568bceca6a8bb1b3982da5c7078c6744ed --- /dev/null +++ b/stubs/icount.c @@ -0,0 +1,45 @@ +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "sysemu/cpu-timers.h" + +/* icount - Instruction Counter API */ + +int use_icount; + +void icount_update(CPUState *cpu) +{ + abort(); +} +void icount_configure(QemuOpts *opts, Error **errp) +{ + /* signal error */ + error_setg(errp, "cannot configure icount, TCG support not available"); +} +int64_t icount_get_raw(void) +{ + abort(); + return 0; +} +int64_t icount_get(void) +{ + abort(); + return 0; +} +int64_t icount_to_ns(int64_t icount) +{ + abort(); + return 0; +} +int64_t icount_round(int64_t count) +{ + abort(); + return 0; +} +void icount_start_warp_timer(void) +{ + abort(); +} +void icount_account_warp_timer(void) +{ + abort(); +} diff --git a/stubs/isa-bus.c b/stubs/isa-bus.c new file mode 100644 index 0000000000000000000000000000000000000000..522f448997d4322444835a47b6fe6c8dd4a86366 --- /dev/null +++ b/stubs/isa-bus.c @@ -0,0 +1,7 @@ +#include "qemu/osdep.h" +#include "hw/isa/isa.h" + +ISADevice *isa_create_simple(ISABus *bus, const char *name) +{ + g_assert_not_reached(); +} diff --git a/stubs/meson.build b/stubs/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..82b7ba60abe54bfe0e3069ac17c238eaed76fb38 --- /dev/null +++ b/stubs/meson.build @@ -0,0 +1,55 @@ +stub_ss.add(files('arch_type.c')) +stub_ss.add(files('bdrv-next-monitor-owned.c')) +stub_ss.add(files('blk-commit-all.c')) +stub_ss.add(files('blk-exp-close-all.c')) +stub_ss.add(files('blockdev-close-all-bdrv-states.c')) +stub_ss.add(files('change-state-handler.c')) +stub_ss.add(files('cmos.c')) +stub_ss.add(files('cpu-get-clock.c')) +stub_ss.add(files('cpus-get-virtual-clock.c')) +stub_ss.add(files('qemu-timer-notify-cb.c')) +stub_ss.add(files('icount.c')) +stub_ss.add(files('dump.c')) +stub_ss.add(files('error-printf.c')) +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')) +stub_ss.add(files('iothread.c')) +stub_ss.add(files('iothread-lock.c')) +stub_ss.add(files('isa-bus.c')) +stub_ss.add(files('is-daemonized.c')) +stub_ss.add(when: 'CONFIG_LINUX_AIO', if_true: files('linux-aio.c')) +stub_ss.add(files('machine-init-done.c')) +stub_ss.add(files('migr-blocker.c')) +stub_ss.add(files('monitor.c')) +stub_ss.add(files('monitor-core.c')) +stub_ss.add(files('pci-bus.c')) +stub_ss.add(files('pci-host-piix.c')) +stub_ss.add(files('qemu-timer-notify-cb.c')) +stub_ss.add(files('qmp_memory_device.c')) +stub_ss.add(files('qtest.c')) +stub_ss.add(files('ram-block.c')) +stub_ss.add(files('ramfb.c')) +stub_ss.add(files('replay.c')) +stub_ss.add(files('runstate-check.c')) +stub_ss.add(files('set-fd-handler.c')) +stub_ss.add(files('sysbus.c')) +stub_ss.add(files('target-get-monitor-def.c')) +stub_ss.add(files('target-monitor-defs.c')) +stub_ss.add(files('tpm.c')) +stub_ss.add(files('trace-control.c')) +stub_ss.add(files('uuid.c')) +stub_ss.add(files('vmgenid.c')) +stub_ss.add(files('vmstate.c')) +stub_ss.add(files('vm-stop.c')) +stub_ss.add(files('win32-kbd-hook.c')) +stub_ss.add(files('cpu-synchronize-state.c')) +if have_block + stub_ss.add(files('replay-tools.c')) +endif +if have_system + stub_ss.add(files('semihost.c')) + stub_ss.add(files('xen-hw-stub.c')) +endif diff --git a/stubs/monitor-core.c b/stubs/monitor-core.c index 6cff1c4e1dd58d9f14389021001cffcbec802262..d058a2a00d85e36274b2d33c14c1940b9605f22e 100644 --- a/stubs/monitor-core.c +++ b/stubs/monitor-core.c @@ -3,7 +3,15 @@ #include "qemu-common.h" #include "qapi/qapi-emit-events.h" -__thread Monitor *cur_mon; +Monitor *monitor_cur(void) +{ + return NULL; +} + +Monitor *monitor_set_cur(Coroutine *co, Monitor *mon) +{ + return NULL; +} void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp) { diff --git a/stubs/notify-event.c b/stubs/notify-event.c deleted file mode 100644 index 827bb52d1a13c120cc23049bae8e2735e64ab50f..0000000000000000000000000000000000000000 --- a/stubs/notify-event.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "qemu/osdep.h" -#include "qemu/main-loop.h" - -void qemu_notify_event(void) -{ -} diff --git a/stubs/pci-bus.c b/stubs/pci-bus.c new file mode 100644 index 0000000000000000000000000000000000000000..a8932fa93250e3ac87ec53d5ce51e6bb7b03e875 --- /dev/null +++ b/stubs/pci-bus.c @@ -0,0 +1,7 @@ +#include "qemu/osdep.h" +#include "hw/pci/pci.h" + +PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name) +{ + g_assert_not_reached(); +} diff --git a/stubs/cpu-get-icount.c b/stubs/qemu-timer-notify-cb.c similarity index 46% rename from stubs/cpu-get-icount.c rename to stubs/qemu-timer-notify-cb.c index b35f84463861d20cd433208b7918394642d918cd..845e46f8e039e23f3e3aabe1e1d9b357a055667e 100644 --- a/stubs/cpu-get-icount.c +++ b/stubs/qemu-timer-notify-cb.c @@ -1,20 +1,7 @@ #include "qemu/osdep.h" -#include "qemu/timer.h" -#include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" #include "qemu/main-loop.h" -int use_icount; - -int64_t cpu_get_icount(void) -{ - abort(); -} - -int64_t cpu_get_icount_raw(void) -{ - abort(); -} - void qemu_timer_notify_cb(void *opaque, QEMUClockType type) { qemu_notify_event(); diff --git a/stubs/qmp_memory_device.c b/stubs/qmp_memory_device.c index 85ff8f2d7eedc2e06b2f37d9f6106f40c2978261..e75cac62dc6f59b96c57f3b756eb3a8d70b68e53 100644 --- a/stubs/qmp_memory_device.c +++ b/stubs/qmp_memory_device.c @@ -1,5 +1,4 @@ #include "qemu/osdep.h" -#include "qom/object.h" #include "hw/mem/memory-device.h" MemoryDeviceInfoList *qmp_memory_device_list(void) diff --git a/stubs/qtest.c b/stubs/qtest.c index 891eb954fbeead7ce295c39ad34bd88a75f0d3d4..4666a49d7d1d6919343596045e5c891ef29cdd9c 100644 --- a/stubs/qtest.c +++ b/stubs/qtest.c @@ -18,3 +18,8 @@ bool qtest_driver(void) { return false; } + +int64_t qtest_get_virtual_clock(void) +{ + return 0; +} diff --git a/stubs/ram-block.c b/stubs/ram-block.c index 73c0a3ee089fc9c902cde2027fd2e42213ab1012..108197683bb3c006b1e6318f782a50b1e6374a01 100644 --- a/stubs/ram-block.c +++ b/stubs/ram-block.c @@ -1,6 +1,7 @@ #include "qemu/osdep.h" #include "exec/ramlist.h" #include "exec/cpu-common.h" +#include "exec/memory.h" void *qemu_ram_get_host_addr(RAMBlock *rb) { @@ -29,3 +30,8 @@ int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque) { return 0; } + +int ram_block_discard_disable(bool state) +{ + return 0; +} diff --git a/stubs/replay-tools.c b/stubs/replay-tools.c new file mode 100644 index 0000000000000000000000000000000000000000..c06b360e2224cd2a7b65faebff634011cd38afbd --- /dev/null +++ b/stubs/replay-tools.c @@ -0,0 +1,83 @@ +#include "qemu/osdep.h" +#include "sysemu/replay.h" +#include "block/aio.h" + +bool replay_events_enabled(void) +{ + return false; +} + +int64_t replay_save_clock(unsigned int kind, int64_t clock, int64_t raw_icount) +{ + abort(); + return 0; +} + +int64_t replay_read_clock(unsigned int kind) +{ + abort(); + return 0; +} + +uint64_t replay_get_current_icount(void) +{ + return 0; +} + +void replay_bh_schedule_event(QEMUBH *bh) +{ + qemu_bh_schedule(bh); +} + +void replay_bh_schedule_oneshot_event(AioContext *ctx, + QEMUBHFunc *cb, void *opaque) +{ + aio_bh_schedule_oneshot(ctx, cb, opaque); +} + +bool replay_checkpoint(ReplayCheckpoint checkpoint) +{ + return true; +} + +void replay_mutex_lock(void) +{ +} + +void replay_mutex_unlock(void) +{ +} + +void replay_register_char_driver(Chardev *chr) +{ +} + +void replay_chr_be_write(Chardev *s, uint8_t *buf, int len) +{ + abort(); +} + +void replay_char_write_event_save(int res, int offset) +{ + abort(); +} + +void replay_char_write_event_load(int *res, int *offset) +{ + abort(); +} + +int replay_char_read_all_load(uint8_t *buf) +{ + abort(); +} + +void replay_char_read_all_save_error(int res) +{ + abort(); +} + +void replay_char_read_all_save_buf(uint8_t *buf, int offset) +{ + abort(); +} diff --git a/stubs/replay-user.c b/stubs/replay-user.c deleted file mode 100644 index 2ad9e272037ae246ca09ca8ad545a9f06e29dfa7..0000000000000000000000000000000000000000 --- a/stubs/replay-user.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "qemu/osdep.h" -#include "sysemu/replay.h" -#include "sysemu/sysemu.h" - -void replay_bh_schedule_oneshot_event(AioContext *ctx, - QEMUBHFunc *cb, void *opaque) -{ - aio_bh_schedule_oneshot(ctx, cb, opaque); -} diff --git a/stubs/replay.c b/stubs/replay.c index 5974ec1f50e60f40fc90b12de6537460045b9cbd..9d5b4be339b5aef7d62dac7fc53ee6afc017d26c 100644 --- a/stubs/replay.c +++ b/stubs/replay.c @@ -3,88 +3,25 @@ ReplayMode replay_mode; -int64_t replay_save_clock(unsigned int kind, int64_t clock, int64_t raw_icount) -{ - abort(); - return 0; -} - -int64_t replay_read_clock(unsigned int kind) -{ - abort(); - return 0; -} - -bool replay_checkpoint(ReplayCheckpoint checkpoint) -{ - return true; -} - -bool replay_events_enabled(void) -{ - return false; -} - void replay_finish(void) { } -void replay_register_char_driver(Chardev *chr) -{ -} - -void replay_chr_be_write(Chardev *s, uint8_t *buf, int len) -{ - abort(); -} - -void replay_char_write_event_save(int res, int offset) -{ - abort(); -} - -void replay_char_write_event_load(int *res, int *offset) -{ - abort(); -} - -int replay_char_read_all_load(uint8_t *buf) -{ - abort(); -} - -void replay_char_read_all_save_error(int res) -{ - abort(); -} - -void replay_char_read_all_save_buf(uint8_t *buf, int offset) -{ - abort(); -} - -void replay_block_event(QEMUBH *bh, uint64_t id) +void replay_save_random(int ret, void *buf, size_t len) { } -uint64_t blkreplay_next_id(void) +int replay_read_random(void *buf, size_t len) { return 0; } -void replay_mutex_lock(void) -{ -} - -void replay_mutex_unlock(void) -{ -} - -void replay_save_random(int ret, void *buf, size_t len) +bool replay_reverse_step(void) { + return false; } -int replay_read_random(void *buf, size_t len) +bool replay_reverse_continue(void) { - return 0; + return false; } diff --git a/stubs/tpm.c b/stubs/tpm.c index 66c99d667dd68287b721a08d5dc6b5923f6d65d1..9bded191d9d0e47d3a90e73b48bc3259827d162d 100644 --- a/stubs/tpm.c +++ b/stubs/tpm.c @@ -10,8 +10,9 @@ #include "sysemu/tpm.h" #include "hw/acpi/tpm.h" -void tpm_init(void) +int tpm_init(void) { + return 0; } void tpm_cleanup(void) diff --git a/stubs/uuid.c b/stubs/uuid.c index 67f182fa3aa07dc6583d2b0aba213360c1e41945..e5112eb3f60470e2c5f1581715ab229cb2b1ca45 100644 --- a/stubs/uuid.c +++ b/stubs/uuid.c @@ -1,5 +1,5 @@ #include "qemu/osdep.h" -#include "qapi/qapi-commands-misc.h" +#include "qapi/qapi-commands-machine.h" #include "qemu/uuid.h" UuidInfo *qmp_query_uuid(Error **errp) diff --git a/stubs/vmgenid.c b/stubs/vmgenid.c index 568e42b0648c8e3a3cffa6f2f4972ef1679c2bd6..bfad656c6ccfbbd9b1baba8fb5587135c5536a68 100644 --- a/stubs/vmgenid.c +++ b/stubs/vmgenid.c @@ -1,6 +1,6 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "qapi/qapi-commands-misc.h" +#include "qapi/qapi-commands-machine.h" #include "qapi/qmp/qerror.h" GuidInfo *qmp_query_vm_generation_id(Error **errp) diff --git a/stubs/xen-hvm.c b/stubs/xen-hw-stub.c similarity index 49% rename from stubs/xen-hvm.c rename to stubs/xen-hw-stub.c index b7d53b5e2f2cc83a017c8907b11abb9f897569a5..15f3921a76b05b90f953b3e4ecc8095322245efb 100644 --- a/stubs/xen-hvm.c +++ b/stubs/xen-hw-stub.c @@ -1,17 +1,14 @@ /* - * Copyright (C) 2010 Citrix Ltd. + * Copyright (C) 2014 Citrix Systems UK Ltd. * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. + * 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/xen/xen.h" -#include "exec/memory.h" -#include "qapi/qapi-commands-misc.h" +#include "hw/xen/xen-x86.h" int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) { @@ -35,11 +32,6 @@ int xen_is_pirq_msi(uint32_t msi_data) return 0; } -void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr, - Error **errp) -{ -} - qemu_irq *xen_interrupt_controller_init(void) { return NULL; @@ -49,14 +41,6 @@ void xen_register_framebuffer(MemoryRegion *mr) { } -void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length) -{ -} - -void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory) -{ -} - -void qmp_xen_set_global_dirty_log(bool enable, Error **errp) +void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion **ram_memory) { } diff --git a/target/alpha/Makefile.objs b/target/alpha/Makefile.objs deleted file mode 100644 index 63664629f6d9ebd56f327b1cf9d0a12a7a07ec32..0000000000000000000000000000000000000000 --- a/target/alpha/Makefile.objs +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_SOFTMMU) += machine.o -obj-y += translate.o helper.o cpu.o -obj-y += int_helper.o fpu_helper.o vax_helper.o sys_helper.o mem_helper.o -obj-y += gdbstub.o diff --git a/target/alpha/cpu-qom.h b/target/alpha/cpu-qom.h index 08832fa7672cdbf6607d06a2231b050ab17eacb1..7bb9173c57feb58f03f0a5f0db3e03cb79080c17 100644 --- a/target/alpha/cpu-qom.h +++ b/target/alpha/cpu-qom.h @@ -21,15 +21,12 @@ #define QEMU_ALPHA_CPU_QOM_H #include "hw/core/cpu.h" +#include "qom/object.h" #define TYPE_ALPHA_CPU "alpha-cpu" -#define ALPHA_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(AlphaCPUClass, (klass), TYPE_ALPHA_CPU) -#define ALPHA_CPU(obj) \ - OBJECT_CHECK(AlphaCPU, (obj), TYPE_ALPHA_CPU) -#define ALPHA_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(AlphaCPUClass, (obj), TYPE_ALPHA_CPU) +OBJECT_DECLARE_TYPE(AlphaCPU, AlphaCPUClass, + ALPHA_CPU) /** * AlphaCPUClass: @@ -38,15 +35,14 @@ * * An Alpha CPU model. */ -typedef struct AlphaCPUClass { +struct AlphaCPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ DeviceRealize parent_realize; DeviceReset parent_reset; -} AlphaCPUClass; +}; -typedef struct AlphaCPU AlphaCPU; #endif diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h index be29bdd53011ecc1b1572765a58f9be668e633c4..82df108967bec0951ebe6510c75821bbd9b29084 100644 --- a/target/alpha/cpu.h +++ b/target/alpha/cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/alpha/fpu_helper.c b/target/alpha/fpu_helper.c index df8b58963bad912d9cfb1b6622a942153adc7d79..3ff8bb456d390b3eac7d102c5742fbf5fd0e52c9 100644 --- a/target/alpha/fpu_helper.c +++ b/target/alpha/fpu_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/alpha/gdbstub.c b/target/alpha/gdbstub.c index 0cd76ddaa9e9c2df311eb0fc2cafcdd2bcabf7af..7db14f44312bdf193c73808388a3becc39a82367 100644 --- a/target/alpha/gdbstub.c +++ b/target/alpha/gdbstub.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/alpha/helper.c b/target/alpha/helper.c index 55d7274d946a92e9ed66f49546a9de9eb0a5ac1c..4f56fe4d2317acb4e2b516d2accb491ec5191e9f 100644 --- a/target/alpha/helper.c +++ b/target/alpha/helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/alpha/int_helper.c b/target/alpha/int_helper.c index e43b50a743565012b912f819f02f5c421e5a2b49..5672696f6f120c5f0e8fae3413ce91d1ffd8ae5b 100644 --- a/target/alpha/int_helper.c +++ b/target/alpha/int_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/alpha/mem_helper.c b/target/alpha/mem_helper.c index 934faa1d6fa6698f495fe6e1b9237fba735d8bb5..75e72bc3370f34763b03f2f31bb4e8668ab1b30a 100644 --- a/target/alpha/mem_helper.c +++ b/target/alpha/mem_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/alpha/meson.build b/target/alpha/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..1aec55abb4a7dac69e21a5d54aea1869b1c134ab --- /dev/null +++ b/target/alpha/meson.build @@ -0,0 +1,18 @@ +alpha_ss = ss.source_set() +alpha_ss.add(files( + 'cpu.c', + 'fpu_helper.c', + 'gdbstub.c', + 'helper.c', + 'int_helper.c', + 'mem_helper.c', + 'sys_helper.c', + 'translate.c', + 'vax_helper.c', +)) + +alpha_softmmu_ss = ss.source_set() +alpha_softmmu_ss.add(files('machine.c')) + +target_arch += {'alpha': alpha_ss} +target_softmmu_arch += {'alpha': alpha_softmmu_ss} diff --git a/target/alpha/sys_helper.c b/target/alpha/sys_helper.c index 39229236e1ef1eb1b509972a4a6b183561f5515d..25f6cb88940d9a8164d2edbc1904c66f4022a0e0 100644 --- a/target/alpha/sys_helper.c +++ b/target/alpha/sys_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/alpha/translate.c b/target/alpha/translate.c index 8870284f5742fd4576e174fad1d5a734b061729e..a02b4e70b70e6a2522412cadc620dfcc0023b6dc 100644 --- a/target/alpha/translate.c +++ b/target/alpha/translate.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "cpu.h" #include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" #include "disas/disas.h" #include "qemu/host-utils.h" #include "exec/exec-all.h" @@ -1329,7 +1330,7 @@ static DisasJumpType gen_mfpr(DisasContext *ctx, TCGv va, int regno) case 249: /* VMTIME */ helper = gen_helper_get_vmtime; do_helper: - if (use_icount) { + if (icount_enabled()) { gen_io_start(); helper(va); return DISAS_PC_STALE; diff --git a/target/alpha/vax_helper.c b/target/alpha/vax_helper.c index 2b0c17827438d637ecad63f79f9ee05d8c1ffbe7..f94fb519dbd86cf109cf7330606cebd5918a5f4f 100644 --- a/target/alpha/vax_helper.c +++ b/target/alpha/vax_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs deleted file mode 100644 index 83febd232c8a365b9217366439203dd0a5fbddfd..0000000000000000000000000000000000000000 --- a/target/arm/Makefile.objs +++ /dev/null @@ -1,88 +0,0 @@ -obj-$(CONFIG_TCG) += arm-semi.o -obj-y += helper.o vfp_helper.o -obj-y += cpu.o gdbstub.o -obj-$(TARGET_AARCH64) += cpu64.o gdbstub64.o - -obj-$(CONFIG_SOFTMMU) += machine.o arch_dump.o monitor.o -obj-$(CONFIG_SOFTMMU) += arm-powerctl.o - -obj-$(CONFIG_KVM) += kvm.o -obj-$(call land,$(CONFIG_KVM),$(call lnot,$(TARGET_AARCH64))) += kvm32.o -obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o -obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o - -DECODETREE = $(SRC_PATH)/scripts/decodetree.py - -target/arm/decode-sve.inc.c: $(SRC_PATH)/target/arm/sve.decode $(DECODETREE) - $(call quiet-command,\ - $(PYTHON) $(DECODETREE) --decode disas_sve -o $@ $<,\ - "GEN", $(TARGET_DIR)$@) - -target/arm/decode-neon-shared.inc.c: $(SRC_PATH)/target/arm/neon-shared.decode $(DECODETREE) - $(call quiet-command,\ - $(PYTHON) $(DECODETREE) --static-decode disas_neon_shared -o $@ $<,\ - "GEN", $(TARGET_DIR)$@) - -target/arm/decode-neon-dp.inc.c: $(SRC_PATH)/target/arm/neon-dp.decode $(DECODETREE) - $(call quiet-command,\ - $(PYTHON) $(DECODETREE) --static-decode disas_neon_dp -o $@ $<,\ - "GEN", $(TARGET_DIR)$@) - -target/arm/decode-neon-ls.inc.c: $(SRC_PATH)/target/arm/neon-ls.decode $(DECODETREE) - $(call quiet-command,\ - $(PYTHON) $(DECODETREE) --static-decode disas_neon_ls -o $@ $<,\ - "GEN", $(TARGET_DIR)$@) - -target/arm/decode-vfp.inc.c: $(SRC_PATH)/target/arm/vfp.decode $(DECODETREE) - $(call quiet-command,\ - $(PYTHON) $(DECODETREE) --static-decode disas_vfp -o $@ $<,\ - "GEN", $(TARGET_DIR)$@) - -target/arm/decode-vfp-uncond.inc.c: $(SRC_PATH)/target/arm/vfp-uncond.decode $(DECODETREE) - $(call quiet-command,\ - $(PYTHON) $(DECODETREE) --static-decode disas_vfp_uncond -o $@ $<,\ - "GEN", $(TARGET_DIR)$@) - -target/arm/decode-a32.inc.c: $(SRC_PATH)/target/arm/a32.decode $(DECODETREE) - $(call quiet-command,\ - $(PYTHON) $(DECODETREE) --static-decode disas_a32 -o $@ $<,\ - "GEN", $(TARGET_DIR)$@) - -target/arm/decode-a32-uncond.inc.c: $(SRC_PATH)/target/arm/a32-uncond.decode $(DECODETREE) - $(call quiet-command,\ - $(PYTHON) $(DECODETREE) --static-decode disas_a32_uncond -o $@ $<,\ - "GEN", $(TARGET_DIR)$@) - -target/arm/decode-t32.inc.c: $(SRC_PATH)/target/arm/t32.decode $(DECODETREE) - $(call quiet-command,\ - $(PYTHON) $(DECODETREE) --static-decode disas_t32 -o $@ $<,\ - "GEN", $(TARGET_DIR)$@) - -target/arm/decode-t16.inc.c: $(SRC_PATH)/target/arm/t16.decode $(DECODETREE) - $(call quiet-command,\ - $(PYTHON) $(DECODETREE) -w 16 --static-decode disas_t16 -o $@ $<,\ - "GEN", $(TARGET_DIR)$@) - -target/arm/translate-sve.o: target/arm/decode-sve.inc.c -target/arm/translate.o: target/arm/decode-neon-shared.inc.c -target/arm/translate.o: target/arm/decode-neon-dp.inc.c -target/arm/translate.o: target/arm/decode-neon-ls.inc.c -target/arm/translate.o: target/arm/decode-vfp.inc.c -target/arm/translate.o: target/arm/decode-vfp-uncond.inc.c -target/arm/translate.o: target/arm/decode-a32.inc.c -target/arm/translate.o: target/arm/decode-a32-uncond.inc.c -target/arm/translate.o: target/arm/decode-t32.inc.c -target/arm/translate.o: target/arm/decode-t16.inc.c - -obj-y += tlb_helper.o debug_helper.o -obj-y += translate.o op_helper.o -obj-y += crypto_helper.o -obj-y += iwmmxt_helper.o vec_helper.o neon_helper.o -obj-y += m_helper.o -obj-y += cpu_tcg.o - -obj-$(CONFIG_SOFTMMU) += psci.o - -obj-$(TARGET_AARCH64) += translate-a64.o helper-a64.o -obj-$(TARGET_AARCH64) += translate-sve.o sve_helper.o -obj-$(TARGET_AARCH64) += pauth_helper.o diff --git a/target/arm/a32-uncond.decode b/target/arm/a32-uncond.decode index 60ccfc598d39c881f6bbbf65f35f75636b494730..2339de2e943309e9ebd276cc455c547a28bce09c 100644 --- a/target/arm/a32-uncond.decode +++ b/target/arm/a32-uncond.decode @@ -5,7 +5,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/arm/a32.decode b/target/arm/a32.decode index 0bd952c0692807f321bb0cc8f3262f8de5096194..fcd8cd4f7d9264464d3aa1ad5d9dc6122ce905c0 100644 --- a/target/arm/a32.decode +++ b/target/arm/a32.decode @@ -5,7 +5,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -47,6 +47,8 @@ &bfi rd rn lsb msb &sat rd rn satimm imm sh &pkh rd rn rm imm tb +&mcr cp opc1 crn crm opc2 rt +&mcrr cp opc1 crm rt rt2 # Data-processing (register) @@ -529,6 +531,23 @@ LDM_a32 ---- 100 b:1 i:1 u:1 w:1 1 rn:4 list:16 &ldst_block B .... 1010 ........................ @branch BL .... 1011 ........................ @branch +# Coprocessor instructions + +# We decode MCR, MCR, MRRC and MCRR only, because for QEMU the +# other coprocessor instructions always UNDEF. +# The trans_ functions for these will ignore cp values 8..13 for v7 or +# earlier, and 0..13 for v8 and later, because those areas of the +# encoding space may be used for other things, such as VFP or Neon. + +@mcr ---- .... opc1:3 . crn:4 rt:4 cp:4 opc2:3 . crm:4 &mcr +@mcrr ---- .... .... rt2:4 rt:4 cp:4 opc1:4 crm:4 &mcrr + +MCRR .... 1100 0100 .... .... .... .... .... @mcrr +MRRC .... 1100 0101 .... .... .... .... .... @mcrr + +MCR .... 1110 ... 0 .... .... .... ... 1 .... @mcr +MRC .... 1110 ... 1 .... .... .... ... 1 .... @mcr + # Supervisor call SVC ---- 1111 imm:24 &i diff --git a/target/arm/arch_dump.c b/target/arm/arch_dump.c index 7693e17e964429ea6c4d23aeb323fc077a4f596a..01848453109137b711bda9ab86d33cd6b8831429 100644 --- a/target/arm/arch_dump.c +++ b/target/arm/arch_dump.c @@ -114,8 +114,8 @@ static int aarch64_write_elf64_prfpreg(WriteCoreDumpFunction f, for (i = 0; i < 32; ++i) { uint64_t *q = aa64_vfp_qreg(env, i); - note.vfp.vregs[2*i + 0] = cpu_to_dump64(s, q[0]); - note.vfp.vregs[2*i + 1] = cpu_to_dump64(s, q[1]); + note.vfp.vregs[2 * i + 0] = cpu_to_dump64(s, q[0]); + note.vfp.vregs[2 * i + 1] = cpu_to_dump64(s, q[1]); } if (s->dump_info.d_endian == ELFDATA2MSB) { @@ -125,8 +125,8 @@ static int aarch64_write_elf64_prfpreg(WriteCoreDumpFunction f, */ for (i = 0; i < 32; ++i) { uint64_t tmp = note.vfp.vregs[2*i]; - note.vfp.vregs[2*i] = note.vfp.vregs[2*i+1]; - note.vfp.vregs[2*i+1] = tmp; + note.vfp.vregs[2 * i] = note.vfp.vregs[2 * i + 1]; + note.vfp.vregs[2 * i + 1] = tmp; } } diff --git a/target/arm/arm-semi.c b/target/arm/arm-semi.c index 8718fd019480fbf3f10ea0b01eb0d3f91b4131c5..c892e0e674e50cc199228b5c8658a08a6976c623 100644 --- a/target/arm/arm-semi.c +++ b/target/arm/arm-semi.c @@ -36,6 +36,7 @@ #else #include "exec/gdbstub.h" #include "qemu/cutils.h" +#include "hw/arm/boot.h" #endif #define TARGET_SYS_OPEN 0x01 @@ -755,7 +756,7 @@ target_ulong do_arm_semihosting(CPUARMState *env) if (use_gdb_syscalls()) { arm_semi_open_guestfd = guestfd; ret = arm_gdb_syscall(cpu, arm_semi_open_cb, "open,%s,%x,1a4", arg0, - (int)arg2+1, gdb_open_modeflags[arg1]); + (int)arg2 + 1, gdb_open_modeflags[arg1]); } else { ret = set_swi_errno(env, open(s, open_modeflags[arg1], 0644)); if (ret == (uint32_t)-1) { @@ -852,7 +853,7 @@ target_ulong do_arm_semihosting(CPUARMState *env) GET_ARG(1); if (use_gdb_syscalls()) { ret = arm_gdb_syscall(cpu, arm_semi_cb, "unlink,%s", - arg0, (int)arg1+1); + arg0, (int)arg1 + 1); } else { s = lock_user_string(arg0); if (!s) { @@ -870,7 +871,7 @@ target_ulong do_arm_semihosting(CPUARMState *env) GET_ARG(3); if (use_gdb_syscalls()) { return arm_gdb_syscall(cpu, arm_semi_cb, "rename,%s,%s", - arg0, (int)arg1+1, arg2, (int)arg3+1); + arg0, (int)arg1 + 1, arg2, (int)arg3 + 1); } else { char *s2; s = lock_user_string(arg0); @@ -896,7 +897,7 @@ target_ulong do_arm_semihosting(CPUARMState *env) GET_ARG(1); if (use_gdb_syscalls()) { return arm_gdb_syscall(cpu, arm_semi_cb, "system,%s", - arg0, (int)arg1+1); + arg0, (int)arg1 + 1); } else { s = lock_user_string(arg0); if (!s) { @@ -1014,6 +1015,9 @@ target_ulong do_arm_semihosting(CPUARMState *env) int i; #ifdef CONFIG_USER_ONLY TaskState *ts = cs->opaque; +#else + const struct arm_boot_info *info = env->boot_info; + target_ulong rambase = info->loader_start; #endif GET_ARG(0); @@ -1046,10 +1050,10 @@ target_ulong do_arm_semihosting(CPUARMState *env) #else limit = ram_size; /* TODO: Make this use the limit of the loaded application. */ - retvals[0] = limit / 2; - retvals[1] = limit; - retvals[2] = limit; /* Stack base */ - retvals[3] = 0; /* Stack limit. */ + retvals[0] = rambase + limit / 2; + retvals[1] = rambase + limit; + retvals[2] = rambase + limit; /* Stack base */ + retvals[3] = rambase; /* Stack limit. */ #endif for (i = 0; i < ARRAY_SIZE(retvals); i++) { diff --git a/target/arm/arm_ldst.h b/target/arm/arm_ldst.h index 45edb108f6aaa37f69ee6f953ec3bcf38081d38e..057160e8da6dd97c91c853f50603155ba1490f59 100644 --- a/target/arm/arm_ldst.h +++ b/target/arm/arm_ldst.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h index 56395b87f62d25916a36f56de0a3bb4748e5b10c..a22bd506d07d0f8c88ab39f6b77d3b1f848cee78 100644 --- a/target/arm/cpu-qom.h +++ b/target/arm/cpu-qom.h @@ -21,17 +21,14 @@ #define QEMU_ARM_CPU_QOM_H #include "hw/core/cpu.h" +#include "qom/object.h" struct arm_boot_info; #define TYPE_ARM_CPU "arm-cpu" -#define ARM_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(ARMCPUClass, (klass), TYPE_ARM_CPU) -#define ARM_CPU(obj) \ - OBJECT_CHECK(ARMCPU, (obj), TYPE_ARM_CPU) -#define ARM_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ARMCPUClass, (obj), TYPE_ARM_CPU) +OBJECT_DECLARE_TYPE(ARMCPU, ARMCPUClass, + ARM_CPU) #define TYPE_ARM_MAX_CPU "max-" TYPE_ARM_CPU @@ -51,7 +48,7 @@ void aarch64_cpu_register(const ARMCPUInfo *info); * * An ARM CPU model. */ -typedef struct ARMCPUClass { +struct ARMCPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ @@ -59,21 +56,19 @@ typedef struct ARMCPUClass { const ARMCPUInfo *info; DeviceRealize parent_realize; DeviceReset parent_reset; -} ARMCPUClass; +}; -typedef struct ARMCPU ARMCPU; #define TYPE_AARCH64_CPU "aarch64-cpu" -#define AARCH64_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(AArch64CPUClass, (klass), TYPE_AARCH64_CPU) -#define AARCH64_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(AArch64CPUClass, (obj), TYPE_AArch64_CPU) +typedef struct AArch64CPUClass AArch64CPUClass; +DECLARE_CLASS_CHECKERS(AArch64CPUClass, AARCH64_CPU, + TYPE_AARCH64_CPU) -typedef struct AArch64CPUClass { +struct AArch64CPUClass { /*< private >*/ ARMCPUClass parent_class; /*< public >*/ -} AArch64CPUClass; +}; void register_cp_regs_for_features(ARMCPU *cpu); void init_cpreg_list(ARMCPU *cpu); diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 32bec156f2d4f35f32d4a4566d81e9e12021efee..07492e9f9a44640dad640d87daed50b5463cfbde 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -174,8 +174,7 @@ static void arm_cpu_reset(DeviceState *dev) env->vfp.xregs[ARM_VFP_MVFR1] = cpu->isar.mvfr1; env->vfp.xregs[ARM_VFP_MVFR2] = cpu->isar.mvfr2; - cpu->power_state = cpu->start_powered_off ? PSCI_OFF : PSCI_ON; - s->halted = cpu->start_powered_off; + cpu->power_state = s->start_powered_off ? PSCI_OFF : PSCI_ON; if (arm_feature(env, ARM_FEATURE_IWMMXT)) { env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q'; @@ -203,6 +202,9 @@ static void arm_cpu_reset(DeviceState *dev) * Enable TBI0 and TBI1. While the real kernel only enables TBI0, * turning on both here will produce smaller code and otherwise * make no difference to the user-level emulation. + * + * In sve_probe_page, we assume that this is set. + * Do not modify this without other changes. */ env->cp15.tcr_el[1].raw_tcr = (3ULL << 37); #else @@ -253,6 +255,15 @@ static void arm_cpu_reset(DeviceState *dev) uint8_t *rom; uint32_t vecbase; + if (cpu_isar_feature(aa32_lob, cpu)) { + /* + * LTPSIZE is constant 4 if MVE not implemented, and resets + * to an UNKNOWN value if MVE is implemented. We choose to + * always reset to 4. + */ + env->v7m.ltpsize = 4; + } + if (arm_feature(env, ARM_FEATURE_M_SECURITY)) { env->v7m.secure = true; } else { @@ -388,12 +399,15 @@ static void arm_cpu_reset(DeviceState *dev) set_flush_to_zero(1, &env->vfp.standard_fp_status); set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status); set_default_nan_mode(1, &env->vfp.standard_fp_status); + set_default_nan_mode(1, &env->vfp.standard_fp_status_f16); set_float_detect_tininess(float_tininess_before_rounding, &env->vfp.fp_status); set_float_detect_tininess(float_tininess_before_rounding, &env->vfp.standard_fp_status); set_float_detect_tininess(float_tininess_before_rounding, &env->vfp.fp_status_f16); + set_float_detect_tininess(float_tininess_before_rounding, + &env->vfp.standard_fp_status_f16); #ifndef CONFIG_USER_ONLY if (kvm_enabled()) { kvm_arm_reset_vcpu(cpu); @@ -1108,7 +1122,7 @@ static void arm_set_pmu(Object *obj, bool value, Error **errp) ARMCPU *cpu = ARM_CPU(obj); if (value) { - if (kvm_enabled() && !kvm_arm_pmu_supported(CPU(cpu))) { + if (kvm_enabled() && !kvm_arm_pmu_supported()) { error_setg(errp, "'pmu' feature not supported by KVM on this host"); return; } @@ -1245,6 +1259,29 @@ void arm_cpu_post_init(Object *obj) if (arm_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER)) { qdev_property_add_static(DEVICE(cpu), &arm_cpu_gt_cntfrq_property); } + + if (kvm_enabled()) { + kvm_arm_add_vcpu_properties(obj); + } + +#ifndef CONFIG_USER_ONLY + if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && + cpu_isar_feature(aa64_mte, cpu)) { + object_property_add_link(obj, "tag-memory", + TYPE_MEMORY_REGION, + (Object **)&cpu->tag_memory, + qdev_prop_allow_set_link_before_realize, + OBJ_PROP_LINK_STRONG); + + if (arm_feature(&cpu->env, ARM_FEATURE_EL3)) { + object_property_add_link(obj, "secure-tag-memory", + TYPE_MEMORY_REGION, + (Object **)&cpu->secure_tag_memory, + qdev_prop_allow_set_link_before_realize, + OBJ_PROP_LINK_STRONG); + } + } +#endif } static void arm_cpu_finalizefn(Object *obj) @@ -1282,6 +1319,14 @@ void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp) return; } } + + if (kvm_enabled()) { + kvm_arm_steal_time_finalize(cpu, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; + } + } } static void arm_cpu_realizefn(DeviceState *dev, Error **errp) @@ -1393,17 +1438,22 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) u = cpu->isar.mvfr0; u = FIELD_DP32(u, MVFR0, FPSP, 0); u = FIELD_DP32(u, MVFR0, FPDP, 0); - u = FIELD_DP32(u, MVFR0, FPTRAP, 0); u = FIELD_DP32(u, MVFR0, FPDIVIDE, 0); u = FIELD_DP32(u, MVFR0, FPSQRT, 0); - u = FIELD_DP32(u, MVFR0, FPSHVEC, 0); u = FIELD_DP32(u, MVFR0, FPROUND, 0); + if (!arm_feature(env, ARM_FEATURE_M)) { + u = FIELD_DP32(u, MVFR0, FPTRAP, 0); + u = FIELD_DP32(u, MVFR0, FPSHVEC, 0); + } cpu->isar.mvfr0 = u; u = cpu->isar.mvfr1; u = FIELD_DP32(u, MVFR1, FPFTZ, 0); u = FIELD_DP32(u, MVFR1, FPDNAN, 0); u = FIELD_DP32(u, MVFR1, FPHP, 0); + if (arm_feature(env, ARM_FEATURE_M)) { + u = FIELD_DP32(u, MVFR1, FP16, 0); + } cpu->isar.mvfr1 = u; u = cpu->isar.mvfr2; @@ -1439,16 +1489,18 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) u = FIELD_DP32(u, ID_ISAR6, FHM, 0); cpu->isar.id_isar6 = u; - u = cpu->isar.mvfr1; - u = FIELD_DP32(u, MVFR1, SIMDLS, 0); - u = FIELD_DP32(u, MVFR1, SIMDINT, 0); - u = FIELD_DP32(u, MVFR1, SIMDSP, 0); - u = FIELD_DP32(u, MVFR1, SIMDHP, 0); - cpu->isar.mvfr1 = u; - - u = cpu->isar.mvfr2; - u = FIELD_DP32(u, MVFR2, SIMDMISC, 0); - cpu->isar.mvfr2 = u; + if (!arm_feature(env, ARM_FEATURE_M)) { + u = cpu->isar.mvfr1; + u = FIELD_DP32(u, MVFR1, SIMDLS, 0); + u = FIELD_DP32(u, MVFR1, SIMDINT, 0); + u = FIELD_DP32(u, MVFR1, SIMDSP, 0); + u = FIELD_DP32(u, MVFR1, SIMDHP, 0); + cpu->isar.mvfr1 = u; + + u = cpu->isar.mvfr2; + u = FIELD_DP32(u, MVFR2, SIMDMISC, 0); + cpu->isar.mvfr2 = u; + } } if (!cpu->has_neon && !cpu->has_vfp) { @@ -1560,7 +1612,6 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) } if (arm_feature(env, ARM_FEATURE_LPAE)) { set_feature(env, ARM_FEATURE_V7MP); - set_feature(env, ARM_FEATURE_PXN); } if (arm_feature(env, ARM_FEATURE_CBAR_RO)) { set_feature(env, ARM_FEATURE_CBAR); @@ -1632,7 +1683,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) /* Disable the security extension feature bits in the processor feature * registers as well. These are id_pfr1[7:4] and id_aa64pfr0[15:12]. */ - cpu->id_pfr1 &= ~0xf0; + cpu->isar.id_pfr1 &= ~0xf0; cpu->isar.id_aa64pfr0 &= ~0xf000; } @@ -1669,9 +1720,20 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) * id_aa64pfr0_el1[11:8]. */ cpu->isar.id_aa64pfr0 &= ~0xf00; - cpu->id_pfr1 &= ~0xf000; + cpu->isar.id_pfr1 &= ~0xf000; } +#ifndef CONFIG_USER_ONLY + if (cpu->tag_memory == NULL && cpu_isar_feature(aa64_mte, cpu)) { + /* + * Disable the MTE feature bits if we do not have tag-memory + * provided by the machine. + */ + cpu->isar.id_aa64pfr1 = + FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 0); + } +#endif + /* MPU can be configured out of a PMSA CPU either by setting has-mpu * to false or by setting pmsav7-dregion to 0. */ @@ -1734,18 +1796,35 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) #ifndef CONFIG_USER_ONLY MachineState *ms = MACHINE(qdev_get_machine()); unsigned int smp_cpus = ms->smp.cpus; + bool has_secure = cpu->has_el3 || arm_feature(env, ARM_FEATURE_M_SECURITY); - if (cpu->has_el3 || arm_feature(env, ARM_FEATURE_M_SECURITY)) { - cs->num_ases = 2; + /* + * We must set cs->num_ases to the final value before + * the first call to cpu_address_space_init. + */ + if (cpu->tag_memory != NULL) { + cs->num_ases = 3 + has_secure; + } else { + cs->num_ases = 1 + has_secure; + } + if (has_secure) { if (!cpu->secure_memory) { cpu->secure_memory = cs->memory; } cpu_address_space_init(cs, ARMASIdx_S, "cpu-secure-memory", cpu->secure_memory); - } else { - cs->num_ases = 1; } + + if (cpu->tag_memory != NULL) { + cpu_address_space_init(cs, ARMASIdx_TagNS, "cpu-tag-memory", + cpu->tag_memory); + if (has_secure) { + cpu_address_space_init(cs, ARMASIdx_TagS, "cpu-tag-memory", + cpu->secure_tag_memory); + } + } + cpu_address_space_init(cs, ARMASIdx_NS, "cpu-memory", cs->memory); /* No core_count specified, default to smp_cpus. */ @@ -1754,6 +1833,30 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) } #endif + if (tcg_enabled()) { + int dcz_blocklen = 4 << cpu->dcz_blocksize; + + /* + * We only support DCZ blocklen that fits on one page. + * + * Architectually this is always true. However TARGET_PAGE_SIZE + * is variable and, for compatibility with -machine virt-2.7, + * is only 1KiB, as an artifact of legacy ARMv5 subpage support. + * But even then, while the largest architectural DCZ blocklen + * is 2KiB, no cpu actually uses such a large blocklen. + */ + assert(dcz_blocklen <= TARGET_PAGE_SIZE); + + /* + * We only support DCZ blocksize >= 2*TAG_GRANULE, which is to say + * both nibbles of each byte storing tag data may be written at once. + * Since TAG_GRANULE is 16, this means that blocklen must be >= 32. + */ + if (cpu_isar_feature(aa64_mte, cpu)) { + assert(dcz_blocklen >= 2 * TAG_GRANULE); + } + } + qemu_init_vcpu(cs); cpu_reset(cs); @@ -1815,8 +1918,8 @@ static void cortex_a8_initfn(Object *obj) cpu->isar.mvfr1 = 0x00011111; cpu->ctr = 0x82048004; cpu->reset_sctlr = 0x00c50078; - cpu->id_pfr0 = 0x1031; - cpu->id_pfr1 = 0x11; + cpu->isar.id_pfr0 = 0x1031; + cpu->isar.id_pfr1 = 0x11; cpu->isar.id_dfr0 = 0x400; cpu->id_afr0 = 0; cpu->isar.id_mmfr0 = 0x31100003; @@ -1887,8 +1990,8 @@ static void cortex_a9_initfn(Object *obj) cpu->isar.mvfr1 = 0x01111111; cpu->ctr = 0x80038003; cpu->reset_sctlr = 0x00c50078; - cpu->id_pfr0 = 0x1031; - cpu->id_pfr1 = 0x11; + cpu->isar.id_pfr0 = 0x1031; + cpu->isar.id_pfr1 = 0x11; cpu->isar.id_dfr0 = 0x000; cpu->id_afr0 = 0; cpu->isar.id_mmfr0 = 0x00100103; @@ -1951,8 +2054,8 @@ static void cortex_a7_initfn(Object *obj) cpu->isar.mvfr1 = 0x11111111; cpu->ctr = 0x84448003; cpu->reset_sctlr = 0x00c50078; - cpu->id_pfr0 = 0x00001131; - cpu->id_pfr1 = 0x00011011; + cpu->isar.id_pfr0 = 0x00001131; + cpu->isar.id_pfr1 = 0x00011011; cpu->isar.id_dfr0 = 0x02010555; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x10101105; @@ -1996,8 +2099,8 @@ static void cortex_a15_initfn(Object *obj) cpu->isar.mvfr1 = 0x11111111; cpu->ctr = 0x8444c004; cpu->reset_sctlr = 0x00c50078; - cpu->id_pfr0 = 0x00001131; - cpu->id_pfr1 = 0x00011011; + cpu->isar.id_pfr0 = 0x00001131; + cpu->isar.id_pfr1 = 0x00011011; cpu->isar.id_dfr0 = 0x02010555; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x10201105; @@ -2018,72 +2121,69 @@ static void cortex_a15_initfn(Object *obj) } #ifndef TARGET_AARCH64 -/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host); - * otherwise, a CPU with as many features enabled as our emulation supports. +/* + * -cpu max: a CPU with as many features enabled as our emulation supports. * The version of '-cpu max' for qemu-system-aarch64 is defined in cpu64.c; - * this only needs to handle 32 bits. + * this only needs to handle 32 bits, and need not care about KVM. */ static void arm_max_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); - if (kvm_enabled()) { - kvm_arm_set_cpu_features_from_host(cpu); - kvm_arm_add_vcpu_properties(obj); - } else { - cortex_a15_initfn(obj); + cortex_a15_initfn(obj); - /* old-style VFP short-vector support */ - cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); + /* old-style VFP short-vector support */ + cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); #ifdef CONFIG_USER_ONLY - /* We don't set these in system emulation mode for the moment, - * since we don't correctly set (all of) the ID registers to - * advertise them. - */ - set_feature(&cpu->env, ARM_FEATURE_V8); - { - uint32_t t; - - t = cpu->isar.id_isar5; - t = FIELD_DP32(t, ID_ISAR5, AES, 2); - t = FIELD_DP32(t, ID_ISAR5, SHA1, 1); - t = FIELD_DP32(t, ID_ISAR5, SHA2, 1); - t = FIELD_DP32(t, ID_ISAR5, CRC32, 1); - t = FIELD_DP32(t, ID_ISAR5, RDM, 1); - t = FIELD_DP32(t, ID_ISAR5, VCMA, 1); - cpu->isar.id_isar5 = t; - - t = cpu->isar.id_isar6; - t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1); - t = FIELD_DP32(t, ID_ISAR6, DP, 1); - t = FIELD_DP32(t, ID_ISAR6, FHM, 1); - t = FIELD_DP32(t, ID_ISAR6, SB, 1); - t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1); - cpu->isar.id_isar6 = t; - - t = cpu->isar.mvfr1; - t = FIELD_DP32(t, MVFR1, FPHP, 2); /* v8.0 FP support */ - cpu->isar.mvfr1 = t; - - t = cpu->isar.mvfr2; - t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */ - t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */ - cpu->isar.mvfr2 = t; - - t = cpu->isar.id_mmfr3; - t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */ - cpu->isar.id_mmfr3 = t; - - t = cpu->isar.id_mmfr4; - t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */ - t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */ - t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */ - t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */ - cpu->isar.id_mmfr4 = t; - } -#endif + /* + * We don't set these in system emulation mode for the moment, + * since we don't correctly set (all of) the ID registers to + * advertise them. + */ + set_feature(&cpu->env, ARM_FEATURE_V8); + { + uint32_t t; + + t = cpu->isar.id_isar5; + t = FIELD_DP32(t, ID_ISAR5, AES, 2); + t = FIELD_DP32(t, ID_ISAR5, SHA1, 1); + t = FIELD_DP32(t, ID_ISAR5, SHA2, 1); + t = FIELD_DP32(t, ID_ISAR5, CRC32, 1); + t = FIELD_DP32(t, ID_ISAR5, RDM, 1); + t = FIELD_DP32(t, ID_ISAR5, VCMA, 1); + cpu->isar.id_isar5 = t; + + t = cpu->isar.id_isar6; + t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1); + t = FIELD_DP32(t, ID_ISAR6, DP, 1); + t = FIELD_DP32(t, ID_ISAR6, FHM, 1); + t = FIELD_DP32(t, ID_ISAR6, SB, 1); + t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1); + cpu->isar.id_isar6 = t; + + t = cpu->isar.mvfr1; + t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */ + t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */ + cpu->isar.mvfr1 = t; + + t = cpu->isar.mvfr2; + t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */ + t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */ + cpu->isar.mvfr2 = t; + + t = cpu->isar.id_mmfr3; + t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */ + cpu->isar.id_mmfr3 = t; + + t = cpu->isar.id_mmfr4; + t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */ + t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */ + t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */ + t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */ + cpu->isar.id_mmfr4 = t; } +#endif } #endif @@ -2105,7 +2205,6 @@ static const ARMCPUInfo arm_cpus[] = { }; static Property arm_cpu_properties[] = { - DEFINE_PROP_BOOL("start-powered-off", ARMCPU, start_powered_off, false), DEFINE_PROP_UINT32("psci-conduit", ARMCPU, psci_conduit, 0), DEFINE_PROP_UINT64("midr", ARMCPU, midr, 0), DEFINE_PROP_UINT64("mp-affinity", ARMCPU, @@ -2166,8 +2265,8 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) cc->tlb_fill = arm_cpu_tlb_fill; cc->debug_excp_handler = arm_debug_excp_handler; cc->debug_check_watchpoint = arm_debug_check_watchpoint; -#if !defined(CONFIG_USER_ONLY) cc->do_unaligned_access = arm_cpu_do_unaligned_access; +#if !defined(CONFIG_USER_ONLY) cc->do_transaction_failed = arm_cpu_do_transaction_failed; cc->adjust_watchpoint_address = arm_adjust_watchpoint_address; #endif /* CONFIG_TCG && !CONFIG_USER_ONLY */ @@ -2183,17 +2282,12 @@ static void arm_host_initfn(Object *obj) if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { aarch64_add_sve_properties(obj); } - kvm_arm_add_vcpu_properties(obj); arm_cpu_post_init(obj); } static const TypeInfo host_arm_cpu_type_info = { .name = TYPE_ARM_HOST_CPU, -#ifdef TARGET_AARCH64 .parent = TYPE_AARCH64_CPU, -#else - .parent = TYPE_ARM_CPU, -#endif .instance_init = arm_host_initfn, }; @@ -2219,6 +2313,7 @@ void arm_cpu_register(const ARMCPUInfo *info) TypeInfo type_info = { .parent = TYPE_ARM_CPU, .instance_size = sizeof(ARMCPU), + .instance_align = __alignof__(ARMCPU), .instance_init = arm_cpu_instance_init, .class_size = sizeof(ARMCPUClass), .class_init = info->class_init ?: cpu_register_class_init, @@ -2234,6 +2329,7 @@ static const TypeInfo arm_cpu_type_info = { .name = TYPE_ARM_CPU, .parent = TYPE_CPU, .instance_size = sizeof(ARMCPU), + .instance_align = __alignof__(ARMCPU), .instance_init = arm_cpu_initfn, .instance_finalize = arm_cpu_finalizefn, .abstract = true, diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 677584e5da0468fb274777a5643b4de4ba5ecf84..e5514c828623614aed238350830c3e4281153bd4 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -24,6 +24,7 @@ #include "hw/registerfields.h" #include "cpu-qom.h" #include "exec/cpu-defs.h" +#include "qapi/qapi-types-common.h" /* ARM processors have a weak memory model */ #define TCG_GUEST_DEFAULT_MO (0) @@ -502,6 +503,9 @@ typedef struct CPUARMState { uint64_t pmccfiltr_el0; /* Performance Monitor Filter Register */ uint64_t vpidr_el2; /* Virtualization Processor ID Register */ uint64_t vmpidr_el2; /* Virtualization Multiprocessor ID Register */ + uint64_t tfsr_el[4]; /* tfsre0_el1 is index 0. */ + uint64_t gcr_el1; + uint64_t rgsr_el1; } cp15; struct { @@ -545,6 +549,7 @@ typedef struct CPUARMState { uint32_t fpdscr[M_REG_NUM_BANKS]; uint32_t cpacr[M_REG_NUM_BANKS]; uint32_t nsacr; + int ltpsize; } v7m; /* Information associated with an exception about to be taken: @@ -570,6 +575,8 @@ typedef struct CPUARMState { uint64_t esr; } serror; + uint8_t ext_dabt_raised; /* Tracking/verifying injection of ext DABT */ + /* State of our input IRQ/FIQ/VIRQ/VFIQ lines */ uint32_t irq_line_state; @@ -604,6 +611,8 @@ typedef struct CPUARMState { * fp_status: is the "normal" fp status. * fp_status_fp16: used for half-precision calculations * standard_fp_status : the ARM "Standard FPSCR Value" + * standard_fp_status_fp16 : used for half-precision + * calculations with the ARM "Standard FPSCR Value" * * Half-precision operations are governed by a separate * flush-to-zero control bit in FPSCR:FZ16. We pass a separate @@ -614,15 +623,20 @@ typedef struct CPUARMState { * Neon) which the architecture defines as controlled by the * standard FPSCR value rather than the FPSCR. * + * The "standard FPSCR but for fp16 ops" is needed because + * the "standard FPSCR" tracks the FPSCR.FZ16 bit rather than + * using a fixed value for it. + * * To avoid having to transfer exception bits around, we simply * say that the FPSCR cumulative exception flags are the logical - * OR of the flags in the three fp statuses. This relies on the + * OR of the flags in the four fp statuses. This relies on the * only thing which needs to read the exception flags being * an explicit FPSCR read. */ float_status fp_status; float_status fp_status_f16; float_status standard_fp_status; + float_status standard_fp_status_f16; /* ZCR_EL[1-3] */ uint64_t zcr_el[4]; @@ -789,6 +803,10 @@ struct ARMCPU { /* MemoryRegion to use for secure physical accesses */ MemoryRegion *secure_memory; + /* MemoryRegion to use for allocation tag accesses */ + MemoryRegion *tag_memory; + MemoryRegion *secure_tag_memory; + /* For v8M, pointer to the IDAU interface provided by board/SoC */ Object *idau; @@ -801,9 +819,6 @@ struct ARMCPU { */ uint32_t psci_version; - /* Should CPU start in PSCI powered-off state? */ - bool start_powered_off; - /* Current power state, access guarded by BQL */ ARMPSCIState power_state; @@ -850,6 +865,9 @@ struct ARMCPU { bool kvm_vtime_dirty; uint64_t kvm_vtime; + /* KVM steal time */ + OnOffAuto kvm_steal_time; + /* Uniprocessor system with MP extensions */ bool mp_is_up; @@ -893,6 +911,8 @@ struct ARMCPU { uint32_t id_mmfr2; uint32_t id_mmfr3; uint32_t id_mmfr4; + uint32_t id_pfr0; + uint32_t id_pfr1; uint32_t mvfr0; uint32_t mvfr1; uint32_t mvfr2; @@ -913,8 +933,6 @@ struct ARMCPU { uint32_t reset_fpsid; uint32_t ctr; uint32_t reset_sctlr; - uint32_t id_pfr0; - uint32_t id_pfr1; uint64_t pmceid0; uint64_t pmceid1; uint32_t id_afr0; @@ -1282,6 +1300,7 @@ void pmu_init(ARMCPU *cpu); #define PSTATE_SS (1U << 21) #define PSTATE_PAN (1U << 22) #define PSTATE_UAO (1U << 23) +#define PSTATE_TCO (1U << 25) #define PSTATE_V (1U << 28) #define PSTATE_C (1U << 29) #define PSTATE_Z (1U << 30) @@ -1758,6 +1777,15 @@ FIELD(ID_ISAR6, FHM, 8, 4) FIELD(ID_ISAR6, SB, 12, 4) FIELD(ID_ISAR6, SPECRES, 16, 4) +FIELD(ID_MMFR0, VMSA, 0, 4) +FIELD(ID_MMFR0, PMSA, 4, 4) +FIELD(ID_MMFR0, OUTERSHR, 8, 4) +FIELD(ID_MMFR0, SHARELVL, 12, 4) +FIELD(ID_MMFR0, TCM, 16, 4) +FIELD(ID_MMFR0, AUXREG, 20, 4) +FIELD(ID_MMFR0, FCSE, 24, 4) +FIELD(ID_MMFR0, INNERSHR, 28, 4) + FIELD(ID_MMFR3, CMAINTVA, 0, 4) FIELD(ID_MMFR3, CMAINTSW, 4, 4) FIELD(ID_MMFR3, BPMAINT, 8, 4) @@ -1776,6 +1804,15 @@ FIELD(ID_MMFR4, LSM, 20, 4) FIELD(ID_MMFR4, CCIDX, 24, 4) FIELD(ID_MMFR4, EVT, 28, 4) +FIELD(ID_PFR1, PROGMOD, 0, 4) +FIELD(ID_PFR1, SECURITY, 4, 4) +FIELD(ID_PFR1, MPROGMOD, 8, 4) +FIELD(ID_PFR1, VIRTUALIZATION, 12, 4) +FIELD(ID_PFR1, GENTIMER, 16, 4) +FIELD(ID_PFR1, SEC_FRAC, 20, 4) +FIELD(ID_PFR1, VIRT_FRAC, 24, 4) +FIELD(ID_PFR1, GIC, 28, 4) + FIELD(ID_AA64ISAR0, AES, 4, 4) FIELD(ID_AA64ISAR0, SHA1, 8, 4) FIELD(ID_AA64ISAR0, SHA2, 12, 4) @@ -1893,10 +1930,12 @@ FIELD(MVFR0, FPROUND, 28, 4) FIELD(MVFR1, FPFTZ, 0, 4) FIELD(MVFR1, FPDNAN, 4, 4) -FIELD(MVFR1, SIMDLS, 8, 4) -FIELD(MVFR1, SIMDINT, 12, 4) -FIELD(MVFR1, SIMDSP, 16, 4) -FIELD(MVFR1, SIMDHP, 20, 4) +FIELD(MVFR1, SIMDLS, 8, 4) /* A-profile only */ +FIELD(MVFR1, SIMDINT, 12, 4) /* A-profile only */ +FIELD(MVFR1, SIMDSP, 16, 4) /* A-profile only */ +FIELD(MVFR1, SIMDHP, 20, 4) /* A-profile only */ +FIELD(MVFR1, MVE, 8, 4) /* M-profile only */ +FIELD(MVFR1, FP16, 20, 4) /* M-profile only */ FIELD(MVFR1, FPHP, 24, 4) FIELD(MVFR1, SIMDFMAC, 28, 4) @@ -1935,12 +1974,10 @@ enum arm_features { ARM_FEATURE_CACHE_DIRTY_REG, /* 1136/1176 cache dirty status register */ ARM_FEATURE_CACHE_BLOCK_OPS, /* v6 optional cache block operations */ ARM_FEATURE_MPIDR, /* has cp15 MPIDR */ - ARM_FEATURE_PXN, /* has Privileged Execute Never bit */ ARM_FEATURE_LPAE, /* has Large Physical Address Extension */ ARM_FEATURE_V8, ARM_FEATURE_AARCH64, /* supports 64 bit mode */ ARM_FEATURE_CBAR, /* has cp15 CBAR */ - ARM_FEATURE_CRC, /* ARMv8 CRC instructions */ ARM_FEATURE_CBAR_RO, /* has cp15 CBAR and it is read-only */ ARM_FEATURE_EL2, /* has EL2 Virtualization support */ ARM_FEATURE_EL3, /* has EL3 Secure monitor support */ @@ -1949,6 +1986,7 @@ enum arm_features { ARM_FEATURE_VBAR, /* has cp15 VBAR */ ARM_FEATURE_M_SECURITY, /* M profile Security Extension */ ARM_FEATURE_M_MAIN, /* M profile Main Extension */ + ARM_FEATURE_V8_1M, /* M profile extras only in v8.1M and later */ }; static inline int arm_feature(CPUARMState *env, int feature) @@ -2334,7 +2372,7 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid) * migration or KVM state synchronization. (Typically this is for "registers" * which are actually used as instructions for cache maintenance and so on.) * IO indicates that this register does I/O and therefore its accesses - * need to be surrounded by gen_io_start()/gen_io_end(). In particular, + * need to be marked with gen_io_start() and also end the TB. In particular, * registers which implement clocks or timers require this. * RAISES_EXC is for when the read or write hook might raise an exception; * the generated code will synchronize the CPU state before calling the hook @@ -2356,7 +2394,9 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid) #define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300) #define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400) #define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500) -#define ARM_LAST_SPECIAL ARM_CP_DC_ZVA +#define ARM_CP_DC_GVA (ARM_CP_SPECIAL | 0x0600) +#define ARM_CP_DC_GZVA (ARM_CP_SPECIAL | 0x0700) +#define ARM_LAST_SPECIAL ARM_CP_DC_GZVA #define ARM_CP_FPU 0x1000 #define ARM_CP_SVE 0x2000 #define ARM_CP_NO_GDB 0x4000 @@ -2979,6 +3019,8 @@ typedef enum ARMMMUIdxBit { typedef enum ARMASIdx { ARMASIdx_NS = 0, ARMASIdx_S = 1, + ARMASIdx_TagNS = 2, + ARMASIdx_TagS = 3, } ARMASIdx; /* Return the Exception Level targeted by debug exceptions. */ @@ -3183,10 +3225,10 @@ typedef ARMCPU ArchCPU; * | | | TBFLAG_A32 | | * | | +-----+----------+ TBFLAG_AM32 | * | TBFLAG_ANY | |TBFLAG_M32| | - * | | +-+----------+--------------| - * | | | TBFLAG_A64 | - * +--------------+---------+---------------------------+ - * 31 20 15 0 + * | +-----------+----------+--------------| + * | | TBFLAG_A64 | + * +--------------+-------------------------------------+ + * 31 20 0 * * Unless otherwise noted, these bits are cached in env->hflags. */ @@ -3253,6 +3295,10 @@ FIELD(TBFLAG_A64, BT, 9, 1) FIELD(TBFLAG_A64, BTYPE, 10, 2) /* Not cached. */ FIELD(TBFLAG_A64, TBID, 12, 2) FIELD(TBFLAG_A64, UNPRIV, 14, 1) +FIELD(TBFLAG_A64, ATA, 15, 1) +FIELD(TBFLAG_A64, TCMA, 16, 2) +FIELD(TBFLAG_A64, MTE_ACTIVE, 18, 1) +FIELD(TBFLAG_A64, MTE0_ACTIVE, 19, 1) /** * cpu_mmu_index: @@ -3385,6 +3431,25 @@ static inline uint64_t *aa64_vfp_qreg(CPUARMState *env, unsigned regno) /* Shared between translate-sve.c and sve_helper.c. */ extern const uint64_t pred_esz_masks[4]; +/* Helper for the macros below, validating the argument type. */ +static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x) +{ + return x; +} + +/* + * Lvalue macros for ARM TLB bits that we must cache in the TCG TLB. + * Using these should be a bit more self-documenting than using the + * generic target bits directly. + */ +#define arm_tlb_bti_gp(x) (typecheck_memtxattrs(x)->target_tlb_bit0) +#define arm_tlb_mte_tagged(x) (typecheck_memtxattrs(x)->target_tlb_bit1) + +/* + * AArch64 usage of the PAGE_TARGET_* bits for linux-user. + */ +#define PAGE_BTI PAGE_TARGET_1 + /* * Naming convention for isar_feature functions: * Functions which test 32-bit ID registers should have _aa32_ in @@ -3414,6 +3479,12 @@ static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id) return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1; } +static inline bool isar_feature_aa32_lob(const ARMISARegisters *id) +{ + /* (M-profile) low-overhead loops and branch future */ + return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3; +} + static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id) { return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0; @@ -3479,14 +3550,19 @@ static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id) return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0; } +static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0; +} + static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id) { - /* - * This is a placeholder for use by VCMA until the rest of - * the ARMv8.2-FP16 extension is implemented for aa32 mode. - * At which point we can properly set and check MVFR1.FPHP. - */ - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1; + /* Sadly this is encoded differently for A-profile and M-profile */ + if (isar_feature_aa32_mprofile(id)) { + return FIELD_EX32(id->mvfr1, MVFR1, FP16) > 0; + } else { + return FIELD_EX32(id->mvfr1, MVFR1, FPHP) >= 3; + } } static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id) @@ -3585,6 +3661,11 @@ static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id) return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 4; } +static inline bool isar_feature_aa32_pxn(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_mmfr0, ID_MMFR0, VMSA) >= 4; +} + static inline bool isar_feature_aa32_pan(const ARMISARegisters *id) { return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) != 0; @@ -3814,6 +3895,16 @@ static inline bool isar_feature_aa64_bti(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0; } +static inline bool isar_feature_aa64_mte_insn_reg(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) != 0; +} + +static inline bool isar_feature_aa64_mte(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 2; +} + static inline bool isar_feature_aa64_pmu_8_1(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 4 && diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index cbc5c3868fce53c5f4906a4c4069c196ba7eaff5..649213082ff93a94b4df3d1f4453351ea3269221 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -108,8 +108,8 @@ static void aarch64_a57_initfn(Object *obj) cpu->isar.mvfr2 = 0x00000043; cpu->ctr = 0x8444c004; cpu->reset_sctlr = 0x00c50838; - cpu->id_pfr0 = 0x00000131; - cpu->id_pfr1 = 0x00011011; + cpu->isar.id_pfr0 = 0x00000131; + cpu->isar.id_pfr1 = 0x00011011; cpu->isar.id_dfr0 = 0x03010066; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x10101105; @@ -161,8 +161,8 @@ static void aarch64_a53_initfn(Object *obj) cpu->isar.mvfr2 = 0x00000043; cpu->ctr = 0x84448004; /* L1Ip = VIPT */ cpu->reset_sctlr = 0x00c50838; - cpu->id_pfr0 = 0x00000131; - cpu->id_pfr1 = 0x00011011; + cpu->isar.id_pfr0 = 0x00000131; + cpu->isar.id_pfr1 = 0x00011011; cpu->isar.id_dfr0 = 0x03010066; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x10101105; @@ -213,8 +213,8 @@ static void aarch64_a72_initfn(Object *obj) cpu->isar.mvfr2 = 0x00000043; cpu->ctr = 0x8444c004; cpu->reset_sctlr = 0x00c50838; - cpu->id_pfr0 = 0x00000131; - cpu->id_pfr1 = 0x00011011; + cpu->isar.id_pfr0 = 0x00000131; + cpu->isar.id_pfr1 = 0x00011011; cpu->isar.id_dfr0 = 0x03010066; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x10201105; @@ -266,7 +266,7 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) /* Collect the set of vector lengths supported by KVM. */ bitmap_zero(kvm_supported, ARM_MAX_VQ); - if (kvm_enabled() && kvm_arm_sve_supported(CPU(cpu))) { + if (kvm_enabled() && kvm_arm_sve_supported()) { kvm_arm_sve_get_vls(CPU(cpu), kvm_supported); } else if (kvm_enabled()) { assert(!cpu_isar_feature(aa64_sve, cpu)); @@ -464,16 +464,13 @@ static void cpu_max_set_sve_max_vq(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { ARMCPU *cpu = ARM_CPU(obj); - Error *err = NULL; uint32_t max_vq; - visit_type_uint32(v, name, &max_vq, &err); - if (err) { - error_propagate(errp, err); + if (!visit_type_uint32(v, name, &max_vq, errp)) { return; } - if (kvm_enabled() && !kvm_arm_sve_supported(CPU(cpu))) { + if (kvm_enabled() && !kvm_arm_sve_supported()) { error_setg(errp, "cannot set sve-max-vq"); error_append_hint(errp, "SVE not supported by KVM on this host\n"); return; @@ -510,16 +507,13 @@ static void cpu_arm_set_sve_vq(Object *obj, Visitor *v, const char *name, { ARMCPU *cpu = ARM_CPU(obj); uint32_t vq = atoi(&name[3]) / 128; - Error *err = NULL; bool value; - visit_type_bool(v, name, &value, &err); - if (err) { - error_propagate(errp, err); + if (!visit_type_bool(v, name, &value, errp)) { return; } - if (value && kvm_enabled() && !kvm_arm_sve_supported(CPU(cpu))) { + if (value && kvm_enabled() && !kvm_arm_sve_supported()) { error_setg(errp, "cannot enable %s", name); error_append_hint(errp, "SVE not supported by KVM on this host\n"); return; @@ -546,17 +540,14 @@ static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { ARMCPU *cpu = ARM_CPU(obj); - Error *err = NULL; bool value; uint64_t t; - visit_type_bool(v, name, &value, &err); - if (err) { - error_propagate(errp, err); + if (!visit_type_bool(v, name, &value, errp)) { return; } - if (value && kvm_enabled() && !kvm_arm_sve_supported(CPU(cpu))) { + if (value && kvm_enabled() && !kvm_arm_sve_supported()) { error_setg(errp, "'sve' feature not supported by KVM on this host"); return; } @@ -592,7 +583,6 @@ static void aarch64_max_initfn(Object *obj) if (kvm_enabled()) { kvm_arm_set_cpu_features_from_host(cpu); - kvm_arm_add_vcpu_properties(obj); } else { uint64_t t; uint32_t u; @@ -655,8 +645,18 @@ static void aarch64_max_initfn(Object *obj) t = cpu->isar.id_aa64pfr1; t = FIELD_DP64(t, ID_AA64PFR1, BT, 1); + /* + * Begin with full support for MTE. This will be downgraded to MTE=0 + * during realize if the board provides no tag memory, much like + * we do for EL2 with the virtualization=on property. + */ + t = FIELD_DP64(t, ID_AA64PFR1, MTE, 2); cpu->isar.id_aa64pfr1 = t; + t = cpu->isar.id_aa64mmfr0; + t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 5); /* PARange: 48 bits */ + cpu->isar.id_aa64mmfr0 = t; + t = cpu->isar.id_aa64mmfr1; t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */ t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1); @@ -708,12 +708,10 @@ static void aarch64_max_initfn(Object *obj) u = FIELD_DP32(u, ID_DFR0, PERFMON, 5); /* v8.4-PMU */ cpu->isar.id_dfr0 = u; - /* - * FIXME: We do not yet support ARMv8.2-fp16 for AArch32 yet, - * so do not set MVFR1.FPHP. Strictly speaking this is not legal, - * but it is also not legal to enable SVE without support for FP16, - * and enabling SVE in system mode is more useful in the short term. - */ + u = cpu->isar.mvfr1; + u = FIELD_DP32(u, MVFR1, FPHP, 3); /* v8.2-FP16 */ + u = FIELD_DP32(u, MVFR1, SIMDHP, 2); /* v8.2-FP16 */ + cpu->isar.mvfr1 = u; #ifdef CONFIG_USER_ONLY /* For usermode -cpu max we can use a larger and more efficient DCZ @@ -752,7 +750,7 @@ static void aarch64_cpu_set_aarch64(Object *obj, bool value, Error **errp) * uniform execution state like do_interrupt. */ if (value == false) { - if (!kvm_enabled() || !kvm_arm_aarch32_supported(CPU(cpu))) { + if (!kvm_enabled() || !kvm_arm_aarch32_supported()) { error_setg(errp, "'aarch64' feature cannot be disabled " "unless KVM is enabled and 32-bit EL1 " "is supported"); diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c index 00b0e08f33e15b3c69b0aaf354b7588138c7cce9..0013e25412f8943c4d9f052dcf1b53cd60297eb6 100644 --- a/target/arm/cpu_tcg.c +++ b/target/arm/cpu_tcg.c @@ -142,8 +142,8 @@ static void arm1136_r2_initfn(Object *obj) cpu->isar.mvfr1 = 0x00000000; cpu->ctr = 0x1dd20d2; cpu->reset_sctlr = 0x00050078; - cpu->id_pfr0 = 0x111; - cpu->id_pfr1 = 0x1; + cpu->isar.id_pfr0 = 0x111; + cpu->isar.id_pfr1 = 0x1; cpu->isar.id_dfr0 = 0x2; cpu->id_afr0 = 0x3; cpu->isar.id_mmfr0 = 0x01130003; @@ -173,8 +173,8 @@ static void arm1136_initfn(Object *obj) cpu->isar.mvfr1 = 0x00000000; cpu->ctr = 0x1dd20d2; cpu->reset_sctlr = 0x00050078; - cpu->id_pfr0 = 0x111; - cpu->id_pfr1 = 0x1; + cpu->isar.id_pfr0 = 0x111; + cpu->isar.id_pfr1 = 0x1; cpu->isar.id_dfr0 = 0x2; cpu->id_afr0 = 0x3; cpu->isar.id_mmfr0 = 0x01130003; @@ -205,8 +205,8 @@ static void arm1176_initfn(Object *obj) cpu->isar.mvfr1 = 0x00000000; cpu->ctr = 0x1dd20d2; cpu->reset_sctlr = 0x00050078; - cpu->id_pfr0 = 0x111; - cpu->id_pfr1 = 0x11; + cpu->isar.id_pfr0 = 0x111; + cpu->isar.id_pfr1 = 0x11; cpu->isar.id_dfr0 = 0x33; cpu->id_afr0 = 0; cpu->isar.id_mmfr0 = 0x01130003; @@ -234,8 +234,8 @@ static void arm11mpcore_initfn(Object *obj) cpu->isar.mvfr0 = 0x11111111; cpu->isar.mvfr1 = 0x00000000; cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */ - cpu->id_pfr0 = 0x111; - cpu->id_pfr1 = 0x1; + cpu->isar.id_pfr0 = 0x111; + cpu->isar.id_pfr1 = 0x1; cpu->isar.id_dfr0 = 0; cpu->id_afr0 = 0x2; cpu->isar.id_mmfr0 = 0x01100103; @@ -256,6 +256,30 @@ static void cortex_m0_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_M); cpu->midr = 0x410cc200; + + /* + * These ID register values are not guest visible, because + * we do not implement the Main Extension. They must be set + * to values corresponding to the Cortex-M0's implemented + * features, because QEMU generally controls its emulation + * by looking at ID register fields. We use the same values as + * for the M3. + */ + cpu->isar.id_pfr0 = 0x00000030; + cpu->isar.id_pfr1 = 0x00000200; + cpu->isar.id_dfr0 = 0x00100000; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x00000030; + cpu->isar.id_mmfr1 = 0x00000000; + cpu->isar.id_mmfr2 = 0x00000000; + cpu->isar.id_mmfr3 = 0x00000000; + cpu->isar.id_isar0 = 0x01141110; + cpu->isar.id_isar1 = 0x02111000; + cpu->isar.id_isar2 = 0x21112231; + cpu->isar.id_isar3 = 0x01111110; + cpu->isar.id_isar4 = 0x01310102; + cpu->isar.id_isar5 = 0x00000000; + cpu->isar.id_isar6 = 0x00000000; } static void cortex_m3_initfn(Object *obj) @@ -266,8 +290,8 @@ static void cortex_m3_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_M_MAIN); cpu->midr = 0x410fc231; cpu->pmsav7_dregion = 8; - cpu->id_pfr0 = 0x00000030; - cpu->id_pfr1 = 0x00000200; + cpu->isar.id_pfr0 = 0x00000030; + cpu->isar.id_pfr1 = 0x00000200; cpu->isar.id_dfr0 = 0x00100000; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x00000030; @@ -296,8 +320,8 @@ static void cortex_m4_initfn(Object *obj) cpu->isar.mvfr0 = 0x10110021; cpu->isar.mvfr1 = 0x11000011; cpu->isar.mvfr2 = 0x00000000; - cpu->id_pfr0 = 0x00000030; - cpu->id_pfr1 = 0x00000200; + cpu->isar.id_pfr0 = 0x00000030; + cpu->isar.id_pfr1 = 0x00000200; cpu->isar.id_dfr0 = 0x00100000; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x00000030; @@ -326,8 +350,8 @@ static void cortex_m7_initfn(Object *obj) cpu->isar.mvfr0 = 0x10110221; cpu->isar.mvfr1 = 0x12000011; cpu->isar.mvfr2 = 0x00000040; - cpu->id_pfr0 = 0x00000030; - cpu->id_pfr1 = 0x00000200; + cpu->isar.id_pfr0 = 0x00000030; + cpu->isar.id_pfr1 = 0x00000200; cpu->isar.id_dfr0 = 0x00100000; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x00100030; @@ -358,8 +382,8 @@ static void cortex_m33_initfn(Object *obj) cpu->isar.mvfr0 = 0x10110021; cpu->isar.mvfr1 = 0x11000011; cpu->isar.mvfr2 = 0x00000040; - cpu->id_pfr0 = 0x00000030; - cpu->id_pfr1 = 0x00000210; + cpu->isar.id_pfr0 = 0x00000030; + cpu->isar.id_pfr1 = 0x00000210; cpu->isar.id_dfr0 = 0x00200000; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x00101F40; @@ -397,8 +421,8 @@ static void cortex_r5_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_PMSA); set_feature(&cpu->env, ARM_FEATURE_PMU); cpu->midr = 0x411fc153; /* r1p3 */ - cpu->id_pfr0 = 0x0131; - cpu->id_pfr1 = 0x001; + cpu->isar.id_pfr0 = 0x0131; + cpu->isar.id_pfr1 = 0x001; cpu->isar.id_dfr0 = 0x010400; cpu->id_afr0 = 0x0; cpu->isar.id_mmfr0 = 0x0210030; diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c index f800266727525911a2742c96c982d9b4a70dc2d8..28a84c2dbdb6e82eeb071c76a0662a3db33e04db 100644 --- a/target/arm/crypto_helper.c +++ b/target/arm/crypto_helper.c @@ -6,14 +6,16 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. */ #include "qemu/osdep.h" #include "cpu.h" #include "exec/helper-proto.h" +#include "tcg/tcg-gvec-desc.h" #include "crypto/aes.h" +#include "vec_internal.h" union CRYPTO_STATE { uint8_t bytes[16]; @@ -22,25 +24,35 @@ union CRYPTO_STATE { }; #ifdef HOST_WORDS_BIGENDIAN -#define CR_ST_BYTE(state, i) (state.bytes[(15 - (i)) ^ 8]) -#define CR_ST_WORD(state, i) (state.words[(3 - (i)) ^ 2]) +#define CR_ST_BYTE(state, i) ((state).bytes[(15 - (i)) ^ 8]) +#define CR_ST_WORD(state, i) ((state).words[(3 - (i)) ^ 2]) #else -#define CR_ST_BYTE(state, i) (state.bytes[i]) -#define CR_ST_WORD(state, i) (state.words[i]) +#define CR_ST_BYTE(state, i) ((state).bytes[i]) +#define CR_ST_WORD(state, i) ((state).words[i]) #endif -void HELPER(crypto_aese)(void *vd, void *vm, uint32_t decrypt) +/* + * The caller has not been converted to full gvec, and so only + * modifies the low 16 bytes of the vector register. + */ +static void clear_tail_16(void *vd, uint32_t desc) +{ + int opr_sz = simd_oprsz(desc); + int max_sz = simd_maxsz(desc); + + assert(opr_sz == 16); + clear_tail(vd, opr_sz, max_sz); +} + +static void do_crypto_aese(uint64_t *rd, uint64_t *rn, + uint64_t *rm, bool decrypt) { static uint8_t const * const sbox[2] = { AES_sbox, AES_isbox }; static uint8_t const * const shift[2] = { AES_shifts, AES_ishifts }; - uint64_t *rd = vd; - uint64_t *rm = vm; union CRYPTO_STATE rk = { .l = { rm[0], rm[1] } }; - union CRYPTO_STATE st = { .l = { rd[0], rd[1] } }; + union CRYPTO_STATE st = { .l = { rn[0], rn[1] } }; int i; - assert(decrypt < 2); - /* xor state vector with round key */ rk.l[0] ^= st.l[0]; rk.l[1] ^= st.l[1]; @@ -54,7 +66,18 @@ void HELPER(crypto_aese)(void *vd, void *vm, uint32_t decrypt) rd[1] = st.l[1]; } -void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t decrypt) +void HELPER(crypto_aese)(void *vd, void *vn, void *vm, uint32_t desc) +{ + intptr_t i, opr_sz = simd_oprsz(desc); + bool decrypt = simd_data(desc); + + for (i = 0; i < opr_sz; i += 16) { + do_crypto_aese(vd + i, vn + i, vm + i, decrypt); + } + clear_tail(vd, opr_sz, simd_maxsz(desc)); +} + +static void do_crypto_aesmc(uint64_t *rd, uint64_t *rm, bool decrypt) { static uint32_t const mc[][256] = { { /* MixColumns lookup table */ @@ -190,13 +213,9 @@ void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t decrypt) 0xbe805d9f, 0xb58d5491, 0xa89a4f83, 0xa397468d, } }; - uint64_t *rd = vd; - uint64_t *rm = vm; union CRYPTO_STATE st = { .l = { rm[0], rm[1] } }; int i; - assert(decrypt < 2); - for (i = 0; i < 16; i += 4) { CR_ST_WORD(st, i >> 2) = mc[decrypt][CR_ST_BYTE(st, i)] ^ @@ -209,6 +228,17 @@ void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t decrypt) rd[1] = st.l[1]; } +void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t desc) +{ + intptr_t i, opr_sz = simd_oprsz(desc); + bool decrypt = simd_data(desc); + + for (i = 0; i < opr_sz; i += 16) { + do_crypto_aesmc(vd + i, vm + i, decrypt); + } + clear_tail(vd, opr_sz, simd_maxsz(desc)); +} + /* * SHA-1 logical functions */ @@ -228,52 +258,77 @@ static uint32_t maj(uint32_t x, uint32_t y, uint32_t z) return (x & y) | ((x | y) & z); } -void HELPER(crypto_sha1_3reg)(void *vd, void *vn, void *vm, uint32_t op) +void HELPER(crypto_sha1su0)(void *vd, void *vn, void *vm, uint32_t desc) +{ + uint64_t *d = vd, *n = vn, *m = vm; + uint64_t d0, d1; + + d0 = d[1] ^ d[0] ^ m[0]; + d1 = n[0] ^ d[1] ^ m[1]; + d[0] = d0; + d[1] = d1; + + clear_tail_16(vd, desc); +} + +static inline void crypto_sha1_3reg(uint64_t *rd, uint64_t *rn, + uint64_t *rm, uint32_t desc, + uint32_t (*fn)(union CRYPTO_STATE *d)) { - uint64_t *rd = vd; - uint64_t *rn = vn; - uint64_t *rm = vm; union CRYPTO_STATE d = { .l = { rd[0], rd[1] } }; union CRYPTO_STATE n = { .l = { rn[0], rn[1] } }; union CRYPTO_STATE m = { .l = { rm[0], rm[1] } }; + int i; - if (op == 3) { /* sha1su0 */ - d.l[0] ^= d.l[1] ^ m.l[0]; - d.l[1] ^= n.l[0] ^ m.l[1]; - } else { - int i; - - for (i = 0; i < 4; i++) { - uint32_t t; - - switch (op) { - case 0: /* sha1c */ - t = cho(CR_ST_WORD(d, 1), CR_ST_WORD(d, 2), CR_ST_WORD(d, 3)); - break; - case 1: /* sha1p */ - t = par(CR_ST_WORD(d, 1), CR_ST_WORD(d, 2), CR_ST_WORD(d, 3)); - break; - case 2: /* sha1m */ - t = maj(CR_ST_WORD(d, 1), CR_ST_WORD(d, 2), CR_ST_WORD(d, 3)); - break; - default: - g_assert_not_reached(); - } - t += rol32(CR_ST_WORD(d, 0), 5) + CR_ST_WORD(n, 0) - + CR_ST_WORD(m, i); - - CR_ST_WORD(n, 0) = CR_ST_WORD(d, 3); - CR_ST_WORD(d, 3) = CR_ST_WORD(d, 2); - CR_ST_WORD(d, 2) = ror32(CR_ST_WORD(d, 1), 2); - CR_ST_WORD(d, 1) = CR_ST_WORD(d, 0); - CR_ST_WORD(d, 0) = t; - } + for (i = 0; i < 4; i++) { + uint32_t t = fn(&d); + + t += rol32(CR_ST_WORD(d, 0), 5) + CR_ST_WORD(n, 0) + + CR_ST_WORD(m, i); + + CR_ST_WORD(n, 0) = CR_ST_WORD(d, 3); + CR_ST_WORD(d, 3) = CR_ST_WORD(d, 2); + CR_ST_WORD(d, 2) = ror32(CR_ST_WORD(d, 1), 2); + CR_ST_WORD(d, 1) = CR_ST_WORD(d, 0); + CR_ST_WORD(d, 0) = t; } rd[0] = d.l[0]; rd[1] = d.l[1]; + + clear_tail_16(rd, desc); +} + +static uint32_t do_sha1c(union CRYPTO_STATE *d) +{ + return cho(CR_ST_WORD(*d, 1), CR_ST_WORD(*d, 2), CR_ST_WORD(*d, 3)); +} + +void HELPER(crypto_sha1c)(void *vd, void *vn, void *vm, uint32_t desc) +{ + crypto_sha1_3reg(vd, vn, vm, desc, do_sha1c); +} + +static uint32_t do_sha1p(union CRYPTO_STATE *d) +{ + return par(CR_ST_WORD(*d, 1), CR_ST_WORD(*d, 2), CR_ST_WORD(*d, 3)); +} + +void HELPER(crypto_sha1p)(void *vd, void *vn, void *vm, uint32_t desc) +{ + crypto_sha1_3reg(vd, vn, vm, desc, do_sha1p); } -void HELPER(crypto_sha1h)(void *vd, void *vm) +static uint32_t do_sha1m(union CRYPTO_STATE *d) +{ + return maj(CR_ST_WORD(*d, 1), CR_ST_WORD(*d, 2), CR_ST_WORD(*d, 3)); +} + +void HELPER(crypto_sha1m)(void *vd, void *vn, void *vm, uint32_t desc) +{ + crypto_sha1_3reg(vd, vn, vm, desc, do_sha1m); +} + +void HELPER(crypto_sha1h)(void *vd, void *vm, uint32_t desc) { uint64_t *rd = vd; uint64_t *rm = vm; @@ -284,9 +339,11 @@ void HELPER(crypto_sha1h)(void *vd, void *vm) rd[0] = m.l[0]; rd[1] = m.l[1]; + + clear_tail_16(vd, desc); } -void HELPER(crypto_sha1su1)(void *vd, void *vm) +void HELPER(crypto_sha1su1)(void *vd, void *vm, uint32_t desc) { uint64_t *rd = vd; uint64_t *rm = vm; @@ -300,6 +357,8 @@ void HELPER(crypto_sha1su1)(void *vd, void *vm) rd[0] = d.l[0]; rd[1] = d.l[1]; + + clear_tail_16(vd, desc); } /* @@ -327,7 +386,7 @@ static uint32_t s1(uint32_t x) return ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10); } -void HELPER(crypto_sha256h)(void *vd, void *vn, void *vm) +void HELPER(crypto_sha256h)(void *vd, void *vn, void *vm, uint32_t desc) { uint64_t *rd = vd; uint64_t *rn = vn; @@ -358,9 +417,11 @@ void HELPER(crypto_sha256h)(void *vd, void *vn, void *vm) rd[0] = d.l[0]; rd[1] = d.l[1]; + + clear_tail_16(vd, desc); } -void HELPER(crypto_sha256h2)(void *vd, void *vn, void *vm) +void HELPER(crypto_sha256h2)(void *vd, void *vn, void *vm, uint32_t desc) { uint64_t *rd = vd; uint64_t *rn = vn; @@ -383,9 +444,11 @@ void HELPER(crypto_sha256h2)(void *vd, void *vn, void *vm) rd[0] = d.l[0]; rd[1] = d.l[1]; + + clear_tail_16(vd, desc); } -void HELPER(crypto_sha256su0)(void *vd, void *vm) +void HELPER(crypto_sha256su0)(void *vd, void *vm, uint32_t desc) { uint64_t *rd = vd; uint64_t *rm = vm; @@ -399,9 +462,11 @@ void HELPER(crypto_sha256su0)(void *vd, void *vm) rd[0] = d.l[0]; rd[1] = d.l[1]; + + clear_tail_16(vd, desc); } -void HELPER(crypto_sha256su1)(void *vd, void *vn, void *vm) +void HELPER(crypto_sha256su1)(void *vd, void *vn, void *vm, uint32_t desc) { uint64_t *rd = vd; uint64_t *rn = vn; @@ -417,6 +482,8 @@ void HELPER(crypto_sha256su1)(void *vd, void *vn, void *vm) rd[0] = d.l[0]; rd[1] = d.l[1]; + + clear_tail_16(vd, desc); } /* @@ -453,7 +520,7 @@ static uint64_t s1_512(uint64_t x) return ror64(x, 19) ^ ror64(x, 61) ^ (x >> 6); } -void HELPER(crypto_sha512h)(void *vd, void *vn, void *vm) +void HELPER(crypto_sha512h)(void *vd, void *vn, void *vm, uint32_t desc) { uint64_t *rd = vd; uint64_t *rn = vn; @@ -466,9 +533,11 @@ void HELPER(crypto_sha512h)(void *vd, void *vn, void *vm) rd[0] = d0; rd[1] = d1; + + clear_tail_16(vd, desc); } -void HELPER(crypto_sha512h2)(void *vd, void *vn, void *vm) +void HELPER(crypto_sha512h2)(void *vd, void *vn, void *vm, uint32_t desc) { uint64_t *rd = vd; uint64_t *rn = vn; @@ -481,9 +550,11 @@ void HELPER(crypto_sha512h2)(void *vd, void *vn, void *vm) rd[0] = d0; rd[1] = d1; + + clear_tail_16(vd, desc); } -void HELPER(crypto_sha512su0)(void *vd, void *vn) +void HELPER(crypto_sha512su0)(void *vd, void *vn, uint32_t desc) { uint64_t *rd = vd; uint64_t *rn = vn; @@ -495,9 +566,11 @@ void HELPER(crypto_sha512su0)(void *vd, void *vn) rd[0] = d0; rd[1] = d1; + + clear_tail_16(vd, desc); } -void HELPER(crypto_sha512su1)(void *vd, void *vn, void *vm) +void HELPER(crypto_sha512su1)(void *vd, void *vn, void *vm, uint32_t desc) { uint64_t *rd = vd; uint64_t *rn = vn; @@ -505,9 +578,11 @@ void HELPER(crypto_sha512su1)(void *vd, void *vn, void *vm) rd[0] += s1_512(rn[0]) + rm[0]; rd[1] += s1_512(rn[1]) + rm[1]; + + clear_tail_16(vd, desc); } -void HELPER(crypto_sm3partw1)(void *vd, void *vn, void *vm) +void HELPER(crypto_sm3partw1)(void *vd, void *vn, void *vm, uint32_t desc) { uint64_t *rd = vd; uint64_t *rn = vn; @@ -531,9 +606,11 @@ void HELPER(crypto_sm3partw1)(void *vd, void *vn, void *vm) rd[0] = d.l[0]; rd[1] = d.l[1]; + + clear_tail_16(vd, desc); } -void HELPER(crypto_sm3partw2)(void *vd, void *vn, void *vm) +void HELPER(crypto_sm3partw2)(void *vd, void *vn, void *vm, uint32_t desc) { uint64_t *rd = vd; uint64_t *rn = vn; @@ -551,17 +628,18 @@ void HELPER(crypto_sm3partw2)(void *vd, void *vn, void *vm) rd[0] = d.l[0]; rd[1] = d.l[1]; + + clear_tail_16(vd, desc); } -void HELPER(crypto_sm3tt)(void *vd, void *vn, void *vm, uint32_t imm2, - uint32_t opcode) +static inline void QEMU_ALWAYS_INLINE +crypto_sm3tt(uint64_t *rd, uint64_t *rn, uint64_t *rm, + uint32_t desc, uint32_t opcode) { - uint64_t *rd = vd; - uint64_t *rn = vn; - uint64_t *rm = vm; union CRYPTO_STATE d = { .l = { rd[0], rd[1] } }; union CRYPTO_STATE n = { .l = { rn[0], rn[1] } }; union CRYPTO_STATE m = { .l = { rm[0], rm[1] } }; + uint32_t imm2 = simd_data(desc); uint32_t t; assert(imm2 < 4); @@ -576,7 +654,7 @@ void HELPER(crypto_sm3tt)(void *vd, void *vn, void *vm, uint32_t imm2, /* SM3TT2B */ t = cho(CR_ST_WORD(d, 3), CR_ST_WORD(d, 2), CR_ST_WORD(d, 1)); } else { - g_assert_not_reached(); + qemu_build_not_reached(); } t += CR_ST_WORD(d, 0) + CR_ST_WORD(m, imm2); @@ -601,8 +679,21 @@ void HELPER(crypto_sm3tt)(void *vd, void *vn, void *vm, uint32_t imm2, rd[0] = d.l[0]; rd[1] = d.l[1]; + + clear_tail_16(rd, desc); } +#define DO_SM3TT(NAME, OPCODE) \ + void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \ + { crypto_sm3tt(vd, vn, vm, desc, OPCODE); } + +DO_SM3TT(crypto_sm3tt1a, 0) +DO_SM3TT(crypto_sm3tt1b, 1) +DO_SM3TT(crypto_sm3tt2a, 2) +DO_SM3TT(crypto_sm3tt2b, 3) + +#undef DO_SM3TT + static uint8_t const sm4_sbox[] = { 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, @@ -638,12 +729,10 @@ static uint8_t const sm4_sbox[] = { 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48, }; -void HELPER(crypto_sm4e)(void *vd, void *vn) +static void do_crypto_sm4e(uint64_t *rd, uint64_t *rn, uint64_t *rm) { - uint64_t *rd = vd; - uint64_t *rn = vn; - union CRYPTO_STATE d = { .l = { rd[0], rd[1] } }; - union CRYPTO_STATE n = { .l = { rn[0], rn[1] } }; + union CRYPTO_STATE d = { .l = { rn[0], rn[1] } }; + union CRYPTO_STATE n = { .l = { rm[0], rm[1] } }; uint32_t t, i; for (i = 0; i < 4; i++) { @@ -665,11 +754,18 @@ void HELPER(crypto_sm4e)(void *vd, void *vn) rd[1] = d.l[1]; } -void HELPER(crypto_sm4ekey)(void *vd, void *vn, void* vm) +void HELPER(crypto_sm4e)(void *vd, void *vn, void *vm, uint32_t desc) +{ + intptr_t i, opr_sz = simd_oprsz(desc); + + for (i = 0; i < opr_sz; i += 16) { + do_crypto_sm4e(vd + i, vn + i, vm + i); + } + clear_tail(vd, opr_sz, simd_maxsz(desc)); +} + +static void do_crypto_sm4ekey(uint64_t *rd, uint64_t *rn, uint64_t *rm) { - uint64_t *rd = vd; - uint64_t *rn = vn; - uint64_t *rm = vm; union CRYPTO_STATE d; union CRYPTO_STATE n = { .l = { rn[0], rn[1] } }; union CRYPTO_STATE m = { .l = { rm[0], rm[1] } }; @@ -693,3 +789,24 @@ void HELPER(crypto_sm4ekey)(void *vd, void *vn, void* vm) rd[0] = d.l[0]; rd[1] = d.l[1]; } + +void HELPER(crypto_sm4ekey)(void *vd, void *vn, void* vm, uint32_t desc) +{ + intptr_t i, opr_sz = simd_oprsz(desc); + + for (i = 0; i < opr_sz; i += 16) { + do_crypto_sm4ekey(vd + i, vn + i, vm + i); + } + clear_tail(vd, opr_sz, simd_maxsz(desc)); +} + +void HELPER(crypto_rax1)(void *vd, void *vn, void *vm, uint32_t desc) +{ + intptr_t i, opr_sz = simd_oprsz(desc); + uint64_t *d = vd, *n = vn, *m = vm; + + for (i = 0; i < opr_sz / 8; ++i) { + d[i] = n[i] ^ rol64(m[i], 1); + } + clear_tail(vd, opr_sz, simd_maxsz(desc)); +} diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c index ecfa88f8e605e0f24fee2a46786fe4f0f2d26976..866595b4f152878c00468862110d3fda73212d44 100644 --- a/target/arm/gdbstub.c +++ b/target/arm/gdbstub.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c index 35d0b80c2dee0ddb2391b264c43fac552dd5feb1..251539ef7997eb8c6e039c750d461ba1d80bd004 100644 --- a/target/arm/gdbstub64.c +++ b/target/arm/gdbstub64.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c index bc0649a44aac17c44f695f848d21901e79901ee1..30b2ad119f3ee9fe85f952daf4c36aa410219262 100644 --- a/target/arm/helper-a64.c +++ b/target/arm/helper-a64.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -234,17 +234,6 @@ uint64_t HELPER(neon_cgt_f64)(float64 a, float64 b, void *fpstp) * versions, these do a fully fused multiply-add or * multiply-add-and-halve. */ -#define float16_two make_float16(0x4000) -#define float16_three make_float16(0x4200) -#define float16_one_point_five make_float16(0x3e00) - -#define float32_two make_float32(0x40000000) -#define float32_three make_float32(0x40400000) -#define float32_one_point_five make_float32(0x3fc00000) - -#define float64_two make_float64(0x4000000000000000ULL) -#define float64_three make_float64(0x4008000000000000ULL) -#define float64_one_point_five make_float64(0x3FF8000000000000ULL) uint32_t HELPER(recpsf_f16)(uint32_t a, uint32_t b, void *fpstp) { @@ -1119,85 +1108,41 @@ void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in) * (which matches the usual QEMU behaviour of not implementing either * alignment faults or any memory attribute handling). */ - - ARMCPU *cpu = env_archcpu(env); - uint64_t blocklen = 4 << cpu->dcz_blocksize; + int blocklen = 4 << env_archcpu(env)->dcz_blocksize; uint64_t vaddr = vaddr_in & ~(blocklen - 1); + int mmu_idx = cpu_mmu_index(env, false); + void *mem; + + /* + * Trapless lookup. In addition to actual invalid page, may + * return NULL for I/O, watchpoints, clean pages, etc. + */ + mem = tlb_vaddr_to_host(env, vaddr, MMU_DATA_STORE, mmu_idx); #ifndef CONFIG_USER_ONLY - { + if (unlikely(!mem)) { + uintptr_t ra = GETPC(); + /* - * Slightly awkwardly, QEMU's TARGET_PAGE_SIZE may be less than - * the block size so we might have to do more than one TLB lookup. - * We know that in fact for any v8 CPU the page size is at least 4K - * and the block size must be 2K or less, but TARGET_PAGE_SIZE is only - * 1K as an artefact of legacy v5 subpage support being present in the - * same QEMU executable. So in practice the hostaddr[] array has - * two entries, given the current setting of TARGET_PAGE_BITS_MIN. + * Trap if accessing an invalid page. DC_ZVA requires that we supply + * the original pointer for an invalid page. But watchpoints require + * that we probe the actual space. So do both. */ - int maxidx = DIV_ROUND_UP(blocklen, TARGET_PAGE_SIZE); - void *hostaddr[DIV_ROUND_UP(2 * KiB, 1 << TARGET_PAGE_BITS_MIN)]; - int try, i; - unsigned mmu_idx = cpu_mmu_index(env, false); - TCGMemOpIdx oi = make_memop_idx(MO_UB, mmu_idx); - - assert(maxidx <= ARRAY_SIZE(hostaddr)); - - for (try = 0; try < 2; try++) { - - for (i = 0; i < maxidx; i++) { - hostaddr[i] = tlb_vaddr_to_host(env, - vaddr + TARGET_PAGE_SIZE * i, - 1, mmu_idx); - if (!hostaddr[i]) { - break; - } - } - if (i == maxidx) { - /* - * If it's all in the TLB it's fair game for just writing to; - * we know we don't need to update dirty status, etc. - */ - for (i = 0; i < maxidx - 1; i++) { - memset(hostaddr[i], 0, TARGET_PAGE_SIZE); - } - memset(hostaddr[i], 0, blocklen - (i * TARGET_PAGE_SIZE)); - return; - } + (void) probe_write(env, vaddr_in, 1, mmu_idx, ra); + mem = probe_write(env, vaddr, blocklen, mmu_idx, ra); + + if (unlikely(!mem)) { /* - * OK, try a store and see if we can populate the tlb. This - * might cause an exception if the memory isn't writable, - * in which case we will longjmp out of here. We must for - * this purpose use the actual register value passed to us - * so that we get the fault address right. + * The only remaining reason for mem == NULL is I/O. + * Just do a series of byte writes as the architecture demands. */ - helper_ret_stb_mmu(env, vaddr_in, 0, oi, GETPC()); - /* Now we can populate the other TLB entries, if any */ - for (i = 0; i < maxidx; i++) { - uint64_t va = vaddr + TARGET_PAGE_SIZE * i; - if (va != (vaddr_in & TARGET_PAGE_MASK)) { - helper_ret_stb_mmu(env, va, 0, oi, GETPC()); - } + for (int i = 0; i < blocklen; i++) { + cpu_stb_mmuidx_ra(env, vaddr + i, 0, mmu_idx, ra); } - } - - /* - * Slow path (probably attempt to do this to an I/O device or - * similar, or clearing of a block of code we have translations - * cached for). Just do a series of byte writes as the architecture - * demands. It's not worth trying to use a cpu_physical_memory_map(), - * memset(), unmap() sequence here because: - * + we'd need to account for the blocksize being larger than a page - * + the direct-RAM access case is almost always going to be dealt - * with in the fastpath code above, so there's no speed benefit - * + we would have to deal with the map returning NULL because the - * bounce buffer was in use - */ - for (i = 0; i < blocklen; i++) { - helper_ret_stb_mmu(env, vaddr + i, 0, oi, GETPC()); + return; } } -#else - memset(g2h(vaddr), 0, blocklen); #endif + + memset(mem, 0, blocklen); } diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h index 3df7c185aa1df67fe087d8dc34d752bd01902c5f..7bd6aed659bbe03de5671f2d57ff6525ef191379 100644 --- a/target/arm/helper-a64.h +++ b/target/arm/helper-a64.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -103,3 +103,19 @@ DEF_HELPER_FLAGS_3(autda, TCG_CALL_NO_WG, i64, env, i64, i64) DEF_HELPER_FLAGS_3(autdb, TCG_CALL_NO_WG, i64, env, i64, i64) DEF_HELPER_FLAGS_2(xpaci, TCG_CALL_NO_RWG_SE, i64, env, i64) DEF_HELPER_FLAGS_2(xpacd, TCG_CALL_NO_RWG_SE, i64, env, i64) + +DEF_HELPER_FLAGS_3(mte_check1, TCG_CALL_NO_WG, i64, env, i32, i64) +DEF_HELPER_FLAGS_3(mte_checkN, TCG_CALL_NO_WG, i64, env, i32, i64) +DEF_HELPER_FLAGS_3(mte_check_zva, TCG_CALL_NO_WG, i64, env, i32, i64) +DEF_HELPER_FLAGS_3(irg, TCG_CALL_NO_RWG, i64, env, i64, i64) +DEF_HELPER_FLAGS_4(addsubg, TCG_CALL_NO_RWG_SE, i64, env, i64, s32, i32) +DEF_HELPER_FLAGS_3(ldg, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(stg, TCG_CALL_NO_WG, void, env, i64, i64) +DEF_HELPER_FLAGS_3(stg_parallel, TCG_CALL_NO_WG, void, env, i64, i64) +DEF_HELPER_FLAGS_2(stg_stub, TCG_CALL_NO_WG, void, env, i64) +DEF_HELPER_FLAGS_3(st2g, TCG_CALL_NO_WG, void, env, i64, i64) +DEF_HELPER_FLAGS_3(st2g_parallel, TCG_CALL_NO_WG, void, env, i64, i64) +DEF_HELPER_FLAGS_2(st2g_stub, TCG_CALL_NO_WG, void, env, i64) +DEF_HELPER_FLAGS_2(ldgm, TCG_CALL_NO_WG, i64, env, i64) +DEF_HELPER_FLAGS_3(stgm, TCG_CALL_NO_WG, void, env, i64, i64) +DEF_HELPER_FLAGS_3(stzgm_tags, TCG_CALL_NO_WG, void, env, i64, i64) diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h index 7a200755ace1965a6ebd788b02f8f42a1a7852a5..e4cadd2a65b629b42a8fc3f56e3f81d2e1201d08 100644 --- a/target/arm/helper-sve.h +++ b/target/arm/helper-sve.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -269,11 +269,6 @@ DEF_HELPER_FLAGS_3(sve_uminv_h, TCG_CALL_NO_RWG, i64, ptr, ptr, i32) DEF_HELPER_FLAGS_3(sve_uminv_s, TCG_CALL_NO_RWG, i64, ptr, ptr, i32) DEF_HELPER_FLAGS_3(sve_uminv_d, TCG_CALL_NO_RWG, i64, ptr, ptr, i32) -DEF_HELPER_FLAGS_3(sve_clr_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32) -DEF_HELPER_FLAGS_3(sve_clr_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) -DEF_HELPER_FLAGS_3(sve_clr_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32) -DEF_HELPER_FLAGS_3(sve_clr_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32) - DEF_HELPER_FLAGS_4(sve_movz_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(sve_movz_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(sve_movz_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) @@ -1196,6 +1191,64 @@ DEF_HELPER_FLAGS_4(sve_ld1sds_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) DEF_HELPER_FLAGS_4(sve_ld1sdu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) DEF_HELPER_FLAGS_4(sve_ld1sds_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld1bb_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld2bb_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld3bb_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld4bb_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ld1hh_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld2hh_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld3hh_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld4hh_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ld1hh_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld2hh_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld3hh_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld4hh_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ld1ss_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld2ss_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld3ss_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld4ss_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ld1ss_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld2ss_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld3ss_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld4ss_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ld1dd_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld2dd_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld3dd_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld4dd_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ld1dd_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld2dd_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld3dd_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld4dd_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ld1bhu_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld1bsu_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld1bdu_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld1bhs_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld1bss_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld1bds_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ld1hsu_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld1hdu_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld1hss_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld1hds_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ld1hsu_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld1hdu_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld1hss_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld1hds_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ld1sdu_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld1sds_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ld1sdu_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ld1sds_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + DEF_HELPER_FLAGS_4(sve_ldff1bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) DEF_HELPER_FLAGS_4(sve_ldff1bhu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) DEF_HELPER_FLAGS_4(sve_ldff1bsu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) @@ -1227,6 +1280,55 @@ DEF_HELPER_FLAGS_4(sve_ldff1sds_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) DEF_HELPER_FLAGS_4(sve_ldff1dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) DEF_HELPER_FLAGS_4(sve_ldff1dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1bb_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1bhu_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1bsu_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1bdu_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1bhs_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1bss_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1bds_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ldff1hh_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1hsu_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1hdu_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1hss_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1hds_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ldff1hh_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1hsu_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1hdu_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1hss_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1hds_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ldff1ss_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1sdu_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1sds_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ldff1ss_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1sdu_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1sds_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ldff1dd_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldff1dd_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) + DEF_HELPER_FLAGS_4(sve_ldnf1bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) DEF_HELPER_FLAGS_4(sve_ldnf1bhu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) DEF_HELPER_FLAGS_4(sve_ldnf1bsu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) @@ -1258,6 +1360,55 @@ DEF_HELPER_FLAGS_4(sve_ldnf1sds_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) DEF_HELPER_FLAGS_4(sve_ldnf1dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) DEF_HELPER_FLAGS_4(sve_ldnf1dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1bb_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1bhu_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1bsu_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1bdu_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1bhs_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1bss_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1bds_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ldnf1hh_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1hsu_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1hdu_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1hss_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1hds_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ldnf1hh_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1hsu_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1hdu_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1hss_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1hds_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ldnf1ss_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1sdu_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1sds_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ldnf1ss_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1sdu_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1sds_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_ldnf1dd_le_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_ldnf1dd_be_r_mte, TCG_CALL_NO_WG, + void, env, ptr, tl, i32) + DEF_HELPER_FLAGS_4(sve_st1bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) DEF_HELPER_FLAGS_4(sve_st2bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) DEF_HELPER_FLAGS_4(sve_st3bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) @@ -1305,6 +1456,53 @@ DEF_HELPER_FLAGS_4(sve_st1hd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) DEF_HELPER_FLAGS_4(sve_st1sd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) DEF_HELPER_FLAGS_4(sve_st1sd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st1bb_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st2bb_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st3bb_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st4bb_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_st1hh_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st2hh_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st3hh_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st4hh_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_st1hh_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st2hh_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st3hh_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st4hh_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_st1ss_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st2ss_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st3ss_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st4ss_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_st1ss_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st2ss_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st3ss_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st4ss_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_st1dd_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st2dd_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st3dd_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st4dd_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_st1dd_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st2dd_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st3dd_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st4dd_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_st1bh_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st1bs_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st1bd_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_st1hs_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st1hd_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st1hs_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st1hd_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + +DEF_HELPER_FLAGS_4(sve_st1sd_le_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) +DEF_HELPER_FLAGS_4(sve_st1sd_be_r_mte, TCG_CALL_NO_WG, void, env, ptr, tl, i32) + DEF_HELPER_FLAGS_6(sve_ldbsu_zsu, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr, tl, i32) DEF_HELPER_FLAGS_6(sve_ldhsu_le_zsu, TCG_CALL_NO_WG, @@ -1414,6 +1612,115 @@ DEF_HELPER_FLAGS_6(sve_ldsds_le_zd, TCG_CALL_NO_WG, DEF_HELPER_FLAGS_6(sve_ldsds_be_zd, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldbsu_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhsu_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhsu_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldss_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldss_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldbss_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhss_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhss_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) + +DEF_HELPER_FLAGS_6(sve_ldbsu_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhsu_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhsu_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldss_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldss_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldbss_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhss_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhss_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) + +DEF_HELPER_FLAGS_6(sve_ldbdu_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhdu_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhdu_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldsdu_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldsdu_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_lddd_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_lddd_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldbds_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhds_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhds_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldsds_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldsds_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) + +DEF_HELPER_FLAGS_6(sve_ldbdu_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhdu_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhdu_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldsdu_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldsdu_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_lddd_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_lddd_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldbds_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhds_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhds_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldsds_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldsds_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) + +DEF_HELPER_FLAGS_6(sve_ldbdu_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhdu_le_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhdu_be_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldsdu_le_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldsdu_be_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_lddd_le_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_lddd_be_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldbds_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhds_le_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldhds_be_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldsds_le_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldsds_be_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) + DEF_HELPER_FLAGS_6(sve_ldffbsu_zsu, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr, tl, i32) DEF_HELPER_FLAGS_6(sve_ldffhsu_le_zsu, TCG_CALL_NO_WG, @@ -1523,6 +1830,115 @@ DEF_HELPER_FLAGS_6(sve_ldffsds_le_zd, TCG_CALL_NO_WG, DEF_HELPER_FLAGS_6(sve_ldffsds_be_zd, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffbsu_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhsu_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhsu_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffss_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffss_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffbss_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhss_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhss_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) + +DEF_HELPER_FLAGS_6(sve_ldffbsu_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhsu_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhsu_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffss_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffss_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffbss_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhss_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhss_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) + +DEF_HELPER_FLAGS_6(sve_ldffbdu_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhdu_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhdu_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffsdu_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffsdu_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffdd_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffdd_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffbds_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhds_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhds_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffsds_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffsds_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) + +DEF_HELPER_FLAGS_6(sve_ldffbdu_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhdu_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhdu_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffsdu_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffsdu_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffdd_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffdd_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffbds_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhds_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhds_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffsds_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffsds_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) + +DEF_HELPER_FLAGS_6(sve_ldffbdu_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhdu_le_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhdu_be_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffsdu_le_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffsdu_be_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffdd_le_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffdd_be_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffbds_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhds_le_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffhds_be_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffsds_le_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_ldffsds_be_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) + DEF_HELPER_FLAGS_6(sve_stbs_zsu, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr, tl, i32) DEF_HELPER_FLAGS_6(sve_sths_le_zsu, TCG_CALL_NO_WG, @@ -1590,4 +2006,71 @@ DEF_HELPER_FLAGS_6(sve_stdd_le_zd, TCG_CALL_NO_WG, DEF_HELPER_FLAGS_6(sve_stdd_be_zd, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_stbs_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_sths_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_sths_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_stss_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_stss_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) + +DEF_HELPER_FLAGS_6(sve_stbs_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_sths_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_sths_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_stss_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_stss_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) + +DEF_HELPER_FLAGS_6(sve_stbd_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_sthd_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_sthd_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_stsd_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_stsd_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_stdd_le_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_stdd_be_zsu_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) + +DEF_HELPER_FLAGS_6(sve_stbd_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_sthd_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_sthd_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_stsd_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_stsd_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_stdd_le_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_stdd_be_zss_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) + +DEF_HELPER_FLAGS_6(sve_stbd_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_sthd_le_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_sthd_be_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_stsd_le_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_stsd_be_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_stdd_le_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) +DEF_HELPER_FLAGS_6(sve_stdd_be_zd_mte, TCG_CALL_NO_WG, + void, env, ptr, ptr, ptr, tl, i32) + DEF_HELPER_FLAGS_4(sve2_pmull_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) diff --git a/target/arm/helper.c b/target/arm/helper.c index a92ae55672fbcdfd88f874a5cf247bb512c41e25..38cd35c049292d40df5a35854f4b1c2be49e946e 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -24,6 +24,7 @@ #include "hw/irq.h" #include "hw/semihosting/semihost.h" #include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" #include "sysemu/kvm.h" #include "sysemu/tcg.h" #include "qemu/range.h" @@ -39,15 +40,17 @@ #ifndef CONFIG_USER_ONLY -static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address, +static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, bool s1_is_el0, hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot, target_ulong *page_size_ptr, - ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs); + ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs) + __attribute__((nonnull)); #endif static void switch_mode(CPUARMState *env, int mode); +static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx); static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg) { @@ -728,13 +731,12 @@ static void tlbimvaa_is_write(CPUARMState *env, const ARMCPRegInfo *ri, /* * Non-IS variants of TLB operations are upgraded to - * IS versions if we are at NS EL1 and HCR_EL2.FB is set to + * IS versions if we are at EL1 and HCR_EL2.FB is effectively set to * force broadcast of these operations. */ static bool tlb_force_broadcast(CPUARMState *env) { - return (env->cp15.hcr_el2 & HCR_FB) && - arm_current_el(env) == 1 && arm_is_secure_below_el3(env); + return arm_current_el(env) == 1 && (arm_hcr_el2_eff(env) & HCR_FB); } static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -1205,17 +1207,17 @@ static int64_t cycles_ns_per(uint64_t cycles) static bool instructions_supported(CPUARMState *env) { - return use_icount == 1 /* Precise instruction counting */; + return icount_enabled() == 1; /* Precise instruction counting */ } static uint64_t instructions_get_count(CPUARMState *env) { - return (uint64_t)cpu_get_icount_raw(); + return (uint64_t)icount_get_raw(); } static int64_t instructions_ns_per(uint64_t icount) { - return cpu_icount_to_ns((int64_t)icount); + return icount_to_ns((int64_t)icount); } #endif @@ -1451,7 +1453,7 @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter) } } else { prohibited = arm_feature(env, ARM_FEATURE_EL3) && - (env->cp15.mdcr_el3 & MDCR_SPME); + !(env->cp15.mdcr_el3 & MDCR_SPME); } if (prohibited && counter == 31) { @@ -2011,9 +2013,19 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) uint32_t valid_mask = 0x3fff; ARMCPU *cpu = env_archcpu(env); - if (arm_el_is_aa64(env, 3)) { + if (ri->state == ARM_CP_STATE_AA64) { value |= SCR_FW | SCR_AW; /* these two bits are RES1. */ valid_mask &= ~SCR_NET; + + if (cpu_isar_feature(aa64_lor, cpu)) { + valid_mask |= SCR_TLOR; + } + if (cpu_isar_feature(aa64_pauth, cpu)) { + valid_mask |= SCR_API | SCR_APK; + } + if (cpu_isar_feature(aa64_mte, cpu)) { + valid_mask |= SCR_ATA; + } } else { valid_mask &= ~(SCR_RW | SCR_ST); } @@ -2032,12 +2044,6 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) valid_mask &= ~SCR_SMD; } } - if (cpu_isar_feature(aa64_lor, cpu)) { - valid_mask |= SCR_TLOR; - } - if (cpu_isar_feature(aa64_pauth, cpu)) { - valid_mask |= SCR_API | SCR_APK; - } /* Clear all-context RES0 bits. */ value &= valid_mask; @@ -2264,13 +2270,13 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { .resetvalue = 0x0 }, { .name = "PMINTENCLR", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 2, .access = PL1_RW, .accessfn = access_tpm, - .type = ARM_CP_ALIAS | ARM_CP_IO, + .type = ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_NO_RAW, .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten), .writefn = pmintenclr_write, }, { .name = "PMINTENCLR_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 2, .access = PL1_RW, .accessfn = access_tpm, - .type = ARM_CP_ALIAS | ARM_CP_IO, + .type = ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_NO_RAW, .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten), .writefn = pmintenclr_write }, { .name = "CCSIDR", .state = ARM_CP_STATE_BOTH, @@ -4451,6 +4457,33 @@ static int vae1_tlbmask(CPUARMState *env) } } +/* Return 56 if TBI is enabled, 64 otherwise. */ +static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx, + uint64_t addr) +{ + uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr; + int tbi = aa64_va_parameter_tbi(tcr, mmu_idx); + int select = extract64(addr, 55, 1); + + return (tbi >> select) & 1 ? 56 : 64; +} + +static int vae1_tlbbits(CPUARMState *env, uint64_t addr) +{ + ARMMMUIdx mmu_idx; + + /* Only the regime of the mmu_idx below is significant. */ + if (arm_is_secure_below_el3(env)) { + mmu_idx = ARMMMUIdx_SE10_0; + } else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE)) + == (HCR_E2H | HCR_TGE)) { + mmu_idx = ARMMMUIdx_E20_0; + } else { + mmu_idx = ARMMMUIdx_E10_0; + } + return tlbbits_for_regime(env, mmu_idx, addr); +} + static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { @@ -4587,8 +4620,9 @@ static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri, CPUState *cs = env_cpu(env); int mask = vae1_tlbmask(env); uint64_t pageaddr = sextract64(value << 12, 0, 56); + int bits = vae1_tlbbits(env, pageaddr); - tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask); + tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits); } static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -4602,11 +4636,12 @@ static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri, CPUState *cs = env_cpu(env); int mask = vae1_tlbmask(env); uint64_t pageaddr = sextract64(value << 12, 0, 56); + int bits = vae1_tlbbits(env, pageaddr); if (tlb_force_broadcast(env)) { - tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask); + tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits); } else { - tlb_flush_page_by_mmuidx(cs, pageaddr, mask); + tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits); } } @@ -4615,9 +4650,10 @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri, { CPUState *cs = env_cpu(env); uint64_t pageaddr = sextract64(value << 12, 0, 56); + int bits = tlbbits_for_regime(env, ARMMMUIdx_E2, pageaddr); - tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, - ARMMMUIdxBit_E2); + tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, + ARMMMUIdxBit_E2, bits); } static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -4625,9 +4661,10 @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri, { CPUState *cs = env_cpu(env); uint64_t pageaddr = sextract64(value << 12, 0, 56); + int bits = tlbbits_for_regime(env, ARMMMUIdx_SE3, pageaddr); - tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, - ARMMMUIdxBit_SE3); + tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, + ARMMMUIdxBit_SE3, bits); } static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri, @@ -4697,6 +4734,22 @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, { ARMCPU *cpu = env_archcpu(env); + if (arm_feature(env, ARM_FEATURE_PMSA) && !cpu->has_mpu) { + /* M bit is RAZ/WI for PMSA with no MPU implemented */ + value &= ~SCTLR_M; + } + + /* ??? Lots of these bits are not implemented. */ + + if (ri->state == ARM_CP_STATE_AA64 && !cpu_isar_feature(aa64_mte, cpu)) { + if (ri->opc1 == 6) { /* SCTLR_EL3 */ + value &= ~(SCTLR_ITFSB | SCTLR_TCF | SCTLR_ATA); + } else { + value &= ~(SCTLR_ITFSB | SCTLR_TCF0 | SCTLR_TCF | + SCTLR_ATA0 | SCTLR_ATA); + } + } + if (raw_read(env, ri) == value) { /* Skip the TLB flush if nothing actually changed; Linux likes * to do a lot of pointless SCTLR writes. @@ -4704,13 +4757,8 @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, return; } - if (arm_feature(env, ARM_FEATURE_PMSA) && !cpu->has_mpu) { - /* M bit is RAZ/WI for PMSA with no MPU implemented */ - value &= ~SCTLR_M; - } - raw_write(env, ri, value); - /* ??? Lots of these bits are not implemented. */ + /* This may enable/disable the MMU, so do a TLB flush. */ tlb_flush(CPU(cpu)); @@ -5089,7 +5137,6 @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = { .access = PL2_RW, .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore }, { .name = "HCR_EL2", .state = ARM_CP_STATE_BOTH, - .type = ARM_CP_NO_RAW, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0, .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, @@ -5236,17 +5283,22 @@ static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask) if (cpu_isar_feature(aa64_pauth, cpu)) { valid_mask |= HCR_API | HCR_APK; } + if (cpu_isar_feature(aa64_mte, cpu)) { + valid_mask |= HCR_ATA | HCR_DCT | HCR_TID5; + } } /* Clear RES0 bits. */ value &= valid_mask; - /* These bits change the MMU setup: + /* + * These bits change the MMU setup: * HCR_VM enables stage 2 translation * HCR_PTW forbids certain page-table setups - * HCR_DC Disables stage1 and enables stage2 translation + * HCR_DC disables stage1 and enables stage2 translation + * HCR_DCT enables tagging on (disabled) stage1 translation */ - if ((env->cp15.hcr_el2 ^ value) & (HCR_VM | HCR_PTW | HCR_DC)) { + if ((env->cp15.hcr_el2 ^ value) & (HCR_VM | HCR_PTW | HCR_DC | HCR_DCT)) { tlb_flush(CPU(cpu)); } env->cp15.hcr_el2 = value; @@ -5861,6 +5913,9 @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu) { K(3, 0, 1, 2, 0), K(3, 4, 1, 2, 0), K(3, 5, 1, 2, 0), "ZCR_EL1", "ZCR_EL2", "ZCR_EL12", isar_feature_aa64_sve }, + { K(3, 0, 5, 6, 0), K(3, 4, 5, 6, 0), K(3, 5, 5, 6, 0), + "TFSR_EL1", "TFSR_EL2", "TFSR_EL12", isar_feature_aa64_mte }, + /* TODO: ARMv8.2-SPE -- PMSCR_EL2 */ /* TODO: ARMv8.4-Trace -- TRFCR_EL2 */ }; @@ -6602,7 +6657,7 @@ static void define_pmu_regs(ARMCPU *cpu) static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) { ARMCPU *cpu = env_archcpu(env); - uint64_t pfr1 = cpu->id_pfr1; + uint64_t pfr1 = cpu->isar.id_pfr1; if (env->gicv3state) { pfr1 |= 1 << 28; @@ -6624,9 +6679,10 @@ static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri) #endif /* Shared logic between LORID and the rest of the LOR* registers. - * Secure state has already been delt with. + * Secure state exclusion has already been dealt with. */ -static CPAccessResult access_lor_ns(CPUARMState *env) +static CPAccessResult access_lor_ns(CPUARMState *env, + const ARMCPRegInfo *ri, bool isread) { int el = arm_current_el(env); @@ -6639,16 +6695,6 @@ static CPAccessResult access_lor_ns(CPUARMState *env) return CP_ACCESS_OK; } -static CPAccessResult access_lorid(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - if (arm_is_secure_below_el3(env)) { - /* Access ok in secure mode. */ - return CP_ACCESS_OK; - } - return access_lor_ns(env); -} - static CPAccessResult access_lor_other(CPUARMState *env, const ARMCPRegInfo *ri, bool isread) { @@ -6656,7 +6702,7 @@ static CPAccessResult access_lor_other(CPUARMState *env, /* Access denied in secure mode. */ return CP_ACCESS_TRAP; } - return access_lor_ns(env); + return access_lor_ns(env, ri, isread); } /* @@ -6683,7 +6729,7 @@ static const ARMCPRegInfo lor_reginfo[] = { .type = ARM_CP_CONST, .resetvalue = 0 }, { .name = "LORID_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7, - .access = PL1_R, .accessfn = access_lorid, + .access = PL1_R, .accessfn = access_lor_ns, .type = ARM_CP_CONST, .resetvalue = 0 }, REGINFO_SENTINEL }; @@ -6813,7 +6859,7 @@ static void dccvap_writefn(CPUARMState *env, const ARMCPRegInfo *opaque, mr = memory_region_from_host(haddr, &offset); if (mr) { - memory_region_do_writeback(mr, offset, dline_size); + memory_region_writeback(mr, offset, dline_size); } } } @@ -6835,6 +6881,166 @@ static const ARMCPRegInfo dcpodp_reg[] = { }; #endif /*CONFIG_USER_ONLY*/ +static CPAccessResult access_aa64_tid5(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + if ((arm_current_el(env) < 2) && (arm_hcr_el2_eff(env) & HCR_TID5)) { + return CP_ACCESS_TRAP_EL2; + } + + return CP_ACCESS_OK; +} + +static CPAccessResult access_mte(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + int el = arm_current_el(env); + + if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) { + uint64_t hcr = arm_hcr_el2_eff(env); + if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) { + return CP_ACCESS_TRAP_EL2; + } + } + if (el < 3 && + arm_feature(env, ARM_FEATURE_EL3) && + !(env->cp15.scr_el3 & SCR_ATA)) { + return CP_ACCESS_TRAP_EL3; + } + return CP_ACCESS_OK; +} + +static uint64_t tco_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return env->pstate & PSTATE_TCO; +} + +static void tco_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t val) +{ + env->pstate = (env->pstate & ~PSTATE_TCO) | (val & PSTATE_TCO); +} + +static const ARMCPRegInfo mte_reginfo[] = { + { .name = "TFSRE0_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 5, .crm = 6, .opc2 = 1, + .access = PL1_RW, .accessfn = access_mte, + .fieldoffset = offsetof(CPUARMState, cp15.tfsr_el[0]) }, + { .name = "TFSR_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 5, .crm = 6, .opc2 = 0, + .access = PL1_RW, .accessfn = access_mte, + .fieldoffset = offsetof(CPUARMState, cp15.tfsr_el[1]) }, + { .name = "TFSR_EL2", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 6, .opc2 = 0, + .access = PL2_RW, .accessfn = access_mte, + .fieldoffset = offsetof(CPUARMState, cp15.tfsr_el[2]) }, + { .name = "TFSR_EL3", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 6, .crn = 5, .crm = 6, .opc2 = 0, + .access = PL3_RW, + .fieldoffset = offsetof(CPUARMState, cp15.tfsr_el[3]) }, + { .name = "RGSR_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 5, + .access = PL1_RW, .accessfn = access_mte, + .fieldoffset = offsetof(CPUARMState, cp15.rgsr_el1) }, + { .name = "GCR_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 6, + .access = PL1_RW, .accessfn = access_mte, + .fieldoffset = offsetof(CPUARMState, cp15.gcr_el1) }, + { .name = "GMID_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 4, + .access = PL1_R, .accessfn = access_aa64_tid5, + .type = ARM_CP_CONST, .resetvalue = GMID_EL1_BS }, + { .name = "TCO", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 7, + .type = ARM_CP_NO_RAW, + .access = PL0_RW, .readfn = tco_read, .writefn = tco_write }, + { .name = "DC_IGVAC", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 3, + .type = ARM_CP_NOP, .access = PL1_W, + .accessfn = aa64_cacheop_poc_access }, + { .name = "DC_IGSW", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 4, + .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw }, + { .name = "DC_IGDVAC", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 5, + .type = ARM_CP_NOP, .access = PL1_W, + .accessfn = aa64_cacheop_poc_access }, + { .name = "DC_IGDSW", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 6, + .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw }, + { .name = "DC_CGSW", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 4, + .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw }, + { .name = "DC_CGDSW", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 6, + .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw }, + { .name = "DC_CIGSW", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 4, + .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw }, + { .name = "DC_CIGDSW", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 6, + .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw }, + REGINFO_SENTINEL +}; + +static const ARMCPRegInfo mte_tco_ro_reginfo[] = { + { .name = "TCO", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 7, + .type = ARM_CP_CONST, .access = PL0_RW, }, + REGINFO_SENTINEL +}; + +static const ARMCPRegInfo mte_el0_cacheop_reginfo[] = { + { .name = "DC_CGVAC", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 10, .opc2 = 3, + .type = ARM_CP_NOP, .access = PL0_W, + .accessfn = aa64_cacheop_poc_access }, + { .name = "DC_CGDVAC", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 10, .opc2 = 5, + .type = ARM_CP_NOP, .access = PL0_W, + .accessfn = aa64_cacheop_poc_access }, + { .name = "DC_CGVAP", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 12, .opc2 = 3, + .type = ARM_CP_NOP, .access = PL0_W, + .accessfn = aa64_cacheop_poc_access }, + { .name = "DC_CGDVAP", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 12, .opc2 = 5, + .type = ARM_CP_NOP, .access = PL0_W, + .accessfn = aa64_cacheop_poc_access }, + { .name = "DC_CGVADP", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 13, .opc2 = 3, + .type = ARM_CP_NOP, .access = PL0_W, + .accessfn = aa64_cacheop_poc_access }, + { .name = "DC_CGDVADP", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 13, .opc2 = 5, + .type = ARM_CP_NOP, .access = PL0_W, + .accessfn = aa64_cacheop_poc_access }, + { .name = "DC_CIGVAC", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 14, .opc2 = 3, + .type = ARM_CP_NOP, .access = PL0_W, + .accessfn = aa64_cacheop_poc_access }, + { .name = "DC_CIGDVAC", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 14, .opc2 = 5, + .type = ARM_CP_NOP, .access = PL0_W, + .accessfn = aa64_cacheop_poc_access }, + { .name = "DC_GVA", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 4, .opc2 = 3, + .access = PL0_W, .type = ARM_CP_DC_GVA, +#ifndef CONFIG_USER_ONLY + /* Avoid overhead of an access check that always passes in user-mode */ + .accessfn = aa64_zva_access, +#endif + }, + { .name = "DC_GZVA", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 4, .opc2 = 4, + .access = PL0_W, .type = ARM_CP_DC_GZVA, +#ifndef CONFIG_USER_ONLY + /* Avoid overhead of an access check that always passes in user-mode */ + .accessfn = aa64_zva_access, +#endif + }, + REGINFO_SENTINEL +}; + #endif static CPAccessResult access_predinv(CPUARMState *env, const ARMCPRegInfo *ri, @@ -7076,7 +7282,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa32_tid3, - .resetvalue = cpu->id_pfr0 }, + .resetvalue = cpu->isar.id_pfr0 }, /* ID_PFR1 is not a plain ARM_CP_CONST because we don't know * the value of the GIC field until after we define these regs. */ @@ -7960,6 +8166,19 @@ void register_cp_regs_for_features(ARMCPU *cpu) } } #endif /*CONFIG_USER_ONLY*/ + + /* + * If full MTE is enabled, add all of the system registers. + * If only "instructions available at EL0" are enabled, + * then define only a RAZ/WI version of PSTATE.TCO. + */ + if (cpu_isar_feature(aa64_mte, cpu)) { + define_arm_cp_regs(cpu, mte_reginfo); + define_arm_cp_regs(cpu, mte_el0_cacheop_reginfo); + } else if (cpu_isar_feature(aa64_mte_insn_reg, cpu)) { + define_arm_cp_regs(cpu, mte_tco_ro_reginfo); + define_arm_cp_regs(cpu, mte_el0_cacheop_reginfo); + } #endif if (cpu_isar_feature(any_predinv, cpu)) { @@ -8266,6 +8485,35 @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu, assert((r->state != ARM_CP_STATE_AA32) || (r->opc0 == 0)); /* AArch64 regs are all 64 bit so ARM_CP_64BIT is meaningless */ assert((r->state != ARM_CP_STATE_AA64) || !(r->type & ARM_CP_64BIT)); + /* + * This API is only for Arm's system coprocessors (14 and 15) or + * (M-profile or v7A-and-earlier only) for implementation defined + * coprocessors in the range 0..7. Our decode assumes this, since + * 8..13 can be used for other insns including VFP and Neon. See + * valid_cp() in translate.c. Assert here that we haven't tried + * to use an invalid coprocessor number. + */ + switch (r->state) { + case ARM_CP_STATE_BOTH: + /* 0 has a special meaning, but otherwise the same rules as AA32. */ + if (r->cp == 0) { + break; + } + /* fall through */ + case ARM_CP_STATE_AA32: + if (arm_feature(&cpu->env, ARM_FEATURE_V8) && + !arm_feature(&cpu->env, ARM_FEATURE_M)) { + assert(r->cp >= 14 && r->cp <= 15); + } else { + assert(r->cp < 8 || (r->cp >= 14 && r->cp <= 15)); + } + break; + case ARM_CP_STATE_AA64: + assert(r->cp == 0 || r->cp == CP_REG_ARM64_SYSREG_CP); + break; + default: + g_assert_not_reached(); + } /* The AArch64 pseudocode CheckSystemAccess() specifies that op1 * encodes a minimum access level for the register. We roll this * runtime check into our general permission check code, so check @@ -9385,6 +9633,66 @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs) take_aarch32_exception(env, new_mode, mask, offset, addr); } +static int aarch64_regnum(CPUARMState *env, int aarch32_reg) +{ + /* + * Return the register number of the AArch64 view of the AArch32 + * register @aarch32_reg. The CPUARMState CPSR is assumed to still + * be that of the AArch32 mode the exception came from. + */ + int mode = env->uncached_cpsr & CPSR_M; + + switch (aarch32_reg) { + case 0 ... 7: + return aarch32_reg; + case 8 ... 12: + return mode == ARM_CPU_MODE_FIQ ? aarch32_reg + 16 : aarch32_reg; + case 13: + switch (mode) { + case ARM_CPU_MODE_USR: + case ARM_CPU_MODE_SYS: + return 13; + case ARM_CPU_MODE_HYP: + return 15; + case ARM_CPU_MODE_IRQ: + return 17; + case ARM_CPU_MODE_SVC: + return 19; + case ARM_CPU_MODE_ABT: + return 21; + case ARM_CPU_MODE_UND: + return 23; + case ARM_CPU_MODE_FIQ: + return 29; + default: + g_assert_not_reached(); + } + case 14: + switch (mode) { + case ARM_CPU_MODE_USR: + case ARM_CPU_MODE_SYS: + case ARM_CPU_MODE_HYP: + return 14; + case ARM_CPU_MODE_IRQ: + return 16; + case ARM_CPU_MODE_SVC: + return 18; + case ARM_CPU_MODE_ABT: + return 20; + case ARM_CPU_MODE_UND: + return 22; + case ARM_CPU_MODE_FIQ: + return 30; + default: + g_assert_not_reached(); + } + case 15: + return 31; + default: + g_assert_not_reached(); + } +} + /* Handle exception entry to a target EL which is using AArch64 */ static void arm_cpu_do_interrupt_aarch64(CPUState *cs) { @@ -9395,6 +9703,7 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs) unsigned int new_mode = aarch64_pstate_mode(new_el, true); unsigned int old_mode; unsigned int cur_el = arm_current_el(env); + int rt; /* * Note that new_el can never be 0. If cur_el is 0, then @@ -9449,7 +9758,8 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs) case EXCP_HVC: case EXCP_HYP_TRAP: case EXCP_SMC: - if (syn_get_ec(env->exception.syndrome) == EC_ADVSIMDFPACCESSTRAP) { + switch (syn_get_ec(env->exception.syndrome)) { + case EC_ADVSIMDFPACCESSTRAP: /* * QEMU internal FP/SIMD syndromes from AArch32 include the * TA and coproc fields which are only exposed if the exception @@ -9457,6 +9767,34 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs) * AArch64 format syndrome. */ env->exception.syndrome &= ~MAKE_64BIT_MASK(0, 20); + break; + case EC_CP14RTTRAP: + case EC_CP15RTTRAP: + case EC_CP14DTTRAP: + /* + * For a trap on AArch32 MRC/MCR/LDC/STC the Rt field is currently + * the raw register field from the insn; when taking this to + * AArch64 we must convert it to the AArch64 view of the register + * number. Notice that we read a 4-bit AArch32 register number and + * write back a 5-bit AArch64 one. + */ + rt = extract32(env->exception.syndrome, 5, 4); + rt = aarch64_regnum(env, rt); + env->exception.syndrome = deposit32(env->exception.syndrome, + 5, 5, rt); + break; + case EC_CP15RRTTRAP: + case EC_CP14RRTTRAP: + /* Similarly for MRRC/MCRR traps for Rt and Rt2 fields */ + rt = extract32(env->exception.syndrome, 5, 4); + rt = aarch64_regnum(env, rt); + env->exception.syndrome = deposit32(env->exception.syndrome, + 5, 5, rt); + rt = extract32(env->exception.syndrome, 10, 4); + rt = aarch64_regnum(env, rt); + env->exception.syndrome = deposit32(env->exception.syndrome, + 10, 5, rt); + break; } env->cp15.esr_el[new_el] = env->exception.syndrome; break; @@ -9509,6 +9847,9 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs) break; } } + if (cpu_isar_feature(aa64_mte, cpu)) { + new_mode |= PSTATE_TCO; + } pstate_write(env, PSTATE_DAIF | new_mode); env->aarch64 = 1; @@ -9614,42 +9955,6 @@ void arm_cpu_do_interrupt(CPUState *cs) } #endif /* !CONFIG_USER_ONLY */ -/* Return the exception level which controls this address translation regime */ -static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx) -{ - switch (mmu_idx) { - case ARMMMUIdx_E20_0: - case ARMMMUIdx_E20_2: - case ARMMMUIdx_E20_2_PAN: - case ARMMMUIdx_Stage2: - case ARMMMUIdx_E2: - return 2; - case ARMMMUIdx_SE3: - return 3; - case ARMMMUIdx_SE10_0: - return arm_el_is_aa64(env, 3) ? 1 : 3; - case ARMMMUIdx_SE10_1: - case ARMMMUIdx_SE10_1_PAN: - case ARMMMUIdx_Stage1_E0: - case ARMMMUIdx_Stage1_E1: - case ARMMMUIdx_Stage1_E1_PAN: - case ARMMMUIdx_E10_0: - case ARMMMUIdx_E10_1: - case ARMMMUIdx_E10_1_PAN: - case ARMMMUIdx_MPrivNegPri: - case ARMMMUIdx_MUserNegPri: - case ARMMMUIdx_MPriv: - case ARMMMUIdx_MUser: - case ARMMMUIdx_MSPrivNegPri: - case ARMMMUIdx_MSUserNegPri: - case ARMMMUIdx_MSPriv: - case ARMMMUIdx_MSUser: - return 1; - default: - g_assert_not_reached(); - } -} - uint64_t arm_sctlr(CPUARMState *env, int el) { /* Only EL0 needs to be adjusted for EL1&0 or EL2&0. */ @@ -9732,15 +10037,6 @@ static inline uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx, #endif /* !CONFIG_USER_ONLY */ -/* Return the TCR controlling this translation regime */ -static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx) -{ - if (mmu_idx == ARMMMUIdx_Stage2) { - return &env->cp15.vtcr_el2; - } - return &env->cp15.tcr_el[regime_el(env, mmu_idx)]; -} - /* Convert a possible stage1+2 MMU index into the appropriate * stage 1 MMU index */ @@ -10050,21 +10346,11 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, int s2prot; int ret; ARMCacheAttrs cacheattrs = {}; - ARMCacheAttrs *pcacheattrs = NULL; - - if (env->cp15.hcr_el2 & HCR_PTW) { - /* - * PTW means we must fault if this S1 walk touches S2 Device - * memory; otherwise we don't care about the attributes and can - * save the S2 translation the effort of computing them. - */ - pcacheattrs = &cacheattrs; - } ret = get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, ARMMMUIdx_Stage2, false, &s2pa, &txattrs, &s2prot, &s2size, fi, - pcacheattrs); + &cacheattrs); if (ret) { assert(fi->type != ARMFault_None); fi->s2addr = addr; @@ -10072,8 +10358,11 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, fi->s1ptw = true; return ~0; } - if (pcacheattrs && (pcacheattrs->attrs & 0xf0) == 0) { - /* Access was to Device memory: generate Permission fault */ + if ((env->cp15.hcr_el2 & HCR_PTW) && (cacheattrs.attrs & 0xf0) == 0) { + /* + * PTW set and S1 walk touched S2 Device memory: + * generate Permission fault. + */ fi->type = ARMFault_Permission; fi->s2addr = addr; fi->stage2 = true; @@ -10272,6 +10561,7 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, target_ulong *page_size, ARMMMUFaultInfo *fi) { CPUState *cs = env_cpu(env); + ARMCPU *cpu = env_archcpu(env); int level = 1; uint32_t table; uint32_t desc; @@ -10298,7 +10588,7 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, goto do_fault; } type = (desc & 3); - if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) { + if (type == 0 || (type == 3 && !cpu_isar_feature(aa32_pxn, cpu))) { /* Section translation fault, or attempt to use the encoding * which is Reserved on implementations without PXN. */ @@ -10340,7 +10630,7 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, pxn = desc & 1; ns = extract32(desc, 19, 1); } else { - if (arm_feature(env, ARM_FEATURE_PXN)) { + if (cpu_isar_feature(aa32_pxn, cpu)) { pxn = (desc >> 2) & 1; } ns = extract32(desc, 3, 1); @@ -10541,6 +10831,16 @@ static int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx) } } +static int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx) +{ + if (regime_has_2_ranges(mmu_idx)) { + return extract64(tcr, 57, 2); + } else { + /* Replicate the single TCMA bit so we always have 2 bits. */ + return extract32(tcr, 30, 1) * 3; + } +} + ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, ARMMMUIdx mmu_idx, bool data) { @@ -10688,7 +10988,7 @@ static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va, * @fi: set to fault info if the translation fails * @cacheattrs: (if non-NULL) set to the cacheability/shareability attributes */ -static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address, +static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, bool s1_is_el0, hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot, @@ -10935,22 +11235,19 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address, } /* When in aarch64 mode, and BTI is enabled, remember GP in the IOTLB. */ if (aarch64 && guarded && cpu_isar_feature(aa64_bti, cpu)) { - txattrs->target_tlb_bit0 = true; + arm_tlb_bti_gp(txattrs) = true; } - if (cacheattrs != NULL) { - if (mmu_idx == ARMMMUIdx_Stage2) { - cacheattrs->attrs = convert_stage2_attrs(env, - extract32(attrs, 0, 4)); - } else { - /* Index into MAIR registers for cache attributes */ - uint8_t attrindx = extract32(attrs, 0, 3); - uint64_t mair = env->cp15.mair_el[regime_el(env, mmu_idx)]; - assert(attrindx <= 7); - cacheattrs->attrs = extract64(mair, attrindx * 8, 8); - } - cacheattrs->shareability = extract32(attrs, 6, 2); + if (mmu_idx == ARMMMUIdx_Stage2) { + cacheattrs->attrs = convert_stage2_attrs(env, extract32(attrs, 0, 4)); + } else { + /* Index into MAIR registers for cache attributes */ + uint8_t attrindx = extract32(attrs, 0, 3); + uint64_t mair = env->cp15.mair_el[regime_el(env, mmu_idx)]; + assert(attrindx <= 7); + cacheattrs->attrs = extract64(mair, attrindx * 8, 8); } + cacheattrs->shareability = extract32(attrs, 6, 2); *phys_ptr = descaddr; *page_size_ptr = page_size; @@ -11673,9 +11970,19 @@ static uint8_t combine_cacheattr_nibble(uint8_t s1, uint8_t s2) */ static ARMCacheAttrs combine_cacheattrs(ARMCacheAttrs s1, ARMCacheAttrs s2) { - uint8_t s1lo = extract32(s1.attrs, 0, 4), s2lo = extract32(s2.attrs, 0, 4); - uint8_t s1hi = extract32(s1.attrs, 4, 4), s2hi = extract32(s2.attrs, 4, 4); + uint8_t s1lo, s2lo, s1hi, s2hi; ARMCacheAttrs ret; + bool tagged = false; + + if (s1.attrs == 0xf0) { + tagged = true; + s1.attrs = 0xff; + } + + s1lo = extract32(s1.attrs, 0, 4); + s2lo = extract32(s2.attrs, 0, 4); + s1hi = extract32(s1.attrs, 4, 4); + s2hi = extract32(s2.attrs, 4, 4); /* Combine shareability attributes (table D4-43) */ if (s1.shareability == 2 || s2.shareability == 2) { @@ -11723,6 +12030,11 @@ static ARMCacheAttrs combine_cacheattrs(ARMCacheAttrs s1, ARMCacheAttrs s2) } } + /* TODO: CombineS1S2Desc does not consider transient, only WB, RWA. */ + if (tagged && ret.attrs == 0xff) { + ret.attrs = 0xf0; + } + return ret; } @@ -11785,28 +12097,32 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, ret = get_phys_addr_lpae(env, ipa, access_type, ARMMMUIdx_Stage2, mmu_idx == ARMMMUIdx_E10_0, phys_ptr, attrs, &s2_prot, - page_size, fi, - cacheattrs != NULL ? &cacheattrs2 : NULL); + page_size, fi, &cacheattrs2); fi->s2addr = ipa; /* Combine the S1 and S2 perms. */ *prot &= s2_prot; - /* Combine the S1 and S2 cache attributes, if needed */ - if (!ret && cacheattrs != NULL) { - if (env->cp15.hcr_el2 & HCR_DC) { - /* - * HCR.DC forces the first stage attributes to - * Normal Non-Shareable, - * Inner Write-Back Read-Allocate Write-Allocate, - * Outer Write-Back Read-Allocate Write-Allocate. - */ + /* If S2 fails, return early. */ + if (ret) { + return ret; + } + + /* Combine the S1 and S2 cache attributes. */ + if (env->cp15.hcr_el2 & HCR_DC) { + /* + * HCR.DC forces the first stage attributes to + * Normal Non-Shareable, + * Inner Write-Back Read-Allocate Write-Allocate, + * Outer Write-Back Read-Allocate Write-Allocate. + * Do not overwrite Tagged within attrs. + */ + if (cacheattrs->attrs != 0xf0) { cacheattrs->attrs = 0xff; - cacheattrs->shareability = 0; } - *cacheattrs = combine_cacheattrs(*cacheattrs, cacheattrs2); + cacheattrs->shareability = 0; } - - return ret; + *cacheattrs = combine_cacheattrs(*cacheattrs, cacheattrs2); + return 0; } else { /* * For non-EL2 CPUs a stage1+stage2 translation is just stage 1. @@ -11867,6 +12183,9 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, /* Definitely a real MMU, not an MPU */ if (regime_translation_disabled(env, mmu_idx)) { + uint64_t hcr; + uint8_t memattr; + /* * MMU disabled. S1 addresses within aa64 translation regimes are * still checked for bounds -- see AArch64.TranslateAddressS1Off. @@ -11904,6 +12223,27 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, *phys_ptr = address; *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; *page_size = TARGET_PAGE_SIZE; + + /* Fill in cacheattr a-la AArch64.TranslateAddressS1Off. */ + hcr = arm_hcr_el2_eff(env); + cacheattrs->shareability = 0; + if (hcr & HCR_DC) { + if (hcr & HCR_DCT) { + memattr = 0xf0; /* Tagged, Normal, WB, RWA */ + } else { + memattr = 0xff; /* Normal, WB, RWA */ + } + } else if (access_type == MMU_INST_FETCH) { + if (regime_sctlr(env, mmu_idx) & SCTLR_I) { + memattr = 0xee; /* Normal, WT, RA, NT */ + } else { + memattr = 0x44; /* Normal, NC, No */ + } + cacheattrs->shareability = 2; /* outer sharable */ + } else { + memattr = 0x00; /* Device, nGnRnE */ + } + cacheattrs->attrs = memattr; return 0; } @@ -11931,11 +12271,12 @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr, bool ret; ARMMMUFaultInfo fi = {}; ARMMMUIdx mmu_idx = arm_mmu_idx(env); + ARMCacheAttrs cacheattrs = {}; *attrs = (MemTxAttrs) {}; ret = get_phys_addr(env, addr, 0, mmu_idx, &phys_addr, - attrs, &prot, &page_size, &fi, NULL); + attrs, &prot, &page_size, &fi, &cacheattrs); if (ret) { return -1; @@ -12167,7 +12508,7 @@ uint32_t HELPER(usad8)(uint32_t a, uint32_t b) uint32_t sum; sum = do_usad(a, b); sum += do_usad(a >> 8, b >> 8); - sum += do_usad(a >> 16, b >>16); + sum += do_usad(a >> 16, b >> 16); sum += do_usad(a >> 24, b >> 24); return sum; } @@ -12565,6 +12906,36 @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, } } + if (cpu_isar_feature(aa64_mte, env_archcpu(env))) { + /* + * Set MTE_ACTIVE if any access may be Checked, and leave clear + * if all accesses must be Unchecked: + * 1) If no TBI, then there are no tags in the address to check, + * 2) If Tag Check Override, then all accesses are Unchecked, + * 3) If Tag Check Fail == 0, then Checked access have no effect, + * 4) If no Allocation Tag Access, then all accesses are Unchecked. + */ + if (allocation_tag_access_enabled(env, el, sctlr)) { + flags = FIELD_DP32(flags, TBFLAG_A64, ATA, 1); + if (tbid + && !(env->pstate & PSTATE_TCO) + && (sctlr & (el == 0 ? SCTLR_TCF0 : SCTLR_TCF))) { + flags = FIELD_DP32(flags, TBFLAG_A64, MTE_ACTIVE, 1); + } + } + /* And again for unprivileged accesses, if required. */ + if (FIELD_EX32(flags, TBFLAG_A64, UNPRIV) + && tbid + && !(env->pstate & PSTATE_TCO) + && (sctlr & SCTLR_TCF0) + && allocation_tag_access_enabled(env, 0, sctlr)) { + flags = FIELD_DP32(flags, TBFLAG_A64, MTE0_ACTIVE, 1); + } + /* Cache TCMA as well as TBI. */ + flags = FIELD_DP32(flags, TBFLAG_A64, TCMA, + aa64_va_parameter_tcma(tcr, mmu_idx)); + } + return rebuild_hflags_common(env, fp_el, mmu_idx, flags); } diff --git a/target/arm/helper.h b/target/arm/helper.h index 49336dc432c3b650b3300759eadfada24a5aa358..ff8148ddc6bd8e827ea2b281ebb12498bd3d2de8 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -96,33 +96,48 @@ DEF_HELPER_FLAGS_1(rebuild_hflags_a32_newel, TCG_CALL_NO_RWG, void, env) DEF_HELPER_FLAGS_2(rebuild_hflags_a32, TCG_CALL_NO_RWG, void, env, int) DEF_HELPER_FLAGS_2(rebuild_hflags_a64, TCG_CALL_NO_RWG, void, env, int) +DEF_HELPER_FLAGS_5(probe_access, TCG_CALL_NO_WG, void, env, tl, i32, i32, i32) + DEF_HELPER_1(vfp_get_fpscr, i32, env) DEF_HELPER_2(vfp_set_fpscr, void, env, i32) +DEF_HELPER_3(vfp_addh, f16, f16, f16, ptr) DEF_HELPER_3(vfp_adds, f32, f32, f32, ptr) DEF_HELPER_3(vfp_addd, f64, f64, f64, ptr) +DEF_HELPER_3(vfp_subh, f16, f16, f16, ptr) DEF_HELPER_3(vfp_subs, f32, f32, f32, ptr) DEF_HELPER_3(vfp_subd, f64, f64, f64, ptr) +DEF_HELPER_3(vfp_mulh, f16, f16, f16, ptr) DEF_HELPER_3(vfp_muls, f32, f32, f32, ptr) DEF_HELPER_3(vfp_muld, f64, f64, f64, ptr) +DEF_HELPER_3(vfp_divh, f16, f16, f16, ptr) DEF_HELPER_3(vfp_divs, f32, f32, f32, ptr) DEF_HELPER_3(vfp_divd, f64, f64, f64, ptr) +DEF_HELPER_3(vfp_maxh, f16, f16, f16, ptr) DEF_HELPER_3(vfp_maxs, f32, f32, f32, ptr) DEF_HELPER_3(vfp_maxd, f64, f64, f64, ptr) +DEF_HELPER_3(vfp_minh, f16, f16, f16, ptr) DEF_HELPER_3(vfp_mins, f32, f32, f32, ptr) DEF_HELPER_3(vfp_mind, f64, f64, f64, ptr) +DEF_HELPER_3(vfp_maxnumh, f16, f16, f16, ptr) DEF_HELPER_3(vfp_maxnums, f32, f32, f32, ptr) DEF_HELPER_3(vfp_maxnumd, f64, f64, f64, ptr) +DEF_HELPER_3(vfp_minnumh, f16, f16, f16, ptr) DEF_HELPER_3(vfp_minnums, f32, f32, f32, ptr) DEF_HELPER_3(vfp_minnumd, f64, f64, f64, ptr) +DEF_HELPER_1(vfp_negh, f16, f16) DEF_HELPER_1(vfp_negs, f32, f32) DEF_HELPER_1(vfp_negd, f64, f64) +DEF_HELPER_1(vfp_absh, f16, f16) DEF_HELPER_1(vfp_abss, f32, f32) DEF_HELPER_1(vfp_absd, f64, f64) +DEF_HELPER_2(vfp_sqrth, f16, f16, env) DEF_HELPER_2(vfp_sqrts, f32, f32, env) DEF_HELPER_2(vfp_sqrtd, f64, f64, env) +DEF_HELPER_3(vfp_cmph, void, f16, f16, env) DEF_HELPER_3(vfp_cmps, void, f32, f32, env) DEF_HELPER_3(vfp_cmpd, void, f64, f64, env) +DEF_HELPER_3(vfp_cmpeh, void, f16, f16, env) DEF_HELPER_3(vfp_cmpes, void, f32, f32, env) DEF_HELPER_3(vfp_cmped, void, f64, f64, env) @@ -149,6 +164,10 @@ DEF_HELPER_2(vfp_tosizh, s32, f16, ptr) DEF_HELPER_2(vfp_tosizs, s32, f32, ptr) DEF_HELPER_2(vfp_tosizd, s32, f64, ptr) +DEF_HELPER_3(vfp_toshh_round_to_zero, i32, f16, i32, ptr) +DEF_HELPER_3(vfp_toslh_round_to_zero, i32, f16, i32, ptr) +DEF_HELPER_3(vfp_touhh_round_to_zero, i32, f16, i32, ptr) +DEF_HELPER_3(vfp_toulh_round_to_zero, i32, f16, i32, ptr) DEF_HELPER_3(vfp_toshs_round_to_zero, i32, f32, i32, ptr) DEF_HELPER_3(vfp_tosls_round_to_zero, i32, f32, i32, ptr) DEF_HELPER_3(vfp_touhs_round_to_zero, i32, f32, i32, ptr) @@ -187,13 +206,27 @@ DEF_HELPER_3(vfp_sqtod, f64, i64, i32, ptr) DEF_HELPER_3(vfp_uhtod, f64, i64, i32, ptr) DEF_HELPER_3(vfp_ultod, f64, i64, i32, ptr) DEF_HELPER_3(vfp_uqtod, f64, i64, i32, ptr) +DEF_HELPER_3(vfp_shtoh, f16, i32, i32, ptr) +DEF_HELPER_3(vfp_uhtoh, f16, i32, i32, ptr) DEF_HELPER_3(vfp_sltoh, f16, i32, i32, ptr) DEF_HELPER_3(vfp_ultoh, f16, i32, i32, ptr) DEF_HELPER_3(vfp_sqtoh, f16, i64, i32, ptr) DEF_HELPER_3(vfp_uqtoh, f16, i64, i32, ptr) +DEF_HELPER_3(vfp_shtos_round_to_nearest, f32, i32, i32, ptr) +DEF_HELPER_3(vfp_sltos_round_to_nearest, f32, i32, i32, ptr) +DEF_HELPER_3(vfp_uhtos_round_to_nearest, f32, i32, i32, ptr) +DEF_HELPER_3(vfp_ultos_round_to_nearest, f32, i32, i32, ptr) +DEF_HELPER_3(vfp_shtod_round_to_nearest, f64, i64, i32, ptr) +DEF_HELPER_3(vfp_sltod_round_to_nearest, f64, i64, i32, ptr) +DEF_HELPER_3(vfp_uhtod_round_to_nearest, f64, i64, i32, ptr) +DEF_HELPER_3(vfp_ultod_round_to_nearest, f64, i64, i32, ptr) +DEF_HELPER_3(vfp_shtoh_round_to_nearest, f16, i32, i32, ptr) +DEF_HELPER_3(vfp_uhtoh_round_to_nearest, f16, i32, i32, ptr) +DEF_HELPER_3(vfp_sltoh_round_to_nearest, f16, i32, i32, ptr) +DEF_HELPER_3(vfp_ultoh_round_to_nearest, f16, i32, i32, ptr) + DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, ptr) -DEF_HELPER_FLAGS_2(set_neon_rmode, TCG_CALL_NO_RWG, i32, i32, env) DEF_HELPER_FLAGS_3(vfp_fcvt_f16_to_f32, TCG_CALL_NO_RWG, f32, f16, ptr, i32) DEF_HELPER_FLAGS_3(vfp_fcvt_f32_to_f16, TCG_CALL_NO_RWG, f16, f32, ptr, i32) @@ -202,9 +235,8 @@ DEF_HELPER_FLAGS_3(vfp_fcvt_f64_to_f16, TCG_CALL_NO_RWG, f16, f64, ptr, i32) DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr) DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr) +DEF_HELPER_4(vfp_muladdh, f16, f16, f16, f16, ptr) -DEF_HELPER_3(recps_f32, f32, env, f32, f32) -DEF_HELPER_3(rsqrts_f32, f32, env, f32, f32) DEF_HELPER_FLAGS_2(recpe_f16, TCG_CALL_NO_RWG, f16, f16, ptr) DEF_HELPER_FLAGS_2(recpe_f32, TCG_CALL_NO_RWG, f32, f32, ptr) DEF_HELPER_FLAGS_2(recpe_f64, TCG_CALL_NO_RWG, f64, f64, ptr) @@ -213,15 +245,17 @@ DEF_HELPER_FLAGS_2(rsqrte_f32, TCG_CALL_NO_RWG, f32, f32, ptr) DEF_HELPER_FLAGS_2(rsqrte_f64, TCG_CALL_NO_RWG, f64, f64, ptr) DEF_HELPER_FLAGS_1(recpe_u32, TCG_CALL_NO_RWG, i32, i32) DEF_HELPER_FLAGS_1(rsqrte_u32, TCG_CALL_NO_RWG, i32, i32) -DEF_HELPER_FLAGS_4(neon_tbl, TCG_CALL_NO_RWG, i32, i32, i32, ptr, i32) +DEF_HELPER_FLAGS_4(neon_tbl, TCG_CALL_NO_RWG, i64, env, i32, i64, i64) DEF_HELPER_3(shl_cc, i32, env, i32, i32) DEF_HELPER_3(shr_cc, i32, env, i32, i32) DEF_HELPER_3(sar_cc, i32, env, i32, i32) DEF_HELPER_3(ror_cc, i32, env, i32, i32) +DEF_HELPER_FLAGS_2(rinth_exact, TCG_CALL_NO_RWG, f16, f16, ptr) DEF_HELPER_FLAGS_2(rints_exact, TCG_CALL_NO_RWG, f32, f32, ptr) DEF_HELPER_FLAGS_2(rintd_exact, TCG_CALL_NO_RWG, f64, f64, ptr) +DEF_HELPER_FLAGS_2(rinth, TCG_CALL_NO_RWG, f16, f16, ptr) DEF_HELPER_FLAGS_2(rints, TCG_CALL_NO_RWG, f32, f32, ptr) DEF_HELPER_FLAGS_2(rintd, TCG_CALL_NO_RWG, f64, f64, ptr) @@ -510,29 +544,40 @@ DEF_HELPER_FLAGS_2(neon_qzip8, TCG_CALL_NO_RWG, void, ptr, ptr) DEF_HELPER_FLAGS_2(neon_qzip16, TCG_CALL_NO_RWG, void, ptr, ptr) DEF_HELPER_FLAGS_2(neon_qzip32, TCG_CALL_NO_RWG, void, ptr, ptr) -DEF_HELPER_FLAGS_3(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32) -DEF_HELPER_FLAGS_4(crypto_sha1_3reg, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) -DEF_HELPER_FLAGS_2(crypto_sha1h, TCG_CALL_NO_RWG, void, ptr, ptr) -DEF_HELPER_FLAGS_2(crypto_sha1su1, TCG_CALL_NO_RWG, void, ptr, ptr) - -DEF_HELPER_FLAGS_3(crypto_sha256h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr) -DEF_HELPER_FLAGS_3(crypto_sha256h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr) -DEF_HELPER_FLAGS_2(crypto_sha256su0, TCG_CALL_NO_RWG, void, ptr, ptr) -DEF_HELPER_FLAGS_3(crypto_sha256su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr) - -DEF_HELPER_FLAGS_3(crypto_sha512h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr) -DEF_HELPER_FLAGS_3(crypto_sha512h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr) -DEF_HELPER_FLAGS_2(crypto_sha512su0, TCG_CALL_NO_RWG, void, ptr, ptr) -DEF_HELPER_FLAGS_3(crypto_sha512su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr) - -DEF_HELPER_FLAGS_5(crypto_sm3tt, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32, i32) -DEF_HELPER_FLAGS_3(crypto_sm3partw1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr) -DEF_HELPER_FLAGS_3(crypto_sm3partw2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr) - -DEF_HELPER_FLAGS_2(crypto_sm4e, TCG_CALL_NO_RWG, void, ptr, ptr) -DEF_HELPER_FLAGS_3(crypto_sm4ekey, TCG_CALL_NO_RWG, void, ptr, ptr, ptr) +DEF_HELPER_FLAGS_4(crypto_sha1su0, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(crypto_sha1c, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(crypto_sha1p, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(crypto_sha1m, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_3(crypto_sha1h, TCG_CALL_NO_RWG, void, ptr, ptr, i32) +DEF_HELPER_FLAGS_3(crypto_sha1su1, TCG_CALL_NO_RWG, void, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(crypto_sha256h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(crypto_sha256h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_3(crypto_sha256su0, TCG_CALL_NO_RWG, void, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(crypto_sha256su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(crypto_sha512h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(crypto_sha512h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_3(crypto_sha512su0, TCG_CALL_NO_RWG, void, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(crypto_sha512su1, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(crypto_sm3tt1a, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(crypto_sm3tt1b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(crypto_sm3tt2a, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(crypto_sm3tt2b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(crypto_sm3partw1, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(crypto_sm3partw2, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(crypto_sm4e, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(crypto_sm4ekey, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(crypto_rax1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) @@ -574,6 +619,43 @@ DEF_HELPER_FLAGS_5(gvec_fcmlas_idx, TCG_CALL_NO_RWG, DEF_HELPER_FLAGS_5(gvec_fcmlad, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(neon_paddh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(neon_pmaxh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(neon_pminh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(neon_padds, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(neon_pmaxs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(neon_pmins, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(gvec_sstoh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_sitos, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_ustoh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_uitos, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_tosszh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_tosizs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_touszh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_touizs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(gvec_vcvt_sf, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_vcvt_uf, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_vcvt_fs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_vcvt_fu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(gvec_vcvt_sh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_vcvt_uh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_vcvt_hs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_vcvt_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(gvec_vcvt_rm_ss, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_vcvt_rm_us, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_vcvt_rm_sh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_vcvt_rm_uh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(gvec_vrint_rm_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_vrint_rm_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(gvec_vrintx_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_vrintx_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + DEF_HELPER_FLAGS_4(gvec_frecpe_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_frecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_frecpe_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) @@ -582,6 +664,21 @@ DEF_HELPER_FLAGS_4(gvec_frsqrte_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_frsqrte_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_frsqrte_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_fcgt0_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_fcgt0_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(gvec_fcge0_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_fcge0_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(gvec_fceq0_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_fceq0_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(gvec_fcle0_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_fcle0_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(gvec_fclt0_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_fclt0_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + DEF_HELPER_FLAGS_5(gvec_fadd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_5(gvec_fadd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_5(gvec_fadd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) @@ -594,8 +691,54 @@ DEF_HELPER_FLAGS_5(gvec_fmul_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_5(gvec_fmul_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_5(gvec_fmul_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_5(gvec_fabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fceq_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fceq_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_fcge_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fcge_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_fcgt_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fcgt_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_facge_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_facge_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_facgt_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_facgt_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_fmax_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fmax_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_fmin_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fmin_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_fmaxnum_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fmaxnum_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_fminnum_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fminnum_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_recps_nf_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_recps_nf_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_rsqrts_nf_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_rsqrts_nf_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_fmla_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fmla_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_fmls_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fmls_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_vfma_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_vfma_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_vfms_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_vfms_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG, @@ -610,6 +753,16 @@ DEF_HELPER_FLAGS_5(gvec_fmul_idx_s, TCG_CALL_NO_RWG, DEF_HELPER_FLAGS_5(gvec_fmul_idx_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fmla_nf_idx_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fmla_nf_idx_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_fmls_nf_idx_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fmls_nf_idx_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) + DEF_HELPER_FLAGS_6(gvec_fmla_idx_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_6(gvec_fmla_idx_s, TCG_CALL_NO_RWG, @@ -745,6 +898,34 @@ DEF_HELPER_FLAGS_4(gvec_uaba_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_uaba_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_uaba_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_mul_idx_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_mul_idx_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(gvec_mul_idx_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_mla_idx_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_mla_idx_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_mla_idx_d, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(gvec_mls_idx_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_mls_idx_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_mls_idx_d, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(neon_sqdmulh_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(neon_sqdmulh_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(neon_sqrdmulh_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(neon_sqrdmulh_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) + #ifdef TARGET_AARCH64 #include "helper-a64.h" #include "helper-sve.h" diff --git a/target/arm/idau.h b/target/arm/idau.h index 7c0e4e377619b3b8b14e26a654f89f0c9eaed06a..0ef5251971d62818606f2723c67a961d77f63842 100644 --- a/target/arm/idau.h +++ b/target/arm/idau.h @@ -33,16 +33,15 @@ #define TYPE_IDAU_INTERFACE "idau-interface" #define IDAU_INTERFACE(obj) \ INTERFACE_CHECK(IDAUInterface, (obj), TYPE_IDAU_INTERFACE) -#define IDAU_INTERFACE_CLASS(class) \ - OBJECT_CLASS_CHECK(IDAUInterfaceClass, (class), TYPE_IDAU_INTERFACE) -#define IDAU_INTERFACE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(IDAUInterfaceClass, (obj), TYPE_IDAU_INTERFACE) +typedef struct IDAUInterfaceClass IDAUInterfaceClass; +DECLARE_CLASS_CHECKERS(IDAUInterfaceClass, IDAU_INTERFACE, + TYPE_IDAU_INTERFACE) typedef struct IDAUInterface IDAUInterface; #define IREGION_NOTVALID -1 -typedef struct IDAUInterfaceClass { +struct IDAUInterfaceClass { InterfaceClass parent; /* Check the specified address and return the IDAU security information @@ -54,6 +53,6 @@ typedef struct IDAUInterfaceClass { */ void (*check)(IDAUInterface *ii, uint32_t address, int *iregion, bool *exempt, bool *ns, bool *nsc); -} IDAUInterfaceClass; +}; #endif diff --git a/target/arm/internals.h b/target/arm/internals.h index 4bdbc3a8ace99013a6145e8989084fb00445e383..5460678756d3c4e5f34abe5f6411bd0e38482794 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -913,6 +913,51 @@ static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx) } } +/* Return the exception level which controls this address translation regime */ +static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx) +{ + switch (mmu_idx) { + case ARMMMUIdx_E20_0: + case ARMMMUIdx_E20_2: + case ARMMMUIdx_E20_2_PAN: + case ARMMMUIdx_Stage2: + case ARMMMUIdx_E2: + return 2; + case ARMMMUIdx_SE3: + return 3; + case ARMMMUIdx_SE10_0: + return arm_el_is_aa64(env, 3) ? 1 : 3; + case ARMMMUIdx_SE10_1: + case ARMMMUIdx_SE10_1_PAN: + case ARMMMUIdx_Stage1_E0: + case ARMMMUIdx_Stage1_E1: + case ARMMMUIdx_Stage1_E1_PAN: + case ARMMMUIdx_E10_0: + case ARMMMUIdx_E10_1: + case ARMMMUIdx_E10_1_PAN: + case ARMMMUIdx_MPrivNegPri: + case ARMMMUIdx_MUserNegPri: + case ARMMMUIdx_MPriv: + case ARMMMUIdx_MUser: + case ARMMMUIdx_MSPrivNegPri: + case ARMMMUIdx_MSUserNegPri: + case ARMMMUIdx_MSPriv: + case ARMMMUIdx_MSUser: + return 1; + default: + g_assert_not_reached(); + } +} + +/* Return the TCR controlling this translation regime */ +static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx) +{ + if (mmu_idx == ARMMMUIdx_Stage2) { + return &env->cp15.vtcr_el2; + } + return &env->cp15.tcr_el[regime_el(env, mmu_idx)]; +} + /* Return the FSR value for a debug exception (watchpoint, hardware * breakpoint or BKPT insn) targeting the specified exception level. */ @@ -1159,6 +1204,9 @@ static inline uint32_t aarch64_pstate_valid_mask(const ARMISARegisters *id) if (isar_feature_aa64_uao(id)) { valid |= PSTATE_UAO; } + if (isar_feature_aa64_mte(id)) { + valid |= PSTATE_TCO; + } return valid; } @@ -1195,6 +1243,25 @@ static inline int exception_target_el(CPUARMState *env) return target_el; } +/* Determine if allocation tags are available. */ +static inline bool allocation_tag_access_enabled(CPUARMState *env, int el, + uint64_t sctlr) +{ + if (el < 3 + && arm_feature(env, ARM_FEATURE_EL3) + && !(env->cp15.scr_el3 & SCR_ATA)) { + return false; + } + if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) { + uint64_t hcr = arm_hcr_el2_eff(env); + if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) { + return false; + } + } + sctlr &= (el == 0 ? SCTLR_ATA0 : SCTLR_ATA); + return sctlr != 0; +} + #ifndef CONFIG_USER_ONLY /* Security attributes for an address, as returned by v8m_security_lookup. */ @@ -1228,10 +1295,95 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, MMUAccessType access_type, ARMMMUIdx mmu_idx, hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot, target_ulong *page_size, - ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs); + ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs) + __attribute__((nonnull)); void arm_log_exception(int idx); #endif /* !CONFIG_USER_ONLY */ +/* + * The log2 of the words in the tag block, for GMID_EL1.BS. + * The is the maximum, 256 bytes, which manipulates 64-bits of tags. + */ +#define GMID_EL1_BS 6 + +/* We associate one allocation tag per 16 bytes, the minimum. */ +#define LOG2_TAG_GRANULE 4 +#define TAG_GRANULE (1 << LOG2_TAG_GRANULE) + +/* + * The SVE simd_data field, for memory ops, contains either + * rd (5 bits) or a shift count (2 bits). + */ +#define SVE_MTEDESC_SHIFT 5 + +/* Bits within a descriptor passed to the helper_mte_check* functions. */ +FIELD(MTEDESC, MIDX, 0, 4) +FIELD(MTEDESC, TBI, 4, 2) +FIELD(MTEDESC, TCMA, 6, 2) +FIELD(MTEDESC, WRITE, 8, 1) +FIELD(MTEDESC, ESIZE, 9, 5) +FIELD(MTEDESC, TSIZE, 14, 10) /* mte_checkN only */ + +bool mte_probe1(CPUARMState *env, uint32_t desc, uint64_t ptr); +uint64_t mte_check1(CPUARMState *env, uint32_t desc, + uint64_t ptr, uintptr_t ra); +uint64_t mte_checkN(CPUARMState *env, uint32_t desc, + uint64_t ptr, uintptr_t ra); + +static inline int allocation_tag_from_addr(uint64_t ptr) +{ + return extract64(ptr, 56, 4); +} + +static inline uint64_t address_with_allocation_tag(uint64_t ptr, int rtag) +{ + return deposit64(ptr, 56, 4, rtag); +} + +/* Return true if tbi bits mean that the access is checked. */ +static inline bool tbi_check(uint32_t desc, int bit55) +{ + return (desc >> (R_MTEDESC_TBI_SHIFT + bit55)) & 1; +} + +/* Return true if tcma bits mean that the access is unchecked. */ +static inline bool tcma_check(uint32_t desc, int bit55, int ptr_tag) +{ + /* + * We had extracted bit55 and ptr_tag for other reasons, so fold + * (ptr<59:55> == 00000 || ptr<59:55> == 11111) into a single test. + */ + bool match = ((ptr_tag + bit55) & 0xf) == 0; + bool tcma = (desc >> (R_MTEDESC_TCMA_SHIFT + bit55)) & 1; + return tcma && match; +} + +/* + * For TBI, ideally, we would do nothing. Proper behaviour on fault is + * for the tag to be present in the FAR_ELx register. But for user-only + * mode, we do not have a TLB with which to implement this, so we must + * remove the top byte. + */ +static inline uint64_t useronly_clean_ptr(uint64_t ptr) +{ + /* TBI is known to be enabled. */ +#ifdef CONFIG_USER_ONLY + ptr = sextract64(ptr, 0, 56); +#endif + return ptr; +} + +static inline uint64_t useronly_maybe_clean_ptr(uint32_t desc, uint64_t ptr) +{ +#ifdef CONFIG_USER_ONLY + int64_t clean_ptr = sextract64(ptr, 0, 56); + if (tbi_check(desc, clean_ptr < 0)) { + ptr = clean_ptr; + } +#endif + return ptr; +} + #endif diff --git a/target/arm/iwmmxt_helper.c b/target/arm/iwmmxt_helper.c index 24244d012cd598c5c2ab7d9e80fbd678dc44bcc7..610b1b2103eb8d0b85d488c952dce434b42510fb 100644 --- a/target/arm/iwmmxt_helper.c +++ b/target/arm/iwmmxt_helper.c @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h index aad28258a36932caf8c63bfb82ec13650377d8b9..580f1c1fee0c50455a284fed2bde9df0ad49f40e 100644 --- a/target/arm/kvm-consts.h +++ b/target/arm/kvm-consts.h @@ -136,16 +136,11 @@ MISMATCH_CHECK(QEMU_PSCI_RET_DISABLED, PSCI_RET_DISABLED); */ #define QEMU_KVM_ARM_TARGET_NONE UINT_MAX -#ifdef TARGET_AARCH64 MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_AEM_V8, KVM_ARM_TARGET_AEM_V8); MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_FOUNDATION_V8, KVM_ARM_TARGET_FOUNDATION_V8); MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A57, KVM_ARM_TARGET_CORTEX_A57); MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_XGENE_POTENZA, KVM_ARM_TARGET_XGENE_POTENZA); MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A53, KVM_ARM_TARGET_CORTEX_A53); -#else -MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A15, KVM_ARM_TARGET_CORTEX_A15); -MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A7, KVM_ARM_TARGET_CORTEX_A7); -#endif #define CP_REG_ARM64 0x6000000000000000ULL #define CP_REG_ARM_COPROC_MASK 0x000000000FFF0000 @@ -165,7 +160,6 @@ MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A7, KVM_ARM_TARGET_CORTEX_A7); /* No kernel define but it's useful to QEMU */ #define CP_REG_ARM64_SYSREG_CP (CP_REG_ARM64_SYSREG >> CP_REG_ARM_COPROC_SHIFT) -#ifdef TARGET_AARCH64 MISMATCH_CHECK(CP_REG_ARM64, KVM_REG_ARM64); MISMATCH_CHECK(CP_REG_ARM_COPROC_MASK, KVM_REG_ARM_COPROC_MASK); MISMATCH_CHECK(CP_REG_ARM_COPROC_SHIFT, KVM_REG_ARM_COPROC_SHIFT); @@ -180,7 +174,6 @@ MISMATCH_CHECK(CP_REG_ARM64_SYSREG_CRM_MASK, KVM_REG_ARM64_SYSREG_CRM_MASK); MISMATCH_CHECK(CP_REG_ARM64_SYSREG_CRM_SHIFT, KVM_REG_ARM64_SYSREG_CRM_SHIFT); MISMATCH_CHECK(CP_REG_ARM64_SYSREG_OP2_MASK, KVM_REG_ARM64_SYSREG_OP2_MASK); MISMATCH_CHECK(CP_REG_ARM64_SYSREG_OP2_SHIFT, KVM_REG_ARM64_SYSREG_OP2_SHIFT); -#endif #undef MISMATCH_CHECK diff --git a/target/arm/kvm.c b/target/arm/kvm.c index 4bdbe6dcac0724098ad09817f0bccb79a07bb3ac..ffe186de8d1974fb31645dd6b1c4691e3040afd1 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -39,6 +39,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = { static bool cap_has_mp_state; static bool cap_has_inject_serror_esr; +static bool cap_has_inject_ext_dabt; static ARMHostCPUFeatures arm_host_cpu_features; @@ -70,7 +71,7 @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try, { int ret = 0, kvmfd = -1, vmfd = -1, cpufd = -1; - kvmfd = qemu_open("/dev/kvm", O_RDWR); + kvmfd = qemu_open_old("/dev/kvm", O_RDWR); if (kvmfd < 0) { goto err; } @@ -191,25 +192,42 @@ static void kvm_no_adjvtime_set(Object *obj, bool value, Error **errp) ARM_CPU(obj)->kvm_adjvtime = !value; } +static bool kvm_steal_time_get(Object *obj, Error **errp) +{ + return ARM_CPU(obj)->kvm_steal_time != ON_OFF_AUTO_OFF; +} + +static void kvm_steal_time_set(Object *obj, bool value, Error **errp) +{ + ARM_CPU(obj)->kvm_steal_time = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF; +} + /* KVM VCPU properties should be prefixed with "kvm-". */ void kvm_arm_add_vcpu_properties(Object *obj) { - if (!kvm_enabled()) { - return; + ARMCPU *cpu = ARM_CPU(obj); + CPUARMState *env = &cpu->env; + + if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) { + cpu->kvm_adjvtime = true; + object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get, + kvm_no_adjvtime_set); + object_property_set_description(obj, "kvm-no-adjvtime", + "Set on to disable the adjustment of " + "the virtual counter. VM stopped time " + "will be counted."); } - ARM_CPU(obj)->kvm_adjvtime = true; - object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get, - kvm_no_adjvtime_set); - object_property_set_description(obj, "kvm-no-adjvtime", - "Set on to disable the adjustment of " - "the virtual counter. VM stopped time " - "will be counted."); + cpu->kvm_steal_time = ON_OFF_AUTO_AUTO; + object_property_add_bool(obj, "kvm-steal-time", kvm_steal_time_get, + kvm_steal_time_set); + object_property_set_description(obj, "kvm-steal-time", + "Set off to disable KVM steal time."); } -bool kvm_arm_pmu_supported(CPUState *cpu) +bool kvm_arm_pmu_supported(void) { - return kvm_check_extension(cpu->kvm_state, KVM_CAP_ARM_PMU_V3); + return kvm_check_extension(kvm_state, KVM_CAP_ARM_PMU_V3); } int kvm_arm_get_max_vm_ipa_size(MachineState *ms) @@ -244,6 +262,16 @@ int kvm_arch_init(MachineState *ms, KVMState *s) ret = -EINVAL; } + if (kvm_check_extension(s, KVM_CAP_ARM_NISV_TO_USER)) { + if (kvm_vm_enable_cap(s, KVM_CAP_ARM_NISV_TO_USER, 0)) { + error_report("Failed to enable KVM_CAP_ARM_NISV_TO_USER cap"); + } else { + /* Set status for supporting the external dabt injection */ + cap_has_inject_ext_dabt = kvm_check_extension(s, + KVM_CAP_ARM_INJECT_EXT_DABT); + } + } + return ret; } @@ -737,6 +765,29 @@ int kvm_get_vcpu_events(ARMCPU *cpu) void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) { + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + + if (unlikely(env->ext_dabt_raised)) { + /* + * Verifying that the ext DABT has been properly injected, + * otherwise risking indefinitely re-running the faulting instruction + * Covering a very narrow case for kernels 5.5..5.5.4 + * when injected abort was misconfigured to be + * an IMPLEMENTATION DEFINED exception (for 32-bit EL1) + */ + if (!arm_feature(env, ARM_FEATURE_AARCH64) && + unlikely(!kvm_arm_verify_ext_dabt_pending(cs))) { + + error_report("Data abort exception with no valid ISS generated by " + "guest memory access. KVM unable to emulate faulting " + "instruction. Failed to inject an external data abort " + "into the guest."); + abort(); + } + /* Clear the status */ + env->ext_dabt_raised = 0; + } } MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) @@ -809,6 +860,47 @@ void kvm_arm_vm_state_change(void *opaque, int running, RunState state) } } +/** + * kvm_arm_handle_dabt_nisv: + * @cs: CPUState + * @esr_iss: ISS encoding (limited) for the exception from Data Abort + * ISV bit set to '0b0' -> no valid instruction syndrome + * @fault_ipa: faulting address for the synchronous data abort + * + * Returns: 0 if the exception has been handled, < 0 otherwise + */ +static int kvm_arm_handle_dabt_nisv(CPUState *cs, uint64_t esr_iss, + uint64_t fault_ipa) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + /* + * Request KVM to inject the external data abort into the guest + */ + if (cap_has_inject_ext_dabt) { + struct kvm_vcpu_events events = { }; + /* + * The external data abort event will be handled immediately by KVM + * using the address fault that triggered the exit on given VCPU. + * Requesting injection of the external data abort does not rely + * on any other VCPU state. Therefore, in this particular case, the VCPU + * synchronization can be exceptionally skipped. + */ + events.exception.ext_dabt_pending = 1; + /* KVM_CAP_ARM_INJECT_EXT_DABT implies KVM_CAP_VCPU_EVENTS */ + if (!kvm_vcpu_ioctl(cs, KVM_SET_VCPU_EVENTS, &events)) { + env->ext_dabt_raised = 1; + return 0; + } + } else { + error_report("Data abort exception triggered by guest memory access " + "at physical address: 0x" TARGET_FMT_lx, + (target_ulong)fault_ipa); + error_printf("KVM unable to emulate faulting instruction.\n"); + } + return -1; +} + int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) { int ret = 0; @@ -819,6 +911,11 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) ret = EXCP_DEBUG; } /* otherwise return to guest */ break; + case KVM_EXIT_ARM_NISV: + /* External DABT with no valid iss to decode */ + ret = kvm_arm_handle_dabt_nisv(cs, run->arm_nisv.esr_iss, + run->arm_nisv.fault_ipa); + break; default: qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n", __func__, run->exit_reason); @@ -837,22 +934,15 @@ int kvm_arch_process_async_events(CPUState *cs) return 0; } -/* The #ifdef protections are until 32bit headers are imported and can - * be removed once both 32 and 64 bit reach feature parity. - */ void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg) { -#ifdef KVM_GUESTDBG_USE_SW_BP if (kvm_sw_breakpoints_active(cs)) { dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; } -#endif -#ifdef KVM_GUESTDBG_USE_HW if (kvm_arm_hw_debug_active(cs)) { dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW; kvm_arm_copy_hw_debug_data(&dbg->arch); } -#endif } void kvm_arch_init_irq_routing(KVMState *s) diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c deleted file mode 100644 index 7b3a19e9aef16b661d08097a1b37d6331ceee10b..0000000000000000000000000000000000000000 --- a/target/arm/kvm32.c +++ /dev/null @@ -1,561 +0,0 @@ -/* - * ARM implementation of KVM hooks, 32 bit specific code. - * - * Copyright Christoffer Dall 2009-2010 - * - * 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 - -#include - -#include "qemu-common.h" -#include "cpu.h" -#include "qemu/timer.h" -#include "sysemu/runstate.h" -#include "sysemu/kvm.h" -#include "kvm_arm.h" -#include "internals.h" -#include "qemu/log.h" - -static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id) -{ - struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)pret }; - - assert((id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U32); - return ioctl(fd, KVM_GET_ONE_REG, &idreg); -} - -bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) -{ - /* Identify the feature bits corresponding to the host CPU, and - * fill out the ARMHostCPUClass fields accordingly. To do this - * we have to create a scratch VM, create a single CPU inside it, - * and then query that CPU for the relevant ID registers. - */ - int err = 0, fdarray[3]; - uint32_t midr, id_pfr0; - uint64_t features = 0; - - /* Old kernels may not know about the PREFERRED_TARGET ioctl: however - * we know these will only support creating one kind of guest CPU, - * which is its preferred CPU type. - */ - static const uint32_t cpus_to_try[] = { - QEMU_KVM_ARM_TARGET_CORTEX_A15, - QEMU_KVM_ARM_TARGET_NONE - }; - /* - * target = -1 informs kvm_arm_create_scratch_host_vcpu() - * to use the preferred target - */ - struct kvm_vcpu_init init = { .target = -1, }; - - if (!kvm_arm_create_scratch_host_vcpu(cpus_to_try, fdarray, &init)) { - return false; - } - - ahcf->target = init.target; - - /* This is not strictly blessed by the device tree binding docs yet, - * but in practice the kernel does not care about this string so - * there is no point maintaining an KVM_ARM_TARGET_* -> string table. - */ - ahcf->dtb_compatible = "arm,arm-v7"; - - err |= read_sys_reg32(fdarray[2], &midr, ARM_CP15_REG32(0, 0, 0, 0)); - err |= read_sys_reg32(fdarray[2], &id_pfr0, ARM_CP15_REG32(0, 0, 1, 0)); - - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0, - ARM_CP15_REG32(0, 0, 2, 0)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1, - ARM_CP15_REG32(0, 0, 2, 1)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar2, - ARM_CP15_REG32(0, 0, 2, 2)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar3, - ARM_CP15_REG32(0, 0, 2, 3)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar4, - ARM_CP15_REG32(0, 0, 2, 4)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5, - ARM_CP15_REG32(0, 0, 2, 5)); - if (read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6, - ARM_CP15_REG32(0, 0, 2, 7))) { - /* - * Older kernels don't support reading ID_ISAR6. This register was - * only introduced in ARMv8, so we can assume that it is zero on a - * CPU that a kernel this old is running on. - */ - ahcf->isar.id_isar6 = 0; - } - - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0, - ARM_CP15_REG32(0, 0, 1, 2)); - - err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0, - KVM_REG_ARM | KVM_REG_SIZE_U32 | - KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR0); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr1, - KVM_REG_ARM | KVM_REG_SIZE_U32 | - KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR1); - /* - * FIXME: There is not yet a way to read MVFR2. - * Fortunately there is not yet anything in there that affects migration. - */ - - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0, - ARM_CP15_REG32(0, 0, 1, 4)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1, - ARM_CP15_REG32(0, 0, 1, 5)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2, - ARM_CP15_REG32(0, 0, 1, 6)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3, - ARM_CP15_REG32(0, 0, 1, 7)); - if (read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4, - ARM_CP15_REG32(0, 0, 2, 6))) { - /* - * Older kernels don't support reading ID_MMFR4 (a new in v8 - * register); assume it's zero. - */ - ahcf->isar.id_mmfr4 = 0; - } - - /* - * There is no way to read DBGDIDR, because currently 32-bit KVM - * doesn't implement debug at all. Leave it at zero. - */ - - kvm_arm_destroy_scratch_host_vcpu(fdarray); - - if (err < 0) { - return false; - } - - /* Now we've retrieved all the register information we can - * set the feature bits based on the ID register fields. - * We can assume any KVM supporting CPU is at least a v7 - * with VFPv3, virtualization extensions, and the generic - * timers; this in turn implies most of the other feature - * bits, but a few must be tested. - */ - features |= 1ULL << ARM_FEATURE_V7VE; - features |= 1ULL << ARM_FEATURE_GENERIC_TIMER; - - if (extract32(id_pfr0, 12, 4) == 1) { - features |= 1ULL << ARM_FEATURE_THUMB2EE; - } - if (extract32(ahcf->isar.mvfr1, 12, 4) == 1) { - features |= 1ULL << ARM_FEATURE_NEON; - } - - ahcf->features = features; - - return true; -} - -bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx) -{ - /* Return true if the regidx is a register we should synchronize - * via the cpreg_tuples array (ie is not a core reg we sync by - * hand in kvm_arch_get/put_registers()) - */ - switch (regidx & KVM_REG_ARM_COPROC_MASK) { - case KVM_REG_ARM_CORE: - case KVM_REG_ARM_VFP: - return false; - default: - return true; - } -} - -typedef struct CPRegStateLevel { - uint64_t regidx; - int level; -} CPRegStateLevel; - -/* All coprocessor registers not listed in the following table are assumed to - * be of the level KVM_PUT_RUNTIME_STATE. If a register should be written less - * often, you must add it to this table with a state of either - * KVM_PUT_RESET_STATE or KVM_PUT_FULL_STATE. - */ -static const CPRegStateLevel non_runtime_cpregs[] = { - { KVM_REG_ARM_TIMER_CNT, KVM_PUT_FULL_STATE }, -}; - -int kvm_arm_cpreg_level(uint64_t regidx) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(non_runtime_cpregs); i++) { - const CPRegStateLevel *l = &non_runtime_cpregs[i]; - if (l->regidx == regidx) { - return l->level; - } - } - - return KVM_PUT_RUNTIME_STATE; -} - -#define ARM_CPU_ID_MPIDR 0, 0, 0, 5 - -int kvm_arch_init_vcpu(CPUState *cs) -{ - int ret; - uint64_t v; - uint32_t mpidr; - struct kvm_one_reg r; - ARMCPU *cpu = ARM_CPU(cs); - - if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE) { - fprintf(stderr, "KVM is not supported for this guest CPU type\n"); - return -EINVAL; - } - - qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs); - - /* Determine init features for this CPU */ - memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features)); - if (cpu->start_powered_off) { - cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_POWER_OFF; - } - if (kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PSCI_0_2)) { - cpu->psci_version = 2; - cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_PSCI_0_2; - } - - /* Do KVM_ARM_VCPU_INIT ioctl */ - ret = kvm_arm_vcpu_init(cs); - if (ret) { - return ret; - } - - /* Query the kernel to make sure it supports 32 VFP - * registers: QEMU's "cortex-a15" CPU is always a - * VFP-D32 core. The simplest way to do this is just - * to attempt to read register d31. - */ - r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP | 31; - r.addr = (uintptr_t)(&v); - ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r); - if (ret == -ENOENT) { - return -EINVAL; - } - - /* - * When KVM is in use, PSCI is emulated in-kernel and not by qemu. - * Currently KVM has its own idea about MPIDR assignment, so we - * override our defaults with what we get from KVM. - */ - ret = kvm_get_one_reg(cs, ARM_CP15_REG32(ARM_CPU_ID_MPIDR), &mpidr); - if (ret) { - return ret; - } - cpu->mp_affinity = mpidr & ARM32_AFFINITY_MASK; - - /* Check whether userspace can specify guest syndrome value */ - kvm_arm_init_serror_injection(cs); - - return kvm_arm_init_cpreg_list(cpu); -} - -int kvm_arch_destroy_vcpu(CPUState *cs) -{ - return 0; -} - -typedef struct Reg { - uint64_t id; - int offset; -} Reg; - -#define COREREG(KERNELNAME, QEMUFIELD) \ - { \ - KVM_REG_ARM | KVM_REG_SIZE_U32 | \ - KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \ - offsetof(CPUARMState, QEMUFIELD) \ - } - -#define VFPSYSREG(R) \ - { \ - KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP | \ - KVM_REG_ARM_VFP_##R, \ - offsetof(CPUARMState, vfp.xregs[ARM_VFP_##R]) \ - } - -/* Like COREREG, but handle fields which are in a uint64_t in CPUARMState. */ -#define COREREG64(KERNELNAME, QEMUFIELD) \ - { \ - KVM_REG_ARM | KVM_REG_SIZE_U32 | \ - KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \ - offsetoflow32(CPUARMState, QEMUFIELD) \ - } - -static const Reg regs[] = { - /* R0_usr .. R14_usr */ - COREREG(usr_regs.uregs[0], regs[0]), - COREREG(usr_regs.uregs[1], regs[1]), - COREREG(usr_regs.uregs[2], regs[2]), - COREREG(usr_regs.uregs[3], regs[3]), - COREREG(usr_regs.uregs[4], regs[4]), - COREREG(usr_regs.uregs[5], regs[5]), - COREREG(usr_regs.uregs[6], regs[6]), - COREREG(usr_regs.uregs[7], regs[7]), - COREREG(usr_regs.uregs[8], usr_regs[0]), - COREREG(usr_regs.uregs[9], usr_regs[1]), - COREREG(usr_regs.uregs[10], usr_regs[2]), - COREREG(usr_regs.uregs[11], usr_regs[3]), - COREREG(usr_regs.uregs[12], usr_regs[4]), - COREREG(usr_regs.uregs[13], banked_r13[BANK_USRSYS]), - COREREG(usr_regs.uregs[14], banked_r14[BANK_USRSYS]), - /* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */ - COREREG(svc_regs[0], banked_r13[BANK_SVC]), - COREREG(svc_regs[1], banked_r14[BANK_SVC]), - COREREG64(svc_regs[2], banked_spsr[BANK_SVC]), - COREREG(abt_regs[0], banked_r13[BANK_ABT]), - COREREG(abt_regs[1], banked_r14[BANK_ABT]), - COREREG64(abt_regs[2], banked_spsr[BANK_ABT]), - COREREG(und_regs[0], banked_r13[BANK_UND]), - COREREG(und_regs[1], banked_r14[BANK_UND]), - COREREG64(und_regs[2], banked_spsr[BANK_UND]), - COREREG(irq_regs[0], banked_r13[BANK_IRQ]), - COREREG(irq_regs[1], banked_r14[BANK_IRQ]), - COREREG64(irq_regs[2], banked_spsr[BANK_IRQ]), - /* R8_fiq .. R14_fiq and SPSR_fiq */ - COREREG(fiq_regs[0], fiq_regs[0]), - COREREG(fiq_regs[1], fiq_regs[1]), - COREREG(fiq_regs[2], fiq_regs[2]), - COREREG(fiq_regs[3], fiq_regs[3]), - COREREG(fiq_regs[4], fiq_regs[4]), - COREREG(fiq_regs[5], banked_r13[BANK_FIQ]), - COREREG(fiq_regs[6], banked_r14[BANK_FIQ]), - COREREG64(fiq_regs[7], banked_spsr[BANK_FIQ]), - /* R15 */ - COREREG(usr_regs.uregs[15], regs[15]), - /* VFP system registers */ - VFPSYSREG(FPSID), - VFPSYSREG(MVFR1), - VFPSYSREG(MVFR0), - VFPSYSREG(FPEXC), - VFPSYSREG(FPINST), - VFPSYSREG(FPINST2), -}; - -int kvm_arch_put_registers(CPUState *cs, int level) -{ - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; - struct kvm_one_reg r; - int mode, bn; - int ret, i; - uint32_t cpsr, fpscr; - - /* Make sure the banked regs are properly set */ - mode = env->uncached_cpsr & CPSR_M; - bn = bank_number(mode); - if (mode == ARM_CPU_MODE_FIQ) { - memcpy(env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t)); - } else { - memcpy(env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t)); - } - env->banked_r13[bn] = env->regs[13]; - env->banked_spsr[bn] = env->spsr; - env->banked_r14[r14_bank_number(mode)] = env->regs[14]; - - /* Now we can safely copy stuff down to the kernel */ - for (i = 0; i < ARRAY_SIZE(regs); i++) { - r.id = regs[i].id; - r.addr = (uintptr_t)(env) + regs[i].offset; - ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r); - if (ret) { - return ret; - } - } - - /* Special cases which aren't a single CPUARMState field */ - cpsr = cpsr_read(env); - r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | - KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr); - r.addr = (uintptr_t)(&cpsr); - ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r); - if (ret) { - return ret; - } - - /* VFP registers */ - r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP; - for (i = 0; i < 32; i++) { - r.addr = (uintptr_t)aa32_vfp_dreg(env, i); - ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r); - if (ret) { - return ret; - } - r.id++; - } - - r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP | - KVM_REG_ARM_VFP_FPSCR; - fpscr = vfp_get_fpscr(env); - r.addr = (uintptr_t)&fpscr; - ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r); - if (ret) { - return ret; - } - - write_cpustate_to_list(cpu, true); - - if (!write_list_to_kvmstate(cpu, level)) { - return EINVAL; - } - - /* - * Setting VCPU events should be triggered after syncing the registers - * to avoid overwriting potential changes made by KVM upon calling - * KVM_SET_VCPU_EVENTS ioctl - */ - ret = kvm_put_vcpu_events(cpu); - if (ret) { - return ret; - } - - kvm_arm_sync_mpstate_to_kvm(cpu); - - return ret; -} - -int kvm_arch_get_registers(CPUState *cs) -{ - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; - struct kvm_one_reg r; - int mode, bn; - int ret, i; - uint32_t cpsr, fpscr; - - for (i = 0; i < ARRAY_SIZE(regs); i++) { - r.id = regs[i].id; - r.addr = (uintptr_t)(env) + regs[i].offset; - ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r); - if (ret) { - return ret; - } - } - - /* Special cases which aren't a single CPUARMState field */ - r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | - KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr); - r.addr = (uintptr_t)(&cpsr); - ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r); - if (ret) { - return ret; - } - cpsr_write(env, cpsr, 0xffffffff, CPSRWriteRaw); - - /* Make sure the current mode regs are properly set */ - mode = env->uncached_cpsr & CPSR_M; - bn = bank_number(mode); - if (mode == ARM_CPU_MODE_FIQ) { - memcpy(env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t)); - } else { - memcpy(env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t)); - } - env->regs[13] = env->banked_r13[bn]; - env->spsr = env->banked_spsr[bn]; - env->regs[14] = env->banked_r14[r14_bank_number(mode)]; - - /* VFP registers */ - r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP; - for (i = 0; i < 32; i++) { - r.addr = (uintptr_t)aa32_vfp_dreg(env, i); - ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r); - if (ret) { - return ret; - } - r.id++; - } - - r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP | - KVM_REG_ARM_VFP_FPSCR; - r.addr = (uintptr_t)&fpscr; - ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r); - if (ret) { - return ret; - } - vfp_set_fpscr(env, fpscr); - - ret = kvm_get_vcpu_events(cpu); - if (ret) { - return ret; - } - - if (!write_kvmstate_to_list(cpu)) { - return EINVAL; - } - /* Note that it's OK to have registers which aren't in CPUState, - * so we can ignore a failure return here. - */ - write_list_to_cpustate(cpu); - - kvm_arm_sync_mpstate_to_qemu(cpu); - - return 0; -} - -int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) -{ - qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__); - return -EINVAL; -} - -int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) -{ - qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__); - return -EINVAL; -} - -bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit) -{ - qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__); - return false; -} - -int kvm_arch_insert_hw_breakpoint(target_ulong addr, - target_ulong len, int type) -{ - qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__); - return -EINVAL; -} - -int kvm_arch_remove_hw_breakpoint(target_ulong addr, - target_ulong len, int type) -{ - qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__); - return -EINVAL; -} - -void kvm_arch_remove_all_hw_breakpoints(void) -{ - qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__); -} - -void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr) -{ - qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__); -} - -bool kvm_arm_hw_debug_active(CPUState *cs) -{ - return false; -} - -void kvm_arm_pmu_set_irq(CPUState *cs, int irq) -{ - qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__); -} - -void kvm_arm_pmu_init(CPUState *cs) -{ - qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__); -} diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index f09ed9f4df349446f017927bd65c965e3952a956..f74bac24574d49cc90b91d2a3954aa0b90f0c415 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -17,6 +17,7 @@ #include #include "qemu-common.h" +#include "qapi/error.h" #include "cpu.h" #include "qemu/timer.h" #include "qemu/error-report.h" @@ -330,7 +331,6 @@ int kvm_arch_remove_hw_breakpoint(target_ulong addr, switch (type) { case GDB_BREAKPOINT_HW: return delete_hw_breakpoint(addr); - break; case GDB_WATCHPOINT_READ: case GDB_WATCHPOINT_WRITE: case GDB_WATCHPOINT_ACCESS: @@ -398,19 +398,20 @@ static CPUWatchpoint *find_hw_watchpoint(CPUState *cpu, target_ulong addr) return NULL; } -static bool kvm_arm_pmu_set_attr(CPUState *cs, struct kvm_device_attr *attr) +static bool kvm_arm_set_device_attr(CPUState *cs, struct kvm_device_attr *attr, + const char *name) { int err; err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr); if (err != 0) { - error_report("PMU: KVM_HAS_DEVICE_ATTR: %s", strerror(-err)); + error_report("%s: KVM_HAS_DEVICE_ATTR: %s", name, strerror(-err)); return false; } err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, attr); if (err != 0) { - error_report("PMU: KVM_SET_DEVICE_ATTR: %s", strerror(-err)); + error_report("%s: KVM_SET_DEVICE_ATTR: %s", name, strerror(-err)); return false; } @@ -427,7 +428,7 @@ void kvm_arm_pmu_init(CPUState *cs) if (!ARM_CPU(cs)->has_pmu) { return; } - if (!kvm_arm_pmu_set_attr(cs, &attr)) { + if (!kvm_arm_set_device_attr(cs, &attr, "PMU")) { error_report("failed to init PMU"); abort(); } @@ -444,12 +445,29 @@ void kvm_arm_pmu_set_irq(CPUState *cs, int irq) if (!ARM_CPU(cs)->has_pmu) { return; } - if (!kvm_arm_pmu_set_attr(cs, &attr)) { + if (!kvm_arm_set_device_attr(cs, &attr, "PMU")) { error_report("failed to set irq for PMU"); abort(); } } +void kvm_arm_pvtime_init(CPUState *cs, uint64_t ipa) +{ + struct kvm_device_attr attr = { + .group = KVM_ARM_VCPU_PVTIME_CTRL, + .attr = KVM_ARM_VCPU_PVTIME_IPA, + .addr = (uint64_t)&ipa, + }; + + if (ARM_CPU(cs)->kvm_steal_time == ON_OFF_AUTO_OFF) { + return; + } + if (!kvm_arm_set_device_attr(cs, &attr, "PVTIME IPA")) { + error_report("failed to init PVTIME IPA"); + abort(); + } +} + static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id) { uint64_t ret; @@ -556,6 +574,10 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) * than skipping the reads and leaving 0, as we must avoid * considering the values in every case. */ + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr0, + ARM64_SYS_REG(3, 0, 0, 1, 0)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr1, + ARM64_SYS_REG(3, 0, 0, 1, 1)); err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0, ARM64_SYS_REG(3, 0, 0, 1, 2)); err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0, @@ -652,18 +674,49 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) return true; } -bool kvm_arm_aarch32_supported(CPUState *cpu) +void kvm_arm_steal_time_finalize(ARMCPU *cpu, Error **errp) { - KVMState *s = KVM_STATE(current_accel()); + bool has_steal_time = kvm_arm_steal_time_supported(); - return kvm_check_extension(s, KVM_CAP_ARM_EL1_32BIT); + if (cpu->kvm_steal_time == ON_OFF_AUTO_AUTO) { + if (!has_steal_time || !arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { + cpu->kvm_steal_time = ON_OFF_AUTO_OFF; + } else { + cpu->kvm_steal_time = ON_OFF_AUTO_ON; + } + } else if (cpu->kvm_steal_time == ON_OFF_AUTO_ON) { + if (!has_steal_time) { + error_setg(errp, "'kvm-steal-time' cannot be enabled " + "on this host"); + return; + } else if (!arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { + /* + * DEN0057A chapter 2 says "This specification only covers + * systems in which the Execution state of the hypervisor + * as well as EL1 of virtual machines is AArch64.". And, + * to ensure that, the smc/hvc calls are only specified as + * smc64/hvc64. + */ + error_setg(errp, "'kvm-steal-time' cannot be enabled " + "for AArch32 guests"); + return; + } + } } -bool kvm_arm_sve_supported(CPUState *cpu) +bool kvm_arm_aarch32_supported(void) { - KVMState *s = KVM_STATE(current_accel()); + return kvm_check_extension(kvm_state, KVM_CAP_ARM_EL1_32BIT); +} - return kvm_check_extension(s, KVM_CAP_ARM_SVE); +bool kvm_arm_sve_supported(void) +{ + return kvm_check_extension(kvm_state, KVM_CAP_ARM_SVE); +} + +bool kvm_arm_steal_time_supported(void) +{ + return kvm_check_extension(kvm_state, KVM_CAP_STEAL_TIME); } QEMU_BUILD_BUG_ON(KVM_ARM64_SVE_VQ_MIN != 1); @@ -779,7 +832,7 @@ int kvm_arch_init_vcpu(CPUState *cs) /* Determine init features for this CPU */ memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features)); - if (cpu->start_powered_off) { + if (cs->start_powered_off) { cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_POWER_OFF; } if (kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PSCI_0_2)) { @@ -798,7 +851,7 @@ int kvm_arch_init_vcpu(CPUState *cs) env->features &= ~(1ULL << ARM_FEATURE_PMU); } if (cpu_isar_feature(aa64_sve, cpu)) { - assert(kvm_arm_sve_supported(cs)); + assert(kvm_arm_sve_supported()); cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_SVE; } @@ -1497,3 +1550,52 @@ bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit) return false; } + +#define ARM64_REG_ESR_EL1 ARM64_SYS_REG(3, 0, 5, 2, 0) +#define ARM64_REG_TCR_EL1 ARM64_SYS_REG(3, 0, 2, 0, 2) + +/* + * ESR_EL1 + * ISS encoding + * AARCH64: DFSC, bits [5:0] + * AARCH32: + * TTBCR.EAE == 0 + * FS[4] - DFSR[10] + * FS[3:0] - DFSR[3:0] + * TTBCR.EAE == 1 + * FS, bits [5:0] + */ +#define ESR_DFSC(aarch64, lpae, v) \ + ((aarch64 || (lpae)) ? ((v) & 0x3F) \ + : (((v) >> 6) | ((v) & 0x1F))) + +#define ESR_DFSC_EXTABT(aarch64, lpae) \ + ((aarch64) ? 0x10 : (lpae) ? 0x10 : 0x8) + +bool kvm_arm_verify_ext_dabt_pending(CPUState *cs) +{ + uint64_t dfsr_val; + + if (!kvm_get_one_reg(cs, ARM64_REG_ESR_EL1, &dfsr_val)) { + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + int aarch64_mode = arm_feature(env, ARM_FEATURE_AARCH64); + int lpae = 0; + + if (!aarch64_mode) { + uint64_t ttbcr; + + if (!kvm_get_one_reg(cs, ARM64_REG_TCR_EL1, &ttbcr)) { + lpae = arm_feature(env, ARM_FEATURE_LPAE) + && (ttbcr & TTBCR_EAE); + } + } + /* + * The verification here is based on the DFSC bits + * of the ESR_EL1 reg only + */ + return (ESR_DFSC(aarch64_mode, lpae, dfsr_val) == + ESR_DFSC_EXTABT(aarch64_mode, lpae)); + } + return false; +} diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h index 48bf5e16d58bbfa11480c27a252f9115d45295ac..eb81b7059eb1c444be134a77662b4c9784404e23 100644 --- a/target/arm/kvm_arm.h +++ b/target/arm/kvm_arm.h @@ -267,31 +267,46 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu); */ void kvm_arm_add_vcpu_properties(Object *obj); +/** + * kvm_arm_steal_time_finalize: + * @cpu: ARMCPU for which to finalize kvm-steal-time + * @errp: Pointer to Error* for error propagation + * + * Validate the kvm-steal-time property selection and set its default + * based on KVM support and guest configuration. + */ +void kvm_arm_steal_time_finalize(ARMCPU *cpu, Error **errp); + +/** + * kvm_arm_steal_time_supported: + * + * Returns: true if KVM can enable steal time reporting + * and false otherwise. + */ +bool kvm_arm_steal_time_supported(void); + /** * kvm_arm_aarch32_supported: - * @cs: CPUState * - * Returns: true if the KVM VCPU can enable AArch32 mode + * Returns: true if KVM can enable AArch32 mode * and false otherwise. */ -bool kvm_arm_aarch32_supported(CPUState *cs); +bool kvm_arm_aarch32_supported(void); /** * kvm_arm_pmu_supported: - * @cs: CPUState * - * Returns: true if the KVM VCPU can enable its PMU + * Returns: true if KVM can enable the PMU * and false otherwise. */ -bool kvm_arm_pmu_supported(CPUState *cs); +bool kvm_arm_pmu_supported(void); /** * kvm_arm_sve_supported: - * @cs: CPUState * - * Returns true if the KVM VCPU can enable SVE and false otherwise. + * Returns true if KVM can enable SVE and false otherwise. */ -bool kvm_arm_sve_supported(CPUState *cs); +bool kvm_arm_sve_supported(void); /** * kvm_arm_get_max_vm_ipa_size: @@ -343,54 +358,92 @@ int kvm_arm_vgic_probe(void); void kvm_arm_pmu_set_irq(CPUState *cs, int irq); void kvm_arm_pmu_init(CPUState *cs); + +/** + * kvm_arm_pvtime_init: + * @cs: CPUState + * @ipa: Per-vcpu guest physical base address of the pvtime structures + * + * Initializes PVTIME for the VCPU, setting the PVTIME IPA to @ipa. + */ +void kvm_arm_pvtime_init(CPUState *cs, uint64_t ipa); + int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level); #else -static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) +/* + * It's safe to call these functions without KVM support. + * They should either do nothing or return "not supported". + */ +static inline bool kvm_arm_aarch32_supported(void) { - /* - * This should never actually be called in the "not KVM" case, - * but set up the fields to indicate an error anyway. - */ - cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE; - cpu->host_cpu_probe_failed = true; + return false; } -static inline void kvm_arm_add_vcpu_properties(Object *obj) {} - -static inline bool kvm_arm_aarch32_supported(CPUState *cs) +static inline bool kvm_arm_pmu_supported(void) { return false; } -static inline bool kvm_arm_pmu_supported(CPUState *cs) +static inline bool kvm_arm_sve_supported(void) { return false; } -static inline bool kvm_arm_sve_supported(CPUState *cs) +static inline bool kvm_arm_steal_time_supported(void) { return false; } +/* + * These functions should never actually be called without KVM support. + */ +static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) +{ + g_assert_not_reached(); +} + +static inline void kvm_arm_add_vcpu_properties(Object *obj) +{ + g_assert_not_reached(); +} + static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms) { - return -ENOENT; + g_assert_not_reached(); } static inline int kvm_arm_vgic_probe(void) { - return 0; + g_assert_not_reached(); +} + +static inline void kvm_arm_pmu_set_irq(CPUState *cs, int irq) +{ + g_assert_not_reached(); +} + +static inline void kvm_arm_pmu_init(CPUState *cs) +{ + g_assert_not_reached(); +} + +static inline void kvm_arm_pvtime_init(CPUState *cs, uint64_t ipa) +{ + g_assert_not_reached(); } -static inline void kvm_arm_pmu_set_irq(CPUState *cs, int irq) {} -static inline void kvm_arm_pmu_init(CPUState *cs) {} +static inline void kvm_arm_steal_time_finalize(ARMCPU *cpu, Error **errp) +{ + g_assert_not_reached(); +} -static inline void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map) {} +static inline void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map) +{ + g_assert_not_reached(); +} -static inline void kvm_arm_get_virtual_time(CPUState *cs) {} -static inline void kvm_arm_put_virtual_time(CPUState *cs) {} #endif static inline const char *gic_class_name(void) @@ -409,13 +462,7 @@ static inline const char *gic_class_name(void) static inline const char *gicv3_class_name(void) { if (kvm_irqchip_in_kernel()) { -#ifdef TARGET_AARCH64 return "kvm-arm-gicv3"; -#else - error_report("KVM GICv3 acceleration is not supported on this " - "platform"); - exit(1); -#endif } else { if (kvm_enabled()) { error_report("Userspace GICv3 is not supported with KVM"); @@ -452,6 +499,16 @@ bool kvm_arm_hw_debug_active(CPUState *cs); struct kvm_guest_debug_arch; void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr); +/** + * kvm_arm_verify_ext_dabt_pending: + * @cs: CPUState + * + * Verify the fault status code wrt the Ext DABT injection + * + * Returns: true if the fault status code is as expected, false otherwise + */ +bool kvm_arm_verify_ext_dabt_pending(CPUState *cs); + /** * its_class_name: * diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode new file mode 100644 index 0000000000000000000000000000000000000000..28c8ac6b94ccc2a8cf70dd5b583ca1f1ace5af87 --- /dev/null +++ b/target/arm/m-nocp.decode @@ -0,0 +1,44 @@ +# M-profile UserFault.NOCP exception handling +# +# Copyright (c) 2020 Linaro, Ltd +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see . + +# +# This file is processed by scripts/decodetree.py +# +# For M-profile, the architecture specifies that NOCP UsageFaults +# should take precedence over UNDEF faults over the whole wide +# range of coprocessor-space encodings, with the exception of +# VLLDM and VLSTM. (Compare v8.1M IsCPInstruction() pseudocode and +# v8M Arm ARM rule R_QLGM.) This isn't mandatory for v8.0M but we choose +# to behave the same as v8.1M. +# This decode is handled before any others (and in particular before +# decoding FP instructions which are in the coprocessor space). +# If the coprocessor is not present or disabled then we will generate +# the NOCP exception; otherwise we let the insn through to the main decode. + +&nocp cp + +{ + # Special cases which do not take an early NOCP: VLLDM and VLSTM + VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000 + # TODO: VSCCLRM (new in v8.1M) is similar: + #VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0 + + NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp + NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp + # From v8.1M onwards this range will also NOCP: + NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- &nocp cp=10 +} diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c index 5e8a795d2028c9b0de325b26910b78a9bcad00f1..aad01ea0127eb7f1084b9e2d2d58d785575b9e54 100644 --- a/target/arm/m_helper.c +++ b/target/arm/m_helper.c @@ -187,12 +187,13 @@ static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value, hwaddr physaddr; int prot; ARMMMUFaultInfo fi = {}; + ARMCacheAttrs cacheattrs = {}; bool secure = mmu_idx & ARM_MMU_IDX_M_S; int exc; bool exc_secure; if (get_phys_addr(env, addr, MMU_DATA_STORE, mmu_idx, &physaddr, - &attrs, &prot, &page_size, &fi, NULL)) { + &attrs, &prot, &page_size, &fi, &cacheattrs)) { /* MPU/SAU lookup failed */ if (fi.type == ARMFault_QEMU_SFault) { if (mode == STACK_LAZYFP) { @@ -279,13 +280,14 @@ static bool v7m_stack_read(ARMCPU *cpu, uint32_t *dest, uint32_t addr, hwaddr physaddr; int prot; ARMMMUFaultInfo fi = {}; + ARMCacheAttrs cacheattrs = {}; bool secure = mmu_idx & ARM_MMU_IDX_M_S; int exc; bool exc_secure; uint32_t value; if (get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &physaddr, - &attrs, &prot, &page_size, &fi, NULL)) { + &attrs, &prot, &page_size, &fi, &cacheattrs)) { /* MPU/SAU lookup failed */ if (fi.type == ARMFault_QEMU_SFault) { qemu_log_mask(CPU_LOG_INT, @@ -1928,6 +1930,7 @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx, V8M_SAttributes sattrs = {}; MemTxAttrs attrs = {}; ARMMMUFaultInfo fi = {}; + ARMCacheAttrs cacheattrs = {}; MemTxResult txres; target_ulong page_size; hwaddr physaddr; @@ -1945,8 +1948,8 @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx, "...really SecureFault with SFSR.INVEP\n"); return false; } - if (get_phys_addr(env, addr, MMU_INST_FETCH, mmu_idx, - &physaddr, &attrs, &prot, &page_size, &fi, NULL)) { + if (get_phys_addr(env, addr, MMU_INST_FETCH, mmu_idx, &physaddr, + &attrs, &prot, &page_size, &fi, &cacheattrs)) { /* the MPU lookup failed */ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_IACCVIOL_MASK; armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM, env->v7m.secure); @@ -2716,7 +2719,8 @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env, /* Return the MMU index for a v7M CPU in the specified security state */ ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate) { - bool priv = arm_current_el(env) != 0; + bool priv = arm_v7m_is_handler_mode(env) || + !(env->v7m.control[secstate] & 1); return arm_v7m_mmu_idx_for_secstate_and_priv(env, secstate, priv); } diff --git a/target/arm/meson.build b/target/arm/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..f5de2a77b89f30ef1203ee943a82be90747368e9 --- /dev/null +++ b/target/arm/meson.build @@ -0,0 +1,60 @@ +gen = [ + decodetree.process('sve.decode', extra_args: '--decode=disas_sve'), + decodetree.process('neon-shared.decode', extra_args: '--static-decode=disas_neon_shared'), + decodetree.process('neon-dp.decode', extra_args: '--static-decode=disas_neon_dp'), + decodetree.process('neon-ls.decode', extra_args: '--static-decode=disas_neon_ls'), + decodetree.process('vfp.decode', extra_args: '--static-decode=disas_vfp'), + decodetree.process('vfp-uncond.decode', extra_args: '--static-decode=disas_vfp_uncond'), + decodetree.process('m-nocp.decode', extra_args: '--static-decode=disas_m_nocp'), + decodetree.process('a32.decode', extra_args: '--static-decode=disas_a32'), + decodetree.process('a32-uncond.decode', extra_args: '--static-decode=disas_a32_uncond'), + decodetree.process('t32.decode', extra_args: '--static-decode=disas_t32'), + decodetree.process('t16.decode', extra_args: ['-w', '16', '--static-decode=disas_t16']), +] + +arm_ss = ss.source_set() +arm_ss.add(gen) +arm_ss.add(files( + 'cpu.c', + 'crypto_helper.c', + 'debug_helper.c', + 'gdbstub.c', + 'helper.c', + 'iwmmxt_helper.c', + 'm_helper.c', + 'neon_helper.c', + 'op_helper.c', + 'tlb_helper.c', + 'translate.c', + 'vec_helper.c', + 'vfp_helper.c', + 'cpu_tcg.c', +)) +arm_ss.add(zlib) + +arm_ss.add(when: 'CONFIG_TCG', if_true: files('arm-semi.c')) + +arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c')) + +arm_ss.add(when: 'TARGET_AARCH64', if_true: files( + 'cpu64.c', + 'gdbstub64.c', + 'helper-a64.c', + 'mte_helper.c', + 'pauth_helper.c', + 'sve_helper.c', + 'translate-a64.c', + 'translate-sve.c', +)) + +arm_softmmu_ss = ss.source_set() +arm_softmmu_ss.add(files( + 'arch_dump.c', + 'arm-powerctl.c', + 'machine.c', + 'monitor.c', + 'psci.c', +)) + +target_arch += {'arm': arm_ss} +target_softmmu_arch += {'arm': arm_softmmu_ss} diff --git a/target/arm/monitor.c b/target/arm/monitor.c index ea6598c412433290f9e17254a32843a3fd1d2132..169d8a64b651d23b9e6a2bd16ef3fa3b1f6f9951 100644 --- a/target/arm/monitor.c +++ b/target/arm/monitor.c @@ -103,7 +103,7 @@ static const char *cpu_model_advertised_features[] = { "sve128", "sve256", "sve384", "sve512", "sve640", "sve768", "sve896", "sve1024", "sve1152", "sve1280", "sve1408", "sve1536", "sve1664", "sve1792", "sve1920", "sve2048", - "kvm-no-adjvtime", + "kvm-no-adjvtime", "kvm-steal-time", NULL }; @@ -174,19 +174,16 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, Error *err = NULL; visitor = qobject_input_visitor_new(model->props); - visit_start_struct(visitor, NULL, NULL, 0, &err); - if (err) { + if (!visit_start_struct(visitor, NULL, NULL, 0, errp)) { visit_free(visitor); object_unref(obj); - error_propagate(errp, err); return NULL; } i = 0; while ((name = cpu_model_advertised_features[i++]) != NULL) { if (qdict_get(qdict_in, name)) { - object_property_set(obj, visitor, name, &err); - if (err) { + if (!object_property_set(obj, name, visitor, &err)) { break; } } @@ -217,7 +214,7 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, i = 0; while ((name = cpu_model_advertised_features[i++]) != NULL) { - ObjectProperty *prop = object_property_find(obj, name, NULL); + ObjectProperty *prop = object_property_find(obj, name); if (prop) { QObject *value; diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c new file mode 100644 index 0000000000000000000000000000000000000000..153bd1e9df889eb08259857daf3633ff9e39efde --- /dev/null +++ b/target/arm/mte_helper.c @@ -0,0 +1,925 @@ +/* + * ARM v8.5-MemTag Operations + * + * Copyright (c) 2020 Linaro, Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "internals.h" +#include "exec/exec-all.h" +#include "exec/ram_addr.h" +#include "exec/cpu_ldst.h" +#include "exec/helper-proto.h" +#include "qapi/error.h" +#include "qemu/guest-random.h" + + +static int choose_nonexcluded_tag(int tag, int offset, uint16_t exclude) +{ + if (exclude == 0xffff) { + return 0; + } + if (offset == 0) { + while (exclude & (1 << tag)) { + tag = (tag + 1) & 15; + } + } else { + do { + do { + tag = (tag + 1) & 15; + } while (exclude & (1 << tag)); + } while (--offset > 0); + } + return tag; +} + +/** + * allocation_tag_mem: + * @env: the cpu environment + * @ptr_mmu_idx: the addressing regime to use for the virtual address + * @ptr: the virtual address for which to look up tag memory + * @ptr_access: the access to use for the virtual address + * @ptr_size: the number of bytes in the normal memory access + * @tag_access: the access to use for the tag memory + * @tag_size: the number of bytes in the tag memory access + * @ra: the return address for exception handling + * + * Our tag memory is formatted as a sequence of little-endian nibbles. + * That is, the byte at (addr >> (LOG2_TAG_GRANULE + 1)) contains two + * tags, with the tag at [3:0] for the lower addr and the tag at [7:4] + * for the higher addr. + * + * Here, resolve the physical address from the virtual address, and return + * a pointer to the corresponding tag byte. Exit with exception if the + * virtual address is not accessible for @ptr_access. + * + * The @ptr_size and @tag_size values may not have an obvious relation + * due to the alignment of @ptr, and the number of tag checks required. + * + * If there is no tag storage corresponding to @ptr, return NULL. + */ +static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx, + uint64_t ptr, MMUAccessType ptr_access, + int ptr_size, MMUAccessType tag_access, + int tag_size, uintptr_t ra) +{ +#ifdef CONFIG_USER_ONLY + /* Tag storage not implemented. */ + return NULL; +#else + uintptr_t index; + CPUIOTLBEntry *iotlbentry; + int in_page, flags; + ram_addr_t ptr_ra; + hwaddr ptr_paddr, tag_paddr, xlat; + MemoryRegion *mr; + ARMASIdx tag_asi; + AddressSpace *tag_as; + void *host; + + /* + * Probe the first byte of the virtual address. This raises an + * exception for inaccessible pages, and resolves the virtual address + * into the softmmu tlb. + * + * When RA == 0, this is for mte_probe1. The page is expected to be + * valid. Indicate to probe_access_flags no-fault, then assert that + * we received a valid page. + */ + flags = probe_access_flags(env, ptr, ptr_access, ptr_mmu_idx, + ra == 0, &host, ra); + assert(!(flags & TLB_INVALID_MASK)); + + /* + * Find the iotlbentry for ptr. This *must* be present in the TLB + * because we just found the mapping. + * TODO: Perhaps there should be a cputlb helper that returns a + * matching tlb entry + iotlb entry. + */ + index = tlb_index(env, ptr_mmu_idx, ptr); +# ifdef CONFIG_DEBUG_TCG + { + CPUTLBEntry *entry = tlb_entry(env, ptr_mmu_idx, ptr); + target_ulong comparator = (ptr_access == MMU_DATA_LOAD + ? entry->addr_read + : tlb_addr_write(entry)); + g_assert(tlb_hit(comparator, ptr)); + } +# endif + iotlbentry = &env_tlb(env)->d[ptr_mmu_idx].iotlb[index]; + + /* If the virtual page MemAttr != Tagged, access unchecked. */ + if (!arm_tlb_mte_tagged(&iotlbentry->attrs)) { + return NULL; + } + + /* + * If not backed by host ram, there is no tag storage: access unchecked. + * This is probably a guest os bug though, so log it. + */ + if (unlikely(flags & TLB_MMIO)) { + qemu_log_mask(LOG_GUEST_ERROR, + "Page @ 0x%" PRIx64 " indicates Tagged Normal memory " + "but is not backed by host ram\n", ptr); + return NULL; + } + + /* + * The Normal memory access can extend to the next page. E.g. a single + * 8-byte access to the last byte of a page will check only the last + * tag on the first page. + * Any page access exception has priority over tag check exception. + */ + in_page = -(ptr | TARGET_PAGE_MASK); + if (unlikely(ptr_size > in_page)) { + void *ignore; + flags |= probe_access_flags(env, ptr + in_page, ptr_access, + ptr_mmu_idx, ra == 0, &ignore, ra); + assert(!(flags & TLB_INVALID_MASK)); + } + + /* Any debug exception has priority over a tag check exception. */ + if (unlikely(flags & TLB_WATCHPOINT)) { + int wp = ptr_access == MMU_DATA_LOAD ? BP_MEM_READ : BP_MEM_WRITE; + assert(ra != 0); + cpu_check_watchpoint(env_cpu(env), ptr, ptr_size, + iotlbentry->attrs, wp, ra); + } + + /* + * Find the physical address within the normal mem space. + * The memory region lookup must succeed because TLB_MMIO was + * not set in the cputlb lookup above. + */ + mr = memory_region_from_host(host, &ptr_ra); + tcg_debug_assert(mr != NULL); + tcg_debug_assert(memory_region_is_ram(mr)); + ptr_paddr = ptr_ra; + do { + ptr_paddr += mr->addr; + mr = mr->container; + } while (mr); + + /* Convert to the physical address in tag space. */ + tag_paddr = ptr_paddr >> (LOG2_TAG_GRANULE + 1); + + /* Look up the address in tag space. */ + tag_asi = iotlbentry->attrs.secure ? ARMASIdx_TagS : ARMASIdx_TagNS; + tag_as = cpu_get_address_space(env_cpu(env), tag_asi); + mr = address_space_translate(tag_as, tag_paddr, &xlat, NULL, + tag_access == MMU_DATA_STORE, + iotlbentry->attrs); + + /* + * Note that @mr will never be NULL. If there is nothing in the address + * space at @tag_paddr, the translation will return the unallocated memory + * region. For our purposes, the result must be ram. + */ + if (unlikely(!memory_region_is_ram(mr))) { + /* ??? Failure is a board configuration error. */ + qemu_log_mask(LOG_UNIMP, + "Tag Memory @ 0x%" HWADDR_PRIx " not found for " + "Normal Memory @ 0x%" HWADDR_PRIx "\n", + tag_paddr, ptr_paddr); + return NULL; + } + + /* + * Ensure the tag memory is dirty on write, for migration. + * Tag memory can never contain code or display memory (vga). + */ + if (tag_access == MMU_DATA_STORE) { + ram_addr_t tag_ra = memory_region_get_ram_addr(mr) + xlat; + cpu_physical_memory_set_dirty_flag(tag_ra, DIRTY_MEMORY_MIGRATION); + } + + return memory_region_get_ram_ptr(mr) + xlat; +#endif +} + +uint64_t HELPER(irg)(CPUARMState *env, uint64_t rn, uint64_t rm) +{ + uint16_t exclude = extract32(rm | env->cp15.gcr_el1, 0, 16); + int rrnd = extract32(env->cp15.gcr_el1, 16, 1); + int start = extract32(env->cp15.rgsr_el1, 0, 4); + int seed = extract32(env->cp15.rgsr_el1, 8, 16); + int offset, i, rtag; + + /* + * Our IMPDEF choice for GCR_EL1.RRND==1 is to continue to use the + * deterministic algorithm. Except that with RRND==1 the kernel is + * not required to have set RGSR_EL1.SEED != 0, which is required for + * the deterministic algorithm to function. So we force a non-zero + * SEED for that case. + */ + if (unlikely(seed == 0) && rrnd) { + do { + Error *err = NULL; + uint16_t two; + + if (qemu_guest_getrandom(&two, sizeof(two), &err) < 0) { + /* + * Failed, for unknown reasons in the crypto subsystem. + * Best we can do is log the reason and use a constant seed. + */ + qemu_log_mask(LOG_UNIMP, "IRG: Crypto failure: %s\n", + error_get_pretty(err)); + error_free(err); + two = 1; + } + seed = two; + } while (seed == 0); + } + + /* RandomTag */ + for (i = offset = 0; i < 4; ++i) { + /* NextRandomTagBit */ + int top = (extract32(seed, 5, 1) ^ extract32(seed, 3, 1) ^ + extract32(seed, 2, 1) ^ extract32(seed, 0, 1)); + seed = (top << 15) | (seed >> 1); + offset |= top << i; + } + rtag = choose_nonexcluded_tag(start, offset, exclude); + env->cp15.rgsr_el1 = rtag | (seed << 8); + + return address_with_allocation_tag(rn, rtag); +} + +uint64_t HELPER(addsubg)(CPUARMState *env, uint64_t ptr, + int32_t offset, uint32_t tag_offset) +{ + int start_tag = allocation_tag_from_addr(ptr); + uint16_t exclude = extract32(env->cp15.gcr_el1, 0, 16); + int rtag = choose_nonexcluded_tag(start_tag, tag_offset, exclude); + + return address_with_allocation_tag(ptr + offset, rtag); +} + +static int load_tag1(uint64_t ptr, uint8_t *mem) +{ + int ofs = extract32(ptr, LOG2_TAG_GRANULE, 1) * 4; + return extract32(*mem, ofs, 4); +} + +uint64_t HELPER(ldg)(CPUARMState *env, uint64_t ptr, uint64_t xt) +{ + int mmu_idx = cpu_mmu_index(env, false); + uint8_t *mem; + int rtag = 0; + + /* Trap if accessing an invalid page. */ + mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_LOAD, 1, + MMU_DATA_LOAD, 1, GETPC()); + + /* Load if page supports tags. */ + if (mem) { + rtag = load_tag1(ptr, mem); + } + + return address_with_allocation_tag(xt, rtag); +} + +static void check_tag_aligned(CPUARMState *env, uint64_t ptr, uintptr_t ra) +{ + if (unlikely(!QEMU_IS_ALIGNED(ptr, TAG_GRANULE))) { + arm_cpu_do_unaligned_access(env_cpu(env), ptr, MMU_DATA_STORE, + cpu_mmu_index(env, false), ra); + g_assert_not_reached(); + } +} + +/* For use in a non-parallel context, store to the given nibble. */ +static void store_tag1(uint64_t ptr, uint8_t *mem, int tag) +{ + int ofs = extract32(ptr, LOG2_TAG_GRANULE, 1) * 4; + *mem = deposit32(*mem, ofs, 4, tag); +} + +/* For use in a parallel context, atomically store to the given nibble. */ +static void store_tag1_parallel(uint64_t ptr, uint8_t *mem, int tag) +{ + int ofs = extract32(ptr, LOG2_TAG_GRANULE, 1) * 4; + uint8_t old = qatomic_read(mem); + + while (1) { + uint8_t new = deposit32(old, ofs, 4, tag); + uint8_t cmp = qatomic_cmpxchg(mem, old, new); + if (likely(cmp == old)) { + return; + } + old = cmp; + } +} + +typedef void stg_store1(uint64_t, uint8_t *, int); + +static inline void do_stg(CPUARMState *env, uint64_t ptr, uint64_t xt, + uintptr_t ra, stg_store1 store1) +{ + int mmu_idx = cpu_mmu_index(env, false); + uint8_t *mem; + + check_tag_aligned(env, ptr, ra); + + /* Trap if accessing an invalid page. */ + mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_STORE, TAG_GRANULE, + MMU_DATA_STORE, 1, ra); + + /* Store if page supports tags. */ + if (mem) { + store1(ptr, mem, allocation_tag_from_addr(xt)); + } +} + +void HELPER(stg)(CPUARMState *env, uint64_t ptr, uint64_t xt) +{ + do_stg(env, ptr, xt, GETPC(), store_tag1); +} + +void HELPER(stg_parallel)(CPUARMState *env, uint64_t ptr, uint64_t xt) +{ + do_stg(env, ptr, xt, GETPC(), store_tag1_parallel); +} + +void HELPER(stg_stub)(CPUARMState *env, uint64_t ptr) +{ + int mmu_idx = cpu_mmu_index(env, false); + uintptr_t ra = GETPC(); + + check_tag_aligned(env, ptr, ra); + probe_write(env, ptr, TAG_GRANULE, mmu_idx, ra); +} + +static inline void do_st2g(CPUARMState *env, uint64_t ptr, uint64_t xt, + uintptr_t ra, stg_store1 store1) +{ + int mmu_idx = cpu_mmu_index(env, false); + int tag = allocation_tag_from_addr(xt); + uint8_t *mem1, *mem2; + + check_tag_aligned(env, ptr, ra); + + /* + * Trap if accessing an invalid page(s). + * This takes priority over !allocation_tag_access_enabled. + */ + if (ptr & TAG_GRANULE) { + /* Two stores unaligned mod TAG_GRANULE*2 -- modify two bytes. */ + mem1 = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_STORE, + TAG_GRANULE, MMU_DATA_STORE, 1, ra); + mem2 = allocation_tag_mem(env, mmu_idx, ptr + TAG_GRANULE, + MMU_DATA_STORE, TAG_GRANULE, + MMU_DATA_STORE, 1, ra); + + /* Store if page(s) support tags. */ + if (mem1) { + store1(TAG_GRANULE, mem1, tag); + } + if (mem2) { + store1(0, mem2, tag); + } + } else { + /* Two stores aligned mod TAG_GRANULE*2 -- modify one byte. */ + mem1 = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_STORE, + 2 * TAG_GRANULE, MMU_DATA_STORE, 1, ra); + if (mem1) { + tag |= tag << 4; + qatomic_set(mem1, tag); + } + } +} + +void HELPER(st2g)(CPUARMState *env, uint64_t ptr, uint64_t xt) +{ + do_st2g(env, ptr, xt, GETPC(), store_tag1); +} + +void HELPER(st2g_parallel)(CPUARMState *env, uint64_t ptr, uint64_t xt) +{ + do_st2g(env, ptr, xt, GETPC(), store_tag1_parallel); +} + +void HELPER(st2g_stub)(CPUARMState *env, uint64_t ptr) +{ + int mmu_idx = cpu_mmu_index(env, false); + uintptr_t ra = GETPC(); + int in_page = -(ptr | TARGET_PAGE_MASK); + + check_tag_aligned(env, ptr, ra); + + if (likely(in_page >= 2 * TAG_GRANULE)) { + probe_write(env, ptr, 2 * TAG_GRANULE, mmu_idx, ra); + } else { + probe_write(env, ptr, TAG_GRANULE, mmu_idx, ra); + probe_write(env, ptr + TAG_GRANULE, TAG_GRANULE, mmu_idx, ra); + } +} + +#define LDGM_STGM_SIZE (4 << GMID_EL1_BS) + +uint64_t HELPER(ldgm)(CPUARMState *env, uint64_t ptr) +{ + int mmu_idx = cpu_mmu_index(env, false); + uintptr_t ra = GETPC(); + void *tag_mem; + + ptr = QEMU_ALIGN_DOWN(ptr, LDGM_STGM_SIZE); + + /* Trap if accessing an invalid page. */ + tag_mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_LOAD, + LDGM_STGM_SIZE, MMU_DATA_LOAD, + LDGM_STGM_SIZE / (2 * TAG_GRANULE), ra); + + /* The tag is squashed to zero if the page does not support tags. */ + if (!tag_mem) { + return 0; + } + + QEMU_BUILD_BUG_ON(GMID_EL1_BS != 6); + /* + * We are loading 64-bits worth of tags. The ordering of elements + * within the word corresponds to a 64-bit little-endian operation. + */ + return ldq_le_p(tag_mem); +} + +void HELPER(stgm)(CPUARMState *env, uint64_t ptr, uint64_t val) +{ + int mmu_idx = cpu_mmu_index(env, false); + uintptr_t ra = GETPC(); + void *tag_mem; + + ptr = QEMU_ALIGN_DOWN(ptr, LDGM_STGM_SIZE); + + /* Trap if accessing an invalid page. */ + tag_mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_STORE, + LDGM_STGM_SIZE, MMU_DATA_LOAD, + LDGM_STGM_SIZE / (2 * TAG_GRANULE), ra); + + /* + * Tag store only happens if the page support tags, + * and if the OS has enabled access to the tags. + */ + if (!tag_mem) { + return; + } + + QEMU_BUILD_BUG_ON(GMID_EL1_BS != 6); + /* + * We are storing 64-bits worth of tags. The ordering of elements + * within the word corresponds to a 64-bit little-endian operation. + */ + stq_le_p(tag_mem, val); +} + +void HELPER(stzgm_tags)(CPUARMState *env, uint64_t ptr, uint64_t val) +{ + uintptr_t ra = GETPC(); + int mmu_idx = cpu_mmu_index(env, false); + int log2_dcz_bytes, log2_tag_bytes; + intptr_t dcz_bytes, tag_bytes; + uint8_t *mem; + + /* + * In arm_cpu_realizefn, we assert that dcz > LOG2_TAG_GRANULE+1, + * i.e. 32 bytes, which is an unreasonably small dcz anyway, + * to make sure that we can access one complete tag byte here. + */ + log2_dcz_bytes = env_archcpu(env)->dcz_blocksize + 2; + log2_tag_bytes = log2_dcz_bytes - (LOG2_TAG_GRANULE + 1); + dcz_bytes = (intptr_t)1 << log2_dcz_bytes; + tag_bytes = (intptr_t)1 << log2_tag_bytes; + ptr &= -dcz_bytes; + + mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_STORE, dcz_bytes, + MMU_DATA_STORE, tag_bytes, ra); + if (mem) { + int tag_pair = (val & 0xf) * 0x11; + memset(mem, tag_pair, tag_bytes); + } +} + +/* Record a tag check failure. */ +static void mte_check_fail(CPUARMState *env, uint32_t desc, + uint64_t dirty_ptr, uintptr_t ra) +{ + int mmu_idx = FIELD_EX32(desc, MTEDESC, MIDX); + ARMMMUIdx arm_mmu_idx = core_to_aa64_mmu_idx(mmu_idx); + int el, reg_el, tcf, select, is_write, syn; + uint64_t sctlr; + + reg_el = regime_el(env, arm_mmu_idx); + sctlr = env->cp15.sctlr_el[reg_el]; + + el = arm_current_el(env); + if (el == 0) { + tcf = extract64(sctlr, 38, 2); + } else { + tcf = extract64(sctlr, 40, 2); + } + + switch (tcf) { + case 1: + /* + * Tag check fail causes a synchronous exception. + * + * In restore_state_to_opc, we set the exception syndrome + * for the load or store operation. Unwind first so we + * may overwrite that with the syndrome for the tag check. + */ + cpu_restore_state(env_cpu(env), ra, true); + env->exception.vaddress = dirty_ptr; + + is_write = FIELD_EX32(desc, MTEDESC, WRITE); + syn = syn_data_abort_no_iss(el != 0, 0, 0, 0, 0, is_write, 0x11); + raise_exception(env, EXCP_DATA_ABORT, syn, exception_target_el(env)); + /* noreturn, but fall through to the assert anyway */ + + case 0: + /* + * Tag check fail does not affect the PE. + * We eliminate this case by not setting MTE_ACTIVE + * in tb_flags, so that we never make this runtime call. + */ + g_assert_not_reached(); + + case 2: + /* Tag check fail causes asynchronous flag set. */ + if (regime_has_2_ranges(arm_mmu_idx)) { + select = extract64(dirty_ptr, 55, 1); + } else { + select = 0; + } + env->cp15.tfsr_el[el] |= 1 << select; + break; + + default: + /* Case 3: Reserved. */ + qemu_log_mask(LOG_GUEST_ERROR, + "Tag check failure with SCTLR_EL%d.TCF%s " + "set to reserved value %d\n", + reg_el, el ? "" : "0", tcf); + break; + } +} + +/* + * Perform an MTE checked access for a single logical or atomic access. + */ +static bool mte_probe1_int(CPUARMState *env, uint32_t desc, uint64_t ptr, + uintptr_t ra, int bit55) +{ + int mem_tag, mmu_idx, ptr_tag, size; + MMUAccessType type; + uint8_t *mem; + + ptr_tag = allocation_tag_from_addr(ptr); + + if (tcma_check(desc, bit55, ptr_tag)) { + return true; + } + + mmu_idx = FIELD_EX32(desc, MTEDESC, MIDX); + type = FIELD_EX32(desc, MTEDESC, WRITE) ? MMU_DATA_STORE : MMU_DATA_LOAD; + size = FIELD_EX32(desc, MTEDESC, ESIZE); + + mem = allocation_tag_mem(env, mmu_idx, ptr, type, size, + MMU_DATA_LOAD, 1, ra); + if (!mem) { + return true; + } + + mem_tag = load_tag1(ptr, mem); + return ptr_tag == mem_tag; +} + +/* + * No-fault version of mte_check1, to be used by SVE for MemSingleNF. + * Returns false if the access is Checked and the check failed. This + * is only intended to probe the tag -- the validity of the page must + * be checked beforehand. + */ +bool mte_probe1(CPUARMState *env, uint32_t desc, uint64_t ptr) +{ + int bit55 = extract64(ptr, 55, 1); + + /* If TBI is disabled, the access is unchecked. */ + if (unlikely(!tbi_check(desc, bit55))) { + return true; + } + + return mte_probe1_int(env, desc, ptr, 0, bit55); +} + +uint64_t mte_check1(CPUARMState *env, uint32_t desc, + uint64_t ptr, uintptr_t ra) +{ + int bit55 = extract64(ptr, 55, 1); + + /* If TBI is disabled, the access is unchecked, and ptr is not dirty. */ + if (unlikely(!tbi_check(desc, bit55))) { + return ptr; + } + + if (unlikely(!mte_probe1_int(env, desc, ptr, ra, bit55))) { + mte_check_fail(env, desc, ptr, ra); + } + + return useronly_clean_ptr(ptr); +} + +uint64_t HELPER(mte_check1)(CPUARMState *env, uint32_t desc, uint64_t ptr) +{ + return mte_check1(env, desc, ptr, GETPC()); +} + +/* + * Perform an MTE checked access for multiple logical accesses. + */ + +/** + * checkN: + * @tag: tag memory to test + * @odd: true to begin testing at tags at odd nibble + * @cmp: the tag to compare against + * @count: number of tags to test + * + * Return the number of successful tests. + * Thus a return value < @count indicates a failure. + * + * A note about sizes: count is expected to be small. + * + * The most common use will be LDP/STP of two integer registers, + * which means 16 bytes of memory touching at most 2 tags, but + * often the access is aligned and thus just 1 tag. + * + * Using AdvSIMD LD/ST (multiple), one can access 64 bytes of memory, + * touching at most 5 tags. SVE LDR/STR (vector) with the default + * vector length is also 64 bytes; the maximum architectural length + * is 256 bytes touching at most 9 tags. + * + * The loop below uses 7 logical operations and 1 memory operation + * per tag pair. An implementation that loads an aligned word and + * uses masking to ignore adjacent tags requires 18 logical operations + * and thus does not begin to pay off until 6 tags. + * Which, according to the survey above, is unlikely to be common. + */ +static int checkN(uint8_t *mem, int odd, int cmp, int count) +{ + int n = 0, diff; + + /* Replicate the test tag and compare. */ + cmp *= 0x11; + diff = *mem++ ^ cmp; + + if (odd) { + goto start_odd; + } + + while (1) { + /* Test even tag. */ + if (unlikely((diff) & 0x0f)) { + break; + } + if (++n == count) { + break; + } + + start_odd: + /* Test odd tag. */ + if (unlikely((diff) & 0xf0)) { + break; + } + if (++n == count) { + break; + } + + diff = *mem++ ^ cmp; + } + return n; +} + +uint64_t mte_checkN(CPUARMState *env, uint32_t desc, + uint64_t ptr, uintptr_t ra) +{ + int mmu_idx, ptr_tag, bit55; + uint64_t ptr_last, ptr_end, prev_page, next_page; + uint64_t tag_first, tag_end; + uint64_t tag_byte_first, tag_byte_end; + uint32_t esize, total, tag_count, tag_size, n, c; + uint8_t *mem1, *mem2; + MMUAccessType type; + + bit55 = extract64(ptr, 55, 1); + + /* If TBI is disabled, the access is unchecked, and ptr is not dirty. */ + if (unlikely(!tbi_check(desc, bit55))) { + return ptr; + } + + ptr_tag = allocation_tag_from_addr(ptr); + + if (tcma_check(desc, bit55, ptr_tag)) { + goto done; + } + + mmu_idx = FIELD_EX32(desc, MTEDESC, MIDX); + type = FIELD_EX32(desc, MTEDESC, WRITE) ? MMU_DATA_STORE : MMU_DATA_LOAD; + esize = FIELD_EX32(desc, MTEDESC, ESIZE); + total = FIELD_EX32(desc, MTEDESC, TSIZE); + + /* Find the addr of the end of the access, and of the last element. */ + ptr_end = ptr + total; + ptr_last = ptr_end - esize; + + /* Round the bounds to the tag granule, and compute the number of tags. */ + tag_first = QEMU_ALIGN_DOWN(ptr, TAG_GRANULE); + tag_end = QEMU_ALIGN_UP(ptr_last, TAG_GRANULE); + tag_count = (tag_end - tag_first) / TAG_GRANULE; + + /* Round the bounds to twice the tag granule, and compute the bytes. */ + tag_byte_first = QEMU_ALIGN_DOWN(ptr, 2 * TAG_GRANULE); + tag_byte_end = QEMU_ALIGN_UP(ptr_last, 2 * TAG_GRANULE); + + /* Locate the page boundaries. */ + prev_page = ptr & TARGET_PAGE_MASK; + next_page = prev_page + TARGET_PAGE_SIZE; + + if (likely(tag_end - prev_page <= TARGET_PAGE_SIZE)) { + /* Memory access stays on one page. */ + tag_size = (tag_byte_end - tag_byte_first) / (2 * TAG_GRANULE); + mem1 = allocation_tag_mem(env, mmu_idx, ptr, type, total, + MMU_DATA_LOAD, tag_size, ra); + if (!mem1) { + goto done; + } + /* Perform all of the comparisons. */ + n = checkN(mem1, ptr & TAG_GRANULE, ptr_tag, tag_count); + } else { + /* Memory access crosses to next page. */ + tag_size = (next_page - tag_byte_first) / (2 * TAG_GRANULE); + mem1 = allocation_tag_mem(env, mmu_idx, ptr, type, next_page - ptr, + MMU_DATA_LOAD, tag_size, ra); + + tag_size = (tag_byte_end - next_page) / (2 * TAG_GRANULE); + mem2 = allocation_tag_mem(env, mmu_idx, next_page, type, + ptr_end - next_page, + MMU_DATA_LOAD, tag_size, ra); + + /* + * Perform all of the comparisons. + * Note the possible but unlikely case of the operation spanning + * two pages that do not both have tagging enabled. + */ + n = c = (next_page - tag_first) / TAG_GRANULE; + if (mem1) { + n = checkN(mem1, ptr & TAG_GRANULE, ptr_tag, c); + } + if (n == c) { + if (!mem2) { + goto done; + } + n += checkN(mem2, 0, ptr_tag, tag_count - c); + } + } + + /* + * If we failed, we know which granule. Compute the element that + * is first in that granule, and signal failure on that element. + */ + if (unlikely(n < tag_count)) { + uint64_t fail_ofs; + + fail_ofs = tag_first + n * TAG_GRANULE - ptr; + fail_ofs = ROUND_UP(fail_ofs, esize); + mte_check_fail(env, desc, ptr + fail_ofs, ra); + } + + done: + return useronly_clean_ptr(ptr); +} + +uint64_t HELPER(mte_checkN)(CPUARMState *env, uint32_t desc, uint64_t ptr) +{ + return mte_checkN(env, desc, ptr, GETPC()); +} + +/* + * Perform an MTE checked access for DC_ZVA. + */ +uint64_t HELPER(mte_check_zva)(CPUARMState *env, uint32_t desc, uint64_t ptr) +{ + uintptr_t ra = GETPC(); + int log2_dcz_bytes, log2_tag_bytes; + int mmu_idx, bit55; + intptr_t dcz_bytes, tag_bytes, i; + void *mem; + uint64_t ptr_tag, mem_tag, align_ptr; + + bit55 = extract64(ptr, 55, 1); + + /* If TBI is disabled, the access is unchecked, and ptr is not dirty. */ + if (unlikely(!tbi_check(desc, bit55))) { + return ptr; + } + + ptr_tag = allocation_tag_from_addr(ptr); + + if (tcma_check(desc, bit55, ptr_tag)) { + goto done; + } + + /* + * In arm_cpu_realizefn, we asserted that dcz > LOG2_TAG_GRANULE+1, + * i.e. 32 bytes, which is an unreasonably small dcz anyway, to make + * sure that we can access one complete tag byte here. + */ + log2_dcz_bytes = env_archcpu(env)->dcz_blocksize + 2; + log2_tag_bytes = log2_dcz_bytes - (LOG2_TAG_GRANULE + 1); + dcz_bytes = (intptr_t)1 << log2_dcz_bytes; + tag_bytes = (intptr_t)1 << log2_tag_bytes; + align_ptr = ptr & -dcz_bytes; + + /* + * Trap if accessing an invalid page. DC_ZVA requires that we supply + * the original pointer for an invalid page. But watchpoints require + * that we probe the actual space. So do both. + */ + mmu_idx = FIELD_EX32(desc, MTEDESC, MIDX); + (void) probe_write(env, ptr, 1, mmu_idx, ra); + mem = allocation_tag_mem(env, mmu_idx, align_ptr, MMU_DATA_STORE, + dcz_bytes, MMU_DATA_LOAD, tag_bytes, ra); + if (!mem) { + goto done; + } + + /* + * Unlike the reasoning for checkN, DC_ZVA is always aligned, and thus + * it is quite easy to perform all of the comparisons at once without + * any extra masking. + * + * The most common zva block size is 64; some of the thunderx cpus use + * a block size of 128. For user-only, aarch64_max_initfn will set the + * block size to 512. Fill out the other cases for future-proofing. + * + * In order to be able to find the first miscompare later, we want the + * tag bytes to be in little-endian order. + */ + switch (log2_tag_bytes) { + case 0: /* zva_blocksize 32 */ + mem_tag = *(uint8_t *)mem; + ptr_tag *= 0x11u; + break; + case 1: /* zva_blocksize 64 */ + mem_tag = cpu_to_le16(*(uint16_t *)mem); + ptr_tag *= 0x1111u; + break; + case 2: /* zva_blocksize 128 */ + mem_tag = cpu_to_le32(*(uint32_t *)mem); + ptr_tag *= 0x11111111u; + break; + case 3: /* zva_blocksize 256 */ + mem_tag = cpu_to_le64(*(uint64_t *)mem); + ptr_tag *= 0x1111111111111111ull; + break; + + default: /* zva_blocksize 512, 1024, 2048 */ + ptr_tag *= 0x1111111111111111ull; + i = 0; + do { + mem_tag = cpu_to_le64(*(uint64_t *)(mem + i)); + if (unlikely(mem_tag != ptr_tag)) { + goto fail; + } + i += 8; + align_ptr += 16 * TAG_GRANULE; + } while (i < tag_bytes); + goto done; + } + + if (likely(mem_tag == ptr_tag)) { + goto done; + } + + fail: + /* Locate the first nibble that differs. */ + i = ctz64(mem_tag ^ ptr_tag) >> 4; + mte_check_fail(env, desc, align_ptr + i * TAG_GRANULE, ra); + + done: + return useronly_clean_ptr(ptr); +} diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode index 8beb1db768b1f77def3b7990fd3026d47577c174..ec83f10ab359dbaa0d8f1fccb535d9eb2b4beba2 100644 --- a/target/arm/neon-dp.decode +++ b/target/arm/neon-dp.decode @@ -5,7 +5,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -45,11 +45,16 @@ @3same_q0 .... ... . . . size:2 .... .... .... . 0 . . .... \ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0 -# For FP insns the high bit of 'size' is used as part of opcode decode -@3same_fp .... ... . . . . size:1 .... .... .... . q:1 . . .... \ - &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp -@3same_fp_q0 .... ... . . . . size:1 .... .... .... . 0 . . .... \ - &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0 +# For FP insns the high bit of 'size' is used as part of opcode decode, +# and the 'size' bit is 0 for 32-bit float and 1 for 16-bit float. +# This converts this encoding to the same MO_8/16/32/64 values that the +# integer neon insns use. +%3same_fp_size 20:1 !function=neon_3same_fp_size + +@3same_fp .... ... . . . . . .... .... .... . q:1 . . .... \ + &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%3same_fp_size +@3same_fp_q0 .... ... . . . . . .... .... .... . 0 . . .... \ + &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0 size=%3same_fp_size VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same @@ -165,14 +170,16 @@ VPADD_3s 1111 001 0 0 . .. .... .... 1011 . . . 1 .... @3same_q0 VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same -SHA1_3s 1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \ - vm=%vm_dp vn=%vn_dp vd=%vd_dp -SHA256H_3s 1111 001 1 0 . 00 .... .... 1100 . 1 . 0 .... \ - vm=%vm_dp vn=%vn_dp vd=%vd_dp -SHA256H2_3s 1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... \ - vm=%vm_dp vn=%vn_dp vd=%vd_dp -SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... \ - vm=%vm_dp vn=%vn_dp vd=%vd_dp +@3same_crypto .... .... .... .... .... .... .... .... \ + &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=0 q=1 + +SHA1C_3s 1111 001 0 0 . 00 .... .... 1100 . 1 . 0 .... @3same_crypto +SHA1P_3s 1111 001 0 0 . 01 .... .... 1100 . 1 . 0 .... @3same_crypto +SHA1M_3s 1111 001 0 0 . 10 .... .... 1100 . 1 . 0 .... @3same_crypto +SHA1SU0_3s 1111 001 0 0 . 11 .... .... 1100 . 1 . 0 .... @3same_crypto +SHA256H_3s 1111 001 1 0 . 00 .... .... 1100 . 1 . 0 .... @3same_crypto +SHA256H2_3s 1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... @3same_crypto +SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... @3same_crypto VFMA_fp_3s 1111 001 0 0 . 0 . .... .... 1100 ... 1 .... @3same_fp VFMS_fp_3s 1111 001 0 0 . 1 . .... .... 1100 ... 1 .... @3same_fp @@ -199,3 +206,440 @@ VRECPS_fp_3s 1111 001 0 0 . 0 . .... .... 1111 ... 1 .... @3same_fp VRSQRTS_fp_3s 1111 001 0 0 . 1 . .... .... 1111 ... 1 .... @3same_fp VMAXNM_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 1 .... @3same_fp VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp + +###################################################################### +# 2-reg-and-shift grouping: +# 1111 001 U 1 D immH:3 immL:3 Vd:4 opc:4 L Q M 1 Vm:4 +###################################################################### +&2reg_shift vm vd q shift size + +# Right shifts are encoded as N - shift, where N is the element size in bits. +%neon_rshift_i6 16:6 !function=rsub_64 +%neon_rshift_i5 16:5 !function=rsub_32 +%neon_rshift_i4 16:4 !function=rsub_16 +%neon_rshift_i3 16:3 !function=rsub_8 + +@2reg_shr_d .... ... . . . ...... .... .... 1 q:1 . . .... \ + &2reg_shift vm=%vm_dp vd=%vd_dp size=3 shift=%neon_rshift_i6 +@2reg_shr_s .... ... . . . 1 ..... .... .... 0 q:1 . . .... \ + &2reg_shift vm=%vm_dp vd=%vd_dp size=2 shift=%neon_rshift_i5 +@2reg_shr_h .... ... . . . 01 .... .... .... 0 q:1 . . .... \ + &2reg_shift vm=%vm_dp vd=%vd_dp size=1 shift=%neon_rshift_i4 +@2reg_shr_b .... ... . . . 001 ... .... .... 0 q:1 . . .... \ + &2reg_shift vm=%vm_dp vd=%vd_dp size=0 shift=%neon_rshift_i3 + +@2reg_shl_d .... ... . . . shift:6 .... .... 1 q:1 . . .... \ + &2reg_shift vm=%vm_dp vd=%vd_dp size=3 +@2reg_shl_s .... ... . . . 1 shift:5 .... .... 0 q:1 . . .... \ + &2reg_shift vm=%vm_dp vd=%vd_dp size=2 +@2reg_shl_h .... ... . . . 01 shift:4 .... .... 0 q:1 . . .... \ + &2reg_shift vm=%vm_dp vd=%vd_dp size=1 +@2reg_shl_b .... ... . . . 001 shift:3 .... .... 0 q:1 . . .... \ + &2reg_shift vm=%vm_dp vd=%vd_dp size=0 + +# Narrowing right shifts: here the Q bit is part of the opcode decode +@2reg_shrn_d .... ... . . . 1 ..... .... .... 0 . . . .... \ + &2reg_shift vm=%vm_dp vd=%vd_dp size=3 q=0 \ + shift=%neon_rshift_i5 +@2reg_shrn_s .... ... . . . 01 .... .... .... 0 . . . .... \ + &2reg_shift vm=%vm_dp vd=%vd_dp size=2 q=0 \ + shift=%neon_rshift_i4 +@2reg_shrn_h .... ... . . . 001 ... .... .... 0 . . . .... \ + &2reg_shift vm=%vm_dp vd=%vd_dp size=1 q=0 \ + shift=%neon_rshift_i3 + +# Long left shifts: again Q is part of opcode decode +@2reg_shll_s .... ... . . . 1 shift:5 .... .... 0 . . . .... \ + &2reg_shift vm=%vm_dp vd=%vd_dp size=2 q=0 +@2reg_shll_h .... ... . . . 01 shift:4 .... .... 0 . . . .... \ + &2reg_shift vm=%vm_dp vd=%vd_dp size=1 q=0 +@2reg_shll_b .... ... . . . 001 shift:3 .... .... 0 . . . .... \ + &2reg_shift vm=%vm_dp vd=%vd_dp size=0 q=0 + +@2reg_vcvt .... ... . . . 1 ..... .... .... . q:1 . . .... \ + &2reg_shift vm=%vm_dp vd=%vd_dp size=2 shift=%neon_rshift_i5 +@2reg_vcvt_f16 .... ... . . . 11 .... .... .... . q:1 . . .... \ + &2reg_shift vm=%vm_dp vd=%vd_dp size=1 shift=%neon_rshift_i4 + +VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_d +VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_s +VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_h +VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_b + +VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_d +VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_s +VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_h +VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_b + +VSRA_S_2sh 1111 001 0 1 . ...... .... 0001 . . . 1 .... @2reg_shr_d +VSRA_S_2sh 1111 001 0 1 . ...... .... 0001 . . . 1 .... @2reg_shr_s +VSRA_S_2sh 1111 001 0 1 . ...... .... 0001 . . . 1 .... @2reg_shr_h +VSRA_S_2sh 1111 001 0 1 . ...... .... 0001 . . . 1 .... @2reg_shr_b + +VSRA_U_2sh 1111 001 1 1 . ...... .... 0001 . . . 1 .... @2reg_shr_d +VSRA_U_2sh 1111 001 1 1 . ...... .... 0001 . . . 1 .... @2reg_shr_s +VSRA_U_2sh 1111 001 1 1 . ...... .... 0001 . . . 1 .... @2reg_shr_h +VSRA_U_2sh 1111 001 1 1 . ...... .... 0001 . . . 1 .... @2reg_shr_b + +VRSHR_S_2sh 1111 001 0 1 . ...... .... 0010 . . . 1 .... @2reg_shr_d +VRSHR_S_2sh 1111 001 0 1 . ...... .... 0010 . . . 1 .... @2reg_shr_s +VRSHR_S_2sh 1111 001 0 1 . ...... .... 0010 . . . 1 .... @2reg_shr_h +VRSHR_S_2sh 1111 001 0 1 . ...... .... 0010 . . . 1 .... @2reg_shr_b + +VRSHR_U_2sh 1111 001 1 1 . ...... .... 0010 . . . 1 .... @2reg_shr_d +VRSHR_U_2sh 1111 001 1 1 . ...... .... 0010 . . . 1 .... @2reg_shr_s +VRSHR_U_2sh 1111 001 1 1 . ...... .... 0010 . . . 1 .... @2reg_shr_h +VRSHR_U_2sh 1111 001 1 1 . ...... .... 0010 . . . 1 .... @2reg_shr_b + +VRSRA_S_2sh 1111 001 0 1 . ...... .... 0011 . . . 1 .... @2reg_shr_d +VRSRA_S_2sh 1111 001 0 1 . ...... .... 0011 . . . 1 .... @2reg_shr_s +VRSRA_S_2sh 1111 001 0 1 . ...... .... 0011 . . . 1 .... @2reg_shr_h +VRSRA_S_2sh 1111 001 0 1 . ...... .... 0011 . . . 1 .... @2reg_shr_b + +VRSRA_U_2sh 1111 001 1 1 . ...... .... 0011 . . . 1 .... @2reg_shr_d +VRSRA_U_2sh 1111 001 1 1 . ...... .... 0011 . . . 1 .... @2reg_shr_s +VRSRA_U_2sh 1111 001 1 1 . ...... .... 0011 . . . 1 .... @2reg_shr_h +VRSRA_U_2sh 1111 001 1 1 . ...... .... 0011 . . . 1 .... @2reg_shr_b + +VSRI_2sh 1111 001 1 1 . ...... .... 0100 . . . 1 .... @2reg_shr_d +VSRI_2sh 1111 001 1 1 . ...... .... 0100 . . . 1 .... @2reg_shr_s +VSRI_2sh 1111 001 1 1 . ...... .... 0100 . . . 1 .... @2reg_shr_h +VSRI_2sh 1111 001 1 1 . ...... .... 0100 . . . 1 .... @2reg_shr_b + +VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_d +VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_s +VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_h +VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_b + +VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_d +VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_s +VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_h +VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_b + +VQSHLU_64_2sh 1111 001 1 1 . ...... .... 0110 . . . 1 .... @2reg_shl_d +VQSHLU_2sh 1111 001 1 1 . ...... .... 0110 . . . 1 .... @2reg_shl_s +VQSHLU_2sh 1111 001 1 1 . ...... .... 0110 . . . 1 .... @2reg_shl_h +VQSHLU_2sh 1111 001 1 1 . ...... .... 0110 . . . 1 .... @2reg_shl_b + +VQSHL_S_64_2sh 1111 001 0 1 . ...... .... 0111 . . . 1 .... @2reg_shl_d +VQSHL_S_2sh 1111 001 0 1 . ...... .... 0111 . . . 1 .... @2reg_shl_s +VQSHL_S_2sh 1111 001 0 1 . ...... .... 0111 . . . 1 .... @2reg_shl_h +VQSHL_S_2sh 1111 001 0 1 . ...... .... 0111 . . . 1 .... @2reg_shl_b + +VQSHL_U_64_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_d +VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_s +VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_h +VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_b + +VSHRN_64_2sh 1111 001 0 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_d +VSHRN_32_2sh 1111 001 0 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_s +VSHRN_16_2sh 1111 001 0 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_h + +VRSHRN_64_2sh 1111 001 0 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_d +VRSHRN_32_2sh 1111 001 0 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_s +VRSHRN_16_2sh 1111 001 0 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_h + +VQSHRUN_64_2sh 1111 001 1 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_d +VQSHRUN_32_2sh 1111 001 1 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_s +VQSHRUN_16_2sh 1111 001 1 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_h + +VQRSHRUN_64_2sh 1111 001 1 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_d +VQRSHRUN_32_2sh 1111 001 1 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_s +VQRSHRUN_16_2sh 1111 001 1 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_h + +# VQSHRN with signed input +VQSHRN_S64_2sh 1111 001 0 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_d +VQSHRN_S32_2sh 1111 001 0 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_s +VQSHRN_S16_2sh 1111 001 0 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_h + +# VQRSHRN with signed input +VQRSHRN_S64_2sh 1111 001 0 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_d +VQRSHRN_S32_2sh 1111 001 0 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_s +VQRSHRN_S16_2sh 1111 001 0 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_h + +# VQSHRN with unsigned input +VQSHRN_U64_2sh 1111 001 1 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_d +VQSHRN_U32_2sh 1111 001 1 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_s +VQSHRN_U16_2sh 1111 001 1 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_h + +# VQRSHRN with unsigned input +VQRSHRN_U64_2sh 1111 001 1 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_d +VQRSHRN_U32_2sh 1111 001 1 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_s +VQRSHRN_U16_2sh 1111 001 1 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_h + +VSHLL_S_2sh 1111 001 0 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_s +VSHLL_S_2sh 1111 001 0 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_h +VSHLL_S_2sh 1111 001 0 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_b + +VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_s +VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_h +VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_b + +# VCVT fixed<->float conversions +VCVT_SH_2sh 1111 001 0 1 . ...... .... 1100 0 . . 1 .... @2reg_vcvt_f16 +VCVT_UH_2sh 1111 001 1 1 . ...... .... 1100 0 . . 1 .... @2reg_vcvt_f16 +VCVT_HS_2sh 1111 001 0 1 . ...... .... 1101 0 . . 1 .... @2reg_vcvt_f16 +VCVT_HU_2sh 1111 001 1 1 . ...... .... 1101 0 . . 1 .... @2reg_vcvt_f16 + +VCVT_SF_2sh 1111 001 0 1 . ...... .... 1110 0 . . 1 .... @2reg_vcvt +VCVT_UF_2sh 1111 001 1 1 . ...... .... 1110 0 . . 1 .... @2reg_vcvt +VCVT_FS_2sh 1111 001 0 1 . ...... .... 1111 0 . . 1 .... @2reg_vcvt +VCVT_FU_2sh 1111 001 1 1 . ...... .... 1111 0 . . 1 .... @2reg_vcvt + +###################################################################### +# 1-reg-and-modified-immediate grouping: +# 1111 001 i 1 D 000 imm:3 Vd:4 cmode:4 0 Q op 1 Vm:4 +###################################################################### + +&1reg_imm vd q imm cmode op + +%asimd_imm_value 24:1 16:3 0:4 + +@1reg_imm .... ... . . . ... ... .... .... . q:1 . . .... \ + &1reg_imm imm=%asimd_imm_value vd=%vd_dp + +# The cmode/op bits here decode VORR/VBIC/VMOV/VMNV, but +# not in a way we can conveniently represent in decodetree without +# a lot of repetition: +# VORR: op=0, (cmode & 1) && cmode < 12 +# VBIC: op=1, (cmode & 1) && cmode < 12 +# VMOV: everything else +# So we have a single decode line and check the cmode/op in the +# trans function. +Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm + +###################################################################### +# Within the "two registers, or three registers of different lengths" +# grouping ([23,4]=0b10), bits [21:20] are either part of the opcode +# decode: 0b11 for VEXT, two-reg-misc, VTBL, and duplicate-scalar; +# or they are a size field for the three-reg-different-lengths and +# two-reg-and-scalar insn groups (where size cannot be 0b11). This +# is slightly awkward for decodetree: we handle it with this +# non-exclusive group which contains within it two exclusive groups: +# one for the size=0b11 patterns, and one for the size-not-0b11 +# patterns. This allows us to check that none of the insns within +# each subgroup accidentally overlap each other. Note that all the +# trans functions for the size-not-0b11 patterns must check and +# return false for size==3. +###################################################################### +{ + [ + ################################################################## + # Miscellaneous size=0b11 insns + ################################################################## + VEXT 1111 001 0 1 . 11 .... .... imm:4 . q:1 . 0 .... \ + vm=%vm_dp vn=%vn_dp vd=%vd_dp + + VTBL 1111 001 1 1 . 11 .... .... 10 len:2 . op:1 . 0 .... \ + vm=%vm_dp vn=%vn_dp vd=%vd_dp + + VDUP_scalar 1111 001 1 1 . 11 index:3 1 .... 11 000 q:1 . 0 .... \ + vm=%vm_dp vd=%vd_dp size=0 + VDUP_scalar 1111 001 1 1 . 11 index:2 10 .... 11 000 q:1 . 0 .... \ + vm=%vm_dp vd=%vd_dp size=1 + VDUP_scalar 1111 001 1 1 . 11 index:1 100 .... 11 000 q:1 . 0 .... \ + vm=%vm_dp vd=%vd_dp size=2 + + ################################################################## + # 2-reg-misc grouping: + # 1111 001 11 D 11 size:2 opc1:2 Vd:4 0 opc2:4 q:1 M 0 Vm:4 + ################################################################## + + &2misc vd vm q size + + @2misc .... ... .. . .. size:2 .. .... . .... q:1 . . .... \ + &2misc vm=%vm_dp vd=%vd_dp + @2misc_q0 .... ... .. . .. size:2 .. .... . .... . . . .... \ + &2misc vm=%vm_dp vd=%vd_dp q=0 + @2misc_q1 .... ... .. . .. size:2 .. .... . .... . . . .... \ + &2misc vm=%vm_dp vd=%vd_dp q=1 + + VREV64 1111 001 11 . 11 .. 00 .... 0 0000 . . 0 .... @2misc + VREV32 1111 001 11 . 11 .. 00 .... 0 0001 . . 0 .... @2misc + VREV16 1111 001 11 . 11 .. 00 .... 0 0010 . . 0 .... @2misc + + VPADDL_S 1111 001 11 . 11 .. 00 .... 0 0100 . . 0 .... @2misc + VPADDL_U 1111 001 11 . 11 .. 00 .... 0 0101 . . 0 .... @2misc + + AESE 1111 001 11 . 11 .. 00 .... 0 0110 0 . 0 .... @2misc_q1 + AESD 1111 001 11 . 11 .. 00 .... 0 0110 1 . 0 .... @2misc_q1 + AESMC 1111 001 11 . 11 .. 00 .... 0 0111 0 . 0 .... @2misc_q1 + AESIMC 1111 001 11 . 11 .. 00 .... 0 0111 1 . 0 .... @2misc_q1 + + VCLS 1111 001 11 . 11 .. 00 .... 0 1000 . . 0 .... @2misc + VCLZ 1111 001 11 . 11 .. 00 .... 0 1001 . . 0 .... @2misc + VCNT 1111 001 11 . 11 .. 00 .... 0 1010 . . 0 .... @2misc + + VMVN 1111 001 11 . 11 .. 00 .... 0 1011 . . 0 .... @2misc + + VPADAL_S 1111 001 11 . 11 .. 00 .... 0 1100 . . 0 .... @2misc + VPADAL_U 1111 001 11 . 11 .. 00 .... 0 1101 . . 0 .... @2misc + + VQABS 1111 001 11 . 11 .. 00 .... 0 1110 . . 0 .... @2misc + VQNEG 1111 001 11 . 11 .. 00 .... 0 1111 . . 0 .... @2misc + + VCGT0 1111 001 11 . 11 .. 01 .... 0 0000 . . 0 .... @2misc + VCGE0 1111 001 11 . 11 .. 01 .... 0 0001 . . 0 .... @2misc + VCEQ0 1111 001 11 . 11 .. 01 .... 0 0010 . . 0 .... @2misc + VCLE0 1111 001 11 . 11 .. 01 .... 0 0011 . . 0 .... @2misc + VCLT0 1111 001 11 . 11 .. 01 .... 0 0100 . . 0 .... @2misc + + SHA1H 1111 001 11 . 11 .. 01 .... 0 0101 1 . 0 .... @2misc_q1 + + VABS 1111 001 11 . 11 .. 01 .... 0 0110 . . 0 .... @2misc + VNEG 1111 001 11 . 11 .. 01 .... 0 0111 . . 0 .... @2misc + + VCGT0_F 1111 001 11 . 11 .. 01 .... 0 1000 . . 0 .... @2misc + VCGE0_F 1111 001 11 . 11 .. 01 .... 0 1001 . . 0 .... @2misc + VCEQ0_F 1111 001 11 . 11 .. 01 .... 0 1010 . . 0 .... @2misc + VCLE0_F 1111 001 11 . 11 .. 01 .... 0 1011 . . 0 .... @2misc + VCLT0_F 1111 001 11 . 11 .. 01 .... 0 1100 . . 0 .... @2misc + + VABS_F 1111 001 11 . 11 .. 01 .... 0 1110 . . 0 .... @2misc + VNEG_F 1111 001 11 . 11 .. 01 .... 0 1111 . . 0 .... @2misc + + VSWP 1111 001 11 . 11 .. 10 .... 0 0000 . . 0 .... @2misc + VTRN 1111 001 11 . 11 .. 10 .... 0 0001 . . 0 .... @2misc + VUZP 1111 001 11 . 11 .. 10 .... 0 0010 . . 0 .... @2misc + VZIP 1111 001 11 . 11 .. 10 .... 0 0011 . . 0 .... @2misc + + VMOVN 1111 001 11 . 11 .. 10 .... 0 0100 0 . 0 .... @2misc_q0 + # VQMOVUN: unsigned result (source is always signed) + VQMOVUN 1111 001 11 . 11 .. 10 .... 0 0100 1 . 0 .... @2misc_q0 + # VQMOVN: signed result, source may be signed (_S) or unsigned (_U) + VQMOVN_S 1111 001 11 . 11 .. 10 .... 0 0101 0 . 0 .... @2misc_q0 + VQMOVN_U 1111 001 11 . 11 .. 10 .... 0 0101 1 . 0 .... @2misc_q0 + + VSHLL 1111 001 11 . 11 .. 10 .... 0 0110 0 . 0 .... @2misc_q0 + + SHA1SU1 1111 001 11 . 11 .. 10 .... 0 0111 0 . 0 .... @2misc_q1 + SHA256SU0 1111 001 11 . 11 .. 10 .... 0 0111 1 . 0 .... @2misc_q1 + + VRINTN 1111 001 11 . 11 .. 10 .... 0 1000 . . 0 .... @2misc + VRINTX 1111 001 11 . 11 .. 10 .... 0 1001 . . 0 .... @2misc + VRINTA 1111 001 11 . 11 .. 10 .... 0 1010 . . 0 .... @2misc + VRINTZ 1111 001 11 . 11 .. 10 .... 0 1011 . . 0 .... @2misc + + VCVT_F16_F32 1111 001 11 . 11 .. 10 .... 0 1100 0 . 0 .... @2misc_q0 + + VRINTM 1111 001 11 . 11 .. 10 .... 0 1101 . . 0 .... @2misc + + VCVT_F32_F16 1111 001 11 . 11 .. 10 .... 0 1110 0 . 0 .... @2misc_q0 + + VRINTP 1111 001 11 . 11 .. 10 .... 0 1111 . . 0 .... @2misc + + VCVTAS 1111 001 11 . 11 .. 11 .... 0 0000 . . 0 .... @2misc + VCVTAU 1111 001 11 . 11 .. 11 .... 0 0001 . . 0 .... @2misc + VCVTNS 1111 001 11 . 11 .. 11 .... 0 0010 . . 0 .... @2misc + VCVTNU 1111 001 11 . 11 .. 11 .... 0 0011 . . 0 .... @2misc + VCVTPS 1111 001 11 . 11 .. 11 .... 0 0100 . . 0 .... @2misc + VCVTPU 1111 001 11 . 11 .. 11 .... 0 0101 . . 0 .... @2misc + VCVTMS 1111 001 11 . 11 .. 11 .... 0 0110 . . 0 .... @2misc + VCVTMU 1111 001 11 . 11 .. 11 .... 0 0111 . . 0 .... @2misc + + VRECPE 1111 001 11 . 11 .. 11 .... 0 1000 . . 0 .... @2misc + VRSQRTE 1111 001 11 . 11 .. 11 .... 0 1001 . . 0 .... @2misc + VRECPE_F 1111 001 11 . 11 .. 11 .... 0 1010 . . 0 .... @2misc + VRSQRTE_F 1111 001 11 . 11 .. 11 .... 0 1011 . . 0 .... @2misc + VCVT_FS 1111 001 11 . 11 .. 11 .... 0 1100 . . 0 .... @2misc + VCVT_FU 1111 001 11 . 11 .. 11 .... 0 1101 . . 0 .... @2misc + VCVT_SF 1111 001 11 . 11 .. 11 .... 0 1110 . . 0 .... @2misc + VCVT_UF 1111 001 11 . 11 .. 11 .... 0 1111 . . 0 .... @2misc + ] + + # Subgroup for size != 0b11 + [ + ################################################################## + # 3-reg-different-length grouping: + # 1111 001 U 1 D sz!=11 Vn:4 Vd:4 opc:4 N 0 M 0 Vm:4 + ################################################################## + + &3diff vm vn vd size + + @3diff .... ... . . . size:2 .... .... .... . . . . .... \ + &3diff vm=%vm_dp vn=%vn_dp vd=%vd_dp + + VADDL_S_3d 1111 001 0 1 . .. .... .... 0000 . 0 . 0 .... @3diff + VADDL_U_3d 1111 001 1 1 . .. .... .... 0000 . 0 . 0 .... @3diff + + VADDW_S_3d 1111 001 0 1 . .. .... .... 0001 . 0 . 0 .... @3diff + VADDW_U_3d 1111 001 1 1 . .. .... .... 0001 . 0 . 0 .... @3diff + + VSUBL_S_3d 1111 001 0 1 . .. .... .... 0010 . 0 . 0 .... @3diff + VSUBL_U_3d 1111 001 1 1 . .. .... .... 0010 . 0 . 0 .... @3diff + + VSUBW_S_3d 1111 001 0 1 . .. .... .... 0011 . 0 . 0 .... @3diff + VSUBW_U_3d 1111 001 1 1 . .. .... .... 0011 . 0 . 0 .... @3diff + + VADDHN_3d 1111 001 0 1 . .. .... .... 0100 . 0 . 0 .... @3diff + VRADDHN_3d 1111 001 1 1 . .. .... .... 0100 . 0 . 0 .... @3diff + + VABAL_S_3d 1111 001 0 1 . .. .... .... 0101 . 0 . 0 .... @3diff + VABAL_U_3d 1111 001 1 1 . .. .... .... 0101 . 0 . 0 .... @3diff + + VSUBHN_3d 1111 001 0 1 . .. .... .... 0110 . 0 . 0 .... @3diff + VRSUBHN_3d 1111 001 1 1 . .. .... .... 0110 . 0 . 0 .... @3diff + + VABDL_S_3d 1111 001 0 1 . .. .... .... 0111 . 0 . 0 .... @3diff + VABDL_U_3d 1111 001 1 1 . .. .... .... 0111 . 0 . 0 .... @3diff + + VMLAL_S_3d 1111 001 0 1 . .. .... .... 1000 . 0 . 0 .... @3diff + VMLAL_U_3d 1111 001 1 1 . .. .... .... 1000 . 0 . 0 .... @3diff + + VQDMLAL_3d 1111 001 0 1 . .. .... .... 1001 . 0 . 0 .... @3diff + + VMLSL_S_3d 1111 001 0 1 . .. .... .... 1010 . 0 . 0 .... @3diff + VMLSL_U_3d 1111 001 1 1 . .. .... .... 1010 . 0 . 0 .... @3diff + + VQDMLSL_3d 1111 001 0 1 . .. .... .... 1011 . 0 . 0 .... @3diff + + VMULL_S_3d 1111 001 0 1 . .. .... .... 1100 . 0 . 0 .... @3diff + VMULL_U_3d 1111 001 1 1 . .. .... .... 1100 . 0 . 0 .... @3diff + + VQDMULL_3d 1111 001 0 1 . .. .... .... 1101 . 0 . 0 .... @3diff + + VMULL_P_3d 1111 001 0 1 . .. .... .... 1110 . 0 . 0 .... @3diff + + ################################################################## + # 2-regs-plus-scalar grouping: + # 1111 001 Q 1 D sz!=11 Vn:4 Vd:4 opc:4 N 1 M 0 Vm:4 + ################################################################## + &2scalar vm vn vd size q + + @2scalar .... ... q:1 . . size:2 .... .... .... . . . . .... \ + &2scalar vm=%vm_dp vn=%vn_dp vd=%vd_dp + # For the 'long' ops the Q bit is part of insn decode + @2scalar_q0 .... ... . . . size:2 .... .... .... . . . . .... \ + &2scalar vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0 + + VMLA_2sc 1111 001 . 1 . .. .... .... 0000 . 1 . 0 .... @2scalar + VMLA_F_2sc 1111 001 . 1 . .. .... .... 0001 . 1 . 0 .... @2scalar + + VMLAL_S_2sc 1111 001 0 1 . .. .... .... 0010 . 1 . 0 .... @2scalar_q0 + VMLAL_U_2sc 1111 001 1 1 . .. .... .... 0010 . 1 . 0 .... @2scalar_q0 + + VQDMLAL_2sc 1111 001 0 1 . .. .... .... 0011 . 1 . 0 .... @2scalar_q0 + + VMLS_2sc 1111 001 . 1 . .. .... .... 0100 . 1 . 0 .... @2scalar + VMLS_F_2sc 1111 001 . 1 . .. .... .... 0101 . 1 . 0 .... @2scalar + + VMLSL_S_2sc 1111 001 0 1 . .. .... .... 0110 . 1 . 0 .... @2scalar_q0 + VMLSL_U_2sc 1111 001 1 1 . .. .... .... 0110 . 1 . 0 .... @2scalar_q0 + + VQDMLSL_2sc 1111 001 0 1 . .. .... .... 0111 . 1 . 0 .... @2scalar_q0 + + VMUL_2sc 1111 001 . 1 . .. .... .... 1000 . 1 . 0 .... @2scalar + VMUL_F_2sc 1111 001 . 1 . .. .... .... 1001 . 1 . 0 .... @2scalar + + VMULL_S_2sc 1111 001 0 1 . .. .... .... 1010 . 1 . 0 .... @2scalar_q0 + VMULL_U_2sc 1111 001 1 1 . .. .... .... 1010 . 1 . 0 .... @2scalar_q0 + + VQDMULL_2sc 1111 001 0 1 . .. .... .... 1011 . 1 . 0 .... @2scalar_q0 + + VQDMULH_2sc 1111 001 . 1 . .. .... .... 1100 . 1 . 0 .... @2scalar + VQRDMULH_2sc 1111 001 . 1 . .. .... .... 1101 . 1 . 0 .... @2scalar + + VQRDMLAH_2sc 1111 001 . 1 . .. .... .... 1110 . 1 . 0 .... @2scalar + VQRDMLSH_2sc 1111 001 . 1 . .. .... .... 1111 . 1 . 0 .... @2scalar + ] +} diff --git a/target/arm/neon-ls.decode b/target/arm/neon-ls.decode index c7b03a72e8d32f5262f46cfb8da2b8dd87179103..c17f5019e312dc2567fbe5c30c38617879119dc8 100644 --- a/target/arm/neon-ls.decode +++ b/target/arm/neon-ls.decode @@ -5,7 +5,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode index f297ba8cdfc361b5c8ab23e6417e04fdae7884ac..ca0c699072e8efdc9da5df0c09e66881826ac349 100644 --- a/target/arm/neon-shared.decode +++ b/target/arm/neon-shared.decode @@ -5,7 +5,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -34,11 +34,17 @@ %vd_dp 22:1 12:4 %vd_sp 12:4 22:1 -VCMLA 1111 110 rot:2 . 1 size:1 .... .... 1000 . q:1 . 0 .... \ - vm=%vm_dp vn=%vn_dp vd=%vd_dp +# For VCMLA/VCADD insns, convert the single-bit size field +# which is 0 for fp16 and 1 for fp32 into a MO_* constant. +# (Note that this is the reverse of the sense of the 1-bit size +# field in the 3same_fp Neon insns.) +%vcadd_size 20:1 !function=plus1 -VCADD 1111 110 rot:1 1 . 0 size:1 .... .... 1000 . q:1 . 0 .... \ - vm=%vm_dp vn=%vn_dp vd=%vd_dp +VCMLA 1111 110 rot:2 . 1 . .... .... 1000 . q:1 . 0 .... \ + vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%vcadd_size + +VCADD 1111 110 rot:1 1 . 0 . .... .... 1000 . q:1 . 0 .... \ + vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%vcadd_size # VUDOT and VSDOT VDOT 1111 110 00 . 10 .... .... 1101 . q:1 . u:1 .... \ @@ -51,9 +57,9 @@ VFML 1111 110 0 s:1 . 10 .... .... 1000 . 1 . 1 .... \ vm=%vm_dp vn=%vn_dp vd=%vd_dp q=1 VCMLA_scalar 1111 1110 0 . rot:2 .... .... 1000 . q:1 index:1 0 vm:4 \ - vn=%vn_dp vd=%vd_dp size=0 + vn=%vn_dp vd=%vd_dp size=1 VCMLA_scalar 1111 1110 1 . rot:2 .... .... 1000 . q:1 . 0 .... \ - vm=%vm_dp vn=%vn_dp vd=%vd_dp size=1 index=0 + vm=%vm_dp vn=%vn_dp vd=%vd_dp size=2 index=0 VDOT_scalar 1111 1110 0 . 10 .... .... 1101 . q:1 index:1 u:1 rm:4 \ vm=%vm_dp vn=%vn_dp vd=%vd_dp diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index eb0de080f11192e0c2ddc92c1c681993ad444de8..ff91fe612138e23ca32da51115cdcdece501d963 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -68,21 +68,24 @@ void raise_exception_ra(CPUARMState *env, uint32_t excp, uint32_t syndrome, cpu_loop_exit_restore(cs, ra); } -uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def, void *vn, - uint32_t maxindex) +uint64_t HELPER(neon_tbl)(CPUARMState *env, uint32_t desc, + uint64_t ireg, uint64_t def) { - uint32_t val, shift; - uint64_t *table = vn; + uint64_t tmp, val = 0; + uint32_t maxindex = ((desc & 3) + 1) * 8; + uint32_t base_reg = desc >> 2; + uint32_t shift, index, reg; - val = 0; - for (shift = 0; shift < 32; shift += 8) { - uint32_t index = (ireg >> shift) & 0xff; + for (shift = 0; shift < 64; shift += 8) { + index = (ireg >> shift) & 0xff; if (index < maxindex) { - uint32_t tmp = (table[index >> 3] >> ((index & 7) << 3)) & 0xff; - val |= tmp << shift; + reg = base_reg + (index >> 3); + tmp = *aa32_vfp_dreg(env, reg); + tmp = ((tmp >> ((index & 7) << 3)) & 0xff) << shift; } else { - val |= def & (0xff << shift); + tmp = def & (0xffull << shift); } + val |= tmp; } return val; } @@ -935,3 +938,19 @@ uint32_t HELPER(ror_cc)(CPUARMState *env, uint32_t x, uint32_t i) return ((uint32_t)x >> shift) | (x << (32 - shift)); } } + +void HELPER(probe_access)(CPUARMState *env, target_ulong ptr, + uint32_t access_type, uint32_t mmu_idx, + uint32_t size) +{ + uint32_t in_page = -((uint32_t)ptr | TARGET_PAGE_SIZE); + uintptr_t ra = GETPC(); + + if (likely(size <= in_page)) { + probe_access(env, ptr, size, access_type, mmu_idx, ra); + } else { + probe_access(env, ptr, in_page, access_type, mmu_idx, ra); + probe_access(env, ptr + in_page, size - in_page, + access_type, mmu_idx, ra); + } +} diff --git a/target/arm/pauth_helper.c b/target/arm/pauth_helper.c index b909630317ecede831df7d0dd3d8c5a7646d6b70..564c48faa67ec5404f7ce1799e7e62eabdf4b98e 100644 --- a/target/arm/pauth_helper.c +++ b/target/arm/pauth_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -300,7 +300,11 @@ static uint64_t pauth_addpac(CPUARMState *env, uint64_t ptr, uint64_t modifier, */ test = sextract64(ptr, bot_bit, top_bit - bot_bit); if (test != 0 && test != -1) { - pac ^= MAKE_64BIT_MASK(top_bit - 1, 1); + /* + * Note that our top_bit is one greater than the pseudocode's + * version, hence "- 2" here. + */ + pac ^= MAKE_64BIT_MASK(top_bit - 2, 1); } /* diff --git a/target/arm/sve.decode b/target/arm/sve.decode index 4f580a25e703c18f76b4fcf5542a28398516304d..5c906033588dfa79dd0895ab1e1c26682ee31e52 100644 --- a/target/arm/sve.decode +++ b/target/arm/sve.decode @@ -5,7 +5,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -150,13 +150,17 @@ @rd_rn_i6 ........ ... rn:5 ..... imm:s6 rd:5 &rri # Two register operand, one immediate operand, with predicate, -# element size encoded as TSZHL. User must fill in imm. -@rdn_pg_tszimm ........ .. ... ... ... pg:3 ..... rd:5 \ - &rpri_esz rn=%reg_movprfx esz=%tszimm_esz +# element size encoded as TSZHL. +@rdn_pg_tszimm_shl ........ .. ... ... ... pg:3 ..... rd:5 \ + &rpri_esz rn=%reg_movprfx esz=%tszimm_esz imm=%tszimm_shl +@rdn_pg_tszimm_shr ........ .. ... ... ... pg:3 ..... rd:5 \ + &rpri_esz rn=%reg_movprfx esz=%tszimm_esz imm=%tszimm_shr # Similarly without predicate. -@rd_rn_tszimm ........ .. ... ... ...... rn:5 rd:5 \ - &rri_esz esz=%tszimm16_esz +@rd_rn_tszimm_shl ........ .. ... ... ...... rn:5 rd:5 \ + &rri_esz esz=%tszimm16_esz imm=%tszimm16_shl +@rd_rn_tszimm_shr ........ .. ... ... ...... rn:5 rd:5 \ + &rri_esz esz=%tszimm16_esz imm=%tszimm16_shr # Two register operand, one immediate operand, with 4-bit predicate. # User must fill in imm. @@ -289,14 +293,10 @@ UMINV 00000100 .. 001 011 001 ... ..... ..... @rd_pg_rn ### SVE Shift by Immediate - Predicated Group # SVE bitwise shift by immediate (predicated) -ASR_zpzi 00000100 .. 000 000 100 ... .. ... ..... \ - @rdn_pg_tszimm imm=%tszimm_shr -LSR_zpzi 00000100 .. 000 001 100 ... .. ... ..... \ - @rdn_pg_tszimm imm=%tszimm_shr -LSL_zpzi 00000100 .. 000 011 100 ... .. ... ..... \ - @rdn_pg_tszimm imm=%tszimm_shl -ASRD 00000100 .. 000 100 100 ... .. ... ..... \ - @rdn_pg_tszimm imm=%tszimm_shr +ASR_zpzi 00000100 .. 000 000 100 ... .. ... ..... @rdn_pg_tszimm_shr +LSR_zpzi 00000100 .. 000 001 100 ... .. ... ..... @rdn_pg_tszimm_shr +LSL_zpzi 00000100 .. 000 011 100 ... .. ... ..... @rdn_pg_tszimm_shl +ASRD 00000100 .. 000 100 100 ... .. ... ..... @rdn_pg_tszimm_shr # SVE bitwise shift by vector (predicated) ASR_zpzz 00000100 .. 010 000 100 ... ..... ..... @rdn_pg_rm @@ -400,12 +400,9 @@ RDVL 00000100 101 11111 01010 imm:s6 rd:5 ### SVE Bitwise Shift - Unpredicated Group # SVE bitwise shift by immediate (unpredicated) -ASR_zzi 00000100 .. 1 ..... 1001 00 ..... ..... \ - @rd_rn_tszimm imm=%tszimm16_shr -LSR_zzi 00000100 .. 1 ..... 1001 01 ..... ..... \ - @rd_rn_tszimm imm=%tszimm16_shr -LSL_zzi 00000100 .. 1 ..... 1001 11 ..... ..... \ - @rd_rn_tszimm imm=%tszimm16_shl +ASR_zzi 00000100 .. 1 ..... 1001 00 ..... ..... @rd_rn_tszimm_shr +LSR_zzi 00000100 .. 1 ..... 1001 01 ..... ..... @rd_rn_tszimm_shr +LSL_zzi 00000100 .. 1 ..... 1001 11 ..... ..... @rd_rn_tszimm_shl # SVE bitwise shift by wide elements (unpredicated) # Note esz != 3 diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c index e590db663750f9bd655ed10f8f4b67a760a905ba..5f037c3a8f8cbc6c09343370315329131d1bd0bb 100644 --- a/target/arm/sve_helper.c +++ b/target/arm/sve_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -956,85 +956,43 @@ uint32_t HELPER(sve_pnext)(void *vd, void *vg, uint32_t pred_desc) return flags; } -/* Store zero into every active element of Zd. We will use this for two - * and three-operand predicated instructions for which logic dictates a - * zero result. In particular, logical shift by element size, which is - * otherwise undefined on the host. - * - * For element sizes smaller than uint64_t, we use tables to expand - * the N bits of the controlling predicate to a byte mask, and clear - * those bytes. +/* + * Copy Zn into Zd, and store zero into inactive elements. + * If inv, store zeros into the active elements. */ -void HELPER(sve_clr_b)(void *vd, void *vg, uint32_t desc) -{ - intptr_t i, opr_sz = simd_oprsz(desc) / 8; - uint64_t *d = vd; - uint8_t *pg = vg; - for (i = 0; i < opr_sz; i += 1) { - d[i] &= ~expand_pred_b(pg[H1(i)]); - } -} - -void HELPER(sve_clr_h)(void *vd, void *vg, uint32_t desc) -{ - intptr_t i, opr_sz = simd_oprsz(desc) / 8; - uint64_t *d = vd; - uint8_t *pg = vg; - for (i = 0; i < opr_sz; i += 1) { - d[i] &= ~expand_pred_h(pg[H1(i)]); - } -} - -void HELPER(sve_clr_s)(void *vd, void *vg, uint32_t desc) -{ - intptr_t i, opr_sz = simd_oprsz(desc) / 8; - uint64_t *d = vd; - uint8_t *pg = vg; - for (i = 0; i < opr_sz; i += 1) { - d[i] &= ~expand_pred_s(pg[H1(i)]); - } -} - -void HELPER(sve_clr_d)(void *vd, void *vg, uint32_t desc) -{ - intptr_t i, opr_sz = simd_oprsz(desc) / 8; - uint64_t *d = vd; - uint8_t *pg = vg; - for (i = 0; i < opr_sz; i += 1) { - if (pg[H1(i)] & 1) { - d[i] = 0; - } - } -} - -/* Copy Zn into Zd, and store zero into inactive elements. */ void HELPER(sve_movz_b)(void *vd, void *vn, void *vg, uint32_t desc) { intptr_t i, opr_sz = simd_oprsz(desc) / 8; + uint64_t inv = -(uint64_t)(simd_data(desc) & 1); uint64_t *d = vd, *n = vn; uint8_t *pg = vg; + for (i = 0; i < opr_sz; i += 1) { - d[i] = n[i] & expand_pred_b(pg[H1(i)]); + d[i] = n[i] & (expand_pred_b(pg[H1(i)]) ^ inv); } } void HELPER(sve_movz_h)(void *vd, void *vn, void *vg, uint32_t desc) { intptr_t i, opr_sz = simd_oprsz(desc) / 8; + uint64_t inv = -(uint64_t)(simd_data(desc) & 1); uint64_t *d = vd, *n = vn; uint8_t *pg = vg; + for (i = 0; i < opr_sz; i += 1) { - d[i] = n[i] & expand_pred_h(pg[H1(i)]); + d[i] = n[i] & (expand_pred_h(pg[H1(i)]) ^ inv); } } void HELPER(sve_movz_s)(void *vd, void *vn, void *vg, uint32_t desc) { intptr_t i, opr_sz = simd_oprsz(desc) / 8; + uint64_t inv = -(uint64_t)(simd_data(desc) & 1); uint64_t *d = vd, *n = vn; uint8_t *pg = vg; + for (i = 0; i < opr_sz; i += 1) { - d[i] = n[i] & expand_pred_s(pg[H1(i)]); + d[i] = n[i] & (expand_pred_s(pg[H1(i)]) ^ inv); } } @@ -1043,8 +1001,10 @@ void HELPER(sve_movz_d)(void *vd, void *vn, void *vg, uint32_t desc) intptr_t i, opr_sz = simd_oprsz(desc) / 8; uint64_t *d = vd, *n = vn; uint8_t *pg = vg; + uint8_t inv = simd_data(desc); + for (i = 0; i < opr_sz; i += 1) { - d[i] = n[i] & -(uint64_t)(pg[H1(i)] & 1); + d[i] = n[i] & -(uint64_t)((pg[H1(i)] ^ inv) & 1); } } @@ -3966,14 +3926,16 @@ static void sve_##NAME##_host(void *vd, intptr_t reg_off, void *host) \ static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \ target_ulong addr, uintptr_t ra) \ { \ - *(TYPEE *)(vd + H(reg_off)) = (TYPEM)TLB(env, addr, ra); \ + *(TYPEE *)(vd + H(reg_off)) = \ + (TYPEM)TLB(env, useronly_clean_ptr(addr), ra); \ } #define DO_ST_TLB(NAME, H, TYPEE, TYPEM, TLB) \ static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \ target_ulong addr, uintptr_t ra) \ { \ - TLB(env, addr, (TYPEM)*(TYPEE *)(vd + H(reg_off)), ra); \ + TLB(env, useronly_clean_ptr(addr), \ + (TYPEM)*(TYPEE *)(vd + H(reg_off)), ra); \ } #define DO_LD_PRIM_1(NAME, H, TE, TM) \ @@ -4091,6 +4053,19 @@ static bool sve_probe_page(SVEHostPage *info, bool nofault, int flags; addr += mem_off; + + /* + * User-only currently always issues with TBI. See the comment + * above useronly_clean_ptr. Usually we clean this top byte away + * during translation, but we can't do that for e.g. vector + imm + * addressing modes. + * + * We currently always enable TBI for user-only, and do not provide + * a way to turn it off. So clean the pointer unconditionally here, + * rather than look it up here, or pass it down from above. + */ + addr = useronly_clean_ptr(addr); + flags = probe_access_flags(env, addr, access_type, mmu_idx, nofault, &info->host, retaddr); info->flags = flags; @@ -4393,15 +4368,89 @@ static void sve_cont_ldst_watchpoints(SVEContLdSt *info, CPUARMState *env, #endif } +typedef uint64_t mte_check_fn(CPUARMState *, uint32_t, uint64_t, uintptr_t); + +static inline QEMU_ALWAYS_INLINE +void sve_cont_ldst_mte_check_int(SVEContLdSt *info, CPUARMState *env, + uint64_t *vg, target_ulong addr, int esize, + int msize, uint32_t mtedesc, uintptr_t ra, + mte_check_fn *check) +{ + intptr_t mem_off, reg_off, reg_last; + + /* Process the page only if MemAttr == Tagged. */ + if (arm_tlb_mte_tagged(&info->page[0].attrs)) { + mem_off = info->mem_off_first[0]; + reg_off = info->reg_off_first[0]; + reg_last = info->reg_off_split; + if (reg_last < 0) { + reg_last = info->reg_off_last[0]; + } + + do { + uint64_t pg = vg[reg_off >> 6]; + do { + if ((pg >> (reg_off & 63)) & 1) { + check(env, mtedesc, addr, ra); + } + reg_off += esize; + mem_off += msize; + } while (reg_off <= reg_last && (reg_off & 63)); + } while (reg_off <= reg_last); + } + + mem_off = info->mem_off_first[1]; + if (mem_off >= 0 && arm_tlb_mte_tagged(&info->page[1].attrs)) { + reg_off = info->reg_off_first[1]; + reg_last = info->reg_off_last[1]; + + do { + uint64_t pg = vg[reg_off >> 6]; + do { + if ((pg >> (reg_off & 63)) & 1) { + check(env, mtedesc, addr, ra); + } + reg_off += esize; + mem_off += msize; + } while (reg_off & 63); + } while (reg_off <= reg_last); + } +} + +typedef void sve_cont_ldst_mte_check_fn(SVEContLdSt *info, CPUARMState *env, + uint64_t *vg, target_ulong addr, + int esize, int msize, uint32_t mtedesc, + uintptr_t ra); + +static void sve_cont_ldst_mte_check1(SVEContLdSt *info, CPUARMState *env, + uint64_t *vg, target_ulong addr, + int esize, int msize, uint32_t mtedesc, + uintptr_t ra) +{ + sve_cont_ldst_mte_check_int(info, env, vg, addr, esize, msize, + mtedesc, ra, mte_check1); +} + +static void sve_cont_ldst_mte_checkN(SVEContLdSt *info, CPUARMState *env, + uint64_t *vg, target_ulong addr, + int esize, int msize, uint32_t mtedesc, + uintptr_t ra) +{ + sve_cont_ldst_mte_check_int(info, env, vg, addr, esize, msize, + mtedesc, ra, mte_checkN); +} + + /* * Common helper for all contiguous 1,2,3,4-register predicated stores. */ static inline QEMU_ALWAYS_INLINE void sve_ldN_r(CPUARMState *env, uint64_t *vg, const target_ulong addr, uint32_t desc, const uintptr_t retaddr, - const int esz, const int msz, const int N, + const int esz, const int msz, const int N, uint32_t mtedesc, sve_ldst1_host_fn *host_fn, - sve_ldst1_tlb_fn *tlb_fn) + sve_ldst1_tlb_fn *tlb_fn, + sve_cont_ldst_mte_check_fn *mte_check_fn) { const unsigned rd = simd_data(desc); const intptr_t reg_max = simd_oprsz(desc); @@ -4426,7 +4475,14 @@ void sve_ldN_r(CPUARMState *env, uint64_t *vg, const target_ulong addr, sve_cont_ldst_watchpoints(&info, env, vg, addr, 1 << esz, N << msz, BP_MEM_READ, retaddr); - /* TODO: MTE check. */ + /* + * Handle mte checks for all active elements. + * Since TBI must be set for MTE, !mtedesc => !mte_active. + */ + if (mte_check_fn && mtedesc) { + mte_check_fn(&info, env, vg, addr, 1 << esz, N << msz, + mtedesc, retaddr); + } flags = info.page[0].flags | info.page[1].flags; if (unlikely(flags != 0)) { @@ -4532,26 +4588,67 @@ void sve_ldN_r(CPUARMState *env, uint64_t *vg, const target_ulong addr, } } -#define DO_LD1_1(NAME, ESZ) \ -void HELPER(sve_##NAME##_r)(CPUARMState *env, void *vg, \ - target_ulong addr, uint32_t desc) \ -{ \ - sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, MO_8, 1, \ - sve_##NAME##_host, sve_##NAME##_tlb); \ +static inline QEMU_ALWAYS_INLINE +void sve_ldN_r_mte(CPUARMState *env, uint64_t *vg, target_ulong addr, + uint32_t desc, const uintptr_t ra, + const int esz, const int msz, const int N, + sve_ldst1_host_fn *host_fn, + sve_ldst1_tlb_fn *tlb_fn) +{ + uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT); + int bit55 = extract64(addr, 55, 1); + + /* Remove mtedesc from the normal sve descriptor. */ + desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT); + + /* Perform gross MTE suppression early. */ + if (!tbi_check(desc, bit55) || + tcma_check(desc, bit55, allocation_tag_from_addr(addr))) { + mtedesc = 0; + } + + sve_ldN_r(env, vg, addr, desc, ra, esz, msz, N, mtedesc, host_fn, tlb_fn, + N == 1 ? sve_cont_ldst_mte_check1 : sve_cont_ldst_mte_checkN); } -#define DO_LD1_2(NAME, ESZ, MSZ) \ -void HELPER(sve_##NAME##_le_r)(CPUARMState *env, void *vg, \ - target_ulong addr, uint32_t desc) \ -{ \ - sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, 1, \ - sve_##NAME##_le_host, sve_##NAME##_le_tlb); \ -} \ -void HELPER(sve_##NAME##_be_r)(CPUARMState *env, void *vg, \ - target_ulong addr, uint32_t desc) \ -{ \ - sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, 1, \ - sve_##NAME##_be_host, sve_##NAME##_be_tlb); \ +#define DO_LD1_1(NAME, ESZ) \ +void HELPER(sve_##NAME##_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, MO_8, 1, 0, \ + sve_##NAME##_host, sve_##NAME##_tlb, NULL); \ +} \ +void HELPER(sve_##NAME##_r_mte)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldN_r_mte(env, vg, addr, desc, GETPC(), ESZ, MO_8, 1, \ + sve_##NAME##_host, sve_##NAME##_tlb); \ +} + +#define DO_LD1_2(NAME, ESZ, MSZ) \ +void HELPER(sve_##NAME##_le_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, 1, 0, \ + sve_##NAME##_le_host, sve_##NAME##_le_tlb, NULL); \ +} \ +void HELPER(sve_##NAME##_be_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, 1, 0, \ + sve_##NAME##_be_host, sve_##NAME##_be_tlb, NULL); \ +} \ +void HELPER(sve_##NAME##_le_r_mte)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldN_r_mte(env, vg, addr, desc, GETPC(), ESZ, MSZ, 1, \ + sve_##NAME##_le_host, sve_##NAME##_le_tlb); \ +} \ +void HELPER(sve_##NAME##_be_r_mte)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldN_r_mte(env, vg, addr, desc, GETPC(), ESZ, MSZ, 1, \ + sve_##NAME##_be_host, sve_##NAME##_be_tlb); \ } DO_LD1_1(ld1bb, MO_8) @@ -4577,26 +4674,44 @@ DO_LD1_2(ld1dd, MO_64, MO_64) #undef DO_LD1_1 #undef DO_LD1_2 -#define DO_LDN_1(N) \ -void HELPER(sve_ld##N##bb_r)(CPUARMState *env, void *vg, \ - target_ulong addr, uint32_t desc) \ -{ \ - sve_ldN_r(env, vg, addr, desc, GETPC(), MO_8, MO_8, N, \ - sve_ld1bb_host, sve_ld1bb_tlb); \ +#define DO_LDN_1(N) \ +void HELPER(sve_ld##N##bb_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldN_r(env, vg, addr, desc, GETPC(), MO_8, MO_8, N, 0, \ + sve_ld1bb_host, sve_ld1bb_tlb, NULL); \ +} \ +void HELPER(sve_ld##N##bb_r_mte)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldN_r_mte(env, vg, addr, desc, GETPC(), MO_8, MO_8, N, \ + sve_ld1bb_host, sve_ld1bb_tlb); \ } -#define DO_LDN_2(N, SUFF, ESZ) \ -void HELPER(sve_ld##N##SUFF##_le_r)(CPUARMState *env, void *vg, \ - target_ulong addr, uint32_t desc) \ -{ \ - sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, ESZ, N, \ - sve_ld1##SUFF##_le_host, sve_ld1##SUFF##_le_tlb); \ -} \ -void HELPER(sve_ld##N##SUFF##_be_r)(CPUARMState *env, void *vg, \ - target_ulong addr, uint32_t desc) \ -{ \ - sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, ESZ, N, \ - sve_ld1##SUFF##_be_host, sve_ld1##SUFF##_be_tlb); \ +#define DO_LDN_2(N, SUFF, ESZ) \ +void HELPER(sve_ld##N##SUFF##_le_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, ESZ, N, 0, \ + sve_ld1##SUFF##_le_host, sve_ld1##SUFF##_le_tlb, NULL); \ +} \ +void HELPER(sve_ld##N##SUFF##_be_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, ESZ, N, 0, \ + sve_ld1##SUFF##_be_host, sve_ld1##SUFF##_be_tlb, NULL); \ +} \ +void HELPER(sve_ld##N##SUFF##_le_r_mte)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldN_r_mte(env, vg, addr, desc, GETPC(), ESZ, ESZ, N, \ + sve_ld1##SUFF##_le_host, sve_ld1##SUFF##_le_tlb); \ +} \ +void HELPER(sve_ld##N##SUFF##_be_r_mte)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldN_r_mte(env, vg, addr, desc, GETPC(), ESZ, ESZ, N, \ + sve_ld1##SUFF##_be_host, sve_ld1##SUFF##_be_tlb); \ } DO_LDN_1(2) @@ -4654,7 +4769,7 @@ static void record_fault(CPUARMState *env, uintptr_t i, uintptr_t oprsz) */ static inline QEMU_ALWAYS_INLINE void sve_ldnfff1_r(CPUARMState *env, void *vg, const target_ulong addr, - uint32_t desc, const uintptr_t retaddr, + uint32_t desc, const uintptr_t retaddr, uint32_t mtedesc, const int esz, const int msz, const SVEContFault fault, sve_ldst1_host_fn *host_fn, sve_ldst1_tlb_fn *tlb_fn) @@ -4686,13 +4801,25 @@ void sve_ldnfff1_r(CPUARMState *env, void *vg, const target_ulong addr, mem_off = info.mem_off_first[0]; flags = info.page[0].flags; + /* + * Disable MTE checking if the Tagged bit is not set. Since TBI must + * be set within MTEDESC for MTE, !mtedesc => !mte_active. + */ + if (arm_tlb_mte_tagged(&info.page[0].attrs)) { + mtedesc = 0; + } + if (fault == FAULT_FIRST) { + /* Trapping mte check for the first-fault element. */ + if (mtedesc) { + mte_check1(env, mtedesc, addr + mem_off, retaddr); + } + /* * Special handling of the first active element, * if it crosses a page boundary or is MMIO. */ bool is_split = mem_off == info.mem_off_split; - /* TODO: MTE check. */ if (unlikely(flags != 0) || unlikely(is_split)) { /* * Use the slow path for cross-page handling. @@ -4728,7 +4855,9 @@ void sve_ldnfff1_r(CPUARMState *env, void *vg, const target_ulong addr, /* Watchpoint hit, see below. */ goto do_fault; } - /* TODO: MTE check. */ + if (mtedesc && !mte_probe1(env, mtedesc, addr + mem_off)) { + goto do_fault; + } /* * Use the slow path for cross-page handling. * This is RAM, without a watchpoint, and will not trap. @@ -4776,7 +4905,9 @@ void sve_ldnfff1_r(CPUARMState *env, void *vg, const target_ulong addr, & BP_MEM_READ)) { goto do_fault; } - /* TODO: MTE check. */ + if (mtedesc && !mte_probe1(env, mtedesc, addr + mem_off)) { + goto do_fault; + } host_fn(vd, reg_off, host + mem_off); } reg_off += 1 << esz; @@ -4814,44 +4945,103 @@ void sve_ldnfff1_r(CPUARMState *env, void *vg, const target_ulong addr, record_fault(env, reg_off, reg_max); } -#define DO_LDFF1_LDNF1_1(PART, ESZ) \ +static inline QEMU_ALWAYS_INLINE +void sve_ldnfff1_r_mte(CPUARMState *env, void *vg, target_ulong addr, + uint32_t desc, const uintptr_t retaddr, + const int esz, const int msz, const SVEContFault fault, + sve_ldst1_host_fn *host_fn, + sve_ldst1_tlb_fn *tlb_fn) +{ + uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT); + int bit55 = extract64(addr, 55, 1); + + /* Remove mtedesc from the normal sve descriptor. */ + desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT); + + /* Perform gross MTE suppression early. */ + if (!tbi_check(desc, bit55) || + tcma_check(desc, bit55, allocation_tag_from_addr(addr))) { + mtedesc = 0; + } + + sve_ldnfff1_r(env, vg, addr, desc, retaddr, mtedesc, + esz, msz, fault, host_fn, tlb_fn); +} + +#define DO_LDFF1_LDNF1_1(PART, ESZ) \ void HELPER(sve_ldff1##PART##_r)(CPUARMState *env, void *vg, \ target_ulong addr, uint32_t desc) \ { \ - sve_ldnfff1_r(env, vg, addr, desc, GETPC(), ESZ, MO_8, FAULT_FIRST, \ + sve_ldnfff1_r(env, vg, addr, desc, GETPC(), 0, ESZ, MO_8, FAULT_FIRST, \ sve_ld1##PART##_host, sve_ld1##PART##_tlb); \ } \ void HELPER(sve_ldnf1##PART##_r)(CPUARMState *env, void *vg, \ target_ulong addr, uint32_t desc) \ { \ - sve_ldnfff1_r(env, vg, addr, desc, GETPC(), ESZ, MO_8, FAULT_NO, \ + sve_ldnfff1_r(env, vg, addr, desc, GETPC(), 0, ESZ, MO_8, FAULT_NO, \ + sve_ld1##PART##_host, sve_ld1##PART##_tlb); \ +} \ +void HELPER(sve_ldff1##PART##_r_mte)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldnfff1_r_mte(env, vg, addr, desc, GETPC(), ESZ, MO_8, FAULT_FIRST, \ + sve_ld1##PART##_host, sve_ld1##PART##_tlb); \ +} \ +void HELPER(sve_ldnf1##PART##_r_mte)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldnfff1_r_mte(env, vg, addr, desc, GETPC(), ESZ, MO_8, FAULT_NO, \ sve_ld1##PART##_host, sve_ld1##PART##_tlb); \ } -#define DO_LDFF1_LDNF1_2(PART, ESZ, MSZ) \ +#define DO_LDFF1_LDNF1_2(PART, ESZ, MSZ) \ void HELPER(sve_ldff1##PART##_le_r)(CPUARMState *env, void *vg, \ target_ulong addr, uint32_t desc) \ { \ - sve_ldnfff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, FAULT_FIRST, \ + sve_ldnfff1_r(env, vg, addr, desc, GETPC(), 0, ESZ, MSZ, FAULT_FIRST, \ sve_ld1##PART##_le_host, sve_ld1##PART##_le_tlb); \ } \ void HELPER(sve_ldnf1##PART##_le_r)(CPUARMState *env, void *vg, \ target_ulong addr, uint32_t desc) \ { \ - sve_ldnfff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, FAULT_NO, \ + sve_ldnfff1_r(env, vg, addr, desc, GETPC(), 0, ESZ, MSZ, FAULT_NO, \ sve_ld1##PART##_le_host, sve_ld1##PART##_le_tlb); \ } \ void HELPER(sve_ldff1##PART##_be_r)(CPUARMState *env, void *vg, \ target_ulong addr, uint32_t desc) \ { \ - sve_ldnfff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, FAULT_FIRST, \ + sve_ldnfff1_r(env, vg, addr, desc, GETPC(), 0, ESZ, MSZ, FAULT_FIRST, \ sve_ld1##PART##_be_host, sve_ld1##PART##_be_tlb); \ } \ void HELPER(sve_ldnf1##PART##_be_r)(CPUARMState *env, void *vg, \ target_ulong addr, uint32_t desc) \ { \ - sve_ldnfff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, FAULT_NO, \ + sve_ldnfff1_r(env, vg, addr, desc, GETPC(), 0, ESZ, MSZ, FAULT_NO, \ sve_ld1##PART##_be_host, sve_ld1##PART##_be_tlb); \ +} \ +void HELPER(sve_ldff1##PART##_le_r_mte)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldnfff1_r_mte(env, vg, addr, desc, GETPC(), ESZ, MSZ, FAULT_FIRST, \ + sve_ld1##PART##_le_host, sve_ld1##PART##_le_tlb); \ +} \ +void HELPER(sve_ldnf1##PART##_le_r_mte)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldnfff1_r_mte(env, vg, addr, desc, GETPC(), ESZ, MSZ, FAULT_NO, \ + sve_ld1##PART##_le_host, sve_ld1##PART##_le_tlb); \ +} \ +void HELPER(sve_ldff1##PART##_be_r_mte)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldnfff1_r_mte(env, vg, addr, desc, GETPC(), ESZ, MSZ, FAULT_FIRST, \ + sve_ld1##PART##_be_host, sve_ld1##PART##_be_tlb); \ +} \ +void HELPER(sve_ldnf1##PART##_be_r_mte)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_ldnfff1_r_mte(env, vg, addr, desc, GETPC(), ESZ, MSZ, FAULT_NO, \ + sve_ld1##PART##_be_host, sve_ld1##PART##_be_tlb); \ } DO_LDFF1_LDNF1_1(bb, MO_8) @@ -4882,11 +5072,12 @@ DO_LDFF1_LDNF1_2(dd, MO_64, MO_64) */ static inline QEMU_ALWAYS_INLINE -void sve_stN_r(CPUARMState *env, uint64_t *vg, target_ulong addr, uint32_t desc, - const uintptr_t retaddr, const int esz, - const int msz, const int N, +void sve_stN_r(CPUARMState *env, uint64_t *vg, target_ulong addr, + uint32_t desc, const uintptr_t retaddr, + const int esz, const int msz, const int N, uint32_t mtedesc, sve_ldst1_host_fn *host_fn, - sve_ldst1_tlb_fn *tlb_fn) + sve_ldst1_tlb_fn *tlb_fn, + sve_cont_ldst_mte_check_fn *mte_check_fn) { const unsigned rd = simd_data(desc); const intptr_t reg_max = simd_oprsz(desc); @@ -4908,7 +5099,14 @@ void sve_stN_r(CPUARMState *env, uint64_t *vg, target_ulong addr, uint32_t desc, sve_cont_ldst_watchpoints(&info, env, vg, addr, 1 << esz, N << msz, BP_MEM_WRITE, retaddr); - /* TODO: MTE check. */ + /* + * Handle mte checks for all active elements. + * Since TBI must be set for MTE, !mtedesc => !mte_active. + */ + if (mte_check_fn && mtedesc) { + mte_check_fn(&info, env, vg, addr, 1 << esz, N << msz, + mtedesc, retaddr); + } flags = info.page[0].flags | info.page[1].flags; if (unlikely(flags != 0)) { @@ -5002,26 +5200,67 @@ void sve_stN_r(CPUARMState *env, uint64_t *vg, target_ulong addr, uint32_t desc, } } -#define DO_STN_1(N, NAME, ESZ) \ -void HELPER(sve_st##N##NAME##_r)(CPUARMState *env, void *vg, \ - target_ulong addr, uint32_t desc) \ -{ \ - sve_stN_r(env, vg, addr, desc, GETPC(), ESZ, MO_8, N, \ - sve_st1##NAME##_host, sve_st1##NAME##_tlb); \ +static inline QEMU_ALWAYS_INLINE +void sve_stN_r_mte(CPUARMState *env, uint64_t *vg, target_ulong addr, + uint32_t desc, const uintptr_t ra, + const int esz, const int msz, const int N, + sve_ldst1_host_fn *host_fn, + sve_ldst1_tlb_fn *tlb_fn) +{ + uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT); + int bit55 = extract64(addr, 55, 1); + + /* Remove mtedesc from the normal sve descriptor. */ + desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT); + + /* Perform gross MTE suppression early. */ + if (!tbi_check(desc, bit55) || + tcma_check(desc, bit55, allocation_tag_from_addr(addr))) { + mtedesc = 0; + } + + sve_stN_r(env, vg, addr, desc, ra, esz, msz, N, mtedesc, host_fn, tlb_fn, + N == 1 ? sve_cont_ldst_mte_check1 : sve_cont_ldst_mte_checkN); } -#define DO_STN_2(N, NAME, ESZ, MSZ) \ -void HELPER(sve_st##N##NAME##_le_r)(CPUARMState *env, void *vg, \ - target_ulong addr, uint32_t desc) \ -{ \ - sve_stN_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, N, \ - sve_st1##NAME##_le_host, sve_st1##NAME##_le_tlb); \ -} \ -void HELPER(sve_st##N##NAME##_be_r)(CPUARMState *env, void *vg, \ - target_ulong addr, uint32_t desc) \ -{ \ - sve_stN_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, N, \ - sve_st1##NAME##_be_host, sve_st1##NAME##_be_tlb); \ +#define DO_STN_1(N, NAME, ESZ) \ +void HELPER(sve_st##N##NAME##_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_stN_r(env, vg, addr, desc, GETPC(), ESZ, MO_8, N, 0, \ + sve_st1##NAME##_host, sve_st1##NAME##_tlb, NULL); \ +} \ +void HELPER(sve_st##N##NAME##_r_mte)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_stN_r_mte(env, vg, addr, desc, GETPC(), ESZ, MO_8, N, \ + sve_st1##NAME##_host, sve_st1##NAME##_tlb); \ +} + +#define DO_STN_2(N, NAME, ESZ, MSZ) \ +void HELPER(sve_st##N##NAME##_le_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_stN_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, N, 0, \ + sve_st1##NAME##_le_host, sve_st1##NAME##_le_tlb, NULL); \ +} \ +void HELPER(sve_st##N##NAME##_be_r)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_stN_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, N, 0, \ + sve_st1##NAME##_be_host, sve_st1##NAME##_be_tlb, NULL); \ +} \ +void HELPER(sve_st##N##NAME##_le_r_mte)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_stN_r_mte(env, vg, addr, desc, GETPC(), ESZ, MSZ, N, \ + sve_st1##NAME##_le_host, sve_st1##NAME##_le_tlb); \ +} \ +void HELPER(sve_st##N##NAME##_be_r_mte)(CPUARMState *env, void *vg, \ + target_ulong addr, uint32_t desc) \ +{ \ + sve_stN_r_mte(env, vg, addr, desc, GETPC(), ESZ, MSZ, N, \ + sve_st1##NAME##_be_host, sve_st1##NAME##_be_tlb); \ } DO_STN_1(1, bb, MO_8) @@ -5090,7 +5329,8 @@ static target_ulong off_zd_d(void *reg, intptr_t reg_ofs) static inline QEMU_ALWAYS_INLINE void sve_ld1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, target_ulong base, uint32_t desc, uintptr_t retaddr, - int esize, int msize, zreg_off_fn *off_fn, + uint32_t mtedesc, int esize, int msize, + zreg_off_fn *off_fn, sve_ldst1_host_fn *host_fn, sve_ldst1_tlb_fn *tlb_fn) { @@ -5118,7 +5358,9 @@ void sve_ld1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, cpu_check_watchpoint(env_cpu(env), addr, msize, info.attrs, BP_MEM_READ, retaddr); } - /* TODO: MTE check */ + if (mtedesc && arm_tlb_mte_tagged(&info.attrs)) { + mte_check1(env, mtedesc, addr, retaddr); + } host_fn(&scratch, reg_off, info.host); } else { /* Element crosses the page boundary. */ @@ -5129,7 +5371,9 @@ void sve_ld1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, msize, info.attrs, BP_MEM_READ, retaddr); } - /* TODO: MTE check */ + if (mtedesc && arm_tlb_mte_tagged(&info.attrs)) { + mte_check1(env, mtedesc, addr, retaddr); + } tlb_fn(env, &scratch, reg_off, addr, retaddr); } } @@ -5142,20 +5386,53 @@ void sve_ld1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, memcpy(vd, &scratch, reg_max); } +static inline QEMU_ALWAYS_INLINE +void sve_ld1_z_mte(CPUARMState *env, void *vd, uint64_t *vg, void *vm, + target_ulong base, uint32_t desc, uintptr_t retaddr, + int esize, int msize, zreg_off_fn *off_fn, + sve_ldst1_host_fn *host_fn, + sve_ldst1_tlb_fn *tlb_fn) +{ + uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT); + /* Remove mtedesc from the normal sve descriptor. */ + desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT); + + /* + * ??? TODO: For the 32-bit offset extractions, base + ofs cannot + * offset base entirely over the address space hole to change the + * pointer tag, or change the bit55 selector. So we could here + * examine TBI + TCMA like we do for sve_ldN_r_mte(). + */ + sve_ld1_z(env, vd, vg, vm, base, desc, retaddr, mtedesc, + esize, msize, off_fn, host_fn, tlb_fn); +} + #define DO_LD1_ZPZ_S(MEM, OFS, MSZ) \ void HELPER(sve_ld##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg, \ void *vm, target_ulong base, uint32_t desc) \ { \ - sve_ld1_z(env, vd, vg, vm, base, desc, GETPC(), 4, 1 << MSZ, \ + sve_ld1_z(env, vd, vg, vm, base, desc, GETPC(), 0, 4, 1 << MSZ, \ off_##OFS##_s, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \ +} \ +void HELPER(sve_ld##MEM##_##OFS##_mte)(CPUARMState *env, void *vd, void *vg, \ + void *vm, target_ulong base, uint32_t desc) \ +{ \ + sve_ld1_z_mte(env, vd, vg, vm, base, desc, GETPC(), 4, 1 << MSZ, \ + off_##OFS##_s, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \ } #define DO_LD1_ZPZ_D(MEM, OFS, MSZ) \ void HELPER(sve_ld##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg, \ void *vm, target_ulong base, uint32_t desc) \ { \ - sve_ld1_z(env, vd, vg, vm, base, desc, GETPC(), 8, 1 << MSZ, \ + sve_ld1_z(env, vd, vg, vm, base, desc, GETPC(), 0, 8, 1 << MSZ, \ off_##OFS##_d, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \ +} \ +void HELPER(sve_ld##MEM##_##OFS##_mte)(CPUARMState *env, void *vd, void *vg, \ + void *vm, target_ulong base, uint32_t desc) \ +{ \ + sve_ld1_z_mte(env, vd, vg, vm, base, desc, GETPC(), 8, 1 << MSZ, \ + off_##OFS##_d, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \ } DO_LD1_ZPZ_S(bsu, zsu, MO_8) @@ -5234,7 +5511,8 @@ DO_LD1_ZPZ_D(dd_be, zd, MO_64) static inline QEMU_ALWAYS_INLINE void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, target_ulong base, uint32_t desc, uintptr_t retaddr, - const int esz, const int msz, zreg_off_fn *off_fn, + uint32_t mtedesc, const int esz, const int msz, + zreg_off_fn *off_fn, sve_ldst1_host_fn *host_fn, sve_ldst1_tlb_fn *tlb_fn) { @@ -5259,6 +5537,9 @@ void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, * Probe the first element, allowing faults. */ addr = base + (off_fn(vm, reg_off) << scale); + if (mtedesc) { + mte_check1(env, mtedesc, addr, retaddr); + } tlb_fn(env, vd, reg_off, addr, retaddr); /* After any fault, zero the other elements. */ @@ -5291,7 +5572,11 @@ void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, (env_cpu(env), addr, msize) & BP_MEM_READ)) { goto fault; } - /* TODO: MTE check. */ + if (mtedesc && + arm_tlb_mte_tagged(&info.attrs) && + !mte_probe1(env, mtedesc, addr)) { + goto fault; + } host_fn(vd, reg_off, info.host); } @@ -5304,20 +5589,58 @@ void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, record_fault(env, reg_off, reg_max); } -#define DO_LDFF1_ZPZ_S(MEM, OFS, MSZ) \ -void HELPER(sve_ldff##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg, \ - void *vm, target_ulong base, uint32_t desc) \ -{ \ - sve_ldff1_z(env, vd, vg, vm, base, desc, GETPC(), MO_32, MSZ, \ - off_##OFS##_s, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \ +static inline QEMU_ALWAYS_INLINE +void sve_ldff1_z_mte(CPUARMState *env, void *vd, uint64_t *vg, void *vm, + target_ulong base, uint32_t desc, uintptr_t retaddr, + const int esz, const int msz, + zreg_off_fn *off_fn, + sve_ldst1_host_fn *host_fn, + sve_ldst1_tlb_fn *tlb_fn) +{ + uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT); + /* Remove mtedesc from the normal sve descriptor. */ + desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT); + + /* + * ??? TODO: For the 32-bit offset extractions, base + ofs cannot + * offset base entirely over the address space hole to change the + * pointer tag, or change the bit55 selector. So we could here + * examine TBI + TCMA like we do for sve_ldN_r_mte(). + */ + sve_ldff1_z(env, vd, vg, vm, base, desc, retaddr, mtedesc, + esz, msz, off_fn, host_fn, tlb_fn); } -#define DO_LDFF1_ZPZ_D(MEM, OFS, MSZ) \ -void HELPER(sve_ldff##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg, \ - void *vm, target_ulong base, uint32_t desc) \ -{ \ - sve_ldff1_z(env, vd, vg, vm, base, desc, GETPC(), MO_64, MSZ, \ - off_##OFS##_d, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \ +#define DO_LDFF1_ZPZ_S(MEM, OFS, MSZ) \ +void HELPER(sve_ldff##MEM##_##OFS) \ + (CPUARMState *env, void *vd, void *vg, \ + void *vm, target_ulong base, uint32_t desc) \ +{ \ + sve_ldff1_z(env, vd, vg, vm, base, desc, GETPC(), 0, MO_32, MSZ, \ + off_##OFS##_s, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \ +} \ +void HELPER(sve_ldff##MEM##_##OFS##_mte) \ + (CPUARMState *env, void *vd, void *vg, \ + void *vm, target_ulong base, uint32_t desc) \ +{ \ + sve_ldff1_z_mte(env, vd, vg, vm, base, desc, GETPC(), MO_32, MSZ, \ + off_##OFS##_s, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \ +} + +#define DO_LDFF1_ZPZ_D(MEM, OFS, MSZ) \ +void HELPER(sve_ldff##MEM##_##OFS) \ + (CPUARMState *env, void *vd, void *vg, \ + void *vm, target_ulong base, uint32_t desc) \ +{ \ + sve_ldff1_z(env, vd, vg, vm, base, desc, GETPC(), 0, MO_64, MSZ, \ + off_##OFS##_d, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \ +} \ +void HELPER(sve_ldff##MEM##_##OFS##_mte) \ + (CPUARMState *env, void *vd, void *vg, \ + void *vm, target_ulong base, uint32_t desc) \ +{ \ + sve_ldff1_z_mte(env, vd, vg, vm, base, desc, GETPC(), MO_64, MSZ, \ + off_##OFS##_d, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \ } DO_LDFF1_ZPZ_S(bsu, zsu, MO_8) @@ -5389,7 +5712,8 @@ DO_LDFF1_ZPZ_D(dd_be, zd, MO_64) static inline QEMU_ALWAYS_INLINE void sve_st1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, target_ulong base, uint32_t desc, uintptr_t retaddr, - int esize, int msize, zreg_off_fn *off_fn, + uint32_t mtedesc, int esize, int msize, + zreg_off_fn *off_fn, sve_ldst1_host_fn *host_fn, sve_ldst1_tlb_fn *tlb_fn) { @@ -5433,7 +5757,10 @@ void sve_st1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, cpu_check_watchpoint(env_cpu(env), addr, msize, info.attrs, BP_MEM_WRITE, retaddr); } - /* TODO: MTE check. */ + + if (mtedesc && arm_tlb_mte_tagged(&info.attrs)) { + mte_check1(env, mtedesc, addr, retaddr); + } } i += 1; reg_off += esize; @@ -5463,20 +5790,53 @@ void sve_st1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, } while (reg_off < reg_max); } -#define DO_ST1_ZPZ_S(MEM, OFS, MSZ) \ -void HELPER(sve_st##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg, \ +static inline QEMU_ALWAYS_INLINE +void sve_st1_z_mte(CPUARMState *env, void *vd, uint64_t *vg, void *vm, + target_ulong base, uint32_t desc, uintptr_t retaddr, + int esize, int msize, zreg_off_fn *off_fn, + sve_ldst1_host_fn *host_fn, + sve_ldst1_tlb_fn *tlb_fn) +{ + uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT); + /* Remove mtedesc from the normal sve descriptor. */ + desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT); + + /* + * ??? TODO: For the 32-bit offset extractions, base + ofs cannot + * offset base entirely over the address space hole to change the + * pointer tag, or change the bit55 selector. So we could here + * examine TBI + TCMA like we do for sve_ldN_r_mte(). + */ + sve_st1_z(env, vd, vg, vm, base, desc, retaddr, mtedesc, + esize, msize, off_fn, host_fn, tlb_fn); +} + +#define DO_ST1_ZPZ_S(MEM, OFS, MSZ) \ +void HELPER(sve_st##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg, \ void *vm, target_ulong base, uint32_t desc) \ -{ \ - sve_st1_z(env, vd, vg, vm, base, desc, GETPC(), 4, 1 << MSZ, \ - off_##OFS##_s, sve_st1##MEM##_host, sve_st1##MEM##_tlb); \ +{ \ + sve_st1_z(env, vd, vg, vm, base, desc, GETPC(), 0, 4, 1 << MSZ, \ + off_##OFS##_s, sve_st1##MEM##_host, sve_st1##MEM##_tlb); \ +} \ +void HELPER(sve_st##MEM##_##OFS##_mte)(CPUARMState *env, void *vd, void *vg, \ + void *vm, target_ulong base, uint32_t desc) \ +{ \ + sve_st1_z_mte(env, vd, vg, vm, base, desc, GETPC(), 4, 1 << MSZ, \ + off_##OFS##_s, sve_st1##MEM##_host, sve_st1##MEM##_tlb); \ } -#define DO_ST1_ZPZ_D(MEM, OFS, MSZ) \ -void HELPER(sve_st##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg, \ +#define DO_ST1_ZPZ_D(MEM, OFS, MSZ) \ +void HELPER(sve_st##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg, \ void *vm, target_ulong base, uint32_t desc) \ -{ \ - sve_st1_z(env, vd, vg, vm, base, desc, GETPC(), 8, 1 << MSZ, \ - off_##OFS##_d, sve_st1##MEM##_host, sve_st1##MEM##_tlb); \ +{ \ + sve_st1_z(env, vd, vg, vm, base, desc, GETPC(), 0, 8, 1 << MSZ, \ + off_##OFS##_d, sve_st1##MEM##_host, sve_st1##MEM##_tlb); \ +} \ +void HELPER(sve_st##MEM##_##OFS##_mte)(CPUARMState *env, void *vd, void *vg, \ + void *vm, target_ulong base, uint32_t desc) \ +{ \ + sve_st1_z_mte(env, vd, vg, vm, base, desc, GETPC(), 8, 1 << MSZ, \ + off_##OFS##_d, sve_st1##MEM##_host, sve_st1##MEM##_tlb); \ } DO_ST1_ZPZ_S(bs, zsu, MO_8) diff --git a/target/arm/t16.decode b/target/arm/t16.decode index 43b9a267a134a87b4e937d15e2d3c5afe07337b5..646c74929d55ab070bbb68c84e956a2dc13b1077 100644 --- a/target/arm/t16.decode +++ b/target/arm/t16.decode @@ -5,7 +5,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/arm/t32.decode b/target/arm/t32.decode index c63082fc9cb5d8b2ff1cec07066cf88392b106b7..cfcc71bfb0a8af0434e3142ea7ad6aeecd78197c 100644 --- a/target/arm/t32.decode +++ b/target/arm/t32.decode @@ -5,7 +5,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -45,6 +45,8 @@ &sat !extern rd rn satimm imm sh &pkh !extern rd rn rm imm tb &cps !extern mode imod M A I F +&mcr !extern cp opc1 crn crm opc2 rt +&mcrr !extern cp opc1 crm rt rt2 # Data-processing (register) @@ -88,6 +90,9 @@ SBC_rrri 1110101 1011 . .... 0 ... .... .... .... @s_rrr_shi } RSB_rrri 1110101 1110 . .... 0 ... .... .... .... @s_rrr_shi +# v8.1M CSEL and friends +CSEL 1110101 0010 1 rn:4 10 op:2 rd:4 fcond:4 rm:4 + # Data-processing (register-shifted register) MOV_rxrr 1111 1010 0 shty:2 s:1 rm:4 1111 rd:4 0000 rs:4 \ @@ -291,8 +296,8 @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm { # Group insn[25:23] = 111, which is cond=111x for the branch below, # or unconditional, which would be illegal for the branch. - { - # Hints + [ + # Hints, and CPS { YIELD 1111 0011 1010 1111 1000 0000 0000 0001 WFE 1111 0011 1010 1111 1000 0000 0000 0010 @@ -305,20 +310,18 @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm # The canonical nop ends in 0000 0000, but the whole rest # of the space is "reserved hint, behaves as nop". NOP 1111 0011 1010 1111 1000 0000 ---- ---- - } - # If imod == '00' && M == '0' then SEE "Hint instructions", above. - CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \ + # If imod == '00' && M == '0' then SEE "Hint instructions", above. + CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \ &cps + } # Miscellaneous control - { - CLREX 1111 0011 1011 1111 1000 1111 0010 1111 - DSB 1111 0011 1011 1111 1000 1111 0100 ---- - DMB 1111 0011 1011 1111 1000 1111 0101 ---- - ISB 1111 0011 1011 1111 1000 1111 0110 ---- - SB 1111 0011 1011 1111 1000 1111 0111 0000 - } + CLREX 1111 0011 1011 1111 1000 1111 0010 1111 + DSB 1111 0011 1011 1111 1000 1111 0100 ---- + DMB 1111 0011 1011 1111 1000 1111 0101 ---- + ISB 1111 0011 1011 1111 1000 1111 0110 ---- + SB 1111 0011 1011 1111 1000 1111 0111 0000 # Note that the v7m insn overlaps both the normal and banked insn. { @@ -346,7 +349,7 @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm HVC 1111 0111 1110 .... 1000 .... .... .... \ &i imm=%imm16_16_0 UDF 1111 0111 1111 ---- 1010 ---- ---- ---- - } + ] B_cond_thumb 1111 0. cond:4 ...... 10.0 ............ &ci imm=%imm21 } @@ -621,6 +624,23 @@ RFE 1110 1001 10.1 .... 1100000000000000 @rfe pu=1 SRS 1110 1000 00.0 1101 1100 0000 000. .... @srs pu=2 SRS 1110 1001 10.0 1101 1100 0000 000. .... @srs pu=1 +# Coprocessor instructions + +# We decode MCR, MCR, MRRC and MCRR only, because for QEMU the +# other coprocessor instructions always UNDEF. +# The trans_ functions for these will ignore cp values 8..13 for v7 or +# earlier, and 0..13 for v8 and later, because those areas of the +# encoding space may be used for other things, such as VFP or Neon. + +@mcr .... .... opc1:3 . crn:4 rt:4 cp:4 opc2:3 . crm:4 +@mcrr .... .... .... rt2:4 rt:4 cp:4 opc1:4 crm:4 + +MCRR 1110 1100 0100 .... .... .... .... .... @mcrr +MRRC 1110 1100 0101 .... .... .... .... .... @mcrr + +MCR 1110 1110 ... 0 .... .... .... ... 1 .... @mcr +MRC 1110 1110 ... 1 .... .... .... ... 1 .... @mcr + # Branches %imm24 26:s1 13:1 11:1 16:10 0:11 !function=t32_branch24 @@ -628,4 +648,23 @@ SRS 1110 1001 10.0 1101 1100 0000 000. .... @srs pu=1 B 1111 0. .......... 10.1 ............ @branch24 BL 1111 0. .......... 11.1 ............ @branch24 -BLX_i 1111 0. .......... 11.0 ............ @branch24 +{ + # BLX_i is non-M-profile only + BLX_i 1111 0. .......... 11.0 ............ @branch24 + # M-profile only: loop and branch insns + [ + # All these BF insns have boff != 0b0000; we NOP them all + BF 1111 0 boff:4 ------- 1100 - ---------- 1 # BFL + BF 1111 0 boff:4 0 ------ 1110 - ---------- 1 # BFCSEL + BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF + BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX + ] + [ + # LE and WLS immediate + %lob_imm 1:10 11:1 !function=times_2 + + DLS 1111 0 0000 100 rn:4 1110 0000 0000 0001 + WLS 1111 0 0000 100 rn:4 1100 . .......... 1 imm=%lob_imm + LE 1111 0 0000 0 f:1 0 1111 1100 . .......... 1 imm=%lob_imm + ] +} diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c index 7388494a55493a3057b074b04370f4ac160a01dc..b35dc8a01187707ae120613772453e7a96a0c0e6 100644 --- a/target/arm/tlb_helper.c +++ b/target/arm/tlb_helper.c @@ -10,8 +10,6 @@ #include "internals.h" #include "exec/exec-all.h" -#if !defined(CONFIG_USER_ONLY) - static inline uint32_t merge_syn_data_abort(uint32_t template_syn, unsigned int target_el, bool same_el, bool ea, @@ -122,6 +120,8 @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, arm_deliver_fault(cpu, vaddr, access_type, mmu_idx, &fi); } +#if !defined(CONFIG_USER_ONLY) + /* * arm_cpu_do_transaction_failed: handle a memory system error response * (eg "no device/memory present at address") by raising an external abort @@ -166,6 +166,7 @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size, int prot, ret; MemTxAttrs attrs = {}; ARMMMUFaultInfo fi = {}; + ARMCacheAttrs cacheattrs = {}; /* * Walk the page table and (if the mapping exists) add the page @@ -175,7 +176,8 @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size, */ ret = get_phys_addr(&cpu->env, address, access_type, core_to_arm_mmu_idx(&cpu->env, mmu_idx), - &phys_addr, &attrs, &prot, &page_size, &fi, NULL); + &phys_addr, &attrs, &prot, &page_size, + &fi, &cacheattrs); if (likely(!ret)) { /* * Map a single [sub]page. Regions smaller than our declared @@ -186,6 +188,11 @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size, phys_addr &= TARGET_PAGE_MASK; address &= TARGET_PAGE_MASK; } + /* Notice and record tagged memory. */ + if (cpu_isar_feature(aa64_mte, cpu) && cacheattrs.attrs == 0xf0) { + arm_tlb_mte_tagged(&attrs) = true; + } + tlb_set_page_with_attrs(cs, address, phys_addr, attrs, prot, mmu_idx, page_size); return true; diff --git a/target/arm/trace.h b/target/arm/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..60372d8e26b8b108908662c91f8ecb5525b28f9d --- /dev/null +++ b/target/arm/trace.h @@ -0,0 +1 @@ +#include "trace/trace-target_arm.h" diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 874f3eb4f97572efb4171f143b7c90cceba91e83..2e3fdfdf6ba8a55e0e80975dae6f66e4b90984e6 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -204,20 +204,20 @@ static void gen_a64_set_pc(DisasContext *s, TCGv_i64 src) } /* - * Return a "clean" address for ADDR according to TBID. - * This is always a fresh temporary, as we need to be able to - * increment this independently of a dirty write-back address. + * Handle MTE and/or TBI. + * + * For TBI, ideally, we would do nothing. Proper behaviour on fault is + * for the tag to be present in the FAR_ELx register. But for user-only + * mode we do not have a TLB with which to implement this, so we must + * remove the top byte now. + * + * Always return a fresh temporary that we can increment independently + * of the write-back address. */ -static TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr) + +TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr) { TCGv_i64 clean = new_tmp_a64(s); - /* - * In order to get the correct value in the FAR_ELx register, - * we must present the memory subsystem with the "dirty" address - * including the TBI. In system mode we can make this work via - * the TLB, dropping the TBI during translation. But for user-only - * mode we don't have that option, and must remove the top byte now. - */ #ifdef CONFIG_USER_ONLY gen_top_byte_ignore(s, clean, addr, s->tbid); #else @@ -226,6 +226,92 @@ static TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr) return clean; } +/* Insert a zero tag into src, with the result at dst. */ +static void gen_address_with_allocation_tag0(TCGv_i64 dst, TCGv_i64 src) +{ + tcg_gen_andi_i64(dst, src, ~MAKE_64BIT_MASK(56, 4)); +} + +static void gen_probe_access(DisasContext *s, TCGv_i64 ptr, + MMUAccessType acc, int log2_size) +{ + TCGv_i32 t_acc = tcg_const_i32(acc); + TCGv_i32 t_idx = tcg_const_i32(get_mem_index(s)); + TCGv_i32 t_size = tcg_const_i32(1 << log2_size); + + gen_helper_probe_access(cpu_env, ptr, t_acc, t_idx, t_size); + tcg_temp_free_i32(t_acc); + tcg_temp_free_i32(t_idx); + tcg_temp_free_i32(t_size); +} + +/* + * For MTE, check a single logical or atomic access. This probes a single + * address, the exact one specified. The size and alignment of the access + * is not relevant to MTE, per se, but watchpoints do require the size, + * and we want to recognize those before making any other changes to state. + */ +static TCGv_i64 gen_mte_check1_mmuidx(DisasContext *s, TCGv_i64 addr, + bool is_write, bool tag_checked, + int log2_size, bool is_unpriv, + int core_idx) +{ + if (tag_checked && s->mte_active[is_unpriv]) { + TCGv_i32 tcg_desc; + TCGv_i64 ret; + int desc = 0; + + desc = FIELD_DP32(desc, MTEDESC, MIDX, core_idx); + desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid); + desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma); + desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write); + desc = FIELD_DP32(desc, MTEDESC, ESIZE, 1 << log2_size); + tcg_desc = tcg_const_i32(desc); + + ret = new_tmp_a64(s); + gen_helper_mte_check1(ret, cpu_env, tcg_desc, addr); + tcg_temp_free_i32(tcg_desc); + + return ret; + } + return clean_data_tbi(s, addr); +} + +TCGv_i64 gen_mte_check1(DisasContext *s, TCGv_i64 addr, bool is_write, + bool tag_checked, int log2_size) +{ + return gen_mte_check1_mmuidx(s, addr, is_write, tag_checked, log2_size, + false, get_mem_index(s)); +} + +/* + * For MTE, check multiple logical sequential accesses. + */ +TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, bool is_write, + bool tag_checked, int log2_esize, int total_size) +{ + if (tag_checked && s->mte_active[0] && total_size != (1 << log2_esize)) { + TCGv_i32 tcg_desc; + TCGv_i64 ret; + int desc = 0; + + desc = FIELD_DP32(desc, MTEDESC, MIDX, get_mem_index(s)); + desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid); + desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma); + desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write); + desc = FIELD_DP32(desc, MTEDESC, ESIZE, 1 << log2_esize); + desc = FIELD_DP32(desc, MTEDESC, TSIZE, total_size); + tcg_desc = tcg_const_i32(desc); + + ret = new_tmp_a64(s); + gen_helper_mte_checkN(ret, cpu_env, tcg_desc, addr); + tcg_temp_free_i32(tcg_desc); + + return ret; + } + return gen_mte_check1(s, addr, is_write, tag_checked, log2_esize); +} + typedef struct DisasCompare64 { TCGCond cond; TCGv_i64 value; @@ -375,6 +461,12 @@ TCGv_i64 new_tmp_a64(DisasContext *s) return s->tmp_a64[s->tmp_a64_count++] = tcg_temp_new_i64(); } +TCGv_i64 new_tmp_a64_local(DisasContext *s) +{ + assert(s->tmp_a64_count < TMP_A64_MAX); + return s->tmp_a64[s->tmp_a64_count++] = tcg_temp_local_new_i64(); +} + TCGv_i64 new_tmp_a64_zero(DisasContext *s) { TCGv_i64 t = new_tmp_a64(s); @@ -517,25 +609,6 @@ static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v) tcg_temp_free_i64(tmp); } -TCGv_ptr get_fpstatus_ptr(bool is_f16) -{ - TCGv_ptr statusptr = tcg_temp_new_ptr(); - int offset; - - /* In A64 all instructions (both FP and Neon) use the FPCR; there - * is no equivalent of the A32 Neon "standard FPSCR value". - * However half-precision operations operate under a different - * FZ16 flag and use vfp.fp_status_f16 instead of vfp.fp_status. - */ - if (is_f16) { - offset = offsetof(CPUARMState, vfp.fp_status_f16); - } else { - offset = offsetof(CPUARMState, vfp.fp_status); - } - tcg_gen_addi_ptr(statusptr, cpu_env, offset); - return statusptr; -} - /* Expand a 2-operand AdvSIMD vector operation using an expander function. */ static void gen_gvec_fn2(DisasContext *s, bool is_q, int rd, int rn, GVecGen2Fn *gvec_fn, int vece) @@ -571,6 +644,15 @@ static void gen_gvec_fn4(DisasContext *s, bool is_q, int rd, int rn, int rm, is_q ? 16 : 8, vec_full_reg_size(s)); } +/* Expand a 2-operand operation using an out-of-line helper. */ +static void gen_gvec_op2_ool(DisasContext *s, bool is_q, int rd, + int rn, int data, gen_helper_gvec_2 *fn) +{ + tcg_gen_gvec_2_ool(vec_full_reg_offset(s, rd), + vec_full_reg_offset(s, rn), + is_q ? 16 : 8, vec_full_reg_size(s), data, fn); +} + /* Expand a 3-operand operation using an out-of-line helper. */ static void gen_gvec_op3_ool(DisasContext *s, bool is_q, int rd, int rn, int rm, int data, gen_helper_gvec_3 *fn) @@ -588,7 +670,7 @@ static void gen_gvec_op3_fpst(DisasContext *s, bool is_q, int rd, int rn, int rm, bool is_fp16, int data, gen_helper_gvec_3_ptr *fn) { - TCGv_ptr fpst = get_fpstatus_ptr(is_fp16); + TCGv_ptr fpst = fpstatus_ptr(is_fp16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn), vec_full_reg_offset(s, rm), fpst, @@ -596,6 +678,20 @@ static void gen_gvec_op3_fpst(DisasContext *s, bool is_q, int rd, int rn, tcg_temp_free_ptr(fpst); } +/* Expand a 3-operand + qc + operation using an out-of-line helper. */ +static void gen_gvec_op3_qc(DisasContext *s, bool is_q, int rd, int rn, + int rm, gen_helper_gvec_3_ptr *fn) +{ + TCGv_ptr qc_ptr = tcg_temp_new_ptr(); + + tcg_gen_addi_ptr(qc_ptr, cpu_env, offsetof(CPUARMState, vfp.qc)); + tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd), + vec_full_reg_offset(s, rn), + vec_full_reg_offset(s, rm), qc_ptr, + is_q ? 16 : 8, vec_full_reg_size(s), 0, fn); + tcg_temp_free_ptr(qc_ptr); +} + /* Set ZF and NF based on a 64 bit result. This is alas fiddlier * than the 32 bit equivalent. */ @@ -1074,18 +1170,18 @@ static void do_vec_ld(DisasContext *s, int destidx, int element, * unallocated-encoding checks (otherwise the syndrome information * for the resulting exception will be incorrect). */ -static inline bool fp_access_check(DisasContext *s) +static bool fp_access_check(DisasContext *s) { - assert(!s->fp_access_checked); - s->fp_access_checked = true; + if (s->fp_excp_el) { + assert(!s->fp_access_checked); + s->fp_access_checked = true; - if (!s->fp_excp_el) { - return true; + gen_exception_insn(s, s->pc_curr, EXCP_UDEF, + syn_fp_access_trap(1, 0xe, false), s->fp_excp_el); + return false; } - - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_fp_access_trap(1, 0xe, false), s->fp_excp_el); - return false; + s->fp_access_checked = true; + return true; } /* Check that SVE access is enabled. If it is, return true. @@ -1094,10 +1190,14 @@ static inline bool fp_access_check(DisasContext *s) bool sve_access_check(DisasContext *s) { if (s->sve_excp_el) { - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_sve_access_trap(), - s->sve_excp_el); + assert(!s->sve_access_checked); + s->sve_access_checked = true; + + gen_exception_insn(s, s->pc_curr, EXCP_UDEF, + syn_sve_access_trap(), s->sve_excp_el); return false; } + s->sve_access_checked = true; return fp_access_check(s); } @@ -1607,7 +1707,28 @@ static void handle_msr_i(DisasContext *s, uint32_t insn, gen_helper_msr_i_daifclear(cpu_env, t1); tcg_temp_free_i32(t1); /* For DAIFClear, exit the cpu loop to re-evaluate pending IRQs. */ - s->base.is_jmp = DISAS_UPDATE; + s->base.is_jmp = DISAS_UPDATE_EXIT; + break; + + case 0x1c: /* TCO */ + if (dc_isar_feature(aa64_mte, s)) { + /* Full MTE is enabled -- set the TCO bit as directed. */ + if (crm & 1) { + set_pstate_bits(PSTATE_TCO); + } else { + clear_pstate_bits(PSTATE_TCO); + } + t1 = tcg_const_i32(s->current_el); + gen_helper_rebuild_hflags_a64(cpu_env, t1); + tcg_temp_free_i32(t1); + /* Many factors, including TCO, go into MTE_ACTIVE. */ + s->base.is_jmp = DISAS_UPDATE_NOCHAIN; + } else if (dc_isar_feature(aa64_mte_insn_reg, s)) { + /* Only "instructions accessible at EL0" -- PSTATE.TCO is WI. */ + s->base.is_jmp = DISAS_NEXT; + } else { + goto do_unallocated; + } break; default: @@ -1741,9 +1862,62 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread, return; case ARM_CP_DC_ZVA: /* Writes clear the aligned block of memory which rt points into. */ - tcg_rt = clean_data_tbi(s, cpu_reg(s, rt)); + if (s->mte_active[0]) { + TCGv_i32 t_desc; + int desc = 0; + + desc = FIELD_DP32(desc, MTEDESC, MIDX, get_mem_index(s)); + desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid); + desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma); + t_desc = tcg_const_i32(desc); + + tcg_rt = new_tmp_a64(s); + gen_helper_mte_check_zva(tcg_rt, cpu_env, t_desc, cpu_reg(s, rt)); + tcg_temp_free_i32(t_desc); + } else { + tcg_rt = clean_data_tbi(s, cpu_reg(s, rt)); + } gen_helper_dc_zva(cpu_env, tcg_rt); return; + case ARM_CP_DC_GVA: + { + TCGv_i64 clean_addr, tag; + + /* + * DC_GVA, like DC_ZVA, requires that we supply the original + * pointer for an invalid page. Probe that address first. + */ + tcg_rt = cpu_reg(s, rt); + clean_addr = clean_data_tbi(s, tcg_rt); + gen_probe_access(s, clean_addr, MMU_DATA_STORE, MO_8); + + if (s->ata) { + /* Extract the tag from the register to match STZGM. */ + tag = tcg_temp_new_i64(); + tcg_gen_shri_i64(tag, tcg_rt, 56); + gen_helper_stzgm_tags(cpu_env, clean_addr, tag); + tcg_temp_free_i64(tag); + } + } + return; + case ARM_CP_DC_GZVA: + { + TCGv_i64 clean_addr, tag; + + /* For DC_GZVA, we can rely on DC_ZVA for the proper fault. */ + tcg_rt = cpu_reg(s, rt); + clean_addr = clean_data_tbi(s, tcg_rt); + gen_helper_dc_zva(cpu_env, clean_addr); + + if (s->ata) { + /* Extract the tag from the register to match STZGM. */ + tag = tcg_temp_new_i64(); + tcg_gen_shri_i64(tag, tcg_rt, 56); + gen_helper_stzgm_tags(cpu_env, clean_addr, tag); + tcg_temp_free_i64(tag); + } + } + return; default: break; } @@ -1786,7 +1960,7 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread, if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) { /* I/O operations must end the TB here (whether read or write) */ - s->base.is_jmp = DISAS_UPDATE; + s->base.is_jmp = DISAS_UPDATE_EXIT; } if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) { /* @@ -1801,7 +1975,7 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread, * but allow this to be suppressed by the register definition * (usually only necessary to work around guest bugs). */ - s->base.is_jmp = DISAS_UPDATE; + s->base.is_jmp = DISAS_UPDATE_EXIT; } } @@ -2318,7 +2492,7 @@ static void gen_compare_and_swap(DisasContext *s, int rs, int rt, if (rn == 31) { gen_check_sp_alignment(s); } - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), true, rn != 31, size); tcg_gen_atomic_cmpxchg_i64(tcg_rs, clean_addr, tcg_rs, tcg_rt, memidx, size | MO_ALIGN | s->be_data); } @@ -2336,7 +2510,9 @@ static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt, if (rn == 31) { gen_check_sp_alignment(s); } - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + + /* This is a single atomic access, despite the "pair". */ + clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), true, rn != 31, size + 1); if (size == 2) { TCGv_i64 cmp = tcg_temp_new_i64(); @@ -2461,7 +2637,8 @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn) if (is_lasr) { tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL); } - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), + true, rn != 31, size); gen_store_exclusive(s, rs, rt, rt2, clean_addr, size, false); return; @@ -2470,7 +2647,8 @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn) if (rn == 31) { gen_check_sp_alignment(s); } - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), + false, rn != 31, size); s->is_ldex = true; gen_load_exclusive(s, rt, rt2, clean_addr, size, false); if (is_lasr) { @@ -2490,7 +2668,8 @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn) gen_check_sp_alignment(s); } tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL); - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), + true, rn != 31, size); do_gpr_st(s, cpu_reg(s, rt), clean_addr, size, true, rt, disas_ldst_compute_iss_sf(size, false, 0), is_lasr); return; @@ -2506,7 +2685,8 @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn) if (rn == 31) { gen_check_sp_alignment(s); } - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), + false, rn != 31, size); do_gpr_ld(s, cpu_reg(s, rt), clean_addr, size, false, false, true, rt, disas_ldst_compute_iss_sf(size, false, 0), is_lasr); tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ); @@ -2520,7 +2700,8 @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn) if (is_lasr) { tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL); } - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), + true, rn != 31, size); gen_store_exclusive(s, rs, rt, rt2, clean_addr, size, true); return; } @@ -2538,7 +2719,8 @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn) if (rn == 31) { gen_check_sp_alignment(s); } - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), + false, rn != 31, size); s->is_ldex = true; gen_load_exclusive(s, rt, rt2, clean_addr, size, true); if (is_lasr) { @@ -2641,7 +2823,7 @@ static void disas_ld_lit(DisasContext *s, uint32_t insn) * +-----+-------+---+---+-------+---+-------+-------+------+------+ * * opc: LDP/STP/LDNP/STNP 00 -> 32 bit, 10 -> 64 bit - * LDPSW 01 + * LDPSW/STGP 01 * LDP/STP/LDNP/STNP (SIMD) 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit * V: 0 -> GPR, 1 -> Vector * idx: 00 -> signed offset with non-temporal hint, 01 -> post-index, @@ -2666,6 +2848,7 @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn) bool is_signed = false; bool postindex = false; bool wback = false; + bool set_tag = false; TCGv_i64 clean_addr, dirty_addr; @@ -2678,6 +2861,14 @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn) if (is_vector) { size = 2 + opc; + } else if (opc == 1 && !is_load) { + /* STGP */ + if (!dc_isar_feature(aa64_mte_insn_reg, s) || index == 0) { + unallocated_encoding(s); + return; + } + size = 3; + set_tag = true; } else { size = 2 + extract32(opc, 1, 1); is_signed = extract32(opc, 0, 1); @@ -2718,7 +2909,7 @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn) return; } - offset <<= size; + offset <<= (set_tag ? LOG2_TAG_GRANULE : size); if (rn == 31) { gen_check_sp_alignment(s); @@ -2728,7 +2919,24 @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn) if (!postindex) { tcg_gen_addi_i64(dirty_addr, dirty_addr, offset); } - clean_addr = clean_data_tbi(s, dirty_addr); + + if (set_tag) { + if (!s->ata) { + /* + * TODO: We could rely on the stores below, at least for + * system mode, if we arrange to add MO_ALIGN_16. + */ + gen_helper_stg_stub(cpu_env, dirty_addr); + } else if (tb_cflags(s->base.tb) & CF_PARALLEL) { + gen_helper_stg_parallel(cpu_env, dirty_addr, dirty_addr); + } else { + gen_helper_stg(cpu_env, dirty_addr, dirty_addr); + } + } + + clean_addr = gen_mte_checkN(s, dirty_addr, !is_load, + (wback || rn != 31) && !set_tag, + size, 2 << size); if (is_vector) { if (is_load) { @@ -2809,6 +3017,7 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn, bool iss_valid = !is_vector; bool post_index; bool writeback; + int memidx; TCGv_i64 clean_addr, dirty_addr; @@ -2866,7 +3075,11 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn, if (!post_index) { tcg_gen_addi_i64(dirty_addr, dirty_addr, imm9); } - clean_addr = clean_data_tbi(s, dirty_addr); + + memidx = is_unpriv ? get_a64_user_mem_index(s) : get_mem_index(s); + clean_addr = gen_mte_check1_mmuidx(s, dirty_addr, is_store, + writeback || rn != 31, + size, is_unpriv, memidx); if (is_vector) { if (is_store) { @@ -2876,7 +3089,6 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn, } } else { TCGv_i64 tcg_rt = cpu_reg(s, rt); - int memidx = is_unpriv ? get_a64_user_mem_index(s) : get_mem_index(s); bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc); if (is_store) { @@ -2973,7 +3185,7 @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn, ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0); tcg_gen_add_i64(dirty_addr, dirty_addr, tcg_rm); - clean_addr = clean_data_tbi(s, dirty_addr); + clean_addr = gen_mte_check1(s, dirty_addr, is_store, true, size); if (is_vector) { if (is_store) { @@ -3058,7 +3270,7 @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn, dirty_addr = read_cpu_reg_sp(s, rn, 1); offset = imm12 << size; tcg_gen_addi_i64(dirty_addr, dirty_addr, offset); - clean_addr = clean_data_tbi(s, dirty_addr); + clean_addr = gen_mte_check1(s, dirty_addr, is_store, rn != 31, size); if (is_vector) { if (is_store) { @@ -3102,7 +3314,7 @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn, bool r = extract32(insn, 22, 1); bool a = extract32(insn, 23, 1); TCGv_i64 tcg_rs, clean_addr; - AtomicThreeOpFn *fn; + AtomicThreeOpFn *fn = NULL; if (is_vector || !dc_isar_feature(aa64_atomics, s)) { unallocated_encoding(s); @@ -3151,7 +3363,7 @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn, if (rn == 31) { gen_check_sp_alignment(s); } - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), false, rn != 31, size); if (o3_opc == 014) { /* @@ -3216,9 +3428,11 @@ static void disas_ldst_pac(DisasContext *s, uint32_t insn, if (s->pauth_active) { if (use_key_a) { - gen_helper_autda(dirty_addr, cpu_env, dirty_addr, cpu_X[31]); + gen_helper_autda(dirty_addr, cpu_env, dirty_addr, + new_tmp_a64_zero(s)); } else { - gen_helper_autdb(dirty_addr, cpu_env, dirty_addr, cpu_X[31]); + gen_helper_autdb(dirty_addr, cpu_env, dirty_addr, + new_tmp_a64_zero(s)); } } @@ -3228,7 +3442,8 @@ static void disas_ldst_pac(DisasContext *s, uint32_t insn, tcg_gen_addi_i64(dirty_addr, dirty_addr, offset); /* Note that "clean" and "dirty" here refer to TBI not PAC. */ - clean_addr = clean_data_tbi(s, dirty_addr); + clean_addr = gen_mte_check1(s, dirty_addr, false, + is_wback || rn != 31, size); tcg_rt = cpu_reg(s, rt); do_gpr_ld(s, tcg_rt, clean_addr, size, /* is_signed */ false, @@ -3390,7 +3605,7 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn) TCGv_i64 clean_addr, tcg_rn, tcg_ebytes; MemOp endian = s->be_data; - int ebytes; /* bytes per element */ + int total; /* total bytes */ int elements; /* elements per vector */ int rpt; /* num iterations */ int selem; /* structure elements */ @@ -3460,19 +3675,26 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn) endian = MO_LE; } - /* Consecutive little-endian elements from a single register + total = rpt * selem * (is_q ? 16 : 8); + tcg_rn = cpu_reg_sp(s, rn); + + /* + * Issue the MTE check vs the logical repeat count, before we + * promote consecutive little-endian elements below. + */ + clean_addr = gen_mte_checkN(s, tcg_rn, is_store, is_postidx || rn != 31, + size, total); + + /* + * Consecutive little-endian elements from a single register * can be promoted to a larger little-endian operation. */ if (selem == 1 && endian == MO_LE) { size = 3; } - ebytes = 1 << size; - elements = (is_q ? 16 : 8) / ebytes; - - tcg_rn = cpu_reg_sp(s, rn); - clean_addr = clean_data_tbi(s, tcg_rn); - tcg_ebytes = tcg_const_i64(ebytes); + elements = (is_q ? 16 : 8) >> size; + tcg_ebytes = tcg_const_i64(1 << size); for (r = 0; r < rpt; r++) { int e; for (e = 0; e < elements; e++) { @@ -3506,7 +3728,7 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn) if (is_postidx) { if (rm == 31) { - tcg_gen_addi_i64(tcg_rn, tcg_rn, rpt * elements * selem * ebytes); + tcg_gen_addi_i64(tcg_rn, tcg_rn, total); } else { tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm)); } @@ -3552,7 +3774,7 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn) int selem = (extract32(opc, 0, 1) << 1 | R) + 1; bool replicate = false; int index = is_q << 3 | S << 2 | size; - int ebytes, xs; + int xs, total; TCGv_i64 clean_addr, tcg_rn, tcg_ebytes; if (extract32(insn, 31, 1)) { @@ -3606,16 +3828,17 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn) return; } - ebytes = 1 << scale; - if (rn == 31) { gen_check_sp_alignment(s); } + total = selem << scale; tcg_rn = cpu_reg_sp(s, rn); - clean_addr = clean_data_tbi(s, tcg_rn); - tcg_ebytes = tcg_const_i64(ebytes); + clean_addr = gen_mte_checkN(s, tcg_rn, !is_load, is_postidx || rn != 31, + scale, total); + + tcg_ebytes = tcg_const_i64(1 << scale); for (xs = 0; xs < selem; xs++) { if (replicate) { /* Load and replicate to all elements */ @@ -3642,13 +3865,216 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn) if (is_postidx) { if (rm == 31) { - tcg_gen_addi_i64(tcg_rn, tcg_rn, selem * ebytes); + tcg_gen_addi_i64(tcg_rn, tcg_rn, total); } else { tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm)); } } } +/* + * Load/Store memory tags + * + * 31 30 29 24 22 21 12 10 5 0 + * +-----+-------------+-----+---+------+-----+------+------+ + * | 1 1 | 0 1 1 0 0 1 | op1 | 1 | imm9 | op2 | Rn | Rt | + * +-----+-------------+-----+---+------+-----+------+------+ + */ +static void disas_ldst_tag(DisasContext *s, uint32_t insn) +{ + int rt = extract32(insn, 0, 5); + int rn = extract32(insn, 5, 5); + uint64_t offset = sextract64(insn, 12, 9) << LOG2_TAG_GRANULE; + int op2 = extract32(insn, 10, 2); + int op1 = extract32(insn, 22, 2); + bool is_load = false, is_pair = false, is_zero = false, is_mult = false; + int index = 0; + TCGv_i64 addr, clean_addr, tcg_rt; + + /* We checked insn bits [29:24,21] in the caller. */ + if (extract32(insn, 30, 2) != 3) { + goto do_unallocated; + } + + /* + * @index is a tri-state variable which has 3 states: + * < 0 : post-index, writeback + * = 0 : signed offset + * > 0 : pre-index, writeback + */ + switch (op1) { + case 0: + if (op2 != 0) { + /* STG */ + index = op2 - 2; + } else { + /* STZGM */ + if (s->current_el == 0 || offset != 0) { + goto do_unallocated; + } + is_mult = is_zero = true; + } + break; + case 1: + if (op2 != 0) { + /* STZG */ + is_zero = true; + index = op2 - 2; + } else { + /* LDG */ + is_load = true; + } + break; + case 2: + if (op2 != 0) { + /* ST2G */ + is_pair = true; + index = op2 - 2; + } else { + /* STGM */ + if (s->current_el == 0 || offset != 0) { + goto do_unallocated; + } + is_mult = true; + } + break; + case 3: + if (op2 != 0) { + /* STZ2G */ + is_pair = is_zero = true; + index = op2 - 2; + } else { + /* LDGM */ + if (s->current_el == 0 || offset != 0) { + goto do_unallocated; + } + is_mult = is_load = true; + } + break; + + default: + do_unallocated: + unallocated_encoding(s); + return; + } + + if (is_mult + ? !dc_isar_feature(aa64_mte, s) + : !dc_isar_feature(aa64_mte_insn_reg, s)) { + goto do_unallocated; + } + + if (rn == 31) { + gen_check_sp_alignment(s); + } + + addr = read_cpu_reg_sp(s, rn, true); + if (index >= 0) { + /* pre-index or signed offset */ + tcg_gen_addi_i64(addr, addr, offset); + } + + if (is_mult) { + tcg_rt = cpu_reg(s, rt); + + if (is_zero) { + int size = 4 << s->dcz_blocksize; + + if (s->ata) { + gen_helper_stzgm_tags(cpu_env, addr, tcg_rt); + } + /* + * The non-tags portion of STZGM is mostly like DC_ZVA, + * except the alignment happens before the access. + */ + clean_addr = clean_data_tbi(s, addr); + tcg_gen_andi_i64(clean_addr, clean_addr, -size); + gen_helper_dc_zva(cpu_env, clean_addr); + } else if (s->ata) { + if (is_load) { + gen_helper_ldgm(tcg_rt, cpu_env, addr); + } else { + gen_helper_stgm(cpu_env, addr, tcg_rt); + } + } else { + MMUAccessType acc = is_load ? MMU_DATA_LOAD : MMU_DATA_STORE; + int size = 4 << GMID_EL1_BS; + + clean_addr = clean_data_tbi(s, addr); + tcg_gen_andi_i64(clean_addr, clean_addr, -size); + gen_probe_access(s, clean_addr, acc, size); + + if (is_load) { + /* The result tags are zeros. */ + tcg_gen_movi_i64(tcg_rt, 0); + } + } + return; + } + + if (is_load) { + tcg_gen_andi_i64(addr, addr, -TAG_GRANULE); + tcg_rt = cpu_reg(s, rt); + if (s->ata) { + gen_helper_ldg(tcg_rt, cpu_env, addr, tcg_rt); + } else { + clean_addr = clean_data_tbi(s, addr); + gen_probe_access(s, clean_addr, MMU_DATA_LOAD, MO_8); + gen_address_with_allocation_tag0(tcg_rt, addr); + } + } else { + tcg_rt = cpu_reg_sp(s, rt); + if (!s->ata) { + /* + * For STG and ST2G, we need to check alignment and probe memory. + * TODO: For STZG and STZ2G, we could rely on the stores below, + * at least for system mode; user-only won't enforce alignment. + */ + if (is_pair) { + gen_helper_st2g_stub(cpu_env, addr); + } else { + gen_helper_stg_stub(cpu_env, addr); + } + } else if (tb_cflags(s->base.tb) & CF_PARALLEL) { + if (is_pair) { + gen_helper_st2g_parallel(cpu_env, addr, tcg_rt); + } else { + gen_helper_stg_parallel(cpu_env, addr, tcg_rt); + } + } else { + if (is_pair) { + gen_helper_st2g(cpu_env, addr, tcg_rt); + } else { + gen_helper_stg(cpu_env, addr, tcg_rt); + } + } + } + + if (is_zero) { + TCGv_i64 clean_addr = clean_data_tbi(s, addr); + TCGv_i64 tcg_zero = tcg_const_i64(0); + int mem_index = get_mem_index(s); + int i, n = (1 + is_pair) << LOG2_TAG_GRANULE; + + tcg_gen_qemu_st_i64(tcg_zero, clean_addr, mem_index, + MO_Q | MO_ALIGN_16); + for (i = 8; i < n; i += 8) { + tcg_gen_addi_i64(clean_addr, clean_addr, 8); + tcg_gen_qemu_st_i64(tcg_zero, clean_addr, mem_index, MO_Q); + } + tcg_temp_free_i64(tcg_zero); + } + + if (index != 0) { + /* pre-index or post-index */ + if (index < 0) { + /* post-index */ + tcg_gen_addi_i64(addr, addr, offset); + } + tcg_gen_mov_i64(cpu_reg_sp(s, rn), addr); + } +} + /* Loads and stores */ static void disas_ldst(DisasContext *s, uint32_t insn) { @@ -3673,13 +4099,14 @@ static void disas_ldst(DisasContext *s, uint32_t insn) case 0x0d: /* AdvSIMD load/store single structure */ disas_ldst_single_struct(s, insn); break; - case 0x19: /* LDAPR/STLR (unscaled immediate) */ - if (extract32(insn, 10, 2) != 0 || - extract32(insn, 21, 1) != 0) { + case 0x19: + if (extract32(insn, 21, 1) != 0) { + disas_ldst_tag(s, insn); + } else if (extract32(insn, 10, 2) == 0) { + disas_ldst_ldapr_stlr(s, insn); + } else { unallocated_encoding(s); - break; } - disas_ldst_ldapr_stlr(s, insn); break; default: unallocated_encoding(s); @@ -3718,22 +4145,22 @@ static void disas_pc_rel_adr(DisasContext *s, uint32_t insn) /* * Add/subtract (immediate) * - * 31 30 29 28 24 23 22 21 10 9 5 4 0 - * +--+--+--+-----------+-----+-------------+-----+-----+ - * |sf|op| S| 1 0 0 0 1 |shift| imm12 | Rn | Rd | - * +--+--+--+-----------+-----+-------------+-----+-----+ + * 31 30 29 28 23 22 21 10 9 5 4 0 + * +--+--+--+-------------+--+-------------+-----+-----+ + * |sf|op| S| 1 0 0 0 1 0 |sh| imm12 | Rn | Rd | + * +--+--+--+-------------+--+-------------+-----+-----+ * * sf: 0 -> 32bit, 1 -> 64bit * op: 0 -> add , 1 -> sub * S: 1 -> set flags - * shift: 00 -> LSL imm by 0, 01 -> LSL imm by 12 + * sh: 1 -> LSL imm by 12 */ static void disas_add_sub_imm(DisasContext *s, uint32_t insn) { int rd = extract32(insn, 0, 5); int rn = extract32(insn, 5, 5); uint64_t imm = extract32(insn, 10, 12); - int shift = extract32(insn, 22, 2); + bool shift = extract32(insn, 22, 1); bool setflags = extract32(insn, 29, 1); bool sub_op = extract32(insn, 30, 1); bool is_64bit = extract32(insn, 31, 1); @@ -3742,15 +4169,8 @@ static void disas_add_sub_imm(DisasContext *s, uint32_t insn) TCGv_i64 tcg_rd = setflags ? cpu_reg(s, rd) : cpu_reg_sp(s, rd); TCGv_i64 tcg_result; - switch (shift) { - case 0x0: - break; - case 0x1: + if (shift) { imm <<= 12; - break; - default: - unallocated_encoding(s); - return; } tcg_result = tcg_temp_new_i64(); @@ -3779,6 +4199,54 @@ static void disas_add_sub_imm(DisasContext *s, uint32_t insn) tcg_temp_free_i64(tcg_result); } +/* + * Add/subtract (immediate, with tags) + * + * 31 30 29 28 23 22 21 16 14 10 9 5 4 0 + * +--+--+--+-------------+--+---------+--+-------+-----+-----+ + * |sf|op| S| 1 0 0 0 1 1 |o2| uimm6 |o3| uimm4 | Rn | Rd | + * +--+--+--+-------------+--+---------+--+-------+-----+-----+ + * + * op: 0 -> add, 1 -> sub + */ +static void disas_add_sub_imm_with_tags(DisasContext *s, uint32_t insn) +{ + int rd = extract32(insn, 0, 5); + int rn = extract32(insn, 5, 5); + int uimm4 = extract32(insn, 10, 4); + int uimm6 = extract32(insn, 16, 6); + bool sub_op = extract32(insn, 30, 1); + TCGv_i64 tcg_rn, tcg_rd; + int imm; + + /* Test all of sf=1, S=0, o2=0, o3=0. */ + if ((insn & 0xa040c000u) != 0x80000000u || + !dc_isar_feature(aa64_mte_insn_reg, s)) { + unallocated_encoding(s); + return; + } + + imm = uimm6 << LOG2_TAG_GRANULE; + if (sub_op) { + imm = -imm; + } + + tcg_rn = cpu_reg_sp(s, rn); + tcg_rd = cpu_reg_sp(s, rd); + + if (s->ata) { + TCGv_i32 offset = tcg_const_i32(imm); + TCGv_i32 tag_offset = tcg_const_i32(uimm4); + + gen_helper_addsubg(tcg_rd, cpu_env, tcg_rn, offset, tag_offset); + tcg_temp_free_i32(tag_offset); + tcg_temp_free_i32(offset); + } else { + tcg_gen_addi_i64(tcg_rd, tcg_rn, imm); + gen_address_with_allocation_tag0(tcg_rd, tcg_rd); + } +} + /* The input should be a value in the bottom e bits (with higher * bits zero); returns that value replicated into every element * of size e in a 64 bit integer. @@ -4138,9 +4606,12 @@ static void disas_data_proc_imm(DisasContext *s, uint32_t insn) case 0x20: case 0x21: /* PC-rel. addressing */ disas_pc_rel_adr(s, insn); break; - case 0x22: case 0x23: /* Add/subtract (immediate) */ + case 0x22: /* Add/subtract (immediate) */ disas_add_sub_imm(s, insn); break; + case 0x23: /* Add/subtract (immediate, with tags) */ + disas_add_sub_imm_with_tags(s, insn); + break; case 0x24: /* Logical (immediate) */ disas_logic_imm(s, insn); break; @@ -5235,25 +5706,72 @@ static void handle_crc32(DisasContext *s, */ static void disas_data_proc_2src(DisasContext *s, uint32_t insn) { - unsigned int sf, rm, opcode, rn, rd; + unsigned int sf, rm, opcode, rn, rd, setflag; sf = extract32(insn, 31, 1); + setflag = extract32(insn, 29, 1); rm = extract32(insn, 16, 5); opcode = extract32(insn, 10, 6); rn = extract32(insn, 5, 5); rd = extract32(insn, 0, 5); - if (extract32(insn, 29, 1)) { + if (setflag && opcode != 0) { unallocated_encoding(s); return; } switch (opcode) { + case 0: /* SUBP(S) */ + if (sf == 0 || !dc_isar_feature(aa64_mte_insn_reg, s)) { + goto do_unallocated; + } else { + TCGv_i64 tcg_n, tcg_m, tcg_d; + + tcg_n = read_cpu_reg_sp(s, rn, true); + tcg_m = read_cpu_reg_sp(s, rm, true); + tcg_gen_sextract_i64(tcg_n, tcg_n, 0, 56); + tcg_gen_sextract_i64(tcg_m, tcg_m, 0, 56); + tcg_d = cpu_reg(s, rd); + + if (setflag) { + gen_sub_CC(true, tcg_d, tcg_n, tcg_m); + } else { + tcg_gen_sub_i64(tcg_d, tcg_n, tcg_m); + } + } + break; case 2: /* UDIV */ handle_div(s, false, sf, rm, rn, rd); break; case 3: /* SDIV */ handle_div(s, true, sf, rm, rn, rd); break; + case 4: /* IRG */ + if (sf == 0 || !dc_isar_feature(aa64_mte_insn_reg, s)) { + goto do_unallocated; + } + if (s->ata) { + gen_helper_irg(cpu_reg_sp(s, rd), cpu_env, + cpu_reg_sp(s, rn), cpu_reg(s, rm)); + } else { + gen_address_with_allocation_tag0(cpu_reg_sp(s, rd), + cpu_reg_sp(s, rn)); + } + break; + case 5: /* GMI */ + if (sf == 0 || !dc_isar_feature(aa64_mte_insn_reg, s)) { + goto do_unallocated; + } else { + TCGv_i64 t1 = tcg_const_i64(1); + TCGv_i64 t2 = tcg_temp_new_i64(); + + tcg_gen_extract_i64(t2, cpu_reg_sp(s, rn), 56, 4); + tcg_gen_shl_i64(t1, t1, t2); + tcg_gen_or_i64(cpu_reg(s, rd), cpu_reg(s, rm), t1); + + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); + } + break; case 8: /* LSLV */ handle_shift_reg(s, A64_SHIFT_TYPE_LSL, sf, rm, rn, rd); break; @@ -5379,7 +5897,7 @@ static void handle_fp_compare(DisasContext *s, int size, bool cmp_with_zero, bool signal_all_nans) { TCGv_i64 tcg_flags = tcg_temp_new_i64(); - TCGv_ptr fpst = get_fpstatus_ptr(size == MO_16); + TCGv_ptr fpst = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); if (size == MO_64) { TCGv_i64 tcg_vn, tcg_vm; @@ -5638,7 +6156,7 @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn) tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000); break; case 0x3: /* FSQRT */ - fpst = get_fpstatus_ptr(true); + fpst = fpstatus_ptr(FPST_FPCR_F16); gen_helper_sqrt_f16(tcg_res, tcg_op, fpst); break; case 0x8: /* FRINTN */ @@ -5648,7 +6166,7 @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn) case 0xc: /* FRINTA */ { TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7)); - fpst = get_fpstatus_ptr(true); + fpst = fpstatus_ptr(FPST_FPCR_F16); gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst); @@ -5658,11 +6176,11 @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn) break; } case 0xe: /* FRINTX */ - fpst = get_fpstatus_ptr(true); + fpst = fpstatus_ptr(FPST_FPCR_F16); gen_helper_advsimd_rinth_exact(tcg_res, tcg_op, fpst); break; case 0xf: /* FRINTI */ - fpst = get_fpstatus_ptr(true); + fpst = fpstatus_ptr(FPST_FPCR_F16); gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst); break; default: @@ -5734,7 +6252,7 @@ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn) g_assert_not_reached(); } - fpst = get_fpstatus_ptr(false); + fpst = fpstatus_ptr(FPST_FPCR); if (rmode >= 0) { TCGv_i32 tcg_rmode = tcg_const_i32(rmode); gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); @@ -5811,7 +6329,7 @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn) g_assert_not_reached(); } - fpst = get_fpstatus_ptr(false); + fpst = fpstatus_ptr(FPST_FPCR); if (rmode >= 0) { TCGv_i32 tcg_rmode = tcg_const_i32(rmode); gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); @@ -5846,7 +6364,7 @@ static void handle_fp_fcvt(DisasContext *s, int opcode, /* Single to half */ TCGv_i32 tcg_rd = tcg_temp_new_i32(); TCGv_i32 ahp = get_ahp_flag(); - TCGv_ptr fpst = get_fpstatus_ptr(false); + TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR); gen_helper_vfp_fcvt_f32_to_f16(tcg_rd, tcg_rn, fpst, ahp); /* write_fp_sreg is OK here because top half of tcg_rd is zero */ @@ -5866,7 +6384,7 @@ static void handle_fp_fcvt(DisasContext *s, int opcode, /* Double to single */ gen_helper_vfp_fcvtsd(tcg_rd, tcg_rn, cpu_env); } else { - TCGv_ptr fpst = get_fpstatus_ptr(false); + TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR); TCGv_i32 ahp = get_ahp_flag(); /* Double to half */ gen_helper_vfp_fcvt_f64_to_f16(tcg_rd, tcg_rn, fpst, ahp); @@ -5882,7 +6400,7 @@ static void handle_fp_fcvt(DisasContext *s, int opcode, case 0x3: { TCGv_i32 tcg_rn = read_fp_sreg(s, rn); - TCGv_ptr tcg_fpst = get_fpstatus_ptr(false); + TCGv_ptr tcg_fpst = fpstatus_ptr(FPST_FPCR); TCGv_i32 tcg_ahp = get_ahp_flag(); tcg_gen_ext16u_i32(tcg_rn, tcg_rn); if (dtype == 0) { @@ -5999,7 +6517,7 @@ static void handle_fp_2src_single(DisasContext *s, int opcode, TCGv_ptr fpst; tcg_res = tcg_temp_new_i32(); - fpst = get_fpstatus_ptr(false); + fpst = fpstatus_ptr(FPST_FPCR); tcg_op1 = read_fp_sreg(s, rn); tcg_op2 = read_fp_sreg(s, rm); @@ -6052,7 +6570,7 @@ static void handle_fp_2src_double(DisasContext *s, int opcode, TCGv_ptr fpst; tcg_res = tcg_temp_new_i64(); - fpst = get_fpstatus_ptr(false); + fpst = fpstatus_ptr(FPST_FPCR); tcg_op1 = read_fp_dreg(s, rn); tcg_op2 = read_fp_dreg(s, rm); @@ -6105,7 +6623,7 @@ static void handle_fp_2src_half(DisasContext *s, int opcode, TCGv_ptr fpst; tcg_res = tcg_temp_new_i32(); - fpst = get_fpstatus_ptr(true); + fpst = fpstatus_ptr(FPST_FPCR_F16); tcg_op1 = read_fp_hreg(s, rn); tcg_op2 = read_fp_hreg(s, rm); @@ -6204,7 +6722,7 @@ static void handle_fp_3src_single(DisasContext *s, bool o0, bool o1, { TCGv_i32 tcg_op1, tcg_op2, tcg_op3; TCGv_i32 tcg_res = tcg_temp_new_i32(); - TCGv_ptr fpst = get_fpstatus_ptr(false); + TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR); tcg_op1 = read_fp_sreg(s, rn); tcg_op2 = read_fp_sreg(s, rm); @@ -6242,7 +6760,7 @@ static void handle_fp_3src_double(DisasContext *s, bool o0, bool o1, { TCGv_i64 tcg_op1, tcg_op2, tcg_op3; TCGv_i64 tcg_res = tcg_temp_new_i64(); - TCGv_ptr fpst = get_fpstatus_ptr(false); + TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR); tcg_op1 = read_fp_dreg(s, rn); tcg_op2 = read_fp_dreg(s, rm); @@ -6280,7 +6798,7 @@ static void handle_fp_3src_half(DisasContext *s, bool o0, bool o1, { TCGv_i32 tcg_op1, tcg_op2, tcg_op3; TCGv_i32 tcg_res = tcg_temp_new_i32(); - TCGv_ptr fpst = get_fpstatus_ptr(true); + TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR_F16); tcg_op1 = read_fp_hreg(s, rn); tcg_op2 = read_fp_hreg(s, rm); @@ -6426,7 +6944,7 @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode, TCGv_i32 tcg_shift, tcg_single; TCGv_i64 tcg_double; - tcg_fpstatus = get_fpstatus_ptr(type == 3); + tcg_fpstatus = fpstatus_ptr(type == 3 ? FPST_FPCR_F16 : FPST_FPCR); tcg_shift = tcg_const_i32(64 - scale); @@ -6714,7 +7232,7 @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof) static void handle_fjcvtzs(DisasContext *s, int rd, int rn) { TCGv_i64 t = read_fp_dreg(s, rn); - TCGv_ptr fpstatus = get_fpstatus_ptr(false); + TCGv_ptr fpstatus = fpstatus_ptr(FPST_FPCR); gen_helper_fjcvtzs(t, t, fpstatus); @@ -7328,7 +7846,7 @@ static void disas_simd_across_lanes(DisasContext *s, uint32_t insn) * Note that correct NaN propagation requires that we do these * operations in exactly the order specified by the pseudocode. */ - TCGv_ptr fpst = get_fpstatus_ptr(size == MO_16); + TCGv_ptr fpst = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); int fpopcode = opcode | is_min << 4 | is_u << 5; int vmap = (1 << elements) - 1; TCGv_i32 tcg_res32 = do_reduction_op(s, fpopcode, rn, esize, @@ -7840,7 +8358,7 @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn) return; } - fpst = get_fpstatus_ptr(size == MO_16); + fpst = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); break; default: unallocated_encoding(s); @@ -8113,8 +8631,8 @@ static void handle_scalar_simd_shli(DisasContext *s, bool insert, int size = 32 - clz32(immh) - 1; int immhb = immh << 3 | immb; int shift = immhb - (8 << size); - TCGv_i64 tcg_rn = new_tmp_a64(s); - TCGv_i64 tcg_rd = new_tmp_a64(s); + TCGv_i64 tcg_rn; + TCGv_i64 tcg_rd; if (!extract32(immh, 3, 1)) { unallocated_encoding(s); @@ -8353,7 +8871,7 @@ static void handle_simd_intfp_conv(DisasContext *s, int rd, int rn, int elements, int is_signed, int fracbits, int size) { - TCGv_ptr tcg_fpst = get_fpstatus_ptr(size == MO_16); + TCGv_ptr tcg_fpst = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); TCGv_i32 tcg_shift = NULL; MemOp mop = size | (is_signed ? MO_SIGN : 0); @@ -8534,7 +9052,7 @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar, assert(!(is_scalar && is_q)); tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO)); - tcg_fpstatus = get_fpstatus_ptr(size == MO_16); + tcg_fpstatus = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus); fracbits = (16 << size) - immhb; tcg_shift = tcg_const_i32(fracbits); @@ -8873,7 +9391,7 @@ static void handle_3same_float(DisasContext *s, int size, int elements, int fpopcode, int rd, int rn, int rm) { int pass; - TCGv_ptr fpst = get_fpstatus_ptr(false); + TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR); for (pass = 0; pass < elements; pass++) { if (size) { @@ -9266,7 +9784,7 @@ static void disas_simd_scalar_three_reg_same_fp16(DisasContext *s, return; } - fpst = get_fpstatus_ptr(true); + fpst = fpstatus_ptr(FPST_FPCR_F16); tcg_op1 = read_fp_hreg(s, rn); tcg_op2 = read_fp_hreg(s, rm); @@ -9519,13 +10037,13 @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode, return; } - fpst = get_fpstatus_ptr(size == MO_16); + fpst = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); if (is_double) { TCGv_i64 tcg_op = tcg_temp_new_i64(); TCGv_i64 tcg_zero = tcg_const_i64(0); TCGv_i64 tcg_res = tcg_temp_new_i64(); - NeonGenTwoDoubleOPFn *genfn; + NeonGenTwoDoubleOpFn *genfn; bool swap = false; int pass; @@ -9567,7 +10085,7 @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode, TCGv_i32 tcg_op = tcg_temp_new_i32(); TCGv_i32 tcg_zero = tcg_const_i32(0); TCGv_i32 tcg_res = tcg_temp_new_i32(); - NeonGenTwoSingleOPFn *genfn; + NeonGenTwoSingleOpFn *genfn; bool swap = false; int pass, maxpasses; @@ -9649,7 +10167,7 @@ static void handle_2misc_reciprocal(DisasContext *s, int opcode, int size, int rn, int rd) { bool is_double = (size == 3); - TCGv_ptr fpst = get_fpstatus_ptr(false); + TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR); if (is_double) { TCGv_i64 tcg_op = tcg_temp_new_i64(); @@ -9790,7 +10308,7 @@ static void handle_2misc_narrow(DisasContext *s, bool scalar, } else { TCGv_i32 tcg_lo = tcg_temp_new_i32(); TCGv_i32 tcg_hi = tcg_temp_new_i32(); - TCGv_ptr fpst = get_fpstatus_ptr(false); + TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR); TCGv_i32 ahp = get_ahp_flag(); tcg_gen_extr_i64_i32(tcg_lo, tcg_hi, tcg_op); @@ -10052,7 +10570,7 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn) if (is_fcvt) { tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode)); - tcg_fpstatus = get_fpstatus_ptr(false); + tcg_fpstatus = fpstatus_ptr(FPST_FPCR); gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus); } else { tcg_rmode = NULL; @@ -10877,7 +11395,7 @@ static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode, /* Floating point operations need fpst */ if (opcode >= 0x58) { - fpst = get_fpstatus_ptr(false); + fpst = fpstatus_ptr(FPST_FPCR); } else { fpst = NULL; } @@ -11230,6 +11748,15 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn) gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_mla, size); } return; + case 0x16: /* SQDMULH, SQRDMULH */ + { + static gen_helper_gvec_3_ptr * const fns[2][2] = { + { gen_helper_neon_sqdmulh_h, gen_helper_neon_sqrdmulh_h }, + { gen_helper_neon_sqdmulh_s, gen_helper_neon_sqrdmulh_s }, + }; + gen_gvec_op3_qc(s, is_q, rd, rn, rm, fns[size - 1][u]); + } + return; case 0x11: if (!u) { /* CMTST */ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_cmtst, size); @@ -11341,16 +11868,6 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn) genenvfn = fns[size][u]; break; } - case 0x16: /* SQDMULH, SQRDMULH */ - { - static NeonGenTwoOpEnvFn * const fns[2][2] = { - { gen_helper_neon_qdmulh_s16, gen_helper_neon_qrdmulh_s16 }, - { gen_helper_neon_qdmulh_s32, gen_helper_neon_qrdmulh_s32 }, - }; - assert(size == 1 || size == 2); - genenvfn = fns[size - 1][u]; - break; - } default: g_assert_not_reached(); } @@ -11361,18 +11878,6 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn) genfn(tcg_res, tcg_op1, tcg_op2); } - if (opcode == 0xf) { - /* SABA, UABA: accumulating ops */ - static NeonGenTwoOpFn * const fns[3] = { - gen_helper_neon_add_u8, - gen_helper_neon_add_u16, - tcg_gen_add_i32, - }; - - read_vec_element_i32(s, tcg_op1, rd, pass, MO_32); - fns[size](tcg_res, tcg_op1, tcg_res); - } - write_vec_element_i32(s, tcg_res, rd, pass, MO_32); tcg_temp_free_i32(tcg_res); @@ -11487,7 +11992,7 @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn) break; } - fpst = get_fpstatus_ptr(true); + fpst = fpstatus_ptr(FPST_FPCR_F16); if (pairwise) { int maxpass = is_q ? 8 : 4; @@ -11609,7 +12114,7 @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn) gen_helper_advsimd_acgt_f16(tcg_res, tcg_op1, tcg_op2, fpst); break; default: - fprintf(stderr, "%s: insn %#04x, fpop %#2x @ %#" PRIx64 "\n", + fprintf(stderr, "%s: insn 0x%04x, fpop 0x%2x @ 0x%" PRIx64 "\n", __func__, insn, fpopcode, s->pc_curr); g_assert_not_reached(); } @@ -11780,7 +12285,7 @@ static void handle_2misc_widening(DisasContext *s, int opcode, bool is_q, /* 16 -> 32 bit fp conversion */ int srcelt = is_q ? 4 : 0; TCGv_i32 tcg_res[4]; - TCGv_ptr fpst = get_fpstatus_ptr(false); + TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR); TCGv_i32 ahp = get_ahp_flag(); for (pass = 0; pass < 4; pass++) { @@ -11908,8 +12413,8 @@ static void handle_2misc_pairwise(DisasContext *s, int opcode, bool u, } else { for (pass = 0; pass < maxpass; pass++) { TCGv_i64 tcg_op = tcg_temp_new_i64(); - NeonGenOneOpFn *genfn; - static NeonGenOneOpFn * const fns[2][2] = { + NeonGenOne64OpFn *genfn; + static NeonGenOne64OpFn * const fns[2][2] = { { gen_helper_neon_addlp_s8, gen_helper_neon_addlp_u8 }, { gen_helper_neon_addlp_s16, gen_helper_neon_addlp_u16 }, }; @@ -12252,7 +12757,7 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) } if (need_fpstatus || need_rmode) { - tcg_fpstatus = get_fpstatus_ptr(false); + tcg_fpstatus = fpstatus_ptr(FPST_FPCR); } else { tcg_fpstatus = NULL; } @@ -12509,9 +13014,6 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn) fpop = deposit32(opcode, 5, 1, a); fpop = deposit32(fpop, 6, 1, u); - rd = extract32(insn, 0, 5); - rn = extract32(insn, 5, 5); - switch (fpop) { case 0x1d: /* SCVTF */ case 0x5d: /* UCVTF */ @@ -12619,7 +13121,7 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn) case 0x7f: /* FSQRT (vector) */ break; default: - fprintf(stderr, "%s: insn %#04x fpop %#2x\n", __func__, insn, fpop); + fprintf(stderr, "%s: insn 0x%04x fpop 0x%2x\n", __func__, insn, fpop); g_assert_not_reached(); } @@ -12642,7 +13144,7 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn) } if (need_rmode || need_fpst) { - tcg_fpstatus = get_fpstatus_ptr(true); + tcg_fpstatus = fpstatus_ptr(FPST_FPCR_F16); } if (need_rmode) { @@ -12951,7 +13453,7 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn) } if (is_fp) { - fpst = get_fpstatus_ptr(is_fp16); + fpst = fpstatus_ptr(is_fp16 ? FPST_FPCR_F16 : FPST_FPCR); } else { fpst = NULL; } @@ -12996,6 +13498,56 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn) data, gen_helper_gvec_fmlal_idx_a64); } return; + + case 0x08: /* MUL */ + if (!is_long && !is_scalar) { + static gen_helper_gvec_3 * const fns[3] = { + gen_helper_gvec_mul_idx_h, + gen_helper_gvec_mul_idx_s, + gen_helper_gvec_mul_idx_d, + }; + tcg_gen_gvec_3_ool(vec_full_reg_offset(s, rd), + vec_full_reg_offset(s, rn), + vec_full_reg_offset(s, rm), + is_q ? 16 : 8, vec_full_reg_size(s), + index, fns[size - 1]); + return; + } + break; + + case 0x10: /* MLA */ + if (!is_long && !is_scalar) { + static gen_helper_gvec_4 * const fns[3] = { + gen_helper_gvec_mla_idx_h, + gen_helper_gvec_mla_idx_s, + gen_helper_gvec_mla_idx_d, + }; + tcg_gen_gvec_4_ool(vec_full_reg_offset(s, rd), + vec_full_reg_offset(s, rn), + vec_full_reg_offset(s, rm), + vec_full_reg_offset(s, rd), + is_q ? 16 : 8, vec_full_reg_size(s), + index, fns[size - 1]); + return; + } + break; + + case 0x14: /* MLS */ + if (!is_long && !is_scalar) { + static gen_helper_gvec_4 * const fns[3] = { + gen_helper_gvec_mls_idx_h, + gen_helper_gvec_mls_idx_s, + gen_helper_gvec_mls_idx_d, + }; + tcg_gen_gvec_4_ool(vec_full_reg_offset(s, rd), + vec_full_reg_offset(s, rn), + vec_full_reg_offset(s, rm), + vec_full_reg_offset(s, rd), + is_q ? 16 : 8, vec_full_reg_size(s), + index, fns[size - 1]); + return; + } + break; } if (size == 3) { @@ -13403,9 +13955,8 @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn) int rn = extract32(insn, 5, 5); int rd = extract32(insn, 0, 5); int decrypt; - TCGv_ptr tcg_rd_ptr, tcg_rn_ptr; - TCGv_i32 tcg_decrypt; - CryptoThreeOpIntFn *genfn; + gen_helper_gvec_2 *genfn2 = NULL; + gen_helper_gvec_3 *genfn3 = NULL; if (!dc_isar_feature(aa64_aes, s) || size != 0) { unallocated_encoding(s); @@ -13415,19 +13966,19 @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn) switch (opcode) { case 0x4: /* AESE */ decrypt = 0; - genfn = gen_helper_crypto_aese; + genfn3 = gen_helper_crypto_aese; break; case 0x6: /* AESMC */ decrypt = 0; - genfn = gen_helper_crypto_aesmc; + genfn2 = gen_helper_crypto_aesmc; break; case 0x5: /* AESD */ decrypt = 1; - genfn = gen_helper_crypto_aese; + genfn3 = gen_helper_crypto_aese; break; case 0x7: /* AESIMC */ decrypt = 1; - genfn = gen_helper_crypto_aesmc; + genfn2 = gen_helper_crypto_aesmc; break; default: unallocated_encoding(s); @@ -13437,16 +13988,11 @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn) if (!fp_access_check(s)) { return; } - - tcg_rd_ptr = vec_full_reg_ptr(s, rd); - tcg_rn_ptr = vec_full_reg_ptr(s, rn); - tcg_decrypt = tcg_const_i32(decrypt); - - genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_decrypt); - - tcg_temp_free_ptr(tcg_rd_ptr); - tcg_temp_free_ptr(tcg_rn_ptr); - tcg_temp_free_i32(tcg_decrypt); + if (genfn2) { + gen_gvec_op2_ool(s, true, rd, rn, decrypt, genfn2); + } else { + gen_gvec_op3_ool(s, true, rd, rd, rn, decrypt, genfn3); + } } /* Crypto three-reg SHA @@ -13462,8 +14008,7 @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn) int rm = extract32(insn, 16, 5); int rn = extract32(insn, 5, 5); int rd = extract32(insn, 0, 5); - CryptoThreeOpFn *genfn; - TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr; + gen_helper_gvec_3 *genfn; bool feature; if (size != 0) { @@ -13473,10 +14018,19 @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn) switch (opcode) { case 0: /* SHA1C */ + genfn = gen_helper_crypto_sha1c; + feature = dc_isar_feature(aa64_sha1, s); + break; case 1: /* SHA1P */ + genfn = gen_helper_crypto_sha1p; + feature = dc_isar_feature(aa64_sha1, s); + break; case 2: /* SHA1M */ + genfn = gen_helper_crypto_sha1m; + feature = dc_isar_feature(aa64_sha1, s); + break; case 3: /* SHA1SU0 */ - genfn = NULL; + genfn = gen_helper_crypto_sha1su0; feature = dc_isar_feature(aa64_sha1, s); break; case 4: /* SHA256H */ @@ -13504,24 +14058,7 @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn) if (!fp_access_check(s)) { return; } - - tcg_rd_ptr = vec_full_reg_ptr(s, rd); - tcg_rn_ptr = vec_full_reg_ptr(s, rn); - tcg_rm_ptr = vec_full_reg_ptr(s, rm); - - if (genfn) { - genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr); - } else { - TCGv_i32 tcg_opcode = tcg_const_i32(opcode); - - gen_helper_crypto_sha1_3reg(tcg_rd_ptr, tcg_rn_ptr, - tcg_rm_ptr, tcg_opcode); - tcg_temp_free_i32(tcg_opcode); - } - - tcg_temp_free_ptr(tcg_rd_ptr); - tcg_temp_free_ptr(tcg_rn_ptr); - tcg_temp_free_ptr(tcg_rm_ptr); + gen_gvec_op3_ool(s, true, rd, rn, rm, 0, genfn); } /* Crypto two-reg SHA @@ -13536,9 +14073,8 @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn) int opcode = extract32(insn, 12, 5); int rn = extract32(insn, 5, 5); int rd = extract32(insn, 0, 5); - CryptoTwoOpFn *genfn; + gen_helper_gvec_2 *genfn; bool feature; - TCGv_ptr tcg_rd_ptr, tcg_rn_ptr; if (size != 0) { unallocated_encoding(s); @@ -13571,14 +14107,33 @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn) if (!fp_access_check(s)) { return; } + gen_gvec_op2_ool(s, true, rd, rn, 0, genfn); +} - tcg_rd_ptr = vec_full_reg_ptr(s, rd); - tcg_rn_ptr = vec_full_reg_ptr(s, rn); +static void gen_rax1_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m) +{ + tcg_gen_rotli_i64(d, m, 1); + tcg_gen_xor_i64(d, d, n); +} - genfn(tcg_rd_ptr, tcg_rn_ptr); +static void gen_rax1_vec(unsigned vece, TCGv_vec d, TCGv_vec n, TCGv_vec m) +{ + tcg_gen_rotli_vec(vece, d, m, 1); + tcg_gen_xor_vec(vece, d, d, n); +} - tcg_temp_free_ptr(tcg_rd_ptr); - tcg_temp_free_ptr(tcg_rn_ptr); +void gen_gvec_rax1(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, + uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_rotli_vec, 0 }; + static const GVecGen3 op = { + .fni8 = gen_rax1_i64, + .fniv = gen_rax1_vec, + .opt_opc = vecop_list, + .fno = gen_helper_crypto_rax1, + .vece = MO_64, + }; + tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &op); } /* Crypto three-reg SHA512 @@ -13595,25 +14150,26 @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn) int rn = extract32(insn, 5, 5); int rd = extract32(insn, 0, 5); bool feature; - CryptoThreeOpFn *genfn; + gen_helper_gvec_3 *oolfn = NULL; + GVecGen3Fn *gvecfn = NULL; if (o == 0) { switch (opcode) { case 0: /* SHA512H */ feature = dc_isar_feature(aa64_sha512, s); - genfn = gen_helper_crypto_sha512h; + oolfn = gen_helper_crypto_sha512h; break; case 1: /* SHA512H2 */ feature = dc_isar_feature(aa64_sha512, s); - genfn = gen_helper_crypto_sha512h2; + oolfn = gen_helper_crypto_sha512h2; break; case 2: /* SHA512SU1 */ feature = dc_isar_feature(aa64_sha512, s); - genfn = gen_helper_crypto_sha512su1; + oolfn = gen_helper_crypto_sha512su1; break; case 3: /* RAX1 */ feature = dc_isar_feature(aa64_sha3, s); - genfn = NULL; + gvecfn = gen_gvec_rax1; break; default: g_assert_not_reached(); @@ -13622,15 +14178,15 @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn) switch (opcode) { case 0: /* SM3PARTW1 */ feature = dc_isar_feature(aa64_sm3, s); - genfn = gen_helper_crypto_sm3partw1; + oolfn = gen_helper_crypto_sm3partw1; break; case 1: /* SM3PARTW2 */ feature = dc_isar_feature(aa64_sm3, s); - genfn = gen_helper_crypto_sm3partw2; + oolfn = gen_helper_crypto_sm3partw2; break; case 2: /* SM4EKEY */ feature = dc_isar_feature(aa64_sm4, s); - genfn = gen_helper_crypto_sm4ekey; + oolfn = gen_helper_crypto_sm4ekey; break; default: unallocated_encoding(s); @@ -13647,41 +14203,10 @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn) return; } - if (genfn) { - TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr; - - tcg_rd_ptr = vec_full_reg_ptr(s, rd); - tcg_rn_ptr = vec_full_reg_ptr(s, rn); - tcg_rm_ptr = vec_full_reg_ptr(s, rm); - - genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr); - - tcg_temp_free_ptr(tcg_rd_ptr); - tcg_temp_free_ptr(tcg_rn_ptr); - tcg_temp_free_ptr(tcg_rm_ptr); + if (oolfn) { + gen_gvec_op3_ool(s, true, rd, rn, rm, 0, oolfn); } else { - TCGv_i64 tcg_op1, tcg_op2, tcg_res[2]; - int pass; - - tcg_op1 = tcg_temp_new_i64(); - tcg_op2 = tcg_temp_new_i64(); - tcg_res[0] = tcg_temp_new_i64(); - tcg_res[1] = tcg_temp_new_i64(); - - for (pass = 0; pass < 2; pass++) { - read_vec_element(s, tcg_op1, rn, pass, MO_64); - read_vec_element(s, tcg_op2, rm, pass, MO_64); - - tcg_gen_rotli_i64(tcg_res[pass], tcg_op2, 1); - tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1); - } - write_vec_element(s, tcg_res[0], rd, 0, MO_64); - write_vec_element(s, tcg_res[1], rd, 1, MO_64); - - tcg_temp_free_i64(tcg_op1); - tcg_temp_free_i64(tcg_op2); - tcg_temp_free_i64(tcg_res[0]); - tcg_temp_free_i64(tcg_res[1]); + gen_gvec_fn3(s, true, rd, rn, rm, gvecfn, MO_64); } } @@ -13696,18 +14221,14 @@ static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn) int opcode = extract32(insn, 10, 2); int rn = extract32(insn, 5, 5); int rd = extract32(insn, 0, 5); - TCGv_ptr tcg_rd_ptr, tcg_rn_ptr; bool feature; - CryptoTwoOpFn *genfn; switch (opcode) { case 0: /* SHA512SU0 */ feature = dc_isar_feature(aa64_sha512, s); - genfn = gen_helper_crypto_sha512su0; break; case 1: /* SM4E */ feature = dc_isar_feature(aa64_sm4, s); - genfn = gen_helper_crypto_sm4e; break; default: unallocated_encoding(s); @@ -13723,13 +14244,16 @@ static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn) return; } - tcg_rd_ptr = vec_full_reg_ptr(s, rd); - tcg_rn_ptr = vec_full_reg_ptr(s, rn); - - genfn(tcg_rd_ptr, tcg_rn_ptr); - - tcg_temp_free_ptr(tcg_rd_ptr); - tcg_temp_free_ptr(tcg_rn_ptr); + switch (opcode) { + case 0: /* SHA512SU0 */ + gen_gvec_op2_ool(s, true, rd, rn, 0, gen_helper_crypto_sha512su0); + break; + case 1: /* SM4E */ + gen_gvec_op3_ool(s, true, rd, rd, rn, 0, gen_helper_crypto_sm4e); + break; + default: + g_assert_not_reached(); + } } /* Crypto four-register @@ -13885,13 +14409,15 @@ static void disas_crypto_xar(DisasContext *s, uint32_t insn) */ static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn) { + static gen_helper_gvec_3 * const fns[4] = { + gen_helper_crypto_sm3tt1a, gen_helper_crypto_sm3tt1b, + gen_helper_crypto_sm3tt2a, gen_helper_crypto_sm3tt2b, + }; int opcode = extract32(insn, 10, 2); int imm2 = extract32(insn, 12, 2); int rm = extract32(insn, 16, 5); int rn = extract32(insn, 5, 5); int rd = extract32(insn, 0, 5); - TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr; - TCGv_i32 tcg_imm2, tcg_opcode; if (!dc_isar_feature(aa64_sm3, s)) { unallocated_encoding(s); @@ -13902,20 +14428,7 @@ static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn) return; } - tcg_rd_ptr = vec_full_reg_ptr(s, rd); - tcg_rn_ptr = vec_full_reg_ptr(s, rn); - tcg_rm_ptr = vec_full_reg_ptr(s, rm); - tcg_imm2 = tcg_const_i32(imm2); - tcg_opcode = tcg_const_i32(opcode); - - gen_helper_crypto_sm3tt(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr, tcg_imm2, - tcg_opcode); - - tcg_temp_free_ptr(tcg_rd_ptr); - tcg_temp_free_ptr(tcg_rn_ptr); - tcg_temp_free_ptr(tcg_rm_ptr); - tcg_temp_free_i32(tcg_imm2); - tcg_temp_free_i32(tcg_opcode); + gen_gvec_op3_ool(s, true, rd, rn, rm, imm2, fns[opcode]); } /* C3.6 Data processing - SIMD, inc Crypto @@ -13994,10 +14507,10 @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn) */ static bool is_guarded_page(CPUARMState *env, DisasContext *s) { + uint64_t addr = s->base.pc_first; #ifdef CONFIG_USER_ONLY - return false; /* FIXME */ + return page_get_flags(addr) & PAGE_BTI; #else - uint64_t addr = s->base.pc_first; int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx); unsigned int index = tlb_index(env, mmu_idx, addr); CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr); @@ -14013,7 +14526,7 @@ static bool is_guarded_page(CPUARMState *env, DisasContext *s) * table entry even for that case. */ return (tlb_hit(entry->addr_code, addr) && - env_tlb(env)->d[mmu_idx].iotlb[index].attrs.target_tlb_bit0); + arm_tlb_bti_gp(&env_tlb(env)->d[mmu_idx].iotlb[index].attrs)); #endif } @@ -14080,6 +14593,7 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s) s->base.pc_next += 4; s->fp_access_checked = false; + s->sve_access_checked = false; if (dc_isar_feature(aa64_bti, s)) { if (s->base.num_insns == 1) { @@ -14192,6 +14706,7 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase, dc->mmu_idx = core_to_aa64_mmu_idx(core_mmu_idx); dc->tbii = FIELD_EX32(tb_flags, TBFLAG_A64, TBII); dc->tbid = FIELD_EX32(tb_flags, TBFLAG_A64, TBID); + dc->tcma = FIELD_EX32(tb_flags, TBFLAG_A64, TCMA); dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx); #if !defined(CONFIG_USER_ONLY) dc->user = (dc->current_el == 0); @@ -14203,10 +14718,19 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase, dc->bt = FIELD_EX32(tb_flags, TBFLAG_A64, BT); dc->btype = FIELD_EX32(tb_flags, TBFLAG_A64, BTYPE); dc->unpriv = FIELD_EX32(tb_flags, TBFLAG_A64, UNPRIV); + dc->ata = FIELD_EX32(tb_flags, TBFLAG_A64, ATA); + dc->mte_active[0] = FIELD_EX32(tb_flags, TBFLAG_A64, MTE_ACTIVE); + dc->mte_active[1] = FIELD_EX32(tb_flags, TBFLAG_A64, MTE0_ACTIVE); dc->vec_len = 0; dc->vec_stride = 0; dc->cp_regs = arm_cpu->cp_regs; dc->features = env->features; + dc->dcz_blocksize = arm_cpu->dcz_blocksize; + +#ifdef CONFIG_USER_ONLY + /* In sve_probe_page, we assume TBI is enabled. */ + tcg_debug_assert(dc->tbid & 1); +#endif /* Single step state. The code-generation logic here is: * SS_ACTIVE == 0: @@ -14334,12 +14858,15 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) gen_goto_tb(dc, 1, dc->base.pc_next); break; default: - case DISAS_UPDATE: + case DISAS_UPDATE_EXIT: gen_a64_set_pc_im(dc->base.pc_next); /* fall through */ case DISAS_EXIT: tcg_gen_exit_tb(NULL, 0); break; + case DISAS_UPDATE_NOCHAIN: + gen_a64_set_pc_im(dc->base.pc_next); + /* fall through */ case DISAS_JUMP: tcg_gen_lookup_and_goto_ptr(); break; diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h index f02fbb63a4aeeac193249192b95b15051521e577..3668b671ddb8f46345167bd57efd04d36b923db7 100644 --- a/target/arm/translate-a64.h +++ b/target/arm/translate-a64.h @@ -4,7 +4,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -30,16 +30,21 @@ void unallocated_encoding(DisasContext *s); } while (0) TCGv_i64 new_tmp_a64(DisasContext *s); +TCGv_i64 new_tmp_a64_local(DisasContext *s); TCGv_i64 new_tmp_a64_zero(DisasContext *s); TCGv_i64 cpu_reg(DisasContext *s, int reg); TCGv_i64 cpu_reg_sp(DisasContext *s, int reg); TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf); TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf); void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v); -TCGv_ptr get_fpstatus_ptr(bool); bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn, unsigned int imms, unsigned int immr); bool sve_access_check(DisasContext *s); +TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr); +TCGv_i64 gen_mte_check1(DisasContext *s, TCGv_i64 addr, bool is_write, + bool tag_checked, int log2_size); +TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, bool is_write, + bool tag_checked, int count, int log2_esize); /* We should have at some point before trying to access an FP register * done the necessary access check, so assert that @@ -115,4 +120,7 @@ static inline int vec_full_reg_size(DisasContext *s) bool disas_sve(DisasContext *, uint32_t); +void gen_gvec_rax1(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, + uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); + #endif /* TARGET_ARM_TRANSLATE_A64_H */ diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc new file mode 100644 index 0000000000000000000000000000000000000000..f6c68e30ab2b0743a5198ed37cb26adef8676ec6 --- /dev/null +++ b/target/arm/translate-neon.c.inc @@ -0,0 +1,3942 @@ +/* + * ARM translation: AArch32 Neon instructions + * + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2005-2007 CodeSourcery + * Copyright (c) 2007 OpenedHand, Ltd. + * Copyright (c) 2020 Linaro, Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +/* + * This file is intended to be included from translate.c; it uses + * some macros and definitions provided by that file. + * It might be possible to convert it to a standalone .c file eventually. + */ + +static inline int plus1(DisasContext *s, int x) +{ + return x + 1; +} + +static inline int rsub_64(DisasContext *s, int x) +{ + return 64 - x; +} + +static inline int rsub_32(DisasContext *s, int x) +{ + return 32 - x; +} +static inline int rsub_16(DisasContext *s, int x) +{ + return 16 - x; +} +static inline int rsub_8(DisasContext *s, int x) +{ + return 8 - x; +} + +static inline int neon_3same_fp_size(DisasContext *s, int x) +{ + /* Convert 0==fp32, 1==fp16 into a MO_* value */ + return MO_32 - x; +} + +/* Include the generated Neon decoder */ +#include "decode-neon-dp.c.inc" +#include "decode-neon-ls.c.inc" +#include "decode-neon-shared.c.inc" + +static void neon_load_element(TCGv_i32 var, int reg, int ele, MemOp mop) +{ + long offset = neon_element_offset(reg, ele, mop & MO_SIZE); + + switch (mop) { + case MO_UB: + tcg_gen_ld8u_i32(var, cpu_env, offset); + break; + case MO_UW: + tcg_gen_ld16u_i32(var, cpu_env, offset); + break; + case MO_UL: + tcg_gen_ld_i32(var, cpu_env, offset); + break; + default: + g_assert_not_reached(); + } +} + +static void neon_load_element64(TCGv_i64 var, int reg, int ele, MemOp mop) +{ + long offset = neon_element_offset(reg, ele, mop & MO_SIZE); + + switch (mop) { + case MO_UB: + tcg_gen_ld8u_i64(var, cpu_env, offset); + break; + case MO_UW: + tcg_gen_ld16u_i64(var, cpu_env, offset); + break; + case MO_UL: + tcg_gen_ld32u_i64(var, cpu_env, offset); + break; + case MO_Q: + tcg_gen_ld_i64(var, cpu_env, offset); + break; + default: + g_assert_not_reached(); + } +} + +static void neon_store_element(int reg, int ele, MemOp size, TCGv_i32 var) +{ + long offset = neon_element_offset(reg, ele, size); + + switch (size) { + case MO_8: + tcg_gen_st8_i32(var, cpu_env, offset); + break; + case MO_16: + tcg_gen_st16_i32(var, cpu_env, offset); + break; + case MO_32: + tcg_gen_st_i32(var, cpu_env, offset); + break; + default: + g_assert_not_reached(); + } +} + +static void neon_store_element64(int reg, int ele, MemOp size, TCGv_i64 var) +{ + long offset = neon_element_offset(reg, ele, size); + + switch (size) { + case MO_8: + tcg_gen_st8_i64(var, cpu_env, offset); + break; + case MO_16: + tcg_gen_st16_i64(var, cpu_env, offset); + break; + case MO_32: + tcg_gen_st32_i64(var, cpu_env, offset); + break; + case MO_64: + tcg_gen_st_i64(var, cpu_env, offset); + break; + default: + g_assert_not_reached(); + } +} + +static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a) +{ + int opr_sz; + TCGv_ptr fpst; + gen_helper_gvec_3_ptr *fn_gvec_ptr; + + if (!dc_isar_feature(aa32_vcma, s) + || (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s))) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if ((a->vn | a->vm | a->vd) & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + opr_sz = (1 + a->q) * 8; + fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD); + fn_gvec_ptr = (a->size == MO_16) ? + gen_helper_gvec_fcmlah : gen_helper_gvec_fcmlas; + tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd), + vfp_reg_offset(1, a->vn), + vfp_reg_offset(1, a->vm), + fpst, opr_sz, opr_sz, a->rot, + fn_gvec_ptr); + tcg_temp_free_ptr(fpst); + return true; +} + +static bool trans_VCADD(DisasContext *s, arg_VCADD *a) +{ + int opr_sz; + TCGv_ptr fpst; + gen_helper_gvec_3_ptr *fn_gvec_ptr; + + if (!dc_isar_feature(aa32_vcma, s) + || (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s))) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if ((a->vn | a->vm | a->vd) & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + opr_sz = (1 + a->q) * 8; + fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD); + fn_gvec_ptr = (a->size == MO_16) ? + gen_helper_gvec_fcaddh : gen_helper_gvec_fcadds; + tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd), + vfp_reg_offset(1, a->vn), + vfp_reg_offset(1, a->vm), + fpst, opr_sz, opr_sz, a->rot, + fn_gvec_ptr); + tcg_temp_free_ptr(fpst); + return true; +} + +static bool trans_VDOT(DisasContext *s, arg_VDOT *a) +{ + int opr_sz; + gen_helper_gvec_3 *fn_gvec; + + if (!dc_isar_feature(aa32_dp, s)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if ((a->vn | a->vm | a->vd) & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + opr_sz = (1 + a->q) * 8; + fn_gvec = a->u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b; + tcg_gen_gvec_3_ool(vfp_reg_offset(1, a->vd), + vfp_reg_offset(1, a->vn), + vfp_reg_offset(1, a->vm), + opr_sz, opr_sz, 0, fn_gvec); + return true; +} + +static bool trans_VFML(DisasContext *s, arg_VFML *a) +{ + int opr_sz; + + if (!dc_isar_feature(aa32_fhm, s)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + (a->vd & 0x10)) { + return false; + } + + if (a->vd & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + opr_sz = (1 + a->q) * 8; + tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd), + vfp_reg_offset(a->q, a->vn), + vfp_reg_offset(a->q, a->vm), + cpu_env, opr_sz, opr_sz, a->s, /* is_2 == 0 */ + gen_helper_gvec_fmlal_a32); + return true; +} + +static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a) +{ + gen_helper_gvec_3_ptr *fn_gvec_ptr; + int opr_sz; + TCGv_ptr fpst; + + if (!dc_isar_feature(aa32_vcma, s)) { + return false; + } + if (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if ((a->vd | a->vn) & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + fn_gvec_ptr = (a->size == MO_16) ? + gen_helper_gvec_fcmlah_idx : gen_helper_gvec_fcmlas_idx; + opr_sz = (1 + a->q) * 8; + fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD); + tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd), + vfp_reg_offset(1, a->vn), + vfp_reg_offset(1, a->vm), + fpst, opr_sz, opr_sz, + (a->index << 2) | a->rot, fn_gvec_ptr); + tcg_temp_free_ptr(fpst); + return true; +} + +static bool trans_VDOT_scalar(DisasContext *s, arg_VDOT_scalar *a) +{ + gen_helper_gvec_3 *fn_gvec; + int opr_sz; + TCGv_ptr fpst; + + if (!dc_isar_feature(aa32_dp, s)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn) & 0x10)) { + return false; + } + + if ((a->vd | a->vn) & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + fn_gvec = a->u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b; + opr_sz = (1 + a->q) * 8; + fpst = fpstatus_ptr(FPST_STD); + tcg_gen_gvec_3_ool(vfp_reg_offset(1, a->vd), + vfp_reg_offset(1, a->vn), + vfp_reg_offset(1, a->rm), + opr_sz, opr_sz, a->index, fn_gvec); + tcg_temp_free_ptr(fpst); + return true; +} + +static bool trans_VFML_scalar(DisasContext *s, arg_VFML_scalar *a) +{ + int opr_sz; + + if (!dc_isar_feature(aa32_fhm, s)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd & 0x10) || (a->q && (a->vn & 0x10)))) { + return false; + } + + if (a->vd & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + opr_sz = (1 + a->q) * 8; + tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd), + vfp_reg_offset(a->q, a->vn), + vfp_reg_offset(a->q, a->rm), + cpu_env, opr_sz, opr_sz, + (a->index << 2) | a->s, /* is_2 == 0 */ + gen_helper_gvec_fmlal_idx_a32); + return true; +} + +static struct { + int nregs; + int interleave; + int spacing; +} const neon_ls_element_type[11] = { + {1, 4, 1}, + {1, 4, 2}, + {4, 1, 1}, + {2, 2, 2}, + {1, 3, 1}, + {1, 3, 2}, + {3, 1, 1}, + {1, 1, 1}, + {1, 2, 1}, + {1, 2, 2}, + {2, 1, 1} +}; + +static void gen_neon_ldst_base_update(DisasContext *s, int rm, int rn, + int stride) +{ + if (rm != 15) { + TCGv_i32 base; + + base = load_reg(s, rn); + if (rm == 13) { + tcg_gen_addi_i32(base, base, stride); + } else { + TCGv_i32 index; + index = load_reg(s, rm); + tcg_gen_add_i32(base, base, index); + tcg_temp_free_i32(index); + } + store_reg(s, rn, base); + } +} + +static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a) +{ + /* Neon load/store multiple structures */ + int nregs, interleave, spacing, reg, n; + MemOp endian = s->be_data; + int mmu_idx = get_mem_index(s); + int size = a->size; + TCGv_i64 tmp64; + TCGv_i32 addr, tmp; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist */ + if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) { + return false; + } + if (a->itype > 10) { + return false; + } + /* Catch UNDEF cases for bad values of align field */ + switch (a->itype & 0xc) { + case 4: + if (a->align >= 2) { + return false; + } + break; + case 8: + if (a->align == 3) { + return false; + } + break; + default: + break; + } + nregs = neon_ls_element_type[a->itype].nregs; + interleave = neon_ls_element_type[a->itype].interleave; + spacing = neon_ls_element_type[a->itype].spacing; + if (size == 3 && (interleave | spacing) != 1) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + /* For our purposes, bytes are always little-endian. */ + if (size == 0) { + endian = MO_LE; + } + /* + * Consecutive little-endian elements from a single register + * can be promoted to a larger little-endian operation. + */ + if (interleave == 1 && endian == MO_LE) { + size = 3; + } + tmp64 = tcg_temp_new_i64(); + addr = tcg_temp_new_i32(); + tmp = tcg_const_i32(1 << size); + load_reg_var(s, addr, a->rn); + for (reg = 0; reg < nregs; reg++) { + for (n = 0; n < 8 >> size; n++) { + int xs; + for (xs = 0; xs < interleave; xs++) { + int tt = a->vd + reg + spacing * xs; + + if (a->l) { + gen_aa32_ld_i64(s, tmp64, addr, mmu_idx, endian | size); + neon_store_element64(tt, n, size, tmp64); + } else { + neon_load_element64(tmp64, tt, n, size); + gen_aa32_st_i64(s, tmp64, addr, mmu_idx, endian | size); + } + tcg_gen_add_i32(addr, addr, tmp); + } + } + } + tcg_temp_free_i32(addr); + tcg_temp_free_i32(tmp); + tcg_temp_free_i64(tmp64); + + gen_neon_ldst_base_update(s, a->rm, a->rn, nregs * interleave * 8); + return true; +} + +static bool trans_VLD_all_lanes(DisasContext *s, arg_VLD_all_lanes *a) +{ + /* Neon load single structure to all lanes */ + int reg, stride, vec_size; + int vd = a->vd; + int size = a->size; + int nregs = a->n + 1; + TCGv_i32 addr, tmp; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist */ + if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) { + return false; + } + + if (size == 3) { + if (nregs != 4 || a->a == 0) { + return false; + } + /* For VLD4 size == 3 a == 1 means 32 bits at 16 byte alignment */ + size = 2; + } + if (nregs == 1 && a->a == 1 && size == 0) { + return false; + } + if (nregs == 3 && a->a == 1) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + /* + * VLD1 to all lanes: T bit indicates how many Dregs to write. + * VLD2/3/4 to all lanes: T bit indicates register stride. + */ + stride = a->t ? 2 : 1; + vec_size = nregs == 1 ? stride * 8 : 8; + + tmp = tcg_temp_new_i32(); + addr = tcg_temp_new_i32(); + load_reg_var(s, addr, a->rn); + for (reg = 0; reg < nregs; reg++) { + gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), + s->be_data | size); + if ((vd & 1) && vec_size == 16) { + /* + * We cannot write 16 bytes at once because the + * destination is unaligned. + */ + tcg_gen_gvec_dup_i32(size, neon_full_reg_offset(vd), + 8, 8, tmp); + tcg_gen_gvec_mov(0, neon_full_reg_offset(vd + 1), + neon_full_reg_offset(vd), 8, 8); + } else { + tcg_gen_gvec_dup_i32(size, neon_full_reg_offset(vd), + vec_size, vec_size, tmp); + } + tcg_gen_addi_i32(addr, addr, 1 << size); + vd += stride; + } + tcg_temp_free_i32(tmp); + tcg_temp_free_i32(addr); + + gen_neon_ldst_base_update(s, a->rm, a->rn, (1 << size) * nregs); + + return true; +} + +static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a) +{ + /* Neon load/store single structure to one lane */ + int reg; + int nregs = a->n + 1; + int vd = a->vd; + TCGv_i32 addr, tmp; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist */ + if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) { + return false; + } + + /* Catch the UNDEF cases. This is unavoidably a bit messy. */ + switch (nregs) { + case 1: + if (((a->align & (1 << a->size)) != 0) || + (a->size == 2 && ((a->align & 3) == 1 || (a->align & 3) == 2))) { + return false; + } + break; + case 3: + if ((a->align & 1) != 0) { + return false; + } + /* fall through */ + case 2: + if (a->size == 2 && (a->align & 2) != 0) { + return false; + } + break; + case 4: + if ((a->size == 2) && ((a->align & 3) == 3)) { + return false; + } + break; + default: + abort(); + } + if ((vd + a->stride * (nregs - 1)) > 31) { + /* + * Attempts to write off the end of the register file are + * UNPREDICTABLE; we choose to UNDEF because otherwise we would + * access off the end of the array that holds the register data. + */ + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + tmp = tcg_temp_new_i32(); + addr = tcg_temp_new_i32(); + load_reg_var(s, addr, a->rn); + /* + * TODO: if we implemented alignment exceptions, we should check + * addr against the alignment encoded in a->align here. + */ + for (reg = 0; reg < nregs; reg++) { + if (a->l) { + gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), + s->be_data | a->size); + neon_store_element(vd, a->reg_idx, a->size, tmp); + } else { /* Store */ + neon_load_element(tmp, vd, a->reg_idx, a->size); + gen_aa32_st_i32(s, tmp, addr, get_mem_index(s), + s->be_data | a->size); + } + vd += a->stride; + tcg_gen_addi_i32(addr, addr, 1 << a->size); + } + tcg_temp_free_i32(addr); + tcg_temp_free_i32(tmp); + + gen_neon_ldst_base_update(s, a->rm, a->rn, (1 << a->size) * nregs); + + return true; +} + +static bool do_3same(DisasContext *s, arg_3same *a, GVecGen3Fn fn) +{ + int vec_size = a->q ? 16 : 8; + int rd_ofs = neon_full_reg_offset(a->vd); + int rn_ofs = neon_full_reg_offset(a->vn); + int rm_ofs = neon_full_reg_offset(a->vm); + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if ((a->vn | a->vm | a->vd) & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + fn(a->size, rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size); + return true; +} + +#define DO_3SAME(INSN, FUNC) \ + static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ + { \ + return do_3same(s, a, FUNC); \ + } + +DO_3SAME(VADD, tcg_gen_gvec_add) +DO_3SAME(VSUB, tcg_gen_gvec_sub) +DO_3SAME(VAND, tcg_gen_gvec_and) +DO_3SAME(VBIC, tcg_gen_gvec_andc) +DO_3SAME(VORR, tcg_gen_gvec_or) +DO_3SAME(VORN, tcg_gen_gvec_orc) +DO_3SAME(VEOR, tcg_gen_gvec_xor) +DO_3SAME(VSHL_S, gen_gvec_sshl) +DO_3SAME(VSHL_U, gen_gvec_ushl) +DO_3SAME(VQADD_S, gen_gvec_sqadd_qc) +DO_3SAME(VQADD_U, gen_gvec_uqadd_qc) +DO_3SAME(VQSUB_S, gen_gvec_sqsub_qc) +DO_3SAME(VQSUB_U, gen_gvec_uqsub_qc) + +/* These insns are all gvec_bitsel but with the inputs in various orders. */ +#define DO_3SAME_BITSEL(INSN, O1, O2, O3) \ + static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ + uint32_t rn_ofs, uint32_t rm_ofs, \ + uint32_t oprsz, uint32_t maxsz) \ + { \ + tcg_gen_gvec_bitsel(vece, rd_ofs, O1, O2, O3, oprsz, maxsz); \ + } \ + DO_3SAME(INSN, gen_##INSN##_3s) + +DO_3SAME_BITSEL(VBSL, rd_ofs, rn_ofs, rm_ofs) +DO_3SAME_BITSEL(VBIT, rm_ofs, rn_ofs, rd_ofs) +DO_3SAME_BITSEL(VBIF, rm_ofs, rd_ofs, rn_ofs) + +#define DO_3SAME_NO_SZ_3(INSN, FUNC) \ + static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ + { \ + if (a->size == 3) { \ + return false; \ + } \ + return do_3same(s, a, FUNC); \ + } + +DO_3SAME_NO_SZ_3(VMAX_S, tcg_gen_gvec_smax) +DO_3SAME_NO_SZ_3(VMAX_U, tcg_gen_gvec_umax) +DO_3SAME_NO_SZ_3(VMIN_S, tcg_gen_gvec_smin) +DO_3SAME_NO_SZ_3(VMIN_U, tcg_gen_gvec_umin) +DO_3SAME_NO_SZ_3(VMUL, tcg_gen_gvec_mul) +DO_3SAME_NO_SZ_3(VMLA, gen_gvec_mla) +DO_3SAME_NO_SZ_3(VMLS, gen_gvec_mls) +DO_3SAME_NO_SZ_3(VTST, gen_gvec_cmtst) +DO_3SAME_NO_SZ_3(VABD_S, gen_gvec_sabd) +DO_3SAME_NO_SZ_3(VABA_S, gen_gvec_saba) +DO_3SAME_NO_SZ_3(VABD_U, gen_gvec_uabd) +DO_3SAME_NO_SZ_3(VABA_U, gen_gvec_uaba) + +#define DO_3SAME_CMP(INSN, COND) \ + static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ + uint32_t rn_ofs, uint32_t rm_ofs, \ + uint32_t oprsz, uint32_t maxsz) \ + { \ + tcg_gen_gvec_cmp(COND, vece, rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz); \ + } \ + DO_3SAME_NO_SZ_3(INSN, gen_##INSN##_3s) + +DO_3SAME_CMP(VCGT_S, TCG_COND_GT) +DO_3SAME_CMP(VCGT_U, TCG_COND_GTU) +DO_3SAME_CMP(VCGE_S, TCG_COND_GE) +DO_3SAME_CMP(VCGE_U, TCG_COND_GEU) +DO_3SAME_CMP(VCEQ, TCG_COND_EQ) + +#define WRAP_OOL_FN(WRAPNAME, FUNC) \ + static void WRAPNAME(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, \ + uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz) \ + { \ + tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, 0, FUNC); \ + } + +WRAP_OOL_FN(gen_VMUL_p_3s, gen_helper_gvec_pmul_b) + +static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a) +{ + if (a->size != 0) { + return false; + } + return do_3same(s, a, gen_VMUL_p_3s); +} + +#define DO_VQRDMLAH(INSN, FUNC) \ + static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ + { \ + if (!dc_isar_feature(aa32_rdm, s)) { \ + return false; \ + } \ + if (a->size != 1 && a->size != 2) { \ + return false; \ + } \ + return do_3same(s, a, FUNC); \ + } + +DO_VQRDMLAH(VQRDMLAH, gen_gvec_sqrdmlah_qc) +DO_VQRDMLAH(VQRDMLSH, gen_gvec_sqrdmlsh_qc) + +#define DO_SHA1(NAME, FUNC) \ + WRAP_OOL_FN(gen_##NAME##_3s, FUNC) \ + static bool trans_##NAME##_3s(DisasContext *s, arg_3same *a) \ + { \ + if (!dc_isar_feature(aa32_sha1, s)) { \ + return false; \ + } \ + return do_3same(s, a, gen_##NAME##_3s); \ + } + +DO_SHA1(SHA1C, gen_helper_crypto_sha1c) +DO_SHA1(SHA1P, gen_helper_crypto_sha1p) +DO_SHA1(SHA1M, gen_helper_crypto_sha1m) +DO_SHA1(SHA1SU0, gen_helper_crypto_sha1su0) + +#define DO_SHA2(NAME, FUNC) \ + WRAP_OOL_FN(gen_##NAME##_3s, FUNC) \ + static bool trans_##NAME##_3s(DisasContext *s, arg_3same *a) \ + { \ + if (!dc_isar_feature(aa32_sha2, s)) { \ + return false; \ + } \ + return do_3same(s, a, gen_##NAME##_3s); \ + } + +DO_SHA2(SHA256H, gen_helper_crypto_sha256h) +DO_SHA2(SHA256H2, gen_helper_crypto_sha256h2) +DO_SHA2(SHA256SU1, gen_helper_crypto_sha256su1) + +#define DO_3SAME_64(INSN, FUNC) \ + static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ + uint32_t rn_ofs, uint32_t rm_ofs, \ + uint32_t oprsz, uint32_t maxsz) \ + { \ + static const GVecGen3 op = { .fni8 = FUNC }; \ + tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &op); \ + } \ + DO_3SAME(INSN, gen_##INSN##_3s) + +#define DO_3SAME_64_ENV(INSN, FUNC) \ + static void gen_##INSN##_elt(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m) \ + { \ + FUNC(d, cpu_env, n, m); \ + } \ + DO_3SAME_64(INSN, gen_##INSN##_elt) + +DO_3SAME_64(VRSHL_S64, gen_helper_neon_rshl_s64) +DO_3SAME_64(VRSHL_U64, gen_helper_neon_rshl_u64) +DO_3SAME_64_ENV(VQSHL_S64, gen_helper_neon_qshl_s64) +DO_3SAME_64_ENV(VQSHL_U64, gen_helper_neon_qshl_u64) +DO_3SAME_64_ENV(VQRSHL_S64, gen_helper_neon_qrshl_s64) +DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64) + +#define DO_3SAME_32(INSN, FUNC) \ + static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ + uint32_t rn_ofs, uint32_t rm_ofs, \ + uint32_t oprsz, uint32_t maxsz) \ + { \ + static const GVecGen3 ops[4] = { \ + { .fni4 = gen_helper_neon_##FUNC##8 }, \ + { .fni4 = gen_helper_neon_##FUNC##16 }, \ + { .fni4 = gen_helper_neon_##FUNC##32 }, \ + { 0 }, \ + }; \ + tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece]); \ + } \ + static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ + { \ + if (a->size > 2) { \ + return false; \ + } \ + return do_3same(s, a, gen_##INSN##_3s); \ + } + +/* + * Some helper functions need to be passed the cpu_env. In order + * to use those with the gvec APIs like tcg_gen_gvec_3() we need + * to create wrapper functions whose prototype is a NeonGenTwoOpFn() + * and which call a NeonGenTwoOpEnvFn(). + */ +#define WRAP_ENV_FN(WRAPNAME, FUNC) \ + static void WRAPNAME(TCGv_i32 d, TCGv_i32 n, TCGv_i32 m) \ + { \ + FUNC(d, cpu_env, n, m); \ + } + +#define DO_3SAME_32_ENV(INSN, FUNC) \ + WRAP_ENV_FN(gen_##INSN##_tramp8, gen_helper_neon_##FUNC##8); \ + WRAP_ENV_FN(gen_##INSN##_tramp16, gen_helper_neon_##FUNC##16); \ + WRAP_ENV_FN(gen_##INSN##_tramp32, gen_helper_neon_##FUNC##32); \ + static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ + uint32_t rn_ofs, uint32_t rm_ofs, \ + uint32_t oprsz, uint32_t maxsz) \ + { \ + static const GVecGen3 ops[4] = { \ + { .fni4 = gen_##INSN##_tramp8 }, \ + { .fni4 = gen_##INSN##_tramp16 }, \ + { .fni4 = gen_##INSN##_tramp32 }, \ + { 0 }, \ + }; \ + tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece]); \ + } \ + static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ + { \ + if (a->size > 2) { \ + return false; \ + } \ + return do_3same(s, a, gen_##INSN##_3s); \ + } + +DO_3SAME_32(VHADD_S, hadd_s) +DO_3SAME_32(VHADD_U, hadd_u) +DO_3SAME_32(VHSUB_S, hsub_s) +DO_3SAME_32(VHSUB_U, hsub_u) +DO_3SAME_32(VRHADD_S, rhadd_s) +DO_3SAME_32(VRHADD_U, rhadd_u) +DO_3SAME_32(VRSHL_S, rshl_s) +DO_3SAME_32(VRSHL_U, rshl_u) + +DO_3SAME_32_ENV(VQSHL_S, qshl_s) +DO_3SAME_32_ENV(VQSHL_U, qshl_u) +DO_3SAME_32_ENV(VQRSHL_S, qrshl_s) +DO_3SAME_32_ENV(VQRSHL_U, qrshl_u) + +static bool do_3same_pair(DisasContext *s, arg_3same *a, NeonGenTwoOpFn *fn) +{ + /* Operations handled pairwise 32 bits at a time */ + TCGv_i32 tmp, tmp2, tmp3; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if (a->size == 3) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + assert(a->q == 0); /* enforced by decode patterns */ + + /* + * Note that we have to be careful not to clobber the source operands + * in the "vm == vd" case by storing the result of the first pass too + * early. Since Q is 0 there are always just two passes, so instead + * of a complicated loop over each pass we just unroll. + */ + tmp = tcg_temp_new_i32(); + tmp2 = tcg_temp_new_i32(); + tmp3 = tcg_temp_new_i32(); + + read_neon_element32(tmp, a->vn, 0, MO_32); + read_neon_element32(tmp2, a->vn, 1, MO_32); + fn(tmp, tmp, tmp2); + + read_neon_element32(tmp3, a->vm, 0, MO_32); + read_neon_element32(tmp2, a->vm, 1, MO_32); + fn(tmp3, tmp3, tmp2); + + write_neon_element32(tmp, a->vd, 0, MO_32); + write_neon_element32(tmp3, a->vd, 1, MO_32); + + tcg_temp_free_i32(tmp); + tcg_temp_free_i32(tmp2); + tcg_temp_free_i32(tmp3); + return true; +} + +#define DO_3SAME_PAIR(INSN, func) \ + static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ + { \ + static NeonGenTwoOpFn * const fns[] = { \ + gen_helper_neon_##func##8, \ + gen_helper_neon_##func##16, \ + gen_helper_neon_##func##32, \ + }; \ + if (a->size > 2) { \ + return false; \ + } \ + return do_3same_pair(s, a, fns[a->size]); \ + } + +/* 32-bit pairwise ops end up the same as the elementwise versions. */ +#define gen_helper_neon_pmax_s32 tcg_gen_smax_i32 +#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32 +#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32 +#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32 +#define gen_helper_neon_padd_u32 tcg_gen_add_i32 + +DO_3SAME_PAIR(VPMAX_S, pmax_s) +DO_3SAME_PAIR(VPMIN_S, pmin_s) +DO_3SAME_PAIR(VPMAX_U, pmax_u) +DO_3SAME_PAIR(VPMIN_U, pmin_u) +DO_3SAME_PAIR(VPADD, padd_u) + +#define DO_3SAME_VQDMULH(INSN, FUNC) \ + WRAP_ENV_FN(gen_##INSN##_tramp16, gen_helper_neon_##FUNC##_s16); \ + WRAP_ENV_FN(gen_##INSN##_tramp32, gen_helper_neon_##FUNC##_s32); \ + static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ + uint32_t rn_ofs, uint32_t rm_ofs, \ + uint32_t oprsz, uint32_t maxsz) \ + { \ + static const GVecGen3 ops[2] = { \ + { .fni4 = gen_##INSN##_tramp16 }, \ + { .fni4 = gen_##INSN##_tramp32 }, \ + }; \ + tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece - 1]); \ + } \ + static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ + { \ + if (a->size != 1 && a->size != 2) { \ + return false; \ + } \ + return do_3same(s, a, gen_##INSN##_3s); \ + } + +DO_3SAME_VQDMULH(VQDMULH, qdmulh) +DO_3SAME_VQDMULH(VQRDMULH, qrdmulh) + +#define WRAP_FP_GVEC(WRAPNAME, FPST, FUNC) \ + static void WRAPNAME(unsigned vece, uint32_t rd_ofs, \ + uint32_t rn_ofs, uint32_t rm_ofs, \ + uint32_t oprsz, uint32_t maxsz) \ + { \ + TCGv_ptr fpst = fpstatus_ptr(FPST); \ + tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, fpst, \ + oprsz, maxsz, 0, FUNC); \ + tcg_temp_free_ptr(fpst); \ + } + +#define DO_3S_FP_GVEC(INSN,SFUNC,HFUNC) \ + WRAP_FP_GVEC(gen_##INSN##_fp32_3s, FPST_STD, SFUNC) \ + WRAP_FP_GVEC(gen_##INSN##_fp16_3s, FPST_STD_F16, HFUNC) \ + static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \ + { \ + if (a->size == MO_16) { \ + if (!dc_isar_feature(aa32_fp16_arith, s)) { \ + return false; \ + } \ + return do_3same(s, a, gen_##INSN##_fp16_3s); \ + } \ + return do_3same(s, a, gen_##INSN##_fp32_3s); \ + } + + +DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s, gen_helper_gvec_fadd_h) +DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s, gen_helper_gvec_fsub_h) +DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s, gen_helper_gvec_fabd_h) +DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s, gen_helper_gvec_fmul_h) +DO_3S_FP_GVEC(VCEQ, gen_helper_gvec_fceq_s, gen_helper_gvec_fceq_h) +DO_3S_FP_GVEC(VCGE, gen_helper_gvec_fcge_s, gen_helper_gvec_fcge_h) +DO_3S_FP_GVEC(VCGT, gen_helper_gvec_fcgt_s, gen_helper_gvec_fcgt_h) +DO_3S_FP_GVEC(VACGE, gen_helper_gvec_facge_s, gen_helper_gvec_facge_h) +DO_3S_FP_GVEC(VACGT, gen_helper_gvec_facgt_s, gen_helper_gvec_facgt_h) +DO_3S_FP_GVEC(VMAX, gen_helper_gvec_fmax_s, gen_helper_gvec_fmax_h) +DO_3S_FP_GVEC(VMIN, gen_helper_gvec_fmin_s, gen_helper_gvec_fmin_h) +DO_3S_FP_GVEC(VMLA, gen_helper_gvec_fmla_s, gen_helper_gvec_fmla_h) +DO_3S_FP_GVEC(VMLS, gen_helper_gvec_fmls_s, gen_helper_gvec_fmls_h) +DO_3S_FP_GVEC(VFMA, gen_helper_gvec_vfma_s, gen_helper_gvec_vfma_h) +DO_3S_FP_GVEC(VFMS, gen_helper_gvec_vfms_s, gen_helper_gvec_vfms_h) +DO_3S_FP_GVEC(VRECPS, gen_helper_gvec_recps_nf_s, gen_helper_gvec_recps_nf_h) +DO_3S_FP_GVEC(VRSQRTS, gen_helper_gvec_rsqrts_nf_s, gen_helper_gvec_rsqrts_nf_h) + +WRAP_FP_GVEC(gen_VMAXNM_fp32_3s, FPST_STD, gen_helper_gvec_fmaxnum_s) +WRAP_FP_GVEC(gen_VMAXNM_fp16_3s, FPST_STD_F16, gen_helper_gvec_fmaxnum_h) +WRAP_FP_GVEC(gen_VMINNM_fp32_3s, FPST_STD, gen_helper_gvec_fminnum_s) +WRAP_FP_GVEC(gen_VMINNM_fp16_3s, FPST_STD_F16, gen_helper_gvec_fminnum_h) + +static bool trans_VMAXNM_fp_3s(DisasContext *s, arg_3same *a) +{ + if (!arm_dc_feature(s, ARM_FEATURE_V8)) { + return false; + } + + if (a->size == MO_16) { + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + return do_3same(s, a, gen_VMAXNM_fp16_3s); + } + return do_3same(s, a, gen_VMAXNM_fp32_3s); +} + +static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a) +{ + if (!arm_dc_feature(s, ARM_FEATURE_V8)) { + return false; + } + + if (a->size == MO_16) { + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + return do_3same(s, a, gen_VMINNM_fp16_3s); + } + return do_3same(s, a, gen_VMINNM_fp32_3s); +} + +static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, + gen_helper_gvec_3_ptr *fn) +{ + /* FP pairwise operations */ + TCGv_ptr fpstatus; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + assert(a->q == 0); /* enforced by decode patterns */ + + + fpstatus = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD); + tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd), + vfp_reg_offset(1, a->vn), + vfp_reg_offset(1, a->vm), + fpstatus, 8, 8, 0, fn); + tcg_temp_free_ptr(fpstatus); + + return true; +} + +/* + * For all the functions using this macro, size == 1 means fp16, + * which is an architecture extension we don't implement yet. + */ +#define DO_3S_FP_PAIR(INSN,FUNC) \ + static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \ + { \ + if (a->size == MO_16) { \ + if (!dc_isar_feature(aa32_fp16_arith, s)) { \ + return false; \ + } \ + return do_3same_fp_pair(s, a, FUNC##h); \ + } \ + return do_3same_fp_pair(s, a, FUNC##s); \ + } + +DO_3S_FP_PAIR(VPADD, gen_helper_neon_padd) +DO_3S_FP_PAIR(VPMAX, gen_helper_neon_pmax) +DO_3S_FP_PAIR(VPMIN, gen_helper_neon_pmin) + +static bool do_vector_2sh(DisasContext *s, arg_2reg_shift *a, GVecGen2iFn *fn) +{ + /* Handle a 2-reg-shift insn which can be vectorized. */ + int vec_size = a->q ? 16 : 8; + int rd_ofs = neon_full_reg_offset(a->vd); + int rm_ofs = neon_full_reg_offset(a->vm); + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if ((a->vm | a->vd) & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + fn(a->size, rd_ofs, rm_ofs, a->shift, vec_size, vec_size); + return true; +} + +#define DO_2SH(INSN, FUNC) \ + static bool trans_##INSN##_2sh(DisasContext *s, arg_2reg_shift *a) \ + { \ + return do_vector_2sh(s, a, FUNC); \ + } \ + +DO_2SH(VSHL, tcg_gen_gvec_shli) +DO_2SH(VSLI, gen_gvec_sli) +DO_2SH(VSRI, gen_gvec_sri) +DO_2SH(VSRA_S, gen_gvec_ssra) +DO_2SH(VSRA_U, gen_gvec_usra) +DO_2SH(VRSHR_S, gen_gvec_srshr) +DO_2SH(VRSHR_U, gen_gvec_urshr) +DO_2SH(VRSRA_S, gen_gvec_srsra) +DO_2SH(VRSRA_U, gen_gvec_ursra) + +static bool trans_VSHR_S_2sh(DisasContext *s, arg_2reg_shift *a) +{ + /* Signed shift out of range results in all-sign-bits */ + a->shift = MIN(a->shift, (8 << a->size) - 1); + return do_vector_2sh(s, a, tcg_gen_gvec_sari); +} + +static void gen_zero_rd_2sh(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, + int64_t shift, uint32_t oprsz, uint32_t maxsz) +{ + tcg_gen_gvec_dup_imm(vece, rd_ofs, oprsz, maxsz, 0); +} + +static bool trans_VSHR_U_2sh(DisasContext *s, arg_2reg_shift *a) +{ + /* Shift out of range is architecturally valid and results in zero. */ + if (a->shift >= (8 << a->size)) { + return do_vector_2sh(s, a, gen_zero_rd_2sh); + } else { + return do_vector_2sh(s, a, tcg_gen_gvec_shri); + } +} + +static bool do_2shift_env_64(DisasContext *s, arg_2reg_shift *a, + NeonGenTwo64OpEnvFn *fn) +{ + /* + * 2-reg-and-shift operations, size == 3 case, where the + * function needs to be passed cpu_env. + */ + TCGv_i64 constimm; + int pass; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if ((a->vm | a->vd) & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + /* + * To avoid excessive duplication of ops we implement shift + * by immediate using the variable shift operations. + */ + constimm = tcg_const_i64(dup_const(a->size, a->shift)); + + for (pass = 0; pass < a->q + 1; pass++) { + TCGv_i64 tmp = tcg_temp_new_i64(); + + read_neon_element64(tmp, a->vm, pass, MO_64); + fn(tmp, cpu_env, tmp, constimm); + write_neon_element64(tmp, a->vd, pass, MO_64); + tcg_temp_free_i64(tmp); + } + tcg_temp_free_i64(constimm); + return true; +} + +static bool do_2shift_env_32(DisasContext *s, arg_2reg_shift *a, + NeonGenTwoOpEnvFn *fn) +{ + /* + * 2-reg-and-shift operations, size < 3 case, where the + * helper needs to be passed cpu_env. + */ + TCGv_i32 constimm, tmp; + int pass; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if ((a->vm | a->vd) & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + /* + * To avoid excessive duplication of ops we implement shift + * by immediate using the variable shift operations. + */ + constimm = tcg_const_i32(dup_const(a->size, a->shift)); + tmp = tcg_temp_new_i32(); + + for (pass = 0; pass < (a->q ? 4 : 2); pass++) { + read_neon_element32(tmp, a->vm, pass, MO_32); + fn(tmp, cpu_env, tmp, constimm); + write_neon_element32(tmp, a->vd, pass, MO_32); + } + tcg_temp_free_i32(tmp); + tcg_temp_free_i32(constimm); + return true; +} + +#define DO_2SHIFT_ENV(INSN, FUNC) \ + static bool trans_##INSN##_64_2sh(DisasContext *s, arg_2reg_shift *a) \ + { \ + return do_2shift_env_64(s, a, gen_helper_neon_##FUNC##64); \ + } \ + static bool trans_##INSN##_2sh(DisasContext *s, arg_2reg_shift *a) \ + { \ + static NeonGenTwoOpEnvFn * const fns[] = { \ + gen_helper_neon_##FUNC##8, \ + gen_helper_neon_##FUNC##16, \ + gen_helper_neon_##FUNC##32, \ + }; \ + assert(a->size < ARRAY_SIZE(fns)); \ + return do_2shift_env_32(s, a, fns[a->size]); \ + } + +DO_2SHIFT_ENV(VQSHLU, qshlu_s) +DO_2SHIFT_ENV(VQSHL_U, qshl_u) +DO_2SHIFT_ENV(VQSHL_S, qshl_s) + +static bool do_2shift_narrow_64(DisasContext *s, arg_2reg_shift *a, + NeonGenTwo64OpFn *shiftfn, + NeonGenNarrowEnvFn *narrowfn) +{ + /* 2-reg-and-shift narrowing-shift operations, size == 3 case */ + TCGv_i64 constimm, rm1, rm2; + TCGv_i32 rd; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if (a->vm & 1) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + /* + * This is always a right shift, and the shiftfn is always a + * left-shift helper, which thus needs the negated shift count. + */ + constimm = tcg_const_i64(-a->shift); + rm1 = tcg_temp_new_i64(); + rm2 = tcg_temp_new_i64(); + rd = tcg_temp_new_i32(); + + /* Load both inputs first to avoid potential overwrite if rm == rd */ + read_neon_element64(rm1, a->vm, 0, MO_64); + read_neon_element64(rm2, a->vm, 1, MO_64); + + shiftfn(rm1, rm1, constimm); + narrowfn(rd, cpu_env, rm1); + write_neon_element32(rd, a->vd, 0, MO_32); + + shiftfn(rm2, rm2, constimm); + narrowfn(rd, cpu_env, rm2); + write_neon_element32(rd, a->vd, 1, MO_32); + + tcg_temp_free_i32(rd); + tcg_temp_free_i64(rm1); + tcg_temp_free_i64(rm2); + tcg_temp_free_i64(constimm); + + return true; +} + +static bool do_2shift_narrow_32(DisasContext *s, arg_2reg_shift *a, + NeonGenTwoOpFn *shiftfn, + NeonGenNarrowEnvFn *narrowfn) +{ + /* 2-reg-and-shift narrowing-shift operations, size < 3 case */ + TCGv_i32 constimm, rm1, rm2, rm3, rm4; + TCGv_i64 rtmp; + uint32_t imm; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if (a->vm & 1) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + /* + * This is always a right shift, and the shiftfn is always a + * left-shift helper, which thus needs the negated shift count + * duplicated into each lane of the immediate value. + */ + if (a->size == 1) { + imm = (uint16_t)(-a->shift); + imm |= imm << 16; + } else { + /* size == 2 */ + imm = -a->shift; + } + constimm = tcg_const_i32(imm); + + /* Load all inputs first to avoid potential overwrite */ + rm1 = tcg_temp_new_i32(); + rm2 = tcg_temp_new_i32(); + rm3 = tcg_temp_new_i32(); + rm4 = tcg_temp_new_i32(); + read_neon_element32(rm1, a->vm, 0, MO_32); + read_neon_element32(rm2, a->vm, 1, MO_32); + read_neon_element32(rm3, a->vm, 2, MO_32); + read_neon_element32(rm4, a->vm, 3, MO_32); + rtmp = tcg_temp_new_i64(); + + shiftfn(rm1, rm1, constimm); + shiftfn(rm2, rm2, constimm); + + tcg_gen_concat_i32_i64(rtmp, rm1, rm2); + tcg_temp_free_i32(rm2); + + narrowfn(rm1, cpu_env, rtmp); + write_neon_element32(rm1, a->vd, 0, MO_32); + tcg_temp_free_i32(rm1); + + shiftfn(rm3, rm3, constimm); + shiftfn(rm4, rm4, constimm); + tcg_temp_free_i32(constimm); + + tcg_gen_concat_i32_i64(rtmp, rm3, rm4); + tcg_temp_free_i32(rm4); + + narrowfn(rm3, cpu_env, rtmp); + tcg_temp_free_i64(rtmp); + write_neon_element32(rm3, a->vd, 1, MO_32); + tcg_temp_free_i32(rm3); + return true; +} + +#define DO_2SN_64(INSN, FUNC, NARROWFUNC) \ + static bool trans_##INSN##_2sh(DisasContext *s, arg_2reg_shift *a) \ + { \ + return do_2shift_narrow_64(s, a, FUNC, NARROWFUNC); \ + } +#define DO_2SN_32(INSN, FUNC, NARROWFUNC) \ + static bool trans_##INSN##_2sh(DisasContext *s, arg_2reg_shift *a) \ + { \ + return do_2shift_narrow_32(s, a, FUNC, NARROWFUNC); \ + } + +static void gen_neon_narrow_u32(TCGv_i32 dest, TCGv_ptr env, TCGv_i64 src) +{ + tcg_gen_extrl_i64_i32(dest, src); +} + +static void gen_neon_narrow_u16(TCGv_i32 dest, TCGv_ptr env, TCGv_i64 src) +{ + gen_helper_neon_narrow_u16(dest, src); +} + +static void gen_neon_narrow_u8(TCGv_i32 dest, TCGv_ptr env, TCGv_i64 src) +{ + gen_helper_neon_narrow_u8(dest, src); +} + +DO_2SN_64(VSHRN_64, gen_ushl_i64, gen_neon_narrow_u32) +DO_2SN_32(VSHRN_32, gen_ushl_i32, gen_neon_narrow_u16) +DO_2SN_32(VSHRN_16, gen_helper_neon_shl_u16, gen_neon_narrow_u8) + +DO_2SN_64(VRSHRN_64, gen_helper_neon_rshl_u64, gen_neon_narrow_u32) +DO_2SN_32(VRSHRN_32, gen_helper_neon_rshl_u32, gen_neon_narrow_u16) +DO_2SN_32(VRSHRN_16, gen_helper_neon_rshl_u16, gen_neon_narrow_u8) + +DO_2SN_64(VQSHRUN_64, gen_sshl_i64, gen_helper_neon_unarrow_sat32) +DO_2SN_32(VQSHRUN_32, gen_sshl_i32, gen_helper_neon_unarrow_sat16) +DO_2SN_32(VQSHRUN_16, gen_helper_neon_shl_s16, gen_helper_neon_unarrow_sat8) + +DO_2SN_64(VQRSHRUN_64, gen_helper_neon_rshl_s64, gen_helper_neon_unarrow_sat32) +DO_2SN_32(VQRSHRUN_32, gen_helper_neon_rshl_s32, gen_helper_neon_unarrow_sat16) +DO_2SN_32(VQRSHRUN_16, gen_helper_neon_rshl_s16, gen_helper_neon_unarrow_sat8) +DO_2SN_64(VQSHRN_S64, gen_sshl_i64, gen_helper_neon_narrow_sat_s32) +DO_2SN_32(VQSHRN_S32, gen_sshl_i32, gen_helper_neon_narrow_sat_s16) +DO_2SN_32(VQSHRN_S16, gen_helper_neon_shl_s16, gen_helper_neon_narrow_sat_s8) + +DO_2SN_64(VQRSHRN_S64, gen_helper_neon_rshl_s64, gen_helper_neon_narrow_sat_s32) +DO_2SN_32(VQRSHRN_S32, gen_helper_neon_rshl_s32, gen_helper_neon_narrow_sat_s16) +DO_2SN_32(VQRSHRN_S16, gen_helper_neon_rshl_s16, gen_helper_neon_narrow_sat_s8) + +DO_2SN_64(VQSHRN_U64, gen_ushl_i64, gen_helper_neon_narrow_sat_u32) +DO_2SN_32(VQSHRN_U32, gen_ushl_i32, gen_helper_neon_narrow_sat_u16) +DO_2SN_32(VQSHRN_U16, gen_helper_neon_shl_u16, gen_helper_neon_narrow_sat_u8) + +DO_2SN_64(VQRSHRN_U64, gen_helper_neon_rshl_u64, gen_helper_neon_narrow_sat_u32) +DO_2SN_32(VQRSHRN_U32, gen_helper_neon_rshl_u32, gen_helper_neon_narrow_sat_u16) +DO_2SN_32(VQRSHRN_U16, gen_helper_neon_rshl_u16, gen_helper_neon_narrow_sat_u8) + +static bool do_vshll_2sh(DisasContext *s, arg_2reg_shift *a, + NeonGenWidenFn *widenfn, bool u) +{ + TCGv_i64 tmp; + TCGv_i32 rm0, rm1; + uint64_t widen_mask = 0; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if (a->vd & 1) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + /* + * This is a widen-and-shift operation. The shift is always less + * than the width of the source type, so after widening the input + * vector we can simply shift the whole 64-bit widened register, + * and then clear the potential overflow bits resulting from left + * bits of the narrow input appearing as right bits of the left + * neighbour narrow input. Calculate a mask of bits to clear. + */ + if ((a->shift != 0) && (a->size < 2 || u)) { + int esize = 8 << a->size; + widen_mask = MAKE_64BIT_MASK(0, esize); + widen_mask >>= esize - a->shift; + widen_mask = dup_const(a->size + 1, widen_mask); + } + + rm0 = tcg_temp_new_i32(); + rm1 = tcg_temp_new_i32(); + read_neon_element32(rm0, a->vm, 0, MO_32); + read_neon_element32(rm1, a->vm, 1, MO_32); + tmp = tcg_temp_new_i64(); + + widenfn(tmp, rm0); + tcg_temp_free_i32(rm0); + if (a->shift != 0) { + tcg_gen_shli_i64(tmp, tmp, a->shift); + tcg_gen_andi_i64(tmp, tmp, ~widen_mask); + } + write_neon_element64(tmp, a->vd, 0, MO_64); + + widenfn(tmp, rm1); + tcg_temp_free_i32(rm1); + if (a->shift != 0) { + tcg_gen_shli_i64(tmp, tmp, a->shift); + tcg_gen_andi_i64(tmp, tmp, ~widen_mask); + } + write_neon_element64(tmp, a->vd, 1, MO_64); + tcg_temp_free_i64(tmp); + return true; +} + +static bool trans_VSHLL_S_2sh(DisasContext *s, arg_2reg_shift *a) +{ + static NeonGenWidenFn * const widenfn[] = { + gen_helper_neon_widen_s8, + gen_helper_neon_widen_s16, + tcg_gen_ext_i32_i64, + }; + return do_vshll_2sh(s, a, widenfn[a->size], false); +} + +static bool trans_VSHLL_U_2sh(DisasContext *s, arg_2reg_shift *a) +{ + static NeonGenWidenFn * const widenfn[] = { + gen_helper_neon_widen_u8, + gen_helper_neon_widen_u16, + tcg_gen_extu_i32_i64, + }; + return do_vshll_2sh(s, a, widenfn[a->size], true); +} + +static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a, + gen_helper_gvec_2_ptr *fn) +{ + /* FP operations in 2-reg-and-shift group */ + int vec_size = a->q ? 16 : 8; + int rd_ofs = neon_full_reg_offset(a->vd); + int rm_ofs = neon_full_reg_offset(a->vm); + TCGv_ptr fpst; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + if (a->size == MO_16) { + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if ((a->vm | a->vd) & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD); + tcg_gen_gvec_2_ptr(rd_ofs, rm_ofs, fpst, vec_size, vec_size, a->shift, fn); + tcg_temp_free_ptr(fpst); + return true; +} + +#define DO_FP_2SH(INSN, FUNC) \ + static bool trans_##INSN##_2sh(DisasContext *s, arg_2reg_shift *a) \ + { \ + return do_fp_2sh(s, a, FUNC); \ + } + +DO_FP_2SH(VCVT_SF, gen_helper_gvec_vcvt_sf) +DO_FP_2SH(VCVT_UF, gen_helper_gvec_vcvt_uf) +DO_FP_2SH(VCVT_FS, gen_helper_gvec_vcvt_fs) +DO_FP_2SH(VCVT_FU, gen_helper_gvec_vcvt_fu) + +DO_FP_2SH(VCVT_SH, gen_helper_gvec_vcvt_sh) +DO_FP_2SH(VCVT_UH, gen_helper_gvec_vcvt_uh) +DO_FP_2SH(VCVT_HS, gen_helper_gvec_vcvt_hs) +DO_FP_2SH(VCVT_HU, gen_helper_gvec_vcvt_hu) + +static uint64_t asimd_imm_const(uint32_t imm, int cmode, int op) +{ + /* + * Expand the encoded constant. + * Note that cmode = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE. + * We choose to not special-case this and will behave as if a + * valid constant encoding of 0 had been given. + * cmode = 15 op = 1 must UNDEF; we assume decode has handled that. + */ + switch (cmode) { + case 0: case 1: + /* no-op */ + break; + case 2: case 3: + imm <<= 8; + break; + case 4: case 5: + imm <<= 16; + break; + case 6: case 7: + imm <<= 24; + break; + case 8: case 9: + imm |= imm << 16; + break; + case 10: case 11: + imm = (imm << 8) | (imm << 24); + break; + case 12: + imm = (imm << 8) | 0xff; + break; + case 13: + imm = (imm << 16) | 0xffff; + break; + case 14: + if (op) { + /* + * This is the only case where the top and bottom 32 bits + * of the encoded constant differ. + */ + uint64_t imm64 = 0; + int n; + + for (n = 0; n < 8; n++) { + if (imm & (1 << n)) { + imm64 |= (0xffULL << (n * 8)); + } + } + return imm64; + } + imm |= (imm << 8) | (imm << 16) | (imm << 24); + break; + case 15: + imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19) + | ((imm & 0x40) ? (0x1f << 25) : (1 << 30)); + break; + } + if (op) { + imm = ~imm; + } + return dup_const(MO_32, imm); +} + +static bool do_1reg_imm(DisasContext *s, arg_1reg_imm *a, + GVecGen2iFn *fn) +{ + uint64_t imm; + int reg_ofs, vec_size; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) { + return false; + } + + if (a->vd & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + reg_ofs = neon_full_reg_offset(a->vd); + vec_size = a->q ? 16 : 8; + imm = asimd_imm_const(a->imm, a->cmode, a->op); + + fn(MO_64, reg_ofs, reg_ofs, imm, vec_size, vec_size); + return true; +} + +static void gen_VMOV_1r(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t c, uint32_t oprsz, uint32_t maxsz) +{ + tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, c); +} + +static bool trans_Vimm_1r(DisasContext *s, arg_1reg_imm *a) +{ + /* Handle decode of cmode/op here between VORR/VBIC/VMOV */ + GVecGen2iFn *fn; + + if ((a->cmode & 1) && a->cmode < 12) { + /* for op=1, the imm will be inverted, so BIC becomes AND. */ + fn = a->op ? tcg_gen_gvec_andi : tcg_gen_gvec_ori; + } else { + /* There is one unallocated cmode/op combination in this space */ + if (a->cmode == 15 && a->op == 1) { + return false; + } + fn = gen_VMOV_1r; + } + return do_1reg_imm(s, a, fn); +} + +static bool do_prewiden_3d(DisasContext *s, arg_3diff *a, + NeonGenWidenFn *widenfn, + NeonGenTwo64OpFn *opfn, + int src1_mop, int src2_mop) +{ + /* 3-regs different lengths, prewidening case (VADDL/VSUBL/VAADW/VSUBW) */ + TCGv_i64 rn0_64, rn1_64, rm_64; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if (!opfn) { + /* size == 3 case, which is an entirely different insn group */ + return false; + } + + if ((a->vd & 1) || (src1_mop == MO_Q && (a->vn & 1))) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + rn0_64 = tcg_temp_new_i64(); + rn1_64 = tcg_temp_new_i64(); + rm_64 = tcg_temp_new_i64(); + + if (src1_mop >= 0) { + read_neon_element64(rn0_64, a->vn, 0, src1_mop); + } else { + TCGv_i32 tmp = tcg_temp_new_i32(); + read_neon_element32(tmp, a->vn, 0, MO_32); + widenfn(rn0_64, tmp); + tcg_temp_free_i32(tmp); + } + if (src2_mop >= 0) { + read_neon_element64(rm_64, a->vm, 0, src2_mop); + } else { + TCGv_i32 tmp = tcg_temp_new_i32(); + read_neon_element32(tmp, a->vm, 0, MO_32); + widenfn(rm_64, tmp); + tcg_temp_free_i32(tmp); + } + + opfn(rn0_64, rn0_64, rm_64); + + /* + * Load second pass inputs before storing the first pass result, to + * avoid incorrect results if a narrow input overlaps with the result. + */ + if (src1_mop >= 0) { + read_neon_element64(rn1_64, a->vn, 1, src1_mop); + } else { + TCGv_i32 tmp = tcg_temp_new_i32(); + read_neon_element32(tmp, a->vn, 1, MO_32); + widenfn(rn1_64, tmp); + tcg_temp_free_i32(tmp); + } + if (src2_mop >= 0) { + read_neon_element64(rm_64, a->vm, 1, src2_mop); + } else { + TCGv_i32 tmp = tcg_temp_new_i32(); + read_neon_element32(tmp, a->vm, 1, MO_32); + widenfn(rm_64, tmp); + tcg_temp_free_i32(tmp); + } + + write_neon_element64(rn0_64, a->vd, 0, MO_64); + + opfn(rn1_64, rn1_64, rm_64); + write_neon_element64(rn1_64, a->vd, 1, MO_64); + + tcg_temp_free_i64(rn0_64); + tcg_temp_free_i64(rn1_64); + tcg_temp_free_i64(rm_64); + + return true; +} + +#define DO_PREWIDEN(INSN, S, OP, SRC1WIDE, SIGN) \ + static bool trans_##INSN##_3d(DisasContext *s, arg_3diff *a) \ + { \ + static NeonGenWidenFn * const widenfn[] = { \ + gen_helper_neon_widen_##S##8, \ + gen_helper_neon_widen_##S##16, \ + NULL, NULL, \ + }; \ + static NeonGenTwo64OpFn * const addfn[] = { \ + gen_helper_neon_##OP##l_u16, \ + gen_helper_neon_##OP##l_u32, \ + tcg_gen_##OP##_i64, \ + NULL, \ + }; \ + int narrow_mop = a->size == MO_32 ? MO_32 | SIGN : -1; \ + return do_prewiden_3d(s, a, widenfn[a->size], addfn[a->size], \ + SRC1WIDE ? MO_Q : narrow_mop, \ + narrow_mop); \ + } + +DO_PREWIDEN(VADDL_S, s, add, false, MO_SIGN) +DO_PREWIDEN(VADDL_U, u, add, false, 0) +DO_PREWIDEN(VSUBL_S, s, sub, false, MO_SIGN) +DO_PREWIDEN(VSUBL_U, u, sub, false, 0) +DO_PREWIDEN(VADDW_S, s, add, true, MO_SIGN) +DO_PREWIDEN(VADDW_U, u, add, true, 0) +DO_PREWIDEN(VSUBW_S, s, sub, true, MO_SIGN) +DO_PREWIDEN(VSUBW_U, u, sub, true, 0) + +static bool do_narrow_3d(DisasContext *s, arg_3diff *a, + NeonGenTwo64OpFn *opfn, NeonGenNarrowFn *narrowfn) +{ + /* 3-regs different lengths, narrowing (VADDHN/VSUBHN/VRADDHN/VRSUBHN) */ + TCGv_i64 rn_64, rm_64; + TCGv_i32 rd0, rd1; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if (!opfn || !narrowfn) { + /* size == 3 case, which is an entirely different insn group */ + return false; + } + + if ((a->vn | a->vm) & 1) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + rn_64 = tcg_temp_new_i64(); + rm_64 = tcg_temp_new_i64(); + rd0 = tcg_temp_new_i32(); + rd1 = tcg_temp_new_i32(); + + read_neon_element64(rn_64, a->vn, 0, MO_64); + read_neon_element64(rm_64, a->vm, 0, MO_64); + + opfn(rn_64, rn_64, rm_64); + + narrowfn(rd0, rn_64); + + read_neon_element64(rn_64, a->vn, 1, MO_64); + read_neon_element64(rm_64, a->vm, 1, MO_64); + + opfn(rn_64, rn_64, rm_64); + + narrowfn(rd1, rn_64); + + write_neon_element32(rd0, a->vd, 0, MO_32); + write_neon_element32(rd1, a->vd, 1, MO_32); + + tcg_temp_free_i32(rd0); + tcg_temp_free_i32(rd1); + tcg_temp_free_i64(rn_64); + tcg_temp_free_i64(rm_64); + + return true; +} + +#define DO_NARROW_3D(INSN, OP, NARROWTYPE, EXTOP) \ + static bool trans_##INSN##_3d(DisasContext *s, arg_3diff *a) \ + { \ + static NeonGenTwo64OpFn * const addfn[] = { \ + gen_helper_neon_##OP##l_u16, \ + gen_helper_neon_##OP##l_u32, \ + tcg_gen_##OP##_i64, \ + NULL, \ + }; \ + static NeonGenNarrowFn * const narrowfn[] = { \ + gen_helper_neon_##NARROWTYPE##_high_u8, \ + gen_helper_neon_##NARROWTYPE##_high_u16, \ + EXTOP, \ + NULL, \ + }; \ + return do_narrow_3d(s, a, addfn[a->size], narrowfn[a->size]); \ + } + +static void gen_narrow_round_high_u32(TCGv_i32 rd, TCGv_i64 rn) +{ + tcg_gen_addi_i64(rn, rn, 1u << 31); + tcg_gen_extrh_i64_i32(rd, rn); +} + +DO_NARROW_3D(VADDHN, add, narrow, tcg_gen_extrh_i64_i32) +DO_NARROW_3D(VSUBHN, sub, narrow, tcg_gen_extrh_i64_i32) +DO_NARROW_3D(VRADDHN, add, narrow_round, gen_narrow_round_high_u32) +DO_NARROW_3D(VRSUBHN, sub, narrow_round, gen_narrow_round_high_u32) + +static bool do_long_3d(DisasContext *s, arg_3diff *a, + NeonGenTwoOpWidenFn *opfn, + NeonGenTwo64OpFn *accfn) +{ + /* + * 3-regs different lengths, long operations. + * These perform an operation on two inputs that returns a double-width + * result, and then possibly perform an accumulation operation of + * that result into the double-width destination. + */ + TCGv_i64 rd0, rd1, tmp; + TCGv_i32 rn, rm; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if (!opfn) { + /* size == 3 case, which is an entirely different insn group */ + return false; + } + + if (a->vd & 1) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + rd0 = tcg_temp_new_i64(); + rd1 = tcg_temp_new_i64(); + + rn = tcg_temp_new_i32(); + rm = tcg_temp_new_i32(); + read_neon_element32(rn, a->vn, 0, MO_32); + read_neon_element32(rm, a->vm, 0, MO_32); + opfn(rd0, rn, rm); + + read_neon_element32(rn, a->vn, 1, MO_32); + read_neon_element32(rm, a->vm, 1, MO_32); + opfn(rd1, rn, rm); + tcg_temp_free_i32(rn); + tcg_temp_free_i32(rm); + + /* Don't store results until after all loads: they might overlap */ + if (accfn) { + tmp = tcg_temp_new_i64(); + read_neon_element64(tmp, a->vd, 0, MO_64); + accfn(rd0, tmp, rd0); + read_neon_element64(tmp, a->vd, 1, MO_64); + accfn(rd1, tmp, rd1); + tcg_temp_free_i64(tmp); + } + + write_neon_element64(rd0, a->vd, 0, MO_64); + write_neon_element64(rd1, a->vd, 1, MO_64); + tcg_temp_free_i64(rd0); + tcg_temp_free_i64(rd1); + + return true; +} + +static bool trans_VABDL_S_3d(DisasContext *s, arg_3diff *a) +{ + static NeonGenTwoOpWidenFn * const opfn[] = { + gen_helper_neon_abdl_s16, + gen_helper_neon_abdl_s32, + gen_helper_neon_abdl_s64, + NULL, + }; + + return do_long_3d(s, a, opfn[a->size], NULL); +} + +static bool trans_VABDL_U_3d(DisasContext *s, arg_3diff *a) +{ + static NeonGenTwoOpWidenFn * const opfn[] = { + gen_helper_neon_abdl_u16, + gen_helper_neon_abdl_u32, + gen_helper_neon_abdl_u64, + NULL, + }; + + return do_long_3d(s, a, opfn[a->size], NULL); +} + +static bool trans_VABAL_S_3d(DisasContext *s, arg_3diff *a) +{ + static NeonGenTwoOpWidenFn * const opfn[] = { + gen_helper_neon_abdl_s16, + gen_helper_neon_abdl_s32, + gen_helper_neon_abdl_s64, + NULL, + }; + static NeonGenTwo64OpFn * const addfn[] = { + gen_helper_neon_addl_u16, + gen_helper_neon_addl_u32, + tcg_gen_add_i64, + NULL, + }; + + return do_long_3d(s, a, opfn[a->size], addfn[a->size]); +} + +static bool trans_VABAL_U_3d(DisasContext *s, arg_3diff *a) +{ + static NeonGenTwoOpWidenFn * const opfn[] = { + gen_helper_neon_abdl_u16, + gen_helper_neon_abdl_u32, + gen_helper_neon_abdl_u64, + NULL, + }; + static NeonGenTwo64OpFn * const addfn[] = { + gen_helper_neon_addl_u16, + gen_helper_neon_addl_u32, + tcg_gen_add_i64, + NULL, + }; + + return do_long_3d(s, a, opfn[a->size], addfn[a->size]); +} + +static void gen_mull_s32(TCGv_i64 rd, TCGv_i32 rn, TCGv_i32 rm) +{ + TCGv_i32 lo = tcg_temp_new_i32(); + TCGv_i32 hi = tcg_temp_new_i32(); + + tcg_gen_muls2_i32(lo, hi, rn, rm); + tcg_gen_concat_i32_i64(rd, lo, hi); + + tcg_temp_free_i32(lo); + tcg_temp_free_i32(hi); +} + +static void gen_mull_u32(TCGv_i64 rd, TCGv_i32 rn, TCGv_i32 rm) +{ + TCGv_i32 lo = tcg_temp_new_i32(); + TCGv_i32 hi = tcg_temp_new_i32(); + + tcg_gen_mulu2_i32(lo, hi, rn, rm); + tcg_gen_concat_i32_i64(rd, lo, hi); + + tcg_temp_free_i32(lo); + tcg_temp_free_i32(hi); +} + +static bool trans_VMULL_S_3d(DisasContext *s, arg_3diff *a) +{ + static NeonGenTwoOpWidenFn * const opfn[] = { + gen_helper_neon_mull_s8, + gen_helper_neon_mull_s16, + gen_mull_s32, + NULL, + }; + + return do_long_3d(s, a, opfn[a->size], NULL); +} + +static bool trans_VMULL_U_3d(DisasContext *s, arg_3diff *a) +{ + static NeonGenTwoOpWidenFn * const opfn[] = { + gen_helper_neon_mull_u8, + gen_helper_neon_mull_u16, + gen_mull_u32, + NULL, + }; + + return do_long_3d(s, a, opfn[a->size], NULL); +} + +#define DO_VMLAL(INSN,MULL,ACC) \ + static bool trans_##INSN##_3d(DisasContext *s, arg_3diff *a) \ + { \ + static NeonGenTwoOpWidenFn * const opfn[] = { \ + gen_helper_neon_##MULL##8, \ + gen_helper_neon_##MULL##16, \ + gen_##MULL##32, \ + NULL, \ + }; \ + static NeonGenTwo64OpFn * const accfn[] = { \ + gen_helper_neon_##ACC##l_u16, \ + gen_helper_neon_##ACC##l_u32, \ + tcg_gen_##ACC##_i64, \ + NULL, \ + }; \ + return do_long_3d(s, a, opfn[a->size], accfn[a->size]); \ + } + +DO_VMLAL(VMLAL_S,mull_s,add) +DO_VMLAL(VMLAL_U,mull_u,add) +DO_VMLAL(VMLSL_S,mull_s,sub) +DO_VMLAL(VMLSL_U,mull_u,sub) + +static void gen_VQDMULL_16(TCGv_i64 rd, TCGv_i32 rn, TCGv_i32 rm) +{ + gen_helper_neon_mull_s16(rd, rn, rm); + gen_helper_neon_addl_saturate_s32(rd, cpu_env, rd, rd); +} + +static void gen_VQDMULL_32(TCGv_i64 rd, TCGv_i32 rn, TCGv_i32 rm) +{ + gen_mull_s32(rd, rn, rm); + gen_helper_neon_addl_saturate_s64(rd, cpu_env, rd, rd); +} + +static bool trans_VQDMULL_3d(DisasContext *s, arg_3diff *a) +{ + static NeonGenTwoOpWidenFn * const opfn[] = { + NULL, + gen_VQDMULL_16, + gen_VQDMULL_32, + NULL, + }; + + return do_long_3d(s, a, opfn[a->size], NULL); +} + +static void gen_VQDMLAL_acc_16(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm) +{ + gen_helper_neon_addl_saturate_s32(rd, cpu_env, rn, rm); +} + +static void gen_VQDMLAL_acc_32(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm) +{ + gen_helper_neon_addl_saturate_s64(rd, cpu_env, rn, rm); +} + +static bool trans_VQDMLAL_3d(DisasContext *s, arg_3diff *a) +{ + static NeonGenTwoOpWidenFn * const opfn[] = { + NULL, + gen_VQDMULL_16, + gen_VQDMULL_32, + NULL, + }; + static NeonGenTwo64OpFn * const accfn[] = { + NULL, + gen_VQDMLAL_acc_16, + gen_VQDMLAL_acc_32, + NULL, + }; + + return do_long_3d(s, a, opfn[a->size], accfn[a->size]); +} + +static void gen_VQDMLSL_acc_16(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm) +{ + gen_helper_neon_negl_u32(rm, rm); + gen_helper_neon_addl_saturate_s32(rd, cpu_env, rn, rm); +} + +static void gen_VQDMLSL_acc_32(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm) +{ + tcg_gen_neg_i64(rm, rm); + gen_helper_neon_addl_saturate_s64(rd, cpu_env, rn, rm); +} + +static bool trans_VQDMLSL_3d(DisasContext *s, arg_3diff *a) +{ + static NeonGenTwoOpWidenFn * const opfn[] = { + NULL, + gen_VQDMULL_16, + gen_VQDMULL_32, + NULL, + }; + static NeonGenTwo64OpFn * const accfn[] = { + NULL, + gen_VQDMLSL_acc_16, + gen_VQDMLSL_acc_32, + NULL, + }; + + return do_long_3d(s, a, opfn[a->size], accfn[a->size]); +} + +static bool trans_VMULL_P_3d(DisasContext *s, arg_3diff *a) +{ + gen_helper_gvec_3 *fn_gvec; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if (a->vd & 1) { + return false; + } + + switch (a->size) { + case 0: + fn_gvec = gen_helper_neon_pmull_h; + break; + case 2: + if (!dc_isar_feature(aa32_pmull, s)) { + return false; + } + fn_gvec = gen_helper_gvec_pmull_q; + break; + default: + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + tcg_gen_gvec_3_ool(neon_full_reg_offset(a->vd), + neon_full_reg_offset(a->vn), + neon_full_reg_offset(a->vm), + 16, 16, 0, fn_gvec); + return true; +} + +static void gen_neon_dup_low16(TCGv_i32 var) +{ + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_ext16u_i32(var, var); + tcg_gen_shli_i32(tmp, var, 16); + tcg_gen_or_i32(var, var, tmp); + tcg_temp_free_i32(tmp); +} + +static void gen_neon_dup_high16(TCGv_i32 var) +{ + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_andi_i32(var, var, 0xffff0000); + tcg_gen_shri_i32(tmp, var, 16); + tcg_gen_or_i32(var, var, tmp); + tcg_temp_free_i32(tmp); +} + +static inline TCGv_i32 neon_get_scalar(int size, int reg) +{ + TCGv_i32 tmp = tcg_temp_new_i32(); + if (size == MO_16) { + read_neon_element32(tmp, reg & 7, reg >> 4, MO_32); + if (reg & 8) { + gen_neon_dup_high16(tmp); + } else { + gen_neon_dup_low16(tmp); + } + } else { + read_neon_element32(tmp, reg & 15, reg >> 4, MO_32); + } + return tmp; +} + +static bool do_2scalar(DisasContext *s, arg_2scalar *a, + NeonGenTwoOpFn *opfn, NeonGenTwoOpFn *accfn) +{ + /* + * Two registers and a scalar: perform an operation between + * the input elements and the scalar, and then possibly + * perform an accumulation operation of that result into the + * destination. + */ + TCGv_i32 scalar, tmp; + int pass; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if (!opfn) { + /* Bad size (including size == 3, which is a different insn group) */ + return false; + } + + if (a->q && ((a->vd | a->vn) & 1)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + scalar = neon_get_scalar(a->size, a->vm); + tmp = tcg_temp_new_i32(); + + for (pass = 0; pass < (a->q ? 4 : 2); pass++) { + read_neon_element32(tmp, a->vn, pass, MO_32); + opfn(tmp, tmp, scalar); + if (accfn) { + TCGv_i32 rd = tcg_temp_new_i32(); + read_neon_element32(rd, a->vd, pass, MO_32); + accfn(tmp, rd, tmp); + tcg_temp_free_i32(rd); + } + write_neon_element32(tmp, a->vd, pass, MO_32); + } + tcg_temp_free_i32(tmp); + tcg_temp_free_i32(scalar); + return true; +} + +static bool trans_VMUL_2sc(DisasContext *s, arg_2scalar *a) +{ + static NeonGenTwoOpFn * const opfn[] = { + NULL, + gen_helper_neon_mul_u16, + tcg_gen_mul_i32, + NULL, + }; + + return do_2scalar(s, a, opfn[a->size], NULL); +} + +static bool trans_VMLA_2sc(DisasContext *s, arg_2scalar *a) +{ + static NeonGenTwoOpFn * const opfn[] = { + NULL, + gen_helper_neon_mul_u16, + tcg_gen_mul_i32, + NULL, + }; + static NeonGenTwoOpFn * const accfn[] = { + NULL, + gen_helper_neon_add_u16, + tcg_gen_add_i32, + NULL, + }; + + return do_2scalar(s, a, opfn[a->size], accfn[a->size]); +} + +static bool trans_VMLS_2sc(DisasContext *s, arg_2scalar *a) +{ + static NeonGenTwoOpFn * const opfn[] = { + NULL, + gen_helper_neon_mul_u16, + tcg_gen_mul_i32, + NULL, + }; + static NeonGenTwoOpFn * const accfn[] = { + NULL, + gen_helper_neon_sub_u16, + tcg_gen_sub_i32, + NULL, + }; + + return do_2scalar(s, a, opfn[a->size], accfn[a->size]); +} + +static bool do_2scalar_fp_vec(DisasContext *s, arg_2scalar *a, + gen_helper_gvec_3_ptr *fn) +{ + /* Two registers and a scalar, using gvec */ + int vec_size = a->q ? 16 : 8; + int rd_ofs = neon_full_reg_offset(a->vd); + int rn_ofs = neon_full_reg_offset(a->vn); + int rm_ofs; + int idx; + TCGv_ptr fpstatus; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if (!fn) { + /* Bad size (including size == 3, which is a different insn group) */ + return false; + } + + if (a->q && ((a->vd | a->vn) & 1)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + /* a->vm is M:Vm, which encodes both register and index */ + idx = extract32(a->vm, a->size + 2, 2); + a->vm = extract32(a->vm, 0, a->size + 2); + rm_ofs = neon_full_reg_offset(a->vm); + + fpstatus = fpstatus_ptr(a->size == 1 ? FPST_STD_F16 : FPST_STD); + tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, fpstatus, + vec_size, vec_size, idx, fn); + tcg_temp_free_ptr(fpstatus); + return true; +} + +#define DO_VMUL_F_2sc(NAME, FUNC) \ + static bool trans_##NAME##_F_2sc(DisasContext *s, arg_2scalar *a) \ + { \ + static gen_helper_gvec_3_ptr * const opfn[] = { \ + NULL, \ + gen_helper_##FUNC##_h, \ + gen_helper_##FUNC##_s, \ + NULL, \ + }; \ + if (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s)) { \ + return false; \ + } \ + return do_2scalar_fp_vec(s, a, opfn[a->size]); \ + } + +DO_VMUL_F_2sc(VMUL, gvec_fmul_idx) +DO_VMUL_F_2sc(VMLA, gvec_fmla_nf_idx) +DO_VMUL_F_2sc(VMLS, gvec_fmls_nf_idx) + +WRAP_ENV_FN(gen_VQDMULH_16, gen_helper_neon_qdmulh_s16) +WRAP_ENV_FN(gen_VQDMULH_32, gen_helper_neon_qdmulh_s32) +WRAP_ENV_FN(gen_VQRDMULH_16, gen_helper_neon_qrdmulh_s16) +WRAP_ENV_FN(gen_VQRDMULH_32, gen_helper_neon_qrdmulh_s32) + +static bool trans_VQDMULH_2sc(DisasContext *s, arg_2scalar *a) +{ + static NeonGenTwoOpFn * const opfn[] = { + NULL, + gen_VQDMULH_16, + gen_VQDMULH_32, + NULL, + }; + + return do_2scalar(s, a, opfn[a->size], NULL); +} + +static bool trans_VQRDMULH_2sc(DisasContext *s, arg_2scalar *a) +{ + static NeonGenTwoOpFn * const opfn[] = { + NULL, + gen_VQRDMULH_16, + gen_VQRDMULH_32, + NULL, + }; + + return do_2scalar(s, a, opfn[a->size], NULL); +} + +static bool do_vqrdmlah_2sc(DisasContext *s, arg_2scalar *a, + NeonGenThreeOpEnvFn *opfn) +{ + /* + * VQRDMLAH/VQRDMLSH: this is like do_2scalar, but the opfn + * performs a kind of fused op-then-accumulate using a helper + * function that takes all of rd, rn and the scalar at once. + */ + TCGv_i32 scalar, rn, rd; + int pass; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + if (!dc_isar_feature(aa32_rdm, s)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if (!opfn) { + /* Bad size (including size == 3, which is a different insn group) */ + return false; + } + + if (a->q && ((a->vd | a->vn) & 1)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + scalar = neon_get_scalar(a->size, a->vm); + rn = tcg_temp_new_i32(); + rd = tcg_temp_new_i32(); + + for (pass = 0; pass < (a->q ? 4 : 2); pass++) { + read_neon_element32(rn, a->vn, pass, MO_32); + read_neon_element32(rd, a->vd, pass, MO_32); + opfn(rd, cpu_env, rn, scalar, rd); + write_neon_element32(rd, a->vd, pass, MO_32); + } + tcg_temp_free_i32(rn); + tcg_temp_free_i32(rd); + tcg_temp_free_i32(scalar); + + return true; +} + +static bool trans_VQRDMLAH_2sc(DisasContext *s, arg_2scalar *a) +{ + static NeonGenThreeOpEnvFn *opfn[] = { + NULL, + gen_helper_neon_qrdmlah_s16, + gen_helper_neon_qrdmlah_s32, + NULL, + }; + return do_vqrdmlah_2sc(s, a, opfn[a->size]); +} + +static bool trans_VQRDMLSH_2sc(DisasContext *s, arg_2scalar *a) +{ + static NeonGenThreeOpEnvFn *opfn[] = { + NULL, + gen_helper_neon_qrdmlsh_s16, + gen_helper_neon_qrdmlsh_s32, + NULL, + }; + return do_vqrdmlah_2sc(s, a, opfn[a->size]); +} + +static bool do_2scalar_long(DisasContext *s, arg_2scalar *a, + NeonGenTwoOpWidenFn *opfn, + NeonGenTwo64OpFn *accfn) +{ + /* + * Two registers and a scalar, long operations: perform an + * operation on the input elements and the scalar which produces + * a double-width result, and then possibly perform an accumulation + * operation of that result into the destination. + */ + TCGv_i32 scalar, rn; + TCGv_i64 rn0_64, rn1_64; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if (!opfn) { + /* Bad size (including size == 3, which is a different insn group) */ + return false; + } + + if (a->vd & 1) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + scalar = neon_get_scalar(a->size, a->vm); + + /* Load all inputs before writing any outputs, in case of overlap */ + rn = tcg_temp_new_i32(); + read_neon_element32(rn, a->vn, 0, MO_32); + rn0_64 = tcg_temp_new_i64(); + opfn(rn0_64, rn, scalar); + + read_neon_element32(rn, a->vn, 1, MO_32); + rn1_64 = tcg_temp_new_i64(); + opfn(rn1_64, rn, scalar); + tcg_temp_free_i32(rn); + tcg_temp_free_i32(scalar); + + if (accfn) { + TCGv_i64 t64 = tcg_temp_new_i64(); + read_neon_element64(t64, a->vd, 0, MO_64); + accfn(rn0_64, t64, rn0_64); + read_neon_element64(t64, a->vd, 1, MO_64); + accfn(rn1_64, t64, rn1_64); + tcg_temp_free_i64(t64); + } + + write_neon_element64(rn0_64, a->vd, 0, MO_64); + write_neon_element64(rn1_64, a->vd, 1, MO_64); + tcg_temp_free_i64(rn0_64); + tcg_temp_free_i64(rn1_64); + return true; +} + +static bool trans_VMULL_S_2sc(DisasContext *s, arg_2scalar *a) +{ + static NeonGenTwoOpWidenFn * const opfn[] = { + NULL, + gen_helper_neon_mull_s16, + gen_mull_s32, + NULL, + }; + + return do_2scalar_long(s, a, opfn[a->size], NULL); +} + +static bool trans_VMULL_U_2sc(DisasContext *s, arg_2scalar *a) +{ + static NeonGenTwoOpWidenFn * const opfn[] = { + NULL, + gen_helper_neon_mull_u16, + gen_mull_u32, + NULL, + }; + + return do_2scalar_long(s, a, opfn[a->size], NULL); +} + +#define DO_VMLAL_2SC(INSN, MULL, ACC) \ + static bool trans_##INSN##_2sc(DisasContext *s, arg_2scalar *a) \ + { \ + static NeonGenTwoOpWidenFn * const opfn[] = { \ + NULL, \ + gen_helper_neon_##MULL##16, \ + gen_##MULL##32, \ + NULL, \ + }; \ + static NeonGenTwo64OpFn * const accfn[] = { \ + NULL, \ + gen_helper_neon_##ACC##l_u32, \ + tcg_gen_##ACC##_i64, \ + NULL, \ + }; \ + return do_2scalar_long(s, a, opfn[a->size], accfn[a->size]); \ + } + +DO_VMLAL_2SC(VMLAL_S, mull_s, add) +DO_VMLAL_2SC(VMLAL_U, mull_u, add) +DO_VMLAL_2SC(VMLSL_S, mull_s, sub) +DO_VMLAL_2SC(VMLSL_U, mull_u, sub) + +static bool trans_VQDMULL_2sc(DisasContext *s, arg_2scalar *a) +{ + static NeonGenTwoOpWidenFn * const opfn[] = { + NULL, + gen_VQDMULL_16, + gen_VQDMULL_32, + NULL, + }; + + return do_2scalar_long(s, a, opfn[a->size], NULL); +} + +static bool trans_VQDMLAL_2sc(DisasContext *s, arg_2scalar *a) +{ + static NeonGenTwoOpWidenFn * const opfn[] = { + NULL, + gen_VQDMULL_16, + gen_VQDMULL_32, + NULL, + }; + static NeonGenTwo64OpFn * const accfn[] = { + NULL, + gen_VQDMLAL_acc_16, + gen_VQDMLAL_acc_32, + NULL, + }; + + return do_2scalar_long(s, a, opfn[a->size], accfn[a->size]); +} + +static bool trans_VQDMLSL_2sc(DisasContext *s, arg_2scalar *a) +{ + static NeonGenTwoOpWidenFn * const opfn[] = { + NULL, + gen_VQDMULL_16, + gen_VQDMULL_32, + NULL, + }; + static NeonGenTwo64OpFn * const accfn[] = { + NULL, + gen_VQDMLSL_acc_16, + gen_VQDMLSL_acc_32, + NULL, + }; + + return do_2scalar_long(s, a, opfn[a->size], accfn[a->size]); +} + +static bool trans_VEXT(DisasContext *s, arg_VEXT *a) +{ + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if ((a->vn | a->vm | a->vd) & a->q) { + return false; + } + + if (a->imm > 7 && !a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + if (!a->q) { + /* Extract 64 bits from */ + TCGv_i64 left, right, dest; + + left = tcg_temp_new_i64(); + right = tcg_temp_new_i64(); + dest = tcg_temp_new_i64(); + + read_neon_element64(right, a->vn, 0, MO_64); + read_neon_element64(left, a->vm, 0, MO_64); + tcg_gen_extract2_i64(dest, right, left, a->imm * 8); + write_neon_element64(dest, a->vd, 0, MO_64); + + tcg_temp_free_i64(left); + tcg_temp_free_i64(right); + tcg_temp_free_i64(dest); + } else { + /* Extract 128 bits from */ + TCGv_i64 left, middle, right, destleft, destright; + + left = tcg_temp_new_i64(); + middle = tcg_temp_new_i64(); + right = tcg_temp_new_i64(); + destleft = tcg_temp_new_i64(); + destright = tcg_temp_new_i64(); + + if (a->imm < 8) { + read_neon_element64(right, a->vn, 0, MO_64); + read_neon_element64(middle, a->vn, 1, MO_64); + tcg_gen_extract2_i64(destright, right, middle, a->imm * 8); + read_neon_element64(left, a->vm, 0, MO_64); + tcg_gen_extract2_i64(destleft, middle, left, a->imm * 8); + } else { + read_neon_element64(right, a->vn, 1, MO_64); + read_neon_element64(middle, a->vm, 0, MO_64); + tcg_gen_extract2_i64(destright, right, middle, (a->imm - 8) * 8); + read_neon_element64(left, a->vm, 1, MO_64); + tcg_gen_extract2_i64(destleft, middle, left, (a->imm - 8) * 8); + } + + write_neon_element64(destright, a->vd, 0, MO_64); + write_neon_element64(destleft, a->vd, 1, MO_64); + + tcg_temp_free_i64(destright); + tcg_temp_free_i64(destleft); + tcg_temp_free_i64(right); + tcg_temp_free_i64(middle); + tcg_temp_free_i64(left); + } + return true; +} + +static bool trans_VTBL(DisasContext *s, arg_VTBL *a) +{ + TCGv_i64 val, def; + TCGv_i32 desc; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if ((a->vn + a->len + 1) > 32) { + /* + * This is UNPREDICTABLE; we choose to UNDEF to avoid the + * helper function running off the end of the register file. + */ + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + desc = tcg_const_i32((a->vn << 2) | a->len); + def = tcg_temp_new_i64(); + if (a->op) { + read_neon_element64(def, a->vd, 0, MO_64); + } else { + tcg_gen_movi_i64(def, 0); + } + val = tcg_temp_new_i64(); + read_neon_element64(val, a->vm, 0, MO_64); + + gen_helper_neon_tbl(val, cpu_env, desc, val, def); + write_neon_element64(val, a->vd, 0, MO_64); + + tcg_temp_free_i64(def); + tcg_temp_free_i64(val); + tcg_temp_free_i32(desc); + return true; +} + +static bool trans_VDUP_scalar(DisasContext *s, arg_VDUP_scalar *a) +{ + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if (a->vd & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + tcg_gen_gvec_dup_mem(a->size, neon_full_reg_offset(a->vd), + neon_element_offset(a->vm, a->index, a->size), + a->q ? 16 : 8, a->q ? 16 : 8); + return true; +} + +static bool trans_VREV64(DisasContext *s, arg_VREV64 *a) +{ + int pass, half; + TCGv_i32 tmp[2]; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if ((a->vd | a->vm) & a->q) { + return false; + } + + if (a->size == 3) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + tmp[0] = tcg_temp_new_i32(); + tmp[1] = tcg_temp_new_i32(); + + for (pass = 0; pass < (a->q ? 2 : 1); pass++) { + for (half = 0; half < 2; half++) { + read_neon_element32(tmp[half], a->vm, pass * 2 + half, MO_32); + switch (a->size) { + case 0: + tcg_gen_bswap32_i32(tmp[half], tmp[half]); + break; + case 1: + gen_swap_half(tmp[half], tmp[half]); + break; + case 2: + break; + default: + g_assert_not_reached(); + } + } + write_neon_element32(tmp[1], a->vd, pass * 2, MO_32); + write_neon_element32(tmp[0], a->vd, pass * 2 + 1, MO_32); + } + + tcg_temp_free_i32(tmp[0]); + tcg_temp_free_i32(tmp[1]); + return true; +} + +static bool do_2misc_pairwise(DisasContext *s, arg_2misc *a, + NeonGenWidenFn *widenfn, + NeonGenTwo64OpFn *opfn, + NeonGenTwo64OpFn *accfn) +{ + /* + * Pairwise long operations: widen both halves of the pair, + * combine the pairs with the opfn, and then possibly accumulate + * into the destination with the accfn. + */ + int pass; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if ((a->vd | a->vm) & a->q) { + return false; + } + + if (!widenfn) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + for (pass = 0; pass < a->q + 1; pass++) { + TCGv_i32 tmp; + TCGv_i64 rm0_64, rm1_64, rd_64; + + rm0_64 = tcg_temp_new_i64(); + rm1_64 = tcg_temp_new_i64(); + rd_64 = tcg_temp_new_i64(); + + tmp = tcg_temp_new_i32(); + read_neon_element32(tmp, a->vm, pass * 2, MO_32); + widenfn(rm0_64, tmp); + read_neon_element32(tmp, a->vm, pass * 2 + 1, MO_32); + widenfn(rm1_64, tmp); + tcg_temp_free_i32(tmp); + + opfn(rd_64, rm0_64, rm1_64); + tcg_temp_free_i64(rm0_64); + tcg_temp_free_i64(rm1_64); + + if (accfn) { + TCGv_i64 tmp64 = tcg_temp_new_i64(); + read_neon_element64(tmp64, a->vd, pass, MO_64); + accfn(rd_64, tmp64, rd_64); + tcg_temp_free_i64(tmp64); + } + write_neon_element64(rd_64, a->vd, pass, MO_64); + tcg_temp_free_i64(rd_64); + } + return true; +} + +static bool trans_VPADDL_S(DisasContext *s, arg_2misc *a) +{ + static NeonGenWidenFn * const widenfn[] = { + gen_helper_neon_widen_s8, + gen_helper_neon_widen_s16, + tcg_gen_ext_i32_i64, + NULL, + }; + static NeonGenTwo64OpFn * const opfn[] = { + gen_helper_neon_paddl_u16, + gen_helper_neon_paddl_u32, + tcg_gen_add_i64, + NULL, + }; + + return do_2misc_pairwise(s, a, widenfn[a->size], opfn[a->size], NULL); +} + +static bool trans_VPADDL_U(DisasContext *s, arg_2misc *a) +{ + static NeonGenWidenFn * const widenfn[] = { + gen_helper_neon_widen_u8, + gen_helper_neon_widen_u16, + tcg_gen_extu_i32_i64, + NULL, + }; + static NeonGenTwo64OpFn * const opfn[] = { + gen_helper_neon_paddl_u16, + gen_helper_neon_paddl_u32, + tcg_gen_add_i64, + NULL, + }; + + return do_2misc_pairwise(s, a, widenfn[a->size], opfn[a->size], NULL); +} + +static bool trans_VPADAL_S(DisasContext *s, arg_2misc *a) +{ + static NeonGenWidenFn * const widenfn[] = { + gen_helper_neon_widen_s8, + gen_helper_neon_widen_s16, + tcg_gen_ext_i32_i64, + NULL, + }; + static NeonGenTwo64OpFn * const opfn[] = { + gen_helper_neon_paddl_u16, + gen_helper_neon_paddl_u32, + tcg_gen_add_i64, + NULL, + }; + static NeonGenTwo64OpFn * const accfn[] = { + gen_helper_neon_addl_u16, + gen_helper_neon_addl_u32, + tcg_gen_add_i64, + NULL, + }; + + return do_2misc_pairwise(s, a, widenfn[a->size], opfn[a->size], + accfn[a->size]); +} + +static bool trans_VPADAL_U(DisasContext *s, arg_2misc *a) +{ + static NeonGenWidenFn * const widenfn[] = { + gen_helper_neon_widen_u8, + gen_helper_neon_widen_u16, + tcg_gen_extu_i32_i64, + NULL, + }; + static NeonGenTwo64OpFn * const opfn[] = { + gen_helper_neon_paddl_u16, + gen_helper_neon_paddl_u32, + tcg_gen_add_i64, + NULL, + }; + static NeonGenTwo64OpFn * const accfn[] = { + gen_helper_neon_addl_u16, + gen_helper_neon_addl_u32, + tcg_gen_add_i64, + NULL, + }; + + return do_2misc_pairwise(s, a, widenfn[a->size], opfn[a->size], + accfn[a->size]); +} + +typedef void ZipFn(TCGv_ptr, TCGv_ptr); + +static bool do_zip_uzp(DisasContext *s, arg_2misc *a, + ZipFn *fn) +{ + TCGv_ptr pd, pm; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if ((a->vd | a->vm) & a->q) { + return false; + } + + if (!fn) { + /* Bad size or size/q combination */ + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + pd = vfp_reg_ptr(true, a->vd); + pm = vfp_reg_ptr(true, a->vm); + fn(pd, pm); + tcg_temp_free_ptr(pd); + tcg_temp_free_ptr(pm); + return true; +} + +static bool trans_VUZP(DisasContext *s, arg_2misc *a) +{ + static ZipFn * const fn[2][4] = { + { + gen_helper_neon_unzip8, + gen_helper_neon_unzip16, + NULL, + NULL, + }, { + gen_helper_neon_qunzip8, + gen_helper_neon_qunzip16, + gen_helper_neon_qunzip32, + NULL, + } + }; + return do_zip_uzp(s, a, fn[a->q][a->size]); +} + +static bool trans_VZIP(DisasContext *s, arg_2misc *a) +{ + static ZipFn * const fn[2][4] = { + { + gen_helper_neon_zip8, + gen_helper_neon_zip16, + NULL, + NULL, + }, { + gen_helper_neon_qzip8, + gen_helper_neon_qzip16, + gen_helper_neon_qzip32, + NULL, + } + }; + return do_zip_uzp(s, a, fn[a->q][a->size]); +} + +static bool do_vmovn(DisasContext *s, arg_2misc *a, + NeonGenNarrowEnvFn *narrowfn) +{ + TCGv_i64 rm; + TCGv_i32 rd0, rd1; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if (a->vm & 1) { + return false; + } + + if (!narrowfn) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + rm = tcg_temp_new_i64(); + rd0 = tcg_temp_new_i32(); + rd1 = tcg_temp_new_i32(); + + read_neon_element64(rm, a->vm, 0, MO_64); + narrowfn(rd0, cpu_env, rm); + read_neon_element64(rm, a->vm, 1, MO_64); + narrowfn(rd1, cpu_env, rm); + write_neon_element32(rd0, a->vd, 0, MO_32); + write_neon_element32(rd1, a->vd, 1, MO_32); + tcg_temp_free_i32(rd0); + tcg_temp_free_i32(rd1); + tcg_temp_free_i64(rm); + return true; +} + +#define DO_VMOVN(INSN, FUNC) \ + static bool trans_##INSN(DisasContext *s, arg_2misc *a) \ + { \ + static NeonGenNarrowEnvFn * const narrowfn[] = { \ + FUNC##8, \ + FUNC##16, \ + FUNC##32, \ + NULL, \ + }; \ + return do_vmovn(s, a, narrowfn[a->size]); \ + } + +DO_VMOVN(VMOVN, gen_neon_narrow_u) +DO_VMOVN(VQMOVUN, gen_helper_neon_unarrow_sat) +DO_VMOVN(VQMOVN_S, gen_helper_neon_narrow_sat_s) +DO_VMOVN(VQMOVN_U, gen_helper_neon_narrow_sat_u) + +static bool trans_VSHLL(DisasContext *s, arg_2misc *a) +{ + TCGv_i32 rm0, rm1; + TCGv_i64 rd; + static NeonGenWidenFn * const widenfns[] = { + gen_helper_neon_widen_u8, + gen_helper_neon_widen_u16, + tcg_gen_extu_i32_i64, + NULL, + }; + NeonGenWidenFn *widenfn = widenfns[a->size]; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if (a->vd & 1) { + return false; + } + + if (!widenfn) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + rd = tcg_temp_new_i64(); + rm0 = tcg_temp_new_i32(); + rm1 = tcg_temp_new_i32(); + + read_neon_element32(rm0, a->vm, 0, MO_32); + read_neon_element32(rm1, a->vm, 1, MO_32); + + widenfn(rd, rm0); + tcg_gen_shli_i64(rd, rd, 8 << a->size); + write_neon_element64(rd, a->vd, 0, MO_64); + widenfn(rd, rm1); + tcg_gen_shli_i64(rd, rd, 8 << a->size); + write_neon_element64(rd, a->vd, 1, MO_64); + + tcg_temp_free_i64(rd); + tcg_temp_free_i32(rm0); + tcg_temp_free_i32(rm1); + return true; +} + +static bool trans_VCVT_F16_F32(DisasContext *s, arg_2misc *a) +{ + TCGv_ptr fpst; + TCGv_i32 ahp, tmp, tmp2, tmp3; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON) || + !dc_isar_feature(aa32_fp16_spconv, s)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if ((a->vm & 1) || (a->size != 1)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + fpst = fpstatus_ptr(FPST_STD); + ahp = get_ahp_flag(); + tmp = tcg_temp_new_i32(); + read_neon_element32(tmp, a->vm, 0, MO_32); + gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp); + tmp2 = tcg_temp_new_i32(); + read_neon_element32(tmp2, a->vm, 1, MO_32); + gen_helper_vfp_fcvt_f32_to_f16(tmp2, tmp2, fpst, ahp); + tcg_gen_shli_i32(tmp2, tmp2, 16); + tcg_gen_or_i32(tmp2, tmp2, tmp); + read_neon_element32(tmp, a->vm, 2, MO_32); + gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp); + tmp3 = tcg_temp_new_i32(); + read_neon_element32(tmp3, a->vm, 3, MO_32); + write_neon_element32(tmp2, a->vd, 0, MO_32); + tcg_temp_free_i32(tmp2); + gen_helper_vfp_fcvt_f32_to_f16(tmp3, tmp3, fpst, ahp); + tcg_gen_shli_i32(tmp3, tmp3, 16); + tcg_gen_or_i32(tmp3, tmp3, tmp); + write_neon_element32(tmp3, a->vd, 1, MO_32); + tcg_temp_free_i32(tmp3); + tcg_temp_free_i32(tmp); + tcg_temp_free_i32(ahp); + tcg_temp_free_ptr(fpst); + + return true; +} + +static bool trans_VCVT_F32_F16(DisasContext *s, arg_2misc *a) +{ + TCGv_ptr fpst; + TCGv_i32 ahp, tmp, tmp2, tmp3; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON) || + !dc_isar_feature(aa32_fp16_spconv, s)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if ((a->vd & 1) || (a->size != 1)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + fpst = fpstatus_ptr(FPST_STD); + ahp = get_ahp_flag(); + tmp3 = tcg_temp_new_i32(); + tmp2 = tcg_temp_new_i32(); + tmp = tcg_temp_new_i32(); + read_neon_element32(tmp, a->vm, 0, MO_32); + read_neon_element32(tmp2, a->vm, 1, MO_32); + tcg_gen_ext16u_i32(tmp3, tmp); + gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp); + write_neon_element32(tmp3, a->vd, 0, MO_32); + tcg_gen_shri_i32(tmp, tmp, 16); + gen_helper_vfp_fcvt_f16_to_f32(tmp, tmp, fpst, ahp); + write_neon_element32(tmp, a->vd, 1, MO_32); + tcg_temp_free_i32(tmp); + tcg_gen_ext16u_i32(tmp3, tmp2); + gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp); + write_neon_element32(tmp3, a->vd, 2, MO_32); + tcg_temp_free_i32(tmp3); + tcg_gen_shri_i32(tmp2, tmp2, 16); + gen_helper_vfp_fcvt_f16_to_f32(tmp2, tmp2, fpst, ahp); + write_neon_element32(tmp2, a->vd, 3, MO_32); + tcg_temp_free_i32(tmp2); + tcg_temp_free_i32(ahp); + tcg_temp_free_ptr(fpst); + + return true; +} + +static bool do_2misc_vec(DisasContext *s, arg_2misc *a, GVecGen2Fn *fn) +{ + int vec_size = a->q ? 16 : 8; + int rd_ofs = neon_full_reg_offset(a->vd); + int rm_ofs = neon_full_reg_offset(a->vm); + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if (a->size == 3) { + return false; + } + + if ((a->vd | a->vm) & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + fn(a->size, rd_ofs, rm_ofs, vec_size, vec_size); + + return true; +} + +#define DO_2MISC_VEC(INSN, FN) \ + static bool trans_##INSN(DisasContext *s, arg_2misc *a) \ + { \ + return do_2misc_vec(s, a, FN); \ + } + +DO_2MISC_VEC(VNEG, tcg_gen_gvec_neg) +DO_2MISC_VEC(VABS, tcg_gen_gvec_abs) +DO_2MISC_VEC(VCEQ0, gen_gvec_ceq0) +DO_2MISC_VEC(VCGT0, gen_gvec_cgt0) +DO_2MISC_VEC(VCLE0, gen_gvec_cle0) +DO_2MISC_VEC(VCGE0, gen_gvec_cge0) +DO_2MISC_VEC(VCLT0, gen_gvec_clt0) + +static bool trans_VMVN(DisasContext *s, arg_2misc *a) +{ + if (a->size != 0) { + return false; + } + return do_2misc_vec(s, a, tcg_gen_gvec_not); +} + +#define WRAP_2M_3_OOL_FN(WRAPNAME, FUNC, DATA) \ + static void WRAPNAME(unsigned vece, uint32_t rd_ofs, \ + uint32_t rm_ofs, uint32_t oprsz, \ + uint32_t maxsz) \ + { \ + tcg_gen_gvec_3_ool(rd_ofs, rd_ofs, rm_ofs, oprsz, maxsz, \ + DATA, FUNC); \ + } + +#define WRAP_2M_2_OOL_FN(WRAPNAME, FUNC, DATA) \ + static void WRAPNAME(unsigned vece, uint32_t rd_ofs, \ + uint32_t rm_ofs, uint32_t oprsz, \ + uint32_t maxsz) \ + { \ + tcg_gen_gvec_2_ool(rd_ofs, rm_ofs, oprsz, maxsz, DATA, FUNC); \ + } + +WRAP_2M_3_OOL_FN(gen_AESE, gen_helper_crypto_aese, 0) +WRAP_2M_3_OOL_FN(gen_AESD, gen_helper_crypto_aese, 1) +WRAP_2M_2_OOL_FN(gen_AESMC, gen_helper_crypto_aesmc, 0) +WRAP_2M_2_OOL_FN(gen_AESIMC, gen_helper_crypto_aesmc, 1) +WRAP_2M_2_OOL_FN(gen_SHA1H, gen_helper_crypto_sha1h, 0) +WRAP_2M_2_OOL_FN(gen_SHA1SU1, gen_helper_crypto_sha1su1, 0) +WRAP_2M_2_OOL_FN(gen_SHA256SU0, gen_helper_crypto_sha256su0, 0) + +#define DO_2M_CRYPTO(INSN, FEATURE, SIZE) \ + static bool trans_##INSN(DisasContext *s, arg_2misc *a) \ + { \ + if (!dc_isar_feature(FEATURE, s) || a->size != SIZE) { \ + return false; \ + } \ + return do_2misc_vec(s, a, gen_##INSN); \ + } + +DO_2M_CRYPTO(AESE, aa32_aes, 0) +DO_2M_CRYPTO(AESD, aa32_aes, 0) +DO_2M_CRYPTO(AESMC, aa32_aes, 0) +DO_2M_CRYPTO(AESIMC, aa32_aes, 0) +DO_2M_CRYPTO(SHA1H, aa32_sha1, 2) +DO_2M_CRYPTO(SHA1SU1, aa32_sha1, 2) +DO_2M_CRYPTO(SHA256SU0, aa32_sha2, 2) + +static bool do_2misc(DisasContext *s, arg_2misc *a, NeonGenOneOpFn *fn) +{ + TCGv_i32 tmp; + int pass; + + /* Handle a 2-reg-misc operation by iterating 32 bits at a time */ + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if (!fn) { + return false; + } + + if ((a->vd | a->vm) & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + tmp = tcg_temp_new_i32(); + for (pass = 0; pass < (a->q ? 4 : 2); pass++) { + read_neon_element32(tmp, a->vm, pass, MO_32); + fn(tmp, tmp); + write_neon_element32(tmp, a->vd, pass, MO_32); + } + tcg_temp_free_i32(tmp); + + return true; +} + +static bool trans_VREV32(DisasContext *s, arg_2misc *a) +{ + static NeonGenOneOpFn * const fn[] = { + tcg_gen_bswap32_i32, + gen_swap_half, + NULL, + NULL, + }; + return do_2misc(s, a, fn[a->size]); +} + +static bool trans_VREV16(DisasContext *s, arg_2misc *a) +{ + if (a->size != 0) { + return false; + } + return do_2misc(s, a, gen_rev16); +} + +static bool trans_VCLS(DisasContext *s, arg_2misc *a) +{ + static NeonGenOneOpFn * const fn[] = { + gen_helper_neon_cls_s8, + gen_helper_neon_cls_s16, + gen_helper_neon_cls_s32, + NULL, + }; + return do_2misc(s, a, fn[a->size]); +} + +static void do_VCLZ_32(TCGv_i32 rd, TCGv_i32 rm) +{ + tcg_gen_clzi_i32(rd, rm, 32); +} + +static bool trans_VCLZ(DisasContext *s, arg_2misc *a) +{ + static NeonGenOneOpFn * const fn[] = { + gen_helper_neon_clz_u8, + gen_helper_neon_clz_u16, + do_VCLZ_32, + NULL, + }; + return do_2misc(s, a, fn[a->size]); +} + +static bool trans_VCNT(DisasContext *s, arg_2misc *a) +{ + if (a->size != 0) { + return false; + } + return do_2misc(s, a, gen_helper_neon_cnt_u8); +} + +static void gen_VABS_F(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, + uint32_t oprsz, uint32_t maxsz) +{ + tcg_gen_gvec_andi(vece, rd_ofs, rm_ofs, + vece == MO_16 ? 0x7fff : 0x7fffffff, + oprsz, maxsz); +} + +static bool trans_VABS_F(DisasContext *s, arg_2misc *a) +{ + if (a->size == MO_16) { + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + } else if (a->size != MO_32) { + return false; + } + return do_2misc_vec(s, a, gen_VABS_F); +} + +static void gen_VNEG_F(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs, + uint32_t oprsz, uint32_t maxsz) +{ + tcg_gen_gvec_xori(vece, rd_ofs, rm_ofs, + vece == MO_16 ? 0x8000 : 0x80000000, + oprsz, maxsz); +} + +static bool trans_VNEG_F(DisasContext *s, arg_2misc *a) +{ + if (a->size == MO_16) { + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + } else if (a->size != MO_32) { + return false; + } + return do_2misc_vec(s, a, gen_VNEG_F); +} + +static bool trans_VRECPE(DisasContext *s, arg_2misc *a) +{ + if (a->size != 2) { + return false; + } + return do_2misc(s, a, gen_helper_recpe_u32); +} + +static bool trans_VRSQRTE(DisasContext *s, arg_2misc *a) +{ + if (a->size != 2) { + return false; + } + return do_2misc(s, a, gen_helper_rsqrte_u32); +} + +#define WRAP_1OP_ENV_FN(WRAPNAME, FUNC) \ + static void WRAPNAME(TCGv_i32 d, TCGv_i32 m) \ + { \ + FUNC(d, cpu_env, m); \ + } + +WRAP_1OP_ENV_FN(gen_VQABS_s8, gen_helper_neon_qabs_s8) +WRAP_1OP_ENV_FN(gen_VQABS_s16, gen_helper_neon_qabs_s16) +WRAP_1OP_ENV_FN(gen_VQABS_s32, gen_helper_neon_qabs_s32) +WRAP_1OP_ENV_FN(gen_VQNEG_s8, gen_helper_neon_qneg_s8) +WRAP_1OP_ENV_FN(gen_VQNEG_s16, gen_helper_neon_qneg_s16) +WRAP_1OP_ENV_FN(gen_VQNEG_s32, gen_helper_neon_qneg_s32) + +static bool trans_VQABS(DisasContext *s, arg_2misc *a) +{ + static NeonGenOneOpFn * const fn[] = { + gen_VQABS_s8, + gen_VQABS_s16, + gen_VQABS_s32, + NULL, + }; + return do_2misc(s, a, fn[a->size]); +} + +static bool trans_VQNEG(DisasContext *s, arg_2misc *a) +{ + static NeonGenOneOpFn * const fn[] = { + gen_VQNEG_s8, + gen_VQNEG_s16, + gen_VQNEG_s32, + NULL, + }; + return do_2misc(s, a, fn[a->size]); +} + +#define DO_2MISC_FP_VEC(INSN, HFUNC, SFUNC) \ + static void gen_##INSN(unsigned vece, uint32_t rd_ofs, \ + uint32_t rm_ofs, \ + uint32_t oprsz, uint32_t maxsz) \ + { \ + static gen_helper_gvec_2_ptr * const fns[4] = { \ + NULL, HFUNC, SFUNC, NULL, \ + }; \ + TCGv_ptr fpst; \ + fpst = fpstatus_ptr(vece == MO_16 ? FPST_STD_F16 : FPST_STD); \ + tcg_gen_gvec_2_ptr(rd_ofs, rm_ofs, fpst, oprsz, maxsz, 0, \ + fns[vece]); \ + tcg_temp_free_ptr(fpst); \ + } \ + static bool trans_##INSN(DisasContext *s, arg_2misc *a) \ + { \ + if (a->size == MO_16) { \ + if (!dc_isar_feature(aa32_fp16_arith, s)) { \ + return false; \ + } \ + } else if (a->size != MO_32) { \ + return false; \ + } \ + return do_2misc_vec(s, a, gen_##INSN); \ + } + +DO_2MISC_FP_VEC(VRECPE_F, gen_helper_gvec_frecpe_h, gen_helper_gvec_frecpe_s) +DO_2MISC_FP_VEC(VRSQRTE_F, gen_helper_gvec_frsqrte_h, gen_helper_gvec_frsqrte_s) +DO_2MISC_FP_VEC(VCGT0_F, gen_helper_gvec_fcgt0_h, gen_helper_gvec_fcgt0_s) +DO_2MISC_FP_VEC(VCGE0_F, gen_helper_gvec_fcge0_h, gen_helper_gvec_fcge0_s) +DO_2MISC_FP_VEC(VCEQ0_F, gen_helper_gvec_fceq0_h, gen_helper_gvec_fceq0_s) +DO_2MISC_FP_VEC(VCLT0_F, gen_helper_gvec_fclt0_h, gen_helper_gvec_fclt0_s) +DO_2MISC_FP_VEC(VCLE0_F, gen_helper_gvec_fcle0_h, gen_helper_gvec_fcle0_s) +DO_2MISC_FP_VEC(VCVT_FS, gen_helper_gvec_sstoh, gen_helper_gvec_sitos) +DO_2MISC_FP_VEC(VCVT_FU, gen_helper_gvec_ustoh, gen_helper_gvec_uitos) +DO_2MISC_FP_VEC(VCVT_SF, gen_helper_gvec_tosszh, gen_helper_gvec_tosizs) +DO_2MISC_FP_VEC(VCVT_UF, gen_helper_gvec_touszh, gen_helper_gvec_touizs) + +DO_2MISC_FP_VEC(VRINTX_impl, gen_helper_gvec_vrintx_h, gen_helper_gvec_vrintx_s) + +static bool trans_VRINTX(DisasContext *s, arg_2misc *a) +{ + if (!arm_dc_feature(s, ARM_FEATURE_V8)) { + return false; + } + return trans_VRINTX_impl(s, a); +} + +#define DO_VEC_RMODE(INSN, RMODE, OP) \ + static void gen_##INSN(unsigned vece, uint32_t rd_ofs, \ + uint32_t rm_ofs, \ + uint32_t oprsz, uint32_t maxsz) \ + { \ + static gen_helper_gvec_2_ptr * const fns[4] = { \ + NULL, \ + gen_helper_gvec_##OP##h, \ + gen_helper_gvec_##OP##s, \ + NULL, \ + }; \ + TCGv_ptr fpst; \ + fpst = fpstatus_ptr(vece == 1 ? FPST_STD_F16 : FPST_STD); \ + tcg_gen_gvec_2_ptr(rd_ofs, rm_ofs, fpst, oprsz, maxsz, \ + arm_rmode_to_sf(RMODE), fns[vece]); \ + tcg_temp_free_ptr(fpst); \ + } \ + static bool trans_##INSN(DisasContext *s, arg_2misc *a) \ + { \ + if (!arm_dc_feature(s, ARM_FEATURE_V8)) { \ + return false; \ + } \ + if (a->size == MO_16) { \ + if (!dc_isar_feature(aa32_fp16_arith, s)) { \ + return false; \ + } \ + } else if (a->size != MO_32) { \ + return false; \ + } \ + return do_2misc_vec(s, a, gen_##INSN); \ + } + +DO_VEC_RMODE(VCVTAU, FPROUNDING_TIEAWAY, vcvt_rm_u) +DO_VEC_RMODE(VCVTAS, FPROUNDING_TIEAWAY, vcvt_rm_s) +DO_VEC_RMODE(VCVTNU, FPROUNDING_TIEEVEN, vcvt_rm_u) +DO_VEC_RMODE(VCVTNS, FPROUNDING_TIEEVEN, vcvt_rm_s) +DO_VEC_RMODE(VCVTPU, FPROUNDING_POSINF, vcvt_rm_u) +DO_VEC_RMODE(VCVTPS, FPROUNDING_POSINF, vcvt_rm_s) +DO_VEC_RMODE(VCVTMU, FPROUNDING_NEGINF, vcvt_rm_u) +DO_VEC_RMODE(VCVTMS, FPROUNDING_NEGINF, vcvt_rm_s) + +DO_VEC_RMODE(VRINTN, FPROUNDING_TIEEVEN, vrint_rm_) +DO_VEC_RMODE(VRINTA, FPROUNDING_TIEAWAY, vrint_rm_) +DO_VEC_RMODE(VRINTZ, FPROUNDING_ZERO, vrint_rm_) +DO_VEC_RMODE(VRINTM, FPROUNDING_NEGINF, vrint_rm_) +DO_VEC_RMODE(VRINTP, FPROUNDING_POSINF, vrint_rm_) + +static bool trans_VSWP(DisasContext *s, arg_2misc *a) +{ + TCGv_i64 rm, rd; + int pass; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if (a->size != 0) { + return false; + } + + if ((a->vd | a->vm) & a->q) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + rm = tcg_temp_new_i64(); + rd = tcg_temp_new_i64(); + for (pass = 0; pass < (a->q ? 2 : 1); pass++) { + read_neon_element64(rm, a->vm, pass, MO_64); + read_neon_element64(rd, a->vd, pass, MO_64); + write_neon_element64(rm, a->vd, pass, MO_64); + write_neon_element64(rd, a->vm, pass, MO_64); + } + tcg_temp_free_i64(rm); + tcg_temp_free_i64(rd); + + return true; +} +static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1) +{ + TCGv_i32 rd, tmp; + + rd = tcg_temp_new_i32(); + tmp = tcg_temp_new_i32(); + + tcg_gen_shli_i32(rd, t0, 8); + tcg_gen_andi_i32(rd, rd, 0xff00ff00); + tcg_gen_andi_i32(tmp, t1, 0x00ff00ff); + tcg_gen_or_i32(rd, rd, tmp); + + tcg_gen_shri_i32(t1, t1, 8); + tcg_gen_andi_i32(t1, t1, 0x00ff00ff); + tcg_gen_andi_i32(tmp, t0, 0xff00ff00); + tcg_gen_or_i32(t1, t1, tmp); + tcg_gen_mov_i32(t0, rd); + + tcg_temp_free_i32(tmp); + tcg_temp_free_i32(rd); +} + +static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1) +{ + TCGv_i32 rd, tmp; + + rd = tcg_temp_new_i32(); + tmp = tcg_temp_new_i32(); + + tcg_gen_shli_i32(rd, t0, 16); + tcg_gen_andi_i32(tmp, t1, 0xffff); + tcg_gen_or_i32(rd, rd, tmp); + tcg_gen_shri_i32(t1, t1, 16); + tcg_gen_andi_i32(tmp, t0, 0xffff0000); + tcg_gen_or_i32(t1, t1, tmp); + tcg_gen_mov_i32(t0, rd); + + tcg_temp_free_i32(tmp); + tcg_temp_free_i32(rd); +} + +static bool trans_VTRN(DisasContext *s, arg_2misc *a) +{ + TCGv_i32 tmp, tmp2; + int pass; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vm) & 0x10)) { + return false; + } + + if ((a->vd | a->vm) & a->q) { + return false; + } + + if (a->size == 3) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + tmp = tcg_temp_new_i32(); + tmp2 = tcg_temp_new_i32(); + if (a->size == MO_32) { + for (pass = 0; pass < (a->q ? 4 : 2); pass += 2) { + read_neon_element32(tmp, a->vm, pass, MO_32); + read_neon_element32(tmp2, a->vd, pass + 1, MO_32); + write_neon_element32(tmp2, a->vm, pass, MO_32); + write_neon_element32(tmp, a->vd, pass + 1, MO_32); + } + } else { + for (pass = 0; pass < (a->q ? 4 : 2); pass++) { + read_neon_element32(tmp, a->vm, pass, MO_32); + read_neon_element32(tmp2, a->vd, pass, MO_32); + if (a->size == MO_8) { + gen_neon_trn_u8(tmp, tmp2); + } else { + gen_neon_trn_u16(tmp, tmp2); + } + write_neon_element32(tmp2, a->vm, pass, MO_32); + write_neon_element32(tmp, a->vd, pass, MO_32); + } + } + tcg_temp_free_i32(tmp); + tcg_temp_free_i32(tmp2); + return true; +} diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c deleted file mode 100644 index 3fe65a0b080a50b9c13cb94745460a72b317e523..0000000000000000000000000000000000000000 --- a/target/arm/translate-neon.inc.c +++ /dev/null @@ -1,1312 +0,0 @@ -/* - * ARM translation: AArch32 Neon instructions - * - * Copyright (c) 2003 Fabrice Bellard - * Copyright (c) 2005-2007 CodeSourcery - * Copyright (c) 2007 OpenedHand, Ltd. - * Copyright (c) 2020 Linaro, Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -/* - * This file is intended to be included from translate.c; it uses - * some macros and definitions provided by that file. - * It might be possible to convert it to a standalone .c file eventually. - */ - -static inline int plus1(DisasContext *s, int x) -{ - return x + 1; -} - -/* Include the generated Neon decoder */ -#include "decode-neon-dp.inc.c" -#include "decode-neon-ls.inc.c" -#include "decode-neon-shared.inc.c" - -static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a) -{ - int opr_sz; - TCGv_ptr fpst; - gen_helper_gvec_3_ptr *fn_gvec_ptr; - - if (!dc_isar_feature(aa32_vcma, s) - || (!a->size && !dc_isar_feature(aa32_fp16_arith, s))) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist. */ - if (!dc_isar_feature(aa32_simd_r32, s) && - ((a->vd | a->vn | a->vm) & 0x10)) { - return false; - } - - if ((a->vn | a->vm | a->vd) & a->q) { - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - opr_sz = (1 + a->q) * 8; - fpst = get_fpstatus_ptr(1); - fn_gvec_ptr = a->size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah; - tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd), - vfp_reg_offset(1, a->vn), - vfp_reg_offset(1, a->vm), - fpst, opr_sz, opr_sz, a->rot, - fn_gvec_ptr); - tcg_temp_free_ptr(fpst); - return true; -} - -static bool trans_VCADD(DisasContext *s, arg_VCADD *a) -{ - int opr_sz; - TCGv_ptr fpst; - gen_helper_gvec_3_ptr *fn_gvec_ptr; - - if (!dc_isar_feature(aa32_vcma, s) - || (!a->size && !dc_isar_feature(aa32_fp16_arith, s))) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist. */ - if (!dc_isar_feature(aa32_simd_r32, s) && - ((a->vd | a->vn | a->vm) & 0x10)) { - return false; - } - - if ((a->vn | a->vm | a->vd) & a->q) { - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - opr_sz = (1 + a->q) * 8; - fpst = get_fpstatus_ptr(1); - fn_gvec_ptr = a->size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh; - tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd), - vfp_reg_offset(1, a->vn), - vfp_reg_offset(1, a->vm), - fpst, opr_sz, opr_sz, a->rot, - fn_gvec_ptr); - tcg_temp_free_ptr(fpst); - return true; -} - -static bool trans_VDOT(DisasContext *s, arg_VDOT *a) -{ - int opr_sz; - gen_helper_gvec_3 *fn_gvec; - - if (!dc_isar_feature(aa32_dp, s)) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist. */ - if (!dc_isar_feature(aa32_simd_r32, s) && - ((a->vd | a->vn | a->vm) & 0x10)) { - return false; - } - - if ((a->vn | a->vm | a->vd) & a->q) { - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - opr_sz = (1 + a->q) * 8; - fn_gvec = a->u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b; - tcg_gen_gvec_3_ool(vfp_reg_offset(1, a->vd), - vfp_reg_offset(1, a->vn), - vfp_reg_offset(1, a->vm), - opr_sz, opr_sz, 0, fn_gvec); - return true; -} - -static bool trans_VFML(DisasContext *s, arg_VFML *a) -{ - int opr_sz; - - if (!dc_isar_feature(aa32_fhm, s)) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist. */ - if (!dc_isar_feature(aa32_simd_r32, s) && - (a->vd & 0x10)) { - return false; - } - - if (a->vd & a->q) { - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - opr_sz = (1 + a->q) * 8; - tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd), - vfp_reg_offset(a->q, a->vn), - vfp_reg_offset(a->q, a->vm), - cpu_env, opr_sz, opr_sz, a->s, /* is_2 == 0 */ - gen_helper_gvec_fmlal_a32); - return true; -} - -static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a) -{ - gen_helper_gvec_3_ptr *fn_gvec_ptr; - int opr_sz; - TCGv_ptr fpst; - - if (!dc_isar_feature(aa32_vcma, s)) { - return false; - } - if (a->size == 0 && !dc_isar_feature(aa32_fp16_arith, s)) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist. */ - if (!dc_isar_feature(aa32_simd_r32, s) && - ((a->vd | a->vn | a->vm) & 0x10)) { - return false; - } - - if ((a->vd | a->vn) & a->q) { - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - fn_gvec_ptr = (a->size ? gen_helper_gvec_fcmlas_idx - : gen_helper_gvec_fcmlah_idx); - opr_sz = (1 + a->q) * 8; - fpst = get_fpstatus_ptr(1); - tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd), - vfp_reg_offset(1, a->vn), - vfp_reg_offset(1, a->vm), - fpst, opr_sz, opr_sz, - (a->index << 2) | a->rot, fn_gvec_ptr); - tcg_temp_free_ptr(fpst); - return true; -} - -static bool trans_VDOT_scalar(DisasContext *s, arg_VDOT_scalar *a) -{ - gen_helper_gvec_3 *fn_gvec; - int opr_sz; - TCGv_ptr fpst; - - if (!dc_isar_feature(aa32_dp, s)) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist. */ - if (!dc_isar_feature(aa32_simd_r32, s) && - ((a->vd | a->vn) & 0x10)) { - return false; - } - - if ((a->vd | a->vn) & a->q) { - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - fn_gvec = a->u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b; - opr_sz = (1 + a->q) * 8; - fpst = get_fpstatus_ptr(1); - tcg_gen_gvec_3_ool(vfp_reg_offset(1, a->vd), - vfp_reg_offset(1, a->vn), - vfp_reg_offset(1, a->rm), - opr_sz, opr_sz, a->index, fn_gvec); - tcg_temp_free_ptr(fpst); - return true; -} - -static bool trans_VFML_scalar(DisasContext *s, arg_VFML_scalar *a) -{ - int opr_sz; - - if (!dc_isar_feature(aa32_fhm, s)) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist. */ - if (!dc_isar_feature(aa32_simd_r32, s) && - ((a->vd & 0x10) || (a->q && (a->vn & 0x10)))) { - return false; - } - - if (a->vd & a->q) { - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - opr_sz = (1 + a->q) * 8; - tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd), - vfp_reg_offset(a->q, a->vn), - vfp_reg_offset(a->q, a->rm), - cpu_env, opr_sz, opr_sz, - (a->index << 2) | a->s, /* is_2 == 0 */ - gen_helper_gvec_fmlal_idx_a32); - return true; -} - -static struct { - int nregs; - int interleave; - int spacing; -} const neon_ls_element_type[11] = { - {1, 4, 1}, - {1, 4, 2}, - {4, 1, 1}, - {2, 2, 2}, - {1, 3, 1}, - {1, 3, 2}, - {3, 1, 1}, - {1, 1, 1}, - {1, 2, 1}, - {1, 2, 2}, - {2, 1, 1} -}; - -static void gen_neon_ldst_base_update(DisasContext *s, int rm, int rn, - int stride) -{ - if (rm != 15) { - TCGv_i32 base; - - base = load_reg(s, rn); - if (rm == 13) { - tcg_gen_addi_i32(base, base, stride); - } else { - TCGv_i32 index; - index = load_reg(s, rm); - tcg_gen_add_i32(base, base, index); - tcg_temp_free_i32(index); - } - store_reg(s, rn, base); - } -} - -static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a) -{ - /* Neon load/store multiple structures */ - int nregs, interleave, spacing, reg, n; - MemOp endian = s->be_data; - int mmu_idx = get_mem_index(s); - int size = a->size; - TCGv_i64 tmp64; - TCGv_i32 addr, tmp; - - if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist */ - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) { - return false; - } - if (a->itype > 10) { - return false; - } - /* Catch UNDEF cases for bad values of align field */ - switch (a->itype & 0xc) { - case 4: - if (a->align >= 2) { - return false; - } - break; - case 8: - if (a->align == 3) { - return false; - } - break; - default: - break; - } - nregs = neon_ls_element_type[a->itype].nregs; - interleave = neon_ls_element_type[a->itype].interleave; - spacing = neon_ls_element_type[a->itype].spacing; - if (size == 3 && (interleave | spacing) != 1) { - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - /* For our purposes, bytes are always little-endian. */ - if (size == 0) { - endian = MO_LE; - } - /* - * Consecutive little-endian elements from a single register - * can be promoted to a larger little-endian operation. - */ - if (interleave == 1 && endian == MO_LE) { - size = 3; - } - tmp64 = tcg_temp_new_i64(); - addr = tcg_temp_new_i32(); - tmp = tcg_const_i32(1 << size); - load_reg_var(s, addr, a->rn); - for (reg = 0; reg < nregs; reg++) { - for (n = 0; n < 8 >> size; n++) { - int xs; - for (xs = 0; xs < interleave; xs++) { - int tt = a->vd + reg + spacing * xs; - - if (a->l) { - gen_aa32_ld_i64(s, tmp64, addr, mmu_idx, endian | size); - neon_store_element64(tt, n, size, tmp64); - } else { - neon_load_element64(tmp64, tt, n, size); - gen_aa32_st_i64(s, tmp64, addr, mmu_idx, endian | size); - } - tcg_gen_add_i32(addr, addr, tmp); - } - } - } - tcg_temp_free_i32(addr); - tcg_temp_free_i32(tmp); - tcg_temp_free_i64(tmp64); - - gen_neon_ldst_base_update(s, a->rm, a->rn, nregs * interleave * 8); - return true; -} - -static bool trans_VLD_all_lanes(DisasContext *s, arg_VLD_all_lanes *a) -{ - /* Neon load single structure to all lanes */ - int reg, stride, vec_size; - int vd = a->vd; - int size = a->size; - int nregs = a->n + 1; - TCGv_i32 addr, tmp; - - if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist */ - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) { - return false; - } - - if (size == 3) { - if (nregs != 4 || a->a == 0) { - return false; - } - /* For VLD4 size == 3 a == 1 means 32 bits at 16 byte alignment */ - size = 2; - } - if (nregs == 1 && a->a == 1 && size == 0) { - return false; - } - if (nregs == 3 && a->a == 1) { - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - /* - * VLD1 to all lanes: T bit indicates how many Dregs to write. - * VLD2/3/4 to all lanes: T bit indicates register stride. - */ - stride = a->t ? 2 : 1; - vec_size = nregs == 1 ? stride * 8 : 8; - - tmp = tcg_temp_new_i32(); - addr = tcg_temp_new_i32(); - load_reg_var(s, addr, a->rn); - for (reg = 0; reg < nregs; reg++) { - gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), - s->be_data | size); - if ((vd & 1) && vec_size == 16) { - /* - * We cannot write 16 bytes at once because the - * destination is unaligned. - */ - tcg_gen_gvec_dup_i32(size, neon_reg_offset(vd, 0), - 8, 8, tmp); - tcg_gen_gvec_mov(0, neon_reg_offset(vd + 1, 0), - neon_reg_offset(vd, 0), 8, 8); - } else { - tcg_gen_gvec_dup_i32(size, neon_reg_offset(vd, 0), - vec_size, vec_size, tmp); - } - tcg_gen_addi_i32(addr, addr, 1 << size); - vd += stride; - } - tcg_temp_free_i32(tmp); - tcg_temp_free_i32(addr); - - gen_neon_ldst_base_update(s, a->rm, a->rn, (1 << size) * nregs); - - return true; -} - -static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a) -{ - /* Neon load/store single structure to one lane */ - int reg; - int nregs = a->n + 1; - int vd = a->vd; - TCGv_i32 addr, tmp; - - if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist */ - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) { - return false; - } - - /* Catch the UNDEF cases. This is unavoidably a bit messy. */ - switch (nregs) { - case 1: - if (((a->align & (1 << a->size)) != 0) || - (a->size == 2 && ((a->align & 3) == 1 || (a->align & 3) == 2))) { - return false; - } - break; - case 3: - if ((a->align & 1) != 0) { - return false; - } - /* fall through */ - case 2: - if (a->size == 2 && (a->align & 2) != 0) { - return false; - } - break; - case 4: - if ((a->size == 2) && ((a->align & 3) == 3)) { - return false; - } - break; - default: - abort(); - } - if ((vd + a->stride * (nregs - 1)) > 31) { - /* - * Attempts to write off the end of the register file are - * UNPREDICTABLE; we choose to UNDEF because otherwise we would - * access off the end of the array that holds the register data. - */ - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - tmp = tcg_temp_new_i32(); - addr = tcg_temp_new_i32(); - load_reg_var(s, addr, a->rn); - /* - * TODO: if we implemented alignment exceptions, we should check - * addr against the alignment encoded in a->align here. - */ - for (reg = 0; reg < nregs; reg++) { - if (a->l) { - gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), - s->be_data | a->size); - neon_store_element(vd, a->reg_idx, a->size, tmp); - } else { /* Store */ - neon_load_element(tmp, vd, a->reg_idx, a->size); - gen_aa32_st_i32(s, tmp, addr, get_mem_index(s), - s->be_data | a->size); - } - vd += a->stride; - tcg_gen_addi_i32(addr, addr, 1 << a->size); - } - tcg_temp_free_i32(addr); - tcg_temp_free_i32(tmp); - - gen_neon_ldst_base_update(s, a->rm, a->rn, (1 << a->size) * nregs); - - return true; -} - -static bool do_3same(DisasContext *s, arg_3same *a, GVecGen3Fn fn) -{ - int vec_size = a->q ? 16 : 8; - int rd_ofs = neon_reg_offset(a->vd, 0); - int rn_ofs = neon_reg_offset(a->vn, 0); - int rm_ofs = neon_reg_offset(a->vm, 0); - - if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist. */ - if (!dc_isar_feature(aa32_simd_r32, s) && - ((a->vd | a->vn | a->vm) & 0x10)) { - return false; - } - - if ((a->vn | a->vm | a->vd) & a->q) { - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - fn(a->size, rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size); - return true; -} - -#define DO_3SAME(INSN, FUNC) \ - static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ - { \ - return do_3same(s, a, FUNC); \ - } - -DO_3SAME(VADD, tcg_gen_gvec_add) -DO_3SAME(VSUB, tcg_gen_gvec_sub) -DO_3SAME(VAND, tcg_gen_gvec_and) -DO_3SAME(VBIC, tcg_gen_gvec_andc) -DO_3SAME(VORR, tcg_gen_gvec_or) -DO_3SAME(VORN, tcg_gen_gvec_orc) -DO_3SAME(VEOR, tcg_gen_gvec_xor) -DO_3SAME(VSHL_S, gen_gvec_sshl) -DO_3SAME(VSHL_U, gen_gvec_ushl) -DO_3SAME(VQADD_S, gen_gvec_sqadd_qc) -DO_3SAME(VQADD_U, gen_gvec_uqadd_qc) -DO_3SAME(VQSUB_S, gen_gvec_sqsub_qc) -DO_3SAME(VQSUB_U, gen_gvec_uqsub_qc) - -/* These insns are all gvec_bitsel but with the inputs in various orders. */ -#define DO_3SAME_BITSEL(INSN, O1, O2, O3) \ - static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ - uint32_t rn_ofs, uint32_t rm_ofs, \ - uint32_t oprsz, uint32_t maxsz) \ - { \ - tcg_gen_gvec_bitsel(vece, rd_ofs, O1, O2, O3, oprsz, maxsz); \ - } \ - DO_3SAME(INSN, gen_##INSN##_3s) - -DO_3SAME_BITSEL(VBSL, rd_ofs, rn_ofs, rm_ofs) -DO_3SAME_BITSEL(VBIT, rm_ofs, rn_ofs, rd_ofs) -DO_3SAME_BITSEL(VBIF, rm_ofs, rd_ofs, rn_ofs) - -#define DO_3SAME_NO_SZ_3(INSN, FUNC) \ - static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ - { \ - if (a->size == 3) { \ - return false; \ - } \ - return do_3same(s, a, FUNC); \ - } - -DO_3SAME_NO_SZ_3(VMAX_S, tcg_gen_gvec_smax) -DO_3SAME_NO_SZ_3(VMAX_U, tcg_gen_gvec_umax) -DO_3SAME_NO_SZ_3(VMIN_S, tcg_gen_gvec_smin) -DO_3SAME_NO_SZ_3(VMIN_U, tcg_gen_gvec_umin) -DO_3SAME_NO_SZ_3(VMUL, tcg_gen_gvec_mul) -DO_3SAME_NO_SZ_3(VMLA, gen_gvec_mla) -DO_3SAME_NO_SZ_3(VMLS, gen_gvec_mls) -DO_3SAME_NO_SZ_3(VTST, gen_gvec_cmtst) -DO_3SAME_NO_SZ_3(VABD_S, gen_gvec_sabd) -DO_3SAME_NO_SZ_3(VABA_S, gen_gvec_saba) -DO_3SAME_NO_SZ_3(VABD_U, gen_gvec_uabd) -DO_3SAME_NO_SZ_3(VABA_U, gen_gvec_uaba) - -#define DO_3SAME_CMP(INSN, COND) \ - static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ - uint32_t rn_ofs, uint32_t rm_ofs, \ - uint32_t oprsz, uint32_t maxsz) \ - { \ - tcg_gen_gvec_cmp(COND, vece, rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz); \ - } \ - DO_3SAME_NO_SZ_3(INSN, gen_##INSN##_3s) - -DO_3SAME_CMP(VCGT_S, TCG_COND_GT) -DO_3SAME_CMP(VCGT_U, TCG_COND_GTU) -DO_3SAME_CMP(VCGE_S, TCG_COND_GE) -DO_3SAME_CMP(VCGE_U, TCG_COND_GEU) -DO_3SAME_CMP(VCEQ, TCG_COND_EQ) - -static void gen_VMUL_p_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, - uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz) -{ - tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, - 0, gen_helper_gvec_pmul_b); -} - -static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a) -{ - if (a->size != 0) { - return false; - } - return do_3same(s, a, gen_VMUL_p_3s); -} - -#define DO_VQRDMLAH(INSN, FUNC) \ - static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ - { \ - if (!dc_isar_feature(aa32_rdm, s)) { \ - return false; \ - } \ - if (a->size != 1 && a->size != 2) { \ - return false; \ - } \ - return do_3same(s, a, FUNC); \ - } - -DO_VQRDMLAH(VQRDMLAH, gen_gvec_sqrdmlah_qc) -DO_VQRDMLAH(VQRDMLSH, gen_gvec_sqrdmlsh_qc) - -static bool trans_SHA1_3s(DisasContext *s, arg_SHA1_3s *a) -{ - TCGv_ptr ptr1, ptr2, ptr3; - TCGv_i32 tmp; - - if (!arm_dc_feature(s, ARM_FEATURE_NEON) || - !dc_isar_feature(aa32_sha1, s)) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist. */ - if (!dc_isar_feature(aa32_simd_r32, s) && - ((a->vd | a->vn | a->vm) & 0x10)) { - return false; - } - - if ((a->vn | a->vm | a->vd) & 1) { - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - ptr1 = vfp_reg_ptr(true, a->vd); - ptr2 = vfp_reg_ptr(true, a->vn); - ptr3 = vfp_reg_ptr(true, a->vm); - tmp = tcg_const_i32(a->optype); - gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp); - tcg_temp_free_i32(tmp); - tcg_temp_free_ptr(ptr1); - tcg_temp_free_ptr(ptr2); - tcg_temp_free_ptr(ptr3); - - return true; -} - -static bool trans_SHA256H_3s(DisasContext *s, arg_SHA256H_3s *a) -{ - TCGv_ptr ptr1, ptr2, ptr3; - - if (!arm_dc_feature(s, ARM_FEATURE_NEON) || - !dc_isar_feature(aa32_sha2, s)) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist. */ - if (!dc_isar_feature(aa32_simd_r32, s) && - ((a->vd | a->vn | a->vm) & 0x10)) { - return false; - } - - if ((a->vn | a->vm | a->vd) & 1) { - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - ptr1 = vfp_reg_ptr(true, a->vd); - ptr2 = vfp_reg_ptr(true, a->vn); - ptr3 = vfp_reg_ptr(true, a->vm); - gen_helper_crypto_sha256h(ptr1, ptr2, ptr3); - tcg_temp_free_ptr(ptr1); - tcg_temp_free_ptr(ptr2); - tcg_temp_free_ptr(ptr3); - - return true; -} - -static bool trans_SHA256H2_3s(DisasContext *s, arg_SHA256H2_3s *a) -{ - TCGv_ptr ptr1, ptr2, ptr3; - - if (!arm_dc_feature(s, ARM_FEATURE_NEON) || - !dc_isar_feature(aa32_sha2, s)) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist. */ - if (!dc_isar_feature(aa32_simd_r32, s) && - ((a->vd | a->vn | a->vm) & 0x10)) { - return false; - } - - if ((a->vn | a->vm | a->vd) & 1) { - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - ptr1 = vfp_reg_ptr(true, a->vd); - ptr2 = vfp_reg_ptr(true, a->vn); - ptr3 = vfp_reg_ptr(true, a->vm); - gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3); - tcg_temp_free_ptr(ptr1); - tcg_temp_free_ptr(ptr2); - tcg_temp_free_ptr(ptr3); - - return true; -} - -static bool trans_SHA256SU1_3s(DisasContext *s, arg_SHA256SU1_3s *a) -{ - TCGv_ptr ptr1, ptr2, ptr3; - - if (!arm_dc_feature(s, ARM_FEATURE_NEON) || - !dc_isar_feature(aa32_sha2, s)) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist. */ - if (!dc_isar_feature(aa32_simd_r32, s) && - ((a->vd | a->vn | a->vm) & 0x10)) { - return false; - } - - if ((a->vn | a->vm | a->vd) & 1) { - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - ptr1 = vfp_reg_ptr(true, a->vd); - ptr2 = vfp_reg_ptr(true, a->vn); - ptr3 = vfp_reg_ptr(true, a->vm); - gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3); - tcg_temp_free_ptr(ptr1); - tcg_temp_free_ptr(ptr2); - tcg_temp_free_ptr(ptr3); - - return true; -} - -#define DO_3SAME_64(INSN, FUNC) \ - static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ - uint32_t rn_ofs, uint32_t rm_ofs, \ - uint32_t oprsz, uint32_t maxsz) \ - { \ - static const GVecGen3 op = { .fni8 = FUNC }; \ - tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &op); \ - } \ - DO_3SAME(INSN, gen_##INSN##_3s) - -#define DO_3SAME_64_ENV(INSN, FUNC) \ - static void gen_##INSN##_elt(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m) \ - { \ - FUNC(d, cpu_env, n, m); \ - } \ - DO_3SAME_64(INSN, gen_##INSN##_elt) - -DO_3SAME_64(VRSHL_S64, gen_helper_neon_rshl_s64) -DO_3SAME_64(VRSHL_U64, gen_helper_neon_rshl_u64) -DO_3SAME_64_ENV(VQSHL_S64, gen_helper_neon_qshl_s64) -DO_3SAME_64_ENV(VQSHL_U64, gen_helper_neon_qshl_u64) -DO_3SAME_64_ENV(VQRSHL_S64, gen_helper_neon_qrshl_s64) -DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64) - -#define DO_3SAME_32(INSN, FUNC) \ - static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ - uint32_t rn_ofs, uint32_t rm_ofs, \ - uint32_t oprsz, uint32_t maxsz) \ - { \ - static const GVecGen3 ops[4] = { \ - { .fni4 = gen_helper_neon_##FUNC##8 }, \ - { .fni4 = gen_helper_neon_##FUNC##16 }, \ - { .fni4 = gen_helper_neon_##FUNC##32 }, \ - { 0 }, \ - }; \ - tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece]); \ - } \ - static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ - { \ - if (a->size > 2) { \ - return false; \ - } \ - return do_3same(s, a, gen_##INSN##_3s); \ - } - -/* - * Some helper functions need to be passed the cpu_env. In order - * to use those with the gvec APIs like tcg_gen_gvec_3() we need - * to create wrapper functions whose prototype is a NeonGenTwoOpFn() - * and which call a NeonGenTwoOpEnvFn(). - */ -#define WRAP_ENV_FN(WRAPNAME, FUNC) \ - static void WRAPNAME(TCGv_i32 d, TCGv_i32 n, TCGv_i32 m) \ - { \ - FUNC(d, cpu_env, n, m); \ - } - -#define DO_3SAME_32_ENV(INSN, FUNC) \ - WRAP_ENV_FN(gen_##INSN##_tramp8, gen_helper_neon_##FUNC##8); \ - WRAP_ENV_FN(gen_##INSN##_tramp16, gen_helper_neon_##FUNC##16); \ - WRAP_ENV_FN(gen_##INSN##_tramp32, gen_helper_neon_##FUNC##32); \ - static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ - uint32_t rn_ofs, uint32_t rm_ofs, \ - uint32_t oprsz, uint32_t maxsz) \ - { \ - static const GVecGen3 ops[4] = { \ - { .fni4 = gen_##INSN##_tramp8 }, \ - { .fni4 = gen_##INSN##_tramp16 }, \ - { .fni4 = gen_##INSN##_tramp32 }, \ - { 0 }, \ - }; \ - tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece]); \ - } \ - static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ - { \ - if (a->size > 2) { \ - return false; \ - } \ - return do_3same(s, a, gen_##INSN##_3s); \ - } - -DO_3SAME_32(VHADD_S, hadd_s) -DO_3SAME_32(VHADD_U, hadd_u) -DO_3SAME_32(VHSUB_S, hsub_s) -DO_3SAME_32(VHSUB_U, hsub_u) -DO_3SAME_32(VRHADD_S, rhadd_s) -DO_3SAME_32(VRHADD_U, rhadd_u) -DO_3SAME_32(VRSHL_S, rshl_s) -DO_3SAME_32(VRSHL_U, rshl_u) - -DO_3SAME_32_ENV(VQSHL_S, qshl_s) -DO_3SAME_32_ENV(VQSHL_U, qshl_u) -DO_3SAME_32_ENV(VQRSHL_S, qrshl_s) -DO_3SAME_32_ENV(VQRSHL_U, qrshl_u) - -static bool do_3same_pair(DisasContext *s, arg_3same *a, NeonGenTwoOpFn *fn) -{ - /* Operations handled pairwise 32 bits at a time */ - TCGv_i32 tmp, tmp2, tmp3; - - if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist. */ - if (!dc_isar_feature(aa32_simd_r32, s) && - ((a->vd | a->vn | a->vm) & 0x10)) { - return false; - } - - if (a->size == 3) { - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - assert(a->q == 0); /* enforced by decode patterns */ - - /* - * Note that we have to be careful not to clobber the source operands - * in the "vm == vd" case by storing the result of the first pass too - * early. Since Q is 0 there are always just two passes, so instead - * of a complicated loop over each pass we just unroll. - */ - tmp = neon_load_reg(a->vn, 0); - tmp2 = neon_load_reg(a->vn, 1); - fn(tmp, tmp, tmp2); - tcg_temp_free_i32(tmp2); - - tmp3 = neon_load_reg(a->vm, 0); - tmp2 = neon_load_reg(a->vm, 1); - fn(tmp3, tmp3, tmp2); - tcg_temp_free_i32(tmp2); - - neon_store_reg(a->vd, 0, tmp); - neon_store_reg(a->vd, 1, tmp3); - return true; -} - -#define DO_3SAME_PAIR(INSN, func) \ - static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ - { \ - static NeonGenTwoOpFn * const fns[] = { \ - gen_helper_neon_##func##8, \ - gen_helper_neon_##func##16, \ - gen_helper_neon_##func##32, \ - }; \ - if (a->size > 2) { \ - return false; \ - } \ - return do_3same_pair(s, a, fns[a->size]); \ - } - -/* 32-bit pairwise ops end up the same as the elementwise versions. */ -#define gen_helper_neon_pmax_s32 tcg_gen_smax_i32 -#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32 -#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32 -#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32 -#define gen_helper_neon_padd_u32 tcg_gen_add_i32 - -DO_3SAME_PAIR(VPMAX_S, pmax_s) -DO_3SAME_PAIR(VPMIN_S, pmin_s) -DO_3SAME_PAIR(VPMAX_U, pmax_u) -DO_3SAME_PAIR(VPMIN_U, pmin_u) -DO_3SAME_PAIR(VPADD, padd_u) - -#define DO_3SAME_VQDMULH(INSN, FUNC) \ - WRAP_ENV_FN(gen_##INSN##_tramp16, gen_helper_neon_##FUNC##_s16); \ - WRAP_ENV_FN(gen_##INSN##_tramp32, gen_helper_neon_##FUNC##_s32); \ - static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ - uint32_t rn_ofs, uint32_t rm_ofs, \ - uint32_t oprsz, uint32_t maxsz) \ - { \ - static const GVecGen3 ops[2] = { \ - { .fni4 = gen_##INSN##_tramp16 }, \ - { .fni4 = gen_##INSN##_tramp32 }, \ - }; \ - tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece - 1]); \ - } \ - static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \ - { \ - if (a->size != 1 && a->size != 2) { \ - return false; \ - } \ - return do_3same(s, a, gen_##INSN##_3s); \ - } - -DO_3SAME_VQDMULH(VQDMULH, qdmulh) -DO_3SAME_VQDMULH(VQRDMULH, qrdmulh) - -static bool do_3same_fp(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn, - bool reads_vd) -{ - /* - * FP operations handled elementwise 32 bits at a time. - * If reads_vd is true then the old value of Vd will be - * loaded before calling the callback function. This is - * used for multiply-accumulate type operations. - */ - TCGv_i32 tmp, tmp2; - int pass; - - if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist. */ - if (!dc_isar_feature(aa32_simd_r32, s) && - ((a->vd | a->vn | a->vm) & 0x10)) { - return false; - } - - if ((a->vn | a->vm | a->vd) & a->q) { - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - TCGv_ptr fpstatus = get_fpstatus_ptr(1); - for (pass = 0; pass < (a->q ? 4 : 2); pass++) { - tmp = neon_load_reg(a->vn, pass); - tmp2 = neon_load_reg(a->vm, pass); - if (reads_vd) { - TCGv_i32 tmp_rd = neon_load_reg(a->vd, pass); - fn(tmp_rd, tmp, tmp2, fpstatus); - neon_store_reg(a->vd, pass, tmp_rd); - tcg_temp_free_i32(tmp); - } else { - fn(tmp, tmp, tmp2, fpstatus); - neon_store_reg(a->vd, pass, tmp); - } - tcg_temp_free_i32(tmp2); - } - tcg_temp_free_ptr(fpstatus); - return true; -} - -/* - * For all the functions using this macro, size == 1 means fp16, - * which is an architecture extension we don't implement yet. - */ -#define DO_3S_FP_GVEC(INSN,FUNC) \ - static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ - uint32_t rn_ofs, uint32_t rm_ofs, \ - uint32_t oprsz, uint32_t maxsz) \ - { \ - TCGv_ptr fpst = get_fpstatus_ptr(1); \ - tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, fpst, \ - oprsz, maxsz, 0, FUNC); \ - tcg_temp_free_ptr(fpst); \ - } \ - static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \ - { \ - if (a->size != 0) { \ - /* TODO fp16 support */ \ - return false; \ - } \ - return do_3same(s, a, gen_##INSN##_3s); \ - } - - -DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s) -DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s) -DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s) -DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s) - -/* - * For all the functions using this macro, size == 1 means fp16, - * which is an architecture extension we don't implement yet. - */ -#define DO_3S_FP(INSN,FUNC,READS_VD) \ - static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \ - { \ - if (a->size != 0) { \ - /* TODO fp16 support */ \ - return false; \ - } \ - return do_3same_fp(s, a, FUNC, READS_VD); \ - } - -DO_3S_FP(VCEQ, gen_helper_neon_ceq_f32, false) -DO_3S_FP(VCGE, gen_helper_neon_cge_f32, false) -DO_3S_FP(VCGT, gen_helper_neon_cgt_f32, false) -DO_3S_FP(VACGE, gen_helper_neon_acge_f32, false) -DO_3S_FP(VACGT, gen_helper_neon_acgt_f32, false) -DO_3S_FP(VMAX, gen_helper_vfp_maxs, false) -DO_3S_FP(VMIN, gen_helper_vfp_mins, false) - -static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, - TCGv_ptr fpstatus) -{ - gen_helper_vfp_muls(vn, vn, vm, fpstatus); - gen_helper_vfp_adds(vd, vd, vn, fpstatus); -} - -static void gen_VMLS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, - TCGv_ptr fpstatus) -{ - gen_helper_vfp_muls(vn, vn, vm, fpstatus); - gen_helper_vfp_subs(vd, vd, vn, fpstatus); -} - -DO_3S_FP(VMLA, gen_VMLA_fp_3s, true) -DO_3S_FP(VMLS, gen_VMLS_fp_3s, true) - -static bool trans_VMAXNM_fp_3s(DisasContext *s, arg_3same *a) -{ - if (!arm_dc_feature(s, ARM_FEATURE_V8)) { - return false; - } - - if (a->size != 0) { - /* TODO fp16 support */ - return false; - } - - return do_3same_fp(s, a, gen_helper_vfp_maxnums, false); -} - -static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a) -{ - if (!arm_dc_feature(s, ARM_FEATURE_V8)) { - return false; - } - - if (a->size != 0) { - /* TODO fp16 support */ - return false; - } - - return do_3same_fp(s, a, gen_helper_vfp_minnums, false); -} - -WRAP_ENV_FN(gen_VRECPS_tramp, gen_helper_recps_f32) - -static void gen_VRECPS_fp_3s(unsigned vece, uint32_t rd_ofs, - uint32_t rn_ofs, uint32_t rm_ofs, - uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen3 ops = { .fni4 = gen_VRECPS_tramp }; - tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops); -} - -static bool trans_VRECPS_fp_3s(DisasContext *s, arg_3same *a) -{ - if (a->size != 0) { - /* TODO fp16 support */ - return false; - } - - return do_3same(s, a, gen_VRECPS_fp_3s); -} - -WRAP_ENV_FN(gen_VRSQRTS_tramp, gen_helper_rsqrts_f32) - -static void gen_VRSQRTS_fp_3s(unsigned vece, uint32_t rd_ofs, - uint32_t rn_ofs, uint32_t rm_ofs, - uint32_t oprsz, uint32_t maxsz) -{ - static const GVecGen3 ops = { .fni4 = gen_VRSQRTS_tramp }; - tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops); -} - -static bool trans_VRSQRTS_fp_3s(DisasContext *s, arg_3same *a) -{ - if (a->size != 0) { - /* TODO fp16 support */ - return false; - } - - return do_3same(s, a, gen_VRSQRTS_fp_3s); -} - -static void gen_VFMA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, - TCGv_ptr fpstatus) -{ - gen_helper_vfp_muladds(vd, vn, vm, vd, fpstatus); -} - -static bool trans_VFMA_fp_3s(DisasContext *s, arg_3same *a) -{ - if (!dc_isar_feature(aa32_simdfmac, s)) { - return false; - } - - if (a->size != 0) { - /* TODO fp16 support */ - return false; - } - - return do_3same_fp(s, a, gen_VFMA_fp_3s, true); -} - -static void gen_VFMS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, - TCGv_ptr fpstatus) -{ - gen_helper_vfp_negs(vn, vn); - gen_helper_vfp_muladds(vd, vn, vm, vd, fpstatus); -} - -static bool trans_VFMS_fp_3s(DisasContext *s, arg_3same *a) -{ - if (!dc_isar_feature(aa32_simdfmac, s)) { - return false; - } - - if (a->size != 0) { - /* TODO fp16 support */ - return false; - } - - return do_3same_fp(s, a, gen_VFMS_fp_3s, true); -} - -static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn) -{ - /* FP operations handled pairwise 32 bits at a time */ - TCGv_i32 tmp, tmp2, tmp3; - TCGv_ptr fpstatus; - - if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { - return false; - } - - /* UNDEF accesses to D16-D31 if they don't exist. */ - if (!dc_isar_feature(aa32_simd_r32, s) && - ((a->vd | a->vn | a->vm) & 0x10)) { - return false; - } - - if (!vfp_access_check(s)) { - return true; - } - - assert(a->q == 0); /* enforced by decode patterns */ - - /* - * Note that we have to be careful not to clobber the source operands - * in the "vm == vd" case by storing the result of the first pass too - * early. Since Q is 0 there are always just two passes, so instead - * of a complicated loop over each pass we just unroll. - */ - fpstatus = get_fpstatus_ptr(1); - tmp = neon_load_reg(a->vn, 0); - tmp2 = neon_load_reg(a->vn, 1); - fn(tmp, tmp, tmp2, fpstatus); - tcg_temp_free_i32(tmp2); - - tmp3 = neon_load_reg(a->vm, 0); - tmp2 = neon_load_reg(a->vm, 1); - fn(tmp3, tmp3, tmp2, fpstatus); - tcg_temp_free_i32(tmp2); - tcg_temp_free_ptr(fpstatus); - - neon_store_reg(a->vd, 0, tmp); - neon_store_reg(a->vd, 1, tmp3); - return true; -} - -/* - * For all the functions using this macro, size == 1 means fp16, - * which is an architecture extension we don't implement yet. - */ -#define DO_3S_FP_PAIR(INSN,FUNC) \ - static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \ - { \ - if (a->size != 0) { \ - /* TODO fp16 support */ \ - return false; \ - } \ - return do_3same_fp_pair(s, a, FUNC); \ - } - -DO_3S_FP_PAIR(VPADD, gen_helper_vfp_adds) -DO_3S_FP_PAIR(VPMAX, gen_helper_vfp_maxs) -DO_3S_FP_PAIR(VPMIN, gen_helper_vfp_mins) diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c index ac7b3119e5fa1408fe9198c332bedcac33bc8cbb..0c3a6d21210404a1340e58c9a02178e7fa048d5b 100644 --- a/target/arm/translate-sve.c +++ b/target/arm/translate-sve.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -100,7 +100,7 @@ static inline int msz_dtype(DisasContext *s, int msz) * Include the generated decoder. */ -#include "decode-sve.inc.c" +#include "decode-sve.c.inc" /* * Implement all of the translator functions referenced by the decoder. @@ -142,35 +142,76 @@ static int pred_gvec_reg_size(DisasContext *s) return size_for_gvec(pred_full_reg_size(s)); } +/* Invoke an out-of-line helper on 2 Zregs. */ +static void gen_gvec_ool_zz(DisasContext *s, gen_helper_gvec_2 *fn, + int rd, int rn, int data) +{ + unsigned vsz = vec_full_reg_size(s); + tcg_gen_gvec_2_ool(vec_full_reg_offset(s, rd), + vec_full_reg_offset(s, rn), + vsz, vsz, data, fn); +} + +/* Invoke an out-of-line helper on 3 Zregs. */ +static void gen_gvec_ool_zzz(DisasContext *s, gen_helper_gvec_3 *fn, + int rd, int rn, int rm, int data) +{ + unsigned vsz = vec_full_reg_size(s); + tcg_gen_gvec_3_ool(vec_full_reg_offset(s, rd), + vec_full_reg_offset(s, rn), + vec_full_reg_offset(s, rm), + vsz, vsz, data, fn); +} + +/* Invoke an out-of-line helper on 2 Zregs and a predicate. */ +static void gen_gvec_ool_zzp(DisasContext *s, gen_helper_gvec_3 *fn, + int rd, int rn, int pg, int data) +{ + unsigned vsz = vec_full_reg_size(s); + tcg_gen_gvec_3_ool(vec_full_reg_offset(s, rd), + vec_full_reg_offset(s, rn), + pred_full_reg_offset(s, pg), + vsz, vsz, data, fn); +} + +/* Invoke an out-of-line helper on 3 Zregs and a predicate. */ +static void gen_gvec_ool_zzzp(DisasContext *s, gen_helper_gvec_4 *fn, + int rd, int rn, int rm, int pg, int data) +{ + unsigned vsz = vec_full_reg_size(s); + tcg_gen_gvec_4_ool(vec_full_reg_offset(s, rd), + vec_full_reg_offset(s, rn), + vec_full_reg_offset(s, rm), + pred_full_reg_offset(s, pg), + vsz, vsz, data, fn); +} + /* Invoke a vector expander on two Zregs. */ -static bool do_vector2_z(DisasContext *s, GVecGen2Fn *gvec_fn, - int esz, int rd, int rn) +static void gen_gvec_fn_zz(DisasContext *s, GVecGen2Fn *gvec_fn, + int esz, int rd, int rn) { - if (sve_access_check(s)) { - unsigned vsz = vec_full_reg_size(s); - gvec_fn(esz, vec_full_reg_offset(s, rd), - vec_full_reg_offset(s, rn), vsz, vsz); - } - return true; + unsigned vsz = vec_full_reg_size(s); + gvec_fn(esz, vec_full_reg_offset(s, rd), + vec_full_reg_offset(s, rn), vsz, vsz); } /* Invoke a vector expander on three Zregs. */ -static bool do_vector3_z(DisasContext *s, GVecGen3Fn *gvec_fn, - int esz, int rd, int rn, int rm) +static void gen_gvec_fn_zzz(DisasContext *s, GVecGen3Fn *gvec_fn, + int esz, int rd, int rn, int rm) { - if (sve_access_check(s)) { - unsigned vsz = vec_full_reg_size(s); - gvec_fn(esz, vec_full_reg_offset(s, rd), - vec_full_reg_offset(s, rn), - vec_full_reg_offset(s, rm), vsz, vsz); - } - return true; + unsigned vsz = vec_full_reg_size(s); + gvec_fn(esz, vec_full_reg_offset(s, rd), + vec_full_reg_offset(s, rn), + vec_full_reg_offset(s, rm), vsz, vsz); } /* Invoke a vector move on two Zregs. */ static bool do_mov_z(DisasContext *s, int rd, int rn) { - return do_vector2_z(s, tcg_gen_gvec_mov, 0, rd, rn); + if (sve_access_check(s)) { + gen_gvec_fn_zz(s, tcg_gen_gvec_mov, MO_8, rd, rn); + } + return true; } /* Initialize a Zreg with replications of a 64-bit immediate. */ @@ -180,52 +221,27 @@ static void do_dupi_z(DisasContext *s, int rd, uint64_t word) tcg_gen_gvec_dup_imm(MO_64, vec_full_reg_offset(s, rd), vsz, vsz, word); } -/* Invoke a vector expander on two Pregs. */ -static bool do_vector2_p(DisasContext *s, GVecGen2Fn *gvec_fn, - int esz, int rd, int rn) -{ - if (sve_access_check(s)) { - unsigned psz = pred_gvec_reg_size(s); - gvec_fn(esz, pred_full_reg_offset(s, rd), - pred_full_reg_offset(s, rn), psz, psz); - } - return true; -} - /* Invoke a vector expander on three Pregs. */ -static bool do_vector3_p(DisasContext *s, GVecGen3Fn *gvec_fn, - int esz, int rd, int rn, int rm) +static void gen_gvec_fn_ppp(DisasContext *s, GVecGen3Fn *gvec_fn, + int rd, int rn, int rm) { - if (sve_access_check(s)) { - unsigned psz = pred_gvec_reg_size(s); - gvec_fn(esz, pred_full_reg_offset(s, rd), - pred_full_reg_offset(s, rn), - pred_full_reg_offset(s, rm), psz, psz); - } - return true; + unsigned psz = pred_gvec_reg_size(s); + gvec_fn(MO_64, pred_full_reg_offset(s, rd), + pred_full_reg_offset(s, rn), + pred_full_reg_offset(s, rm), psz, psz); } -/* Invoke a vector operation on four Pregs. */ -static bool do_vecop4_p(DisasContext *s, const GVecGen4 *gvec_op, - int rd, int rn, int rm, int rg) +/* Invoke a vector move on two Pregs. */ +static bool do_mov_p(DisasContext *s, int rd, int rn) { if (sve_access_check(s)) { unsigned psz = pred_gvec_reg_size(s); - tcg_gen_gvec_4(pred_full_reg_offset(s, rd), - pred_full_reg_offset(s, rn), - pred_full_reg_offset(s, rm), - pred_full_reg_offset(s, rg), - psz, psz, gvec_op); + tcg_gen_gvec_mov(MO_8, pred_full_reg_offset(s, rd), + pred_full_reg_offset(s, rn), psz, psz); } return true; } -/* Invoke a vector move on two Pregs. */ -static bool do_mov_p(DisasContext *s, int rd, int rn) -{ - return do_vector2_p(s, tcg_gen_gvec_mov, 0, rd, rn); -} - /* Set the cpu flags as per a return from an SVE helper. */ static void do_pred_flags(TCGv_i32 t) { @@ -273,24 +289,32 @@ const uint64_t pred_esz_masks[4] = { *** SVE Logical - Unpredicated Group */ +static bool do_zzz_fn(DisasContext *s, arg_rrr_esz *a, GVecGen3Fn *gvec_fn) +{ + if (sve_access_check(s)) { + gen_gvec_fn_zzz(s, gvec_fn, a->esz, a->rd, a->rn, a->rm); + } + return true; +} + static bool trans_AND_zzz(DisasContext *s, arg_rrr_esz *a) { - return do_vector3_z(s, tcg_gen_gvec_and, 0, a->rd, a->rn, a->rm); + return do_zzz_fn(s, a, tcg_gen_gvec_and); } static bool trans_ORR_zzz(DisasContext *s, arg_rrr_esz *a) { - return do_vector3_z(s, tcg_gen_gvec_or, 0, a->rd, a->rn, a->rm); + return do_zzz_fn(s, a, tcg_gen_gvec_or); } static bool trans_EOR_zzz(DisasContext *s, arg_rrr_esz *a) { - return do_vector3_z(s, tcg_gen_gvec_xor, 0, a->rd, a->rn, a->rm); + return do_zzz_fn(s, a, tcg_gen_gvec_xor); } static bool trans_BIC_zzz(DisasContext *s, arg_rrr_esz *a) { - return do_vector3_z(s, tcg_gen_gvec_andc, 0, a->rd, a->rn, a->rm); + return do_zzz_fn(s, a, tcg_gen_gvec_andc); } /* @@ -299,32 +323,32 @@ static bool trans_BIC_zzz(DisasContext *s, arg_rrr_esz *a) static bool trans_ADD_zzz(DisasContext *s, arg_rrr_esz *a) { - return do_vector3_z(s, tcg_gen_gvec_add, a->esz, a->rd, a->rn, a->rm); + return do_zzz_fn(s, a, tcg_gen_gvec_add); } static bool trans_SUB_zzz(DisasContext *s, arg_rrr_esz *a) { - return do_vector3_z(s, tcg_gen_gvec_sub, a->esz, a->rd, a->rn, a->rm); + return do_zzz_fn(s, a, tcg_gen_gvec_sub); } static bool trans_SQADD_zzz(DisasContext *s, arg_rrr_esz *a) { - return do_vector3_z(s, tcg_gen_gvec_ssadd, a->esz, a->rd, a->rn, a->rm); + return do_zzz_fn(s, a, tcg_gen_gvec_ssadd); } static bool trans_SQSUB_zzz(DisasContext *s, arg_rrr_esz *a) { - return do_vector3_z(s, tcg_gen_gvec_sssub, a->esz, a->rd, a->rn, a->rm); + return do_zzz_fn(s, a, tcg_gen_gvec_sssub); } static bool trans_UQADD_zzz(DisasContext *s, arg_rrr_esz *a) { - return do_vector3_z(s, tcg_gen_gvec_usadd, a->esz, a->rd, a->rn, a->rm); + return do_zzz_fn(s, a, tcg_gen_gvec_usadd); } static bool trans_UQSUB_zzz(DisasContext *s, arg_rrr_esz *a) { - return do_vector3_z(s, tcg_gen_gvec_ussub, a->esz, a->rd, a->rn, a->rm); + return do_zzz_fn(s, a, tcg_gen_gvec_ussub); } /* @@ -333,16 +357,11 @@ static bool trans_UQSUB_zzz(DisasContext *s, arg_rrr_esz *a) static bool do_zpzz_ool(DisasContext *s, arg_rprr_esz *a, gen_helper_gvec_4 *fn) { - unsigned vsz = vec_full_reg_size(s); if (fn == NULL) { return false; } if (sve_access_check(s)) { - tcg_gen_gvec_4_ool(vec_full_reg_offset(s, a->rd), - vec_full_reg_offset(s, a->rn), - vec_full_reg_offset(s, a->rm), - pred_full_reg_offset(s, a->pg), - vsz, vsz, 0, fn); + gen_gvec_ool_zzzp(s, fn, a->rd, a->rn, a->rm, a->pg, 0); } return true; } @@ -356,12 +375,7 @@ static void do_sel_z(DisasContext *s, int rd, int rn, int rm, int pg, int esz) gen_helper_sve_sel_zpzz_b, gen_helper_sve_sel_zpzz_h, gen_helper_sve_sel_zpzz_s, gen_helper_sve_sel_zpzz_d }; - unsigned vsz = vec_full_reg_size(s); - tcg_gen_gvec_4_ool(vec_full_reg_offset(s, rd), - vec_full_reg_offset(s, rn), - vec_full_reg_offset(s, rm), - pred_full_reg_offset(s, pg), - vsz, vsz, 0, fns[esz]); + gen_gvec_ool_zzzp(s, fns[esz], rd, rn, rm, pg, 0); } #define DO_ZPZZ(NAME, name) \ @@ -433,11 +447,7 @@ static bool do_zpz_ool(DisasContext *s, arg_rpr_esz *a, gen_helper_gvec_3 *fn) return false; } if (sve_access_check(s)) { - unsigned vsz = vec_full_reg_size(s); - tcg_gen_gvec_3_ool(vec_full_reg_offset(s, a->rd), - vec_full_reg_offset(s, a->rn), - pred_full_reg_offset(s, a->pg), - vsz, vsz, 0, fn); + gen_gvec_ool_zzp(s, fn, a->rd, a->rn, a->pg, 0); } return true; } @@ -608,48 +618,29 @@ static bool trans_SADDV(DisasContext *s, arg_rpr_esz *a) *** SVE Shift by Immediate - Predicated Group */ -/* Store zero into every active element of Zd. We will use this for two - * and three-operand predicated instructions for which logic dictates a - * zero result. +/* + * Copy Zn into Zd, storing zeros into inactive elements. + * If invert, store zeros into the active elements. */ -static bool do_clr_zp(DisasContext *s, int rd, int pg, int esz) -{ - static gen_helper_gvec_2 * const fns[4] = { - gen_helper_sve_clr_b, gen_helper_sve_clr_h, - gen_helper_sve_clr_s, gen_helper_sve_clr_d, - }; - if (sve_access_check(s)) { - unsigned vsz = vec_full_reg_size(s); - tcg_gen_gvec_2_ool(vec_full_reg_offset(s, rd), - pred_full_reg_offset(s, pg), - vsz, vsz, 0, fns[esz]); - } - return true; -} - -/* Copy Zn into Zd, storing zeros into inactive elements. */ -static void do_movz_zpz(DisasContext *s, int rd, int rn, int pg, int esz) +static bool do_movz_zpz(DisasContext *s, int rd, int rn, int pg, + int esz, bool invert) { static gen_helper_gvec_3 * const fns[4] = { gen_helper_sve_movz_b, gen_helper_sve_movz_h, gen_helper_sve_movz_s, gen_helper_sve_movz_d, }; - unsigned vsz = vec_full_reg_size(s); - tcg_gen_gvec_3_ool(vec_full_reg_offset(s, rd), - vec_full_reg_offset(s, rn), - pred_full_reg_offset(s, pg), - vsz, vsz, 0, fns[esz]); + + if (sve_access_check(s)) { + gen_gvec_ool_zzp(s, fns[esz], rd, rn, pg, invert); + } + return true; } static bool do_zpzi_ool(DisasContext *s, arg_rpri_esz *a, gen_helper_gvec_3 *fn) { if (sve_access_check(s)) { - unsigned vsz = vec_full_reg_size(s); - tcg_gen_gvec_3_ool(vec_full_reg_offset(s, a->rd), - vec_full_reg_offset(s, a->rn), - pred_full_reg_offset(s, a->pg), - vsz, vsz, a->imm, fn); + gen_gvec_ool_zzp(s, fn, a->rd, a->rn, a->pg, a->imm); } return true; } @@ -682,7 +673,7 @@ static bool trans_LSR_zpzi(DisasContext *s, arg_rpri_esz *a) /* Shift by element size is architecturally valid. For logical shifts, it is a zeroing operation. */ if (a->imm >= (8 << a->esz)) { - return do_clr_zp(s, a->rd, a->pg, a->esz); + return do_movz_zpz(s, a->rd, a->rd, a->pg, a->esz, true); } else { return do_zpzi_ool(s, a, fns[a->esz]); } @@ -700,7 +691,7 @@ static bool trans_LSL_zpzi(DisasContext *s, arg_rpri_esz *a) /* Shift by element size is architecturally valid. For logical shifts, it is a zeroing operation. */ if (a->imm >= (8 << a->esz)) { - return do_clr_zp(s, a->rd, a->pg, a->esz); + return do_movz_zpz(s, a->rd, a->rd, a->pg, a->esz, true); } else { return do_zpzi_ool(s, a, fns[a->esz]); } @@ -718,7 +709,7 @@ static bool trans_ASRD(DisasContext *s, arg_rpri_esz *a) /* Shift by element size is architecturally valid. For arithmetic right shift for division, it is a zeroing operation. */ if (a->imm >= (8 << a->esz)) { - return do_clr_zp(s, a->rd, a->pg, a->esz); + return do_movz_zpz(s, a->rd, a->rd, a->pg, a->esz, true); } else { return do_zpzi_ool(s, a, fns[a->esz]); } @@ -799,11 +790,7 @@ static bool do_zzw_ool(DisasContext *s, arg_rrr_esz *a, gen_helper_gvec_3 *fn) return false; } if (sve_access_check(s)) { - unsigned vsz = vec_full_reg_size(s); - tcg_gen_gvec_3_ool(vec_full_reg_offset(s, a->rd), - vec_full_reg_offset(s, a->rn), - vec_full_reg_offset(s, a->rm), - vsz, vsz, 0, fn); + gen_gvec_ool_zzz(s, fn, a->rd, a->rn, a->rm, 0); } return true; } @@ -977,11 +964,7 @@ static bool trans_RDVL(DisasContext *s, arg_RDVL *a) static bool do_adr(DisasContext *s, arg_rrri *a, gen_helper_gvec_3 *fn) { if (sve_access_check(s)) { - unsigned vsz = vec_full_reg_size(s); - tcg_gen_gvec_3_ool(vec_full_reg_offset(s, a->rd), - vec_full_reg_offset(s, a->rn), - vec_full_reg_offset(s, a->rm), - vsz, vsz, a->imm, fn); + gen_gvec_ool_zzz(s, fn, a->rd, a->rn, a->rm, a->imm); } return true; } @@ -1022,10 +1005,7 @@ static bool trans_FEXPA(DisasContext *s, arg_rr_esz *a) return false; } if (sve_access_check(s)) { - unsigned vsz = vec_full_reg_size(s); - tcg_gen_gvec_2_ool(vec_full_reg_offset(s, a->rd), - vec_full_reg_offset(s, a->rn), - vsz, vsz, 0, fns[a->esz]); + gen_gvec_ool_zz(s, fns[a->esz], a->rd, a->rn, 0); } return true; } @@ -1042,11 +1022,7 @@ static bool trans_FTSSEL(DisasContext *s, arg_rrr_esz *a) return false; } if (sve_access_check(s)) { - unsigned vsz = vec_full_reg_size(s); - tcg_gen_gvec_3_ool(vec_full_reg_offset(s, a->rd), - vec_full_reg_offset(s, a->rn), - vec_full_reg_offset(s, a->rm), - vsz, vsz, 0, fns[a->esz]); + gen_gvec_ool_zzz(s, fns[a->esz], a->rd, a->rn, a->rm, 0); } return true; } @@ -1068,6 +1044,11 @@ static bool do_pppp_flags(DisasContext *s, arg_rprr_s *a, int mofs = pred_full_reg_offset(s, a->rm); int gofs = pred_full_reg_offset(s, a->pg); + if (!a->s) { + tcg_gen_gvec_4(dofs, nofs, mofs, gofs, psz, psz, gvec_op); + return true; + } + if (psz == 8) { /* Do the operation and the flags generation in temps. */ TCGv_i64 pd = tcg_temp_new_i64(); @@ -1127,19 +1108,24 @@ static bool trans_AND_pppp(DisasContext *s, arg_rprr_s *a) .fno = gen_helper_sve_and_pppp, .prefer_i64 = TCG_TARGET_REG_BITS == 64, }; - if (a->s) { - return do_pppp_flags(s, a, &op); - } else if (a->rn == a->rm) { - if (a->pg == a->rn) { - return do_mov_p(s, a->rd, a->rn); - } else { - return do_vector3_p(s, tcg_gen_gvec_and, 0, a->rd, a->rn, a->pg); + + if (!a->s) { + if (!sve_access_check(s)) { + return true; + } + if (a->rn == a->rm) { + if (a->pg == a->rn) { + do_mov_p(s, a->rd, a->rn); + } else { + gen_gvec_fn_ppp(s, tcg_gen_gvec_and, a->rd, a->rn, a->pg); + } + return true; + } else if (a->pg == a->rn || a->pg == a->rm) { + gen_gvec_fn_ppp(s, tcg_gen_gvec_and, a->rd, a->rn, a->rm); + return true; } - } else if (a->pg == a->rn || a->pg == a->rm) { - return do_vector3_p(s, tcg_gen_gvec_and, 0, a->rd, a->rn, a->rm); - } else { - return do_vecop4_p(s, &op, a->rd, a->rn, a->rm, a->pg); } + return do_pppp_flags(s, a, &op); } static void gen_bic_pg_i64(TCGv_i64 pd, TCGv_i64 pn, TCGv_i64 pm, TCGv_i64 pg) @@ -1163,13 +1149,14 @@ static bool trans_BIC_pppp(DisasContext *s, arg_rprr_s *a) .fno = gen_helper_sve_bic_pppp, .prefer_i64 = TCG_TARGET_REG_BITS == 64, }; - if (a->s) { - return do_pppp_flags(s, a, &op); - } else if (a->pg == a->rn) { - return do_vector3_p(s, tcg_gen_gvec_andc, 0, a->rd, a->rn, a->rm); - } else { - return do_vecop4_p(s, &op, a->rd, a->rn, a->rm, a->pg); + + if (!a->s && a->pg == a->rn) { + if (sve_access_check(s)) { + gen_gvec_fn_ppp(s, tcg_gen_gvec_andc, a->rd, a->rn, a->rm); + } + return true; } + return do_pppp_flags(s, a, &op); } static void gen_eor_pg_i64(TCGv_i64 pd, TCGv_i64 pn, TCGv_i64 pm, TCGv_i64 pg) @@ -1193,41 +1180,22 @@ static bool trans_EOR_pppp(DisasContext *s, arg_rprr_s *a) .fno = gen_helper_sve_eor_pppp, .prefer_i64 = TCG_TARGET_REG_BITS == 64, }; - if (a->s) { - return do_pppp_flags(s, a, &op); - } else { - return do_vecop4_p(s, &op, a->rd, a->rn, a->rm, a->pg); - } -} - -static void gen_sel_pg_i64(TCGv_i64 pd, TCGv_i64 pn, TCGv_i64 pm, TCGv_i64 pg) -{ - tcg_gen_and_i64(pn, pn, pg); - tcg_gen_andc_i64(pm, pm, pg); - tcg_gen_or_i64(pd, pn, pm); -} - -static void gen_sel_pg_vec(unsigned vece, TCGv_vec pd, TCGv_vec pn, - TCGv_vec pm, TCGv_vec pg) -{ - tcg_gen_and_vec(vece, pn, pn, pg); - tcg_gen_andc_vec(vece, pm, pm, pg); - tcg_gen_or_vec(vece, pd, pn, pm); + return do_pppp_flags(s, a, &op); } static bool trans_SEL_pppp(DisasContext *s, arg_rprr_s *a) { - static const GVecGen4 op = { - .fni8 = gen_sel_pg_i64, - .fniv = gen_sel_pg_vec, - .fno = gen_helper_sve_sel_pppp, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - }; if (a->s) { return false; - } else { - return do_vecop4_p(s, &op, a->rd, a->rn, a->rm, a->pg); } + if (sve_access_check(s)) { + unsigned psz = pred_gvec_reg_size(s); + tcg_gen_gvec_bitsel(MO_8, pred_full_reg_offset(s, a->rd), + pred_full_reg_offset(s, a->pg), + pred_full_reg_offset(s, a->rn), + pred_full_reg_offset(s, a->rm), psz, psz); + } + return true; } static void gen_orr_pg_i64(TCGv_i64 pd, TCGv_i64 pn, TCGv_i64 pm, TCGv_i64 pg) @@ -1251,13 +1219,11 @@ static bool trans_ORR_pppp(DisasContext *s, arg_rprr_s *a) .fno = gen_helper_sve_orr_pppp, .prefer_i64 = TCG_TARGET_REG_BITS == 64, }; - if (a->s) { - return do_pppp_flags(s, a, &op); - } else if (a->pg == a->rn && a->rn == a->rm) { + + if (!a->s && a->pg == a->rn && a->rn == a->rm) { return do_mov_p(s, a->rd, a->rn); - } else { - return do_vecop4_p(s, &op, a->rd, a->rn, a->rm, a->pg); } + return do_pppp_flags(s, a, &op); } static void gen_orn_pg_i64(TCGv_i64 pd, TCGv_i64 pn, TCGv_i64 pm, TCGv_i64 pg) @@ -1281,11 +1247,7 @@ static bool trans_ORN_pppp(DisasContext *s, arg_rprr_s *a) .fno = gen_helper_sve_orn_pppp, .prefer_i64 = TCG_TARGET_REG_BITS == 64, }; - if (a->s) { - return do_pppp_flags(s, a, &op); - } else { - return do_vecop4_p(s, &op, a->rd, a->rn, a->rm, a->pg); - } + return do_pppp_flags(s, a, &op); } static void gen_nor_pg_i64(TCGv_i64 pd, TCGv_i64 pn, TCGv_i64 pm, TCGv_i64 pg) @@ -1309,11 +1271,7 @@ static bool trans_NOR_pppp(DisasContext *s, arg_rprr_s *a) .fno = gen_helper_sve_nor_pppp, .prefer_i64 = TCG_TARGET_REG_BITS == 64, }; - if (a->s) { - return do_pppp_flags(s, a, &op); - } else { - return do_vecop4_p(s, &op, a->rd, a->rn, a->rm, a->pg); - } + return do_pppp_flags(s, a, &op); } static void gen_nand_pg_i64(TCGv_i64 pd, TCGv_i64 pn, TCGv_i64 pm, TCGv_i64 pg) @@ -1337,11 +1295,7 @@ static bool trans_NAND_pppp(DisasContext *s, arg_rprr_s *a) .fno = gen_helper_sve_nand_pppp, .prefer_i64 = TCG_TARGET_REG_BITS == 64, }; - if (a->s) { - return do_pppp_flags(s, a, &op); - } else { - return do_vecop4_p(s, &op, a->rd, a->rn, a->rm, a->pg); - } + return do_pppp_flags(s, a, &op); } /* @@ -2103,10 +2057,7 @@ static bool trans_REV_v(DisasContext *s, arg_rr_esz *a) }; if (sve_access_check(s)) { - unsigned vsz = vec_full_reg_size(s); - tcg_gen_gvec_2_ool(vec_full_reg_offset(s, a->rd), - vec_full_reg_offset(s, a->rn), - vsz, vsz, 0, fns[a->esz]); + gen_gvec_ool_zz(s, fns[a->esz], a->rd, a->rn, 0); } return true; } @@ -2119,11 +2070,7 @@ static bool trans_TBL(DisasContext *s, arg_rrr_esz *a) }; if (sve_access_check(s)) { - unsigned vsz = vec_full_reg_size(s); - tcg_gen_gvec_3_ool(vec_full_reg_offset(s, a->rd), - vec_full_reg_offset(s, a->rn), - vec_full_reg_offset(s, a->rm), - vsz, vsz, 0, fns[a->esz]); + gen_gvec_ool_zzz(s, fns[a->esz], a->rd, a->rn, a->rm, 0); } return true; } @@ -2296,11 +2243,7 @@ static bool do_zzz_data_ool(DisasContext *s, arg_rrr_esz *a, int data, gen_helper_gvec_3 *fn) { if (sve_access_check(s)) { - unsigned vsz = vec_full_reg_size(s); - tcg_gen_gvec_3_ool(vec_full_reg_offset(s, a->rd), - vec_full_reg_offset(s, a->rn), - vec_full_reg_offset(s, a->rm), - vsz, vsz, data, fn); + gen_gvec_ool_zzz(s, fn, a->rd, a->rn, a->rm, data); } return true; } @@ -2745,12 +2688,8 @@ static bool trans_RBIT(DisasContext *s, arg_rpr_esz *a) static bool trans_SPLICE(DisasContext *s, arg_rprr_esz *a) { if (sve_access_check(s)) { - unsigned vsz = vec_full_reg_size(s); - tcg_gen_gvec_4_ool(vec_full_reg_offset(s, a->rd), - vec_full_reg_offset(s, a->rn), - vec_full_reg_offset(s, a->rm), - pred_full_reg_offset(s, a->pg), - vsz, vsz, a->esz, gen_helper_sve_splice); + gen_gvec_ool_zzzp(s, gen_helper_sve_splice, + a->rd, a->rn, a->rm, a->pg, a->esz); } return true; } @@ -3429,11 +3368,7 @@ static bool trans_DOT_zzz(DisasContext *s, arg_DOT_zzz *a) }; if (sve_access_check(s)) { - unsigned vsz = vec_full_reg_size(s); - tcg_gen_gvec_3_ool(vec_full_reg_offset(s, a->rd), - vec_full_reg_offset(s, a->rn), - vec_full_reg_offset(s, a->rm), - vsz, vsz, 0, fns[a->u][a->sz]); + gen_gvec_ool_zzz(s, fns[a->u][a->sz], a->rd, a->rn, a->rm, 0); } return true; } @@ -3446,11 +3381,7 @@ static bool trans_DOT_zzx(DisasContext *s, arg_DOT_zzx *a) }; if (sve_access_check(s)) { - unsigned vsz = vec_full_reg_size(s); - tcg_gen_gvec_3_ool(vec_full_reg_offset(s, a->rd), - vec_full_reg_offset(s, a->rn), - vec_full_reg_offset(s, a->rm), - vsz, vsz, a->index, fns[a->u][a->sz]); + gen_gvec_ool_zzz(s, fns[a->u][a->sz], a->rd, a->rn, a->rm, a->index); } return true; } @@ -3470,7 +3401,7 @@ static bool trans_FMLA_zzxz(DisasContext *s, arg_FMLA_zzxz *a) if (sve_access_check(s)) { unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_4_ptr(vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -3496,7 +3427,7 @@ static bool trans_FMUL_zzx(DisasContext *s, arg_FMUL_zzx *a) if (sve_access_check(s)) { unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -3528,7 +3459,7 @@ static void do_reduce(DisasContext *s, arg_rpr_esz *a, tcg_gen_addi_ptr(t_zn, cpu_env, vec_full_reg_offset(s, a->rn)); tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, a->pg)); - status = get_fpstatus_ptr(a->esz == MO_16); + status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); fn(temp, t_zn, t_pg, status, t_desc); tcg_temp_free_ptr(t_zn); @@ -3570,7 +3501,7 @@ DO_VPZ(FMAXV, fmaxv) static void do_zz_fp(DisasContext *s, arg_rr_esz *a, gen_helper_gvec_2_ptr *fn) { unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_2_ptr(vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), @@ -3618,7 +3549,7 @@ static void do_ppz_fp(DisasContext *s, arg_rpr_esz *a, gen_helper_gvec_3_ptr *fn) { unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_3_ptr(pred_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), @@ -3670,7 +3601,7 @@ static bool trans_FTMAD(DisasContext *s, arg_FTMAD *a) } if (sve_access_check(s)) { unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -3710,7 +3641,7 @@ static bool trans_FADDA(DisasContext *s, arg_rprr_esz *a) t_pg = tcg_temp_new_ptr(); tcg_gen_addi_ptr(t_rm, cpu_env, vec_full_reg_offset(s, a->rm)); tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, a->pg)); - t_fpst = get_fpstatus_ptr(a->esz == MO_16); + t_fpst = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); t_desc = tcg_const_i32(simd_desc(vsz, vsz, 0)); fns[a->esz - 1](t_val, t_val, t_rm, t_pg, t_fpst, t_desc); @@ -3737,7 +3668,7 @@ static bool do_zzz_fp(DisasContext *s, arg_rrr_esz *a, } if (sve_access_check(s)) { unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -3779,7 +3710,7 @@ static bool do_zpzz_fp(DisasContext *s, arg_rprr_esz *a, } if (sve_access_check(s)) { unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_4_ptr(vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -3831,7 +3762,7 @@ static void do_fp_scalar(DisasContext *s, int zd, int zn, int pg, bool is_fp16, tcg_gen_addi_ptr(t_zn, cpu_env, vec_full_reg_offset(s, zn)); tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg)); - status = get_fpstatus_ptr(is_fp16); + status = fpstatus_ptr(is_fp16 ? FPST_FPCR_F16 : FPST_FPCR); desc = tcg_const_i32(simd_desc(vsz, vsz, 0)); fn(t_zd, t_zn, t_pg, scalar, status, desc); @@ -3872,10 +3803,6 @@ static bool trans_##NAME##_zpzi(DisasContext *s, arg_rpri_esz *a) \ return true; \ } -#define float16_two make_float16(0x4000) -#define float32_two make_float32(0x40000000) -#define float64_two make_float64(0x4000000000000000ULL) - DO_FP_IMM(FADD, fadds, half, one) DO_FP_IMM(FSUB, fsubs, half, one) DO_FP_IMM(FMUL, fmuls, half, two) @@ -3895,7 +3822,7 @@ static bool do_fp_cmp(DisasContext *s, arg_rprr_esz *a, } if (sve_access_check(s)) { unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_4_ptr(pred_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -3939,7 +3866,7 @@ static bool trans_FCADD(DisasContext *s, arg_FCADD *a) } if (sve_access_check(s)) { unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_4_ptr(vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -3958,7 +3885,7 @@ static bool do_fmla(DisasContext *s, arg_rprrr_esz *a, } if (sve_access_check(s)) { unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_5_ptr(vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -4001,7 +3928,7 @@ static bool trans_FCMLA_zpzzz(DisasContext *s, arg_FCMLA_zpzzz *a) } if (sve_access_check(s)) { unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_5_ptr(vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -4024,7 +3951,7 @@ static bool trans_FCMLA_zzxz(DisasContext *s, arg_FCMLA_zzxz *a) tcg_debug_assert(a->rd == a->ra); if (sve_access_check(s)) { unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -4045,7 +3972,7 @@ static bool do_zpz_ptr(DisasContext *s, int rd, int rn, int pg, { if (sve_access_check(s)) { unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = get_fpstatus_ptr(is_fp16); + TCGv_ptr status = fpstatus_ptr(is_fp16 ? FPST_FPCR_F16 : FPST_FPCR); tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn), pred_full_reg_offset(s, pg), @@ -4191,7 +4118,7 @@ static bool do_frint_mode(DisasContext *s, arg_rpr_esz *a, int mode) if (sve_access_check(s)) { unsigned vsz = vec_full_reg_size(s); TCGv_i32 tmode = tcg_const_i32(mode); - TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16); + TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); gen_helper_set_rmode(tmode, tmode, status); @@ -4342,71 +4269,75 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm) int len_remain = len % 8; int nparts = len / 8 + ctpop8(len_remain); int midx = get_mem_index(s); - TCGv_i64 addr, t0, t1; + TCGv_i64 dirty_addr, clean_addr, t0, t1; - addr = tcg_temp_new_i64(); - t0 = tcg_temp_new_i64(); + dirty_addr = tcg_temp_new_i64(); + tcg_gen_addi_i64(dirty_addr, cpu_reg_sp(s, rn), imm); + clean_addr = gen_mte_checkN(s, dirty_addr, false, rn != 31, len, MO_8); + tcg_temp_free_i64(dirty_addr); - /* Note that unpredicated load/store of vector/predicate registers + /* + * Note that unpredicated load/store of vector/predicate registers * are defined as a stream of bytes, which equates to little-endian - * operations on larger quantities. There is no nice way to force - * a little-endian load for aarch64_be-linux-user out of line. - * + * operations on larger quantities. * Attempt to keep code expansion to a minimum by limiting the * amount of unrolling done. */ if (nparts <= 4) { int i; + t0 = tcg_temp_new_i64(); for (i = 0; i < len_align; i += 8) { - tcg_gen_addi_i64(addr, cpu_reg_sp(s, rn), imm + i); - tcg_gen_qemu_ld_i64(t0, addr, midx, MO_LEQ); + tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEQ); tcg_gen_st_i64(t0, cpu_env, vofs + i); + tcg_gen_addi_i64(clean_addr, clean_addr, 8); } + tcg_temp_free_i64(t0); } else { TCGLabel *loop = gen_new_label(); TCGv_ptr tp, i = tcg_const_local_ptr(0); - gen_set_label(loop); + /* Copy the clean address into a local temp, live across the loop. */ + t0 = clean_addr; + clean_addr = new_tmp_a64_local(s); + tcg_gen_mov_i64(clean_addr, t0); - /* Minimize the number of local temps that must be re-read from - * the stack each iteration. Instead, re-compute values other - * than the loop counter. - */ - tp = tcg_temp_new_ptr(); - tcg_gen_addi_ptr(tp, i, imm); - tcg_gen_extu_ptr_i64(addr, tp); - tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, rn)); + gen_set_label(loop); - tcg_gen_qemu_ld_i64(t0, addr, midx, MO_LEQ); + t0 = tcg_temp_new_i64(); + tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEQ); + tcg_gen_addi_i64(clean_addr, clean_addr, 8); + tp = tcg_temp_new_ptr(); tcg_gen_add_ptr(tp, cpu_env, i); tcg_gen_addi_ptr(i, i, 8); tcg_gen_st_i64(t0, tp, vofs); tcg_temp_free_ptr(tp); + tcg_temp_free_i64(t0); tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop); tcg_temp_free_ptr(i); } - /* Predicate register loads can be any multiple of 2. + /* + * Predicate register loads can be any multiple of 2. * Note that we still store the entire 64-bit unit into cpu_env. */ if (len_remain) { - tcg_gen_addi_i64(addr, cpu_reg_sp(s, rn), imm + len_align); - + t0 = tcg_temp_new_i64(); switch (len_remain) { case 2: case 4: case 8: - tcg_gen_qemu_ld_i64(t0, addr, midx, MO_LE | ctz32(len_remain)); + tcg_gen_qemu_ld_i64(t0, clean_addr, midx, + MO_LE | ctz32(len_remain)); break; case 6: t1 = tcg_temp_new_i64(); - tcg_gen_qemu_ld_i64(t0, addr, midx, MO_LEUL); - tcg_gen_addi_i64(addr, addr, 4); - tcg_gen_qemu_ld_i64(t1, addr, midx, MO_LEUW); + tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUL); + tcg_gen_addi_i64(clean_addr, clean_addr, 4); + tcg_gen_qemu_ld_i64(t1, clean_addr, midx, MO_LEUW); tcg_gen_deposit_i64(t0, t0, t1, 32, 32); tcg_temp_free_i64(t1); break; @@ -4415,9 +4346,8 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm) g_assert_not_reached(); } tcg_gen_st_i64(t0, cpu_env, vofs + len_align); + tcg_temp_free_i64(t0); } - tcg_temp_free_i64(addr); - tcg_temp_free_i64(t0); } /* Similarly for stores. */ @@ -4427,10 +4357,12 @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm) int len_remain = len % 8; int nparts = len / 8 + ctpop8(len_remain); int midx = get_mem_index(s); - TCGv_i64 addr, t0; + TCGv_i64 dirty_addr, clean_addr, t0; - addr = tcg_temp_new_i64(); - t0 = tcg_temp_new_i64(); + dirty_addr = tcg_temp_new_i64(); + tcg_gen_addi_i64(dirty_addr, cpu_reg_sp(s, rn), imm); + clean_addr = gen_mte_checkN(s, dirty_addr, false, rn != 31, len, MO_8); + tcg_temp_free_i64(dirty_addr); /* Note that unpredicated load/store of vector/predicate registers * are defined as a stream of bytes, which equates to little-endian @@ -4443,33 +4375,34 @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm) if (nparts <= 4) { int i; + t0 = tcg_temp_new_i64(); for (i = 0; i < len_align; i += 8) { tcg_gen_ld_i64(t0, cpu_env, vofs + i); - tcg_gen_addi_i64(addr, cpu_reg_sp(s, rn), imm + i); - tcg_gen_qemu_st_i64(t0, addr, midx, MO_LEQ); + tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEQ); + tcg_gen_addi_i64(clean_addr, clean_addr, 8); } + tcg_temp_free_i64(t0); } else { TCGLabel *loop = gen_new_label(); - TCGv_ptr t2, i = tcg_const_local_ptr(0); - - gen_set_label(loop); - - t2 = tcg_temp_new_ptr(); - tcg_gen_add_ptr(t2, cpu_env, i); - tcg_gen_ld_i64(t0, t2, vofs); + TCGv_ptr tp, i = tcg_const_local_ptr(0); - /* Minimize the number of local temps that must be re-read from - * the stack each iteration. Instead, re-compute values other - * than the loop counter. - */ - tcg_gen_addi_ptr(t2, i, imm); - tcg_gen_extu_ptr_i64(addr, t2); - tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, rn)); - tcg_temp_free_ptr(t2); + /* Copy the clean address into a local temp, live across the loop. */ + t0 = clean_addr; + clean_addr = new_tmp_a64_local(s); + tcg_gen_mov_i64(clean_addr, t0); - tcg_gen_qemu_st_i64(t0, addr, midx, MO_LEQ); + gen_set_label(loop); + t0 = tcg_temp_new_i64(); + tp = tcg_temp_new_ptr(); + tcg_gen_add_ptr(tp, cpu_env, i); + tcg_gen_ld_i64(t0, tp, vofs); tcg_gen_addi_ptr(i, i, 8); + tcg_temp_free_ptr(tp); + + tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEQ); + tcg_gen_addi_i64(clean_addr, clean_addr, 8); + tcg_temp_free_i64(t0); tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop); tcg_temp_free_ptr(i); @@ -4477,29 +4410,29 @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm) /* Predicate register stores can be any multiple of 2. */ if (len_remain) { + t0 = tcg_temp_new_i64(); tcg_gen_ld_i64(t0, cpu_env, vofs + len_align); - tcg_gen_addi_i64(addr, cpu_reg_sp(s, rn), imm + len_align); switch (len_remain) { case 2: case 4: case 8: - tcg_gen_qemu_st_i64(t0, addr, midx, MO_LE | ctz32(len_remain)); + tcg_gen_qemu_st_i64(t0, clean_addr, midx, + MO_LE | ctz32(len_remain)); break; case 6: - tcg_gen_qemu_st_i64(t0, addr, midx, MO_LEUL); - tcg_gen_addi_i64(addr, addr, 4); + tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUL); + tcg_gen_addi_i64(clean_addr, clean_addr, 4); tcg_gen_shri_i64(t0, t0, 32); - tcg_gen_qemu_st_i64(t0, addr, midx, MO_LEUW); + tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUW); break; default: g_assert_not_reached(); } + tcg_temp_free_i64(t0); } - tcg_temp_free_i64(addr); - tcg_temp_free_i64(t0); } static bool trans_LDR_zri(DisasContext *s, arg_rri *a) @@ -4565,18 +4498,34 @@ static const uint8_t dtype_esz[16] = { }; static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr, - int dtype, gen_helper_gvec_mem *fn) + int dtype, uint32_t mte_n, bool is_write, + gen_helper_gvec_mem *fn) { unsigned vsz = vec_full_reg_size(s); TCGv_ptr t_pg; TCGv_i32 t_desc; - int desc; + int desc = 0; - /* For e.g. LD4, there are not enough arguments to pass all 4 + /* + * For e.g. LD4, there are not enough arguments to pass all 4 * registers as pointers, so encode the regno into the data field. * For consistency, do this even for LD1. */ - desc = simd_desc(vsz, vsz, zt); + if (s->mte_active[0]) { + int msz = dtype_msz(dtype); + + desc = FIELD_DP32(desc, MTEDESC, MIDX, get_mem_index(s)); + desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid); + desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma); + desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write); + desc = FIELD_DP32(desc, MTEDESC, ESIZE, 1 << msz); + desc = FIELD_DP32(desc, MTEDESC, TSIZE, mte_n << msz); + desc <<= SVE_MTEDESC_SHIFT; + } else { + addr = clean_data_tbi(s, addr); + } + + desc = simd_desc(vsz, vsz, zt | desc); t_desc = tcg_const_i32(desc); t_pg = tcg_temp_new_ptr(); @@ -4590,64 +4539,132 @@ static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr, static void do_ld_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr, int dtype, int nreg) { - static gen_helper_gvec_mem * const fns[2][16][4] = { - /* Little-endian */ - { { gen_helper_sve_ld1bb_r, gen_helper_sve_ld2bb_r, - gen_helper_sve_ld3bb_r, gen_helper_sve_ld4bb_r }, - { gen_helper_sve_ld1bhu_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1bsu_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1bdu_r, NULL, NULL, NULL }, - - { gen_helper_sve_ld1sds_le_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1hh_le_r, gen_helper_sve_ld2hh_le_r, - gen_helper_sve_ld3hh_le_r, gen_helper_sve_ld4hh_le_r }, - { gen_helper_sve_ld1hsu_le_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1hdu_le_r, NULL, NULL, NULL }, - - { gen_helper_sve_ld1hds_le_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1hss_le_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1ss_le_r, gen_helper_sve_ld2ss_le_r, - gen_helper_sve_ld3ss_le_r, gen_helper_sve_ld4ss_le_r }, - { gen_helper_sve_ld1sdu_le_r, NULL, NULL, NULL }, - - { gen_helper_sve_ld1bds_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1bss_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1bhs_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1dd_le_r, gen_helper_sve_ld2dd_le_r, - gen_helper_sve_ld3dd_le_r, gen_helper_sve_ld4dd_le_r } }, - - /* Big-endian */ - { { gen_helper_sve_ld1bb_r, gen_helper_sve_ld2bb_r, + static gen_helper_gvec_mem * const fns[2][2][16][4] = { + { /* mte inactive, little-endian */ + { { gen_helper_sve_ld1bb_r, gen_helper_sve_ld2bb_r, gen_helper_sve_ld3bb_r, gen_helper_sve_ld4bb_r }, - { gen_helper_sve_ld1bhu_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1bsu_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1bdu_r, NULL, NULL, NULL }, - - { gen_helper_sve_ld1sds_be_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1hh_be_r, gen_helper_sve_ld2hh_be_r, - gen_helper_sve_ld3hh_be_r, gen_helper_sve_ld4hh_be_r }, - { gen_helper_sve_ld1hsu_be_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1hdu_be_r, NULL, NULL, NULL }, - - { gen_helper_sve_ld1hds_be_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1hss_be_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1ss_be_r, gen_helper_sve_ld2ss_be_r, - gen_helper_sve_ld3ss_be_r, gen_helper_sve_ld4ss_be_r }, - { gen_helper_sve_ld1sdu_be_r, NULL, NULL, NULL }, - - { gen_helper_sve_ld1bds_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1bss_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1bhs_r, NULL, NULL, NULL }, - { gen_helper_sve_ld1dd_be_r, gen_helper_sve_ld2dd_be_r, - gen_helper_sve_ld3dd_be_r, gen_helper_sve_ld4dd_be_r } } + { gen_helper_sve_ld1bhu_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1bsu_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1bdu_r, NULL, NULL, NULL }, + + { gen_helper_sve_ld1sds_le_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1hh_le_r, gen_helper_sve_ld2hh_le_r, + gen_helper_sve_ld3hh_le_r, gen_helper_sve_ld4hh_le_r }, + { gen_helper_sve_ld1hsu_le_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1hdu_le_r, NULL, NULL, NULL }, + + { gen_helper_sve_ld1hds_le_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1hss_le_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1ss_le_r, gen_helper_sve_ld2ss_le_r, + gen_helper_sve_ld3ss_le_r, gen_helper_sve_ld4ss_le_r }, + { gen_helper_sve_ld1sdu_le_r, NULL, NULL, NULL }, + + { gen_helper_sve_ld1bds_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1bss_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1bhs_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1dd_le_r, gen_helper_sve_ld2dd_le_r, + gen_helper_sve_ld3dd_le_r, gen_helper_sve_ld4dd_le_r } }, + + /* mte inactive, big-endian */ + { { gen_helper_sve_ld1bb_r, gen_helper_sve_ld2bb_r, + gen_helper_sve_ld3bb_r, gen_helper_sve_ld4bb_r }, + { gen_helper_sve_ld1bhu_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1bsu_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1bdu_r, NULL, NULL, NULL }, + + { gen_helper_sve_ld1sds_be_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1hh_be_r, gen_helper_sve_ld2hh_be_r, + gen_helper_sve_ld3hh_be_r, gen_helper_sve_ld4hh_be_r }, + { gen_helper_sve_ld1hsu_be_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1hdu_be_r, NULL, NULL, NULL }, + + { gen_helper_sve_ld1hds_be_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1hss_be_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1ss_be_r, gen_helper_sve_ld2ss_be_r, + gen_helper_sve_ld3ss_be_r, gen_helper_sve_ld4ss_be_r }, + { gen_helper_sve_ld1sdu_be_r, NULL, NULL, NULL }, + + { gen_helper_sve_ld1bds_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1bss_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1bhs_r, NULL, NULL, NULL }, + { gen_helper_sve_ld1dd_be_r, gen_helper_sve_ld2dd_be_r, + gen_helper_sve_ld3dd_be_r, gen_helper_sve_ld4dd_be_r } } }, + + { /* mte active, little-endian */ + { { gen_helper_sve_ld1bb_r_mte, + gen_helper_sve_ld2bb_r_mte, + gen_helper_sve_ld3bb_r_mte, + gen_helper_sve_ld4bb_r_mte }, + { gen_helper_sve_ld1bhu_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1bsu_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1bdu_r_mte, NULL, NULL, NULL }, + + { gen_helper_sve_ld1sds_le_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1hh_le_r_mte, + gen_helper_sve_ld2hh_le_r_mte, + gen_helper_sve_ld3hh_le_r_mte, + gen_helper_sve_ld4hh_le_r_mte }, + { gen_helper_sve_ld1hsu_le_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1hdu_le_r_mte, NULL, NULL, NULL }, + + { gen_helper_sve_ld1hds_le_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1hss_le_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1ss_le_r_mte, + gen_helper_sve_ld2ss_le_r_mte, + gen_helper_sve_ld3ss_le_r_mte, + gen_helper_sve_ld4ss_le_r_mte }, + { gen_helper_sve_ld1sdu_le_r_mte, NULL, NULL, NULL }, + + { gen_helper_sve_ld1bds_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1bss_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1bhs_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1dd_le_r_mte, + gen_helper_sve_ld2dd_le_r_mte, + gen_helper_sve_ld3dd_le_r_mte, + gen_helper_sve_ld4dd_le_r_mte } }, + + /* mte active, big-endian */ + { { gen_helper_sve_ld1bb_r_mte, + gen_helper_sve_ld2bb_r_mte, + gen_helper_sve_ld3bb_r_mte, + gen_helper_sve_ld4bb_r_mte }, + { gen_helper_sve_ld1bhu_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1bsu_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1bdu_r_mte, NULL, NULL, NULL }, + + { gen_helper_sve_ld1sds_be_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1hh_be_r_mte, + gen_helper_sve_ld2hh_be_r_mte, + gen_helper_sve_ld3hh_be_r_mte, + gen_helper_sve_ld4hh_be_r_mte }, + { gen_helper_sve_ld1hsu_be_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1hdu_be_r_mte, NULL, NULL, NULL }, + + { gen_helper_sve_ld1hds_be_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1hss_be_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1ss_be_r_mte, + gen_helper_sve_ld2ss_be_r_mte, + gen_helper_sve_ld3ss_be_r_mte, + gen_helper_sve_ld4ss_be_r_mte }, + { gen_helper_sve_ld1sdu_be_r_mte, NULL, NULL, NULL }, + + { gen_helper_sve_ld1bds_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1bss_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1bhs_r_mte, NULL, NULL, NULL }, + { gen_helper_sve_ld1dd_be_r_mte, + gen_helper_sve_ld2dd_be_r_mte, + gen_helper_sve_ld3dd_be_r_mte, + gen_helper_sve_ld4dd_be_r_mte } } }, }; - gen_helper_gvec_mem *fn = fns[s->be_data == MO_BE][dtype][nreg]; + gen_helper_gvec_mem *fn + = fns[s->mte_active[0]][s->be_data == MO_BE][dtype][nreg]; - /* While there are holes in the table, they are not + /* + * While there are holes in the table, they are not * accessible via the instruction encoding. */ assert(fn != NULL); - do_mem_zpa(s, zt, pg, addr, dtype, fn); + do_mem_zpa(s, zt, pg, addr, dtype, nreg, false, fn); } static bool trans_LD_zprr(DisasContext *s, arg_rprr_load *a) @@ -4681,104 +4698,188 @@ static bool trans_LD_zpri(DisasContext *s, arg_rpri_load *a) static bool trans_LDFF1_zprr(DisasContext *s, arg_rprr_load *a) { - static gen_helper_gvec_mem * const fns[2][16] = { - /* Little-endian */ - { gen_helper_sve_ldff1bb_r, - gen_helper_sve_ldff1bhu_r, - gen_helper_sve_ldff1bsu_r, - gen_helper_sve_ldff1bdu_r, - - gen_helper_sve_ldff1sds_le_r, - gen_helper_sve_ldff1hh_le_r, - gen_helper_sve_ldff1hsu_le_r, - gen_helper_sve_ldff1hdu_le_r, - - gen_helper_sve_ldff1hds_le_r, - gen_helper_sve_ldff1hss_le_r, - gen_helper_sve_ldff1ss_le_r, - gen_helper_sve_ldff1sdu_le_r, - - gen_helper_sve_ldff1bds_r, - gen_helper_sve_ldff1bss_r, - gen_helper_sve_ldff1bhs_r, - gen_helper_sve_ldff1dd_le_r }, - - /* Big-endian */ - { gen_helper_sve_ldff1bb_r, - gen_helper_sve_ldff1bhu_r, - gen_helper_sve_ldff1bsu_r, - gen_helper_sve_ldff1bdu_r, - - gen_helper_sve_ldff1sds_be_r, - gen_helper_sve_ldff1hh_be_r, - gen_helper_sve_ldff1hsu_be_r, - gen_helper_sve_ldff1hdu_be_r, - - gen_helper_sve_ldff1hds_be_r, - gen_helper_sve_ldff1hss_be_r, - gen_helper_sve_ldff1ss_be_r, - gen_helper_sve_ldff1sdu_be_r, - - gen_helper_sve_ldff1bds_r, - gen_helper_sve_ldff1bss_r, - gen_helper_sve_ldff1bhs_r, - gen_helper_sve_ldff1dd_be_r }, + static gen_helper_gvec_mem * const fns[2][2][16] = { + { /* mte inactive, little-endian */ + { gen_helper_sve_ldff1bb_r, + gen_helper_sve_ldff1bhu_r, + gen_helper_sve_ldff1bsu_r, + gen_helper_sve_ldff1bdu_r, + + gen_helper_sve_ldff1sds_le_r, + gen_helper_sve_ldff1hh_le_r, + gen_helper_sve_ldff1hsu_le_r, + gen_helper_sve_ldff1hdu_le_r, + + gen_helper_sve_ldff1hds_le_r, + gen_helper_sve_ldff1hss_le_r, + gen_helper_sve_ldff1ss_le_r, + gen_helper_sve_ldff1sdu_le_r, + + gen_helper_sve_ldff1bds_r, + gen_helper_sve_ldff1bss_r, + gen_helper_sve_ldff1bhs_r, + gen_helper_sve_ldff1dd_le_r }, + + /* mte inactive, big-endian */ + { gen_helper_sve_ldff1bb_r, + gen_helper_sve_ldff1bhu_r, + gen_helper_sve_ldff1bsu_r, + gen_helper_sve_ldff1bdu_r, + + gen_helper_sve_ldff1sds_be_r, + gen_helper_sve_ldff1hh_be_r, + gen_helper_sve_ldff1hsu_be_r, + gen_helper_sve_ldff1hdu_be_r, + + gen_helper_sve_ldff1hds_be_r, + gen_helper_sve_ldff1hss_be_r, + gen_helper_sve_ldff1ss_be_r, + gen_helper_sve_ldff1sdu_be_r, + + gen_helper_sve_ldff1bds_r, + gen_helper_sve_ldff1bss_r, + gen_helper_sve_ldff1bhs_r, + gen_helper_sve_ldff1dd_be_r } }, + + { /* mte active, little-endian */ + { gen_helper_sve_ldff1bb_r_mte, + gen_helper_sve_ldff1bhu_r_mte, + gen_helper_sve_ldff1bsu_r_mte, + gen_helper_sve_ldff1bdu_r_mte, + + gen_helper_sve_ldff1sds_le_r_mte, + gen_helper_sve_ldff1hh_le_r_mte, + gen_helper_sve_ldff1hsu_le_r_mte, + gen_helper_sve_ldff1hdu_le_r_mte, + + gen_helper_sve_ldff1hds_le_r_mte, + gen_helper_sve_ldff1hss_le_r_mte, + gen_helper_sve_ldff1ss_le_r_mte, + gen_helper_sve_ldff1sdu_le_r_mte, + + gen_helper_sve_ldff1bds_r_mte, + gen_helper_sve_ldff1bss_r_mte, + gen_helper_sve_ldff1bhs_r_mte, + gen_helper_sve_ldff1dd_le_r_mte }, + + /* mte active, big-endian */ + { gen_helper_sve_ldff1bb_r_mte, + gen_helper_sve_ldff1bhu_r_mte, + gen_helper_sve_ldff1bsu_r_mte, + gen_helper_sve_ldff1bdu_r_mte, + + gen_helper_sve_ldff1sds_be_r_mte, + gen_helper_sve_ldff1hh_be_r_mte, + gen_helper_sve_ldff1hsu_be_r_mte, + gen_helper_sve_ldff1hdu_be_r_mte, + + gen_helper_sve_ldff1hds_be_r_mte, + gen_helper_sve_ldff1hss_be_r_mte, + gen_helper_sve_ldff1ss_be_r_mte, + gen_helper_sve_ldff1sdu_be_r_mte, + + gen_helper_sve_ldff1bds_r_mte, + gen_helper_sve_ldff1bss_r_mte, + gen_helper_sve_ldff1bhs_r_mte, + gen_helper_sve_ldff1dd_be_r_mte } }, }; if (sve_access_check(s)) { TCGv_i64 addr = new_tmp_a64(s); tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), dtype_msz(a->dtype)); tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn)); - do_mem_zpa(s, a->rd, a->pg, addr, a->dtype, - fns[s->be_data == MO_BE][a->dtype]); + do_mem_zpa(s, a->rd, a->pg, addr, a->dtype, 1, false, + fns[s->mte_active[0]][s->be_data == MO_BE][a->dtype]); } return true; } static bool trans_LDNF1_zpri(DisasContext *s, arg_rpri_load *a) { - static gen_helper_gvec_mem * const fns[2][16] = { - /* Little-endian */ - { gen_helper_sve_ldnf1bb_r, - gen_helper_sve_ldnf1bhu_r, - gen_helper_sve_ldnf1bsu_r, - gen_helper_sve_ldnf1bdu_r, - - gen_helper_sve_ldnf1sds_le_r, - gen_helper_sve_ldnf1hh_le_r, - gen_helper_sve_ldnf1hsu_le_r, - gen_helper_sve_ldnf1hdu_le_r, - - gen_helper_sve_ldnf1hds_le_r, - gen_helper_sve_ldnf1hss_le_r, - gen_helper_sve_ldnf1ss_le_r, - gen_helper_sve_ldnf1sdu_le_r, - - gen_helper_sve_ldnf1bds_r, - gen_helper_sve_ldnf1bss_r, - gen_helper_sve_ldnf1bhs_r, - gen_helper_sve_ldnf1dd_le_r }, - - /* Big-endian */ - { gen_helper_sve_ldnf1bb_r, - gen_helper_sve_ldnf1bhu_r, - gen_helper_sve_ldnf1bsu_r, - gen_helper_sve_ldnf1bdu_r, - - gen_helper_sve_ldnf1sds_be_r, - gen_helper_sve_ldnf1hh_be_r, - gen_helper_sve_ldnf1hsu_be_r, - gen_helper_sve_ldnf1hdu_be_r, - - gen_helper_sve_ldnf1hds_be_r, - gen_helper_sve_ldnf1hss_be_r, - gen_helper_sve_ldnf1ss_be_r, - gen_helper_sve_ldnf1sdu_be_r, - - gen_helper_sve_ldnf1bds_r, - gen_helper_sve_ldnf1bss_r, - gen_helper_sve_ldnf1bhs_r, - gen_helper_sve_ldnf1dd_be_r }, + static gen_helper_gvec_mem * const fns[2][2][16] = { + { /* mte inactive, little-endian */ + { gen_helper_sve_ldnf1bb_r, + gen_helper_sve_ldnf1bhu_r, + gen_helper_sve_ldnf1bsu_r, + gen_helper_sve_ldnf1bdu_r, + + gen_helper_sve_ldnf1sds_le_r, + gen_helper_sve_ldnf1hh_le_r, + gen_helper_sve_ldnf1hsu_le_r, + gen_helper_sve_ldnf1hdu_le_r, + + gen_helper_sve_ldnf1hds_le_r, + gen_helper_sve_ldnf1hss_le_r, + gen_helper_sve_ldnf1ss_le_r, + gen_helper_sve_ldnf1sdu_le_r, + + gen_helper_sve_ldnf1bds_r, + gen_helper_sve_ldnf1bss_r, + gen_helper_sve_ldnf1bhs_r, + gen_helper_sve_ldnf1dd_le_r }, + + /* mte inactive, big-endian */ + { gen_helper_sve_ldnf1bb_r, + gen_helper_sve_ldnf1bhu_r, + gen_helper_sve_ldnf1bsu_r, + gen_helper_sve_ldnf1bdu_r, + + gen_helper_sve_ldnf1sds_be_r, + gen_helper_sve_ldnf1hh_be_r, + gen_helper_sve_ldnf1hsu_be_r, + gen_helper_sve_ldnf1hdu_be_r, + + gen_helper_sve_ldnf1hds_be_r, + gen_helper_sve_ldnf1hss_be_r, + gen_helper_sve_ldnf1ss_be_r, + gen_helper_sve_ldnf1sdu_be_r, + + gen_helper_sve_ldnf1bds_r, + gen_helper_sve_ldnf1bss_r, + gen_helper_sve_ldnf1bhs_r, + gen_helper_sve_ldnf1dd_be_r } }, + + { /* mte inactive, little-endian */ + { gen_helper_sve_ldnf1bb_r_mte, + gen_helper_sve_ldnf1bhu_r_mte, + gen_helper_sve_ldnf1bsu_r_mte, + gen_helper_sve_ldnf1bdu_r_mte, + + gen_helper_sve_ldnf1sds_le_r_mte, + gen_helper_sve_ldnf1hh_le_r_mte, + gen_helper_sve_ldnf1hsu_le_r_mte, + gen_helper_sve_ldnf1hdu_le_r_mte, + + gen_helper_sve_ldnf1hds_le_r_mte, + gen_helper_sve_ldnf1hss_le_r_mte, + gen_helper_sve_ldnf1ss_le_r_mte, + gen_helper_sve_ldnf1sdu_le_r_mte, + + gen_helper_sve_ldnf1bds_r_mte, + gen_helper_sve_ldnf1bss_r_mte, + gen_helper_sve_ldnf1bhs_r_mte, + gen_helper_sve_ldnf1dd_le_r_mte }, + + /* mte inactive, big-endian */ + { gen_helper_sve_ldnf1bb_r_mte, + gen_helper_sve_ldnf1bhu_r_mte, + gen_helper_sve_ldnf1bsu_r_mte, + gen_helper_sve_ldnf1bdu_r_mte, + + gen_helper_sve_ldnf1sds_be_r_mte, + gen_helper_sve_ldnf1hh_be_r_mte, + gen_helper_sve_ldnf1hsu_be_r_mte, + gen_helper_sve_ldnf1hdu_be_r_mte, + + gen_helper_sve_ldnf1hds_be_r_mte, + gen_helper_sve_ldnf1hss_be_r_mte, + gen_helper_sve_ldnf1ss_be_r_mte, + gen_helper_sve_ldnf1sdu_be_r_mte, + + gen_helper_sve_ldnf1bds_r_mte, + gen_helper_sve_ldnf1bss_r_mte, + gen_helper_sve_ldnf1bhs_r_mte, + gen_helper_sve_ldnf1dd_be_r_mte } }, }; if (sve_access_check(s)) { @@ -4788,8 +4889,8 @@ static bool trans_LDNF1_zpri(DisasContext *s, arg_rpri_load *a) TCGv_i64 addr = new_tmp_a64(s); tcg_gen_addi_i64(addr, cpu_reg_sp(s, a->rn), off); - do_mem_zpa(s, a->rd, a->pg, addr, a->dtype, - fns[s->be_data == MO_BE][a->dtype]); + do_mem_zpa(s, a->rd, a->pg, addr, a->dtype, 1, false, + fns[s->mte_active[0]][s->be_data == MO_BE][a->dtype]); } return true; } @@ -4873,16 +4974,18 @@ static bool trans_LD1RQ_zpri(DisasContext *s, arg_rpri_load *a) /* Load and broadcast element. */ static bool trans_LD1R_zpri(DisasContext *s, arg_rpri_load *a) { - if (!sve_access_check(s)) { - return true; - } - unsigned vsz = vec_full_reg_size(s); unsigned psz = pred_full_reg_size(s); unsigned esz = dtype_esz[a->dtype]; unsigned msz = dtype_msz(a->dtype); - TCGLabel *over = gen_new_label(); - TCGv_i64 temp; + TCGLabel *over; + TCGv_i64 temp, clean_addr; + + if (!sve_access_check(s)) { + return true; + } + + over = gen_new_label(); /* If the guarding predicate has no bits set, no load occurs. */ if (psz <= 8) { @@ -4905,7 +5008,9 @@ static bool trans_LD1R_zpri(DisasContext *s, arg_rpri_load *a) /* Load the data. */ temp = tcg_temp_new_i64(); tcg_gen_addi_i64(temp, cpu_reg_sp(s, a->rn), a->imm << msz); - tcg_gen_qemu_ld_i64(temp, temp, get_mem_index(s), + clean_addr = gen_mte_check1(s, temp, false, true, msz); + + tcg_gen_qemu_ld_i64(temp, clean_addr, get_mem_index(s), s->be_data | dtype_mop[a->dtype]); /* Broadcast to *all* elements. */ @@ -4915,80 +5020,131 @@ static bool trans_LD1R_zpri(DisasContext *s, arg_rpri_load *a) /* Zero the inactive elements. */ gen_set_label(over); - do_movz_zpz(s, a->rd, a->rd, a->pg, esz); - return true; + return do_movz_zpz(s, a->rd, a->rd, a->pg, esz, false); } static void do_st_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr, int msz, int esz, int nreg) { - static gen_helper_gvec_mem * const fn_single[2][4][4] = { - { { gen_helper_sve_st1bb_r, - gen_helper_sve_st1bh_r, - gen_helper_sve_st1bs_r, - gen_helper_sve_st1bd_r }, - { NULL, - gen_helper_sve_st1hh_le_r, - gen_helper_sve_st1hs_le_r, - gen_helper_sve_st1hd_le_r }, - { NULL, NULL, - gen_helper_sve_st1ss_le_r, - gen_helper_sve_st1sd_le_r }, - { NULL, NULL, NULL, - gen_helper_sve_st1dd_le_r } }, - { { gen_helper_sve_st1bb_r, - gen_helper_sve_st1bh_r, - gen_helper_sve_st1bs_r, - gen_helper_sve_st1bd_r }, - { NULL, - gen_helper_sve_st1hh_be_r, - gen_helper_sve_st1hs_be_r, - gen_helper_sve_st1hd_be_r }, - { NULL, NULL, - gen_helper_sve_st1ss_be_r, - gen_helper_sve_st1sd_be_r }, - { NULL, NULL, NULL, - gen_helper_sve_st1dd_be_r } }, + static gen_helper_gvec_mem * const fn_single[2][2][4][4] = { + { { { gen_helper_sve_st1bb_r, + gen_helper_sve_st1bh_r, + gen_helper_sve_st1bs_r, + gen_helper_sve_st1bd_r }, + { NULL, + gen_helper_sve_st1hh_le_r, + gen_helper_sve_st1hs_le_r, + gen_helper_sve_st1hd_le_r }, + { NULL, NULL, + gen_helper_sve_st1ss_le_r, + gen_helper_sve_st1sd_le_r }, + { NULL, NULL, NULL, + gen_helper_sve_st1dd_le_r } }, + { { gen_helper_sve_st1bb_r, + gen_helper_sve_st1bh_r, + gen_helper_sve_st1bs_r, + gen_helper_sve_st1bd_r }, + { NULL, + gen_helper_sve_st1hh_be_r, + gen_helper_sve_st1hs_be_r, + gen_helper_sve_st1hd_be_r }, + { NULL, NULL, + gen_helper_sve_st1ss_be_r, + gen_helper_sve_st1sd_be_r }, + { NULL, NULL, NULL, + gen_helper_sve_st1dd_be_r } } }, + + { { { gen_helper_sve_st1bb_r_mte, + gen_helper_sve_st1bh_r_mte, + gen_helper_sve_st1bs_r_mte, + gen_helper_sve_st1bd_r_mte }, + { NULL, + gen_helper_sve_st1hh_le_r_mte, + gen_helper_sve_st1hs_le_r_mte, + gen_helper_sve_st1hd_le_r_mte }, + { NULL, NULL, + gen_helper_sve_st1ss_le_r_mte, + gen_helper_sve_st1sd_le_r_mte }, + { NULL, NULL, NULL, + gen_helper_sve_st1dd_le_r_mte } }, + { { gen_helper_sve_st1bb_r_mte, + gen_helper_sve_st1bh_r_mte, + gen_helper_sve_st1bs_r_mte, + gen_helper_sve_st1bd_r_mte }, + { NULL, + gen_helper_sve_st1hh_be_r_mte, + gen_helper_sve_st1hs_be_r_mte, + gen_helper_sve_st1hd_be_r_mte }, + { NULL, NULL, + gen_helper_sve_st1ss_be_r_mte, + gen_helper_sve_st1sd_be_r_mte }, + { NULL, NULL, NULL, + gen_helper_sve_st1dd_be_r_mte } } }, }; - static gen_helper_gvec_mem * const fn_multiple[2][3][4] = { - { { gen_helper_sve_st2bb_r, - gen_helper_sve_st2hh_le_r, - gen_helper_sve_st2ss_le_r, - gen_helper_sve_st2dd_le_r }, - { gen_helper_sve_st3bb_r, - gen_helper_sve_st3hh_le_r, - gen_helper_sve_st3ss_le_r, - gen_helper_sve_st3dd_le_r }, - { gen_helper_sve_st4bb_r, - gen_helper_sve_st4hh_le_r, - gen_helper_sve_st4ss_le_r, - gen_helper_sve_st4dd_le_r } }, - { { gen_helper_sve_st2bb_r, - gen_helper_sve_st2hh_be_r, - gen_helper_sve_st2ss_be_r, - gen_helper_sve_st2dd_be_r }, - { gen_helper_sve_st3bb_r, - gen_helper_sve_st3hh_be_r, - gen_helper_sve_st3ss_be_r, - gen_helper_sve_st3dd_be_r }, - { gen_helper_sve_st4bb_r, - gen_helper_sve_st4hh_be_r, - gen_helper_sve_st4ss_be_r, - gen_helper_sve_st4dd_be_r } }, + static gen_helper_gvec_mem * const fn_multiple[2][2][3][4] = { + { { { gen_helper_sve_st2bb_r, + gen_helper_sve_st2hh_le_r, + gen_helper_sve_st2ss_le_r, + gen_helper_sve_st2dd_le_r }, + { gen_helper_sve_st3bb_r, + gen_helper_sve_st3hh_le_r, + gen_helper_sve_st3ss_le_r, + gen_helper_sve_st3dd_le_r }, + { gen_helper_sve_st4bb_r, + gen_helper_sve_st4hh_le_r, + gen_helper_sve_st4ss_le_r, + gen_helper_sve_st4dd_le_r } }, + { { gen_helper_sve_st2bb_r, + gen_helper_sve_st2hh_be_r, + gen_helper_sve_st2ss_be_r, + gen_helper_sve_st2dd_be_r }, + { gen_helper_sve_st3bb_r, + gen_helper_sve_st3hh_be_r, + gen_helper_sve_st3ss_be_r, + gen_helper_sve_st3dd_be_r }, + { gen_helper_sve_st4bb_r, + gen_helper_sve_st4hh_be_r, + gen_helper_sve_st4ss_be_r, + gen_helper_sve_st4dd_be_r } } }, + { { { gen_helper_sve_st2bb_r_mte, + gen_helper_sve_st2hh_le_r_mte, + gen_helper_sve_st2ss_le_r_mte, + gen_helper_sve_st2dd_le_r_mte }, + { gen_helper_sve_st3bb_r_mte, + gen_helper_sve_st3hh_le_r_mte, + gen_helper_sve_st3ss_le_r_mte, + gen_helper_sve_st3dd_le_r_mte }, + { gen_helper_sve_st4bb_r_mte, + gen_helper_sve_st4hh_le_r_mte, + gen_helper_sve_st4ss_le_r_mte, + gen_helper_sve_st4dd_le_r_mte } }, + { { gen_helper_sve_st2bb_r_mte, + gen_helper_sve_st2hh_be_r_mte, + gen_helper_sve_st2ss_be_r_mte, + gen_helper_sve_st2dd_be_r_mte }, + { gen_helper_sve_st3bb_r_mte, + gen_helper_sve_st3hh_be_r_mte, + gen_helper_sve_st3ss_be_r_mte, + gen_helper_sve_st3dd_be_r_mte }, + { gen_helper_sve_st4bb_r_mte, + gen_helper_sve_st4hh_be_r_mte, + gen_helper_sve_st4ss_be_r_mte, + gen_helper_sve_st4dd_be_r_mte } } }, }; gen_helper_gvec_mem *fn; int be = s->be_data == MO_BE; if (nreg == 0) { /* ST1 */ - fn = fn_single[be][msz][esz]; + fn = fn_single[s->mte_active[0]][be][msz][esz]; + nreg = 1; } else { /* ST2, ST3, ST4 -- msz == esz, enforced by encoding */ assert(msz == esz); - fn = fn_multiple[be][nreg - 1][msz]; + fn = fn_multiple[s->mte_active[0]][be][nreg - 1][msz]; } assert(fn != NULL); - do_mem_zpa(s, zt, pg, addr, msz_dtype(s, msz), fn); + do_mem_zpa(s, zt, pg, addr, msz_dtype(s, msz), nreg, true, fn); } static bool trans_ST_zprr(DisasContext *s, arg_rprr_store *a) @@ -5027,7 +5183,7 @@ static bool trans_ST_zpri(DisasContext *s, arg_rpri_store *a) */ static void do_mem_zpz(DisasContext *s, int zt, int pg, int zm, - int scale, TCGv_i64 scalar, int msz, + int scale, TCGv_i64 scalar, int msz, bool is_write, gen_helper_gvec_mem_scatter *fn) { unsigned vsz = vec_full_reg_size(s); @@ -5035,9 +5191,17 @@ static void do_mem_zpz(DisasContext *s, int zt, int pg, int zm, TCGv_ptr t_pg = tcg_temp_new_ptr(); TCGv_ptr t_zt = tcg_temp_new_ptr(); TCGv_i32 t_desc; - int desc; + int desc = 0; - desc = simd_desc(vsz, vsz, scale); + if (s->mte_active[0]) { + desc = FIELD_DP32(desc, MTEDESC, MIDX, get_mem_index(s)); + desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid); + desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma); + desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write); + desc = FIELD_DP32(desc, MTEDESC, ESIZE, 1 << msz); + desc <<= SVE_MTEDESC_SHIFT; + } + desc = simd_desc(vsz, vsz, desc | scale); t_desc = tcg_const_i32(desc); tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg)); @@ -5051,176 +5215,339 @@ static void do_mem_zpz(DisasContext *s, int zt, int pg, int zm, tcg_temp_free_i32(t_desc); } -/* Indexed by [be][ff][xs][u][msz]. */ -static gen_helper_gvec_mem_scatter * const gather_load_fn32[2][2][2][2][3] = { - /* Little-endian */ - { { { { gen_helper_sve_ldbss_zsu, - gen_helper_sve_ldhss_le_zsu, - NULL, }, - { gen_helper_sve_ldbsu_zsu, - gen_helper_sve_ldhsu_le_zsu, - gen_helper_sve_ldss_le_zsu, } }, - { { gen_helper_sve_ldbss_zss, - gen_helper_sve_ldhss_le_zss, - NULL, }, - { gen_helper_sve_ldbsu_zss, - gen_helper_sve_ldhsu_le_zss, - gen_helper_sve_ldss_le_zss, } } }, - - /* First-fault */ - { { { gen_helper_sve_ldffbss_zsu, - gen_helper_sve_ldffhss_le_zsu, - NULL, }, - { gen_helper_sve_ldffbsu_zsu, - gen_helper_sve_ldffhsu_le_zsu, - gen_helper_sve_ldffss_le_zsu, } }, - { { gen_helper_sve_ldffbss_zss, - gen_helper_sve_ldffhss_le_zss, - NULL, }, - { gen_helper_sve_ldffbsu_zss, - gen_helper_sve_ldffhsu_le_zss, - gen_helper_sve_ldffss_le_zss, } } } }, - - /* Big-endian */ - { { { { gen_helper_sve_ldbss_zsu, - gen_helper_sve_ldhss_be_zsu, - NULL, }, - { gen_helper_sve_ldbsu_zsu, - gen_helper_sve_ldhsu_be_zsu, - gen_helper_sve_ldss_be_zsu, } }, - { { gen_helper_sve_ldbss_zss, - gen_helper_sve_ldhss_be_zss, - NULL, }, - { gen_helper_sve_ldbsu_zss, - gen_helper_sve_ldhsu_be_zss, - gen_helper_sve_ldss_be_zss, } } }, - - /* First-fault */ - { { { gen_helper_sve_ldffbss_zsu, - gen_helper_sve_ldffhss_be_zsu, - NULL, }, - { gen_helper_sve_ldffbsu_zsu, - gen_helper_sve_ldffhsu_be_zsu, - gen_helper_sve_ldffss_be_zsu, } }, - { { gen_helper_sve_ldffbss_zss, - gen_helper_sve_ldffhss_be_zss, - NULL, }, - { gen_helper_sve_ldffbsu_zss, - gen_helper_sve_ldffhsu_be_zss, - gen_helper_sve_ldffss_be_zss, } } } }, +/* Indexed by [mte][be][ff][xs][u][msz]. */ +static gen_helper_gvec_mem_scatter * const +gather_load_fn32[2][2][2][2][2][3] = { + { /* MTE Inactive */ + { /* Little-endian */ + { { { gen_helper_sve_ldbss_zsu, + gen_helper_sve_ldhss_le_zsu, + NULL, }, + { gen_helper_sve_ldbsu_zsu, + gen_helper_sve_ldhsu_le_zsu, + gen_helper_sve_ldss_le_zsu, } }, + { { gen_helper_sve_ldbss_zss, + gen_helper_sve_ldhss_le_zss, + NULL, }, + { gen_helper_sve_ldbsu_zss, + gen_helper_sve_ldhsu_le_zss, + gen_helper_sve_ldss_le_zss, } } }, + + /* First-fault */ + { { { gen_helper_sve_ldffbss_zsu, + gen_helper_sve_ldffhss_le_zsu, + NULL, }, + { gen_helper_sve_ldffbsu_zsu, + gen_helper_sve_ldffhsu_le_zsu, + gen_helper_sve_ldffss_le_zsu, } }, + { { gen_helper_sve_ldffbss_zss, + gen_helper_sve_ldffhss_le_zss, + NULL, }, + { gen_helper_sve_ldffbsu_zss, + gen_helper_sve_ldffhsu_le_zss, + gen_helper_sve_ldffss_le_zss, } } } }, + + { /* Big-endian */ + { { { gen_helper_sve_ldbss_zsu, + gen_helper_sve_ldhss_be_zsu, + NULL, }, + { gen_helper_sve_ldbsu_zsu, + gen_helper_sve_ldhsu_be_zsu, + gen_helper_sve_ldss_be_zsu, } }, + { { gen_helper_sve_ldbss_zss, + gen_helper_sve_ldhss_be_zss, + NULL, }, + { gen_helper_sve_ldbsu_zss, + gen_helper_sve_ldhsu_be_zss, + gen_helper_sve_ldss_be_zss, } } }, + + /* First-fault */ + { { { gen_helper_sve_ldffbss_zsu, + gen_helper_sve_ldffhss_be_zsu, + NULL, }, + { gen_helper_sve_ldffbsu_zsu, + gen_helper_sve_ldffhsu_be_zsu, + gen_helper_sve_ldffss_be_zsu, } }, + { { gen_helper_sve_ldffbss_zss, + gen_helper_sve_ldffhss_be_zss, + NULL, }, + { gen_helper_sve_ldffbsu_zss, + gen_helper_sve_ldffhsu_be_zss, + gen_helper_sve_ldffss_be_zss, } } } } }, + { /* MTE Active */ + { /* Little-endian */ + { { { gen_helper_sve_ldbss_zsu_mte, + gen_helper_sve_ldhss_le_zsu_mte, + NULL, }, + { gen_helper_sve_ldbsu_zsu_mte, + gen_helper_sve_ldhsu_le_zsu_mte, + gen_helper_sve_ldss_le_zsu_mte, } }, + { { gen_helper_sve_ldbss_zss_mte, + gen_helper_sve_ldhss_le_zss_mte, + NULL, }, + { gen_helper_sve_ldbsu_zss_mte, + gen_helper_sve_ldhsu_le_zss_mte, + gen_helper_sve_ldss_le_zss_mte, } } }, + + /* First-fault */ + { { { gen_helper_sve_ldffbss_zsu_mte, + gen_helper_sve_ldffhss_le_zsu_mte, + NULL, }, + { gen_helper_sve_ldffbsu_zsu_mte, + gen_helper_sve_ldffhsu_le_zsu_mte, + gen_helper_sve_ldffss_le_zsu_mte, } }, + { { gen_helper_sve_ldffbss_zss_mte, + gen_helper_sve_ldffhss_le_zss_mte, + NULL, }, + { gen_helper_sve_ldffbsu_zss_mte, + gen_helper_sve_ldffhsu_le_zss_mte, + gen_helper_sve_ldffss_le_zss_mte, } } } }, + + { /* Big-endian */ + { { { gen_helper_sve_ldbss_zsu_mte, + gen_helper_sve_ldhss_be_zsu_mte, + NULL, }, + { gen_helper_sve_ldbsu_zsu_mte, + gen_helper_sve_ldhsu_be_zsu_mte, + gen_helper_sve_ldss_be_zsu_mte, } }, + { { gen_helper_sve_ldbss_zss_mte, + gen_helper_sve_ldhss_be_zss_mte, + NULL, }, + { gen_helper_sve_ldbsu_zss_mte, + gen_helper_sve_ldhsu_be_zss_mte, + gen_helper_sve_ldss_be_zss_mte, } } }, + + /* First-fault */ + { { { gen_helper_sve_ldffbss_zsu_mte, + gen_helper_sve_ldffhss_be_zsu_mte, + NULL, }, + { gen_helper_sve_ldffbsu_zsu_mte, + gen_helper_sve_ldffhsu_be_zsu_mte, + gen_helper_sve_ldffss_be_zsu_mte, } }, + { { gen_helper_sve_ldffbss_zss_mte, + gen_helper_sve_ldffhss_be_zss_mte, + NULL, }, + { gen_helper_sve_ldffbsu_zss_mte, + gen_helper_sve_ldffhsu_be_zss_mte, + gen_helper_sve_ldffss_be_zss_mte, } } } } }, }; /* Note that we overload xs=2 to indicate 64-bit offset. */ -static gen_helper_gvec_mem_scatter * const gather_load_fn64[2][2][3][2][4] = { - /* Little-endian */ - { { { { gen_helper_sve_ldbds_zsu, - gen_helper_sve_ldhds_le_zsu, - gen_helper_sve_ldsds_le_zsu, - NULL, }, - { gen_helper_sve_ldbdu_zsu, - gen_helper_sve_ldhdu_le_zsu, - gen_helper_sve_ldsdu_le_zsu, - gen_helper_sve_lddd_le_zsu, } }, - { { gen_helper_sve_ldbds_zss, - gen_helper_sve_ldhds_le_zss, - gen_helper_sve_ldsds_le_zss, - NULL, }, - { gen_helper_sve_ldbdu_zss, - gen_helper_sve_ldhdu_le_zss, - gen_helper_sve_ldsdu_le_zss, - gen_helper_sve_lddd_le_zss, } }, - { { gen_helper_sve_ldbds_zd, - gen_helper_sve_ldhds_le_zd, - gen_helper_sve_ldsds_le_zd, - NULL, }, - { gen_helper_sve_ldbdu_zd, - gen_helper_sve_ldhdu_le_zd, - gen_helper_sve_ldsdu_le_zd, - gen_helper_sve_lddd_le_zd, } } }, - - /* First-fault */ - { { { gen_helper_sve_ldffbds_zsu, - gen_helper_sve_ldffhds_le_zsu, - gen_helper_sve_ldffsds_le_zsu, - NULL, }, - { gen_helper_sve_ldffbdu_zsu, - gen_helper_sve_ldffhdu_le_zsu, - gen_helper_sve_ldffsdu_le_zsu, - gen_helper_sve_ldffdd_le_zsu, } }, - { { gen_helper_sve_ldffbds_zss, - gen_helper_sve_ldffhds_le_zss, - gen_helper_sve_ldffsds_le_zss, - NULL, }, - { gen_helper_sve_ldffbdu_zss, - gen_helper_sve_ldffhdu_le_zss, - gen_helper_sve_ldffsdu_le_zss, - gen_helper_sve_ldffdd_le_zss, } }, - { { gen_helper_sve_ldffbds_zd, - gen_helper_sve_ldffhds_le_zd, - gen_helper_sve_ldffsds_le_zd, - NULL, }, - { gen_helper_sve_ldffbdu_zd, - gen_helper_sve_ldffhdu_le_zd, - gen_helper_sve_ldffsdu_le_zd, - gen_helper_sve_ldffdd_le_zd, } } } }, - - /* Big-endian */ - { { { { gen_helper_sve_ldbds_zsu, - gen_helper_sve_ldhds_be_zsu, - gen_helper_sve_ldsds_be_zsu, - NULL, }, - { gen_helper_sve_ldbdu_zsu, - gen_helper_sve_ldhdu_be_zsu, - gen_helper_sve_ldsdu_be_zsu, - gen_helper_sve_lddd_be_zsu, } }, - { { gen_helper_sve_ldbds_zss, - gen_helper_sve_ldhds_be_zss, - gen_helper_sve_ldsds_be_zss, - NULL, }, - { gen_helper_sve_ldbdu_zss, - gen_helper_sve_ldhdu_be_zss, - gen_helper_sve_ldsdu_be_zss, - gen_helper_sve_lddd_be_zss, } }, - { { gen_helper_sve_ldbds_zd, - gen_helper_sve_ldhds_be_zd, - gen_helper_sve_ldsds_be_zd, - NULL, }, - { gen_helper_sve_ldbdu_zd, - gen_helper_sve_ldhdu_be_zd, - gen_helper_sve_ldsdu_be_zd, - gen_helper_sve_lddd_be_zd, } } }, - - /* First-fault */ - { { { gen_helper_sve_ldffbds_zsu, - gen_helper_sve_ldffhds_be_zsu, - gen_helper_sve_ldffsds_be_zsu, - NULL, }, - { gen_helper_sve_ldffbdu_zsu, - gen_helper_sve_ldffhdu_be_zsu, - gen_helper_sve_ldffsdu_be_zsu, - gen_helper_sve_ldffdd_be_zsu, } }, - { { gen_helper_sve_ldffbds_zss, - gen_helper_sve_ldffhds_be_zss, - gen_helper_sve_ldffsds_be_zss, - NULL, }, - { gen_helper_sve_ldffbdu_zss, - gen_helper_sve_ldffhdu_be_zss, - gen_helper_sve_ldffsdu_be_zss, - gen_helper_sve_ldffdd_be_zss, } }, - { { gen_helper_sve_ldffbds_zd, - gen_helper_sve_ldffhds_be_zd, - gen_helper_sve_ldffsds_be_zd, - NULL, }, - { gen_helper_sve_ldffbdu_zd, - gen_helper_sve_ldffhdu_be_zd, - gen_helper_sve_ldffsdu_be_zd, - gen_helper_sve_ldffdd_be_zd, } } } }, +static gen_helper_gvec_mem_scatter * const +gather_load_fn64[2][2][2][3][2][4] = { + { /* MTE Inactive */ + { /* Little-endian */ + { { { gen_helper_sve_ldbds_zsu, + gen_helper_sve_ldhds_le_zsu, + gen_helper_sve_ldsds_le_zsu, + NULL, }, + { gen_helper_sve_ldbdu_zsu, + gen_helper_sve_ldhdu_le_zsu, + gen_helper_sve_ldsdu_le_zsu, + gen_helper_sve_lddd_le_zsu, } }, + { { gen_helper_sve_ldbds_zss, + gen_helper_sve_ldhds_le_zss, + gen_helper_sve_ldsds_le_zss, + NULL, }, + { gen_helper_sve_ldbdu_zss, + gen_helper_sve_ldhdu_le_zss, + gen_helper_sve_ldsdu_le_zss, + gen_helper_sve_lddd_le_zss, } }, + { { gen_helper_sve_ldbds_zd, + gen_helper_sve_ldhds_le_zd, + gen_helper_sve_ldsds_le_zd, + NULL, }, + { gen_helper_sve_ldbdu_zd, + gen_helper_sve_ldhdu_le_zd, + gen_helper_sve_ldsdu_le_zd, + gen_helper_sve_lddd_le_zd, } } }, + + /* First-fault */ + { { { gen_helper_sve_ldffbds_zsu, + gen_helper_sve_ldffhds_le_zsu, + gen_helper_sve_ldffsds_le_zsu, + NULL, }, + { gen_helper_sve_ldffbdu_zsu, + gen_helper_sve_ldffhdu_le_zsu, + gen_helper_sve_ldffsdu_le_zsu, + gen_helper_sve_ldffdd_le_zsu, } }, + { { gen_helper_sve_ldffbds_zss, + gen_helper_sve_ldffhds_le_zss, + gen_helper_sve_ldffsds_le_zss, + NULL, }, + { gen_helper_sve_ldffbdu_zss, + gen_helper_sve_ldffhdu_le_zss, + gen_helper_sve_ldffsdu_le_zss, + gen_helper_sve_ldffdd_le_zss, } }, + { { gen_helper_sve_ldffbds_zd, + gen_helper_sve_ldffhds_le_zd, + gen_helper_sve_ldffsds_le_zd, + NULL, }, + { gen_helper_sve_ldffbdu_zd, + gen_helper_sve_ldffhdu_le_zd, + gen_helper_sve_ldffsdu_le_zd, + gen_helper_sve_ldffdd_le_zd, } } } }, + { /* Big-endian */ + { { { gen_helper_sve_ldbds_zsu, + gen_helper_sve_ldhds_be_zsu, + gen_helper_sve_ldsds_be_zsu, + NULL, }, + { gen_helper_sve_ldbdu_zsu, + gen_helper_sve_ldhdu_be_zsu, + gen_helper_sve_ldsdu_be_zsu, + gen_helper_sve_lddd_be_zsu, } }, + { { gen_helper_sve_ldbds_zss, + gen_helper_sve_ldhds_be_zss, + gen_helper_sve_ldsds_be_zss, + NULL, }, + { gen_helper_sve_ldbdu_zss, + gen_helper_sve_ldhdu_be_zss, + gen_helper_sve_ldsdu_be_zss, + gen_helper_sve_lddd_be_zss, } }, + { { gen_helper_sve_ldbds_zd, + gen_helper_sve_ldhds_be_zd, + gen_helper_sve_ldsds_be_zd, + NULL, }, + { gen_helper_sve_ldbdu_zd, + gen_helper_sve_ldhdu_be_zd, + gen_helper_sve_ldsdu_be_zd, + gen_helper_sve_lddd_be_zd, } } }, + + /* First-fault */ + { { { gen_helper_sve_ldffbds_zsu, + gen_helper_sve_ldffhds_be_zsu, + gen_helper_sve_ldffsds_be_zsu, + NULL, }, + { gen_helper_sve_ldffbdu_zsu, + gen_helper_sve_ldffhdu_be_zsu, + gen_helper_sve_ldffsdu_be_zsu, + gen_helper_sve_ldffdd_be_zsu, } }, + { { gen_helper_sve_ldffbds_zss, + gen_helper_sve_ldffhds_be_zss, + gen_helper_sve_ldffsds_be_zss, + NULL, }, + { gen_helper_sve_ldffbdu_zss, + gen_helper_sve_ldffhdu_be_zss, + gen_helper_sve_ldffsdu_be_zss, + gen_helper_sve_ldffdd_be_zss, } }, + { { gen_helper_sve_ldffbds_zd, + gen_helper_sve_ldffhds_be_zd, + gen_helper_sve_ldffsds_be_zd, + NULL, }, + { gen_helper_sve_ldffbdu_zd, + gen_helper_sve_ldffhdu_be_zd, + gen_helper_sve_ldffsdu_be_zd, + gen_helper_sve_ldffdd_be_zd, } } } } }, + { /* MTE Active */ + { /* Little-endian */ + { { { gen_helper_sve_ldbds_zsu_mte, + gen_helper_sve_ldhds_le_zsu_mte, + gen_helper_sve_ldsds_le_zsu_mte, + NULL, }, + { gen_helper_sve_ldbdu_zsu_mte, + gen_helper_sve_ldhdu_le_zsu_mte, + gen_helper_sve_ldsdu_le_zsu_mte, + gen_helper_sve_lddd_le_zsu_mte, } }, + { { gen_helper_sve_ldbds_zss_mte, + gen_helper_sve_ldhds_le_zss_mte, + gen_helper_sve_ldsds_le_zss_mte, + NULL, }, + { gen_helper_sve_ldbdu_zss_mte, + gen_helper_sve_ldhdu_le_zss_mte, + gen_helper_sve_ldsdu_le_zss_mte, + gen_helper_sve_lddd_le_zss_mte, } }, + { { gen_helper_sve_ldbds_zd_mte, + gen_helper_sve_ldhds_le_zd_mte, + gen_helper_sve_ldsds_le_zd_mte, + NULL, }, + { gen_helper_sve_ldbdu_zd_mte, + gen_helper_sve_ldhdu_le_zd_mte, + gen_helper_sve_ldsdu_le_zd_mte, + gen_helper_sve_lddd_le_zd_mte, } } }, + + /* First-fault */ + { { { gen_helper_sve_ldffbds_zsu_mte, + gen_helper_sve_ldffhds_le_zsu_mte, + gen_helper_sve_ldffsds_le_zsu_mte, + NULL, }, + { gen_helper_sve_ldffbdu_zsu_mte, + gen_helper_sve_ldffhdu_le_zsu_mte, + gen_helper_sve_ldffsdu_le_zsu_mte, + gen_helper_sve_ldffdd_le_zsu_mte, } }, + { { gen_helper_sve_ldffbds_zss_mte, + gen_helper_sve_ldffhds_le_zss_mte, + gen_helper_sve_ldffsds_le_zss_mte, + NULL, }, + { gen_helper_sve_ldffbdu_zss_mte, + gen_helper_sve_ldffhdu_le_zss_mte, + gen_helper_sve_ldffsdu_le_zss_mte, + gen_helper_sve_ldffdd_le_zss_mte, } }, + { { gen_helper_sve_ldffbds_zd_mte, + gen_helper_sve_ldffhds_le_zd_mte, + gen_helper_sve_ldffsds_le_zd_mte, + NULL, }, + { gen_helper_sve_ldffbdu_zd_mte, + gen_helper_sve_ldffhdu_le_zd_mte, + gen_helper_sve_ldffsdu_le_zd_mte, + gen_helper_sve_ldffdd_le_zd_mte, } } } }, + { /* Big-endian */ + { { { gen_helper_sve_ldbds_zsu_mte, + gen_helper_sve_ldhds_be_zsu_mte, + gen_helper_sve_ldsds_be_zsu_mte, + NULL, }, + { gen_helper_sve_ldbdu_zsu_mte, + gen_helper_sve_ldhdu_be_zsu_mte, + gen_helper_sve_ldsdu_be_zsu_mte, + gen_helper_sve_lddd_be_zsu_mte, } }, + { { gen_helper_sve_ldbds_zss_mte, + gen_helper_sve_ldhds_be_zss_mte, + gen_helper_sve_ldsds_be_zss_mte, + NULL, }, + { gen_helper_sve_ldbdu_zss_mte, + gen_helper_sve_ldhdu_be_zss_mte, + gen_helper_sve_ldsdu_be_zss_mte, + gen_helper_sve_lddd_be_zss_mte, } }, + { { gen_helper_sve_ldbds_zd_mte, + gen_helper_sve_ldhds_be_zd_mte, + gen_helper_sve_ldsds_be_zd_mte, + NULL, }, + { gen_helper_sve_ldbdu_zd_mte, + gen_helper_sve_ldhdu_be_zd_mte, + gen_helper_sve_ldsdu_be_zd_mte, + gen_helper_sve_lddd_be_zd_mte, } } }, + + /* First-fault */ + { { { gen_helper_sve_ldffbds_zsu_mte, + gen_helper_sve_ldffhds_be_zsu_mte, + gen_helper_sve_ldffsds_be_zsu_mte, + NULL, }, + { gen_helper_sve_ldffbdu_zsu_mte, + gen_helper_sve_ldffhdu_be_zsu_mte, + gen_helper_sve_ldffsdu_be_zsu_mte, + gen_helper_sve_ldffdd_be_zsu_mte, } }, + { { gen_helper_sve_ldffbds_zss_mte, + gen_helper_sve_ldffhds_be_zss_mte, + gen_helper_sve_ldffsds_be_zss_mte, + NULL, }, + { gen_helper_sve_ldffbdu_zss_mte, + gen_helper_sve_ldffhdu_be_zss_mte, + gen_helper_sve_ldffsdu_be_zss_mte, + gen_helper_sve_ldffdd_be_zss_mte, } }, + { { gen_helper_sve_ldffbds_zd_mte, + gen_helper_sve_ldffhds_be_zd_mte, + gen_helper_sve_ldffsds_be_zd_mte, + NULL, }, + { gen_helper_sve_ldffbdu_zd_mte, + gen_helper_sve_ldffhdu_be_zd_mte, + gen_helper_sve_ldffsdu_be_zd_mte, + gen_helper_sve_ldffdd_be_zd_mte, } } } } }, }; static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a) { gen_helper_gvec_mem_scatter *fn = NULL; - int be = s->be_data == MO_BE; + bool be = s->be_data == MO_BE; + bool mte = s->mte_active[0]; if (!sve_access_check(s)) { return true; @@ -5228,23 +5555,24 @@ static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a) switch (a->esz) { case MO_32: - fn = gather_load_fn32[be][a->ff][a->xs][a->u][a->msz]; + fn = gather_load_fn32[mte][be][a->ff][a->xs][a->u][a->msz]; break; case MO_64: - fn = gather_load_fn64[be][a->ff][a->xs][a->u][a->msz]; + fn = gather_load_fn64[mte][be][a->ff][a->xs][a->u][a->msz]; break; } assert(fn != NULL); do_mem_zpz(s, a->rd, a->pg, a->rm, a->scale * a->msz, - cpu_reg_sp(s, a->rn), a->msz, fn); + cpu_reg_sp(s, a->rn), a->msz, false, fn); return true; } static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a) { gen_helper_gvec_mem_scatter *fn = NULL; - int be = s->be_data == MO_BE; + bool be = s->be_data == MO_BE; + bool mte = s->mte_active[0]; TCGv_i64 imm; if (a->esz < a->msz || (a->esz == a->msz && !a->u)) { @@ -5256,10 +5584,10 @@ static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a) switch (a->esz) { case MO_32: - fn = gather_load_fn32[be][a->ff][0][a->u][a->msz]; + fn = gather_load_fn32[mte][be][a->ff][0][a->u][a->msz]; break; case MO_64: - fn = gather_load_fn64[be][a->ff][2][a->u][a->msz]; + fn = gather_load_fn64[mte][be][a->ff][2][a->u][a->msz]; break; } assert(fn != NULL); @@ -5268,63 +5596,108 @@ static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a) * by loading the immediate into the scalar parameter. */ imm = tcg_const_i64(a->imm << a->msz); - do_mem_zpz(s, a->rd, a->pg, a->rn, 0, imm, a->msz, fn); + do_mem_zpz(s, a->rd, a->pg, a->rn, 0, imm, a->msz, false, fn); tcg_temp_free_i64(imm); return true; } -/* Indexed by [be][xs][msz]. */ -static gen_helper_gvec_mem_scatter * const scatter_store_fn32[2][2][3] = { - /* Little-endian */ - { { gen_helper_sve_stbs_zsu, - gen_helper_sve_sths_le_zsu, - gen_helper_sve_stss_le_zsu, }, - { gen_helper_sve_stbs_zss, - gen_helper_sve_sths_le_zss, - gen_helper_sve_stss_le_zss, } }, - /* Big-endian */ - { { gen_helper_sve_stbs_zsu, - gen_helper_sve_sths_be_zsu, - gen_helper_sve_stss_be_zsu, }, - { gen_helper_sve_stbs_zss, - gen_helper_sve_sths_be_zss, - gen_helper_sve_stss_be_zss, } }, +/* Indexed by [mte][be][xs][msz]. */ +static gen_helper_gvec_mem_scatter * const scatter_store_fn32[2][2][2][3] = { + { /* MTE Inactive */ + { /* Little-endian */ + { gen_helper_sve_stbs_zsu, + gen_helper_sve_sths_le_zsu, + gen_helper_sve_stss_le_zsu, }, + { gen_helper_sve_stbs_zss, + gen_helper_sve_sths_le_zss, + gen_helper_sve_stss_le_zss, } }, + { /* Big-endian */ + { gen_helper_sve_stbs_zsu, + gen_helper_sve_sths_be_zsu, + gen_helper_sve_stss_be_zsu, }, + { gen_helper_sve_stbs_zss, + gen_helper_sve_sths_be_zss, + gen_helper_sve_stss_be_zss, } } }, + { /* MTE Active */ + { /* Little-endian */ + { gen_helper_sve_stbs_zsu_mte, + gen_helper_sve_sths_le_zsu_mte, + gen_helper_sve_stss_le_zsu_mte, }, + { gen_helper_sve_stbs_zss_mte, + gen_helper_sve_sths_le_zss_mte, + gen_helper_sve_stss_le_zss_mte, } }, + { /* Big-endian */ + { gen_helper_sve_stbs_zsu_mte, + gen_helper_sve_sths_be_zsu_mte, + gen_helper_sve_stss_be_zsu_mte, }, + { gen_helper_sve_stbs_zss_mte, + gen_helper_sve_sths_be_zss_mte, + gen_helper_sve_stss_be_zss_mte, } } }, }; /* Note that we overload xs=2 to indicate 64-bit offset. */ -static gen_helper_gvec_mem_scatter * const scatter_store_fn64[2][3][4] = { - /* Little-endian */ - { { gen_helper_sve_stbd_zsu, - gen_helper_sve_sthd_le_zsu, - gen_helper_sve_stsd_le_zsu, - gen_helper_sve_stdd_le_zsu, }, - { gen_helper_sve_stbd_zss, - gen_helper_sve_sthd_le_zss, - gen_helper_sve_stsd_le_zss, - gen_helper_sve_stdd_le_zss, }, - { gen_helper_sve_stbd_zd, - gen_helper_sve_sthd_le_zd, - gen_helper_sve_stsd_le_zd, - gen_helper_sve_stdd_le_zd, } }, - /* Big-endian */ - { { gen_helper_sve_stbd_zsu, - gen_helper_sve_sthd_be_zsu, - gen_helper_sve_stsd_be_zsu, - gen_helper_sve_stdd_be_zsu, }, - { gen_helper_sve_stbd_zss, - gen_helper_sve_sthd_be_zss, - gen_helper_sve_stsd_be_zss, - gen_helper_sve_stdd_be_zss, }, - { gen_helper_sve_stbd_zd, - gen_helper_sve_sthd_be_zd, - gen_helper_sve_stsd_be_zd, - gen_helper_sve_stdd_be_zd, } }, +static gen_helper_gvec_mem_scatter * const scatter_store_fn64[2][2][3][4] = { + { /* MTE Inactive */ + { /* Little-endian */ + { gen_helper_sve_stbd_zsu, + gen_helper_sve_sthd_le_zsu, + gen_helper_sve_stsd_le_zsu, + gen_helper_sve_stdd_le_zsu, }, + { gen_helper_sve_stbd_zss, + gen_helper_sve_sthd_le_zss, + gen_helper_sve_stsd_le_zss, + gen_helper_sve_stdd_le_zss, }, + { gen_helper_sve_stbd_zd, + gen_helper_sve_sthd_le_zd, + gen_helper_sve_stsd_le_zd, + gen_helper_sve_stdd_le_zd, } }, + { /* Big-endian */ + { gen_helper_sve_stbd_zsu, + gen_helper_sve_sthd_be_zsu, + gen_helper_sve_stsd_be_zsu, + gen_helper_sve_stdd_be_zsu, }, + { gen_helper_sve_stbd_zss, + gen_helper_sve_sthd_be_zss, + gen_helper_sve_stsd_be_zss, + gen_helper_sve_stdd_be_zss, }, + { gen_helper_sve_stbd_zd, + gen_helper_sve_sthd_be_zd, + gen_helper_sve_stsd_be_zd, + gen_helper_sve_stdd_be_zd, } } }, + { /* MTE Inactive */ + { /* Little-endian */ + { gen_helper_sve_stbd_zsu_mte, + gen_helper_sve_sthd_le_zsu_mte, + gen_helper_sve_stsd_le_zsu_mte, + gen_helper_sve_stdd_le_zsu_mte, }, + { gen_helper_sve_stbd_zss_mte, + gen_helper_sve_sthd_le_zss_mte, + gen_helper_sve_stsd_le_zss_mte, + gen_helper_sve_stdd_le_zss_mte, }, + { gen_helper_sve_stbd_zd_mte, + gen_helper_sve_sthd_le_zd_mte, + gen_helper_sve_stsd_le_zd_mte, + gen_helper_sve_stdd_le_zd_mte, } }, + { /* Big-endian */ + { gen_helper_sve_stbd_zsu_mte, + gen_helper_sve_sthd_be_zsu_mte, + gen_helper_sve_stsd_be_zsu_mte, + gen_helper_sve_stdd_be_zsu_mte, }, + { gen_helper_sve_stbd_zss_mte, + gen_helper_sve_sthd_be_zss_mte, + gen_helper_sve_stsd_be_zss_mte, + gen_helper_sve_stdd_be_zss_mte, }, + { gen_helper_sve_stbd_zd_mte, + gen_helper_sve_sthd_be_zd_mte, + gen_helper_sve_stsd_be_zd_mte, + gen_helper_sve_stdd_be_zd_mte, } } }, }; static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a) { gen_helper_gvec_mem_scatter *fn; - int be = s->be_data == MO_BE; + bool be = s->be_data == MO_BE; + bool mte = s->mte_active[0]; if (a->esz < a->msz || (a->msz == 0 && a->scale)) { return false; @@ -5334,23 +5707,24 @@ static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a) } switch (a->esz) { case MO_32: - fn = scatter_store_fn32[be][a->xs][a->msz]; + fn = scatter_store_fn32[mte][be][a->xs][a->msz]; break; case MO_64: - fn = scatter_store_fn64[be][a->xs][a->msz]; + fn = scatter_store_fn64[mte][be][a->xs][a->msz]; break; default: g_assert_not_reached(); } do_mem_zpz(s, a->rd, a->pg, a->rm, a->scale * a->msz, - cpu_reg_sp(s, a->rn), a->msz, fn); + cpu_reg_sp(s, a->rn), a->msz, true, fn); return true; } static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a) { gen_helper_gvec_mem_scatter *fn = NULL; - int be = s->be_data == MO_BE; + bool be = s->be_data == MO_BE; + bool mte = s->mte_active[0]; TCGv_i64 imm; if (a->esz < a->msz) { @@ -5362,10 +5736,10 @@ static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a) switch (a->esz) { case MO_32: - fn = scatter_store_fn32[be][0][a->msz]; + fn = scatter_store_fn32[mte][be][0][a->msz]; break; case MO_64: - fn = scatter_store_fn64[be][2][a->msz]; + fn = scatter_store_fn64[mte][be][2][a->msz]; break; } assert(fn != NULL); @@ -5374,7 +5748,7 @@ static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a) * by loading the immediate into the scalar parameter. */ imm = tcg_const_i64(a->imm << a->msz); - do_mem_zpz(s, a->rd, a->pg, a->rn, 0, imm, a->msz, fn); + do_mem_zpz(s, a->rd, a->pg, a->rn, 0, imm, a->msz, true, fn); tcg_temp_free_i64(imm); return true; } @@ -5429,8 +5803,5 @@ static bool trans_MOVPRFX_m(DisasContext *s, arg_rpr_esz *a) static bool trans_MOVPRFX_z(DisasContext *s, arg_rpr_esz *a) { - if (sve_access_check(s)) { - do_movz_zpz(s, a->rd, a->rn, a->pg, a->esz); - } - return true; + return do_movz_zpz(s, a->rd, a->rn, a->pg, a->esz, false); } diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.c.inc similarity index 71% rename from target/arm/translate-vfp.inc.c rename to target/arm/translate-vfp.c.inc index e1a90175983d0f7a2c0f16248df5423eada2ec55..96948f5a2d308ba9175fafef53190556b4ff27da 100644 --- a/target/arm/translate-vfp.inc.c +++ b/target/arm/translate-vfp.c.inc @@ -9,7 +9,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -27,8 +27,8 @@ */ /* Include the generated VFP decoder */ -#include "decode-vfp.inc.c" -#include "decode-vfp-uncond.inc.c" +#include "decode-vfp.c.inc" +#include "decode-vfp-uncond.c.inc" /* * The imm8 encodes the sign bit, enough bits to represent an exponent in @@ -95,14 +95,11 @@ static inline long vfp_f16_offset(unsigned reg, bool top) static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled) { if (s->fp_excp_el) { - if (arm_dc_feature(s, ARM_FEATURE_M)) { - gen_exception_insn(s, s->pc_curr, EXCP_NOCP, syn_uncategorized(), - s->fp_excp_el); - } else { - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_fp_access_trap(1, 0xe, false), - s->fp_excp_el); - } + /* M-profile handled this earlier, in disas_m_nocp() */ + assert (!arm_dc_feature(s, ARM_FEATURE_M)); + gen_exception_insn(s, s->pc_curr, EXCP_UDEF, + syn_fp_access_trap(1, 0xe, false), + s->fp_excp_el); return false; } @@ -119,15 +116,14 @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled) if (s->v7m_lspact) { /* * Lazy state saving affects external memory and also the NVIC, - * so we must mark it as an IO operation for icount. + * so we must mark it as an IO operation for icount (and cause + * this to be the last insn in the TB). */ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { + s->base.is_jmp = DISAS_UPDATE_EXIT; gen_io_start(); } gen_helper_v7m_preserve_fp_state(cpu_env); - if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { - gen_io_end(); - } /* * If the preserve_fp_state helper doesn't throw an exception * then it will clear LSPACT; we don't need to repeat this for @@ -194,18 +190,22 @@ static bool vfp_access_check(DisasContext *s) static bool trans_VSEL(DisasContext *s, arg_VSEL *a) { uint32_t rd, rn, rm; - bool dp = a->dp; + int sz = a->sz; if (!dc_isar_feature(aa32_vsel, s)) { return false; } - if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) { + if (sz == 3 && !dc_isar_feature(aa32_fpdp_v2, s)) { + return false; + } + + if (sz == 1 && !dc_isar_feature(aa32_fp16_arith, s)) { return false; } /* UNDEF accesses to D16-D31 if they don't exist */ - if (dp && !dc_isar_feature(aa32_simd_r32, s) && + if (sz == 3 && !dc_isar_feature(aa32_simd_r32, s) && ((a->vm | a->vn | a->vd) & 0x10)) { return false; } @@ -218,7 +218,7 @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a) return true; } - if (dp) { + if (sz == 3) { TCGv_i64 frn, frm, dest; TCGv_i64 tmp, zero, zf, nf, vf; @@ -236,8 +236,8 @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a) tcg_gen_ext_i32_i64(nf, cpu_NF); tcg_gen_ext_i32_i64(vf, cpu_VF); - neon_load_reg64(frn, rn); - neon_load_reg64(frm, rm); + vfp_load_reg64(frn, rn); + vfp_load_reg64(frm, rm); switch (a->cc) { case 0: /* eq: Z */ tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero, @@ -264,7 +264,7 @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a) tcg_temp_free_i64(tmp); break; } - neon_store_reg64(dest, rd); + vfp_store_reg64(dest, rd); tcg_temp_free_i64(frn); tcg_temp_free_i64(frm); tcg_temp_free_i64(dest); @@ -283,8 +283,8 @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a) frn = tcg_temp_new_i32(); frm = tcg_temp_new_i32(); dest = tcg_temp_new_i32(); - neon_load_reg32(frn, rn); - neon_load_reg32(frm, rm); + vfp_load_reg32(frn, rn); + vfp_load_reg32(frm, rm); switch (a->cc) { case 0: /* eq: Z */ tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero, @@ -311,7 +311,11 @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a) tcg_temp_free_i32(tmp); break; } - neon_store_reg32(dest, rd); + /* For fp16 the top half is always zeroes */ + if (sz == 1) { + tcg_gen_andi_i32(dest, dest, 0xffff); + } + vfp_store_reg32(dest, rd); tcg_temp_free_i32(frn); tcg_temp_free_i32(frm); tcg_temp_free_i32(dest); @@ -337,7 +341,7 @@ static const uint8_t fp_decode_rm[] = { static bool trans_VRINT(DisasContext *s, arg_VRINT *a) { uint32_t rd, rm; - bool dp = a->dp; + int sz = a->sz; TCGv_ptr fpst; TCGv_i32 tcg_rmode; int rounding = fp_decode_rm[a->rm]; @@ -346,12 +350,16 @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a) return false; } - if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) { + if (sz == 3 && !dc_isar_feature(aa32_fpdp_v2, s)) { + return false; + } + + if (sz == 1 && !dc_isar_feature(aa32_fp16_arith, s)) { return false; } /* UNDEF accesses to D16-D31 if they don't exist */ - if (dp && !dc_isar_feature(aa32_simd_r32, s) && + if (sz == 3 && !dc_isar_feature(aa32_simd_r32, s) && ((a->vm | a->vd) & 0x10)) { return false; } @@ -363,19 +371,23 @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a) return true; } - fpst = get_fpstatus_ptr(0); + if (sz == 1) { + fpst = fpstatus_ptr(FPST_FPCR_F16); + } else { + fpst = fpstatus_ptr(FPST_FPCR); + } tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding)); gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); - if (dp) { + if (sz == 3) { TCGv_i64 tcg_op; TCGv_i64 tcg_res; tcg_op = tcg_temp_new_i64(); tcg_res = tcg_temp_new_i64(); - neon_load_reg64(tcg_op, rm); + vfp_load_reg64(tcg_op, rm); gen_helper_rintd(tcg_res, tcg_op, fpst); - neon_store_reg64(tcg_res, rd); + vfp_store_reg64(tcg_res, rd); tcg_temp_free_i64(tcg_op); tcg_temp_free_i64(tcg_res); } else { @@ -383,9 +395,13 @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a) TCGv_i32 tcg_res; tcg_op = tcg_temp_new_i32(); tcg_res = tcg_temp_new_i32(); - neon_load_reg32(tcg_op, rm); - gen_helper_rints(tcg_res, tcg_op, fpst); - neon_store_reg32(tcg_res, rd); + vfp_load_reg32(tcg_op, rm); + if (sz == 1) { + gen_helper_rinth(tcg_res, tcg_op, fpst); + } else { + gen_helper_rints(tcg_res, tcg_op, fpst); + } + vfp_store_reg32(tcg_res, rd); tcg_temp_free_i32(tcg_op); tcg_temp_free_i32(tcg_res); } @@ -400,7 +416,7 @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a) static bool trans_VCVT(DisasContext *s, arg_VCVT *a) { uint32_t rd, rm; - bool dp = a->dp; + int sz = a->sz; TCGv_ptr fpst; TCGv_i32 tcg_rmode, tcg_shift; int rounding = fp_decode_rm[a->rm]; @@ -410,12 +426,16 @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a) return false; } - if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) { + if (sz == 3 && !dc_isar_feature(aa32_fpdp_v2, s)) { + return false; + } + + if (sz == 1 && !dc_isar_feature(aa32_fp16_arith, s)) { return false; } /* UNDEF accesses to D16-D31 if they don't exist */ - if (dp && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) { + if (sz == 3 && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) { return false; } @@ -426,27 +446,31 @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a) return true; } - fpst = get_fpstatus_ptr(0); + if (sz == 1) { + fpst = fpstatus_ptr(FPST_FPCR_F16); + } else { + fpst = fpstatus_ptr(FPST_FPCR); + } tcg_shift = tcg_const_i32(0); tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding)); gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); - if (dp) { + if (sz == 3) { TCGv_i64 tcg_double, tcg_res; TCGv_i32 tcg_tmp; tcg_double = tcg_temp_new_i64(); tcg_res = tcg_temp_new_i64(); tcg_tmp = tcg_temp_new_i32(); - neon_load_reg64(tcg_double, rm); + vfp_load_reg64(tcg_double, rm); if (is_signed) { gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst); } else { gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst); } tcg_gen_extrl_i64_i32(tcg_tmp, tcg_res); - neon_store_reg32(tcg_tmp, rd); + vfp_store_reg32(tcg_tmp, rd); tcg_temp_free_i32(tcg_tmp); tcg_temp_free_i64(tcg_res); tcg_temp_free_i64(tcg_double); @@ -454,13 +478,21 @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a) TCGv_i32 tcg_single, tcg_res; tcg_single = tcg_temp_new_i32(); tcg_res = tcg_temp_new_i32(); - neon_load_reg32(tcg_single, rm); - if (is_signed) { - gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst); + vfp_load_reg32(tcg_single, rm); + if (sz == 1) { + if (is_signed) { + gen_helper_vfp_toslh(tcg_res, tcg_single, tcg_shift, fpst); + } else { + gen_helper_vfp_toulh(tcg_res, tcg_single, tcg_shift, fpst); + } } else { - gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst); + if (is_signed) { + gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst); + } else { + gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst); + } } - neon_store_reg32(tcg_res, rd); + vfp_store_reg32(tcg_res, rd); tcg_temp_free_i32(tcg_res); tcg_temp_free_i32(tcg_single); } @@ -479,11 +511,9 @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a) { /* VMOV scalar to general purpose register */ TCGv_i32 tmp; - int pass; - uint32_t offset; - /* SIZE == 2 is a VFP instruction; otherwise NEON. */ - if (a->size == 2 + /* SIZE == MO_32 is a VFP instruction; otherwise NEON. */ + if (a->size == MO_32 ? !dc_isar_feature(aa32_fpsp_v2, s) : !arm_dc_feature(s, ARM_FEATURE_NEON)) { return false; @@ -494,44 +524,12 @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a) return false; } - offset = a->index << a->size; - pass = extract32(offset, 2, 1); - offset = extract32(offset, 0, 2) * 8; - if (!vfp_access_check(s)) { return true; } - tmp = neon_load_reg(a->vn, pass); - switch (a->size) { - case 0: - if (offset) { - tcg_gen_shri_i32(tmp, tmp, offset); - } - if (a->u) { - gen_uxtb(tmp); - } else { - gen_sxtb(tmp); - } - break; - case 1: - if (a->u) { - if (offset) { - tcg_gen_shri_i32(tmp, tmp, 16); - } else { - gen_uxth(tmp); - } - } else { - if (offset) { - tcg_gen_sari_i32(tmp, tmp, 16); - } else { - gen_sxth(tmp); - } - } - break; - case 2: - break; - } + tmp = tcg_temp_new_i32(); + read_neon_element32(tmp, a->vn, a->index, a->size | (a->u ? 0 : MO_SIGN)); store_reg(s, a->rt, tmp); return true; @@ -540,12 +538,10 @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a) static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a) { /* VMOV general purpose register to scalar */ - TCGv_i32 tmp, tmp2; - int pass; - uint32_t offset; + TCGv_i32 tmp; - /* SIZE == 2 is a VFP instruction; otherwise NEON. */ - if (a->size == 2 + /* SIZE == MO_32 is a VFP instruction; otherwise NEON. */ + if (a->size == MO_32 ? !dc_isar_feature(aa32_fpsp_v2, s) : !arm_dc_feature(s, ARM_FEATURE_NEON)) { return false; @@ -556,30 +552,13 @@ static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a) return false; } - offset = a->index << a->size; - pass = extract32(offset, 2, 1); - offset = extract32(offset, 0, 2) * 8; - if (!vfp_access_check(s)) { return true; } tmp = load_reg(s, a->rt); - switch (a->size) { - case 0: - tmp2 = neon_load_reg(a->vn, pass); - tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8); - tcg_temp_free_i32(tmp2); - break; - case 1: - tmp2 = neon_load_reg(a->vn, pass); - tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16); - tcg_temp_free_i32(tmp2); - break; - case 2: - break; - } - neon_store_reg(a->vn, pass, tmp); + write_neon_element32(tmp, a->vn, a->index, a->size); + tcg_temp_free_i32(tmp); return true; } @@ -621,7 +600,7 @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a) } tmp = load_reg(s, a->rt); - tcg_gen_gvec_dup_i32(size, neon_reg_offset(a->vn, 0), + tcg_gen_gvec_dup_i32(size, neon_full_reg_offset(a->vn), vec_size, vec_size, tmp); tcg_temp_free_i32(tmp); @@ -777,6 +756,40 @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a) return true; } +static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a) +{ + TCGv_i32 tmp; + + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + + if (a->rt == 15) { + /* UNPREDICTABLE; we choose to UNDEF */ + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + if (a->l) { + /* VFP to general purpose register */ + tmp = tcg_temp_new_i32(); + vfp_load_reg32(tmp, a->vn); + tcg_gen_andi_i32(tmp, tmp, 0xffff); + store_reg(s, a->rt, tmp); + } else { + /* general purpose register to VFP */ + tmp = load_reg(s, a->rt); + tcg_gen_andi_i32(tmp, tmp, 0xffff); + vfp_store_reg32(tmp, a->vn); + tcg_temp_free_i32(tmp); + } + + return true; +} + static bool trans_VMOV_single(DisasContext *s, arg_VMOV_single *a) { TCGv_i32 tmp; @@ -792,7 +805,7 @@ static bool trans_VMOV_single(DisasContext *s, arg_VMOV_single *a) if (a->l) { /* VFP to general purpose register */ tmp = tcg_temp_new_i32(); - neon_load_reg32(tmp, a->vn); + vfp_load_reg32(tmp, a->vn); if (a->rt == 15) { /* Set the 4 flag bits in the CPSR. */ gen_set_nzcv(tmp); @@ -803,7 +816,7 @@ static bool trans_VMOV_single(DisasContext *s, arg_VMOV_single *a) } else { /* general purpose register to VFP */ tmp = load_reg(s, a->rt); - neon_store_reg32(tmp, a->vn); + vfp_store_reg32(tmp, a->vn); tcg_temp_free_i32(tmp); } @@ -829,18 +842,18 @@ static bool trans_VMOV_64_sp(DisasContext *s, arg_VMOV_64_sp *a) if (a->op) { /* fpreg to gpreg */ tmp = tcg_temp_new_i32(); - neon_load_reg32(tmp, a->vm); + vfp_load_reg32(tmp, a->vm); store_reg(s, a->rt, tmp); tmp = tcg_temp_new_i32(); - neon_load_reg32(tmp, a->vm + 1); + vfp_load_reg32(tmp, a->vm + 1); store_reg(s, a->rt2, tmp); } else { /* gpreg to fpreg */ tmp = load_reg(s, a->rt); - neon_store_reg32(tmp, a->vm); + vfp_store_reg32(tmp, a->vm); tcg_temp_free_i32(tmp); tmp = load_reg(s, a->rt2); - neon_store_reg32(tmp, a->vm + 1); + vfp_store_reg32(tmp, a->vm + 1); tcg_temp_free_i32(tmp); } @@ -872,24 +885,59 @@ static bool trans_VMOV_64_dp(DisasContext *s, arg_VMOV_64_dp *a) if (a->op) { /* fpreg to gpreg */ tmp = tcg_temp_new_i32(); - neon_load_reg32(tmp, a->vm * 2); + vfp_load_reg32(tmp, a->vm * 2); store_reg(s, a->rt, tmp); tmp = tcg_temp_new_i32(); - neon_load_reg32(tmp, a->vm * 2 + 1); + vfp_load_reg32(tmp, a->vm * 2 + 1); store_reg(s, a->rt2, tmp); } else { /* gpreg to fpreg */ tmp = load_reg(s, a->rt); - neon_store_reg32(tmp, a->vm * 2); + vfp_store_reg32(tmp, a->vm * 2); tcg_temp_free_i32(tmp); tmp = load_reg(s, a->rt2); - neon_store_reg32(tmp, a->vm * 2 + 1); + vfp_store_reg32(tmp, a->vm * 2 + 1); tcg_temp_free_i32(tmp); } return true; } +static bool trans_VLDR_VSTR_hp(DisasContext *s, arg_VLDR_VSTR_sp *a) +{ + uint32_t offset; + TCGv_i32 addr, tmp; + + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + /* imm8 field is offset/2 for fp16, unlike fp32 and fp64 */ + offset = a->imm << 1; + if (!a->u) { + offset = -offset; + } + + /* For thumb, use of PC is UNPREDICTABLE. */ + addr = add_reg_for_lit(s, a->rn, offset); + tmp = tcg_temp_new_i32(); + if (a->l) { + gen_aa32_ld16u(s, tmp, addr, get_mem_index(s)); + vfp_store_reg32(tmp, a->vd); + } else { + vfp_load_reg32(tmp, a->vd); + gen_aa32_st16(s, tmp, addr, get_mem_index(s)); + } + tcg_temp_free_i32(tmp); + tcg_temp_free_i32(addr); + + return true; +} + static bool trans_VLDR_VSTR_sp(DisasContext *s, arg_VLDR_VSTR_sp *a) { uint32_t offset; @@ -913,9 +961,9 @@ static bool trans_VLDR_VSTR_sp(DisasContext *s, arg_VLDR_VSTR_sp *a) tmp = tcg_temp_new_i32(); if (a->l) { gen_aa32_ld32u(s, tmp, addr, get_mem_index(s)); - neon_store_reg32(tmp, a->vd); + vfp_store_reg32(tmp, a->vd); } else { - neon_load_reg32(tmp, a->vd); + vfp_load_reg32(tmp, a->vd); gen_aa32_st32(s, tmp, addr, get_mem_index(s)); } tcg_temp_free_i32(tmp); @@ -954,9 +1002,9 @@ static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_dp *a) tmp = tcg_temp_new_i64(); if (a->l) { gen_aa32_ld64(s, tmp, addr, get_mem_index(s)); - neon_store_reg64(tmp, a->vd); + vfp_store_reg64(tmp, a->vd); } else { - neon_load_reg64(tmp, a->vd); + vfp_load_reg64(tmp, a->vd); gen_aa32_st64(s, tmp, addr, get_mem_index(s)); } tcg_temp_free_i64(tmp); @@ -1018,10 +1066,10 @@ static bool trans_VLDM_VSTM_sp(DisasContext *s, arg_VLDM_VSTM_sp *a) if (a->l) { /* load */ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s)); - neon_store_reg32(tmp, a->vd + i); + vfp_store_reg32(tmp, a->vd + i); } else { /* store */ - neon_load_reg32(tmp, a->vd + i); + vfp_load_reg32(tmp, a->vd + i); gen_aa32_st32(s, tmp, addr, get_mem_index(s)); } tcg_gen_addi_i32(addr, addr, offset); @@ -1101,10 +1149,10 @@ static bool trans_VLDM_VSTM_dp(DisasContext *s, arg_VLDM_VSTM_dp *a) if (a->l) { /* load */ gen_aa32_ld64(s, tmp, addr, get_mem_index(s)); - neon_store_reg64(tmp, a->vd + i); + vfp_store_reg64(tmp, a->vd + i); } else { /* store */ - neon_load_reg64(tmp, a->vd + i); + vfp_load_reg64(tmp, a->vd + i); gen_aa32_st64(s, tmp, addr, get_mem_index(s)); } tcg_gen_addi_i32(addr, addr, offset); @@ -1235,17 +1283,17 @@ static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn, f0 = tcg_temp_new_i32(); f1 = tcg_temp_new_i32(); fd = tcg_temp_new_i32(); - fpst = get_fpstatus_ptr(0); + fpst = fpstatus_ptr(FPST_FPCR); - neon_load_reg32(f0, vn); - neon_load_reg32(f1, vm); + vfp_load_reg32(f0, vn); + vfp_load_reg32(f1, vm); for (;;) { if (reads_vd) { - neon_load_reg32(fd, vd); + vfp_load_reg32(fd, vd); } fn(fd, f0, f1, fpst); - neon_store_reg32(fd, vd); + vfp_store_reg32(fd, vd); if (veclen == 0) { break; @@ -1255,10 +1303,10 @@ static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn, veclen--; vd = vfp_advance_sreg(vd, delta_d); vn = vfp_advance_sreg(vn, delta_d); - neon_load_reg32(f0, vn); + vfp_load_reg32(f0, vn); if (delta_m) { vm = vfp_advance_sreg(vm, delta_m); - neon_load_reg32(f1, vm); + vfp_load_reg32(f1, vm); } } @@ -1270,6 +1318,54 @@ static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn, return true; } +static bool do_vfp_3op_hp(DisasContext *s, VFPGen3OpSPFn *fn, + int vd, int vn, int vm, bool reads_vd) +{ + /* + * Do a half-precision operation. Functionally this is + * the same as do_vfp_3op_sp(), except: + * - it uses the FPST_FPCR_F16 + * - it doesn't need the VFP vector handling (fp16 is a + * v8 feature, and in v8 VFP vectors don't exist) + * - it does the aa32_fp16_arith feature test + */ + TCGv_i32 f0, f1, fd; + TCGv_ptr fpst; + + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + + if (s->vec_len != 0 || s->vec_stride != 0) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + f0 = tcg_temp_new_i32(); + f1 = tcg_temp_new_i32(); + fd = tcg_temp_new_i32(); + fpst = fpstatus_ptr(FPST_FPCR_F16); + + vfp_load_reg32(f0, vn); + vfp_load_reg32(f1, vm); + + if (reads_vd) { + vfp_load_reg32(fd, vd); + } + fn(fd, f0, f1, fpst); + vfp_store_reg32(fd, vd); + + tcg_temp_free_i32(f0); + tcg_temp_free_i32(f1); + tcg_temp_free_i32(fd); + tcg_temp_free_ptr(fpst); + + return true; +} + static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn, int vd, int vn, int vm, bool reads_vd) { @@ -1318,17 +1414,17 @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn, f0 = tcg_temp_new_i64(); f1 = tcg_temp_new_i64(); fd = tcg_temp_new_i64(); - fpst = get_fpstatus_ptr(0); + fpst = fpstatus_ptr(FPST_FPCR); - neon_load_reg64(f0, vn); - neon_load_reg64(f1, vm); + vfp_load_reg64(f0, vn); + vfp_load_reg64(f1, vm); for (;;) { if (reads_vd) { - neon_load_reg64(fd, vd); + vfp_load_reg64(fd, vd); } fn(fd, f0, f1, fpst); - neon_store_reg64(fd, vd); + vfp_store_reg64(fd, vd); if (veclen == 0) { break; @@ -1337,10 +1433,10 @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn, veclen--; vd = vfp_advance_dreg(vd, delta_d); vn = vfp_advance_dreg(vn, delta_d); - neon_load_reg64(f0, vn); + vfp_load_reg64(f0, vn); if (delta_m) { vm = vfp_advance_dreg(vm, delta_m); - neon_load_reg64(f1, vm); + vfp_load_reg64(f1, vm); } } @@ -1393,11 +1489,11 @@ static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm) f0 = tcg_temp_new_i32(); fd = tcg_temp_new_i32(); - neon_load_reg32(f0, vm); + vfp_load_reg32(f0, vm); for (;;) { fn(fd, f0); - neon_store_reg32(fd, vd); + vfp_store_reg32(fd, vd); if (veclen == 0) { break; @@ -1407,7 +1503,7 @@ static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm) /* single source one-many */ while (veclen--) { vd = vfp_advance_sreg(vd, delta_d); - neon_store_reg32(fd, vd); + vfp_store_reg32(fd, vd); } break; } @@ -1416,7 +1512,7 @@ static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm) veclen--; vd = vfp_advance_sreg(vd, delta_d); vm = vfp_advance_sreg(vm, delta_m); - neon_load_reg32(f0, vm); + vfp_load_reg32(f0, vm); } tcg_temp_free_i32(f0); @@ -1425,6 +1521,38 @@ static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm) return true; } +static bool do_vfp_2op_hp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm) +{ + /* + * Do a half-precision operation. Functionally this is + * the same as do_vfp_2op_sp(), except: + * - it doesn't need the VFP vector handling (fp16 is a + * v8 feature, and in v8 VFP vectors don't exist) + * - it does the aa32_fp16_arith feature test + */ + TCGv_i32 f0; + + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + + if (s->vec_len != 0 || s->vec_stride != 0) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + f0 = tcg_temp_new_i32(); + vfp_load_reg32(f0, vm); + fn(f0, f0); + vfp_store_reg32(f0, vd); + tcg_temp_free_i32(f0); + + return true; +} + static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm) { uint32_t delta_m = 0; @@ -1471,11 +1599,11 @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm) f0 = tcg_temp_new_i64(); fd = tcg_temp_new_i64(); - neon_load_reg64(f0, vm); + vfp_load_reg64(f0, vm); for (;;) { fn(fd, f0); - neon_store_reg64(fd, vd); + vfp_store_reg64(fd, vd); if (veclen == 0) { break; @@ -1485,7 +1613,7 @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm) /* single source one-many */ while (veclen--) { vd = vfp_advance_dreg(vd, delta_d); - neon_store_reg64(fd, vd); + vfp_store_reg64(fd, vd); } break; } @@ -1494,7 +1622,7 @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm) veclen--; vd = vfp_advance_dreg(vd, delta_d); vd = vfp_advance_dreg(vm, delta_m); - neon_load_reg64(f0, vm); + vfp_load_reg64(f0, vm); } tcg_temp_free_i64(f0); @@ -1503,6 +1631,21 @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm) return true; } +static void gen_VMLA_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst) +{ + /* Note that order of inputs to the add matters for NaNs */ + TCGv_i32 tmp = tcg_temp_new_i32(); + + gen_helper_vfp_mulh(tmp, vn, vm, fpst); + gen_helper_vfp_addh(vd, vd, tmp, fpst); + tcg_temp_free_i32(tmp); +} + +static bool trans_VMLA_hp(DisasContext *s, arg_VMLA_sp *a) +{ + return do_vfp_3op_hp(s, gen_VMLA_hp, a->vd, a->vn, a->vm, true); +} + static void gen_VMLA_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst) { /* Note that order of inputs to the add matters for NaNs */ @@ -1533,6 +1676,25 @@ static bool trans_VMLA_dp(DisasContext *s, arg_VMLA_dp *a) return do_vfp_3op_dp(s, gen_VMLA_dp, a->vd, a->vn, a->vm, true); } +static void gen_VMLS_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst) +{ + /* + * VMLS: vd = vd + -(vn * vm) + * Note that order of inputs to the add matters for NaNs. + */ + TCGv_i32 tmp = tcg_temp_new_i32(); + + gen_helper_vfp_mulh(tmp, vn, vm, fpst); + gen_helper_vfp_negh(tmp, tmp); + gen_helper_vfp_addh(vd, vd, tmp, fpst); + tcg_temp_free_i32(tmp); +} + +static bool trans_VMLS_hp(DisasContext *s, arg_VMLS_sp *a) +{ + return do_vfp_3op_hp(s, gen_VMLS_hp, a->vd, a->vn, a->vm, true); +} + static void gen_VMLS_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst) { /* @@ -1571,6 +1733,27 @@ static bool trans_VMLS_dp(DisasContext *s, arg_VMLS_dp *a) return do_vfp_3op_dp(s, gen_VMLS_dp, a->vd, a->vn, a->vm, true); } +static void gen_VNMLS_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst) +{ + /* + * VNMLS: -fd + (fn * fm) + * Note that it isn't valid to replace (-A + B) with (B - A) or similar + * plausible looking simplifications because this will give wrong results + * for NaNs. + */ + TCGv_i32 tmp = tcg_temp_new_i32(); + + gen_helper_vfp_mulh(tmp, vn, vm, fpst); + gen_helper_vfp_negh(vd, vd); + gen_helper_vfp_addh(vd, vd, tmp, fpst); + tcg_temp_free_i32(tmp); +} + +static bool trans_VNMLS_hp(DisasContext *s, arg_VNMLS_sp *a) +{ + return do_vfp_3op_hp(s, gen_VNMLS_hp, a->vd, a->vn, a->vm, true); +} + static void gen_VNMLS_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst) { /* @@ -1613,6 +1796,23 @@ static bool trans_VNMLS_dp(DisasContext *s, arg_VNMLS_dp *a) return do_vfp_3op_dp(s, gen_VNMLS_dp, a->vd, a->vn, a->vm, true); } +static void gen_VNMLA_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst) +{ + /* VNMLA: -fd + -(fn * fm) */ + TCGv_i32 tmp = tcg_temp_new_i32(); + + gen_helper_vfp_mulh(tmp, vn, vm, fpst); + gen_helper_vfp_negh(tmp, tmp); + gen_helper_vfp_negh(vd, vd); + gen_helper_vfp_addh(vd, vd, tmp, fpst); + tcg_temp_free_i32(tmp); +} + +static bool trans_VNMLA_hp(DisasContext *s, arg_VNMLA_sp *a) +{ + return do_vfp_3op_hp(s, gen_VNMLA_hp, a->vd, a->vn, a->vm, true); +} + static void gen_VNMLA_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst) { /* VNMLA: -fd + -(fn * fm) */ @@ -1647,6 +1847,11 @@ static bool trans_VNMLA_dp(DisasContext *s, arg_VNMLA_dp *a) return do_vfp_3op_dp(s, gen_VNMLA_dp, a->vd, a->vn, a->vm, true); } +static bool trans_VMUL_hp(DisasContext *s, arg_VMUL_sp *a) +{ + return do_vfp_3op_hp(s, gen_helper_vfp_mulh, a->vd, a->vn, a->vm, false); +} + static bool trans_VMUL_sp(DisasContext *s, arg_VMUL_sp *a) { return do_vfp_3op_sp(s, gen_helper_vfp_muls, a->vd, a->vn, a->vm, false); @@ -1657,6 +1862,18 @@ static bool trans_VMUL_dp(DisasContext *s, arg_VMUL_dp *a) return do_vfp_3op_dp(s, gen_helper_vfp_muld, a->vd, a->vn, a->vm, false); } +static void gen_VNMUL_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst) +{ + /* VNMUL: -(fn * fm) */ + gen_helper_vfp_mulh(vd, vn, vm, fpst); + gen_helper_vfp_negh(vd, vd); +} + +static bool trans_VNMUL_hp(DisasContext *s, arg_VNMUL_sp *a) +{ + return do_vfp_3op_hp(s, gen_VNMUL_hp, a->vd, a->vn, a->vm, false); +} + static void gen_VNMUL_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst) { /* VNMUL: -(fn * fm) */ @@ -1681,6 +1898,11 @@ static bool trans_VNMUL_dp(DisasContext *s, arg_VNMUL_dp *a) return do_vfp_3op_dp(s, gen_VNMUL_dp, a->vd, a->vn, a->vm, false); } +static bool trans_VADD_hp(DisasContext *s, arg_VADD_sp *a) +{ + return do_vfp_3op_hp(s, gen_helper_vfp_addh, a->vd, a->vn, a->vm, false); +} + static bool trans_VADD_sp(DisasContext *s, arg_VADD_sp *a) { return do_vfp_3op_sp(s, gen_helper_vfp_adds, a->vd, a->vn, a->vm, false); @@ -1691,6 +1913,11 @@ static bool trans_VADD_dp(DisasContext *s, arg_VADD_dp *a) return do_vfp_3op_dp(s, gen_helper_vfp_addd, a->vd, a->vn, a->vm, false); } +static bool trans_VSUB_hp(DisasContext *s, arg_VSUB_sp *a) +{ + return do_vfp_3op_hp(s, gen_helper_vfp_subh, a->vd, a->vn, a->vm, false); +} + static bool trans_VSUB_sp(DisasContext *s, arg_VSUB_sp *a) { return do_vfp_3op_sp(s, gen_helper_vfp_subs, a->vd, a->vn, a->vm, false); @@ -1701,6 +1928,11 @@ static bool trans_VSUB_dp(DisasContext *s, arg_VSUB_dp *a) return do_vfp_3op_dp(s, gen_helper_vfp_subd, a->vd, a->vn, a->vm, false); } +static bool trans_VDIV_hp(DisasContext *s, arg_VDIV_sp *a) +{ + return do_vfp_3op_hp(s, gen_helper_vfp_divh, a->vd, a->vn, a->vm, false); +} + static bool trans_VDIV_sp(DisasContext *s, arg_VDIV_sp *a) { return do_vfp_3op_sp(s, gen_helper_vfp_divs, a->vd, a->vn, a->vm, false); @@ -1711,6 +1943,24 @@ static bool trans_VDIV_dp(DisasContext *s, arg_VDIV_dp *a) return do_vfp_3op_dp(s, gen_helper_vfp_divd, a->vd, a->vn, a->vm, false); } +static bool trans_VMINNM_hp(DisasContext *s, arg_VMINNM_sp *a) +{ + if (!dc_isar_feature(aa32_vminmaxnm, s)) { + return false; + } + return do_vfp_3op_hp(s, gen_helper_vfp_minnumh, + a->vd, a->vn, a->vm, false); +} + +static bool trans_VMAXNM_hp(DisasContext *s, arg_VMAXNM_sp *a) +{ + if (!dc_isar_feature(aa32_vminmaxnm, s)) { + return false; + } + return do_vfp_3op_hp(s, gen_helper_vfp_maxnumh, + a->vd, a->vn, a->vm, false); +} + static bool trans_VMINNM_sp(DisasContext *s, arg_VMINNM_sp *a) { if (!dc_isar_feature(aa32_vminmaxnm, s)) { @@ -1747,7 +1997,7 @@ static bool trans_VMAXNM_dp(DisasContext *s, arg_VMAXNM_dp *a) a->vd, a->vn, a->vm, false); } -static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d) +static bool do_vfm_hp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d) { /* * VFNMA : fd = muladd(-fd, fn, fm) @@ -1765,18 +2015,16 @@ static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d) TCGv_i32 vn, vm, vd; /* - * Present in VFPv4 only. + * Present in VFPv4 only, and only with the FP16 extension. * Note that we can't rely on the SIMDFMAC check alone, because * in a Neon-no-VFP core that ID register field will be non-zero. */ - if (!dc_isar_feature(aa32_simdfmac, s) || + if (!dc_isar_feature(aa32_fp16_arith, s) || + !dc_isar_feature(aa32_simdfmac, s) || !dc_isar_feature(aa32_fpsp_v2, s)) { return false; } - /* - * In v7A, UNPREDICTABLE with non-zero vector length/stride; from - * v8A, must UNDEF. We choose to UNDEF for both v7A and v8A. - */ + if (s->vec_len != 0 || s->vec_stride != 0) { return false; } @@ -1789,20 +2037,20 @@ static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d) vm = tcg_temp_new_i32(); vd = tcg_temp_new_i32(); - neon_load_reg32(vn, a->vn); - neon_load_reg32(vm, a->vm); + vfp_load_reg32(vn, a->vn); + vfp_load_reg32(vm, a->vm); if (neg_n) { /* VFNMS, VFMS */ - gen_helper_vfp_negs(vn, vn); + gen_helper_vfp_negh(vn, vn); } - neon_load_reg32(vd, a->vd); + vfp_load_reg32(vd, a->vd); if (neg_d) { /* VFNMA, VFNMS */ - gen_helper_vfp_negs(vd, vd); + gen_helper_vfp_negh(vd, vd); } - fpst = get_fpstatus_ptr(0); - gen_helper_vfp_muladds(vd, vn, vm, vd, fpst); - neon_store_reg32(vd, a->vd); + fpst = fpstatus_ptr(FPST_FPCR_F16); + gen_helper_vfp_muladdh(vd, vn, vm, vd, fpst); + vfp_store_reg32(vd, a->vd); tcg_temp_free_ptr(fpst); tcg_temp_free_i32(vn); @@ -1812,24 +2060,69 @@ static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d) return true; } -static bool trans_VFMA_sp(DisasContext *s, arg_VFMA_sp *a) +static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d) { - return do_vfm_sp(s, a, false, false); -} + /* + * VFNMA : fd = muladd(-fd, fn, fm) + * VFNMS : fd = muladd(-fd, -fn, fm) + * VFMA : fd = muladd( fd, fn, fm) + * VFMS : fd = muladd( fd, -fn, fm) + * + * These are fused multiply-add, and must be done as one floating + * point operation with no rounding between the multiplication and + * addition steps. NB that doing the negations here as separate + * steps is correct : an input NaN should come out with its sign + * bit flipped if it is a negated-input. + */ + TCGv_ptr fpst; + TCGv_i32 vn, vm, vd; -static bool trans_VFMS_sp(DisasContext *s, arg_VFMS_sp *a) -{ - return do_vfm_sp(s, a, true, false); -} + /* + * Present in VFPv4 only. + * Note that we can't rely on the SIMDFMAC check alone, because + * in a Neon-no-VFP core that ID register field will be non-zero. + */ + if (!dc_isar_feature(aa32_simdfmac, s) || + !dc_isar_feature(aa32_fpsp_v2, s)) { + return false; + } + /* + * In v7A, UNPREDICTABLE with non-zero vector length/stride; from + * v8A, must UNDEF. We choose to UNDEF for both v7A and v8A. + */ + if (s->vec_len != 0 || s->vec_stride != 0) { + return false; + } -static bool trans_VFNMA_sp(DisasContext *s, arg_VFNMA_sp *a) -{ - return do_vfm_sp(s, a, false, true); -} + if (!vfp_access_check(s)) { + return true; + } -static bool trans_VFNMS_sp(DisasContext *s, arg_VFNMS_sp *a) -{ - return do_vfm_sp(s, a, true, true); + vn = tcg_temp_new_i32(); + vm = tcg_temp_new_i32(); + vd = tcg_temp_new_i32(); + + vfp_load_reg32(vn, a->vn); + vfp_load_reg32(vm, a->vm); + if (neg_n) { + /* VFNMS, VFMS */ + gen_helper_vfp_negs(vn, vn); + } + vfp_load_reg32(vd, a->vd); + if (neg_d) { + /* VFNMA, VFNMS */ + gen_helper_vfp_negs(vd, vd); + } + fpst = fpstatus_ptr(FPST_FPCR); + gen_helper_vfp_muladds(vd, vn, vm, vd, fpst); + vfp_store_reg32(vd, a->vd); + + tcg_temp_free_ptr(fpst); + tcg_temp_free_i32(vn); + tcg_temp_free_i32(vm); + tcg_temp_free_i32(vd); + + return true; } static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d) @@ -1880,20 +2173,20 @@ static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d) vm = tcg_temp_new_i64(); vd = tcg_temp_new_i64(); - neon_load_reg64(vn, a->vn); - neon_load_reg64(vm, a->vm); + vfp_load_reg64(vn, a->vn); + vfp_load_reg64(vm, a->vm); if (neg_n) { /* VFNMS, VFMS */ gen_helper_vfp_negd(vn, vn); } - neon_load_reg64(vd, a->vd); + vfp_load_reg64(vd, a->vd); if (neg_d) { /* VFNMA, VFNMS */ gen_helper_vfp_negd(vd, vd); } - fpst = get_fpstatus_ptr(0); + fpst = fpstatus_ptr(FPST_FPCR); gen_helper_vfp_muladdd(vd, vn, vm, vd, fpst); - neon_store_reg64(vd, a->vd); + vfp_store_reg64(vd, a->vd); tcg_temp_free_ptr(fpst); tcg_temp_free_i64(vn); @@ -1903,24 +2196,43 @@ static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d) return true; } -static bool trans_VFMA_dp(DisasContext *s, arg_VFMA_dp *a) -{ - return do_vfm_dp(s, a, false, false); -} +#define MAKE_ONE_VFM_TRANS_FN(INSN, PREC, NEGN, NEGD) \ + static bool trans_##INSN##_##PREC(DisasContext *s, \ + arg_##INSN##_##PREC *a) \ + { \ + return do_vfm_##PREC(s, a, NEGN, NEGD); \ + } -static bool trans_VFMS_dp(DisasContext *s, arg_VFMS_dp *a) -{ - return do_vfm_dp(s, a, true, false); -} +#define MAKE_VFM_TRANS_FNS(PREC) \ + MAKE_ONE_VFM_TRANS_FN(VFMA, PREC, false, false) \ + MAKE_ONE_VFM_TRANS_FN(VFMS, PREC, true, false) \ + MAKE_ONE_VFM_TRANS_FN(VFNMA, PREC, false, true) \ + MAKE_ONE_VFM_TRANS_FN(VFNMS, PREC, true, true) -static bool trans_VFNMA_dp(DisasContext *s, arg_VFNMA_dp *a) -{ - return do_vfm_dp(s, a, false, true); -} +MAKE_VFM_TRANS_FNS(hp) +MAKE_VFM_TRANS_FNS(sp) +MAKE_VFM_TRANS_FNS(dp) -static bool trans_VFNMS_dp(DisasContext *s, arg_VFNMS_dp *a) +static bool trans_VMOV_imm_hp(DisasContext *s, arg_VMOV_imm_sp *a) { - return do_vfm_dp(s, a, true, true); + TCGv_i32 fd; + + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + + if (s->vec_len != 0 || s->vec_stride != 0) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + fd = tcg_const_i32(vfp_expand_imm(MO_16, a->imm)); + vfp_store_reg32(fd, a->vd); + tcg_temp_free_i32(fd); + return true; } static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a) @@ -1958,7 +2270,7 @@ static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a) fd = tcg_const_i32(vfp_expand_imm(MO_32, a->imm)); for (;;) { - neon_store_reg32(fd, vd); + vfp_store_reg32(fd, vd); if (veclen == 0) { break; @@ -2013,7 +2325,7 @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a) fd = tcg_const_i64(vfp_expand_imm(MO_64, a->imm)); for (;;) { - neon_store_reg64(fd, vd); + vfp_store_reg64(fd, vd); if (veclen == 0) { break; @@ -2028,34 +2340,27 @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a) return true; } -static bool trans_VMOV_reg_sp(DisasContext *s, arg_VMOV_reg_sp *a) -{ - return do_vfp_2op_sp(s, tcg_gen_mov_i32, a->vd, a->vm); -} - -static bool trans_VMOV_reg_dp(DisasContext *s, arg_VMOV_reg_dp *a) -{ - return do_vfp_2op_dp(s, tcg_gen_mov_i64, a->vd, a->vm); -} +#define DO_VFP_2OP(INSN, PREC, FN) \ + static bool trans_##INSN##_##PREC(DisasContext *s, \ + arg_##INSN##_##PREC *a) \ + { \ + return do_vfp_2op_##PREC(s, FN, a->vd, a->vm); \ + } -static bool trans_VABS_sp(DisasContext *s, arg_VABS_sp *a) -{ - return do_vfp_2op_sp(s, gen_helper_vfp_abss, a->vd, a->vm); -} +DO_VFP_2OP(VMOV_reg, sp, tcg_gen_mov_i32) +DO_VFP_2OP(VMOV_reg, dp, tcg_gen_mov_i64) -static bool trans_VABS_dp(DisasContext *s, arg_VABS_dp *a) -{ - return do_vfp_2op_dp(s, gen_helper_vfp_absd, a->vd, a->vm); -} +DO_VFP_2OP(VABS, hp, gen_helper_vfp_absh) +DO_VFP_2OP(VABS, sp, gen_helper_vfp_abss) +DO_VFP_2OP(VABS, dp, gen_helper_vfp_absd) -static bool trans_VNEG_sp(DisasContext *s, arg_VNEG_sp *a) -{ - return do_vfp_2op_sp(s, gen_helper_vfp_negs, a->vd, a->vm); -} +DO_VFP_2OP(VNEG, hp, gen_helper_vfp_negh) +DO_VFP_2OP(VNEG, sp, gen_helper_vfp_negs) +DO_VFP_2OP(VNEG, dp, gen_helper_vfp_negd) -static bool trans_VNEG_dp(DisasContext *s, arg_VNEG_dp *a) +static void gen_VSQRT_hp(TCGv_i32 vd, TCGv_i32 vm) { - return do_vfp_2op_dp(s, gen_helper_vfp_negd, a->vd, a->vm); + gen_helper_vfp_sqrth(vd, vm, cpu_env); } static void gen_VSQRT_sp(TCGv_i32 vd, TCGv_i32 vm) @@ -2063,19 +2368,52 @@ static void gen_VSQRT_sp(TCGv_i32 vd, TCGv_i32 vm) gen_helper_vfp_sqrts(vd, vm, cpu_env); } -static bool trans_VSQRT_sp(DisasContext *s, arg_VSQRT_sp *a) -{ - return do_vfp_2op_sp(s, gen_VSQRT_sp, a->vd, a->vm); -} - static void gen_VSQRT_dp(TCGv_i64 vd, TCGv_i64 vm) { gen_helper_vfp_sqrtd(vd, vm, cpu_env); } -static bool trans_VSQRT_dp(DisasContext *s, arg_VSQRT_dp *a) +DO_VFP_2OP(VSQRT, hp, gen_VSQRT_hp) +DO_VFP_2OP(VSQRT, sp, gen_VSQRT_sp) +DO_VFP_2OP(VSQRT, dp, gen_VSQRT_dp) + +static bool trans_VCMP_hp(DisasContext *s, arg_VCMP_sp *a) { - return do_vfp_2op_dp(s, gen_VSQRT_dp, a->vd, a->vm); + TCGv_i32 vd, vm; + + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + + /* Vm/M bits must be zero for the Z variant */ + if (a->z && a->vm != 0) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + vd = tcg_temp_new_i32(); + vm = tcg_temp_new_i32(); + + vfp_load_reg32(vd, a->vd); + if (a->z) { + tcg_gen_movi_i32(vm, 0); + } else { + vfp_load_reg32(vm, a->vm); + } + + if (a->e) { + gen_helper_vfp_cmpeh(vd, vm, cpu_env); + } else { + gen_helper_vfp_cmph(vd, vm, cpu_env); + } + + tcg_temp_free_i32(vd); + tcg_temp_free_i32(vm); + + return true; } static bool trans_VCMP_sp(DisasContext *s, arg_VCMP_sp *a) @@ -2098,11 +2436,11 @@ static bool trans_VCMP_sp(DisasContext *s, arg_VCMP_sp *a) vd = tcg_temp_new_i32(); vm = tcg_temp_new_i32(); - neon_load_reg32(vd, a->vd); + vfp_load_reg32(vd, a->vd); if (a->z) { tcg_gen_movi_i32(vm, 0); } else { - neon_load_reg32(vm, a->vm); + vfp_load_reg32(vm, a->vm); } if (a->e) { @@ -2142,11 +2480,11 @@ static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a) vd = tcg_temp_new_i64(); vm = tcg_temp_new_i64(); - neon_load_reg64(vd, a->vd); + vfp_load_reg64(vd, a->vd); if (a->z) { tcg_gen_movi_i64(vm, 0); } else { - neon_load_reg64(vm, a->vm); + vfp_load_reg64(vm, a->vm); } if (a->e) { @@ -2175,13 +2513,13 @@ static bool trans_VCVT_f32_f16(DisasContext *s, arg_VCVT_f32_f16 *a) return true; } - fpst = get_fpstatus_ptr(false); + fpst = fpstatus_ptr(FPST_FPCR); ahp_mode = get_ahp_flag(); tmp = tcg_temp_new_i32(); /* The T bit tells us if we want the low or high 16 bits of Vm */ tcg_gen_ld16u_i32(tmp, cpu_env, vfp_f16_offset(a->vm, a->t)); gen_helper_vfp_fcvt_f16_to_f32(tmp, tmp, fpst, ahp_mode); - neon_store_reg32(tmp, a->vd); + vfp_store_reg32(tmp, a->vd); tcg_temp_free_i32(ahp_mode); tcg_temp_free_ptr(fpst); tcg_temp_free_i32(tmp); @@ -2212,14 +2550,14 @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a) return true; } - fpst = get_fpstatus_ptr(false); + fpst = fpstatus_ptr(FPST_FPCR); ahp_mode = get_ahp_flag(); tmp = tcg_temp_new_i32(); /* The T bit tells us if we want the low or high 16 bits of Vm */ tcg_gen_ld16u_i32(tmp, cpu_env, vfp_f16_offset(a->vm, a->t)); vd = tcg_temp_new_i64(); gen_helper_vfp_fcvt_f16_to_f64(vd, tmp, fpst, ahp_mode); - neon_store_reg64(vd, a->vd); + vfp_store_reg64(vd, a->vd); tcg_temp_free_i32(ahp_mode); tcg_temp_free_ptr(fpst); tcg_temp_free_i32(tmp); @@ -2241,11 +2579,11 @@ static bool trans_VCVT_f16_f32(DisasContext *s, arg_VCVT_f16_f32 *a) return true; } - fpst = get_fpstatus_ptr(false); + fpst = fpstatus_ptr(FPST_FPCR); ahp_mode = get_ahp_flag(); tmp = tcg_temp_new_i32(); - neon_load_reg32(tmp, a->vm); + vfp_load_reg32(tmp, a->vm); gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp_mode); tcg_gen_st16_i32(tmp, cpu_env, vfp_f16_offset(a->vd, a->t)); tcg_temp_free_i32(ahp_mode); @@ -2278,12 +2616,12 @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a) return true; } - fpst = get_fpstatus_ptr(false); + fpst = fpstatus_ptr(FPST_FPCR); ahp_mode = get_ahp_flag(); tmp = tcg_temp_new_i32(); vm = tcg_temp_new_i64(); - neon_load_reg64(vm, a->vm); + vfp_load_reg64(vm, a->vm); gen_helper_vfp_fcvt_f64_to_f16(tmp, vm, fpst, ahp_mode); tcg_temp_free_i64(vm); tcg_gen_st16_i32(tmp, cpu_env, vfp_f16_offset(a->vd, a->t)); @@ -2293,6 +2631,29 @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a) return true; } +static bool trans_VRINTR_hp(DisasContext *s, arg_VRINTR_sp *a) +{ + TCGv_ptr fpst; + TCGv_i32 tmp; + + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + tmp = tcg_temp_new_i32(); + vfp_load_reg32(tmp, a->vm); + fpst = fpstatus_ptr(FPST_FPCR_F16); + gen_helper_rinth(tmp, tmp, fpst); + vfp_store_reg32(tmp, a->vd); + tcg_temp_free_ptr(fpst); + tcg_temp_free_i32(tmp); + return true; +} + static bool trans_VRINTR_sp(DisasContext *s, arg_VRINTR_sp *a) { TCGv_ptr fpst; @@ -2307,10 +2668,10 @@ static bool trans_VRINTR_sp(DisasContext *s, arg_VRINTR_sp *a) } tmp = tcg_temp_new_i32(); - neon_load_reg32(tmp, a->vm); - fpst = get_fpstatus_ptr(false); + vfp_load_reg32(tmp, a->vm); + fpst = fpstatus_ptr(FPST_FPCR); gen_helper_rints(tmp, tmp, fpst); - neon_store_reg32(tmp, a->vd); + vfp_store_reg32(tmp, a->vd); tcg_temp_free_ptr(fpst); tcg_temp_free_i32(tmp); return true; @@ -2339,15 +2700,43 @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a) } tmp = tcg_temp_new_i64(); - neon_load_reg64(tmp, a->vm); - fpst = get_fpstatus_ptr(false); + vfp_load_reg64(tmp, a->vm); + fpst = fpstatus_ptr(FPST_FPCR); gen_helper_rintd(tmp, tmp, fpst); - neon_store_reg64(tmp, a->vd); + vfp_store_reg64(tmp, a->vd); tcg_temp_free_ptr(fpst); tcg_temp_free_i64(tmp); return true; } +static bool trans_VRINTZ_hp(DisasContext *s, arg_VRINTZ_sp *a) +{ + TCGv_ptr fpst; + TCGv_i32 tmp; + TCGv_i32 tcg_rmode; + + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + tmp = tcg_temp_new_i32(); + vfp_load_reg32(tmp, a->vm); + fpst = fpstatus_ptr(FPST_FPCR_F16); + tcg_rmode = tcg_const_i32(float_round_to_zero); + gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); + gen_helper_rinth(tmp, tmp, fpst); + gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); + vfp_store_reg32(tmp, a->vd); + tcg_temp_free_ptr(fpst); + tcg_temp_free_i32(tcg_rmode); + tcg_temp_free_i32(tmp); + return true; +} + static bool trans_VRINTZ_sp(DisasContext *s, arg_VRINTZ_sp *a) { TCGv_ptr fpst; @@ -2363,13 +2752,13 @@ static bool trans_VRINTZ_sp(DisasContext *s, arg_VRINTZ_sp *a) } tmp = tcg_temp_new_i32(); - neon_load_reg32(tmp, a->vm); - fpst = get_fpstatus_ptr(false); + vfp_load_reg32(tmp, a->vm); + fpst = fpstatus_ptr(FPST_FPCR); tcg_rmode = tcg_const_i32(float_round_to_zero); gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); gen_helper_rints(tmp, tmp, fpst); gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); - neon_store_reg32(tmp, a->vd); + vfp_store_reg32(tmp, a->vd); tcg_temp_free_ptr(fpst); tcg_temp_free_i32(tcg_rmode); tcg_temp_free_i32(tmp); @@ -2400,19 +2789,42 @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a) } tmp = tcg_temp_new_i64(); - neon_load_reg64(tmp, a->vm); - fpst = get_fpstatus_ptr(false); + vfp_load_reg64(tmp, a->vm); + fpst = fpstatus_ptr(FPST_FPCR); tcg_rmode = tcg_const_i32(float_round_to_zero); gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); gen_helper_rintd(tmp, tmp, fpst); gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); - neon_store_reg64(tmp, a->vd); + vfp_store_reg64(tmp, a->vd); tcg_temp_free_ptr(fpst); tcg_temp_free_i64(tmp); tcg_temp_free_i32(tcg_rmode); return true; } +static bool trans_VRINTX_hp(DisasContext *s, arg_VRINTX_sp *a) +{ + TCGv_ptr fpst; + TCGv_i32 tmp; + + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + tmp = tcg_temp_new_i32(); + vfp_load_reg32(tmp, a->vm); + fpst = fpstatus_ptr(FPST_FPCR_F16); + gen_helper_rinth_exact(tmp, tmp, fpst); + vfp_store_reg32(tmp, a->vd); + tcg_temp_free_ptr(fpst); + tcg_temp_free_i32(tmp); + return true; +} + static bool trans_VRINTX_sp(DisasContext *s, arg_VRINTX_sp *a) { TCGv_ptr fpst; @@ -2427,10 +2839,10 @@ static bool trans_VRINTX_sp(DisasContext *s, arg_VRINTX_sp *a) } tmp = tcg_temp_new_i32(); - neon_load_reg32(tmp, a->vm); - fpst = get_fpstatus_ptr(false); + vfp_load_reg32(tmp, a->vm); + fpst = fpstatus_ptr(FPST_FPCR); gen_helper_rints_exact(tmp, tmp, fpst); - neon_store_reg32(tmp, a->vd); + vfp_store_reg32(tmp, a->vd); tcg_temp_free_ptr(fpst); tcg_temp_free_i32(tmp); return true; @@ -2459,10 +2871,10 @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a) } tmp = tcg_temp_new_i64(); - neon_load_reg64(tmp, a->vm); - fpst = get_fpstatus_ptr(false); + vfp_load_reg64(tmp, a->vm); + fpst = fpstatus_ptr(FPST_FPCR); gen_helper_rintd_exact(tmp, tmp, fpst); - neon_store_reg64(tmp, a->vd); + vfp_store_reg64(tmp, a->vd); tcg_temp_free_ptr(fpst); tcg_temp_free_i64(tmp); return true; @@ -2488,9 +2900,9 @@ static bool trans_VCVT_sp(DisasContext *s, arg_VCVT_sp *a) vm = tcg_temp_new_i32(); vd = tcg_temp_new_i64(); - neon_load_reg32(vm, a->vm); + vfp_load_reg32(vm, a->vm); gen_helper_vfp_fcvtds(vd, vm, cpu_env); - neon_store_reg64(vd, a->vd); + vfp_store_reg64(vd, a->vd); tcg_temp_free_i32(vm); tcg_temp_free_i64(vd); return true; @@ -2516,14 +2928,43 @@ static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a) vd = tcg_temp_new_i32(); vm = tcg_temp_new_i64(); - neon_load_reg64(vm, a->vm); + vfp_load_reg64(vm, a->vm); gen_helper_vfp_fcvtsd(vd, vm, cpu_env); - neon_store_reg32(vd, a->vd); + vfp_store_reg32(vd, a->vd); tcg_temp_free_i32(vd); tcg_temp_free_i64(vm); return true; } +static bool trans_VCVT_int_hp(DisasContext *s, arg_VCVT_int_sp *a) +{ + TCGv_i32 vm; + TCGv_ptr fpst; + + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + vm = tcg_temp_new_i32(); + vfp_load_reg32(vm, a->vm); + fpst = fpstatus_ptr(FPST_FPCR_F16); + if (a->s) { + /* i32 -> f16 */ + gen_helper_vfp_sitoh(vm, vm, fpst); + } else { + /* u32 -> f16 */ + gen_helper_vfp_uitoh(vm, vm, fpst); + } + vfp_store_reg32(vm, a->vd); + tcg_temp_free_i32(vm); + tcg_temp_free_ptr(fpst); + return true; +} + static bool trans_VCVT_int_sp(DisasContext *s, arg_VCVT_int_sp *a) { TCGv_i32 vm; @@ -2538,8 +2979,8 @@ static bool trans_VCVT_int_sp(DisasContext *s, arg_VCVT_int_sp *a) } vm = tcg_temp_new_i32(); - neon_load_reg32(vm, a->vm); - fpst = get_fpstatus_ptr(false); + vfp_load_reg32(vm, a->vm); + fpst = fpstatus_ptr(FPST_FPCR); if (a->s) { /* i32 -> f32 */ gen_helper_vfp_sitos(vm, vm, fpst); @@ -2547,7 +2988,7 @@ static bool trans_VCVT_int_sp(DisasContext *s, arg_VCVT_int_sp *a) /* u32 -> f32 */ gen_helper_vfp_uitos(vm, vm, fpst); } - neon_store_reg32(vm, a->vd); + vfp_store_reg32(vm, a->vd); tcg_temp_free_i32(vm); tcg_temp_free_ptr(fpst); return true; @@ -2574,8 +3015,8 @@ static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a) vm = tcg_temp_new_i32(); vd = tcg_temp_new_i64(); - neon_load_reg32(vm, a->vm); - fpst = get_fpstatus_ptr(false); + vfp_load_reg32(vm, a->vm); + fpst = fpstatus_ptr(FPST_FPCR); if (a->s) { /* i32 -> f64 */ gen_helper_vfp_sitod(vd, vm, fpst); @@ -2583,7 +3024,7 @@ static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a) /* u32 -> f64 */ gen_helper_vfp_uitod(vd, vm, fpst); } - neon_store_reg64(vd, a->vd); + vfp_store_reg64(vd, a->vd); tcg_temp_free_i32(vm); tcg_temp_free_i64(vd); tcg_temp_free_ptr(fpst); @@ -2614,14 +3055,73 @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a) vm = tcg_temp_new_i64(); vd = tcg_temp_new_i32(); - neon_load_reg64(vm, a->vm); + vfp_load_reg64(vm, a->vm); gen_helper_vjcvt(vd, vm, cpu_env); - neon_store_reg32(vd, a->vd); + vfp_store_reg32(vd, a->vd); tcg_temp_free_i64(vm); tcg_temp_free_i32(vd); return true; } +static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a) +{ + TCGv_i32 vd, shift; + TCGv_ptr fpst; + int frac_bits; + + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm); + + vd = tcg_temp_new_i32(); + vfp_load_reg32(vd, a->vd); + + fpst = fpstatus_ptr(FPST_FPCR_F16); + shift = tcg_const_i32(frac_bits); + + /* Switch on op:U:sx bits */ + switch (a->opc) { + case 0: + gen_helper_vfp_shtoh_round_to_nearest(vd, vd, shift, fpst); + break; + case 1: + gen_helper_vfp_sltoh_round_to_nearest(vd, vd, shift, fpst); + break; + case 2: + gen_helper_vfp_uhtoh_round_to_nearest(vd, vd, shift, fpst); + break; + case 3: + gen_helper_vfp_ultoh_round_to_nearest(vd, vd, shift, fpst); + break; + case 4: + gen_helper_vfp_toshh_round_to_zero(vd, vd, shift, fpst); + break; + case 5: + gen_helper_vfp_toslh_round_to_zero(vd, vd, shift, fpst); + break; + case 6: + gen_helper_vfp_touhh_round_to_zero(vd, vd, shift, fpst); + break; + case 7: + gen_helper_vfp_toulh_round_to_zero(vd, vd, shift, fpst); + break; + default: + g_assert_not_reached(); + } + + vfp_store_reg32(vd, a->vd); + tcg_temp_free_i32(vd); + tcg_temp_free_i32(shift); + tcg_temp_free_ptr(fpst); + return true; +} + static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a) { TCGv_i32 vd, shift; @@ -2639,24 +3139,24 @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a) frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm); vd = tcg_temp_new_i32(); - neon_load_reg32(vd, a->vd); + vfp_load_reg32(vd, a->vd); - fpst = get_fpstatus_ptr(false); + fpst = fpstatus_ptr(FPST_FPCR); shift = tcg_const_i32(frac_bits); /* Switch on op:U:sx bits */ switch (a->opc) { case 0: - gen_helper_vfp_shtos(vd, vd, shift, fpst); + gen_helper_vfp_shtos_round_to_nearest(vd, vd, shift, fpst); break; case 1: - gen_helper_vfp_sltos(vd, vd, shift, fpst); + gen_helper_vfp_sltos_round_to_nearest(vd, vd, shift, fpst); break; case 2: - gen_helper_vfp_uhtos(vd, vd, shift, fpst); + gen_helper_vfp_uhtos_round_to_nearest(vd, vd, shift, fpst); break; case 3: - gen_helper_vfp_ultos(vd, vd, shift, fpst); + gen_helper_vfp_ultos_round_to_nearest(vd, vd, shift, fpst); break; case 4: gen_helper_vfp_toshs_round_to_zero(vd, vd, shift, fpst); @@ -2674,7 +3174,7 @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a) g_assert_not_reached(); } - neon_store_reg32(vd, a->vd); + vfp_store_reg32(vd, a->vd); tcg_temp_free_i32(vd); tcg_temp_free_i32(shift); tcg_temp_free_ptr(fpst); @@ -2704,24 +3204,24 @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a) frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm); vd = tcg_temp_new_i64(); - neon_load_reg64(vd, a->vd); + vfp_load_reg64(vd, a->vd); - fpst = get_fpstatus_ptr(false); + fpst = fpstatus_ptr(FPST_FPCR); shift = tcg_const_i32(frac_bits); /* Switch on op:U:sx bits */ switch (a->opc) { case 0: - gen_helper_vfp_shtod(vd, vd, shift, fpst); + gen_helper_vfp_shtod_round_to_nearest(vd, vd, shift, fpst); break; case 1: - gen_helper_vfp_sltod(vd, vd, shift, fpst); + gen_helper_vfp_sltod_round_to_nearest(vd, vd, shift, fpst); break; case 2: - gen_helper_vfp_uhtod(vd, vd, shift, fpst); + gen_helper_vfp_uhtod_round_to_nearest(vd, vd, shift, fpst); break; case 3: - gen_helper_vfp_ultod(vd, vd, shift, fpst); + gen_helper_vfp_ultod_round_to_nearest(vd, vd, shift, fpst); break; case 4: gen_helper_vfp_toshd_round_to_zero(vd, vd, shift, fpst); @@ -2739,13 +3239,49 @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a) g_assert_not_reached(); } - neon_store_reg64(vd, a->vd); + vfp_store_reg64(vd, a->vd); tcg_temp_free_i64(vd); tcg_temp_free_i32(shift); tcg_temp_free_ptr(fpst); return true; } +static bool trans_VCVT_hp_int(DisasContext *s, arg_VCVT_sp_int *a) +{ + TCGv_i32 vm; + TCGv_ptr fpst; + + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + fpst = fpstatus_ptr(FPST_FPCR_F16); + vm = tcg_temp_new_i32(); + vfp_load_reg32(vm, a->vm); + + if (a->s) { + if (a->rz) { + gen_helper_vfp_tosizh(vm, vm, fpst); + } else { + gen_helper_vfp_tosih(vm, vm, fpst); + } + } else { + if (a->rz) { + gen_helper_vfp_touizh(vm, vm, fpst); + } else { + gen_helper_vfp_touih(vm, vm, fpst); + } + } + vfp_store_reg32(vm, a->vd); + tcg_temp_free_i32(vm); + tcg_temp_free_ptr(fpst); + return true; +} + static bool trans_VCVT_sp_int(DisasContext *s, arg_VCVT_sp_int *a) { TCGv_i32 vm; @@ -2759,9 +3295,9 @@ static bool trans_VCVT_sp_int(DisasContext *s, arg_VCVT_sp_int *a) return true; } - fpst = get_fpstatus_ptr(false); + fpst = fpstatus_ptr(FPST_FPCR); vm = tcg_temp_new_i32(); - neon_load_reg32(vm, a->vm); + vfp_load_reg32(vm, a->vm); if (a->s) { if (a->rz) { @@ -2776,7 +3312,7 @@ static bool trans_VCVT_sp_int(DisasContext *s, arg_VCVT_sp_int *a) gen_helper_vfp_touis(vm, vm, fpst); } } - neon_store_reg32(vm, a->vd); + vfp_store_reg32(vm, a->vd); tcg_temp_free_i32(vm); tcg_temp_free_ptr(fpst); return true; @@ -2801,10 +3337,10 @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a) return true; } - fpst = get_fpstatus_ptr(false); + fpst = fpstatus_ptr(FPST_FPCR); vm = tcg_temp_new_i64(); vd = tcg_temp_new_i32(); - neon_load_reg64(vm, a->vm); + vfp_load_reg64(vm, a->vm); if (a->s) { if (a->rz) { @@ -2819,7 +3355,7 @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a) gen_helper_vfp_touid(vd, vm, fpst); } } - neon_store_reg32(vd, a->vd); + vfp_store_reg32(vd, a->vd); tcg_temp_free_i32(vd); tcg_temp_free_i64(vm); tcg_temp_free_ptr(fpst); @@ -2843,9 +3379,14 @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a) !arm_dc_feature(s, ARM_FEATURE_V8)) { return false; } - /* If not secure, UNDEF. */ + /* + * If not secure, UNDEF. We must emit code for this + * rather than returning false so that this takes + * precedence over the m-nocp.decode NOCP fallback. + */ if (!s->v8m_secure) { - return false; + unallocated_encoding(s); + return true; } /* If no fpu, NOP. */ if (!dc_isar_feature(aa32_vfp, s)) { @@ -2861,6 +3402,102 @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a) tcg_temp_free_i32(fptr); /* End the TB, because we have updated FP control bits */ - s->base.is_jmp = DISAS_UPDATE; + s->base.is_jmp = DISAS_UPDATE_EXIT; + return true; +} + +static bool trans_NOCP(DisasContext *s, arg_nocp *a) +{ + /* + * Handle M-profile early check for disabled coprocessor: + * all we need to do here is emit the NOCP exception if + * the coprocessor is disabled. Otherwise we return false + * and the real VFP/etc decode will handle the insn. + */ + assert(arm_dc_feature(s, ARM_FEATURE_M)); + + if (a->cp == 11) { + a->cp = 10; + } + if (arm_dc_feature(s, ARM_FEATURE_V8_1M) && + (a->cp == 8 || a->cp == 9 || a->cp == 14 || a->cp == 15)) { + /* in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */ + a->cp = 10; + } + + if (a->cp != 10) { + gen_exception_insn(s, s->pc_curr, EXCP_NOCP, + syn_uncategorized(), default_exception_el(s)); + return true; + } + + if (s->fp_excp_el != 0) { + gen_exception_insn(s, s->pc_curr, EXCP_NOCP, + syn_uncategorized(), s->fp_excp_el); + return true; + } + + return false; +} + +static bool trans_NOCP_8_1(DisasContext *s, arg_nocp *a) +{ + /* This range needs a coprocessor check for v8.1M and later only */ + if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) { + return false; + } + return trans_NOCP(s, a); +} + +static bool trans_VINS(DisasContext *s, arg_VINS *a) +{ + TCGv_i32 rd, rm; + + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + + if (s->vec_len != 0 || s->vec_stride != 0) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + /* Insert low half of Vm into high half of Vd */ + rm = tcg_temp_new_i32(); + rd = tcg_temp_new_i32(); + vfp_load_reg32(rm, a->vm); + vfp_load_reg32(rd, a->vd); + tcg_gen_deposit_i32(rd, rd, rm, 16, 16); + vfp_store_reg32(rd, a->vd); + tcg_temp_free_i32(rm); + tcg_temp_free_i32(rd); + return true; +} + +static bool trans_VMOVX(DisasContext *s, arg_VINS *a) +{ + TCGv_i32 rm; + + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + + if (s->vec_len != 0 || s->vec_stride != 0) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + /* Set Vd to high half of Vm */ + rm = tcg_temp_new_i32(); + vfp_load_reg32(rm, a->vm); + tcg_gen_shri_i32(rm, rm, 16); + vfp_store_reg32(rm, a->vd); + tcg_temp_free_i32(rm); return true; } diff --git a/target/arm/translate.c b/target/arm/translate.c index c8296116d4b3ea150d75118bac2c8e0e0bbe0b81..6d04ca3a8a09818cfbfba706a4c31fb201cc9cf5 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -49,8 +49,6 @@ #define ENABLE_ARCH_7 arm_dc_feature(s, ARM_FEATURE_V7) #define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8) -#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0) - #include "translate.h" #if defined(CONFIG_USER_ONLY) @@ -59,8 +57,9 @@ #define IS_USER(s) (s->user) #endif -/* We reuse the same 64-bit temporaries for efficiency. */ +/* These are TCG temporaries used only by the legacy iwMMXt decoder */ static TCGv_i64 cpu_V0, cpu_V1, cpu_M0; +/* These are TCG globals which alias CPUARMState fields */ static TCGv_i32 cpu_R[16]; TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF; TCGv_i64 cpu_exclusive_addr; @@ -377,47 +376,10 @@ static void gen_revsh(TCGv_i32 dest, TCGv_i32 var) tcg_gen_ext16s_i32(dest, var); } -/* 32x32->64 multiply. Marks inputs as dead. */ -static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b) -{ - TCGv_i32 lo = tcg_temp_new_i32(); - TCGv_i32 hi = tcg_temp_new_i32(); - TCGv_i64 ret; - - tcg_gen_mulu2_i32(lo, hi, a, b); - tcg_temp_free_i32(a); - tcg_temp_free_i32(b); - - ret = tcg_temp_new_i64(); - tcg_gen_concat_i32_i64(ret, lo, hi); - tcg_temp_free_i32(lo); - tcg_temp_free_i32(hi); - - return ret; -} - -static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b) -{ - TCGv_i32 lo = tcg_temp_new_i32(); - TCGv_i32 hi = tcg_temp_new_i32(); - TCGv_i64 ret; - - tcg_gen_muls2_i32(lo, hi, a, b); - tcg_temp_free_i32(a); - tcg_temp_free_i32(b); - - ret = tcg_temp_new_i64(); - tcg_gen_concat_i32_i64(ret, lo, hi); - tcg_temp_free_i32(lo); - tcg_temp_free_i32(hi); - - return ret; -} - /* Swap low and high halfwords. */ -static void gen_swap_half(TCGv_i32 var) +static void gen_swap_half(TCGv_i32 dest, TCGv_i32 var) { - tcg_gen_rotri_i32(var, var, 16); + tcg_gen_rotri_i32(dest, var, 16); } /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead. @@ -1132,178 +1094,141 @@ static inline void gen_hlt(DisasContext *s, int imm) unallocated_encoding(s); } -static TCGv_ptr get_fpstatus_ptr(int neon) -{ - TCGv_ptr statusptr = tcg_temp_new_ptr(); - int offset; - if (neon) { - offset = offsetof(CPUARMState, vfp.standard_fp_status); - } else { - offset = offsetof(CPUARMState, vfp.fp_status); - } - tcg_gen_addi_ptr(statusptr, cpu_env, offset); - return statusptr; -} - -static inline long vfp_reg_offset(bool dp, unsigned reg) -{ - if (dp) { - return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]); - } else { - long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]); - if (reg & 1) { - ofs += offsetof(CPU_DoubleU, l.upper); - } else { - ofs += offsetof(CPU_DoubleU, l.lower); - } - return ofs; - } -} - -/* Return the offset of a 32-bit piece of a NEON register. - zero is the least significant end of the register. */ -static inline long -neon_reg_offset (int reg, int n) +/* + * Return the offset of a "full" NEON Dreg. + */ +static long neon_full_reg_offset(unsigned reg) { - int sreg; - sreg = reg * 2 + n; - return vfp_reg_offset(0, sreg); + return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]); } -/* Return the offset of a 2**SIZE piece of a NEON register, at index ELE, +/* + * Return the offset of a 2**SIZE piece of a NEON register, at index ELE, * where 0 is the least significant end of the register. */ -static inline long -neon_element_offset(int reg, int element, MemOp size) +static long neon_element_offset(int reg, int element, MemOp memop) { - int element_size = 1 << size; + int element_size = 1 << (memop & MO_SIZE); int ofs = element * element_size; #ifdef HOST_WORDS_BIGENDIAN - /* Calculate the offset assuming fully little-endian, + /* + * Calculate the offset assuming fully little-endian, * then XOR to account for the order of the 8-byte units. */ if (element_size < 8) { ofs ^= 8 - element_size; } #endif - return neon_reg_offset(reg, 0) + ofs; + return neon_full_reg_offset(reg) + ofs; } -static TCGv_i32 neon_load_reg(int reg, int pass) +/* Return the offset of a VFP Dreg (dp = true) or VFP Sreg (dp = false). */ +static long vfp_reg_offset(bool dp, unsigned reg) { - TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass)); - return tmp; + if (dp) { + return neon_element_offset(reg, 0, MO_64); + } else { + return neon_element_offset(reg >> 1, reg & 1, MO_32); + } +} + +static inline void vfp_load_reg64(TCGv_i64 var, int reg) +{ + tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(true, reg)); +} + +static inline void vfp_store_reg64(TCGv_i64 var, int reg) +{ + tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(true, reg)); +} + +static inline void vfp_load_reg32(TCGv_i32 var, int reg) +{ + tcg_gen_ld_i32(var, cpu_env, vfp_reg_offset(false, reg)); +} + +static inline void vfp_store_reg32(TCGv_i32 var, int reg) +{ + tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg)); } -static void neon_load_element(TCGv_i32 var, int reg, int ele, MemOp mop) +static void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop) { - long offset = neon_element_offset(reg, ele, mop & MO_SIZE); + long off = neon_element_offset(reg, ele, memop); - switch (mop) { + switch (memop) { + case MO_SB: + tcg_gen_ld8s_i32(dest, cpu_env, off); + break; case MO_UB: - tcg_gen_ld8u_i32(var, cpu_env, offset); + tcg_gen_ld8u_i32(dest, cpu_env, off); + break; + case MO_SW: + tcg_gen_ld16s_i32(dest, cpu_env, off); break; case MO_UW: - tcg_gen_ld16u_i32(var, cpu_env, offset); + tcg_gen_ld16u_i32(dest, cpu_env, off); break; case MO_UL: - tcg_gen_ld_i32(var, cpu_env, offset); + case MO_SL: + tcg_gen_ld_i32(dest, cpu_env, off); break; default: g_assert_not_reached(); } } -static void neon_load_element64(TCGv_i64 var, int reg, int ele, MemOp mop) +static void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop) { - long offset = neon_element_offset(reg, ele, mop & MO_SIZE); + long off = neon_element_offset(reg, ele, memop); - switch (mop) { - case MO_UB: - tcg_gen_ld8u_i64(var, cpu_env, offset); - break; - case MO_UW: - tcg_gen_ld16u_i64(var, cpu_env, offset); + switch (memop) { + case MO_SL: + tcg_gen_ld32s_i64(dest, cpu_env, off); break; case MO_UL: - tcg_gen_ld32u_i64(var, cpu_env, offset); + tcg_gen_ld32u_i64(dest, cpu_env, off); break; case MO_Q: - tcg_gen_ld_i64(var, cpu_env, offset); + tcg_gen_ld_i64(dest, cpu_env, off); break; default: g_assert_not_reached(); } } -static void neon_store_reg(int reg, int pass, TCGv_i32 var) +static void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop) { - tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass)); - tcg_temp_free_i32(var); -} + long off = neon_element_offset(reg, ele, memop); -static void neon_store_element(int reg, int ele, MemOp size, TCGv_i32 var) -{ - long offset = neon_element_offset(reg, ele, size); - - switch (size) { + switch (memop) { case MO_8: - tcg_gen_st8_i32(var, cpu_env, offset); + tcg_gen_st8_i32(src, cpu_env, off); break; case MO_16: - tcg_gen_st16_i32(var, cpu_env, offset); + tcg_gen_st16_i32(src, cpu_env, off); break; case MO_32: - tcg_gen_st_i32(var, cpu_env, offset); + tcg_gen_st_i32(src, cpu_env, off); break; default: g_assert_not_reached(); } } -static void neon_store_element64(int reg, int ele, MemOp size, TCGv_i64 var) +static void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop) { - long offset = neon_element_offset(reg, ele, size); + long off = neon_element_offset(reg, ele, memop); - switch (size) { - case MO_8: - tcg_gen_st8_i64(var, cpu_env, offset); - break; - case MO_16: - tcg_gen_st16_i64(var, cpu_env, offset); - break; - case MO_32: - tcg_gen_st32_i64(var, cpu_env, offset); - break; + switch (memop) { case MO_64: - tcg_gen_st_i64(var, cpu_env, offset); + tcg_gen_st_i64(src, cpu_env, off); break; default: g_assert_not_reached(); } } -static inline void neon_load_reg64(TCGv_i64 var, int reg) -{ - tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg)); -} - -static inline void neon_store_reg64(TCGv_i64 var, int reg) -{ - tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg)); -} - -static inline void neon_load_reg32(TCGv_i32 var, int reg) -{ - tcg_gen_ld_i32(var, cpu_env, vfp_reg_offset(false, reg)); -} - -static inline void neon_store_reg32(TCGv_i32 var, int reg) -{ - tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg)); -} - static TCGv_ptr vfp_reg_ptr(bool dp, int reg) { TCGv_ptr ret = tcg_temp_new_ptr(); @@ -1314,8 +1239,9 @@ static TCGv_ptr vfp_reg_ptr(bool dp, int reg) #define ARM_CP_RW_BIT (1 << 20) /* Include the VFP and Neon decoders */ -#include "translate-vfp.inc.c" -#include "translate-neon.inc.c" +#include "decode-m-nocp.c.inc" +#include "translate-vfp.c.inc" +#include "translate-neon.c.inc" static inline void iwmmxt_load_reg(TCGv_i64 var, int reg) { @@ -2609,39 +2535,6 @@ static int disas_dsp_insn(DisasContext *s, uint32_t insn) return 1; } -#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n)) -#define VFP_DREG(reg, insn, bigbit, smallbit) do { \ - if (dc_isar_feature(aa32_simd_r32, s)) { \ - reg = (((insn) >> (bigbit)) & 0x0f) \ - | (((insn) >> ((smallbit) - 4)) & 0x10); \ - } else { \ - if (insn & (1 << (smallbit))) \ - return 1; \ - reg = ((insn) >> (bigbit)) & 0x0f; \ - }} while (0) - -#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22) -#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7) -#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5) - -static void gen_neon_dup_low16(TCGv_i32 var) -{ - TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_ext16u_i32(var, var); - tcg_gen_shli_i32(tmp, var, 16); - tcg_gen_or_i32(var, var, tmp); - tcg_temp_free_i32(tmp); -} - -static void gen_neon_dup_high16(TCGv_i32 var) -{ - TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_andi_i32(var, var, 0xffff0000); - tcg_gen_shri_i32(tmp, var, 16); - tcg_gen_or_i32(var, var, tmp); - tcg_temp_free_i32(tmp); -} - static inline bool use_goto_tb(DisasContext *s, target_ulong dest) { #ifndef CONFIG_USER_ONLY @@ -2674,17 +2567,23 @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest) s->base.is_jmp = DISAS_NORETURN; } -static inline void gen_jmp (DisasContext *s, uint32_t dest) +/* Jump, specifying which TB number to use if we gen_goto_tb() */ +static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno) { if (unlikely(is_singlestepping(s))) { /* An indirect jump so that we still trigger the debug exception. */ gen_set_pc_im(s, dest); s->base.is_jmp = DISAS_JUMP; } else { - gen_goto_tb(s, 0, dest); + gen_goto_tb(s, tbno, dest); } } +static inline void gen_jmp(DisasContext *s, uint32_t dest) +{ + gen_jmp_tb(s, dest, 0); +} + static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y) { if (x) @@ -2931,7 +2830,7 @@ static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn) tcg_temp_free_i32(tcg_tgtmode); tcg_temp_free_i32(tcg_regno); tcg_temp_free_i32(tcg_reg); - s->base.is_jmp = DISAS_UPDATE; + s->base.is_jmp = DISAS_UPDATE_EXIT; } static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn) @@ -2953,7 +2852,7 @@ static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn) tcg_temp_free_i32(tcg_tgtmode); tcg_temp_free_i32(tcg_regno); store_reg(s, rn, tcg_reg); - s->base.is_jmp = DISAS_UPDATE; + s->base.is_jmp = DISAS_UPDATE_EXIT; } /* Store value to PC as for an exception return (ie don't @@ -2989,545 +2888,6 @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc) gen_rfe(s, pc, load_cpu_field(spsr)); } -#define CPU_V001 cpu_V0, cpu_V0, cpu_V1 - -static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1) -{ - switch (size) { - case 0: gen_helper_neon_add_u8(t0, t0, t1); break; - case 1: gen_helper_neon_add_u16(t0, t0, t1); break; - case 2: tcg_gen_add_i32(t0, t0, t1); break; - default: abort(); - } -} - -static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1) -{ - switch (size) { - case 0: gen_helper_neon_sub_u8(t0, t1, t0); break; - case 1: gen_helper_neon_sub_u16(t0, t1, t0); break; - case 2: tcg_gen_sub_i32(t0, t1, t0); break; - default: return; - } -} - -#define GEN_NEON_INTEGER_OP_ENV(name) do { \ - switch ((size << 1) | u) { \ - case 0: \ - gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \ - break; \ - case 1: \ - gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \ - break; \ - case 2: \ - gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \ - break; \ - case 3: \ - gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \ - break; \ - case 4: \ - gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \ - break; \ - case 5: \ - gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \ - break; \ - default: return 1; \ - }} while (0) - -static TCGv_i32 neon_load_scratch(int scratch) -{ - TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch])); - return tmp; -} - -static void neon_store_scratch(int scratch, TCGv_i32 var) -{ - tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch])); - tcg_temp_free_i32(var); -} - -static inline TCGv_i32 neon_get_scalar(int size, int reg) -{ - TCGv_i32 tmp; - if (size == 1) { - tmp = neon_load_reg(reg & 7, reg >> 4); - if (reg & 8) { - gen_neon_dup_high16(tmp); - } else { - gen_neon_dup_low16(tmp); - } - } else { - tmp = neon_load_reg(reg & 15, reg >> 4); - } - return tmp; -} - -static int gen_neon_unzip(int rd, int rm, int size, int q) -{ - TCGv_ptr pd, pm; - - if (!q && size == 2) { - return 1; - } - pd = vfp_reg_ptr(true, rd); - pm = vfp_reg_ptr(true, rm); - if (q) { - switch (size) { - case 0: - gen_helper_neon_qunzip8(pd, pm); - break; - case 1: - gen_helper_neon_qunzip16(pd, pm); - break; - case 2: - gen_helper_neon_qunzip32(pd, pm); - break; - default: - abort(); - } - } else { - switch (size) { - case 0: - gen_helper_neon_unzip8(pd, pm); - break; - case 1: - gen_helper_neon_unzip16(pd, pm); - break; - default: - abort(); - } - } - tcg_temp_free_ptr(pd); - tcg_temp_free_ptr(pm); - return 0; -} - -static int gen_neon_zip(int rd, int rm, int size, int q) -{ - TCGv_ptr pd, pm; - - if (!q && size == 2) { - return 1; - } - pd = vfp_reg_ptr(true, rd); - pm = vfp_reg_ptr(true, rm); - if (q) { - switch (size) { - case 0: - gen_helper_neon_qzip8(pd, pm); - break; - case 1: - gen_helper_neon_qzip16(pd, pm); - break; - case 2: - gen_helper_neon_qzip32(pd, pm); - break; - default: - abort(); - } - } else { - switch (size) { - case 0: - gen_helper_neon_zip8(pd, pm); - break; - case 1: - gen_helper_neon_zip16(pd, pm); - break; - default: - abort(); - } - } - tcg_temp_free_ptr(pd); - tcg_temp_free_ptr(pm); - return 0; -} - -static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1) -{ - TCGv_i32 rd, tmp; - - rd = tcg_temp_new_i32(); - tmp = tcg_temp_new_i32(); - - tcg_gen_shli_i32(rd, t0, 8); - tcg_gen_andi_i32(rd, rd, 0xff00ff00); - tcg_gen_andi_i32(tmp, t1, 0x00ff00ff); - tcg_gen_or_i32(rd, rd, tmp); - - tcg_gen_shri_i32(t1, t1, 8); - tcg_gen_andi_i32(t1, t1, 0x00ff00ff); - tcg_gen_andi_i32(tmp, t0, 0xff00ff00); - tcg_gen_or_i32(t1, t1, tmp); - tcg_gen_mov_i32(t0, rd); - - tcg_temp_free_i32(tmp); - tcg_temp_free_i32(rd); -} - -static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1) -{ - TCGv_i32 rd, tmp; - - rd = tcg_temp_new_i32(); - tmp = tcg_temp_new_i32(); - - tcg_gen_shli_i32(rd, t0, 16); - tcg_gen_andi_i32(tmp, t1, 0xffff); - tcg_gen_or_i32(rd, rd, tmp); - tcg_gen_shri_i32(t1, t1, 16); - tcg_gen_andi_i32(tmp, t0, 0xffff0000); - tcg_gen_or_i32(t1, t1, tmp); - tcg_gen_mov_i32(t0, rd); - - tcg_temp_free_i32(tmp); - tcg_temp_free_i32(rd); -} - -static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src) -{ - switch (size) { - case 0: gen_helper_neon_narrow_u8(dest, src); break; - case 1: gen_helper_neon_narrow_u16(dest, src); break; - case 2: tcg_gen_extrl_i64_i32(dest, src); break; - default: abort(); - } -} - -static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src) -{ - switch (size) { - case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break; - case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break; - case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break; - default: abort(); - } -} - -static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src) -{ - switch (size) { - case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break; - case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break; - case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break; - default: abort(); - } -} - -static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src) -{ - switch (size) { - case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break; - case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break; - case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break; - default: abort(); - } -} - -static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift, - int q, int u) -{ - if (q) { - if (u) { - switch (size) { - case 1: gen_helper_neon_rshl_u16(var, var, shift); break; - case 2: gen_helper_neon_rshl_u32(var, var, shift); break; - default: abort(); - } - } else { - switch (size) { - case 1: gen_helper_neon_rshl_s16(var, var, shift); break; - case 2: gen_helper_neon_rshl_s32(var, var, shift); break; - default: abort(); - } - } - } else { - if (u) { - switch (size) { - case 1: gen_helper_neon_shl_u16(var, var, shift); break; - case 2: gen_ushl_i32(var, var, shift); break; - default: abort(); - } - } else { - switch (size) { - case 1: gen_helper_neon_shl_s16(var, var, shift); break; - case 2: gen_sshl_i32(var, var, shift); break; - default: abort(); - } - } - } -} - -static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u) -{ - if (u) { - switch (size) { - case 0: gen_helper_neon_widen_u8(dest, src); break; - case 1: gen_helper_neon_widen_u16(dest, src); break; - case 2: tcg_gen_extu_i32_i64(dest, src); break; - default: abort(); - } - } else { - switch (size) { - case 0: gen_helper_neon_widen_s8(dest, src); break; - case 1: gen_helper_neon_widen_s16(dest, src); break; - case 2: tcg_gen_ext_i32_i64(dest, src); break; - default: abort(); - } - } - tcg_temp_free_i32(src); -} - -static inline void gen_neon_addl(int size) -{ - switch (size) { - case 0: gen_helper_neon_addl_u16(CPU_V001); break; - case 1: gen_helper_neon_addl_u32(CPU_V001); break; - case 2: tcg_gen_add_i64(CPU_V001); break; - default: abort(); - } -} - -static inline void gen_neon_subl(int size) -{ - switch (size) { - case 0: gen_helper_neon_subl_u16(CPU_V001); break; - case 1: gen_helper_neon_subl_u32(CPU_V001); break; - case 2: tcg_gen_sub_i64(CPU_V001); break; - default: abort(); - } -} - -static inline void gen_neon_negl(TCGv_i64 var, int size) -{ - switch (size) { - case 0: gen_helper_neon_negl_u16(var, var); break; - case 1: gen_helper_neon_negl_u32(var, var); break; - case 2: - tcg_gen_neg_i64(var, var); - break; - default: abort(); - } -} - -static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size) -{ - switch (size) { - case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break; - case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break; - default: abort(); - } -} - -static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b, - int size, int u) -{ - TCGv_i64 tmp; - - switch ((size << 1) | u) { - case 0: gen_helper_neon_mull_s8(dest, a, b); break; - case 1: gen_helper_neon_mull_u8(dest, a, b); break; - case 2: gen_helper_neon_mull_s16(dest, a, b); break; - case 3: gen_helper_neon_mull_u16(dest, a, b); break; - case 4: - tmp = gen_muls_i64_i32(a, b); - tcg_gen_mov_i64(dest, tmp); - tcg_temp_free_i64(tmp); - break; - case 5: - tmp = gen_mulu_i64_i32(a, b); - tcg_gen_mov_i64(dest, tmp); - tcg_temp_free_i64(tmp); - break; - default: abort(); - } - - /* gen_helper_neon_mull_[su]{8|16} do not free their parameters. - Don't forget to clean them now. */ - if (size < 2) { - tcg_temp_free_i32(a); - tcg_temp_free_i32(b); - } -} - -static void gen_neon_narrow_op(int op, int u, int size, - TCGv_i32 dest, TCGv_i64 src) -{ - if (op) { - if (u) { - gen_neon_unarrow_sats(size, dest, src); - } else { - gen_neon_narrow(size, dest, src); - } - } else { - if (u) { - gen_neon_narrow_satu(size, dest, src); - } else { - gen_neon_narrow_sats(size, dest, src); - } - } -} - -/* Symbolic constants for op fields for Neon 2-register miscellaneous. - * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B - * table A7-13. - */ -#define NEON_2RM_VREV64 0 -#define NEON_2RM_VREV32 1 -#define NEON_2RM_VREV16 2 -#define NEON_2RM_VPADDL 4 -#define NEON_2RM_VPADDL_U 5 -#define NEON_2RM_AESE 6 /* Includes AESD */ -#define NEON_2RM_AESMC 7 /* Includes AESIMC */ -#define NEON_2RM_VCLS 8 -#define NEON_2RM_VCLZ 9 -#define NEON_2RM_VCNT 10 -#define NEON_2RM_VMVN 11 -#define NEON_2RM_VPADAL 12 -#define NEON_2RM_VPADAL_U 13 -#define NEON_2RM_VQABS 14 -#define NEON_2RM_VQNEG 15 -#define NEON_2RM_VCGT0 16 -#define NEON_2RM_VCGE0 17 -#define NEON_2RM_VCEQ0 18 -#define NEON_2RM_VCLE0 19 -#define NEON_2RM_VCLT0 20 -#define NEON_2RM_SHA1H 21 -#define NEON_2RM_VABS 22 -#define NEON_2RM_VNEG 23 -#define NEON_2RM_VCGT0_F 24 -#define NEON_2RM_VCGE0_F 25 -#define NEON_2RM_VCEQ0_F 26 -#define NEON_2RM_VCLE0_F 27 -#define NEON_2RM_VCLT0_F 28 -#define NEON_2RM_VABS_F 30 -#define NEON_2RM_VNEG_F 31 -#define NEON_2RM_VSWP 32 -#define NEON_2RM_VTRN 33 -#define NEON_2RM_VUZP 34 -#define NEON_2RM_VZIP 35 -#define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */ -#define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */ -#define NEON_2RM_VSHLL 38 -#define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */ -#define NEON_2RM_VRINTN 40 -#define NEON_2RM_VRINTX 41 -#define NEON_2RM_VRINTA 42 -#define NEON_2RM_VRINTZ 43 -#define NEON_2RM_VCVT_F16_F32 44 -#define NEON_2RM_VRINTM 45 -#define NEON_2RM_VCVT_F32_F16 46 -#define NEON_2RM_VRINTP 47 -#define NEON_2RM_VCVTAU 48 -#define NEON_2RM_VCVTAS 49 -#define NEON_2RM_VCVTNU 50 -#define NEON_2RM_VCVTNS 51 -#define NEON_2RM_VCVTPU 52 -#define NEON_2RM_VCVTPS 53 -#define NEON_2RM_VCVTMU 54 -#define NEON_2RM_VCVTMS 55 -#define NEON_2RM_VRECPE 56 -#define NEON_2RM_VRSQRTE 57 -#define NEON_2RM_VRECPE_F 58 -#define NEON_2RM_VRSQRTE_F 59 -#define NEON_2RM_VCVT_FS 60 -#define NEON_2RM_VCVT_FU 61 -#define NEON_2RM_VCVT_SF 62 -#define NEON_2RM_VCVT_UF 63 - -static bool neon_2rm_is_v8_op(int op) -{ - /* Return true if this neon 2reg-misc op is ARMv8 and up */ - switch (op) { - case NEON_2RM_VRINTN: - case NEON_2RM_VRINTA: - case NEON_2RM_VRINTM: - case NEON_2RM_VRINTP: - case NEON_2RM_VRINTZ: - case NEON_2RM_VRINTX: - case NEON_2RM_VCVTAU: - case NEON_2RM_VCVTAS: - case NEON_2RM_VCVTNU: - case NEON_2RM_VCVTNS: - case NEON_2RM_VCVTPU: - case NEON_2RM_VCVTPS: - case NEON_2RM_VCVTMU: - case NEON_2RM_VCVTMS: - return true; - default: - return false; - } -} - -/* Each entry in this array has bit n set if the insn allows - * size value n (otherwise it will UNDEF). Since unallocated - * op values will have no bits set they always UNDEF. - */ -static const uint8_t neon_2rm_sizes[] = { - [NEON_2RM_VREV64] = 0x7, - [NEON_2RM_VREV32] = 0x3, - [NEON_2RM_VREV16] = 0x1, - [NEON_2RM_VPADDL] = 0x7, - [NEON_2RM_VPADDL_U] = 0x7, - [NEON_2RM_AESE] = 0x1, - [NEON_2RM_AESMC] = 0x1, - [NEON_2RM_VCLS] = 0x7, - [NEON_2RM_VCLZ] = 0x7, - [NEON_2RM_VCNT] = 0x1, - [NEON_2RM_VMVN] = 0x1, - [NEON_2RM_VPADAL] = 0x7, - [NEON_2RM_VPADAL_U] = 0x7, - [NEON_2RM_VQABS] = 0x7, - [NEON_2RM_VQNEG] = 0x7, - [NEON_2RM_VCGT0] = 0x7, - [NEON_2RM_VCGE0] = 0x7, - [NEON_2RM_VCEQ0] = 0x7, - [NEON_2RM_VCLE0] = 0x7, - [NEON_2RM_VCLT0] = 0x7, - [NEON_2RM_SHA1H] = 0x4, - [NEON_2RM_VABS] = 0x7, - [NEON_2RM_VNEG] = 0x7, - [NEON_2RM_VCGT0_F] = 0x4, - [NEON_2RM_VCGE0_F] = 0x4, - [NEON_2RM_VCEQ0_F] = 0x4, - [NEON_2RM_VCLE0_F] = 0x4, - [NEON_2RM_VCLT0_F] = 0x4, - [NEON_2RM_VABS_F] = 0x4, - [NEON_2RM_VNEG_F] = 0x4, - [NEON_2RM_VSWP] = 0x1, - [NEON_2RM_VTRN] = 0x7, - [NEON_2RM_VUZP] = 0x7, - [NEON_2RM_VZIP] = 0x7, - [NEON_2RM_VMOVN] = 0x7, - [NEON_2RM_VQMOVN] = 0x7, - [NEON_2RM_VSHLL] = 0x7, - [NEON_2RM_SHA1SU1] = 0x4, - [NEON_2RM_VRINTN] = 0x4, - [NEON_2RM_VRINTX] = 0x4, - [NEON_2RM_VRINTA] = 0x4, - [NEON_2RM_VRINTZ] = 0x4, - [NEON_2RM_VCVT_F16_F32] = 0x2, - [NEON_2RM_VRINTM] = 0x4, - [NEON_2RM_VCVT_F32_F16] = 0x2, - [NEON_2RM_VRINTP] = 0x4, - [NEON_2RM_VCVTAU] = 0x4, - [NEON_2RM_VCVTAS] = 0x4, - [NEON_2RM_VCVTNU] = 0x4, - [NEON_2RM_VCVTNS] = 0x4, - [NEON_2RM_VCVTPU] = 0x4, - [NEON_2RM_VCVTPS] = 0x4, - [NEON_2RM_VCVTMU] = 0x4, - [NEON_2RM_VCVTMS] = 0x4, - [NEON_2RM_VRECPE] = 0x4, - [NEON_2RM_VRSQRTE] = 0x4, - [NEON_2RM_VRECPE_F] = 0x4, - [NEON_2RM_VRSQRTE_F] = 0x4, - [NEON_2RM_VCVT_FS] = 0x4, - [NEON_2RM_VCVT_FU] = 0x4, - [NEON_2RM_VCVT_SF] = 0x4, - [NEON_2RM_VCVT_UF] = 0x4, -}; - static void gen_gvec_fn3_qc(uint32_t rd_ofs, uint32_t rn_ofs, uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz, gen_helper_gvec_3_ptr *fn) @@ -5207,1583 +4567,44 @@ static void gen_uaba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b) void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz) { - static const TCGOpcode vecop_list[] = { - INDEX_op_sub_vec, INDEX_op_add_vec, - INDEX_op_umin_vec, INDEX_op_umax_vec, 0 - }; - static const GVecGen3 ops[4] = { - { .fniv = gen_uaba_vec, - .fno = gen_helper_gvec_uaba_b, - .opt_opc = vecop_list, - .load_dest = true, - .vece = MO_8 }, - { .fniv = gen_uaba_vec, - .fno = gen_helper_gvec_uaba_h, - .opt_opc = vecop_list, - .load_dest = true, - .vece = MO_16 }, - { .fni4 = gen_uaba_i32, - .fniv = gen_uaba_vec, - .fno = gen_helper_gvec_uaba_s, - .opt_opc = vecop_list, - .load_dest = true, - .vece = MO_32 }, - { .fni8 = gen_uaba_i64, - .fniv = gen_uaba_vec, - .fno = gen_helper_gvec_uaba_d, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - .opt_opc = vecop_list, - .load_dest = true, - .vece = MO_64 }, - }; - tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); -} - -/* Translate a NEON data processing instruction. Return nonzero if the - instruction is invalid. - We process data in a mixture of 32-bit and 64-bit chunks. - Mostly we use 32-bit chunks so we can use normal scalar instructions. */ - -static int disas_neon_data_insn(DisasContext *s, uint32_t insn) -{ - int op; - int q; - int rd, rn, rm, rd_ofs, rn_ofs, rm_ofs; - int size; - int shift; - int pass; - int count; - int u; - int vec_size; - uint32_t imm; - TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5; - TCGv_ptr ptr1, ptr2; - TCGv_i64 tmp64; - - if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { - return 1; - } - - /* FIXME: this access check should not take precedence over UNDEF - * for invalid encodings; we will generate incorrect syndrome information - * for attempts to execute invalid vfp/neon encodings with FP disabled. - */ - if (s->fp_excp_el) { - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_simd_access_trap(1, 0xe, false), s->fp_excp_el); - return 0; - } - - if (!s->vfp_enabled) - return 1; - q = (insn & (1 << 6)) != 0; - u = (insn >> 24) & 1; - VFP_DREG_D(rd, insn); - VFP_DREG_N(rn, insn); - VFP_DREG_M(rm, insn); - size = (insn >> 20) & 3; - vec_size = q ? 16 : 8; - rd_ofs = neon_reg_offset(rd, 0); - rn_ofs = neon_reg_offset(rn, 0); - rm_ofs = neon_reg_offset(rm, 0); - - if ((insn & (1 << 23)) == 0) { - /* Three register same length: handled by decodetree */ - return 1; - } else if (insn & (1 << 4)) { - if ((insn & 0x00380080) != 0) { - /* Two registers and shift. */ - op = (insn >> 8) & 0xf; - if (insn & (1 << 7)) { - /* 64-bit shift. */ - if (op > 7) { - return 1; - } - size = 3; - } else { - size = 2; - while ((insn & (1 << (size + 19))) == 0) - size--; - } - shift = (insn >> 16) & ((1 << (3 + size)) - 1); - if (op < 8) { - /* Shift by immediate: - VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */ - if (q && ((rd | rm) & 1)) { - return 1; - } - if (!u && (op == 4 || op == 6)) { - return 1; - } - /* Right shifts are encoded as N - shift, where N is the - element size in bits. */ - if (op <= 4) { - shift = shift - (1 << (size + 3)); - } - - switch (op) { - case 0: /* VSHR */ - /* Right shift comes here negative. */ - shift = -shift; - /* Shifts larger than the element size are architecturally - * valid. Unsigned results in all zeros; signed results - * in all sign bits. - */ - if (!u) { - tcg_gen_gvec_sari(size, rd_ofs, rm_ofs, - MIN(shift, (8 << size) - 1), - vec_size, vec_size); - } else if (shift >= 8 << size) { - tcg_gen_gvec_dup_imm(MO_8, rd_ofs, vec_size, - vec_size, 0); - } else { - tcg_gen_gvec_shri(size, rd_ofs, rm_ofs, shift, - vec_size, vec_size); - } - return 0; - - case 1: /* VSRA */ - /* Right shift comes here negative. */ - shift = -shift; - if (u) { - gen_gvec_usra(size, rd_ofs, rm_ofs, shift, - vec_size, vec_size); - } else { - gen_gvec_ssra(size, rd_ofs, rm_ofs, shift, - vec_size, vec_size); - } - return 0; - - case 2: /* VRSHR */ - /* Right shift comes here negative. */ - shift = -shift; - if (u) { - gen_gvec_urshr(size, rd_ofs, rm_ofs, shift, - vec_size, vec_size); - } else { - gen_gvec_srshr(size, rd_ofs, rm_ofs, shift, - vec_size, vec_size); - } - return 0; - - case 3: /* VRSRA */ - /* Right shift comes here negative. */ - shift = -shift; - if (u) { - gen_gvec_ursra(size, rd_ofs, rm_ofs, shift, - vec_size, vec_size); - } else { - gen_gvec_srsra(size, rd_ofs, rm_ofs, shift, - vec_size, vec_size); - } - return 0; - - case 4: /* VSRI */ - if (!u) { - return 1; - } - /* Right shift comes here negative. */ - shift = -shift; - gen_gvec_sri(size, rd_ofs, rm_ofs, shift, - vec_size, vec_size); - return 0; - - case 5: /* VSHL, VSLI */ - if (u) { /* VSLI */ - gen_gvec_sli(size, rd_ofs, rm_ofs, shift, - vec_size, vec_size); - } else { /* VSHL */ - tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift, - vec_size, vec_size); - } - return 0; - } - - if (size == 3) { - count = q + 1; - } else { - count = q ? 4: 2; - } - - /* To avoid excessive duplication of ops we implement shift - * by immediate using the variable shift operations. - */ - imm = dup_const(size, shift); - - for (pass = 0; pass < count; pass++) { - if (size == 3) { - neon_load_reg64(cpu_V0, rm + pass); - tcg_gen_movi_i64(cpu_V1, imm); - switch (op) { - case 6: /* VQSHLU */ - gen_helper_neon_qshlu_s64(cpu_V0, cpu_env, - cpu_V0, cpu_V1); - break; - case 7: /* VQSHL */ - if (u) { - gen_helper_neon_qshl_u64(cpu_V0, cpu_env, - cpu_V0, cpu_V1); - } else { - gen_helper_neon_qshl_s64(cpu_V0, cpu_env, - cpu_V0, cpu_V1); - } - break; - default: - g_assert_not_reached(); - } - neon_store_reg64(cpu_V0, rd + pass); - } else { /* size < 3 */ - /* Operands in T0 and T1. */ - tmp = neon_load_reg(rm, pass); - tmp2 = tcg_temp_new_i32(); - tcg_gen_movi_i32(tmp2, imm); - switch (op) { - case 6: /* VQSHLU */ - switch (size) { - case 0: - gen_helper_neon_qshlu_s8(tmp, cpu_env, - tmp, tmp2); - break; - case 1: - gen_helper_neon_qshlu_s16(tmp, cpu_env, - tmp, tmp2); - break; - case 2: - gen_helper_neon_qshlu_s32(tmp, cpu_env, - tmp, tmp2); - break; - default: - abort(); - } - break; - case 7: /* VQSHL */ - GEN_NEON_INTEGER_OP_ENV(qshl); - break; - default: - g_assert_not_reached(); - } - tcg_temp_free_i32(tmp2); - neon_store_reg(rd, pass, tmp); - } - } /* for pass */ - } else if (op < 10) { - /* Shift by immediate and narrow: - VSHRN, VRSHRN, VQSHRN, VQRSHRN. */ - int input_unsigned = (op == 8) ? !u : u; - if (rm & 1) { - return 1; - } - shift = shift - (1 << (size + 3)); - size++; - if (size == 3) { - tmp64 = tcg_const_i64(shift); - neon_load_reg64(cpu_V0, rm); - neon_load_reg64(cpu_V1, rm + 1); - for (pass = 0; pass < 2; pass++) { - TCGv_i64 in; - if (pass == 0) { - in = cpu_V0; - } else { - in = cpu_V1; - } - if (q) { - if (input_unsigned) { - gen_helper_neon_rshl_u64(cpu_V0, in, tmp64); - } else { - gen_helper_neon_rshl_s64(cpu_V0, in, tmp64); - } - } else { - if (input_unsigned) { - gen_ushl_i64(cpu_V0, in, tmp64); - } else { - gen_sshl_i64(cpu_V0, in, tmp64); - } - } - tmp = tcg_temp_new_i32(); - gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0); - neon_store_reg(rd, pass, tmp); - } /* for pass */ - tcg_temp_free_i64(tmp64); - } else { - if (size == 1) { - imm = (uint16_t)shift; - imm |= imm << 16; - } else { - /* size == 2 */ - imm = (uint32_t)shift; - } - tmp2 = tcg_const_i32(imm); - tmp4 = neon_load_reg(rm + 1, 0); - tmp5 = neon_load_reg(rm + 1, 1); - for (pass = 0; pass < 2; pass++) { - if (pass == 0) { - tmp = neon_load_reg(rm, 0); - } else { - tmp = tmp4; - } - gen_neon_shift_narrow(size, tmp, tmp2, q, - input_unsigned); - if (pass == 0) { - tmp3 = neon_load_reg(rm, 1); - } else { - tmp3 = tmp5; - } - gen_neon_shift_narrow(size, tmp3, tmp2, q, - input_unsigned); - tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3); - tcg_temp_free_i32(tmp); - tcg_temp_free_i32(tmp3); - tmp = tcg_temp_new_i32(); - gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0); - neon_store_reg(rd, pass, tmp); - } /* for pass */ - tcg_temp_free_i32(tmp2); - } - } else if (op == 10) { - /* VSHLL, VMOVL */ - if (q || (rd & 1)) { - return 1; - } - tmp = neon_load_reg(rm, 0); - tmp2 = neon_load_reg(rm, 1); - for (pass = 0; pass < 2; pass++) { - if (pass == 1) - tmp = tmp2; - - gen_neon_widen(cpu_V0, tmp, size, u); - - if (shift != 0) { - /* The shift is less than the width of the source - type, so we can just shift the whole register. */ - tcg_gen_shli_i64(cpu_V0, cpu_V0, shift); - /* Widen the result of shift: we need to clear - * the potential overflow bits resulting from - * left bits of the narrow input appearing as - * right bits of left the neighbour narrow - * input. */ - if (size < 2 || !u) { - uint64_t imm64; - if (size == 0) { - imm = (0xffu >> (8 - shift)); - imm |= imm << 16; - } else if (size == 1) { - imm = 0xffff >> (16 - shift); - } else { - /* size == 2 */ - imm = 0xffffffff >> (32 - shift); - } - if (size < 2) { - imm64 = imm | (((uint64_t)imm) << 32); - } else { - imm64 = imm; - } - tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64); - } - } - neon_store_reg64(cpu_V0, rd + pass); - } - } else if (op >= 14) { - /* VCVT fixed-point. */ - TCGv_ptr fpst; - TCGv_i32 shiftv; - VFPGenFixPointFn *fn; - - if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) { - return 1; - } - - if (!(op & 1)) { - if (u) { - fn = gen_helper_vfp_ultos; - } else { - fn = gen_helper_vfp_sltos; - } - } else { - if (u) { - fn = gen_helper_vfp_touls_round_to_zero; - } else { - fn = gen_helper_vfp_tosls_round_to_zero; - } - } - - /* We have already masked out the must-be-1 top bit of imm6, - * hence this 32-shift where the ARM ARM has 64-imm6. - */ - shift = 32 - shift; - fpst = get_fpstatus_ptr(1); - shiftv = tcg_const_i32(shift); - for (pass = 0; pass < (q ? 4 : 2); pass++) { - TCGv_i32 tmpf = neon_load_reg(rm, pass); - fn(tmpf, tmpf, shiftv, fpst); - neon_store_reg(rd, pass, tmpf); - } - tcg_temp_free_ptr(fpst); - tcg_temp_free_i32(shiftv); - } else { - return 1; - } - } else { /* (insn & 0x00380080) == 0 */ - int invert, reg_ofs, vec_size; - - if (q && (rd & 1)) { - return 1; - } - - op = (insn >> 8) & 0xf; - /* One register and immediate. */ - imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf); - invert = (insn & (1 << 5)) != 0; - /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE. - * We choose to not special-case this and will behave as if a - * valid constant encoding of 0 had been given. - */ - switch (op) { - case 0: case 1: - /* no-op */ - break; - case 2: case 3: - imm <<= 8; - break; - case 4: case 5: - imm <<= 16; - break; - case 6: case 7: - imm <<= 24; - break; - case 8: case 9: - imm |= imm << 16; - break; - case 10: case 11: - imm = (imm << 8) | (imm << 24); - break; - case 12: - imm = (imm << 8) | 0xff; - break; - case 13: - imm = (imm << 16) | 0xffff; - break; - case 14: - imm |= (imm << 8) | (imm << 16) | (imm << 24); - if (invert) { - imm = ~imm; - } - break; - case 15: - if (invert) { - return 1; - } - imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19) - | ((imm & 0x40) ? (0x1f << 25) : (1 << 30)); - break; - } - if (invert) { - imm = ~imm; - } - - reg_ofs = neon_reg_offset(rd, 0); - vec_size = q ? 16 : 8; - - if (op & 1 && op < 12) { - if (invert) { - /* The immediate value has already been inverted, - * so BIC becomes AND. - */ - tcg_gen_gvec_andi(MO_32, reg_ofs, reg_ofs, imm, - vec_size, vec_size); - } else { - tcg_gen_gvec_ori(MO_32, reg_ofs, reg_ofs, imm, - vec_size, vec_size); - } - } else { - /* VMOV, VMVN. */ - if (op == 14 && invert) { - TCGv_i64 t64 = tcg_temp_new_i64(); - - for (pass = 0; pass <= q; ++pass) { - uint64_t val = 0; - int n; - - for (n = 0; n < 8; n++) { - if (imm & (1 << (n + pass * 8))) { - val |= 0xffull << (n * 8); - } - } - tcg_gen_movi_i64(t64, val); - neon_store_reg64(t64, rd + pass); - } - tcg_temp_free_i64(t64); - } else { - tcg_gen_gvec_dup_imm(MO_32, reg_ofs, vec_size, - vec_size, imm); - } - } - } - } else { /* (insn & 0x00800010 == 0x00800000) */ - if (size != 3) { - op = (insn >> 8) & 0xf; - if ((insn & (1 << 6)) == 0) { - /* Three registers of different lengths. */ - int src1_wide; - int src2_wide; - int prewiden; - /* undefreq: bit 0 : UNDEF if size == 0 - * bit 1 : UNDEF if size == 1 - * bit 2 : UNDEF if size == 2 - * bit 3 : UNDEF if U == 1 - * Note that [2:0] set implies 'always UNDEF' - */ - int undefreq; - /* prewiden, src1_wide, src2_wide, undefreq */ - static const int neon_3reg_wide[16][4] = { - {1, 0, 0, 0}, /* VADDL */ - {1, 1, 0, 0}, /* VADDW */ - {1, 0, 0, 0}, /* VSUBL */ - {1, 1, 0, 0}, /* VSUBW */ - {0, 1, 1, 0}, /* VADDHN */ - {0, 0, 0, 0}, /* VABAL */ - {0, 1, 1, 0}, /* VSUBHN */ - {0, 0, 0, 0}, /* VABDL */ - {0, 0, 0, 0}, /* VMLAL */ - {0, 0, 0, 9}, /* VQDMLAL */ - {0, 0, 0, 0}, /* VMLSL */ - {0, 0, 0, 9}, /* VQDMLSL */ - {0, 0, 0, 0}, /* Integer VMULL */ - {0, 0, 0, 9}, /* VQDMULL */ - {0, 0, 0, 0xa}, /* Polynomial VMULL */ - {0, 0, 0, 7}, /* Reserved: always UNDEF */ - }; - - prewiden = neon_3reg_wide[op][0]; - src1_wide = neon_3reg_wide[op][1]; - src2_wide = neon_3reg_wide[op][2]; - undefreq = neon_3reg_wide[op][3]; - - if ((undefreq & (1 << size)) || - ((undefreq & 8) && u)) { - return 1; - } - if ((src1_wide && (rn & 1)) || - (src2_wide && (rm & 1)) || - (!src2_wide && (rd & 1))) { - return 1; - } - - /* Handle polynomial VMULL in a single pass. */ - if (op == 14) { - if (size == 0) { - /* VMULL.P8 */ - tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, 16, 16, - 0, gen_helper_neon_pmull_h); - } else { - /* VMULL.P64 */ - if (!dc_isar_feature(aa32_pmull, s)) { - return 1; - } - tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, 16, 16, - 0, gen_helper_gvec_pmull_q); - } - return 0; - } - - /* Avoid overlapping operands. Wide source operands are - always aligned so will never overlap with wide - destinations in problematic ways. */ - if (rd == rm && !src2_wide) { - tmp = neon_load_reg(rm, 1); - neon_store_scratch(2, tmp); - } else if (rd == rn && !src1_wide) { - tmp = neon_load_reg(rn, 1); - neon_store_scratch(2, tmp); - } - tmp3 = NULL; - for (pass = 0; pass < 2; pass++) { - if (src1_wide) { - neon_load_reg64(cpu_V0, rn + pass); - tmp = NULL; - } else { - if (pass == 1 && rd == rn) { - tmp = neon_load_scratch(2); - } else { - tmp = neon_load_reg(rn, pass); - } - if (prewiden) { - gen_neon_widen(cpu_V0, tmp, size, u); - } - } - if (src2_wide) { - neon_load_reg64(cpu_V1, rm + pass); - tmp2 = NULL; - } else { - if (pass == 1 && rd == rm) { - tmp2 = neon_load_scratch(2); - } else { - tmp2 = neon_load_reg(rm, pass); - } - if (prewiden) { - gen_neon_widen(cpu_V1, tmp2, size, u); - } - } - switch (op) { - case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */ - gen_neon_addl(size); - break; - case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */ - gen_neon_subl(size); - break; - case 5: case 7: /* VABAL, VABDL */ - switch ((size << 1) | u) { - case 0: - gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2); - break; - case 1: - gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2); - break; - case 2: - gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2); - break; - case 3: - gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2); - break; - case 4: - gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2); - break; - case 5: - gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2); - break; - default: abort(); - } - tcg_temp_free_i32(tmp2); - tcg_temp_free_i32(tmp); - break; - case 8: case 9: case 10: case 11: case 12: case 13: - /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */ - gen_neon_mull(cpu_V0, tmp, tmp2, size, u); - break; - default: /* 15 is RESERVED: caught earlier */ - abort(); - } - if (op == 13) { - /* VQDMULL */ - gen_neon_addl_saturate(cpu_V0, cpu_V0, size); - neon_store_reg64(cpu_V0, rd + pass); - } else if (op == 5 || (op >= 8 && op <= 11)) { - /* Accumulate. */ - neon_load_reg64(cpu_V1, rd + pass); - switch (op) { - case 10: /* VMLSL */ - gen_neon_negl(cpu_V0, size); - /* Fall through */ - case 5: case 8: /* VABAL, VMLAL */ - gen_neon_addl(size); - break; - case 9: case 11: /* VQDMLAL, VQDMLSL */ - gen_neon_addl_saturate(cpu_V0, cpu_V0, size); - if (op == 11) { - gen_neon_negl(cpu_V0, size); - } - gen_neon_addl_saturate(cpu_V0, cpu_V1, size); - break; - default: - abort(); - } - neon_store_reg64(cpu_V0, rd + pass); - } else if (op == 4 || op == 6) { - /* Narrowing operation. */ - tmp = tcg_temp_new_i32(); - if (!u) { - switch (size) { - case 0: - gen_helper_neon_narrow_high_u8(tmp, cpu_V0); - break; - case 1: - gen_helper_neon_narrow_high_u16(tmp, cpu_V0); - break; - case 2: - tcg_gen_extrh_i64_i32(tmp, cpu_V0); - break; - default: abort(); - } - } else { - switch (size) { - case 0: - gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0); - break; - case 1: - gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0); - break; - case 2: - tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31); - tcg_gen_extrh_i64_i32(tmp, cpu_V0); - break; - default: abort(); - } - } - if (pass == 0) { - tmp3 = tmp; - } else { - neon_store_reg(rd, 0, tmp3); - neon_store_reg(rd, 1, tmp); - } - } else { - /* Write back the result. */ - neon_store_reg64(cpu_V0, rd + pass); - } - } - } else { - /* Two registers and a scalar. NB that for ops of this form - * the ARM ARM labels bit 24 as Q, but it is in our variable - * 'u', not 'q'. - */ - if (size == 0) { - return 1; - } - switch (op) { - case 1: /* Float VMLA scalar */ - case 5: /* Floating point VMLS scalar */ - case 9: /* Floating point VMUL scalar */ - if (size == 1) { - return 1; - } - /* fall through */ - case 0: /* Integer VMLA scalar */ - case 4: /* Integer VMLS scalar */ - case 8: /* Integer VMUL scalar */ - case 12: /* VQDMULH scalar */ - case 13: /* VQRDMULH scalar */ - if (u && ((rd | rn) & 1)) { - return 1; - } - tmp = neon_get_scalar(size, rm); - neon_store_scratch(0, tmp); - for (pass = 0; pass < (u ? 4 : 2); pass++) { - tmp = neon_load_scratch(0); - tmp2 = neon_load_reg(rn, pass); - if (op == 12) { - if (size == 1) { - gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); - } else { - gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); - } - } else if (op == 13) { - if (size == 1) { - gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); - } else { - gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); - } - } else if (op & 1) { - TCGv_ptr fpstatus = get_fpstatus_ptr(1); - gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus); - tcg_temp_free_ptr(fpstatus); - } else { - switch (size) { - case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break; - case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break; - case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break; - default: abort(); - } - } - tcg_temp_free_i32(tmp2); - if (op < 8) { - /* Accumulate. */ - tmp2 = neon_load_reg(rd, pass); - switch (op) { - case 0: - gen_neon_add(size, tmp, tmp2); - break; - case 1: - { - TCGv_ptr fpstatus = get_fpstatus_ptr(1); - gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus); - tcg_temp_free_ptr(fpstatus); - break; - } - case 4: - gen_neon_rsb(size, tmp, tmp2); - break; - case 5: - { - TCGv_ptr fpstatus = get_fpstatus_ptr(1); - gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus); - tcg_temp_free_ptr(fpstatus); - break; - } - default: - abort(); - } - tcg_temp_free_i32(tmp2); - } - neon_store_reg(rd, pass, tmp); - } - break; - case 3: /* VQDMLAL scalar */ - case 7: /* VQDMLSL scalar */ - case 11: /* VQDMULL scalar */ - if (u == 1) { - return 1; - } - /* fall through */ - case 2: /* VMLAL sclar */ - case 6: /* VMLSL scalar */ - case 10: /* VMULL scalar */ - if (rd & 1) { - return 1; - } - tmp2 = neon_get_scalar(size, rm); - /* We need a copy of tmp2 because gen_neon_mull - * deletes it during pass 0. */ - tmp4 = tcg_temp_new_i32(); - tcg_gen_mov_i32(tmp4, tmp2); - tmp3 = neon_load_reg(rn, 1); - - for (pass = 0; pass < 2; pass++) { - if (pass == 0) { - tmp = neon_load_reg(rn, 0); - } else { - tmp = tmp3; - tmp2 = tmp4; - } - gen_neon_mull(cpu_V0, tmp, tmp2, size, u); - if (op != 11) { - neon_load_reg64(cpu_V1, rd + pass); - } - switch (op) { - case 6: - gen_neon_negl(cpu_V0, size); - /* Fall through */ - case 2: - gen_neon_addl(size); - break; - case 3: case 7: - gen_neon_addl_saturate(cpu_V0, cpu_V0, size); - if (op == 7) { - gen_neon_negl(cpu_V0, size); - } - gen_neon_addl_saturate(cpu_V0, cpu_V1, size); - break; - case 10: - /* no-op */ - break; - case 11: - gen_neon_addl_saturate(cpu_V0, cpu_V0, size); - break; - default: - abort(); - } - neon_store_reg64(cpu_V0, rd + pass); - } - break; - case 14: /* VQRDMLAH scalar */ - case 15: /* VQRDMLSH scalar */ - { - NeonGenThreeOpEnvFn *fn; - - if (!dc_isar_feature(aa32_rdm, s)) { - return 1; - } - if (u && ((rd | rn) & 1)) { - return 1; - } - if (op == 14) { - if (size == 1) { - fn = gen_helper_neon_qrdmlah_s16; - } else { - fn = gen_helper_neon_qrdmlah_s32; - } - } else { - if (size == 1) { - fn = gen_helper_neon_qrdmlsh_s16; - } else { - fn = gen_helper_neon_qrdmlsh_s32; - } - } - - tmp2 = neon_get_scalar(size, rm); - for (pass = 0; pass < (u ? 4 : 2); pass++) { - tmp = neon_load_reg(rn, pass); - tmp3 = neon_load_reg(rd, pass); - fn(tmp, cpu_env, tmp, tmp2, tmp3); - tcg_temp_free_i32(tmp3); - neon_store_reg(rd, pass, tmp); - } - tcg_temp_free_i32(tmp2); - } - break; - default: - g_assert_not_reached(); - } - } - } else { /* size == 3 */ - if (!u) { - /* Extract. */ - imm = (insn >> 8) & 0xf; - - if (imm > 7 && !q) - return 1; - - if (q && ((rd | rn | rm) & 1)) { - return 1; - } - - if (imm == 0) { - neon_load_reg64(cpu_V0, rn); - if (q) { - neon_load_reg64(cpu_V1, rn + 1); - } - } else if (imm == 8) { - neon_load_reg64(cpu_V0, rn + 1); - if (q) { - neon_load_reg64(cpu_V1, rm); - } - } else if (q) { - tmp64 = tcg_temp_new_i64(); - if (imm < 8) { - neon_load_reg64(cpu_V0, rn); - neon_load_reg64(tmp64, rn + 1); - } else { - neon_load_reg64(cpu_V0, rn + 1); - neon_load_reg64(tmp64, rm); - } - tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8); - tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8)); - tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1); - if (imm < 8) { - neon_load_reg64(cpu_V1, rm); - } else { - neon_load_reg64(cpu_V1, rm + 1); - imm -= 8; - } - tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8)); - tcg_gen_shri_i64(tmp64, tmp64, imm * 8); - tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64); - tcg_temp_free_i64(tmp64); - } else { - /* BUGFIX */ - neon_load_reg64(cpu_V0, rn); - tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8); - neon_load_reg64(cpu_V1, rm); - tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8)); - tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1); - } - neon_store_reg64(cpu_V0, rd); - if (q) { - neon_store_reg64(cpu_V1, rd + 1); - } - } else if ((insn & (1 << 11)) == 0) { - /* Two register misc. */ - op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf); - size = (insn >> 18) & 3; - /* UNDEF for unknown op values and bad op-size combinations */ - if ((neon_2rm_sizes[op] & (1 << size)) == 0) { - return 1; - } - if (neon_2rm_is_v8_op(op) && - !arm_dc_feature(s, ARM_FEATURE_V8)) { - return 1; - } - if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) && - q && ((rm | rd) & 1)) { - return 1; - } - switch (op) { - case NEON_2RM_VREV64: - for (pass = 0; pass < (q ? 2 : 1); pass++) { - tmp = neon_load_reg(rm, pass * 2); - tmp2 = neon_load_reg(rm, pass * 2 + 1); - switch (size) { - case 0: tcg_gen_bswap32_i32(tmp, tmp); break; - case 1: gen_swap_half(tmp); break; - case 2: /* no-op */ break; - default: abort(); - } - neon_store_reg(rd, pass * 2 + 1, tmp); - if (size == 2) { - neon_store_reg(rd, pass * 2, tmp2); - } else { - switch (size) { - case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break; - case 1: gen_swap_half(tmp2); break; - default: abort(); - } - neon_store_reg(rd, pass * 2, tmp2); - } - } - break; - case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U: - case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U: - for (pass = 0; pass < q + 1; pass++) { - tmp = neon_load_reg(rm, pass * 2); - gen_neon_widen(cpu_V0, tmp, size, op & 1); - tmp = neon_load_reg(rm, pass * 2 + 1); - gen_neon_widen(cpu_V1, tmp, size, op & 1); - switch (size) { - case 0: gen_helper_neon_paddl_u16(CPU_V001); break; - case 1: gen_helper_neon_paddl_u32(CPU_V001); break; - case 2: tcg_gen_add_i64(CPU_V001); break; - default: abort(); - } - if (op >= NEON_2RM_VPADAL) { - /* Accumulate. */ - neon_load_reg64(cpu_V1, rd + pass); - gen_neon_addl(size); - } - neon_store_reg64(cpu_V0, rd + pass); - } - break; - case NEON_2RM_VTRN: - if (size == 2) { - int n; - for (n = 0; n < (q ? 4 : 2); n += 2) { - tmp = neon_load_reg(rm, n); - tmp2 = neon_load_reg(rd, n + 1); - neon_store_reg(rm, n, tmp2); - neon_store_reg(rd, n + 1, tmp); - } - } else { - goto elementwise; - } - break; - case NEON_2RM_VUZP: - if (gen_neon_unzip(rd, rm, size, q)) { - return 1; - } - break; - case NEON_2RM_VZIP: - if (gen_neon_zip(rd, rm, size, q)) { - return 1; - } - break; - case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN: - /* also VQMOVUN; op field and mnemonics don't line up */ - if (rm & 1) { - return 1; - } - tmp2 = NULL; - for (pass = 0; pass < 2; pass++) { - neon_load_reg64(cpu_V0, rm + pass); - tmp = tcg_temp_new_i32(); - gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size, - tmp, cpu_V0); - if (pass == 0) { - tmp2 = tmp; - } else { - neon_store_reg(rd, 0, tmp2); - neon_store_reg(rd, 1, tmp); - } - } - break; - case NEON_2RM_VSHLL: - if (q || (rd & 1)) { - return 1; - } - tmp = neon_load_reg(rm, 0); - tmp2 = neon_load_reg(rm, 1); - for (pass = 0; pass < 2; pass++) { - if (pass == 1) - tmp = tmp2; - gen_neon_widen(cpu_V0, tmp, size, 1); - tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size); - neon_store_reg64(cpu_V0, rd + pass); - } - break; - case NEON_2RM_VCVT_F16_F32: - { - TCGv_ptr fpst; - TCGv_i32 ahp; - - if (!dc_isar_feature(aa32_fp16_spconv, s) || - q || (rm & 1)) { - return 1; - } - fpst = get_fpstatus_ptr(true); - ahp = get_ahp_flag(); - tmp = neon_load_reg(rm, 0); - gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp); - tmp2 = neon_load_reg(rm, 1); - gen_helper_vfp_fcvt_f32_to_f16(tmp2, tmp2, fpst, ahp); - tcg_gen_shli_i32(tmp2, tmp2, 16); - tcg_gen_or_i32(tmp2, tmp2, tmp); - tcg_temp_free_i32(tmp); - tmp = neon_load_reg(rm, 2); - gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp); - tmp3 = neon_load_reg(rm, 3); - neon_store_reg(rd, 0, tmp2); - gen_helper_vfp_fcvt_f32_to_f16(tmp3, tmp3, fpst, ahp); - tcg_gen_shli_i32(tmp3, tmp3, 16); - tcg_gen_or_i32(tmp3, tmp3, tmp); - neon_store_reg(rd, 1, tmp3); - tcg_temp_free_i32(tmp); - tcg_temp_free_i32(ahp); - tcg_temp_free_ptr(fpst); - break; - } - case NEON_2RM_VCVT_F32_F16: - { - TCGv_ptr fpst; - TCGv_i32 ahp; - if (!dc_isar_feature(aa32_fp16_spconv, s) || - q || (rd & 1)) { - return 1; - } - fpst = get_fpstatus_ptr(true); - ahp = get_ahp_flag(); - tmp3 = tcg_temp_new_i32(); - tmp = neon_load_reg(rm, 0); - tmp2 = neon_load_reg(rm, 1); - tcg_gen_ext16u_i32(tmp3, tmp); - gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp); - neon_store_reg(rd, 0, tmp3); - tcg_gen_shri_i32(tmp, tmp, 16); - gen_helper_vfp_fcvt_f16_to_f32(tmp, tmp, fpst, ahp); - neon_store_reg(rd, 1, tmp); - tmp3 = tcg_temp_new_i32(); - tcg_gen_ext16u_i32(tmp3, tmp2); - gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp); - neon_store_reg(rd, 2, tmp3); - tcg_gen_shri_i32(tmp2, tmp2, 16); - gen_helper_vfp_fcvt_f16_to_f32(tmp2, tmp2, fpst, ahp); - neon_store_reg(rd, 3, tmp2); - tcg_temp_free_i32(ahp); - tcg_temp_free_ptr(fpst); - break; - } - case NEON_2RM_AESE: case NEON_2RM_AESMC: - if (!dc_isar_feature(aa32_aes, s) || ((rm | rd) & 1)) { - return 1; - } - ptr1 = vfp_reg_ptr(true, rd); - ptr2 = vfp_reg_ptr(true, rm); - - /* Bit 6 is the lowest opcode bit; it distinguishes between - * encryption (AESE/AESMC) and decryption (AESD/AESIMC) - */ - tmp3 = tcg_const_i32(extract32(insn, 6, 1)); - - if (op == NEON_2RM_AESE) { - gen_helper_crypto_aese(ptr1, ptr2, tmp3); - } else { - gen_helper_crypto_aesmc(ptr1, ptr2, tmp3); - } - tcg_temp_free_ptr(ptr1); - tcg_temp_free_ptr(ptr2); - tcg_temp_free_i32(tmp3); - break; - case NEON_2RM_SHA1H: - if (!dc_isar_feature(aa32_sha1, s) || ((rm | rd) & 1)) { - return 1; - } - ptr1 = vfp_reg_ptr(true, rd); - ptr2 = vfp_reg_ptr(true, rm); - - gen_helper_crypto_sha1h(ptr1, ptr2); - - tcg_temp_free_ptr(ptr1); - tcg_temp_free_ptr(ptr2); - break; - case NEON_2RM_SHA1SU1: - if ((rm | rd) & 1) { - return 1; - } - /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */ - if (q) { - if (!dc_isar_feature(aa32_sha2, s)) { - return 1; - } - } else if (!dc_isar_feature(aa32_sha1, s)) { - return 1; - } - ptr1 = vfp_reg_ptr(true, rd); - ptr2 = vfp_reg_ptr(true, rm); - if (q) { - gen_helper_crypto_sha256su0(ptr1, ptr2); - } else { - gen_helper_crypto_sha1su1(ptr1, ptr2); - } - tcg_temp_free_ptr(ptr1); - tcg_temp_free_ptr(ptr2); - break; - - case NEON_2RM_VMVN: - tcg_gen_gvec_not(0, rd_ofs, rm_ofs, vec_size, vec_size); - break; - case NEON_2RM_VNEG: - tcg_gen_gvec_neg(size, rd_ofs, rm_ofs, vec_size, vec_size); - break; - case NEON_2RM_VABS: - tcg_gen_gvec_abs(size, rd_ofs, rm_ofs, vec_size, vec_size); - break; - - case NEON_2RM_VCEQ0: - gen_gvec_ceq0(size, rd_ofs, rm_ofs, vec_size, vec_size); - break; - case NEON_2RM_VCGT0: - gen_gvec_cgt0(size, rd_ofs, rm_ofs, vec_size, vec_size); - break; - case NEON_2RM_VCLE0: - gen_gvec_cle0(size, rd_ofs, rm_ofs, vec_size, vec_size); - break; - case NEON_2RM_VCGE0: - gen_gvec_cge0(size, rd_ofs, rm_ofs, vec_size, vec_size); - break; - case NEON_2RM_VCLT0: - gen_gvec_clt0(size, rd_ofs, rm_ofs, vec_size, vec_size); - break; - - default: - elementwise: - for (pass = 0; pass < (q ? 4 : 2); pass++) { - tmp = neon_load_reg(rm, pass); - switch (op) { - case NEON_2RM_VREV32: - switch (size) { - case 0: tcg_gen_bswap32_i32(tmp, tmp); break; - case 1: gen_swap_half(tmp); break; - default: abort(); - } - break; - case NEON_2RM_VREV16: - gen_rev16(tmp, tmp); - break; - case NEON_2RM_VCLS: - switch (size) { - case 0: gen_helper_neon_cls_s8(tmp, tmp); break; - case 1: gen_helper_neon_cls_s16(tmp, tmp); break; - case 2: gen_helper_neon_cls_s32(tmp, tmp); break; - default: abort(); - } - break; - case NEON_2RM_VCLZ: - switch (size) { - case 0: gen_helper_neon_clz_u8(tmp, tmp); break; - case 1: gen_helper_neon_clz_u16(tmp, tmp); break; - case 2: tcg_gen_clzi_i32(tmp, tmp, 32); break; - default: abort(); - } - break; - case NEON_2RM_VCNT: - gen_helper_neon_cnt_u8(tmp, tmp); - break; - case NEON_2RM_VQABS: - switch (size) { - case 0: - gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); - break; - case 1: - gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); - break; - case 2: - gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); - break; - default: abort(); - } - break; - case NEON_2RM_VQNEG: - switch (size) { - case 0: - gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); - break; - case 1: - gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); - break; - case 2: - gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); - break; - default: abort(); - } - break; - case NEON_2RM_VCGT0_F: - { - TCGv_ptr fpstatus = get_fpstatus_ptr(1); - tmp2 = tcg_const_i32(0); - gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus); - tcg_temp_free_i32(tmp2); - tcg_temp_free_ptr(fpstatus); - break; - } - case NEON_2RM_VCGE0_F: - { - TCGv_ptr fpstatus = get_fpstatus_ptr(1); - tmp2 = tcg_const_i32(0); - gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus); - tcg_temp_free_i32(tmp2); - tcg_temp_free_ptr(fpstatus); - break; - } - case NEON_2RM_VCEQ0_F: - { - TCGv_ptr fpstatus = get_fpstatus_ptr(1); - tmp2 = tcg_const_i32(0); - gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus); - tcg_temp_free_i32(tmp2); - tcg_temp_free_ptr(fpstatus); - break; - } - case NEON_2RM_VCLE0_F: - { - TCGv_ptr fpstatus = get_fpstatus_ptr(1); - tmp2 = tcg_const_i32(0); - gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus); - tcg_temp_free_i32(tmp2); - tcg_temp_free_ptr(fpstatus); - break; - } - case NEON_2RM_VCLT0_F: - { - TCGv_ptr fpstatus = get_fpstatus_ptr(1); - tmp2 = tcg_const_i32(0); - gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus); - tcg_temp_free_i32(tmp2); - tcg_temp_free_ptr(fpstatus); - break; - } - case NEON_2RM_VABS_F: - gen_helper_vfp_abss(tmp, tmp); - break; - case NEON_2RM_VNEG_F: - gen_helper_vfp_negs(tmp, tmp); - break; - case NEON_2RM_VSWP: - tmp2 = neon_load_reg(rd, pass); - neon_store_reg(rm, pass, tmp2); - break; - case NEON_2RM_VTRN: - tmp2 = neon_load_reg(rd, pass); - switch (size) { - case 0: gen_neon_trn_u8(tmp, tmp2); break; - case 1: gen_neon_trn_u16(tmp, tmp2); break; - default: abort(); - } - neon_store_reg(rm, pass, tmp2); - break; - case NEON_2RM_VRINTN: - case NEON_2RM_VRINTA: - case NEON_2RM_VRINTM: - case NEON_2RM_VRINTP: - case NEON_2RM_VRINTZ: - { - TCGv_i32 tcg_rmode; - TCGv_ptr fpstatus = get_fpstatus_ptr(1); - int rmode; - - if (op == NEON_2RM_VRINTZ) { - rmode = FPROUNDING_ZERO; - } else { - rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1]; - } - - tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode)); - gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, - cpu_env); - gen_helper_rints(tmp, tmp, fpstatus); - gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, - cpu_env); - tcg_temp_free_ptr(fpstatus); - tcg_temp_free_i32(tcg_rmode); - break; - } - case NEON_2RM_VRINTX: - { - TCGv_ptr fpstatus = get_fpstatus_ptr(1); - gen_helper_rints_exact(tmp, tmp, fpstatus); - tcg_temp_free_ptr(fpstatus); - break; - } - case NEON_2RM_VCVTAU: - case NEON_2RM_VCVTAS: - case NEON_2RM_VCVTNU: - case NEON_2RM_VCVTNS: - case NEON_2RM_VCVTPU: - case NEON_2RM_VCVTPS: - case NEON_2RM_VCVTMU: - case NEON_2RM_VCVTMS: - { - bool is_signed = !extract32(insn, 7, 1); - TCGv_ptr fpst = get_fpstatus_ptr(1); - TCGv_i32 tcg_rmode, tcg_shift; - int rmode = fp_decode_rm[extract32(insn, 8, 2)]; - - tcg_shift = tcg_const_i32(0); - tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode)); - gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, - cpu_env); - - if (is_signed) { - gen_helper_vfp_tosls(tmp, tmp, - tcg_shift, fpst); - } else { - gen_helper_vfp_touls(tmp, tmp, - tcg_shift, fpst); - } - - gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, - cpu_env); - tcg_temp_free_i32(tcg_rmode); - tcg_temp_free_i32(tcg_shift); - tcg_temp_free_ptr(fpst); - break; - } - case NEON_2RM_VRECPE: - gen_helper_recpe_u32(tmp, tmp); - break; - case NEON_2RM_VRSQRTE: - gen_helper_rsqrte_u32(tmp, tmp); - break; - case NEON_2RM_VRECPE_F: - { - TCGv_ptr fpstatus = get_fpstatus_ptr(1); - gen_helper_recpe_f32(tmp, tmp, fpstatus); - tcg_temp_free_ptr(fpstatus); - break; - } - case NEON_2RM_VRSQRTE_F: - { - TCGv_ptr fpstatus = get_fpstatus_ptr(1); - gen_helper_rsqrte_f32(tmp, tmp, fpstatus); - tcg_temp_free_ptr(fpstatus); - break; - } - case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */ - { - TCGv_ptr fpstatus = get_fpstatus_ptr(1); - gen_helper_vfp_sitos(tmp, tmp, fpstatus); - tcg_temp_free_ptr(fpstatus); - break; - } - case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */ - { - TCGv_ptr fpstatus = get_fpstatus_ptr(1); - gen_helper_vfp_uitos(tmp, tmp, fpstatus); - tcg_temp_free_ptr(fpstatus); - break; - } - case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */ - { - TCGv_ptr fpstatus = get_fpstatus_ptr(1); - gen_helper_vfp_tosizs(tmp, tmp, fpstatus); - tcg_temp_free_ptr(fpstatus); - break; - } - case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */ - { - TCGv_ptr fpstatus = get_fpstatus_ptr(1); - gen_helper_vfp_touizs(tmp, tmp, fpstatus); - tcg_temp_free_ptr(fpstatus); - break; - } - default: - /* Reserved op values were caught by the - * neon_2rm_sizes[] check earlier. - */ - abort(); - } - neon_store_reg(rd, pass, tmp); - } - break; - } - } else if ((insn & (1 << 10)) == 0) { - /* VTBL, VTBX. */ - int n = ((insn >> 8) & 3) + 1; - if ((rn + n) > 32) { - /* This is UNPREDICTABLE; we choose to UNDEF to avoid the - * helper function running off the end of the register file. - */ - return 1; - } - n <<= 3; - if (insn & (1 << 6)) { - tmp = neon_load_reg(rd, 0); - } else { - tmp = tcg_temp_new_i32(); - tcg_gen_movi_i32(tmp, 0); - } - tmp2 = neon_load_reg(rm, 0); - ptr1 = vfp_reg_ptr(true, rn); - tmp5 = tcg_const_i32(n); - gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5); - tcg_temp_free_i32(tmp); - if (insn & (1 << 6)) { - tmp = neon_load_reg(rd, 1); - } else { - tmp = tcg_temp_new_i32(); - tcg_gen_movi_i32(tmp, 0); - } - tmp3 = neon_load_reg(rm, 1); - gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5); - tcg_temp_free_i32(tmp5); - tcg_temp_free_ptr(ptr1); - neon_store_reg(rd, 0, tmp2); - neon_store_reg(rd, 1, tmp3); - tcg_temp_free_i32(tmp); - } else if ((insn & 0x380) == 0) { - /* VDUP */ - int element; - MemOp size; - - if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) { - return 1; - } - if (insn & (1 << 16)) { - size = MO_8; - element = (insn >> 17) & 7; - } else if (insn & (1 << 17)) { - size = MO_16; - element = (insn >> 18) & 3; - } else { - size = MO_32; - element = (insn >> 19) & 1; - } - tcg_gen_gvec_dup_mem(size, neon_reg_offset(rd, 0), - neon_element_offset(rm, element, size), - q ? 16 : 8, q ? 16 : 8); - } else { - return 1; - } - } - } - return 0; + static const TCGOpcode vecop_list[] = { + INDEX_op_sub_vec, INDEX_op_add_vec, + INDEX_op_umin_vec, INDEX_op_umax_vec, 0 + }; + static const GVecGen3 ops[4] = { + { .fniv = gen_uaba_vec, + .fno = gen_helper_gvec_uaba_b, + .opt_opc = vecop_list, + .load_dest = true, + .vece = MO_8 }, + { .fniv = gen_uaba_vec, + .fno = gen_helper_gvec_uaba_h, + .opt_opc = vecop_list, + .load_dest = true, + .vece = MO_16 }, + { .fni4 = gen_uaba_i32, + .fniv = gen_uaba_vec, + .fno = gen_helper_gvec_uaba_s, + .opt_opc = vecop_list, + .load_dest = true, + .vece = MO_32 }, + { .fni8 = gen_uaba_i64, + .fniv = gen_uaba_vec, + .fno = gen_helper_gvec_uaba_d, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .opt_opc = vecop_list, + .load_dest = true, + .vece = MO_64 }, + }; + tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); } -static int disas_coproc_insn(DisasContext *s, uint32_t insn) +static void do_coproc_insn(DisasContext *s, int cpnum, int is64, + int opc1, int crn, int crm, int opc2, + bool isread, int rt, int rt2) { - int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2; const ARMCPRegInfo *ri; - cpnum = (insn >> 8) & 0xf; - - /* First check for coprocessor space used for XScale/iwMMXt insns */ - if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) { - if (extract32(s->c15_cpar, cpnum, 1) == 0) { - return 1; - } - if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) { - return disas_iwmmxt_insn(s, insn); - } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) { - return disas_dsp_insn(s, insn); - } - return 1; - } - - /* Otherwise treat as a generic register access */ - is64 = (insn & (1 << 25)) == 0; - if (!is64 && ((insn & (1 << 4)) == 0)) { - /* cdp */ - return 1; - } - - crm = insn & 0xf; - if (is64) { - crn = 0; - opc1 = (insn >> 4) & 0xf; - opc2 = 0; - rt2 = (insn >> 16) & 0xf; - } else { - crn = (insn >> 16) & 0xf; - opc1 = (insn >> 21) & 7; - opc2 = (insn >> 5) & 7; - rt2 = 0; - } - isread = (insn >> 20) & 1; - rt = (insn >> 12) & 0xf; - ri = get_arm_cp_reginfo(s->cp_regs, ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2)); if (ri) { @@ -6791,7 +4612,8 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn) /* Check access permissions */ if (!cp_access_ok(s->current_el, ri, isread)) { - return 1; + unallocated_encoding(s); + return; } if (s->hstr_active || ri->accessfn || @@ -6865,14 +4687,15 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn) /* Handle special cases first */ switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) { case ARM_CP_NOP: - return 0; + return; case ARM_CP_WFI: if (isread) { - return 1; + unallocated_encoding(s); + return; } gen_set_pc_im(s, s->base.pc_next); s->base.is_jmp = DISAS_WFI; - return 0; + return; default: break; } @@ -6932,7 +4755,7 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn) /* Write */ if (ri->type & ARM_CP_CONST) { /* If not forbidden by access permissions, treat as WI */ - return 0; + return; } if (is64) { @@ -6998,7 +4821,7 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn) gen_lookup_tb(s); } - return 0; + return; } /* Unknown register; this might be a guest error or a QEMU @@ -7018,9 +4841,27 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn) s->ns ? "non-secure" : "secure"); } - return 1; + unallocated_encoding(s); + return; } +/* Decode XScale DSP or iWMMXt insn (in the copro space, cp=0 or 1) */ +static void disas_xscale_insn(DisasContext *s, uint32_t insn) +{ + int cpnum = (insn >> 8) & 0xf; + + if (extract32(s->c15_cpar, cpnum, 1) == 0) { + unallocated_encoding(s); + } else if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) { + if (disas_iwmmxt_insn(s, insn)) { + unallocated_encoding(s); + } + } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) { + if (disas_dsp_insn(s, insn)) { + unallocated_encoding(s); + } + } +} /* Store a 64-bit value to a register pair. Clobbers val. */ static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val) @@ -7312,7 +5153,7 @@ static void gen_srs(DisasContext *s, tcg_temp_free_i32(tmp); } tcg_temp_free_i32(addr); - s->base.is_jmp = DISAS_UPDATE; + s->base.is_jmp = DISAS_UPDATE_EXIT; } /* Generate a label used for skipping this instruction */ @@ -7415,10 +5256,72 @@ static int t16_pop_list(DisasContext *s, int x) * Include the generated decoders. */ -#include "decode-a32.inc.c" -#include "decode-a32-uncond.inc.c" -#include "decode-t32.inc.c" -#include "decode-t16.inc.c" +#include "decode-a32.c.inc" +#include "decode-a32-uncond.c.inc" +#include "decode-t32.c.inc" +#include "decode-t16.c.inc" + +static bool valid_cp(DisasContext *s, int cp) +{ + /* + * Return true if this coprocessor field indicates something + * that's really a possible coprocessor. + * For v7 and earlier, coprocessors 8..15 were reserved for Arm use, + * and of those only cp14 and cp15 were used for registers. + * cp10 and cp11 were used for VFP and Neon, whose decode is + * dealt with elsewhere. With the advent of fp16, cp9 is also + * now part of VFP. + * For v8A and later, the encoding has been tightened so that + * only cp14 and cp15 are valid, and other values aren't considered + * to be in the coprocessor-instruction space at all. v8M still + * permits coprocessors 0..7. + */ + if (arm_dc_feature(s, ARM_FEATURE_V8) && + !arm_dc_feature(s, ARM_FEATURE_M)) { + return cp >= 14; + } + return cp < 8 || cp >= 14; +} + +static bool trans_MCR(DisasContext *s, arg_MCR *a) +{ + if (!valid_cp(s, a->cp)) { + return false; + } + do_coproc_insn(s, a->cp, false, a->opc1, a->crn, a->crm, a->opc2, + false, a->rt, 0); + return true; +} + +static bool trans_MRC(DisasContext *s, arg_MRC *a) +{ + if (!valid_cp(s, a->cp)) { + return false; + } + do_coproc_insn(s, a->cp, false, a->opc1, a->crn, a->crm, a->opc2, + true, a->rt, 0); + return true; +} + +static bool trans_MCRR(DisasContext *s, arg_MCRR *a) +{ + if (!valid_cp(s, a->cp)) { + return false; + } + do_coproc_insn(s, a->cp, true, a->opc1, 0, a->crm, 0, + false, a->rt, a->rt2); + return true; +} + +static bool trans_MRRC(DisasContext *s, arg_MRRC *a) +{ + if (!valid_cp(s, a->cp)) { + return false; + } + do_coproc_insn(s, a->cp, true, a->opc1, 0, a->crm, 0, + true, a->rt, a->rt2); + return true; +} /* Helpers to swap operands for reverse-subtract. */ static void gen_rsb(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b) @@ -9576,27 +7479,65 @@ static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub) t1 = load_reg(s, a->rn); t2 = load_reg(s, a->rm); if (m_swap) { - gen_swap_half(t2); + gen_swap_half(t2, t2); } gen_smul_dual(t1, t2); if (sub) { - /* This subtraction cannot overflow. */ - tcg_gen_sub_i32(t1, t1, t2); - } else { /* - * This addition cannot overflow 32 bits; however it may - * overflow considered as a signed operation, in which case - * we must set the Q flag. + * This subtraction cannot overflow, so we can do a simple + * 32-bit subtraction and then a possible 32-bit saturating + * addition of Ra. */ - gen_helper_add_setq(t1, cpu_env, t1, t2); - } - tcg_temp_free_i32(t2); + tcg_gen_sub_i32(t1, t1, t2); + tcg_temp_free_i32(t2); - if (a->ra != 15) { - t2 = load_reg(s, a->ra); + if (a->ra != 15) { + t2 = load_reg(s, a->ra); + gen_helper_add_setq(t1, cpu_env, t1, t2); + tcg_temp_free_i32(t2); + } + } else if (a->ra == 15) { + /* Single saturation-checking addition */ gen_helper_add_setq(t1, cpu_env, t1, t2); tcg_temp_free_i32(t2); + } else { + /* + * We need to add the products and Ra together and then + * determine whether the final result overflowed. Doing + * this as two separate add-and-check-overflow steps incorrectly + * sets Q for cases like (-32768 * -32768) + (-32768 * -32768) + -1. + * Do all the arithmetic at 64-bits and then check for overflow. + */ + TCGv_i64 p64, q64; + TCGv_i32 t3, qf, one; + + p64 = tcg_temp_new_i64(); + q64 = tcg_temp_new_i64(); + tcg_gen_ext_i32_i64(p64, t1); + tcg_gen_ext_i32_i64(q64, t2); + tcg_gen_add_i64(p64, p64, q64); + load_reg_var(s, t2, a->ra); + tcg_gen_ext_i32_i64(q64, t2); + tcg_gen_add_i64(p64, p64, q64); + tcg_temp_free_i64(q64); + + tcg_gen_extr_i64_i32(t1, t2, p64); + tcg_temp_free_i64(p64); + /* + * t1 is the low half of the result which goes into Rd. + * We have overflow and must set Q if the high half (t2) + * is different from the sign-extension of t1. + */ + t3 = tcg_temp_new_i32(); + tcg_gen_sari_i32(t3, t1, 31); + qf = load_cpu_field(QF); + one = tcg_const_i32(1); + tcg_gen_movcond_i32(TCG_COND_NE, qf, t2, t3, one, qf); + store_cpu_field(qf, QF); + tcg_temp_free_i32(one); + tcg_temp_free_i32(t3); + tcg_temp_free_i32(t2); } store_reg(s, a->rd, t1); return true; @@ -9634,7 +7575,7 @@ static bool op_smlald(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub) t1 = load_reg(s, a->rn); t2 = load_reg(s, a->rm); if (m_swap) { - gen_swap_half(t2); + gen_swap_half(t2, t2); } gen_smul_dual(t1, t2); @@ -9983,9 +7924,6 @@ static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n) gen_io_start(); } gen_helper_cpsr_write_eret(cpu_env, tmp); - if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { - gen_io_end(); - } tcg_temp_free_i32(tmp); /* Must exit loop to check un-masked IRQs */ s->base.is_jmp = DISAS_EXIT; @@ -10063,7 +8001,15 @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a) { TCGv_i32 tmp; - /* For A32, ARCH(5) is checked near the start of the uncond block. */ + /* + * BLX would be useless on M-profile; the encoding space + * is used for other insns from v8.1M onward, and UNDEFs before that. + */ + if (arm_dc_feature(s, ARM_FEATURE_M)) { + return false; + } + + /* For A32, ARM_FEATURE_V5 is checked near the start of the uncond block. */ if (s->thumb && (a->imm & 2)) { return false; } @@ -10108,6 +8054,109 @@ static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a) return true; } +static bool trans_BF(DisasContext *s, arg_BF *a) +{ + /* + * M-profile branch future insns. The architecture permits an + * implementation to implement these as NOPs (equivalent to + * discarding the LO_BRANCH_INFO cache immediately), and we + * take that IMPDEF option because for QEMU a "real" implementation + * would be complicated and wouldn't execute any faster. + */ + if (!dc_isar_feature(aa32_lob, s)) { + return false; + } + if (a->boff == 0) { + /* SEE "Related encodings" (loop insns) */ + return false; + } + /* Handle as NOP */ + return true; +} + +static bool trans_DLS(DisasContext *s, arg_DLS *a) +{ + /* M-profile low-overhead loop start */ + TCGv_i32 tmp; + + if (!dc_isar_feature(aa32_lob, s)) { + return false; + } + if (a->rn == 13 || a->rn == 15) { + /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */ + return false; + } + + /* Not a while loop, no tail predication: just set LR to the count */ + tmp = load_reg(s, a->rn); + store_reg(s, 14, tmp); + return true; +} + +static bool trans_WLS(DisasContext *s, arg_WLS *a) +{ + /* M-profile low-overhead while-loop start */ + TCGv_i32 tmp; + TCGLabel *nextlabel; + + if (!dc_isar_feature(aa32_lob, s)) { + return false; + } + if (a->rn == 13 || a->rn == 15) { + /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */ + return false; + } + if (s->condexec_mask) { + /* + * WLS in an IT block is CONSTRAINED UNPREDICTABLE; + * we choose to UNDEF, because otherwise our use of + * gen_goto_tb(1) would clash with the use of TB exit 1 + * in the dc->condjmp condition-failed codepath in + * arm_tr_tb_stop() and we'd get an assertion. + */ + return false; + } + nextlabel = gen_new_label(); + tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_R[a->rn], 0, nextlabel); + tmp = load_reg(s, a->rn); + store_reg(s, 14, tmp); + gen_jmp_tb(s, s->base.pc_next, 1); + + gen_set_label(nextlabel); + gen_jmp(s, read_pc(s) + a->imm); + return true; +} + +static bool trans_LE(DisasContext *s, arg_LE *a) +{ + /* + * M-profile low-overhead loop end. The architecture permits an + * implementation to discard the LO_BRANCH_INFO cache at any time, + * and we take the IMPDEF option to never set it in the first place + * (equivalent to always discarding it immediately), because for QEMU + * a "real" implementation would be complicated and wouldn't execute + * any faster. + */ + TCGv_i32 tmp; + + if (!dc_isar_feature(aa32_lob, s)) { + return false; + } + + if (!a->f) { + /* Not loop-forever. If LR <= 1 this is the last loop: do nothing. */ + arm_gen_condlabel(s); + tcg_gen_brcondi_i32(TCG_COND_LEU, cpu_R[14], 1, s->condlabel); + /* Decrement LR */ + tmp = load_reg(s, 14); + tcg_gen_addi_i32(tmp, tmp, -1); + store_reg(s, 14, tmp); + } + /* Jump back to the loop start */ + gen_jmp(s, read_pc(s) - a->imm); + return true; +} + static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half) { TCGv_i32 addr, tmp; @@ -10361,7 +8410,7 @@ static bool trans_SETEND(DisasContext *s, arg_SETEND *a) } if (a->E != (s->be_data == MO_BE)) { gen_helper_setend(cpu_env); - s->base.is_jmp = DISAS_UPDATE; + s->base.is_jmp = DISAS_UPDATE_EXIT; } return true; } @@ -10407,6 +8456,66 @@ static bool trans_IT(DisasContext *s, arg_IT *a) return true; } +/* v8.1M CSEL/CSINC/CSNEG/CSINV */ +static bool trans_CSEL(DisasContext *s, arg_CSEL *a) +{ + TCGv_i32 rn, rm, zero; + DisasCompare c; + + if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) { + return false; + } + + if (a->rm == 13) { + /* SEE "Related encodings" (MVE shifts) */ + return false; + } + + if (a->rd == 13 || a->rd == 15 || a->rn == 13 || a->fcond >= 14) { + /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */ + return false; + } + + /* In this insn input reg fields of 0b1111 mean "zero", not "PC" */ + if (a->rn == 15) { + rn = tcg_const_i32(0); + } else { + rn = load_reg(s, a->rn); + } + if (a->rm == 15) { + rm = tcg_const_i32(0); + } else { + rm = load_reg(s, a->rm); + } + + switch (a->op) { + case 0: /* CSEL */ + break; + case 1: /* CSINC */ + tcg_gen_addi_i32(rm, rm, 1); + break; + case 2: /* CSINV */ + tcg_gen_not_i32(rm, rm); + break; + case 3: /* CSNEG */ + tcg_gen_neg_i32(rm, rm); + break; + default: + g_assert_not_reached(); + } + + arm_test_cc(&c, a->fcond); + zero = tcg_const_i32(0); + tcg_gen_movcond_i32(c.cond, rn, c.value, zero, rn, rm); + arm_free_cc(&c); + tcg_temp_free_i32(zero); + + store_reg(s, a->rd, rn); + tcg_temp_free_i32(rm); + + return true; +} + /* * Legacy decoder. */ @@ -10429,7 +8538,10 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) * choose to UNDEF. In ARMv5 and above the space is used * for miscellaneous unconditional instructions. */ - ARCH(5); + if (!arm_dc_feature(s, ARM_FEATURE_V5)) { + unallocated_encoding(s); + return; + } /* Unconditional instructions. */ /* TODO: Perhaps merge these into one decodetree output file. */ @@ -10442,13 +8554,6 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) } /* fall back to legacy decoder */ - if (((insn >> 25) & 7) == 1) { - /* NEON Data processing. */ - if (disas_neon_data_insn(s, insn)) { - goto illegal_op; - } - return; - } if ((insn & 0x0e000f00) == 0x0c000100) { if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) { /* iWMMXt register transfer. */ @@ -10473,25 +8578,18 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) return; } /* fall back to legacy decoder */ - - switch ((insn >> 24) & 0xf) { - case 0xc: - case 0xd: - case 0xe: - if (((insn >> 8) & 0xe) == 10) { - /* VFP, but failed disas_vfp. */ - goto illegal_op; - } - if (disas_coproc_insn(s, insn)) { - /* Coprocessor. */ - goto illegal_op; + /* TODO: convert xscale/iwmmxt decoder to decodetree ?? */ + if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) { + if (((insn & 0x0c000e00) == 0x0c000000) + && ((insn & 0x03000000) != 0x03000000)) { + /* Coprocessor insn, coprocessor 0 or 1 */ + disas_xscale_insn(s, insn); + return; } - break; - default: - illegal_op: - unallocated_encoding(s); - break; } + +illegal_op: + unallocated_encoding(s); } static bool thumb_insn_is_16bit(DisasContext *s, uint32_t pc, uint32_t insn) @@ -10568,7 +8666,23 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn) goto illegal_op; } } else if ((insn & 0xf800e800) != 0xf000e800) { - ARCH(6T2); + if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) { + unallocated_encoding(s); + return; + } + } + + if (arm_dc_feature(s, ARM_FEATURE_M)) { + /* + * NOCP takes precedence over any UNDEF for (almost) the + * entire wide range of coprocessor-space encodings, so check + * for it first before proceeding to actually decode eg VFP + * insns. This decode also handles the few insns which are + * in copro space but do not have NOCP checks (eg VLLDM, VLSTM). + */ + if (disas_m_nocp(s, insn)) { + return; + } } if ((insn & 0xef000000) == 0xef000000) { @@ -10609,55 +8723,9 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn) ((insn >> 28) == 0xe && disas_vfp(s, insn))) { return; } - /* fall back to legacy decoder */ - - switch ((insn >> 25) & 0xf) { - case 0: case 1: case 2: case 3: - /* 16-bit instructions. Should never happen. */ - abort(); - case 6: case 7: case 14: case 15: - /* Coprocessor. */ - if (arm_dc_feature(s, ARM_FEATURE_M)) { - /* 0b111x_11xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx */ - if (extract32(insn, 24, 2) == 3) { - goto illegal_op; /* op0 = 0b11 : unallocated */ - } - if (((insn >> 8) & 0xe) == 10 && - dc_isar_feature(aa32_fpsp_v2, s)) { - /* FP, and the CPU supports it */ - goto illegal_op; - } else { - /* All other insns: NOCP */ - gen_exception_insn(s, s->pc_curr, EXCP_NOCP, - syn_uncategorized(), - default_exception_el(s)); - } - break; - } - if (((insn >> 24) & 3) == 3) { - /* Translate into the equivalent ARM encoding. */ - insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28); - if (disas_neon_data_insn(s, insn)) { - goto illegal_op; - } - } else if (((insn >> 8) & 0xe) == 10) { - /* VFP, but failed disas_vfp. */ - goto illegal_op; - } else { - if (insn & (1 << 28)) - goto illegal_op; - if (disas_coproc_insn(s, insn)) { - goto illegal_op; - } - } - break; - case 12: - goto illegal_op; - default: - illegal_op: - unallocated_encoding(s); - } +illegal_op: + unallocated_encoding(s); } static void disas_thumb_insn(DisasContext *s, uint32_t insn) @@ -10778,7 +8846,6 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) cpu_V0 = tcg_temp_new_i64(); cpu_V1 = tcg_temp_new_i64(); - /* FIXME: cpu_M0 can probably be the same as cpu_V0. */ cpu_M0 = tcg_temp_new_i64(); } @@ -11084,7 +9151,8 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) break; case DISAS_NEXT: case DISAS_TOO_MANY: - case DISAS_UPDATE: + case DISAS_UPDATE_EXIT: + case DISAS_UPDATE_NOCHAIN: gen_set_pc_im(dc, dc->base.pc_next); /* fall through */ default: @@ -11103,15 +9171,18 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) - Hardware watchpoints. Hardware breakpoints have already been handled and skip this code. */ - switch(dc->base.is_jmp) { + switch (dc->base.is_jmp) { case DISAS_NEXT: case DISAS_TOO_MANY: gen_goto_tb(dc, 1, dc->base.pc_next); break; + case DISAS_UPDATE_NOCHAIN: + gen_set_pc_im(dc, dc->base.pc_next); + /* fall through */ case DISAS_JUMP: gen_goto_ptr(); break; - case DISAS_UPDATE: + case DISAS_UPDATE_EXIT: gen_set_pc_im(dc, dc->base.pc_next); /* fall through */ default: diff --git a/target/arm/translate.h b/target/arm/translate.h index c937dfe9bf0ce82c2c6ed2d0c9e085ddb796a5a7..423b0e08df0c4343ffee3d84b351620ced20722f 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -30,6 +30,7 @@ typedef struct DisasContext { ARMMMUIdx mmu_idx; /* MMU index to use for normal loads/stores */ uint8_t tbii; /* TBI1|TBI0 for insns */ uint8_t tbid; /* TBI1|TBI0 for data */ + uint8_t tcma; /* TCMA1|TCMA0 for MTE */ bool ns; /* Use non-secure CPREG bank on access */ int fp_excp_el; /* FP exception EL or 0 if enabled */ int sve_excp_el; /* SVE exception EL or 0 if enabled */ @@ -63,6 +64,7 @@ typedef struct DisasContext { * that it is set at the point where we actually touch the FP regs. */ bool fp_access_checked; + bool sve_access_checked; /* ARMv8 single-step state (this is distinct from the QEMU gdbstub * single-step support). */ @@ -77,6 +79,10 @@ typedef struct DisasContext { bool unpriv; /* True if v8.3-PAuth is active. */ bool pauth_active; + /* True if v8.5-MTE access to tags is enabled. */ + bool ata; + /* True if v8.5-MTE tag checks affect the PE; index with is_unpriv. */ + bool mte_active[2]; /* True with v8.5-BTI and SCTLR_ELx.BT* set. */ bool bt; /* True if any CP15 access is trapped by HSTR_EL2 */ @@ -86,6 +92,8 @@ typedef struct DisasContext { * < 0, set by the current instruction. */ int8_t btype; + /* A copy of cpu->dcz_blocksize. */ + uint8_t dcz_blocksize; /* True if this page is guarded. */ bool guarded_page; /* Bottom two bits of XScale c15_cpar coprocessor access control reg */ @@ -148,7 +156,8 @@ static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn) /* is_jmp field values */ #define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */ -#define DISAS_UPDATE DISAS_TARGET_1 /* cpu state was modified dynamically */ +/* CPU state was modified dynamically; exit to main loop for interrupts. */ +#define DISAS_UPDATE_EXIT DISAS_TARGET_1 /* These instructions trap after executing, so the A32/T32 decoder must * defer them until after the conditional execution state has been updated. * WFI also needs special handling when single-stepping. @@ -164,13 +173,16 @@ static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn) * custom end-of-TB code) */ #define DISAS_BX_EXCRET DISAS_TARGET_8 -/* For instructions which want an immediate exit to the main loop, - * as opposed to attempting to use lookup_and_goto_ptr. Unlike - * DISAS_UPDATE this doesn't write the PC on exiting the translation - * loop so you need to ensure something (gen_a64_set_pc_im or runtime - * helper) has done so before we reach return from cpu_tb_exec. +/* + * For instructions which want an immediate exit to the main loop, as opposed + * to attempting to use lookup_and_goto_ptr. Unlike DISAS_UPDATE_EXIT, this + * doesn't write the PC on exiting the translation loop so you need to ensure + * something (gen_a64_set_pc_im or runtime helper) has done so before we reach + * return from cpu_tb_exec. */ #define DISAS_EXIT DISAS_TARGET_9 +/* CPU state was modified dynamically; no need to exit, but do not chain. */ +#define DISAS_UPDATE_NOCHAIN DISAS_TARGET_10 #ifdef TARGET_AARCH64 void a64_translate_init(void); @@ -363,6 +375,7 @@ typedef void GVecGen4Fn(unsigned, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); /* Function prototype for gen_ functions for calling Neon helpers */ +typedef void NeonGenOneOpFn(TCGv_i32, TCGv_i32); typedef void NeonGenOneOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32); typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32); typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32); @@ -371,12 +384,66 @@ typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64); typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64); typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64); typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32); -typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr); -typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr); -typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64); +typedef void NeonGenTwoOpWidenFn(TCGv_i64, TCGv_i32, TCGv_i32); +typedef void NeonGenOneSingleOpFn(TCGv_i32, TCGv_i32, TCGv_ptr); +typedef void NeonGenTwoSingleOpFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr); +typedef void NeonGenTwoDoubleOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr); +typedef void NeonGenOne64OpFn(TCGv_i64, TCGv_i64); typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr); typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32); typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr); typedef void AtomicThreeOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGArg, MemOp); +/* + * Enum for argument to fpstatus_ptr(). + */ +typedef enum ARMFPStatusFlavour { + FPST_FPCR, + FPST_FPCR_F16, + FPST_STD, + FPST_STD_F16, +} ARMFPStatusFlavour; + +/** + * fpstatus_ptr: return TCGv_ptr to the specified fp_status field + * + * We have multiple softfloat float_status fields in the Arm CPU state struct + * (see the comment in cpu.h for details). Return a TCGv_ptr which has + * been set up to point to the requested field in the CPU state struct. + * The options are: + * + * FPST_FPCR + * for non-FP16 operations controlled by the FPCR + * FPST_FPCR_F16 + * for operations controlled by the FPCR where FPCR.FZ16 is to be used + * FPST_STD + * for A32/T32 Neon operations using the "standard FPSCR value" + * FPST_STD_F16 + * as FPST_STD, but where FPCR.FZ16 is to be used + */ +static inline TCGv_ptr fpstatus_ptr(ARMFPStatusFlavour flavour) +{ + TCGv_ptr statusptr = tcg_temp_new_ptr(); + int offset; + + switch (flavour) { + case FPST_FPCR: + offset = offsetof(CPUARMState, vfp.fp_status); + break; + case FPST_FPCR_F16: + offset = offsetof(CPUARMState, vfp.fp_status_f16); + break; + case FPST_STD: + offset = offsetof(CPUARMState, vfp.standard_fp_status); + break; + case FPST_STD_F16: + offset = offsetof(CPUARMState, vfp.standard_fp_status_f16); + break; + default: + g_assert_not_reached(); + } + tcg_gen_addi_ptr(statusptr, cpu_env, offset); + return statusptr; +} + #endif /* TARGET_ARM_TRANSLATE_H */ diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c index 50a499299fd1fa0f01548b0c7756dc1bd25e0533..7174030377c5c1500d53fe8bc4f4e30ead3fa029 100644 --- a/target/arm/vec_helper.c +++ b/target/arm/vec_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -22,7 +22,7 @@ #include "exec/helper-proto.h" #include "tcg/tcg-gvec-desc.h" #include "fpu/softfloat.h" - +#include "vec_internal.h" /* Note that vector data is stored in host-endian 64-bit chunks, so addressing units smaller than that needs a host-endian fixup. */ @@ -36,30 +36,25 @@ #define H4(x) (x) #endif -static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz) -{ - uint64_t *d = vd + opr_sz; - uintptr_t i; - - for (i = opr_sz; i < max_sz; i += 8) { - *d++ = 0; - } -} - /* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */ -static int16_t inl_qrdmlah_s16(int16_t src1, int16_t src2, - int16_t src3, uint32_t *sat) +static int16_t do_sqrdmlah_h(int16_t src1, int16_t src2, int16_t src3, + bool neg, bool round, uint32_t *sat) { - /* Simplify: + /* + * Simplify: * = ((a3 << 16) + ((e1 * e2) << 1) + (1 << 15)) >> 16 * = ((a3 << 15) + (e1 * e2) + (1 << 14)) >> 15 */ int32_t ret = (int32_t)src1 * src2; - ret = ((int32_t)src3 << 15) + ret + (1 << 14); + if (neg) { + ret = -ret; + } + ret += ((int32_t)src3 << 15) + (round << 14); ret >>= 15; + if (ret != (int16_t)ret) { *sat = 1; - ret = (ret < 0 ? -0x8000 : 0x7fff); + ret = (ret < 0 ? INT16_MIN : INT16_MAX); } return ret; } @@ -68,8 +63,9 @@ uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1, uint32_t src2, uint32_t src3) { uint32_t *sat = &env->vfp.qc[0]; - uint16_t e1 = inl_qrdmlah_s16(src1, src2, src3, sat); - uint16_t e2 = inl_qrdmlah_s16(src1 >> 16, src2 >> 16, src3 >> 16, sat); + uint16_t e1 = do_sqrdmlah_h(src1, src2, src3, false, true, sat); + uint16_t e2 = do_sqrdmlah_h(src1 >> 16, src2 >> 16, src3 >> 16, + false, true, sat); return deposit32(e1, 16, 16, e2); } @@ -83,35 +79,18 @@ void HELPER(gvec_qrdmlah_s16)(void *vd, void *vn, void *vm, uintptr_t i; for (i = 0; i < opr_sz / 2; ++i) { - d[i] = inl_qrdmlah_s16(n[i], m[i], d[i], vq); + d[i] = do_sqrdmlah_h(n[i], m[i], d[i], false, true, vq); } clear_tail(d, opr_sz, simd_maxsz(desc)); } -/* Signed saturating rounding doubling multiply-subtract high half, 16-bit */ -static int16_t inl_qrdmlsh_s16(int16_t src1, int16_t src2, - int16_t src3, uint32_t *sat) -{ - /* Similarly, using subtraction: - * = ((a3 << 16) - ((e1 * e2) << 1) + (1 << 15)) >> 16 - * = ((a3 << 15) - (e1 * e2) + (1 << 14)) >> 15 - */ - int32_t ret = (int32_t)src1 * src2; - ret = ((int32_t)src3 << 15) - ret + (1 << 14); - ret >>= 15; - if (ret != (int16_t)ret) { - *sat = 1; - ret = (ret < 0 ? -0x8000 : 0x7fff); - } - return ret; -} - uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1, uint32_t src2, uint32_t src3) { uint32_t *sat = &env->vfp.qc[0]; - uint16_t e1 = inl_qrdmlsh_s16(src1, src2, src3, sat); - uint16_t e2 = inl_qrdmlsh_s16(src1 >> 16, src2 >> 16, src3 >> 16, sat); + uint16_t e1 = do_sqrdmlah_h(src1, src2, src3, true, true, sat); + uint16_t e2 = do_sqrdmlah_h(src1 >> 16, src2 >> 16, src3 >> 16, + true, true, sat); return deposit32(e1, 16, 16, e2); } @@ -125,19 +104,47 @@ void HELPER(gvec_qrdmlsh_s16)(void *vd, void *vn, void *vm, uintptr_t i; for (i = 0; i < opr_sz / 2; ++i) { - d[i] = inl_qrdmlsh_s16(n[i], m[i], d[i], vq); + d[i] = do_sqrdmlah_h(n[i], m[i], d[i], true, true, vq); + } + clear_tail(d, opr_sz, simd_maxsz(desc)); +} + +void HELPER(neon_sqdmulh_h)(void *vd, void *vn, void *vm, + void *vq, uint32_t desc) +{ + intptr_t i, opr_sz = simd_oprsz(desc); + int16_t *d = vd, *n = vn, *m = vm; + + for (i = 0; i < opr_sz / 2; ++i) { + d[i] = do_sqrdmlah_h(n[i], m[i], 0, false, false, vq); + } + clear_tail(d, opr_sz, simd_maxsz(desc)); +} + +void HELPER(neon_sqrdmulh_h)(void *vd, void *vn, void *vm, + void *vq, uint32_t desc) +{ + intptr_t i, opr_sz = simd_oprsz(desc); + int16_t *d = vd, *n = vn, *m = vm; + + for (i = 0; i < opr_sz / 2; ++i) { + d[i] = do_sqrdmlah_h(n[i], m[i], 0, false, true, vq); } clear_tail(d, opr_sz, simd_maxsz(desc)); } /* Signed saturating rounding doubling multiply-accumulate high half, 32-bit */ -static int32_t inl_qrdmlah_s32(int32_t src1, int32_t src2, - int32_t src3, uint32_t *sat) +static int32_t do_sqrdmlah_s(int32_t src1, int32_t src2, int32_t src3, + bool neg, bool round, uint32_t *sat) { /* Simplify similarly to int_qrdmlah_s16 above. */ int64_t ret = (int64_t)src1 * src2; - ret = ((int64_t)src3 << 31) + ret + (1 << 30); + if (neg) { + ret = -ret; + } + ret += ((int64_t)src3 << 31) + (round << 30); ret >>= 31; + if (ret != (int32_t)ret) { *sat = 1; ret = (ret < 0 ? INT32_MIN : INT32_MAX); @@ -149,7 +156,7 @@ uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1, int32_t src2, int32_t src3) { uint32_t *sat = &env->vfp.qc[0]; - return inl_qrdmlah_s32(src1, src2, src3, sat); + return do_sqrdmlah_s(src1, src2, src3, false, true, sat); } void HELPER(gvec_qrdmlah_s32)(void *vd, void *vn, void *vm, @@ -162,31 +169,16 @@ void HELPER(gvec_qrdmlah_s32)(void *vd, void *vn, void *vm, uintptr_t i; for (i = 0; i < opr_sz / 4; ++i) { - d[i] = inl_qrdmlah_s32(n[i], m[i], d[i], vq); + d[i] = do_sqrdmlah_s(n[i], m[i], d[i], false, true, vq); } clear_tail(d, opr_sz, simd_maxsz(desc)); } -/* Signed saturating rounding doubling multiply-subtract high half, 32-bit */ -static int32_t inl_qrdmlsh_s32(int32_t src1, int32_t src2, - int32_t src3, uint32_t *sat) -{ - /* Simplify similarly to int_qrdmlsh_s16 above. */ - int64_t ret = (int64_t)src1 * src2; - ret = ((int64_t)src3 << 31) - ret + (1 << 30); - ret >>= 31; - if (ret != (int32_t)ret) { - *sat = 1; - ret = (ret < 0 ? INT32_MIN : INT32_MAX); - } - return ret; -} - uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1, int32_t src2, int32_t src3) { uint32_t *sat = &env->vfp.qc[0]; - return inl_qrdmlsh_s32(src1, src2, src3, sat); + return do_sqrdmlah_s(src1, src2, src3, true, true, sat); } void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm, @@ -199,7 +191,31 @@ void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm, uintptr_t i; for (i = 0; i < opr_sz / 4; ++i) { - d[i] = inl_qrdmlsh_s32(n[i], m[i], d[i], vq); + d[i] = do_sqrdmlah_s(n[i], m[i], d[i], true, true, vq); + } + clear_tail(d, opr_sz, simd_maxsz(desc)); +} + +void HELPER(neon_sqdmulh_s)(void *vd, void *vn, void *vm, + void *vq, uint32_t desc) +{ + intptr_t i, opr_sz = simd_oprsz(desc); + int32_t *d = vd, *n = vn, *m = vm; + + for (i = 0; i < opr_sz / 4; ++i) { + d[i] = do_sqrdmlah_s(n[i], m[i], 0, false, false, vq); + } + clear_tail(d, opr_sz, simd_maxsz(desc)); +} + +void HELPER(neon_sqrdmulh_s)(void *vd, void *vn, void *vm, + void *vq, uint32_t desc) +{ + intptr_t i, opr_sz = simd_oprsz(desc); + int32_t *d = vd, *n = vn, *m = vm; + + for (i = 0; i < opr_sz / 4; ++i) { + d[i] = do_sqrdmlah_s(n[i], m[i], 0, false, true, vq); } clear_tail(d, opr_sz, simd_maxsz(desc)); } @@ -277,7 +293,7 @@ void HELPER(gvec_sdot_idx_b)(void *vd, void *vn, void *vm, uint32_t desc) intptr_t index = simd_data(desc); uint32_t *d = vd; int8_t *n = vn; - int8_t *m_indexed = (int8_t *)vm + index * 4; + int8_t *m_indexed = (int8_t *)vm + H4(index) * 4; /* Notice the special case of opr_sz == 8, from aa64/aa32 advsimd. * Otherwise opr_sz is a multiple of 16. @@ -308,7 +324,7 @@ void HELPER(gvec_udot_idx_b)(void *vd, void *vn, void *vm, uint32_t desc) intptr_t index = simd_data(desc); uint32_t *d = vd; uint8_t *n = vn; - uint8_t *m_indexed = (uint8_t *)vm + index * 4; + uint8_t *m_indexed = (uint8_t *)vm + H4(index) * 4; /* Notice the special case of opr_sz == 8, from aa64/aa32 advsimd. * Otherwise opr_sz is a multiple of 16. @@ -640,6 +656,81 @@ void HELPER(gvec_fcmlad)(void *vd, void *vn, void *vm, clear_tail(d, opr_sz, simd_maxsz(desc)); } +/* + * Floating point comparisons producing an integer result (all 1s or all 0s). + * Note that EQ doesn't signal InvalidOp for QNaNs but GE and GT do. + * Softfloat routines return 0/1, which we convert to the 0/-1 Neon requires. + */ +static uint16_t float16_ceq(float16 op1, float16 op2, float_status *stat) +{ + return -float16_eq_quiet(op1, op2, stat); +} + +static uint32_t float32_ceq(float32 op1, float32 op2, float_status *stat) +{ + return -float32_eq_quiet(op1, op2, stat); +} + +static uint16_t float16_cge(float16 op1, float16 op2, float_status *stat) +{ + return -float16_le(op2, op1, stat); +} + +static uint32_t float32_cge(float32 op1, float32 op2, float_status *stat) +{ + return -float32_le(op2, op1, stat); +} + +static uint16_t float16_cgt(float16 op1, float16 op2, float_status *stat) +{ + return -float16_lt(op2, op1, stat); +} + +static uint32_t float32_cgt(float32 op1, float32 op2, float_status *stat) +{ + return -float32_lt(op2, op1, stat); +} + +static uint16_t float16_acge(float16 op1, float16 op2, float_status *stat) +{ + return -float16_le(float16_abs(op2), float16_abs(op1), stat); +} + +static uint32_t float32_acge(float32 op1, float32 op2, float_status *stat) +{ + return -float32_le(float32_abs(op2), float32_abs(op1), stat); +} + +static uint16_t float16_acgt(float16 op1, float16 op2, float_status *stat) +{ + return -float16_lt(float16_abs(op2), float16_abs(op1), stat); +} + +static uint32_t float32_acgt(float32 op1, float32 op2, float_status *stat) +{ + return -float32_lt(float32_abs(op2), float32_abs(op1), stat); +} + +static int16_t vfp_tosszh(float16 x, void *fpstp) +{ + float_status *fpst = fpstp; + if (float16_is_any_nan(x)) { + float_raise(float_flag_invalid, fpst); + return 0; + } + return float16_to_int16_round_to_zero(x, fpst); +} + +static uint16_t vfp_touszh(float16 x, void *fpstp) +{ + float_status *fpst = fpstp; + if (float16_is_any_nan(x)) { + float_raise(float_flag_invalid, fpst); + return 0; + } + return float16_to_uint16_round_to_zero(x, fpst); +} + #define DO_2OP(NAME, FUNC, TYPE) \ void HELPER(NAME)(void *vd, void *vn, void *stat, uint32_t desc) \ { \ @@ -659,7 +750,44 @@ DO_2OP(gvec_frsqrte_h, helper_rsqrte_f16, float16) DO_2OP(gvec_frsqrte_s, helper_rsqrte_f32, float32) DO_2OP(gvec_frsqrte_d, helper_rsqrte_f64, float64) +DO_2OP(gvec_vrintx_h, float16_round_to_int, float16) +DO_2OP(gvec_vrintx_s, float32_round_to_int, float32) + +DO_2OP(gvec_sitos, helper_vfp_sitos, int32_t) +DO_2OP(gvec_uitos, helper_vfp_uitos, uint32_t) +DO_2OP(gvec_tosizs, helper_vfp_tosizs, float32) +DO_2OP(gvec_touizs, helper_vfp_touizs, float32) +DO_2OP(gvec_sstoh, int16_to_float16, int16_t) +DO_2OP(gvec_ustoh, uint16_to_float16, uint16_t) +DO_2OP(gvec_tosszh, vfp_tosszh, float16) +DO_2OP(gvec_touszh, vfp_touszh, float16) + +#define WRAP_CMP0_FWD(FN, CMPOP, TYPE) \ + static TYPE TYPE##_##FN##0(TYPE op, float_status *stat) \ + { \ + return TYPE##_##CMPOP(op, TYPE##_zero, stat); \ + } + +#define WRAP_CMP0_REV(FN, CMPOP, TYPE) \ + static TYPE TYPE##_##FN##0(TYPE op, float_status *stat) \ + { \ + return TYPE##_##CMPOP(TYPE##_zero, op, stat); \ + } + +#define DO_2OP_CMP0(FN, CMPOP, DIRN) \ + WRAP_CMP0_##DIRN(FN, CMPOP, float16) \ + WRAP_CMP0_##DIRN(FN, CMPOP, float32) \ + DO_2OP(gvec_f##FN##0_h, float16_##FN##0, float16) \ + DO_2OP(gvec_f##FN##0_s, float32_##FN##0, float32) + +DO_2OP_CMP0(cgt, cgt, FWD) +DO_2OP_CMP0(cge, cge, FWD) +DO_2OP_CMP0(ceq, ceq, FWD) +DO_2OP_CMP0(clt, cgt, REV) +DO_2OP_CMP0(cle, cge, REV) + #undef DO_2OP +#undef DO_2OP_CMP0 /* Floating-point trigonometric starting value. * See the ARM ARM pseudocode function FPTrigSMul. @@ -691,11 +819,71 @@ static float64 float64_ftsmul(float64 op1, uint64_t op2, float_status *stat) return result; } +static float16 float16_abd(float16 op1, float16 op2, float_status *stat) +{ + return float16_abs(float16_sub(op1, op2, stat)); +} + static float32 float32_abd(float32 op1, float32 op2, float_status *stat) { return float32_abs(float32_sub(op1, op2, stat)); } +/* + * Reciprocal step. These are the AArch32 version which uses a + * non-fused multiply-and-subtract. + */ +static float16 float16_recps_nf(float16 op1, float16 op2, float_status *stat) +{ + op1 = float16_squash_input_denormal(op1, stat); + op2 = float16_squash_input_denormal(op2, stat); + + if ((float16_is_infinity(op1) && float16_is_zero(op2)) || + (float16_is_infinity(op2) && float16_is_zero(op1))) { + return float16_two; + } + return float16_sub(float16_two, float16_mul(op1, op2, stat), stat); +} + +static float32 float32_recps_nf(float32 op1, float32 op2, float_status *stat) +{ + op1 = float32_squash_input_denormal(op1, stat); + op2 = float32_squash_input_denormal(op2, stat); + + if ((float32_is_infinity(op1) && float32_is_zero(op2)) || + (float32_is_infinity(op2) && float32_is_zero(op1))) { + return float32_two; + } + return float32_sub(float32_two, float32_mul(op1, op2, stat), stat); +} + +/* Reciprocal square-root step. AArch32 non-fused semantics. */ +static float16 float16_rsqrts_nf(float16 op1, float16 op2, float_status *stat) +{ + op1 = float16_squash_input_denormal(op1, stat); + op2 = float16_squash_input_denormal(op2, stat); + + if ((float16_is_infinity(op1) && float16_is_zero(op2)) || + (float16_is_infinity(op2) && float16_is_zero(op1))) { + return float16_one_point_five; + } + op1 = float16_sub(float16_three, float16_mul(op1, op2, stat), stat); + return float16_div(op1, float16_two, stat); +} + +static float32 float32_rsqrts_nf(float32 op1, float32 op2, float_status *stat) +{ + op1 = float32_squash_input_denormal(op1, stat); + op2 = float32_squash_input_denormal(op2, stat); + + if ((float32_is_infinity(op1) && float32_is_zero(op2)) || + (float32_is_infinity(op2) && float32_is_zero(op1))) { + return float32_one_point_five; + } + op1 = float32_sub(float32_three, float32_mul(op1, op2, stat), stat); + return float32_div(op1, float32_two, stat); +} + #define DO_3OP(NAME, FUNC, TYPE) \ void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \ { \ @@ -723,8 +911,42 @@ DO_3OP(gvec_ftsmul_h, float16_ftsmul, float16) DO_3OP(gvec_ftsmul_s, float32_ftsmul, float32) DO_3OP(gvec_ftsmul_d, float64_ftsmul, float64) +DO_3OP(gvec_fabd_h, float16_abd, float16) DO_3OP(gvec_fabd_s, float32_abd, float32) +DO_3OP(gvec_fceq_h, float16_ceq, float16) +DO_3OP(gvec_fceq_s, float32_ceq, float32) + +DO_3OP(gvec_fcge_h, float16_cge, float16) +DO_3OP(gvec_fcge_s, float32_cge, float32) + +DO_3OP(gvec_fcgt_h, float16_cgt, float16) +DO_3OP(gvec_fcgt_s, float32_cgt, float32) + +DO_3OP(gvec_facge_h, float16_acge, float16) +DO_3OP(gvec_facge_s, float32_acge, float32) + +DO_3OP(gvec_facgt_h, float16_acgt, float16) +DO_3OP(gvec_facgt_s, float32_acgt, float32) + +DO_3OP(gvec_fmax_h, float16_max, float16) +DO_3OP(gvec_fmax_s, float32_max, float32) + +DO_3OP(gvec_fmin_h, float16_min, float16) +DO_3OP(gvec_fmin_s, float32_min, float32) + +DO_3OP(gvec_fmaxnum_h, float16_maxnum, float16) +DO_3OP(gvec_fmaxnum_s, float32_maxnum, float32) + +DO_3OP(gvec_fminnum_h, float16_minnum, float16) +DO_3OP(gvec_fminnum_s, float32_minnum, float32) + +DO_3OP(gvec_recps_nf_h, float16_recps_nf, float16) +DO_3OP(gvec_recps_nf_s, float32_recps_nf, float32) + +DO_3OP(gvec_rsqrts_nf_h, float16_rsqrts_nf, float16) +DO_3OP(gvec_rsqrts_nf_s, float32_rsqrts_nf, float32) + #ifdef TARGET_AARCH64 DO_3OP(gvec_recps_h, helper_recpsf_f16, float16) @@ -738,36 +960,176 @@ DO_3OP(gvec_rsqrts_d, helper_rsqrtsf_f64, float64) #endif #undef DO_3OP +/* Non-fused multiply-add (unlike float16_muladd etc, which are fused) */ +static float16 float16_muladd_nf(float16 dest, float16 op1, float16 op2, + float_status *stat) +{ + return float16_add(dest, float16_mul(op1, op2, stat), stat); +} + +static float32 float32_muladd_nf(float32 dest, float32 op1, float32 op2, + float_status *stat) +{ + return float32_add(dest, float32_mul(op1, op2, stat), stat); +} + +static float16 float16_mulsub_nf(float16 dest, float16 op1, float16 op2, + float_status *stat) +{ + return float16_sub(dest, float16_mul(op1, op2, stat), stat); +} + +static float32 float32_mulsub_nf(float32 dest, float32 op1, float32 op2, + float_status *stat) +{ + return float32_sub(dest, float32_mul(op1, op2, stat), stat); +} + +/* Fused versions; these have the semantics Neon VFMA/VFMS want */ +static float16 float16_muladd_f(float16 dest, float16 op1, float16 op2, + float_status *stat) +{ + return float16_muladd(op1, op2, dest, 0, stat); +} + +static float32 float32_muladd_f(float32 dest, float32 op1, float32 op2, + float_status *stat) +{ + return float32_muladd(op1, op2, dest, 0, stat); +} + +static float16 float16_mulsub_f(float16 dest, float16 op1, float16 op2, + float_status *stat) +{ + return float16_muladd(float16_chs(op1), op2, dest, 0, stat); +} + +static float32 float32_mulsub_f(float32 dest, float32 op1, float32 op2, + float_status *stat) +{ + return float32_muladd(float32_chs(op1), op2, dest, 0, stat); +} + +#define DO_MULADD(NAME, FUNC, TYPE) \ +void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \ +{ \ + intptr_t i, oprsz = simd_oprsz(desc); \ + TYPE *d = vd, *n = vn, *m = vm; \ + for (i = 0; i < oprsz / sizeof(TYPE); i++) { \ + d[i] = FUNC(d[i], n[i], m[i], stat); \ + } \ + clear_tail(d, oprsz, simd_maxsz(desc)); \ +} + +DO_MULADD(gvec_fmla_h, float16_muladd_nf, float16) +DO_MULADD(gvec_fmla_s, float32_muladd_nf, float32) + +DO_MULADD(gvec_fmls_h, float16_mulsub_nf, float16) +DO_MULADD(gvec_fmls_s, float32_mulsub_nf, float32) + +DO_MULADD(gvec_vfma_h, float16_muladd_f, float16) +DO_MULADD(gvec_vfma_s, float32_muladd_f, float32) + +DO_MULADD(gvec_vfms_h, float16_mulsub_f, float16) +DO_MULADD(gvec_vfms_s, float32_mulsub_f, float32) + /* For the indexed ops, SVE applies the index per 128-bit vector segment. * For AdvSIMD, there is of course only one such vector segment. */ #define DO_MUL_IDX(NAME, TYPE, H) \ -void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \ +void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \ { \ - intptr_t i, j, oprsz = simd_oprsz(desc), segment = 16 / sizeof(TYPE); \ + intptr_t i, j, oprsz = simd_oprsz(desc); \ + intptr_t segment = MIN(16, oprsz) / sizeof(TYPE); \ intptr_t idx = simd_data(desc); \ TYPE *d = vd, *n = vn, *m = vm; \ for (i = 0; i < oprsz / sizeof(TYPE); i += segment) { \ TYPE mm = m[H(i + idx)]; \ for (j = 0; j < segment; j++) { \ - d[i + j] = TYPE##_mul(n[i + j], mm, stat); \ + d[i + j] = n[i + j] * mm; \ } \ } \ clear_tail(d, oprsz, simd_maxsz(desc)); \ } -DO_MUL_IDX(gvec_fmul_idx_h, float16, H2) -DO_MUL_IDX(gvec_fmul_idx_s, float32, H4) -DO_MUL_IDX(gvec_fmul_idx_d, float64, ) +DO_MUL_IDX(gvec_mul_idx_h, uint16_t, H2) +DO_MUL_IDX(gvec_mul_idx_s, uint32_t, H4) +DO_MUL_IDX(gvec_mul_idx_d, uint64_t, ) #undef DO_MUL_IDX +#define DO_MLA_IDX(NAME, TYPE, OP, H) \ +void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, uint32_t desc) \ +{ \ + intptr_t i, j, oprsz = simd_oprsz(desc); \ + intptr_t segment = MIN(16, oprsz) / sizeof(TYPE); \ + intptr_t idx = simd_data(desc); \ + TYPE *d = vd, *n = vn, *m = vm, *a = va; \ + for (i = 0; i < oprsz / sizeof(TYPE); i += segment) { \ + TYPE mm = m[H(i + idx)]; \ + for (j = 0; j < segment; j++) { \ + d[i + j] = a[i + j] OP n[i + j] * mm; \ + } \ + } \ + clear_tail(d, oprsz, simd_maxsz(desc)); \ +} + +DO_MLA_IDX(gvec_mla_idx_h, uint16_t, +, H2) +DO_MLA_IDX(gvec_mla_idx_s, uint32_t, +, H4) +DO_MLA_IDX(gvec_mla_idx_d, uint64_t, +, ) + +DO_MLA_IDX(gvec_mls_idx_h, uint16_t, -, H2) +DO_MLA_IDX(gvec_mls_idx_s, uint32_t, -, H4) +DO_MLA_IDX(gvec_mls_idx_d, uint64_t, -, ) + +#undef DO_MLA_IDX + +#define DO_FMUL_IDX(NAME, ADD, TYPE, H) \ +void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \ +{ \ + intptr_t i, j, oprsz = simd_oprsz(desc); \ + intptr_t segment = MIN(16, oprsz) / sizeof(TYPE); \ + intptr_t idx = simd_data(desc); \ + TYPE *d = vd, *n = vn, *m = vm; \ + for (i = 0; i < oprsz / sizeof(TYPE); i += segment) { \ + TYPE mm = m[H(i + idx)]; \ + for (j = 0; j < segment; j++) { \ + d[i + j] = TYPE##_##ADD(d[i + j], \ + TYPE##_mul(n[i + j], mm, stat), stat); \ + } \ + } \ + clear_tail(d, oprsz, simd_maxsz(desc)); \ +} + +#define float16_nop(N, M, S) (M) +#define float32_nop(N, M, S) (M) +#define float64_nop(N, M, S) (M) + +DO_FMUL_IDX(gvec_fmul_idx_h, nop, float16, H2) +DO_FMUL_IDX(gvec_fmul_idx_s, nop, float32, H4) +DO_FMUL_IDX(gvec_fmul_idx_d, nop, float64, ) + +/* + * Non-fused multiply-accumulate operations, for Neon. NB that unlike + * the fused ops below they assume accumulate both from and into Vd. + */ +DO_FMUL_IDX(gvec_fmla_nf_idx_h, add, float16, H2) +DO_FMUL_IDX(gvec_fmla_nf_idx_s, add, float32, H4) +DO_FMUL_IDX(gvec_fmls_nf_idx_h, sub, float16, H2) +DO_FMUL_IDX(gvec_fmls_nf_idx_s, sub, float32, H4) + +#undef float16_nop +#undef float32_nop +#undef float64_nop +#undef DO_FMUL_IDX + #define DO_FMLA_IDX(NAME, TYPE, H) \ void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, \ void *stat, uint32_t desc) \ { \ - intptr_t i, j, oprsz = simd_oprsz(desc), segment = 16 / sizeof(TYPE); \ + intptr_t i, j, oprsz = simd_oprsz(desc); \ + intptr_t segment = MIN(16, oprsz) / sizeof(TYPE); \ TYPE op1_neg = extract32(desc, SIMD_DATA_SHIFT, 1); \ intptr_t idx = desc >> (SIMD_DATA_SHIFT + 1); \ TYPE *d = vd, *n = vn, *m = vm, *a = va; \ @@ -1462,3 +1824,116 @@ DO_ABA(gvec_uaba_s, uint32_t) DO_ABA(gvec_uaba_d, uint64_t) #undef DO_ABA + +#define DO_NEON_PAIRWISE(NAME, OP) \ + void HELPER(NAME##s)(void *vd, void *vn, void *vm, \ + void *stat, uint32_t oprsz) \ + { \ + float_status *fpst = stat; \ + float32 *d = vd; \ + float32 *n = vn; \ + float32 *m = vm; \ + float32 r0, r1; \ + \ + /* Read all inputs before writing outputs in case vm == vd */ \ + r0 = float32_##OP(n[H4(0)], n[H4(1)], fpst); \ + r1 = float32_##OP(m[H4(0)], m[H4(1)], fpst); \ + \ + d[H4(0)] = r0; \ + d[H4(1)] = r1; \ + } \ + \ + void HELPER(NAME##h)(void *vd, void *vn, void *vm, \ + void *stat, uint32_t oprsz) \ + { \ + float_status *fpst = stat; \ + float16 *d = vd; \ + float16 *n = vn; \ + float16 *m = vm; \ + float16 r0, r1, r2, r3; \ + \ + /* Read all inputs before writing outputs in case vm == vd */ \ + r0 = float16_##OP(n[H2(0)], n[H2(1)], fpst); \ + r1 = float16_##OP(n[H2(2)], n[H2(3)], fpst); \ + r2 = float16_##OP(m[H2(0)], m[H2(1)], fpst); \ + r3 = float16_##OP(m[H2(2)], m[H2(3)], fpst); \ + \ + d[H2(0)] = r0; \ + d[H2(1)] = r1; \ + d[H2(2)] = r2; \ + d[H2(3)] = r3; \ + } + +DO_NEON_PAIRWISE(neon_padd, add) +DO_NEON_PAIRWISE(neon_pmax, max) +DO_NEON_PAIRWISE(neon_pmin, min) + +#undef DO_NEON_PAIRWISE + +#define DO_VCVT_FIXED(NAME, FUNC, TYPE) \ + void HELPER(NAME)(void *vd, void *vn, void *stat, uint32_t desc) \ + { \ + intptr_t i, oprsz = simd_oprsz(desc); \ + int shift = simd_data(desc); \ + TYPE *d = vd, *n = vn; \ + float_status *fpst = stat; \ + for (i = 0; i < oprsz / sizeof(TYPE); i++) { \ + d[i] = FUNC(n[i], shift, fpst); \ + } \ + clear_tail(d, oprsz, simd_maxsz(desc)); \ + } + +DO_VCVT_FIXED(gvec_vcvt_sf, helper_vfp_sltos, uint32_t) +DO_VCVT_FIXED(gvec_vcvt_uf, helper_vfp_ultos, uint32_t) +DO_VCVT_FIXED(gvec_vcvt_fs, helper_vfp_tosls_round_to_zero, uint32_t) +DO_VCVT_FIXED(gvec_vcvt_fu, helper_vfp_touls_round_to_zero, uint32_t) +DO_VCVT_FIXED(gvec_vcvt_sh, helper_vfp_shtoh, uint16_t) +DO_VCVT_FIXED(gvec_vcvt_uh, helper_vfp_uhtoh, uint16_t) +DO_VCVT_FIXED(gvec_vcvt_hs, helper_vfp_toshh_round_to_zero, uint16_t) +DO_VCVT_FIXED(gvec_vcvt_hu, helper_vfp_touhh_round_to_zero, uint16_t) + +#undef DO_VCVT_FIXED + +#define DO_VCVT_RMODE(NAME, FUNC, TYPE) \ + void HELPER(NAME)(void *vd, void *vn, void *stat, uint32_t desc) \ + { \ + float_status *fpst = stat; \ + intptr_t i, oprsz = simd_oprsz(desc); \ + uint32_t rmode = simd_data(desc); \ + uint32_t prev_rmode = get_float_rounding_mode(fpst); \ + TYPE *d = vd, *n = vn; \ + set_float_rounding_mode(rmode, fpst); \ + for (i = 0; i < oprsz / sizeof(TYPE); i++) { \ + d[i] = FUNC(n[i], 0, fpst); \ + } \ + set_float_rounding_mode(prev_rmode, fpst); \ + clear_tail(d, oprsz, simd_maxsz(desc)); \ + } + +DO_VCVT_RMODE(gvec_vcvt_rm_ss, helper_vfp_tosls, uint32_t) +DO_VCVT_RMODE(gvec_vcvt_rm_us, helper_vfp_touls, uint32_t) +DO_VCVT_RMODE(gvec_vcvt_rm_sh, helper_vfp_toshh, uint16_t) +DO_VCVT_RMODE(gvec_vcvt_rm_uh, helper_vfp_touhh, uint16_t) + +#undef DO_VCVT_RMODE + +#define DO_VRINT_RMODE(NAME, FUNC, TYPE) \ + void HELPER(NAME)(void *vd, void *vn, void *stat, uint32_t desc) \ + { \ + float_status *fpst = stat; \ + intptr_t i, oprsz = simd_oprsz(desc); \ + uint32_t rmode = simd_data(desc); \ + uint32_t prev_rmode = get_float_rounding_mode(fpst); \ + TYPE *d = vd, *n = vn; \ + set_float_rounding_mode(rmode, fpst); \ + for (i = 0; i < oprsz / sizeof(TYPE); i++) { \ + d[i] = FUNC(n[i], fpst); \ + } \ + set_float_rounding_mode(prev_rmode, fpst); \ + clear_tail(d, oprsz, simd_maxsz(desc)); \ + } + +DO_VRINT_RMODE(gvec_vrint_rm_h, helper_rinth, uint16_t) +DO_VRINT_RMODE(gvec_vrint_rm_s, helper_rints, uint32_t) + +#undef DO_VRINT_RMODE diff --git a/target/arm/vec_internal.h b/target/arm/vec_internal.h new file mode 100644 index 0000000000000000000000000000000000000000..e3eb3e7a6bc3d7966e11deea53dbdf304d164678 --- /dev/null +++ b/target/arm/vec_internal.h @@ -0,0 +1,33 @@ +/* + * ARM AdvSIMD / SVE Vector Helpers + * + * Copyright (c) 2020 Linaro + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef TARGET_ARM_VEC_INTERNALS_H +#define TARGET_ARM_VEC_INTERNALS_H + +static inline void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz) +{ + uint64_t *d = vd + opr_sz; + uintptr_t i; + + for (i = opr_sz; i < max_sz; i += 8) { + *d++ = 0; + } +} + +#endif /* TARGET_ARM_VEC_INTERNALS_H */ diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode index 34ca164266f8643b9d9d33df687eeb51b8784792..5c50447a668c18ed7bcb9d5c87d09c5fc7b3f27b 100644 --- a/target/arm/vfp-uncond.decode +++ b/target/arm/vfp-uncond.decode @@ -5,7 +5,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -44,10 +44,15 @@ @vfp_dnm_s ................................ vm=%vm_sp vn=%vn_sp vd=%vd_sp @vfp_dnm_d ................................ vm=%vm_dp vn=%vn_dp vd=%vd_dp +VSEL 1111 1110 0. cc:2 .... .... 1001 .0.0 .... \ + vm=%vm_sp vn=%vn_sp vd=%vd_sp sz=1 VSEL 1111 1110 0. cc:2 .... .... 1010 .0.0 .... \ - vm=%vm_sp vn=%vn_sp vd=%vd_sp dp=0 + vm=%vm_sp vn=%vn_sp vd=%vd_sp sz=2 VSEL 1111 1110 0. cc:2 .... .... 1011 .0.0 .... \ - vm=%vm_dp vn=%vn_dp vd=%vd_dp dp=1 + vm=%vm_dp vn=%vn_dp vd=%vd_dp sz=3 + +VMAXNM_hp 1111 1110 1.00 .... .... 1001 .0.0 .... @vfp_dnm_s +VMINNM_hp 1111 1110 1.00 .... .... 1001 .1.0 .... @vfp_dnm_s VMAXNM_sp 1111 1110 1.00 .... .... 1010 .0.0 .... @vfp_dnm_s VMINNM_sp 1111 1110 1.00 .... .... 1010 .1.0 .... @vfp_dnm_s @@ -55,13 +60,23 @@ VMINNM_sp 1111 1110 1.00 .... .... 1010 .1.0 .... @vfp_dnm_s VMAXNM_dp 1111 1110 1.00 .... .... 1011 .0.0 .... @vfp_dnm_d VMINNM_dp 1111 1110 1.00 .... .... 1011 .1.0 .... @vfp_dnm_d +VRINT 1111 1110 1.11 10 rm:2 .... 1001 01.0 .... \ + vm=%vm_sp vd=%vd_sp sz=1 VRINT 1111 1110 1.11 10 rm:2 .... 1010 01.0 .... \ - vm=%vm_sp vd=%vd_sp dp=0 + vm=%vm_sp vd=%vd_sp sz=2 VRINT 1111 1110 1.11 10 rm:2 .... 1011 01.0 .... \ - vm=%vm_dp vd=%vd_dp dp=1 + vm=%vm_dp vd=%vd_dp sz=3 # VCVT float to int with specified rounding mode; Vd is always single-precision +VCVT 1111 1110 1.11 11 rm:2 .... 1001 op:1 1.0 .... \ + vm=%vm_sp vd=%vd_sp sz=1 VCVT 1111 1110 1.11 11 rm:2 .... 1010 op:1 1.0 .... \ - vm=%vm_sp vd=%vd_sp dp=0 + vm=%vm_sp vd=%vd_sp sz=2 VCVT 1111 1110 1.11 11 rm:2 .... 1011 op:1 1.0 .... \ - vm=%vm_dp vd=%vd_sp dp=1 + vm=%vm_dp vd=%vd_sp sz=3 + +VMOVX 1111 1110 1.11 0000 .... 1010 01 . 0 .... \ + vd=%vd_sp vm=%vm_sp + +VINS 1111 1110 1.11 0000 .... 1010 11 . 0 .... \ + vd=%vd_sp vm=%vm_sp diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode index 5fd70f975aefa02e704ba17b3628e460f9b84682..1300ba045ddaa571fad7cb63c636e86c5729a276 100644 --- a/target/arm/vfp.decode +++ b/target/arm/vfp.decode @@ -5,7 +5,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -74,13 +74,13 @@ VDUP ---- 1110 1 b:1 q:1 0 .... rt:4 1011 . 0 e:1 1 0000 \ vn=%vn_dp VMSR_VMRS ---- 1110 111 l:1 reg:4 rt:4 1010 0001 0000 +VMOV_half ---- 1110 000 l:1 .... rt:4 1001 . 001 0000 vn=%vn_sp VMOV_single ---- 1110 000 l:1 .... rt:4 1010 . 001 0000 vn=%vn_sp VMOV_64_sp ---- 1100 010 op:1 rt2:4 rt:4 1010 00.1 .... vm=%vm_sp VMOV_64_dp ---- 1100 010 op:1 rt2:4 rt:4 1011 00.1 .... vm=%vm_dp -# Note that the half-precision variants of VLDR and VSTR are -# not part of this decodetree at all because they have bits [9:8] == 0b01 +VLDR_VSTR_hp ---- 1101 u:1 .0 l:1 rn:4 .... 1001 imm:8 vd=%vd_sp VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp @@ -103,33 +103,47 @@ VLDM_VSTM_dp ---- 1101 0.1 l:1 rn:4 .... 1011 imm:8 \ vd=%vd_dp p=1 u=0 w=1 # 3-register VFP data-processing; bits [23,21:20,6] identify the operation. +VMLA_hp ---- 1110 0.00 .... .... 1001 .0.0 .... @vfp_dnm_s VMLA_sp ---- 1110 0.00 .... .... 1010 .0.0 .... @vfp_dnm_s VMLA_dp ---- 1110 0.00 .... .... 1011 .0.0 .... @vfp_dnm_d +VMLS_hp ---- 1110 0.00 .... .... 1001 .1.0 .... @vfp_dnm_s VMLS_sp ---- 1110 0.00 .... .... 1010 .1.0 .... @vfp_dnm_s VMLS_dp ---- 1110 0.00 .... .... 1011 .1.0 .... @vfp_dnm_d +VNMLS_hp ---- 1110 0.01 .... .... 1001 .0.0 .... @vfp_dnm_s VNMLS_sp ---- 1110 0.01 .... .... 1010 .0.0 .... @vfp_dnm_s VNMLS_dp ---- 1110 0.01 .... .... 1011 .0.0 .... @vfp_dnm_d +VNMLA_hp ---- 1110 0.01 .... .... 1001 .1.0 .... @vfp_dnm_s VNMLA_sp ---- 1110 0.01 .... .... 1010 .1.0 .... @vfp_dnm_s VNMLA_dp ---- 1110 0.01 .... .... 1011 .1.0 .... @vfp_dnm_d +VMUL_hp ---- 1110 0.10 .... .... 1001 .0.0 .... @vfp_dnm_s VMUL_sp ---- 1110 0.10 .... .... 1010 .0.0 .... @vfp_dnm_s VMUL_dp ---- 1110 0.10 .... .... 1011 .0.0 .... @vfp_dnm_d +VNMUL_hp ---- 1110 0.10 .... .... 1001 .1.0 .... @vfp_dnm_s VNMUL_sp ---- 1110 0.10 .... .... 1010 .1.0 .... @vfp_dnm_s VNMUL_dp ---- 1110 0.10 .... .... 1011 .1.0 .... @vfp_dnm_d +VADD_hp ---- 1110 0.11 .... .... 1001 .0.0 .... @vfp_dnm_s VADD_sp ---- 1110 0.11 .... .... 1010 .0.0 .... @vfp_dnm_s VADD_dp ---- 1110 0.11 .... .... 1011 .0.0 .... @vfp_dnm_d +VSUB_hp ---- 1110 0.11 .... .... 1001 .1.0 .... @vfp_dnm_s VSUB_sp ---- 1110 0.11 .... .... 1010 .1.0 .... @vfp_dnm_s VSUB_dp ---- 1110 0.11 .... .... 1011 .1.0 .... @vfp_dnm_d +VDIV_hp ---- 1110 1.00 .... .... 1001 .0.0 .... @vfp_dnm_s VDIV_sp ---- 1110 1.00 .... .... 1010 .0.0 .... @vfp_dnm_s VDIV_dp ---- 1110 1.00 .... .... 1011 .0.0 .... @vfp_dnm_d +VFMA_hp ---- 1110 1.10 .... .... 1001 .0. 0 .... @vfp_dnm_s +VFMS_hp ---- 1110 1.10 .... .... 1001 .1. 0 .... @vfp_dnm_s +VFNMA_hp ---- 1110 1.01 .... .... 1001 .0. 0 .... @vfp_dnm_s +VFNMS_hp ---- 1110 1.01 .... .... 1001 .1. 0 .... @vfp_dnm_s + VFMA_sp ---- 1110 1.10 .... .... 1010 .0. 0 .... @vfp_dnm_s VFMS_sp ---- 1110 1.10 .... .... 1010 .1. 0 .... @vfp_dnm_s VFNMA_sp ---- 1110 1.01 .... .... 1010 .0. 0 .... @vfp_dnm_s @@ -140,6 +154,8 @@ VFMS_dp ---- 1110 1.10 .... .... 1011 .1.0 .... @vfp_dnm_d VFNMA_dp ---- 1110 1.01 .... .... 1011 .0.0 .... @vfp_dnm_d VFNMS_dp ---- 1110 1.01 .... .... 1011 .1.0 .... @vfp_dnm_d +VMOV_imm_hp ---- 1110 1.11 .... .... 1001 0000 .... \ + vd=%vd_sp imm=%vmov_imm VMOV_imm_sp ---- 1110 1.11 .... .... 1010 0000 .... \ vd=%vd_sp imm=%vmov_imm VMOV_imm_dp ---- 1110 1.11 .... .... 1011 0000 .... \ @@ -148,15 +164,20 @@ VMOV_imm_dp ---- 1110 1.11 .... .... 1011 0000 .... \ VMOV_reg_sp ---- 1110 1.11 0000 .... 1010 01.0 .... @vfp_dm_ss VMOV_reg_dp ---- 1110 1.11 0000 .... 1011 01.0 .... @vfp_dm_dd +VABS_hp ---- 1110 1.11 0000 .... 1001 11.0 .... @vfp_dm_ss VABS_sp ---- 1110 1.11 0000 .... 1010 11.0 .... @vfp_dm_ss VABS_dp ---- 1110 1.11 0000 .... 1011 11.0 .... @vfp_dm_dd +VNEG_hp ---- 1110 1.11 0001 .... 1001 01.0 .... @vfp_dm_ss VNEG_sp ---- 1110 1.11 0001 .... 1010 01.0 .... @vfp_dm_ss VNEG_dp ---- 1110 1.11 0001 .... 1011 01.0 .... @vfp_dm_dd +VSQRT_hp ---- 1110 1.11 0001 .... 1001 11.0 .... @vfp_dm_ss VSQRT_sp ---- 1110 1.11 0001 .... 1010 11.0 .... @vfp_dm_ss VSQRT_dp ---- 1110 1.11 0001 .... 1011 11.0 .... @vfp_dm_dd +VCMP_hp ---- 1110 1.11 010 z:1 .... 1001 e:1 1.0 .... \ + vd=%vd_sp vm=%vm_sp VCMP_sp ---- 1110 1.11 010 z:1 .... 1010 e:1 1.0 .... \ vd=%vd_sp vm=%vm_sp VCMP_dp ---- 1110 1.11 010 z:1 .... 1011 e:1 1.0 .... \ @@ -175,12 +196,15 @@ VCVT_f16_f32 ---- 1110 1.11 0011 .... 1010 t:1 1.0 .... \ VCVT_f16_f64 ---- 1110 1.11 0011 .... 1011 t:1 1.0 .... \ vd=%vd_sp vm=%vm_dp +VRINTR_hp ---- 1110 1.11 0110 .... 1001 01.0 .... @vfp_dm_ss VRINTR_sp ---- 1110 1.11 0110 .... 1010 01.0 .... @vfp_dm_ss VRINTR_dp ---- 1110 1.11 0110 .... 1011 01.0 .... @vfp_dm_dd +VRINTZ_hp ---- 1110 1.11 0110 .... 1001 11.0 .... @vfp_dm_ss VRINTZ_sp ---- 1110 1.11 0110 .... 1010 11.0 .... @vfp_dm_ss VRINTZ_dp ---- 1110 1.11 0110 .... 1011 11.0 .... @vfp_dm_dd +VRINTX_hp ---- 1110 1.11 0111 .... 1001 01.0 .... @vfp_dm_ss VRINTX_sp ---- 1110 1.11 0111 .... 1010 01.0 .... @vfp_dm_ss VRINTX_dp ---- 1110 1.11 0111 .... 1011 01.0 .... @vfp_dm_dd @@ -190,6 +214,8 @@ VCVT_sp ---- 1110 1.11 0111 .... 1010 11.0 .... @vfp_dm_ds VCVT_dp ---- 1110 1.11 0111 .... 1011 11.0 .... @vfp_dm_sd # VCVT from integer to floating point: Vm always single; Vd depends on size +VCVT_int_hp ---- 1110 1.11 1000 .... 1001 s:1 1.0 .... \ + vd=%vd_sp vm=%vm_sp VCVT_int_sp ---- 1110 1.11 1000 .... 1010 s:1 1.0 .... \ vd=%vd_sp vm=%vm_sp VCVT_int_dp ---- 1110 1.11 1000 .... 1011 s:1 1.0 .... \ @@ -203,15 +229,17 @@ VJCVT ---- 1110 1.11 1001 .... 1011 11.0 .... @vfp_dm_sd # We assemble bits 18 (op), 16 (u) and 7 (sx) into a single opc field # for the convenience of the trans_VCVT_fix functions. %vcvt_fix_op 18:1 16:1 7:1 +VCVT_fix_hp ---- 1110 1.11 1.1. .... 1001 .1.0 .... \ + vd=%vd_sp imm=%vm_sp opc=%vcvt_fix_op VCVT_fix_sp ---- 1110 1.11 1.1. .... 1010 .1.0 .... \ vd=%vd_sp imm=%vm_sp opc=%vcvt_fix_op VCVT_fix_dp ---- 1110 1.11 1.1. .... 1011 .1.0 .... \ vd=%vd_dp imm=%vm_sp opc=%vcvt_fix_op # VCVT float to integer (VCVT and VCVTR): Vd always single; Vd depends on size +VCVT_hp_int ---- 1110 1.11 110 s:1 .... 1001 rz:1 1.0 .... \ + vd=%vd_sp vm=%vm_sp VCVT_sp_int ---- 1110 1.11 110 s:1 .... 1010 rz:1 1.0 .... \ vd=%vd_sp vm=%vm_sp VCVT_dp_int ---- 1110 1.11 110 s:1 .... 1011 rz:1 1.0 .... \ vd=%vd_sp vm=%vm_dp - -VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000 diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c index 60dcd4bf14516a78df74a66fdac5f62681b205a8..01b9d8557f75b0bc2aa1dd65c6df1aaa9410c563 100644 --- a/target/arm/vfp_helper.c +++ b/target/arm/vfp_helper.c @@ -93,6 +93,8 @@ static uint32_t vfp_get_fpscr_from_host(CPUARMState *env) /* FZ16 does not generate an input denormal exception. */ i |= (get_float_exception_flags(&env->vfp.fp_status_f16) & ~float_flag_input_denormal); + i |= (get_float_exception_flags(&env->vfp.standard_fp_status_f16) + & ~float_flag_input_denormal); return vfp_exceptbits_from_host(i); } @@ -124,7 +126,9 @@ static void vfp_set_fpscr_to_host(CPUARMState *env, uint32_t val) if (changed & FPCR_FZ16) { bool ftz_enabled = val & FPCR_FZ16; set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_f16); + set_flush_to_zero(ftz_enabled, &env->vfp.standard_fp_status_f16); set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_f16); + set_flush_inputs_to_zero(ftz_enabled, &env->vfp.standard_fp_status_f16); } if (changed & FPCR_FZ) { bool ftz_enabled = val & FPCR_FZ; @@ -146,6 +150,7 @@ static void vfp_set_fpscr_to_host(CPUARMState *env, uint32_t val) set_float_exception_flags(i, &env->vfp.fp_status); set_float_exception_flags(0, &env->vfp.fp_status_f16); set_float_exception_flags(0, &env->vfp.standard_fp_status); + set_float_exception_flags(0, &env->vfp.standard_fp_status_f16); } #else @@ -169,6 +174,12 @@ uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env) | (env->vfp.vec_len << 16) | (env->vfp.vec_stride << 20); + /* + * M-profile LTPSIZE overlaps A-profile Stride; whichever of the + * two is not applicable to this CPU will always be zero. + */ + fpscr |= env->v7m.ltpsize << 16; + fpscr |= vfp_get_fpscr_from_host(env); i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3]; @@ -189,36 +200,45 @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val) val &= ~FPCR_FZ16; } - if (arm_feature(env, ARM_FEATURE_M)) { + vfp_set_fpscr_to_host(env, val); + + if (!arm_feature(env, ARM_FEATURE_M)) { /* - * M profile FPSCR is RES0 for the QC, STRIDE, FZ16, LEN bits - * and also for the trapped-exception-handling bits IxE. + * Short-vector length and stride; on M-profile these bits + * are used for different purposes. + * We can't make this conditional be "if MVFR0.FPShVec != 0", + * because in v7A no-short-vector-support cores still had to + * allow Stride/Len to be written with the only effect that + * some insns are required to UNDEF if the guest sets them. + * + * TODO: if M-profile MVE implemented, set LTPSIZE. */ - val &= 0xf7c0009f; + env->vfp.vec_len = extract32(val, 16, 3); + env->vfp.vec_stride = extract32(val, 20, 2); } - vfp_set_fpscr_to_host(env, val); + if (arm_feature(env, ARM_FEATURE_NEON)) { + /* + * The bit we set within fpscr_q is arbitrary; the register as a + * whole being zero/non-zero is what counts. + * TODO: M-profile MVE also has a QC bit. + */ + env->vfp.qc[0] = val & FPCR_QC; + env->vfp.qc[1] = 0; + env->vfp.qc[2] = 0; + env->vfp.qc[3] = 0; + } /* * We don't implement trapped exception handling, so the * trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!) * - * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC - * (which are stored in fp_status), and the other RES0 bits - * in between, then we clear all of the low 16 bits. + * The exception flags IOC|DZC|OFC|UFC|IXC|IDC are stored in + * fp_status; QC, Len and Stride are stored separately earlier. + * Clear out all of those and the RES0 bits: only NZCV, AHP, DN, + * FZ, RMode and FZ16 are kept in vfp.xregs[FPSCR]. */ env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000; - env->vfp.vec_len = (val >> 16) & 7; - env->vfp.vec_stride = (val >> 20) & 3; - - /* - * The bit we set within fpscr_q is arbitrary; the register as a - * whole being zero/non-zero is what counts. - */ - env->vfp.qc[0] = val & FPCR_QC; - env->vfp.qc[1] = 0; - env->vfp.qc[2] = 0; - env->vfp.qc[3] = 0; } void vfp_set_fpscr(CPUARMState *env, uint32_t val) @@ -231,6 +251,11 @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val) #define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p)) #define VFP_BINOP(name) \ +dh_ctype_f16 VFP_HELPER(name, h)(dh_ctype_f16 a, dh_ctype_f16 b, void *fpstp) \ +{ \ + float_status *fpst = fpstp; \ + return float16_ ## name(a, b, fpst); \ +} \ float32 VFP_HELPER(name, s)(float32 a, float32 b, void *fpstp) \ { \ float_status *fpst = fpstp; \ @@ -251,6 +276,11 @@ VFP_BINOP(minnum) VFP_BINOP(maxnum) #undef VFP_BINOP +dh_ctype_f16 VFP_HELPER(neg, h)(dh_ctype_f16 a) +{ + return float16_chs(a); +} + float32 VFP_HELPER(neg, s)(float32 a) { return float32_chs(a); @@ -261,6 +291,11 @@ float64 VFP_HELPER(neg, d)(float64 a) return float64_chs(a); } +dh_ctype_f16 VFP_HELPER(abs, h)(dh_ctype_f16 a) +{ + return float16_abs(a); +} + float32 VFP_HELPER(abs, s)(float32 a) { return float32_abs(a); @@ -271,6 +306,11 @@ float64 VFP_HELPER(abs, d)(float64 a) return float64_abs(a); } +dh_ctype_f16 VFP_HELPER(sqrt, h)(dh_ctype_f16 a, CPUARMState *env) +{ + return float16_sqrt(a, &env->vfp.fp_status_f16); +} + float32 VFP_HELPER(sqrt, s)(float32 a, CPUARMState *env) { return float32_sqrt(a, &env->vfp.fp_status); @@ -305,19 +345,20 @@ static void softfloat_to_vfp_compare(CPUARMState *env, FloatRelation cmp) } /* XXX: check quiet/signaling case */ -#define DO_VFP_cmp(p, type) \ -void VFP_HELPER(cmp, p)(type a, type b, CPUARMState *env) \ +#define DO_VFP_cmp(P, FLOATTYPE, ARGTYPE, FPST) \ +void VFP_HELPER(cmp, P)(ARGTYPE a, ARGTYPE b, CPUARMState *env) \ { \ softfloat_to_vfp_compare(env, \ - type ## _compare_quiet(a, b, &env->vfp.fp_status)); \ + FLOATTYPE ## _compare_quiet(a, b, &env->vfp.FPST)); \ } \ -void VFP_HELPER(cmpe, p)(type a, type b, CPUARMState *env) \ +void VFP_HELPER(cmpe, P)(ARGTYPE a, ARGTYPE b, CPUARMState *env) \ { \ softfloat_to_vfp_compare(env, \ - type ## _compare(a, b, &env->vfp.fp_status)); \ + FLOATTYPE ## _compare(a, b, &env->vfp.FPST)); \ } -DO_VFP_cmp(s, float32) -DO_VFP_cmp(d, float64) +DO_VFP_cmp(h, float16, dh_ctype_f16, fp_status_f16) +DO_VFP_cmp(s, float32, float32, fp_status) +DO_VFP_cmp(d, float64, float64, fp_status) #undef DO_VFP_cmp /* Integer to float and float to integer conversions */ @@ -367,14 +408,34 @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env) return float64_to_float32(x, &env->vfp.fp_status); } -/* VFP3 fixed point conversion. */ -#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \ -float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \ +/* + * VFP3 fixed point conversion. The AArch32 versions of fix-to-float + * must always round-to-nearest; the AArch64 ones honour the FPSCR + * rounding mode. (For AArch32 Neon the standard-FPSCR is set to + * round-to-nearest so either helper will work.) AArch32 float-to-fix + * must round-to-zero. + */ +#define VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \ +ftype HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \ void *fpstp) \ { return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); } -#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, ROUND, suff) \ -uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \ +#define VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \ + ftype HELPER(vfp_##name##to##p##_round_to_nearest)(uint##isz##_t x, \ + uint32_t shift, \ + void *fpstp) \ + { \ + ftype ret; \ + float_status *fpst = fpstp; \ + FloatRoundMode oldmode = fpst->float_rounding_mode; \ + fpst->float_rounding_mode = float_round_nearest_even; \ + ret = itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); \ + fpst->float_rounding_mode = oldmode; \ + return ret; \ + } + +#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, ROUND, suff) \ +uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \ void *fpst) \ { \ if (unlikely(float##fsz##_is_any_nan(x))) { \ @@ -384,116 +445,43 @@ uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \ return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \ } -#define VFP_CONV_FIX(name, p, fsz, isz, itype) \ -VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \ -VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \ +#define VFP_CONV_FIX(name, p, fsz, ftype, isz, itype) \ +VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \ +VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \ +VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \ float_round_to_zero, _round_to_zero) \ -VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \ +VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \ get_float_rounding_mode(fpst), ) -#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype) \ -VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \ -VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \ +#define VFP_CONV_FIX_A64(name, p, fsz, ftype, isz, itype) \ +VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \ +VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \ get_float_rounding_mode(fpst), ) -VFP_CONV_FIX(sh, d, 64, 64, int16) -VFP_CONV_FIX(sl, d, 64, 64, int32) -VFP_CONV_FIX_A64(sq, d, 64, 64, int64) -VFP_CONV_FIX(uh, d, 64, 64, uint16) -VFP_CONV_FIX(ul, d, 64, 64, uint32) -VFP_CONV_FIX_A64(uq, d, 64, 64, uint64) -VFP_CONV_FIX(sh, s, 32, 32, int16) -VFP_CONV_FIX(sl, s, 32, 32, int32) -VFP_CONV_FIX_A64(sq, s, 32, 64, int64) -VFP_CONV_FIX(uh, s, 32, 32, uint16) -VFP_CONV_FIX(ul, s, 32, 32, uint32) -VFP_CONV_FIX_A64(uq, s, 32, 64, uint64) +VFP_CONV_FIX(sh, d, 64, float64, 64, int16) +VFP_CONV_FIX(sl, d, 64, float64, 64, int32) +VFP_CONV_FIX_A64(sq, d, 64, float64, 64, int64) +VFP_CONV_FIX(uh, d, 64, float64, 64, uint16) +VFP_CONV_FIX(ul, d, 64, float64, 64, uint32) +VFP_CONV_FIX_A64(uq, d, 64, float64, 64, uint64) +VFP_CONV_FIX(sh, s, 32, float32, 32, int16) +VFP_CONV_FIX(sl, s, 32, float32, 32, int32) +VFP_CONV_FIX_A64(sq, s, 32, float32, 64, int64) +VFP_CONV_FIX(uh, s, 32, float32, 32, uint16) +VFP_CONV_FIX(ul, s, 32, float32, 32, uint32) +VFP_CONV_FIX_A64(uq, s, 32, float32, 64, uint64) +VFP_CONV_FIX(sh, h, 16, dh_ctype_f16, 32, int16) +VFP_CONV_FIX(sl, h, 16, dh_ctype_f16, 32, int32) +VFP_CONV_FIX_A64(sq, h, 16, dh_ctype_f16, 64, int64) +VFP_CONV_FIX(uh, h, 16, dh_ctype_f16, 32, uint16) +VFP_CONV_FIX(ul, h, 16, dh_ctype_f16, 32, uint32) +VFP_CONV_FIX_A64(uq, h, 16, dh_ctype_f16, 64, uint64) #undef VFP_CONV_FIX #undef VFP_CONV_FIX_FLOAT #undef VFP_CONV_FLOAT_FIX_ROUND #undef VFP_CONV_FIX_A64 -uint32_t HELPER(vfp_sltoh)(uint32_t x, uint32_t shift, void *fpst) -{ - return int32_to_float16_scalbn(x, -shift, fpst); -} - -uint32_t HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, void *fpst) -{ - return uint32_to_float16_scalbn(x, -shift, fpst); -} - -uint32_t HELPER(vfp_sqtoh)(uint64_t x, uint32_t shift, void *fpst) -{ - return int64_to_float16_scalbn(x, -shift, fpst); -} - -uint32_t HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst) -{ - return uint64_to_float16_scalbn(x, -shift, fpst); -} - -uint32_t HELPER(vfp_toshh)(uint32_t x, uint32_t shift, void *fpst) -{ - if (unlikely(float16_is_any_nan(x))) { - float_raise(float_flag_invalid, fpst); - return 0; - } - return float16_to_int16_scalbn(x, get_float_rounding_mode(fpst), - shift, fpst); -} - -uint32_t HELPER(vfp_touhh)(uint32_t x, uint32_t shift, void *fpst) -{ - if (unlikely(float16_is_any_nan(x))) { - float_raise(float_flag_invalid, fpst); - return 0; - } - return float16_to_uint16_scalbn(x, get_float_rounding_mode(fpst), - shift, fpst); -} - -uint32_t HELPER(vfp_toslh)(uint32_t x, uint32_t shift, void *fpst) -{ - if (unlikely(float16_is_any_nan(x))) { - float_raise(float_flag_invalid, fpst); - return 0; - } - return float16_to_int32_scalbn(x, get_float_rounding_mode(fpst), - shift, fpst); -} - -uint32_t HELPER(vfp_toulh)(uint32_t x, uint32_t shift, void *fpst) -{ - if (unlikely(float16_is_any_nan(x))) { - float_raise(float_flag_invalid, fpst); - return 0; - } - return float16_to_uint32_scalbn(x, get_float_rounding_mode(fpst), - shift, fpst); -} - -uint64_t HELPER(vfp_tosqh)(uint32_t x, uint32_t shift, void *fpst) -{ - if (unlikely(float16_is_any_nan(x))) { - float_raise(float_flag_invalid, fpst); - return 0; - } - return float16_to_int64_scalbn(x, get_float_rounding_mode(fpst), - shift, fpst); -} - -uint64_t HELPER(vfp_touqh)(uint32_t x, uint32_t shift, void *fpst) -{ - if (unlikely(float16_is_any_nan(x))) { - float_raise(float_flag_invalid, fpst); - return 0; - } - return float16_to_uint64_scalbn(x, get_float_rounding_mode(fpst), - shift, fpst); -} - /* Set the current fp rounding mode and return the old one. * The argument is a softfloat float_round_ value. */ @@ -507,23 +495,6 @@ uint32_t HELPER(set_rmode)(uint32_t rmode, void *fpstp) return prev_rmode; } -/* Set the current fp rounding mode in the standard fp status and return - * the old one. This is for NEON instructions that need to change the - * rounding mode but wish to use the standard FPSCR values for everything - * else. Always set the rounding mode back to the correct value after - * modifying it. - * The argument is a softfloat float_round_ value. - */ -uint32_t HELPER(set_neon_rmode)(uint32_t rmode, CPUARMState *env) -{ - float_status *fp_status = &env->vfp.standard_fp_status; - - uint32_t prev_rmode = get_float_rounding_mode(fp_status); - set_float_rounding_mode(rmode, fp_status); - - return prev_rmode; -} - /* Half precision conversions. */ float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, void *fpstp, uint32_t ahp_mode) { @@ -577,38 +548,6 @@ uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode) return r; } -#define float32_two make_float32(0x40000000) -#define float32_three make_float32(0x40400000) -#define float32_one_point_five make_float32(0x3fc00000) - -float32 HELPER(recps_f32)(CPUARMState *env, float32 a, float32 b) -{ - float_status *s = &env->vfp.standard_fp_status; - if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) || - (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) { - if (!(float32_is_zero(a) || float32_is_zero(b))) { - float_raise(float_flag_input_denormal, s); - } - return float32_two; - } - return float32_sub(float32_two, float32_mul(a, b, s), s); -} - -float32 HELPER(rsqrts_f32)(CPUARMState *env, float32 a, float32 b) -{ - float_status *s = &env->vfp.standard_fp_status; - float32 product; - if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) || - (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) { - if (!(float32_is_zero(a) || float32_is_zero(b))) { - float_raise(float_flag_input_denormal, s); - } - return float32_one_point_five; - } - product = float32_mul(a, b, s); - return float32_div(float32_sub(float32_three, product, s), float32_two, s); -} - /* NEON helpers. */ /* Constants 256 and 512 are used in some helpers; we avoid relying on @@ -1051,6 +990,13 @@ uint32_t HELPER(rsqrte_u32)(uint32_t a) } /* VFPv4 fused multiply-accumulate */ +dh_ctype_f16 VFP_HELPER(muladd, h)(dh_ctype_f16 a, dh_ctype_f16 b, + dh_ctype_f16 c, void *fpstp) +{ + float_status *fpst = fpstp; + return float16_muladd(a, b, c, 0, fpst); +} + float32 VFP_HELPER(muladd, s)(float32 a, float32 b, float32 c, void *fpstp) { float_status *fpst = fpstp; @@ -1064,6 +1010,11 @@ float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp) } /* ARMv8 round to integral */ +dh_ctype_f16 HELPER(rinth_exact)(dh_ctype_f16 x, void *fp_status) +{ + return float16_round_to_int(x, fp_status); +} + float32 HELPER(rints_exact)(float32 x, void *fp_status) { return float32_round_to_int(x, fp_status); @@ -1074,6 +1025,22 @@ float64 HELPER(rintd_exact)(float64 x, void *fp_status) return float64_round_to_int(x, fp_status); } +dh_ctype_f16 HELPER(rinth)(dh_ctype_f16 x, void *fp_status) +{ + int old_flags = get_float_exception_flags(fp_status), new_flags; + float16 ret; + + ret = float16_round_to_int(x, fp_status); + + /* Suppress any inexact exceptions the conversion produced */ + if (!(old_flags & float_flag_inexact)) { + new_flags = get_float_exception_flags(fp_status); + set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status); + } + + return ret; +} + float32 HELPER(rints)(float32 x, void *fp_status) { int old_flags = get_float_exception_flags(fp_status), new_flags; diff --git a/target/avr/cpu-param.h b/target/avr/cpu-param.h new file mode 100644 index 0000000000000000000000000000000000000000..7ef4e7c6793caec76dd370800e06843f08b12644 --- /dev/null +++ b/target/avr/cpu-param.h @@ -0,0 +1,36 @@ +/* + * QEMU AVR CPU + * + * Copyright (c) 2016-2020 Michael Rolnik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * + */ + +#ifndef AVR_CPU_PARAM_H +#define AVR_CPU_PARAM_H + +#define TARGET_LONG_BITS 32 +/* + * TARGET_PAGE_BITS cannot be more than 8 bits because + * 1. all IO registers occupy [0x0000 .. 0x00ff] address range, and they + * should be implemented as a device and not memory + * 2. SRAM starts at the address 0x0100 + */ +#define TARGET_PAGE_BITS 8 +#define TARGET_PHYS_ADDR_SPACE_BITS 24 +#define TARGET_VIRT_ADDR_SPACE_BITS 24 +#define NB_MMU_MODES 2 + +#endif diff --git a/target/avr/cpu-qom.h b/target/avr/cpu-qom.h new file mode 100644 index 0000000000000000000000000000000000000000..9fa6989c188297d0bdd1f3d1294137eb1e44c380 --- /dev/null +++ b/target/avr/cpu-qom.h @@ -0,0 +1,49 @@ +/* + * QEMU AVR CPU + * + * Copyright (c) 2016-2020 Michael Rolnik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * + */ + +#ifndef QEMU_AVR_QOM_H +#define QEMU_AVR_QOM_H + +#include "hw/core/cpu.h" +#include "qom/object.h" + +#define TYPE_AVR_CPU "avr-cpu" + +OBJECT_DECLARE_TYPE(AVRCPU, AVRCPUClass, + AVR_CPU) + +/** + * AVRCPUClass: + * @parent_realize: The parent class' realize handler. + * @parent_reset: The parent class' reset handler. + * @vr: Version Register value. + * + * A AVR CPU model. + */ +struct AVRCPUClass { + /*< private >*/ + CPUClass parent_class; + /*< public >*/ + DeviceRealize parent_realize; + DeviceReset parent_reset; +}; + + +#endif /* !defined (QEMU_AVR_CPU_QOM_H) */ diff --git a/target/avr/cpu.c b/target/avr/cpu.c new file mode 100644 index 0000000000000000000000000000000000000000..5d9c4ad5bff8a6cf4e46237246c30cda35b7fd2d --- /dev/null +++ b/target/avr/cpu.c @@ -0,0 +1,366 @@ +/* + * QEMU AVR CPU + * + * Copyright (c) 2019-2020 Michael Rolnik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/qemu-print.h" +#include "exec/exec-all.h" +#include "cpu.h" +#include "disas/dis-asm.h" + +static void avr_cpu_set_pc(CPUState *cs, vaddr value) +{ + AVRCPU *cpu = AVR_CPU(cs); + + cpu->env.pc_w = value / 2; /* internally PC points to words */ +} + +static bool avr_cpu_has_work(CPUState *cs) +{ + AVRCPU *cpu = AVR_CPU(cs); + CPUAVRState *env = &cpu->env; + + return (cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_RESET)) + && cpu_interrupts_enabled(env); +} + +static void avr_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) +{ + AVRCPU *cpu = AVR_CPU(cs); + CPUAVRState *env = &cpu->env; + + env->pc_w = tb->pc / 2; /* internally PC points to words */ +} + +static void avr_cpu_reset(DeviceState *ds) +{ + CPUState *cs = CPU(ds); + AVRCPU *cpu = AVR_CPU(cs); + AVRCPUClass *mcc = AVR_CPU_GET_CLASS(cpu); + CPUAVRState *env = &cpu->env; + + mcc->parent_reset(ds); + + env->pc_w = 0; + env->sregI = 1; + env->sregC = 0; + env->sregZ = 0; + env->sregN = 0; + env->sregV = 0; + env->sregS = 0; + env->sregH = 0; + env->sregT = 0; + + env->rampD = 0; + env->rampX = 0; + env->rampY = 0; + env->rampZ = 0; + env->eind = 0; + env->sp = 0; + + env->skip = 0; + + memset(env->r, 0, sizeof(env->r)); +} + +static void avr_cpu_disas_set_info(CPUState *cpu, disassemble_info *info) +{ + info->mach = bfd_arch_avr; + info->print_insn = avr_print_insn; +} + +static void avr_cpu_realizefn(DeviceState *dev, Error **errp) +{ + CPUState *cs = CPU(dev); + AVRCPUClass *mcc = AVR_CPU_GET_CLASS(dev); + Error *local_err = NULL; + + cpu_exec_realizefn(cs, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; + } + qemu_init_vcpu(cs); + cpu_reset(cs); + + mcc->parent_realize(dev, errp); +} + +static void avr_cpu_set_int(void *opaque, int irq, int level) +{ + AVRCPU *cpu = opaque; + CPUAVRState *env = &cpu->env; + CPUState *cs = CPU(cpu); + uint64_t mask = (1ull << irq); + + if (level) { + env->intsrc |= mask; + cpu_interrupt(cs, CPU_INTERRUPT_HARD); + } else { + env->intsrc &= ~mask; + if (env->intsrc == 0) { + cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); + } + } +} + +static void avr_cpu_initfn(Object *obj) +{ + AVRCPU *cpu = AVR_CPU(obj); + + cpu_set_cpustate_pointers(cpu); + + /* Set the number of interrupts supported by the CPU. */ + qdev_init_gpio_in(DEVICE(cpu), avr_cpu_set_int, + sizeof(cpu->env.intsrc) * 8); +} + +static ObjectClass *avr_cpu_class_by_name(const char *cpu_model) +{ + ObjectClass *oc; + + oc = object_class_by_name(cpu_model); + if (object_class_dynamic_cast(oc, TYPE_AVR_CPU) == NULL || + object_class_is_abstract(oc)) { + oc = NULL; + } + return oc; +} + +static void avr_cpu_dump_state(CPUState *cs, FILE *f, int flags) +{ + AVRCPU *cpu = AVR_CPU(cs); + CPUAVRState *env = &cpu->env; + int i; + + qemu_fprintf(f, "\n"); + qemu_fprintf(f, "PC: %06x\n", env->pc_w * 2); /* PC points to words */ + qemu_fprintf(f, "SP: %04x\n", env->sp); + qemu_fprintf(f, "rampD: %02x\n", env->rampD >> 16); + qemu_fprintf(f, "rampX: %02x\n", env->rampX >> 16); + qemu_fprintf(f, "rampY: %02x\n", env->rampY >> 16); + qemu_fprintf(f, "rampZ: %02x\n", env->rampZ >> 16); + qemu_fprintf(f, "EIND: %02x\n", env->eind >> 16); + qemu_fprintf(f, "X: %02x%02x\n", env->r[27], env->r[26]); + qemu_fprintf(f, "Y: %02x%02x\n", env->r[29], env->r[28]); + qemu_fprintf(f, "Z: %02x%02x\n", env->r[31], env->r[30]); + qemu_fprintf(f, "SREG: [ %c %c %c %c %c %c %c %c ]\n", + env->sregI ? 'I' : '-', + env->sregT ? 'T' : '-', + env->sregH ? 'H' : '-', + env->sregS ? 'S' : '-', + env->sregV ? 'V' : '-', + env->sregN ? '-' : 'N', /* Zf has negative logic */ + env->sregZ ? 'Z' : '-', + env->sregC ? 'I' : '-'); + qemu_fprintf(f, "SKIP: %02x\n", env->skip); + + qemu_fprintf(f, "\n"); + for (i = 0; i < ARRAY_SIZE(env->r); i++) { + qemu_fprintf(f, "R[%02d]: %02x ", i, env->r[i]); + + if ((i % 8) == 7) { + qemu_fprintf(f, "\n"); + } + } + qemu_fprintf(f, "\n"); +} + +static void avr_cpu_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + CPUClass *cc = CPU_CLASS(oc); + AVRCPUClass *mcc = AVR_CPU_CLASS(oc); + + mcc->parent_realize = dc->realize; + dc->realize = avr_cpu_realizefn; + + device_class_set_parent_reset(dc, avr_cpu_reset, &mcc->parent_reset); + + cc->class_by_name = avr_cpu_class_by_name; + + cc->has_work = avr_cpu_has_work; + cc->do_interrupt = avr_cpu_do_interrupt; + cc->cpu_exec_interrupt = avr_cpu_exec_interrupt; + cc->dump_state = avr_cpu_dump_state; + cc->set_pc = avr_cpu_set_pc; + cc->memory_rw_debug = avr_cpu_memory_rw_debug; + cc->get_phys_page_debug = avr_cpu_get_phys_page_debug; + cc->tlb_fill = avr_cpu_tlb_fill; + cc->vmsd = &vms_avr_cpu; + cc->disas_set_info = avr_cpu_disas_set_info; + cc->tcg_initialize = avr_cpu_tcg_init; + cc->synchronize_from_tb = avr_cpu_synchronize_from_tb; + cc->gdb_read_register = avr_cpu_gdb_read_register; + cc->gdb_write_register = avr_cpu_gdb_write_register; + cc->gdb_num_core_regs = 35; + cc->gdb_core_xml_file = "avr-cpu.xml"; +} + +/* + * Setting features of AVR core type avr5 + * -------------------------------------- + * + * This type of AVR core is present in the following AVR MCUs: + * + * ata5702m322, ata5782, ata5790, ata5790n, ata5791, ata5795, ata5831, ata6613c, + * ata6614q, ata8210, ata8510, atmega16, atmega16a, atmega161, atmega162, + * atmega163, atmega164a, atmega164p, atmega164pa, atmega165, atmega165a, + * atmega165p, atmega165pa, atmega168, atmega168a, atmega168p, atmega168pa, + * atmega168pb, atmega169, atmega169a, atmega169p, atmega169pa, atmega16hvb, + * atmega16hvbrevb, atmega16m1, atmega16u4, atmega32a, atmega32, atmega323, + * atmega324a, atmega324p, atmega324pa, atmega325, atmega325a, atmega325p, + * atmega325pa, atmega3250, atmega3250a, atmega3250p, atmega3250pa, atmega328, + * atmega328p, atmega328pb, atmega329, atmega329a, atmega329p, atmega329pa, + * atmega3290, atmega3290a, atmega3290p, atmega3290pa, atmega32c1, atmega32m1, + * atmega32u4, atmega32u6, atmega406, atmega64, atmega64a, atmega640, atmega644, + * atmega644a, atmega644p, atmega644pa, atmega645, atmega645a, atmega645p, + * atmega6450, atmega6450a, atmega6450p, atmega649, atmega649a, atmega649p, + * atmega6490, atmega16hva, atmega16hva2, atmega32hvb, atmega6490a, atmega6490p, + * atmega64c1, atmega64m1, atmega64hve, atmega64hve2, atmega64rfr2, + * atmega644rfr2, atmega32hvbrevb, at90can32, at90can64, at90pwm161, at90pwm216, + * at90pwm316, at90scr100, at90usb646, at90usb647, at94k, m3000 + */ +static void avr_avr5_initfn(Object *obj) +{ + AVRCPU *cpu = AVR_CPU(obj); + CPUAVRState *env = &cpu->env; + + set_avr_feature(env, AVR_FEATURE_LPM); + set_avr_feature(env, AVR_FEATURE_IJMP_ICALL); + set_avr_feature(env, AVR_FEATURE_ADIW_SBIW); + set_avr_feature(env, AVR_FEATURE_SRAM); + set_avr_feature(env, AVR_FEATURE_BREAK); + + set_avr_feature(env, AVR_FEATURE_2_BYTE_PC); + set_avr_feature(env, AVR_FEATURE_2_BYTE_SP); + set_avr_feature(env, AVR_FEATURE_JMP_CALL); + set_avr_feature(env, AVR_FEATURE_LPMX); + set_avr_feature(env, AVR_FEATURE_MOVW); + set_avr_feature(env, AVR_FEATURE_MUL); +} + +/* + * Setting features of AVR core type avr51 + * -------------------------------------- + * + * This type of AVR core is present in the following AVR MCUs: + * + * atmega128, atmega128a, atmega1280, atmega1281, atmega1284, atmega1284p, + * atmega128rfa1, atmega128rfr2, atmega1284rfr2, at90can128, at90usb1286, + * at90usb1287 + */ +static void avr_avr51_initfn(Object *obj) +{ + AVRCPU *cpu = AVR_CPU(obj); + CPUAVRState *env = &cpu->env; + + set_avr_feature(env, AVR_FEATURE_LPM); + set_avr_feature(env, AVR_FEATURE_IJMP_ICALL); + set_avr_feature(env, AVR_FEATURE_ADIW_SBIW); + set_avr_feature(env, AVR_FEATURE_SRAM); + set_avr_feature(env, AVR_FEATURE_BREAK); + + set_avr_feature(env, AVR_FEATURE_2_BYTE_PC); + set_avr_feature(env, AVR_FEATURE_2_BYTE_SP); + set_avr_feature(env, AVR_FEATURE_RAMPZ); + set_avr_feature(env, AVR_FEATURE_ELPMX); + set_avr_feature(env, AVR_FEATURE_ELPM); + set_avr_feature(env, AVR_FEATURE_JMP_CALL); + set_avr_feature(env, AVR_FEATURE_LPMX); + set_avr_feature(env, AVR_FEATURE_MOVW); + set_avr_feature(env, AVR_FEATURE_MUL); +} + +/* + * Setting features of AVR core type avr6 + * -------------------------------------- + * + * This type of AVR core is present in the following AVR MCUs: + * + * atmega2560, atmega2561, atmega256rfr2, atmega2564rfr2 + */ +static void avr_avr6_initfn(Object *obj) +{ + AVRCPU *cpu = AVR_CPU(obj); + CPUAVRState *env = &cpu->env; + + set_avr_feature(env, AVR_FEATURE_LPM); + set_avr_feature(env, AVR_FEATURE_IJMP_ICALL); + set_avr_feature(env, AVR_FEATURE_ADIW_SBIW); + set_avr_feature(env, AVR_FEATURE_SRAM); + set_avr_feature(env, AVR_FEATURE_BREAK); + + set_avr_feature(env, AVR_FEATURE_3_BYTE_PC); + set_avr_feature(env, AVR_FEATURE_2_BYTE_SP); + set_avr_feature(env, AVR_FEATURE_RAMPZ); + set_avr_feature(env, AVR_FEATURE_EIJMP_EICALL); + set_avr_feature(env, AVR_FEATURE_ELPMX); + set_avr_feature(env, AVR_FEATURE_ELPM); + set_avr_feature(env, AVR_FEATURE_JMP_CALL); + set_avr_feature(env, AVR_FEATURE_LPMX); + set_avr_feature(env, AVR_FEATURE_MOVW); + set_avr_feature(env, AVR_FEATURE_MUL); +} + +typedef struct AVRCPUInfo { + const char *name; + void (*initfn)(Object *obj); +} AVRCPUInfo; + + +static void avr_cpu_list_entry(gpointer data, gpointer user_data) +{ + const char *typename = object_class_get_name(OBJECT_CLASS(data)); + + qemu_printf("%s\n", typename); +} + +void avr_cpu_list(void) +{ + GSList *list; + list = object_class_get_list_sorted(TYPE_AVR_CPU, false); + g_slist_foreach(list, avr_cpu_list_entry, NULL); + g_slist_free(list); +} + +#define DEFINE_AVR_CPU_TYPE(model, initfn) \ + { \ + .parent = TYPE_AVR_CPU, \ + .instance_init = initfn, \ + .name = AVR_CPU_TYPE_NAME(model), \ + } + +static const TypeInfo avr_cpu_type_info[] = { + { + .name = TYPE_AVR_CPU, + .parent = TYPE_CPU, + .instance_size = sizeof(AVRCPU), + .instance_init = avr_cpu_initfn, + .class_size = sizeof(AVRCPUClass), + .class_init = avr_cpu_class_init, + .abstract = true, + }, + DEFINE_AVR_CPU_TYPE("avr5", avr_avr5_initfn), + DEFINE_AVR_CPU_TYPE("avr51", avr_avr51_initfn), + DEFINE_AVR_CPU_TYPE("avr6", avr_avr6_initfn), +}; + +DEFINE_TYPES(avr_cpu_type_info) diff --git a/target/avr/cpu.h b/target/avr/cpu.h new file mode 100644 index 0000000000000000000000000000000000000000..d148e8c75a45e43664abb8f99ac01fb113508b9e --- /dev/null +++ b/target/avr/cpu.h @@ -0,0 +1,256 @@ +/* + * QEMU AVR CPU + * + * Copyright (c) 2016-2020 Michael Rolnik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * + */ + +#ifndef QEMU_AVR_CPU_H +#define QEMU_AVR_CPU_H + +#include "cpu-qom.h" +#include "exec/cpu-defs.h" + +#ifdef CONFIG_USER_ONLY +#error "AVR 8-bit does not support user mode" +#endif + +#define AVR_CPU_TYPE_SUFFIX "-" TYPE_AVR_CPU +#define AVR_CPU_TYPE_NAME(name) (name AVR_CPU_TYPE_SUFFIX) +#define CPU_RESOLVING_TYPE TYPE_AVR_CPU + +#define TCG_GUEST_DEFAULT_MO 0 + +/* + * AVR has two memory spaces, data & code. + * e.g. both have 0 address + * ST/LD instructions access data space + * LPM/SPM and instruction fetching access code memory space + */ +#define MMU_CODE_IDX 0 +#define MMU_DATA_IDX 1 + +#define EXCP_RESET 1 +#define EXCP_INT(n) (EXCP_RESET + (n) + 1) + +/* Number of CPU registers */ +#define NUMBER_OF_CPU_REGISTERS 32 +/* Number of IO registers accessible by ld/st/in/out */ +#define NUMBER_OF_IO_REGISTERS 64 + +/* + * Offsets of AVR memory regions in host memory space. + * + * This is needed because the AVR has separate code and data address + * spaces that both have start from zero but have to go somewhere in + * host memory. + * + * It's also useful to know where some things are, like the IO registers. + */ +/* Flash program memory */ +#define OFFSET_CODE 0x00000000 +/* CPU registers, IO registers, and SRAM */ +#define OFFSET_DATA 0x00800000 +/* CPU registers specifically, these are mapped at the start of data */ +#define OFFSET_CPU_REGISTERS OFFSET_DATA +/* + * IO registers, including status register, stack pointer, and memory + * mapped peripherals, mapped just after CPU registers + */ +#define OFFSET_IO_REGISTERS (OFFSET_DATA + NUMBER_OF_CPU_REGISTERS) + +typedef enum AVRFeature { + AVR_FEATURE_SRAM, + + AVR_FEATURE_1_BYTE_PC, + AVR_FEATURE_2_BYTE_PC, + AVR_FEATURE_3_BYTE_PC, + + AVR_FEATURE_1_BYTE_SP, + AVR_FEATURE_2_BYTE_SP, + + AVR_FEATURE_BREAK, + AVR_FEATURE_DES, + AVR_FEATURE_RMW, /* Read Modify Write - XCH LAC LAS LAT */ + + AVR_FEATURE_EIJMP_EICALL, + AVR_FEATURE_IJMP_ICALL, + AVR_FEATURE_JMP_CALL, + + AVR_FEATURE_ADIW_SBIW, + + AVR_FEATURE_SPM, + AVR_FEATURE_SPMX, + + AVR_FEATURE_ELPMX, + AVR_FEATURE_ELPM, + AVR_FEATURE_LPMX, + AVR_FEATURE_LPM, + + AVR_FEATURE_MOVW, + AVR_FEATURE_MUL, + AVR_FEATURE_RAMPD, + AVR_FEATURE_RAMPX, + AVR_FEATURE_RAMPY, + AVR_FEATURE_RAMPZ, +} AVRFeature; + +typedef struct CPUAVRState CPUAVRState; + +struct CPUAVRState { + uint32_t pc_w; /* 0x003fffff up to 22 bits */ + + uint32_t sregC; /* 0x00000001 1 bit */ + uint32_t sregZ; /* 0x00000001 1 bit */ + uint32_t sregN; /* 0x00000001 1 bit */ + uint32_t sregV; /* 0x00000001 1 bit */ + uint32_t sregS; /* 0x00000001 1 bit */ + uint32_t sregH; /* 0x00000001 1 bit */ + uint32_t sregT; /* 0x00000001 1 bit */ + uint32_t sregI; /* 0x00000001 1 bit */ + + uint32_t rampD; /* 0x00ff0000 8 bits */ + uint32_t rampX; /* 0x00ff0000 8 bits */ + uint32_t rampY; /* 0x00ff0000 8 bits */ + uint32_t rampZ; /* 0x00ff0000 8 bits */ + uint32_t eind; /* 0x00ff0000 8 bits */ + + uint32_t r[NUMBER_OF_CPU_REGISTERS]; /* 8 bits each */ + uint32_t sp; /* 16 bits */ + + uint32_t skip; /* if set skip instruction */ + + uint64_t intsrc; /* interrupt sources */ + bool fullacc; /* CPU/MEM if true MEM only otherwise */ + + uint64_t features; +}; + +/** + * AVRCPU: + * @env: #CPUAVRState + * + * A AVR CPU. + */ +typedef struct AVRCPU { + /*< private >*/ + CPUState parent_obj; + /*< public >*/ + + CPUNegativeOffsetState neg; + CPUAVRState env; +} AVRCPU; + +extern const struct VMStateDescription vms_avr_cpu; + +void avr_cpu_do_interrupt(CPUState *cpu); +bool avr_cpu_exec_interrupt(CPUState *cpu, int int_req); +hwaddr avr_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); +int avr_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); +int avr_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); +int avr_print_insn(bfd_vma addr, disassemble_info *info); + +static inline int avr_feature(CPUAVRState *env, AVRFeature feature) +{ + return (env->features & (1U << feature)) != 0; +} + +static inline void set_avr_feature(CPUAVRState *env, int feature) +{ + env->features |= (1U << feature); +} + +#define cpu_list avr_cpu_list +#define cpu_signal_handler cpu_avr_signal_handler +#define cpu_mmu_index avr_cpu_mmu_index + +static inline int avr_cpu_mmu_index(CPUAVRState *env, bool ifetch) +{ + return ifetch ? MMU_CODE_IDX : MMU_DATA_IDX; +} + +void avr_cpu_tcg_init(void); + +void avr_cpu_list(void); +int cpu_avr_exec(CPUState *cpu); +int cpu_avr_signal_handler(int host_signum, void *pinfo, void *puc); +int avr_cpu_memory_rw_debug(CPUState *cs, vaddr address, uint8_t *buf, + int len, bool is_write); + +enum { + TB_FLAGS_FULL_ACCESS = 1, + TB_FLAGS_SKIP = 2, +}; + +static inline void cpu_get_tb_cpu_state(CPUAVRState *env, target_ulong *pc, + target_ulong *cs_base, uint32_t *pflags) +{ + uint32_t flags = 0; + + *pc = env->pc_w * 2; + *cs_base = 0; + + if (env->fullacc) { + flags |= TB_FLAGS_FULL_ACCESS; + } + if (env->skip) { + flags |= TB_FLAGS_SKIP; + } + + *pflags = flags; +} + +static inline int cpu_interrupts_enabled(CPUAVRState *env) +{ + return env->sregI != 0; +} + +static inline uint8_t cpu_get_sreg(CPUAVRState *env) +{ + uint8_t sreg; + sreg = (env->sregC) << 0 + | (env->sregZ) << 1 + | (env->sregN) << 2 + | (env->sregV) << 3 + | (env->sregS) << 4 + | (env->sregH) << 5 + | (env->sregT) << 6 + | (env->sregI) << 7; + return sreg; +} + +static inline void cpu_set_sreg(CPUAVRState *env, uint8_t sreg) +{ + env->sregC = (sreg >> 0) & 0x01; + env->sregZ = (sreg >> 1) & 0x01; + env->sregN = (sreg >> 2) & 0x01; + env->sregV = (sreg >> 3) & 0x01; + env->sregS = (sreg >> 4) & 0x01; + env->sregH = (sreg >> 5) & 0x01; + env->sregT = (sreg >> 6) & 0x01; + env->sregI = (sreg >> 7) & 0x01; +} + +bool avr_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); + +typedef CPUAVRState CPUArchState; +typedef AVRCPU ArchCPU; + +#include "exec/cpu-all.h" + +#endif /* !defined (QEMU_AVR_CPU_H) */ diff --git a/target/avr/disas.c b/target/avr/disas.c new file mode 100644 index 0000000000000000000000000000000000000000..b7689e8d7cd9566bc148f8a4e25a348fdaec59fe --- /dev/null +++ b/target/avr/disas.c @@ -0,0 +1,245 @@ +/* + * AVR disassembler + * + * Copyright (c) 2019-2020 Richard Henderson + * Copyright (c) 2019-2020 Michael Rolnik + * + * 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 . + */ + +#include "qemu/osdep.h" +#include "cpu.h" + +typedef struct { + disassemble_info *info; + uint16_t next_word; + bool next_word_used; +} DisasContext; + +static int to_regs_16_31_by_one(DisasContext *ctx, int indx) +{ + return 16 + (indx % 16); +} + +static int to_regs_16_23_by_one(DisasContext *ctx, int indx) +{ + return 16 + (indx % 8); +} + +static int to_regs_24_30_by_two(DisasContext *ctx, int indx) +{ + return 24 + (indx % 4) * 2; +} + +static int to_regs_00_30_by_two(DisasContext *ctx, int indx) +{ + return (indx % 16) * 2; +} + +static uint16_t next_word(DisasContext *ctx) +{ + ctx->next_word_used = true; + return ctx->next_word; +} + +static int append_16(DisasContext *ctx, int x) +{ + return x << 16 | next_word(ctx); +} + +/* Include the auto-generated decoder. */ +static bool decode_insn(DisasContext *ctx, uint16_t insn); +#include "decode-insn.c.inc" + +#define output(mnemonic, format, ...) \ + (pctx->info->fprintf_func(pctx->info->stream, "%-9s " format, \ + mnemonic, ##__VA_ARGS__)) + +int avr_print_insn(bfd_vma addr, disassemble_info *info) +{ + DisasContext ctx; + DisasContext *pctx = &ctx; + bfd_byte buffer[4]; + uint16_t insn; + int status; + + ctx.info = info; + + status = info->read_memory_func(addr, buffer, 4, info); + if (status != 0) { + info->memory_error_func(status, addr, info); + return -1; + } + insn = bfd_getl16(buffer); + ctx.next_word = bfd_getl16(buffer + 2); + ctx.next_word_used = false; + + if (!decode_insn(&ctx, insn)) { + output(".db", "0x%02x, 0x%02x", buffer[0], buffer[1]); + } + + return ctx.next_word_used ? 4 : 2; +} + + +#define INSN(opcode, format, ...) \ +static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a) \ +{ \ + output(#opcode, format, ##__VA_ARGS__); \ + return true; \ +} + +#define INSN_MNEMONIC(opcode, mnemonic, format, ...) \ +static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a) \ +{ \ + output(mnemonic, format, ##__VA_ARGS__); \ + return true; \ +} + +/* + * C Z N V S H T I + * 0 1 2 3 4 5 6 7 + */ +static const char brbc[][5] = { + "BRCC", "BRNE", "BRPL", "BRVC", "BRGE", "BRHC", "BRTC", "BRID" +}; + +static const char brbs[][5] = { + "BRCS", "BREQ", "BRMI", "BRVS", "BRLT", "BRHS", "BRTS", "BRIE" +}; + +static const char bset[][4] = { + "SEC", "SEZ", "SEN", "SEZ", "SES", "SEH", "SET", "SEI" +}; + +static const char bclr[][4] = { + "CLC", "CLZ", "CLN", "CLZ", "CLS", "CLH", "CLT", "CLI" +}; + +/* + * Arithmetic Instructions + */ +INSN(ADD, "r%d, r%d", a->rd, a->rr) +INSN(ADC, "r%d, r%d", a->rd, a->rr) +INSN(ADIW, "r%d:r%d, %d", a->rd + 1, a->rd, a->imm) +INSN(SUB, "r%d, r%d", a->rd, a->rr) +INSN(SUBI, "r%d, %d", a->rd, a->imm) +INSN(SBC, "r%d, r%d", a->rd, a->rr) +INSN(SBCI, "r%d, %d", a->rd, a->imm) +INSN(SBIW, "r%d:r%d, %d", a->rd + 1, a->rd, a->imm) +INSN(AND, "r%d, r%d", a->rd, a->rr) +INSN(ANDI, "r%d, %d", a->rd, a->imm) +INSN(OR, "r%d, r%d", a->rd, a->rr) +INSN(ORI, "r%d, %d", a->rd, a->imm) +INSN(EOR, "r%d, r%d", a->rd, a->rr) +INSN(COM, "r%d", a->rd) +INSN(NEG, "r%d", a->rd) +INSN(INC, "r%d", a->rd) +INSN(DEC, "r%d", a->rd) +INSN(MUL, "r%d, r%d", a->rd, a->rr) +INSN(MULS, "r%d, r%d", a->rd, a->rr) +INSN(MULSU, "r%d, r%d", a->rd, a->rr) +INSN(FMUL, "r%d, r%d", a->rd, a->rr) +INSN(FMULS, "r%d, r%d", a->rd, a->rr) +INSN(FMULSU, "r%d, r%d", a->rd, a->rr) +INSN(DES, "%d", a->imm) + +/* + * Branch Instructions + */ +INSN(RJMP, ".%+d", a->imm * 2) +INSN(IJMP, "") +INSN(EIJMP, "") +INSN(JMP, "0x%x", a->imm * 2) +INSN(RCALL, ".%+d", a->imm * 2) +INSN(ICALL, "") +INSN(EICALL, "") +INSN(CALL, "0x%x", a->imm * 2) +INSN(RET, "") +INSN(RETI, "") +INSN(CPSE, "r%d, r%d", a->rd, a->rr) +INSN(CP, "r%d, r%d", a->rd, a->rr) +INSN(CPC, "r%d, r%d", a->rd, a->rr) +INSN(CPI, "r%d, %d", a->rd, a->imm) +INSN(SBRC, "r%d, %d", a->rr, a->bit) +INSN(SBRS, "r%d, %d", a->rr, a->bit) +INSN(SBIC, "$%d, %d", a->reg, a->bit) +INSN(SBIS, "$%d, %d", a->reg, a->bit) +INSN_MNEMONIC(BRBS, brbs[a->bit], ".%+d", a->imm * 2) +INSN_MNEMONIC(BRBC, brbc[a->bit], ".%+d", a->imm * 2) + +/* + * Data Transfer Instructions + */ +INSN(MOV, "r%d, r%d", a->rd, a->rr) +INSN(MOVW, "r%d:r%d, r%d:r%d", a->rd + 1, a->rd, a->rr + 1, a->rr) +INSN(LDI, "r%d, %d", a->rd, a->imm) +INSN(LDS, "r%d, %d", a->rd, a->imm) +INSN(LDX1, "r%d, X", a->rd) +INSN(LDX2, "r%d, X+", a->rd) +INSN(LDX3, "r%d, -X", a->rd) +INSN(LDY2, "r%d, Y+", a->rd) +INSN(LDY3, "r%d, -Y", a->rd) +INSN(LDZ2, "r%d, Z+", a->rd) +INSN(LDZ3, "r%d, -Z", a->rd) +INSN(LDDY, "r%d, Y+%d", a->rd, a->imm) +INSN(LDDZ, "r%d, Z+%d", a->rd, a->imm) +INSN(STS, "%d, r%d", a->imm, a->rd) +INSN(STX1, "X, r%d", a->rr) +INSN(STX2, "X+, r%d", a->rr) +INSN(STX3, "-X, r%d", a->rr) +INSN(STY2, "Y+, r%d", a->rd) +INSN(STY3, "-Y, r%d", a->rd) +INSN(STZ2, "Z+, r%d", a->rd) +INSN(STZ3, "-Z, r%d", a->rd) +INSN(STDY, "Y+%d, r%d", a->imm, a->rd) +INSN(STDZ, "Z+%d, r%d", a->imm, a->rd) +INSN(LPM1, "") +INSN(LPM2, "r%d, Z", a->rd) +INSN(LPMX, "r%d, Z+", a->rd) +INSN(ELPM1, "") +INSN(ELPM2, "r%d, Z", a->rd) +INSN(ELPMX, "r%d, Z+", a->rd) +INSN(SPM, "") +INSN(SPMX, "Z+") +INSN(IN, "r%d, $%d", a->rd, a->imm) +INSN(OUT, "$%d, r%d", a->imm, a->rd) +INSN(PUSH, "r%d", a->rd) +INSN(POP, "r%d", a->rd) +INSN(XCH, "Z, r%d", a->rd) +INSN(LAC, "Z, r%d", a->rd) +INSN(LAS, "Z, r%d", a->rd) +INSN(LAT, "Z, r%d", a->rd) + +/* + * Bit and Bit-test Instructions + */ +INSN(LSR, "r%d", a->rd) +INSN(ROR, "r%d", a->rd) +INSN(ASR, "r%d", a->rd) +INSN(SWAP, "r%d", a->rd) +INSN(SBI, "$%d, %d", a->reg, a->bit) +INSN(CBI, "%d, %d", a->reg, a->bit) +INSN(BST, "r%d, %d", a->rd, a->bit) +INSN(BLD, "r%d, %d", a->rd, a->bit) +INSN_MNEMONIC(BSET, bset[a->bit], "") +INSN_MNEMONIC(BCLR, bclr[a->bit], "") + +/* + * MCU Control Instructions + */ +INSN(BREAK, "") +INSN(NOP, "") +INSN(SLEEP, "") +INSN(WDR, "") diff --git a/target/avr/gdbstub.c b/target/avr/gdbstub.c new file mode 100644 index 0000000000000000000000000000000000000000..c28ed67efe1837bb549a869df36796ee428878cc --- /dev/null +++ b/target/avr/gdbstub.c @@ -0,0 +1,84 @@ +/* + * QEMU AVR gdbstub + * + * Copyright (c) 2016-2020 Michael Rolnik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * + */ + +#include "qemu/osdep.h" +#include "exec/gdbstub.h" + +int avr_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) +{ + AVRCPU *cpu = AVR_CPU(cs); + CPUAVRState *env = &cpu->env; + + /* R */ + if (n < 32) { + return gdb_get_reg8(mem_buf, env->r[n]); + } + + /* SREG */ + if (n == 32) { + uint8_t sreg = cpu_get_sreg(env); + + return gdb_get_reg8(mem_buf, sreg); + } + + /* SP */ + if (n == 33) { + return gdb_get_reg16(mem_buf, env->sp & 0x0000ffff); + } + + /* PC */ + if (n == 34) { + return gdb_get_reg32(mem_buf, env->pc_w * 2); + } + + return 0; +} + +int avr_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) +{ + AVRCPU *cpu = AVR_CPU(cs); + CPUAVRState *env = &cpu->env; + + /* R */ + if (n < 32) { + env->r[n] = *mem_buf; + return 1; + } + + /* SREG */ + if (n == 32) { + cpu_set_sreg(env, *mem_buf); + return 1; + } + + /* SP */ + if (n == 33) { + env->sp = lduw_p(mem_buf); + return 2; + } + + /* PC */ + if (n == 34) { + env->pc_w = ldl_p(mem_buf) / 2; + return 4; + } + + return 0; +} diff --git a/target/avr/helper.c b/target/avr/helper.c new file mode 100644 index 0000000000000000000000000000000000000000..d96d14372b42e11af64df1a928e849eab2ba47eb --- /dev/null +++ b/target/avr/helper.c @@ -0,0 +1,348 @@ +/* + * QEMU AVR CPU helpers + * + * Copyright (c) 2016-2020 Michael Rolnik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/exec-all.h" +#include "exec/address-spaces.h" +#include "exec/helper-proto.h" + +bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request) +{ + bool ret = false; + CPUClass *cc = CPU_GET_CLASS(cs); + AVRCPU *cpu = AVR_CPU(cs); + CPUAVRState *env = &cpu->env; + + if (interrupt_request & CPU_INTERRUPT_RESET) { + if (cpu_interrupts_enabled(env)) { + cs->exception_index = EXCP_RESET; + cc->do_interrupt(cs); + + cs->interrupt_request &= ~CPU_INTERRUPT_RESET; + + ret = true; + } + } + if (interrupt_request & CPU_INTERRUPT_HARD) { + if (cpu_interrupts_enabled(env) && env->intsrc != 0) { + int index = ctz32(env->intsrc); + cs->exception_index = EXCP_INT(index); + cc->do_interrupt(cs); + + env->intsrc &= env->intsrc - 1; /* clear the interrupt */ + cs->interrupt_request &= ~CPU_INTERRUPT_HARD; + + ret = true; + } + } + return ret; +} + +void avr_cpu_do_interrupt(CPUState *cs) +{ + AVRCPU *cpu = AVR_CPU(cs); + CPUAVRState *env = &cpu->env; + + uint32_t ret = env->pc_w; + int vector = 0; + int size = avr_feature(env, AVR_FEATURE_JMP_CALL) ? 2 : 1; + int base = 0; + + if (cs->exception_index == EXCP_RESET) { + vector = 0; + } else if (env->intsrc != 0) { + vector = ctz32(env->intsrc) + 1; + } + + if (avr_feature(env, AVR_FEATURE_3_BYTE_PC)) { + cpu_stb_data(env, env->sp--, (ret & 0x0000ff)); + cpu_stb_data(env, env->sp--, (ret & 0x00ff00) >> 8); + cpu_stb_data(env, env->sp--, (ret & 0xff0000) >> 16); + } else if (avr_feature(env, AVR_FEATURE_2_BYTE_PC)) { + cpu_stb_data(env, env->sp--, (ret & 0x0000ff)); + cpu_stb_data(env, env->sp--, (ret & 0x00ff00) >> 8); + } else { + cpu_stb_data(env, env->sp--, (ret & 0x0000ff)); + } + + env->pc_w = base + vector * size; + env->sregI = 0; /* clear Global Interrupt Flag */ + + cs->exception_index = -1; +} + +int avr_cpu_memory_rw_debug(CPUState *cs, vaddr addr, uint8_t *buf, + int len, bool is_write) +{ + return cpu_memory_rw_debug(cs, addr, buf, len, is_write); +} + +hwaddr avr_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) +{ + return addr; /* I assume 1:1 address correspondance */ +} + +bool avr_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) +{ + int prot = 0; + MemTxAttrs attrs = {}; + uint32_t paddr; + + address &= TARGET_PAGE_MASK; + + if (mmu_idx == MMU_CODE_IDX) { + /* access to code in flash */ + paddr = OFFSET_CODE + address; + prot = PAGE_READ | PAGE_EXEC; + if (paddr + TARGET_PAGE_SIZE > OFFSET_DATA) { + error_report("execution left flash memory"); + abort(); + } + } else if (address < NUMBER_OF_CPU_REGISTERS + NUMBER_OF_IO_REGISTERS) { + /* + * access to CPU registers, exit and rebuilt this TB to use full access + * incase it touches specially handled registers like SREG or SP + */ + AVRCPU *cpu = AVR_CPU(cs); + CPUAVRState *env = &cpu->env; + env->fullacc = 1; + cpu_loop_exit_restore(cs, retaddr); + } else { + /* access to memory. nothing special */ + paddr = OFFSET_DATA + address; + prot = PAGE_READ | PAGE_WRITE; + } + + tlb_set_page_with_attrs(cs, address, paddr, attrs, prot, + mmu_idx, TARGET_PAGE_SIZE); + + return true; +} + +/* + * helpers + */ + +void helper_sleep(CPUAVRState *env) +{ + CPUState *cs = env_cpu(env); + + cs->exception_index = EXCP_HLT; + cpu_loop_exit(cs); +} + +void helper_unsupported(CPUAVRState *env) +{ + CPUState *cs = env_cpu(env); + + /* + * I count not find what happens on the real platform, so + * it's EXCP_DEBUG for meanwhile + */ + cs->exception_index = EXCP_DEBUG; + if (qemu_loglevel_mask(LOG_UNIMP)) { + qemu_log("UNSUPPORTED\n"); + cpu_dump_state(cs, stderr, 0); + } + cpu_loop_exit(cs); +} + +void helper_debug(CPUAVRState *env) +{ + CPUState *cs = env_cpu(env); + + cs->exception_index = EXCP_DEBUG; + cpu_loop_exit(cs); +} + +void helper_break(CPUAVRState *env) +{ + CPUState *cs = env_cpu(env); + + cs->exception_index = EXCP_DEBUG; + cpu_loop_exit(cs); +} + +void helper_wdr(CPUAVRState *env) +{ + CPUState *cs = env_cpu(env); + + /* WD is not implemented yet, placeholder */ + cs->exception_index = EXCP_DEBUG; + cpu_loop_exit(cs); +} + +/* + * This function implements IN instruction + * + * It does the following + * a. if an IO register belongs to CPU, its value is read and returned + * b. otherwise io address is translated to mem address and physical memory + * is read. + * c. it caches the value for sake of SBI, SBIC, SBIS & CBI implementation + * + */ +target_ulong helper_inb(CPUAVRState *env, uint32_t port) +{ + target_ulong data = 0; + + switch (port) { + case 0x38: /* RAMPD */ + data = 0xff & (env->rampD >> 16); + break; + case 0x39: /* RAMPX */ + data = 0xff & (env->rampX >> 16); + break; + case 0x3a: /* RAMPY */ + data = 0xff & (env->rampY >> 16); + break; + case 0x3b: /* RAMPZ */ + data = 0xff & (env->rampZ >> 16); + break; + case 0x3c: /* EIND */ + data = 0xff & (env->eind >> 16); + break; + case 0x3d: /* SPL */ + data = env->sp & 0x00ff; + break; + case 0x3e: /* SPH */ + data = env->sp >> 8; + break; + case 0x3f: /* SREG */ + data = cpu_get_sreg(env); + break; + default: + /* not a special register, pass to normal memory access */ + data = address_space_ldub(&address_space_memory, + OFFSET_IO_REGISTERS + port, + MEMTXATTRS_UNSPECIFIED, NULL); + } + + return data; +} + +/* + * This function implements OUT instruction + * + * It does the following + * a. if an IO register belongs to CPU, its value is written into the register + * b. otherwise io address is translated to mem address and physical memory + * is written. + * c. it caches the value for sake of SBI, SBIC, SBIS & CBI implementation + * + */ +void helper_outb(CPUAVRState *env, uint32_t port, uint32_t data) +{ + data &= 0x000000ff; + + switch (port) { + case 0x38: /* RAMPD */ + if (avr_feature(env, AVR_FEATURE_RAMPD)) { + env->rampD = (data & 0xff) << 16; + } + break; + case 0x39: /* RAMPX */ + if (avr_feature(env, AVR_FEATURE_RAMPX)) { + env->rampX = (data & 0xff) << 16; + } + break; + case 0x3a: /* RAMPY */ + if (avr_feature(env, AVR_FEATURE_RAMPY)) { + env->rampY = (data & 0xff) << 16; + } + break; + case 0x3b: /* RAMPZ */ + if (avr_feature(env, AVR_FEATURE_RAMPZ)) { + env->rampZ = (data & 0xff) << 16; + } + break; + case 0x3c: /* EIDN */ + env->eind = (data & 0xff) << 16; + break; + case 0x3d: /* SPL */ + env->sp = (env->sp & 0xff00) | (data); + break; + case 0x3e: /* SPH */ + if (avr_feature(env, AVR_FEATURE_2_BYTE_SP)) { + env->sp = (env->sp & 0x00ff) | (data << 8); + } + break; + case 0x3f: /* SREG */ + cpu_set_sreg(env, data); + break; + default: + /* not a special register, pass to normal memory access */ + address_space_stb(&address_space_memory, OFFSET_IO_REGISTERS + port, + data, MEMTXATTRS_UNSPECIFIED, NULL); + } +} + +/* + * this function implements LD instruction when there is a posibility to read + * from a CPU register + */ +target_ulong helper_fullrd(CPUAVRState *env, uint32_t addr) +{ + uint8_t data; + + env->fullacc = false; + + if (addr < NUMBER_OF_CPU_REGISTERS) { + /* CPU registers */ + data = env->r[addr]; + } else if (addr < NUMBER_OF_CPU_REGISTERS + NUMBER_OF_IO_REGISTERS) { + /* IO registers */ + data = helper_inb(env, addr - NUMBER_OF_CPU_REGISTERS); + } else { + /* memory */ + data = address_space_ldub(&address_space_memory, OFFSET_DATA + addr, + MEMTXATTRS_UNSPECIFIED, NULL); + } + return data; +} + +/* + * this function implements ST instruction when there is a posibility to write + * into a CPU register + */ +void helper_fullwr(CPUAVRState *env, uint32_t data, uint32_t addr) +{ + env->fullacc = false; + + /* Following logic assumes this: */ + assert(OFFSET_CPU_REGISTERS == OFFSET_DATA); + assert(OFFSET_IO_REGISTERS == OFFSET_CPU_REGISTERS + + NUMBER_OF_CPU_REGISTERS); + + if (addr < NUMBER_OF_CPU_REGISTERS) { + /* CPU registers */ + env->r[addr] = data; + } else if (addr < NUMBER_OF_CPU_REGISTERS + NUMBER_OF_IO_REGISTERS) { + /* IO registers */ + helper_outb(env, addr - NUMBER_OF_CPU_REGISTERS, data); + } else { + /* memory */ + address_space_stb(&address_space_memory, OFFSET_DATA + addr, data, + MEMTXATTRS_UNSPECIFIED, NULL); + } +} diff --git a/target/avr/helper.h b/target/avr/helper.h new file mode 100644 index 0000000000000000000000000000000000000000..8e1ae7fda033e8f6a8b3c1c26608996d68584593 --- /dev/null +++ b/target/avr/helper.h @@ -0,0 +1,29 @@ +/* + * QEMU AVR CPU helpers + * + * Copyright (c) 2016-2020 Michael Rolnik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * + */ + +DEF_HELPER_1(wdr, void, env) +DEF_HELPER_1(debug, void, env) +DEF_HELPER_1(break, void, env) +DEF_HELPER_1(sleep, void, env) +DEF_HELPER_1(unsupported, void, env) +DEF_HELPER_3(outb, void, env, i32, i32) +DEF_HELPER_2(inb, tl, env, i32) +DEF_HELPER_3(fullwr, void, env, i32, i32) +DEF_HELPER_2(fullrd, tl, env, i32) diff --git a/target/avr/insn.decode b/target/avr/insn.decode new file mode 100644 index 0000000000000000000000000000000000000000..482c23ad0cff86edc92bfffa10ee464fe623dbe7 --- /dev/null +++ b/target/avr/insn.decode @@ -0,0 +1,187 @@ +# +# AVR instruction decode definitions. +# +# Copyright (c) 2019-2020 Michael Rolnik +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see . +# + +# +# regs_16_31_by_one = [16 .. 31] +# regs_16_23_by_one = [16 .. 23] +# regs_24_30_by_two = [24, 26, 28, 30] +# regs_00_30_by_two = [0, 2, 4, 6, 8, .. 30] + +%rd 4:5 +%rr 9:1 0:4 + +%rd_a 4:4 !function=to_regs_16_31_by_one +%rd_b 4:3 !function=to_regs_16_23_by_one +%rd_c 4:2 !function=to_regs_24_30_by_two +%rr_a 0:4 !function=to_regs_16_31_by_one +%rr_b 0:3 !function=to_regs_16_23_by_one + +%imm6 6:2 0:4 +%imm8 8:4 0:4 + +%io_imm 9:2 0:4 +%ldst_d_imm 13:1 10:2 0:3 + + +&rd_rr rd rr +&rd_imm rd imm + +@op_rd_rr .... .. . ..... .... &rd_rr rd=%rd rr=%rr +@op_rd_imm6 .... .... .. .. .... &rd_imm rd=%rd_c imm=%imm6 +@op_rd_imm8 .... .... .... .... &rd_imm rd=%rd_a imm=%imm8 +@fmul .... .... . ... . ... &rd_rr rd=%rd_b rr=%rr_b + +# +# Arithmetic Instructions +# +ADD 0000 11 . ..... .... @op_rd_rr +ADC 0001 11 . ..... .... @op_rd_rr +ADIW 1001 0110 .. .. .... @op_rd_imm6 +SUB 0001 10 . ..... .... @op_rd_rr +SUBI 0101 .... .... .... @op_rd_imm8 +SBC 0000 10 . ..... .... @op_rd_rr +SBCI 0100 .... .... .... @op_rd_imm8 +SBIW 1001 0111 .. .. .... @op_rd_imm6 +AND 0010 00 . ..... .... @op_rd_rr +ANDI 0111 .... .... .... @op_rd_imm8 +OR 0010 10 . ..... .... @op_rd_rr +ORI 0110 .... .... .... @op_rd_imm8 +EOR 0010 01 . ..... .... @op_rd_rr +COM 1001 010 rd:5 0000 +NEG 1001 010 rd:5 0001 +INC 1001 010 rd:5 0011 +DEC 1001 010 rd:5 1010 +MUL 1001 11 . ..... .... @op_rd_rr +MULS 0000 0010 .... .... &rd_rr rd=%rd_a rr=%rr_a +MULSU 0000 0011 0 ... 0 ... @fmul +FMUL 0000 0011 0 ... 1 ... @fmul +FMULS 0000 0011 1 ... 0 ... @fmul +FMULSU 0000 0011 1 ... 1 ... @fmul +DES 1001 0100 imm:4 1011 + +# +# Branch Instructions +# + +# The 22-bit immediate is partially in the opcode word, +# and partially in the next. Use append_16 to build the +# complete 22-bit value. +%imm_call 4:5 0:1 !function=append_16 + +@op_bit .... .... . bit:3 .... +@op_bit_imm .... .. imm:s7 bit:3 + +RJMP 1100 imm:s12 +IJMP 1001 0100 0000 1001 +EIJMP 1001 0100 0001 1001 +JMP 1001 010 ..... 110 . imm=%imm_call +RCALL 1101 imm:s12 +ICALL 1001 0101 0000 1001 +EICALL 1001 0101 0001 1001 +CALL 1001 010 ..... 111 . imm=%imm_call +RET 1001 0101 0000 1000 +RETI 1001 0101 0001 1000 +CPSE 0001 00 . ..... .... @op_rd_rr +CP 0001 01 . ..... .... @op_rd_rr +CPC 0000 01 . ..... .... @op_rd_rr +CPI 0011 .... .... .... @op_rd_imm8 +SBRC 1111 110 rr:5 0 bit:3 +SBRS 1111 111 rr:5 0 bit:3 +SBIC 1001 1001 reg:5 bit:3 +SBIS 1001 1011 reg:5 bit:3 +BRBS 1111 00 ....... ... @op_bit_imm +BRBC 1111 01 ....... ... @op_bit_imm + +# +# Data Transfer Instructions +# + +%rd_d 4:4 !function=to_regs_00_30_by_two +%rr_d 0:4 !function=to_regs_00_30_by_two + +@io_rd_imm .... . .. ..... .... &rd_imm rd=%rd imm=%io_imm +@ldst_d .. . . .. . rd:5 . ... &rd_imm imm=%ldst_d_imm + +# The 16-bit immediate is completely in the next word. +# Fields cannot be defined with no bits, so we cannot play +# the same trick and append to a zero-bit value. +# Defer reading the immediate until trans_{LDS,STS}. +@ldst_s .... ... rd:5 .... imm=0 + +MOV 0010 11 . ..... .... @op_rd_rr +MOVW 0000 0001 .... .... &rd_rr rd=%rd_d rr=%rr_d +LDI 1110 .... .... .... @op_rd_imm8 +LDS 1001 000 ..... 0000 @ldst_s +LDX1 1001 000 rd:5 1100 +LDX2 1001 000 rd:5 1101 +LDX3 1001 000 rd:5 1110 +LDY2 1001 000 rd:5 1001 +LDY3 1001 000 rd:5 1010 +LDZ2 1001 000 rd:5 0001 +LDZ3 1001 000 rd:5 0010 +LDDY 10 . 0 .. 0 ..... 1 ... @ldst_d +LDDZ 10 . 0 .. 0 ..... 0 ... @ldst_d +STS 1001 001 ..... 0000 @ldst_s +STX1 1001 001 rr:5 1100 +STX2 1001 001 rr:5 1101 +STX3 1001 001 rr:5 1110 +STY2 1001 001 rd:5 1001 +STY3 1001 001 rd:5 1010 +STZ2 1001 001 rd:5 0001 +STZ3 1001 001 rd:5 0010 +STDY 10 . 0 .. 1 ..... 1 ... @ldst_d +STDZ 10 . 0 .. 1 ..... 0 ... @ldst_d +LPM1 1001 0101 1100 1000 +LPM2 1001 000 rd:5 0100 +LPMX 1001 000 rd:5 0101 +ELPM1 1001 0101 1101 1000 +ELPM2 1001 000 rd:5 0110 +ELPMX 1001 000 rd:5 0111 +SPM 1001 0101 1110 1000 +SPMX 1001 0101 1111 1000 +IN 1011 0 .. ..... .... @io_rd_imm +OUT 1011 1 .. ..... .... @io_rd_imm +PUSH 1001 001 rd:5 1111 +POP 1001 000 rd:5 1111 +XCH 1001 001 rd:5 0100 +LAC 1001 001 rd:5 0110 +LAS 1001 001 rd:5 0101 +LAT 1001 001 rd:5 0111 + +# +# Bit and Bit-test Instructions +# +LSR 1001 010 rd:5 0110 +ROR 1001 010 rd:5 0111 +ASR 1001 010 rd:5 0101 +SWAP 1001 010 rd:5 0010 +SBI 1001 1010 reg:5 bit:3 +CBI 1001 1000 reg:5 bit:3 +BST 1111 101 rd:5 0 bit:3 +BLD 1111 100 rd:5 0 bit:3 +BSET 1001 0100 0 bit:3 1000 +BCLR 1001 0100 1 bit:3 1000 + +# +# MCU Control Instructions +# +BREAK 1001 0101 1001 1000 +NOP 0000 0000 0000 0000 +SLEEP 1001 0101 1000 1000 +WDR 1001 0101 1010 1000 diff --git a/target/avr/machine.c b/target/avr/machine.c new file mode 100644 index 0000000000000000000000000000000000000000..e315442787613374673c71e3a0024d5a01d8c679 --- /dev/null +++ b/target/avr/machine.c @@ -0,0 +1,119 @@ +/* + * QEMU AVR CPU + * + * Copyright (c) 2016-2020 Michael Rolnik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "migration/cpu.h" + +static int get_sreg(QEMUFile *f, void *opaque, size_t size, + const VMStateField *field) +{ + CPUAVRState *env = opaque; + uint8_t sreg; + + sreg = qemu_get_byte(f); + cpu_set_sreg(env, sreg); + return 0; +} + +static int put_sreg(QEMUFile *f, void *opaque, size_t size, + const VMStateField *field, QJSON *vmdesc) +{ + CPUAVRState *env = opaque; + uint8_t sreg = cpu_get_sreg(env); + + qemu_put_byte(f, sreg); + return 0; +} + +static const VMStateInfo vms_sreg = { + .name = "sreg", + .get = get_sreg, + .put = put_sreg, +}; + +static int get_segment(QEMUFile *f, void *opaque, size_t size, + const VMStateField *field) +{ + uint32_t *ramp = opaque; + uint8_t temp; + + temp = qemu_get_byte(f); + *ramp = ((uint32_t)temp) << 16; + return 0; +} + +static int put_segment(QEMUFile *f, void *opaque, size_t size, + const VMStateField *field, QJSON *vmdesc) +{ + uint32_t *ramp = opaque; + uint8_t temp = *ramp >> 16; + + qemu_put_byte(f, temp); + return 0; +} + +static const VMStateInfo vms_rampD = { + .name = "rampD", + .get = get_segment, + .put = put_segment, +}; +static const VMStateInfo vms_rampX = { + .name = "rampX", + .get = get_segment, + .put = put_segment, +}; +static const VMStateInfo vms_rampY = { + .name = "rampY", + .get = get_segment, + .put = put_segment, +}; +static const VMStateInfo vms_rampZ = { + .name = "rampZ", + .get = get_segment, + .put = put_segment, +}; +static const VMStateInfo vms_eind = { + .name = "eind", + .get = get_segment, + .put = put_segment, +}; + +const VMStateDescription vms_avr_cpu = { + .name = "cpu", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32(env.pc_w, AVRCPU), + VMSTATE_UINT32(env.sp, AVRCPU), + VMSTATE_UINT32(env.skip, AVRCPU), + + VMSTATE_UINT32_ARRAY(env.r, AVRCPU, NUMBER_OF_CPU_REGISTERS), + + VMSTATE_SINGLE(env, AVRCPU, 0, vms_sreg, CPUAVRState), + VMSTATE_SINGLE(env.rampD, AVRCPU, 0, vms_rampD, uint32_t), + VMSTATE_SINGLE(env.rampX, AVRCPU, 0, vms_rampX, uint32_t), + VMSTATE_SINGLE(env.rampY, AVRCPU, 0, vms_rampY, uint32_t), + VMSTATE_SINGLE(env.rampZ, AVRCPU, 0, vms_rampZ, uint32_t), + VMSTATE_SINGLE(env.eind, AVRCPU, 0, vms_eind, uint32_t), + + VMSTATE_END_OF_LIST() + } +}; diff --git a/target/avr/meson.build b/target/avr/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..7e8e29c59d0240a9e0820a18f1d20d03afda59ac --- /dev/null +++ b/target/avr/meson.build @@ -0,0 +1,20 @@ +gen = [ + decodetree.process('insn.decode', extra_args: [ '--decode', 'decode_insn', + '--insnwidth', '16' ]) +] + +avr_ss = ss.source_set() +avr_softmmu_ss = ss.source_set() + +avr_ss.add(gen) +avr_ss.add(files( + 'translate.c', + 'helper.c', + 'cpu.c', + 'gdbstub.c', + 'disas.c')) + +avr_softmmu_ss.add(files('machine.c')) + +target_arch += {'avr': avr_ss} +target_softmmu_arch += {'avr': avr_softmmu_ss} diff --git a/target/avr/translate.c b/target/avr/translate.c new file mode 100644 index 0000000000000000000000000000000000000000..850c5941d95cf55e48d0531ae1bf4b7b9f3d9a47 --- /dev/null +++ b/target/avr/translate.c @@ -0,0 +1,3061 @@ +/* + * QEMU AVR CPU + * + * Copyright (c) 2019-2020 Michael Rolnik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * + */ + +#include "qemu/osdep.h" +#include "qemu/qemu-print.h" +#include "tcg/tcg.h" +#include "cpu.h" +#include "exec/exec-all.h" +#include "tcg/tcg-op.h" +#include "exec/cpu_ldst.h" +#include "exec/helper-proto.h" +#include "exec/helper-gen.h" +#include "exec/log.h" +#include "exec/translator.h" +#include "exec/gen-icount.h" + +/* + * Define if you want a BREAK instruction translated to a breakpoint + * Active debugging connection is assumed + * This is for + * https://github.com/seharris/qemu-avr-tests/tree/master/instruction-tests + * tests + */ +#undef BREAKPOINT_ON_BREAK + +static TCGv cpu_pc; + +static TCGv cpu_Cf; +static TCGv cpu_Zf; +static TCGv cpu_Nf; +static TCGv cpu_Vf; +static TCGv cpu_Sf; +static TCGv cpu_Hf; +static TCGv cpu_Tf; +static TCGv cpu_If; + +static TCGv cpu_rampD; +static TCGv cpu_rampX; +static TCGv cpu_rampY; +static TCGv cpu_rampZ; + +static TCGv cpu_r[NUMBER_OF_CPU_REGISTERS]; +static TCGv cpu_eind; +static TCGv cpu_sp; + +static TCGv cpu_skip; + +static const char reg_names[NUMBER_OF_CPU_REGISTERS][8] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", +}; +#define REG(x) (cpu_r[x]) + +enum { + DISAS_EXIT = DISAS_TARGET_0, /* We want return to the cpu main loop. */ + DISAS_LOOKUP = DISAS_TARGET_1, /* We have a variable condition exit. */ + DISAS_CHAIN = DISAS_TARGET_2, /* We have a single condition exit. */ +}; + +typedef struct DisasContext DisasContext; + +/* This is the state at translation time. */ +struct DisasContext { + TranslationBlock *tb; + + CPUAVRState *env; + CPUState *cs; + + target_long npc; + uint32_t opcode; + + /* Routine used to access memory */ + int memidx; + int bstate; + int singlestep; + + /* + * some AVR instructions can make the following instruction to be skipped + * Let's name those instructions + * A - instruction that can skip the next one + * B - instruction that can be skipped. this depends on execution of A + * there are two scenarios + * 1. A and B belong to the same translation block + * 2. A is the last instruction in the translation block and B is the last + * + * following variables are used to simplify the skipping logic, they are + * used in the following manner (sketch) + * + * TCGLabel *skip_label = NULL; + * if (ctx.skip_cond != TCG_COND_NEVER) { + * skip_label = gen_new_label(); + * tcg_gen_brcond_tl(skip_cond, skip_var0, skip_var1, skip_label); + * } + * + * if (free_skip_var0) { + * tcg_temp_free(skip_var0); + * free_skip_var0 = false; + * } + * + * translate(&ctx); + * + * if (skip_label) { + * gen_set_label(skip_label); + * } + */ + TCGv skip_var0; + TCGv skip_var1; + TCGCond skip_cond; + bool free_skip_var0; +}; + +void avr_cpu_tcg_init(void) +{ + int i; + +#define AVR_REG_OFFS(x) offsetof(CPUAVRState, x) + cpu_pc = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(pc_w), "pc"); + cpu_Cf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregC), "Cf"); + cpu_Zf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregZ), "Zf"); + cpu_Nf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregN), "Nf"); + cpu_Vf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregV), "Vf"); + cpu_Sf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregS), "Sf"); + cpu_Hf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregH), "Hf"); + cpu_Tf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregT), "Tf"); + cpu_If = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregI), "If"); + cpu_rampD = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(rampD), "rampD"); + cpu_rampX = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(rampX), "rampX"); + cpu_rampY = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(rampY), "rampY"); + cpu_rampZ = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(rampZ), "rampZ"); + cpu_eind = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(eind), "eind"); + cpu_sp = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sp), "sp"); + cpu_skip = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(skip), "skip"); + + for (i = 0; i < NUMBER_OF_CPU_REGISTERS; i++) { + cpu_r[i] = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(r[i]), + reg_names[i]); + } +#undef AVR_REG_OFFS +} + +static int to_regs_16_31_by_one(DisasContext *ctx, int indx) +{ + return 16 + (indx % 16); +} + +static int to_regs_16_23_by_one(DisasContext *ctx, int indx) +{ + return 16 + (indx % 8); +} + +static int to_regs_24_30_by_two(DisasContext *ctx, int indx) +{ + return 24 + (indx % 4) * 2; +} + +static int to_regs_00_30_by_two(DisasContext *ctx, int indx) +{ + return (indx % 16) * 2; +} + +static uint16_t next_word(DisasContext *ctx) +{ + return cpu_lduw_code(ctx->env, ctx->npc++ * 2); +} + +static int append_16(DisasContext *ctx, int x) +{ + return x << 16 | next_word(ctx); +} + +static bool avr_have_feature(DisasContext *ctx, int feature) +{ + if (!avr_feature(ctx->env, feature)) { + gen_helper_unsupported(cpu_env); + ctx->bstate = DISAS_NORETURN; + return false; + } + return true; +} + +static bool decode_insn(DisasContext *ctx, uint16_t insn); +#include "decode-insn.c.inc" + +/* + * Arithmetic Instructions + */ + +/* + * Utility functions for updating status registers: + * + * - gen_add_CHf() + * - gen_add_Vf() + * - gen_sub_CHf() + * - gen_sub_Vf() + * - gen_NSf() + * - gen_ZNSf() + * + */ + +static void gen_add_CHf(TCGv R, TCGv Rd, TCGv Rr) +{ + TCGv t1 = tcg_temp_new_i32(); + TCGv t2 = tcg_temp_new_i32(); + TCGv t3 = tcg_temp_new_i32(); + + tcg_gen_and_tl(t1, Rd, Rr); /* t1 = Rd & Rr */ + tcg_gen_andc_tl(t2, Rd, R); /* t2 = Rd & ~R */ + tcg_gen_andc_tl(t3, Rr, R); /* t3 = Rr & ~R */ + tcg_gen_or_tl(t1, t1, t2); /* t1 = t1 | t2 | t3 */ + tcg_gen_or_tl(t1, t1, t3); + + tcg_gen_shri_tl(cpu_Cf, t1, 7); /* Cf = t1(7) */ + tcg_gen_shri_tl(cpu_Hf, t1, 3); /* Hf = t1(3) */ + tcg_gen_andi_tl(cpu_Hf, cpu_Hf, 1); + + tcg_temp_free_i32(t3); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t1); +} + +static void gen_add_Vf(TCGv R, TCGv Rd, TCGv Rr) +{ + TCGv t1 = tcg_temp_new_i32(); + TCGv t2 = tcg_temp_new_i32(); + + /* t1 = Rd & Rr & ~R | ~Rd & ~Rr & R */ + /* = (Rd ^ R) & ~(Rd ^ Rr) */ + tcg_gen_xor_tl(t1, Rd, R); + tcg_gen_xor_tl(t2, Rd, Rr); + tcg_gen_andc_tl(t1, t1, t2); + + tcg_gen_shri_tl(cpu_Vf, t1, 7); /* Vf = t1(7) */ + + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t1); +} + +static void gen_sub_CHf(TCGv R, TCGv Rd, TCGv Rr) +{ + TCGv t1 = tcg_temp_new_i32(); + TCGv t2 = tcg_temp_new_i32(); + TCGv t3 = tcg_temp_new_i32(); + + tcg_gen_not_tl(t1, Rd); /* t1 = ~Rd */ + tcg_gen_and_tl(t2, t1, Rr); /* t2 = ~Rd & Rr */ + tcg_gen_or_tl(t3, t1, Rr); /* t3 = (~Rd | Rr) & R */ + tcg_gen_and_tl(t3, t3, R); + tcg_gen_or_tl(t2, t2, t3); /* t2 = ~Rd & Rr | ~Rd & R | R & Rr */ + + tcg_gen_shri_tl(cpu_Cf, t2, 7); /* Cf = t2(7) */ + tcg_gen_shri_tl(cpu_Hf, t2, 3); /* Hf = t2(3) */ + tcg_gen_andi_tl(cpu_Hf, cpu_Hf, 1); + + tcg_temp_free_i32(t3); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t1); +} + +static void gen_sub_Vf(TCGv R, TCGv Rd, TCGv Rr) +{ + TCGv t1 = tcg_temp_new_i32(); + TCGv t2 = tcg_temp_new_i32(); + + /* t1 = Rd & ~Rr & ~R | ~Rd & Rr & R */ + /* = (Rd ^ R) & (Rd ^ R) */ + tcg_gen_xor_tl(t1, Rd, R); + tcg_gen_xor_tl(t2, Rd, Rr); + tcg_gen_and_tl(t1, t1, t2); + + tcg_gen_shri_tl(cpu_Vf, t1, 7); /* Vf = t1(7) */ + + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t1); +} + +static void gen_NSf(TCGv R) +{ + tcg_gen_shri_tl(cpu_Nf, R, 7); /* Nf = R(7) */ + tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */ +} + +static void gen_ZNSf(TCGv R) +{ + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0); /* Zf = R == 0 */ + + /* update status register */ + tcg_gen_shri_tl(cpu_Nf, R, 7); /* Nf = R(7) */ + tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */ +} + +/* + * Adds two registers without the C Flag and places the result in the + * destination register Rd. + */ +static bool trans_ADD(DisasContext *ctx, arg_ADD *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = cpu_r[a->rr]; + TCGv R = tcg_temp_new_i32(); + + tcg_gen_add_tl(R, Rd, Rr); /* Rd = Rd + Rr */ + tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */ + + /* update status register */ + gen_add_CHf(R, Rd, Rr); + gen_add_Vf(R, Rd, Rr); + gen_ZNSf(R); + + /* update output registers */ + tcg_gen_mov_tl(Rd, R); + + tcg_temp_free_i32(R); + + return true; +} + +/* + * Adds two registers and the contents of the C Flag and places the result in + * the destination register Rd. + */ +static bool trans_ADC(DisasContext *ctx, arg_ADC *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = cpu_r[a->rr]; + TCGv R = tcg_temp_new_i32(); + + tcg_gen_add_tl(R, Rd, Rr); /* R = Rd + Rr + Cf */ + tcg_gen_add_tl(R, R, cpu_Cf); + tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */ + + /* update status register */ + gen_add_CHf(R, Rd, Rr); + gen_add_Vf(R, Rd, Rr); + gen_ZNSf(R); + + /* update output registers */ + tcg_gen_mov_tl(Rd, R); + + tcg_temp_free_i32(R); + + return true; +} + +/* + * Adds an immediate value (0 - 63) to a register pair and places the result + * in the register pair. This instruction operates on the upper four register + * pairs, and is well suited for operations on the pointer registers. This + * instruction is not available in all devices. Refer to the device specific + * instruction set summary. + */ +static bool trans_ADIW(DisasContext *ctx, arg_ADIW *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_ADIW_SBIW)) { + return true; + } + + TCGv RdL = cpu_r[a->rd]; + TCGv RdH = cpu_r[a->rd + 1]; + int Imm = (a->imm); + TCGv R = tcg_temp_new_i32(); + TCGv Rd = tcg_temp_new_i32(); + + tcg_gen_deposit_tl(Rd, RdL, RdH, 8, 8); /* Rd = RdH:RdL */ + tcg_gen_addi_tl(R, Rd, Imm); /* R = Rd + Imm */ + tcg_gen_andi_tl(R, R, 0xffff); /* make it 16 bits */ + + /* update status register */ + tcg_gen_andc_tl(cpu_Cf, Rd, R); /* Cf = Rd & ~R */ + tcg_gen_shri_tl(cpu_Cf, cpu_Cf, 15); + tcg_gen_andc_tl(cpu_Vf, R, Rd); /* Vf = R & ~Rd */ + tcg_gen_shri_tl(cpu_Vf, cpu_Vf, 15); + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0); /* Zf = R == 0 */ + tcg_gen_shri_tl(cpu_Nf, R, 15); /* Nf = R(15) */ + tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf);/* Sf = Nf ^ Vf */ + + /* update output registers */ + tcg_gen_andi_tl(RdL, R, 0xff); + tcg_gen_shri_tl(RdH, R, 8); + + tcg_temp_free_i32(Rd); + tcg_temp_free_i32(R); + + return true; +} + +/* + * Subtracts two registers and places the result in the destination + * register Rd. + */ +static bool trans_SUB(DisasContext *ctx, arg_SUB *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = cpu_r[a->rr]; + TCGv R = tcg_temp_new_i32(); + + tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */ + tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */ + + /* update status register */ + tcg_gen_andc_tl(cpu_Cf, Rd, R); /* Cf = Rd & ~R */ + gen_sub_CHf(R, Rd, Rr); + gen_sub_Vf(R, Rd, Rr); + gen_ZNSf(R); + + /* update output registers */ + tcg_gen_mov_tl(Rd, R); + + tcg_temp_free_i32(R); + + return true; +} + +/* + * Subtracts a register and a constant and places the result in the + * destination register Rd. This instruction is working on Register R16 to R31 + * and is very well suited for operations on the X, Y, and Z-pointers. + */ +static bool trans_SUBI(DisasContext *ctx, arg_SUBI *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = tcg_const_i32(a->imm); + TCGv R = tcg_temp_new_i32(); + + tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Imm */ + tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */ + + /* update status register */ + gen_sub_CHf(R, Rd, Rr); + gen_sub_Vf(R, Rd, Rr); + gen_ZNSf(R); + + /* update output registers */ + tcg_gen_mov_tl(Rd, R); + + tcg_temp_free_i32(R); + tcg_temp_free_i32(Rr); + + return true; +} + +/* + * Subtracts two registers and subtracts with the C Flag and places the + * result in the destination register Rd. + */ +static bool trans_SBC(DisasContext *ctx, arg_SBC *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = cpu_r[a->rr]; + TCGv R = tcg_temp_new_i32(); + TCGv zero = tcg_const_i32(0); + + tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */ + tcg_gen_sub_tl(R, R, cpu_Cf); + tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */ + + /* update status register */ + gen_sub_CHf(R, Rd, Rr); + gen_sub_Vf(R, Rd, Rr); + gen_NSf(R); + + /* + * Previous value remains unchanged when the result is zero; + * cleared otherwise. + */ + tcg_gen_movcond_tl(TCG_COND_EQ, cpu_Zf, R, zero, cpu_Zf, zero); + + /* update output registers */ + tcg_gen_mov_tl(Rd, R); + + tcg_temp_free_i32(zero); + tcg_temp_free_i32(R); + + return true; +} + +/* + * SBCI -- Subtract Immediate with Carry + */ +static bool trans_SBCI(DisasContext *ctx, arg_SBCI *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = tcg_const_i32(a->imm); + TCGv R = tcg_temp_new_i32(); + TCGv zero = tcg_const_i32(0); + + tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */ + tcg_gen_sub_tl(R, R, cpu_Cf); + tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */ + + /* update status register */ + gen_sub_CHf(R, Rd, Rr); + gen_sub_Vf(R, Rd, Rr); + gen_NSf(R); + + /* + * Previous value remains unchanged when the result is zero; + * cleared otherwise. + */ + tcg_gen_movcond_tl(TCG_COND_EQ, cpu_Zf, R, zero, cpu_Zf, zero); + + /* update output registers */ + tcg_gen_mov_tl(Rd, R); + + tcg_temp_free_i32(zero); + tcg_temp_free_i32(R); + tcg_temp_free_i32(Rr); + + return true; +} + +/* + * Subtracts an immediate value (0-63) from a register pair and places the + * result in the register pair. This instruction operates on the upper four + * register pairs, and is well suited for operations on the Pointer Registers. + * This instruction is not available in all devices. Refer to the device + * specific instruction set summary. + */ +static bool trans_SBIW(DisasContext *ctx, arg_SBIW *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_ADIW_SBIW)) { + return true; + } + + TCGv RdL = cpu_r[a->rd]; + TCGv RdH = cpu_r[a->rd + 1]; + int Imm = (a->imm); + TCGv R = tcg_temp_new_i32(); + TCGv Rd = tcg_temp_new_i32(); + + tcg_gen_deposit_tl(Rd, RdL, RdH, 8, 8); /* Rd = RdH:RdL */ + tcg_gen_subi_tl(R, Rd, Imm); /* R = Rd - Imm */ + tcg_gen_andi_tl(R, R, 0xffff); /* make it 16 bits */ + + /* update status register */ + tcg_gen_andc_tl(cpu_Cf, R, Rd); + tcg_gen_shri_tl(cpu_Cf, cpu_Cf, 15); /* Cf = R & ~Rd */ + tcg_gen_andc_tl(cpu_Vf, Rd, R); + tcg_gen_shri_tl(cpu_Vf, cpu_Vf, 15); /* Vf = Rd & ~R */ + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0); /* Zf = R == 0 */ + tcg_gen_shri_tl(cpu_Nf, R, 15); /* Nf = R(15) */ + tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */ + + /* update output registers */ + tcg_gen_andi_tl(RdL, R, 0xff); + tcg_gen_shri_tl(RdH, R, 8); + + tcg_temp_free_i32(Rd); + tcg_temp_free_i32(R); + + return true; +} + +/* + * Performs the logical AND between the contents of register Rd and register + * Rr and places the result in the destination register Rd. + */ +static bool trans_AND(DisasContext *ctx, arg_AND *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = cpu_r[a->rr]; + TCGv R = tcg_temp_new_i32(); + + tcg_gen_and_tl(R, Rd, Rr); /* Rd = Rd and Rr */ + + /* update status register */ + tcg_gen_movi_tl(cpu_Vf, 0); /* Vf = 0 */ + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0); /* Zf = R == 0 */ + gen_ZNSf(R); + + /* update output registers */ + tcg_gen_mov_tl(Rd, R); + + tcg_temp_free_i32(R); + + return true; +} + +/* + * Performs the logical AND between the contents of register Rd and a constant + * and places the result in the destination register Rd. + */ +static bool trans_ANDI(DisasContext *ctx, arg_ANDI *a) +{ + TCGv Rd = cpu_r[a->rd]; + int Imm = (a->imm); + + tcg_gen_andi_tl(Rd, Rd, Imm); /* Rd = Rd & Imm */ + + /* update status register */ + tcg_gen_movi_tl(cpu_Vf, 0x00); /* Vf = 0 */ + gen_ZNSf(Rd); + + return true; +} + +/* + * Performs the logical OR between the contents of register Rd and register + * Rr and places the result in the destination register Rd. + */ +static bool trans_OR(DisasContext *ctx, arg_OR *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = cpu_r[a->rr]; + TCGv R = tcg_temp_new_i32(); + + tcg_gen_or_tl(R, Rd, Rr); + + /* update status register */ + tcg_gen_movi_tl(cpu_Vf, 0); + gen_ZNSf(R); + + /* update output registers */ + tcg_gen_mov_tl(Rd, R); + + tcg_temp_free_i32(R); + + return true; +} + +/* + * Performs the logical OR between the contents of register Rd and a + * constant and places the result in the destination register Rd. + */ +static bool trans_ORI(DisasContext *ctx, arg_ORI *a) +{ + TCGv Rd = cpu_r[a->rd]; + int Imm = (a->imm); + + tcg_gen_ori_tl(Rd, Rd, Imm); /* Rd = Rd | Imm */ + + /* update status register */ + tcg_gen_movi_tl(cpu_Vf, 0x00); /* Vf = 0 */ + gen_ZNSf(Rd); + + return true; +} + +/* + * Performs the logical EOR between the contents of register Rd and + * register Rr and places the result in the destination register Rd. + */ +static bool trans_EOR(DisasContext *ctx, arg_EOR *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = cpu_r[a->rr]; + + tcg_gen_xor_tl(Rd, Rd, Rr); + + /* update status register */ + tcg_gen_movi_tl(cpu_Vf, 0); + gen_ZNSf(Rd); + + return true; +} + +/* + * Clears the specified bits in register Rd. Performs the logical AND + * between the contents of register Rd and the complement of the constant mask + * K. The result will be placed in register Rd. + */ +static bool trans_COM(DisasContext *ctx, arg_COM *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv R = tcg_temp_new_i32(); + + tcg_gen_xori_tl(Rd, Rd, 0xff); + + /* update status register */ + tcg_gen_movi_tl(cpu_Cf, 1); /* Cf = 1 */ + tcg_gen_movi_tl(cpu_Vf, 0); /* Vf = 0 */ + gen_ZNSf(Rd); + + tcg_temp_free_i32(R); + + return true; +} + +/* + * Replaces the contents of register Rd with its two's complement; the + * value $80 is left unchanged. + */ +static bool trans_NEG(DisasContext *ctx, arg_NEG *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv t0 = tcg_const_i32(0); + TCGv R = tcg_temp_new_i32(); + + tcg_gen_sub_tl(R, t0, Rd); /* R = 0 - Rd */ + tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */ + + /* update status register */ + gen_sub_CHf(R, t0, Rd); + gen_sub_Vf(R, t0, Rd); + gen_ZNSf(R); + + /* update output registers */ + tcg_gen_mov_tl(Rd, R); + + tcg_temp_free_i32(t0); + tcg_temp_free_i32(R); + + return true; +} + +/* + * Adds one -1- to the contents of register Rd and places the result in the + * destination register Rd. The C Flag in SREG is not affected by the + * operation, thus allowing the INC instruction to be used on a loop counter in + * multiple-precision computations. When operating on unsigned numbers, only + * BREQ and BRNE branches can be expected to perform consistently. When + * operating on two's complement values, all signed branches are available. + */ +static bool trans_INC(DisasContext *ctx, arg_INC *a) +{ + TCGv Rd = cpu_r[a->rd]; + + tcg_gen_addi_tl(Rd, Rd, 1); + tcg_gen_andi_tl(Rd, Rd, 0xff); + + /* update status register */ + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Vf, Rd, 0x80); /* Vf = Rd == 0x80 */ + gen_ZNSf(Rd); + + return true; +} + +/* + * Subtracts one -1- from the contents of register Rd and places the result + * in the destination register Rd. The C Flag in SREG is not affected by the + * operation, thus allowing the DEC instruction to be used on a loop counter in + * multiple-precision computations. When operating on unsigned values, only + * BREQ and BRNE branches can be expected to perform consistently. When + * operating on two's complement values, all signed branches are available. + */ +static bool trans_DEC(DisasContext *ctx, arg_DEC *a) +{ + TCGv Rd = cpu_r[a->rd]; + + tcg_gen_subi_tl(Rd, Rd, 1); /* Rd = Rd - 1 */ + tcg_gen_andi_tl(Rd, Rd, 0xff); /* make it 8 bits */ + + /* update status register */ + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Vf, Rd, 0x7f); /* Vf = Rd == 0x7f */ + gen_ZNSf(Rd); + + return true; +} + +/* + * This instruction performs 8-bit x 8-bit -> 16-bit unsigned multiplication. + */ +static bool trans_MUL(DisasContext *ctx, arg_MUL *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_MUL)) { + return true; + } + + TCGv R0 = cpu_r[0]; + TCGv R1 = cpu_r[1]; + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = cpu_r[a->rr]; + TCGv R = tcg_temp_new_i32(); + + tcg_gen_mul_tl(R, Rd, Rr); /* R = Rd * Rr */ + tcg_gen_andi_tl(R0, R, 0xff); + tcg_gen_shri_tl(R1, R, 8); + + /* update status register */ + tcg_gen_shri_tl(cpu_Cf, R, 15); /* Cf = R(15) */ + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0); /* Zf = R == 0 */ + + tcg_temp_free_i32(R); + + return true; +} + +/* + * This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication. + */ +static bool trans_MULS(DisasContext *ctx, arg_MULS *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_MUL)) { + return true; + } + + TCGv R0 = cpu_r[0]; + TCGv R1 = cpu_r[1]; + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = cpu_r[a->rr]; + TCGv R = tcg_temp_new_i32(); + TCGv t0 = tcg_temp_new_i32(); + TCGv t1 = tcg_temp_new_i32(); + + tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */ + tcg_gen_ext8s_tl(t1, Rr); /* make Rr full 32 bit signed */ + tcg_gen_mul_tl(R, t0, t1); /* R = Rd * Rr */ + tcg_gen_andi_tl(R, R, 0xffff); /* make it 16 bits */ + tcg_gen_andi_tl(R0, R, 0xff); + tcg_gen_shri_tl(R1, R, 8); + + /* update status register */ + tcg_gen_shri_tl(cpu_Cf, R, 15); /* Cf = R(15) */ + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0); /* Zf = R == 0 */ + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); + tcg_temp_free_i32(R); + + return true; +} + +/* + * This instruction performs 8-bit x 8-bit -> 16-bit multiplication of a + * signed and an unsigned number. + */ +static bool trans_MULSU(DisasContext *ctx, arg_MULSU *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_MUL)) { + return true; + } + + TCGv R0 = cpu_r[0]; + TCGv R1 = cpu_r[1]; + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = cpu_r[a->rr]; + TCGv R = tcg_temp_new_i32(); + TCGv t0 = tcg_temp_new_i32(); + + tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */ + tcg_gen_mul_tl(R, t0, Rr); /* R = Rd * Rr */ + tcg_gen_andi_tl(R, R, 0xffff); /* make R 16 bits */ + tcg_gen_andi_tl(R0, R, 0xff); + tcg_gen_shri_tl(R1, R, 8); + + /* update status register */ + tcg_gen_shri_tl(cpu_Cf, R, 15); /* Cf = R(15) */ + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0); /* Zf = R == 0 */ + + tcg_temp_free_i32(t0); + tcg_temp_free_i32(R); + + return true; +} + +/* + * This instruction performs 8-bit x 8-bit -> 16-bit unsigned + * multiplication and shifts the result one bit left. + */ +static bool trans_FMUL(DisasContext *ctx, arg_FMUL *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_MUL)) { + return true; + } + + TCGv R0 = cpu_r[0]; + TCGv R1 = cpu_r[1]; + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = cpu_r[a->rr]; + TCGv R = tcg_temp_new_i32(); + + tcg_gen_mul_tl(R, Rd, Rr); /* R = Rd * Rr */ + + /* update status register */ + tcg_gen_shri_tl(cpu_Cf, R, 15); /* Cf = R(15) */ + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0); /* Zf = R == 0 */ + + /* update output registers */ + tcg_gen_shli_tl(R, R, 1); + tcg_gen_andi_tl(R0, R, 0xff); + tcg_gen_shri_tl(R1, R, 8); + tcg_gen_andi_tl(R1, R1, 0xff); + + + tcg_temp_free_i32(R); + + return true; +} + +/* + * This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication + * and shifts the result one bit left. + */ +static bool trans_FMULS(DisasContext *ctx, arg_FMULS *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_MUL)) { + return true; + } + + TCGv R0 = cpu_r[0]; + TCGv R1 = cpu_r[1]; + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = cpu_r[a->rr]; + TCGv R = tcg_temp_new_i32(); + TCGv t0 = tcg_temp_new_i32(); + TCGv t1 = tcg_temp_new_i32(); + + tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */ + tcg_gen_ext8s_tl(t1, Rr); /* make Rr full 32 bit signed */ + tcg_gen_mul_tl(R, t0, t1); /* R = Rd * Rr */ + tcg_gen_andi_tl(R, R, 0xffff); /* make it 16 bits */ + + /* update status register */ + tcg_gen_shri_tl(cpu_Cf, R, 15); /* Cf = R(15) */ + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0); /* Zf = R == 0 */ + + /* update output registers */ + tcg_gen_shli_tl(R, R, 1); + tcg_gen_andi_tl(R0, R, 0xff); + tcg_gen_shri_tl(R1, R, 8); + tcg_gen_andi_tl(R1, R1, 0xff); + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); + tcg_temp_free_i32(R); + + return true; +} + +/* + * This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication + * and shifts the result one bit left. + */ +static bool trans_FMULSU(DisasContext *ctx, arg_FMULSU *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_MUL)) { + return true; + } + + TCGv R0 = cpu_r[0]; + TCGv R1 = cpu_r[1]; + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = cpu_r[a->rr]; + TCGv R = tcg_temp_new_i32(); + TCGv t0 = tcg_temp_new_i32(); + + tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */ + tcg_gen_mul_tl(R, t0, Rr); /* R = Rd * Rr */ + tcg_gen_andi_tl(R, R, 0xffff); /* make it 16 bits */ + + /* update status register */ + tcg_gen_shri_tl(cpu_Cf, R, 15); /* Cf = R(15) */ + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0); /* Zf = R == 0 */ + + /* update output registers */ + tcg_gen_shli_tl(R, R, 1); + tcg_gen_andi_tl(R0, R, 0xff); + tcg_gen_shri_tl(R1, R, 8); + tcg_gen_andi_tl(R1, R1, 0xff); + + tcg_temp_free_i32(t0); + tcg_temp_free_i32(R); + + return true; +} + +/* + * The module is an instruction set extension to the AVR CPU, performing + * DES iterations. The 64-bit data block (plaintext or ciphertext) is placed in + * the CPU register file, registers R0-R7, where LSB of data is placed in LSB + * of R0 and MSB of data is placed in MSB of R7. The full 64-bit key (including + * parity bits) is placed in registers R8- R15, organized in the register file + * with LSB of key in LSB of R8 and MSB of key in MSB of R15. Executing one DES + * instruction performs one round in the DES algorithm. Sixteen rounds must be + * executed in increasing order to form the correct DES ciphertext or + * plaintext. Intermediate results are stored in the register file (R0-R15) + * after each DES instruction. The instruction's operand (K) determines which + * round is executed, and the half carry flag (H) determines whether encryption + * or decryption is performed. The DES algorithm is described in + * "Specifications for the Data Encryption Standard" (Federal Information + * Processing Standards Publication 46). Intermediate results in this + * implementation differ from the standard because the initial permutation and + * the inverse initial permutation are performed each iteration. This does not + * affect the result in the final ciphertext or plaintext, but reduces + * execution time. + */ +static bool trans_DES(DisasContext *ctx, arg_DES *a) +{ + /* TODO */ + if (!avr_have_feature(ctx, AVR_FEATURE_DES)) { + return true; + } + + qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__); + + return true; +} + +/* + * Branch Instructions + */ +static void gen_jmp_ez(DisasContext *ctx) +{ + tcg_gen_deposit_tl(cpu_pc, cpu_r[30], cpu_r[31], 8, 8); + tcg_gen_or_tl(cpu_pc, cpu_pc, cpu_eind); + ctx->bstate = DISAS_LOOKUP; +} + +static void gen_jmp_z(DisasContext *ctx) +{ + tcg_gen_deposit_tl(cpu_pc, cpu_r[30], cpu_r[31], 8, 8); + ctx->bstate = DISAS_LOOKUP; +} + +static void gen_push_ret(DisasContext *ctx, int ret) +{ + if (avr_feature(ctx->env, AVR_FEATURE_1_BYTE_PC)) { + + TCGv t0 = tcg_const_i32((ret & 0x0000ff)); + + tcg_gen_qemu_st_tl(t0, cpu_sp, MMU_DATA_IDX, MO_UB); + tcg_gen_subi_tl(cpu_sp, cpu_sp, 1); + + tcg_temp_free_i32(t0); + } else if (avr_feature(ctx->env, AVR_FEATURE_2_BYTE_PC)) { + + TCGv t0 = tcg_const_i32((ret & 0x00ffff)); + + tcg_gen_subi_tl(cpu_sp, cpu_sp, 1); + tcg_gen_qemu_st_tl(t0, cpu_sp, MMU_DATA_IDX, MO_BEUW); + tcg_gen_subi_tl(cpu_sp, cpu_sp, 1); + + tcg_temp_free_i32(t0); + + } else if (avr_feature(ctx->env, AVR_FEATURE_3_BYTE_PC)) { + + TCGv lo = tcg_const_i32((ret & 0x0000ff)); + TCGv hi = tcg_const_i32((ret & 0xffff00) >> 8); + + tcg_gen_qemu_st_tl(lo, cpu_sp, MMU_DATA_IDX, MO_UB); + tcg_gen_subi_tl(cpu_sp, cpu_sp, 2); + tcg_gen_qemu_st_tl(hi, cpu_sp, MMU_DATA_IDX, MO_BEUW); + tcg_gen_subi_tl(cpu_sp, cpu_sp, 1); + + tcg_temp_free_i32(lo); + tcg_temp_free_i32(hi); + } +} + +static void gen_pop_ret(DisasContext *ctx, TCGv ret) +{ + if (avr_feature(ctx->env, AVR_FEATURE_1_BYTE_PC)) { + tcg_gen_addi_tl(cpu_sp, cpu_sp, 1); + tcg_gen_qemu_ld_tl(ret, cpu_sp, MMU_DATA_IDX, MO_UB); + } else if (avr_feature(ctx->env, AVR_FEATURE_2_BYTE_PC)) { + tcg_gen_addi_tl(cpu_sp, cpu_sp, 1); + tcg_gen_qemu_ld_tl(ret, cpu_sp, MMU_DATA_IDX, MO_BEUW); + tcg_gen_addi_tl(cpu_sp, cpu_sp, 1); + } else if (avr_feature(ctx->env, AVR_FEATURE_3_BYTE_PC)) { + TCGv lo = tcg_temp_new_i32(); + TCGv hi = tcg_temp_new_i32(); + + tcg_gen_addi_tl(cpu_sp, cpu_sp, 1); + tcg_gen_qemu_ld_tl(hi, cpu_sp, MMU_DATA_IDX, MO_BEUW); + + tcg_gen_addi_tl(cpu_sp, cpu_sp, 2); + tcg_gen_qemu_ld_tl(lo, cpu_sp, MMU_DATA_IDX, MO_UB); + + tcg_gen_deposit_tl(ret, lo, hi, 8, 16); + + tcg_temp_free_i32(lo); + tcg_temp_free_i32(hi); + } +} + +static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) +{ + TranslationBlock *tb = ctx->tb; + + if (ctx->singlestep == 0) { + tcg_gen_goto_tb(n); + tcg_gen_movi_i32(cpu_pc, dest); + tcg_gen_exit_tb(tb, n); + } else { + tcg_gen_movi_i32(cpu_pc, dest); + gen_helper_debug(cpu_env); + tcg_gen_exit_tb(NULL, 0); + } + ctx->bstate = DISAS_NORETURN; +} + +/* + * Relative jump to an address within PC - 2K +1 and PC + 2K (words). For + * AVR microcontrollers with Program memory not exceeding 4K words (8KB) this + * instruction can address the entire memory from every address location. See + * also JMP. + */ +static bool trans_RJMP(DisasContext *ctx, arg_RJMP *a) +{ + int dst = ctx->npc + a->imm; + + gen_goto_tb(ctx, 0, dst); + + return true; +} + +/* + * Indirect jump to the address pointed to by the Z (16 bits) Pointer + * Register in the Register File. The Z-pointer Register is 16 bits wide and + * allows jump within the lowest 64K words (128KB) section of Program memory. + * This instruction is not available in all devices. Refer to the device + * specific instruction set summary. + */ +static bool trans_IJMP(DisasContext *ctx, arg_IJMP *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_IJMP_ICALL)) { + return true; + } + + gen_jmp_z(ctx); + + return true; +} + +/* + * Indirect jump to the address pointed to by the Z (16 bits) Pointer + * Register in the Register File and the EIND Register in the I/O space. This + * instruction allows for indirect jumps to the entire 4M (words) Program + * memory space. See also IJMP. This instruction is not available in all + * devices. Refer to the device specific instruction set summary. + */ +static bool trans_EIJMP(DisasContext *ctx, arg_EIJMP *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_EIJMP_EICALL)) { + return true; + } + + gen_jmp_ez(ctx); + return true; +} + +/* + * Jump to an address within the entire 4M (words) Program memory. See also + * RJMP. This instruction is not available in all devices. Refer to the device + * specific instruction set summary.0 + */ +static bool trans_JMP(DisasContext *ctx, arg_JMP *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_JMP_CALL)) { + return true; + } + + gen_goto_tb(ctx, 0, a->imm); + + return true; +} + +/* + * Relative call to an address within PC - 2K + 1 and PC + 2K (words). The + * return address (the instruction after the RCALL) is stored onto the Stack. + * See also CALL. For AVR microcontrollers with Program memory not exceeding 4K + * words (8KB) this instruction can address the entire memory from every + * address location. The Stack Pointer uses a post-decrement scheme during + * RCALL. + */ +static bool trans_RCALL(DisasContext *ctx, arg_RCALL *a) +{ + int ret = ctx->npc; + int dst = ctx->npc + a->imm; + + gen_push_ret(ctx, ret); + gen_goto_tb(ctx, 0, dst); + + return true; +} + +/* + * Calls to a subroutine within the entire 4M (words) Program memory. The + * return address (to the instruction after the CALL) will be stored onto the + * Stack. See also RCALL. The Stack Pointer uses a post-decrement scheme during + * CALL. This instruction is not available in all devices. Refer to the device + * specific instruction set summary. + */ +static bool trans_ICALL(DisasContext *ctx, arg_ICALL *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_IJMP_ICALL)) { + return true; + } + + int ret = ctx->npc; + + gen_push_ret(ctx, ret); + gen_jmp_z(ctx); + + return true; +} + +/* + * Indirect call of a subroutine pointed to by the Z (16 bits) Pointer + * Register in the Register File and the EIND Register in the I/O space. This + * instruction allows for indirect calls to the entire 4M (words) Program + * memory space. See also ICALL. The Stack Pointer uses a post-decrement scheme + * during EICALL. This instruction is not available in all devices. Refer to + * the device specific instruction set summary. + */ +static bool trans_EICALL(DisasContext *ctx, arg_EICALL *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_EIJMP_EICALL)) { + return true; + } + + int ret = ctx->npc; + + gen_push_ret(ctx, ret); + gen_jmp_ez(ctx); + return true; +} + +/* + * Calls to a subroutine within the entire Program memory. The return + * address (to the instruction after the CALL) will be stored onto the Stack. + * (See also RCALL). The Stack Pointer uses a post-decrement scheme during + * CALL. This instruction is not available in all devices. Refer to the device + * specific instruction set summary. + */ +static bool trans_CALL(DisasContext *ctx, arg_CALL *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_JMP_CALL)) { + return true; + } + + int Imm = a->imm; + int ret = ctx->npc; + + gen_push_ret(ctx, ret); + gen_goto_tb(ctx, 0, Imm); + + return true; +} + +/* + * Returns from subroutine. The return address is loaded from the STACK. + * The Stack Pointer uses a preincrement scheme during RET. + */ +static bool trans_RET(DisasContext *ctx, arg_RET *a) +{ + gen_pop_ret(ctx, cpu_pc); + + ctx->bstate = DISAS_LOOKUP; + return true; +} + +/* + * Returns from interrupt. The return address is loaded from the STACK and + * the Global Interrupt Flag is set. Note that the Status Register is not + * automatically stored when entering an interrupt routine, and it is not + * restored when returning from an interrupt routine. This must be handled by + * the application program. The Stack Pointer uses a pre-increment scheme + * during RETI. + */ +static bool trans_RETI(DisasContext *ctx, arg_RETI *a) +{ + gen_pop_ret(ctx, cpu_pc); + tcg_gen_movi_tl(cpu_If, 1); + + /* Need to return to main loop to re-evaluate interrupts. */ + ctx->bstate = DISAS_EXIT; + return true; +} + +/* + * This instruction performs a compare between two registers Rd and Rr, and + * skips the next instruction if Rd = Rr. + */ +static bool trans_CPSE(DisasContext *ctx, arg_CPSE *a) +{ + ctx->skip_cond = TCG_COND_EQ; + ctx->skip_var0 = cpu_r[a->rd]; + ctx->skip_var1 = cpu_r[a->rr]; + return true; +} + +/* + * This instruction performs a compare between two registers Rd and Rr. + * None of the registers are changed. All conditional branches can be used + * after this instruction. + */ +static bool trans_CP(DisasContext *ctx, arg_CP *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = cpu_r[a->rr]; + TCGv R = tcg_temp_new_i32(); + + tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */ + tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */ + + /* update status register */ + gen_sub_CHf(R, Rd, Rr); + gen_sub_Vf(R, Rd, Rr); + gen_ZNSf(R); + + tcg_temp_free_i32(R); + + return true; +} + +/* + * This instruction performs a compare between two registers Rd and Rr and + * also takes into account the previous carry. None of the registers are + * changed. All conditional branches can be used after this instruction. + */ +static bool trans_CPC(DisasContext *ctx, arg_CPC *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = cpu_r[a->rr]; + TCGv R = tcg_temp_new_i32(); + TCGv zero = tcg_const_i32(0); + + tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */ + tcg_gen_sub_tl(R, R, cpu_Cf); + tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */ + /* update status register */ + gen_sub_CHf(R, Rd, Rr); + gen_sub_Vf(R, Rd, Rr); + gen_NSf(R); + + /* + * Previous value remains unchanged when the result is zero; + * cleared otherwise. + */ + tcg_gen_movcond_tl(TCG_COND_EQ, cpu_Zf, R, zero, cpu_Zf, zero); + + tcg_temp_free_i32(zero); + tcg_temp_free_i32(R); + + return true; +} + +/* + * This instruction performs a compare between register Rd and a constant. + * The register is not changed. All conditional branches can be used after this + * instruction. + */ +static bool trans_CPI(DisasContext *ctx, arg_CPI *a) +{ + TCGv Rd = cpu_r[a->rd]; + int Imm = a->imm; + TCGv Rr = tcg_const_i32(Imm); + TCGv R = tcg_temp_new_i32(); + + tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */ + tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */ + + /* update status register */ + gen_sub_CHf(R, Rd, Rr); + gen_sub_Vf(R, Rd, Rr); + gen_ZNSf(R); + + tcg_temp_free_i32(R); + tcg_temp_free_i32(Rr); + + return true; +} + +/* + * This instruction tests a single bit in a register and skips the next + * instruction if the bit is cleared. + */ +static bool trans_SBRC(DisasContext *ctx, arg_SBRC *a) +{ + TCGv Rr = cpu_r[a->rr]; + + ctx->skip_cond = TCG_COND_EQ; + ctx->skip_var0 = tcg_temp_new(); + ctx->free_skip_var0 = true; + + tcg_gen_andi_tl(ctx->skip_var0, Rr, 1 << a->bit); + return true; +} + +/* + * This instruction tests a single bit in a register and skips the next + * instruction if the bit is set. + */ +static bool trans_SBRS(DisasContext *ctx, arg_SBRS *a) +{ + TCGv Rr = cpu_r[a->rr]; + + ctx->skip_cond = TCG_COND_NE; + ctx->skip_var0 = tcg_temp_new(); + ctx->free_skip_var0 = true; + + tcg_gen_andi_tl(ctx->skip_var0, Rr, 1 << a->bit); + return true; +} + +/* + * This instruction tests a single bit in an I/O Register and skips the + * next instruction if the bit is cleared. This instruction operates on the + * lower 32 I/O Registers -- addresses 0-31. + */ +static bool trans_SBIC(DisasContext *ctx, arg_SBIC *a) +{ + TCGv temp = tcg_const_i32(a->reg); + + gen_helper_inb(temp, cpu_env, temp); + tcg_gen_andi_tl(temp, temp, 1 << a->bit); + ctx->skip_cond = TCG_COND_EQ; + ctx->skip_var0 = temp; + ctx->free_skip_var0 = true; + + return true; +} + +/* + * This instruction tests a single bit in an I/O Register and skips the + * next instruction if the bit is set. This instruction operates on the lower + * 32 I/O Registers -- addresses 0-31. + */ +static bool trans_SBIS(DisasContext *ctx, arg_SBIS *a) +{ + TCGv temp = tcg_const_i32(a->reg); + + gen_helper_inb(temp, cpu_env, temp); + tcg_gen_andi_tl(temp, temp, 1 << a->bit); + ctx->skip_cond = TCG_COND_NE; + ctx->skip_var0 = temp; + ctx->free_skip_var0 = true; + + return true; +} + +/* + * Conditional relative branch. Tests a single bit in SREG and branches + * relatively to PC if the bit is cleared. This instruction branches relatively + * to PC in either direction (PC - 63 < = destination <= PC + 64). The + * parameter k is the offset from PC and is represented in two's complement + * form. + */ +static bool trans_BRBC(DisasContext *ctx, arg_BRBC *a) +{ + TCGLabel *not_taken = gen_new_label(); + + TCGv var; + + switch (a->bit) { + case 0x00: + var = cpu_Cf; + break; + case 0x01: + var = cpu_Zf; + break; + case 0x02: + var = cpu_Nf; + break; + case 0x03: + var = cpu_Vf; + break; + case 0x04: + var = cpu_Sf; + break; + case 0x05: + var = cpu_Hf; + break; + case 0x06: + var = cpu_Tf; + break; + case 0x07: + var = cpu_If; + break; + default: + g_assert_not_reached(); + } + + tcg_gen_brcondi_i32(TCG_COND_NE, var, 0, not_taken); + gen_goto_tb(ctx, 0, ctx->npc + a->imm); + gen_set_label(not_taken); + + ctx->bstate = DISAS_CHAIN; + return true; +} + +/* + * Conditional relative branch. Tests a single bit in SREG and branches + * relatively to PC if the bit is set. This instruction branches relatively to + * PC in either direction (PC - 63 < = destination <= PC + 64). The parameter k + * is the offset from PC and is represented in two's complement form. + */ +static bool trans_BRBS(DisasContext *ctx, arg_BRBS *a) +{ + TCGLabel *not_taken = gen_new_label(); + + TCGv var; + + switch (a->bit) { + case 0x00: + var = cpu_Cf; + break; + case 0x01: + var = cpu_Zf; + break; + case 0x02: + var = cpu_Nf; + break; + case 0x03: + var = cpu_Vf; + break; + case 0x04: + var = cpu_Sf; + break; + case 0x05: + var = cpu_Hf; + break; + case 0x06: + var = cpu_Tf; + break; + case 0x07: + var = cpu_If; + break; + default: + g_assert_not_reached(); + } + + tcg_gen_brcondi_i32(TCG_COND_EQ, var, 0, not_taken); + gen_goto_tb(ctx, 0, ctx->npc + a->imm); + gen_set_label(not_taken); + + ctx->bstate = DISAS_CHAIN; + return true; +} + +/* + * Data Transfer Instructions + */ + +/* + * in the gen_set_addr & gen_get_addr functions + * H assumed to be in 0x00ff0000 format + * M assumed to be in 0x000000ff format + * L assumed to be in 0x000000ff format + */ +static void gen_set_addr(TCGv addr, TCGv H, TCGv M, TCGv L) +{ + + tcg_gen_andi_tl(L, addr, 0x000000ff); + + tcg_gen_andi_tl(M, addr, 0x0000ff00); + tcg_gen_shri_tl(M, M, 8); + + tcg_gen_andi_tl(H, addr, 0x00ff0000); +} + +static void gen_set_xaddr(TCGv addr) +{ + gen_set_addr(addr, cpu_rampX, cpu_r[27], cpu_r[26]); +} + +static void gen_set_yaddr(TCGv addr) +{ + gen_set_addr(addr, cpu_rampY, cpu_r[29], cpu_r[28]); +} + +static void gen_set_zaddr(TCGv addr) +{ + gen_set_addr(addr, cpu_rampZ, cpu_r[31], cpu_r[30]); +} + +static TCGv gen_get_addr(TCGv H, TCGv M, TCGv L) +{ + TCGv addr = tcg_temp_new_i32(); + + tcg_gen_deposit_tl(addr, M, H, 8, 8); + tcg_gen_deposit_tl(addr, L, addr, 8, 16); + + return addr; +} + +static TCGv gen_get_xaddr(void) +{ + return gen_get_addr(cpu_rampX, cpu_r[27], cpu_r[26]); +} + +static TCGv gen_get_yaddr(void) +{ + return gen_get_addr(cpu_rampY, cpu_r[29], cpu_r[28]); +} + +static TCGv gen_get_zaddr(void) +{ + return gen_get_addr(cpu_rampZ, cpu_r[31], cpu_r[30]); +} + +/* + * Load one byte indirect from data space to register and stores an clear + * the bits in data space specified by the register. The instruction can only + * be used towards internal SRAM. The data location is pointed to by the Z (16 + * bits) Pointer Register in the Register File. Memory access is limited to the + * current data segment of 64KB. To access another data segment in devices with + * more than 64KB data space, the RAMPZ in register in the I/O area has to be + * changed. The Z-pointer Register is left unchanged by the operation. This + * instruction is especially suited for clearing status bits stored in SRAM. + */ +static void gen_data_store(DisasContext *ctx, TCGv data, TCGv addr) +{ + if (ctx->tb->flags & TB_FLAGS_FULL_ACCESS) { + gen_helper_fullwr(cpu_env, data, addr); + } else { + tcg_gen_qemu_st8(data, addr, MMU_DATA_IDX); /* mem[addr] = data */ + } +} + +static void gen_data_load(DisasContext *ctx, TCGv data, TCGv addr) +{ + if (ctx->tb->flags & TB_FLAGS_FULL_ACCESS) { + gen_helper_fullrd(data, cpu_env, addr); + } else { + tcg_gen_qemu_ld8u(data, addr, MMU_DATA_IDX); /* data = mem[addr] */ + } +} + +/* + * This instruction makes a copy of one register into another. The source + * register Rr is left unchanged, while the destination register Rd is loaded + * with a copy of Rr. + */ +static bool trans_MOV(DisasContext *ctx, arg_MOV *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv Rr = cpu_r[a->rr]; + + tcg_gen_mov_tl(Rd, Rr); + + return true; +} + +/* + * This instruction makes a copy of one register pair into another register + * pair. The source register pair Rr+1:Rr is left unchanged, while the + * destination register pair Rd+1:Rd is loaded with a copy of Rr + 1:Rr. This + * instruction is not available in all devices. Refer to the device specific + * instruction set summary. + */ +static bool trans_MOVW(DisasContext *ctx, arg_MOVW *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_MOVW)) { + return true; + } + + TCGv RdL = cpu_r[a->rd]; + TCGv RdH = cpu_r[a->rd + 1]; + TCGv RrL = cpu_r[a->rr]; + TCGv RrH = cpu_r[a->rr + 1]; + + tcg_gen_mov_tl(RdH, RrH); + tcg_gen_mov_tl(RdL, RrL); + + return true; +} + +/* + * Loads an 8 bit constant directly to register 16 to 31. + */ +static bool trans_LDI(DisasContext *ctx, arg_LDI *a) +{ + TCGv Rd = cpu_r[a->rd]; + int imm = a->imm; + + tcg_gen_movi_tl(Rd, imm); + + return true; +} + +/* + * Loads one byte from the data space to a register. For parts with SRAM, + * the data space consists of the Register File, I/O memory and internal SRAM + * (and external SRAM if applicable). For parts without SRAM, the data space + * consists of the register file only. The EEPROM has a separate address space. + * A 16-bit address must be supplied. Memory access is limited to the current + * data segment of 64KB. The LDS instruction uses the RAMPD Register to access + * memory above 64KB. To access another data segment in devices with more than + * 64KB data space, the RAMPD in register in the I/O area has to be changed. + * This instruction is not available in all devices. Refer to the device + * specific instruction set summary. + */ +static bool trans_LDS(DisasContext *ctx, arg_LDS *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv addr = tcg_temp_new_i32(); + TCGv H = cpu_rampD; + a->imm = next_word(ctx); + + tcg_gen_mov_tl(addr, H); /* addr = H:M:L */ + tcg_gen_shli_tl(addr, addr, 16); + tcg_gen_ori_tl(addr, addr, a->imm); + + gen_data_load(ctx, Rd, addr); + + tcg_temp_free_i32(addr); + + return true; +} + +/* + * Loads one byte indirect from the data space to a register. For parts + * with SRAM, the data space consists of the Register File, I/O memory and + * internal SRAM (and external SRAM if applicable). For parts without SRAM, the + * data space consists of the Register File only. In some parts the Flash + * Memory has been mapped to the data space and can be read using this command. + * The EEPROM has a separate address space. The data location is pointed to by + * the X (16 bits) Pointer Register in the Register File. Memory access is + * limited to the current data segment of 64KB. To access another data segment + * in devices with more than 64KB data space, the RAMPX in register in the I/O + * area has to be changed. The X-pointer Register can either be left unchanged + * by the operation, or it can be post-incremented or predecremented. These + * features are especially suited for accessing arrays, tables, and Stack + * Pointer usage of the X-pointer Register. Note that only the low byte of the + * X-pointer is updated in devices with no more than 256 bytes data space. For + * such devices, the high byte of the pointer is not used by this instruction + * and can be used for other purposes. The RAMPX Register in the I/O area is + * updated in parts with more than 64KB data space or more than 64KB Program + * memory, and the increment/decrement is added to the entire 24-bit address on + * such devices. Not all variants of this instruction is available in all + * devices. Refer to the device specific instruction set summary. In the + * Reduced Core tinyAVR the LD instruction can be used to achieve the same + * operation as LPM since the program memory is mapped to the data memory + * space. + */ +static bool trans_LDX1(DisasContext *ctx, arg_LDX1 *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_xaddr(); + + gen_data_load(ctx, Rd, addr); + + tcg_temp_free_i32(addr); + + return true; +} + +static bool trans_LDX2(DisasContext *ctx, arg_LDX2 *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_xaddr(); + + gen_data_load(ctx, Rd, addr); + tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */ + + gen_set_xaddr(addr); + + tcg_temp_free_i32(addr); + + return true; +} + +static bool trans_LDX3(DisasContext *ctx, arg_LDX3 *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_xaddr(); + + tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */ + gen_data_load(ctx, Rd, addr); + gen_set_xaddr(addr); + + tcg_temp_free_i32(addr); + + return true; +} + +/* + * Loads one byte indirect with or without displacement from the data space + * to a register. For parts with SRAM, the data space consists of the Register + * File, I/O memory and internal SRAM (and external SRAM if applicable). For + * parts without SRAM, the data space consists of the Register File only. In + * some parts the Flash Memory has been mapped to the data space and can be + * read using this command. The EEPROM has a separate address space. The data + * location is pointed to by the Y (16 bits) Pointer Register in the Register + * File. Memory access is limited to the current data segment of 64KB. To + * access another data segment in devices with more than 64KB data space, the + * RAMPY in register in the I/O area has to be changed. The Y-pointer Register + * can either be left unchanged by the operation, or it can be post-incremented + * or predecremented. These features are especially suited for accessing + * arrays, tables, and Stack Pointer usage of the Y-pointer Register. Note that + * only the low byte of the Y-pointer is updated in devices with no more than + * 256 bytes data space. For such devices, the high byte of the pointer is not + * used by this instruction and can be used for other purposes. The RAMPY + * Register in the I/O area is updated in parts with more than 64KB data space + * or more than 64KB Program memory, and the increment/decrement/displacement + * is added to the entire 24-bit address on such devices. Not all variants of + * this instruction is available in all devices. Refer to the device specific + * instruction set summary. In the Reduced Core tinyAVR the LD instruction can + * be used to achieve the same operation as LPM since the program memory is + * mapped to the data memory space. + */ +static bool trans_LDY2(DisasContext *ctx, arg_LDY2 *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_yaddr(); + + gen_data_load(ctx, Rd, addr); + tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */ + + gen_set_yaddr(addr); + + tcg_temp_free_i32(addr); + + return true; +} + +static bool trans_LDY3(DisasContext *ctx, arg_LDY3 *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_yaddr(); + + tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */ + gen_data_load(ctx, Rd, addr); + gen_set_yaddr(addr); + + tcg_temp_free_i32(addr); + + return true; +} + +static bool trans_LDDY(DisasContext *ctx, arg_LDDY *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_yaddr(); + + tcg_gen_addi_tl(addr, addr, a->imm); /* addr = addr + q */ + gen_data_load(ctx, Rd, addr); + + tcg_temp_free_i32(addr); + + return true; +} + +/* + * Loads one byte indirect with or without displacement from the data space + * to a register. For parts with SRAM, the data space consists of the Register + * File, I/O memory and internal SRAM (and external SRAM if applicable). For + * parts without SRAM, the data space consists of the Register File only. In + * some parts the Flash Memory has been mapped to the data space and can be + * read using this command. The EEPROM has a separate address space. The data + * location is pointed to by the Z (16 bits) Pointer Register in the Register + * File. Memory access is limited to the current data segment of 64KB. To + * access another data segment in devices with more than 64KB data space, the + * RAMPZ in register in the I/O area has to be changed. The Z-pointer Register + * can either be left unchanged by the operation, or it can be post-incremented + * or predecremented. These features are especially suited for Stack Pointer + * usage of the Z-pointer Register, however because the Z-pointer Register can + * be used for indirect subroutine calls, indirect jumps and table lookup, it + * is often more convenient to use the X or Y-pointer as a dedicated Stack + * Pointer. Note that only the low byte of the Z-pointer is updated in devices + * with no more than 256 bytes data space. For such devices, the high byte of + * the pointer is not used by this instruction and can be used for other + * purposes. The RAMPZ Register in the I/O area is updated in parts with more + * than 64KB data space or more than 64KB Program memory, and the + * increment/decrement/displacement is added to the entire 24-bit address on + * such devices. Not all variants of this instruction is available in all + * devices. Refer to the device specific instruction set summary. In the + * Reduced Core tinyAVR the LD instruction can be used to achieve the same + * operation as LPM since the program memory is mapped to the data memory + * space. For using the Z-pointer for table lookup in Program memory see the + * LPM and ELPM instructions. + */ +static bool trans_LDZ2(DisasContext *ctx, arg_LDZ2 *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_zaddr(); + + gen_data_load(ctx, Rd, addr); + tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */ + + gen_set_zaddr(addr); + + tcg_temp_free_i32(addr); + + return true; +} + +static bool trans_LDZ3(DisasContext *ctx, arg_LDZ3 *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_zaddr(); + + tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */ + gen_data_load(ctx, Rd, addr); + + gen_set_zaddr(addr); + + tcg_temp_free_i32(addr); + + return true; +} + +static bool trans_LDDZ(DisasContext *ctx, arg_LDDZ *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_zaddr(); + + tcg_gen_addi_tl(addr, addr, a->imm); /* addr = addr + q */ + gen_data_load(ctx, Rd, addr); + + tcg_temp_free_i32(addr); + + return true; +} + +/* + * Stores one byte from a Register to the data space. For parts with SRAM, + * the data space consists of the Register File, I/O memory and internal SRAM + * (and external SRAM if applicable). For parts without SRAM, the data space + * consists of the Register File only. The EEPROM has a separate address space. + * A 16-bit address must be supplied. Memory access is limited to the current + * data segment of 64KB. The STS instruction uses the RAMPD Register to access + * memory above 64KB. To access another data segment in devices with more than + * 64KB data space, the RAMPD in register in the I/O area has to be changed. + * This instruction is not available in all devices. Refer to the device + * specific instruction set summary. + */ +static bool trans_STS(DisasContext *ctx, arg_STS *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv addr = tcg_temp_new_i32(); + TCGv H = cpu_rampD; + a->imm = next_word(ctx); + + tcg_gen_mov_tl(addr, H); /* addr = H:M:L */ + tcg_gen_shli_tl(addr, addr, 16); + tcg_gen_ori_tl(addr, addr, a->imm); + gen_data_store(ctx, Rd, addr); + + tcg_temp_free_i32(addr); + + return true; +} + +/* + * Stores one byte indirect from a register to data space. For parts with SRAM, + * the data space consists of the Register File, I/O memory, and internal SRAM + * (and external SRAM if applicable). For parts without SRAM, the data space + * consists of the Register File only. The EEPROM has a separate address space. + * + * The data location is pointed to by the X (16 bits) Pointer Register in the + * Register File. Memory access is limited to the current data segment of 64KB. + * To access another data segment in devices with more than 64KB data space, the + * RAMPX in register in the I/O area has to be changed. + * + * The X-pointer Register can either be left unchanged by the operation, or it + * can be post-incremented or pre-decremented. These features are especially + * suited for accessing arrays, tables, and Stack Pointer usage of the + * X-pointer Register. Note that only the low byte of the X-pointer is updated + * in devices with no more than 256 bytes data space. For such devices, the high + * byte of the pointer is not used by this instruction and can be used for other + * purposes. The RAMPX Register in the I/O area is updated in parts with more + * than 64KB data space or more than 64KB Program memory, and the increment / + * decrement is added to the entire 24-bit address on such devices. + */ +static bool trans_STX1(DisasContext *ctx, arg_STX1 *a) +{ + TCGv Rd = cpu_r[a->rr]; + TCGv addr = gen_get_xaddr(); + + gen_data_store(ctx, Rd, addr); + + tcg_temp_free_i32(addr); + + return true; +} + +static bool trans_STX2(DisasContext *ctx, arg_STX2 *a) +{ + TCGv Rd = cpu_r[a->rr]; + TCGv addr = gen_get_xaddr(); + + gen_data_store(ctx, Rd, addr); + tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */ + gen_set_xaddr(addr); + + tcg_temp_free_i32(addr); + + return true; +} + +static bool trans_STX3(DisasContext *ctx, arg_STX3 *a) +{ + TCGv Rd = cpu_r[a->rr]; + TCGv addr = gen_get_xaddr(); + + tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */ + gen_data_store(ctx, Rd, addr); + gen_set_xaddr(addr); + + tcg_temp_free_i32(addr); + + return true; +} + +/* + * Stores one byte indirect with or without displacement from a register to data + * space. For parts with SRAM, the data space consists of the Register File, I/O + * memory, and internal SRAM (and external SRAM if applicable). For parts + * without SRAM, the data space consists of the Register File only. The EEPROM + * has a separate address space. + * + * The data location is pointed to by the Y (16 bits) Pointer Register in the + * Register File. Memory access is limited to the current data segment of 64KB. + * To access another data segment in devices with more than 64KB data space, the + * RAMPY in register in the I/O area has to be changed. + * + * The Y-pointer Register can either be left unchanged by the operation, or it + * can be post-incremented or pre-decremented. These features are especially + * suited for accessing arrays, tables, and Stack Pointer usage of the Y-pointer + * Register. Note that only the low byte of the Y-pointer is updated in devices + * with no more than 256 bytes data space. For such devices, the high byte of + * the pointer is not used by this instruction and can be used for other + * purposes. The RAMPY Register in the I/O area is updated in parts with more + * than 64KB data space or more than 64KB Program memory, and the increment / + * decrement / displacement is added to the entire 24-bit address on such + * devices. + */ +static bool trans_STY2(DisasContext *ctx, arg_STY2 *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_yaddr(); + + gen_data_store(ctx, Rd, addr); + tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */ + gen_set_yaddr(addr); + + tcg_temp_free_i32(addr); + + return true; +} + +static bool trans_STY3(DisasContext *ctx, arg_STY3 *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_yaddr(); + + tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */ + gen_data_store(ctx, Rd, addr); + gen_set_yaddr(addr); + + tcg_temp_free_i32(addr); + + return true; +} + +static bool trans_STDY(DisasContext *ctx, arg_STDY *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_yaddr(); + + tcg_gen_addi_tl(addr, addr, a->imm); /* addr = addr + q */ + gen_data_store(ctx, Rd, addr); + + tcg_temp_free_i32(addr); + + return true; +} + +/* + * Stores one byte indirect with or without displacement from a register to data + * space. For parts with SRAM, the data space consists of the Register File, I/O + * memory, and internal SRAM (and external SRAM if applicable). For parts + * without SRAM, the data space consists of the Register File only. The EEPROM + * has a separate address space. + * + * The data location is pointed to by the Y (16 bits) Pointer Register in the + * Register File. Memory access is limited to the current data segment of 64KB. + * To access another data segment in devices with more than 64KB data space, the + * RAMPY in register in the I/O area has to be changed. + * + * The Y-pointer Register can either be left unchanged by the operation, or it + * can be post-incremented or pre-decremented. These features are especially + * suited for accessing arrays, tables, and Stack Pointer usage of the Y-pointer + * Register. Note that only the low byte of the Y-pointer is updated in devices + * with no more than 256 bytes data space. For such devices, the high byte of + * the pointer is not used by this instruction and can be used for other + * purposes. The RAMPY Register in the I/O area is updated in parts with more + * than 64KB data space or more than 64KB Program memory, and the increment / + * decrement / displacement is added to the entire 24-bit address on such + * devices. + */ +static bool trans_STZ2(DisasContext *ctx, arg_STZ2 *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_zaddr(); + + gen_data_store(ctx, Rd, addr); + tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */ + + gen_set_zaddr(addr); + + tcg_temp_free_i32(addr); + + return true; +} + +static bool trans_STZ3(DisasContext *ctx, arg_STZ3 *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_zaddr(); + + tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */ + gen_data_store(ctx, Rd, addr); + + gen_set_zaddr(addr); + + tcg_temp_free_i32(addr); + + return true; +} + +static bool trans_STDZ(DisasContext *ctx, arg_STDZ *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_zaddr(); + + tcg_gen_addi_tl(addr, addr, a->imm); /* addr = addr + q */ + gen_data_store(ctx, Rd, addr); + + tcg_temp_free_i32(addr); + + return true; +} + +/* + * Loads one byte pointed to by the Z-register into the destination + * register Rd. This instruction features a 100% space effective constant + * initialization or constant data fetch. The Program memory is organized in + * 16-bit words while the Z-pointer is a byte address. Thus, the least + * significant bit of the Z-pointer selects either low byte (ZLSB = 0) or high + * byte (ZLSB = 1). This instruction can address the first 64KB (32K words) of + * Program memory. The Zpointer Register can either be left unchanged by the + * operation, or it can be incremented. The incrementation does not apply to + * the RAMPZ Register. + * + * Devices with Self-Programming capability can use the LPM instruction to read + * the Fuse and Lock bit values. + */ +static bool trans_LPM1(DisasContext *ctx, arg_LPM1 *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_LPM)) { + return true; + } + + TCGv Rd = cpu_r[0]; + TCGv addr = tcg_temp_new_i32(); + TCGv H = cpu_r[31]; + TCGv L = cpu_r[30]; + + tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */ + tcg_gen_or_tl(addr, addr, L); + tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */ + + tcg_temp_free_i32(addr); + + return true; +} + +static bool trans_LPM2(DisasContext *ctx, arg_LPM2 *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_LPM)) { + return true; + } + + TCGv Rd = cpu_r[a->rd]; + TCGv addr = tcg_temp_new_i32(); + TCGv H = cpu_r[31]; + TCGv L = cpu_r[30]; + + tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */ + tcg_gen_or_tl(addr, addr, L); + tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */ + + tcg_temp_free_i32(addr); + + return true; +} + +static bool trans_LPMX(DisasContext *ctx, arg_LPMX *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_LPMX)) { + return true; + } + + TCGv Rd = cpu_r[a->rd]; + TCGv addr = tcg_temp_new_i32(); + TCGv H = cpu_r[31]; + TCGv L = cpu_r[30]; + + tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */ + tcg_gen_or_tl(addr, addr, L); + tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */ + tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */ + tcg_gen_andi_tl(L, addr, 0xff); + tcg_gen_shri_tl(addr, addr, 8); + tcg_gen_andi_tl(H, addr, 0xff); + + tcg_temp_free_i32(addr); + + return true; +} + +/* + * Loads one byte pointed to by the Z-register and the RAMPZ Register in + * the I/O space, and places this byte in the destination register Rd. This + * instruction features a 100% space effective constant initialization or + * constant data fetch. The Program memory is organized in 16-bit words while + * the Z-pointer is a byte address. Thus, the least significant bit of the + * Z-pointer selects either low byte (ZLSB = 0) or high byte (ZLSB = 1). This + * instruction can address the entire Program memory space. The Z-pointer + * Register can either be left unchanged by the operation, or it can be + * incremented. The incrementation applies to the entire 24-bit concatenation + * of the RAMPZ and Z-pointer Registers. + * + * Devices with Self-Programming capability can use the ELPM instruction to + * read the Fuse and Lock bit value. + */ +static bool trans_ELPM1(DisasContext *ctx, arg_ELPM1 *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_ELPM)) { + return true; + } + + TCGv Rd = cpu_r[0]; + TCGv addr = gen_get_zaddr(); + + tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */ + + tcg_temp_free_i32(addr); + + return true; +} + +static bool trans_ELPM2(DisasContext *ctx, arg_ELPM2 *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_ELPM)) { + return true; + } + + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_zaddr(); + + tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */ + + tcg_temp_free_i32(addr); + + return true; +} + +static bool trans_ELPMX(DisasContext *ctx, arg_ELPMX *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_ELPMX)) { + return true; + } + + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_zaddr(); + + tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */ + tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */ + gen_set_zaddr(addr); + + tcg_temp_free_i32(addr); + + return true; +} + +/* + * SPM can be used to erase a page in the Program memory, to write a page + * in the Program memory (that is already erased), and to set Boot Loader Lock + * bits. In some devices, the Program memory can be written one word at a time, + * in other devices an entire page can be programmed simultaneously after first + * filling a temporary page buffer. In all cases, the Program memory must be + * erased one page at a time. When erasing the Program memory, the RAMPZ and + * Z-register are used as page address. When writing the Program memory, the + * RAMPZ and Z-register are used as page or word address, and the R1:R0 + * register pair is used as data(1). When setting the Boot Loader Lock bits, + * the R1:R0 register pair is used as data. Refer to the device documentation + * for detailed description of SPM usage. This instruction can address the + * entire Program memory. + * + * The SPM instruction is not available in all devices. Refer to the device + * specific instruction set summary. + * + * Note: 1. R1 determines the instruction high byte, and R0 determines the + * instruction low byte. + */ +static bool trans_SPM(DisasContext *ctx, arg_SPM *a) +{ + /* TODO */ + if (!avr_have_feature(ctx, AVR_FEATURE_SPM)) { + return true; + } + + return true; +} + +static bool trans_SPMX(DisasContext *ctx, arg_SPMX *a) +{ + /* TODO */ + if (!avr_have_feature(ctx, AVR_FEATURE_SPMX)) { + return true; + } + + return true; +} + +/* + * Loads data from the I/O Space (Ports, Timers, Configuration Registers, + * etc.) into register Rd in the Register File. + */ +static bool trans_IN(DisasContext *ctx, arg_IN *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv port = tcg_const_i32(a->imm); + + gen_helper_inb(Rd, cpu_env, port); + + tcg_temp_free_i32(port); + + return true; +} + +/* + * Stores data from register Rr in the Register File to I/O Space (Ports, + * Timers, Configuration Registers, etc.). + */ +static bool trans_OUT(DisasContext *ctx, arg_OUT *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv port = tcg_const_i32(a->imm); + + gen_helper_outb(cpu_env, port, Rd); + + tcg_temp_free_i32(port); + + return true; +} + +/* + * This instruction stores the contents of register Rr on the STACK. The + * Stack Pointer is post-decremented by 1 after the PUSH. This instruction is + * not available in all devices. Refer to the device specific instruction set + * summary. + */ +static bool trans_PUSH(DisasContext *ctx, arg_PUSH *a) +{ + TCGv Rd = cpu_r[a->rd]; + + gen_data_store(ctx, Rd, cpu_sp); + tcg_gen_subi_tl(cpu_sp, cpu_sp, 1); + + return true; +} + +/* + * This instruction loads register Rd with a byte from the STACK. The Stack + * Pointer is pre-incremented by 1 before the POP. This instruction is not + * available in all devices. Refer to the device specific instruction set + * summary. + */ +static bool trans_POP(DisasContext *ctx, arg_POP *a) +{ + /* + * Using a temp to work around some strange behaviour: + * tcg_gen_addi_tl(cpu_sp, cpu_sp, 1); + * gen_data_load(ctx, Rd, cpu_sp); + * seems to cause the add to happen twice. + * This doesn't happen if either the add or the load is removed. + */ + TCGv t1 = tcg_temp_new_i32(); + TCGv Rd = cpu_r[a->rd]; + + tcg_gen_addi_tl(t1, cpu_sp, 1); + gen_data_load(ctx, Rd, t1); + tcg_gen_mov_tl(cpu_sp, t1); + + return true; +} + +/* + * Exchanges one byte indirect between register and data space. The data + * location is pointed to by the Z (16 bits) Pointer Register in the Register + * File. Memory access is limited to the current data segment of 64KB. To + * access another data segment in devices with more than 64KB data space, the + * RAMPZ in register in the I/O area has to be changed. + * + * The Z-pointer Register is left unchanged by the operation. This instruction + * is especially suited for writing/reading status bits stored in SRAM. + */ +static bool trans_XCH(DisasContext *ctx, arg_XCH *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_RMW)) { + return true; + } + + TCGv Rd = cpu_r[a->rd]; + TCGv t0 = tcg_temp_new_i32(); + TCGv addr = gen_get_zaddr(); + + gen_data_load(ctx, t0, addr); + gen_data_store(ctx, Rd, addr); + tcg_gen_mov_tl(Rd, t0); + + tcg_temp_free_i32(t0); + tcg_temp_free_i32(addr); + + return true; +} + +/* + * Load one byte indirect from data space to register and set bits in data + * space specified by the register. The instruction can only be used towards + * internal SRAM. The data location is pointed to by the Z (16 bits) Pointer + * Register in the Register File. Memory access is limited to the current data + * segment of 64KB. To access another data segment in devices with more than + * 64KB data space, the RAMPZ in register in the I/O area has to be changed. + * + * The Z-pointer Register is left unchanged by the operation. This instruction + * is especially suited for setting status bits stored in SRAM. + */ +static bool trans_LAS(DisasContext *ctx, arg_LAS *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_RMW)) { + return true; + } + + TCGv Rr = cpu_r[a->rd]; + TCGv addr = gen_get_zaddr(); + TCGv t0 = tcg_temp_new_i32(); + TCGv t1 = tcg_temp_new_i32(); + + gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */ + tcg_gen_or_tl(t1, t0, Rr); + tcg_gen_mov_tl(Rr, t0); /* Rr = t0 */ + gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */ + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); + tcg_temp_free_i32(addr); + + return true; +} + +/* + * Load one byte indirect from data space to register and stores and clear + * the bits in data space specified by the register. The instruction can + * only be used towards internal SRAM. The data location is pointed to by + * the Z (16 bits) Pointer Register in the Register File. Memory access is + * limited to the current data segment of 64KB. To access another data + * segment in devices with more than 64KB data space, the RAMPZ in register + * in the I/O area has to be changed. + * + * The Z-pointer Register is left unchanged by the operation. This instruction + * is especially suited for clearing status bits stored in SRAM. + */ +static bool trans_LAC(DisasContext *ctx, arg_LAC *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_RMW)) { + return true; + } + + TCGv Rr = cpu_r[a->rd]; + TCGv addr = gen_get_zaddr(); + TCGv t0 = tcg_temp_new_i32(); + TCGv t1 = tcg_temp_new_i32(); + + gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */ + tcg_gen_andc_tl(t1, t0, Rr); /* t1 = t0 & (0xff - Rr) = t0 & ~Rr */ + tcg_gen_mov_tl(Rr, t0); /* Rr = t0 */ + gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */ + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); + tcg_temp_free_i32(addr); + + return true; +} + + +/* + * Load one byte indirect from data space to register and toggles bits in + * the data space specified by the register. The instruction can only be used + * towards SRAM. The data location is pointed to by the Z (16 bits) Pointer + * Register in the Register File. Memory access is limited to the current data + * segment of 64KB. To access another data segment in devices with more than + * 64KB data space, the RAMPZ in register in the I/O area has to be changed. + * + * The Z-pointer Register is left unchanged by the operation. This instruction + * is especially suited for changing status bits stored in SRAM. + */ +static bool trans_LAT(DisasContext *ctx, arg_LAT *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_RMW)) { + return true; + } + + TCGv Rd = cpu_r[a->rd]; + TCGv addr = gen_get_zaddr(); + TCGv t0 = tcg_temp_new_i32(); + TCGv t1 = tcg_temp_new_i32(); + + gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */ + tcg_gen_xor_tl(t1, t0, Rd); + tcg_gen_mov_tl(Rd, t0); /* Rd = t0 */ + gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */ + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); + tcg_temp_free_i32(addr); + + return true; +} + +/* + * Bit and Bit-test Instructions + */ +static void gen_rshift_ZNVSf(TCGv R) +{ + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0); /* Zf = R == 0 */ + tcg_gen_shri_tl(cpu_Nf, R, 7); /* Nf = R(7) */ + tcg_gen_xor_tl(cpu_Vf, cpu_Nf, cpu_Cf); + tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */ +} + +/* + * Shifts all bits in Rd one place to the right. Bit 7 is cleared. Bit 0 is + * loaded into the C Flag of the SREG. This operation effectively divides an + * unsigned value by two. The C Flag can be used to round the result. + */ +static bool trans_LSR(DisasContext *ctx, arg_LSR *a) +{ + TCGv Rd = cpu_r[a->rd]; + + tcg_gen_andi_tl(cpu_Cf, Rd, 1); + tcg_gen_shri_tl(Rd, Rd, 1); + + /* update status register */ + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, Rd, 0); /* Zf = Rd == 0 */ + tcg_gen_movi_tl(cpu_Nf, 0); + tcg_gen_mov_tl(cpu_Vf, cpu_Cf); + tcg_gen_mov_tl(cpu_Sf, cpu_Vf); + + return true; +} + +/* + * Shifts all bits in Rd one place to the right. The C Flag is shifted into + * bit 7 of Rd. Bit 0 is shifted into the C Flag. This operation, combined + * with ASR, effectively divides multi-byte signed values by two. Combined with + * LSR it effectively divides multi-byte unsigned values by two. The Carry Flag + * can be used to round the result. + */ +static bool trans_ROR(DisasContext *ctx, arg_ROR *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv t0 = tcg_temp_new_i32(); + + tcg_gen_shli_tl(t0, cpu_Cf, 7); + + /* update status register */ + tcg_gen_andi_tl(cpu_Cf, Rd, 1); + + /* update output register */ + tcg_gen_shri_tl(Rd, Rd, 1); + tcg_gen_or_tl(Rd, Rd, t0); + + /* update status register */ + gen_rshift_ZNVSf(Rd); + + tcg_temp_free_i32(t0); + + return true; +} + +/* + * Shifts all bits in Rd one place to the right. Bit 7 is held constant. Bit 0 + * is loaded into the C Flag of the SREG. This operation effectively divides a + * signed value by two without changing its sign. The Carry Flag can be used to + * round the result. + */ +static bool trans_ASR(DisasContext *ctx, arg_ASR *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv t0 = tcg_temp_new_i32(); + + /* update status register */ + tcg_gen_andi_tl(cpu_Cf, Rd, 1); /* Cf = Rd(0) */ + + /* update output register */ + tcg_gen_andi_tl(t0, Rd, 0x80); /* Rd = (Rd & 0x80) | (Rd >> 1) */ + tcg_gen_shri_tl(Rd, Rd, 1); + tcg_gen_or_tl(Rd, Rd, t0); + + /* update status register */ + gen_rshift_ZNVSf(Rd); + + tcg_temp_free_i32(t0); + + return true; +} + +/* + * Swaps high and low nibbles in a register. + */ +static bool trans_SWAP(DisasContext *ctx, arg_SWAP *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv t0 = tcg_temp_new_i32(); + TCGv t1 = tcg_temp_new_i32(); + + tcg_gen_andi_tl(t0, Rd, 0x0f); + tcg_gen_shli_tl(t0, t0, 4); + tcg_gen_andi_tl(t1, Rd, 0xf0); + tcg_gen_shri_tl(t1, t1, 4); + tcg_gen_or_tl(Rd, t0, t1); + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); + + return true; +} + +/* + * Sets a specified bit in an I/O Register. This instruction operates on + * the lower 32 I/O Registers -- addresses 0-31. + */ +static bool trans_SBI(DisasContext *ctx, arg_SBI *a) +{ + TCGv data = tcg_temp_new_i32(); + TCGv port = tcg_const_i32(a->reg); + + gen_helper_inb(data, cpu_env, port); + tcg_gen_ori_tl(data, data, 1 << a->bit); + gen_helper_outb(cpu_env, port, data); + + tcg_temp_free_i32(port); + tcg_temp_free_i32(data); + + return true; +} + +/* + * Clears a specified bit in an I/O Register. This instruction operates on + * the lower 32 I/O Registers -- addresses 0-31. + */ +static bool trans_CBI(DisasContext *ctx, arg_CBI *a) +{ + TCGv data = tcg_temp_new_i32(); + TCGv port = tcg_const_i32(a->reg); + + gen_helper_inb(data, cpu_env, port); + tcg_gen_andi_tl(data, data, ~(1 << a->bit)); + gen_helper_outb(cpu_env, port, data); + + tcg_temp_free_i32(data); + tcg_temp_free_i32(port); + + return true; +} + +/* + * Stores bit b from Rd to the T Flag in SREG (Status Register). + */ +static bool trans_BST(DisasContext *ctx, arg_BST *a) +{ + TCGv Rd = cpu_r[a->rd]; + + tcg_gen_andi_tl(cpu_Tf, Rd, 1 << a->bit); + tcg_gen_shri_tl(cpu_Tf, cpu_Tf, a->bit); + + return true; +} + +/* + * Copies the T Flag in the SREG (Status Register) to bit b in register Rd. + */ +static bool trans_BLD(DisasContext *ctx, arg_BLD *a) +{ + TCGv Rd = cpu_r[a->rd]; + TCGv t1 = tcg_temp_new_i32(); + + tcg_gen_andi_tl(Rd, Rd, ~(1u << a->bit)); /* clear bit */ + tcg_gen_shli_tl(t1, cpu_Tf, a->bit); /* create mask */ + tcg_gen_or_tl(Rd, Rd, t1); + + tcg_temp_free_i32(t1); + + return true; +} + +/* + * Sets a single Flag or bit in SREG. + */ +static bool trans_BSET(DisasContext *ctx, arg_BSET *a) +{ + switch (a->bit) { + case 0x00: + tcg_gen_movi_tl(cpu_Cf, 0x01); + break; + case 0x01: + tcg_gen_movi_tl(cpu_Zf, 0x01); + break; + case 0x02: + tcg_gen_movi_tl(cpu_Nf, 0x01); + break; + case 0x03: + tcg_gen_movi_tl(cpu_Vf, 0x01); + break; + case 0x04: + tcg_gen_movi_tl(cpu_Sf, 0x01); + break; + case 0x05: + tcg_gen_movi_tl(cpu_Hf, 0x01); + break; + case 0x06: + tcg_gen_movi_tl(cpu_Tf, 0x01); + break; + case 0x07: + tcg_gen_movi_tl(cpu_If, 0x01); + break; + } + + return true; +} + +/* + * Clears a single Flag in SREG. + */ +static bool trans_BCLR(DisasContext *ctx, arg_BCLR *a) +{ + switch (a->bit) { + case 0x00: + tcg_gen_movi_tl(cpu_Cf, 0x00); + break; + case 0x01: + tcg_gen_movi_tl(cpu_Zf, 0x00); + break; + case 0x02: + tcg_gen_movi_tl(cpu_Nf, 0x00); + break; + case 0x03: + tcg_gen_movi_tl(cpu_Vf, 0x00); + break; + case 0x04: + tcg_gen_movi_tl(cpu_Sf, 0x00); + break; + case 0x05: + tcg_gen_movi_tl(cpu_Hf, 0x00); + break; + case 0x06: + tcg_gen_movi_tl(cpu_Tf, 0x00); + break; + case 0x07: + tcg_gen_movi_tl(cpu_If, 0x00); + break; + } + + return true; +} + +/* + * MCU Control Instructions + */ + +/* + * The BREAK instruction is used by the On-chip Debug system, and is + * normally not used in the application software. When the BREAK instruction is + * executed, the AVR CPU is set in the Stopped Mode. This gives the On-chip + * Debugger access to internal resources. If any Lock bits are set, or either + * the JTAGEN or OCDEN Fuses are unprogrammed, the CPU will treat the BREAK + * instruction as a NOP and will not enter the Stopped mode. This instruction + * is not available in all devices. Refer to the device specific instruction + * set summary. + */ +static bool trans_BREAK(DisasContext *ctx, arg_BREAK *a) +{ + if (!avr_have_feature(ctx, AVR_FEATURE_BREAK)) { + return true; + } + +#ifdef BREAKPOINT_ON_BREAK + tcg_gen_movi_tl(cpu_pc, ctx->npc - 1); + gen_helper_debug(cpu_env); + ctx->bstate = DISAS_EXIT; +#else + /* NOP */ +#endif + + return true; +} + +/* + * This instruction performs a single cycle No Operation. + */ +static bool trans_NOP(DisasContext *ctx, arg_NOP *a) +{ + + /* NOP */ + + return true; +} + +/* + * This instruction sets the circuit in sleep mode defined by the MCU + * Control Register. + */ +static bool trans_SLEEP(DisasContext *ctx, arg_SLEEP *a) +{ + gen_helper_sleep(cpu_env); + ctx->bstate = DISAS_NORETURN; + return true; +} + +/* + * This instruction resets the Watchdog Timer. This instruction must be + * executed within a limited time given by the WD prescaler. See the Watchdog + * Timer hardware specification. + */ +static bool trans_WDR(DisasContext *ctx, arg_WDR *a) +{ + gen_helper_wdr(cpu_env); + + return true; +} + +/* + * Core translation mechanism functions: + * + * - translate() + * - canonicalize_skip() + * - gen_intermediate_code() + * - restore_state_to_opc() + * + */ +static void translate(DisasContext *ctx) +{ + uint32_t opcode = next_word(ctx); + + if (!decode_insn(ctx, opcode)) { + gen_helper_unsupported(cpu_env); + ctx->bstate = DISAS_NORETURN; + } +} + +/* Standardize the cpu_skip condition to NE. */ +static bool canonicalize_skip(DisasContext *ctx) +{ + switch (ctx->skip_cond) { + case TCG_COND_NEVER: + /* Normal case: cpu_skip is known to be false. */ + return false; + + case TCG_COND_ALWAYS: + /* + * Breakpoint case: cpu_skip is known to be true, via TB_FLAGS_SKIP. + * The breakpoint is on the instruction being skipped, at the start + * of the TranslationBlock. No need to update. + */ + return false; + + case TCG_COND_NE: + if (ctx->skip_var1 == NULL) { + tcg_gen_mov_tl(cpu_skip, ctx->skip_var0); + } else { + tcg_gen_xor_tl(cpu_skip, ctx->skip_var0, ctx->skip_var1); + ctx->skip_var1 = NULL; + } + break; + + default: + /* Convert to a NE condition vs 0. */ + if (ctx->skip_var1 == NULL) { + tcg_gen_setcondi_tl(ctx->skip_cond, cpu_skip, ctx->skip_var0, 0); + } else { + tcg_gen_setcond_tl(ctx->skip_cond, cpu_skip, + ctx->skip_var0, ctx->skip_var1); + ctx->skip_var1 = NULL; + } + ctx->skip_cond = TCG_COND_NE; + break; + } + if (ctx->free_skip_var0) { + tcg_temp_free(ctx->skip_var0); + ctx->free_skip_var0 = false; + } + ctx->skip_var0 = cpu_skip; + return true; +} + +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) +{ + CPUAVRState *env = cs->env_ptr; + DisasContext ctx = { + .tb = tb, + .cs = cs, + .env = env, + .memidx = 0, + .bstate = DISAS_NEXT, + .skip_cond = TCG_COND_NEVER, + .singlestep = cs->singlestep_enabled, + }; + target_ulong pc_start = tb->pc / 2; + int num_insns = 0; + + if (tb->flags & TB_FLAGS_FULL_ACCESS) { + /* + * This flag is set by ST/LD instruction we will regenerate it ONLY + * with mem/cpu memory access instead of mem access + */ + max_insns = 1; + } + if (ctx.singlestep) { + max_insns = 1; + } + + gen_tb_start(tb); + + ctx.npc = pc_start; + if (tb->flags & TB_FLAGS_SKIP) { + ctx.skip_cond = TCG_COND_ALWAYS; + ctx.skip_var0 = cpu_skip; + } + + do { + TCGLabel *skip_label = NULL; + + /* translate current instruction */ + tcg_gen_insn_start(ctx.npc); + num_insns++; + + /* + * this is due to some strange GDB behavior + * let's assume main has address 0x100 + * b main - sets breakpoint at address 0x00000100 (code) + * b *0x100 - sets breakpoint at address 0x00800100 (data) + */ + if (unlikely(!ctx.singlestep && + (cpu_breakpoint_test(cs, OFFSET_CODE + ctx.npc * 2, BP_ANY) || + cpu_breakpoint_test(cs, OFFSET_DATA + ctx.npc * 2, BP_ANY)))) { + canonicalize_skip(&ctx); + tcg_gen_movi_tl(cpu_pc, ctx.npc); + gen_helper_debug(cpu_env); + goto done_generating; + } + + /* Conditionally skip the next instruction, if indicated. */ + if (ctx.skip_cond != TCG_COND_NEVER) { + skip_label = gen_new_label(); + if (ctx.skip_var0 == cpu_skip) { + /* + * Copy cpu_skip so that we may zero it before the branch. + * This ensures that cpu_skip is non-zero after the label + * if and only if the skipped insn itself sets a skip. + */ + ctx.free_skip_var0 = true; + ctx.skip_var0 = tcg_temp_new(); + tcg_gen_mov_tl(ctx.skip_var0, cpu_skip); + tcg_gen_movi_tl(cpu_skip, 0); + } + if (ctx.skip_var1 == NULL) { + tcg_gen_brcondi_tl(ctx.skip_cond, ctx.skip_var0, 0, skip_label); + } else { + tcg_gen_brcond_tl(ctx.skip_cond, ctx.skip_var0, + ctx.skip_var1, skip_label); + ctx.skip_var1 = NULL; + } + if (ctx.free_skip_var0) { + tcg_temp_free(ctx.skip_var0); + ctx.free_skip_var0 = false; + } + ctx.skip_cond = TCG_COND_NEVER; + ctx.skip_var0 = NULL; + } + + translate(&ctx); + + if (skip_label) { + canonicalize_skip(&ctx); + gen_set_label(skip_label); + if (ctx.bstate == DISAS_NORETURN) { + ctx.bstate = DISAS_CHAIN; + } + } + } while (ctx.bstate == DISAS_NEXT + && num_insns < max_insns + && (ctx.npc - pc_start) * 2 < TARGET_PAGE_SIZE - 4 + && !tcg_op_buf_full()); + + if (tb->cflags & CF_LAST_IO) { + gen_io_end(); + } + + bool nonconst_skip = canonicalize_skip(&ctx); + + switch (ctx.bstate) { + case DISAS_NORETURN: + assert(!nonconst_skip); + break; + case DISAS_NEXT: + case DISAS_TOO_MANY: + case DISAS_CHAIN: + if (!nonconst_skip) { + /* Note gen_goto_tb checks singlestep. */ + gen_goto_tb(&ctx, 1, ctx.npc); + break; + } + tcg_gen_movi_tl(cpu_pc, ctx.npc); + /* fall through */ + case DISAS_LOOKUP: + if (!ctx.singlestep) { + tcg_gen_lookup_and_goto_ptr(); + break; + } + /* fall through */ + case DISAS_EXIT: + if (ctx.singlestep) { + gen_helper_debug(cpu_env); + } else { + tcg_gen_exit_tb(NULL, 0); + } + break; + default: + g_assert_not_reached(); + } + +done_generating: + gen_tb_end(tb, num_insns); + + tb->size = (ctx.npc - pc_start) * 2; + tb->icount = num_insns; + +#ifdef DEBUG_DISAS + if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) + && qemu_log_in_addr_range(tb->pc)) { + FILE *fd; + fd = qemu_log_lock(); + qemu_log("IN: %s\n", lookup_symbol(tb->pc)); + log_target_disas(cs, tb->pc, tb->size); + qemu_log("\n"); + qemu_log_unlock(fd); + } +#endif +} + +void restore_state_to_opc(CPUAVRState *env, TranslationBlock *tb, + target_ulong *data) +{ + env->pc_w = data[0]; +} diff --git a/target/cris/Makefile.objs b/target/cris/Makefile.objs deleted file mode 100644 index 7779227fc4f1fd63c43d634fda60d1f8400273a3..0000000000000000000000000000000000000000 --- a/target/cris/Makefile.objs +++ /dev/null @@ -1,3 +0,0 @@ -obj-y += translate.o op_helper.o helper.o cpu.o -obj-y += gdbstub.o -obj-$(CONFIG_SOFTMMU) += mmu.o machine.o diff --git a/target/cris/cpu-qom.h b/target/cris/cpu-qom.h index f1de6041dcb17fab9237a0f07743a92e50ea91f3..2596edc7e31f9f41cdd9d591bbfd30fac05f4105 100644 --- a/target/cris/cpu-qom.h +++ b/target/cris/cpu-qom.h @@ -21,15 +21,12 @@ #define QEMU_CRIS_CPU_QOM_H #include "hw/core/cpu.h" +#include "qom/object.h" #define TYPE_CRIS_CPU "cris-cpu" -#define CRIS_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(CRISCPUClass, (klass), TYPE_CRIS_CPU) -#define CRIS_CPU(obj) \ - OBJECT_CHECK(CRISCPU, (obj), TYPE_CRIS_CPU) -#define CRIS_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(CRISCPUClass, (obj), TYPE_CRIS_CPU) +OBJECT_DECLARE_TYPE(CRISCPU, CRISCPUClass, + CRIS_CPU) /** * CRISCPUClass: @@ -39,7 +36,7 @@ * * A CRIS CPU model. */ -typedef struct CRISCPUClass { +struct CRISCPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ @@ -48,8 +45,7 @@ typedef struct CRISCPUClass { DeviceReset parent_reset; uint32_t vr; -} CRISCPUClass; +}; -typedef struct CRISCPU CRISCPU; #endif diff --git a/target/cris/cpu.h b/target/cris/cpu.h index 8f08d7628b2765dcccb670f5539b95eeba4d8fa5..d3b64929096dac199f7bdc87f22898f946b34624 100644 --- a/target/cris/cpu.h +++ b/target/cris/cpu.h @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/cris/crisv10-decode.h b/target/cris/crisv10-decode.h index 028179bd0f0309d865bdb546251749cd304632f6..9c531f36b4242247c8bb4090aac7c27210eb0dc8 100644 --- a/target/cris/crisv10-decode.h +++ b/target/cris/crisv10-decode.h @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/cris/crisv32-decode.h b/target/cris/crisv32-decode.h index cdc2f8cbe6a2de3c13ee718a7b8f03535da8ed3a..fa0a7f0d63ab52ef7071896c49b6ffcdff1d3bd6 100644 --- a/target/cris/crisv32-decode.h +++ b/target/cris/crisv32-decode.h @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/cris/gdbstub.c b/target/cris/gdbstub.c index b01b2aa0811b71a64887e64b369ce921ff551424..2418d575b158f9da09e82b458df05a9afa011815 100644 --- a/target/cris/gdbstub.c +++ b/target/cris/gdbstub.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/cris/helper.c b/target/cris/helper.c index b5159b83577d92d79d7c50ed13e6535ef7bdd41e..ed45c3d9b70ac03910eb43a4ff0b8d857376a559 100644 --- a/target/cris/helper.c +++ b/target/cris/helper.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/cris/machine.c b/target/cris/machine.c index be38a89377a4609dad071a77c00be046dc7d63cb..f370f33486dad968a16daabbf941522ee272cbb4 100644 --- a/target/cris/machine.c +++ b/target/cris/machine.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/cris/meson.build b/target/cris/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..67c3793c85e7aea4c24a55c614d8d4c669ac17ee --- /dev/null +++ b/target/cris/meson.build @@ -0,0 +1,14 @@ +cris_ss = ss.source_set() +cris_ss.add(files( + 'cpu.c', + 'gdbstub.c', + 'helper.c', + 'op_helper.c', + 'translate.c', +)) + +cris_softmmu_ss = ss.source_set() +cris_softmmu_ss.add(files('mmu.c', 'machine.c')) + +target_arch += {'cris': cris_ss} +target_softmmu_arch += {'cris': cris_softmmu_ss} diff --git a/target/cris/mmu.c b/target/cris/mmu.c index 2acbcfd1c7af4f2b0742ffe3a19be937317b0119..a279b7f1b60b67638660b3c6eaa0b2dbd0c9cc1a 100644 --- a/target/cris/mmu.c +++ b/target/cris/mmu.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/cris/op_helper.c b/target/cris/op_helper.c index 6b1e7ae4a8dfcc9b8bbad446dba4e6980f4858af..d55a18a213e7306b462b2cfb93775847e04b10a9 100644 --- a/target/cris/op_helper.c +++ b/target/cris/op_helper.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/cris/translate.c b/target/cris/translate.c index aaa46b5bcaaecdacb81158ec87f42692d62217b7..c893f877abfe49350dd77a00af7232d55861786d 100644 --- a/target/cris/translate.c +++ b/target/cris/translate.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -1178,12 +1178,11 @@ static inline void t_gen_zext(TCGv d, TCGv s, int size) static char memsize_char(int size) { switch (size) { - case 1: return 'b'; break; - case 2: return 'w'; break; - case 4: return 'd'; break; + case 1: return 'b'; + case 2: return 'w'; + case 4: return 'd'; default: return 'x'; - break; } } #endif @@ -3037,7 +3036,7 @@ static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc) return insn_len; } -#include "translate_v10.inc.c" +#include "translate_v10.c.inc" /* * Delay slots on QEMU/CRIS. diff --git a/target/cris/translate_v10.inc.c b/target/cris/translate_v10.c.inc similarity index 99% rename from target/cris/translate_v10.inc.c rename to target/cris/translate_v10.c.inc index ae34a0d1a3d806e7048694d15a3f15ae4760f35c..86d78a82aa4150c929ede9d1198e31ea82aed671 100644 --- a/target/cris/translate_v10.inc.c +++ b/target/cris/translate_v10.c.inc @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -1026,10 +1026,8 @@ static unsigned int dec10_ind(CPUCRISState *env, DisasContext *dc) switch (dc->opcode) { case CRISV10_IND_MOVE_M_R: return dec10_ind_move_m_r(env, dc, size); - break; case CRISV10_IND_MOVE_R_M: return dec10_ind_move_r_m(dc, size); - break; case CRISV10_IND_CMP: LOG_DIS("cmp size=%d op=%d %d\n", size, dc->src, dc->dst); cris_cc_mask(dc, CC_MASK_NZVC); diff --git a/target/hppa/Makefile.objs b/target/hppa/Makefile.objs deleted file mode 100644 index 174f50a96caebb76e2a8be1d2f216355cbae23e3..0000000000000000000000000000000000000000 --- a/target/hppa/Makefile.objs +++ /dev/null @@ -1,11 +0,0 @@ -obj-y += translate.o helper.o cpu.o op_helper.o gdbstub.o mem_helper.o -obj-y += int_helper.o -obj-$(CONFIG_SOFTMMU) += machine.o - -DECODETREE = $(SRC_PATH)/scripts/decodetree.py - -target/hppa/decode.inc.c: $(SRC_PATH)/target/hppa/insns.decode $(DECODETREE) - $(call quiet-command,\ - $(PYTHON) $(DECODETREE) -o $@ $<, "GEN", $(TARGET_DIR)$@) - -target/hppa/translate.o: target/hppa/decode.inc.c diff --git a/target/hppa/cpu-qom.h b/target/hppa/cpu-qom.h index b1f604549538fa0e64e01f50d7d02c09a42a52b7..d424f88370c947f2fb6caaa91dd727f64a2f7920 100644 --- a/target/hppa/cpu-qom.h +++ b/target/hppa/cpu-qom.h @@ -21,15 +21,12 @@ #define QEMU_HPPA_CPU_QOM_H #include "hw/core/cpu.h" +#include "qom/object.h" #define TYPE_HPPA_CPU "hppa-cpu" -#define HPPA_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(HPPACPUClass, (klass), TYPE_HPPA_CPU) -#define HPPA_CPU(obj) \ - OBJECT_CHECK(HPPACPU, (obj), TYPE_HPPA_CPU) -#define HPPA_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(HPPACPUClass, (obj), TYPE_HPPA_CPU) +OBJECT_DECLARE_TYPE(HPPACPU, HPPACPUClass, + HPPA_CPU) /** * HPPACPUClass: @@ -38,15 +35,14 @@ * * An HPPA CPU model. */ -typedef struct HPPACPUClass { +struct HPPACPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ DeviceRealize parent_realize; DeviceReset parent_reset; -} HPPACPUClass; +}; -typedef struct HPPACPU HPPACPU; #endif diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 801a4fb1baebf22032b74a48149bc531d0fb70f6..61178fa6a2a5427c5e8f2fefbf2ac46cc3bba1f1 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -196,9 +196,12 @@ struct CPUHPPAState { target_ureg shadow[7]; /* shadow registers */ /* ??? The number of entries isn't specified by the architecture. */ +#define HPPA_TLB_ENTRIES 256 +#define HPPA_BTLB_ENTRIES 0 + /* ??? Implement a unified itlb/dtlb for the moment. */ /* ??? We should use a more intelligent data structure. */ - hppa_tlb_entry tlb[256]; + hppa_tlb_entry tlb[HPPA_TLB_ENTRIES]; uint32_t tlb_last; }; diff --git a/target/hppa/gdbstub.c b/target/hppa/gdbstub.c index a6428a2893f620d69f81211a3e88c99c192780a4..729c37b2cab39562e06c60927be8b13a6b7754e5 100644 --- a/target/hppa/gdbstub.c +++ b/target/hppa/gdbstub.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/hppa/helper.c b/target/hppa/helper.c index 0dcd105b88440b1ad0d28f67ead4b0e839adcf2c..1ccff5765a80a999a2100ba72a0456b086b44efa 100644 --- a/target/hppa/helper.c +++ b/target/hppa/helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/hppa/insns.decode b/target/hppa/insns.decode index f0dd71dd087d50b2596e0bbd8fa81674cc02e0d2..d4eefc0d48f300a01deb64c036795450430ccb60 100644 --- a/target/hppa/insns.decode +++ b/target/hppa/insns.decode @@ -6,7 +6,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -149,9 +149,9 @@ lci 000001 ----- ----- -- 01001100 0 t:5 # Arith/Log #### -andcm 000010 ..... ..... .... 000000 0 ..... @rrr_cf -and 000010 ..... ..... .... 001000 0 ..... @rrr_cf -or 000010 ..... ..... .... 001001 0 ..... @rrr_cf +andcm 000010 ..... ..... .... 000000 - ..... @rrr_cf +and 000010 ..... ..... .... 001000 - ..... @rrr_cf +or 000010 ..... ..... .... 001001 - ..... @rrr_cf xor 000010 ..... ..... .... 001010 0 ..... @rrr_cf uxor 000010 ..... ..... .... 001110 0 ..... @rrr_cf ds 000010 ..... ..... .... 010001 0 ..... @rrr_cf @@ -161,13 +161,13 @@ uaddcm_tc 000010 ..... ..... .... 100111 0 ..... @rrr_cf dcor 000010 ..... 00000 .... 101110 0 ..... @rr_cf dcor_i 000010 ..... 00000 .... 101111 0 ..... @rr_cf -add 000010 ..... ..... .... 0110.. 0 ..... @rrr_cf_sh +add 000010 ..... ..... .... 0110.. - ..... @rrr_cf_sh add_l 000010 ..... ..... .... 1010.. 0 ..... @rrr_cf_sh add_tsv 000010 ..... ..... .... 1110.. 0 ..... @rrr_cf_sh add_c 000010 ..... ..... .... 011100 0 ..... @rrr_cf_sh0 add_c_tsv 000010 ..... ..... .... 111100 0 ..... @rrr_cf_sh0 -sub 000010 ..... ..... .... 010000 0 ..... @rrr_cf +sub 000010 ..... ..... .... 010000 - ..... @rrr_cf sub_tsv 000010 ..... ..... .... 110000 0 ..... @rrr_cf sub_tc 000010 ..... ..... .... 010011 0 ..... @rrr_cf sub_tsv_tc 000010 ..... ..... .... 110011 0 ..... @rrr_cf diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c index 462747baf8621d9cfcd6620fe3a9e44be37d9866..349495d3610d7840269d49a12f8d188f8628daf3 100644 --- a/target/hppa/int_helper.c +++ b/target/hppa/int_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/hppa/machine.c b/target/hppa/machine.c index 7030101724899ef72216c54dbfc380902da19cc3..b60b654efbee585eb9ea0aabf826bd97fc0ca23a 100644 --- a/target/hppa/machine.c +++ b/target/hppa/machine.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index 5a465db0dd8695d646823358bee725bb26a225ec..afc5b56c3e86490e06f01f2dfa349a3e0daf8e76 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/hppa/meson.build b/target/hppa/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..8a7ff82efc37675274551b281b9d2d64baf40f3a --- /dev/null +++ b/target/hppa/meson.build @@ -0,0 +1,19 @@ +gen = decodetree.process('insns.decode') + +hppa_ss = ss.source_set() +hppa_ss.add(gen) +hppa_ss.add(files( + 'cpu.c', + 'gdbstub.c', + 'helper.c', + 'int_helper.c', + 'mem_helper.c', + 'op_helper.c', + 'translate.c', +)) + +hppa_softmmu_ss = ss.source_set() +hppa_softmmu_ss.add(files('machine.c')) + +target_arch += {'hppa': hppa_ss} +target_softmmu_arch += {'hppa': hppa_softmmu_ss} diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index 5685e303abb459f6c4167f110b3286220962a16f..7ae31e1a15453a476d1702632790893748a886c9 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -67,7 +67,7 @@ static void atomic_store_3(CPUHPPAState *env, target_ulong addr, uint32_t val, old = *haddr; while (1) { new = (old & ~mask) | (val & mask); - cmp = atomic_cmpxchg(haddr, old, new); + cmp = qatomic_cmpxchg(haddr, old, new); if (cmp == old) { return; } diff --git a/target/hppa/trace.h b/target/hppa/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..810cc096927321709ae01d74f7080f5af4c881fa --- /dev/null +++ b/target/hppa/trace.h @@ -0,0 +1 @@ +#include "trace/trace-target_hppa.h" diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 52d7bea1eac0733aac1b6e6b0720a3e5430a28cd..64af1e0d5cc3437bc77578563ba59fccf3846116 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -334,7 +334,7 @@ static int expand_shl11(DisasContext *ctx, int val) /* Include the auto-generated decoder. */ -#include "decode.inc.c" +#include "decode-insns.c.inc" /* We are not using a goto_tb (for whatever reason), but have updated the iaq (for whatever reason), so don't do it again on exit. */ @@ -1294,6 +1294,8 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1, save_or_nullify(ctx, cpu_psw_cb_msb, cb_msb); save_gpr(ctx, rt, dest); tcg_temp_free(dest); + tcg_temp_free(cb); + tcg_temp_free(cb_msb); /* Install the new nullification. */ cond_free(&ctx->null_cond); diff --git a/target/i386/Makefile.objs b/target/i386/Makefile.objs deleted file mode 100644 index 48e0c28434223537a4832d9e36c177ed19b83fc7..0000000000000000000000000000000000000000 --- a/target/i386/Makefile.objs +++ /dev/null @@ -1,22 +0,0 @@ -obj-y += helper.o cpu.o gdbstub.o xsave_helper.o -obj-$(CONFIG_TCG) += translate.o -obj-$(CONFIG_TCG) += bpt_helper.o cc_helper.o excp_helper.o fpu_helper.o -obj-$(CONFIG_TCG) += int_helper.o mem_helper.o misc_helper.o mpx_helper.o -obj-$(CONFIG_TCG) += seg_helper.o smm_helper.o svm_helper.o -obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o -ifeq ($(CONFIG_SOFTMMU),y) -obj-y += machine.o arch_memory_mapping.o arch_dump.o monitor.o -obj-$(CONFIG_KVM) += kvm.o -obj-$(CONFIG_HYPERV) += hyperv.o -obj-$(call lnot,$(CONFIG_HYPERV)) += hyperv-stub.o -ifeq ($(CONFIG_WIN32),y) -obj-$(CONFIG_HAX) += hax-all.o hax-mem.o hax-windows.o -endif -ifeq ($(CONFIG_POSIX),y) -obj-$(CONFIG_HAX) += hax-all.o hax-mem.o hax-posix.o -endif -obj-$(CONFIG_HVF) += hvf/ -obj-$(CONFIG_WHPX) += whpx-all.o -endif -obj-$(CONFIG_SEV) += sev.o -obj-$(call lnot,$(CONFIG_SEV)) += sev-stub.o diff --git a/target/i386/TODO b/target/i386/TODO deleted file mode 100644 index a8d69cf87f2c37f0663e6c2557340527220b5970..0000000000000000000000000000000000000000 --- a/target/i386/TODO +++ /dev/null @@ -1,31 +0,0 @@ -Correctness issues: - -- some eflags manipulation incorrectly reset the bit 0x2. -- SVM: test, cpu save/restore, SMM save/restore. -- x86_64: lcall/ljmp intel/amd differences ? -- better code fetch (different exception handling + CS.limit support) -- user/kernel PUSHL/POPL in helper.c -- add missing cpuid tests -- return UD exception if LOCK prefix incorrectly used -- test ldt limit < 7 ? -- fix some 16 bit sp push/pop overflow (pusha/popa, lcall lret) -- full support of segment limit/rights -- full x87 exception support -- improve x87 bit exactness (use bochs code ?) -- DRx register support -- CR0.AC emulation -- SSE alignment checks - -Optimizations/Features: - -- add SVM nested paging support -- add VMX support -- add AVX support -- add SSE5 support -- fxsave/fxrstor AMD extensions -- improve monitor/mwait support -- faster EFLAGS update: consider SZAP, C, O can be updated separately - with a bit field in CC_OP and more state variables. -- evaluate x87 stack pointer statically -- find a way to avoid translating several time the same TB if CR0.TS - is set or not. diff --git a/target/i386/bpt_helper.c b/target/i386/bpt_helper.c index c3a8ea73c90f32ea380b69f0f7714c30fb670082..e6cc2921e227c2f295ba2cd3697b640a5aad5df9 100644 --- a/target/i386/bpt_helper.c +++ b/target/i386/bpt_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/i386/cc_helper.c b/target/i386/cc_helper.c index c9c90e10db7d05a3a1fe23499cbf9b199b543247..924dd3cd578d38f4aa0a95bec086518c78f93971 100644 --- a/target/i386/cc_helper.c +++ b/target/i386/cc_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/i386/cc_helper_template.h b/target/i386/cc_helper_template.h index 607311f1951391655ebbdbc80f1393f5c699b0e7..bb611feb048cbf0e1cbfdd0b212b0dd5b4dcb4b1 100644 --- a/target/i386/cc_helper_template.h +++ b/target/i386/cc_helper_template.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/i386/cpu-qom.h b/target/i386/cpu-qom.h index 3e96f8d668efd735bbd89c249ed6099323f7ba97..f9923cee04640df2e1a134bfb8ffee4754ce215b 100644 --- a/target/i386/cpu-qom.h +++ b/target/i386/cpu-qom.h @@ -22,6 +22,7 @@ #include "hw/core/cpu.h" #include "qemu/notify.h" +#include "qom/object.h" #ifdef TARGET_X86_64 #define TYPE_X86_CPU "x86_64-cpu" @@ -29,12 +30,8 @@ #define TYPE_X86_CPU "i386-cpu" #endif -#define X86_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(X86CPUClass, (klass), TYPE_X86_CPU) -#define X86_CPU(obj) \ - OBJECT_CHECK(X86CPU, (obj), TYPE_X86_CPU) -#define X86_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(X86CPUClass, (obj), TYPE_X86_CPU) +OBJECT_DECLARE_TYPE(X86CPU, X86CPUClass, + X86_CPU) typedef struct X86CPUModel X86CPUModel; @@ -50,7 +47,7 @@ typedef struct X86CPUModel X86CPUModel; * * An x86 CPU model or family. */ -typedef struct X86CPUClass { +struct X86CPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ @@ -72,8 +69,7 @@ typedef struct X86CPUClass { DeviceRealize parent_realize; DeviceUnrealize parent_unrealize; DeviceReset parent_reset; -} X86CPUClass; +}; -typedef struct X86CPU X86CPU; #endif diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 7a4a8e3847f03432e63f25482e6ca06ee917ebc8..5a8c96072e4125b0822f16d421099721722bf343 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -29,6 +29,7 @@ #include "sysemu/reset.h" #include "sysemu/hvf.h" #include "sysemu/cpus.h" +#include "sysemu/xen.h" #include "kvm_i386.h" #include "sev_i386.h" @@ -54,7 +55,6 @@ #include "hw/i386/topology.h" #ifndef CONFIG_USER_ONLY #include "exec/address-spaces.h" -#include "hw/xen/xen.h" #include "hw/i386/apic_internal.h" #include "hw/boards.h" #endif @@ -344,9 +344,7 @@ static void encode_cache_cpuid8000001d(CPUCacheInfo *cache, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { - uint32_t l3_cores; - unsigned nodes = MAX(topo_info->nodes_per_pkg, 1); - + uint32_t l3_threads; assert(cache->size == cache->line_size * cache->associativity * cache->partitions * cache->sets); @@ -355,11 +353,8 @@ static void encode_cache_cpuid8000001d(CPUCacheInfo *cache, /* L3 is shared among multiple cores */ if (cache->level == 3) { - l3_cores = DIV_ROUND_UP((topo_info->dies_per_pkg * - topo_info->cores_per_die * - topo_info->threads_per_core), - nodes); - *eax |= (l3_cores - 1) << 14; + l3_threads = topo_info->cores_per_die * topo_info->threads_per_core; + *eax |= (l3_threads - 1) << 14; } else { *eax |= ((topo_info->threads_per_core - 1) << 14); } @@ -382,63 +377,57 @@ static void encode_cache_cpuid8000001d(CPUCacheInfo *cache, } /* Encode cache info for CPUID[8000001E] */ -static void encode_topo_cpuid8000001e(X86CPUTopoInfo *topo_info, X86CPU *cpu, - uint32_t *eax, uint32_t *ebx, - uint32_t *ecx, uint32_t *edx) +static void encode_topo_cpuid8000001e(X86CPU *cpu, X86CPUTopoInfo *topo_info, + uint32_t *eax, uint32_t *ebx, + uint32_t *ecx, uint32_t *edx) { - X86CPUTopoIDs topo_ids = {0}; - unsigned long nodes = MAX(topo_info->nodes_per_pkg, 1); - int shift; + X86CPUTopoIDs topo_ids; - x86_topo_ids_from_apicid_epyc(cpu->apic_id, topo_info, &topo_ids); + x86_topo_ids_from_apicid(cpu->apic_id, topo_info, &topo_ids); *eax = cpu->apic_id; + /* - * CPUID_Fn8000001E_EBX - * 31:16 Reserved - * 15:8 Threads per core (The number of threads per core is - * Threads per core + 1) - * 7:0 Core id (see bit decoding below) - * SMT: - * 4:3 node id - * 2 Core complex id - * 1:0 Core id - * Non SMT: - * 5:4 node id - * 3 Core complex id - * 1:0 Core id + * CPUID_Fn8000001E_EBX [Core Identifiers] (CoreId) + * Read-only. Reset: 0000_XXXXh. + * See Core::X86::Cpuid::ExtApicId. + * Core::X86::Cpuid::CoreId_lthree[1:0]_core[3:0]_thread[1:0]; + * Bits Description + * 31:16 Reserved. + * 15:8 ThreadsPerCore: threads per core. Read-only. Reset: XXh. + * The number of threads per core is ThreadsPerCore+1. + * 7:0 CoreId: core ID. Read-only. Reset: XXh. + * + * NOTE: CoreId is already part of apic_id. Just use it. We can + * use all the 8 bits to represent the core_id here. */ - *ebx = ((topo_info->threads_per_core - 1) << 8) | (topo_ids.node_id << 3) | - (topo_ids.core_id); + *ebx = ((topo_info->threads_per_core - 1) << 8) | (topo_ids.core_id & 0xFF); + /* - * CPUID_Fn8000001E_ECX - * 31:11 Reserved - * 10:8 Nodes per processor (Nodes per processor is number of nodes + 1) - * 7:0 Node id (see bit decoding below) - * 2 Socket id - * 1:0 Node id + * CPUID_Fn8000001E_ECX [Node Identifiers] (NodeId) + * Read-only. Reset: 0000_0XXXh. + * Core::X86::Cpuid::NodeId_lthree[1:0]_core[3:0]_thread[1:0]; + * Bits Description + * 31:11 Reserved. + * 10:8 NodesPerProcessor: Node per processor. Read-only. Reset: XXXb. + * ValidValues: + * Value Description + * 000b 1 node per processor. + * 001b 2 nodes per processor. + * 010b Reserved. + * 011b 4 nodes per processor. + * 111b-100b Reserved. + * 7:0 NodeId: Node ID. Read-only. Reset: XXh. + * + * NOTE: Hardware reserves 3 bits for number of nodes per processor. + * But users can create more nodes than the actual hardware can + * support. To genaralize we can use all the upper 8 bits for nodes. + * NodeId is combination of node and socket_id which is already decoded + * in apic_id. Just use it by shifting. */ - if (nodes <= 4) { - *ecx = ((nodes - 1) << 8) | (topo_ids.pkg_id << 2) | topo_ids.node_id; - } else { - /* - * Node id fix up. Actual hardware supports up to 4 nodes. But with - * more than 32 cores, we may end up with more than 4 nodes. - * Node id is a combination of socket id and node id. Only requirement - * here is that this number should be unique accross the system. - * Shift the socket id to accommodate more nodes. We dont expect both - * socket id and node id to be big number at the same time. This is not - * an ideal config but we need to to support it. Max nodes we can have - * is 32 (255/8) with 8 cores per node and 255 max cores. We only need - * 5 bits for nodes. Find the left most set bit to represent the total - * number of nodes. find_last_bit returns last set bit(0 based). Left - * shift(+1) the socket id to represent all the nodes. - */ - nodes -= 1; - shift = find_last_bit(&nodes, 8); - *ecx = (nodes << 8) | (topo_ids.pkg_id << (shift + 1)) | - topo_ids.node_id; - } + *ecx = ((topo_info->dies_per_pkg - 1) << 8) | + ((cpu->apic_id >> apicid_die_offset(topo_info)) & 0xFF); + *edx = 0; } @@ -810,7 +799,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { "kvmclock", "kvm-nopiodelay", "kvm-mmu", "kvmclock", "kvm-asyncpf", "kvm-steal-time", "kvm-pv-eoi", "kvm-pv-unhalt", NULL, "kvm-pv-tlb-flush", NULL, "kvm-pv-ipi", - "kvm-poll-control", "kvm-pv-sched-yield", NULL, NULL, + "kvm-poll-control", "kvm-pv-sched-yield", "kvm-asyncpf-int", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "kvmclock-stable-bit", NULL, NULL, NULL, @@ -984,10 +973,10 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { .type = CPUID_FEATURE_WORD, .feat_names = { NULL, NULL, "avx512-4vnniw", "avx512-4fmaps", - NULL, NULL, NULL, NULL, - NULL, NULL, "md-clear", NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL /* pconfig */, NULL, + "fsrm", NULL, NULL, NULL, + "avx512-vp2intersect", NULL, "md-clear", NULL, + NULL, NULL, "serialize", NULL, + "tsx-ldtrk", NULL, NULL /* pconfig */, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "spec-ctrl", "stibp", NULL, "arch-capabilities", "core-capability", "ssbd", @@ -1139,6 +1128,22 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { .index = MSR_IA32_CORE_CAPABILITY, }, }, + [FEAT_PERF_CAPABILITIES] = { + .type = MSR_FEATURE_WORD, + .feat_names = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, "full-width-write", NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, + .msr = { + .index = MSR_IA32_PERF_CAPABILITIES, + }, + }, [FEAT_VMX_PROCBASED_CTLS] = { .type = MSR_FEATURE_WORD, @@ -1316,6 +1321,10 @@ static FeatureDep feature_dependencies[] = { .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_CORE_CAPABILITY }, .to = { FEAT_CORE_CAPABILITY, ~0ull }, }, + { + .from = { FEAT_1_ECX, CPUID_EXT_PDCM }, + .to = { FEAT_PERF_CAPABILITIES, ~0ull }, + }, { .from = { FEAT_1_ECX, CPUID_EXT_VMX }, .to = { FEAT_VMX_PROCBASED_CTLS, ~0ull }, @@ -1384,6 +1393,10 @@ static FeatureDep feature_dependencies[] = { .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_VMFUNC }, .to = { FEAT_VMX_VMFUNC, ~0ull }, }, + { + .from = { FEAT_8000_0001_ECX, CPUID_EXT3_SVM }, + .to = { FEAT_SVM, ~0ull }, + }, }; typedef struct X86RegisterInfo32 { @@ -1614,16 +1627,13 @@ typedef struct X86CPUDefinition { FeatureWordArray features; const char *model_id; CPUCaches *cache_info; - - /* Use AMD EPYC encoding for apic id */ - bool use_epyc_apic_id_encoding; - /* * Definitions for alternative versions of CPU model. * List is terminated by item with version == 0. * If NULL, version 1 will be registered automatically. */ const X86CPUVersionDefinition *versions; + const char *deprecation_note; } X86CPUDefinition; /* Reference to a specific CPU model version */ @@ -1659,18 +1669,6 @@ static const X86CPUVersionDefinition *x86_cpu_def_get_versions(X86CPUDefinition return def->versions ?: default_version_list; } -bool cpu_x86_use_epyc_apic_id_encoding(const char *cpu_type) -{ - X86CPUClass *xcc = X86_CPU_CLASS(object_class_by_name(cpu_type)); - - assert(xcc); - if (xcc->model && xcc->model->cpudef) { - return xcc->model->cpudef->use_epyc_apic_id_encoding; - } else { - return false; - } -} - static CPUCaches epyc_cache_info = { .l1d_cache = &(CPUCacheInfo) { .type = DATA_CACHE, @@ -3010,6 +3008,13 @@ static X86CPUDefinition builtin_x86_defs[] = { { /* end of list */ } } }, + { + .version = 4, + .props = (PropValue[]) { + { "vmx-eptp-switching", "on" }, + { /* end of list */ } + } + }, { /* end of list */ } } }, @@ -3115,6 +3120,7 @@ static X86CPUDefinition builtin_x86_defs[] = { .versions = (X86CPUVersionDefinition[]) { { .version = 1 }, { .version = 2, + .note = "ARCH_CAPABILITIES", .props = (PropValue[]) { { "arch-capabilities", "on" }, { "rdctl-no", "on" }, @@ -3126,12 +3132,20 @@ static X86CPUDefinition builtin_x86_defs[] = { }, { .version = 3, .alias = "Cascadelake-Server-noTSX", + .note = "ARCH_CAPABILITIES, no TSX", .props = (PropValue[]) { { "hle", "off" }, { "rtm", "off" }, { /* end of list */ } }, }, + { .version = 4, + .note = "ARCH_CAPABILITIES, no TSX", + .props = (PropValue[]) { + { "vmx-eptp-switching", "on" }, + { /* end of list */ } + }, + }, { /* end of list */ } } }, @@ -3344,9 +3358,13 @@ static X86CPUDefinition builtin_x86_defs[] = { .xlevel = 0x80000008, .model_id = "Intel Core Processor (Icelake)", .versions = (X86CPUVersionDefinition[]) { - { .version = 1 }, + { + .version = 1, + .note = "deprecated" + }, { .version = 2, + .note = "no TSX, deprecated", .alias = "Icelake-Client-noTSX", .props = (PropValue[]) { { "hle", "off" }, @@ -3355,7 +3373,8 @@ static X86CPUDefinition builtin_x86_defs[] = { }, }, { /* end of list */ } - } + }, + .deprecation_note = "use Icelake-Server instead" }, { .name = "Icelake-Server", @@ -3464,6 +3483,7 @@ static X86CPUDefinition builtin_x86_defs[] = { { .version = 1 }, { .version = 2, + .note = "no TSX", .alias = "Icelake-Server-noTSX", .props = (PropValue[]) { { "hle", "off" }, @@ -3484,6 +3504,20 @@ static X86CPUDefinition builtin_x86_defs[] = { { /* end of list */ } }, }, + { + .version = 4, + .props = (PropValue[]) { + { "sha-ni", "on" }, + { "avx512ifma", "on" }, + { "rdpid", "on" }, + { "fsrm", "on" }, + { "vmx-rdseed-exit", "on" }, + { "vmx-pml", "on" }, + { "vmx-eptp-switching", "on" }, + { "model", "106" }, + { /* end of list */ } + }, + }, { /* end of list */ } } }, @@ -3584,6 +3618,7 @@ static X86CPUDefinition builtin_x86_defs[] = { { .version = 1 }, { .version = 2, + .note = "no MPX, no MONITOR", .props = (PropValue[]) { { "monitor", "off" }, { "mpx", "off" }, @@ -3938,7 +3973,6 @@ static X86CPUDefinition builtin_x86_defs[] = { .xlevel = 0x8000001E, .model_id = "AMD EPYC Processor", .cache_info = &epyc_cache_info, - .use_epyc_apic_id_encoding = 1, .versions = (X86CPUVersionDefinition[]) { { .version = 1 }, { @@ -4066,7 +4100,6 @@ static X86CPUDefinition builtin_x86_defs[] = { .xlevel = 0x8000001E, .model_id = "AMD EPYC-Rome Processor", .cache_info = &epyc_rome_cache_info, - .use_epyc_apic_id_encoding = 1, }, }; @@ -4099,7 +4132,8 @@ static PropValue tcg_default_props[] = { * We resolve CPU model aliases using -v1 when using "-machine * none", but this is just for compatibility while libvirt isn't * adapted to resolve CPU model versions before creating VMs. - * See "Runnability guarantee of CPU models" at * qemu-deprecated.texi. + * See "Runnability guarantee of CPU models" at + * docs/system/deprecated.rst. */ X86CPUVersion default_cpu_version = 1; @@ -4151,9 +4185,6 @@ void x86_cpu_change_kvm_default(const char *prop, const char *value) assert(pv->prop); } -static uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, - bool migratable_only); - static bool lmce_supported(void) { uint64_t mce_cap = 0; @@ -4231,12 +4262,12 @@ static void max_x86_cpu_initfn(Object *obj) host_vendor_fms(vendor, &family, &model, &stepping); cpu_x86_fill_model_id(model_id); - object_property_set_str(OBJECT(cpu), vendor, "vendor", &error_abort); - object_property_set_int(OBJECT(cpu), family, "family", &error_abort); - object_property_set_int(OBJECT(cpu), model, "model", &error_abort); - object_property_set_int(OBJECT(cpu), stepping, "stepping", + object_property_set_str(OBJECT(cpu), "vendor", vendor, &error_abort); + object_property_set_int(OBJECT(cpu), "family", family, &error_abort); + object_property_set_int(OBJECT(cpu), "model", model, &error_abort); + object_property_set_int(OBJECT(cpu), "stepping", stepping, &error_abort); - object_property_set_str(OBJECT(cpu), model_id, "model-id", + object_property_set_str(OBJECT(cpu), "model-id", model_id, &error_abort); if (kvm_enabled()) { @@ -4256,20 +4287,20 @@ static void max_x86_cpu_initfn(Object *obj) } if (lmce_supported()) { - object_property_set_bool(OBJECT(cpu), true, "lmce", &error_abort); + object_property_set_bool(OBJECT(cpu), "lmce", true, &error_abort); } } else { - object_property_set_str(OBJECT(cpu), CPUID_VENDOR_AMD, - "vendor", &error_abort); - object_property_set_int(OBJECT(cpu), 6, "family", &error_abort); - object_property_set_int(OBJECT(cpu), 6, "model", &error_abort); - object_property_set_int(OBJECT(cpu), 3, "stepping", &error_abort); - object_property_set_str(OBJECT(cpu), + object_property_set_str(OBJECT(cpu), "vendor", CPUID_VENDOR_AMD, + &error_abort); + object_property_set_int(OBJECT(cpu), "family", 6, &error_abort); + object_property_set_int(OBJECT(cpu), "model", 6, &error_abort); + object_property_set_int(OBJECT(cpu), "stepping", 3, &error_abort); + object_property_set_str(OBJECT(cpu), "model-id", "QEMU TCG CPU version " QEMU_HW_VERSION, - "model-id", &error_abort); + &error_abort); } - object_property_set_bool(OBJECT(cpu), true, "pmu", &error_abort); + object_property_set_bool(OBJECT(cpu), "pmu", true, &error_abort); } static const TypeInfo max_x86_cpu_type_info = { @@ -4388,12 +4419,9 @@ static void x86_cpuid_version_set_family(Object *obj, Visitor *v, CPUX86State *env = &cpu->env; const int64_t min = 0; const int64_t max = 0xff + 0xf; - Error *local_err = NULL; int64_t value; - visit_type_int(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_int(v, name, &value, errp)) { return; } if (value < min || value > max) { @@ -4431,12 +4459,9 @@ static void x86_cpuid_version_set_model(Object *obj, Visitor *v, CPUX86State *env = &cpu->env; const int64_t min = 0; const int64_t max = 0xff; - Error *local_err = NULL; int64_t value; - visit_type_int(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_int(v, name, &value, errp)) { return; } if (value < min || value > max) { @@ -4469,12 +4494,9 @@ static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v, CPUX86State *env = &cpu->env; const int64_t min = 0; const int64_t max = 0xf; - Error *local_err = NULL; int64_t value; - visit_type_int(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_int(v, name, &value, errp)) { return; } if (value < min || value > max) { @@ -4574,12 +4596,9 @@ static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, const char *name, X86CPU *cpu = X86_CPU(obj); const int64_t min = 0; const int64_t max = INT64_MAX; - Error *local_err = NULL; int64_t value; - visit_type_int(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_int(v, name, &value, errp)) { return; } if (value < min || value > max) { @@ -4827,6 +4846,7 @@ static void x86_cpu_class_check_missing_features(X86CPUClass *xcc, new->value = g_strdup("type"); *next = new; next = &new->next; + error_free(err); } x86_cpu_filter_features(xc, false); @@ -4975,6 +4995,11 @@ static void x86_cpu_definition_entry(gpointer data, gpointer user_data) info->migration_safe = cc->migration_safe; info->has_migration_safe = true; info->q_static = cc->static_model; + if (cc->model && cc->model->cpudef->deprecation_note) { + info->deprecated = true; + } else { + info->deprecated = false; + } /* * Old machine types won't report aliases, so that alias translation * doesn't break compatibility with previous QEMU versions. @@ -5042,7 +5067,7 @@ static void x86_cpu_apply_props(X86CPU *cpu, PropValue *props) if (!pv->value) { continue; } - object_property_parse(OBJECT(cpu), pv->value, pv->prop, + object_property_parse(OBJECT(cpu), pv->prop, pv->value, &error_abort); } } @@ -5061,7 +5086,7 @@ static void x86_cpu_apply_version_props(X86CPU *cpu, X86CPUModel *model) PropValue *p; for (p = vdef->props; p && p->prop; p++) { - object_property_parse(OBJECT(cpu), p->value, p->prop, + object_property_parse(OBJECT(cpu), p->prop, p->value, &error_abort); } @@ -5078,7 +5103,7 @@ static void x86_cpu_apply_version_props(X86CPU *cpu, X86CPUModel *model) /* Load data from X86CPUDefinition into a X86CPU object */ -static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel *model, Error **errp) +static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel *model) { X86CPUDefinition *def = model->cpudef; CPUX86State *env = &cpu->env; @@ -5092,13 +5117,17 @@ static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel *model, Error **errp) */ /* CPU models only set _minimum_ values for level/xlevel: */ - object_property_set_uint(OBJECT(cpu), def->level, "min-level", errp); - object_property_set_uint(OBJECT(cpu), def->xlevel, "min-xlevel", errp); - - object_property_set_int(OBJECT(cpu), def->family, "family", errp); - object_property_set_int(OBJECT(cpu), def->model, "model", errp); - object_property_set_int(OBJECT(cpu), def->stepping, "stepping", errp); - object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp); + object_property_set_uint(OBJECT(cpu), "min-level", def->level, + &error_abort); + object_property_set_uint(OBJECT(cpu), "min-xlevel", def->xlevel, + &error_abort); + + object_property_set_int(OBJECT(cpu), "family", def->family, &error_abort); + object_property_set_int(OBJECT(cpu), "model", def->model, &error_abort); + object_property_set_int(OBJECT(cpu), "stepping", def->stepping, + &error_abort); + object_property_set_str(OBJECT(cpu), "model-id", def->model_id, + &error_abort); for (w = 0; w < FEATURE_WORDS; w++) { env->features[w] = def->features[w]; } @@ -5135,9 +5164,16 @@ static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel *model, Error **errp) vendor = host_vendor; } - object_property_set_str(OBJECT(cpu), vendor, "vendor", errp); + object_property_set_str(OBJECT(cpu), "vendor", vendor, &error_abort); x86_cpu_apply_version_props(cpu, model); + + /* + * Properties in versioned CPU model are not user specified features. + * We can simply clear env->user_features here since it will be filled later + * in x86_cpu_expand_features() based on plus_features and minus_features. + */ + memset(&env->user_features, 0, sizeof(env->user_features)); } #ifndef CONFIG_USER_ONLY @@ -5239,17 +5275,13 @@ static void x86_cpu_to_dict_full(X86CPU *cpu, QDict *props) static void object_apply_props(Object *obj, QDict *props, Error **errp) { const QDictEntry *prop; - Error *err = NULL; for (prop = qdict_first(props); prop; prop = qdict_next(props, prop)) { - object_property_set_qobject(obj, qdict_entry_value(prop), - qdict_entry_key(prop), &err); - if (err) { + if (!object_property_set_qobject(obj, qdict_entry_key(prop), + qdict_entry_value(prop), errp)) { break; } } - - error_propagate(errp, err); } /* Create X86CPU object according to model+props specification */ @@ -5358,9 +5390,11 @@ static void x86_cpu_cpudef_class_init(ObjectClass *oc, void *data) { X86CPUModel *model = data; X86CPUClass *xcc = X86_CPU_CLASS(oc); + CPUClass *cc = CPU_CLASS(oc); xcc->model = model; xcc->migration_safe = true; + cc->deprecation_note = model->cpudef->deprecation_note; } static void x86_register_cpu_model_type(const char *name, X86CPUModel *model) @@ -5437,7 +5471,6 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, uint32_t signature[3]; X86CPUTopoInfo topo_info; - topo_info.nodes_per_pkg = env->nr_nodes; topo_info.dies_per_pkg = env->nr_dies; topo_info.cores_per_die = cs->nr_cores; topo_info.threads_per_core = cs->nr_threads; @@ -5481,6 +5514,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *ebx |= (cs->nr_cores * cs->nr_threads) << 16; *edx |= CPUID_HT; } + if (!cpu->enable_pmu) { + *ecx &= ~CPUID_EXT_PDCM; + } break; case 2: /* cache info: needed for Pentium Pro compatibility */ @@ -5623,7 +5659,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *ecx |= CPUID_TOPOLOGY_LEVEL_SMT; break; case 1: - *eax = env->pkg_offset; + *eax = apicid_pkg_offset(&topo_info); *ebx = cs->nr_cores * cs->nr_threads; *ecx |= CPUID_TOPOLOGY_LEVEL_CORE; break; @@ -5657,7 +5693,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *ecx |= CPUID_TOPOLOGY_LEVEL_CORE; break; case 2: - *eax = env->pkg_offset; + *eax = apicid_pkg_offset(&topo_info); *ebx = env->nr_dies * cs->nr_cores * cs->nr_threads; *ecx |= CPUID_TOPOLOGY_LEVEL_DIE; break; @@ -5830,11 +5866,19 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *eax = cpu->phys_bits; } *ebx = env->features[FEAT_8000_0008_EBX]; - *ecx = 0; - *edx = 0; if (cs->nr_cores * cs->nr_threads > 1) { - *ecx |= (cs->nr_cores * cs->nr_threads) - 1; + /* + * Bits 15:12 is "The number of bits in the initial + * Core::X86::Apic::ApicId[ApicId] value that indicate + * thread ID within a package". + * Bits 7:0 is "The number of threads in the package is NC+1" + */ + *ecx = (apicid_pkg_offset(&topo_info) << 12) | + ((cs->nr_cores * cs->nr_threads) - 1); + } else { + *ecx = 0; } + *edx = 0; break; case 0x8000000A: if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) { @@ -5878,8 +5922,14 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, } break; case 0x8000001E: - assert(cpu->core_id <= 255); - encode_topo_cpuid8000001e(&topo_info, cpu, eax, ebx, ecx, edx); + if (cpu->core_id <= 255) { + encode_topo_cpuid8000001e(cpu, &topo_info, eax, ebx, ecx, edx); + } else { + *eax = 0; + *ebx = 0; + *ecx = 0; + *edx = 0; + } break; case 0xC0000000: *eax = env->cpuid_xlevel2; @@ -5939,6 +5989,7 @@ static void x86_cpu_reset(DeviceState *dev) /* init to reset state */ env->hflags2 |= HF2_GIF_MASK; + env->hflags &= ~HF_GUEST_MASK; cpu_x86_update_cr0(env, 0x60000010); env->a20_mask = ~0x0; @@ -6050,9 +6101,6 @@ static void x86_cpu_reset(DeviceState *dev) if (kvm_enabled()) { kvm_arch_reset_vcpu(cpu); } - else if (hvf_enabled()) { - hvf_reset_vcpu(s); - } #endif } @@ -6128,8 +6176,7 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp) if (cpu->apic_state == NULL) { return; } - object_property_set_bool(OBJECT(cpu->apic_state), true, "realized", - errp); + qdev_realize(DEVICE(cpu->apic_state), NULL, errp); /* Map APIC MMIO area */ apic = APIC_COMMON(cpu->apic_state); @@ -6152,7 +6199,7 @@ static void x86_cpu_machine_done(Notifier *n, void *unused) if (smram) { cpu->smram = g_new(MemoryRegion, 1); memory_region_init_alias(cpu->smram, OBJECT(cpu), "smram", - smram, 0, 1ull << 32); + smram, 0, 4 * GiB); memory_region_set_enabled(cpu->smram, true); memory_region_add_subregion_overlap(cpu->cpu_as_root, 0, cpu->smram, 1); } @@ -6235,6 +6282,8 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu) uint64_t mask; if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) { + env->features[FEAT_XSAVE_COMP_LO] = 0; + env->features[FEAT_XSAVE_COMP_HI] = 0; return; } @@ -6296,21 +6345,18 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) FeatureWord w; int i; GList *l; - Error *local_err = NULL; for (l = plus_features; l; l = l->next) { const char *prop = l->data; - object_property_set_bool(OBJECT(cpu), true, prop, &local_err); - if (local_err) { - goto out; + if (!object_property_set_bool(OBJECT(cpu), prop, true, errp)) { + return; } } for (l = minus_features; l; l = l->next) { const char *prop = l->data; - object_property_set_bool(OBJECT(cpu), false, prop, &local_err); - if (local_err) { - goto out; + if (!object_property_set_bool(OBJECT(cpu), prop, false, errp)) { + return; } } @@ -6341,7 +6387,6 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) unavailable_features & env->user_features[d->to.index], "This feature depends on other features that were not requested"); - env->user_features[d->to.index] |= unavailable_features; env->features[d->to.index] &= ~unavailable_features; } } @@ -6375,7 +6420,7 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) } else if (cpu->env.cpuid_min_level < 0x14) { mark_unavailable_features(cpu, FEAT_7_0_EBX, CPUID_7_0_EBX_INTEL_PT, - "Intel PT need CPUID leaf 0x14, please set by \"-cpu ...,+intel-pt,level=0x14\""); + "Intel PT need CPUID leaf 0x14, please set by \"-cpu ...,+intel-pt,min-level=0x14\""); } } @@ -6408,11 +6453,6 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) if (env->cpuid_xlevel2 == UINT32_MAX) { env->cpuid_xlevel2 = env->cpuid_min_xlevel2; } - -out: - if (local_err != NULL) { - error_propagate(errp, local_err); - } } /* @@ -6491,6 +6531,9 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) host_cpuid(5, 0, &cpu->mwait.eax, &cpu->mwait.ebx, &cpu->mwait.ecx, &cpu->mwait.edx); env->features[FEAT_1_ECX] |= CPUID_EXT_MONITOR; + if (kvm_enabled() && kvm_has_waitpkg()) { + env->features[FEAT_7_0_ECX] |= CPUID_7_0_ECX_WAITPKG; + } } if (kvm_enabled() && cpu->ucode_rev == 0) { cpu->ucode_rev = kvm_arch_get_supported_msr_feature(kvm_state, @@ -6761,7 +6804,6 @@ static void x86_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name, DeviceState *dev = DEVICE(obj); X86CPU *cpu = X86_CPU(obj); BitProperty *fp = opaque; - Error *local_err = NULL; bool value; if (dev->realized) { @@ -6769,9 +6811,7 @@ static void x86_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name, return; } - visit_type_bool(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_bool(v, name, &value, errp)) { return; } @@ -6805,7 +6845,7 @@ static void x86_cpu_register_bit_prop(X86CPU *cpu, ObjectProperty *op; uint64_t mask = (1ULL << bitnr); - op = object_property_find(OBJECT(cpu), prop_name, NULL); + op = object_property_find(OBJECT(cpu), prop_name); if (op) { fp = op->opaque; assert(fp->w == w); @@ -6843,6 +6883,7 @@ static void x86_cpu_register_feature_bit_props(X86CPU *cpu, x86_cpu_register_bit_prop(cpu, name, w, bitnr); } +#if !defined(CONFIG_USER_ONLY) static GuestPanicInformation *x86_cpu_get_crash_info(CPUState *cs) { X86CPU *cpu = X86_CPU(cs); @@ -6886,6 +6927,7 @@ static void x86_cpu_get_crash_info_qom(Object *obj, Visitor *v, errp); qapi_free_GuestPanicInformation(panic_info); } +#endif /* !CONFIG_USER_ONLY */ static void x86_cpu_initfn(Object *obj) { @@ -6895,45 +6937,14 @@ static void x86_cpu_initfn(Object *obj) FeatureWord w; env->nr_dies = 1; - env->nr_nodes = 1; cpu_set_cpustate_pointers(cpu); - object_property_add(obj, "family", "int", - x86_cpuid_version_get_family, - x86_cpuid_version_set_family, NULL, NULL); - object_property_add(obj, "model", "int", - x86_cpuid_version_get_model, - x86_cpuid_version_set_model, NULL, NULL); - object_property_add(obj, "stepping", "int", - x86_cpuid_version_get_stepping, - x86_cpuid_version_set_stepping, NULL, NULL); - object_property_add_str(obj, "vendor", - x86_cpuid_get_vendor, - x86_cpuid_set_vendor); - object_property_add_str(obj, "model-id", - x86_cpuid_get_model_id, - x86_cpuid_set_model_id); - object_property_add(obj, "tsc-frequency", "int", - x86_cpuid_get_tsc_freq, - x86_cpuid_set_tsc_freq, NULL, NULL); object_property_add(obj, "feature-words", "X86CPUFeatureWordInfo", x86_cpu_get_feature_words, NULL, NULL, (void *)env->features); object_property_add(obj, "filtered-features", "X86CPUFeatureWordInfo", x86_cpu_get_feature_words, NULL, NULL, (void *)cpu->filtered_features); - /* - * The "unavailable-features" property has the same semantics as - * CpuDefinitionInfo.unavailable-features on the "query-cpu-definitions" - * QMP command: they list the features that would have prevented the - * CPU from running if the "enforce" flag was set. - */ - object_property_add(obj, "unavailable-features", "strList", - x86_cpu_get_unavailable_features, - NULL, NULL, NULL); - - object_property_add(obj, "crash-information", "GuestPanicInformation", - x86_cpu_get_crash_info_qom, NULL, NULL, NULL); for (w = 0; w < FEATURE_WORDS; w++) { int bitnr; @@ -6962,6 +6973,7 @@ static void x86_cpu_initfn(Object *obj) object_property_add_alias(obj, "kvm_nopiodelay", obj, "kvm-nopiodelay"); object_property_add_alias(obj, "kvm_mmu", obj, "kvm-mmu"); object_property_add_alias(obj, "kvm_asyncpf", obj, "kvm-asyncpf"); + object_property_add_alias(obj, "kvm_asyncpf_int", obj, "kvm-asyncpf-int"); object_property_add_alias(obj, "kvm_steal_time", obj, "kvm-steal-time"); object_property_add_alias(obj, "kvm_pv_eoi", obj, "kvm-pv-eoi"); object_property_add_alias(obj, "kvm_pv_unhalt", obj, "kvm-pv-unhalt"); @@ -6975,7 +6987,7 @@ static void x86_cpu_initfn(Object *obj) object_property_add_alias(obj, "sse4_2", obj, "sse4.2"); if (xcc->model) { - x86_cpu_load_model(cpu, xcc->model, &error_abort); + x86_cpu_load_model(cpu, xcc->model); } } @@ -7133,7 +7145,7 @@ static Property x86_cpu_properties[] = { DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false), DEFINE_PROP_UINT32("hv-spinlocks", X86CPU, hyperv_spinlock_attempts, - HYPERV_SPINLOCK_NEVER_RETRY), + HYPERV_SPINLOCK_NEVER_NOTIFY), DEFINE_PROP_BIT64("hv-relaxed", X86CPU, hyperv_features, HYPERV_FEAT_RELAXED, 0), DEFINE_PROP_BIT64("hv-vapic", X86CPU, hyperv_features, @@ -7245,7 +7257,6 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) cc->cpu_exec_interrupt = x86_cpu_exec_interrupt; #endif cc->dump_state = x86_cpu_dump_state; - cc->get_crash_info = x86_cpu_get_crash_info; cc->set_pc = x86_cpu_set_pc; cc->synchronize_from_tb = x86_cpu_synchronize_from_tb; cc->gdb_read_register = x86_cpu_gdb_read_register; @@ -7256,6 +7267,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) cc->asidx_from_attrs = x86_asidx_from_attrs; cc->get_memory_mapping = x86_cpu_get_memory_mapping; cc->get_phys_page_attrs_debug = x86_cpu_get_phys_page_attrs_debug; + cc->get_crash_info = x86_cpu_get_crash_info; cc->write_elf64_note = x86_cpu_write_elf64_note; cc->write_elf64_qemunote = x86_cpu_write_elf64_qemunote; cc->write_elf32_note = x86_cpu_write_elf32_note; @@ -7282,6 +7294,40 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) cc->disas_set_info = x86_disas_set_info; dc->user_creatable = true; + + object_class_property_add(oc, "family", "int", + x86_cpuid_version_get_family, + x86_cpuid_version_set_family, NULL, NULL); + object_class_property_add(oc, "model", "int", + x86_cpuid_version_get_model, + x86_cpuid_version_set_model, NULL, NULL); + object_class_property_add(oc, "stepping", "int", + x86_cpuid_version_get_stepping, + x86_cpuid_version_set_stepping, NULL, NULL); + object_class_property_add_str(oc, "vendor", + x86_cpuid_get_vendor, + x86_cpuid_set_vendor); + object_class_property_add_str(oc, "model-id", + x86_cpuid_get_model_id, + x86_cpuid_set_model_id); + object_class_property_add(oc, "tsc-frequency", "int", + x86_cpuid_get_tsc_freq, + x86_cpuid_set_tsc_freq, NULL, NULL); + /* + * The "unavailable-features" property has the same semantics as + * CpuDefinitionInfo.unavailable-features on the "query-cpu-definitions" + * QMP command: they list the features that would have prevented the + * CPU from running if the "enforce" flag was set. + */ + object_class_property_add(oc, "unavailable-features", "strList", + x86_cpu_get_unavailable_features, + NULL, NULL, NULL); + +#if !defined(CONFIG_USER_ONLY) + object_class_property_add(oc, "crash-information", "GuestPanicInformation", + x86_cpu_get_crash_info_qom, NULL, NULL, NULL); +#endif + } static const TypeInfo x86_cpu_type_info = { diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 408392dbf6f463805b10f6107a96d01f00795f15..88e8586f8fb46293810cb34a06a06400f055c17c 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -356,6 +356,8 @@ typedef enum X86Seg { #define MSR_IA32_ARCH_CAPABILITIES 0x10a #define ARCH_CAP_TSX_CTRL_MSR (1<<7) +#define MSR_IA32_PERF_CAPABILITIES 0x345 + #define MSR_IA32_TSX_CTRL 0x122 #define MSR_IA32_TSCDEADLINE 0x6e0 @@ -529,6 +531,7 @@ typedef enum FeatureWord { FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */ FEAT_ARCH_CAPABILITIES, FEAT_CORE_CAPABILITY, + FEAT_PERF_CAPABILITIES, FEAT_VMX_PROCBASED_CTLS, FEAT_VMX_SECONDARY_CTLS, FEAT_VMX_PINBASED_CTLS, @@ -772,6 +775,14 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; #define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Multiply Accumulation Single Precision */ #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) +/* Fast Short Rep Mov */ +#define CPUID_7_0_EDX_FSRM (1U << 4) +/* AVX512 Vector Pair Intersection to a Pair of Mask Registers */ +#define CPUID_7_0_EDX_AVX512_VP2INTERSECT (1U << 8) +/* SERIALIZE instruction */ +#define CPUID_7_0_EDX_SERIALIZE (1U << 14) +/* TSX Suspend Load Address Tracking instruction */ +#define CPUID_7_0_EDX_TSX_LDTRK (1U << 16) /* Speculation Control */ #define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) /* Single Thread Indirect Branch Predictors */ @@ -980,8 +991,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; #define HYPERV_FEAT_IPI 13 #define HYPERV_FEAT_STIMER_DIRECT 14 -#ifndef HYPERV_SPINLOCK_NEVER_RETRY -#define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF +#ifndef HYPERV_SPINLOCK_NEVER_NOTIFY +#define HYPERV_SPINLOCK_NEVER_NOTIFY 0xFFFFFFFF #endif #define EXCP00_DIVZ 0 @@ -1361,6 +1372,11 @@ typedef struct CPUCaches { CPUCacheInfo *l3_cache; } CPUCaches; +typedef struct HVFX86LazyFlags { + target_ulong result; + target_ulong auxbits; +} HVFX86LazyFlags; + typedef struct CPUX86State { /* standard registers */ target_ulong regs[CPU_NB_REGS]; @@ -1476,6 +1492,7 @@ typedef struct CPUX86State { uint64_t wall_clock_msr; uint64_t steal_time_msr; uint64_t async_pf_en_msr; + uint64_t async_pf_int_msr; uint64_t pv_eoi_en_msr; uint64_t poll_control_msr; @@ -1584,6 +1601,7 @@ typedef struct CPUX86State { bool tsc_valid; int64_t tsc_khz; int64_t user_tsc_khz; /* for sanity check only */ + uint64_t apic_bus_freq; #if defined(CONFIG_KVM) || defined(CONFIG_HVF) void *xsave_buf; #endif @@ -1591,7 +1609,8 @@ typedef struct CPUX86State { struct kvm_nested_state *nested_state; #endif #if defined(CONFIG_HVF) - HVFX86EmulatorState *hvf_emul; + HVFX86LazyFlags hvf_lflags; + void *hvf_mmio_buf; #endif uint64_t mcg_cap; @@ -1611,8 +1630,6 @@ typedef struct CPUX86State { TPRAccess tpr_access_type; unsigned nr_dies; - unsigned nr_nodes; - unsigned pkg_offset; } CPUX86State; struct kvm_msrs; @@ -1633,6 +1650,7 @@ struct X86CPU { CPUNegativeOffsetState neg; CPUX86State env; + VMChangeStateEntry *vmsentry; uint64_t ucode_rev; @@ -1900,7 +1918,6 @@ void cpu_clear_apic_feature(CPUX86State *env); void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); void host_vendor_fms(char *vendor, int *family, int *model, int *stepping); -bool cpu_x86_use_epyc_apic_id_encoding(const char *cpu_type); /* helper.c */ bool x86_cpu_tlb_fill(CPUState *cs, vaddr address, int size, @@ -2105,6 +2122,11 @@ static inline bool cpu_has_vmx(CPUX86State *env) return env->features[FEAT_1_ECX] & CPUID_EXT_VMX; } +static inline bool cpu_has_svm(CPUX86State *env) +{ + return env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM; +} + /* * In order for a vCPU to enter VMX operation it must have CR4.VMXE set. * Since it was set, CR4.VMXE must remain set as long as vCPU is in @@ -2130,6 +2152,7 @@ static inline bool cpu_vmx_maybe_enabled(CPUX86State *env) /* fpu_helper.c */ void update_fp_status(CPUX86State *env); void update_mxcsr_status(CPUX86State *env); +void update_mxcsr_from_sse_status(CPUX86State *env); static inline void cpu_set_mxcsr(CPUX86State *env, uint32_t mxcsr) { diff --git a/target/i386/excp_helper.c b/target/i386/excp_helper.c index 1447bda7a9b1a72483a64e4e3dc55a0f35850d33..191471749fbf8dcd729a1e55cebbecce06cec76f 100644 --- a/target/i386/excp_helper.c +++ b/target/i386/excp_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -262,8 +262,8 @@ static hwaddr get_hphys(CPUState *cs, hwaddr gphys, MMUAccessType access_type, } ptep = pde | PG_NX_MASK; - /* if PSE bit is set, then we use a 4MB page */ - if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) { + /* if host cr4 PSE bit is set, then we use a 4MB page */ + if ((pde & PG_PSE_MASK) && (env->nested_pg_mode & SVM_NPT_PSE)) { page_size = 4096 * 1024; pte_addr = pde_addr; diff --git a/target/i386/fpu_helper.c b/target/i386/fpu_helper.c index b34fa784eb80f8c28b35d71d10bf389bc8fce8a4..03b35443a6a073522ad657c09b3d4c4131e2ca77 100644 --- a/target/i386/fpu_helper.c +++ b/target/i386/fpu_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,6 +25,7 @@ #include "exec/exec-all.h" #include "exec/cpu_ldst.h" #include "fpu/softfloat.h" +#include "fpu/softfloat-macros.h" #ifdef CONFIG_SOFTMMU #include "hw/irq.h" @@ -59,8 +60,13 @@ #define FPUC_EM 0x3f #define floatx80_lg2 make_floatx80(0x3ffd, 0x9a209a84fbcff799LL) +#define floatx80_lg2_d make_floatx80(0x3ffd, 0x9a209a84fbcff798LL) #define floatx80_l2e make_floatx80(0x3fff, 0xb8aa3b295c17f0bcLL) +#define floatx80_l2e_d make_floatx80(0x3fff, 0xb8aa3b295c17f0bbLL) #define floatx80_l2t make_floatx80(0x4000, 0xd49a784bcd1b8afeLL) +#define floatx80_l2t_u make_floatx80(0x4000, 0xd49a784bcd1b8affLL) +#define floatx80_ln2_d make_floatx80(0x3ffe, 0xb17217f7d1cf79abLL) +#define floatx80_pi_d make_floatx80(0x4000, 0xc90fdaa22168c234LL) #if !defined(CONFIG_USER_ONLY) static qemu_irq ferr_irq; @@ -156,12 +162,32 @@ static void fpu_set_exception(CPUX86State *env, int mask) } } +static inline uint8_t save_exception_flags(CPUX86State *env) +{ + uint8_t old_flags = get_float_exception_flags(&env->fp_status); + set_float_exception_flags(0, &env->fp_status); + return old_flags; +} + +static void merge_exception_flags(CPUX86State *env, uint8_t old_flags) +{ + uint8_t new_flags = get_float_exception_flags(&env->fp_status); + float_raise(old_flags, &env->fp_status); + fpu_set_exception(env, + ((new_flags & float_flag_invalid ? FPUS_IE : 0) | + (new_flags & float_flag_divbyzero ? FPUS_ZE : 0) | + (new_flags & float_flag_overflow ? FPUS_OE : 0) | + (new_flags & float_flag_underflow ? FPUS_UE : 0) | + (new_flags & float_flag_inexact ? FPUS_PE : 0) | + (new_flags & float_flag_input_denormal ? FPUS_DE : 0))); +} + static inline floatx80 helper_fdiv(CPUX86State *env, floatx80 a, floatx80 b) { - if (floatx80_is_zero(b)) { - fpu_set_exception(env, FPUS_ZE); - } - return floatx80_div(a, b, &env->fp_status); + uint8_t old_flags = save_exception_flags(env); + floatx80 ret = floatx80_div(a, b, &env->fp_status); + merge_exception_flags(env, old_flags); + return ret; } static void fpu_raise_exception(CPUX86State *env, uintptr_t retaddr) @@ -178,6 +204,7 @@ static void fpu_raise_exception(CPUX86State *env, uintptr_t retaddr) void helper_flds_FT0(CPUX86State *env, uint32_t val) { + uint8_t old_flags = save_exception_flags(env); union { float32 f; uint32_t i; @@ -185,10 +212,12 @@ void helper_flds_FT0(CPUX86State *env, uint32_t val) u.i = val; FT0 = float32_to_floatx80(u.f, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fldl_FT0(CPUX86State *env, uint64_t val) { + uint8_t old_flags = save_exception_flags(env); union { float64 f; uint64_t i; @@ -196,6 +225,7 @@ void helper_fldl_FT0(CPUX86State *env, uint64_t val) u.i = val; FT0 = float64_to_floatx80(u.f, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fildl_FT0(CPUX86State *env, int32_t val) @@ -205,6 +235,7 @@ void helper_fildl_FT0(CPUX86State *env, int32_t val) void helper_flds_ST0(CPUX86State *env, uint32_t val) { + uint8_t old_flags = save_exception_flags(env); int new_fpstt; union { float32 f; @@ -216,10 +247,12 @@ void helper_flds_ST0(CPUX86State *env, uint32_t val) env->fpregs[new_fpstt].d = float32_to_floatx80(u.f, &env->fp_status); env->fpstt = new_fpstt; env->fptags[new_fpstt] = 0; /* validate stack entry */ + merge_exception_flags(env, old_flags); } void helper_fldl_ST0(CPUX86State *env, uint64_t val) { + uint8_t old_flags = save_exception_flags(env); int new_fpstt; union { float64 f; @@ -231,6 +264,7 @@ void helper_fldl_ST0(CPUX86State *env, uint64_t val) env->fpregs[new_fpstt].d = float64_to_floatx80(u.f, &env->fp_status); env->fpstt = new_fpstt; env->fptags[new_fpstt] = 0; /* validate stack entry */ + merge_exception_flags(env, old_flags); } void helper_fildl_ST0(CPUX86State *env, int32_t val) @@ -255,90 +289,108 @@ void helper_fildll_ST0(CPUX86State *env, int64_t val) uint32_t helper_fsts_ST0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); union { float32 f; uint32_t i; } u; u.f = floatx80_to_float32(ST0, &env->fp_status); + merge_exception_flags(env, old_flags); return u.i; } uint64_t helper_fstl_ST0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); union { float64 f; uint64_t i; } u; u.f = floatx80_to_float64(ST0, &env->fp_status); + merge_exception_flags(env, old_flags); return u.i; } int32_t helper_fist_ST0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); int32_t val; val = floatx80_to_int32(ST0, &env->fp_status); if (val != (int16_t)val) { + set_float_exception_flags(float_flag_invalid, &env->fp_status); val = -32768; } + merge_exception_flags(env, old_flags); return val; } int32_t helper_fistl_ST0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); int32_t val; - signed char old_exp_flags; - - old_exp_flags = get_float_exception_flags(&env->fp_status); - set_float_exception_flags(0, &env->fp_status); val = floatx80_to_int32(ST0, &env->fp_status); if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) { val = 0x80000000; } - set_float_exception_flags(get_float_exception_flags(&env->fp_status) - | old_exp_flags, &env->fp_status); + merge_exception_flags(env, old_flags); return val; } int64_t helper_fistll_ST0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); int64_t val; - signed char old_exp_flags; - - old_exp_flags = get_float_exception_flags(&env->fp_status); - set_float_exception_flags(0, &env->fp_status); val = floatx80_to_int64(ST0, &env->fp_status); if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) { val = 0x8000000000000000ULL; } - set_float_exception_flags(get_float_exception_flags(&env->fp_status) - | old_exp_flags, &env->fp_status); + merge_exception_flags(env, old_flags); return val; } int32_t helper_fistt_ST0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); int32_t val; val = floatx80_to_int32_round_to_zero(ST0, &env->fp_status); if (val != (int16_t)val) { + set_float_exception_flags(float_flag_invalid, &env->fp_status); val = -32768; } + merge_exception_flags(env, old_flags); return val; } int32_t helper_fisttl_ST0(CPUX86State *env) { - return floatx80_to_int32_round_to_zero(ST0, &env->fp_status); + uint8_t old_flags = save_exception_flags(env); + int32_t val; + + val = floatx80_to_int32_round_to_zero(ST0, &env->fp_status); + if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) { + val = 0x80000000; + } + merge_exception_flags(env, old_flags); + return val; } int64_t helper_fisttll_ST0(CPUX86State *env) { - return floatx80_to_int64_round_to_zero(ST0, &env->fp_status); + uint8_t old_flags = save_exception_flags(env); + int64_t val; + + val = floatx80_to_int64_round_to_zero(ST0, &env->fp_status); + if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) { + val = 0x8000000000000000ULL; + } + merge_exception_flags(env, old_flags); + return val; } void helper_fldt_ST0(CPUX86State *env, target_ulong ptr) @@ -420,24 +472,29 @@ static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500}; void helper_fcom_ST0_FT0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); FloatRelation ret; ret = floatx80_compare(ST0, FT0, &env->fp_status); env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1]; + merge_exception_flags(env, old_flags); } void helper_fucom_ST0_FT0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); FloatRelation ret; ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status); env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1]; + merge_exception_flags(env, old_flags); } static const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C}; void helper_fcomi_ST0_FT0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); int eflags; FloatRelation ret; @@ -445,10 +502,12 @@ void helper_fcomi_ST0_FT0(CPUX86State *env) eflags = cpu_cc_compute_all(env, CC_OP); eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; CC_SRC = eflags; + merge_exception_flags(env, old_flags); } void helper_fucomi_ST0_FT0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); int eflags; FloatRelation ret; @@ -456,26 +515,35 @@ void helper_fucomi_ST0_FT0(CPUX86State *env) eflags = cpu_cc_compute_all(env, CC_OP); eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; CC_SRC = eflags; + merge_exception_flags(env, old_flags); } void helper_fadd_ST0_FT0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); ST0 = floatx80_add(ST0, FT0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fmul_ST0_FT0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); ST0 = floatx80_mul(ST0, FT0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fsub_ST0_FT0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); ST0 = floatx80_sub(ST0, FT0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fsubr_ST0_FT0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); ST0 = floatx80_sub(FT0, ST0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fdiv_ST0_FT0(CPUX86State *env) @@ -492,22 +560,30 @@ void helper_fdivr_ST0_FT0(CPUX86State *env) void helper_fadd_STN_ST0(CPUX86State *env, int st_index) { + uint8_t old_flags = save_exception_flags(env); ST(st_index) = floatx80_add(ST(st_index), ST0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fmul_STN_ST0(CPUX86State *env, int st_index) { + uint8_t old_flags = save_exception_flags(env); ST(st_index) = floatx80_mul(ST(st_index), ST0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fsub_STN_ST0(CPUX86State *env, int st_index) { + uint8_t old_flags = save_exception_flags(env); ST(st_index) = floatx80_sub(ST(st_index), ST0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fsubr_STN_ST0(CPUX86State *env, int st_index) { + uint8_t old_flags = save_exception_flags(env); ST(st_index) = floatx80_sub(ST0, ST(st_index), &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fdiv_STN_ST0(CPUX86State *env, int st_index) @@ -544,27 +620,66 @@ void helper_fld1_ST0(CPUX86State *env) void helper_fldl2t_ST0(CPUX86State *env) { - ST0 = floatx80_l2t; + switch (env->fpuc & FPU_RC_MASK) { + case FPU_RC_UP: + ST0 = floatx80_l2t_u; + break; + default: + ST0 = floatx80_l2t; + break; + } } void helper_fldl2e_ST0(CPUX86State *env) { - ST0 = floatx80_l2e; + switch (env->fpuc & FPU_RC_MASK) { + case FPU_RC_DOWN: + case FPU_RC_CHOP: + ST0 = floatx80_l2e_d; + break; + default: + ST0 = floatx80_l2e; + break; + } } void helper_fldpi_ST0(CPUX86State *env) { - ST0 = floatx80_pi; + switch (env->fpuc & FPU_RC_MASK) { + case FPU_RC_DOWN: + case FPU_RC_CHOP: + ST0 = floatx80_pi_d; + break; + default: + ST0 = floatx80_pi; + break; + } } void helper_fldlg2_ST0(CPUX86State *env) { - ST0 = floatx80_lg2; + switch (env->fpuc & FPU_RC_MASK) { + case FPU_RC_DOWN: + case FPU_RC_CHOP: + ST0 = floatx80_lg2_d; + break; + default: + ST0 = floatx80_lg2; + break; + } } void helper_fldln2_ST0(CPUX86State *env) { - ST0 = floatx80_ln2; + switch (env->fpuc & FPU_RC_MASK) { + case FPU_RC_DOWN: + case FPU_RC_CHOP: + ST0 = floatx80_ln2_d; + break; + default: + ST0 = floatx80_ln2; + break; + } } void helper_fldz_ST0(CPUX86State *env) @@ -679,14 +794,29 @@ void helper_fbld_ST0(CPUX86State *env, target_ulong ptr) void helper_fbst_ST0(CPUX86State *env, target_ulong ptr) { + uint8_t old_flags = save_exception_flags(env); int v; target_ulong mem_ref, mem_end; int64_t val; + CPU_LDoubleU temp; + + temp.d = ST0; val = floatx80_to_int64(ST0, &env->fp_status); mem_ref = ptr; + if (val >= 1000000000000000000LL || val <= -1000000000000000000LL) { + set_float_exception_flags(float_flag_invalid, &env->fp_status); + while (mem_ref < ptr + 7) { + cpu_stb_data_ra(env, mem_ref++, 0, GETPC()); + } + cpu_stb_data_ra(env, mem_ref++, 0xc0, GETPC()); + cpu_stb_data_ra(env, mem_ref++, 0xff, GETPC()); + cpu_stb_data_ra(env, mem_ref++, 0xff, GETPC()); + merge_exception_flags(env, old_flags); + return; + } mem_end = mem_ref + 9; - if (val < 0) { + if (SIGND(temp)) { cpu_stb_data_ra(env, mem_end, 0x80, GETPC()); val = -val; } else { @@ -704,29 +834,393 @@ void helper_fbst_ST0(CPUX86State *env, target_ulong ptr) while (mem_ref < mem_end) { cpu_stb_data_ra(env, mem_ref++, 0, GETPC()); } + merge_exception_flags(env, old_flags); } -void helper_f2xm1(CPUX86State *env) -{ - double val = floatx80_to_double(env, ST0); +/* 128-bit significand of log(2). */ +#define ln2_sig_high 0xb17217f7d1cf79abULL +#define ln2_sig_low 0xc9e3b39803f2f6afULL - val = pow(2.0, val) - 1.0; - ST0 = double_to_floatx80(env, val); -} +/* + * Polynomial coefficients for an approximation to (2^x - 1) / x, on + * the interval [-1/64, 1/64]. + */ +#define f2xm1_coeff_0 make_floatx80(0x3ffe, 0xb17217f7d1cf79acULL) +#define f2xm1_coeff_0_low make_floatx80(0xbfbc, 0xd87edabf495b3762ULL) +#define f2xm1_coeff_1 make_floatx80(0x3ffc, 0xf5fdeffc162c7543ULL) +#define f2xm1_coeff_2 make_floatx80(0x3ffa, 0xe35846b82505fcc7ULL) +#define f2xm1_coeff_3 make_floatx80(0x3ff8, 0x9d955b7dd273b899ULL) +#define f2xm1_coeff_4 make_floatx80(0x3ff5, 0xaec3ff3c4ef4ac0cULL) +#define f2xm1_coeff_5 make_floatx80(0x3ff2, 0xa184897c3a7f0de9ULL) +#define f2xm1_coeff_6 make_floatx80(0x3fee, 0xffe634d0ec30d504ULL) +#define f2xm1_coeff_7 make_floatx80(0x3feb, 0xb160111d2db515e4ULL) + +struct f2xm1_data { + /* + * A value very close to a multiple of 1/32, such that 2^t and 2^t - 1 + * are very close to exact floatx80 values. + */ + floatx80 t; + /* The value of 2^t. */ + floatx80 exp2; + /* The value of 2^t - 1. */ + floatx80 exp2m1; +}; + +static const struct f2xm1_data f2xm1_table[65] = { + { make_floatx80_init(0xbfff, 0x8000000000000000ULL), + make_floatx80_init(0x3ffe, 0x8000000000000000ULL), + make_floatx80_init(0xbffe, 0x8000000000000000ULL) }, + { make_floatx80_init(0xbffe, 0xf800000000002e7eULL), + make_floatx80_init(0x3ffe, 0x82cd8698ac2b9160ULL), + make_floatx80_init(0xbffd, 0xfa64f2cea7a8dd40ULL) }, + { make_floatx80_init(0xbffe, 0xefffffffffffe960ULL), + make_floatx80_init(0x3ffe, 0x85aac367cc488345ULL), + make_floatx80_init(0xbffd, 0xf4aa7930676ef976ULL) }, + { make_floatx80_init(0xbffe, 0xe800000000006f10ULL), + make_floatx80_init(0x3ffe, 0x88980e8092da5c14ULL), + make_floatx80_init(0xbffd, 0xeecfe2feda4b47d8ULL) }, + { make_floatx80_init(0xbffe, 0xe000000000008a45ULL), + make_floatx80_init(0x3ffe, 0x8b95c1e3ea8ba2a5ULL), + make_floatx80_init(0xbffd, 0xe8d47c382ae8bab6ULL) }, + { make_floatx80_init(0xbffe, 0xd7ffffffffff8a9eULL), + make_floatx80_init(0x3ffe, 0x8ea4398b45cd8116ULL), + make_floatx80_init(0xbffd, 0xe2b78ce97464fdd4ULL) }, + { make_floatx80_init(0xbffe, 0xd0000000000019a0ULL), + make_floatx80_init(0x3ffe, 0x91c3d373ab11b919ULL), + make_floatx80_init(0xbffd, 0xdc785918a9dc8dceULL) }, + { make_floatx80_init(0xbffe, 0xc7ffffffffff14dfULL), + make_floatx80_init(0x3ffe, 0x94f4efa8fef76836ULL), + make_floatx80_init(0xbffd, 0xd61620ae02112f94ULL) }, + { make_floatx80_init(0xbffe, 0xc000000000006530ULL), + make_floatx80_init(0x3ffe, 0x9837f0518db87fbbULL), + make_floatx80_init(0xbffd, 0xcf901f5ce48f008aULL) }, + { make_floatx80_init(0xbffe, 0xb7ffffffffff1723ULL), + make_floatx80_init(0x3ffe, 0x9b8d39b9d54eb74cULL), + make_floatx80_init(0xbffd, 0xc8e58c8c55629168ULL) }, + { make_floatx80_init(0xbffe, 0xb00000000000b5e1ULL), + make_floatx80_init(0x3ffe, 0x9ef5326091a0c366ULL), + make_floatx80_init(0xbffd, 0xc2159b3edcbe7934ULL) }, + { make_floatx80_init(0xbffe, 0xa800000000006f8aULL), + make_floatx80_init(0x3ffe, 0xa27043030c49370aULL), + make_floatx80_init(0xbffd, 0xbb1f79f9e76d91ecULL) }, + { make_floatx80_init(0xbffe, 0x9fffffffffff816aULL), + make_floatx80_init(0x3ffe, 0xa5fed6a9b15171cfULL), + make_floatx80_init(0xbffd, 0xb40252ac9d5d1c62ULL) }, + { make_floatx80_init(0xbffe, 0x97ffffffffffb621ULL), + make_floatx80_init(0x3ffe, 0xa9a15ab4ea7c30e6ULL), + make_floatx80_init(0xbffd, 0xacbd4a962b079e34ULL) }, + { make_floatx80_init(0xbffe, 0x8fffffffffff162bULL), + make_floatx80_init(0x3ffe, 0xad583eea42a1b886ULL), + make_floatx80_init(0xbffd, 0xa54f822b7abc8ef4ULL) }, + { make_floatx80_init(0xbffe, 0x87ffffffffff4d34ULL), + make_floatx80_init(0x3ffe, 0xb123f581d2ac7b51ULL), + make_floatx80_init(0xbffd, 0x9db814fc5aa7095eULL) }, + { make_floatx80_init(0xbffe, 0x800000000000227dULL), + make_floatx80_init(0x3ffe, 0xb504f333f9de539dULL), + make_floatx80_init(0xbffd, 0x95f619980c4358c6ULL) }, + { make_floatx80_init(0xbffd, 0xefffffffffff3978ULL), + make_floatx80_init(0x3ffe, 0xb8fbaf4762fbd0a1ULL), + make_floatx80_init(0xbffd, 0x8e08a1713a085ebeULL) }, + { make_floatx80_init(0xbffd, 0xe00000000000df81ULL), + make_floatx80_init(0x3ffe, 0xbd08a39f580bfd8cULL), + make_floatx80_init(0xbffd, 0x85eeb8c14fe804e8ULL) }, + { make_floatx80_init(0xbffd, 0xd00000000000bccfULL), + make_floatx80_init(0x3ffe, 0xc12c4cca667062f6ULL), + make_floatx80_init(0xbffc, 0xfb4eccd6663e7428ULL) }, + { make_floatx80_init(0xbffd, 0xc00000000000eff0ULL), + make_floatx80_init(0x3ffe, 0xc5672a1155069abeULL), + make_floatx80_init(0xbffc, 0xea6357baabe59508ULL) }, + { make_floatx80_init(0xbffd, 0xb000000000000fe6ULL), + make_floatx80_init(0x3ffe, 0xc9b9bd866e2f234bULL), + make_floatx80_init(0xbffc, 0xd91909e6474372d4ULL) }, + { make_floatx80_init(0xbffd, 0x9fffffffffff2172ULL), + make_floatx80_init(0x3ffe, 0xce248c151f84bf00ULL), + make_floatx80_init(0xbffc, 0xc76dcfab81ed0400ULL) }, + { make_floatx80_init(0xbffd, 0x8fffffffffffafffULL), + make_floatx80_init(0x3ffe, 0xd2a81d91f12afb2bULL), + make_floatx80_init(0xbffc, 0xb55f89b83b541354ULL) }, + { make_floatx80_init(0xbffc, 0xffffffffffff81a3ULL), + make_floatx80_init(0x3ffe, 0xd744fccad69d7d5eULL), + make_floatx80_init(0xbffc, 0xa2ec0cd4a58a0a88ULL) }, + { make_floatx80_init(0xbffc, 0xdfffffffffff1568ULL), + make_floatx80_init(0x3ffe, 0xdbfbb797daf25a44ULL), + make_floatx80_init(0xbffc, 0x901121a0943696f0ULL) }, + { make_floatx80_init(0xbffc, 0xbfffffffffff68daULL), + make_floatx80_init(0x3ffe, 0xe0ccdeec2a94f811ULL), + make_floatx80_init(0xbffb, 0xf999089eab583f78ULL) }, + { make_floatx80_init(0xbffc, 0x9fffffffffff4690ULL), + make_floatx80_init(0x3ffe, 0xe5b906e77c83657eULL), + make_floatx80_init(0xbffb, 0xd237c8c41be4d410ULL) }, + { make_floatx80_init(0xbffb, 0xffffffffffff8aeeULL), + make_floatx80_init(0x3ffe, 0xeac0c6e7dd24427cULL), + make_floatx80_init(0xbffb, 0xa9f9c8c116ddec20ULL) }, + { make_floatx80_init(0xbffb, 0xbfffffffffff2d18ULL), + make_floatx80_init(0x3ffe, 0xefe4b99bdcdb06ebULL), + make_floatx80_init(0xbffb, 0x80da33211927c8a8ULL) }, + { make_floatx80_init(0xbffa, 0xffffffffffff8ccbULL), + make_floatx80_init(0x3ffe, 0xf5257d152486d0f4ULL), + make_floatx80_init(0xbffa, 0xada82eadb792f0c0ULL) }, + { make_floatx80_init(0xbff9, 0xffffffffffff11feULL), + make_floatx80_init(0x3ffe, 0xfa83b2db722a0846ULL), + make_floatx80_init(0xbff9, 0xaf89a491babef740ULL) }, + { floatx80_zero_init, + make_floatx80_init(0x3fff, 0x8000000000000000ULL), + floatx80_zero_init }, + { make_floatx80_init(0x3ff9, 0xffffffffffff2680ULL), + make_floatx80_init(0x3fff, 0x82cd8698ac2b9f6fULL), + make_floatx80_init(0x3ff9, 0xb361a62b0ae7dbc0ULL) }, + { make_floatx80_init(0x3ffb, 0x800000000000b500ULL), + make_floatx80_init(0x3fff, 0x85aac367cc488345ULL), + make_floatx80_init(0x3ffa, 0xb5586cf9891068a0ULL) }, + { make_floatx80_init(0x3ffb, 0xbfffffffffff4b67ULL), + make_floatx80_init(0x3fff, 0x88980e8092da7cceULL), + make_floatx80_init(0x3ffb, 0x8980e8092da7cce0ULL) }, + { make_floatx80_init(0x3ffb, 0xffffffffffffff57ULL), + make_floatx80_init(0x3fff, 0x8b95c1e3ea8bd6dfULL), + make_floatx80_init(0x3ffb, 0xb95c1e3ea8bd6df0ULL) }, + { make_floatx80_init(0x3ffc, 0x9fffffffffff811fULL), + make_floatx80_init(0x3fff, 0x8ea4398b45cd4780ULL), + make_floatx80_init(0x3ffb, 0xea4398b45cd47800ULL) }, + { make_floatx80_init(0x3ffc, 0xbfffffffffff9980ULL), + make_floatx80_init(0x3fff, 0x91c3d373ab11b919ULL), + make_floatx80_init(0x3ffc, 0x8e1e9b9d588dc8c8ULL) }, + { make_floatx80_init(0x3ffc, 0xdffffffffffff631ULL), + make_floatx80_init(0x3fff, 0x94f4efa8fef70864ULL), + make_floatx80_init(0x3ffc, 0xa7a77d47f7b84320ULL) }, + { make_floatx80_init(0x3ffc, 0xffffffffffff2499ULL), + make_floatx80_init(0x3fff, 0x9837f0518db892d4ULL), + make_floatx80_init(0x3ffc, 0xc1bf828c6dc496a0ULL) }, + { make_floatx80_init(0x3ffd, 0x8fffffffffff80fbULL), + make_floatx80_init(0x3fff, 0x9b8d39b9d54e3a79ULL), + make_floatx80_init(0x3ffc, 0xdc69cdceaa71d3c8ULL) }, + { make_floatx80_init(0x3ffd, 0x9fffffffffffbc23ULL), + make_floatx80_init(0x3fff, 0x9ef5326091a10313ULL), + make_floatx80_init(0x3ffc, 0xf7a993048d081898ULL) }, + { make_floatx80_init(0x3ffd, 0xafffffffffff20ecULL), + make_floatx80_init(0x3fff, 0xa27043030c49370aULL), + make_floatx80_init(0x3ffd, 0x89c10c0c3124dc28ULL) }, + { make_floatx80_init(0x3ffd, 0xc00000000000fd2cULL), + make_floatx80_init(0x3fff, 0xa5fed6a9b15171cfULL), + make_floatx80_init(0x3ffd, 0x97fb5aa6c545c73cULL) }, + { make_floatx80_init(0x3ffd, 0xd0000000000093beULL), + make_floatx80_init(0x3fff, 0xa9a15ab4ea7c30e6ULL), + make_floatx80_init(0x3ffd, 0xa6856ad3a9f0c398ULL) }, + { make_floatx80_init(0x3ffd, 0xe00000000000c2aeULL), + make_floatx80_init(0x3fff, 0xad583eea42a17876ULL), + make_floatx80_init(0x3ffd, 0xb560fba90a85e1d8ULL) }, + { make_floatx80_init(0x3ffd, 0xefffffffffff1e3fULL), + make_floatx80_init(0x3fff, 0xb123f581d2abef6cULL), + make_floatx80_init(0x3ffd, 0xc48fd6074aafbdb0ULL) }, + { make_floatx80_init(0x3ffd, 0xffffffffffff1c23ULL), + make_floatx80_init(0x3fff, 0xb504f333f9de2cadULL), + make_floatx80_init(0x3ffd, 0xd413cccfe778b2b4ULL) }, + { make_floatx80_init(0x3ffe, 0x8800000000006344ULL), + make_floatx80_init(0x3fff, 0xb8fbaf4762fbd0a1ULL), + make_floatx80_init(0x3ffd, 0xe3eebd1d8bef4284ULL) }, + { make_floatx80_init(0x3ffe, 0x9000000000005d67ULL), + make_floatx80_init(0x3fff, 0xbd08a39f580c668dULL), + make_floatx80_init(0x3ffd, 0xf4228e7d60319a34ULL) }, + { make_floatx80_init(0x3ffe, 0x9800000000009127ULL), + make_floatx80_init(0x3fff, 0xc12c4cca6670e042ULL), + make_floatx80_init(0x3ffe, 0x82589994cce1c084ULL) }, + { make_floatx80_init(0x3ffe, 0x9fffffffffff06f9ULL), + make_floatx80_init(0x3fff, 0xc5672a11550655c3ULL), + make_floatx80_init(0x3ffe, 0x8ace5422aa0cab86ULL) }, + { make_floatx80_init(0x3ffe, 0xa7fffffffffff80dULL), + make_floatx80_init(0x3fff, 0xc9b9bd866e2f234bULL), + make_floatx80_init(0x3ffe, 0x93737b0cdc5e4696ULL) }, + { make_floatx80_init(0x3ffe, 0xafffffffffff1470ULL), + make_floatx80_init(0x3fff, 0xce248c151f83fd69ULL), + make_floatx80_init(0x3ffe, 0x9c49182a3f07fad2ULL) }, + { make_floatx80_init(0x3ffe, 0xb800000000000e0aULL), + make_floatx80_init(0x3fff, 0xd2a81d91f12aec5cULL), + make_floatx80_init(0x3ffe, 0xa5503b23e255d8b8ULL) }, + { make_floatx80_init(0x3ffe, 0xc00000000000b7faULL), + make_floatx80_init(0x3fff, 0xd744fccad69dd630ULL), + make_floatx80_init(0x3ffe, 0xae89f995ad3bac60ULL) }, + { make_floatx80_init(0x3ffe, 0xc800000000003aa6ULL), + make_floatx80_init(0x3fff, 0xdbfbb797daf25a44ULL), + make_floatx80_init(0x3ffe, 0xb7f76f2fb5e4b488ULL) }, + { make_floatx80_init(0x3ffe, 0xd00000000000a6aeULL), + make_floatx80_init(0x3fff, 0xe0ccdeec2a954685ULL), + make_floatx80_init(0x3ffe, 0xc199bdd8552a8d0aULL) }, + { make_floatx80_init(0x3ffe, 0xd800000000004165ULL), + make_floatx80_init(0x3fff, 0xe5b906e77c837155ULL), + make_floatx80_init(0x3ffe, 0xcb720dcef906e2aaULL) }, + { make_floatx80_init(0x3ffe, 0xe00000000000582cULL), + make_floatx80_init(0x3fff, 0xeac0c6e7dd24713aULL), + make_floatx80_init(0x3ffe, 0xd5818dcfba48e274ULL) }, + { make_floatx80_init(0x3ffe, 0xe800000000001a5dULL), + make_floatx80_init(0x3fff, 0xefe4b99bdcdb06ebULL), + make_floatx80_init(0x3ffe, 0xdfc97337b9b60dd6ULL) }, + { make_floatx80_init(0x3ffe, 0xefffffffffffc1efULL), + make_floatx80_init(0x3fff, 0xf5257d152486a2faULL), + make_floatx80_init(0x3ffe, 0xea4afa2a490d45f4ULL) }, + { make_floatx80_init(0x3ffe, 0xf800000000001069ULL), + make_floatx80_init(0x3fff, 0xfa83b2db722a0e5cULL), + make_floatx80_init(0x3ffe, 0xf50765b6e4541cb8ULL) }, + { make_floatx80_init(0x3fff, 0x8000000000000000ULL), + make_floatx80_init(0x4000, 0x8000000000000000ULL), + make_floatx80_init(0x3fff, 0x8000000000000000ULL) }, +}; -void helper_fyl2x(CPUX86State *env) +void helper_f2xm1(CPUX86State *env) { - double fptemp = floatx80_to_double(env, ST0); - - if (fptemp > 0.0) { - fptemp = log(fptemp) / log(2.0); /* log2(ST) */ - fptemp *= floatx80_to_double(env, ST1); - ST1 = double_to_floatx80(env, fptemp); - fpop(env); + uint8_t old_flags = save_exception_flags(env); + uint64_t sig = extractFloatx80Frac(ST0); + int32_t exp = extractFloatx80Exp(ST0); + bool sign = extractFloatx80Sign(ST0); + + if (floatx80_invalid_encoding(ST0)) { + float_raise(float_flag_invalid, &env->fp_status); + ST0 = floatx80_default_nan(&env->fp_status); + } else if (floatx80_is_any_nan(ST0)) { + if (floatx80_is_signaling_nan(ST0, &env->fp_status)) { + float_raise(float_flag_invalid, &env->fp_status); + ST0 = floatx80_silence_nan(ST0, &env->fp_status); + } + } else if (exp > 0x3fff || + (exp == 0x3fff && sig != (0x8000000000000000ULL))) { + /* Out of range for the instruction, treat as invalid. */ + float_raise(float_flag_invalid, &env->fp_status); + ST0 = floatx80_default_nan(&env->fp_status); + } else if (exp == 0x3fff) { + /* Argument 1 or -1, exact result 1 or -0.5. */ + if (sign) { + ST0 = make_floatx80(0xbffe, 0x8000000000000000ULL); + } + } else if (exp < 0x3fb0) { + if (!floatx80_is_zero(ST0)) { + /* + * Multiplying the argument by an extra-precision version + * of log(2) is sufficiently precise. Zero arguments are + * returned unchanged. + */ + uint64_t sig0, sig1, sig2; + if (exp == 0) { + normalizeFloatx80Subnormal(sig, &exp, &sig); + } + mul128By64To192(ln2_sig_high, ln2_sig_low, sig, &sig0, &sig1, + &sig2); + /* This result is inexact. */ + sig1 |= 1; + ST0 = normalizeRoundAndPackFloatx80(80, sign, exp, sig0, sig1, + &env->fp_status); + } } else { - env->fpus &= ~0x4700; - env->fpus |= 0x400; + floatx80 tmp, y, accum; + bool asign, bsign; + int32_t n, aexp, bexp; + uint64_t asig0, asig1, asig2, bsig0, bsig1; + FloatRoundMode save_mode = env->fp_status.float_rounding_mode; + signed char save_prec = env->fp_status.floatx80_rounding_precision; + env->fp_status.float_rounding_mode = float_round_nearest_even; + env->fp_status.floatx80_rounding_precision = 80; + + /* Find the nearest multiple of 1/32 to the argument. */ + tmp = floatx80_scalbn(ST0, 5, &env->fp_status); + n = 32 + floatx80_to_int32(tmp, &env->fp_status); + y = floatx80_sub(ST0, f2xm1_table[n].t, &env->fp_status); + + if (floatx80_is_zero(y)) { + /* + * Use the value of 2^t - 1 from the table, to avoid + * needing to special-case zero as a result of + * multiplication below. + */ + ST0 = f2xm1_table[n].t; + set_float_exception_flags(float_flag_inexact, &env->fp_status); + env->fp_status.float_rounding_mode = save_mode; + } else { + /* + * Compute the lower parts of a polynomial expansion for + * (2^y - 1) / y. + */ + accum = floatx80_mul(f2xm1_coeff_7, y, &env->fp_status); + accum = floatx80_add(f2xm1_coeff_6, accum, &env->fp_status); + accum = floatx80_mul(accum, y, &env->fp_status); + accum = floatx80_add(f2xm1_coeff_5, accum, &env->fp_status); + accum = floatx80_mul(accum, y, &env->fp_status); + accum = floatx80_add(f2xm1_coeff_4, accum, &env->fp_status); + accum = floatx80_mul(accum, y, &env->fp_status); + accum = floatx80_add(f2xm1_coeff_3, accum, &env->fp_status); + accum = floatx80_mul(accum, y, &env->fp_status); + accum = floatx80_add(f2xm1_coeff_2, accum, &env->fp_status); + accum = floatx80_mul(accum, y, &env->fp_status); + accum = floatx80_add(f2xm1_coeff_1, accum, &env->fp_status); + accum = floatx80_mul(accum, y, &env->fp_status); + accum = floatx80_add(f2xm1_coeff_0_low, accum, &env->fp_status); + + /* + * The full polynomial expansion is f2xm1_coeff_0 + accum + * (where accum has much lower magnitude, and so, in + * particular, carry out of the addition is not possible). + * (This expansion is only accurate to about 70 bits, not + * 128 bits.) + */ + aexp = extractFloatx80Exp(f2xm1_coeff_0); + asign = extractFloatx80Sign(f2xm1_coeff_0); + shift128RightJamming(extractFloatx80Frac(accum), 0, + aexp - extractFloatx80Exp(accum), + &asig0, &asig1); + bsig0 = extractFloatx80Frac(f2xm1_coeff_0); + bsig1 = 0; + if (asign == extractFloatx80Sign(accum)) { + add128(bsig0, bsig1, asig0, asig1, &asig0, &asig1); + } else { + sub128(bsig0, bsig1, asig0, asig1, &asig0, &asig1); + } + /* And thus compute an approximation to 2^y - 1. */ + mul128By64To192(asig0, asig1, extractFloatx80Frac(y), + &asig0, &asig1, &asig2); + aexp += extractFloatx80Exp(y) - 0x3ffe; + asign ^= extractFloatx80Sign(y); + if (n != 32) { + /* + * Multiply this by the precomputed value of 2^t and + * add that of 2^t - 1. + */ + mul128By64To192(asig0, asig1, + extractFloatx80Frac(f2xm1_table[n].exp2), + &asig0, &asig1, &asig2); + aexp += extractFloatx80Exp(f2xm1_table[n].exp2) - 0x3ffe; + bexp = extractFloatx80Exp(f2xm1_table[n].exp2m1); + bsig0 = extractFloatx80Frac(f2xm1_table[n].exp2m1); + bsig1 = 0; + if (bexp < aexp) { + shift128RightJamming(bsig0, bsig1, aexp - bexp, + &bsig0, &bsig1); + } else if (aexp < bexp) { + shift128RightJamming(asig0, asig1, bexp - aexp, + &asig0, &asig1); + aexp = bexp; + } + /* The sign of 2^t - 1 is always that of the result. */ + bsign = extractFloatx80Sign(f2xm1_table[n].exp2m1); + if (asign == bsign) { + /* Avoid possible carry out of the addition. */ + shift128RightJamming(asig0, asig1, 1, + &asig0, &asig1); + shift128RightJamming(bsig0, bsig1, 1, + &bsig0, &bsig1); + ++aexp; + add128(asig0, asig1, bsig0, bsig1, &asig0, &asig1); + } else { + sub128(bsig0, bsig1, asig0, asig1, &asig0, &asig1); + asign = bsign; + } + } + env->fp_status.float_rounding_mode = save_mode; + /* This result is inexact. */ + asig1 |= 1; + ST0 = normalizeRoundAndPackFloatx80(80, asign, aexp, asig0, asig1, + &env->fp_status); + } + + env->fp_status.floatx80_rounding_precision = save_prec; } + merge_exception_flags(env, old_flags); } void helper_fptan(CPUX86State *env) @@ -745,18 +1239,498 @@ void helper_fptan(CPUX86State *env) } } +/* Values of pi/4, pi/2, 3pi/4 and pi, with 128-bit precision. */ +#define pi_4_exp 0x3ffe +#define pi_4_sig_high 0xc90fdaa22168c234ULL +#define pi_4_sig_low 0xc4c6628b80dc1cd1ULL +#define pi_2_exp 0x3fff +#define pi_2_sig_high 0xc90fdaa22168c234ULL +#define pi_2_sig_low 0xc4c6628b80dc1cd1ULL +#define pi_34_exp 0x4000 +#define pi_34_sig_high 0x96cbe3f9990e91a7ULL +#define pi_34_sig_low 0x9394c9e8a0a5159dULL +#define pi_exp 0x4000 +#define pi_sig_high 0xc90fdaa22168c234ULL +#define pi_sig_low 0xc4c6628b80dc1cd1ULL + +/* + * Polynomial coefficients for an approximation to atan(x), with only + * odd powers of x used, for x in the interval [-1/16, 1/16]. (Unlike + * for some other approximations, no low part is needed for the first + * coefficient here to achieve a sufficiently accurate result, because + * the coefficient in this minimax approximation is very close to + * exactly 1.) + */ +#define fpatan_coeff_0 make_floatx80(0x3fff, 0x8000000000000000ULL) +#define fpatan_coeff_1 make_floatx80(0xbffd, 0xaaaaaaaaaaaaaa43ULL) +#define fpatan_coeff_2 make_floatx80(0x3ffc, 0xccccccccccbfe4f8ULL) +#define fpatan_coeff_3 make_floatx80(0xbffc, 0x92492491fbab2e66ULL) +#define fpatan_coeff_4 make_floatx80(0x3ffb, 0xe38e372881ea1e0bULL) +#define fpatan_coeff_5 make_floatx80(0xbffb, 0xba2c0104bbdd0615ULL) +#define fpatan_coeff_6 make_floatx80(0x3ffb, 0x9baf7ebf898b42efULL) + +struct fpatan_data { + /* High and low parts of atan(x). */ + floatx80 atan_high, atan_low; +}; + +static const struct fpatan_data fpatan_table[9] = { + { floatx80_zero_init, + floatx80_zero_init }, + { make_floatx80_init(0x3ffb, 0xfeadd4d5617b6e33ULL), + make_floatx80_init(0xbfb9, 0xdda19d8305ddc420ULL) }, + { make_floatx80_init(0x3ffc, 0xfadbafc96406eb15ULL), + make_floatx80_init(0x3fbb, 0xdb8f3debef442fccULL) }, + { make_floatx80_init(0x3ffd, 0xb7b0ca0f26f78474ULL), + make_floatx80_init(0xbfbc, 0xeab9bdba460376faULL) }, + { make_floatx80_init(0x3ffd, 0xed63382b0dda7b45ULL), + make_floatx80_init(0x3fbc, 0xdfc88bd978751a06ULL) }, + { make_floatx80_init(0x3ffe, 0x8f005d5ef7f59f9bULL), + make_floatx80_init(0x3fbd, 0xb906bc2ccb886e90ULL) }, + { make_floatx80_init(0x3ffe, 0xa4bc7d1934f70924ULL), + make_floatx80_init(0x3fbb, 0xcd43f9522bed64f8ULL) }, + { make_floatx80_init(0x3ffe, 0xb8053e2bc2319e74ULL), + make_floatx80_init(0xbfbc, 0xd3496ab7bd6eef0cULL) }, + { make_floatx80_init(0x3ffe, 0xc90fdaa22168c235ULL), + make_floatx80_init(0xbfbc, 0xece675d1fc8f8cbcULL) }, +}; + void helper_fpatan(CPUX86State *env) { - double fptemp, fpsrcop; + uint8_t old_flags = save_exception_flags(env); + uint64_t arg0_sig = extractFloatx80Frac(ST0); + int32_t arg0_exp = extractFloatx80Exp(ST0); + bool arg0_sign = extractFloatx80Sign(ST0); + uint64_t arg1_sig = extractFloatx80Frac(ST1); + int32_t arg1_exp = extractFloatx80Exp(ST1); + bool arg1_sign = extractFloatx80Sign(ST1); + + if (floatx80_is_signaling_nan(ST0, &env->fp_status)) { + float_raise(float_flag_invalid, &env->fp_status); + ST1 = floatx80_silence_nan(ST0, &env->fp_status); + } else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) { + float_raise(float_flag_invalid, &env->fp_status); + ST1 = floatx80_silence_nan(ST1, &env->fp_status); + } else if (floatx80_invalid_encoding(ST0) || + floatx80_invalid_encoding(ST1)) { + float_raise(float_flag_invalid, &env->fp_status); + ST1 = floatx80_default_nan(&env->fp_status); + } else if (floatx80_is_any_nan(ST0)) { + ST1 = ST0; + } else if (floatx80_is_any_nan(ST1)) { + /* Pass this NaN through. */ + } else if (floatx80_is_zero(ST1) && !arg0_sign) { + /* Pass this zero through. */ + } else if (((floatx80_is_infinity(ST0) && !floatx80_is_infinity(ST1)) || + arg0_exp - arg1_exp >= 80) && + !arg0_sign) { + /* + * Dividing ST1 by ST0 gives the correct result up to + * rounding, and avoids spurious underflow exceptions that + * might result from passing some small values through the + * polynomial approximation, but if a finite nonzero result of + * division is exact, the result of fpatan is still inexact + * (and underflowing where appropriate). + */ + signed char save_prec = env->fp_status.floatx80_rounding_precision; + env->fp_status.floatx80_rounding_precision = 80; + ST1 = floatx80_div(ST1, ST0, &env->fp_status); + env->fp_status.floatx80_rounding_precision = save_prec; + if (!floatx80_is_zero(ST1) && + !(get_float_exception_flags(&env->fp_status) & + float_flag_inexact)) { + /* + * The mathematical result is very slightly closer to zero + * than this exact result. Round a value with the + * significand adjusted accordingly to get the correct + * exceptions, and possibly an adjusted result depending + * on the rounding mode. + */ + uint64_t sig = extractFloatx80Frac(ST1); + int32_t exp = extractFloatx80Exp(ST1); + bool sign = extractFloatx80Sign(ST1); + if (exp == 0) { + normalizeFloatx80Subnormal(sig, &exp, &sig); + } + ST1 = normalizeRoundAndPackFloatx80(80, sign, exp, sig - 1, + -1, &env->fp_status); + } + } else { + /* The result is inexact. */ + bool rsign = arg1_sign; + int32_t rexp; + uint64_t rsig0, rsig1; + if (floatx80_is_zero(ST1)) { + /* + * ST0 is negative. The result is pi with the sign of + * ST1. + */ + rexp = pi_exp; + rsig0 = pi_sig_high; + rsig1 = pi_sig_low; + } else if (floatx80_is_infinity(ST1)) { + if (floatx80_is_infinity(ST0)) { + if (arg0_sign) { + rexp = pi_34_exp; + rsig0 = pi_34_sig_high; + rsig1 = pi_34_sig_low; + } else { + rexp = pi_4_exp; + rsig0 = pi_4_sig_high; + rsig1 = pi_4_sig_low; + } + } else { + rexp = pi_2_exp; + rsig0 = pi_2_sig_high; + rsig1 = pi_2_sig_low; + } + } else if (floatx80_is_zero(ST0) || arg1_exp - arg0_exp >= 80) { + rexp = pi_2_exp; + rsig0 = pi_2_sig_high; + rsig1 = pi_2_sig_low; + } else if (floatx80_is_infinity(ST0) || arg0_exp - arg1_exp >= 80) { + /* ST0 is negative. */ + rexp = pi_exp; + rsig0 = pi_sig_high; + rsig1 = pi_sig_low; + } else { + /* + * ST0 and ST1 are finite, nonzero and with exponents not + * too far apart. + */ + int32_t adj_exp, num_exp, den_exp, xexp, yexp, n, texp, zexp, aexp; + int32_t azexp, axexp; + bool adj_sub, ysign, zsign; + uint64_t adj_sig0, adj_sig1, num_sig, den_sig, xsig0, xsig1; + uint64_t msig0, msig1, msig2, remsig0, remsig1, remsig2; + uint64_t ysig0, ysig1, tsig, zsig0, zsig1, asig0, asig1; + uint64_t azsig0, azsig1; + uint64_t azsig2, azsig3, axsig0, axsig1; + floatx80 x8; + FloatRoundMode save_mode = env->fp_status.float_rounding_mode; + signed char save_prec = env->fp_status.floatx80_rounding_precision; + env->fp_status.float_rounding_mode = float_round_nearest_even; + env->fp_status.floatx80_rounding_precision = 80; + + if (arg0_exp == 0) { + normalizeFloatx80Subnormal(arg0_sig, &arg0_exp, &arg0_sig); + } + if (arg1_exp == 0) { + normalizeFloatx80Subnormal(arg1_sig, &arg1_exp, &arg1_sig); + } + if (arg0_exp > arg1_exp || + (arg0_exp == arg1_exp && arg0_sig >= arg1_sig)) { + /* Work with abs(ST1) / abs(ST0). */ + num_exp = arg1_exp; + num_sig = arg1_sig; + den_exp = arg0_exp; + den_sig = arg0_sig; + if (arg0_sign) { + /* The result is subtracted from pi. */ + adj_exp = pi_exp; + adj_sig0 = pi_sig_high; + adj_sig1 = pi_sig_low; + adj_sub = true; + } else { + /* The result is used as-is. */ + adj_exp = 0; + adj_sig0 = 0; + adj_sig1 = 0; + adj_sub = false; + } + } else { + /* Work with abs(ST0) / abs(ST1). */ + num_exp = arg0_exp; + num_sig = arg0_sig; + den_exp = arg1_exp; + den_sig = arg1_sig; + /* The result is added to or subtracted from pi/2. */ + adj_exp = pi_2_exp; + adj_sig0 = pi_2_sig_high; + adj_sig1 = pi_2_sig_low; + adj_sub = !arg0_sign; + } + + /* + * Compute x = num/den, where 0 < x <= 1 and x is not too + * small. + */ + xexp = num_exp - den_exp + 0x3ffe; + remsig0 = num_sig; + remsig1 = 0; + if (den_sig <= remsig0) { + shift128Right(remsig0, remsig1, 1, &remsig0, &remsig1); + ++xexp; + } + xsig0 = estimateDiv128To64(remsig0, remsig1, den_sig); + mul64To128(den_sig, xsig0, &msig0, &msig1); + sub128(remsig0, remsig1, msig0, msig1, &remsig0, &remsig1); + while ((int64_t) remsig0 < 0) { + --xsig0; + add128(remsig0, remsig1, 0, den_sig, &remsig0, &remsig1); + } + xsig1 = estimateDiv128To64(remsig1, 0, den_sig); + /* + * No need to correct any estimation error in xsig1; even + * with such error, it is accurate enough. + */ + + /* + * Split x as x = t + y, where t = n/8 is the nearest + * multiple of 1/8 to x. + */ + x8 = normalizeRoundAndPackFloatx80(80, false, xexp + 3, xsig0, + xsig1, &env->fp_status); + n = floatx80_to_int32(x8, &env->fp_status); + if (n == 0) { + ysign = false; + yexp = xexp; + ysig0 = xsig0; + ysig1 = xsig1; + texp = 0; + tsig = 0; + } else { + int shift = clz32(n) + 32; + texp = 0x403b - shift; + tsig = n; + tsig <<= shift; + if (texp == xexp) { + sub128(xsig0, xsig1, tsig, 0, &ysig0, &ysig1); + if ((int64_t) ysig0 >= 0) { + ysign = false; + if (ysig0 == 0) { + if (ysig1 == 0) { + yexp = 0; + } else { + shift = clz64(ysig1) + 64; + yexp = xexp - shift; + shift128Left(ysig0, ysig1, shift, + &ysig0, &ysig1); + } + } else { + shift = clz64(ysig0); + yexp = xexp - shift; + shift128Left(ysig0, ysig1, shift, &ysig0, &ysig1); + } + } else { + ysign = true; + sub128(0, 0, ysig0, ysig1, &ysig0, &ysig1); + if (ysig0 == 0) { + shift = clz64(ysig1) + 64; + } else { + shift = clz64(ysig0); + } + yexp = xexp - shift; + shift128Left(ysig0, ysig1, shift, &ysig0, &ysig1); + } + } else { + /* + * t's exponent must be greater than x's because t + * is positive and the nearest multiple of 1/8 to + * x, and if x has a greater exponent, the power + * of 2 with that exponent is also a multiple of + * 1/8. + */ + uint64_t usig0, usig1; + shift128RightJamming(xsig0, xsig1, texp - xexp, + &usig0, &usig1); + ysign = true; + sub128(tsig, 0, usig0, usig1, &ysig0, &ysig1); + if (ysig0 == 0) { + shift = clz64(ysig1) + 64; + } else { + shift = clz64(ysig0); + } + yexp = texp - shift; + shift128Left(ysig0, ysig1, shift, &ysig0, &ysig1); + } + } + + /* + * Compute z = y/(1+tx), so arctan(x) = arctan(t) + + * arctan(z). + */ + zsign = ysign; + if (texp == 0 || yexp == 0) { + zexp = yexp; + zsig0 = ysig0; + zsig1 = ysig1; + } else { + /* + * t <= 1, x <= 1 and if both are 1 then y is 0, so tx < 1. + */ + int32_t dexp = texp + xexp - 0x3ffe; + uint64_t dsig0, dsig1, dsig2; + mul128By64To192(xsig0, xsig1, tsig, &dsig0, &dsig1, &dsig2); + /* + * dexp <= 0x3fff (and if equal, dsig0 has a leading 0 + * bit). Add 1 to produce the denominator 1+tx. + */ + shift128RightJamming(dsig0, dsig1, 0x3fff - dexp, + &dsig0, &dsig1); + dsig0 |= 0x8000000000000000ULL; + zexp = yexp - 1; + remsig0 = ysig0; + remsig1 = ysig1; + remsig2 = 0; + if (dsig0 <= remsig0) { + shift128Right(remsig0, remsig1, 1, &remsig0, &remsig1); + ++zexp; + } + zsig0 = estimateDiv128To64(remsig0, remsig1, dsig0); + mul128By64To192(dsig0, dsig1, zsig0, &msig0, &msig1, &msig2); + sub192(remsig0, remsig1, remsig2, msig0, msig1, msig2, + &remsig0, &remsig1, &remsig2); + while ((int64_t) remsig0 < 0) { + --zsig0; + add192(remsig0, remsig1, remsig2, 0, dsig0, dsig1, + &remsig0, &remsig1, &remsig2); + } + zsig1 = estimateDiv128To64(remsig1, remsig2, dsig0); + /* No need to correct any estimation error in zsig1. */ + } + + if (zexp == 0) { + azexp = 0; + azsig0 = 0; + azsig1 = 0; + } else { + floatx80 z2, accum; + uint64_t z2sig0, z2sig1, z2sig2, z2sig3; + /* Compute z^2. */ + mul128To256(zsig0, zsig1, zsig0, zsig1, + &z2sig0, &z2sig1, &z2sig2, &z2sig3); + z2 = normalizeRoundAndPackFloatx80(80, false, + zexp + zexp - 0x3ffe, + z2sig0, z2sig1, + &env->fp_status); + + /* Compute the lower parts of the polynomial expansion. */ + accum = floatx80_mul(fpatan_coeff_6, z2, &env->fp_status); + accum = floatx80_add(fpatan_coeff_5, accum, &env->fp_status); + accum = floatx80_mul(accum, z2, &env->fp_status); + accum = floatx80_add(fpatan_coeff_4, accum, &env->fp_status); + accum = floatx80_mul(accum, z2, &env->fp_status); + accum = floatx80_add(fpatan_coeff_3, accum, &env->fp_status); + accum = floatx80_mul(accum, z2, &env->fp_status); + accum = floatx80_add(fpatan_coeff_2, accum, &env->fp_status); + accum = floatx80_mul(accum, z2, &env->fp_status); + accum = floatx80_add(fpatan_coeff_1, accum, &env->fp_status); + accum = floatx80_mul(accum, z2, &env->fp_status); + + /* + * The full polynomial expansion is z*(fpatan_coeff_0 + accum). + * fpatan_coeff_0 is 1, and accum is negative and much smaller. + */ + aexp = extractFloatx80Exp(fpatan_coeff_0); + shift128RightJamming(extractFloatx80Frac(accum), 0, + aexp - extractFloatx80Exp(accum), + &asig0, &asig1); + sub128(extractFloatx80Frac(fpatan_coeff_0), 0, asig0, asig1, + &asig0, &asig1); + /* Multiply by z to compute arctan(z). */ + azexp = aexp + zexp - 0x3ffe; + mul128To256(asig0, asig1, zsig0, zsig1, &azsig0, &azsig1, + &azsig2, &azsig3); + } + + /* Add arctan(t) (positive or zero) and arctan(z) (sign zsign). */ + if (texp == 0) { + /* z is positive. */ + axexp = azexp; + axsig0 = azsig0; + axsig1 = azsig1; + } else { + bool low_sign = extractFloatx80Sign(fpatan_table[n].atan_low); + int32_t low_exp = extractFloatx80Exp(fpatan_table[n].atan_low); + uint64_t low_sig0 = + extractFloatx80Frac(fpatan_table[n].atan_low); + uint64_t low_sig1 = 0; + axexp = extractFloatx80Exp(fpatan_table[n].atan_high); + axsig0 = extractFloatx80Frac(fpatan_table[n].atan_high); + axsig1 = 0; + shift128RightJamming(low_sig0, low_sig1, axexp - low_exp, + &low_sig0, &low_sig1); + if (low_sign) { + sub128(axsig0, axsig1, low_sig0, low_sig1, + &axsig0, &axsig1); + } else { + add128(axsig0, axsig1, low_sig0, low_sig1, + &axsig0, &axsig1); + } + if (azexp >= axexp) { + shift128RightJamming(axsig0, axsig1, azexp - axexp + 1, + &axsig0, &axsig1); + axexp = azexp + 1; + shift128RightJamming(azsig0, azsig1, 1, + &azsig0, &azsig1); + } else { + shift128RightJamming(axsig0, axsig1, 1, + &axsig0, &axsig1); + shift128RightJamming(azsig0, azsig1, axexp - azexp + 1, + &azsig0, &azsig1); + ++axexp; + } + if (zsign) { + sub128(axsig0, axsig1, azsig0, azsig1, + &axsig0, &axsig1); + } else { + add128(axsig0, axsig1, azsig0, azsig1, + &axsig0, &axsig1); + } + } + + if (adj_exp == 0) { + rexp = axexp; + rsig0 = axsig0; + rsig1 = axsig1; + } else { + /* + * Add or subtract arctan(x) (exponent axexp, + * significand axsig0 and axsig1, positive, not + * necessarily normalized) to the number given by + * adj_exp, adj_sig0 and adj_sig1, according to + * adj_sub. + */ + if (adj_exp >= axexp) { + shift128RightJamming(axsig0, axsig1, adj_exp - axexp + 1, + &axsig0, &axsig1); + rexp = adj_exp + 1; + shift128RightJamming(adj_sig0, adj_sig1, 1, + &adj_sig0, &adj_sig1); + } else { + shift128RightJamming(axsig0, axsig1, 1, + &axsig0, &axsig1); + shift128RightJamming(adj_sig0, adj_sig1, + axexp - adj_exp + 1, + &adj_sig0, &adj_sig1); + rexp = axexp + 1; + } + if (adj_sub) { + sub128(adj_sig0, adj_sig1, axsig0, axsig1, + &rsig0, &rsig1); + } else { + add128(adj_sig0, adj_sig1, axsig0, axsig1, + &rsig0, &rsig1); + } + } + + env->fp_status.float_rounding_mode = save_mode; + env->fp_status.floatx80_rounding_precision = save_prec; + } + /* This result is inexact. */ + rsig1 |= 1; + ST1 = normalizeRoundAndPackFloatx80(80, rsign, rexp, + rsig0, rsig1, &env->fp_status); + } - fpsrcop = floatx80_to_double(env, ST1); - fptemp = floatx80_to_double(env, ST0); - ST1 = double_to_floatx80(env, atan2(fpsrcop, fptemp)); fpop(env); + merge_exception_flags(env, old_flags); } void helper_fxtract(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); CPU_LDoubleU temp; temp.d = ST0; @@ -767,160 +1741,485 @@ void helper_fxtract(CPUX86State *env) &env->fp_status); fpush(env); ST0 = temp.d; + } else if (floatx80_invalid_encoding(ST0)) { + float_raise(float_flag_invalid, &env->fp_status); + ST0 = floatx80_default_nan(&env->fp_status); + fpush(env); + ST0 = ST1; + } else if (floatx80_is_any_nan(ST0)) { + if (floatx80_is_signaling_nan(ST0, &env->fp_status)) { + float_raise(float_flag_invalid, &env->fp_status); + ST0 = floatx80_silence_nan(ST0, &env->fp_status); + } + fpush(env); + ST0 = ST1; + } else if (floatx80_is_infinity(ST0)) { + fpush(env); + ST0 = ST1; + ST1 = floatx80_infinity; } else { int expdif; - expdif = EXPD(temp) - EXPBIAS; + if (EXPD(temp) == 0) { + int shift = clz64(temp.l.lower); + temp.l.lower <<= shift; + expdif = 1 - EXPBIAS - shift; + float_raise(float_flag_input_denormal, &env->fp_status); + } else { + expdif = EXPD(temp) - EXPBIAS; + } /* DP exponent bias */ ST0 = int32_to_floatx80(expdif, &env->fp_status); fpush(env); BIASEXPONENT(temp); ST0 = temp.d; } + merge_exception_flags(env, old_flags); } -void helper_fprem1(CPUX86State *env) +static void helper_fprem_common(CPUX86State *env, bool mod) { - double st0, st1, dblq, fpsrcop, fptemp; - CPU_LDoubleU fpsrcop1, fptemp1; - int expdif; - signed long long int q; - - st0 = floatx80_to_double(env, ST0); - st1 = floatx80_to_double(env, ST1); - - if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) { - ST0 = double_to_floatx80(env, 0.0 / 0.0); /* NaN */ - env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */ - return; - } - - fpsrcop = st0; - fptemp = st1; - fpsrcop1.d = ST0; - fptemp1.d = ST1; - expdif = EXPD(fpsrcop1) - EXPD(fptemp1); - - if (expdif < 0) { - /* optimisation? taken from the AMD docs */ - env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */ - /* ST0 is unchanged */ - return; - } + uint8_t old_flags = save_exception_flags(env); + uint64_t quotient; + CPU_LDoubleU temp0, temp1; + int exp0, exp1, expdiff; - if (expdif < 53) { - dblq = fpsrcop / fptemp; - /* round dblq towards nearest integer */ - dblq = rint(dblq); - st0 = fpsrcop - fptemp * dblq; + temp0.d = ST0; + temp1.d = ST1; + exp0 = EXPD(temp0); + exp1 = EXPD(temp1); - /* convert dblq to q by truncating towards zero */ - if (dblq < 0.0) { - q = (signed long long int)(-dblq); + env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */ + if (floatx80_is_zero(ST0) || floatx80_is_zero(ST1) || + exp0 == 0x7fff || exp1 == 0x7fff || + floatx80_invalid_encoding(ST0) || floatx80_invalid_encoding(ST1)) { + ST0 = floatx80_modrem(ST0, ST1, mod, "ient, &env->fp_status); + } else { + if (exp0 == 0) { + exp0 = 1 - clz64(temp0.l.lower); + } + if (exp1 == 0) { + exp1 = 1 - clz64(temp1.l.lower); + } + expdiff = exp0 - exp1; + if (expdiff < 64) { + ST0 = floatx80_modrem(ST0, ST1, mod, "ient, &env->fp_status); + env->fpus |= (quotient & 0x4) << (8 - 2); /* (C0) <-- q2 */ + env->fpus |= (quotient & 0x2) << (14 - 1); /* (C3) <-- q1 */ + env->fpus |= (quotient & 0x1) << (9 - 0); /* (C1) <-- q0 */ } else { - q = (signed long long int)dblq; + /* + * Partial remainder. This choice of how many bits to + * process at once is specified in AMD instruction set + * manuals, and empirically is followed by Intel + * processors as well; it ensures that the final remainder + * operation in a loop does produce the correct low three + * bits of the quotient. AMD manuals specify that the + * flags other than C2 are cleared, and empirically Intel + * processors clear them as well. + */ + int n = 32 + (expdiff % 32); + temp1.d = floatx80_scalbn(temp1.d, expdiff - n, &env->fp_status); + ST0 = floatx80_mod(ST0, temp1.d, &env->fp_status); + env->fpus |= 0x400; /* C2 <-- 1 */ } - - env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */ - /* (C0,C3,C1) <-- (q2,q1,q0) */ - env->fpus |= (q & 0x4) << (8 - 2); /* (C0) <-- q2 */ - env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */ - env->fpus |= (q & 0x1) << (9 - 0); /* (C1) <-- q0 */ - } else { - env->fpus |= 0x400; /* C2 <-- 1 */ - fptemp = pow(2.0, expdif - 50); - fpsrcop = (st0 / st1) / fptemp; - /* fpsrcop = integer obtained by chopping */ - fpsrcop = (fpsrcop < 0.0) ? - -(floor(fabs(fpsrcop))) : floor(fpsrcop); - st0 -= (st1 * fpsrcop * fptemp); } - ST0 = double_to_floatx80(env, st0); + merge_exception_flags(env, old_flags); } -void helper_fprem(CPUX86State *env) +void helper_fprem1(CPUX86State *env) { - double st0, st1, dblq, fpsrcop, fptemp; - CPU_LDoubleU fpsrcop1, fptemp1; - int expdif; - signed long long int q; - - st0 = floatx80_to_double(env, ST0); - st1 = floatx80_to_double(env, ST1); - - if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) { - ST0 = double_to_floatx80(env, 0.0 / 0.0); /* NaN */ - env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */ - return; - } + helper_fprem_common(env, false); +} - fpsrcop = st0; - fptemp = st1; - fpsrcop1.d = ST0; - fptemp1.d = ST1; - expdif = EXPD(fpsrcop1) - EXPD(fptemp1); +void helper_fprem(CPUX86State *env) +{ + helper_fprem_common(env, true); +} - if (expdif < 0) { - /* optimisation? taken from the AMD docs */ - env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */ - /* ST0 is unchanged */ - return; - } +/* 128-bit significand of log2(e). */ +#define log2_e_sig_high 0xb8aa3b295c17f0bbULL +#define log2_e_sig_low 0xbe87fed0691d3e89ULL - if (expdif < 53) { - dblq = fpsrcop / fptemp; /* ST0 / ST1 */ - /* round dblq towards zero */ - dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq); - st0 = fpsrcop - fptemp * dblq; /* fpsrcop is ST0 */ +/* + * Polynomial coefficients for an approximation to log2((1+x)/(1-x)), + * with only odd powers of x used, for x in the interval [2*sqrt(2)-3, + * 3-2*sqrt(2)], which corresponds to logarithms of numbers in the + * interval [sqrt(2)/2, sqrt(2)]. + */ +#define fyl2x_coeff_0 make_floatx80(0x4000, 0xb8aa3b295c17f0bcULL) +#define fyl2x_coeff_0_low make_floatx80(0xbfbf, 0x834972fe2d7bab1bULL) +#define fyl2x_coeff_1 make_floatx80(0x3ffe, 0xf6384ee1d01febb8ULL) +#define fyl2x_coeff_2 make_floatx80(0x3ffe, 0x93bb62877cdfa2e3ULL) +#define fyl2x_coeff_3 make_floatx80(0x3ffd, 0xd30bb153d808f269ULL) +#define fyl2x_coeff_4 make_floatx80(0x3ffd, 0xa42589eaf451499eULL) +#define fyl2x_coeff_5 make_floatx80(0x3ffd, 0x864d42c0f8f17517ULL) +#define fyl2x_coeff_6 make_floatx80(0x3ffc, 0xe3476578adf26272ULL) +#define fyl2x_coeff_7 make_floatx80(0x3ffc, 0xc506c5f874e6d80fULL) +#define fyl2x_coeff_8 make_floatx80(0x3ffc, 0xac5cf50cc57d6372ULL) +#define fyl2x_coeff_9 make_floatx80(0x3ffc, 0xb1ed0066d971a103ULL) - /* convert dblq to q by truncating towards zero */ - if (dblq < 0.0) { - q = (signed long long int)(-dblq); - } else { - q = (signed long long int)dblq; - } +/* + * Compute an approximation of log2(1+arg), where 1+arg is in the + * interval [sqrt(2)/2, sqrt(2)]. It is assumed that when this + * function is called, rounding precision is set to 80 and the + * round-to-nearest mode is in effect. arg must not be exactly zero, + * and must not be so close to zero that underflow might occur. + */ +static void helper_fyl2x_common(CPUX86State *env, floatx80 arg, int32_t *exp, + uint64_t *sig0, uint64_t *sig1) +{ + uint64_t arg0_sig = extractFloatx80Frac(arg); + int32_t arg0_exp = extractFloatx80Exp(arg); + bool arg0_sign = extractFloatx80Sign(arg); + bool asign; + int32_t dexp, texp, aexp; + uint64_t dsig0, dsig1, tsig0, tsig1, rsig0, rsig1, rsig2; + uint64_t msig0, msig1, msig2, t2sig0, t2sig1, t2sig2, t2sig3; + uint64_t asig0, asig1, asig2, asig3, bsig0, bsig1; + floatx80 t2, accum; - env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */ - /* (C0,C3,C1) <-- (q2,q1,q0) */ - env->fpus |= (q & 0x4) << (8 - 2); /* (C0) <-- q2 */ - env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */ - env->fpus |= (q & 0x1) << (9 - 0); /* (C1) <-- q0 */ + /* + * Compute an approximation of arg/(2+arg), with extra precision, + * as the argument to a polynomial approximation. The extra + * precision is only needed for the first term of the + * approximation, with subsequent terms being significantly + * smaller; the approximation only uses odd exponents, and the + * square of arg/(2+arg) is at most 17-12*sqrt(2) = 0.029.... + */ + if (arg0_sign) { + dexp = 0x3fff; + shift128RightJamming(arg0_sig, 0, dexp - arg0_exp, &dsig0, &dsig1); + sub128(0, 0, dsig0, dsig1, &dsig0, &dsig1); } else { - int N = 32 + (expdif % 32); /* as per AMD docs */ + dexp = 0x4000; + shift128RightJamming(arg0_sig, 0, dexp - arg0_exp, &dsig0, &dsig1); + dsig0 |= 0x8000000000000000ULL; + } + texp = arg0_exp - dexp + 0x3ffe; + rsig0 = arg0_sig; + rsig1 = 0; + rsig2 = 0; + if (dsig0 <= rsig0) { + shift128Right(rsig0, rsig1, 1, &rsig0, &rsig1); + ++texp; + } + tsig0 = estimateDiv128To64(rsig0, rsig1, dsig0); + mul128By64To192(dsig0, dsig1, tsig0, &msig0, &msig1, &msig2); + sub192(rsig0, rsig1, rsig2, msig0, msig1, msig2, + &rsig0, &rsig1, &rsig2); + while ((int64_t) rsig0 < 0) { + --tsig0; + add192(rsig0, rsig1, rsig2, 0, dsig0, dsig1, + &rsig0, &rsig1, &rsig2); + } + tsig1 = estimateDiv128To64(rsig1, rsig2, dsig0); + /* + * No need to correct any estimation error in tsig1; even with + * such error, it is accurate enough. Now compute the square of + * that approximation. + */ + mul128To256(tsig0, tsig1, tsig0, tsig1, + &t2sig0, &t2sig1, &t2sig2, &t2sig3); + t2 = normalizeRoundAndPackFloatx80(80, false, texp + texp - 0x3ffe, + t2sig0, t2sig1, &env->fp_status); + + /* Compute the lower parts of the polynomial expansion. */ + accum = floatx80_mul(fyl2x_coeff_9, t2, &env->fp_status); + accum = floatx80_add(fyl2x_coeff_8, accum, &env->fp_status); + accum = floatx80_mul(accum, t2, &env->fp_status); + accum = floatx80_add(fyl2x_coeff_7, accum, &env->fp_status); + accum = floatx80_mul(accum, t2, &env->fp_status); + accum = floatx80_add(fyl2x_coeff_6, accum, &env->fp_status); + accum = floatx80_mul(accum, t2, &env->fp_status); + accum = floatx80_add(fyl2x_coeff_5, accum, &env->fp_status); + accum = floatx80_mul(accum, t2, &env->fp_status); + accum = floatx80_add(fyl2x_coeff_4, accum, &env->fp_status); + accum = floatx80_mul(accum, t2, &env->fp_status); + accum = floatx80_add(fyl2x_coeff_3, accum, &env->fp_status); + accum = floatx80_mul(accum, t2, &env->fp_status); + accum = floatx80_add(fyl2x_coeff_2, accum, &env->fp_status); + accum = floatx80_mul(accum, t2, &env->fp_status); + accum = floatx80_add(fyl2x_coeff_1, accum, &env->fp_status); + accum = floatx80_mul(accum, t2, &env->fp_status); + accum = floatx80_add(fyl2x_coeff_0_low, accum, &env->fp_status); - env->fpus |= 0x400; /* C2 <-- 1 */ - fptemp = pow(2.0, (double)(expdif - N)); - fpsrcop = (st0 / st1) / fptemp; - /* fpsrcop = integer obtained by chopping */ - fpsrcop = (fpsrcop < 0.0) ? - -(floor(fabs(fpsrcop))) : floor(fpsrcop); - st0 -= (st1 * fpsrcop * fptemp); + /* + * The full polynomial expansion is fyl2x_coeff_0 + accum (where + * accum has much lower magnitude, and so, in particular, carry + * out of the addition is not possible), multiplied by t. (This + * expansion is only accurate to about 70 bits, not 128 bits.) + */ + aexp = extractFloatx80Exp(fyl2x_coeff_0); + asign = extractFloatx80Sign(fyl2x_coeff_0); + shift128RightJamming(extractFloatx80Frac(accum), 0, + aexp - extractFloatx80Exp(accum), + &asig0, &asig1); + bsig0 = extractFloatx80Frac(fyl2x_coeff_0); + bsig1 = 0; + if (asign == extractFloatx80Sign(accum)) { + add128(bsig0, bsig1, asig0, asig1, &asig0, &asig1); + } else { + sub128(bsig0, bsig1, asig0, asig1, &asig0, &asig1); } - ST0 = double_to_floatx80(env, st0); + /* Multiply by t to compute the required result. */ + mul128To256(asig0, asig1, tsig0, tsig1, + &asig0, &asig1, &asig2, &asig3); + aexp += texp - 0x3ffe; + *exp = aexp; + *sig0 = asig0; + *sig1 = asig1; } void helper_fyl2xp1(CPUX86State *env) { - double fptemp = floatx80_to_double(env, ST0); + uint8_t old_flags = save_exception_flags(env); + uint64_t arg0_sig = extractFloatx80Frac(ST0); + int32_t arg0_exp = extractFloatx80Exp(ST0); + bool arg0_sign = extractFloatx80Sign(ST0); + uint64_t arg1_sig = extractFloatx80Frac(ST1); + int32_t arg1_exp = extractFloatx80Exp(ST1); + bool arg1_sign = extractFloatx80Sign(ST1); + + if (floatx80_is_signaling_nan(ST0, &env->fp_status)) { + float_raise(float_flag_invalid, &env->fp_status); + ST1 = floatx80_silence_nan(ST0, &env->fp_status); + } else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) { + float_raise(float_flag_invalid, &env->fp_status); + ST1 = floatx80_silence_nan(ST1, &env->fp_status); + } else if (floatx80_invalid_encoding(ST0) || + floatx80_invalid_encoding(ST1)) { + float_raise(float_flag_invalid, &env->fp_status); + ST1 = floatx80_default_nan(&env->fp_status); + } else if (floatx80_is_any_nan(ST0)) { + ST1 = ST0; + } else if (floatx80_is_any_nan(ST1)) { + /* Pass this NaN through. */ + } else if (arg0_exp > 0x3ffd || + (arg0_exp == 0x3ffd && arg0_sig > (arg0_sign ? + 0x95f619980c4336f7ULL : + 0xd413cccfe7799211ULL))) { + /* + * Out of range for the instruction (ST0 must have absolute + * value less than 1 - sqrt(2)/2 = 0.292..., according to + * Intel manuals; AMD manuals allow a range from sqrt(2)/2 - 1 + * to sqrt(2) - 1, which we allow here), treat as invalid. + */ + float_raise(float_flag_invalid, &env->fp_status); + ST1 = floatx80_default_nan(&env->fp_status); + } else if (floatx80_is_zero(ST0) || floatx80_is_zero(ST1) || + arg1_exp == 0x7fff) { + /* + * One argument is zero, or multiplying by infinity; correct + * result is exact and can be obtained by multiplying the + * arguments. + */ + ST1 = floatx80_mul(ST0, ST1, &env->fp_status); + } else if (arg0_exp < 0x3fb0) { + /* + * Multiplying both arguments and an extra-precision version + * of log2(e) is sufficiently precise. + */ + uint64_t sig0, sig1, sig2; + int32_t exp; + if (arg0_exp == 0) { + normalizeFloatx80Subnormal(arg0_sig, &arg0_exp, &arg0_sig); + } + if (arg1_exp == 0) { + normalizeFloatx80Subnormal(arg1_sig, &arg1_exp, &arg1_sig); + } + mul128By64To192(log2_e_sig_high, log2_e_sig_low, arg0_sig, + &sig0, &sig1, &sig2); + exp = arg0_exp + 1; + mul128By64To192(sig0, sig1, arg1_sig, &sig0, &sig1, &sig2); + exp += arg1_exp - 0x3ffe; + /* This result is inexact. */ + sig1 |= 1; + ST1 = normalizeRoundAndPackFloatx80(80, arg0_sign ^ arg1_sign, exp, + sig0, sig1, &env->fp_status); + } else { + int32_t aexp; + uint64_t asig0, asig1, asig2; + FloatRoundMode save_mode = env->fp_status.float_rounding_mode; + signed char save_prec = env->fp_status.floatx80_rounding_precision; + env->fp_status.float_rounding_mode = float_round_nearest_even; + env->fp_status.floatx80_rounding_precision = 80; + + helper_fyl2x_common(env, ST0, &aexp, &asig0, &asig1); + /* + * Multiply by the second argument to compute the required + * result. + */ + if (arg1_exp == 0) { + normalizeFloatx80Subnormal(arg1_sig, &arg1_exp, &arg1_sig); + } + mul128By64To192(asig0, asig1, arg1_sig, &asig0, &asig1, &asig2); + aexp += arg1_exp - 0x3ffe; + /* This result is inexact. */ + asig1 |= 1; + env->fp_status.float_rounding_mode = save_mode; + ST1 = normalizeRoundAndPackFloatx80(80, arg0_sign ^ arg1_sign, aexp, + asig0, asig1, &env->fp_status); + env->fp_status.floatx80_rounding_precision = save_prec; + } + fpop(env); + merge_exception_flags(env, old_flags); +} - if ((fptemp + 1.0) > 0.0) { - fptemp = log(fptemp + 1.0) / log(2.0); /* log2(ST + 1.0) */ - fptemp *= floatx80_to_double(env, ST1); - ST1 = double_to_floatx80(env, fptemp); - fpop(env); +void helper_fyl2x(CPUX86State *env) +{ + uint8_t old_flags = save_exception_flags(env); + uint64_t arg0_sig = extractFloatx80Frac(ST0); + int32_t arg0_exp = extractFloatx80Exp(ST0); + bool arg0_sign = extractFloatx80Sign(ST0); + uint64_t arg1_sig = extractFloatx80Frac(ST1); + int32_t arg1_exp = extractFloatx80Exp(ST1); + bool arg1_sign = extractFloatx80Sign(ST1); + + if (floatx80_is_signaling_nan(ST0, &env->fp_status)) { + float_raise(float_flag_invalid, &env->fp_status); + ST1 = floatx80_silence_nan(ST0, &env->fp_status); + } else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) { + float_raise(float_flag_invalid, &env->fp_status); + ST1 = floatx80_silence_nan(ST1, &env->fp_status); + } else if (floatx80_invalid_encoding(ST0) || + floatx80_invalid_encoding(ST1)) { + float_raise(float_flag_invalid, &env->fp_status); + ST1 = floatx80_default_nan(&env->fp_status); + } else if (floatx80_is_any_nan(ST0)) { + ST1 = ST0; + } else if (floatx80_is_any_nan(ST1)) { + /* Pass this NaN through. */ + } else if (arg0_sign && !floatx80_is_zero(ST0)) { + float_raise(float_flag_invalid, &env->fp_status); + ST1 = floatx80_default_nan(&env->fp_status); + } else if (floatx80_is_infinity(ST1)) { + FloatRelation cmp = floatx80_compare(ST0, floatx80_one, + &env->fp_status); + switch (cmp) { + case float_relation_less: + ST1 = floatx80_chs(ST1); + break; + case float_relation_greater: + /* Result is infinity of the same sign as ST1. */ + break; + default: + float_raise(float_flag_invalid, &env->fp_status); + ST1 = floatx80_default_nan(&env->fp_status); + break; + } + } else if (floatx80_is_infinity(ST0)) { + if (floatx80_is_zero(ST1)) { + float_raise(float_flag_invalid, &env->fp_status); + ST1 = floatx80_default_nan(&env->fp_status); + } else if (arg1_sign) { + ST1 = floatx80_chs(ST0); + } else { + ST1 = ST0; + } + } else if (floatx80_is_zero(ST0)) { + if (floatx80_is_zero(ST1)) { + float_raise(float_flag_invalid, &env->fp_status); + ST1 = floatx80_default_nan(&env->fp_status); + } else { + /* Result is infinity with opposite sign to ST1. */ + float_raise(float_flag_divbyzero, &env->fp_status); + ST1 = make_floatx80(arg1_sign ? 0x7fff : 0xffff, + 0x8000000000000000ULL); + } + } else if (floatx80_is_zero(ST1)) { + if (floatx80_lt(ST0, floatx80_one, &env->fp_status)) { + ST1 = floatx80_chs(ST1); + } + /* Otherwise, ST1 is already the correct result. */ + } else if (floatx80_eq(ST0, floatx80_one, &env->fp_status)) { + if (arg1_sign) { + ST1 = floatx80_chs(floatx80_zero); + } else { + ST1 = floatx80_zero; + } } else { - env->fpus &= ~0x4700; - env->fpus |= 0x400; + int32_t int_exp; + floatx80 arg0_m1; + FloatRoundMode save_mode = env->fp_status.float_rounding_mode; + signed char save_prec = env->fp_status.floatx80_rounding_precision; + env->fp_status.float_rounding_mode = float_round_nearest_even; + env->fp_status.floatx80_rounding_precision = 80; + + if (arg0_exp == 0) { + normalizeFloatx80Subnormal(arg0_sig, &arg0_exp, &arg0_sig); + } + if (arg1_exp == 0) { + normalizeFloatx80Subnormal(arg1_sig, &arg1_exp, &arg1_sig); + } + int_exp = arg0_exp - 0x3fff; + if (arg0_sig > 0xb504f333f9de6484ULL) { + ++int_exp; + } + arg0_m1 = floatx80_sub(floatx80_scalbn(ST0, -int_exp, + &env->fp_status), + floatx80_one, &env->fp_status); + if (floatx80_is_zero(arg0_m1)) { + /* Exact power of 2; multiply by ST1. */ + env->fp_status.float_rounding_mode = save_mode; + ST1 = floatx80_mul(int32_to_floatx80(int_exp, &env->fp_status), + ST1, &env->fp_status); + } else { + bool asign = extractFloatx80Sign(arg0_m1); + int32_t aexp; + uint64_t asig0, asig1, asig2; + helper_fyl2x_common(env, arg0_m1, &aexp, &asig0, &asig1); + if (int_exp != 0) { + bool isign = (int_exp < 0); + int32_t iexp; + uint64_t isig; + int shift; + int_exp = isign ? -int_exp : int_exp; + shift = clz32(int_exp) + 32; + isig = int_exp; + isig <<= shift; + iexp = 0x403e - shift; + shift128RightJamming(asig0, asig1, iexp - aexp, + &asig0, &asig1); + if (asign == isign) { + add128(isig, 0, asig0, asig1, &asig0, &asig1); + } else { + sub128(isig, 0, asig0, asig1, &asig0, &asig1); + } + aexp = iexp; + asign = isign; + } + /* + * Multiply by the second argument to compute the required + * result. + */ + if (arg1_exp == 0) { + normalizeFloatx80Subnormal(arg1_sig, &arg1_exp, &arg1_sig); + } + mul128By64To192(asig0, asig1, arg1_sig, &asig0, &asig1, &asig2); + aexp += arg1_exp - 0x3ffe; + /* This result is inexact. */ + asig1 |= 1; + env->fp_status.float_rounding_mode = save_mode; + ST1 = normalizeRoundAndPackFloatx80(80, asign ^ arg1_sign, aexp, + asig0, asig1, &env->fp_status); + } + + env->fp_status.floatx80_rounding_precision = save_prec; } + fpop(env); + merge_exception_flags(env, old_flags); } void helper_fsqrt(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); if (floatx80_is_neg(ST0)) { env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */ env->fpus |= 0x400; } ST0 = floatx80_sqrt(ST0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fsincos(CPUX86State *env) @@ -940,17 +2239,60 @@ void helper_fsincos(CPUX86State *env) void helper_frndint(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); ST0 = floatx80_round_to_int(ST0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fscale(CPUX86State *env) { - if (floatx80_is_any_nan(ST1)) { + uint8_t old_flags = save_exception_flags(env); + if (floatx80_invalid_encoding(ST1) || floatx80_invalid_encoding(ST0)) { + float_raise(float_flag_invalid, &env->fp_status); + ST0 = floatx80_default_nan(&env->fp_status); + } else if (floatx80_is_any_nan(ST1)) { + if (floatx80_is_signaling_nan(ST0, &env->fp_status)) { + float_raise(float_flag_invalid, &env->fp_status); + } ST0 = ST1; + if (floatx80_is_signaling_nan(ST0, &env->fp_status)) { + float_raise(float_flag_invalid, &env->fp_status); + ST0 = floatx80_silence_nan(ST0, &env->fp_status); + } + } else if (floatx80_is_infinity(ST1) && + !floatx80_invalid_encoding(ST0) && + !floatx80_is_any_nan(ST0)) { + if (floatx80_is_neg(ST1)) { + if (floatx80_is_infinity(ST0)) { + float_raise(float_flag_invalid, &env->fp_status); + ST0 = floatx80_default_nan(&env->fp_status); + } else { + ST0 = (floatx80_is_neg(ST0) ? + floatx80_chs(floatx80_zero) : + floatx80_zero); + } + } else { + if (floatx80_is_zero(ST0)) { + float_raise(float_flag_invalid, &env->fp_status); + ST0 = floatx80_default_nan(&env->fp_status); + } else { + ST0 = (floatx80_is_neg(ST0) ? + floatx80_chs(floatx80_infinity) : + floatx80_infinity); + } + } } else { - int n = floatx80_to_int32_round_to_zero(ST1, &env->fp_status); + int n; + signed char save = env->fp_status.floatx80_rounding_precision; + uint8_t save_flags = get_float_exception_flags(&env->fp_status); + set_float_exception_flags(0, &env->fp_status); + n = floatx80_to_int32_round_to_zero(ST1, &env->fp_status); + set_float_exception_flags(save_flags, &env->fp_status); + env->fp_status.floatx80_rounding_precision = 80; ST0 = floatx80_scalbn(ST0, n, &env->fp_status); + env->fp_status.floatx80_rounding_precision = save; } + merge_exception_flags(env, old_flags); } void helper_fsin(CPUX86State *env) @@ -1000,7 +2342,7 @@ void helper_fxam_ST0(CPUX86State *env) if (expdif == MAXEXPD) { if (MANTD(temp) == 0x8000000000000000ULL) { env->fpus |= 0x500; /* Infinity */ - } else { + } else if (MANTD(temp) & 0x8000000000000000ULL) { env->fpus |= 0x100; /* NaN */ } } else if (expdif == 0) { @@ -1009,7 +2351,7 @@ void helper_fxam_ST0(CPUX86State *env) } else { env->fpus |= 0x4400; /* Denormal */ } - } else { + } else if (MANTD(temp) & 0x8000000000000000ULL) { env->fpus |= 0x400; } } @@ -1197,6 +2539,7 @@ static void do_xsave_fpu(CPUX86State *env, target_ulong ptr, uintptr_t ra) static void do_xsave_mxcsr(CPUX86State *env, target_ulong ptr, uintptr_t ra) { + update_mxcsr_from_sse_status(env); cpu_stl_data_ra(env, ptr + XO(legacy.mxcsr), env->mxcsr, ra); cpu_stl_data_ra(env, ptr + XO(legacy.mxcsr_mask), 0x0000ffff, ra); } @@ -1626,11 +2969,45 @@ void update_mxcsr_status(CPUX86State *env) } set_float_rounding_mode(rnd_type, &env->sse_status); + /* Set exception flags. */ + set_float_exception_flags((mxcsr & FPUS_IE ? float_flag_invalid : 0) | + (mxcsr & FPUS_ZE ? float_flag_divbyzero : 0) | + (mxcsr & FPUS_OE ? float_flag_overflow : 0) | + (mxcsr & FPUS_UE ? float_flag_underflow : 0) | + (mxcsr & FPUS_PE ? float_flag_inexact : 0), + &env->sse_status); + /* set denormals are zero */ set_flush_inputs_to_zero((mxcsr & SSE_DAZ) ? 1 : 0, &env->sse_status); /* set flush to zero */ - set_flush_to_zero((mxcsr & SSE_FZ) ? 1 : 0, &env->fp_status); + set_flush_to_zero((mxcsr & SSE_FZ) ? 1 : 0, &env->sse_status); +} + +void update_mxcsr_from_sse_status(CPUX86State *env) +{ + if (tcg_enabled()) { + uint8_t flags = get_float_exception_flags(&env->sse_status); + /* + * The MXCSR denormal flag has opposite semantics to + * float_flag_input_denormal (the softfloat code sets that flag + * only when flushing input denormals to zero, but SSE sets it + * only when not flushing them to zero), so is not converted + * here. + */ + env->mxcsr |= ((flags & float_flag_invalid ? FPUS_IE : 0) | + (flags & float_flag_divbyzero ? FPUS_ZE : 0) | + (flags & float_flag_overflow ? FPUS_OE : 0) | + (flags & float_flag_underflow ? FPUS_UE : 0) | + (flags & float_flag_inexact ? FPUS_PE : 0) | + (flags & float_flag_output_denormal ? FPUS_UE | FPUS_PE : + 0)); + } +} + +void helper_update_mxcsr(CPUX86State *env) +{ + update_mxcsr_from_sse_status(env); } void helper_ldmxcsr(CPUX86State *env, uint32_t val) diff --git a/target/i386/gdbstub.c b/target/i386/gdbstub.c index b98a99500ae15682323c9e2f1915da64cfad04c5..4a3de5f69da88a7e1d72ca9d7ad552a464b2fe21 100644 --- a/target/i386/gdbstub.c +++ b/target/i386/gdbstub.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -184,6 +184,7 @@ int x86_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) return gdb_get_reg32(mem_buf, 0); /* fop */ case IDX_MXCSR_REG: + update_mxcsr_from_sse_status(env); return gdb_get_reg32(mem_buf, env->mxcsr); case IDX_CTL_CR0_REG: diff --git a/target/i386/hax-all.c b/target/i386/hax-all.c index f9c83fff2547a21257c1ec3b14de977e84db54b9..fecfe8cd6e40d4891562204ba1c479db50ee0e08 100644 --- a/target/i386/hax-all.c +++ b/target/i386/hax-all.c @@ -28,13 +28,13 @@ #include "exec/address-spaces.h" #include "qemu-common.h" -#include "hax-i386.h" #include "sysemu/accel.h" #include "sysemu/reset.h" #include "sysemu/runstate.h" -#include "qemu/main-loop.h" #include "hw/boards.h" +#include "hax-cpus.h" + #define DEBUG_HAX 0 #define DPRINTF(fmt, ...) \ @@ -232,10 +232,10 @@ int hax_init_vcpu(CPUState *cpu) return ret; } -struct hax_vm *hax_vm_create(struct hax_state *hax) +struct hax_vm *hax_vm_create(struct hax_state *hax, int max_cpus) { struct hax_vm *vm; - int vm_id = 0, ret; + int vm_id = 0, ret, i; if (hax_invalid_fd(hax->fd)) { return NULL; @@ -245,6 +245,11 @@ struct hax_vm *hax_vm_create(struct hax_state *hax) return hax->vm; } + if (max_cpus > HAX_MAX_VCPU) { + fprintf(stderr, "Maximum VCPU number QEMU supported is %d\n", HAX_MAX_VCPU); + return NULL; + } + vm = g_new0(struct hax_vm, 1); ret = hax_host_create_vm(hax, &vm_id); @@ -259,6 +264,12 @@ struct hax_vm *hax_vm_create(struct hax_state *hax) goto error; } + vm->numvcpus = max_cpus; + vm->vcpus = g_new0(struct hax_vcpu_state *, vm->numvcpus); + for (i = 0; i < vm->numvcpus; i++) { + vm->vcpus[i] = NULL; + } + hax->vm = vm; return vm; @@ -272,27 +283,20 @@ int hax_vm_destroy(struct hax_vm *vm) { int i; - for (i = 0; i < HAX_MAX_VCPU; i++) + for (i = 0; i < vm->numvcpus; i++) if (vm->vcpus[i]) { fprintf(stderr, "VCPU should be cleaned before vm clean\n"); return -1; } hax_close_fd(vm->fd); + vm->numvcpus = 0; + g_free(vm->vcpus); g_free(vm); hax_global.vm = NULL; return 0; } -static void hax_handle_interrupt(CPUState *cpu, int mask) -{ - cpu->interrupt_request |= mask; - - if (!qemu_cpu_is_self(cpu)) { - qemu_cpu_kick(cpu); - } -} - -static int hax_init(ram_addr_t ram_size) +static int hax_init(ram_addr_t ram_size, int max_cpus) { struct hax_state *hax = NULL; struct hax_qemu_version qversion; @@ -324,7 +328,7 @@ static int hax_init(ram_addr_t ram_size) goto error; } - hax->vm = hax_vm_create(hax); + hax->vm = hax_vm_create(hax, max_cpus); if (!hax->vm) { fprintf(stderr, "Failed to create HAX VM\n"); ret = -EINVAL; @@ -336,7 +340,6 @@ static int hax_init(ram_addr_t ram_size) qversion.cur_version = hax_cur_version; qversion.min_version = hax_min_version; hax_notify_qemu_version(hax->vm->fd, &qversion); - cpu_interrupt_handler = hax_handle_interrupt; return ret; error: @@ -352,7 +355,7 @@ static int hax_init(ram_addr_t ram_size) static int hax_accel_init(MachineState *ms) { - int ret = hax_init(ms->ram_size); + int ret = hax_init(ms->ram_size, (int)ms->smp.max_cpus); if (ret && (ret != -ENOSPC)) { fprintf(stderr, "No accelerator found.\n"); @@ -361,6 +364,9 @@ static int hax_accel_init(MachineState *ms) !ret ? "working" : "not working", !ret ? "fast virt" : "emulation"); } + if (ret == 0) { + cpus_register_accel(&hax_cpus); + } return ret; } diff --git a/target/i386/hax-cpus.c b/target/i386/hax-cpus.c new file mode 100644 index 0000000000000000000000000000000000000000..f72c85bd49f80f21576270f985f0aa65974af57f --- /dev/null +++ b/target/i386/hax-cpus.c @@ -0,0 +1,85 @@ +/* + * QEMU HAX support + * + * Copyright IBM, Corp. 2008 + * Red Hat, Inc. 2008 + * + * Authors: + * Anthony Liguori + * Glauber Costa + * + * Copyright (c) 2011 Intel Corporation + * Written by: + * Jiang Yunhong + * Xin Xiaohui + * Zhang Xiantao + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" +#include "sysemu/runstate.h" +#include "sysemu/cpus.h" +#include "qemu/guest-random.h" + +#include "hax-cpus.h" + +static void *hax_cpu_thread_fn(void *arg) +{ + CPUState *cpu = arg; + int r; + + rcu_register_thread(); + qemu_mutex_lock_iothread(); + qemu_thread_get_self(cpu->thread); + + cpu->thread_id = qemu_get_thread_id(); + current_cpu = cpu; + hax_init_vcpu(cpu); + cpu_thread_signal_created(cpu); + qemu_guest_random_seed_thread_part2(cpu->random_seed); + + do { + if (cpu_can_run(cpu)) { + r = hax_smp_cpu_exec(cpu); + if (r == EXCP_DEBUG) { + cpu_handle_guest_debug(cpu); + } + } + + qemu_wait_io_event(cpu); + } while (!cpu->unplug || cpu_can_run(cpu)); + rcu_unregister_thread(); + return NULL; +} + +static void hax_start_vcpu_thread(CPUState *cpu) +{ + char thread_name[VCPU_THREAD_NAME_SIZE]; + + cpu->thread = g_malloc0(sizeof(QemuThread)); + cpu->halt_cond = g_malloc0(sizeof(QemuCond)); + qemu_cond_init(cpu->halt_cond); + + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HAX", + cpu->cpu_index); + qemu_thread_create(cpu->thread, thread_name, hax_cpu_thread_fn, + cpu, QEMU_THREAD_JOINABLE); +#ifdef _WIN32 + cpu->hThread = qemu_thread_get_handle(cpu->thread); +#endif +} + +const CpusAccel hax_cpus = { + .create_vcpu_thread = hax_start_vcpu_thread, + .kick_vcpu_thread = hax_kick_vcpu_thread, + + .synchronize_post_reset = hax_cpu_synchronize_post_reset, + .synchronize_post_init = hax_cpu_synchronize_post_init, + .synchronize_state = hax_cpu_synchronize_state, + .synchronize_pre_loadvm = hax_cpu_synchronize_pre_loadvm, +}; diff --git a/target/i386/hax-cpus.h b/target/i386/hax-cpus.h new file mode 100644 index 0000000000000000000000000000000000000000..ee8ab7a631cf5593f085f7085e8d6f59a9d5e9b9 --- /dev/null +++ b/target/i386/hax-cpus.h @@ -0,0 +1,33 @@ +/* + * Accelerator CPUS Interface + * + * Copyright 2020 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HAX_CPUS_H +#define HAX_CPUS_H + +#include "sysemu/cpus.h" + +extern const CpusAccel hax_cpus; + +#include "hax-interface.h" +#include "hax-i386.h" + +int hax_init_vcpu(CPUState *cpu); +int hax_smp_cpu_exec(CPUState *cpu); +int hax_populate_ram(uint64_t va, uint64_t size); + +void hax_cpu_synchronize_state(CPUState *cpu); +void hax_cpu_synchronize_post_reset(CPUState *cpu); +void hax_cpu_synchronize_post_init(CPUState *cpu); +void hax_cpu_synchronize_pre_loadvm(CPUState *cpu); + +int hax_vcpu_destroy(CPUState *cpu); +void hax_raise_event(CPUState *cpu); +void hax_reset_vcpu_state(void *opaque); + +#endif /* HAX_CPUS_H */ diff --git a/target/i386/hax-i386.h b/target/i386/hax-i386.h index 54e9d8b057f30e4c631fe18950b56039fb80cb11..48c4abe14e9f8816efc892e7034fc049cb8dcc66 100644 --- a/target/i386/hax-i386.h +++ b/target/i386/hax-i386.h @@ -41,13 +41,12 @@ struct hax_state { }; #define HAX_MAX_VCPU 0x10 -#define MAX_VM_ID 0x40 -#define MAX_VCPU_ID 0x40 struct hax_vm { hax_fd fd; int id; - struct hax_vcpu_state *vcpus[HAX_MAX_VCPU]; + int numvcpus; + struct hax_vcpu_state **vcpus; }; #ifdef NEED_CPU_H @@ -58,9 +57,11 @@ int valid_hax_tunnel_size(uint16_t size); /* Host specific functions */ int hax_mod_version(struct hax_state *hax, struct hax_module_version *version); int hax_inject_interrupt(CPUArchState *env, int vector); -struct hax_vm *hax_vm_create(struct hax_state *hax); +struct hax_vm *hax_vm_create(struct hax_state *hax, int max_cpus); int hax_vcpu_run(struct hax_vcpu_state *vcpu); int hax_vcpu_create(int id); +void hax_kick_vcpu_thread(CPUState *cpu); + int hax_sync_vcpu_state(CPUArchState *env, struct vcpu_state_t *state, int set); int hax_sync_msr(CPUArchState *env, struct hax_msr_data *msrs, int set); diff --git a/target/i386/hax-mem.c b/target/i386/hax-mem.c index 6bb5a249175cc9835625cdd4273cb86300a56d1d..71e637cf16bbdfca798565e735696ab3dfff4cb5 100644 --- a/target/i386/hax-mem.c +++ b/target/i386/hax-mem.c @@ -13,7 +13,7 @@ #include "exec/address-spaces.h" #include "qemu/error-report.h" -#include "target/i386/hax-i386.h" +#include "hax-cpus.h" #include "qemu/queue.h" #define DEBUG_HAX_MEM 0 diff --git a/target/i386/hax-posix.c b/target/i386/hax-posix.c index 3bad89f133376bc054c0a0523591f13294e58678..735a749d4b3d032a7c5fe1b95d383bab43587357 100644 --- a/target/i386/hax-posix.c +++ b/target/i386/hax-posix.c @@ -14,7 +14,8 @@ #include "qemu/osdep.h" #include -#include "target/i386/hax-i386.h" +#include "sysemu/cpus.h" +#include "hax-cpus.h" hax_fd hax_mod_open(void) { @@ -23,7 +24,7 @@ hax_fd hax_mod_open(void) fprintf(stderr, "Failed to open the hax module\n"); } - fcntl(fd, F_SETFD, FD_CLOEXEC); + qemu_set_cloexec(fd); return fd; } @@ -147,7 +148,7 @@ hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id) fd = open(vm_name, O_RDWR); g_free(vm_name); - fcntl(fd, F_SETFD, FD_CLOEXEC); + qemu_set_cloexec(fd); return fd; } @@ -200,7 +201,7 @@ hax_fd hax_host_open_vcpu(int vmid, int vcpuid) if (fd < 0) { fprintf(stderr, "Failed to open the vcpu devfs\n"); } - fcntl(fd, F_SETFD, FD_CLOEXEC); + qemu_set_cloexec(fd); return fd; } @@ -292,3 +293,13 @@ int hax_inject_interrupt(CPUArchState *env, int vector) return ioctl(fd, HAX_VCPU_IOCTL_INTERRUPT, &vector); } + +void hax_kick_vcpu_thread(CPUState *cpu) +{ + /* + * FIXME: race condition with the exit_request check in + * hax_vcpu_hax_exec + */ + cpu->exit_request = 1; + cpus_kick_thread(cpu); +} diff --git a/target/i386/hax-windows.c b/target/i386/hax-windows.c index 863c2bcc192b2d5630d22e18618c83c9bdad41cb..6c82dfb54fa44641c87d04b635b93c7e866597df 100644 --- a/target/i386/hax-windows.c +++ b/target/i386/hax-windows.c @@ -12,7 +12,7 @@ #include "qemu/osdep.h" #include "cpu.h" -#include "hax-i386.h" +#include "hax-cpus.h" /* * return 0 when success, -1 when driver not loaded, @@ -463,3 +463,23 @@ int hax_inject_interrupt(CPUArchState *env, int vector) return 0; } } + +static void CALLBACK dummy_apc_func(ULONG_PTR unused) +{ +} + +void hax_kick_vcpu_thread(CPUState *cpu) +{ + /* + * FIXME: race condition with the exit_request check in + * hax_vcpu_hax_exec + */ + cpu->exit_request = 1; + if (!qemu_cpu_is_self(cpu)) { + if (!QueueUserAPC(dummy_apc_func, cpu->hThread, 0)) { + fprintf(stderr, "%s: QueueUserAPC failed with error %lu\n", + __func__, GetLastError()); + exit(1); + } + } +} diff --git a/target/i386/hax-windows.h b/target/i386/hax-windows.h index 12cbd813dccf836c44af0ca01b8ba2ef711e6899..a5ce12d6637ea9a23d2bb63c733ae1ac6f71333a 100644 --- a/target/i386/hax-windows.h +++ b/target/i386/hax-windows.h @@ -23,6 +23,8 @@ #include #include +#include "hax-cpus.h" + #define HAX_INVALID_FD INVALID_HANDLE_VALUE static inline void hax_mod_close(struct hax_state *hax) diff --git a/target/i386/helper.c b/target/i386/helper.c index c3a6e4fabe20928cfb94eba8227a757107dbd664..034f46bcc2100f8e0472e4e43f8fd22b66101394 100644 --- a/target/i386/helper.c +++ b/target/i386/helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -18,6 +18,7 @@ */ #include "qemu/osdep.h" +#include "qapi/qapi-events-run-state.h" #include "cpu.h" #include "exec/exec-all.h" #include "qemu/qemu-print.h" @@ -370,10 +371,11 @@ void x86_cpu_dump_local_apic_state(CPUState *cs, int flags) dump_apic_lvt("LVTTHMR", lvt[APIC_LVT_THERMAL], false); dump_apic_lvt("LVTT", lvt[APIC_LVT_TIMER], true); - qemu_printf("Timer\t DCR=0x%x (divide by %u) initial_count = %u\n", + qemu_printf("Timer\t DCR=0x%x (divide by %u) initial_count = %u" + " current_count = %u\n", s->divide_conf & APIC_DCR_MASK, divider_conf(s->divide_conf), - s->initial_count); + s->initial_count, apic_get_current_count(s)); qemu_printf("SPIV\t 0x%08x APIC %s, focus=%s, spurious vec %u\n", s->spurious_vec, @@ -544,6 +546,7 @@ void x86_cpu_dump_state(CPUState *cs, FILE *f, int flags) for(i = 0; i < 8; i++) { fptag |= ((!env->fptags[i]) << i); } + update_mxcsr_from_sse_status(env); qemu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n", env->fpuc, (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11, @@ -849,22 +852,35 @@ typedef struct MCEInjectionParams { int flags; } MCEInjectionParams; +static void emit_guest_memory_failure(MemoryFailureAction action, bool ar, + bool recursive) +{ + MemoryFailureFlags mff = {.action_required = ar, .recursive = recursive}; + + qapi_event_send_memory_failure(MEMORY_FAILURE_RECIPIENT_GUEST, action, + &mff); +} + static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data) { MCEInjectionParams *params = data.host_ptr; X86CPU *cpu = X86_CPU(cs); CPUX86State *cenv = &cpu->env; uint64_t *banks = cenv->mce_banks + 4 * params->bank; + g_autofree char *msg = NULL; + bool need_reset = false; + bool recursive; + bool ar = !!(params->status & MCI_STATUS_AR); cpu_synchronize_state(cs); + recursive = !!(cenv->mcg_status & MCG_STATUS_MCIP); /* * If there is an MCE exception being processed, ignore this SRAO MCE * unless unconditional injection was requested. */ - if (!(params->flags & MCE_INJECT_UNCOND_AO) - && !(params->status & MCI_STATUS_AR) - && (cenv->mcg_status & MCG_STATUS_MCIP)) { + if (!(params->flags & MCE_INJECT_UNCOND_AO) && !ar && recursive) { + emit_guest_memory_failure(MEMORY_FAILURE_ACTION_IGNORE, ar, recursive); return; } @@ -892,16 +908,25 @@ static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data) return; } - if ((cenv->mcg_status & MCG_STATUS_MCIP) || - !(cenv->cr[4] & CR4_MCE_MASK)) { - monitor_printf(params->mon, - "CPU %d: Previous MCE still in progress, raising" - " triple fault\n", - cs->cpu_index); - qemu_log_mask(CPU_LOG_RESET, "Triple fault\n"); + if (!(cenv->cr[4] & CR4_MCE_MASK)) { + need_reset = true; + msg = g_strdup_printf("CPU %d: MCE capability is not enabled, " + "raising triple fault", cs->cpu_index); + } else if (recursive) { + need_reset = true; + msg = g_strdup_printf("CPU %d: Previous MCE still in progress, " + "raising triple fault", cs->cpu_index); + } + + if (need_reset) { + emit_guest_memory_failure(MEMORY_FAILURE_ACTION_RESET, ar, + recursive); + monitor_printf(params->mon, "%s", msg); + qemu_log_mask(CPU_LOG_RESET, "%s\n", msg); qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); return; } + if (banks[1] & MCI_STATUS_VAL) { params->status |= MCI_STATUS_OVER; } @@ -921,6 +946,8 @@ static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data) } else { banks[1] |= MCI_STATUS_OVER; } + + emit_guest_memory_failure(MEMORY_FAILURE_ACTION_INJECT, ar, recursive); } void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank, diff --git a/target/i386/helper.h b/target/i386/helper.h index 8f9e1905c3c694766d2a1341f1d3d3b381300d1c..c2ae2f7e61bafe6fac8ef52ed479c88846de836b 100644 --- a/target/i386/helper.h +++ b/target/i386/helper.h @@ -207,6 +207,7 @@ DEF_HELPER_FLAGS_2(pext, TCG_CALL_NO_RWG_SE, tl, tl, tl) /* MMX/SSE */ DEF_HELPER_2(ldmxcsr, void, env, i32) +DEF_HELPER_1(update_mxcsr, void, env) DEF_HELPER_1(enter_mmx, void, env) DEF_HELPER_1(emms, void, env) DEF_HELPER_3(movq, void, env, ptr, ptr) diff --git a/target/i386/hvf/Makefile.objs b/target/i386/hvf/Makefile.objs deleted file mode 100644 index 927b86bc6704699172853de66e3e18e6cb61beed..0000000000000000000000000000000000000000 --- a/target/i386/hvf/Makefile.objs +++ /dev/null @@ -1,2 +0,0 @@ -obj-y += hvf.o -obj-y += x86.o x86_cpuid.o x86_decode.o x86_descr.o x86_emu.o x86_flags.o x86_mmu.o x86hvf.o x86_task.o diff --git a/target/i386/hvf/hvf-cpus.c b/target/i386/hvf/hvf-cpus.c new file mode 100644 index 0000000000000000000000000000000000000000..817b3d7452927d6752fcf0c3977282bccc38075e --- /dev/null +++ b/target/i386/hvf/hvf-cpus.c @@ -0,0 +1,131 @@ +/* + * Copyright 2008 IBM Corporation + * 2008 Red Hat, Inc. + * Copyright 2011 Intel Corporation + * Copyright 2016 Veertu, Inc. + * Copyright 2017 The Android Open Source Project + * + * QEMU Hypervisor.framework support + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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 . + * + * This file contain code under public domain from the hvdos project: + * https://github.com/mist64/hvdos + * + * Parts Copyright (c) 2011 NetApp, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" +#include "sysemu/hvf.h" +#include "sysemu/runstate.h" +#include "target/i386/cpu.h" +#include "qemu/guest-random.h" + +#include "hvf-cpus.h" + +/* + * The HVF-specific vCPU thread function. This one should only run when the host + * CPU supports the VMX "unrestricted guest" feature. + */ +static void *hvf_cpu_thread_fn(void *arg) +{ + CPUState *cpu = arg; + + int r; + + assert(hvf_enabled()); + + rcu_register_thread(); + + qemu_mutex_lock_iothread(); + qemu_thread_get_self(cpu->thread); + + cpu->thread_id = qemu_get_thread_id(); + cpu->can_do_io = 1; + current_cpu = cpu; + + hvf_init_vcpu(cpu); + + /* signal CPU creation */ + cpu_thread_signal_created(cpu); + qemu_guest_random_seed_thread_part2(cpu->random_seed); + + do { + if (cpu_can_run(cpu)) { + r = hvf_vcpu_exec(cpu); + if (r == EXCP_DEBUG) { + cpu_handle_guest_debug(cpu); + } + } + qemu_wait_io_event(cpu); + } while (!cpu->unplug || cpu_can_run(cpu)); + + hvf_vcpu_destroy(cpu); + cpu_thread_signal_destroyed(cpu); + qemu_mutex_unlock_iothread(); + rcu_unregister_thread(); + return NULL; +} + +static void hvf_start_vcpu_thread(CPUState *cpu) +{ + char thread_name[VCPU_THREAD_NAME_SIZE]; + + /* + * HVF currently does not support TCG, and only runs in + * unrestricted-guest mode. + */ + assert(hvf_enabled()); + + cpu->thread = g_malloc0(sizeof(QemuThread)); + cpu->halt_cond = g_malloc0(sizeof(QemuCond)); + qemu_cond_init(cpu->halt_cond); + + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HVF", + cpu->cpu_index); + qemu_thread_create(cpu->thread, thread_name, hvf_cpu_thread_fn, + cpu, QEMU_THREAD_JOINABLE); +} + +const CpusAccel hvf_cpus = { + .create_vcpu_thread = hvf_start_vcpu_thread, + + .synchronize_post_reset = hvf_cpu_synchronize_post_reset, + .synchronize_post_init = hvf_cpu_synchronize_post_init, + .synchronize_state = hvf_cpu_synchronize_state, + .synchronize_pre_loadvm = hvf_cpu_synchronize_pre_loadvm, +}; diff --git a/target/i386/hvf/hvf-cpus.h b/target/i386/hvf/hvf-cpus.h new file mode 100644 index 0000000000000000000000000000000000000000..ced31b82c0ea7dacc6a428924d708a8f96365449 --- /dev/null +++ b/target/i386/hvf/hvf-cpus.h @@ -0,0 +1,25 @@ +/* + * Accelerator CPUS Interface + * + * Copyright 2020 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HVF_CPUS_H +#define HVF_CPUS_H + +#include "sysemu/cpus.h" + +extern const CpusAccel hvf_cpus; + +int hvf_init_vcpu(CPUState *); +int hvf_vcpu_exec(CPUState *); +void hvf_cpu_synchronize_state(CPUState *); +void hvf_cpu_synchronize_post_reset(CPUState *); +void hvf_cpu_synchronize_post_init(CPUState *); +void hvf_cpu_synchronize_pre_loadvm(CPUState *); +void hvf_vcpu_destroy(CPUState *); + +#endif /* HVF_CPUS_H */ diff --git a/target/i386/hvf/hvf-i386.h b/target/i386/hvf/hvf-i386.h index 15ee4835cf180367e7cbe5501efea852a8466577..e0edffd077a9658aedd82fed3241a848df72b72c 100644 --- a/target/i386/hvf/hvf-i386.h +++ b/target/i386/hvf/hvf-i386.h @@ -16,13 +16,12 @@ #ifndef HVF_I386_H #define HVF_I386_H +#include "sysemu/accel.h" #include "sysemu/hvf.h" #include "cpu.h" #include "x86.h" #define HVF_MAX_VCPU 0x10 -#define MAX_VM_ID 0x40 -#define MAX_VCPU_ID 0x40 extern struct hvf_state hvf_global; @@ -37,6 +36,40 @@ struct hvf_state { uint64_t mem_quota; }; +/* hvf_slot flags */ +#define HVF_SLOT_LOG (1 << 0) + +typedef struct hvf_slot { + uint64_t start; + uint64_t size; + uint8_t *mem; + int slot_id; + uint32_t flags; + MemoryRegion *region; +} hvf_slot; + +typedef struct hvf_vcpu_caps { + uint64_t vmx_cap_pinbased; + uint64_t vmx_cap_procbased; + uint64_t vmx_cap_procbased2; + uint64_t vmx_cap_entry; + uint64_t vmx_cap_exit; + uint64_t vmx_cap_preemption_timer; +} hvf_vcpu_caps; + +struct HVFState { + AccelState parent; + hvf_slot slots[32]; + int num_slots; + + hvf_vcpu_caps *hvf_caps; +}; +extern HVFState *hvf_state; + +void hvf_set_phys_mem(MemoryRegionSection *, bool); +void hvf_handle_io(CPUArchState *, uint16_t, void *, int, int, int); +hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t); + #ifdef NEED_CPU_H /* Functions exported to host specific mode */ diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index d72543dc31b65f21302e2e139ef687eb36b80b61..ed9356565c920395791603615e1c08eec45e5205 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -72,6 +72,8 @@ #include "sysemu/accel.h" #include "target/i386/cpu.h" +#include "hvf-cpus.h" + HVFState *hvf_state; static void assert_hvf_ok(hv_return_t ret) @@ -251,7 +253,7 @@ void vmx_update_tpr(CPUState *cpu) } } -void update_apic_tpr(CPUState *cpu) +static void update_apic_tpr(CPUState *cpu) { X86CPU *x86_cpu = X86_CPU(cpu); int tpr = rreg(cpu->hvf_fd, HV_X86_TPR) >> 4; @@ -260,14 +262,6 @@ void update_apic_tpr(CPUState *cpu) #define VECTORING_INFO_VECTOR_MASK 0xff -static void hvf_handle_interrupt(CPUState * cpu, int mask) -{ - cpu->interrupt_request |= mask; - if (!qemu_cpu_is_self(cpu)) { - qemu_cpu_kick(cpu); - } -} - void hvf_handle_io(CPUArchState *env, uint16_t port, void *buffer, int direction, int size, int count) { @@ -282,46 +276,54 @@ void hvf_handle_io(CPUArchState *env, uint16_t port, void *buffer, } } -/* TODO: synchronize vcpu state */ static void do_hvf_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg) { - CPUState *cpu_state = cpu; - if (cpu_state->vcpu_dirty == 0) { - hvf_get_registers(cpu_state); + if (!cpu->vcpu_dirty) { + hvf_get_registers(cpu); + cpu->vcpu_dirty = true; } - - cpu_state->vcpu_dirty = 1; } -void hvf_cpu_synchronize_state(CPUState *cpu_state) +void hvf_cpu_synchronize_state(CPUState *cpu) { - if (cpu_state->vcpu_dirty == 0) { - run_on_cpu(cpu_state, do_hvf_cpu_synchronize_state, RUN_ON_CPU_NULL); + if (!cpu->vcpu_dirty) { + run_on_cpu(cpu, do_hvf_cpu_synchronize_state, RUN_ON_CPU_NULL); } } -static void do_hvf_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg) +static void do_hvf_cpu_synchronize_post_reset(CPUState *cpu, + run_on_cpu_data arg) +{ + hvf_put_registers(cpu); + cpu->vcpu_dirty = false; +} + +void hvf_cpu_synchronize_post_reset(CPUState *cpu) +{ + run_on_cpu(cpu, do_hvf_cpu_synchronize_post_reset, RUN_ON_CPU_NULL); +} + +static void do_hvf_cpu_synchronize_post_init(CPUState *cpu, + run_on_cpu_data arg) { - CPUState *cpu_state = cpu; - hvf_put_registers(cpu_state); - cpu_state->vcpu_dirty = false; + hvf_put_registers(cpu); + cpu->vcpu_dirty = false; } -void hvf_cpu_synchronize_post_reset(CPUState *cpu_state) +void hvf_cpu_synchronize_post_init(CPUState *cpu) { - run_on_cpu(cpu_state, do_hvf_cpu_synchronize_post_reset, RUN_ON_CPU_NULL); + run_on_cpu(cpu, do_hvf_cpu_synchronize_post_init, RUN_ON_CPU_NULL); } -void _hvf_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg) +static void do_hvf_cpu_synchronize_pre_loadvm(CPUState *cpu, + run_on_cpu_data arg) { - CPUState *cpu_state = cpu; - hvf_put_registers(cpu_state); - cpu_state->vcpu_dirty = false; + cpu->vcpu_dirty = true; } -void hvf_cpu_synchronize_post_init(CPUState *cpu_state) +void hvf_cpu_synchronize_pre_loadvm(CPUState *cpu) { - run_on_cpu(cpu_state, _hvf_cpu_synchronize_post_init, RUN_ON_CPU_NULL); + run_on_cpu(cpu, do_hvf_cpu_synchronize_pre_loadvm, RUN_ON_CPU_NULL); } static bool ept_emulation_fault(hvf_slot *slot, uint64_t gpa, uint64_t ept_qual) @@ -440,99 +442,13 @@ static MemoryListener hvf_memory_listener = { .log_sync = hvf_log_sync, }; -void hvf_reset_vcpu(CPUState *cpu) { - uint64_t pdpte[4] = {0, 0, 0, 0}; - int i; - - /* TODO: this shouldn't be needed; there is already a call to - * cpu_synchronize_all_post_reset in vl.c - */ - wvmcs(cpu->hvf_fd, VMCS_ENTRY_CTLS, 0); - wvmcs(cpu->hvf_fd, VMCS_GUEST_IA32_EFER, 0); - - /* Initialize PDPTE */ - for (i = 0; i < 4; i++) { - wvmcs(cpu->hvf_fd, VMCS_GUEST_PDPTE0 + i * 2, pdpte[i]); - } - - macvm_set_cr0(cpu->hvf_fd, 0x60000010); - - wvmcs(cpu->hvf_fd, VMCS_CR4_MASK, CR4_VMXE_MASK); - wvmcs(cpu->hvf_fd, VMCS_CR4_SHADOW, 0x0); - wvmcs(cpu->hvf_fd, VMCS_GUEST_CR4, CR4_VMXE_MASK); - - /* set VMCS guest state fields */ - wvmcs(cpu->hvf_fd, VMCS_GUEST_CS_SELECTOR, 0xf000); - wvmcs(cpu->hvf_fd, VMCS_GUEST_CS_LIMIT, 0xffff); - wvmcs(cpu->hvf_fd, VMCS_GUEST_CS_ACCESS_RIGHTS, 0x9b); - wvmcs(cpu->hvf_fd, VMCS_GUEST_CS_BASE, 0xffff0000); - - wvmcs(cpu->hvf_fd, VMCS_GUEST_DS_SELECTOR, 0); - wvmcs(cpu->hvf_fd, VMCS_GUEST_DS_LIMIT, 0xffff); - wvmcs(cpu->hvf_fd, VMCS_GUEST_DS_ACCESS_RIGHTS, 0x93); - wvmcs(cpu->hvf_fd, VMCS_GUEST_DS_BASE, 0); - - wvmcs(cpu->hvf_fd, VMCS_GUEST_ES_SELECTOR, 0); - wvmcs(cpu->hvf_fd, VMCS_GUEST_ES_LIMIT, 0xffff); - wvmcs(cpu->hvf_fd, VMCS_GUEST_ES_ACCESS_RIGHTS, 0x93); - wvmcs(cpu->hvf_fd, VMCS_GUEST_ES_BASE, 0); - - wvmcs(cpu->hvf_fd, VMCS_GUEST_FS_SELECTOR, 0); - wvmcs(cpu->hvf_fd, VMCS_GUEST_FS_LIMIT, 0xffff); - wvmcs(cpu->hvf_fd, VMCS_GUEST_FS_ACCESS_RIGHTS, 0x93); - wvmcs(cpu->hvf_fd, VMCS_GUEST_FS_BASE, 0); - - wvmcs(cpu->hvf_fd, VMCS_GUEST_GS_SELECTOR, 0); - wvmcs(cpu->hvf_fd, VMCS_GUEST_GS_LIMIT, 0xffff); - wvmcs(cpu->hvf_fd, VMCS_GUEST_GS_ACCESS_RIGHTS, 0x93); - wvmcs(cpu->hvf_fd, VMCS_GUEST_GS_BASE, 0); - - wvmcs(cpu->hvf_fd, VMCS_GUEST_SS_SELECTOR, 0); - wvmcs(cpu->hvf_fd, VMCS_GUEST_SS_LIMIT, 0xffff); - wvmcs(cpu->hvf_fd, VMCS_GUEST_SS_ACCESS_RIGHTS, 0x93); - wvmcs(cpu->hvf_fd, VMCS_GUEST_SS_BASE, 0); - - wvmcs(cpu->hvf_fd, VMCS_GUEST_LDTR_SELECTOR, 0); - wvmcs(cpu->hvf_fd, VMCS_GUEST_LDTR_LIMIT, 0); - wvmcs(cpu->hvf_fd, VMCS_GUEST_LDTR_ACCESS_RIGHTS, 0x10000); - wvmcs(cpu->hvf_fd, VMCS_GUEST_LDTR_BASE, 0); - - wvmcs(cpu->hvf_fd, VMCS_GUEST_TR_SELECTOR, 0); - wvmcs(cpu->hvf_fd, VMCS_GUEST_TR_LIMIT, 0); - wvmcs(cpu->hvf_fd, VMCS_GUEST_TR_ACCESS_RIGHTS, 0x83); - wvmcs(cpu->hvf_fd, VMCS_GUEST_TR_BASE, 0); - - wvmcs(cpu->hvf_fd, VMCS_GUEST_GDTR_LIMIT, 0); - wvmcs(cpu->hvf_fd, VMCS_GUEST_GDTR_BASE, 0); - - wvmcs(cpu->hvf_fd, VMCS_GUEST_IDTR_LIMIT, 0); - wvmcs(cpu->hvf_fd, VMCS_GUEST_IDTR_BASE, 0); - - /*wvmcs(cpu->hvf_fd, VMCS_GUEST_CR2, 0x0);*/ - wvmcs(cpu->hvf_fd, VMCS_GUEST_CR3, 0x0); - - wreg(cpu->hvf_fd, HV_X86_RIP, 0xfff0); - wreg(cpu->hvf_fd, HV_X86_RDX, 0x623); - wreg(cpu->hvf_fd, HV_X86_RFLAGS, 0x2); - wreg(cpu->hvf_fd, HV_X86_RSP, 0x0); - wreg(cpu->hvf_fd, HV_X86_RAX, 0x0); - wreg(cpu->hvf_fd, HV_X86_RBX, 0x0); - wreg(cpu->hvf_fd, HV_X86_RCX, 0x0); - wreg(cpu->hvf_fd, HV_X86_RSI, 0x0); - wreg(cpu->hvf_fd, HV_X86_RDI, 0x0); - wreg(cpu->hvf_fd, HV_X86_RBP, 0x0); - - for (int i = 0; i < 8; i++) { - wreg(cpu->hvf_fd, HV_X86_R8 + i, 0x0); - } - - hv_vcpu_invalidate_tlb(cpu->hvf_fd); - hv_vcpu_flush(cpu->hvf_fd); -} - void hvf_vcpu_destroy(CPUState *cpu) { + X86CPU *x86_cpu = X86_CPU(cpu); + CPUX86State *env = &x86_cpu->env; + hv_return_t ret = hv_vcpu_destroy((hv_vcpuid_t)cpu->hvf_fd); + g_free(env->hvf_mmio_buf); assert_hvf_ok(ret); } @@ -562,7 +478,7 @@ int hvf_init_vcpu(CPUState *cpu) init_decoder(); hvf_state->hvf_caps = g_new0(struct hvf_vcpu_caps, 1); - env->hvf_emul = g_new0(HVFX86EmulatorState, 1); + env->hvf_mmio_buf = g_new(char, 4096); r = hv_vcpu_create((hv_vcpuid_t *)&cpu->hvf_fd, HV_VCPU_DEFAULT); cpu->vcpu_dirty = 1; @@ -722,8 +638,7 @@ int hvf_vcpu_exec(CPUState *cpu) hvf_store_events(cpu, ins_len, idtvec_info); rip = rreg(cpu->hvf_fd, HV_X86_RIP); - RFLAGS(env) = rreg(cpu->hvf_fd, HV_X86_RFLAGS); - env->eflags = RFLAGS(env); + env->eflags = rreg(cpu->hvf_fd, HV_X86_RFLAGS); qemu_mutex_lock_iothread(); @@ -735,7 +650,7 @@ int hvf_vcpu_exec(CPUState *cpu) case EXIT_REASON_HLT: { macvm_set_rip(cpu, rip + ins_len); if (!((cpu->interrupt_request & CPU_INTERRUPT_HARD) && - (EFLAGS(env) & IF_MASK)) + (env->eflags & IF_MASK)) && !(cpu->interrupt_request & CPU_INTERRUPT_NMI) && !(idtvec_info & VMCS_IDT_VEC_VALID)) { cpu->halted = 1; @@ -766,8 +681,6 @@ int hvf_vcpu_exec(CPUState *cpu) struct x86_decode decode; load_regs(cpu); - env->hvf_emul->fetch_rip = rip; - decode_instruction(env, &decode); exec_instruction(env, &decode); store_regs(cpu); @@ -796,7 +709,7 @@ int hvf_vcpu_exec(CPUState *cpu) } else { RAX(env) = (uint64_t)val; } - RIP(env) += ins_len; + env->eip += ins_len; store_regs(cpu); break; } else if (!string && !in) { @@ -808,8 +721,6 @@ int hvf_vcpu_exec(CPUState *cpu) struct x86_decode decode; load_regs(cpu); - env->hvf_emul->fetch_rip = rip; - decode_instruction(env, &decode); assert(ins_len == decode.len); exec_instruction(env, &decode); @@ -870,7 +781,7 @@ int hvf_vcpu_exec(CPUState *cpu) } else { simulate_wrmsr(cpu); } - RIP(env) += rvmcs(cpu->hvf_fd, VMCS_EXIT_INSTRUCTION_LENGTH); + env->eip += ins_len; store_regs(cpu); break; } @@ -906,7 +817,7 @@ int hvf_vcpu_exec(CPUState *cpu) error_report("Unrecognized CR %d", cr); abort(); } - RIP(env) += ins_len; + env->eip += ins_len; store_regs(cpu); break; } @@ -914,8 +825,6 @@ int hvf_vcpu_exec(CPUState *cpu) struct x86_decode decode; load_regs(cpu); - env->hvf_emul->fetch_rip = rip; - decode_instruction(env, &decode); exec_instruction(env, &decode); store_regs(cpu); @@ -977,8 +886,8 @@ static int hvf_accel_init(MachineState *ms) } hvf_state = s; - cpu_interrupt_handler = hvf_handle_interrupt; memory_listener_register(&hvf_memory_listener, &address_space_memory); + cpus_register_accel(&hvf_cpus); return 0; } diff --git a/target/i386/hvf/meson.build b/target/i386/hvf/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..409c9a3f14467fb0cfca624b3531fa598e94b6ce --- /dev/null +++ b/target/i386/hvf/meson.build @@ -0,0 +1,13 @@ +i386_softmmu_ss.add(when: [hvf, 'CONFIG_HVF'], if_true: files( + 'hvf.c', + 'hvf-cpus.c', + 'x86.c', + 'x86_cpuid.c', + 'x86_decode.c', + 'x86_descr.c', + 'x86_emu.c', + 'x86_flags.c', + 'x86_mmu.c', + 'x86_task.c', + 'x86hvf.c', +)) diff --git a/target/i386/hvf/panic.h b/target/i386/hvf/panic.h index 411ef43a5bf03490bdc7e411eb15db5682e68142..a3eabebbb49dff9ff5e1ec5c8de19667ebd11faa 100644 --- a/target/i386/hvf/panic.h +++ b/target/i386/hvf/panic.h @@ -5,7 +5,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 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 diff --git a/target/i386/hvf/vmx.h b/target/i386/hvf/vmx.h index ce2a1532d5581470df5f68436127ab0c6cd5e5af..24c4cdf0be0cc6e509916257379a2640ece47da5 100644 --- a/target/i386/hvf/vmx.h +++ b/target/i386/hvf/vmx.h @@ -8,7 +8,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 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 @@ -121,7 +121,9 @@ static inline void macvm_set_cr0(hv_vcpuid_t vcpu, uint64_t cr0) uint64_t pdpte[4] = {0, 0, 0, 0}; uint64_t efer = rvmcs(vcpu, VMCS_GUEST_IA32_EFER); uint64_t old_cr0 = rvmcs(vcpu, VMCS_GUEST_CR0); + uint64_t changed_cr0 = old_cr0 ^ cr0; uint64_t mask = CR0_PG | CR0_CD | CR0_NW | CR0_NE | CR0_ET; + uint64_t entry_ctls; if ((cr0 & CR0_PG) && (rvmcs(vcpu, VMCS_GUEST_CR4) & CR4_PAE) && !(efer & MSR_EFER_LME)) { @@ -138,12 +140,16 @@ static inline void macvm_set_cr0(hv_vcpuid_t vcpu, uint64_t cr0) wvmcs(vcpu, VMCS_CR0_SHADOW, cr0); if (efer & MSR_EFER_LME) { - if (!(old_cr0 & CR0_PG) && (cr0 & CR0_PG)) { - enter_long_mode(vcpu, cr0, efer); - } - if (/*(old_cr0 & CR0_PG) &&*/ !(cr0 & CR0_PG)) { - exit_long_mode(vcpu, cr0, efer); + if (changed_cr0 & CR0_PG) { + if (cr0 & CR0_PG) { + enter_long_mode(vcpu, cr0, efer); + } else { + exit_long_mode(vcpu, cr0, efer); + } } + } else { + entry_ctls = rvmcs(vcpu, VMCS_ENTRY_CTLS); + wvmcs(vcpu, VMCS_ENTRY_CTLS, entry_ctls & ~VM_ENTRY_GUEST_LMA); } /* Filter new CR0 after we are finished examining it above. */ @@ -160,6 +166,7 @@ static inline void macvm_set_cr4(hv_vcpuid_t vcpu, uint64_t cr4) wvmcs(vcpu, VMCS_GUEST_CR4, guest_cr4); wvmcs(vcpu, VMCS_CR4_SHADOW, cr4); + wvmcs(vcpu, VMCS_CR4_MASK, CR4_VMXE); hv_vcpu_invalidate_tlb(vcpu); hv_vcpu_flush(vcpu); @@ -173,6 +180,7 @@ static inline void macvm_set_rip(CPUState *cpu, uint64_t rip) /* BUG, should take considering overlap.. */ wreg(cpu->hvf_fd, HV_X86_RIP, rip); + env->eip = rip; /* after moving forward in rip, we need to clean INTERRUPTABILITY */ val = rvmcs(cpu->hvf_fd, VMCS_GUEST_INTERRUPTIBILITY); diff --git a/target/i386/hvf/x86.c b/target/i386/hvf/x86.c index 3afcedc7fc047714d0775854a7beff438e3cec87..cd045183a811857fde2174d96a2393c53bcd8ae9 100644 --- a/target/i386/hvf/x86.c +++ b/target/i386/hvf/x86.c @@ -5,7 +5,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 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 @@ -131,7 +131,7 @@ bool x86_is_v8086(struct CPUState *cpu) { X86CPU *x86_cpu = X86_CPU(cpu); CPUX86State *env = &x86_cpu->env; - return x86_is_protected(cpu) && (RFLAGS(env) & RFLAGS_VM); + return x86_is_protected(cpu) && (env->eflags & VM_MASK); } bool x86_is_long_mode(struct CPUState *cpu) diff --git a/target/i386/hvf/x86.h b/target/i386/hvf/x86.h index c95d5b21167406fb27107f7b8c658605d61babe2..782664c2eab87a5e8200082d887557e679bc7121 100644 --- a/target/i386/hvf/x86.h +++ b/target/i386/hvf/x86.h @@ -5,7 +5,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 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 @@ -42,64 +42,6 @@ typedef struct x86_register { }; } __attribute__ ((__packed__)) x86_register; -typedef enum x86_rflags { - RFLAGS_CF = (1L << 0), - RFLAGS_PF = (1L << 2), - RFLAGS_AF = (1L << 4), - RFLAGS_ZF = (1L << 6), - RFLAGS_SF = (1L << 7), - RFLAGS_TF = (1L << 8), - RFLAGS_IF = (1L << 9), - RFLAGS_DF = (1L << 10), - RFLAGS_OF = (1L << 11), - RFLAGS_IOPL = (3L << 12), - RFLAGS_NT = (1L << 14), - RFLAGS_RF = (1L << 16), - RFLAGS_VM = (1L << 17), - RFLAGS_AC = (1L << 18), - RFLAGS_VIF = (1L << 19), - RFLAGS_VIP = (1L << 20), - RFLAGS_ID = (1L << 21), -} x86_rflags; - -/* rflags register */ -typedef struct x86_reg_flags { - union { - struct { - uint64_t rflags; - }; - struct { - uint32_t eflags; - uint32_t hi32_unused1; - }; - struct { - uint32_t cf:1; - uint32_t unused1:1; - uint32_t pf:1; - uint32_t unused2:1; - uint32_t af:1; - uint32_t unused3:1; - uint32_t zf:1; - uint32_t sf:1; - uint32_t tf:1; - uint32_t ief:1; - uint32_t df:1; - uint32_t of:1; - uint32_t iopl:2; - uint32_t nt:1; - uint32_t unused4:1; - uint32_t rf:1; - uint32_t vm:1; - uint32_t ac:1; - uint32_t vif:1; - uint32_t vip:1; - uint32_t id:1; - uint32_t unused5:10; - uint32_t hi32_unused2; - }; - }; -} __attribute__ ((__packed__)) x86_reg_flags; - typedef enum x86_reg_cr0 { CR0_PE = (1L << 0), CR0_MP = (1L << 1), @@ -272,43 +214,24 @@ static inline uint32_t x86_call_gate_offset(x86_call_gate *gate) return (uint32_t)((gate->offset1 << 16) | gate->offset0); } -#define LDT_SEL 0 -#define GDT_SEL 1 +#define GDT_SEL 0 +#define LDT_SEL 1 typedef struct x68_segment_selector { union { uint16_t sel; struct { - uint16_t rpl:3; + uint16_t rpl:2; uint16_t ti:1; - uint16_t index:12; + uint16_t index:13; }; }; } __attribute__ ((__packed__)) x68_segment_selector; -typedef struct lazy_flags { - target_ulong result; - target_ulong auxbits; -} lazy_flags; - -/* Definition of hvf_x86_state is here */ -struct HVFX86EmulatorState { - int interruptable; - uint64_t fetch_rip; - uint64_t rip; - struct x86_register regs[16]; - struct x86_reg_flags rflags; - struct lazy_flags lflags; - uint8_t mmio_buf[4096]; -}; - /* useful register access macros */ -#define RIP(cpu) (cpu->hvf_emul->rip) -#define EIP(cpu) ((uint32_t)cpu->hvf_emul->rip) -#define RFLAGS(cpu) (cpu->hvf_emul->rflags.rflags) -#define EFLAGS(cpu) (cpu->hvf_emul->rflags.eflags) +#define x86_reg(cpu, reg) ((x86_register *) &cpu->regs[reg]) -#define RRX(cpu, reg) (cpu->hvf_emul->regs[reg].rrx) +#define RRX(cpu, reg) (x86_reg(cpu, reg)->rrx) #define RAX(cpu) RRX(cpu, R_EAX) #define RCX(cpu) RRX(cpu, R_ECX) #define RDX(cpu) RRX(cpu, R_EDX) @@ -326,7 +249,7 @@ struct HVFX86EmulatorState { #define R14(cpu) RRX(cpu, R_R14) #define R15(cpu) RRX(cpu, R_R15) -#define ERX(cpu, reg) (cpu->hvf_emul->regs[reg].erx) +#define ERX(cpu, reg) (x86_reg(cpu, reg)->erx) #define EAX(cpu) ERX(cpu, R_EAX) #define ECX(cpu) ERX(cpu, R_ECX) #define EDX(cpu) ERX(cpu, R_EDX) @@ -336,7 +259,7 @@ struct HVFX86EmulatorState { #define ESI(cpu) ERX(cpu, R_ESI) #define EDI(cpu) ERX(cpu, R_EDI) -#define RX(cpu, reg) (cpu->hvf_emul->regs[reg].rx) +#define RX(cpu, reg) (x86_reg(cpu, reg)->rx) #define AX(cpu) RX(cpu, R_EAX) #define CX(cpu) RX(cpu, R_ECX) #define DX(cpu) RX(cpu, R_EDX) @@ -346,13 +269,13 @@ struct HVFX86EmulatorState { #define SI(cpu) RX(cpu, R_ESI) #define DI(cpu) RX(cpu, R_EDI) -#define RL(cpu, reg) (cpu->hvf_emul->regs[reg].lx) +#define RL(cpu, reg) (x86_reg(cpu, reg)->lx) #define AL(cpu) RL(cpu, R_EAX) #define CL(cpu) RL(cpu, R_ECX) #define DL(cpu) RL(cpu, R_EDX) #define BL(cpu) RL(cpu, R_EBX) -#define RH(cpu, reg) (cpu->hvf_emul->regs[reg].hx) +#define RH(cpu, reg) (x86_reg(cpu, reg)->hx) #define AH(cpu) RH(cpu, R_EAX) #define CH(cpu) RH(cpu, R_ECX) #define DH(cpu) RH(cpu, R_EDX) diff --git a/target/i386/hvf/x86_cpuid.c b/target/i386/hvf/x86_cpuid.c index 16762b6eb44a6112a4ad729a2ce3f1d7a786d54f..a6842912f5759cae08c7d36efec8cf570d53389e 100644 --- a/target/i386/hvf/x86_cpuid.c +++ b/target/i386/hvf/x86_cpuid.c @@ -7,7 +7,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 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 @@ -122,6 +122,10 @@ uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx, CPUID_PAT | CPUID_PSE36 | CPUID_EXT2_MMXEXT | CPUID_MMX | CPUID_FXSR | CPUID_EXT2_FXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX; + hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap); + if (!(cap & CPU_BASED2_RDTSCP)) { + edx &= ~CPUID_EXT2_RDTSCP; + } hv_vmx_read_capability(HV_VMX_CAP_PROCBASED, &cap); if (!(cap & CPU_BASED_TSC_OFFSET)) { edx &= ~CPUID_EXT2_RDTSCP; diff --git a/target/i386/hvf/x86_decode.c b/target/i386/hvf/x86_decode.c index 77c346605fb301f0562a2ad5c728a8b5d4ac9a5c..062713b1a450c465632cc21d1a8a00ec2a34c7da 100644 --- a/target/i386/hvf/x86_decode.c +++ b/target/i386/hvf/x86_decode.c @@ -5,7 +5,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 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 @@ -29,8 +29,7 @@ static void decode_invalid(CPUX86State *env, struct x86_decode *decode) { - printf("%llx: failed to decode instruction ", env->hvf_emul->fetch_rip - - decode->len); + printf("%llx: failed to decode instruction ", env->eip); for (int i = 0; i < decode->opcode_len; i++) { printf("%x ", decode->opcode[i]); } @@ -75,7 +74,7 @@ static inline uint64_t decode_bytes(CPUX86State *env, struct x86_decode *decode, VM_PANIC_EX("%s invalid size %d\n", __func__, size); break; } - target_ulong va = linear_rip(env_cpu(env), RIP(env)) + decode->len; + target_ulong va = linear_rip(env_cpu(env), env->eip) + decode->len; vmx_read_mem(env_cpu(env), &val, va, size); decode->len += size; @@ -698,15 +697,13 @@ static void decode_db_4(CPUX86State *env, struct x86_decode *decode) #define RFLAGS_MASK_NONE 0 -#define RFLAGS_MASK_OSZAPC (RFLAGS_OF | RFLAGS_SF | RFLAGS_ZF | RFLAGS_AF | \ - RFLAGS_PF | RFLAGS_CF) -#define RFLAGS_MASK_LAHF (RFLAGS_SF | RFLAGS_ZF | RFLAGS_AF | RFLAGS_PF | \ - RFLAGS_CF) -#define RFLAGS_MASK_CF (RFLAGS_CF) -#define RFLAGS_MASK_IF (RFLAGS_IF) -#define RFLAGS_MASK_TF (RFLAGS_TF) -#define RFLAGS_MASK_DF (RFLAGS_DF) -#define RFLAGS_MASK_ZF (RFLAGS_ZF) +#define RFLAGS_MASK_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C) +#define RFLAGS_MASK_LAHF (CC_S | CC_Z | CC_A | CC_P | CC_C) +#define RFLAGS_MASK_CF (CC_C) +#define RFLAGS_MASK_IF (IF_MASK) +#define RFLAGS_MASK_TF (TF_MASK) +#define RFLAGS_MASK_DF (DF_MASK) +#define RFLAGS_MASK_ZF (CC_Z) struct decode_tbl _1op_inst[] = { {0x0, X86_DECODE_CMD_ADD, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, @@ -1771,7 +1768,7 @@ void calc_modrm_operand32(CPUX86State *env, struct x86_decode *decode, ptr += get_sib_val(env, decode, &seg); } else if (!decode->modrm.mod && 5 == decode->modrm.rm) { if (x86_is_long_mode(env_cpu(env))) { - ptr += RIP(env) + decode->len; + ptr += env->eip + decode->len; } else { ptr = decode->displacement; } @@ -1807,7 +1804,7 @@ void calc_modrm_operand64(CPUX86State *env, struct x86_decode *decode, if (4 == rm) { ptr = get_sib_val(env, decode, &seg) + offset; } else if (0 == mod && 5 == rm) { - ptr = RIP(env) + decode->len + (int32_t) offset; + ptr = env->eip + decode->len + (int32_t) offset; } else { ptr = get_reg_val(env, src, decode->rex.rex, decode->rex.b, 8) + (int64_t) offset; diff --git a/target/i386/hvf/x86_decode.h b/target/i386/hvf/x86_decode.h index ef7960113fb1b72da17257ee54e2c3b4e7017180..a2d7a2a27b68ea2395a4e71e1d7d0fbcab85d949 100644 --- a/target/i386/hvf/x86_decode.h +++ b/target/i386/hvf/x86_decode.h @@ -4,7 +4,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 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 diff --git a/target/i386/hvf/x86_descr.c b/target/i386/hvf/x86_descr.c index 8c05c34f33e00dff6602672c6d5d7d4a0f7f8b4d..9f539e73f6ddfd37576bbbcf816c53d76ca98993 100644 --- a/target/i386/hvf/x86_descr.c +++ b/target/i386/hvf/x86_descr.c @@ -5,7 +5,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 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 diff --git a/target/i386/hvf/x86_descr.h b/target/i386/hvf/x86_descr.h index 049ef9a417e9bbfe35aeb3b00a7cd4d5e541dc1f..c356932fa4a959a2774530bb53287b6c18d6dc69 100644 --- a/target/i386/hvf/x86_descr.h +++ b/target/i386/hvf/x86_descr.h @@ -5,7 +5,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 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 diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c index 92ab815f5d6262b41cf3bbb43f0afd5e54025187..da570e352b495653cb5840b36334556dd6e045fd 100644 --- a/target/i386/hvf/x86_emu.c +++ b/target/i386/hvf/x86_emu.c @@ -5,7 +5,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 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 @@ -23,7 +23,7 @@ // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. +// version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -95,13 +95,13 @@ target_ulong read_reg(CPUX86State *env, int reg, int size) { switch (size) { case 1: - return env->hvf_emul->regs[reg].lx; + return x86_reg(env, reg)->lx; case 2: - return env->hvf_emul->regs[reg].rx; + return x86_reg(env, reg)->rx; case 4: - return env->hvf_emul->regs[reg].erx; + return x86_reg(env, reg)->erx; case 8: - return env->hvf_emul->regs[reg].rrx; + return x86_reg(env, reg)->rrx; default: abort(); } @@ -112,16 +112,16 @@ void write_reg(CPUX86State *env, int reg, target_ulong val, int size) { switch (size) { case 1: - env->hvf_emul->regs[reg].lx = val; + x86_reg(env, reg)->lx = val; break; case 2: - env->hvf_emul->regs[reg].rx = val; + x86_reg(env, reg)->rx = val; break; case 4: - env->hvf_emul->regs[reg].rrx = (uint32_t)val; + x86_reg(env, reg)->rrx = (uint32_t)val; break; case 8: - env->hvf_emul->regs[reg].rrx = val; + x86_reg(env, reg)->rrx = val; break; default: abort(); @@ -173,7 +173,7 @@ void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size) static bool is_host_reg(struct CPUX86State *env, target_ulong ptr) { - return (ptr - (target_ulong)&env->hvf_emul->regs[0]) < sizeof(env->hvf_emul->regs); + return (ptr - (target_ulong)&env->regs[0]) < sizeof(env->regs); } void write_val_ext(struct CPUX86State *env, target_ulong ptr, target_ulong val, int size) @@ -187,8 +187,8 @@ void write_val_ext(struct CPUX86State *env, target_ulong ptr, target_ulong val, uint8_t *read_mmio(struct CPUX86State *env, target_ulong ptr, int bytes) { - vmx_read_mem(env_cpu(env), env->hvf_emul->mmio_buf, ptr, bytes); - return env->hvf_emul->mmio_buf; + vmx_read_mem(env_cpu(env), env->hvf_mmio_buf, ptr, bytes); + return env->hvf_mmio_buf; } @@ -267,49 +267,49 @@ static void exec_mov(struct CPUX86State *env, struct x86_decode *decode) write_val_ext(env, decode->op[0].ptr, decode->op[1].val, decode->operand_size); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_add(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_or(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, |, SET_FLAGS_OSZAPC_LOGIC, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_adc(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, +get_CF(env)+, SET_FLAGS_OSZAPC_ADD, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_sbb(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, -get_CF(env)-, SET_FLAGS_OSZAPC_SUB, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_and(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_sub(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_xor(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, ^, SET_FLAGS_OSZAPC_LOGIC, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_neg(struct CPUX86State *env, struct x86_decode *decode) @@ -332,13 +332,13 @@ static void exec_neg(struct CPUX86State *env, struct x86_decode *decode) } /*lflags_to_rflags(env);*/ - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_cmp(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_inc(struct CPUX86State *env, struct x86_decode *decode) @@ -348,7 +348,7 @@ static void exec_inc(struct CPUX86State *env, struct x86_decode *decode) EXEC_2OP_FLAGS_CMD(env, decode, +1+, SET_FLAGS_OSZAP_ADD, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_dec(struct CPUX86State *env, struct x86_decode *decode) @@ -357,13 +357,13 @@ static void exec_dec(struct CPUX86State *env, struct x86_decode *decode) decode->op[1].val = 0; EXEC_2OP_FLAGS_CMD(env, decode, -1-, SET_FLAGS_OSZAP_SUB, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_tst(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, false); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_not(struct CPUX86State *env, struct x86_decode *decode) @@ -372,7 +372,7 @@ static void exec_not(struct CPUX86State *env, struct x86_decode *decode) write_val_ext(env, decode->op[0].ptr, ~decode->op[0].val, decode->operand_size); - RIP(env) += decode->len; + env->eip += decode->len; } void exec_movzx(struct CPUX86State *env, struct x86_decode *decode) @@ -392,7 +392,7 @@ void exec_movzx(struct CPUX86State *env, struct x86_decode *decode) decode->op[1].val = read_val_ext(env, decode->op[1].ptr, src_op_size); write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_out(struct CPUX86State *env, struct x86_decode *decode) @@ -416,7 +416,7 @@ static void exec_out(struct CPUX86State *env, struct x86_decode *decode) VM_PANIC("Bad out opcode\n"); break; } - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_in(struct CPUX86State *env, struct x86_decode *decode) @@ -452,14 +452,14 @@ static void exec_in(struct CPUX86State *env, struct x86_decode *decode) break; } - RIP(env) += decode->len; + env->eip += decode->len; } static inline void string_increment_reg(struct CPUX86State *env, int reg, struct x86_decode *decode) { target_ulong val = read_reg(env, reg, decode->addressing_size); - if (env->hvf_emul->rflags.df) { + if (env->eflags & DF_MASK) { val -= decode->operand_size; } else { val += decode->operand_size; @@ -489,9 +489,9 @@ static void exec_ins_single(struct CPUX86State *env, struct x86_decode *decode) target_ulong addr = linear_addr_size(env_cpu(env), RDI(env), decode->addressing_size, R_ES); - hvf_handle_io(env_cpu(env), DX(env), env->hvf_emul->mmio_buf, 0, + hvf_handle_io(env_cpu(env), DX(env), env->hvf_mmio_buf, 0, decode->operand_size, 1); - vmx_write_mem(env_cpu(env), addr, env->hvf_emul->mmio_buf, + vmx_write_mem(env_cpu(env), addr, env->hvf_mmio_buf, decode->operand_size); string_increment_reg(env, R_EDI, decode); @@ -505,16 +505,16 @@ static void exec_ins(struct CPUX86State *env, struct x86_decode *decode) exec_ins_single(env, decode); } - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_outs_single(struct CPUX86State *env, struct x86_decode *decode) { target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS); - vmx_read_mem(env_cpu(env), env->hvf_emul->mmio_buf, addr, + vmx_read_mem(env_cpu(env), env->hvf_mmio_buf, addr, decode->operand_size); - hvf_handle_io(env_cpu(env), DX(env), env->hvf_emul->mmio_buf, 1, + hvf_handle_io(env_cpu(env), DX(env), env->hvf_mmio_buf, 1, decode->operand_size, 1); string_increment_reg(env, R_ESI, decode); @@ -528,7 +528,7 @@ static void exec_outs(struct CPUX86State *env, struct x86_decode *decode) exec_outs_single(env, decode); } - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_movs_single(struct CPUX86State *env, struct x86_decode *decode) @@ -556,7 +556,7 @@ static void exec_movs(struct CPUX86State *env, struct x86_decode *decode) exec_movs_single(env, decode); } - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_cmps_single(struct CPUX86State *env, struct x86_decode *decode) @@ -586,7 +586,7 @@ static void exec_cmps(struct CPUX86State *env, struct x86_decode *decode) } else { exec_cmps_single(env, decode); } - RIP(env) += decode->len; + env->eip += decode->len; } @@ -612,7 +612,7 @@ static void exec_stos(struct CPUX86State *env, struct x86_decode *decode) exec_stos_single(env, decode); } - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_scas_single(struct CPUX86State *env, struct x86_decode *decode) @@ -638,7 +638,7 @@ static void exec_scas(struct CPUX86State *env, struct x86_decode *decode) exec_scas_single(env, decode); } - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_lods_single(struct CPUX86State *env, struct x86_decode *decode) @@ -661,7 +661,7 @@ static void exec_lods(struct CPUX86State *env, struct x86_decode *decode) exec_lods_single(env, decode); } - RIP(env) += decode->len; + env->eip += decode->len; } void simulate_rdmsr(struct CPUState *cpu) @@ -758,7 +758,7 @@ void simulate_rdmsr(struct CPUState *cpu) static void exec_rdmsr(struct CPUX86State *env, struct x86_decode *decode) { simulate_rdmsr(env_cpu(env)); - RIP(env) += decode->len; + env->eip += decode->len; } void simulate_wrmsr(struct CPUState *cpu) @@ -853,7 +853,7 @@ void simulate_wrmsr(struct CPUState *cpu) static void exec_wrmsr(struct CPUX86State *env, struct x86_decode *decode) { simulate_wrmsr(env_cpu(env)); - RIP(env) += decode->len; + env->eip += decode->len; } /* @@ -909,25 +909,25 @@ static void do_bt(struct CPUX86State *env, struct x86_decode *decode, int flag) static void exec_bt(struct CPUX86State *env, struct x86_decode *decode) { do_bt(env, decode, 0); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_btc(struct CPUX86State *env, struct x86_decode *decode) { do_bt(env, decode, 1); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_btr(struct CPUX86State *env, struct x86_decode *decode) { do_bt(env, decode, 3); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_bts(struct CPUX86State *env, struct x86_decode *decode) { do_bt(env, decode, 2); - RIP(env) += decode->len; + env->eip += decode->len; } void exec_shl(struct CPUX86State *env, struct x86_decode *decode) @@ -991,7 +991,7 @@ void exec_shl(struct CPUX86State *env, struct x86_decode *decode) exit: /* lflags_to_rflags(env); */ - RIP(env) += decode->len; + env->eip += decode->len; } void exec_movsx(CPUX86State *env, struct x86_decode *decode) @@ -1014,7 +1014,7 @@ void exec_movsx(CPUX86State *env, struct x86_decode *decode) write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size); - RIP(env) += decode->len; + env->eip += decode->len; } void exec_ror(struct CPUX86State *env, struct x86_decode *decode) @@ -1092,7 +1092,7 @@ void exec_ror(struct CPUX86State *env, struct x86_decode *decode) break; } } - RIP(env) += decode->len; + env->eip += decode->len; } void exec_rol(struct CPUX86State *env, struct x86_decode *decode) @@ -1173,7 +1173,7 @@ void exec_rol(struct CPUX86State *env, struct x86_decode *decode) break; } } - RIP(env) += decode->len; + env->eip += decode->len; } @@ -1259,7 +1259,7 @@ void exec_rcl(struct CPUX86State *env, struct x86_decode *decode) break; } } - RIP(env) += decode->len; + env->eip += decode->len; } void exec_rcr(struct CPUX86State *env, struct x86_decode *decode) @@ -1334,7 +1334,7 @@ void exec_rcr(struct CPUX86State *env, struct x86_decode *decode) break; } } - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_xchg(struct CPUX86State *env, struct x86_decode *decode) @@ -1346,7 +1346,7 @@ static void exec_xchg(struct CPUX86State *env, struct x86_decode *decode) write_val_ext(env, decode->op[1].ptr, decode->op[0].val, decode->operand_size); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_xadd(struct CPUX86State *env, struct x86_decode *decode) @@ -1355,7 +1355,7 @@ static void exec_xadd(struct CPUX86State *env, struct x86_decode *decode) write_val_ext(env, decode->op[1].ptr, decode->op[0].val, decode->operand_size); - RIP(env) += decode->len; + env->eip += decode->len; } static struct cmd_handler { @@ -1432,9 +1432,9 @@ void load_regs(struct CPUState *cpu) RRX(env, i) = rreg(cpu->hvf_fd, HV_X86_RAX + i); } - RFLAGS(env) = rreg(cpu->hvf_fd, HV_X86_RFLAGS); + env->eflags = rreg(cpu->hvf_fd, HV_X86_RFLAGS); rflags_to_lflags(env); - RIP(env) = rreg(cpu->hvf_fd, HV_X86_RIP); + env->eip = rreg(cpu->hvf_fd, HV_X86_RIP); } void store_regs(struct CPUState *cpu) @@ -1456,21 +1456,21 @@ void store_regs(struct CPUState *cpu) } lflags_to_rflags(env); - wreg(cpu->hvf_fd, HV_X86_RFLAGS, RFLAGS(env)); - macvm_set_rip(cpu, RIP(env)); + wreg(cpu->hvf_fd, HV_X86_RFLAGS, env->eflags); + macvm_set_rip(cpu, env->eip); } bool exec_instruction(struct CPUX86State *env, struct x86_decode *ins) { /*if (hvf_vcpu_id(cpu)) - printf("%d, %llx: exec_instruction %s\n", hvf_vcpu_id(cpu), RIP(cpu), + printf("%d, %llx: exec_instruction %s\n", hvf_vcpu_id(cpu), env->eip, decode_cmd_to_string(ins->cmd));*/ if (!_cmd_handler[ins->cmd].handler) { - printf("Unimplemented handler (%llx) for %d (%x %x) \n", RIP(env), + printf("Unimplemented handler (%llx) for %d (%x %x) \n", env->eip, ins->cmd, ins->opcode[0], ins->opcode_len > 1 ? ins->opcode[1] : 0); - RIP(env) += ins->len; + env->eip += ins->len; return true; } diff --git a/target/i386/hvf/x86_emu.h b/target/i386/hvf/x86_emu.h index f92a9c54b590f4ed3c5e6213cb45784da03201c0..233f7b8daa3ec229987e24c4e4492bad3642d1cc 100644 --- a/target/i386/hvf/x86_emu.h +++ b/target/i386/hvf/x86_emu.h @@ -5,7 +5,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 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 diff --git a/target/i386/hvf/x86_flags.c b/target/i386/hvf/x86_flags.c index ee6d33f86182e849d575e0d0d483a4e7d5bf4b2d..fecbca751770c9667c9527cd551568c46f8d0f3c 100644 --- a/target/i386/hvf/x86_flags.c +++ b/target/i386/hvf/x86_flags.c @@ -6,7 +6,7 @@ // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. +// version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -63,7 +63,7 @@ #define SET_FLAGS_OSZAPC_SIZE(size, lf_carries, lf_result) { \ target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \ (((lf_carries) >> (size - 2)) << LF_BIT_PO); \ - env->hvf_emul->lflags.result = (target_ulong)(int##size##_t)(lf_result); \ + env->hvf_lflags.result = (target_ulong)(int##size##_t)(lf_result); \ if ((size) == 32) { \ temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \ } else if ((size) == 16) { \ @@ -73,7 +73,7 @@ } else { \ VM_PANIC("unimplemented"); \ } \ - env->hvf_emul->lflags.auxbits = (target_ulong)(uint32_t)temp; \ + env->hvf_lflags.auxbits = (target_ulong)(uint32_t)temp; \ } /* carries, result */ @@ -100,10 +100,10 @@ } else { \ VM_PANIC("unimplemented"); \ } \ - env->hvf_emul->lflags.result = (target_ulong)(int##size##_t)(lf_result); \ - target_ulong delta_c = (env->hvf_emul->lflags.auxbits ^ temp) & LF_MASK_CF; \ + env->hvf_lflags.result = (target_ulong)(int##size##_t)(lf_result); \ + target_ulong delta_c = (env->hvf_lflags.auxbits ^ temp) & LF_MASK_CF; \ delta_c ^= (delta_c >> 1); \ - env->hvf_emul->lflags.auxbits = (target_ulong)(uint32_t)(temp ^ delta_c); \ + env->hvf_lflags.auxbits = (target_ulong)(uint32_t)(temp ^ delta_c); \ } /* carries, result */ @@ -117,9 +117,8 @@ void SET_FLAGS_OxxxxC(CPUX86State *env, uint32_t new_of, uint32_t new_cf) { uint32_t temp_po = new_of ^ new_cf; - env->hvf_emul->lflags.auxbits &= ~(LF_MASK_PO | LF_MASK_CF); - env->hvf_emul->lflags.auxbits |= (temp_po << LF_BIT_PO) | - (new_cf << LF_BIT_CF); + env->hvf_lflags.auxbits &= ~(LF_MASK_PO | LF_MASK_CF); + env->hvf_lflags.auxbits |= (temp_po << LF_BIT_PO) | (new_cf << LF_BIT_CF); } void SET_FLAGS_OSZAPC_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2, @@ -215,27 +214,27 @@ void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t v1, uint8_t v2, bool get_PF(CPUX86State *env) { - uint32_t temp = (255 & env->hvf_emul->lflags.result); - temp = temp ^ (255 & (env->hvf_emul->lflags.auxbits >> LF_BIT_PDB)); + uint32_t temp = (255 & env->hvf_lflags.result); + temp = temp ^ (255 & (env->hvf_lflags.auxbits >> LF_BIT_PDB)); temp = (temp ^ (temp >> 4)) & 0x0F; return (0x9669U >> temp) & 1; } void set_PF(CPUX86State *env, bool val) { - uint32_t temp = (255 & env->hvf_emul->lflags.result) ^ (!val); - env->hvf_emul->lflags.auxbits &= ~(LF_MASK_PDB); - env->hvf_emul->lflags.auxbits |= (temp << LF_BIT_PDB); + uint32_t temp = (255 & env->hvf_lflags.result) ^ (!val); + env->hvf_lflags.auxbits &= ~(LF_MASK_PDB); + env->hvf_lflags.auxbits |= (temp << LF_BIT_PDB); } bool get_OF(CPUX86State *env) { - return ((env->hvf_emul->lflags.auxbits + (1U << LF_BIT_PO)) >> LF_BIT_CF) & 1; + return ((env->hvf_lflags.auxbits + (1U << LF_BIT_PO)) >> LF_BIT_CF) & 1; } bool get_CF(CPUX86State *env) { - return (env->hvf_emul->lflags.auxbits >> LF_BIT_CF) & 1; + return (env->hvf_lflags.auxbits >> LF_BIT_CF) & 1; } void set_OF(CPUX86State *env, bool val) @@ -252,64 +251,64 @@ void set_CF(CPUX86State *env, bool val) bool get_AF(CPUX86State *env) { - return (env->hvf_emul->lflags.auxbits >> LF_BIT_AF) & 1; + return (env->hvf_lflags.auxbits >> LF_BIT_AF) & 1; } void set_AF(CPUX86State *env, bool val) { - env->hvf_emul->lflags.auxbits &= ~(LF_MASK_AF); - env->hvf_emul->lflags.auxbits |= val << LF_BIT_AF; + env->hvf_lflags.auxbits &= ~(LF_MASK_AF); + env->hvf_lflags.auxbits |= val << LF_BIT_AF; } bool get_ZF(CPUX86State *env) { - return !env->hvf_emul->lflags.result; + return !env->hvf_lflags.result; } void set_ZF(CPUX86State *env, bool val) { if (val) { - env->hvf_emul->lflags.auxbits ^= - (((env->hvf_emul->lflags.result >> LF_SIGN_BIT) & 1) << LF_BIT_SD); + env->hvf_lflags.auxbits ^= + (((env->hvf_lflags.result >> LF_SIGN_BIT) & 1) << LF_BIT_SD); /* merge the parity bits into the Parity Delta Byte */ - uint32_t temp_pdb = (255 & env->hvf_emul->lflags.result); - env->hvf_emul->lflags.auxbits ^= (temp_pdb << LF_BIT_PDB); + uint32_t temp_pdb = (255 & env->hvf_lflags.result); + env->hvf_lflags.auxbits ^= (temp_pdb << LF_BIT_PDB); /* now zero the .result value */ - env->hvf_emul->lflags.result = 0; + env->hvf_lflags.result = 0; } else { - env->hvf_emul->lflags.result |= (1 << 8); + env->hvf_lflags.result |= (1 << 8); } } bool get_SF(CPUX86State *env) { - return ((env->hvf_emul->lflags.result >> LF_SIGN_BIT) ^ - (env->hvf_emul->lflags.auxbits >> LF_BIT_SD)) & 1; + return ((env->hvf_lflags.result >> LF_SIGN_BIT) ^ + (env->hvf_lflags.auxbits >> LF_BIT_SD)) & 1; } void set_SF(CPUX86State *env, bool val) { bool temp_sf = get_SF(env); - env->hvf_emul->lflags.auxbits ^= (temp_sf ^ val) << LF_BIT_SD; + env->hvf_lflags.auxbits ^= (temp_sf ^ val) << LF_BIT_SD; } void lflags_to_rflags(CPUX86State *env) { - env->hvf_emul->rflags.cf = get_CF(env); - env->hvf_emul->rflags.pf = get_PF(env); - env->hvf_emul->rflags.af = get_AF(env); - env->hvf_emul->rflags.zf = get_ZF(env); - env->hvf_emul->rflags.sf = get_SF(env); - env->hvf_emul->rflags.of = get_OF(env); + env->eflags |= get_CF(env) ? CC_C : 0; + env->eflags |= get_PF(env) ? CC_P : 0; + env->eflags |= get_AF(env) ? CC_A : 0; + env->eflags |= get_ZF(env) ? CC_Z : 0; + env->eflags |= get_SF(env) ? CC_S : 0; + env->eflags |= get_OF(env) ? CC_O : 0; } void rflags_to_lflags(CPUX86State *env) { - env->hvf_emul->lflags.auxbits = env->hvf_emul->lflags.result = 0; - set_OF(env, env->hvf_emul->rflags.of); - set_SF(env, env->hvf_emul->rflags.sf); - set_ZF(env, env->hvf_emul->rflags.zf); - set_AF(env, env->hvf_emul->rflags.af); - set_PF(env, env->hvf_emul->rflags.pf); - set_CF(env, env->hvf_emul->rflags.cf); + env->hvf_lflags.auxbits = env->hvf_lflags.result = 0; + set_OF(env, env->eflags & CC_O); + set_SF(env, env->eflags & CC_S); + set_ZF(env, env->eflags & CC_Z); + set_AF(env, env->eflags & CC_A); + set_PF(env, env->eflags & CC_P); + set_CF(env, env->eflags & CC_C); } diff --git a/target/i386/hvf/x86_flags.h b/target/i386/hvf/x86_flags.h index 785e80cfca9de178e44489d9e64f62f209614c8b..75c2a7feab534fed64f721d5555ce333ea9b215f 100644 --- a/target/i386/hvf/x86_flags.h +++ b/target/i386/hvf/x86_flags.h @@ -6,7 +6,7 @@ // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. +// version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/i386/hvf/x86_mmu.c b/target/i386/hvf/x86_mmu.c index 65d4603dbf9cc51f9c0c07e1b5424e1c33ec3d2a..882a6237eea300050a5d432e54f863b0225bcc63 100644 --- a/target/i386/hvf/x86_mmu.c +++ b/target/i386/hvf/x86_mmu.c @@ -5,7 +5,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 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 diff --git a/target/i386/hvf/x86_mmu.h b/target/i386/hvf/x86_mmu.h index cd6e137e79c413ff317b713e2d03be9cd49ab716..9ae8a548de36ed8708775cf2f1a1657a549c56fd 100644 --- a/target/i386/hvf/x86_mmu.h +++ b/target/i386/hvf/x86_mmu.h @@ -5,7 +5,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 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 diff --git a/target/i386/hvf/x86_task.c b/target/i386/hvf/x86_task.c index 1daac6cc2b35d350897022bd29568d89d8292671..6f04478b3adb51bed81ac24cecd96393d03ce58e 100644 --- a/target/i386/hvf/x86_task.c +++ b/target/i386/hvf/x86_task.c @@ -38,8 +38,8 @@ static void save_state_to_tss32(CPUState *cpu, struct x86_tss_segment32 *tss) CPUX86State *env = &x86_cpu->env; /* CR3 and ldt selector are not saved intentionally */ - tss->eip = EIP(env); - tss->eflags = EFLAGS(env); + tss->eip = (uint32_t)env->eip; + tss->eflags = (uint32_t)env->eflags; tss->eax = EAX(env); tss->ecx = ECX(env); tss->edx = EDX(env); @@ -64,8 +64,8 @@ static void load_state_from_tss32(CPUState *cpu, struct x86_tss_segment32 *tss) wvmcs(cpu->hvf_fd, VMCS_GUEST_CR3, tss->cr3); - RIP(env) = tss->eip; - EFLAGS(env) = tss->eflags | 2; + env->eip = tss->eip; + env->eflags = tss->eflags | 2; /* General purpose registers */ RAX(env) = tss->eax; @@ -158,7 +158,7 @@ void vmx_handle_task_switch(CPUState *cpu, x68_segment_selector tss_sel, int rea } if (reason == TSR_IRET) - EFLAGS(env) &= ~RFLAGS_NT; + env->eflags &= ~NT_MASK; if (reason != TSR_CALL && reason != TSR_IDT_GATE) old_tss_sel.sel = 0xffff; diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c index edefe5319a444b313c3d320f7edd8d1eb3de1336..bbec412b6c807653252bd5935f27fc61b842b8bf 100644 --- a/target/i386/hvf/x86hvf.c +++ b/target/i386/hvf/x86hvf.c @@ -6,7 +6,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 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 @@ -32,6 +32,8 @@ #include #include +#include "hvf-cpus.h" + void hvf_set_segment(struct CPUState *cpu, struct vmx_segment *vmx_seg, SegmentCache *qseg, bool is_tr) { @@ -412,7 +414,7 @@ bool hvf_inject_interrupts(CPUState *cpu_state) if (!(env->hflags & HF_INHIBIT_IRQ_MASK) && (cpu_state->interrupt_request & CPU_INTERRUPT_HARD) && - (EFLAGS(env) & IF_MASK) && !(info & VMCS_INTR_VALID)) { + (env->eflags & IF_MASK) && !(info & VMCS_INTR_VALID)) { int line = cpu_get_pic_interrupt(&x86cpu->env); cpu_state->interrupt_request &= ~CPU_INTERRUPT_HARD; if (line >= 0) { @@ -432,7 +434,7 @@ int hvf_process_events(CPUState *cpu_state) X86CPU *cpu = X86_CPU(cpu_state); CPUX86State *env = &cpu->env; - EFLAGS(env) = rreg(cpu_state->hvf_fd, HV_X86_RFLAGS); + env->eflags = rreg(cpu_state->hvf_fd, HV_X86_RFLAGS); if (cpu_state->interrupt_request & CPU_INTERRUPT_INIT) { hvf_cpu_synchronize_state(cpu_state); @@ -444,7 +446,7 @@ int hvf_process_events(CPUState *cpu_state) apic_poll_irq(cpu->apic_state); } if (((cpu_state->interrupt_request & CPU_INTERRUPT_HARD) && - (EFLAGS(env) & IF_MASK)) || + (env->eflags & IF_MASK)) || (cpu_state->interrupt_request & CPU_INTERRUPT_NMI)) { cpu_state->halted = 0; } diff --git a/target/i386/hvf/x86hvf.h b/target/i386/hvf/x86hvf.h index 79539f7282fae0954dfed4f519b858b36d8f52bd..635ab0f34e48ff39098610622711f8618cf53071 100644 --- a/target/i386/hvf/x86hvf.h +++ b/target/i386/hvf/x86hvf.h @@ -5,7 +5,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 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 @@ -35,5 +35,4 @@ void hvf_get_msrs(CPUState *cpu_state); void vmx_clear_int_window_exiting(CPUState *cpu); void hvf_get_segments(CPUState *cpu_state); void vmx_update_tpr(CPUState *cpu); -void hvf_cpu_synchronize_state(CPUState *cpu_state); #endif diff --git a/target/i386/int_helper.c b/target/i386/int_helper.c index 334469ca8ce8ba8e09bb781057120b38dd210efd..4f89436b53f7468edb7e602c00236d210c4ffd7a 100644 --- a/target/i386/int_helper.c +++ b/target/i386/int_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/i386/kvm-stub.c b/target/i386/kvm-stub.c index 872ef7df4c88024213c5e216210498eabde34418..92f49121b8fa101347337bfd3565b760f928564a 100644 --- a/target/i386/kvm-stub.c +++ b/target/i386/kvm-stub.c @@ -13,11 +13,6 @@ #include "cpu.h" #include "kvm_i386.h" -bool kvm_allows_irq0_override(void) -{ - return 1; -} - #ifndef __OPTIMIZE__ bool kvm_has_smm(void) { diff --git a/target/i386/kvm.c b/target/i386/kvm.c index 34f838728dd6ab444a31ac1c03bd700bf66e1543..a2934dda027c66b634637986b58926468910ea67 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -13,6 +13,7 @@ */ #include "qemu/osdep.h" +#include "qapi/qapi-events-run-state.h" #include "qapi/error.h" #include #include @@ -59,6 +60,10 @@ do { } while (0) #endif +/* From arch/x86/kvm/lapic.h */ +#define KVM_APIC_BUS_CYCLE_NS 1 +#define KVM_APIC_BUS_FREQUENCY (1000000000ULL / KVM_APIC_BUS_CYCLE_NS) + #define MSR_KVM_WALL_CLOCK 0x11 #define MSR_KVM_SYSTEM_TIME 0x12 @@ -106,6 +111,7 @@ static bool has_msr_core_capabs; static bool has_msr_vmx_vmfunc; static bool has_msr_ucode_rev; static bool has_msr_vmx_procbased_ctls2; +static bool has_msr_perf_capabs; static uint32_t has_architectural_pmu_version; static uint32_t num_architectural_pmu_gp_counters; @@ -138,14 +144,14 @@ bool kvm_has_adjust_clock_stable(void) return (ret == KVM_CLOCK_TSC_STABLE); } -bool kvm_has_exception_payload(void) +bool kvm_has_adjust_clock(void) { - return has_exception_payload; + return kvm_check_extension(kvm_state, KVM_CAP_ADJUST_CLOCK); } -bool kvm_allows_irq0_override(void) +bool kvm_has_exception_payload(void) { - return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing(); + return has_exception_payload; } static bool kvm_x2apic_api_set_flags(uint64_t flags) @@ -274,30 +280,7 @@ static struct kvm_cpuid2 *get_supported_cpuid(KVMState *s) return cpuid; } -static const struct kvm_para_features { - int cap; - int feature; -} para_features[] = { - { KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE }, - { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY }, - { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP }, - { KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF }, -}; - -static int get_para_features(KVMState *s) -{ - int i, features = 0; - - for (i = 0; i < ARRAY_SIZE(para_features); i++) { - if (kvm_check_extension(s, para_features[i].cap)) { - features |= (1 << para_features[i].feature); - } - } - - return features; -} - -static bool host_tsx_blacklisted(void) +static bool host_tsx_broken(void) { int family, model, stepping;\ char vendor[CPUID_VENDOR_SZ + 1]; @@ -356,13 +339,11 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, struct kvm_cpuid2 *cpuid; uint32_t ret = 0; uint32_t cpuid_1_edx; - bool found = false; cpuid = get_supported_cpuid(s); struct kvm_cpuid_entry2 *entry = cpuid_find_entry(cpuid, function, index); if (entry) { - found = true; ret = cpuid_entry_get_reg(entry, reg); } @@ -403,15 +384,9 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, } else if (function == 6 && reg == R_EAX) { ret |= CPUID_6_EAX_ARAT; /* safe to allow because of emulated APIC */ } else if (function == 7 && index == 0 && reg == R_EBX) { - if (host_tsx_blacklisted()) { + if (host_tsx_broken()) { ret &= ~(CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_HLE); } - } else if (function == 7 && index == 0 && reg == R_ECX) { - if (enable_cpu_pm) { - ret |= CPUID_7_0_ECX_WAITPKG; - } else { - ret &= ~CPUID_7_0_ECX_WAITPKG; - } } else if (function == 7 && index == 0 && reg == R_EDX) { /* * Linux v4.17-v4.20 incorrectly return ARCH_CAPABILITIES on SVM hosts. @@ -443,12 +418,6 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, } } else if (function == KVM_CPUID_FEATURES && reg == R_EDX) { ret |= 1U << KVM_HINTS_REALTIME; - found = 1; - } - - /* fallback for older kernels */ - if ((function == KVM_CPUID_FEATURES) && !found) { - ret = get_para_features(s); } return ret; @@ -576,8 +545,17 @@ static void kvm_mce_inject(X86CPU *cpu, hwaddr paddr, int code) (MCM_ADDR_PHYS << 6) | 0xc, flags); } +static void emit_hypervisor_memory_failure(MemoryFailureAction action, bool ar) +{ + MemoryFailureFlags mff = {.action_required = ar, .recursive = false}; + + qapi_event_send_memory_failure(MEMORY_FAILURE_RECIPIENT_HYPERVISOR, action, + &mff); +} + static void hardware_memory_error(void *host_addr) { + emit_hypervisor_memory_failure(MEMORY_FAILURE_ACTION_FATAL, true); error_report("QEMU got Hardware memory error at addr %p", host_addr); exit(1); } @@ -632,7 +610,8 @@ void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) hardware_memory_error(addr); } - /* Hope we are lucky for AO MCE */ + /* Hope we are lucky for AO MCE, just notify a event */ + emit_hypervisor_memory_failure(MEMORY_FAILURE_ACTION_IGNORE, false); } static void kvm_reset_exception(CPUX86State *env) @@ -731,30 +710,66 @@ static bool hyperv_enabled(X86CPU *cpu) { CPUState *cs = CPU(cpu); return kvm_check_extension(cs->kvm_state, KVM_CAP_HYPERV) > 0 && - ((cpu->hyperv_spinlock_attempts != HYPERV_SPINLOCK_NEVER_RETRY) || + ((cpu->hyperv_spinlock_attempts != HYPERV_SPINLOCK_NEVER_NOTIFY) || cpu->hyperv_features || cpu->hyperv_passthrough); } +/* + * Check whether target_freq is within conservative + * ntp correctable bounds (250ppm) of freq + */ +static inline bool freq_within_bounds(int freq, int target_freq) +{ + int max_freq = freq + (freq * 250 / 1000000); + int min_freq = freq - (freq * 250 / 1000000); + + if (target_freq >= min_freq && target_freq <= max_freq) { + return true; + } + + return false; +} + static int kvm_arch_set_tsc_khz(CPUState *cs) { X86CPU *cpu = X86_CPU(cs); CPUX86State *env = &cpu->env; - int r; + int r, cur_freq; + bool set_ioctl = false; if (!env->tsc_khz) { return 0; } - r = kvm_check_extension(cs->kvm_state, KVM_CAP_TSC_CONTROL) ? + cur_freq = kvm_check_extension(cs->kvm_state, KVM_CAP_GET_TSC_KHZ) ? + kvm_vcpu_ioctl(cs, KVM_GET_TSC_KHZ) : -ENOTSUP; + + /* + * If TSC scaling is supported, attempt to set TSC frequency. + */ + if (kvm_check_extension(cs->kvm_state, KVM_CAP_TSC_CONTROL)) { + set_ioctl = true; + } + + /* + * If desired TSC frequency is within bounds of NTP correction, + * attempt to set TSC frequency. + */ + if (cur_freq != -ENOTSUP && freq_within_bounds(cur_freq, env->tsc_khz)) { + set_ioctl = true; + } + + r = set_ioctl ? kvm_vcpu_ioctl(cs, KVM_SET_TSC_KHZ, env->tsc_khz) : -ENOTSUP; + if (r < 0) { /* When KVM_SET_TSC_KHZ fails, it's an error only if the current * TSC frequency doesn't match the one we want. */ - int cur_freq = kvm_check_extension(cs->kvm_state, KVM_CAP_GET_TSC_KHZ) ? - kvm_vcpu_ioctl(cs, KVM_GET_TSC_KHZ) : - -ENOTSUP; + cur_freq = kvm_check_extension(cs->kvm_state, KVM_CAP_GET_TSC_KHZ) ? + kvm_vcpu_ioctl(cs, KVM_GET_TSC_KHZ) : + -ENOTSUP; if (cur_freq <= 0 || cur_freq != env->tsc_khz) { warn_report("TSC frequency mismatch between " "VM (%" PRId64 " kHz) and host (%d kHz), " @@ -1194,14 +1209,14 @@ static int hyperv_handle_properties(CPUState *cs, if (c) { env->features[FEAT_HYPERV_EAX] = c->eax; env->features[FEAT_HYPERV_EBX] = c->ebx; - env->features[FEAT_HYPERV_EDX] = c->eax; + env->features[FEAT_HYPERV_EDX] = c->edx; } c = cpuid_find_entry(cpuid, HV_CPUID_ENLIGHTMENT_INFO, 0); if (c) { env->features[FEAT_HV_RECOMM_EAX] = c->eax; /* hv-spinlocks may have been overriden */ - if (cpu->hyperv_spinlock_attempts != HYPERV_SPINLOCK_NEVER_RETRY) { + if (cpu->hyperv_spinlock_attempts != HYPERV_SPINLOCK_NEVER_NOTIFY) { c->ebx = cpu->hyperv_spinlock_attempts; } } @@ -1469,6 +1484,8 @@ int kvm_arch_init_vcpu(CPUState *cs) } } + env->apic_bus_freq = KVM_APIC_BUS_FREQUENCY; + /* Paravirtualization CPUIDs */ r = hyperv_handle_properties(cs, cpuid_data.entries); if (r < 0) { @@ -1531,6 +1548,7 @@ int kvm_arch_init_vcpu(CPUState *cs) if (env->nr_dies < 2) { break; } + /* fallthrough */ case 4: case 0xb: case 0xd: @@ -1735,7 +1753,7 @@ int kvm_arch_init_vcpu(CPUState *cs) } } - qemu_add_vm_change_state_handler(cpu_update_state, env); + cpu->vmsentry = qemu_add_vm_change_state_handler(cpu_update_state, env); c = cpuid_find_entry(&cpuid_data.cpuid, 1, 0); if (c) { @@ -1773,9 +1791,7 @@ int kvm_arch_init_vcpu(CPUState *cs) c = &cpuid_data.entries[cpuid_i++]; c->function = KVM_CPUID_SIGNATURE | 0x10; c->eax = env->tsc_khz; - /* LAPIC resolution of 1ns (freq: 1GHz) is hardcoded in KVM's - * APIC_BUS_CYCLE_NS */ - c->ebx = 1000000; + c->ebx = env->apic_bus_freq / 1000; /* Hz to KHz */ c->ecx = c->edx = 0; c = cpuid_find_entry(&cpuid_data.cpuid, kvm_base, 0); @@ -1799,16 +1815,20 @@ int kvm_arch_init_vcpu(CPUState *cs) if (max_nested_state_len > 0) { assert(max_nested_state_len >= offsetof(struct kvm_nested_state, data)); - if (cpu_has_vmx(env)) { + if (cpu_has_vmx(env) || cpu_has_svm(env)) { struct kvm_vmx_nested_state_hdr *vmx_hdr; env->nested_state = g_malloc0(max_nested_state_len); env->nested_state->size = max_nested_state_len; - env->nested_state->format = KVM_STATE_NESTED_FORMAT_VMX; - vmx_hdr = &env->nested_state->hdr.vmx; - vmx_hdr->vmxon_pa = -1ull; - vmx_hdr->vmcs12_pa = -1ull; + if (cpu_has_vmx(env)) { + env->nested_state->format = KVM_STATE_NESTED_FORMAT_VMX; + vmx_hdr = &env->nested_state->hdr.vmx; + vmx_hdr->vmxon_pa = -1ull; + vmx_hdr->vmcs12_pa = -1ull; + } else { + env->nested_state->format = KVM_STATE_NESTED_FORMAT_SVM; + } } } @@ -1848,6 +1868,8 @@ int kvm_arch_destroy_vcpu(CPUState *cs) env->nested_state = NULL; } + qemu_del_vm_change_state_handler(cpu->vmsentry); + return 0; } @@ -2027,6 +2049,9 @@ static int kvm_get_supported_msrs(KVMState *s) case MSR_IA32_CORE_CAPABILITY: has_msr_core_capabs = true; break; + case MSR_IA32_PERF_CAPABILITIES: + has_msr_perf_capabs = true; + break; case MSR_IA32_VMX_VMFUNC: has_msr_vmx_vmfunc = true; break; @@ -2086,6 +2111,11 @@ int kvm_arch_init(MachineState *ms, KVMState *s) int ret; struct utsname utsname; + if (!kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) { + error_report("kvm: KVM_CAP_IRQ_ROUTING not supported by KVM"); + return -ENOTSUP; + } + has_xsave = kvm_check_extension(s, KVM_CAP_XSAVE); has_xcrs = kvm_check_extension(s, KVM_CAP_XCRS); has_pit_state2 = kvm_check_extension(s, KVM_CAP_PIT_STATE2); @@ -2643,6 +2673,18 @@ static void kvm_msr_entry_add_vmx(X86CPU *cpu, FeatureWordArray f) VMCS12_MAX_FIELD_INDEX << 1); } +static void kvm_msr_entry_add_perf(X86CPU *cpu, FeatureWordArray f) +{ + uint64_t kvm_perf_cap = + kvm_arch_get_supported_msr_feature(kvm_state, + MSR_IA32_PERF_CAPABILITIES); + + if (kvm_perf_cap) { + kvm_msr_entry_add(cpu, MSR_IA32_PERF_CAPABILITIES, + kvm_perf_cap & f[FEAT_PERF_CAPABILITIES]); + } +} + static int kvm_buf_set_msrs(X86CPU *cpu) { int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf); @@ -2675,6 +2717,10 @@ static void kvm_init_msrs(X86CPU *cpu) env->features[FEAT_CORE_CAPABILITY]); } + if (has_msr_perf_capabs && cpu->enable_pmu) { + kvm_msr_entry_add_perf(cpu, env->features); + } + if (has_msr_ucode_rev) { kvm_msr_entry_add(cpu, MSR_IA32_UCODE_REV, cpu->ucode_rev); } @@ -2759,6 +2805,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level) kvm_msr_entry_add(cpu, MSR_IA32_TSC, env->tsc); kvm_msr_entry_add(cpu, MSR_KVM_SYSTEM_TIME, env->system_time_msr); kvm_msr_entry_add(cpu, MSR_KVM_WALL_CLOCK, env->wall_clock_msr); + if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_ASYNC_PF_INT)) { + kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_INT, env->async_pf_int_msr); + } if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_ASYNC_PF)) { kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_EN, env->async_pf_en_msr); } @@ -3144,6 +3193,9 @@ static int kvm_get_msrs(X86CPU *cpu) #endif kvm_msr_entry_add(cpu, MSR_KVM_SYSTEM_TIME, 0); kvm_msr_entry_add(cpu, MSR_KVM_WALL_CLOCK, 0); + if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_ASYNC_PF_INT)) { + kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_INT, 0); + } if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_ASYNC_PF)) { kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_EN, 0); } @@ -3387,6 +3439,9 @@ static int kvm_get_msrs(X86CPU *cpu) case MSR_KVM_ASYNC_PF_EN: env->async_pf_en_msr = msrs[i].data; break; + case MSR_KVM_ASYNC_PF_INT: + env->async_pf_int_msr = msrs[i].data; + break; case MSR_KVM_PV_EOI_EN: env->pv_eoi_en_msr = msrs[i].data; break; @@ -3811,6 +3866,22 @@ static int kvm_put_nested_state(X86CPU *cpu) return 0; } + /* + * Copy flags that are affected by reset from env->hflags and env->hflags2. + */ + if (env->hflags & HF_GUEST_MASK) { + env->nested_state->flags |= KVM_STATE_NESTED_GUEST_MODE; + } else { + env->nested_state->flags &= ~KVM_STATE_NESTED_GUEST_MODE; + } + + /* Don't set KVM_STATE_NESTED_GIF_SET on VMX as it is illegal */ + if (cpu_has_svm(env) && (env->hflags2 & HF2_GIF_MASK)) { + env->nested_state->flags |= KVM_STATE_NESTED_GIF_SET; + } else { + env->nested_state->flags &= ~KVM_STATE_NESTED_GIF_SET; + } + assert(env->nested_state->size <= max_nested_state_len); return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_NESTED_STATE, env->nested_state); } @@ -3839,12 +3910,24 @@ static int kvm_get_nested_state(X86CPU *cpu) return ret; } + /* + * Copy flags that are affected by reset to env->hflags and env->hflags2. + */ if (env->nested_state->flags & KVM_STATE_NESTED_GUEST_MODE) { env->hflags |= HF_GUEST_MASK; } else { env->hflags &= ~HF_GUEST_MASK; } + /* Keep HF2_GIF_MASK set on !SVM as x86_cpu_pending_interrupt() needs it */ + if (cpu_has_svm(env)) { + if (env->nested_state->flags & KVM_STATE_NESTED_GIF_SET) { + env->hflags2 |= HF2_GIF_MASK; + } else { + env->hflags2 &= ~HF2_GIF_MASK; + } + } + return ret; } @@ -3855,6 +3938,12 @@ int kvm_arch_put_registers(CPUState *cpu, int level) assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); + /* must be before kvm_put_nested_state so that EFER.SVME is set */ + ret = kvm_put_sregs(x86_cpu); + if (ret < 0) { + return ret; + } + if (level >= KVM_PUT_RESET_STATE) { ret = kvm_put_nested_state(x86_cpu); if (ret < 0) { @@ -3888,10 +3977,6 @@ int kvm_arch_put_registers(CPUState *cpu, int level) if (ret < 0) { return ret; } - ret = kvm_put_sregs(x86_cpu); - if (ret < 0) { - return ret; - } /* must be before kvm_put_msrs */ ret = kvm_inject_mce_oldstyle(x86_cpu); if (ret < 0) { @@ -4464,13 +4549,6 @@ bool kvm_arch_stop_on_emulation_error(CPUState *cs) void kvm_arch_init_irq_routing(KVMState *s) { - if (!kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) { - /* If kernel can't do irq routing, interrupt source - * override 0->2 cannot be set up as required by HPET. - * So we have to disable it. - */ - no_hpet = 1; - } /* We know at this point that we're using the in-kernel * irqchip, so we can use irqfds, and on x86 we know * we can use msi via irqfd and GSI routing. @@ -4519,7 +4597,7 @@ int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, if (iommu) { int ret; MSIMessage src, dst; - X86IOMMUClass *class = X86_IOMMU_GET_CLASS(iommu); + X86IOMMUClass *class = X86_IOMMU_DEVICE_GET_CLASS(iommu); if (!class->int_remap) { return 0; @@ -4642,3 +4720,8 @@ int kvm_arch_msi_data_to_gsi(uint32_t data) { abort(); } + +bool kvm_has_waitpkg(void) +{ + return has_msr_umwait; +} diff --git a/target/i386/kvm_i386.h b/target/i386/kvm_i386.h index 00bde7acaf21612cbb519e656350ab141f260482..a4a619cebb441b71d62ca9598bb51ff2e83f9582 100644 --- a/target/i386/kvm_i386.h +++ b/target/i386/kvm_i386.h @@ -32,8 +32,8 @@ #endif /* CONFIG_KVM */ -bool kvm_allows_irq0_override(void); bool kvm_has_smm(void); +bool kvm_has_adjust_clock(void); bool kvm_has_adjust_clock_stable(void); bool kvm_has_exception_payload(void); void kvm_synchronize_all_tsc(void); @@ -44,6 +44,7 @@ void kvm_put_apicbase(X86CPU *cpu, uint64_t value); bool kvm_enable_x2apic(void); bool kvm_has_x2apic_api(void); +bool kvm_has_waitpkg(void); bool kvm_hv_vpindex_settable(void); diff --git a/target/i386/machine.c b/target/i386/machine.c index 0c96531a56f021b5c8aeef462fb5ed0123a16fe1..233e46bb70b5334b78183c1d47ba2a120f31f173 100644 --- a/target/i386/machine.c +++ b/target/i386/machine.c @@ -394,6 +394,13 @@ static bool async_pf_msr_needed(void *opaque) return cpu->env.async_pf_en_msr != 0; } +static bool async_pf_int_msr_needed(void *opaque) +{ + X86CPU *cpu = opaque; + + return cpu->env.async_pf_int_msr != 0; +} + static bool pv_eoi_msr_needed(void *opaque) { X86CPU *cpu = opaque; @@ -467,6 +474,17 @@ static const VMStateDescription vmstate_async_pf_msr = { } }; +static const VMStateDescription vmstate_async_pf_int_msr = { + .name = "cpu/async_pf_int_msr", + .version_id = 1, + .minimum_version_id = 1, + .needed = async_pf_int_msr_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT64(env.async_pf_int_msr, X86CPU), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_pv_eoi_msr = { .name = "cpu/async_pv_eoi_msr", .version_id = 1, @@ -1071,13 +1089,41 @@ static const VMStateDescription vmstate_vmx_nested_state = { } }; +static bool svm_nested_state_needed(void *opaque) +{ + struct kvm_nested_state *nested_state = opaque; + + /* + * HF_GUEST_MASK and HF2_GIF_MASK are already serialized + * via hflags and hflags2, all that's left is the opaque + * nested state blob. + */ + return (nested_state->format == KVM_STATE_NESTED_FORMAT_SVM && + nested_state->size > offsetof(struct kvm_nested_state, data)); +} + +static const VMStateDescription vmstate_svm_nested_state = { + .name = "cpu/kvm_nested_state/svm", + .version_id = 1, + .minimum_version_id = 1, + .needed = svm_nested_state_needed, + .fields = (VMStateField[]) { + VMSTATE_U64(hdr.svm.vmcb_pa, struct kvm_nested_state), + VMSTATE_UINT8_ARRAY(data.svm[0].vmcb12, + struct kvm_nested_state, + KVM_STATE_NESTED_SVM_VMCB_SIZE), + VMSTATE_END_OF_LIST() + } +}; + static bool nested_state_needed(void *opaque) { X86CPU *cpu = opaque; CPUX86State *env = &cpu->env; return (env->nested_state && - vmx_nested_state_needed(env->nested_state)); + (vmx_nested_state_needed(env->nested_state) || + svm_nested_state_needed(env->nested_state))); } static int nested_state_post_load(void *opaque, int version_id) @@ -1139,6 +1185,7 @@ static const VMStateDescription vmstate_kvm_nested_state = { }, .subsections = (const VMStateDescription*[]) { &vmstate_vmx_nested_state, + &vmstate_svm_nested_state, NULL } }; @@ -1409,6 +1456,7 @@ VMStateDescription vmstate_x86_cpu = { .subsections = (const VMStateDescription*[]) { &vmstate_exception_info, &vmstate_async_pf_msr, + &vmstate_async_pf_int_msr, &vmstate_pv_eoi_msr, &vmstate_steal_time_msr, &vmstate_poll_control_msr, diff --git a/target/i386/mem_helper.c b/target/i386/mem_helper.c index acf41f88857b6c60545b670ddf77b030f6ba6a18..21ca3e3e88f45b02ad4b7ea6ae3f43358edb7072 100644 --- a/target/i386/mem_helper.c +++ b/target/i386/mem_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -68,7 +68,7 @@ void helper_cmpxchg8b(CPUX86State *env, target_ulong a0) uint64_t *haddr = g2h(a0); cmpv = cpu_to_le64(cmpv); newv = cpu_to_le64(newv); - oldv = atomic_cmpxchg__nocheck(haddr, cmpv, newv); + oldv = qatomic_cmpxchg__nocheck(haddr, cmpv, newv); oldv = le64_to_cpu(oldv); } #else diff --git a/target/i386/meson.build b/target/i386/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..a1a02f3e99cd0986fb782ac67a450556438589f6 --- /dev/null +++ b/target/i386/meson.build @@ -0,0 +1,48 @@ +i386_ss = ss.source_set() +i386_ss.add(files( + 'cpu.c', + 'gdbstub.c', + 'helper.c', + 'xsave_helper.c', +)) +i386_ss.add(when: 'CONFIG_TCG', if_true: files( + 'bpt_helper.c', + 'cc_helper.c', + 'excp_helper.c', + 'fpu_helper.c', + 'int_helper.c', + 'mem_helper.c', + 'misc_helper.c', + 'mpx_helper.c', + 'seg_helper.c', + 'smm_helper.c', + 'svm_helper.c', + 'translate.c'), if_false: files('tcg-stub.c')) +i386_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c')) +i386_ss.add(when: 'CONFIG_SEV', if_true: files('sev.c'), if_false: files('sev-stub.c')) + +i386_softmmu_ss = ss.source_set() +i386_softmmu_ss.add(files( + 'arch_dump.c', + 'arch_memory_mapping.c', + 'machine.c', + 'monitor.c', +)) +i386_softmmu_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c'), if_false: files('hyperv-stub.c')) +i386_softmmu_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c')) +i386_softmmu_ss.add(when: 'CONFIG_WHPX', if_true: files( + 'whpx-all.c', + 'whpx-cpus.c', +)) +i386_softmmu_ss.add(when: 'CONFIG_HAX', if_true: files( + 'hax-all.c', + 'hax-mem.c', + 'hax-cpus.c', +)) +i386_softmmu_ss.add(when: ['CONFIG_HAX', 'CONFIG_POSIX'], if_true: files('hax-posix.c')) +i386_softmmu_ss.add(when: ['CONFIG_HAX', 'CONFIG_WIN32'], if_true: files('hax-windows.c')) + +subdir('hvf') + +target_arch += {'i386': i386_ss} +target_softmmu_arch += {'i386': i386_softmmu_ss} diff --git a/target/i386/misc_helper.c b/target/i386/misc_helper.c index 7d612210244af4aa6d36611da6defa5f1ac92b19..ae259d914565836c0e787133ac0f970874c45c5c 100644 --- a/target/i386/misc_helper.c +++ b/target/i386/misc_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -70,7 +70,7 @@ target_ulong helper_inw(CPUX86State *env, uint32_t port) void helper_outl(CPUX86State *env, uint32_t port, uint32_t data) { #ifdef CONFIG_USER_ONLY - fprintf(stderr, "outw: port=0x%04x, data=%08x\n", port, data); + fprintf(stderr, "outl: port=0x%04x, data=%08x\n", port, data); #else address_space_stl(&address_space_io, port, data, cpu_get_mem_attrs(env), NULL); diff --git a/target/i386/monitor.c b/target/i386/monitor.c index 27ebfa3ad22002ff30e3b10fd6e86b192a0ea46a..9f9e1c42f477301f1b3eb097841414eedc38676c 100644 --- a/target/i386/monitor.c +++ b/target/i386/monitor.c @@ -222,7 +222,7 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict) { CPUArchState *env; - env = mon_get_cpu_env(); + env = mon_get_cpu_env(mon); if (!env) { monitor_printf(mon, "No CPU available\n"); return; @@ -550,7 +550,7 @@ void hmp_info_mem(Monitor *mon, const QDict *qdict) { CPUArchState *env; - env = mon_get_cpu_env(); + env = mon_get_cpu_env(mon); if (!env) { monitor_printf(mon, "No CPU available\n"); return; @@ -601,9 +601,10 @@ void hmp_mce(Monitor *mon, const QDict *qdict) } } -static target_long monitor_get_pc(const struct MonitorDef *md, int val) +static target_long monitor_get_pc(Monitor *mon, const struct MonitorDef *md, + int val) { - CPUArchState *env = mon_get_cpu_env(); + CPUArchState *env = mon_get_cpu_env(mon); return env->eip + env->segs[R_CS].base; } @@ -656,7 +657,7 @@ void hmp_info_local_apic(Monitor *mon, const QDict *qdict) int id = qdict_get_try_int(qdict, "apic-id", 0); cs = cpu_by_arch_id(id); } else { - cs = mon_get_cpu(); + cs = mon_get_cpu(mon); } @@ -726,13 +727,5 @@ SevLaunchMeasureInfo *qmp_query_sev_launch_measure(Error **errp) SevCapability *qmp_query_sev_capabilities(Error **errp) { - SevCapability *data; - - data = sev_get_capabilities(); - if (!data) { - error_setg(errp, "SEV feature is not available"); - return NULL; - } - - return data; + return sev_get_capabilities(errp); } diff --git a/target/i386/mpx_helper.c b/target/i386/mpx_helper.c index ade5d245d25355d0790ca431c6b7fe7e6e9730cd..fd966174b49a44c5533117bbdd946118e67f0e81 100644 --- a/target/i386/mpx_helper.c +++ b/target/i386/mpx_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index 4658768de21ecee2440b3859cad70f5b31a353eb..6f1fc174b3243a8fc70709e0f046182c699da9a4 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -843,6 +843,7 @@ int64_t helper_cvttsd2sq(CPUX86State *env, ZMMReg *s) void helper_rsqrtps(CPUX86State *env, ZMMReg *d, ZMMReg *s) { + uint8_t old_flags = get_float_exception_flags(&env->sse_status); d->ZMM_S(0) = float32_div(float32_one, float32_sqrt(s->ZMM_S(0), &env->sse_status), &env->sse_status); @@ -855,26 +856,33 @@ void helper_rsqrtps(CPUX86State *env, ZMMReg *d, ZMMReg *s) d->ZMM_S(3) = float32_div(float32_one, float32_sqrt(s->ZMM_S(3), &env->sse_status), &env->sse_status); + set_float_exception_flags(old_flags, &env->sse_status); } void helper_rsqrtss(CPUX86State *env, ZMMReg *d, ZMMReg *s) { + uint8_t old_flags = get_float_exception_flags(&env->sse_status); d->ZMM_S(0) = float32_div(float32_one, float32_sqrt(s->ZMM_S(0), &env->sse_status), &env->sse_status); + set_float_exception_flags(old_flags, &env->sse_status); } void helper_rcpps(CPUX86State *env, ZMMReg *d, ZMMReg *s) { + uint8_t old_flags = get_float_exception_flags(&env->sse_status); d->ZMM_S(0) = float32_div(float32_one, s->ZMM_S(0), &env->sse_status); d->ZMM_S(1) = float32_div(float32_one, s->ZMM_S(1), &env->sse_status); d->ZMM_S(2) = float32_div(float32_one, s->ZMM_S(2), &env->sse_status); d->ZMM_S(3) = float32_div(float32_one, s->ZMM_S(3), &env->sse_status); + set_float_exception_flags(old_flags, &env->sse_status); } void helper_rcpss(CPUX86State *env, ZMMReg *d, ZMMReg *s) { + uint8_t old_flags = get_float_exception_flags(&env->sse_status); d->ZMM_S(0) = float32_div(float32_one, s->ZMM_S(0), &env->sse_status); + set_float_exception_flags(old_flags, &env->sse_status); } static inline uint64_t helper_extrq(uint64_t src, int shift, int len) @@ -1435,34 +1443,47 @@ void glue(helper_pshufb, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) void glue(helper_phaddw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - d->W(0) = (int16_t)d->W(0) + (int16_t)d->W(1); - d->W(1) = (int16_t)d->W(2) + (int16_t)d->W(3); - XMM_ONLY(d->W(2) = (int16_t)d->W(4) + (int16_t)d->W(5)); - XMM_ONLY(d->W(3) = (int16_t)d->W(6) + (int16_t)d->W(7)); - d->W((2 << SHIFT) + 0) = (int16_t)s->W(0) + (int16_t)s->W(1); - d->W((2 << SHIFT) + 1) = (int16_t)s->W(2) + (int16_t)s->W(3); - XMM_ONLY(d->W(6) = (int16_t)s->W(4) + (int16_t)s->W(5)); - XMM_ONLY(d->W(7) = (int16_t)s->W(6) + (int16_t)s->W(7)); + + Reg r; + + r.W(0) = (int16_t)d->W(0) + (int16_t)d->W(1); + r.W(1) = (int16_t)d->W(2) + (int16_t)d->W(3); + XMM_ONLY(r.W(2) = (int16_t)d->W(4) + (int16_t)d->W(5)); + XMM_ONLY(r.W(3) = (int16_t)d->W(6) + (int16_t)d->W(7)); + r.W((2 << SHIFT) + 0) = (int16_t)s->W(0) + (int16_t)s->W(1); + r.W((2 << SHIFT) + 1) = (int16_t)s->W(2) + (int16_t)s->W(3); + XMM_ONLY(r.W(6) = (int16_t)s->W(4) + (int16_t)s->W(5)); + XMM_ONLY(r.W(7) = (int16_t)s->W(6) + (int16_t)s->W(7)); + + *d = r; } void glue(helper_phaddd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - d->L(0) = (int32_t)d->L(0) + (int32_t)d->L(1); - XMM_ONLY(d->L(1) = (int32_t)d->L(2) + (int32_t)d->L(3)); - d->L((1 << SHIFT) + 0) = (int32_t)s->L(0) + (int32_t)s->L(1); - XMM_ONLY(d->L(3) = (int32_t)s->L(2) + (int32_t)s->L(3)); + Reg r; + + r.L(0) = (int32_t)d->L(0) + (int32_t)d->L(1); + XMM_ONLY(r.L(1) = (int32_t)d->L(2) + (int32_t)d->L(3)); + r.L((1 << SHIFT) + 0) = (int32_t)s->L(0) + (int32_t)s->L(1); + XMM_ONLY(r.L(3) = (int32_t)s->L(2) + (int32_t)s->L(3)); + + *d = r; } void glue(helper_phaddsw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - d->W(0) = satsw((int16_t)d->W(0) + (int16_t)d->W(1)); - d->W(1) = satsw((int16_t)d->W(2) + (int16_t)d->W(3)); - XMM_ONLY(d->W(2) = satsw((int16_t)d->W(4) + (int16_t)d->W(5))); - XMM_ONLY(d->W(3) = satsw((int16_t)d->W(6) + (int16_t)d->W(7))); - d->W((2 << SHIFT) + 0) = satsw((int16_t)s->W(0) + (int16_t)s->W(1)); - d->W((2 << SHIFT) + 1) = satsw((int16_t)s->W(2) + (int16_t)s->W(3)); - XMM_ONLY(d->W(6) = satsw((int16_t)s->W(4) + (int16_t)s->W(5))); - XMM_ONLY(d->W(7) = satsw((int16_t)s->W(6) + (int16_t)s->W(7))); + Reg r; + + r.W(0) = satsw((int16_t)d->W(0) + (int16_t)d->W(1)); + r.W(1) = satsw((int16_t)d->W(2) + (int16_t)d->W(3)); + XMM_ONLY(r.W(2) = satsw((int16_t)d->W(4) + (int16_t)d->W(5))); + XMM_ONLY(r.W(3) = satsw((int16_t)d->W(6) + (int16_t)d->W(7))); + r.W((2 << SHIFT) + 0) = satsw((int16_t)s->W(0) + (int16_t)s->W(1)); + r.W((2 << SHIFT) + 1) = satsw((int16_t)s->W(2) + (int16_t)s->W(3)); + XMM_ONLY(r.W(6) = satsw((int16_t)s->W(4) + (int16_t)s->W(5))); + XMM_ONLY(r.W(7) = satsw((int16_t)s->W(6) + (int16_t)s->W(7))); + + *d = r; } void glue(helper_pmaddubsw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) @@ -1751,6 +1772,7 @@ void glue(helper_phminposuw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) void glue(helper_roundps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t mode) { + uint8_t old_flags = get_float_exception_flags(&env->sse_status); signed char prev_rounding_mode; prev_rounding_mode = env->sse_status.float_rounding_mode; @@ -1776,19 +1798,18 @@ void glue(helper_roundps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, d->ZMM_S(2) = float32_round_to_int(s->ZMM_S(2), &env->sse_status); d->ZMM_S(3) = float32_round_to_int(s->ZMM_S(3), &env->sse_status); -#if 0 /* TODO */ - if (mode & (1 << 3)) { + if (mode & (1 << 3) && !(old_flags & float_flag_inexact)) { set_float_exception_flags(get_float_exception_flags(&env->sse_status) & ~float_flag_inexact, &env->sse_status); } -#endif env->sse_status.float_rounding_mode = prev_rounding_mode; } void glue(helper_roundpd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t mode) { + uint8_t old_flags = get_float_exception_flags(&env->sse_status); signed char prev_rounding_mode; prev_rounding_mode = env->sse_status.float_rounding_mode; @@ -1812,19 +1833,18 @@ void glue(helper_roundpd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, d->ZMM_D(0) = float64_round_to_int(s->ZMM_D(0), &env->sse_status); d->ZMM_D(1) = float64_round_to_int(s->ZMM_D(1), &env->sse_status); -#if 0 /* TODO */ - if (mode & (1 << 3)) { + if (mode & (1 << 3) && !(old_flags & float_flag_inexact)) { set_float_exception_flags(get_float_exception_flags(&env->sse_status) & ~float_flag_inexact, &env->sse_status); } -#endif env->sse_status.float_rounding_mode = prev_rounding_mode; } void glue(helper_roundss, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t mode) { + uint8_t old_flags = get_float_exception_flags(&env->sse_status); signed char prev_rounding_mode; prev_rounding_mode = env->sse_status.float_rounding_mode; @@ -1847,19 +1867,18 @@ void glue(helper_roundss, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, d->ZMM_S(0) = float32_round_to_int(s->ZMM_S(0), &env->sse_status); -#if 0 /* TODO */ - if (mode & (1 << 3)) { + if (mode & (1 << 3) && !(old_flags & float_flag_inexact)) { set_float_exception_flags(get_float_exception_flags(&env->sse_status) & ~float_flag_inexact, &env->sse_status); } -#endif env->sse_status.float_rounding_mode = prev_rounding_mode; } void glue(helper_roundsd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t mode) { + uint8_t old_flags = get_float_exception_flags(&env->sse_status); signed char prev_rounding_mode; prev_rounding_mode = env->sse_status.float_rounding_mode; @@ -1882,13 +1901,11 @@ void glue(helper_roundsd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, d->ZMM_D(0) = float64_round_to_int(s->ZMM_D(0), &env->sse_status); -#if 0 /* TODO */ - if (mode & (1 << 3)) { + if (mode & (1 << 3) && !(old_flags & float_flag_inexact)) { set_float_exception_flags(get_float_exception_flags(&env->sse_status) & ~float_flag_inexact, &env->sse_status); } -#endif env->sse_status.float_rounding_mode = prev_rounding_mode; } @@ -2076,10 +2093,10 @@ static inline unsigned pcmpxstrx(CPUX86State *env, Reg *d, Reg *s, res = (2 << upper) - 1; break; } - for (j = valids - validd; j >= 0; j--) { + for (j = valids == upper ? valids : valids - validd; j >= 0; j--) { res <<= 1; v = 1; - for (i = validd; i >= 0; i--) { + for (i = MIN(valids - j, validd); i >= 0; i--) { v &= (pcmp_val(s, ctrl, i + j) == pcmp_val(d, ctrl, i)); } res |= v; diff --git a/target/i386/ops_sse_header.h b/target/i386/ops_sse_header.h index 094aafc573c552a189238ab161f34fdd0c561e41..6c0c849347a0111b399f9ad75696fd3e902fdfef 100644 --- a/target/i386/ops_sse_header.h +++ b/target/i386/ops_sse_header.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/i386/seg_helper.c b/target/i386/seg_helper.c index b96de068cad02d98e49c862564bb5625677b8eb1..09b65546609acb53823a17588008244b9869ef6f 100644 --- a/target/i386/seg_helper.c +++ b/target/i386/seg_helper.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -975,6 +975,7 @@ void helper_syscall(CPUX86State *env, int next_eip_addend) CPUState *cs = env_cpu(env); cs->exception_index = EXCP_SYSCALL; + env->exception_is_int = 0; env->exception_next_eip = env->eip + next_eip_addend; cpu_loop_exit(cs); } diff --git a/target/i386/sev-stub.c b/target/i386/sev-stub.c index e5ee13309cc0fcc5a8483104eef46b9dd3b62682..88e3f39a1e609097e79600c43bd549c589615d37 100644 --- a/target/i386/sev-stub.c +++ b/target/i386/sev-stub.c @@ -44,7 +44,8 @@ char *sev_get_launch_measurement(void) return NULL; } -SevCapability *sev_get_capabilities(void) +SevCapability *sev_get_capabilities(Error **errp) { + error_setg(errp, "SEV is not available in this QEMU"); return NULL; } diff --git a/target/i386/sev.c b/target/i386/sev.c index 51cdbe5496729b307580cf4ccf2697ad925dcf22..93c4d60b82b919d8a2e73374aef28cf7b8f7b5ca 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -28,11 +28,48 @@ #include "sysemu/runstate.h" #include "trace.h" #include "migration/blocker.h" +#include "qom/object.h" + +#define TYPE_SEV_GUEST "sev-guest" +OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState, SEV_GUEST) + + +/** + * SevGuestState: + * + * The SevGuestState object is used for creating and managing a SEV + * guest. + * + * # $QEMU \ + * -object sev-guest,id=sev0 \ + * -machine ...,memory-encryption=sev0 + */ +struct SevGuestState { + Object parent_obj; + + /* configuration parameters */ + char *sev_device; + uint32_t policy; + char *dh_cert_file; + char *session_file; + uint32_t cbitpos; + uint32_t reduced_phys_bits; + + /* runtime state */ + uint32_t handle; + uint8_t api_major; + uint8_t api_minor; + uint8_t build_id; + uint64_t me_mask; + int sev_fd; + SevState state; + gchar *measurement; +}; #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */ #define DEFAULT_SEV_DEVICE "/dev/sev" -static SEVState *sev_state; +static SevGuestState *sev_guest; static Error *sev_mig_blocker; static const char *const sev_fw_errlist[] = { @@ -111,21 +148,21 @@ fw_error_to_str(int code) } static bool -sev_check_state(SevState state) +sev_check_state(const SevGuestState *sev, SevState state) { - assert(sev_state); - return sev_state->state == state ? true : false; + assert(sev); + return sev->state == state ? true : false; } static void -sev_set_guest_state(SevState new_state) +sev_set_guest_state(SevGuestState *sev, SevState new_state) { assert(new_state < SEV_STATE__MAX); - assert(sev_state); + assert(sev); - trace_kvm_sev_change_state(SevState_str(sev_state->state), + trace_kvm_sev_change_state(SevState_str(sev->state), SevState_str(new_state)); - sev_state->state = new_state; + sev->state = new_state; } static void @@ -191,82 +228,82 @@ static struct RAMBlockNotifier sev_ram_notifier = { }; static void -qsev_guest_finalize(Object *obj) +sev_guest_finalize(Object *obj) { } static char * -qsev_guest_get_session_file(Object *obj, Error **errp) +sev_guest_get_session_file(Object *obj, Error **errp) { - QSevGuestInfo *s = QSEV_GUEST_INFO(obj); + SevGuestState *s = SEV_GUEST(obj); return s->session_file ? g_strdup(s->session_file) : NULL; } static void -qsev_guest_set_session_file(Object *obj, const char *value, Error **errp) +sev_guest_set_session_file(Object *obj, const char *value, Error **errp) { - QSevGuestInfo *s = QSEV_GUEST_INFO(obj); + SevGuestState *s = SEV_GUEST(obj); s->session_file = g_strdup(value); } static char * -qsev_guest_get_dh_cert_file(Object *obj, Error **errp) +sev_guest_get_dh_cert_file(Object *obj, Error **errp) { - QSevGuestInfo *s = QSEV_GUEST_INFO(obj); + SevGuestState *s = SEV_GUEST(obj); return g_strdup(s->dh_cert_file); } static void -qsev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp) +sev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp) { - QSevGuestInfo *s = QSEV_GUEST_INFO(obj); + SevGuestState *s = SEV_GUEST(obj); s->dh_cert_file = g_strdup(value); } static char * -qsev_guest_get_sev_device(Object *obj, Error **errp) +sev_guest_get_sev_device(Object *obj, Error **errp) { - QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); + SevGuestState *sev = SEV_GUEST(obj); return g_strdup(sev->sev_device); } static void -qsev_guest_set_sev_device(Object *obj, const char *value, Error **errp) +sev_guest_set_sev_device(Object *obj, const char *value, Error **errp) { - QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); + SevGuestState *sev = SEV_GUEST(obj); sev->sev_device = g_strdup(value); } static void -qsev_guest_class_init(ObjectClass *oc, void *data) +sev_guest_class_init(ObjectClass *oc, void *data) { object_class_property_add_str(oc, "sev-device", - qsev_guest_get_sev_device, - qsev_guest_set_sev_device); + sev_guest_get_sev_device, + sev_guest_set_sev_device); object_class_property_set_description(oc, "sev-device", "SEV device to use"); object_class_property_add_str(oc, "dh-cert-file", - qsev_guest_get_dh_cert_file, - qsev_guest_set_dh_cert_file); + sev_guest_get_dh_cert_file, + sev_guest_set_dh_cert_file); object_class_property_set_description(oc, "dh-cert-file", "guest owners DH certificate (encoded with base64)"); object_class_property_add_str(oc, "session-file", - qsev_guest_get_session_file, - qsev_guest_set_session_file); + sev_guest_get_session_file, + sev_guest_set_session_file); object_class_property_set_description(oc, "session-file", "guest owners session parameters (encoded with base64)"); } static void -qsev_guest_init(Object *obj) +sev_guest_instance_init(Object *obj) { - QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); + SevGuestState *sev = SEV_GUEST(obj); sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE); sev->policy = DEFAULT_GUEST_POLICY; @@ -282,33 +319,32 @@ qsev_guest_init(Object *obj) } /* sev guest info */ -static const TypeInfo qsev_guest_info = { +static const TypeInfo sev_guest_info = { .parent = TYPE_OBJECT, - .name = TYPE_QSEV_GUEST_INFO, - .instance_size = sizeof(QSevGuestInfo), - .instance_finalize = qsev_guest_finalize, - .class_size = sizeof(QSevGuestInfoClass), - .class_init = qsev_guest_class_init, - .instance_init = qsev_guest_init, + .name = TYPE_SEV_GUEST, + .instance_size = sizeof(SevGuestState), + .instance_finalize = sev_guest_finalize, + .class_init = sev_guest_class_init, + .instance_init = sev_guest_instance_init, .interfaces = (InterfaceInfo[]) { { TYPE_USER_CREATABLE }, { } } }; -static QSevGuestInfo * +static SevGuestState * lookup_sev_guest_info(const char *id) { Object *obj; - QSevGuestInfo *info; + SevGuestState *info; obj = object_resolve_path_component(object_get_objects_root(), id); if (!obj) { return NULL; } - info = (QSevGuestInfo *) - object_dynamic_cast(obj, TYPE_QSEV_GUEST_INFO); + info = (SevGuestState *) + object_dynamic_cast(obj, TYPE_SEV_GUEST); if (!info) { return NULL; } @@ -319,25 +355,25 @@ lookup_sev_guest_info(const char *id) bool sev_enabled(void) { - return sev_state ? true : false; + return !!sev_guest; } uint64_t sev_get_me_mask(void) { - return sev_state ? sev_state->me_mask : ~0; + return sev_guest ? sev_guest->me_mask : ~0; } uint32_t sev_get_cbit_position(void) { - return sev_state ? sev_state->cbitpos : 0; + return sev_guest ? sev_guest->cbitpos : 0; } uint32_t sev_get_reduced_phys_bits(void) { - return sev_state ? sev_state->reduced_phys_bits : 0; + return sev_guest ? sev_guest->reduced_phys_bits : 0; } SevInfo * @@ -346,15 +382,15 @@ sev_get_info(void) SevInfo *info; info = g_new0(SevInfo, 1); - info->enabled = sev_state ? true : false; + info->enabled = sev_enabled(); if (info->enabled) { - info->api_major = sev_state->api_major; - info->api_minor = sev_state->api_minor; - info->build_id = sev_state->build_id; - info->policy = sev_state->policy; - info->state = sev_state->state; - info->handle = sev_state->handle; + info->api_major = sev_guest->api_major; + info->api_minor = sev_guest->api_minor; + info->build_id = sev_guest->build_id; + info->policy = sev_guest->policy; + info->state = sev_guest->state; + info->handle = sev_guest->handle; } return info; @@ -362,7 +398,7 @@ sev_get_info(void) static int sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain, - size_t *cert_chain_len) + size_t *cert_chain_len, Error **errp) { guchar *pdh_data = NULL; guchar *cert_chain_data = NULL; @@ -373,8 +409,8 @@ sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain, r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err); if (r < 0) { if (err != SEV_RET_INVALID_LEN) { - error_report("failed to export PDH cert ret=%d fw_err=%d (%s)", - r, err, fw_error_to_str(err)); + error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)", + r, err, fw_error_to_str(err)); return 1; } } @@ -386,8 +422,8 @@ sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain, r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err); if (r < 0) { - error_report("failed to export PDH cert ret=%d fw_err=%d (%s)", - r, err, fw_error_to_str(err)); + error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)", + r, err, fw_error_to_str(err)); goto e_free; } @@ -404,7 +440,7 @@ e_free: } SevCapability * -sev_get_capabilities(void) +sev_get_capabilities(Error **errp) { SevCapability *cap = NULL; guchar *pdh_data = NULL; @@ -413,15 +449,24 @@ sev_get_capabilities(void) uint32_t ebx; int fd; + if (!kvm_enabled()) { + error_setg(errp, "KVM not enabled"); + return NULL; + } + if (kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, NULL) < 0) { + error_setg(errp, "SEV is not enabled in KVM"); + return NULL; + } + fd = open(DEFAULT_SEV_DEVICE, O_RDWR); if (fd < 0) { - error_report("%s: Failed to open %s '%s'", __func__, - DEFAULT_SEV_DEVICE, strerror(errno)); + error_setg_errno(errp, errno, "Failed to open %s", + DEFAULT_SEV_DEVICE); return NULL; } if (sev_get_pdh_info(fd, &pdh_data, &pdh_len, - &cert_chain_data, &cert_chain_len)) { + &cert_chain_data, &cert_chain_len, errp)) { goto out; } @@ -454,6 +499,7 @@ sev_read_file_base64(const char *filename, guchar **data, gsize *len) if (!g_file_get_contents(filename, &base64, &sz, &error)) { error_report("failed to read '%s' (%s)", filename, error->message); + g_error_free(error); return -1; } @@ -462,21 +508,18 @@ sev_read_file_base64(const char *filename, guchar **data, gsize *len) } static int -sev_launch_start(SEVState *s) +sev_launch_start(SevGuestState *sev) { gsize sz; int ret = 1; int fw_error, rc; - QSevGuestInfo *sev = s->sev_info; struct kvm_sev_launch_start *start; guchar *session = NULL, *dh_cert = NULL; start = g_new0(struct kvm_sev_launch_start, 1); - start->handle = object_property_get_int(OBJECT(sev), "handle", - &error_abort); - start->policy = object_property_get_int(OBJECT(sev), "policy", - &error_abort); + start->handle = sev->handle; + start->policy = sev->policy; if (sev->session_file) { if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) { goto out; @@ -494,18 +537,15 @@ sev_launch_start(SEVState *s) } trace_kvm_sev_launch_start(start->policy, session, dh_cert); - rc = sev_ioctl(s->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error); + rc = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error); if (rc < 0) { error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'", __func__, ret, fw_error, fw_error_to_str(fw_error)); goto out; } - object_property_set_int(OBJECT(sev), start->handle, "handle", - &error_abort); - sev_set_guest_state(SEV_STATE_LAUNCH_UPDATE); - s->handle = start->handle; - s->policy = start->policy; + sev_set_guest_state(sev, SEV_STATE_LAUNCH_UPDATE); + sev->handle = start->handle; ret = 0; out: @@ -516,7 +556,7 @@ out: } static int -sev_launch_update_data(uint8_t *addr, uint64_t len) +sev_launch_update_data(SevGuestState *sev, uint8_t *addr, uint64_t len) { int ret, fw_error; struct kvm_sev_launch_update_data update; @@ -528,7 +568,7 @@ sev_launch_update_data(uint8_t *addr, uint64_t len) update.uaddr = (__u64)(unsigned long)addr; update.len = len; trace_kvm_sev_launch_update_data(addr, len); - ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA, + ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA, &update, &fw_error); if (ret) { error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'", @@ -541,19 +581,19 @@ sev_launch_update_data(uint8_t *addr, uint64_t len) static void sev_launch_get_measure(Notifier *notifier, void *unused) { + SevGuestState *sev = sev_guest; int ret, error; guchar *data; - SEVState *s = sev_state; struct kvm_sev_launch_measure *measurement; - if (!sev_check_state(SEV_STATE_LAUNCH_UPDATE)) { + if (!sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) { return; } measurement = g_new0(struct kvm_sev_launch_measure, 1); /* query the measurement blob length */ - ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_MEASURE, + ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE, measurement, &error); if (!measurement->len) { error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'", @@ -565,7 +605,7 @@ sev_launch_get_measure(Notifier *notifier, void *unused) measurement->uaddr = (unsigned long)data; /* get the measurement blob */ - ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_MEASURE, + ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE, measurement, &error); if (ret) { error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'", @@ -573,11 +613,11 @@ sev_launch_get_measure(Notifier *notifier, void *unused) goto free_data; } - sev_set_guest_state(SEV_STATE_LAUNCH_SECRET); + sev_set_guest_state(sev, SEV_STATE_LAUNCH_SECRET); /* encode the measurement value and emit the event */ - s->measurement = g_base64_encode(data, measurement->len); - trace_kvm_sev_launch_measurement(s->measurement); + sev->measurement = g_base64_encode(data, measurement->len); + trace_kvm_sev_launch_measurement(sev->measurement); free_data: g_free(data); @@ -588,9 +628,9 @@ free_measurement: char * sev_get_launch_measurement(void) { - if (sev_state && - sev_state->state >= SEV_STATE_LAUNCH_SECRET) { - return g_strdup(sev_state->measurement); + if (sev_guest && + sev_guest->state >= SEV_STATE_LAUNCH_SECRET) { + return g_strdup(sev_guest->measurement); } return NULL; @@ -601,20 +641,20 @@ static Notifier sev_machine_done_notify = { }; static void -sev_launch_finish(SEVState *s) +sev_launch_finish(SevGuestState *sev) { int ret, error; Error *local_err = NULL; trace_kvm_sev_launch_finish(); - ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error); + ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error); if (ret) { error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'", __func__, ret, error, fw_error_to_str(error)); exit(1); } - sev_set_guest_state(SEV_STATE_RUNNING); + sev_set_guest_state(sev, SEV_STATE_RUNNING); /* add migration blocker */ error_setg(&sev_mig_blocker, @@ -630,11 +670,11 @@ sev_launch_finish(SEVState *s) static void sev_vm_state_change(void *opaque, int running, RunState state) { - SEVState *s = opaque; + SevGuestState *sev = opaque; if (running) { - if (!sev_check_state(SEV_STATE_RUNNING)) { - sev_launch_finish(s); + if (!sev_check_state(sev, SEV_STATE_RUNNING)) { + sev_launch_finish(sev); } } } @@ -642,55 +682,58 @@ sev_vm_state_change(void *opaque, int running, RunState state) void * sev_guest_init(const char *id) { - SEVState *s; + SevGuestState *sev; char *devname; int ret, fw_error; uint32_t ebx; uint32_t host_cbitpos; struct sev_user_data_status status = {}; - sev_state = s = g_new0(SEVState, 1); - s->sev_info = lookup_sev_guest_info(id); - if (!s->sev_info) { + ret = ram_block_discard_disable(true); + if (ret) { + error_report("%s: cannot disable RAM discard", __func__); + return NULL; + } + + sev = lookup_sev_guest_info(id); + if (!sev) { error_report("%s: '%s' is not a valid '%s' object", - __func__, id, TYPE_QSEV_GUEST_INFO); + __func__, id, TYPE_SEV_GUEST); goto err; } - s->state = SEV_STATE_UNINIT; + sev_guest = sev; + sev->state = SEV_STATE_UNINIT; host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL); host_cbitpos = ebx & 0x3f; - s->cbitpos = object_property_get_int(OBJECT(s->sev_info), "cbitpos", NULL); - if (host_cbitpos != s->cbitpos) { + if (host_cbitpos != sev->cbitpos) { error_report("%s: cbitpos check failed, host '%d' requested '%d'", - __func__, host_cbitpos, s->cbitpos); + __func__, host_cbitpos, sev->cbitpos); goto err; } - s->reduced_phys_bits = object_property_get_int(OBJECT(s->sev_info), - "reduced-phys-bits", NULL); - if (s->reduced_phys_bits < 1) { + if (sev->reduced_phys_bits < 1) { error_report("%s: reduced_phys_bits check failed, it should be >=1," - " requested '%d'", __func__, s->reduced_phys_bits); + " requested '%d'", __func__, sev->reduced_phys_bits); goto err; } - s->me_mask = ~(1UL << s->cbitpos); + sev->me_mask = ~(1UL << sev->cbitpos); - devname = object_property_get_str(OBJECT(s->sev_info), "sev-device", NULL); - s->sev_fd = open(devname, O_RDWR); - if (s->sev_fd < 0) { + devname = object_property_get_str(OBJECT(sev), "sev-device", NULL); + sev->sev_fd = open(devname, O_RDWR); + if (sev->sev_fd < 0) { error_report("%s: Failed to open %s '%s'", __func__, devname, strerror(errno)); } g_free(devname); - if (s->sev_fd < 0) { + if (sev->sev_fd < 0) { goto err; } - ret = sev_platform_ioctl(s->sev_fd, SEV_PLATFORM_STATUS, &status, + ret = sev_platform_ioctl(sev->sev_fd, SEV_PLATFORM_STATUS, &status, &fw_error); if (ret) { error_report("%s: failed to get platform status ret=%d " @@ -698,19 +741,19 @@ sev_guest_init(const char *id) fw_error_to_str(fw_error)); goto err; } - s->build_id = status.build; - s->api_major = status.api_major; - s->api_minor = status.api_minor; + sev->build_id = status.build; + sev->api_major = status.api_major; + sev->api_minor = status.api_minor; trace_kvm_sev_init(); - ret = sev_ioctl(s->sev_fd, KVM_SEV_INIT, NULL, &fw_error); + ret = sev_ioctl(sev->sev_fd, KVM_SEV_INIT, NULL, &fw_error); if (ret) { error_report("%s: failed to initialize ret=%d fw_error=%d '%s'", __func__, ret, fw_error, fw_error_to_str(fw_error)); goto err; } - ret = sev_launch_start(s); + ret = sev_launch_start(sev); if (ret) { error_report("%s: failed to create encryption context", __func__); goto err; @@ -718,23 +761,25 @@ sev_guest_init(const char *id) ram_block_notifier_add(&sev_ram_notifier); qemu_add_machine_init_done_notifier(&sev_machine_done_notify); - qemu_add_vm_change_state_handler(sev_vm_state_change, s); + qemu_add_vm_change_state_handler(sev_vm_state_change, sev); - return s; + return sev; err: - g_free(sev_state); - sev_state = NULL; + sev_guest = NULL; + ram_block_discard_disable(false); return NULL; } int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len) { - assert(handle); + SevGuestState *sev = handle; + + assert(sev); /* if SEV is in update state then encrypt the data else do nothing */ - if (sev_check_state(SEV_STATE_LAUNCH_UPDATE)) { - return sev_launch_update_data(ptr, len); + if (sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) { + return sev_launch_update_data(sev, ptr, len); } return 0; @@ -743,7 +788,7 @@ sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len) static void sev_register_types(void) { - type_register_static(&qsev_guest_info); + type_register_static(&sev_guest_info); } type_init(sev_register_types); diff --git a/target/i386/sev_i386.h b/target/i386/sev_i386.h index 8ada9d385d0e8631f78c96a826598b3a01056825..4db6960f6036190a225be279f143ef0d93fc14c8 100644 --- a/target/i386/sev_i386.h +++ b/target/i386/sev_i386.h @@ -28,61 +28,12 @@ #define SEV_POLICY_DOMAIN 0x10 #define SEV_POLICY_SEV 0x20 -#define TYPE_QSEV_GUEST_INFO "sev-guest" -#define QSEV_GUEST_INFO(obj) \ - OBJECT_CHECK(QSevGuestInfo, (obj), TYPE_QSEV_GUEST_INFO) - extern bool sev_enabled(void); extern uint64_t sev_get_me_mask(void); extern SevInfo *sev_get_info(void); extern uint32_t sev_get_cbit_position(void); extern uint32_t sev_get_reduced_phys_bits(void); extern char *sev_get_launch_measurement(void); -extern SevCapability *sev_get_capabilities(void); - -typedef struct QSevGuestInfo QSevGuestInfo; -typedef struct QSevGuestInfoClass QSevGuestInfoClass; - -/** - * QSevGuestInfo: - * - * The QSevGuestInfo object is used for creating a SEV guest. - * - * # $QEMU \ - * -object sev-guest,id=sev0 \ - * -machine ...,memory-encryption=sev0 - */ -struct QSevGuestInfo { - Object parent_obj; - - char *sev_device; - uint32_t policy; - uint32_t handle; - char *dh_cert_file; - char *session_file; - uint32_t cbitpos; - uint32_t reduced_phys_bits; -}; - -struct QSevGuestInfoClass { - ObjectClass parent_class; -}; - -struct SEVState { - QSevGuestInfo *sev_info; - uint8_t api_major; - uint8_t api_minor; - uint8_t build_id; - uint32_t policy; - uint64_t me_mask; - uint32_t cbitpos; - uint32_t reduced_phys_bits; - uint32_t handle; - int sev_fd; - SevState state; - gchar *measurement; -}; - -typedef struct SEVState SEVState; +extern SevCapability *sev_get_capabilities(Error **errp); #endif diff --git a/target/i386/shift_helper_template.h b/target/i386/shift_helper_template.h index cf91a2d284d51f10cddeb80d123cf96c2836b2dd..54f15d6e05c1ee77958297244b01ba1639202acf 100644 --- a/target/i386/shift_helper_template.h +++ b/target/i386/shift_helper_template.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/i386/smm_helper.c b/target/i386/smm_helper.c index eb5aa6eb3dd9b506a8a7d7b79fbcdbc3de0b753a..d20e8edfdf99fc395c8a316686de0fde012e67e4 100644 --- a/target/i386/smm_helper.c +++ b/target/i386/smm_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/i386/svm.h b/target/i386/svm.h index 23a3a040b887fcd5469a1376103669ef44f13d64..ae30fc6f79419db079818e0d9d46959684ec71ef 100644 --- a/target/i386/svm.h +++ b/target/i386/svm.h @@ -135,6 +135,7 @@ #define SVM_NPT_PAE (1 << 0) #define SVM_NPT_LMA (1 << 1) #define SVM_NPT_NXE (1 << 2) +#define SVM_NPT_PSE (1 << 3) #define SVM_NPTEXIT_P (1ULL << 0) #define SVM_NPTEXIT_RW (1ULL << 1) diff --git a/target/i386/svm_helper.c b/target/i386/svm_helper.c index 7b8105a1c3fe5e09b0183712d158ff5bed08bdff..38931586e53ba3f2d29120b519ec32ceace26fad 100644 --- a/target/i386/svm_helper.c +++ b/target/i386/svm_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -209,16 +209,21 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend) nested_ctl = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, control.nested_ctl)); + + env->nested_pg_mode = 0; + if (nested_ctl & SVM_NPT_ENABLED) { env->nested_cr3 = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, control.nested_cr3)); env->hflags2 |= HF2_NPT_MASK; - env->nested_pg_mode = 0; if (env->cr[4] & CR4_PAE_MASK) { env->nested_pg_mode |= SVM_NPT_PAE; } + if (env->cr[4] & CR4_PSE_MASK) { + env->nested_pg_mode |= SVM_NPT_PSE; + } if (env->hflags & HF_LMA_MASK) { env->nested_pg_mode |= SVM_NPT_LMA; } diff --git a/target/i386/tcg-stub.c b/target/i386/tcg-stub.c new file mode 100644 index 0000000000000000000000000000000000000000..8d45579ada253388acfe98316153f26bee59cb9b --- /dev/null +++ b/target/i386/tcg-stub.c @@ -0,0 +1,25 @@ +/* + * x86 FPU, MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4/PNI helpers + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "cpu.h" + +void update_mxcsr_from_sse_status(CPUX86State *env) +{ +} diff --git a/target/i386/trace.h b/target/i386/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..781e8ec55c907338f8968e7d1a700e245f4eabbc --- /dev/null +++ b/target/i386/trace.h @@ -0,0 +1 @@ +#include "trace/trace-target_i386.h" diff --git a/target/i386/translate.c b/target/i386/translate.c index 5e5dbb41b0cee3ee7d7cb67a2c561edd08c2540d..4c57307e42a4137706a1b20885145f490ccf077b 100644 --- a/target/i386/translate.c +++ b/target/i386/translate.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -1128,9 +1128,6 @@ static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot) static inline void gen_ins(DisasContext *s, MemOp ot) { - if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { - gen_io_start(); - } gen_string_movl_A0_EDI(s); /* Note: we must do this dummy write first to be restartable in case of page fault. */ @@ -1143,16 +1140,10 @@ static inline void gen_ins(DisasContext *s, MemOp ot) gen_op_movl_T0_Dshift(s, ot); gen_op_add_reg_T0(s, s->aflag, R_EDI); gen_bpt_io(s, s->tmp2_i32, ot); - if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { - gen_io_end(); - } } static inline void gen_outs(DisasContext *s, MemOp ot) { - if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { - gen_io_start(); - } gen_string_movl_A0_ESI(s); gen_op_ld_v(s, ot, s->T0, s->A0); @@ -1163,9 +1154,6 @@ static inline void gen_outs(DisasContext *s, MemOp ot) gen_op_movl_T0_Dshift(s, ot); gen_op_add_reg_T0(s, s->aflag, R_ESI); gen_bpt_io(s, s->tmp2_i32, ot); - if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { - gen_io_end(); - } } /* same method as Valgrind : we generate jumps to current or next @@ -6400,8 +6388,12 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]); gen_check_io(s, ot, pc_start - s->cs_base, SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4); + if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { + gen_io_start(); + } if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); + /* jump generated by gen_repz_ins */ } else { gen_ins(s, ot); if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { @@ -6415,8 +6407,12 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]); gen_check_io(s, ot, pc_start - s->cs_base, svm_is_rep(prefixes) | 4); + if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { + gen_io_start(); + } if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); + /* jump generated by gen_repz_outs */ } else { gen_outs(s, ot); if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { @@ -7152,6 +7148,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) l1 = gen_new_label(); l2 = gen_new_label(); l3 = gen_new_label(); + gen_update_cc_op(s); b &= 3; switch(b) { case 0: /* loopnz */ @@ -7583,12 +7580,13 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) CASE_MODRM_OP(4): /* smsw */ gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0); tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, cr[0])); - if (CODE64(s)) { - mod = (modrm >> 6) & 3; - ot = (mod != 3 ? MO_16 : s->dflag); - } else { - ot = MO_16; - } + /* + * In 32-bit mode, the higher 16 bits of the destination + * register are undefined. In practice CR0[31:0] is stored + * just like in 64-bit mode. + */ + mod = (modrm >> 6) & 3; + ot = (mod != 3 ? MO_16 : s->dflag); gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1); break; case 0xee: /* rdpkru */ @@ -8039,7 +8037,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) gen_helper_read_crN(s->T0, cpu_env, tcg_const_i32(reg)); gen_op_mov_reg_v(s, ot, rm, s->T0); if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { - gen_io_end(); + gen_jmp(s, s->pc - s->cs_base); } } break; @@ -8157,6 +8155,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); break; } + gen_helper_update_mxcsr(cpu_env); gen_lea_modrm(env, s, modrm); tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, mxcsr)); gen_op_st_v(s, MO_32, s->T0, s->A0); diff --git a/target/i386/whp-dispatch.h b/target/i386/whp-dispatch.h index e4695c349f18aab54fa979d345df2c1a16ff206f..b18aba20ed93f0ade28436ecbb809dd1e52811e7 100644 --- a/target/i386/whp-dispatch.h +++ b/target/i386/whp-dispatch.h @@ -2,10 +2,11 @@ #define WHP_DISPATCH_H #include - #include #include +#define WHV_E_UNKNOWN_CAPABILITY 0x80370300L + #define LIST_WINHVPLATFORM_FUNCTIONS(X) \ X(HRESULT, WHvGetCapability, (WHV_CAPABILITY_CODE CapabilityCode, VOID* CapabilityBuffer, UINT32 CapabilityBufferSizeInBytes, UINT32* WrittenSizeInBytes)) \ X(HRESULT, WHvCreatePartition, (WHV_PARTITION_HANDLE* Partition)) \ diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c index c78baac6df75c665ece962cea5c6ba4be83ef9aa..f4f3e33eac39c3dfeb6885bee163769ed914c1ff 100644 --- a/target/i386/whpx-all.c +++ b/target/i386/whpx-all.c @@ -24,9 +24,13 @@ #include "migration/blocker.h" #include "whp-dispatch.h" +#include "whpx-cpus.h" + #include #include +#define HYPERV_APIC_BUS_FREQUENCY (200000000ULL) + struct whpx_state { uint64_t mem_quota; WHV_PARTITION_HANDLE partition; @@ -946,7 +950,7 @@ static int whpx_vcpu_run(CPUState *cpu) whpx_vcpu_process_async_events(cpu); if (cpu->halted) { cpu->exception_index = EXCP_HLT; - atomic_set(&cpu->exit_request, false); + qatomic_set(&cpu->exit_request, false); return 0; } @@ -961,7 +965,7 @@ static int whpx_vcpu_run(CPUState *cpu) whpx_vcpu_pre_run(cpu); - if (atomic_read(&cpu->exit_request)) { + if (qatomic_read(&cpu->exit_request)) { whpx_vcpu_kick(cpu); } @@ -1061,6 +1065,18 @@ static int whpx_vcpu_run(CPUState *cpu) cpu_x86_cpuid(env, cpuid_fn, 0, (UINT32 *)&rax, (UINT32 *)&rbx, (UINT32 *)&rcx, (UINT32 *)&rdx); switch (cpuid_fn) { + case 0x40000000: + /* Expose the vmware cpu frequency cpuid leaf */ + rax = 0x40000010; + rbx = rcx = rdx = 0; + break; + + case 0x40000010: + rax = env->tsc_khz; + rbx = env->apic_bus_freq / 1000; /* Hz to KHz */ + rcx = rdx = 0; + break; + case 0x80000001: /* Remove any support of OSVW */ rcx &= ~CPUID_EXT3_OSVW; @@ -1113,7 +1129,7 @@ static int whpx_vcpu_run(CPUState *cpu) qemu_mutex_lock_iothread(); current_cpu = cpu; - atomic_set(&cpu->exit_request, false); + qatomic_set(&cpu->exit_request, false); return ret < 0; } @@ -1191,8 +1207,12 @@ int whpx_init_vcpu(CPUState *cpu) { HRESULT hr; struct whpx_state *whpx = &whpx_global; - struct whpx_vcpu *vcpu; + struct whpx_vcpu *vcpu = NULL; Error *local_error = NULL; + struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr); + X86CPU *x86_cpu = X86_CPU(cpu); + UINT64 freq = 0; + int ret; /* Add migration blockers for all unsupported features of the * Windows Hypervisor Platform @@ -1207,7 +1227,8 @@ int whpx_init_vcpu(CPUState *cpu) error_report_err(local_error); migrate_del_blocker(whpx_migration_blocker); error_free(whpx_migration_blocker); - return -EINVAL; + ret = -EINVAL; + goto error; } } @@ -1215,7 +1236,8 @@ int whpx_init_vcpu(CPUState *cpu) if (!vcpu) { error_report("WHPX: Failed to allocte VCPU context."); - return -ENOMEM; + ret = -ENOMEM; + goto error; } hr = whp_dispatch.WHvEmulatorCreateEmulator( @@ -1224,8 +1246,8 @@ int whpx_init_vcpu(CPUState *cpu) if (FAILED(hr)) { error_report("WHPX: Failed to setup instruction completion support," " hr=%08lx", hr); - g_free(vcpu); - return -EINVAL; + ret = -EINVAL; + goto error; } hr = whp_dispatch.WHvCreateVirtualProcessor( @@ -1234,17 +1256,72 @@ int whpx_init_vcpu(CPUState *cpu) error_report("WHPX: Failed to create a virtual processor," " hr=%08lx", hr); whp_dispatch.WHvEmulatorDestroyEmulator(vcpu->emulator); - g_free(vcpu); - return -EINVAL; + ret = -EINVAL; + goto error; } - vcpu->interruptable = true; + /* + * vcpu's TSC frequency is either specified by user, or use the value + * provided by Hyper-V if the former is not present. In the latter case, we + * query it from Hyper-V and record in env->tsc_khz, so that vcpu's TSC + * frequency can be migrated later via this field. + */ + if (!env->tsc_khz) { + hr = whp_dispatch.WHvGetCapability( + WHvCapabilityCodeProcessorClockFrequency, &freq, sizeof(freq), + NULL); + if (hr != WHV_E_UNKNOWN_CAPABILITY) { + if (FAILED(hr)) { + printf("WHPX: Failed to query tsc frequency, hr=0x%08lx\n", hr); + } else { + env->tsc_khz = freq / 1000; /* Hz to KHz */ + } + } + } + env->apic_bus_freq = HYPERV_APIC_BUS_FREQUENCY; + hr = whp_dispatch.WHvGetCapability( + WHvCapabilityCodeInterruptClockFrequency, &freq, sizeof(freq), NULL); + if (hr != WHV_E_UNKNOWN_CAPABILITY) { + if (FAILED(hr)) { + printf("WHPX: Failed to query apic bus frequency hr=0x%08lx\n", hr); + } else { + env->apic_bus_freq = freq; + } + } + + /* + * If the vmware cpuid frequency leaf option is set, and we have a valid + * tsc value, trap the corresponding cpuid's. + */ + if (x86_cpu->vmware_cpuid_freq && env->tsc_khz) { + UINT32 cpuidExitList[] = {1, 0x80000001, 0x40000000, 0x40000010}; + + hr = whp_dispatch.WHvSetPartitionProperty( + whpx->partition, + WHvPartitionPropertyCodeCpuidExitList, + cpuidExitList, + RTL_NUMBER_OF(cpuidExitList) * sizeof(UINT32)); + + if (FAILED(hr)) { + error_report("WHPX: Failed to set partition CpuidExitList hr=%08lx", + hr); + ret = -EINVAL; + goto error; + } + } + + vcpu->interruptable = true; cpu->vcpu_dirty = true; cpu->hax_vcpu = (struct hax_vcpu_state *)vcpu; qemu_add_vm_change_state_handler(whpx_cpu_update_state, cpu->env_ptr); return 0; + +error: + g_free(vcpu); + + return ret; } int whpx_vcpu_exec(CPUState *cpu) @@ -1411,15 +1488,6 @@ static void whpx_memory_init(void) memory_listener_register(&whpx_memory_listener, &address_space_memory); } -static void whpx_handle_interrupt(CPUState *cpu, int mask) -{ - cpu->interrupt_request |= mask; - - if (!qemu_cpu_is_self(cpu)) { - qemu_cpu_kick(cpu); - } -} - /* * Load the functions from the given library, using the given handle. If a * handle is provided, it is used, otherwise the library is opened. The @@ -1493,6 +1561,7 @@ static int whpx_accel_init(MachineState *ms) WHV_CAPABILITY whpx_cap; UINT32 whpx_cap_size; WHV_PARTITION_PROPERTY prop; + UINT32 cpuidExitList[] = {1, 0x80000001}; whpx = &whpx_global; @@ -1551,7 +1620,6 @@ static int whpx_accel_init(MachineState *ms) goto error; } - UINT32 cpuidExitList[] = {1, 0x80000001}; hr = whp_dispatch.WHvSetPartitionProperty( whpx->partition, WHvPartitionPropertyCodeCpuidExitList, @@ -1574,19 +1642,18 @@ static int whpx_accel_init(MachineState *ms) whpx_memory_init(); - cpu_interrupt_handler = whpx_handle_interrupt; + cpus_register_accel(&whpx_cpus); printf("Windows Hypervisor Platform accelerator is operational\n"); return 0; - error: +error: if (NULL != whpx->partition) { whp_dispatch.WHvDeletePartition(whpx->partition); whpx->partition = NULL; } - return ret; } diff --git a/target/i386/whpx-cpus.c b/target/i386/whpx-cpus.c new file mode 100644 index 0000000000000000000000000000000000000000..d9bd5a2d36066eeef419354a3440cfc178746ea2 --- /dev/null +++ b/target/i386/whpx-cpus.c @@ -0,0 +1,96 @@ +/* + * QEMU Windows Hypervisor Platform accelerator (WHPX) + * + * Copyright Microsoft Corp. 2017 + * + * 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 "sysemu/kvm_int.h" +#include "qemu/main-loop.h" +#include "sysemu/cpus.h" +#include "qemu/guest-random.h" + +#include "sysemu/whpx.h" +#include "whpx-cpus.h" + +#include +#include + +static void *whpx_cpu_thread_fn(void *arg) +{ + CPUState *cpu = arg; + int r; + + rcu_register_thread(); + + qemu_mutex_lock_iothread(); + qemu_thread_get_self(cpu->thread); + cpu->thread_id = qemu_get_thread_id(); + current_cpu = cpu; + + r = whpx_init_vcpu(cpu); + if (r < 0) { + fprintf(stderr, "whpx_init_vcpu failed: %s\n", strerror(-r)); + exit(1); + } + + /* signal CPU creation */ + cpu_thread_signal_created(cpu); + qemu_guest_random_seed_thread_part2(cpu->random_seed); + + do { + if (cpu_can_run(cpu)) { + r = whpx_vcpu_exec(cpu); + if (r == EXCP_DEBUG) { + cpu_handle_guest_debug(cpu); + } + } + while (cpu_thread_is_idle(cpu)) { + qemu_cond_wait_iothread(cpu->halt_cond); + } + qemu_wait_io_event_common(cpu); + } while (!cpu->unplug || cpu_can_run(cpu)); + + whpx_destroy_vcpu(cpu); + cpu_thread_signal_destroyed(cpu); + qemu_mutex_unlock_iothread(); + rcu_unregister_thread(); + return NULL; +} + +static void whpx_start_vcpu_thread(CPUState *cpu) +{ + char thread_name[VCPU_THREAD_NAME_SIZE]; + + cpu->thread = g_malloc0(sizeof(QemuThread)); + cpu->halt_cond = g_malloc0(sizeof(QemuCond)); + qemu_cond_init(cpu->halt_cond); + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/WHPX", + cpu->cpu_index); + qemu_thread_create(cpu->thread, thread_name, whpx_cpu_thread_fn, + cpu, QEMU_THREAD_JOINABLE); +#ifdef _WIN32 + cpu->hThread = qemu_thread_get_handle(cpu->thread); +#endif +} + +static void whpx_kick_vcpu_thread(CPUState *cpu) +{ + if (!qemu_cpu_is_self(cpu)) { + whpx_vcpu_kick(cpu); + } +} + +const CpusAccel whpx_cpus = { + .create_vcpu_thread = whpx_start_vcpu_thread, + .kick_vcpu_thread = whpx_kick_vcpu_thread, + + .synchronize_post_reset = whpx_cpu_synchronize_post_reset, + .synchronize_post_init = whpx_cpu_synchronize_post_init, + .synchronize_state = whpx_cpu_synchronize_state, + .synchronize_pre_loadvm = whpx_cpu_synchronize_pre_loadvm, +}; diff --git a/target/i386/whpx-cpus.h b/target/i386/whpx-cpus.h new file mode 100644 index 0000000000000000000000000000000000000000..bdb367d1d0b1144e13155899309b961a101abb51 --- /dev/null +++ b/target/i386/whpx-cpus.h @@ -0,0 +1,34 @@ +/* + * Accelerator CPUS Interface + * + * Copyright 2020 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef WHPX_CPUS_H +#define WHPX_CPUS_H + +#include "sysemu/cpus.h" + +extern const CpusAccel whpx_cpus; + +int whpx_init_vcpu(CPUState *cpu); +int whpx_vcpu_exec(CPUState *cpu); +void whpx_destroy_vcpu(CPUState *cpu); +void whpx_vcpu_kick(CPUState *cpu); + +void whpx_cpu_synchronize_state(CPUState *cpu); +void whpx_cpu_synchronize_post_reset(CPUState *cpu); +void whpx_cpu_synchronize_post_init(CPUState *cpu); +void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu); + +/* state subset only touched by the VCPU itself during runtime */ +#define WHPX_SET_RUNTIME_STATE 1 +/* state subset modified during VCPU reset */ +#define WHPX_SET_RESET_STATE 2 +/* full state set, modified during initialization or on vmload */ +#define WHPX_SET_FULL_STATE 3 + +#endif /* WHPX_CPUS_H */ diff --git a/target/lm32/Makefile.objs b/target/lm32/Makefile.objs deleted file mode 100644 index c3e1bd6bd61aa1b1453a788e5ddc0057a2707358..0000000000000000000000000000000000000000 --- a/target/lm32/Makefile.objs +++ /dev/null @@ -1,4 +0,0 @@ -obj-y += translate.o op_helper.o helper.o cpu.o -obj-y += gdbstub.o -obj-y += lm32-semi.o -obj-$(CONFIG_SOFTMMU) += machine.o diff --git a/target/lm32/cpu-qom.h b/target/lm32/cpu-qom.h index bdedb3759acfcc9515366f52a4483f4575dadb93..245b35cd1d9f45817f363814507b7aacc67d9ded 100644 --- a/target/lm32/cpu-qom.h +++ b/target/lm32/cpu-qom.h @@ -21,15 +21,12 @@ #define QEMU_LM32_CPU_QOM_H #include "hw/core/cpu.h" +#include "qom/object.h" #define TYPE_LM32_CPU "lm32-cpu" -#define LM32_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(LM32CPUClass, (klass), TYPE_LM32_CPU) -#define LM32_CPU(obj) \ - OBJECT_CHECK(LM32CPU, (obj), TYPE_LM32_CPU) -#define LM32_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(LM32CPUClass, (obj), TYPE_LM32_CPU) +OBJECT_DECLARE_TYPE(LM32CPU, LM32CPUClass, + LM32_CPU) /** * LM32CPUClass: @@ -38,15 +35,14 @@ * * A LatticeMico32 CPU model. */ -typedef struct LM32CPUClass { +struct LM32CPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ DeviceRealize parent_realize; DeviceReset parent_reset; -} LM32CPUClass; +}; -typedef struct LM32CPU LM32CPU; #endif diff --git a/target/lm32/cpu.h b/target/lm32/cpu.h index 01d408eb55d32aa0d89cf34246d9128e8c2ad7e8..ea7c01ca8b0bf609667a928c4e58457a003e3a60 100644 --- a/target/lm32/cpu.h +++ b/target/lm32/cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/lm32/gdbstub.c b/target/lm32/gdbstub.c index b6fe12e1d612f170a11f024e6ca762840e67727e..56f508a5b697390225765a439367b1f4ff7d4dcb 100644 --- a/target/lm32/gdbstub.c +++ b/target/lm32/gdbstub.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/lm32/helper.c b/target/lm32/helper.c index 1130fc88846131c17e44bbbaac4a35182873a900..7c52ae76d6dcceae1b84cd0a847a68df00c9f1c8 100644 --- a/target/lm32/helper.c +++ b/target/lm32/helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/lm32/meson.build b/target/lm32/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..ef0eef07f12bea597bdfcd9af68829c8c9a19689 --- /dev/null +++ b/target/lm32/meson.build @@ -0,0 +1,15 @@ +lm32_ss = ss.source_set() +lm32_ss.add(files( + 'cpu.c', + 'gdbstub.c', + 'helper.c', + 'lm32-semi.c', + 'op_helper.c', + 'translate.c', +)) + +lm32_softmmu_ss = ss.source_set() +lm32_softmmu_ss.add(files('machine.c')) + +target_arch += {'lm32': lm32_ss} +target_softmmu_arch += {'lm32': lm32_softmmu_ss} diff --git a/target/lm32/translate.c b/target/lm32/translate.c index e583d52d034a2ebccf1da9b233e5b6f049de08f5..030b232d6603732db39c4f6b06035ee90cc47616 100644 --- a/target/lm32/translate.c +++ b/target/lm32/translate.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/m68k/Makefile.objs b/target/m68k/Makefile.objs deleted file mode 100644 index ac619486765e59987aefcd2d691e4a6613c55e90..0000000000000000000000000000000000000000 --- a/target/m68k/Makefile.objs +++ /dev/null @@ -1,5 +0,0 @@ -obj-y += m68k-semi.o -obj-y += translate.o op_helper.o helper.o cpu.o -obj-y += fpu_helper.o softfloat.o -obj-y += gdbstub.o -obj-$(CONFIG_SOFTMMU) += monitor.o diff --git a/target/m68k/cpu-qom.h b/target/m68k/cpu-qom.h index 88b11b60f1318ec4e3036c05d50ea93ef0d39cee..1ceb160ecb0270cb9898c0a8e87181d4a265cf8c 100644 --- a/target/m68k/cpu-qom.h +++ b/target/m68k/cpu-qom.h @@ -21,15 +21,12 @@ #define QEMU_M68K_CPU_QOM_H #include "hw/core/cpu.h" +#include "qom/object.h" #define TYPE_M68K_CPU "m68k-cpu" -#define M68K_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(M68kCPUClass, (klass), TYPE_M68K_CPU) -#define M68K_CPU(obj) \ - OBJECT_CHECK(M68kCPU, (obj), TYPE_M68K_CPU) -#define M68K_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(M68kCPUClass, (obj), TYPE_M68K_CPU) +OBJECT_DECLARE_TYPE(M68kCPU, M68kCPUClass, + M68K_CPU) /* * M68kCPUClass: @@ -38,15 +35,14 @@ * * A Motorola 68k CPU model. */ -typedef struct M68kCPUClass { +struct M68kCPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ DeviceRealize parent_realize; DeviceReset parent_reset; -} M68kCPUClass; +}; -typedef struct M68kCPU M68kCPU; #endif diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c index 36e6c704d1d044d39bcdac68e23c3a3e3d029242..9acf60dfd443ee4dfa69ba6fa2ddef0e0042087e 100644 --- a/target/m68k/fpu_helper.c +++ b/target/m68k/fpu_helper.c @@ -641,6 +641,11 @@ void HELPER(fatanh)(CPUM68KState *env, FPReg *res, FPReg *val) res->d = floatx80_atanh(val->d, &env->fp_status); } +void HELPER(fetoxm1)(CPUM68KState *env, FPReg *res, FPReg *val) +{ + res->d = floatx80_etoxm1(val->d, &env->fp_status); +} + void HELPER(ftanh)(CPUM68KState *env, FPReg *res, FPReg *val) { res->d = floatx80_tanh(val->d, &env->fp_status); diff --git a/target/m68k/helper.c b/target/m68k/helper.c index 79b0b10ea9bcef121418f37347af29ef5d418b78..3ff57657958ca0b1c83f2d33be8dbbe9f43902a4 100644 --- a/target/m68k/helper.c +++ b/target/m68k/helper.c @@ -643,7 +643,7 @@ static int get_physical_address(CPUM68KState *env, hwaddr *physical, /* Transparent Translation Register bit */ env->mmu.mmusr = M68K_MMU_T_040 | M68K_MMU_R_040; } - *physical = address & TARGET_PAGE_MASK; + *physical = address; *page_size = TARGET_PAGE_SIZE; return 0; } @@ -771,7 +771,7 @@ static int get_physical_address(CPUM68KState *env, hwaddr *physical, } *page_size = 1 << page_bits; page_mask = ~(*page_size - 1); - *physical = next & page_mask; + *physical = (next & page_mask) + (address & (*page_size - 1)); if (access_type & ACCESS_PTEST) { env->mmu.mmusr |= next & M68K_MMU_SR_MASK_040; @@ -820,10 +820,12 @@ hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) if (env->sr & SR_S) { access_type |= ACCESS_SUPER; } + if (get_physical_address(env, &phys_addr, &prot, addr, access_type, &page_size) != 0) { return -1; } + return phys_addr; } @@ -887,10 +889,8 @@ bool m68k_cpu_tlb_fill(CPUState *cs, vaddr address, int size, ret = get_physical_address(&cpu->env, &physical, &prot, address, access_type, &page_size); if (likely(ret == 0)) { - address &= TARGET_PAGE_MASK; - physical += address & (page_size - 1); - tlb_set_page(cs, address, physical, - prot, mmu_idx, TARGET_PAGE_SIZE); + tlb_set_page(cs, address & TARGET_PAGE_MASK, + physical & TARGET_PAGE_MASK, prot, mmu_idx, page_size); return true; } @@ -1379,9 +1379,8 @@ void HELPER(ptest)(CPUM68KState *env, uint32_t addr, uint32_t is_read) ret = get_physical_address(env, &physical, &prot, addr, access_type, &page_size); if (ret == 0) { - addr &= TARGET_PAGE_MASK; - physical += addr & (page_size - 1); - tlb_set_page(env_cpu(env), addr, physical, + tlb_set_page(env_cpu(env), addr & TARGET_PAGE_MASK, + physical & TARGET_PAGE_MASK, prot, access_type & ACCESS_SUPER ? MMU_KERNEL_IDX : MMU_USER_IDX, page_size); } diff --git a/target/m68k/helper.h b/target/m68k/helper.h index feee7be626552ecffb8175bc96a8c379a4480884..77808497a95cd18a6ee771fe01b31065efce84ac 100644 --- a/target/m68k/helper.h +++ b/target/m68k/helper.h @@ -83,6 +83,7 @@ DEF_HELPER_3(fatan, void, env, fp, fp) DEF_HELPER_3(fasin, void, env, fp, fp) DEF_HELPER_3(facos, void, env, fp, fp) DEF_HELPER_3(fatanh, void, env, fp, fp) +DEF_HELPER_3(fetoxm1, void, env, fp, fp) DEF_HELPER_3(ftanh, void, env, fp, fp) DEF_HELPER_3(fsinh, void, env, fp, fp) DEF_HELPER_3(fcosh, void, env, fp, fp) diff --git a/target/m68k/meson.build b/target/m68k/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..05cd9fbd1e8d24f668eba2139cae27dc82d8a312 --- /dev/null +++ b/target/m68k/meson.build @@ -0,0 +1,17 @@ +m68k_ss = ss.source_set() +m68k_ss.add(files( + 'cpu.c', + 'fpu_helper.c', + 'gdbstub.c', + 'helper.c', + 'm68k-semi.c', + 'op_helper.c', + 'softfloat.c', + 'translate.c', +)) + +m68k_softmmu_ss = ss.source_set() +m68k_softmmu_ss.add(files('monitor.c')) + +target_arch += {'m68k': m68k_ss} +target_softmmu_arch += {'m68k': m68k_softmmu_ss} diff --git a/target/m68k/monitor.c b/target/m68k/monitor.c index 2055fe8a000840571ea7faf455999805fba04873..2bdf6acae0af74a5aa892d19963e339fc7c455e5 100644 --- a/target/m68k/monitor.c +++ b/target/m68k/monitor.c @@ -12,7 +12,7 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict) { - CPUArchState *env1 = mon_get_cpu_env(); + CPUArchState *env1 = mon_get_cpu_env(mon); if (!env1) { monitor_printf(mon, "No CPU available\n"); diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c index 9f120cf15e07981661fcb0d4d97a0329e25b55e0..b6d0ed7acfe8dd122e052d2ea9348e9ef0f750fe 100644 --- a/target/m68k/softfloat.c +++ b/target/m68k/softfloat.c @@ -42,89 +42,6 @@ static floatx80 propagateFloatx80NaNOneArg(floatx80 a, float_status *status) return a; } -/* - * Returns the modulo remainder of the extended double-precision floating-point - * value `a' with respect to the corresponding value `b'. - */ - -floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status) -{ - bool aSign, zSign; - int32_t aExp, bExp, expDiff; - uint64_t aSig0, aSig1, bSig; - uint64_t qTemp, term0, term1; - - aSig0 = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - - if (aExp == 0x7FFF) { - if ((uint64_t) (aSig0 << 1) - || ((bExp == 0x7FFF) && (uint64_t) (bSig << 1))) { - return propagateFloatx80NaN(a, b, status); - } - goto invalid; - } - if (bExp == 0x7FFF) { - if ((uint64_t) (bSig << 1)) { - return propagateFloatx80NaN(a, b, status); - } - return a; - } - if (bExp == 0) { - if (bSig == 0) { - invalid: - float_raise(float_flag_invalid, status); - return floatx80_default_nan(status); - } - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0) { - if ((uint64_t) (aSig0 << 1) == 0) { - return a; - } - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); - } - bSig |= UINT64_C(0x8000000000000000); - zSign = aSign; - expDiff = aExp - bExp; - aSig1 = 0; - if (expDiff < 0) { - return a; - } - qTemp = (bSig <= aSig0); - if (qTemp) { - aSig0 -= bSig; - } - expDiff -= 64; - while (0 < expDiff) { - qTemp = estimateDiv128To64(aSig0, aSig1, bSig); - qTemp = (2 < qTemp) ? qTemp - 2 : 0; - mul64To128(bSig, qTemp, &term0, &term1); - sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1); - shortShift128Left(aSig0, aSig1, 62, &aSig0, &aSig1); - expDiff -= 62; - } - expDiff += 64; - if (0 < expDiff) { - qTemp = estimateDiv128To64(aSig0, aSig1, bSig); - qTemp = (2 < qTemp) ? qTemp - 2 : 0; - qTemp >>= 64 - expDiff; - mul64To128(bSig, qTemp << (64 - expDiff), &term0, &term1); - sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1); - shortShift128Left(0, bSig, 64 - expDiff, &term0, &term1); - while (le128(term0, term1, aSig0, aSig1)) { - ++qTemp; - sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1); - } - } - return - normalizeRoundAndPackFloatx80( - 80, zSign, bExp + expDiff, aSig0, aSig1, status); -} - /* * Returns the mantissa of the extended double-precision floating-point * value `a'. diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h index 365ef6ac7ad299253e8618fbb9ccb58da9e53b6b..4bb95671345219164d99d3d01df5b0c7b8fdd94c 100644 --- a/target/m68k/softfloat.h +++ b/target/m68k/softfloat.h @@ -23,7 +23,6 @@ #define TARGET_M68K_SOFTFLOAT_H #include "fpu/softfloat.h" -floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status); floatx80 floatx80_getman(floatx80 a, float_status *status); floatx80 floatx80_getexp(floatx80 a, float_status *status); floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status); diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 0f80888203d3d480b3f53b7cc05f57dda945c6f5..3fc67aa45261c70b04b735f31c24edb4bffb7bd7 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -4936,6 +4936,20 @@ static void gen_op_fmove_fcr(CPUM68KState *env, DisasContext *s, gen_store_fcr(s, AREG(insn, 0), mask); } return; + case 7: /* Immediate */ + if (REG(insn, 0) == 4) { + if (is_write || + (mask != M68K_FPIAR && mask != M68K_FPSR && + mask != M68K_FPCR)) { + gen_exception(s, s->base.pc_next, EXCP_ILLEGAL); + return; + } + tmp = tcg_const_i32(read_im32(env, s)); + gen_store_fcr(s, tmp, mask); + tcg_temp_free(tmp); + return; + } + break; default: break; } @@ -5146,6 +5160,9 @@ DISAS_INSN(fpu) case 0x06: /* flognp1 */ gen_helper_flognp1(cpu_env, cpu_dest, cpu_src); break; + case 0x08: /* fetoxm1 */ + gen_helper_fetoxm1(cpu_env, cpu_dest, cpu_src); + break; case 0x09: /* ftanh */ gen_helper_ftanh(cpu_env, cpu_dest, cpu_src); break; diff --git a/target/meson.build b/target/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..9f0ae93b75ef815efabce237f581089c709271b4 --- /dev/null +++ b/target/meson.build @@ -0,0 +1,23 @@ +subdir('alpha') +subdir('arm') +subdir('avr') +subdir('cris') +subdir('hppa') +subdir('i386') +subdir('lm32') +subdir('m68k') +subdir('microblaze') +subdir('mips') +subdir('moxie') +subdir('nios2') +subdir('openrisc') +subdir('ppc') +subdir('riscv') +subdir('rx') +subdir('s390x') +subdir('sh4') +subdir('sparc') +subdir('tilegx') +subdir('tricore') +subdir('unicore32') +subdir('xtensa') diff --git a/target/microblaze/Makefile.objs b/target/microblaze/Makefile.objs deleted file mode 100644 index f3d7b44c890e5c27fb0b7078af936ec515a988f5..0000000000000000000000000000000000000000 --- a/target/microblaze/Makefile.objs +++ /dev/null @@ -1,3 +0,0 @@ -obj-y += translate.o op_helper.o helper.o cpu.o -obj-y += gdbstub.o -obj-$(CONFIG_SOFTMMU) += mmu.o diff --git a/target/microblaze/cpu-param.h b/target/microblaze/cpu-param.h index 4abbc62d50963c2d0b4fe6a706aa10d6eee5d38c..4d8297fa94075be944637debb0f0f87fa71366b7 100644 --- a/target/microblaze/cpu-param.h +++ b/target/microblaze/cpu-param.h @@ -8,9 +8,24 @@ #ifndef MICROBLAZE_CPU_PARAM_H #define MICROBLAZE_CPU_PARAM_H 1 +/* + * While system mode can address up to 64 bits of address space, + * this is done via the lea/sea instructions, which are system-only + * (as they also bypass the mmu). + * + * We can improve the user-only experience by only exposing 32 bits + * of address space. + */ +#ifdef CONFIG_USER_ONLY +#define TARGET_LONG_BITS 32 +#define TARGET_PHYS_ADDR_SPACE_BITS 32 +#define TARGET_VIRT_ADDR_SPACE_BITS 32 +#else #define TARGET_LONG_BITS 64 #define TARGET_PHYS_ADDR_SPACE_BITS 64 #define TARGET_VIRT_ADDR_SPACE_BITS 64 +#endif + /* FIXME: MB uses variable pages down to 1K but linux only uses 4k. */ #define TARGET_PAGE_BITS 12 #define NB_MMU_MODES 3 diff --git a/target/microblaze/cpu-qom.h b/target/microblaze/cpu-qom.h index 053ba44ee8c3f77a72231062e89237bb67a7dd95..e520eefb127e871ffa934ddd1f78e2198fa2d3af 100644 --- a/target/microblaze/cpu-qom.h +++ b/target/microblaze/cpu-qom.h @@ -21,15 +21,12 @@ #define QEMU_MICROBLAZE_CPU_QOM_H #include "hw/core/cpu.h" +#include "qom/object.h" #define TYPE_MICROBLAZE_CPU "microblaze-cpu" -#define MICROBLAZE_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(MicroBlazeCPUClass, (klass), TYPE_MICROBLAZE_CPU) -#define MICROBLAZE_CPU(obj) \ - OBJECT_CHECK(MicroBlazeCPU, (obj), TYPE_MICROBLAZE_CPU) -#define MICROBLAZE_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(MicroBlazeCPUClass, (obj), TYPE_MICROBLAZE_CPU) +OBJECT_DECLARE_TYPE(MicroBlazeCPU, MicroBlazeCPUClass, + MICROBLAZE_CPU) /** * MicroBlazeCPUClass: @@ -38,15 +35,14 @@ * * A MicroBlaze CPU model. */ -typedef struct MicroBlazeCPUClass { +struct MicroBlazeCPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ DeviceRealize parent_realize; DeviceReset parent_reset; -} MicroBlazeCPUClass; +}; -typedef struct MicroBlazeCPU MicroBlazeCPU; #endif diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c index 51e5c85b100138fee59961cd1b98366ab2b108b0..9b2482159d18ed714999664fc32aa7b722611704 100644 --- a/target/microblaze/cpu.c +++ b/target/microblaze/cpu.c @@ -26,7 +26,6 @@ #include "cpu.h" #include "qemu/module.h" #include "hw/qdev-properties.h" -#include "migration/vmstate.h" #include "exec/exec-all.h" #include "fpu/softfloat-helpers.h" @@ -79,7 +78,17 @@ static void mb_cpu_set_pc(CPUState *cs, vaddr value) { MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); - cpu->env.sregs[SR_PC] = value; + cpu->env.pc = value; + /* Ensure D_FLAG and IMM_FLAG are clear for the new PC */ + cpu->env.iflags = 0; +} + +static void mb_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) +{ + MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); + + cpu->env.pc = tb->pc; + cpu->env.iflags = tb->flags & IFLAGS_TB_MASK; } static bool mb_cpu_has_work(CPUState *cs) @@ -117,18 +126,14 @@ static void mb_cpu_reset(DeviceState *dev) /* Disable stack protector. */ env->shr = ~0; - env->sregs[SR_PC] = cpu->cfg.base_vectors; + env->pc = cpu->cfg.base_vectors; #if defined(CONFIG_USER_ONLY) /* start in user mode with interrupts enabled. */ - env->sregs[SR_MSR] = MSR_EE | MSR_IE | MSR_VM | MSR_UM; + mb_cpu_write_msr(env, MSR_EE | MSR_IE | MSR_VM | MSR_UM); #else - env->sregs[SR_MSR] = 0; + mb_cpu_write_msr(env, 0); mmu_init(&env->mmu); - env->mmu.c_mmu = 3; - env->mmu.c_mmu_tlb_access = 3; - env->mmu.c_mmu_zones = 16; - env->mmu.c_addr_mask = MAKE_64BIT_MASK(0, cpu->cfg.addr_size); #endif } @@ -143,7 +148,6 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp) CPUState *cs = CPU(dev); MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_GET_CLASS(dev); MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); - CPUMBState *env = &cpu->env; uint8_t version_code = 0; const char *version; int i = 0; @@ -163,16 +167,6 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp) qemu_init_vcpu(cs); - env->pvr.regs[0] = PVR0_USE_EXC_MASK - | PVR0_USE_ICACHE_MASK - | PVR0_USE_DCACHE_MASK; - env->pvr.regs[2] = PVR2_D_OPB_MASK - | PVR2_D_LMB_MASK - | PVR2_I_OPB_MASK - | PVR2_I_LMB_MASK - | PVR2_FPU_EXC_MASK - | 0; - version = cpu->cfg.version ? cpu->cfg.version : DEFAULT_CPU_VERSION; for (i = 0; mb_cpu_lookup[i].name && version; i++) { if (strcmp(mb_cpu_lookup[i].name, version) == 0) { @@ -185,46 +179,58 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp) qemu_log("Invalid MicroBlaze version number: %s\n", cpu->cfg.version); } - env->pvr.regs[0] |= (cpu->cfg.stackprot ? PVR0_SPROT_MASK : 0) | - (cpu->cfg.use_fpu ? PVR0_USE_FPU_MASK : 0) | - (cpu->cfg.use_hw_mul ? PVR0_USE_HW_MUL_MASK : 0) | - (cpu->cfg.use_barrel ? PVR0_USE_BARREL_MASK : 0) | - (cpu->cfg.use_div ? PVR0_USE_DIV_MASK : 0) | - (cpu->cfg.use_mmu ? PVR0_USE_MMU_MASK : 0) | - (cpu->cfg.endi ? PVR0_ENDI_MASK : 0) | - (version_code << PVR0_VERSION_SHIFT) | - (cpu->cfg.pvr == C_PVR_FULL ? PVR0_PVR_FULL_MASK : 0) | - cpu->cfg.pvr_user1; - - env->pvr.regs[1] = cpu->cfg.pvr_user2; - env->pvr.regs[2] |= (cpu->cfg.use_fpu ? PVR2_USE_FPU_MASK : 0) | - (cpu->cfg.use_fpu > 1 ? PVR2_USE_FPU2_MASK : 0) | - (cpu->cfg.use_hw_mul ? PVR2_USE_HW_MUL_MASK : 0) | - (cpu->cfg.use_hw_mul > 1 ? PVR2_USE_MUL64_MASK : 0) | - (cpu->cfg.use_barrel ? PVR2_USE_BARREL_MASK : 0) | - (cpu->cfg.use_div ? PVR2_USE_DIV_MASK : 0) | - (cpu->cfg.use_msr_instr ? PVR2_USE_MSR_INSTR : 0) | - (cpu->cfg.use_pcmp_instr ? PVR2_USE_PCMP_INSTR : 0) | - (cpu->cfg.dopb_bus_exception ? - PVR2_DOPB_BUS_EXC_MASK : 0) | - (cpu->cfg.iopb_bus_exception ? - PVR2_IOPB_BUS_EXC_MASK : 0) | - (cpu->cfg.div_zero_exception ? - PVR2_DIV_ZERO_EXC_MASK : 0) | - (cpu->cfg.illegal_opcode_exception ? - PVR2_ILL_OPCODE_EXC_MASK : 0) | - (cpu->cfg.unaligned_exceptions ? - PVR2_UNALIGNED_EXC_MASK : 0) | - (cpu->cfg.opcode_0_illegal ? - PVR2_OPCODE_0x0_ILL_MASK : 0); - - env->pvr.regs[5] |= cpu->cfg.dcache_writeback ? - PVR5_DCACHE_WRITEBACK_MASK : 0; - - env->pvr.regs[10] = 0x0c000000 | /* Default to spartan 3a dsp family. */ - (cpu->cfg.addr_size - 32) << PVR10_ASIZE_SHIFT; - env->pvr.regs[11] = (cpu->cfg.use_mmu ? PVR11_USE_MMU : 0) | - 16 << 17; + cpu->cfg.pvr_regs[0] = + (PVR0_USE_EXC_MASK | + PVR0_USE_ICACHE_MASK | + PVR0_USE_DCACHE_MASK | + (cpu->cfg.stackprot ? PVR0_SPROT_MASK : 0) | + (cpu->cfg.use_fpu ? PVR0_USE_FPU_MASK : 0) | + (cpu->cfg.use_hw_mul ? PVR0_USE_HW_MUL_MASK : 0) | + (cpu->cfg.use_barrel ? PVR0_USE_BARREL_MASK : 0) | + (cpu->cfg.use_div ? PVR0_USE_DIV_MASK : 0) | + (cpu->cfg.use_mmu ? PVR0_USE_MMU_MASK : 0) | + (cpu->cfg.endi ? PVR0_ENDI_MASK : 0) | + (version_code << PVR0_VERSION_SHIFT) | + (cpu->cfg.pvr == C_PVR_FULL ? PVR0_PVR_FULL_MASK : 0) | + cpu->cfg.pvr_user1); + + cpu->cfg.pvr_regs[1] = cpu->cfg.pvr_user2; + + cpu->cfg.pvr_regs[2] = + (PVR2_D_OPB_MASK | + PVR2_D_LMB_MASK | + PVR2_I_OPB_MASK | + PVR2_I_LMB_MASK | + PVR2_FPU_EXC_MASK | + (cpu->cfg.use_fpu ? PVR2_USE_FPU_MASK : 0) | + (cpu->cfg.use_fpu > 1 ? PVR2_USE_FPU2_MASK : 0) | + (cpu->cfg.use_hw_mul ? PVR2_USE_HW_MUL_MASK : 0) | + (cpu->cfg.use_hw_mul > 1 ? PVR2_USE_MUL64_MASK : 0) | + (cpu->cfg.use_barrel ? PVR2_USE_BARREL_MASK : 0) | + (cpu->cfg.use_div ? PVR2_USE_DIV_MASK : 0) | + (cpu->cfg.use_msr_instr ? PVR2_USE_MSR_INSTR : 0) | + (cpu->cfg.use_pcmp_instr ? PVR2_USE_PCMP_INSTR : 0) | + (cpu->cfg.dopb_bus_exception ? PVR2_DOPB_BUS_EXC_MASK : 0) | + (cpu->cfg.iopb_bus_exception ? PVR2_IOPB_BUS_EXC_MASK : 0) | + (cpu->cfg.div_zero_exception ? PVR2_DIV_ZERO_EXC_MASK : 0) | + (cpu->cfg.illegal_opcode_exception ? PVR2_ILL_OPCODE_EXC_MASK : 0) | + (cpu->cfg.unaligned_exceptions ? PVR2_UNALIGNED_EXC_MASK : 0) | + (cpu->cfg.opcode_0_illegal ? PVR2_OPCODE_0x0_ILL_MASK : 0)); + + cpu->cfg.pvr_regs[5] |= + cpu->cfg.dcache_writeback ? PVR5_DCACHE_WRITEBACK_MASK : 0; + + cpu->cfg.pvr_regs[10] = + (0x0c000000 | /* Default to spartan 3a dsp family. */ + (cpu->cfg.addr_size - 32) << PVR10_ASIZE_SHIFT); + + cpu->cfg.pvr_regs[11] = ((cpu->cfg.use_mmu ? PVR11_USE_MMU : 0) | + 16 << 17); + + cpu->cfg.mmu = 3; + cpu->cfg.mmu_tlb_access = 3; + cpu->cfg.mmu_zones = 16; + cpu->cfg.addr_mask = MAKE_64BIT_MASK(0, cpu->cfg.addr_size); mcc->parent_realize(dev, errp); } @@ -244,11 +250,6 @@ static void mb_cpu_initfn(Object *obj) #endif } -static const VMStateDescription vmstate_mb_cpu = { - .name = "cpu", - .unmigratable = 1, -}; - static Property mb_properties[] = { DEFINE_PROP_UINT32("base-vectors", MicroBlazeCPU, cfg.base_vectors, 0), DEFINE_PROP_BOOL("use-stack-protection", MicroBlazeCPU, cfg.stackprot, @@ -317,17 +318,19 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = mb_cpu_class_by_name; cc->has_work = mb_cpu_has_work; cc->do_interrupt = mb_cpu_do_interrupt; + cc->do_unaligned_access = mb_cpu_do_unaligned_access; cc->cpu_exec_interrupt = mb_cpu_exec_interrupt; cc->dump_state = mb_cpu_dump_state; cc->set_pc = mb_cpu_set_pc; + cc->synchronize_from_tb = mb_cpu_synchronize_from_tb; cc->gdb_read_register = mb_cpu_gdb_read_register; cc->gdb_write_register = mb_cpu_gdb_write_register; cc->tlb_fill = mb_cpu_tlb_fill; #ifndef CONFIG_USER_ONLY cc->do_transaction_failed = mb_cpu_transaction_failed; cc->get_phys_page_debug = mb_cpu_get_phys_page_debug; -#endif dc->vmsd = &vmstate_mb_cpu; +#endif device_class_set_props(dc, mb_properties); cc->gdb_num_core_regs = 32 + 27; diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h index a31134b65cfe585fac0378006f4941cf290fb381..c1c264199fccbb2ec575dea520fdbbb05dd24a18 100644 --- a/target/microblaze/cpu.h +++ b/target/microblaze/cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,7 +31,7 @@ typedef struct CPUMBState CPUMBState; #define EXCP_MMU 1 #define EXCP_IRQ 2 -#define EXCP_BREAK 3 +#define EXCP_SYSCALL 3 /* user-only */ #define EXCP_HW_BREAK 4 #define EXCP_HW_EXCP 5 @@ -79,10 +79,13 @@ typedef struct CPUMBState CPUMBState; /* Exception State Register (ESR) Fields */ #define ESR_DIZ (1<<11) /* Zone Protection */ +#define ESR_W (1<<11) /* Unaligned word access */ #define ESR_S (1<<10) /* Store instruction */ #define ESR_ESS_FSL_OFFSET 5 +#define ESR_ESS_MASK (0x7f << 5) + #define ESR_EC_FSL 0 #define ESR_EC_UNALIGNED_DATA 1 #define ESR_EC_ILLEGAL_OP 2 @@ -228,15 +231,22 @@ typedef struct CPUMBState CPUMBState; #define STREAM_CONTROL (1 << 3) #define STREAM_NONBLOCK (1 << 4) +#define TARGET_INSN_START_EXTRA_WORDS 1 + struct CPUMBState { - uint32_t debug; - uint32_t btaken; - uint64_t btarget; - uint32_t bimm; + uint32_t bvalue; /* TCG temporary, only valid during a TB */ + uint32_t btarget; /* Full resolved branch destination */ uint32_t imm; uint32_t regs[32]; - uint64_t sregs[14]; + uint32_t pc; + uint32_t msr; /* All bits of MSR except MSR[C] and MSR[CC] */ + uint32_t msr_c; /* MSR[C], in low bit; other bits must be 0 */ + target_ulong ear; + uint32_t esr; + uint32_t fsr; + uint32_t btr; + uint32_t edr; float_status fp_status; /* Stack protectors. Yes, it's a hw feature. */ uint32_t slr, shr; @@ -247,31 +257,75 @@ struct CPUMBState { uint32_t res_val; /* Internal flags. */ -#define IMM_FLAG 4 -#define MSR_EE_FLAG (1 << 8) +#define IMM_FLAG (1 << 0) +#define BIMM_FLAG (1 << 1) +#define ESR_ESS_FLAG (1 << 2) /* indicates ESR_ESS_MASK is present */ +/* MSR_EE (1 << 8) -- these 3 are not in iflags but tb_flags */ +/* MSR_UM (1 << 11) */ +/* MSR_VM (1 << 13) */ +/* ESR_ESS_MASK [11:5] -- unwind into iflags for unaligned excp */ +#define D_FLAG (1 << 12) /* Bit in ESR. */ #define DRTI_FLAG (1 << 16) #define DRTE_FLAG (1 << 17) #define DRTB_FLAG (1 << 18) -#define D_FLAG (1 << 19) /* Bit in ESR. */ + /* TB dependent CPUMBState. */ -#define IFLAGS_TB_MASK (D_FLAG | IMM_FLAG | DRTI_FLAG | DRTE_FLAG | DRTB_FLAG) +#define IFLAGS_TB_MASK (D_FLAG | BIMM_FLAG | IMM_FLAG | \ + DRTI_FLAG | DRTE_FLAG | DRTB_FLAG) +#define MSR_TB_MASK (MSR_UM | MSR_VM | MSR_EE) + uint32_t iflags; #if !defined(CONFIG_USER_ONLY) /* Unified MMU. */ - struct microblaze_mmu mmu; + MicroBlazeMMU mmu; #endif /* Fields up to this point are cleared by a CPU reset */ struct {} end_reset_fields; /* These fields are preserved on reset. */ - - struct { - uint32_t regs[13]; - } pvr; }; +/* + * Microblaze Configuration Settings + * + * Note that the structure is sorted by type and size to minimize holes. + */ +typedef struct { + char *version; + + uint64_t addr_mask; + + uint32_t base_vectors; + uint32_t pvr_user2; + uint32_t pvr_regs[13]; + + uint8_t addr_size; + uint8_t use_fpu; + uint8_t use_hw_mul; + uint8_t pvr_user1; + uint8_t pvr; + uint8_t mmu; + uint8_t mmu_tlb_access; + uint8_t mmu_zones; + + bool stackprot; + bool use_barrel; + bool use_div; + bool use_msr_instr; + bool use_pcmp_instr; + bool use_mmu; + bool dcache_writeback; + bool endi; + bool dopb_bus_exception; + bool iopb_bus_exception; + bool illegal_opcode_exception; + bool opcode_0_illegal; + bool div_zero_exception; + bool unaligned_exceptions; +} MicroBlazeCPUConfig; + /** * MicroBlazeCPU: * @env: #CPUMBState @@ -286,42 +340,36 @@ struct MicroBlazeCPU { CPUNegativeOffsetState neg; CPUMBState env; - - /* Microblaze Configuration Settings */ - struct { - bool stackprot; - uint32_t base_vectors; - uint8_t addr_size; - uint8_t use_fpu; - uint8_t use_hw_mul; - bool use_barrel; - bool use_div; - bool use_msr_instr; - bool use_pcmp_instr; - bool use_mmu; - bool dcache_writeback; - bool endi; - bool dopb_bus_exception; - bool iopb_bus_exception; - bool illegal_opcode_exception; - bool opcode_0_illegal; - bool div_zero_exception; - bool unaligned_exceptions; - uint8_t pvr_user1; - uint32_t pvr_user2; - char *version; - uint8_t pvr; - } cfg; + MicroBlazeCPUConfig cfg; }; void mb_cpu_do_interrupt(CPUState *cs); bool mb_cpu_exec_interrupt(CPUState *cs, int int_req); +void mb_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, + MMUAccessType access_type, + int mmu_idx, uintptr_t retaddr); void mb_cpu_dump_state(CPUState *cpu, FILE *f, int flags); hwaddr mb_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); int mb_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); int mb_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); +static inline uint32_t mb_cpu_read_msr(const CPUMBState *env) +{ + /* Replicate MSR[C] to MSR[CC]. */ + return env->msr | (env->msr_c * (MSR_C | MSR_CC)); +} + +static inline void mb_cpu_write_msr(CPUMBState *env, uint32_t val) +{ + env->msr_c = (val >> 2) & 1; + /* + * Clear both MSR[C] and MSR[CC] from the saved copy. + * MSR_PVR is not writable and is always clear. + */ + env->msr = val & ~(MSR_C | MSR_CC | MSR_PVR); +} + void mb_tcg_init(void); /* you can call this signal handler from your SIGBUS and SIGSEGV signal handlers to inform the virtual CPU of exceptions. non zero @@ -348,13 +396,15 @@ typedef MicroBlazeCPU ArchCPU; #include "exec/cpu-all.h" +/* Ensure there is no overlap between the two masks. */ +QEMU_BUILD_BUG_ON(MSR_TB_MASK & IFLAGS_TB_MASK); + static inline void cpu_get_tb_cpu_state(CPUMBState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *flags) { - *pc = env->sregs[SR_PC]; - *cs_base = 0; - *flags = (env->iflags & IFLAGS_TB_MASK) | - (env->sregs[SR_MSR] & (MSR_UM | MSR_VM | MSR_EE)); + *pc = env->pc; + *flags = (env->iflags & IFLAGS_TB_MASK) | (env->msr & MSR_TB_MASK); + *cs_base = (*flags & IMM_FLAG ? env->imm : 0); } #if !defined(CONFIG_USER_ONLY) @@ -369,14 +419,18 @@ static inline int cpu_mmu_index(CPUMBState *env, bool ifetch) MicroBlazeCPU *cpu = env_archcpu(env); /* Are we in nommu mode?. */ - if (!(env->sregs[SR_MSR] & MSR_VM) || !cpu->cfg.use_mmu) { + if (!(env->msr & MSR_VM) || !cpu->cfg.use_mmu) { return MMU_NOMMU_IDX; } - if (env->sregs[SR_MSR] & MSR_UM) { + if (env->msr & MSR_UM) { return MMU_USER_IDX; } return MMU_KERNEL_IDX; } +#ifndef CONFIG_USER_ONLY +extern const VMStateDescription vmstate_mb_cpu; +#endif + #endif diff --git a/target/microblaze/gdbstub.c b/target/microblaze/gdbstub.c index 73e89735979117c2d5d31de9ec24a0ebb7a05e39..2e6e070051ffa6b6df44c8dd33b94221259f773a 100644 --- a/target/microblaze/gdbstub.c +++ b/target/microblaze/gdbstub.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -21,58 +21,80 @@ #include "cpu.h" #include "exec/gdbstub.h" +/* + * GDB expects SREGs in the following order: + * PC, MSR, EAR, ESR, FSR, BTR, EDR, PID, ZPR, TLBX, TLBSX, TLBLO, TLBHI. + * + * PID, ZPR, TLBx, TLBsx, TLBLO, and TLBHI aren't modeled, so we don't + * map them to anything and return a value of 0 instead. + */ + +enum { + GDB_PC = 32 + 0, + GDB_MSR = 32 + 1, + GDB_EAR = 32 + 2, + GDB_ESR = 32 + 3, + GDB_FSR = 32 + 4, + GDB_BTR = 32 + 5, + GDB_PVR0 = 32 + 6, + GDB_PVR11 = 32 + 17, + GDB_EDR = 32 + 18, + GDB_SLR = 32 + 25, + GDB_SHR = 32 + 26, +}; + int mb_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) { MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); + CPUClass *cc = CPU_GET_CLASS(cs); CPUMBState *env = &cpu->env; - /* - * GDB expects SREGs in the following order: - * PC, MSR, EAR, ESR, FSR, BTR, EDR, PID, ZPR, TLBX, TLBSX, TLBLO, TLBHI. - * They aren't stored in this order, so make a map. - * PID, ZPR, TLBx, TLBsx, TLBLO, and TLBHI aren't modeled, so we don't - * map them to anything and return a value of 0 instead. - */ - static const uint8_t sreg_map[6] = { - SR_PC, - SR_MSR, - SR_EAR, - SR_ESR, - SR_FSR, - SR_BTR - }; + uint32_t val; - /* - * GDB expects registers to be reported in this order: - * R0-R31 - * PC-BTR - * PVR0-PVR11 - * EDR-TLBHI - * SLR-SHR - */ - if (n < 32) { - return gdb_get_reg32(mem_buf, env->regs[n]); - } else { - n -= 32; - switch (n) { - case 0 ... 5: - return gdb_get_reg32(mem_buf, env->sregs[sreg_map[n]]); + if (n > cc->gdb_num_core_regs) { + return 0; + } + + switch (n) { + case 1 ... 31: + val = env->regs[n]; + break; + case GDB_PC: + val = env->pc; + break; + case GDB_MSR: + val = mb_cpu_read_msr(env); + break; + case GDB_EAR: + val = env->ear; + break; + case GDB_ESR: + val = env->esr; + break; + case GDB_FSR: + val = env->fsr; + break; + case GDB_BTR: + val = env->btr; + break; + case GDB_PVR0 ... GDB_PVR11: /* PVR12 is intentionally skipped */ - case 6 ... 17: - n -= 6; - return gdb_get_reg32(mem_buf, env->pvr.regs[n]); - case 18: - return gdb_get_reg32(mem_buf, env->sregs[SR_EDR]); + val = cpu->cfg.pvr_regs[n - GDB_PVR0]; + break; + case GDB_EDR: + val = env->edr; + break; + case GDB_SLR: + val = env->slr; + break; + case GDB_SHR: + val = env->shr; + break; + default: /* Other SRegs aren't modeled, so report a value of 0 */ - case 19 ... 24: - return gdb_get_reg32(mem_buf, 0); - case 25: - return gdb_get_reg32(mem_buf, env->slr); - case 26: - return gdb_get_reg32(mem_buf, env->shr); - default: - return 0; - } + val = 0; + break; } + return gdb_get_reg32(mem_buf, val); } int mb_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) @@ -82,60 +104,43 @@ int mb_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) CPUMBState *env = &cpu->env; uint32_t tmp; - /* - * GDB expects SREGs in the following order: - * PC, MSR, EAR, ESR, FSR, BTR, EDR, PID, ZPR, TLBX, TLBSX, TLBLO, TLBHI. - * They aren't stored in this order, so make a map. - * PID, ZPR, TLBx, TLBsx, TLBLO, and TLBHI aren't modeled, so we don't - * map them to anything. - */ - static const uint8_t sreg_map[6] = { - SR_PC, - SR_MSR, - SR_EAR, - SR_ESR, - SR_FSR, - SR_BTR - }; - if (n > cc->gdb_num_core_regs) { return 0; } tmp = ldl_p(mem_buf); - /* - * GDB expects registers to be reported in this order: - * R0-R31 - * PC-BTR - * PVR0-PVR11 - * EDR-TLBHI - * SLR-SHR - */ - if (n < 32) { + switch (n) { + case 1 ... 31: env->regs[n] = tmp; - } else { - n -= 32; - switch (n) { - case 0 ... 5: - env->sregs[sreg_map[n]] = tmp; - break; - /* PVR12 is intentionally skipped */ - case 6 ... 17: - n -= 6; - env->pvr.regs[n] = tmp; - break; - /* Only EDR is modeled in these indeces, so ignore the rest */ - case 18: - env->sregs[SR_EDR] = tmp; - break; - case 25: - env->slr = tmp; - break; - case 26: - env->shr = tmp; - break; - } + break; + case GDB_PC: + env->pc = tmp; + break; + case GDB_MSR: + mb_cpu_write_msr(env, tmp); + break; + case GDB_EAR: + env->ear = tmp; + break; + case GDB_ESR: + env->esr = tmp; + break; + case GDB_FSR: + env->fsr = tmp; + break; + case GDB_BTR: + env->btr = tmp; + break; + case GDB_EDR: + env->edr = tmp; + break; + case GDB_SLR: + env->slr = tmp; + break; + case GDB_SHR: + env->shr = tmp; + break; } return 4; } diff --git a/target/microblaze/helper.c b/target/microblaze/helper.c index ab2ceeb05527baa270945bf15016bcb8453d1e17..cda14a14bec696c53af9a4090635918e1a911d3e 100644 --- a/target/microblaze/helper.c +++ b/target/microblaze/helper.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -24,8 +24,6 @@ #include "qemu/host-utils.h" #include "exec/log.h" -#define D(x) - #if defined(CONFIG_USER_ONLY) void mb_cpu_do_interrupt(CPUState *cs) @@ -35,7 +33,7 @@ void mb_cpu_do_interrupt(CPUState *cs) cs->exception_index = -1; env->res_addr = RES_ADDR_NONE; - env->regs[14] = env->sregs[SR_PC]; + env->regs[14] = env->pc; } bool mb_cpu_tlb_fill(CPUState *cs, vaddr address, int size, @@ -54,7 +52,7 @@ bool mb_cpu_tlb_fill(CPUState *cs, vaddr address, int size, { MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); CPUMBState *env = &cpu->env; - struct microblaze_mmu_lookup lu; + MicroBlazeMMULookup lu; unsigned int hit; int prot; @@ -66,7 +64,7 @@ bool mb_cpu_tlb_fill(CPUState *cs, vaddr address, int size, return true; } - hit = mmu_translate(&env->mmu, &lu, address, access_type, mmu_idx); + hit = mmu_translate(cpu, &lu, address, access_type, mmu_idx); if (likely(hit)) { uint32_t vaddr = address & TARGET_PAGE_MASK; uint32_t paddr = lu.paddr + vaddr - lu.vaddr; @@ -85,15 +83,15 @@ bool mb_cpu_tlb_fill(CPUState *cs, vaddr address, int size, qemu_log_mask(CPU_LOG_MMU, "mmu=%d miss v=%" VADDR_PRIx "\n", mmu_idx, address); - env->sregs[SR_EAR] = address; + env->ear = address; switch (lu.err) { case ERR_PROT: - env->sregs[SR_ESR] = access_type == MMU_INST_FETCH ? 17 : 16; - env->sregs[SR_ESR] |= (access_type == MMU_DATA_STORE) << 10; + env->esr = access_type == MMU_INST_FETCH ? 17 : 16; + env->esr |= (access_type == MMU_DATA_STORE) << 10; break; case ERR_MISS: - env->sregs[SR_ESR] = access_type == MMU_INST_FETCH ? 19 : 18; - env->sregs[SR_ESR] |= (access_type == MMU_DATA_STORE) << 10; + env->esr = access_type == MMU_INST_FETCH ? 19 : 18; + env->esr |= (access_type == MMU_DATA_STORE) << 10; break; default: abort(); @@ -112,155 +110,123 @@ void mb_cpu_do_interrupt(CPUState *cs) { MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); CPUMBState *env = &cpu->env; - uint32_t t; + uint32_t t, msr = mb_cpu_read_msr(env); + bool set_esr; /* IMM flag cannot propagate across a branch and into the dslot. */ - assert(!((env->iflags & D_FLAG) && (env->iflags & IMM_FLAG))); + assert((env->iflags & (D_FLAG | IMM_FLAG)) != (D_FLAG | IMM_FLAG)); + /* BIMM flag cannot be set without D_FLAG. */ + assert((env->iflags & (D_FLAG | BIMM_FLAG)) != BIMM_FLAG); + /* RTI flags are private to translate. */ assert(!(env->iflags & (DRTI_FLAG | DRTE_FLAG | DRTB_FLAG))); -/* assert(env->sregs[SR_MSR] & (MSR_EE)); Only for HW exceptions. */ - env->res_addr = RES_ADDR_NONE; + switch (cs->exception_index) { - case EXCP_HW_EXCP: - if (!(env->pvr.regs[0] & PVR0_USE_EXC_MASK)) { - qemu_log_mask(LOG_GUEST_ERROR, "Exception raised on system without exceptions!\n"); - return; - } - - env->regs[17] = env->sregs[SR_PC] + 4; - env->sregs[SR_ESR] &= ~(1 << 12); - - /* Exception breaks branch + dslot sequence? */ - if (env->iflags & D_FLAG) { - env->sregs[SR_ESR] |= 1 << 12 ; - env->sregs[SR_BTR] = env->btarget; - } - - /* Disable the MMU. */ - t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1; - env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM); - env->sregs[SR_MSR] |= t; - /* Exception in progress. */ - env->sregs[SR_MSR] |= MSR_EIP; - - qemu_log_mask(CPU_LOG_INT, - "hw exception at pc=%" PRIx64 " ear=%" PRIx64 " " - "esr=%" PRIx64 " iflags=%x\n", - env->sregs[SR_PC], env->sregs[SR_EAR], - env->sregs[SR_ESR], env->iflags); - log_cpu_state_mask(CPU_LOG_INT, cs, 0); - env->iflags &= ~(IMM_FLAG | D_FLAG); - env->sregs[SR_PC] = cpu->cfg.base_vectors + 0x20; - break; - - case EXCP_MMU: - env->regs[17] = env->sregs[SR_PC]; - - env->sregs[SR_ESR] &= ~(1 << 12); - /* Exception breaks branch + dslot sequence? */ - if (env->iflags & D_FLAG) { - D(qemu_log("D_FLAG set at exception bimm=%d\n", env->bimm)); - env->sregs[SR_ESR] |= 1 << 12 ; - env->sregs[SR_BTR] = env->btarget; - - /* Reexecute the branch. */ - env->regs[17] -= 4; - /* was the branch immprefixed?. */ - if (env->bimm) { - qemu_log_mask(CPU_LOG_INT, - "bimm exception at pc=%" PRIx64 " " - "iflags=%x\n", - env->sregs[SR_PC], env->iflags); - env->regs[17] -= 4; - log_cpu_state_mask(CPU_LOG_INT, cs, 0); - } - } else if (env->iflags & IMM_FLAG) { - D(qemu_log("IMM_FLAG set at exception\n")); - env->regs[17] -= 4; - } - - /* Disable the MMU. */ - t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1; - env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM); - env->sregs[SR_MSR] |= t; - /* Exception in progress. */ - env->sregs[SR_MSR] |= MSR_EIP; - - qemu_log_mask(CPU_LOG_INT, - "exception at pc=%" PRIx64 " ear=%" PRIx64 " " - "iflags=%x\n", - env->sregs[SR_PC], env->sregs[SR_EAR], env->iflags); - log_cpu_state_mask(CPU_LOG_INT, cs, 0); - env->iflags &= ~(IMM_FLAG | D_FLAG); - env->sregs[SR_PC] = cpu->cfg.base_vectors + 0x20; - break; - - case EXCP_IRQ: - assert(!(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))); - assert(env->sregs[SR_MSR] & MSR_IE); - assert(!(env->iflags & D_FLAG)); - - t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1; - -#if 0 -#include "disas/disas.h" - -/* Useful instrumentation when debugging interrupt issues in either - the models or in sw. */ - { - const char *sym; - - sym = lookup_symbol(env->sregs[SR_PC]); - if (sym - && (!strcmp("netif_rx", sym) - || !strcmp("process_backlog", sym))) { - - qemu_log( - "interrupt at pc=%x msr=%x %x iflags=%x sym=%s\n", - env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags, - sym); - - log_cpu_state(cs, 0); - } - } -#endif - qemu_log_mask(CPU_LOG_INT, - "interrupt at pc=%" PRIx64 " msr=%" PRIx64 " %x " - "iflags=%x\n", - env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags); - - env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM \ - | MSR_UM | MSR_IE); - env->sregs[SR_MSR] |= t; - - env->regs[14] = env->sregs[SR_PC]; - env->sregs[SR_PC] = cpu->cfg.base_vectors + 0x10; - //log_cpu_state_mask(CPU_LOG_INT, cs, 0); - break; - - case EXCP_BREAK: - case EXCP_HW_BREAK: - assert(!(env->iflags & IMM_FLAG)); - assert(!(env->iflags & D_FLAG)); - t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1; - qemu_log_mask(CPU_LOG_INT, - "break at pc=%" PRIx64 " msr=%" PRIx64 " %x " - "iflags=%x\n", - env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags); - log_cpu_state_mask(CPU_LOG_INT, cs, 0); - env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM); - env->sregs[SR_MSR] |= t; - env->sregs[SR_MSR] |= MSR_BIP; - if (cs->exception_index == EXCP_HW_BREAK) { - env->regs[16] = env->sregs[SR_PC]; - env->sregs[SR_MSR] |= MSR_BIP; - env->sregs[SR_PC] = cpu->cfg.base_vectors + 0x18; - } else - env->sregs[SR_PC] = env->btarget; - break; - default: - cpu_abort(cs, "unhandled exception type=%d\n", - cs->exception_index); - break; + case EXCP_HW_EXCP: + if (!(cpu->cfg.pvr_regs[0] & PVR0_USE_EXC_MASK)) { + qemu_log_mask(LOG_GUEST_ERROR, + "Exception raised on system without exceptions!\n"); + return; + } + + qemu_log_mask(CPU_LOG_INT, + "INT: HWE at pc=%08x msr=%08x iflags=%x\n", + env->pc, msr, env->iflags); + + /* Exception breaks branch + dslot sequence? */ + set_esr = true; + env->esr &= ~D_FLAG; + if (env->iflags & D_FLAG) { + env->esr |= D_FLAG; + env->btr = env->btarget; + } + + /* Exception in progress. */ + msr |= MSR_EIP; + env->regs[17] = env->pc + 4; + env->pc = cpu->cfg.base_vectors + 0x20; + break; + + case EXCP_MMU: + qemu_log_mask(CPU_LOG_INT, + "INT: MMU at pc=%08x msr=%08x " + "ear=%" PRIx64 " iflags=%x\n", + env->pc, msr, env->ear, env->iflags); + + /* Exception breaks branch + dslot sequence? */ + set_esr = true; + env->esr &= ~D_FLAG; + if (env->iflags & D_FLAG) { + env->esr |= D_FLAG; + env->btr = env->btarget; + /* Reexecute the branch. */ + env->regs[17] = env->pc - (env->iflags & BIMM_FLAG ? 8 : 4); + } else if (env->iflags & IMM_FLAG) { + /* Reexecute the imm. */ + env->regs[17] = env->pc - 4; + } else { + env->regs[17] = env->pc; + } + + /* Exception in progress. */ + msr |= MSR_EIP; + env->pc = cpu->cfg.base_vectors + 0x20; + break; + + case EXCP_IRQ: + assert(!(msr & (MSR_EIP | MSR_BIP))); + assert(msr & MSR_IE); + assert(!(env->iflags & (D_FLAG | IMM_FLAG))); + + qemu_log_mask(CPU_LOG_INT, + "INT: DEV at pc=%08x msr=%08x iflags=%x\n", + env->pc, msr, env->iflags); + set_esr = false; + + /* Disable interrupts. */ + msr &= ~MSR_IE; + env->regs[14] = env->pc; + env->pc = cpu->cfg.base_vectors + 0x10; + break; + + case EXCP_HW_BREAK: + assert(!(env->iflags & (D_FLAG | IMM_FLAG))); + + qemu_log_mask(CPU_LOG_INT, + "INT: BRK at pc=%08x msr=%08x iflags=%x\n", + env->pc, msr, env->iflags); + set_esr = false; + + /* Break in progress. */ + msr |= MSR_BIP; + env->regs[16] = env->pc; + env->pc = cpu->cfg.base_vectors + 0x18; + break; + + default: + cpu_abort(cs, "unhandled exception type=%d\n", cs->exception_index); + /* not reached */ + } + + /* Save previous mode, disable mmu, disable user-mode. */ + t = (msr & (MSR_VM | MSR_UM)) << 1; + msr &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM); + msr |= t; + mb_cpu_write_msr(env, msr); + + env->res_addr = RES_ADDR_NONE; + env->iflags = 0; + + if (!set_esr) { + qemu_log_mask(CPU_LOG_INT, + " to pc=%08x msr=%08x\n", env->pc, msr); + } else if (env->esr & D_FLAG) { + qemu_log_mask(CPU_LOG_INT, + " to pc=%08x msr=%08x esr=%04x btr=%08x\n", + env->pc, msr, env->esr, env->btr); + } else { + qemu_log_mask(CPU_LOG_INT, + " to pc=%08x msr=%08x esr=%04x\n", + env->pc, msr, env->esr); } } @@ -269,12 +235,12 @@ hwaddr mb_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); CPUMBState *env = &cpu->env; target_ulong vaddr, paddr = 0; - struct microblaze_mmu_lookup lu; + MicroBlazeMMULookup lu; int mmu_idx = cpu_mmu_index(env, false); unsigned int hit; if (mmu_idx != MMU_NOMMU_IDX) { - hit = mmu_translate(&env->mmu, &lu, addr, 0, 0); + hit = mmu_translate(cpu, &lu, addr, 0, 0); if (hit) { vaddr = addr & TARGET_PAGE_MASK; paddr = lu.paddr + vaddr - lu.vaddr; @@ -293,8 +259,8 @@ bool mb_cpu_exec_interrupt(CPUState *cs, int interrupt_request) CPUMBState *env = &cpu->env; if ((interrupt_request & CPU_INTERRUPT_HARD) - && (env->sregs[SR_MSR] & MSR_IE) - && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP)) + && (env->msr & MSR_IE) + && !(env->msr & (MSR_EIP | MSR_BIP)) && !(env->iflags & (D_FLAG | IMM_FLAG))) { cs->exception_index = EXCP_IRQ; mb_cpu_do_interrupt(cs); @@ -302,3 +268,31 @@ bool mb_cpu_exec_interrupt(CPUState *cs, int interrupt_request) } return false; } + +void mb_cpu_do_unaligned_access(CPUState *cs, vaddr addr, + MMUAccessType access_type, + int mmu_idx, uintptr_t retaddr) +{ + MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); + uint32_t esr, iflags; + + /* Recover the pc and iflags from the corresponding insn_start. */ + cpu_restore_state(cs, retaddr, true); + iflags = cpu->env.iflags; + + qemu_log_mask(CPU_LOG_INT, + "Unaligned access addr=" TARGET_FMT_lx " pc=%x iflags=%x\n", + (target_ulong)addr, cpu->env.pc, iflags); + + esr = ESR_EC_UNALIGNED_DATA; + if (likely(iflags & ESR_ESS_FLAG)) { + esr |= iflags & ESR_ESS_MASK; + } else { + qemu_log_mask(LOG_UNIMP, "Unaligned access without ESR_ESS_FLAG\n"); + } + + cpu->env.ear = addr; + cpu->env.esr = esr; + cs->exception_index = EXCP_HW_EXCP; + cpu_loop_exit(cs); +} diff --git a/target/microblaze/helper.h b/target/microblaze/helper.h index 2f8bdea22b0c0e9d14b9aad71e6060165d6ad3db..f740835fcb0e30342ebbc021516ecac32835802c 100644 --- a/target/microblaze/helper.h +++ b/target/microblaze/helper.h @@ -1,36 +1,31 @@ -DEF_HELPER_2(raise_exception, void, env, i32) -DEF_HELPER_1(debug, void, env) -DEF_HELPER_FLAGS_3(carry, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) -DEF_HELPER_2(cmp, i32, i32, i32) -DEF_HELPER_2(cmpu, i32, i32, i32) +DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_WG, noreturn, env, i32) -DEF_HELPER_3(divs, i32, env, i32, i32) -DEF_HELPER_3(divu, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(divs, TCG_CALL_NO_WG, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(divu, TCG_CALL_NO_WG, i32, env, i32, i32) -DEF_HELPER_3(fadd, i32, env, i32, i32) -DEF_HELPER_3(frsub, i32, env, i32, i32) -DEF_HELPER_3(fmul, i32, env, i32, i32) -DEF_HELPER_3(fdiv, i32, env, i32, i32) -DEF_HELPER_2(flt, i32, env, i32) -DEF_HELPER_2(fint, i32, env, i32) -DEF_HELPER_2(fsqrt, i32, env, i32) +DEF_HELPER_FLAGS_3(fadd, TCG_CALL_NO_WG, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(frsub, TCG_CALL_NO_WG, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(fmul, TCG_CALL_NO_WG, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(fdiv, TCG_CALL_NO_WG, i32, env, i32, i32) +DEF_HELPER_FLAGS_2(flt, TCG_CALL_NO_WG, i32, env, i32) +DEF_HELPER_FLAGS_2(fint, TCG_CALL_NO_WG, i32, env, i32) +DEF_HELPER_FLAGS_2(fsqrt, TCG_CALL_NO_WG, i32, env, i32) -DEF_HELPER_3(fcmp_un, i32, env, i32, i32) -DEF_HELPER_3(fcmp_lt, i32, env, i32, i32) -DEF_HELPER_3(fcmp_eq, i32, env, i32, i32) -DEF_HELPER_3(fcmp_le, i32, env, i32, i32) -DEF_HELPER_3(fcmp_gt, i32, env, i32, i32) -DEF_HELPER_3(fcmp_ne, i32, env, i32, i32) -DEF_HELPER_3(fcmp_ge, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(fcmp_un, TCG_CALL_NO_WG, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(fcmp_lt, TCG_CALL_NO_WG, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(fcmp_eq, TCG_CALL_NO_WG, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(fcmp_le, TCG_CALL_NO_WG, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(fcmp_gt, TCG_CALL_NO_WG, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(fcmp_ne, TCG_CALL_NO_WG, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(fcmp_ge, TCG_CALL_NO_WG, i32, env, i32, i32) DEF_HELPER_FLAGS_2(pcmpbf, TCG_CALL_NO_RWG_SE, i32, i32, i32) #if !defined(CONFIG_USER_ONLY) -DEF_HELPER_3(mmu_read, i32, env, i32, i32) -DEF_HELPER_4(mmu_write, void, env, i32, i32, i32) +DEF_HELPER_FLAGS_3(mmu_read, TCG_CALL_NO_RWG, i32, env, i32, i32) +DEF_HELPER_FLAGS_4(mmu_write, TCG_CALL_NO_RWG, void, env, i32, i32, i32) #endif -DEF_HELPER_5(memalign, void, env, tl, i32, i32, i32) -DEF_HELPER_2(stackprot, void, env, tl) +DEF_HELPER_FLAGS_2(stackprot, TCG_CALL_NO_WG, void, env, tl) -DEF_HELPER_2(get, i32, i32, i32) -DEF_HELPER_3(put, void, i32, i32, i32) +DEF_HELPER_FLAGS_2(get, TCG_CALL_NO_RWG, i32, i32, i32) +DEF_HELPER_FLAGS_3(put, TCG_CALL_NO_RWG, void, i32, i32, i32) diff --git a/target/microblaze/insns.decode b/target/microblaze/insns.decode new file mode 100644 index 0000000000000000000000000000000000000000..fb0f0e68386c338eea1f7ef3fa3367ea0e90ac6b --- /dev/null +++ b/target/microblaze/insns.decode @@ -0,0 +1,256 @@ +# +# MicroBlaze instruction decode definitions. +# +# Copyright (c) 2020 Richard Henderson +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see . +# + +&typea0 rd ra +&typea rd ra rb +&typea_br rd rb +&typea_bc ra rb +&typeb rd ra imm +&typeb_br rd imm +&typeb_bc ra imm +&type_msr rd imm + +# Include any IMM prefix in the value reported. +%extimm 0:s16 !function=typeb_imm + +@typea ...... rd:5 ra:5 rb:5 ... .... .... &typea +@typeb ...... rd:5 ra:5 ................ &typeb imm=%extimm + +# Officially typea, but with rb==0, which is not used. +@typea0 ...... rd:5 ra:5 ................ &typea0 + +# Officially typea, but with ra as opcode. +@typea_br ...... rd:5 ..... rb:5 ........... &typea_br + +# Officially typea, but with rd as opcode. +@typea_bc ...... ..... ra:5 rb:5 ........... &typea_bc + +# Officially typeb, but any immediate extension is unused. +@typeb_bs ...... rd:5 ra:5 ..... ...... imm:5 &typeb + +# Officially typeb, but with ra as opcode. +@typeb_br ...... rd:5 ..... ................ &typeb_br imm=%extimm + +# Officially typeb, but with rd as opcode. +@typeb_bc ...... ..... ra:5 ................ &typeb_bc imm=%extimm + +# For convenience, extract the two imm_w/imm_s fields, then pack +# them back together as "imm". Doing this makes it easiest to +# match the required zero at bit 5. +%ieimm 6:5 0:5 +@typeb_ie ...... rd:5 ra:5 ..... ..... . ..... &typeb imm=%ieimm + +@type_msr ...... rd:5 ...... imm:15 &type_msr + +### + +{ + zero 000000 00000 00000 00000 000 0000 0000 + add 000000 ..... ..... ..... 000 0000 0000 @typea +} +addc 000010 ..... ..... ..... 000 0000 0000 @typea +addk 000100 ..... ..... ..... 000 0000 0000 @typea +addkc 000110 ..... ..... ..... 000 0000 0000 @typea + +addi 001000 ..... ..... ................ @typeb +addic 001010 ..... ..... ................ @typeb +addik 001100 ..... ..... ................ @typeb +addikc 001110 ..... ..... ................ @typeb + +and 100001 ..... ..... ..... 000 0000 0000 @typea +andi 101001 ..... ..... ................ @typeb + +andn 100011 ..... ..... ..... 000 0000 0000 @typea +andni 101011 ..... ..... ................ @typeb + +beq 100111 00000 ..... ..... 000 0000 0000 @typea_bc +bge 100111 00101 ..... ..... 000 0000 0000 @typea_bc +bgt 100111 00100 ..... ..... 000 0000 0000 @typea_bc +ble 100111 00011 ..... ..... 000 0000 0000 @typea_bc +blt 100111 00010 ..... ..... 000 0000 0000 @typea_bc +bne 100111 00001 ..... ..... 000 0000 0000 @typea_bc + +beqd 100111 10000 ..... ..... 000 0000 0000 @typea_bc +bged 100111 10101 ..... ..... 000 0000 0000 @typea_bc +bgtd 100111 10100 ..... ..... 000 0000 0000 @typea_bc +bled 100111 10011 ..... ..... 000 0000 0000 @typea_bc +bltd 100111 10010 ..... ..... 000 0000 0000 @typea_bc +bned 100111 10001 ..... ..... 000 0000 0000 @typea_bc + +beqi 101111 00000 ..... ................ @typeb_bc +bgei 101111 00101 ..... ................ @typeb_bc +bgti 101111 00100 ..... ................ @typeb_bc +blei 101111 00011 ..... ................ @typeb_bc +blti 101111 00010 ..... ................ @typeb_bc +bnei 101111 00001 ..... ................ @typeb_bc + +beqid 101111 10000 ..... ................ @typeb_bc +bgeid 101111 10101 ..... ................ @typeb_bc +bgtid 101111 10100 ..... ................ @typeb_bc +bleid 101111 10011 ..... ................ @typeb_bc +bltid 101111 10010 ..... ................ @typeb_bc +bneid 101111 10001 ..... ................ @typeb_bc + +br 100110 ..... 00000 ..... 000 0000 0000 @typea_br +bra 100110 ..... 01000 ..... 000 0000 0000 @typea_br +brd 100110 ..... 10000 ..... 000 0000 0000 @typea_br +brad 100110 ..... 11000 ..... 000 0000 0000 @typea_br +brld 100110 ..... 10100 ..... 000 0000 0000 @typea_br +brald 100110 ..... 11100 ..... 000 0000 0000 @typea_br + +bri 101110 ..... 00000 ................ @typeb_br +brai 101110 ..... 01000 ................ @typeb_br +brid 101110 ..... 10000 ................ @typeb_br +braid 101110 ..... 11000 ................ @typeb_br +brlid 101110 ..... 10100 ................ @typeb_br +bralid 101110 ..... 11100 ................ @typeb_br + +brk 100110 ..... 01100 ..... 000 0000 0000 @typea_br +brki 101110 ..... 01100 ................ @typeb_br + +bsrl 010001 ..... ..... ..... 000 0000 0000 @typea +bsra 010001 ..... ..... ..... 010 0000 0000 @typea +bsll 010001 ..... ..... ..... 100 0000 0000 @typea + +bsrli 011001 ..... ..... 00000 000000 ..... @typeb_bs +bsrai 011001 ..... ..... 00000 010000 ..... @typeb_bs +bslli 011001 ..... ..... 00000 100000 ..... @typeb_bs + +bsefi 011001 ..... ..... 01000 .....0 ..... @typeb_ie +bsifi 011001 ..... ..... 10000 .....0 ..... @typeb_ie + +clz 100100 ..... ..... 00000 000 1110 0000 @typea0 + +cmp 000101 ..... ..... ..... 000 0000 0001 @typea +cmpu 000101 ..... ..... ..... 000 0000 0011 @typea + +fadd 010110 ..... ..... ..... 0000 000 0000 @typea +frsub 010110 ..... ..... ..... 0001 000 0000 @typea +fmul 010110 ..... ..... ..... 0010 000 0000 @typea +fdiv 010110 ..... ..... ..... 0011 000 0000 @typea +fcmp_un 010110 ..... ..... ..... 0100 000 0000 @typea +fcmp_lt 010110 ..... ..... ..... 0100 001 0000 @typea +fcmp_eq 010110 ..... ..... ..... 0100 010 0000 @typea +fcmp_le 010110 ..... ..... ..... 0100 011 0000 @typea +fcmp_gt 010110 ..... ..... ..... 0100 100 0000 @typea +fcmp_ne 010110 ..... ..... ..... 0100 101 0000 @typea +fcmp_ge 010110 ..... ..... ..... 0100 110 0000 @typea + +# Note that flt and fint, unlike fsqrt, are documented as having the RB +# operand which is unused. So allow the field to be non-zero but discard +# the value and treat as 2-operand insns. +flt 010110 ..... ..... ----- 0101 000 0000 @typea0 +fint 010110 ..... ..... ----- 0110 000 0000 @typea0 +fsqrt 010110 ..... ..... 00000 0111 000 0000 @typea0 + +get 011011 rd:5 00000 0 ctrl:5 000000 imm:4 +getd 010011 rd:5 00000 rb:5 0 ctrl:5 00000 + +idiv 010010 ..... ..... ..... 000 0000 0000 @typea +idivu 010010 ..... ..... ..... 000 0000 0010 @typea + +imm 101100 00000 00000 imm:16 + +lbu 110000 ..... ..... ..... 0000 000 0000 @typea +lbur 110000 ..... ..... ..... 0100 000 0000 @typea +lbuea 110000 ..... ..... ..... 0001 000 0000 @typea +lbui 111000 ..... ..... ................ @typeb + +lhu 110001 ..... ..... ..... 0000 000 0000 @typea +lhur 110001 ..... ..... ..... 0100 000 0000 @typea +lhuea 110001 ..... ..... ..... 0001 000 0000 @typea +lhui 111001 ..... ..... ................ @typeb + +lw 110010 ..... ..... ..... 0000 000 0000 @typea +lwr 110010 ..... ..... ..... 0100 000 0000 @typea +lwea 110010 ..... ..... ..... 0001 000 0000 @typea +lwx 110010 ..... ..... ..... 1000 000 0000 @typea +lwi 111010 ..... ..... ................ @typeb + +mbar 101110 imm:5 00010 0000 0000 0000 0100 + +mfs 100101 rd:5 0 e:1 000 10 rs:14 +mts 100101 0 e:1 000 ra:5 11 rs:14 + +msrclr 100101 ..... 100010 ............... @type_msr +msrset 100101 ..... 100000 ............... @type_msr + +mul 010000 ..... ..... ..... 000 0000 0000 @typea +mulh 010000 ..... ..... ..... 000 0000 0001 @typea +mulhu 010000 ..... ..... ..... 000 0000 0011 @typea +mulhsu 010000 ..... ..... ..... 000 0000 0010 @typea +muli 011000 ..... ..... ................ @typeb + +or 100000 ..... ..... ..... 000 0000 0000 @typea +ori 101000 ..... ..... ................ @typeb + +pcmpbf 100000 ..... ..... ..... 100 0000 0000 @typea +pcmpeq 100010 ..... ..... ..... 100 0000 0000 @typea +pcmpne 100011 ..... ..... ..... 100 0000 0000 @typea + +put 011011 00000 ra:5 1 ctrl:5 000000 imm:4 +putd 010011 00000 ra:5 rb:5 1 ctrl:5 00000 + +rsub 000001 ..... ..... ..... 000 0000 0000 @typea +rsubc 000011 ..... ..... ..... 000 0000 0000 @typea +rsubk 000101 ..... ..... ..... 000 0000 0000 @typea +rsubkc 000111 ..... ..... ..... 000 0000 0000 @typea + +rsubi 001001 ..... ..... ................ @typeb +rsubic 001011 ..... ..... ................ @typeb +rsubik 001101 ..... ..... ................ @typeb +rsubikc 001111 ..... ..... ................ @typeb + +rtbd 101101 10010 ..... ................ @typeb_bc +rtid 101101 10001 ..... ................ @typeb_bc +rted 101101 10100 ..... ................ @typeb_bc +rtsd 101101 10000 ..... ................ @typeb_bc + +sb 110100 ..... ..... ..... 0000 000 0000 @typea +sbr 110100 ..... ..... ..... 0100 000 0000 @typea +sbea 110100 ..... ..... ..... 0001 000 0000 @typea +sbi 111100 ..... ..... ................ @typeb + +sh 110101 ..... ..... ..... 0000 000 0000 @typea +shr 110101 ..... ..... ..... 0100 000 0000 @typea +shea 110101 ..... ..... ..... 0001 000 0000 @typea +shi 111101 ..... ..... ................ @typeb + +sw 110110 ..... ..... ..... 0000 000 0000 @typea +swr 110110 ..... ..... ..... 0100 000 0000 @typea +swea 110110 ..... ..... ..... 0001 000 0000 @typea +swx 110110 ..... ..... ..... 1000 000 0000 @typea +swi 111110 ..... ..... ................ @typeb + +sext8 100100 ..... ..... 00000 000 0110 0000 @typea0 +sext16 100100 ..... ..... 00000 000 0110 0001 @typea0 + +sra 100100 ..... ..... 00000 000 0000 0001 @typea0 +src 100100 ..... ..... 00000 000 0010 0001 @typea0 +srl 100100 ..... ..... 00000 000 0100 0001 @typea0 + +swapb 100100 ..... ..... 00000 001 1110 0000 @typea0 +swaph 100100 ..... ..... 00000 001 1110 0010 @typea0 + +# Cache operations have no effect in qemu: discard the arguments. +wdic 100100 00000 ----- ----- -00 -11- 01-0 # wdc +wdic 100100 00000 ----- ----- 000 0110 1000 # wic + +xor 100010 ..... ..... ..... 000 0000 0000 @typea +xori 101010 ..... ..... ................ @typeb diff --git a/target/microblaze/machine.c b/target/microblaze/machine.c new file mode 100644 index 0000000000000000000000000000000000000000..c2074bbdfedd03019f52ee9fc34f536bea13b617 --- /dev/null +++ b/target/microblaze/machine.c @@ -0,0 +1,106 @@ +/* + * Microblaze VMState for qemu. + * + * Copyright (c) 2020 Linaro, Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "migration/cpu.h" + + +static VMStateField vmstate_mmu_fields[] = { + VMSTATE_UINT64_2DARRAY(rams, MicroBlazeMMU, 2, TLB_ENTRIES), + VMSTATE_UINT8_ARRAY(tids, MicroBlazeMMU, TLB_ENTRIES), + VMSTATE_UINT32_ARRAY(regs, MicroBlazeMMU, 3), + VMSTATE_END_OF_LIST() +}; + +static const VMStateDescription vmstate_mmu = { + .name = "mmu", + .version_id = 0, + .minimum_version_id = 0, + .fields = vmstate_mmu_fields, +}; + +static int get_msr(QEMUFile *f, void *opaque, size_t size, + const VMStateField *field) +{ + CPUMBState *env = container_of(opaque, CPUMBState, msr); + + mb_cpu_write_msr(env, qemu_get_be32(f)); + return 0; +} + +static int put_msr(QEMUFile *f, void *opaque, size_t size, + const VMStateField *field, QJSON *vmdesc) +{ + CPUMBState *env = container_of(opaque, CPUMBState, msr); + + qemu_put_be32(f, mb_cpu_read_msr(env)); + return 0; +} + +static const VMStateInfo vmstate_msr = { + .name = "msr", + .get = get_msr, + .put = put_msr, +}; + +static VMStateField vmstate_env_fields[] = { + VMSTATE_UINT32_ARRAY(regs, CPUMBState, 32), + + VMSTATE_UINT32(pc, CPUMBState), + VMSTATE_SINGLE(msr, CPUMBState, 0, vmstate_msr, uint32_t), + VMSTATE_UINT32(esr, CPUMBState), + VMSTATE_UINT32(fsr, CPUMBState), + VMSTATE_UINT32(btr, CPUMBState), + VMSTATE_UINT32(edr, CPUMBState), + VMSTATE_UINT32(slr, CPUMBState), + VMSTATE_UINT32(shr, CPUMBState), + VMSTATE_UINT64(ear, CPUMBState), + + VMSTATE_UINT32(btarget, CPUMBState), + VMSTATE_UINT32(imm, CPUMBState), + VMSTATE_UINT32(iflags, CPUMBState), + + VMSTATE_UINT32(res_val, CPUMBState), + VMSTATE_UINTTL(res_addr, CPUMBState), + + VMSTATE_STRUCT(mmu, CPUMBState, 0, vmstate_mmu, MicroBlazeMMU), + + VMSTATE_END_OF_LIST() +}; + +static const VMStateDescription vmstate_env = { + .name = "env", + .version_id = 0, + .minimum_version_id = 0, + .fields = vmstate_env_fields, +}; + +static VMStateField vmstate_cpu_fields[] = { + VMSTATE_CPU(), + VMSTATE_STRUCT(env, MicroBlazeCPU, 1, vmstate_env, CPUMBState), + VMSTATE_END_OF_LIST() +}; + +const VMStateDescription vmstate_mb_cpu = { + .name = "cpu", + .version_id = 0, + .minimum_version_id = 0, + .fields = vmstate_cpu_fields, +}; diff --git a/target/microblaze/meson.build b/target/microblaze/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..05ee0ec1635fd6959bf5b875d8b45474991409d2 --- /dev/null +++ b/target/microblaze/meson.build @@ -0,0 +1,20 @@ +gen = decodetree.process('insns.decode') + +microblaze_ss = ss.source_set() +microblaze_ss.add(gen) +microblaze_ss.add(files( + 'cpu.c', + 'gdbstub.c', + 'helper.c', + 'op_helper.c', + 'translate.c', +)) + +microblaze_softmmu_ss = ss.source_set() +microblaze_softmmu_ss.add(files( + 'mmu.c', + 'machine.c', +)) + +target_arch += {'microblaze': microblaze_ss} +target_softmmu_arch += {'microblaze': microblaze_softmmu_ss} diff --git a/target/microblaze/microblaze-decode.h b/target/microblaze/microblaze-decode.h deleted file mode 100644 index 17b2f29fff92d358fe5d6bcf117b1a7e9d00bedb..0000000000000000000000000000000000000000 --- a/target/microblaze/microblaze-decode.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * MicroBlaze insn decoding macros. - * - * Copyright (c) 2009 Edgar E. Iglesias - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -#ifndef TARGET_MICROBLAZE_MICROBLAZE_DECODE_H -#define TARGET_MICROBLAZE_MICROBLAZE_DECODE_H - -/* Convenient binary macros. */ -#define HEX__(n) 0x##n##LU -#define B8__(x) ((x&0x0000000FLU)?1:0) \ - + ((x&0x000000F0LU)?2:0) \ - + ((x&0x00000F00LU)?4:0) \ - + ((x&0x0000F000LU)?8:0) \ - + ((x&0x000F0000LU)?16:0) \ - + ((x&0x00F00000LU)?32:0) \ - + ((x&0x0F000000LU)?64:0) \ - + ((x&0xF0000000LU)?128:0) -#define B8(d) ((unsigned char)B8__(HEX__(d))) - -/* Decode logic, value and mask. */ -#define DEC_ADD {B8(00000000), B8(00110001)} -#define DEC_SUB {B8(00000001), B8(00110001)} -#define DEC_AND {B8(00100001), B8(00110101)} -#define DEC_XOR {B8(00100010), B8(00110111)} -#define DEC_OR {B8(00100000), B8(00110111)} -#define DEC_BIT {B8(00100100), B8(00111111)} -#define DEC_MSR {B8(00100101), B8(00111111)} - -#define DEC_BARREL {B8(00010001), B8(00110111)} -#define DEC_MUL {B8(00010000), B8(00110111)} -#define DEC_DIV {B8(00010010), B8(00110111)} -#define DEC_FPU {B8(00010110), B8(00111111)} - -#define DEC_LD {B8(00110000), B8(00110100)} -#define DEC_ST {B8(00110100), B8(00110100)} -#define DEC_IMM {B8(00101100), B8(00111111)} - -#define DEC_BR {B8(00100110), B8(00110111)} -#define DEC_BCC {B8(00100111), B8(00110111)} -#define DEC_RTS {B8(00101101), B8(00111111)} - -#define DEC_STREAM {B8(00010011), B8(00110111)} - -#endif diff --git a/target/microblaze/mmu.c b/target/microblaze/mmu.c index 6763421ba2534a286a46f7318cffe71d5c8fc74e..1e426963baac12d9c117a9c6c5cb931e41893681 100644 --- a/target/microblaze/mmu.c +++ b/target/microblaze/mmu.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -35,7 +35,7 @@ static unsigned int tlb_decode_size(unsigned int f) static void mmu_flush_idx(CPUMBState *env, unsigned int idx) { CPUState *cs = env_cpu(env); - struct microblaze_mmu *mmu = &env->mmu; + MicroBlazeMMU *mmu = &env->mmu; unsigned int tlb_size; uint32_t tlb_tag, end, t; @@ -55,7 +55,7 @@ static void mmu_flush_idx(CPUMBState *env, unsigned int idx) static void mmu_change_pid(CPUMBState *env, unsigned int newpid) { - struct microblaze_mmu *mmu = &env->mmu; + MicroBlazeMMU *mmu = &env->mmu; unsigned int i; uint32_t t; @@ -73,10 +73,10 @@ static void mmu_change_pid(CPUMBState *env, unsigned int newpid) } /* rw - 0 = read, 1 = write, 2 = fetch. */ -unsigned int mmu_translate(struct microblaze_mmu *mmu, - struct microblaze_mmu_lookup *lu, +unsigned int mmu_translate(MicroBlazeCPU *cpu, MicroBlazeMMULookup *lu, target_ulong vaddr, int rw, int mmu_idx) { + MicroBlazeMMU *mmu = &cpu->env.mmu; unsigned int i, hit = 0; unsigned int tlb_ex = 0, tlb_wr = 0, tlb_zsel; uint64_t tlb_tag, tlb_rpn, mask; @@ -115,13 +115,13 @@ unsigned int mmu_translate(struct microblaze_mmu *mmu, t0 = mmu->regs[MMU_R_ZPR] >> (30 - (tlb_zsel * 2)); t0 &= 0x3; - if (tlb_zsel > mmu->c_mmu_zones) { + if (tlb_zsel > cpu->cfg.mmu_zones) { qemu_log_mask(LOG_GUEST_ERROR, "tlb zone select out of range! %d\n", tlb_zsel); t0 = 1; /* Ignore. */ } - if (mmu->c_mmu == 1) { + if (cpu->cfg.mmu == 1) { t0 = 1; /* Zones are disabled. */ } @@ -158,7 +158,7 @@ unsigned int mmu_translate(struct microblaze_mmu *mmu, tlb_rpn = d & TLB_RPN_MASK; lu->vaddr = tlb_tag; - lu->paddr = tlb_rpn & mmu->c_addr_mask; + lu->paddr = tlb_rpn & cpu->cfg.addr_mask; lu->size = tlb_size; lu->err = ERR_HIT; lu->idx = i; @@ -176,10 +176,11 @@ done: /* Writes/reads to the MMU's special regs end up here. */ uint32_t mmu_read(CPUMBState *env, bool ext, uint32_t rn) { + MicroBlazeCPU *cpu = env_archcpu(env); unsigned int i; uint32_t r = 0; - if (env->mmu.c_mmu < 2 || !env->mmu.c_mmu_tlb_access) { + if (cpu->cfg.mmu < 2 || !cpu->cfg.mmu_tlb_access) { qemu_log_mask(LOG_GUEST_ERROR, "MMU access on MMU-less system\n"); return 0; } @@ -192,7 +193,7 @@ uint32_t mmu_read(CPUMBState *env, bool ext, uint32_t rn) /* Reads to HI/LO trig reads from the mmu rams. */ case MMU_R_TLBLO: case MMU_R_TLBHI: - if (!(env->mmu.c_mmu_tlb_access & 1)) { + if (!(cpu->cfg.mmu_tlb_access & 1)) { qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); return 0; @@ -205,7 +206,7 @@ uint32_t mmu_read(CPUMBState *env, bool ext, uint32_t rn) break; case MMU_R_PID: case MMU_R_ZPR: - if (!(env->mmu.c_mmu_tlb_access & 1)) { + if (!(cpu->cfg.mmu_tlb_access & 1)) { qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); return 0; @@ -228,12 +229,15 @@ uint32_t mmu_read(CPUMBState *env, bool ext, uint32_t rn) void mmu_write(CPUMBState *env, bool ext, uint32_t rn, uint32_t v) { + MicroBlazeCPU *cpu = env_archcpu(env); uint64_t tmp64; unsigned int i; + qemu_log_mask(CPU_LOG_MMU, - "%s rn=%d=%x old=%x\n", __func__, rn, v, env->mmu.regs[rn]); + "%s rn=%d=%x old=%x\n", __func__, rn, v, + rn < 3 ? env->mmu.regs[rn] : env->mmu.regs[MMU_R_TLBX]); - if (env->mmu.c_mmu < 2 || !env->mmu.c_mmu_tlb_access) { + if (cpu->cfg.mmu < 2 || !cpu->cfg.mmu_tlb_access) { qemu_log_mask(LOG_GUEST_ERROR, "MMU access on MMU-less system\n"); return; } @@ -250,8 +254,8 @@ void mmu_write(CPUMBState *env, bool ext, uint32_t rn, uint32_t v) if (rn == MMU_R_TLBHI) { if (i < 3 && !(v & TLB_VALID) && qemu_loglevel_mask(~0)) qemu_log_mask(LOG_GUEST_ERROR, - "invalidating index %x at pc=%" PRIx64 "\n", - i, env->sregs[SR_PC]); + "invalidating index %x at pc=%x\n", + i, env->pc); env->mmu.tids[i] = env->mmu.regs[MMU_R_PID] & 0xff; mmu_flush_idx(env, i); } @@ -259,7 +263,7 @@ void mmu_write(CPUMBState *env, bool ext, uint32_t rn, uint32_t v) env->mmu.rams[rn & 1][i] = deposit64(tmp64, ext * 32, 32, v); break; case MMU_R_ZPR: - if (env->mmu.c_mmu_tlb_access <= 1) { + if (cpu->cfg.mmu_tlb_access <= 1) { qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); return; @@ -273,7 +277,7 @@ void mmu_write(CPUMBState *env, bool ext, uint32_t rn, uint32_t v) env->mmu.regs[rn] = v; break; case MMU_R_PID: - if (env->mmu.c_mmu_tlb_access <= 1) { + if (cpu->cfg.mmu_tlb_access <= 1) { qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); return; @@ -290,17 +294,17 @@ void mmu_write(CPUMBState *env, bool ext, uint32_t rn, uint32_t v) break; case MMU_R_TLBSX: { - struct microblaze_mmu_lookup lu; + MicroBlazeMMULookup lu; int hit; - if (env->mmu.c_mmu_tlb_access <= 1) { + if (cpu->cfg.mmu_tlb_access <= 1) { qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); return; } - hit = mmu_translate(&env->mmu, &lu, - v & TLB_EPN_MASK, 0, cpu_mmu_index(env, false)); + hit = mmu_translate(cpu, &lu, v & TLB_EPN_MASK, + 0, cpu_mmu_index(env, false)); if (hit) { env->mmu.regs[MMU_R_TLBX] = lu.idx; } else { @@ -314,7 +318,7 @@ void mmu_write(CPUMBState *env, bool ext, uint32_t rn, uint32_t v) } } -void mmu_init(struct microblaze_mmu *mmu) +void mmu_init(MicroBlazeMMU *mmu) { int i; for (i = 0; i < ARRAY_SIZE(mmu->regs); i++) { diff --git a/target/microblaze/mmu.h b/target/microblaze/mmu.h index 75e5301c79fd7a9a2fbbb6f9f79a7b02ad43826c..09e40757396091bd11a693db3e1e5c5146097ba3 100644 --- a/target/microblaze/mmu.h +++ b/target/microblaze/mmu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -63,23 +63,16 @@ #define TLB_ENTRIES 64 -struct microblaze_mmu -{ +typedef struct { /* Data and tag brams. */ uint64_t rams[2][TLB_ENTRIES]; /* We keep a separate ram for the tids to avoid the 48 bit tag width. */ uint8_t tids[TLB_ENTRIES]; /* Control flops. */ uint32_t regs[3]; +} MicroBlazeMMU; - int c_mmu; - int c_mmu_tlb_access; - int c_mmu_zones; - uint64_t c_addr_mask; /* Mask to apply to physical addresses. */ -}; - -struct microblaze_mmu_lookup -{ +typedef struct { uint32_t paddr; uint32_t vaddr; unsigned int size; @@ -88,13 +81,12 @@ struct microblaze_mmu_lookup enum { ERR_PROT, ERR_MISS, ERR_HIT } err; -}; +} MicroBlazeMMULookup; -unsigned int mmu_translate(struct microblaze_mmu *mmu, - struct microblaze_mmu_lookup *lu, +unsigned int mmu_translate(MicroBlazeCPU *cpu, MicroBlazeMMULookup *lu, target_ulong vaddr, int rw, int mmu_idx); uint32_t mmu_read(CPUMBState *env, bool ea, uint32_t rn); void mmu_write(CPUMBState *env, bool ea, uint32_t rn, uint32_t v); -void mmu_init(struct microblaze_mmu *mmu); +void mmu_init(MicroBlazeMMU *mmu); #endif diff --git a/target/microblaze/op_helper.c b/target/microblaze/op_helper.c index f3b17a95b304940c8d7b4b0d0678c2196d7b94ad..58d633584d37fb62fc7ac35c605e752861cca8fc 100644 --- a/target/microblaze/op_helper.c +++ b/target/microblaze/op_helper.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -26,8 +26,6 @@ #include "exec/cpu_ldst.h" #include "fpu/softfloat.h" -#define D(x) - void helper_put(uint32_t id, uint32_t ctrl, uint32_t data) { int test = ctrl & STREAM_TEST; @@ -71,85 +69,27 @@ void helper_raise_exception(CPUMBState *env, uint32_t index) cpu_loop_exit(cs); } -void helper_debug(CPUMBState *env) -{ - int i; - - qemu_log("PC=%" PRIx64 "\n", env->sregs[SR_PC]); - qemu_log("rmsr=%" PRIx64 " resr=%" PRIx64 " rear=%" PRIx64 " " - "debug[%x] imm=%x iflags=%x\n", - env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR], - env->debug, env->imm, env->iflags); - qemu_log("btaken=%d btarget=%" PRIx64 " mode=%s(saved=%s) eip=%d ie=%d\n", - env->btaken, env->btarget, - (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel", - (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel", - (bool)(env->sregs[SR_MSR] & MSR_EIP), - (bool)(env->sregs[SR_MSR] & MSR_IE)); - for (i = 0; i < 32; i++) { - qemu_log("r%2.2d=%8.8x ", i, env->regs[i]); - if ((i + 1) % 4 == 0) - qemu_log("\n"); - } - qemu_log("\n\n"); -} - -static inline uint32_t compute_carry(uint32_t a, uint32_t b, uint32_t cin) -{ - uint32_t cout = 0; - - if ((b == ~0) && cin) - cout = 1; - else if ((~0 - a) < (b + cin)) - cout = 1; - return cout; -} - -uint32_t helper_cmp(uint32_t a, uint32_t b) -{ - uint32_t t; - - t = b + ~a + 1; - if ((b & 0x80000000) ^ (a & 0x80000000)) - t = (t & 0x7fffffff) | (b & 0x80000000); - return t; -} - -uint32_t helper_cmpu(uint32_t a, uint32_t b) +static bool check_divz(CPUMBState *env, uint32_t a, uint32_t b, uintptr_t ra) { - uint32_t t; + if (unlikely(b == 0)) { + env->msr |= MSR_DZ; - t = b + ~a + 1; - if ((b & 0x80000000) ^ (a & 0x80000000)) - t = (t & 0x7fffffff) | (a & 0x80000000); - return t; -} + if ((env->msr & MSR_EE) && + env_archcpu(env)->cfg.div_zero_exception) { + CPUState *cs = env_cpu(env); -uint32_t helper_carry(uint32_t a, uint32_t b, uint32_t cf) -{ - return compute_carry(a, b, cf); -} - -static inline int div_prepare(CPUMBState *env, uint32_t a, uint32_t b) -{ - MicroBlazeCPU *cpu = env_archcpu(env); - - if (b == 0) { - env->sregs[SR_MSR] |= MSR_DZ; - - if ((env->sregs[SR_MSR] & MSR_EE) && cpu->cfg.div_zero_exception) { - env->sregs[SR_ESR] = ESR_EC_DIVZERO; - helper_raise_exception(env, EXCP_HW_EXCP); + env->esr = ESR_EC_DIVZERO; + cs->exception_index = EXCP_HW_EXCP; + cpu_loop_exit_restore(cs, ra); } - return 0; + return false; } - env->sregs[SR_MSR] &= ~MSR_DZ; - return 1; + return true; } uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b) { - if (!div_prepare(env, a, b)) { + if (!check_divz(env, a, b, GETPC())) { return 0; } return (int32_t)a / (int32_t)b; @@ -157,43 +97,46 @@ uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b) uint32_t helper_divu(CPUMBState *env, uint32_t a, uint32_t b) { - if (!div_prepare(env, a, b)) { + if (!check_divz(env, a, b, GETPC())) { return 0; } return a / b; } /* raise FPU exception. */ -static void raise_fpu_exception(CPUMBState *env) +static void raise_fpu_exception(CPUMBState *env, uintptr_t ra) { - env->sregs[SR_ESR] = ESR_EC_FPU; - helper_raise_exception(env, EXCP_HW_EXCP); + CPUState *cs = env_cpu(env); + + env->esr = ESR_EC_FPU; + cs->exception_index = EXCP_HW_EXCP; + cpu_loop_exit_restore(cs, ra); } -static void update_fpu_flags(CPUMBState *env, int flags) +static void update_fpu_flags(CPUMBState *env, int flags, uintptr_t ra) { int raise = 0; if (flags & float_flag_invalid) { - env->sregs[SR_FSR] |= FSR_IO; + env->fsr |= FSR_IO; raise = 1; } if (flags & float_flag_divbyzero) { - env->sregs[SR_FSR] |= FSR_DZ; + env->fsr |= FSR_DZ; raise = 1; } if (flags & float_flag_overflow) { - env->sregs[SR_FSR] |= FSR_OF; + env->fsr |= FSR_OF; raise = 1; } if (flags & float_flag_underflow) { - env->sregs[SR_FSR] |= FSR_UF; + env->fsr |= FSR_UF; raise = 1; } if (raise - && (env->pvr.regs[2] & PVR2_FPU_EXC_MASK) - && (env->sregs[SR_MSR] & MSR_EE)) { - raise_fpu_exception(env); + && (env_archcpu(env)->cfg.pvr_regs[2] & PVR2_FPU_EXC_MASK) + && (env->msr & MSR_EE)) { + raise_fpu_exception(env, ra); } } @@ -208,7 +151,7 @@ uint32_t helper_fadd(CPUMBState *env, uint32_t a, uint32_t b) fd.f = float32_add(fa.f, fb.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags); + update_fpu_flags(env, flags, GETPC()); return fd.l; } @@ -222,7 +165,7 @@ uint32_t helper_frsub(CPUMBState *env, uint32_t a, uint32_t b) fb.l = b; fd.f = float32_sub(fb.f, fa.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags); + update_fpu_flags(env, flags, GETPC()); return fd.l; } @@ -236,7 +179,7 @@ uint32_t helper_fmul(CPUMBState *env, uint32_t a, uint32_t b) fb.l = b; fd.f = float32_mul(fa.f, fb.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags); + update_fpu_flags(env, flags, GETPC()); return fd.l; } @@ -251,7 +194,7 @@ uint32_t helper_fdiv(CPUMBState *env, uint32_t a, uint32_t b) fb.l = b; fd.f = float32_div(fb.f, fa.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags); + update_fpu_flags(env, flags, GETPC()); return fd.l; } @@ -266,7 +209,7 @@ uint32_t helper_fcmp_un(CPUMBState *env, uint32_t a, uint32_t b) if (float32_is_signaling_nan(fa.f, &env->fp_status) || float32_is_signaling_nan(fb.f, &env->fp_status)) { - update_fpu_flags(env, float_flag_invalid); + update_fpu_flags(env, float_flag_invalid, GETPC()); r = 1; } @@ -289,7 +232,7 @@ uint32_t helper_fcmp_lt(CPUMBState *env, uint32_t a, uint32_t b) fb.l = b; r = float32_lt(fb.f, fa.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags & float_flag_invalid); + update_fpu_flags(env, flags & float_flag_invalid, GETPC()); return r; } @@ -305,7 +248,7 @@ uint32_t helper_fcmp_eq(CPUMBState *env, uint32_t a, uint32_t b) fb.l = b; r = float32_eq_quiet(fa.f, fb.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags & float_flag_invalid); + update_fpu_flags(env, flags & float_flag_invalid, GETPC()); return r; } @@ -321,7 +264,7 @@ uint32_t helper_fcmp_le(CPUMBState *env, uint32_t a, uint32_t b) set_float_exception_flags(0, &env->fp_status); r = float32_le(fa.f, fb.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags & float_flag_invalid); + update_fpu_flags(env, flags & float_flag_invalid, GETPC()); return r; @@ -337,7 +280,7 @@ uint32_t helper_fcmp_gt(CPUMBState *env, uint32_t a, uint32_t b) set_float_exception_flags(0, &env->fp_status); r = float32_lt(fa.f, fb.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags & float_flag_invalid); + update_fpu_flags(env, flags & float_flag_invalid, GETPC()); return r; } @@ -351,7 +294,7 @@ uint32_t helper_fcmp_ne(CPUMBState *env, uint32_t a, uint32_t b) set_float_exception_flags(0, &env->fp_status); r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags & float_flag_invalid); + update_fpu_flags(env, flags & float_flag_invalid, GETPC()); return r; } @@ -366,7 +309,7 @@ uint32_t helper_fcmp_ge(CPUMBState *env, uint32_t a, uint32_t b) set_float_exception_flags(0, &env->fp_status); r = !float32_lt(fa.f, fb.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags & float_flag_invalid); + update_fpu_flags(env, flags & float_flag_invalid, GETPC()); return r; } @@ -390,7 +333,7 @@ uint32_t helper_fint(CPUMBState *env, uint32_t a) fa.l = a; r = float32_to_int32(fa.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags); + update_fpu_flags(env, flags, GETPC()); return r; } @@ -404,7 +347,7 @@ uint32_t helper_fsqrt(CPUMBState *env, uint32_t a) fa.l = a; fd.l = float32_sqrt(fa.f, &env->fp_status); flags = get_float_exception_flags(&env->fp_status); - update_fpu_flags(env, flags); + update_fpu_flags(env, flags, GETPC()); return fd.l; } @@ -422,37 +365,19 @@ uint32_t helper_pcmpbf(uint32_t a, uint32_t b) return 0; } -void helper_memalign(CPUMBState *env, target_ulong addr, - uint32_t dr, uint32_t wr, - uint32_t mask) -{ - if (addr & mask) { - qemu_log_mask(CPU_LOG_INT, - "unaligned access addr=" TARGET_FMT_lx - " mask=%x, wr=%d dr=r%d\n", - addr, mask, wr, dr); - env->sregs[SR_EAR] = addr; - env->sregs[SR_ESR] = ESR_EC_UNALIGNED_DATA | (wr << 10) \ - | (dr & 31) << 5; - if (mask == 3) { - env->sregs[SR_ESR] |= 1 << 11; - } - if (!(env->sregs[SR_MSR] & MSR_EE)) { - return; - } - helper_raise_exception(env, EXCP_HW_EXCP); - } -} - void helper_stackprot(CPUMBState *env, target_ulong addr) { if (addr < env->slr || addr > env->shr) { + CPUState *cs = env_cpu(env); + qemu_log_mask(CPU_LOG_INT, "Stack protector violation at " TARGET_FMT_lx " %x %x\n", addr, env->slr, env->shr); - env->sregs[SR_EAR] = addr; - env->sregs[SR_ESR] = ESR_EC_STACKPROT; - helper_raise_exception(env, EXCP_HW_EXCP); + + env->ear = addr; + env->esr = ESR_EC_STACKPROT; + cs->exception_index = EXCP_HW_EXCP; + cpu_loop_exit_restore(cs, GETPC()); } } @@ -473,32 +398,33 @@ void mb_cpu_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr, int mmu_idx, MemTxAttrs attrs, MemTxResult response, uintptr_t retaddr) { - MicroBlazeCPU *cpu; - CPUMBState *env; + MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); + CPUMBState *env = &cpu->env; + qemu_log_mask(CPU_LOG_INT, "Transaction failed: vaddr 0x%" VADDR_PRIx " physaddr 0x" TARGET_FMT_plx " size %d access type %s\n", addr, physaddr, size, access_type == MMU_INST_FETCH ? "INST_FETCH" : (access_type == MMU_DATA_LOAD ? "DATA_LOAD" : "DATA_STORE")); - cpu = MICROBLAZE_CPU(cs); - env = &cpu->env; - cpu_restore_state(cs, retaddr, true); - if (!(env->sregs[SR_MSR] & MSR_EE)) { + if (!(env->msr & MSR_EE)) { return; } - env->sregs[SR_EAR] = addr; if (access_type == MMU_INST_FETCH) { - if ((env->pvr.regs[2] & PVR2_IOPB_BUS_EXC_MASK)) { - env->sregs[SR_ESR] = ESR_EC_INSN_BUS; - helper_raise_exception(env, EXCP_HW_EXCP); + if (!cpu->cfg.iopb_bus_exception) { + return; } + env->esr = ESR_EC_INSN_BUS; } else { - if ((env->pvr.regs[2] & PVR2_DOPB_BUS_EXC_MASK)) { - env->sregs[SR_ESR] = ESR_EC_DATA_BUS; - helper_raise_exception(env, EXCP_HW_EXCP); + if (!cpu->cfg.dopb_bus_exception) { + return; } + env->esr = ESR_EC_DATA_BUS; } + + env->ear = addr; + cs->exception_index = EXCP_HW_EXCP; + cpu_loop_exit_restore(cs, retaddr); } #endif diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c index f6ff2591c35609e779546c58afb2f6ab6ef98326..c1b13f4c7d3d34bfb5b1e455c7e3924717e21d6c 100644 --- a/target/microblaze/translate.c +++ b/target/microblaze/translate.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -24,7 +24,6 @@ #include "exec/exec-all.h" #include "tcg/tcg-op.h" #include "exec/helper-proto.h" -#include "microblaze-decode.h" #include "exec/cpu_ldst.h" #include "exec/helper-gen.h" #include "exec/translator.h" @@ -33,106 +32,103 @@ #include "trace-tcg.h" #include "exec/log.h" - -#define SIM_COMPAT 0 -#define DISAS_GNU 1 -#define DISAS_MB 1 -#if DISAS_MB && !SIM_COMPAT -# define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__) -#else -# define LOG_DIS(...) do { } while (0) -#endif - -#define D(x) - #define EXTRACT_FIELD(src, start, end) \ (((src) >> start) & ((1 << (end - start + 1)) - 1)) /* is_jmp field values */ #define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */ -#define DISAS_UPDATE DISAS_TARGET_1 /* cpu state was modified dynamically */ -#define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */ +#define DISAS_EXIT DISAS_TARGET_1 /* all cpu state modified dynamically */ + +/* cpu state besides pc was modified dynamically; update pc to next */ +#define DISAS_EXIT_NEXT DISAS_TARGET_2 +/* cpu state besides pc was modified dynamically; update pc to btarget */ +#define DISAS_EXIT_JUMP DISAS_TARGET_3 -static TCGv_i32 env_debug; static TCGv_i32 cpu_R[32]; -static TCGv_i64 cpu_SR[14]; -static TCGv_i32 env_imm; -static TCGv_i32 env_btaken; -static TCGv_i64 env_btarget; -static TCGv_i32 env_iflags; -static TCGv env_res_addr; -static TCGv_i32 env_res_val; +static TCGv_i32 cpu_pc; +static TCGv_i32 cpu_msr; +static TCGv_i32 cpu_msr_c; +static TCGv_i32 cpu_imm; +static TCGv_i32 cpu_bvalue; +static TCGv_i32 cpu_btarget; +static TCGv_i32 cpu_iflags; +static TCGv cpu_res_addr; +static TCGv_i32 cpu_res_val; #include "exec/gen-icount.h" /* This is the state at translation time. */ typedef struct DisasContext { - MicroBlazeCPU *cpu; - uint32_t pc; + DisasContextBase base; + const MicroBlazeCPUConfig *cfg; + + /* TCG op of the current insn_start. */ + TCGOp *insn_start; + + TCGv_i32 r0; + bool r0_set; /* Decoder. */ - int type_b; - uint32_t ir; - uint8_t opcode; - uint8_t rd, ra, rb; - uint16_t imm; - - unsigned int cpustate_changed; - unsigned int delayed_branch; - unsigned int tb_flags, synced_flags; /* tb dependent flags. */ - unsigned int clear_imm; - int is_jmp; - -#define JMP_NOJMP 0 -#define JMP_DIRECT 1 -#define JMP_DIRECT_CC 2 -#define JMP_INDIRECT 3 - unsigned int jmp; - uint32_t jmp_pc; - - int abort_at_next_insn; - struct TranslationBlock *tb; - int singlestep_enabled; + uint32_t ext_imm; + unsigned int tb_flags; + unsigned int tb_flags_to_set; + int mem_index; + + /* Condition under which to jump, including NEVER and ALWAYS. */ + TCGCond jmp_cond; + + /* Immediate branch-taken destination, or -1 for indirect. */ + uint32_t jmp_dest; } DisasContext; -static const char *regnames[] = +static int typeb_imm(DisasContext *dc, int x) { - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", - "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", -}; + if (dc->tb_flags & IMM_FLAG) { + return deposit32(dc->ext_imm, 0, 16, x); + } + return x; +} -static const char *special_regnames[] = -{ - "rpc", "rmsr", "sr2", "rear", "sr4", "resr", "sr6", "rfsr", - "sr8", "sr9", "sr10", "rbtr", "sr12", "redr" -}; +/* Include the auto-generated decoder. */ +#include "decode-insns.c.inc" -static inline void t_sync_flags(DisasContext *dc) +static void t_sync_flags(DisasContext *dc) { /* Synch the tb dependent flags between translator and runtime. */ - if (dc->tb_flags != dc->synced_flags) { - tcg_gen_movi_i32(env_iflags, dc->tb_flags); - dc->synced_flags = dc->tb_flags; + if ((dc->tb_flags ^ dc->base.tb->flags) & IFLAGS_TB_MASK) { + tcg_gen_movi_i32(cpu_iflags, dc->tb_flags & IFLAGS_TB_MASK); } } -static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index) +static void gen_raise_exception(DisasContext *dc, uint32_t index) { TCGv_i32 tmp = tcg_const_i32(index); - t_sync_flags(dc); - tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc); gen_helper_raise_exception(cpu_env, tmp); tcg_temp_free_i32(tmp); - dc->is_jmp = DISAS_UPDATE; + dc->base.is_jmp = DISAS_NORETURN; +} + +static void gen_raise_exception_sync(DisasContext *dc, uint32_t index) +{ + t_sync_flags(dc); + tcg_gen_movi_i32(cpu_pc, dc->base.pc_next); + gen_raise_exception(dc, index); +} + +static void gen_raise_hw_excp(DisasContext *dc, uint32_t esr_ec) +{ + TCGv_i32 tmp = tcg_const_i32(esr_ec); + tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUMBState, esr)); + tcg_temp_free_i32(tmp); + + gen_raise_exception_sync(dc, EXCP_HW_EXCP); } static inline bool use_goto_tb(DisasContext *dc, target_ulong dest) { #ifndef CONFIG_USER_ONLY - return (dc->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); + return (dc->base.pc_first & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); #else return true; #endif @@ -140,42 +136,20 @@ static inline bool use_goto_tb(DisasContext *dc, target_ulong dest) static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) { - if (use_goto_tb(dc, dest)) { + if (dc->base.singlestep_enabled) { + TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG); + tcg_gen_movi_i32(cpu_pc, dest); + gen_helper_raise_exception(cpu_env, tmp); + tcg_temp_free_i32(tmp); + } else if (use_goto_tb(dc, dest)) { tcg_gen_goto_tb(n); - tcg_gen_movi_i64(cpu_SR[SR_PC], dest); - tcg_gen_exit_tb(dc->tb, n); + tcg_gen_movi_i32(cpu_pc, dest); + tcg_gen_exit_tb(dc->base.tb, n); } else { - tcg_gen_movi_i64(cpu_SR[SR_PC], dest); - tcg_gen_exit_tb(NULL, 0); + tcg_gen_movi_i32(cpu_pc, dest); + tcg_gen_lookup_and_goto_ptr(); } -} - -static void read_carry(DisasContext *dc, TCGv_i32 d) -{ - tcg_gen_extrl_i64_i32(d, cpu_SR[SR_MSR]); - tcg_gen_shri_i32(d, d, 31); -} - -/* - * write_carry sets the carry bits in MSR based on bit 0 of v. - * v[31:1] are ignored. - */ -static void write_carry(DisasContext *dc, TCGv_i32 v) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - tcg_gen_extu_i32_i64(t0, v); - /* Deposit bit 0 into MSR_C and the alias MSR_CC. */ - tcg_gen_deposit_i64(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0, 2, 1); - tcg_gen_deposit_i64(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0, 31, 1); - tcg_temp_free_i64(t0); -} - -static void write_carryi(DisasContext *dc, bool carry) -{ - TCGv_i32 t0 = tcg_temp_new_i32(); - tcg_gen_movi_i32(t0, carry); - write_carry(dc, t0); - tcg_temp_free_i32(t0); + dc->base.is_jmp = DISAS_NORETURN; } /* @@ -184,10 +158,9 @@ static void write_carryi(DisasContext *dc, bool carry) */ static bool trap_illegal(DisasContext *dc, bool cond) { - if (cond && (dc->tb_flags & MSR_EE_FLAG) - && dc->cpu->cfg.illegal_opcode_exception) { - tcg_gen_movi_i64(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); + if (cond && (dc->tb_flags & MSR_EE) + && dc->cfg->illegal_opcode_exception) { + gen_raise_hw_excp(dc, ESR_EC_ILLEGAL_OP); } return cond; } @@ -198,759 +171,589 @@ static bool trap_illegal(DisasContext *dc, bool cond) */ static bool trap_userspace(DisasContext *dc, bool cond) { - int mem_index = cpu_mmu_index(&dc->cpu->env, false); - bool cond_user = cond && mem_index == MMU_USER_IDX; + bool cond_user = cond && dc->mem_index == MMU_USER_IDX; - if (cond_user && (dc->tb_flags & MSR_EE_FLAG)) { - tcg_gen_movi_i64(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); + if (cond_user && (dc->tb_flags & MSR_EE)) { + gen_raise_hw_excp(dc, ESR_EC_PRIVINSN); } return cond_user; } -/* True if ALU operand b is a small immediate that may deserve - faster treatment. */ -static inline int dec_alu_op_b_is_small_imm(DisasContext *dc) +/* + * Return true, and log an error, if the current insn is + * within a delay slot. + */ +static bool invalid_delay_slot(DisasContext *dc, const char *insn_type) { - /* Immediate insn without the imm prefix ? */ - return dc->type_b && !(dc->tb_flags & IMM_FLAG); + if (dc->tb_flags & D_FLAG) { + qemu_log_mask(LOG_GUEST_ERROR, + "Invalid insn in delay slot: %s at %08x\n", + insn_type, (uint32_t)dc->base.pc_next); + return true; + } + return false; } -static inline TCGv_i32 *dec_alu_op_b(DisasContext *dc) +static TCGv_i32 reg_for_read(DisasContext *dc, int reg) { - if (dc->type_b) { - if (dc->tb_flags & IMM_FLAG) - tcg_gen_ori_i32(env_imm, env_imm, dc->imm); - else - tcg_gen_movi_i32(env_imm, (int32_t)((int16_t)dc->imm)); - return &env_imm; - } else - return &cpu_R[dc->rb]; + if (likely(reg != 0)) { + return cpu_R[reg]; + } + if (!dc->r0_set) { + if (dc->r0 == NULL) { + dc->r0 = tcg_temp_new_i32(); + } + tcg_gen_movi_i32(dc->r0, 0); + dc->r0_set = true; + } + return dc->r0; } -static void dec_add(DisasContext *dc) +static TCGv_i32 reg_for_write(DisasContext *dc, int reg) { - unsigned int k, c; - TCGv_i32 cf; + if (likely(reg != 0)) { + return cpu_R[reg]; + } + if (dc->r0 == NULL) { + dc->r0 = tcg_temp_new_i32(); + } + return dc->r0; +} - k = dc->opcode & 4; - c = dc->opcode & 2; +static bool do_typea(DisasContext *dc, arg_typea *arg, bool side_effects, + void (*fn)(TCGv_i32, TCGv_i32, TCGv_i32)) +{ + TCGv_i32 rd, ra, rb; - LOG_DIS("add%s%s%s r%d r%d r%d\n", - dc->type_b ? "i" : "", k ? "k" : "", c ? "c" : "", - dc->rd, dc->ra, dc->rb); + if (arg->rd == 0 && !side_effects) { + return true; + } - /* Take care of the easy cases first. */ - if (k) { - /* k - keep carry, no need to update MSR. */ - /* If rd == r0, it's a nop. */ - if (dc->rd) { - tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); + rd = reg_for_write(dc, arg->rd); + ra = reg_for_read(dc, arg->ra); + rb = reg_for_read(dc, arg->rb); + fn(rd, ra, rb); + return true; +} - if (c) { - /* c - Add carry into the result. */ - cf = tcg_temp_new_i32(); +static bool do_typea0(DisasContext *dc, arg_typea0 *arg, bool side_effects, + void (*fn)(TCGv_i32, TCGv_i32)) +{ + TCGv_i32 rd, ra; - read_carry(dc, cf); - tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->rd], cf); - tcg_temp_free_i32(cf); - } - } - return; + if (arg->rd == 0 && !side_effects) { + return true; } - /* From now on, we can assume k is zero. So we need to update MSR. */ - /* Extract carry. */ - cf = tcg_temp_new_i32(); - if (c) { - read_carry(dc, cf); - } else { - tcg_gen_movi_i32(cf, 0); - } + rd = reg_for_write(dc, arg->rd); + ra = reg_for_read(dc, arg->ra); + fn(rd, ra); + return true; +} - if (dc->rd) { - TCGv_i32 ncf = tcg_temp_new_i32(); - gen_helper_carry(ncf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf); - tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); - tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->rd], cf); - write_carry(dc, ncf); - tcg_temp_free_i32(ncf); - } else { - gen_helper_carry(cf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf); - write_carry(dc, cf); +static bool do_typeb_imm(DisasContext *dc, arg_typeb *arg, bool side_effects, + void (*fni)(TCGv_i32, TCGv_i32, int32_t)) +{ + TCGv_i32 rd, ra; + + if (arg->rd == 0 && !side_effects) { + return true; } - tcg_temp_free_i32(cf); + + rd = reg_for_write(dc, arg->rd); + ra = reg_for_read(dc, arg->ra); + fni(rd, ra, arg->imm); + return true; } -static void dec_sub(DisasContext *dc) +static bool do_typeb_val(DisasContext *dc, arg_typeb *arg, bool side_effects, + void (*fn)(TCGv_i32, TCGv_i32, TCGv_i32)) { - unsigned int u, cmp, k, c; - TCGv_i32 cf, na; - - u = dc->imm & 2; - k = dc->opcode & 4; - c = dc->opcode & 2; - cmp = (dc->imm & 1) && (!dc->type_b) && k; + TCGv_i32 rd, ra, imm; - if (cmp) { - LOG_DIS("cmp%s r%d, r%d ir=%x\n", u ? "u" : "", dc->rd, dc->ra, dc->ir); - if (dc->rd) { - if (u) - gen_helper_cmpu(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); - else - gen_helper_cmp(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); - } - return; + if (arg->rd == 0 && !side_effects) { + return true; } - LOG_DIS("sub%s%s r%d, r%d r%d\n", - k ? "k" : "", c ? "c" : "", dc->rd, dc->ra, dc->rb); + rd = reg_for_write(dc, arg->rd); + ra = reg_for_read(dc, arg->ra); + imm = tcg_const_i32(arg->imm); - /* Take care of the easy cases first. */ - if (k) { - /* k - keep carry, no need to update MSR. */ - /* If rd == r0, it's a nop. */ - if (dc->rd) { - tcg_gen_sub_i32(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]); + fn(rd, ra, imm); - if (c) { - /* c - Add carry into the result. */ - cf = tcg_temp_new_i32(); + tcg_temp_free_i32(imm); + return true; +} - read_carry(dc, cf); - tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->rd], cf); - tcg_temp_free_i32(cf); - } - } - return; - } +#define DO_TYPEA(NAME, SE, FN) \ + static bool trans_##NAME(DisasContext *dc, arg_typea *a) \ + { return do_typea(dc, a, SE, FN); } - /* From now on, we can assume k is zero. So we need to update MSR. */ - /* Extract carry. And complement a into na. */ - cf = tcg_temp_new_i32(); - na = tcg_temp_new_i32(); - if (c) { - read_carry(dc, cf); - } else { - tcg_gen_movi_i32(cf, 1); - } +#define DO_TYPEA_CFG(NAME, CFG, SE, FN) \ + static bool trans_##NAME(DisasContext *dc, arg_typea *a) \ + { return dc->cfg->CFG && do_typea(dc, a, SE, FN); } - /* d = b + ~a + c. carry defaults to 1. */ - tcg_gen_not_i32(na, cpu_R[dc->ra]); +#define DO_TYPEA0(NAME, SE, FN) \ + static bool trans_##NAME(DisasContext *dc, arg_typea0 *a) \ + { return do_typea0(dc, a, SE, FN); } - if (dc->rd) { - TCGv_i32 ncf = tcg_temp_new_i32(); - gen_helper_carry(ncf, na, *(dec_alu_op_b(dc)), cf); - tcg_gen_add_i32(cpu_R[dc->rd], na, *(dec_alu_op_b(dc))); - tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->rd], cf); - write_carry(dc, ncf); - tcg_temp_free_i32(ncf); - } else { - gen_helper_carry(cf, na, *(dec_alu_op_b(dc)), cf); - write_carry(dc, cf); - } - tcg_temp_free_i32(cf); - tcg_temp_free_i32(na); -} +#define DO_TYPEA0_CFG(NAME, CFG, SE, FN) \ + static bool trans_##NAME(DisasContext *dc, arg_typea0 *a) \ + { return dc->cfg->CFG && do_typea0(dc, a, SE, FN); } -static void dec_pattern(DisasContext *dc) -{ - unsigned int mode; +#define DO_TYPEBI(NAME, SE, FNI) \ + static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \ + { return do_typeb_imm(dc, a, SE, FNI); } - if (trap_illegal(dc, !dc->cpu->cfg.use_pcmp_instr)) { - return; - } +#define DO_TYPEBI_CFG(NAME, CFG, SE, FNI) \ + static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \ + { return dc->cfg->CFG && do_typeb_imm(dc, a, SE, FNI); } - mode = dc->opcode & 3; - switch (mode) { - case 0: - /* pcmpbf. */ - LOG_DIS("pcmpbf r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - if (dc->rd) - gen_helper_pcmpbf(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 2: - LOG_DIS("pcmpeq r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - if (dc->rd) { - tcg_gen_setcond_i32(TCG_COND_EQ, cpu_R[dc->rd], - cpu_R[dc->ra], cpu_R[dc->rb]); - } - break; - case 3: - LOG_DIS("pcmpne r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - if (dc->rd) { - tcg_gen_setcond_i32(TCG_COND_NE, cpu_R[dc->rd], - cpu_R[dc->ra], cpu_R[dc->rb]); - } - break; - default: - cpu_abort(CPU(dc->cpu), - "unsupported pattern insn opcode=%x\n", dc->opcode); - break; - } -} +#define DO_TYPEBV(NAME, SE, FN) \ + static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \ + { return do_typeb_val(dc, a, SE, FN); } -static void dec_and(DisasContext *dc) -{ - unsigned int not; +#define ENV_WRAPPER2(NAME, HELPER) \ + static void NAME(TCGv_i32 out, TCGv_i32 ina) \ + { HELPER(out, cpu_env, ina); } - if (!dc->type_b && (dc->imm & (1 << 10))) { - dec_pattern(dc); - return; - } +#define ENV_WRAPPER3(NAME, HELPER) \ + static void NAME(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) \ + { HELPER(out, cpu_env, ina, inb); } - not = dc->opcode & (1 << 1); - LOG_DIS("and%s\n", not ? "n" : ""); +/* No input carry, but output carry. */ +static void gen_add(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) +{ + TCGv_i32 zero = tcg_const_i32(0); - if (!dc->rd) - return; + tcg_gen_add2_i32(out, cpu_msr_c, ina, zero, inb, zero); - if (not) { - tcg_gen_andc_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); - } else - tcg_gen_and_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); + tcg_temp_free_i32(zero); } -static void dec_or(DisasContext *dc) +/* Input and output carry. */ +static void gen_addc(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) { - if (!dc->type_b && (dc->imm & (1 << 10))) { - dec_pattern(dc); - return; - } + TCGv_i32 zero = tcg_const_i32(0); + TCGv_i32 tmp = tcg_temp_new_i32(); - LOG_DIS("or r%d r%d r%d imm=%x\n", dc->rd, dc->ra, dc->rb, dc->imm); - if (dc->rd) - tcg_gen_or_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); + tcg_gen_add2_i32(tmp, cpu_msr_c, ina, zero, cpu_msr_c, zero); + tcg_gen_add2_i32(out, cpu_msr_c, tmp, cpu_msr_c, inb, zero); + + tcg_temp_free_i32(tmp); + tcg_temp_free_i32(zero); } -static void dec_xor(DisasContext *dc) +/* Input carry, but no output carry. */ +static void gen_addkc(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) { - if (!dc->type_b && (dc->imm & (1 << 10))) { - dec_pattern(dc); - return; - } - - LOG_DIS("xor r%d\n", dc->rd); - if (dc->rd) - tcg_gen_xor_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); + tcg_gen_add_i32(out, ina, inb); + tcg_gen_add_i32(out, out, cpu_msr_c); } -static inline void msr_read(DisasContext *dc, TCGv_i32 d) +DO_TYPEA(add, true, gen_add) +DO_TYPEA(addc, true, gen_addc) +DO_TYPEA(addk, false, tcg_gen_add_i32) +DO_TYPEA(addkc, true, gen_addkc) + +DO_TYPEBV(addi, true, gen_add) +DO_TYPEBV(addic, true, gen_addc) +DO_TYPEBI(addik, false, tcg_gen_addi_i32) +DO_TYPEBV(addikc, true, gen_addkc) + +static void gen_andni(TCGv_i32 out, TCGv_i32 ina, int32_t imm) { - tcg_gen_extrl_i64_i32(d, cpu_SR[SR_MSR]); + tcg_gen_andi_i32(out, ina, ~imm); } -static inline void msr_write(DisasContext *dc, TCGv_i32 v) +DO_TYPEA(and, false, tcg_gen_and_i32) +DO_TYPEBI(andi, false, tcg_gen_andi_i32) +DO_TYPEA(andn, false, tcg_gen_andc_i32) +DO_TYPEBI(andni, false, gen_andni) + +static void gen_bsra(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) { - TCGv_i64 t; + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_andi_i32(tmp, inb, 31); + tcg_gen_sar_i32(out, ina, tmp); + tcg_temp_free_i32(tmp); +} - t = tcg_temp_new_i64(); - dc->cpustate_changed = 1; - /* PVR bit is not writable. */ - tcg_gen_extu_i32_i64(t, v); - tcg_gen_andi_i64(t, t, ~MSR_PVR); - tcg_gen_andi_i64(cpu_SR[SR_MSR], cpu_SR[SR_MSR], MSR_PVR); - tcg_gen_or_i64(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t); - tcg_temp_free_i64(t); +static void gen_bsrl(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) +{ + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_andi_i32(tmp, inb, 31); + tcg_gen_shr_i32(out, ina, tmp); + tcg_temp_free_i32(tmp); } -static void dec_msr(DisasContext *dc) +static void gen_bsll(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) { - CPUState *cs = CPU(dc->cpu); - TCGv_i32 t0, t1; - unsigned int sr, rn; - bool to, clrset, extended = false; + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_andi_i32(tmp, inb, 31); + tcg_gen_shl_i32(out, ina, tmp); + tcg_temp_free_i32(tmp); +} - sr = extract32(dc->imm, 0, 14); - to = extract32(dc->imm, 14, 1); - clrset = extract32(dc->imm, 15, 1) == 0; - dc->type_b = 1; - if (to) { - dc->cpustate_changed = 1; +static void gen_bsefi(TCGv_i32 out, TCGv_i32 ina, int32_t imm) +{ + /* Note that decodetree has extracted and reassembled imm_w/imm_s. */ + int imm_w = extract32(imm, 5, 5); + int imm_s = extract32(imm, 0, 5); + + if (imm_w + imm_s > 32 || imm_w == 0) { + /* These inputs have an undefined behavior. */ + qemu_log_mask(LOG_GUEST_ERROR, "bsefi: Bad input w=%d s=%d\n", + imm_w, imm_s); + } else { + tcg_gen_extract_i32(out, ina, imm_s, imm_w); } +} - /* Extended MSRs are only available if addr_size > 32. */ - if (dc->cpu->cfg.addr_size > 32) { - /* The E-bit is encoded differently for To/From MSR. */ - static const unsigned int e_bit[] = { 19, 24 }; - - extended = extract32(dc->imm, e_bit[to], 1); +static void gen_bsifi(TCGv_i32 out, TCGv_i32 ina, int32_t imm) +{ + /* Note that decodetree has extracted and reassembled imm_w/imm_s. */ + int imm_w = extract32(imm, 5, 5); + int imm_s = extract32(imm, 0, 5); + int width = imm_w - imm_s + 1; + + if (imm_w < imm_s) { + /* These inputs have an undefined behavior. */ + qemu_log_mask(LOG_GUEST_ERROR, "bsifi: Bad input w=%d s=%d\n", + imm_w, imm_s); + } else { + tcg_gen_deposit_i32(out, out, ina, imm_s, width); } +} - /* msrclr and msrset. */ - if (clrset) { - bool clr = extract32(dc->ir, 16, 1); - - LOG_DIS("msr%s r%d imm=%x\n", clr ? "clr" : "set", - dc->rd, dc->imm); +DO_TYPEA_CFG(bsra, use_barrel, false, gen_bsra) +DO_TYPEA_CFG(bsrl, use_barrel, false, gen_bsrl) +DO_TYPEA_CFG(bsll, use_barrel, false, gen_bsll) - if (!dc->cpu->cfg.use_msr_instr) { - /* nop??? */ - return; - } +DO_TYPEBI_CFG(bsrai, use_barrel, false, tcg_gen_sari_i32) +DO_TYPEBI_CFG(bsrli, use_barrel, false, tcg_gen_shri_i32) +DO_TYPEBI_CFG(bslli, use_barrel, false, tcg_gen_shli_i32) - if (trap_userspace(dc, dc->imm != 4 && dc->imm != 0)) { - return; - } +DO_TYPEBI_CFG(bsefi, use_barrel, false, gen_bsefi) +DO_TYPEBI_CFG(bsifi, use_barrel, false, gen_bsifi) - if (dc->rd) - msr_read(dc, cpu_R[dc->rd]); - - t0 = tcg_temp_new_i32(); - t1 = tcg_temp_new_i32(); - msr_read(dc, t0); - tcg_gen_mov_i32(t1, *(dec_alu_op_b(dc))); - - if (clr) { - tcg_gen_not_i32(t1, t1); - tcg_gen_and_i32(t0, t0, t1); - } else - tcg_gen_or_i32(t0, t0, t1); - msr_write(dc, t0); - tcg_temp_free_i32(t0); - tcg_temp_free_i32(t1); - tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc + 4); - dc->is_jmp = DISAS_UPDATE; - return; - } +static void gen_clz(TCGv_i32 out, TCGv_i32 ina) +{ + tcg_gen_clzi_i32(out, ina, 32); +} - if (trap_userspace(dc, to)) { - return; - } +DO_TYPEA0_CFG(clz, use_pcmp_instr, false, gen_clz) -#if !defined(CONFIG_USER_ONLY) - /* Catch read/writes to the mmu block. */ - if ((sr & ~0xff) == 0x1000) { - TCGv_i32 tmp_ext = tcg_const_i32(extended); - TCGv_i32 tmp_sr; +static void gen_cmp(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) +{ + TCGv_i32 lt = tcg_temp_new_i32(); - sr &= 7; - tmp_sr = tcg_const_i32(sr); - LOG_DIS("m%ss sr%d r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm); - if (to) { - gen_helper_mmu_write(cpu_env, tmp_ext, tmp_sr, cpu_R[dc->ra]); - } else { - gen_helper_mmu_read(cpu_R[dc->rd], cpu_env, tmp_ext, tmp_sr); - } - tcg_temp_free_i32(tmp_sr); - tcg_temp_free_i32(tmp_ext); - return; - } -#endif + tcg_gen_setcond_i32(TCG_COND_LT, lt, inb, ina); + tcg_gen_sub_i32(out, inb, ina); + tcg_gen_deposit_i32(out, out, lt, 31, 1); + tcg_temp_free_i32(lt); +} - if (to) { - LOG_DIS("m%ss sr%x r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm); - switch (sr) { - case 0: - break; - case 1: - msr_write(dc, cpu_R[dc->ra]); - break; - case SR_EAR: - case SR_ESR: - case SR_FSR: - tcg_gen_extu_i32_i64(cpu_SR[sr], cpu_R[dc->ra]); - break; - case 0x800: - tcg_gen_st_i32(cpu_R[dc->ra], - cpu_env, offsetof(CPUMBState, slr)); - break; - case 0x802: - tcg_gen_st_i32(cpu_R[dc->ra], - cpu_env, offsetof(CPUMBState, shr)); - break; - default: - cpu_abort(CPU(dc->cpu), "unknown mts reg %x\n", sr); - break; - } - } else { - LOG_DIS("m%ss r%d sr%x imm=%x\n", to ? "t" : "f", dc->rd, sr, dc->imm); - - switch (sr) { - case 0: - tcg_gen_movi_i32(cpu_R[dc->rd], dc->pc); - break; - case 1: - msr_read(dc, cpu_R[dc->rd]); - break; - case SR_EAR: - if (extended) { - tcg_gen_extrh_i64_i32(cpu_R[dc->rd], cpu_SR[sr]); - break; - } - case SR_ESR: - case SR_FSR: - case SR_BTR: - case SR_EDR: - tcg_gen_extrl_i64_i32(cpu_R[dc->rd], cpu_SR[sr]); - break; - case 0x800: - tcg_gen_ld_i32(cpu_R[dc->rd], - cpu_env, offsetof(CPUMBState, slr)); - break; - case 0x802: - tcg_gen_ld_i32(cpu_R[dc->rd], - cpu_env, offsetof(CPUMBState, shr)); - break; - case 0x2000 ... 0x200c: - rn = sr & 0xf; - tcg_gen_ld_i32(cpu_R[dc->rd], - cpu_env, offsetof(CPUMBState, pvr.regs[rn])); - break; - default: - cpu_abort(cs, "unknown mfs reg %x\n", sr); - break; - } - } +static void gen_cmpu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) +{ + TCGv_i32 lt = tcg_temp_new_i32(); - if (dc->rd == 0) { - tcg_gen_movi_i32(cpu_R[0], 0); - } + tcg_gen_setcond_i32(TCG_COND_LTU, lt, inb, ina); + tcg_gen_sub_i32(out, inb, ina); + tcg_gen_deposit_i32(out, out, lt, 31, 1); + tcg_temp_free_i32(lt); } -/* Multiplier unit. */ -static void dec_mul(DisasContext *dc) +DO_TYPEA(cmp, false, gen_cmp) +DO_TYPEA(cmpu, false, gen_cmpu) + +ENV_WRAPPER3(gen_fadd, gen_helper_fadd) +ENV_WRAPPER3(gen_frsub, gen_helper_frsub) +ENV_WRAPPER3(gen_fmul, gen_helper_fmul) +ENV_WRAPPER3(gen_fdiv, gen_helper_fdiv) +ENV_WRAPPER3(gen_fcmp_un, gen_helper_fcmp_un) +ENV_WRAPPER3(gen_fcmp_lt, gen_helper_fcmp_lt) +ENV_WRAPPER3(gen_fcmp_eq, gen_helper_fcmp_eq) +ENV_WRAPPER3(gen_fcmp_le, gen_helper_fcmp_le) +ENV_WRAPPER3(gen_fcmp_gt, gen_helper_fcmp_gt) +ENV_WRAPPER3(gen_fcmp_ne, gen_helper_fcmp_ne) +ENV_WRAPPER3(gen_fcmp_ge, gen_helper_fcmp_ge) + +DO_TYPEA_CFG(fadd, use_fpu, true, gen_fadd) +DO_TYPEA_CFG(frsub, use_fpu, true, gen_frsub) +DO_TYPEA_CFG(fmul, use_fpu, true, gen_fmul) +DO_TYPEA_CFG(fdiv, use_fpu, true, gen_fdiv) +DO_TYPEA_CFG(fcmp_un, use_fpu, true, gen_fcmp_un) +DO_TYPEA_CFG(fcmp_lt, use_fpu, true, gen_fcmp_lt) +DO_TYPEA_CFG(fcmp_eq, use_fpu, true, gen_fcmp_eq) +DO_TYPEA_CFG(fcmp_le, use_fpu, true, gen_fcmp_le) +DO_TYPEA_CFG(fcmp_gt, use_fpu, true, gen_fcmp_gt) +DO_TYPEA_CFG(fcmp_ne, use_fpu, true, gen_fcmp_ne) +DO_TYPEA_CFG(fcmp_ge, use_fpu, true, gen_fcmp_ge) + +ENV_WRAPPER2(gen_flt, gen_helper_flt) +ENV_WRAPPER2(gen_fint, gen_helper_fint) +ENV_WRAPPER2(gen_fsqrt, gen_helper_fsqrt) + +DO_TYPEA0_CFG(flt, use_fpu >= 2, true, gen_flt) +DO_TYPEA0_CFG(fint, use_fpu >= 2, true, gen_fint) +DO_TYPEA0_CFG(fsqrt, use_fpu >= 2, true, gen_fsqrt) + +/* Does not use ENV_WRAPPER3, because arguments are swapped as well. */ +static void gen_idiv(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) { - TCGv_i32 tmp; - unsigned int subcode; + gen_helper_divs(out, cpu_env, inb, ina); +} - if (trap_illegal(dc, !dc->cpu->cfg.use_hw_mul)) { - return; - } +static void gen_idivu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) +{ + gen_helper_divu(out, cpu_env, inb, ina); +} - subcode = dc->imm & 3; +DO_TYPEA_CFG(idiv, use_div, true, gen_idiv) +DO_TYPEA_CFG(idivu, use_div, true, gen_idivu) - if (dc->type_b) { - LOG_DIS("muli r%d r%d %x\n", dc->rd, dc->ra, dc->imm); - tcg_gen_mul_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); - return; +static bool trans_imm(DisasContext *dc, arg_imm *arg) +{ + if (invalid_delay_slot(dc, "imm")) { + return true; } + dc->ext_imm = arg->imm << 16; + tcg_gen_movi_i32(cpu_imm, dc->ext_imm); + dc->tb_flags_to_set = IMM_FLAG; + return true; +} - /* mulh, mulhsu and mulhu are not available if C_USE_HW_MUL is < 2. */ - if (subcode >= 1 && subcode <= 3 && dc->cpu->cfg.use_hw_mul < 2) { - /* nop??? */ - } +static void gen_mulh(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) +{ + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_muls2_i32(tmp, out, ina, inb); + tcg_temp_free_i32(tmp); +} - tmp = tcg_temp_new_i32(); - switch (subcode) { - case 0: - LOG_DIS("mul r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - tcg_gen_mul_i32(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 1: - LOG_DIS("mulh r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - tcg_gen_muls2_i32(tmp, cpu_R[dc->rd], - cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 2: - LOG_DIS("mulhsu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - tcg_gen_mulsu2_i32(tmp, cpu_R[dc->rd], - cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 3: - LOG_DIS("mulhu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - tcg_gen_mulu2_i32(tmp, cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); - break; - default: - cpu_abort(CPU(dc->cpu), "unknown MUL insn %x\n", subcode); - break; - } +static void gen_mulhu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) +{ + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_mulu2_i32(tmp, out, ina, inb); tcg_temp_free_i32(tmp); } -/* Div unit. */ -static void dec_div(DisasContext *dc) +static void gen_mulhsu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) { - unsigned int u; + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_mulsu2_i32(tmp, out, ina, inb); + tcg_temp_free_i32(tmp); +} - u = dc->imm & 2; - LOG_DIS("div\n"); +DO_TYPEA_CFG(mul, use_hw_mul, false, tcg_gen_mul_i32) +DO_TYPEA_CFG(mulh, use_hw_mul >= 2, false, gen_mulh) +DO_TYPEA_CFG(mulhu, use_hw_mul >= 2, false, gen_mulhu) +DO_TYPEA_CFG(mulhsu, use_hw_mul >= 2, false, gen_mulhsu) +DO_TYPEBI_CFG(muli, use_hw_mul, false, tcg_gen_muli_i32) - if (trap_illegal(dc, !dc->cpu->cfg.use_div)) { - return; - } +DO_TYPEA(or, false, tcg_gen_or_i32) +DO_TYPEBI(ori, false, tcg_gen_ori_i32) - if (u) - gen_helper_divu(cpu_R[dc->rd], cpu_env, *(dec_alu_op_b(dc)), - cpu_R[dc->ra]); - else - gen_helper_divs(cpu_R[dc->rd], cpu_env, *(dec_alu_op_b(dc)), - cpu_R[dc->ra]); - if (!dc->rd) - tcg_gen_movi_i32(cpu_R[dc->rd], 0); +static void gen_pcmpeq(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) +{ + tcg_gen_setcond_i32(TCG_COND_EQ, out, ina, inb); } -static void dec_barrel(DisasContext *dc) +static void gen_pcmpne(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) { - TCGv_i32 t0; - unsigned int imm_w, imm_s; - bool s, t, e = false, i = false; - - if (trap_illegal(dc, !dc->cpu->cfg.use_barrel)) { - return; - } - - if (dc->type_b) { - /* Insert and extract are only available in immediate mode. */ - i = extract32(dc->imm, 15, 1); - e = extract32(dc->imm, 14, 1); - } - s = extract32(dc->imm, 10, 1); - t = extract32(dc->imm, 9, 1); - imm_w = extract32(dc->imm, 6, 5); - imm_s = extract32(dc->imm, 0, 5); + tcg_gen_setcond_i32(TCG_COND_NE, out, ina, inb); +} - LOG_DIS("bs%s%s%s r%d r%d r%d\n", - e ? "e" : "", - s ? "l" : "r", t ? "a" : "l", dc->rd, dc->ra, dc->rb); +DO_TYPEA_CFG(pcmpbf, use_pcmp_instr, false, gen_helper_pcmpbf) +DO_TYPEA_CFG(pcmpeq, use_pcmp_instr, false, gen_pcmpeq) +DO_TYPEA_CFG(pcmpne, use_pcmp_instr, false, gen_pcmpne) - if (e) { - if (imm_w + imm_s > 32 || imm_w == 0) { - /* These inputs have an undefined behavior. */ - qemu_log_mask(LOG_GUEST_ERROR, "bsefi: Bad input w=%d s=%d\n", - imm_w, imm_s); - } else { - tcg_gen_extract_i32(cpu_R[dc->rd], cpu_R[dc->ra], imm_s, imm_w); - } - } else if (i) { - int width = imm_w - imm_s + 1; +/* No input carry, but output carry. */ +static void gen_rsub(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) +{ + tcg_gen_setcond_i32(TCG_COND_GEU, cpu_msr_c, inb, ina); + tcg_gen_sub_i32(out, inb, ina); +} - if (imm_w < imm_s) { - /* These inputs have an undefined behavior. */ - qemu_log_mask(LOG_GUEST_ERROR, "bsifi: Bad input w=%d s=%d\n", - imm_w, imm_s); - } else { - tcg_gen_deposit_i32(cpu_R[dc->rd], cpu_R[dc->rd], cpu_R[dc->ra], - imm_s, width); - } - } else { - t0 = tcg_temp_new_i32(); +/* Input and output carry. */ +static void gen_rsubc(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) +{ + TCGv_i32 zero = tcg_const_i32(0); + TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_mov_i32(t0, *(dec_alu_op_b(dc))); - tcg_gen_andi_i32(t0, t0, 31); + tcg_gen_not_i32(tmp, ina); + tcg_gen_add2_i32(tmp, cpu_msr_c, tmp, zero, cpu_msr_c, zero); + tcg_gen_add2_i32(out, cpu_msr_c, tmp, cpu_msr_c, inb, zero); - if (s) { - tcg_gen_shl_i32(cpu_R[dc->rd], cpu_R[dc->ra], t0); - } else { - if (t) { - tcg_gen_sar_i32(cpu_R[dc->rd], cpu_R[dc->ra], t0); - } else { - tcg_gen_shr_i32(cpu_R[dc->rd], cpu_R[dc->ra], t0); - } - } - tcg_temp_free_i32(t0); - } + tcg_temp_free_i32(zero); + tcg_temp_free_i32(tmp); } -static void dec_bit(DisasContext *dc) +/* No input or output carry. */ +static void gen_rsubk(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) { - CPUState *cs = CPU(dc->cpu); - TCGv_i32 t0; - unsigned int op; + tcg_gen_sub_i32(out, inb, ina); +} - op = dc->ir & ((1 << 9) - 1); - switch (op) { - case 0x21: - /* src. */ - t0 = tcg_temp_new_i32(); +/* Input carry, no output carry. */ +static void gen_rsubkc(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) +{ + TCGv_i32 nota = tcg_temp_new_i32(); - LOG_DIS("src r%d r%d\n", dc->rd, dc->ra); - tcg_gen_extrl_i64_i32(t0, cpu_SR[SR_MSR]); - tcg_gen_andi_i32(t0, t0, MSR_CC); - write_carry(dc, cpu_R[dc->ra]); - if (dc->rd) { - tcg_gen_shri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 1); - tcg_gen_or_i32(cpu_R[dc->rd], cpu_R[dc->rd], t0); - } - tcg_temp_free_i32(t0); - break; + tcg_gen_not_i32(nota, ina); + tcg_gen_add_i32(out, inb, nota); + tcg_gen_add_i32(out, out, cpu_msr_c); - case 0x1: - case 0x41: - /* srl. */ - LOG_DIS("srl r%d r%d\n", dc->rd, dc->ra); - - /* Update carry. Note that write carry only looks at the LSB. */ - write_carry(dc, cpu_R[dc->ra]); - if (dc->rd) { - if (op == 0x41) - tcg_gen_shri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 1); - else - tcg_gen_sari_i32(cpu_R[dc->rd], cpu_R[dc->ra], 1); - } - break; - case 0x60: - LOG_DIS("ext8s r%d r%d\n", dc->rd, dc->ra); - tcg_gen_ext8s_i32(cpu_R[dc->rd], cpu_R[dc->ra]); - break; - case 0x61: - LOG_DIS("ext16s r%d r%d\n", dc->rd, dc->ra); - tcg_gen_ext16s_i32(cpu_R[dc->rd], cpu_R[dc->ra]); - break; - case 0x64: - case 0x66: - case 0x74: - case 0x76: - /* wdc. */ - LOG_DIS("wdc r%d\n", dc->ra); - trap_userspace(dc, true); - break; - case 0x68: - /* wic. */ - LOG_DIS("wic r%d\n", dc->ra); - trap_userspace(dc, true); - break; - case 0xe0: - if (trap_illegal(dc, !dc->cpu->cfg.use_pcmp_instr)) { - return; - } - if (dc->cpu->cfg.use_pcmp_instr) { - tcg_gen_clzi_i32(cpu_R[dc->rd], cpu_R[dc->ra], 32); - } - break; - case 0x1e0: - /* swapb */ - LOG_DIS("swapb r%d r%d\n", dc->rd, dc->ra); - tcg_gen_bswap32_i32(cpu_R[dc->rd], cpu_R[dc->ra]); - break; - case 0x1e2: - /*swaph */ - LOG_DIS("swaph r%d r%d\n", dc->rd, dc->ra); - tcg_gen_rotri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 16); - break; - default: - cpu_abort(cs, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n", - dc->pc, op, dc->rd, dc->ra, dc->rb); - break; - } + tcg_temp_free_i32(nota); } -static inline void sync_jmpstate(DisasContext *dc) +DO_TYPEA(rsub, true, gen_rsub) +DO_TYPEA(rsubc, true, gen_rsubc) +DO_TYPEA(rsubk, false, gen_rsubk) +DO_TYPEA(rsubkc, true, gen_rsubkc) + +DO_TYPEBV(rsubi, true, gen_rsub) +DO_TYPEBV(rsubic, true, gen_rsubc) +DO_TYPEBV(rsubik, false, gen_rsubk) +DO_TYPEBV(rsubikc, true, gen_rsubkc) + +DO_TYPEA0(sext8, false, tcg_gen_ext8s_i32) +DO_TYPEA0(sext16, false, tcg_gen_ext16s_i32) + +static void gen_sra(TCGv_i32 out, TCGv_i32 ina) { - if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) { - if (dc->jmp == JMP_DIRECT) { - tcg_gen_movi_i32(env_btaken, 1); - } - dc->jmp = JMP_INDIRECT; - tcg_gen_movi_i64(env_btarget, dc->jmp_pc); - } + tcg_gen_andi_i32(cpu_msr_c, ina, 1); + tcg_gen_sari_i32(out, ina, 1); } -static void dec_imm(DisasContext *dc) +static void gen_src(TCGv_i32 out, TCGv_i32 ina) { - LOG_DIS("imm %x\n", dc->imm << 16); - tcg_gen_movi_i32(env_imm, (dc->imm << 16)); - dc->tb_flags |= IMM_FLAG; - dc->clear_imm = 0; + TCGv_i32 tmp = tcg_temp_new_i32(); + + tcg_gen_mov_i32(tmp, cpu_msr_c); + tcg_gen_andi_i32(cpu_msr_c, ina, 1); + tcg_gen_extract2_i32(out, ina, tmp, 1); + + tcg_temp_free_i32(tmp); } -static inline void compute_ldst_addr(DisasContext *dc, bool ea, TCGv t) +static void gen_srl(TCGv_i32 out, TCGv_i32 ina) { - bool extimm = dc->tb_flags & IMM_FLAG; - /* Should be set to true if r1 is used by loadstores. */ - bool stackprot = false; - TCGv_i32 t32; - - /* All load/stores use ra. */ - if (dc->ra == 1 && dc->cpu->cfg.stackprot) { - stackprot = true; - } + tcg_gen_andi_i32(cpu_msr_c, ina, 1); + tcg_gen_shri_i32(out, ina, 1); +} - /* Treat the common cases first. */ - if (!dc->type_b) { - if (ea) { - int addr_size = dc->cpu->cfg.addr_size; +DO_TYPEA0(sra, false, gen_sra) +DO_TYPEA0(src, false, gen_src) +DO_TYPEA0(srl, false, gen_srl) - if (addr_size == 32) { - tcg_gen_extu_i32_tl(t, cpu_R[dc->rb]); - return; - } +static void gen_swaph(TCGv_i32 out, TCGv_i32 ina) +{ + tcg_gen_rotri_i32(out, ina, 16); +} - tcg_gen_concat_i32_i64(t, cpu_R[dc->rb], cpu_R[dc->ra]); - if (addr_size < 64) { - /* Mask off out of range bits. */ - tcg_gen_andi_i64(t, t, MAKE_64BIT_MASK(0, addr_size)); - } - return; - } +DO_TYPEA0(swapb, false, tcg_gen_bswap32_i32) +DO_TYPEA0(swaph, false, gen_swaph) - /* If any of the regs is r0, set t to the value of the other reg. */ - if (dc->ra == 0) { - tcg_gen_extu_i32_tl(t, cpu_R[dc->rb]); - return; - } else if (dc->rb == 0) { - tcg_gen_extu_i32_tl(t, cpu_R[dc->ra]); - return; - } +static bool trans_wdic(DisasContext *dc, arg_wdic *a) +{ + /* Cache operations are nops: only check for supervisor mode. */ + trap_userspace(dc, true); + return true; +} - if (dc->rb == 1 && dc->cpu->cfg.stackprot) { - stackprot = true; - } +DO_TYPEA(xor, false, tcg_gen_xor_i32) +DO_TYPEBI(xori, false, tcg_gen_xori_i32) - t32 = tcg_temp_new_i32(); - tcg_gen_add_i32(t32, cpu_R[dc->ra], cpu_R[dc->rb]); - tcg_gen_extu_i32_tl(t, t32); - tcg_temp_free_i32(t32); +static TCGv compute_ldst_addr_typea(DisasContext *dc, int ra, int rb) +{ + TCGv ret = tcg_temp_new(); - if (stackprot) { - gen_helper_stackprot(cpu_env, t); - } - return; - } - /* Immediate. */ - t32 = tcg_temp_new_i32(); - if (!extimm) { - tcg_gen_addi_i32(t32, cpu_R[dc->ra], (int16_t)dc->imm); + /* If any of the regs is r0, set t to the value of the other reg. */ + if (ra && rb) { + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_add_i32(tmp, cpu_R[ra], cpu_R[rb]); + tcg_gen_extu_i32_tl(ret, tmp); + tcg_temp_free_i32(tmp); + } else if (ra) { + tcg_gen_extu_i32_tl(ret, cpu_R[ra]); + } else if (rb) { + tcg_gen_extu_i32_tl(ret, cpu_R[rb]); } else { - tcg_gen_add_i32(t32, cpu_R[dc->ra], *(dec_alu_op_b(dc))); + tcg_gen_movi_tl(ret, 0); } - tcg_gen_extu_i32_tl(t, t32); - tcg_temp_free_i32(t32); - if (stackprot) { - gen_helper_stackprot(cpu_env, t); + if ((ra == 1 || rb == 1) && dc->cfg->stackprot) { + gen_helper_stackprot(cpu_env, ret); } - return; + return ret; } -static void dec_load(DisasContext *dc) +static TCGv compute_ldst_addr_typeb(DisasContext *dc, int ra, int imm) { - TCGv_i32 v; - TCGv addr; - unsigned int size; - bool rev = false, ex = false, ea = false; - int mem_index = cpu_mmu_index(&dc->cpu->env, false); - MemOp mop; + TCGv ret = tcg_temp_new(); - mop = dc->opcode & 3; - size = 1 << mop; - if (!dc->type_b) { - ea = extract32(dc->ir, 7, 1); - rev = extract32(dc->ir, 9, 1); - ex = extract32(dc->ir, 10, 1); - } - mop |= MO_TE; - if (rev) { - mop ^= MO_BSWAP; + /* If any of the regs is r0, set t to the value of the other reg. */ + if (ra) { + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_addi_i32(tmp, cpu_R[ra], imm); + tcg_gen_extu_i32_tl(ret, tmp); + tcg_temp_free_i32(tmp); + } else { + tcg_gen_movi_tl(ret, (uint32_t)imm); } - if (trap_illegal(dc, size > 4)) { - return; + if (ra == 1 && dc->cfg->stackprot) { + gen_helper_stackprot(cpu_env, ret); } + return ret; +} - if (trap_userspace(dc, ea)) { - return; +#ifndef CONFIG_USER_ONLY +static TCGv compute_ldst_addr_ea(DisasContext *dc, int ra, int rb) +{ + int addr_size = dc->cfg->addr_size; + TCGv ret = tcg_temp_new(); + + if (addr_size == 32 || ra == 0) { + if (rb) { + tcg_gen_extu_i32_tl(ret, cpu_R[rb]); + } else { + tcg_gen_movi_tl(ret, 0); + } + } else { + if (rb) { + tcg_gen_concat_i32_i64(ret, cpu_R[rb], cpu_R[ra]); + } else { + tcg_gen_extu_i32_tl(ret, cpu_R[ra]); + tcg_gen_shli_tl(ret, ret, 32); + } + if (addr_size < 64) { + /* Mask off out of range bits. */ + tcg_gen_andi_i64(ret, ret, MAKE_64BIT_MASK(0, addr_size)); + } } + return ret; +} +#endif - LOG_DIS("l%d%s%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "", - ex ? "x" : "", - ea ? "ea" : ""); +static void record_unaligned_ess(DisasContext *dc, int rd, + MemOp size, bool store) +{ + uint32_t iflags = tcg_get_insn_start_param(dc->insn_start, 1); - t_sync_flags(dc); - addr = tcg_temp_new(); - compute_ldst_addr(dc, ea, addr); - /* Extended addressing bypasses the MMU. */ - mem_index = ea ? MMU_NOMMU_IDX : mem_index; + iflags |= ESR_ESS_FLAG; + iflags |= rd << 5; + iflags |= store * ESR_S; + iflags |= (size == MO_32) * ESR_W; + + tcg_set_insn_start_param(dc->insn_start, 1, iflags); +} + +static bool do_load(DisasContext *dc, int rd, TCGv addr, MemOp mop, + int mem_index, bool rev) +{ + MemOp size = mop & MO_SIZE; /* * When doing reverse accesses we need to do two things. @@ -958,907 +761,1215 @@ static void dec_load(DisasContext *dc) * 1. Reverse the address wrt endianness. * 2. Byteswap the data lanes on the way back into the CPU core. */ - if (rev && size != 4) { - /* Endian reverse the address. t is addr. */ - switch (size) { - case 1: - { - tcg_gen_xori_tl(addr, addr, 3); - break; - } - - case 2: - /* 00 -> 10 - 10 -> 00. */ - tcg_gen_xori_tl(addr, addr, 2); - break; - default: - cpu_abort(CPU(dc->cpu), "Invalid reverse size\n"); - break; + if (rev) { + if (size > MO_8) { + mop ^= MO_BSWAP; + } + if (size < MO_32) { + tcg_gen_xori_tl(addr, addr, 3 - size); } } - /* lwx does not throw unaligned access errors, so force alignment */ - if (ex) { - tcg_gen_andi_tl(addr, addr, ~3); + if (size > MO_8 && + (dc->tb_flags & MSR_EE) && + dc->cfg->unaligned_exceptions) { + record_unaligned_ess(dc, rd, size, false); + mop |= MO_ALIGN; } - /* If we get a fault on a dslot, the jmpstate better be in sync. */ - sync_jmpstate(dc); + tcg_gen_qemu_ld_i32(reg_for_write(dc, rd), addr, mem_index, mop); - /* Verify alignment if needed. */ - /* - * Microblaze gives MMU faults priority over faults due to - * unaligned addresses. That's why we speculatively do the load - * into v. If the load succeeds, we verify alignment of the - * address and if that succeeds we write into the destination reg. - */ - v = tcg_temp_new_i32(); - tcg_gen_qemu_ld_i32(v, addr, mem_index, mop); + tcg_temp_free(addr); + return true; +} - if (dc->cpu->cfg.unaligned_exceptions && size > 1) { - TCGv_i32 t0 = tcg_const_i32(0); - TCGv_i32 treg = tcg_const_i32(dc->rd); - TCGv_i32 tsize = tcg_const_i32(size - 1); +static bool trans_lbu(DisasContext *dc, arg_typea *arg) +{ + TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); + return do_load(dc, arg->rd, addr, MO_UB, dc->mem_index, false); +} - tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc); - gen_helper_memalign(cpu_env, addr, treg, t0, tsize); +static bool trans_lbur(DisasContext *dc, arg_typea *arg) +{ + TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); + return do_load(dc, arg->rd, addr, MO_UB, dc->mem_index, true); +} - tcg_temp_free_i32(t0); - tcg_temp_free_i32(treg); - tcg_temp_free_i32(tsize); +static bool trans_lbuea(DisasContext *dc, arg_typea *arg) +{ + if (trap_userspace(dc, true)) { + return true; } +#ifdef CONFIG_USER_ONLY + return true; +#else + TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); + return do_load(dc, arg->rd, addr, MO_UB, MMU_NOMMU_IDX, false); +#endif +} - if (ex) { - tcg_gen_mov_tl(env_res_addr, addr); - tcg_gen_mov_i32(env_res_val, v); - } - if (dc->rd) { - tcg_gen_mov_i32(cpu_R[dc->rd], v); - } - tcg_temp_free_i32(v); +static bool trans_lbui(DisasContext *dc, arg_typeb *arg) +{ + TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); + return do_load(dc, arg->rd, addr, MO_UB, dc->mem_index, false); +} + +static bool trans_lhu(DisasContext *dc, arg_typea *arg) +{ + TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); + return do_load(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false); +} - if (ex) { /* lwx */ - /* no support for AXI exclusive so always clear C */ - write_carryi(dc, 0); +static bool trans_lhur(DisasContext *dc, arg_typea *arg) +{ + TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); + return do_load(dc, arg->rd, addr, MO_TEUW, dc->mem_index, true); +} + +static bool trans_lhuea(DisasContext *dc, arg_typea *arg) +{ + if (trap_userspace(dc, true)) { + return true; } +#ifdef CONFIG_USER_ONLY + return true; +#else + TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); + return do_load(dc, arg->rd, addr, MO_TEUW, MMU_NOMMU_IDX, false); +#endif +} - tcg_temp_free(addr); +static bool trans_lhui(DisasContext *dc, arg_typeb *arg) +{ + TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); + return do_load(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false); } -static void dec_store(DisasContext *dc) +static bool trans_lw(DisasContext *dc, arg_typea *arg) { - TCGv addr; - TCGLabel *swx_skip = NULL; - unsigned int size; - bool rev = false, ex = false, ea = false; - int mem_index = cpu_mmu_index(&dc->cpu->env, false); - MemOp mop; + TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); + return do_load(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false); +} - mop = dc->opcode & 3; - size = 1 << mop; - if (!dc->type_b) { - ea = extract32(dc->ir, 7, 1); - rev = extract32(dc->ir, 9, 1); - ex = extract32(dc->ir, 10, 1); - } - mop |= MO_TE; - if (rev) { - mop ^= MO_BSWAP; - } +static bool trans_lwr(DisasContext *dc, arg_typea *arg) +{ + TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); + return do_load(dc, arg->rd, addr, MO_TEUL, dc->mem_index, true); +} - if (trap_illegal(dc, size > 4)) { - return; +static bool trans_lwea(DisasContext *dc, arg_typea *arg) +{ + if (trap_userspace(dc, true)) { + return true; } +#ifdef CONFIG_USER_ONLY + return true; +#else + TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); + return do_load(dc, arg->rd, addr, MO_TEUL, MMU_NOMMU_IDX, false); +#endif +} + +static bool trans_lwi(DisasContext *dc, arg_typeb *arg) +{ + TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); + return do_load(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false); +} - trap_userspace(dc, ea); +static bool trans_lwx(DisasContext *dc, arg_typea *arg) +{ + TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); - LOG_DIS("s%d%s%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "", - ex ? "x" : "", - ea ? "ea" : ""); - t_sync_flags(dc); - /* If we get a fault on a dslot, the jmpstate better be in sync. */ - sync_jmpstate(dc); - /* SWX needs a temp_local. */ - addr = ex ? tcg_temp_local_new() : tcg_temp_new(); - compute_ldst_addr(dc, ea, addr); - /* Extended addressing bypasses the MMU. */ - mem_index = ea ? MMU_NOMMU_IDX : mem_index; - - if (ex) { /* swx */ - TCGv_i32 tval; - - /* swx does not throw unaligned access errors, so force alignment */ - tcg_gen_andi_tl(addr, addr, ~3); - - write_carryi(dc, 1); - swx_skip = gen_new_label(); - tcg_gen_brcond_tl(TCG_COND_NE, env_res_addr, addr, swx_skip); - - /* Compare the value loaded at lwx with current contents of - the reserved location. - FIXME: This only works for system emulation where we can expect - this compare and the following write to be atomic. For user - emulation we need to add atomicity between threads. */ - tval = tcg_temp_new_i32(); - tcg_gen_qemu_ld_i32(tval, addr, cpu_mmu_index(&dc->cpu->env, false), - MO_TEUL); - tcg_gen_brcond_i32(TCG_COND_NE, env_res_val, tval, swx_skip); - write_carryi(dc, 0); - tcg_temp_free_i32(tval); - } - - if (rev && size != 4) { - /* Endian reverse the address. t is addr. */ - switch (size) { - case 1: - { - tcg_gen_xori_tl(addr, addr, 3); - break; - } + /* lwx does not throw unaligned access errors, so force alignment */ + tcg_gen_andi_tl(addr, addr, ~3); - case 2: - /* 00 -> 10 - 10 -> 00. */ - /* Force addr into the temp. */ - tcg_gen_xori_tl(addr, addr, 2); - break; - default: - cpu_abort(CPU(dc->cpu), "Invalid reverse size\n"); - break; - } + tcg_gen_qemu_ld_i32(cpu_res_val, addr, dc->mem_index, MO_TEUL); + tcg_gen_mov_tl(cpu_res_addr, addr); + tcg_temp_free(addr); + + if (arg->rd) { + tcg_gen_mov_i32(cpu_R[arg->rd], cpu_res_val); } - tcg_gen_qemu_st_i32(cpu_R[dc->rd], addr, mem_index, mop); - /* Verify alignment if needed. */ - if (dc->cpu->cfg.unaligned_exceptions && size > 1) { - TCGv_i32 t1 = tcg_const_i32(1); - TCGv_i32 treg = tcg_const_i32(dc->rd); - TCGv_i32 tsize = tcg_const_i32(size - 1); + /* No support for AXI exclusive so always clear C */ + tcg_gen_movi_i32(cpu_msr_c, 0); + return true; +} - tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc); - /* FIXME: if the alignment is wrong, we should restore the value - * in memory. One possible way to achieve this is to probe - * the MMU prior to the memaccess, thay way we could put - * the alignment checks in between the probe and the mem - * access. - */ - gen_helper_memalign(cpu_env, addr, treg, t1, tsize); +static bool do_store(DisasContext *dc, int rd, TCGv addr, MemOp mop, + int mem_index, bool rev) +{ + MemOp size = mop & MO_SIZE; - tcg_temp_free_i32(t1); - tcg_temp_free_i32(treg); - tcg_temp_free_i32(tsize); + /* + * When doing reverse accesses we need to do two things. + * + * 1. Reverse the address wrt endianness. + * 2. Byteswap the data lanes on the way back into the CPU core. + */ + if (rev) { + if (size > MO_8) { + mop ^= MO_BSWAP; + } + if (size < MO_32) { + tcg_gen_xori_tl(addr, addr, 3 - size); + } } - if (ex) { - gen_set_label(swx_skip); + if (size > MO_8 && + (dc->tb_flags & MSR_EE) && + dc->cfg->unaligned_exceptions) { + record_unaligned_ess(dc, rd, size, true); + mop |= MO_ALIGN; } + tcg_gen_qemu_st_i32(reg_for_read(dc, rd), addr, mem_index, mop); + tcg_temp_free(addr); + return true; } -static inline void eval_cc(DisasContext *dc, unsigned int cc, - TCGv_i32 d, TCGv_i32 a) +static bool trans_sb(DisasContext *dc, arg_typea *arg) { - static const int mb_to_tcg_cc[] = { - [CC_EQ] = TCG_COND_EQ, - [CC_NE] = TCG_COND_NE, - [CC_LT] = TCG_COND_LT, - [CC_LE] = TCG_COND_LE, - [CC_GE] = TCG_COND_GE, - [CC_GT] = TCG_COND_GT, - }; + TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); + return do_store(dc, arg->rd, addr, MO_UB, dc->mem_index, false); +} - switch (cc) { - case CC_EQ: - case CC_NE: - case CC_LT: - case CC_LE: - case CC_GE: - case CC_GT: - tcg_gen_setcondi_i32(mb_to_tcg_cc[cc], d, a, 0); - break; - default: - cpu_abort(CPU(dc->cpu), "Unknown condition code %x.\n", cc); - break; - } +static bool trans_sbr(DisasContext *dc, arg_typea *arg) +{ + TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); + return do_store(dc, arg->rd, addr, MO_UB, dc->mem_index, true); } -static void eval_cond_jmp(DisasContext *dc, TCGv_i64 pc_true, TCGv_i64 pc_false) +static bool trans_sbea(DisasContext *dc, arg_typea *arg) { - TCGv_i64 tmp_btaken = tcg_temp_new_i64(); - TCGv_i64 tmp_zero = tcg_const_i64(0); + if (trap_userspace(dc, true)) { + return true; + } +#ifdef CONFIG_USER_ONLY + return true; +#else + TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); + return do_store(dc, arg->rd, addr, MO_UB, MMU_NOMMU_IDX, false); +#endif +} - tcg_gen_extu_i32_i64(tmp_btaken, env_btaken); - tcg_gen_movcond_i64(TCG_COND_NE, cpu_SR[SR_PC], - tmp_btaken, tmp_zero, - pc_true, pc_false); +static bool trans_sbi(DisasContext *dc, arg_typeb *arg) +{ + TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); + return do_store(dc, arg->rd, addr, MO_UB, dc->mem_index, false); +} - tcg_temp_free_i64(tmp_btaken); - tcg_temp_free_i64(tmp_zero); +static bool trans_sh(DisasContext *dc, arg_typea *arg) +{ + TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); + return do_store(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false); } -static void dec_setup_dslot(DisasContext *dc) +static bool trans_shr(DisasContext *dc, arg_typea *arg) { - TCGv_i32 tmp = tcg_const_i32(dc->type_b && (dc->tb_flags & IMM_FLAG)); + TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); + return do_store(dc, arg->rd, addr, MO_TEUW, dc->mem_index, true); +} - dc->delayed_branch = 2; - dc->tb_flags |= D_FLAG; +static bool trans_shea(DisasContext *dc, arg_typea *arg) +{ + if (trap_userspace(dc, true)) { + return true; + } +#ifdef CONFIG_USER_ONLY + return true; +#else + TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); + return do_store(dc, arg->rd, addr, MO_TEUW, MMU_NOMMU_IDX, false); +#endif +} - tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUMBState, bimm)); - tcg_temp_free_i32(tmp); +static bool trans_shi(DisasContext *dc, arg_typeb *arg) +{ + TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); + return do_store(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false); } -static void dec_bcc(DisasContext *dc) +static bool trans_sw(DisasContext *dc, arg_typea *arg) { - unsigned int cc; - unsigned int dslot; + TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); + return do_store(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false); +} - cc = EXTRACT_FIELD(dc->ir, 21, 23); - dslot = dc->ir & (1 << 25); - LOG_DIS("bcc%s r%d %x\n", dslot ? "d" : "", dc->ra, dc->imm); +static bool trans_swr(DisasContext *dc, arg_typea *arg) +{ + TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); + return do_store(dc, arg->rd, addr, MO_TEUL, dc->mem_index, true); +} - dc->delayed_branch = 1; - if (dslot) { - dec_setup_dslot(dc); +static bool trans_swea(DisasContext *dc, arg_typea *arg) +{ + if (trap_userspace(dc, true)) { + return true; } +#ifdef CONFIG_USER_ONLY + return true; +#else + TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); + return do_store(dc, arg->rd, addr, MO_TEUL, MMU_NOMMU_IDX, false); +#endif +} - if (dec_alu_op_b_is_small_imm(dc)) { - int32_t offset = (int32_t)((int16_t)dc->imm); /* sign-extend. */ - - tcg_gen_movi_i64(env_btarget, dc->pc + offset); - dc->jmp = JMP_DIRECT_CC; - dc->jmp_pc = dc->pc + offset; - } else { - dc->jmp = JMP_INDIRECT; - tcg_gen_extu_i32_i64(env_btarget, *(dec_alu_op_b(dc))); - tcg_gen_addi_i64(env_btarget, env_btarget, dc->pc); - tcg_gen_andi_i64(env_btarget, env_btarget, UINT32_MAX); - } - eval_cc(dc, cc, env_btaken, cpu_R[dc->ra]); +static bool trans_swi(DisasContext *dc, arg_typeb *arg) +{ + TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); + return do_store(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false); } -static void dec_br(DisasContext *dc) +static bool trans_swx(DisasContext *dc, arg_typea *arg) { - unsigned int dslot, link, abs, mbar; + TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); + TCGLabel *swx_done = gen_new_label(); + TCGLabel *swx_fail = gen_new_label(); + TCGv_i32 tval; - dslot = dc->ir & (1 << 20); - abs = dc->ir & (1 << 19); - link = dc->ir & (1 << 18); + /* swx does not throw unaligned access errors, so force alignment */ + tcg_gen_andi_tl(addr, addr, ~3); - /* Memory barrier. */ - mbar = (dc->ir >> 16) & 31; - if (mbar == 2 && dc->imm == 4) { - /* mbar IMM & 16 decodes to sleep. */ - if (dc->rd & 16) { - TCGv_i32 tmp_hlt = tcg_const_i32(EXCP_HLT); - TCGv_i32 tmp_1 = tcg_const_i32(1); + /* + * Compare the address vs the one we used during lwx. + * On mismatch, the operation fails. On match, addr dies at the + * branch, but we know we can use the equal version in the global. + * In either case, addr is no longer needed. + */ + tcg_gen_brcond_tl(TCG_COND_NE, cpu_res_addr, addr, swx_fail); + tcg_temp_free(addr); - LOG_DIS("sleep\n"); + /* + * Compare the value loaded during lwx with current contents of + * the reserved location. + */ + tval = tcg_temp_new_i32(); - t_sync_flags(dc); - tcg_gen_st_i32(tmp_1, cpu_env, - -offsetof(MicroBlazeCPU, env) - +offsetof(CPUState, halted)); - tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc + 4); - gen_helper_raise_exception(cpu_env, tmp_hlt); - tcg_temp_free_i32(tmp_hlt); - tcg_temp_free_i32(tmp_1); - return; - } - LOG_DIS("mbar %d\n", dc->rd); - /* Break the TB. */ - dc->cpustate_changed = 1; - return; + tcg_gen_atomic_cmpxchg_i32(tval, cpu_res_addr, cpu_res_val, + reg_for_write(dc, arg->rd), + dc->mem_index, MO_TEUL); + + tcg_gen_brcond_i32(TCG_COND_NE, cpu_res_val, tval, swx_fail); + tcg_temp_free_i32(tval); + + /* Success */ + tcg_gen_movi_i32(cpu_msr_c, 0); + tcg_gen_br(swx_done); + + /* Failure */ + gen_set_label(swx_fail); + tcg_gen_movi_i32(cpu_msr_c, 1); + + gen_set_label(swx_done); + + /* + * Prevent the saved address from working again without another ldx. + * Akin to the pseudocode setting reservation = 0. + */ + tcg_gen_movi_tl(cpu_res_addr, -1); + return true; +} + +static void setup_dslot(DisasContext *dc, bool type_b) +{ + dc->tb_flags_to_set |= D_FLAG; + if (type_b && (dc->tb_flags & IMM_FLAG)) { + dc->tb_flags_to_set |= BIMM_FLAG; } +} - LOG_DIS("br%s%s%s%s imm=%x\n", - abs ? "a" : "", link ? "l" : "", - dc->type_b ? "i" : "", dslot ? "d" : "", - dc->imm); +static bool do_branch(DisasContext *dc, int dest_rb, int dest_imm, + bool delay, bool abs, int link) +{ + uint32_t add_pc; - dc->delayed_branch = 1; - if (dslot) { - dec_setup_dslot(dc); + if (invalid_delay_slot(dc, "branch")) { + return true; + } + if (delay) { + setup_dslot(dc, dest_rb < 0); } - if (link && dc->rd) - tcg_gen_movi_i32(cpu_R[dc->rd], dc->pc); - dc->jmp = JMP_INDIRECT; - if (abs) { - tcg_gen_movi_i32(env_btaken, 1); - tcg_gen_extu_i32_i64(env_btarget, *(dec_alu_op_b(dc))); - if (link && !dslot) { - if (!(dc->tb_flags & IMM_FLAG) && (dc->imm == 8 || dc->imm == 0x18)) - t_gen_raise_exception(dc, EXCP_BREAK); - if (dc->imm == 0) { - if (trap_userspace(dc, true)) { - return; - } + if (link) { + tcg_gen_movi_i32(cpu_R[link], dc->base.pc_next); + } - t_gen_raise_exception(dc, EXCP_DEBUG); - } - } + /* Store the branch taken destination into btarget. */ + add_pc = abs ? 0 : dc->base.pc_next; + if (dest_rb > 0) { + dc->jmp_dest = -1; + tcg_gen_addi_i32(cpu_btarget, cpu_R[dest_rb], add_pc); } else { - if (dec_alu_op_b_is_small_imm(dc)) { - dc->jmp = JMP_DIRECT; - dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm); - } else { - tcg_gen_movi_i32(env_btaken, 1); - tcg_gen_extu_i32_i64(env_btarget, *(dec_alu_op_b(dc))); - tcg_gen_addi_i64(env_btarget, env_btarget, dc->pc); - tcg_gen_andi_i64(env_btarget, env_btarget, UINT32_MAX); - } + dc->jmp_dest = add_pc + dest_imm; + tcg_gen_movi_i32(cpu_btarget, dc->jmp_dest); } + dc->jmp_cond = TCG_COND_ALWAYS; + return true; } -static inline void do_rti(DisasContext *dc) +#define DO_BR(NAME, NAMEI, DELAY, ABS, LINK) \ + static bool trans_##NAME(DisasContext *dc, arg_typea_br *arg) \ + { return do_branch(dc, arg->rb, 0, DELAY, ABS, LINK ? arg->rd : 0); } \ + static bool trans_##NAMEI(DisasContext *dc, arg_typeb_br *arg) \ + { return do_branch(dc, -1, arg->imm, DELAY, ABS, LINK ? arg->rd : 0); } + +DO_BR(br, bri, false, false, false) +DO_BR(bra, brai, false, true, false) +DO_BR(brd, brid, true, false, false) +DO_BR(brad, braid, true, true, false) +DO_BR(brld, brlid, true, false, true) +DO_BR(brald, bralid, true, true, true) + +static bool do_bcc(DisasContext *dc, int dest_rb, int dest_imm, + TCGCond cond, int ra, bool delay) { - TCGv_i32 t0, t1; - t0 = tcg_temp_new_i32(); - t1 = tcg_temp_new_i32(); - tcg_gen_extrl_i64_i32(t1, cpu_SR[SR_MSR]); - tcg_gen_shri_i32(t0, t1, 1); - tcg_gen_ori_i32(t1, t1, MSR_IE); - tcg_gen_andi_i32(t0, t0, (MSR_VM | MSR_UM)); + TCGv_i32 zero, next; + + if (invalid_delay_slot(dc, "bcc")) { + return true; + } + if (delay) { + setup_dslot(dc, dest_rb < 0); + } + + dc->jmp_cond = cond; + + /* Cache the condition register in cpu_bvalue across any delay slot. */ + tcg_gen_mov_i32(cpu_bvalue, reg_for_read(dc, ra)); + + /* Store the branch taken destination into btarget. */ + if (dest_rb > 0) { + dc->jmp_dest = -1; + tcg_gen_addi_i32(cpu_btarget, cpu_R[dest_rb], dc->base.pc_next); + } else { + dc->jmp_dest = dc->base.pc_next + dest_imm; + tcg_gen_movi_i32(cpu_btarget, dc->jmp_dest); + } - tcg_gen_andi_i32(t1, t1, ~(MSR_VM | MSR_UM)); - tcg_gen_or_i32(t1, t1, t0); - msr_write(dc, t1); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t0); - dc->tb_flags &= ~DRTI_FLAG; + /* Compute the final destination into btarget. */ + zero = tcg_const_i32(0); + next = tcg_const_i32(dc->base.pc_next + (delay + 1) * 4); + tcg_gen_movcond_i32(dc->jmp_cond, cpu_btarget, + reg_for_read(dc, ra), zero, + cpu_btarget, next); + tcg_temp_free_i32(zero); + tcg_temp_free_i32(next); + + return true; } -static inline void do_rtb(DisasContext *dc) +#define DO_BCC(NAME, COND) \ + static bool trans_##NAME(DisasContext *dc, arg_typea_bc *arg) \ + { return do_bcc(dc, arg->rb, 0, COND, arg->ra, false); } \ + static bool trans_##NAME##d(DisasContext *dc, arg_typea_bc *arg) \ + { return do_bcc(dc, arg->rb, 0, COND, arg->ra, true); } \ + static bool trans_##NAME##i(DisasContext *dc, arg_typeb_bc *arg) \ + { return do_bcc(dc, -1, arg->imm, COND, arg->ra, false); } \ + static bool trans_##NAME##id(DisasContext *dc, arg_typeb_bc *arg) \ + { return do_bcc(dc, -1, arg->imm, COND, arg->ra, true); } + +DO_BCC(beq, TCG_COND_EQ) +DO_BCC(bge, TCG_COND_GE) +DO_BCC(bgt, TCG_COND_GT) +DO_BCC(ble, TCG_COND_LE) +DO_BCC(blt, TCG_COND_LT) +DO_BCC(bne, TCG_COND_NE) + +static bool trans_brk(DisasContext *dc, arg_typea_br *arg) { - TCGv_i32 t0, t1; - t0 = tcg_temp_new_i32(); - t1 = tcg_temp_new_i32(); - tcg_gen_extrl_i64_i32(t1, cpu_SR[SR_MSR]); - tcg_gen_andi_i32(t1, t1, ~MSR_BIP); - tcg_gen_shri_i32(t0, t1, 1); - tcg_gen_andi_i32(t0, t0, (MSR_VM | MSR_UM)); + if (trap_userspace(dc, true)) { + return true; + } + if (invalid_delay_slot(dc, "brk")) { + return true; + } + + tcg_gen_mov_i32(cpu_pc, reg_for_read(dc, arg->rb)); + if (arg->rd) { + tcg_gen_movi_i32(cpu_R[arg->rd], dc->base.pc_next); + } + tcg_gen_ori_i32(cpu_msr, cpu_msr, MSR_BIP); + tcg_gen_movi_tl(cpu_res_addr, -1); - tcg_gen_andi_i32(t1, t1, ~(MSR_VM | MSR_UM)); - tcg_gen_or_i32(t1, t1, t0); - msr_write(dc, t1); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t0); - dc->tb_flags &= ~DRTB_FLAG; + dc->base.is_jmp = DISAS_EXIT; + return true; } -static inline void do_rte(DisasContext *dc) +static bool trans_brki(DisasContext *dc, arg_typeb_br *arg) { - TCGv_i32 t0, t1; - t0 = tcg_temp_new_i32(); - t1 = tcg_temp_new_i32(); + uint32_t imm = arg->imm; + + if (trap_userspace(dc, imm != 0x8 && imm != 0x18)) { + return true; + } + if (invalid_delay_slot(dc, "brki")) { + return true; + } + + tcg_gen_movi_i32(cpu_pc, imm); + if (arg->rd) { + tcg_gen_movi_i32(cpu_R[arg->rd], dc->base.pc_next); + } + tcg_gen_movi_tl(cpu_res_addr, -1); - tcg_gen_extrl_i64_i32(t1, cpu_SR[SR_MSR]); - tcg_gen_ori_i32(t1, t1, MSR_EE); - tcg_gen_andi_i32(t1, t1, ~MSR_EIP); - tcg_gen_shri_i32(t0, t1, 1); - tcg_gen_andi_i32(t0, t0, (MSR_VM | MSR_UM)); +#ifdef CONFIG_USER_ONLY + switch (imm) { + case 0x8: /* syscall trap */ + gen_raise_exception_sync(dc, EXCP_SYSCALL); + break; + case 0x18: /* debug trap */ + gen_raise_exception_sync(dc, EXCP_DEBUG); + break; + default: /* eliminated with trap_userspace check */ + g_assert_not_reached(); + } +#else + uint32_t msr_to_set = 0; - tcg_gen_andi_i32(t1, t1, ~(MSR_VM | MSR_UM)); - tcg_gen_or_i32(t1, t1, t0); - msr_write(dc, t1); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t0); - dc->tb_flags &= ~DRTE_FLAG; + if (imm != 0x18) { + msr_to_set |= MSR_BIP; + } + if (imm == 0x8 || imm == 0x18) { + /* MSR_UM and MSR_VM are in tb_flags, so we know their value. */ + msr_to_set |= (dc->tb_flags & (MSR_UM | MSR_VM)) << 1; + tcg_gen_andi_i32(cpu_msr, cpu_msr, + ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM)); + } + tcg_gen_ori_i32(cpu_msr, cpu_msr, msr_to_set); + dc->base.is_jmp = DISAS_EXIT; +#endif + + return true; } -static void dec_rts(DisasContext *dc) +static bool trans_mbar(DisasContext *dc, arg_mbar *arg) { - unsigned int b_bit, i_bit, e_bit; - TCGv_i64 tmp64; + int mbar_imm = arg->imm; + + /* Note that mbar is a specialized branch instruction. */ + if (invalid_delay_slot(dc, "mbar")) { + return true; + } - i_bit = dc->ir & (1 << 21); - b_bit = dc->ir & (1 << 22); - e_bit = dc->ir & (1 << 23); + /* Data access memory barrier. */ + if ((mbar_imm & 2) == 0) { + tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL); + } - if (trap_userspace(dc, i_bit || b_bit || e_bit)) { - return; + /* Sleep. */ + if (mbar_imm & 16) { + TCGv_i32 tmp_1; + + if (trap_userspace(dc, true)) { + /* Sleep is a privileged instruction. */ + return true; + } + + t_sync_flags(dc); + + tmp_1 = tcg_const_i32(1); + tcg_gen_st_i32(tmp_1, cpu_env, + -offsetof(MicroBlazeCPU, env) + +offsetof(CPUState, halted)); + tcg_temp_free_i32(tmp_1); + + tcg_gen_movi_i32(cpu_pc, dc->base.pc_next + 4); + + gen_raise_exception(dc, EXCP_HLT); } - dec_setup_dslot(dc); + /* + * If !(mbar_imm & 1), this is an instruction access memory barrier + * and we need to end the TB so that we recognize self-modified + * code immediately. + * + * However, there are some data mbars that need the TB break + * (and return to main loop) to recognize interrupts right away. + * E.g. recognizing a change to an interrupt controller register. + * + * Therefore, choose to end the TB always. + */ + dc->base.is_jmp = DISAS_EXIT_NEXT; + return true; +} - if (i_bit) { - LOG_DIS("rtid ir=%x\n", dc->ir); - dc->tb_flags |= DRTI_FLAG; - } else if (b_bit) { - LOG_DIS("rtbd ir=%x\n", dc->ir); - dc->tb_flags |= DRTB_FLAG; - } else if (e_bit) { - LOG_DIS("rted ir=%x\n", dc->ir); - dc->tb_flags |= DRTE_FLAG; - } else - LOG_DIS("rts ir=%x\n", dc->ir); +static bool do_rts(DisasContext *dc, arg_typeb_bc *arg, int to_set) +{ + if (trap_userspace(dc, to_set)) { + return true; + } + if (invalid_delay_slot(dc, "rts")) { + return true; + } - dc->jmp = JMP_INDIRECT; - tcg_gen_movi_i32(env_btaken, 1); + dc->tb_flags_to_set |= to_set; + setup_dslot(dc, true); - tmp64 = tcg_temp_new_i64(); - tcg_gen_extu_i32_i64(env_btarget, *(dec_alu_op_b(dc))); - tcg_gen_extu_i32_i64(tmp64, cpu_R[dc->ra]); - tcg_gen_add_i64(env_btarget, env_btarget, tmp64); - tcg_gen_andi_i64(env_btarget, env_btarget, UINT32_MAX); - tcg_temp_free_i64(tmp64); + dc->jmp_cond = TCG_COND_ALWAYS; + dc->jmp_dest = -1; + tcg_gen_addi_i32(cpu_btarget, reg_for_read(dc, arg->ra), arg->imm); + return true; } -static int dec_check_fpuv2(DisasContext *dc) +#define DO_RTS(NAME, IFLAG) \ + static bool trans_##NAME(DisasContext *dc, arg_typeb_bc *arg) \ + { return do_rts(dc, arg, IFLAG); } + +DO_RTS(rtbd, DRTB_FLAG) +DO_RTS(rtid, DRTI_FLAG) +DO_RTS(rted, DRTE_FLAG) +DO_RTS(rtsd, 0) + +static bool trans_zero(DisasContext *dc, arg_zero *arg) { - if ((dc->cpu->cfg.use_fpu != 2) && (dc->tb_flags & MSR_EE_FLAG)) { - tcg_gen_movi_i64(cpu_SR[SR_ESR], ESR_EC_FPU); - t_gen_raise_exception(dc, EXCP_HW_EXCP); + /* If opcode_0_illegal, trap. */ + if (dc->cfg->opcode_0_illegal) { + trap_illegal(dc, true); + return true; } - return (dc->cpu->cfg.use_fpu == 2) ? PVR2_USE_FPU2_MASK : 0; + /* + * Otherwise, this is "add r0, r0, r0". + * Continue to trans_add so that MSR[C] gets cleared. + */ + return false; } -static void dec_fpu(DisasContext *dc) +static void msr_read(DisasContext *dc, TCGv_i32 d) { - unsigned int fpu_insn; + TCGv_i32 t; - if (trap_illegal(dc, !dc->cpu->cfg.use_fpu)) { - return; + /* Replicate the cpu_msr_c boolean into the proper bit and the copy. */ + t = tcg_temp_new_i32(); + tcg_gen_muli_i32(t, cpu_msr_c, MSR_C | MSR_CC); + tcg_gen_or_i32(d, cpu_msr, t); + tcg_temp_free_i32(t); +} + +static bool do_msrclrset(DisasContext *dc, arg_type_msr *arg, bool set) +{ + uint32_t imm = arg->imm; + + if (trap_userspace(dc, imm != MSR_C)) { + return true; } - fpu_insn = (dc->ir >> 7) & 7; + if (arg->rd) { + msr_read(dc, cpu_R[arg->rd]); + } - switch (fpu_insn) { - case 0: - gen_helper_fadd(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], - cpu_R[dc->rb]); - break; + /* + * Handle the carry bit separately. + * This is the only bit that userspace can modify. + */ + if (imm & MSR_C) { + tcg_gen_movi_i32(cpu_msr_c, set); + } - case 1: - gen_helper_frsub(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], - cpu_R[dc->rb]); - break; + /* + * MSR_C and MSR_CC set above. + * MSR_PVR is not writable, and is always clear. + */ + imm &= ~(MSR_C | MSR_CC | MSR_PVR); - case 2: - gen_helper_fmul(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], - cpu_R[dc->rb]); - break; + if (imm != 0) { + if (set) { + tcg_gen_ori_i32(cpu_msr, cpu_msr, imm); + } else { + tcg_gen_andi_i32(cpu_msr, cpu_msr, ~imm); + } + dc->base.is_jmp = DISAS_EXIT_NEXT; + } + return true; +} - case 3: - gen_helper_fdiv(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], - cpu_R[dc->rb]); - break; +static bool trans_msrclr(DisasContext *dc, arg_type_msr *arg) +{ + return do_msrclrset(dc, arg, false); +} - case 4: - switch ((dc->ir >> 4) & 7) { - case 0: - gen_helper_fcmp_un(cpu_R[dc->rd], cpu_env, - cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 1: - gen_helper_fcmp_lt(cpu_R[dc->rd], cpu_env, - cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 2: - gen_helper_fcmp_eq(cpu_R[dc->rd], cpu_env, - cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 3: - gen_helper_fcmp_le(cpu_R[dc->rd], cpu_env, - cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 4: - gen_helper_fcmp_gt(cpu_R[dc->rd], cpu_env, - cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 5: - gen_helper_fcmp_ne(cpu_R[dc->rd], cpu_env, - cpu_R[dc->ra], cpu_R[dc->rb]); - break; - case 6: - gen_helper_fcmp_ge(cpu_R[dc->rd], cpu_env, - cpu_R[dc->ra], cpu_R[dc->rb]); - break; - default: - qemu_log_mask(LOG_UNIMP, - "unimplemented fcmp fpu_insn=%x pc=%x" - " opc=%x\n", - fpu_insn, dc->pc, dc->opcode); - dc->abort_at_next_insn = 1; - break; - } - break; +static bool trans_msrset(DisasContext *dc, arg_type_msr *arg) +{ + return do_msrclrset(dc, arg, true); +} - case 5: - if (!dec_check_fpuv2(dc)) { - return; - } - gen_helper_flt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]); - break; +static bool trans_mts(DisasContext *dc, arg_mts *arg) +{ + if (trap_userspace(dc, true)) { + return true; + } - case 6: - if (!dec_check_fpuv2(dc)) { - return; - } - gen_helper_fint(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]); - break; +#ifdef CONFIG_USER_ONLY + g_assert_not_reached(); +#else + if (arg->e && arg->rs != 0x1003) { + qemu_log_mask(LOG_GUEST_ERROR, + "Invalid extended mts reg 0x%x\n", arg->rs); + return true; + } + + TCGv_i32 src = reg_for_read(dc, arg->ra); + switch (arg->rs) { + case SR_MSR: + /* Install MSR_C. */ + tcg_gen_extract_i32(cpu_msr_c, src, 2, 1); + /* + * Clear MSR_C and MSR_CC; + * MSR_PVR is not writable, and is always clear. + */ + tcg_gen_andi_i32(cpu_msr, src, ~(MSR_C | MSR_CC | MSR_PVR)); + break; + case SR_FSR: + tcg_gen_st_i32(src, cpu_env, offsetof(CPUMBState, fsr)); + break; + case 0x800: + tcg_gen_st_i32(src, cpu_env, offsetof(CPUMBState, slr)); + break; + case 0x802: + tcg_gen_st_i32(src, cpu_env, offsetof(CPUMBState, shr)); + break; + + case 0x1000: /* PID */ + case 0x1001: /* ZPR */ + case 0x1002: /* TLBX */ + case 0x1003: /* TLBLO */ + case 0x1004: /* TLBHI */ + case 0x1005: /* TLBSX */ + { + TCGv_i32 tmp_ext = tcg_const_i32(arg->e); + TCGv_i32 tmp_reg = tcg_const_i32(arg->rs & 7); + + gen_helper_mmu_write(cpu_env, tmp_ext, tmp_reg, src); + tcg_temp_free_i32(tmp_reg); + tcg_temp_free_i32(tmp_ext); + } + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, "Invalid mts reg 0x%x\n", arg->rs); + return true; + } + dc->base.is_jmp = DISAS_EXIT_NEXT; + return true; +#endif +} + +static bool trans_mfs(DisasContext *dc, arg_mfs *arg) +{ + TCGv_i32 dest = reg_for_write(dc, arg->rd); - case 7: - if (!dec_check_fpuv2(dc)) { - return; + if (arg->e) { + switch (arg->rs) { + case SR_EAR: + { + TCGv_i64 t64 = tcg_temp_new_i64(); + tcg_gen_ld_i64(t64, cpu_env, offsetof(CPUMBState, ear)); + tcg_gen_extrh_i64_i32(dest, t64); + tcg_temp_free_i64(t64); } - gen_helper_fsqrt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]); + return true; +#ifndef CONFIG_USER_ONLY + case 0x1003: /* TLBLO */ + /* Handled below. */ break; - +#endif + case 0x2006 ... 0x2009: + /* High bits of PVR6-9 not implemented. */ + tcg_gen_movi_i32(dest, 0); + return true; default: - qemu_log_mask(LOG_UNIMP, "unimplemented FPU insn fpu_insn=%x pc=%x" - " opc=%x\n", - fpu_insn, dc->pc, dc->opcode); - dc->abort_at_next_insn = 1; - break; + qemu_log_mask(LOG_GUEST_ERROR, + "Invalid extended mfs reg 0x%x\n", arg->rs); + return true; + } } + + switch (arg->rs) { + case SR_PC: + tcg_gen_movi_i32(dest, dc->base.pc_next); + break; + case SR_MSR: + msr_read(dc, dest); + break; + case SR_EAR: + { + TCGv_i64 t64 = tcg_temp_new_i64(); + tcg_gen_ld_i64(t64, cpu_env, offsetof(CPUMBState, ear)); + tcg_gen_extrl_i64_i32(dest, t64); + tcg_temp_free_i64(t64); + } + break; + case SR_ESR: + tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, esr)); + break; + case SR_FSR: + tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, fsr)); + break; + case SR_BTR: + tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, btr)); + break; + case SR_EDR: + tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, edr)); + break; + case 0x800: + tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, slr)); + break; + case 0x802: + tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, shr)); + break; + +#ifndef CONFIG_USER_ONLY + case 0x1000: /* PID */ + case 0x1001: /* ZPR */ + case 0x1002: /* TLBX */ + case 0x1003: /* TLBLO */ + case 0x1004: /* TLBHI */ + case 0x1005: /* TLBSX */ + { + TCGv_i32 tmp_ext = tcg_const_i32(arg->e); + TCGv_i32 tmp_reg = tcg_const_i32(arg->rs & 7); + + gen_helper_mmu_read(dest, cpu_env, tmp_ext, tmp_reg); + tcg_temp_free_i32(tmp_reg); + tcg_temp_free_i32(tmp_ext); + } + break; +#endif + + case 0x2000 ... 0x200c: + tcg_gen_ld_i32(dest, cpu_env, + offsetof(MicroBlazeCPU, cfg.pvr_regs[arg->rs - 0x2000]) + - offsetof(MicroBlazeCPU, env)); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "Invalid mfs reg 0x%x\n", arg->rs); + break; + } + return true; } -static void dec_null(DisasContext *dc) +static void do_rti(DisasContext *dc) { - if (trap_illegal(dc, true)) { - return; - } - qemu_log_mask(LOG_GUEST_ERROR, "unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode); - dc->abort_at_next_insn = 1; + TCGv_i32 tmp = tcg_temp_new_i32(); + + tcg_gen_shri_i32(tmp, cpu_msr, 1); + tcg_gen_ori_i32(cpu_msr, cpu_msr, MSR_IE); + tcg_gen_andi_i32(tmp, tmp, MSR_VM | MSR_UM); + tcg_gen_andi_i32(cpu_msr, cpu_msr, ~(MSR_VM | MSR_UM)); + tcg_gen_or_i32(cpu_msr, cpu_msr, tmp); + + tcg_temp_free_i32(tmp); +} + +static void do_rtb(DisasContext *dc) +{ + TCGv_i32 tmp = tcg_temp_new_i32(); + + tcg_gen_shri_i32(tmp, cpu_msr, 1); + tcg_gen_andi_i32(cpu_msr, cpu_msr, ~(MSR_VM | MSR_UM | MSR_BIP)); + tcg_gen_andi_i32(tmp, tmp, (MSR_VM | MSR_UM)); + tcg_gen_or_i32(cpu_msr, cpu_msr, tmp); + + tcg_temp_free_i32(tmp); +} + +static void do_rte(DisasContext *dc) +{ + TCGv_i32 tmp = tcg_temp_new_i32(); + + tcg_gen_shri_i32(tmp, cpu_msr, 1); + tcg_gen_ori_i32(cpu_msr, cpu_msr, MSR_EE); + tcg_gen_andi_i32(tmp, tmp, (MSR_VM | MSR_UM)); + tcg_gen_andi_i32(cpu_msr, cpu_msr, ~(MSR_VM | MSR_UM | MSR_EIP)); + tcg_gen_or_i32(cpu_msr, cpu_msr, tmp); + + tcg_temp_free_i32(tmp); } /* Insns connected to FSL or AXI stream attached devices. */ -static void dec_stream(DisasContext *dc) +static bool do_get(DisasContext *dc, int rd, int rb, int imm, int ctrl) { TCGv_i32 t_id, t_ctrl; - int ctrl; - - LOG_DIS("%s%s imm=%x\n", dc->rd ? "get" : "put", - dc->type_b ? "" : "d", dc->imm); if (trap_userspace(dc, true)) { - return; + return true; } t_id = tcg_temp_new_i32(); - if (dc->type_b) { - tcg_gen_movi_i32(t_id, dc->imm & 0xf); - ctrl = dc->imm >> 10; + if (rb) { + tcg_gen_andi_i32(t_id, cpu_R[rb], 0xf); } else { - tcg_gen_andi_i32(t_id, cpu_R[dc->rb], 0xf); - ctrl = dc->imm >> 5; + tcg_gen_movi_i32(t_id, imm); } t_ctrl = tcg_const_i32(ctrl); + gen_helper_get(reg_for_write(dc, rd), t_id, t_ctrl); + tcg_temp_free_i32(t_id); + tcg_temp_free_i32(t_ctrl); + return true; +} + +static bool trans_get(DisasContext *dc, arg_get *arg) +{ + return do_get(dc, arg->rd, 0, arg->imm, arg->ctrl); +} + +static bool trans_getd(DisasContext *dc, arg_getd *arg) +{ + return do_get(dc, arg->rd, arg->rb, 0, arg->ctrl); +} + +static bool do_put(DisasContext *dc, int ra, int rb, int imm, int ctrl) +{ + TCGv_i32 t_id, t_ctrl; + + if (trap_userspace(dc, true)) { + return true; + } - if (dc->rd == 0) { - gen_helper_put(t_id, t_ctrl, cpu_R[dc->ra]); + t_id = tcg_temp_new_i32(); + if (rb) { + tcg_gen_andi_i32(t_id, cpu_R[rb], 0xf); } else { - gen_helper_get(cpu_R[dc->rd], t_id, t_ctrl); + tcg_gen_movi_i32(t_id, imm); } + + t_ctrl = tcg_const_i32(ctrl); + gen_helper_put(t_id, t_ctrl, reg_for_read(dc, ra)); tcg_temp_free_i32(t_id); tcg_temp_free_i32(t_ctrl); + return true; } -static struct decoder_info { - struct { - uint32_t bits; - uint32_t mask; - }; - void (*dec)(DisasContext *dc); -} decinfo[] = { - {DEC_ADD, dec_add}, - {DEC_SUB, dec_sub}, - {DEC_AND, dec_and}, - {DEC_XOR, dec_xor}, - {DEC_OR, dec_or}, - {DEC_BIT, dec_bit}, - {DEC_BARREL, dec_barrel}, - {DEC_LD, dec_load}, - {DEC_ST, dec_store}, - {DEC_IMM, dec_imm}, - {DEC_BR, dec_br}, - {DEC_BCC, dec_bcc}, - {DEC_RTS, dec_rts}, - {DEC_FPU, dec_fpu}, - {DEC_MUL, dec_mul}, - {DEC_DIV, dec_div}, - {DEC_MSR, dec_msr}, - {DEC_STREAM, dec_stream}, - {{0, 0}, dec_null} -}; +static bool trans_put(DisasContext *dc, arg_put *arg) +{ + return do_put(dc, arg->ra, 0, arg->imm, arg->ctrl); +} -static inline void decode(DisasContext *dc, uint32_t ir) +static bool trans_putd(DisasContext *dc, arg_putd *arg) { - int i; + return do_put(dc, arg->ra, arg->rb, 0, arg->ctrl); +} - dc->ir = ir; - LOG_DIS("%8.8x\t", dc->ir); +static void mb_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) +{ + DisasContext *dc = container_of(dcb, DisasContext, base); + MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); + int bound; + + dc->cfg = &cpu->cfg; + dc->tb_flags = dc->base.tb->flags; + dc->ext_imm = dc->base.tb->cs_base; + dc->r0 = NULL; + dc->r0_set = false; + dc->mem_index = cpu_mmu_index(&cpu->env, false); + dc->jmp_cond = dc->tb_flags & D_FLAG ? TCG_COND_ALWAYS : TCG_COND_NEVER; + dc->jmp_dest = -1; + + bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; + dc->base.max_insns = MIN(dc->base.max_insns, bound); +} - if (ir == 0) { - trap_illegal(dc, dc->cpu->cfg.opcode_0_illegal); - /* Don't decode nop/zero instructions any further. */ - return; - } +static void mb_tr_tb_start(DisasContextBase *dcb, CPUState *cs) +{ +} - /* bit 2 seems to indicate insn type. */ - dc->type_b = ir & (1 << 29); +static void mb_tr_insn_start(DisasContextBase *dcb, CPUState *cs) +{ + DisasContext *dc = container_of(dcb, DisasContext, base); - dc->opcode = EXTRACT_FIELD(ir, 26, 31); - dc->rd = EXTRACT_FIELD(ir, 21, 25); - dc->ra = EXTRACT_FIELD(ir, 16, 20); - dc->rb = EXTRACT_FIELD(ir, 11, 15); - dc->imm = EXTRACT_FIELD(ir, 0, 15); + tcg_gen_insn_start(dc->base.pc_next, dc->tb_flags & ~MSR_TB_MASK); + dc->insn_start = tcg_last_op(); +} - /* Large switch for all insns. */ - for (i = 0; i < ARRAY_SIZE(decinfo); i++) { - if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) { - decinfo[i].dec(dc); - break; - } - } +static bool mb_tr_breakpoint_check(DisasContextBase *dcb, CPUState *cs, + const CPUBreakpoint *bp) +{ + DisasContext *dc = container_of(dcb, DisasContext, base); + + gen_raise_exception_sync(dc, EXCP_DEBUG); + + /* + * The address covered by the breakpoint must be included in + * [tb->pc, tb->pc + tb->size) in order to for it to be + * properly cleared -- thus we increment the PC here so that + * the logic setting tb->size below does the right thing. + */ + dc->base.pc_next += 4; + return true; } -/* generate intermediate code for basic block 'tb'. */ -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) +static void mb_tr_translate_insn(DisasContextBase *dcb, CPUState *cs) { + DisasContext *dc = container_of(dcb, DisasContext, base); CPUMBState *env = cs->env_ptr; - MicroBlazeCPU *cpu = env_archcpu(env); - uint32_t pc_start; - struct DisasContext ctx; - struct DisasContext *dc = &ctx; - uint32_t page_start, org_flags; - uint32_t npc; - int num_insns; - - pc_start = tb->pc; - dc->cpu = cpu; - dc->tb = tb; - org_flags = dc->synced_flags = dc->tb_flags = tb->flags; - - dc->is_jmp = DISAS_NEXT; - dc->jmp = 0; - dc->delayed_branch = !!(dc->tb_flags & D_FLAG); - if (dc->delayed_branch) { - dc->jmp = JMP_INDIRECT; - } - dc->pc = pc_start; - dc->singlestep_enabled = cs->singlestep_enabled; - dc->cpustate_changed = 0; - dc->abort_at_next_insn = 0; - - if (pc_start & 3) { - cpu_abort(cs, "Microblaze: unaligned PC=%x\n", pc_start); - } - - page_start = pc_start & TARGET_PAGE_MASK; - num_insns = 0; - - gen_tb_start(tb); - do - { - tcg_gen_insn_start(dc->pc); - num_insns++; - -#if SIM_COMPAT - if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { - tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc); - gen_helper_debug(); - } -#endif + uint32_t ir; - if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { - t_gen_raise_exception(dc, EXCP_DEBUG); - dc->is_jmp = DISAS_UPDATE; - /* The address covered by the breakpoint must be included in - [tb->pc, tb->pc + tb->size) in order to for it to be - properly cleared -- thus we increment the PC here so that - the logic setting tb->size below does the right thing. */ - dc->pc += 4; - break; - } + /* TODO: This should raise an exception, not terminate qemu. */ + if (dc->base.pc_next & 3) { + cpu_abort(cs, "Microblaze: unaligned PC=%x\n", + (uint32_t)dc->base.pc_next); + } - /* Pretty disas. */ - LOG_DIS("%8.8x:\t", dc->pc); + dc->tb_flags_to_set = 0; - if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) { - gen_io_start(); - } + ir = cpu_ldl_code(env, dc->base.pc_next); + if (!decode(dc, ir)) { + trap_illegal(dc, true); + } + + if (dc->r0) { + tcg_temp_free_i32(dc->r0); + dc->r0 = NULL; + dc->r0_set = false; + } - dc->clear_imm = 1; - decode(dc, cpu_ldl_code(env, dc->pc)); - if (dc->clear_imm) - dc->tb_flags &= ~IMM_FLAG; - dc->pc += 4; - - if (dc->delayed_branch) { - dc->delayed_branch--; - if (!dc->delayed_branch) { - if (dc->tb_flags & DRTI_FLAG) - do_rti(dc); - if (dc->tb_flags & DRTB_FLAG) - do_rtb(dc); - if (dc->tb_flags & DRTE_FLAG) - do_rte(dc); - /* Clear the delay slot flag. */ - dc->tb_flags &= ~D_FLAG; - /* If it is a direct jump, try direct chaining. */ - if (dc->jmp == JMP_INDIRECT) { - TCGv_i64 tmp_pc = tcg_const_i64(dc->pc); - eval_cond_jmp(dc, env_btarget, tmp_pc); - tcg_temp_free_i64(tmp_pc); - - dc->is_jmp = DISAS_JUMP; - } else if (dc->jmp == JMP_DIRECT) { - t_sync_flags(dc); - gen_goto_tb(dc, 0, dc->jmp_pc); - dc->is_jmp = DISAS_TB_JUMP; - } else if (dc->jmp == JMP_DIRECT_CC) { - TCGLabel *l1 = gen_new_label(); - t_sync_flags(dc); - /* Conditional jmp. */ - tcg_gen_brcondi_i32(TCG_COND_NE, env_btaken, 0, l1); - gen_goto_tb(dc, 1, dc->pc); - gen_set_label(l1); - gen_goto_tb(dc, 0, dc->jmp_pc); - - dc->is_jmp = DISAS_TB_JUMP; - } - break; + /* Discard the imm global when its contents cannot be used. */ + if ((dc->tb_flags & ~dc->tb_flags_to_set) & IMM_FLAG) { + tcg_gen_discard_i32(cpu_imm); + } + + dc->tb_flags &= ~(IMM_FLAG | BIMM_FLAG | D_FLAG); + dc->tb_flags |= dc->tb_flags_to_set; + dc->base.pc_next += 4; + + if (dc->jmp_cond != TCG_COND_NEVER && !(dc->tb_flags & D_FLAG)) { + /* + * Finish any return-from branch. + */ + uint32_t rt_ibe = dc->tb_flags & (DRTI_FLAG | DRTB_FLAG | DRTE_FLAG); + if (unlikely(rt_ibe != 0)) { + dc->tb_flags &= ~(DRTI_FLAG | DRTB_FLAG | DRTE_FLAG); + if (rt_ibe & DRTI_FLAG) { + do_rti(dc); + } else if (rt_ibe & DRTB_FLAG) { + do_rtb(dc); + } else { + do_rte(dc); } } - if (cs->singlestep_enabled) { + + /* Complete the branch, ending the TB. */ + switch (dc->base.is_jmp) { + case DISAS_NORETURN: + /* + * E.g. illegal insn in a delay slot. We've already exited + * and will handle D_FLAG in mb_cpu_do_interrupt. + */ + break; + case DISAS_NEXT: + /* + * Normal insn a delay slot. + * However, the return-from-exception type insns should + * return to the main loop, as they have adjusted MSR. + */ + dc->base.is_jmp = (rt_ibe ? DISAS_EXIT_JUMP : DISAS_JUMP); break; + case DISAS_EXIT_NEXT: + /* + * E.g. mts insn in a delay slot. Continue with btarget, + * but still return to the main loop. + */ + dc->base.is_jmp = DISAS_EXIT_JUMP; + break; + default: + g_assert_not_reached(); } - } while (!dc->is_jmp && !dc->cpustate_changed - && !tcg_op_buf_full() - && !singlestep - && (dc->pc - page_start < TARGET_PAGE_SIZE) - && num_insns < max_insns); - - npc = dc->pc; - if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) { - if (dc->tb_flags & D_FLAG) { - dc->is_jmp = DISAS_UPDATE; - tcg_gen_movi_i64(cpu_SR[SR_PC], npc); - sync_jmpstate(dc); - } else - npc = dc->jmp_pc; - } - - /* Force an update if the per-tb cpu state has changed. */ - if (dc->is_jmp == DISAS_NEXT - && (dc->cpustate_changed || org_flags != dc->tb_flags)) { - dc->is_jmp = DISAS_UPDATE; - tcg_gen_movi_i64(cpu_SR[SR_PC], npc); } +} + +static void mb_tr_tb_stop(DisasContextBase *dcb, CPUState *cs) +{ + DisasContext *dc = container_of(dcb, DisasContext, base); + + if (dc->base.is_jmp == DISAS_NORETURN) { + /* We have already exited the TB. */ + return; + } + t_sync_flags(dc); - if (unlikely(cs->singlestep_enabled)) { - TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG); + switch (dc->base.is_jmp) { + case DISAS_TOO_MANY: + gen_goto_tb(dc, 0, dc->base.pc_next); + return; - if (dc->is_jmp != DISAS_JUMP) { - tcg_gen_movi_i64(cpu_SR[SR_PC], npc); + case DISAS_EXIT: + break; + case DISAS_EXIT_NEXT: + tcg_gen_movi_i32(cpu_pc, dc->base.pc_next); + break; + case DISAS_EXIT_JUMP: + tcg_gen_mov_i32(cpu_pc, cpu_btarget); + tcg_gen_discard_i32(cpu_btarget); + break; + + case DISAS_JUMP: + if (dc->jmp_dest != -1 && !cs->singlestep_enabled) { + /* Direct jump. */ + tcg_gen_discard_i32(cpu_btarget); + + if (dc->jmp_cond != TCG_COND_ALWAYS) { + /* Conditional direct jump. */ + TCGLabel *taken = gen_new_label(); + TCGv_i32 tmp = tcg_temp_new_i32(); + + /* + * Copy bvalue to a temp now, so we can discard bvalue. + * This can avoid writing bvalue to memory when the + * delay slot cannot raise an exception. + */ + tcg_gen_mov_i32(tmp, cpu_bvalue); + tcg_gen_discard_i32(cpu_bvalue); + + tcg_gen_brcondi_i32(dc->jmp_cond, tmp, 0, taken); + gen_goto_tb(dc, 1, dc->base.pc_next); + gen_set_label(taken); + } + gen_goto_tb(dc, 0, dc->jmp_dest); + return; } - gen_helper_raise_exception(cpu_env, tmp); - tcg_temp_free_i32(tmp); - } else { - switch(dc->is_jmp) { - case DISAS_NEXT: - gen_goto_tb(dc, 1, npc); - break; - default: - case DISAS_JUMP: - case DISAS_UPDATE: - /* indicate that the hash table must be used - to find the next TB */ - tcg_gen_exit_tb(NULL, 0); - break; - case DISAS_TB_JUMP: - /* nothing more to generate */ - break; + + /* Indirect jump (or direct jump w/ singlestep) */ + tcg_gen_mov_i32(cpu_pc, cpu_btarget); + tcg_gen_discard_i32(cpu_btarget); + + if (unlikely(cs->singlestep_enabled)) { + gen_raise_exception(dc, EXCP_DEBUG); + } else { + tcg_gen_lookup_and_goto_ptr(); } - } - gen_tb_end(tb, num_insns); + return; - tb->size = dc->pc - pc_start; - tb->icount = num_insns; + default: + g_assert_not_reached(); + } -#ifdef DEBUG_DISAS -#if !SIM_COMPAT - if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) - && qemu_log_in_addr_range(pc_start)) { - FILE *logfile = qemu_log_lock(); - qemu_log("--------------\n"); - log_target_disas(cs, pc_start, dc->pc - pc_start); - qemu_log_unlock(logfile); + /* Finish DISAS_EXIT_* */ + if (unlikely(cs->singlestep_enabled)) { + gen_raise_exception(dc, EXCP_DEBUG); + } else { + tcg_gen_exit_tb(NULL, 0); } -#endif -#endif - assert(!dc->abort_at_next_insn); +} + +static void mb_tr_disas_log(const DisasContextBase *dcb, CPUState *cs) +{ + qemu_log("IN: %s\n", lookup_symbol(dcb->pc_first)); + log_target_disas(cs, dcb->pc_first, dcb->tb->size); +} + +static const TranslatorOps mb_tr_ops = { + .init_disas_context = mb_tr_init_disas_context, + .tb_start = mb_tr_tb_start, + .insn_start = mb_tr_insn_start, + .breakpoint_check = mb_tr_breakpoint_check, + .translate_insn = mb_tr_translate_insn, + .tb_stop = mb_tr_tb_stop, + .disas_log = mb_tr_disas_log, +}; + +void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns) +{ + DisasContext dc; + translator_loop(&mb_tr_ops, &dc.base, cpu, tb, max_insns); } void mb_cpu_dump_state(CPUState *cs, FILE *f, int flags) { MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); CPUMBState *env = &cpu->env; + uint32_t iflags; int i; - if (!env) { - return; - } + qemu_fprintf(f, "pc=0x%08x msr=0x%05x mode=%s(saved=%s) eip=%d ie=%d\n", + env->pc, env->msr, + (env->msr & MSR_UM) ? "user" : "kernel", + (env->msr & MSR_UMS) ? "user" : "kernel", + (bool)(env->msr & MSR_EIP), + (bool)(env->msr & MSR_IE)); - qemu_fprintf(f, "IN: PC=%" PRIx64 " %s\n", - env->sregs[SR_PC], lookup_symbol(env->sregs[SR_PC])); - qemu_fprintf(f, "rmsr=%" PRIx64 " resr=%" PRIx64 " rear=%" PRIx64 " " - "debug=%x imm=%x iflags=%x fsr=%" PRIx64 " " - "rbtr=%" PRIx64 "\n", - env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR], - env->debug, env->imm, env->iflags, env->sregs[SR_FSR], - env->sregs[SR_BTR]); - qemu_fprintf(f, "btaken=%d btarget=%" PRIx64 " mode=%s(saved=%s) " - "eip=%d ie=%d\n", - env->btaken, env->btarget, - (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel", - (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel", - (bool)(env->sregs[SR_MSR] & MSR_EIP), - (bool)(env->sregs[SR_MSR] & MSR_IE)); - for (i = 0; i < 12; i++) { - qemu_fprintf(f, "rpvr%2.2d=%8.8x ", i, env->pvr.regs[i]); - if ((i + 1) % 4 == 0) { - qemu_fprintf(f, "\n"); - } + iflags = env->iflags; + qemu_fprintf(f, "iflags: 0x%08x", iflags); + if (iflags & IMM_FLAG) { + qemu_fprintf(f, " IMM(0x%08x)", env->imm); + } + if (iflags & BIMM_FLAG) { + qemu_fprintf(f, " BIMM"); } + if (iflags & D_FLAG) { + qemu_fprintf(f, " D(btarget=0x%08x)", env->btarget); + } + if (iflags & DRTI_FLAG) { + qemu_fprintf(f, " DRTI"); + } + if (iflags & DRTE_FLAG) { + qemu_fprintf(f, " DRTE"); + } + if (iflags & DRTB_FLAG) { + qemu_fprintf(f, " DRTB"); + } + if (iflags & ESR_ESS_FLAG) { + qemu_fprintf(f, " ESR_ESS(0x%04x)", iflags & ESR_ESS_MASK); + } + + qemu_fprintf(f, "\nesr=0x%04x fsr=0x%02x btr=0x%08x edr=0x%x\n" + "ear=0x" TARGET_FMT_lx " slr=0x%x shr=0x%x\n", + env->esr, env->fsr, env->btr, env->edr, + env->ear, env->slr, env->shr); - /* Registers that aren't modeled are reported as 0 */ - qemu_fprintf(f, "redr=%" PRIx64 " rpid=0 rzpr=0 rtlbx=0 rtlbsx=0 " - "rtlblo=0 rtlbhi=0\n", env->sregs[SR_EDR]); - qemu_fprintf(f, "slr=%x shr=%x\n", env->slr, env->shr); for (i = 0; i < 32; i++) { - qemu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]); - if ((i + 1) % 4 == 0) - qemu_fprintf(f, "\n"); - } - qemu_fprintf(f, "\n\n"); + qemu_fprintf(f, "r%2.2d=%08x%c", + i, env->regs[i], i % 4 == 3 ? '\n' : ' '); + } + qemu_fprintf(f, "\n"); } void mb_tcg_init(void) { - int i; +#define R(X) { &cpu_R[X], offsetof(CPUMBState, regs[X]), "r" #X } +#define SP(X) { &cpu_##X, offsetof(CPUMBState, X), #X } + + static const struct { + TCGv_i32 *var; int ofs; char name[8]; + } i32s[] = { + /* + * Note that r0 is handled specially in reg_for_read + * and reg_for_write. Nothing should touch cpu_R[0]. + * Leave that element NULL, which will assert quickly + * inside the tcg generator functions. + */ + R(1), R(2), R(3), R(4), R(5), R(6), R(7), + R(8), R(9), R(10), R(11), R(12), R(13), R(14), R(15), + R(16), R(17), R(18), R(19), R(20), R(21), R(22), R(23), + R(24), R(25), R(26), R(27), R(28), R(29), R(30), R(31), + + SP(pc), + SP(msr), + SP(msr_c), + SP(imm), + SP(iflags), + SP(bvalue), + SP(btarget), + SP(res_val), + }; + +#undef R +#undef SP - env_debug = tcg_global_mem_new_i32(cpu_env, - offsetof(CPUMBState, debug), - "debug0"); - env_iflags = tcg_global_mem_new_i32(cpu_env, - offsetof(CPUMBState, iflags), - "iflags"); - env_imm = tcg_global_mem_new_i32(cpu_env, - offsetof(CPUMBState, imm), - "imm"); - env_btarget = tcg_global_mem_new_i64(cpu_env, - offsetof(CPUMBState, btarget), - "btarget"); - env_btaken = tcg_global_mem_new_i32(cpu_env, - offsetof(CPUMBState, btaken), - "btaken"); - env_res_addr = tcg_global_mem_new(cpu_env, - offsetof(CPUMBState, res_addr), - "res_addr"); - env_res_val = tcg_global_mem_new_i32(cpu_env, - offsetof(CPUMBState, res_val), - "res_val"); - for (i = 0; i < ARRAY_SIZE(cpu_R); i++) { - cpu_R[i] = tcg_global_mem_new_i32(cpu_env, - offsetof(CPUMBState, regs[i]), - regnames[i]); - } - for (i = 0; i < ARRAY_SIZE(cpu_SR); i++) { - cpu_SR[i] = tcg_global_mem_new_i64(cpu_env, - offsetof(CPUMBState, sregs[i]), - special_regnames[i]); + for (int i = 0; i < ARRAY_SIZE(i32s); ++i) { + *i32s[i].var = + tcg_global_mem_new_i32(cpu_env, i32s[i].ofs, i32s[i].name); } + + cpu_res_addr = + tcg_global_mem_new(cpu_env, offsetof(CPUMBState, res_addr), "res_addr"); } void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb, target_ulong *data) { - env->sregs[SR_PC] = data[0]; + env->pc = data[0]; + env->iflags = data[1]; } diff --git a/target/mips/Makefile.objs b/target/mips/Makefile.objs deleted file mode 100644 index 91eb691833b2885498b7009d2a03ca2b1eff9297..0000000000000000000000000000000000000000 --- a/target/mips/Makefile.objs +++ /dev/null @@ -1,6 +0,0 @@ -obj-y += translate.o cpu.o gdbstub.o helper.o -obj-y += op_helper.o cp0_helper.o fpu_helper.o -obj-y += dsp_helper.o lmi_helper.o msa_helper.o -obj-$(CONFIG_SOFTMMU) += mips-semi.o -obj-$(CONFIG_SOFTMMU) += machine.o cp0_timer.o -obj-$(CONFIG_KVM) += kvm.o diff --git a/target/mips/cp0_helper.c b/target/mips/cp0_helper.c index bbf12e4a975b4d709ebff77ac3d1ad8bb807ca90..a1b5140ccaf085f7ccd198be1e4ad7ddd8d25b56 100644 --- a/target/mips/cp0_helper.c +++ b/target/mips/cp0_helper.c @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -203,6 +203,31 @@ static void sync_c0_entryhi(CPUMIPSState *cpu, int tc) *tcst |= asid; } +/* XXX: do not use a global */ +uint32_t cpu_mips_get_random(CPUMIPSState *env) +{ + static uint32_t seed = 1; + static uint32_t prev_idx; + uint32_t idx; + uint32_t nb_rand_tlb = env->tlb->nb_tlb - env->CP0_Wired; + + if (nb_rand_tlb == 1) { + return env->tlb->nb_tlb - 1; + } + + /* Don't return same value twice, so get another value */ + do { + /* + * Use a simple algorithm of Linear Congruential Generator + * from ISO/IEC 9899 standard. + */ + seed = 1103515245 * seed + 12345; + idx = (seed >> 16) % nb_rand_tlb + env->CP0_Wired; + } while (idx == prev_idx); + prev_idx = idx; + return idx; +} + /* CP0 helpers */ target_ulong helper_mfc0_mvpcontrol(CPUMIPSState *env) { @@ -375,16 +400,9 @@ target_ulong helper_mftc0_entryhi(CPUMIPSState *env) target_ulong helper_mftc0_cause(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - int32_t tccause; CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); - if (other_tc == other->current_tc) { - tccause = other->CP0_Cause; - } else { - tccause = other->CP0_Cause; - } - - return tccause; + return other->CP0_Cause; } target_ulong helper_mftc0_status(CPUMIPSState *env) @@ -874,13 +892,28 @@ void helper_mtc0_memorymapid(CPUMIPSState *env, target_ulong arg1) void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask) { - uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1); - if (!(env->insn_flags & ISA_MIPS32R6) || (arg1 == ~0) || - (mask == 0x0000 || mask == 0x0003 || mask == 0x000F || - mask == 0x003F || mask == 0x00FF || mask == 0x03FF || - mask == 0x0FFF || mask == 0x3FFF || mask == 0xFFFF)) { - env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1)); + uint32_t mask; + int maskbits; + + /* Don't care MASKX as we don't support 1KB page */ + mask = extract32((uint32_t)arg1, CP0PM_MASK, 16); + maskbits = cto32(mask); + + /* Ensure no more set bit after first zero */ + if ((mask >> maskbits) != 0) { + goto invalid; + } + /* We don't support VTLB entry smaller than target page */ + if ((maskbits + 12) < TARGET_PAGE_BITS) { + goto invalid; } + env->CP0_PageMask = mask << CP0PM_MASK; + + return; + +invalid: + /* When invalid, set to default target page size. */ + env->CP0_PageMask = (~TARGET_PAGE_MASK >> 12) << CP0PM_MASK; } void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1) diff --git a/target/mips/cp0_timer.c b/target/mips/cp0_timer.c index bd7efb152ddc9283865d631e686dbe1431392f69..5ec0d6249e93ceedb60aad97085a35a08f8cca07 100644 --- a/target/mips/cp0_timer.c +++ b/target/mips/cp0_timer.c @@ -27,43 +27,17 @@ #include "sysemu/kvm.h" #include "internal.h" -#define TIMER_PERIOD 10 /* 10 ns period for 100 Mhz frequency */ - -/* XXX: do not use a global */ -uint32_t cpu_mips_get_random(CPUMIPSState *env) -{ - static uint32_t seed = 1; - static uint32_t prev_idx = 0; - uint32_t idx; - uint32_t nb_rand_tlb = env->tlb->nb_tlb - env->CP0_Wired; - - if (nb_rand_tlb == 1) { - return env->tlb->nb_tlb - 1; - } - - /* Don't return same value twice, so get another value */ - do { - /* - * Use a simple algorithm of Linear Congruential Generator - * from ISO/IEC 9899 standard. - */ - seed = 1103515245 * seed + 12345; - idx = (seed >> 16) % nb_rand_tlb + env->CP0_Wired; - } while (idx == prev_idx); - prev_idx = idx; - return idx; -} - /* MIPS R4K timer */ static void cpu_mips_timer_update(CPUMIPSState *env) { - uint64_t now, next; + uint64_t now_ns, next_ns; uint32_t wait; - now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - wait = env->CP0_Compare - env->CP0_Count - (uint32_t)(now / TIMER_PERIOD); - next = now + (uint64_t)wait * TIMER_PERIOD; - timer_mod(env->timer, next); + now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + wait = env->CP0_Compare - env->CP0_Count - + (uint32_t)(now_ns / env->cp0_count_ns); + next_ns = now_ns + (uint64_t)wait * env->cp0_count_ns; + timer_mod(env->timer, next_ns); } /* Expire the timer. */ @@ -81,16 +55,16 @@ uint32_t cpu_mips_get_count(CPUMIPSState *env) if (env->CP0_Cause & (1 << CP0Ca_DC)) { return env->CP0_Count; } else { - uint64_t now; + uint64_t now_ns; - now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); if (timer_pending(env->timer) - && timer_expired(env->timer, now)) { + && timer_expired(env->timer, now_ns)) { /* The timer has already expired. */ cpu_mips_timer_expire(env); } - return env->CP0_Count + (uint32_t)(now / TIMER_PERIOD); + return env->CP0_Count + (uint32_t)(now_ns / env->cp0_count_ns); } } @@ -106,7 +80,8 @@ void cpu_mips_store_count(CPUMIPSState *env, uint32_t count) } else { /* Store new count register */ env->CP0_Count = count - - (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD); + (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / + env->cp0_count_ns); /* Update timer timer */ cpu_mips_timer_update(env); } @@ -133,7 +108,7 @@ void cpu_mips_stop_count(CPUMIPSState *env) { /* Store the current value */ env->CP0_Count += (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / - TIMER_PERIOD); + env->cp0_count_ns); } static void mips_timer_cb(void *opaque) diff --git a/target/mips/cpu-param.h b/target/mips/cpu-param.h index 308660d29d346d856a09f440f479f03a33d0200b..9c4a6ea45e204ca485d7199719ccdd0aaf3fac67 100644 --- a/target/mips/cpu-param.h +++ b/target/mips/cpu-param.h @@ -23,7 +23,12 @@ # define TARGET_VIRT_ADDR_SPACE_BITS 32 #endif #endif +#ifdef CONFIG_USER_ONLY #define TARGET_PAGE_BITS 12 +#else +#define TARGET_PAGE_BITS_VARY +#define TARGET_PAGE_BITS_MIN 12 +#endif #define NB_MMU_MODES 4 #endif diff --git a/target/mips/cpu-qom.h b/target/mips/cpu-qom.h index 9d0df6c034b4f19eed2710da8ffcfa9ea83e8837..826ab1301932b1040b3d04c1a37ca773ef8facc2 100644 --- a/target/mips/cpu-qom.h +++ b/target/mips/cpu-qom.h @@ -21,6 +21,7 @@ #define QEMU_MIPS_CPU_QOM_H #include "hw/core/cpu.h" +#include "qom/object.h" #ifdef TARGET_MIPS64 #define TYPE_MIPS_CPU "mips64-cpu" @@ -28,12 +29,8 @@ #define TYPE_MIPS_CPU "mips-cpu" #endif -#define MIPS_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(MIPSCPUClass, (klass), TYPE_MIPS_CPU) -#define MIPS_CPU(obj) \ - OBJECT_CHECK(MIPSCPU, (obj), TYPE_MIPS_CPU) -#define MIPS_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(MIPSCPUClass, (obj), TYPE_MIPS_CPU) +OBJECT_DECLARE_TYPE(MIPSCPU, MIPSCPUClass, + MIPS_CPU) /** * MIPSCPUClass: @@ -42,7 +39,7 @@ * * A MIPS CPU model. */ -typedef struct MIPSCPUClass { +struct MIPSCPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ @@ -50,8 +47,7 @@ typedef struct MIPSCPUClass { DeviceRealize parent_realize; DeviceReset parent_reset; const struct mips_def_t *cpu_def; -} MIPSCPUClass; +}; -typedef struct MIPSCPU MIPSCPU; #endif diff --git a/target/mips/cpu.c b/target/mips/cpu.c index e86cd065483b3beb87b3604e8b09f3601be94838..76d50b00b42b38d0c266fe735d4127ddf51b20d8 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -19,14 +19,17 @@ */ #include "qemu/osdep.h" +#include "qemu/cutils.h" #include "qapi/error.h" #include "cpu.h" #include "internal.h" #include "kvm_mips.h" #include "qemu/module.h" #include "sysemu/kvm.h" +#include "sysemu/qtest.h" #include "exec/exec-all.h" - +#include "hw/qdev-properties.h" +#include "hw/qdev-clock.h" static void mips_cpu_set_pc(CPUState *cs, vaddr value) { @@ -134,6 +137,21 @@ static void mips_cpu_disas_set_info(CPUState *s, disassemble_info *info) } } +/* + * Since commit 6af0bf9c7c3 this model assumes a CPU clocked at 200MHz. + */ +#define CPU_FREQ_HZ_DEFAULT 200000000 +#define CP0_COUNT_RATE_DEFAULT 2 + +static void mips_cp0_period_set(MIPSCPU *cpu) +{ + CPUMIPSState *env = &cpu->env; + + env->cp0_count_ns = cpu->cp0_count_rate + * clock_get_ns(MIPS_CPU(cpu)->clock); + assert(env->cp0_count_ns); +} + static void mips_cpu_realizefn(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); @@ -141,6 +159,20 @@ static void mips_cpu_realizefn(DeviceState *dev, Error **errp) MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev); Error *local_err = NULL; + if (!clock_get(cpu->clock)) { +#ifndef CONFIG_USER_ONLY + if (!qtest_enabled()) { + g_autofree char *cpu_freq_str = freq_to_str(CPU_FREQ_HZ_DEFAULT); + + warn_report("CPU input clock is not connected to any output clock, " + "using default frequency of %s.", cpu_freq_str); + } +#endif + /* Initialize the frequency in case the clock remains unconnected. */ + clock_set_hz(cpu->clock, CPU_FREQ_HZ_DEFAULT); + } + mips_cp0_period_set(cpu); + cpu_exec_realizefn(cs, &local_err); if (local_err != NULL) { error_propagate(errp, local_err); @@ -162,6 +194,7 @@ static void mips_cpu_initfn(Object *obj) MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(obj); cpu_set_cpustate_pointers(cpu); + cpu->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, cpu); env->cpu_model = mcc->cpu_def; } @@ -181,6 +214,13 @@ static ObjectClass *mips_cpu_class_by_name(const char *cpu_model) return oc; } +static Property mips_cpu_properties[] = { + /* CP0 timer running at half the clock of the CPU */ + DEFINE_PROP_UINT32("cp0-count-rate", MIPSCPU, cp0_count_rate, + CP0_COUNT_RATE_DEFAULT), + DEFINE_PROP_END_OF_LIST() +}; + static void mips_cpu_class_init(ObjectClass *c, void *data) { MIPSCPUClass *mcc = MIPS_CPU_CLASS(c); @@ -190,6 +230,7 @@ static void mips_cpu_class_init(ObjectClass *c, void *data) device_class_set_parent_realize(dc, mips_cpu_realizefn, &mcc->parent_realize); device_class_set_parent_reset(dc, mips_cpu_reset, &mcc->parent_reset); + device_class_set_props(dc, mips_cpu_properties); cc->class_by_name = mips_cpu_class_by_name; cc->has_work = mips_cpu_has_work; @@ -257,3 +298,15 @@ static void mips_cpu_register_types(void) } type_init(mips_cpu_register_types) + +/* Could be used by generic CPU object */ +MIPSCPU *mips_cpu_create_with_clock(const char *cpu_type, Clock *cpu_refclk) +{ + DeviceState *cpu; + + cpu = DEVICE(object_new(cpu_type)); + qdev_connect_clock_in(cpu, "clk-in", cpu_refclk); + qdev_realize(cpu, NULL, &error_abort); + + return MIPS_CPU(cpu); +} diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 94d01ea79876a1c123df977a7a7655cb61c0f6b2..23f8c6f96cd3e69c3e8b494828a5c18121423bdd 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -4,6 +4,7 @@ #include "cpu-qom.h" #include "exec/cpu-defs.h" #include "fpu/softfloat-types.h" +#include "hw/clock.h" #include "mips-defs.h" #define TCG_GUEST_DEFAULT_MO (0) @@ -198,8 +199,8 @@ typedef struct mips_def_t mips_def_t; * 3 Config3 WatchLo3 WatchHi * 4 Config4 WatchLo4 WatchHi * 5 Config5 WatchLo5 WatchHi - * 6 WatchLo6 WatchHi - * 7 WatchLo7 WatchHi + * 6 Config6 WatchLo6 WatchHi + * 7 Config7 WatchLo7 WatchHi * * * Register 20 Register 21 Register 22 Register 23 @@ -618,6 +619,7 @@ struct CPUMIPSState { * CP0 Register 5 */ int32_t CP0_PageMask; +#define CP0PM_MASK 13 int32_t CP0_PageGrain_rw_bitmask; int32_t CP0_PageGrain; #define CP0PG_RIE 31 @@ -940,7 +942,35 @@ struct CPUMIPSState { #define CP0C5_UFR 2 #define CP0C5_NFExists 0 int32_t CP0_Config6; + int32_t CP0_Config6_rw_bitmask; +#define CP0C6_BPPASS 31 +#define CP0C6_KPOS 24 +#define CP0C6_KE 23 +#define CP0C6_VTLBONLY 22 +#define CP0C6_LASX 21 +#define CP0C6_SSEN 20 +#define CP0C6_DISDRTIME 19 +#define CP0C6_PIXNUEN 18 +#define CP0C6_SCRAND 17 +#define CP0C6_LLEXCEN 16 +#define CP0C6_DISVC 15 +#define CP0C6_VCLRU 14 +#define CP0C6_DCLRU 13 +#define CP0C6_PIXUEN 12 +#define CP0C6_DISBLKLYEN 11 +#define CP0C6_UMEMUALEN 10 +#define CP0C6_SFBEN 8 +#define CP0C6_FLTINT 7 +#define CP0C6_VLTINT 6 +#define CP0C6_DISBTB 5 +#define CP0C6_STPREFCTL 2 +#define CP0C6_INSTPREF 1 +#define CP0C6_DATAPREF 0 int32_t CP0_Config7; + int64_t CP0_Config7_rw_bitmask; +#define CP0C7_NAPCGEN 2 +#define CP0C7_UNIMUEN 1 +#define CP0C7_VFPUCGEN 0 uint64_t CP0_LLAddr; uint64_t CP0_MAAR[MIPS_MAAR_MAX]; int32_t CP0_MAARI; @@ -1117,11 +1147,15 @@ struct CPUMIPSState { struct MIPSITUState *itu; MemoryRegion *itc_tag; /* ITC Configuration Tags */ target_ulong exception_base; /* ExceptionBase input to the core */ + uint64_t cp0_count_ns; /* CP0_Count clock period (in nanoseconds) */ }; /** * MIPSCPU: * @env: #CPUMIPSState + * @clock: this CPU input clock (may be connected + * to an output clock from another device). + * @cp0_count_rate: rate at which the coprocessor 0 counter increments * * A MIPS CPU. */ @@ -1130,8 +1164,17 @@ struct MIPSCPU { CPUState parent_obj; /*< public >*/ + Clock *clock; CPUNegativeOffsetState neg; CPUMIPSState env; + /* + * The Count register acts as a timer, incrementing at a constant rate, + * whether or not an instruction is executed, retired, or any forward + * progress is made through the pipeline. The rate at which the counter + * increments is implementation dependent, and is a function of the + * pipeline clock of the processor, not the issue width of the processor. + */ + unsigned cp0_count_rate; }; @@ -1265,4 +1308,16 @@ static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc, MIPS_HFLAG_HWRENA_ULR); } +/** + * mips_cpu_create_with_clock: + * @typename: a MIPS CPU type. + * @cpu_refclk: this cpu input clock (an output clock of another device) + * + * Instantiates a MIPS CPU, set the input clock of the CPU to @cpu_refclk, + * then realizes the CPU. + * + * Returns: A #CPUState or %NULL if an error occurred. + */ +MIPSCPU *mips_cpu_create_with_clock(const char *cpu_type, Clock *cpu_refclk); + #endif /* MIPS_CPU_H */ diff --git a/target/mips/dsp_helper.c b/target/mips/dsp_helper.c index 8c58eeb0bf86bf315d10e9f1d80b4c38ad53e46b..09b6e5fb15aa54af06b19d0c04cc1df082a5d56c 100644 --- a/target/mips/dsp_helper.c +++ b/target/mips/dsp_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c index 5287c86c619290e3156dd18b3ddfdb38b7785d9e..020b768e87b9637f853229968f2f369f674c7b18 100644 --- a/target/mips/fpu_helper.c +++ b/target/mips/fpu_helper.c @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -189,43 +189,48 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt) } } -int ieee_ex_to_mips(int xcpt) +static inline int ieee_to_mips_xcpt(int ieee_xcpt) { - int ret = 0; - if (xcpt) { - if (xcpt & float_flag_invalid) { - ret |= FP_INVALID; - } - if (xcpt & float_flag_overflow) { - ret |= FP_OVERFLOW; - } - if (xcpt & float_flag_underflow) { - ret |= FP_UNDERFLOW; - } - if (xcpt & float_flag_divbyzero) { - ret |= FP_DIV0; - } - if (xcpt & float_flag_inexact) { - ret |= FP_INEXACT; - } + int mips_xcpt = 0; + + if (ieee_xcpt & float_flag_invalid) { + mips_xcpt |= FP_INVALID; } - return ret; + if (ieee_xcpt & float_flag_overflow) { + mips_xcpt |= FP_OVERFLOW; + } + if (ieee_xcpt & float_flag_underflow) { + mips_xcpt |= FP_UNDERFLOW; + } + if (ieee_xcpt & float_flag_divbyzero) { + mips_xcpt |= FP_DIV0; + } + if (ieee_xcpt & float_flag_inexact) { + mips_xcpt |= FP_INEXACT; + } + + return mips_xcpt; } static inline void update_fcr31(CPUMIPSState *env, uintptr_t pc) { - int tmp = ieee_ex_to_mips(get_float_exception_flags( - &env->active_fpu.fp_status)); + int ieee_exception_flags = get_float_exception_flags( + &env->active_fpu.fp_status); + int mips_exception_flags = 0; - SET_FP_CAUSE(env->active_fpu.fcr31, tmp); + if (ieee_exception_flags) { + mips_exception_flags = ieee_to_mips_xcpt(ieee_exception_flags); + } + + SET_FP_CAUSE(env->active_fpu.fcr31, mips_exception_flags); - if (tmp) { + if (mips_exception_flags) { set_float_exception_flags(0, &env->active_fpu.fp_status); - if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp) { + if (GET_FP_ENABLE(env->active_fpu.fcr31) & mips_exception_flags) { do_raise_exception(env, EXCP_FPE, pc); } else { - UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp); + UPDATE_FP_FLAGS(env->active_fpu.fcr31, mips_exception_flags); } } } @@ -978,27 +983,46 @@ uint32_t helper_float_floor_2008_w_s(CPUMIPSState *env, uint32_t fst0) } /* unary operations, not modifying fp status */ -#define FLOAT_UNOP(name) \ -uint64_t helper_float_ ## name ## _d(uint64_t fdt0) \ -{ \ - return float64_ ## name(fdt0); \ -} \ -uint32_t helper_float_ ## name ## _s(uint32_t fst0) \ -{ \ - return float32_ ## name(fst0); \ -} \ -uint64_t helper_float_ ## name ## _ps(uint64_t fdt0) \ -{ \ - uint32_t wt0; \ - uint32_t wth0; \ - \ - wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF); \ - wth0 = float32_ ## name(fdt0 >> 32); \ - return ((uint64_t)wth0 << 32) | wt0; \ + +uint64_t helper_float_abs_d(uint64_t fdt0) +{ + return float64_abs(fdt0); +} + +uint32_t helper_float_abs_s(uint32_t fst0) +{ + return float32_abs(fst0); +} + +uint64_t helper_float_abs_ps(uint64_t fdt0) +{ + uint32_t wt0; + uint32_t wth0; + + wt0 = float32_abs(fdt0 & 0XFFFFFFFF); + wth0 = float32_abs(fdt0 >> 32); + return ((uint64_t)wth0 << 32) | wt0; +} + +uint64_t helper_float_chs_d(uint64_t fdt0) +{ + return float64_chs(fdt0); +} + +uint32_t helper_float_chs_s(uint32_t fst0) +{ + return float32_chs(fst0); +} + +uint64_t helper_float_chs_ps(uint64_t fdt0) +{ + uint32_t wt0; + uint32_t wth0; + + wt0 = float32_chs(fdt0 & 0XFFFFFFFF); + wth0 = float32_chs(fdt0 >> 32); + return ((uint64_t)wth0 << 32) | wt0; } -FLOAT_UNOP(abs) -FLOAT_UNOP(chs) -#undef FLOAT_UNOP /* MIPS specific unary operations */ uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0) @@ -1059,14 +1083,14 @@ uint32_t helper_float_recip1_s(CPUMIPSState *env, uint32_t fst0) uint64_t helper_float_recip1_ps(CPUMIPSState *env, uint64_t fdt0) { - uint32_t fst2; + uint32_t fstl2; uint32_t fsth2; - fst2 = float32_div(float32_one, fdt0 & 0XFFFFFFFF, - &env->active_fpu.fp_status); + fstl2 = float32_div(float32_one, fdt0 & 0XFFFFFFFF, + &env->active_fpu.fp_status); fsth2 = float32_div(float32_one, fdt0 >> 32, &env->active_fpu.fp_status); update_fcr31(env, GETPC()); - return ((uint64_t)fsth2 << 32) | fst2; + return ((uint64_t)fsth2 << 32) | fstl2; } uint64_t helper_float_rsqrt1_d(CPUMIPSState *env, uint64_t fdt0) @@ -1091,31 +1115,34 @@ uint32_t helper_float_rsqrt1_s(CPUMIPSState *env, uint32_t fst0) uint64_t helper_float_rsqrt1_ps(CPUMIPSState *env, uint64_t fdt0) { - uint32_t fst2; + uint32_t fstl2; uint32_t fsth2; - fst2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); + fstl2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status); - fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status); + fstl2 = float32_div(float32_one, fstl2, &env->active_fpu.fp_status); fsth2 = float32_div(float32_one, fsth2, &env->active_fpu.fp_status); update_fcr31(env, GETPC()); - return ((uint64_t)fsth2 << 32) | fst2; + return ((uint64_t)fsth2 << 32) | fstl2; } -#define FLOAT_RINT(name, bits) \ -uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \ - uint ## bits ## _t fs) \ -{ \ - uint ## bits ## _t fdret; \ - \ - fdret = float ## bits ## _round_to_int(fs, &env->active_fpu.fp_status); \ - update_fcr31(env, GETPC()); \ - return fdret; \ +uint64_t helper_float_rint_d(CPUMIPSState *env, uint64_t fs) +{ + uint64_t fdret; + + fdret = float64_round_to_int(fs, &env->active_fpu.fp_status); + update_fcr31(env, GETPC()); + return fdret; } -FLOAT_RINT(rint_s, 32) -FLOAT_RINT(rint_d, 64) -#undef FLOAT_RINT +uint32_t helper_float_rint_s(CPUMIPSState *env, uint32_t fs) +{ + uint32_t fdret; + + fdret = float32_round_to_int(fs, &env->active_fpu.fp_status); + update_fcr31(env, GETPC()); + return fdret; +} #define FLOAT_CLASS_SIGNALING_NAN 0x001 #define FLOAT_CLASS_QUIET_NAN 0x002 @@ -1128,91 +1155,220 @@ FLOAT_RINT(rint_d, 64) #define FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100 #define FLOAT_CLASS_POSITIVE_ZERO 0x200 -#define FLOAT_CLASS(name, bits) \ -uint ## bits ## _t float_ ## name(uint ## bits ## _t arg, \ - float_status *status) \ -{ \ - if (float ## bits ## _is_signaling_nan(arg, status)) { \ - return FLOAT_CLASS_SIGNALING_NAN; \ - } else if (float ## bits ## _is_quiet_nan(arg, status)) { \ - return FLOAT_CLASS_QUIET_NAN; \ - } else if (float ## bits ## _is_neg(arg)) { \ - if (float ## bits ## _is_infinity(arg)) { \ - return FLOAT_CLASS_NEGATIVE_INFINITY; \ - } else if (float ## bits ## _is_zero(arg)) { \ - return FLOAT_CLASS_NEGATIVE_ZERO; \ - } else if (float ## bits ## _is_zero_or_denormal(arg)) { \ - return FLOAT_CLASS_NEGATIVE_SUBNORMAL; \ - } else { \ - return FLOAT_CLASS_NEGATIVE_NORMAL; \ - } \ - } else { \ - if (float ## bits ## _is_infinity(arg)) { \ - return FLOAT_CLASS_POSITIVE_INFINITY; \ - } else if (float ## bits ## _is_zero(arg)) { \ - return FLOAT_CLASS_POSITIVE_ZERO; \ - } else if (float ## bits ## _is_zero_or_denormal(arg)) { \ - return FLOAT_CLASS_POSITIVE_SUBNORMAL; \ - } else { \ - return FLOAT_CLASS_POSITIVE_NORMAL; \ - } \ - } \ -} \ - \ -uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \ - uint ## bits ## _t arg) \ -{ \ - return float_ ## name(arg, &env->active_fpu.fp_status); \ -} - -FLOAT_CLASS(class_s, 32) -FLOAT_CLASS(class_d, 64) -#undef FLOAT_CLASS +uint64_t float_class_d(uint64_t arg, float_status *status) +{ + if (float64_is_signaling_nan(arg, status)) { + return FLOAT_CLASS_SIGNALING_NAN; + } else if (float64_is_quiet_nan(arg, status)) { + return FLOAT_CLASS_QUIET_NAN; + } else if (float64_is_neg(arg)) { + if (float64_is_infinity(arg)) { + return FLOAT_CLASS_NEGATIVE_INFINITY; + } else if (float64_is_zero(arg)) { + return FLOAT_CLASS_NEGATIVE_ZERO; + } else if (float64_is_zero_or_denormal(arg)) { + return FLOAT_CLASS_NEGATIVE_SUBNORMAL; + } else { + return FLOAT_CLASS_NEGATIVE_NORMAL; + } + } else { + if (float64_is_infinity(arg)) { + return FLOAT_CLASS_POSITIVE_INFINITY; + } else if (float64_is_zero(arg)) { + return FLOAT_CLASS_POSITIVE_ZERO; + } else if (float64_is_zero_or_denormal(arg)) { + return FLOAT_CLASS_POSITIVE_SUBNORMAL; + } else { + return FLOAT_CLASS_POSITIVE_NORMAL; + } + } +} + +uint64_t helper_float_class_d(CPUMIPSState *env, uint64_t arg) +{ + return float_class_d(arg, &env->active_fpu.fp_status); +} + +uint32_t float_class_s(uint32_t arg, float_status *status) +{ + if (float32_is_signaling_nan(arg, status)) { + return FLOAT_CLASS_SIGNALING_NAN; + } else if (float32_is_quiet_nan(arg, status)) { + return FLOAT_CLASS_QUIET_NAN; + } else if (float32_is_neg(arg)) { + if (float32_is_infinity(arg)) { + return FLOAT_CLASS_NEGATIVE_INFINITY; + } else if (float32_is_zero(arg)) { + return FLOAT_CLASS_NEGATIVE_ZERO; + } else if (float32_is_zero_or_denormal(arg)) { + return FLOAT_CLASS_NEGATIVE_SUBNORMAL; + } else { + return FLOAT_CLASS_NEGATIVE_NORMAL; + } + } else { + if (float32_is_infinity(arg)) { + return FLOAT_CLASS_POSITIVE_INFINITY; + } else if (float32_is_zero(arg)) { + return FLOAT_CLASS_POSITIVE_ZERO; + } else if (float32_is_zero_or_denormal(arg)) { + return FLOAT_CLASS_POSITIVE_SUBNORMAL; + } else { + return FLOAT_CLASS_POSITIVE_NORMAL; + } + } +} + +uint32_t helper_float_class_s(CPUMIPSState *env, uint32_t arg) +{ + return float_class_s(arg, &env->active_fpu.fp_status); +} /* binary operations */ -#define FLOAT_BINOP(name) \ -uint64_t helper_float_ ## name ## _d(CPUMIPSState *env, \ - uint64_t fdt0, uint64_t fdt1) \ -{ \ - uint64_t dt2; \ - \ - dt2 = float64_ ## name(fdt0, fdt1, &env->active_fpu.fp_status);\ - update_fcr31(env, GETPC()); \ - return dt2; \ -} \ - \ -uint32_t helper_float_ ## name ## _s(CPUMIPSState *env, \ - uint32_t fst0, uint32_t fst1) \ -{ \ - uint32_t wt2; \ - \ - wt2 = float32_ ## name(fst0, fst1, &env->active_fpu.fp_status);\ - update_fcr31(env, GETPC()); \ - return wt2; \ -} \ - \ -uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env, \ - uint64_t fdt0, \ - uint64_t fdt1) \ -{ \ - uint32_t fst0 = fdt0 & 0XFFFFFFFF; \ - uint32_t fsth0 = fdt0 >> 32; \ - uint32_t fst1 = fdt1 & 0XFFFFFFFF; \ - uint32_t fsth1 = fdt1 >> 32; \ - uint32_t wt2; \ - uint32_t wth2; \ - \ - wt2 = float32_ ## name(fst0, fst1, &env->active_fpu.fp_status); \ - wth2 = float32_ ## name(fsth0, fsth1, &env->active_fpu.fp_status); \ - update_fcr31(env, GETPC()); \ - return ((uint64_t)wth2 << 32) | wt2; \ -} - -FLOAT_BINOP(add) -FLOAT_BINOP(sub) -FLOAT_BINOP(mul) -FLOAT_BINOP(div) -#undef FLOAT_BINOP + +uint64_t helper_float_add_d(CPUMIPSState *env, + uint64_t fdt0, uint64_t fdt1) +{ + uint64_t dt2; + + dt2 = float64_add(fdt0, fdt1, &env->active_fpu.fp_status); + update_fcr31(env, GETPC()); + return dt2; +} + +uint32_t helper_float_add_s(CPUMIPSState *env, + uint32_t fst0, uint32_t fst1) +{ + uint32_t wt2; + + wt2 = float32_add(fst0, fst1, &env->active_fpu.fp_status); + update_fcr31(env, GETPC()); + return wt2; +} + +uint64_t helper_float_add_ps(CPUMIPSState *env, + uint64_t fdt0, uint64_t fdt1) +{ + uint32_t fstl0 = fdt0 & 0XFFFFFFFF; + uint32_t fsth0 = fdt0 >> 32; + uint32_t fstl1 = fdt1 & 0XFFFFFFFF; + uint32_t fsth1 = fdt1 >> 32; + uint32_t wtl2; + uint32_t wth2; + + wtl2 = float32_add(fstl0, fstl1, &env->active_fpu.fp_status); + wth2 = float32_add(fsth0, fsth1, &env->active_fpu.fp_status); + update_fcr31(env, GETPC()); + return ((uint64_t)wth2 << 32) | wtl2; +} + +uint64_t helper_float_sub_d(CPUMIPSState *env, + uint64_t fdt0, uint64_t fdt1) +{ + uint64_t dt2; + + dt2 = float64_sub(fdt0, fdt1, &env->active_fpu.fp_status); + update_fcr31(env, GETPC()); + return dt2; +} + +uint32_t helper_float_sub_s(CPUMIPSState *env, + uint32_t fst0, uint32_t fst1) +{ + uint32_t wt2; + + wt2 = float32_sub(fst0, fst1, &env->active_fpu.fp_status); + update_fcr31(env, GETPC()); + return wt2; +} + +uint64_t helper_float_sub_ps(CPUMIPSState *env, + uint64_t fdt0, uint64_t fdt1) +{ + uint32_t fstl0 = fdt0 & 0XFFFFFFFF; + uint32_t fsth0 = fdt0 >> 32; + uint32_t fstl1 = fdt1 & 0XFFFFFFFF; + uint32_t fsth1 = fdt1 >> 32; + uint32_t wtl2; + uint32_t wth2; + + wtl2 = float32_sub(fstl0, fstl1, &env->active_fpu.fp_status); + wth2 = float32_sub(fsth0, fsth1, &env->active_fpu.fp_status); + update_fcr31(env, GETPC()); + return ((uint64_t)wth2 << 32) | wtl2; +} + +uint64_t helper_float_mul_d(CPUMIPSState *env, + uint64_t fdt0, uint64_t fdt1) +{ + uint64_t dt2; + + dt2 = float64_mul(fdt0, fdt1, &env->active_fpu.fp_status); + update_fcr31(env, GETPC()); + return dt2; +} + +uint32_t helper_float_mul_s(CPUMIPSState *env, + uint32_t fst0, uint32_t fst1) +{ + uint32_t wt2; + + wt2 = float32_mul(fst0, fst1, &env->active_fpu.fp_status); + update_fcr31(env, GETPC()); + return wt2; +} + +uint64_t helper_float_mul_ps(CPUMIPSState *env, + uint64_t fdt0, uint64_t fdt1) +{ + uint32_t fstl0 = fdt0 & 0XFFFFFFFF; + uint32_t fsth0 = fdt0 >> 32; + uint32_t fstl1 = fdt1 & 0XFFFFFFFF; + uint32_t fsth1 = fdt1 >> 32; + uint32_t wtl2; + uint32_t wth2; + + wtl2 = float32_mul(fstl0, fstl1, &env->active_fpu.fp_status); + wth2 = float32_mul(fsth0, fsth1, &env->active_fpu.fp_status); + update_fcr31(env, GETPC()); + return ((uint64_t)wth2 << 32) | wtl2; +} + +uint64_t helper_float_div_d(CPUMIPSState *env, + uint64_t fdt0, uint64_t fdt1) +{ + uint64_t dt2; + + dt2 = float64_div(fdt0, fdt1, &env->active_fpu.fp_status); + update_fcr31(env, GETPC()); + return dt2; +} + +uint32_t helper_float_div_s(CPUMIPSState *env, + uint32_t fst0, uint32_t fst1) +{ + uint32_t wt2; + + wt2 = float32_div(fst0, fst1, &env->active_fpu.fp_status); + update_fcr31(env, GETPC()); + return wt2; +} + +uint64_t helper_float_div_ps(CPUMIPSState *env, + uint64_t fdt0, uint64_t fdt1) +{ + uint32_t fstl0 = fdt0 & 0XFFFFFFFF; + uint32_t fsth0 = fdt0 >> 32; + uint32_t fstl1 = fdt1 & 0XFFFFFFFF; + uint32_t fsth1 = fdt1 >> 32; + uint32_t wtl2; + uint32_t wth2; + + wtl2 = float32_div(fstl0, fstl1, &env->active_fpu.fp_status); + wth2 = float32_div(fsth0, fsth1, &env->active_fpu.fp_status); + update_fcr31(env, GETPC()); + return ((uint64_t)wth2 << 32) | wtl2; +} + /* MIPS specific binary operations */ uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) @@ -1235,19 +1391,19 @@ uint32_t helper_float_recip2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2) uint64_t helper_float_recip2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) { - uint32_t fst0 = fdt0 & 0XFFFFFFFF; + uint32_t fstl0 = fdt0 & 0XFFFFFFFF; uint32_t fsth0 = fdt0 >> 32; - uint32_t fst2 = fdt2 & 0XFFFFFFFF; + uint32_t fstl2 = fdt2 & 0XFFFFFFFF; uint32_t fsth2 = fdt2 >> 32; - fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); + fstl2 = float32_mul(fstl0, fstl2, &env->active_fpu.fp_status); fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status); - fst2 = float32_chs(float32_sub(fst2, float32_one, + fstl2 = float32_chs(float32_sub(fstl2, float32_one, &env->active_fpu.fp_status)); fsth2 = float32_chs(float32_sub(fsth2, float32_one, &env->active_fpu.fp_status)); update_fcr31(env, GETPC()); - return ((uint64_t)fsth2 << 32) | fst2; + return ((uint64_t)fsth2 << 32) | fstl2; } uint64_t helper_float_rsqrt2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) @@ -1272,152 +1428,350 @@ uint32_t helper_float_rsqrt2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2) uint64_t helper_float_rsqrt2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) { - uint32_t fst0 = fdt0 & 0XFFFFFFFF; + uint32_t fstl0 = fdt0 & 0XFFFFFFFF; uint32_t fsth0 = fdt0 >> 32; - uint32_t fst2 = fdt2 & 0XFFFFFFFF; + uint32_t fstl2 = fdt2 & 0XFFFFFFFF; uint32_t fsth2 = fdt2 >> 32; - fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); + fstl2 = float32_mul(fstl0, fstl2, &env->active_fpu.fp_status); fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status); - fst2 = float32_sub(fst2, float32_one, &env->active_fpu.fp_status); + fstl2 = float32_sub(fstl2, float32_one, &env->active_fpu.fp_status); fsth2 = float32_sub(fsth2, float32_one, &env->active_fpu.fp_status); - fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, + fstl2 = float32_chs(float32_div(fstl2, FLOAT_TWO32, &env->active_fpu.fp_status)); fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, &env->active_fpu.fp_status)); update_fcr31(env, GETPC()); - return ((uint64_t)fsth2 << 32) | fst2; + return ((uint64_t)fsth2 << 32) | fstl2; } uint64_t helper_float_addr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1) { - uint32_t fst0 = fdt0 & 0XFFFFFFFF; + uint32_t fstl0 = fdt0 & 0XFFFFFFFF; uint32_t fsth0 = fdt0 >> 32; - uint32_t fst1 = fdt1 & 0XFFFFFFFF; + uint32_t fstl1 = fdt1 & 0XFFFFFFFF; uint32_t fsth1 = fdt1 >> 32; - uint32_t fst2; + uint32_t fstl2; uint32_t fsth2; - fst2 = float32_add(fst0, fsth0, &env->active_fpu.fp_status); - fsth2 = float32_add(fst1, fsth1, &env->active_fpu.fp_status); + fstl2 = float32_add(fstl0, fsth0, &env->active_fpu.fp_status); + fsth2 = float32_add(fstl1, fsth1, &env->active_fpu.fp_status); update_fcr31(env, GETPC()); - return ((uint64_t)fsth2 << 32) | fst2; + return ((uint64_t)fsth2 << 32) | fstl2; } uint64_t helper_float_mulr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1) { - uint32_t fst0 = fdt0 & 0XFFFFFFFF; + uint32_t fstl0 = fdt0 & 0XFFFFFFFF; uint32_t fsth0 = fdt0 >> 32; - uint32_t fst1 = fdt1 & 0XFFFFFFFF; + uint32_t fstl1 = fdt1 & 0XFFFFFFFF; uint32_t fsth1 = fdt1 >> 32; - uint32_t fst2; + uint32_t fstl2; uint32_t fsth2; - fst2 = float32_mul(fst0, fsth0, &env->active_fpu.fp_status); - fsth2 = float32_mul(fst1, fsth1, &env->active_fpu.fp_status); + fstl2 = float32_mul(fstl0, fsth0, &env->active_fpu.fp_status); + fsth2 = float32_mul(fstl1, fsth1, &env->active_fpu.fp_status); update_fcr31(env, GETPC()); - return ((uint64_t)fsth2 << 32) | fst2; + return ((uint64_t)fsth2 << 32) | fstl2; } -#define FLOAT_MINMAX(name, bits, minmaxfunc) \ -uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \ - uint ## bits ## _t fs, \ - uint ## bits ## _t ft) \ -{ \ - uint ## bits ## _t fdret; \ - \ - fdret = float ## bits ## _ ## minmaxfunc(fs, ft, \ - &env->active_fpu.fp_status); \ - update_fcr31(env, GETPC()); \ - return fdret; \ + +uint32_t helper_float_max_s(CPUMIPSState *env, uint32_t fs, uint32_t ft) +{ + uint32_t fdret; + + fdret = float32_maxnum(fs, ft, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; } -FLOAT_MINMAX(max_s, 32, maxnum) -FLOAT_MINMAX(max_d, 64, maxnum) -FLOAT_MINMAX(maxa_s, 32, maxnummag) -FLOAT_MINMAX(maxa_d, 64, maxnummag) +uint64_t helper_float_max_d(CPUMIPSState *env, uint64_t fs, uint64_t ft) +{ + uint64_t fdret; + + fdret = float64_maxnum(fs, ft, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint32_t helper_float_maxa_s(CPUMIPSState *env, uint32_t fs, uint32_t ft) +{ + uint32_t fdret; + + fdret = float32_maxnummag(fs, ft, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint64_t helper_float_maxa_d(CPUMIPSState *env, uint64_t fs, uint64_t ft) +{ + uint64_t fdret; + + fdret = float64_maxnummag(fs, ft, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint32_t helper_float_min_s(CPUMIPSState *env, uint32_t fs, uint32_t ft) +{ + uint32_t fdret; + + fdret = float32_minnum(fs, ft, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint64_t helper_float_min_d(CPUMIPSState *env, uint64_t fs, uint64_t ft) +{ + uint64_t fdret; + + fdret = float64_minnum(fs, ft, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint32_t helper_float_mina_s(CPUMIPSState *env, uint32_t fs, uint32_t ft) +{ + uint32_t fdret; + + fdret = float32_minnummag(fs, ft, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint64_t helper_float_mina_d(CPUMIPSState *env, uint64_t fs, uint64_t ft) +{ + uint64_t fdret; + + fdret = float64_minnummag(fs, ft, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} -FLOAT_MINMAX(min_s, 32, minnum) -FLOAT_MINMAX(min_d, 64, minnum) -FLOAT_MINMAX(mina_s, 32, minnummag) -FLOAT_MINMAX(mina_d, 64, minnummag) -#undef FLOAT_MINMAX /* ternary operations */ -#define UNFUSED_FMA(prefix, a, b, c, flags) \ -{ \ - a = prefix##_mul(a, b, &env->active_fpu.fp_status); \ - if ((flags) & float_muladd_negate_c) { \ - a = prefix##_sub(a, c, &env->active_fpu.fp_status); \ - } else { \ - a = prefix##_add(a, c, &env->active_fpu.fp_status); \ - } \ - if ((flags) & float_muladd_negate_result) { \ - a = prefix##_chs(a); \ - } \ -} - -/* FMA based operations */ -#define FLOAT_FMA(name, type) \ -uint64_t helper_float_ ## name ## _d(CPUMIPSState *env, \ - uint64_t fdt0, uint64_t fdt1, \ - uint64_t fdt2) \ -{ \ - UNFUSED_FMA(float64, fdt0, fdt1, fdt2, type); \ - update_fcr31(env, GETPC()); \ - return fdt0; \ -} \ - \ -uint32_t helper_float_ ## name ## _s(CPUMIPSState *env, \ - uint32_t fst0, uint32_t fst1, \ - uint32_t fst2) \ -{ \ - UNFUSED_FMA(float32, fst0, fst1, fst2, type); \ - update_fcr31(env, GETPC()); \ - return fst0; \ -} \ - \ -uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env, \ - uint64_t fdt0, uint64_t fdt1, \ - uint64_t fdt2) \ -{ \ - uint32_t fst0 = fdt0 & 0XFFFFFFFF; \ - uint32_t fsth0 = fdt0 >> 32; \ - uint32_t fst1 = fdt1 & 0XFFFFFFFF; \ - uint32_t fsth1 = fdt1 >> 32; \ - uint32_t fst2 = fdt2 & 0XFFFFFFFF; \ - uint32_t fsth2 = fdt2 >> 32; \ - \ - UNFUSED_FMA(float32, fst0, fst1, fst2, type); \ - UNFUSED_FMA(float32, fsth0, fsth1, fsth2, type); \ - update_fcr31(env, GETPC()); \ - return ((uint64_t)fsth0 << 32) | fst0; \ -} -FLOAT_FMA(madd, 0) -FLOAT_FMA(msub, float_muladd_negate_c) -FLOAT_FMA(nmadd, float_muladd_negate_result) -FLOAT_FMA(nmsub, float_muladd_negate_result | float_muladd_negate_c) -#undef FLOAT_FMA - -#define FLOAT_FMADDSUB(name, bits, muladd_arg) \ -uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \ - uint ## bits ## _t fs, \ - uint ## bits ## _t ft, \ - uint ## bits ## _t fd) \ -{ \ - uint ## bits ## _t fdret; \ - \ - fdret = float ## bits ## _muladd(fs, ft, fd, muladd_arg, \ - &env->active_fpu.fp_status); \ - update_fcr31(env, GETPC()); \ - return fdret; \ -} - -FLOAT_FMADDSUB(maddf_s, 32, 0) -FLOAT_FMADDSUB(maddf_d, 64, 0) -FLOAT_FMADDSUB(msubf_s, 32, float_muladd_negate_product) -FLOAT_FMADDSUB(msubf_d, 64, float_muladd_negate_product) -#undef FLOAT_FMADDSUB + +uint64_t helper_float_madd_d(CPUMIPSState *env, uint64_t fst0, + uint64_t fst1, uint64_t fst2) +{ + fst0 = float64_mul(fst0, fst1, &env->active_fpu.fp_status); + fst0 = float64_add(fst0, fst2, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fst0; +} + +uint32_t helper_float_madd_s(CPUMIPSState *env, uint32_t fst0, + uint32_t fst1, uint32_t fst2) +{ + fst0 = float32_mul(fst0, fst1, &env->active_fpu.fp_status); + fst0 = float32_add(fst0, fst2, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fst0; +} + +uint64_t helper_float_madd_ps(CPUMIPSState *env, uint64_t fdt0, + uint64_t fdt1, uint64_t fdt2) +{ + uint32_t fstl0 = fdt0 & 0XFFFFFFFF; + uint32_t fsth0 = fdt0 >> 32; + uint32_t fstl1 = fdt1 & 0XFFFFFFFF; + uint32_t fsth1 = fdt1 >> 32; + uint32_t fstl2 = fdt2 & 0XFFFFFFFF; + uint32_t fsth2 = fdt2 >> 32; + + fstl0 = float32_mul(fstl0, fstl1, &env->active_fpu.fp_status); + fstl0 = float32_add(fstl0, fstl2, &env->active_fpu.fp_status); + fsth0 = float32_mul(fsth0, fsth1, &env->active_fpu.fp_status); + fsth0 = float32_add(fsth0, fsth2, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return ((uint64_t)fsth0 << 32) | fstl0; +} + +uint64_t helper_float_msub_d(CPUMIPSState *env, uint64_t fst0, + uint64_t fst1, uint64_t fst2) +{ + fst0 = float64_mul(fst0, fst1, &env->active_fpu.fp_status); + fst0 = float64_sub(fst0, fst2, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fst0; +} + +uint32_t helper_float_msub_s(CPUMIPSState *env, uint32_t fst0, + uint32_t fst1, uint32_t fst2) +{ + fst0 = float32_mul(fst0, fst1, &env->active_fpu.fp_status); + fst0 = float32_sub(fst0, fst2, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fst0; +} + +uint64_t helper_float_msub_ps(CPUMIPSState *env, uint64_t fdt0, + uint64_t fdt1, uint64_t fdt2) +{ + uint32_t fstl0 = fdt0 & 0XFFFFFFFF; + uint32_t fsth0 = fdt0 >> 32; + uint32_t fstl1 = fdt1 & 0XFFFFFFFF; + uint32_t fsth1 = fdt1 >> 32; + uint32_t fstl2 = fdt2 & 0XFFFFFFFF; + uint32_t fsth2 = fdt2 >> 32; + + fstl0 = float32_mul(fstl0, fstl1, &env->active_fpu.fp_status); + fstl0 = float32_sub(fstl0, fstl2, &env->active_fpu.fp_status); + fsth0 = float32_mul(fsth0, fsth1, &env->active_fpu.fp_status); + fsth0 = float32_sub(fsth0, fsth2, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return ((uint64_t)fsth0 << 32) | fstl0; +} + +uint64_t helper_float_nmadd_d(CPUMIPSState *env, uint64_t fst0, + uint64_t fst1, uint64_t fst2) +{ + fst0 = float64_mul(fst0, fst1, &env->active_fpu.fp_status); + fst0 = float64_add(fst0, fst2, &env->active_fpu.fp_status); + fst0 = float64_chs(fst0); + + update_fcr31(env, GETPC()); + return fst0; +} + +uint32_t helper_float_nmadd_s(CPUMIPSState *env, uint32_t fst0, + uint32_t fst1, uint32_t fst2) +{ + fst0 = float32_mul(fst0, fst1, &env->active_fpu.fp_status); + fst0 = float32_add(fst0, fst2, &env->active_fpu.fp_status); + fst0 = float32_chs(fst0); + + update_fcr31(env, GETPC()); + return fst0; +} + +uint64_t helper_float_nmadd_ps(CPUMIPSState *env, uint64_t fdt0, + uint64_t fdt1, uint64_t fdt2) +{ + uint32_t fstl0 = fdt0 & 0XFFFFFFFF; + uint32_t fsth0 = fdt0 >> 32; + uint32_t fstl1 = fdt1 & 0XFFFFFFFF; + uint32_t fsth1 = fdt1 >> 32; + uint32_t fstl2 = fdt2 & 0XFFFFFFFF; + uint32_t fsth2 = fdt2 >> 32; + + fstl0 = float32_mul(fstl0, fstl1, &env->active_fpu.fp_status); + fstl0 = float32_add(fstl0, fstl2, &env->active_fpu.fp_status); + fstl0 = float32_chs(fstl0); + fsth0 = float32_mul(fsth0, fsth1, &env->active_fpu.fp_status); + fsth0 = float32_add(fsth0, fsth2, &env->active_fpu.fp_status); + fsth0 = float32_chs(fsth0); + + update_fcr31(env, GETPC()); + return ((uint64_t)fsth0 << 32) | fstl0; +} + +uint64_t helper_float_nmsub_d(CPUMIPSState *env, uint64_t fst0, + uint64_t fst1, uint64_t fst2) +{ + fst0 = float64_mul(fst0, fst1, &env->active_fpu.fp_status); + fst0 = float64_sub(fst0, fst2, &env->active_fpu.fp_status); + fst0 = float64_chs(fst0); + + update_fcr31(env, GETPC()); + return fst0; +} + +uint32_t helper_float_nmsub_s(CPUMIPSState *env, uint32_t fst0, + uint32_t fst1, uint32_t fst2) +{ + fst0 = float32_mul(fst0, fst1, &env->active_fpu.fp_status); + fst0 = float32_sub(fst0, fst2, &env->active_fpu.fp_status); + fst0 = float32_chs(fst0); + + update_fcr31(env, GETPC()); + return fst0; +} + +uint64_t helper_float_nmsub_ps(CPUMIPSState *env, uint64_t fdt0, + uint64_t fdt1, uint64_t fdt2) +{ + uint32_t fstl0 = fdt0 & 0XFFFFFFFF; + uint32_t fsth0 = fdt0 >> 32; + uint32_t fstl1 = fdt1 & 0XFFFFFFFF; + uint32_t fsth1 = fdt1 >> 32; + uint32_t fstl2 = fdt2 & 0XFFFFFFFF; + uint32_t fsth2 = fdt2 >> 32; + + fstl0 = float32_mul(fstl0, fstl1, &env->active_fpu.fp_status); + fstl0 = float32_sub(fstl0, fstl2, &env->active_fpu.fp_status); + fstl0 = float32_chs(fstl0); + fsth0 = float32_mul(fsth0, fsth1, &env->active_fpu.fp_status); + fsth0 = float32_sub(fsth0, fsth2, &env->active_fpu.fp_status); + fsth0 = float32_chs(fsth0); + + update_fcr31(env, GETPC()); + return ((uint64_t)fsth0 << 32) | fstl0; +} + + +uint32_t helper_float_maddf_s(CPUMIPSState *env, uint32_t fs, + uint32_t ft, uint32_t fd) +{ + uint32_t fdret; + + fdret = float32_muladd(fs, ft, fd, 0, + &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint64_t helper_float_maddf_d(CPUMIPSState *env, uint64_t fs, + uint64_t ft, uint64_t fd) +{ + uint64_t fdret; + + fdret = float64_muladd(fs, ft, fd, 0, + &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint32_t helper_float_msubf_s(CPUMIPSState *env, uint32_t fs, + uint32_t ft, uint32_t fd) +{ + uint32_t fdret; + + fdret = float32_muladd(fs, ft, fd, float_muladd_negate_product, + &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint64_t helper_float_msubf_d(CPUMIPSState *env, uint64_t fs, + uint64_t ft, uint64_t fd) +{ + uint64_t fdret; + + fdret = float64_muladd(fs, ft, fd, float_muladd_negate_product, + &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + /* compare operations */ #define FOP_COND_D(op, cond) \ diff --git a/target/mips/gdbstub.c b/target/mips/gdbstub.c index 98f56e660d27270ed695d66ee78e6043dc159286..e39f8d75cf08f25308ac6b3a0cae0d04562e5044 100644 --- a/target/mips/gdbstub.c +++ b/target/mips/gdbstub.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/mips/helper.c b/target/mips/helper.c index afd78b1990be4083f7bbe31c9325d31c82087b63..063b65c0528d70eae5795784d8e703221d92d272 100644 --- a/target/mips/helper.c +++ b/target/mips/helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/mips/helper.h b/target/mips/helper.h index 84fdd9fd271876ec6f6398d79c4f5af27977021f..e97655dc0eb752fa9a8af36d3c617b2670ef131e 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -950,6 +950,21 @@ DEF_HELPER_4(msa_mod_s_h, void, env, i32, i32, i32) DEF_HELPER_4(msa_mod_s_w, void, env, i32, i32, i32) DEF_HELPER_4(msa_mod_s_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_maddv_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_maddv_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_maddv_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_maddv_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_msubv_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_msubv_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_msubv_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_msubv_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_mulv_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mulv_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mulv_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_mulv_d, void, env, i32, i32, i32) + DEF_HELPER_4(msa_asub_s_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_asub_s_h, void, env, i32, i32, i32) DEF_HELPER_4(msa_asub_s_w, void, env, i32, i32, i32) @@ -968,6 +983,31 @@ DEF_HELPER_4(msa_hsub_u_h, void, env, i32, i32, i32) DEF_HELPER_4(msa_hsub_u_w, void, env, i32, i32, i32) DEF_HELPER_4(msa_hsub_u_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subs_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subs_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subs_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subs_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_subs_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subs_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subs_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subs_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_subsus_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subsus_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subsus_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subsus_u_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_subsuu_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subsuu_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subsuu_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subsuu_s_d, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_subv_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subv_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subv_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_subv_d, void, env, i32, i32, i32) + DEF_HELPER_4(msa_ilvev_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_ilvev_h, void, env, i32, i32, i32) DEF_HELPER_4(msa_ilvev_w, void, env, i32, i32, i32) @@ -1063,20 +1103,25 @@ DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_subv_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_subs_s_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_subs_u_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_subsus_u_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_subsuu_s_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_maddv_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_msubv_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_dotp_s_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_dotp_u_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_dpadd_s_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_dpadd_u_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_dpsub_s_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_dpsub_u_df, void, env, i32, i32, i32, i32) + +DEF_HELPER_4(msa_dotp_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dotp_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dotp_s_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dotp_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dotp_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dotp_u_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpadd_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpadd_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpadd_s_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpadd_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpadd_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpadd_u_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpsub_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpsub_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpsub_s_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpsub_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpsub_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_dpsub_u_d, void, env, i32, i32, i32) DEF_HELPER_5(msa_sld_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_splat_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_vshf_df, void, env, i32, i32, i32, i32) diff --git a/target/mips/internal.h b/target/mips/internal.h index 1bf274b3ef5b01a56a757c60cc32a7b6a5d22354..dd8a7809b645a177ac3145489f231d16400dc617 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -36,7 +36,9 @@ struct mips_def_t { int32_t CP0_Config5; int32_t CP0_Config5_rw_bitmask; int32_t CP0_Config6; + int32_t CP0_Config6_rw_bitmask; int32_t CP0_Config7; + int32_t CP0_Config7_rw_bitmask; target_ulong CP0_LLAddr_rw_bitmask; int CP0_LLAddr_shift; int32_t SYNCI_Step; @@ -142,6 +144,7 @@ void r4k_helper_tlbr(CPUMIPSState *env); void r4k_helper_tlbinv(CPUMIPSState *env); void r4k_helper_tlbinvf(CPUMIPSState *env); void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra); +uint32_t cpu_mips_get_random(CPUMIPSState *env); void mips_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr, unsigned size, @@ -186,7 +189,7 @@ static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env) /* * A MIPS configured with a vectorizing external interrupt controller * will feed a vector into the Cause pending lines. The core treats - * the status lines as a vector level, not as indiviual masks. + * the status lines as a vector level, not as individual masks. */ r = pending > status; } else { @@ -207,7 +210,6 @@ void cpu_state_reset(CPUMIPSState *s); void cpu_mips_realize_env(CPUMIPSState *env); /* cp0_timer.c */ -uint32_t cpu_mips_get_random(CPUMIPSState *env); uint32_t cpu_mips_get_count(CPUMIPSState *env); void cpu_mips_store_count(CPUMIPSState *env, uint32_t value); void cpu_mips_store_compare(CPUMIPSState *env, uint32_t value); @@ -224,7 +226,6 @@ uint32_t float_class_s(uint32_t arg, float_status *fst); uint64_t float_class_d(uint64_t arg, float_status *fst); extern unsigned int ieee_rm[]; -int ieee_ex_to_mips(int xcpt); void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask); static inline void restore_rounding_mode(CPUMIPSState *env) diff --git a/target/mips/kvm.c b/target/mips/kvm.c index de3e26ef1f9c6c9d285824fb468c074e2495a72e..72637a1e0216b30496e9c6eaaf954a6bca3f12e3 100644 --- a/target/mips/kvm.c +++ b/target/mips/kvm.c @@ -21,10 +21,12 @@ #include "qemu/main-loop.h" #include "qemu/timer.h" #include "sysemu/kvm.h" +#include "sysemu/kvm_int.h" #include "sysemu/runstate.h" #include "sysemu/cpus.h" #include "kvm_mips.h" #include "exec/memattrs.h" +#include "hw/boards.h" #define DEBUG_KVM 0 @@ -245,10 +247,16 @@ int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level) (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U64 | (8 * (_R) + (_S))) #define KVM_REG_MIPS_CP0_INDEX MIPS_CP0_32(0, 0) +#define KVM_REG_MIPS_CP0_RANDOM MIPS_CP0_32(1, 0) #define KVM_REG_MIPS_CP0_CONTEXT MIPS_CP0_64(4, 0) #define KVM_REG_MIPS_CP0_USERLOCAL MIPS_CP0_64(4, 2) #define KVM_REG_MIPS_CP0_PAGEMASK MIPS_CP0_32(5, 0) +#define KVM_REG_MIPS_CP0_PAGEGRAIN MIPS_CP0_32(5, 1) +#define KVM_REG_MIPS_CP0_PWBASE MIPS_CP0_64(5, 5) +#define KVM_REG_MIPS_CP0_PWFIELD MIPS_CP0_64(5, 6) +#define KVM_REG_MIPS_CP0_PWSIZE MIPS_CP0_64(5, 7) #define KVM_REG_MIPS_CP0_WIRED MIPS_CP0_32(6, 0) +#define KVM_REG_MIPS_CP0_PWCTL MIPS_CP0_32(6, 6) #define KVM_REG_MIPS_CP0_HWRENA MIPS_CP0_32(7, 0) #define KVM_REG_MIPS_CP0_BADVADDR MIPS_CP0_64(8, 0) #define KVM_REG_MIPS_CP0_COUNT MIPS_CP0_32(9, 0) @@ -258,13 +266,22 @@ int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level) #define KVM_REG_MIPS_CP0_CAUSE MIPS_CP0_32(13, 0) #define KVM_REG_MIPS_CP0_EPC MIPS_CP0_64(14, 0) #define KVM_REG_MIPS_CP0_PRID MIPS_CP0_32(15, 0) +#define KVM_REG_MIPS_CP0_EBASE MIPS_CP0_64(15, 1) #define KVM_REG_MIPS_CP0_CONFIG MIPS_CP0_32(16, 0) #define KVM_REG_MIPS_CP0_CONFIG1 MIPS_CP0_32(16, 1) #define KVM_REG_MIPS_CP0_CONFIG2 MIPS_CP0_32(16, 2) #define KVM_REG_MIPS_CP0_CONFIG3 MIPS_CP0_32(16, 3) #define KVM_REG_MIPS_CP0_CONFIG4 MIPS_CP0_32(16, 4) #define KVM_REG_MIPS_CP0_CONFIG5 MIPS_CP0_32(16, 5) +#define KVM_REG_MIPS_CP0_CONFIG6 MIPS_CP0_32(16, 6) +#define KVM_REG_MIPS_CP0_XCONTEXT MIPS_CP0_64(20, 0) #define KVM_REG_MIPS_CP0_ERROREPC MIPS_CP0_64(30, 0) +#define KVM_REG_MIPS_CP0_KSCRATCH1 MIPS_CP0_64(31, 2) +#define KVM_REG_MIPS_CP0_KSCRATCH2 MIPS_CP0_64(31, 3) +#define KVM_REG_MIPS_CP0_KSCRATCH3 MIPS_CP0_64(31, 4) +#define KVM_REG_MIPS_CP0_KSCRATCH4 MIPS_CP0_64(31, 5) +#define KVM_REG_MIPS_CP0_KSCRATCH5 MIPS_CP0_64(31, 6) +#define KVM_REG_MIPS_CP0_KSCRATCH6 MIPS_CP0_64(31, 7) static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id, int32_t *addr) @@ -394,6 +411,29 @@ static inline int kvm_mips_get_one_ureg64(CPUState *cs, uint64_t reg_id, (1U << CP0C5_UFE) | \ (1U << CP0C5_FRE) | \ (1U << CP0C5_UFR)) +#define KVM_REG_MIPS_CP0_CONFIG6_MASK ((1U << CP0C6_BPPASS) | \ + (0x3fU << CP0C6_KPOS) | \ + (1U << CP0C6_KE) | \ + (1U << CP0C6_VTLBONLY) | \ + (1U << CP0C6_LASX) | \ + (1U << CP0C6_SSEN) | \ + (1U << CP0C6_DISDRTIME) | \ + (1U << CP0C6_PIXNUEN) | \ + (1U << CP0C6_SCRAND) | \ + (1U << CP0C6_LLEXCEN) | \ + (1U << CP0C6_DISVC) | \ + (1U << CP0C6_VCLRU) | \ + (1U << CP0C6_DCLRU) | \ + (1U << CP0C6_PIXUEN) | \ + (1U << CP0C6_DISBLKLYEN) | \ + (1U << CP0C6_UMEMUALEN) | \ + (1U << CP0C6_SFBEN) | \ + (1U << CP0C6_FLTINT) | \ + (1U << CP0C6_VLTINT) | \ + (1U << CP0C6_DISBTB) | \ + (3U << CP0C6_STPREFCTL) | \ + (1U << CP0C6_INSTPREF) | \ + (1U << CP0C6_DATAPREF)) static inline int kvm_mips_change_one_reg(CPUState *cs, uint64_t reg_id, int32_t *addr, int32_t mask) @@ -729,6 +769,11 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level) DPRINTF("%s: Failed to put CP0_INDEX (%d)\n", __func__, err); ret = err; } + err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random); + if (err < 0) { + DPRINTF("%s: Failed to put CP0_RANDOM (%d)\n", __func__, err); + ret = err; + } err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT, &env->CP0_Context); if (err < 0) { @@ -747,11 +792,40 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level) DPRINTF("%s: Failed to put CP0_PAGEMASK (%d)\n", __func__, err); ret = err; } + err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN, + &env->CP0_PageGrain); + if (err < 0) { + DPRINTF("%s: Failed to put CP0_PAGEGRAIN (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE, + &env->CP0_PWBase); + if (err < 0) { + DPRINTF("%s: Failed to put CP0_PWBASE (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD, + &env->CP0_PWField); + if (err < 0) { + DPRINTF("%s: Failed to put CP0_PWField (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE, + &env->CP0_PWSize); + if (err < 0) { + DPRINTF("%s: Failed to put CP0_PWSIZE (%d)\n", __func__, err); + ret = err; + } err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired); if (err < 0) { DPRINTF("%s: Failed to put CP0_WIRED (%d)\n", __func__, err); ret = err; } + err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl); + if (err < 0) { + DPRINTF("%s: Failed to put CP0_PWCTL (%d)\n", __func__, err); + ret = err; + } err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna); if (err < 0) { DPRINTF("%s: Failed to put CP0_HWRENA (%d)\n", __func__, err); @@ -799,6 +873,11 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level) DPRINTF("%s: Failed to put CP0_PRID (%d)\n", __func__, err); ret = err; } + err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase); + if (err < 0) { + DPRINTF("%s: Failed to put CP0_EBASE (%d)\n", __func__, err); + ret = err; + } err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, &env->CP0_Config0, KVM_REG_MIPS_CP0_CONFIG_MASK); @@ -841,12 +920,61 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level) DPRINTF("%s: Failed to change CP0_CONFIG5 (%d)\n", __func__, err); ret = err; } + err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6, + &env->CP0_Config6, + KVM_REG_MIPS_CP0_CONFIG6_MASK); + if (err < 0) { + DPRINTF("%s: Failed to change CP0_CONFIG6 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT, + &env->CP0_XContext); + if (err < 0) { + DPRINTF("%s: Failed to put CP0_XCONTEXT (%d)\n", __func__, err); + ret = err; + } err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC, &env->CP0_ErrorEPC); if (err < 0) { DPRINTF("%s: Failed to put CP0_ERROREPC (%d)\n", __func__, err); ret = err; } + err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1, + &env->CP0_KScratch[0]); + if (err < 0) { + DPRINTF("%s: Failed to put CP0_KSCRATCH1 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2, + &env->CP0_KScratch[1]); + if (err < 0) { + DPRINTF("%s: Failed to put CP0_KSCRATCH2 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3, + &env->CP0_KScratch[2]); + if (err < 0) { + DPRINTF("%s: Failed to put CP0_KSCRATCH3 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4, + &env->CP0_KScratch[3]); + if (err < 0) { + DPRINTF("%s: Failed to put CP0_KSCRATCH4 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5, + &env->CP0_KScratch[4]); + if (err < 0) { + DPRINTF("%s: Failed to put CP0_KSCRATCH5 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6, + &env->CP0_KScratch[5]); + if (err < 0) { + DPRINTF("%s: Failed to put CP0_KSCRATCH6 (%d)\n", __func__, err); + ret = err; + } return ret; } @@ -862,6 +990,11 @@ static int kvm_mips_get_cp0_registers(CPUState *cs) DPRINTF("%s: Failed to get CP0_INDEX (%d)\n", __func__, err); ret = err; } + err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_RANDOM (%d)\n", __func__, err); + ret = err; + } err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT, &env->CP0_Context); if (err < 0) { @@ -880,11 +1013,40 @@ static int kvm_mips_get_cp0_registers(CPUState *cs) DPRINTF("%s: Failed to get CP0_PAGEMASK (%d)\n", __func__, err); ret = err; } + err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN, + &env->CP0_PageGrain); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_PAGEGRAIN (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE, + &env->CP0_PWBase); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_PWBASE (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD, + &env->CP0_PWField); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_PWFIELD (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE, + &env->CP0_PWSize); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_PWSIZE (%d)\n", __func__, err); + ret = err; + } err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired); if (err < 0) { DPRINTF("%s: Failed to get CP0_WIRED (%d)\n", __func__, err); ret = err; } + err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_PWCtl (%d)\n", __func__, err); + ret = err; + } err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna); if (err < 0) { DPRINTF("%s: Failed to get CP0_HWRENA (%d)\n", __func__, err); @@ -932,6 +1094,11 @@ static int kvm_mips_get_cp0_registers(CPUState *cs) DPRINTF("%s: Failed to get CP0_PRID (%d)\n", __func__, err); ret = err; } + err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_EBASE (%d)\n", __func__, err); + ret = err; + } err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, &env->CP0_Config0); if (err < 0) { DPRINTF("%s: Failed to get CP0_CONFIG (%d)\n", __func__, err); @@ -962,12 +1129,59 @@ static int kvm_mips_get_cp0_registers(CPUState *cs) DPRINTF("%s: Failed to get CP0_CONFIG5 (%d)\n", __func__, err); ret = err; } + err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6, &env->CP0_Config6); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_CONFIG6 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT, + &env->CP0_XContext); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_XCONTEXT (%d)\n", __func__, err); + ret = err; + } err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC, &env->CP0_ErrorEPC); if (err < 0) { DPRINTF("%s: Failed to get CP0_ERROREPC (%d)\n", __func__, err); ret = err; } + err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1, + &env->CP0_KScratch[0]); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_KSCRATCH1 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2, + &env->CP0_KScratch[1]); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_KSCRATCH2 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3, + &env->CP0_KScratch[2]); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_KSCRATCH3 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4, + &env->CP0_KScratch[3]); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_KSCRATCH4 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5, + &env->CP0_KScratch[4]); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_KSCRATCH5 (%d)\n", __func__, err); + ret = err; + } + err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6, + &env->CP0_KScratch[5]); + if (err < 0) { + DPRINTF("%s: Failed to get CP0_KSCRATCH6 (%d)\n", __func__, err); + ret = err; + } return ret; } @@ -1058,3 +1272,27 @@ int kvm_arch_msi_data_to_gsi(uint32_t data) { abort(); } + +int mips_kvm_type(MachineState *machine, const char *vm_type) +{ +#if defined(KVM_CAP_MIPS_VZ) || defined(KVM_CAP_MIPS_TE) + int r; + KVMState *s = KVM_STATE(machine->accelerator); +#endif + +#if defined(KVM_CAP_MIPS_VZ) + r = kvm_check_extension(s, KVM_CAP_MIPS_VZ); + if (r > 0) { + return KVM_VM_MIPS_VZ; + } +#endif + +#if defined(KVM_CAP_MIPS_TE) + r = kvm_check_extension(s, KVM_CAP_MIPS_TE); + if (r > 0) { + return KVM_VM_MIPS_TE; + } +#endif + + return -1; +} diff --git a/target/mips/kvm_mips.h b/target/mips/kvm_mips.h index 1e4014792ddc3482f3c516433f5d4a56c038bfb6..171d53dbe1396a4e3b514b96246efcfb97babe38 100644 --- a/target/mips/kvm_mips.h +++ b/target/mips/kvm_mips.h @@ -12,6 +12,8 @@ #ifndef KVM_MIPS_H #define KVM_MIPS_H +#include "cpu.h" + /** * kvm_mips_reset_vcpu: * @cpu: MIPSCPU @@ -23,4 +25,13 @@ void kvm_mips_reset_vcpu(MIPSCPU *cpu); int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level); int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level); +#ifdef CONFIG_KVM +int mips_kvm_type(MachineState *machine, const char *vm_type); +#else +static inline int mips_kvm_type(MachineState *machine, const char *vm_type) +{ + return 0; +} +#endif + #endif /* KVM_MIPS_H */ diff --git a/target/mips/lmi_helper.c b/target/mips/lmmi_helper.c similarity index 99% rename from target/mips/lmi_helper.c rename to target/mips/lmmi_helper.c index 6c645cf679add5b73c7711098bd207a66fa5393d..abeb7736aeb21b418d5527fb4830989674f6e655 100644 --- a/target/mips/lmi_helper.c +++ b/target/mips/lmmi_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/mips/machine.c b/target/mips/machine.c index 8d5b18bea2236733b4359cd436e06d0295cf4251..5b23e3e912a7624f531978c9708b740c75c95f80 100644 --- a/target/mips/machine.c +++ b/target/mips/machine.c @@ -212,8 +212,8 @@ const VMStateDescription vmstate_tlb = { const VMStateDescription vmstate_mips_cpu = { .name = "cpu", - .version_id = 19, - .minimum_version_id = 19, + .version_id = 20, + .minimum_version_id = 20, .post_load = cpu_post_load, .fields = (VMStateField[]) { /* Active TC */ @@ -289,6 +289,8 @@ const VMStateDescription vmstate_mips_cpu = { VMSTATE_INT32(env.CP0_Config1, MIPSCPU), VMSTATE_INT32(env.CP0_Config2, MIPSCPU), VMSTATE_INT32(env.CP0_Config3, MIPSCPU), + VMSTATE_INT32(env.CP0_Config4, MIPSCPU), + VMSTATE_INT32(env.CP0_Config5, MIPSCPU), VMSTATE_INT32(env.CP0_Config6, MIPSCPU), VMSTATE_INT32(env.CP0_Config7, MIPSCPU), VMSTATE_UINT64(env.CP0_LLAddr, MIPSCPU), diff --git a/target/mips/meson.build b/target/mips/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..fa1f024e782fe5bd39df687836e456912ec4bc8d --- /dev/null +++ b/target/mips/meson.build @@ -0,0 +1,24 @@ +mips_ss = ss.source_set() +mips_ss.add(files( + 'cp0_helper.c', + 'cpu.c', + 'dsp_helper.c', + 'fpu_helper.c', + 'gdbstub.c', + 'helper.c', + 'lmmi_helper.c', + 'msa_helper.c', + 'op_helper.c', + 'translate.c', +)) +mips_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c')) + +mips_softmmu_ss = ss.source_set() +mips_softmmu_ss.add(files( + 'cp0_timer.c', + 'machine.c', + 'mips-semi.c', +)) + +target_arch += {'mips': mips_ss} +target_softmmu_arch += {'mips': mips_softmmu_ss} diff --git a/target/mips/mips-defs.h b/target/mips/mips-defs.h index a831bb43844eaa16712664a477065d5b63787010..ed6a7a9e545ce367cb4fece21e38c06c16719c6c 100644 --- a/target/mips/mips-defs.h +++ b/target/mips/mips-defs.h @@ -15,7 +15,7 @@ * ------------------------------------------------ */ /* - * bits 0-31: MIPS base instruction sets + * bits 0-23: MIPS base instruction sets */ #define ISA_MIPS1 0x0000000000000001ULL #define ISA_MIPS2 0x0000000000000002ULL @@ -34,30 +34,37 @@ #define ISA_MIPS64R6 0x0000000000004000ULL #define ISA_NANOMIPS32 0x0000000000008000ULL /* - * bits 32-47: MIPS ASEs + * bits 24-39: MIPS ASEs */ -#define ASE_MIPS16 0x0000000100000000ULL -#define ASE_MIPS3D 0x0000000200000000ULL -#define ASE_MDMX 0x0000000400000000ULL -#define ASE_DSP 0x0000000800000000ULL -#define ASE_DSP_R2 0x0000001000000000ULL -#define ASE_DSP_R3 0x0000002000000000ULL -#define ASE_MT 0x0000004000000000ULL -#define ASE_SMARTMIPS 0x0000008000000000ULL -#define ASE_MICROMIPS 0x0000010000000000ULL -#define ASE_MSA 0x0000020000000000ULL +#define ASE_MIPS16 0x0000000001000000ULL +#define ASE_MIPS3D 0x0000000002000000ULL +#define ASE_MDMX 0x0000000004000000ULL +#define ASE_DSP 0x0000000008000000ULL +#define ASE_DSP_R2 0x0000000010000000ULL +#define ASE_DSP_R3 0x0000000020000000ULL +#define ASE_MT 0x0000000040000000ULL +#define ASE_SMARTMIPS 0x0000000080000000ULL +#define ASE_MICROMIPS 0x0000000100000000ULL +#define ASE_MSA 0x0000000200000000ULL /* - * bits 48-55: vendor-specific base instruction sets + * bits 40-51: vendor-specific base instruction sets */ -#define INSN_LOONGSON2E 0x0001000000000000ULL -#define INSN_LOONGSON2F 0x0002000000000000ULL -#define INSN_VR54XX 0x0004000000000000ULL -#define INSN_R5900 0x0008000000000000ULL +#define INSN_VR54XX 0x0000010000000000ULL +#define INSN_R5900 0x0000020000000000ULL +#define INSN_LOONGSON2E 0x0000040000000000ULL +#define INSN_LOONGSON2F 0x0000080000000000ULL +#define INSN_LOONGSON3A 0x0000100000000000ULL /* - * bits 56-63: vendor-specific ASEs + * bits 52-63: vendor-specific ASEs */ -#define ASE_MMI 0x0100000000000000ULL -#define ASE_MXU 0x0200000000000000ULL +/* MultiMedia Instructions defined by R5900 */ +#define ASE_MMI 0x0010000000000000ULL +/* MIPS eXtension/enhanced Unit defined by Ingenic */ +#define ASE_MXU 0x0020000000000000ULL +/* Loongson MultiMedia Instructions */ +#define ASE_LMMI 0x0040000000000000ULL +/* Loongson EXTensions */ +#define ASE_LEXT 0x0080000000000000ULL /* MIPS CPU defines. */ #define CPU_MIPS1 (ISA_MIPS1) @@ -67,7 +74,7 @@ #define CPU_VR54XX (CPU_MIPS4 | INSN_VR54XX) #define CPU_R5900 (CPU_MIPS3 | INSN_R5900) #define CPU_LOONGSON2E (CPU_MIPS3 | INSN_LOONGSON2E) -#define CPU_LOONGSON2F (CPU_MIPS3 | INSN_LOONGSON2F) +#define CPU_LOONGSON2F (CPU_MIPS3 | INSN_LOONGSON2F | ASE_LMMI) #define CPU_MIPS5 (CPU_MIPS4 | ISA_MIPS5) @@ -94,6 +101,8 @@ /* Wave Computing: "nanoMIPS" */ #define CPU_NANOMIPS32 (CPU_MIPS32R6 | ISA_NANOMIPS32) +#define CPU_LOONGSON3A (CPU_MIPS64R2 | INSN_LOONGSON3A | ASE_LMMI | ASE_LEXT) + /* * Strictly follow the architecture standard: * - Disallow "special" instruction handling for PMON/SPIM. diff --git a/target/mips/mips-semi.c b/target/mips/mips-semi.c index 10a710c1e80331cb7b31da684ede0b5d68713d53..898251aa0233f3c7dd3438d0aade1d33b9e11fbf 100644 --- a/target/mips/mips-semi.c +++ b/target/mips/mips-semi.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c index 3c7012c0b87ff26ffab6d91803c3a646dd2f68c8..249f0fdad802452c2a39394450f8464443007fc3 100644 --- a/target/mips/msa_helper.c +++ b/target/mips/msa_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -2224,7 +2224,339 @@ void helper_msa_div_u_d(CPUMIPSState *env, * +---------------+----------------------------------------------------------+ */ -/* TODO: insert Int Dot Product group helpers here */ +#define SIGNED_EXTRACT(e, o, a, df) \ + do { \ + e = SIGNED_EVEN(a, df); \ + o = SIGNED_ODD(a, df); \ + } while (0) + +#define UNSIGNED_EXTRACT(e, o, a, df) \ + do { \ + e = UNSIGNED_EVEN(a, df); \ + o = UNSIGNED_ODD(a, df); \ + } while (0) + + +static inline int64_t msa_dotp_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + int64_t even_arg1; + int64_t even_arg2; + int64_t odd_arg1; + int64_t odd_arg2; + SIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df); + SIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df); + return (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2); +} + +void helper_msa_dotp_s_h(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->h[0] = msa_dotp_s_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_dotp_s_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_dotp_s_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_dotp_s_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_dotp_s_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_dotp_s_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_dotp_s_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_dotp_s_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_dotp_s_w(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->w[0] = msa_dotp_s_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_dotp_s_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_dotp_s_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_dotp_s_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_dotp_s_d(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = msa_dotp_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_dotp_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + + +static inline int64_t msa_dotp_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + int64_t even_arg1; + int64_t even_arg2; + int64_t odd_arg1; + int64_t odd_arg2; + UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df); + UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df); + return (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2); +} + +void helper_msa_dotp_u_h(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->h[0] = msa_dotp_u_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_dotp_u_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_dotp_u_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_dotp_u_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_dotp_u_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_dotp_u_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_dotp_u_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_dotp_u_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_dotp_u_w(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->w[0] = msa_dotp_u_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_dotp_u_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_dotp_u_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_dotp_u_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_dotp_u_d(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = msa_dotp_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_dotp_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + + +static inline int64_t msa_dpadd_s_df(uint32_t df, int64_t dest, int64_t arg1, + int64_t arg2) +{ + int64_t even_arg1; + int64_t even_arg2; + int64_t odd_arg1; + int64_t odd_arg2; + SIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df); + SIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df); + return dest + (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2); +} + +void helper_msa_dpadd_s_h(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->h[0] = msa_dpadd_s_df(DF_HALF, pwd->h[0], pws->h[0], pwt->h[0]); + pwd->h[1] = msa_dpadd_s_df(DF_HALF, pwd->h[1], pws->h[1], pwt->h[1]); + pwd->h[2] = msa_dpadd_s_df(DF_HALF, pwd->h[2], pws->h[2], pwt->h[2]); + pwd->h[3] = msa_dpadd_s_df(DF_HALF, pwd->h[3], pws->h[3], pwt->h[3]); + pwd->h[4] = msa_dpadd_s_df(DF_HALF, pwd->h[4], pws->h[4], pwt->h[4]); + pwd->h[5] = msa_dpadd_s_df(DF_HALF, pwd->h[5], pws->h[5], pwt->h[5]); + pwd->h[6] = msa_dpadd_s_df(DF_HALF, pwd->h[6], pws->h[6], pwt->h[6]); + pwd->h[7] = msa_dpadd_s_df(DF_HALF, pwd->h[7], pws->h[7], pwt->h[7]); +} + +void helper_msa_dpadd_s_w(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->w[0] = msa_dpadd_s_df(DF_WORD, pwd->w[0], pws->w[0], pwt->w[0]); + pwd->w[1] = msa_dpadd_s_df(DF_WORD, pwd->w[1], pws->w[1], pwt->w[1]); + pwd->w[2] = msa_dpadd_s_df(DF_WORD, pwd->w[2], pws->w[2], pwt->w[2]); + pwd->w[3] = msa_dpadd_s_df(DF_WORD, pwd->w[3], pws->w[3], pwt->w[3]); +} + +void helper_msa_dpadd_s_d(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = msa_dpadd_s_df(DF_DOUBLE, pwd->d[0], pws->d[0], pwt->d[0]); + pwd->d[1] = msa_dpadd_s_df(DF_DOUBLE, pwd->d[1], pws->d[1], pwt->d[1]); +} + + +static inline int64_t msa_dpadd_u_df(uint32_t df, int64_t dest, int64_t arg1, + int64_t arg2) +{ + int64_t even_arg1; + int64_t even_arg2; + int64_t odd_arg1; + int64_t odd_arg2; + UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df); + UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df); + return dest + (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2); +} + +void helper_msa_dpadd_u_h(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->h[0] = msa_dpadd_u_df(DF_HALF, pwd->h[0], pws->h[0], pwt->h[0]); + pwd->h[1] = msa_dpadd_u_df(DF_HALF, pwd->h[1], pws->h[1], pwt->h[1]); + pwd->h[2] = msa_dpadd_u_df(DF_HALF, pwd->h[2], pws->h[2], pwt->h[2]); + pwd->h[3] = msa_dpadd_u_df(DF_HALF, pwd->h[3], pws->h[3], pwt->h[3]); + pwd->h[4] = msa_dpadd_u_df(DF_HALF, pwd->h[4], pws->h[4], pwt->h[4]); + pwd->h[5] = msa_dpadd_u_df(DF_HALF, pwd->h[5], pws->h[5], pwt->h[5]); + pwd->h[6] = msa_dpadd_u_df(DF_HALF, pwd->h[6], pws->h[6], pwt->h[6]); + pwd->h[7] = msa_dpadd_u_df(DF_HALF, pwd->h[7], pws->h[7], pwt->h[7]); +} + +void helper_msa_dpadd_u_w(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->w[0] = msa_dpadd_u_df(DF_WORD, pwd->w[0], pws->w[0], pwt->w[0]); + pwd->w[1] = msa_dpadd_u_df(DF_WORD, pwd->w[1], pws->w[1], pwt->w[1]); + pwd->w[2] = msa_dpadd_u_df(DF_WORD, pwd->w[2], pws->w[2], pwt->w[2]); + pwd->w[3] = msa_dpadd_u_df(DF_WORD, pwd->w[3], pws->w[3], pwt->w[3]); +} + +void helper_msa_dpadd_u_d(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = msa_dpadd_u_df(DF_DOUBLE, pwd->d[0], pws->d[0], pwt->d[0]); + pwd->d[1] = msa_dpadd_u_df(DF_DOUBLE, pwd->d[1], pws->d[1], pwt->d[1]); +} + + +static inline int64_t msa_dpsub_s_df(uint32_t df, int64_t dest, int64_t arg1, + int64_t arg2) +{ + int64_t even_arg1; + int64_t even_arg2; + int64_t odd_arg1; + int64_t odd_arg2; + SIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df); + SIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df); + return dest - ((even_arg1 * even_arg2) + (odd_arg1 * odd_arg2)); +} + +void helper_msa_dpsub_s_h(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->h[0] = msa_dpsub_s_df(DF_HALF, pwd->h[0], pws->h[0], pwt->h[0]); + pwd->h[1] = msa_dpsub_s_df(DF_HALF, pwd->h[1], pws->h[1], pwt->h[1]); + pwd->h[2] = msa_dpsub_s_df(DF_HALF, pwd->h[2], pws->h[2], pwt->h[2]); + pwd->h[3] = msa_dpsub_s_df(DF_HALF, pwd->h[3], pws->h[3], pwt->h[3]); + pwd->h[4] = msa_dpsub_s_df(DF_HALF, pwd->h[4], pws->h[4], pwt->h[4]); + pwd->h[5] = msa_dpsub_s_df(DF_HALF, pwd->h[5], pws->h[5], pwt->h[5]); + pwd->h[6] = msa_dpsub_s_df(DF_HALF, pwd->h[6], pws->h[6], pwt->h[6]); + pwd->h[7] = msa_dpsub_s_df(DF_HALF, pwd->h[7], pws->h[7], pwt->h[7]); +} + +void helper_msa_dpsub_s_w(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->w[0] = msa_dpsub_s_df(DF_WORD, pwd->w[0], pws->w[0], pwt->w[0]); + pwd->w[1] = msa_dpsub_s_df(DF_WORD, pwd->w[1], pws->w[1], pwt->w[1]); + pwd->w[2] = msa_dpsub_s_df(DF_WORD, pwd->w[2], pws->w[2], pwt->w[2]); + pwd->w[3] = msa_dpsub_s_df(DF_WORD, pwd->w[3], pws->w[3], pwt->w[3]); +} + +void helper_msa_dpsub_s_d(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = msa_dpsub_s_df(DF_DOUBLE, pwd->d[0], pws->d[0], pwt->d[0]); + pwd->d[1] = msa_dpsub_s_df(DF_DOUBLE, pwd->d[1], pws->d[1], pwt->d[1]); +} + + +static inline int64_t msa_dpsub_u_df(uint32_t df, int64_t dest, int64_t arg1, + int64_t arg2) +{ + int64_t even_arg1; + int64_t even_arg2; + int64_t odd_arg1; + int64_t odd_arg2; + UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df); + UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df); + return dest - ((even_arg1 * even_arg2) + (odd_arg1 * odd_arg2)); +} + +void helper_msa_dpsub_u_h(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->h[0] = msa_dpsub_u_df(DF_HALF, pwd->h[0], pws->h[0], pwt->h[0]); + pwd->h[1] = msa_dpsub_u_df(DF_HALF, pwd->h[1], pws->h[1], pwt->h[1]); + pwd->h[2] = msa_dpsub_u_df(DF_HALF, pwd->h[2], pws->h[2], pwt->h[2]); + pwd->h[3] = msa_dpsub_u_df(DF_HALF, pwd->h[3], pws->h[3], pwt->h[3]); + pwd->h[4] = msa_dpsub_u_df(DF_HALF, pwd->h[4], pws->h[4], pwt->h[4]); + pwd->h[5] = msa_dpsub_u_df(DF_HALF, pwd->h[5], pws->h[5], pwt->h[5]); + pwd->h[6] = msa_dpsub_u_df(DF_HALF, pwd->h[6], pws->h[6], pwt->h[6]); + pwd->h[7] = msa_dpsub_u_df(DF_HALF, pwd->h[7], pws->h[7], pwt->h[7]); +} + +void helper_msa_dpsub_u_w(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->w[0] = msa_dpsub_u_df(DF_WORD, pwd->w[0], pws->w[0], pwt->w[0]); + pwd->w[1] = msa_dpsub_u_df(DF_WORD, pwd->w[1], pws->w[1], pwt->w[1]); + pwd->w[2] = msa_dpsub_u_df(DF_WORD, pwd->w[2], pws->w[2], pwt->w[2]); + pwd->w[3] = msa_dpsub_u_df(DF_WORD, pwd->w[3], pws->w[3], pwt->w[3]); +} + +void helper_msa_dpsub_u_d(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = msa_dpsub_u_df(DF_DOUBLE, pwd->d[0], pws->d[0], pwt->d[0]); + pwd->d[1] = msa_dpsub_u_df(DF_DOUBLE, pwd->d[1], pws->d[1], pwt->d[1]); +} /* @@ -2883,36 +3215,250 @@ void helper_msa_mod_u_d(CPUMIPSState *env, * +---------------+----------------------------------------------------------+ */ -/* TODO: insert Int Multiply group helpers here */ +static inline int64_t msa_maddv_df(uint32_t df, int64_t dest, int64_t arg1, + int64_t arg2) +{ + return dest + arg1 * arg2; +} +void helper_msa_maddv_b(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); -/* - * Int Subtract - * ------------ - * - * +---------------+----------------------------------------------------------+ - * | ASUB_S.B | Vector Absolute Values of Signed Subtract (byte) | - * | ASUB_S.H | Vector Absolute Values of Signed Subtract (halfword) | - * | ASUB_S.W | Vector Absolute Values of Signed Subtract (word) | - * | ASUB_S.D | Vector Absolute Values of Signed Subtract (doubleword) | - * | ASUB_U.B | Vector Absolute Values of Unsigned Subtract (byte) | - * | ASUB_U.H | Vector Absolute Values of Unsigned Subtract (halfword) | - * | ASUB_U.W | Vector Absolute Values of Unsigned Subtract (word) | - * | ASUB_U.D | Vector Absolute Values of Unsigned Subtract (doubleword) | - * | HSUB_S.H | Vector Signed Horizontal Subtract (halfword) | - * | HSUB_S.W | Vector Signed Horizontal Subtract (word) | - * | HSUB_S.D | Vector Signed Horizontal Subtract (doubleword) | - * | HSUB_U.H | Vector Unigned Horizontal Subtract (halfword) | - * | HSUB_U.W | Vector Unigned Horizontal Subtract (word) | - * | HSUB_U.D | Vector Unigned Horizontal Subtract (doubleword) | - * | SUBS_S.B | Vector Signed Saturated Subtract (of Signed) (byte) | - * | SUBS_S.H | Vector Signed Saturated Subtract (of Signed) (halfword) | - * | SUBS_S.W | Vector Signed Saturated Subtract (of Signed) (word) | - * | SUBS_S.D | Vector Signed Saturated Subtract (of Signed) (doubleword)| - * | SUBS_U.B | Vector Unsigned Saturated Subtract (of Uns.) (byte) | - * | SUBS_U.H | Vector Unsigned Saturated Subtract (of Uns.) (halfword) | - * | SUBS_U.W | Vector Unsigned Saturated Subtract (of Uns.) (word) | - * | SUBS_U.D | Vector Unsigned Saturated Subtract (of Uns.) (doubleword)| + pwd->b[0] = msa_maddv_df(DF_BYTE, pwt->b[0], pws->b[0], pwt->b[0]); + pwd->b[1] = msa_maddv_df(DF_BYTE, pwt->b[1], pws->b[1], pwt->b[1]); + pwd->b[2] = msa_maddv_df(DF_BYTE, pwt->b[2], pws->b[2], pwt->b[2]); + pwd->b[3] = msa_maddv_df(DF_BYTE, pwt->b[3], pws->b[3], pwt->b[3]); + pwd->b[4] = msa_maddv_df(DF_BYTE, pwt->b[4], pws->b[4], pwt->b[4]); + pwd->b[5] = msa_maddv_df(DF_BYTE, pwt->b[5], pws->b[5], pwt->b[5]); + pwd->b[6] = msa_maddv_df(DF_BYTE, pwt->b[6], pws->b[6], pwt->b[6]); + pwd->b[7] = msa_maddv_df(DF_BYTE, pwt->b[7], pws->b[7], pwt->b[7]); + pwd->b[8] = msa_maddv_df(DF_BYTE, pwt->b[8], pws->b[8], pwt->b[8]); + pwd->b[9] = msa_maddv_df(DF_BYTE, pwt->b[9], pws->b[9], pwt->b[9]); + pwd->b[10] = msa_maddv_df(DF_BYTE, pwt->b[10], pws->b[10], pwt->b[10]); + pwd->b[11] = msa_maddv_df(DF_BYTE, pwt->b[11], pws->b[11], pwt->b[11]); + pwd->b[12] = msa_maddv_df(DF_BYTE, pwt->b[12], pws->b[12], pwt->b[12]); + pwd->b[13] = msa_maddv_df(DF_BYTE, pwt->b[13], pws->b[13], pwt->b[13]); + pwd->b[14] = msa_maddv_df(DF_BYTE, pwt->b[14], pws->b[14], pwt->b[14]); + pwd->b[15] = msa_maddv_df(DF_BYTE, pwt->b[15], pws->b[15], pwt->b[15]); +} + +void helper_msa_maddv_h(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->h[0] = msa_maddv_df(DF_HALF, pwd->h[0], pws->h[0], pwt->h[0]); + pwd->h[1] = msa_maddv_df(DF_HALF, pwd->h[1], pws->h[1], pwt->h[1]); + pwd->h[2] = msa_maddv_df(DF_HALF, pwd->h[2], pws->h[2], pwt->h[2]); + pwd->h[3] = msa_maddv_df(DF_HALF, pwd->h[3], pws->h[3], pwt->h[3]); + pwd->h[4] = msa_maddv_df(DF_HALF, pwd->h[4], pws->h[4], pwt->h[4]); + pwd->h[5] = msa_maddv_df(DF_HALF, pwd->h[5], pws->h[5], pwt->h[5]); + pwd->h[6] = msa_maddv_df(DF_HALF, pwd->h[6], pws->h[6], pwt->h[6]); + pwd->h[7] = msa_maddv_df(DF_HALF, pwd->h[7], pws->h[7], pwt->h[7]); +} + +void helper_msa_maddv_w(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->w[0] = msa_maddv_df(DF_WORD, pwd->w[0], pws->w[0], pwt->w[0]); + pwd->w[1] = msa_maddv_df(DF_WORD, pwd->w[1], pws->w[1], pwt->w[1]); + pwd->w[2] = msa_maddv_df(DF_WORD, pwd->w[2], pws->w[2], pwt->w[2]); + pwd->w[3] = msa_maddv_df(DF_WORD, pwd->w[3], pws->w[3], pwt->w[3]); +} + +void helper_msa_maddv_d(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = msa_maddv_df(DF_DOUBLE, pwd->d[0], pws->d[0], pwt->d[0]); + pwd->d[1] = msa_maddv_df(DF_DOUBLE, pwd->d[1], pws->d[1], pwt->d[1]); +} + +static inline int64_t msa_msubv_df(uint32_t df, int64_t dest, int64_t arg1, + int64_t arg2) +{ + return dest - arg1 * arg2; +} + +void helper_msa_msubv_b(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->b[0] = msa_msubv_df(DF_BYTE, pwt->b[0], pws->b[0], pwt->b[0]); + pwd->b[1] = msa_msubv_df(DF_BYTE, pwt->b[1], pws->b[1], pwt->b[1]); + pwd->b[2] = msa_msubv_df(DF_BYTE, pwt->b[2], pws->b[2], pwt->b[2]); + pwd->b[3] = msa_msubv_df(DF_BYTE, pwt->b[3], pws->b[3], pwt->b[3]); + pwd->b[4] = msa_msubv_df(DF_BYTE, pwt->b[4], pws->b[4], pwt->b[4]); + pwd->b[5] = msa_msubv_df(DF_BYTE, pwt->b[5], pws->b[5], pwt->b[5]); + pwd->b[6] = msa_msubv_df(DF_BYTE, pwt->b[6], pws->b[6], pwt->b[6]); + pwd->b[7] = msa_msubv_df(DF_BYTE, pwt->b[7], pws->b[7], pwt->b[7]); + pwd->b[8] = msa_msubv_df(DF_BYTE, pwt->b[8], pws->b[8], pwt->b[8]); + pwd->b[9] = msa_msubv_df(DF_BYTE, pwt->b[9], pws->b[9], pwt->b[9]); + pwd->b[10] = msa_msubv_df(DF_BYTE, pwt->b[10], pws->b[10], pwt->b[10]); + pwd->b[11] = msa_msubv_df(DF_BYTE, pwt->b[11], pws->b[11], pwt->b[11]); + pwd->b[12] = msa_msubv_df(DF_BYTE, pwt->b[12], pws->b[12], pwt->b[12]); + pwd->b[13] = msa_msubv_df(DF_BYTE, pwt->b[13], pws->b[13], pwt->b[13]); + pwd->b[14] = msa_msubv_df(DF_BYTE, pwt->b[14], pws->b[14], pwt->b[14]); + pwd->b[15] = msa_msubv_df(DF_BYTE, pwt->b[15], pws->b[15], pwt->b[15]); +} + +void helper_msa_msubv_h(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->h[0] = msa_msubv_df(DF_HALF, pwd->h[0], pws->h[0], pwt->h[0]); + pwd->h[1] = msa_msubv_df(DF_HALF, pwd->h[1], pws->h[1], pwt->h[1]); + pwd->h[2] = msa_msubv_df(DF_HALF, pwd->h[2], pws->h[2], pwt->h[2]); + pwd->h[3] = msa_msubv_df(DF_HALF, pwd->h[3], pws->h[3], pwt->h[3]); + pwd->h[4] = msa_msubv_df(DF_HALF, pwd->h[4], pws->h[4], pwt->h[4]); + pwd->h[5] = msa_msubv_df(DF_HALF, pwd->h[5], pws->h[5], pwt->h[5]); + pwd->h[6] = msa_msubv_df(DF_HALF, pwd->h[6], pws->h[6], pwt->h[6]); + pwd->h[7] = msa_msubv_df(DF_HALF, pwd->h[7], pws->h[7], pwt->h[7]); +} + +void helper_msa_msubv_w(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->w[0] = msa_msubv_df(DF_WORD, pwd->w[0], pws->w[0], pwt->w[0]); + pwd->w[1] = msa_msubv_df(DF_WORD, pwd->w[1], pws->w[1], pwt->w[1]); + pwd->w[2] = msa_msubv_df(DF_WORD, pwd->w[2], pws->w[2], pwt->w[2]); + pwd->w[3] = msa_msubv_df(DF_WORD, pwd->w[3], pws->w[3], pwt->w[3]); +} + +void helper_msa_msubv_d(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = msa_msubv_df(DF_DOUBLE, pwd->d[0], pws->d[0], pwt->d[0]); + pwd->d[1] = msa_msubv_df(DF_DOUBLE, pwd->d[1], pws->d[1], pwt->d[1]); +} + + +static inline int64_t msa_mulv_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + return arg1 * arg2; +} + +void helper_msa_mulv_b(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->b[0] = msa_mulv_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_mulv_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_mulv_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_mulv_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_mulv_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_mulv_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_mulv_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_mulv_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_mulv_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_mulv_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_mulv_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_mulv_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_mulv_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_mulv_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_mulv_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_mulv_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_mulv_h(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->h[0] = msa_mulv_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_mulv_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_mulv_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_mulv_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_mulv_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_mulv_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_mulv_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_mulv_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_mulv_w(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->w[0] = msa_mulv_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_mulv_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_mulv_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_mulv_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_mulv_d(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = msa_mulv_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_mulv_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + + +/* + * Int Subtract + * ------------ + * + * +---------------+----------------------------------------------------------+ + * | ASUB_S.B | Vector Absolute Values of Signed Subtract (byte) | + * | ASUB_S.H | Vector Absolute Values of Signed Subtract (halfword) | + * | ASUB_S.W | Vector Absolute Values of Signed Subtract (word) | + * | ASUB_S.D | Vector Absolute Values of Signed Subtract (doubleword) | + * | ASUB_U.B | Vector Absolute Values of Unsigned Subtract (byte) | + * | ASUB_U.H | Vector Absolute Values of Unsigned Subtract (halfword) | + * | ASUB_U.W | Vector Absolute Values of Unsigned Subtract (word) | + * | ASUB_U.D | Vector Absolute Values of Unsigned Subtract (doubleword) | + * | HSUB_S.H | Vector Signed Horizontal Subtract (halfword) | + * | HSUB_S.W | Vector Signed Horizontal Subtract (word) | + * | HSUB_S.D | Vector Signed Horizontal Subtract (doubleword) | + * | HSUB_U.H | Vector Unigned Horizontal Subtract (halfword) | + * | HSUB_U.W | Vector Unigned Horizontal Subtract (word) | + * | HSUB_U.D | Vector Unigned Horizontal Subtract (doubleword) | + * | SUBS_S.B | Vector Signed Saturated Subtract (of Signed) (byte) | + * | SUBS_S.H | Vector Signed Saturated Subtract (of Signed) (halfword) | + * | SUBS_S.W | Vector Signed Saturated Subtract (of Signed) (word) | + * | SUBS_S.D | Vector Signed Saturated Subtract (of Signed) (doubleword)| + * | SUBS_U.B | Vector Unsigned Saturated Subtract (of Uns.) (byte) | + * | SUBS_U.H | Vector Unsigned Saturated Subtract (of Uns.) (halfword) | + * | SUBS_U.W | Vector Unsigned Saturated Subtract (of Uns.) (word) | + * | SUBS_U.D | Vector Unsigned Saturated Subtract (of Uns.) (doubleword)| * | SUBSUS_U.B | Vector Uns. Sat. Subtract (of S. from Uns.) (byte) | * | SUBSUS_U.H | Vector Uns. Sat. Subtract (of S. from Uns.) (halfword) | * | SUBSUS_U.W | Vector Uns. Sat. Subtract (of S. from Uns.) (word) | @@ -3067,112 +3613,501 @@ void helper_msa_asub_u_w(CPUMIPSState *env, pwd->w[3] = msa_asub_u_df(DF_WORD, pws->w[3], pwt->w[3]); } -void helper_msa_asub_u_d(CPUMIPSState *env, - uint32_t wd, uint32_t ws, uint32_t wt) +void helper_msa_asub_u_d(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = msa_asub_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_asub_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + + +static inline int64_t msa_hsub_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + return SIGNED_ODD(arg1, df) - SIGNED_EVEN(arg2, df); +} + +void helper_msa_hsub_s_h(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->h[0] = msa_hsub_s_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_hsub_s_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_hsub_s_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_hsub_s_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_hsub_s_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_hsub_s_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_hsub_s_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_hsub_s_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_hsub_s_w(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->w[0] = msa_hsub_s_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_hsub_s_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_hsub_s_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_hsub_s_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_hsub_s_d(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = msa_hsub_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_hsub_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + + +static inline int64_t msa_hsub_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + return UNSIGNED_ODD(arg1, df) - UNSIGNED_EVEN(arg2, df); +} + +void helper_msa_hsub_u_h(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->h[0] = msa_hsub_u_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_hsub_u_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_hsub_u_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_hsub_u_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_hsub_u_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_hsub_u_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_hsub_u_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_hsub_u_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_hsub_u_w(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->w[0] = msa_hsub_u_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_hsub_u_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_hsub_u_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_hsub_u_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_hsub_u_d(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = msa_hsub_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_hsub_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + + +static inline int64_t msa_subs_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + int64_t max_int = DF_MAX_INT(df); + int64_t min_int = DF_MIN_INT(df); + if (arg2 > 0) { + return (min_int + arg2 < arg1) ? arg1 - arg2 : min_int; + } else { + return (arg1 < max_int + arg2) ? arg1 - arg2 : max_int; + } +} + +void helper_msa_subs_s_b(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->b[0] = msa_subs_s_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_subs_s_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_subs_s_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_subs_s_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_subs_s_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_subs_s_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_subs_s_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_subs_s_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_subs_s_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_subs_s_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_subs_s_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_subs_s_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_subs_s_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_subs_s_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_subs_s_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_subs_s_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_subs_s_h(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->h[0] = msa_subs_s_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_subs_s_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_subs_s_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_subs_s_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_subs_s_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_subs_s_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_subs_s_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_subs_s_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_subs_s_w(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->w[0] = msa_subs_s_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_subs_s_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_subs_s_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_subs_s_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_subs_s_d(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = msa_subs_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_subs_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + + +static inline int64_t msa_subs_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_arg2 = UNSIGNED(arg2, df); + return (u_arg1 > u_arg2) ? u_arg1 - u_arg2 : 0; +} + +void helper_msa_subs_u_b(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->b[0] = msa_subs_u_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_subs_u_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_subs_u_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_subs_u_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_subs_u_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_subs_u_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_subs_u_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_subs_u_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_subs_u_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_subs_u_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_subs_u_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_subs_u_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_subs_u_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_subs_u_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_subs_u_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_subs_u_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_subs_u_h(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->h[0] = msa_subs_u_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_subs_u_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_subs_u_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_subs_u_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_subs_u_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_subs_u_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_subs_u_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_subs_u_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_subs_u_w(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->w[0] = msa_subs_u_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_subs_u_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_subs_u_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_subs_u_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_subs_u_d(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = msa_subs_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_subs_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]); +} + + +static inline int64_t msa_subsus_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t max_uint = DF_MAX_UINT(df); + if (arg2 >= 0) { + uint64_t u_arg2 = (uint64_t)arg2; + return (u_arg1 > u_arg2) ? + (int64_t)(u_arg1 - u_arg2) : + 0; + } else { + uint64_t u_arg2 = (uint64_t)(-arg2); + return (u_arg1 < max_uint - u_arg2) ? + (int64_t)(u_arg1 + u_arg2) : + (int64_t)max_uint; + } +} + +void helper_msa_subsus_u_b(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->b[0] = msa_subsus_u_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_subsus_u_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_subsus_u_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_subsus_u_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_subsus_u_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_subsus_u_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_subsus_u_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_subsus_u_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_subsus_u_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_subsus_u_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_subsus_u_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_subsus_u_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_subsus_u_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_subsus_u_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_subsus_u_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_subsus_u_df(DF_BYTE, pws->b[15], pwt->b[15]); +} + +void helper_msa_subsus_u_h(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->h[0] = msa_subsus_u_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_subsus_u_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_subsus_u_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_subsus_u_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_subsus_u_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_subsus_u_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_subsus_u_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_subsus_u_df(DF_HALF, pws->h[7], pwt->h[7]); +} + +void helper_msa_subsus_u_w(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->w[0] = msa_subsus_u_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_subsus_u_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_subsus_u_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_subsus_u_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_subsus_u_d(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) { wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - pwd->d[0] = msa_asub_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]); - pwd->d[1] = msa_asub_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]); + pwd->d[0] = msa_subsus_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_subsus_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]); } -/* TODO: insert the rest of Int Subtract group helpers here */ - +static inline int64_t msa_subsuu_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_arg2 = UNSIGNED(arg2, df); + int64_t max_int = DF_MAX_INT(df); + int64_t min_int = DF_MIN_INT(df); + if (u_arg1 > u_arg2) { + return u_arg1 - u_arg2 < (uint64_t)max_int ? + (int64_t)(u_arg1 - u_arg2) : + max_int; + } else { + return u_arg2 - u_arg1 < (uint64_t)(-min_int) ? + (int64_t)(u_arg1 - u_arg2) : + min_int; + } +} -static inline int64_t msa_hsub_s_df(uint32_t df, int64_t arg1, int64_t arg2) +void helper_msa_subsuu_s_b(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) { - return SIGNED_ODD(arg1, df) - SIGNED_EVEN(arg2, df); + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->b[0] = msa_subsuu_s_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_subsuu_s_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_subsuu_s_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_subsuu_s_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_subsuu_s_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_subsuu_s_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_subsuu_s_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_subsuu_s_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_subsuu_s_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_subsuu_s_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_subsuu_s_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_subsuu_s_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_subsuu_s_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_subsuu_s_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_subsuu_s_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_subsuu_s_df(DF_BYTE, pws->b[15], pwt->b[15]); } -void helper_msa_hsub_s_h(CPUMIPSState *env, - uint32_t wd, uint32_t ws, uint32_t wt) +void helper_msa_subsuu_s_h(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) { wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - pwd->h[0] = msa_hsub_s_df(DF_HALF, pws->h[0], pwt->h[0]); - pwd->h[1] = msa_hsub_s_df(DF_HALF, pws->h[1], pwt->h[1]); - pwd->h[2] = msa_hsub_s_df(DF_HALF, pws->h[2], pwt->h[2]); - pwd->h[3] = msa_hsub_s_df(DF_HALF, pws->h[3], pwt->h[3]); - pwd->h[4] = msa_hsub_s_df(DF_HALF, pws->h[4], pwt->h[4]); - pwd->h[5] = msa_hsub_s_df(DF_HALF, pws->h[5], pwt->h[5]); - pwd->h[6] = msa_hsub_s_df(DF_HALF, pws->h[6], pwt->h[6]); - pwd->h[7] = msa_hsub_s_df(DF_HALF, pws->h[7], pwt->h[7]); + pwd->h[0] = msa_subsuu_s_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_subsuu_s_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_subsuu_s_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_subsuu_s_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_subsuu_s_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_subsuu_s_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_subsuu_s_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_subsuu_s_df(DF_HALF, pws->h[7], pwt->h[7]); } -void helper_msa_hsub_s_w(CPUMIPSState *env, - uint32_t wd, uint32_t ws, uint32_t wt) +void helper_msa_subsuu_s_w(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) { wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - pwd->w[0] = msa_hsub_s_df(DF_WORD, pws->w[0], pwt->w[0]); - pwd->w[1] = msa_hsub_s_df(DF_WORD, pws->w[1], pwt->w[1]); - pwd->w[2] = msa_hsub_s_df(DF_WORD, pws->w[2], pwt->w[2]); - pwd->w[3] = msa_hsub_s_df(DF_WORD, pws->w[3], pwt->w[3]); + pwd->w[0] = msa_subsuu_s_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_subsuu_s_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_subsuu_s_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_subsuu_s_df(DF_WORD, pws->w[3], pwt->w[3]); } -void helper_msa_hsub_s_d(CPUMIPSState *env, - uint32_t wd, uint32_t ws, uint32_t wt) +void helper_msa_subsuu_s_d(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) { wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - pwd->d[0] = msa_hsub_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]); - pwd->d[1] = msa_hsub_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]); + pwd->d[0] = msa_subsuu_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_subsuu_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]); } -static inline int64_t msa_hsub_u_df(uint32_t df, int64_t arg1, int64_t arg2) +static inline int64_t msa_subv_df(uint32_t df, int64_t arg1, int64_t arg2) { - return UNSIGNED_ODD(arg1, df) - UNSIGNED_EVEN(arg2, df); + return arg1 - arg2; } -void helper_msa_hsub_u_h(CPUMIPSState *env, - uint32_t wd, uint32_t ws, uint32_t wt) +void helper_msa_subv_b(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) { wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - pwd->h[0] = msa_hsub_u_df(DF_HALF, pws->h[0], pwt->h[0]); - pwd->h[1] = msa_hsub_u_df(DF_HALF, pws->h[1], pwt->h[1]); - pwd->h[2] = msa_hsub_u_df(DF_HALF, pws->h[2], pwt->h[2]); - pwd->h[3] = msa_hsub_u_df(DF_HALF, pws->h[3], pwt->h[3]); - pwd->h[4] = msa_hsub_u_df(DF_HALF, pws->h[4], pwt->h[4]); - pwd->h[5] = msa_hsub_u_df(DF_HALF, pws->h[5], pwt->h[5]); - pwd->h[6] = msa_hsub_u_df(DF_HALF, pws->h[6], pwt->h[6]); - pwd->h[7] = msa_hsub_u_df(DF_HALF, pws->h[7], pwt->h[7]); + pwd->b[0] = msa_subv_df(DF_BYTE, pws->b[0], pwt->b[0]); + pwd->b[1] = msa_subv_df(DF_BYTE, pws->b[1], pwt->b[1]); + pwd->b[2] = msa_subv_df(DF_BYTE, pws->b[2], pwt->b[2]); + pwd->b[3] = msa_subv_df(DF_BYTE, pws->b[3], pwt->b[3]); + pwd->b[4] = msa_subv_df(DF_BYTE, pws->b[4], pwt->b[4]); + pwd->b[5] = msa_subv_df(DF_BYTE, pws->b[5], pwt->b[5]); + pwd->b[6] = msa_subv_df(DF_BYTE, pws->b[6], pwt->b[6]); + pwd->b[7] = msa_subv_df(DF_BYTE, pws->b[7], pwt->b[7]); + pwd->b[8] = msa_subv_df(DF_BYTE, pws->b[8], pwt->b[8]); + pwd->b[9] = msa_subv_df(DF_BYTE, pws->b[9], pwt->b[9]); + pwd->b[10] = msa_subv_df(DF_BYTE, pws->b[10], pwt->b[10]); + pwd->b[11] = msa_subv_df(DF_BYTE, pws->b[11], pwt->b[11]); + pwd->b[12] = msa_subv_df(DF_BYTE, pws->b[12], pwt->b[12]); + pwd->b[13] = msa_subv_df(DF_BYTE, pws->b[13], pwt->b[13]); + pwd->b[14] = msa_subv_df(DF_BYTE, pws->b[14], pwt->b[14]); + pwd->b[15] = msa_subv_df(DF_BYTE, pws->b[15], pwt->b[15]); } -void helper_msa_hsub_u_w(CPUMIPSState *env, - uint32_t wd, uint32_t ws, uint32_t wt) +void helper_msa_subv_h(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) { wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - pwd->w[0] = msa_hsub_u_df(DF_WORD, pws->w[0], pwt->w[0]); - pwd->w[1] = msa_hsub_u_df(DF_WORD, pws->w[1], pwt->w[1]); - pwd->w[2] = msa_hsub_u_df(DF_WORD, pws->w[2], pwt->w[2]); - pwd->w[3] = msa_hsub_u_df(DF_WORD, pws->w[3], pwt->w[3]); + pwd->h[0] = msa_subv_df(DF_HALF, pws->h[0], pwt->h[0]); + pwd->h[1] = msa_subv_df(DF_HALF, pws->h[1], pwt->h[1]); + pwd->h[2] = msa_subv_df(DF_HALF, pws->h[2], pwt->h[2]); + pwd->h[3] = msa_subv_df(DF_HALF, pws->h[3], pwt->h[3]); + pwd->h[4] = msa_subv_df(DF_HALF, pws->h[4], pwt->h[4]); + pwd->h[5] = msa_subv_df(DF_HALF, pws->h[5], pwt->h[5]); + pwd->h[6] = msa_subv_df(DF_HALF, pws->h[6], pwt->h[6]); + pwd->h[7] = msa_subv_df(DF_HALF, pws->h[7], pwt->h[7]); } -void helper_msa_hsub_u_d(CPUMIPSState *env, - uint32_t wd, uint32_t ws, uint32_t wt) +void helper_msa_subv_w(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) { wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - pwd->d[0] = msa_hsub_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]); - pwd->d[1] = msa_hsub_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]); + pwd->w[0] = msa_subv_df(DF_WORD, pws->w[0], pwt->w[0]); + pwd->w[1] = msa_subv_df(DF_WORD, pws->w[1], pwt->w[1]); + pwd->w[2] = msa_subv_df(DF_WORD, pws->w[2], pwt->w[2]); + pwd->w[3] = msa_subv_df(DF_WORD, pws->w[3], pwt->w[3]); +} + +void helper_msa_subv_d(CPUMIPSState *env, + uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = msa_subv_df(DF_DOUBLE, pws->d[0], pwt->d[0]); + pwd->d[1] = msa_subv_df(DF_DOUBLE, pws->d[1], pwt->d[1]); } @@ -4400,11 +5335,6 @@ void helper_msa_shf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, msa_move_v(pwd, pwx); } -static inline int64_t msa_subv_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - return arg1 - arg2; -} - #define MSA_BINOP_IMM_DF(helper, func) \ void helper_msa_ ## helper ## _df(CPUMIPSState *env, uint32_t df, \ uint32_t wd, uint32_t ws, int32_t u5) \ @@ -4586,97 +5516,6 @@ MSA_TEROP_IMMU_DF(binsli, binsl) MSA_TEROP_IMMU_DF(binsri, binsr) #undef MSA_TEROP_IMMU_DF -static inline int64_t msa_subs_s_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - int64_t max_int = DF_MAX_INT(df); - int64_t min_int = DF_MIN_INT(df); - if (arg2 > 0) { - return (min_int + arg2 < arg1) ? arg1 - arg2 : min_int; - } else { - return (arg1 < max_int + arg2) ? arg1 - arg2 : max_int; - } -} - -static inline int64_t msa_subs_u_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - uint64_t u_arg1 = UNSIGNED(arg1, df); - uint64_t u_arg2 = UNSIGNED(arg2, df); - return (u_arg1 > u_arg2) ? u_arg1 - u_arg2 : 0; -} - -static inline int64_t msa_subsus_u_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - uint64_t u_arg1 = UNSIGNED(arg1, df); - uint64_t max_uint = DF_MAX_UINT(df); - if (arg2 >= 0) { - uint64_t u_arg2 = (uint64_t)arg2; - return (u_arg1 > u_arg2) ? - (int64_t)(u_arg1 - u_arg2) : - 0; - } else { - uint64_t u_arg2 = (uint64_t)(-arg2); - return (u_arg1 < max_uint - u_arg2) ? - (int64_t)(u_arg1 + u_arg2) : - (int64_t)max_uint; - } -} - -static inline int64_t msa_subsuu_s_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - uint64_t u_arg1 = UNSIGNED(arg1, df); - uint64_t u_arg2 = UNSIGNED(arg2, df); - int64_t max_int = DF_MAX_INT(df); - int64_t min_int = DF_MIN_INT(df); - if (u_arg1 > u_arg2) { - return u_arg1 - u_arg2 < (uint64_t)max_int ? - (int64_t)(u_arg1 - u_arg2) : - max_int; - } else { - return u_arg2 - u_arg1 < (uint64_t)(-min_int) ? - (int64_t)(u_arg1 - u_arg2) : - min_int; - } -} - -static inline int64_t msa_mulv_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - return arg1 * arg2; -} - -#define SIGNED_EXTRACT(e, o, a, df) \ - do { \ - e = SIGNED_EVEN(a, df); \ - o = SIGNED_ODD(a, df); \ - } while (0) - -#define UNSIGNED_EXTRACT(e, o, a, df) \ - do { \ - e = UNSIGNED_EVEN(a, df); \ - o = UNSIGNED_ODD(a, df); \ - } while (0) - -static inline int64_t msa_dotp_s_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - int64_t even_arg1; - int64_t even_arg2; - int64_t odd_arg1; - int64_t odd_arg2; - SIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df); - SIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df); - return (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2); -} - -static inline int64_t msa_dotp_u_df(uint32_t df, int64_t arg1, int64_t arg2) -{ - int64_t even_arg1; - int64_t even_arg2; - int64_t odd_arg1; - int64_t odd_arg2; - UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df); - UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df); - return (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2); -} - #define CONCATENATE_AND_SLIDE(s, k) \ do { \ for (i = 0; i < s; i++) { \ @@ -4794,15 +5633,6 @@ void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, \ } \ } -MSA_BINOP_DF(subv) -MSA_BINOP_DF(subs_s) -MSA_BINOP_DF(subs_u) -MSA_BINOP_DF(subsus_u) -MSA_BINOP_DF(subsuu_s) -MSA_BINOP_DF(mulv) -MSA_BINOP_DF(dotp_s) -MSA_BINOP_DF(dotp_u) - MSA_BINOP_DF(mul_q) MSA_BINOP_DF(mulr_q) #undef MSA_BINOP_DF @@ -4816,66 +5646,6 @@ void helper_msa_sld_df(CPUMIPSState *env, uint32_t df, uint32_t wd, msa_sld_df(df, pwd, pws, env->active_tc.gpr[rt]); } -static inline int64_t msa_maddv_df(uint32_t df, int64_t dest, int64_t arg1, - int64_t arg2) -{ - return dest + arg1 * arg2; -} - -static inline int64_t msa_msubv_df(uint32_t df, int64_t dest, int64_t arg1, - int64_t arg2) -{ - return dest - arg1 * arg2; -} - -static inline int64_t msa_dpadd_s_df(uint32_t df, int64_t dest, int64_t arg1, - int64_t arg2) -{ - int64_t even_arg1; - int64_t even_arg2; - int64_t odd_arg1; - int64_t odd_arg2; - SIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df); - SIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df); - return dest + (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2); -} - -static inline int64_t msa_dpadd_u_df(uint32_t df, int64_t dest, int64_t arg1, - int64_t arg2) -{ - int64_t even_arg1; - int64_t even_arg2; - int64_t odd_arg1; - int64_t odd_arg2; - UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df); - UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df); - return dest + (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2); -} - -static inline int64_t msa_dpsub_s_df(uint32_t df, int64_t dest, int64_t arg1, - int64_t arg2) -{ - int64_t even_arg1; - int64_t even_arg2; - int64_t odd_arg1; - int64_t odd_arg2; - SIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df); - SIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df); - return dest - ((even_arg1 * even_arg2) + (odd_arg1 * odd_arg2)); -} - -static inline int64_t msa_dpsub_u_df(uint32_t df, int64_t dest, int64_t arg1, - int64_t arg2) -{ - int64_t even_arg1; - int64_t even_arg2; - int64_t odd_arg1; - int64_t odd_arg2; - UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df); - UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df); - return dest - ((even_arg1 * even_arg2) + (odd_arg1 * odd_arg2)); -} - static inline int64_t msa_madd_q_df(uint32_t df, int64_t dest, int64_t arg1, int64_t arg2) { @@ -5002,12 +5772,6 @@ void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, uint32_t wd, \ } \ } -MSA_TEROP_DF(maddv) -MSA_TEROP_DF(msubv) -MSA_TEROP_DF(dpadd_s) -MSA_TEROP_DF(dpadd_u) -MSA_TEROP_DF(dpsub_s) -MSA_TEROP_DF(dpsub_u) MSA_TEROP_DF(binsl) MSA_TEROP_DF(binsr) MSA_TEROP_DF(madd_q) @@ -5419,54 +6183,81 @@ static inline void check_msacsr_cause(CPUMIPSState *env, uintptr_t retaddr) #define CLEAR_IS_INEXACT 2 #define RECIPROCAL_INEXACT 4 -static inline int update_msacsr(CPUMIPSState *env, int action, int denormal) + +static inline int ieee_to_mips_xcpt_msa(int ieee_xcpt) { - int ieee_ex; + int mips_xcpt = 0; + + if (ieee_xcpt & float_flag_invalid) { + mips_xcpt |= FP_INVALID; + } + if (ieee_xcpt & float_flag_overflow) { + mips_xcpt |= FP_OVERFLOW; + } + if (ieee_xcpt & float_flag_underflow) { + mips_xcpt |= FP_UNDERFLOW; + } + if (ieee_xcpt & float_flag_divbyzero) { + mips_xcpt |= FP_DIV0; + } + if (ieee_xcpt & float_flag_inexact) { + mips_xcpt |= FP_INEXACT; + } + + return mips_xcpt; +} - int c; +static inline int update_msacsr(CPUMIPSState *env, int action, int denormal) +{ + int ieee_exception_flags; + int mips_exception_flags = 0; int cause; int enable; - ieee_ex = get_float_exception_flags(&env->active_tc.msa_fp_status); + ieee_exception_flags = get_float_exception_flags( + &env->active_tc.msa_fp_status); /* QEMU softfloat does not signal all underflow cases */ if (denormal) { - ieee_ex |= float_flag_underflow; + ieee_exception_flags |= float_flag_underflow; + } + if (ieee_exception_flags) { + mips_exception_flags = ieee_to_mips_xcpt_msa(ieee_exception_flags); } - - c = ieee_ex_to_mips(ieee_ex); enable = GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED; /* Set Inexact (I) when flushing inputs to zero */ - if ((ieee_ex & float_flag_input_denormal) && + if ((ieee_exception_flags & float_flag_input_denormal) && (env->active_tc.msacsr & MSACSR_FS_MASK) != 0) { if (action & CLEAR_IS_INEXACT) { - c &= ~FP_INEXACT; + mips_exception_flags &= ~FP_INEXACT; } else { - c |= FP_INEXACT; + mips_exception_flags |= FP_INEXACT; } } /* Set Inexact (I) and Underflow (U) when flushing outputs to zero */ - if ((ieee_ex & float_flag_output_denormal) && + if ((ieee_exception_flags & float_flag_output_denormal) && (env->active_tc.msacsr & MSACSR_FS_MASK) != 0) { - c |= FP_INEXACT; + mips_exception_flags |= FP_INEXACT; if (action & CLEAR_FS_UNDERFLOW) { - c &= ~FP_UNDERFLOW; + mips_exception_flags &= ~FP_UNDERFLOW; } else { - c |= FP_UNDERFLOW; + mips_exception_flags |= FP_UNDERFLOW; } } /* Set Inexact (I) when Overflow (O) is not enabled */ - if ((c & FP_OVERFLOW) != 0 && (enable & FP_OVERFLOW) == 0) { - c |= FP_INEXACT; + if ((mips_exception_flags & FP_OVERFLOW) != 0 && + (enable & FP_OVERFLOW) == 0) { + mips_exception_flags |= FP_INEXACT; } /* Clear Exact Underflow when Underflow (U) is not enabled */ - if ((c & FP_UNDERFLOW) != 0 && (enable & FP_UNDERFLOW) == 0 && - (c & FP_INEXACT) == 0) { - c &= ~FP_UNDERFLOW; + if ((mips_exception_flags & FP_UNDERFLOW) != 0 && + (enable & FP_UNDERFLOW) == 0 && + (mips_exception_flags & FP_INEXACT) == 0) { + mips_exception_flags &= ~FP_UNDERFLOW; } /* @@ -5474,11 +6265,11 @@ static inline int update_msacsr(CPUMIPSState *env, int action, int denormal) * divide by zero */ if ((action & RECIPROCAL_INEXACT) && - (c & (FP_INVALID | FP_DIV0)) == 0) { - c = FP_INEXACT; + (mips_exception_flags & (FP_INVALID | FP_DIV0)) == 0) { + mips_exception_flags = FP_INEXACT; } - cause = c & enable; /* all current enabled exceptions */ + cause = mips_exception_flags & enable; /* all current enabled exceptions */ if (cause == 0) { /* @@ -5486,7 +6277,7 @@ static inline int update_msacsr(CPUMIPSState *env, int action, int denormal) * with all current exceptions */ SET_FP_CAUSE(env->active_tc.msacsr, - (GET_FP_CAUSE(env->active_tc.msacsr) | c)); + (GET_FP_CAUSE(env->active_tc.msacsr) | mips_exception_flags)); } else { /* Current exceptions are enabled */ if ((env->active_tc.msacsr & MSACSR_NX_MASK) == 0) { @@ -5495,11 +6286,11 @@ static inline int update_msacsr(CPUMIPSState *env, int action, int denormal) * with all enabled exceptions */ SET_FP_CAUSE(env->active_tc.msacsr, - (GET_FP_CAUSE(env->active_tc.msacsr) | c)); + (GET_FP_CAUSE(env->active_tc.msacsr) | mips_exception_flags)); } } - return c; + return mips_exception_flags; } static inline int get_enabled_exceptions(const CPUMIPSState *env, int c) diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index 9552b280e073c7b616cf6037fc36a3352da21e84..5184a1838beb1d99dd3eaeba109e97d5c526b89b 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -1574,15 +1574,34 @@ void helper_msa_st_d(CPUMIPSState *env, uint32_t wd, void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op) { #ifndef CONFIG_USER_ONLY + static const char *const type_name[] = { + "Primary Instruction", + "Primary Data or Unified Primary", + "Tertiary", + "Secondary" + }; + uint32_t cache_type = extract32(op, 0, 2); + uint32_t cache_operation = extract32(op, 2, 3); target_ulong index = addr & 0x1fffffff; - if (op == 9) { - /* Index Store Tag */ + + switch (cache_operation) { + case 0b010: /* Index Store Tag */ memory_region_dispatch_write(env->itc_tag, index, env->CP0_TagLo, MO_64, MEMTXATTRS_UNSPECIFIED); - } else if (op == 5) { - /* Index Load Tag */ + break; + case 0b001: /* Index Load Tag */ memory_region_dispatch_read(env->itc_tag, index, &env->CP0_TagLo, MO_64, MEMTXATTRS_UNSPECIFIED); + break; + case 0b000: /* Index Invalidate */ + case 0b100: /* Hit Invalidate */ + case 0b110: /* Hit Writeback */ + /* no-op */ + break; + default: + qemu_log_mask(LOG_UNIMP, "cache operation:%u (type: %s cache)\n", + cache_operation, type_name[cache_type]); + break; } #endif } diff --git a/target/mips/trace.h b/target/mips/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..f25b88ca6f9d0b0e0410e1a02c22b784b7d505db --- /dev/null +++ b/target/mips/trace.h @@ -0,0 +1 @@ +#include "trace/trace-target_mips.h" diff --git a/target/mips/translate.c b/target/mips/translate.c index 25b595a17ddcd250e7be3f758c42b2dcfda691bb..c64a1bc42e16a9b43dd231a87eea489b4dddfe4c 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -10,7 +10,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -460,6 +460,48 @@ enum { R6_OPC_SCD = 0x27 | OPC_SPECIAL3, }; +/* Loongson EXT load/store quad word opcodes */ +#define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020)) +enum { + OPC_GSLQ = 0x0020 | OPC_LWC2, + OPC_GSLQC1 = 0x8020 | OPC_LWC2, + OPC_GSSHFL = OPC_LWC2, + OPC_GSSQ = 0x0020 | OPC_SWC2, + OPC_GSSQC1 = 0x8020 | OPC_SWC2, + OPC_GSSHFS = OPC_SWC2, +}; + +/* Loongson EXT shifted load/store opcodes */ +#define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f)) +enum { + OPC_GSLWLC1 = 0x4 | OPC_GSSHFL, + OPC_GSLWRC1 = 0x5 | OPC_GSSHFL, + OPC_GSLDLC1 = 0x6 | OPC_GSSHFL, + OPC_GSLDRC1 = 0x7 | OPC_GSSHFL, + OPC_GSSWLC1 = 0x4 | OPC_GSSHFS, + OPC_GSSWRC1 = 0x5 | OPC_GSSHFS, + OPC_GSSDLC1 = 0x6 | OPC_GSSHFS, + OPC_GSSDRC1 = 0x7 | OPC_GSSHFS, +}; + +/* Loongson EXT LDC2/SDC2 opcodes */ +#define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7)) + +enum { + OPC_GSLBX = 0x0 | OPC_LDC2, + OPC_GSLHX = 0x1 | OPC_LDC2, + OPC_GSLWX = 0x2 | OPC_LDC2, + OPC_GSLDX = 0x3 | OPC_LDC2, + OPC_GSLWXC1 = 0x6 | OPC_LDC2, + OPC_GSLDXC1 = 0x7 | OPC_LDC2, + OPC_GSSBX = 0x0 | OPC_SDC2, + OPC_GSSHX = 0x1 | OPC_SDC2, + OPC_GSSWX = 0x2 | OPC_SDC2, + OPC_GSSDX = 0x3 | OPC_SDC2, + OPC_GSSWXC1 = 0x6 | OPC_SDC2, + OPC_GSSDXC1 = 0x7 | OPC_SDC2, +}; + /* BSHFL opcodes */ #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) @@ -1046,7 +1088,7 @@ enum { OPC_BC2NEZ = (0x0D << 21) | OPC_CP2, }; -#define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F)) +#define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F)) enum { OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2, @@ -3421,7 +3463,8 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, TCGv t0, t1, t2; int mem_idx = ctx->mem_idx; - if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) { + if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F | + INSN_LOONGSON3A)) { /* * Loongson CPU uses a load to zero register for prefetch. * We emulate it as a NOP. On other CPU we must perform the @@ -3717,7 +3760,7 @@ static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset, t0 = tcg_temp_new(); addr = tcg_temp_new(); - /* compare the address against that of the preceeding LL */ + /* compare the address against that of the preceding LL */ gen_base_offset_addr(ctx, addr, base, offset); tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1); tcg_temp_free(addr); @@ -5531,7 +5574,7 @@ static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt) TCGv_i64 t0, t1; TCGCond cond; - opc = MASK_LMI(ctx->opcode); + opc = MASK_LMMI(ctx->opcode); switch (opc) { case OPC_ADD_CP2: case OPC_SUB_CP2: @@ -5909,6 +5952,403 @@ no_rd: tcg_temp_free_i64(t1); } +static void gen_loongson_lswc2(DisasContext *ctx, int rt, + int rs, int rd) +{ + TCGv t0, t1, t2; + TCGv_i32 fp0; +#if defined(TARGET_MIPS64) + int lsq_rt1 = ctx->opcode & 0x1f; + int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4; +#endif + int shf_offset = sextract32(ctx->opcode, 6, 8); + + t0 = tcg_temp_new(); + + switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) { +#if defined(TARGET_MIPS64) + case OPC_GSLQ: + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, lsq_offset); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_store_gpr(t1, rt); + gen_store_gpr(t0, lsq_rt1); + tcg_temp_free(t1); + break; + case OPC_GSLQC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, lsq_offset); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_store_fpr64(ctx, t1, rt); + gen_store_fpr64(ctx, t0, lsq_rt1); + tcg_temp_free(t1); + break; + case OPC_GSSQ: + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, lsq_offset); + gen_load_gpr(t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); + gen_load_gpr(t1, lsq_rt1); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; + case OPC_GSSQC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, lsq_offset); + gen_load_fpr64(ctx, t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); + gen_load_fpr64(ctx, t1, lsq_rt1); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; +#endif + case OPC_GSSHFL: + switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) { + case OPC_GSLWLC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + t1 = tcg_temp_new(); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_andi_tl(t1, t0, 3); +#ifndef TARGET_WORDS_BIGENDIAN + tcg_gen_xori_tl(t1, t1, 3); +#endif + tcg_gen_shli_tl(t1, t1, 3); + tcg_gen_andi_tl(t0, t0, ~3); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL); + tcg_gen_shl_tl(t0, t0, t1); + t2 = tcg_const_tl(-1); + tcg_gen_shl_tl(t2, t2, t1); + fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, rt); + tcg_gen_ext_i32_tl(t1, fp0); + tcg_gen_andc_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_or_tl(t0, t0, t1); + tcg_temp_free(t1); +#if defined(TARGET_MIPS64) + tcg_gen_extrl_i64_i32(fp0, t0); +#else + tcg_gen_ext32s_tl(fp0, t0); +#endif + gen_store_fpr32(ctx, fp0, rt); + tcg_temp_free_i32(fp0); + break; + case OPC_GSLWRC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + t1 = tcg_temp_new(); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_andi_tl(t1, t0, 3); +#ifdef TARGET_WORDS_BIGENDIAN + tcg_gen_xori_tl(t1, t1, 3); +#endif + tcg_gen_shli_tl(t1, t1, 3); + tcg_gen_andi_tl(t0, t0, ~3); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL); + tcg_gen_shr_tl(t0, t0, t1); + tcg_gen_xori_tl(t1, t1, 31); + t2 = tcg_const_tl(0xfffffffeull); + tcg_gen_shl_tl(t2, t2, t1); + fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, rt); + tcg_gen_ext_i32_tl(t1, fp0); + tcg_gen_and_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_or_tl(t0, t0, t1); + tcg_temp_free(t1); +#if defined(TARGET_MIPS64) + tcg_gen_extrl_i64_i32(fp0, t0); +#else + tcg_gen_ext32s_tl(fp0, t0); +#endif + gen_store_fpr32(ctx, fp0, rt); + tcg_temp_free_i32(fp0); + break; +#if defined(TARGET_MIPS64) + case OPC_GSLDLC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + t1 = tcg_temp_new(); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_andi_tl(t1, t0, 7); +#ifndef TARGET_WORDS_BIGENDIAN + tcg_gen_xori_tl(t1, t1, 7); +#endif + tcg_gen_shli_tl(t1, t1, 3); + tcg_gen_andi_tl(t0, t0, ~7); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_shl_tl(t0, t0, t1); + t2 = tcg_const_tl(-1); + tcg_gen_shl_tl(t2, t2, t1); + gen_load_fpr64(ctx, t1, rt); + tcg_gen_andc_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_or_tl(t0, t0, t1); + tcg_temp_free(t1); + gen_store_fpr64(ctx, t0, rt); + break; + case OPC_GSLDRC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + t1 = tcg_temp_new(); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_andi_tl(t1, t0, 7); +#ifdef TARGET_WORDS_BIGENDIAN + tcg_gen_xori_tl(t1, t1, 7); +#endif + tcg_gen_shli_tl(t1, t1, 3); + tcg_gen_andi_tl(t0, t0, ~7); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_shr_tl(t0, t0, t1); + tcg_gen_xori_tl(t1, t1, 63); + t2 = tcg_const_tl(0xfffffffffffffffeull); + tcg_gen_shl_tl(t2, t2, t1); + gen_load_fpr64(ctx, t1, rt); + tcg_gen_and_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_or_tl(t0, t0, t1); + tcg_temp_free(t1); + gen_store_fpr64(ctx, t0, rt); + break; +#endif + default: + MIPS_INVAL("loongson_gsshfl"); + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case OPC_GSSHFS: + switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) { + case OPC_GSSWLC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, rt); + tcg_gen_ext_i32_tl(t1, fp0); + gen_helper_0e2i(swl, t1, t0, ctx->mem_idx); + tcg_temp_free_i32(fp0); + tcg_temp_free(t1); + break; + case OPC_GSSWRC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, rt); + tcg_gen_ext_i32_tl(t1, fp0); + gen_helper_0e2i(swr, t1, t0, ctx->mem_idx); + tcg_temp_free_i32(fp0); + tcg_temp_free(t1); + break; +#if defined(TARGET_MIPS64) + case OPC_GSSDLC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + gen_load_fpr64(ctx, t1, rt); + gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx); + tcg_temp_free(t1); + break; + case OPC_GSSDRC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + gen_load_fpr64(ctx, t1, rt); + gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx); + tcg_temp_free(t1); + break; +#endif + default: + MIPS_INVAL("loongson_gsshfs"); + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + default: + MIPS_INVAL("loongson_gslsq"); + generate_exception_end(ctx, EXCP_RI); + break; + } + tcg_temp_free(t0); +} + +/* Loongson EXT LDC2/SDC2 */ +static void gen_loongson_lsdc2(DisasContext *ctx, int rt, + int rs, int rd) +{ + int offset = sextract32(ctx->opcode, 3, 8); + uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode); + TCGv t0, t1; + TCGv_i32 fp0; + + /* Pre-conditions */ + switch (opc) { + case OPC_GSLBX: + case OPC_GSLHX: + case OPC_GSLWX: + case OPC_GSLDX: + /* prefetch, implement as NOP */ + if (rt == 0) { + return; + } + break; + case OPC_GSSBX: + case OPC_GSSHX: + case OPC_GSSWX: + case OPC_GSSDX: + break; + case OPC_GSLWXC1: +#if defined(TARGET_MIPS64) + case OPC_GSLDXC1: +#endif + check_cp1_enabled(ctx); + /* prefetch, implement as NOP */ + if (rt == 0) { + return; + } + break; + case OPC_GSSWXC1: +#if defined(TARGET_MIPS64) + case OPC_GSSDXC1: +#endif + check_cp1_enabled(ctx); + break; + default: + MIPS_INVAL("loongson_lsdc2"); + generate_exception_end(ctx, EXCP_RI); + return; + break; + } + + t0 = tcg_temp_new(); + + gen_base_offset_addr(ctx, t0, rs, offset); + gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); + + switch (opc) { + case OPC_GSLBX: + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB); + gen_store_gpr(t0, rt); + break; + case OPC_GSLHX: + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW | + ctx->default_tcg_memop_mask); + gen_store_gpr(t0, rt); + break; + case OPC_GSLWX: + gen_base_offset_addr(ctx, t0, rs, offset); + if (rd) { + gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); + } + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL | + ctx->default_tcg_memop_mask); + gen_store_gpr(t0, rt); + break; +#if defined(TARGET_MIPS64) + case OPC_GSLDX: + gen_base_offset_addr(ctx, t0, rs, offset); + if (rd) { + gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); + } + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_store_gpr(t0, rt); + break; +#endif + case OPC_GSLWXC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, offset); + if (rd) { + gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); + } + fp0 = tcg_temp_new_i32(); + tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL | + ctx->default_tcg_memop_mask); + gen_store_fpr32(ctx, fp0, rt); + tcg_temp_free_i32(fp0); + break; +#if defined(TARGET_MIPS64) + case OPC_GSLDXC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, offset); + if (rd) { + gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); + } + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_store_fpr64(ctx, t0, rt); + break; +#endif + case OPC_GSSBX: + t1 = tcg_temp_new(); + gen_load_gpr(t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB); + tcg_temp_free(t1); + break; + case OPC_GSSHX: + t1 = tcg_temp_new(); + gen_load_gpr(t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; + case OPC_GSSWX: + t1 = tcg_temp_new(); + gen_load_gpr(t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; +#if defined(TARGET_MIPS64) + case OPC_GSSDX: + t1 = tcg_temp_new(); + gen_load_gpr(t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; +#endif + case OPC_GSSWXC1: + fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, rt); + tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL | + ctx->default_tcg_memop_mask); + tcg_temp_free_i32(fp0); + break; +#if defined(TARGET_MIPS64) + case OPC_GSSDXC1: + t1 = tcg_temp_new(); + gen_load_fpr64(ctx, t1, rt); + tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; +#endif + default: + break; + } + + tcg_temp_free(t0); +} + /* Traps */ static void gen_trap(DisasContext *ctx, uint32_t opc, int rs, int rt, int16_t imm) @@ -20027,8 +20467,7 @@ static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx) static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc, int rt, int32_t imm, int32_t offset) { - TCGCond cond; - int bcond_compute = 0; + TCGCond cond = TCG_COND_ALWAYS; TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); @@ -20045,7 +20484,6 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc, /* Treat as NOP */ goto out; } else { - bcond_compute = 1; cond = TCG_COND_EQ; } break; @@ -20064,7 +20502,6 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc, tcg_gen_shri_tl(t0, t0, imm); tcg_gen_andi_tl(t0, t0, 1); tcg_gen_movi_tl(t1, 0); - bcond_compute = 1; if (opc == NM_BBEQZC) { cond = TCG_COND_EQ; } else { @@ -20079,7 +20516,6 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc, } else if (rt == 0 && imm != 0) { /* Unconditional branch */ } else { - bcond_compute = 1; cond = TCG_COND_NE; } break; @@ -20087,24 +20523,20 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc, if (rt == 0 && imm == 0) { /* Unconditional branch */ } else { - bcond_compute = 1; cond = TCG_COND_GE; } break; case NM_BLTIC: - bcond_compute = 1; cond = TCG_COND_LT; break; case NM_BGEIUC: if (rt == 0 && imm == 0) { /* Unconditional branch */ } else { - bcond_compute = 1; cond = TCG_COND_GEU; } break; case NM_BLTIUC: - bcond_compute = 1; cond = TCG_COND_LTU; break; default: @@ -20117,7 +20549,7 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc, clear_branch_hflags(ctx); ctx->base.is_jmp = DISAS_NORETURN; - if (bcond_compute == 0) { + if (cond == TCG_COND_ALWAYS) { /* Uncoditional compact branch */ gen_goto_tb(ctx, 0, ctx->btarget); } else { @@ -25604,7 +26036,7 @@ static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx) } /* return resulting half-words to its original position */ tcg_gen_shri_i32(t0, t0, 16); - /* finaly update the destination */ + /* finally update the destination */ tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); tcg_temp_free(t1); @@ -25640,7 +26072,7 @@ static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx) } /* return resulting half-words to its original position */ tcg_gen_shri_i32(t0, t0, 16); - /* finaly update the destination */ + /* finally update the destination */ tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); tcg_temp_free(t1); @@ -25709,7 +26141,7 @@ static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx) } /* return resulting byte to its original position */ tcg_gen_shri_i32(t0, t0, 8 * (3 - i)); - /* finaly update the destination */ + /* finally update the destination */ tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); } @@ -25749,7 +26181,7 @@ static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx) } /* return resulting byte to its original position */ tcg_gen_shri_i32(t0, t0, 8 * (3 - i)); - /* finaly update the destination */ + /* finally update the destination */ tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); } @@ -27161,7 +27593,7 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx) case OPC_MULTU_G_2F: case OPC_MOD_G_2F: case OPC_MODU_G_2F: - check_insn(ctx, INSN_LOONGSON2F); + check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT); gen_loongson_integer(ctx, op1, rd, rs, rt); break; case OPC_CLO: @@ -27194,7 +27626,7 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx) case OPC_DDIVU_G_2F: case OPC_DMOD_G_2F: case OPC_DMODU_G_2F: - check_insn(ctx, INSN_LOONGSON2F); + check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT); gen_loongson_integer(ctx, op1, rd, rs, rt); break; #endif @@ -29057,6 +29489,38 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx) break; } break; + case OPC_MADDV_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_maddv_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_maddv_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_maddv_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_maddv_d(cpu_env, twd, tws, twt); + break; + } + break; + case OPC_MSUBV_df: + switch (df) { + case DF_BYTE: + gen_helper_msa_msubv_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_msubv_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_msubv_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_msubv_d(cpu_env, twd, tws, twt); + break; + } + break; case OPC_ASUB_S_df: switch (df) { case DF_BYTE: @@ -29266,10 +29730,36 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx) } break; case OPC_SUBS_S_df: - gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt); + switch (df) { + case DF_BYTE: + gen_helper_msa_subs_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_subs_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_subs_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_subs_s_d(cpu_env, twd, tws, twt); + break; + } break; case OPC_MULV_df: - gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt); + switch (df) { + case DF_BYTE: + gen_helper_msa_mulv_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_mulv_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_mulv_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_mulv_d(cpu_env, twd, tws, twt); + break; + } break; case OPC_SLD_df: gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt); @@ -29278,25 +29768,71 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx) gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt); break; case OPC_SUBV_df: - gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt); + switch (df) { + case DF_BYTE: + gen_helper_msa_subv_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_subv_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_subv_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_subv_d(cpu_env, twd, tws, twt); + break; + } break; case OPC_SUBS_U_df: - gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_MADDV_df: - gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt); + switch (df) { + case DF_BYTE: + gen_helper_msa_subs_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_subs_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_subs_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_subs_u_d(cpu_env, twd, tws, twt); + break; + } break; case OPC_SPLAT_df: gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt); break; case OPC_SUBSUS_U_df: - gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt); - break; - case OPC_MSUBV_df: - gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt); + switch (df) { + case DF_BYTE: + gen_helper_msa_subsus_u_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_subsus_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_subsus_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_subsus_u_d(cpu_env, twd, tws, twt); + break; + } break; case OPC_SUBSUU_S_df: - gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt); + switch (df) { + case DF_BYTE: + gen_helper_msa_subsuu_s_b(cpu_env, twd, tws, twt); + break; + case DF_HALF: + gen_helper_msa_subsuu_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_subsuu_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_subsuu_s_d(cpu_env, twd, tws, twt); + break; + } break; case OPC_DOTP_S_df: @@ -29367,22 +29903,82 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx) } break; case OPC_DOTP_S_df: - gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt); + switch (df) { + case DF_HALF: + gen_helper_msa_dotp_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_dotp_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_dotp_s_d(cpu_env, twd, tws, twt); + break; + } break; case OPC_DOTP_U_df: - gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt); + switch (df) { + case DF_HALF: + gen_helper_msa_dotp_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_dotp_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_dotp_u_d(cpu_env, twd, tws, twt); + break; + } break; case OPC_DPADD_S_df: - gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt); + switch (df) { + case DF_HALF: + gen_helper_msa_dpadd_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_dpadd_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_dpadd_s_d(cpu_env, twd, tws, twt); + break; + } break; case OPC_DPADD_U_df: - gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt); + switch (df) { + case DF_HALF: + gen_helper_msa_dpadd_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_dpadd_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_dpadd_u_d(cpu_env, twd, tws, twt); + break; + } break; case OPC_DPSUB_S_df: - gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt); + switch (df) { + case DF_HALF: + gen_helper_msa_dpsub_s_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_dpsub_s_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_dpsub_s_d(cpu_env, twd, tws, twt); + break; + } break; case OPC_DPSUB_U_df: - gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt); + switch (df) { + case DF_HALF: + gen_helper_msa_dpsub_u_h(cpu_env, twd, tws, twt); + break; + case DF_WORD: + gen_helper_msa_dpsub_u_w(cpu_env, twd, tws, twt); + break; + case DF_DOUBLE: + gen_helper_msa_dpsub_u_d(cpu_env, twd, tws, twt); + break; + } break; } break; @@ -30617,6 +31213,8 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) /* OPC_BC, OPC_BALC */ gen_compute_compact_branch(ctx, op, 0, 0, sextract32(ctx->opcode << 2, 0, 28)); + } else if (ctx->insn_flags & ASE_LEXT) { + gen_loongson_lswc2(ctx, rt, rs, rd); } else { /* OPC_LWC2, OPC_SWC2 */ /* COP2: Not implemented. */ @@ -30634,6 +31232,8 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) /* OPC_JIC, OPC_JIALC */ gen_compute_compact_branch(ctx, op, 0, rt, imm); } + } else if (ctx->insn_flags & ASE_LEXT) { + gen_loongson_lsdc2(ctx, rt, rs, rd); } else { /* OPC_LWC2, OPC_SWC2 */ /* COP2: Not implemented. */ @@ -30641,7 +31241,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) } break; case OPC_CP2: - check_insn(ctx, INSN_LOONGSON2F); + check_insn(ctx, ASE_LMMI); /* Note that these instructions use different fields. */ gen_loongson_multimedia(ctx, sa, rd, rt); break; @@ -30842,8 +31442,8 @@ static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) #else ctx->mem_idx = hflags_mmu_index(ctx->hflags); #endif - ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ? - MO_UNALN : MO_ALIGN; + ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS32R6 | ISA_MIPS64R6 | + INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN; LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx, ctx->hflags); @@ -31157,7 +31757,7 @@ void mips_tcg_init(void) #endif } -#include "translate_init.inc.c" +#include "translate_init.c.inc" void cpu_mips_realize_env(CPUMIPSState *env) { @@ -31206,7 +31806,9 @@ void cpu_state_reset(CPUMIPSState *env) env->CP0_Config5 = env->cpu_model->CP0_Config5; env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask; env->CP0_Config6 = env->cpu_model->CP0_Config6; + env->CP0_Config6_rw_bitmask = env->cpu_model->CP0_Config6_rw_bitmask; env->CP0_Config7 = env->cpu_model->CP0_Config7; + env->CP0_Config7_rw_bitmask = env->cpu_model->CP0_Config7_rw_bitmask; env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask << env->cpu_model->CP0_LLAddr_shift; env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift; diff --git a/target/mips/translate_init.inc.c b/target/mips/translate_init.c.inc similarity index 88% rename from target/mips/translate_init.inc.c rename to target/mips/translate_init.c.inc index 6d145a905a4b422ff6a29531909cd86d62745e02..ea85d5c6a7997bcbeb8377e359dc1b3f7304e6db 100644 --- a/target/mips/translate_init.inc.c +++ b/target/mips/translate_init.c.inc @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -254,7 +254,7 @@ const mips_def_t mips_defs[] = .CP0_PRid = 0x00019500, .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (MMU_TYPE_R4000 << CP0C0_MT), - .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) | + .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) | (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | (1 << CP0C1_CA), @@ -366,7 +366,7 @@ const mips_def_t mips_defs[] = }, { /* FIXME: - * Config3: CMGCR, PW, VZ, CTXTC, CDMM, TL + * Config3: VZ, CTXTC, CDMM, TL * Config4: MMUExtDef * Config5: MRP * FIR(FCR0): Has2008 @@ -380,10 +380,11 @@ const mips_def_t mips_defs[] = (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) | (1 << CP0C1_PC) | (1 << CP0C1_FP), .CP0_Config2 = MIPS_CONFIG2, - .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) | + .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | + (1 << CP0C3_CMGCR) | (1 << CP0C3_MSAP) | (1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_SC) | - (1 << CP0C3_ULRI) | (1 << CP0C3_RXI) | (1 << CP0C3_LPA) | - (1 << CP0C3_VInt), + (1 << CP0C3_PW) | (1 << CP0C3_ULRI) | (1 << CP0C3_RXI) | + (1 << CP0C3_LPA) | (1 << CP0C3_VInt), .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (2 << CP0C4_IE) | (0x1c << CP0C4_KScrExist), .CP0_Config4_rw_bitmask = 0, @@ -801,6 +802,92 @@ const mips_def_t mips_defs[] = .insn_flags = CPU_LOONGSON2F, .mmu_type = MMU_TYPE_R4000, }, + { + .name = "Loongson-3A1000", + .CP0_PRid = 0x6305, + /* 64KB I-cache and d-cache. 4 way with 32 bit cache line size. */ + .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) | + (MMU_TYPE_R4000 << CP0C0_MT), + .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) | + (3 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) | + (3 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) | + (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP), + .CP0_Config2 = MIPS_CONFIG2 | (7 << CP0C2_SS) | (4 << CP0C2_SL) | + (3 << CP0C2_SA), + .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_LPA), + .CP0_LLAddr_rw_bitmask = 0, + .SYNCI_Step = 32, + .CCRes = 2, + .CP0_Status_rw_bitmask = 0x74D8FFFF, + .CP0_PageGrain = (1 << CP0PG_ELPA), + .CP0_PageGrain_rw_bitmask = (1 << CP0PG_ELPA), + .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV) | (0x1 << FCR0_F64) | + (0x1 << FCR0_PS) | (0x1 << FCR0_L) | (0x1 << FCR0_W) | + (0x1 << FCR0_D) | (0x1 << FCR0_S), + .CP1_fcr31 = 0, + .CP1_fcr31_rw_bitmask = 0xFF83FFFF, + .SEGBITS = 42, + .PABITS = 48, + .insn_flags = CPU_LOONGSON3A, + .mmu_type = MMU_TYPE_R4000, + }, + { + .name = "Loongson-3A4000", + .CP0_PRid = 0x14C000, + /* 64KB I-cache and d-cache. 4 way with 32 bit cache line size. */ + .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) | + (MMU_TYPE_R4000 << CP0C0_MT), + .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) | + (2 << CP0C1_IS) | (5 << CP0C1_IL) | (3 << CP0C1_IA) | + (2 << CP0C1_DS) | (5 << CP0C1_DL) | (3 << CP0C1_DA) | + (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP), + .CP0_Config2 = MIPS_CONFIG2 | (5 << CP0C2_SS) | (5 << CP0C2_SL) | + (15 << CP0C2_SA), + .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) | + (1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) | + (1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt), + .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (2 << CP0C4_IE) | + (1 << CP0C4_AE) | (0x1c << CP0C4_KScrExist), + .CP0_Config4_rw_bitmask = 0, + .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_CRCP) | (1 << CP0C5_NFExists), + .CP0_Config5_rw_bitmask = (1 << CP0C5_K) | (1 << CP0C5_CV) | + (1 << CP0C5_MSAEn) | (1 << CP0C5_UFE) | + (1 << CP0C5_FRE) | (1 << CP0C5_SBRI), + .CP0_Config6 = (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) | + (1 << CP0C6_SFBEN) | (1 << CP0C6_VLTINT) | + (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF), + .CP0_Config6_rw_bitmask = (1 << CP0C6_BPPASS) | (0x3f << CP0C6_KPOS) | + (1 << CP0C6_KE) | (1 << CP0C6_VTLBONLY) | + (1 << CP0C6_LASX) | (1 << CP0C6_SSEN) | + (1 << CP0C6_DISDRTIME) | (1 << CP0C6_PIXNUEN) | + (1 << CP0C6_SCRAND) | (1 << CP0C6_LLEXCEN) | + (1 << CP0C6_DISVC) | (1 << CP0C6_VCLRU) | + (1 << CP0C6_DCLRU) | (1 << CP0C6_PIXUEN) | + (1 << CP0C6_DISBLKLYEN) | (1 << CP0C6_UMEMUALEN) | + (1 << CP0C6_SFBEN) | (1 << CP0C6_FLTINT) | + (1 << CP0C6_VLTINT) | (1 << CP0C6_DISBTB) | + (3 << CP0C6_STPREFCTL) | (1 << CP0C6_INSTPREF) | + (1 << CP0C6_DATAPREF), + .CP0_Config7 = 0, + .CP0_Config7_rw_bitmask = (1 << CP0C7_NAPCGEN) | (1 << CP0C7_UNIMUEN) | + (1 << CP0C7_VFPUCGEN), + .CP0_LLAddr_rw_bitmask = 1, + .SYNCI_Step = 16, + .CCRes = 2, + .CP0_Status_rw_bitmask = 0x7DDBFFFF, + .CP0_PageGrain = (1 << CP0PG_ELPA), + .CP0_PageGrain_rw_bitmask = (1U << CP0PG_RIE) | (1 << CP0PG_XIE) | + (1 << CP0PG_ELPA) | (1 << CP0PG_IEC), + .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV) | (0x1 << FCR0_F64) | + (0x1 << FCR0_PS) | (0x1 << FCR0_L) | (0x1 << FCR0_W) | + (0x1 << FCR0_D) | (0x1 << FCR0_S), + .CP1_fcr31 = 0, + .CP1_fcr31_rw_bitmask = 0xFF83FFFF, + .SEGBITS = 48, + .PABITS = 48, + .insn_flags = CPU_LOONGSON3A, + .mmu_type = MMU_TYPE_R4000, + }, { /* A generic CPU providing MIPS64 DSP R2 ASE features. FIXME: Eventually this should be replaced by a real CPU model. */ @@ -908,7 +995,7 @@ static void mvp_init (CPUMIPSState *env, const mips_def_t *def) /* MVPConf1 implemented, TLB sharable, no gating storage support, programmable cache partitioning implemented, number of allocatable - and sharable TLB entries, MVP has allocatable TCs, 2 VPEs + and shareable TLB entries, MVP has allocatable TCs, 2 VPEs implemented, 5 TCs implemented. */ env->mvp->CP0_MVPConf0 = (1U << CP0MVPC0_M) | (1 << CP0MVPC0_TLBS) | (0 << CP0MVPC0_GS) | (1 << CP0MVPC0_PCP) | diff --git a/target/moxie/Makefile.objs b/target/moxie/Makefile.objs deleted file mode 100644 index 6381d4d636f9b2119e1bc8bc75ff3d1e902e6431..0000000000000000000000000000000000000000 --- a/target/moxie/Makefile.objs +++ /dev/null @@ -1,2 +0,0 @@ -obj-y += translate.o helper.o machine.o cpu.o machine.o -obj-$(CONFIG_SOFTMMU) += mmu.o diff --git a/target/moxie/cpu.h b/target/moxie/cpu.h index 455553b794a41c7c24fd13e528620b847d06bdcd..bd6ab66084d186fa7081023eedff5e107ff74981 100644 --- a/target/moxie/cpu.h +++ b/target/moxie/cpu.h @@ -21,6 +21,7 @@ #define MOXIE_CPU_H #include "exec/cpu-defs.h" +#include "qom/object.h" #define MOXIE_EX_DIV0 0 #define MOXIE_EX_BAD 1 @@ -50,12 +51,8 @@ typedef struct CPUMoxieState { #define TYPE_MOXIE_CPU "moxie-cpu" -#define MOXIE_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(MoxieCPUClass, (klass), TYPE_MOXIE_CPU) -#define MOXIE_CPU(obj) \ - OBJECT_CHECK(MoxieCPU, (obj), TYPE_MOXIE_CPU) -#define MOXIE_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(MoxieCPUClass, (obj), TYPE_MOXIE_CPU) +OBJECT_DECLARE_TYPE(MoxieCPU, MoxieCPUClass, + MOXIE_CPU) /** * MoxieCPUClass: @@ -63,14 +60,14 @@ typedef struct CPUMoxieState { * * A Moxie CPU model. */ -typedef struct MoxieCPUClass { +struct MoxieCPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ DeviceRealize parent_realize; DeviceReset parent_reset; -} MoxieCPUClass; +}; /** * MoxieCPU: @@ -78,14 +75,14 @@ typedef struct MoxieCPUClass { * * A Moxie CPU. */ -typedef struct MoxieCPU { +struct MoxieCPU { /*< private >*/ CPUState parent_obj; /*< public >*/ CPUNegativeOffsetState neg; CPUMoxieState env; -} MoxieCPU; +}; void moxie_cpu_do_interrupt(CPUState *cs); diff --git a/target/moxie/meson.build b/target/moxie/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..b4beb528ccaea2df2057f96c77f93ecd05f8a6de --- /dev/null +++ b/target/moxie/meson.build @@ -0,0 +1,14 @@ +moxie_ss = ss.source_set() +moxie_ss.add(files( + 'cpu.c', + 'helper.c', + 'machine.c', + 'machine.c', + 'translate.c', +)) + +moxie_softmmu_ss = ss.source_set() +moxie_softmmu_ss.add(files('mmu.c')) + +target_arch += {'moxie': moxie_ss} +target_softmmu_arch += {'moxie': moxie_softmmu_ss} diff --git a/target/nios2/Makefile.objs b/target/nios2/Makefile.objs deleted file mode 100644 index 010de0e7a6fb79cee981a1ad3b8717f399bb141a..0000000000000000000000000000000000000000 --- a/target/nios2/Makefile.objs +++ /dev/null @@ -1,4 +0,0 @@ -obj-y += translate.o op_helper.o helper.o cpu.o mmu.o nios2-semi.o -obj-$(CONFIG_SOFTMMU) += monitor.o - -$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h index 4dddf9c3a108f99fd20b7e99d88fe6fe3c152e0c..86bbe1d8670fe9a7c4e616db83eead98179f7fbd 100644 --- a/target/nios2/cpu.h +++ b/target/nios2/cpu.h @@ -23,6 +23,7 @@ #include "exec/cpu-defs.h" #include "hw/core/cpu.h" +#include "qom/object.h" typedef struct CPUNios2State CPUNios2State; #if !defined(CONFIG_USER_ONLY) @@ -31,12 +32,8 @@ typedef struct CPUNios2State CPUNios2State; #define TYPE_NIOS2_CPU "nios2-cpu" -#define NIOS2_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(Nios2CPUClass, (klass), TYPE_NIOS2_CPU) -#define NIOS2_CPU(obj) \ - OBJECT_CHECK(Nios2CPU, (obj), TYPE_NIOS2_CPU) -#define NIOS2_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(Nios2CPUClass, (obj), TYPE_NIOS2_CPU) +OBJECT_DECLARE_TYPE(Nios2CPU, Nios2CPUClass, + NIOS2_CPU) /** * Nios2CPUClass: @@ -44,14 +41,14 @@ typedef struct CPUNios2State CPUNios2State; * * A Nios2 CPU model. */ -typedef struct Nios2CPUClass { +struct Nios2CPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ DeviceRealize parent_realize; DeviceReset parent_reset; -} Nios2CPUClass; +}; #define TARGET_HAS_ICE 1 @@ -174,7 +171,7 @@ struct CPUNios2State { * * A Nios2 CPU. */ -typedef struct Nios2CPU { +struct Nios2CPU { /*< private >*/ CPUState parent_obj; /*< public >*/ @@ -191,7 +188,7 @@ typedef struct Nios2CPU { uint32_t reset_addr; uint32_t exception_addr; uint32_t fast_tlb_miss_addr; -} Nios2CPU; +}; void nios2_tcg_init(void); diff --git a/target/nios2/meson.build b/target/nios2/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..e643917db1a56b0c948091a1c3f420f0c49cdbe2 --- /dev/null +++ b/target/nios2/meson.build @@ -0,0 +1,15 @@ +nios2_ss = ss.source_set() +nios2_ss.add(files( + 'cpu.c', + 'helper.c', + 'mmu.c', + 'nios2-semi.c', + 'op_helper.c', + 'translate.c', +)) + +nios2_softmmu_ss = ss.source_set() +nios2_softmmu_ss.add(files('monitor.c')) + +target_arch += {'nios2': nios2_ss} +target_softmmu_arch += {'nios2': nios2_softmmu_ss} diff --git a/target/nios2/monitor.c b/target/nios2/monitor.c index 6646836df58c032cf8852e6050d7b98e88c61d04..0152dec3fab1d1d79662bbb74207881e29f63ccc 100644 --- a/target/nios2/monitor.c +++ b/target/nios2/monitor.c @@ -29,7 +29,7 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict) { - CPUArchState *env1 = mon_get_cpu_env(); + CPUArchState *env1 = mon_get_cpu_env(mon); dump_mmu(env1); } diff --git a/target/nios2/translate.c b/target/nios2/translate.c index 6c34cd31937650b190a7074a3f3a0ca06d802dbc..9824544eb37c9a94d18081a566d14c0bf4ce8bda 100644 --- a/target/nios2/translate.c +++ b/target/nios2/translate.c @@ -32,6 +32,7 @@ #include "exec/cpu_ldst.h" #include "exec/translator.h" #include "qemu/qemu-print.h" +#include "exec/gen-icount.h" /* is_jmp field values */ #define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */ @@ -149,7 +150,7 @@ static void t_gen_helper_raise_exception(DisasContext *dc, tcg_gen_movi_tl(dc->cpu_R[R_PC], dc->pc); gen_helper_raise_exception(dc->cpu_env, tmp); tcg_temp_free_i32(tmp); - dc->is_jmp = DISAS_UPDATE; + dc->is_jmp = DISAS_NORETURN; } static bool use_goto_tb(DisasContext *dc, uint32_t dest) @@ -518,7 +519,11 @@ static void wrctl(DisasContext *dc, uint32_t code, uint32_t flags) /* If interrupts were enabled using WRCTL, trigger them. */ #if !defined(CONFIG_USER_ONLY) if ((instr.imm5 + CR_BASE) == CR_STATUS) { + if (tb_cflags(dc->tb) & CF_USE_ICOUNT) { + gen_io_start(); + } gen_helper_check_interrupts(dc->cpu_env); + dc->is_jmp = DISAS_UPDATE; } #endif } @@ -802,7 +807,7 @@ static void gen_exception(DisasContext *dc, uint32_t excp) tcg_gen_movi_tl(cpu_R[R_PC], dc->pc); gen_helper_raise_exception(cpu_env, tmp); tcg_temp_free_i32(tmp); - dc->is_jmp = DISAS_UPDATE; + dc->is_jmp = DISAS_NORETURN; } /* generate intermediate code for basic block 'tb'. */ @@ -865,6 +870,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) /* Indicate where the next block should start */ switch (dc->is_jmp) { case DISAS_NEXT: + case DISAS_UPDATE: /* Save the current PC back into the CPU register */ tcg_gen_movi_tl(cpu_R[R_PC], dc->pc); tcg_gen_exit_tb(NULL, 0); @@ -872,11 +878,11 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) default: case DISAS_JUMP: - case DISAS_UPDATE: /* The jump will already have updated the PC register */ tcg_gen_exit_tb(NULL, 0); break; + case DISAS_NORETURN: case DISAS_TB_JUMP: /* nothing more to generate */ break; diff --git a/target/openrisc/Makefile.objs b/target/openrisc/Makefile.objs deleted file mode 100644 index b5432f46843ee40f1f66693a09416b9c0a7a4b88..0000000000000000000000000000000000000000 --- a/target/openrisc/Makefile.objs +++ /dev/null @@ -1,15 +0,0 @@ -obj-$(CONFIG_SOFTMMU) += machine.o -obj-y += cpu.o exception.o interrupt.o mmu.o translate.o disas.o -obj-y += exception_helper.o fpu_helper.o \ - interrupt_helper.o sys_helper.o -obj-y += gdbstub.o - -DECODETREE = $(SRC_PATH)/scripts/decodetree.py - -target/openrisc/decode.inc.c: \ - $(SRC_PATH)/target/openrisc/insns.decode $(DECODETREE) - $(call quiet-command,\ - $(PYTHON) $(DECODETREE) -o $@ $<, "GEN", $(TARGET_DIR)$@) - -target/openrisc/translate.o: target/openrisc/decode.inc.c -target/openrisc/disas.o: target/openrisc/decode.inc.c diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index f37a52e1530535b05033513bd74c38574d62033c..bd42faf144f854d823211df409523c8eac91f076 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -22,18 +22,15 @@ #include "exec/cpu-defs.h" #include "hw/core/cpu.h" +#include "qom/object.h" /* cpu_openrisc_map_address_* in CPUOpenRISCTLBContext need this decl. */ struct OpenRISCCPU; #define TYPE_OPENRISC_CPU "or1k-cpu" -#define OPENRISC_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(OpenRISCCPUClass, (klass), TYPE_OPENRISC_CPU) -#define OPENRISC_CPU(obj) \ - OBJECT_CHECK(OpenRISCCPU, (obj), TYPE_OPENRISC_CPU) -#define OPENRISC_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(OpenRISCCPUClass, (obj), TYPE_OPENRISC_CPU) +OBJECT_DECLARE_TYPE(OpenRISCCPU, OpenRISCCPUClass, + OPENRISC_CPU) /** * OpenRISCCPUClass: @@ -42,14 +39,14 @@ struct OpenRISCCPU; * * A OpenRISC CPU model. */ -typedef struct OpenRISCCPUClass { +struct OpenRISCCPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ DeviceRealize parent_realize; DeviceReset parent_reset; -} OpenRISCCPUClass; +}; #define TARGET_INSN_START_EXTRA_WORDS 1 @@ -305,14 +302,14 @@ typedef struct CPUOpenRISCState { * * A OpenRISC CPU. */ -typedef struct OpenRISCCPU { +struct OpenRISCCPU { /*< private >*/ CPUState parent_obj; /*< public >*/ CPUNegativeOffsetState neg; CPUOpenRISCState env; -} OpenRISCCPU; +}; void cpu_openrisc_list(void); diff --git a/target/openrisc/disas.c b/target/openrisc/disas.c index ce112640b95c8f00872f2c88bcbbb9d8539f5095..dc025bd64d57bfdaccf45d3e12f7500bbb5c6a31 100644 --- a/target/openrisc/disas.c +++ b/target/openrisc/disas.c @@ -25,7 +25,7 @@ typedef disassemble_info DisasContext; /* Include the auto-generated decoder. */ -#include "decode.inc.c" +#include "decode-insns.c.inc" #define output(mnemonic, format, ...) \ (info->fprintf_func(info->stream, "%-9s " format, \ diff --git a/target/openrisc/meson.build b/target/openrisc/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..9774a583065cc551928b39d9b3d1c8325138fd02 --- /dev/null +++ b/target/openrisc/meson.build @@ -0,0 +1,23 @@ +gen = decodetree.process('insns.decode') + +openrisc_ss = ss.source_set() +openrisc_ss.add(gen) +openrisc_ss.add(files( + 'cpu.c', + 'disas.c', + 'exception.c', + 'exception_helper.c', + 'fpu_helper.c', + 'gdbstub.c', + 'interrupt.c', + 'interrupt_helper.c', + 'mmu.c', + 'sys_helper.c', + 'translate.c', +)) + +openrisc_softmmu_ss = ss.source_set() +openrisc_softmmu_ss.add(files('machine.c')) + +target_arch += {'openrisc': openrisc_ss} +target_softmmu_arch += {'openrisc': openrisc_softmmu_ss} diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index d9fe6c594893399fc0d22bc1d30d6d2a3d18b991..41390d046f64d9099bb4fcaa123cef7debb8d2f8 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -176,9 +176,6 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) case TO_SPR(10, 1): /* TTCR */ cpu_openrisc_count_set(cpu, rb); - if (env->ttmr & TIMER_NONE) { - return; - } cpu_openrisc_timer_update(cpu); break; #endif diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 52323a16df4efde063f68048ba2a9a2a10ce5430..c6dce879f14db3d9ee6a6dccd41786604700839c 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -65,7 +65,7 @@ static inline bool is_user(DisasContext *dc) } /* Include the auto-generated decoder. */ -#include "decode.inc.c" +#include "decode-insns.c.inc" static TCGv cpu_sr; static TCGv cpu_regs[32]; diff --git a/target/ppc/Makefile.objs b/target/ppc/Makefile.objs deleted file mode 100644 index e8fa18ce13d118650380283e6abab27dbe6bfcda..0000000000000000000000000000000000000000 --- a/target/ppc/Makefile.objs +++ /dev/null @@ -1,20 +0,0 @@ -obj-y += cpu-models.o -obj-y += cpu.o -obj-y += translate.o -ifeq ($(CONFIG_SOFTMMU),y) -obj-y += machine.o mmu_helper.o mmu-hash32.o monitor.o arch_dump.o -obj-$(TARGET_PPC64) += mmu-hash64.o mmu-book3s-v3.o compat.o -obj-$(TARGET_PPC64) += mmu-radix64.o -endif -obj-$(CONFIG_KVM) += kvm.o -obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o -obj-y += dfp_helper.o -obj-y += excp_helper.o -obj-y += fpu_helper.o -obj-y += int_helper.o -obj-y += timebase_helper.o -obj-y += misc_helper.o -obj-y += mem_helper.o -obj-y += ../../libdecnumber/ -obj-$(CONFIG_USER_ONLY) += user_only_helper.o -obj-y += gdbstub.o diff --git a/target/ppc/compat.c b/target/ppc/compat.c index fda0dfe8f8bfc65273cafc0ee48fdefec072d4fa..7949a24f5a156bdb54133be1f2b96eafd117d91a 100644 --- a/target/ppc/compat.c +++ b/target/ppc/compat.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -158,7 +158,7 @@ bool ppc_type_check_compat(const char *cputype, uint32_t compat_pvr, return pcc_compat(pcc, compat_pvr, min_compat_pvr, max_compat_pvr); } -void ppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr, Error **errp) +int ppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr, Error **errp) { const CompatInfo *compat = compat_by_pvr(compat_pvr); CPUPPCState *env = &cpu->env; @@ -169,11 +169,11 @@ void ppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr, Error **errp) pcr = 0; } else if (!compat) { error_setg(errp, "Unknown compatibility PVR 0x%08"PRIx32, compat_pvr); - return; + return -EINVAL; } else if (!ppc_check_compat(cpu, compat_pvr, 0, 0)) { error_setg(errp, "Compatibility PVR 0x%08"PRIx32" not valid for CPU", compat_pvr); - return; + return -EINVAL; } else { pcr = compat->pcr; } @@ -185,17 +185,19 @@ void ppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr, Error **errp) if (ret < 0) { error_setg_errno(errp, -ret, "Unable to set CPU compatibility mode in KVM"); - return; + return ret; } } cpu->compat_pvr = compat_pvr; env->spr[SPR_PCR] = pcr & pcc->pcr_mask; + return 0; } typedef struct { uint32_t compat_pvr; - Error *err; + Error **errp; + int ret; } SetCompatState; static void do_set_compat(CPUState *cs, run_on_cpu_data arg) @@ -203,26 +205,28 @@ static void do_set_compat(CPUState *cs, run_on_cpu_data arg) PowerPCCPU *cpu = POWERPC_CPU(cs); SetCompatState *s = arg.host_ptr; - ppc_set_compat(cpu, s->compat_pvr, &s->err); + s->ret = ppc_set_compat(cpu, s->compat_pvr, s->errp); } -void ppc_set_compat_all(uint32_t compat_pvr, Error **errp) +int ppc_set_compat_all(uint32_t compat_pvr, Error **errp) { CPUState *cs; CPU_FOREACH(cs) { SetCompatState s = { .compat_pvr = compat_pvr, - .err = NULL, + .errp = errp, + .ret = 0, }; run_on_cpu(cs, do_set_compat, RUN_ON_CPU_HOST_PTR(&s)); - if (s.err) { - error_propagate(errp, s.err); - return; + if (s.ret < 0) { + return s.ret; } } + + return 0; } int ppc_compat_max_vthreads(PowerPCCPU *cpu) @@ -260,13 +264,10 @@ static void ppc_compat_prop_get(Object *obj, Visitor *v, const char *name, static void ppc_compat_prop_set(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - Error *local_err = NULL; char *value; uint32_t compat_pvr; - visit_type_str(v, name, &value, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_str(v, name, &value, errp)) { return; } diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c index 4ad16863c0ceea12e9022620912850e988f98924..87e4228614b0b70aa8922b3f1e3a811512a4d49d 100644 --- a/target/ppc/cpu-models.c +++ b/target/ppc/cpu-models.c @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h index ce750b2d55d2885bf988093eb9933877de7b3cc1..fc5e21728d7e91905d92b545eff3793f8a3b354b 100644 --- a/target/ppc/cpu-models.h +++ b/target/ppc/cpu-models.h @@ -8,7 +8,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h index 000c7d405b70abf4353b6a1b7625a271e8845c6e..5fdb96f04df5784c4ee72a7d28644a0e0d35f93b 100644 --- a/target/ppc/cpu-qom.h +++ b/target/ppc/cpu-qom.h @@ -21,6 +21,7 @@ #define QEMU_PPC_CPU_QOM_H #include "hw/core/cpu.h" +#include "qom/object.h" #ifdef TARGET_PPC64 #define TYPE_POWERPC_CPU "powerpc64-cpu" @@ -28,14 +29,9 @@ #define TYPE_POWERPC_CPU "powerpc-cpu" #endif -#define POWERPC_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(PowerPCCPUClass, (klass), TYPE_POWERPC_CPU) -#define POWERPC_CPU(obj) \ - OBJECT_CHECK(PowerPCCPU, (obj), TYPE_POWERPC_CPU) -#define POWERPC_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PowerPCCPUClass, (obj), TYPE_POWERPC_CPU) +OBJECT_DECLARE_TYPE(PowerPCCPU, PowerPCCPUClass, + POWERPC_CPU) -typedef struct PowerPCCPU PowerPCCPU; typedef struct CPUPPCState CPUPPCState; typedef struct ppc_tb_t ppc_tb_t; typedef struct ppc_dcr_t ppc_dcr_t; @@ -159,7 +155,7 @@ typedef struct PPCHash64Options PPCHash64Options; * * A PowerPC CPU model. */ -typedef struct PowerPCCPUClass { +struct PowerPCCPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ @@ -197,7 +193,7 @@ typedef struct PowerPCCPUClass { int (*check_pow)(CPUPPCState *env); int (*handle_mmu_fault)(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx); bool (*interrupts_big_endian)(PowerPCCPU *cpu); -} PowerPCCPUClass; +}; #ifndef CONFIG_USER_ONLY typedef struct PPCTimebase { diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c index 28011668e7b1b29ccbf9c3175ed15abccb5d7ac8..e501a7ff6f49b566896272ba5c46fc1884a33896 100644 --- a/target/ppc/cpu.c +++ b/target/ppc/cpu.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 7db7882f5292c02dd05be77c876f0cabd59a590e..2609e4082ed841a65a8ddba586ec35a10a3312bd 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -23,6 +23,7 @@ #include "qemu/int128.h" #include "exec/cpu-defs.h" #include "cpu-qom.h" +#include "qom/object.h" #define TCG_GUEST_DEFAULT_MO 0 @@ -127,8 +128,9 @@ enum { POWERPC_EXCP_SDOOR_HV = 100, /* ISA 3.00 additions */ POWERPC_EXCP_HVIRT = 101, + POWERPC_EXCP_SYSCALL_VECTORED = 102, /* scv exception */ /* EOL */ - POWERPC_EXCP_NB = 102, + POWERPC_EXCP_NB = 103, /* QEMU exceptions: used internally during code translation */ POWERPC_EXCP_STOP = 0x200, /* stop translation */ POWERPC_EXCP_BRANCH = 0x201, /* branch instruction */ @@ -475,9 +477,31 @@ typedef struct ppc_v3_pate_t { #define SRR1_PROTFAULT DSISR_PROTFAULT #define SRR1_IAMR DSISR_AMR +/* SRR1[42:45] wakeup fields for System Reset Interrupt */ + +#define SRR1_WAKEMASK 0x003c0000 /* reason for wakeup */ + +#define SRR1_WAKEHMI 0x00280000 /* Hypervisor maintenance */ +#define SRR1_WAKEHVI 0x00240000 /* Hypervisor Virt. Interrupt (P9) */ +#define SRR1_WAKEEE 0x00200000 /* External interrupt */ +#define SRR1_WAKEDEC 0x00180000 /* Decrementer interrupt */ +#define SRR1_WAKEDBELL 0x00140000 /* Privileged doorbell */ +#define SRR1_WAKERESET 0x00100000 /* System reset */ +#define SRR1_WAKEHDBELL 0x000c0000 /* Hypervisor doorbell */ +#define SRR1_WAKESCOM 0x00080000 /* SCOM not in power-saving mode */ + +/* SRR1[46:47] power-saving exit mode */ + +#define SRR1_WAKESTATE 0x00030000 /* Powersave exit mask */ + +#define SRR1_WS_HVLOSS 0x00030000 /* HV resources not maintained */ +#define SRR1_WS_GPRLOSS 0x00020000 /* GPRs not maintained */ +#define SRR1_WS_NOLOSS 0x00010000 /* All resources maintained */ + /* Facility Status and Control (FSCR) bits */ #define FSCR_EBB (63 - 56) /* Event-Based Branch Facility */ #define FSCR_TAR (63 - 55) /* Target Address Register */ +#define FSCR_SCV (63 - 51) /* System call vectored */ /* Interrupt cause mask and position in FSCR. HFSCR has the same format */ #define FSCR_IC_MASK (0xFFULL) #define FSCR_IC_POS (63 - 7) @@ -487,6 +511,7 @@ typedef struct ppc_v3_pate_t { #define FSCR_IC_TM 5 #define FSCR_IC_EBB 7 #define FSCR_IC_TAR 8 +#define FSCR_IC_SCV 12 /* Exception state register bits definition */ #define ESR_PIL PPC_BIT(36) /* Illegal Instruction */ @@ -554,6 +579,8 @@ enum { POWERPC_FLAG_VSX = 0x00080000, /* Has Transaction Memory (ISA 2.07) */ POWERPC_FLAG_TM = 0x00100000, + /* Has SCV (ISA 3.00) */ + POWERPC_FLAG_SCV = 0x00200000, }; /*****************************************************************************/ @@ -588,7 +615,7 @@ enum { #define FPSCR_VXCVI 8 /* Floating-point invalid operation exception (int) */ #define FPSCR_VE 7 /* Floating-point invalid operation exception enable */ #define FPSCR_OE 6 /* Floating-point overflow exception enable */ -#define FPSCR_UE 5 /* Floating-point undeflow exception enable */ +#define FPSCR_UE 5 /* Floating-point underflow exception enable */ #define FPSCR_ZE 4 /* Floating-point zero divide exception enable */ #define FPSCR_XE 3 /* Floating-point inexact exception enable */ #define FPSCR_NI 2 /* Floating-point non-IEEE mode */ @@ -1176,6 +1203,7 @@ PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr); PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t pvr); PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc); +#ifndef CONFIG_USER_ONLY struct PPCVirtualHypervisorClass { InterfaceClass parent; void (*hypercall)(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu); @@ -1189,21 +1217,14 @@ struct PPCVirtualHypervisorClass { void (*hpte_set_r)(PPCVirtualHypervisor *vhyp, hwaddr ptex, uint64_t pte1); void (*get_pate)(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry); target_ulong (*encode_hpt_for_kvm_pr)(PPCVirtualHypervisor *vhyp); -#ifndef CONFIG_USER_ONLY void (*cpu_exec_enter)(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu); void (*cpu_exec_exit)(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu); -#endif }; #define TYPE_PPC_VIRTUAL_HYPERVISOR "ppc-virtual-hypervisor" -#define PPC_VIRTUAL_HYPERVISOR(obj) \ - OBJECT_CHECK(PPCVirtualHypervisor, (obj), TYPE_PPC_VIRTUAL_HYPERVISOR) -#define PPC_VIRTUAL_HYPERVISOR_CLASS(klass) \ - OBJECT_CLASS_CHECK(PPCVirtualHypervisorClass, (klass), \ - TYPE_PPC_VIRTUAL_HYPERVISOR) -#define PPC_VIRTUAL_HYPERVISOR_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PPCVirtualHypervisorClass, (obj), \ - TYPE_PPC_VIRTUAL_HYPERVISOR) +DECLARE_OBJ_CHECKERS(PPCVirtualHypervisor, PPCVirtualHypervisorClass, + PPC_VIRTUAL_HYPERVISOR, TYPE_PPC_VIRTUAL_HYPERVISOR) +#endif /* CONFIG_USER_ONLY */ void ppc_cpu_do_interrupt(CPUState *cpu); bool ppc_cpu_exec_interrupt(CPUState *cpu, int int_req); @@ -1331,10 +1352,10 @@ bool ppc_check_compat(PowerPCCPU *cpu, uint32_t compat_pvr, bool ppc_type_check_compat(const char *cputype, uint32_t compat_pvr, uint32_t min_compat_pvr, uint32_t max_compat_pvr); -void ppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr, Error **errp); +int ppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr, Error **errp); #if !defined(CONFIG_USER_ONLY) -void ppc_set_compat_all(uint32_t compat_pvr, Error **errp); +int ppc_set_compat_all(uint32_t compat_pvr, Error **errp); #endif int ppc_compat_max_vthreads(PowerPCCPU *cpu); void ppc_compat_add_property(Object *obj, const char *name, @@ -2165,6 +2186,8 @@ enum { PPC2_PM_ISA206 = 0x0000000000040000ULL, /* POWER ISA 3.0 */ PPC2_ISA300 = 0x0000000000080000ULL, + /* POWER ISA 3.1 */ + PPC2_ISA310 = 0x0000000000100000ULL, #define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_VSX | PPC2_PRCNTL | PPC2_DBRX | \ PPC2_ISA205 | PPC2_VSX207 | PPC2_PERM_ISA206 | \ @@ -2173,7 +2196,7 @@ enum { PPC2_BCTAR_ISA207 | PPC2_LSQ_ISA207 | \ PPC2_ALTIVEC_207 | PPC2_ISA207S | PPC2_DFP | \ PPC2_FP_CVT_S64 | PPC2_TM | PPC2_PM_ISA206 | \ - PPC2_ISA300) + PPC2_ISA300 | PPC2_ISA310) }; /*****************************************************************************/ @@ -2308,13 +2331,13 @@ enum { /* Internal hardware exception sources */ PPC_INTERRUPT_DECR, /* Decrementer exception */ PPC_INTERRUPT_HDECR, /* Hypervisor decrementer exception */ - PPC_INTERRUPT_PIT, /* Programmable inteval timer interrupt */ + PPC_INTERRUPT_PIT, /* Programmable interval timer interrupt */ PPC_INTERRUPT_FIT, /* Fixed interval timer interrupt */ PPC_INTERRUPT_WDT, /* Watchdog timer interrupt */ PPC_INTERRUPT_CDOORBELL, /* Critical doorbell interrupt */ PPC_INTERRUPT_DOORBELL, /* Doorbell interrupt */ PPC_INTERRUPT_PERFM, /* Performance monitor interrupt */ - PPC_INTERRUPT_HMI, /* Hypervisor Maintainance interrupt */ + PPC_INTERRUPT_HMI, /* Hypervisor Maintenance interrupt */ PPC_INTERRUPT_HDOORBELL, /* Hypervisor Doorbell interrupt */ PPC_INTERRUPT_HVIRT, /* Hypervisor virtualization interrupt */ }; diff --git a/target/ppc/dfp_helper.c b/target/ppc/dfp_helper.c index 2c65badae446fb5eb705681adeb43744ed2f9818..07341a69f5204f5808d0089e0e83e9aa1439462c 100644 --- a/target/ppc/dfp_helper.c +++ b/target/ppc/dfp_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index f0529796647208372e79cf4be51abb8d52d2c537..74f987080ffcbe4a0002816c9f89939441f0ceaa 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -67,19 +67,31 @@ static inline void dump_syscall(CPUPPCState *env) ppc_dump_gpr(env, 8), env->nip); } +static inline void dump_syscall_vectored(CPUPPCState *env) +{ + qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 + " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64 + " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64 + " nip=" TARGET_FMT_lx "\n", + ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3), + ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5), + ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7), + ppc_dump_gpr(env, 8), env->nip); +} + static inline void dump_hcall(CPUPPCState *env) { qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64 - " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64 - " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64 - " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64 + " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64 + " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64 + " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64 " nip=" TARGET_FMT_lx "\n", ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4), - ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6), - ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8), - ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10), - ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12), - env->nip); + ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6), + ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8), + ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10), + ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12), + env->nip); } static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, @@ -89,7 +101,7 @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, env->resume_as_sreset = false; /* Pretend to be returning from doze always as we don't lose state */ - *msr |= (0x1ull << (63 - 47)); + *msr |= SRR1_WS_NOLOSS; /* Machine checks are sent normally */ if (excp == POWERPC_EXCP_MCHECK) { @@ -97,25 +109,25 @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, } switch (excp) { case POWERPC_EXCP_RESET: - *msr |= 0x4ull << (63 - 45); + *msr |= SRR1_WAKERESET; break; case POWERPC_EXCP_EXTERNAL: - *msr |= 0x8ull << (63 - 45); + *msr |= SRR1_WAKEEE; break; case POWERPC_EXCP_DECR: - *msr |= 0x6ull << (63 - 45); + *msr |= SRR1_WAKEDEC; break; case POWERPC_EXCP_SDOOR: - *msr |= 0x5ull << (63 - 45); + *msr |= SRR1_WAKEDBELL; break; case POWERPC_EXCP_SDOOR_HV: - *msr |= 0x3ull << (63 - 45); + *msr |= SRR1_WAKEHDBELL; break; case POWERPC_EXCP_HV_MAINT: - *msr |= 0xaull << (63 - 45); + *msr |= SRR1_WAKEHMI; break; case POWERPC_EXCP_HVIRT: - *msr |= 0x9ull << (63 - 45); + *msr |= SRR1_WAKEHVI; break; default: cpu_abort(cs, "Unsupported exception %d in Power Save mode\n", @@ -185,7 +197,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; target_ulong msr, new_msr, vector; - int srr0, srr1, asrr0, asrr1, lev, ail; + int srr0, srr1, asrr0, asrr1, lev = -1, ail; bool lpes0; qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx @@ -219,7 +231,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) } /* - * Exception targetting modifiers + * Exception targeting modifiers * * LPES0 is supported on POWER7/8/9 * LPES1 is not supported (old iSeries mode) @@ -421,6 +433,13 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) new_msr |= (target_ulong)MSR_HVB; } break; + case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */ + lev = env->error_code; + dump_syscall_vectored(env); + env->nip += 4; + new_msr |= env->msr & ((target_ulong)1 << MSR_EE); + new_msr |= env->msr & ((target_ulong)1 << MSR_RI); + break; case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ case POWERPC_EXCP_DECR: /* Decrementer exception */ @@ -508,6 +527,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) break; case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */ msr |= env->error_code; + /* fall through */ case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ @@ -724,12 +744,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) break; } - /* Save PC */ - env->spr[srr0] = env->nip; - - /* Save MSR */ - env->spr[srr1] = msr; - /* Sanity check */ if (!(env->msr_mask & MSR_HVB)) { if (new_msr & MSR_HVB) { @@ -742,14 +756,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) } } - /* If any alternate SRR register are defined, duplicate saved values */ - if (asrr0 != -1) { - env->spr[asrr0] = env->spr[srr0]; - } - if (asrr1 != -1) { - env->spr[asrr1] = env->spr[srr1]; - } - /* * Sort out endianness of interrupt, this differs depending on the * CPU, the HV mode, etc... @@ -784,14 +790,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) } #endif - /* Jump to handler */ - vector = env->excp_vectors[excp]; - if (vector == (target_ulong)-1ULL) { - cpu_abort(cs, "Raised an exception without defined vector %d\n", - excp); - } - vector |= env->excp_prefix; - /* * AIL only works if there is no HV transition and we are running * with translations enabled @@ -800,10 +798,21 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) ((new_msr & MSR_HVB) && !(msr & MSR_HVB))) { ail = 0; } - /* Handle AIL */ - if (ail) { - new_msr |= (1 << MSR_IR) | (1 << MSR_DR); - vector |= ppc_excp_vector_offset(cs, ail); + + vector = env->excp_vectors[excp]; + if (vector == (target_ulong)-1ULL) { + cpu_abort(cs, "Raised an exception without defined vector %d\n", + excp); + } + + vector |= env->excp_prefix; + + /* If any alternate SRR register are defined, duplicate saved values */ + if (asrr0 != -1) { + env->spr[asrr0] = env->nip; + } + if (asrr1 != -1) { + env->spr[asrr1] = msr; } #if defined(TARGET_PPC64) @@ -823,6 +832,37 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) } #endif + if (excp != POWERPC_EXCP_SYSCALL_VECTORED) { + /* Save PC */ + env->spr[srr0] = env->nip; + + /* Save MSR */ + env->spr[srr1] = msr; + + /* Handle AIL */ + if (ail) { + new_msr |= (1 << MSR_IR) | (1 << MSR_DR); + vector |= ppc_excp_vector_offset(cs, ail); + } + +#if defined(TARGET_PPC64) + } else { + /* scv AIL is a little different */ + if (ail) { + new_msr |= (1 << MSR_IR) | (1 << MSR_DR); + } + if (ail == AIL_C000_0000_0000_4000) { + vector |= 0xc000000000003000ull; + } else { + vector |= 0x0000000000017000ull; + } + vector += lev * 0x20; + + env->lr = env->nip; + env->ctr = msr; +#endif + } + powerpc_set_excp_state(cpu, vector, new_msr); } @@ -976,7 +1016,7 @@ static void ppc_hw_interrupt(CPUPPCState *env) * This means we will incorrectly execute past the power management * instruction instead of triggering a reset. * - * It generally means a discrepancy between the wakup conditions in the + * It generally means a discrepancy between the wakeup conditions in the * processor has_work implementation and the logic in this function. */ cpu_abort(env_cpu(env), @@ -1152,7 +1192,7 @@ void helper_rfi(CPUPPCState *env) void helper_rfid(CPUPPCState *env) { /* - * The architeture defines a number of rules for which bits can + * The architecture defines a number of rules for which bits can * change but in practice, we handle this in hreg_store_msr() * which will be called by do_rfi(), so there is no need to filter * here @@ -1160,6 +1200,11 @@ void helper_rfid(CPUPPCState *env) do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]); } +void helper_rfscv(CPUPPCState *env) +{ + do_rfi(env, env->lr, env->ctr); +} + void helper_hrfid(CPUPPCState *env) { do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]); diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c index ae43b08eb5a99c20433180ea2048bd7309119a9b..32a9a8a0f8ab2dd632307fb521e8a32d535eee91 100644 --- a/target/ppc/fpu_helper.c +++ b/target/ppc/fpu_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -1804,7 +1804,7 @@ uint32_t helper_efdcmpeq(CPUPPCState *env, uint64_t op1, uint64_t op2) /* - * VSX_ADD_SUB - VSX floating point add/subract + * VSX_ADD_SUB - VSX floating point add/subtract * name - instruction mnemonic * op - operation (add or sub) * nels - number of elements (1, 2 or 4) diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c index 5c11c88b2a879fc7475711b3ba9ce5589b0816db..01459dd31d23ceac2d52927102dc0b4e783ecfa1 100644 --- a/target/ppc/gdbstub.c +++ b/target/ppc/gdbstub.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/ppc/helper.h b/target/ppc/helper.h index a95c0103912bd483f78172a8fc41c69ebccb02a8..6a4dccf70c0a8ab58fad8df88124084b6b10b806 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -15,6 +15,7 @@ DEF_HELPER_1(rfmci, void, env) #if defined(TARGET_PPC64) DEF_HELPER_2(pminsn, void, env, i32) DEF_HELPER_1(rfid, void, env) +DEF_HELPER_1(rfscv, void, env) DEF_HELPER_1(hrfid, void, env) DEF_HELPER_2(store_lpcr, void, env, tl) DEF_HELPER_2(store_pcr, void, env, tl) @@ -183,7 +184,10 @@ DEF_HELPER_3(vmulosw, void, avr, avr, avr) DEF_HELPER_3(vmuloub, void, avr, avr, avr) DEF_HELPER_3(vmulouh, void, avr, avr, avr) DEF_HELPER_3(vmulouw, void, avr, avr, avr) -DEF_HELPER_3(vmuluwm, void, avr, avr, avr) +DEF_HELPER_3(vmulhsw, void, avr, avr, avr) +DEF_HELPER_3(vmulhuw, void, avr, avr, avr) +DEF_HELPER_3(vmulhsd, void, avr, avr, avr) +DEF_HELPER_3(vmulhud, void, avr, avr, avr) DEF_HELPER_3(vslo, void, avr, avr, avr) DEF_HELPER_3(vsro, void, avr, avr, avr) DEF_HELPER_3(vsrv, void, avr, avr, avr) @@ -213,10 +217,6 @@ DEF_HELPER_3(vsubuqm, void, avr, avr, avr) DEF_HELPER_4(vsubecuq, void, avr, avr, avr, avr) DEF_HELPER_4(vsubeuqm, void, avr, avr, avr, avr) DEF_HELPER_3(vsubcuq, void, avr, avr, avr) -DEF_HELPER_3(vrlb, void, avr, avr, avr) -DEF_HELPER_3(vrlh, void, avr, avr, avr) -DEF_HELPER_3(vrlw, void, avr, avr, avr) -DEF_HELPER_3(vrld, void, avr, avr, avr) DEF_HELPER_4(vsldoi, void, avr, avr, avr, i32) DEF_HELPER_3(vextractub, void, avr, avr, i32) DEF_HELPER_3(vextractuh, void, avr, avr, i32) diff --git a/target/ppc/helper_regs.h b/target/ppc/helper_regs.h index d78c2af63eac0ba5aa7206bb2d7502f0a04b93ce..efcc9034271249722c3377ee47499d02098b4f7b 100644 --- a/target/ppc/helper_regs.h +++ b/target/ppc/helper_regs.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index be53cd6f68dd67026938710b01efefc07979df60..0b682a1f94a22f8d751f38dbdeecbd0c6dd192bc 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -398,7 +398,7 @@ target_ulong helper_divso(CPUPPCState *env, target_ulong arg1, target_ulong helper_602_mfrom(target_ulong arg) { if (likely(arg < 602)) { -#include "mfrom_table.inc.c" +#include "mfrom_table.c.inc" return mfrom_ROM_table[arg]; } else { return 0; @@ -523,19 +523,6 @@ void helper_vprtybq(ppc_avr_t *r, ppc_avr_t *b) r->VsrD(0) = 0; } -#define VARITH_DO(name, op, element) \ - void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ - { \ - int i; \ - \ - for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ - r->element[i] = a->element[i] op b->element[i]; \ - } \ - } -VARITH_DO(muluwm, *, u32) -#undef VARITH_DO -#undef VARITH - #define VARITHFP(suffix, func) \ void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \ ppc_avr_t *b) \ @@ -1099,6 +1086,41 @@ VMUL(uw, u32, VsrW, VsrD, uint64_t) #undef VMUL_DO_ODD #undef VMUL +void helper_vmulhsw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) +{ + int i; + + for (i = 0; i < 4; i++) { + r->s32[i] = (int32_t)(((int64_t)a->s32[i] * (int64_t)b->s32[i]) >> 32); + } +} + +void helper_vmulhuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) +{ + int i; + + for (i = 0; i < 4; i++) { + r->u32[i] = (uint32_t)(((uint64_t)a->u32[i] * + (uint64_t)b->u32[i]) >> 32); + } +} + +void helper_vmulhsd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) +{ + uint64_t discard; + + muls64(&discard, &r->u64[0], a->s64[0], b->s64[0]); + muls64(&discard, &r->u64[1], a->s64[1], b->s64[1]); +} + +void helper_vmulhud(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) +{ + uint64_t discard; + + mulu64(&discard, &r->u64[0], a->u64[0], b->u64[0]); + mulu64(&discard, &r->u64[1], a->u64[1], b->u64[1]); +} + void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) { @@ -1348,23 +1370,6 @@ VRFI(p, float_round_up) VRFI(z, float_round_to_zero) #undef VRFI -#define VROTATE(suffix, element, mask) \ - void helper_vrl##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ - { \ - int i; \ - \ - for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ - unsigned int shift = b->element[i] & mask; \ - r->element[i] = (a->element[i] << shift) | \ - (a->element[i] >> (sizeof(a->element[0]) * 8 - shift)); \ - } \ - } -VROTATE(b, u8, 0x7) -VROTATE(h, u16, 0xF) -VROTATE(w, u32, 0x1F) -VROTATE(d, u64, 0x3F) -#undef VROTATE - void helper_vrsqrtefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b) { int i; diff --git a/target/ppc/internal.h b/target/ppc/internal.h index 15d655b35649bd87de56dfdd91d44c515f5c02e7..d547448065a140a5a47452aa27720f2c0b14e889 100644 --- a/target/ppc/internal.h +++ b/target/ppc/internal.h @@ -1,10 +1,10 @@ /* - * PowerPC interal definitions for qemu. + * PowerPC internal definitions for qemu. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 2692f76130aae94e0ff4367e3f5efc21afb14d09..daf690a67820dc551cfc8fd917f0cb9a118d7421 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -487,7 +487,7 @@ int kvm_arch_init_vcpu(CPUState *cs) /* * KVM-HV has transactional memory on POWER8 also without * the KVM_CAP_PPC_HTM extension, so enable it here - * instead as long as it's availble to userspace on the + * instead as long as it's available to userspace on the * host. */ if (qemu_getauxval(AT_HWCAP2) & PPC_FEATURE2_HAS_HTM) { @@ -2071,9 +2071,8 @@ bool kvmppc_get_fwnmi(void) return cap_fwnmi; } -int kvmppc_set_fwnmi(void) +int kvmppc_set_fwnmi(PowerPCCPU *cpu) { - PowerPCCPU *cpu = POWERPC_CPU(first_cpu); CPUState *cs = CPU(cpu); return kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_FWNMI, 0); @@ -2684,7 +2683,7 @@ int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, int64_t max_ns) } int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index, - uint16_t n_valid, uint16_t n_invalid) + uint16_t n_valid, uint16_t n_invalid, Error **errp) { struct kvm_get_htab_header *buf; size_t chunksize = sizeof(*buf) + n_valid * HASH_PTE_SIZE_64; @@ -2699,14 +2698,13 @@ int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index, rc = write(fd, buf, chunksize); if (rc < 0) { - fprintf(stderr, "Error writing KVM hash table: %s\n", - strerror(errno)); - return rc; + error_setg_errno(errp, errno, "Error writing the KVM hash table"); + return -errno; } if (rc != chunksize) { /* We should never get a short write on a single chunk */ - fprintf(stderr, "Short write, restoring KVM hash table\n"); - return -1; + error_setg(errp, "Short write while restoring the KVM hash table"); + return -ENOSPC; } return 0; } diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h index fcaf745516b4d960231b9a0d05b659dc64771e73..73ce2bc95114afa472e20aab1802d3d4a22b2adc 100644 --- a/target/ppc/kvm_ppc.h +++ b/target/ppc/kvm_ppc.h @@ -28,7 +28,7 @@ void kvmppc_set_papr(PowerPCCPU *cpu); int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr); void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy); bool kvmppc_get_fwnmi(void); -int kvmppc_set_fwnmi(void); +int kvmppc_set_fwnmi(PowerPCCPU *cpu); int kvmppc_smt_threads(void); void kvmppc_error_append_smt_possible_hint(Error *const *errp); int kvmppc_set_smt_threads(int smt); @@ -56,7 +56,7 @@ int kvmppc_define_rtas_kernel_token(uint32_t token, const char *function); int kvmppc_get_htab_fd(bool write, uint64_t index, Error **errp); int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, int64_t max_ns); int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index, - uint16_t n_valid, uint16_t n_invalid); + uint16_t n_valid, uint16_t n_invalid, Error **errp); void kvmppc_read_hptes(ppc_hash_pte64_t *hptes, hwaddr ptex, int n); void kvmppc_write_hpte(hwaddr ptex, uint64_t pte0, uint64_t pte1); bool kvmppc_has_cap_fixup_hcalls(void); @@ -169,7 +169,7 @@ static inline bool kvmppc_get_fwnmi(void) return false; } -static inline int kvmppc_set_fwnmi(void) +static inline int kvmppc_set_fwnmi(PowerPCCPU *cpu) { return -1; } @@ -280,6 +280,17 @@ static inline bool kvmppc_has_cap_spapr_vfio(void) return false; } +static inline void kvmppc_read_hptes(ppc_hash_pte64_t *hptes, + hwaddr ptex, int n) +{ + abort(); +} + +static inline void kvmppc_write_hpte(hwaddr ptex, uint64_t pte0, uint64_t pte1) +{ + abort(); +} + #endif /* !CONFIG_USER_ONLY */ static inline bool kvmppc_has_cap_epr(void) @@ -305,18 +316,8 @@ static inline int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, } static inline int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index, - uint16_t n_valid, uint16_t n_invalid) -{ - abort(); -} - -static inline void kvmppc_read_hptes(ppc_hash_pte64_t *hptes, - hwaddr ptex, int n) -{ - abort(); -} - -static inline void kvmppc_write_hpte(hwaddr ptex, uint64_t pte0, uint64_t pte1) + uint16_t n_valid, uint16_t n_invalid, + Error **errp) { abort(); } diff --git a/target/ppc/machine.c b/target/ppc/machine.c index 109d0711628f686140b6a76984898014191ad46b..c38e7b1268ddcf70c9be6e1f678ba86c857964a9 100644 --- a/target/ppc/machine.c +++ b/target/ppc/machine.c @@ -337,7 +337,7 @@ static int cpu_post_load(void *opaque, int version_id) /* * If we're operating in compat mode, we should be ok as long as - * the destination supports the same compatiblity mode. + * the destination supports the same compatibility mode. * * Otherwise, however, we require that the destination has exactly * the same CPU model as the source. @@ -347,18 +347,19 @@ static int cpu_post_load(void *opaque, int version_id) if (cpu->compat_pvr) { uint32_t compat_pvr = cpu->compat_pvr; Error *local_err = NULL; + int ret; cpu->compat_pvr = 0; - ppc_set_compat(cpu, compat_pvr, &local_err); - if (local_err) { + ret = ppc_set_compat(cpu, compat_pvr, &local_err); + if (ret < 0) { error_report_err(local_err); - return -1; + return ret; } } else #endif { if (!pvr_match(cpu, env->spr[SPR_PVR])) { - return -1; + return -EINVAL; } } diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c index 98f589552b2fbe826f319d5fa5e9134bb2ade0e0..f4f7e730de18595bb1efdeed308f9cbafc0eca41 100644 --- a/target/ppc/mem_helper.c +++ b/target/ppc/mem_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/ppc/meson.build b/target/ppc/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..bbfef90e08c9cf9585ea0aff32086c126422dd19 --- /dev/null +++ b/target/ppc/meson.build @@ -0,0 +1,37 @@ +ppc_ss = ss.source_set() +ppc_ss.add(files( + 'cpu-models.c', + 'cpu.c', + 'dfp_helper.c', + 'excp_helper.c', + 'fpu_helper.c', + 'gdbstub.c', + 'int_helper.c', + 'mem_helper.c', + 'misc_helper.c', + 'timebase_helper.c', + 'translate.c', +)) + +ppc_ss.add(libdecnumber) + +ppc_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('kvm-stub.c')) +ppc_ss.add(when: 'CONFIG_USER_ONLY', if_true: files('user_only_helper.c')) + +ppc_softmmu_ss = ss.source_set() +ppc_softmmu_ss.add(files( + 'arch_dump.c', + 'machine.c', + 'mmu-hash32.c', + 'mmu_helper.c', + 'monitor.c', +)) +ppc_softmmu_ss.add(when: 'TARGET_PPC64', if_true: files( + 'compat.c', + 'mmu-book3s-v3.c', + 'mmu-hash64.c', + 'mmu-radix64.c', +)) + +target_arch += {'ppc': ppc_ss} +target_softmmu_arch += {'ppc': ppc_softmmu_ss} diff --git a/target/ppc/mfrom_table.inc.c b/target/ppc/mfrom_table.c.inc similarity index 100% rename from target/ppc/mfrom_table.inc.c rename to target/ppc/mfrom_table.c.inc diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c index 55b68d1246e4532c2b1672cff575e23a567a9c74..5d6e0de396ce9d2a4dd9b331507cae008c967d62 100644 --- a/target/ppc/misc_helper.c +++ b/target/ppc/misc_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -234,25 +234,20 @@ target_ulong helper_clcs(CPUPPCState *env, uint32_t arg) case 0x0CUL: /* Instruction cache line size */ return env->icache_line_size; - break; case 0x0DUL: /* Data cache line size */ return env->dcache_line_size; - break; case 0x0EUL: /* Minimum cache line size */ return (env->icache_line_size < env->dcache_line_size) ? env->icache_line_size : env->dcache_line_size; - break; case 0x0FUL: /* Maximum cache line size */ return (env->icache_line_size > env->dcache_line_size) ? env->icache_line_size : env->dcache_line_size; - break; default: /* Undefined */ return 0; - break; } } diff --git a/target/ppc/mmu-book3s-v3.c b/target/ppc/mmu-book3s-v3.c index 32b8c166b576b06daece77be67b31e8adf6cf502..c78fd8dc0e3842a515a51ef6ac3f0115c17b4c8d 100644 --- a/target/ppc/mmu-book3s-v3.c +++ b/target/ppc/mmu-book3s-v3.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/ppc/mmu-book3s-v3.h b/target/ppc/mmu-book3s-v3.h index 0f3c9d09c6c0e31ad06810cbb3e2810332a68d40..7b89be54b83a9a1855d7cba86bb96217082078e1 100644 --- a/target/ppc/mmu-book3s-v3.h +++ b/target/ppc/mmu-book3s-v3.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c index 55cf156a0b49be6b3d2e68e408845c27d9e44021..178cf090b72eef4af5213d2fa19b1ed5a914a122 100644 --- a/target/ppc/mmu-hash32.c +++ b/target/ppc/mmu-hash32.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c index e5baabf0e1e8b417240d679d81f5a5394d1ccfd3..1b1248fc9054920da8b24da773b67c76e75acf54 100644 --- a/target/ppc/mmu-hash64.c +++ b/target/ppc/mmu-hash64.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -859,7 +859,7 @@ static int build_vrma_slbe(PowerPCCPU *cpu, ppc_slb_t *slb) } error_report("Bad page size encoding in LPCR[VRMASD]; LPCR=0x" - TARGET_FMT_lx"\n", lpcr); + TARGET_FMT_lx, lpcr); return -1; } @@ -883,7 +883,7 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, /* * Note on LPCR usage: 970 uses HID4, but our special variant of * store_spr copies relevant fields into env->spr[SPR_LPCR]. - * Similarily we filter unimplemented bits when storing into LPCR + * Similarly we filter unimplemented bits when storing into LPCR * depending on the MMU version. This code can thus just use the * LPCR "as-is". */ diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c index 1404e53deca825e3d67619ffbe24b24cef581ba7..30fcfcf11fcd8324805c946762980eb2c2ee8740 100644 --- a/target/ppc/mmu-radix64.c +++ b/target/ppc/mmu-radix64.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -28,7 +28,8 @@ #include "mmu-radix64.h" #include "mmu-book3s-v3.h" -static bool ppc_radix64_get_fully_qualified_addr(CPUPPCState *env, vaddr eaddr, +static bool ppc_radix64_get_fully_qualified_addr(const CPUPPCState *env, + vaddr eaddr, uint64_t *lpid, uint64_t *pid) { if (msr_hv) { /* MSR[HV] -> Hypervisor/bare metal */ @@ -49,6 +50,8 @@ static bool ppc_radix64_get_fully_qualified_addr(CPUPPCState *env, vaddr eaddr, *lpid = 0; *pid = 0; break; + default: + g_assert_not_reached(); } } else { /* !MSR[HV] -> Guest */ switch (eaddr & R_EADDR_QUADRANT) { @@ -63,6 +66,8 @@ static bool ppc_radix64_get_fully_qualified_addr(CPUPPCState *env, vaddr eaddr, *lpid = env->spr[SPR_LPIDR]; *pid = 0; /* pid set to 0 -> addresses guest operating system */ break; + default: + g_assert_not_reached(); } } @@ -269,7 +274,7 @@ static int ppc_radix64_partition_scoped_xlate(PowerPCCPU *cpu, int rwx, ppc_v3_pate_t pate, hwaddr *h_raddr, int *h_prot, int *h_page_size, bool pde_addr, - bool cause_excp) + bool guest_visible) { int fault_cause = 0; hwaddr pte_addr; @@ -281,16 +286,18 @@ static int ppc_radix64_partition_scoped_xlate(PowerPCCPU *cpu, int rwx, pate.dw0 & PRTBE_R_RPDS, h_raddr, h_page_size, &pte, &fault_cause, &pte_addr) || ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, h_prot, true)) { - if (pde_addr) /* address being translated was that of a guest pde */ + if (pde_addr) { /* address being translated was that of a guest pde */ fault_cause |= DSISR_PRTABLE_FAULT; - if (cause_excp) { + } + if (guest_visible) { ppc_radix64_raise_hsi(cpu, rwx, eaddr, g_raddr, fault_cause); } return 1; } - /* Update Reference and Change Bits */ - ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, h_prot); + if (guest_visible) { + ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, h_prot); + } return 0; } @@ -299,7 +306,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx, vaddr eaddr, uint64_t pid, ppc_v3_pate_t pate, hwaddr *g_raddr, int *g_prot, int *g_page_size, - bool cause_excp) + bool guest_visible) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; @@ -313,7 +320,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx, size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12); if (offset >= size) { /* offset exceeds size of the process table */ - if (cause_excp) { + if (guest_visible) { ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE); } return 1; @@ -333,7 +340,8 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx, */ ret = ppc_radix64_partition_scoped_xlate(cpu, 0, eaddr, prtbe_addr, pate, &h_raddr, &h_prot, - &h_page_size, 1, 1); + &h_page_size, true, + guest_visible); if (ret) { return ret; } @@ -353,7 +361,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx, &fault_cause, &pte_addr); if (ret) { /* No valid PTE */ - if (cause_excp) { + if (guest_visible) { ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause); } return ret; @@ -372,7 +380,8 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx, do { ret = ppc_radix64_partition_scoped_xlate(cpu, 0, eaddr, pte_addr, pate, &h_raddr, &h_prot, - &h_page_size, 1, 1); + &h_page_size, true, + guest_visible); if (ret) { return ret; } @@ -381,7 +390,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx, &nls, g_page_size, &pte, &fault_cause); if (ret) { /* No valid pte */ - if (cause_excp) { + if (guest_visible) { ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause); } return ret; @@ -398,13 +407,15 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx, if (ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, g_prot, false)) { /* Access denied due to protection */ - if (cause_excp) { + if (guest_visible) { ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause); } return 1; } - ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, g_prot); + if (guest_visible) { + ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, g_prot); + } return 0; } @@ -429,17 +440,17 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx, static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx, bool relocation, hwaddr *raddr, int *psizep, int *protp, - bool cause_excp) + bool guest_visible) { CPUPPCState *env = &cpu->env; - uint64_t lpid = 0, pid = 0; + uint64_t lpid, pid; ppc_v3_pate_t pate; int psize, prot; hwaddr g_raddr; /* Virtual Mode Access - get the fully qualified address */ if (!ppc_radix64_get_fully_qualified_addr(&cpu->env, eaddr, &lpid, &pid)) { - if (cause_excp) { + if (guest_visible) { ppc_radix64_raise_segi(cpu, rwx, eaddr); } return 1; @@ -452,13 +463,13 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx, vhc->get_pate(cpu->vhyp, &pate); } else { if (!ppc64_v3_get_pate(cpu, lpid, &pate)) { - if (cause_excp) { + if (guest_visible) { ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE); } return 1; } if (!validate_pate(cpu, lpid, &pate)) { - if (cause_excp) { + if (guest_visible) { ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_R_BADCONFIG); } return 1; @@ -479,7 +490,7 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx, if (relocation) { int ret = ppc_radix64_process_scoped_xlate(cpu, rwx, eaddr, pid, pate, &g_raddr, &prot, - &psize, cause_excp); + &psize, guest_visible); if (ret) { return ret; } @@ -502,7 +513,7 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx, ret = ppc_radix64_partition_scoped_xlate(cpu, rwx, eaddr, g_raddr, pate, raddr, &prot, &psize, - 0, cause_excp); + false, guest_visible); if (ret) { return ret; } diff --git a/target/ppc/mmu-radix64.h b/target/ppc/mmu-radix64.h index 96228546aa853de5d9cda7a3164178dcdec70542..f28c5794d071aca2b1aa56e209418360c2cd28ee 100644 --- a/target/ppc/mmu-radix64.h +++ b/target/ppc/mmu-radix64.h @@ -55,9 +55,9 @@ static inline int ppc_radix64_get_prot_eaa(uint64_t pte) (pte & R_PTE_EAA_X ? PAGE_EXEC : 0); } -static inline int ppc_radix64_get_prot_amr(PowerPCCPU *cpu) +static inline int ppc_radix64_get_prot_amr(const PowerPCCPU *cpu) { - CPUPPCState *env = &cpu->env; + const CPUPPCState *env = &cpu->env; int amr = env->spr[SPR_AMR] >> 62; /* We only care about key0 AMR63:62 */ int iamr = env->spr[SPR_IAMR] >> 62; /* We only care about key0 IAMR63:62 */ diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index 8972714775e8b194e9c7a8732d95608bc73290cf..064d2e8d13cac91be2f4b560b53c752f96594b3b 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -179,7 +179,7 @@ static inline int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0, } /* Compute access rights */ access = pp_check(ctx->key, pp, ctx->nx); - /* Keep the matching PTE informations */ + /* Keep the matching PTE information */ ctx->raddr = pte1; ctx->prot = access; ret = check_prot(ctx->prot, rw, type); @@ -2176,7 +2176,7 @@ void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value) env->sr[srnum] = value; /* * Invalidating 256MB of virtual memory in 4kB pages is way - * longer than flusing the whole TLB. + * longer than flushing the whole TLB. */ #if !defined(FLUSH_ALL_TLBS) && 0 { diff --git a/target/ppc/monitor.c b/target/ppc/monitor.c index a5a177d717e6fa1232822fdf51a49cb6b9d78fe5..a475108b2dbc1d9bbb6956f6675df3c722bab051 100644 --- a/target/ppc/monitor.c +++ b/target/ppc/monitor.c @@ -29,9 +29,10 @@ #include "monitor/hmp-target.h" #include "monitor/hmp.h" -static target_long monitor_get_ccr(const struct MonitorDef *md, int val) +static target_long monitor_get_ccr(Monitor *mon, const struct MonitorDef *md, + int val) { - CPUArchState *env = mon_get_cpu_env(); + CPUArchState *env = mon_get_cpu_env(mon); unsigned int u; int i; @@ -43,27 +44,30 @@ static target_long monitor_get_ccr(const struct MonitorDef *md, int val) return u; } -static target_long monitor_get_decr(const struct MonitorDef *md, int val) +static target_long monitor_get_decr(Monitor *mon, const struct MonitorDef *md, + int val) { - CPUArchState *env = mon_get_cpu_env(); + CPUArchState *env = mon_get_cpu_env(mon); return cpu_ppc_load_decr(env); } -static target_long monitor_get_tbu(const struct MonitorDef *md, int val) +static target_long monitor_get_tbu(Monitor *mon, const struct MonitorDef *md, + int val) { - CPUArchState *env = mon_get_cpu_env(); + CPUArchState *env = mon_get_cpu_env(mon); return cpu_ppc_load_tbu(env); } -static target_long monitor_get_tbl(const struct MonitorDef *md, int val) +static target_long monitor_get_tbl(Monitor *mon, const struct MonitorDef *md, + int val) { - CPUArchState *env = mon_get_cpu_env(); + CPUArchState *env = mon_get_cpu_env(mon); return cpu_ppc_load_tbl(env); } void hmp_info_tlb(Monitor *mon, const QDict *qdict) { - CPUArchState *env1 = mon_get_cpu_env(); + CPUArchState *env1 = mon_get_cpu_env(mon); if (!env1) { monitor_printf(mon, "No CPU available\n"); diff --git a/target/ppc/timebase_helper.c b/target/ppc/timebase_helper.c index d16360ab667558f8cc107245baae0dcf0e9fa59f..8ff4080eb91ed28dd829091e57b31bce1d1ca04e 100644 --- a/target/ppc/timebase_helper.c +++ b/target/ppc/timebase_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/ppc/trace-events b/target/ppc/trace-events index 6d15aa90b4f6fd153ce4e87fb38ec37397d88bc4..bc0d4e6f8bb79132b35657f3fd2a76ef3e3940d6 100644 --- a/target/ppc/trace-events +++ b/target/ppc/trace-events @@ -20,7 +20,6 @@ kvm_failed_dtl_set(const char *msg) "Unable to set dispatch trace log state to K kvm_failed_null_vpa_addr_set(const char *msg) "Unable to set VPA address to KVM: %s" kvm_failed_put_vpa(void) "Warning: Unable to set VPA information to KVM" kvm_failed_get_vpa(void) "Warning: Unable to get VPA information from KVM" -kvm_injected_interrupt(int irq) "injected interrupt %d" kvm_handle_dcr_write(void) "handle dcr write" kvm_handle_dcr_read(void) "handle dcr read" kvm_handle_halt(void) "handle halt" diff --git a/target/ppc/trace.h b/target/ppc/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..a9e89628280b2c8fd2a48398ff3d8680794e9579 --- /dev/null +++ b/target/ppc/trace.h @@ -0,0 +1 @@ +#include "trace/trace-target_ppc.h" diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 338529879f95ddce800706e501ba25baf979ac9a..54cac0e6a77974a5730d0bb89bbdc5200bc15b1c 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -173,6 +173,7 @@ struct DisasContext { bool vsx_enabled; bool spe_enabled; bool tm_enabled; + bool scv_enabled; bool gtse; ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */ int singlestep_enabled; @@ -4030,6 +4031,24 @@ static void gen_rfid(DisasContext *ctx) #endif } +#if !defined(CONFIG_USER_ONLY) +static void gen_rfscv(DisasContext *ctx) +{ +#if defined(CONFIG_USER_ONLY) + GEN_PRIV; +#else + /* Restore CPU state */ + CHK_SV; + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_io_start(); + } + gen_update_cfar(ctx, ctx->base.pc_next - 4); + gen_helper_rfscv(cpu_env); + gen_sync_exception(ctx); +#endif +} +#endif + static void gen_hrfid(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) @@ -4048,6 +4067,7 @@ static void gen_hrfid(DisasContext *ctx) #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER #else #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL +#define POWERPC_SYSCALL_VECTORED POWERPC_EXCP_SYSCALL_VECTORED #endif static void gen_sc(DisasContext *ctx) { @@ -4057,6 +4077,23 @@ static void gen_sc(DisasContext *ctx) gen_exception_err(ctx, POWERPC_SYSCALL, lev); } +#if defined(TARGET_PPC64) +#if !defined(CONFIG_USER_ONLY) +static void gen_scv(DisasContext *ctx) +{ + uint32_t lev; + + if (unlikely(!ctx->scv_enabled)) { + gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_SCV); + return; + } + + lev = (ctx->opcode >> 5) & 0x7F; + gen_exception_err(ctx, POWERPC_SYSCALL_VECTORED, lev); +} +#endif +#endif + /*** Trap ***/ /* Check for unconditional traps (always or never) */ @@ -6863,15 +6900,15 @@ static inline void set_avr64(int regno, TCGv_i64 src, bool high) tcg_gen_st_i64(src, cpu_env, avr64_offset(regno, high)); } -#include "translate/fp-impl.inc.c" +#include "translate/fp-impl.c.inc" -#include "translate/vmx-impl.inc.c" +#include "translate/vmx-impl.c.inc" -#include "translate/vsx-impl.inc.c" +#include "translate/vsx-impl.c.inc" -#include "translate/dfp-impl.inc.c" +#include "translate/dfp-impl.c.inc" -#include "translate/spe-impl.inc.c" +#include "translate/spe-impl.c.inc" /* Handles lfdp, lxsd, lxssp */ static void gen_dform39(DisasContext *ctx) @@ -6934,7 +6971,47 @@ static void gen_dform3D(DisasContext *ctx) return gen_invalid(ctx); } +#if defined(TARGET_PPC64) +/* brd */ +static void gen_brd(DisasContext *ctx) +{ + tcg_gen_bswap64_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); +} + +/* brw */ +static void gen_brw(DisasContext *ctx) +{ + tcg_gen_bswap64_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); + tcg_gen_rotli_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 32); + +} + +/* brh */ +static void gen_brh(DisasContext *ctx) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + + tcg_gen_movi_i64(t0, 0x00ff00ff00ff00ffull); + tcg_gen_shri_i64(t1, cpu_gpr[rS(ctx->opcode)], 8); + tcg_gen_and_i64(t2, t1, t0); + tcg_gen_and_i64(t1, cpu_gpr[rS(ctx->opcode)], t0); + tcg_gen_shli_i64(t1, t1, 8); + tcg_gen_or_i64(cpu_gpr[rA(ctx->opcode)], t1, t2); + + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); +} +#endif + static opcode_t opcodes[] = { +#if defined(TARGET_PPC64) +GEN_HANDLER_E(brd, 0x1F, 0x1B, 0x05, 0x0000F801, PPC_NONE, PPC2_ISA310), +GEN_HANDLER_E(brw, 0x1F, 0x1B, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA310), +GEN_HANDLER_E(brh, 0x1F, 0x1B, 0x06, 0x0000F801, PPC_NONE, PPC2_ISA310), +#endif GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE), GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER), GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER), @@ -7049,6 +7126,12 @@ GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER), GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW), #if defined(TARGET_PPC64) GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B), +#if !defined(CONFIG_USER_ONLY) +/* Top bit of opc2 corresponds with low bit of LEV, so use two handlers */ +GEN_HANDLER_E(scv, 0x11, 0x10, 0xFF, 0x03FFF01E, PPC_NONE, PPC2_ISA300), +GEN_HANDLER_E(scv, 0x11, 0x00, 0xFF, 0x03FFF01E, PPC_NONE, PPC2_ISA300), +GEN_HANDLER_E(rfscv, 0x13, 0x12, 0x02, 0x03FF8001, PPC_NONE, PPC2_ISA300), +#endif GEN_HANDLER_E(stop, 0x13, 0x12, 0x0b, 0x03FFF801, PPC_NONE, PPC2_ISA300), GEN_HANDLER_E(doze, 0x13, 0x12, 0x0c, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206), GEN_HANDLER_E(nap, 0x13, 0x12, 0x0d, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206), @@ -7056,7 +7139,9 @@ GEN_HANDLER_E(sleep, 0x13, 0x12, 0x0e, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206), GEN_HANDLER_E(rvwinkle, 0x13, 0x12, 0x0f, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206), GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H), #endif -GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW), +/* Top bit of opc2 corresponds with low bit of LEV, so use two handlers */ +GEN_HANDLER(sc, 0x11, 0x11, 0xFF, 0x03FFF01D, PPC_FLOW), +GEN_HANDLER(sc, 0x11, 0x01, 0xFF, 0x03FFF01D, PPC_FLOW), GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW), GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW), #if defined(TARGET_PPC64) @@ -7542,19 +7627,19 @@ GEN_HANDLER2_E(treclaim, "treclaim", 0x1F, 0x0E, 0x1D, 0x03E0F800, \ GEN_HANDLER2_E(trechkpt, "trechkpt", 0x1F, 0x0E, 0x1F, 0x03FFF800, \ PPC_NONE, PPC2_TM), -#include "translate/fp-ops.inc.c" +#include "translate/fp-ops.c.inc" -#include "translate/vmx-ops.inc.c" +#include "translate/vmx-ops.c.inc" -#include "translate/vsx-ops.inc.c" +#include "translate/vsx-ops.c.inc" -#include "translate/dfp-ops.inc.c" +#include "translate/dfp-ops.c.inc" -#include "translate/spe-ops.inc.c" +#include "translate/spe-ops.c.inc" }; #include "helper_regs.h" -#include "translate_init.inc.c" +#include "translate_init.c.inc" /*****************************************************************************/ /* Misc PowerPC helpers */ @@ -7835,6 +7920,12 @@ static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) } else { ctx->vsx_enabled = false; } + if ((env->flags & POWERPC_FLAG_SCV) + && (env->spr[SPR_FSCR] & (1ull << FSCR_SCV))) { + ctx->scv_enabled = true; + } else { + ctx->scv_enabled = false; + } #if defined(TARGET_PPC64) if ((env->flags & POWERPC_FLAG_TM) && msr_tm) { ctx->tm_enabled = !!msr_tm; diff --git a/target/ppc/translate/dfp-impl.inc.c b/target/ppc/translate/dfp-impl.c.inc similarity index 100% rename from target/ppc/translate/dfp-impl.inc.c rename to target/ppc/translate/dfp-impl.c.inc diff --git a/target/ppc/translate/dfp-ops.inc.c b/target/ppc/translate/dfp-ops.c.inc similarity index 100% rename from target/ppc/translate/dfp-ops.inc.c rename to target/ppc/translate/dfp-ops.c.inc diff --git a/target/ppc/translate/fp-impl.inc.c b/target/ppc/translate/fp-impl.c.inc similarity index 100% rename from target/ppc/translate/fp-impl.inc.c rename to target/ppc/translate/fp-impl.c.inc diff --git a/target/ppc/translate/fp-ops.inc.c b/target/ppc/translate/fp-ops.c.inc similarity index 100% rename from target/ppc/translate/fp-ops.inc.c rename to target/ppc/translate/fp-ops.c.inc diff --git a/target/ppc/translate/spe-impl.inc.c b/target/ppc/translate/spe-impl.c.inc similarity index 96% rename from target/ppc/translate/spe-impl.inc.c rename to target/ppc/translate/spe-impl.c.inc index 36b4d5654d30da9693b05ce34c400bed4e86b70a..2e6e799a2542db988dc743d9663a7a3e20afbb91 100644 --- a/target/ppc/translate/spe-impl.inc.c +++ b/target/ppc/translate/spe-impl.c.inc @@ -349,14 +349,24 @@ static inline void gen_evmergelohi(DisasContext *ctx) } static inline void gen_evsplati(DisasContext *ctx) { - uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27; + uint64_t imm; + if (unlikely(!ctx->spe_enabled)) { + gen_exception(ctx, POWERPC_EXCP_SPEU); + return; + } + imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27; tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], imm); tcg_gen_movi_tl(cpu_gprh[rD(ctx->opcode)], imm); } static inline void gen_evsplatfi(DisasContext *ctx) { - uint64_t imm = rA(ctx->opcode) << 27; + uint64_t imm; + if (unlikely(!ctx->spe_enabled)) { + gen_exception(ctx, POWERPC_EXCP_SPEU); + return; + } + imm = rA(ctx->opcode) << 27; tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], imm); tcg_gen_movi_tl(cpu_gprh[rD(ctx->opcode)], imm); @@ -389,21 +399,37 @@ static inline void gen_evsel(DisasContext *ctx) static void gen_evsel0(DisasContext *ctx) { + if (unlikely(!ctx->spe_enabled)) { + gen_exception(ctx, POWERPC_EXCP_SPEU); + return; + } gen_evsel(ctx); } static void gen_evsel1(DisasContext *ctx) { + if (unlikely(!ctx->spe_enabled)) { + gen_exception(ctx, POWERPC_EXCP_SPEU); + return; + } gen_evsel(ctx); } static void gen_evsel2(DisasContext *ctx) { + if (unlikely(!ctx->spe_enabled)) { + gen_exception(ctx, POWERPC_EXCP_SPEU); + return; + } gen_evsel(ctx); } static void gen_evsel3(DisasContext *ctx) { + if (unlikely(!ctx->spe_enabled)) { + gen_exception(ctx, POWERPC_EXCP_SPEU); + return; + } gen_evsel(ctx); } @@ -518,6 +544,11 @@ static inline void gen_evmwsmia(DisasContext *ctx) { TCGv_i64 tmp; + if (unlikely(!ctx->spe_enabled)) { + gen_exception(ctx, POWERPC_EXCP_SPEU); + return; + } + gen_evmwsmi(ctx); /* rD := rA * rB */ tmp = tcg_temp_new_i64(); @@ -531,8 +562,13 @@ static inline void gen_evmwsmia(DisasContext *ctx) static inline void gen_evmwsmiaa(DisasContext *ctx) { - TCGv_i64 acc = tcg_temp_new_i64(); - TCGv_i64 tmp = tcg_temp_new_i64(); + TCGv_i64 acc; + TCGv_i64 tmp; + + if (unlikely(!ctx->spe_enabled)) { + gen_exception(ctx, POWERPC_EXCP_SPEU); + return; + } gen_evmwsmi(ctx); /* rD := rA * rB */ @@ -892,8 +928,14 @@ static inline void gen_##name(DisasContext *ctx) \ #define GEN_SPEFPUOP_CONV_32_64(name) \ static inline void gen_##name(DisasContext *ctx) \ { \ - TCGv_i64 t0 = tcg_temp_new_i64(); \ - TCGv_i32 t1 = tcg_temp_new_i32(); \ + TCGv_i64 t0; \ + TCGv_i32 t1; \ + if (unlikely(!ctx->spe_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ + return; \ + } \ + t0 = tcg_temp_new_i64(); \ + t1 = tcg_temp_new_i32(); \ gen_load_gpr64(t0, rB(ctx->opcode)); \ gen_helper_##name(t1, cpu_env, t0); \ tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1); \ @@ -903,8 +945,14 @@ static inline void gen_##name(DisasContext *ctx) \ #define GEN_SPEFPUOP_CONV_64_32(name) \ static inline void gen_##name(DisasContext *ctx) \ { \ - TCGv_i64 t0 = tcg_temp_new_i64(); \ - TCGv_i32 t1 = tcg_temp_new_i32(); \ + TCGv_i64 t0; \ + TCGv_i32 t1; \ + if (unlikely(!ctx->spe_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ + return; \ + } \ + t0 = tcg_temp_new_i64(); \ + t1 = tcg_temp_new_i32(); \ tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \ gen_helper_##name(t0, cpu_env, t1); \ gen_store_gpr64(rD(ctx->opcode), t0); \ @@ -914,7 +962,12 @@ static inline void gen_##name(DisasContext *ctx) \ #define GEN_SPEFPUOP_CONV_64_64(name) \ static inline void gen_##name(DisasContext *ctx) \ { \ - TCGv_i64 t0 = tcg_temp_new_i64(); \ + TCGv_i64 t0; \ + if (unlikely(!ctx->spe_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ + return; \ + } \ + t0 = tcg_temp_new_i64(); \ gen_load_gpr64(t0, rB(ctx->opcode)); \ gen_helper_##name(t0, cpu_env, t0); \ gen_store_gpr64(rD(ctx->opcode), t0); \ @@ -923,13 +976,8 @@ static inline void gen_##name(DisasContext *ctx) \ #define GEN_SPEFPUOP_ARITH2_32_32(name) \ static inline void gen_##name(DisasContext *ctx) \ { \ - TCGv_i32 t0, t1; \ - if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_SPEU); \ - return; \ - } \ - t0 = tcg_temp_new_i32(); \ - t1 = tcg_temp_new_i32(); \ + TCGv_i32 t0 = tcg_temp_new_i32(); \ + TCGv_i32 t1 = tcg_temp_new_i32(); \ tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \ tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \ gen_helper_##name(t0, cpu_env, t0, t1); \ @@ -958,13 +1006,8 @@ static inline void gen_##name(DisasContext *ctx) \ #define GEN_SPEFPUOP_COMP_32(name) \ static inline void gen_##name(DisasContext *ctx) \ { \ - TCGv_i32 t0, t1; \ - if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_SPEU); \ - return; \ - } \ - t0 = tcg_temp_new_i32(); \ - t1 = tcg_temp_new_i32(); \ + TCGv_i32 t0 = tcg_temp_new_i32(); \ + TCGv_i32 t1 = tcg_temp_new_i32(); \ \ tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \ tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \ @@ -1074,28 +1117,16 @@ GEN_SPEFPUOP_ARITH2_32_32(efsmul); GEN_SPEFPUOP_ARITH2_32_32(efsdiv); static inline void gen_efsabs(DisasContext *ctx) { - if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_SPEU); - return; - } tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL); } static inline void gen_efsnabs(DisasContext *ctx) { - if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_SPEU); - return; - } tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000); } static inline void gen_efsneg(DisasContext *ctx) { - if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_SPEU); - return; - } tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000); } diff --git a/target/ppc/translate/spe-ops.inc.c b/target/ppc/translate/spe-ops.c.inc similarity index 100% rename from target/ppc/translate/spe-ops.inc.c rename to target/ppc/translate/spe-ops.c.inc diff --git a/target/ppc/translate/vmx-impl.inc.c b/target/ppc/translate/vmx-impl.c.inc similarity index 99% rename from target/ppc/translate/vmx-impl.inc.c rename to target/ppc/translate/vmx-impl.c.inc index 403ed3a01c27703159e7e77f0febf7f36b79ce6d..92b9527aff35dc4ca37e20edc8c58517c1a3e66c 100644 --- a/target/ppc/translate/vmx-impl.inc.c +++ b/target/ppc/translate/vmx-impl.c.inc @@ -801,18 +801,27 @@ static void trans_vclzd(DisasContext *ctx) GEN_VXFORM(vmuloub, 4, 0); GEN_VXFORM(vmulouh, 4, 1); GEN_VXFORM(vmulouw, 4, 2); -GEN_VXFORM(vmuluwm, 4, 2); +GEN_VXFORM_V(vmuluwm, MO_32, tcg_gen_gvec_mul, 4, 2); GEN_VXFORM_DUAL(vmulouw, PPC_ALTIVEC, PPC_NONE, vmuluwm, PPC_NONE, PPC2_ALTIVEC_207) GEN_VXFORM(vmulosb, 4, 4); GEN_VXFORM(vmulosh, 4, 5); GEN_VXFORM(vmulosw, 4, 6); +GEN_VXFORM_V(vmulld, MO_64, tcg_gen_gvec_mul, 4, 7); GEN_VXFORM(vmuleub, 4, 8); GEN_VXFORM(vmuleuh, 4, 9); GEN_VXFORM(vmuleuw, 4, 10); +GEN_VXFORM(vmulhuw, 4, 10); +GEN_VXFORM(vmulhud, 4, 11); +GEN_VXFORM_DUAL(vmuleuw, PPC_ALTIVEC, PPC_NONE, + vmulhuw, PPC_NONE, PPC2_ISA310); GEN_VXFORM(vmulesb, 4, 12); GEN_VXFORM(vmulesh, 4, 13); GEN_VXFORM(vmulesw, 4, 14); +GEN_VXFORM(vmulhsw, 4, 14); +GEN_VXFORM_DUAL(vmulesw, PPC_ALTIVEC, PPC_NONE, + vmulhsw, PPC_NONE, PPC2_ISA310); +GEN_VXFORM(vmulhsd, 4, 15); GEN_VXFORM_V(vslb, MO_8, tcg_gen_gvec_shlv, 2, 4); GEN_VXFORM_V(vslh, MO_16, tcg_gen_gvec_shlv, 2, 5); GEN_VXFORM_V(vslw, MO_32, tcg_gen_gvec_shlv, 2, 6); @@ -900,13 +909,13 @@ GEN_VXFORM3(vsubeuqm, 31, 0); GEN_VXFORM3(vsubecuq, 31, 0); GEN_VXFORM_DUAL(vsubeuqm, PPC_NONE, PPC2_ALTIVEC_207, \ vsubecuq, PPC_NONE, PPC2_ALTIVEC_207) -GEN_VXFORM(vrlb, 2, 0); -GEN_VXFORM(vrlh, 2, 1); -GEN_VXFORM(vrlw, 2, 2); +GEN_VXFORM_V(vrlb, MO_8, tcg_gen_gvec_rotlv, 2, 0); +GEN_VXFORM_V(vrlh, MO_16, tcg_gen_gvec_rotlv, 2, 1); +GEN_VXFORM_V(vrlw, MO_32, tcg_gen_gvec_rotlv, 2, 2); GEN_VXFORM(vrlwmi, 2, 2); GEN_VXFORM_DUAL(vrlw, PPC_ALTIVEC, PPC_NONE, \ vrlwmi, PPC_NONE, PPC2_ISA300) -GEN_VXFORM(vrld, 2, 3); +GEN_VXFORM_V(vrld, MO_64, tcg_gen_gvec_rotlv, 2, 3); GEN_VXFORM(vrldmi, 2, 3); GEN_VXFORM_DUAL(vrld, PPC_NONE, PPC2_ALTIVEC_207, \ vrldmi, PPC_NONE, PPC2_ISA300) diff --git a/target/ppc/translate/vmx-ops.inc.c b/target/ppc/translate/vmx-ops.c.inc similarity index 97% rename from target/ppc/translate/vmx-ops.inc.c rename to target/ppc/translate/vmx-ops.c.inc index 84e05fb827d15113f04a052dd166c2a8e19a80ba..f3f485511127f50dba5765c6329d9ad171a70f9e 100644 --- a/target/ppc/translate/vmx-ops.inc.c +++ b/target/ppc/translate/vmx-ops.c.inc @@ -48,6 +48,9 @@ GEN_HANDLER_E(name, 0x04, opc2, opc3, inval, PPC_NONE, PPC2_ISA300) GEN_HANDLER_E_2(name, 0x04, opc2, opc3, opc4, 0x00000000, PPC_NONE, \ PPC2_ISA300) +#define GEN_VXFORM_310(name, opc2, opc3) \ +GEN_HANDLER_E(name, 0x04, opc2, opc3, 0x00000000, PPC_NONE, PPC2_ISA310) + #define GEN_VXFORM_DUAL(name0, name1, opc2, opc3, type0, type1) \ GEN_HANDLER_E(name0##_##name1, 0x4, opc2, opc3, 0x00000000, type0, type1) @@ -104,12 +107,15 @@ GEN_VXFORM_DUAL(vmulouw, vmuluwm, 4, 2, PPC_ALTIVEC, PPC_NONE), GEN_VXFORM(vmulosb, 4, 4), GEN_VXFORM(vmulosh, 4, 5), GEN_VXFORM_207(vmulosw, 4, 6), +GEN_VXFORM_310(vmulld, 4, 7), GEN_VXFORM(vmuleub, 4, 8), GEN_VXFORM(vmuleuh, 4, 9), -GEN_VXFORM_207(vmuleuw, 4, 10), +GEN_VXFORM_DUAL(vmuleuw, vmulhuw, 4, 10, PPC_ALTIVEC, PPC_NONE), +GEN_VXFORM_310(vmulhud, 4, 11), GEN_VXFORM(vmulesb, 4, 12), GEN_VXFORM(vmulesh, 4, 13), -GEN_VXFORM_207(vmulesw, 4, 14), +GEN_VXFORM_DUAL(vmulesw, vmulhsw, 4, 14, PPC_ALTIVEC, PPC_NONE), +GEN_VXFORM_310(vmulhsd, 4, 15), GEN_VXFORM(vslb, 2, 4), GEN_VXFORM(vslh, 2, 5), GEN_VXFORM_DUAL(vslw, vrlwnm, 2, 6, PPC_ALTIVEC, PPC_NONE), diff --git a/target/ppc/translate/vsx-impl.inc.c b/target/ppc/translate/vsx-impl.c.inc similarity index 99% rename from target/ppc/translate/vsx-impl.inc.c rename to target/ppc/translate/vsx-impl.c.inc index b518de46db8e305b4d511cc789323d64fa3a32da..075f063e9848cfd4421a68a16f6540af61aaf6fd 100644 --- a/target/ppc/translate/vsx-impl.inc.c +++ b/target/ppc/translate/vsx-impl.c.inc @@ -139,6 +139,36 @@ static void gen_lxvw4x(DisasContext *ctx) tcg_temp_free_i64(xtl); } +static void gen_lxvwsx(DisasContext *ctx) +{ + TCGv EA; + TCGv_i32 data; + + if (xT(ctx->opcode) < 32) { + if (unlikely(!ctx->vsx_enabled)) { + gen_exception(ctx, POWERPC_EXCP_VSXU); + return; + } + } else { + if (unlikely(!ctx->altivec_enabled)) { + gen_exception(ctx, POWERPC_EXCP_VPU); + return; + } + } + + gen_set_access_type(ctx, ACCESS_INT); + EA = tcg_temp_new(); + + gen_addr_reg_index(ctx, EA); + + data = tcg_temp_new_i32(); + tcg_gen_qemu_ld_i32(data, EA, ctx->mem_idx, MO_TEUL); + tcg_gen_gvec_dup_i32(MO_UL, vsr_full_offset(xT(ctx->opcode)), 16, 16, data); + + tcg_temp_free(EA); + tcg_temp_free_i32(data); +} + static void gen_bswap16x8(TCGv_i64 outh, TCGv_i64 outl, TCGv_i64 inh, TCGv_i64 inl) { diff --git a/target/ppc/translate/vsx-ops.inc.c b/target/ppc/translate/vsx-ops.c.inc similarity index 99% rename from target/ppc/translate/vsx-ops.inc.c rename to target/ppc/translate/vsx-ops.c.inc index 7fd3942b843da5fd418f5b0695acb5a30e217480..1d41beef26a17c389d8951ed67e015230d8facd5 100644 --- a/target/ppc/translate/vsx-ops.inc.c +++ b/target/ppc/translate/vsx-ops.c.inc @@ -5,6 +5,7 @@ GEN_HANDLER_E(lxsibzx, 0x1F, 0x0D, 0x18, 0, PPC_NONE, PPC2_ISA300), GEN_HANDLER_E(lxsihzx, 0x1F, 0x0D, 0x19, 0, PPC_NONE, PPC2_ISA300), GEN_HANDLER_E(lxsspx, 0x1F, 0x0C, 0x10, 0, PPC_NONE, PPC2_VSX207), GEN_HANDLER_E(lxvd2x, 0x1F, 0x0C, 0x1A, 0, PPC_NONE, PPC2_VSX), +GEN_HANDLER_E(lxvwsx, 0x1F, 0x0C, 0x0B, 0, PPC_NONE, PPC2_ISA300), GEN_HANDLER_E(lxvdsx, 0x1F, 0x0C, 0x0A, 0, PPC_NONE, PPC2_VSX), GEN_HANDLER_E(lxvw4x, 0x1F, 0x0C, 0x18, 0, PPC_NONE, PPC2_VSX), GEN_HANDLER_E(lxvh8x, 0x1F, 0x0C, 0x19, 0, PPC_NONE, PPC2_ISA300), diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.c.inc similarity index 99% rename from target/ppc/translate_init.inc.c rename to target/ppc/translate_init.c.inc index d8adc1bd49ba80694d2165548b686c8a302197c0..78cc8f043b92f88f593822fe7fd4202fc5b118d7 100644 --- a/target/ppc/translate_init.inc.c +++ b/target/ppc/translate_init.c.inc @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -284,12 +284,24 @@ static void spr_write_atbu(DisasContext *ctx, int sprn, int gprn) ATTRIBUTE_UNUSED static void spr_read_purr(DisasContext *ctx, int gprn, int sprn) { + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_io_start(); + } gen_helper_load_purr(cpu_gpr[gprn], cpu_env); + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_stop_exception(ctx); + } } static void spr_write_purr(DisasContext *ctx, int sprn, int gprn) { + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_io_start(); + } gen_helper_store_purr(cpu_env, cpu_gpr[gprn]); + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_stop_exception(ctx); + } } /* HDECR */ @@ -319,17 +331,35 @@ static void spr_write_hdecr(DisasContext *ctx, int sprn, int gprn) static void spr_read_vtb(DisasContext *ctx, int gprn, int sprn) { + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_io_start(); + } gen_helper_load_vtb(cpu_gpr[gprn], cpu_env); + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_stop_exception(ctx); + } } static void spr_write_vtb(DisasContext *ctx, int sprn, int gprn) { + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_io_start(); + } gen_helper_store_vtb(cpu_env, cpu_gpr[gprn]); + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_stop_exception(ctx); + } } static void spr_write_tbu40(DisasContext *ctx, int sprn, int gprn) { + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_io_start(); + } gen_helper_store_tbu40(cpu_env, cpu_gpr[gprn]); + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_stop_exception(ctx); + } } #endif @@ -762,7 +792,7 @@ static void gen_spr_generic(CPUPPCState *env) &spr_read_xer, &spr_write_xer, &spr_read_xer, &spr_write_xer, 0x00000000); - /* Branch contol */ + /* Branch control */ spr_register(env, SPR_LR, "LR", &spr_read_lr, &spr_write_lr, &spr_read_lr, &spr_write_lr, @@ -3382,6 +3412,7 @@ static void init_excp_POWER9(CPUPPCState *env) #if !defined(CONFIG_USER_ONLY) env->excp_vectors[POWERPC_EXCP_HVIRT] = 0x00000EA0; + env->excp_vectors[POWERPC_EXCP_SYSCALL_VECTORED] = 0x00000000; #endif } @@ -9030,7 +9061,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data) pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE | POWERPC_FLAG_BE | POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR | - POWERPC_FLAG_VSX | POWERPC_FLAG_TM; + POWERPC_FLAG_VSX | POWERPC_FLAG_TM | POWERPC_FLAG_SCV; pcc->l1_dcache_size = 0x8000; pcc->l1_icache_size = 0x8000; pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr; @@ -9085,11 +9116,6 @@ static void init_proc_POWER10(CPUPPCState *env) gen_spr_power8_rpr(env); gen_spr_power9_mmu(env); - /* POWER9 Specific registers */ - spr_register_kvm(env, SPR_TIDR, "TIDR", NULL, NULL, - spr_read_generic, spr_write_generic, - KVM_REG_PPC_TIDR, 0); - /* FIXME: Filter fields properly based on privilege level */ spr_register_kvm_hv(env, SPR_PSSCR, "PSSCR", NULL, NULL, NULL, NULL, spr_read_generic, spr_write_generic, @@ -9205,7 +9231,7 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data) PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 | PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 | PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 | - PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL; + PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL | PPC2_ISA310; pcc->msr_mask = (1ull << MSR_SF) | (1ull << MSR_HV) | (1ull << MSR_TM) | @@ -10302,6 +10328,8 @@ static void ppc_cpu_unrealize(DeviceState *dev) pcc->parent_unrealize(dev); + cpu_remove_sync(CPU(cpu)); + for (i = 0; i < PPC_CPU_OPCODES_LEN; i++) { if (cpu->opcodes[i] == &invalid_handler) { continue; @@ -10452,7 +10480,7 @@ static void ppc_cpu_parse_featurestr(const char *type, char *features, return; } - if (object_property_find(machine, "max-cpu-compat", NULL)) { + if (object_property_find(machine, "max-cpu-compat")) { int i; char **inpieces; char *s = features; @@ -10486,7 +10514,7 @@ static void ppc_cpu_parse_featurestr(const char *type, char *features, if (compat_str) { char *v = compat_str + strlen("compat="); - object_property_set_str(machine, v, "max-cpu-compat", &local_err); + object_property_set_str(machine, "max-cpu-compat", v, &local_err); } g_strfreev(inpieces); if (local_err) { @@ -10934,6 +10962,7 @@ static const TypeInfo ppc_cpu_type_info = { .name = TYPE_POWERPC_CPU, .parent = TYPE_CPU, .instance_size = sizeof(PowerPCCPU), + .instance_align = __alignof__(PowerPCCPU), .instance_init = ppc_cpu_instance_init, .instance_finalize = ppc_cpu_instance_finalize, .abstract = true, @@ -10941,16 +10970,20 @@ static const TypeInfo ppc_cpu_type_info = { .class_init = ppc_cpu_class_init, }; +#ifndef CONFIG_USER_ONLY static const TypeInfo ppc_vhyp_type_info = { .name = TYPE_PPC_VIRTUAL_HYPERVISOR, .parent = TYPE_INTERFACE, .class_size = sizeof(PPCVirtualHypervisorClass), }; +#endif static void ppc_cpu_register_types(void) { type_register_static(&ppc_cpu_type_info); +#ifndef CONFIG_USER_ONLY type_register_static(&ppc_vhyp_type_info); +#endif } type_init(ppc_cpu_register_types) diff --git a/target/ppc/user_only_helper.c b/target/ppc/user_only_helper.c index 683c03390d7129347ade26c1e8f6b22e31ce3a8e..aa3f8675963169b9102c8fc69979a9c8b703208c 100644 --- a/target/ppc/user_only_helper.c +++ b/target/ppc/user_only_helper.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs deleted file mode 100644 index 7ea8f4c3da197c869461cf60cd4ff0e31bbb7734..0000000000000000000000000000000000000000 --- a/target/riscv/Makefile.objs +++ /dev/null @@ -1,29 +0,0 @@ -obj-y += translate.o op_helper.o cpu_helper.o cpu.o csr.o fpu_helper.o gdbstub.o -obj-$(CONFIG_SOFTMMU) += pmp.o -obj-$(CONFIG_KVM) += kvm.o - -ifeq ($(CONFIG_SOFTMMU),y) -obj-y += monitor.o -endif - -DECODETREE = $(SRC_PATH)/scripts/decodetree.py - -decode32-y = $(SRC_PATH)/target/riscv/insn32.decode -decode32-$(TARGET_RISCV64) += $(SRC_PATH)/target/riscv/insn32-64.decode - -decode16-y = $(SRC_PATH)/target/riscv/insn16.decode -decode16-$(TARGET_RISCV32) += $(SRC_PATH)/target/riscv/insn16-32.decode -decode16-$(TARGET_RISCV64) += $(SRC_PATH)/target/riscv/insn16-64.decode - -target/riscv/decode_insn32.inc.c: $(decode32-y) $(DECODETREE) - $(call quiet-command, \ - $(PYTHON) $(DECODETREE) -o $@ --static-decode decode_insn32 \ - $(decode32-y), "GEN", $(TARGET_DIR)$@) - -target/riscv/decode_insn16.inc.c: $(decode16-y) $(DECODETREE) - $(call quiet-command, \ - $(PYTHON) $(DECODETREE) -o $@ --static-decode decode_insn16 \ - --insnwidth 16 $(decode16-y), "GEN", $(TARGET_DIR)$@) - -target/riscv/translate.o: target/riscv/decode_insn32.inc.c \ - target/riscv/decode_insn16.inc.c diff --git a/target/riscv/cpu-param.h b/target/riscv/cpu-param.h index 664fc1d371a4fd098bfea4e325e9278db90e7874..80eb615f93f49f3870559c691dfcb5a795610c82 100644 --- a/target/riscv/cpu-param.h +++ b/target/riscv/cpu-param.h @@ -18,6 +18,15 @@ # define TARGET_VIRT_ADDR_SPACE_BITS 32 /* sv32 */ #endif #define TARGET_PAGE_BITS 12 /* 4 KiB Pages */ -#define NB_MMU_MODES 4 +/* + * The current MMU Modes are: + * - U mode 0b000 + * - S mode 0b001 + * - M mode 0b011 + * - U mode HLV/HLVX/HSV 0b100 + * - S mode HLV/HLVX/HSV 0b101 + * - M mode HLV/HLVX/HSV 0b111 + */ +#define NB_MMU_MODES 8 #endif diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 9891d4012b43b6c34fcbab831bfed326ddb823a7..439dc89ee754f686cb7ced3337fb69e7be758339 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -22,11 +22,12 @@ #include "qemu/ctype.h" #include "qemu/log.h" #include "cpu.h" +#include "internals.h" #include "exec/exec-all.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "hw/qdev-properties.h" -#include "migration/cpu.h" +#include "migration/vmstate.h" #include "fpu/softfloat-helpers.h" #include "kvm_riscv.h" @@ -97,6 +98,17 @@ const char * const riscv_intr_names[] = { "reserved" }; +const char *riscv_cpu_get_trap_name(target_ulong cause, bool async) +{ + if (async) { + return (cause < ARRAY_SIZE(riscv_intr_names)) ? + riscv_intr_names[cause] : "(unknown)"; + } else { + return (cause < ARRAY_SIZE(riscv_excp_names)) ? + riscv_excp_names[cause] : "(unknown)"; + } +} + static void set_misa(CPURISCVState *env, target_ulong misa) { env->misa_mask = env->misa = misa; @@ -107,6 +119,11 @@ static void set_priv_version(CPURISCVState *env, int priv_ver) env->priv_ver = priv_ver; } +static void set_vext_version(CPURISCVState *env, int vext_ver) +{ + env->vext_ver = vext_ver; +} + static void set_feature(CPURISCVState *env, int feature) { env->features |= (1ULL << feature); @@ -124,80 +141,55 @@ static void riscv_any_cpu_init(Object *obj) CPURISCVState *env = &RISCV_CPU(obj)->env; set_misa(env, RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVU); set_priv_version(env, PRIV_VERSION_1_11_0); - set_resetvec(env, DEFAULT_RSTVEC); } -#if defined(TARGET_RISCV32) - -static void riscv_base32_cpu_init(Object *obj) +static void riscv_base_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; /* We set this in the realise function */ set_misa(env, 0); } -static void rv32gcsu_priv1_10_0_cpu_init(Object *obj) -{ - CPURISCVState *env = &RISCV_CPU(obj)->env; - set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); - set_priv_version(env, PRIV_VERSION_1_10_0); - set_resetvec(env, DEFAULT_RSTVEC); - set_feature(env, RISCV_FEATURE_MMU); - set_feature(env, RISCV_FEATURE_PMP); -} - -static void rv32imacu_nommu_cpu_init(Object *obj) +static void rvxx_sifive_u_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; - set_misa(env, RV32 | RVI | RVM | RVA | RVC | RVU); + set_misa(env, RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); set_priv_version(env, PRIV_VERSION_1_10_0); - set_resetvec(env, DEFAULT_RSTVEC); - set_feature(env, RISCV_FEATURE_PMP); } -static void rv32imafcu_nommu_cpu_init(Object *obj) +static void rvxx_sifive_e_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; - set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVC | RVU); + set_misa(env, RVXLEN | RVI | RVM | RVA | RVC | RVU); set_priv_version(env, PRIV_VERSION_1_10_0); - set_resetvec(env, DEFAULT_RSTVEC); - set_feature(env, RISCV_FEATURE_PMP); + qdev_prop_set_bit(DEVICE(obj), "mmu", false); } -#elif defined(TARGET_RISCV64) - -static void riscv_base64_cpu_init(Object *obj) -{ - CPURISCVState *env = &RISCV_CPU(obj)->env; - /* We set this in the realise function */ - set_misa(env, 0); -} +#if defined(TARGET_RISCV32) -static void rv64gcsu_priv1_10_0_cpu_init(Object *obj) +static void rv32_ibex_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; - set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); + set_misa(env, RV32 | RVI | RVM | RVC | RVU); set_priv_version(env, PRIV_VERSION_1_10_0); - set_resetvec(env, DEFAULT_RSTVEC); - set_feature(env, RISCV_FEATURE_MMU); - set_feature(env, RISCV_FEATURE_PMP); + qdev_prop_set_bit(DEVICE(obj), "mmu", false); } -static void rv64imacu_nommu_cpu_init(Object *obj) +static void rv32_imafcu_nommu_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; - set_misa(env, RV64 | RVI | RVM | RVA | RVC | RVU); + set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVC | RVU); set_priv_version(env, PRIV_VERSION_1_10_0); set_resetvec(env, DEFAULT_RSTVEC); - set_feature(env, RISCV_FEATURE_PMP); + qdev_prop_set_bit(DEVICE(obj), "mmu", false); } +#endif + static void riscv_host_cpu_init(Object *obj) { } -#endif - static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model) { ObjectClass *oc; @@ -230,13 +222,15 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags) qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc ", env->pc); #ifndef CONFIG_USER_ONLY qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus); + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", (target_ulong)env->mstatus); #ifdef TARGET_RISCV32 - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatush ", env->mstatush); + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatush ", + (target_ulong)(env->mstatus >> 32)); #endif if (riscv_has_ext(env, RVH)) { qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", env->vsstatus); + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", + (target_ulong)env->vsstatus); } qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip ", env->mip); qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie ", env->mie); @@ -362,6 +356,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) CPURISCVState *env = &cpu->env; RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev); int priv_version = PRIV_VERSION_1_11_0; + int vext_version = VEXT_VERSION_0_07_1; target_ulong target_misa = 0; Error *local_err = NULL; @@ -385,7 +380,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) } set_priv_version(env, priv_version); - set_resetvec(env, DEFAULT_RSTVEC); + set_vext_version(env, vext_version); if (cpu->cfg.mmu) { set_feature(env, RISCV_FEATURE_MMU); @@ -395,6 +390,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) set_feature(env, RISCV_FEATURE_PMP); } + set_resetvec(env, cpu->cfg.resetvec); + /* If misa isn't set (rv32 and rv64 machines) set it here */ if (!env->misa) { /* Do some ISA extension error checking */ @@ -452,6 +449,45 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) if (cpu->cfg.ext_h) { target_misa |= RVH; } + if (cpu->cfg.ext_v) { + target_misa |= RVV; + if (!is_power_of_2(cpu->cfg.vlen)) { + error_setg(errp, + "Vector extension VLEN must be power of 2"); + return; + } + if (cpu->cfg.vlen > RV_VLEN_MAX || cpu->cfg.vlen < 128) { + error_setg(errp, + "Vector extension implementation only supports VLEN " + "in the range [128, %d]", RV_VLEN_MAX); + return; + } + if (!is_power_of_2(cpu->cfg.elen)) { + error_setg(errp, + "Vector extension ELEN must be power of 2"); + return; + } + if (cpu->cfg.elen > 64 || cpu->cfg.vlen < 8) { + error_setg(errp, + "Vector extension implementation only supports ELEN " + "in the range [8, 64]"); + return; + } + if (cpu->cfg.vext_spec) { + if (!g_strcmp0(cpu->cfg.vext_spec, "v0.7.1")) { + vext_version = VEXT_VERSION_0_07_1; + } else { + error_setg(errp, + "Unsupported vector spec version '%s'", + cpu->cfg.vext_spec); + return; + } + } else { + qemu_log("vector verison is not specified, " + "use the default value v0.7.1\n"); + } + set_vext_version(env, vext_version); + } set_misa(env, RVXLEN | target_misa); } @@ -471,38 +507,6 @@ static void riscv_cpu_init(Object *obj) cpu_set_cpustate_pointers(cpu); } -static int cpu_post_load(void *opaque, int version_id) -{ - RISCVCPU *cpu = opaque; - cpu->env.kvm_timer_dirty = true; - return 0; -} - -static const VMStateDescription vmstate_riscv_cpu = { - .name = "cpu", - .version_id = 1, - .minimum_version_id = 1, - .post_load = cpu_post_load, - .fields = (VMStateField[]) { - VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32), - VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32), - VMSTATE_UINTTL(env.pc, RISCVCPU), - VMSTATE_UINTTL(env.mstatus, RISCVCPU), - VMSTATE_UINTTL(env.mie, RISCVCPU), - VMSTATE_UINTTL(env.stvec, RISCVCPU), - VMSTATE_UINTTL(env.sscratch, RISCVCPU), - VMSTATE_UINTTL(env.sepc, RISCVCPU), - VMSTATE_UINTTL(env.scause, RISCVCPU), - VMSTATE_UINTTL(env.sbadaddr, RISCVCPU), - VMSTATE_UINTTL(env.mip, RISCVCPU), - VMSTATE_UINTTL(env.satp, RISCVCPU), - VMSTATE_UINT64(env.kvm_timer_time, RISCVCPU), - VMSTATE_UINT64(env.kvm_timer_compare, RISCVCPU), - VMSTATE_UINT64(env.kvm_timer_state, RISCVCPU), - VMSTATE_END_OF_LIST() - } -}; - static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("i", RISCVCPU, cfg.ext_i, true), DEFINE_PROP_BOOL("e", RISCVCPU, cfg.ext_e, false), @@ -516,12 +520,17 @@ static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true), /* This is experimental so mark with 'x-' */ DEFINE_PROP_BOOL("x-h", RISCVCPU, cfg.ext_h, false), + DEFINE_PROP_BOOL("x-v", RISCVCPU, cfg.ext_v, false), DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true), DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec), + DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec), + DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128), + DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64), DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true), DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true), + DEFINE_PROP_UINT64("resetvec", RISCVCPU, cfg.resetvec, DEFAULT_RSTVEC), DEFINE_PROP_END_OF_LIST(), }; @@ -557,13 +566,13 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data) cc->do_transaction_failed = riscv_cpu_do_transaction_failed; cc->do_unaligned_access = riscv_cpu_do_unaligned_access; cc->get_phys_page_debug = riscv_cpu_get_phys_page_debug; + /* For now, mark unmigratable: */ + cc->vmsd = &vmstate_riscv_cpu; #endif #ifdef CONFIG_TCG cc->tcg_initialize = riscv_translate_init; cc->tlb_fill = riscv_cpu_tlb_fill; #endif - /* For now, mark unmigratable: */ - cc->vmsd = &vmstate_riscv_cpu; device_class_set_props(dc, riscv_cpu_properties); } @@ -623,6 +632,7 @@ static const TypeInfo riscv_cpu_type_infos[] = { .name = TYPE_RISCV_CPU, .parent = TYPE_CPU, .instance_size = sizeof(RISCVCPU), + .instance_align = __alignof__(RISCVCPU), .instance_init = riscv_cpu_init, .abstract = true, .class_size = sizeof(RISCVCPUClass), @@ -630,15 +640,16 @@ static const TypeInfo riscv_cpu_type_infos[] = { }, DEFINE_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init), #if defined(TARGET_RISCV32) - DEFINE_CPU(TYPE_RISCV_CPU_BASE32, riscv_base32_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32imacu_nommu_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34, rv32imafcu_nommu_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32gcsu_priv1_10_0_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_BASE32, riscv_base_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_IBEX, rv32_ibex_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rvxx_sifive_e_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34, rv32_imafcu_nommu_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rvxx_sifive_u_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_HOST, riscv_host_cpu_init), #elif defined(TARGET_RISCV64) - DEFINE_CPU(TYPE_RISCV_CPU_BASE64, riscv_base64_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rv64imacu_nommu_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rv64gcsu_priv1_10_0_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_BASE64, riscv_base_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rvxx_sifive_e_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rvxx_sifive_u_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_HOST, riscv_host_cpu_init), #endif }; diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 315981ea1d69cda28644c6de26ab071b522b2dcb..16d6050ead45255d035472382683af9eca238b65 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -21,8 +21,10 @@ #define RISCV_CPU_H #include "hw/core/cpu.h" +#include "hw/registerfields.h" #include "exec/cpu-defs.h" #include "fpu/softfloat-types.h" +#include "qom/object.h" #define TCG_GUEST_DEFAULT_MO 0 @@ -35,6 +37,7 @@ #define TYPE_RISCV_CPU_ANY RISCV_CPU_TYPE_NAME("any") #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32") #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64") +#define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex") #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31") #define TYPE_RISCV_CPU_SIFIVE_E34 RISCV_CPU_TYPE_NAME("sifive-e34") #define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51") @@ -59,6 +62,7 @@ #define RVA RV('A') #define RVF RV('F') #define RVD RV('D') +#define RVV RV('V') #define RVC RV('C') #define RVS RV('S') #define RVU RV('U') @@ -77,11 +81,16 @@ enum { #define PRIV_VERSION_1_10_0 0x00011000 #define PRIV_VERSION_1_11_0 0x00011100 -#define TRANSLATE_PMP_FAIL 2 -#define TRANSLATE_FAIL 1 -#define TRANSLATE_SUCCESS 0 +#define VEXT_VERSION_0_07_1 0x00000701 + +enum { + TRANSLATE_SUCCESS, + TRANSLATE_FAIL, + TRANSLATE_PMP_FAIL, + TRANSLATE_G_STAGE_FAIL +}; + #define MMU_USER_IDX 3 -#define TRANSLATE_G_STAGE_FAIL 4 #define MAX_RISCV_PMPS (16) @@ -89,9 +98,26 @@ typedef struct CPURISCVState CPURISCVState; #include "pmp.h" +#define RV_VLEN_MAX 256 + +FIELD(VTYPE, VLMUL, 0, 2) +FIELD(VTYPE, VSEW, 2, 3) +FIELD(VTYPE, VEDIV, 5, 2) +FIELD(VTYPE, RESERVED, 7, sizeof(target_ulong) * 8 - 9) +FIELD(VTYPE, VILL, sizeof(target_ulong) * 8 - 1, 1) + struct CPURISCVState { target_ulong gpr[32]; uint64_t fpr[32]; /* assume both F and D extensions */ + + /* vector coprocessor state. */ + uint64_t vreg[32 * RV_VLEN_MAX / 64] QEMU_ALIGNED(16); + target_ulong vxrm; + target_ulong vxsat; + target_ulong vl; + target_ulong vstart; + target_ulong vtype; + target_ulong pc; target_ulong load_res; target_ulong load_val; @@ -102,6 +128,7 @@ struct CPURISCVState { target_ulong guest_phys_fault_addr; target_ulong priv_ver; + target_ulong vext_ver; target_ulong misa; target_ulong misa_mask; @@ -118,14 +145,14 @@ struct CPURISCVState { target_ulong resetvec; target_ulong mhartid; - target_ulong mstatus; + /* + * For RV32 this is 32-bit mstatus and 32-bit mstatush. + * For RV64 this is a 64-bit mstatus. + */ + uint64_t mstatus; target_ulong mip; -#ifdef TARGET_RISCV32 - target_ulong mstatush; -#endif - uint32_t miclaim; target_ulong mie; @@ -157,16 +184,17 @@ struct CPURISCVState { uint64_t htimedelta; /* Virtual CSRs */ - target_ulong vsstatus; + /* + * For RV32 this is 32-bit vsstatus and 32-bit vsstatush. + * For RV64 this is a 64-bit vsstatus. + */ + uint64_t vsstatus; target_ulong vstvec; target_ulong vsscratch; target_ulong vsepc; target_ulong vscause; target_ulong vstval; target_ulong vsatp; -#ifdef TARGET_RISCV32 - target_ulong vsstatush; -#endif target_ulong mtval2; target_ulong mtinst; @@ -178,10 +206,7 @@ struct CPURISCVState { target_ulong scause_hs; target_ulong stval_hs; target_ulong satp_hs; - target_ulong mstatus_hs; -#ifdef TARGET_RISCV32 - target_ulong mstatush_hs; -#endif + uint64_t mstatus_hs; target_ulong scounteren; target_ulong mcounteren; @@ -198,7 +223,8 @@ struct CPURISCVState { pmp_table_t pmp_state; /* machine specific rdtime callback */ - uint64_t (*rdtime_fn)(void); + uint64_t (*rdtime_fn)(uint32_t); + uint32_t rdtime_fn_arg; /* True if in debugger mode. */ bool debugger; @@ -209,8 +235,8 @@ struct CPURISCVState { /* Fields from here on are preserved across CPU reset. */ QEMUTimer *timer; /* Internal timer */ - hwaddr loader_start; - hwaddr fdt_start; + hwaddr kernel_addr; + hwaddr fdt_addr; /* kvm timer */ bool kvm_timer_dirty; @@ -219,12 +245,8 @@ struct CPURISCVState { uint64_t kvm_timer_state; }; -#define RISCV_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(RISCVCPUClass, (klass), TYPE_RISCV_CPU) -#define RISCV_CPU(obj) \ - OBJECT_CHECK(RISCVCPU, (obj), TYPE_RISCV_CPU) -#define RISCV_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(RISCVCPUClass, (obj), TYPE_RISCV_CPU) +OBJECT_DECLARE_TYPE(RISCVCPU, RISCVCPUClass, + RISCV_CPU) /** * RISCVCPUClass: @@ -233,13 +255,13 @@ struct CPURISCVState { * * A RISCV CPU model. */ -typedef struct RISCVCPUClass { +struct RISCVCPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ DeviceRealize parent_realize; DeviceReset parent_reset; -} RISCVCPUClass; +}; /** * RISCVCPU: @@ -247,7 +269,7 @@ typedef struct RISCVCPUClass { * * A RISCV CPU. */ -typedef struct RISCVCPU { +struct RISCVCPU { /*< private >*/ CPUState parent_obj; /*< public >*/ @@ -267,16 +289,21 @@ typedef struct RISCVCPU { bool ext_s; bool ext_u; bool ext_h; + bool ext_v; bool ext_counters; bool ext_ifencei; bool ext_icsr; char *priv_spec; char *user_spec; + char *vext_spec; + uint16_t vlen; + uint16_t elen; bool mmu; bool pmp; + uint64_t resetvec; } cfg; -} RISCVCPU; +}; static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext) { @@ -296,6 +323,7 @@ extern const char * const riscv_fpr_regnames[]; extern const char * const riscv_excp_names[]; extern const char * const riscv_intr_names[]; +const char *riscv_cpu_get_trap_name(target_ulong cause, bool async); void riscv_cpu_do_interrupt(CPUState *cpu); int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); @@ -305,8 +333,7 @@ bool riscv_cpu_virt_enabled(CPURISCVState *env); void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable); bool riscv_cpu_force_hs_excep_enabled(CPURISCVState *env); void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable); -bool riscv_cpu_two_stage_lookup(CPURISCVState *env); -void riscv_cpu_set_two_stage_lookup(CPURISCVState *env, bool enable); +bool riscv_cpu_two_stage_lookup(int mmu_idx); int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch); hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, @@ -332,7 +359,8 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env); int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts); uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value); #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */ -void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void)); +void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t), + uint32_t arg); #endif void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv); @@ -344,22 +372,79 @@ void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env, target_ulong riscv_cpu_get_fflags(CPURISCVState *env); void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong); -#define TB_FLAGS_MMU_MASK 3 +#define TB_FLAGS_MMU_MASK 7 +#define TB_FLAGS_PRIV_MMU_MASK 3 +#define TB_FLAGS_PRIV_HYP_ACCESS_MASK (1 << 2) #define TB_FLAGS_MSTATUS_FS MSTATUS_FS +typedef CPURISCVState CPUArchState; +typedef RISCVCPU ArchCPU; +#include "exec/cpu-all.h" + +FIELD(TB_FLAGS, VL_EQ_VLMAX, 2, 1) +FIELD(TB_FLAGS, LMUL, 3, 2) +FIELD(TB_FLAGS, SEW, 5, 3) +FIELD(TB_FLAGS, VILL, 8, 1) +/* Is a Hypervisor instruction load/store allowed? */ +FIELD(TB_FLAGS, HLSX, 9, 1) + +/* + * A simplification for VLMAX + * = (1 << LMUL) * VLEN / (8 * (1 << SEW)) + * = (VLEN << LMUL) / (8 << SEW) + * = (VLEN << LMUL) >> (SEW + 3) + * = VLEN >> (SEW + 3 - LMUL) + */ +static inline uint32_t vext_get_vlmax(RISCVCPU *cpu, target_ulong vtype) +{ + uint8_t sew, lmul; + + sew = FIELD_EX64(vtype, VTYPE, VSEW); + lmul = FIELD_EX64(vtype, VTYPE, VLMUL); + return cpu->cfg.vlen >> (sew + 3 - lmul); +} + static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, - target_ulong *cs_base, uint32_t *flags) + target_ulong *cs_base, uint32_t *pflags) { + uint32_t flags = 0; + *pc = env->pc; *cs_base = 0; + + if (riscv_has_ext(env, RVV)) { + uint32_t vlmax = vext_get_vlmax(env_archcpu(env), env->vtype); + bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl); + flags = FIELD_DP32(flags, TB_FLAGS, VILL, + FIELD_EX64(env->vtype, VTYPE, VILL)); + flags = FIELD_DP32(flags, TB_FLAGS, SEW, + FIELD_EX64(env->vtype, VTYPE, VSEW)); + flags = FIELD_DP32(flags, TB_FLAGS, LMUL, + FIELD_EX64(env->vtype, VTYPE, VLMUL)); + flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax); + } else { + flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1); + } + #ifdef CONFIG_USER_ONLY - *flags = TB_FLAGS_MSTATUS_FS; + flags |= TB_FLAGS_MSTATUS_FS; #else - *flags = cpu_mmu_index(env, 0); + flags |= cpu_mmu_index(env, 0); if (riscv_cpu_fp_enabled(env)) { - *flags |= env->mstatus & MSTATUS_FS; + flags |= env->mstatus & MSTATUS_FS; + } + + if (riscv_has_ext(env, RVH)) { + if (env->priv == PRV_M || + (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || + (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && + get_field(env->hstatus, HSTATUS_HU))) { + flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1); + } } #endif + + *pflags = flags; } int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value, @@ -400,9 +485,4 @@ void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops); void riscv_cpu_register_gdb_regs_for_features(CPUState *cs); -typedef CPURISCVState CPUArchState; -typedef RISCVCPU ArchCPU; - -#include "exec/cpu-all.h" - #endif /* RISCV_CPU_H */ diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 30fa746d10742bd1d1912bfc021054005dcb386c..24b24c69c51edfb7a5617050bed161dfee46cab2 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -4,10 +4,10 @@ #define TARGET_RISCV_CPU_BITS_H #define get_field(reg, mask) (((reg) & \ - (target_ulong)(mask)) / ((mask) & ~((mask) << 1))) -#define set_field(reg, mask, val) (((reg) & ~(target_ulong)(mask)) | \ - (((target_ulong)(val) * ((mask) & ~((mask) << 1))) & \ - (target_ulong)(mask))) + (uint64_t)(mask)) / ((mask) & ~((mask) << 1))) +#define set_field(reg, mask, val) (((reg) & ~(uint64_t)(mask)) | \ + (((uint64_t)(val) * ((mask) & ~((mask) << 1))) & \ + (uint64_t)(mask))) /* Floating point round mode */ #define FSR_RD_SHIFT 5 @@ -29,6 +29,14 @@ #define FSR_NXA (FPEXC_NX << FSR_AEXC_SHIFT) #define FSR_AEXC (FSR_NVA | FSR_OFA | FSR_UFA | FSR_DZA | FSR_NXA) +/* Vector Fixed-Point round model */ +#define FSR_VXRM_SHIFT 9 +#define FSR_VXRM (0x3 << FSR_VXRM_SHIFT) + +/* Vector Fixed-Point saturation flag */ +#define FSR_VXSAT_SHIFT 8 +#define FSR_VXSAT (0x1 << FSR_VXSAT_SHIFT) + /* Control and Status Registers */ /* User Trap Setup */ @@ -48,6 +56,13 @@ #define CSR_FRM 0x002 #define CSR_FCSR 0x003 +/* User Vector CSRs */ +#define CSR_VSTART 0x008 +#define CSR_VXSAT 0x009 +#define CSR_VXRM 0x00a +#define CSR_VL 0xc20 +#define CSR_VTYPE 0xc21 + /* User Timers and Counters */ #define CSR_CYCLE 0xc00 #define CSR_TIME 0xc01 @@ -366,19 +381,8 @@ #define MSTATUS_TVM 0x00100000 /* since: priv-1.10 */ #define MSTATUS_TW 0x20000000 /* since: priv-1.10 */ #define MSTATUS_TSR 0x40000000 /* since: priv-1.10 */ -#if defined(TARGET_RISCV64) #define MSTATUS_GVA 0x4000000000ULL #define MSTATUS_MPV 0x8000000000ULL -#elif defined(TARGET_RISCV32) -#define MSTATUS_GVA 0x00000040 -#define MSTATUS_MPV 0x00000080 -#endif - -#ifdef TARGET_RISCV32 -# define MSTATUS_MPV_ISSET(env) get_field(env->mstatush, MSTATUS_MPV) -#else -# define MSTATUS_MPV_ISSET(env) get_field(env->mstatus, MSTATUS_MPV) -#endif #define MSTATUS64_UXL 0x0000000300000000ULL #define MSTATUS64_SXL 0x0000000C00000000ULL @@ -465,7 +469,6 @@ * page table fault. */ #define FORCE_HS_EXCEP 2 -#define HS_TWO_STAGE 4 /* RV32 satp CSR field masks */ #define SATP32_MODE 0x80000000 diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 821cea029347a6bff1cb412301b4280fd440a864..a2787b1d4875e774d95c3040ec919bed995f6b7f 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -110,27 +110,19 @@ bool riscv_cpu_fp_enabled(CPURISCVState *env) void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env) { - target_ulong mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS | - MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE; + uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS | + MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE | + MSTATUS64_UXL; bool current_virt = riscv_cpu_virt_enabled(env); g_assert(riscv_has_ext(env, RVH)); -#if defined(TARGET_RISCV64) - mstatus_mask |= MSTATUS64_UXL; -#endif - if (current_virt) { /* Current V=1 and we are about to change to V=0 */ env->vsstatus = env->mstatus & mstatus_mask; env->mstatus &= ~mstatus_mask; env->mstatus |= env->mstatus_hs; -#if defined(TARGET_RISCV32) - env->vsstatush = env->mstatush; - env->mstatush |= env->mstatush_hs; -#endif - env->vstvec = env->stvec; env->stvec = env->stvec_hs; @@ -154,11 +146,6 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env) env->mstatus &= ~mstatus_mask; env->mstatus |= env->vsstatus; -#if defined(TARGET_RISCV32) - env->mstatush_hs = env->mstatush; - env->mstatush |= env->vsstatush; -#endif - env->stvec_hs = env->stvec; env->stvec = env->vstvec; @@ -220,22 +207,9 @@ void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable) env->virt = set_field(env->virt, FORCE_HS_EXCEP, enable); } -bool riscv_cpu_two_stage_lookup(CPURISCVState *env) +bool riscv_cpu_two_stage_lookup(int mmu_idx) { - if (!riscv_has_ext(env, RVH)) { - return false; - } - - return get_field(env->virt, HS_TWO_STAGE); -} - -void riscv_cpu_set_two_stage_lookup(CPURISCVState *env, bool enable) -{ - if (!riscv_has_ext(env, RVH)) { - return; - } - - env->virt = set_field(env->virt, HS_TWO_STAGE, enable); + return mmu_idx & TB_FLAGS_PRIV_HYP_ACCESS_MASK; } int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts) @@ -276,9 +250,11 @@ uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value) return old; } -void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void)) +void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t), + uint32_t arg) { env->rdtime_fn = fn; + env->rdtime_fn_arg = arg; } void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv) @@ -314,6 +290,9 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv) * @physical: This will be set to the calculated physical address * @prot: The returned protection attributes * @addr: The virtual address to be translated + * @fault_pte_addr: If not NULL, this will be set to fault pte address + * when a error occurs on pte address translation. + * This will already be shifted to match htval. * @access_type: The type of MMU access * @mmu_idx: Indicates current privilege level * @first_stage: Are we in first stage translation? @@ -322,6 +301,7 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv) */ static int get_physical_address(CPURISCVState *env, hwaddr *physical, int *prot, target_ulong addr, + target_ulong *fault_pte_addr, int access_type, int mmu_idx, bool first_stage, bool two_stage) { @@ -330,7 +310,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical, * (riscv_cpu_do_interrupt) is correct */ MemTxResult res; MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; - int mode = mmu_idx; + int mode = mmu_idx & TB_FLAGS_PRIV_MMU_MASK; bool use_background = false; /* @@ -340,7 +320,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical, * was called. Background registers will be used if the guest has * forced a two stage translation to be on (in HS or M mode). */ - if (riscv_cpu_two_stage_lookup(env) && access_type != MMU_INST_FETCH) { + if (!riscv_cpu_virt_enabled(env) && riscv_cpu_two_stage_lookup(mmu_idx)) { use_background = true; } @@ -445,13 +425,13 @@ restart: /* Do the second stage translation on the base PTE address. */ int vbase_ret = get_physical_address(env, &vbase, &vbase_prot, - base, MMU_DATA_LOAD, + base, NULL, MMU_DATA_LOAD, mmu_idx, false, true); if (vbase_ret != TRANSLATE_SUCCESS) { - env->guest_phys_fault_addr = (base | - (addr & - (TARGET_PAGE_SIZE - 1))) >> 2; + if (fault_pte_addr) { + *fault_pte_addr = (base + idx * ptesize) >> 2; + } return TRANSLATE_G_STAGE_FAIL; } @@ -538,7 +518,7 @@ restart: *pte_pa = pte = updated_pte; #else target_ulong old_pte = - atomic_cmpxchg(pte_pa, pte, updated_pte); + qatomic_cmpxchg(pte_pa, pte, updated_pte); if (old_pte != pte) { goto restart; } else { @@ -555,7 +535,8 @@ restart: /* for superpage mappings, make a fake leaf PTE for the TLB's benefit. */ target_ulong vpn = addr >> PGSHIFT; - *physical = (ppn | (vpn & ((1L << ptshift) - 1))) << PGSHIFT; + *physical = ((ppn | (vpn & ((1L << ptshift) - 1))) << PGSHIFT) | + (addr & ~TARGET_PAGE_MASK); /* set permissions on the TLB entry */ if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) { @@ -578,7 +559,7 @@ restart: static void raise_mmu_exception(CPURISCVState *env, target_ulong address, MMUAccessType access_type, bool pmp_violation, - bool first_stage) + bool first_stage, bool two_stage) { CPUState *cs = env_cpu(env); int page_fault_exceptions; @@ -601,7 +582,7 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address, } break; case MMU_DATA_LOAD: - if ((riscv_cpu_virt_enabled(env) || riscv_cpu_two_stage_lookup(env)) && !first_stage) { + if (two_stage && !first_stage) { cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT; } else { cs->exception_index = page_fault_exceptions ? @@ -609,7 +590,7 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address, } break; case MMU_DATA_STORE: - if ((riscv_cpu_virt_enabled(env) || riscv_cpu_two_stage_lookup(env)) && !first_stage) { + if (two_stage && !first_stage) { cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT; } else { cs->exception_index = page_fault_exceptions ? @@ -630,19 +611,19 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) int prot; int mmu_idx = cpu_mmu_index(&cpu->env, false); - if (get_physical_address(env, &phys_addr, &prot, addr, 0, mmu_idx, + if (get_physical_address(env, &phys_addr, &prot, addr, NULL, 0, mmu_idx, true, riscv_cpu_virt_enabled(env))) { return -1; } if (riscv_cpu_virt_enabled(env)) { - if (get_physical_address(env, &phys_addr, &prot, phys_addr, + if (get_physical_address(env, &phys_addr, &prot, phys_addr, NULL, 0, mmu_idx, false, true)) { return -1; } } - return phys_addr; + return phys_addr & TARGET_PAGE_MASK; } void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, @@ -700,8 +681,10 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, int prot, prot2; bool pmp_violation = false; bool first_stage_error = true; + bool two_stage_lookup = false; int ret = TRANSLATE_FAIL; int mode = mmu_idx; + target_ulong tlb_size = 0; env->guest_phys_fault_addr = 0; @@ -717,16 +700,23 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, if (riscv_has_ext(env, RVH) && env->priv == PRV_M && access_type != MMU_INST_FETCH && get_field(env->mstatus, MSTATUS_MPRV) && - MSTATUS_MPV_ISSET(env)) { - riscv_cpu_set_two_stage_lookup(env, true); + get_field(env->mstatus, MSTATUS_MPV)) { + two_stage_lookup = true; } if (riscv_cpu_virt_enabled(env) || - (riscv_cpu_two_stage_lookup(env) && access_type != MMU_INST_FETCH)) { + ((riscv_cpu_two_stage_lookup(mmu_idx) || two_stage_lookup) && + access_type != MMU_INST_FETCH)) { /* Two stage lookup */ - ret = get_physical_address(env, &pa, &prot, address, access_type, + ret = get_physical_address(env, &pa, &prot, address, + &env->guest_phys_fault_addr, access_type, mmu_idx, true, true); + /* + * A G-stage exception may be triggered during two state lookup. + * And the env->guest_phys_fault_addr has already been set in + * get_physical_address(). + */ if (ret == TRANSLATE_G_STAGE_FAIL) { first_stage_error = false; access_type = MMU_DATA_LOAD; @@ -737,11 +727,11 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, TARGET_FMT_plx " prot %d\n", __func__, address, ret, pa, prot); - if (ret != TRANSLATE_FAIL && ret != TRANSLATE_G_STAGE_FAIL) { + if (ret == TRANSLATE_SUCCESS) { /* Second stage lookup */ im_address = pa; - ret = get_physical_address(env, &pa, &prot2, im_address, + ret = get_physical_address(env, &pa, &prot2, im_address, NULL, access_type, mmu_idx, false, true); qemu_log_mask(CPU_LOG_MMU, @@ -770,8 +760,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, } } else { /* Single stage lookup */ - ret = get_physical_address(env, &pa, &prot, address, access_type, - mmu_idx, true, false); + ret = get_physical_address(env, &pa, &prot, address, NULL, + access_type, mmu_idx, true, false); qemu_log_mask(CPU_LOG_MMU, "%s address=%" VADDR_PRIx " ret %d physical " @@ -779,14 +769,6 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, __func__, address, ret, pa, prot); } - /* We did the two stage lookup based on MPRV, unset the lookup */ - if (riscv_has_ext(env, RVH) && env->priv == PRV_M && - access_type != MMU_INST_FETCH && - get_field(env->mstatus, MSTATUS_MPRV) && - MSTATUS_MPV_ISSET(env)) { - riscv_cpu_set_two_stage_lookup(env, false); - } - if (riscv_feature(env, RISCV_FEATURE_PMP) && (ret == TRANSLATE_SUCCESS) && !pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) { @@ -797,13 +779,21 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, } if (ret == TRANSLATE_SUCCESS) { - tlb_set_page(cs, address & TARGET_PAGE_MASK, pa & TARGET_PAGE_MASK, - prot, mmu_idx, TARGET_PAGE_SIZE); + if (pmp_is_range_in_tlb(env, pa & TARGET_PAGE_MASK, &tlb_size)) { + tlb_set_page(cs, address & ~(tlb_size - 1), pa & ~(tlb_size - 1), + prot, mmu_idx, tlb_size); + } else { + tlb_set_page(cs, address & TARGET_PAGE_MASK, pa & TARGET_PAGE_MASK, + prot, mmu_idx, TARGET_PAGE_SIZE); + } return true; } else if (probe) { return false; } else { - raise_mmu_exception(env, address, access_type, pmp_violation, first_stage_error); + raise_mmu_exception(env, address, access_type, pmp_violation, + first_stage_error, + riscv_cpu_virt_enabled(env) || + riscv_cpu_two_stage_lookup(mmu_idx)); riscv_raise_exception(env, cs->exception_index, retaddr); } @@ -841,7 +831,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; bool force_hs_execp = riscv_cpu_force_hs_excep_enabled(env); - target_ulong s; + uint64_t s; /* cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide * so we mask off the MSB and separate into trap type and cause. @@ -849,6 +839,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) bool async = !!(cs->exception_index & RISCV_EXCP_INT_FLAG); target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK; target_ulong deleg = async ? env->mideleg : env->medeleg; + bool write_tval = false; target_ulong tval = 0; target_ulong htval = 0; target_ulong mtval2 = 0; @@ -870,6 +861,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) case RISCV_EXCP_INST_PAGE_FAULT: case RISCV_EXCP_LOAD_PAGE_FAULT: case RISCV_EXCP_STORE_PAGE_FAULT: + write_tval = true; tval = env->badaddr; break; default: @@ -891,17 +883,30 @@ void riscv_cpu_do_interrupt(CPUState *cs) } } - trace_riscv_trap(env->mhartid, async, cause, env->pc, tval, cause < 23 ? - (async ? riscv_intr_names : riscv_excp_names)[cause] : "(unknown)"); + trace_riscv_trap(env->mhartid, async, cause, env->pc, tval, + riscv_cpu_get_trap_name(cause, async)); + + qemu_log_mask(CPU_LOG_INT, + "%s: hart:"TARGET_FMT_ld", async:%d, cause:"TARGET_FMT_lx", " + "epc:0x"TARGET_FMT_lx", tval:0x"TARGET_FMT_lx", desc=%s\n", + __func__, env->mhartid, async, cause, env->pc, tval, + riscv_cpu_get_trap_name(cause, async)); if (env->priv <= PRV_S && cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) { /* handle the trap in S-mode */ if (riscv_has_ext(env, RVH)) { target_ulong hdeleg = async ? env->hideleg : env->hedeleg; + bool two_stage_lookup = false; + + if (env->priv == PRV_M || + (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || + (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && + get_field(env->hstatus, HSTATUS_HU))) { + two_stage_lookup = true; + } - if ((riscv_cpu_virt_enabled(env) || - riscv_cpu_two_stage_lookup(env)) && tval) { + if ((riscv_cpu_virt_enabled(env) || two_stage_lookup) && write_tval) { /* * If we are writing a guest virtual address to stval, set * this to 1. If we are trapping to VS we will set this to 0 @@ -929,7 +934,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) /* Trap into HS mode, from virt */ riscv_cpu_swap_hypervisor_regs(env); env->hstatus = set_field(env->hstatus, HSTATUS_SPVP, - get_field(env->mstatus, SSTATUS_SPP)); + env->priv); env->hstatus = set_field(env->hstatus, HSTATUS_SPV, riscv_cpu_virt_enabled(env)); @@ -939,11 +944,10 @@ void riscv_cpu_do_interrupt(CPUState *cs) riscv_cpu_set_force_hs_excep(env, 0); } else { /* Trap into HS mode */ - if (!riscv_cpu_two_stage_lookup(env)) { + if (!two_stage_lookup) { env->hstatus = set_field(env->hstatus, HSTATUS_SPV, riscv_cpu_virt_enabled(env)); } - riscv_cpu_set_two_stage_lookup(env, false); htval = env->guest_phys_fault_addr; } } @@ -966,19 +970,11 @@ void riscv_cpu_do_interrupt(CPUState *cs) if (riscv_cpu_virt_enabled(env)) { riscv_cpu_swap_hypervisor_regs(env); } -#ifdef TARGET_RISCV32 - env->mstatush = set_field(env->mstatush, MSTATUS_MPV, - riscv_cpu_virt_enabled(env)); - if (riscv_cpu_virt_enabled(env) && tval) { - env->mstatush = set_field(env->mstatush, MSTATUS_GVA, 1); - } -#else env->mstatus = set_field(env->mstatus, MSTATUS_MPV, - riscv_cpu_virt_enabled(env)); + riscv_cpu_virt_enabled(env)); if (riscv_cpu_virt_enabled(env) && tval) { env->mstatus = set_field(env->mstatus, MSTATUS_GVA, 1); } -#endif mtval2 = env->guest_phys_fault_addr; diff --git a/target/riscv/csr.c b/target/riscv/csr.c index f985b85de450fdc7972cf29e1fa969753d6683cd..93263f8e065dc540fd09d09c7ca64c95e883bdd0 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -46,6 +46,10 @@ void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops) static int fs(CPURISCVState *env, int csrno) { #if !defined(CONFIG_USER_ONLY) + /* loose check condition for fcsr in vector extension */ + if ((csrno == CSR_FCSR) && (env->misa & RVV)) { + return 0; + } if (!env->debugger && !riscv_cpu_fp_enabled(env)) { return -RISCV_EXCP_ILLEGAL_INST; } @@ -53,6 +57,14 @@ static int fs(CPURISCVState *env, int csrno) return 0; } +static int vs(CPURISCVState *env, int csrno) +{ + if (env->misa & RVV) { + return 0; + } + return -1; +} + static int ctr(CPURISCVState *env, int csrno) { #if !defined(CONFIG_USER_ONLY) @@ -67,43 +79,51 @@ static int ctr(CPURISCVState *env, int csrno) if (riscv_cpu_virt_enabled(env)) { switch (csrno) { case CSR_CYCLE: - if (!get_field(env->hcounteren, HCOUNTEREN_CY)) { + if (!get_field(env->hcounteren, HCOUNTEREN_CY) && + get_field(env->mcounteren, HCOUNTEREN_CY)) { return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } break; case CSR_TIME: - if (!get_field(env->hcounteren, HCOUNTEREN_TM)) { + if (!get_field(env->hcounteren, HCOUNTEREN_TM) && + get_field(env->mcounteren, HCOUNTEREN_TM)) { return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } break; case CSR_INSTRET: - if (!get_field(env->hcounteren, HCOUNTEREN_IR)) { + if (!get_field(env->hcounteren, HCOUNTEREN_IR) && + get_field(env->mcounteren, HCOUNTEREN_IR)) { return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } break; case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31: - if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3))) { + if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3)) && + get_field(env->mcounteren, 1 << (csrno - CSR_HPMCOUNTER3))) { return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } break; #if defined(TARGET_RISCV32) case CSR_CYCLEH: - if (!get_field(env->hcounteren, HCOUNTEREN_CY)) { + if (!get_field(env->hcounteren, HCOUNTEREN_CY) && + get_field(env->mcounteren, HCOUNTEREN_CY)) { return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } break; case CSR_TIMEH: - if (!get_field(env->hcounteren, HCOUNTEREN_TM)) { + if (!get_field(env->hcounteren, HCOUNTEREN_TM) && + get_field(env->mcounteren, HCOUNTEREN_TM)) { return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } break; case CSR_INSTRETH: - if (!get_field(env->hcounteren, HCOUNTEREN_IR)) { + if (!get_field(env->hcounteren, HCOUNTEREN_IR) && + get_field(env->mcounteren, HCOUNTEREN_IR)) { return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } break; case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H: - if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3H))) { + if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3H)) && + get_field(env->mcounteren, 1 << (csrno - CSR_HPMCOUNTER3H))) { return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } break; @@ -203,6 +223,10 @@ static int read_fcsr(CPURISCVState *env, int csrno, target_ulong *val) #endif *val = (riscv_cpu_get_fflags(env) << FSR_AEXC_SHIFT) | (env->frm << FSR_RD_SHIFT); + if (vs(env, csrno) >= 0) { + *val |= (env->vxrm << FSR_VXRM_SHIFT) + | (env->vxsat << FSR_VXSAT_SHIFT); + } return 0; } @@ -215,16 +239,68 @@ static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val) env->mstatus |= MSTATUS_FS; #endif env->frm = (val & FSR_RD) >> FSR_RD_SHIFT; + if (vs(env, csrno) >= 0) { + env->vxrm = (val & FSR_VXRM) >> FSR_VXRM_SHIFT; + env->vxsat = (val & FSR_VXSAT) >> FSR_VXSAT_SHIFT; + } riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT); return 0; } +static int read_vtype(CPURISCVState *env, int csrno, target_ulong *val) +{ + *val = env->vtype; + return 0; +} + +static int read_vl(CPURISCVState *env, int csrno, target_ulong *val) +{ + *val = env->vl; + return 0; +} + +static int read_vxrm(CPURISCVState *env, int csrno, target_ulong *val) +{ + *val = env->vxrm; + return 0; +} + +static int write_vxrm(CPURISCVState *env, int csrno, target_ulong val) +{ + env->vxrm = val; + return 0; +} + +static int read_vxsat(CPURISCVState *env, int csrno, target_ulong *val) +{ + *val = env->vxsat; + return 0; +} + +static int write_vxsat(CPURISCVState *env, int csrno, target_ulong val) +{ + env->vxsat = val; + return 0; +} + +static int read_vstart(CPURISCVState *env, int csrno, target_ulong *val) +{ + *val = env->vstart; + return 0; +} + +static int write_vstart(CPURISCVState *env, int csrno, target_ulong val) +{ + env->vstart = val; + return 0; +} + /* User Timers and Counters */ static int read_instret(CPURISCVState *env, int csrno, target_ulong *val) { #if !defined(CONFIG_USER_ONLY) - if (use_icount) { - *val = cpu_get_icount(); + if (icount_enabled()) { + *val = icount_get(); } else { *val = cpu_get_host_ticks(); } @@ -238,8 +314,8 @@ static int read_instret(CPURISCVState *env, int csrno, target_ulong *val) static int read_instreth(CPURISCVState *env, int csrno, target_ulong *val) { #if !defined(CONFIG_USER_ONLY) - if (use_icount) { - *val = cpu_get_icount() >> 32; + if (icount_enabled()) { + *val = icount_get() >> 32; } else { *val = cpu_get_host_ticks() >> 32; } @@ -275,7 +351,7 @@ static int read_time(CPURISCVState *env, int csrno, target_ulong *val) return -RISCV_EXCP_ILLEGAL_INST; } - *val = env->rdtime_fn() + delta; + *val = env->rdtime_fn(env->rdtime_fn_arg) + delta; return 0; } @@ -288,7 +364,7 @@ static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val) return -RISCV_EXCP_ILLEGAL_INST; } - *val = (env->rdtime_fn() + delta) >> 32; + *val = (env->rdtime_fn(env->rdtime_fn_arg) + delta) >> 32; return 0; } #endif @@ -370,8 +446,8 @@ static int validate_vm(CPURISCVState *env, target_ulong vm) static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val) { - target_ulong mstatus = env->mstatus; - target_ulong mask = 0; + uint64_t mstatus = env->mstatus; + uint64_t mask = 0; int dirty; /* flush tlb on mstatus fields that affect VM */ @@ -404,19 +480,20 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val) #ifdef TARGET_RISCV32 static int read_mstatush(CPURISCVState *env, int csrno, target_ulong *val) { - *val = env->mstatush; + *val = env->mstatus >> 32; return 0; } static int write_mstatush(CPURISCVState *env, int csrno, target_ulong val) { - if ((val ^ env->mstatush) & (MSTATUS_MPV)) { + uint64_t valh = (uint64_t)val << 32; + uint64_t mask = MSTATUS_MPV | MSTATUS_GVA; + + if ((valh ^ env->mstatus) & (MSTATUS_MPV)) { tlb_flush(env_cpu(env)); } - val &= MSTATUS_MPV | MSTATUS_GVA; - - env->mstatush = val; + env->mstatus = (env->mstatus & ~mask) | (valh & mask); return 0; } @@ -805,7 +882,7 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val) if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) { return -RISCV_EXCP_ILLEGAL_INST; } else { - if((val ^ env->satp) & SATP_ASID) { + if ((val ^ env->satp) & SATP_ASID) { tlb_flush(env_cpu(env)); } env->satp = val; @@ -1029,7 +1106,8 @@ static int read_vsstatus(CPURISCVState *env, int csrno, target_ulong *val) static int write_vsstatus(CPURISCVState *env, int csrno, target_ulong val) { - env->vsstatus = val; + uint64_t mask = (target_ulong)-1; + env->vsstatus = (env->vsstatus & ~mask) | (uint64_t)val; return 0; } @@ -1287,7 +1365,12 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_FFLAGS] = { fs, read_fflags, write_fflags }, [CSR_FRM] = { fs, read_frm, write_frm }, [CSR_FCSR] = { fs, read_fcsr, write_fcsr }, - + /* Vector CSRs */ + [CSR_VSTART] = { vs, read_vstart, write_vstart }, + [CSR_VXSAT] = { vs, read_vxsat, write_vxsat }, + [CSR_VXRM] = { vs, read_vxrm, write_vxrm }, + [CSR_VL] = { vs, read_vl }, + [CSR_VTYPE] = { vs, read_vtype }, /* User Timers and Counters */ [CSR_CYCLE] = { ctr, read_instret }, [CSR_INSTRET] = { ctr, read_instret }, @@ -1387,7 +1470,7 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_MTINST] = { hmode, read_mtinst, write_mtinst }, /* Physical Memory Protection */ - [CSR_PMPCFG0 ... CSR_PMPADDR9] = { pmp, read_pmpcfg, write_pmpcfg }, + [CSR_PMPCFG0 ... CSR_PMPCFG3] = { pmp, read_pmpcfg, write_pmpcfg }, [CSR_PMPADDR0 ... CSR_PMPADDR15] = { pmp, read_pmpaddr, write_pmpaddr }, /* Performance Counters */ diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c index 0b79562a690b28de3399596ec624ff79bf53c091..bb346a824992b0edde1fe586b0e97a476ad0b54a 100644 --- a/target/riscv/fpu_helper.c +++ b/target/riscv/fpu_helper.c @@ -22,6 +22,7 @@ #include "exec/exec-all.h" #include "exec/helper-proto.h" #include "fpu/softfloat.h" +#include "internals.h" target_ulong riscv_cpu_get_fflags(CPURISCVState *env) { @@ -80,10 +81,19 @@ void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm) set_float_rounding_mode(softrm, &env->fp_status); } +static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2, + uint64_t rs3, int flags) +{ + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); + float32 frs3 = check_nanbox_s(rs3); + return nanbox_s(float32_muladd(frs1, frs2, frs3, flags, &env->fp_status)); +} + uint64_t helper_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2, uint64_t frs3) { - return float32_muladd(frs1, frs2, frs3, 0, &env->fp_status); + return do_fmadd_s(env, frs1, frs2, frs3, 0); } uint64_t helper_fmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, @@ -95,8 +105,7 @@ uint64_t helper_fmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, uint64_t helper_fmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2, uint64_t frs3) { - return float32_muladd(frs1, frs2, frs3, float_muladd_negate_c, - &env->fp_status); + return do_fmadd_s(env, frs1, frs2, frs3, float_muladd_negate_c); } uint64_t helper_fmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, @@ -109,8 +118,7 @@ uint64_t helper_fmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, uint64_t helper_fnmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2, uint64_t frs3) { - return float32_muladd(frs1, frs2, frs3, float_muladd_negate_product, - &env->fp_status); + return do_fmadd_s(env, frs1, frs2, frs3, float_muladd_negate_product); } uint64_t helper_fnmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, @@ -123,8 +131,8 @@ uint64_t helper_fnmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, uint64_t helper_fnmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2, uint64_t frs3) { - return float32_muladd(frs1, frs2, frs3, float_muladd_negate_c | - float_muladd_negate_product, &env->fp_status); + return do_fmadd_s(env, frs1, frs2, frs3, + float_muladd_negate_c | float_muladd_negate_product); } uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, @@ -134,117 +142,127 @@ uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, float_muladd_negate_product, &env->fp_status); } -uint64_t helper_fadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +uint64_t helper_fadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { - return float32_add(frs1, frs2, &env->fp_status); + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); + return nanbox_s(float32_add(frs1, frs2, &env->fp_status)); } -uint64_t helper_fsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +uint64_t helper_fsub_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { - return float32_sub(frs1, frs2, &env->fp_status); + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); + return nanbox_s(float32_sub(frs1, frs2, &env->fp_status)); } -uint64_t helper_fmul_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +uint64_t helper_fmul_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { - return float32_mul(frs1, frs2, &env->fp_status); + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); + return nanbox_s(float32_mul(frs1, frs2, &env->fp_status)); } -uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { - return float32_div(frs1, frs2, &env->fp_status); + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); + return nanbox_s(float32_div(frs1, frs2, &env->fp_status)); } -uint64_t helper_fmin_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +uint64_t helper_fmin_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { - return float32_minnum(frs1, frs2, &env->fp_status); + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); + return nanbox_s(float32_minnum(frs1, frs2, &env->fp_status)); } -uint64_t helper_fmax_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +uint64_t helper_fmax_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { - return float32_maxnum(frs1, frs2, &env->fp_status); + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); + return nanbox_s(float32_maxnum(frs1, frs2, &env->fp_status)); } -uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t frs1) +uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t rs1) { - return float32_sqrt(frs1, &env->fp_status); + float32 frs1 = check_nanbox_s(rs1); + return nanbox_s(float32_sqrt(frs1, &env->fp_status)); } -target_ulong helper_fle_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +target_ulong helper_fle_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); return float32_le(frs1, frs2, &env->fp_status); } -target_ulong helper_flt_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +target_ulong helper_flt_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); return float32_lt(frs1, frs2, &env->fp_status); } -target_ulong helper_feq_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +target_ulong helper_feq_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); return float32_eq_quiet(frs1, frs2, &env->fp_status); } -target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t frs1) +target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t rs1) { + float32 frs1 = check_nanbox_s(rs1); return float32_to_int32(frs1, &env->fp_status); } -target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t frs1) +target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t rs1) { + float32 frs1 = check_nanbox_s(rs1); return (int32_t)float32_to_uint32(frs1, &env->fp_status); } #if defined(TARGET_RISCV64) -uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t frs1) +uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t rs1) { + float32 frs1 = check_nanbox_s(rs1); return float32_to_int64(frs1, &env->fp_status); } -uint64_t helper_fcvt_lu_s(CPURISCVState *env, uint64_t frs1) +uint64_t helper_fcvt_lu_s(CPURISCVState *env, uint64_t rs1) { + float32 frs1 = check_nanbox_s(rs1); return float32_to_uint64(frs1, &env->fp_status); } #endif uint64_t helper_fcvt_s_w(CPURISCVState *env, target_ulong rs1) { - return int32_to_float32((int32_t)rs1, &env->fp_status); + return nanbox_s(int32_to_float32((int32_t)rs1, &env->fp_status)); } uint64_t helper_fcvt_s_wu(CPURISCVState *env, target_ulong rs1) { - return uint32_to_float32((uint32_t)rs1, &env->fp_status); + return nanbox_s(uint32_to_float32((uint32_t)rs1, &env->fp_status)); } #if defined(TARGET_RISCV64) uint64_t helper_fcvt_s_l(CPURISCVState *env, uint64_t rs1) { - return int64_to_float32(rs1, &env->fp_status); + return nanbox_s(int64_to_float32(rs1, &env->fp_status)); } uint64_t helper_fcvt_s_lu(CPURISCVState *env, uint64_t rs1) { - return uint64_to_float32(rs1, &env->fp_status); + return nanbox_s(uint64_to_float32(rs1, &env->fp_status)); } #endif -target_ulong helper_fclass_s(uint64_t frs1) -{ - float32 f = frs1; - bool sign = float32_is_neg(f); - - if (float32_is_infinity(f)) { - return sign ? 1 << 0 : 1 << 7; - } else if (float32_is_zero(f)) { - return sign ? 1 << 3 : 1 << 4; - } else if (float32_is_zero_or_denormal(f)) { - return sign ? 1 << 2 : 1 << 5; - } else if (float32_is_any_nan(f)) { - float_status s = { }; /* for snan_bit_is_one */ - return float32_is_quiet_nan(f, &s) ? 1 << 9 : 1 << 8; - } else { - return sign ? 1 << 1 : 1 << 6; - } +target_ulong helper_fclass_s(uint64_t rs1) +{ + float32 frs1 = check_nanbox_s(rs1); + return fclass_s(frs1); } uint64_t helper_fadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) @@ -279,12 +297,13 @@ uint64_t helper_fmax_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) uint64_t helper_fcvt_s_d(CPURISCVState *env, uint64_t rs1) { - return float64_to_float32(rs1, &env->fp_status); + return nanbox_s(float64_to_float32(rs1, &env->fp_status)); } uint64_t helper_fcvt_d_s(CPURISCVState *env, uint64_t rs1) { - return float32_to_float64(rs1, &env->fp_status); + float32 frs1 = check_nanbox_s(rs1); + return float32_to_float64(frs1, &env->fp_status); } uint64_t helper_fsqrt_d(CPURISCVState *env, uint64_t frs1) @@ -353,19 +372,5 @@ uint64_t helper_fcvt_d_lu(CPURISCVState *env, uint64_t rs1) target_ulong helper_fclass_d(uint64_t frs1) { - float64 f = frs1; - bool sign = float64_is_neg(f); - - if (float64_is_infinity(f)) { - return sign ? 1 << 0 : 1 << 7; - } else if (float64_is_zero(f)) { - return sign ? 1 << 3 : 1 << 4; - } else if (float64_is_zero_or_denormal(f)) { - return sign ? 1 << 2 : 1 << 5; - } else if (float64_is_any_nan(f)) { - float_status s = { }; /* for snan_bit_is_one */ - return float64_is_quiet_nan(f, &s) ? 1 << 9 : 1 << 8; - } else { - return sign ? 1 << 1 : 1 << 6; - } + return fclass_d(frs1); } diff --git a/target/riscv/helper.h b/target/riscv/helper.h index 2df7e09766d26cac0c47158905045fabf98b8970..939731c345d9a28d07432fba72f00c1b3a75721e 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -81,7 +81,1075 @@ DEF_HELPER_1(tlb_flush, void, env) #ifndef CONFIG_USER_ONLY DEF_HELPER_1(hyp_tlb_flush, void, env) DEF_HELPER_1(hyp_gvma_tlb_flush, void, env) -DEF_HELPER_4(hyp_load, tl, env, tl, tl, tl) -DEF_HELPER_5(hyp_store, void, env, tl, tl, tl, tl) -DEF_HELPER_4(hyp_x_load, tl, env, tl, tl, tl) +DEF_HELPER_2(hyp_hlvx_hu, tl, env, tl) +DEF_HELPER_2(hyp_hlvx_wu, tl, env, tl) #endif + +/* Vector functions */ +DEF_HELPER_3(vsetvl, tl, env, tl, tl) +DEF_HELPER_5(vlb_v_b, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlb_v_b_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlb_v_h, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlb_v_h_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlb_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlb_v_w_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlb_v_d, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlb_v_d_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlh_v_h, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlh_v_h_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlh_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlh_v_w_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlh_v_d, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlh_v_d_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlw_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlw_v_w_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlw_v_d, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlw_v_d_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vle_v_b, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vle_v_b_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vle_v_h, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vle_v_h_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vle_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vle_v_w_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vle_v_d, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vle_v_d_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlbu_v_b, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlbu_v_b_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlbu_v_h, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlbu_v_h_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlbu_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlbu_v_w_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlbu_v_d, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlbu_v_d_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlhu_v_h, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlhu_v_h_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlhu_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlhu_v_w_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlhu_v_d, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlhu_v_d_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlwu_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlwu_v_w_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlwu_v_d, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlwu_v_d_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsb_v_b, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsb_v_b_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsb_v_h, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsb_v_h_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsb_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsb_v_w_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsb_v_d, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsb_v_d_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsh_v_h, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsh_v_h_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsh_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsh_v_w_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsh_v_d, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsh_v_d_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsw_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsw_v_w_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsw_v_d, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vsw_v_d_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vse_v_b, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vse_v_b_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vse_v_h, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vse_v_h_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vse_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vse_v_w_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vse_v_d, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vse_v_d_mask, void, ptr, ptr, tl, env, i32) +DEF_HELPER_6(vlsb_v_b, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlsb_v_h, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlsb_v_w, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlsb_v_d, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlsh_v_h, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlsh_v_w, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlsh_v_d, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlsw_v_w, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlsw_v_d, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlse_v_b, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlse_v_h, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlse_v_w, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlse_v_d, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlsbu_v_b, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlsbu_v_h, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlsbu_v_w, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlsbu_v_d, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlshu_v_h, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlshu_v_w, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlshu_v_d, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlswu_v_w, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlswu_v_d, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vssb_v_b, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vssb_v_h, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vssb_v_w, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vssb_v_d, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vssh_v_h, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vssh_v_w, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vssh_v_d, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vssw_v_w, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vssw_v_d, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vsse_v_b, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vsse_v_h, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vsse_v_w, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vsse_v_d, void, ptr, ptr, tl, tl, env, i32) +DEF_HELPER_6(vlxb_v_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxb_v_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxb_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxb_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxh_v_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxh_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxh_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxw_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxw_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxe_v_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxe_v_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxe_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxe_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxbu_v_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxbu_v_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxbu_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxbu_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxhu_v_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxhu_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxhu_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxwu_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vlxwu_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsxb_v_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsxb_v_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsxb_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsxb_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsxh_v_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsxh_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsxh_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsxw_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsxw_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsxe_v_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsxe_v_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsxe_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsxe_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_5(vlbff_v_b, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlbff_v_h, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlbff_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlbff_v_d, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlhff_v_h, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlhff_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlhff_v_d, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlwff_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlwff_v_d, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vleff_v_b, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vleff_v_h, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vleff_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vleff_v_d, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlbuff_v_b, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlbuff_v_h, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlbuff_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlbuff_v_d, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlhuff_v_h, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlhuff_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlhuff_v_d, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlwuff_v_w, void, ptr, ptr, tl, env, i32) +DEF_HELPER_5(vlwuff_v_d, void, ptr, ptr, tl, env, i32) +#ifdef TARGET_RISCV64 +DEF_HELPER_6(vamoswapw_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamoswapd_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamoaddw_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamoaddd_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamoxorw_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamoxord_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamoandw_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamoandd_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamoorw_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamoord_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamominw_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamomind_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamomaxw_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamomaxd_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamominuw_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamominud_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamomaxuw_v_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamomaxud_v_d, void, ptr, ptr, tl, ptr, env, i32) +#endif +DEF_HELPER_6(vamoswapw_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamoaddw_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamoxorw_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamoandw_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamoorw_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamominw_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamomaxw_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamominuw_v_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vamomaxuw_v_w, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vadd_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vadd_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vadd_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vadd_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsub_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsub_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsub_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsub_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vadd_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vadd_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vadd_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vadd_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsub_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsub_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsub_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsub_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vrsub_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vrsub_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vrsub_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vrsub_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_FLAGS_4(vec_rsubs8, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) +DEF_HELPER_FLAGS_4(vec_rsubs16, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) +DEF_HELPER_FLAGS_4(vec_rsubs32, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) +DEF_HELPER_FLAGS_4(vec_rsubs64, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) + +DEF_HELPER_6(vwaddu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwaddu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwaddu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsubu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsubu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsubu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwadd_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwadd_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwadd_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsub_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsub_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsub_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwaddu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwaddu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwaddu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsubu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsubu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsubu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwadd_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwadd_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwadd_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsub_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsub_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsub_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwaddu_wv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwaddu_wv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwaddu_wv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsubu_wv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsubu_wv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsubu_wv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwadd_wv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwadd_wv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwadd_wv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsub_wv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsub_wv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsub_wv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwaddu_wx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwaddu_wx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwaddu_wx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsubu_wx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsubu_wx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsubu_wx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwadd_wx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwadd_wx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwadd_wx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsub_wx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsub_wx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsub_wx_w, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vadc_vvm_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vadc_vvm_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vadc_vvm_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vadc_vvm_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsbc_vvm_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsbc_vvm_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsbc_vvm_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsbc_vvm_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmadc_vvm_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmadc_vvm_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmadc_vvm_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmadc_vvm_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsbc_vvm_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsbc_vvm_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsbc_vvm_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsbc_vvm_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vadc_vxm_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vadc_vxm_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vadc_vxm_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vadc_vxm_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsbc_vxm_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsbc_vxm_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsbc_vxm_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsbc_vxm_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmadc_vxm_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmadc_vxm_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmadc_vxm_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmadc_vxm_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsbc_vxm_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsbc_vxm_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsbc_vxm_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsbc_vxm_d, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vand_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vand_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vand_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vand_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vor_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vor_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vor_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vor_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vxor_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vxor_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vxor_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vxor_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vand_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vand_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vand_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vand_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vor_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vor_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vor_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vor_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vxor_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vxor_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vxor_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vxor_vx_d, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vsll_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsll_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsll_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsll_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsrl_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsrl_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsrl_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsrl_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsra_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsra_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsra_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsra_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsll_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsll_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsll_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsll_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsrl_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsrl_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsrl_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsrl_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsra_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsra_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsra_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsra_vx_d, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vnsrl_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnsrl_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnsrl_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnsra_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnsra_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnsra_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnsrl_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnsrl_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnsrl_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnsra_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnsra_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnsra_vx_w, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vmseq_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmseq_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmseq_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmseq_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsne_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsne_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsne_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsne_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsltu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsltu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsltu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsltu_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmslt_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmslt_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmslt_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmslt_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsleu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsleu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsleu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsleu_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsle_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsle_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsle_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmsle_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmseq_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmseq_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmseq_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmseq_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsne_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsne_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsne_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsne_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsltu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsltu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsltu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsltu_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmslt_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmslt_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmslt_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmslt_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsleu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsleu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsleu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsleu_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsle_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsle_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsle_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsle_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsgtu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsgtu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsgtu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsgtu_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsgt_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsgt_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsgt_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmsgt_vx_d, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vminu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vminu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vminu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vminu_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmin_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmin_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmin_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmin_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmaxu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmaxu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmaxu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmaxu_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmax_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmax_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmax_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmax_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vminu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vminu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vminu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vminu_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmin_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmin_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmin_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmin_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmaxu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmaxu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmaxu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmaxu_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmax_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmax_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmax_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmax_vx_d, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vmul_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmul_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmul_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmul_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmulh_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmulh_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmulh_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmulh_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmulhu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmulhu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmulhu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmulhu_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmulhsu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmulhsu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmulhsu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmulhsu_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmul_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmul_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmul_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmul_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmulh_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmulh_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmulh_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmulh_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmulhu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmulhu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmulhu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmulhu_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmulhsu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmulhsu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmulhsu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmulhsu_vx_d, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vdivu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vdivu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vdivu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vdivu_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vdiv_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vdiv_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vdiv_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vdiv_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vremu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vremu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vremu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vremu_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vrem_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vrem_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vrem_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vrem_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vdivu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vdivu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vdivu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vdivu_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vdiv_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vdiv_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vdiv_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vdiv_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vremu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vremu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vremu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vremu_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vrem_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vrem_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vrem_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vrem_vx_d, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vwmul_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmul_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmul_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmulu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmulu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmulu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmulsu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmulsu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmulsu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmul_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmul_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmul_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmulu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmulu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmulu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmulsu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmulsu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmulsu_vx_w, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vmacc_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmacc_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmacc_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmacc_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnmsac_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnmsac_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnmsac_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnmsac_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmadd_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmadd_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmadd_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmadd_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnmsub_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnmsub_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnmsub_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnmsub_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmacc_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmacc_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmacc_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmacc_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnmsac_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnmsac_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnmsac_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnmsac_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmadd_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmadd_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmadd_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmadd_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnmsub_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnmsub_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnmsub_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnmsub_vx_d, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vwmaccu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmaccu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmaccu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmacc_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmacc_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmacc_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmaccsu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmaccsu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmaccsu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwmaccu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmaccu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmaccu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmacc_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmacc_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmacc_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmaccsu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmaccsu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmaccsu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmaccus_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmaccus_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwmaccus_vx_w, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vmerge_vvm_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmerge_vvm_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmerge_vvm_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmerge_vvm_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmerge_vxm_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmerge_vxm_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmerge_vxm_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vmerge_vxm_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_4(vmv_v_v_b, void, ptr, ptr, env, i32) +DEF_HELPER_4(vmv_v_v_h, void, ptr, ptr, env, i32) +DEF_HELPER_4(vmv_v_v_w, void, ptr, ptr, env, i32) +DEF_HELPER_4(vmv_v_v_d, void, ptr, ptr, env, i32) +DEF_HELPER_4(vmv_v_x_b, void, ptr, i64, env, i32) +DEF_HELPER_4(vmv_v_x_h, void, ptr, i64, env, i32) +DEF_HELPER_4(vmv_v_x_w, void, ptr, i64, env, i32) +DEF_HELPER_4(vmv_v_x_d, void, ptr, i64, env, i32) + +DEF_HELPER_6(vsaddu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsaddu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsaddu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsaddu_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsadd_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsadd_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsadd_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsadd_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vssubu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vssubu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vssubu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vssubu_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vssub_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vssub_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vssub_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vssub_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsaddu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsaddu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsaddu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsaddu_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsadd_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsadd_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsadd_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsadd_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vssubu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vssubu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vssubu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vssubu_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vssub_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vssub_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vssub_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vssub_vx_d, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vaadd_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vaadd_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vaadd_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vaadd_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vasub_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vasub_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vasub_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vasub_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vaadd_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vaadd_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vaadd_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vaadd_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vasub_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vasub_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vasub_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vasub_vx_d, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vsmul_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsmul_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsmul_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsmul_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vsmul_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsmul_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsmul_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vsmul_vx_d, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vwsmaccu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsmaccu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsmaccu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsmacc_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsmacc_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsmacc_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsmaccsu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsmaccsu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsmaccsu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwsmaccu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsmaccu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsmaccu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsmacc_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsmacc_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsmacc_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsmaccsu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsmaccsu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsmaccsu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsmaccus_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsmaccus_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vwsmaccus_vx_w, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vssrl_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vssrl_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vssrl_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vssrl_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vssra_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vssra_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vssra_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vssra_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vssrl_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vssrl_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vssrl_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vssrl_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vssra_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vssra_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vssra_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vssra_vx_d, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vnclip_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnclip_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnclip_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnclipu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnclipu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnclipu_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vnclipu_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnclipu_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnclipu_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnclip_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnclip_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vnclip_vx_w, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vfadd_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfadd_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfadd_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfsub_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfsub_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfsub_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfadd_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfadd_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfadd_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfsub_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfsub_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfsub_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfrsub_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfrsub_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfrsub_vf_d, void, ptr, ptr, i64, ptr, env, i32) + +DEF_HELPER_6(vfwadd_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwadd_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwsub_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwsub_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwadd_wv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwadd_wv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwsub_wv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwsub_wv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwadd_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfwadd_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfwsub_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfwsub_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfwadd_wf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfwadd_wf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfwsub_wf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfwsub_wf_w, void, ptr, ptr, i64, ptr, env, i32) + +DEF_HELPER_6(vfmul_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmul_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmul_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfdiv_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfdiv_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfdiv_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmul_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmul_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmul_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfdiv_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfdiv_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfdiv_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfrdiv_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfrdiv_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfrdiv_vf_d, void, ptr, ptr, i64, ptr, env, i32) + +DEF_HELPER_6(vfwmul_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwmul_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwmul_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfwmul_vf_w, void, ptr, ptr, i64, ptr, env, i32) + +DEF_HELPER_6(vfmacc_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmacc_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmacc_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfnmacc_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfnmacc_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfnmacc_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmsac_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmsac_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmsac_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfnmsac_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfnmsac_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfnmsac_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmadd_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmadd_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmadd_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfnmadd_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfnmadd_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfnmadd_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmsub_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmsub_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmsub_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfnmsub_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfnmsub_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfnmsub_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmacc_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmacc_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmacc_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfnmacc_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfnmacc_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfnmacc_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmsac_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmsac_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmsac_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfnmsac_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfnmsac_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfnmsac_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmadd_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmadd_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmadd_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfnmadd_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfnmadd_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfnmadd_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmsub_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmsub_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmsub_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfnmsub_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfnmsub_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfnmsub_vf_d, void, ptr, ptr, i64, ptr, env, i32) + +DEF_HELPER_6(vfwmacc_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwmacc_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwnmacc_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwnmacc_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwmsac_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwmsac_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwnmsac_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwnmsac_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwmacc_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfwmacc_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfwnmacc_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfwnmacc_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfwmsac_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfwmsac_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfwnmsac_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfwnmsac_vf_w, void, ptr, ptr, i64, ptr, env, i32) + +DEF_HELPER_5(vfsqrt_v_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfsqrt_v_w, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfsqrt_v_d, void, ptr, ptr, ptr, env, i32) + +DEF_HELPER_6(vfmin_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmin_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmin_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmax_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmax_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmax_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfmin_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmin_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmin_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmax_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmax_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmax_vf_d, void, ptr, ptr, i64, ptr, env, i32) + +DEF_HELPER_6(vfsgnj_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfsgnj_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfsgnj_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfsgnjn_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfsgnjn_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfsgnjn_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfsgnjx_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfsgnjx_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfsgnjx_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfsgnj_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfsgnj_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfsgnj_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfsgnjn_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfsgnjn_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfsgnjn_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfsgnjx_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfsgnjx_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfsgnjx_vf_d, void, ptr, ptr, i64, ptr, env, i32) + +DEF_HELPER_6(vmfeq_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmfeq_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmfeq_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmfne_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmfne_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmfne_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmflt_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmflt_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmflt_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmfle_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmfle_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmfle_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmfeq_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmfeq_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmfeq_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmfne_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmfne_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmfne_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmflt_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmflt_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmflt_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmfle_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmfle_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmfle_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmfgt_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmfgt_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmfgt_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmfge_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmfge_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmfge_vf_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmford_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmford_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmford_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmford_vf_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmford_vf_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vmford_vf_d, void, ptr, ptr, i64, ptr, env, i32) + +DEF_HELPER_5(vfclass_v_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfclass_v_w, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfclass_v_d, void, ptr, ptr, ptr, env, i32) + +DEF_HELPER_6(vfmerge_vfm_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmerge_vfm_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vfmerge_vfm_d, void, ptr, ptr, i64, ptr, env, i32) + +DEF_HELPER_5(vfcvt_xu_f_v_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfcvt_xu_f_v_w, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfcvt_xu_f_v_d, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfcvt_x_f_v_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfcvt_x_f_v_w, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfcvt_x_f_v_d, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfcvt_f_xu_v_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfcvt_f_xu_v_w, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfcvt_f_xu_v_d, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfcvt_f_x_v_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfcvt_f_x_v_w, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfcvt_f_x_v_d, void, ptr, ptr, ptr, env, i32) + +DEF_HELPER_5(vfwcvt_xu_f_v_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfwcvt_xu_f_v_w, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfwcvt_x_f_v_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfwcvt_x_f_v_w, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfwcvt_f_xu_v_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfwcvt_f_xu_v_w, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfwcvt_f_x_v_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfwcvt_f_x_v_w, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfwcvt_f_f_v_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfwcvt_f_f_v_w, void, ptr, ptr, ptr, env, i32) + +DEF_HELPER_5(vfncvt_xu_f_v_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfncvt_xu_f_v_w, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfncvt_x_f_v_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfncvt_x_f_v_w, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfncvt_f_xu_v_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfncvt_f_xu_v_w, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfncvt_f_x_v_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfncvt_f_x_v_w, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfncvt_f_f_v_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfncvt_f_f_v_w, void, ptr, ptr, ptr, env, i32) + +DEF_HELPER_6(vredsum_vs_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredsum_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredsum_vs_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredsum_vs_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredmaxu_vs_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredmaxu_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredmaxu_vs_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredmaxu_vs_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredmax_vs_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredmax_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredmax_vs_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredmax_vs_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredminu_vs_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredminu_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredminu_vs_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredminu_vs_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredmin_vs_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredmin_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredmin_vs_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredmin_vs_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredand_vs_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredand_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredand_vs_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredand_vs_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredor_vs_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredor_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredor_vs_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredor_vs_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredxor_vs_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredxor_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredxor_vs_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vredxor_vs_d, void, ptr, ptr, ptr, ptr, env, i32) + +DEF_HELPER_6(vwredsumu_vs_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwredsumu_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwredsumu_vs_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwredsum_vs_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwredsum_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vwredsum_vs_w, void, ptr, ptr, ptr, ptr, env, i32) + +DEF_HELPER_6(vfredsum_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfredsum_vs_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfredsum_vs_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfredmax_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfredmax_vs_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfredmax_vs_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfredmin_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfredmin_vs_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfredmin_vs_d, void, ptr, ptr, ptr, ptr, env, i32) + +DEF_HELPER_6(vfwredsum_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwredsum_vs_w, void, ptr, ptr, ptr, ptr, env, i32) + +DEF_HELPER_6(vmand_mm, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmnand_mm, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmandnot_mm, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmxor_mm, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmor_mm, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmnor_mm, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmornot_mm, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vmxnor_mm, void, ptr, ptr, ptr, ptr, env, i32) + +DEF_HELPER_4(vmpopc_m, tl, ptr, ptr, env, i32) + +DEF_HELPER_4(vmfirst_m, tl, ptr, ptr, env, i32) + +DEF_HELPER_5(vmsbf_m, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vmsif_m, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vmsof_m, void, ptr, ptr, ptr, env, i32) + +DEF_HELPER_5(viota_m_b, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(viota_m_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(viota_m_w, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(viota_m_d, void, ptr, ptr, ptr, env, i32) + +DEF_HELPER_4(vid_v_b, void, ptr, ptr, env, i32) +DEF_HELPER_4(vid_v_h, void, ptr, ptr, env, i32) +DEF_HELPER_4(vid_v_w, void, ptr, ptr, env, i32) +DEF_HELPER_4(vid_v_d, void, ptr, ptr, env, i32) + +DEF_HELPER_6(vslideup_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vslideup_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vslideup_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vslideup_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vslidedown_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vslidedown_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vslidedown_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vslidedown_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vslide1up_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vslide1up_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vslide1up_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vslide1up_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vslide1down_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vslide1down_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vslide1down_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vslide1down_vx_d, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vrgather_vv_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vrgather_vv_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vrgather_vv_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vrgather_vv_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vrgather_vx_b, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vrgather_vx_h, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vrgather_vx_w, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vrgather_vx_d, void, ptr, ptr, tl, ptr, env, i32) + +DEF_HELPER_6(vcompress_vm_b, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vcompress_vm_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vcompress_vm_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vcompress_vm_d, void, ptr, ptr, ptr, ptr, env, i32) diff --git a/target/riscv/insn32-64.decode b/target/riscv/insn32-64.decode index 24feef4e0ffb15d7608aa82b45c3675736851e5b..8157dee8b7c86b7626069c0d15a88b562fe0d142 100644 --- a/target/riscv/insn32-64.decode +++ b/target/riscv/insn32-64.decode @@ -57,6 +57,17 @@ amomax_d 10100 . . ..... ..... 011 ..... 0101111 @atom_st amominu_d 11000 . . ..... ..... 011 ..... 0101111 @atom_st amomaxu_d 11100 . . ..... ..... 011 ..... 0101111 @atom_st +#*** Vector AMO operations (in addition to Zvamo) *** +vamoswapd_v 00001 . . ..... ..... 111 ..... 0101111 @r_wdvm +vamoaddd_v 00000 . . ..... ..... 111 ..... 0101111 @r_wdvm +vamoxord_v 00100 . . ..... ..... 111 ..... 0101111 @r_wdvm +vamoandd_v 01100 . . ..... ..... 111 ..... 0101111 @r_wdvm +vamoord_v 01000 . . ..... ..... 111 ..... 0101111 @r_wdvm +vamomind_v 10000 . . ..... ..... 111 ..... 0101111 @r_wdvm +vamomaxd_v 10100 . . ..... ..... 111 ..... 0101111 @r_wdvm +vamominud_v 11000 . . ..... ..... 111 ..... 0101111 @r_wdvm +vamomaxud_v 11100 . . ..... ..... 111 ..... 0101111 @r_wdvm + # *** RV64F Standard Extension (in addition to RV32F) *** fcvt_l_s 1100000 00010 ..... ... ..... 1010011 @r2_rm fcvt_lu_s 1100000 00011 ..... ... ..... 1010011 @r2_rm diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 18bbe08ebbba757e947d60c399dfdc5c42fc40f5..84080dd18cae692934577d82af863a97b71a9714 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -25,6 +25,7 @@ %sh10 20:10 %csr 20:12 %rm 12:3 +%nf 29:3 !function=ex_plus_1 # immediates: %imm_i 20:s12 @@ -43,6 +44,11 @@ &u imm rd &shift shamt rs1 rd &atomic aq rl rs2 rs1 rd +&rmrr vm rd rs1 rs2 +&rmr vm rd rs2 +&rwdvm vm wd rd rs1 rs2 +&r2nfvm vm rd rs1 nf +&rnfvm vm rd rs1 rs2 nf # Formats 32: @r ....... ..... ..... ... ..... ....... &r %rs2 %rs1 %rd @@ -62,6 +68,16 @@ @r_rm ....... ..... ..... ... ..... ....... %rs2 %rs1 %rm %rd @r2_rm ....... ..... ..... ... ..... ....... %rs1 %rm %rd @r2 ....... ..... ..... ... ..... ....... %rs1 %rd +@r2_nfvm ... ... vm:1 ..... ..... ... ..... ....... &r2nfvm %nf %rs1 %rd +@r2_vm ...... vm:1 ..... ..... ... ..... ....... &rmr %rs2 %rd +@r1_vm ...... vm:1 ..... ..... ... ..... ....... %rd +@r_nfvm ... ... vm:1 ..... ..... ... ..... ....... &rnfvm %nf %rs2 %rs1 %rd +@r2rd ....... ..... ..... ... ..... ....... %rs2 %rd +@r_vm ...... vm:1 ..... ..... ... ..... ....... &rmrr %rs2 %rs1 %rd +@r_vm_1 ...... . ..... ..... ... ..... ....... &rmrr vm=1 %rs2 %rs1 %rd +@r_vm_0 ...... . ..... ..... ... ..... ....... &rmrr vm=0 %rs2 %rs1 %rd +@r_wdvm ..... wd:1 vm:1 ..... ..... ... ..... ....... &rwdvm %rs2 %rs1 %rd +@r2_zimm . zimm:11 ..... ... ..... ....... %rs1 %rd @r2_s ....... ..... ..... ... ..... ....... %rs2 %rs1 @hfence_gvma ....... ..... ..... ... ..... ....... %rs2 %rs1 @@ -220,3 +236,359 @@ hsv_h 0110011 ..... ..... 100 00000 1110011 @r2_s hsv_w 0110101 ..... ..... 100 00000 1110011 @r2_s hfence_gvma 0110001 ..... ..... 000 00000 1110011 @hfence_gvma hfence_vvma 0010001 ..... ..... 000 00000 1110011 @hfence_vvma + +# *** RV32V Extension *** + +# *** Vector loads and stores are encoded within LOADFP/STORE-FP *** +vlb_v ... 100 . 00000 ..... 000 ..... 0000111 @r2_nfvm +vlh_v ... 100 . 00000 ..... 101 ..... 0000111 @r2_nfvm +vlw_v ... 100 . 00000 ..... 110 ..... 0000111 @r2_nfvm +vle_v ... 000 . 00000 ..... 111 ..... 0000111 @r2_nfvm +vlbu_v ... 000 . 00000 ..... 000 ..... 0000111 @r2_nfvm +vlhu_v ... 000 . 00000 ..... 101 ..... 0000111 @r2_nfvm +vlwu_v ... 000 . 00000 ..... 110 ..... 0000111 @r2_nfvm +vlbff_v ... 100 . 10000 ..... 000 ..... 0000111 @r2_nfvm +vlhff_v ... 100 . 10000 ..... 101 ..... 0000111 @r2_nfvm +vlwff_v ... 100 . 10000 ..... 110 ..... 0000111 @r2_nfvm +vleff_v ... 000 . 10000 ..... 111 ..... 0000111 @r2_nfvm +vlbuff_v ... 000 . 10000 ..... 000 ..... 0000111 @r2_nfvm +vlhuff_v ... 000 . 10000 ..... 101 ..... 0000111 @r2_nfvm +vlwuff_v ... 000 . 10000 ..... 110 ..... 0000111 @r2_nfvm +vsb_v ... 000 . 00000 ..... 000 ..... 0100111 @r2_nfvm +vsh_v ... 000 . 00000 ..... 101 ..... 0100111 @r2_nfvm +vsw_v ... 000 . 00000 ..... 110 ..... 0100111 @r2_nfvm +vse_v ... 000 . 00000 ..... 111 ..... 0100111 @r2_nfvm + +vlsb_v ... 110 . ..... ..... 000 ..... 0000111 @r_nfvm +vlsh_v ... 110 . ..... ..... 101 ..... 0000111 @r_nfvm +vlsw_v ... 110 . ..... ..... 110 ..... 0000111 @r_nfvm +vlse_v ... 010 . ..... ..... 111 ..... 0000111 @r_nfvm +vlsbu_v ... 010 . ..... ..... 000 ..... 0000111 @r_nfvm +vlshu_v ... 010 . ..... ..... 101 ..... 0000111 @r_nfvm +vlswu_v ... 010 . ..... ..... 110 ..... 0000111 @r_nfvm +vssb_v ... 010 . ..... ..... 000 ..... 0100111 @r_nfvm +vssh_v ... 010 . ..... ..... 101 ..... 0100111 @r_nfvm +vssw_v ... 010 . ..... ..... 110 ..... 0100111 @r_nfvm +vsse_v ... 010 . ..... ..... 111 ..... 0100111 @r_nfvm + +vlxb_v ... 111 . ..... ..... 000 ..... 0000111 @r_nfvm +vlxh_v ... 111 . ..... ..... 101 ..... 0000111 @r_nfvm +vlxw_v ... 111 . ..... ..... 110 ..... 0000111 @r_nfvm +vlxe_v ... 011 . ..... ..... 111 ..... 0000111 @r_nfvm +vlxbu_v ... 011 . ..... ..... 000 ..... 0000111 @r_nfvm +vlxhu_v ... 011 . ..... ..... 101 ..... 0000111 @r_nfvm +vlxwu_v ... 011 . ..... ..... 110 ..... 0000111 @r_nfvm +# Vector ordered-indexed and unordered-indexed store insns. +vsxb_v ... -11 . ..... ..... 000 ..... 0100111 @r_nfvm +vsxh_v ... -11 . ..... ..... 101 ..... 0100111 @r_nfvm +vsxw_v ... -11 . ..... ..... 110 ..... 0100111 @r_nfvm +vsxe_v ... -11 . ..... ..... 111 ..... 0100111 @r_nfvm + +#*** Vector AMO operations are encoded under the standard AMO major opcode *** +vamoswapw_v 00001 . . ..... ..... 110 ..... 0101111 @r_wdvm +vamoaddw_v 00000 . . ..... ..... 110 ..... 0101111 @r_wdvm +vamoxorw_v 00100 . . ..... ..... 110 ..... 0101111 @r_wdvm +vamoandw_v 01100 . . ..... ..... 110 ..... 0101111 @r_wdvm +vamoorw_v 01000 . . ..... ..... 110 ..... 0101111 @r_wdvm +vamominw_v 10000 . . ..... ..... 110 ..... 0101111 @r_wdvm +vamomaxw_v 10100 . . ..... ..... 110 ..... 0101111 @r_wdvm +vamominuw_v 11000 . . ..... ..... 110 ..... 0101111 @r_wdvm +vamomaxuw_v 11100 . . ..... ..... 110 ..... 0101111 @r_wdvm + +# *** new major opcode OP-V *** +vadd_vv 000000 . ..... ..... 000 ..... 1010111 @r_vm +vadd_vx 000000 . ..... ..... 100 ..... 1010111 @r_vm +vadd_vi 000000 . ..... ..... 011 ..... 1010111 @r_vm +vsub_vv 000010 . ..... ..... 000 ..... 1010111 @r_vm +vsub_vx 000010 . ..... ..... 100 ..... 1010111 @r_vm +vrsub_vx 000011 . ..... ..... 100 ..... 1010111 @r_vm +vrsub_vi 000011 . ..... ..... 011 ..... 1010111 @r_vm +vwaddu_vv 110000 . ..... ..... 010 ..... 1010111 @r_vm +vwaddu_vx 110000 . ..... ..... 110 ..... 1010111 @r_vm +vwadd_vv 110001 . ..... ..... 010 ..... 1010111 @r_vm +vwadd_vx 110001 . ..... ..... 110 ..... 1010111 @r_vm +vwsubu_vv 110010 . ..... ..... 010 ..... 1010111 @r_vm +vwsubu_vx 110010 . ..... ..... 110 ..... 1010111 @r_vm +vwsub_vv 110011 . ..... ..... 010 ..... 1010111 @r_vm +vwsub_vx 110011 . ..... ..... 110 ..... 1010111 @r_vm +vwaddu_wv 110100 . ..... ..... 010 ..... 1010111 @r_vm +vwaddu_wx 110100 . ..... ..... 110 ..... 1010111 @r_vm +vwadd_wv 110101 . ..... ..... 010 ..... 1010111 @r_vm +vwadd_wx 110101 . ..... ..... 110 ..... 1010111 @r_vm +vwsubu_wv 110110 . ..... ..... 010 ..... 1010111 @r_vm +vwsubu_wx 110110 . ..... ..... 110 ..... 1010111 @r_vm +vwsub_wv 110111 . ..... ..... 010 ..... 1010111 @r_vm +vwsub_wx 110111 . ..... ..... 110 ..... 1010111 @r_vm +vadc_vvm 010000 1 ..... ..... 000 ..... 1010111 @r_vm_1 +vadc_vxm 010000 1 ..... ..... 100 ..... 1010111 @r_vm_1 +vadc_vim 010000 1 ..... ..... 011 ..... 1010111 @r_vm_1 +vmadc_vvm 010001 1 ..... ..... 000 ..... 1010111 @r_vm_1 +vmadc_vxm 010001 1 ..... ..... 100 ..... 1010111 @r_vm_1 +vmadc_vim 010001 1 ..... ..... 011 ..... 1010111 @r_vm_1 +vsbc_vvm 010010 1 ..... ..... 000 ..... 1010111 @r_vm_1 +vsbc_vxm 010010 1 ..... ..... 100 ..... 1010111 @r_vm_1 +vmsbc_vvm 010011 1 ..... ..... 000 ..... 1010111 @r_vm_1 +vmsbc_vxm 010011 1 ..... ..... 100 ..... 1010111 @r_vm_1 +vand_vv 001001 . ..... ..... 000 ..... 1010111 @r_vm +vand_vx 001001 . ..... ..... 100 ..... 1010111 @r_vm +vand_vi 001001 . ..... ..... 011 ..... 1010111 @r_vm +vor_vv 001010 . ..... ..... 000 ..... 1010111 @r_vm +vor_vx 001010 . ..... ..... 100 ..... 1010111 @r_vm +vor_vi 001010 . ..... ..... 011 ..... 1010111 @r_vm +vxor_vv 001011 . ..... ..... 000 ..... 1010111 @r_vm +vxor_vx 001011 . ..... ..... 100 ..... 1010111 @r_vm +vxor_vi 001011 . ..... ..... 011 ..... 1010111 @r_vm +vsll_vv 100101 . ..... ..... 000 ..... 1010111 @r_vm +vsll_vx 100101 . ..... ..... 100 ..... 1010111 @r_vm +vsll_vi 100101 . ..... ..... 011 ..... 1010111 @r_vm +vsrl_vv 101000 . ..... ..... 000 ..... 1010111 @r_vm +vsrl_vx 101000 . ..... ..... 100 ..... 1010111 @r_vm +vsrl_vi 101000 . ..... ..... 011 ..... 1010111 @r_vm +vsra_vv 101001 . ..... ..... 000 ..... 1010111 @r_vm +vsra_vx 101001 . ..... ..... 100 ..... 1010111 @r_vm +vsra_vi 101001 . ..... ..... 011 ..... 1010111 @r_vm +vnsrl_vv 101100 . ..... ..... 000 ..... 1010111 @r_vm +vnsrl_vx 101100 . ..... ..... 100 ..... 1010111 @r_vm +vnsrl_vi 101100 . ..... ..... 011 ..... 1010111 @r_vm +vnsra_vv 101101 . ..... ..... 000 ..... 1010111 @r_vm +vnsra_vx 101101 . ..... ..... 100 ..... 1010111 @r_vm +vnsra_vi 101101 . ..... ..... 011 ..... 1010111 @r_vm +vmseq_vv 011000 . ..... ..... 000 ..... 1010111 @r_vm +vmseq_vx 011000 . ..... ..... 100 ..... 1010111 @r_vm +vmseq_vi 011000 . ..... ..... 011 ..... 1010111 @r_vm +vmsne_vv 011001 . ..... ..... 000 ..... 1010111 @r_vm +vmsne_vx 011001 . ..... ..... 100 ..... 1010111 @r_vm +vmsne_vi 011001 . ..... ..... 011 ..... 1010111 @r_vm +vmsltu_vv 011010 . ..... ..... 000 ..... 1010111 @r_vm +vmsltu_vx 011010 . ..... ..... 100 ..... 1010111 @r_vm +vmslt_vv 011011 . ..... ..... 000 ..... 1010111 @r_vm +vmslt_vx 011011 . ..... ..... 100 ..... 1010111 @r_vm +vmsleu_vv 011100 . ..... ..... 000 ..... 1010111 @r_vm +vmsleu_vx 011100 . ..... ..... 100 ..... 1010111 @r_vm +vmsleu_vi 011100 . ..... ..... 011 ..... 1010111 @r_vm +vmsle_vv 011101 . ..... ..... 000 ..... 1010111 @r_vm +vmsle_vx 011101 . ..... ..... 100 ..... 1010111 @r_vm +vmsle_vi 011101 . ..... ..... 011 ..... 1010111 @r_vm +vmsgtu_vx 011110 . ..... ..... 100 ..... 1010111 @r_vm +vmsgtu_vi 011110 . ..... ..... 011 ..... 1010111 @r_vm +vmsgt_vx 011111 . ..... ..... 100 ..... 1010111 @r_vm +vmsgt_vi 011111 . ..... ..... 011 ..... 1010111 @r_vm +vminu_vv 000100 . ..... ..... 000 ..... 1010111 @r_vm +vminu_vx 000100 . ..... ..... 100 ..... 1010111 @r_vm +vmin_vv 000101 . ..... ..... 000 ..... 1010111 @r_vm +vmin_vx 000101 . ..... ..... 100 ..... 1010111 @r_vm +vmaxu_vv 000110 . ..... ..... 000 ..... 1010111 @r_vm +vmaxu_vx 000110 . ..... ..... 100 ..... 1010111 @r_vm +vmax_vv 000111 . ..... ..... 000 ..... 1010111 @r_vm +vmax_vx 000111 . ..... ..... 100 ..... 1010111 @r_vm +vmul_vv 100101 . ..... ..... 010 ..... 1010111 @r_vm +vmul_vx 100101 . ..... ..... 110 ..... 1010111 @r_vm +vmulh_vv 100111 . ..... ..... 010 ..... 1010111 @r_vm +vmulh_vx 100111 . ..... ..... 110 ..... 1010111 @r_vm +vmulhu_vv 100100 . ..... ..... 010 ..... 1010111 @r_vm +vmulhu_vx 100100 . ..... ..... 110 ..... 1010111 @r_vm +vmulhsu_vv 100110 . ..... ..... 010 ..... 1010111 @r_vm +vmulhsu_vx 100110 . ..... ..... 110 ..... 1010111 @r_vm +vdivu_vv 100000 . ..... ..... 010 ..... 1010111 @r_vm +vdivu_vx 100000 . ..... ..... 110 ..... 1010111 @r_vm +vdiv_vv 100001 . ..... ..... 010 ..... 1010111 @r_vm +vdiv_vx 100001 . ..... ..... 110 ..... 1010111 @r_vm +vremu_vv 100010 . ..... ..... 010 ..... 1010111 @r_vm +vremu_vx 100010 . ..... ..... 110 ..... 1010111 @r_vm +vrem_vv 100011 . ..... ..... 010 ..... 1010111 @r_vm +vrem_vx 100011 . ..... ..... 110 ..... 1010111 @r_vm +vwmulu_vv 111000 . ..... ..... 010 ..... 1010111 @r_vm +vwmulu_vx 111000 . ..... ..... 110 ..... 1010111 @r_vm +vwmulsu_vv 111010 . ..... ..... 010 ..... 1010111 @r_vm +vwmulsu_vx 111010 . ..... ..... 110 ..... 1010111 @r_vm +vwmul_vv 111011 . ..... ..... 010 ..... 1010111 @r_vm +vwmul_vx 111011 . ..... ..... 110 ..... 1010111 @r_vm +vmacc_vv 101101 . ..... ..... 010 ..... 1010111 @r_vm +vmacc_vx 101101 . ..... ..... 110 ..... 1010111 @r_vm +vnmsac_vv 101111 . ..... ..... 010 ..... 1010111 @r_vm +vnmsac_vx 101111 . ..... ..... 110 ..... 1010111 @r_vm +vmadd_vv 101001 . ..... ..... 010 ..... 1010111 @r_vm +vmadd_vx 101001 . ..... ..... 110 ..... 1010111 @r_vm +vnmsub_vv 101011 . ..... ..... 010 ..... 1010111 @r_vm +vnmsub_vx 101011 . ..... ..... 110 ..... 1010111 @r_vm +vwmaccu_vv 111100 . ..... ..... 010 ..... 1010111 @r_vm +vwmaccu_vx 111100 . ..... ..... 110 ..... 1010111 @r_vm +vwmacc_vv 111101 . ..... ..... 010 ..... 1010111 @r_vm +vwmacc_vx 111101 . ..... ..... 110 ..... 1010111 @r_vm +vwmaccsu_vv 111110 . ..... ..... 010 ..... 1010111 @r_vm +vwmaccsu_vx 111110 . ..... ..... 110 ..... 1010111 @r_vm +vwmaccus_vx 111111 . ..... ..... 110 ..... 1010111 @r_vm +vmv_v_v 010111 1 00000 ..... 000 ..... 1010111 @r2 +vmv_v_x 010111 1 00000 ..... 100 ..... 1010111 @r2 +vmv_v_i 010111 1 00000 ..... 011 ..... 1010111 @r2 +vmerge_vvm 010111 0 ..... ..... 000 ..... 1010111 @r_vm_0 +vmerge_vxm 010111 0 ..... ..... 100 ..... 1010111 @r_vm_0 +vmerge_vim 010111 0 ..... ..... 011 ..... 1010111 @r_vm_0 +vsaddu_vv 100000 . ..... ..... 000 ..... 1010111 @r_vm +vsaddu_vx 100000 . ..... ..... 100 ..... 1010111 @r_vm +vsaddu_vi 100000 . ..... ..... 011 ..... 1010111 @r_vm +vsadd_vv 100001 . ..... ..... 000 ..... 1010111 @r_vm +vsadd_vx 100001 . ..... ..... 100 ..... 1010111 @r_vm +vsadd_vi 100001 . ..... ..... 011 ..... 1010111 @r_vm +vssubu_vv 100010 . ..... ..... 000 ..... 1010111 @r_vm +vssubu_vx 100010 . ..... ..... 100 ..... 1010111 @r_vm +vssub_vv 100011 . ..... ..... 000 ..... 1010111 @r_vm +vssub_vx 100011 . ..... ..... 100 ..... 1010111 @r_vm +vaadd_vv 100100 . ..... ..... 000 ..... 1010111 @r_vm +vaadd_vx 100100 . ..... ..... 100 ..... 1010111 @r_vm +vaadd_vi 100100 . ..... ..... 011 ..... 1010111 @r_vm +vasub_vv 100110 . ..... ..... 000 ..... 1010111 @r_vm +vasub_vx 100110 . ..... ..... 100 ..... 1010111 @r_vm +vsmul_vv 100111 . ..... ..... 000 ..... 1010111 @r_vm +vsmul_vx 100111 . ..... ..... 100 ..... 1010111 @r_vm +vwsmaccu_vv 111100 . ..... ..... 000 ..... 1010111 @r_vm +vwsmaccu_vx 111100 . ..... ..... 100 ..... 1010111 @r_vm +vwsmacc_vv 111101 . ..... ..... 000 ..... 1010111 @r_vm +vwsmacc_vx 111101 . ..... ..... 100 ..... 1010111 @r_vm +vwsmaccsu_vv 111110 . ..... ..... 000 ..... 1010111 @r_vm +vwsmaccsu_vx 111110 . ..... ..... 100 ..... 1010111 @r_vm +vwsmaccus_vx 111111 . ..... ..... 100 ..... 1010111 @r_vm +vssrl_vv 101010 . ..... ..... 000 ..... 1010111 @r_vm +vssrl_vx 101010 . ..... ..... 100 ..... 1010111 @r_vm +vssrl_vi 101010 . ..... ..... 011 ..... 1010111 @r_vm +vssra_vv 101011 . ..... ..... 000 ..... 1010111 @r_vm +vssra_vx 101011 . ..... ..... 100 ..... 1010111 @r_vm +vssra_vi 101011 . ..... ..... 011 ..... 1010111 @r_vm +vnclipu_vv 101110 . ..... ..... 000 ..... 1010111 @r_vm +vnclipu_vx 101110 . ..... ..... 100 ..... 1010111 @r_vm +vnclipu_vi 101110 . ..... ..... 011 ..... 1010111 @r_vm +vnclip_vv 101111 . ..... ..... 000 ..... 1010111 @r_vm +vnclip_vx 101111 . ..... ..... 100 ..... 1010111 @r_vm +vnclip_vi 101111 . ..... ..... 011 ..... 1010111 @r_vm +vfadd_vv 000000 . ..... ..... 001 ..... 1010111 @r_vm +vfadd_vf 000000 . ..... ..... 101 ..... 1010111 @r_vm +vfsub_vv 000010 . ..... ..... 001 ..... 1010111 @r_vm +vfsub_vf 000010 . ..... ..... 101 ..... 1010111 @r_vm +vfrsub_vf 100111 . ..... ..... 101 ..... 1010111 @r_vm +vfwadd_vv 110000 . ..... ..... 001 ..... 1010111 @r_vm +vfwadd_vf 110000 . ..... ..... 101 ..... 1010111 @r_vm +vfwadd_wv 110100 . ..... ..... 001 ..... 1010111 @r_vm +vfwadd_wf 110100 . ..... ..... 101 ..... 1010111 @r_vm +vfwsub_vv 110010 . ..... ..... 001 ..... 1010111 @r_vm +vfwsub_vf 110010 . ..... ..... 101 ..... 1010111 @r_vm +vfwsub_wv 110110 . ..... ..... 001 ..... 1010111 @r_vm +vfwsub_wf 110110 . ..... ..... 101 ..... 1010111 @r_vm +vfmul_vv 100100 . ..... ..... 001 ..... 1010111 @r_vm +vfmul_vf 100100 . ..... ..... 101 ..... 1010111 @r_vm +vfdiv_vv 100000 . ..... ..... 001 ..... 1010111 @r_vm +vfdiv_vf 100000 . ..... ..... 101 ..... 1010111 @r_vm +vfrdiv_vf 100001 . ..... ..... 101 ..... 1010111 @r_vm +vfwmul_vv 111000 . ..... ..... 001 ..... 1010111 @r_vm +vfwmul_vf 111000 . ..... ..... 101 ..... 1010111 @r_vm +vfmacc_vv 101100 . ..... ..... 001 ..... 1010111 @r_vm +vfnmacc_vv 101101 . ..... ..... 001 ..... 1010111 @r_vm +vfnmacc_vf 101101 . ..... ..... 101 ..... 1010111 @r_vm +vfmacc_vf 101100 . ..... ..... 101 ..... 1010111 @r_vm +vfmsac_vv 101110 . ..... ..... 001 ..... 1010111 @r_vm +vfmsac_vf 101110 . ..... ..... 101 ..... 1010111 @r_vm +vfnmsac_vv 101111 . ..... ..... 001 ..... 1010111 @r_vm +vfnmsac_vf 101111 . ..... ..... 101 ..... 1010111 @r_vm +vfmadd_vv 101000 . ..... ..... 001 ..... 1010111 @r_vm +vfmadd_vf 101000 . ..... ..... 101 ..... 1010111 @r_vm +vfnmadd_vv 101001 . ..... ..... 001 ..... 1010111 @r_vm +vfnmadd_vf 101001 . ..... ..... 101 ..... 1010111 @r_vm +vfmsub_vv 101010 . ..... ..... 001 ..... 1010111 @r_vm +vfmsub_vf 101010 . ..... ..... 101 ..... 1010111 @r_vm +vfnmsub_vv 101011 . ..... ..... 001 ..... 1010111 @r_vm +vfnmsub_vf 101011 . ..... ..... 101 ..... 1010111 @r_vm +vfwmacc_vv 111100 . ..... ..... 001 ..... 1010111 @r_vm +vfwmacc_vf 111100 . ..... ..... 101 ..... 1010111 @r_vm +vfwnmacc_vv 111101 . ..... ..... 001 ..... 1010111 @r_vm +vfwnmacc_vf 111101 . ..... ..... 101 ..... 1010111 @r_vm +vfwmsac_vv 111110 . ..... ..... 001 ..... 1010111 @r_vm +vfwmsac_vf 111110 . ..... ..... 101 ..... 1010111 @r_vm +vfwnmsac_vv 111111 . ..... ..... 001 ..... 1010111 @r_vm +vfwnmsac_vf 111111 . ..... ..... 101 ..... 1010111 @r_vm +vfsqrt_v 100011 . ..... 00000 001 ..... 1010111 @r2_vm +vfmin_vv 000100 . ..... ..... 001 ..... 1010111 @r_vm +vfmin_vf 000100 . ..... ..... 101 ..... 1010111 @r_vm +vfmax_vv 000110 . ..... ..... 001 ..... 1010111 @r_vm +vfmax_vf 000110 . ..... ..... 101 ..... 1010111 @r_vm +vfsgnj_vv 001000 . ..... ..... 001 ..... 1010111 @r_vm +vfsgnj_vf 001000 . ..... ..... 101 ..... 1010111 @r_vm +vfsgnjn_vv 001001 . ..... ..... 001 ..... 1010111 @r_vm +vfsgnjn_vf 001001 . ..... ..... 101 ..... 1010111 @r_vm +vfsgnjx_vv 001010 . ..... ..... 001 ..... 1010111 @r_vm +vfsgnjx_vf 001010 . ..... ..... 101 ..... 1010111 @r_vm +vmfeq_vv 011000 . ..... ..... 001 ..... 1010111 @r_vm +vmfeq_vf 011000 . ..... ..... 101 ..... 1010111 @r_vm +vmfne_vv 011100 . ..... ..... 001 ..... 1010111 @r_vm +vmfne_vf 011100 . ..... ..... 101 ..... 1010111 @r_vm +vmflt_vv 011011 . ..... ..... 001 ..... 1010111 @r_vm +vmflt_vf 011011 . ..... ..... 101 ..... 1010111 @r_vm +vmfle_vv 011001 . ..... ..... 001 ..... 1010111 @r_vm +vmfle_vf 011001 . ..... ..... 101 ..... 1010111 @r_vm +vmfgt_vf 011101 . ..... ..... 101 ..... 1010111 @r_vm +vmfge_vf 011111 . ..... ..... 101 ..... 1010111 @r_vm +vmford_vv 011010 . ..... ..... 001 ..... 1010111 @r_vm +vmford_vf 011010 . ..... ..... 101 ..... 1010111 @r_vm +vfclass_v 100011 . ..... 10000 001 ..... 1010111 @r2_vm +vfmerge_vfm 010111 0 ..... ..... 101 ..... 1010111 @r_vm_0 +vfmv_v_f 010111 1 00000 ..... 101 ..... 1010111 @r2 +vfcvt_xu_f_v 100010 . ..... 00000 001 ..... 1010111 @r2_vm +vfcvt_x_f_v 100010 . ..... 00001 001 ..... 1010111 @r2_vm +vfcvt_f_xu_v 100010 . ..... 00010 001 ..... 1010111 @r2_vm +vfcvt_f_x_v 100010 . ..... 00011 001 ..... 1010111 @r2_vm +vfwcvt_xu_f_v 100010 . ..... 01000 001 ..... 1010111 @r2_vm +vfwcvt_x_f_v 100010 . ..... 01001 001 ..... 1010111 @r2_vm +vfwcvt_f_xu_v 100010 . ..... 01010 001 ..... 1010111 @r2_vm +vfwcvt_f_x_v 100010 . ..... 01011 001 ..... 1010111 @r2_vm +vfwcvt_f_f_v 100010 . ..... 01100 001 ..... 1010111 @r2_vm +vfncvt_xu_f_v 100010 . ..... 10000 001 ..... 1010111 @r2_vm +vfncvt_x_f_v 100010 . ..... 10001 001 ..... 1010111 @r2_vm +vfncvt_f_xu_v 100010 . ..... 10010 001 ..... 1010111 @r2_vm +vfncvt_f_x_v 100010 . ..... 10011 001 ..... 1010111 @r2_vm +vfncvt_f_f_v 100010 . ..... 10100 001 ..... 1010111 @r2_vm +vredsum_vs 000000 . ..... ..... 010 ..... 1010111 @r_vm +vredand_vs 000001 . ..... ..... 010 ..... 1010111 @r_vm +vredor_vs 000010 . ..... ..... 010 ..... 1010111 @r_vm +vredxor_vs 000011 . ..... ..... 010 ..... 1010111 @r_vm +vredminu_vs 000100 . ..... ..... 010 ..... 1010111 @r_vm +vredmin_vs 000101 . ..... ..... 010 ..... 1010111 @r_vm +vredmaxu_vs 000110 . ..... ..... 010 ..... 1010111 @r_vm +vredmax_vs 000111 . ..... ..... 010 ..... 1010111 @r_vm +vwredsumu_vs 110000 . ..... ..... 000 ..... 1010111 @r_vm +vwredsum_vs 110001 . ..... ..... 000 ..... 1010111 @r_vm +# Vector ordered and unordered reduction sum +vfredsum_vs 0000-1 . ..... ..... 001 ..... 1010111 @r_vm +vfredmin_vs 000101 . ..... ..... 001 ..... 1010111 @r_vm +vfredmax_vs 000111 . ..... ..... 001 ..... 1010111 @r_vm +# Vector widening ordered and unordered float reduction sum +vfwredsum_vs 1100-1 . ..... ..... 001 ..... 1010111 @r_vm +vmand_mm 011001 - ..... ..... 010 ..... 1010111 @r +vmnand_mm 011101 - ..... ..... 010 ..... 1010111 @r +vmandnot_mm 011000 - ..... ..... 010 ..... 1010111 @r +vmxor_mm 011011 - ..... ..... 010 ..... 1010111 @r +vmor_mm 011010 - ..... ..... 010 ..... 1010111 @r +vmnor_mm 011110 - ..... ..... 010 ..... 1010111 @r +vmornot_mm 011100 - ..... ..... 010 ..... 1010111 @r +vmxnor_mm 011111 - ..... ..... 010 ..... 1010111 @r +vmpopc_m 010100 . ..... ----- 010 ..... 1010111 @r2_vm +vmfirst_m 010101 . ..... ----- 010 ..... 1010111 @r2_vm +vmsbf_m 010110 . ..... 00001 010 ..... 1010111 @r2_vm +vmsif_m 010110 . ..... 00011 010 ..... 1010111 @r2_vm +vmsof_m 010110 . ..... 00010 010 ..... 1010111 @r2_vm +viota_m 010110 . ..... 10000 010 ..... 1010111 @r2_vm +vid_v 010110 . 00000 10001 010 ..... 1010111 @r1_vm +vext_x_v 001100 1 ..... ..... 010 ..... 1010111 @r +vmv_s_x 001101 1 00000 ..... 110 ..... 1010111 @r2 +vfmv_f_s 001100 1 ..... 00000 001 ..... 1010111 @r2rd +vfmv_s_f 001101 1 00000 ..... 101 ..... 1010111 @r2 +vslideup_vx 001110 . ..... ..... 100 ..... 1010111 @r_vm +vslideup_vi 001110 . ..... ..... 011 ..... 1010111 @r_vm +vslide1up_vx 001110 . ..... ..... 110 ..... 1010111 @r_vm +vslidedown_vx 001111 . ..... ..... 100 ..... 1010111 @r_vm +vslidedown_vi 001111 . ..... ..... 011 ..... 1010111 @r_vm +vslide1down_vx 001111 . ..... ..... 110 ..... 1010111 @r_vm +vrgather_vv 001100 . ..... ..... 000 ..... 1010111 @r_vm +vrgather_vx 001100 . ..... ..... 100 ..... 1010111 @r_vm +vrgather_vi 001100 . ..... ..... 011 ..... 1010111 @r_vm +vcompress_vm 010111 - ..... ..... 010 ..... 1010111 @r + +vsetvli 0 ........... ..... 111 ..... 1010111 @r2_zimm +vsetvl 1000000 ..... ..... 111 ..... 1010111 @r diff --git a/target/riscv/insn_trans/trans_privileged.inc.c b/target/riscv/insn_trans/trans_privileged.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_privileged.inc.c rename to target/riscv/insn_trans/trans_privileged.c.inc diff --git a/target/riscv/insn_trans/trans_rva.inc.c b/target/riscv/insn_trans/trans_rva.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rva.inc.c rename to target/riscv/insn_trans/trans_rva.c.inc diff --git a/target/riscv/insn_trans/trans_rvd.inc.c b/target/riscv/insn_trans/trans_rvd.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvd.inc.c rename to target/riscv/insn_trans/trans_rvd.c.inc index ea1044f13b46e656279335f59702560e56831de8..4f832637fa810ea2a23778ec01c26fb7f417fcfc 100644 --- a/target/riscv/insn_trans/trans_rvd.inc.c +++ b/target/riscv/insn_trans/trans_rvd.c.inc @@ -20,10 +20,10 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a) { - TCGv t0 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); + TCGv t0 = tcg_temp_new(); + gen_get_gpr(t0, a->rs1); tcg_gen_addi_tl(t0, t0, a->imm); tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], t0, ctx->mem_idx, MO_TEQ); @@ -35,10 +35,10 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a) static bool trans_fsd(DisasContext *ctx, arg_fsd *a) { - TCGv t0 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); + TCGv t0 = tcg_temp_new(); + gen_get_gpr(t0, a->rs1); tcg_gen_addi_tl(t0, t0, a->imm); tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, MO_TEQ); diff --git a/target/riscv/insn_trans/trans_rvf.inc.c b/target/riscv/insn_trans/trans_rvf.c.inc similarity index 84% rename from target/riscv/insn_trans/trans_rvf.inc.c rename to target/riscv/insn_trans/trans_rvf.c.inc index e23cd639a626ade9056d2b0b7ec6a73d5dcb7c22..3dfec8211df07b8f560171f79207d92717bacfcb 100644 --- a/target/riscv/insn_trans/trans_rvf.inc.c +++ b/target/riscv/insn_trans/trans_rvf.c.inc @@ -25,15 +25,14 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a) { - TCGv t0 = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); + TCGv t0 = tcg_temp_new(); + gen_get_gpr(t0, a->rs1); tcg_gen_addi_tl(t0, t0, a->imm); tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], t0, ctx->mem_idx, MO_TEUL); - /* RISC-V requires NaN-boxing of narrower width floating point values */ - tcg_gen_ori_i64(cpu_fpr[a->rd], cpu_fpr[a->rd], 0xffffffff00000000ULL); + gen_nanbox_s(cpu_fpr[a->rd], cpu_fpr[a->rd]); tcg_temp_free(t0); mark_fs_dirty(ctx); @@ -42,11 +41,11 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a) static bool trans_fsw(DisasContext *ctx, arg_fsw *a) { + REQUIRE_FPU; + REQUIRE_EXT(ctx, RVF); TCGv t0 = tcg_temp_new(); gen_get_gpr(t0, a->rs1); - REQUIRE_FPU; - REQUIRE_EXT(ctx, RVF); tcg_gen_addi_tl(t0, t0, a->imm); tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, MO_TEUL); @@ -162,11 +161,20 @@ static bool trans_fsgnj_s(DisasContext *ctx, arg_fsgnj_s *a) { REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); + if (a->rs1 == a->rs2) { /* FMOV */ - tcg_gen_mov_i64(cpu_fpr[a->rd], cpu_fpr[a->rs1]); + gen_check_nanbox_s(cpu_fpr[a->rd], cpu_fpr[a->rs1]); } else { /* FSGNJ */ - tcg_gen_deposit_i64(cpu_fpr[a->rd], cpu_fpr[a->rs2], cpu_fpr[a->rs1], - 0, 31); + TCGv_i64 rs1 = tcg_temp_new_i64(); + TCGv_i64 rs2 = tcg_temp_new_i64(); + + gen_check_nanbox_s(rs1, cpu_fpr[a->rs1]); + gen_check_nanbox_s(rs2, cpu_fpr[a->rs2]); + + /* This formulation retains the nanboxing of rs2. */ + tcg_gen_deposit_i64(cpu_fpr[a->rd], rs2, rs1, 0, 31); + tcg_temp_free_i64(rs1); + tcg_temp_free_i64(rs2); } mark_fs_dirty(ctx); return true; @@ -174,32 +182,65 @@ static bool trans_fsgnj_s(DisasContext *ctx, arg_fsgnj_s *a) static bool trans_fsgnjn_s(DisasContext *ctx, arg_fsgnjn_s *a) { + TCGv_i64 rs1, rs2, mask; + REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); + + rs1 = tcg_temp_new_i64(); + gen_check_nanbox_s(rs1, cpu_fpr[a->rs1]); + if (a->rs1 == a->rs2) { /* FNEG */ - tcg_gen_xori_i64(cpu_fpr[a->rd], cpu_fpr[a->rs1], INT32_MIN); + tcg_gen_xori_i64(cpu_fpr[a->rd], rs1, MAKE_64BIT_MASK(31, 1)); } else { - TCGv_i64 t0 = tcg_temp_new_i64(); - tcg_gen_not_i64(t0, cpu_fpr[a->rs2]); - tcg_gen_deposit_i64(cpu_fpr[a->rd], t0, cpu_fpr[a->rs1], 0, 31); - tcg_temp_free_i64(t0); + rs2 = tcg_temp_new_i64(); + gen_check_nanbox_s(rs2, cpu_fpr[a->rs2]); + + /* + * Replace bit 31 in rs1 with inverse in rs2. + * This formulation retains the nanboxing of rs1. + */ + mask = tcg_const_i64(~MAKE_64BIT_MASK(31, 1)); + tcg_gen_nor_i64(rs2, rs2, mask); + tcg_gen_and_i64(rs1, mask, rs1); + tcg_gen_or_i64(cpu_fpr[a->rd], rs1, rs2); + + tcg_temp_free_i64(mask); + tcg_temp_free_i64(rs2); } + tcg_temp_free_i64(rs1); + mark_fs_dirty(ctx); return true; } static bool trans_fsgnjx_s(DisasContext *ctx, arg_fsgnjx_s *a) { + TCGv_i64 rs1, rs2; + REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); + + rs1 = tcg_temp_new_i64(); + gen_check_nanbox_s(rs1, cpu_fpr[a->rs1]); + if (a->rs1 == a->rs2) { /* FABS */ - tcg_gen_andi_i64(cpu_fpr[a->rd], cpu_fpr[a->rs1], ~INT32_MIN); + tcg_gen_andi_i64(cpu_fpr[a->rd], rs1, ~MAKE_64BIT_MASK(31, 1)); } else { - TCGv_i64 t0 = tcg_temp_new_i64(); - tcg_gen_andi_i64(t0, cpu_fpr[a->rs2], INT32_MIN); - tcg_gen_xor_i64(cpu_fpr[a->rd], cpu_fpr[a->rs1], t0); - tcg_temp_free_i64(t0); + rs2 = tcg_temp_new_i64(); + gen_check_nanbox_s(rs2, cpu_fpr[a->rs2]); + + /* + * Xor bit 31 in rs1 with that in rs2. + * This formulation retains the nanboxing of rs1. + */ + tcg_gen_andi_i64(rs2, rs2, MAKE_64BIT_MASK(31, 1)); + tcg_gen_xor_i64(cpu_fpr[a->rd], rs1, rs2); + + tcg_temp_free_i64(rs2); } + tcg_temp_free_i64(rs1); + mark_fs_dirty(ctx); return true; } @@ -365,11 +406,8 @@ static bool trans_fmv_w_x(DisasContext *ctx, arg_fmv_w_x *a) TCGv t0 = tcg_temp_new(); gen_get_gpr(t0, a->rs1); -#if defined(TARGET_RISCV64) - tcg_gen_mov_i64(cpu_fpr[a->rd], t0); -#else - tcg_gen_extu_i32_i64(cpu_fpr[a->rd], t0); -#endif + tcg_gen_extu_tl_i64(cpu_fpr[a->rd], t0); + gen_nanbox_s(cpu_fpr[a->rd], cpu_fpr[a->rd]); mark_fs_dirty(ctx); tcg_temp_free(t0); diff --git a/target/riscv/insn_trans/trans_rvh.inc.c b/target/riscv/insn_trans/trans_rvh.c.inc similarity index 61% rename from target/riscv/insn_trans/trans_rvh.inc.c rename to target/riscv/insn_trans/trans_rvh.c.inc index 881c9ef4d260796404e86229548b890f4b449ae5..ce7ed5affb4aad53f282079a00342a057ea4533c 100644 --- a/target/riscv/insn_trans/trans_rvh.inc.c +++ b/target/riscv/insn_trans/trans_rvh.c.inc @@ -16,26 +16,34 @@ * this program. If not, see . */ +#ifndef CONFIG_USER_ONLY +static void check_access(DisasContext *ctx) { + if (!ctx->hlsx) { + if (ctx->virt_enabled) { + generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT); + } else { + generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); + } + } +} +#endif + static bool trans_hlv_b(DisasContext *ctx, arg_hlv_b *a) { REQUIRE_EXT(ctx, RVH); #ifndef CONFIG_USER_ONLY TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - TCGv mem_idx = tcg_temp_new(); - TCGv memop = tcg_temp_new(); + + check_access(ctx); gen_get_gpr(t0, a->rs1); - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(memop, MO_SB); - gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_SB); gen_set_gpr(a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); - tcg_temp_free(mem_idx); - tcg_temp_free(memop); return true; #else return false; @@ -48,20 +56,16 @@ static bool trans_hlv_h(DisasContext *ctx, arg_hlv_h *a) #ifndef CONFIG_USER_ONLY TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - TCGv mem_idx = tcg_temp_new(); - TCGv memop = tcg_temp_new(); + + check_access(ctx); gen_get_gpr(t0, a->rs1); - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(memop, MO_TESW); - gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESW); gen_set_gpr(a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); - tcg_temp_free(mem_idx); - tcg_temp_free(memop); return true; #else return false; @@ -74,20 +78,16 @@ static bool trans_hlv_w(DisasContext *ctx, arg_hlv_w *a) #ifndef CONFIG_USER_ONLY TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - TCGv mem_idx = tcg_temp_new(); - TCGv memop = tcg_temp_new(); + + check_access(ctx); gen_get_gpr(t0, a->rs1); - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(memop, MO_TESL); - gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESL); gen_set_gpr(a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); - tcg_temp_free(mem_idx); - tcg_temp_free(memop); return true; #else return false; @@ -100,20 +100,16 @@ static bool trans_hlv_bu(DisasContext *ctx, arg_hlv_bu *a) #ifndef CONFIG_USER_ONLY TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - TCGv mem_idx = tcg_temp_new(); - TCGv memop = tcg_temp_new(); + + check_access(ctx); gen_get_gpr(t0, a->rs1); - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(memop, MO_UB); - gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_UB); gen_set_gpr(a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); - tcg_temp_free(mem_idx); - tcg_temp_free(memop); return true; #else return false; @@ -126,20 +122,15 @@ static bool trans_hlv_hu(DisasContext *ctx, arg_hlv_hu *a) #ifndef CONFIG_USER_ONLY TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - TCGv mem_idx = tcg_temp_new(); - TCGv memop = tcg_temp_new(); - gen_get_gpr(t0, a->rs1); - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(memop, MO_TEUW); + check_access(ctx); - gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); + gen_get_gpr(t0, a->rs1); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEUW); gen_set_gpr(a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); - tcg_temp_free(mem_idx); - tcg_temp_free(memop); return true; #else return false; @@ -152,20 +143,16 @@ static bool trans_hsv_b(DisasContext *ctx, arg_hsv_b *a) #ifndef CONFIG_USER_ONLY TCGv t0 = tcg_temp_new(); TCGv dat = tcg_temp_new(); - TCGv mem_idx = tcg_temp_new(); - TCGv memop = tcg_temp_new(); + + check_access(ctx); gen_get_gpr(t0, a->rs1); gen_get_gpr(dat, a->rs2); - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(memop, MO_SB); - gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop); + tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_SB); tcg_temp_free(t0); tcg_temp_free(dat); - tcg_temp_free(mem_idx); - tcg_temp_free(memop); return true; #else return false; @@ -178,20 +165,16 @@ static bool trans_hsv_h(DisasContext *ctx, arg_hsv_h *a) #ifndef CONFIG_USER_ONLY TCGv t0 = tcg_temp_new(); TCGv dat = tcg_temp_new(); - TCGv mem_idx = tcg_temp_new(); - TCGv memop = tcg_temp_new(); + + check_access(ctx); gen_get_gpr(t0, a->rs1); gen_get_gpr(dat, a->rs2); - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(memop, MO_TESW); - gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop); + tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESW); tcg_temp_free(t0); tcg_temp_free(dat); - tcg_temp_free(mem_idx); - tcg_temp_free(memop); return true; #else return false; @@ -204,20 +187,16 @@ static bool trans_hsv_w(DisasContext *ctx, arg_hsv_w *a) #ifndef CONFIG_USER_ONLY TCGv t0 = tcg_temp_new(); TCGv dat = tcg_temp_new(); - TCGv mem_idx = tcg_temp_new(); - TCGv memop = tcg_temp_new(); + + check_access(ctx); gen_get_gpr(t0, a->rs1); gen_get_gpr(dat, a->rs2); - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(memop, MO_TESL); - gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop); + tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TESL); tcg_temp_free(t0); tcg_temp_free(dat); - tcg_temp_free(mem_idx); - tcg_temp_free(memop); return true; #else return false; @@ -231,20 +210,16 @@ static bool trans_hlv_wu(DisasContext *ctx, arg_hlv_wu *a) #ifndef CONFIG_USER_ONLY TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - TCGv mem_idx = tcg_temp_new(); - TCGv memop = tcg_temp_new(); + + check_access(ctx); gen_get_gpr(t0, a->rs1); - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(memop, MO_TEUL); - gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEUL); gen_set_gpr(a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); - tcg_temp_free(mem_idx); - tcg_temp_free(memop); return true; #else return false; @@ -257,20 +232,16 @@ static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a) #ifndef CONFIG_USER_ONLY TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - TCGv mem_idx = tcg_temp_new(); - TCGv memop = tcg_temp_new(); + + check_access(ctx); gen_get_gpr(t0, a->rs1); - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(memop, MO_TEQ); - gen_helper_hyp_load(t1, cpu_env, t0, mem_idx, memop); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEQ); gen_set_gpr(a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); - tcg_temp_free(mem_idx); - tcg_temp_free(memop); return true; #else return false; @@ -283,20 +254,16 @@ static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a) #ifndef CONFIG_USER_ONLY TCGv t0 = tcg_temp_new(); TCGv dat = tcg_temp_new(); - TCGv mem_idx = tcg_temp_new(); - TCGv memop = tcg_temp_new(); + + check_access(ctx); gen_get_gpr(t0, a->rs1); gen_get_gpr(dat, a->rs2); - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(memop, MO_TEQ); - gen_helper_hyp_store(cpu_env, t0, dat, mem_idx, memop); + tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK, MO_TEQ); tcg_temp_free(t0); tcg_temp_free(dat); - tcg_temp_free(mem_idx); - tcg_temp_free(memop); return true; #else return false; @@ -310,20 +277,16 @@ static bool trans_hlvx_hu(DisasContext *ctx, arg_hlvx_hu *a) #ifndef CONFIG_USER_ONLY TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - TCGv mem_idx = tcg_temp_new(); - TCGv memop = tcg_temp_new(); + + check_access(ctx); gen_get_gpr(t0, a->rs1); - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(memop, MO_TEUW); - gen_helper_hyp_x_load(t1, cpu_env, t0, mem_idx, memop); + gen_helper_hyp_hlvx_hu(t1, cpu_env, t0); gen_set_gpr(a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); - tcg_temp_free(mem_idx); - tcg_temp_free(memop); return true; #else return false; @@ -336,20 +299,16 @@ static bool trans_hlvx_wu(DisasContext *ctx, arg_hlvx_wu *a) #ifndef CONFIG_USER_ONLY TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); - TCGv mem_idx = tcg_temp_new(); - TCGv memop = tcg_temp_new(); + + check_access(ctx); gen_get_gpr(t0, a->rs1); - tcg_gen_movi_tl(mem_idx, ctx->mem_idx); - tcg_gen_movi_tl(memop, MO_TEUL); - gen_helper_hyp_x_load(t1, cpu_env, t0, mem_idx, memop); + gen_helper_hyp_hlvx_wu(t1, cpu_env, t0); gen_set_gpr(a->rd, t1); tcg_temp_free(t0); tcg_temp_free(t1); - tcg_temp_free(mem_idx); - tcg_temp_free(memop); return true; #else return false; diff --git a/target/riscv/insn_trans/trans_rvi.inc.c b/target/riscv/insn_trans/trans_rvi.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvi.inc.c rename to target/riscv/insn_trans/trans_rvi.c.inc diff --git a/target/riscv/insn_trans/trans_rvm.inc.c b/target/riscv/insn_trans/trans_rvm.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvm.inc.c rename to target/riscv/insn_trans/trans_rvm.c.inc diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc new file mode 100644 index 0000000000000000000000000000000000000000..887c6b8883173d7c3d735a4d6c2f26c3d922e7bd --- /dev/null +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -0,0 +1,2902 @@ +/* + * RISC-V translation routines for the RVV Standard Extension. + * + * Copyright (c) 2020 T-Head Semiconductor Co., Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ +#include "tcg/tcg-op-gvec.h" +#include "tcg/tcg-gvec-desc.h" +#include "internals.h" + +static bool trans_vsetvl(DisasContext *ctx, arg_vsetvl *a) +{ + TCGv s1, s2, dst; + + if (!has_ext(ctx, RVV)) { + return false; + } + + s2 = tcg_temp_new(); + dst = tcg_temp_new(); + + /* Using x0 as the rs1 register specifier, encodes an infinite AVL */ + if (a->rs1 == 0) { + /* As the mask is at least one bit, RV_VLEN_MAX is >= VLMAX */ + s1 = tcg_const_tl(RV_VLEN_MAX); + } else { + s1 = tcg_temp_new(); + gen_get_gpr(s1, a->rs1); + } + gen_get_gpr(s2, a->rs2); + gen_helper_vsetvl(dst, cpu_env, s1, s2); + gen_set_gpr(a->rd, dst); + tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); + lookup_and_goto_ptr(ctx); + ctx->base.is_jmp = DISAS_NORETURN; + + tcg_temp_free(s1); + tcg_temp_free(s2); + tcg_temp_free(dst); + return true; +} + +static bool trans_vsetvli(DisasContext *ctx, arg_vsetvli *a) +{ + TCGv s1, s2, dst; + + if (!has_ext(ctx, RVV)) { + return false; + } + + s2 = tcg_const_tl(a->zimm); + dst = tcg_temp_new(); + + /* Using x0 as the rs1 register specifier, encodes an infinite AVL */ + if (a->rs1 == 0) { + /* As the mask is at least one bit, RV_VLEN_MAX is >= VLMAX */ + s1 = tcg_const_tl(RV_VLEN_MAX); + } else { + s1 = tcg_temp_new(); + gen_get_gpr(s1, a->rs1); + } + gen_helper_vsetvl(dst, cpu_env, s1, s2); + gen_set_gpr(a->rd, dst); + gen_goto_tb(ctx, 0, ctx->pc_succ_insn); + ctx->base.is_jmp = DISAS_NORETURN; + + tcg_temp_free(s1); + tcg_temp_free(s2); + tcg_temp_free(dst); + return true; +} + +/* vector register offset from env */ +static uint32_t vreg_ofs(DisasContext *s, int reg) +{ + return offsetof(CPURISCVState, vreg) + reg * s->vlen / 8; +} + +/* check functions */ + +/* + * In cpu_get_tb_cpu_state(), set VILL if RVV was not present. + * So RVV is also be checked in this function. + */ +static bool vext_check_isa_ill(DisasContext *s) +{ + return !s->vill; +} + +/* + * There are two rules check here. + * + * 1. Vector register numbers are multiples of LMUL. (Section 3.2) + * + * 2. For all widening instructions, the destination LMUL value must also be + * a supported LMUL value. (Section 11.2) + */ +static bool vext_check_reg(DisasContext *s, uint32_t reg, bool widen) +{ + /* + * The destination vector register group results are arranged as if both + * SEW and LMUL were at twice their current settings. (Section 11.2). + */ + int legal = widen ? 2 << s->lmul : 1 << s->lmul; + + return !((s->lmul == 0x3 && widen) || (reg % legal)); +} + +/* + * There are two rules check here. + * + * 1. The destination vector register group for a masked vector instruction can + * only overlap the source mask register (v0) when LMUL=1. (Section 5.3) + * + * 2. In widen instructions and some other insturctions, like vslideup.vx, + * there is no need to check whether LMUL=1. + */ +static bool vext_check_overlap_mask(DisasContext *s, uint32_t vd, bool vm, + bool force) +{ + return (vm != 0 || vd != 0) || (!force && (s->lmul == 0)); +} + +/* The LMUL setting must be such that LMUL * NFIELDS <= 8. (Section 7.8) */ +static bool vext_check_nf(DisasContext *s, uint32_t nf) +{ + return (1 << s->lmul) * nf <= 8; +} + +/* + * The destination vector register group cannot overlap a source vector register + * group of a different element width. (Section 11.2) + */ +static inline bool vext_check_overlap_group(int rd, int dlen, int rs, int slen) +{ + return ((rd >= rs + slen) || (rs >= rd + dlen)); +} +/* common translation macro */ +#define GEN_VEXT_TRANS(NAME, SEQ, ARGTYPE, OP, CHECK) \ +static bool trans_##NAME(DisasContext *s, arg_##ARGTYPE *a)\ +{ \ + if (CHECK(s, a)) { \ + return OP(s, a, SEQ); \ + } \ + return false; \ +} + +/* + *** unit stride load and store + */ +typedef void gen_helper_ldst_us(TCGv_ptr, TCGv_ptr, TCGv, + TCGv_env, TCGv_i32); + +static bool ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data, + gen_helper_ldst_us *fn, DisasContext *s) +{ + TCGv_ptr dest, mask; + TCGv base; + TCGv_i32 desc; + + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + dest = tcg_temp_new_ptr(); + mask = tcg_temp_new_ptr(); + base = tcg_temp_new(); + + /* + * As simd_desc supports at most 256 bytes, and in this implementation, + * the max vector group length is 2048 bytes. So split it into two parts. + * + * The first part is vlen in bytes, encoded in maxsz of simd_desc. + * The second part is lmul, encoded in data of simd_desc. + */ + desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + + gen_get_gpr(base, rs1); + tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); + tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); + + fn(dest, mask, base, cpu_env, desc); + + tcg_temp_free_ptr(dest); + tcg_temp_free_ptr(mask); + tcg_temp_free(base); + tcg_temp_free_i32(desc); + gen_set_label(over); + return true; +} + +static bool ld_us_op(DisasContext *s, arg_r2nfvm *a, uint8_t seq) +{ + uint32_t data = 0; + gen_helper_ldst_us *fn; + static gen_helper_ldst_us * const fns[2][7][4] = { + /* masked unit stride load */ + { { gen_helper_vlb_v_b_mask, gen_helper_vlb_v_h_mask, + gen_helper_vlb_v_w_mask, gen_helper_vlb_v_d_mask }, + { NULL, gen_helper_vlh_v_h_mask, + gen_helper_vlh_v_w_mask, gen_helper_vlh_v_d_mask }, + { NULL, NULL, + gen_helper_vlw_v_w_mask, gen_helper_vlw_v_d_mask }, + { gen_helper_vle_v_b_mask, gen_helper_vle_v_h_mask, + gen_helper_vle_v_w_mask, gen_helper_vle_v_d_mask }, + { gen_helper_vlbu_v_b_mask, gen_helper_vlbu_v_h_mask, + gen_helper_vlbu_v_w_mask, gen_helper_vlbu_v_d_mask }, + { NULL, gen_helper_vlhu_v_h_mask, + gen_helper_vlhu_v_w_mask, gen_helper_vlhu_v_d_mask }, + { NULL, NULL, + gen_helper_vlwu_v_w_mask, gen_helper_vlwu_v_d_mask } }, + /* unmasked unit stride load */ + { { gen_helper_vlb_v_b, gen_helper_vlb_v_h, + gen_helper_vlb_v_w, gen_helper_vlb_v_d }, + { NULL, gen_helper_vlh_v_h, + gen_helper_vlh_v_w, gen_helper_vlh_v_d }, + { NULL, NULL, + gen_helper_vlw_v_w, gen_helper_vlw_v_d }, + { gen_helper_vle_v_b, gen_helper_vle_v_h, + gen_helper_vle_v_w, gen_helper_vle_v_d }, + { gen_helper_vlbu_v_b, gen_helper_vlbu_v_h, + gen_helper_vlbu_v_w, gen_helper_vlbu_v_d }, + { NULL, gen_helper_vlhu_v_h, + gen_helper_vlhu_v_w, gen_helper_vlhu_v_d }, + { NULL, NULL, + gen_helper_vlwu_v_w, gen_helper_vlwu_v_d } } + }; + + fn = fns[a->vm][seq][s->sew]; + if (fn == NULL) { + return false; + } + + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, VM, a->vm); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + data = FIELD_DP32(data, VDATA, NF, a->nf); + return ldst_us_trans(a->rd, a->rs1, data, fn, s); +} + +static bool ld_us_check(DisasContext *s, arg_r2nfvm* a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, false) && + vext_check_reg(s, a->rd, false) && + vext_check_nf(s, a->nf)); +} + +GEN_VEXT_TRANS(vlb_v, 0, r2nfvm, ld_us_op, ld_us_check) +GEN_VEXT_TRANS(vlh_v, 1, r2nfvm, ld_us_op, ld_us_check) +GEN_VEXT_TRANS(vlw_v, 2, r2nfvm, ld_us_op, ld_us_check) +GEN_VEXT_TRANS(vle_v, 3, r2nfvm, ld_us_op, ld_us_check) +GEN_VEXT_TRANS(vlbu_v, 4, r2nfvm, ld_us_op, ld_us_check) +GEN_VEXT_TRANS(vlhu_v, 5, r2nfvm, ld_us_op, ld_us_check) +GEN_VEXT_TRANS(vlwu_v, 6, r2nfvm, ld_us_op, ld_us_check) + +static bool st_us_op(DisasContext *s, arg_r2nfvm *a, uint8_t seq) +{ + uint32_t data = 0; + gen_helper_ldst_us *fn; + static gen_helper_ldst_us * const fns[2][4][4] = { + /* masked unit stride load and store */ + { { gen_helper_vsb_v_b_mask, gen_helper_vsb_v_h_mask, + gen_helper_vsb_v_w_mask, gen_helper_vsb_v_d_mask }, + { NULL, gen_helper_vsh_v_h_mask, + gen_helper_vsh_v_w_mask, gen_helper_vsh_v_d_mask }, + { NULL, NULL, + gen_helper_vsw_v_w_mask, gen_helper_vsw_v_d_mask }, + { gen_helper_vse_v_b_mask, gen_helper_vse_v_h_mask, + gen_helper_vse_v_w_mask, gen_helper_vse_v_d_mask } }, + /* unmasked unit stride store */ + { { gen_helper_vsb_v_b, gen_helper_vsb_v_h, + gen_helper_vsb_v_w, gen_helper_vsb_v_d }, + { NULL, gen_helper_vsh_v_h, + gen_helper_vsh_v_w, gen_helper_vsh_v_d }, + { NULL, NULL, + gen_helper_vsw_v_w, gen_helper_vsw_v_d }, + { gen_helper_vse_v_b, gen_helper_vse_v_h, + gen_helper_vse_v_w, gen_helper_vse_v_d } } + }; + + fn = fns[a->vm][seq][s->sew]; + if (fn == NULL) { + return false; + } + + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, VM, a->vm); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + data = FIELD_DP32(data, VDATA, NF, a->nf); + return ldst_us_trans(a->rd, a->rs1, data, fn, s); +} + +static bool st_us_check(DisasContext *s, arg_r2nfvm* a) +{ + return (vext_check_isa_ill(s) && + vext_check_reg(s, a->rd, false) && + vext_check_nf(s, a->nf)); +} + +GEN_VEXT_TRANS(vsb_v, 0, r2nfvm, st_us_op, st_us_check) +GEN_VEXT_TRANS(vsh_v, 1, r2nfvm, st_us_op, st_us_check) +GEN_VEXT_TRANS(vsw_v, 2, r2nfvm, st_us_op, st_us_check) +GEN_VEXT_TRANS(vse_v, 3, r2nfvm, st_us_op, st_us_check) + +/* + *** stride load and store + */ +typedef void gen_helper_ldst_stride(TCGv_ptr, TCGv_ptr, TCGv, + TCGv, TCGv_env, TCGv_i32); + +static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, uint32_t rs2, + uint32_t data, gen_helper_ldst_stride *fn, + DisasContext *s) +{ + TCGv_ptr dest, mask; + TCGv base, stride; + TCGv_i32 desc; + + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + dest = tcg_temp_new_ptr(); + mask = tcg_temp_new_ptr(); + base = tcg_temp_new(); + stride = tcg_temp_new(); + desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + + gen_get_gpr(base, rs1); + gen_get_gpr(stride, rs2); + tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); + tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); + + fn(dest, mask, base, stride, cpu_env, desc); + + tcg_temp_free_ptr(dest); + tcg_temp_free_ptr(mask); + tcg_temp_free(base); + tcg_temp_free(stride); + tcg_temp_free_i32(desc); + gen_set_label(over); + return true; +} + +static bool ld_stride_op(DisasContext *s, arg_rnfvm *a, uint8_t seq) +{ + uint32_t data = 0; + gen_helper_ldst_stride *fn; + static gen_helper_ldst_stride * const fns[7][4] = { + { gen_helper_vlsb_v_b, gen_helper_vlsb_v_h, + gen_helper_vlsb_v_w, gen_helper_vlsb_v_d }, + { NULL, gen_helper_vlsh_v_h, + gen_helper_vlsh_v_w, gen_helper_vlsh_v_d }, + { NULL, NULL, + gen_helper_vlsw_v_w, gen_helper_vlsw_v_d }, + { gen_helper_vlse_v_b, gen_helper_vlse_v_h, + gen_helper_vlse_v_w, gen_helper_vlse_v_d }, + { gen_helper_vlsbu_v_b, gen_helper_vlsbu_v_h, + gen_helper_vlsbu_v_w, gen_helper_vlsbu_v_d }, + { NULL, gen_helper_vlshu_v_h, + gen_helper_vlshu_v_w, gen_helper_vlshu_v_d }, + { NULL, NULL, + gen_helper_vlswu_v_w, gen_helper_vlswu_v_d }, + }; + + fn = fns[seq][s->sew]; + if (fn == NULL) { + return false; + } + + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, VM, a->vm); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + data = FIELD_DP32(data, VDATA, NF, a->nf); + return ldst_stride_trans(a->rd, a->rs1, a->rs2, data, fn, s); +} + +static bool ld_stride_check(DisasContext *s, arg_rnfvm* a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, false) && + vext_check_reg(s, a->rd, false) && + vext_check_nf(s, a->nf)); +} + +GEN_VEXT_TRANS(vlsb_v, 0, rnfvm, ld_stride_op, ld_stride_check) +GEN_VEXT_TRANS(vlsh_v, 1, rnfvm, ld_stride_op, ld_stride_check) +GEN_VEXT_TRANS(vlsw_v, 2, rnfvm, ld_stride_op, ld_stride_check) +GEN_VEXT_TRANS(vlse_v, 3, rnfvm, ld_stride_op, ld_stride_check) +GEN_VEXT_TRANS(vlsbu_v, 4, rnfvm, ld_stride_op, ld_stride_check) +GEN_VEXT_TRANS(vlshu_v, 5, rnfvm, ld_stride_op, ld_stride_check) +GEN_VEXT_TRANS(vlswu_v, 6, rnfvm, ld_stride_op, ld_stride_check) + +static bool st_stride_op(DisasContext *s, arg_rnfvm *a, uint8_t seq) +{ + uint32_t data = 0; + gen_helper_ldst_stride *fn; + static gen_helper_ldst_stride * const fns[4][4] = { + /* masked stride store */ + { gen_helper_vssb_v_b, gen_helper_vssb_v_h, + gen_helper_vssb_v_w, gen_helper_vssb_v_d }, + { NULL, gen_helper_vssh_v_h, + gen_helper_vssh_v_w, gen_helper_vssh_v_d }, + { NULL, NULL, + gen_helper_vssw_v_w, gen_helper_vssw_v_d }, + { gen_helper_vsse_v_b, gen_helper_vsse_v_h, + gen_helper_vsse_v_w, gen_helper_vsse_v_d } + }; + + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, VM, a->vm); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + data = FIELD_DP32(data, VDATA, NF, a->nf); + fn = fns[seq][s->sew]; + if (fn == NULL) { + return false; + } + + return ldst_stride_trans(a->rd, a->rs1, a->rs2, data, fn, s); +} + +static bool st_stride_check(DisasContext *s, arg_rnfvm* a) +{ + return (vext_check_isa_ill(s) && + vext_check_reg(s, a->rd, false) && + vext_check_nf(s, a->nf)); +} + +GEN_VEXT_TRANS(vssb_v, 0, rnfvm, st_stride_op, st_stride_check) +GEN_VEXT_TRANS(vssh_v, 1, rnfvm, st_stride_op, st_stride_check) +GEN_VEXT_TRANS(vssw_v, 2, rnfvm, st_stride_op, st_stride_check) +GEN_VEXT_TRANS(vsse_v, 3, rnfvm, st_stride_op, st_stride_check) + +/* + *** index load and store + */ +typedef void gen_helper_ldst_index(TCGv_ptr, TCGv_ptr, TCGv, + TCGv_ptr, TCGv_env, TCGv_i32); + +static bool ldst_index_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, + uint32_t data, gen_helper_ldst_index *fn, + DisasContext *s) +{ + TCGv_ptr dest, mask, index; + TCGv base; + TCGv_i32 desc; + + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + dest = tcg_temp_new_ptr(); + mask = tcg_temp_new_ptr(); + index = tcg_temp_new_ptr(); + base = tcg_temp_new(); + desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + + gen_get_gpr(base, rs1); + tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); + tcg_gen_addi_ptr(index, cpu_env, vreg_ofs(s, vs2)); + tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); + + fn(dest, mask, base, index, cpu_env, desc); + + tcg_temp_free_ptr(dest); + tcg_temp_free_ptr(mask); + tcg_temp_free_ptr(index); + tcg_temp_free(base); + tcg_temp_free_i32(desc); + gen_set_label(over); + return true; +} + +static bool ld_index_op(DisasContext *s, arg_rnfvm *a, uint8_t seq) +{ + uint32_t data = 0; + gen_helper_ldst_index *fn; + static gen_helper_ldst_index * const fns[7][4] = { + { gen_helper_vlxb_v_b, gen_helper_vlxb_v_h, + gen_helper_vlxb_v_w, gen_helper_vlxb_v_d }, + { NULL, gen_helper_vlxh_v_h, + gen_helper_vlxh_v_w, gen_helper_vlxh_v_d }, + { NULL, NULL, + gen_helper_vlxw_v_w, gen_helper_vlxw_v_d }, + { gen_helper_vlxe_v_b, gen_helper_vlxe_v_h, + gen_helper_vlxe_v_w, gen_helper_vlxe_v_d }, + { gen_helper_vlxbu_v_b, gen_helper_vlxbu_v_h, + gen_helper_vlxbu_v_w, gen_helper_vlxbu_v_d }, + { NULL, gen_helper_vlxhu_v_h, + gen_helper_vlxhu_v_w, gen_helper_vlxhu_v_d }, + { NULL, NULL, + gen_helper_vlxwu_v_w, gen_helper_vlxwu_v_d }, + }; + + fn = fns[seq][s->sew]; + if (fn == NULL) { + return false; + } + + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, VM, a->vm); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + data = FIELD_DP32(data, VDATA, NF, a->nf); + return ldst_index_trans(a->rd, a->rs1, a->rs2, data, fn, s); +} + +/* + * For vector indexed segment loads, the destination vector register + * groups cannot overlap the source vector register group (specified by + * `vs2`), else an illegal instruction exception is raised. + */ +static bool ld_index_check(DisasContext *s, arg_rnfvm* a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, false) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs2, false) && + vext_check_nf(s, a->nf) && + ((a->nf == 1) || + vext_check_overlap_group(a->rd, a->nf << s->lmul, + a->rs2, 1 << s->lmul))); +} + +GEN_VEXT_TRANS(vlxb_v, 0, rnfvm, ld_index_op, ld_index_check) +GEN_VEXT_TRANS(vlxh_v, 1, rnfvm, ld_index_op, ld_index_check) +GEN_VEXT_TRANS(vlxw_v, 2, rnfvm, ld_index_op, ld_index_check) +GEN_VEXT_TRANS(vlxe_v, 3, rnfvm, ld_index_op, ld_index_check) +GEN_VEXT_TRANS(vlxbu_v, 4, rnfvm, ld_index_op, ld_index_check) +GEN_VEXT_TRANS(vlxhu_v, 5, rnfvm, ld_index_op, ld_index_check) +GEN_VEXT_TRANS(vlxwu_v, 6, rnfvm, ld_index_op, ld_index_check) + +static bool st_index_op(DisasContext *s, arg_rnfvm *a, uint8_t seq) +{ + uint32_t data = 0; + gen_helper_ldst_index *fn; + static gen_helper_ldst_index * const fns[4][4] = { + { gen_helper_vsxb_v_b, gen_helper_vsxb_v_h, + gen_helper_vsxb_v_w, gen_helper_vsxb_v_d }, + { NULL, gen_helper_vsxh_v_h, + gen_helper_vsxh_v_w, gen_helper_vsxh_v_d }, + { NULL, NULL, + gen_helper_vsxw_v_w, gen_helper_vsxw_v_d }, + { gen_helper_vsxe_v_b, gen_helper_vsxe_v_h, + gen_helper_vsxe_v_w, gen_helper_vsxe_v_d } + }; + + fn = fns[seq][s->sew]; + if (fn == NULL) { + return false; + } + + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, VM, a->vm); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + data = FIELD_DP32(data, VDATA, NF, a->nf); + return ldst_index_trans(a->rd, a->rs1, a->rs2, data, fn, s); +} + +static bool st_index_check(DisasContext *s, arg_rnfvm* a) +{ + return (vext_check_isa_ill(s) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs2, false) && + vext_check_nf(s, a->nf)); +} + +GEN_VEXT_TRANS(vsxb_v, 0, rnfvm, st_index_op, st_index_check) +GEN_VEXT_TRANS(vsxh_v, 1, rnfvm, st_index_op, st_index_check) +GEN_VEXT_TRANS(vsxw_v, 2, rnfvm, st_index_op, st_index_check) +GEN_VEXT_TRANS(vsxe_v, 3, rnfvm, st_index_op, st_index_check) + +/* + *** unit stride fault-only-first load + */ +static bool ldff_trans(uint32_t vd, uint32_t rs1, uint32_t data, + gen_helper_ldst_us *fn, DisasContext *s) +{ + TCGv_ptr dest, mask; + TCGv base; + TCGv_i32 desc; + + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + dest = tcg_temp_new_ptr(); + mask = tcg_temp_new_ptr(); + base = tcg_temp_new(); + desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + + gen_get_gpr(base, rs1); + tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); + tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); + + fn(dest, mask, base, cpu_env, desc); + + tcg_temp_free_ptr(dest); + tcg_temp_free_ptr(mask); + tcg_temp_free(base); + tcg_temp_free_i32(desc); + gen_set_label(over); + return true; +} + +static bool ldff_op(DisasContext *s, arg_r2nfvm *a, uint8_t seq) +{ + uint32_t data = 0; + gen_helper_ldst_us *fn; + static gen_helper_ldst_us * const fns[7][4] = { + { gen_helper_vlbff_v_b, gen_helper_vlbff_v_h, + gen_helper_vlbff_v_w, gen_helper_vlbff_v_d }, + { NULL, gen_helper_vlhff_v_h, + gen_helper_vlhff_v_w, gen_helper_vlhff_v_d }, + { NULL, NULL, + gen_helper_vlwff_v_w, gen_helper_vlwff_v_d }, + { gen_helper_vleff_v_b, gen_helper_vleff_v_h, + gen_helper_vleff_v_w, gen_helper_vleff_v_d }, + { gen_helper_vlbuff_v_b, gen_helper_vlbuff_v_h, + gen_helper_vlbuff_v_w, gen_helper_vlbuff_v_d }, + { NULL, gen_helper_vlhuff_v_h, + gen_helper_vlhuff_v_w, gen_helper_vlhuff_v_d }, + { NULL, NULL, + gen_helper_vlwuff_v_w, gen_helper_vlwuff_v_d } + }; + + fn = fns[seq][s->sew]; + if (fn == NULL) { + return false; + } + + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, VM, a->vm); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + data = FIELD_DP32(data, VDATA, NF, a->nf); + return ldff_trans(a->rd, a->rs1, data, fn, s); +} + +GEN_VEXT_TRANS(vlbff_v, 0, r2nfvm, ldff_op, ld_us_check) +GEN_VEXT_TRANS(vlhff_v, 1, r2nfvm, ldff_op, ld_us_check) +GEN_VEXT_TRANS(vlwff_v, 2, r2nfvm, ldff_op, ld_us_check) +GEN_VEXT_TRANS(vleff_v, 3, r2nfvm, ldff_op, ld_us_check) +GEN_VEXT_TRANS(vlbuff_v, 4, r2nfvm, ldff_op, ld_us_check) +GEN_VEXT_TRANS(vlhuff_v, 5, r2nfvm, ldff_op, ld_us_check) +GEN_VEXT_TRANS(vlwuff_v, 6, r2nfvm, ldff_op, ld_us_check) + +/* + *** vector atomic operation + */ +typedef void gen_helper_amo(TCGv_ptr, TCGv_ptr, TCGv, TCGv_ptr, + TCGv_env, TCGv_i32); + +static bool amo_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, + uint32_t data, gen_helper_amo *fn, DisasContext *s) +{ + TCGv_ptr dest, mask, index; + TCGv base; + TCGv_i32 desc; + + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + dest = tcg_temp_new_ptr(); + mask = tcg_temp_new_ptr(); + index = tcg_temp_new_ptr(); + base = tcg_temp_new(); + desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + + gen_get_gpr(base, rs1); + tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); + tcg_gen_addi_ptr(index, cpu_env, vreg_ofs(s, vs2)); + tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); + + fn(dest, mask, base, index, cpu_env, desc); + + tcg_temp_free_ptr(dest); + tcg_temp_free_ptr(mask); + tcg_temp_free_ptr(index); + tcg_temp_free(base); + tcg_temp_free_i32(desc); + gen_set_label(over); + return true; +} + +static bool amo_op(DisasContext *s, arg_rwdvm *a, uint8_t seq) +{ + uint32_t data = 0; + gen_helper_amo *fn; + static gen_helper_amo *const fnsw[9] = { + /* no atomic operation */ + gen_helper_vamoswapw_v_w, + gen_helper_vamoaddw_v_w, + gen_helper_vamoxorw_v_w, + gen_helper_vamoandw_v_w, + gen_helper_vamoorw_v_w, + gen_helper_vamominw_v_w, + gen_helper_vamomaxw_v_w, + gen_helper_vamominuw_v_w, + gen_helper_vamomaxuw_v_w + }; +#ifdef TARGET_RISCV64 + static gen_helper_amo *const fnsd[18] = { + gen_helper_vamoswapw_v_d, + gen_helper_vamoaddw_v_d, + gen_helper_vamoxorw_v_d, + gen_helper_vamoandw_v_d, + gen_helper_vamoorw_v_d, + gen_helper_vamominw_v_d, + gen_helper_vamomaxw_v_d, + gen_helper_vamominuw_v_d, + gen_helper_vamomaxuw_v_d, + gen_helper_vamoswapd_v_d, + gen_helper_vamoaddd_v_d, + gen_helper_vamoxord_v_d, + gen_helper_vamoandd_v_d, + gen_helper_vamoord_v_d, + gen_helper_vamomind_v_d, + gen_helper_vamomaxd_v_d, + gen_helper_vamominud_v_d, + gen_helper_vamomaxud_v_d + }; +#endif + + if (tb_cflags(s->base.tb) & CF_PARALLEL) { + gen_helper_exit_atomic(cpu_env); + s->base.is_jmp = DISAS_NORETURN; + return true; + } else { + if (s->sew == 3) { +#ifdef TARGET_RISCV64 + fn = fnsd[seq]; +#else + /* Check done in amo_check(). */ + g_assert_not_reached(); +#endif + } else { + assert(seq < ARRAY_SIZE(fnsw)); + fn = fnsw[seq]; + } + } + + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, VM, a->vm); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + data = FIELD_DP32(data, VDATA, WD, a->wd); + return amo_trans(a->rd, a->rs1, a->rs2, data, fn, s); +} +/* + * There are two rules check here. + * + * 1. SEW must be at least as wide as the AMO memory element size. + * + * 2. If SEW is greater than XLEN, an illegal instruction exception is raised. + */ +static bool amo_check(DisasContext *s, arg_rwdvm* a) +{ + return (!s->vill && has_ext(s, RVA) && + (!a->wd || vext_check_overlap_mask(s, a->rd, a->vm, false)) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs2, false) && + ((1 << s->sew) <= sizeof(target_ulong)) && + ((1 << s->sew) >= 4)); +} + +GEN_VEXT_TRANS(vamoswapw_v, 0, rwdvm, amo_op, amo_check) +GEN_VEXT_TRANS(vamoaddw_v, 1, rwdvm, amo_op, amo_check) +GEN_VEXT_TRANS(vamoxorw_v, 2, rwdvm, amo_op, amo_check) +GEN_VEXT_TRANS(vamoandw_v, 3, rwdvm, amo_op, amo_check) +GEN_VEXT_TRANS(vamoorw_v, 4, rwdvm, amo_op, amo_check) +GEN_VEXT_TRANS(vamominw_v, 5, rwdvm, amo_op, amo_check) +GEN_VEXT_TRANS(vamomaxw_v, 6, rwdvm, amo_op, amo_check) +GEN_VEXT_TRANS(vamominuw_v, 7, rwdvm, amo_op, amo_check) +GEN_VEXT_TRANS(vamomaxuw_v, 8, rwdvm, amo_op, amo_check) +#ifdef TARGET_RISCV64 +GEN_VEXT_TRANS(vamoswapd_v, 9, rwdvm, amo_op, amo_check) +GEN_VEXT_TRANS(vamoaddd_v, 10, rwdvm, amo_op, amo_check) +GEN_VEXT_TRANS(vamoxord_v, 11, rwdvm, amo_op, amo_check) +GEN_VEXT_TRANS(vamoandd_v, 12, rwdvm, amo_op, amo_check) +GEN_VEXT_TRANS(vamoord_v, 13, rwdvm, amo_op, amo_check) +GEN_VEXT_TRANS(vamomind_v, 14, rwdvm, amo_op, amo_check) +GEN_VEXT_TRANS(vamomaxd_v, 15, rwdvm, amo_op, amo_check) +GEN_VEXT_TRANS(vamominud_v, 16, rwdvm, amo_op, amo_check) +GEN_VEXT_TRANS(vamomaxud_v, 17, rwdvm, amo_op, amo_check) +#endif + +/* + *** Vector Integer Arithmetic Instructions + */ +#define MAXSZ(s) (s->vlen >> (3 - s->lmul)) + +static bool opivv_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, false) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs2, false) && + vext_check_reg(s, a->rs1, false)); +} + +typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t, + uint32_t, uint32_t, uint32_t); + +static inline bool +do_opivv_gvec(DisasContext *s, arg_rmrr *a, GVecGen3Fn *gvec_fn, + gen_helper_gvec_4_ptr *fn) +{ + TCGLabel *over = gen_new_label(); + if (!opivv_check(s, a)) { + return false; + } + + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + if (a->vm && s->vl_eq_vlmax) { + gvec_fn(s->sew, vreg_ofs(s, a->rd), + vreg_ofs(s, a->rs2), vreg_ofs(s, a->rs1), + MAXSZ(s), MAXSZ(s)); + } else { + uint32_t data = 0; + + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, VM, a->vm); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), + vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2), + cpu_env, 0, s->vlen / 8, data, fn); + } + gen_set_label(over); + return true; +} + +/* OPIVV with GVEC IR */ +#define GEN_OPIVV_GVEC_TRANS(NAME, SUF) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + static gen_helper_gvec_4_ptr * const fns[4] = { \ + gen_helper_##NAME##_b, gen_helper_##NAME##_h, \ + gen_helper_##NAME##_w, gen_helper_##NAME##_d, \ + }; \ + return do_opivv_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]); \ +} + +GEN_OPIVV_GVEC_TRANS(vadd_vv, add) +GEN_OPIVV_GVEC_TRANS(vsub_vv, sub) + +typedef void gen_helper_opivx(TCGv_ptr, TCGv_ptr, TCGv, TCGv_ptr, + TCGv_env, TCGv_i32); + +static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm, + gen_helper_opivx *fn, DisasContext *s) +{ + TCGv_ptr dest, src2, mask; + TCGv src1; + TCGv_i32 desc; + uint32_t data = 0; + + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + dest = tcg_temp_new_ptr(); + mask = tcg_temp_new_ptr(); + src2 = tcg_temp_new_ptr(); + src1 = tcg_temp_new(); + gen_get_gpr(src1, rs1); + + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, VM, vm); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + + tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); + tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2)); + tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); + + fn(dest, mask, src1, src2, cpu_env, desc); + + tcg_temp_free_ptr(dest); + tcg_temp_free_ptr(mask); + tcg_temp_free_ptr(src2); + tcg_temp_free(src1); + tcg_temp_free_i32(desc); + gen_set_label(over); + return true; +} + +static bool opivx_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, false) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs2, false)); +} + +typedef void GVecGen2sFn(unsigned, uint32_t, uint32_t, TCGv_i64, + uint32_t, uint32_t); + +static inline bool +do_opivx_gvec(DisasContext *s, arg_rmrr *a, GVecGen2sFn *gvec_fn, + gen_helper_opivx *fn) +{ + if (!opivx_check(s, a)) { + return false; + } + + if (a->vm && s->vl_eq_vlmax) { + TCGv_i64 src1 = tcg_temp_new_i64(); + TCGv tmp = tcg_temp_new(); + + gen_get_gpr(tmp, a->rs1); + tcg_gen_ext_tl_i64(src1, tmp); + gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2), + src1, MAXSZ(s), MAXSZ(s)); + + tcg_temp_free_i64(src1); + tcg_temp_free(tmp); + return true; + } + return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s); +} + +/* OPIVX with GVEC IR */ +#define GEN_OPIVX_GVEC_TRANS(NAME, SUF) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + static gen_helper_opivx * const fns[4] = { \ + gen_helper_##NAME##_b, gen_helper_##NAME##_h, \ + gen_helper_##NAME##_w, gen_helper_##NAME##_d, \ + }; \ + return do_opivx_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]); \ +} + +GEN_OPIVX_GVEC_TRANS(vadd_vx, adds) +GEN_OPIVX_GVEC_TRANS(vsub_vx, subs) + +static void gen_vec_rsub8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) +{ + tcg_gen_vec_sub8_i64(d, b, a); +} + +static void gen_vec_rsub16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) +{ + tcg_gen_vec_sub16_i64(d, b, a); +} + +static void gen_rsub_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) +{ + tcg_gen_sub_i32(ret, arg2, arg1); +} + +static void gen_rsub_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) +{ + tcg_gen_sub_i64(ret, arg2, arg1); +} + +static void gen_rsub_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) +{ + tcg_gen_sub_vec(vece, r, b, a); +} + +static void tcg_gen_gvec_rsubs(unsigned vece, uint32_t dofs, uint32_t aofs, + TCGv_i64 c, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_sub_vec, 0 }; + static const GVecGen2s rsub_op[4] = { + { .fni8 = gen_vec_rsub8_i64, + .fniv = gen_rsub_vec, + .fno = gen_helper_vec_rsubs8, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fni8 = gen_vec_rsub16_i64, + .fniv = gen_rsub_vec, + .fno = gen_helper_vec_rsubs16, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = gen_rsub_i32, + .fniv = gen_rsub_vec, + .fno = gen_helper_vec_rsubs32, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = gen_rsub_i64, + .fniv = gen_rsub_vec, + .fno = gen_helper_vec_rsubs64, + .opt_opc = vecop_list, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, c, &rsub_op[vece]); +} + +GEN_OPIVX_GVEC_TRANS(vrsub_vx, rsubs) + +static bool opivi_trans(uint32_t vd, uint32_t imm, uint32_t vs2, uint32_t vm, + gen_helper_opivx *fn, DisasContext *s, int zx) +{ + TCGv_ptr dest, src2, mask; + TCGv src1; + TCGv_i32 desc; + uint32_t data = 0; + + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + dest = tcg_temp_new_ptr(); + mask = tcg_temp_new_ptr(); + src2 = tcg_temp_new_ptr(); + if (zx) { + src1 = tcg_const_tl(imm); + } else { + src1 = tcg_const_tl(sextract64(imm, 0, 5)); + } + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, VM, vm); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + + tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); + tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2)); + tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); + + fn(dest, mask, src1, src2, cpu_env, desc); + + tcg_temp_free_ptr(dest); + tcg_temp_free_ptr(mask); + tcg_temp_free_ptr(src2); + tcg_temp_free(src1); + tcg_temp_free_i32(desc); + gen_set_label(over); + return true; +} + +typedef void GVecGen2iFn(unsigned, uint32_t, uint32_t, int64_t, + uint32_t, uint32_t); + +static inline bool +do_opivi_gvec(DisasContext *s, arg_rmrr *a, GVecGen2iFn *gvec_fn, + gen_helper_opivx *fn, int zx) +{ + if (!opivx_check(s, a)) { + return false; + } + + if (a->vm && s->vl_eq_vlmax) { + if (zx) { + gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2), + extract64(a->rs1, 0, 5), MAXSZ(s), MAXSZ(s)); + } else { + gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2), + sextract64(a->rs1, 0, 5), MAXSZ(s), MAXSZ(s)); + } + } else { + return opivi_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s, zx); + } + return true; +} + +/* OPIVI with GVEC IR */ +#define GEN_OPIVI_GVEC_TRANS(NAME, ZX, OPIVX, SUF) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + static gen_helper_opivx * const fns[4] = { \ + gen_helper_##OPIVX##_b, gen_helper_##OPIVX##_h, \ + gen_helper_##OPIVX##_w, gen_helper_##OPIVX##_d, \ + }; \ + return do_opivi_gvec(s, a, tcg_gen_gvec_##SUF, \ + fns[s->sew], ZX); \ +} + +GEN_OPIVI_GVEC_TRANS(vadd_vi, 0, vadd_vx, addi) + +static void tcg_gen_gvec_rsubi(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t c, uint32_t oprsz, uint32_t maxsz) +{ + TCGv_i64 tmp = tcg_const_i64(c); + tcg_gen_gvec_rsubs(vece, dofs, aofs, tmp, oprsz, maxsz); + tcg_temp_free_i64(tmp); +} + +GEN_OPIVI_GVEC_TRANS(vrsub_vi, 0, vrsub_vx, rsubi) + +/* Vector Widening Integer Add/Subtract */ + +/* OPIVV with WIDEN */ +static bool opivv_widen_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, true) && + vext_check_reg(s, a->rd, true) && + vext_check_reg(s, a->rs2, false) && + vext_check_reg(s, a->rs1, false) && + vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs2, + 1 << s->lmul) && + vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs1, + 1 << s->lmul) && + (s->lmul < 0x3) && (s->sew < 0x3)); +} + +static bool do_opivv_widen(DisasContext *s, arg_rmrr *a, + gen_helper_gvec_4_ptr *fn, + bool (*checkfn)(DisasContext *, arg_rmrr *)) +{ + if (checkfn(s, a)) { + uint32_t data = 0; + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, VM, a->vm); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), + vreg_ofs(s, a->rs1), + vreg_ofs(s, a->rs2), + cpu_env, 0, s->vlen / 8, + data, fn); + gen_set_label(over); + return true; + } + return false; +} + +#define GEN_OPIVV_WIDEN_TRANS(NAME, CHECK) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + static gen_helper_gvec_4_ptr * const fns[3] = { \ + gen_helper_##NAME##_b, \ + gen_helper_##NAME##_h, \ + gen_helper_##NAME##_w \ + }; \ + return do_opivv_widen(s, a, fns[s->sew], CHECK); \ +} + +GEN_OPIVV_WIDEN_TRANS(vwaddu_vv, opivv_widen_check) +GEN_OPIVV_WIDEN_TRANS(vwadd_vv, opivv_widen_check) +GEN_OPIVV_WIDEN_TRANS(vwsubu_vv, opivv_widen_check) +GEN_OPIVV_WIDEN_TRANS(vwsub_vv, opivv_widen_check) + +/* OPIVX with WIDEN */ +static bool opivx_widen_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, true) && + vext_check_reg(s, a->rd, true) && + vext_check_reg(s, a->rs2, false) && + vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs2, + 1 << s->lmul) && + (s->lmul < 0x3) && (s->sew < 0x3)); +} + +static bool do_opivx_widen(DisasContext *s, arg_rmrr *a, + gen_helper_opivx *fn) +{ + if (opivx_widen_check(s, a)) { + return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s); + } + return false; +} + +#define GEN_OPIVX_WIDEN_TRANS(NAME) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + static gen_helper_opivx * const fns[3] = { \ + gen_helper_##NAME##_b, \ + gen_helper_##NAME##_h, \ + gen_helper_##NAME##_w \ + }; \ + return do_opivx_widen(s, a, fns[s->sew]); \ +} + +GEN_OPIVX_WIDEN_TRANS(vwaddu_vx) +GEN_OPIVX_WIDEN_TRANS(vwadd_vx) +GEN_OPIVX_WIDEN_TRANS(vwsubu_vx) +GEN_OPIVX_WIDEN_TRANS(vwsub_vx) + +/* WIDEN OPIVV with WIDEN */ +static bool opiwv_widen_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, true) && + vext_check_reg(s, a->rd, true) && + vext_check_reg(s, a->rs2, true) && + vext_check_reg(s, a->rs1, false) && + vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs1, + 1 << s->lmul) && + (s->lmul < 0x3) && (s->sew < 0x3)); +} + +static bool do_opiwv_widen(DisasContext *s, arg_rmrr *a, + gen_helper_gvec_4_ptr *fn) +{ + if (opiwv_widen_check(s, a)) { + uint32_t data = 0; + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, VM, a->vm); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), + vreg_ofs(s, a->rs1), + vreg_ofs(s, a->rs2), + cpu_env, 0, s->vlen / 8, data, fn); + gen_set_label(over); + return true; + } + return false; +} + +#define GEN_OPIWV_WIDEN_TRANS(NAME) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + static gen_helper_gvec_4_ptr * const fns[3] = { \ + gen_helper_##NAME##_b, \ + gen_helper_##NAME##_h, \ + gen_helper_##NAME##_w \ + }; \ + return do_opiwv_widen(s, a, fns[s->sew]); \ +} + +GEN_OPIWV_WIDEN_TRANS(vwaddu_wv) +GEN_OPIWV_WIDEN_TRANS(vwadd_wv) +GEN_OPIWV_WIDEN_TRANS(vwsubu_wv) +GEN_OPIWV_WIDEN_TRANS(vwsub_wv) + +/* WIDEN OPIVX with WIDEN */ +static bool opiwx_widen_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, true) && + vext_check_reg(s, a->rd, true) && + vext_check_reg(s, a->rs2, true) && + (s->lmul < 0x3) && (s->sew < 0x3)); +} + +static bool do_opiwx_widen(DisasContext *s, arg_rmrr *a, + gen_helper_opivx *fn) +{ + if (opiwx_widen_check(s, a)) { + return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s); + } + return false; +} + +#define GEN_OPIWX_WIDEN_TRANS(NAME) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + static gen_helper_opivx * const fns[3] = { \ + gen_helper_##NAME##_b, \ + gen_helper_##NAME##_h, \ + gen_helper_##NAME##_w \ + }; \ + return do_opiwx_widen(s, a, fns[s->sew]); \ +} + +GEN_OPIWX_WIDEN_TRANS(vwaddu_wx) +GEN_OPIWX_WIDEN_TRANS(vwadd_wx) +GEN_OPIWX_WIDEN_TRANS(vwsubu_wx) +GEN_OPIWX_WIDEN_TRANS(vwsub_wx) + +/* Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions */ +/* OPIVV without GVEC IR */ +#define GEN_OPIVV_TRANS(NAME, CHECK) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + if (CHECK(s, a)) { \ + uint32_t data = 0; \ + static gen_helper_gvec_4_ptr * const fns[4] = { \ + gen_helper_##NAME##_b, gen_helper_##NAME##_h, \ + gen_helper_##NAME##_w, gen_helper_##NAME##_d, \ + }; \ + TCGLabel *over = gen_new_label(); \ + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \ + \ + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); \ + data = FIELD_DP32(data, VDATA, VM, a->vm); \ + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ + tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ + vreg_ofs(s, a->rs1), \ + vreg_ofs(s, a->rs2), cpu_env, 0, \ + s->vlen / 8, data, fns[s->sew]); \ + gen_set_label(over); \ + return true; \ + } \ + return false; \ +} + +/* + * For vadc and vsbc, an illegal instruction exception is raised if the + * destination vector register is v0 and LMUL > 1. (Section 12.3) + */ +static bool opivv_vadc_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs2, false) && + vext_check_reg(s, a->rs1, false) && + ((a->rd != 0) || (s->lmul == 0))); +} + +GEN_OPIVV_TRANS(vadc_vvm, opivv_vadc_check) +GEN_OPIVV_TRANS(vsbc_vvm, opivv_vadc_check) + +/* + * For vmadc and vmsbc, an illegal instruction exception is raised if the + * destination vector register overlaps a source vector register group. + */ +static bool opivv_vmadc_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_reg(s, a->rs2, false) && + vext_check_reg(s, a->rs1, false) && + vext_check_overlap_group(a->rd, 1, a->rs1, 1 << s->lmul) && + vext_check_overlap_group(a->rd, 1, a->rs2, 1 << s->lmul)); +} + +GEN_OPIVV_TRANS(vmadc_vvm, opivv_vmadc_check) +GEN_OPIVV_TRANS(vmsbc_vvm, opivv_vmadc_check) + +static bool opivx_vadc_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs2, false) && + ((a->rd != 0) || (s->lmul == 0))); +} + +/* OPIVX without GVEC IR */ +#define GEN_OPIVX_TRANS(NAME, CHECK) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + if (CHECK(s, a)) { \ + static gen_helper_opivx * const fns[4] = { \ + gen_helper_##NAME##_b, gen_helper_##NAME##_h, \ + gen_helper_##NAME##_w, gen_helper_##NAME##_d, \ + }; \ + \ + return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s);\ + } \ + return false; \ +} + +GEN_OPIVX_TRANS(vadc_vxm, opivx_vadc_check) +GEN_OPIVX_TRANS(vsbc_vxm, opivx_vadc_check) + +static bool opivx_vmadc_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_reg(s, a->rs2, false) && + vext_check_overlap_group(a->rd, 1, a->rs2, 1 << s->lmul)); +} + +GEN_OPIVX_TRANS(vmadc_vxm, opivx_vmadc_check) +GEN_OPIVX_TRANS(vmsbc_vxm, opivx_vmadc_check) + +/* OPIVI without GVEC IR */ +#define GEN_OPIVI_TRANS(NAME, ZX, OPIVX, CHECK) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + if (CHECK(s, a)) { \ + static gen_helper_opivx * const fns[4] = { \ + gen_helper_##OPIVX##_b, gen_helper_##OPIVX##_h, \ + gen_helper_##OPIVX##_w, gen_helper_##OPIVX##_d, \ + }; \ + return opivi_trans(a->rd, a->rs1, a->rs2, a->vm, \ + fns[s->sew], s, ZX); \ + } \ + return false; \ +} + +GEN_OPIVI_TRANS(vadc_vim, 0, vadc_vxm, opivx_vadc_check) +GEN_OPIVI_TRANS(vmadc_vim, 0, vmadc_vxm, opivx_vmadc_check) + +/* Vector Bitwise Logical Instructions */ +GEN_OPIVV_GVEC_TRANS(vand_vv, and) +GEN_OPIVV_GVEC_TRANS(vor_vv, or) +GEN_OPIVV_GVEC_TRANS(vxor_vv, xor) +GEN_OPIVX_GVEC_TRANS(vand_vx, ands) +GEN_OPIVX_GVEC_TRANS(vor_vx, ors) +GEN_OPIVX_GVEC_TRANS(vxor_vx, xors) +GEN_OPIVI_GVEC_TRANS(vand_vi, 0, vand_vx, andi) +GEN_OPIVI_GVEC_TRANS(vor_vi, 0, vor_vx, ori) +GEN_OPIVI_GVEC_TRANS(vxor_vi, 0, vxor_vx, xori) + +/* Vector Single-Width Bit Shift Instructions */ +GEN_OPIVV_GVEC_TRANS(vsll_vv, shlv) +GEN_OPIVV_GVEC_TRANS(vsrl_vv, shrv) +GEN_OPIVV_GVEC_TRANS(vsra_vv, sarv) + +typedef void GVecGen2sFn32(unsigned, uint32_t, uint32_t, TCGv_i32, + uint32_t, uint32_t); + +static inline bool +do_opivx_gvec_shift(DisasContext *s, arg_rmrr *a, GVecGen2sFn32 *gvec_fn, + gen_helper_opivx *fn) +{ + if (!opivx_check(s, a)) { + return false; + } + + if (a->vm && s->vl_eq_vlmax) { + TCGv_i32 src1 = tcg_temp_new_i32(); + TCGv tmp = tcg_temp_new(); + + gen_get_gpr(tmp, a->rs1); + tcg_gen_trunc_tl_i32(src1, tmp); + tcg_gen_extract_i32(src1, src1, 0, s->sew + 3); + gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2), + src1, MAXSZ(s), MAXSZ(s)); + + tcg_temp_free_i32(src1); + tcg_temp_free(tmp); + return true; + } + return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s); +} + +#define GEN_OPIVX_GVEC_SHIFT_TRANS(NAME, SUF) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + static gen_helper_opivx * const fns[4] = { \ + gen_helper_##NAME##_b, gen_helper_##NAME##_h, \ + gen_helper_##NAME##_w, gen_helper_##NAME##_d, \ + }; \ + \ + return do_opivx_gvec_shift(s, a, tcg_gen_gvec_##SUF, fns[s->sew]); \ +} + +GEN_OPIVX_GVEC_SHIFT_TRANS(vsll_vx, shls) +GEN_OPIVX_GVEC_SHIFT_TRANS(vsrl_vx, shrs) +GEN_OPIVX_GVEC_SHIFT_TRANS(vsra_vx, sars) + +GEN_OPIVI_GVEC_TRANS(vsll_vi, 1, vsll_vx, shli) +GEN_OPIVI_GVEC_TRANS(vsrl_vi, 1, vsrl_vx, shri) +GEN_OPIVI_GVEC_TRANS(vsra_vi, 1, vsra_vx, sari) + +/* Vector Narrowing Integer Right Shift Instructions */ +static bool opivv_narrow_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, false) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs2, true) && + vext_check_reg(s, a->rs1, false) && + vext_check_overlap_group(a->rd, 1 << s->lmul, a->rs2, + 2 << s->lmul) && + (s->lmul < 0x3) && (s->sew < 0x3)); +} + +/* OPIVV with NARROW */ +#define GEN_OPIVV_NARROW_TRANS(NAME) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + if (opivv_narrow_check(s, a)) { \ + uint32_t data = 0; \ + static gen_helper_gvec_4_ptr * const fns[3] = { \ + gen_helper_##NAME##_b, \ + gen_helper_##NAME##_h, \ + gen_helper_##NAME##_w, \ + }; \ + TCGLabel *over = gen_new_label(); \ + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \ + \ + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); \ + data = FIELD_DP32(data, VDATA, VM, a->vm); \ + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ + tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ + vreg_ofs(s, a->rs1), \ + vreg_ofs(s, a->rs2), cpu_env, 0, \ + s->vlen / 8, data, fns[s->sew]); \ + gen_set_label(over); \ + return true; \ + } \ + return false; \ +} +GEN_OPIVV_NARROW_TRANS(vnsra_vv) +GEN_OPIVV_NARROW_TRANS(vnsrl_vv) + +static bool opivx_narrow_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, false) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs2, true) && + vext_check_overlap_group(a->rd, 1 << s->lmul, a->rs2, + 2 << s->lmul) && + (s->lmul < 0x3) && (s->sew < 0x3)); +} + +/* OPIVX with NARROW */ +#define GEN_OPIVX_NARROW_TRANS(NAME) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + if (opivx_narrow_check(s, a)) { \ + static gen_helper_opivx * const fns[3] = { \ + gen_helper_##NAME##_b, \ + gen_helper_##NAME##_h, \ + gen_helper_##NAME##_w, \ + }; \ + return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s);\ + } \ + return false; \ +} + +GEN_OPIVX_NARROW_TRANS(vnsra_vx) +GEN_OPIVX_NARROW_TRANS(vnsrl_vx) + +/* OPIVI with NARROW */ +#define GEN_OPIVI_NARROW_TRANS(NAME, ZX, OPIVX) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + if (opivx_narrow_check(s, a)) { \ + static gen_helper_opivx * const fns[3] = { \ + gen_helper_##OPIVX##_b, \ + gen_helper_##OPIVX##_h, \ + gen_helper_##OPIVX##_w, \ + }; \ + return opivi_trans(a->rd, a->rs1, a->rs2, a->vm, \ + fns[s->sew], s, ZX); \ + } \ + return false; \ +} + +GEN_OPIVI_NARROW_TRANS(vnsra_vi, 1, vnsra_vx) +GEN_OPIVI_NARROW_TRANS(vnsrl_vi, 1, vnsrl_vx) + +/* Vector Integer Comparison Instructions */ +/* + * For all comparison instructions, an illegal instruction exception is raised + * if the destination vector register overlaps a source vector register group + * and LMUL > 1. + */ +static bool opivv_cmp_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_reg(s, a->rs2, false) && + vext_check_reg(s, a->rs1, false) && + ((vext_check_overlap_group(a->rd, 1, a->rs1, 1 << s->lmul) && + vext_check_overlap_group(a->rd, 1, a->rs2, 1 << s->lmul)) || + (s->lmul == 0))); +} +GEN_OPIVV_TRANS(vmseq_vv, opivv_cmp_check) +GEN_OPIVV_TRANS(vmsne_vv, opivv_cmp_check) +GEN_OPIVV_TRANS(vmsltu_vv, opivv_cmp_check) +GEN_OPIVV_TRANS(vmslt_vv, opivv_cmp_check) +GEN_OPIVV_TRANS(vmsleu_vv, opivv_cmp_check) +GEN_OPIVV_TRANS(vmsle_vv, opivv_cmp_check) + +static bool opivx_cmp_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_reg(s, a->rs2, false) && + (vext_check_overlap_group(a->rd, 1, a->rs2, 1 << s->lmul) || + (s->lmul == 0))); +} + +GEN_OPIVX_TRANS(vmseq_vx, opivx_cmp_check) +GEN_OPIVX_TRANS(vmsne_vx, opivx_cmp_check) +GEN_OPIVX_TRANS(vmsltu_vx, opivx_cmp_check) +GEN_OPIVX_TRANS(vmslt_vx, opivx_cmp_check) +GEN_OPIVX_TRANS(vmsleu_vx, opivx_cmp_check) +GEN_OPIVX_TRANS(vmsle_vx, opivx_cmp_check) +GEN_OPIVX_TRANS(vmsgtu_vx, opivx_cmp_check) +GEN_OPIVX_TRANS(vmsgt_vx, opivx_cmp_check) + +GEN_OPIVI_TRANS(vmseq_vi, 0, vmseq_vx, opivx_cmp_check) +GEN_OPIVI_TRANS(vmsne_vi, 0, vmsne_vx, opivx_cmp_check) +GEN_OPIVI_TRANS(vmsleu_vi, 1, vmsleu_vx, opivx_cmp_check) +GEN_OPIVI_TRANS(vmsle_vi, 0, vmsle_vx, opivx_cmp_check) +GEN_OPIVI_TRANS(vmsgtu_vi, 1, vmsgtu_vx, opivx_cmp_check) +GEN_OPIVI_TRANS(vmsgt_vi, 0, vmsgt_vx, opivx_cmp_check) + +/* Vector Integer Min/Max Instructions */ +GEN_OPIVV_GVEC_TRANS(vminu_vv, umin) +GEN_OPIVV_GVEC_TRANS(vmin_vv, smin) +GEN_OPIVV_GVEC_TRANS(vmaxu_vv, umax) +GEN_OPIVV_GVEC_TRANS(vmax_vv, smax) +GEN_OPIVX_TRANS(vminu_vx, opivx_check) +GEN_OPIVX_TRANS(vmin_vx, opivx_check) +GEN_OPIVX_TRANS(vmaxu_vx, opivx_check) +GEN_OPIVX_TRANS(vmax_vx, opivx_check) + +/* Vector Single-Width Integer Multiply Instructions */ +GEN_OPIVV_GVEC_TRANS(vmul_vv, mul) +GEN_OPIVV_TRANS(vmulh_vv, opivv_check) +GEN_OPIVV_TRANS(vmulhu_vv, opivv_check) +GEN_OPIVV_TRANS(vmulhsu_vv, opivv_check) +GEN_OPIVX_GVEC_TRANS(vmul_vx, muls) +GEN_OPIVX_TRANS(vmulh_vx, opivx_check) +GEN_OPIVX_TRANS(vmulhu_vx, opivx_check) +GEN_OPIVX_TRANS(vmulhsu_vx, opivx_check) + +/* Vector Integer Divide Instructions */ +GEN_OPIVV_TRANS(vdivu_vv, opivv_check) +GEN_OPIVV_TRANS(vdiv_vv, opivv_check) +GEN_OPIVV_TRANS(vremu_vv, opivv_check) +GEN_OPIVV_TRANS(vrem_vv, opivv_check) +GEN_OPIVX_TRANS(vdivu_vx, opivx_check) +GEN_OPIVX_TRANS(vdiv_vx, opivx_check) +GEN_OPIVX_TRANS(vremu_vx, opivx_check) +GEN_OPIVX_TRANS(vrem_vx, opivx_check) + +/* Vector Widening Integer Multiply Instructions */ +GEN_OPIVV_WIDEN_TRANS(vwmul_vv, opivv_widen_check) +GEN_OPIVV_WIDEN_TRANS(vwmulu_vv, opivv_widen_check) +GEN_OPIVV_WIDEN_TRANS(vwmulsu_vv, opivv_widen_check) +GEN_OPIVX_WIDEN_TRANS(vwmul_vx) +GEN_OPIVX_WIDEN_TRANS(vwmulu_vx) +GEN_OPIVX_WIDEN_TRANS(vwmulsu_vx) + +/* Vector Single-Width Integer Multiply-Add Instructions */ +GEN_OPIVV_TRANS(vmacc_vv, opivv_check) +GEN_OPIVV_TRANS(vnmsac_vv, opivv_check) +GEN_OPIVV_TRANS(vmadd_vv, opivv_check) +GEN_OPIVV_TRANS(vnmsub_vv, opivv_check) +GEN_OPIVX_TRANS(vmacc_vx, opivx_check) +GEN_OPIVX_TRANS(vnmsac_vx, opivx_check) +GEN_OPIVX_TRANS(vmadd_vx, opivx_check) +GEN_OPIVX_TRANS(vnmsub_vx, opivx_check) + +/* Vector Widening Integer Multiply-Add Instructions */ +GEN_OPIVV_WIDEN_TRANS(vwmaccu_vv, opivv_widen_check) +GEN_OPIVV_WIDEN_TRANS(vwmacc_vv, opivv_widen_check) +GEN_OPIVV_WIDEN_TRANS(vwmaccsu_vv, opivv_widen_check) +GEN_OPIVX_WIDEN_TRANS(vwmaccu_vx) +GEN_OPIVX_WIDEN_TRANS(vwmacc_vx) +GEN_OPIVX_WIDEN_TRANS(vwmaccsu_vx) +GEN_OPIVX_WIDEN_TRANS(vwmaccus_vx) + +/* Vector Integer Merge and Move Instructions */ +static bool trans_vmv_v_v(DisasContext *s, arg_vmv_v_v *a) +{ + if (vext_check_isa_ill(s) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs1, false)) { + + if (s->vl_eq_vlmax) { + tcg_gen_gvec_mov(s->sew, vreg_ofs(s, a->rd), + vreg_ofs(s, a->rs1), + MAXSZ(s), MAXSZ(s)); + } else { + uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul); + static gen_helper_gvec_2_ptr * const fns[4] = { + gen_helper_vmv_v_v_b, gen_helper_vmv_v_v_h, + gen_helper_vmv_v_v_w, gen_helper_vmv_v_v_d, + }; + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1), + cpu_env, 0, s->vlen / 8, data, fns[s->sew]); + gen_set_label(over); + } + return true; + } + return false; +} + +typedef void gen_helper_vmv_vx(TCGv_ptr, TCGv_i64, TCGv_env, TCGv_i32); +static bool trans_vmv_v_x(DisasContext *s, arg_vmv_v_x *a) +{ + if (vext_check_isa_ill(s) && + vext_check_reg(s, a->rd, false)) { + + TCGv s1; + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + s1 = tcg_temp_new(); + gen_get_gpr(s1, a->rs1); + + if (s->vl_eq_vlmax) { + tcg_gen_gvec_dup_tl(s->sew, vreg_ofs(s, a->rd), + MAXSZ(s), MAXSZ(s), s1); + } else { + TCGv_i32 desc ; + TCGv_i64 s1_i64 = tcg_temp_new_i64(); + TCGv_ptr dest = tcg_temp_new_ptr(); + uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul); + static gen_helper_vmv_vx * const fns[4] = { + gen_helper_vmv_v_x_b, gen_helper_vmv_v_x_h, + gen_helper_vmv_v_x_w, gen_helper_vmv_v_x_d, + }; + + tcg_gen_ext_tl_i64(s1_i64, s1); + desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd)); + fns[s->sew](dest, s1_i64, cpu_env, desc); + + tcg_temp_free_ptr(dest); + tcg_temp_free_i32(desc); + tcg_temp_free_i64(s1_i64); + } + + tcg_temp_free(s1); + gen_set_label(over); + return true; + } + return false; +} + +static bool trans_vmv_v_i(DisasContext *s, arg_vmv_v_i *a) +{ + if (vext_check_isa_ill(s) && + vext_check_reg(s, a->rd, false)) { + + int64_t simm = sextract64(a->rs1, 0, 5); + if (s->vl_eq_vlmax) { + tcg_gen_gvec_dup_imm(s->sew, vreg_ofs(s, a->rd), + MAXSZ(s), MAXSZ(s), simm); + } else { + TCGv_i32 desc; + TCGv_i64 s1; + TCGv_ptr dest; + uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul); + static gen_helper_vmv_vx * const fns[4] = { + gen_helper_vmv_v_x_b, gen_helper_vmv_v_x_h, + gen_helper_vmv_v_x_w, gen_helper_vmv_v_x_d, + }; + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + s1 = tcg_const_i64(simm); + dest = tcg_temp_new_ptr(); + desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd)); + fns[s->sew](dest, s1, cpu_env, desc); + + tcg_temp_free_ptr(dest); + tcg_temp_free_i32(desc); + tcg_temp_free_i64(s1); + gen_set_label(over); + } + return true; + } + return false; +} + +GEN_OPIVV_TRANS(vmerge_vvm, opivv_vadc_check) +GEN_OPIVX_TRANS(vmerge_vxm, opivx_vadc_check) +GEN_OPIVI_TRANS(vmerge_vim, 0, vmerge_vxm, opivx_vadc_check) + +/* + *** Vector Fixed-Point Arithmetic Instructions + */ + +/* Vector Single-Width Saturating Add and Subtract */ +GEN_OPIVV_TRANS(vsaddu_vv, opivv_check) +GEN_OPIVV_TRANS(vsadd_vv, opivv_check) +GEN_OPIVV_TRANS(vssubu_vv, opivv_check) +GEN_OPIVV_TRANS(vssub_vv, opivv_check) +GEN_OPIVX_TRANS(vsaddu_vx, opivx_check) +GEN_OPIVX_TRANS(vsadd_vx, opivx_check) +GEN_OPIVX_TRANS(vssubu_vx, opivx_check) +GEN_OPIVX_TRANS(vssub_vx, opivx_check) +GEN_OPIVI_TRANS(vsaddu_vi, 1, vsaddu_vx, opivx_check) +GEN_OPIVI_TRANS(vsadd_vi, 0, vsadd_vx, opivx_check) + +/* Vector Single-Width Averaging Add and Subtract */ +GEN_OPIVV_TRANS(vaadd_vv, opivv_check) +GEN_OPIVV_TRANS(vasub_vv, opivv_check) +GEN_OPIVX_TRANS(vaadd_vx, opivx_check) +GEN_OPIVX_TRANS(vasub_vx, opivx_check) +GEN_OPIVI_TRANS(vaadd_vi, 0, vaadd_vx, opivx_check) + +/* Vector Single-Width Fractional Multiply with Rounding and Saturation */ +GEN_OPIVV_TRANS(vsmul_vv, opivv_check) +GEN_OPIVX_TRANS(vsmul_vx, opivx_check) + +/* Vector Widening Saturating Scaled Multiply-Add */ +GEN_OPIVV_WIDEN_TRANS(vwsmaccu_vv, opivv_widen_check) +GEN_OPIVV_WIDEN_TRANS(vwsmacc_vv, opivv_widen_check) +GEN_OPIVV_WIDEN_TRANS(vwsmaccsu_vv, opivv_widen_check) +GEN_OPIVX_WIDEN_TRANS(vwsmaccu_vx) +GEN_OPIVX_WIDEN_TRANS(vwsmacc_vx) +GEN_OPIVX_WIDEN_TRANS(vwsmaccsu_vx) +GEN_OPIVX_WIDEN_TRANS(vwsmaccus_vx) + +/* Vector Single-Width Scaling Shift Instructions */ +GEN_OPIVV_TRANS(vssrl_vv, opivv_check) +GEN_OPIVV_TRANS(vssra_vv, opivv_check) +GEN_OPIVX_TRANS(vssrl_vx, opivx_check) +GEN_OPIVX_TRANS(vssra_vx, opivx_check) +GEN_OPIVI_TRANS(vssrl_vi, 1, vssrl_vx, opivx_check) +GEN_OPIVI_TRANS(vssra_vi, 0, vssra_vx, opivx_check) + +/* Vector Narrowing Fixed-Point Clip Instructions */ +GEN_OPIVV_NARROW_TRANS(vnclipu_vv) +GEN_OPIVV_NARROW_TRANS(vnclip_vv) +GEN_OPIVX_NARROW_TRANS(vnclipu_vx) +GEN_OPIVX_NARROW_TRANS(vnclip_vx) +GEN_OPIVI_NARROW_TRANS(vnclipu_vi, 1, vnclipu_vx) +GEN_OPIVI_NARROW_TRANS(vnclip_vi, 1, vnclip_vx) + +/* + *** Vector Float Point Arithmetic Instructions + */ +/* Vector Single-Width Floating-Point Add/Subtract Instructions */ + +/* + * If the current SEW does not correspond to a supported IEEE floating-point + * type, an illegal instruction exception is raised. + */ +static bool opfvv_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, false) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs2, false) && + vext_check_reg(s, a->rs1, false) && + (s->sew != 0)); +} + +/* OPFVV without GVEC IR */ +#define GEN_OPFVV_TRANS(NAME, CHECK) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + if (CHECK(s, a)) { \ + uint32_t data = 0; \ + static gen_helper_gvec_4_ptr * const fns[3] = { \ + gen_helper_##NAME##_h, \ + gen_helper_##NAME##_w, \ + gen_helper_##NAME##_d, \ + }; \ + TCGLabel *over = gen_new_label(); \ + gen_set_rm(s, 7); \ + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \ + \ + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); \ + data = FIELD_DP32(data, VDATA, VM, a->vm); \ + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ + tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ + vreg_ofs(s, a->rs1), \ + vreg_ofs(s, a->rs2), cpu_env, 0, \ + s->vlen / 8, data, fns[s->sew - 1]); \ + gen_set_label(over); \ + return true; \ + } \ + return false; \ +} +GEN_OPFVV_TRANS(vfadd_vv, opfvv_check) +GEN_OPFVV_TRANS(vfsub_vv, opfvv_check) + +typedef void gen_helper_opfvf(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv_ptr, + TCGv_env, TCGv_i32); + +static bool opfvf_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, + uint32_t data, gen_helper_opfvf *fn, DisasContext *s) +{ + TCGv_ptr dest, src2, mask; + TCGv_i32 desc; + + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + dest = tcg_temp_new_ptr(); + mask = tcg_temp_new_ptr(); + src2 = tcg_temp_new_ptr(); + desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + + tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); + tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2)); + tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); + + fn(dest, mask, cpu_fpr[rs1], src2, cpu_env, desc); + + tcg_temp_free_ptr(dest); + tcg_temp_free_ptr(mask); + tcg_temp_free_ptr(src2); + tcg_temp_free_i32(desc); + gen_set_label(over); + return true; +} + +static bool opfvf_check(DisasContext *s, arg_rmrr *a) +{ +/* + * If the current SEW does not correspond to a supported IEEE floating-point + * type, an illegal instruction exception is raised + */ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, false) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs2, false) && + (s->sew != 0)); +} + +/* OPFVF without GVEC IR */ +#define GEN_OPFVF_TRANS(NAME, CHECK) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + if (CHECK(s, a)) { \ + uint32_t data = 0; \ + static gen_helper_opfvf *const fns[3] = { \ + gen_helper_##NAME##_h, \ + gen_helper_##NAME##_w, \ + gen_helper_##NAME##_d, \ + }; \ + gen_set_rm(s, 7); \ + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); \ + data = FIELD_DP32(data, VDATA, VM, a->vm); \ + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ + return opfvf_trans(a->rd, a->rs1, a->rs2, data, \ + fns[s->sew - 1], s); \ + } \ + return false; \ +} + +GEN_OPFVF_TRANS(vfadd_vf, opfvf_check) +GEN_OPFVF_TRANS(vfsub_vf, opfvf_check) +GEN_OPFVF_TRANS(vfrsub_vf, opfvf_check) + +/* Vector Widening Floating-Point Add/Subtract Instructions */ +static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, true) && + vext_check_reg(s, a->rd, true) && + vext_check_reg(s, a->rs2, false) && + vext_check_reg(s, a->rs1, false) && + vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs2, + 1 << s->lmul) && + vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs1, + 1 << s->lmul) && + (s->lmul < 0x3) && (s->sew < 0x3) && (s->sew != 0)); +} + +/* OPFVV with WIDEN */ +#define GEN_OPFVV_WIDEN_TRANS(NAME, CHECK) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + if (CHECK(s, a)) { \ + uint32_t data = 0; \ + static gen_helper_gvec_4_ptr * const fns[2] = { \ + gen_helper_##NAME##_h, gen_helper_##NAME##_w, \ + }; \ + TCGLabel *over = gen_new_label(); \ + gen_set_rm(s, 7); \ + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \ + \ + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); \ + data = FIELD_DP32(data, VDATA, VM, a->vm); \ + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ + tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ + vreg_ofs(s, a->rs1), \ + vreg_ofs(s, a->rs2), cpu_env, 0, \ + s->vlen / 8, data, fns[s->sew - 1]); \ + gen_set_label(over); \ + return true; \ + } \ + return false; \ +} + +GEN_OPFVV_WIDEN_TRANS(vfwadd_vv, opfvv_widen_check) +GEN_OPFVV_WIDEN_TRANS(vfwsub_vv, opfvv_widen_check) + +static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, true) && + vext_check_reg(s, a->rd, true) && + vext_check_reg(s, a->rs2, false) && + vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs2, + 1 << s->lmul) && + (s->lmul < 0x3) && (s->sew < 0x3) && (s->sew != 0)); +} + +/* OPFVF with WIDEN */ +#define GEN_OPFVF_WIDEN_TRANS(NAME) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + if (opfvf_widen_check(s, a)) { \ + uint32_t data = 0; \ + static gen_helper_opfvf *const fns[2] = { \ + gen_helper_##NAME##_h, gen_helper_##NAME##_w, \ + }; \ + gen_set_rm(s, 7); \ + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); \ + data = FIELD_DP32(data, VDATA, VM, a->vm); \ + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ + return opfvf_trans(a->rd, a->rs1, a->rs2, data, \ + fns[s->sew - 1], s); \ + } \ + return false; \ +} + +GEN_OPFVF_WIDEN_TRANS(vfwadd_vf) +GEN_OPFVF_WIDEN_TRANS(vfwsub_vf) + +static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, true) && + vext_check_reg(s, a->rd, true) && + vext_check_reg(s, a->rs2, true) && + vext_check_reg(s, a->rs1, false) && + vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs1, + 1 << s->lmul) && + (s->lmul < 0x3) && (s->sew < 0x3) && (s->sew != 0)); +} + +/* WIDEN OPFVV with WIDEN */ +#define GEN_OPFWV_WIDEN_TRANS(NAME) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + if (opfwv_widen_check(s, a)) { \ + uint32_t data = 0; \ + static gen_helper_gvec_4_ptr * const fns[2] = { \ + gen_helper_##NAME##_h, gen_helper_##NAME##_w, \ + }; \ + TCGLabel *over = gen_new_label(); \ + gen_set_rm(s, 7); \ + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \ + \ + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); \ + data = FIELD_DP32(data, VDATA, VM, a->vm); \ + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ + tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ + vreg_ofs(s, a->rs1), \ + vreg_ofs(s, a->rs2), cpu_env, 0, \ + s->vlen / 8, data, fns[s->sew - 1]); \ + gen_set_label(over); \ + return true; \ + } \ + return false; \ +} + +GEN_OPFWV_WIDEN_TRANS(vfwadd_wv) +GEN_OPFWV_WIDEN_TRANS(vfwsub_wv) + +static bool opfwf_widen_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, true) && + vext_check_reg(s, a->rd, true) && + vext_check_reg(s, a->rs2, true) && + (s->lmul < 0x3) && (s->sew < 0x3) && (s->sew != 0)); +} + +/* WIDEN OPFVF with WIDEN */ +#define GEN_OPFWF_WIDEN_TRANS(NAME) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + if (opfwf_widen_check(s, a)) { \ + uint32_t data = 0; \ + static gen_helper_opfvf *const fns[2] = { \ + gen_helper_##NAME##_h, gen_helper_##NAME##_w, \ + }; \ + gen_set_rm(s, 7); \ + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); \ + data = FIELD_DP32(data, VDATA, VM, a->vm); \ + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ + return opfvf_trans(a->rd, a->rs1, a->rs2, data, \ + fns[s->sew - 1], s); \ + } \ + return false; \ +} + +GEN_OPFWF_WIDEN_TRANS(vfwadd_wf) +GEN_OPFWF_WIDEN_TRANS(vfwsub_wf) + +/* Vector Single-Width Floating-Point Multiply/Divide Instructions */ +GEN_OPFVV_TRANS(vfmul_vv, opfvv_check) +GEN_OPFVV_TRANS(vfdiv_vv, opfvv_check) +GEN_OPFVF_TRANS(vfmul_vf, opfvf_check) +GEN_OPFVF_TRANS(vfdiv_vf, opfvf_check) +GEN_OPFVF_TRANS(vfrdiv_vf, opfvf_check) + +/* Vector Widening Floating-Point Multiply */ +GEN_OPFVV_WIDEN_TRANS(vfwmul_vv, opfvv_widen_check) +GEN_OPFVF_WIDEN_TRANS(vfwmul_vf) + +/* Vector Single-Width Floating-Point Fused Multiply-Add Instructions */ +GEN_OPFVV_TRANS(vfmacc_vv, opfvv_check) +GEN_OPFVV_TRANS(vfnmacc_vv, opfvv_check) +GEN_OPFVV_TRANS(vfmsac_vv, opfvv_check) +GEN_OPFVV_TRANS(vfnmsac_vv, opfvv_check) +GEN_OPFVV_TRANS(vfmadd_vv, opfvv_check) +GEN_OPFVV_TRANS(vfnmadd_vv, opfvv_check) +GEN_OPFVV_TRANS(vfmsub_vv, opfvv_check) +GEN_OPFVV_TRANS(vfnmsub_vv, opfvv_check) +GEN_OPFVF_TRANS(vfmacc_vf, opfvf_check) +GEN_OPFVF_TRANS(vfnmacc_vf, opfvf_check) +GEN_OPFVF_TRANS(vfmsac_vf, opfvf_check) +GEN_OPFVF_TRANS(vfnmsac_vf, opfvf_check) +GEN_OPFVF_TRANS(vfmadd_vf, opfvf_check) +GEN_OPFVF_TRANS(vfnmadd_vf, opfvf_check) +GEN_OPFVF_TRANS(vfmsub_vf, opfvf_check) +GEN_OPFVF_TRANS(vfnmsub_vf, opfvf_check) + +/* Vector Widening Floating-Point Fused Multiply-Add Instructions */ +GEN_OPFVV_WIDEN_TRANS(vfwmacc_vv, opfvv_widen_check) +GEN_OPFVV_WIDEN_TRANS(vfwnmacc_vv, opfvv_widen_check) +GEN_OPFVV_WIDEN_TRANS(vfwmsac_vv, opfvv_widen_check) +GEN_OPFVV_WIDEN_TRANS(vfwnmsac_vv, opfvv_widen_check) +GEN_OPFVF_WIDEN_TRANS(vfwmacc_vf) +GEN_OPFVF_WIDEN_TRANS(vfwnmacc_vf) +GEN_OPFVF_WIDEN_TRANS(vfwmsac_vf) +GEN_OPFVF_WIDEN_TRANS(vfwnmsac_vf) + +/* Vector Floating-Point Square-Root Instruction */ + +/* + * If the current SEW does not correspond to a supported IEEE floating-point + * type, an illegal instruction exception is raised + */ +static bool opfv_check(DisasContext *s, arg_rmr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, false) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs2, false) && + (s->sew != 0)); +} + +#define GEN_OPFV_TRANS(NAME, CHECK) \ +static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ +{ \ + if (CHECK(s, a)) { \ + uint32_t data = 0; \ + static gen_helper_gvec_3_ptr * const fns[3] = { \ + gen_helper_##NAME##_h, \ + gen_helper_##NAME##_w, \ + gen_helper_##NAME##_d, \ + }; \ + TCGLabel *over = gen_new_label(); \ + gen_set_rm(s, 7); \ + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \ + \ + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); \ + data = FIELD_DP32(data, VDATA, VM, a->vm); \ + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ + tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ + vreg_ofs(s, a->rs2), cpu_env, 0, \ + s->vlen / 8, data, fns[s->sew - 1]); \ + gen_set_label(over); \ + return true; \ + } \ + return false; \ +} + +GEN_OPFV_TRANS(vfsqrt_v, opfv_check) + +/* Vector Floating-Point MIN/MAX Instructions */ +GEN_OPFVV_TRANS(vfmin_vv, opfvv_check) +GEN_OPFVV_TRANS(vfmax_vv, opfvv_check) +GEN_OPFVF_TRANS(vfmin_vf, opfvf_check) +GEN_OPFVF_TRANS(vfmax_vf, opfvf_check) + +/* Vector Floating-Point Sign-Injection Instructions */ +GEN_OPFVV_TRANS(vfsgnj_vv, opfvv_check) +GEN_OPFVV_TRANS(vfsgnjn_vv, opfvv_check) +GEN_OPFVV_TRANS(vfsgnjx_vv, opfvv_check) +GEN_OPFVF_TRANS(vfsgnj_vf, opfvf_check) +GEN_OPFVF_TRANS(vfsgnjn_vf, opfvf_check) +GEN_OPFVF_TRANS(vfsgnjx_vf, opfvf_check) + +/* Vector Floating-Point Compare Instructions */ +static bool opfvv_cmp_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_reg(s, a->rs2, false) && + vext_check_reg(s, a->rs1, false) && + (s->sew != 0) && + ((vext_check_overlap_group(a->rd, 1, a->rs1, 1 << s->lmul) && + vext_check_overlap_group(a->rd, 1, a->rs2, 1 << s->lmul)) || + (s->lmul == 0))); +} + +GEN_OPFVV_TRANS(vmfeq_vv, opfvv_cmp_check) +GEN_OPFVV_TRANS(vmfne_vv, opfvv_cmp_check) +GEN_OPFVV_TRANS(vmflt_vv, opfvv_cmp_check) +GEN_OPFVV_TRANS(vmfle_vv, opfvv_cmp_check) +GEN_OPFVV_TRANS(vmford_vv, opfvv_cmp_check) + +static bool opfvf_cmp_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_reg(s, a->rs2, false) && + (s->sew != 0) && + (vext_check_overlap_group(a->rd, 1, a->rs2, 1 << s->lmul) || + (s->lmul == 0))); +} + +GEN_OPFVF_TRANS(vmfeq_vf, opfvf_cmp_check) +GEN_OPFVF_TRANS(vmfne_vf, opfvf_cmp_check) +GEN_OPFVF_TRANS(vmflt_vf, opfvf_cmp_check) +GEN_OPFVF_TRANS(vmfle_vf, opfvf_cmp_check) +GEN_OPFVF_TRANS(vmfgt_vf, opfvf_cmp_check) +GEN_OPFVF_TRANS(vmfge_vf, opfvf_cmp_check) +GEN_OPFVF_TRANS(vmford_vf, opfvf_cmp_check) + +/* Vector Floating-Point Classify Instruction */ +GEN_OPFV_TRANS(vfclass_v, opfv_check) + +/* Vector Floating-Point Merge Instruction */ +GEN_OPFVF_TRANS(vfmerge_vfm, opfvf_check) + +static bool trans_vfmv_v_f(DisasContext *s, arg_vfmv_v_f *a) +{ + if (vext_check_isa_ill(s) && + vext_check_reg(s, a->rd, false) && + (s->sew != 0)) { + + if (s->vl_eq_vlmax) { + tcg_gen_gvec_dup_i64(s->sew, vreg_ofs(s, a->rd), + MAXSZ(s), MAXSZ(s), cpu_fpr[a->rs1]); + } else { + TCGv_ptr dest; + TCGv_i32 desc; + uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul); + static gen_helper_vmv_vx * const fns[3] = { + gen_helper_vmv_v_x_h, + gen_helper_vmv_v_x_w, + gen_helper_vmv_v_x_d, + }; + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + dest = tcg_temp_new_ptr(); + desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd)); + fns[s->sew - 1](dest, cpu_fpr[a->rs1], cpu_env, desc); + + tcg_temp_free_ptr(dest); + tcg_temp_free_i32(desc); + gen_set_label(over); + } + return true; + } + return false; +} + +/* Single-Width Floating-Point/Integer Type-Convert Instructions */ +GEN_OPFV_TRANS(vfcvt_xu_f_v, opfv_check) +GEN_OPFV_TRANS(vfcvt_x_f_v, opfv_check) +GEN_OPFV_TRANS(vfcvt_f_xu_v, opfv_check) +GEN_OPFV_TRANS(vfcvt_f_x_v, opfv_check) + +/* Widening Floating-Point/Integer Type-Convert Instructions */ + +/* + * If the current SEW does not correspond to a supported IEEE floating-point + * type, an illegal instruction exception is raised + */ +static bool opfv_widen_check(DisasContext *s, arg_rmr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, true) && + vext_check_reg(s, a->rd, true) && + vext_check_reg(s, a->rs2, false) && + vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs2, + 1 << s->lmul) && + (s->lmul < 0x3) && (s->sew < 0x3) && (s->sew != 0)); +} + +#define GEN_OPFV_WIDEN_TRANS(NAME) \ +static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ +{ \ + if (opfv_widen_check(s, a)) { \ + uint32_t data = 0; \ + static gen_helper_gvec_3_ptr * const fns[2] = { \ + gen_helper_##NAME##_h, \ + gen_helper_##NAME##_w, \ + }; \ + TCGLabel *over = gen_new_label(); \ + gen_set_rm(s, 7); \ + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \ + \ + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); \ + data = FIELD_DP32(data, VDATA, VM, a->vm); \ + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ + tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ + vreg_ofs(s, a->rs2), cpu_env, 0, \ + s->vlen / 8, data, fns[s->sew - 1]); \ + gen_set_label(over); \ + return true; \ + } \ + return false; \ +} + +GEN_OPFV_WIDEN_TRANS(vfwcvt_xu_f_v) +GEN_OPFV_WIDEN_TRANS(vfwcvt_x_f_v) +GEN_OPFV_WIDEN_TRANS(vfwcvt_f_xu_v) +GEN_OPFV_WIDEN_TRANS(vfwcvt_f_x_v) +GEN_OPFV_WIDEN_TRANS(vfwcvt_f_f_v) + +/* Narrowing Floating-Point/Integer Type-Convert Instructions */ + +/* + * If the current SEW does not correspond to a supported IEEE floating-point + * type, an illegal instruction exception is raised + */ +static bool opfv_narrow_check(DisasContext *s, arg_rmr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, false) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs2, true) && + vext_check_overlap_group(a->rd, 1 << s->lmul, a->rs2, + 2 << s->lmul) && + (s->lmul < 0x3) && (s->sew < 0x3) && (s->sew != 0)); +} + +#define GEN_OPFV_NARROW_TRANS(NAME) \ +static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ +{ \ + if (opfv_narrow_check(s, a)) { \ + uint32_t data = 0; \ + static gen_helper_gvec_3_ptr * const fns[2] = { \ + gen_helper_##NAME##_h, \ + gen_helper_##NAME##_w, \ + }; \ + TCGLabel *over = gen_new_label(); \ + gen_set_rm(s, 7); \ + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \ + \ + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); \ + data = FIELD_DP32(data, VDATA, VM, a->vm); \ + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ + tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ + vreg_ofs(s, a->rs2), cpu_env, 0, \ + s->vlen / 8, data, fns[s->sew - 1]); \ + gen_set_label(over); \ + return true; \ + } \ + return false; \ +} + +GEN_OPFV_NARROW_TRANS(vfncvt_xu_f_v) +GEN_OPFV_NARROW_TRANS(vfncvt_x_f_v) +GEN_OPFV_NARROW_TRANS(vfncvt_f_xu_v) +GEN_OPFV_NARROW_TRANS(vfncvt_f_x_v) +GEN_OPFV_NARROW_TRANS(vfncvt_f_f_v) + +/* + *** Vector Reduction Operations + */ +/* Vector Single-Width Integer Reduction Instructions */ +static bool reduction_check(DisasContext *s, arg_rmrr *a) +{ + return vext_check_isa_ill(s) && vext_check_reg(s, a->rs2, false); +} + +GEN_OPIVV_TRANS(vredsum_vs, reduction_check) +GEN_OPIVV_TRANS(vredmaxu_vs, reduction_check) +GEN_OPIVV_TRANS(vredmax_vs, reduction_check) +GEN_OPIVV_TRANS(vredminu_vs, reduction_check) +GEN_OPIVV_TRANS(vredmin_vs, reduction_check) +GEN_OPIVV_TRANS(vredand_vs, reduction_check) +GEN_OPIVV_TRANS(vredor_vs, reduction_check) +GEN_OPIVV_TRANS(vredxor_vs, reduction_check) + +/* Vector Widening Integer Reduction Instructions */ +GEN_OPIVV_WIDEN_TRANS(vwredsum_vs, reduction_check) +GEN_OPIVV_WIDEN_TRANS(vwredsumu_vs, reduction_check) + +/* Vector Single-Width Floating-Point Reduction Instructions */ +GEN_OPFVV_TRANS(vfredsum_vs, reduction_check) +GEN_OPFVV_TRANS(vfredmax_vs, reduction_check) +GEN_OPFVV_TRANS(vfredmin_vs, reduction_check) + +/* Vector Widening Floating-Point Reduction Instructions */ +GEN_OPFVV_WIDEN_TRANS(vfwredsum_vs, reduction_check) + +/* + *** Vector Mask Operations + */ + +/* Vector Mask-Register Logical Instructions */ +#define GEN_MM_TRANS(NAME) \ +static bool trans_##NAME(DisasContext *s, arg_r *a) \ +{ \ + if (vext_check_isa_ill(s)) { \ + uint32_t data = 0; \ + gen_helper_gvec_4_ptr *fn = gen_helper_##NAME; \ + TCGLabel *over = gen_new_label(); \ + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \ + \ + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); \ + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ + tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ + vreg_ofs(s, a->rs1), \ + vreg_ofs(s, a->rs2), cpu_env, 0, \ + s->vlen / 8, data, fn); \ + gen_set_label(over); \ + return true; \ + } \ + return false; \ +} + +GEN_MM_TRANS(vmand_mm) +GEN_MM_TRANS(vmnand_mm) +GEN_MM_TRANS(vmandnot_mm) +GEN_MM_TRANS(vmxor_mm) +GEN_MM_TRANS(vmor_mm) +GEN_MM_TRANS(vmnor_mm) +GEN_MM_TRANS(vmornot_mm) +GEN_MM_TRANS(vmxnor_mm) + +/* Vector mask population count vmpopc */ +static bool trans_vmpopc_m(DisasContext *s, arg_rmr *a) +{ + if (vext_check_isa_ill(s)) { + TCGv_ptr src2, mask; + TCGv dst; + TCGv_i32 desc; + uint32_t data = 0; + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, VM, a->vm); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + + mask = tcg_temp_new_ptr(); + src2 = tcg_temp_new_ptr(); + dst = tcg_temp_new(); + desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + + tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, a->rs2)); + tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); + + gen_helper_vmpopc_m(dst, mask, src2, cpu_env, desc); + gen_set_gpr(a->rd, dst); + + tcg_temp_free_ptr(mask); + tcg_temp_free_ptr(src2); + tcg_temp_free(dst); + tcg_temp_free_i32(desc); + return true; + } + return false; +} + +/* vmfirst find-first-set mask bit */ +static bool trans_vmfirst_m(DisasContext *s, arg_rmr *a) +{ + if (vext_check_isa_ill(s)) { + TCGv_ptr src2, mask; + TCGv dst; + TCGv_i32 desc; + uint32_t data = 0; + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, VM, a->vm); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + + mask = tcg_temp_new_ptr(); + src2 = tcg_temp_new_ptr(); + dst = tcg_temp_new(); + desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + + tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, a->rs2)); + tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); + + gen_helper_vmfirst_m(dst, mask, src2, cpu_env, desc); + gen_set_gpr(a->rd, dst); + + tcg_temp_free_ptr(mask); + tcg_temp_free_ptr(src2); + tcg_temp_free(dst); + tcg_temp_free_i32(desc); + return true; + } + return false; +} + +/* vmsbf.m set-before-first mask bit */ +/* vmsif.m set-includ-first mask bit */ +/* vmsof.m set-only-first mask bit */ +#define GEN_M_TRANS(NAME) \ +static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ +{ \ + if (vext_check_isa_ill(s)) { \ + uint32_t data = 0; \ + gen_helper_gvec_3_ptr *fn = gen_helper_##NAME; \ + TCGLabel *over = gen_new_label(); \ + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \ + \ + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); \ + data = FIELD_DP32(data, VDATA, VM, a->vm); \ + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ + tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), \ + vreg_ofs(s, 0), vreg_ofs(s, a->rs2), \ + cpu_env, 0, s->vlen / 8, data, fn); \ + gen_set_label(over); \ + return true; \ + } \ + return false; \ +} + +GEN_M_TRANS(vmsbf_m) +GEN_M_TRANS(vmsif_m) +GEN_M_TRANS(vmsof_m) + +/* Vector Iota Instruction */ +static bool trans_viota_m(DisasContext *s, arg_viota_m *a) +{ + if (vext_check_isa_ill(s) && + vext_check_reg(s, a->rd, false) && + vext_check_overlap_group(a->rd, 1 << s->lmul, a->rs2, 1) && + (a->vm != 0 || a->rd != 0)) { + uint32_t data = 0; + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, VM, a->vm); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + static gen_helper_gvec_3_ptr * const fns[4] = { + gen_helper_viota_m_b, gen_helper_viota_m_h, + gen_helper_viota_m_w, gen_helper_viota_m_d, + }; + tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), + vreg_ofs(s, a->rs2), cpu_env, 0, + s->vlen / 8, data, fns[s->sew]); + gen_set_label(over); + return true; + } + return false; +} + +/* Vector Element Index Instruction */ +static bool trans_vid_v(DisasContext *s, arg_vid_v *a) +{ + if (vext_check_isa_ill(s) && + vext_check_reg(s, a->rd, false) && + vext_check_overlap_mask(s, a->rd, a->vm, false)) { + uint32_t data = 0; + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, VM, a->vm); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + static gen_helper_gvec_2_ptr * const fns[4] = { + gen_helper_vid_v_b, gen_helper_vid_v_h, + gen_helper_vid_v_w, gen_helper_vid_v_d, + }; + tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), + cpu_env, 0, s->vlen / 8, data, fns[s->sew]); + gen_set_label(over); + return true; + } + return false; +} + +/* + *** Vector Permutation Instructions + */ + +/* Integer Extract Instruction */ + +static void load_element(TCGv_i64 dest, TCGv_ptr base, + int ofs, int sew) +{ + switch (sew) { + case MO_8: + tcg_gen_ld8u_i64(dest, base, ofs); + break; + case MO_16: + tcg_gen_ld16u_i64(dest, base, ofs); + break; + case MO_32: + tcg_gen_ld32u_i64(dest, base, ofs); + break; + case MO_64: + tcg_gen_ld_i64(dest, base, ofs); + break; + default: + g_assert_not_reached(); + break; + } +} + +/* offset of the idx element with base regsiter r */ +static uint32_t endian_ofs(DisasContext *s, int r, int idx) +{ +#ifdef HOST_WORDS_BIGENDIAN + return vreg_ofs(s, r) + ((idx ^ (7 >> s->sew)) << s->sew); +#else + return vreg_ofs(s, r) + (idx << s->sew); +#endif +} + +/* adjust the index according to the endian */ +static void endian_adjust(TCGv_i32 ofs, int sew) +{ +#ifdef HOST_WORDS_BIGENDIAN + tcg_gen_xori_i32(ofs, ofs, 7 >> sew); +#endif +} + +/* Load idx >= VLMAX ? 0 : vreg[idx] */ +static void vec_element_loadx(DisasContext *s, TCGv_i64 dest, + int vreg, TCGv idx, int vlmax) +{ + TCGv_i32 ofs = tcg_temp_new_i32(); + TCGv_ptr base = tcg_temp_new_ptr(); + TCGv_i64 t_idx = tcg_temp_new_i64(); + TCGv_i64 t_vlmax, t_zero; + + /* + * Mask the index to the length so that we do + * not produce an out-of-range load. + */ + tcg_gen_trunc_tl_i32(ofs, idx); + tcg_gen_andi_i32(ofs, ofs, vlmax - 1); + + /* Convert the index to an offset. */ + endian_adjust(ofs, s->sew); + tcg_gen_shli_i32(ofs, ofs, s->sew); + + /* Convert the index to a pointer. */ + tcg_gen_ext_i32_ptr(base, ofs); + tcg_gen_add_ptr(base, base, cpu_env); + + /* Perform the load. */ + load_element(dest, base, + vreg_ofs(s, vreg), s->sew); + tcg_temp_free_ptr(base); + tcg_temp_free_i32(ofs); + + /* Flush out-of-range indexing to zero. */ + t_vlmax = tcg_const_i64(vlmax); + t_zero = tcg_const_i64(0); + tcg_gen_extu_tl_i64(t_idx, idx); + + tcg_gen_movcond_i64(TCG_COND_LTU, dest, t_idx, + t_vlmax, dest, t_zero); + + tcg_temp_free_i64(t_vlmax); + tcg_temp_free_i64(t_zero); + tcg_temp_free_i64(t_idx); +} + +static void vec_element_loadi(DisasContext *s, TCGv_i64 dest, + int vreg, int idx) +{ + load_element(dest, cpu_env, endian_ofs(s, vreg, idx), s->sew); +} + +static bool trans_vext_x_v(DisasContext *s, arg_r *a) +{ + TCGv_i64 tmp = tcg_temp_new_i64(); + TCGv dest = tcg_temp_new(); + + if (a->rs1 == 0) { + /* Special case vmv.x.s rd, vs2. */ + vec_element_loadi(s, tmp, a->rs2, 0); + } else { + /* This instruction ignores LMUL and vector register groups */ + int vlmax = s->vlen >> (3 + s->sew); + vec_element_loadx(s, tmp, a->rs2, cpu_gpr[a->rs1], vlmax); + } + tcg_gen_trunc_i64_tl(dest, tmp); + gen_set_gpr(a->rd, dest); + + tcg_temp_free(dest); + tcg_temp_free_i64(tmp); + return true; +} + +/* Integer Scalar Move Instruction */ + +static void store_element(TCGv_i64 val, TCGv_ptr base, + int ofs, int sew) +{ + switch (sew) { + case MO_8: + tcg_gen_st8_i64(val, base, ofs); + break; + case MO_16: + tcg_gen_st16_i64(val, base, ofs); + break; + case MO_32: + tcg_gen_st32_i64(val, base, ofs); + break; + case MO_64: + tcg_gen_st_i64(val, base, ofs); + break; + default: + g_assert_not_reached(); + break; + } +} + +/* + * Store vreg[idx] = val. + * The index must be in range of VLMAX. + */ +static void vec_element_storei(DisasContext *s, int vreg, + int idx, TCGv_i64 val) +{ + store_element(val, cpu_env, endian_ofs(s, vreg, idx), s->sew); +} + +/* vmv.s.x vd, rs1 # vd[0] = rs1 */ +static bool trans_vmv_s_x(DisasContext *s, arg_vmv_s_x *a) +{ + if (vext_check_isa_ill(s)) { + /* This instruction ignores LMUL and vector register groups */ + int maxsz = s->vlen >> 3; + TCGv_i64 t1; + TCGLabel *over = gen_new_label(); + + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + tcg_gen_gvec_dup_imm(SEW64, vreg_ofs(s, a->rd), maxsz, maxsz, 0); + if (a->rs1 == 0) { + goto done; + } + + t1 = tcg_temp_new_i64(); + tcg_gen_extu_tl_i64(t1, cpu_gpr[a->rs1]); + vec_element_storei(s, a->rd, 0, t1); + tcg_temp_free_i64(t1); + done: + gen_set_label(over); + return true; + } + return false; +} + +/* Floating-Point Scalar Move Instructions */ +static bool trans_vfmv_f_s(DisasContext *s, arg_vfmv_f_s *a) +{ + if (!s->vill && has_ext(s, RVF) && + (s->mstatus_fs != 0) && (s->sew != 0)) { + unsigned int len = 8 << s->sew; + + vec_element_loadi(s, cpu_fpr[a->rd], a->rs2, 0); + if (len < 64) { + tcg_gen_ori_i64(cpu_fpr[a->rd], cpu_fpr[a->rd], + MAKE_64BIT_MASK(len, 64 - len)); + } + + mark_fs_dirty(s); + return true; + } + return false; +} + +/* vfmv.s.f vd, rs1 # vd[0] = rs1 (vs2=0) */ +static bool trans_vfmv_s_f(DisasContext *s, arg_vfmv_s_f *a) +{ + if (!s->vill && has_ext(s, RVF) && (s->sew != 0)) { + TCGv_i64 t1; + /* The instructions ignore LMUL and vector register group. */ + uint32_t vlmax = s->vlen >> 3; + + /* if vl == 0, skip vector register write back */ + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + /* zeroed all elements */ + tcg_gen_gvec_dup_imm(SEW64, vreg_ofs(s, a->rd), vlmax, vlmax, 0); + + /* NaN-box f[rs1] as necessary for SEW */ + t1 = tcg_temp_new_i64(); + if (s->sew == MO_64 && !has_ext(s, RVD)) { + tcg_gen_ori_i64(t1, cpu_fpr[a->rs1], MAKE_64BIT_MASK(32, 32)); + } else { + tcg_gen_mov_i64(t1, cpu_fpr[a->rs1]); + } + vec_element_storei(s, a->rd, 0, t1); + tcg_temp_free_i64(t1); + gen_set_label(over); + return true; + } + return false; +} + +/* Vector Slide Instructions */ +static bool slideup_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, true) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs2, false) && + (a->rd != a->rs2)); +} + +GEN_OPIVX_TRANS(vslideup_vx, slideup_check) +GEN_OPIVX_TRANS(vslide1up_vx, slideup_check) +GEN_OPIVI_TRANS(vslideup_vi, 1, vslideup_vx, slideup_check) + +GEN_OPIVX_TRANS(vslidedown_vx, opivx_check) +GEN_OPIVX_TRANS(vslide1down_vx, opivx_check) +GEN_OPIVI_TRANS(vslidedown_vi, 1, vslidedown_vx, opivx_check) + +/* Vector Register Gather Instruction */ +static bool vrgather_vv_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, true) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs1, false) && + vext_check_reg(s, a->rs2, false) && + (a->rd != a->rs2) && (a->rd != a->rs1)); +} + +GEN_OPIVV_TRANS(vrgather_vv, vrgather_vv_check) + +static bool vrgather_vx_check(DisasContext *s, arg_rmrr *a) +{ + return (vext_check_isa_ill(s) && + vext_check_overlap_mask(s, a->rd, a->vm, true) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs2, false) && + (a->rd != a->rs2)); +} + +/* vrgather.vx vd, vs2, rs1, vm # vd[i] = (x[rs1] >= VLMAX) ? 0 : vs2[rs1] */ +static bool trans_vrgather_vx(DisasContext *s, arg_rmrr *a) +{ + if (!vrgather_vx_check(s, a)) { + return false; + } + + if (a->vm && s->vl_eq_vlmax) { + int vlmax = s->vlen / s->mlen; + TCGv_i64 dest = tcg_temp_new_i64(); + + if (a->rs1 == 0) { + vec_element_loadi(s, dest, a->rs2, 0); + } else { + vec_element_loadx(s, dest, a->rs2, cpu_gpr[a->rs1], vlmax); + } + + tcg_gen_gvec_dup_i64(s->sew, vreg_ofs(s, a->rd), + MAXSZ(s), MAXSZ(s), dest); + tcg_temp_free_i64(dest); + } else { + static gen_helper_opivx * const fns[4] = { + gen_helper_vrgather_vx_b, gen_helper_vrgather_vx_h, + gen_helper_vrgather_vx_w, gen_helper_vrgather_vx_d + }; + return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s); + } + return true; +} + +/* vrgather.vi vd, vs2, imm, vm # vd[i] = (imm >= VLMAX) ? 0 : vs2[imm] */ +static bool trans_vrgather_vi(DisasContext *s, arg_rmrr *a) +{ + if (!vrgather_vx_check(s, a)) { + return false; + } + + if (a->vm && s->vl_eq_vlmax) { + if (a->rs1 >= s->vlen / s->mlen) { + tcg_gen_gvec_dup_imm(SEW64, vreg_ofs(s, a->rd), + MAXSZ(s), MAXSZ(s), 0); + } else { + tcg_gen_gvec_dup_mem(s->sew, vreg_ofs(s, a->rd), + endian_ofs(s, a->rs2, a->rs1), + MAXSZ(s), MAXSZ(s)); + } + } else { + static gen_helper_opivx * const fns[4] = { + gen_helper_vrgather_vx_b, gen_helper_vrgather_vx_h, + gen_helper_vrgather_vx_w, gen_helper_vrgather_vx_d + }; + return opivi_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s, 1); + } + return true; +} + +/* Vector Compress Instruction */ +static bool vcompress_vm_check(DisasContext *s, arg_r *a) +{ + return (vext_check_isa_ill(s) && + vext_check_reg(s, a->rd, false) && + vext_check_reg(s, a->rs2, false) && + vext_check_overlap_group(a->rd, 1 << s->lmul, a->rs1, 1) && + (a->rd != a->rs2)); +} + +static bool trans_vcompress_vm(DisasContext *s, arg_r *a) +{ + if (vcompress_vm_check(s, a)) { + uint32_t data = 0; + static gen_helper_gvec_4_ptr * const fns[4] = { + gen_helper_vcompress_vm_b, gen_helper_vcompress_vm_h, + gen_helper_vcompress_vm_w, gen_helper_vcompress_vm_d, + }; + TCGLabel *over = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); + + data = FIELD_DP32(data, VDATA, MLEN, s->mlen); + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); + tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), + vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2), + cpu_env, 0, s->vlen / 8, data, fns[s->sew]); + gen_set_label(over); + return true; + } + return false; +} diff --git a/target/riscv/internals.h b/target/riscv/internals.h new file mode 100644 index 0000000000000000000000000000000000000000..b15ad394bb972cec6cdbfd748c846c4b99ef875d --- /dev/null +++ b/target/riscv/internals.h @@ -0,0 +1,61 @@ +/* + * QEMU RISC-V CPU -- internal functions and types + * + * Copyright (c) 2020 T-Head Semiconductor Co., Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#ifndef RISCV_CPU_INTERNALS_H +#define RISCV_CPU_INTERNALS_H + +#include "hw/registerfields.h" + +/* share data between vector helpers and decode code */ +FIELD(VDATA, MLEN, 0, 8) +FIELD(VDATA, VM, 8, 1) +FIELD(VDATA, LMUL, 9, 2) +FIELD(VDATA, NF, 11, 4) +FIELD(VDATA, WD, 11, 1) + +/* float point classify helpers */ +target_ulong fclass_h(uint64_t frs1); +target_ulong fclass_s(uint64_t frs1); +target_ulong fclass_d(uint64_t frs1); + +#define SEW8 0 +#define SEW16 1 +#define SEW32 2 +#define SEW64 3 + +#ifndef CONFIG_USER_ONLY +extern const VMStateDescription vmstate_riscv_cpu; +#endif + +static inline uint64_t nanbox_s(float32 f) +{ + return f | MAKE_64BIT_MASK(32, 32); +} + +static inline float32 check_nanbox_s(uint64_t f) +{ + uint64_t mask = MAKE_64BIT_MASK(32, 32); + + if (likely((f & mask) == mask)) { + return (uint32_t)f; + } else { + return 0x7fc00000u; /* default qnan */ + } +} + +#endif diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index 0ab5de43d3af2346e201d6baa67deaf7ffffc9e5..1e16d24544a0d520ce9db6622869499c0ef1584f 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -13,7 +13,7 @@ * more details. * * You should have received a copy of the GNU General Public License along with - * this program. If not, see ;. + * this program. If not, see . */ #include "qemu/osdep.h" @@ -159,6 +159,12 @@ static int kvm_riscv_get_regs_csr(CPUState *cs) } env->scause = reg; + ret = kvm_get_one_reg(cs, RISCV_CSR_REG(stval), ®); + if (ret) { + return ret; + } + env->sbadaddr = reg; + ret = kvm_get_one_reg(cs, RISCV_CSR_REG(sip), ®); if (ret) { return ret; @@ -216,6 +222,12 @@ static int kvm_riscv_put_regs_csr(CPUState *cs) return ret; } + reg = env->sbadaddr; + ret = kvm_set_one_reg(cs, RISCV_CSR_REG(stval), ®); + if (ret) { + return ret; + } + reg = env->mip; ret = kvm_set_one_reg(cs, RISCV_CSR_REG(sip), ®); if (ret) { @@ -457,6 +469,7 @@ int kvm_arch_init_vcpu(CPUState *cs) int ret = 0; target_ulong isa; RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; __u64 id; qemu_add_vm_change_state_handler(kvm_riscv_vm_state_change, cs); @@ -466,7 +479,7 @@ int kvm_arch_init_vcpu(CPUState *cs) if (ret) { return ret; } - cpu->env.misa = isa; + env->misa = isa; return ret; } @@ -561,9 +574,10 @@ void kvm_riscv_reset_vcpu(RISCVCPU *cpu) if (!kvm_enabled()) { return; } - env->pc = cpu->env.loader_start; + env->pc = cpu->env.kernel_addr; env->gpr[10] = kvm_arch_vcpu_id(CPU(cpu)); /* a0 */ - env->gpr[11] = cpu->env.fdt_start; /* a1 */ + env->gpr[11] = cpu->env.fdt_addr; /* a1 */ + env->satp = 0; } void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level) diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h index b3ab2c3d96172b114574d74edcecc234645df01c..ed281bdce02839524aef9ab0cb91447944cd6e39 100644 --- a/target/riscv/kvm_riscv.h +++ b/target/riscv/kvm_riscv.h @@ -13,7 +13,7 @@ * more details. * * You should have received a copy of the GNU General Public License along with - * this program. If not, see ;. + * this program. If not, see . */ #ifndef QEMU_KVM_RISCV_H diff --git a/target/riscv/machine.c b/target/riscv/machine.c new file mode 100644 index 0000000000000000000000000000000000000000..ef2d5395a837c221647d51d632a0fafd98a4108c --- /dev/null +++ b/target/riscv/machine.c @@ -0,0 +1,210 @@ +/* + * RISC-V VMState Description + * + * Copyright (c) 2020 Huawei Technologies Co., Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "qemu/error-report.h" +#include "sysemu/kvm.h" +#include "migration/cpu.h" + +static bool pmp_needed(void *opaque) +{ + RISCVCPU *cpu = opaque; + CPURISCVState *env = &cpu->env; + + return riscv_feature(env, RISCV_FEATURE_PMP); +} + +static int pmp_post_load(void *opaque, int version_id) +{ + RISCVCPU *cpu = opaque; + CPURISCVState *env = &cpu->env; + int i; + + for (i = 0; i < MAX_RISCV_PMPS; i++) { + pmp_update_rule_addr(env, i); + } + pmp_update_rule_nums(env); + + return 0; +} + +static const VMStateDescription vmstate_pmp_entry = { + .name = "cpu/pmp/entry", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINTTL(addr_reg, pmp_entry_t), + VMSTATE_UINT8(cfg_reg, pmp_entry_t), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_pmp = { + .name = "cpu/pmp", + .version_id = 1, + .minimum_version_id = 1, + .needed = pmp_needed, + .post_load = pmp_post_load, + .fields = (VMStateField[]) { + VMSTATE_STRUCT_ARRAY(env.pmp_state.pmp, RISCVCPU, MAX_RISCV_PMPS, + 0, vmstate_pmp_entry, pmp_entry_t), + VMSTATE_END_OF_LIST() + } +}; + +static bool hyper_needed(void *opaque) +{ + RISCVCPU *cpu = opaque; + CPURISCVState *env = &cpu->env; + + return riscv_has_ext(env, RVH); +} + +static bool vector_needed(void *opaque) +{ + RISCVCPU *cpu = opaque; + CPURISCVState *env = &cpu->env; + + return riscv_has_ext(env, RVV); +} + +static const VMStateDescription vmstate_vector = { + .name = "cpu/vector", + .version_id = 1, + .minimum_version_id = 1, + .needed = vector_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT64_ARRAY(env.vreg, RISCVCPU, 32 * RV_VLEN_MAX / 64), + VMSTATE_UINTTL(env.vxrm, RISCVCPU), + VMSTATE_UINTTL(env.vxsat, RISCVCPU), + VMSTATE_UINTTL(env.vl, RISCVCPU), + VMSTATE_UINTTL(env.vstart, RISCVCPU), + VMSTATE_UINTTL(env.vtype, RISCVCPU), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_hyper = { + .name = "cpu/hyper", + .version_id = 1, + .minimum_version_id = 1, + .needed = hyper_needed, + .fields = (VMStateField[]) { + VMSTATE_UINTTL(env.hstatus, RISCVCPU), + VMSTATE_UINTTL(env.hedeleg, RISCVCPU), + VMSTATE_UINTTL(env.hideleg, RISCVCPU), + VMSTATE_UINTTL(env.hcounteren, RISCVCPU), + VMSTATE_UINTTL(env.htval, RISCVCPU), + VMSTATE_UINTTL(env.htinst, RISCVCPU), + VMSTATE_UINTTL(env.hgatp, RISCVCPU), + VMSTATE_UINT64(env.htimedelta, RISCVCPU), + + VMSTATE_UINT64(env.vsstatus, RISCVCPU), + VMSTATE_UINTTL(env.vstvec, RISCVCPU), + VMSTATE_UINTTL(env.vsscratch, RISCVCPU), + VMSTATE_UINTTL(env.vsepc, RISCVCPU), + VMSTATE_UINTTL(env.vscause, RISCVCPU), + VMSTATE_UINTTL(env.vstval, RISCVCPU), + VMSTATE_UINTTL(env.vsatp, RISCVCPU), + + VMSTATE_UINTTL(env.mtval2, RISCVCPU), + VMSTATE_UINTTL(env.mtinst, RISCVCPU), + + VMSTATE_UINTTL(env.stvec_hs, RISCVCPU), + VMSTATE_UINTTL(env.sscratch_hs, RISCVCPU), + VMSTATE_UINTTL(env.sepc_hs, RISCVCPU), + VMSTATE_UINTTL(env.scause_hs, RISCVCPU), + VMSTATE_UINTTL(env.stval_hs, RISCVCPU), + VMSTATE_UINTTL(env.satp_hs, RISCVCPU), + VMSTATE_UINT64(env.mstatus_hs, RISCVCPU), + + VMSTATE_END_OF_LIST() + } +}; + +static int cpu_post_load(void *opaque, int version_id) +{ + RISCVCPU *cpu = opaque; + CPURISCVState *env = &cpu->env; + + env->kvm_timer_dirty = true; + return 0; +} + +const VMStateDescription vmstate_riscv_cpu = { + .name = "cpu", + .version_id = 1, + .minimum_version_id = 1, + .post_load = cpu_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32), + VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32), + VMSTATE_UINTTL(env.pc, RISCVCPU), + VMSTATE_UINTTL(env.load_res, RISCVCPU), + VMSTATE_UINTTL(env.load_val, RISCVCPU), + VMSTATE_UINTTL(env.frm, RISCVCPU), + VMSTATE_UINTTL(env.badaddr, RISCVCPU), + VMSTATE_UINTTL(env.guest_phys_fault_addr, RISCVCPU), + VMSTATE_UINTTL(env.priv_ver, RISCVCPU), + VMSTATE_UINTTL(env.vext_ver, RISCVCPU), + VMSTATE_UINTTL(env.misa, RISCVCPU), + VMSTATE_UINTTL(env.misa_mask, RISCVCPU), + VMSTATE_UINT32(env.features, RISCVCPU), + VMSTATE_UINTTL(env.priv, RISCVCPU), + VMSTATE_UINTTL(env.virt, RISCVCPU), + VMSTATE_UINTTL(env.resetvec, RISCVCPU), + VMSTATE_UINTTL(env.mhartid, RISCVCPU), + VMSTATE_UINT64(env.mstatus, RISCVCPU), + VMSTATE_UINTTL(env.mip, RISCVCPU), + VMSTATE_UINT32(env.miclaim, RISCVCPU), + VMSTATE_UINTTL(env.mie, RISCVCPU), + VMSTATE_UINTTL(env.mideleg, RISCVCPU), + VMSTATE_UINTTL(env.sptbr, RISCVCPU), + VMSTATE_UINTTL(env.satp, RISCVCPU), + VMSTATE_UINTTL(env.sbadaddr, RISCVCPU), + VMSTATE_UINTTL(env.mbadaddr, RISCVCPU), + VMSTATE_UINTTL(env.medeleg, RISCVCPU), + VMSTATE_UINTTL(env.stvec, RISCVCPU), + VMSTATE_UINTTL(env.sepc, RISCVCPU), + VMSTATE_UINTTL(env.scause, RISCVCPU), + VMSTATE_UINTTL(env.mtvec, RISCVCPU), + VMSTATE_UINTTL(env.mepc, RISCVCPU), + VMSTATE_UINTTL(env.mcause, RISCVCPU), + VMSTATE_UINTTL(env.mtval, RISCVCPU), + VMSTATE_UINTTL(env.scounteren, RISCVCPU), + VMSTATE_UINTTL(env.mcounteren, RISCVCPU), + VMSTATE_UINTTL(env.sscratch, RISCVCPU), + VMSTATE_UINTTL(env.mscratch, RISCVCPU), + VMSTATE_UINT64(env.mfromhost, RISCVCPU), + VMSTATE_UINT64(env.mtohost, RISCVCPU), + VMSTATE_UINT64(env.timecmp, RISCVCPU), + + VMSTATE_UINT64(env.kvm_timer_time, RISCVCPU), + VMSTATE_UINT64(env.kvm_timer_compare, RISCVCPU), + VMSTATE_UINT64(env.kvm_timer_state, RISCVCPU), + + VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription * []) { + &vmstate_pmp, + &vmstate_hyper, + &vmstate_vector, + NULL + } +}; diff --git a/target/riscv/meson.build b/target/riscv/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..12e9c074afa643a7d9a978fe2720955b754b36fb --- /dev/null +++ b/target/riscv/meson.build @@ -0,0 +1,36 @@ +# FIXME extra_args should accept files() +dir = meson.current_source_dir() +gen32 = [ + decodetree.process('insn16.decode', extra_args: [dir / 'insn16-32.decode', '--static-decode=decode_insn16', '--insnwidth=16']), + decodetree.process('insn32.decode', extra_args: '--static-decode=decode_insn32'), +] + +gen64 = [ + decodetree.process('insn16.decode', extra_args: [dir / 'insn16-64.decode', '--static-decode=decode_insn16', '--insnwidth=16']), + decodetree.process('insn32.decode', extra_args: [dir / 'insn32-64.decode', '--static-decode=decode_insn32']), +] + +riscv_ss = ss.source_set() +riscv_ss.add(when: 'TARGET_RISCV32', if_true: gen32) +riscv_ss.add(when: 'TARGET_RISCV64', if_true: gen64) +riscv_ss.add(files( + 'cpu.c', + 'cpu_helper.c', + 'csr.c', + 'fpu_helper.c', + 'gdbstub.c', + 'op_helper.c', + 'vector_helper.c', + 'translate.c', +)) +riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c')) + +riscv_softmmu_ss = ss.source_set() +riscv_softmmu_ss.add(files( + 'pmp.c', + 'monitor.c', + 'machine.c' +)) + +target_arch += {'riscv': riscv_ss} +target_softmmu_arch += {'riscv': riscv_softmmu_ss} diff --git a/target/riscv/monitor.c b/target/riscv/monitor.c index b569f08387772770c4bd03cebb11bef2457cac7f..e51188f919b266907c0b5a3cdc73862c2da0ef4f 100644 --- a/target/riscv/monitor.c +++ b/target/riscv/monitor.c @@ -204,7 +204,7 @@ void hmp_info_mem(Monitor *mon, const QDict *qdict) { CPUArchState *env; - env = mon_get_cpu_env(); + env = mon_get_cpu_env(mon); if (!env) { monitor_printf(mon, "No CPU available\n"); return; diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index d7d9d212fc873b67071f7a7fbe9fc2d7115ef32d..d55def76cffdc983d4363ec0259dc25e99ec8ef6 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -29,7 +29,6 @@ void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env, uint32_t exception, uintptr_t pc) { CPUState *cs = env_cpu(env); - qemu_log_mask(CPU_LOG_INT, "%s: %d\n", __func__, exception); cs->exception_index = exception; cpu_loop_exit_restore(cs, pc); } @@ -79,7 +78,8 @@ target_ulong helper_csrrc(CPURISCVState *env, target_ulong src, target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) { - target_ulong prev_priv, prev_virt, mstatus; + uint64_t mstatus; + target_ulong prev_priv, prev_virt; if (!(env->priv >= PRV_S)) { riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); @@ -148,18 +148,14 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb) riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC()); } - target_ulong mstatus = env->mstatus; + uint64_t mstatus = env->mstatus; target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP); - target_ulong prev_virt = MSTATUS_MPV_ISSET(env); + target_ulong prev_virt = get_field(env->mstatus, MSTATUS_MPV); mstatus = set_field(mstatus, MSTATUS_MIE, get_field(mstatus, MSTATUS_MPIE)); mstatus = set_field(mstatus, MSTATUS_MPIE, 1); mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U); -#ifdef TARGET_RISCV32 - env->mstatush = set_field(env->mstatush, MSTATUS_MPV, 0); -#else mstatus = set_field(mstatus, MSTATUS_MPV, 0); -#endif env->mstatus = mstatus; riscv_cpu_set_mode(env, prev_priv); @@ -208,7 +204,7 @@ void helper_hyp_tlb_flush(CPURISCVState *env) { CPUState *cs = env_cpu(env); - if (env->priv == PRV_S && riscv_cpu_virt_enabled(env)){ + if (env->priv == PRV_S && riscv_cpu_virt_enabled(env)) { riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); } @@ -231,130 +227,18 @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env) helper_hyp_tlb_flush(env); } -target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address, - target_ulong attrs, target_ulong memop) +target_ulong helper_hyp_hlvx_hu(CPURISCVState *env, target_ulong address) { - if (env->priv == PRV_M || - (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || - (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && - get_field(env->hstatus, HSTATUS_HU))) { - target_ulong pte; - - riscv_cpu_set_two_stage_lookup(env, true); - - switch (memop) { - case MO_SB: - pte = cpu_ldsb_data_ra(env, address, GETPC()); - break; - case MO_UB: - pte = cpu_ldub_data_ra(env, address, GETPC()); - break; - case MO_TESW: - pte = cpu_ldsw_data_ra(env, address, GETPC()); - break; - case MO_TEUW: - pte = cpu_lduw_data_ra(env, address, GETPC()); - break; - case MO_TESL: - pte = cpu_ldl_data_ra(env, address, GETPC()); - break; - case MO_TEUL: - pte = cpu_ldl_data_ra(env, address, GETPC()); - break; - case MO_TEQ: - pte = cpu_ldq_data_ra(env, address, GETPC()); - break; - default: - g_assert_not_reached(); - } - - riscv_cpu_set_two_stage_lookup(env, false); - - return pte; - } - - if (riscv_cpu_virt_enabled(env)) { - riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); - } else { - riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); - } - return 0; -} - -void helper_hyp_store(CPURISCVState *env, target_ulong address, - target_ulong val, target_ulong attrs, target_ulong memop) -{ - if (env->priv == PRV_M || - (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || - (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && - get_field(env->hstatus, HSTATUS_HU))) { - riscv_cpu_set_two_stage_lookup(env, true); - - switch (memop) { - case MO_SB: - case MO_UB: - cpu_stb_data_ra(env, address, val, GETPC()); - break; - case MO_TESW: - case MO_TEUW: - cpu_stw_data_ra(env, address, val, GETPC()); - break; - case MO_TESL: - case MO_TEUL: - cpu_stl_data_ra(env, address, val, GETPC()); - break; - case MO_TEQ: - cpu_stq_data_ra(env, address, val, GETPC()); - break; - default: - g_assert_not_reached(); - } - - riscv_cpu_set_two_stage_lookup(env, false); + int mmu_idx = cpu_mmu_index(env, true) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; - return; - } - - if (riscv_cpu_virt_enabled(env)) { - riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); - } else { - riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); - } + return cpu_lduw_mmuidx_ra(env, address, mmu_idx, GETPC()); } -target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address, - target_ulong attrs, target_ulong memop) +target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong address) { - if (env->priv == PRV_M || - (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || - (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && - get_field(env->hstatus, HSTATUS_HU))) { - target_ulong pte; - - riscv_cpu_set_two_stage_lookup(env, true); - - switch (memop) { - case MO_TEUL: - pte = cpu_ldub_data_ra(env, address, GETPC()); - break; - case MO_TEUW: - pte = cpu_lduw_data_ra(env, address, GETPC()); - break; - default: - g_assert_not_reached(); - } - - riscv_cpu_set_two_stage_lookup(env, false); - - return pte; - } + int mmu_idx = cpu_mmu_index(env, true) | TB_FLAGS_PRIV_HYP_ACCESS_MASK; - if (riscv_cpu_virt_enabled(env)) { - riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); - } else { - riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); - } - return 0; + return cpu_ldl_mmuidx_ra(env, address, mmu_idx, GETPC()); } #endif /* !CONFIG_USER_ONLY */ diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c index 0e6b640fbd8711eafdfc24ff40634502a23d0bbf..2eda8e1e2f07e7e9a090bb040c886af6b5b907bd 100644 --- a/target/riscv/pmp.c +++ b/target/riscv/pmp.c @@ -136,18 +136,8 @@ static void pmp_decode_napot(target_ulong a, target_ulong *sa, target_ulong *ea) } } - -/* Convert cfg/addr reg values here into simple 'sa' --> start address and 'ea' - * end address values. - * This function is called relatively infrequently whereas the check that - * an address is within a pmp rule is called often, so optimise that one - */ -static void pmp_update_rule(CPURISCVState *env, uint32_t pmp_index) +void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index) { - int i; - - env->pmp_state.num_rules = 0; - uint8_t this_cfg = env->pmp_state.pmp[pmp_index].cfg_reg; target_ulong this_addr = env->pmp_state.pmp[pmp_index].addr_reg; target_ulong prev_addr = 0u; @@ -171,7 +161,7 @@ static void pmp_update_rule(CPURISCVState *env, uint32_t pmp_index) case PMP_AMATCH_NA4: sa = this_addr << 2; /* shift up from [xx:0] to [xx+2:2] */ - ea = (this_addr + 4u) - 1u; + ea = (sa + 4u) - 1u; break; case PMP_AMATCH_NAPOT: @@ -186,7 +176,13 @@ static void pmp_update_rule(CPURISCVState *env, uint32_t pmp_index) env->pmp_state.addr[pmp_index].sa = sa; env->pmp_state.addr[pmp_index].ea = ea; +} + +void pmp_update_rule_nums(CPURISCVState *env) +{ + int i; + env->pmp_state.num_rules = 0; for (i = 0; i < MAX_RISCV_PMPS; i++) { const uint8_t a_field = pmp_get_a_field(env->pmp_state.pmp[i].cfg_reg); @@ -196,6 +192,17 @@ static void pmp_update_rule(CPURISCVState *env, uint32_t pmp_index) } } +/* Convert cfg/addr reg values here into simple 'sa' --> start address and 'ea' + * end address values. + * This function is called relatively infrequently whereas the check that + * an address is within a pmp rule is called often, so optimise that one + */ +static void pmp_update_rule(CPURISCVState *env, uint32_t pmp_index) +{ + pmp_update_rule_addr(env, pmp_index); + pmp_update_rule_nums(env); +} + static int pmp_is_in_range(CPURISCVState *env, int pmp_index, target_ulong addr) { int result = 0; @@ -233,12 +240,16 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, return true; } - /* - * if size is unknown (0), assume that all bytes - * from addr to the end of the page will be accessed. - */ if (size == 0) { - pmp_size = -(addr | TARGET_PAGE_MASK); + if (riscv_feature(env, RISCV_FEATURE_MMU)) { + /* + * If size is unknown (0), assume that all bytes + * from addr to the end of the page will be accessed. + */ + pmp_size = -(addr | TARGET_PAGE_MASK); + } else { + pmp_size = sizeof(target_ulong); + } } else { pmp_size = size; } @@ -316,8 +327,7 @@ void pmpcfg_csr_write(CPURISCVState *env, uint32_t reg_index, for (i = 0; i < sizeof(target_ulong); i++) { cfg_val = (val >> 8 * i) & 0xff; - pmp_write_cfg(env, (reg_index * sizeof(target_ulong)) + i, - cfg_val); + pmp_write_cfg(env, (reg_index * 4) + i, cfg_val); } } @@ -332,7 +342,7 @@ target_ulong pmpcfg_csr_read(CPURISCVState *env, uint32_t reg_index) target_ulong val = 0; for (i = 0; i < sizeof(target_ulong); i++) { - val = pmp_read_cfg(env, (reg_index * sizeof(target_ulong)) + i); + val = pmp_read_cfg(env, (reg_index * 4) + i); cfg_val |= (val << (i * 8)); } trace_pmpcfg_csr_read(env->mhartid, reg_index, cfg_val); @@ -380,3 +390,55 @@ target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index) return val; } + +/* + * Calculate the TLB size if the start address or the end address of + * PMP entry is presented in thie TLB page. + */ +static target_ulong pmp_get_tlb_size(CPURISCVState *env, int pmp_index, + target_ulong tlb_sa, target_ulong tlb_ea) +{ + target_ulong pmp_sa = env->pmp_state.addr[pmp_index].sa; + target_ulong pmp_ea = env->pmp_state.addr[pmp_index].ea; + + if (pmp_sa >= tlb_sa && pmp_ea <= tlb_ea) { + return pmp_ea - pmp_sa + 1; + } + + if (pmp_sa >= tlb_sa && pmp_sa <= tlb_ea && pmp_ea >= tlb_ea) { + return tlb_ea - pmp_sa + 1; + } + + if (pmp_ea <= tlb_ea && pmp_ea >= tlb_sa && pmp_sa <= tlb_sa) { + return pmp_ea - tlb_sa + 1; + } + + return 0; +} + +/* + * Check is there a PMP entry which range covers this page. If so, + * try to find the minimum granularity for the TLB size. + */ +bool pmp_is_range_in_tlb(CPURISCVState *env, hwaddr tlb_sa, + target_ulong *tlb_size) +{ + int i; + target_ulong val; + target_ulong tlb_ea = (tlb_sa + TARGET_PAGE_SIZE - 1); + + for (i = 0; i < MAX_RISCV_PMPS; i++) { + val = pmp_get_tlb_size(env, i, tlb_sa, tlb_ea); + if (val) { + if (*tlb_size == 0 || *tlb_size > val) { + *tlb_size = val; + } + } + } + + if (*tlb_size != 0) { + return true; + } + + return false; +} diff --git a/target/riscv/pmp.h b/target/riscv/pmp.h index 8e19793132db8833ffeb670cba47ee0a6a4979b4..6c6b4c9befe80cdf033e3629bf0989a4193bb45b 100644 --- a/target/riscv/pmp.h +++ b/target/riscv/pmp.h @@ -60,5 +60,9 @@ void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index, target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index); bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, target_ulong size, pmp_priv_t priv, target_ulong mode); +bool pmp_is_range_in_tlb(CPURISCVState *env, hwaddr tlb_sa, + target_ulong *tlb_size); +void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index); +void pmp_update_rule_nums(CPURISCVState *env); #endif diff --git a/target/riscv/sbi_ecall_interface.h b/target/riscv/sbi_ecall_interface.h index d8f3cb3ba535d3ab79115541ec54b0a1e61f0ab0..fb1a3fa8f23f47be34560ce10d2aca13e7b420c9 100644 --- a/target/riscv/sbi_ecall_interface.h +++ b/target/riscv/sbi_ecall_interface.h @@ -4,7 +4,7 @@ * Copyright (c) 2019 Western Digital Corporation or its affiliates. * * Authors: - * Anup Patel */ #ifndef __SBI_ECALL_INTERFACE_H__ diff --git a/target/riscv/trace-events b/target/riscv/trace-events index 4b6c652ae9145de836182c3657fb56caba20ecf9..b7e371ee97a5b739786b62ffb5a48c34a5617ce5 100644 --- a/target/riscv/trace-events +++ b/target/riscv/trace-events @@ -1,4 +1,4 @@ -# target/riscv/cpu_helper.c +# cpu_helper.c riscv_trap(uint64_t hartid, bool async, uint64_t cause, uint64_t epc, uint64_t tval, const char *desc) "hart:%"PRId64", async:%d, cause:%"PRId64", epc:0x%"PRIx64", tval:0x%"PRIx64", desc=%s" # pmp.c diff --git a/target/riscv/trace.h b/target/riscv/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..03a89fcd9b91442a10a471a51373ddba99ecfc0d --- /dev/null +++ b/target/riscv/trace.h @@ -0,0 +1 @@ +#include "trace/trace-target_riscv.h" diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 1d973b62e9b50554bcb09b39ca34372d5bcbafa7..554d52a4be336bc9650e7b07d3a160674c760f87 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -32,7 +32,7 @@ #include "instmap.h" /* global register indices */ -static TCGv cpu_gpr[32], cpu_pc; +static TCGv cpu_gpr[32], cpu_pc, cpu_vl; static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */ static TCGv load_res; static TCGv load_val; @@ -56,6 +56,14 @@ typedef struct DisasContext { to reset this known value. */ int frm; bool ext_ifencei; + bool hlsx; + /* vector extension */ + bool vill; + uint8_t lmul; + uint8_t sew; + uint16_t vlen; + uint16_t mlen; + bool vl_eq_vlmax; } DisasContext; #ifdef TARGET_RISCV64 @@ -83,6 +91,35 @@ static inline bool has_ext(DisasContext *ctx, uint32_t ext) return ctx->misa & ext; } +/* + * RISC-V requires NaN-boxing of narrower width floating point values. + * This applies when a 32-bit value is assigned to a 64-bit FP register. + * For consistency and simplicity, we nanbox results even when the RVD + * extension is not present. + */ +static void gen_nanbox_s(TCGv_i64 out, TCGv_i64 in) +{ + tcg_gen_ori_i64(out, in, MAKE_64BIT_MASK(32, 32)); +} + +/* + * A narrow n-bit operation, where n < FLEN, checks that input operands + * are correctly Nan-boxed, i.e., all upper FLEN - n bits are 1. + * If so, the least-significant bits of the input are used, otherwise the + * input value is treated as an n-bit canonical NaN (v2.2 section 9.2). + * + * Here, the result is always nan-boxed, even the canonical nan. + */ +static void gen_check_nanbox_s(TCGv_i64 out, TCGv_i64 in) +{ + TCGv_i64 t_max = tcg_const_i64(0xffffffff00000000ull); + TCGv_i64 t_nan = tcg_const_i64(0xffffffff7fc00000ull); + + tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan); + tcg_temp_free_i64(t_max); + tcg_temp_free_i64(t_nan); +} + static void generate_exception(DisasContext *ctx, int excp) { tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); @@ -542,6 +579,11 @@ static void decode_RV32_64C(DisasContext *ctx, uint16_t opcode) } } +static int ex_plus_1(DisasContext *ctx, int nf) +{ + return nf + 1; +} + #define EX_SH(amount) \ static int ex_shift_##amount(DisasContext *ctx, int imm) \ { \ @@ -571,7 +613,7 @@ static int ex_rvc_shifti(DisasContext *ctx, int imm) } /* Include the auto-generated decoder for 32 bit insn */ -#include "decode_insn32.inc.c" +#include "decode-insn32.c.inc" static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, void (*func)(TCGv, TCGv, target_long)) @@ -706,16 +748,17 @@ static bool gen_shift(DisasContext *ctx, arg_r *a, } /* Include insn module translation function */ -#include "insn_trans/trans_rvi.inc.c" -#include "insn_trans/trans_rvm.inc.c" -#include "insn_trans/trans_rva.inc.c" -#include "insn_trans/trans_rvf.inc.c" -#include "insn_trans/trans_rvd.inc.c" -#include "insn_trans/trans_rvh.inc.c" -#include "insn_trans/trans_privileged.inc.c" +#include "insn_trans/trans_rvi.c.inc" +#include "insn_trans/trans_rvm.c.inc" +#include "insn_trans/trans_rva.c.inc" +#include "insn_trans/trans_rvf.c.inc" +#include "insn_trans/trans_rvd.c.inc" +#include "insn_trans/trans_rvh.c.inc" +#include "insn_trans/trans_rvv.c.inc" +#include "insn_trans/trans_privileged.c.inc" /* Include the auto-generated decoder for 16 bit insn */ -#include "decode_insn16.inc.c" +#include "decode-insn16.c.inc" static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode) { @@ -746,10 +789,11 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) DisasContext *ctx = container_of(dcbase, DisasContext, base); CPURISCVState *env = cs->env_ptr; RISCVCPU *cpu = RISCV_CPU(cs); + uint32_t tb_flags = ctx->base.tb->flags; ctx->pc_succ_insn = ctx->base.pc_first; - ctx->mem_idx = ctx->base.tb->flags & TB_FLAGS_MMU_MASK; - ctx->mstatus_fs = ctx->base.tb->flags & TB_FLAGS_MSTATUS_FS; + ctx->mem_idx = tb_flags & TB_FLAGS_MMU_MASK; + ctx->mstatus_fs = tb_flags & TB_FLAGS_MSTATUS_FS; ctx->priv_ver = env->priv_ver; #if !defined(CONFIG_USER_ONLY) if (riscv_has_ext(env, RVH)) { @@ -763,6 +807,13 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->misa = env->misa; ctx->frm = -1; /* unknown rounding mode */ ctx->ext_ifencei = cpu->cfg.ext_ifencei; + ctx->vlen = cpu->cfg.vlen; + ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX); + ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL); + ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW); + ctx->lmul = FIELD_EX32(tb_flags, TB_FLAGS, LMUL); + ctx->mlen = 1 << (ctx->sew + 3 - ctx->lmul); + ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX); } static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu) @@ -877,6 +928,7 @@ void riscv_translate_init(void) } cpu_pc = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, pc), "pc"); + cpu_vl = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, vl), "vl"); load_res = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, load_res), "load_res"); load_val = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, load_val), diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c new file mode 100644 index 0000000000000000000000000000000000000000..a156573d28122d58672e516f4c95b08fcc46deb4 --- /dev/null +++ b/target/riscv/vector_helper.c @@ -0,0 +1,4874 @@ +/* + * RISC-V Vector Extension Helpers for QEMU. + * + * Copyright (c) 2020 T-Head Semiconductor Co., Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/memop.h" +#include "exec/exec-all.h" +#include "exec/helper-proto.h" +#include "fpu/softfloat.h" +#include "tcg/tcg-gvec-desc.h" +#include "internals.h" +#include + +target_ulong HELPER(vsetvl)(CPURISCVState *env, target_ulong s1, + target_ulong s2) +{ + int vlmax, vl; + RISCVCPU *cpu = env_archcpu(env); + uint16_t sew = 8 << FIELD_EX64(s2, VTYPE, VSEW); + uint8_t ediv = FIELD_EX64(s2, VTYPE, VEDIV); + bool vill = FIELD_EX64(s2, VTYPE, VILL); + target_ulong reserved = FIELD_EX64(s2, VTYPE, RESERVED); + + if ((sew > cpu->cfg.elen) || vill || (ediv != 0) || (reserved != 0)) { + /* only set vill bit. */ + env->vtype = FIELD_DP64(0, VTYPE, VILL, 1); + env->vl = 0; + env->vstart = 0; + return 0; + } + + vlmax = vext_get_vlmax(cpu, s2); + if (s1 <= vlmax) { + vl = s1; + } else { + vl = vlmax; + } + env->vl = vl; + env->vtype = s2; + env->vstart = 0; + return vl; +} + +/* + * Note that vector data is stored in host-endian 64-bit chunks, + * so addressing units smaller than that needs a host-endian fixup. + */ +#ifdef HOST_WORDS_BIGENDIAN +#define H1(x) ((x) ^ 7) +#define H1_2(x) ((x) ^ 6) +#define H1_4(x) ((x) ^ 4) +#define H2(x) ((x) ^ 3) +#define H4(x) ((x) ^ 1) +#define H8(x) ((x)) +#else +#define H1(x) (x) +#define H1_2(x) (x) +#define H1_4(x) (x) +#define H2(x) (x) +#define H4(x) (x) +#define H8(x) (x) +#endif + +static inline uint32_t vext_nf(uint32_t desc) +{ + return FIELD_EX32(simd_data(desc), VDATA, NF); +} + +static inline uint32_t vext_mlen(uint32_t desc) +{ + return FIELD_EX32(simd_data(desc), VDATA, MLEN); +} + +static inline uint32_t vext_vm(uint32_t desc) +{ + return FIELD_EX32(simd_data(desc), VDATA, VM); +} + +static inline uint32_t vext_lmul(uint32_t desc) +{ + return FIELD_EX32(simd_data(desc), VDATA, LMUL); +} + +static uint32_t vext_wd(uint32_t desc) +{ + return (simd_data(desc) >> 11) & 0x1; +} + +/* + * Get vector group length in bytes. Its range is [64, 2048]. + * + * As simd_desc support at most 256, the max vlen is 512 bits. + * So vlen in bytes is encoded as maxsz. + */ +static inline uint32_t vext_maxsz(uint32_t desc) +{ + return simd_maxsz(desc) << vext_lmul(desc); +} + +/* + * This function checks watchpoint before real load operation. + * + * In softmmu mode, the TLB API probe_access is enough for watchpoint check. + * In user mode, there is no watchpoint support now. + * + * It will trigger an exception if there is no mapping in TLB + * and page table walk can't fill the TLB entry. Then the guest + * software can return here after process the exception or never return. + */ +static void probe_pages(CPURISCVState *env, target_ulong addr, + target_ulong len, uintptr_t ra, + MMUAccessType access_type) +{ + target_ulong pagelen = -(addr | TARGET_PAGE_MASK); + target_ulong curlen = MIN(pagelen, len); + + probe_access(env, addr, curlen, access_type, + cpu_mmu_index(env, false), ra); + if (len > curlen) { + addr += curlen; + curlen = len - curlen; + probe_access(env, addr, curlen, access_type, + cpu_mmu_index(env, false), ra); + } +} + +#ifdef HOST_WORDS_BIGENDIAN +static void vext_clear(void *tail, uint32_t cnt, uint32_t tot) +{ + /* + * Split the remaining range to two parts. + * The first part is in the last uint64_t unit. + * The second part start from the next uint64_t unit. + */ + int part1 = 0, part2 = tot - cnt; + if (cnt % 8) { + part1 = 8 - (cnt % 8); + part2 = tot - cnt - part1; + memset(QEMU_ALIGN_PTR_DOWN(tail, 8), 0, part1); + memset(QEMU_ALIGN_PTR_UP(tail, 8), 0, part2); + } else { + memset(tail, 0, part2); + } +} +#else +static void vext_clear(void *tail, uint32_t cnt, uint32_t tot) +{ + memset(tail, 0, tot - cnt); +} +#endif + +static void clearb(void *vd, uint32_t idx, uint32_t cnt, uint32_t tot) +{ + int8_t *cur = ((int8_t *)vd + H1(idx)); + vext_clear(cur, cnt, tot); +} + +static void clearh(void *vd, uint32_t idx, uint32_t cnt, uint32_t tot) +{ + int16_t *cur = ((int16_t *)vd + H2(idx)); + vext_clear(cur, cnt, tot); +} + +static void clearl(void *vd, uint32_t idx, uint32_t cnt, uint32_t tot) +{ + int32_t *cur = ((int32_t *)vd + H4(idx)); + vext_clear(cur, cnt, tot); +} + +static void clearq(void *vd, uint32_t idx, uint32_t cnt, uint32_t tot) +{ + int64_t *cur = (int64_t *)vd + idx; + vext_clear(cur, cnt, tot); +} + +static inline void vext_set_elem_mask(void *v0, int mlen, int index, + uint8_t value) +{ + int idx = (index * mlen) / 64; + int pos = (index * mlen) % 64; + uint64_t old = ((uint64_t *)v0)[idx]; + ((uint64_t *)v0)[idx] = deposit64(old, pos, mlen, value); +} + +static inline int vext_elem_mask(void *v0, int mlen, int index) +{ + int idx = (index * mlen) / 64; + int pos = (index * mlen) % 64; + return (((uint64_t *)v0)[idx] >> pos) & 1; +} + +/* elements operations for load and store */ +typedef void vext_ldst_elem_fn(CPURISCVState *env, target_ulong addr, + uint32_t idx, void *vd, uintptr_t retaddr); +typedef void clear_fn(void *vd, uint32_t idx, uint32_t cnt, uint32_t tot); + +#define GEN_VEXT_LD_ELEM(NAME, MTYPE, ETYPE, H, LDSUF) \ +static void NAME(CPURISCVState *env, abi_ptr addr, \ + uint32_t idx, void *vd, uintptr_t retaddr)\ +{ \ + MTYPE data; \ + ETYPE *cur = ((ETYPE *)vd + H(idx)); \ + data = cpu_##LDSUF##_data_ra(env, addr, retaddr); \ + *cur = data; \ +} \ + +GEN_VEXT_LD_ELEM(ldb_b, int8_t, int8_t, H1, ldsb) +GEN_VEXT_LD_ELEM(ldb_h, int8_t, int16_t, H2, ldsb) +GEN_VEXT_LD_ELEM(ldb_w, int8_t, int32_t, H4, ldsb) +GEN_VEXT_LD_ELEM(ldb_d, int8_t, int64_t, H8, ldsb) +GEN_VEXT_LD_ELEM(ldh_h, int16_t, int16_t, H2, ldsw) +GEN_VEXT_LD_ELEM(ldh_w, int16_t, int32_t, H4, ldsw) +GEN_VEXT_LD_ELEM(ldh_d, int16_t, int64_t, H8, ldsw) +GEN_VEXT_LD_ELEM(ldw_w, int32_t, int32_t, H4, ldl) +GEN_VEXT_LD_ELEM(ldw_d, int32_t, int64_t, H8, ldl) +GEN_VEXT_LD_ELEM(lde_b, int8_t, int8_t, H1, ldsb) +GEN_VEXT_LD_ELEM(lde_h, int16_t, int16_t, H2, ldsw) +GEN_VEXT_LD_ELEM(lde_w, int32_t, int32_t, H4, ldl) +GEN_VEXT_LD_ELEM(lde_d, int64_t, int64_t, H8, ldq) +GEN_VEXT_LD_ELEM(ldbu_b, uint8_t, uint8_t, H1, ldub) +GEN_VEXT_LD_ELEM(ldbu_h, uint8_t, uint16_t, H2, ldub) +GEN_VEXT_LD_ELEM(ldbu_w, uint8_t, uint32_t, H4, ldub) +GEN_VEXT_LD_ELEM(ldbu_d, uint8_t, uint64_t, H8, ldub) +GEN_VEXT_LD_ELEM(ldhu_h, uint16_t, uint16_t, H2, lduw) +GEN_VEXT_LD_ELEM(ldhu_w, uint16_t, uint32_t, H4, lduw) +GEN_VEXT_LD_ELEM(ldhu_d, uint16_t, uint64_t, H8, lduw) +GEN_VEXT_LD_ELEM(ldwu_w, uint32_t, uint32_t, H4, ldl) +GEN_VEXT_LD_ELEM(ldwu_d, uint32_t, uint64_t, H8, ldl) + +#define GEN_VEXT_ST_ELEM(NAME, ETYPE, H, STSUF) \ +static void NAME(CPURISCVState *env, abi_ptr addr, \ + uint32_t idx, void *vd, uintptr_t retaddr)\ +{ \ + ETYPE data = *((ETYPE *)vd + H(idx)); \ + cpu_##STSUF##_data_ra(env, addr, data, retaddr); \ +} + +GEN_VEXT_ST_ELEM(stb_b, int8_t, H1, stb) +GEN_VEXT_ST_ELEM(stb_h, int16_t, H2, stb) +GEN_VEXT_ST_ELEM(stb_w, int32_t, H4, stb) +GEN_VEXT_ST_ELEM(stb_d, int64_t, H8, stb) +GEN_VEXT_ST_ELEM(sth_h, int16_t, H2, stw) +GEN_VEXT_ST_ELEM(sth_w, int32_t, H4, stw) +GEN_VEXT_ST_ELEM(sth_d, int64_t, H8, stw) +GEN_VEXT_ST_ELEM(stw_w, int32_t, H4, stl) +GEN_VEXT_ST_ELEM(stw_d, int64_t, H8, stl) +GEN_VEXT_ST_ELEM(ste_b, int8_t, H1, stb) +GEN_VEXT_ST_ELEM(ste_h, int16_t, H2, stw) +GEN_VEXT_ST_ELEM(ste_w, int32_t, H4, stl) +GEN_VEXT_ST_ELEM(ste_d, int64_t, H8, stq) + +/* + *** stride: access vector element from strided memory + */ +static void +vext_ldst_stride(void *vd, void *v0, target_ulong base, + target_ulong stride, CPURISCVState *env, + uint32_t desc, uint32_t vm, + vext_ldst_elem_fn *ldst_elem, clear_fn *clear_elem, + uint32_t esz, uint32_t msz, uintptr_t ra, + MMUAccessType access_type) +{ + uint32_t i, k; + uint32_t nf = vext_nf(desc); + uint32_t mlen = vext_mlen(desc); + uint32_t vlmax = vext_maxsz(desc) / esz; + + /* probe every access*/ + for (i = 0; i < env->vl; i++) { + if (!vm && !vext_elem_mask(v0, mlen, i)) { + continue; + } + probe_pages(env, base + stride * i, nf * msz, ra, access_type); + } + /* do real access */ + for (i = 0; i < env->vl; i++) { + k = 0; + if (!vm && !vext_elem_mask(v0, mlen, i)) { + continue; + } + while (k < nf) { + target_ulong addr = base + stride * i + k * msz; + ldst_elem(env, addr, i + k * vlmax, vd, ra); + k++; + } + } + /* clear tail elements */ + if (clear_elem) { + for (k = 0; k < nf; k++) { + clear_elem(vd, env->vl + k * vlmax, env->vl * esz, vlmax * esz); + } + } +} + +#define GEN_VEXT_LD_STRIDE(NAME, MTYPE, ETYPE, LOAD_FN, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void * v0, target_ulong base, \ + target_ulong stride, CPURISCVState *env, \ + uint32_t desc) \ +{ \ + uint32_t vm = vext_vm(desc); \ + vext_ldst_stride(vd, v0, base, stride, env, desc, vm, LOAD_FN, \ + CLEAR_FN, sizeof(ETYPE), sizeof(MTYPE), \ + GETPC(), MMU_DATA_LOAD); \ +} + +GEN_VEXT_LD_STRIDE(vlsb_v_b, int8_t, int8_t, ldb_b, clearb) +GEN_VEXT_LD_STRIDE(vlsb_v_h, int8_t, int16_t, ldb_h, clearh) +GEN_VEXT_LD_STRIDE(vlsb_v_w, int8_t, int32_t, ldb_w, clearl) +GEN_VEXT_LD_STRIDE(vlsb_v_d, int8_t, int64_t, ldb_d, clearq) +GEN_VEXT_LD_STRIDE(vlsh_v_h, int16_t, int16_t, ldh_h, clearh) +GEN_VEXT_LD_STRIDE(vlsh_v_w, int16_t, int32_t, ldh_w, clearl) +GEN_VEXT_LD_STRIDE(vlsh_v_d, int16_t, int64_t, ldh_d, clearq) +GEN_VEXT_LD_STRIDE(vlsw_v_w, int32_t, int32_t, ldw_w, clearl) +GEN_VEXT_LD_STRIDE(vlsw_v_d, int32_t, int64_t, ldw_d, clearq) +GEN_VEXT_LD_STRIDE(vlse_v_b, int8_t, int8_t, lde_b, clearb) +GEN_VEXT_LD_STRIDE(vlse_v_h, int16_t, int16_t, lde_h, clearh) +GEN_VEXT_LD_STRIDE(vlse_v_w, int32_t, int32_t, lde_w, clearl) +GEN_VEXT_LD_STRIDE(vlse_v_d, int64_t, int64_t, lde_d, clearq) +GEN_VEXT_LD_STRIDE(vlsbu_v_b, uint8_t, uint8_t, ldbu_b, clearb) +GEN_VEXT_LD_STRIDE(vlsbu_v_h, uint8_t, uint16_t, ldbu_h, clearh) +GEN_VEXT_LD_STRIDE(vlsbu_v_w, uint8_t, uint32_t, ldbu_w, clearl) +GEN_VEXT_LD_STRIDE(vlsbu_v_d, uint8_t, uint64_t, ldbu_d, clearq) +GEN_VEXT_LD_STRIDE(vlshu_v_h, uint16_t, uint16_t, ldhu_h, clearh) +GEN_VEXT_LD_STRIDE(vlshu_v_w, uint16_t, uint32_t, ldhu_w, clearl) +GEN_VEXT_LD_STRIDE(vlshu_v_d, uint16_t, uint64_t, ldhu_d, clearq) +GEN_VEXT_LD_STRIDE(vlswu_v_w, uint32_t, uint32_t, ldwu_w, clearl) +GEN_VEXT_LD_STRIDE(vlswu_v_d, uint32_t, uint64_t, ldwu_d, clearq) + +#define GEN_VEXT_ST_STRIDE(NAME, MTYPE, ETYPE, STORE_FN) \ +void HELPER(NAME)(void *vd, void *v0, target_ulong base, \ + target_ulong stride, CPURISCVState *env, \ + uint32_t desc) \ +{ \ + uint32_t vm = vext_vm(desc); \ + vext_ldst_stride(vd, v0, base, stride, env, desc, vm, STORE_FN, \ + NULL, sizeof(ETYPE), sizeof(MTYPE), \ + GETPC(), MMU_DATA_STORE); \ +} + +GEN_VEXT_ST_STRIDE(vssb_v_b, int8_t, int8_t, stb_b) +GEN_VEXT_ST_STRIDE(vssb_v_h, int8_t, int16_t, stb_h) +GEN_VEXT_ST_STRIDE(vssb_v_w, int8_t, int32_t, stb_w) +GEN_VEXT_ST_STRIDE(vssb_v_d, int8_t, int64_t, stb_d) +GEN_VEXT_ST_STRIDE(vssh_v_h, int16_t, int16_t, sth_h) +GEN_VEXT_ST_STRIDE(vssh_v_w, int16_t, int32_t, sth_w) +GEN_VEXT_ST_STRIDE(vssh_v_d, int16_t, int64_t, sth_d) +GEN_VEXT_ST_STRIDE(vssw_v_w, int32_t, int32_t, stw_w) +GEN_VEXT_ST_STRIDE(vssw_v_d, int32_t, int64_t, stw_d) +GEN_VEXT_ST_STRIDE(vsse_v_b, int8_t, int8_t, ste_b) +GEN_VEXT_ST_STRIDE(vsse_v_h, int16_t, int16_t, ste_h) +GEN_VEXT_ST_STRIDE(vsse_v_w, int32_t, int32_t, ste_w) +GEN_VEXT_ST_STRIDE(vsse_v_d, int64_t, int64_t, ste_d) + +/* + *** unit-stride: access elements stored contiguously in memory + */ + +/* unmasked unit-stride load and store operation*/ +static void +vext_ldst_us(void *vd, target_ulong base, CPURISCVState *env, uint32_t desc, + vext_ldst_elem_fn *ldst_elem, clear_fn *clear_elem, + uint32_t esz, uint32_t msz, uintptr_t ra, + MMUAccessType access_type) +{ + uint32_t i, k; + uint32_t nf = vext_nf(desc); + uint32_t vlmax = vext_maxsz(desc) / esz; + + /* probe every access */ + probe_pages(env, base, env->vl * nf * msz, ra, access_type); + /* load bytes from guest memory */ + for (i = 0; i < env->vl; i++) { + k = 0; + while (k < nf) { + target_ulong addr = base + (i * nf + k) * msz; + ldst_elem(env, addr, i + k * vlmax, vd, ra); + k++; + } + } + /* clear tail elements */ + if (clear_elem) { + for (k = 0; k < nf; k++) { + clear_elem(vd, env->vl + k * vlmax, env->vl * esz, vlmax * esz); + } + } +} + +/* + * masked unit-stride load and store operation will be a special case of stride, + * stride = NF * sizeof (MTYPE) + */ + +#define GEN_VEXT_LD_US(NAME, MTYPE, ETYPE, LOAD_FN, CLEAR_FN) \ +void HELPER(NAME##_mask)(void *vd, void *v0, target_ulong base, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t stride = vext_nf(desc) * sizeof(MTYPE); \ + vext_ldst_stride(vd, v0, base, stride, env, desc, false, LOAD_FN, \ + CLEAR_FN, sizeof(ETYPE), sizeof(MTYPE), \ + GETPC(), MMU_DATA_LOAD); \ +} \ + \ +void HELPER(NAME)(void *vd, void *v0, target_ulong base, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + vext_ldst_us(vd, base, env, desc, LOAD_FN, CLEAR_FN, \ + sizeof(ETYPE), sizeof(MTYPE), GETPC(), MMU_DATA_LOAD); \ +} + +GEN_VEXT_LD_US(vlb_v_b, int8_t, int8_t, ldb_b, clearb) +GEN_VEXT_LD_US(vlb_v_h, int8_t, int16_t, ldb_h, clearh) +GEN_VEXT_LD_US(vlb_v_w, int8_t, int32_t, ldb_w, clearl) +GEN_VEXT_LD_US(vlb_v_d, int8_t, int64_t, ldb_d, clearq) +GEN_VEXT_LD_US(vlh_v_h, int16_t, int16_t, ldh_h, clearh) +GEN_VEXT_LD_US(vlh_v_w, int16_t, int32_t, ldh_w, clearl) +GEN_VEXT_LD_US(vlh_v_d, int16_t, int64_t, ldh_d, clearq) +GEN_VEXT_LD_US(vlw_v_w, int32_t, int32_t, ldw_w, clearl) +GEN_VEXT_LD_US(vlw_v_d, int32_t, int64_t, ldw_d, clearq) +GEN_VEXT_LD_US(vle_v_b, int8_t, int8_t, lde_b, clearb) +GEN_VEXT_LD_US(vle_v_h, int16_t, int16_t, lde_h, clearh) +GEN_VEXT_LD_US(vle_v_w, int32_t, int32_t, lde_w, clearl) +GEN_VEXT_LD_US(vle_v_d, int64_t, int64_t, lde_d, clearq) +GEN_VEXT_LD_US(vlbu_v_b, uint8_t, uint8_t, ldbu_b, clearb) +GEN_VEXT_LD_US(vlbu_v_h, uint8_t, uint16_t, ldbu_h, clearh) +GEN_VEXT_LD_US(vlbu_v_w, uint8_t, uint32_t, ldbu_w, clearl) +GEN_VEXT_LD_US(vlbu_v_d, uint8_t, uint64_t, ldbu_d, clearq) +GEN_VEXT_LD_US(vlhu_v_h, uint16_t, uint16_t, ldhu_h, clearh) +GEN_VEXT_LD_US(vlhu_v_w, uint16_t, uint32_t, ldhu_w, clearl) +GEN_VEXT_LD_US(vlhu_v_d, uint16_t, uint64_t, ldhu_d, clearq) +GEN_VEXT_LD_US(vlwu_v_w, uint32_t, uint32_t, ldwu_w, clearl) +GEN_VEXT_LD_US(vlwu_v_d, uint32_t, uint64_t, ldwu_d, clearq) + +#define GEN_VEXT_ST_US(NAME, MTYPE, ETYPE, STORE_FN) \ +void HELPER(NAME##_mask)(void *vd, void *v0, target_ulong base, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t stride = vext_nf(desc) * sizeof(MTYPE); \ + vext_ldst_stride(vd, v0, base, stride, env, desc, false, STORE_FN, \ + NULL, sizeof(ETYPE), sizeof(MTYPE), \ + GETPC(), MMU_DATA_STORE); \ +} \ + \ +void HELPER(NAME)(void *vd, void *v0, target_ulong base, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + vext_ldst_us(vd, base, env, desc, STORE_FN, NULL, \ + sizeof(ETYPE), sizeof(MTYPE), GETPC(), MMU_DATA_STORE);\ +} + +GEN_VEXT_ST_US(vsb_v_b, int8_t, int8_t , stb_b) +GEN_VEXT_ST_US(vsb_v_h, int8_t, int16_t, stb_h) +GEN_VEXT_ST_US(vsb_v_w, int8_t, int32_t, stb_w) +GEN_VEXT_ST_US(vsb_v_d, int8_t, int64_t, stb_d) +GEN_VEXT_ST_US(vsh_v_h, int16_t, int16_t, sth_h) +GEN_VEXT_ST_US(vsh_v_w, int16_t, int32_t, sth_w) +GEN_VEXT_ST_US(vsh_v_d, int16_t, int64_t, sth_d) +GEN_VEXT_ST_US(vsw_v_w, int32_t, int32_t, stw_w) +GEN_VEXT_ST_US(vsw_v_d, int32_t, int64_t, stw_d) +GEN_VEXT_ST_US(vse_v_b, int8_t, int8_t , ste_b) +GEN_VEXT_ST_US(vse_v_h, int16_t, int16_t, ste_h) +GEN_VEXT_ST_US(vse_v_w, int32_t, int32_t, ste_w) +GEN_VEXT_ST_US(vse_v_d, int64_t, int64_t, ste_d) + +/* + *** index: access vector element from indexed memory + */ +typedef target_ulong vext_get_index_addr(target_ulong base, + uint32_t idx, void *vs2); + +#define GEN_VEXT_GET_INDEX_ADDR(NAME, ETYPE, H) \ +static target_ulong NAME(target_ulong base, \ + uint32_t idx, void *vs2) \ +{ \ + return (base + *((ETYPE *)vs2 + H(idx))); \ +} + +GEN_VEXT_GET_INDEX_ADDR(idx_b, int8_t, H1) +GEN_VEXT_GET_INDEX_ADDR(idx_h, int16_t, H2) +GEN_VEXT_GET_INDEX_ADDR(idx_w, int32_t, H4) +GEN_VEXT_GET_INDEX_ADDR(idx_d, int64_t, H8) + +static inline void +vext_ldst_index(void *vd, void *v0, target_ulong base, + void *vs2, CPURISCVState *env, uint32_t desc, + vext_get_index_addr get_index_addr, + vext_ldst_elem_fn *ldst_elem, + clear_fn *clear_elem, + uint32_t esz, uint32_t msz, uintptr_t ra, + MMUAccessType access_type) +{ + uint32_t i, k; + uint32_t nf = vext_nf(desc); + uint32_t vm = vext_vm(desc); + uint32_t mlen = vext_mlen(desc); + uint32_t vlmax = vext_maxsz(desc) / esz; + + /* probe every access*/ + for (i = 0; i < env->vl; i++) { + if (!vm && !vext_elem_mask(v0, mlen, i)) { + continue; + } + probe_pages(env, get_index_addr(base, i, vs2), nf * msz, ra, + access_type); + } + /* load bytes from guest memory */ + for (i = 0; i < env->vl; i++) { + k = 0; + if (!vm && !vext_elem_mask(v0, mlen, i)) { + continue; + } + while (k < nf) { + abi_ptr addr = get_index_addr(base, i, vs2) + k * msz; + ldst_elem(env, addr, i + k * vlmax, vd, ra); + k++; + } + } + /* clear tail elements */ + if (clear_elem) { + for (k = 0; k < nf; k++) { + clear_elem(vd, env->vl + k * vlmax, env->vl * esz, vlmax * esz); + } + } +} + +#define GEN_VEXT_LD_INDEX(NAME, MTYPE, ETYPE, INDEX_FN, LOAD_FN, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, target_ulong base, \ + void *vs2, CPURISCVState *env, uint32_t desc) \ +{ \ + vext_ldst_index(vd, v0, base, vs2, env, desc, INDEX_FN, \ + LOAD_FN, CLEAR_FN, sizeof(ETYPE), sizeof(MTYPE), \ + GETPC(), MMU_DATA_LOAD); \ +} + +GEN_VEXT_LD_INDEX(vlxb_v_b, int8_t, int8_t, idx_b, ldb_b, clearb) +GEN_VEXT_LD_INDEX(vlxb_v_h, int8_t, int16_t, idx_h, ldb_h, clearh) +GEN_VEXT_LD_INDEX(vlxb_v_w, int8_t, int32_t, idx_w, ldb_w, clearl) +GEN_VEXT_LD_INDEX(vlxb_v_d, int8_t, int64_t, idx_d, ldb_d, clearq) +GEN_VEXT_LD_INDEX(vlxh_v_h, int16_t, int16_t, idx_h, ldh_h, clearh) +GEN_VEXT_LD_INDEX(vlxh_v_w, int16_t, int32_t, idx_w, ldh_w, clearl) +GEN_VEXT_LD_INDEX(vlxh_v_d, int16_t, int64_t, idx_d, ldh_d, clearq) +GEN_VEXT_LD_INDEX(vlxw_v_w, int32_t, int32_t, idx_w, ldw_w, clearl) +GEN_VEXT_LD_INDEX(vlxw_v_d, int32_t, int64_t, idx_d, ldw_d, clearq) +GEN_VEXT_LD_INDEX(vlxe_v_b, int8_t, int8_t, idx_b, lde_b, clearb) +GEN_VEXT_LD_INDEX(vlxe_v_h, int16_t, int16_t, idx_h, lde_h, clearh) +GEN_VEXT_LD_INDEX(vlxe_v_w, int32_t, int32_t, idx_w, lde_w, clearl) +GEN_VEXT_LD_INDEX(vlxe_v_d, int64_t, int64_t, idx_d, lde_d, clearq) +GEN_VEXT_LD_INDEX(vlxbu_v_b, uint8_t, uint8_t, idx_b, ldbu_b, clearb) +GEN_VEXT_LD_INDEX(vlxbu_v_h, uint8_t, uint16_t, idx_h, ldbu_h, clearh) +GEN_VEXT_LD_INDEX(vlxbu_v_w, uint8_t, uint32_t, idx_w, ldbu_w, clearl) +GEN_VEXT_LD_INDEX(vlxbu_v_d, uint8_t, uint64_t, idx_d, ldbu_d, clearq) +GEN_VEXT_LD_INDEX(vlxhu_v_h, uint16_t, uint16_t, idx_h, ldhu_h, clearh) +GEN_VEXT_LD_INDEX(vlxhu_v_w, uint16_t, uint32_t, idx_w, ldhu_w, clearl) +GEN_VEXT_LD_INDEX(vlxhu_v_d, uint16_t, uint64_t, idx_d, ldhu_d, clearq) +GEN_VEXT_LD_INDEX(vlxwu_v_w, uint32_t, uint32_t, idx_w, ldwu_w, clearl) +GEN_VEXT_LD_INDEX(vlxwu_v_d, uint32_t, uint64_t, idx_d, ldwu_d, clearq) + +#define GEN_VEXT_ST_INDEX(NAME, MTYPE, ETYPE, INDEX_FN, STORE_FN)\ +void HELPER(NAME)(void *vd, void *v0, target_ulong base, \ + void *vs2, CPURISCVState *env, uint32_t desc) \ +{ \ + vext_ldst_index(vd, v0, base, vs2, env, desc, INDEX_FN, \ + STORE_FN, NULL, sizeof(ETYPE), sizeof(MTYPE),\ + GETPC(), MMU_DATA_STORE); \ +} + +GEN_VEXT_ST_INDEX(vsxb_v_b, int8_t, int8_t, idx_b, stb_b) +GEN_VEXT_ST_INDEX(vsxb_v_h, int8_t, int16_t, idx_h, stb_h) +GEN_VEXT_ST_INDEX(vsxb_v_w, int8_t, int32_t, idx_w, stb_w) +GEN_VEXT_ST_INDEX(vsxb_v_d, int8_t, int64_t, idx_d, stb_d) +GEN_VEXT_ST_INDEX(vsxh_v_h, int16_t, int16_t, idx_h, sth_h) +GEN_VEXT_ST_INDEX(vsxh_v_w, int16_t, int32_t, idx_w, sth_w) +GEN_VEXT_ST_INDEX(vsxh_v_d, int16_t, int64_t, idx_d, sth_d) +GEN_VEXT_ST_INDEX(vsxw_v_w, int32_t, int32_t, idx_w, stw_w) +GEN_VEXT_ST_INDEX(vsxw_v_d, int32_t, int64_t, idx_d, stw_d) +GEN_VEXT_ST_INDEX(vsxe_v_b, int8_t, int8_t, idx_b, ste_b) +GEN_VEXT_ST_INDEX(vsxe_v_h, int16_t, int16_t, idx_h, ste_h) +GEN_VEXT_ST_INDEX(vsxe_v_w, int32_t, int32_t, idx_w, ste_w) +GEN_VEXT_ST_INDEX(vsxe_v_d, int64_t, int64_t, idx_d, ste_d) + +/* + *** unit-stride fault-only-fisrt load instructions + */ +static inline void +vext_ldff(void *vd, void *v0, target_ulong base, + CPURISCVState *env, uint32_t desc, + vext_ldst_elem_fn *ldst_elem, + clear_fn *clear_elem, + uint32_t esz, uint32_t msz, uintptr_t ra) +{ + void *host; + uint32_t i, k, vl = 0; + uint32_t mlen = vext_mlen(desc); + uint32_t nf = vext_nf(desc); + uint32_t vm = vext_vm(desc); + uint32_t vlmax = vext_maxsz(desc) / esz; + target_ulong addr, offset, remain; + + /* probe every access*/ + for (i = 0; i < env->vl; i++) { + if (!vm && !vext_elem_mask(v0, mlen, i)) { + continue; + } + addr = base + nf * i * msz; + if (i == 0) { + probe_pages(env, addr, nf * msz, ra, MMU_DATA_LOAD); + } else { + /* if it triggers an exception, no need to check watchpoint */ + remain = nf * msz; + while (remain > 0) { + offset = -(addr | TARGET_PAGE_MASK); + host = tlb_vaddr_to_host(env, addr, MMU_DATA_LOAD, + cpu_mmu_index(env, false)); + if (host) { +#ifdef CONFIG_USER_ONLY + if (page_check_range(addr, nf * msz, PAGE_READ) < 0) { + vl = i; + goto ProbeSuccess; + } +#else + probe_pages(env, addr, nf * msz, ra, MMU_DATA_LOAD); +#endif + } else { + vl = i; + goto ProbeSuccess; + } + if (remain <= offset) { + break; + } + remain -= offset; + addr += offset; + } + } + } +ProbeSuccess: + /* load bytes from guest memory */ + if (vl != 0) { + env->vl = vl; + } + for (i = 0; i < env->vl; i++) { + k = 0; + if (!vm && !vext_elem_mask(v0, mlen, i)) { + continue; + } + while (k < nf) { + target_ulong addr = base + (i * nf + k) * msz; + ldst_elem(env, addr, i + k * vlmax, vd, ra); + k++; + } + } + /* clear tail elements */ + if (vl != 0) { + return; + } + for (k = 0; k < nf; k++) { + clear_elem(vd, env->vl + k * vlmax, env->vl * esz, vlmax * esz); + } +} + +#define GEN_VEXT_LDFF(NAME, MTYPE, ETYPE, LOAD_FN, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, target_ulong base, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + vext_ldff(vd, v0, base, env, desc, LOAD_FN, CLEAR_FN, \ + sizeof(ETYPE), sizeof(MTYPE), GETPC()); \ +} + +GEN_VEXT_LDFF(vlbff_v_b, int8_t, int8_t, ldb_b, clearb) +GEN_VEXT_LDFF(vlbff_v_h, int8_t, int16_t, ldb_h, clearh) +GEN_VEXT_LDFF(vlbff_v_w, int8_t, int32_t, ldb_w, clearl) +GEN_VEXT_LDFF(vlbff_v_d, int8_t, int64_t, ldb_d, clearq) +GEN_VEXT_LDFF(vlhff_v_h, int16_t, int16_t, ldh_h, clearh) +GEN_VEXT_LDFF(vlhff_v_w, int16_t, int32_t, ldh_w, clearl) +GEN_VEXT_LDFF(vlhff_v_d, int16_t, int64_t, ldh_d, clearq) +GEN_VEXT_LDFF(vlwff_v_w, int32_t, int32_t, ldw_w, clearl) +GEN_VEXT_LDFF(vlwff_v_d, int32_t, int64_t, ldw_d, clearq) +GEN_VEXT_LDFF(vleff_v_b, int8_t, int8_t, lde_b, clearb) +GEN_VEXT_LDFF(vleff_v_h, int16_t, int16_t, lde_h, clearh) +GEN_VEXT_LDFF(vleff_v_w, int32_t, int32_t, lde_w, clearl) +GEN_VEXT_LDFF(vleff_v_d, int64_t, int64_t, lde_d, clearq) +GEN_VEXT_LDFF(vlbuff_v_b, uint8_t, uint8_t, ldbu_b, clearb) +GEN_VEXT_LDFF(vlbuff_v_h, uint8_t, uint16_t, ldbu_h, clearh) +GEN_VEXT_LDFF(vlbuff_v_w, uint8_t, uint32_t, ldbu_w, clearl) +GEN_VEXT_LDFF(vlbuff_v_d, uint8_t, uint64_t, ldbu_d, clearq) +GEN_VEXT_LDFF(vlhuff_v_h, uint16_t, uint16_t, ldhu_h, clearh) +GEN_VEXT_LDFF(vlhuff_v_w, uint16_t, uint32_t, ldhu_w, clearl) +GEN_VEXT_LDFF(vlhuff_v_d, uint16_t, uint64_t, ldhu_d, clearq) +GEN_VEXT_LDFF(vlwuff_v_w, uint32_t, uint32_t, ldwu_w, clearl) +GEN_VEXT_LDFF(vlwuff_v_d, uint32_t, uint64_t, ldwu_d, clearq) + +/* + *** Vector AMO Operations (Zvamo) + */ +typedef void vext_amo_noatomic_fn(void *vs3, target_ulong addr, + uint32_t wd, uint32_t idx, CPURISCVState *env, + uintptr_t retaddr); + +/* no atomic opreation for vector atomic insructions */ +#define DO_SWAP(N, M) (M) +#define DO_AND(N, M) (N & M) +#define DO_XOR(N, M) (N ^ M) +#define DO_OR(N, M) (N | M) +#define DO_ADD(N, M) (N + M) + +#define GEN_VEXT_AMO_NOATOMIC_OP(NAME, ESZ, MSZ, H, DO_OP, SUF) \ +static void \ +vext_##NAME##_noatomic_op(void *vs3, target_ulong addr, \ + uint32_t wd, uint32_t idx, \ + CPURISCVState *env, uintptr_t retaddr)\ +{ \ + typedef int##ESZ##_t ETYPE; \ + typedef int##MSZ##_t MTYPE; \ + typedef uint##MSZ##_t UMTYPE __attribute__((unused)); \ + ETYPE *pe3 = (ETYPE *)vs3 + H(idx); \ + MTYPE a = cpu_ld##SUF##_data(env, addr), b = *pe3; \ + \ + cpu_st##SUF##_data(env, addr, DO_OP(a, b)); \ + if (wd) { \ + *pe3 = a; \ + } \ +} + +/* Signed min/max */ +#define DO_MAX(N, M) ((N) >= (M) ? (N) : (M)) +#define DO_MIN(N, M) ((N) >= (M) ? (M) : (N)) + +/* Unsigned min/max */ +#define DO_MAXU(N, M) DO_MAX((UMTYPE)N, (UMTYPE)M) +#define DO_MINU(N, M) DO_MIN((UMTYPE)N, (UMTYPE)M) + +GEN_VEXT_AMO_NOATOMIC_OP(vamoswapw_v_w, 32, 32, H4, DO_SWAP, l) +GEN_VEXT_AMO_NOATOMIC_OP(vamoaddw_v_w, 32, 32, H4, DO_ADD, l) +GEN_VEXT_AMO_NOATOMIC_OP(vamoxorw_v_w, 32, 32, H4, DO_XOR, l) +GEN_VEXT_AMO_NOATOMIC_OP(vamoandw_v_w, 32, 32, H4, DO_AND, l) +GEN_VEXT_AMO_NOATOMIC_OP(vamoorw_v_w, 32, 32, H4, DO_OR, l) +GEN_VEXT_AMO_NOATOMIC_OP(vamominw_v_w, 32, 32, H4, DO_MIN, l) +GEN_VEXT_AMO_NOATOMIC_OP(vamomaxw_v_w, 32, 32, H4, DO_MAX, l) +GEN_VEXT_AMO_NOATOMIC_OP(vamominuw_v_w, 32, 32, H4, DO_MINU, l) +GEN_VEXT_AMO_NOATOMIC_OP(vamomaxuw_v_w, 32, 32, H4, DO_MAXU, l) +#ifdef TARGET_RISCV64 +GEN_VEXT_AMO_NOATOMIC_OP(vamoswapw_v_d, 64, 32, H8, DO_SWAP, l) +GEN_VEXT_AMO_NOATOMIC_OP(vamoswapd_v_d, 64, 64, H8, DO_SWAP, q) +GEN_VEXT_AMO_NOATOMIC_OP(vamoaddw_v_d, 64, 32, H8, DO_ADD, l) +GEN_VEXT_AMO_NOATOMIC_OP(vamoaddd_v_d, 64, 64, H8, DO_ADD, q) +GEN_VEXT_AMO_NOATOMIC_OP(vamoxorw_v_d, 64, 32, H8, DO_XOR, l) +GEN_VEXT_AMO_NOATOMIC_OP(vamoxord_v_d, 64, 64, H8, DO_XOR, q) +GEN_VEXT_AMO_NOATOMIC_OP(vamoandw_v_d, 64, 32, H8, DO_AND, l) +GEN_VEXT_AMO_NOATOMIC_OP(vamoandd_v_d, 64, 64, H8, DO_AND, q) +GEN_VEXT_AMO_NOATOMIC_OP(vamoorw_v_d, 64, 32, H8, DO_OR, l) +GEN_VEXT_AMO_NOATOMIC_OP(vamoord_v_d, 64, 64, H8, DO_OR, q) +GEN_VEXT_AMO_NOATOMIC_OP(vamominw_v_d, 64, 32, H8, DO_MIN, l) +GEN_VEXT_AMO_NOATOMIC_OP(vamomind_v_d, 64, 64, H8, DO_MIN, q) +GEN_VEXT_AMO_NOATOMIC_OP(vamomaxw_v_d, 64, 32, H8, DO_MAX, l) +GEN_VEXT_AMO_NOATOMIC_OP(vamomaxd_v_d, 64, 64, H8, DO_MAX, q) +GEN_VEXT_AMO_NOATOMIC_OP(vamominuw_v_d, 64, 32, H8, DO_MINU, l) +GEN_VEXT_AMO_NOATOMIC_OP(vamominud_v_d, 64, 64, H8, DO_MINU, q) +GEN_VEXT_AMO_NOATOMIC_OP(vamomaxuw_v_d, 64, 32, H8, DO_MAXU, l) +GEN_VEXT_AMO_NOATOMIC_OP(vamomaxud_v_d, 64, 64, H8, DO_MAXU, q) +#endif + +static inline void +vext_amo_noatomic(void *vs3, void *v0, target_ulong base, + void *vs2, CPURISCVState *env, uint32_t desc, + vext_get_index_addr get_index_addr, + vext_amo_noatomic_fn *noatomic_op, + clear_fn *clear_elem, + uint32_t esz, uint32_t msz, uintptr_t ra) +{ + uint32_t i; + target_long addr; + uint32_t wd = vext_wd(desc); + uint32_t vm = vext_vm(desc); + uint32_t mlen = vext_mlen(desc); + uint32_t vlmax = vext_maxsz(desc) / esz; + + for (i = 0; i < env->vl; i++) { + if (!vm && !vext_elem_mask(v0, mlen, i)) { + continue; + } + probe_pages(env, get_index_addr(base, i, vs2), msz, ra, MMU_DATA_LOAD); + probe_pages(env, get_index_addr(base, i, vs2), msz, ra, MMU_DATA_STORE); + } + for (i = 0; i < env->vl; i++) { + if (!vm && !vext_elem_mask(v0, mlen, i)) { + continue; + } + addr = get_index_addr(base, i, vs2); + noatomic_op(vs3, addr, wd, i, env, ra); + } + clear_elem(vs3, env->vl, env->vl * esz, vlmax * esz); +} + +#define GEN_VEXT_AMO(NAME, MTYPE, ETYPE, INDEX_FN, CLEAR_FN) \ +void HELPER(NAME)(void *vs3, void *v0, target_ulong base, \ + void *vs2, CPURISCVState *env, uint32_t desc) \ +{ \ + vext_amo_noatomic(vs3, v0, base, vs2, env, desc, \ + INDEX_FN, vext_##NAME##_noatomic_op, \ + CLEAR_FN, sizeof(ETYPE), sizeof(MTYPE), \ + GETPC()); \ +} + +#ifdef TARGET_RISCV64 +GEN_VEXT_AMO(vamoswapw_v_d, int32_t, int64_t, idx_d, clearq) +GEN_VEXT_AMO(vamoswapd_v_d, int64_t, int64_t, idx_d, clearq) +GEN_VEXT_AMO(vamoaddw_v_d, int32_t, int64_t, idx_d, clearq) +GEN_VEXT_AMO(vamoaddd_v_d, int64_t, int64_t, idx_d, clearq) +GEN_VEXT_AMO(vamoxorw_v_d, int32_t, int64_t, idx_d, clearq) +GEN_VEXT_AMO(vamoxord_v_d, int64_t, int64_t, idx_d, clearq) +GEN_VEXT_AMO(vamoandw_v_d, int32_t, int64_t, idx_d, clearq) +GEN_VEXT_AMO(vamoandd_v_d, int64_t, int64_t, idx_d, clearq) +GEN_VEXT_AMO(vamoorw_v_d, int32_t, int64_t, idx_d, clearq) +GEN_VEXT_AMO(vamoord_v_d, int64_t, int64_t, idx_d, clearq) +GEN_VEXT_AMO(vamominw_v_d, int32_t, int64_t, idx_d, clearq) +GEN_VEXT_AMO(vamomind_v_d, int64_t, int64_t, idx_d, clearq) +GEN_VEXT_AMO(vamomaxw_v_d, int32_t, int64_t, idx_d, clearq) +GEN_VEXT_AMO(vamomaxd_v_d, int64_t, int64_t, idx_d, clearq) +GEN_VEXT_AMO(vamominuw_v_d, uint32_t, uint64_t, idx_d, clearq) +GEN_VEXT_AMO(vamominud_v_d, uint64_t, uint64_t, idx_d, clearq) +GEN_VEXT_AMO(vamomaxuw_v_d, uint32_t, uint64_t, idx_d, clearq) +GEN_VEXT_AMO(vamomaxud_v_d, uint64_t, uint64_t, idx_d, clearq) +#endif +GEN_VEXT_AMO(vamoswapw_v_w, int32_t, int32_t, idx_w, clearl) +GEN_VEXT_AMO(vamoaddw_v_w, int32_t, int32_t, idx_w, clearl) +GEN_VEXT_AMO(vamoxorw_v_w, int32_t, int32_t, idx_w, clearl) +GEN_VEXT_AMO(vamoandw_v_w, int32_t, int32_t, idx_w, clearl) +GEN_VEXT_AMO(vamoorw_v_w, int32_t, int32_t, idx_w, clearl) +GEN_VEXT_AMO(vamominw_v_w, int32_t, int32_t, idx_w, clearl) +GEN_VEXT_AMO(vamomaxw_v_w, int32_t, int32_t, idx_w, clearl) +GEN_VEXT_AMO(vamominuw_v_w, uint32_t, uint32_t, idx_w, clearl) +GEN_VEXT_AMO(vamomaxuw_v_w, uint32_t, uint32_t, idx_w, clearl) + +/* + *** Vector Integer Arithmetic Instructions + */ + +/* expand macro args before macro */ +#define RVVCALL(macro, ...) macro(__VA_ARGS__) + +/* (TD, T1, T2, TX1, TX2) */ +#define OP_SSS_B int8_t, int8_t, int8_t, int8_t, int8_t +#define OP_SSS_H int16_t, int16_t, int16_t, int16_t, int16_t +#define OP_SSS_W int32_t, int32_t, int32_t, int32_t, int32_t +#define OP_SSS_D int64_t, int64_t, int64_t, int64_t, int64_t +#define OP_UUU_B uint8_t, uint8_t, uint8_t, uint8_t, uint8_t +#define OP_UUU_H uint16_t, uint16_t, uint16_t, uint16_t, uint16_t +#define OP_UUU_W uint32_t, uint32_t, uint32_t, uint32_t, uint32_t +#define OP_UUU_D uint64_t, uint64_t, uint64_t, uint64_t, uint64_t +#define OP_SUS_B int8_t, uint8_t, int8_t, uint8_t, int8_t +#define OP_SUS_H int16_t, uint16_t, int16_t, uint16_t, int16_t +#define OP_SUS_W int32_t, uint32_t, int32_t, uint32_t, int32_t +#define OP_SUS_D int64_t, uint64_t, int64_t, uint64_t, int64_t +#define WOP_UUU_B uint16_t, uint8_t, uint8_t, uint16_t, uint16_t +#define WOP_UUU_H uint32_t, uint16_t, uint16_t, uint32_t, uint32_t +#define WOP_UUU_W uint64_t, uint32_t, uint32_t, uint64_t, uint64_t +#define WOP_SSS_B int16_t, int8_t, int8_t, int16_t, int16_t +#define WOP_SSS_H int32_t, int16_t, int16_t, int32_t, int32_t +#define WOP_SSS_W int64_t, int32_t, int32_t, int64_t, int64_t +#define WOP_SUS_B int16_t, uint8_t, int8_t, uint16_t, int16_t +#define WOP_SUS_H int32_t, uint16_t, int16_t, uint32_t, int32_t +#define WOP_SUS_W int64_t, uint32_t, int32_t, uint64_t, int64_t +#define WOP_SSU_B int16_t, int8_t, uint8_t, int16_t, uint16_t +#define WOP_SSU_H int32_t, int16_t, uint16_t, int32_t, uint32_t +#define WOP_SSU_W int64_t, int32_t, uint32_t, int64_t, uint64_t +#define NOP_SSS_B int8_t, int8_t, int16_t, int8_t, int16_t +#define NOP_SSS_H int16_t, int16_t, int32_t, int16_t, int32_t +#define NOP_SSS_W int32_t, int32_t, int64_t, int32_t, int64_t +#define NOP_UUU_B uint8_t, uint8_t, uint16_t, uint8_t, uint16_t +#define NOP_UUU_H uint16_t, uint16_t, uint32_t, uint16_t, uint32_t +#define NOP_UUU_W uint32_t, uint32_t, uint64_t, uint32_t, uint64_t + +/* operation of two vector elements */ +typedef void opivv2_fn(void *vd, void *vs1, void *vs2, int i); + +#define OPIVV2(NAME, TD, T1, T2, TX1, TX2, HD, HS1, HS2, OP) \ +static void do_##NAME(void *vd, void *vs1, void *vs2, int i) \ +{ \ + TX1 s1 = *((T1 *)vs1 + HS1(i)); \ + TX2 s2 = *((T2 *)vs2 + HS2(i)); \ + *((TD *)vd + HD(i)) = OP(s2, s1); \ +} +#define DO_SUB(N, M) (N - M) +#define DO_RSUB(N, M) (M - N) + +RVVCALL(OPIVV2, vadd_vv_b, OP_SSS_B, H1, H1, H1, DO_ADD) +RVVCALL(OPIVV2, vadd_vv_h, OP_SSS_H, H2, H2, H2, DO_ADD) +RVVCALL(OPIVV2, vadd_vv_w, OP_SSS_W, H4, H4, H4, DO_ADD) +RVVCALL(OPIVV2, vadd_vv_d, OP_SSS_D, H8, H8, H8, DO_ADD) +RVVCALL(OPIVV2, vsub_vv_b, OP_SSS_B, H1, H1, H1, DO_SUB) +RVVCALL(OPIVV2, vsub_vv_h, OP_SSS_H, H2, H2, H2, DO_SUB) +RVVCALL(OPIVV2, vsub_vv_w, OP_SSS_W, H4, H4, H4, DO_SUB) +RVVCALL(OPIVV2, vsub_vv_d, OP_SSS_D, H8, H8, H8, DO_SUB) + +static void do_vext_vv(void *vd, void *v0, void *vs1, void *vs2, + CPURISCVState *env, uint32_t desc, + uint32_t esz, uint32_t dsz, + opivv2_fn *fn, clear_fn *clearfn) +{ + uint32_t vlmax = vext_maxsz(desc) / esz; + uint32_t mlen = vext_mlen(desc); + uint32_t vm = vext_vm(desc); + uint32_t vl = env->vl; + uint32_t i; + + for (i = 0; i < vl; i++) { + if (!vm && !vext_elem_mask(v0, mlen, i)) { + continue; + } + fn(vd, vs1, vs2, i); + } + clearfn(vd, vl, vl * dsz, vlmax * dsz); +} + +/* generate the helpers for OPIVV */ +#define GEN_VEXT_VV(NAME, ESZ, DSZ, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, void *vs1, \ + void *vs2, CPURISCVState *env, \ + uint32_t desc) \ +{ \ + do_vext_vv(vd, v0, vs1, vs2, env, desc, ESZ, DSZ, \ + do_##NAME, CLEAR_FN); \ +} + +GEN_VEXT_VV(vadd_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vadd_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vadd_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vadd_vv_d, 8, 8, clearq) +GEN_VEXT_VV(vsub_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vsub_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vsub_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vsub_vv_d, 8, 8, clearq) + +typedef void opivx2_fn(void *vd, target_long s1, void *vs2, int i); + +/* + * (T1)s1 gives the real operator type. + * (TX1)(T1)s1 expands the operator type of widen or narrow operations. + */ +#define OPIVX2(NAME, TD, T1, T2, TX1, TX2, HD, HS2, OP) \ +static void do_##NAME(void *vd, target_long s1, void *vs2, int i) \ +{ \ + TX2 s2 = *((T2 *)vs2 + HS2(i)); \ + *((TD *)vd + HD(i)) = OP(s2, (TX1)(T1)s1); \ +} + +RVVCALL(OPIVX2, vadd_vx_b, OP_SSS_B, H1, H1, DO_ADD) +RVVCALL(OPIVX2, vadd_vx_h, OP_SSS_H, H2, H2, DO_ADD) +RVVCALL(OPIVX2, vadd_vx_w, OP_SSS_W, H4, H4, DO_ADD) +RVVCALL(OPIVX2, vadd_vx_d, OP_SSS_D, H8, H8, DO_ADD) +RVVCALL(OPIVX2, vsub_vx_b, OP_SSS_B, H1, H1, DO_SUB) +RVVCALL(OPIVX2, vsub_vx_h, OP_SSS_H, H2, H2, DO_SUB) +RVVCALL(OPIVX2, vsub_vx_w, OP_SSS_W, H4, H4, DO_SUB) +RVVCALL(OPIVX2, vsub_vx_d, OP_SSS_D, H8, H8, DO_SUB) +RVVCALL(OPIVX2, vrsub_vx_b, OP_SSS_B, H1, H1, DO_RSUB) +RVVCALL(OPIVX2, vrsub_vx_h, OP_SSS_H, H2, H2, DO_RSUB) +RVVCALL(OPIVX2, vrsub_vx_w, OP_SSS_W, H4, H4, DO_RSUB) +RVVCALL(OPIVX2, vrsub_vx_d, OP_SSS_D, H8, H8, DO_RSUB) + +static void do_vext_vx(void *vd, void *v0, target_long s1, void *vs2, + CPURISCVState *env, uint32_t desc, + uint32_t esz, uint32_t dsz, + opivx2_fn fn, clear_fn *clearfn) +{ + uint32_t vlmax = vext_maxsz(desc) / esz; + uint32_t mlen = vext_mlen(desc); + uint32_t vm = vext_vm(desc); + uint32_t vl = env->vl; + uint32_t i; + + for (i = 0; i < vl; i++) { + if (!vm && !vext_elem_mask(v0, mlen, i)) { + continue; + } + fn(vd, s1, vs2, i); + } + clearfn(vd, vl, vl * dsz, vlmax * dsz); +} + +/* generate the helpers for OPIVX */ +#define GEN_VEXT_VX(NAME, ESZ, DSZ, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \ + void *vs2, CPURISCVState *env, \ + uint32_t desc) \ +{ \ + do_vext_vx(vd, v0, s1, vs2, env, desc, ESZ, DSZ, \ + do_##NAME, CLEAR_FN); \ +} + +GEN_VEXT_VX(vadd_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vadd_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vadd_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vadd_vx_d, 8, 8, clearq) +GEN_VEXT_VX(vsub_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vsub_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vsub_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vsub_vx_d, 8, 8, clearq) +GEN_VEXT_VX(vrsub_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vrsub_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vrsub_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vrsub_vx_d, 8, 8, clearq) + +void HELPER(vec_rsubs8)(void *d, void *a, uint64_t b, uint32_t desc) +{ + intptr_t oprsz = simd_oprsz(desc); + intptr_t i; + + for (i = 0; i < oprsz; i += sizeof(uint8_t)) { + *(uint8_t *)(d + i) = (uint8_t)b - *(uint8_t *)(a + i); + } +} + +void HELPER(vec_rsubs16)(void *d, void *a, uint64_t b, uint32_t desc) +{ + intptr_t oprsz = simd_oprsz(desc); + intptr_t i; + + for (i = 0; i < oprsz; i += sizeof(uint16_t)) { + *(uint16_t *)(d + i) = (uint16_t)b - *(uint16_t *)(a + i); + } +} + +void HELPER(vec_rsubs32)(void *d, void *a, uint64_t b, uint32_t desc) +{ + intptr_t oprsz = simd_oprsz(desc); + intptr_t i; + + for (i = 0; i < oprsz; i += sizeof(uint32_t)) { + *(uint32_t *)(d + i) = (uint32_t)b - *(uint32_t *)(a + i); + } +} + +void HELPER(vec_rsubs64)(void *d, void *a, uint64_t b, uint32_t desc) +{ + intptr_t oprsz = simd_oprsz(desc); + intptr_t i; + + for (i = 0; i < oprsz; i += sizeof(uint64_t)) { + *(uint64_t *)(d + i) = b - *(uint64_t *)(a + i); + } +} + +/* Vector Widening Integer Add/Subtract */ +#define WOP_UUU_B uint16_t, uint8_t, uint8_t, uint16_t, uint16_t +#define WOP_UUU_H uint32_t, uint16_t, uint16_t, uint32_t, uint32_t +#define WOP_UUU_W uint64_t, uint32_t, uint32_t, uint64_t, uint64_t +#define WOP_SSS_B int16_t, int8_t, int8_t, int16_t, int16_t +#define WOP_SSS_H int32_t, int16_t, int16_t, int32_t, int32_t +#define WOP_SSS_W int64_t, int32_t, int32_t, int64_t, int64_t +#define WOP_WUUU_B uint16_t, uint8_t, uint16_t, uint16_t, uint16_t +#define WOP_WUUU_H uint32_t, uint16_t, uint32_t, uint32_t, uint32_t +#define WOP_WUUU_W uint64_t, uint32_t, uint64_t, uint64_t, uint64_t +#define WOP_WSSS_B int16_t, int8_t, int16_t, int16_t, int16_t +#define WOP_WSSS_H int32_t, int16_t, int32_t, int32_t, int32_t +#define WOP_WSSS_W int64_t, int32_t, int64_t, int64_t, int64_t +RVVCALL(OPIVV2, vwaddu_vv_b, WOP_UUU_B, H2, H1, H1, DO_ADD) +RVVCALL(OPIVV2, vwaddu_vv_h, WOP_UUU_H, H4, H2, H2, DO_ADD) +RVVCALL(OPIVV2, vwaddu_vv_w, WOP_UUU_W, H8, H4, H4, DO_ADD) +RVVCALL(OPIVV2, vwsubu_vv_b, WOP_UUU_B, H2, H1, H1, DO_SUB) +RVVCALL(OPIVV2, vwsubu_vv_h, WOP_UUU_H, H4, H2, H2, DO_SUB) +RVVCALL(OPIVV2, vwsubu_vv_w, WOP_UUU_W, H8, H4, H4, DO_SUB) +RVVCALL(OPIVV2, vwadd_vv_b, WOP_SSS_B, H2, H1, H1, DO_ADD) +RVVCALL(OPIVV2, vwadd_vv_h, WOP_SSS_H, H4, H2, H2, DO_ADD) +RVVCALL(OPIVV2, vwadd_vv_w, WOP_SSS_W, H8, H4, H4, DO_ADD) +RVVCALL(OPIVV2, vwsub_vv_b, WOP_SSS_B, H2, H1, H1, DO_SUB) +RVVCALL(OPIVV2, vwsub_vv_h, WOP_SSS_H, H4, H2, H2, DO_SUB) +RVVCALL(OPIVV2, vwsub_vv_w, WOP_SSS_W, H8, H4, H4, DO_SUB) +RVVCALL(OPIVV2, vwaddu_wv_b, WOP_WUUU_B, H2, H1, H1, DO_ADD) +RVVCALL(OPIVV2, vwaddu_wv_h, WOP_WUUU_H, H4, H2, H2, DO_ADD) +RVVCALL(OPIVV2, vwaddu_wv_w, WOP_WUUU_W, H8, H4, H4, DO_ADD) +RVVCALL(OPIVV2, vwsubu_wv_b, WOP_WUUU_B, H2, H1, H1, DO_SUB) +RVVCALL(OPIVV2, vwsubu_wv_h, WOP_WUUU_H, H4, H2, H2, DO_SUB) +RVVCALL(OPIVV2, vwsubu_wv_w, WOP_WUUU_W, H8, H4, H4, DO_SUB) +RVVCALL(OPIVV2, vwadd_wv_b, WOP_WSSS_B, H2, H1, H1, DO_ADD) +RVVCALL(OPIVV2, vwadd_wv_h, WOP_WSSS_H, H4, H2, H2, DO_ADD) +RVVCALL(OPIVV2, vwadd_wv_w, WOP_WSSS_W, H8, H4, H4, DO_ADD) +RVVCALL(OPIVV2, vwsub_wv_b, WOP_WSSS_B, H2, H1, H1, DO_SUB) +RVVCALL(OPIVV2, vwsub_wv_h, WOP_WSSS_H, H4, H2, H2, DO_SUB) +RVVCALL(OPIVV2, vwsub_wv_w, WOP_WSSS_W, H8, H4, H4, DO_SUB) +GEN_VEXT_VV(vwaddu_vv_b, 1, 2, clearh) +GEN_VEXT_VV(vwaddu_vv_h, 2, 4, clearl) +GEN_VEXT_VV(vwaddu_vv_w, 4, 8, clearq) +GEN_VEXT_VV(vwsubu_vv_b, 1, 2, clearh) +GEN_VEXT_VV(vwsubu_vv_h, 2, 4, clearl) +GEN_VEXT_VV(vwsubu_vv_w, 4, 8, clearq) +GEN_VEXT_VV(vwadd_vv_b, 1, 2, clearh) +GEN_VEXT_VV(vwadd_vv_h, 2, 4, clearl) +GEN_VEXT_VV(vwadd_vv_w, 4, 8, clearq) +GEN_VEXT_VV(vwsub_vv_b, 1, 2, clearh) +GEN_VEXT_VV(vwsub_vv_h, 2, 4, clearl) +GEN_VEXT_VV(vwsub_vv_w, 4, 8, clearq) +GEN_VEXT_VV(vwaddu_wv_b, 1, 2, clearh) +GEN_VEXT_VV(vwaddu_wv_h, 2, 4, clearl) +GEN_VEXT_VV(vwaddu_wv_w, 4, 8, clearq) +GEN_VEXT_VV(vwsubu_wv_b, 1, 2, clearh) +GEN_VEXT_VV(vwsubu_wv_h, 2, 4, clearl) +GEN_VEXT_VV(vwsubu_wv_w, 4, 8, clearq) +GEN_VEXT_VV(vwadd_wv_b, 1, 2, clearh) +GEN_VEXT_VV(vwadd_wv_h, 2, 4, clearl) +GEN_VEXT_VV(vwadd_wv_w, 4, 8, clearq) +GEN_VEXT_VV(vwsub_wv_b, 1, 2, clearh) +GEN_VEXT_VV(vwsub_wv_h, 2, 4, clearl) +GEN_VEXT_VV(vwsub_wv_w, 4, 8, clearq) + +RVVCALL(OPIVX2, vwaddu_vx_b, WOP_UUU_B, H2, H1, DO_ADD) +RVVCALL(OPIVX2, vwaddu_vx_h, WOP_UUU_H, H4, H2, DO_ADD) +RVVCALL(OPIVX2, vwaddu_vx_w, WOP_UUU_W, H8, H4, DO_ADD) +RVVCALL(OPIVX2, vwsubu_vx_b, WOP_UUU_B, H2, H1, DO_SUB) +RVVCALL(OPIVX2, vwsubu_vx_h, WOP_UUU_H, H4, H2, DO_SUB) +RVVCALL(OPIVX2, vwsubu_vx_w, WOP_UUU_W, H8, H4, DO_SUB) +RVVCALL(OPIVX2, vwadd_vx_b, WOP_SSS_B, H2, H1, DO_ADD) +RVVCALL(OPIVX2, vwadd_vx_h, WOP_SSS_H, H4, H2, DO_ADD) +RVVCALL(OPIVX2, vwadd_vx_w, WOP_SSS_W, H8, H4, DO_ADD) +RVVCALL(OPIVX2, vwsub_vx_b, WOP_SSS_B, H2, H1, DO_SUB) +RVVCALL(OPIVX2, vwsub_vx_h, WOP_SSS_H, H4, H2, DO_SUB) +RVVCALL(OPIVX2, vwsub_vx_w, WOP_SSS_W, H8, H4, DO_SUB) +RVVCALL(OPIVX2, vwaddu_wx_b, WOP_WUUU_B, H2, H1, DO_ADD) +RVVCALL(OPIVX2, vwaddu_wx_h, WOP_WUUU_H, H4, H2, DO_ADD) +RVVCALL(OPIVX2, vwaddu_wx_w, WOP_WUUU_W, H8, H4, DO_ADD) +RVVCALL(OPIVX2, vwsubu_wx_b, WOP_WUUU_B, H2, H1, DO_SUB) +RVVCALL(OPIVX2, vwsubu_wx_h, WOP_WUUU_H, H4, H2, DO_SUB) +RVVCALL(OPIVX2, vwsubu_wx_w, WOP_WUUU_W, H8, H4, DO_SUB) +RVVCALL(OPIVX2, vwadd_wx_b, WOP_WSSS_B, H2, H1, DO_ADD) +RVVCALL(OPIVX2, vwadd_wx_h, WOP_WSSS_H, H4, H2, DO_ADD) +RVVCALL(OPIVX2, vwadd_wx_w, WOP_WSSS_W, H8, H4, DO_ADD) +RVVCALL(OPIVX2, vwsub_wx_b, WOP_WSSS_B, H2, H1, DO_SUB) +RVVCALL(OPIVX2, vwsub_wx_h, WOP_WSSS_H, H4, H2, DO_SUB) +RVVCALL(OPIVX2, vwsub_wx_w, WOP_WSSS_W, H8, H4, DO_SUB) +GEN_VEXT_VX(vwaddu_vx_b, 1, 2, clearh) +GEN_VEXT_VX(vwaddu_vx_h, 2, 4, clearl) +GEN_VEXT_VX(vwaddu_vx_w, 4, 8, clearq) +GEN_VEXT_VX(vwsubu_vx_b, 1, 2, clearh) +GEN_VEXT_VX(vwsubu_vx_h, 2, 4, clearl) +GEN_VEXT_VX(vwsubu_vx_w, 4, 8, clearq) +GEN_VEXT_VX(vwadd_vx_b, 1, 2, clearh) +GEN_VEXT_VX(vwadd_vx_h, 2, 4, clearl) +GEN_VEXT_VX(vwadd_vx_w, 4, 8, clearq) +GEN_VEXT_VX(vwsub_vx_b, 1, 2, clearh) +GEN_VEXT_VX(vwsub_vx_h, 2, 4, clearl) +GEN_VEXT_VX(vwsub_vx_w, 4, 8, clearq) +GEN_VEXT_VX(vwaddu_wx_b, 1, 2, clearh) +GEN_VEXT_VX(vwaddu_wx_h, 2, 4, clearl) +GEN_VEXT_VX(vwaddu_wx_w, 4, 8, clearq) +GEN_VEXT_VX(vwsubu_wx_b, 1, 2, clearh) +GEN_VEXT_VX(vwsubu_wx_h, 2, 4, clearl) +GEN_VEXT_VX(vwsubu_wx_w, 4, 8, clearq) +GEN_VEXT_VX(vwadd_wx_b, 1, 2, clearh) +GEN_VEXT_VX(vwadd_wx_h, 2, 4, clearl) +GEN_VEXT_VX(vwadd_wx_w, 4, 8, clearq) +GEN_VEXT_VX(vwsub_wx_b, 1, 2, clearh) +GEN_VEXT_VX(vwsub_wx_h, 2, 4, clearl) +GEN_VEXT_VX(vwsub_wx_w, 4, 8, clearq) + +/* Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions */ +#define DO_VADC(N, M, C) (N + M + C) +#define DO_VSBC(N, M, C) (N - M - C) + +#define GEN_VEXT_VADC_VVM(NAME, ETYPE, H, DO_OP, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vl = env->vl; \ + uint32_t esz = sizeof(ETYPE); \ + uint32_t vlmax = vext_maxsz(desc) / esz; \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + ETYPE s1 = *((ETYPE *)vs1 + H(i)); \ + ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ + uint8_t carry = vext_elem_mask(v0, mlen, i); \ + \ + *((ETYPE *)vd + H(i)) = DO_OP(s2, s1, carry); \ + } \ + CLEAR_FN(vd, vl, vl * esz, vlmax * esz); \ +} + +GEN_VEXT_VADC_VVM(vadc_vvm_b, uint8_t, H1, DO_VADC, clearb) +GEN_VEXT_VADC_VVM(vadc_vvm_h, uint16_t, H2, DO_VADC, clearh) +GEN_VEXT_VADC_VVM(vadc_vvm_w, uint32_t, H4, DO_VADC, clearl) +GEN_VEXT_VADC_VVM(vadc_vvm_d, uint64_t, H8, DO_VADC, clearq) + +GEN_VEXT_VADC_VVM(vsbc_vvm_b, uint8_t, H1, DO_VSBC, clearb) +GEN_VEXT_VADC_VVM(vsbc_vvm_h, uint16_t, H2, DO_VSBC, clearh) +GEN_VEXT_VADC_VVM(vsbc_vvm_w, uint32_t, H4, DO_VSBC, clearl) +GEN_VEXT_VADC_VVM(vsbc_vvm_d, uint64_t, H8, DO_VSBC, clearq) + +#define GEN_VEXT_VADC_VXM(NAME, ETYPE, H, DO_OP, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vl = env->vl; \ + uint32_t esz = sizeof(ETYPE); \ + uint32_t vlmax = vext_maxsz(desc) / esz; \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ + uint8_t carry = vext_elem_mask(v0, mlen, i); \ + \ + *((ETYPE *)vd + H(i)) = DO_OP(s2, (ETYPE)(target_long)s1, carry);\ + } \ + CLEAR_FN(vd, vl, vl * esz, vlmax * esz); \ +} + +GEN_VEXT_VADC_VXM(vadc_vxm_b, uint8_t, H1, DO_VADC, clearb) +GEN_VEXT_VADC_VXM(vadc_vxm_h, uint16_t, H2, DO_VADC, clearh) +GEN_VEXT_VADC_VXM(vadc_vxm_w, uint32_t, H4, DO_VADC, clearl) +GEN_VEXT_VADC_VXM(vadc_vxm_d, uint64_t, H8, DO_VADC, clearq) + +GEN_VEXT_VADC_VXM(vsbc_vxm_b, uint8_t, H1, DO_VSBC, clearb) +GEN_VEXT_VADC_VXM(vsbc_vxm_h, uint16_t, H2, DO_VSBC, clearh) +GEN_VEXT_VADC_VXM(vsbc_vxm_w, uint32_t, H4, DO_VSBC, clearl) +GEN_VEXT_VADC_VXM(vsbc_vxm_d, uint64_t, H8, DO_VSBC, clearq) + +#define DO_MADC(N, M, C) (C ? (__typeof(N))(N + M + 1) <= N : \ + (__typeof(N))(N + M) < N) +#define DO_MSBC(N, M, C) (C ? N <= M : N < M) + +#define GEN_VEXT_VMADC_VVM(NAME, ETYPE, H, DO_OP) \ +void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vl = env->vl; \ + uint32_t vlmax = vext_maxsz(desc) / sizeof(ETYPE); \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + ETYPE s1 = *((ETYPE *)vs1 + H(i)); \ + ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ + uint8_t carry = vext_elem_mask(v0, mlen, i); \ + \ + vext_set_elem_mask(vd, mlen, i, DO_OP(s2, s1, carry));\ + } \ + for (; i < vlmax; i++) { \ + vext_set_elem_mask(vd, mlen, i, 0); \ + } \ +} + +GEN_VEXT_VMADC_VVM(vmadc_vvm_b, uint8_t, H1, DO_MADC) +GEN_VEXT_VMADC_VVM(vmadc_vvm_h, uint16_t, H2, DO_MADC) +GEN_VEXT_VMADC_VVM(vmadc_vvm_w, uint32_t, H4, DO_MADC) +GEN_VEXT_VMADC_VVM(vmadc_vvm_d, uint64_t, H8, DO_MADC) + +GEN_VEXT_VMADC_VVM(vmsbc_vvm_b, uint8_t, H1, DO_MSBC) +GEN_VEXT_VMADC_VVM(vmsbc_vvm_h, uint16_t, H2, DO_MSBC) +GEN_VEXT_VMADC_VVM(vmsbc_vvm_w, uint32_t, H4, DO_MSBC) +GEN_VEXT_VMADC_VVM(vmsbc_vvm_d, uint64_t, H8, DO_MSBC) + +#define GEN_VEXT_VMADC_VXM(NAME, ETYPE, H, DO_OP) \ +void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \ + void *vs2, CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vl = env->vl; \ + uint32_t vlmax = vext_maxsz(desc) / sizeof(ETYPE); \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ + uint8_t carry = vext_elem_mask(v0, mlen, i); \ + \ + vext_set_elem_mask(vd, mlen, i, \ + DO_OP(s2, (ETYPE)(target_long)s1, carry)); \ + } \ + for (; i < vlmax; i++) { \ + vext_set_elem_mask(vd, mlen, i, 0); \ + } \ +} + +GEN_VEXT_VMADC_VXM(vmadc_vxm_b, uint8_t, H1, DO_MADC) +GEN_VEXT_VMADC_VXM(vmadc_vxm_h, uint16_t, H2, DO_MADC) +GEN_VEXT_VMADC_VXM(vmadc_vxm_w, uint32_t, H4, DO_MADC) +GEN_VEXT_VMADC_VXM(vmadc_vxm_d, uint64_t, H8, DO_MADC) + +GEN_VEXT_VMADC_VXM(vmsbc_vxm_b, uint8_t, H1, DO_MSBC) +GEN_VEXT_VMADC_VXM(vmsbc_vxm_h, uint16_t, H2, DO_MSBC) +GEN_VEXT_VMADC_VXM(vmsbc_vxm_w, uint32_t, H4, DO_MSBC) +GEN_VEXT_VMADC_VXM(vmsbc_vxm_d, uint64_t, H8, DO_MSBC) + +/* Vector Bitwise Logical Instructions */ +RVVCALL(OPIVV2, vand_vv_b, OP_SSS_B, H1, H1, H1, DO_AND) +RVVCALL(OPIVV2, vand_vv_h, OP_SSS_H, H2, H2, H2, DO_AND) +RVVCALL(OPIVV2, vand_vv_w, OP_SSS_W, H4, H4, H4, DO_AND) +RVVCALL(OPIVV2, vand_vv_d, OP_SSS_D, H8, H8, H8, DO_AND) +RVVCALL(OPIVV2, vor_vv_b, OP_SSS_B, H1, H1, H1, DO_OR) +RVVCALL(OPIVV2, vor_vv_h, OP_SSS_H, H2, H2, H2, DO_OR) +RVVCALL(OPIVV2, vor_vv_w, OP_SSS_W, H4, H4, H4, DO_OR) +RVVCALL(OPIVV2, vor_vv_d, OP_SSS_D, H8, H8, H8, DO_OR) +RVVCALL(OPIVV2, vxor_vv_b, OP_SSS_B, H1, H1, H1, DO_XOR) +RVVCALL(OPIVV2, vxor_vv_h, OP_SSS_H, H2, H2, H2, DO_XOR) +RVVCALL(OPIVV2, vxor_vv_w, OP_SSS_W, H4, H4, H4, DO_XOR) +RVVCALL(OPIVV2, vxor_vv_d, OP_SSS_D, H8, H8, H8, DO_XOR) +GEN_VEXT_VV(vand_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vand_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vand_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vand_vv_d, 8, 8, clearq) +GEN_VEXT_VV(vor_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vor_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vor_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vor_vv_d, 8, 8, clearq) +GEN_VEXT_VV(vxor_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vxor_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vxor_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vxor_vv_d, 8, 8, clearq) + +RVVCALL(OPIVX2, vand_vx_b, OP_SSS_B, H1, H1, DO_AND) +RVVCALL(OPIVX2, vand_vx_h, OP_SSS_H, H2, H2, DO_AND) +RVVCALL(OPIVX2, vand_vx_w, OP_SSS_W, H4, H4, DO_AND) +RVVCALL(OPIVX2, vand_vx_d, OP_SSS_D, H8, H8, DO_AND) +RVVCALL(OPIVX2, vor_vx_b, OP_SSS_B, H1, H1, DO_OR) +RVVCALL(OPIVX2, vor_vx_h, OP_SSS_H, H2, H2, DO_OR) +RVVCALL(OPIVX2, vor_vx_w, OP_SSS_W, H4, H4, DO_OR) +RVVCALL(OPIVX2, vor_vx_d, OP_SSS_D, H8, H8, DO_OR) +RVVCALL(OPIVX2, vxor_vx_b, OP_SSS_B, H1, H1, DO_XOR) +RVVCALL(OPIVX2, vxor_vx_h, OP_SSS_H, H2, H2, DO_XOR) +RVVCALL(OPIVX2, vxor_vx_w, OP_SSS_W, H4, H4, DO_XOR) +RVVCALL(OPIVX2, vxor_vx_d, OP_SSS_D, H8, H8, DO_XOR) +GEN_VEXT_VX(vand_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vand_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vand_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vand_vx_d, 8, 8, clearq) +GEN_VEXT_VX(vor_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vor_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vor_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vor_vx_d, 8, 8, clearq) +GEN_VEXT_VX(vxor_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vxor_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vxor_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vxor_vx_d, 8, 8, clearq) + +/* Vector Single-Width Bit Shift Instructions */ +#define DO_SLL(N, M) (N << (M)) +#define DO_SRL(N, M) (N >> (M)) + +/* generate the helpers for shift instructions with two vector operators */ +#define GEN_VEXT_SHIFT_VV(NAME, TS1, TS2, HS1, HS2, OP, MASK, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, void *vs1, \ + void *vs2, CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t esz = sizeof(TS1); \ + uint32_t vlmax = vext_maxsz(desc) / esz; \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + TS1 s1 = *((TS1 *)vs1 + HS1(i)); \ + TS2 s2 = *((TS2 *)vs2 + HS2(i)); \ + *((TS1 *)vd + HS1(i)) = OP(s2, s1 & MASK); \ + } \ + CLEAR_FN(vd, vl, vl * esz, vlmax * esz); \ +} + +GEN_VEXT_SHIFT_VV(vsll_vv_b, uint8_t, uint8_t, H1, H1, DO_SLL, 0x7, clearb) +GEN_VEXT_SHIFT_VV(vsll_vv_h, uint16_t, uint16_t, H2, H2, DO_SLL, 0xf, clearh) +GEN_VEXT_SHIFT_VV(vsll_vv_w, uint32_t, uint32_t, H4, H4, DO_SLL, 0x1f, clearl) +GEN_VEXT_SHIFT_VV(vsll_vv_d, uint64_t, uint64_t, H8, H8, DO_SLL, 0x3f, clearq) + +GEN_VEXT_SHIFT_VV(vsrl_vv_b, uint8_t, uint8_t, H1, H1, DO_SRL, 0x7, clearb) +GEN_VEXT_SHIFT_VV(vsrl_vv_h, uint16_t, uint16_t, H2, H2, DO_SRL, 0xf, clearh) +GEN_VEXT_SHIFT_VV(vsrl_vv_w, uint32_t, uint32_t, H4, H4, DO_SRL, 0x1f, clearl) +GEN_VEXT_SHIFT_VV(vsrl_vv_d, uint64_t, uint64_t, H8, H8, DO_SRL, 0x3f, clearq) + +GEN_VEXT_SHIFT_VV(vsra_vv_b, uint8_t, int8_t, H1, H1, DO_SRL, 0x7, clearb) +GEN_VEXT_SHIFT_VV(vsra_vv_h, uint16_t, int16_t, H2, H2, DO_SRL, 0xf, clearh) +GEN_VEXT_SHIFT_VV(vsra_vv_w, uint32_t, int32_t, H4, H4, DO_SRL, 0x1f, clearl) +GEN_VEXT_SHIFT_VV(vsra_vv_d, uint64_t, int64_t, H8, H8, DO_SRL, 0x3f, clearq) + +/* generate the helpers for shift instructions with one vector and one scalar */ +#define GEN_VEXT_SHIFT_VX(NAME, TD, TS2, HD, HS2, OP, MASK, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \ + void *vs2, CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t esz = sizeof(TD); \ + uint32_t vlmax = vext_maxsz(desc) / esz; \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + TS2 s2 = *((TS2 *)vs2 + HS2(i)); \ + *((TD *)vd + HD(i)) = OP(s2, s1 & MASK); \ + } \ + CLEAR_FN(vd, vl, vl * esz, vlmax * esz); \ +} + +GEN_VEXT_SHIFT_VX(vsll_vx_b, uint8_t, int8_t, H1, H1, DO_SLL, 0x7, clearb) +GEN_VEXT_SHIFT_VX(vsll_vx_h, uint16_t, int16_t, H2, H2, DO_SLL, 0xf, clearh) +GEN_VEXT_SHIFT_VX(vsll_vx_w, uint32_t, int32_t, H4, H4, DO_SLL, 0x1f, clearl) +GEN_VEXT_SHIFT_VX(vsll_vx_d, uint64_t, int64_t, H8, H8, DO_SLL, 0x3f, clearq) + +GEN_VEXT_SHIFT_VX(vsrl_vx_b, uint8_t, uint8_t, H1, H1, DO_SRL, 0x7, clearb) +GEN_VEXT_SHIFT_VX(vsrl_vx_h, uint16_t, uint16_t, H2, H2, DO_SRL, 0xf, clearh) +GEN_VEXT_SHIFT_VX(vsrl_vx_w, uint32_t, uint32_t, H4, H4, DO_SRL, 0x1f, clearl) +GEN_VEXT_SHIFT_VX(vsrl_vx_d, uint64_t, uint64_t, H8, H8, DO_SRL, 0x3f, clearq) + +GEN_VEXT_SHIFT_VX(vsra_vx_b, int8_t, int8_t, H1, H1, DO_SRL, 0x7, clearb) +GEN_VEXT_SHIFT_VX(vsra_vx_h, int16_t, int16_t, H2, H2, DO_SRL, 0xf, clearh) +GEN_VEXT_SHIFT_VX(vsra_vx_w, int32_t, int32_t, H4, H4, DO_SRL, 0x1f, clearl) +GEN_VEXT_SHIFT_VX(vsra_vx_d, int64_t, int64_t, H8, H8, DO_SRL, 0x3f, clearq) + +/* Vector Narrowing Integer Right Shift Instructions */ +GEN_VEXT_SHIFT_VV(vnsrl_vv_b, uint8_t, uint16_t, H1, H2, DO_SRL, 0xf, clearb) +GEN_VEXT_SHIFT_VV(vnsrl_vv_h, uint16_t, uint32_t, H2, H4, DO_SRL, 0x1f, clearh) +GEN_VEXT_SHIFT_VV(vnsrl_vv_w, uint32_t, uint64_t, H4, H8, DO_SRL, 0x3f, clearl) +GEN_VEXT_SHIFT_VV(vnsra_vv_b, uint8_t, int16_t, H1, H2, DO_SRL, 0xf, clearb) +GEN_VEXT_SHIFT_VV(vnsra_vv_h, uint16_t, int32_t, H2, H4, DO_SRL, 0x1f, clearh) +GEN_VEXT_SHIFT_VV(vnsra_vv_w, uint32_t, int64_t, H4, H8, DO_SRL, 0x3f, clearl) +GEN_VEXT_SHIFT_VX(vnsrl_vx_b, uint8_t, uint16_t, H1, H2, DO_SRL, 0xf, clearb) +GEN_VEXT_SHIFT_VX(vnsrl_vx_h, uint16_t, uint32_t, H2, H4, DO_SRL, 0x1f, clearh) +GEN_VEXT_SHIFT_VX(vnsrl_vx_w, uint32_t, uint64_t, H4, H8, DO_SRL, 0x3f, clearl) +GEN_VEXT_SHIFT_VX(vnsra_vx_b, int8_t, int16_t, H1, H2, DO_SRL, 0xf, clearb) +GEN_VEXT_SHIFT_VX(vnsra_vx_h, int16_t, int32_t, H2, H4, DO_SRL, 0x1f, clearh) +GEN_VEXT_SHIFT_VX(vnsra_vx_w, int32_t, int64_t, H4, H8, DO_SRL, 0x3f, clearl) + +/* Vector Integer Comparison Instructions */ +#define DO_MSEQ(N, M) (N == M) +#define DO_MSNE(N, M) (N != M) +#define DO_MSLT(N, M) (N < M) +#define DO_MSLE(N, M) (N <= M) +#define DO_MSGT(N, M) (N > M) + +#define GEN_VEXT_CMP_VV(NAME, ETYPE, H, DO_OP) \ +void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t vlmax = vext_maxsz(desc) / sizeof(ETYPE); \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + ETYPE s1 = *((ETYPE *)vs1 + H(i)); \ + ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + vext_set_elem_mask(vd, mlen, i, DO_OP(s2, s1)); \ + } \ + for (; i < vlmax; i++) { \ + vext_set_elem_mask(vd, mlen, i, 0); \ + } \ +} + +GEN_VEXT_CMP_VV(vmseq_vv_b, uint8_t, H1, DO_MSEQ) +GEN_VEXT_CMP_VV(vmseq_vv_h, uint16_t, H2, DO_MSEQ) +GEN_VEXT_CMP_VV(vmseq_vv_w, uint32_t, H4, DO_MSEQ) +GEN_VEXT_CMP_VV(vmseq_vv_d, uint64_t, H8, DO_MSEQ) + +GEN_VEXT_CMP_VV(vmsne_vv_b, uint8_t, H1, DO_MSNE) +GEN_VEXT_CMP_VV(vmsne_vv_h, uint16_t, H2, DO_MSNE) +GEN_VEXT_CMP_VV(vmsne_vv_w, uint32_t, H4, DO_MSNE) +GEN_VEXT_CMP_VV(vmsne_vv_d, uint64_t, H8, DO_MSNE) + +GEN_VEXT_CMP_VV(vmsltu_vv_b, uint8_t, H1, DO_MSLT) +GEN_VEXT_CMP_VV(vmsltu_vv_h, uint16_t, H2, DO_MSLT) +GEN_VEXT_CMP_VV(vmsltu_vv_w, uint32_t, H4, DO_MSLT) +GEN_VEXT_CMP_VV(vmsltu_vv_d, uint64_t, H8, DO_MSLT) + +GEN_VEXT_CMP_VV(vmslt_vv_b, int8_t, H1, DO_MSLT) +GEN_VEXT_CMP_VV(vmslt_vv_h, int16_t, H2, DO_MSLT) +GEN_VEXT_CMP_VV(vmslt_vv_w, int32_t, H4, DO_MSLT) +GEN_VEXT_CMP_VV(vmslt_vv_d, int64_t, H8, DO_MSLT) + +GEN_VEXT_CMP_VV(vmsleu_vv_b, uint8_t, H1, DO_MSLE) +GEN_VEXT_CMP_VV(vmsleu_vv_h, uint16_t, H2, DO_MSLE) +GEN_VEXT_CMP_VV(vmsleu_vv_w, uint32_t, H4, DO_MSLE) +GEN_VEXT_CMP_VV(vmsleu_vv_d, uint64_t, H8, DO_MSLE) + +GEN_VEXT_CMP_VV(vmsle_vv_b, int8_t, H1, DO_MSLE) +GEN_VEXT_CMP_VV(vmsle_vv_h, int16_t, H2, DO_MSLE) +GEN_VEXT_CMP_VV(vmsle_vv_w, int32_t, H4, DO_MSLE) +GEN_VEXT_CMP_VV(vmsle_vv_d, int64_t, H8, DO_MSLE) + +#define GEN_VEXT_CMP_VX(NAME, ETYPE, H, DO_OP) \ +void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t vlmax = vext_maxsz(desc) / sizeof(ETYPE); \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + vext_set_elem_mask(vd, mlen, i, \ + DO_OP(s2, (ETYPE)(target_long)s1)); \ + } \ + for (; i < vlmax; i++) { \ + vext_set_elem_mask(vd, mlen, i, 0); \ + } \ +} + +GEN_VEXT_CMP_VX(vmseq_vx_b, uint8_t, H1, DO_MSEQ) +GEN_VEXT_CMP_VX(vmseq_vx_h, uint16_t, H2, DO_MSEQ) +GEN_VEXT_CMP_VX(vmseq_vx_w, uint32_t, H4, DO_MSEQ) +GEN_VEXT_CMP_VX(vmseq_vx_d, uint64_t, H8, DO_MSEQ) + +GEN_VEXT_CMP_VX(vmsne_vx_b, uint8_t, H1, DO_MSNE) +GEN_VEXT_CMP_VX(vmsne_vx_h, uint16_t, H2, DO_MSNE) +GEN_VEXT_CMP_VX(vmsne_vx_w, uint32_t, H4, DO_MSNE) +GEN_VEXT_CMP_VX(vmsne_vx_d, uint64_t, H8, DO_MSNE) + +GEN_VEXT_CMP_VX(vmsltu_vx_b, uint8_t, H1, DO_MSLT) +GEN_VEXT_CMP_VX(vmsltu_vx_h, uint16_t, H2, DO_MSLT) +GEN_VEXT_CMP_VX(vmsltu_vx_w, uint32_t, H4, DO_MSLT) +GEN_VEXT_CMP_VX(vmsltu_vx_d, uint64_t, H8, DO_MSLT) + +GEN_VEXT_CMP_VX(vmslt_vx_b, int8_t, H1, DO_MSLT) +GEN_VEXT_CMP_VX(vmslt_vx_h, int16_t, H2, DO_MSLT) +GEN_VEXT_CMP_VX(vmslt_vx_w, int32_t, H4, DO_MSLT) +GEN_VEXT_CMP_VX(vmslt_vx_d, int64_t, H8, DO_MSLT) + +GEN_VEXT_CMP_VX(vmsleu_vx_b, uint8_t, H1, DO_MSLE) +GEN_VEXT_CMP_VX(vmsleu_vx_h, uint16_t, H2, DO_MSLE) +GEN_VEXT_CMP_VX(vmsleu_vx_w, uint32_t, H4, DO_MSLE) +GEN_VEXT_CMP_VX(vmsleu_vx_d, uint64_t, H8, DO_MSLE) + +GEN_VEXT_CMP_VX(vmsle_vx_b, int8_t, H1, DO_MSLE) +GEN_VEXT_CMP_VX(vmsle_vx_h, int16_t, H2, DO_MSLE) +GEN_VEXT_CMP_VX(vmsle_vx_w, int32_t, H4, DO_MSLE) +GEN_VEXT_CMP_VX(vmsle_vx_d, int64_t, H8, DO_MSLE) + +GEN_VEXT_CMP_VX(vmsgtu_vx_b, uint8_t, H1, DO_MSGT) +GEN_VEXT_CMP_VX(vmsgtu_vx_h, uint16_t, H2, DO_MSGT) +GEN_VEXT_CMP_VX(vmsgtu_vx_w, uint32_t, H4, DO_MSGT) +GEN_VEXT_CMP_VX(vmsgtu_vx_d, uint64_t, H8, DO_MSGT) + +GEN_VEXT_CMP_VX(vmsgt_vx_b, int8_t, H1, DO_MSGT) +GEN_VEXT_CMP_VX(vmsgt_vx_h, int16_t, H2, DO_MSGT) +GEN_VEXT_CMP_VX(vmsgt_vx_w, int32_t, H4, DO_MSGT) +GEN_VEXT_CMP_VX(vmsgt_vx_d, int64_t, H8, DO_MSGT) + +/* Vector Integer Min/Max Instructions */ +RVVCALL(OPIVV2, vminu_vv_b, OP_UUU_B, H1, H1, H1, DO_MIN) +RVVCALL(OPIVV2, vminu_vv_h, OP_UUU_H, H2, H2, H2, DO_MIN) +RVVCALL(OPIVV2, vminu_vv_w, OP_UUU_W, H4, H4, H4, DO_MIN) +RVVCALL(OPIVV2, vminu_vv_d, OP_UUU_D, H8, H8, H8, DO_MIN) +RVVCALL(OPIVV2, vmin_vv_b, OP_SSS_B, H1, H1, H1, DO_MIN) +RVVCALL(OPIVV2, vmin_vv_h, OP_SSS_H, H2, H2, H2, DO_MIN) +RVVCALL(OPIVV2, vmin_vv_w, OP_SSS_W, H4, H4, H4, DO_MIN) +RVVCALL(OPIVV2, vmin_vv_d, OP_SSS_D, H8, H8, H8, DO_MIN) +RVVCALL(OPIVV2, vmaxu_vv_b, OP_UUU_B, H1, H1, H1, DO_MAX) +RVVCALL(OPIVV2, vmaxu_vv_h, OP_UUU_H, H2, H2, H2, DO_MAX) +RVVCALL(OPIVV2, vmaxu_vv_w, OP_UUU_W, H4, H4, H4, DO_MAX) +RVVCALL(OPIVV2, vmaxu_vv_d, OP_UUU_D, H8, H8, H8, DO_MAX) +RVVCALL(OPIVV2, vmax_vv_b, OP_SSS_B, H1, H1, H1, DO_MAX) +RVVCALL(OPIVV2, vmax_vv_h, OP_SSS_H, H2, H2, H2, DO_MAX) +RVVCALL(OPIVV2, vmax_vv_w, OP_SSS_W, H4, H4, H4, DO_MAX) +RVVCALL(OPIVV2, vmax_vv_d, OP_SSS_D, H8, H8, H8, DO_MAX) +GEN_VEXT_VV(vminu_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vminu_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vminu_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vminu_vv_d, 8, 8, clearq) +GEN_VEXT_VV(vmin_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vmin_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vmin_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vmin_vv_d, 8, 8, clearq) +GEN_VEXT_VV(vmaxu_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vmaxu_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vmaxu_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vmaxu_vv_d, 8, 8, clearq) +GEN_VEXT_VV(vmax_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vmax_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vmax_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vmax_vv_d, 8, 8, clearq) + +RVVCALL(OPIVX2, vminu_vx_b, OP_UUU_B, H1, H1, DO_MIN) +RVVCALL(OPIVX2, vminu_vx_h, OP_UUU_H, H2, H2, DO_MIN) +RVVCALL(OPIVX2, vminu_vx_w, OP_UUU_W, H4, H4, DO_MIN) +RVVCALL(OPIVX2, vminu_vx_d, OP_UUU_D, H8, H8, DO_MIN) +RVVCALL(OPIVX2, vmin_vx_b, OP_SSS_B, H1, H1, DO_MIN) +RVVCALL(OPIVX2, vmin_vx_h, OP_SSS_H, H2, H2, DO_MIN) +RVVCALL(OPIVX2, vmin_vx_w, OP_SSS_W, H4, H4, DO_MIN) +RVVCALL(OPIVX2, vmin_vx_d, OP_SSS_D, H8, H8, DO_MIN) +RVVCALL(OPIVX2, vmaxu_vx_b, OP_UUU_B, H1, H1, DO_MAX) +RVVCALL(OPIVX2, vmaxu_vx_h, OP_UUU_H, H2, H2, DO_MAX) +RVVCALL(OPIVX2, vmaxu_vx_w, OP_UUU_W, H4, H4, DO_MAX) +RVVCALL(OPIVX2, vmaxu_vx_d, OP_UUU_D, H8, H8, DO_MAX) +RVVCALL(OPIVX2, vmax_vx_b, OP_SSS_B, H1, H1, DO_MAX) +RVVCALL(OPIVX2, vmax_vx_h, OP_SSS_H, H2, H2, DO_MAX) +RVVCALL(OPIVX2, vmax_vx_w, OP_SSS_W, H4, H4, DO_MAX) +RVVCALL(OPIVX2, vmax_vx_d, OP_SSS_D, H8, H8, DO_MAX) +GEN_VEXT_VX(vminu_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vminu_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vminu_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vminu_vx_d, 8, 8, clearq) +GEN_VEXT_VX(vmin_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vmin_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vmin_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vmin_vx_d, 8, 8, clearq) +GEN_VEXT_VX(vmaxu_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vmaxu_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vmaxu_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vmaxu_vx_d, 8, 8, clearq) +GEN_VEXT_VX(vmax_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vmax_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vmax_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vmax_vx_d, 8, 8, clearq) + +/* Vector Single-Width Integer Multiply Instructions */ +#define DO_MUL(N, M) (N * M) +RVVCALL(OPIVV2, vmul_vv_b, OP_SSS_B, H1, H1, H1, DO_MUL) +RVVCALL(OPIVV2, vmul_vv_h, OP_SSS_H, H2, H2, H2, DO_MUL) +RVVCALL(OPIVV2, vmul_vv_w, OP_SSS_W, H4, H4, H4, DO_MUL) +RVVCALL(OPIVV2, vmul_vv_d, OP_SSS_D, H8, H8, H8, DO_MUL) +GEN_VEXT_VV(vmul_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vmul_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vmul_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vmul_vv_d, 8, 8, clearq) + +static int8_t do_mulh_b(int8_t s2, int8_t s1) +{ + return (int16_t)s2 * (int16_t)s1 >> 8; +} + +static int16_t do_mulh_h(int16_t s2, int16_t s1) +{ + return (int32_t)s2 * (int32_t)s1 >> 16; +} + +static int32_t do_mulh_w(int32_t s2, int32_t s1) +{ + return (int64_t)s2 * (int64_t)s1 >> 32; +} + +static int64_t do_mulh_d(int64_t s2, int64_t s1) +{ + uint64_t hi_64, lo_64; + + muls64(&lo_64, &hi_64, s1, s2); + return hi_64; +} + +static uint8_t do_mulhu_b(uint8_t s2, uint8_t s1) +{ + return (uint16_t)s2 * (uint16_t)s1 >> 8; +} + +static uint16_t do_mulhu_h(uint16_t s2, uint16_t s1) +{ + return (uint32_t)s2 * (uint32_t)s1 >> 16; +} + +static uint32_t do_mulhu_w(uint32_t s2, uint32_t s1) +{ + return (uint64_t)s2 * (uint64_t)s1 >> 32; +} + +static uint64_t do_mulhu_d(uint64_t s2, uint64_t s1) +{ + uint64_t hi_64, lo_64; + + mulu64(&lo_64, &hi_64, s2, s1); + return hi_64; +} + +static int8_t do_mulhsu_b(int8_t s2, uint8_t s1) +{ + return (int16_t)s2 * (uint16_t)s1 >> 8; +} + +static int16_t do_mulhsu_h(int16_t s2, uint16_t s1) +{ + return (int32_t)s2 * (uint32_t)s1 >> 16; +} + +static int32_t do_mulhsu_w(int32_t s2, uint32_t s1) +{ + return (int64_t)s2 * (uint64_t)s1 >> 32; +} + +/* + * Let A = signed operand, + * B = unsigned operand + * P = mulu64(A, B), unsigned product + * + * LET X = 2 ** 64 - A, 2's complement of A + * SP = signed product + * THEN + * IF A < 0 + * SP = -X * B + * = -(2 ** 64 - A) * B + * = A * B - 2 ** 64 * B + * = P - 2 ** 64 * B + * ELSE + * SP = P + * THEN + * HI_P -= (A < 0 ? B : 0) + */ + +static int64_t do_mulhsu_d(int64_t s2, uint64_t s1) +{ + uint64_t hi_64, lo_64; + + mulu64(&lo_64, &hi_64, s2, s1); + + hi_64 -= s2 < 0 ? s1 : 0; + return hi_64; +} + +RVVCALL(OPIVV2, vmulh_vv_b, OP_SSS_B, H1, H1, H1, do_mulh_b) +RVVCALL(OPIVV2, vmulh_vv_h, OP_SSS_H, H2, H2, H2, do_mulh_h) +RVVCALL(OPIVV2, vmulh_vv_w, OP_SSS_W, H4, H4, H4, do_mulh_w) +RVVCALL(OPIVV2, vmulh_vv_d, OP_SSS_D, H8, H8, H8, do_mulh_d) +RVVCALL(OPIVV2, vmulhu_vv_b, OP_UUU_B, H1, H1, H1, do_mulhu_b) +RVVCALL(OPIVV2, vmulhu_vv_h, OP_UUU_H, H2, H2, H2, do_mulhu_h) +RVVCALL(OPIVV2, vmulhu_vv_w, OP_UUU_W, H4, H4, H4, do_mulhu_w) +RVVCALL(OPIVV2, vmulhu_vv_d, OP_UUU_D, H8, H8, H8, do_mulhu_d) +RVVCALL(OPIVV2, vmulhsu_vv_b, OP_SUS_B, H1, H1, H1, do_mulhsu_b) +RVVCALL(OPIVV2, vmulhsu_vv_h, OP_SUS_H, H2, H2, H2, do_mulhsu_h) +RVVCALL(OPIVV2, vmulhsu_vv_w, OP_SUS_W, H4, H4, H4, do_mulhsu_w) +RVVCALL(OPIVV2, vmulhsu_vv_d, OP_SUS_D, H8, H8, H8, do_mulhsu_d) +GEN_VEXT_VV(vmulh_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vmulh_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vmulh_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vmulh_vv_d, 8, 8, clearq) +GEN_VEXT_VV(vmulhu_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vmulhu_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vmulhu_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vmulhu_vv_d, 8, 8, clearq) +GEN_VEXT_VV(vmulhsu_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vmulhsu_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vmulhsu_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vmulhsu_vv_d, 8, 8, clearq) + +RVVCALL(OPIVX2, vmul_vx_b, OP_SSS_B, H1, H1, DO_MUL) +RVVCALL(OPIVX2, vmul_vx_h, OP_SSS_H, H2, H2, DO_MUL) +RVVCALL(OPIVX2, vmul_vx_w, OP_SSS_W, H4, H4, DO_MUL) +RVVCALL(OPIVX2, vmul_vx_d, OP_SSS_D, H8, H8, DO_MUL) +RVVCALL(OPIVX2, vmulh_vx_b, OP_SSS_B, H1, H1, do_mulh_b) +RVVCALL(OPIVX2, vmulh_vx_h, OP_SSS_H, H2, H2, do_mulh_h) +RVVCALL(OPIVX2, vmulh_vx_w, OP_SSS_W, H4, H4, do_mulh_w) +RVVCALL(OPIVX2, vmulh_vx_d, OP_SSS_D, H8, H8, do_mulh_d) +RVVCALL(OPIVX2, vmulhu_vx_b, OP_UUU_B, H1, H1, do_mulhu_b) +RVVCALL(OPIVX2, vmulhu_vx_h, OP_UUU_H, H2, H2, do_mulhu_h) +RVVCALL(OPIVX2, vmulhu_vx_w, OP_UUU_W, H4, H4, do_mulhu_w) +RVVCALL(OPIVX2, vmulhu_vx_d, OP_UUU_D, H8, H8, do_mulhu_d) +RVVCALL(OPIVX2, vmulhsu_vx_b, OP_SUS_B, H1, H1, do_mulhsu_b) +RVVCALL(OPIVX2, vmulhsu_vx_h, OP_SUS_H, H2, H2, do_mulhsu_h) +RVVCALL(OPIVX2, vmulhsu_vx_w, OP_SUS_W, H4, H4, do_mulhsu_w) +RVVCALL(OPIVX2, vmulhsu_vx_d, OP_SUS_D, H8, H8, do_mulhsu_d) +GEN_VEXT_VX(vmul_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vmul_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vmul_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vmul_vx_d, 8, 8, clearq) +GEN_VEXT_VX(vmulh_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vmulh_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vmulh_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vmulh_vx_d, 8, 8, clearq) +GEN_VEXT_VX(vmulhu_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vmulhu_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vmulhu_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vmulhu_vx_d, 8, 8, clearq) +GEN_VEXT_VX(vmulhsu_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vmulhsu_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vmulhsu_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vmulhsu_vx_d, 8, 8, clearq) + +/* Vector Integer Divide Instructions */ +#define DO_DIVU(N, M) (unlikely(M == 0) ? (__typeof(N))(-1) : N / M) +#define DO_REMU(N, M) (unlikely(M == 0) ? N : N % M) +#define DO_DIV(N, M) (unlikely(M == 0) ? (__typeof(N))(-1) :\ + unlikely((N == -N) && (M == (__typeof(N))(-1))) ? N : N / M) +#define DO_REM(N, M) (unlikely(M == 0) ? N :\ + unlikely((N == -N) && (M == (__typeof(N))(-1))) ? 0 : N % M) + +RVVCALL(OPIVV2, vdivu_vv_b, OP_UUU_B, H1, H1, H1, DO_DIVU) +RVVCALL(OPIVV2, vdivu_vv_h, OP_UUU_H, H2, H2, H2, DO_DIVU) +RVVCALL(OPIVV2, vdivu_vv_w, OP_UUU_W, H4, H4, H4, DO_DIVU) +RVVCALL(OPIVV2, vdivu_vv_d, OP_UUU_D, H8, H8, H8, DO_DIVU) +RVVCALL(OPIVV2, vdiv_vv_b, OP_SSS_B, H1, H1, H1, DO_DIV) +RVVCALL(OPIVV2, vdiv_vv_h, OP_SSS_H, H2, H2, H2, DO_DIV) +RVVCALL(OPIVV2, vdiv_vv_w, OP_SSS_W, H4, H4, H4, DO_DIV) +RVVCALL(OPIVV2, vdiv_vv_d, OP_SSS_D, H8, H8, H8, DO_DIV) +RVVCALL(OPIVV2, vremu_vv_b, OP_UUU_B, H1, H1, H1, DO_REMU) +RVVCALL(OPIVV2, vremu_vv_h, OP_UUU_H, H2, H2, H2, DO_REMU) +RVVCALL(OPIVV2, vremu_vv_w, OP_UUU_W, H4, H4, H4, DO_REMU) +RVVCALL(OPIVV2, vremu_vv_d, OP_UUU_D, H8, H8, H8, DO_REMU) +RVVCALL(OPIVV2, vrem_vv_b, OP_SSS_B, H1, H1, H1, DO_REM) +RVVCALL(OPIVV2, vrem_vv_h, OP_SSS_H, H2, H2, H2, DO_REM) +RVVCALL(OPIVV2, vrem_vv_w, OP_SSS_W, H4, H4, H4, DO_REM) +RVVCALL(OPIVV2, vrem_vv_d, OP_SSS_D, H8, H8, H8, DO_REM) +GEN_VEXT_VV(vdivu_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vdivu_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vdivu_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vdivu_vv_d, 8, 8, clearq) +GEN_VEXT_VV(vdiv_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vdiv_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vdiv_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vdiv_vv_d, 8, 8, clearq) +GEN_VEXT_VV(vremu_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vremu_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vremu_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vremu_vv_d, 8, 8, clearq) +GEN_VEXT_VV(vrem_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vrem_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vrem_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vrem_vv_d, 8, 8, clearq) + +RVVCALL(OPIVX2, vdivu_vx_b, OP_UUU_B, H1, H1, DO_DIVU) +RVVCALL(OPIVX2, vdivu_vx_h, OP_UUU_H, H2, H2, DO_DIVU) +RVVCALL(OPIVX2, vdivu_vx_w, OP_UUU_W, H4, H4, DO_DIVU) +RVVCALL(OPIVX2, vdivu_vx_d, OP_UUU_D, H8, H8, DO_DIVU) +RVVCALL(OPIVX2, vdiv_vx_b, OP_SSS_B, H1, H1, DO_DIV) +RVVCALL(OPIVX2, vdiv_vx_h, OP_SSS_H, H2, H2, DO_DIV) +RVVCALL(OPIVX2, vdiv_vx_w, OP_SSS_W, H4, H4, DO_DIV) +RVVCALL(OPIVX2, vdiv_vx_d, OP_SSS_D, H8, H8, DO_DIV) +RVVCALL(OPIVX2, vremu_vx_b, OP_UUU_B, H1, H1, DO_REMU) +RVVCALL(OPIVX2, vremu_vx_h, OP_UUU_H, H2, H2, DO_REMU) +RVVCALL(OPIVX2, vremu_vx_w, OP_UUU_W, H4, H4, DO_REMU) +RVVCALL(OPIVX2, vremu_vx_d, OP_UUU_D, H8, H8, DO_REMU) +RVVCALL(OPIVX2, vrem_vx_b, OP_SSS_B, H1, H1, DO_REM) +RVVCALL(OPIVX2, vrem_vx_h, OP_SSS_H, H2, H2, DO_REM) +RVVCALL(OPIVX2, vrem_vx_w, OP_SSS_W, H4, H4, DO_REM) +RVVCALL(OPIVX2, vrem_vx_d, OP_SSS_D, H8, H8, DO_REM) +GEN_VEXT_VX(vdivu_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vdivu_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vdivu_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vdivu_vx_d, 8, 8, clearq) +GEN_VEXT_VX(vdiv_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vdiv_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vdiv_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vdiv_vx_d, 8, 8, clearq) +GEN_VEXT_VX(vremu_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vremu_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vremu_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vremu_vx_d, 8, 8, clearq) +GEN_VEXT_VX(vrem_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vrem_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vrem_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vrem_vx_d, 8, 8, clearq) + +/* Vector Widening Integer Multiply Instructions */ +RVVCALL(OPIVV2, vwmul_vv_b, WOP_SSS_B, H2, H1, H1, DO_MUL) +RVVCALL(OPIVV2, vwmul_vv_h, WOP_SSS_H, H4, H2, H2, DO_MUL) +RVVCALL(OPIVV2, vwmul_vv_w, WOP_SSS_W, H8, H4, H4, DO_MUL) +RVVCALL(OPIVV2, vwmulu_vv_b, WOP_UUU_B, H2, H1, H1, DO_MUL) +RVVCALL(OPIVV2, vwmulu_vv_h, WOP_UUU_H, H4, H2, H2, DO_MUL) +RVVCALL(OPIVV2, vwmulu_vv_w, WOP_UUU_W, H8, H4, H4, DO_MUL) +RVVCALL(OPIVV2, vwmulsu_vv_b, WOP_SUS_B, H2, H1, H1, DO_MUL) +RVVCALL(OPIVV2, vwmulsu_vv_h, WOP_SUS_H, H4, H2, H2, DO_MUL) +RVVCALL(OPIVV2, vwmulsu_vv_w, WOP_SUS_W, H8, H4, H4, DO_MUL) +GEN_VEXT_VV(vwmul_vv_b, 1, 2, clearh) +GEN_VEXT_VV(vwmul_vv_h, 2, 4, clearl) +GEN_VEXT_VV(vwmul_vv_w, 4, 8, clearq) +GEN_VEXT_VV(vwmulu_vv_b, 1, 2, clearh) +GEN_VEXT_VV(vwmulu_vv_h, 2, 4, clearl) +GEN_VEXT_VV(vwmulu_vv_w, 4, 8, clearq) +GEN_VEXT_VV(vwmulsu_vv_b, 1, 2, clearh) +GEN_VEXT_VV(vwmulsu_vv_h, 2, 4, clearl) +GEN_VEXT_VV(vwmulsu_vv_w, 4, 8, clearq) + +RVVCALL(OPIVX2, vwmul_vx_b, WOP_SSS_B, H2, H1, DO_MUL) +RVVCALL(OPIVX2, vwmul_vx_h, WOP_SSS_H, H4, H2, DO_MUL) +RVVCALL(OPIVX2, vwmul_vx_w, WOP_SSS_W, H8, H4, DO_MUL) +RVVCALL(OPIVX2, vwmulu_vx_b, WOP_UUU_B, H2, H1, DO_MUL) +RVVCALL(OPIVX2, vwmulu_vx_h, WOP_UUU_H, H4, H2, DO_MUL) +RVVCALL(OPIVX2, vwmulu_vx_w, WOP_UUU_W, H8, H4, DO_MUL) +RVVCALL(OPIVX2, vwmulsu_vx_b, WOP_SUS_B, H2, H1, DO_MUL) +RVVCALL(OPIVX2, vwmulsu_vx_h, WOP_SUS_H, H4, H2, DO_MUL) +RVVCALL(OPIVX2, vwmulsu_vx_w, WOP_SUS_W, H8, H4, DO_MUL) +GEN_VEXT_VX(vwmul_vx_b, 1, 2, clearh) +GEN_VEXT_VX(vwmul_vx_h, 2, 4, clearl) +GEN_VEXT_VX(vwmul_vx_w, 4, 8, clearq) +GEN_VEXT_VX(vwmulu_vx_b, 1, 2, clearh) +GEN_VEXT_VX(vwmulu_vx_h, 2, 4, clearl) +GEN_VEXT_VX(vwmulu_vx_w, 4, 8, clearq) +GEN_VEXT_VX(vwmulsu_vx_b, 1, 2, clearh) +GEN_VEXT_VX(vwmulsu_vx_h, 2, 4, clearl) +GEN_VEXT_VX(vwmulsu_vx_w, 4, 8, clearq) + +/* Vector Single-Width Integer Multiply-Add Instructions */ +#define OPIVV3(NAME, TD, T1, T2, TX1, TX2, HD, HS1, HS2, OP) \ +static void do_##NAME(void *vd, void *vs1, void *vs2, int i) \ +{ \ + TX1 s1 = *((T1 *)vs1 + HS1(i)); \ + TX2 s2 = *((T2 *)vs2 + HS2(i)); \ + TD d = *((TD *)vd + HD(i)); \ + *((TD *)vd + HD(i)) = OP(s2, s1, d); \ +} + +#define DO_MACC(N, M, D) (M * N + D) +#define DO_NMSAC(N, M, D) (-(M * N) + D) +#define DO_MADD(N, M, D) (M * D + N) +#define DO_NMSUB(N, M, D) (-(M * D) + N) +RVVCALL(OPIVV3, vmacc_vv_b, OP_SSS_B, H1, H1, H1, DO_MACC) +RVVCALL(OPIVV3, vmacc_vv_h, OP_SSS_H, H2, H2, H2, DO_MACC) +RVVCALL(OPIVV3, vmacc_vv_w, OP_SSS_W, H4, H4, H4, DO_MACC) +RVVCALL(OPIVV3, vmacc_vv_d, OP_SSS_D, H8, H8, H8, DO_MACC) +RVVCALL(OPIVV3, vnmsac_vv_b, OP_SSS_B, H1, H1, H1, DO_NMSAC) +RVVCALL(OPIVV3, vnmsac_vv_h, OP_SSS_H, H2, H2, H2, DO_NMSAC) +RVVCALL(OPIVV3, vnmsac_vv_w, OP_SSS_W, H4, H4, H4, DO_NMSAC) +RVVCALL(OPIVV3, vnmsac_vv_d, OP_SSS_D, H8, H8, H8, DO_NMSAC) +RVVCALL(OPIVV3, vmadd_vv_b, OP_SSS_B, H1, H1, H1, DO_MADD) +RVVCALL(OPIVV3, vmadd_vv_h, OP_SSS_H, H2, H2, H2, DO_MADD) +RVVCALL(OPIVV3, vmadd_vv_w, OP_SSS_W, H4, H4, H4, DO_MADD) +RVVCALL(OPIVV3, vmadd_vv_d, OP_SSS_D, H8, H8, H8, DO_MADD) +RVVCALL(OPIVV3, vnmsub_vv_b, OP_SSS_B, H1, H1, H1, DO_NMSUB) +RVVCALL(OPIVV3, vnmsub_vv_h, OP_SSS_H, H2, H2, H2, DO_NMSUB) +RVVCALL(OPIVV3, vnmsub_vv_w, OP_SSS_W, H4, H4, H4, DO_NMSUB) +RVVCALL(OPIVV3, vnmsub_vv_d, OP_SSS_D, H8, H8, H8, DO_NMSUB) +GEN_VEXT_VV(vmacc_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vmacc_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vmacc_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vmacc_vv_d, 8, 8, clearq) +GEN_VEXT_VV(vnmsac_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vnmsac_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vnmsac_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vnmsac_vv_d, 8, 8, clearq) +GEN_VEXT_VV(vmadd_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vmadd_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vmadd_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vmadd_vv_d, 8, 8, clearq) +GEN_VEXT_VV(vnmsub_vv_b, 1, 1, clearb) +GEN_VEXT_VV(vnmsub_vv_h, 2, 2, clearh) +GEN_VEXT_VV(vnmsub_vv_w, 4, 4, clearl) +GEN_VEXT_VV(vnmsub_vv_d, 8, 8, clearq) + +#define OPIVX3(NAME, TD, T1, T2, TX1, TX2, HD, HS2, OP) \ +static void do_##NAME(void *vd, target_long s1, void *vs2, int i) \ +{ \ + TX2 s2 = *((T2 *)vs2 + HS2(i)); \ + TD d = *((TD *)vd + HD(i)); \ + *((TD *)vd + HD(i)) = OP(s2, (TX1)(T1)s1, d); \ +} + +RVVCALL(OPIVX3, vmacc_vx_b, OP_SSS_B, H1, H1, DO_MACC) +RVVCALL(OPIVX3, vmacc_vx_h, OP_SSS_H, H2, H2, DO_MACC) +RVVCALL(OPIVX3, vmacc_vx_w, OP_SSS_W, H4, H4, DO_MACC) +RVVCALL(OPIVX3, vmacc_vx_d, OP_SSS_D, H8, H8, DO_MACC) +RVVCALL(OPIVX3, vnmsac_vx_b, OP_SSS_B, H1, H1, DO_NMSAC) +RVVCALL(OPIVX3, vnmsac_vx_h, OP_SSS_H, H2, H2, DO_NMSAC) +RVVCALL(OPIVX3, vnmsac_vx_w, OP_SSS_W, H4, H4, DO_NMSAC) +RVVCALL(OPIVX3, vnmsac_vx_d, OP_SSS_D, H8, H8, DO_NMSAC) +RVVCALL(OPIVX3, vmadd_vx_b, OP_SSS_B, H1, H1, DO_MADD) +RVVCALL(OPIVX3, vmadd_vx_h, OP_SSS_H, H2, H2, DO_MADD) +RVVCALL(OPIVX3, vmadd_vx_w, OP_SSS_W, H4, H4, DO_MADD) +RVVCALL(OPIVX3, vmadd_vx_d, OP_SSS_D, H8, H8, DO_MADD) +RVVCALL(OPIVX3, vnmsub_vx_b, OP_SSS_B, H1, H1, DO_NMSUB) +RVVCALL(OPIVX3, vnmsub_vx_h, OP_SSS_H, H2, H2, DO_NMSUB) +RVVCALL(OPIVX3, vnmsub_vx_w, OP_SSS_W, H4, H4, DO_NMSUB) +RVVCALL(OPIVX3, vnmsub_vx_d, OP_SSS_D, H8, H8, DO_NMSUB) +GEN_VEXT_VX(vmacc_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vmacc_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vmacc_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vmacc_vx_d, 8, 8, clearq) +GEN_VEXT_VX(vnmsac_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vnmsac_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vnmsac_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vnmsac_vx_d, 8, 8, clearq) +GEN_VEXT_VX(vmadd_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vmadd_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vmadd_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vmadd_vx_d, 8, 8, clearq) +GEN_VEXT_VX(vnmsub_vx_b, 1, 1, clearb) +GEN_VEXT_VX(vnmsub_vx_h, 2, 2, clearh) +GEN_VEXT_VX(vnmsub_vx_w, 4, 4, clearl) +GEN_VEXT_VX(vnmsub_vx_d, 8, 8, clearq) + +/* Vector Widening Integer Multiply-Add Instructions */ +RVVCALL(OPIVV3, vwmaccu_vv_b, WOP_UUU_B, H2, H1, H1, DO_MACC) +RVVCALL(OPIVV3, vwmaccu_vv_h, WOP_UUU_H, H4, H2, H2, DO_MACC) +RVVCALL(OPIVV3, vwmaccu_vv_w, WOP_UUU_W, H8, H4, H4, DO_MACC) +RVVCALL(OPIVV3, vwmacc_vv_b, WOP_SSS_B, H2, H1, H1, DO_MACC) +RVVCALL(OPIVV3, vwmacc_vv_h, WOP_SSS_H, H4, H2, H2, DO_MACC) +RVVCALL(OPIVV3, vwmacc_vv_w, WOP_SSS_W, H8, H4, H4, DO_MACC) +RVVCALL(OPIVV3, vwmaccsu_vv_b, WOP_SSU_B, H2, H1, H1, DO_MACC) +RVVCALL(OPIVV3, vwmaccsu_vv_h, WOP_SSU_H, H4, H2, H2, DO_MACC) +RVVCALL(OPIVV3, vwmaccsu_vv_w, WOP_SSU_W, H8, H4, H4, DO_MACC) +GEN_VEXT_VV(vwmaccu_vv_b, 1, 2, clearh) +GEN_VEXT_VV(vwmaccu_vv_h, 2, 4, clearl) +GEN_VEXT_VV(vwmaccu_vv_w, 4, 8, clearq) +GEN_VEXT_VV(vwmacc_vv_b, 1, 2, clearh) +GEN_VEXT_VV(vwmacc_vv_h, 2, 4, clearl) +GEN_VEXT_VV(vwmacc_vv_w, 4, 8, clearq) +GEN_VEXT_VV(vwmaccsu_vv_b, 1, 2, clearh) +GEN_VEXT_VV(vwmaccsu_vv_h, 2, 4, clearl) +GEN_VEXT_VV(vwmaccsu_vv_w, 4, 8, clearq) + +RVVCALL(OPIVX3, vwmaccu_vx_b, WOP_UUU_B, H2, H1, DO_MACC) +RVVCALL(OPIVX3, vwmaccu_vx_h, WOP_UUU_H, H4, H2, DO_MACC) +RVVCALL(OPIVX3, vwmaccu_vx_w, WOP_UUU_W, H8, H4, DO_MACC) +RVVCALL(OPIVX3, vwmacc_vx_b, WOP_SSS_B, H2, H1, DO_MACC) +RVVCALL(OPIVX3, vwmacc_vx_h, WOP_SSS_H, H4, H2, DO_MACC) +RVVCALL(OPIVX3, vwmacc_vx_w, WOP_SSS_W, H8, H4, DO_MACC) +RVVCALL(OPIVX3, vwmaccsu_vx_b, WOP_SSU_B, H2, H1, DO_MACC) +RVVCALL(OPIVX3, vwmaccsu_vx_h, WOP_SSU_H, H4, H2, DO_MACC) +RVVCALL(OPIVX3, vwmaccsu_vx_w, WOP_SSU_W, H8, H4, DO_MACC) +RVVCALL(OPIVX3, vwmaccus_vx_b, WOP_SUS_B, H2, H1, DO_MACC) +RVVCALL(OPIVX3, vwmaccus_vx_h, WOP_SUS_H, H4, H2, DO_MACC) +RVVCALL(OPIVX3, vwmaccus_vx_w, WOP_SUS_W, H8, H4, DO_MACC) +GEN_VEXT_VX(vwmaccu_vx_b, 1, 2, clearh) +GEN_VEXT_VX(vwmaccu_vx_h, 2, 4, clearl) +GEN_VEXT_VX(vwmaccu_vx_w, 4, 8, clearq) +GEN_VEXT_VX(vwmacc_vx_b, 1, 2, clearh) +GEN_VEXT_VX(vwmacc_vx_h, 2, 4, clearl) +GEN_VEXT_VX(vwmacc_vx_w, 4, 8, clearq) +GEN_VEXT_VX(vwmaccsu_vx_b, 1, 2, clearh) +GEN_VEXT_VX(vwmaccsu_vx_h, 2, 4, clearl) +GEN_VEXT_VX(vwmaccsu_vx_w, 4, 8, clearq) +GEN_VEXT_VX(vwmaccus_vx_b, 1, 2, clearh) +GEN_VEXT_VX(vwmaccus_vx_h, 2, 4, clearl) +GEN_VEXT_VX(vwmaccus_vx_w, 4, 8, clearq) + +/* Vector Integer Merge and Move Instructions */ +#define GEN_VEXT_VMV_VV(NAME, ETYPE, H, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *vs1, CPURISCVState *env, \ + uint32_t desc) \ +{ \ + uint32_t vl = env->vl; \ + uint32_t esz = sizeof(ETYPE); \ + uint32_t vlmax = vext_maxsz(desc) / esz; \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + ETYPE s1 = *((ETYPE *)vs1 + H(i)); \ + *((ETYPE *)vd + H(i)) = s1; \ + } \ + CLEAR_FN(vd, vl, vl * esz, vlmax * esz); \ +} + +GEN_VEXT_VMV_VV(vmv_v_v_b, int8_t, H1, clearb) +GEN_VEXT_VMV_VV(vmv_v_v_h, int16_t, H2, clearh) +GEN_VEXT_VMV_VV(vmv_v_v_w, int32_t, H4, clearl) +GEN_VEXT_VMV_VV(vmv_v_v_d, int64_t, H8, clearq) + +#define GEN_VEXT_VMV_VX(NAME, ETYPE, H, CLEAR_FN) \ +void HELPER(NAME)(void *vd, uint64_t s1, CPURISCVState *env, \ + uint32_t desc) \ +{ \ + uint32_t vl = env->vl; \ + uint32_t esz = sizeof(ETYPE); \ + uint32_t vlmax = vext_maxsz(desc) / esz; \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + *((ETYPE *)vd + H(i)) = (ETYPE)s1; \ + } \ + CLEAR_FN(vd, vl, vl * esz, vlmax * esz); \ +} + +GEN_VEXT_VMV_VX(vmv_v_x_b, int8_t, H1, clearb) +GEN_VEXT_VMV_VX(vmv_v_x_h, int16_t, H2, clearh) +GEN_VEXT_VMV_VX(vmv_v_x_w, int32_t, H4, clearl) +GEN_VEXT_VMV_VX(vmv_v_x_d, int64_t, H8, clearq) + +#define GEN_VEXT_VMERGE_VV(NAME, ETYPE, H, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vl = env->vl; \ + uint32_t esz = sizeof(ETYPE); \ + uint32_t vlmax = vext_maxsz(desc) / esz; \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + ETYPE *vt = (!vext_elem_mask(v0, mlen, i) ? vs2 : vs1); \ + *((ETYPE *)vd + H(i)) = *(vt + H(i)); \ + } \ + CLEAR_FN(vd, vl, vl * esz, vlmax * esz); \ +} + +GEN_VEXT_VMERGE_VV(vmerge_vvm_b, int8_t, H1, clearb) +GEN_VEXT_VMERGE_VV(vmerge_vvm_h, int16_t, H2, clearh) +GEN_VEXT_VMERGE_VV(vmerge_vvm_w, int32_t, H4, clearl) +GEN_VEXT_VMERGE_VV(vmerge_vvm_d, int64_t, H8, clearq) + +#define GEN_VEXT_VMERGE_VX(NAME, ETYPE, H, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \ + void *vs2, CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vl = env->vl; \ + uint32_t esz = sizeof(ETYPE); \ + uint32_t vlmax = vext_maxsz(desc) / esz; \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ + ETYPE d = (!vext_elem_mask(v0, mlen, i) ? s2 : \ + (ETYPE)(target_long)s1); \ + *((ETYPE *)vd + H(i)) = d; \ + } \ + CLEAR_FN(vd, vl, vl * esz, vlmax * esz); \ +} + +GEN_VEXT_VMERGE_VX(vmerge_vxm_b, int8_t, H1, clearb) +GEN_VEXT_VMERGE_VX(vmerge_vxm_h, int16_t, H2, clearh) +GEN_VEXT_VMERGE_VX(vmerge_vxm_w, int32_t, H4, clearl) +GEN_VEXT_VMERGE_VX(vmerge_vxm_d, int64_t, H8, clearq) + +/* + *** Vector Fixed-Point Arithmetic Instructions + */ + +/* Vector Single-Width Saturating Add and Subtract */ + +/* + * As fixed point instructions probably have round mode and saturation, + * define common macros for fixed point here. + */ +typedef void opivv2_rm_fn(void *vd, void *vs1, void *vs2, int i, + CPURISCVState *env, int vxrm); + +#define OPIVV2_RM(NAME, TD, T1, T2, TX1, TX2, HD, HS1, HS2, OP) \ +static inline void \ +do_##NAME(void *vd, void *vs1, void *vs2, int i, \ + CPURISCVState *env, int vxrm) \ +{ \ + TX1 s1 = *((T1 *)vs1 + HS1(i)); \ + TX2 s2 = *((T2 *)vs2 + HS2(i)); \ + *((TD *)vd + HD(i)) = OP(env, vxrm, s2, s1); \ +} + +static inline void +vext_vv_rm_1(void *vd, void *v0, void *vs1, void *vs2, + CPURISCVState *env, + uint32_t vl, uint32_t vm, uint32_t mlen, int vxrm, + opivv2_rm_fn *fn) +{ + for (uint32_t i = 0; i < vl; i++) { + if (!vm && !vext_elem_mask(v0, mlen, i)) { + continue; + } + fn(vd, vs1, vs2, i, env, vxrm); + } +} + +static inline void +vext_vv_rm_2(void *vd, void *v0, void *vs1, void *vs2, + CPURISCVState *env, + uint32_t desc, uint32_t esz, uint32_t dsz, + opivv2_rm_fn *fn, clear_fn *clearfn) +{ + uint32_t vlmax = vext_maxsz(desc) / esz; + uint32_t mlen = vext_mlen(desc); + uint32_t vm = vext_vm(desc); + uint32_t vl = env->vl; + + switch (env->vxrm) { + case 0: /* rnu */ + vext_vv_rm_1(vd, v0, vs1, vs2, + env, vl, vm, mlen, 0, fn); + break; + case 1: /* rne */ + vext_vv_rm_1(vd, v0, vs1, vs2, + env, vl, vm, mlen, 1, fn); + break; + case 2: /* rdn */ + vext_vv_rm_1(vd, v0, vs1, vs2, + env, vl, vm, mlen, 2, fn); + break; + default: /* rod */ + vext_vv_rm_1(vd, v0, vs1, vs2, + env, vl, vm, mlen, 3, fn); + break; + } + + clearfn(vd, vl, vl * dsz, vlmax * dsz); +} + +/* generate helpers for fixed point instructions with OPIVV format */ +#define GEN_VEXT_VV_RM(NAME, ESZ, DSZ, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + vext_vv_rm_2(vd, v0, vs1, vs2, env, desc, ESZ, DSZ, \ + do_##NAME, CLEAR_FN); \ +} + +static inline uint8_t saddu8(CPURISCVState *env, int vxrm, uint8_t a, uint8_t b) +{ + uint8_t res = a + b; + if (res < a) { + res = UINT8_MAX; + env->vxsat = 0x1; + } + return res; +} + +static inline uint16_t saddu16(CPURISCVState *env, int vxrm, uint16_t a, + uint16_t b) +{ + uint16_t res = a + b; + if (res < a) { + res = UINT16_MAX; + env->vxsat = 0x1; + } + return res; +} + +static inline uint32_t saddu32(CPURISCVState *env, int vxrm, uint32_t a, + uint32_t b) +{ + uint32_t res = a + b; + if (res < a) { + res = UINT32_MAX; + env->vxsat = 0x1; + } + return res; +} + +static inline uint64_t saddu64(CPURISCVState *env, int vxrm, uint64_t a, + uint64_t b) +{ + uint64_t res = a + b; + if (res < a) { + res = UINT64_MAX; + env->vxsat = 0x1; + } + return res; +} + +RVVCALL(OPIVV2_RM, vsaddu_vv_b, OP_UUU_B, H1, H1, H1, saddu8) +RVVCALL(OPIVV2_RM, vsaddu_vv_h, OP_UUU_H, H2, H2, H2, saddu16) +RVVCALL(OPIVV2_RM, vsaddu_vv_w, OP_UUU_W, H4, H4, H4, saddu32) +RVVCALL(OPIVV2_RM, vsaddu_vv_d, OP_UUU_D, H8, H8, H8, saddu64) +GEN_VEXT_VV_RM(vsaddu_vv_b, 1, 1, clearb) +GEN_VEXT_VV_RM(vsaddu_vv_h, 2, 2, clearh) +GEN_VEXT_VV_RM(vsaddu_vv_w, 4, 4, clearl) +GEN_VEXT_VV_RM(vsaddu_vv_d, 8, 8, clearq) + +typedef void opivx2_rm_fn(void *vd, target_long s1, void *vs2, int i, + CPURISCVState *env, int vxrm); + +#define OPIVX2_RM(NAME, TD, T1, T2, TX1, TX2, HD, HS2, OP) \ +static inline void \ +do_##NAME(void *vd, target_long s1, void *vs2, int i, \ + CPURISCVState *env, int vxrm) \ +{ \ + TX2 s2 = *((T2 *)vs2 + HS2(i)); \ + *((TD *)vd + HD(i)) = OP(env, vxrm, s2, (TX1)(T1)s1); \ +} + +static inline void +vext_vx_rm_1(void *vd, void *v0, target_long s1, void *vs2, + CPURISCVState *env, + uint32_t vl, uint32_t vm, uint32_t mlen, int vxrm, + opivx2_rm_fn *fn) +{ + for (uint32_t i = 0; i < vl; i++) { + if (!vm && !vext_elem_mask(v0, mlen, i)) { + continue; + } + fn(vd, s1, vs2, i, env, vxrm); + } +} + +static inline void +vext_vx_rm_2(void *vd, void *v0, target_long s1, void *vs2, + CPURISCVState *env, + uint32_t desc, uint32_t esz, uint32_t dsz, + opivx2_rm_fn *fn, clear_fn *clearfn) +{ + uint32_t vlmax = vext_maxsz(desc) / esz; + uint32_t mlen = vext_mlen(desc); + uint32_t vm = vext_vm(desc); + uint32_t vl = env->vl; + + switch (env->vxrm) { + case 0: /* rnu */ + vext_vx_rm_1(vd, v0, s1, vs2, + env, vl, vm, mlen, 0, fn); + break; + case 1: /* rne */ + vext_vx_rm_1(vd, v0, s1, vs2, + env, vl, vm, mlen, 1, fn); + break; + case 2: /* rdn */ + vext_vx_rm_1(vd, v0, s1, vs2, + env, vl, vm, mlen, 2, fn); + break; + default: /* rod */ + vext_vx_rm_1(vd, v0, s1, vs2, + env, vl, vm, mlen, 3, fn); + break; + } + + clearfn(vd, vl, vl * dsz, vlmax * dsz); +} + +/* generate helpers for fixed point instructions with OPIVX format */ +#define GEN_VEXT_VX_RM(NAME, ESZ, DSZ, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \ + void *vs2, CPURISCVState *env, uint32_t desc) \ +{ \ + vext_vx_rm_2(vd, v0, s1, vs2, env, desc, ESZ, DSZ, \ + do_##NAME, CLEAR_FN); \ +} + +RVVCALL(OPIVX2_RM, vsaddu_vx_b, OP_UUU_B, H1, H1, saddu8) +RVVCALL(OPIVX2_RM, vsaddu_vx_h, OP_UUU_H, H2, H2, saddu16) +RVVCALL(OPIVX2_RM, vsaddu_vx_w, OP_UUU_W, H4, H4, saddu32) +RVVCALL(OPIVX2_RM, vsaddu_vx_d, OP_UUU_D, H8, H8, saddu64) +GEN_VEXT_VX_RM(vsaddu_vx_b, 1, 1, clearb) +GEN_VEXT_VX_RM(vsaddu_vx_h, 2, 2, clearh) +GEN_VEXT_VX_RM(vsaddu_vx_w, 4, 4, clearl) +GEN_VEXT_VX_RM(vsaddu_vx_d, 8, 8, clearq) + +static inline int8_t sadd8(CPURISCVState *env, int vxrm, int8_t a, int8_t b) +{ + int8_t res = a + b; + if ((res ^ a) & (res ^ b) & INT8_MIN) { + res = a > 0 ? INT8_MAX : INT8_MIN; + env->vxsat = 0x1; + } + return res; +} + +static inline int16_t sadd16(CPURISCVState *env, int vxrm, int16_t a, int16_t b) +{ + int16_t res = a + b; + if ((res ^ a) & (res ^ b) & INT16_MIN) { + res = a > 0 ? INT16_MAX : INT16_MIN; + env->vxsat = 0x1; + } + return res; +} + +static inline int32_t sadd32(CPURISCVState *env, int vxrm, int32_t a, int32_t b) +{ + int32_t res = a + b; + if ((res ^ a) & (res ^ b) & INT32_MIN) { + res = a > 0 ? INT32_MAX : INT32_MIN; + env->vxsat = 0x1; + } + return res; +} + +static inline int64_t sadd64(CPURISCVState *env, int vxrm, int64_t a, int64_t b) +{ + int64_t res = a + b; + if ((res ^ a) & (res ^ b) & INT64_MIN) { + res = a > 0 ? INT64_MAX : INT64_MIN; + env->vxsat = 0x1; + } + return res; +} + +RVVCALL(OPIVV2_RM, vsadd_vv_b, OP_SSS_B, H1, H1, H1, sadd8) +RVVCALL(OPIVV2_RM, vsadd_vv_h, OP_SSS_H, H2, H2, H2, sadd16) +RVVCALL(OPIVV2_RM, vsadd_vv_w, OP_SSS_W, H4, H4, H4, sadd32) +RVVCALL(OPIVV2_RM, vsadd_vv_d, OP_SSS_D, H8, H8, H8, sadd64) +GEN_VEXT_VV_RM(vsadd_vv_b, 1, 1, clearb) +GEN_VEXT_VV_RM(vsadd_vv_h, 2, 2, clearh) +GEN_VEXT_VV_RM(vsadd_vv_w, 4, 4, clearl) +GEN_VEXT_VV_RM(vsadd_vv_d, 8, 8, clearq) + +RVVCALL(OPIVX2_RM, vsadd_vx_b, OP_SSS_B, H1, H1, sadd8) +RVVCALL(OPIVX2_RM, vsadd_vx_h, OP_SSS_H, H2, H2, sadd16) +RVVCALL(OPIVX2_RM, vsadd_vx_w, OP_SSS_W, H4, H4, sadd32) +RVVCALL(OPIVX2_RM, vsadd_vx_d, OP_SSS_D, H8, H8, sadd64) +GEN_VEXT_VX_RM(vsadd_vx_b, 1, 1, clearb) +GEN_VEXT_VX_RM(vsadd_vx_h, 2, 2, clearh) +GEN_VEXT_VX_RM(vsadd_vx_w, 4, 4, clearl) +GEN_VEXT_VX_RM(vsadd_vx_d, 8, 8, clearq) + +static inline uint8_t ssubu8(CPURISCVState *env, int vxrm, uint8_t a, uint8_t b) +{ + uint8_t res = a - b; + if (res > a) { + res = 0; + env->vxsat = 0x1; + } + return res; +} + +static inline uint16_t ssubu16(CPURISCVState *env, int vxrm, uint16_t a, + uint16_t b) +{ + uint16_t res = a - b; + if (res > a) { + res = 0; + env->vxsat = 0x1; + } + return res; +} + +static inline uint32_t ssubu32(CPURISCVState *env, int vxrm, uint32_t a, + uint32_t b) +{ + uint32_t res = a - b; + if (res > a) { + res = 0; + env->vxsat = 0x1; + } + return res; +} + +static inline uint64_t ssubu64(CPURISCVState *env, int vxrm, uint64_t a, + uint64_t b) +{ + uint64_t res = a - b; + if (res > a) { + res = 0; + env->vxsat = 0x1; + } + return res; +} + +RVVCALL(OPIVV2_RM, vssubu_vv_b, OP_UUU_B, H1, H1, H1, ssubu8) +RVVCALL(OPIVV2_RM, vssubu_vv_h, OP_UUU_H, H2, H2, H2, ssubu16) +RVVCALL(OPIVV2_RM, vssubu_vv_w, OP_UUU_W, H4, H4, H4, ssubu32) +RVVCALL(OPIVV2_RM, vssubu_vv_d, OP_UUU_D, H8, H8, H8, ssubu64) +GEN_VEXT_VV_RM(vssubu_vv_b, 1, 1, clearb) +GEN_VEXT_VV_RM(vssubu_vv_h, 2, 2, clearh) +GEN_VEXT_VV_RM(vssubu_vv_w, 4, 4, clearl) +GEN_VEXT_VV_RM(vssubu_vv_d, 8, 8, clearq) + +RVVCALL(OPIVX2_RM, vssubu_vx_b, OP_UUU_B, H1, H1, ssubu8) +RVVCALL(OPIVX2_RM, vssubu_vx_h, OP_UUU_H, H2, H2, ssubu16) +RVVCALL(OPIVX2_RM, vssubu_vx_w, OP_UUU_W, H4, H4, ssubu32) +RVVCALL(OPIVX2_RM, vssubu_vx_d, OP_UUU_D, H8, H8, ssubu64) +GEN_VEXT_VX_RM(vssubu_vx_b, 1, 1, clearb) +GEN_VEXT_VX_RM(vssubu_vx_h, 2, 2, clearh) +GEN_VEXT_VX_RM(vssubu_vx_w, 4, 4, clearl) +GEN_VEXT_VX_RM(vssubu_vx_d, 8, 8, clearq) + +static inline int8_t ssub8(CPURISCVState *env, int vxrm, int8_t a, int8_t b) +{ + int8_t res = a - b; + if ((res ^ a) & (a ^ b) & INT8_MIN) { + res = a > 0 ? INT8_MAX : INT8_MIN; + env->vxsat = 0x1; + } + return res; +} + +static inline int16_t ssub16(CPURISCVState *env, int vxrm, int16_t a, int16_t b) +{ + int16_t res = a - b; + if ((res ^ a) & (a ^ b) & INT16_MIN) { + res = a > 0 ? INT16_MAX : INT16_MIN; + env->vxsat = 0x1; + } + return res; +} + +static inline int32_t ssub32(CPURISCVState *env, int vxrm, int32_t a, int32_t b) +{ + int32_t res = a - b; + if ((res ^ a) & (a ^ b) & INT32_MIN) { + res = a > 0 ? INT32_MAX : INT32_MIN; + env->vxsat = 0x1; + } + return res; +} + +static inline int64_t ssub64(CPURISCVState *env, int vxrm, int64_t a, int64_t b) +{ + int64_t res = a - b; + if ((res ^ a) & (a ^ b) & INT64_MIN) { + res = a > 0 ? INT64_MAX : INT64_MIN; + env->vxsat = 0x1; + } + return res; +} + +RVVCALL(OPIVV2_RM, vssub_vv_b, OP_SSS_B, H1, H1, H1, ssub8) +RVVCALL(OPIVV2_RM, vssub_vv_h, OP_SSS_H, H2, H2, H2, ssub16) +RVVCALL(OPIVV2_RM, vssub_vv_w, OP_SSS_W, H4, H4, H4, ssub32) +RVVCALL(OPIVV2_RM, vssub_vv_d, OP_SSS_D, H8, H8, H8, ssub64) +GEN_VEXT_VV_RM(vssub_vv_b, 1, 1, clearb) +GEN_VEXT_VV_RM(vssub_vv_h, 2, 2, clearh) +GEN_VEXT_VV_RM(vssub_vv_w, 4, 4, clearl) +GEN_VEXT_VV_RM(vssub_vv_d, 8, 8, clearq) + +RVVCALL(OPIVX2_RM, vssub_vx_b, OP_SSS_B, H1, H1, ssub8) +RVVCALL(OPIVX2_RM, vssub_vx_h, OP_SSS_H, H2, H2, ssub16) +RVVCALL(OPIVX2_RM, vssub_vx_w, OP_SSS_W, H4, H4, ssub32) +RVVCALL(OPIVX2_RM, vssub_vx_d, OP_SSS_D, H8, H8, ssub64) +GEN_VEXT_VX_RM(vssub_vx_b, 1, 1, clearb) +GEN_VEXT_VX_RM(vssub_vx_h, 2, 2, clearh) +GEN_VEXT_VX_RM(vssub_vx_w, 4, 4, clearl) +GEN_VEXT_VX_RM(vssub_vx_d, 8, 8, clearq) + +/* Vector Single-Width Averaging Add and Subtract */ +static inline uint8_t get_round(int vxrm, uint64_t v, uint8_t shift) +{ + uint8_t d = extract64(v, shift, 1); + uint8_t d1; + uint64_t D1, D2; + + if (shift == 0 || shift > 64) { + return 0; + } + + d1 = extract64(v, shift - 1, 1); + D1 = extract64(v, 0, shift); + if (vxrm == 0) { /* round-to-nearest-up (add +0.5 LSB) */ + return d1; + } else if (vxrm == 1) { /* round-to-nearest-even */ + if (shift > 1) { + D2 = extract64(v, 0, shift - 1); + return d1 & ((D2 != 0) | d); + } else { + return d1 & d; + } + } else if (vxrm == 3) { /* round-to-odd (OR bits into LSB, aka "jam") */ + return !d & (D1 != 0); + } + return 0; /* round-down (truncate) */ +} + +static inline int32_t aadd32(CPURISCVState *env, int vxrm, int32_t a, int32_t b) +{ + int64_t res = (int64_t)a + b; + uint8_t round = get_round(vxrm, res, 1); + + return (res >> 1) + round; +} + +static inline int64_t aadd64(CPURISCVState *env, int vxrm, int64_t a, int64_t b) +{ + int64_t res = a + b; + uint8_t round = get_round(vxrm, res, 1); + int64_t over = (res ^ a) & (res ^ b) & INT64_MIN; + + /* With signed overflow, bit 64 is inverse of bit 63. */ + return ((res >> 1) ^ over) + round; +} + +RVVCALL(OPIVV2_RM, vaadd_vv_b, OP_SSS_B, H1, H1, H1, aadd32) +RVVCALL(OPIVV2_RM, vaadd_vv_h, OP_SSS_H, H2, H2, H2, aadd32) +RVVCALL(OPIVV2_RM, vaadd_vv_w, OP_SSS_W, H4, H4, H4, aadd32) +RVVCALL(OPIVV2_RM, vaadd_vv_d, OP_SSS_D, H8, H8, H8, aadd64) +GEN_VEXT_VV_RM(vaadd_vv_b, 1, 1, clearb) +GEN_VEXT_VV_RM(vaadd_vv_h, 2, 2, clearh) +GEN_VEXT_VV_RM(vaadd_vv_w, 4, 4, clearl) +GEN_VEXT_VV_RM(vaadd_vv_d, 8, 8, clearq) + +RVVCALL(OPIVX2_RM, vaadd_vx_b, OP_SSS_B, H1, H1, aadd32) +RVVCALL(OPIVX2_RM, vaadd_vx_h, OP_SSS_H, H2, H2, aadd32) +RVVCALL(OPIVX2_RM, vaadd_vx_w, OP_SSS_W, H4, H4, aadd32) +RVVCALL(OPIVX2_RM, vaadd_vx_d, OP_SSS_D, H8, H8, aadd64) +GEN_VEXT_VX_RM(vaadd_vx_b, 1, 1, clearb) +GEN_VEXT_VX_RM(vaadd_vx_h, 2, 2, clearh) +GEN_VEXT_VX_RM(vaadd_vx_w, 4, 4, clearl) +GEN_VEXT_VX_RM(vaadd_vx_d, 8, 8, clearq) + +static inline int32_t asub32(CPURISCVState *env, int vxrm, int32_t a, int32_t b) +{ + int64_t res = (int64_t)a - b; + uint8_t round = get_round(vxrm, res, 1); + + return (res >> 1) + round; +} + +static inline int64_t asub64(CPURISCVState *env, int vxrm, int64_t a, int64_t b) +{ + int64_t res = (int64_t)a - b; + uint8_t round = get_round(vxrm, res, 1); + int64_t over = (res ^ a) & (a ^ b) & INT64_MIN; + + /* With signed overflow, bit 64 is inverse of bit 63. */ + return ((res >> 1) ^ over) + round; +} + +RVVCALL(OPIVV2_RM, vasub_vv_b, OP_SSS_B, H1, H1, H1, asub32) +RVVCALL(OPIVV2_RM, vasub_vv_h, OP_SSS_H, H2, H2, H2, asub32) +RVVCALL(OPIVV2_RM, vasub_vv_w, OP_SSS_W, H4, H4, H4, asub32) +RVVCALL(OPIVV2_RM, vasub_vv_d, OP_SSS_D, H8, H8, H8, asub64) +GEN_VEXT_VV_RM(vasub_vv_b, 1, 1, clearb) +GEN_VEXT_VV_RM(vasub_vv_h, 2, 2, clearh) +GEN_VEXT_VV_RM(vasub_vv_w, 4, 4, clearl) +GEN_VEXT_VV_RM(vasub_vv_d, 8, 8, clearq) + +RVVCALL(OPIVX2_RM, vasub_vx_b, OP_SSS_B, H1, H1, asub32) +RVVCALL(OPIVX2_RM, vasub_vx_h, OP_SSS_H, H2, H2, asub32) +RVVCALL(OPIVX2_RM, vasub_vx_w, OP_SSS_W, H4, H4, asub32) +RVVCALL(OPIVX2_RM, vasub_vx_d, OP_SSS_D, H8, H8, asub64) +GEN_VEXT_VX_RM(vasub_vx_b, 1, 1, clearb) +GEN_VEXT_VX_RM(vasub_vx_h, 2, 2, clearh) +GEN_VEXT_VX_RM(vasub_vx_w, 4, 4, clearl) +GEN_VEXT_VX_RM(vasub_vx_d, 8, 8, clearq) + +/* Vector Single-Width Fractional Multiply with Rounding and Saturation */ +static inline int8_t vsmul8(CPURISCVState *env, int vxrm, int8_t a, int8_t b) +{ + uint8_t round; + int16_t res; + + res = (int16_t)a * (int16_t)b; + round = get_round(vxrm, res, 7); + res = (res >> 7) + round; + + if (res > INT8_MAX) { + env->vxsat = 0x1; + return INT8_MAX; + } else if (res < INT8_MIN) { + env->vxsat = 0x1; + return INT8_MIN; + } else { + return res; + } +} + +static int16_t vsmul16(CPURISCVState *env, int vxrm, int16_t a, int16_t b) +{ + uint8_t round; + int32_t res; + + res = (int32_t)a * (int32_t)b; + round = get_round(vxrm, res, 15); + res = (res >> 15) + round; + + if (res > INT16_MAX) { + env->vxsat = 0x1; + return INT16_MAX; + } else if (res < INT16_MIN) { + env->vxsat = 0x1; + return INT16_MIN; + } else { + return res; + } +} + +static int32_t vsmul32(CPURISCVState *env, int vxrm, int32_t a, int32_t b) +{ + uint8_t round; + int64_t res; + + res = (int64_t)a * (int64_t)b; + round = get_round(vxrm, res, 31); + res = (res >> 31) + round; + + if (res > INT32_MAX) { + env->vxsat = 0x1; + return INT32_MAX; + } else if (res < INT32_MIN) { + env->vxsat = 0x1; + return INT32_MIN; + } else { + return res; + } +} + +static int64_t vsmul64(CPURISCVState *env, int vxrm, int64_t a, int64_t b) +{ + uint8_t round; + uint64_t hi_64, lo_64; + int64_t res; + + if (a == INT64_MIN && b == INT64_MIN) { + env->vxsat = 1; + return INT64_MAX; + } + + muls64(&lo_64, &hi_64, a, b); + round = get_round(vxrm, lo_64, 63); + /* + * Cannot overflow, as there are always + * 2 sign bits after multiply. + */ + res = (hi_64 << 1) | (lo_64 >> 63); + if (round) { + if (res == INT64_MAX) { + env->vxsat = 1; + } else { + res += 1; + } + } + return res; +} + +RVVCALL(OPIVV2_RM, vsmul_vv_b, OP_SSS_B, H1, H1, H1, vsmul8) +RVVCALL(OPIVV2_RM, vsmul_vv_h, OP_SSS_H, H2, H2, H2, vsmul16) +RVVCALL(OPIVV2_RM, vsmul_vv_w, OP_SSS_W, H4, H4, H4, vsmul32) +RVVCALL(OPIVV2_RM, vsmul_vv_d, OP_SSS_D, H8, H8, H8, vsmul64) +GEN_VEXT_VV_RM(vsmul_vv_b, 1, 1, clearb) +GEN_VEXT_VV_RM(vsmul_vv_h, 2, 2, clearh) +GEN_VEXT_VV_RM(vsmul_vv_w, 4, 4, clearl) +GEN_VEXT_VV_RM(vsmul_vv_d, 8, 8, clearq) + +RVVCALL(OPIVX2_RM, vsmul_vx_b, OP_SSS_B, H1, H1, vsmul8) +RVVCALL(OPIVX2_RM, vsmul_vx_h, OP_SSS_H, H2, H2, vsmul16) +RVVCALL(OPIVX2_RM, vsmul_vx_w, OP_SSS_W, H4, H4, vsmul32) +RVVCALL(OPIVX2_RM, vsmul_vx_d, OP_SSS_D, H8, H8, vsmul64) +GEN_VEXT_VX_RM(vsmul_vx_b, 1, 1, clearb) +GEN_VEXT_VX_RM(vsmul_vx_h, 2, 2, clearh) +GEN_VEXT_VX_RM(vsmul_vx_w, 4, 4, clearl) +GEN_VEXT_VX_RM(vsmul_vx_d, 8, 8, clearq) + +/* Vector Widening Saturating Scaled Multiply-Add */ +static inline uint16_t +vwsmaccu8(CPURISCVState *env, int vxrm, uint8_t a, uint8_t b, + uint16_t c) +{ + uint8_t round; + uint16_t res = (uint16_t)a * b; + + round = get_round(vxrm, res, 4); + res = (res >> 4) + round; + return saddu16(env, vxrm, c, res); +} + +static inline uint32_t +vwsmaccu16(CPURISCVState *env, int vxrm, uint16_t a, uint16_t b, + uint32_t c) +{ + uint8_t round; + uint32_t res = (uint32_t)a * b; + + round = get_round(vxrm, res, 8); + res = (res >> 8) + round; + return saddu32(env, vxrm, c, res); +} + +static inline uint64_t +vwsmaccu32(CPURISCVState *env, int vxrm, uint32_t a, uint32_t b, + uint64_t c) +{ + uint8_t round; + uint64_t res = (uint64_t)a * b; + + round = get_round(vxrm, res, 16); + res = (res >> 16) + round; + return saddu64(env, vxrm, c, res); +} + +#define OPIVV3_RM(NAME, TD, T1, T2, TX1, TX2, HD, HS1, HS2, OP) \ +static inline void \ +do_##NAME(void *vd, void *vs1, void *vs2, int i, \ + CPURISCVState *env, int vxrm) \ +{ \ + TX1 s1 = *((T1 *)vs1 + HS1(i)); \ + TX2 s2 = *((T2 *)vs2 + HS2(i)); \ + TD d = *((TD *)vd + HD(i)); \ + *((TD *)vd + HD(i)) = OP(env, vxrm, s2, s1, d); \ +} + +RVVCALL(OPIVV3_RM, vwsmaccu_vv_b, WOP_UUU_B, H2, H1, H1, vwsmaccu8) +RVVCALL(OPIVV3_RM, vwsmaccu_vv_h, WOP_UUU_H, H4, H2, H2, vwsmaccu16) +RVVCALL(OPIVV3_RM, vwsmaccu_vv_w, WOP_UUU_W, H8, H4, H4, vwsmaccu32) +GEN_VEXT_VV_RM(vwsmaccu_vv_b, 1, 2, clearh) +GEN_VEXT_VV_RM(vwsmaccu_vv_h, 2, 4, clearl) +GEN_VEXT_VV_RM(vwsmaccu_vv_w, 4, 8, clearq) + +#define OPIVX3_RM(NAME, TD, T1, T2, TX1, TX2, HD, HS2, OP) \ +static inline void \ +do_##NAME(void *vd, target_long s1, void *vs2, int i, \ + CPURISCVState *env, int vxrm) \ +{ \ + TX2 s2 = *((T2 *)vs2 + HS2(i)); \ + TD d = *((TD *)vd + HD(i)); \ + *((TD *)vd + HD(i)) = OP(env, vxrm, s2, (TX1)(T1)s1, d); \ +} + +RVVCALL(OPIVX3_RM, vwsmaccu_vx_b, WOP_UUU_B, H2, H1, vwsmaccu8) +RVVCALL(OPIVX3_RM, vwsmaccu_vx_h, WOP_UUU_H, H4, H2, vwsmaccu16) +RVVCALL(OPIVX3_RM, vwsmaccu_vx_w, WOP_UUU_W, H8, H4, vwsmaccu32) +GEN_VEXT_VX_RM(vwsmaccu_vx_b, 1, 2, clearh) +GEN_VEXT_VX_RM(vwsmaccu_vx_h, 2, 4, clearl) +GEN_VEXT_VX_RM(vwsmaccu_vx_w, 4, 8, clearq) + +static inline int16_t +vwsmacc8(CPURISCVState *env, int vxrm, int8_t a, int8_t b, int16_t c) +{ + uint8_t round; + int16_t res = (int16_t)a * b; + + round = get_round(vxrm, res, 4); + res = (res >> 4) + round; + return sadd16(env, vxrm, c, res); +} + +static inline int32_t +vwsmacc16(CPURISCVState *env, int vxrm, int16_t a, int16_t b, int32_t c) +{ + uint8_t round; + int32_t res = (int32_t)a * b; + + round = get_round(vxrm, res, 8); + res = (res >> 8) + round; + return sadd32(env, vxrm, c, res); + +} + +static inline int64_t +vwsmacc32(CPURISCVState *env, int vxrm, int32_t a, int32_t b, int64_t c) +{ + uint8_t round; + int64_t res = (int64_t)a * b; + + round = get_round(vxrm, res, 16); + res = (res >> 16) + round; + return sadd64(env, vxrm, c, res); +} + +RVVCALL(OPIVV3_RM, vwsmacc_vv_b, WOP_SSS_B, H2, H1, H1, vwsmacc8) +RVVCALL(OPIVV3_RM, vwsmacc_vv_h, WOP_SSS_H, H4, H2, H2, vwsmacc16) +RVVCALL(OPIVV3_RM, vwsmacc_vv_w, WOP_SSS_W, H8, H4, H4, vwsmacc32) +GEN_VEXT_VV_RM(vwsmacc_vv_b, 1, 2, clearh) +GEN_VEXT_VV_RM(vwsmacc_vv_h, 2, 4, clearl) +GEN_VEXT_VV_RM(vwsmacc_vv_w, 4, 8, clearq) +RVVCALL(OPIVX3_RM, vwsmacc_vx_b, WOP_SSS_B, H2, H1, vwsmacc8) +RVVCALL(OPIVX3_RM, vwsmacc_vx_h, WOP_SSS_H, H4, H2, vwsmacc16) +RVVCALL(OPIVX3_RM, vwsmacc_vx_w, WOP_SSS_W, H8, H4, vwsmacc32) +GEN_VEXT_VX_RM(vwsmacc_vx_b, 1, 2, clearh) +GEN_VEXT_VX_RM(vwsmacc_vx_h, 2, 4, clearl) +GEN_VEXT_VX_RM(vwsmacc_vx_w, 4, 8, clearq) + +static inline int16_t +vwsmaccsu8(CPURISCVState *env, int vxrm, uint8_t a, int8_t b, int16_t c) +{ + uint8_t round; + int16_t res = a * (int16_t)b; + + round = get_round(vxrm, res, 4); + res = (res >> 4) + round; + return ssub16(env, vxrm, c, res); +} + +static inline int32_t +vwsmaccsu16(CPURISCVState *env, int vxrm, uint16_t a, int16_t b, uint32_t c) +{ + uint8_t round; + int32_t res = a * (int32_t)b; + + round = get_round(vxrm, res, 8); + res = (res >> 8) + round; + return ssub32(env, vxrm, c, res); +} + +static inline int64_t +vwsmaccsu32(CPURISCVState *env, int vxrm, uint32_t a, int32_t b, int64_t c) +{ + uint8_t round; + int64_t res = a * (int64_t)b; + + round = get_round(vxrm, res, 16); + res = (res >> 16) + round; + return ssub64(env, vxrm, c, res); +} + +RVVCALL(OPIVV3_RM, vwsmaccsu_vv_b, WOP_SSU_B, H2, H1, H1, vwsmaccsu8) +RVVCALL(OPIVV3_RM, vwsmaccsu_vv_h, WOP_SSU_H, H4, H2, H2, vwsmaccsu16) +RVVCALL(OPIVV3_RM, vwsmaccsu_vv_w, WOP_SSU_W, H8, H4, H4, vwsmaccsu32) +GEN_VEXT_VV_RM(vwsmaccsu_vv_b, 1, 2, clearh) +GEN_VEXT_VV_RM(vwsmaccsu_vv_h, 2, 4, clearl) +GEN_VEXT_VV_RM(vwsmaccsu_vv_w, 4, 8, clearq) +RVVCALL(OPIVX3_RM, vwsmaccsu_vx_b, WOP_SSU_B, H2, H1, vwsmaccsu8) +RVVCALL(OPIVX3_RM, vwsmaccsu_vx_h, WOP_SSU_H, H4, H2, vwsmaccsu16) +RVVCALL(OPIVX3_RM, vwsmaccsu_vx_w, WOP_SSU_W, H8, H4, vwsmaccsu32) +GEN_VEXT_VX_RM(vwsmaccsu_vx_b, 1, 2, clearh) +GEN_VEXT_VX_RM(vwsmaccsu_vx_h, 2, 4, clearl) +GEN_VEXT_VX_RM(vwsmaccsu_vx_w, 4, 8, clearq) + +static inline int16_t +vwsmaccus8(CPURISCVState *env, int vxrm, int8_t a, uint8_t b, int16_t c) +{ + uint8_t round; + int16_t res = (int16_t)a * b; + + round = get_round(vxrm, res, 4); + res = (res >> 4) + round; + return ssub16(env, vxrm, c, res); +} + +static inline int32_t +vwsmaccus16(CPURISCVState *env, int vxrm, int16_t a, uint16_t b, int32_t c) +{ + uint8_t round; + int32_t res = (int32_t)a * b; + + round = get_round(vxrm, res, 8); + res = (res >> 8) + round; + return ssub32(env, vxrm, c, res); +} + +static inline int64_t +vwsmaccus32(CPURISCVState *env, int vxrm, int32_t a, uint32_t b, int64_t c) +{ + uint8_t round; + int64_t res = (int64_t)a * b; + + round = get_round(vxrm, res, 16); + res = (res >> 16) + round; + return ssub64(env, vxrm, c, res); +} + +RVVCALL(OPIVX3_RM, vwsmaccus_vx_b, WOP_SUS_B, H2, H1, vwsmaccus8) +RVVCALL(OPIVX3_RM, vwsmaccus_vx_h, WOP_SUS_H, H4, H2, vwsmaccus16) +RVVCALL(OPIVX3_RM, vwsmaccus_vx_w, WOP_SUS_W, H8, H4, vwsmaccus32) +GEN_VEXT_VX_RM(vwsmaccus_vx_b, 1, 2, clearh) +GEN_VEXT_VX_RM(vwsmaccus_vx_h, 2, 4, clearl) +GEN_VEXT_VX_RM(vwsmaccus_vx_w, 4, 8, clearq) + +/* Vector Single-Width Scaling Shift Instructions */ +static inline uint8_t +vssrl8(CPURISCVState *env, int vxrm, uint8_t a, uint8_t b) +{ + uint8_t round, shift = b & 0x7; + uint8_t res; + + round = get_round(vxrm, a, shift); + res = (a >> shift) + round; + return res; +} +static inline uint16_t +vssrl16(CPURISCVState *env, int vxrm, uint16_t a, uint16_t b) +{ + uint8_t round, shift = b & 0xf; + uint16_t res; + + round = get_round(vxrm, a, shift); + res = (a >> shift) + round; + return res; +} +static inline uint32_t +vssrl32(CPURISCVState *env, int vxrm, uint32_t a, uint32_t b) +{ + uint8_t round, shift = b & 0x1f; + uint32_t res; + + round = get_round(vxrm, a, shift); + res = (a >> shift) + round; + return res; +} +static inline uint64_t +vssrl64(CPURISCVState *env, int vxrm, uint64_t a, uint64_t b) +{ + uint8_t round, shift = b & 0x3f; + uint64_t res; + + round = get_round(vxrm, a, shift); + res = (a >> shift) + round; + return res; +} +RVVCALL(OPIVV2_RM, vssrl_vv_b, OP_UUU_B, H1, H1, H1, vssrl8) +RVVCALL(OPIVV2_RM, vssrl_vv_h, OP_UUU_H, H2, H2, H2, vssrl16) +RVVCALL(OPIVV2_RM, vssrl_vv_w, OP_UUU_W, H4, H4, H4, vssrl32) +RVVCALL(OPIVV2_RM, vssrl_vv_d, OP_UUU_D, H8, H8, H8, vssrl64) +GEN_VEXT_VV_RM(vssrl_vv_b, 1, 1, clearb) +GEN_VEXT_VV_RM(vssrl_vv_h, 2, 2, clearh) +GEN_VEXT_VV_RM(vssrl_vv_w, 4, 4, clearl) +GEN_VEXT_VV_RM(vssrl_vv_d, 8, 8, clearq) + +RVVCALL(OPIVX2_RM, vssrl_vx_b, OP_UUU_B, H1, H1, vssrl8) +RVVCALL(OPIVX2_RM, vssrl_vx_h, OP_UUU_H, H2, H2, vssrl16) +RVVCALL(OPIVX2_RM, vssrl_vx_w, OP_UUU_W, H4, H4, vssrl32) +RVVCALL(OPIVX2_RM, vssrl_vx_d, OP_UUU_D, H8, H8, vssrl64) +GEN_VEXT_VX_RM(vssrl_vx_b, 1, 1, clearb) +GEN_VEXT_VX_RM(vssrl_vx_h, 2, 2, clearh) +GEN_VEXT_VX_RM(vssrl_vx_w, 4, 4, clearl) +GEN_VEXT_VX_RM(vssrl_vx_d, 8, 8, clearq) + +static inline int8_t +vssra8(CPURISCVState *env, int vxrm, int8_t a, int8_t b) +{ + uint8_t round, shift = b & 0x7; + int8_t res; + + round = get_round(vxrm, a, shift); + res = (a >> shift) + round; + return res; +} +static inline int16_t +vssra16(CPURISCVState *env, int vxrm, int16_t a, int16_t b) +{ + uint8_t round, shift = b & 0xf; + int16_t res; + + round = get_round(vxrm, a, shift); + res = (a >> shift) + round; + return res; +} +static inline int32_t +vssra32(CPURISCVState *env, int vxrm, int32_t a, int32_t b) +{ + uint8_t round, shift = b & 0x1f; + int32_t res; + + round = get_round(vxrm, a, shift); + res = (a >> shift) + round; + return res; +} +static inline int64_t +vssra64(CPURISCVState *env, int vxrm, int64_t a, int64_t b) +{ + uint8_t round, shift = b & 0x3f; + int64_t res; + + round = get_round(vxrm, a, shift); + res = (a >> shift) + round; + return res; +} + +RVVCALL(OPIVV2_RM, vssra_vv_b, OP_SSS_B, H1, H1, H1, vssra8) +RVVCALL(OPIVV2_RM, vssra_vv_h, OP_SSS_H, H2, H2, H2, vssra16) +RVVCALL(OPIVV2_RM, vssra_vv_w, OP_SSS_W, H4, H4, H4, vssra32) +RVVCALL(OPIVV2_RM, vssra_vv_d, OP_SSS_D, H8, H8, H8, vssra64) +GEN_VEXT_VV_RM(vssra_vv_b, 1, 1, clearb) +GEN_VEXT_VV_RM(vssra_vv_h, 2, 2, clearh) +GEN_VEXT_VV_RM(vssra_vv_w, 4, 4, clearl) +GEN_VEXT_VV_RM(vssra_vv_d, 8, 8, clearq) + +RVVCALL(OPIVX2_RM, vssra_vx_b, OP_SSS_B, H1, H1, vssra8) +RVVCALL(OPIVX2_RM, vssra_vx_h, OP_SSS_H, H2, H2, vssra16) +RVVCALL(OPIVX2_RM, vssra_vx_w, OP_SSS_W, H4, H4, vssra32) +RVVCALL(OPIVX2_RM, vssra_vx_d, OP_SSS_D, H8, H8, vssra64) +GEN_VEXT_VX_RM(vssra_vx_b, 1, 1, clearb) +GEN_VEXT_VX_RM(vssra_vx_h, 2, 2, clearh) +GEN_VEXT_VX_RM(vssra_vx_w, 4, 4, clearl) +GEN_VEXT_VX_RM(vssra_vx_d, 8, 8, clearq) + +/* Vector Narrowing Fixed-Point Clip Instructions */ +static inline int8_t +vnclip8(CPURISCVState *env, int vxrm, int16_t a, int8_t b) +{ + uint8_t round, shift = b & 0xf; + int16_t res; + + round = get_round(vxrm, a, shift); + res = (a >> shift) + round; + if (res > INT8_MAX) { + env->vxsat = 0x1; + return INT8_MAX; + } else if (res < INT8_MIN) { + env->vxsat = 0x1; + return INT8_MIN; + } else { + return res; + } +} + +static inline int16_t +vnclip16(CPURISCVState *env, int vxrm, int32_t a, int16_t b) +{ + uint8_t round, shift = b & 0x1f; + int32_t res; + + round = get_round(vxrm, a, shift); + res = (a >> shift) + round; + if (res > INT16_MAX) { + env->vxsat = 0x1; + return INT16_MAX; + } else if (res < INT16_MIN) { + env->vxsat = 0x1; + return INT16_MIN; + } else { + return res; + } +} + +static inline int32_t +vnclip32(CPURISCVState *env, int vxrm, int64_t a, int32_t b) +{ + uint8_t round, shift = b & 0x3f; + int64_t res; + + round = get_round(vxrm, a, shift); + res = (a >> shift) + round; + if (res > INT32_MAX) { + env->vxsat = 0x1; + return INT32_MAX; + } else if (res < INT32_MIN) { + env->vxsat = 0x1; + return INT32_MIN; + } else { + return res; + } +} + +RVVCALL(OPIVV2_RM, vnclip_vv_b, NOP_SSS_B, H1, H2, H1, vnclip8) +RVVCALL(OPIVV2_RM, vnclip_vv_h, NOP_SSS_H, H2, H4, H2, vnclip16) +RVVCALL(OPIVV2_RM, vnclip_vv_w, NOP_SSS_W, H4, H8, H4, vnclip32) +GEN_VEXT_VV_RM(vnclip_vv_b, 1, 1, clearb) +GEN_VEXT_VV_RM(vnclip_vv_h, 2, 2, clearh) +GEN_VEXT_VV_RM(vnclip_vv_w, 4, 4, clearl) + +RVVCALL(OPIVX2_RM, vnclip_vx_b, NOP_SSS_B, H1, H2, vnclip8) +RVVCALL(OPIVX2_RM, vnclip_vx_h, NOP_SSS_H, H2, H4, vnclip16) +RVVCALL(OPIVX2_RM, vnclip_vx_w, NOP_SSS_W, H4, H8, vnclip32) +GEN_VEXT_VX_RM(vnclip_vx_b, 1, 1, clearb) +GEN_VEXT_VX_RM(vnclip_vx_h, 2, 2, clearh) +GEN_VEXT_VX_RM(vnclip_vx_w, 4, 4, clearl) + +static inline uint8_t +vnclipu8(CPURISCVState *env, int vxrm, uint16_t a, uint8_t b) +{ + uint8_t round, shift = b & 0xf; + uint16_t res; + + round = get_round(vxrm, a, shift); + res = (a >> shift) + round; + if (res > UINT8_MAX) { + env->vxsat = 0x1; + return UINT8_MAX; + } else { + return res; + } +} + +static inline uint16_t +vnclipu16(CPURISCVState *env, int vxrm, uint32_t a, uint16_t b) +{ + uint8_t round, shift = b & 0x1f; + uint32_t res; + + round = get_round(vxrm, a, shift); + res = (a >> shift) + round; + if (res > UINT16_MAX) { + env->vxsat = 0x1; + return UINT16_MAX; + } else { + return res; + } +} + +static inline uint32_t +vnclipu32(CPURISCVState *env, int vxrm, uint64_t a, uint32_t b) +{ + uint8_t round, shift = b & 0x3f; + int64_t res; + + round = get_round(vxrm, a, shift); + res = (a >> shift) + round; + if (res > UINT32_MAX) { + env->vxsat = 0x1; + return UINT32_MAX; + } else { + return res; + } +} + +RVVCALL(OPIVV2_RM, vnclipu_vv_b, NOP_UUU_B, H1, H2, H1, vnclipu8) +RVVCALL(OPIVV2_RM, vnclipu_vv_h, NOP_UUU_H, H2, H4, H2, vnclipu16) +RVVCALL(OPIVV2_RM, vnclipu_vv_w, NOP_UUU_W, H4, H8, H4, vnclipu32) +GEN_VEXT_VV_RM(vnclipu_vv_b, 1, 1, clearb) +GEN_VEXT_VV_RM(vnclipu_vv_h, 2, 2, clearh) +GEN_VEXT_VV_RM(vnclipu_vv_w, 4, 4, clearl) + +RVVCALL(OPIVX2_RM, vnclipu_vx_b, NOP_UUU_B, H1, H2, vnclipu8) +RVVCALL(OPIVX2_RM, vnclipu_vx_h, NOP_UUU_H, H2, H4, vnclipu16) +RVVCALL(OPIVX2_RM, vnclipu_vx_w, NOP_UUU_W, H4, H8, vnclipu32) +GEN_VEXT_VX_RM(vnclipu_vx_b, 1, 1, clearb) +GEN_VEXT_VX_RM(vnclipu_vx_h, 2, 2, clearh) +GEN_VEXT_VX_RM(vnclipu_vx_w, 4, 4, clearl) + +/* + *** Vector Float Point Arithmetic Instructions + */ +/* Vector Single-Width Floating-Point Add/Subtract Instructions */ +#define OPFVV2(NAME, TD, T1, T2, TX1, TX2, HD, HS1, HS2, OP) \ +static void do_##NAME(void *vd, void *vs1, void *vs2, int i, \ + CPURISCVState *env) \ +{ \ + TX1 s1 = *((T1 *)vs1 + HS1(i)); \ + TX2 s2 = *((T2 *)vs2 + HS2(i)); \ + *((TD *)vd + HD(i)) = OP(s2, s1, &env->fp_status); \ +} + +#define GEN_VEXT_VV_ENV(NAME, ESZ, DSZ, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, void *vs1, \ + void *vs2, CPURISCVState *env, \ + uint32_t desc) \ +{ \ + uint32_t vlmax = vext_maxsz(desc) / ESZ; \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + do_##NAME(vd, vs1, vs2, i, env); \ + } \ + CLEAR_FN(vd, vl, vl * DSZ, vlmax * DSZ); \ +} + +RVVCALL(OPFVV2, vfadd_vv_h, OP_UUU_H, H2, H2, H2, float16_add) +RVVCALL(OPFVV2, vfadd_vv_w, OP_UUU_W, H4, H4, H4, float32_add) +RVVCALL(OPFVV2, vfadd_vv_d, OP_UUU_D, H8, H8, H8, float64_add) +GEN_VEXT_VV_ENV(vfadd_vv_h, 2, 2, clearh) +GEN_VEXT_VV_ENV(vfadd_vv_w, 4, 4, clearl) +GEN_VEXT_VV_ENV(vfadd_vv_d, 8, 8, clearq) + +#define OPFVF2(NAME, TD, T1, T2, TX1, TX2, HD, HS2, OP) \ +static void do_##NAME(void *vd, uint64_t s1, void *vs2, int i, \ + CPURISCVState *env) \ +{ \ + TX2 s2 = *((T2 *)vs2 + HS2(i)); \ + *((TD *)vd + HD(i)) = OP(s2, (TX1)(T1)s1, &env->fp_status);\ +} + +#define GEN_VEXT_VF(NAME, ESZ, DSZ, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, uint64_t s1, \ + void *vs2, CPURISCVState *env, \ + uint32_t desc) \ +{ \ + uint32_t vlmax = vext_maxsz(desc) / ESZ; \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + do_##NAME(vd, s1, vs2, i, env); \ + } \ + CLEAR_FN(vd, vl, vl * DSZ, vlmax * DSZ); \ +} + +RVVCALL(OPFVF2, vfadd_vf_h, OP_UUU_H, H2, H2, float16_add) +RVVCALL(OPFVF2, vfadd_vf_w, OP_UUU_W, H4, H4, float32_add) +RVVCALL(OPFVF2, vfadd_vf_d, OP_UUU_D, H8, H8, float64_add) +GEN_VEXT_VF(vfadd_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfadd_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfadd_vf_d, 8, 8, clearq) + +RVVCALL(OPFVV2, vfsub_vv_h, OP_UUU_H, H2, H2, H2, float16_sub) +RVVCALL(OPFVV2, vfsub_vv_w, OP_UUU_W, H4, H4, H4, float32_sub) +RVVCALL(OPFVV2, vfsub_vv_d, OP_UUU_D, H8, H8, H8, float64_sub) +GEN_VEXT_VV_ENV(vfsub_vv_h, 2, 2, clearh) +GEN_VEXT_VV_ENV(vfsub_vv_w, 4, 4, clearl) +GEN_VEXT_VV_ENV(vfsub_vv_d, 8, 8, clearq) +RVVCALL(OPFVF2, vfsub_vf_h, OP_UUU_H, H2, H2, float16_sub) +RVVCALL(OPFVF2, vfsub_vf_w, OP_UUU_W, H4, H4, float32_sub) +RVVCALL(OPFVF2, vfsub_vf_d, OP_UUU_D, H8, H8, float64_sub) +GEN_VEXT_VF(vfsub_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfsub_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfsub_vf_d, 8, 8, clearq) + +static uint16_t float16_rsub(uint16_t a, uint16_t b, float_status *s) +{ + return float16_sub(b, a, s); +} + +static uint32_t float32_rsub(uint32_t a, uint32_t b, float_status *s) +{ + return float32_sub(b, a, s); +} + +static uint64_t float64_rsub(uint64_t a, uint64_t b, float_status *s) +{ + return float64_sub(b, a, s); +} + +RVVCALL(OPFVF2, vfrsub_vf_h, OP_UUU_H, H2, H2, float16_rsub) +RVVCALL(OPFVF2, vfrsub_vf_w, OP_UUU_W, H4, H4, float32_rsub) +RVVCALL(OPFVF2, vfrsub_vf_d, OP_UUU_D, H8, H8, float64_rsub) +GEN_VEXT_VF(vfrsub_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfrsub_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfrsub_vf_d, 8, 8, clearq) + +/* Vector Widening Floating-Point Add/Subtract Instructions */ +static uint32_t vfwadd16(uint16_t a, uint16_t b, float_status *s) +{ + return float32_add(float16_to_float32(a, true, s), + float16_to_float32(b, true, s), s); +} + +static uint64_t vfwadd32(uint32_t a, uint32_t b, float_status *s) +{ + return float64_add(float32_to_float64(a, s), + float32_to_float64(b, s), s); + +} + +RVVCALL(OPFVV2, vfwadd_vv_h, WOP_UUU_H, H4, H2, H2, vfwadd16) +RVVCALL(OPFVV2, vfwadd_vv_w, WOP_UUU_W, H8, H4, H4, vfwadd32) +GEN_VEXT_VV_ENV(vfwadd_vv_h, 2, 4, clearl) +GEN_VEXT_VV_ENV(vfwadd_vv_w, 4, 8, clearq) +RVVCALL(OPFVF2, vfwadd_vf_h, WOP_UUU_H, H4, H2, vfwadd16) +RVVCALL(OPFVF2, vfwadd_vf_w, WOP_UUU_W, H8, H4, vfwadd32) +GEN_VEXT_VF(vfwadd_vf_h, 2, 4, clearl) +GEN_VEXT_VF(vfwadd_vf_w, 4, 8, clearq) + +static uint32_t vfwsub16(uint16_t a, uint16_t b, float_status *s) +{ + return float32_sub(float16_to_float32(a, true, s), + float16_to_float32(b, true, s), s); +} + +static uint64_t vfwsub32(uint32_t a, uint32_t b, float_status *s) +{ + return float64_sub(float32_to_float64(a, s), + float32_to_float64(b, s), s); + +} + +RVVCALL(OPFVV2, vfwsub_vv_h, WOP_UUU_H, H4, H2, H2, vfwsub16) +RVVCALL(OPFVV2, vfwsub_vv_w, WOP_UUU_W, H8, H4, H4, vfwsub32) +GEN_VEXT_VV_ENV(vfwsub_vv_h, 2, 4, clearl) +GEN_VEXT_VV_ENV(vfwsub_vv_w, 4, 8, clearq) +RVVCALL(OPFVF2, vfwsub_vf_h, WOP_UUU_H, H4, H2, vfwsub16) +RVVCALL(OPFVF2, vfwsub_vf_w, WOP_UUU_W, H8, H4, vfwsub32) +GEN_VEXT_VF(vfwsub_vf_h, 2, 4, clearl) +GEN_VEXT_VF(vfwsub_vf_w, 4, 8, clearq) + +static uint32_t vfwaddw16(uint32_t a, uint16_t b, float_status *s) +{ + return float32_add(a, float16_to_float32(b, true, s), s); +} + +static uint64_t vfwaddw32(uint64_t a, uint32_t b, float_status *s) +{ + return float64_add(a, float32_to_float64(b, s), s); +} + +RVVCALL(OPFVV2, vfwadd_wv_h, WOP_WUUU_H, H4, H2, H2, vfwaddw16) +RVVCALL(OPFVV2, vfwadd_wv_w, WOP_WUUU_W, H8, H4, H4, vfwaddw32) +GEN_VEXT_VV_ENV(vfwadd_wv_h, 2, 4, clearl) +GEN_VEXT_VV_ENV(vfwadd_wv_w, 4, 8, clearq) +RVVCALL(OPFVF2, vfwadd_wf_h, WOP_WUUU_H, H4, H2, vfwaddw16) +RVVCALL(OPFVF2, vfwadd_wf_w, WOP_WUUU_W, H8, H4, vfwaddw32) +GEN_VEXT_VF(vfwadd_wf_h, 2, 4, clearl) +GEN_VEXT_VF(vfwadd_wf_w, 4, 8, clearq) + +static uint32_t vfwsubw16(uint32_t a, uint16_t b, float_status *s) +{ + return float32_sub(a, float16_to_float32(b, true, s), s); +} + +static uint64_t vfwsubw32(uint64_t a, uint32_t b, float_status *s) +{ + return float64_sub(a, float32_to_float64(b, s), s); +} + +RVVCALL(OPFVV2, vfwsub_wv_h, WOP_WUUU_H, H4, H2, H2, vfwsubw16) +RVVCALL(OPFVV2, vfwsub_wv_w, WOP_WUUU_W, H8, H4, H4, vfwsubw32) +GEN_VEXT_VV_ENV(vfwsub_wv_h, 2, 4, clearl) +GEN_VEXT_VV_ENV(vfwsub_wv_w, 4, 8, clearq) +RVVCALL(OPFVF2, vfwsub_wf_h, WOP_WUUU_H, H4, H2, vfwsubw16) +RVVCALL(OPFVF2, vfwsub_wf_w, WOP_WUUU_W, H8, H4, vfwsubw32) +GEN_VEXT_VF(vfwsub_wf_h, 2, 4, clearl) +GEN_VEXT_VF(vfwsub_wf_w, 4, 8, clearq) + +/* Vector Single-Width Floating-Point Multiply/Divide Instructions */ +RVVCALL(OPFVV2, vfmul_vv_h, OP_UUU_H, H2, H2, H2, float16_mul) +RVVCALL(OPFVV2, vfmul_vv_w, OP_UUU_W, H4, H4, H4, float32_mul) +RVVCALL(OPFVV2, vfmul_vv_d, OP_UUU_D, H8, H8, H8, float64_mul) +GEN_VEXT_VV_ENV(vfmul_vv_h, 2, 2, clearh) +GEN_VEXT_VV_ENV(vfmul_vv_w, 4, 4, clearl) +GEN_VEXT_VV_ENV(vfmul_vv_d, 8, 8, clearq) +RVVCALL(OPFVF2, vfmul_vf_h, OP_UUU_H, H2, H2, float16_mul) +RVVCALL(OPFVF2, vfmul_vf_w, OP_UUU_W, H4, H4, float32_mul) +RVVCALL(OPFVF2, vfmul_vf_d, OP_UUU_D, H8, H8, float64_mul) +GEN_VEXT_VF(vfmul_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfmul_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfmul_vf_d, 8, 8, clearq) + +RVVCALL(OPFVV2, vfdiv_vv_h, OP_UUU_H, H2, H2, H2, float16_div) +RVVCALL(OPFVV2, vfdiv_vv_w, OP_UUU_W, H4, H4, H4, float32_div) +RVVCALL(OPFVV2, vfdiv_vv_d, OP_UUU_D, H8, H8, H8, float64_div) +GEN_VEXT_VV_ENV(vfdiv_vv_h, 2, 2, clearh) +GEN_VEXT_VV_ENV(vfdiv_vv_w, 4, 4, clearl) +GEN_VEXT_VV_ENV(vfdiv_vv_d, 8, 8, clearq) +RVVCALL(OPFVF2, vfdiv_vf_h, OP_UUU_H, H2, H2, float16_div) +RVVCALL(OPFVF2, vfdiv_vf_w, OP_UUU_W, H4, H4, float32_div) +RVVCALL(OPFVF2, vfdiv_vf_d, OP_UUU_D, H8, H8, float64_div) +GEN_VEXT_VF(vfdiv_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfdiv_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfdiv_vf_d, 8, 8, clearq) + +static uint16_t float16_rdiv(uint16_t a, uint16_t b, float_status *s) +{ + return float16_div(b, a, s); +} + +static uint32_t float32_rdiv(uint32_t a, uint32_t b, float_status *s) +{ + return float32_div(b, a, s); +} + +static uint64_t float64_rdiv(uint64_t a, uint64_t b, float_status *s) +{ + return float64_div(b, a, s); +} + +RVVCALL(OPFVF2, vfrdiv_vf_h, OP_UUU_H, H2, H2, float16_rdiv) +RVVCALL(OPFVF2, vfrdiv_vf_w, OP_UUU_W, H4, H4, float32_rdiv) +RVVCALL(OPFVF2, vfrdiv_vf_d, OP_UUU_D, H8, H8, float64_rdiv) +GEN_VEXT_VF(vfrdiv_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfrdiv_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfrdiv_vf_d, 8, 8, clearq) + +/* Vector Widening Floating-Point Multiply */ +static uint32_t vfwmul16(uint16_t a, uint16_t b, float_status *s) +{ + return float32_mul(float16_to_float32(a, true, s), + float16_to_float32(b, true, s), s); +} + +static uint64_t vfwmul32(uint32_t a, uint32_t b, float_status *s) +{ + return float64_mul(float32_to_float64(a, s), + float32_to_float64(b, s), s); + +} +RVVCALL(OPFVV2, vfwmul_vv_h, WOP_UUU_H, H4, H2, H2, vfwmul16) +RVVCALL(OPFVV2, vfwmul_vv_w, WOP_UUU_W, H8, H4, H4, vfwmul32) +GEN_VEXT_VV_ENV(vfwmul_vv_h, 2, 4, clearl) +GEN_VEXT_VV_ENV(vfwmul_vv_w, 4, 8, clearq) +RVVCALL(OPFVF2, vfwmul_vf_h, WOP_UUU_H, H4, H2, vfwmul16) +RVVCALL(OPFVF2, vfwmul_vf_w, WOP_UUU_W, H8, H4, vfwmul32) +GEN_VEXT_VF(vfwmul_vf_h, 2, 4, clearl) +GEN_VEXT_VF(vfwmul_vf_w, 4, 8, clearq) + +/* Vector Single-Width Floating-Point Fused Multiply-Add Instructions */ +#define OPFVV3(NAME, TD, T1, T2, TX1, TX2, HD, HS1, HS2, OP) \ +static void do_##NAME(void *vd, void *vs1, void *vs2, int i, \ + CPURISCVState *env) \ +{ \ + TX1 s1 = *((T1 *)vs1 + HS1(i)); \ + TX2 s2 = *((T2 *)vs2 + HS2(i)); \ + TD d = *((TD *)vd + HD(i)); \ + *((TD *)vd + HD(i)) = OP(s2, s1, d, &env->fp_status); \ +} + +static uint16_t fmacc16(uint16_t a, uint16_t b, uint16_t d, float_status *s) +{ + return float16_muladd(a, b, d, 0, s); +} + +static uint32_t fmacc32(uint32_t a, uint32_t b, uint32_t d, float_status *s) +{ + return float32_muladd(a, b, d, 0, s); +} + +static uint64_t fmacc64(uint64_t a, uint64_t b, uint64_t d, float_status *s) +{ + return float64_muladd(a, b, d, 0, s); +} + +RVVCALL(OPFVV3, vfmacc_vv_h, OP_UUU_H, H2, H2, H2, fmacc16) +RVVCALL(OPFVV3, vfmacc_vv_w, OP_UUU_W, H4, H4, H4, fmacc32) +RVVCALL(OPFVV3, vfmacc_vv_d, OP_UUU_D, H8, H8, H8, fmacc64) +GEN_VEXT_VV_ENV(vfmacc_vv_h, 2, 2, clearh) +GEN_VEXT_VV_ENV(vfmacc_vv_w, 4, 4, clearl) +GEN_VEXT_VV_ENV(vfmacc_vv_d, 8, 8, clearq) + +#define OPFVF3(NAME, TD, T1, T2, TX1, TX2, HD, HS2, OP) \ +static void do_##NAME(void *vd, uint64_t s1, void *vs2, int i, \ + CPURISCVState *env) \ +{ \ + TX2 s2 = *((T2 *)vs2 + HS2(i)); \ + TD d = *((TD *)vd + HD(i)); \ + *((TD *)vd + HD(i)) = OP(s2, (TX1)(T1)s1, d, &env->fp_status);\ +} + +RVVCALL(OPFVF3, vfmacc_vf_h, OP_UUU_H, H2, H2, fmacc16) +RVVCALL(OPFVF3, vfmacc_vf_w, OP_UUU_W, H4, H4, fmacc32) +RVVCALL(OPFVF3, vfmacc_vf_d, OP_UUU_D, H8, H8, fmacc64) +GEN_VEXT_VF(vfmacc_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfmacc_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfmacc_vf_d, 8, 8, clearq) + +static uint16_t fnmacc16(uint16_t a, uint16_t b, uint16_t d, float_status *s) +{ + return float16_muladd(a, b, d, + float_muladd_negate_c | float_muladd_negate_product, s); +} + +static uint32_t fnmacc32(uint32_t a, uint32_t b, uint32_t d, float_status *s) +{ + return float32_muladd(a, b, d, + float_muladd_negate_c | float_muladd_negate_product, s); +} + +static uint64_t fnmacc64(uint64_t a, uint64_t b, uint64_t d, float_status *s) +{ + return float64_muladd(a, b, d, + float_muladd_negate_c | float_muladd_negate_product, s); +} + +RVVCALL(OPFVV3, vfnmacc_vv_h, OP_UUU_H, H2, H2, H2, fnmacc16) +RVVCALL(OPFVV3, vfnmacc_vv_w, OP_UUU_W, H4, H4, H4, fnmacc32) +RVVCALL(OPFVV3, vfnmacc_vv_d, OP_UUU_D, H8, H8, H8, fnmacc64) +GEN_VEXT_VV_ENV(vfnmacc_vv_h, 2, 2, clearh) +GEN_VEXT_VV_ENV(vfnmacc_vv_w, 4, 4, clearl) +GEN_VEXT_VV_ENV(vfnmacc_vv_d, 8, 8, clearq) +RVVCALL(OPFVF3, vfnmacc_vf_h, OP_UUU_H, H2, H2, fnmacc16) +RVVCALL(OPFVF3, vfnmacc_vf_w, OP_UUU_W, H4, H4, fnmacc32) +RVVCALL(OPFVF3, vfnmacc_vf_d, OP_UUU_D, H8, H8, fnmacc64) +GEN_VEXT_VF(vfnmacc_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfnmacc_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfnmacc_vf_d, 8, 8, clearq) + +static uint16_t fmsac16(uint16_t a, uint16_t b, uint16_t d, float_status *s) +{ + return float16_muladd(a, b, d, float_muladd_negate_c, s); +} + +static uint32_t fmsac32(uint32_t a, uint32_t b, uint32_t d, float_status *s) +{ + return float32_muladd(a, b, d, float_muladd_negate_c, s); +} + +static uint64_t fmsac64(uint64_t a, uint64_t b, uint64_t d, float_status *s) +{ + return float64_muladd(a, b, d, float_muladd_negate_c, s); +} + +RVVCALL(OPFVV3, vfmsac_vv_h, OP_UUU_H, H2, H2, H2, fmsac16) +RVVCALL(OPFVV3, vfmsac_vv_w, OP_UUU_W, H4, H4, H4, fmsac32) +RVVCALL(OPFVV3, vfmsac_vv_d, OP_UUU_D, H8, H8, H8, fmsac64) +GEN_VEXT_VV_ENV(vfmsac_vv_h, 2, 2, clearh) +GEN_VEXT_VV_ENV(vfmsac_vv_w, 4, 4, clearl) +GEN_VEXT_VV_ENV(vfmsac_vv_d, 8, 8, clearq) +RVVCALL(OPFVF3, vfmsac_vf_h, OP_UUU_H, H2, H2, fmsac16) +RVVCALL(OPFVF3, vfmsac_vf_w, OP_UUU_W, H4, H4, fmsac32) +RVVCALL(OPFVF3, vfmsac_vf_d, OP_UUU_D, H8, H8, fmsac64) +GEN_VEXT_VF(vfmsac_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfmsac_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfmsac_vf_d, 8, 8, clearq) + +static uint16_t fnmsac16(uint16_t a, uint16_t b, uint16_t d, float_status *s) +{ + return float16_muladd(a, b, d, float_muladd_negate_product, s); +} + +static uint32_t fnmsac32(uint32_t a, uint32_t b, uint32_t d, float_status *s) +{ + return float32_muladd(a, b, d, float_muladd_negate_product, s); +} + +static uint64_t fnmsac64(uint64_t a, uint64_t b, uint64_t d, float_status *s) +{ + return float64_muladd(a, b, d, float_muladd_negate_product, s); +} + +RVVCALL(OPFVV3, vfnmsac_vv_h, OP_UUU_H, H2, H2, H2, fnmsac16) +RVVCALL(OPFVV3, vfnmsac_vv_w, OP_UUU_W, H4, H4, H4, fnmsac32) +RVVCALL(OPFVV3, vfnmsac_vv_d, OP_UUU_D, H8, H8, H8, fnmsac64) +GEN_VEXT_VV_ENV(vfnmsac_vv_h, 2, 2, clearh) +GEN_VEXT_VV_ENV(vfnmsac_vv_w, 4, 4, clearl) +GEN_VEXT_VV_ENV(vfnmsac_vv_d, 8, 8, clearq) +RVVCALL(OPFVF3, vfnmsac_vf_h, OP_UUU_H, H2, H2, fnmsac16) +RVVCALL(OPFVF3, vfnmsac_vf_w, OP_UUU_W, H4, H4, fnmsac32) +RVVCALL(OPFVF3, vfnmsac_vf_d, OP_UUU_D, H8, H8, fnmsac64) +GEN_VEXT_VF(vfnmsac_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfnmsac_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfnmsac_vf_d, 8, 8, clearq) + +static uint16_t fmadd16(uint16_t a, uint16_t b, uint16_t d, float_status *s) +{ + return float16_muladd(d, b, a, 0, s); +} + +static uint32_t fmadd32(uint32_t a, uint32_t b, uint32_t d, float_status *s) +{ + return float32_muladd(d, b, a, 0, s); +} + +static uint64_t fmadd64(uint64_t a, uint64_t b, uint64_t d, float_status *s) +{ + return float64_muladd(d, b, a, 0, s); +} + +RVVCALL(OPFVV3, vfmadd_vv_h, OP_UUU_H, H2, H2, H2, fmadd16) +RVVCALL(OPFVV3, vfmadd_vv_w, OP_UUU_W, H4, H4, H4, fmadd32) +RVVCALL(OPFVV3, vfmadd_vv_d, OP_UUU_D, H8, H8, H8, fmadd64) +GEN_VEXT_VV_ENV(vfmadd_vv_h, 2, 2, clearh) +GEN_VEXT_VV_ENV(vfmadd_vv_w, 4, 4, clearl) +GEN_VEXT_VV_ENV(vfmadd_vv_d, 8, 8, clearq) +RVVCALL(OPFVF3, vfmadd_vf_h, OP_UUU_H, H2, H2, fmadd16) +RVVCALL(OPFVF3, vfmadd_vf_w, OP_UUU_W, H4, H4, fmadd32) +RVVCALL(OPFVF3, vfmadd_vf_d, OP_UUU_D, H8, H8, fmadd64) +GEN_VEXT_VF(vfmadd_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfmadd_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfmadd_vf_d, 8, 8, clearq) + +static uint16_t fnmadd16(uint16_t a, uint16_t b, uint16_t d, float_status *s) +{ + return float16_muladd(d, b, a, + float_muladd_negate_c | float_muladd_negate_product, s); +} + +static uint32_t fnmadd32(uint32_t a, uint32_t b, uint32_t d, float_status *s) +{ + return float32_muladd(d, b, a, + float_muladd_negate_c | float_muladd_negate_product, s); +} + +static uint64_t fnmadd64(uint64_t a, uint64_t b, uint64_t d, float_status *s) +{ + return float64_muladd(d, b, a, + float_muladd_negate_c | float_muladd_negate_product, s); +} + +RVVCALL(OPFVV3, vfnmadd_vv_h, OP_UUU_H, H2, H2, H2, fnmadd16) +RVVCALL(OPFVV3, vfnmadd_vv_w, OP_UUU_W, H4, H4, H4, fnmadd32) +RVVCALL(OPFVV3, vfnmadd_vv_d, OP_UUU_D, H8, H8, H8, fnmadd64) +GEN_VEXT_VV_ENV(vfnmadd_vv_h, 2, 2, clearh) +GEN_VEXT_VV_ENV(vfnmadd_vv_w, 4, 4, clearl) +GEN_VEXT_VV_ENV(vfnmadd_vv_d, 8, 8, clearq) +RVVCALL(OPFVF3, vfnmadd_vf_h, OP_UUU_H, H2, H2, fnmadd16) +RVVCALL(OPFVF3, vfnmadd_vf_w, OP_UUU_W, H4, H4, fnmadd32) +RVVCALL(OPFVF3, vfnmadd_vf_d, OP_UUU_D, H8, H8, fnmadd64) +GEN_VEXT_VF(vfnmadd_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfnmadd_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfnmadd_vf_d, 8, 8, clearq) + +static uint16_t fmsub16(uint16_t a, uint16_t b, uint16_t d, float_status *s) +{ + return float16_muladd(d, b, a, float_muladd_negate_c, s); +} + +static uint32_t fmsub32(uint32_t a, uint32_t b, uint32_t d, float_status *s) +{ + return float32_muladd(d, b, a, float_muladd_negate_c, s); +} + +static uint64_t fmsub64(uint64_t a, uint64_t b, uint64_t d, float_status *s) +{ + return float64_muladd(d, b, a, float_muladd_negate_c, s); +} + +RVVCALL(OPFVV3, vfmsub_vv_h, OP_UUU_H, H2, H2, H2, fmsub16) +RVVCALL(OPFVV3, vfmsub_vv_w, OP_UUU_W, H4, H4, H4, fmsub32) +RVVCALL(OPFVV3, vfmsub_vv_d, OP_UUU_D, H8, H8, H8, fmsub64) +GEN_VEXT_VV_ENV(vfmsub_vv_h, 2, 2, clearh) +GEN_VEXT_VV_ENV(vfmsub_vv_w, 4, 4, clearl) +GEN_VEXT_VV_ENV(vfmsub_vv_d, 8, 8, clearq) +RVVCALL(OPFVF3, vfmsub_vf_h, OP_UUU_H, H2, H2, fmsub16) +RVVCALL(OPFVF3, vfmsub_vf_w, OP_UUU_W, H4, H4, fmsub32) +RVVCALL(OPFVF3, vfmsub_vf_d, OP_UUU_D, H8, H8, fmsub64) +GEN_VEXT_VF(vfmsub_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfmsub_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfmsub_vf_d, 8, 8, clearq) + +static uint16_t fnmsub16(uint16_t a, uint16_t b, uint16_t d, float_status *s) +{ + return float16_muladd(d, b, a, float_muladd_negate_product, s); +} + +static uint32_t fnmsub32(uint32_t a, uint32_t b, uint32_t d, float_status *s) +{ + return float32_muladd(d, b, a, float_muladd_negate_product, s); +} + +static uint64_t fnmsub64(uint64_t a, uint64_t b, uint64_t d, float_status *s) +{ + return float64_muladd(d, b, a, float_muladd_negate_product, s); +} + +RVVCALL(OPFVV3, vfnmsub_vv_h, OP_UUU_H, H2, H2, H2, fnmsub16) +RVVCALL(OPFVV3, vfnmsub_vv_w, OP_UUU_W, H4, H4, H4, fnmsub32) +RVVCALL(OPFVV3, vfnmsub_vv_d, OP_UUU_D, H8, H8, H8, fnmsub64) +GEN_VEXT_VV_ENV(vfnmsub_vv_h, 2, 2, clearh) +GEN_VEXT_VV_ENV(vfnmsub_vv_w, 4, 4, clearl) +GEN_VEXT_VV_ENV(vfnmsub_vv_d, 8, 8, clearq) +RVVCALL(OPFVF3, vfnmsub_vf_h, OP_UUU_H, H2, H2, fnmsub16) +RVVCALL(OPFVF3, vfnmsub_vf_w, OP_UUU_W, H4, H4, fnmsub32) +RVVCALL(OPFVF3, vfnmsub_vf_d, OP_UUU_D, H8, H8, fnmsub64) +GEN_VEXT_VF(vfnmsub_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfnmsub_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfnmsub_vf_d, 8, 8, clearq) + +/* Vector Widening Floating-Point Fused Multiply-Add Instructions */ +static uint32_t fwmacc16(uint16_t a, uint16_t b, uint32_t d, float_status *s) +{ + return float32_muladd(float16_to_float32(a, true, s), + float16_to_float32(b, true, s), d, 0, s); +} + +static uint64_t fwmacc32(uint32_t a, uint32_t b, uint64_t d, float_status *s) +{ + return float64_muladd(float32_to_float64(a, s), + float32_to_float64(b, s), d, 0, s); +} + +RVVCALL(OPFVV3, vfwmacc_vv_h, WOP_UUU_H, H4, H2, H2, fwmacc16) +RVVCALL(OPFVV3, vfwmacc_vv_w, WOP_UUU_W, H8, H4, H4, fwmacc32) +GEN_VEXT_VV_ENV(vfwmacc_vv_h, 2, 4, clearl) +GEN_VEXT_VV_ENV(vfwmacc_vv_w, 4, 8, clearq) +RVVCALL(OPFVF3, vfwmacc_vf_h, WOP_UUU_H, H4, H2, fwmacc16) +RVVCALL(OPFVF3, vfwmacc_vf_w, WOP_UUU_W, H8, H4, fwmacc32) +GEN_VEXT_VF(vfwmacc_vf_h, 2, 4, clearl) +GEN_VEXT_VF(vfwmacc_vf_w, 4, 8, clearq) + +static uint32_t fwnmacc16(uint16_t a, uint16_t b, uint32_t d, float_status *s) +{ + return float32_muladd(float16_to_float32(a, true, s), + float16_to_float32(b, true, s), d, + float_muladd_negate_c | float_muladd_negate_product, s); +} + +static uint64_t fwnmacc32(uint32_t a, uint32_t b, uint64_t d, float_status *s) +{ + return float64_muladd(float32_to_float64(a, s), + float32_to_float64(b, s), d, + float_muladd_negate_c | float_muladd_negate_product, s); +} + +RVVCALL(OPFVV3, vfwnmacc_vv_h, WOP_UUU_H, H4, H2, H2, fwnmacc16) +RVVCALL(OPFVV3, vfwnmacc_vv_w, WOP_UUU_W, H8, H4, H4, fwnmacc32) +GEN_VEXT_VV_ENV(vfwnmacc_vv_h, 2, 4, clearl) +GEN_VEXT_VV_ENV(vfwnmacc_vv_w, 4, 8, clearq) +RVVCALL(OPFVF3, vfwnmacc_vf_h, WOP_UUU_H, H4, H2, fwnmacc16) +RVVCALL(OPFVF3, vfwnmacc_vf_w, WOP_UUU_W, H8, H4, fwnmacc32) +GEN_VEXT_VF(vfwnmacc_vf_h, 2, 4, clearl) +GEN_VEXT_VF(vfwnmacc_vf_w, 4, 8, clearq) + +static uint32_t fwmsac16(uint16_t a, uint16_t b, uint32_t d, float_status *s) +{ + return float32_muladd(float16_to_float32(a, true, s), + float16_to_float32(b, true, s), d, + float_muladd_negate_c, s); +} + +static uint64_t fwmsac32(uint32_t a, uint32_t b, uint64_t d, float_status *s) +{ + return float64_muladd(float32_to_float64(a, s), + float32_to_float64(b, s), d, + float_muladd_negate_c, s); +} + +RVVCALL(OPFVV3, vfwmsac_vv_h, WOP_UUU_H, H4, H2, H2, fwmsac16) +RVVCALL(OPFVV3, vfwmsac_vv_w, WOP_UUU_W, H8, H4, H4, fwmsac32) +GEN_VEXT_VV_ENV(vfwmsac_vv_h, 2, 4, clearl) +GEN_VEXT_VV_ENV(vfwmsac_vv_w, 4, 8, clearq) +RVVCALL(OPFVF3, vfwmsac_vf_h, WOP_UUU_H, H4, H2, fwmsac16) +RVVCALL(OPFVF3, vfwmsac_vf_w, WOP_UUU_W, H8, H4, fwmsac32) +GEN_VEXT_VF(vfwmsac_vf_h, 2, 4, clearl) +GEN_VEXT_VF(vfwmsac_vf_w, 4, 8, clearq) + +static uint32_t fwnmsac16(uint16_t a, uint16_t b, uint32_t d, float_status *s) +{ + return float32_muladd(float16_to_float32(a, true, s), + float16_to_float32(b, true, s), d, + float_muladd_negate_product, s); +} + +static uint64_t fwnmsac32(uint32_t a, uint32_t b, uint64_t d, float_status *s) +{ + return float64_muladd(float32_to_float64(a, s), + float32_to_float64(b, s), d, + float_muladd_negate_product, s); +} + +RVVCALL(OPFVV3, vfwnmsac_vv_h, WOP_UUU_H, H4, H2, H2, fwnmsac16) +RVVCALL(OPFVV3, vfwnmsac_vv_w, WOP_UUU_W, H8, H4, H4, fwnmsac32) +GEN_VEXT_VV_ENV(vfwnmsac_vv_h, 2, 4, clearl) +GEN_VEXT_VV_ENV(vfwnmsac_vv_w, 4, 8, clearq) +RVVCALL(OPFVF3, vfwnmsac_vf_h, WOP_UUU_H, H4, H2, fwnmsac16) +RVVCALL(OPFVF3, vfwnmsac_vf_w, WOP_UUU_W, H8, H4, fwnmsac32) +GEN_VEXT_VF(vfwnmsac_vf_h, 2, 4, clearl) +GEN_VEXT_VF(vfwnmsac_vf_w, 4, 8, clearq) + +/* Vector Floating-Point Square-Root Instruction */ +/* (TD, T2, TX2) */ +#define OP_UU_H uint16_t, uint16_t, uint16_t +#define OP_UU_W uint32_t, uint32_t, uint32_t +#define OP_UU_D uint64_t, uint64_t, uint64_t + +#define OPFVV1(NAME, TD, T2, TX2, HD, HS2, OP) \ +static void do_##NAME(void *vd, void *vs2, int i, \ + CPURISCVState *env) \ +{ \ + TX2 s2 = *((T2 *)vs2 + HS2(i)); \ + *((TD *)vd + HD(i)) = OP(s2, &env->fp_status); \ +} + +#define GEN_VEXT_V_ENV(NAME, ESZ, DSZ, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t vlmax = vext_maxsz(desc) / ESZ; \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t i; \ + \ + if (vl == 0) { \ + return; \ + } \ + for (i = 0; i < vl; i++) { \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + do_##NAME(vd, vs2, i, env); \ + } \ + CLEAR_FN(vd, vl, vl * DSZ, vlmax * DSZ); \ +} + +RVVCALL(OPFVV1, vfsqrt_v_h, OP_UU_H, H2, H2, float16_sqrt) +RVVCALL(OPFVV1, vfsqrt_v_w, OP_UU_W, H4, H4, float32_sqrt) +RVVCALL(OPFVV1, vfsqrt_v_d, OP_UU_D, H8, H8, float64_sqrt) +GEN_VEXT_V_ENV(vfsqrt_v_h, 2, 2, clearh) +GEN_VEXT_V_ENV(vfsqrt_v_w, 4, 4, clearl) +GEN_VEXT_V_ENV(vfsqrt_v_d, 8, 8, clearq) + +/* Vector Floating-Point MIN/MAX Instructions */ +RVVCALL(OPFVV2, vfmin_vv_h, OP_UUU_H, H2, H2, H2, float16_minnum) +RVVCALL(OPFVV2, vfmin_vv_w, OP_UUU_W, H4, H4, H4, float32_minnum) +RVVCALL(OPFVV2, vfmin_vv_d, OP_UUU_D, H8, H8, H8, float64_minnum) +GEN_VEXT_VV_ENV(vfmin_vv_h, 2, 2, clearh) +GEN_VEXT_VV_ENV(vfmin_vv_w, 4, 4, clearl) +GEN_VEXT_VV_ENV(vfmin_vv_d, 8, 8, clearq) +RVVCALL(OPFVF2, vfmin_vf_h, OP_UUU_H, H2, H2, float16_minnum) +RVVCALL(OPFVF2, vfmin_vf_w, OP_UUU_W, H4, H4, float32_minnum) +RVVCALL(OPFVF2, vfmin_vf_d, OP_UUU_D, H8, H8, float64_minnum) +GEN_VEXT_VF(vfmin_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfmin_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfmin_vf_d, 8, 8, clearq) + +RVVCALL(OPFVV2, vfmax_vv_h, OP_UUU_H, H2, H2, H2, float16_maxnum) +RVVCALL(OPFVV2, vfmax_vv_w, OP_UUU_W, H4, H4, H4, float32_maxnum) +RVVCALL(OPFVV2, vfmax_vv_d, OP_UUU_D, H8, H8, H8, float64_maxnum) +GEN_VEXT_VV_ENV(vfmax_vv_h, 2, 2, clearh) +GEN_VEXT_VV_ENV(vfmax_vv_w, 4, 4, clearl) +GEN_VEXT_VV_ENV(vfmax_vv_d, 8, 8, clearq) +RVVCALL(OPFVF2, vfmax_vf_h, OP_UUU_H, H2, H2, float16_maxnum) +RVVCALL(OPFVF2, vfmax_vf_w, OP_UUU_W, H4, H4, float32_maxnum) +RVVCALL(OPFVF2, vfmax_vf_d, OP_UUU_D, H8, H8, float64_maxnum) +GEN_VEXT_VF(vfmax_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfmax_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfmax_vf_d, 8, 8, clearq) + +/* Vector Floating-Point Sign-Injection Instructions */ +static uint16_t fsgnj16(uint16_t a, uint16_t b, float_status *s) +{ + return deposit64(b, 0, 15, a); +} + +static uint32_t fsgnj32(uint32_t a, uint32_t b, float_status *s) +{ + return deposit64(b, 0, 31, a); +} + +static uint64_t fsgnj64(uint64_t a, uint64_t b, float_status *s) +{ + return deposit64(b, 0, 63, a); +} + +RVVCALL(OPFVV2, vfsgnj_vv_h, OP_UUU_H, H2, H2, H2, fsgnj16) +RVVCALL(OPFVV2, vfsgnj_vv_w, OP_UUU_W, H4, H4, H4, fsgnj32) +RVVCALL(OPFVV2, vfsgnj_vv_d, OP_UUU_D, H8, H8, H8, fsgnj64) +GEN_VEXT_VV_ENV(vfsgnj_vv_h, 2, 2, clearh) +GEN_VEXT_VV_ENV(vfsgnj_vv_w, 4, 4, clearl) +GEN_VEXT_VV_ENV(vfsgnj_vv_d, 8, 8, clearq) +RVVCALL(OPFVF2, vfsgnj_vf_h, OP_UUU_H, H2, H2, fsgnj16) +RVVCALL(OPFVF2, vfsgnj_vf_w, OP_UUU_W, H4, H4, fsgnj32) +RVVCALL(OPFVF2, vfsgnj_vf_d, OP_UUU_D, H8, H8, fsgnj64) +GEN_VEXT_VF(vfsgnj_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfsgnj_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfsgnj_vf_d, 8, 8, clearq) + +static uint16_t fsgnjn16(uint16_t a, uint16_t b, float_status *s) +{ + return deposit64(~b, 0, 15, a); +} + +static uint32_t fsgnjn32(uint32_t a, uint32_t b, float_status *s) +{ + return deposit64(~b, 0, 31, a); +} + +static uint64_t fsgnjn64(uint64_t a, uint64_t b, float_status *s) +{ + return deposit64(~b, 0, 63, a); +} + +RVVCALL(OPFVV2, vfsgnjn_vv_h, OP_UUU_H, H2, H2, H2, fsgnjn16) +RVVCALL(OPFVV2, vfsgnjn_vv_w, OP_UUU_W, H4, H4, H4, fsgnjn32) +RVVCALL(OPFVV2, vfsgnjn_vv_d, OP_UUU_D, H8, H8, H8, fsgnjn64) +GEN_VEXT_VV_ENV(vfsgnjn_vv_h, 2, 2, clearh) +GEN_VEXT_VV_ENV(vfsgnjn_vv_w, 4, 4, clearl) +GEN_VEXT_VV_ENV(vfsgnjn_vv_d, 8, 8, clearq) +RVVCALL(OPFVF2, vfsgnjn_vf_h, OP_UUU_H, H2, H2, fsgnjn16) +RVVCALL(OPFVF2, vfsgnjn_vf_w, OP_UUU_W, H4, H4, fsgnjn32) +RVVCALL(OPFVF2, vfsgnjn_vf_d, OP_UUU_D, H8, H8, fsgnjn64) +GEN_VEXT_VF(vfsgnjn_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfsgnjn_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfsgnjn_vf_d, 8, 8, clearq) + +static uint16_t fsgnjx16(uint16_t a, uint16_t b, float_status *s) +{ + return deposit64(b ^ a, 0, 15, a); +} + +static uint32_t fsgnjx32(uint32_t a, uint32_t b, float_status *s) +{ + return deposit64(b ^ a, 0, 31, a); +} + +static uint64_t fsgnjx64(uint64_t a, uint64_t b, float_status *s) +{ + return deposit64(b ^ a, 0, 63, a); +} + +RVVCALL(OPFVV2, vfsgnjx_vv_h, OP_UUU_H, H2, H2, H2, fsgnjx16) +RVVCALL(OPFVV2, vfsgnjx_vv_w, OP_UUU_W, H4, H4, H4, fsgnjx32) +RVVCALL(OPFVV2, vfsgnjx_vv_d, OP_UUU_D, H8, H8, H8, fsgnjx64) +GEN_VEXT_VV_ENV(vfsgnjx_vv_h, 2, 2, clearh) +GEN_VEXT_VV_ENV(vfsgnjx_vv_w, 4, 4, clearl) +GEN_VEXT_VV_ENV(vfsgnjx_vv_d, 8, 8, clearq) +RVVCALL(OPFVF2, vfsgnjx_vf_h, OP_UUU_H, H2, H2, fsgnjx16) +RVVCALL(OPFVF2, vfsgnjx_vf_w, OP_UUU_W, H4, H4, fsgnjx32) +RVVCALL(OPFVF2, vfsgnjx_vf_d, OP_UUU_D, H8, H8, fsgnjx64) +GEN_VEXT_VF(vfsgnjx_vf_h, 2, 2, clearh) +GEN_VEXT_VF(vfsgnjx_vf_w, 4, 4, clearl) +GEN_VEXT_VF(vfsgnjx_vf_d, 8, 8, clearq) + +/* Vector Floating-Point Compare Instructions */ +#define GEN_VEXT_CMP_VV_ENV(NAME, ETYPE, H, DO_OP) \ +void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t vlmax = vext_maxsz(desc) / sizeof(ETYPE); \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + ETYPE s1 = *((ETYPE *)vs1 + H(i)); \ + ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + vext_set_elem_mask(vd, mlen, i, \ + DO_OP(s2, s1, &env->fp_status)); \ + } \ + for (; i < vlmax; i++) { \ + vext_set_elem_mask(vd, mlen, i, 0); \ + } \ +} + +GEN_VEXT_CMP_VV_ENV(vmfeq_vv_h, uint16_t, H2, float16_eq_quiet) +GEN_VEXT_CMP_VV_ENV(vmfeq_vv_w, uint32_t, H4, float32_eq_quiet) +GEN_VEXT_CMP_VV_ENV(vmfeq_vv_d, uint64_t, H8, float64_eq_quiet) + +#define GEN_VEXT_CMP_VF(NAME, ETYPE, H, DO_OP) \ +void HELPER(NAME)(void *vd, void *v0, uint64_t s1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t vlmax = vext_maxsz(desc) / sizeof(ETYPE); \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + vext_set_elem_mask(vd, mlen, i, \ + DO_OP(s2, (ETYPE)s1, &env->fp_status)); \ + } \ + for (; i < vlmax; i++) { \ + vext_set_elem_mask(vd, mlen, i, 0); \ + } \ +} + +GEN_VEXT_CMP_VF(vmfeq_vf_h, uint16_t, H2, float16_eq_quiet) +GEN_VEXT_CMP_VF(vmfeq_vf_w, uint32_t, H4, float32_eq_quiet) +GEN_VEXT_CMP_VF(vmfeq_vf_d, uint64_t, H8, float64_eq_quiet) + +static bool vmfne16(uint16_t a, uint16_t b, float_status *s) +{ + FloatRelation compare = float16_compare_quiet(a, b, s); + return compare != float_relation_equal; +} + +static bool vmfne32(uint32_t a, uint32_t b, float_status *s) +{ + FloatRelation compare = float32_compare_quiet(a, b, s); + return compare != float_relation_equal; +} + +static bool vmfne64(uint64_t a, uint64_t b, float_status *s) +{ + FloatRelation compare = float64_compare_quiet(a, b, s); + return compare != float_relation_equal; +} + +GEN_VEXT_CMP_VV_ENV(vmfne_vv_h, uint16_t, H2, vmfne16) +GEN_VEXT_CMP_VV_ENV(vmfne_vv_w, uint32_t, H4, vmfne32) +GEN_VEXT_CMP_VV_ENV(vmfne_vv_d, uint64_t, H8, vmfne64) +GEN_VEXT_CMP_VF(vmfne_vf_h, uint16_t, H2, vmfne16) +GEN_VEXT_CMP_VF(vmfne_vf_w, uint32_t, H4, vmfne32) +GEN_VEXT_CMP_VF(vmfne_vf_d, uint64_t, H8, vmfne64) + +GEN_VEXT_CMP_VV_ENV(vmflt_vv_h, uint16_t, H2, float16_lt) +GEN_VEXT_CMP_VV_ENV(vmflt_vv_w, uint32_t, H4, float32_lt) +GEN_VEXT_CMP_VV_ENV(vmflt_vv_d, uint64_t, H8, float64_lt) +GEN_VEXT_CMP_VF(vmflt_vf_h, uint16_t, H2, float16_lt) +GEN_VEXT_CMP_VF(vmflt_vf_w, uint32_t, H4, float32_lt) +GEN_VEXT_CMP_VF(vmflt_vf_d, uint64_t, H8, float64_lt) + +GEN_VEXT_CMP_VV_ENV(vmfle_vv_h, uint16_t, H2, float16_le) +GEN_VEXT_CMP_VV_ENV(vmfle_vv_w, uint32_t, H4, float32_le) +GEN_VEXT_CMP_VV_ENV(vmfle_vv_d, uint64_t, H8, float64_le) +GEN_VEXT_CMP_VF(vmfle_vf_h, uint16_t, H2, float16_le) +GEN_VEXT_CMP_VF(vmfle_vf_w, uint32_t, H4, float32_le) +GEN_VEXT_CMP_VF(vmfle_vf_d, uint64_t, H8, float64_le) + +static bool vmfgt16(uint16_t a, uint16_t b, float_status *s) +{ + FloatRelation compare = float16_compare(a, b, s); + return compare == float_relation_greater; +} + +static bool vmfgt32(uint32_t a, uint32_t b, float_status *s) +{ + FloatRelation compare = float32_compare(a, b, s); + return compare == float_relation_greater; +} + +static bool vmfgt64(uint64_t a, uint64_t b, float_status *s) +{ + FloatRelation compare = float64_compare(a, b, s); + return compare == float_relation_greater; +} + +GEN_VEXT_CMP_VF(vmfgt_vf_h, uint16_t, H2, vmfgt16) +GEN_VEXT_CMP_VF(vmfgt_vf_w, uint32_t, H4, vmfgt32) +GEN_VEXT_CMP_VF(vmfgt_vf_d, uint64_t, H8, vmfgt64) + +static bool vmfge16(uint16_t a, uint16_t b, float_status *s) +{ + FloatRelation compare = float16_compare(a, b, s); + return compare == float_relation_greater || + compare == float_relation_equal; +} + +static bool vmfge32(uint32_t a, uint32_t b, float_status *s) +{ + FloatRelation compare = float32_compare(a, b, s); + return compare == float_relation_greater || + compare == float_relation_equal; +} + +static bool vmfge64(uint64_t a, uint64_t b, float_status *s) +{ + FloatRelation compare = float64_compare(a, b, s); + return compare == float_relation_greater || + compare == float_relation_equal; +} + +GEN_VEXT_CMP_VF(vmfge_vf_h, uint16_t, H2, vmfge16) +GEN_VEXT_CMP_VF(vmfge_vf_w, uint32_t, H4, vmfge32) +GEN_VEXT_CMP_VF(vmfge_vf_d, uint64_t, H8, vmfge64) + +GEN_VEXT_CMP_VV_ENV(vmford_vv_h, uint16_t, H2, !float16_unordered_quiet) +GEN_VEXT_CMP_VV_ENV(vmford_vv_w, uint32_t, H4, !float32_unordered_quiet) +GEN_VEXT_CMP_VV_ENV(vmford_vv_d, uint64_t, H8, !float64_unordered_quiet) +GEN_VEXT_CMP_VF(vmford_vf_h, uint16_t, H2, !float16_unordered_quiet) +GEN_VEXT_CMP_VF(vmford_vf_w, uint32_t, H4, !float32_unordered_quiet) +GEN_VEXT_CMP_VF(vmford_vf_d, uint64_t, H8, !float64_unordered_quiet) + +/* Vector Floating-Point Classify Instruction */ +#define OPIVV1(NAME, TD, T2, TX2, HD, HS2, OP) \ +static void do_##NAME(void *vd, void *vs2, int i) \ +{ \ + TX2 s2 = *((T2 *)vs2 + HS2(i)); \ + *((TD *)vd + HD(i)) = OP(s2); \ +} + +#define GEN_VEXT_V(NAME, ESZ, DSZ, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t vlmax = vext_maxsz(desc) / ESZ; \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + do_##NAME(vd, vs2, i); \ + } \ + CLEAR_FN(vd, vl, vl * DSZ, vlmax * DSZ); \ +} + +target_ulong fclass_h(uint64_t frs1) +{ + float16 f = frs1; + bool sign = float16_is_neg(f); + + if (float16_is_infinity(f)) { + return sign ? 1 << 0 : 1 << 7; + } else if (float16_is_zero(f)) { + return sign ? 1 << 3 : 1 << 4; + } else if (float16_is_zero_or_denormal(f)) { + return sign ? 1 << 2 : 1 << 5; + } else if (float16_is_any_nan(f)) { + float_status s = { }; /* for snan_bit_is_one */ + return float16_is_quiet_nan(f, &s) ? 1 << 9 : 1 << 8; + } else { + return sign ? 1 << 1 : 1 << 6; + } +} + +target_ulong fclass_s(uint64_t frs1) +{ + float32 f = frs1; + bool sign = float32_is_neg(f); + + if (float32_is_infinity(f)) { + return sign ? 1 << 0 : 1 << 7; + } else if (float32_is_zero(f)) { + return sign ? 1 << 3 : 1 << 4; + } else if (float32_is_zero_or_denormal(f)) { + return sign ? 1 << 2 : 1 << 5; + } else if (float32_is_any_nan(f)) { + float_status s = { }; /* for snan_bit_is_one */ + return float32_is_quiet_nan(f, &s) ? 1 << 9 : 1 << 8; + } else { + return sign ? 1 << 1 : 1 << 6; + } +} + +target_ulong fclass_d(uint64_t frs1) +{ + float64 f = frs1; + bool sign = float64_is_neg(f); + + if (float64_is_infinity(f)) { + return sign ? 1 << 0 : 1 << 7; + } else if (float64_is_zero(f)) { + return sign ? 1 << 3 : 1 << 4; + } else if (float64_is_zero_or_denormal(f)) { + return sign ? 1 << 2 : 1 << 5; + } else if (float64_is_any_nan(f)) { + float_status s = { }; /* for snan_bit_is_one */ + return float64_is_quiet_nan(f, &s) ? 1 << 9 : 1 << 8; + } else { + return sign ? 1 << 1 : 1 << 6; + } +} + +RVVCALL(OPIVV1, vfclass_v_h, OP_UU_H, H2, H2, fclass_h) +RVVCALL(OPIVV1, vfclass_v_w, OP_UU_W, H4, H4, fclass_s) +RVVCALL(OPIVV1, vfclass_v_d, OP_UU_D, H8, H8, fclass_d) +GEN_VEXT_V(vfclass_v_h, 2, 2, clearh) +GEN_VEXT_V(vfclass_v_w, 4, 4, clearl) +GEN_VEXT_V(vfclass_v_d, 8, 8, clearq) + +/* Vector Floating-Point Merge Instruction */ +#define GEN_VFMERGE_VF(NAME, ETYPE, H, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, uint64_t s1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t esz = sizeof(ETYPE); \ + uint32_t vlmax = vext_maxsz(desc) / esz; \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ + *((ETYPE *)vd + H(i)) \ + = (!vm && !vext_elem_mask(v0, mlen, i) ? s2 : s1); \ + } \ + CLEAR_FN(vd, vl, vl * esz, vlmax * esz); \ +} + +GEN_VFMERGE_VF(vfmerge_vfm_h, int16_t, H2, clearh) +GEN_VFMERGE_VF(vfmerge_vfm_w, int32_t, H4, clearl) +GEN_VFMERGE_VF(vfmerge_vfm_d, int64_t, H8, clearq) + +/* Single-Width Floating-Point/Integer Type-Convert Instructions */ +/* vfcvt.xu.f.v vd, vs2, vm # Convert float to unsigned integer. */ +RVVCALL(OPFVV1, vfcvt_xu_f_v_h, OP_UU_H, H2, H2, float16_to_uint16) +RVVCALL(OPFVV1, vfcvt_xu_f_v_w, OP_UU_W, H4, H4, float32_to_uint32) +RVVCALL(OPFVV1, vfcvt_xu_f_v_d, OP_UU_D, H8, H8, float64_to_uint64) +GEN_VEXT_V_ENV(vfcvt_xu_f_v_h, 2, 2, clearh) +GEN_VEXT_V_ENV(vfcvt_xu_f_v_w, 4, 4, clearl) +GEN_VEXT_V_ENV(vfcvt_xu_f_v_d, 8, 8, clearq) + +/* vfcvt.x.f.v vd, vs2, vm # Convert float to signed integer. */ +RVVCALL(OPFVV1, vfcvt_x_f_v_h, OP_UU_H, H2, H2, float16_to_int16) +RVVCALL(OPFVV1, vfcvt_x_f_v_w, OP_UU_W, H4, H4, float32_to_int32) +RVVCALL(OPFVV1, vfcvt_x_f_v_d, OP_UU_D, H8, H8, float64_to_int64) +GEN_VEXT_V_ENV(vfcvt_x_f_v_h, 2, 2, clearh) +GEN_VEXT_V_ENV(vfcvt_x_f_v_w, 4, 4, clearl) +GEN_VEXT_V_ENV(vfcvt_x_f_v_d, 8, 8, clearq) + +/* vfcvt.f.xu.v vd, vs2, vm # Convert unsigned integer to float. */ +RVVCALL(OPFVV1, vfcvt_f_xu_v_h, OP_UU_H, H2, H2, uint16_to_float16) +RVVCALL(OPFVV1, vfcvt_f_xu_v_w, OP_UU_W, H4, H4, uint32_to_float32) +RVVCALL(OPFVV1, vfcvt_f_xu_v_d, OP_UU_D, H8, H8, uint64_to_float64) +GEN_VEXT_V_ENV(vfcvt_f_xu_v_h, 2, 2, clearh) +GEN_VEXT_V_ENV(vfcvt_f_xu_v_w, 4, 4, clearl) +GEN_VEXT_V_ENV(vfcvt_f_xu_v_d, 8, 8, clearq) + +/* vfcvt.f.x.v vd, vs2, vm # Convert integer to float. */ +RVVCALL(OPFVV1, vfcvt_f_x_v_h, OP_UU_H, H2, H2, int16_to_float16) +RVVCALL(OPFVV1, vfcvt_f_x_v_w, OP_UU_W, H4, H4, int32_to_float32) +RVVCALL(OPFVV1, vfcvt_f_x_v_d, OP_UU_D, H8, H8, int64_to_float64) +GEN_VEXT_V_ENV(vfcvt_f_x_v_h, 2, 2, clearh) +GEN_VEXT_V_ENV(vfcvt_f_x_v_w, 4, 4, clearl) +GEN_VEXT_V_ENV(vfcvt_f_x_v_d, 8, 8, clearq) + +/* Widening Floating-Point/Integer Type-Convert Instructions */ +/* (TD, T2, TX2) */ +#define WOP_UU_H uint32_t, uint16_t, uint16_t +#define WOP_UU_W uint64_t, uint32_t, uint32_t +/* vfwcvt.xu.f.v vd, vs2, vm # Convert float to double-width unsigned integer.*/ +RVVCALL(OPFVV1, vfwcvt_xu_f_v_h, WOP_UU_H, H4, H2, float16_to_uint32) +RVVCALL(OPFVV1, vfwcvt_xu_f_v_w, WOP_UU_W, H8, H4, float32_to_uint64) +GEN_VEXT_V_ENV(vfwcvt_xu_f_v_h, 2, 4, clearl) +GEN_VEXT_V_ENV(vfwcvt_xu_f_v_w, 4, 8, clearq) + +/* vfwcvt.x.f.v vd, vs2, vm # Convert float to double-width signed integer. */ +RVVCALL(OPFVV1, vfwcvt_x_f_v_h, WOP_UU_H, H4, H2, float16_to_int32) +RVVCALL(OPFVV1, vfwcvt_x_f_v_w, WOP_UU_W, H8, H4, float32_to_int64) +GEN_VEXT_V_ENV(vfwcvt_x_f_v_h, 2, 4, clearl) +GEN_VEXT_V_ENV(vfwcvt_x_f_v_w, 4, 8, clearq) + +/* vfwcvt.f.xu.v vd, vs2, vm # Convert unsigned integer to double-width float */ +RVVCALL(OPFVV1, vfwcvt_f_xu_v_h, WOP_UU_H, H4, H2, uint16_to_float32) +RVVCALL(OPFVV1, vfwcvt_f_xu_v_w, WOP_UU_W, H8, H4, uint32_to_float64) +GEN_VEXT_V_ENV(vfwcvt_f_xu_v_h, 2, 4, clearl) +GEN_VEXT_V_ENV(vfwcvt_f_xu_v_w, 4, 8, clearq) + +/* vfwcvt.f.x.v vd, vs2, vm # Convert integer to double-width float. */ +RVVCALL(OPFVV1, vfwcvt_f_x_v_h, WOP_UU_H, H4, H2, int16_to_float32) +RVVCALL(OPFVV1, vfwcvt_f_x_v_w, WOP_UU_W, H8, H4, int32_to_float64) +GEN_VEXT_V_ENV(vfwcvt_f_x_v_h, 2, 4, clearl) +GEN_VEXT_V_ENV(vfwcvt_f_x_v_w, 4, 8, clearq) + +/* + * vfwcvt.f.f.v vd, vs2, vm # + * Convert single-width float to double-width float. + */ +static uint32_t vfwcvtffv16(uint16_t a, float_status *s) +{ + return float16_to_float32(a, true, s); +} + +RVVCALL(OPFVV1, vfwcvt_f_f_v_h, WOP_UU_H, H4, H2, vfwcvtffv16) +RVVCALL(OPFVV1, vfwcvt_f_f_v_w, WOP_UU_W, H8, H4, float32_to_float64) +GEN_VEXT_V_ENV(vfwcvt_f_f_v_h, 2, 4, clearl) +GEN_VEXT_V_ENV(vfwcvt_f_f_v_w, 4, 8, clearq) + +/* Narrowing Floating-Point/Integer Type-Convert Instructions */ +/* (TD, T2, TX2) */ +#define NOP_UU_H uint16_t, uint32_t, uint32_t +#define NOP_UU_W uint32_t, uint64_t, uint64_t +/* vfncvt.xu.f.v vd, vs2, vm # Convert float to unsigned integer. */ +RVVCALL(OPFVV1, vfncvt_xu_f_v_h, NOP_UU_H, H2, H4, float32_to_uint16) +RVVCALL(OPFVV1, vfncvt_xu_f_v_w, NOP_UU_W, H4, H8, float64_to_uint32) +GEN_VEXT_V_ENV(vfncvt_xu_f_v_h, 2, 2, clearh) +GEN_VEXT_V_ENV(vfncvt_xu_f_v_w, 4, 4, clearl) + +/* vfncvt.x.f.v vd, vs2, vm # Convert double-width float to signed integer. */ +RVVCALL(OPFVV1, vfncvt_x_f_v_h, NOP_UU_H, H2, H4, float32_to_int16) +RVVCALL(OPFVV1, vfncvt_x_f_v_w, NOP_UU_W, H4, H8, float64_to_int32) +GEN_VEXT_V_ENV(vfncvt_x_f_v_h, 2, 2, clearh) +GEN_VEXT_V_ENV(vfncvt_x_f_v_w, 4, 4, clearl) + +/* vfncvt.f.xu.v vd, vs2, vm # Convert double-width unsigned integer to float */ +RVVCALL(OPFVV1, vfncvt_f_xu_v_h, NOP_UU_H, H2, H4, uint32_to_float16) +RVVCALL(OPFVV1, vfncvt_f_xu_v_w, NOP_UU_W, H4, H8, uint64_to_float32) +GEN_VEXT_V_ENV(vfncvt_f_xu_v_h, 2, 2, clearh) +GEN_VEXT_V_ENV(vfncvt_f_xu_v_w, 4, 4, clearl) + +/* vfncvt.f.x.v vd, vs2, vm # Convert double-width integer to float. */ +RVVCALL(OPFVV1, vfncvt_f_x_v_h, NOP_UU_H, H2, H4, int32_to_float16) +RVVCALL(OPFVV1, vfncvt_f_x_v_w, NOP_UU_W, H4, H8, int64_to_float32) +GEN_VEXT_V_ENV(vfncvt_f_x_v_h, 2, 2, clearh) +GEN_VEXT_V_ENV(vfncvt_f_x_v_w, 4, 4, clearl) + +/* vfncvt.f.f.v vd, vs2, vm # Convert double float to single-width float. */ +static uint16_t vfncvtffv16(uint32_t a, float_status *s) +{ + return float32_to_float16(a, true, s); +} + +RVVCALL(OPFVV1, vfncvt_f_f_v_h, NOP_UU_H, H2, H4, vfncvtffv16) +RVVCALL(OPFVV1, vfncvt_f_f_v_w, NOP_UU_W, H4, H8, float64_to_float32) +GEN_VEXT_V_ENV(vfncvt_f_f_v_h, 2, 2, clearh) +GEN_VEXT_V_ENV(vfncvt_f_f_v_w, 4, 4, clearl) + +/* + *** Vector Reduction Operations + */ +/* Vector Single-Width Integer Reduction Instructions */ +#define GEN_VEXT_RED(NAME, TD, TS2, HD, HS2, OP, CLEAR_FN)\ +void HELPER(NAME)(void *vd, void *v0, void *vs1, \ + void *vs2, CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t i; \ + uint32_t tot = env_archcpu(env)->cfg.vlen / 8; \ + TD s1 = *((TD *)vs1 + HD(0)); \ + \ + for (i = 0; i < vl; i++) { \ + TS2 s2 = *((TS2 *)vs2 + HS2(i)); \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + s1 = OP(s1, (TD)s2); \ + } \ + *((TD *)vd + HD(0)) = s1; \ + CLEAR_FN(vd, 1, sizeof(TD), tot); \ +} + +/* vd[0] = sum(vs1[0], vs2[*]) */ +GEN_VEXT_RED(vredsum_vs_b, int8_t, int8_t, H1, H1, DO_ADD, clearb) +GEN_VEXT_RED(vredsum_vs_h, int16_t, int16_t, H2, H2, DO_ADD, clearh) +GEN_VEXT_RED(vredsum_vs_w, int32_t, int32_t, H4, H4, DO_ADD, clearl) +GEN_VEXT_RED(vredsum_vs_d, int64_t, int64_t, H8, H8, DO_ADD, clearq) + +/* vd[0] = maxu(vs1[0], vs2[*]) */ +GEN_VEXT_RED(vredmaxu_vs_b, uint8_t, uint8_t, H1, H1, DO_MAX, clearb) +GEN_VEXT_RED(vredmaxu_vs_h, uint16_t, uint16_t, H2, H2, DO_MAX, clearh) +GEN_VEXT_RED(vredmaxu_vs_w, uint32_t, uint32_t, H4, H4, DO_MAX, clearl) +GEN_VEXT_RED(vredmaxu_vs_d, uint64_t, uint64_t, H8, H8, DO_MAX, clearq) + +/* vd[0] = max(vs1[0], vs2[*]) */ +GEN_VEXT_RED(vredmax_vs_b, int8_t, int8_t, H1, H1, DO_MAX, clearb) +GEN_VEXT_RED(vredmax_vs_h, int16_t, int16_t, H2, H2, DO_MAX, clearh) +GEN_VEXT_RED(vredmax_vs_w, int32_t, int32_t, H4, H4, DO_MAX, clearl) +GEN_VEXT_RED(vredmax_vs_d, int64_t, int64_t, H8, H8, DO_MAX, clearq) + +/* vd[0] = minu(vs1[0], vs2[*]) */ +GEN_VEXT_RED(vredminu_vs_b, uint8_t, uint8_t, H1, H1, DO_MIN, clearb) +GEN_VEXT_RED(vredminu_vs_h, uint16_t, uint16_t, H2, H2, DO_MIN, clearh) +GEN_VEXT_RED(vredminu_vs_w, uint32_t, uint32_t, H4, H4, DO_MIN, clearl) +GEN_VEXT_RED(vredminu_vs_d, uint64_t, uint64_t, H8, H8, DO_MIN, clearq) + +/* vd[0] = min(vs1[0], vs2[*]) */ +GEN_VEXT_RED(vredmin_vs_b, int8_t, int8_t, H1, H1, DO_MIN, clearb) +GEN_VEXT_RED(vredmin_vs_h, int16_t, int16_t, H2, H2, DO_MIN, clearh) +GEN_VEXT_RED(vredmin_vs_w, int32_t, int32_t, H4, H4, DO_MIN, clearl) +GEN_VEXT_RED(vredmin_vs_d, int64_t, int64_t, H8, H8, DO_MIN, clearq) + +/* vd[0] = and(vs1[0], vs2[*]) */ +GEN_VEXT_RED(vredand_vs_b, int8_t, int8_t, H1, H1, DO_AND, clearb) +GEN_VEXT_RED(vredand_vs_h, int16_t, int16_t, H2, H2, DO_AND, clearh) +GEN_VEXT_RED(vredand_vs_w, int32_t, int32_t, H4, H4, DO_AND, clearl) +GEN_VEXT_RED(vredand_vs_d, int64_t, int64_t, H8, H8, DO_AND, clearq) + +/* vd[0] = or(vs1[0], vs2[*]) */ +GEN_VEXT_RED(vredor_vs_b, int8_t, int8_t, H1, H1, DO_OR, clearb) +GEN_VEXT_RED(vredor_vs_h, int16_t, int16_t, H2, H2, DO_OR, clearh) +GEN_VEXT_RED(vredor_vs_w, int32_t, int32_t, H4, H4, DO_OR, clearl) +GEN_VEXT_RED(vredor_vs_d, int64_t, int64_t, H8, H8, DO_OR, clearq) + +/* vd[0] = xor(vs1[0], vs2[*]) */ +GEN_VEXT_RED(vredxor_vs_b, int8_t, int8_t, H1, H1, DO_XOR, clearb) +GEN_VEXT_RED(vredxor_vs_h, int16_t, int16_t, H2, H2, DO_XOR, clearh) +GEN_VEXT_RED(vredxor_vs_w, int32_t, int32_t, H4, H4, DO_XOR, clearl) +GEN_VEXT_RED(vredxor_vs_d, int64_t, int64_t, H8, H8, DO_XOR, clearq) + +/* Vector Widening Integer Reduction Instructions */ +/* signed sum reduction into double-width accumulator */ +GEN_VEXT_RED(vwredsum_vs_b, int16_t, int8_t, H2, H1, DO_ADD, clearh) +GEN_VEXT_RED(vwredsum_vs_h, int32_t, int16_t, H4, H2, DO_ADD, clearl) +GEN_VEXT_RED(vwredsum_vs_w, int64_t, int32_t, H8, H4, DO_ADD, clearq) + +/* Unsigned sum reduction into double-width accumulator */ +GEN_VEXT_RED(vwredsumu_vs_b, uint16_t, uint8_t, H2, H1, DO_ADD, clearh) +GEN_VEXT_RED(vwredsumu_vs_h, uint32_t, uint16_t, H4, H2, DO_ADD, clearl) +GEN_VEXT_RED(vwredsumu_vs_w, uint64_t, uint32_t, H8, H4, DO_ADD, clearq) + +/* Vector Single-Width Floating-Point Reduction Instructions */ +#define GEN_VEXT_FRED(NAME, TD, TS2, HD, HS2, OP, CLEAR_FN)\ +void HELPER(NAME)(void *vd, void *v0, void *vs1, \ + void *vs2, CPURISCVState *env, \ + uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t i; \ + uint32_t tot = env_archcpu(env)->cfg.vlen / 8; \ + TD s1 = *((TD *)vs1 + HD(0)); \ + \ + for (i = 0; i < vl; i++) { \ + TS2 s2 = *((TS2 *)vs2 + HS2(i)); \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + s1 = OP(s1, (TD)s2, &env->fp_status); \ + } \ + *((TD *)vd + HD(0)) = s1; \ + CLEAR_FN(vd, 1, sizeof(TD), tot); \ +} + +/* Unordered sum */ +GEN_VEXT_FRED(vfredsum_vs_h, uint16_t, uint16_t, H2, H2, float16_add, clearh) +GEN_VEXT_FRED(vfredsum_vs_w, uint32_t, uint32_t, H4, H4, float32_add, clearl) +GEN_VEXT_FRED(vfredsum_vs_d, uint64_t, uint64_t, H8, H8, float64_add, clearq) + +/* Maximum value */ +GEN_VEXT_FRED(vfredmax_vs_h, uint16_t, uint16_t, H2, H2, float16_maxnum, clearh) +GEN_VEXT_FRED(vfredmax_vs_w, uint32_t, uint32_t, H4, H4, float32_maxnum, clearl) +GEN_VEXT_FRED(vfredmax_vs_d, uint64_t, uint64_t, H8, H8, float64_maxnum, clearq) + +/* Minimum value */ +GEN_VEXT_FRED(vfredmin_vs_h, uint16_t, uint16_t, H2, H2, float16_minnum, clearh) +GEN_VEXT_FRED(vfredmin_vs_w, uint32_t, uint32_t, H4, H4, float32_minnum, clearl) +GEN_VEXT_FRED(vfredmin_vs_d, uint64_t, uint64_t, H8, H8, float64_minnum, clearq) + +/* Vector Widening Floating-Point Reduction Instructions */ +/* Unordered reduce 2*SEW = 2*SEW + sum(promote(SEW)) */ +void HELPER(vfwredsum_vs_h)(void *vd, void *v0, void *vs1, + void *vs2, CPURISCVState *env, uint32_t desc) +{ + uint32_t mlen = vext_mlen(desc); + uint32_t vm = vext_vm(desc); + uint32_t vl = env->vl; + uint32_t i; + uint32_t tot = env_archcpu(env)->cfg.vlen / 8; + uint32_t s1 = *((uint32_t *)vs1 + H4(0)); + + for (i = 0; i < vl; i++) { + uint16_t s2 = *((uint16_t *)vs2 + H2(i)); + if (!vm && !vext_elem_mask(v0, mlen, i)) { + continue; + } + s1 = float32_add(s1, float16_to_float32(s2, true, &env->fp_status), + &env->fp_status); + } + *((uint32_t *)vd + H4(0)) = s1; + clearl(vd, 1, sizeof(uint32_t), tot); +} + +void HELPER(vfwredsum_vs_w)(void *vd, void *v0, void *vs1, + void *vs2, CPURISCVState *env, uint32_t desc) +{ + uint32_t mlen = vext_mlen(desc); + uint32_t vm = vext_vm(desc); + uint32_t vl = env->vl; + uint32_t i; + uint32_t tot = env_archcpu(env)->cfg.vlen / 8; + uint64_t s1 = *((uint64_t *)vs1); + + for (i = 0; i < vl; i++) { + uint32_t s2 = *((uint32_t *)vs2 + H4(i)); + if (!vm && !vext_elem_mask(v0, mlen, i)) { + continue; + } + s1 = float64_add(s1, float32_to_float64(s2, &env->fp_status), + &env->fp_status); + } + *((uint64_t *)vd) = s1; + clearq(vd, 1, sizeof(uint64_t), tot); +} + +/* + *** Vector Mask Operations + */ +/* Vector Mask-Register Logical Instructions */ +#define GEN_VEXT_MASK_VV(NAME, OP) \ +void HELPER(NAME)(void *vd, void *v0, void *vs1, \ + void *vs2, CPURISCVState *env, \ + uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vlmax = env_archcpu(env)->cfg.vlen / mlen; \ + uint32_t vl = env->vl; \ + uint32_t i; \ + int a, b; \ + \ + for (i = 0; i < vl; i++) { \ + a = vext_elem_mask(vs1, mlen, i); \ + b = vext_elem_mask(vs2, mlen, i); \ + vext_set_elem_mask(vd, mlen, i, OP(b, a)); \ + } \ + for (; i < vlmax; i++) { \ + vext_set_elem_mask(vd, mlen, i, 0); \ + } \ +} + +#define DO_NAND(N, M) (!(N & M)) +#define DO_ANDNOT(N, M) (N & !M) +#define DO_NOR(N, M) (!(N | M)) +#define DO_ORNOT(N, M) (N | !M) +#define DO_XNOR(N, M) (!(N ^ M)) + +GEN_VEXT_MASK_VV(vmand_mm, DO_AND) +GEN_VEXT_MASK_VV(vmnand_mm, DO_NAND) +GEN_VEXT_MASK_VV(vmandnot_mm, DO_ANDNOT) +GEN_VEXT_MASK_VV(vmxor_mm, DO_XOR) +GEN_VEXT_MASK_VV(vmor_mm, DO_OR) +GEN_VEXT_MASK_VV(vmnor_mm, DO_NOR) +GEN_VEXT_MASK_VV(vmornot_mm, DO_ORNOT) +GEN_VEXT_MASK_VV(vmxnor_mm, DO_XNOR) + +/* Vector mask population count vmpopc */ +target_ulong HELPER(vmpopc_m)(void *v0, void *vs2, CPURISCVState *env, + uint32_t desc) +{ + target_ulong cnt = 0; + uint32_t mlen = vext_mlen(desc); + uint32_t vm = vext_vm(desc); + uint32_t vl = env->vl; + int i; + + for (i = 0; i < vl; i++) { + if (vm || vext_elem_mask(v0, mlen, i)) { + if (vext_elem_mask(vs2, mlen, i)) { + cnt++; + } + } + } + return cnt; +} + +/* vmfirst find-first-set mask bit*/ +target_ulong HELPER(vmfirst_m)(void *v0, void *vs2, CPURISCVState *env, + uint32_t desc) +{ + uint32_t mlen = vext_mlen(desc); + uint32_t vm = vext_vm(desc); + uint32_t vl = env->vl; + int i; + + for (i = 0; i < vl; i++) { + if (vm || vext_elem_mask(v0, mlen, i)) { + if (vext_elem_mask(vs2, mlen, i)) { + return i; + } + } + } + return -1LL; +} + +enum set_mask_type { + ONLY_FIRST = 1, + INCLUDE_FIRST, + BEFORE_FIRST, +}; + +static void vmsetm(void *vd, void *v0, void *vs2, CPURISCVState *env, + uint32_t desc, enum set_mask_type type) +{ + uint32_t mlen = vext_mlen(desc); + uint32_t vlmax = env_archcpu(env)->cfg.vlen / mlen; + uint32_t vm = vext_vm(desc); + uint32_t vl = env->vl; + int i; + bool first_mask_bit = false; + + for (i = 0; i < vl; i++) { + if (!vm && !vext_elem_mask(v0, mlen, i)) { + continue; + } + /* write a zero to all following active elements */ + if (first_mask_bit) { + vext_set_elem_mask(vd, mlen, i, 0); + continue; + } + if (vext_elem_mask(vs2, mlen, i)) { + first_mask_bit = true; + if (type == BEFORE_FIRST) { + vext_set_elem_mask(vd, mlen, i, 0); + } else { + vext_set_elem_mask(vd, mlen, i, 1); + } + } else { + if (type == ONLY_FIRST) { + vext_set_elem_mask(vd, mlen, i, 0); + } else { + vext_set_elem_mask(vd, mlen, i, 1); + } + } + } + for (; i < vlmax; i++) { + vext_set_elem_mask(vd, mlen, i, 0); + } +} + +void HELPER(vmsbf_m)(void *vd, void *v0, void *vs2, CPURISCVState *env, + uint32_t desc) +{ + vmsetm(vd, v0, vs2, env, desc, BEFORE_FIRST); +} + +void HELPER(vmsif_m)(void *vd, void *v0, void *vs2, CPURISCVState *env, + uint32_t desc) +{ + vmsetm(vd, v0, vs2, env, desc, INCLUDE_FIRST); +} + +void HELPER(vmsof_m)(void *vd, void *v0, void *vs2, CPURISCVState *env, + uint32_t desc) +{ + vmsetm(vd, v0, vs2, env, desc, ONLY_FIRST); +} + +/* Vector Iota Instruction */ +#define GEN_VEXT_VIOTA_M(NAME, ETYPE, H, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, void *vs2, CPURISCVState *env, \ + uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vlmax = env_archcpu(env)->cfg.vlen / mlen; \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t sum = 0; \ + int i; \ + \ + for (i = 0; i < vl; i++) { \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + *((ETYPE *)vd + H(i)) = sum; \ + if (vext_elem_mask(vs2, mlen, i)) { \ + sum++; \ + } \ + } \ + CLEAR_FN(vd, vl, vl * sizeof(ETYPE), vlmax * sizeof(ETYPE)); \ +} + +GEN_VEXT_VIOTA_M(viota_m_b, uint8_t, H1, clearb) +GEN_VEXT_VIOTA_M(viota_m_h, uint16_t, H2, clearh) +GEN_VEXT_VIOTA_M(viota_m_w, uint32_t, H4, clearl) +GEN_VEXT_VIOTA_M(viota_m_d, uint64_t, H8, clearq) + +/* Vector Element Index Instruction */ +#define GEN_VEXT_VID_V(NAME, ETYPE, H, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vlmax = env_archcpu(env)->cfg.vlen / mlen; \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + int i; \ + \ + for (i = 0; i < vl; i++) { \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + *((ETYPE *)vd + H(i)) = i; \ + } \ + CLEAR_FN(vd, vl, vl * sizeof(ETYPE), vlmax * sizeof(ETYPE)); \ +} + +GEN_VEXT_VID_V(vid_v_b, uint8_t, H1, clearb) +GEN_VEXT_VID_V(vid_v_h, uint16_t, H2, clearh) +GEN_VEXT_VID_V(vid_v_w, uint32_t, H4, clearl) +GEN_VEXT_VID_V(vid_v_d, uint64_t, H8, clearq) + +/* + *** Vector Permutation Instructions + */ + +/* Vector Slide Instructions */ +#define GEN_VEXT_VSLIDEUP_VX(NAME, ETYPE, H, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vlmax = env_archcpu(env)->cfg.vlen / mlen; \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + target_ulong offset = s1, i; \ + \ + for (i = offset; i < vl; i++) { \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(i - offset)); \ + } \ + CLEAR_FN(vd, vl, vl * sizeof(ETYPE), vlmax * sizeof(ETYPE)); \ +} + +/* vslideup.vx vd, vs2, rs1, vm # vd[i+rs1] = vs2[i] */ +GEN_VEXT_VSLIDEUP_VX(vslideup_vx_b, uint8_t, H1, clearb) +GEN_VEXT_VSLIDEUP_VX(vslideup_vx_h, uint16_t, H2, clearh) +GEN_VEXT_VSLIDEUP_VX(vslideup_vx_w, uint32_t, H4, clearl) +GEN_VEXT_VSLIDEUP_VX(vslideup_vx_d, uint64_t, H8, clearq) + +#define GEN_VEXT_VSLIDEDOWN_VX(NAME, ETYPE, H, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vlmax = env_archcpu(env)->cfg.vlen / mlen; \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + target_ulong offset = s1, i; \ + \ + for (i = 0; i < vl; ++i) { \ + target_ulong j = i + offset; \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + *((ETYPE *)vd + H(i)) = j >= vlmax ? 0 : *((ETYPE *)vs2 + H(j)); \ + } \ + CLEAR_FN(vd, vl, vl * sizeof(ETYPE), vlmax * sizeof(ETYPE)); \ +} + +/* vslidedown.vx vd, vs2, rs1, vm # vd[i] = vs2[i+rs1] */ +GEN_VEXT_VSLIDEDOWN_VX(vslidedown_vx_b, uint8_t, H1, clearb) +GEN_VEXT_VSLIDEDOWN_VX(vslidedown_vx_h, uint16_t, H2, clearh) +GEN_VEXT_VSLIDEDOWN_VX(vslidedown_vx_w, uint32_t, H4, clearl) +GEN_VEXT_VSLIDEDOWN_VX(vslidedown_vx_d, uint64_t, H8, clearq) + +#define GEN_VEXT_VSLIDE1UP_VX(NAME, ETYPE, H, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vlmax = env_archcpu(env)->cfg.vlen / mlen; \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + if (i == 0) { \ + *((ETYPE *)vd + H(i)) = s1; \ + } else { \ + *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(i - 1)); \ + } \ + } \ + CLEAR_FN(vd, vl, vl * sizeof(ETYPE), vlmax * sizeof(ETYPE)); \ +} + +/* vslide1up.vx vd, vs2, rs1, vm # vd[0]=x[rs1], vd[i+1] = vs2[i] */ +GEN_VEXT_VSLIDE1UP_VX(vslide1up_vx_b, uint8_t, H1, clearb) +GEN_VEXT_VSLIDE1UP_VX(vslide1up_vx_h, uint16_t, H2, clearh) +GEN_VEXT_VSLIDE1UP_VX(vslide1up_vx_w, uint32_t, H4, clearl) +GEN_VEXT_VSLIDE1UP_VX(vslide1up_vx_d, uint64_t, H8, clearq) + +#define GEN_VEXT_VSLIDE1DOWN_VX(NAME, ETYPE, H, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vlmax = env_archcpu(env)->cfg.vlen / mlen; \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t i; \ + \ + for (i = 0; i < vl; i++) { \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + if (i == vl - 1) { \ + *((ETYPE *)vd + H(i)) = s1; \ + } else { \ + *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(i + 1)); \ + } \ + } \ + CLEAR_FN(vd, vl, vl * sizeof(ETYPE), vlmax * sizeof(ETYPE)); \ +} + +/* vslide1down.vx vd, vs2, rs1, vm # vd[i] = vs2[i+1], vd[vl-1]=x[rs1] */ +GEN_VEXT_VSLIDE1DOWN_VX(vslide1down_vx_b, uint8_t, H1, clearb) +GEN_VEXT_VSLIDE1DOWN_VX(vslide1down_vx_h, uint16_t, H2, clearh) +GEN_VEXT_VSLIDE1DOWN_VX(vslide1down_vx_w, uint32_t, H4, clearl) +GEN_VEXT_VSLIDE1DOWN_VX(vslide1down_vx_d, uint64_t, H8, clearq) + +/* Vector Register Gather Instruction */ +#define GEN_VEXT_VRGATHER_VV(NAME, ETYPE, H, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vlmax = env_archcpu(env)->cfg.vlen / mlen; \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t index, i; \ + \ + for (i = 0; i < vl; i++) { \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + index = *((ETYPE *)vs1 + H(i)); \ + if (index >= vlmax) { \ + *((ETYPE *)vd + H(i)) = 0; \ + } else { \ + *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(index)); \ + } \ + } \ + CLEAR_FN(vd, vl, vl * sizeof(ETYPE), vlmax * sizeof(ETYPE)); \ +} + +/* vd[i] = (vs1[i] >= VLMAX) ? 0 : vs2[vs1[i]]; */ +GEN_VEXT_VRGATHER_VV(vrgather_vv_b, uint8_t, H1, clearb) +GEN_VEXT_VRGATHER_VV(vrgather_vv_h, uint16_t, H2, clearh) +GEN_VEXT_VRGATHER_VV(vrgather_vv_w, uint32_t, H4, clearl) +GEN_VEXT_VRGATHER_VV(vrgather_vv_d, uint64_t, H8, clearq) + +#define GEN_VEXT_VRGATHER_VX(NAME, ETYPE, H, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vlmax = env_archcpu(env)->cfg.vlen / mlen; \ + uint32_t vm = vext_vm(desc); \ + uint32_t vl = env->vl; \ + uint32_t index = s1, i; \ + \ + for (i = 0; i < vl; i++) { \ + if (!vm && !vext_elem_mask(v0, mlen, i)) { \ + continue; \ + } \ + if (index >= vlmax) { \ + *((ETYPE *)vd + H(i)) = 0; \ + } else { \ + *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(index)); \ + } \ + } \ + CLEAR_FN(vd, vl, vl * sizeof(ETYPE), vlmax * sizeof(ETYPE)); \ +} + +/* vd[i] = (x[rs1] >= VLMAX) ? 0 : vs2[rs1] */ +GEN_VEXT_VRGATHER_VX(vrgather_vx_b, uint8_t, H1, clearb) +GEN_VEXT_VRGATHER_VX(vrgather_vx_h, uint16_t, H2, clearh) +GEN_VEXT_VRGATHER_VX(vrgather_vx_w, uint32_t, H4, clearl) +GEN_VEXT_VRGATHER_VX(vrgather_vx_d, uint64_t, H8, clearq) + +/* Vector Compress Instruction */ +#define GEN_VEXT_VCOMPRESS_VM(NAME, ETYPE, H, CLEAR_FN) \ +void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + uint32_t mlen = vext_mlen(desc); \ + uint32_t vlmax = env_archcpu(env)->cfg.vlen / mlen; \ + uint32_t vl = env->vl; \ + uint32_t num = 0, i; \ + \ + for (i = 0; i < vl; i++) { \ + if (!vext_elem_mask(vs1, mlen, i)) { \ + continue; \ + } \ + *((ETYPE *)vd + H(num)) = *((ETYPE *)vs2 + H(i)); \ + num++; \ + } \ + CLEAR_FN(vd, num, num * sizeof(ETYPE), vlmax * sizeof(ETYPE)); \ +} + +/* Compress into vd elements of vs2 where vs1 is enabled */ +GEN_VEXT_VCOMPRESS_VM(vcompress_vm_b, uint8_t, H1, clearb) +GEN_VEXT_VCOMPRESS_VM(vcompress_vm_h, uint16_t, H2, clearh) +GEN_VEXT_VCOMPRESS_VM(vcompress_vm_w, uint32_t, H4, clearl) +GEN_VEXT_VCOMPRESS_VM(vcompress_vm_d, uint64_t, H8, clearq) diff --git a/target/rx/Makefile.objs b/target/rx/Makefile.objs deleted file mode 100644 index a0018d5bc55576abaf8a536b02911373b34afc4b..0000000000000000000000000000000000000000 --- a/target/rx/Makefile.objs +++ /dev/null @@ -1,11 +0,0 @@ -obj-y += translate.o op_helper.o helper.o cpu.o gdbstub.o disas.o - -DECODETREE = $(SRC_PATH)/scripts/decodetree.py - -target/rx/decode.inc.c: \ - $(SRC_PATH)/target/rx/insns.decode $(DECODETREE) - $(call quiet-command,\ - $(PYTHON) $(DECODETREE) --varinsnwidth 32 -o $@ $<, "GEN", $(TARGET_DIR)$@) - -target/rx/translate.o: target/rx/decode.inc.c -target/rx/disas.o: target/rx/decode.inc.c diff --git a/target/rx/cpu-qom.h b/target/rx/cpu-qom.h index 3e81856ef54e76deaa77668ddef846b09db3a44f..7310558e0cfd4bf60b3f61bfdc0a691099746631 100644 --- a/target/rx/cpu-qom.h +++ b/target/rx/cpu-qom.h @@ -20,17 +20,14 @@ #define RX_CPU_QOM_H #include "hw/core/cpu.h" +#include "qom/object.h" #define TYPE_RX_CPU "rx-cpu" #define TYPE_RX62N_CPU RX_CPU_TYPE_NAME("rx62n") -#define RXCPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(RXCPUClass, (klass), TYPE_RX_CPU) -#define RXCPU(obj) \ - OBJECT_CHECK(RXCPU, (obj), TYPE_RX_CPU) -#define RXCPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(RXCPUClass, (obj), TYPE_RX_CPU) +OBJECT_DECLARE_TYPE(RXCPU, RXCPUClass, + RX_CPU) /* * RXCPUClass: @@ -39,14 +36,14 @@ * * A RX CPU model. */ -typedef struct RXCPUClass { +struct RXCPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ DeviceRealize parent_realize; DeviceReset parent_reset; -} RXCPUClass; +}; #define CPUArchState struct CPURXState diff --git a/target/rx/cpu.c b/target/rx/cpu.c index 219e05397b9d0047604709a4ece6b75502d0ceb6..23ee17a701876947b6cf64018dc47668a7993972 100644 --- a/target/rx/cpu.c +++ b/target/rx/cpu.c @@ -28,14 +28,14 @@ static void rx_cpu_set_pc(CPUState *cs, vaddr value) { - RXCPU *cpu = RXCPU(cs); + RXCPU *cpu = RX_CPU(cs); cpu->env.pc = value; } static void rx_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) { - RXCPU *cpu = RXCPU(cs); + RXCPU *cpu = RX_CPU(cs); cpu->env.pc = tb->pc; } @@ -48,8 +48,8 @@ static bool rx_cpu_has_work(CPUState *cs) static void rx_cpu_reset(DeviceState *dev) { - RXCPU *cpu = RXCPU(dev); - RXCPUClass *rcc = RXCPU_GET_CLASS(cpu); + RXCPU *cpu = RX_CPU(dev); + RXCPUClass *rcc = RX_CPU_GET_CLASS(cpu); CPURXState *env = &cpu->env; uint32_t *resetvec; @@ -108,7 +108,7 @@ static ObjectClass *rx_cpu_class_by_name(const char *cpu_model) static void rx_cpu_realize(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); - RXCPUClass *rcc = RXCPU_GET_CLASS(dev); + RXCPUClass *rcc = RX_CPU_GET_CLASS(dev); Error *local_err = NULL; cpu_exec_realizefn(cs, &local_err); @@ -164,7 +164,7 @@ static bool rx_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, static void rx_cpu_init(Object *obj) { CPUState *cs = CPU(obj); - RXCPU *cpu = RXCPU(obj); + RXCPU *cpu = RX_CPU(obj); CPURXState *env = &cpu->env; cpu_set_cpustate_pointers(cpu); @@ -176,7 +176,7 @@ static void rx_cpu_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); CPUClass *cc = CPU_CLASS(klass); - RXCPUClass *rcc = RXCPU_CLASS(klass); + RXCPUClass *rcc = RX_CPU_CLASS(klass); device_class_set_parent_realize(dc, rx_cpu_realize, &rcc->parent_realize); diff --git a/target/rx/cpu.h b/target/rx/cpu.h index d1fb1ef3ca7566437332c65490154106b16e00b8..0b4b998c7bef8f8964c4d5741c91a1aa93710361 100644 --- a/target/rx/cpu.h +++ b/target/rx/cpu.h @@ -115,7 +115,6 @@ struct RXCPU { CPURXState env; }; -typedef struct RXCPU RXCPU; typedef RXCPU ArchCPU; #define ENV_OFFSET offsetof(RXCPU, env) diff --git a/target/rx/disas.c b/target/rx/disas.c index 6dee7a0342baf4fcb8cabe95eeaaecc44442a4ca..67b932882914dfbe6fad725102ad027ffc808b02 100644 --- a/target/rx/disas.c +++ b/target/rx/disas.c @@ -100,7 +100,7 @@ static int bdsp_s(DisasContext *ctx, int d) } /* Include the auto-generated decoder. */ -#include "decode.inc.c" +#include "decode-insns.c.inc" static void dump_bytes(DisasContext *ctx) { diff --git a/target/rx/gdbstub.c b/target/rx/gdbstub.c index 9391e8151e95fe932405563d69b014351114af7b..c811d4810b45508120d4612109bed6e6020e7d18 100644 --- a/target/rx/gdbstub.c +++ b/target/rx/gdbstub.c @@ -22,7 +22,7 @@ int rx_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) { - RXCPU *cpu = RXCPU(cs); + RXCPU *cpu = RX_CPU(cs); CPURXState *env = &cpu->env; switch (n) { @@ -54,7 +54,7 @@ int rx_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) int rx_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) { - RXCPU *cpu = RXCPU(cs); + RXCPU *cpu = RX_CPU(cs); CPURXState *env = &cpu->env; uint32_t psw; switch (n) { diff --git a/target/rx/helper.c b/target/rx/helper.c index a6a337a311216224163d01cc54daa6e406dfc2c1..3e380a94fe60b84d17f9715483ae0881287d4617 100644 --- a/target/rx/helper.c +++ b/target/rx/helper.c @@ -44,7 +44,7 @@ void rx_cpu_unpack_psw(CPURXState *env, uint32_t psw, int rte) #define INT_FLAGS (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIR) void rx_cpu_do_interrupt(CPUState *cs) { - RXCPU *cpu = RXCPU(cs); + RXCPU *cpu = RX_CPU(cs); CPURXState *env = &cpu->env; int do_irq = cs->interrupt_request & INT_FLAGS; uint32_t save_psw; @@ -121,7 +121,7 @@ void rx_cpu_do_interrupt(CPUState *cs) bool rx_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { - RXCPU *cpu = RXCPU(cs); + RXCPU *cpu = RX_CPU(cs); CPURXState *env = &cpu->env; int accept = 0; /* hardware interrupt (Normal) */ diff --git a/target/rx/insns.decode b/target/rx/insns.decode index 232a61fc8edc0a37dedc2febf35d222f97cf4ed9..ca9334b37afd17bc502925a28c8d31aacec712c8 100644 --- a/target/rx/insns.decode +++ b/target/rx/insns.decode @@ -7,7 +7,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/rx/meson.build b/target/rx/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..8de0ad49b9b36a65dd363cf088527917043e7752 --- /dev/null +++ b/target/rx/meson.build @@ -0,0 +1,16 @@ +gen = [ + decodetree.process('insns.decode', extra_args: [ '--varinsnwidth', '32' ]) +] + +rx_ss = ss.source_set() +rx_ss.add(gen) +rx_ss.add(files( + 'translate.c', + 'op_helper.c', + 'helper.c', + 'cpu.c', + 'gdbstub.c', + 'disas.c')) + +target_arch += {'rx': rx_ss} +target_softmmu_arch += {'rx': ss.source_set()} diff --git a/target/rx/op_helper.c b/target/rx/op_helper.c index f89d294f2b2eac591158c8ae29196c3377e61f38..59389f49921f0fb6673c27e50e148c00c83b1400 100644 --- a/target/rx/op_helper.c +++ b/target/rx/op_helper.c @@ -318,7 +318,7 @@ void helper_swhile(CPURXState *env, uint32_t sz) env->psw_c = (tmp <= env->regs[2]); } -/* accumlator operations */ +/* accumulator operations */ void helper_rmpa(CPURXState *env, uint32_t sz) { uint64_t result_l, prev; diff --git a/target/rx/translate.c b/target/rx/translate.c index 61e86653a41335aa02fa610379b45dd02bc765c5..9ea941c6302f0b89775dd952cc8b955150d2655e 100644 --- a/target/rx/translate.c +++ b/target/rx/translate.c @@ -124,11 +124,11 @@ static int bdsp_s(DisasContext *ctx, int d) } /* Include the auto-generated decoder. */ -#include "decode.inc.c" +#include "decode-insns.c.inc" void rx_cpu_dump_state(CPUState *cs, FILE *f, int flags) { - RXCPU *cpu = RXCPU(cs); + RXCPU *cpu = RX_CPU(cs); CPURXState *env = &cpu->env; int i; uint32_t psw; @@ -1089,7 +1089,7 @@ static void rx_sub(TCGv ret, TCGv arg1, TCGv arg2) tcg_gen_xor_i32(temp, arg1, arg2); tcg_gen_and_i32(cpu_psw_o, cpu_psw_o, temp); tcg_temp_free_i32(temp); - /* CMP not requred return */ + /* CMP not required return */ if (ret) { tcg_gen_mov_i32(ret, cpu_psw_s); } diff --git a/target/s390x/Makefile.objs b/target/s390x/Makefile.objs deleted file mode 100644 index 3e2745594a29817e65a9fbe81c3e4d810a9f9e06..0000000000000000000000000000000000000000 --- a/target/s390x/Makefile.objs +++ /dev/null @@ -1,30 +0,0 @@ -obj-y += cpu.o cpu_models.o cpu_features.o gdbstub.o interrupt.o helper.o -obj-$(CONFIG_TCG) += translate.o cc_helper.o excp_helper.o fpu_helper.o -obj-$(CONFIG_TCG) += int_helper.o mem_helper.o misc_helper.o crypto_helper.o -obj-$(CONFIG_TCG) += vec_helper.o vec_int_helper.o vec_string_helper.o -obj-$(CONFIG_TCG) += vec_fpu_helper.o -obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o mmu_helper.o diag.o -obj-$(CONFIG_SOFTMMU) += sigp.o -obj-$(CONFIG_KVM) += kvm.o -obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o -obj-$(call lnot,$(CONFIG_TCG)) += tcg-stub.o - -# build and run feature list generator -feat-src = $(SRC_PATH)/target/$(TARGET_BASE_ARCH)/ -feat-dst = $(BUILD_DIR)/$(TARGET_DIR) -ifneq ($(MAKECMDGOALS),clean) -generated-files-y += $(feat-dst)gen-features.h -endif - -$(feat-dst)gen-features.h: $(feat-dst)gen-features.h-timestamp - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ -$(feat-dst)gen-features.h-timestamp: $(feat-dst)gen-features - $(call quiet-command,$< >$@,"GEN","$(TARGET_DIR)gen-features.h") - -$(feat-dst)gen-features: $(feat-src)gen-features.c - $(call quiet-command,$(HOST_CC) $(QEMU_INCLUDES) -o $@ $<,"CC","$(TARGET_DIR)gen-features") - -clean-target: - rm -f gen-features.h-timestamp - rm -f gen-features.h - rm -f gen-features diff --git a/target/s390x/cc_helper.c b/target/s390x/cc_helper.c index 44731e4a85c399bd20482dd81daf7559233785a2..5432aeeed46cf948bc7e1862d22c2550e1563d8a 100644 --- a/target/s390x/cc_helper.c +++ b/target/s390x/cc_helper.c @@ -417,6 +417,32 @@ static uint32_t cc_calc_vc(uint64_t low, uint64_t high) } } +static uint32_t cc_calc_muls_32(int64_t res) +{ + const int64_t tmp = res >> 31; + + if (!res) { + return 0; + } else if (tmp && tmp != -1) { + return 3; + } else if (res < 0) { + return 1; + } + return 2; +} + +static uint64_t cc_calc_muls_64(int64_t res_high, uint64_t res_low) +{ + if (!res_high && !res_low) { + return 0; + } else if (res_high + (res_low >> 63) != 0) { + return 3; + } else if (res_high < 0) { + return 1; + } + return 2; +} + static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst, uint64_t vr) { @@ -484,6 +510,9 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, case CC_OP_COMP_64: r = cc_calc_comp_64(dst); break; + case CC_OP_MULS_64: + r = cc_calc_muls_64(src, dst); + break; case CC_OP_ADD_32: r = cc_calc_add_32(src, dst, vr); @@ -512,6 +541,9 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, case CC_OP_COMP_32: r = cc_calc_comp_32(dst); break; + case CC_OP_MULS_32: + r = cc_calc_muls_32(dst); + break; case CC_OP_ICM: r = cc_calc_icm(src, dst); diff --git a/target/s390x/cpu-qom.h b/target/s390x/cpu-qom.h index 1630818c280db8ff67525056b7491bad67ffe0a5..9f3a0d86c50a099943de21add1c39988d22caf84 100644 --- a/target/s390x/cpu-qom.h +++ b/target/s390x/cpu-qom.h @@ -21,15 +21,12 @@ #define QEMU_S390_CPU_QOM_H #include "hw/core/cpu.h" +#include "qom/object.h" #define TYPE_S390_CPU "s390x-cpu" -#define S390_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(S390CPUClass, (klass), TYPE_S390_CPU) -#define S390_CPU(obj) \ - OBJECT_CHECK(S390CPU, (obj), TYPE_S390_CPU) -#define S390_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(S390CPUClass, (obj), TYPE_S390_CPU) +OBJECT_DECLARE_TYPE(S390CPU, S390CPUClass, + S390_CPU) typedef struct S390CPUModel S390CPUModel; typedef struct S390CPUDef S390CPUDef; @@ -50,7 +47,7 @@ typedef enum cpu_reset_type { * * An S/390 CPU model. */ -typedef struct S390CPUClass { +struct S390CPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ @@ -64,9 +61,8 @@ typedef struct S390CPUClass { DeviceReset parent_reset; void (*load_normal)(CPUState *cpu); void (*reset)(CPUState *cpu, cpu_reset_type type); -} S390CPUClass; +}; -typedef struct S390CPU S390CPU; typedef struct CPUS390XState CPUS390XState; #endif diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index ca50b70451980d807ef1cdec789f3d76f80d19bf..7b66718c44232f5306e9fa8eb4d56520e3cf0513 100644 --- a/target/s390x/cpu.c +++ b/target/s390x/cpu.c @@ -44,6 +44,7 @@ #include "sysemu/tcg.h" #endif #include "fpu/softfloat-helpers.h" +#include "disas/capstone.h" #define CR0_RESET 0xE0UL #define CR14_RESET 0xC2000000UL; @@ -182,6 +183,9 @@ static void s390_cpu_disas_set_info(CPUState *cpu, disassemble_info *info) { info->mach = bfd_mach_s390_64; info->print_insn = print_insn_s390; + info->cap_arch = CS_ARCH_SYSZ; + info->cap_insn_unit = 2; + info->cap_insn_split = 6; } static void s390_cpu_realizefn(DeviceState *dev, Error **errp) @@ -247,6 +251,7 @@ out: error_propagate(errp, err); } +#if !defined(CONFIG_USER_ONLY) static GuestPanicInformation *s390_cpu_get_crash_info(CPUState *cs) { GuestPanicInformation *panic_info; @@ -256,11 +261,7 @@ static GuestPanicInformation *s390_cpu_get_crash_info(CPUState *cs) panic_info = g_malloc0(sizeof(GuestPanicInformation)); panic_info->type = GUEST_PANIC_INFORMATION_TYPE_S390; -#if !defined(CONFIG_USER_ONLY) panic_info->u.s390.core = cpu->env.core_id; -#else - panic_info->u.s390.core = 0; /* sane default for non system emulation */ -#endif panic_info->u.s390.psw_mask = cpu->env.psw.mask; panic_info->u.s390.psw_addr = cpu->env.psw.addr; panic_info->u.s390.reason = cpu->env.crash_reason; @@ -286,6 +287,7 @@ static void s390_cpu_get_crash_info_qom(Object *obj, Visitor *v, errp); qapi_free_GuestPanicInformation(panic_info); } +#endif static void s390_cpu_initfn(Object *obj) { @@ -293,12 +295,11 @@ static void s390_cpu_initfn(Object *obj) S390CPU *cpu = S390_CPU(obj); cpu_set_cpustate_pointers(cpu); - cs->halted = 1; cs->exception_index = EXCP_HLT; +#if !defined(CONFIG_USER_ONLY) + cs->start_powered_off = true; object_property_add(obj, "crash-information", "GuestPanicInformation", s390_cpu_get_crash_info_qom, NULL, NULL, NULL); - s390_cpu_model_register_props(obj); -#if !defined(CONFIG_USER_ONLY) cpu->env.tod_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_tod_timer, cpu); cpu->env.cpu_timer = @@ -446,6 +447,13 @@ void s390_enable_css_support(S390CPU *cpu) kvm_s390_enable_css_support(cpu); } } + +void s390_do_cpu_set_diag318(CPUState *cs, run_on_cpu_data arg) +{ + if (kvm_enabled()) { + kvm_s390_set_diag318(cs, arg.host_ulong); + } +} #endif static gchar *s390_gdb_arch_name(CPUState *cs) @@ -488,13 +496,13 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) cc->do_interrupt = s390_cpu_do_interrupt; #endif cc->dump_state = s390_cpu_dump_state; - cc->get_crash_info = s390_cpu_get_crash_info; cc->set_pc = s390_cpu_set_pc; cc->gdb_read_register = s390_cpu_gdb_read_register; cc->gdb_write_register = s390_cpu_gdb_write_register; #ifndef CONFIG_USER_ONLY cc->get_phys_page_debug = s390_cpu_get_phys_page_debug; cc->vmsd = &vmstate_s390_cpu; + cc->get_crash_info = s390_cpu_get_crash_info; cc->write_elf64_note = s390_cpu_write_elf64_note; #ifdef CONFIG_TCG cc->cpu_exec_interrupt = s390_cpu_exec_interrupt; @@ -519,6 +527,7 @@ static const TypeInfo s390_cpu_type_info = { .name = TYPE_S390_CPU, .parent = TYPE_CPU, .instance_size = sizeof(S390CPU), + .instance_align = __alignof__(S390CPU), .instance_init = s390_cpu_initfn, .instance_finalize = s390_cpu_finalize, .abstract = true, diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index 035427521cec252877c70288d597fea43b874c4d..60d434d5edd55c59cfe7e345967c7a616263b55f 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -112,6 +112,8 @@ struct CPUS390XState { uint16_t external_call_addr; DECLARE_BITMAP(emergency_signals, S390_MAX_CPUS); + uint64_t diag318_info; + /* Fields up to this point are cleared by a CPU reset */ struct {} end_reset_fields; @@ -767,6 +769,7 @@ int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit); void s390_set_max_pagesize(uint64_t pagesize, Error **errp); void s390_cmma_reset(void); void s390_enable_css_support(S390CPU *cpu); +void s390_do_cpu_set_diag318(CPUState *cs, run_on_cpu_data arg); int s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch_id, int vq, bool assign); #ifndef CONFIG_USER_ONLY diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c index 9f817e3cfa72a8a6108f894162ee7b3c3cea2e48..42fe0bf4ca7a88a714c62e1f80c7ffc299fec190 100644 --- a/target/s390x/cpu_features.c +++ b/target/s390x/cpu_features.c @@ -14,6 +14,7 @@ #include "qemu/osdep.h" #include "qemu/module.h" #include "cpu_features.h" +#include "hw/s390x/pv.h" #define DEF_FEAT(_FEAT, _NAME, _TYPE, _BIT, _DESC) \ [S390_FEAT_##_FEAT] = { \ @@ -23,7 +24,7 @@ .desc = _DESC, \ }, static const S390FeatDef s390_features[S390_FEAT_MAX] = { - #include "cpu_features_def.inc.h" + #include "cpu_features_def.h.inc" }; #undef DEF_FEAT @@ -105,6 +106,10 @@ void s390_fill_feat_block(const S390FeatBitmap features, S390FeatType type, } feat = find_next_bit(features, S390_FEAT_MAX, feat + 1); } + + if (type == S390_FEAT_TYPE_SCLP_FAC134 && s390_is_pv()) { + clear_be_bit(s390_feat_def(S390_FEAT_DIAG_318)->bit, data); + } } void s390_add_from_feat_block(S390FeatBitmap features, S390FeatType type, diff --git a/target/s390x/cpu_features.h b/target/s390x/cpu_features.h index da695a8346e98d6b54b9efcae4129fd6d33be1d0..87463f064d2a63620f2cef43236a3005cd2ca6ba 100644 --- a/target/s390x/cpu_features.h +++ b/target/s390x/cpu_features.h @@ -16,13 +16,14 @@ #include "qemu/bitmap.h" #include "cpu_features_def.h" -#include "gen-features.h" +#include "target/s390x/gen-features.h" /* CPU features are announced via different ways */ typedef enum { S390_FEAT_TYPE_STFL, S390_FEAT_TYPE_SCLP_CONF_CHAR, S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, + S390_FEAT_TYPE_SCLP_FAC134, S390_FEAT_TYPE_SCLP_CPU, S390_FEAT_TYPE_MISC, S390_FEAT_TYPE_PLO, @@ -80,6 +81,10 @@ const S390FeatGroupDef *s390_feat_group_def(S390FeatGroup group); #define BE_BIT_NR(BIT) (BIT ^ (BITS_PER_LONG - 1)) +static inline void clear_be_bit(unsigned int bit_nr, uint8_t *array) +{ + array[bit_nr / 8] &= ~(0x80 >> (bit_nr % 8)); +} static inline void set_be_bit(unsigned int bit_nr, uint8_t *array) { array[bit_nr / 8] |= 0x80 >> (bit_nr % 8); diff --git a/target/s390x/cpu_features_def.h b/target/s390x/cpu_features_def.h index 412d356febbb20331a5d0c5cf367e2382f86be2c..87df31848e605762b87a38065a50dee04ba87dcf 100644 --- a/target/s390x/cpu_features_def.h +++ b/target/s390x/cpu_features_def.h @@ -17,7 +17,7 @@ #define DEF_FEAT(_FEAT, ...) S390_FEAT_##_FEAT, typedef enum { - #include "cpu_features_def.inc.h" + #include "cpu_features_def.h.inc" S390_FEAT_MAX, } S390Feat; #undef DEF_FEAT diff --git a/target/s390x/cpu_features_def.inc.h b/target/s390x/cpu_features_def.h.inc similarity index 98% rename from target/s390x/cpu_features_def.inc.h rename to target/s390x/cpu_features_def.h.inc index 5942f81f16595816e7e65cf61299c26b57ae2469..7db3449e04346fad4dbf904a13d677bdc2ccc8dd 100644 --- a/target/s390x/cpu_features_def.inc.h +++ b/target/s390x/cpu_features_def.h.inc @@ -72,7 +72,7 @@ DEF_FEAT(INTERLOCKED_ACCESS_2, "iacc2", STFL, 52, "Interlocked-access facility 2 DEF_FEAT(STFLE_53, "stfle53", STFL, 53, "Various facilities introduced with z13") DEF_FEAT(ENTROPY_ENC_COMP, "eec", STFL, 54, "Entropy encoding compression facility") DEF_FEAT(MSA_EXT_5, "msa5-base", STFL, 57, "Message-security-assist-extension-5 facility (excluding subfunctions)") -DEF_FEAT(MISC_INSTRUCTION_EXT, "minste2", STFL, 58, "Miscellaneous-instruction-extensions facility 2") +DEF_FEAT(MISC_INSTRUCTION_EXT2, "minste2", STFL, 58, "Miscellaneous-instruction-extensions facility 2") DEF_FEAT(SEMAPHORE_ASSIST, "sema", STFL, 59, "Semaphore-assist facility") DEF_FEAT(TIME_SLICE_INSTRUMENTATION, "tsi", STFL, 60, "Time-slice Instrumentation facility") DEF_FEAT(MISC_INSTRUCTION_EXT3, "minste3", STFL, 61, "Miscellaneous-Instruction-Extensions Facility 3") @@ -97,6 +97,7 @@ DEF_FEAT(GUARDED_STORAGE, "gs", STFL, 133, "Guarded-storage facility") DEF_FEAT(VECTOR_PACKED_DECIMAL, "vxpd", STFL, 134, "Vector packed decimal facility") DEF_FEAT(VECTOR_ENH, "vxeh", STFL, 135, "Vector enhancements facility") DEF_FEAT(MULTIPLE_EPOCH, "mepoch", STFL, 139, "Multiple-epoch facility") +DEF_FEAT(EXTENDED_LENGTH_SCCB, "els", STFL, 140, "Extended-length SCCB facility") DEF_FEAT(TEST_PENDING_EXT_INTERRUPTION, "tpei", STFL, 144, "Test-pending-external-interruption facility") DEF_FEAT(INSERT_REFERENCE_BITS_MULT, "irbm", STFL, 145, "Insert-reference-bits-multiple facility") DEF_FEAT(MSA_EXT_8, "msa8-base", STFL, 146, "Message-security-assist-extension-8 facility (excluding subfunctions)") @@ -121,6 +122,9 @@ DEF_FEAT(SIE_CMMA, "cmma", SCLP_CONF_CHAR_EXT, 1, "SIE: Collaborative-memory-man DEF_FEAT(SIE_PFMFI, "pfmfi", SCLP_CONF_CHAR_EXT, 9, "SIE: PFMF interpretation facility") DEF_FEAT(SIE_IBS, "ibs", SCLP_CONF_CHAR_EXT, 10, "SIE: Interlock-and-broadcast-suppression facility") +/* Features exposed via SCLP SCCB Facilities byte 134 (bit numbers relative to byte-134) */ +DEF_FEAT(DIAG_318, "diag318", SCLP_FAC134, 0, "Control program name and version codes") + /* Features exposed via SCLP CPU info. */ DEF_FEAT(SIE_F2, "sief2", SCLP_CPU, 4, "SIE: interception format 2 (Virtual SIE)") DEF_FEAT(SIE_SKEY, "skey", SCLP_CPU, 5, "SIE: Storage-key facility") diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c index 8efe6ed514b707d1b08acbdc8337365ed29b2896..b5abff8befead7313b7ecd7bed83ab630cea6e71 100644 --- a/target/s390x/cpu_models.c +++ b/target/s390x/cpu_models.c @@ -29,6 +29,7 @@ #include "hw/pci/pci.h" #endif #include "qapi/qapi-commands-machine-target.h" +#include "hw/s390x/pv.h" #define CPUDEF_INIT(_type, _gen, _ec_ga, _mha_pow, _hmfai, _name, _desc) \ { \ @@ -238,6 +239,9 @@ bool s390_has_feat(S390Feat feat) } return 0; } + if (feat == S390_FEAT_DIAG_318 && s390_is_pv()) { + return false; + } return test_bit(feat, cpu->model->features); } @@ -510,21 +514,18 @@ static void cpu_model_from_info(S390CPUModel *model, const CpuModelInfo *info, if (qdict) { visitor = qobject_input_visitor_new(info->props); - visit_start_struct(visitor, NULL, NULL, 0, &err); - if (err) { - error_propagate(errp, err); + if (!visit_start_struct(visitor, NULL, NULL, 0, errp)) { visit_free(visitor); object_unref(obj); return; } for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) { - object_property_set(obj, visitor, e->key, &err); - if (err) { + if (!object_property_set(obj, e->key, visitor, &err)) { break; } } if (!err) { - visit_check_struct(visitor, errp); + visit_check_struct(visitor, &err); } visit_end_struct(visitor, NULL); visit_free(visitor); @@ -827,6 +828,7 @@ static void check_consistency(const S390CPUModel *model) { S390_FEAT_PTFF_STOE, S390_FEAT_MULTIPLE_EPOCH }, { S390_FEAT_PTFF_STOUE, S390_FEAT_MULTIPLE_EPOCH }, { S390_FEAT_AP_QUEUE_INTERRUPT_CONTROL, S390_FEAT_AP }, + { S390_FEAT_DIAG_318, S390_FEAT_EXTENDED_LENGTH_SCCB }, }; int i; @@ -984,7 +986,7 @@ void s390_realize_cpu_model(CPUState *cs, Error **errp) static void get_feature(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - S390Feat feat = (S390Feat) opaque; + S390Feat feat = (S390Feat) (uintptr_t) opaque; S390CPU *cpu = S390_CPU(obj); bool value; @@ -1001,8 +1003,7 @@ static void get_feature(Object *obj, Visitor *v, const char *name, static void set_feature(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - Error *err = NULL; - S390Feat feat = (S390Feat) opaque; + S390Feat feat = (S390Feat) (uintptr_t) opaque; DeviceState *dev = DEVICE(obj); S390CPU *cpu = S390_CPU(obj); bool value; @@ -1017,9 +1018,7 @@ static void set_feature(Object *obj, Visitor *v, const char *name, return; } - visit_type_bool(v, name, &value, &err); - if (err) { - error_propagate(errp, err); + if (!visit_type_bool(v, name, &value, errp)) { return; } if (value) { @@ -1038,7 +1037,7 @@ static void set_feature(Object *obj, Visitor *v, const char *name, static void get_feature_group(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - S390FeatGroup group = (S390FeatGroup) opaque; + S390FeatGroup group = (S390FeatGroup) (uintptr_t) opaque; const S390FeatGroupDef *def = s390_feat_group_def(group); S390CPU *cpu = S390_CPU(obj); S390FeatBitmap tmp; @@ -1059,8 +1058,7 @@ static void get_feature_group(Object *obj, Visitor *v, const char *name, static void set_feature_group(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - Error *err = NULL; - S390FeatGroup group = (S390FeatGroup) opaque; + S390FeatGroup group = (S390FeatGroup) (uintptr_t) opaque; const S390FeatGroupDef *def = s390_feat_group_def(group); DeviceState *dev = DEVICE(obj); S390CPU *cpu = S390_CPU(obj); @@ -1076,9 +1074,7 @@ static void set_feature_group(Object *obj, Visitor *v, const char *name, return; } - visit_type_bool(v, name, &value, &err); - if (err) { - error_propagate(errp, err); + if (!visit_type_bool(v, name, &value, errp)) { return; } if (value) { @@ -1098,25 +1094,6 @@ static void set_feature_group(Object *obj, Visitor *v, const char *name, } } -void s390_cpu_model_register_props(Object *obj) -{ - S390FeatGroup group; - S390Feat feat; - - for (feat = 0; feat < S390_FEAT_MAX; feat++) { - const S390FeatDef *def = s390_feat_def(feat); - object_property_add(obj, def->name, "bool", get_feature, - set_feature, NULL, (void *) feat); - object_property_set_description(obj, def->name, def->desc); - } - for (group = 0; group < S390_FEAT_GROUP_MAX; group++) { - const S390FeatGroupDef *def = s390_feat_group_def(group); - object_property_add(obj, def->name, "bool", get_feature_group, - set_feature_group, NULL, (void *) group); - object_property_set_description(obj, def->name, def->desc); - } -} - static void s390_cpu_model_initfn(Object *obj) { S390CPU *cpu = S390_CPU(obj); @@ -1224,11 +1201,27 @@ static char *get_description(Object *obj, Error **errp) void s390_cpu_model_class_register_props(ObjectClass *oc) { + S390FeatGroup group; + S390Feat feat; + object_class_property_add_bool(oc, "migration-safe", get_is_migration_safe, NULL); object_class_property_add_bool(oc, "static", get_is_static, NULL); object_class_property_add_str(oc, "description", get_description, NULL); + + for (feat = 0; feat < S390_FEAT_MAX; feat++) { + const S390FeatDef *def = s390_feat_def(feat); + object_class_property_add(oc, def->name, "bool", get_feature, + set_feature, NULL, (void *) feat); + object_class_property_set_description(oc, def->name, def->desc); + } + for (group = 0; group < S390_FEAT_GROUP_MAX; group++) { + const S390FeatGroupDef *def = s390_feat_group_def(group); + object_class_property_add(oc, def->name, "bool", get_feature_group, + set_feature_group, NULL, (void *) group); + object_class_property_set_description(oc, def->name, def->desc); + } } #ifdef CONFIG_KVM diff --git a/target/s390x/cpu_models.h b/target/s390x/cpu_models.h index 88bd01a61695a060f57204d101fafcd5cdc7e5be..74d1f87e4fd5fca9791abc4bf9e36b3341e5fb63 100644 --- a/target/s390x/cpu_models.h +++ b/target/s390x/cpu_models.h @@ -14,7 +14,7 @@ #define TARGET_S390X_CPU_MODELS_H #include "cpu_features.h" -#include "gen-features.h" +#include "target/s390x/gen-features.h" #include "hw/core/cpu.h" /* static CPU definition */ diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c index 3b58d10df3cace61a5058e713e0b16b665b39459..0adfbbda27084b94c99840d298c88be53b0c101b 100644 --- a/target/s390x/excp_helper.c +++ b/target/s390x/excp_helper.c @@ -610,4 +610,27 @@ void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr, tcg_s390_program_interrupt(env, PGM_SPECIFICATION, retaddr); } +static void QEMU_NORETURN monitor_event(CPUS390XState *env, + uint64_t monitor_code, + uint8_t monitor_class, uintptr_t ra) +{ + /* Store the Monitor Code and the Monitor Class Number into the lowcore */ + stq_phys(env_cpu(env)->as, + env->psa + offsetof(LowCore, monitor_code), monitor_code); + stw_phys(env_cpu(env)->as, + env->psa + offsetof(LowCore, mon_class_num), monitor_class); + + tcg_s390_program_interrupt(env, PGM_MONITOR, ra); +} + +void HELPER(monitor_call)(CPUS390XState *env, uint64_t monitor_code, + uint32_t monitor_class) +{ + g_assert(monitor_class <= 0xff); + + if (env->cregs[8] & (0x8000 >> monitor_class)) { + monitor_event(env, monitor_code, monitor_class, GETPC()); + } +} + #endif /* CONFIG_USER_ONLY */ diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c index 8ddeebc54419a3e2481e2191638984f24a50041f..a6ec918e901e873e16ace060476c4efe8c386251 100644 --- a/target/s390x/gen-features.c +++ b/target/s390x/gen-features.c @@ -412,7 +412,7 @@ static uint16_t base_GEN13_GA1[] = { static uint16_t base_GEN14_GA1[] = { S390_FEAT_ENTROPY_ENC_COMP, - S390_FEAT_MISC_INSTRUCTION_EXT, + S390_FEAT_MISC_INSTRUCTION_EXT2, S390_FEAT_SEMAPHORE_ASSIST, S390_FEAT_TIME_SLICE_INSTRUMENTATION, S390_FEAT_ORDER_PRESERVING_COMPRESSION, @@ -522,6 +522,8 @@ static uint16_t full_GEN12_GA1[] = { S390_FEAT_AP_QUEUE_INTERRUPT_CONTROL, S390_FEAT_AP_FACILITIES_TEST, S390_FEAT_AP, + S390_FEAT_EXTENDED_LENGTH_SCCB, + S390_FEAT_DIAG_318, }; static uint16_t full_GEN12_GA2[] = { @@ -716,6 +718,8 @@ static uint16_t qemu_MAX[] = { S390_FEAT_MSA_EXT_5, /* features introduced after the z13 */ S390_FEAT_INSTRUCTION_EXEC_PROT, + S390_FEAT_MISC_INSTRUCTION_EXT2, + S390_FEAT_MSA_EXT_8, }; /****** END FEATURE DEFS ******/ diff --git a/target/s390x/helper.c b/target/s390x/helper.c index 09f60406aa33c938ff54a0dbda134d0704a067ec..b877690845aa13a951e8284cf80999dd8121bccb 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -42,9 +42,6 @@ void s390x_cpu_timer(void *opaque) { cpu_inject_cpu_timer((S390CPU *) opaque); } -#endif - -#ifndef CONFIG_USER_ONLY hwaddr s390_cpu_get_phys_page_debug(CPUState *cs, vaddr vaddr) { @@ -98,14 +95,12 @@ void s390_handle_wait(S390CPU *cpu) CPUState *cs = CPU(cpu); if (s390_cpu_halt(cpu) == 0) { -#ifndef CONFIG_USER_ONLY if (is_special_wait_psw(cpu->env.psw.addr)) { qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); } else { cpu->env.crash_reason = S390_CRASH_REASON_DISABLED_WAIT; qemu_system_guest_panicked(cpu_get_crash_info(cs)); } -#endif } } @@ -435,6 +430,8 @@ const char *cc_name(enum cc_op cc_op) [CC_OP_FLOGR] = "CC_OP_FLOGR", [CC_OP_LCBB] = "CC_OP_LCBB", [CC_OP_VC] = "CC_OP_VC", + [CC_OP_MULS_32] = "CC_OP_MULS_32", + [CC_OP_MULS_64] = "CC_OP_MULS_64", }; return cc_names[cc_op]; diff --git a/target/s390x/helper.h b/target/s390x/helper.h index b5813c2ac2b94252956ccfdc989867c348bb8f39..55bd1551e6044b05ad2a712d91eaa3e02ed7b2ca 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -198,10 +198,6 @@ DEF_HELPER_FLAGS_4(gvec_vmlo16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) DEF_HELPER_FLAGS_4(gvec_vmlo32, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) DEF_HELPER_FLAGS_3(gvec_vpopct8, TCG_CALL_NO_RWG, void, ptr, cptr, i32) DEF_HELPER_FLAGS_3(gvec_vpopct16, TCG_CALL_NO_RWG, void, ptr, cptr, i32) -DEF_HELPER_FLAGS_4(gvec_verllv8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) -DEF_HELPER_FLAGS_4(gvec_verllv16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) -DEF_HELPER_FLAGS_4(gvec_verll8, TCG_CALL_NO_RWG, void, ptr, cptr, i64, i32) -DEF_HELPER_FLAGS_4(gvec_verll16, TCG_CALL_NO_RWG, void, ptr, cptr, i64, i32) DEF_HELPER_FLAGS_4(gvec_verim8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) DEF_HELPER_FLAGS_4(gvec_verim16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) DEF_HELPER_FLAGS_4(gvec_vsl, TCG_CALL_NO_RWG, void, ptr, cptr, i64, i32) @@ -353,4 +349,5 @@ DEF_HELPER_3(sic, void, env, i64, i64) DEF_HELPER_3(rpcit, void, env, i32, i32) DEF_HELPER_5(pcistb, void, env, i32, i32, i64, i32) DEF_HELPER_4(mpcifc, void, env, i32, i64, i32) +DEF_HELPER_3(monitor_call, void, env, i64, i32) #endif diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 2bc77f08710204e8268606a668de357631d0e677..b95bc98d357adfdd7de1b93e2632409dd686943f 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -52,6 +52,7 @@ /* ADD HALFWORD */ C(0x4a00, AH, RX_a, Z, r1, m2_16s, new, r1_32, add, adds32) C(0xe37a, AHY, RXY_a, LD, r1, m2_16s, new, r1_32, add, adds32) + C(0xe338, AGH, RXY_a, MIE2,r1, m2_16s, r1, 0, add, adds64) /* ADD HALFWORD IMMEDIATE */ C(0xa70a, AHI, RI_a, Z, r1, i2, new, r1_32, add, adds32) C(0xa70b, AGHI, RI_a, Z, r1, i2, r1, 0, add, adds64) @@ -114,6 +115,8 @@ /* BRANCH RELATIVE AND SAVE */ C(0xa705, BRAS, RI_b, Z, 0, 0, r1, 0, basi, 0) C(0xc005, BRASL, RIL_b, Z, 0, 0, r1, 0, basi, 0) +/* BRANCH INDIRECT ON CONDITION */ + C(0xe347, BIC, RXY_b, MIE2,0, m2_64w, 0, 0, bc, 0) /* BRANCH ON CONDITION */ C(0x0700, BCR, RR_b, Z, 0, r2_nz, 0, 0, bc, 0) C(0x4700, BC, RX_b, Z, 0, a2, 0, 0, bc, 0) @@ -376,7 +379,7 @@ /* EXTRACT CPU ATTRIBUTE */ C(0xeb4c, ECAG, RSY_a, GIE, 0, a2, r1, 0, ecag, 0) /* EXTRACT CPU TIME */ - C(0xc801, ECTG, SSF, ECT, 0, 0, 0, 0, ectg, 0) + F(0xc801, ECTG, SSF, ECT, 0, 0, 0, 0, ectg, 0, IF_IO) /* EXTRACT FPC */ F(0xb38c, EFPC, RRE, Z, 0, 0, new, r1_32, efpc, 0, IF_BFP) /* EXTRACT PSW */ @@ -617,6 +620,9 @@ C(0x9a00, LAM, RS_a, Z, 0, a2, 0, 0, lam, 0) C(0xeb9a, LAMY, RSY_a, LD, 0, a2, 0, 0, lam, 0) +/* MONITOR CALL */ + C(0xaf00, MC, SI, Z, la1, 0, 0, 0, mc, 0) + /* MOVE */ C(0xd200, MVC, SS_a, Z, la1, a2, 0, 0, mvc, 0) C(0xe544, MVHHI, SIL, GIE, la1, i2, 0, m1_16, mov2, 0) @@ -649,8 +655,10 @@ /* MULTIPLY */ C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0) + C(0xb9ec, MGRK, RRF_a, MIE2,r3_o, r2_o, r1_P, 0, muls128, 0) C(0x5c00, M, RX_a, Z, r1p1_32s, m2_32s, new, r1_D32, mul, 0) C(0xe35c, MFY, RXY_a, GIE, r1p1_32s, m2_32s, new, r1_D32, mul, 0) + C(0xe384, MG, RXY_a, MIE2,r1p1_o, m2_64, r1_P, 0, muls128, 0) F(0xb317, MEEBR, RRE, Z, e1, e2, new, e1, meeb, 0, IF_BFP) F(0xb31c, MDBR, RRE, Z, f1, f2, new, f1, mdb, 0, IF_BFP) F(0xb34c, MXBR, RRE, Z, x2h, x2l, x1, x1, mxb, 0, IF_BFP) @@ -663,6 +671,7 @@ /* MULTIPLY HALFWORD */ C(0x4c00, MH, RX_a, Z, r1_o, m2_16s, new, r1_32, mul, 0) C(0xe37c, MHY, RXY_a, GIE, r1_o, m2_16s, new, r1_32, mul, 0) + C(0xe33c, MGH, RXY_a, MIE2,r1_o, m2_16s, r1, 0, mul, 0) /* MULTIPLY HALFWORD IMMEDIATE */ C(0xa70c, MHI, RI_a, Z, r1_o, i2, new, r1_32, mul, 0) C(0xa70d, MGHI, RI_a, Z, r1_o, i2, r1, 0, mul, 0) @@ -673,11 +682,15 @@ C(0xe386, MLG, RXY_a, Z, r1p1, m2_64, r1_P, 0, mul128, 0) /* MULTIPLY SINGLE */ C(0xb252, MSR, RRE, Z, r1_o, r2_o, new, r1_32, mul, 0) + C(0xb9fd, MSRKC, RRF_a, MIE2,r3_32s, r2_32s, new, r1_32, mul, muls32) C(0x7100, MS, RX_a, Z, r1_o, m2_32s, new, r1_32, mul, 0) C(0xe351, MSY, RXY_a, LD, r1_o, m2_32s, new, r1_32, mul, 0) + C(0xe353, MSC, RXY_a, MIE2,r1_32s, m2_32s, new, r1_32, mul, muls32) C(0xb90c, MSGR, RRE, Z, r1_o, r2_o, r1, 0, mul, 0) + C(0xb9ed, MSGRKC, RRF_a, MIE2,r3_o, r2_o, new_P, out2_r1, muls128, muls64) C(0xb91c, MSGFR, RRE, Z, r1_o, r2_32s, r1, 0, mul, 0) C(0xe30c, MSG, RXY_a, Z, r1_o, m2_64, r1, 0, mul, 0) + C(0xe383, MSGC, RXY_a, MIE2,r1_o, m2_64, new_P, out2_r1, muls128, muls64) C(0xe31c, MSGF, RXY_a, Z, r1_o, m2_32s, r1, 0, mul, 0) /* MULTIPLY SINGLE IMMEDIATE */ C(0xc201, MSFI, RIL_a, GIE, r1_o, i2, new, r1_32, mul, 0) @@ -798,7 +811,7 @@ /* SQUARE ROOT */ F(0xb314, SQEBR, RRE, Z, 0, e2, new, e1, sqeb, 0, IF_BFP) F(0xb315, SQDBR, RRE, Z, 0, f2, new, f1, sqdb, 0, IF_BFP) - F(0xb316, SQXBR, RRE, Z, x2h, x2l, new, x1, sqxb, 0, IF_BFP) + F(0xb316, SQXBR, RRE, Z, x2h, x2l, new_P, x1, sqxb, 0, IF_BFP) F(0xed14, SQEB, RXE, Z, 0, m2_32u, new, e1, sqeb, 0, IF_BFP) F(0xed15, SQDB, RXE, Z, 0, m2_64, new, f1, sqdb, 0, IF_BFP) @@ -842,10 +855,10 @@ C(0xe32f, STRVG, RXY_a, Z, la2, r1_o, new, m1_64, rev64, 0) /* STORE CLOCK */ - C(0xb205, STCK, S, Z, la2, 0, new, m1_64, stck, 0) - C(0xb27c, STCKF, S, SCF, la2, 0, new, m1_64, stck, 0) + F(0xb205, STCK, S, Z, la2, 0, new, m1_64, stck, 0, IF_IO) + F(0xb27c, STCKF, S, SCF, la2, 0, new, m1_64, stck, 0, IF_IO) /* STORE CLOCK EXTENDED */ - C(0xb278, STCKE, S, Z, 0, a2, 0, 0, stcke, 0) + F(0xb278, STCKE, S, Z, 0, a2, 0, 0, stcke, 0, IF_IO) /* STORE FACILITY LIST EXTENDED */ C(0xb2b0, STFLE, S, SFLE, 0, a2, 0, 0, stfle, 0) @@ -882,6 +895,7 @@ /* SUBTRACT HALFWORD */ C(0x4b00, SH, RX_a, Z, r1, m2_16s, new, r1_32, sub, subs32) C(0xe37b, SHY, RXY_a, LD, r1, m2_16s, new, r1_32, sub, subs32) + C(0xe339, SGH, RXY_a, MIE2,r1, m2_16s, r1, 0, sub, subs64) /* SUBTRACT HIGH */ C(0xb9c9, SHHHR, RRF_a, HW, r2_sr32, r3_sr32, new, r1_32h, sub, subs32) C(0xb9d9, SHHLR, RRF_a, HW, r2_sr32, r3, new, r1_32h, sub, subs32) @@ -968,6 +982,7 @@ D(0xb92d, KMCTR, RRF_b, MSA4, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KMCTR) D(0xb92e, KM, RRE, MSA, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KM) D(0xb92f, KMC, RRE, MSA, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KMC) + D(0xb929, KMA, RRF_b, MSA8, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KMA) D(0xb93c, PPNO, RRE, MSA5, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_PPNO) D(0xb93e, KIMD, RRE, MSA, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KIMD) D(0xb93f, KLMD, RRE, MSA, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KLMD) @@ -1147,8 +1162,8 @@ /* VECTOR POPULATION COUNT */ F(0xe750, VPOPCT, VRR_a, V, 0, 0, 0, 0, vpopct, 0, IF_VEC) /* VECTOR ELEMENT ROTATE LEFT LOGICAL */ - F(0xe773, VERLLV, VRR_c, V, 0, 0, 0, 0, verllv, 0, IF_VEC) - F(0xe733, VERLL, VRS_a, V, la2, 0, 0, 0, verll, 0, IF_VEC) + F(0xe773, VERLLV, VRR_c, V, 0, 0, 0, 0, vesv, 0, IF_VEC) + F(0xe733, VERLL, VRS_a, V, la2, 0, 0, 0, ves, 0, IF_VEC) /* VECTOR ELEMENT ROTATE AND INSERT UNDER MASK */ F(0xe772, VERIM, VRI_d, V, 0, 0, 0, 0, verim, 0, IF_VEC) /* VECTOR ELEMENT SHIFT LEFT */ @@ -1254,7 +1269,7 @@ E(0xb250, CSP, RRE, Z, r1_32u, ra2, r1_P, 0, csp, 0, MO_TEUL, IF_PRIV) E(0xb98a, CSPG, RRE, DAT_ENH, r1_o, ra2, r1_P, 0, csp, 0, MO_TEQ, IF_PRIV) /* DIAGNOSE (KVM hypercall) */ - F(0x8300, DIAG, RSI, Z, 0, 0, 0, 0, diag, 0, IF_PRIV) + F(0x8300, DIAG, RSI, Z, 0, 0, 0, 0, diag, 0, IF_PRIV | IF_IO) /* INSERT STORAGE KEY EXTENDED */ F(0xb229, ISKE, RRE, Z, 0, r2_o, new, r1_8, iske, 0, IF_PRIV) /* INVALIDATE DAT TABLE ENTRY */ @@ -1286,17 +1301,17 @@ /* RESET REFERENCE BIT EXTENDED */ F(0xb22a, RRBE, RRE, Z, 0, r2_o, 0, 0, rrbe, 0, IF_PRIV) /* SERVICE CALL LOGICAL PROCESSOR (PV hypercall) */ - F(0xb220, SERVC, RRE, Z, r1_o, r2_o, 0, 0, servc, 0, IF_PRIV) + F(0xb220, SERVC, RRE, Z, r1_o, r2_o, 0, 0, servc, 0, IF_PRIV | IF_IO) /* SET ADDRESS SPACE CONTROL FAST */ F(0xb279, SACF, S, Z, 0, a2, 0, 0, sacf, 0, IF_PRIV) /* SET CLOCK */ - F(0xb204, SCK, S, Z, la2, 0, 0, 0, sck, 0, IF_PRIV) + F(0xb204, SCK, S, Z, la2, 0, 0, 0, sck, 0, IF_PRIV | IF_IO) /* SET CLOCK COMPARATOR */ - F(0xb206, SCKC, S, Z, 0, m2_64a, 0, 0, sckc, 0, IF_PRIV) + F(0xb206, SCKC, S, Z, 0, m2_64a, 0, 0, sckc, 0, IF_PRIV | IF_IO) /* SET CLOCK PROGRAMMABLE FIELD */ F(0x0107, SCKPF, E, Z, 0, 0, 0, 0, sckpf, 0, IF_PRIV) /* SET CPU TIMER */ - F(0xb208, SPT, S, Z, 0, m2_64a, 0, 0, spt, 0, IF_PRIV) + F(0xb208, SPT, S, Z, 0, m2_64a, 0, 0, spt, 0, IF_PRIV | IF_IO) /* SET PREFIX */ F(0xb210, SPX, S, Z, 0, m2_32ua, 0, 0, spx, 0, IF_PRIV) /* SET PSW KEY FROM ADDRESS */ @@ -1306,7 +1321,7 @@ /* SET SYSTEM MASK */ F(0x8000, SSM, S, Z, 0, m2_8u, 0, 0, ssm, 0, IF_PRIV) /* SIGNAL PROCESSOR */ - F(0xae00, SIGP, RS_a, Z, 0, a2, 0, 0, sigp, 0, IF_PRIV) + F(0xae00, SIGP, RS_a, Z, 0, a2, 0, 0, sigp, 0, IF_PRIV | IF_IO) /* STORE CLOCK COMPARATOR */ F(0xb207, STCKC, S, Z, la2, 0, new, m1_64a, stckc, 0, IF_PRIV) /* STORE CONTROL */ @@ -1317,7 +1332,7 @@ /* STORE CPU ID */ F(0xb202, STIDP, S, Z, la2, 0, new, m1_64a, stidp, 0, IF_PRIV) /* STORE CPU TIMER */ - F(0xb209, STPT, S, Z, la2, 0, new, m1_64a, stpt, 0, IF_PRIV) + F(0xb209, STPT, S, Z, la2, 0, new, m1_64a, stpt, 0, IF_PRIV | IF_IO) /* STORE FACILITY LIST */ F(0xb2b1, STFL, S, Z, 0, 0, 0, 0, stfl, 0, IF_PRIV) /* STORE PREFIX */ @@ -1337,35 +1352,35 @@ C(0xe501, TPROT, SSE, Z, la1, a2, 0, 0, tprot, 0) /* CCW I/O Instructions */ - F(0xb276, XSCH, S, Z, 0, 0, 0, 0, xsch, 0, IF_PRIV) - F(0xb230, CSCH, S, Z, 0, 0, 0, 0, csch, 0, IF_PRIV) - F(0xb231, HSCH, S, Z, 0, 0, 0, 0, hsch, 0, IF_PRIV) - F(0xb232, MSCH, S, Z, 0, insn, 0, 0, msch, 0, IF_PRIV) - F(0xb23b, RCHP, S, Z, 0, 0, 0, 0, rchp, 0, IF_PRIV) - F(0xb238, RSCH, S, Z, 0, 0, 0, 0, rsch, 0, IF_PRIV) - F(0xb237, SAL, S, Z, 0, 0, 0, 0, sal, 0, IF_PRIV) - F(0xb23c, SCHM, S, Z, 0, insn, 0, 0, schm, 0, IF_PRIV) - F(0xb274, SIGA, S, Z, 0, 0, 0, 0, siga, 0, IF_PRIV) - F(0xb23a, STCPS, S, Z, 0, 0, 0, 0, stcps, 0, IF_PRIV) - F(0xb233, SSCH, S, Z, 0, insn, 0, 0, ssch, 0, IF_PRIV) - F(0xb239, STCRW, S, Z, 0, insn, 0, 0, stcrw, 0, IF_PRIV) - F(0xb234, STSCH, S, Z, 0, insn, 0, 0, stsch, 0, IF_PRIV) - F(0xb236, TPI , S, Z, la2, 0, 0, 0, tpi, 0, IF_PRIV) - F(0xb235, TSCH, S, Z, 0, insn, 0, 0, tsch, 0, IF_PRIV) + F(0xb276, XSCH, S, Z, 0, 0, 0, 0, xsch, 0, IF_PRIV | IF_IO) + F(0xb230, CSCH, S, Z, 0, 0, 0, 0, csch, 0, IF_PRIV | IF_IO) + F(0xb231, HSCH, S, Z, 0, 0, 0, 0, hsch, 0, IF_PRIV | IF_IO) + F(0xb232, MSCH, S, Z, 0, insn, 0, 0, msch, 0, IF_PRIV | IF_IO) + F(0xb23b, RCHP, S, Z, 0, 0, 0, 0, rchp, 0, IF_PRIV | IF_IO) + F(0xb238, RSCH, S, Z, 0, 0, 0, 0, rsch, 0, IF_PRIV | IF_IO) + F(0xb237, SAL, S, Z, 0, 0, 0, 0, sal, 0, IF_PRIV | IF_IO) + F(0xb23c, SCHM, S, Z, 0, insn, 0, 0, schm, 0, IF_PRIV | IF_IO) + F(0xb274, SIGA, S, Z, 0, 0, 0, 0, siga, 0, IF_PRIV | IF_IO) + F(0xb23a, STCPS, S, Z, 0, 0, 0, 0, stcps, 0, IF_PRIV | IF_IO) + F(0xb233, SSCH, S, Z, 0, insn, 0, 0, ssch, 0, IF_PRIV | IF_IO) + F(0xb239, STCRW, S, Z, 0, insn, 0, 0, stcrw, 0, IF_PRIV | IF_IO) + F(0xb234, STSCH, S, Z, 0, insn, 0, 0, stsch, 0, IF_PRIV | IF_IO) + F(0xb236, TPI , S, Z, la2, 0, 0, 0, tpi, 0, IF_PRIV | IF_IO) + F(0xb235, TSCH, S, Z, 0, insn, 0, 0, tsch, 0, IF_PRIV | IF_IO) /* ??? Not listed in PoO ninth edition, but there's a linux driver that uses it: "A CHSC subchannel is usually present on LPAR only." */ - F(0xb25f, CHSC, RRE, Z, 0, insn, 0, 0, chsc, 0, IF_PRIV) + F(0xb25f, CHSC, RRE, Z, 0, insn, 0, 0, chsc, 0, IF_PRIV | IF_IO) /* zPCI Instructions */ /* None of these instructions are documented in the PoP, so this is all based upon target/s390x/kvm.c and Linux code and likely incomplete */ - F(0xebd0, PCISTB, RSY_a, PCI, la2, 0, 0, 0, pcistb, 0, IF_PRIV) - F(0xebd1, SIC, RSY_a, AIS, r1, r3, 0, 0, sic, 0, IF_PRIV) - F(0xb9a0, CLP, RRF_c, PCI, 0, 0, 0, 0, clp, 0, IF_PRIV) - F(0xb9d0, PCISTG, RRE, PCI, 0, 0, 0, 0, pcistg, 0, IF_PRIV) - F(0xb9d2, PCILG, RRE, PCI, 0, 0, 0, 0, pcilg, 0, IF_PRIV) - F(0xb9d3, RPCIT, RRE, PCI, 0, 0, 0, 0, rpcit, 0, IF_PRIV) - F(0xe3d0, MPCIFC, RXY_a, PCI, la2, 0, 0, 0, mpcifc, 0, IF_PRIV) - F(0xe3d4, STPCIFC, RXY_a, PCI, la2, 0, 0, 0, stpcifc, 0, IF_PRIV) + F(0xebd0, PCISTB, RSY_a, PCI, la2, 0, 0, 0, pcistb, 0, IF_PRIV | IF_IO) + F(0xebd1, SIC, RSY_a, AIS, r1, r3, 0, 0, sic, 0, IF_PRIV | IF_IO) + F(0xb9a0, CLP, RRF_c, PCI, 0, 0, 0, 0, clp, 0, IF_PRIV | IF_IO) + F(0xb9d0, PCISTG, RRE, PCI, 0, 0, 0, 0, pcistg, 0, IF_PRIV | IF_IO) + F(0xb9d2, PCILG, RRE, PCI, 0, 0, 0, 0, pcilg, 0, IF_PRIV | IF_IO) + F(0xb9d3, RPCIT, RRE, PCI, 0, 0, 0, 0, rpcit, 0, IF_PRIV | IF_IO) + F(0xe3d0, MPCIFC, RXY_a, PCI, la2, 0, 0, 0, mpcifc, 0, IF_PRIV | IF_IO) + F(0xe3d4, STPCIFC, RXY_a, PCI, la2, 0, 0, 0, stpcifc, 0, IF_PRIV | IF_IO) #endif /* CONFIG_USER_ONLY */ diff --git a/target/s390x/internal.h b/target/s390x/internal.h index 8c95c734dbe92f1b2187c9edb9469708718d5e5c..64602660ae17bd54be56320f1516fb81200918be 100644 --- a/target/s390x/internal.h +++ b/target/s390x/internal.h @@ -175,6 +175,7 @@ enum cc_op { CC_OP_SUBB_64, /* overflow on unsigned sub-borrow (64bit) */ CC_OP_ABS_64, /* sign eval on abs (64bit) */ CC_OP_NABS_64, /* sign eval on nabs (64bit) */ + CC_OP_MULS_64, /* overflow on signed multiply (64bit) */ CC_OP_ADD_32, /* overflow on add (32bit) */ CC_OP_ADDU_32, /* overflow on unsigned add (32bit) */ @@ -184,6 +185,7 @@ enum cc_op { CC_OP_SUBB_32, /* overflow on unsigned sub-borrow (32bit) */ CC_OP_ABS_32, /* sign eval on abs (64bit) */ CC_OP_NABS_32, /* sign eval on nabs (64bit) */ + CC_OP_MULS_32, /* overflow on signed multiply (32bit) */ CC_OP_COMP_32, /* complement */ CC_OP_COMP_64, /* complement */ @@ -204,6 +206,8 @@ enum cc_op { CC_OP_MAX }; +#ifndef CONFIG_USER_ONLY + static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb, uint8_t *ar) { @@ -225,6 +229,8 @@ static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb, /* Base/displacement are at the same locations. */ #define decode_basedisp_rs decode_basedisp_s +#endif /* CONFIG_USER_ONLY */ + /* arch_dump.c */ int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, int cpuid, void *opaque); @@ -232,9 +238,11 @@ int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, /* cc_helper.c */ const char *cc_name(enum cc_op cc_op); -void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr); uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst, uint64_t vr); +#ifndef CONFIG_USER_ONLY +void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr); +#endif /* CONFIG_USER_ONLY */ /* cpu.c */ @@ -254,7 +262,6 @@ static inline void s390_cpu_unhalt(S390CPU *cpu) /* cpu_models.c */ -void s390_cpu_model_register_props(Object *obj); void s390_cpu_model_class_register_props(ObjectClass *oc); void s390_realize_cpu_model(CPUState *cs, Error **errp); ObjectClass *s390_cpu_class_by_name(const char *name); @@ -299,18 +306,18 @@ void s390_cpu_gdb_init(CPUState *cs); /* helper.c */ void s390_cpu_dump_state(CPUState *cpu, FILE *f, int flags); -hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); -hwaddr s390_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr); +void do_restart_interrupt(CPUS390XState *env); +#ifndef CONFIG_USER_ONLY uint64_t get_psw_mask(CPUS390XState *env); void s390_cpu_recompute_watchpoints(CPUState *cs); void s390x_tod_timer(void *opaque); void s390x_cpu_timer(void *opaque); -void do_restart_interrupt(CPUS390XState *env); void s390_handle_wait(S390CPU *cpu); +hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); +hwaddr s390_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr); #define S390_STORE_STATUS_DEF_ADDR offsetof(LowCore, floating_pt_save_area) int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch); int s390_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len); -#ifndef CONFIG_USER_ONLY LowCore *cpu_map_lowcore(CPUS390XState *env); void cpu_unmap_lowcore(LowCore *lowcore); #endif /* CONFIG_USER_ONLY */ diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c index 7a14c52c123b842bba0b13f96b16b6c9843065cb..a412926d27808efe0e9245d5a8565e6491e076c7 100644 --- a/target/s390x/ioinst.c +++ b/target/s390x/ioinst.c @@ -292,8 +292,7 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, sch = css_find_subch(m, cssid, ssid, schid); if (sch) { if (css_subch_visible(sch)) { - css_do_stsch(sch, &schib); - cc = 0; + cc = css_do_stsch(sch, &schib); } else { /* Indicate no more subchannels in this css/ss */ cc = 3; diff --git a/target/s390x/kvm-stub.c b/target/s390x/kvm-stub.c index aa185017a2a886ca300fa75747edc242cab32ce2..9970b5a8c7056f1a9c433e593c47f8c5a8fa66cb 100644 --- a/target/s390x/kvm-stub.c +++ b/target/s390x/kvm-stub.c @@ -120,3 +120,7 @@ void kvm_s390_stop_interrupt(S390CPU *cpu) void kvm_s390_restart_interrupt(S390CPU *cpu) { } + +void kvm_s390_set_diag318(CPUState *cs, uint64_t diag318_info) +{ +} diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index 69881a0da0b31f72c4c3794d17ab6275913064b5..b8385e6b95d365e089c4c756ef8933fa2c4f09e2 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -105,6 +105,7 @@ #define DIAG_TIMEREVENT 0x288 #define DIAG_IPL 0x308 +#define DIAG_SET_CONTROL_PROGRAM_CODES 0x318 #define DIAG_KVM_HYPERCALL 0x500 #define DIAG_KVM_BREAKPOINT 0x501 @@ -602,6 +603,11 @@ int kvm_arch_put_registers(CPUState *cs, int level) cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_ETOKEN; } + if (can_sync_regs(cs, KVM_SYNC_DIAG318)) { + cs->kvm_run->s.regs.diag318 = env->diag318_info; + cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_DIAG318; + } + /* Finally the prefix */ if (can_sync_regs(cs, KVM_SYNC_PREFIX)) { cs->kvm_run->s.regs.prefix = env->psa; @@ -741,6 +747,10 @@ int kvm_arch_get_registers(CPUState *cs) } } + if (can_sync_regs(cs, KVM_SYNC_DIAG318)) { + env->diag318_info = cs->kvm_run->s.regs.diag318; + } + return 0; } @@ -1601,6 +1611,39 @@ static int handle_sw_breakpoint(S390CPU *cpu, struct kvm_run *run) return -ENOENT; } +void kvm_s390_set_diag318(CPUState *cs, uint64_t diag318_info) +{ + CPUS390XState *env = &S390_CPU(cs)->env; + + /* Feat bit is set only if KVM supports sync for diag318 */ + if (s390_has_feat(S390_FEAT_DIAG_318)) { + env->diag318_info = diag318_info; + cs->kvm_run->s.regs.diag318 = diag318_info; + cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_DIAG318; + } +} + +static void handle_diag_318(S390CPU *cpu, struct kvm_run *run) +{ + uint64_t reg = (run->s390_sieic.ipa & 0x00f0) >> 4; + uint64_t diag318_info = run->s.regs.gprs[reg]; + CPUState *t; + + /* + * DIAG 318 can only be enabled with KVM support. As such, let's + * ensure a guest cannot execute this instruction erroneously. + */ + if (!s390_has_feat(S390_FEAT_DIAG_318)) { + kvm_s390_program_interrupt(cpu, PGM_SPECIFICATION); + return; + } + + CPU_FOREACH(t) { + run_on_cpu(t, s390_do_cpu_set_diag318, + RUN_ON_CPU_HOST_ULONG(diag318_info)); + } +} + #define DIAG_KVM_CODE_MASK 0x000000000000ffff static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb) @@ -1620,6 +1663,9 @@ static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb) case DIAG_IPL: kvm_handle_diag_308(cpu, run); break; + case DIAG_SET_CONTROL_PROGRAM_CODES: + handle_diag_318(cpu, run); + break; case DIAG_KVM_HYPERCALL: r = handle_hypercall(cpu, run); break; @@ -2165,7 +2211,7 @@ int kvm_arch_msi_data_to_gsi(uint32_t data) static int query_cpu_subfunc(S390FeatBitmap features) { - struct kvm_s390_vm_cpu_subfunc prop; + struct kvm_s390_vm_cpu_subfunc prop = {}; struct kvm_device_attr attr = { .group = KVM_S390_VM_CPU_MODEL, .attr = KVM_S390_VM_CPU_MACHINE_SUBFUNC, @@ -2292,7 +2338,7 @@ static int kvm_to_feat[][2] = { static int query_cpu_feat(S390FeatBitmap features) { - struct kvm_s390_vm_cpu_feat prop; + struct kvm_s390_vm_cpu_feat prop = {}; struct kvm_device_attr attr = { .group = KVM_S390_VM_CPU_MODEL, .attr = KVM_S390_VM_CPU_MACHINE_FEAT, @@ -2456,6 +2502,18 @@ void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp) KVM_S390_VM_CRYPTO_ENABLE_APIE)) { set_bit(S390_FEAT_AP, model->features); } + + /* + * Extended-Length SCCB is handled entirely within QEMU. + * For PV guests this is completely fenced by the Ultravisor, as Service + * Call error checking and STFLE interpretation are handled via SIE. + */ + set_bit(S390_FEAT_EXTENDED_LENGTH_SCCB, model->features); + + if (kvm_check_extension(kvm_state, KVM_CAP_S390_DIAG318)) { + set_bit(S390_FEAT_DIAG_318, model->features); + } + /* strip of features that are not part of the maximum model */ bitmap_and(model->features, model->features, model->def->full_feat, S390_FEAT_MAX); diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h index 6ab17c81b73a0011e32213552698a15cbc08a8d9..25bbe98b25141a81f3b1e1edd6831deb68bec347 100644 --- a/target/s390x/kvm_s390x.h +++ b/target/s390x/kvm_s390x.h @@ -45,5 +45,6 @@ void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp); void kvm_s390_crypto_reset(void); void kvm_s390_restart_interrupt(S390CPU *cpu); void kvm_s390_stop_interrupt(S390CPU *cpu); +void kvm_s390_set_diag318(CPUState *cs, uint64_t diag318_info); #endif /* KVM_S390X_H */ diff --git a/target/s390x/machine.c b/target/s390x/machine.c index 549bb6c2808fdbf4b5c2ffd1e1f649a1e95f4d01..5b4e82f1ab99b0371bf29bfe9e9524152dfe7029 100644 --- a/target/s390x/machine.c +++ b/target/s390x/machine.c @@ -234,6 +234,22 @@ const VMStateDescription vmstate_etoken = { } }; +static bool diag318_needed(void *opaque) +{ + return s390_has_feat(S390_FEAT_DIAG_318); +} + +const VMStateDescription vmstate_diag318 = { + .name = "cpu/diag318", + .version_id = 1, + .minimum_version_id = 1, + .needed = diag318_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT64(env.diag318_info, S390CPU), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_s390_cpu = { .name = "cpu", .post_load = cpu_post_load, @@ -270,6 +286,7 @@ const VMStateDescription vmstate_s390_cpu = { &vmstate_gscb, &vmstate_bpbc, &vmstate_etoken, + &vmstate_diag318, NULL }, }; diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index a237dec7579e66f9ff3c3bb03d5b0d53cbc13502..bd25eed3e85738b58d27d6b1c8080fc9aa02c8c5 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1780,7 +1780,7 @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1, if (parallel) { #ifdef CONFIG_USER_ONLY uint32_t *haddr = g2h(a1); - ov = atomic_cmpxchg__nocheck(haddr, cv, nv); + ov = qatomic_cmpxchg__nocheck(haddr, cv, nv); #else TCGMemOpIdx oi = make_memop_idx(MO_TEUL | MO_ALIGN, mem_idx); ov = helper_atomic_cmpxchgl_be_mmu(env, a1, cv, nv, oi, ra); @@ -1804,7 +1804,7 @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1, #ifdef CONFIG_ATOMIC64 # ifdef CONFIG_USER_ONLY uint64_t *haddr = g2h(a1); - ov = atomic_cmpxchg__nocheck(haddr, cv, nv); + ov = qatomic_cmpxchg__nocheck(haddr, cv, nv); # else TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN, mem_idx); ov = helper_atomic_cmpxchgq_be_mmu(env, a1, cv, nv, oi, ra); diff --git a/target/s390x/meson.build b/target/s390x/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..c42eadb7d245439967082c75fd63337a468c7d23 --- /dev/null +++ b/target/s390x/meson.build @@ -0,0 +1,62 @@ +s390x_ss = ss.source_set() +s390x_ss.add(files( + 'cpu.c', + 'cpu_features.c', + 'cpu_models.c', + 'gdbstub.c', + 'helper.c', + 'interrupt.c', +)) + +s390x_ss.add(when: 'CONFIG_TCG', if_true: files( + 'cc_helper.c', + 'crypto_helper.c', + 'excp_helper.c', + 'fpu_helper.c', + 'int_helper.c', + 'mem_helper.c', + 'misc_helper.c', + 'translate.c', + 'vec_fpu_helper.c', + 'vec_helper.c', + 'vec_int_helper.c', + 'vec_string_helper.c', +), if_false: files('tcg-stub.c')) + +s390x_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('kvm-stub.c')) + +gen_features = executable('gen-features', 'gen-features.c', native: true, + build_by_default: false) + +gen_features_h = custom_target('gen-features.h', + output: 'gen-features.h', + capture: true, + command: gen_features) + +s390x_ss.add(gen_features_h) + +s390x_softmmu_ss = ss.source_set() +s390x_softmmu_ss.add(files( + 'arch_dump.c', + 'diag.c', + 'ioinst.c', + 'machine.c', + 'mmu_helper.c', + 'sigp.c', +)) + +# Newer kernels on s390 check for an S390_PGSTE program header and +# enable the pgste page table extensions in that case. This makes +# the vm.allocate_pgste sysctl unnecessary. We enable this program +# header if +# - we build on s390x +# - we build the system emulation for s390x (qemu-system-s390x) +# - KVM is enabled +# - the linker supports --s390-pgste +if host_machine.cpu_family() == 's390x' and cc.has_link_argument('-Wl,--s390-pgste') + s390x_softmmu_ss.add(when: 'CONFIG_KVM', + if_true: declare_dependency(link_args: ['-Wl,--s390-pgste'])) +endif + +target_arch += {'s390x': s390x_ss} +target_softmmu_arch += {'s390x': s390x_softmmu_ss} diff --git a/target/s390x/trace.h b/target/s390x/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..d7d59d4abad4c06bfa73cdcbec9bfdd574191ef8 --- /dev/null +++ b/target/s390x/trace.h @@ -0,0 +1 @@ +#include "trace/trace-target_s390x.h" diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 4f6f1e31cdfd345542a40ad6b76f60b368b8dd56..be32938f6d21832ebb69e12ef7bbb2feca816d71 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -646,6 +646,7 @@ static void gen_op_calc_cc(DisasContext *s) case CC_OP_NZ_F64: case CC_OP_FLOGR: case CC_OP_LCBB: + case CC_OP_MULS_32: /* 1 argument */ gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy); break; @@ -660,6 +661,7 @@ static void gen_op_calc_cc(DisasContext *s) case CC_OP_SLA_64: case CC_OP_NZ_F128: case CC_OP_VC: + case CC_OP_MULS_64: /* 2 arguments */ gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy); break; @@ -1212,6 +1214,7 @@ typedef struct { #define IF_DFP 0x0010 /* decimal floating point instruction */ #define IF_PRIV 0x0020 /* privileged instruction */ #define IF_VEC 0x0040 /* vector instruction */ +#define IF_IO 0x0080 /* input/output instruction */ struct DisasInsn { unsigned opc:16; @@ -2708,6 +2711,12 @@ static DisasJumpType op_msa(DisasContext *s, DisasOps *o) TCGv_i32 t_r1, t_r2, t_r3, type; switch (s->insn->data) { + case S390_FEAT_TYPE_KMA: + if (r3 == r1 || r3 == r2) { + gen_program_exception(s, PGM_SPECIFICATION); + return DISAS_NORETURN; + } + /* FALL THROUGH */ case S390_FEAT_TYPE_KMCTR: if (r3 & 1 || !r3) { gen_program_exception(s, PGM_SPECIFICATION); @@ -3302,6 +3311,27 @@ static DisasJumpType op_lcbb(DisasContext *s, DisasOps *o) return DISAS_NEXT; } +static DisasJumpType op_mc(DisasContext *s, DisasOps *o) +{ +#if !defined(CONFIG_USER_ONLY) + TCGv_i32 i2; +#endif + const uint16_t monitor_class = get_field(s, i2); + + if (monitor_class & 0xff00) { + gen_program_exception(s, PGM_SPECIFICATION); + return DISAS_NORETURN; + } + +#if !defined(CONFIG_USER_ONLY) + i2 = tcg_const_i32(monitor_class); + gen_helper_monitor_call(cpu_env, o->addr1, i2); + tcg_temp_free_i32(i2); +#endif + /* Defaults to a NOP. */ + return DISAS_NEXT; +} + static DisasJumpType op_mov2(DisasContext *s, DisasOps *o) { o->out = o->in2; @@ -3518,6 +3548,12 @@ static DisasJumpType op_mul128(DisasContext *s, DisasOps *o) return DISAS_NEXT; } +static DisasJumpType op_muls128(DisasContext *s, DisasOps *o) +{ + tcg_gen_muls2_i64(o->out2, o->out, o->in1, o->in2); + return DISAS_NEXT; +} + static DisasJumpType op_meeb(DisasContext *s, DisasOps *o) { gen_helper_meeb(o->out, cpu_env, o->in1, o->in2); @@ -5120,7 +5156,7 @@ static DisasJumpType op_mpcifc(DisasContext *s, DisasOps *o) } #endif -#include "translate_vx.inc.c" +#include "translate_vx.c.inc" /* ====================================================================== */ /* The "Cc OUTput" generators. Given the generated output (and in some cases @@ -5283,6 +5319,17 @@ static void cout_tm64(DisasContext *s, DisasOps *o) gen_op_update2_cc_i64(s, CC_OP_TM_64, o->in1, o->in2); } +static void cout_muls32(DisasContext *s, DisasOps *o) +{ + gen_op_update1_cc_i64(s, CC_OP_MULS_32, o->out); +} + +static void cout_muls64(DisasContext *s, DisasOps *o) +{ + /* out contains "high" part, out2 contains "low" part of 128 bit result */ + gen_op_update2_cc_i64(s, CC_OP_MULS_64, o->out, o->out2); +} + /* ====================================================================== */ /* The "PREParation" generators. These initialize the DisasOps.OUT fields with the TCG register to which we will write. Used in combination with @@ -5338,6 +5385,12 @@ static void wout_r1(DisasContext *s, DisasOps *o) } #define SPEC_wout_r1 0 +static void wout_out2_r1(DisasContext *s, DisasOps *o) +{ + store_reg(get_field(s, r1), o->out2); +} +#define SPEC_wout_out2_r1 0 + static void wout_r1_8(DisasContext *s, DisasOps *o) { int r1 = get_field(s, r1); @@ -5542,6 +5595,13 @@ static void in1_r1p1(DisasContext *s, DisasOps *o) } #define SPEC_in1_r1p1 SPEC_r1_even +static void in1_r1p1_o(DisasContext *s, DisasOps *o) +{ + o->in1 = regs[get_field(s, r1) + 1]; + o->g_in1 = true; +} +#define SPEC_in1_r1p1_o SPEC_r1_even + static void in1_r1p1_32s(DisasContext *s, DisasOps *o) { o->in1 = tcg_temp_new_i64(); @@ -5922,6 +5982,14 @@ static void in2_m2_64(DisasContext *s, DisasOps *o) } #define SPEC_in2_m2_64 0 +static void in2_m2_64w(DisasContext *s, DisasOps *o) +{ + in2_a2(s, o); + tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s)); + gen_addi_and_wrap_i64(s, o->in2, o->in2, 0); +} +#define SPEC_in2_m2_64w 0 + #ifndef CONFIG_USER_ONLY static void in2_m2_64a(DisasContext *s, DisasOps *o) { @@ -6093,11 +6161,13 @@ enum DisasInsnEnum { #define FAC_MSA3 S390_FEAT_MSA_EXT_3 /* msa-extension-3 facility */ #define FAC_MSA4 S390_FEAT_MSA_EXT_4 /* msa-extension-4 facility */ #define FAC_MSA5 S390_FEAT_MSA_EXT_5 /* msa-extension-5 facility */ +#define FAC_MSA8 S390_FEAT_MSA_EXT_8 /* msa-extension-8 facility */ #define FAC_ECT S390_FEAT_EXTRACT_CPU_TIME #define FAC_PCI S390_FEAT_ZPCI /* z/PCI facility */ #define FAC_AIS S390_FEAT_ADAPTER_INT_SUPPRESSION #define FAC_V S390_FEAT_VECTOR /* vector facility */ #define FAC_VE S390_FEAT_VECTOR_ENH /* vector enhancements facility 1 */ +#define FAC_MIE2 S390_FEAT_MISC_INSTRUCTION_EXT2 /* miscellaneous-instruction-extensions facility 2 */ static const DisasInsn insn_info[] = { #include "insn-data.def" @@ -6300,6 +6370,7 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s) const DisasInsn *insn; DisasJumpType ret = DISAS_NEXT; DisasOps o = {}; + bool icount = false; /* Search for the insn in the table. */ insn = extract_insn(env, s); @@ -6366,6 +6437,14 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s) return DISAS_NORETURN; } } + + /* input/output is the special case for icount mode */ + if (unlikely(insn->flags & IF_IO)) { + icount = tb_cflags(s->base.tb) & CF_USE_ICOUNT; + if (icount) { + gen_io_start(); + } + } } /* Check for insn specification exceptions. */ @@ -6419,6 +6498,11 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s) tcg_temp_free_i64(o.addr1); } + /* io should be the last instruction in tb when icount is enabled */ + if (unlikely(icount && ret == DISAS_NEXT)) { + ret = DISAS_PC_STALE; + } + #ifndef CONFIG_USER_ONLY if (s->base.tb->flags & FLAG_MASK_PER) { /* An exception might be triggered, save PSW if not already done. */ diff --git a/target/s390x/translate_vx.inc.c b/target/s390x/translate_vx.c.inc similarity index 98% rename from target/s390x/translate_vx.inc.c rename to target/s390x/translate_vx.c.inc index 12347f8a03d037a6865de3f41471cd378ca8b889..eb767f5288ea7ac1936342a5ad679457b7b6602c 100644 --- a/target/s390x/translate_vx.inc.c +++ b/target/s390x/translate_vx.c.inc @@ -1825,63 +1825,6 @@ static DisasJumpType op_vpopct(DisasContext *s, DisasOps *o) return DISAS_NEXT; } -static void gen_rll_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) -{ - TCGv_i32 t0 = tcg_temp_new_i32(); - - tcg_gen_andi_i32(t0, b, 31); - tcg_gen_rotl_i32(d, a, t0); - tcg_temp_free_i32(t0); -} - -static void gen_rll_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - - tcg_gen_andi_i64(t0, b, 63); - tcg_gen_rotl_i64(d, a, t0); - tcg_temp_free_i64(t0); -} - -static DisasJumpType op_verllv(DisasContext *s, DisasOps *o) -{ - const uint8_t es = get_field(s, m4); - static const GVecGen3 g[4] = { - { .fno = gen_helper_gvec_verllv8, }, - { .fno = gen_helper_gvec_verllv16, }, - { .fni4 = gen_rll_i32, }, - { .fni8 = gen_rll_i64, }, - }; - - if (es > ES_64) { - gen_program_exception(s, PGM_SPECIFICATION); - return DISAS_NORETURN; - } - - gen_gvec_3(get_field(s, v1), get_field(s, v2), - get_field(s, v3), &g[es]); - return DISAS_NEXT; -} - -static DisasJumpType op_verll(DisasContext *s, DisasOps *o) -{ - const uint8_t es = get_field(s, m4); - static const GVecGen2s g[4] = { - { .fno = gen_helper_gvec_verll8, }, - { .fno = gen_helper_gvec_verll16, }, - { .fni4 = gen_rll_i32, }, - { .fni8 = gen_rll_i64, }, - }; - - if (es > ES_64) { - gen_program_exception(s, PGM_SPECIFICATION); - return DISAS_NORETURN; - } - gen_gvec_2s(get_field(s, v1), get_field(s, v3), o->addr1, - &g[es]); - return DISAS_NEXT; -} - static void gen_rim_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b, int32_t c) { TCGv_i32 t = tcg_temp_new_i32(); @@ -1946,6 +1889,9 @@ static DisasJumpType op_vesv(DisasContext *s, DisasOps *o) case 0x70: gen_gvec_fn_3(shlv, es, v1, v2, v3); break; + case 0x73: + gen_gvec_fn_3(rotlv, es, v1, v2, v3); + break; case 0x7a: gen_gvec_fn_3(sarv, es, v1, v2, v3); break; @@ -1977,6 +1923,9 @@ static DisasJumpType op_ves(DisasContext *s, DisasOps *o) case 0x30: gen_gvec_fn_2i(shli, es, v1, v3, d2); break; + case 0x33: + gen_gvec_fn_2i(rotli, es, v1, v3, d2); + break; case 0x3a: gen_gvec_fn_2i(sari, es, v1, v3, d2); break; @@ -1994,6 +1943,9 @@ static DisasJumpType op_ves(DisasContext *s, DisasOps *o) case 0x30: gen_gvec_fn_2s(shls, es, v1, v3, shift); break; + case 0x33: + gen_gvec_fn_2s(rotls, es, v1, v3, shift); + break; case 0x3a: gen_gvec_fn_2s(sars, es, v1, v3, shift); break; diff --git a/target/s390x/vec_int_helper.c b/target/s390x/vec_int_helper.c index 0d6bc13dd6032b1e2339dff2d4e43f1e8fc80629..5561b3ed9096d6131424b598da3f2dea3e3b7671 100644 --- a/target/s390x/vec_int_helper.c +++ b/target/s390x/vec_int_helper.c @@ -515,37 +515,6 @@ void HELPER(gvec_vpopct##BITS)(void *v1, const void *v2, uint32_t desc) \ DEF_VPOPCT(8) DEF_VPOPCT(16) -#define DEF_VERLLV(BITS) \ -void HELPER(gvec_verllv##BITS)(void *v1, const void *v2, const void *v3, \ - uint32_t desc) \ -{ \ - int i; \ - \ - for (i = 0; i < (128 / BITS); i++) { \ - const uint##BITS##_t a = s390_vec_read_element##BITS(v2, i); \ - const uint##BITS##_t b = s390_vec_read_element##BITS(v3, i); \ - \ - s390_vec_write_element##BITS(v1, i, rol##BITS(a, b)); \ - } \ -} -DEF_VERLLV(8) -DEF_VERLLV(16) - -#define DEF_VERLL(BITS) \ -void HELPER(gvec_verll##BITS)(void *v1, const void *v2, uint64_t count, \ - uint32_t desc) \ -{ \ - int i; \ - \ - for (i = 0; i < (128 / BITS); i++) { \ - const uint##BITS##_t a = s390_vec_read_element##BITS(v2, i); \ - \ - s390_vec_write_element##BITS(v1, i, rol##BITS(a, count)); \ - } \ -} -DEF_VERLL(8) -DEF_VERLL(16) - #define DEF_VERIM(BITS) \ void HELPER(gvec_verim##BITS)(void *v1, const void *v2, const void *v3, \ uint32_t desc) \ diff --git a/target/sh4/Makefile.objs b/target/sh4/Makefile.objs deleted file mode 100644 index 2c25d96e65584abf6aca9dfbf93e220eeaf38ecc..0000000000000000000000000000000000000000 --- a/target/sh4/Makefile.objs +++ /dev/null @@ -1,3 +0,0 @@ -obj-y += translate.o op_helper.o helper.o cpu.o -obj-$(CONFIG_SOFTMMU) += monitor.o -obj-y += gdbstub.o diff --git a/target/sh4/cpu-qom.h b/target/sh4/cpu-qom.h index 72a63f3fd3f89c839e9cec2c894587cabb16ab4b..8903b4b9c7c17f79ec5a81961e85139bddc5e57e 100644 --- a/target/sh4/cpu-qom.h +++ b/target/sh4/cpu-qom.h @@ -21,6 +21,7 @@ #define QEMU_SUPERH_CPU_QOM_H #include "hw/core/cpu.h" +#include "qom/object.h" #define TYPE_SUPERH_CPU "superh-cpu" @@ -28,12 +29,8 @@ #define TYPE_SH7751R_CPU SUPERH_CPU_TYPE_NAME("sh7751r") #define TYPE_SH7785_CPU SUPERH_CPU_TYPE_NAME("sh7785") -#define SUPERH_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(SuperHCPUClass, (klass), TYPE_SUPERH_CPU) -#define SUPERH_CPU(obj) \ - OBJECT_CHECK(SuperHCPU, (obj), TYPE_SUPERH_CPU) -#define SUPERH_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SuperHCPUClass, (obj), TYPE_SUPERH_CPU) +OBJECT_DECLARE_TYPE(SuperHCPU, SuperHCPUClass, + SUPERH_CPU) /** * SuperHCPUClass: @@ -45,7 +42,7 @@ * * A SuperH CPU model. */ -typedef struct SuperHCPUClass { +struct SuperHCPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ @@ -56,8 +53,7 @@ typedef struct SuperHCPUClass { uint32_t pvr; uint32_t prr; uint32_t cvr; -} SuperHCPUClass; +}; -typedef struct SuperHCPU SuperHCPU; #endif diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h index dbe58c7888f73422af15260aace6568ac9b684a2..714e3b5641339d0ac2814ddc35f8f0897bd237e8 100644 --- a/target/sh4/cpu.h +++ b/target/sh4/cpu.h @@ -160,7 +160,7 @@ typedef struct CPUSH4State { uint32_t pteh; /* page table entry high register */ uint32_t ptel; /* page table entry low register */ uint32_t ptea; /* page table entry assistance register */ - uint32_t ttb; /* tranlation table base register */ + uint32_t ttb; /* translation table base register */ uint32_t tea; /* TLB exception address register */ uint32_t tra; /* TRAPA exception register */ uint32_t expevt; /* exception event register */ diff --git a/target/sh4/meson.build b/target/sh4/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..56a57576da76b38c8cd6f293c15c376982039235 --- /dev/null +++ b/target/sh4/meson.build @@ -0,0 +1,14 @@ +sh4_ss = ss.source_set() +sh4_ss.add(files( + 'cpu.c', + 'gdbstub.c', + 'helper.c', + 'op_helper.c', + 'translate.c', +)) + +sh4_softmmu_ss = ss.source_set() +sh4_softmmu_ss.add(files('monitor.c')) + +target_arch += {'sh4': sh4_ss} +target_softmmu_arch += {'sh4': sh4_softmmu_ss} diff --git a/target/sh4/monitor.c b/target/sh4/monitor.c index 918a5ccfc6ee07ebc76102fbd661e961eb338a35..2da6a5426eb5d1b18ce3e86cae501acefc596a90 100644 --- a/target/sh4/monitor.c +++ b/target/sh4/monitor.c @@ -41,7 +41,7 @@ static void print_tlb(Monitor *mon, int idx, tlb_t *tlb) void hmp_info_tlb(Monitor *mon, const QDict *qdict) { - CPUArchState *env = mon_get_cpu_env(); + CPUArchState *env = mon_get_cpu_env(mon); int i; if (!env) { diff --git a/target/sh4/op_helper.c b/target/sh4/op_helper.c index 14c3db0f485c78f4e80125d5675e69ed29a2fbda..c0cbb95382878c3abe0df6e26cef320464a52c01 100644 --- a/target/sh4/op_helper.c +++ b/target/sh4/op_helper.c @@ -398,9 +398,11 @@ float32 helper_fsrra_FT(CPUSH4State *env, float32 t0) /* "Approximate" 1/sqrt(x) via actual computation. */ t0 = float32_sqrt(t0, &env->fp_status); t0 = float32_div(float32_one, t0, &env->fp_status); - /* Since this is supposed to be an approximation, an imprecision - exception is required. One supposes this also follows the usual - IEEE rule that other exceptions take precidence. */ + /* + * Since this is supposed to be an approximation, an imprecision + * exception is required. One supposes this also follows the usual + * IEEE rule that other exceptions take precedence. + */ if (get_float_exception_flags(&env->fp_status) == 0) { set_float_exception_flags(float_flag_inexact, &env->fp_status); } diff --git a/target/sh4/translate.c b/target/sh4/translate.c index 6192d83e8c660210d0f968d2daf863d89fcf3980..9312790623730b76b147ddfd765b5cf603379155 100644 --- a/target/sh4/translate.c +++ b/target/sh4/translate.c @@ -1542,7 +1542,6 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL | MO_UNALN); return; - break; case 0x40e9: /* movua.l @Rm+,R0 */ CHECK_SH4A /* Load non-boundary-aligned data */ @@ -1550,7 +1549,6 @@ static void _decode_opc(DisasContext * ctx) MO_TEUL | MO_UNALN); tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); return; - break; case 0x0029: /* movt Rn */ tcg_gen_mov_i32(REG(B11_8), cpu_sr_t); return; @@ -1638,7 +1636,6 @@ static void _decode_opc(DisasContext * ctx) CHECK_SH4A tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC); return; - break; case 0x4024: /* rotcl Rn */ { TCGv tmp = tcg_temp_new(); @@ -1962,9 +1959,11 @@ static void decode_gusa(DisasContext *ctx, CPUSH4State *env) NEXT_INSN; switch (ctx->opcode & 0xf00f) { case 0x6003: /* mov Rm,Rn */ - /* Here we want to recognize ld_dst being saved for later consumtion, - or for another input register being copied so that ld_dst need not - be clobbered during the operation. */ + /* + * Here we want to recognize ld_dst being saved for later consumption, + * or for another input register being copied so that ld_dst need not + * be clobbered during the operation. + */ op_dst = B11_8; mv_src = B7_4; if (op_dst == ld_dst) { diff --git a/target/sparc/Makefile.objs b/target/sparc/Makefile.objs deleted file mode 100644 index ec905698c50a7aef5b4471dcc0f45c226ac54e0f..0000000000000000000000000000000000000000 --- a/target/sparc/Makefile.objs +++ /dev/null @@ -1,7 +0,0 @@ -obj-$(CONFIG_SOFTMMU) += machine.o monitor.o -obj-y += translate.o helper.o cpu.o -obj-y += fop_helper.o cc_helper.o win_helper.o mmu_helper.o ldst_helper.o -obj-$(TARGET_SPARC) += int32_helper.o -obj-$(TARGET_SPARC64) += int64_helper.o -obj-$(TARGET_SPARC64) += vis_helper.o -obj-y += gdbstub.o diff --git a/target/sparc/cc_helper.c b/target/sparc/cc_helper.c index a410a0b98f8768bb6f0fafbe52cfbb69ff2543dd..7ad5b9b29e228835b112ac5cdb9c2df8bc9f61f4 100644 --- a/target/sparc/cc_helper.c +++ b/target/sparc/cc_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/sparc/cpu-qom.h b/target/sparc/cpu-qom.h index 8b4d33c21e50d177de59b39c08626573ad804d3f..f33949aaeec0998d7c73c292f4de29df915d6f1e 100644 --- a/target/sparc/cpu-qom.h +++ b/target/sparc/cpu-qom.h @@ -21,6 +21,7 @@ #define QEMU_SPARC_CPU_QOM_H #include "hw/core/cpu.h" +#include "qom/object.h" #ifdef TARGET_SPARC64 #define TYPE_SPARC_CPU "sparc64-cpu" @@ -28,12 +29,8 @@ #define TYPE_SPARC_CPU "sparc-cpu" #endif -#define SPARC_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(SPARCCPUClass, (klass), TYPE_SPARC_CPU) -#define SPARC_CPU(obj) \ - OBJECT_CHECK(SPARCCPU, (obj), TYPE_SPARC_CPU) -#define SPARC_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SPARCCPUClass, (obj), TYPE_SPARC_CPU) +OBJECT_DECLARE_TYPE(SPARCCPU, SPARCCPUClass, + SPARC_CPU) typedef struct sparc_def_t sparc_def_t; /** @@ -43,7 +40,7 @@ typedef struct sparc_def_t sparc_def_t; * * A SPARC CPU model. */ -typedef struct SPARCCPUClass { +struct SPARCCPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ @@ -51,8 +48,7 @@ typedef struct SPARCCPUClass { DeviceRealize parent_realize; DeviceReset parent_reset; sparc_def_t *cpu_def; -} SPARCCPUClass; +}; -typedef struct SPARCCPU SPARCCPU; #endif diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c index 3f05aba9d66c0c7af072805cd9545e8416d89b36..701e794eac1d618032abd0c062d79bdb206aaf73 100644 --- a/target/sparc/cpu.c +++ b/target/sparc/cpu.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -801,12 +801,9 @@ static void sparc_set_nwindows(Object *obj, Visitor *v, const char *name, const int64_t min = MIN_NWINDOWS; const int64_t max = MAX_NWINDOWS; SPARCCPU *cpu = SPARC_CPU(obj); - Error *err = NULL; int64_t value; - visit_type_int(v, name, &value, &err); - if (err) { - error_propagate(errp, err); + if (!visit_type_int(v, name, &value, errp)) { return; } diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index e6dd3fc3131d63c625ec9c63aaedc976ae5bab9a..f54fa9b9595380f4746a8b2223bbc6bf939f81bf 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/sparc/gdbstub.c b/target/sparc/gdbstub.c index 78dc8dcc980124f9859317324672cd3d19e9f3c6..5d1e808e8c64bcb3c0894a250a04d73d74f14054 100644 --- a/target/sparc/gdbstub.c +++ b/target/sparc/gdbstub.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/sparc/helper.c b/target/sparc/helper.c index 07d87efa4eebdb5d21306e6b23cc67cd6ea78151..c7bcaa3a2031bde6801e6746bc2c19bd865149ba 100644 --- a/target/sparc/helper.c +++ b/target/sparc/helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/sparc/int32_helper.c b/target/sparc/int32_helper.c index 813b47dbb2917ea682bccf40a102376cf9d5a5d4..817a463a179e6797b47b52dfc6c030831ef2077c 100644 --- a/target/sparc/int32_helper.c +++ b/target/sparc/int32_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -23,9 +23,7 @@ #include "exec/log.h" #include "sysemu/runstate.h" -#define DEBUG_PCALL -#ifdef DEBUG_PCALL static const char * const excp_names[0x80] = { [TT_TFAULT] = "Instruction Access Fault", [TT_ILL_INSN] = "Illegal Instruction", @@ -52,13 +50,19 @@ static const char * const excp_names[0x80] = { [TT_EXTINT | 0xd] = "External Interrupt 13", [TT_EXTINT | 0xe] = "External Interrupt 14", [TT_EXTINT | 0xf] = "External Interrupt 15", - [TT_TOVF] = "Tag Overflow", [TT_CODE_ACCESS] = "Instruction Access Error", [TT_DATA_ACCESS] = "Data Access Error", [TT_DIV_ZERO] = "Division By Zero", [TT_NCP_INSN] = "Coprocessor Disabled", }; -#endif + +static const char *excp_name_str(int32_t exception_index) +{ + if (exception_index < 0 || exception_index >= ARRAY_SIZE(excp_names)) { + return "Unknown"; + } + return excp_names[exception_index]; +} void sparc_cpu_do_interrupt(CPUState *cs) { @@ -71,7 +75,6 @@ void sparc_cpu_do_interrupt(CPUState *cs) cpu_get_psr(env); } -#ifdef DEBUG_PCALL if (qemu_loglevel_mask(CPU_LOG_INT)) { static int count; const char *name; @@ -81,10 +84,7 @@ void sparc_cpu_do_interrupt(CPUState *cs) } else if (intno >= 0x80) { name = "Trap Instruction"; } else { - name = excp_names[intno]; - if (!name) { - name = "Unknown"; - } + name = excp_name_str(intno); } qemu_log("%6d: %s (v=%02x)\n", count, name, intno); @@ -104,15 +104,15 @@ void sparc_cpu_do_interrupt(CPUState *cs) #endif count++; } -#endif #if !defined(CONFIG_USER_ONLY) if (env->psret == 0) { if (cs->exception_index == 0x80 && env->def.features & CPU_FEATURE_TA0_SHUTDOWN) { qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); } else { - cpu_abort(cs, "Trap 0x%02x while interrupts disabled, Error state", - cs->exception_index); + cpu_abort(cs, "Trap 0x%02x (%s) while interrupts disabled, " + "Error state", + cs->exception_index, excp_name_str(cs->exception_index)); } return; } diff --git a/target/sparc/int64_helper.c b/target/sparc/int64_helper.c index f3e7f32de612e436e2ae262686da91b236a6719a..ba95bf228cc48da70ea0829591ad5702275c2446 100644 --- a/target/sparc/int64_helper.c +++ b/target/sparc/int64_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c index e91cfdecd3726757d3967fa2ac3100ff46850f53..22327d7d72533d4c67ee8923473af251fc9e28d9 100644 --- a/target/sparc/ldst_helper.c +++ b/target/sparc/ldst_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/sparc/meson.build b/target/sparc/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..a3638b9503f4ed66a86f9a0d286e2b7b2be55dbb --- /dev/null +++ b/target/sparc/meson.build @@ -0,0 +1,23 @@ +sparc_ss = ss.source_set() +sparc_ss.add(files( + 'cc_helper.c', + 'cpu.c', + 'fop_helper.c', + 'gdbstub.c', + 'helper.c', + 'ldst_helper.c', + 'mmu_helper.c', + 'translate.c', + 'win_helper.c', +)) +sparc_ss.add(when: 'TARGET_SPARC', if_true: files('int32_helper.c')) +sparc_ss.add(when: 'TARGET_SPARC64', if_true: files('int64_helper.c', 'vis_helper.c')) + +sparc_softmmu_ss = ss.source_set() +sparc_softmmu_ss.add(files( + 'machine.c', + 'monitor.c', +)) + +target_arch += {'sparc': sparc_ss} +target_softmmu_arch += {'sparc': sparc_softmmu_ss} diff --git a/target/sparc/mmu_helper.c b/target/sparc/mmu_helper.c index afbfba7b7e00a4bc3bdc0b17b82990d781415a9f..a44473a1c7ca1dc3018c5d1aa66e8b7ebee9d942 100644 --- a/target/sparc/mmu_helper.c +++ b/target/sparc/mmu_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/sparc/monitor.c b/target/sparc/monitor.c index a7ea287cbccc4827f1acc6c041299ae6938029fb..318413686aa72986ad5a3239cab3c517d93dd1f1 100644 --- a/target/sparc/monitor.c +++ b/target/sparc/monitor.c @@ -30,7 +30,7 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict) { - CPUArchState *env1 = mon_get_cpu_env(); + CPUArchState *env1 = mon_get_cpu_env(mon); if (!env1) { monitor_printf(mon, "No CPU available\n"); @@ -40,17 +40,19 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict) } #ifndef TARGET_SPARC64 -static target_long monitor_get_psr (const struct MonitorDef *md, int val) +static target_long monitor_get_psr(Monitor *mon, const struct MonitorDef *md, + int val) { - CPUArchState *env = mon_get_cpu_env(); + CPUArchState *env = mon_get_cpu_env(mon); return cpu_get_psr(env); } #endif -static target_long monitor_get_reg(const struct MonitorDef *md, int val) +static target_long monitor_get_reg(Monitor *mon, const struct MonitorDef *md, + int val) { - CPUArchState *env = mon_get_cpu_env(); + CPUArchState *env = mon_get_cpu_env(mon); return env->regwptr[val]; } diff --git a/target/sparc/trace.h b/target/sparc/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..3b2f5a8e295766476a3f531db46f1fa1cbd8a9b1 --- /dev/null +++ b/target/sparc/trace.h @@ -0,0 +1 @@ +#include "trace/trace-target_sparc.h" diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 9416a551cf461f8b5cc9f3da44d424825e2ba2b4..30c73f8d2e71f4f48ec2cbb57e8f71f0dd7dd4e1 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -7,7 +7,7 @@ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -3663,6 +3663,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) #endif gen_store_gpr(dc, rd, cpu_tmp0); break; +#endif +#if defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY) } else if (xop == 0x2b) { /* rdtbr / V9 flushw */ #ifdef TARGET_SPARC64 gen_helper_flushw(cpu_env); diff --git a/target/sparc/vis_helper.c b/target/sparc/vis_helper.c index 8a9b763d0b5b0639b38c9d24e799c99b42db1903..f917e5992dc7114937008ab2dc886db8540adf21 100644 --- a/target/sparc/vis_helper.c +++ b/target/sparc/vis_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/sparc/win_helper.c b/target/sparc/win_helper.c index 8290a21142d4ce0292418aa707b1161a37f2c6fd..5b57892a10e2b5100de2457b68a4b6c4bb167ae3 100644 --- a/target/sparc/win_helper.c +++ b/target/sparc/win_helper.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/tilegx/Makefile.objs b/target/tilegx/Makefile.objs deleted file mode 100644 index 0db778f407bd48e04f54fc45deac69968df02122..0000000000000000000000000000000000000000 --- a/target/tilegx/Makefile.objs +++ /dev/null @@ -1 +0,0 @@ -obj-y += cpu.o translate.o helper.o simd_helper.o diff --git a/target/tilegx/cpu.h b/target/tilegx/cpu.h index 193b6bbccba37ebe5aed155fc0536a37749c239d..7d8e44d12e4714a68443e585eca74bc0bb4242b1 100644 --- a/target/tilegx/cpu.h +++ b/target/tilegx/cpu.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -21,6 +21,7 @@ #define TILEGX_CPU_H #include "exec/cpu-defs.h" +#include "qom/object.h" /* TILE-Gx common register alias */ #define TILEGX_R_RE 0 /* 0 register, for function/syscall return value */ @@ -98,12 +99,8 @@ typedef struct CPUTLGState { #define TYPE_TILEGX_CPU "tilegx-cpu" -#define TILEGX_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(TileGXCPUClass, (klass), TYPE_TILEGX_CPU) -#define TILEGX_CPU(obj) \ - OBJECT_CHECK(TileGXCPU, (obj), TYPE_TILEGX_CPU) -#define TILEGX_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(TileGXCPUClass, (obj), TYPE_TILEGX_CPU) +OBJECT_DECLARE_TYPE(TileGXCPU, TileGXCPUClass, + TILEGX_CPU) /** * TileGXCPUClass: @@ -112,14 +109,14 @@ typedef struct CPUTLGState { * * A Tile-Gx CPU model. */ -typedef struct TileGXCPUClass { +struct TileGXCPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ DeviceRealize parent_realize; DeviceReset parent_reset; -} TileGXCPUClass; +}; /** * TileGXCPU: @@ -127,14 +124,14 @@ typedef struct TileGXCPUClass { * * A Tile-GX CPU. */ -typedef struct TileGXCPU { +struct TileGXCPU { /*< private >*/ CPUState parent_obj; /*< public >*/ CPUNegativeOffsetState neg; CPUTLGState env; -} TileGXCPU; +}; /* TILE-Gx memory attributes */ diff --git a/target/tilegx/meson.build b/target/tilegx/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..678590439c65201471d6f503e1e060f1c91d518c --- /dev/null +++ b/target/tilegx/meson.build @@ -0,0 +1,13 @@ +tilegx_ss = ss.source_set() +tilegx_ss.add(files( + 'cpu.c', + 'helper.c', + 'simd_helper.c', + 'translate.c', +)) +tilegx_ss.add(zlib) + +tilegx_softmmu_ss = ss.source_set() + +target_arch += {'tilegx': tilegx_ss} +target_softmmu_arch += {'tilegx': tilegx_softmmu_ss} diff --git a/target/tricore/Makefile.objs b/target/tricore/Makefile.objs deleted file mode 100644 index 7a056707181fb627bc393d4664d5da23602b2d47..0000000000000000000000000000000000000000 --- a/target/tricore/Makefile.objs +++ /dev/null @@ -1 +0,0 @@ -obj-y += translate.o helper.o cpu.o op_helper.o fpu_helper.o diff --git a/target/tricore/cpu-qom.h b/target/tricore/cpu-qom.h index cd819e6f240c0a4a4f3208fcfc2741f43064bc5b..59bfd01bbcfe285c3d7daebd43a5187028551816 100644 --- a/target/tricore/cpu-qom.h +++ b/target/tricore/cpu-qom.h @@ -19,26 +19,22 @@ #define QEMU_TRICORE_CPU_QOM_H #include "hw/core/cpu.h" +#include "qom/object.h" #define TYPE_TRICORE_CPU "tricore-cpu" -#define TRICORE_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(TriCoreCPUClass, (klass), TYPE_TRICORE_CPU) -#define TRICORE_CPU(obj) \ - OBJECT_CHECK(TriCoreCPU, (obj), TYPE_TRICORE_CPU) -#define TRICORE_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(TriCoreCPUClass, (obj), TYPE_TRICORE_CPU) +OBJECT_DECLARE_TYPE(TriCoreCPU, TriCoreCPUClass, + TRICORE_CPU) -typedef struct TriCoreCPUClass { +struct TriCoreCPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ DeviceRealize parent_realize; DeviceReset parent_reset; -} TriCoreCPUClass; +}; -typedef struct TriCoreCPU TriCoreCPU; #endif /* QEMU_TRICORE_CPU_QOM_H */ diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c index 743b404a95a06aaa0535fde5dd0691f2c84e74ca..2f2e5b029fe36c41e65ebcceb2b2570186f9575c 100644 --- a/target/tricore/cpu.c +++ b/target/tricore/cpu.c @@ -23,17 +23,14 @@ #include "exec/exec-all.h" #include "qemu/error-report.h" -static hwaddr tricore_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr, - MemTxAttrs *attrs) +static inline void set_feature(CPUTriCoreState *env, int feature) { - error_report("function cpu_get_phys_page_attrs_debug not " - "implemented, aborting"); - return -1; + env->features |= 1ULL << feature; } -static inline void set_feature(CPUTriCoreState *env, int feature) +static gchar *tricore_gdb_arch_name(CPUState *cs) { - env->features |= 1ULL << feature; + return g_strdup("tricore"); } static void tricore_cpu_set_pc(CPUState *cs, vaddr value) @@ -158,10 +155,15 @@ static void tricore_cpu_class_init(ObjectClass *c, void *data) cc->class_by_name = tricore_cpu_class_by_name; cc->has_work = tricore_cpu_has_work; + cc->gdb_read_register = tricore_cpu_gdb_read_register; + cc->gdb_write_register = tricore_cpu_gdb_write_register; + cc->gdb_num_core_regs = 44; + cc->gdb_arch_name = tricore_gdb_arch_name; + cc->dump_state = tricore_cpu_dump_state; cc->set_pc = tricore_cpu_set_pc; cc->synchronize_from_tb = tricore_cpu_synchronize_from_tb; - cc->get_phys_page_attrs_debug = tricore_cpu_get_phys_page_attrs_debug; + cc->get_phys_page_debug = tricore_cpu_get_phys_page_debug; cc->tcg_initialize = tricore_tcg_init; cc->tlb_fill = tricore_cpu_tlb_fill; } diff --git a/target/tricore/cpu.h b/target/tricore/cpu.h index 8c014fad076411cfc0f08a87e50454d581d834ae..b82349d1b1023f465724136a23e4b0a04ba55329 100644 --- a/target/tricore/cpu.h +++ b/target/tricore/cpu.h @@ -353,6 +353,8 @@ enum { uint32_t psw_read(CPUTriCoreState *env); void psw_write(CPUTriCoreState *env, uint32_t val); +int tricore_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n); +int tricore_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n); void fpu_set_state(CPUTriCoreState *env); diff --git a/target/tricore/gdbstub.c b/target/tricore/gdbstub.c new file mode 100644 index 0000000000000000000000000000000000000000..3ce55abb8e3bba9074bbccae008d2329aba29734 --- /dev/null +++ b/target/tricore/gdbstub.c @@ -0,0 +1,139 @@ +/* + * TriCore gdb server stub + * + * Copyright (c) 2019 Bastian Koppelmann, Paderborn University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "exec/gdbstub.h" + + +#define LCX_REGNUM 32 +#define FCX_REGNUM 33 +#define PCXI_REGNUM 34 +#define TRICORE_PSW_REGNUM 35 +#define TRICORE_PC_REGNUM 36 +#define ICR_REGNUM 37 +#define ISP_REGNUM 38 +#define BTV_REGNUM 39 +#define BIV_REGNUM 40 +#define SYSCON_REGNUM 41 +#define PMUCON0_REGNUM 42 +#define DMUCON_REGNUM 43 + +static uint32_t tricore_cpu_gdb_read_csfr(CPUTriCoreState *env, int n) +{ + switch (n) { + case LCX_REGNUM: + return env->LCX; + case FCX_REGNUM: + return env->FCX; + case PCXI_REGNUM: + return env->PCXI; + case TRICORE_PSW_REGNUM: + return psw_read(env); + case TRICORE_PC_REGNUM: + return env->PC; + case ICR_REGNUM: + return env->ICR; + case ISP_REGNUM: + return env->ISP; + case BTV_REGNUM: + return env->BTV; + case BIV_REGNUM: + return env->BIV; + case SYSCON_REGNUM: + return env->SYSCON; + case PMUCON0_REGNUM: + return 0; /* PMUCON0 */ + case DMUCON_REGNUM: + return 0; /* DMUCON0 */ + default: + return 0; + } +} + +static void tricore_cpu_gdb_write_csfr(CPUTriCoreState *env, int n, + uint32_t val) +{ + switch (n) { + case LCX_REGNUM: + env->LCX = val; + break; + case FCX_REGNUM: + env->FCX = val; + break; + case PCXI_REGNUM: + env->PCXI = val; + break; + case TRICORE_PSW_REGNUM: + psw_write(env, val); + break; + case TRICORE_PC_REGNUM: + env->PC = val; + break; + case ICR_REGNUM: + env->ICR = val; + break; + case ISP_REGNUM: + env->ISP = val; + break; + case BTV_REGNUM: + env->BTV = val; + break; + case BIV_REGNUM: + env->BIV = val; + break; + case SYSCON_REGNUM: + env->SYSCON = val; + break; + } +} + + +int tricore_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) +{ + TriCoreCPU *cpu = TRICORE_CPU(cs); + CPUTriCoreState *env = &cpu->env; + + if (n < 16) { /* data registers */ + return gdb_get_reg32(mem_buf, env->gpr_d[n]); + } else if (n < 32) { /* address registers */ + return gdb_get_reg32(mem_buf, env->gpr_a[n - 16]); + } else { /* csfr */ + return gdb_get_reg32(mem_buf, tricore_cpu_gdb_read_csfr(env, n)); + } + return 0; +} + +int tricore_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) +{ + TriCoreCPU *cpu = TRICORE_CPU(cs); + CPUTriCoreState *env = &cpu->env; + uint32_t tmp; + + tmp = ldl_p(mem_buf); + + if (n < 16) { /* data registers */ + env->gpr_d[n] = tmp; + } else if (n < 32) { /* address registers */ + env->gpr_d[n - 16] = tmp; + } else { + tricore_cpu_gdb_write_csfr(env, n, tmp); + } + return 4; +} diff --git a/target/tricore/helper.c b/target/tricore/helper.c index d5db7b2c03f46c8e684c63ae977aba6f5d619d89..771529326305c32dc1ad990e1c8e9c947d9ba3e8 100644 --- a/target/tricore/helper.c +++ b/target/tricore/helper.c @@ -42,6 +42,19 @@ static int get_physical_address(CPUTriCoreState *env, hwaddr *physical, return ret; } + +hwaddr tricore_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) +{ + TriCoreCPU *cpu = TRICORE_CPU(cs); + hwaddr phys_addr; + int prot; + int mmu_idx = cpu_mmu_index(&cpu->env, false); + + if (get_physical_address(&cpu->env, &phys_addr, &prot, addr, 0, mmu_idx)) { + return -1; + } + return phys_addr; +} #endif /* TODO: Add exeption support*/ diff --git a/target/tricore/meson.build b/target/tricore/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..0ccc8295179e24c0cca435384df006ce7bbe276b --- /dev/null +++ b/target/tricore/meson.build @@ -0,0 +1,15 @@ +tricore_ss = ss.source_set() +tricore_ss.add(files( + 'cpu.c', + 'fpu_helper.c', + 'helper.c', + 'op_helper.c', + 'translate.c', + 'gdbstub.c', +)) +tricore_ss.add(zlib) + +tricore_softmmu_ss = ss.source_set() + +target_arch += {'tricore': tricore_ss} +target_softmmu_arch += {'tricore': tricore_softmmu_ss} diff --git a/target/tricore/translate.c b/target/tricore/translate.c index 609d75ae8a6b91e7dbd479af05f8fc92eac99c01..7752630ac14c6ce151dc4f6ecf42ffa868c3f7e5 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -66,14 +66,19 @@ static const char *regnames_d[] = { typedef struct DisasContext { DisasContextBase base; - CPUTriCoreState *env; target_ulong pc_succ_insn; uint32_t opcode; /* Routine used to access memory */ int mem_idx; uint32_t hflags, saved_hflags; + uint64_t features; } DisasContext; +static int has_feature(DisasContext *ctx, int feature) +{ + return (ctx->features & (1ULL << feature)) != 0; +} + enum { MODE_LL = 0, MODE_LU = 1, @@ -370,7 +375,7 @@ static void gen_swapmsk(DisasContext *ctx, int reg, TCGv ea) These makros also specify in which ISA version the csfr was introduced. */ #define R(ADDRESS, REG, FEATURE) \ case ADDRESS: \ - if (tricore_feature(ctx->env, FEATURE)) { \ + if (has_feature(ctx, FEATURE)) { \ tcg_gen_ld_tl(ret, cpu_env, offsetof(CPUTriCoreState, REG)); \ } \ break; @@ -395,7 +400,7 @@ static inline void gen_mfcr(DisasContext *ctx, TCGv ret, int32_t offset) since no execption occurs */ #define A(ADDRESS, REG, FEATURE) R(ADDRESS, REG, FEATURE) \ case ADDRESS: \ - if (tricore_feature(ctx->env, FEATURE)) { \ + if (has_feature(ctx, FEATURE)) { \ tcg_gen_st_tl(r1, cpu_env, offsetof(CPUTriCoreState, REG)); \ } \ break; @@ -3158,7 +3163,7 @@ gen_dvinit_b(DisasContext *ctx, TCGv rl, TCGv rh, TCGv r1, TCGv r2) { TCGv_i64 ret = tcg_temp_new_i64(); - if (!tricore_feature(ctx->env, TRICORE_FEATURE_131)) { + if (!has_feature(ctx, TRICORE_FEATURE_131)) { gen_helper_dvinit_b_13(ret, cpu_env, r1, r2); } else { gen_helper_dvinit_b_131(ret, cpu_env, r1, r2); @@ -3173,7 +3178,7 @@ gen_dvinit_h(DisasContext *ctx, TCGv rl, TCGv rh, TCGv r1, TCGv r2) { TCGv_i64 ret = tcg_temp_new_i64(); - if (!tricore_feature(ctx->env, TRICORE_FEATURE_131)) { + if (!has_feature(ctx, TRICORE_FEATURE_131)) { gen_helper_dvinit_h_13(ret, cpu_env, r1, r2); } else { gen_helper_dvinit_h_131(ret, cpu_env, r1, r2); @@ -3233,6 +3238,14 @@ static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest) #endif } +static void generate_qemu_excp(DisasContext *ctx, int excp) +{ + TCGv_i32 tmp = tcg_const_i32(excp); + gen_helper_qemu_excp(cpu_env, tmp); + ctx->base.is_jmp = DISAS_NORETURN; + tcg_temp_free(tmp); +} + static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) { if (use_goto_tb(ctx, dest)) { @@ -3242,7 +3255,7 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) } else { gen_save_pc(dest); if (ctx->base.singlestep_enabled) { - /* raise exception debug */ + generate_qemu_excp(ctx, EXCP_DEBUG); } tcg_gen_exit_tb(NULL, 0); } @@ -3261,15 +3274,6 @@ static void generate_trap(DisasContext *ctx, int class, int tin) tcg_temp_free(tintemp); } -static void generate_qemu_excp(DisasContext *ctx, int excp) -{ - TCGv_i32 tmp = tcg_const_i32(excp); - gen_save_pc(ctx->base.pc_next); - gen_helper_qemu_excp(cpu_env, tmp); - ctx->base.is_jmp = DISAS_NORETURN; - tcg_temp_free(tmp); -} - static inline void gen_branch_cond(DisasContext *ctx, TCGCond cond, TCGv r1, TCGv r2, int16_t address) { @@ -3656,7 +3660,7 @@ static void decode_src_opc(DisasContext *ctx, int op1) tcg_gen_movi_tl(cpu_gpr_a[r1], const4); break; case OPC1_16_SRC_MOV_E: - if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) { + if (has_feature(ctx, TRICORE_FEATURE_16)) { tcg_gen_movi_tl(cpu_gpr_d[r1], const4); tcg_gen_sari_tl(cpu_gpr_d[r1+1], cpu_gpr_d[r1], 31); } else { @@ -4107,7 +4111,7 @@ static void decode_16Bit_opc(DisasContext *ctx) break; case OPC1_16_SBC_JEQ2: case OPC1_16_SBC_JNE2: - if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) { + if (has_feature(ctx, TRICORE_FEATURE_16)) { address = MASK_OP_SBC_DISP4(ctx->opcode); const16 = MASK_OP_SBC_CONST4_SEXT(ctx->opcode); gen_compute_branch(ctx, op1, 0, 0, const16, address); @@ -4125,7 +4129,7 @@ static void decode_16Bit_opc(DisasContext *ctx) /* SBR-format */ case OPC1_16_SBR_JEQ2: case OPC1_16_SBR_JNE2: - if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) { + if (has_feature(ctx, TRICORE_FEATURE_16)) { r1 = MASK_OP_SBR_S2(ctx->opcode); address = MASK_OP_SBR_DISP4(ctx->opcode); gen_compute_branch(ctx, op1, r1, 0, 0, address); @@ -4705,13 +4709,13 @@ static void decode_bo_addrmode_post_pre_base(DisasContext *ctx) break; case OPC2_32_BO_CACHEI_WI_SHORTOFF: case OPC2_32_BO_CACHEI_W_SHORTOFF: - if (!tricore_feature(ctx->env, TRICORE_FEATURE_131)) { + if (!has_feature(ctx, TRICORE_FEATURE_131)) { generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); } break; case OPC2_32_BO_CACHEI_W_POSTINC: case OPC2_32_BO_CACHEI_WI_POSTINC: - if (tricore_feature(ctx->env, TRICORE_FEATURE_131)) { + if (has_feature(ctx, TRICORE_FEATURE_131)) { tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r2], off10); } else { generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); @@ -4719,7 +4723,7 @@ static void decode_bo_addrmode_post_pre_base(DisasContext *ctx) break; case OPC2_32_BO_CACHEI_W_PREINC: case OPC2_32_BO_CACHEI_WI_PREINC: - if (tricore_feature(ctx->env, TRICORE_FEATURE_131)) { + if (has_feature(ctx, TRICORE_FEATURE_131)) { tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r2], off10); } else { generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); @@ -5373,7 +5377,7 @@ static void decode_bol_opc(DisasContext *ctx, int32_t op1) tcg_gen_addi_tl(cpu_gpr_a[r1], cpu_gpr_a[r2], address); break; case OPC1_32_BOL_ST_A_LONGOFF: - if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) { + if (has_feature(ctx, TRICORE_FEATURE_16)) { gen_offset_st(ctx, cpu_gpr_a[r1], cpu_gpr_a[r2], address, MO_LEUL); } else { generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); @@ -5383,42 +5387,42 @@ static void decode_bol_opc(DisasContext *ctx, int32_t op1) gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LEUL); break; case OPC1_32_BOL_LD_B_LONGOFF: - if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) { + if (has_feature(ctx, TRICORE_FEATURE_16)) { gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_SB); } else { generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); } break; case OPC1_32_BOL_LD_BU_LONGOFF: - if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) { + if (has_feature(ctx, TRICORE_FEATURE_16)) { gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_UB); } else { generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); } break; case OPC1_32_BOL_LD_H_LONGOFF: - if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) { + if (has_feature(ctx, TRICORE_FEATURE_16)) { gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LESW); } else { generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); } break; case OPC1_32_BOL_LD_HU_LONGOFF: - if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) { + if (has_feature(ctx, TRICORE_FEATURE_16)) { gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LEUW); } else { generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); } break; case OPC1_32_BOL_ST_B_LONGOFF: - if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) { + if (has_feature(ctx, TRICORE_FEATURE_16)) { gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_SB); } else { generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); } break; case OPC1_32_BOL_ST_H_LONGOFF: - if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) { + if (has_feature(ctx, TRICORE_FEATURE_16)) { gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LESW); } else { generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); @@ -6023,7 +6027,7 @@ static void decode_rlc_opc(DisasContext *ctx, tcg_gen_movi_tl(cpu_gpr_d[r2], const16); break; case OPC1_32_RLC_MOV_64: - if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) { + if (has_feature(ctx, TRICORE_FEATURE_16)) { CHECK_REG_PAIR(r2); tcg_gen_movi_tl(cpu_gpr_d[r2], const16); tcg_gen_movi_tl(cpu_gpr_d[r2+1], const16 >> 15); @@ -6249,7 +6253,7 @@ static void decode_rr_accumulator(DisasContext *ctx) tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r2]); break; case OPC2_32_RR_MOV_64: - if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) { + if (has_feature(ctx, TRICORE_FEATURE_16)) { temp = tcg_temp_new(); CHECK_REG_PAIR(r3); @@ -6263,7 +6267,7 @@ static void decode_rr_accumulator(DisasContext *ctx) } break; case OPC2_32_RR_MOVS_64: - if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) { + if (has_feature(ctx, TRICORE_FEATURE_16)) { CHECK_REG_PAIR(r3); tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r2]); tcg_gen_sari_tl(cpu_gpr_d[r3 + 1], cpu_gpr_d[r2], 31); @@ -6603,7 +6607,7 @@ static void decode_rr_divide(DisasContext *ctx) tcg_gen_shri_tl(temp3, cpu_gpr_d[r1], 8); /* reset av */ tcg_gen_movi_tl(cpu_PSW_AV, 0); - if (!tricore_feature(ctx->env, TRICORE_FEATURE_131)) { + if (!has_feature(ctx, TRICORE_FEATURE_131)) { /* overflow = (abs(D[r3+1]) >= abs(D[r2])) */ tcg_gen_abs_tl(temp, temp3); tcg_gen_abs_tl(temp2, cpu_gpr_d[r2]); @@ -6636,7 +6640,7 @@ static void decode_rr_divide(DisasContext *ctx) tcg_gen_shri_tl(temp3, cpu_gpr_d[r1], 16); /* reset av */ tcg_gen_movi_tl(cpu_PSW_AV, 0); - if (!tricore_feature(ctx->env, TRICORE_FEATURE_131)) { + if (!has_feature(ctx, TRICORE_FEATURE_131)) { /* overflow = (abs(D[r3+1]) >= abs(D[r2])) */ tcg_gen_abs_tl(temp, temp3); tcg_gen_abs_tl(temp2, cpu_gpr_d[r2]); @@ -6699,14 +6703,14 @@ static void decode_rr_divide(DisasContext *ctx) gen_unpack(cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]); break; case OPC2_32_RR_CRC32: - if (tricore_feature(ctx->env, TRICORE_FEATURE_161)) { + if (has_feature(ctx, TRICORE_FEATURE_161)) { gen_helper_crc32(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); } else { generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); } break; case OPC2_32_RR_DIV: - if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) { + if (has_feature(ctx, TRICORE_FEATURE_16)) { GEN_HELPER_RR(divide, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2]); } else { @@ -6714,7 +6718,7 @@ static void decode_rr_divide(DisasContext *ctx) } break; case OPC2_32_RR_DIV_U: - if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) { + if (has_feature(ctx, TRICORE_FEATURE_16)) { GEN_HELPER_RR(divide_u, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2]); } else { @@ -8412,7 +8416,7 @@ static void decode_sys_interrupts(DisasContext *ctx) gen_helper_svlcx(cpu_env); break; case OPC2_32_SYS_RESTORE: - if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) { + if (has_feature(ctx, TRICORE_FEATURE_16)) { if ((ctx->hflags & TRICORE_HFLAG_KUU) == TRICORE_HFLAG_SM || (ctx->hflags & TRICORE_HFLAG_KUU) == TRICORE_HFLAG_UM1) { tcg_gen_deposit_tl(cpu_ICR, cpu_ICR, cpu_gpr_d[r1], 8, 1); @@ -8793,6 +8797,7 @@ static void tricore_tr_init_disas_context(DisasContextBase *dcbase, CPUTriCoreState *env = cs->env_ptr; ctx->mem_idx = cpu_mmu_index(env, false); ctx->hflags = (uint32_t)ctx->base.tb->flags; + ctx->features = env->features; } static void tricore_tr_tb_start(DisasContextBase *db, CPUState *cpu) diff --git a/target/unicore32/Makefile.objs b/target/unicore32/Makefile.objs deleted file mode 100644 index 35d8bf530d87326ca766fba0804f0dfab8ace6f2..0000000000000000000000000000000000000000 --- a/target/unicore32/Makefile.objs +++ /dev/null @@ -1,8 +0,0 @@ -obj-y += translate.o op_helper.o helper.o cpu.o -obj-y += ucf64_helper.o - -obj-$(CONFIG_SOFTMMU) += softmmu.o - -# Huh? Uses curses directly instead of using ui/console.h interfaces ... -helper.o-cflags := $(CURSES_CFLAGS) -helper.o-libs := $(CURSES_LIBS) diff --git a/target/unicore32/cpu-qom.h b/target/unicore32/cpu-qom.h index 7dd04515cb728dc68fa704f867c9ed8c2a4561a5..43621e7479206d3560a346a5249320f8b4784aa3 100644 --- a/target/unicore32/cpu-qom.h +++ b/target/unicore32/cpu-qom.h @@ -12,15 +12,12 @@ #define QEMU_UC32_CPU_QOM_H #include "hw/core/cpu.h" +#include "qom/object.h" #define TYPE_UNICORE32_CPU "unicore32-cpu" -#define UNICORE32_CPU_CLASS(klass) \ - OBJECT_CLASS_CHECK(UniCore32CPUClass, (klass), TYPE_UNICORE32_CPU) -#define UNICORE32_CPU(obj) \ - OBJECT_CHECK(UniCore32CPU, (obj), TYPE_UNICORE32_CPU) -#define UNICORE32_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(UniCore32CPUClass, (obj), TYPE_UNICORE32_CPU) +OBJECT_DECLARE_TYPE(UniCore32CPU, UniCore32CPUClass, + UNICORE32_CPU) /** * UniCore32CPUClass: @@ -28,14 +25,13 @@ * * A UniCore32 CPU model. */ -typedef struct UniCore32CPUClass { +struct UniCore32CPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ DeviceRealize parent_realize; -} UniCore32CPUClass; +}; -typedef struct UniCore32CPU UniCore32CPU; #endif diff --git a/target/unicore32/helper.c b/target/unicore32/helper.c index 7d538e2144ddbb9013a734ad57a621709a69468c..54c26871feab098808f14a6332acb2dd9020c969 100644 --- a/target/unicore32/helper.c +++ b/target/unicore32/helper.c @@ -10,14 +10,11 @@ */ #include "qemu/osdep.h" +#include "qemu/log.h" #include "cpu.h" #include "exec/exec-all.h" -#include "exec/gdbstub.h" #include "exec/helper-proto.h" -#include "qemu/host-utils.h" -#ifndef CONFIG_USER_ONLY -#include "ui/console.h" -#endif +#include "hw/semihosting/console.h" #undef DEBUG_UC32 @@ -108,8 +105,9 @@ void helper_cp0_set(CPUUniCore32State *env, uint32_t val, uint32_t creg, } return; unrecognized: - DPRINTF("Wrong register (%d) or wrong operation (%d) in cp0_set!\n", - creg, cop); + qemu_log_mask(LOG_GUEST_ERROR, + "Wrong register (%d) or wrong operation (%d) in cp0_set!\n", + creg, cop); } uint32_t helper_cp0_get(CPUUniCore32State *env, uint32_t creg, uint32_t cop) @@ -155,63 +153,19 @@ uint32_t helper_cp0_get(CPUUniCore32State *env, uint32_t creg, uint32_t cop) } break; } - DPRINTF("Wrong register (%d) or wrong operation (%d) in cp0_set!\n", - creg, cop); + qemu_log_mask(LOG_GUEST_ERROR, + "Wrong register (%d) or wrong operation (%d) in cp0_set!\n", + creg, cop); return 0; } -#ifdef CONFIG_CURSES - -/* KEY_EVENT is defined in wincon.h and in curses.h. Avoid redefinition. */ -#undef KEY_EVENT -#include -#undef KEY_EVENT - -/* - * FIXME: - * 1. curses windows will be blank when switching back - * 2. backspace is not handled yet - */ -static void putc_on_screen(unsigned char ch) +void helper_cp1_putc(target_ulong regval) { - static WINDOW *localwin; - static int init; - - if (!init) { - /* Assume 80 * 30 screen to minimize the implementation */ - localwin = newwin(30, 80, 0, 0); - scrollok(localwin, TRUE); - init = TRUE; - } + const char c = regval; - if (isprint(ch)) { - wprintw(localwin, "%c", ch); - } else { - switch (ch) { - case '\n': - wprintw(localwin, "%c", ch); - break; - case '\r': - /* If '\r' is put before '\n', the curses window will destroy the - * last print line. And meanwhile, '\n' implifies '\r' inside. */ - break; - default: /* Not handled, so just print it hex code */ - wprintw(localwin, "-- 0x%x --", ch); - } - } - - wrefresh(localwin); -} -#else -#define putc_on_screen(c) do { } while (0) -#endif - -void helper_cp1_putc(target_ulong x) -{ - putc_on_screen((unsigned char)x); /* Output to screen */ - DPRINTF("%c", x); /* Output to stdout */ + qemu_semihosting_log_out(&c, sizeof(c)); } -#endif +#endif /* !CONFIG_USER_ONLY */ bool uc32_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { diff --git a/target/unicore32/meson.build b/target/unicore32/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..0fa78772ebcb109d2832512a7d2c56c35c72435e --- /dev/null +++ b/target/unicore32/meson.build @@ -0,0 +1,14 @@ +unicore32_ss = ss.source_set() +unicore32_ss.add(files( + 'cpu.c', + 'helper.c', + 'op_helper.c', + 'translate.c', + 'ucf64_helper.c', +), curses) + +unicore32_softmmu_ss = ss.source_set() +unicore32_softmmu_ss.add(files('softmmu.c')) + +target_arch += {'unicore32': unicore32_ss} +target_softmmu_arch += {'unicore32': unicore32_softmmu_ss} diff --git a/target/xtensa/Makefile.objs b/target/xtensa/Makefile.objs deleted file mode 100644 index c7e7fe6063844ae104d63ffef62fd6dad428e378..0000000000000000000000000000000000000000 --- a/target/xtensa/Makefile.objs +++ /dev/null @@ -1,16 +0,0 @@ -obj-y += core-dc232b.o -obj-y += core-dc233c.o -obj-y += core-de212.o -obj-y += core-fsf.o -obj-y += core-sample_controller.o -obj-y += core-test_kc705_be.o -obj-y += core-test_mmuhifi_c3.o -obj-$(CONFIG_SOFTMMU) += monitor.o xtensa-semi.o -obj-y += xtensa-isa.o -obj-y += translate.o op_helper.o helper.o cpu.o -obj-$(CONFIG_SOFTMMU) += dbg_helper.o -obj-y += exc_helper.o -obj-y += fpu_helper.o -obj-y += gdbstub.o -obj-$(CONFIG_SOFTMMU) += mmu_helper.o -obj-y += win_helper.o diff --git a/target/xtensa/core-dc232b.c b/target/xtensa/core-dc232b.c index 7851bcb63687d995edff12fa059c6a9c5923d850..c982d09c24b770893537260eb1d90766b62ee54c 100644 --- a/target/xtensa/core-dc232b.c +++ b/target/xtensa/core-dc232b.c @@ -35,13 +35,13 @@ #include "overlay_tool.h" #define xtensa_modules xtensa_modules_dc232b -#include "core-dc232b/xtensa-modules.inc.c" +#include "core-dc232b/xtensa-modules.c.inc" static XtensaConfig dc232b __attribute__((unused)) = { .name = "dc232b", .gdb_regmap = { .reg = { -#include "core-dc232b/gdb-config.inc.c" +#include "core-dc232b/gdb-config.c.inc" } }, .isa_internal = &xtensa_modules, diff --git a/target/xtensa/core-dc232b/gdb-config.inc.c b/target/xtensa/core-dc232b/gdb-config.c.inc similarity index 100% rename from target/xtensa/core-dc232b/gdb-config.inc.c rename to target/xtensa/core-dc232b/gdb-config.c.inc diff --git a/target/xtensa/core-dc232b/xtensa-modules.inc.c b/target/xtensa/core-dc232b/xtensa-modules.c.inc similarity index 100% rename from target/xtensa/core-dc232b/xtensa-modules.inc.c rename to target/xtensa/core-dc232b/xtensa-modules.c.inc diff --git a/target/xtensa/core-dc233c.c b/target/xtensa/core-dc233c.c index f8204f704529739eea25ed11b1f1bced2f35fcd3..595ab9a90fade96e1e3a0847516ad468dda87537 100644 --- a/target/xtensa/core-dc233c.c +++ b/target/xtensa/core-dc233c.c @@ -34,13 +34,13 @@ #include "overlay_tool.h" #define xtensa_modules xtensa_modules_dc233c -#include "core-dc233c/xtensa-modules.inc.c" +#include "core-dc233c/xtensa-modules.c.inc" static XtensaConfig dc233c __attribute__((unused)) = { .name = "dc233c", .gdb_regmap = { .reg = { -#include "core-dc233c/gdb-config.inc.c" +#include "core-dc233c/gdb-config.c.inc" } }, .isa_internal = &xtensa_modules, diff --git a/target/xtensa/core-dc233c/gdb-config.inc.c b/target/xtensa/core-dc233c/gdb-config.c.inc similarity index 100% rename from target/xtensa/core-dc233c/gdb-config.inc.c rename to target/xtensa/core-dc233c/gdb-config.c.inc diff --git a/target/xtensa/core-dc233c/xtensa-modules.inc.c b/target/xtensa/core-dc233c/xtensa-modules.c.inc similarity index 100% rename from target/xtensa/core-dc233c/xtensa-modules.inc.c rename to target/xtensa/core-dc233c/xtensa-modules.c.inc diff --git a/target/xtensa/core-de212.c b/target/xtensa/core-de212.c index a061158f6e3c50356b1b8c8f3ffb45153c69451e..50c995ba790b0846c399a70cf4f9a453b4d6b653 100644 --- a/target/xtensa/core-de212.c +++ b/target/xtensa/core-de212.c @@ -34,13 +34,13 @@ #include "overlay_tool.h" #define xtensa_modules xtensa_modules_de212 -#include "core-de212/xtensa-modules.inc.c" +#include "core-de212/xtensa-modules.c.inc" static XtensaConfig de212 __attribute__((unused)) = { .name = "de212", .gdb_regmap = { .reg = { -#include "core-de212/gdb-config.inc.c" +#include "core-de212/gdb-config.c.inc" } }, .isa_internal = &xtensa_modules, diff --git a/target/xtensa/core-de212/gdb-config.inc.c b/target/xtensa/core-de212/gdb-config.c.inc similarity index 100% rename from target/xtensa/core-de212/gdb-config.inc.c rename to target/xtensa/core-de212/gdb-config.c.inc diff --git a/target/xtensa/core-de212/xtensa-modules.inc.c b/target/xtensa/core-de212/xtensa-modules.c.inc similarity index 100% rename from target/xtensa/core-de212/xtensa-modules.inc.c rename to target/xtensa/core-de212/xtensa-modules.c.inc diff --git a/target/xtensa/core-de233_fpu.c b/target/xtensa/core-de233_fpu.c new file mode 100644 index 0000000000000000000000000000000000000000..c7cbeb1b483438bcc6d1f69fa77434f9a51d596a --- /dev/null +++ b/target/xtensa/core-de233_fpu.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020, Max Filippov, Open Source and Linux Lab. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Open Source and Linux Lab nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/gdbstub.h" +#include "qemu-common.h" +#include "qemu/host-utils.h" + +#include "core-de233_fpu/core-isa.h" +#include "core-de233_fpu/core-matmap.h" +#include "overlay_tool.h" + +#define xtensa_modules xtensa_modules_de233_fpu +#include "core-de233_fpu/xtensa-modules.c.inc" + +static XtensaConfig de233_fpu __attribute__((unused)) = { + .name = "de233_fpu", + .gdb_regmap = { + .reg = { +#include "core-de233_fpu/gdb-config.c.inc" + } + }, + .isa_internal = &xtensa_modules, + .clock_freq_khz = 40000, + .opcode_translators = (const XtensaOpcodeTranslators *[]){ + &xtensa_core_opcodes, + &xtensa_fpu_opcodes, + NULL, + }, + DEFAULT_SECTIONS +}; + +REGISTER_CORE(de233_fpu) diff --git a/target/xtensa/core-de233_fpu/core-isa.h b/target/xtensa/core-de233_fpu/core-isa.h new file mode 100644 index 0000000000000000000000000000000000000000..f125619e8de594b0fbcb398ae18b486eaa0ad8a8 --- /dev/null +++ b/target/xtensa/core-de233_fpu/core-isa.h @@ -0,0 +1,727 @@ +/* + * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa + * processor CORE configuration + * + * See , which includes this file, for more details. + */ + +/* Xtensa processor core configuration information. + + Copyright (c) 1999-2020 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef XTENSA_CORE_CONFIGURATION_H_ +#define XTENSA_CORE_CONFIGURATION_H_ + +//depot/dev/Homewood/Xtensa/SWConfig/hal/core-common.h.tph#24 - edit change 444323 (text+ko) + +/**************************************************************************** + Parameters Useful for Any Code, USER or PRIVILEGED + ****************************************************************************/ + +/* + * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is + * configured, and a value of 0 otherwise. These macros are always defined. + */ + + +/*---------------------------------------------------------------------- + ISA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ +#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ +#define XCHAL_NUM_AREGS 32 /* num of physical addr regs */ +#define XCHAL_NUM_AREGS_LOG2 5 /* log2(XCHAL_NUM_AREGS) */ +#define XCHAL_MAX_INSTRUCTION_SIZE 3 /* max instr bytes (3..8) */ +#define XCHAL_HAVE_DEBUG 1 /* debug option */ +#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ +#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ +#define XCHAL_LOOP_BUFFER_SIZE 0 /* zero-ov. loop instr buffer size */ +#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ +#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ +#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ +#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ +#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ +#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ +#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ +#define XCHAL_HAVE_MUL32_HIGH 0 /* MULUH/MULSH instructions */ +#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ +#define XCHAL_HAVE_L32R 1 /* L32R instruction */ +#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ +#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ +#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ +#define XCHAL_HAVE_EXCLUSIVE 0 /* L32EX/S32EX instructions */ +#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ +#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ +#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ +#define XCHAL_HAVE_ABS 1 /* ABS instruction */ +#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ +#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ +#define XCHAL_HAVE_SPECULATION 0 /* speculation */ +#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ +#define XCHAL_NUM_CONTEXTS 1 /* */ +#define XCHAL_NUM_MISC_REGS 2 /* num of scratch regs (0..4) */ +#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ +#define XCHAL_HAVE_PRID 1 /* processor ID register */ +#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ +#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ +#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ +#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ +#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ +#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ +#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ +#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ +#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ +#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ +#define XCHAL_CP_MAXCFG 8 /* max allowed cp id plus one */ +#define XCHAL_HAVE_MAC16 1 /* MAC16 package */ +#define XCHAL_HAVE_LX 1 /* LX core */ +#define XCHAL_HAVE_NX 0 /* NX core (starting RH) */ + +#define XCHAL_HAVE_SUPERGATHER 0 /* SuperGather */ + +#define XCHAL_HAVE_FUSION 0 /* Fusion*/ +#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ +#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ +#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ +#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ +#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ +#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ +#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ +#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ +#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ +#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ +#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5 0 /* HiFi5 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5_NN_MAC 0 /* HiFi5 Audio Engine NN-MAC option */ +#define XCHAL_HAVE_HIFI5_VFPU 0 /* HiFi5 Audio Engine Single-Precision VFPU option */ +#define XCHAL_HAVE_HIFI5_HP_VFPU 0 /* HiFi5 Audio Engine Half-Precision VFPU option */ +#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4_VFPU 0 /* HiFi4 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3 0 /* HiFi3 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3_VFPU 0 /* HiFi3 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3Z 0 /* HiFi3Z Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3Z_VFPU 0 /* HiFi3Z Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ +#define XCHAL_HAVE_HIFI_MINI 0 + + + +#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ +#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_USER_SPFPU 0 /* user SP floating-point pkg */ +#define XCHAL_HAVE_FP 1 /* single prec floating point */ +#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ +#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ +#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ +#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ +#define XCHAL_HAVE_DFP 1 /* double precision FP pkg */ +#define XCHAL_HAVE_DFP_DIV 1 /* DFP with DIV instructions */ +#define XCHAL_HAVE_DFP_RECIP 1 /* DFP with RECIP instructions*/ +#define XCHAL_HAVE_DFP_SQRT 1 /* DFP with SQRT instructions */ +#define XCHAL_HAVE_DFP_RSQRT 1 /* DFP with RSQRT instructions*/ +#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ +#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ + +#define XCHAL_HAVE_DFPU_SINGLE_ONLY 0 /* DFPU Coprocessor, single precision only */ +#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 1 /* DFPU Coprocessor, single and double precision */ +#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ +#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ + +#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ +#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ +#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ +#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ +#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ +#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ + +#define XCHAL_HAVE_FUSIONJ 0 /* FusionJ */ +#define XCHAL_HAVE_FUSIONJ6 0 /* FusionJ6 */ +#define XCHAL_HAVE_FUSIONJ_SP_VFPU 0 /* sp_vfpu option on FusionJ */ +#define XCHAL_HAVE_FUSIONJ_DP_VFPU 0 /* dp_vfpu option on FusionJ */ +#define XCHAL_FUSIONJ_SIMD32 0 /* simd32 for FusionJ */ + +#define XCHAL_HAVE_PDX 0 /* PDX-LX */ +#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ +#define XCHAL_HAVE_PDX4 0 /* PDX4-LX */ +#define XCHAL_HAVE_PDX8 0 /* PDX8-LX */ +#define XCHAL_HAVE_PDX16 0 /* PDX16-LX */ +#define XCHAL_HAVE_PDXNX 0 /* PDX-NX */ + +#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ +#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ +#define XCHAL_HAVE_BALL 0 +#define XCHAL_HAVE_BALLAP 0 +#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ +#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ +#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ +#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ +#define XCHAL_HAVE_CONNX_B10 0 /* ConnX B10 pkg*/ +#define XCHAL_HAVE_CONNX_B20 0 /* ConnX B20 pkg*/ +#define XCHAL_HAVE_CONNX_B_SP_VFPU 0 /* Single-precision Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_SPX_VFPU 0 /* Single-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_HPX_VFPU 0 /* Half-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_32B_MAC 0 /* 32-bit vector MAC (real and complex), FIR & FFT option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_VITERBI 0 /* Viterbi option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_TURBO 0 /* Turbo option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_LDPC 0 /* LDPC option on ConnX B10 & B20 */ +#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ +#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ +#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ +#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ +#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ +#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ +#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ +#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ +#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ +#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ +#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ + +#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ +#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ +#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, Q6 or Q7 */ +#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ +#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ +#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6/Q6/Q7 */ +#define XCHAL_HAVE_VISION_SP_VFPU_2XFMAC 0 /* sp_vfpu_2xfma option on Vision Q7 */ +#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6/Q6 */ +#define XCHAL_HAVE_VISION_HP_VFPU_2XFMAC 0 /* hp_vfpu_2xfma option on Vision Q7 */ + +#define XCHAL_HAVE_VISIONC 0 /* Vision C */ + +#define XCHAL_HAVE_XNNE 0 /* XNNE */ + +/*---------------------------------------------------------------------- + MISC + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_LOADSTORE_UNITS 1 /* load/store units */ +#define XCHAL_NUM_WRITEBUFFER_ENTRIES 8 /* size of write buffer */ +#define XCHAL_INST_FETCH_WIDTH 4 /* instr-fetch width in bytes */ +#define XCHAL_DATA_WIDTH 8 /* data width in bytes */ +#define XCHAL_DATA_PIPE_DELAY 1 /* d-side pipeline delay + (1 = 5-stage, 2 = 7-stage) */ +#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ +#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ +/* In T1050, applies to selected core load and store instructions (see ISA): */ +#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ +#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ +#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */ +#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/ + +#define XCHAL_UNIFIED_LOADSTORE 0 + +#define XCHAL_SW_VERSION 1403000 /* sw version of this header */ +#define XCHAL_SW_VERSION_MAJOR 14000 /* major ver# of sw */ +#define XCHAL_SW_VERSION_MINOR 3 /* minor ver# of sw */ +#define XCHAL_SW_VERSION_MICRO 0 /* micro ver# of sw */ +#define XCHAL_SW_MINOR_VERSION 1403000 /* with zeroed micro */ +#define XCHAL_SW_MICRO_VERSION 1403000 + +#define XCHAL_CORE_ID "DE_233L_FPU" /* alphanum core name + (CoreID) set in the Xtensa + Processor Generator */ + +#define XCHAL_BUILD_UNIQUE_ID 0x000872E0 /* 22-bit sw build ID */ + +/* + * These definitions describe the hardware targeted by this software. + */ +#define XCHAL_HW_CONFIGID0 0xC1039286 /* ConfigID hi 32 bits*/ +#define XCHAL_HW_CONFIGID1 0x28C872E0 /* ConfigID lo 32 bits*/ +#define XCHAL_HW_VERSION_NAME "LX7.1.3" /* full version name */ +#define XCHAL_HW_VERSION_MAJOR 2810 /* major ver# of targeted hw */ +#define XCHAL_HW_VERSION_MINOR 3 /* minor ver# of targeted hw */ +#define XCHAL_HW_VERSION_MICRO 0 /* subdot ver# of targeted hw */ +#define XCHAL_HW_VERSION 281030 /* major*100+(major<2810 ? minor : minor*10+micro) */ +#define XCHAL_HW_REL_LX7 1 +#define XCHAL_HW_REL_LX7_1 1 +#define XCHAL_HW_REL_LX7_1_3 1 +#define XCHAL_HW_CONFIGID_RELIABLE 1 +/* If software targets a *range* of hardware versions, these are the bounds: */ +#define XCHAL_HW_MIN_VERSION_MAJOR 2810 /* major v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MINOR 3 /* minor v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MICRO 0 /* micro v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION 281030 /* earliest targeted hw */ +#define XCHAL_HW_MAX_VERSION_MAJOR 2810 /* major v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MINOR 3 /* minor v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MICRO 0 /* micro v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION 281030 /* latest targeted hw */ + +/* Config is enabled for functional safety: */ +#define XCHAL_HAVE_FUNC_SAFETY 0 + +#define XCHAL_HAVE_APB 0 + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_ICACHE_LINESIZE 32 /* I-cache line size in bytes */ +#define XCHAL_DCACHE_LINESIZE 32 /* D-cache line size in bytes */ +#define XCHAL_ICACHE_LINEWIDTH 5 /* log2(I line size in bytes) */ +#define XCHAL_DCACHE_LINEWIDTH 5 /* log2(D line size in bytes) */ + +#define XCHAL_ICACHE_SIZE 16384 /* I-cache size in bytes or 0 */ +#define XCHAL_ICACHE_SIZE_LOG2 14 +#define XCHAL_DCACHE_SIZE 16384 /* D-cache size in bytes or 0 */ +#define XCHAL_DCACHE_SIZE_LOG2 14 + +#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ +#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ + +#define XCHAL_HAVE_PREFETCH 0 /* PREFCTL register */ +#define XCHAL_HAVE_PREFETCH_L1 0 /* prefetch to L1 cache */ +#define XCHAL_PREFETCH_CASTOUT_LINES 0 /* dcache pref. castout bufsz */ +#define XCHAL_PREFETCH_ENTRIES 0 /* cache prefetch entries */ +#define XCHAL_PREFETCH_BLOCK_ENTRIES 0 /* prefetch block streams */ +#define XCHAL_HAVE_CACHE_BLOCKOPS 0 /* block prefetch for caches */ +#define XCHAL_HAVE_CME_DOWNGRADES 0 +#define XCHAL_HAVE_ICACHE_TEST 1 /* Icache test instructions */ +#define XCHAL_HAVE_DCACHE_TEST 1 /* Dcache test instructions */ +#define XCHAL_HAVE_ICACHE_DYN_WAYS 0 /* Icache dynamic way support */ +#define XCHAL_HAVE_DCACHE_DYN_WAYS 0 /* Dcache dynamic way support */ +#define XCHAL_HAVE_ICACHE_DYN_ENABLE 0 /* Icache enabled via MEMCTL */ +#define XCHAL_HAVE_DCACHE_DYN_ENABLE 0 /* Dcache enabled via MEMCTL */ + +#define XCHAL_L1SCACHE_SIZE 0 +#define XCHAL_L1SCACHE_SIZE_LOG2 0 +#define XCHAL_L1SCACHE_WAYS 1 +#define XCHAL_L1SCACHE_WAYS_LOG2 0 +#define XCHAL_L1SCACHE_ACCESS_SIZE 0 +#define XCHAL_L1SCACHE_BANKS 1 + +#define XCHAL_HAVE_L2 0 /* NX L2 cache controller */ + +/* Number of cores in cluster */ +#if XCHAL_HAVE_L2 +#define XCHAL_NUM_CORES_IN_CLUSTER XCHAL_L2CC_NUM_CORES_LOG2 +#else +#define XCHAL_NUM_CORES_IN_CLUSTER 0 +#endif + +/* PRID_ID macros are for internal use only ... subject to removal */ +#define PRID_ID_SHIFT 0 +#define PRID_ID_BITS 4 +#define PRID_ID_MASK 0x0000000F + +/* This one is a form of caching, though not architecturally visible: */ +#define XCHAL_HAVE_BRANCH_PREDICTION 0 /* branch [target] prediction */ + + + + +/**************************************************************************** + Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ + +#define XCHAL_HAVE_AXI 0 /* AXI bus */ +#define XCHAL_HAVE_AXI_ECC 0 /* ECC on AXI bus */ +#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ + +#define XCHAL_HAVE_PIF_WR_RESP 0 /* pif write response */ +#define XCHAL_HAVE_PIF_REQ_ATTR 0 /* pif attribute */ + +/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ + +/* Number of cache sets in log2(lines per way): */ +#define XCHAL_ICACHE_SETWIDTH 7 +#define XCHAL_DCACHE_SETWIDTH 7 + +/* Cache set associativity (number of ways): */ +#define XCHAL_ICACHE_WAYS 4 +#define XCHAL_ICACHE_WAYS_LOG2 2 +#define XCHAL_DCACHE_WAYS 4 +#define XCHAL_DCACHE_WAYS_LOG2 2 + +/* Cache features: */ +#define XCHAL_ICACHE_LINE_LOCKABLE 1 +#define XCHAL_DCACHE_LINE_LOCKABLE 1 +#define XCHAL_ICACHE_ECC_PARITY 0 +#define XCHAL_DCACHE_ECC_PARITY 0 +#define XCHAL_ICACHE_ECC_WIDTH 4 +#define XCHAL_DCACHE_ECC_WIDTH 1 + +/* Cache access size in bytes (affects operation of SICW instruction): */ +#define XCHAL_ICACHE_ACCESS_SIZE 4 +#define XCHAL_DCACHE_ACCESS_SIZE 8 + +#define XCHAL_DCACHE_BANKS 1 /* number of banks */ + +/* The number of Cache lines associated with a single cache tag */ +#define XCHAL_DCACHE_LINES_PER_TAG_LOG2 0 + +/* Number of encoded cache attr bits (see for decoded bits): */ +#define XCHAL_CA_BITS 4 + + +/*---------------------------------------------------------------------- + INTERNAL I/D RAM/ROMs and XLMI + ----------------------------------------------------------------------*/ +#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ +#define XCHAL_NUM_INSTRAM 0 /* number of core instr. RAMs */ +#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ +#define XCHAL_NUM_DATARAM 0 /* number of core data RAMs */ +#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ +#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ +#define XCHAL_HAVE_IRAMCFG 0 /* IRAMxCFG register present */ +#define XCHAL_HAVE_DRAMCFG 0 /* DRAMxCFG register present */ + + +#define XCHAL_HAVE_IDMA 0 + + +#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ + +/*---------------------------------------------------------------------- + INTERRUPTS and TIMERS + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ +#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ +#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ +#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ +#define XCHAL_NUM_INTERRUPTS 22 /* number of interrupts */ +#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ +#define XCHAL_NUM_EXTINTERRUPTS 17 /* num of external interrupts */ +#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels + (not including level zero) */ + + +#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ +#define XCHAL_EXCM_LEVEL 3 /* level masked by PS.EXCM */ + /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ + +/* Masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL1_MASK 0x001F80FF +#define XCHAL_INTLEVEL2_MASK 0x00000100 +#define XCHAL_INTLEVEL3_MASK 0x00200E00 +#define XCHAL_INTLEVEL4_MASK 0x00001000 +#define XCHAL_INTLEVEL5_MASK 0x00002000 +#define XCHAL_INTLEVEL6_MASK 0x00000000 +#define XCHAL_INTLEVEL7_MASK 0x00004000 + +/* Masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x001F80FF +#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x001F81FF +#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x003F8FFF +#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x003F9FFF +#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x003FBFFF +#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x003FBFFF +#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x003FFFFF + +/* Level of each interrupt: */ +#define XCHAL_INT0_LEVEL 1 +#define XCHAL_INT1_LEVEL 1 +#define XCHAL_INT2_LEVEL 1 +#define XCHAL_INT3_LEVEL 1 +#define XCHAL_INT4_LEVEL 1 +#define XCHAL_INT5_LEVEL 1 +#define XCHAL_INT6_LEVEL 1 +#define XCHAL_INT7_LEVEL 1 +#define XCHAL_INT8_LEVEL 2 +#define XCHAL_INT9_LEVEL 3 +#define XCHAL_INT10_LEVEL 3 +#define XCHAL_INT11_LEVEL 3 +#define XCHAL_INT12_LEVEL 4 +#define XCHAL_INT13_LEVEL 5 +#define XCHAL_INT14_LEVEL 7 +#define XCHAL_INT15_LEVEL 1 +#define XCHAL_INT16_LEVEL 1 +#define XCHAL_INT17_LEVEL 1 +#define XCHAL_INT18_LEVEL 1 +#define XCHAL_INT19_LEVEL 1 +#define XCHAL_INT20_LEVEL 1 +#define XCHAL_INT21_LEVEL 3 +#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ +#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ +#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with + EXCSAVE/EPS/EPC_n, RFI n) */ + +/* Type of each interrupt: */ +#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT6_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT7_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT10_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT11_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT12_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT13_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT14_TYPE XTHAL_INTTYPE_NMI +#define XCHAL_INT15_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT16_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT17_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT18_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT19_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT20_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT21_TYPE XTHAL_INTTYPE_EXTERN_EDGE + +/* Masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFC00000 +#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x0000133F +#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x003F8000 +#define XCHAL_INTTYPE_MASK_NMI 0x00004000 +#define XCHAL_INTTYPE_MASK_SOFTWARE 0x00000880 +#define XCHAL_INTTYPE_MASK_TIMER 0x00002440 +#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000 +#define XCHAL_INTTYPE_MASK_DBG_REQUEST 0x00000000 +#define XCHAL_INTTYPE_MASK_BREAKIN 0x00000000 +#define XCHAL_INTTYPE_MASK_TRAX 0x00000000 +#define XCHAL_INTTYPE_MASK_PROFILING 0x00000000 +#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000000 +#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_STATUS 0x00000000 +#define XCHAL_INTTYPE_MASK_COR_ECC_ERR 0x00000000 + +/* Interrupt numbers assigned to specific interrupt sources: */ +#define XCHAL_TIMER0_INTERRUPT 6 /* CCOMPARE0 */ +#define XCHAL_TIMER1_INTERRUPT 10 /* CCOMPARE1 */ +#define XCHAL_TIMER2_INTERRUPT 13 /* CCOMPARE2 */ +#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_NMI_INTERRUPT 14 /* non-maskable interrupt */ + +/* Interrupt numbers for levels at which only one interrupt is configured: */ +#define XCHAL_INTLEVEL2_NUM 8 +#define XCHAL_INTLEVEL4_NUM 12 +#define XCHAL_INTLEVEL5_NUM 13 +#define XCHAL_INTLEVEL7_NUM 14 +/* (There are many interrupts each at level(s) 1, 3.) */ + + +/* + * External interrupt mapping. + * These macros describe how Xtensa processor interrupt numbers + * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) + * map to external BInterrupt pins, for those interrupts + * configured as external (level-triggered, edge-triggered, or NMI). + * See the Xtensa processor databook for more details. + */ + +/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ +#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */ +#define XCHAL_EXTINT1_NUM 1 /* (intlevel 1) */ +#define XCHAL_EXTINT2_NUM 2 /* (intlevel 1) */ +#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */ +#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */ +#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */ +#define XCHAL_EXTINT6_NUM 8 /* (intlevel 2) */ +#define XCHAL_EXTINT7_NUM 9 /* (intlevel 3) */ +#define XCHAL_EXTINT8_NUM 12 /* (intlevel 4) */ +#define XCHAL_EXTINT9_NUM 14 /* (intlevel 7) */ +#define XCHAL_EXTINT10_NUM 15 /* (intlevel 1) */ +#define XCHAL_EXTINT11_NUM 16 /* (intlevel 1) */ +#define XCHAL_EXTINT12_NUM 17 /* (intlevel 1) */ +#define XCHAL_EXTINT13_NUM 18 /* (intlevel 1) */ +#define XCHAL_EXTINT14_NUM 19 /* (intlevel 1) */ +#define XCHAL_EXTINT15_NUM 20 /* (intlevel 1) */ +#define XCHAL_EXTINT16_NUM 21 /* (intlevel 3) */ +/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ +#define XCHAL_INT0_EXTNUM 0 /* (intlevel 1) */ +#define XCHAL_INT1_EXTNUM 1 /* (intlevel 1) */ +#define XCHAL_INT2_EXTNUM 2 /* (intlevel 1) */ +#define XCHAL_INT3_EXTNUM 3 /* (intlevel 1) */ +#define XCHAL_INT4_EXTNUM 4 /* (intlevel 1) */ +#define XCHAL_INT5_EXTNUM 5 /* (intlevel 1) */ +#define XCHAL_INT8_EXTNUM 6 /* (intlevel 2) */ +#define XCHAL_INT9_EXTNUM 7 /* (intlevel 3) */ +#define XCHAL_INT12_EXTNUM 8 /* (intlevel 4) */ +#define XCHAL_INT14_EXTNUM 9 /* (intlevel 7) */ +#define XCHAL_INT15_EXTNUM 10 /* (intlevel 1) */ +#define XCHAL_INT16_EXTNUM 11 /* (intlevel 1) */ +#define XCHAL_INT17_EXTNUM 12 /* (intlevel 1) */ +#define XCHAL_INT18_EXTNUM 13 /* (intlevel 1) */ +#define XCHAL_INT19_EXTNUM 14 /* (intlevel 1) */ +#define XCHAL_INT20_EXTNUM 15 /* (intlevel 1) */ +#define XCHAL_INT21_EXTNUM 16 /* (intlevel 3) */ + +#define XCHAL_HAVE_ISB 0 /* No ISB */ +#define XCHAL_ISB_VADDR 0 /* N/A */ +#define XCHAL_HAVE_ITB 0 /* No ITB */ +#define XCHAL_ITB_VADDR 0 /* N/A */ + +#define XCHAL_HAVE_KSL 0 /* Kernel Stack Limit */ +#define XCHAL_HAVE_ISL 0 /* Interrupt Stack Limit */ +#define XCHAL_HAVE_PSL 0 /* Pageable Stack Limit */ + + +/*---------------------------------------------------------------------- + EXCEPTIONS and VECTORS + ----------------------------------------------------------------------*/ + +#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture + number: 1 == XEA1 (until T1050) + 2 == XEA2 (T1040 onwards) + 3 == XEA3 (LX8/NX/SX onwards) + 0 == XEAX (extern) or TX */ +#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ +#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ +#define XCHAL_HAVE_XEA3 0 /* Exception Architecture 3 */ +#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ +#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ +#define XCHAL_HAVE_IMPRECISE_EXCEPTIONS 0 /* imprecise exception option */ +#define XCHAL_EXCCAUSE_NUM 64 /* Number of exceptions */ +#define XCHAL_HAVE_HALT 0 /* halt architecture option */ +#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ +#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ +#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ +#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ +#define XCHAL_VECBASE_RESET_VADDR 0x00002000 /* VECBASE reset value */ +#define XCHAL_VECBASE_RESET_PADDR 0x00002000 +#define XCHAL_RESET_VECBASE_OVERLAP 0 /* UNUSED */ + +#define XCHAL_RESET_VECTOR0_VADDR 0xFE000000 +#define XCHAL_RESET_VECTOR0_PADDR 0xFE000000 +#define XCHAL_RESET_VECTOR1_VADDR 0x00001000 +#define XCHAL_RESET_VECTOR1_PADDR 0x00001000 +#define XCHAL_RESET_VECTOR_VADDR XCHAL_RESET_VECTOR0_VADDR +#define XCHAL_RESET_VECTOR_PADDR XCHAL_RESET_VECTOR0_PADDR +#define XCHAL_USER_VECOFS 0x00000340 +#define XCHAL_USER_VECTOR_VADDR 0x00002340 +#define XCHAL_USER_VECTOR_PADDR 0x00002340 +#define XCHAL_KERNEL_VECOFS 0x00000300 +#define XCHAL_KERNEL_VECTOR_VADDR 0x00002300 +#define XCHAL_KERNEL_VECTOR_PADDR 0x00002300 +#define XCHAL_DOUBLEEXC_VECOFS 0x000003C0 +#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x000023C0 +#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x000023C0 +#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 +#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 +#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 +#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 +#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 +#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 +#define XCHAL_WINDOW_VECTORS_VADDR 0x00002000 +#define XCHAL_WINDOW_VECTORS_PADDR 0x00002000 +#define XCHAL_INTLEVEL2_VECOFS 0x00000180 +#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x00002180 +#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x00002180 +#define XCHAL_INTLEVEL3_VECOFS 0x000001C0 +#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x000021C0 +#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x000021C0 +#define XCHAL_INTLEVEL4_VECOFS 0x00000200 +#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x00002200 +#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x00002200 +#define XCHAL_INTLEVEL5_VECOFS 0x00000240 +#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x00002240 +#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x00002240 +#define XCHAL_INTLEVEL6_VECOFS 0x00000280 +#define XCHAL_INTLEVEL6_VECTOR_VADDR 0x00002280 +#define XCHAL_INTLEVEL6_VECTOR_PADDR 0x00002280 +#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS +#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR +#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR +#define XCHAL_NMI_VECOFS 0x000002C0 +#define XCHAL_NMI_VECTOR_VADDR 0x000022C0 +#define XCHAL_NMI_VECTOR_PADDR 0x000022C0 +#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS +#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR +#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR + + +/*---------------------------------------------------------------------- + DEBUG MODULE + ----------------------------------------------------------------------*/ + +/* Misc */ +#define XCHAL_HAVE_DEBUG_ERI 0 /* ERI to debug module */ +#define XCHAL_HAVE_DEBUG_APB 0 /* APB to debug module */ +#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ + +/* On-Chip Debug (OCD) */ +#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ +#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ +#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ +#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ +#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ + +/* TRAX (in core) */ +#define XCHAL_HAVE_TRAX 0 /* TRAX in debug module */ +#define XCHAL_TRAX_MEM_SIZE 0 /* TRAX memory size in bytes */ +#define XCHAL_TRAX_MEM_SHAREABLE 0 /* start/end regs; ready sig. */ +#define XCHAL_TRAX_ATB_WIDTH 0 /* ATB width (bits), 0=no ATB */ +#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ + +/* Perf counters */ +#define XCHAL_NUM_PERF_COUNTERS 0 /* performance counters */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* See core-matmap.h header file for more details. */ + +#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ +#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ +#define XCHAL_SPANNING_WAY 6 /* TLB spanning way number */ +#define XCHAL_HAVE_IDENTITY_MAP 0 /* vaddr == paddr always */ +#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ +#define XCHAL_HAVE_MIMIC_CACHEATTR 0 /* region protection */ +#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ +#define XCHAL_HAVE_PTP_MMU 1 /* full MMU (with page table + [autorefill] and protection) + usable for an MMU-based OS */ + +/* If none of the above last 5 are set, it's a custom TLB configuration. */ +#define XCHAL_ITLB_ARF_ENTRIES_LOG2 2 /* log2(autorefill way size) */ +#define XCHAL_DTLB_ARF_ENTRIES_LOG2 2 /* log2(autorefill way size) */ + +#define XCHAL_MMU_ASID_BITS 8 /* number of bits in ASIDs */ +#define XCHAL_MMU_RINGS 4 /* number of rings (1..4) */ +#define XCHAL_MMU_RING_BITS 2 /* num of bits in RING field */ + +/*---------------------------------------------------------------------- + MPU + ----------------------------------------------------------------------*/ +#define XCHAL_HAVE_MPU 0 +#define XCHAL_MPU_ENTRIES 0 + +#define XCHAL_MPU_ALIGN_REQ 1 /* MPU requires alignment of entries to background map */ +#define XCHAL_MPU_BACKGROUND_ENTRIES 0 /* number of entries in bg map*/ +#define XCHAL_MPU_BG_CACHEADRDIS 0 /* default CACHEADRDIS for bg */ + +#define XCHAL_MPU_ALIGN_BITS 0 +#define XCHAL_MPU_ALIGN 0 + +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + + +#endif /* XTENSA_CORE_CONFIGURATION_H_ */ + diff --git a/target/xtensa/core-de233_fpu/core-matmap.h b/target/xtensa/core-de233_fpu/core-matmap.h new file mode 100644 index 0000000000000000000000000000000000000000..cca51c7af1b50b5915fda3ab8320e355cd139843 --- /dev/null +++ b/target/xtensa/core-de233_fpu/core-matmap.h @@ -0,0 +1,717 @@ +/* + * xtensa/config/core-matmap.h -- Memory access and translation mapping + * parameters (CHAL) of the Xtensa processor core configuration. + * + * If you are using Xtensa Tools, see (which includes + * this file) for more details. + * + * In the Xtensa processor products released to date, all parameters + * defined in this file are derivable (at least in theory) from + * information contained in the core-isa.h header file. + * In particular, the following core configuration parameters are relevant: + * XCHAL_HAVE_CACHEATTR + * XCHAL_HAVE_MIMIC_CACHEATTR + * XCHAL_HAVE_XLT_CACHEATTR + * XCHAL_HAVE_PTP_MMU + * XCHAL_ITLB_ARF_ENTRIES_LOG2 + * XCHAL_DTLB_ARF_ENTRIES_LOG2 + * XCHAL_DCACHE_IS_WRITEBACK + * XCHAL_ICACHE_SIZE (presence of I-cache) + * XCHAL_DCACHE_SIZE (presence of D-cache) + * XCHAL_HW_VERSION_MAJOR + * XCHAL_HW_VERSION_MINOR + */ + +/* Copyright (c) 1999-2020 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + + +#ifndef XTENSA_CONFIG_CORE_MATMAP_H +#define XTENSA_CONFIG_CORE_MATMAP_H + + +/*---------------------------------------------------------------------- + CACHE (MEMORY ACCESS) ATTRIBUTES + ----------------------------------------------------------------------*/ + + + +/* Cache Attribute encodings -- lists of access modes for each cache attribute: */ +#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION +#define XCHAL_LCA_LIST XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION +#define XCHAL_SCA_LIST XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_WRITEBACK XCHAL_SEP \ + XTHAL_SAM_WRITEBACK XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_WRITETHRU XCHAL_SEP \ + XTHAL_SAM_WRITETHRU XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION + +#define XCHAL_CA_R (0xC0 | 0x40000000) +#define XCHAL_CA_RX (0xD0 | 0x40000000) +#define XCHAL_CA_RW (0xE0 | 0x40000000) +#define XCHAL_CA_RWX (0xF0 | 0x40000000) + +/* + * Specific encoded cache attribute values of general interest. + * If a specific cache mode is not available, the closest available + * one is returned instead (eg. writethru instead of writeback, + * bypass instead of writethru). + */ +#define XCHAL_CA_BYPASS 3 /* cache disabled (bypassed) mode */ +#define XCHAL_CA_WRITETHRU 11 /* cache enabled (write-through) mode */ +#define XCHAL_CA_WRITEBACK 7 /* cache enabled (write-back) mode */ +#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 0 /* write-back no-allocate availability */ +#define XCHAL_CA_WRITEBACK_NOALLOC 7 /* cache enabled (write-back no-allocate) mode */ +#define XCHAL_CA_BYPASS_RX 1 /* cache disabled (bypassed) mode (no write) */ +#define XCHAL_CA_WRITETHRU_RX 9 /* cache enabled (write-through) mode (no write) */ +#define XCHAL_CA_WRITEBACK_RX 5 /* cache enabled (write-back) mode (no write) */ +#define XCHAL_CA_WRITEBACK_NOALLOC_RX 5 /* cache enabled (write-back no-allocate) mode (no write) */ +#define XCHAL_CA_BYPASS_RW 2 /* cache disabled (bypassed) mode (no exec) */ +#define XCHAL_CA_WRITETHRU_RW 10 /* cache enabled (write-through) mode (no exec) */ +#define XCHAL_CA_WRITEBACK_RW 6 /* cache enabled (write-back) mode (no exec) */ +#define XCHAL_CA_WRITEBACK_NOALLOC_RW 6 /* cache enabled (write-back no-allocate) mode (no exec) */ +#define XCHAL_CA_BYPASS_R 0 /* cache disabled (bypassed) mode (no exec, no write) */ +#define XCHAL_CA_WRITETHRU_R 8 /* cache enabled (write-through) mode (no exec, no write) */ +#define XCHAL_CA_WRITEBACK_R 4 /* cache enabled (write-back) mode (no exec, no write) */ +#define XCHAL_CA_WRITEBACK_NOALLOC_R 4 /* cache enabled (write-back no-allocate) mode (no exec, no write) */ +#define XCHAL_CA_ILLEGAL 12 /* no access allowed (all cause exceptions) mode */ + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* + * General notes on MMU parameters. + * + * Terminology: + * ASID = address-space ID (acts as an "extension" of virtual addresses) + * VPN = virtual page number + * PPN = physical page number + * CA = encoded cache attribute (access modes) + * TLB = translation look-aside buffer (term is stretched somewhat here) + * I = instruction (fetch accesses) + * D = data (load and store accesses) + * way = each TLB (ITLB and DTLB) consists of a number of "ways" + * that simultaneously match the virtual address of an access; + * a TLB successfully translates a virtual address if exactly + * one way matches the vaddr; if none match, it is a miss; + * if multiple match, one gets a "multihit" exception; + * each way can be independently configured in terms of number of + * entries, page sizes, which fields are writable or constant, etc. + * set = group of contiguous ways with exactly identical parameters + * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE + * from the page table and storing it in one of the auto-refill ways; + * if this PTE load also misses, a miss exception is posted for s/w. + * min-wired = a "min-wired" way can be used to map a single (minimum-sized) + * page arbitrarily under program control; it has a single entry, + * is non-auto-refill (some other way(s) must be auto-refill), + * all its fields (VPN, PPN, ASID, CA) are all writable, and it + * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current + * restriction is that this be the only page size it supports). + * + * TLB way entries are virtually indexed. + * TLB ways that support multiple page sizes: + * - must have all writable VPN and PPN fields; + * - can only use one page size at any given time (eg. setup at startup), + * selected by the respective ITLBCFG or DTLBCFG special register, + * whose bits n*4+3 .. n*4 index the list of page sizes for way n + * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n); + * this list may be sparse for auto-refill ways because auto-refill + * ways have independent lists of supported page sizes sharing a + * common encoding with PTE entries; the encoding is the index into + * this list; unsupported sizes for a given way are zero in the list; + * selecting unsupported sizes results in undefine hardware behaviour; + * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition). + */ + +#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */ +#define XCHAL_MMU_ASID_KERNEL 1 /* ASID value indicating kernel (ring 0) address space */ +#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */ +#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */ +#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 12 /* max page size in a PTE structure (log2) */ +#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 12 /* min page size in a PTE structure (log2) */ + + +/*** Instruction TLB: ***/ + +#define XCHAL_ITLB_WAY_BITS 3 /* number of bits holding the ways */ +#define XCHAL_ITLB_WAYS 7 /* number of ways (n-way set-associative TLB) */ +#define XCHAL_ITLB_ARF_WAYS 4 /* number of auto-refill ways */ +#define XCHAL_ITLB_SETS 7 /* number of sets (groups of ways with identical settings) */ + +/* Way set to which each way belongs: */ +#define XCHAL_ITLB_WAY0_SET 0 +#define XCHAL_ITLB_WAY1_SET 1 +#define XCHAL_ITLB_WAY2_SET 2 +#define XCHAL_ITLB_WAY3_SET 3 +#define XCHAL_ITLB_WAY4_SET 4 +#define XCHAL_ITLB_WAY5_SET 5 +#define XCHAL_ITLB_WAY6_SET 6 + +/* Ways sets that are used by hardware auto-refill (ARF): */ +#define XCHAL_ITLB_ARF_SETS 4 /* number of auto-refill sets */ +#define XCHAL_ITLB_ARF_SET0 0 /* index of n'th auto-refill set */ +#define XCHAL_ITLB_ARF_SET1 1 /* index of n'th auto-refill set */ +#define XCHAL_ITLB_ARF_SET2 2 /* index of n'th auto-refill set */ +#define XCHAL_ITLB_ARF_SET3 3 /* index of n'th auto-refill set */ + +/* Way sets that are "min-wired" (see terminology comment above): */ +#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ + + +/* ITLB way set 0 (group of ways 0 thru 0): */ +#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */ +#define XCHAL_ITLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_ITLB_SET0_ENTRIES_LOG2 2 /* log2(number of entries in this way) */ +#define XCHAL_ITLB_SET0_ENTRIES 4 /* number of entries in this way (always a power of 2) */ +#define XCHAL_ITLB_SET0_ARF 1 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */ + +/* ITLB way set 1 (group of ways 1 thru 1): */ +#define XCHAL_ITLB_SET1_WAY 1 /* index of first way in this way set */ +#define XCHAL_ITLB_SET1_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_ITLB_SET1_ENTRIES_LOG2 2 /* log2(number of entries in this way) */ +#define XCHAL_ITLB_SET1_ENTRIES 4 /* number of entries in this way (always a power of 2) */ +#define XCHAL_ITLB_SET1_ARF 1 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_ITLB_SET1_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_ITLB_SET1_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_ITLB_SET1_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */ +#define XCHAL_ITLB_SET1_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */ +#define XCHAL_ITLB_SET1_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_ITLB_SET1_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_ITLB_SET1_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET1_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET1_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_ITLB_SET1_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET1_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET1_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET1_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */ + +/* ITLB way set 2 (group of ways 2 thru 2): */ +#define XCHAL_ITLB_SET2_WAY 2 /* index of first way in this way set */ +#define XCHAL_ITLB_SET2_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_ITLB_SET2_ENTRIES_LOG2 2 /* log2(number of entries in this way) */ +#define XCHAL_ITLB_SET2_ENTRIES 4 /* number of entries in this way (always a power of 2) */ +#define XCHAL_ITLB_SET2_ARF 1 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_ITLB_SET2_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_ITLB_SET2_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_ITLB_SET2_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */ +#define XCHAL_ITLB_SET2_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */ +#define XCHAL_ITLB_SET2_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_ITLB_SET2_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_ITLB_SET2_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET2_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET2_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_ITLB_SET2_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET2_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET2_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET2_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */ + +/* ITLB way set 3 (group of ways 3 thru 3): */ +#define XCHAL_ITLB_SET3_WAY 3 /* index of first way in this way set */ +#define XCHAL_ITLB_SET3_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_ITLB_SET3_ENTRIES_LOG2 2 /* log2(number of entries in this way) */ +#define XCHAL_ITLB_SET3_ENTRIES 4 /* number of entries in this way (always a power of 2) */ +#define XCHAL_ITLB_SET3_ARF 1 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_ITLB_SET3_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_ITLB_SET3_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_ITLB_SET3_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */ +#define XCHAL_ITLB_SET3_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */ +#define XCHAL_ITLB_SET3_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_ITLB_SET3_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_ITLB_SET3_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET3_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET3_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_ITLB_SET3_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET3_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET3_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET3_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */ + +/* ITLB way set 4 (group of ways 4 thru 4): */ +#define XCHAL_ITLB_SET4_WAY 4 /* index of first way in this way set */ +#define XCHAL_ITLB_SET4_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_ITLB_SET4_ENTRIES_LOG2 2 /* log2(number of entries in this way) */ +#define XCHAL_ITLB_SET4_ENTRIES 4 /* number of entries in this way (always a power of 2) */ +#define XCHAL_ITLB_SET4_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_ITLB_SET4_PAGESIZES 4 /* number of supported page sizes in this way */ +#define XCHAL_ITLB_SET4_PAGESZ_BITS 2 /* number of bits to encode the page size */ +#define XCHAL_ITLB_SET4_PAGESZ_LOG2_MIN 20 /* log2(minimum supported page size) */ +#define XCHAL_ITLB_SET4_PAGESZ_LOG2_MAX 26 /* log2(maximum supported page size) */ +#define XCHAL_ITLB_SET4_PAGESZ_LOG2_LIST 20 XCHAL_SEP 22 XCHAL_SEP 24 XCHAL_SEP 26 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_ITLB_SET4_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_ITLB_SET4_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET4_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET4_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_ITLB_SET4_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET4_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET4_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET4_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */ + +/* ITLB way set 5 (group of ways 5 thru 5): */ +#define XCHAL_ITLB_SET5_WAY 5 /* index of first way in this way set */ +#define XCHAL_ITLB_SET5_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_ITLB_SET5_ENTRIES_LOG2 2 /* log2(number of entries in this way) */ +#define XCHAL_ITLB_SET5_ENTRIES 4 /* number of entries in this way (always a power of 2) */ +#define XCHAL_ITLB_SET5_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_ITLB_SET5_PAGESIZES 2 /* number of supported page sizes in this way */ +#define XCHAL_ITLB_SET5_PAGESZ_BITS 1 /* number of bits to encode the page size */ +#define XCHAL_ITLB_SET5_PAGESZ_LOG2_MIN 27 /* log2(minimum supported page size) */ +#define XCHAL_ITLB_SET5_PAGESZ_LOG2_MAX 28 /* log2(maximum supported page size) */ +#define XCHAL_ITLB_SET5_PAGESZ_LOG2_LIST 27 XCHAL_SEP 28 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_ITLB_SET5_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_ITLB_SET5_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET5_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET5_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_ITLB_SET5_ASID_RESET 1 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET5_VPN_RESET 1 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET5_PPN_RESET 1 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET5_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Reset ASID values for each entry of ITLB way set 5 (because SET5_ASID_RESET is non-zero): */ +#define XCHAL_ITLB_SET5_E0_ASID_RESET 0x00 +#define XCHAL_ITLB_SET5_E1_ASID_RESET 0x00 +#define XCHAL_ITLB_SET5_E2_ASID_RESET 0x00 +#define XCHAL_ITLB_SET5_E3_ASID_RESET 0x00 +/* Reset VPN values for each entry of ITLB way set 5 (because SET5_VPN_RESET is non-zero): */ +#define XCHAL_ITLB_SET5_E0_VPN_RESET 0x00000000 +#define XCHAL_ITLB_SET5_E1_VPN_RESET 0x00000000 +#define XCHAL_ITLB_SET5_E2_VPN_RESET 0x00000000 +#define XCHAL_ITLB_SET5_E3_VPN_RESET 0x00000000 +/* Reset PPN values for each entry of ITLB way set 5 (because SET5_PPN_RESET is non-zero): */ +#define XCHAL_ITLB_SET5_E0_PPN_RESET 0x00000000 +#define XCHAL_ITLB_SET5_E1_PPN_RESET 0x00000000 +#define XCHAL_ITLB_SET5_E2_PPN_RESET 0x00000000 +#define XCHAL_ITLB_SET5_E3_PPN_RESET 0x00000000 + +/* ITLB way set 6 (group of ways 6 thru 6): */ +#define XCHAL_ITLB_SET6_WAY 6 /* index of first way in this way set */ +#define XCHAL_ITLB_SET6_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_ITLB_SET6_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ +#define XCHAL_ITLB_SET6_ENTRIES 8 /* number of entries in this way (always a power of 2) */ +#define XCHAL_ITLB_SET6_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_ITLB_SET6_PAGESIZES 2 /* number of supported page sizes in this way */ +#define XCHAL_ITLB_SET6_PAGESZ_BITS 1 /* number of bits to encode the page size */ +#define XCHAL_ITLB_SET6_PAGESZ_LOG2_MIN 28 /* log2(minimum supported page size) */ +#define XCHAL_ITLB_SET6_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ +#define XCHAL_ITLB_SET6_PAGESZ_LOG2_LIST 29 XCHAL_SEP 28 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_ITLB_SET6_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_ITLB_SET6_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET6_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET6_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_ITLB_SET6_ASID_RESET 1 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET6_VPN_RESET 1 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET6_PPN_RESET 1 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET6_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Reset ASID values for each entry of ITLB way set 6 (because SET6_ASID_RESET is non-zero): */ +#define XCHAL_ITLB_SET6_E0_ASID_RESET 0x01 +#define XCHAL_ITLB_SET6_E1_ASID_RESET 0x01 +#define XCHAL_ITLB_SET6_E2_ASID_RESET 0x01 +#define XCHAL_ITLB_SET6_E3_ASID_RESET 0x01 +#define XCHAL_ITLB_SET6_E4_ASID_RESET 0x01 +#define XCHAL_ITLB_SET6_E5_ASID_RESET 0x01 +#define XCHAL_ITLB_SET6_E6_ASID_RESET 0x01 +#define XCHAL_ITLB_SET6_E7_ASID_RESET 0x01 +/* Reset VPN values for each entry of ITLB way set 6 (because SET6_VPN_RESET is non-zero): */ +#define XCHAL_ITLB_SET6_E0_VPN_RESET 0x00000000 +#define XCHAL_ITLB_SET6_E1_VPN_RESET 0x20000000 +#define XCHAL_ITLB_SET6_E2_VPN_RESET 0x40000000 +#define XCHAL_ITLB_SET6_E3_VPN_RESET 0x60000000 +#define XCHAL_ITLB_SET6_E4_VPN_RESET 0x80000000 +#define XCHAL_ITLB_SET6_E5_VPN_RESET 0xA0000000 +#define XCHAL_ITLB_SET6_E6_VPN_RESET 0xC0000000 +#define XCHAL_ITLB_SET6_E7_VPN_RESET 0xE0000000 +/* Reset PPN values for each entry of ITLB way set 6 (because SET6_PPN_RESET is non-zero): */ +#define XCHAL_ITLB_SET6_E0_PPN_RESET 0x00000000 +#define XCHAL_ITLB_SET6_E1_PPN_RESET 0x20000000 +#define XCHAL_ITLB_SET6_E2_PPN_RESET 0x40000000 +#define XCHAL_ITLB_SET6_E3_PPN_RESET 0x60000000 +#define XCHAL_ITLB_SET6_E4_PPN_RESET 0x80000000 +#define XCHAL_ITLB_SET6_E5_PPN_RESET 0xA0000000 +#define XCHAL_ITLB_SET6_E6_PPN_RESET 0xC0000000 +#define XCHAL_ITLB_SET6_E7_PPN_RESET 0xE0000000 +/* Reset CA values for each entry of ITLB way set 6 (because SET6_CA_RESET is non-zero): */ +#define XCHAL_ITLB_SET6_E0_CA_RESET 0x03 +#define XCHAL_ITLB_SET6_E1_CA_RESET 0x03 +#define XCHAL_ITLB_SET6_E2_CA_RESET 0x03 +#define XCHAL_ITLB_SET6_E3_CA_RESET 0x03 +#define XCHAL_ITLB_SET6_E4_CA_RESET 0x03 +#define XCHAL_ITLB_SET6_E5_CA_RESET 0x03 +#define XCHAL_ITLB_SET6_E6_CA_RESET 0x03 +#define XCHAL_ITLB_SET6_E7_CA_RESET 0x03 + + +/*** Data TLB: ***/ + +#define XCHAL_DTLB_WAY_BITS 4 /* number of bits holding the ways */ +#define XCHAL_DTLB_WAYS 10 /* number of ways (n-way set-associative TLB) */ +#define XCHAL_DTLB_ARF_WAYS 4 /* number of auto-refill ways */ +#define XCHAL_DTLB_SETS 10 /* number of sets (groups of ways with identical settings) */ + +/* Way set to which each way belongs: */ +#define XCHAL_DTLB_WAY0_SET 0 +#define XCHAL_DTLB_WAY1_SET 1 +#define XCHAL_DTLB_WAY2_SET 2 +#define XCHAL_DTLB_WAY3_SET 3 +#define XCHAL_DTLB_WAY4_SET 4 +#define XCHAL_DTLB_WAY5_SET 5 +#define XCHAL_DTLB_WAY6_SET 6 +#define XCHAL_DTLB_WAY7_SET 7 +#define XCHAL_DTLB_WAY8_SET 8 +#define XCHAL_DTLB_WAY9_SET 9 + +/* Ways sets that are used by hardware auto-refill (ARF): */ +#define XCHAL_DTLB_ARF_SETS 4 /* number of auto-refill sets */ +#define XCHAL_DTLB_ARF_SET0 0 /* index of n'th auto-refill set */ +#define XCHAL_DTLB_ARF_SET1 1 /* index of n'th auto-refill set */ +#define XCHAL_DTLB_ARF_SET2 2 /* index of n'th auto-refill set */ +#define XCHAL_DTLB_ARF_SET3 3 /* index of n'th auto-refill set */ + +/* Way sets that are "min-wired" (see terminology comment above): */ +#define XCHAL_DTLB_MINWIRED_SETS 3 /* number of "min-wired" sets */ +#define XCHAL_DTLB_MINWIRED_SET0 7 /* index of n'th "min-wired" set */ +#define XCHAL_DTLB_MINWIRED_SET1 8 /* index of n'th "min-wired" set */ +#define XCHAL_DTLB_MINWIRED_SET2 9 /* index of n'th "min-wired" set */ + + +/* DTLB way set 0 (group of ways 0 thru 0): */ +#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */ +#define XCHAL_DTLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_DTLB_SET0_ENTRIES_LOG2 2 /* log2(number of entries in this way) */ +#define XCHAL_DTLB_SET0_ENTRIES 4 /* number of entries in this way (always a power of 2) */ +#define XCHAL_DTLB_SET0_ARF 1 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */ + +/* DTLB way set 1 (group of ways 1 thru 1): */ +#define XCHAL_DTLB_SET1_WAY 1 /* index of first way in this way set */ +#define XCHAL_DTLB_SET1_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_DTLB_SET1_ENTRIES_LOG2 2 /* log2(number of entries in this way) */ +#define XCHAL_DTLB_SET1_ENTRIES 4 /* number of entries in this way (always a power of 2) */ +#define XCHAL_DTLB_SET1_ARF 1 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_DTLB_SET1_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_DTLB_SET1_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_DTLB_SET1_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */ +#define XCHAL_DTLB_SET1_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */ +#define XCHAL_DTLB_SET1_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_DTLB_SET1_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_DTLB_SET1_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET1_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET1_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_DTLB_SET1_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET1_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET1_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET1_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */ + +/* DTLB way set 2 (group of ways 2 thru 2): */ +#define XCHAL_DTLB_SET2_WAY 2 /* index of first way in this way set */ +#define XCHAL_DTLB_SET2_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_DTLB_SET2_ENTRIES_LOG2 2 /* log2(number of entries in this way) */ +#define XCHAL_DTLB_SET2_ENTRIES 4 /* number of entries in this way (always a power of 2) */ +#define XCHAL_DTLB_SET2_ARF 1 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_DTLB_SET2_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_DTLB_SET2_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_DTLB_SET2_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */ +#define XCHAL_DTLB_SET2_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */ +#define XCHAL_DTLB_SET2_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_DTLB_SET2_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_DTLB_SET2_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET2_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET2_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_DTLB_SET2_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET2_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET2_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET2_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */ + +/* DTLB way set 3 (group of ways 3 thru 3): */ +#define XCHAL_DTLB_SET3_WAY 3 /* index of first way in this way set */ +#define XCHAL_DTLB_SET3_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_DTLB_SET3_ENTRIES_LOG2 2 /* log2(number of entries in this way) */ +#define XCHAL_DTLB_SET3_ENTRIES 4 /* number of entries in this way (always a power of 2) */ +#define XCHAL_DTLB_SET3_ARF 1 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_DTLB_SET3_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_DTLB_SET3_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_DTLB_SET3_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */ +#define XCHAL_DTLB_SET3_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */ +#define XCHAL_DTLB_SET3_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_DTLB_SET3_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_DTLB_SET3_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET3_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET3_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_DTLB_SET3_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET3_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET3_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET3_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */ + +/* DTLB way set 4 (group of ways 4 thru 4): */ +#define XCHAL_DTLB_SET4_WAY 4 /* index of first way in this way set */ +#define XCHAL_DTLB_SET4_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_DTLB_SET4_ENTRIES_LOG2 2 /* log2(number of entries in this way) */ +#define XCHAL_DTLB_SET4_ENTRIES 4 /* number of entries in this way (always a power of 2) */ +#define XCHAL_DTLB_SET4_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_DTLB_SET4_PAGESIZES 4 /* number of supported page sizes in this way */ +#define XCHAL_DTLB_SET4_PAGESZ_BITS 2 /* number of bits to encode the page size */ +#define XCHAL_DTLB_SET4_PAGESZ_LOG2_MIN 20 /* log2(minimum supported page size) */ +#define XCHAL_DTLB_SET4_PAGESZ_LOG2_MAX 26 /* log2(maximum supported page size) */ +#define XCHAL_DTLB_SET4_PAGESZ_LOG2_LIST 20 XCHAL_SEP 22 XCHAL_SEP 24 XCHAL_SEP 26 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_DTLB_SET4_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_DTLB_SET4_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET4_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET4_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_DTLB_SET4_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET4_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET4_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET4_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */ + +/* DTLB way set 5 (group of ways 5 thru 5): */ +#define XCHAL_DTLB_SET5_WAY 5 /* index of first way in this way set */ +#define XCHAL_DTLB_SET5_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_DTLB_SET5_ENTRIES_LOG2 2 /* log2(number of entries in this way) */ +#define XCHAL_DTLB_SET5_ENTRIES 4 /* number of entries in this way (always a power of 2) */ +#define XCHAL_DTLB_SET5_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_DTLB_SET5_PAGESIZES 2 /* number of supported page sizes in this way */ +#define XCHAL_DTLB_SET5_PAGESZ_BITS 1 /* number of bits to encode the page size */ +#define XCHAL_DTLB_SET5_PAGESZ_LOG2_MIN 27 /* log2(minimum supported page size) */ +#define XCHAL_DTLB_SET5_PAGESZ_LOG2_MAX 28 /* log2(maximum supported page size) */ +#define XCHAL_DTLB_SET5_PAGESZ_LOG2_LIST 27 XCHAL_SEP 28 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_DTLB_SET5_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_DTLB_SET5_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET5_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET5_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_DTLB_SET5_ASID_RESET 1 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET5_VPN_RESET 1 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET5_PPN_RESET 1 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET5_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Reset ASID values for each entry of DTLB way set 5 (because SET5_ASID_RESET is non-zero): */ +#define XCHAL_DTLB_SET5_E0_ASID_RESET 0x00 +#define XCHAL_DTLB_SET5_E1_ASID_RESET 0x00 +#define XCHAL_DTLB_SET5_E2_ASID_RESET 0x00 +#define XCHAL_DTLB_SET5_E3_ASID_RESET 0x00 +/* Reset VPN values for each entry of DTLB way set 5 (because SET5_VPN_RESET is non-zero): */ +#define XCHAL_DTLB_SET5_E0_VPN_RESET 0x00000000 +#define XCHAL_DTLB_SET5_E1_VPN_RESET 0x00000000 +#define XCHAL_DTLB_SET5_E2_VPN_RESET 0x00000000 +#define XCHAL_DTLB_SET5_E3_VPN_RESET 0x00000000 +/* Reset PPN values for each entry of DTLB way set 5 (because SET5_PPN_RESET is non-zero): */ +#define XCHAL_DTLB_SET5_E0_PPN_RESET 0x00000000 +#define XCHAL_DTLB_SET5_E1_PPN_RESET 0x00000000 +#define XCHAL_DTLB_SET5_E2_PPN_RESET 0x00000000 +#define XCHAL_DTLB_SET5_E3_PPN_RESET 0x00000000 + +/* DTLB way set 6 (group of ways 6 thru 6): */ +#define XCHAL_DTLB_SET6_WAY 6 /* index of first way in this way set */ +#define XCHAL_DTLB_SET6_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_DTLB_SET6_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ +#define XCHAL_DTLB_SET6_ENTRIES 8 /* number of entries in this way (always a power of 2) */ +#define XCHAL_DTLB_SET6_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_DTLB_SET6_PAGESIZES 2 /* number of supported page sizes in this way */ +#define XCHAL_DTLB_SET6_PAGESZ_BITS 1 /* number of bits to encode the page size */ +#define XCHAL_DTLB_SET6_PAGESZ_LOG2_MIN 28 /* log2(minimum supported page size) */ +#define XCHAL_DTLB_SET6_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ +#define XCHAL_DTLB_SET6_PAGESZ_LOG2_LIST 29 XCHAL_SEP 28 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_DTLB_SET6_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_DTLB_SET6_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET6_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET6_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_DTLB_SET6_ASID_RESET 1 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET6_VPN_RESET 1 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET6_PPN_RESET 1 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET6_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Reset ASID values for each entry of DTLB way set 6 (because SET6_ASID_RESET is non-zero): */ +#define XCHAL_DTLB_SET6_E0_ASID_RESET 0x01 +#define XCHAL_DTLB_SET6_E1_ASID_RESET 0x01 +#define XCHAL_DTLB_SET6_E2_ASID_RESET 0x01 +#define XCHAL_DTLB_SET6_E3_ASID_RESET 0x01 +#define XCHAL_DTLB_SET6_E4_ASID_RESET 0x01 +#define XCHAL_DTLB_SET6_E5_ASID_RESET 0x01 +#define XCHAL_DTLB_SET6_E6_ASID_RESET 0x01 +#define XCHAL_DTLB_SET6_E7_ASID_RESET 0x01 +/* Reset VPN values for each entry of DTLB way set 6 (because SET6_VPN_RESET is non-zero): */ +#define XCHAL_DTLB_SET6_E0_VPN_RESET 0x00000000 +#define XCHAL_DTLB_SET6_E1_VPN_RESET 0x20000000 +#define XCHAL_DTLB_SET6_E2_VPN_RESET 0x40000000 +#define XCHAL_DTLB_SET6_E3_VPN_RESET 0x60000000 +#define XCHAL_DTLB_SET6_E4_VPN_RESET 0x80000000 +#define XCHAL_DTLB_SET6_E5_VPN_RESET 0xA0000000 +#define XCHAL_DTLB_SET6_E6_VPN_RESET 0xC0000000 +#define XCHAL_DTLB_SET6_E7_VPN_RESET 0xE0000000 +/* Reset PPN values for each entry of DTLB way set 6 (because SET6_PPN_RESET is non-zero): */ +#define XCHAL_DTLB_SET6_E0_PPN_RESET 0x00000000 +#define XCHAL_DTLB_SET6_E1_PPN_RESET 0x20000000 +#define XCHAL_DTLB_SET6_E2_PPN_RESET 0x40000000 +#define XCHAL_DTLB_SET6_E3_PPN_RESET 0x60000000 +#define XCHAL_DTLB_SET6_E4_PPN_RESET 0x80000000 +#define XCHAL_DTLB_SET6_E5_PPN_RESET 0xA0000000 +#define XCHAL_DTLB_SET6_E6_PPN_RESET 0xC0000000 +#define XCHAL_DTLB_SET6_E7_PPN_RESET 0xE0000000 +/* Reset CA values for each entry of DTLB way set 6 (because SET6_CA_RESET is non-zero): */ +#define XCHAL_DTLB_SET6_E0_CA_RESET 0x03 +#define XCHAL_DTLB_SET6_E1_CA_RESET 0x03 +#define XCHAL_DTLB_SET6_E2_CA_RESET 0x03 +#define XCHAL_DTLB_SET6_E3_CA_RESET 0x03 +#define XCHAL_DTLB_SET6_E4_CA_RESET 0x03 +#define XCHAL_DTLB_SET6_E5_CA_RESET 0x03 +#define XCHAL_DTLB_SET6_E6_CA_RESET 0x03 +#define XCHAL_DTLB_SET6_E7_CA_RESET 0x03 + +/* DTLB way set 7 (group of ways 7 thru 7): */ +#define XCHAL_DTLB_SET7_WAY 7 /* index of first way in this way set */ +#define XCHAL_DTLB_SET7_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_DTLB_SET7_ENTRIES_LOG2 0 /* log2(number of entries in this way) */ +#define XCHAL_DTLB_SET7_ENTRIES 1 /* number of entries in this way (always a power of 2) */ +#define XCHAL_DTLB_SET7_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_DTLB_SET7_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_DTLB_SET7_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_DTLB_SET7_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */ +#define XCHAL_DTLB_SET7_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */ +#define XCHAL_DTLB_SET7_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_DTLB_SET7_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_DTLB_SET7_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET7_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET7_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_DTLB_SET7_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET7_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET7_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET7_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */ + +/* DTLB way set 8 (group of ways 8 thru 8): */ +#define XCHAL_DTLB_SET8_WAY 8 /* index of first way in this way set */ +#define XCHAL_DTLB_SET8_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_DTLB_SET8_ENTRIES_LOG2 0 /* log2(number of entries in this way) */ +#define XCHAL_DTLB_SET8_ENTRIES 1 /* number of entries in this way (always a power of 2) */ +#define XCHAL_DTLB_SET8_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_DTLB_SET8_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_DTLB_SET8_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_DTLB_SET8_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */ +#define XCHAL_DTLB_SET8_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */ +#define XCHAL_DTLB_SET8_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_DTLB_SET8_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_DTLB_SET8_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET8_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET8_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_DTLB_SET8_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET8_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET8_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET8_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */ + +/* DTLB way set 9 (group of ways 9 thru 9): */ +#define XCHAL_DTLB_SET9_WAY 9 /* index of first way in this way set */ +#define XCHAL_DTLB_SET9_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_DTLB_SET9_ENTRIES_LOG2 0 /* log2(number of entries in this way) */ +#define XCHAL_DTLB_SET9_ENTRIES 1 /* number of entries in this way (always a power of 2) */ +#define XCHAL_DTLB_SET9_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_DTLB_SET9_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_DTLB_SET9_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_DTLB_SET9_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */ +#define XCHAL_DTLB_SET9_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */ +#define XCHAL_DTLB_SET9_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_DTLB_SET9_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_DTLB_SET9_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET9_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET9_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_DTLB_SET9_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET9_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET9_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET9_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */ + + + + +#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ + diff --git a/target/xtensa/core-de233_fpu/gdb-config.c.inc b/target/xtensa/core-de233_fpu/gdb-config.c.inc new file mode 100644 index 0000000000000000000000000000000000000000..66fcb4894a7cb35df0c0840bce7c0d3ad404019e --- /dev/null +++ b/target/xtensa/core-de233_fpu/gdb-config.c.inc @@ -0,0 +1,277 @@ +/* Configuration for the Xtensa architecture for GDB, the GNU debugger. + + Copyright (c) 2003-2020 Tensilica Inc. + + 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. */ + XTREG( 0, 0,32, 4, 4,0x0020,0x0006,-2, 9,0x2100,pc, 0,0,0,0,0,0) + XTREG( 1, 4,32, 4, 4,0x0100,0x0006,-2, 1,0x0002,ar0, 0,0,0,0,0,0) + XTREG( 2, 8,32, 4, 4,0x0101,0x0006,-2, 1,0x0002,ar1, 0,0,0,0,0,0) + XTREG( 3, 12,32, 4, 4,0x0102,0x0006,-2, 1,0x0002,ar2, 0,0,0,0,0,0) + XTREG( 4, 16,32, 4, 4,0x0103,0x0006,-2, 1,0x0002,ar3, 0,0,0,0,0,0) + XTREG( 5, 20,32, 4, 4,0x0104,0x0006,-2, 1,0x0002,ar4, 0,0,0,0,0,0) + XTREG( 6, 24,32, 4, 4,0x0105,0x0006,-2, 1,0x0002,ar5, 0,0,0,0,0,0) + XTREG( 7, 28,32, 4, 4,0x0106,0x0006,-2, 1,0x0002,ar6, 0,0,0,0,0,0) + XTREG( 8, 32,32, 4, 4,0x0107,0x0006,-2, 1,0x0002,ar7, 0,0,0,0,0,0) + XTREG( 9, 36,32, 4, 4,0x0108,0x0006,-2, 1,0x0002,ar8, 0,0,0,0,0,0) + XTREG( 10, 40,32, 4, 4,0x0109,0x0006,-2, 1,0x0002,ar9, 0,0,0,0,0,0) + XTREG( 11, 44,32, 4, 4,0x010a,0x0006,-2, 1,0x0002,ar10, 0,0,0,0,0,0) + XTREG( 12, 48,32, 4, 4,0x010b,0x0006,-2, 1,0x0002,ar11, 0,0,0,0,0,0) + XTREG( 13, 52,32, 4, 4,0x010c,0x0006,-2, 1,0x0002,ar12, 0,0,0,0,0,0) + XTREG( 14, 56,32, 4, 4,0x010d,0x0006,-2, 1,0x0002,ar13, 0,0,0,0,0,0) + XTREG( 15, 60,32, 4, 4,0x010e,0x0006,-2, 1,0x0002,ar14, 0,0,0,0,0,0) + XTREG( 16, 64,32, 4, 4,0x010f,0x0006,-2, 1,0x0002,ar15, 0,0,0,0,0,0) + XTREG( 17, 68,32, 4, 4,0x0110,0x0006,-2, 1,0x0002,ar16, 0,0,0,0,0,0) + XTREG( 18, 72,32, 4, 4,0x0111,0x0006,-2, 1,0x0002,ar17, 0,0,0,0,0,0) + XTREG( 19, 76,32, 4, 4,0x0112,0x0006,-2, 1,0x0002,ar18, 0,0,0,0,0,0) + XTREG( 20, 80,32, 4, 4,0x0113,0x0006,-2, 1,0x0002,ar19, 0,0,0,0,0,0) + XTREG( 21, 84,32, 4, 4,0x0114,0x0006,-2, 1,0x0002,ar20, 0,0,0,0,0,0) + XTREG( 22, 88,32, 4, 4,0x0115,0x0006,-2, 1,0x0002,ar21, 0,0,0,0,0,0) + XTREG( 23, 92,32, 4, 4,0x0116,0x0006,-2, 1,0x0002,ar22, 0,0,0,0,0,0) + XTREG( 24, 96,32, 4, 4,0x0117,0x0006,-2, 1,0x0002,ar23, 0,0,0,0,0,0) + XTREG( 25,100,32, 4, 4,0x0118,0x0006,-2, 1,0x0002,ar24, 0,0,0,0,0,0) + XTREG( 26,104,32, 4, 4,0x0119,0x0006,-2, 1,0x0002,ar25, 0,0,0,0,0,0) + XTREG( 27,108,32, 4, 4,0x011a,0x0006,-2, 1,0x0002,ar26, 0,0,0,0,0,0) + XTREG( 28,112,32, 4, 4,0x011b,0x0006,-2, 1,0x0002,ar27, 0,0,0,0,0,0) + XTREG( 29,116,32, 4, 4,0x011c,0x0006,-2, 1,0x0002,ar28, 0,0,0,0,0,0) + XTREG( 30,120,32, 4, 4,0x011d,0x0006,-2, 1,0x0002,ar29, 0,0,0,0,0,0) + XTREG( 31,124,32, 4, 4,0x011e,0x0006,-2, 1,0x0002,ar30, 0,0,0,0,0,0) + XTREG( 32,128,32, 4, 4,0x011f,0x0006,-2, 1,0x0002,ar31, 0,0,0,0,0,0) + XTREG( 33,132,32, 4, 4,0x0200,0x0006,-2, 2,0x1100,lbeg, 0,0,0,0,0,0) + XTREG( 34,136,32, 4, 4,0x0201,0x0006,-2, 2,0x1100,lend, 0,0,0,0,0,0) + XTREG( 35,140,32, 4, 4,0x0202,0x0006,-2, 2,0x1100,lcount, 0,0,0,0,0,0) + XTREG( 36,144, 6, 4, 4,0x0203,0x0006,-2, 2,0x1100,sar, 0,0,0,0,0,0) + XTREG( 37,148, 3, 4, 4,0x0248,0x0006,-2, 2,0x1002,windowbase, 0,0,0,0,0,0) + XTREG( 38,152, 8, 4, 4,0x0249,0x0006,-2, 2,0x1002,windowstart, 0,0,0,0,0,0) + XTREG( 39,156,32, 4, 4,0x02b0,0x0002,-2, 2,0x1000,configid0, 0,0,0,0,0,0) + XTREG( 40,160,32, 4, 4,0x02d0,0x0002,-2, 2,0x1000,configid1, 0,0,0,0,0,0) + XTREG( 41,164,19, 4, 4,0x02e6,0x0006,-2, 2,0x1100,ps, 0,0,0,0,0,0) + XTREG( 42,168,32, 4, 4,0x03e7,0x0006,-2, 3,0x0110,threadptr, 0,0,0,0,0,0) + XTREG( 43,172,16, 4, 4,0x0204,0x0006,-1, 2,0x1100,br, 0,0,0,0,0,0) + XTREG( 44,176,32, 4, 4,0x020c,0x0006,-1, 2,0x1100,scompare1, 0,0,0,0,0,0) + XTREG( 45,180,32, 4, 4,0x0210,0x0006,-1, 2,0x1100,acclo, 0,0,0,0,0,0) + XTREG( 46,184, 8, 4, 4,0x0211,0x0006,-1, 2,0x1100,acchi, 0,0,0,0,0,0) + XTREG( 47,188,32, 4, 4,0x0220,0x0006,-1, 2,0x1100,m0, 0,0,0,0,0,0) + XTREG( 48,192,32, 4, 4,0x0221,0x0006,-1, 2,0x1100,m1, 0,0,0,0,0,0) + XTREG( 49,196,32, 4, 4,0x0222,0x0006,-1, 2,0x1100,m2, 0,0,0,0,0,0) + XTREG( 50,200,32, 4, 4,0x0223,0x0006,-1, 2,0x1100,m3, 0,0,0,0,0,0) + XTREG( 51,204,32, 4, 4,0x03e6,0x000e,-1, 3,0x0110,expstate, 0,0,0,0,0,0) + XTREG( 52,208,64, 8, 8,0x0030,0x0006, 0, 4,0x0401,f0, + "03:03:54:00","03:03:14:00",0,0,0,0) + XTREG( 53,216,64, 8, 8,0x0031,0x0006, 0, 4,0x0401,f1, + "03:13:54:00","03:13:14:00",0,0,0,0) + XTREG( 54,224,64, 8, 8,0x0032,0x0006, 0, 4,0x0401,f2, + "03:23:54:00","03:23:14:00",0,0,0,0) + XTREG( 55,232,64, 8, 8,0x0033,0x0006, 0, 4,0x0401,f3, + "03:33:54:00","03:33:14:00",0,0,0,0) + XTREG( 56,240,64, 8, 8,0x0034,0x0006, 0, 4,0x0401,f4, + "03:43:54:00","03:43:14:00",0,0,0,0) + XTREG( 57,248,64, 8, 8,0x0035,0x0006, 0, 4,0x0401,f5, + "03:53:54:00","03:53:14:00",0,0,0,0) + XTREG( 58,256,64, 8, 8,0x0036,0x0006, 0, 4,0x0401,f6, + "03:63:54:00","03:63:14:00",0,0,0,0) + XTREG( 59,264,64, 8, 8,0x0037,0x0006, 0, 4,0x0401,f7, + "03:73:54:00","03:73:14:00",0,0,0,0) + XTREG( 60,272,64, 8, 8,0x0038,0x0006, 0, 4,0x0401,f8, + "03:83:54:00","03:83:14:00",0,0,0,0) + XTREG( 61,280,64, 8, 8,0x0039,0x0006, 0, 4,0x0401,f9, + "03:93:54:00","03:93:14:00",0,0,0,0) + XTREG( 62,288,64, 8, 8,0x003a,0x0006, 0, 4,0x0401,f10, + "03:a3:54:00","03:a3:14:00",0,0,0,0) + XTREG( 63,296,64, 8, 8,0x003b,0x0006, 0, 4,0x0401,f11, + "03:b3:54:00","03:b3:14:00",0,0,0,0) + XTREG( 64,304,64, 8, 8,0x003c,0x0006, 0, 4,0x0401,f12, + "03:c3:54:00","03:c3:14:00",0,0,0,0) + XTREG( 65,312,64, 8, 8,0x003d,0x0006, 0, 4,0x0401,f13, + "03:d3:54:00","03:d3:14:00",0,0,0,0) + XTREG( 66,320,64, 8, 8,0x003e,0x0006, 0, 4,0x0401,f14, + "03:e3:54:00","03:e3:14:00",0,0,0,0) + XTREG( 67,328,64, 8, 8,0x003f,0x0006, 0, 4,0x0401,f15, + "03:f3:54:00","03:f3:14:00",0,0,0,0) + XTREG( 68,336,32, 4, 4,0x03e8,0x0006, 0, 3,0x0100,fcr, 0,0,0,0,0,0) + XTREG( 69,340,32, 4, 4,0x03e9,0x0006, 0, 3,0x0100,fsr, 0,0,0,0,0,0) + XTREG( 70,344,32, 4, 4,0x0253,0x0007,-2, 2,0x1000,ptevaddr, 0,0,0,0,0,0) + XTREG( 71,348,32, 4, 4,0x0259,0x000d,-2, 2,0x1000,mmid, 0,0,0,0,0,0) + XTREG( 72,352,32, 4, 4,0x025a,0x0007,-2, 2,0x1000,rasid, 0,0,0,0,0,0) + XTREG( 73,356,25, 4, 4,0x025b,0x0007,-2, 2,0x1000,itlbcfg, 0,0,0,0,0,0) + XTREG( 74,360,25, 4, 4,0x025c,0x0007,-2, 2,0x1000,dtlbcfg, 0,0,0,0,0,0) + XTREG( 75,364,16, 4, 4,0x025f,0x0007,-2, 2,0x1000,eraccess, 0,0,0,0,0,0) + XTREG( 76,368, 2, 4, 4,0x0260,0x0007,-2, 2,0x1000,ibreakenable,0,0,0,0,0,0) + XTREG( 77,372, 6, 4, 4,0x0263,0x0007,-2, 2,0x1000,atomctl, 0,0,0,0,0,0) + XTREG( 78,376,32, 4, 4,0x0268,0x0007,-2, 2,0x1000,ddr, 0,0,0,0,0,0) + XTREG( 79,380,32, 4, 4,0x0280,0x0007,-2, 2,0x1000,ibreaka0, 0,0,0,0,0,0) + XTREG( 80,384,32, 4, 4,0x0281,0x0007,-2, 2,0x1000,ibreaka1, 0,0,0,0,0,0) + XTREG( 81,388,32, 4, 4,0x0290,0x0007,-2, 2,0x1000,dbreaka0, 0,0,0,0,0,0) + XTREG( 82,392,32, 4, 4,0x0291,0x0007,-2, 2,0x1000,dbreaka1, 0,0,0,0,0,0) + XTREG( 83,396,32, 4, 4,0x02a0,0x0007,-2, 2,0x1000,dbreakc0, 0,0,0,0,0,0) + XTREG( 84,400,32, 4, 4,0x02a1,0x0007,-2, 2,0x1000,dbreakc1, 0,0,0,0,0,0) + XTREG( 85,404,32, 4, 4,0x02b1,0x0007,-2, 2,0x1000,epc1, 0,0,0,0,0,0) + XTREG( 86,408,32, 4, 4,0x02b2,0x0007,-2, 2,0x1000,epc2, 0,0,0,0,0,0) + XTREG( 87,412,32, 4, 4,0x02b3,0x0007,-2, 2,0x1000,epc3, 0,0,0,0,0,0) + XTREG( 88,416,32, 4, 4,0x02b4,0x0007,-2, 2,0x1000,epc4, 0,0,0,0,0,0) + XTREG( 89,420,32, 4, 4,0x02b5,0x0007,-2, 2,0x1000,epc5, 0,0,0,0,0,0) + XTREG( 90,424,32, 4, 4,0x02b6,0x0007,-2, 2,0x1000,epc6, 0,0,0,0,0,0) + XTREG( 91,428,32, 4, 4,0x02b7,0x0007,-2, 2,0x1000,epc7, 0,0,0,0,0,0) + XTREG( 92,432,32, 4, 4,0x02c0,0x0007,-2, 2,0x1000,depc, 0,0,0,0,0,0) + XTREG( 93,436,19, 4, 4,0x02c2,0x0007,-2, 2,0x1000,eps2, 0,0,0,0,0,0) + XTREG( 94,440,19, 4, 4,0x02c3,0x0007,-2, 2,0x1000,eps3, 0,0,0,0,0,0) + XTREG( 95,444,19, 4, 4,0x02c4,0x0007,-2, 2,0x1000,eps4, 0,0,0,0,0,0) + XTREG( 96,448,19, 4, 4,0x02c5,0x0007,-2, 2,0x1000,eps5, 0,0,0,0,0,0) + XTREG( 97,452,19, 4, 4,0x02c6,0x0007,-2, 2,0x1000,eps6, 0,0,0,0,0,0) + XTREG( 98,456,19, 4, 4,0x02c7,0x0007,-2, 2,0x1000,eps7, 0,0,0,0,0,0) + XTREG( 99,460,32, 4, 4,0x02d1,0x0007,-2, 2,0x1000,excsave1, 0,0,0,0,0,0) + XTREG(100,464,32, 4, 4,0x02d2,0x0007,-2, 2,0x1000,excsave2, 0,0,0,0,0,0) + XTREG(101,468,32, 4, 4,0x02d3,0x0007,-2, 2,0x1000,excsave3, 0,0,0,0,0,0) + XTREG(102,472,32, 4, 4,0x02d4,0x0007,-2, 2,0x1000,excsave4, 0,0,0,0,0,0) + XTREG(103,476,32, 4, 4,0x02d5,0x0007,-2, 2,0x1000,excsave5, 0,0,0,0,0,0) + XTREG(104,480,32, 4, 4,0x02d6,0x0007,-2, 2,0x1000,excsave6, 0,0,0,0,0,0) + XTREG(105,484,32, 4, 4,0x02d7,0x0007,-2, 2,0x1000,excsave7, 0,0,0,0,0,0) + XTREG(106,488, 8, 4, 4,0x02e0,0x0007,-2, 2,0x1000,cpenable, 0,0,0,0,0,0) + XTREG(107,492,22, 4, 4,0x02e2,0x000b,-2, 2,0x1000,interrupt, 0,0,0,0,0,0) + XTREG(108,496,22, 4, 4,0x02e2,0x000d,-2, 2,0x1000,intset, 0,0,0,0,0,0) + XTREG(109,500,22, 4, 4,0x02e3,0x000d,-2, 2,0x1000,intclear, 0,0,0,0,0,0) + XTREG(110,504,22, 4, 4,0x02e4,0x0007,-2, 2,0x1000,intenable, 0,0,0,0,0,0) + XTREG(111,508,32, 4, 4,0x02e7,0x0007,-2, 2,0x1000,vecbase, 0,0,0,0,0,0) + XTREG(112,512, 6, 4, 4,0x02e8,0x0007,-2, 2,0x1000,exccause, 0,0,0,0,0,0) + XTREG(113,516,12, 4, 4,0x02e9,0x0003,-2, 2,0x1000,debugcause, 0,0,0,0,0,0) + XTREG(114,520,32, 4, 4,0x02ea,0x000f,-2, 2,0x1000,ccount, 0,0,0,0,0,0) + XTREG(115,524,32, 4, 4,0x02eb,0x0003,-2, 2,0x1000,prid, 0,0,0,0,0,0) + XTREG(116,528,32, 4, 4,0x02ec,0x000f,-2, 2,0x1000,icount, 0,0,0,0,0,0) + XTREG(117,532, 4, 4, 4,0x02ed,0x0007,-2, 2,0x1000,icountlevel, 0,0,0,0,0,0) + XTREG(118,536,32, 4, 4,0x02ee,0x0007,-2, 2,0x1000,excvaddr, 0,0,0,0,0,0) + XTREG(119,540,32, 4, 4,0x02f0,0x000f,-2, 2,0x1000,ccompare0, 0,0,0,0,0,0) + XTREG(120,544,32, 4, 4,0x02f1,0x000f,-2, 2,0x1000,ccompare1, 0,0,0,0,0,0) + XTREG(121,548,32, 4, 4,0x02f2,0x000f,-2, 2,0x1000,ccompare2, 0,0,0,0,0,0) + XTREG(122,552,32, 4, 4,0x02f4,0x0007,-2, 2,0x1000,misc0, 0,0,0,0,0,0) + XTREG(123,556,32, 4, 4,0x02f5,0x0007,-2, 2,0x1000,misc1, 0,0,0,0,0,0) + XTREG(124,560,32, 4, 4,0x0000,0x0006,-2, 8,0x2100,a0, 0,0,0,0,0,0) + XTREG(125,564,32, 4, 4,0x0001,0x0006,-2, 8,0x2100,a1, 0,0,0,0,0,0) + XTREG(126,568,32, 4, 4,0x0002,0x0006,-2, 8,0x2100,a2, 0,0,0,0,0,0) + XTREG(127,572,32, 4, 4,0x0003,0x0006,-2, 8,0x2100,a3, 0,0,0,0,0,0) + XTREG(128,576,32, 4, 4,0x0004,0x0006,-2, 8,0x2100,a4, 0,0,0,0,0,0) + XTREG(129,580,32, 4, 4,0x0005,0x0006,-2, 8,0x2100,a5, 0,0,0,0,0,0) + XTREG(130,584,32, 4, 4,0x0006,0x0006,-2, 8,0x2100,a6, 0,0,0,0,0,0) + XTREG(131,588,32, 4, 4,0x0007,0x0006,-2, 8,0x2100,a7, 0,0,0,0,0,0) + XTREG(132,592,32, 4, 4,0x0008,0x0006,-2, 8,0x2100,a8, 0,0,0,0,0,0) + XTREG(133,596,32, 4, 4,0x0009,0x0006,-2, 8,0x2100,a9, 0,0,0,0,0,0) + XTREG(134,600,32, 4, 4,0x000a,0x0006,-2, 8,0x2100,a10, 0,0,0,0,0,0) + XTREG(135,604,32, 4, 4,0x000b,0x0006,-2, 8,0x2100,a11, 0,0,0,0,0,0) + XTREG(136,608,32, 4, 4,0x000c,0x0006,-2, 8,0x2100,a12, 0,0,0,0,0,0) + XTREG(137,612,32, 4, 4,0x000d,0x0006,-2, 8,0x2100,a13, 0,0,0,0,0,0) + XTREG(138,616,32, 4, 4,0x000e,0x0006,-2, 8,0x2100,a14, 0,0,0,0,0,0) + XTREG(139,620,32, 4, 4,0x000f,0x0006,-2, 8,0x2100,a15, 0,0,0,0,0,0) + XTREG(140,624, 1, 1, 1,0x0010,0x0006,-2, 6,0x1010,b0, + 0,0,&xtensa_mask0,0,0,0) + XTREG(141,625, 1, 1, 1,0x0011,0x0006,-2, 6,0x1010,b1, + 0,0,&xtensa_mask1,0,0,0) + XTREG(142,626, 1, 1, 1,0x0012,0x0006,-2, 6,0x1010,b2, + 0,0,&xtensa_mask2,0,0,0) + XTREG(143,627, 1, 1, 1,0x0013,0x0006,-2, 6,0x1010,b3, + 0,0,&xtensa_mask3,0,0,0) + XTREG(144,628, 1, 1, 1,0x0014,0x0006,-2, 6,0x1010,b4, + 0,0,&xtensa_mask4,0,0,0) + XTREG(145,629, 1, 1, 1,0x0015,0x0006,-2, 6,0x1010,b5, + 0,0,&xtensa_mask5,0,0,0) + XTREG(146,630, 1, 1, 1,0x0016,0x0006,-2, 6,0x1010,b6, + 0,0,&xtensa_mask6,0,0,0) + XTREG(147,631, 1, 1, 1,0x0017,0x0006,-2, 6,0x1010,b7, + 0,0,&xtensa_mask7,0,0,0) + XTREG(148,632, 1, 1, 1,0x0018,0x0006,-2, 6,0x1010,b8, + 0,0,&xtensa_mask8,0,0,0) + XTREG(149,633, 1, 1, 1,0x0019,0x0006,-2, 6,0x1010,b9, + 0,0,&xtensa_mask9,0,0,0) + XTREG(150,634, 1, 1, 1,0x001a,0x0006,-2, 6,0x1010,b10, + 0,0,&xtensa_mask10,0,0,0) + XTREG(151,635, 1, 1, 1,0x001b,0x0006,-2, 6,0x1010,b11, + 0,0,&xtensa_mask11,0,0,0) + XTREG(152,636, 1, 1, 1,0x001c,0x0006,-2, 6,0x1010,b12, + 0,0,&xtensa_mask12,0,0,0) + XTREG(153,637, 1, 1, 1,0x001d,0x0006,-2, 6,0x1010,b13, + 0,0,&xtensa_mask13,0,0,0) + XTREG(154,638, 1, 1, 1,0x001e,0x0006,-2, 6,0x1010,b14, + 0,0,&xtensa_mask14,0,0,0) + XTREG(155,639, 1, 1, 1,0x001f,0x0006,-2, 6,0x1010,b15, + 0,0,&xtensa_mask15,0,0,0) + XTREG(156,640, 4, 4, 4,0x2008,0x0006,-2, 6,0x1010,psintlevel, + 0,0,&xtensa_mask16,0,0,0) + XTREG(157,644, 1, 4, 4,0x2009,0x0006,-2, 6,0x1010,psum, + 0,0,&xtensa_mask17,0,0,0) + XTREG(158,648, 1, 4, 4,0x200a,0x0006,-2, 6,0x1010,pswoe, + 0,0,&xtensa_mask18,0,0,0) + XTREG(159,652, 2, 4, 4,0x200b,0x0006,-2, 6,0x1010,psring, + 0,0,&xtensa_mask19,0,0,0) + XTREG(160,656, 1, 4, 4,0x200c,0x0006,-2, 6,0x1010,psexcm, + 0,0,&xtensa_mask20,0,0,0) + XTREG(161,660, 2, 4, 4,0x200d,0x0006,-2, 6,0x1010,pscallinc, + 0,0,&xtensa_mask21,0,0,0) + XTREG(162,664, 4, 4, 4,0x200e,0x0006,-2, 6,0x1010,psowb, + 0,0,&xtensa_mask22,0,0,0) + XTREG(163,668,40, 8, 4,0x200f,0x0006,-2, 6,0x1010,acc, + 0,0,&xtensa_mask23,0,0,0) + XTREG(164,676, 4, 4, 4,0x2014,0x0006,-2, 6,0x1010,dbnum, + 0,0,&xtensa_mask24,0,0,0) + XTREG(165,680, 8, 4, 4,0x2015,0x0006,-2, 6,0x1010,asid3, + 0,0,&xtensa_mask25,0,0,0) + XTREG(166,684, 8, 4, 4,0x2016,0x0006,-2, 6,0x1010,asid2, + 0,0,&xtensa_mask26,0,0,0) + XTREG(167,688, 8, 4, 4,0x2017,0x0006,-2, 6,0x1010,asid1, + 0,0,&xtensa_mask27,0,0,0) + XTREG(168,692, 1, 4, 4,0x2018,0x0006,-2, 6,0x1010,instpgszid6, + 0,0,&xtensa_mask28,0,0,0) + XTREG(169,696, 1, 4, 4,0x2019,0x0006,-2, 6,0x1010,instpgszid5, + 0,0,&xtensa_mask29,0,0,0) + XTREG(170,700, 2, 4, 4,0x201a,0x0006,-2, 6,0x1010,instpgszid4, + 0,0,&xtensa_mask30,0,0,0) + XTREG(171,704, 1, 4, 4,0x201b,0x0006,-2, 6,0x1010,datapgszid6, + 0,0,&xtensa_mask31,0,0,0) + XTREG(172,708, 1, 4, 4,0x201c,0x0006,-2, 6,0x1010,datapgszid5, + 0,0,&xtensa_mask32,0,0,0) + XTREG(173,712, 2, 4, 4,0x201d,0x0006,-2, 6,0x1010,datapgszid4, + 0,0,&xtensa_mask33,0,0,0) + XTREG(174,716,10, 4, 4,0x201e,0x0006,-2, 6,0x1010,ptbase, + 0,0,&xtensa_mask34,0,0,0) + XTREG(175,720, 2, 4, 4,0x201f,0x0006, 0, 5,0x1010,roundmode, + 0,0,&xtensa_mask35,0,0,0) + XTREG(176,724, 1, 4, 4,0x2020,0x0006, 0, 5,0x1010,invalidenable, + 0,0,&xtensa_mask36,0,0,0) + XTREG(177,728, 1, 4, 4,0x2021,0x0006, 0, 5,0x1010,divzeroenable, + 0,0,&xtensa_mask37,0,0,0) + XTREG(178,732, 1, 4, 4,0x2022,0x0006, 0, 5,0x1010,overflowenable, + 0,0,&xtensa_mask38,0,0,0) + XTREG(179,736, 1, 4, 4,0x2023,0x0006, 0, 5,0x1010,underflowenable, + 0,0,&xtensa_mask39,0,0,0) + XTREG(180,740, 1, 4, 4,0x2024,0x0006, 0, 5,0x1010,inexactenable, + 0,0,&xtensa_mask40,0,0,0) + XTREG(181,744, 1, 4, 4,0x2025,0x0006, 0, 5,0x1010,invalidflag, + 0,0,&xtensa_mask41,0,0,0) + XTREG(182,748, 1, 4, 4,0x2026,0x0006, 0, 5,0x1010,divzeroflag, + 0,0,&xtensa_mask42,0,0,0) + XTREG(183,752, 1, 4, 4,0x2027,0x0006, 0, 5,0x1010,overflowflag, + 0,0,&xtensa_mask43,0,0,0) + XTREG(184,756, 1, 4, 4,0x2028,0x0006, 0, 5,0x1010,underflowflag, + 0,0,&xtensa_mask44,0,0,0) + XTREG(185,760, 1, 4, 4,0x2029,0x0006, 0, 5,0x1010,inexactflag, + 0,0,&xtensa_mask45,0,0,0) + XTREG(186,764,20, 4, 4,0x202a,0x0006, 0, 5,0x1010,fpreserved20, + 0,0,&xtensa_mask46,0,0,0) + XTREG(187,768,20, 4, 4,0x202b,0x0006, 0, 5,0x1010,fpreserved20a, + 0,0,&xtensa_mask47,0,0,0) + XTREG(188,772, 5, 4, 4,0x202c,0x0006, 0, 5,0x1010,fpreserved5, + 0,0,&xtensa_mask48,0,0,0) + XTREG_END diff --git a/target/xtensa/core-de233_fpu/xtensa-modules.c.inc b/target/xtensa/core-de233_fpu/xtensa-modules.c.inc new file mode 100644 index 0000000000000000000000000000000000000000..129c023514167e51ff667f30c3806d270de91f73 --- /dev/null +++ b/target/xtensa/core-de233_fpu/xtensa-modules.c.inc @@ -0,0 +1,20758 @@ +/* Xtensa configuration-specific ISA information. + + Copyright (c) 2003-2020 Tensilica Inc. + + 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 "xtensa-isa.h" +#include "xtensa-isa-internal.h" + + +/* Sysregs. */ + +static xtensa_sysreg_internal sysregs[] = { + { "LBEG", 0, 0 }, + { "LEND", 1, 0 }, + { "LCOUNT", 2, 0 }, + { "BR", 4, 0 }, + { "ACCLO", 16, 0 }, + { "ACCHI", 17, 0 }, + { "M0", 32, 0 }, + { "M1", 33, 0 }, + { "M2", 34, 0 }, + { "M3", 35, 0 }, + { "PTEVADDR", 83, 0 }, + { "MMID", 89, 0 }, + { "DDR", 104, 0 }, + { "CONFIGID0", 176, 0 }, + { "CONFIGID1", 208, 0 }, + { "INTERRUPT", 226, 0 }, + { "INTCLEAR", 227, 0 }, + { "CCOUNT", 234, 0 }, + { "PRID", 235, 0 }, + { "ICOUNT", 236, 0 }, + { "CCOMPARE0", 240, 0 }, + { "CCOMPARE1", 241, 0 }, + { "CCOMPARE2", 242, 0 }, + { "VECBASE", 231, 0 }, + { "EPC1", 177, 0 }, + { "EPC2", 178, 0 }, + { "EPC3", 179, 0 }, + { "EPC4", 180, 0 }, + { "EPC5", 181, 0 }, + { "EPC6", 182, 0 }, + { "EPC7", 183, 0 }, + { "EXCSAVE1", 209, 0 }, + { "EXCSAVE2", 210, 0 }, + { "EXCSAVE3", 211, 0 }, + { "EXCSAVE4", 212, 0 }, + { "EXCSAVE5", 213, 0 }, + { "EXCSAVE6", 214, 0 }, + { "EXCSAVE7", 215, 0 }, + { "EPS2", 194, 0 }, + { "EPS3", 195, 0 }, + { "EPS4", 196, 0 }, + { "EPS5", 197, 0 }, + { "EPS6", 198, 0 }, + { "EPS7", 199, 0 }, + { "EXCCAUSE", 232, 0 }, + { "DEPC", 192, 0 }, + { "EXCVADDR", 238, 0 }, + { "WINDOWBASE", 72, 0 }, + { "WINDOWSTART", 73, 0 }, + { "SAR", 3, 0 }, + { "PS", 230, 0 }, + { "MISC0", 244, 0 }, + { "MISC1", 245, 0 }, + { "INTENABLE", 228, 0 }, + { "DBREAKA0", 144, 0 }, + { "DBREAKC0", 160, 0 }, + { "DBREAKA1", 145, 0 }, + { "DBREAKC1", 161, 0 }, + { "IBREAKA0", 128, 0 }, + { "IBREAKA1", 129, 0 }, + { "IBREAKENABLE", 96, 0 }, + { "ICOUNTLEVEL", 237, 0 }, + { "DEBUGCAUSE", 233, 0 }, + { "RASID", 90, 0 }, + { "ITLBCFG", 91, 0 }, + { "DTLBCFG", 92, 0 }, + { "CPENABLE", 224, 0 }, + { "SCOMPARE1", 12, 0 }, + { "ATOMCTL", 99, 0 }, + { "ERACCESS", 95, 0 }, + { "THREADPTR", 231, 1 }, + { "FCR", 232, 1 }, + { "FSR", 233, 1 }, + { "EXPSTATE", 230, 1 } +}; + +#define NUM_SYSREGS 74 +#define MAX_SPECIAL_REG 245 +#define MAX_USER_REG 233 + + +/* Processor states. */ + +static xtensa_state_internal states[] = { + { "LCOUNT", 32, 0 }, + { "PC", 32, 0 }, + { "ICOUNT", 32, 0 }, + { "DDR", 32, 0 }, + { "INTERRUPT", 22, 0 }, + { "CCOUNT", 32, 0 }, + { "XTSYNC", 1, 0 }, + { "VECBASE", 22, 0 }, + { "EPC1", 32, 0 }, + { "EPC2", 32, 0 }, + { "EPC3", 32, 0 }, + { "EPC4", 32, 0 }, + { "EPC5", 32, 0 }, + { "EPC6", 32, 0 }, + { "EPC7", 32, 0 }, + { "EXCSAVE1", 32, 0 }, + { "EXCSAVE2", 32, 0 }, + { "EXCSAVE3", 32, 0 }, + { "EXCSAVE4", 32, 0 }, + { "EXCSAVE5", 32, 0 }, + { "EXCSAVE6", 32, 0 }, + { "EXCSAVE7", 32, 0 }, + { "EPS2", 15, 0 }, + { "EPS3", 15, 0 }, + { "EPS4", 15, 0 }, + { "EPS5", 15, 0 }, + { "EPS6", 15, 0 }, + { "EPS7", 15, 0 }, + { "EXCCAUSE", 6, 0 }, + { "PSINTLEVEL", 4, 0 }, + { "PSUM", 1, 0 }, + { "PSWOE", 1, 0 }, + { "PSRING", 2, 0 }, + { "PSEXCM", 1, 0 }, + { "DEPC", 32, 0 }, + { "EXCVADDR", 32, 0 }, + { "WindowBase", 3, 0 }, + { "WindowStart", 8, 0 }, + { "PSCALLINC", 2, 0 }, + { "PSOWB", 4, 0 }, + { "LBEG", 32, 0 }, + { "LEND", 32, 0 }, + { "SAR", 6, 0 }, + { "THREADPTR", 32, 0 }, + { "MISC0", 32, 0 }, + { "MISC1", 32, 0 }, + { "ACC", 40, 0 }, + { "InOCDMode", 1, 0 }, + { "INTENABLE", 22, 0 }, + { "DBREAKA0", 32, 0 }, + { "DBREAKC0", 8, 0 }, + { "DBREAKA1", 32, 0 }, + { "DBREAKC1", 8, 0 }, + { "IBREAKA0", 32, 0 }, + { "IBREAKA1", 32, 0 }, + { "IBREAKENABLE", 2, 0 }, + { "ICOUNTLEVEL", 4, 0 }, + { "DEBUGCAUSE", 6, 0 }, + { "DBNUM", 4, 0 }, + { "CCOMPARE0", 32, 0 }, + { "CCOMPARE1", 32, 0 }, + { "CCOMPARE2", 32, 0 }, + { "ASID3", 8, 0 }, + { "ASID2", 8, 0 }, + { "ASID1", 8, 0 }, + { "INSTPGSZID6", 1, 0 }, + { "INSTPGSZID5", 1, 0 }, + { "INSTPGSZID4", 2, 0 }, + { "DATAPGSZID6", 1, 0 }, + { "DATAPGSZID5", 1, 0 }, + { "DATAPGSZID4", 2, 0 }, + { "PTBASE", 10, 0 }, + { "CPENABLE", 8, 0 }, + { "SCOMPARE1", 32, 0 }, + { "ATOMCTL", 6, 0 }, + { "ERACCESS", 16, 0 }, + { "RoundMode", 2, 0 }, + { "InvalidEnable", 1, 0 }, + { "DivZeroEnable", 1, 0 }, + { "OverflowEnable", 1, 0 }, + { "UnderflowEnable", 1, 0 }, + { "InexactEnable", 1, 0 }, + { "InvalidFlag", 1, XTENSA_STATE_IS_SHARED_OR }, + { "DivZeroFlag", 1, XTENSA_STATE_IS_SHARED_OR }, + { "OverflowFlag", 1, XTENSA_STATE_IS_SHARED_OR }, + { "UnderflowFlag", 1, XTENSA_STATE_IS_SHARED_OR }, + { "InexactFlag", 1, XTENSA_STATE_IS_SHARED_OR }, + { "FPreserved20", 20, 0 }, + { "FPreserved20a", 20, 0 }, + { "FPreserved5", 5, 0 }, + { "FPreserved7", 7, 0 }, + { "EXPSTATE", 32, XTENSA_STATE_IS_EXPORTED } +}; + +#define NUM_STATES 92 + +enum xtensa_state_id { + STATE_LCOUNT, + STATE_PC, + STATE_ICOUNT, + STATE_DDR, + STATE_INTERRUPT, + STATE_CCOUNT, + STATE_XTSYNC, + STATE_VECBASE, + STATE_EPC1, + STATE_EPC2, + STATE_EPC3, + STATE_EPC4, + STATE_EPC5, + STATE_EPC6, + STATE_EPC7, + STATE_EXCSAVE1, + STATE_EXCSAVE2, + STATE_EXCSAVE3, + STATE_EXCSAVE4, + STATE_EXCSAVE5, + STATE_EXCSAVE6, + STATE_EXCSAVE7, + STATE_EPS2, + STATE_EPS3, + STATE_EPS4, + STATE_EPS5, + STATE_EPS6, + STATE_EPS7, + STATE_EXCCAUSE, + STATE_PSINTLEVEL, + STATE_PSUM, + STATE_PSWOE, + STATE_PSRING, + STATE_PSEXCM, + STATE_DEPC, + STATE_EXCVADDR, + STATE_WindowBase, + STATE_WindowStart, + STATE_PSCALLINC, + STATE_PSOWB, + STATE_LBEG, + STATE_LEND, + STATE_SAR, + STATE_THREADPTR, + STATE_MISC0, + STATE_MISC1, + STATE_ACC, + STATE_InOCDMode, + STATE_INTENABLE, + STATE_DBREAKA0, + STATE_DBREAKC0, + STATE_DBREAKA1, + STATE_DBREAKC1, + STATE_IBREAKA0, + STATE_IBREAKA1, + STATE_IBREAKENABLE, + STATE_ICOUNTLEVEL, + STATE_DEBUGCAUSE, + STATE_DBNUM, + STATE_CCOMPARE0, + STATE_CCOMPARE1, + STATE_CCOMPARE2, + STATE_ASID3, + STATE_ASID2, + STATE_ASID1, + STATE_INSTPGSZID6, + STATE_INSTPGSZID5, + STATE_INSTPGSZID4, + STATE_DATAPGSZID6, + STATE_DATAPGSZID5, + STATE_DATAPGSZID4, + STATE_PTBASE, + STATE_CPENABLE, + STATE_SCOMPARE1, + STATE_ATOMCTL, + STATE_ERACCESS, + STATE_RoundMode, + STATE_InvalidEnable, + STATE_DivZeroEnable, + STATE_OverflowEnable, + STATE_UnderflowEnable, + STATE_InexactEnable, + STATE_InvalidFlag, + STATE_DivZeroFlag, + STATE_OverflowFlag, + STATE_UnderflowFlag, + STATE_InexactFlag, + STATE_FPreserved20, + STATE_FPreserved20a, + STATE_FPreserved5, + STATE_FPreserved7, + STATE_EXPSTATE +}; + + +/* Field definitions. */ + +static unsigned +Field_t_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_t_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); +} + +static unsigned +Field_s_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_s_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_r_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_r_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_op2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + return tie_t; +} + +static void +Field_op2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_op1_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + return tie_t; +} + +static void +Field_op1_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_op0_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 28) >> 28); + return tie_t; +} + +static void +Field_op0_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf) | (tie_t << 0); +} + +static unsigned +Field_n_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_n_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_m_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_m_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_sr_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_sr_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_st_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_st_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_thi3_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 24) >> 29); + return tie_t; +} + +static void +Field_thi3_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe0) | (tie_t << 5); +} + +static unsigned +Field_t3_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_t3_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_tlo_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_tlo_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_w_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_w_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); +} + +static unsigned +Field_r3_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_r3_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_rhi_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_rhi_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_s3to1_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_s3to1_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); +} + +static unsigned +Field_op0_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 28) >> 28); + return tie_t; +} + +static void +Field_op0_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf) | (tie_t << 0); +} + +static unsigned +Field_t_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_t_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); +} + +static unsigned +Field_r_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_r_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_op0_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 28) >> 28); + return tie_t; +} + +static void +Field_op0_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf) | (tie_t << 0); +} + +static unsigned +Field_z_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_z_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); +} + +static unsigned +Field_i_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_i_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_s_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_s_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_t_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_t_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); +} + +static unsigned +Field_bbi4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + return tie_t; +} + +static void +Field_bbi4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_bbi_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_bbi_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_imm12_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 8) >> 20); + return tie_t; +} + +static void +Field_imm12_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0xfff000) | (tie_t << 12); +} + +static unsigned +Field_imm8_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 8) >> 24); + return tie_t; +} + +static void +Field_imm8_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0000) | (tie_t << 16); +} + +static unsigned +Field_s_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_s_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_s8_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_s8_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); +} + +static unsigned +Field_imms8_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 21) >> 29); + return tie_t; +} + +static void +Field_imms8_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x700) | (tie_t << 8); +} + +static unsigned +Field_imm12b_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 8) >> 24); + return tie_t; +} + +static void +Field_imm12b_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0000) | (tie_t << 16); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_imm16_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 16) | ((insn[0] << 8) >> 16); + return tie_t; +} + +static void +Field_imm16_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 16) >> 16; + insn[0] = (insn[0] & ~0xffff00) | (tie_t << 8); +} + +static unsigned +Field_offset_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 18) | ((insn[0] << 8) >> 14); + return tie_t; +} + +static void +Field_offset_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 14) >> 14; + insn[0] = (insn[0] & ~0xffffc0) | (tie_t << 6); +} + +static unsigned +Field_r_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_r_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_r_disp_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 17) >> 29); + return tie_t; +} + +static void +Field_r_disp_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x7000) | (tie_t << 12); +} + +static unsigned +Field_r_3_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_r_3_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_sa4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + return tie_t; +} + +static void +Field_sa4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_sae4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_sae4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); +} + +static unsigned +Field_sae_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_sae_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); +} + +static unsigned +Field_sal_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_sal_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_sargt_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_sargt_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_sas4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_sas4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); +} + +static unsigned +Field_sas_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_sas_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); +} + +static unsigned +Field_imm4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_mn_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_mn_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_i_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_i_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_imm6lo_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm6lo_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_imm6lo_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm6lo_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_imm6hi_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_imm6hi_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_imm6hi_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_imm6hi_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_imm7lo_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm7lo_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_imm7lo_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm7lo_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_imm7hi_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 25) >> 29); + return tie_t; +} + +static void +Field_imm7hi_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x70) | (tie_t << 4); +} + +static unsigned +Field_imm7hi_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 25) >> 29); + return tie_t; +} + +static void +Field_imm7hi_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x70) | (tie_t << 4); +} + +static unsigned +Field_z_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_z_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); +} + +static unsigned +Field_imm6_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm6_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_imm7_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 25) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm7_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x70) | (tie_t << 4); +} + +static unsigned +Field_rbit2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + return tie_t; +} + +static void +Field_rbit2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_tbit2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_tbit2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); +} + +static unsigned +Field_y_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_y_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); +} + +static unsigned +Field_x_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + return tie_t; +} + +static void +Field_x_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_t2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 24) >> 29); + return tie_t; +} + +static void +Field_t2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe0) | (tie_t << 5); +} + +static unsigned +Field_s2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_s2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); +} + +static unsigned +Field_r2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + return tie_t; +} + +static void +Field_r2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); +} + +static unsigned +Field_t4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_t4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_s4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_s4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_r4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_r4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_t8_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_t8_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_r8_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_r8_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_xt_wbr15_imm_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 15) | ((insn[0] << 8) >> 17); + return tie_t; +} + +static void +Field_xt_wbr15_imm_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 17) >> 17; + insn[0] = (insn[0] & ~0xfffe00) | (tie_t << 9); +} + +static unsigned +Field_xt_wbr18_imm_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 18) | ((insn[0] << 8) >> 14); + return tie_t; +} + +static void +Field_xt_wbr18_imm_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 14) >> 14; + insn[0] = (insn[0] & ~0xffffc0) | (tie_t << 6); +} + +static unsigned +Field_bitindex_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 23) >> 27); + return tie_t; +} + +static void +Field_bitindex_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x1f0) | (tie_t << 4); +} + +static void +Implicit_Field_set (xtensa_insnbuf insn ATTRIBUTE_UNUSED, + uint32 val ATTRIBUTE_UNUSED) +{ + /* Do nothing. */ +} + +static unsigned +Implicit_Field_ar0_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +static unsigned +Implicit_Field_ar4_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 4; +} + +static unsigned +Implicit_Field_ar8_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 8; +} + +static unsigned +Implicit_Field_ar12_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 12; +} + +static unsigned +Implicit_Field_mr0_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +static unsigned +Implicit_Field_mr1_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 1; +} + +static unsigned +Implicit_Field_mr2_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 2; +} + +static unsigned +Implicit_Field_mr3_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 3; +} + +static unsigned +Implicit_Field_bt16_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +static unsigned +Implicit_Field_bs16_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +static unsigned +Implicit_Field_br16_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +static unsigned +Implicit_Field_brall_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +enum xtensa_field_id { + FIELD_t, + FIELD_bbi4, + FIELD_bbi, + FIELD_imm12, + FIELD_imm8, + FIELD_s, + FIELD_s8, + FIELD_imms8, + FIELD_imm12b, + FIELD_imm16, + FIELD_m, + FIELD_n, + FIELD_offset, + FIELD_op0, + FIELD_op1, + FIELD_op2, + FIELD_r, + FIELD_r_disp, + FIELD_r_3, + FIELD_sa4, + FIELD_sae4, + FIELD_sae, + FIELD_sal, + FIELD_sargt, + FIELD_sas4, + FIELD_sas, + FIELD_sr, + FIELD_st, + FIELD_thi3, + FIELD_imm4, + FIELD_mn, + FIELD_i, + FIELD_imm6lo, + FIELD_imm6hi, + FIELD_imm7lo, + FIELD_imm7hi, + FIELD_z, + FIELD_imm6, + FIELD_imm7, + FIELD_r3, + FIELD_rbit2, + FIELD_rhi, + FIELD_t3, + FIELD_tbit2, + FIELD_tlo, + FIELD_w, + FIELD_y, + FIELD_x, + FIELD_t2, + FIELD_s2, + FIELD_r2, + FIELD_t4, + FIELD_s4, + FIELD_r4, + FIELD_t8, + FIELD_r8, + FIELD_xt_wbr15_imm, + FIELD_xt_wbr18_imm, + FIELD_bitindex, + FIELD_s3to1, + FIELD__ar0, + FIELD__ar4, + FIELD__ar8, + FIELD__ar12, + FIELD__mr0, + FIELD__mr1, + FIELD__mr2, + FIELD__mr3, + FIELD__bt16, + FIELD__bs16, + FIELD__br16, + FIELD__brall +}; + + +/* Functional units. */ + +static xtensa_funcUnit_internal funcUnits[] = { + {"XT_LOADSTORE_UNIT", 1} +}; + +enum xtensa_funcUnit_id { + FUNCUNIT_XT_LOADSTORE_UNIT +}; + + +/* Register files. */ + +enum xtensa_regfile_id { + REGFILE_AR, + REGFILE_MR, + REGFILE_BR, + REGFILE_FR, + REGFILE_BR2, + REGFILE_BR4, + REGFILE_BR8, + REGFILE_BR16 +}; + +static xtensa_regfile_internal regfiles[] = { + { "AR", "a", REGFILE_AR, 32, 32 }, + { "MR", "m", REGFILE_MR, 32, 4 }, + { "BR", "b", REGFILE_BR, 1, 16 }, + { "FR", "f", REGFILE_FR, 64, 16 }, + { "BR2", "b", REGFILE_BR, 2, 8 }, + { "BR4", "b", REGFILE_BR, 4, 4 }, + { "BR8", "b", REGFILE_BR, 8, 2 }, + { "BR16", "b", REGFILE_BR, 16, 1 } +}; + + +/* Interfaces. */ + +static xtensa_interface_internal interfaces[] = { + { "IMPWIRE", 32, 0, 0, 'i' } +}; + +enum xtensa_interface_id { + INTERFACE_IMPWIRE +}; + + +/* Constant tables. */ + +/* constant table ai4c */ +static const unsigned CONST_TBL_ai4c_0[] = { + 0xffffffff, + 0x1, + 0x2, + 0x3, + 0x4, + 0x5, + 0x6, + 0x7, + 0x8, + 0x9, + 0xa, + 0xb, + 0xc, + 0xd, + 0xe, + 0xf, + 0 +}; + +/* constant table b4c */ +static const unsigned CONST_TBL_b4c_0[] = { + 0xffffffff, + 0x1, + 0x2, + 0x3, + 0x4, + 0x5, + 0x6, + 0x7, + 0x8, + 0xa, + 0xc, + 0x10, + 0x20, + 0x40, + 0x80, + 0x100, + 0 +}; + +/* constant table b4cu */ +static const unsigned CONST_TBL_b4cu_0[] = { + 0x8000, + 0x10000, + 0x2, + 0x3, + 0x4, + 0x5, + 0x6, + 0x7, + 0x8, + 0xa, + 0xc, + 0x10, + 0x20, + 0x40, + 0x80, + 0x100, + 0 +}; + +/* constant table RECIP_Data8 */ +static const unsigned CONST_TBL_RECIP_Data8_0[] = { + 0xff & 0xff, + 0xfd & 0xff, + 0xfb & 0xff, + 0xf9 & 0xff, + 0xf7 & 0xff, + 0xf5 & 0xff, + 0xf4 & 0xff, + 0xf2 & 0xff, + 0xf0 & 0xff, + 0xee & 0xff, + 0xed & 0xff, + 0xeb & 0xff, + 0xe9 & 0xff, + 0xe8 & 0xff, + 0xe6 & 0xff, + 0xe4 & 0xff, + 0xe3 & 0xff, + 0xe1 & 0xff, + 0xe0 & 0xff, + 0xde & 0xff, + 0xdd & 0xff, + 0xdb & 0xff, + 0xda & 0xff, + 0xd8 & 0xff, + 0xd7 & 0xff, + 0xd5 & 0xff, + 0xd4 & 0xff, + 0xd3 & 0xff, + 0xd1 & 0xff, + 0xd0 & 0xff, + 0xcf & 0xff, + 0xcd & 0xff, + 0xcc & 0xff, + 0xcb & 0xff, + 0xca & 0xff, + 0xc8 & 0xff, + 0xc7 & 0xff, + 0xc6 & 0xff, + 0xc5 & 0xff, + 0xc4 & 0xff, + 0xc2 & 0xff, + 0xc1 & 0xff, + 0xc0 & 0xff, + 0xbf & 0xff, + 0xbe & 0xff, + 0xbd & 0xff, + 0xbc & 0xff, + 0xbb & 0xff, + 0xba & 0xff, + 0xb9 & 0xff, + 0xb8 & 0xff, + 0xb7 & 0xff, + 0xb6 & 0xff, + 0xb5 & 0xff, + 0xb4 & 0xff, + 0xb3 & 0xff, + 0xb2 & 0xff, + 0xb1 & 0xff, + 0xb0 & 0xff, + 0xaf & 0xff, + 0xae & 0xff, + 0xad & 0xff, + 0xac & 0xff, + 0xab & 0xff, + 0xaa & 0xff, + 0xa9 & 0xff, + 0xa8 & 0xff, + 0xa8 & 0xff, + 0xa7 & 0xff, + 0xa6 & 0xff, + 0xa5 & 0xff, + 0xa4 & 0xff, + 0xa3 & 0xff, + 0xa3 & 0xff, + 0xa2 & 0xff, + 0xa1 & 0xff, + 0xa0 & 0xff, + 0x9f & 0xff, + 0x9f & 0xff, + 0x9e & 0xff, + 0x9d & 0xff, + 0x9c & 0xff, + 0x9c & 0xff, + 0x9b & 0xff, + 0x9a & 0xff, + 0x99 & 0xff, + 0x99 & 0xff, + 0x98 & 0xff, + 0x97 & 0xff, + 0x97 & 0xff, + 0x96 & 0xff, + 0x95 & 0xff, + 0x95 & 0xff, + 0x94 & 0xff, + 0x93 & 0xff, + 0x93 & 0xff, + 0x92 & 0xff, + 0x91 & 0xff, + 0x91 & 0xff, + 0x90 & 0xff, + 0x8f & 0xff, + 0x8f & 0xff, + 0x8e & 0xff, + 0x8e & 0xff, + 0x8d & 0xff, + 0x8c & 0xff, + 0x8c & 0xff, + 0x8b & 0xff, + 0x8b & 0xff, + 0x8a & 0xff, + 0x89 & 0xff, + 0x89 & 0xff, + 0x88 & 0xff, + 0x88 & 0xff, + 0x87 & 0xff, + 0x87 & 0xff, + 0x86 & 0xff, + 0x85 & 0xff, + 0x85 & 0xff, + 0x84 & 0xff, + 0x84 & 0xff, + 0x83 & 0xff, + 0x83 & 0xff, + 0x82 & 0xff, + 0x82 & 0xff, + 0x81 & 0xff, + 0x81 & 0xff, + 0x81 & 0xff, + 0 +}; + +/* constant table RSQRT_Data8 */ +static const unsigned CONST_TBL_RSQRT_Data8_0[] = { + 0xb4 & 0xff, + 0xb3 & 0xff, + 0xb2 & 0xff, + 0xb0 & 0xff, + 0xaf & 0xff, + 0xae & 0xff, + 0xac & 0xff, + 0xab & 0xff, + 0xaa & 0xff, + 0xa9 & 0xff, + 0xa8 & 0xff, + 0xa7 & 0xff, + 0xa6 & 0xff, + 0xa5 & 0xff, + 0xa3 & 0xff, + 0xa2 & 0xff, + 0xa1 & 0xff, + 0xa0 & 0xff, + 0x9f & 0xff, + 0x9e & 0xff, + 0x9e & 0xff, + 0x9d & 0xff, + 0x9c & 0xff, + 0x9b & 0xff, + 0x9a & 0xff, + 0x99 & 0xff, + 0x98 & 0xff, + 0x97 & 0xff, + 0x97 & 0xff, + 0x96 & 0xff, + 0x95 & 0xff, + 0x94 & 0xff, + 0x93 & 0xff, + 0x93 & 0xff, + 0x92 & 0xff, + 0x91 & 0xff, + 0x90 & 0xff, + 0x90 & 0xff, + 0x8f & 0xff, + 0x8e & 0xff, + 0x8e & 0xff, + 0x8d & 0xff, + 0x8c & 0xff, + 0x8c & 0xff, + 0x8b & 0xff, + 0x8a & 0xff, + 0x8a & 0xff, + 0x89 & 0xff, + 0x89 & 0xff, + 0x88 & 0xff, + 0x87 & 0xff, + 0x87 & 0xff, + 0x86 & 0xff, + 0x86 & 0xff, + 0x85 & 0xff, + 0x84 & 0xff, + 0x84 & 0xff, + 0x83 & 0xff, + 0x83 & 0xff, + 0x82 & 0xff, + 0x82 & 0xff, + 0x81 & 0xff, + 0x81 & 0xff, + 0x80 & 0xff, + 0xff & 0xff, + 0xfd & 0xff, + 0xfb & 0xff, + 0xf9 & 0xff, + 0xf7 & 0xff, + 0xf6 & 0xff, + 0xf4 & 0xff, + 0xf2 & 0xff, + 0xf1 & 0xff, + 0xef & 0xff, + 0xed & 0xff, + 0xec & 0xff, + 0xea & 0xff, + 0xe9 & 0xff, + 0xe7 & 0xff, + 0xe6 & 0xff, + 0xe4 & 0xff, + 0xe3 & 0xff, + 0xe1 & 0xff, + 0xe0 & 0xff, + 0xdf & 0xff, + 0xdd & 0xff, + 0xdc & 0xff, + 0xdb & 0xff, + 0xda & 0xff, + 0xd8 & 0xff, + 0xd7 & 0xff, + 0xd6 & 0xff, + 0xd5 & 0xff, + 0xd4 & 0xff, + 0xd3 & 0xff, + 0xd2 & 0xff, + 0xd0 & 0xff, + 0xcf & 0xff, + 0xce & 0xff, + 0xcd & 0xff, + 0xcc & 0xff, + 0xcb & 0xff, + 0xca & 0xff, + 0xc9 & 0xff, + 0xc8 & 0xff, + 0xc7 & 0xff, + 0xc6 & 0xff, + 0xc6 & 0xff, + 0xc5 & 0xff, + 0xc4 & 0xff, + 0xc3 & 0xff, + 0xc2 & 0xff, + 0xc1 & 0xff, + 0xc0 & 0xff, + 0xbf & 0xff, + 0xbf & 0xff, + 0xbe & 0xff, + 0xbd & 0xff, + 0xbc & 0xff, + 0xbb & 0xff, + 0xbb & 0xff, + 0xba & 0xff, + 0xb9 & 0xff, + 0xb8 & 0xff, + 0xb8 & 0xff, + 0xb7 & 0xff, + 0xb6 & 0xff, + 0xb5 & 0xff, + 0 +}; + +/* constant table RECIP_Data10_2 */ +static const unsigned CONST_TBL_RECIP_Data10_2_0[] = { + 0x3fc & 0x3ff, + 0x3f4 & 0x3ff, + 0x3ec & 0x3ff, + 0x3e5 & 0x3ff, + 0x3dd & 0x3ff, + 0x3d6 & 0x3ff, + 0x3cf & 0x3ff, + 0x3c7 & 0x3ff, + 0x3c0 & 0x3ff, + 0x3b9 & 0x3ff, + 0x3b2 & 0x3ff, + 0x3ac & 0x3ff, + 0x3a5 & 0x3ff, + 0x39e & 0x3ff, + 0x398 & 0x3ff, + 0x391 & 0x3ff, + 0x38b & 0x3ff, + 0x385 & 0x3ff, + 0x37f & 0x3ff, + 0x378 & 0x3ff, + 0x373 & 0x3ff, + 0x36c & 0x3ff, + 0x367 & 0x3ff, + 0x361 & 0x3ff, + 0x35c & 0x3ff, + 0x356 & 0x3ff, + 0x350 & 0x3ff, + 0x34b & 0x3ff, + 0x345 & 0x3ff, + 0x340 & 0x3ff, + 0x33b & 0x3ff, + 0x335 & 0x3ff, + 0x330 & 0x3ff, + 0x32c & 0x3ff, + 0x327 & 0x3ff, + 0x322 & 0x3ff, + 0x31c & 0x3ff, + 0x318 & 0x3ff, + 0x314 & 0x3ff, + 0x30e & 0x3ff, + 0x30a & 0x3ff, + 0x306 & 0x3ff, + 0x300 & 0x3ff, + 0x2fc & 0x3ff, + 0x2f8 & 0x3ff, + 0x2f4 & 0x3ff, + 0x2f0 & 0x3ff, + 0x2ea & 0x3ff, + 0x2e6 & 0x3ff, + 0x2e2 & 0x3ff, + 0x2de & 0x3ff, + 0x2da & 0x3ff, + 0x2d6 & 0x3ff, + 0x2d2 & 0x3ff, + 0x2ce & 0x3ff, + 0x2ca & 0x3ff, + 0x2c6 & 0x3ff, + 0x2c2 & 0x3ff, + 0x2be & 0x3ff, + 0x2ba & 0x3ff, + 0x2b8 & 0x3ff, + 0x2b4 & 0x3ff, + 0x2b0 & 0x3ff, + 0x2ac & 0x3ff, + 0x2a8 & 0x3ff, + 0x2a6 & 0x3ff, + 0x2a2 & 0x3ff, + 0x29e & 0x3ff, + 0x29c & 0x3ff, + 0x298 & 0x3ff, + 0x294 & 0x3ff, + 0x290 & 0x3ff, + 0x28e & 0x3ff, + 0x28a & 0x3ff, + 0x288 & 0x3ff, + 0x284 & 0x3ff, + 0x280 & 0x3ff, + 0x27e & 0x3ff, + 0x27a & 0x3ff, + 0x278 & 0x3ff, + 0x274 & 0x3ff, + 0x272 & 0x3ff, + 0x26e & 0x3ff, + 0x26c & 0x3ff, + 0x268 & 0x3ff, + 0x266 & 0x3ff, + 0x264 & 0x3ff, + 0x260 & 0x3ff, + 0x25e & 0x3ff, + 0x25a & 0x3ff, + 0x258 & 0x3ff, + 0x254 & 0x3ff, + 0x252 & 0x3ff, + 0x250 & 0x3ff, + 0x24c & 0x3ff, + 0x24a & 0x3ff, + 0x248 & 0x3ff, + 0x246 & 0x3ff, + 0x242 & 0x3ff, + 0x240 & 0x3ff, + 0x23e & 0x3ff, + 0x23c & 0x3ff, + 0x238 & 0x3ff, + 0x236 & 0x3ff, + 0x234 & 0x3ff, + 0x232 & 0x3ff, + 0x230 & 0x3ff, + 0x22c & 0x3ff, + 0x22a & 0x3ff, + 0x228 & 0x3ff, + 0x226 & 0x3ff, + 0x224 & 0x3ff, + 0x220 & 0x3ff, + 0x21e & 0x3ff, + 0x21c & 0x3ff, + 0x21a & 0x3ff, + 0x218 & 0x3ff, + 0x216 & 0x3ff, + 0x214 & 0x3ff, + 0x212 & 0x3ff, + 0x210 & 0x3ff, + 0x20e & 0x3ff, + 0x20c & 0x3ff, + 0x208 & 0x3ff, + 0x208 & 0x3ff, + 0x204 & 0x3ff, + 0x204 & 0x3ff, + 0x201 & 0x3ff, + 0 +}; + +/* constant table RSQRT_10b_256 */ +static const unsigned CONST_TBL_RSQRT_10b_256_0[] = { + 0x1a5 & 0x3ff, + 0x1a0 & 0x3ff, + 0x19a & 0x3ff, + 0x195 & 0x3ff, + 0x18f & 0x3ff, + 0x18a & 0x3ff, + 0x185 & 0x3ff, + 0x180 & 0x3ff, + 0x17a & 0x3ff, + 0x175 & 0x3ff, + 0x170 & 0x3ff, + 0x16b & 0x3ff, + 0x166 & 0x3ff, + 0x161 & 0x3ff, + 0x15d & 0x3ff, + 0x158 & 0x3ff, + 0x153 & 0x3ff, + 0x14e & 0x3ff, + 0x14a & 0x3ff, + 0x145 & 0x3ff, + 0x140 & 0x3ff, + 0x13c & 0x3ff, + 0x138 & 0x3ff, + 0x133 & 0x3ff, + 0x12f & 0x3ff, + 0x12a & 0x3ff, + 0x126 & 0x3ff, + 0x122 & 0x3ff, + 0x11e & 0x3ff, + 0x11a & 0x3ff, + 0x115 & 0x3ff, + 0x111 & 0x3ff, + 0x10d & 0x3ff, + 0x109 & 0x3ff, + 0x105 & 0x3ff, + 0x101 & 0x3ff, + 0xfd & 0x3ff, + 0xfa & 0x3ff, + 0xf6 & 0x3ff, + 0xf2 & 0x3ff, + 0xee & 0x3ff, + 0xea & 0x3ff, + 0xe7 & 0x3ff, + 0xe3 & 0x3ff, + 0xdf & 0x3ff, + 0xdc & 0x3ff, + 0xd8 & 0x3ff, + 0xd5 & 0x3ff, + 0xd1 & 0x3ff, + 0xce & 0x3ff, + 0xca & 0x3ff, + 0xc7 & 0x3ff, + 0xc3 & 0x3ff, + 0xc0 & 0x3ff, + 0xbd & 0x3ff, + 0xb9 & 0x3ff, + 0xb6 & 0x3ff, + 0xb3 & 0x3ff, + 0xb0 & 0x3ff, + 0xad & 0x3ff, + 0xa9 & 0x3ff, + 0xa6 & 0x3ff, + 0xa3 & 0x3ff, + 0xa0 & 0x3ff, + 0x9d & 0x3ff, + 0x9a & 0x3ff, + 0x97 & 0x3ff, + 0x94 & 0x3ff, + 0x91 & 0x3ff, + 0x8e & 0x3ff, + 0x8b & 0x3ff, + 0x88 & 0x3ff, + 0x85 & 0x3ff, + 0x82 & 0x3ff, + 0x7f & 0x3ff, + 0x7d & 0x3ff, + 0x7a & 0x3ff, + 0x77 & 0x3ff, + 0x74 & 0x3ff, + 0x71 & 0x3ff, + 0x6f & 0x3ff, + 0x6c & 0x3ff, + 0x69 & 0x3ff, + 0x67 & 0x3ff, + 0x64 & 0x3ff, + 0x61 & 0x3ff, + 0x5f & 0x3ff, + 0x5c & 0x3ff, + 0x5a & 0x3ff, + 0x57 & 0x3ff, + 0x54 & 0x3ff, + 0x52 & 0x3ff, + 0x4f & 0x3ff, + 0x4d & 0x3ff, + 0x4a & 0x3ff, + 0x48 & 0x3ff, + 0x45 & 0x3ff, + 0x43 & 0x3ff, + 0x41 & 0x3ff, + 0x3e & 0x3ff, + 0x3c & 0x3ff, + 0x3a & 0x3ff, + 0x37 & 0x3ff, + 0x35 & 0x3ff, + 0x33 & 0x3ff, + 0x30 & 0x3ff, + 0x2e & 0x3ff, + 0x2c & 0x3ff, + 0x29 & 0x3ff, + 0x27 & 0x3ff, + 0x25 & 0x3ff, + 0x23 & 0x3ff, + 0x20 & 0x3ff, + 0x1e & 0x3ff, + 0x1c & 0x3ff, + 0x1a & 0x3ff, + 0x18 & 0x3ff, + 0x16 & 0x3ff, + 0x14 & 0x3ff, + 0x11 & 0x3ff, + 0xf & 0x3ff, + 0xd & 0x3ff, + 0xb & 0x3ff, + 0x9 & 0x3ff, + 0x7 & 0x3ff, + 0x5 & 0x3ff, + 0x3 & 0x3ff, + 0x1 & 0x3ff, + 0x3fc & 0x3ff, + 0x3f4 & 0x3ff, + 0x3ec & 0x3ff, + 0x3e5 & 0x3ff, + 0x3dd & 0x3ff, + 0x3d5 & 0x3ff, + 0x3ce & 0x3ff, + 0x3c7 & 0x3ff, + 0x3bf & 0x3ff, + 0x3b8 & 0x3ff, + 0x3b1 & 0x3ff, + 0x3aa & 0x3ff, + 0x3a3 & 0x3ff, + 0x39c & 0x3ff, + 0x395 & 0x3ff, + 0x38e & 0x3ff, + 0x388 & 0x3ff, + 0x381 & 0x3ff, + 0x37a & 0x3ff, + 0x374 & 0x3ff, + 0x36d & 0x3ff, + 0x367 & 0x3ff, + 0x361 & 0x3ff, + 0x35a & 0x3ff, + 0x354 & 0x3ff, + 0x34e & 0x3ff, + 0x348 & 0x3ff, + 0x342 & 0x3ff, + 0x33c & 0x3ff, + 0x336 & 0x3ff, + 0x330 & 0x3ff, + 0x32b & 0x3ff, + 0x325 & 0x3ff, + 0x31f & 0x3ff, + 0x31a & 0x3ff, + 0x314 & 0x3ff, + 0x30f & 0x3ff, + 0x309 & 0x3ff, + 0x304 & 0x3ff, + 0x2fe & 0x3ff, + 0x2f9 & 0x3ff, + 0x2f4 & 0x3ff, + 0x2ee & 0x3ff, + 0x2e9 & 0x3ff, + 0x2e4 & 0x3ff, + 0x2df & 0x3ff, + 0x2da & 0x3ff, + 0x2d5 & 0x3ff, + 0x2d0 & 0x3ff, + 0x2cb & 0x3ff, + 0x2c6 & 0x3ff, + 0x2c1 & 0x3ff, + 0x2bd & 0x3ff, + 0x2b8 & 0x3ff, + 0x2b3 & 0x3ff, + 0x2ae & 0x3ff, + 0x2aa & 0x3ff, + 0x2a5 & 0x3ff, + 0x2a1 & 0x3ff, + 0x29c & 0x3ff, + 0x298 & 0x3ff, + 0x293 & 0x3ff, + 0x28f & 0x3ff, + 0x28a & 0x3ff, + 0x286 & 0x3ff, + 0x282 & 0x3ff, + 0x27d & 0x3ff, + 0x279 & 0x3ff, + 0x275 & 0x3ff, + 0x271 & 0x3ff, + 0x26d & 0x3ff, + 0x268 & 0x3ff, + 0x264 & 0x3ff, + 0x260 & 0x3ff, + 0x25c & 0x3ff, + 0x258 & 0x3ff, + 0x254 & 0x3ff, + 0x250 & 0x3ff, + 0x24c & 0x3ff, + 0x249 & 0x3ff, + 0x245 & 0x3ff, + 0x241 & 0x3ff, + 0x23d & 0x3ff, + 0x239 & 0x3ff, + 0x235 & 0x3ff, + 0x232 & 0x3ff, + 0x22e & 0x3ff, + 0x22a & 0x3ff, + 0x227 & 0x3ff, + 0x223 & 0x3ff, + 0x220 & 0x3ff, + 0x21c & 0x3ff, + 0x218 & 0x3ff, + 0x215 & 0x3ff, + 0x211 & 0x3ff, + 0x20e & 0x3ff, + 0x20a & 0x3ff, + 0x207 & 0x3ff, + 0x204 & 0x3ff, + 0x200 & 0x3ff, + 0x1fd & 0x3ff, + 0x1f9 & 0x3ff, + 0x1f6 & 0x3ff, + 0x1f3 & 0x3ff, + 0x1f0 & 0x3ff, + 0x1ec & 0x3ff, + 0x1e9 & 0x3ff, + 0x1e6 & 0x3ff, + 0x1e3 & 0x3ff, + 0x1df & 0x3ff, + 0x1dc & 0x3ff, + 0x1d9 & 0x3ff, + 0x1d6 & 0x3ff, + 0x1d3 & 0x3ff, + 0x1d0 & 0x3ff, + 0x1cd & 0x3ff, + 0x1ca & 0x3ff, + 0x1c7 & 0x3ff, + 0x1c4 & 0x3ff, + 0x1c1 & 0x3ff, + 0x1be & 0x3ff, + 0x1bb & 0x3ff, + 0x1b8 & 0x3ff, + 0x1b5 & 0x3ff, + 0x1b2 & 0x3ff, + 0x1af & 0x3ff, + 0x1ac & 0x3ff, + 0x1aa & 0x3ff, + 0 +}; + +/* constant table RECIP_10b_256 */ +static const unsigned CONST_TBL_RECIP_10b_256_0[] = { + 0x3fc & 0x3ff, + 0x3f4 & 0x3ff, + 0x3ec & 0x3ff, + 0x3e4 & 0x3ff, + 0x3dd & 0x3ff, + 0x3d5 & 0x3ff, + 0x3cd & 0x3ff, + 0x3c6 & 0x3ff, + 0x3be & 0x3ff, + 0x3b7 & 0x3ff, + 0x3af & 0x3ff, + 0x3a8 & 0x3ff, + 0x3a1 & 0x3ff, + 0x399 & 0x3ff, + 0x392 & 0x3ff, + 0x38b & 0x3ff, + 0x384 & 0x3ff, + 0x37d & 0x3ff, + 0x376 & 0x3ff, + 0x36f & 0x3ff, + 0x368 & 0x3ff, + 0x361 & 0x3ff, + 0x35b & 0x3ff, + 0x354 & 0x3ff, + 0x34d & 0x3ff, + 0x346 & 0x3ff, + 0x340 & 0x3ff, + 0x339 & 0x3ff, + 0x333 & 0x3ff, + 0x32c & 0x3ff, + 0x326 & 0x3ff, + 0x320 & 0x3ff, + 0x319 & 0x3ff, + 0x313 & 0x3ff, + 0x30d & 0x3ff, + 0x307 & 0x3ff, + 0x300 & 0x3ff, + 0x2fa & 0x3ff, + 0x2f4 & 0x3ff, + 0x2ee & 0x3ff, + 0x2e8 & 0x3ff, + 0x2e2 & 0x3ff, + 0x2dc & 0x3ff, + 0x2d7 & 0x3ff, + 0x2d1 & 0x3ff, + 0x2cb & 0x3ff, + 0x2c5 & 0x3ff, + 0x2bf & 0x3ff, + 0x2ba & 0x3ff, + 0x2b4 & 0x3ff, + 0x2af & 0x3ff, + 0x2a9 & 0x3ff, + 0x2a3 & 0x3ff, + 0x29e & 0x3ff, + 0x299 & 0x3ff, + 0x293 & 0x3ff, + 0x28e & 0x3ff, + 0x288 & 0x3ff, + 0x283 & 0x3ff, + 0x27e & 0x3ff, + 0x279 & 0x3ff, + 0x273 & 0x3ff, + 0x26e & 0x3ff, + 0x269 & 0x3ff, + 0x264 & 0x3ff, + 0x25f & 0x3ff, + 0x25a & 0x3ff, + 0x255 & 0x3ff, + 0x250 & 0x3ff, + 0x24b & 0x3ff, + 0x246 & 0x3ff, + 0x241 & 0x3ff, + 0x23c & 0x3ff, + 0x237 & 0x3ff, + 0x232 & 0x3ff, + 0x22e & 0x3ff, + 0x229 & 0x3ff, + 0x224 & 0x3ff, + 0x21f & 0x3ff, + 0x21b & 0x3ff, + 0x216 & 0x3ff, + 0x211 & 0x3ff, + 0x20d & 0x3ff, + 0x208 & 0x3ff, + 0x204 & 0x3ff, + 0x1ff & 0x3ff, + 0x1fb & 0x3ff, + 0x1f6 & 0x3ff, + 0x1f2 & 0x3ff, + 0x1ed & 0x3ff, + 0x1e9 & 0x3ff, + 0x1e5 & 0x3ff, + 0x1e0 & 0x3ff, + 0x1dc & 0x3ff, + 0x1d8 & 0x3ff, + 0x1d4 & 0x3ff, + 0x1cf & 0x3ff, + 0x1cb & 0x3ff, + 0x1c7 & 0x3ff, + 0x1c3 & 0x3ff, + 0x1bf & 0x3ff, + 0x1bb & 0x3ff, + 0x1b6 & 0x3ff, + 0x1b2 & 0x3ff, + 0x1ae & 0x3ff, + 0x1aa & 0x3ff, + 0x1a6 & 0x3ff, + 0x1a2 & 0x3ff, + 0x19e & 0x3ff, + 0x19a & 0x3ff, + 0x197 & 0x3ff, + 0x193 & 0x3ff, + 0x18f & 0x3ff, + 0x18b & 0x3ff, + 0x187 & 0x3ff, + 0x183 & 0x3ff, + 0x17f & 0x3ff, + 0x17c & 0x3ff, + 0x178 & 0x3ff, + 0x174 & 0x3ff, + 0x171 & 0x3ff, + 0x16d & 0x3ff, + 0x169 & 0x3ff, + 0x166 & 0x3ff, + 0x162 & 0x3ff, + 0x15e & 0x3ff, + 0x15b & 0x3ff, + 0x157 & 0x3ff, + 0x154 & 0x3ff, + 0x150 & 0x3ff, + 0x14d & 0x3ff, + 0x149 & 0x3ff, + 0x146 & 0x3ff, + 0x142 & 0x3ff, + 0x13f & 0x3ff, + 0x13b & 0x3ff, + 0x138 & 0x3ff, + 0x134 & 0x3ff, + 0x131 & 0x3ff, + 0x12e & 0x3ff, + 0x12a & 0x3ff, + 0x127 & 0x3ff, + 0x124 & 0x3ff, + 0x120 & 0x3ff, + 0x11d & 0x3ff, + 0x11a & 0x3ff, + 0x117 & 0x3ff, + 0x113 & 0x3ff, + 0x110 & 0x3ff, + 0x10d & 0x3ff, + 0x10a & 0x3ff, + 0x107 & 0x3ff, + 0x103 & 0x3ff, + 0x100 & 0x3ff, + 0xfd & 0x3ff, + 0xfa & 0x3ff, + 0xf7 & 0x3ff, + 0xf4 & 0x3ff, + 0xf1 & 0x3ff, + 0xee & 0x3ff, + 0xeb & 0x3ff, + 0xe8 & 0x3ff, + 0xe5 & 0x3ff, + 0xe2 & 0x3ff, + 0xdf & 0x3ff, + 0xdc & 0x3ff, + 0xd9 & 0x3ff, + 0xd6 & 0x3ff, + 0xd3 & 0x3ff, + 0xd0 & 0x3ff, + 0xcd & 0x3ff, + 0xca & 0x3ff, + 0xc8 & 0x3ff, + 0xc5 & 0x3ff, + 0xc2 & 0x3ff, + 0xbf & 0x3ff, + 0xbc & 0x3ff, + 0xb9 & 0x3ff, + 0xb7 & 0x3ff, + 0xb4 & 0x3ff, + 0xb1 & 0x3ff, + 0xae & 0x3ff, + 0xac & 0x3ff, + 0xa9 & 0x3ff, + 0xa6 & 0x3ff, + 0xa4 & 0x3ff, + 0xa1 & 0x3ff, + 0x9e & 0x3ff, + 0x9c & 0x3ff, + 0x99 & 0x3ff, + 0x96 & 0x3ff, + 0x94 & 0x3ff, + 0x91 & 0x3ff, + 0x8e & 0x3ff, + 0x8c & 0x3ff, + 0x89 & 0x3ff, + 0x87 & 0x3ff, + 0x84 & 0x3ff, + 0x82 & 0x3ff, + 0x7f & 0x3ff, + 0x7c & 0x3ff, + 0x7a & 0x3ff, + 0x77 & 0x3ff, + 0x75 & 0x3ff, + 0x73 & 0x3ff, + 0x70 & 0x3ff, + 0x6e & 0x3ff, + 0x6b & 0x3ff, + 0x69 & 0x3ff, + 0x66 & 0x3ff, + 0x64 & 0x3ff, + 0x61 & 0x3ff, + 0x5f & 0x3ff, + 0x5d & 0x3ff, + 0x5a & 0x3ff, + 0x58 & 0x3ff, + 0x56 & 0x3ff, + 0x53 & 0x3ff, + 0x51 & 0x3ff, + 0x4f & 0x3ff, + 0x4c & 0x3ff, + 0x4a & 0x3ff, + 0x48 & 0x3ff, + 0x45 & 0x3ff, + 0x43 & 0x3ff, + 0x41 & 0x3ff, + 0x3f & 0x3ff, + 0x3c & 0x3ff, + 0x3a & 0x3ff, + 0x38 & 0x3ff, + 0x36 & 0x3ff, + 0x33 & 0x3ff, + 0x31 & 0x3ff, + 0x2f & 0x3ff, + 0x2d & 0x3ff, + 0x2b & 0x3ff, + 0x29 & 0x3ff, + 0x26 & 0x3ff, + 0x24 & 0x3ff, + 0x22 & 0x3ff, + 0x20 & 0x3ff, + 0x1e & 0x3ff, + 0x1c & 0x3ff, + 0x1a & 0x3ff, + 0x18 & 0x3ff, + 0x15 & 0x3ff, + 0x13 & 0x3ff, + 0x11 & 0x3ff, + 0xf & 0x3ff, + 0xd & 0x3ff, + 0xb & 0x3ff, + 0x9 & 0x3ff, + 0x7 & 0x3ff, + 0x5 & 0x3ff, + 0x3 & 0x3ff, + 0x1 & 0x3ff, + 0 +}; + + +/* Instruction operands. */ + +static int +OperandSem_opnd_sem_MR_0_decode (uint32 *valp) +{ + *valp += 2; + return 0; +} + +static int +OperandSem_opnd_sem_MR_0_encode (uint32 *valp) +{ + int error; + error = ((*valp & ~0x3) != 0) || ((*valp & 0x2) == 0); + *valp = *valp & 1; + return error; +} + +static int +OperandSem_opnd_sem_soffsetx4_decode (uint32 *valp) +{ + unsigned soffsetx4_out_0; + unsigned soffsetx4_in_0; + soffsetx4_in_0 = *valp & 0x3ffff; + soffsetx4_out_0 = 0x4 + ((((int) soffsetx4_in_0 << 14) >> 14) << 2); + *valp = soffsetx4_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_soffsetx4_encode (uint32 *valp) +{ + unsigned soffsetx4_in_0; + unsigned soffsetx4_out_0; + soffsetx4_out_0 = *valp; + soffsetx4_in_0 = ((soffsetx4_out_0 - 0x4) >> 2) & 0x3ffff; + *valp = soffsetx4_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_immr_decode (uint32 *valp) +{ + unsigned immr_out_0; + unsigned immr_in_0; + immr_in_0 = *valp & 0xf; + immr_out_0 = immr_in_0; + *valp = immr_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_immr_encode (uint32 *valp) +{ + unsigned immr_in_0; + unsigned immr_out_0; + immr_out_0 = *valp; + immr_in_0 = (immr_out_0 & 0xf); + *valp = immr_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm12x8_decode (uint32 *valp) +{ + unsigned uimm12x8_out_0; + unsigned uimm12x8_in_0; + uimm12x8_in_0 = *valp & 0xfff; + uimm12x8_out_0 = uimm12x8_in_0 << 3; + *valp = uimm12x8_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm12x8_encode (uint32 *valp) +{ + unsigned uimm12x8_in_0; + unsigned uimm12x8_out_0; + uimm12x8_out_0 = *valp; + uimm12x8_in_0 = ((uimm12x8_out_0 >> 3) & 0xfff); + *valp = uimm12x8_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm4_decode (uint32 *valp) +{ + unsigned simm4_out_0; + unsigned simm4_in_0; + simm4_in_0 = *valp & 0xf; + simm4_out_0 = ((int) simm4_in_0 << 28) >> 28; + *valp = simm4_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm4_encode (uint32 *valp) +{ + unsigned simm4_in_0; + unsigned simm4_out_0; + simm4_out_0 = *valp; + simm4_in_0 = (simm4_out_0 & 0xf); + *valp = simm4_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_AR_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_AR_encode (uint32 *valp) +{ + int error; + error = (*valp >= 32); + return error; +} + +static int +OperandSem_opnd_sem_AR_0_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_AR_0_encode (uint32 *valp) +{ + int error; + error = (*valp >= 32); + return error; +} + +static int +OperandSem_opnd_sem_AR_4_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_AR_4_encode (uint32 *valp) +{ + int error; + error = (*valp >= 32); + return error; +} + +static int +OperandSem_opnd_sem_AR_8_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_AR_8_encode (uint32 *valp) +{ + int error; + error = (*valp >= 32); + return error; +} + +static int +OperandSem_opnd_sem_AR_12_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_AR_12_encode (uint32 *valp) +{ + int error; + error = (*valp >= 32); + return error; +} + +static int +OperandSem_opnd_sem_AR_entry_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_AR_entry_encode (uint32 *valp) +{ + int error; + error = (*valp >= 32); + return error; +} + +static int +OperandSem_opnd_sem_immrx4_decode (uint32 *valp) +{ + unsigned immrx4_out_0; + unsigned immrx4_in_0; + immrx4_in_0 = *valp & 0xf; + immrx4_out_0 = (((0xfffffff) << 4) | immrx4_in_0) << 2; + *valp = immrx4_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_immrx4_encode (uint32 *valp) +{ + unsigned immrx4_in_0; + unsigned immrx4_out_0; + immrx4_out_0 = *valp; + immrx4_in_0 = ((immrx4_out_0 >> 2) & 0xf); + *valp = immrx4_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_lsi4x4_decode (uint32 *valp) +{ + unsigned lsi4x4_out_0; + unsigned lsi4x4_in_0; + lsi4x4_in_0 = *valp & 0xf; + lsi4x4_out_0 = lsi4x4_in_0 << 2; + *valp = lsi4x4_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_lsi4x4_encode (uint32 *valp) +{ + unsigned lsi4x4_in_0; + unsigned lsi4x4_out_0; + lsi4x4_out_0 = *valp; + lsi4x4_in_0 = ((lsi4x4_out_0 >> 2) & 0xf); + *valp = lsi4x4_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm7_decode (uint32 *valp) +{ + unsigned simm7_out_0; + unsigned simm7_in_0; + simm7_in_0 = *valp & 0x7f; + simm7_out_0 = ((((-((((simm7_in_0 >> 6) & 1)) & (((simm7_in_0 >> 5) & 1)))) & 0x1ffffff)) << 7) | simm7_in_0; + *valp = simm7_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm7_encode (uint32 *valp) +{ + unsigned simm7_in_0; + unsigned simm7_out_0; + simm7_out_0 = *valp; + simm7_in_0 = (simm7_out_0 & 0x7f); + *valp = simm7_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm6_decode (uint32 *valp) +{ + unsigned uimm6_out_0; + unsigned uimm6_in_0; + uimm6_in_0 = *valp & 0x3f; + uimm6_out_0 = 0x4 + (((0) << 6) | uimm6_in_0); + *valp = uimm6_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm6_encode (uint32 *valp) +{ + unsigned uimm6_in_0; + unsigned uimm6_out_0; + uimm6_out_0 = *valp; + uimm6_in_0 = (uimm6_out_0 - 0x4) & 0x3f; + *valp = uimm6_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_ai4const_decode (uint32 *valp) +{ + unsigned ai4const_out_0; + unsigned ai4const_in_0; + ai4const_in_0 = *valp & 0xf; + ai4const_out_0 = CONST_TBL_ai4c_0[ai4const_in_0 & 0xf]; + *valp = ai4const_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_ai4const_encode (uint32 *valp) +{ + unsigned ai4const_in_0; + unsigned ai4const_out_0; + ai4const_out_0 = *valp; + switch (ai4const_out_0) + { + case 0xffffffff: ai4const_in_0 = 0; break; + case 0x1: ai4const_in_0 = 0x1; break; + case 0x2: ai4const_in_0 = 0x2; break; + case 0x3: ai4const_in_0 = 0x3; break; + case 0x4: ai4const_in_0 = 0x4; break; + case 0x5: ai4const_in_0 = 0x5; break; + case 0x6: ai4const_in_0 = 0x6; break; + case 0x7: ai4const_in_0 = 0x7; break; + case 0x8: ai4const_in_0 = 0x8; break; + case 0x9: ai4const_in_0 = 0x9; break; + case 0xa: ai4const_in_0 = 0xa; break; + case 0xb: ai4const_in_0 = 0xb; break; + case 0xc: ai4const_in_0 = 0xc; break; + case 0xd: ai4const_in_0 = 0xd; break; + case 0xe: ai4const_in_0 = 0xe; break; + default: ai4const_in_0 = 0xf; break; + } + *valp = ai4const_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_b4const_decode (uint32 *valp) +{ + unsigned b4const_out_0; + unsigned b4const_in_0; + b4const_in_0 = *valp & 0xf; + b4const_out_0 = CONST_TBL_b4c_0[b4const_in_0 & 0xf]; + *valp = b4const_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_b4const_encode (uint32 *valp) +{ + unsigned b4const_in_0; + unsigned b4const_out_0; + b4const_out_0 = *valp; + switch (b4const_out_0) + { + case 0xffffffff: b4const_in_0 = 0; break; + case 0x1: b4const_in_0 = 0x1; break; + case 0x2: b4const_in_0 = 0x2; break; + case 0x3: b4const_in_0 = 0x3; break; + case 0x4: b4const_in_0 = 0x4; break; + case 0x5: b4const_in_0 = 0x5; break; + case 0x6: b4const_in_0 = 0x6; break; + case 0x7: b4const_in_0 = 0x7; break; + case 0x8: b4const_in_0 = 0x8; break; + case 0xa: b4const_in_0 = 0x9; break; + case 0xc: b4const_in_0 = 0xa; break; + case 0x10: b4const_in_0 = 0xb; break; + case 0x20: b4const_in_0 = 0xc; break; + case 0x40: b4const_in_0 = 0xd; break; + case 0x80: b4const_in_0 = 0xe; break; + default: b4const_in_0 = 0xf; break; + } + *valp = b4const_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_b4constu_decode (uint32 *valp) +{ + unsigned b4constu_out_0; + unsigned b4constu_in_0; + b4constu_in_0 = *valp & 0xf; + b4constu_out_0 = CONST_TBL_b4cu_0[b4constu_in_0 & 0xf]; + *valp = b4constu_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_b4constu_encode (uint32 *valp) +{ + unsigned b4constu_in_0; + unsigned b4constu_out_0; + b4constu_out_0 = *valp; + switch (b4constu_out_0) + { + case 0x8000: b4constu_in_0 = 0; break; + case 0x10000: b4constu_in_0 = 0x1; break; + case 0x2: b4constu_in_0 = 0x2; break; + case 0x3: b4constu_in_0 = 0x3; break; + case 0x4: b4constu_in_0 = 0x4; break; + case 0x5: b4constu_in_0 = 0x5; break; + case 0x6: b4constu_in_0 = 0x6; break; + case 0x7: b4constu_in_0 = 0x7; break; + case 0x8: b4constu_in_0 = 0x8; break; + case 0xa: b4constu_in_0 = 0x9; break; + case 0xc: b4constu_in_0 = 0xa; break; + case 0x10: b4constu_in_0 = 0xb; break; + case 0x20: b4constu_in_0 = 0xc; break; + case 0x40: b4constu_in_0 = 0xd; break; + case 0x80: b4constu_in_0 = 0xe; break; + default: b4constu_in_0 = 0xf; break; + } + *valp = b4constu_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_immt_decode (uint32 *valp) +{ + unsigned immt_out_0; + unsigned immt_in_0; + immt_in_0 = *valp & 0xf; + immt_out_0 = immt_in_0; + *valp = immt_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_immt_encode (uint32 *valp) +{ + unsigned immt_in_0; + unsigned immt_out_0; + immt_out_0 = *valp; + immt_in_0 = immt_out_0 & 0xf; + *valp = immt_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimms8_decode (uint32 *valp) +{ + unsigned uimms8_out_0; + unsigned uimms8_in_0; + uimms8_in_0 = *valp & 0x7; + uimms8_out_0 = uimms8_in_0; + *valp = uimms8_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimms8_encode (uint32 *valp) +{ + unsigned uimms8_in_0; + unsigned uimms8_out_0; + uimms8_out_0 = *valp; + uimms8_in_0 = uimms8_out_0 & 0x7; + *valp = uimms8_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm8_decode (uint32 *valp) +{ + unsigned uimm8_out_0; + unsigned uimm8_in_0; + uimm8_in_0 = *valp & 0xff; + uimm8_out_0 = uimm8_in_0; + *valp = uimm8_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm8_encode (uint32 *valp) +{ + unsigned uimm8_in_0; + unsigned uimm8_out_0; + uimm8_out_0 = *valp; + uimm8_in_0 = (uimm8_out_0 & 0xff); + *valp = uimm8_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm8x2_decode (uint32 *valp) +{ + unsigned uimm8x2_out_0; + unsigned uimm8x2_in_0; + uimm8x2_in_0 = *valp & 0xff; + uimm8x2_out_0 = uimm8x2_in_0 << 1; + *valp = uimm8x2_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm8x2_encode (uint32 *valp) +{ + unsigned uimm8x2_in_0; + unsigned uimm8x2_out_0; + uimm8x2_out_0 = *valp; + uimm8x2_in_0 = ((uimm8x2_out_0 >> 1) & 0xff); + *valp = uimm8x2_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm8x4_decode (uint32 *valp) +{ + unsigned uimm8x4_out_0; + unsigned uimm8x4_in_0; + uimm8x4_in_0 = *valp & 0xff; + uimm8x4_out_0 = uimm8x4_in_0 << 2; + *valp = uimm8x4_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm8x4_encode (uint32 *valp) +{ + unsigned uimm8x4_in_0; + unsigned uimm8x4_out_0; + uimm8x4_out_0 = *valp; + uimm8x4_in_0 = ((uimm8x4_out_0 >> 2) & 0xff); + *valp = uimm8x4_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm4x16_decode (uint32 *valp) +{ + unsigned uimm4x16_out_0; + unsigned uimm4x16_in_0; + uimm4x16_in_0 = *valp & 0xf; + uimm4x16_out_0 = uimm4x16_in_0 << 4; + *valp = uimm4x16_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm4x16_encode (uint32 *valp) +{ + unsigned uimm4x16_in_0; + unsigned uimm4x16_out_0; + uimm4x16_out_0 = *valp; + uimm4x16_in_0 = ((uimm4x16_out_0 >> 4) & 0xf); + *valp = uimm4x16_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimmrx4_decode (uint32 *valp) +{ + unsigned uimmrx4_out_0; + unsigned uimmrx4_in_0; + uimmrx4_in_0 = *valp & 0xf; + uimmrx4_out_0 = uimmrx4_in_0 << 2; + *valp = uimmrx4_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimmrx4_encode (uint32 *valp) +{ + unsigned uimmrx4_in_0; + unsigned uimmrx4_out_0; + uimmrx4_out_0 = *valp; + uimmrx4_in_0 = ((uimmrx4_out_0 >> 2) & 0xf); + *valp = uimmrx4_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm8_decode (uint32 *valp) +{ + unsigned simm8_out_0; + unsigned simm8_in_0; + simm8_in_0 = *valp & 0xff; + simm8_out_0 = ((int) simm8_in_0 << 24) >> 24; + *valp = simm8_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm8_encode (uint32 *valp) +{ + unsigned simm8_in_0; + unsigned simm8_out_0; + simm8_out_0 = *valp; + simm8_in_0 = (simm8_out_0 & 0xff); + *valp = simm8_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm8x256_decode (uint32 *valp) +{ + unsigned simm8x256_out_0; + unsigned simm8x256_in_0; + simm8x256_in_0 = *valp & 0xff; + simm8x256_out_0 = (((int) simm8x256_in_0 << 24) >> 24) << 8; + *valp = simm8x256_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm8x256_encode (uint32 *valp) +{ + unsigned simm8x256_in_0; + unsigned simm8x256_out_0; + simm8x256_out_0 = *valp; + simm8x256_in_0 = ((simm8x256_out_0 >> 8) & 0xff); + *valp = simm8x256_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm12b_decode (uint32 *valp) +{ + unsigned simm12b_out_0; + unsigned simm12b_in_0; + simm12b_in_0 = *valp & 0xfff; + simm12b_out_0 = ((int) simm12b_in_0 << 20) >> 20; + *valp = simm12b_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm12b_encode (uint32 *valp) +{ + unsigned simm12b_in_0; + unsigned simm12b_out_0; + simm12b_out_0 = *valp; + simm12b_in_0 = (simm12b_out_0 & 0xfff); + *valp = simm12b_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_msalp32_decode (uint32 *valp) +{ + unsigned msalp32_out_0; + unsigned msalp32_in_0; + msalp32_in_0 = *valp & 0x1f; + msalp32_out_0 = 0x20 - msalp32_in_0; + *valp = msalp32_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_msalp32_encode (uint32 *valp) +{ + unsigned msalp32_in_0; + unsigned msalp32_out_0; + msalp32_out_0 = *valp; + msalp32_in_0 = (0x20 - msalp32_out_0) & 0x1f; + *valp = msalp32_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_op2p1_decode (uint32 *valp) +{ + unsigned op2p1_out_0; + unsigned op2p1_in_0; + op2p1_in_0 = *valp & 0xf; + op2p1_out_0 = op2p1_in_0 + 0x1; + *valp = op2p1_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_op2p1_encode (uint32 *valp) +{ + unsigned op2p1_in_0; + unsigned op2p1_out_0; + op2p1_out_0 = *valp; + op2p1_in_0 = (op2p1_out_0 - 0x1) & 0xf; + *valp = op2p1_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_label8_decode (uint32 *valp) +{ + unsigned label8_out_0; + unsigned label8_in_0; + label8_in_0 = *valp & 0xff; + label8_out_0 = 0x4 + (((int) label8_in_0 << 24) >> 24); + *valp = label8_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_label8_encode (uint32 *valp) +{ + unsigned label8_in_0; + unsigned label8_out_0; + label8_out_0 = *valp; + label8_in_0 = (label8_out_0 - 0x4) & 0xff; + *valp = label8_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_ulabel8_decode (uint32 *valp) +{ + unsigned ulabel8_out_0; + unsigned ulabel8_in_0; + ulabel8_in_0 = *valp & 0xff; + ulabel8_out_0 = 0x4 + (((0) << 8) | ulabel8_in_0); + *valp = ulabel8_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_ulabel8_encode (uint32 *valp) +{ + unsigned ulabel8_in_0; + unsigned ulabel8_out_0; + ulabel8_out_0 = *valp; + ulabel8_in_0 = (ulabel8_out_0 - 0x4) & 0xff; + *valp = ulabel8_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_label12_decode (uint32 *valp) +{ + unsigned label12_out_0; + unsigned label12_in_0; + label12_in_0 = *valp & 0xfff; + label12_out_0 = 0x4 + (((int) label12_in_0 << 20) >> 20); + *valp = label12_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_label12_encode (uint32 *valp) +{ + unsigned label12_in_0; + unsigned label12_out_0; + label12_out_0 = *valp; + label12_in_0 = (label12_out_0 - 0x4) & 0xfff; + *valp = label12_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_soffset_decode (uint32 *valp) +{ + unsigned soffset_out_0; + unsigned soffset_in_0; + soffset_in_0 = *valp & 0x3ffff; + soffset_out_0 = 0x4 + (((int) soffset_in_0 << 14) >> 14); + *valp = soffset_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_soffset_encode (uint32 *valp) +{ + unsigned soffset_in_0; + unsigned soffset_out_0; + soffset_out_0 = *valp; + soffset_in_0 = (soffset_out_0 - 0x4) & 0x3ffff; + *valp = soffset_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm16x4_decode (uint32 *valp) +{ + unsigned uimm16x4_out_0; + unsigned uimm16x4_in_0; + uimm16x4_in_0 = *valp & 0xffff; + uimm16x4_out_0 = (((0xffff) << 16) | uimm16x4_in_0) << 2; + *valp = uimm16x4_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm16x4_encode (uint32 *valp) +{ + unsigned uimm16x4_in_0; + unsigned uimm16x4_out_0; + uimm16x4_out_0 = *valp; + uimm16x4_in_0 = (uimm16x4_out_0 >> 2) & 0xffff; + *valp = uimm16x4_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_MR_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_MR_encode (uint32 *valp) +{ + int error; + error = (*valp >= 4); + return error; +} + +static int +OperandSem_opnd_sem_MR_1_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_MR_1_encode (uint32 *valp) +{ + int error; + error = (*valp >= 4); + return error; +} + +static int +OperandSem_opnd_sem_MR_2_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_MR_2_encode (uint32 *valp) +{ + int error; + error = (*valp >= 4); + return error; +} + +static int +OperandSem_opnd_sem_MR_3_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_MR_3_encode (uint32 *valp) +{ + int error; + error = (*valp >= 4); + return error; +} + +static int +OperandSem_opnd_sem_MR_4_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_MR_4_encode (uint32 *valp) +{ + int error; + error = (*valp >= 4); + return error; +} + +static int +OperandSem_opnd_sem_MR_5_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_MR_5_encode (uint32 *valp) +{ + int error; + error = (*valp >= 4); + return error; +} + +static int +OperandSem_opnd_sem_imms_decode (uint32 *valp) +{ + unsigned imms_out_0; + unsigned imms_in_0; + imms_in_0 = *valp & 0xf; + imms_out_0 = imms_in_0; + *valp = imms_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_imms_encode (uint32 *valp) +{ + unsigned imms_in_0; + unsigned imms_out_0; + imms_out_0 = *valp; + imms_in_0 = imms_out_0 & 0xf; + *valp = imms_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_BR_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_BR_encode (uint32 *valp) +{ + int error; + error = (*valp >= 16); + return error; +} + +static int +OperandSem_opnd_sem_BR2_decode (uint32 *valp) +{ + *valp = *valp << 1; + return 0; +} + +static int +OperandSem_opnd_sem_BR2_encode (uint32 *valp) +{ + int error; + error = (*valp >= 16) || ((*valp & 1) != 0); + *valp = *valp >> 1; + return error; +} + +static int +OperandSem_opnd_sem_BR4_decode (uint32 *valp) +{ + *valp = *valp << 2; + return 0; +} + +static int +OperandSem_opnd_sem_BR4_encode (uint32 *valp) +{ + int error; + error = (*valp >= 16) || ((*valp & 3) != 0); + *valp = *valp >> 2; + return error; +} + +static int +OperandSem_opnd_sem_BR8_decode (uint32 *valp) +{ + *valp = *valp << 3; + return 0; +} + +static int +OperandSem_opnd_sem_BR8_encode (uint32 *valp) +{ + int error; + error = (*valp >= 16) || ((*valp & 7) != 0); + *valp = *valp >> 3; + return error; +} + +static int +OperandSem_opnd_sem_BR16_decode (uint32 *valp) +{ + *valp = *valp << 4; + return 0; +} + +static int +OperandSem_opnd_sem_BR16_encode (uint32 *valp) +{ + int error; + error = (*valp >= 16) || ((*valp & 15) != 0); + *valp = *valp >> 4; + return error; +} + +static int +OperandSem_opnd_sem_tp7_decode (uint32 *valp) +{ + unsigned tp7_out_0; + unsigned tp7_in_0; + tp7_in_0 = *valp & 0xf; + tp7_out_0 = tp7_in_0 + 0x7; + *valp = tp7_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_tp7_encode (uint32 *valp) +{ + unsigned tp7_in_0; + unsigned tp7_out_0; + tp7_out_0 = *valp; + tp7_in_0 = (tp7_out_0 - 0x7) & 0xf; + *valp = tp7_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_xt_wbr15_label_decode (uint32 *valp) +{ + unsigned xt_wbr15_label_out_0; + unsigned xt_wbr15_label_in_0; + xt_wbr15_label_in_0 = *valp & 0x7fff; + xt_wbr15_label_out_0 = 0x4 + (((int) xt_wbr15_label_in_0 << 17) >> 17); + *valp = xt_wbr15_label_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_xt_wbr15_label_encode (uint32 *valp) +{ + unsigned xt_wbr15_label_in_0; + unsigned xt_wbr15_label_out_0; + xt_wbr15_label_out_0 = *valp; + xt_wbr15_label_in_0 = (xt_wbr15_label_out_0 - 0x4) & 0x7fff; + *valp = xt_wbr15_label_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_xt_wbr18_label_decode (uint32 *valp) +{ + unsigned xt_wbr18_label_out_0; + unsigned xt_wbr18_label_in_0; + xt_wbr18_label_in_0 = *valp & 0x3ffff; + xt_wbr18_label_out_0 = 0x4 + (((int) xt_wbr18_label_in_0 << 14) >> 14); + *valp = xt_wbr18_label_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_xt_wbr18_label_encode (uint32 *valp) +{ + unsigned xt_wbr18_label_in_0; + unsigned xt_wbr18_label_out_0; + xt_wbr18_label_out_0 = *valp; + xt_wbr18_label_in_0 = (xt_wbr18_label_out_0 - 0x4) & 0x3ffff; + *valp = xt_wbr18_label_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_FR_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_FR_encode (uint32 *valp) +{ + int error; + error = (*valp >= 16); + return error; +} + +static int +OperandSem_opnd_sem_imm_t_decode (uint32 *valp) +{ + unsigned imm_t_out_0; + unsigned imm_t_in_0; + imm_t_in_0 = *valp & 0xf; + imm_t_out_0 = (0 << 4) | imm_t_in_0; + *valp = imm_t_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_imm_t_encode (uint32 *valp) +{ + unsigned imm_t_in_0; + unsigned imm_t_out_0; + imm_t_out_0 = *valp; + imm_t_in_0 = (imm_t_out_0 & 0xf); + *valp = imm_t_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_imm8x4_decode (uint32 *valp) +{ + unsigned imm8x4_out_0; + unsigned imm8x4_in_0; + imm8x4_in_0 = *valp & 0xff; + imm8x4_out_0 = (0 << 10) | (imm8x4_in_0 << 2) | 0; + *valp = imm8x4_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_imm8x4_encode (uint32 *valp) +{ + unsigned imm8x4_in_0; + unsigned imm8x4_out_0; + imm8x4_out_0 = *valp; + imm8x4_in_0 = ((imm8x4_out_0 >> 2) & 0xff); + *valp = imm8x4_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_imm8x8_decode (uint32 *valp) +{ + unsigned imm8x8_out_0; + unsigned imm8x8_in_0; + imm8x8_in_0 = *valp & 0xff; + imm8x8_out_0 = (0 << 11) | (imm8x8_in_0 << 3) | 0; + *valp = imm8x8_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_imm8x8_encode (uint32 *valp) +{ + unsigned imm8x8_in_0; + unsigned imm8x8_out_0; + imm8x8_out_0 = *valp; + imm8x8_in_0 = ((imm8x8_out_0 >> 3) & 0xff); + *valp = imm8x8_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_bbi_decode (uint32 *valp) +{ + unsigned bbi_out_0; + unsigned bbi_in_0; + bbi_in_0 = *valp & 0x1f; + bbi_out_0 = (0 << 5) | bbi_in_0; + *valp = bbi_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_bbi_encode (uint32 *valp) +{ + unsigned bbi_in_0; + unsigned bbi_out_0; + bbi_out_0 = *valp; + bbi_in_0 = (bbi_out_0 & 0x1f); + *valp = bbi_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_s_decode (uint32 *valp) +{ + unsigned s_out_0; + unsigned s_in_0; + s_in_0 = *valp & 0xf; + s_out_0 = (0 << 4) | s_in_0; + *valp = s_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_s_encode (uint32 *valp) +{ + unsigned s_in_0; + unsigned s_out_0; + s_out_0 = *valp; + s_in_0 = (s_out_0 & 0xf); + *valp = s_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_bitindex_decode (uint32 *valp) +{ + unsigned bitindex_out_0; + unsigned bitindex_in_0; + bitindex_in_0 = *valp & 0x1f; + bitindex_out_0 = (0 << 5) | bitindex_in_0; + *valp = bitindex_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_bitindex_encode (uint32 *valp) +{ + unsigned bitindex_in_0; + unsigned bitindex_out_0; + bitindex_out_0 = *valp; + bitindex_in_0 = (bitindex_out_0 & 0x1f); + *valp = bitindex_in_0; + return 0; +} + +static int +Operand_soffsetx4_ator (uint32 *valp, uint32 pc) +{ + *valp -= (pc & ~0x3); + return 0; +} + +static int +Operand_soffsetx4_rtoa (uint32 *valp, uint32 pc) +{ + *valp += (pc & ~0x3); + return 0; +} + +static int +Operand_uimm6_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_uimm6_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_label8_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_label8_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_ulabel8_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_ulabel8_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_label12_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_label12_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_soffset_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_soffset_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_uimm16x4_ator (uint32 *valp, uint32 pc) +{ + *valp -= ((pc + 3) & ~0x3); + return 0; +} + +static int +Operand_uimm16x4_rtoa (uint32 *valp, uint32 pc) +{ + *valp += ((pc + 3) & ~0x3); + return 0; +} + +static int +Operand_xt_wbr15_label_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_xt_wbr15_label_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_xt_wbr18_label_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_xt_wbr18_label_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static xtensa_operand_internal operands[] = { + { "soffsetx4", FIELD_offset, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_soffsetx4_encode, OperandSem_opnd_sem_soffsetx4_decode, + Operand_soffsetx4_ator, Operand_soffsetx4_rtoa }, + { "immr", FIELD_r, -1, 0, + 0, + OperandSem_opnd_sem_immr_encode, OperandSem_opnd_sem_immr_decode, + 0, 0 }, + { "uimm12x8", FIELD_imm12, -1, 0, + 0, + OperandSem_opnd_sem_uimm12x8_encode, OperandSem_opnd_sem_uimm12x8_decode, + 0, 0 }, + { "simm4", FIELD_mn, -1, 0, + 0, + OperandSem_opnd_sem_simm4_encode, OperandSem_opnd_sem_simm4_decode, + 0, 0 }, + { "arr", FIELD_r, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_AR_encode, OperandSem_opnd_sem_AR_decode, + 0, 0 }, + { "ars", FIELD_s, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_AR_encode, OperandSem_opnd_sem_AR_decode, + 0, 0 }, + { "*ars_invisible", FIELD_s, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_AR_encode, OperandSem_opnd_sem_AR_decode, + 0, 0 }, + { "art", FIELD_t, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_AR_encode, OperandSem_opnd_sem_AR_decode, + 0, 0 }, + { "ar0", FIELD__ar0, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_AR_0_encode, OperandSem_opnd_sem_AR_0_decode, + 0, 0 }, + { "ar4", FIELD__ar4, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_AR_4_encode, OperandSem_opnd_sem_AR_4_decode, + 0, 0 }, + { "ar8", FIELD__ar8, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_AR_8_encode, OperandSem_opnd_sem_AR_8_decode, + 0, 0 }, + { "ar12", FIELD__ar12, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_AR_12_encode, OperandSem_opnd_sem_AR_12_decode, + 0, 0 }, + { "ars_entry", FIELD_s, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_AR_entry_encode, OperandSem_opnd_sem_AR_entry_decode, + 0, 0 }, + { "immrx4", FIELD_r, -1, 0, + 0, + OperandSem_opnd_sem_immrx4_encode, OperandSem_opnd_sem_immrx4_decode, + 0, 0 }, + { "lsi4x4", FIELD_r, -1, 0, + 0, + OperandSem_opnd_sem_lsi4x4_encode, OperandSem_opnd_sem_lsi4x4_decode, + 0, 0 }, + { "simm7", FIELD_imm7, -1, 0, + 0, + OperandSem_opnd_sem_simm7_encode, OperandSem_opnd_sem_simm7_decode, + 0, 0 }, + { "uimm6", FIELD_imm6, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_uimm6_encode, OperandSem_opnd_sem_uimm6_decode, + Operand_uimm6_ator, Operand_uimm6_rtoa }, + { "ai4const", FIELD_t, -1, 0, + 0, + OperandSem_opnd_sem_ai4const_encode, OperandSem_opnd_sem_ai4const_decode, + 0, 0 }, + { "b4const", FIELD_r, -1, 0, + 0, + OperandSem_opnd_sem_b4const_encode, OperandSem_opnd_sem_b4const_decode, + 0, 0 }, + { "b4constu", FIELD_r, -1, 0, + 0, + OperandSem_opnd_sem_b4constu_encode, OperandSem_opnd_sem_b4constu_decode, + 0, 0 }, + { "immt", FIELD_t, -1, 0, + 0, + OperandSem_opnd_sem_immt_encode, OperandSem_opnd_sem_immt_decode, + 0, 0 }, + { "uimms8", FIELD_imms8, -1, 0, + 0, + OperandSem_opnd_sem_uimms8_encode, OperandSem_opnd_sem_uimms8_decode, + 0, 0 }, + { "uimm8", FIELD_imm8, -1, 0, + 0, + OperandSem_opnd_sem_uimm8_encode, OperandSem_opnd_sem_uimm8_decode, + 0, 0 }, + { "uimm8x2", FIELD_imm8, -1, 0, + 0, + OperandSem_opnd_sem_uimm8x2_encode, OperandSem_opnd_sem_uimm8x2_decode, + 0, 0 }, + { "uimm8x4", FIELD_imm8, -1, 0, + 0, + OperandSem_opnd_sem_uimm8x4_encode, OperandSem_opnd_sem_uimm8x4_decode, + 0, 0 }, + { "uimm4x16", FIELD_op2, -1, 0, + 0, + OperandSem_opnd_sem_uimm4x16_encode, OperandSem_opnd_sem_uimm4x16_decode, + 0, 0 }, + { "uimmrx4", FIELD_r, -1, 0, + 0, + OperandSem_opnd_sem_uimmrx4_encode, OperandSem_opnd_sem_uimmrx4_decode, + 0, 0 }, + { "simm8", FIELD_imm8, -1, 0, + 0, + OperandSem_opnd_sem_simm8_encode, OperandSem_opnd_sem_simm8_decode, + 0, 0 }, + { "simm8x256", FIELD_imm8, -1, 0, + 0, + OperandSem_opnd_sem_simm8x256_encode, OperandSem_opnd_sem_simm8x256_decode, + 0, 0 }, + { "simm12b", FIELD_imm12b, -1, 0, + 0, + OperandSem_opnd_sem_simm12b_encode, OperandSem_opnd_sem_simm12b_decode, + 0, 0 }, + { "msalp32", FIELD_sal, -1, 0, + 0, + OperandSem_opnd_sem_msalp32_encode, OperandSem_opnd_sem_msalp32_decode, + 0, 0 }, + { "op2p1", FIELD_op2, -1, 0, + 0, + OperandSem_opnd_sem_op2p1_encode, OperandSem_opnd_sem_op2p1_decode, + 0, 0 }, + { "label8", FIELD_imm8, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_label8_encode, OperandSem_opnd_sem_label8_decode, + Operand_label8_ator, Operand_label8_rtoa }, + { "ulabel8", FIELD_imm8, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_ulabel8_encode, OperandSem_opnd_sem_ulabel8_decode, + Operand_ulabel8_ator, Operand_ulabel8_rtoa }, + { "label12", FIELD_imm12, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_label12_encode, OperandSem_opnd_sem_label12_decode, + Operand_label12_ator, Operand_label12_rtoa }, + { "soffset", FIELD_offset, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_soffset_encode, OperandSem_opnd_sem_soffset_decode, + Operand_soffset_ator, Operand_soffset_rtoa }, + { "uimm16x4", FIELD_imm16, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_uimm16x4_encode, OperandSem_opnd_sem_uimm16x4_decode, + Operand_uimm16x4_ator, Operand_uimm16x4_rtoa }, + { "mx", FIELD_x, REGFILE_MR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_UNKNOWN, + OperandSem_opnd_sem_MR_encode, OperandSem_opnd_sem_MR_decode, + 0, 0 }, + { "my", FIELD_y, REGFILE_MR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_UNKNOWN, + OperandSem_opnd_sem_MR_0_encode, OperandSem_opnd_sem_MR_0_decode, + 0, 0 }, + { "mw", FIELD_w, REGFILE_MR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_MR_1_encode, OperandSem_opnd_sem_MR_1_decode, + 0, 0 }, + { "mr0", FIELD__mr0, REGFILE_MR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_MR_2_encode, OperandSem_opnd_sem_MR_2_decode, + 0, 0 }, + { "mr1", FIELD__mr1, REGFILE_MR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_MR_3_encode, OperandSem_opnd_sem_MR_3_decode, + 0, 0 }, + { "mr2", FIELD__mr2, REGFILE_MR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_MR_4_encode, OperandSem_opnd_sem_MR_4_decode, + 0, 0 }, + { "mr3", FIELD__mr3, REGFILE_MR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_MR_5_encode, OperandSem_opnd_sem_MR_5_decode, + 0, 0 }, + { "imms", FIELD_s, -1, 0, + 0, + OperandSem_opnd_sem_imms_encode, OperandSem_opnd_sem_imms_decode, + 0, 0 }, + { "imms1", FIELD_s, -1, 0, + 0, + OperandSem_opnd_sem_imms_encode, OperandSem_opnd_sem_imms_decode, + 0, 0 }, + { "bt", FIELD_t, REGFILE_BR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR_encode, OperandSem_opnd_sem_BR_decode, + 0, 0 }, + { "bs", FIELD_s, REGFILE_BR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR_encode, OperandSem_opnd_sem_BR_decode, + 0, 0 }, + { "br", FIELD_r, REGFILE_BR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR_encode, OperandSem_opnd_sem_BR_decode, + 0, 0 }, + { "bt2", FIELD_t2, REGFILE_BR, 2, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR2_encode, OperandSem_opnd_sem_BR2_decode, + 0, 0 }, + { "bs2", FIELD_s2, REGFILE_BR, 2, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR2_encode, OperandSem_opnd_sem_BR2_decode, + 0, 0 }, + { "br2", FIELD_r2, REGFILE_BR, 2, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR2_encode, OperandSem_opnd_sem_BR2_decode, + 0, 0 }, + { "bt4", FIELD_t4, REGFILE_BR, 4, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR4_encode, OperandSem_opnd_sem_BR4_decode, + 0, 0 }, + { "bs4", FIELD_s4, REGFILE_BR, 4, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR4_encode, OperandSem_opnd_sem_BR4_decode, + 0, 0 }, + { "br4", FIELD_r4, REGFILE_BR, 4, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR4_encode, OperandSem_opnd_sem_BR4_decode, + 0, 0 }, + { "bt8", FIELD_t8, REGFILE_BR, 8, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR8_encode, OperandSem_opnd_sem_BR8_decode, + 0, 0 }, + { "bs8", FIELD_s8, REGFILE_BR, 8, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR8_encode, OperandSem_opnd_sem_BR8_decode, + 0, 0 }, + { "br8", FIELD_r8, REGFILE_BR, 8, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR8_encode, OperandSem_opnd_sem_BR8_decode, + 0, 0 }, + { "bt16", FIELD__bt16, REGFILE_BR, 16, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR16_encode, OperandSem_opnd_sem_BR16_decode, + 0, 0 }, + { "bs16", FIELD__bs16, REGFILE_BR, 16, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR16_encode, OperandSem_opnd_sem_BR16_decode, + 0, 0 }, + { "br16", FIELD__br16, REGFILE_BR, 16, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR16_encode, OperandSem_opnd_sem_BR16_decode, + 0, 0 }, + { "brall", FIELD__brall, REGFILE_BR, 16, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_BR16_encode, OperandSem_opnd_sem_BR16_decode, + 0, 0 }, + { "tp7", FIELD_t, -1, 0, + 0, + OperandSem_opnd_sem_tp7_encode, OperandSem_opnd_sem_tp7_decode, + 0, 0 }, + { "xt_wbr15_label", FIELD_xt_wbr15_imm, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_xt_wbr15_label_encode, OperandSem_opnd_sem_xt_wbr15_label_decode, + Operand_xt_wbr15_label_ator, Operand_xt_wbr15_label_rtoa }, + { "xt_wbr18_label", FIELD_xt_wbr18_imm, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_xt_wbr18_label_encode, OperandSem_opnd_sem_xt_wbr18_label_decode, + Operand_xt_wbr18_label_ator, Operand_xt_wbr18_label_rtoa }, + { "frr", FIELD_r, REGFILE_FR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_FR_encode, OperandSem_opnd_sem_FR_decode, + 0, 0 }, + { "frs", FIELD_s, REGFILE_FR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_FR_encode, OperandSem_opnd_sem_FR_decode, + 0, 0 }, + { "frt", FIELD_t, REGFILE_FR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_FR_encode, OperandSem_opnd_sem_FR_decode, + 0, 0 }, + { "imm_t", FIELD_t, -1, 0, + 0, + OperandSem_opnd_sem_imm_t_encode, OperandSem_opnd_sem_imm_t_decode, + 0, 0 }, + { "imm_s", FIELD_s, -1, 0, + 0, + OperandSem_opnd_sem_imm_t_encode, OperandSem_opnd_sem_imm_t_decode, + 0, 0 }, + { "imm8x4", FIELD_imm8, -1, 0, + 0, + OperandSem_opnd_sem_imm8x4_encode, OperandSem_opnd_sem_imm8x4_decode, + 0, 0 }, + { "imm8x8", FIELD_imm8, -1, 0, + 0, + OperandSem_opnd_sem_imm8x8_encode, OperandSem_opnd_sem_imm8x8_decode, + 0, 0 }, + { "bbi", FIELD_bbi, -1, 0, + 0, + OperandSem_opnd_sem_bbi_encode, OperandSem_opnd_sem_bbi_decode, + 0, 0 }, + { "sae", FIELD_sae, -1, 0, + 0, + OperandSem_opnd_sem_bbi_encode, OperandSem_opnd_sem_bbi_decode, + 0, 0 }, + { "sas", FIELD_sas, -1, 0, + 0, + OperandSem_opnd_sem_bbi_encode, OperandSem_opnd_sem_bbi_decode, + 0, 0 }, + { "sargt", FIELD_sargt, -1, 0, + 0, + OperandSem_opnd_sem_bbi_encode, OperandSem_opnd_sem_bbi_decode, + 0, 0 }, + { "s", FIELD_s, -1, 0, + 0, + OperandSem_opnd_sem_s_encode, OperandSem_opnd_sem_s_decode, + 0, 0 }, + { "bitindex", FIELD_bitindex, -1, 0, + 0, + OperandSem_opnd_sem_bitindex_encode, OperandSem_opnd_sem_bitindex_decode, + 0, 0 }, + { "t", FIELD_t, -1, 0, 0, 0, 0, 0, 0 }, + { "bbi4", FIELD_bbi4, -1, 0, 0, 0, 0, 0, 0 }, + { "imm12", FIELD_imm12, -1, 0, 0, 0, 0, 0, 0 }, + { "imm8", FIELD_imm8, -1, 0, 0, 0, 0, 0, 0 }, + { "s8", FIELD_s8, -1, 0, 0, 0, 0, 0, 0 }, + { "imms8", FIELD_imms8, -1, 0, 0, 0, 0, 0, 0 }, + { "imm12b", FIELD_imm12b, -1, 0, 0, 0, 0, 0, 0 }, + { "imm16", FIELD_imm16, -1, 0, 0, 0, 0, 0, 0 }, + { "m", FIELD_m, -1, 0, 0, 0, 0, 0, 0 }, + { "n", FIELD_n, -1, 0, 0, 0, 0, 0, 0 }, + { "offset", FIELD_offset, -1, 0, 0, 0, 0, 0, 0 }, + { "op0", FIELD_op0, -1, 0, 0, 0, 0, 0, 0 }, + { "op1", FIELD_op1, -1, 0, 0, 0, 0, 0, 0 }, + { "op2", FIELD_op2, -1, 0, 0, 0, 0, 0, 0 }, + { "r", FIELD_r, -1, 0, 0, 0, 0, 0, 0 }, + { "r_disp", FIELD_r_disp, -1, 0, 0, 0, 0, 0, 0 }, + { "r_3", FIELD_r_3, -1, 0, 0, 0, 0, 0, 0 }, + { "sa4", FIELD_sa4, -1, 0, 0, 0, 0, 0, 0 }, + { "sae4", FIELD_sae4, -1, 0, 0, 0, 0, 0, 0 }, + { "sal", FIELD_sal, -1, 0, 0, 0, 0, 0, 0 }, + { "sas4", FIELD_sas4, -1, 0, 0, 0, 0, 0, 0 }, + { "sr", FIELD_sr, -1, 0, 0, 0, 0, 0, 0 }, + { "st", FIELD_st, -1, 0, 0, 0, 0, 0, 0 }, + { "thi3", FIELD_thi3, -1, 0, 0, 0, 0, 0, 0 }, + { "imm4", FIELD_imm4, -1, 0, 0, 0, 0, 0, 0 }, + { "mn", FIELD_mn, -1, 0, 0, 0, 0, 0, 0 }, + { "i", FIELD_i, -1, 0, 0, 0, 0, 0, 0 }, + { "imm6lo", FIELD_imm6lo, -1, 0, 0, 0, 0, 0, 0 }, + { "imm6hi", FIELD_imm6hi, -1, 0, 0, 0, 0, 0, 0 }, + { "imm7lo", FIELD_imm7lo, -1, 0, 0, 0, 0, 0, 0 }, + { "imm7hi", FIELD_imm7hi, -1, 0, 0, 0, 0, 0, 0 }, + { "z", FIELD_z, -1, 0, 0, 0, 0, 0, 0 }, + { "imm6", FIELD_imm6, -1, 0, 0, 0, 0, 0, 0 }, + { "imm7", FIELD_imm7, -1, 0, 0, 0, 0, 0, 0 }, + { "r3", FIELD_r3, -1, 0, 0, 0, 0, 0, 0 }, + { "rbit2", FIELD_rbit2, -1, 0, 0, 0, 0, 0, 0 }, + { "rhi", FIELD_rhi, -1, 0, 0, 0, 0, 0, 0 }, + { "t3", FIELD_t3, -1, 0, 0, 0, 0, 0, 0 }, + { "tbit2", FIELD_tbit2, -1, 0, 0, 0, 0, 0, 0 }, + { "tlo", FIELD_tlo, -1, 0, 0, 0, 0, 0, 0 }, + { "w", FIELD_w, -1, 0, 0, 0, 0, 0, 0 }, + { "y", FIELD_y, -1, 0, 0, 0, 0, 0, 0 }, + { "x", FIELD_x, -1, 0, 0, 0, 0, 0, 0 }, + { "t2", FIELD_t2, -1, 0, 0, 0, 0, 0, 0 }, + { "s2", FIELD_s2, -1, 0, 0, 0, 0, 0, 0 }, + { "r2", FIELD_r2, -1, 0, 0, 0, 0, 0, 0 }, + { "t4", FIELD_t4, -1, 0, 0, 0, 0, 0, 0 }, + { "s4", FIELD_s4, -1, 0, 0, 0, 0, 0, 0 }, + { "r4", FIELD_r4, -1, 0, 0, 0, 0, 0, 0 }, + { "t8", FIELD_t8, -1, 0, 0, 0, 0, 0, 0 }, + { "r8", FIELD_r8, -1, 0, 0, 0, 0, 0, 0 }, + { "xt_wbr15_imm", FIELD_xt_wbr15_imm, -1, 0, 0, 0, 0, 0, 0 }, + { "xt_wbr18_imm", FIELD_xt_wbr18_imm, -1, 0, 0, 0, 0, 0, 0 }, + { "s3to1", FIELD_s3to1, -1, 0, 0, 0, 0, 0, 0 } +}; + +enum xtensa_operand_id { + OPERAND_soffsetx4, + OPERAND_immr, + OPERAND_uimm12x8, + OPERAND_simm4, + OPERAND_arr, + OPERAND_ars, + OPERAND__ars_invisible, + OPERAND_art, + OPERAND_ar0, + OPERAND_ar4, + OPERAND_ar8, + OPERAND_ar12, + OPERAND_ars_entry, + OPERAND_immrx4, + OPERAND_lsi4x4, + OPERAND_simm7, + OPERAND_uimm6, + OPERAND_ai4const, + OPERAND_b4const, + OPERAND_b4constu, + OPERAND_immt, + OPERAND_uimms8, + OPERAND_uimm8, + OPERAND_uimm8x2, + OPERAND_uimm8x4, + OPERAND_uimm4x16, + OPERAND_uimmrx4, + OPERAND_simm8, + OPERAND_simm8x256, + OPERAND_simm12b, + OPERAND_msalp32, + OPERAND_op2p1, + OPERAND_label8, + OPERAND_ulabel8, + OPERAND_label12, + OPERAND_soffset, + OPERAND_uimm16x4, + OPERAND_mx, + OPERAND_my, + OPERAND_mw, + OPERAND_mr0, + OPERAND_mr1, + OPERAND_mr2, + OPERAND_mr3, + OPERAND_imms, + OPERAND_imms1, + OPERAND_bt, + OPERAND_bs, + OPERAND_br, + OPERAND_bt2, + OPERAND_bs2, + OPERAND_br2, + OPERAND_bt4, + OPERAND_bs4, + OPERAND_br4, + OPERAND_bt8, + OPERAND_bs8, + OPERAND_br8, + OPERAND_bt16, + OPERAND_bs16, + OPERAND_br16, + OPERAND_brall, + OPERAND_tp7, + OPERAND_xt_wbr15_label, + OPERAND_xt_wbr18_label, + OPERAND_frr, + OPERAND_frs, + OPERAND_frt, + OPERAND_imm_t, + OPERAND_imm_s, + OPERAND_imm8x4, + OPERAND_imm8x8, + OPERAND_bbi, + OPERAND_sae, + OPERAND_sas, + OPERAND_sargt, + OPERAND_s, + OPERAND_bitindex, + OPERAND_t, + OPERAND_bbi4, + OPERAND_imm12, + OPERAND_imm8, + OPERAND_s8, + OPERAND_imms8, + OPERAND_imm12b, + OPERAND_imm16, + OPERAND_m, + OPERAND_n, + OPERAND_offset, + OPERAND_op0, + OPERAND_op1, + OPERAND_op2, + OPERAND_r, + OPERAND_r_disp, + OPERAND_r_3, + OPERAND_sa4, + OPERAND_sae4, + OPERAND_sal, + OPERAND_sas4, + OPERAND_sr, + OPERAND_st, + OPERAND_thi3, + OPERAND_imm4, + OPERAND_mn, + OPERAND_i, + OPERAND_imm6lo, + OPERAND_imm6hi, + OPERAND_imm7lo, + OPERAND_imm7hi, + OPERAND_z, + OPERAND_imm6, + OPERAND_imm7, + OPERAND_r3, + OPERAND_rbit2, + OPERAND_rhi, + OPERAND_t3, + OPERAND_tbit2, + OPERAND_tlo, + OPERAND_w, + OPERAND_y, + OPERAND_x, + OPERAND_t2, + OPERAND_s2, + OPERAND_r2, + OPERAND_t4, + OPERAND_s4, + OPERAND_r4, + OPERAND_t8, + OPERAND_r8, + OPERAND_xt_wbr15_imm, + OPERAND_xt_wbr18_imm, + OPERAND_s3to1 +}; + + +/* Iclass table. */ + +static xtensa_arg_internal Iclass_xt_iclass_rfe_stateArgs[] = { + { { STATE_PSRING }, 'i' }, + { { STATE_PSEXCM }, 'm' }, + { { STATE_EPC1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfde_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DEPC }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call12_args[] = { + { { OPERAND_soffsetx4 }, 'i' }, + { { OPERAND_ar12 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call12_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call8_args[] = { + { { OPERAND_soffsetx4 }, 'i' }, + { { OPERAND_ar8 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call8_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call4_args[] = { + { { OPERAND_soffsetx4 }, 'i' }, + { { OPERAND_ar4 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call4_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx12_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ar12 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx12_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx8_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ar8 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx8_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx4_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ar4 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx4_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_entry_args[] = { + { { OPERAND_ars_entry }, 's' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm12x8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_entry_stateArgs[] = { + { { STATE_PSCALLINC }, 'i' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSWOE }, 'i' }, + { { STATE_WindowBase }, 'm' }, + { { STATE_WindowStart }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_movsp_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_movsp_stateArgs[] = { + { { STATE_WindowBase }, 'i' }, + { { STATE_WindowStart }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rotw_args[] = { + { { OPERAND_simm4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rotw_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_WindowBase }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_retw_args[] = { + { { OPERAND__ars_invisible }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_retw_stateArgs[] = { + { { STATE_WindowBase }, 'm' }, + { { STATE_WindowStart }, 'm' }, + { { STATE_PSCALLINC }, 'o' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSWOE }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfwou_stateArgs[] = { + { { STATE_EPC1 }, 'i' }, + { { STATE_PSEXCM }, 'm' }, + { { STATE_PSRING }, 'i' }, + { { STATE_WindowBase }, 'm' }, + { { STATE_WindowStart }, 'm' }, + { { STATE_PSOWB }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l32e_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_immrx4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l32e_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32e_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_immrx4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32e_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_windowbase_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_windowbase_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_WindowBase }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_windowbase_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_windowbase_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_WindowBase }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_windowbase_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_windowbase_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_WindowBase }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_windowstart_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_windowstart_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_WindowStart }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_windowstart_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_windowstart_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_WindowStart }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_windowstart_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_windowstart_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_WindowStart }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_add_n_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_addi_n_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_ai4const }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bz6_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm6 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_loadi4_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_lsi4x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mov_n_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_movi_n_args[] = { + { { OPERAND_ars }, 'o' }, + { { OPERAND_simm7 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_retn_args[] = { + { { OPERAND__ars_invisible }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_storei4_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_lsi4x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_threadptr_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_threadptr_stateArgs[] = { + { { STATE_THREADPTR }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_threadptr_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_threadptr_stateArgs[] = { + { { STATE_THREADPTR }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_addi_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_simm8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_addmi_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_simm8x256 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_addsub_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bit_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bsi8_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_b4const }, 'i' }, + { { OPERAND_label8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bsi8b_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_bbi }, 'i' }, + { { OPERAND_label8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bsi8u_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_b4constu }, 'i' }, + { { OPERAND_label8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bst8_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_label8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bsz12_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_label12 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call0_args[] = { + { { OPERAND_soffsetx4 }, 'i' }, + { { OPERAND_ar0 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx0_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ar0 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_exti_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_sae }, 'i' }, + { { OPERAND_op2p1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_jump_args[] = { + { { OPERAND_soffset }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_jumpx_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l16ui_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l16si_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l32i_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l32r_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_uimm16x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l8i_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_loop_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ulabel8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_loop_stateArgs[] = { + { { STATE_LBEG }, 'o' }, + { { STATE_LEND }, 'o' }, + { { STATE_LCOUNT }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_loopz_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ulabel8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_loopz_stateArgs[] = { + { { STATE_LBEG }, 'o' }, + { { STATE_LEND }, 'o' }, + { { STATE_LCOUNT }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_movi_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_simm12b }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_movz_args[] = { + { { OPERAND_arr }, 'm' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_neg_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_return_args[] = { + { { OPERAND__ars_invisible }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_simcall_args[] = { + { { OPERAND_immt }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s16i_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32i_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32nb_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimmrx4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s8i_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sar_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sar_stateArgs[] = { + { { STATE_SAR }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sari_args[] = { + { { OPERAND_sas }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sari_stateArgs[] = { + { { STATE_SAR }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shifts_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shifts_stateArgs[] = { + { { STATE_SAR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shiftst_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shiftst_stateArgs[] = { + { { STATE_SAR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shiftt_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shiftt_stateArgs[] = { + { { STATE_SAR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_slli_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_msalp32 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_srai_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_sargt }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_srli_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_s }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sync_stateArgs[] = { + { { STATE_XTSYNC }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsil_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_s }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsil_stateArgs[] = { + { { STATE_PSWOE }, 'i' }, + { { STATE_PSCALLINC }, 'i' }, + { { STATE_PSOWB }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_PSUM }, 'i' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSINTLEVEL }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lend_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lend_stateArgs[] = { + { { STATE_LEND }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lend_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lend_stateArgs[] = { + { { STATE_LEND }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lend_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lend_stateArgs[] = { + { { STATE_LEND }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lcount_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lcount_stateArgs[] = { + { { STATE_LCOUNT }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lcount_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lcount_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_LCOUNT }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lcount_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lcount_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_LCOUNT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lbeg_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lbeg_stateArgs[] = { + { { STATE_LBEG }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lbeg_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lbeg_stateArgs[] = { + { { STATE_LBEG }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lbeg_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lbeg_stateArgs[] = { + { { STATE_LBEG }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_sar_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_sar_stateArgs[] = { + { { STATE_SAR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_sar_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_sar_stateArgs[] = { + { { STATE_SAR }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_sar_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_sar_stateArgs[] = { + { { STATE_SAR }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_memctl_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_memctl_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_memctl_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_configid0_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_configid0_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_configid0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_configid0_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_configid1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_configid1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ps_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ps_stateArgs[] = { + { { STATE_PSWOE }, 'i' }, + { { STATE_PSCALLINC }, 'i' }, + { { STATE_PSOWB }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_PSUM }, 'i' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSINTLEVEL }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ps_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ps_stateArgs[] = { + { { STATE_PSWOE }, 'o' }, + { { STATE_PSCALLINC }, 'o' }, + { { STATE_PSOWB }, 'o' }, + { { STATE_PSRING }, 'm' }, + { { STATE_PSUM }, 'o' }, + { { STATE_PSEXCM }, 'm' }, + { { STATE_PSINTLEVEL }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ps_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ps_stateArgs[] = { + { { STATE_PSWOE }, 'm' }, + { { STATE_PSCALLINC }, 'm' }, + { { STATE_PSOWB }, 'm' }, + { { STATE_PSRING }, 'm' }, + { { STATE_PSUM }, 'm' }, + { { STATE_PSEXCM }, 'm' }, + { { STATE_PSINTLEVEL }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC1 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC1 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE1 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE1 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc2_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc2_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc2_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC2 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc2_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc2_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC2 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave2_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave2_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave2_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE2 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave2_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave2_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE2 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc3_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc3_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC3 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc3_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC3 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc3_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc3_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC3 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave3_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave3_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE3 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave3_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE3 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave3_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave3_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE3 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc4_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc4_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc4_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc4_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC4 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc4_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc4_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC4 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave4_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave4_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave4_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave4_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE4 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave4_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave4_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE4 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc5_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc5_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC5 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc5_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc5_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC5 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc5_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc5_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC5 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave5_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave5_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE5 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave5_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave5_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE5 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave5_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave5_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE5 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc6_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc6_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC6 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc6_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc6_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC6 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc6_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc6_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC6 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave6_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave6_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE6 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave6_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave6_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE6 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave6_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave6_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE6 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc7_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc7_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC7 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc7_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc7_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC7 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc7_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc7_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPC7 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave7_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave7_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE7 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave7_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave7_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE7 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave7_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave7_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCSAVE7 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps2_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps2_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps2_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS2 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps2_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps2_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS2 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps3_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps3_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS3 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps3_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS3 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps3_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps3_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS3 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps4_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps4_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps4_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps4_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS4 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps4_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps4_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS4 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps5_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps5_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS5 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps5_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps5_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS5 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps5_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps5_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS5 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps6_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps6_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS6 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps6_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps6_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS6 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps6_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps6_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS6 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps7_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps7_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS7 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps7_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps7_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS7 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps7_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps7_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EPS7 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excvaddr_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excvaddr_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCVADDR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excvaddr_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excvaddr_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCVADDR }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excvaddr_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excvaddr_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCVADDR }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_depc_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_depc_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DEPC }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_depc_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_depc_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DEPC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_depc_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_depc_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DEPC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_exccause_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_exccause_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCCAUSE }, 'i' }, + { { STATE_XTSYNC }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_exccause_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_exccause_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCCAUSE }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_exccause_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_exccause_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_EXCCAUSE }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_misc0_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_misc0_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_MISC0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_misc0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_misc0_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_MISC0 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_misc0_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_misc0_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_MISC0 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_misc1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_misc1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_MISC1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_misc1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_misc1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_MISC1 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_misc1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_misc1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_MISC1 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_prid_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_prid_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_vecbase_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_vecbase_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_VECBASE }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_vecbase_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_vecbase_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_VECBASE }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_vecbase_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_vecbase_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_VECBASE }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_salt_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_mul16_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_mul32_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_aa_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_aa_stateArgs[] = { + { { STATE_ACC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_ad_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_my }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_ad_stateArgs[] = { + { { STATE_ACC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_da_args[] = { + { { OPERAND_mx }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_da_stateArgs[] = { + { { STATE_ACC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_dd_args[] = { + { { OPERAND_mx }, 'i' }, + { { OPERAND_my }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_dd_stateArgs[] = { + { { STATE_ACC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16a_aa_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16a_aa_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16a_ad_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_my }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16a_ad_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16a_da_args[] = { + { { OPERAND_mx }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16a_da_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16a_dd_args[] = { + { { OPERAND_mx }, 'i' }, + { { OPERAND_my }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16a_dd_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16al_da_args[] = { + { { OPERAND_mw }, 'o' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_mx }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16al_da_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16al_dd_args[] = { + { { OPERAND_mw }, 'o' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_mx }, 'i' }, + { { OPERAND_my }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16al_dd_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_l_args[] = { + { { OPERAND_mw }, 'o' }, + { { OPERAND_ars }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_m0_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_mr0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_m0_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_mr0 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_m0_args[] = { + { { OPERAND_art }, 'm' }, + { { OPERAND_mr0 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_m1_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_mr1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_m1_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_mr1 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_m1_args[] = { + { { OPERAND_art }, 'm' }, + { { OPERAND_mr1 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_m2_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_mr2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_m2_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_mr2 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_m2_args[] = { + { { OPERAND_art }, 'm' }, + { { OPERAND_mr2 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_m3_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_mr3 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_m3_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_mr3 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_m3_args[] = { + { { OPERAND_art }, 'm' }, + { { OPERAND_mr3 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_acclo_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_acclo_stateArgs[] = { + { { STATE_ACC }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_acclo_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_acclo_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_acclo_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_acclo_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_acchi_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_acchi_stateArgs[] = { + { { STATE_ACC }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_acchi_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_acchi_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_acchi_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_acchi_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfi_args[] = { + { { OPERAND_s }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfi_stateArgs[] = { + { { STATE_PSWOE }, 'o' }, + { { STATE_PSCALLINC }, 'o' }, + { { STATE_PSOWB }, 'o' }, + { { STATE_PSRING }, 'm' }, + { { STATE_PSUM }, 'o' }, + { { STATE_PSEXCM }, 'm' }, + { { STATE_PSINTLEVEL }, 'o' }, + { { STATE_EPC1 }, 'i' }, + { { STATE_EPC2 }, 'i' }, + { { STATE_EPC3 }, 'i' }, + { { STATE_EPC4 }, 'i' }, + { { STATE_EPC5 }, 'i' }, + { { STATE_EPC6 }, 'i' }, + { { STATE_EPC7 }, 'i' }, + { { STATE_EPS2 }, 'i' }, + { { STATE_EPS3 }, 'i' }, + { { STATE_EPS4 }, 'i' }, + { { STATE_EPS5 }, 'i' }, + { { STATE_EPS6 }, 'i' }, + { { STATE_EPS7 }, 'i' }, + { { STATE_InOCDMode }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wait_args[] = { + { { OPERAND_s }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wait_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_PSINTLEVEL }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_interrupt_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_interrupt_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_INTERRUPT }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intset_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intset_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_XTSYNC }, 'o' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intclear_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intclear_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_XTSYNC }, 'o' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_intenable_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_intenable_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_INTENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intenable_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intenable_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_INTENABLE }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_intenable_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_intenable_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_INTENABLE }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_break_args[] = { + { { OPERAND_imms }, 'i' }, + { { OPERAND_immt }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_break_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSINTLEVEL }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_break_n_args[] = { + { { OPERAND_imms }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_break_n_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSINTLEVEL }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreaka0_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreaka0_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DBREAKA0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreaka0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreaka0_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DBREAKA0 }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreaka0_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreaka0_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DBREAKA0 }, 'm' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreakc0_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreakc0_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DBREAKC0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreakc0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreakc0_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DBREAKC0 }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreakc0_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreakc0_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DBREAKC0 }, 'm' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreaka1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreaka1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DBREAKA1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreaka1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreaka1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DBREAKA1 }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreaka1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreaka1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DBREAKA1 }, 'm' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreakc1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreakc1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DBREAKC1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreakc1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreakc1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DBREAKC1 }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreakc1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreakc1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DBREAKC1 }, 'm' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreaka0_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreaka0_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_IBREAKA0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreaka0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreaka0_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_IBREAKA0 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreaka0_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreaka0_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_IBREAKA0 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreaka1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreaka1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_IBREAKA1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreaka1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreaka1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_IBREAKA1 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreaka1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreaka1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_IBREAKA1 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreakenable_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreakenable_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_IBREAKENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreakenable_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreakenable_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_IBREAKENABLE }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreakenable_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreakenable_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_IBREAKENABLE }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_debugcause_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_debugcause_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DEBUGCAUSE }, 'i' }, + { { STATE_DBNUM }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_debugcause_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_debugcause_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DEBUGCAUSE }, 'o' }, + { { STATE_DBNUM }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_debugcause_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_debugcause_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DEBUGCAUSE }, 'm' }, + { { STATE_DBNUM }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_icount_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_icount_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_ICOUNT }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_icount_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_icount_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_XTSYNC }, 'o' }, + { { STATE_ICOUNT }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_icount_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_icount_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_XTSYNC }, 'o' }, + { { STATE_ICOUNT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_icountlevel_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_icountlevel_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_ICOUNTLEVEL }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_icountlevel_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_icountlevel_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_ICOUNTLEVEL }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_icountlevel_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_icountlevel_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_ICOUNTLEVEL }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ddr_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ddr_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DDR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ddr_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ddr_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_XTSYNC }, 'o' }, + { { STATE_DDR }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ddr_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ddr_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_XTSYNC }, 'o' }, + { { STATE_DDR }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_lddr32_p_args[] = { + { { OPERAND_ars }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_lddr32_p_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_XTSYNC }, 'o' }, + { { STATE_InOCDMode }, 'i' }, + { { STATE_DDR }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sddr32_p_args[] = { + { { OPERAND_ars }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sddr32_p_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_InOCDMode }, 'i' }, + { { STATE_DDR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfdo_args[] = { + { { OPERAND_imms }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfdo_stateArgs[] = { + { { STATE_InOCDMode }, 'm' }, + { { STATE_EPC6 }, 'i' }, + { { STATE_PSWOE }, 'o' }, + { { STATE_PSCALLINC }, 'o' }, + { { STATE_PSOWB }, 'o' }, + { { STATE_PSRING }, 'o' }, + { { STATE_PSUM }, 'o' }, + { { STATE_PSEXCM }, 'o' }, + { { STATE_PSINTLEVEL }, 'o' }, + { { STATE_EPS6 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfdd_stateArgs[] = { + { { STATE_InOCDMode }, 'm' }, + { { STATE_VECBASE }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_mmid_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_mmid_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bbool1_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_bs }, 'i' }, + { { OPERAND_bt }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bbool4_args[] = { + { { OPERAND_bt }, 'o' }, + { { OPERAND_bs4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bbool8_args[] = { + { { OPERAND_bt }, 'o' }, + { { OPERAND_bs8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bbranch_args[] = { + { { OPERAND_bs }, 'i' }, + { { OPERAND_label8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bmove_args[] = { + { { OPERAND_arr }, 'm' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_bt }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_RSR_BR_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_brall }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_WSR_BR_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_brall }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_XSR_BR_args[] = { + { { OPERAND_art }, 'm' }, + { { OPERAND_brall }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccount_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccount_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_CCOUNT }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccount_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccount_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_XTSYNC }, 'o' }, + { { STATE_CCOUNT }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccount_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccount_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_XTSYNC }, 'o' }, + { { STATE_CCOUNT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccompare0_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccompare0_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_CCOMPARE0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccompare0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccompare0_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_CCOMPARE0 }, 'o' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccompare0_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccompare0_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_CCOMPARE0 }, 'm' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccompare1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccompare1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_CCOMPARE1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccompare1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccompare1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_CCOMPARE1 }, 'o' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccompare1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccompare1_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_CCOMPARE1 }, 'm' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccompare2_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccompare2_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_CCOMPARE2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccompare2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccompare2_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_CCOMPARE2 }, 'o' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccompare2_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccompare2_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_CCOMPARE2 }, 'm' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_icache_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_icache_lock_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm4x16 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_icache_lock_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_icache_inv_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_icache_inv_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_licx_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_licx_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sicx_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sicx_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_dcache_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_dcache_dyn_args[] = { + { { OPERAND_ars }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_dcache_dyn_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_dcache_ind_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm4x16 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_dcache_ind_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_dcache_inv_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_dcache_inv_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_dpf_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_dcache_lock_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm4x16 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_dcache_lock_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sdct_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sdct_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_ldct_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_ldct_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sdcw_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sdcw_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_ldcw_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_ldcw_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ptevaddr_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ptevaddr_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_PTBASE }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ptevaddr_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ptevaddr_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_PTBASE }, 'i' }, + { { STATE_EXCVADDR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ptevaddr_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ptevaddr_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_PTBASE }, 'm' }, + { { STATE_EXCVADDR }, 'i' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_rasid_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_rasid_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_ASID3 }, 'i' }, + { { STATE_ASID2 }, 'i' }, + { { STATE_ASID1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_rasid_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_rasid_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_ASID3 }, 'o' }, + { { STATE_ASID2 }, 'o' }, + { { STATE_ASID1 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_rasid_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_rasid_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_ASID3 }, 'm' }, + { { STATE_ASID2 }, 'm' }, + { { STATE_ASID1 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_itlbcfg_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_itlbcfg_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_INSTPGSZID6 }, 'i' }, + { { STATE_INSTPGSZID5 }, 'i' }, + { { STATE_INSTPGSZID4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_itlbcfg_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_itlbcfg_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_INSTPGSZID6 }, 'o' }, + { { STATE_INSTPGSZID5 }, 'o' }, + { { STATE_INSTPGSZID4 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_itlbcfg_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_itlbcfg_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_INSTPGSZID6 }, 'm' }, + { { STATE_INSTPGSZID5 }, 'm' }, + { { STATE_INSTPGSZID4 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dtlbcfg_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dtlbcfg_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DATAPGSZID6 }, 'i' }, + { { STATE_DATAPGSZID5 }, 'i' }, + { { STATE_DATAPGSZID4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dtlbcfg_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dtlbcfg_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DATAPGSZID6 }, 'o' }, + { { STATE_DATAPGSZID5 }, 'o' }, + { { STATE_DATAPGSZID4 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dtlbcfg_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dtlbcfg_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_DATAPGSZID6 }, 'm' }, + { { STATE_DATAPGSZID5 }, 'm' }, + { { STATE_DATAPGSZID4 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_idtlb_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_idtlb_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rdtlb_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rdtlb_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wdtlb_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wdtlb_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_iitlb_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_iitlb_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_ritlb_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_ritlb_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_witlb_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_witlb_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_ldpte_stateArgs[] = { + { { STATE_PTBASE }, 'i' }, + { { STATE_EXCVADDR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_hwwitlba_stateArgs[] = { + { { STATE_EXCVADDR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_hwwdtlba_stateArgs[] = { + { { STATE_EXCVADDR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_cpenable_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_cpenable_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_cpenable_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_cpenable_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_CPENABLE }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_cpenable_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_cpenable_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_CPENABLE }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_clamp_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_tp7 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_minmax_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_nsa_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sx_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_tp7 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l32ai_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32ri_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32c1i_args[] = { + { { OPERAND_art }, 'm' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32c1i_stateArgs[] = { + { { STATE_SCOMPARE1 }, 'i' }, + { { STATE_XTSYNC }, 'i' }, + { { STATE_SCOMPARE1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_scompare1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_scompare1_stateArgs[] = { + { { STATE_SCOMPARE1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_scompare1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_scompare1_stateArgs[] = { + { { STATE_SCOMPARE1 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_scompare1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_scompare1_stateArgs[] = { + { { STATE_SCOMPARE1 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_atomctl_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_atomctl_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_ATOMCTL }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_atomctl_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_atomctl_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_ATOMCTL }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_atomctl_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_atomctl_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_ATOMCTL }, 'm' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_div_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eraccess_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eraccess_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_ERACCESS }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eraccess_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eraccess_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_ERACCESS }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eraccess_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eraccess_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' }, + { { STATE_ERACCESS }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rer_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rer_stateArgs[] = { + { { STATE_ERACCESS }, 'i' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wer_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wer_stateArgs[] = { + { { STATE_ERACCESS }, 'i' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSRING }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_fcr_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_fcr_stateArgs[] = { + { { STATE_RoundMode }, 'i' }, + { { STATE_InvalidEnable }, 'i' }, + { { STATE_DivZeroEnable }, 'i' }, + { { STATE_OverflowEnable }, 'i' }, + { { STATE_UnderflowEnable }, 'i' }, + { { STATE_InexactEnable }, 'i' }, + { { STATE_FPreserved20 }, 'i' }, + { { STATE_FPreserved5 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_fcr_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_fcr_stateArgs[] = { + { { STATE_RoundMode }, 'o' }, + { { STATE_InvalidEnable }, 'o' }, + { { STATE_DivZeroEnable }, 'o' }, + { { STATE_OverflowEnable }, 'o' }, + { { STATE_UnderflowEnable }, 'o' }, + { { STATE_InexactEnable }, 'o' }, + { { STATE_FPreserved20 }, 'o' }, + { { STATE_FPreserved5 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_fsr_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_fsr_stateArgs[] = { + { { STATE_InvalidFlag }, 'i' }, + { { STATE_DivZeroFlag }, 'i' }, + { { STATE_OverflowFlag }, 'i' }, + { { STATE_UnderflowFlag }, 'i' }, + { { STATE_InexactFlag }, 'i' }, + { { STATE_FPreserved20a }, 'i' }, + { { STATE_FPreserved7 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_fsr_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_fsr_stateArgs[] = { + { { STATE_InvalidFlag }, 'o' }, + { { STATE_DivZeroFlag }, 'o' }, + { { STATE_OverflowFlag }, 'o' }, + { { STATE_UnderflowFlag }, 'o' }, + { { STATE_InexactFlag }, 'o' }, + { { STATE_FPreserved20a }, 'o' }, + { { STATE_FPreserved7 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_READ_IMPWIRE_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_READ_IMPWIRE_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_READ_IMPWIRE_intfArgs[] = { + INTERFACE_IMPWIRE +}; + +static xtensa_arg_internal Iclass_iclass_SETB_EXPSTATE_args[] = { + { { OPERAND_bitindex }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SETB_EXPSTATE_stateArgs[] = { + { { STATE_EXPSTATE }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CLRB_EXPSTATE_args[] = { + { { OPERAND_bitindex }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CLRB_EXPSTATE_stateArgs[] = { + { { STATE_EXPSTATE }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_WRMSK_EXPSTATE_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_WRMSK_EXPSTATE_stateArgs[] = { + { { STATE_EXPSTATE }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_expstate_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_expstate_stateArgs[] = { + { { STATE_EXPSTATE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_expstate_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_expstate_stateArgs[] = { + { { STATE_EXPSTATE }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_LSI_args[] = { + { { OPERAND_frt }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_imm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_LSI_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_LSIP_args[] = { + { { OPERAND_frt }, 'o' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_imm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_LSIP_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_LSX_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_LSX_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_LSXP_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_LSXP_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SSI_args[] = { + { { OPERAND_frt }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_imm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_SSI_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SSIP_args[] = { + { { OPERAND_frt }, 'i' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_imm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_SSIP_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SSX_args[] = { + { { OPERAND_frr }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_SSX_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SSXP_args[] = { + { { OPERAND_frr }, 'i' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_SSXP_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_LDI_args[] = { + { { OPERAND_frt }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_imm8x8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_LDI_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_LDIP_args[] = { + { { OPERAND_frt }, 'o' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_imm8x8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_LDIP_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_LDX_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_LDX_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_LDXP_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_LDXP_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SDI_args[] = { + { { OPERAND_frt }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_imm8x8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_SDI_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SDIP_args[] = { + { { OPERAND_frt }, 'i' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_imm8x8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_SDIP_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SDX_args[] = { + { { OPERAND_frr }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_SDX_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SDXP_args[] = { + { { OPERAND_frr }, 'i' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_SDXP_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ABS_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_ABS_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_NEG_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_NEG_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ABS_D_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_ABS_D_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_NEG_D_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_NEG_D_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOV_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOV_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOV_D_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOV_D_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVEQZ_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVEQZ_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVNEZ_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVNEZ_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVLTZ_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVLTZ_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVGEZ_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVGEZ_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVF_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_bt }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVF_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVT_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_bt }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVT_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_WFR_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_WFR_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_RFR_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_RFR_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_RFRD_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_RFRD_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_WFRD_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_WFRD_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ROUND_S_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_ROUND_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ROUND_D_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_ROUND_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_CEIL_S_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_CEIL_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_CEIL_D_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_CEIL_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_FLOOR_S_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_FLOOR_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_FLOOR_D_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_FLOOR_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_TRUNC_S_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_TRUNC_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_TRUNC_D_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_TRUNC_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_UTRUNC_S_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_UTRUNC_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_UTRUNC_D_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_UTRUNC_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_FLOAT_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_FLOAT_S_stateArgs[] = { + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_FLOAT_D_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_FLOAT_D_stateArgs[] = { + { { STATE_InexactFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_UFLOAT_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_UFLOAT_S_stateArgs[] = { + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_UFLOAT_D_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_UFLOAT_D_stateArgs[] = { + { { STATE_InexactFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_CVTD_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_CVTD_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_CVTS_D_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_CVTS_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_OverflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_UN_S_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_UN_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_UN_D_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_UN_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ULT_S_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_ULT_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ULT_D_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_ULT_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ULE_S_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_ULE_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ULE_D_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_ULE_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_UEQ_S_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_UEQ_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_UEQ_D_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_UEQ_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_OLT_S_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_OLT_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_OLT_D_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_OLT_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_OLE_S_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_OLE_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_OLE_D_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_OLE_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_OEQ_S_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_OEQ_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_OEQ_D_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_OEQ_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADD_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADD_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADD_D_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADD_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SUB_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_SUB_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SUB_D_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_SUB_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MUL_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_MUL_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MUL_D_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_MUL_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MADD_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_MADD_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MADD_D_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_MADD_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MSUB_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_MSUB_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MSUB_D_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_MSUB_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SQRT0_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_SQRT0_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SQRT0_D_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_SQRT0_D_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_DIV0_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_DIV0_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_DIV0_D_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_DIV0_D_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_RECIP0_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_RECIP0_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_DivZeroFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_RECIP0_D_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_RECIP0_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_DivZeroFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_RSQRT0_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_RSQRT0_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_DivZeroFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_RSQRT0_D_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_RSQRT0_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_DivZeroFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MADDN_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_MADDN_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MADDN_D_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_MADDN_D_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_DIVN_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_DIVN_S_stateArgs[] = { + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_DIVN_D_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_DIVN_D_stateArgs[] = { + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_CONST_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_imm_s }, 'i' } +}; + +static xtensa_arg_internal Iclass_CONST_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_CONST_D_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_imm_s }, 'i' } +}; + +static xtensa_arg_internal Iclass_CONST_D_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_NEXP01_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_NEXP01_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_NEXP01_D_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_NEXP01_D_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADDEXP_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADDEXP_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADDEXP_D_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADDEXP_D_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADDEXPM_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADDEXPM_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADDEXPM_D_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADDEXPM_D_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MKDADJ_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_MKDADJ_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_DivZeroFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MKDADJ_D_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_MKDADJ_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_DivZeroFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MKSADJ_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_MKSADJ_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MKSADJ_D_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_MKSADJ_D_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_iclass_internal iclasses[] = { + { 0, 0 /* xt_iclass_excw */, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_rfe */, + 3, Iclass_xt_iclass_rfe_stateArgs, 0, 0 }, + { 0, 0 /* xt_iclass_rfde */, + 3, Iclass_xt_iclass_rfde_stateArgs, 0, 0 }, + { 0, 0 /* xt_iclass_syscall */, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_call12_args, + 1, Iclass_xt_iclass_call12_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_call8_args, + 1, Iclass_xt_iclass_call8_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_call4_args, + 1, Iclass_xt_iclass_call4_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_callx12_args, + 1, Iclass_xt_iclass_callx12_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_callx8_args, + 1, Iclass_xt_iclass_callx8_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_callx4_args, + 1, Iclass_xt_iclass_callx4_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_entry_args, + 5, Iclass_xt_iclass_entry_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_movsp_args, + 2, Iclass_xt_iclass_movsp_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rotw_args, + 3, Iclass_xt_iclass_rotw_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_retw_args, + 5, Iclass_xt_iclass_retw_stateArgs, 0, 0 }, + { 0, 0 /* xt_iclass_rfwou */, + 6, Iclass_xt_iclass_rfwou_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_l32e_args, + 2, Iclass_xt_iclass_l32e_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_s32e_args, + 2, Iclass_xt_iclass_s32e_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_windowbase_args, + 3, Iclass_xt_iclass_rsr_windowbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_windowbase_args, + 3, Iclass_xt_iclass_wsr_windowbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_windowbase_args, + 3, Iclass_xt_iclass_xsr_windowbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_windowstart_args, + 3, Iclass_xt_iclass_rsr_windowstart_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_windowstart_args, + 3, Iclass_xt_iclass_wsr_windowstart_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_windowstart_args, + 3, Iclass_xt_iclass_xsr_windowstart_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_add_n_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_addi_n_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_bz6_args, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_ill_n */, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_loadi4_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_mov_n_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_movi_n_args, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_nopn */, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_retn_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_storei4_args, + 0, 0, 0, 0 }, + { 1, Iclass_rur_threadptr_args, + 1, Iclass_rur_threadptr_stateArgs, 0, 0 }, + { 1, Iclass_wur_threadptr_args, + 1, Iclass_wur_threadptr_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_addi_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_addmi_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_addsub_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bit_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bsi8_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bsi8b_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bsi8u_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bst8_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_bsz12_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_call0_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_callx0_args, + 0, 0, 0, 0 }, + { 4, Iclass_xt_iclass_exti_args, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_ill */, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_jump_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_jumpx_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_l16ui_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_l16si_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_l32i_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_l32r_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_l8i_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_loop_args, + 3, Iclass_xt_iclass_loop_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_loopz_args, + 3, Iclass_xt_iclass_loopz_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_movi_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_movz_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_neg_args, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_nop */, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_return_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_simcall_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s16i_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s32i_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s32nb_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s8i_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_sar_args, + 1, Iclass_xt_iclass_sar_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_sari_args, + 1, Iclass_xt_iclass_sari_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_shifts_args, + 1, Iclass_xt_iclass_shifts_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_shiftst_args, + 1, Iclass_xt_iclass_shiftst_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_shiftt_args, + 1, Iclass_xt_iclass_shiftt_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_slli_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_srai_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_srli_args, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_memw */, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_extw */, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_isync */, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_sync */, + 1, Iclass_xt_iclass_sync_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_rsil_args, + 7, Iclass_xt_iclass_rsil_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_lend_args, + 1, Iclass_xt_iclass_rsr_lend_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_lend_args, + 1, Iclass_xt_iclass_wsr_lend_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_lend_args, + 1, Iclass_xt_iclass_xsr_lend_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_lcount_args, + 1, Iclass_xt_iclass_rsr_lcount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_lcount_args, + 2, Iclass_xt_iclass_wsr_lcount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_lcount_args, + 2, Iclass_xt_iclass_xsr_lcount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_lbeg_args, + 1, Iclass_xt_iclass_rsr_lbeg_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_lbeg_args, + 1, Iclass_xt_iclass_wsr_lbeg_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_lbeg_args, + 1, Iclass_xt_iclass_xsr_lbeg_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_sar_args, + 1, Iclass_xt_iclass_rsr_sar_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_sar_args, + 2, Iclass_xt_iclass_wsr_sar_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_sar_args, + 1, Iclass_xt_iclass_xsr_sar_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_memctl_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_memctl_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_memctl_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_configid0_args, + 2, Iclass_xt_iclass_rsr_configid0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_configid0_args, + 2, Iclass_xt_iclass_wsr_configid0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_configid1_args, + 2, Iclass_xt_iclass_rsr_configid1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ps_args, + 7, Iclass_xt_iclass_rsr_ps_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ps_args, + 7, Iclass_xt_iclass_wsr_ps_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ps_args, + 7, Iclass_xt_iclass_xsr_ps_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc1_args, + 3, Iclass_xt_iclass_rsr_epc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc1_args, + 3, Iclass_xt_iclass_wsr_epc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc1_args, + 3, Iclass_xt_iclass_xsr_epc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave1_args, + 3, Iclass_xt_iclass_rsr_excsave1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave1_args, + 3, Iclass_xt_iclass_wsr_excsave1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave1_args, + 3, Iclass_xt_iclass_xsr_excsave1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc2_args, + 3, Iclass_xt_iclass_rsr_epc2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc2_args, + 3, Iclass_xt_iclass_wsr_epc2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc2_args, + 3, Iclass_xt_iclass_xsr_epc2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave2_args, + 3, Iclass_xt_iclass_rsr_excsave2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave2_args, + 3, Iclass_xt_iclass_wsr_excsave2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave2_args, + 3, Iclass_xt_iclass_xsr_excsave2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc3_args, + 3, Iclass_xt_iclass_rsr_epc3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc3_args, + 3, Iclass_xt_iclass_wsr_epc3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc3_args, + 3, Iclass_xt_iclass_xsr_epc3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave3_args, + 3, Iclass_xt_iclass_rsr_excsave3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave3_args, + 3, Iclass_xt_iclass_wsr_excsave3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave3_args, + 3, Iclass_xt_iclass_xsr_excsave3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc4_args, + 3, Iclass_xt_iclass_rsr_epc4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc4_args, + 3, Iclass_xt_iclass_wsr_epc4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc4_args, + 3, Iclass_xt_iclass_xsr_epc4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave4_args, + 3, Iclass_xt_iclass_rsr_excsave4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave4_args, + 3, Iclass_xt_iclass_wsr_excsave4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave4_args, + 3, Iclass_xt_iclass_xsr_excsave4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc5_args, + 3, Iclass_xt_iclass_rsr_epc5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc5_args, + 3, Iclass_xt_iclass_wsr_epc5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc5_args, + 3, Iclass_xt_iclass_xsr_epc5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave5_args, + 3, Iclass_xt_iclass_rsr_excsave5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave5_args, + 3, Iclass_xt_iclass_wsr_excsave5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave5_args, + 3, Iclass_xt_iclass_xsr_excsave5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc6_args, + 3, Iclass_xt_iclass_rsr_epc6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc6_args, + 3, Iclass_xt_iclass_wsr_epc6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc6_args, + 3, Iclass_xt_iclass_xsr_epc6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave6_args, + 3, Iclass_xt_iclass_rsr_excsave6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave6_args, + 3, Iclass_xt_iclass_wsr_excsave6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave6_args, + 3, Iclass_xt_iclass_xsr_excsave6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc7_args, + 3, Iclass_xt_iclass_rsr_epc7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc7_args, + 3, Iclass_xt_iclass_wsr_epc7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc7_args, + 3, Iclass_xt_iclass_xsr_epc7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave7_args, + 3, Iclass_xt_iclass_rsr_excsave7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave7_args, + 3, Iclass_xt_iclass_wsr_excsave7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave7_args, + 3, Iclass_xt_iclass_xsr_excsave7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eps2_args, + 3, Iclass_xt_iclass_rsr_eps2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eps2_args, + 3, Iclass_xt_iclass_wsr_eps2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eps2_args, + 3, Iclass_xt_iclass_xsr_eps2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eps3_args, + 3, Iclass_xt_iclass_rsr_eps3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eps3_args, + 3, Iclass_xt_iclass_wsr_eps3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eps3_args, + 3, Iclass_xt_iclass_xsr_eps3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eps4_args, + 3, Iclass_xt_iclass_rsr_eps4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eps4_args, + 3, Iclass_xt_iclass_wsr_eps4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eps4_args, + 3, Iclass_xt_iclass_xsr_eps4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eps5_args, + 3, Iclass_xt_iclass_rsr_eps5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eps5_args, + 3, Iclass_xt_iclass_wsr_eps5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eps5_args, + 3, Iclass_xt_iclass_xsr_eps5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eps6_args, + 3, Iclass_xt_iclass_rsr_eps6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eps6_args, + 3, Iclass_xt_iclass_wsr_eps6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eps6_args, + 3, Iclass_xt_iclass_xsr_eps6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eps7_args, + 3, Iclass_xt_iclass_rsr_eps7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eps7_args, + 3, Iclass_xt_iclass_wsr_eps7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eps7_args, + 3, Iclass_xt_iclass_xsr_eps7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excvaddr_args, + 3, Iclass_xt_iclass_rsr_excvaddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excvaddr_args, + 3, Iclass_xt_iclass_wsr_excvaddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excvaddr_args, + 3, Iclass_xt_iclass_xsr_excvaddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_depc_args, + 3, Iclass_xt_iclass_rsr_depc_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_depc_args, + 3, Iclass_xt_iclass_wsr_depc_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_depc_args, + 3, Iclass_xt_iclass_xsr_depc_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_exccause_args, + 4, Iclass_xt_iclass_rsr_exccause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_exccause_args, + 3, Iclass_xt_iclass_wsr_exccause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_exccause_args, + 3, Iclass_xt_iclass_xsr_exccause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_misc0_args, + 3, Iclass_xt_iclass_rsr_misc0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_misc0_args, + 3, Iclass_xt_iclass_wsr_misc0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_misc0_args, + 3, Iclass_xt_iclass_xsr_misc0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_misc1_args, + 3, Iclass_xt_iclass_rsr_misc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_misc1_args, + 3, Iclass_xt_iclass_wsr_misc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_misc1_args, + 3, Iclass_xt_iclass_xsr_misc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_prid_args, + 2, Iclass_xt_iclass_rsr_prid_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_vecbase_args, + 3, Iclass_xt_iclass_rsr_vecbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_vecbase_args, + 3, Iclass_xt_iclass_wsr_vecbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_vecbase_args, + 3, Iclass_xt_iclass_xsr_vecbase_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_salt_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_mul16_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_mul32_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_mac16_aa_args, + 1, Iclass_xt_iclass_mac16_aa_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_mac16_ad_args, + 1, Iclass_xt_iclass_mac16_ad_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_mac16_da_args, + 1, Iclass_xt_iclass_mac16_da_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_mac16_dd_args, + 1, Iclass_xt_iclass_mac16_dd_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_mac16a_aa_args, + 1, Iclass_xt_iclass_mac16a_aa_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_mac16a_ad_args, + 1, Iclass_xt_iclass_mac16a_ad_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_mac16a_da_args, + 1, Iclass_xt_iclass_mac16a_da_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_mac16a_dd_args, + 1, Iclass_xt_iclass_mac16a_dd_stateArgs, 0, 0 }, + { 4, Iclass_xt_iclass_mac16al_da_args, + 1, Iclass_xt_iclass_mac16al_da_stateArgs, 0, 0 }, + { 4, Iclass_xt_iclass_mac16al_dd_args, + 1, Iclass_xt_iclass_mac16al_dd_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_mac16_l_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_rsr_m0_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_wsr_m0_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_xsr_m0_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_rsr_m1_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_wsr_m1_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_xsr_m1_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_rsr_m2_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_wsr_m2_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_xsr_m2_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_rsr_m3_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_wsr_m3_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_xsr_m3_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_acclo_args, + 1, Iclass_xt_iclass_rsr_acclo_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_acclo_args, + 1, Iclass_xt_iclass_wsr_acclo_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_acclo_args, + 1, Iclass_xt_iclass_xsr_acclo_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_acchi_args, + 1, Iclass_xt_iclass_rsr_acchi_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_acchi_args, + 1, Iclass_xt_iclass_wsr_acchi_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_acchi_args, + 1, Iclass_xt_iclass_xsr_acchi_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rfi_args, + 21, Iclass_xt_iclass_rfi_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wait_args, + 3, Iclass_xt_iclass_wait_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_interrupt_args, + 3, Iclass_xt_iclass_rsr_interrupt_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_intset_args, + 4, Iclass_xt_iclass_wsr_intset_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_intclear_args, + 4, Iclass_xt_iclass_wsr_intclear_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_intenable_args, + 3, Iclass_xt_iclass_rsr_intenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_intenable_args, + 3, Iclass_xt_iclass_wsr_intenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_intenable_args, + 3, Iclass_xt_iclass_xsr_intenable_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_break_args, + 2, Iclass_xt_iclass_break_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_break_n_args, + 2, Iclass_xt_iclass_break_n_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_dbreaka0_args, + 3, Iclass_xt_iclass_rsr_dbreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_dbreaka0_args, + 4, Iclass_xt_iclass_wsr_dbreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_dbreaka0_args, + 4, Iclass_xt_iclass_xsr_dbreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_dbreakc0_args, + 3, Iclass_xt_iclass_rsr_dbreakc0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_dbreakc0_args, + 4, Iclass_xt_iclass_wsr_dbreakc0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_dbreakc0_args, + 4, Iclass_xt_iclass_xsr_dbreakc0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_dbreaka1_args, + 3, Iclass_xt_iclass_rsr_dbreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_dbreaka1_args, + 4, Iclass_xt_iclass_wsr_dbreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_dbreaka1_args, + 4, Iclass_xt_iclass_xsr_dbreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_dbreakc1_args, + 3, Iclass_xt_iclass_rsr_dbreakc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_dbreakc1_args, + 4, Iclass_xt_iclass_wsr_dbreakc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_dbreakc1_args, + 4, Iclass_xt_iclass_xsr_dbreakc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ibreaka0_args, + 3, Iclass_xt_iclass_rsr_ibreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ibreaka0_args, + 3, Iclass_xt_iclass_wsr_ibreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ibreaka0_args, + 3, Iclass_xt_iclass_xsr_ibreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ibreaka1_args, + 3, Iclass_xt_iclass_rsr_ibreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ibreaka1_args, + 3, Iclass_xt_iclass_wsr_ibreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ibreaka1_args, + 3, Iclass_xt_iclass_xsr_ibreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ibreakenable_args, + 3, Iclass_xt_iclass_rsr_ibreakenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ibreakenable_args, + 3, Iclass_xt_iclass_wsr_ibreakenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ibreakenable_args, + 3, Iclass_xt_iclass_xsr_ibreakenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_debugcause_args, + 4, Iclass_xt_iclass_rsr_debugcause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_debugcause_args, + 4, Iclass_xt_iclass_wsr_debugcause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_debugcause_args, + 4, Iclass_xt_iclass_xsr_debugcause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_icount_args, + 3, Iclass_xt_iclass_rsr_icount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_icount_args, + 4, Iclass_xt_iclass_wsr_icount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_icount_args, + 4, Iclass_xt_iclass_xsr_icount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_icountlevel_args, + 3, Iclass_xt_iclass_rsr_icountlevel_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_icountlevel_args, + 3, Iclass_xt_iclass_wsr_icountlevel_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_icountlevel_args, + 3, Iclass_xt_iclass_xsr_icountlevel_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ddr_args, + 3, Iclass_xt_iclass_rsr_ddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ddr_args, + 4, Iclass_xt_iclass_wsr_ddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ddr_args, + 4, Iclass_xt_iclass_xsr_ddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_lddr32_p_args, + 5, Iclass_xt_iclass_lddr32_p_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_sddr32_p_args, + 4, Iclass_xt_iclass_sddr32_p_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rfdo_args, + 10, Iclass_xt_iclass_rfdo_stateArgs, 0, 0 }, + { 0, 0 /* xt_iclass_rfdd */, + 2, Iclass_xt_iclass_rfdd_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_mmid_args, + 3, Iclass_xt_iclass_wsr_mmid_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_bbool1_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_bbool4_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_bbool8_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_bbranch_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bmove_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_RSR_BR_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_WSR_BR_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_XSR_BR_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ccount_args, + 3, Iclass_xt_iclass_rsr_ccount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ccount_args, + 4, Iclass_xt_iclass_wsr_ccount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ccount_args, + 4, Iclass_xt_iclass_xsr_ccount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ccompare0_args, + 3, Iclass_xt_iclass_rsr_ccompare0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ccompare0_args, + 4, Iclass_xt_iclass_wsr_ccompare0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ccompare0_args, + 4, Iclass_xt_iclass_xsr_ccompare0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ccompare1_args, + 3, Iclass_xt_iclass_rsr_ccompare1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ccompare1_args, + 4, Iclass_xt_iclass_wsr_ccompare1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ccompare1_args, + 4, Iclass_xt_iclass_xsr_ccompare1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ccompare2_args, + 3, Iclass_xt_iclass_rsr_ccompare2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ccompare2_args, + 4, Iclass_xt_iclass_wsr_ccompare2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ccompare2_args, + 4, Iclass_xt_iclass_xsr_ccompare2_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_icache_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_icache_lock_args, + 2, Iclass_xt_iclass_icache_lock_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_icache_inv_args, + 2, Iclass_xt_iclass_icache_inv_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_licx_args, + 2, Iclass_xt_iclass_licx_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_sicx_args, + 2, Iclass_xt_iclass_sicx_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_dcache_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_dcache_dyn_args, + 2, Iclass_xt_iclass_dcache_dyn_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_dcache_ind_args, + 2, Iclass_xt_iclass_dcache_ind_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_dcache_inv_args, + 2, Iclass_xt_iclass_dcache_inv_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_dpf_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_dcache_lock_args, + 2, Iclass_xt_iclass_dcache_lock_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_sdct_args, + 2, Iclass_xt_iclass_sdct_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_ldct_args, + 2, Iclass_xt_iclass_ldct_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_sdcw_args, + 2, Iclass_xt_iclass_sdcw_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_ldcw_args, + 2, Iclass_xt_iclass_ldcw_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ptevaddr_args, + 4, Iclass_xt_iclass_wsr_ptevaddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ptevaddr_args, + 4, Iclass_xt_iclass_rsr_ptevaddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ptevaddr_args, + 5, Iclass_xt_iclass_xsr_ptevaddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_rasid_args, + 5, Iclass_xt_iclass_rsr_rasid_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_rasid_args, + 6, Iclass_xt_iclass_wsr_rasid_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_rasid_args, + 6, Iclass_xt_iclass_xsr_rasid_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_itlbcfg_args, + 5, Iclass_xt_iclass_rsr_itlbcfg_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_itlbcfg_args, + 6, Iclass_xt_iclass_wsr_itlbcfg_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_itlbcfg_args, + 6, Iclass_xt_iclass_xsr_itlbcfg_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_dtlbcfg_args, + 5, Iclass_xt_iclass_rsr_dtlbcfg_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_dtlbcfg_args, + 6, Iclass_xt_iclass_wsr_dtlbcfg_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_dtlbcfg_args, + 6, Iclass_xt_iclass_xsr_dtlbcfg_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_idtlb_args, + 3, Iclass_xt_iclass_idtlb_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_rdtlb_args, + 2, Iclass_xt_iclass_rdtlb_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_wdtlb_args, + 3, Iclass_xt_iclass_wdtlb_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_iitlb_args, + 2, Iclass_xt_iclass_iitlb_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_ritlb_args, + 2, Iclass_xt_iclass_ritlb_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_witlb_args, + 2, Iclass_xt_iclass_witlb_stateArgs, 0, 0 }, + { 0, 0 /* xt_iclass_ldpte */, + 2, Iclass_xt_iclass_ldpte_stateArgs, 0, 0 }, + { 0, 0 /* xt_iclass_hwwitlba */, + 1, Iclass_xt_iclass_hwwitlba_stateArgs, 0, 0 }, + { 0, 0 /* xt_iclass_hwwdtlba */, + 1, Iclass_xt_iclass_hwwdtlba_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_cpenable_args, + 3, Iclass_xt_iclass_rsr_cpenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_cpenable_args, + 3, Iclass_xt_iclass_wsr_cpenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_cpenable_args, + 3, Iclass_xt_iclass_xsr_cpenable_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_clamp_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_minmax_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_nsa_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_sx_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_l32ai_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s32ri_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s32c1i_args, + 3, Iclass_xt_iclass_s32c1i_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_scompare1_args, + 1, Iclass_xt_iclass_rsr_scompare1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_scompare1_args, + 1, Iclass_xt_iclass_wsr_scompare1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_scompare1_args, + 1, Iclass_xt_iclass_xsr_scompare1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_atomctl_args, + 3, Iclass_xt_iclass_rsr_atomctl_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_atomctl_args, + 4, Iclass_xt_iclass_wsr_atomctl_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_atomctl_args, + 4, Iclass_xt_iclass_xsr_atomctl_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_div_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eraccess_args, + 3, Iclass_xt_iclass_rsr_eraccess_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eraccess_args, + 3, Iclass_xt_iclass_wsr_eraccess_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eraccess_args, + 3, Iclass_xt_iclass_xsr_eraccess_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_rer_args, + 3, Iclass_xt_iclass_rer_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_wer_args, + 3, Iclass_xt_iclass_wer_stateArgs, 0, 0 }, + { 1, Iclass_rur_fcr_args, + 9, Iclass_rur_fcr_stateArgs, 0, 0 }, + { 1, Iclass_wur_fcr_args, + 9, Iclass_wur_fcr_stateArgs, 0, 0 }, + { 1, Iclass_rur_fsr_args, + 8, Iclass_rur_fsr_stateArgs, 0, 0 }, + { 1, Iclass_wur_fsr_args, + 8, Iclass_wur_fsr_stateArgs, 0, 0 }, + { 1, Iclass_iclass_READ_IMPWIRE_args, + 1, Iclass_iclass_READ_IMPWIRE_stateArgs, 1, Iclass_iclass_READ_IMPWIRE_intfArgs }, + { 1, Iclass_iclass_SETB_EXPSTATE_args, + 2, Iclass_iclass_SETB_EXPSTATE_stateArgs, 0, 0 }, + { 1, Iclass_iclass_CLRB_EXPSTATE_args, + 2, Iclass_iclass_CLRB_EXPSTATE_stateArgs, 0, 0 }, + { 2, Iclass_iclass_WRMSK_EXPSTATE_args, + 2, Iclass_iclass_WRMSK_EXPSTATE_stateArgs, 0, 0 }, + { 1, Iclass_rur_expstate_args, + 2, Iclass_rur_expstate_stateArgs, 0, 0 }, + { 1, Iclass_wur_expstate_args, + 2, Iclass_wur_expstate_stateArgs, 0, 0 }, + { 3, Iclass_LSI_args, + 1, Iclass_LSI_stateArgs, 0, 0 }, + { 3, Iclass_LSIP_args, + 1, Iclass_LSIP_stateArgs, 0, 0 }, + { 3, Iclass_LSX_args, + 1, Iclass_LSX_stateArgs, 0, 0 }, + { 3, Iclass_LSXP_args, + 1, Iclass_LSXP_stateArgs, 0, 0 }, + { 3, Iclass_SSI_args, + 1, Iclass_SSI_stateArgs, 0, 0 }, + { 3, Iclass_SSIP_args, + 1, Iclass_SSIP_stateArgs, 0, 0 }, + { 3, Iclass_SSX_args, + 1, Iclass_SSX_stateArgs, 0, 0 }, + { 3, Iclass_SSXP_args, + 1, Iclass_SSXP_stateArgs, 0, 0 }, + { 3, Iclass_LDI_args, + 1, Iclass_LDI_stateArgs, 0, 0 }, + { 3, Iclass_LDIP_args, + 1, Iclass_LDIP_stateArgs, 0, 0 }, + { 3, Iclass_LDX_args, + 1, Iclass_LDX_stateArgs, 0, 0 }, + { 3, Iclass_LDXP_args, + 1, Iclass_LDXP_stateArgs, 0, 0 }, + { 3, Iclass_SDI_args, + 1, Iclass_SDI_stateArgs, 0, 0 }, + { 3, Iclass_SDIP_args, + 1, Iclass_SDIP_stateArgs, 0, 0 }, + { 3, Iclass_SDX_args, + 1, Iclass_SDX_stateArgs, 0, 0 }, + { 3, Iclass_SDXP_args, + 1, Iclass_SDXP_stateArgs, 0, 0 }, + { 2, Iclass_ABS_S_args, + 1, Iclass_ABS_S_stateArgs, 0, 0 }, + { 2, Iclass_NEG_S_args, + 1, Iclass_NEG_S_stateArgs, 0, 0 }, + { 2, Iclass_ABS_D_args, + 1, Iclass_ABS_D_stateArgs, 0, 0 }, + { 2, Iclass_NEG_D_args, + 1, Iclass_NEG_D_stateArgs, 0, 0 }, + { 2, Iclass_MOV_S_args, + 1, Iclass_MOV_S_stateArgs, 0, 0 }, + { 2, Iclass_MOV_D_args, + 1, Iclass_MOV_D_stateArgs, 0, 0 }, + { 3, Iclass_MOVEQZ_S_args, + 1, Iclass_MOVEQZ_S_stateArgs, 0, 0 }, + { 3, Iclass_MOVNEZ_S_args, + 1, Iclass_MOVNEZ_S_stateArgs, 0, 0 }, + { 3, Iclass_MOVLTZ_S_args, + 1, Iclass_MOVLTZ_S_stateArgs, 0, 0 }, + { 3, Iclass_MOVGEZ_S_args, + 1, Iclass_MOVGEZ_S_stateArgs, 0, 0 }, + { 3, Iclass_MOVF_S_args, + 1, Iclass_MOVF_S_stateArgs, 0, 0 }, + { 3, Iclass_MOVT_S_args, + 1, Iclass_MOVT_S_stateArgs, 0, 0 }, + { 2, Iclass_WFR_args, + 1, Iclass_WFR_stateArgs, 0, 0 }, + { 2, Iclass_RFR_args, + 1, Iclass_RFR_stateArgs, 0, 0 }, + { 2, Iclass_RFRD_args, + 1, Iclass_RFRD_stateArgs, 0, 0 }, + { 3, Iclass_WFRD_args, + 1, Iclass_WFRD_stateArgs, 0, 0 }, + { 3, Iclass_ROUND_S_args, + 3, Iclass_ROUND_S_stateArgs, 0, 0 }, + { 3, Iclass_ROUND_D_args, + 3, Iclass_ROUND_D_stateArgs, 0, 0 }, + { 3, Iclass_CEIL_S_args, + 3, Iclass_CEIL_S_stateArgs, 0, 0 }, + { 3, Iclass_CEIL_D_args, + 3, Iclass_CEIL_D_stateArgs, 0, 0 }, + { 3, Iclass_FLOOR_S_args, + 3, Iclass_FLOOR_S_stateArgs, 0, 0 }, + { 3, Iclass_FLOOR_D_args, + 3, Iclass_FLOOR_D_stateArgs, 0, 0 }, + { 3, Iclass_TRUNC_S_args, + 3, Iclass_TRUNC_S_stateArgs, 0, 0 }, + { 3, Iclass_TRUNC_D_args, + 3, Iclass_TRUNC_D_stateArgs, 0, 0 }, + { 3, Iclass_UTRUNC_S_args, + 3, Iclass_UTRUNC_S_stateArgs, 0, 0 }, + { 3, Iclass_UTRUNC_D_args, + 3, Iclass_UTRUNC_D_stateArgs, 0, 0 }, + { 3, Iclass_FLOAT_S_args, + 3, Iclass_FLOAT_S_stateArgs, 0, 0 }, + { 3, Iclass_FLOAT_D_args, + 2, Iclass_FLOAT_D_stateArgs, 0, 0 }, + { 3, Iclass_UFLOAT_S_args, + 3, Iclass_UFLOAT_S_stateArgs, 0, 0 }, + { 3, Iclass_UFLOAT_D_args, + 2, Iclass_UFLOAT_D_stateArgs, 0, 0 }, + { 2, Iclass_CVTD_S_args, + 2, Iclass_CVTD_S_stateArgs, 0, 0 }, + { 2, Iclass_CVTS_D_args, + 6, Iclass_CVTS_D_stateArgs, 0, 0 }, + { 3, Iclass_UN_S_args, + 2, Iclass_UN_S_stateArgs, 0, 0 }, + { 3, Iclass_UN_D_args, + 2, Iclass_UN_D_stateArgs, 0, 0 }, + { 3, Iclass_ULT_S_args, + 2, Iclass_ULT_S_stateArgs, 0, 0 }, + { 3, Iclass_ULT_D_args, + 2, Iclass_ULT_D_stateArgs, 0, 0 }, + { 3, Iclass_ULE_S_args, + 2, Iclass_ULE_S_stateArgs, 0, 0 }, + { 3, Iclass_ULE_D_args, + 2, Iclass_ULE_D_stateArgs, 0, 0 }, + { 3, Iclass_UEQ_S_args, + 2, Iclass_UEQ_S_stateArgs, 0, 0 }, + { 3, Iclass_UEQ_D_args, + 2, Iclass_UEQ_D_stateArgs, 0, 0 }, + { 3, Iclass_OLT_S_args, + 2, Iclass_OLT_S_stateArgs, 0, 0 }, + { 3, Iclass_OLT_D_args, + 2, Iclass_OLT_D_stateArgs, 0, 0 }, + { 3, Iclass_OLE_S_args, + 2, Iclass_OLE_S_stateArgs, 0, 0 }, + { 3, Iclass_OLE_D_args, + 2, Iclass_OLE_D_stateArgs, 0, 0 }, + { 3, Iclass_OEQ_S_args, + 2, Iclass_OEQ_S_stateArgs, 0, 0 }, + { 3, Iclass_OEQ_D_args, + 2, Iclass_OEQ_D_stateArgs, 0, 0 }, + { 3, Iclass_ADD_S_args, + 6, Iclass_ADD_S_stateArgs, 0, 0 }, + { 3, Iclass_ADD_D_args, + 6, Iclass_ADD_D_stateArgs, 0, 0 }, + { 3, Iclass_SUB_S_args, + 6, Iclass_SUB_S_stateArgs, 0, 0 }, + { 3, Iclass_SUB_D_args, + 6, Iclass_SUB_D_stateArgs, 0, 0 }, + { 3, Iclass_MUL_S_args, + 6, Iclass_MUL_S_stateArgs, 0, 0 }, + { 3, Iclass_MUL_D_args, + 6, Iclass_MUL_D_stateArgs, 0, 0 }, + { 3, Iclass_MADD_S_args, + 6, Iclass_MADD_S_stateArgs, 0, 0 }, + { 3, Iclass_MADD_D_args, + 6, Iclass_MADD_D_stateArgs, 0, 0 }, + { 3, Iclass_MSUB_S_args, + 6, Iclass_MSUB_S_stateArgs, 0, 0 }, + { 3, Iclass_MSUB_D_args, + 6, Iclass_MSUB_D_stateArgs, 0, 0 }, + { 2, Iclass_SQRT0_S_args, + 1, Iclass_SQRT0_S_stateArgs, 0, 0 }, + { 2, Iclass_SQRT0_D_args, + 1, Iclass_SQRT0_D_stateArgs, 0, 0 }, + { 2, Iclass_DIV0_S_args, + 1, Iclass_DIV0_S_stateArgs, 0, 0 }, + { 2, Iclass_DIV0_D_args, + 1, Iclass_DIV0_D_stateArgs, 0, 0 }, + { 2, Iclass_RECIP0_S_args, + 3, Iclass_RECIP0_S_stateArgs, 0, 0 }, + { 2, Iclass_RECIP0_D_args, + 3, Iclass_RECIP0_D_stateArgs, 0, 0 }, + { 2, Iclass_RSQRT0_S_args, + 3, Iclass_RSQRT0_S_stateArgs, 0, 0 }, + { 2, Iclass_RSQRT0_D_args, + 3, Iclass_RSQRT0_D_stateArgs, 0, 0 }, + { 3, Iclass_MADDN_S_args, + 1, Iclass_MADDN_S_stateArgs, 0, 0 }, + { 3, Iclass_MADDN_D_args, + 1, Iclass_MADDN_D_stateArgs, 0, 0 }, + { 3, Iclass_DIVN_S_args, + 5, Iclass_DIVN_S_stateArgs, 0, 0 }, + { 3, Iclass_DIVN_D_args, + 5, Iclass_DIVN_D_stateArgs, 0, 0 }, + { 2, Iclass_CONST_S_args, + 1, Iclass_CONST_S_stateArgs, 0, 0 }, + { 2, Iclass_CONST_D_args, + 1, Iclass_CONST_D_stateArgs, 0, 0 }, + { 2, Iclass_NEXP01_S_args, + 1, Iclass_NEXP01_S_stateArgs, 0, 0 }, + { 2, Iclass_NEXP01_D_args, + 1, Iclass_NEXP01_D_stateArgs, 0, 0 }, + { 2, Iclass_ADDEXP_S_args, + 1, Iclass_ADDEXP_S_stateArgs, 0, 0 }, + { 2, Iclass_ADDEXP_D_args, + 1, Iclass_ADDEXP_D_stateArgs, 0, 0 }, + { 2, Iclass_ADDEXPM_S_args, + 1, Iclass_ADDEXPM_S_stateArgs, 0, 0 }, + { 2, Iclass_ADDEXPM_D_args, + 1, Iclass_ADDEXPM_D_stateArgs, 0, 0 }, + { 2, Iclass_MKDADJ_S_args, + 3, Iclass_MKDADJ_S_stateArgs, 0, 0 }, + { 2, Iclass_MKDADJ_D_args, + 3, Iclass_MKDADJ_D_stateArgs, 0, 0 }, + { 2, Iclass_MKSADJ_S_args, + 2, Iclass_MKSADJ_S_stateArgs, 0, 0 }, + { 2, Iclass_MKSADJ_D_args, + 2, Iclass_MKSADJ_D_stateArgs, 0, 0 } +}; + +enum xtensa_iclass_id { + ICLASS_xt_iclass_excw, + ICLASS_xt_iclass_rfe, + ICLASS_xt_iclass_rfde, + ICLASS_xt_iclass_syscall, + ICLASS_xt_iclass_call12, + ICLASS_xt_iclass_call8, + ICLASS_xt_iclass_call4, + ICLASS_xt_iclass_callx12, + ICLASS_xt_iclass_callx8, + ICLASS_xt_iclass_callx4, + ICLASS_xt_iclass_entry, + ICLASS_xt_iclass_movsp, + ICLASS_xt_iclass_rotw, + ICLASS_xt_iclass_retw, + ICLASS_xt_iclass_rfwou, + ICLASS_xt_iclass_l32e, + ICLASS_xt_iclass_s32e, + ICLASS_xt_iclass_rsr_windowbase, + ICLASS_xt_iclass_wsr_windowbase, + ICLASS_xt_iclass_xsr_windowbase, + ICLASS_xt_iclass_rsr_windowstart, + ICLASS_xt_iclass_wsr_windowstart, + ICLASS_xt_iclass_xsr_windowstart, + ICLASS_xt_iclass_add_n, + ICLASS_xt_iclass_addi_n, + ICLASS_xt_iclass_bz6, + ICLASS_xt_iclass_ill_n, + ICLASS_xt_iclass_loadi4, + ICLASS_xt_iclass_mov_n, + ICLASS_xt_iclass_movi_n, + ICLASS_xt_iclass_nopn, + ICLASS_xt_iclass_retn, + ICLASS_xt_iclass_storei4, + ICLASS_rur_threadptr, + ICLASS_wur_threadptr, + ICLASS_xt_iclass_addi, + ICLASS_xt_iclass_addmi, + ICLASS_xt_iclass_addsub, + ICLASS_xt_iclass_bit, + ICLASS_xt_iclass_bsi8, + ICLASS_xt_iclass_bsi8b, + ICLASS_xt_iclass_bsi8u, + ICLASS_xt_iclass_bst8, + ICLASS_xt_iclass_bsz12, + ICLASS_xt_iclass_call0, + ICLASS_xt_iclass_callx0, + ICLASS_xt_iclass_exti, + ICLASS_xt_iclass_ill, + ICLASS_xt_iclass_jump, + ICLASS_xt_iclass_jumpx, + ICLASS_xt_iclass_l16ui, + ICLASS_xt_iclass_l16si, + ICLASS_xt_iclass_l32i, + ICLASS_xt_iclass_l32r, + ICLASS_xt_iclass_l8i, + ICLASS_xt_iclass_loop, + ICLASS_xt_iclass_loopz, + ICLASS_xt_iclass_movi, + ICLASS_xt_iclass_movz, + ICLASS_xt_iclass_neg, + ICLASS_xt_iclass_nop, + ICLASS_xt_iclass_return, + ICLASS_xt_iclass_simcall, + ICLASS_xt_iclass_s16i, + ICLASS_xt_iclass_s32i, + ICLASS_xt_iclass_s32nb, + ICLASS_xt_iclass_s8i, + ICLASS_xt_iclass_sar, + ICLASS_xt_iclass_sari, + ICLASS_xt_iclass_shifts, + ICLASS_xt_iclass_shiftst, + ICLASS_xt_iclass_shiftt, + ICLASS_xt_iclass_slli, + ICLASS_xt_iclass_srai, + ICLASS_xt_iclass_srli, + ICLASS_xt_iclass_memw, + ICLASS_xt_iclass_extw, + ICLASS_xt_iclass_isync, + ICLASS_xt_iclass_sync, + ICLASS_xt_iclass_rsil, + ICLASS_xt_iclass_rsr_lend, + ICLASS_xt_iclass_wsr_lend, + ICLASS_xt_iclass_xsr_lend, + ICLASS_xt_iclass_rsr_lcount, + ICLASS_xt_iclass_wsr_lcount, + ICLASS_xt_iclass_xsr_lcount, + ICLASS_xt_iclass_rsr_lbeg, + ICLASS_xt_iclass_wsr_lbeg, + ICLASS_xt_iclass_xsr_lbeg, + ICLASS_xt_iclass_rsr_sar, + ICLASS_xt_iclass_wsr_sar, + ICLASS_xt_iclass_xsr_sar, + ICLASS_xt_iclass_rsr_memctl, + ICLASS_xt_iclass_wsr_memctl, + ICLASS_xt_iclass_xsr_memctl, + ICLASS_xt_iclass_rsr_configid0, + ICLASS_xt_iclass_wsr_configid0, + ICLASS_xt_iclass_rsr_configid1, + ICLASS_xt_iclass_rsr_ps, + ICLASS_xt_iclass_wsr_ps, + ICLASS_xt_iclass_xsr_ps, + ICLASS_xt_iclass_rsr_epc1, + ICLASS_xt_iclass_wsr_epc1, + ICLASS_xt_iclass_xsr_epc1, + ICLASS_xt_iclass_rsr_excsave1, + ICLASS_xt_iclass_wsr_excsave1, + ICLASS_xt_iclass_xsr_excsave1, + ICLASS_xt_iclass_rsr_epc2, + ICLASS_xt_iclass_wsr_epc2, + ICLASS_xt_iclass_xsr_epc2, + ICLASS_xt_iclass_rsr_excsave2, + ICLASS_xt_iclass_wsr_excsave2, + ICLASS_xt_iclass_xsr_excsave2, + ICLASS_xt_iclass_rsr_epc3, + ICLASS_xt_iclass_wsr_epc3, + ICLASS_xt_iclass_xsr_epc3, + ICLASS_xt_iclass_rsr_excsave3, + ICLASS_xt_iclass_wsr_excsave3, + ICLASS_xt_iclass_xsr_excsave3, + ICLASS_xt_iclass_rsr_epc4, + ICLASS_xt_iclass_wsr_epc4, + ICLASS_xt_iclass_xsr_epc4, + ICLASS_xt_iclass_rsr_excsave4, + ICLASS_xt_iclass_wsr_excsave4, + ICLASS_xt_iclass_xsr_excsave4, + ICLASS_xt_iclass_rsr_epc5, + ICLASS_xt_iclass_wsr_epc5, + ICLASS_xt_iclass_xsr_epc5, + ICLASS_xt_iclass_rsr_excsave5, + ICLASS_xt_iclass_wsr_excsave5, + ICLASS_xt_iclass_xsr_excsave5, + ICLASS_xt_iclass_rsr_epc6, + ICLASS_xt_iclass_wsr_epc6, + ICLASS_xt_iclass_xsr_epc6, + ICLASS_xt_iclass_rsr_excsave6, + ICLASS_xt_iclass_wsr_excsave6, + ICLASS_xt_iclass_xsr_excsave6, + ICLASS_xt_iclass_rsr_epc7, + ICLASS_xt_iclass_wsr_epc7, + ICLASS_xt_iclass_xsr_epc7, + ICLASS_xt_iclass_rsr_excsave7, + ICLASS_xt_iclass_wsr_excsave7, + ICLASS_xt_iclass_xsr_excsave7, + ICLASS_xt_iclass_rsr_eps2, + ICLASS_xt_iclass_wsr_eps2, + ICLASS_xt_iclass_xsr_eps2, + ICLASS_xt_iclass_rsr_eps3, + ICLASS_xt_iclass_wsr_eps3, + ICLASS_xt_iclass_xsr_eps3, + ICLASS_xt_iclass_rsr_eps4, + ICLASS_xt_iclass_wsr_eps4, + ICLASS_xt_iclass_xsr_eps4, + ICLASS_xt_iclass_rsr_eps5, + ICLASS_xt_iclass_wsr_eps5, + ICLASS_xt_iclass_xsr_eps5, + ICLASS_xt_iclass_rsr_eps6, + ICLASS_xt_iclass_wsr_eps6, + ICLASS_xt_iclass_xsr_eps6, + ICLASS_xt_iclass_rsr_eps7, + ICLASS_xt_iclass_wsr_eps7, + ICLASS_xt_iclass_xsr_eps7, + ICLASS_xt_iclass_rsr_excvaddr, + ICLASS_xt_iclass_wsr_excvaddr, + ICLASS_xt_iclass_xsr_excvaddr, + ICLASS_xt_iclass_rsr_depc, + ICLASS_xt_iclass_wsr_depc, + ICLASS_xt_iclass_xsr_depc, + ICLASS_xt_iclass_rsr_exccause, + ICLASS_xt_iclass_wsr_exccause, + ICLASS_xt_iclass_xsr_exccause, + ICLASS_xt_iclass_rsr_misc0, + ICLASS_xt_iclass_wsr_misc0, + ICLASS_xt_iclass_xsr_misc0, + ICLASS_xt_iclass_rsr_misc1, + ICLASS_xt_iclass_wsr_misc1, + ICLASS_xt_iclass_xsr_misc1, + ICLASS_xt_iclass_rsr_prid, + ICLASS_xt_iclass_rsr_vecbase, + ICLASS_xt_iclass_wsr_vecbase, + ICLASS_xt_iclass_xsr_vecbase, + ICLASS_xt_iclass_salt, + ICLASS_xt_mul16, + ICLASS_xt_mul32, + ICLASS_xt_iclass_mac16_aa, + ICLASS_xt_iclass_mac16_ad, + ICLASS_xt_iclass_mac16_da, + ICLASS_xt_iclass_mac16_dd, + ICLASS_xt_iclass_mac16a_aa, + ICLASS_xt_iclass_mac16a_ad, + ICLASS_xt_iclass_mac16a_da, + ICLASS_xt_iclass_mac16a_dd, + ICLASS_xt_iclass_mac16al_da, + ICLASS_xt_iclass_mac16al_dd, + ICLASS_xt_iclass_mac16_l, + ICLASS_xt_iclass_rsr_m0, + ICLASS_xt_iclass_wsr_m0, + ICLASS_xt_iclass_xsr_m0, + ICLASS_xt_iclass_rsr_m1, + ICLASS_xt_iclass_wsr_m1, + ICLASS_xt_iclass_xsr_m1, + ICLASS_xt_iclass_rsr_m2, + ICLASS_xt_iclass_wsr_m2, + ICLASS_xt_iclass_xsr_m2, + ICLASS_xt_iclass_rsr_m3, + ICLASS_xt_iclass_wsr_m3, + ICLASS_xt_iclass_xsr_m3, + ICLASS_xt_iclass_rsr_acclo, + ICLASS_xt_iclass_wsr_acclo, + ICLASS_xt_iclass_xsr_acclo, + ICLASS_xt_iclass_rsr_acchi, + ICLASS_xt_iclass_wsr_acchi, + ICLASS_xt_iclass_xsr_acchi, + ICLASS_xt_iclass_rfi, + ICLASS_xt_iclass_wait, + ICLASS_xt_iclass_rsr_interrupt, + ICLASS_xt_iclass_wsr_intset, + ICLASS_xt_iclass_wsr_intclear, + ICLASS_xt_iclass_rsr_intenable, + ICLASS_xt_iclass_wsr_intenable, + ICLASS_xt_iclass_xsr_intenable, + ICLASS_xt_iclass_break, + ICLASS_xt_iclass_break_n, + ICLASS_xt_iclass_rsr_dbreaka0, + ICLASS_xt_iclass_wsr_dbreaka0, + ICLASS_xt_iclass_xsr_dbreaka0, + ICLASS_xt_iclass_rsr_dbreakc0, + ICLASS_xt_iclass_wsr_dbreakc0, + ICLASS_xt_iclass_xsr_dbreakc0, + ICLASS_xt_iclass_rsr_dbreaka1, + ICLASS_xt_iclass_wsr_dbreaka1, + ICLASS_xt_iclass_xsr_dbreaka1, + ICLASS_xt_iclass_rsr_dbreakc1, + ICLASS_xt_iclass_wsr_dbreakc1, + ICLASS_xt_iclass_xsr_dbreakc1, + ICLASS_xt_iclass_rsr_ibreaka0, + ICLASS_xt_iclass_wsr_ibreaka0, + ICLASS_xt_iclass_xsr_ibreaka0, + ICLASS_xt_iclass_rsr_ibreaka1, + ICLASS_xt_iclass_wsr_ibreaka1, + ICLASS_xt_iclass_xsr_ibreaka1, + ICLASS_xt_iclass_rsr_ibreakenable, + ICLASS_xt_iclass_wsr_ibreakenable, + ICLASS_xt_iclass_xsr_ibreakenable, + ICLASS_xt_iclass_rsr_debugcause, + ICLASS_xt_iclass_wsr_debugcause, + ICLASS_xt_iclass_xsr_debugcause, + ICLASS_xt_iclass_rsr_icount, + ICLASS_xt_iclass_wsr_icount, + ICLASS_xt_iclass_xsr_icount, + ICLASS_xt_iclass_rsr_icountlevel, + ICLASS_xt_iclass_wsr_icountlevel, + ICLASS_xt_iclass_xsr_icountlevel, + ICLASS_xt_iclass_rsr_ddr, + ICLASS_xt_iclass_wsr_ddr, + ICLASS_xt_iclass_xsr_ddr, + ICLASS_xt_iclass_lddr32_p, + ICLASS_xt_iclass_sddr32_p, + ICLASS_xt_iclass_rfdo, + ICLASS_xt_iclass_rfdd, + ICLASS_xt_iclass_wsr_mmid, + ICLASS_xt_iclass_bbool1, + ICLASS_xt_iclass_bbool4, + ICLASS_xt_iclass_bbool8, + ICLASS_xt_iclass_bbranch, + ICLASS_xt_iclass_bmove, + ICLASS_xt_iclass_RSR_BR, + ICLASS_xt_iclass_WSR_BR, + ICLASS_xt_iclass_XSR_BR, + ICLASS_xt_iclass_rsr_ccount, + ICLASS_xt_iclass_wsr_ccount, + ICLASS_xt_iclass_xsr_ccount, + ICLASS_xt_iclass_rsr_ccompare0, + ICLASS_xt_iclass_wsr_ccompare0, + ICLASS_xt_iclass_xsr_ccompare0, + ICLASS_xt_iclass_rsr_ccompare1, + ICLASS_xt_iclass_wsr_ccompare1, + ICLASS_xt_iclass_xsr_ccompare1, + ICLASS_xt_iclass_rsr_ccompare2, + ICLASS_xt_iclass_wsr_ccompare2, + ICLASS_xt_iclass_xsr_ccompare2, + ICLASS_xt_iclass_icache, + ICLASS_xt_iclass_icache_lock, + ICLASS_xt_iclass_icache_inv, + ICLASS_xt_iclass_licx, + ICLASS_xt_iclass_sicx, + ICLASS_xt_iclass_dcache, + ICLASS_xt_iclass_dcache_dyn, + ICLASS_xt_iclass_dcache_ind, + ICLASS_xt_iclass_dcache_inv, + ICLASS_xt_iclass_dpf, + ICLASS_xt_iclass_dcache_lock, + ICLASS_xt_iclass_sdct, + ICLASS_xt_iclass_ldct, + ICLASS_xt_iclass_sdcw, + ICLASS_xt_iclass_ldcw, + ICLASS_xt_iclass_wsr_ptevaddr, + ICLASS_xt_iclass_rsr_ptevaddr, + ICLASS_xt_iclass_xsr_ptevaddr, + ICLASS_xt_iclass_rsr_rasid, + ICLASS_xt_iclass_wsr_rasid, + ICLASS_xt_iclass_xsr_rasid, + ICLASS_xt_iclass_rsr_itlbcfg, + ICLASS_xt_iclass_wsr_itlbcfg, + ICLASS_xt_iclass_xsr_itlbcfg, + ICLASS_xt_iclass_rsr_dtlbcfg, + ICLASS_xt_iclass_wsr_dtlbcfg, + ICLASS_xt_iclass_xsr_dtlbcfg, + ICLASS_xt_iclass_idtlb, + ICLASS_xt_iclass_rdtlb, + ICLASS_xt_iclass_wdtlb, + ICLASS_xt_iclass_iitlb, + ICLASS_xt_iclass_ritlb, + ICLASS_xt_iclass_witlb, + ICLASS_xt_iclass_ldpte, + ICLASS_xt_iclass_hwwitlba, + ICLASS_xt_iclass_hwwdtlba, + ICLASS_xt_iclass_rsr_cpenable, + ICLASS_xt_iclass_wsr_cpenable, + ICLASS_xt_iclass_xsr_cpenable, + ICLASS_xt_iclass_clamp, + ICLASS_xt_iclass_minmax, + ICLASS_xt_iclass_nsa, + ICLASS_xt_iclass_sx, + ICLASS_xt_iclass_l32ai, + ICLASS_xt_iclass_s32ri, + ICLASS_xt_iclass_s32c1i, + ICLASS_xt_iclass_rsr_scompare1, + ICLASS_xt_iclass_wsr_scompare1, + ICLASS_xt_iclass_xsr_scompare1, + ICLASS_xt_iclass_rsr_atomctl, + ICLASS_xt_iclass_wsr_atomctl, + ICLASS_xt_iclass_xsr_atomctl, + ICLASS_xt_iclass_div, + ICLASS_xt_iclass_rsr_eraccess, + ICLASS_xt_iclass_wsr_eraccess, + ICLASS_xt_iclass_xsr_eraccess, + ICLASS_xt_iclass_rer, + ICLASS_xt_iclass_wer, + ICLASS_rur_fcr, + ICLASS_wur_fcr, + ICLASS_rur_fsr, + ICLASS_wur_fsr, + ICLASS_iclass_READ_IMPWIRE, + ICLASS_iclass_SETB_EXPSTATE, + ICLASS_iclass_CLRB_EXPSTATE, + ICLASS_iclass_WRMSK_EXPSTATE, + ICLASS_rur_expstate, + ICLASS_wur_expstate, + ICLASS_LSI, + ICLASS_LSIP, + ICLASS_LSX, + ICLASS_LSXP, + ICLASS_SSI, + ICLASS_SSIP, + ICLASS_SSX, + ICLASS_SSXP, + ICLASS_LDI, + ICLASS_LDIP, + ICLASS_LDX, + ICLASS_LDXP, + ICLASS_SDI, + ICLASS_SDIP, + ICLASS_SDX, + ICLASS_SDXP, + ICLASS_ABS_S, + ICLASS_NEG_S, + ICLASS_ABS_D, + ICLASS_NEG_D, + ICLASS_MOV_S, + ICLASS_MOV_D, + ICLASS_MOVEQZ_S, + ICLASS_MOVNEZ_S, + ICLASS_MOVLTZ_S, + ICLASS_MOVGEZ_S, + ICLASS_MOVF_S, + ICLASS_MOVT_S, + ICLASS_WFR, + ICLASS_RFR, + ICLASS_RFRD, + ICLASS_WFRD, + ICLASS_ROUND_S, + ICLASS_ROUND_D, + ICLASS_CEIL_S, + ICLASS_CEIL_D, + ICLASS_FLOOR_S, + ICLASS_FLOOR_D, + ICLASS_TRUNC_S, + ICLASS_TRUNC_D, + ICLASS_UTRUNC_S, + ICLASS_UTRUNC_D, + ICLASS_FLOAT_S, + ICLASS_FLOAT_D, + ICLASS_UFLOAT_S, + ICLASS_UFLOAT_D, + ICLASS_CVTD_S, + ICLASS_CVTS_D, + ICLASS_UN_S, + ICLASS_UN_D, + ICLASS_ULT_S, + ICLASS_ULT_D, + ICLASS_ULE_S, + ICLASS_ULE_D, + ICLASS_UEQ_S, + ICLASS_UEQ_D, + ICLASS_OLT_S, + ICLASS_OLT_D, + ICLASS_OLE_S, + ICLASS_OLE_D, + ICLASS_OEQ_S, + ICLASS_OEQ_D, + ICLASS_ADD_S, + ICLASS_ADD_D, + ICLASS_SUB_S, + ICLASS_SUB_D, + ICLASS_MUL_S, + ICLASS_MUL_D, + ICLASS_MADD_S, + ICLASS_MADD_D, + ICLASS_MSUB_S, + ICLASS_MSUB_D, + ICLASS_SQRT0_S, + ICLASS_SQRT0_D, + ICLASS_DIV0_S, + ICLASS_DIV0_D, + ICLASS_RECIP0_S, + ICLASS_RECIP0_D, + ICLASS_RSQRT0_S, + ICLASS_RSQRT0_D, + ICLASS_MADDN_S, + ICLASS_MADDN_D, + ICLASS_DIVN_S, + ICLASS_DIVN_D, + ICLASS_CONST_S, + ICLASS_CONST_D, + ICLASS_NEXP01_S, + ICLASS_NEXP01_D, + ICLASS_ADDEXP_S, + ICLASS_ADDEXP_D, + ICLASS_ADDEXPM_S, + ICLASS_ADDEXPM_D, + ICLASS_MKDADJ_S, + ICLASS_MKDADJ_D, + ICLASS_MKSADJ_S, + ICLASS_MKSADJ_D +}; + + +/* Opcode encodings. */ + +static void +Opcode_excw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2080; +} + +static void +Opcode_rfe_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3000; +} + +static void +Opcode_rfde_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3200; +} + +static void +Opcode_syscall_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5000; +} + +static void +Opcode_call12_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35; +} + +static void +Opcode_call8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x25; +} + +static void +Opcode_call4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x15; +} + +static void +Opcode_callx12_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf0; +} + +static void +Opcode_callx8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe0; +} + +static void +Opcode_callx4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd0; +} + +static void +Opcode_entry_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x36; +} + +static void +Opcode_movsp_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1000; +} + +static void +Opcode_rotw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x408000; +} + +static void +Opcode_retw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x90; +} + +static void +Opcode_retw_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf01d; +} + +static void +Opcode_rfwo_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3400; +} + +static void +Opcode_rfwu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3500; +} + +static void +Opcode_l32e_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x90000; +} + +static void +Opcode_s32e_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x490000; +} + +static void +Opcode_rsr_windowbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34800; +} + +static void +Opcode_wsr_windowbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x134800; +} + +static void +Opcode_xsr_windowbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x614800; +} + +static void +Opcode_rsr_windowstart_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34900; +} + +static void +Opcode_wsr_windowstart_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x134900; +} + +static void +Opcode_xsr_windowstart_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x614900; +} + +static void +Opcode_add_n_Slot_inst16a_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa; +} + +static void +Opcode_addi_n_Slot_inst16a_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb; +} + +static void +Opcode_beqz_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8c; +} + +static void +Opcode_bnez_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcc; +} + +static void +Opcode_ill_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf06d; +} + +static void +Opcode_l32i_n_Slot_inst16a_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8; +} + +static void +Opcode_mov_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd; +} + +static void +Opcode_movi_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc; +} + +static void +Opcode_nop_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf03d; +} + +static void +Opcode_ret_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf00d; +} + +static void +Opcode_s32i_n_Slot_inst16a_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9; +} + +static void +Opcode_rur_threadptr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30e70; +} + +static void +Opcode_wur_threadptr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf3e700; +} + +static void +Opcode_addi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc002; +} + +static void +Opcode_addmi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd002; +} + +static void +Opcode_add_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800000; +} + +static void +Opcode_addx2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x900000; +} + +static void +Opcode_addx4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa00000; +} + +static void +Opcode_addx8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb00000; +} + +static void +Opcode_sub_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc00000; +} + +static void +Opcode_subx2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd00000; +} + +static void +Opcode_subx4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe00000; +} + +static void +Opcode_subx8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf00000; +} + +static void +Opcode_and_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x100000; +} + +static void +Opcode_or_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x200000; +} + +static void +Opcode_xor_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x300000; +} + +static void +Opcode_beqi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x26; +} + +static void +Opcode_bgei_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe6; +} + +static void +Opcode_blti_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa6; +} + +static void +Opcode_bnei_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x66; +} + +static void +Opcode_bbci_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6007; +} + +static void +Opcode_bbsi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe007; +} + +static void +Opcode_bgeui_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf6; +} + +static void +Opcode_bltui_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb6; +} + +static void +Opcode_ball_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4007; +} + +static void +Opcode_bany_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8007; +} + +static void +Opcode_bbc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5007; +} + +static void +Opcode_bbs_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd007; +} + +static void +Opcode_beq_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1007; +} + +static void +Opcode_bge_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa007; +} + +static void +Opcode_bgeu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb007; +} + +static void +Opcode_blt_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2007; +} + +static void +Opcode_bltu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3007; +} + +static void +Opcode_bnall_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc007; +} + +static void +Opcode_bne_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9007; +} + +static void +Opcode_bnone_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7; +} + +static void +Opcode_beqz_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16; +} + +static void +Opcode_bgez_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd6; +} + +static void +Opcode_bltz_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x96; +} + +static void +Opcode_bnez_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x56; +} + +static void +Opcode_call0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5; +} + +static void +Opcode_callx0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc0; +} + +static void +Opcode_extui_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40000; +} + +static void +Opcode_ill_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_j_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6; +} + +static void +Opcode_jx_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa0; +} + +static void +Opcode_l16ui_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1002; +} + +static void +Opcode_l16si_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9002; +} + +static void +Opcode_l32i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2002; +} + +static void +Opcode_l32r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_l8ui_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_loop_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8076; +} + +static void +Opcode_loopgtz_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa076; +} + +static void +Opcode_loopnez_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9076; +} + +static void +Opcode_movi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa002; +} + +static void +Opcode_moveqz_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x830000; +} + +static void +Opcode_movgez_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb30000; +} + +static void +Opcode_movltz_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa30000; +} + +static void +Opcode_movnez_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x930000; +} + +static void +Opcode_abs_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x600100; +} + +static void +Opcode_neg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x600000; +} + +static void +Opcode_nop_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20f0; +} + +static void +Opcode_ret_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80; +} + +static void +Opcode_simcall_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5100; +} + +static void +Opcode_s16i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5002; +} + +static void +Opcode_s32i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6002; +} + +static void +Opcode_s32nb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x590000; +} + +static void +Opcode_s8i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4002; +} + +static void +Opcode_ssa8b_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x403000; +} + +static void +Opcode_ssa8l_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x402000; +} + +static void +Opcode_ssl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x401000; +} + +static void +Opcode_ssr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400000; +} + +static void +Opcode_ssai_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x404000; +} + +static void +Opcode_sll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa10000; +} + +static void +Opcode_src_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x810000; +} + +static void +Opcode_sra_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb10000; +} + +static void +Opcode_srl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x910000; +} + +static void +Opcode_slli_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10000; +} + +static void +Opcode_srai_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x210000; +} + +static void +Opcode_srli_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x410000; +} + +static void +Opcode_memw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20c0; +} + +static void +Opcode_extw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20d0; +} + +static void +Opcode_isync_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2000; +} + +static void +Opcode_dsync_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2030; +} + +static void +Opcode_esync_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2020; +} + +static void +Opcode_rsync_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2010; +} + +static void +Opcode_rsil_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6000; +} + +static void +Opcode_rsr_lend_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30100; +} + +static void +Opcode_wsr_lend_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130100; +} + +static void +Opcode_xsr_lend_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610100; +} + +static void +Opcode_rsr_lcount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30200; +} + +static void +Opcode_wsr_lcount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130200; +} + +static void +Opcode_xsr_lcount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610200; +} + +static void +Opcode_rsr_lbeg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30000; +} + +static void +Opcode_wsr_lbeg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130000; +} + +static void +Opcode_xsr_lbeg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610000; +} + +static void +Opcode_rsr_sar_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30300; +} + +static void +Opcode_wsr_sar_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130300; +} + +static void +Opcode_xsr_sar_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610300; +} + +static void +Opcode_rsr_memctl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x36100; +} + +static void +Opcode_wsr_memctl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x136100; +} + +static void +Opcode_xsr_memctl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x616100; +} + +static void +Opcode_rsr_configid0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b000; +} + +static void +Opcode_wsr_configid0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b000; +} + +static void +Opcode_rsr_configid1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d000; +} + +static void +Opcode_rsr_ps_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e600; +} + +static void +Opcode_wsr_ps_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e600; +} + +static void +Opcode_xsr_ps_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e600; +} + +static void +Opcode_rsr_epc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b100; +} + +static void +Opcode_wsr_epc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b100; +} + +static void +Opcode_xsr_epc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b100; +} + +static void +Opcode_rsr_excsave1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d100; +} + +static void +Opcode_wsr_excsave1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d100; +} + +static void +Opcode_xsr_excsave1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d100; +} + +static void +Opcode_rsr_epc2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b200; +} + +static void +Opcode_wsr_epc2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b200; +} + +static void +Opcode_xsr_epc2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b200; +} + +static void +Opcode_rsr_excsave2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d200; +} + +static void +Opcode_wsr_excsave2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d200; +} + +static void +Opcode_xsr_excsave2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d200; +} + +static void +Opcode_rsr_epc3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b300; +} + +static void +Opcode_wsr_epc3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b300; +} + +static void +Opcode_xsr_epc3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b300; +} + +static void +Opcode_rsr_excsave3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d300; +} + +static void +Opcode_wsr_excsave3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d300; +} + +static void +Opcode_xsr_excsave3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d300; +} + +static void +Opcode_rsr_epc4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b400; +} + +static void +Opcode_wsr_epc4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b400; +} + +static void +Opcode_xsr_epc4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b400; +} + +static void +Opcode_rsr_excsave4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d400; +} + +static void +Opcode_wsr_excsave4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d400; +} + +static void +Opcode_xsr_excsave4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d400; +} + +static void +Opcode_rsr_epc5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b500; +} + +static void +Opcode_wsr_epc5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b500; +} + +static void +Opcode_xsr_epc5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b500; +} + +static void +Opcode_rsr_excsave5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d500; +} + +static void +Opcode_wsr_excsave5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d500; +} + +static void +Opcode_xsr_excsave5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d500; +} + +static void +Opcode_rsr_epc6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b600; +} + +static void +Opcode_wsr_epc6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b600; +} + +static void +Opcode_xsr_epc6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b600; +} + +static void +Opcode_rsr_excsave6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d600; +} + +static void +Opcode_wsr_excsave6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d600; +} + +static void +Opcode_xsr_excsave6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d600; +} + +static void +Opcode_rsr_epc7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b700; +} + +static void +Opcode_wsr_epc7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b700; +} + +static void +Opcode_xsr_epc7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b700; +} + +static void +Opcode_rsr_excsave7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d700; +} + +static void +Opcode_wsr_excsave7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d700; +} + +static void +Opcode_xsr_excsave7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d700; +} + +static void +Opcode_rsr_eps2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c200; +} + +static void +Opcode_wsr_eps2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c200; +} + +static void +Opcode_xsr_eps2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c200; +} + +static void +Opcode_rsr_eps3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c300; +} + +static void +Opcode_wsr_eps3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c300; +} + +static void +Opcode_xsr_eps3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c300; +} + +static void +Opcode_rsr_eps4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c400; +} + +static void +Opcode_wsr_eps4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c400; +} + +static void +Opcode_xsr_eps4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c400; +} + +static void +Opcode_rsr_eps5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c500; +} + +static void +Opcode_wsr_eps5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c500; +} + +static void +Opcode_xsr_eps5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c500; +} + +static void +Opcode_rsr_eps6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c600; +} + +static void +Opcode_wsr_eps6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c600; +} + +static void +Opcode_xsr_eps6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c600; +} + +static void +Opcode_rsr_eps7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c700; +} + +static void +Opcode_wsr_eps7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c700; +} + +static void +Opcode_xsr_eps7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c700; +} + +static void +Opcode_rsr_excvaddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3ee00; +} + +static void +Opcode_wsr_excvaddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13ee00; +} + +static void +Opcode_xsr_excvaddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61ee00; +} + +static void +Opcode_rsr_depc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c000; +} + +static void +Opcode_wsr_depc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c000; +} + +static void +Opcode_xsr_depc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c000; +} + +static void +Opcode_rsr_exccause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e800; +} + +static void +Opcode_wsr_exccause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e800; +} + +static void +Opcode_xsr_exccause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e800; +} + +static void +Opcode_rsr_misc0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f400; +} + +static void +Opcode_wsr_misc0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13f400; +} + +static void +Opcode_xsr_misc0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61f400; +} + +static void +Opcode_rsr_misc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f500; +} + +static void +Opcode_wsr_misc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13f500; +} + +static void +Opcode_xsr_misc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61f500; +} + +static void +Opcode_rsr_prid_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3eb00; +} + +static void +Opcode_rsr_vecbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e700; +} + +static void +Opcode_wsr_vecbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e700; +} + +static void +Opcode_xsr_vecbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e700; +} + +static void +Opcode_salt_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x720000; +} + +static void +Opcode_saltu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x620000; +} + +static void +Opcode_mul16s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd10000; +} + +static void +Opcode_mul16u_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc10000; +} + +static void +Opcode_mull_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x820000; +} + +static void +Opcode_mul_aa_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x770004; +} + +static void +Opcode_mul_aa_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x750004; +} + +static void +Opcode_mul_aa_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x760004; +} + +static void +Opcode_mul_aa_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x740004; +} + +static void +Opcode_umul_aa_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x730004; +} + +static void +Opcode_umul_aa_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x710004; +} + +static void +Opcode_umul_aa_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x720004; +} + +static void +Opcode_umul_aa_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x700004; +} + +static void +Opcode_mul_ad_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x370004; +} + +static void +Opcode_mul_ad_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x350004; +} + +static void +Opcode_mul_ad_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x360004; +} + +static void +Opcode_mul_ad_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x340004; +} + +static void +Opcode_mul_da_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x670004; +} + +static void +Opcode_mul_da_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x650004; +} + +static void +Opcode_mul_da_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x660004; +} + +static void +Opcode_mul_da_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x640004; +} + +static void +Opcode_mul_dd_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x270004; +} + +static void +Opcode_mul_dd_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x250004; +} + +static void +Opcode_mul_dd_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x260004; +} + +static void +Opcode_mul_dd_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x240004; +} + +static void +Opcode_mula_aa_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7b0004; +} + +static void +Opcode_mula_aa_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x790004; +} + +static void +Opcode_mula_aa_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7a0004; +} + +static void +Opcode_mula_aa_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x780004; +} + +static void +Opcode_muls_aa_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7f0004; +} + +static void +Opcode_muls_aa_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7d0004; +} + +static void +Opcode_muls_aa_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7e0004; +} + +static void +Opcode_muls_aa_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7c0004; +} + +static void +Opcode_mula_ad_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b0004; +} + +static void +Opcode_mula_ad_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x390004; +} + +static void +Opcode_mula_ad_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3a0004; +} + +static void +Opcode_mula_ad_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x380004; +} + +static void +Opcode_muls_ad_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f0004; +} + +static void +Opcode_muls_ad_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d0004; +} + +static void +Opcode_muls_ad_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e0004; +} + +static void +Opcode_muls_ad_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c0004; +} + +static void +Opcode_mula_da_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6b0004; +} + +static void +Opcode_mula_da_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x690004; +} + +static void +Opcode_mula_da_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a0004; +} + +static void +Opcode_mula_da_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x680004; +} + +static void +Opcode_muls_da_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6f0004; +} + +static void +Opcode_muls_da_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6d0004; +} + +static void +Opcode_muls_da_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6e0004; +} + +static void +Opcode_muls_da_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6c0004; +} + +static void +Opcode_mula_dd_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2b0004; +} + +static void +Opcode_mula_dd_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x290004; +} + +static void +Opcode_mula_dd_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2a0004; +} + +static void +Opcode_mula_dd_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x280004; +} + +static void +Opcode_muls_dd_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2f0004; +} + +static void +Opcode_muls_dd_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d0004; +} + +static void +Opcode_muls_dd_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2e0004; +} + +static void +Opcode_muls_dd_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c0004; +} + +static void +Opcode_mula_da_hh_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5b0004; +} + +static void +Opcode_mula_da_hh_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4b0004; +} + +static void +Opcode_mula_da_hl_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x590004; +} + +static void +Opcode_mula_da_hl_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x490004; +} + +static void +Opcode_mula_da_lh_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5a0004; +} + +static void +Opcode_mula_da_lh_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4a0004; +} + +static void +Opcode_mula_da_ll_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x580004; +} + +static void +Opcode_mula_da_ll_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x480004; +} + +static void +Opcode_mula_dd_hh_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1b0004; +} + +static void +Opcode_mula_dd_hh_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb0004; +} + +static void +Opcode_mula_dd_hl_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x190004; +} + +static void +Opcode_mula_dd_hl_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x90004; +} + +static void +Opcode_mula_dd_lh_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1a0004; +} + +static void +Opcode_mula_dd_lh_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa0004; +} + +static void +Opcode_mula_dd_ll_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x180004; +} + +static void +Opcode_mula_dd_ll_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80004; +} + +static void +Opcode_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x900004; +} + +static void +Opcode_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800004; +} + +static void +Opcode_rsr_m0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32000; +} + +static void +Opcode_wsr_m0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x132000; +} + +static void +Opcode_xsr_m0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x612000; +} + +static void +Opcode_rsr_m1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32100; +} + +static void +Opcode_wsr_m1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x132100; +} + +static void +Opcode_xsr_m1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x612100; +} + +static void +Opcode_rsr_m2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32200; +} + +static void +Opcode_wsr_m2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x132200; +} + +static void +Opcode_xsr_m2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x612200; +} + +static void +Opcode_rsr_m3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32300; +} + +static void +Opcode_wsr_m3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x132300; +} + +static void +Opcode_xsr_m3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x612300; +} + +static void +Opcode_rsr_acclo_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x31000; +} + +static void +Opcode_wsr_acclo_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x131000; +} + +static void +Opcode_xsr_acclo_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x611000; +} + +static void +Opcode_rsr_acchi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x31100; +} + +static void +Opcode_wsr_acchi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x131100; +} + +static void +Opcode_xsr_acchi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x611100; +} + +static void +Opcode_rfi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3010; +} + +static void +Opcode_waiti_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7000; +} + +static void +Opcode_rsr_interrupt_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e200; +} + +static void +Opcode_wsr_intset_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e200; +} + +static void +Opcode_wsr_intclear_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e300; +} + +static void +Opcode_rsr_intenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e400; +} + +static void +Opcode_wsr_intenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e400; +} + +static void +Opcode_xsr_intenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e400; +} + +static void +Opcode_break_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000; +} + +static void +Opcode_break_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf02d; +} + +static void +Opcode_rsr_dbreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x39000; +} + +static void +Opcode_wsr_dbreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x139000; +} + +static void +Opcode_xsr_dbreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x619000; +} + +static void +Opcode_rsr_dbreakc0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3a000; +} + +static void +Opcode_wsr_dbreakc0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13a000; +} + +static void +Opcode_xsr_dbreakc0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61a000; +} + +static void +Opcode_rsr_dbreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x39100; +} + +static void +Opcode_wsr_dbreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x139100; +} + +static void +Opcode_xsr_dbreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x619100; +} + +static void +Opcode_rsr_dbreakc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3a100; +} + +static void +Opcode_wsr_dbreakc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13a100; +} + +static void +Opcode_xsr_dbreakc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61a100; +} + +static void +Opcode_rsr_ibreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38000; +} + +static void +Opcode_wsr_ibreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x138000; +} + +static void +Opcode_xsr_ibreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x618000; +} + +static void +Opcode_rsr_ibreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38100; +} + +static void +Opcode_wsr_ibreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x138100; +} + +static void +Opcode_xsr_ibreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x618100; +} + +static void +Opcode_rsr_ibreakenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x36000; +} + +static void +Opcode_wsr_ibreakenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x136000; +} + +static void +Opcode_xsr_ibreakenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x616000; +} + +static void +Opcode_rsr_debugcause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e900; +} + +static void +Opcode_wsr_debugcause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e900; +} + +static void +Opcode_xsr_debugcause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e900; +} + +static void +Opcode_rsr_icount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3ec00; +} + +static void +Opcode_wsr_icount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13ec00; +} + +static void +Opcode_xsr_icount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61ec00; +} + +static void +Opcode_rsr_icountlevel_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3ed00; +} + +static void +Opcode_wsr_icountlevel_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13ed00; +} + +static void +Opcode_xsr_icountlevel_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61ed00; +} + +static void +Opcode_rsr_ddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x36800; +} + +static void +Opcode_wsr_ddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x136800; +} + +static void +Opcode_xsr_ddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x616800; +} + +static void +Opcode_lddr32_p_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70e0; +} + +static void +Opcode_sddr32_p_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70f0; +} + +static void +Opcode_rfdo_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf1e000; +} + +static void +Opcode_rfdd_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf1e010; +} + +static void +Opcode_wsr_mmid_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x135900; +} + +static void +Opcode_andb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20000; +} + +static void +Opcode_andbc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x120000; +} + +static void +Opcode_orb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x220000; +} + +static void +Opcode_orbc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x320000; +} + +static void +Opcode_xorb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x420000; +} + +static void +Opcode_all4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9000; +} + +static void +Opcode_any4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8000; +} + +static void +Opcode_all8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb000; +} + +static void +Opcode_any8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa000; +} + +static void +Opcode_bf_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x76; +} + +static void +Opcode_bt_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1076; +} + +static void +Opcode_movf_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc30000; +} + +static void +Opcode_movt_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd30000; +} + +static void +Opcode_rsr_br_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30400; +} + +static void +Opcode_wsr_br_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130400; +} + +static void +Opcode_xsr_br_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610400; +} + +static void +Opcode_rsr_ccount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3ea00; +} + +static void +Opcode_wsr_ccount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13ea00; +} + +static void +Opcode_xsr_ccount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61ea00; +} + +static void +Opcode_rsr_ccompare0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f000; +} + +static void +Opcode_wsr_ccompare0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13f000; +} + +static void +Opcode_xsr_ccompare0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61f000; +} + +static void +Opcode_rsr_ccompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f100; +} + +static void +Opcode_wsr_ccompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13f100; +} + +static void +Opcode_xsr_ccompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61f100; +} + +static void +Opcode_rsr_ccompare2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f200; +} + +static void +Opcode_wsr_ccompare2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13f200; +} + +static void +Opcode_xsr_ccompare2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61f200; +} + +static void +Opcode_ihi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70e2; +} + +static void +Opcode_ipf_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70c2; +} + +static void +Opcode_ihu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x270d2; +} + +static void +Opcode_iiu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x370d2; +} + +static void +Opcode_ipfl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70d2; +} + +static void +Opcode_iii_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70f2; +} + +static void +Opcode_lict_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf10000; +} + +static void +Opcode_licw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf12000; +} + +static void +Opcode_sict_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf11000; +} + +static void +Opcode_sicw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf13000; +} + +static void +Opcode_dhwb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7042; +} + +static void +Opcode_dhwbi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7052; +} + +static void +Opcode_diwbui_p_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf7082; +} + +static void +Opcode_diwb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x47082; +} + +static void +Opcode_diwbi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x57082; +} + +static void +Opcode_dhi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7062; +} + +static void +Opcode_dii_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7072; +} + +static void +Opcode_dpfr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7002; +} + +static void +Opcode_dpfro_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7022; +} + +static void +Opcode_dpfw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7012; +} + +static void +Opcode_dpfwo_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7032; +} + +static void +Opcode_dhu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x27082; +} + +static void +Opcode_diu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x37082; +} + +static void +Opcode_dpfl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7082; +} + +static void +Opcode_sdct_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf19000; +} + +static void +Opcode_ldct_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf18000; +} + +static void +Opcode_sdcw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf1b000; +} + +static void +Opcode_ldcw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf1a000; +} + +static void +Opcode_wsr_ptevaddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x135300; +} + +static void +Opcode_rsr_ptevaddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35300; +} + +static void +Opcode_xsr_ptevaddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x615300; +} + +static void +Opcode_rsr_rasid_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35a00; +} + +static void +Opcode_wsr_rasid_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x135a00; +} + +static void +Opcode_xsr_rasid_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x615a00; +} + +static void +Opcode_rsr_itlbcfg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35b00; +} + +static void +Opcode_wsr_itlbcfg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x135b00; +} + +static void +Opcode_xsr_itlbcfg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x615b00; +} + +static void +Opcode_rsr_dtlbcfg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35c00; +} + +static void +Opcode_wsr_dtlbcfg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x135c00; +} + +static void +Opcode_xsr_dtlbcfg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x615c00; +} + +static void +Opcode_idtlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50c000; +} + +static void +Opcode_pdtlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50d000; +} + +static void +Opcode_rdtlb0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50b000; +} + +static void +Opcode_rdtlb1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50f000; +} + +static void +Opcode_wdtlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50e000; +} + +static void +Opcode_iitlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x504000; +} + +static void +Opcode_pitlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x505000; +} + +static void +Opcode_ritlb0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x503000; +} + +static void +Opcode_ritlb1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x507000; +} + +static void +Opcode_witlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x506000; +} + +static void +Opcode_ldpte_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf1f000; +} + +static void +Opcode_hwwitlba_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x501000; +} + +static void +Opcode_hwwdtlba_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x509000; +} + +static void +Opcode_rsr_cpenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e000; +} + +static void +Opcode_wsr_cpenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e000; +} + +static void +Opcode_xsr_cpenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e000; +} + +static void +Opcode_clamps_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x330000; +} + +static void +Opcode_max_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x530000; +} + +static void +Opcode_maxu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x730000; +} + +static void +Opcode_min_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x430000; +} + +static void +Opcode_minu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x630000; +} + +static void +Opcode_nsa_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40e000; +} + +static void +Opcode_nsau_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40f000; +} + +static void +Opcode_sext_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x230000; +} + +static void +Opcode_l32ai_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb002; +} + +static void +Opcode_s32ri_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf002; +} + +static void +Opcode_s32c1i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe002; +} + +static void +Opcode_rsr_scompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30c00; +} + +static void +Opcode_wsr_scompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130c00; +} + +static void +Opcode_xsr_scompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610c00; +} + +static void +Opcode_rsr_atomctl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x36300; +} + +static void +Opcode_wsr_atomctl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x136300; +} + +static void +Opcode_xsr_atomctl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x616300; +} + +static void +Opcode_quos_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd20000; +} + +static void +Opcode_quou_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc20000; +} + +static void +Opcode_rems_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf20000; +} + +static void +Opcode_remu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe20000; +} + +static void +Opcode_rsr_eraccess_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35f00; +} + +static void +Opcode_wsr_eraccess_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x135f00; +} + +static void +Opcode_xsr_eraccess_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x615f00; +} + +static void +Opcode_rer_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x406000; +} + +static void +Opcode_wer_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x407000; +} + +static void +Opcode_rur_fcr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30e80; +} + +static void +Opcode_wur_fcr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf3e800; +} + +static void +Opcode_rur_fsr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30e90; +} + +static void +Opcode_wur_fsr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf3e900; +} + +static void +Opcode_read_impwire_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe0000; +} + +static void +Opcode_setb_expstate_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe1000; +} + +static void +Opcode_clrb_expstate_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe1200; +} + +static void +Opcode_wrmsk_expstate_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe2000; +} + +static void +Opcode_rur_expstate_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30e60; +} + +static void +Opcode_wur_expstate_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf3e600; +} + +static void +Opcode_lsi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_lsip_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8003; +} + +static void +Opcode_lsx_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80000; +} + +static void +Opcode_lsxp_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x180000; +} + +static void +Opcode_ssi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4003; +} + +static void +Opcode_ssip_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc003; +} + +static void +Opcode_ssx_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x480000; +} + +static void +Opcode_ssxp_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x580000; +} + +static void +Opcode_ldi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1003; +} + +static void +Opcode_ldip_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9003; +} + +static void +Opcode_ldx_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x280000; +} + +static void +Opcode_ldxp_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x380000; +} + +static void +Opcode_sdi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5003; +} + +static void +Opcode_sdip_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd003; +} + +static void +Opcode_sdx_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x680000; +} + +static void +Opcode_sdxp_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x780000; +} + +static void +Opcode_abs_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0010; +} + +static void +Opcode_neg_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0060; +} + +static void +Opcode_abs_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xff0010; +} + +static void +Opcode_neg_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xff0060; +} + +static void +Opcode_mov_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0000; +} + +static void +Opcode_mov_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xff0000; +} + +static void +Opcode_moveqz_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8b0000; +} + +static void +Opcode_movnez_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9b0000; +} + +static void +Opcode_movltz_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xab0000; +} + +static void +Opcode_movgez_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xbb0000; +} + +static void +Opcode_movf_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcb0000; +} + +static void +Opcode_movt_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xdb0000; +} + +static void +Opcode_wfr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0050; +} + +static void +Opcode_rfr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0040; +} + +static void +Opcode_rfrd_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xff0040; +} + +static void +Opcode_wfrd_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8e0000; +} + +static void +Opcode_round_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8a0000; +} + +static void +Opcode_round_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8f0000; +} + +static void +Opcode_ceil_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xba0000; +} + +static void +Opcode_ceil_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xbf0000; +} + +static void +Opcode_floor_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xaa0000; +} + +static void +Opcode_floor_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xaf0000; +} + +static void +Opcode_trunc_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9a0000; +} + +static void +Opcode_trunc_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9f0000; +} + +static void +Opcode_utrunc_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xea0000; +} + +static void +Opcode_utrunc_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xef0000; +} + +static void +Opcode_float_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xca0000; +} + +static void +Opcode_float_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcf0000; +} + +static void +Opcode_ufloat_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xda0000; +} + +static void +Opcode_ufloat_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xdf0000; +} + +static void +Opcode_cvtd_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0020; +} + +static void +Opcode_cvts_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xff0020; +} + +static void +Opcode_un_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1b0000; +} + +static void +Opcode_un_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1e0000; +} + +static void +Opcode_ult_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5b0000; +} + +static void +Opcode_ult_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5e0000; +} + +static void +Opcode_ule_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7b0000; +} + +static void +Opcode_ule_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7e0000; +} + +static void +Opcode_ueq_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b0000; +} + +static void +Opcode_ueq_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e0000; +} + +static void +Opcode_olt_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4b0000; +} + +static void +Opcode_olt_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4e0000; +} + +static void +Opcode_ole_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6b0000; +} + +static void +Opcode_ole_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6e0000; +} + +static void +Opcode_oeq_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2b0000; +} + +static void +Opcode_oeq_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2e0000; +} + +static void +Opcode_add_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa0000; +} + +static void +Opcode_add_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf0000; +} + +static void +Opcode_sub_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1a0000; +} + +static void +Opcode_sub_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1f0000; +} + +static void +Opcode_mul_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2a0000; +} + +static void +Opcode_mul_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2f0000; +} + +static void +Opcode_madd_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4a0000; +} + +static void +Opcode_madd_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4f0000; +} + +static void +Opcode_msub_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5a0000; +} + +static void +Opcode_msub_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5f0000; +} + +static void +Opcode_sqrt0_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0090; +} + +static void +Opcode_sqrt0_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xff0090; +} + +static void +Opcode_div0_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0070; +} + +static void +Opcode_div0_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xff0070; +} + +static void +Opcode_recip0_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0080; +} + +static void +Opcode_recip0_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xff0080; +} + +static void +Opcode_rsqrt0_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa00a0; +} + +static void +Opcode_rsqrt0_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xff00a0; +} + +static void +Opcode_maddn_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a0000; +} + +static void +Opcode_maddn_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6f0000; +} + +static void +Opcode_divn_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7a0000; +} + +static void +Opcode_divn_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7f0000; +} + +static void +Opcode_const_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0030; +} + +static void +Opcode_const_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xff0030; +} + +static void +Opcode_nexp01_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa00b0; +} + +static void +Opcode_nexp01_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xff00b0; +} + +static void +Opcode_addexp_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa00e0; +} + +static void +Opcode_addexp_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xff00e0; +} + +static void +Opcode_addexpm_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa00f0; +} + +static void +Opcode_addexpm_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xff00f0; +} + +static void +Opcode_mkdadj_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa00d0; +} + +static void +Opcode_mkdadj_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xff00d0; +} + +static void +Opcode_mksadj_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa00c0; +} + +static void +Opcode_mksadj_d_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xff00c0; +} + +static xtensa_opcode_encode_fn Opcode_excw_encode_fns[] = { + Opcode_excw_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfe_encode_fns[] = { + Opcode_rfe_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfde_encode_fns[] = { + Opcode_rfde_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_syscall_encode_fns[] = { + Opcode_syscall_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_call12_encode_fns[] = { + Opcode_call12_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_call8_encode_fns[] = { + Opcode_call8_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_call4_encode_fns[] = { + Opcode_call4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_callx12_encode_fns[] = { + Opcode_callx12_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_callx8_encode_fns[] = { + Opcode_callx8_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_callx4_encode_fns[] = { + Opcode_callx4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_entry_encode_fns[] = { + Opcode_entry_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movsp_encode_fns[] = { + Opcode_movsp_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rotw_encode_fns[] = { + Opcode_rotw_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_retw_encode_fns[] = { + Opcode_retw_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_retw_n_encode_fns[] = { + 0, 0, Opcode_retw_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_rfwo_encode_fns[] = { + Opcode_rfwo_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfwu_encode_fns[] = { + Opcode_rfwu_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_l32e_encode_fns[] = { + Opcode_l32e_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s32e_encode_fns[] = { + Opcode_s32e_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_windowbase_encode_fns[] = { + Opcode_rsr_windowbase_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_windowbase_encode_fns[] = { + Opcode_wsr_windowbase_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_windowbase_encode_fns[] = { + Opcode_xsr_windowbase_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_windowstart_encode_fns[] = { + Opcode_rsr_windowstart_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_windowstart_encode_fns[] = { + Opcode_wsr_windowstart_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_windowstart_encode_fns[] = { + Opcode_xsr_windowstart_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_add_n_encode_fns[] = { + 0, Opcode_add_n_Slot_inst16a_encode, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addi_n_encode_fns[] = { + 0, Opcode_addi_n_Slot_inst16a_encode, 0 +}; + +static xtensa_opcode_encode_fn Opcode_beqz_n_encode_fns[] = { + 0, 0, Opcode_beqz_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_bnez_n_encode_fns[] = { + 0, 0, Opcode_bnez_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_ill_n_encode_fns[] = { + 0, 0, Opcode_ill_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_l32i_n_encode_fns[] = { + 0, Opcode_l32i_n_Slot_inst16a_encode, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mov_n_encode_fns[] = { + 0, 0, Opcode_mov_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_movi_n_encode_fns[] = { + 0, 0, Opcode_movi_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_nop_n_encode_fns[] = { + 0, 0, Opcode_nop_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_ret_n_encode_fns[] = { + 0, 0, Opcode_ret_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_s32i_n_encode_fns[] = { + 0, Opcode_s32i_n_Slot_inst16a_encode, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_threadptr_encode_fns[] = { + Opcode_rur_threadptr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_threadptr_encode_fns[] = { + Opcode_wur_threadptr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addi_encode_fns[] = { + Opcode_addi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addmi_encode_fns[] = { + Opcode_addmi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_add_encode_fns[] = { + Opcode_add_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addx2_encode_fns[] = { + Opcode_addx2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addx4_encode_fns[] = { + Opcode_addx4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addx8_encode_fns[] = { + Opcode_addx8_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sub_encode_fns[] = { + Opcode_sub_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_subx2_encode_fns[] = { + Opcode_subx2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_subx4_encode_fns[] = { + Opcode_subx4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_subx8_encode_fns[] = { + Opcode_subx8_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_and_encode_fns[] = { + Opcode_and_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_or_encode_fns[] = { + Opcode_or_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xor_encode_fns[] = { + Opcode_xor_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_beqi_encode_fns[] = { + Opcode_beqi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bgei_encode_fns[] = { + Opcode_bgei_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_blti_encode_fns[] = { + Opcode_blti_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bnei_encode_fns[] = { + Opcode_bnei_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bbci_encode_fns[] = { + Opcode_bbci_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bbsi_encode_fns[] = { + Opcode_bbsi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bgeui_encode_fns[] = { + Opcode_bgeui_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bltui_encode_fns[] = { + Opcode_bltui_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ball_encode_fns[] = { + Opcode_ball_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bany_encode_fns[] = { + Opcode_bany_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bbc_encode_fns[] = { + Opcode_bbc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bbs_encode_fns[] = { + Opcode_bbs_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_beq_encode_fns[] = { + Opcode_beq_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bge_encode_fns[] = { + Opcode_bge_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bgeu_encode_fns[] = { + Opcode_bgeu_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_blt_encode_fns[] = { + Opcode_blt_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bltu_encode_fns[] = { + Opcode_bltu_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bnall_encode_fns[] = { + Opcode_bnall_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bne_encode_fns[] = { + Opcode_bne_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bnone_encode_fns[] = { + Opcode_bnone_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_beqz_encode_fns[] = { + Opcode_beqz_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bgez_encode_fns[] = { + Opcode_bgez_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bltz_encode_fns[] = { + Opcode_bltz_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bnez_encode_fns[] = { + Opcode_bnez_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_call0_encode_fns[] = { + Opcode_call0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_callx0_encode_fns[] = { + Opcode_callx0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_extui_encode_fns[] = { + Opcode_extui_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ill_encode_fns[] = { + Opcode_ill_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_j_encode_fns[] = { + Opcode_j_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_jx_encode_fns[] = { + Opcode_jx_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_l16ui_encode_fns[] = { + Opcode_l16ui_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_l16si_encode_fns[] = { + Opcode_l16si_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_l32i_encode_fns[] = { + Opcode_l32i_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_l32r_encode_fns[] = { + Opcode_l32r_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_l8ui_encode_fns[] = { + Opcode_l8ui_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_loop_encode_fns[] = { + Opcode_loop_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_loopgtz_encode_fns[] = { + Opcode_loopgtz_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_loopnez_encode_fns[] = { + Opcode_loopnez_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movi_encode_fns[] = { + Opcode_movi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_moveqz_encode_fns[] = { + Opcode_moveqz_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movgez_encode_fns[] = { + Opcode_movgez_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movltz_encode_fns[] = { + Opcode_movltz_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movnez_encode_fns[] = { + Opcode_movnez_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_abs_encode_fns[] = { + Opcode_abs_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_neg_encode_fns[] = { + Opcode_neg_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_nop_encode_fns[] = { + Opcode_nop_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ret_encode_fns[] = { + Opcode_ret_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_simcall_encode_fns[] = { + Opcode_simcall_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s16i_encode_fns[] = { + Opcode_s16i_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s32i_encode_fns[] = { + Opcode_s32i_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s32nb_encode_fns[] = { + Opcode_s32nb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s8i_encode_fns[] = { + Opcode_s8i_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssa8b_encode_fns[] = { + Opcode_ssa8b_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssa8l_encode_fns[] = { + Opcode_ssa8l_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssl_encode_fns[] = { + Opcode_ssl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssr_encode_fns[] = { + Opcode_ssr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssai_encode_fns[] = { + Opcode_ssai_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sll_encode_fns[] = { + Opcode_sll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_src_encode_fns[] = { + Opcode_src_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sra_encode_fns[] = { + Opcode_sra_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_srl_encode_fns[] = { + Opcode_srl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_slli_encode_fns[] = { + Opcode_slli_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_srai_encode_fns[] = { + Opcode_srai_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_srli_encode_fns[] = { + Opcode_srli_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_memw_encode_fns[] = { + Opcode_memw_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_extw_encode_fns[] = { + Opcode_extw_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_isync_encode_fns[] = { + Opcode_isync_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dsync_encode_fns[] = { + Opcode_dsync_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_esync_encode_fns[] = { + Opcode_esync_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsync_encode_fns[] = { + Opcode_rsync_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsil_encode_fns[] = { + Opcode_rsil_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_lend_encode_fns[] = { + Opcode_rsr_lend_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_lend_encode_fns[] = { + Opcode_wsr_lend_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_lend_encode_fns[] = { + Opcode_xsr_lend_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_lcount_encode_fns[] = { + Opcode_rsr_lcount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_lcount_encode_fns[] = { + Opcode_wsr_lcount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_lcount_encode_fns[] = { + Opcode_xsr_lcount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_lbeg_encode_fns[] = { + Opcode_rsr_lbeg_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_lbeg_encode_fns[] = { + Opcode_wsr_lbeg_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_lbeg_encode_fns[] = { + Opcode_xsr_lbeg_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_sar_encode_fns[] = { + Opcode_rsr_sar_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_sar_encode_fns[] = { + Opcode_wsr_sar_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_sar_encode_fns[] = { + Opcode_xsr_sar_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_memctl_encode_fns[] = { + Opcode_rsr_memctl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_memctl_encode_fns[] = { + Opcode_wsr_memctl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_memctl_encode_fns[] = { + Opcode_xsr_memctl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_configid0_encode_fns[] = { + Opcode_rsr_configid0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_configid0_encode_fns[] = { + Opcode_wsr_configid0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_configid1_encode_fns[] = { + Opcode_rsr_configid1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ps_encode_fns[] = { + Opcode_rsr_ps_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ps_encode_fns[] = { + Opcode_wsr_ps_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ps_encode_fns[] = { + Opcode_xsr_ps_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc1_encode_fns[] = { + Opcode_rsr_epc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc1_encode_fns[] = { + Opcode_wsr_epc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc1_encode_fns[] = { + Opcode_xsr_epc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave1_encode_fns[] = { + Opcode_rsr_excsave1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave1_encode_fns[] = { + Opcode_wsr_excsave1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave1_encode_fns[] = { + Opcode_xsr_excsave1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc2_encode_fns[] = { + Opcode_rsr_epc2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc2_encode_fns[] = { + Opcode_wsr_epc2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc2_encode_fns[] = { + Opcode_xsr_epc2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave2_encode_fns[] = { + Opcode_rsr_excsave2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave2_encode_fns[] = { + Opcode_wsr_excsave2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave2_encode_fns[] = { + Opcode_xsr_excsave2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc3_encode_fns[] = { + Opcode_rsr_epc3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc3_encode_fns[] = { + Opcode_wsr_epc3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc3_encode_fns[] = { + Opcode_xsr_epc3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave3_encode_fns[] = { + Opcode_rsr_excsave3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave3_encode_fns[] = { + Opcode_wsr_excsave3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave3_encode_fns[] = { + Opcode_xsr_excsave3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc4_encode_fns[] = { + Opcode_rsr_epc4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc4_encode_fns[] = { + Opcode_wsr_epc4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc4_encode_fns[] = { + Opcode_xsr_epc4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave4_encode_fns[] = { + Opcode_rsr_excsave4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave4_encode_fns[] = { + Opcode_wsr_excsave4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave4_encode_fns[] = { + Opcode_xsr_excsave4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc5_encode_fns[] = { + Opcode_rsr_epc5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc5_encode_fns[] = { + Opcode_wsr_epc5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc5_encode_fns[] = { + Opcode_xsr_epc5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave5_encode_fns[] = { + Opcode_rsr_excsave5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave5_encode_fns[] = { + Opcode_wsr_excsave5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave5_encode_fns[] = { + Opcode_xsr_excsave5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc6_encode_fns[] = { + Opcode_rsr_epc6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc6_encode_fns[] = { + Opcode_wsr_epc6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc6_encode_fns[] = { + Opcode_xsr_epc6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave6_encode_fns[] = { + Opcode_rsr_excsave6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave6_encode_fns[] = { + Opcode_wsr_excsave6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave6_encode_fns[] = { + Opcode_xsr_excsave6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc7_encode_fns[] = { + Opcode_rsr_epc7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc7_encode_fns[] = { + Opcode_wsr_epc7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc7_encode_fns[] = { + Opcode_xsr_epc7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave7_encode_fns[] = { + Opcode_rsr_excsave7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave7_encode_fns[] = { + Opcode_wsr_excsave7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave7_encode_fns[] = { + Opcode_xsr_excsave7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eps2_encode_fns[] = { + Opcode_rsr_eps2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eps2_encode_fns[] = { + Opcode_wsr_eps2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eps2_encode_fns[] = { + Opcode_xsr_eps2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eps3_encode_fns[] = { + Opcode_rsr_eps3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eps3_encode_fns[] = { + Opcode_wsr_eps3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eps3_encode_fns[] = { + Opcode_xsr_eps3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eps4_encode_fns[] = { + Opcode_rsr_eps4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eps4_encode_fns[] = { + Opcode_wsr_eps4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eps4_encode_fns[] = { + Opcode_xsr_eps4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eps5_encode_fns[] = { + Opcode_rsr_eps5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eps5_encode_fns[] = { + Opcode_wsr_eps5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eps5_encode_fns[] = { + Opcode_xsr_eps5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eps6_encode_fns[] = { + Opcode_rsr_eps6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eps6_encode_fns[] = { + Opcode_wsr_eps6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eps6_encode_fns[] = { + Opcode_xsr_eps6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eps7_encode_fns[] = { + Opcode_rsr_eps7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eps7_encode_fns[] = { + Opcode_wsr_eps7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eps7_encode_fns[] = { + Opcode_xsr_eps7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excvaddr_encode_fns[] = { + Opcode_rsr_excvaddr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excvaddr_encode_fns[] = { + Opcode_wsr_excvaddr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excvaddr_encode_fns[] = { + Opcode_xsr_excvaddr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_depc_encode_fns[] = { + Opcode_rsr_depc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_depc_encode_fns[] = { + Opcode_wsr_depc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_depc_encode_fns[] = { + Opcode_xsr_depc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_exccause_encode_fns[] = { + Opcode_rsr_exccause_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_exccause_encode_fns[] = { + Opcode_wsr_exccause_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_exccause_encode_fns[] = { + Opcode_xsr_exccause_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_misc0_encode_fns[] = { + Opcode_rsr_misc0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_misc0_encode_fns[] = { + Opcode_wsr_misc0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_misc0_encode_fns[] = { + Opcode_xsr_misc0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_misc1_encode_fns[] = { + Opcode_rsr_misc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_misc1_encode_fns[] = { + Opcode_wsr_misc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_misc1_encode_fns[] = { + Opcode_xsr_misc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_prid_encode_fns[] = { + Opcode_rsr_prid_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_vecbase_encode_fns[] = { + Opcode_rsr_vecbase_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_vecbase_encode_fns[] = { + Opcode_wsr_vecbase_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_vecbase_encode_fns[] = { + Opcode_xsr_vecbase_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_salt_encode_fns[] = { + Opcode_salt_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_saltu_encode_fns[] = { + Opcode_saltu_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul16s_encode_fns[] = { + Opcode_mul16s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul16u_encode_fns[] = { + Opcode_mul16u_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mull_encode_fns[] = { + Opcode_mull_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_aa_hh_encode_fns[] = { + Opcode_mul_aa_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_aa_hl_encode_fns[] = { + Opcode_mul_aa_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_aa_lh_encode_fns[] = { + Opcode_mul_aa_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_aa_ll_encode_fns[] = { + Opcode_mul_aa_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_umul_aa_hh_encode_fns[] = { + Opcode_umul_aa_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_umul_aa_hl_encode_fns[] = { + Opcode_umul_aa_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_umul_aa_lh_encode_fns[] = { + Opcode_umul_aa_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_umul_aa_ll_encode_fns[] = { + Opcode_umul_aa_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_ad_hh_encode_fns[] = { + Opcode_mul_ad_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_ad_hl_encode_fns[] = { + Opcode_mul_ad_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_ad_lh_encode_fns[] = { + Opcode_mul_ad_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_ad_ll_encode_fns[] = { + Opcode_mul_ad_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_da_hh_encode_fns[] = { + Opcode_mul_da_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_da_hl_encode_fns[] = { + Opcode_mul_da_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_da_lh_encode_fns[] = { + Opcode_mul_da_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_da_ll_encode_fns[] = { + Opcode_mul_da_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_dd_hh_encode_fns[] = { + Opcode_mul_dd_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_dd_hl_encode_fns[] = { + Opcode_mul_dd_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_dd_lh_encode_fns[] = { + Opcode_mul_dd_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_dd_ll_encode_fns[] = { + Opcode_mul_dd_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_aa_hh_encode_fns[] = { + Opcode_mula_aa_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_aa_hl_encode_fns[] = { + Opcode_mula_aa_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_aa_lh_encode_fns[] = { + Opcode_mula_aa_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_aa_ll_encode_fns[] = { + Opcode_mula_aa_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_aa_hh_encode_fns[] = { + Opcode_muls_aa_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_aa_hl_encode_fns[] = { + Opcode_muls_aa_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_aa_lh_encode_fns[] = { + Opcode_muls_aa_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_aa_ll_encode_fns[] = { + Opcode_muls_aa_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_ad_hh_encode_fns[] = { + Opcode_mula_ad_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_ad_hl_encode_fns[] = { + Opcode_mula_ad_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_ad_lh_encode_fns[] = { + Opcode_mula_ad_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_ad_ll_encode_fns[] = { + Opcode_mula_ad_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_ad_hh_encode_fns[] = { + Opcode_muls_ad_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_ad_hl_encode_fns[] = { + Opcode_muls_ad_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_ad_lh_encode_fns[] = { + Opcode_muls_ad_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_ad_ll_encode_fns[] = { + Opcode_muls_ad_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_hh_encode_fns[] = { + Opcode_mula_da_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_hl_encode_fns[] = { + Opcode_mula_da_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_lh_encode_fns[] = { + Opcode_mula_da_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_ll_encode_fns[] = { + Opcode_mula_da_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_da_hh_encode_fns[] = { + Opcode_muls_da_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_da_hl_encode_fns[] = { + Opcode_muls_da_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_da_lh_encode_fns[] = { + Opcode_muls_da_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_da_ll_encode_fns[] = { + Opcode_muls_da_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_hh_encode_fns[] = { + Opcode_mula_dd_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_hl_encode_fns[] = { + Opcode_mula_dd_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_lh_encode_fns[] = { + Opcode_mula_dd_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_ll_encode_fns[] = { + Opcode_mula_dd_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_dd_hh_encode_fns[] = { + Opcode_muls_dd_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_dd_hl_encode_fns[] = { + Opcode_muls_dd_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_dd_lh_encode_fns[] = { + Opcode_muls_dd_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_dd_ll_encode_fns[] = { + Opcode_muls_dd_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_hh_lddec_encode_fns[] = { + Opcode_mula_da_hh_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_hh_ldinc_encode_fns[] = { + Opcode_mula_da_hh_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_hl_lddec_encode_fns[] = { + Opcode_mula_da_hl_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_hl_ldinc_encode_fns[] = { + Opcode_mula_da_hl_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_lh_lddec_encode_fns[] = { + Opcode_mula_da_lh_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_lh_ldinc_encode_fns[] = { + Opcode_mula_da_lh_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_ll_lddec_encode_fns[] = { + Opcode_mula_da_ll_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_ll_ldinc_encode_fns[] = { + Opcode_mula_da_ll_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_hh_lddec_encode_fns[] = { + Opcode_mula_dd_hh_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_hh_ldinc_encode_fns[] = { + Opcode_mula_dd_hh_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_hl_lddec_encode_fns[] = { + Opcode_mula_dd_hl_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_hl_ldinc_encode_fns[] = { + Opcode_mula_dd_hl_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_lh_lddec_encode_fns[] = { + Opcode_mula_dd_lh_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_lh_ldinc_encode_fns[] = { + Opcode_mula_dd_lh_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_ll_lddec_encode_fns[] = { + Opcode_mula_dd_ll_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_ll_ldinc_encode_fns[] = { + Opcode_mula_dd_ll_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lddec_encode_fns[] = { + Opcode_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ldinc_encode_fns[] = { + Opcode_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_m0_encode_fns[] = { + Opcode_rsr_m0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_m0_encode_fns[] = { + Opcode_wsr_m0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_m0_encode_fns[] = { + Opcode_xsr_m0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_m1_encode_fns[] = { + Opcode_rsr_m1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_m1_encode_fns[] = { + Opcode_wsr_m1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_m1_encode_fns[] = { + Opcode_xsr_m1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_m2_encode_fns[] = { + Opcode_rsr_m2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_m2_encode_fns[] = { + Opcode_wsr_m2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_m2_encode_fns[] = { + Opcode_xsr_m2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_m3_encode_fns[] = { + Opcode_rsr_m3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_m3_encode_fns[] = { + Opcode_wsr_m3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_m3_encode_fns[] = { + Opcode_xsr_m3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_acclo_encode_fns[] = { + Opcode_rsr_acclo_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_acclo_encode_fns[] = { + Opcode_wsr_acclo_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_acclo_encode_fns[] = { + Opcode_xsr_acclo_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_acchi_encode_fns[] = { + Opcode_rsr_acchi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_acchi_encode_fns[] = { + Opcode_wsr_acchi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_acchi_encode_fns[] = { + Opcode_xsr_acchi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfi_encode_fns[] = { + Opcode_rfi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_waiti_encode_fns[] = { + Opcode_waiti_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_interrupt_encode_fns[] = { + Opcode_rsr_interrupt_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_intset_encode_fns[] = { + Opcode_wsr_intset_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_intclear_encode_fns[] = { + Opcode_wsr_intclear_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_intenable_encode_fns[] = { + Opcode_rsr_intenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_intenable_encode_fns[] = { + Opcode_wsr_intenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_intenable_encode_fns[] = { + Opcode_xsr_intenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_break_encode_fns[] = { + Opcode_break_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_break_n_encode_fns[] = { + 0, 0, Opcode_break_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_rsr_dbreaka0_encode_fns[] = { + Opcode_rsr_dbreaka0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_dbreaka0_encode_fns[] = { + Opcode_wsr_dbreaka0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_dbreaka0_encode_fns[] = { + Opcode_xsr_dbreaka0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_dbreakc0_encode_fns[] = { + Opcode_rsr_dbreakc0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_dbreakc0_encode_fns[] = { + Opcode_wsr_dbreakc0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_dbreakc0_encode_fns[] = { + Opcode_xsr_dbreakc0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_dbreaka1_encode_fns[] = { + Opcode_rsr_dbreaka1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_dbreaka1_encode_fns[] = { + Opcode_wsr_dbreaka1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_dbreaka1_encode_fns[] = { + Opcode_xsr_dbreaka1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_dbreakc1_encode_fns[] = { + Opcode_rsr_dbreakc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_dbreakc1_encode_fns[] = { + Opcode_wsr_dbreakc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_dbreakc1_encode_fns[] = { + Opcode_xsr_dbreakc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ibreaka0_encode_fns[] = { + Opcode_rsr_ibreaka0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ibreaka0_encode_fns[] = { + Opcode_wsr_ibreaka0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ibreaka0_encode_fns[] = { + Opcode_xsr_ibreaka0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ibreaka1_encode_fns[] = { + Opcode_rsr_ibreaka1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ibreaka1_encode_fns[] = { + Opcode_wsr_ibreaka1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ibreaka1_encode_fns[] = { + Opcode_xsr_ibreaka1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ibreakenable_encode_fns[] = { + Opcode_rsr_ibreakenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ibreakenable_encode_fns[] = { + Opcode_wsr_ibreakenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ibreakenable_encode_fns[] = { + Opcode_xsr_ibreakenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_debugcause_encode_fns[] = { + Opcode_rsr_debugcause_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_debugcause_encode_fns[] = { + Opcode_wsr_debugcause_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_debugcause_encode_fns[] = { + Opcode_xsr_debugcause_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_icount_encode_fns[] = { + Opcode_rsr_icount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_icount_encode_fns[] = { + Opcode_wsr_icount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_icount_encode_fns[] = { + Opcode_xsr_icount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_icountlevel_encode_fns[] = { + Opcode_rsr_icountlevel_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_icountlevel_encode_fns[] = { + Opcode_wsr_icountlevel_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_icountlevel_encode_fns[] = { + Opcode_xsr_icountlevel_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ddr_encode_fns[] = { + Opcode_rsr_ddr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ddr_encode_fns[] = { + Opcode_wsr_ddr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ddr_encode_fns[] = { + Opcode_xsr_ddr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lddr32_p_encode_fns[] = { + Opcode_lddr32_p_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sddr32_p_encode_fns[] = { + Opcode_sddr32_p_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfdo_encode_fns[] = { + Opcode_rfdo_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfdd_encode_fns[] = { + Opcode_rfdd_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_mmid_encode_fns[] = { + Opcode_wsr_mmid_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_andb_encode_fns[] = { + Opcode_andb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_andbc_encode_fns[] = { + Opcode_andbc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_orb_encode_fns[] = { + Opcode_orb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_orbc_encode_fns[] = { + Opcode_orbc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xorb_encode_fns[] = { + Opcode_xorb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_all4_encode_fns[] = { + Opcode_all4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_any4_encode_fns[] = { + Opcode_any4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_all8_encode_fns[] = { + Opcode_all8_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_any8_encode_fns[] = { + Opcode_any8_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bf_encode_fns[] = { + Opcode_bf_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bt_encode_fns[] = { + Opcode_bt_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movf_encode_fns[] = { + Opcode_movf_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movt_encode_fns[] = { + Opcode_movt_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_br_encode_fns[] = { + Opcode_rsr_br_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_br_encode_fns[] = { + Opcode_wsr_br_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_br_encode_fns[] = { + Opcode_xsr_br_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ccount_encode_fns[] = { + Opcode_rsr_ccount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ccount_encode_fns[] = { + Opcode_wsr_ccount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ccount_encode_fns[] = { + Opcode_xsr_ccount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ccompare0_encode_fns[] = { + Opcode_rsr_ccompare0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ccompare0_encode_fns[] = { + Opcode_wsr_ccompare0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ccompare0_encode_fns[] = { + Opcode_xsr_ccompare0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ccompare1_encode_fns[] = { + Opcode_rsr_ccompare1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ccompare1_encode_fns[] = { + Opcode_wsr_ccompare1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ccompare1_encode_fns[] = { + Opcode_xsr_ccompare1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ccompare2_encode_fns[] = { + Opcode_rsr_ccompare2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ccompare2_encode_fns[] = { + Opcode_wsr_ccompare2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ccompare2_encode_fns[] = { + Opcode_xsr_ccompare2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ihi_encode_fns[] = { + Opcode_ihi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ipf_encode_fns[] = { + Opcode_ipf_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ihu_encode_fns[] = { + Opcode_ihu_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_iiu_encode_fns[] = { + Opcode_iiu_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ipfl_encode_fns[] = { + Opcode_ipfl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_iii_encode_fns[] = { + Opcode_iii_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lict_encode_fns[] = { + Opcode_lict_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_licw_encode_fns[] = { + Opcode_licw_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sict_encode_fns[] = { + Opcode_sict_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sicw_encode_fns[] = { + Opcode_sicw_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dhwb_encode_fns[] = { + Opcode_dhwb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dhwbi_encode_fns[] = { + Opcode_dhwbi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_diwbui_p_encode_fns[] = { + Opcode_diwbui_p_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_diwb_encode_fns[] = { + Opcode_diwb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_diwbi_encode_fns[] = { + Opcode_diwbi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dhi_encode_fns[] = { + Opcode_dhi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dii_encode_fns[] = { + Opcode_dii_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dpfr_encode_fns[] = { + Opcode_dpfr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dpfro_encode_fns[] = { + Opcode_dpfro_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dpfw_encode_fns[] = { + Opcode_dpfw_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dpfwo_encode_fns[] = { + Opcode_dpfwo_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dhu_encode_fns[] = { + Opcode_dhu_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_diu_encode_fns[] = { + Opcode_diu_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dpfl_encode_fns[] = { + Opcode_dpfl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sdct_encode_fns[] = { + Opcode_sdct_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ldct_encode_fns[] = { + Opcode_ldct_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sdcw_encode_fns[] = { + Opcode_sdcw_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ldcw_encode_fns[] = { + Opcode_ldcw_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ptevaddr_encode_fns[] = { + Opcode_wsr_ptevaddr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ptevaddr_encode_fns[] = { + Opcode_rsr_ptevaddr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ptevaddr_encode_fns[] = { + Opcode_xsr_ptevaddr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_rasid_encode_fns[] = { + Opcode_rsr_rasid_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_rasid_encode_fns[] = { + Opcode_wsr_rasid_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_rasid_encode_fns[] = { + Opcode_xsr_rasid_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_itlbcfg_encode_fns[] = { + Opcode_rsr_itlbcfg_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_itlbcfg_encode_fns[] = { + Opcode_wsr_itlbcfg_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_itlbcfg_encode_fns[] = { + Opcode_xsr_itlbcfg_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_dtlbcfg_encode_fns[] = { + Opcode_rsr_dtlbcfg_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_dtlbcfg_encode_fns[] = { + Opcode_wsr_dtlbcfg_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_dtlbcfg_encode_fns[] = { + Opcode_xsr_dtlbcfg_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_idtlb_encode_fns[] = { + Opcode_idtlb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_pdtlb_encode_fns[] = { + Opcode_pdtlb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rdtlb0_encode_fns[] = { + Opcode_rdtlb0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rdtlb1_encode_fns[] = { + Opcode_rdtlb1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wdtlb_encode_fns[] = { + Opcode_wdtlb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_iitlb_encode_fns[] = { + Opcode_iitlb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_pitlb_encode_fns[] = { + Opcode_pitlb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ritlb0_encode_fns[] = { + Opcode_ritlb0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ritlb1_encode_fns[] = { + Opcode_ritlb1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_witlb_encode_fns[] = { + Opcode_witlb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ldpte_encode_fns[] = { + Opcode_ldpte_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_hwwitlba_encode_fns[] = { + Opcode_hwwitlba_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_hwwdtlba_encode_fns[] = { + Opcode_hwwdtlba_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_cpenable_encode_fns[] = { + Opcode_rsr_cpenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_cpenable_encode_fns[] = { + Opcode_wsr_cpenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_cpenable_encode_fns[] = { + Opcode_xsr_cpenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_clamps_encode_fns[] = { + Opcode_clamps_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_max_encode_fns[] = { + Opcode_max_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_maxu_encode_fns[] = { + Opcode_maxu_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_min_encode_fns[] = { + Opcode_min_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_minu_encode_fns[] = { + Opcode_minu_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_nsa_encode_fns[] = { + Opcode_nsa_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_nsau_encode_fns[] = { + Opcode_nsau_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sext_encode_fns[] = { + Opcode_sext_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_l32ai_encode_fns[] = { + Opcode_l32ai_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s32ri_encode_fns[] = { + Opcode_s32ri_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s32c1i_encode_fns[] = { + Opcode_s32c1i_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_scompare1_encode_fns[] = { + Opcode_rsr_scompare1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_scompare1_encode_fns[] = { + Opcode_wsr_scompare1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_scompare1_encode_fns[] = { + Opcode_xsr_scompare1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_atomctl_encode_fns[] = { + Opcode_rsr_atomctl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_atomctl_encode_fns[] = { + Opcode_wsr_atomctl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_atomctl_encode_fns[] = { + Opcode_xsr_atomctl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_quos_encode_fns[] = { + Opcode_quos_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_quou_encode_fns[] = { + Opcode_quou_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rems_encode_fns[] = { + Opcode_rems_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_remu_encode_fns[] = { + Opcode_remu_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eraccess_encode_fns[] = { + Opcode_rsr_eraccess_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eraccess_encode_fns[] = { + Opcode_wsr_eraccess_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eraccess_encode_fns[] = { + Opcode_xsr_eraccess_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rer_encode_fns[] = { + Opcode_rer_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wer_encode_fns[] = { + Opcode_wer_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_fcr_encode_fns[] = { + Opcode_rur_fcr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_fcr_encode_fns[] = { + Opcode_wur_fcr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_fsr_encode_fns[] = { + Opcode_rur_fsr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_fsr_encode_fns[] = { + Opcode_wur_fsr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_read_impwire_encode_fns[] = { + Opcode_read_impwire_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_setb_expstate_encode_fns[] = { + Opcode_setb_expstate_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_clrb_expstate_encode_fns[] = { + Opcode_clrb_expstate_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wrmsk_expstate_encode_fns[] = { + Opcode_wrmsk_expstate_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_expstate_encode_fns[] = { + Opcode_rur_expstate_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_expstate_encode_fns[] = { + Opcode_wur_expstate_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lsi_encode_fns[] = { + Opcode_lsi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lsip_encode_fns[] = { + Opcode_lsip_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lsx_encode_fns[] = { + Opcode_lsx_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lsxp_encode_fns[] = { + Opcode_lsxp_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssi_encode_fns[] = { + Opcode_ssi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssip_encode_fns[] = { + Opcode_ssip_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssx_encode_fns[] = { + Opcode_ssx_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssxp_encode_fns[] = { + Opcode_ssxp_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ldi_encode_fns[] = { + Opcode_ldi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ldip_encode_fns[] = { + Opcode_ldip_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ldx_encode_fns[] = { + Opcode_ldx_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ldxp_encode_fns[] = { + Opcode_ldxp_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sdi_encode_fns[] = { + Opcode_sdi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sdip_encode_fns[] = { + Opcode_sdip_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sdx_encode_fns[] = { + Opcode_sdx_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sdxp_encode_fns[] = { + Opcode_sdxp_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_abs_s_encode_fns[] = { + Opcode_abs_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_neg_s_encode_fns[] = { + Opcode_neg_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_abs_d_encode_fns[] = { + Opcode_abs_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_neg_d_encode_fns[] = { + Opcode_neg_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mov_s_encode_fns[] = { + Opcode_mov_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mov_d_encode_fns[] = { + Opcode_mov_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_moveqz_s_encode_fns[] = { + Opcode_moveqz_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movnez_s_encode_fns[] = { + Opcode_movnez_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movltz_s_encode_fns[] = { + Opcode_movltz_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movgez_s_encode_fns[] = { + Opcode_movgez_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movf_s_encode_fns[] = { + Opcode_movf_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movt_s_encode_fns[] = { + Opcode_movt_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wfr_encode_fns[] = { + Opcode_wfr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfr_encode_fns[] = { + Opcode_rfr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfrd_encode_fns[] = { + Opcode_rfrd_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wfrd_encode_fns[] = { + Opcode_wfrd_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_round_s_encode_fns[] = { + Opcode_round_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_round_d_encode_fns[] = { + Opcode_round_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ceil_s_encode_fns[] = { + Opcode_ceil_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ceil_d_encode_fns[] = { + Opcode_ceil_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_floor_s_encode_fns[] = { + Opcode_floor_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_floor_d_encode_fns[] = { + Opcode_floor_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_trunc_s_encode_fns[] = { + Opcode_trunc_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_trunc_d_encode_fns[] = { + Opcode_trunc_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_utrunc_s_encode_fns[] = { + Opcode_utrunc_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_utrunc_d_encode_fns[] = { + Opcode_utrunc_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_float_s_encode_fns[] = { + Opcode_float_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_float_d_encode_fns[] = { + Opcode_float_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ufloat_s_encode_fns[] = { + Opcode_ufloat_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ufloat_d_encode_fns[] = { + Opcode_ufloat_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_cvtd_s_encode_fns[] = { + Opcode_cvtd_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_cvts_d_encode_fns[] = { + Opcode_cvts_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_un_s_encode_fns[] = { + Opcode_un_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_un_d_encode_fns[] = { + Opcode_un_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ult_s_encode_fns[] = { + Opcode_ult_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ult_d_encode_fns[] = { + Opcode_ult_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ule_s_encode_fns[] = { + Opcode_ule_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ule_d_encode_fns[] = { + Opcode_ule_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ueq_s_encode_fns[] = { + Opcode_ueq_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ueq_d_encode_fns[] = { + Opcode_ueq_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_olt_s_encode_fns[] = { + Opcode_olt_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_olt_d_encode_fns[] = { + Opcode_olt_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ole_s_encode_fns[] = { + Opcode_ole_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ole_d_encode_fns[] = { + Opcode_ole_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_oeq_s_encode_fns[] = { + Opcode_oeq_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_oeq_d_encode_fns[] = { + Opcode_oeq_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_add_s_encode_fns[] = { + Opcode_add_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_add_d_encode_fns[] = { + Opcode_add_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sub_s_encode_fns[] = { + Opcode_sub_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sub_d_encode_fns[] = { + Opcode_sub_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_s_encode_fns[] = { + Opcode_mul_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_d_encode_fns[] = { + Opcode_mul_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_madd_s_encode_fns[] = { + Opcode_madd_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_madd_d_encode_fns[] = { + Opcode_madd_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_msub_s_encode_fns[] = { + Opcode_msub_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_msub_d_encode_fns[] = { + Opcode_msub_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sqrt0_s_encode_fns[] = { + Opcode_sqrt0_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sqrt0_d_encode_fns[] = { + Opcode_sqrt0_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_div0_s_encode_fns[] = { + Opcode_div0_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_div0_d_encode_fns[] = { + Opcode_div0_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_recip0_s_encode_fns[] = { + Opcode_recip0_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_recip0_d_encode_fns[] = { + Opcode_recip0_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsqrt0_s_encode_fns[] = { + Opcode_rsqrt0_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsqrt0_d_encode_fns[] = { + Opcode_rsqrt0_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_maddn_s_encode_fns[] = { + Opcode_maddn_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_maddn_d_encode_fns[] = { + Opcode_maddn_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_divn_s_encode_fns[] = { + Opcode_divn_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_divn_d_encode_fns[] = { + Opcode_divn_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_const_s_encode_fns[] = { + Opcode_const_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_const_d_encode_fns[] = { + Opcode_const_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_nexp01_s_encode_fns[] = { + Opcode_nexp01_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_nexp01_d_encode_fns[] = { + Opcode_nexp01_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addexp_s_encode_fns[] = { + Opcode_addexp_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addexp_d_encode_fns[] = { + Opcode_addexp_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addexpm_s_encode_fns[] = { + Opcode_addexpm_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addexpm_d_encode_fns[] = { + Opcode_addexpm_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mkdadj_s_encode_fns[] = { + Opcode_mkdadj_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mkdadj_d_encode_fns[] = { + Opcode_mkdadj_d_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mksadj_s_encode_fns[] = { + Opcode_mksadj_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mksadj_d_encode_fns[] = { + Opcode_mksadj_d_Slot_inst_encode, 0, 0 +}; + + + + + +/* Opcode table. */ + +static xtensa_funcUnit_use Opcode_l32e_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_s32e_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_l32i_n_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_s32i_n_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_l16ui_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_l16si_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_l32i_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_l32r_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_l8ui_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_s16i_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_s32i_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_s32nb_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_s8i_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_mula_da_hh_lddec_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_mula_da_hh_ldinc_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_mula_da_hl_lddec_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_mula_da_hl_ldinc_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_mula_da_lh_lddec_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_mula_da_lh_ldinc_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_mula_da_ll_lddec_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_mula_da_ll_ldinc_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_mula_dd_hh_lddec_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_mula_dd_hh_ldinc_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_mula_dd_hl_lddec_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_mula_dd_hl_ldinc_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_mula_dd_lh_lddec_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_mula_dd_lh_ldinc_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_mula_dd_ll_lddec_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_mula_dd_ll_ldinc_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_lddec_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_ldinc_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_lddr32_p_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_sddr32_p_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_lict_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_licw_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_sict_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_sicw_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_sdct_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_ldct_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_sdcw_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_ldcw_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_ldpte_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_l32ai_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_s32ri_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_s32c1i_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_lsi_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_lsip_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_lsx_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_lsxp_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_ssi_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_ssip_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_ssx_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_ssxp_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_ldi_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_ldip_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_ldx_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_ldxp_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_sdi_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_sdip_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_sdx_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_funcUnit_use Opcode_sdxp_funcUnit_uses[] = { + { FUNCUNIT_XT_LOADSTORE_UNIT, 0 } +}; + +static xtensa_opcode_internal opcodes[] = { + { "excw", ICLASS_xt_iclass_excw, + 0, + Opcode_excw_encode_fns, 0, 0 }, + { "rfe", ICLASS_xt_iclass_rfe, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfe_encode_fns, 0, 0 }, + { "rfde", ICLASS_xt_iclass_rfde, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfde_encode_fns, 0, 0 }, + { "syscall", ICLASS_xt_iclass_syscall, + 0, + Opcode_syscall_encode_fns, 0, 0 }, + { "call12", ICLASS_xt_iclass_call12, + XTENSA_OPCODE_IS_CALL, + Opcode_call12_encode_fns, 0, 0 }, + { "call8", ICLASS_xt_iclass_call8, + XTENSA_OPCODE_IS_CALL, + Opcode_call8_encode_fns, 0, 0 }, + { "call4", ICLASS_xt_iclass_call4, + XTENSA_OPCODE_IS_CALL, + Opcode_call4_encode_fns, 0, 0 }, + { "callx12", ICLASS_xt_iclass_callx12, + XTENSA_OPCODE_IS_CALL, + Opcode_callx12_encode_fns, 0, 0 }, + { "callx8", ICLASS_xt_iclass_callx8, + XTENSA_OPCODE_IS_CALL, + Opcode_callx8_encode_fns, 0, 0 }, + { "callx4", ICLASS_xt_iclass_callx4, + XTENSA_OPCODE_IS_CALL, + Opcode_callx4_encode_fns, 0, 0 }, + { "entry", ICLASS_xt_iclass_entry, + 0, + Opcode_entry_encode_fns, 0, 0 }, + { "movsp", ICLASS_xt_iclass_movsp, + 0, + Opcode_movsp_encode_fns, 0, 0 }, + { "rotw", ICLASS_xt_iclass_rotw, + 0, + Opcode_rotw_encode_fns, 0, 0 }, + { "retw", ICLASS_xt_iclass_retw, + XTENSA_OPCODE_IS_JUMP, + Opcode_retw_encode_fns, 0, 0 }, + { "retw.n", ICLASS_xt_iclass_retw, + XTENSA_OPCODE_IS_JUMP, + Opcode_retw_n_encode_fns, 0, 0 }, + { "rfwo", ICLASS_xt_iclass_rfwou, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfwo_encode_fns, 0, 0 }, + { "rfwu", ICLASS_xt_iclass_rfwou, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfwu_encode_fns, 0, 0 }, + { "l32e", ICLASS_xt_iclass_l32e, + 0, + Opcode_l32e_encode_fns, 1, Opcode_l32e_funcUnit_uses }, + { "s32e", ICLASS_xt_iclass_s32e, + 0, + Opcode_s32e_encode_fns, 1, Opcode_s32e_funcUnit_uses }, + { "rsr.windowbase", ICLASS_xt_iclass_rsr_windowbase, + 0, + Opcode_rsr_windowbase_encode_fns, 0, 0 }, + { "wsr.windowbase", ICLASS_xt_iclass_wsr_windowbase, + 0, + Opcode_wsr_windowbase_encode_fns, 0, 0 }, + { "xsr.windowbase", ICLASS_xt_iclass_xsr_windowbase, + 0, + Opcode_xsr_windowbase_encode_fns, 0, 0 }, + { "rsr.windowstart", ICLASS_xt_iclass_rsr_windowstart, + 0, + Opcode_rsr_windowstart_encode_fns, 0, 0 }, + { "wsr.windowstart", ICLASS_xt_iclass_wsr_windowstart, + 0, + Opcode_wsr_windowstart_encode_fns, 0, 0 }, + { "xsr.windowstart", ICLASS_xt_iclass_xsr_windowstart, + 0, + Opcode_xsr_windowstart_encode_fns, 0, 0 }, + { "add.n", ICLASS_xt_iclass_add_n, + 0, + Opcode_add_n_encode_fns, 0, 0 }, + { "addi.n", ICLASS_xt_iclass_addi_n, + 0, + Opcode_addi_n_encode_fns, 0, 0 }, + { "beqz.n", ICLASS_xt_iclass_bz6, + XTENSA_OPCODE_IS_BRANCH, + Opcode_beqz_n_encode_fns, 0, 0 }, + { "bnez.n", ICLASS_xt_iclass_bz6, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bnez_n_encode_fns, 0, 0 }, + { "ill.n", ICLASS_xt_iclass_ill_n, + 0, + Opcode_ill_n_encode_fns, 0, 0 }, + { "l32i.n", ICLASS_xt_iclass_loadi4, + 0, + Opcode_l32i_n_encode_fns, 1, Opcode_l32i_n_funcUnit_uses }, + { "mov.n", ICLASS_xt_iclass_mov_n, + 0, + Opcode_mov_n_encode_fns, 0, 0 }, + { "movi.n", ICLASS_xt_iclass_movi_n, + 0, + Opcode_movi_n_encode_fns, 0, 0 }, + { "nop.n", ICLASS_xt_iclass_nopn, + 0, + Opcode_nop_n_encode_fns, 0, 0 }, + { "ret.n", ICLASS_xt_iclass_retn, + XTENSA_OPCODE_IS_JUMP, + Opcode_ret_n_encode_fns, 0, 0 }, + { "s32i.n", ICLASS_xt_iclass_storei4, + 0, + Opcode_s32i_n_encode_fns, 1, Opcode_s32i_n_funcUnit_uses }, + { "rur.threadptr", ICLASS_rur_threadptr, + 0, + Opcode_rur_threadptr_encode_fns, 0, 0 }, + { "wur.threadptr", ICLASS_wur_threadptr, + 0, + Opcode_wur_threadptr_encode_fns, 0, 0 }, + { "addi", ICLASS_xt_iclass_addi, + 0, + Opcode_addi_encode_fns, 0, 0 }, + { "addmi", ICLASS_xt_iclass_addmi, + 0, + Opcode_addmi_encode_fns, 0, 0 }, + { "add", ICLASS_xt_iclass_addsub, + 0, + Opcode_add_encode_fns, 0, 0 }, + { "addx2", ICLASS_xt_iclass_addsub, + 0, + Opcode_addx2_encode_fns, 0, 0 }, + { "addx4", ICLASS_xt_iclass_addsub, + 0, + Opcode_addx4_encode_fns, 0, 0 }, + { "addx8", ICLASS_xt_iclass_addsub, + 0, + Opcode_addx8_encode_fns, 0, 0 }, + { "sub", ICLASS_xt_iclass_addsub, + 0, + Opcode_sub_encode_fns, 0, 0 }, + { "subx2", ICLASS_xt_iclass_addsub, + 0, + Opcode_subx2_encode_fns, 0, 0 }, + { "subx4", ICLASS_xt_iclass_addsub, + 0, + Opcode_subx4_encode_fns, 0, 0 }, + { "subx8", ICLASS_xt_iclass_addsub, + 0, + Opcode_subx8_encode_fns, 0, 0 }, + { "and", ICLASS_xt_iclass_bit, + 0, + Opcode_and_encode_fns, 0, 0 }, + { "or", ICLASS_xt_iclass_bit, + 0, + Opcode_or_encode_fns, 0, 0 }, + { "xor", ICLASS_xt_iclass_bit, + 0, + Opcode_xor_encode_fns, 0, 0 }, + { "beqi", ICLASS_xt_iclass_bsi8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_beqi_encode_fns, 0, 0 }, + { "bgei", ICLASS_xt_iclass_bsi8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bgei_encode_fns, 0, 0 }, + { "blti", ICLASS_xt_iclass_bsi8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_blti_encode_fns, 0, 0 }, + { "bnei", ICLASS_xt_iclass_bsi8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bnei_encode_fns, 0, 0 }, + { "bbci", ICLASS_xt_iclass_bsi8b, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bbci_encode_fns, 0, 0 }, + { "bbsi", ICLASS_xt_iclass_bsi8b, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bbsi_encode_fns, 0, 0 }, + { "bgeui", ICLASS_xt_iclass_bsi8u, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bgeui_encode_fns, 0, 0 }, + { "bltui", ICLASS_xt_iclass_bsi8u, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bltui_encode_fns, 0, 0 }, + { "ball", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_ball_encode_fns, 0, 0 }, + { "bany", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bany_encode_fns, 0, 0 }, + { "bbc", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bbc_encode_fns, 0, 0 }, + { "bbs", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bbs_encode_fns, 0, 0 }, + { "beq", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_beq_encode_fns, 0, 0 }, + { "bge", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bge_encode_fns, 0, 0 }, + { "bgeu", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bgeu_encode_fns, 0, 0 }, + { "blt", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_blt_encode_fns, 0, 0 }, + { "bltu", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bltu_encode_fns, 0, 0 }, + { "bnall", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bnall_encode_fns, 0, 0 }, + { "bne", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bne_encode_fns, 0, 0 }, + { "bnone", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bnone_encode_fns, 0, 0 }, + { "beqz", ICLASS_xt_iclass_bsz12, + XTENSA_OPCODE_IS_BRANCH, + Opcode_beqz_encode_fns, 0, 0 }, + { "bgez", ICLASS_xt_iclass_bsz12, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bgez_encode_fns, 0, 0 }, + { "bltz", ICLASS_xt_iclass_bsz12, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bltz_encode_fns, 0, 0 }, + { "bnez", ICLASS_xt_iclass_bsz12, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bnez_encode_fns, 0, 0 }, + { "call0", ICLASS_xt_iclass_call0, + XTENSA_OPCODE_IS_CALL, + Opcode_call0_encode_fns, 0, 0 }, + { "callx0", ICLASS_xt_iclass_callx0, + XTENSA_OPCODE_IS_CALL, + Opcode_callx0_encode_fns, 0, 0 }, + { "extui", ICLASS_xt_iclass_exti, + 0, + Opcode_extui_encode_fns, 0, 0 }, + { "ill", ICLASS_xt_iclass_ill, + 0, + Opcode_ill_encode_fns, 0, 0 }, + { "j", ICLASS_xt_iclass_jump, + XTENSA_OPCODE_IS_JUMP, + Opcode_j_encode_fns, 0, 0 }, + { "jx", ICLASS_xt_iclass_jumpx, + XTENSA_OPCODE_IS_JUMP, + Opcode_jx_encode_fns, 0, 0 }, + { "l16ui", ICLASS_xt_iclass_l16ui, + 0, + Opcode_l16ui_encode_fns, 1, Opcode_l16ui_funcUnit_uses }, + { "l16si", ICLASS_xt_iclass_l16si, + 0, + Opcode_l16si_encode_fns, 1, Opcode_l16si_funcUnit_uses }, + { "l32i", ICLASS_xt_iclass_l32i, + 0, + Opcode_l32i_encode_fns, 1, Opcode_l32i_funcUnit_uses }, + { "l32r", ICLASS_xt_iclass_l32r, + 0, + Opcode_l32r_encode_fns, 1, Opcode_l32r_funcUnit_uses }, + { "l8ui", ICLASS_xt_iclass_l8i, + 0, + Opcode_l8ui_encode_fns, 1, Opcode_l8ui_funcUnit_uses }, + { "loop", ICLASS_xt_iclass_loop, + XTENSA_OPCODE_IS_LOOP, + Opcode_loop_encode_fns, 0, 0 }, + { "loopgtz", ICLASS_xt_iclass_loopz, + XTENSA_OPCODE_IS_LOOP, + Opcode_loopgtz_encode_fns, 0, 0 }, + { "loopnez", ICLASS_xt_iclass_loopz, + XTENSA_OPCODE_IS_LOOP, + Opcode_loopnez_encode_fns, 0, 0 }, + { "movi", ICLASS_xt_iclass_movi, + 0, + Opcode_movi_encode_fns, 0, 0 }, + { "moveqz", ICLASS_xt_iclass_movz, + 0, + Opcode_moveqz_encode_fns, 0, 0 }, + { "movgez", ICLASS_xt_iclass_movz, + 0, + Opcode_movgez_encode_fns, 0, 0 }, + { "movltz", ICLASS_xt_iclass_movz, + 0, + Opcode_movltz_encode_fns, 0, 0 }, + { "movnez", ICLASS_xt_iclass_movz, + 0, + Opcode_movnez_encode_fns, 0, 0 }, + { "abs", ICLASS_xt_iclass_neg, + 0, + Opcode_abs_encode_fns, 0, 0 }, + { "neg", ICLASS_xt_iclass_neg, + 0, + Opcode_neg_encode_fns, 0, 0 }, + { "nop", ICLASS_xt_iclass_nop, + 0, + Opcode_nop_encode_fns, 0, 0 }, + { "ret", ICLASS_xt_iclass_return, + XTENSA_OPCODE_IS_JUMP, + Opcode_ret_encode_fns, 0, 0 }, + { "simcall", ICLASS_xt_iclass_simcall, + 0, + Opcode_simcall_encode_fns, 0, 0 }, + { "s16i", ICLASS_xt_iclass_s16i, + 0, + Opcode_s16i_encode_fns, 1, Opcode_s16i_funcUnit_uses }, + { "s32i", ICLASS_xt_iclass_s32i, + 0, + Opcode_s32i_encode_fns, 1, Opcode_s32i_funcUnit_uses }, + { "s32nb", ICLASS_xt_iclass_s32nb, + 0, + Opcode_s32nb_encode_fns, 1, Opcode_s32nb_funcUnit_uses }, + { "s8i", ICLASS_xt_iclass_s8i, + 0, + Opcode_s8i_encode_fns, 1, Opcode_s8i_funcUnit_uses }, + { "ssa8b", ICLASS_xt_iclass_sar, + 0, + Opcode_ssa8b_encode_fns, 0, 0 }, + { "ssa8l", ICLASS_xt_iclass_sar, + 0, + Opcode_ssa8l_encode_fns, 0, 0 }, + { "ssl", ICLASS_xt_iclass_sar, + 0, + Opcode_ssl_encode_fns, 0, 0 }, + { "ssr", ICLASS_xt_iclass_sar, + 0, + Opcode_ssr_encode_fns, 0, 0 }, + { "ssai", ICLASS_xt_iclass_sari, + 0, + Opcode_ssai_encode_fns, 0, 0 }, + { "sll", ICLASS_xt_iclass_shifts, + 0, + Opcode_sll_encode_fns, 0, 0 }, + { "src", ICLASS_xt_iclass_shiftst, + 0, + Opcode_src_encode_fns, 0, 0 }, + { "sra", ICLASS_xt_iclass_shiftt, + 0, + Opcode_sra_encode_fns, 0, 0 }, + { "srl", ICLASS_xt_iclass_shiftt, + 0, + Opcode_srl_encode_fns, 0, 0 }, + { "slli", ICLASS_xt_iclass_slli, + 0, + Opcode_slli_encode_fns, 0, 0 }, + { "srai", ICLASS_xt_iclass_srai, + 0, + Opcode_srai_encode_fns, 0, 0 }, + { "srli", ICLASS_xt_iclass_srli, + 0, + Opcode_srli_encode_fns, 0, 0 }, + { "memw", ICLASS_xt_iclass_memw, + 0, + Opcode_memw_encode_fns, 0, 0 }, + { "extw", ICLASS_xt_iclass_extw, + 0, + Opcode_extw_encode_fns, 0, 0 }, + { "isync", ICLASS_xt_iclass_isync, + 0, + Opcode_isync_encode_fns, 0, 0 }, + { "dsync", ICLASS_xt_iclass_sync, + 0, + Opcode_dsync_encode_fns, 0, 0 }, + { "esync", ICLASS_xt_iclass_sync, + 0, + Opcode_esync_encode_fns, 0, 0 }, + { "rsync", ICLASS_xt_iclass_sync, + 0, + Opcode_rsync_encode_fns, 0, 0 }, + { "rsil", ICLASS_xt_iclass_rsil, + 0, + Opcode_rsil_encode_fns, 0, 0 }, + { "rsr.lend", ICLASS_xt_iclass_rsr_lend, + 0, + Opcode_rsr_lend_encode_fns, 0, 0 }, + { "wsr.lend", ICLASS_xt_iclass_wsr_lend, + 0, + Opcode_wsr_lend_encode_fns, 0, 0 }, + { "xsr.lend", ICLASS_xt_iclass_xsr_lend, + 0, + Opcode_xsr_lend_encode_fns, 0, 0 }, + { "rsr.lcount", ICLASS_xt_iclass_rsr_lcount, + 0, + Opcode_rsr_lcount_encode_fns, 0, 0 }, + { "wsr.lcount", ICLASS_xt_iclass_wsr_lcount, + 0, + Opcode_wsr_lcount_encode_fns, 0, 0 }, + { "xsr.lcount", ICLASS_xt_iclass_xsr_lcount, + 0, + Opcode_xsr_lcount_encode_fns, 0, 0 }, + { "rsr.lbeg", ICLASS_xt_iclass_rsr_lbeg, + 0, + Opcode_rsr_lbeg_encode_fns, 0, 0 }, + { "wsr.lbeg", ICLASS_xt_iclass_wsr_lbeg, + 0, + Opcode_wsr_lbeg_encode_fns, 0, 0 }, + { "xsr.lbeg", ICLASS_xt_iclass_xsr_lbeg, + 0, + Opcode_xsr_lbeg_encode_fns, 0, 0 }, + { "rsr.sar", ICLASS_xt_iclass_rsr_sar, + 0, + Opcode_rsr_sar_encode_fns, 0, 0 }, + { "wsr.sar", ICLASS_xt_iclass_wsr_sar, + 0, + Opcode_wsr_sar_encode_fns, 0, 0 }, + { "xsr.sar", ICLASS_xt_iclass_xsr_sar, + 0, + Opcode_xsr_sar_encode_fns, 0, 0 }, + { "rsr.memctl", ICLASS_xt_iclass_rsr_memctl, + 0, + Opcode_rsr_memctl_encode_fns, 0, 0 }, + { "wsr.memctl", ICLASS_xt_iclass_wsr_memctl, + 0, + Opcode_wsr_memctl_encode_fns, 0, 0 }, + { "xsr.memctl", ICLASS_xt_iclass_xsr_memctl, + 0, + Opcode_xsr_memctl_encode_fns, 0, 0 }, + { "rsr.configid0", ICLASS_xt_iclass_rsr_configid0, + 0, + Opcode_rsr_configid0_encode_fns, 0, 0 }, + { "wsr.configid0", ICLASS_xt_iclass_wsr_configid0, + 0, + Opcode_wsr_configid0_encode_fns, 0, 0 }, + { "rsr.configid1", ICLASS_xt_iclass_rsr_configid1, + 0, + Opcode_rsr_configid1_encode_fns, 0, 0 }, + { "rsr.ps", ICLASS_xt_iclass_rsr_ps, + 0, + Opcode_rsr_ps_encode_fns, 0, 0 }, + { "wsr.ps", ICLASS_xt_iclass_wsr_ps, + 0, + Opcode_wsr_ps_encode_fns, 0, 0 }, + { "xsr.ps", ICLASS_xt_iclass_xsr_ps, + 0, + Opcode_xsr_ps_encode_fns, 0, 0 }, + { "rsr.epc1", ICLASS_xt_iclass_rsr_epc1, + 0, + Opcode_rsr_epc1_encode_fns, 0, 0 }, + { "wsr.epc1", ICLASS_xt_iclass_wsr_epc1, + 0, + Opcode_wsr_epc1_encode_fns, 0, 0 }, + { "xsr.epc1", ICLASS_xt_iclass_xsr_epc1, + 0, + Opcode_xsr_epc1_encode_fns, 0, 0 }, + { "rsr.excsave1", ICLASS_xt_iclass_rsr_excsave1, + 0, + Opcode_rsr_excsave1_encode_fns, 0, 0 }, + { "wsr.excsave1", ICLASS_xt_iclass_wsr_excsave1, + 0, + Opcode_wsr_excsave1_encode_fns, 0, 0 }, + { "xsr.excsave1", ICLASS_xt_iclass_xsr_excsave1, + 0, + Opcode_xsr_excsave1_encode_fns, 0, 0 }, + { "rsr.epc2", ICLASS_xt_iclass_rsr_epc2, + 0, + Opcode_rsr_epc2_encode_fns, 0, 0 }, + { "wsr.epc2", ICLASS_xt_iclass_wsr_epc2, + 0, + Opcode_wsr_epc2_encode_fns, 0, 0 }, + { "xsr.epc2", ICLASS_xt_iclass_xsr_epc2, + 0, + Opcode_xsr_epc2_encode_fns, 0, 0 }, + { "rsr.excsave2", ICLASS_xt_iclass_rsr_excsave2, + 0, + Opcode_rsr_excsave2_encode_fns, 0, 0 }, + { "wsr.excsave2", ICLASS_xt_iclass_wsr_excsave2, + 0, + Opcode_wsr_excsave2_encode_fns, 0, 0 }, + { "xsr.excsave2", ICLASS_xt_iclass_xsr_excsave2, + 0, + Opcode_xsr_excsave2_encode_fns, 0, 0 }, + { "rsr.epc3", ICLASS_xt_iclass_rsr_epc3, + 0, + Opcode_rsr_epc3_encode_fns, 0, 0 }, + { "wsr.epc3", ICLASS_xt_iclass_wsr_epc3, + 0, + Opcode_wsr_epc3_encode_fns, 0, 0 }, + { "xsr.epc3", ICLASS_xt_iclass_xsr_epc3, + 0, + Opcode_xsr_epc3_encode_fns, 0, 0 }, + { "rsr.excsave3", ICLASS_xt_iclass_rsr_excsave3, + 0, + Opcode_rsr_excsave3_encode_fns, 0, 0 }, + { "wsr.excsave3", ICLASS_xt_iclass_wsr_excsave3, + 0, + Opcode_wsr_excsave3_encode_fns, 0, 0 }, + { "xsr.excsave3", ICLASS_xt_iclass_xsr_excsave3, + 0, + Opcode_xsr_excsave3_encode_fns, 0, 0 }, + { "rsr.epc4", ICLASS_xt_iclass_rsr_epc4, + 0, + Opcode_rsr_epc4_encode_fns, 0, 0 }, + { "wsr.epc4", ICLASS_xt_iclass_wsr_epc4, + 0, + Opcode_wsr_epc4_encode_fns, 0, 0 }, + { "xsr.epc4", ICLASS_xt_iclass_xsr_epc4, + 0, + Opcode_xsr_epc4_encode_fns, 0, 0 }, + { "rsr.excsave4", ICLASS_xt_iclass_rsr_excsave4, + 0, + Opcode_rsr_excsave4_encode_fns, 0, 0 }, + { "wsr.excsave4", ICLASS_xt_iclass_wsr_excsave4, + 0, + Opcode_wsr_excsave4_encode_fns, 0, 0 }, + { "xsr.excsave4", ICLASS_xt_iclass_xsr_excsave4, + 0, + Opcode_xsr_excsave4_encode_fns, 0, 0 }, + { "rsr.epc5", ICLASS_xt_iclass_rsr_epc5, + 0, + Opcode_rsr_epc5_encode_fns, 0, 0 }, + { "wsr.epc5", ICLASS_xt_iclass_wsr_epc5, + 0, + Opcode_wsr_epc5_encode_fns, 0, 0 }, + { "xsr.epc5", ICLASS_xt_iclass_xsr_epc5, + 0, + Opcode_xsr_epc5_encode_fns, 0, 0 }, + { "rsr.excsave5", ICLASS_xt_iclass_rsr_excsave5, + 0, + Opcode_rsr_excsave5_encode_fns, 0, 0 }, + { "wsr.excsave5", ICLASS_xt_iclass_wsr_excsave5, + 0, + Opcode_wsr_excsave5_encode_fns, 0, 0 }, + { "xsr.excsave5", ICLASS_xt_iclass_xsr_excsave5, + 0, + Opcode_xsr_excsave5_encode_fns, 0, 0 }, + { "rsr.epc6", ICLASS_xt_iclass_rsr_epc6, + 0, + Opcode_rsr_epc6_encode_fns, 0, 0 }, + { "wsr.epc6", ICLASS_xt_iclass_wsr_epc6, + 0, + Opcode_wsr_epc6_encode_fns, 0, 0 }, + { "xsr.epc6", ICLASS_xt_iclass_xsr_epc6, + 0, + Opcode_xsr_epc6_encode_fns, 0, 0 }, + { "rsr.excsave6", ICLASS_xt_iclass_rsr_excsave6, + 0, + Opcode_rsr_excsave6_encode_fns, 0, 0 }, + { "wsr.excsave6", ICLASS_xt_iclass_wsr_excsave6, + 0, + Opcode_wsr_excsave6_encode_fns, 0, 0 }, + { "xsr.excsave6", ICLASS_xt_iclass_xsr_excsave6, + 0, + Opcode_xsr_excsave6_encode_fns, 0, 0 }, + { "rsr.epc7", ICLASS_xt_iclass_rsr_epc7, + 0, + Opcode_rsr_epc7_encode_fns, 0, 0 }, + { "wsr.epc7", ICLASS_xt_iclass_wsr_epc7, + 0, + Opcode_wsr_epc7_encode_fns, 0, 0 }, + { "xsr.epc7", ICLASS_xt_iclass_xsr_epc7, + 0, + Opcode_xsr_epc7_encode_fns, 0, 0 }, + { "rsr.excsave7", ICLASS_xt_iclass_rsr_excsave7, + 0, + Opcode_rsr_excsave7_encode_fns, 0, 0 }, + { "wsr.excsave7", ICLASS_xt_iclass_wsr_excsave7, + 0, + Opcode_wsr_excsave7_encode_fns, 0, 0 }, + { "xsr.excsave7", ICLASS_xt_iclass_xsr_excsave7, + 0, + Opcode_xsr_excsave7_encode_fns, 0, 0 }, + { "rsr.eps2", ICLASS_xt_iclass_rsr_eps2, + 0, + Opcode_rsr_eps2_encode_fns, 0, 0 }, + { "wsr.eps2", ICLASS_xt_iclass_wsr_eps2, + 0, + Opcode_wsr_eps2_encode_fns, 0, 0 }, + { "xsr.eps2", ICLASS_xt_iclass_xsr_eps2, + 0, + Opcode_xsr_eps2_encode_fns, 0, 0 }, + { "rsr.eps3", ICLASS_xt_iclass_rsr_eps3, + 0, + Opcode_rsr_eps3_encode_fns, 0, 0 }, + { "wsr.eps3", ICLASS_xt_iclass_wsr_eps3, + 0, + Opcode_wsr_eps3_encode_fns, 0, 0 }, + { "xsr.eps3", ICLASS_xt_iclass_xsr_eps3, + 0, + Opcode_xsr_eps3_encode_fns, 0, 0 }, + { "rsr.eps4", ICLASS_xt_iclass_rsr_eps4, + 0, + Opcode_rsr_eps4_encode_fns, 0, 0 }, + { "wsr.eps4", ICLASS_xt_iclass_wsr_eps4, + 0, + Opcode_wsr_eps4_encode_fns, 0, 0 }, + { "xsr.eps4", ICLASS_xt_iclass_xsr_eps4, + 0, + Opcode_xsr_eps4_encode_fns, 0, 0 }, + { "rsr.eps5", ICLASS_xt_iclass_rsr_eps5, + 0, + Opcode_rsr_eps5_encode_fns, 0, 0 }, + { "wsr.eps5", ICLASS_xt_iclass_wsr_eps5, + 0, + Opcode_wsr_eps5_encode_fns, 0, 0 }, + { "xsr.eps5", ICLASS_xt_iclass_xsr_eps5, + 0, + Opcode_xsr_eps5_encode_fns, 0, 0 }, + { "rsr.eps6", ICLASS_xt_iclass_rsr_eps6, + 0, + Opcode_rsr_eps6_encode_fns, 0, 0 }, + { "wsr.eps6", ICLASS_xt_iclass_wsr_eps6, + 0, + Opcode_wsr_eps6_encode_fns, 0, 0 }, + { "xsr.eps6", ICLASS_xt_iclass_xsr_eps6, + 0, + Opcode_xsr_eps6_encode_fns, 0, 0 }, + { "rsr.eps7", ICLASS_xt_iclass_rsr_eps7, + 0, + Opcode_rsr_eps7_encode_fns, 0, 0 }, + { "wsr.eps7", ICLASS_xt_iclass_wsr_eps7, + 0, + Opcode_wsr_eps7_encode_fns, 0, 0 }, + { "xsr.eps7", ICLASS_xt_iclass_xsr_eps7, + 0, + Opcode_xsr_eps7_encode_fns, 0, 0 }, + { "rsr.excvaddr", ICLASS_xt_iclass_rsr_excvaddr, + 0, + Opcode_rsr_excvaddr_encode_fns, 0, 0 }, + { "wsr.excvaddr", ICLASS_xt_iclass_wsr_excvaddr, + 0, + Opcode_wsr_excvaddr_encode_fns, 0, 0 }, + { "xsr.excvaddr", ICLASS_xt_iclass_xsr_excvaddr, + 0, + Opcode_xsr_excvaddr_encode_fns, 0, 0 }, + { "rsr.depc", ICLASS_xt_iclass_rsr_depc, + 0, + Opcode_rsr_depc_encode_fns, 0, 0 }, + { "wsr.depc", ICLASS_xt_iclass_wsr_depc, + 0, + Opcode_wsr_depc_encode_fns, 0, 0 }, + { "xsr.depc", ICLASS_xt_iclass_xsr_depc, + 0, + Opcode_xsr_depc_encode_fns, 0, 0 }, + { "rsr.exccause", ICLASS_xt_iclass_rsr_exccause, + 0, + Opcode_rsr_exccause_encode_fns, 0, 0 }, + { "wsr.exccause", ICLASS_xt_iclass_wsr_exccause, + 0, + Opcode_wsr_exccause_encode_fns, 0, 0 }, + { "xsr.exccause", ICLASS_xt_iclass_xsr_exccause, + 0, + Opcode_xsr_exccause_encode_fns, 0, 0 }, + { "rsr.misc0", ICLASS_xt_iclass_rsr_misc0, + 0, + Opcode_rsr_misc0_encode_fns, 0, 0 }, + { "wsr.misc0", ICLASS_xt_iclass_wsr_misc0, + 0, + Opcode_wsr_misc0_encode_fns, 0, 0 }, + { "xsr.misc0", ICLASS_xt_iclass_xsr_misc0, + 0, + Opcode_xsr_misc0_encode_fns, 0, 0 }, + { "rsr.misc1", ICLASS_xt_iclass_rsr_misc1, + 0, + Opcode_rsr_misc1_encode_fns, 0, 0 }, + { "wsr.misc1", ICLASS_xt_iclass_wsr_misc1, + 0, + Opcode_wsr_misc1_encode_fns, 0, 0 }, + { "xsr.misc1", ICLASS_xt_iclass_xsr_misc1, + 0, + Opcode_xsr_misc1_encode_fns, 0, 0 }, + { "rsr.prid", ICLASS_xt_iclass_rsr_prid, + 0, + Opcode_rsr_prid_encode_fns, 0, 0 }, + { "rsr.vecbase", ICLASS_xt_iclass_rsr_vecbase, + 0, + Opcode_rsr_vecbase_encode_fns, 0, 0 }, + { "wsr.vecbase", ICLASS_xt_iclass_wsr_vecbase, + 0, + Opcode_wsr_vecbase_encode_fns, 0, 0 }, + { "xsr.vecbase", ICLASS_xt_iclass_xsr_vecbase, + 0, + Opcode_xsr_vecbase_encode_fns, 0, 0 }, + { "salt", ICLASS_xt_iclass_salt, + 0, + Opcode_salt_encode_fns, 0, 0 }, + { "saltu", ICLASS_xt_iclass_salt, + 0, + Opcode_saltu_encode_fns, 0, 0 }, + { "mul16s", ICLASS_xt_mul16, + 0, + Opcode_mul16s_encode_fns, 0, 0 }, + { "mul16u", ICLASS_xt_mul16, + 0, + Opcode_mul16u_encode_fns, 0, 0 }, + { "mull", ICLASS_xt_mul32, + 0, + Opcode_mull_encode_fns, 0, 0 }, + { "mul.aa.hh", ICLASS_xt_iclass_mac16_aa, + 0, + Opcode_mul_aa_hh_encode_fns, 0, 0 }, + { "mul.aa.hl", ICLASS_xt_iclass_mac16_aa, + 0, + Opcode_mul_aa_hl_encode_fns, 0, 0 }, + { "mul.aa.lh", ICLASS_xt_iclass_mac16_aa, + 0, + Opcode_mul_aa_lh_encode_fns, 0, 0 }, + { "mul.aa.ll", ICLASS_xt_iclass_mac16_aa, + 0, + Opcode_mul_aa_ll_encode_fns, 0, 0 }, + { "umul.aa.hh", ICLASS_xt_iclass_mac16_aa, + 0, + Opcode_umul_aa_hh_encode_fns, 0, 0 }, + { "umul.aa.hl", ICLASS_xt_iclass_mac16_aa, + 0, + Opcode_umul_aa_hl_encode_fns, 0, 0 }, + { "umul.aa.lh", ICLASS_xt_iclass_mac16_aa, + 0, + Opcode_umul_aa_lh_encode_fns, 0, 0 }, + { "umul.aa.ll", ICLASS_xt_iclass_mac16_aa, + 0, + Opcode_umul_aa_ll_encode_fns, 0, 0 }, + { "mul.ad.hh", ICLASS_xt_iclass_mac16_ad, + 0, + Opcode_mul_ad_hh_encode_fns, 0, 0 }, + { "mul.ad.hl", ICLASS_xt_iclass_mac16_ad, + 0, + Opcode_mul_ad_hl_encode_fns, 0, 0 }, + { "mul.ad.lh", ICLASS_xt_iclass_mac16_ad, + 0, + Opcode_mul_ad_lh_encode_fns, 0, 0 }, + { "mul.ad.ll", ICLASS_xt_iclass_mac16_ad, + 0, + Opcode_mul_ad_ll_encode_fns, 0, 0 }, + { "mul.da.hh", ICLASS_xt_iclass_mac16_da, + 0, + Opcode_mul_da_hh_encode_fns, 0, 0 }, + { "mul.da.hl", ICLASS_xt_iclass_mac16_da, + 0, + Opcode_mul_da_hl_encode_fns, 0, 0 }, + { "mul.da.lh", ICLASS_xt_iclass_mac16_da, + 0, + Opcode_mul_da_lh_encode_fns, 0, 0 }, + { "mul.da.ll", ICLASS_xt_iclass_mac16_da, + 0, + Opcode_mul_da_ll_encode_fns, 0, 0 }, + { "mul.dd.hh", ICLASS_xt_iclass_mac16_dd, + 0, + Opcode_mul_dd_hh_encode_fns, 0, 0 }, + { "mul.dd.hl", ICLASS_xt_iclass_mac16_dd, + 0, + Opcode_mul_dd_hl_encode_fns, 0, 0 }, + { "mul.dd.lh", ICLASS_xt_iclass_mac16_dd, + 0, + Opcode_mul_dd_lh_encode_fns, 0, 0 }, + { "mul.dd.ll", ICLASS_xt_iclass_mac16_dd, + 0, + Opcode_mul_dd_ll_encode_fns, 0, 0 }, + { "mula.aa.hh", ICLASS_xt_iclass_mac16a_aa, + 0, + Opcode_mula_aa_hh_encode_fns, 0, 0 }, + { "mula.aa.hl", ICLASS_xt_iclass_mac16a_aa, + 0, + Opcode_mula_aa_hl_encode_fns, 0, 0 }, + { "mula.aa.lh", ICLASS_xt_iclass_mac16a_aa, + 0, + Opcode_mula_aa_lh_encode_fns, 0, 0 }, + { "mula.aa.ll", ICLASS_xt_iclass_mac16a_aa, + 0, + Opcode_mula_aa_ll_encode_fns, 0, 0 }, + { "muls.aa.hh", ICLASS_xt_iclass_mac16a_aa, + 0, + Opcode_muls_aa_hh_encode_fns, 0, 0 }, + { "muls.aa.hl", ICLASS_xt_iclass_mac16a_aa, + 0, + Opcode_muls_aa_hl_encode_fns, 0, 0 }, + { "muls.aa.lh", ICLASS_xt_iclass_mac16a_aa, + 0, + Opcode_muls_aa_lh_encode_fns, 0, 0 }, + { "muls.aa.ll", ICLASS_xt_iclass_mac16a_aa, + 0, + Opcode_muls_aa_ll_encode_fns, 0, 0 }, + { "mula.ad.hh", ICLASS_xt_iclass_mac16a_ad, + 0, + Opcode_mula_ad_hh_encode_fns, 0, 0 }, + { "mula.ad.hl", ICLASS_xt_iclass_mac16a_ad, + 0, + Opcode_mula_ad_hl_encode_fns, 0, 0 }, + { "mula.ad.lh", ICLASS_xt_iclass_mac16a_ad, + 0, + Opcode_mula_ad_lh_encode_fns, 0, 0 }, + { "mula.ad.ll", ICLASS_xt_iclass_mac16a_ad, + 0, + Opcode_mula_ad_ll_encode_fns, 0, 0 }, + { "muls.ad.hh", ICLASS_xt_iclass_mac16a_ad, + 0, + Opcode_muls_ad_hh_encode_fns, 0, 0 }, + { "muls.ad.hl", ICLASS_xt_iclass_mac16a_ad, + 0, + Opcode_muls_ad_hl_encode_fns, 0, 0 }, + { "muls.ad.lh", ICLASS_xt_iclass_mac16a_ad, + 0, + Opcode_muls_ad_lh_encode_fns, 0, 0 }, + { "muls.ad.ll", ICLASS_xt_iclass_mac16a_ad, + 0, + Opcode_muls_ad_ll_encode_fns, 0, 0 }, + { "mula.da.hh", ICLASS_xt_iclass_mac16a_da, + 0, + Opcode_mula_da_hh_encode_fns, 0, 0 }, + { "mula.da.hl", ICLASS_xt_iclass_mac16a_da, + 0, + Opcode_mula_da_hl_encode_fns, 0, 0 }, + { "mula.da.lh", ICLASS_xt_iclass_mac16a_da, + 0, + Opcode_mula_da_lh_encode_fns, 0, 0 }, + { "mula.da.ll", ICLASS_xt_iclass_mac16a_da, + 0, + Opcode_mula_da_ll_encode_fns, 0, 0 }, + { "muls.da.hh", ICLASS_xt_iclass_mac16a_da, + 0, + Opcode_muls_da_hh_encode_fns, 0, 0 }, + { "muls.da.hl", ICLASS_xt_iclass_mac16a_da, + 0, + Opcode_muls_da_hl_encode_fns, 0, 0 }, + { "muls.da.lh", ICLASS_xt_iclass_mac16a_da, + 0, + Opcode_muls_da_lh_encode_fns, 0, 0 }, + { "muls.da.ll", ICLASS_xt_iclass_mac16a_da, + 0, + Opcode_muls_da_ll_encode_fns, 0, 0 }, + { "mula.dd.hh", ICLASS_xt_iclass_mac16a_dd, + 0, + Opcode_mula_dd_hh_encode_fns, 0, 0 }, + { "mula.dd.hl", ICLASS_xt_iclass_mac16a_dd, + 0, + Opcode_mula_dd_hl_encode_fns, 0, 0 }, + { "mula.dd.lh", ICLASS_xt_iclass_mac16a_dd, + 0, + Opcode_mula_dd_lh_encode_fns, 0, 0 }, + { "mula.dd.ll", ICLASS_xt_iclass_mac16a_dd, + 0, + Opcode_mula_dd_ll_encode_fns, 0, 0 }, + { "muls.dd.hh", ICLASS_xt_iclass_mac16a_dd, + 0, + Opcode_muls_dd_hh_encode_fns, 0, 0 }, + { "muls.dd.hl", ICLASS_xt_iclass_mac16a_dd, + 0, + Opcode_muls_dd_hl_encode_fns, 0, 0 }, + { "muls.dd.lh", ICLASS_xt_iclass_mac16a_dd, + 0, + Opcode_muls_dd_lh_encode_fns, 0, 0 }, + { "muls.dd.ll", ICLASS_xt_iclass_mac16a_dd, + 0, + Opcode_muls_dd_ll_encode_fns, 0, 0 }, + { "mula.da.hh.lddec", ICLASS_xt_iclass_mac16al_da, + 0, + Opcode_mula_da_hh_lddec_encode_fns, 1, Opcode_mula_da_hh_lddec_funcUnit_uses }, + { "mula.da.hh.ldinc", ICLASS_xt_iclass_mac16al_da, + 0, + Opcode_mula_da_hh_ldinc_encode_fns, 1, Opcode_mula_da_hh_ldinc_funcUnit_uses }, + { "mula.da.hl.lddec", ICLASS_xt_iclass_mac16al_da, + 0, + Opcode_mula_da_hl_lddec_encode_fns, 1, Opcode_mula_da_hl_lddec_funcUnit_uses }, + { "mula.da.hl.ldinc", ICLASS_xt_iclass_mac16al_da, + 0, + Opcode_mula_da_hl_ldinc_encode_fns, 1, Opcode_mula_da_hl_ldinc_funcUnit_uses }, + { "mula.da.lh.lddec", ICLASS_xt_iclass_mac16al_da, + 0, + Opcode_mula_da_lh_lddec_encode_fns, 1, Opcode_mula_da_lh_lddec_funcUnit_uses }, + { "mula.da.lh.ldinc", ICLASS_xt_iclass_mac16al_da, + 0, + Opcode_mula_da_lh_ldinc_encode_fns, 1, Opcode_mula_da_lh_ldinc_funcUnit_uses }, + { "mula.da.ll.lddec", ICLASS_xt_iclass_mac16al_da, + 0, + Opcode_mula_da_ll_lddec_encode_fns, 1, Opcode_mula_da_ll_lddec_funcUnit_uses }, + { "mula.da.ll.ldinc", ICLASS_xt_iclass_mac16al_da, + 0, + Opcode_mula_da_ll_ldinc_encode_fns, 1, Opcode_mula_da_ll_ldinc_funcUnit_uses }, + { "mula.dd.hh.lddec", ICLASS_xt_iclass_mac16al_dd, + 0, + Opcode_mula_dd_hh_lddec_encode_fns, 1, Opcode_mula_dd_hh_lddec_funcUnit_uses }, + { "mula.dd.hh.ldinc", ICLASS_xt_iclass_mac16al_dd, + 0, + Opcode_mula_dd_hh_ldinc_encode_fns, 1, Opcode_mula_dd_hh_ldinc_funcUnit_uses }, + { "mula.dd.hl.lddec", ICLASS_xt_iclass_mac16al_dd, + 0, + Opcode_mula_dd_hl_lddec_encode_fns, 1, Opcode_mula_dd_hl_lddec_funcUnit_uses }, + { "mula.dd.hl.ldinc", ICLASS_xt_iclass_mac16al_dd, + 0, + Opcode_mula_dd_hl_ldinc_encode_fns, 1, Opcode_mula_dd_hl_ldinc_funcUnit_uses }, + { "mula.dd.lh.lddec", ICLASS_xt_iclass_mac16al_dd, + 0, + Opcode_mula_dd_lh_lddec_encode_fns, 1, Opcode_mula_dd_lh_lddec_funcUnit_uses }, + { "mula.dd.lh.ldinc", ICLASS_xt_iclass_mac16al_dd, + 0, + Opcode_mula_dd_lh_ldinc_encode_fns, 1, Opcode_mula_dd_lh_ldinc_funcUnit_uses }, + { "mula.dd.ll.lddec", ICLASS_xt_iclass_mac16al_dd, + 0, + Opcode_mula_dd_ll_lddec_encode_fns, 1, Opcode_mula_dd_ll_lddec_funcUnit_uses }, + { "mula.dd.ll.ldinc", ICLASS_xt_iclass_mac16al_dd, + 0, + Opcode_mula_dd_ll_ldinc_encode_fns, 1, Opcode_mula_dd_ll_ldinc_funcUnit_uses }, + { "lddec", ICLASS_xt_iclass_mac16_l, + 0, + Opcode_lddec_encode_fns, 1, Opcode_lddec_funcUnit_uses }, + { "ldinc", ICLASS_xt_iclass_mac16_l, + 0, + Opcode_ldinc_encode_fns, 1, Opcode_ldinc_funcUnit_uses }, + { "rsr.m0", ICLASS_xt_iclass_rsr_m0, + 0, + Opcode_rsr_m0_encode_fns, 0, 0 }, + { "wsr.m0", ICLASS_xt_iclass_wsr_m0, + 0, + Opcode_wsr_m0_encode_fns, 0, 0 }, + { "xsr.m0", ICLASS_xt_iclass_xsr_m0, + 0, + Opcode_xsr_m0_encode_fns, 0, 0 }, + { "rsr.m1", ICLASS_xt_iclass_rsr_m1, + 0, + Opcode_rsr_m1_encode_fns, 0, 0 }, + { "wsr.m1", ICLASS_xt_iclass_wsr_m1, + 0, + Opcode_wsr_m1_encode_fns, 0, 0 }, + { "xsr.m1", ICLASS_xt_iclass_xsr_m1, + 0, + Opcode_xsr_m1_encode_fns, 0, 0 }, + { "rsr.m2", ICLASS_xt_iclass_rsr_m2, + 0, + Opcode_rsr_m2_encode_fns, 0, 0 }, + { "wsr.m2", ICLASS_xt_iclass_wsr_m2, + 0, + Opcode_wsr_m2_encode_fns, 0, 0 }, + { "xsr.m2", ICLASS_xt_iclass_xsr_m2, + 0, + Opcode_xsr_m2_encode_fns, 0, 0 }, + { "rsr.m3", ICLASS_xt_iclass_rsr_m3, + 0, + Opcode_rsr_m3_encode_fns, 0, 0 }, + { "wsr.m3", ICLASS_xt_iclass_wsr_m3, + 0, + Opcode_wsr_m3_encode_fns, 0, 0 }, + { "xsr.m3", ICLASS_xt_iclass_xsr_m3, + 0, + Opcode_xsr_m3_encode_fns, 0, 0 }, + { "rsr.acclo", ICLASS_xt_iclass_rsr_acclo, + 0, + Opcode_rsr_acclo_encode_fns, 0, 0 }, + { "wsr.acclo", ICLASS_xt_iclass_wsr_acclo, + 0, + Opcode_wsr_acclo_encode_fns, 0, 0 }, + { "xsr.acclo", ICLASS_xt_iclass_xsr_acclo, + 0, + Opcode_xsr_acclo_encode_fns, 0, 0 }, + { "rsr.acchi", ICLASS_xt_iclass_rsr_acchi, + 0, + Opcode_rsr_acchi_encode_fns, 0, 0 }, + { "wsr.acchi", ICLASS_xt_iclass_wsr_acchi, + 0, + Opcode_wsr_acchi_encode_fns, 0, 0 }, + { "xsr.acchi", ICLASS_xt_iclass_xsr_acchi, + 0, + Opcode_xsr_acchi_encode_fns, 0, 0 }, + { "rfi", ICLASS_xt_iclass_rfi, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfi_encode_fns, 0, 0 }, + { "waiti", ICLASS_xt_iclass_wait, + 0, + Opcode_waiti_encode_fns, 0, 0 }, + { "rsr.interrupt", ICLASS_xt_iclass_rsr_interrupt, + 0, + Opcode_rsr_interrupt_encode_fns, 0, 0 }, + { "wsr.intset", ICLASS_xt_iclass_wsr_intset, + 0, + Opcode_wsr_intset_encode_fns, 0, 0 }, + { "wsr.intclear", ICLASS_xt_iclass_wsr_intclear, + 0, + Opcode_wsr_intclear_encode_fns, 0, 0 }, + { "rsr.intenable", ICLASS_xt_iclass_rsr_intenable, + 0, + Opcode_rsr_intenable_encode_fns, 0, 0 }, + { "wsr.intenable", ICLASS_xt_iclass_wsr_intenable, + 0, + Opcode_wsr_intenable_encode_fns, 0, 0 }, + { "xsr.intenable", ICLASS_xt_iclass_xsr_intenable, + 0, + Opcode_xsr_intenable_encode_fns, 0, 0 }, + { "break", ICLASS_xt_iclass_break, + 0, + Opcode_break_encode_fns, 0, 0 }, + { "break.n", ICLASS_xt_iclass_break_n, + 0, + Opcode_break_n_encode_fns, 0, 0 }, + { "rsr.dbreaka0", ICLASS_xt_iclass_rsr_dbreaka0, + 0, + Opcode_rsr_dbreaka0_encode_fns, 0, 0 }, + { "wsr.dbreaka0", ICLASS_xt_iclass_wsr_dbreaka0, + 0, + Opcode_wsr_dbreaka0_encode_fns, 0, 0 }, + { "xsr.dbreaka0", ICLASS_xt_iclass_xsr_dbreaka0, + 0, + Opcode_xsr_dbreaka0_encode_fns, 0, 0 }, + { "rsr.dbreakc0", ICLASS_xt_iclass_rsr_dbreakc0, + 0, + Opcode_rsr_dbreakc0_encode_fns, 0, 0 }, + { "wsr.dbreakc0", ICLASS_xt_iclass_wsr_dbreakc0, + 0, + Opcode_wsr_dbreakc0_encode_fns, 0, 0 }, + { "xsr.dbreakc0", ICLASS_xt_iclass_xsr_dbreakc0, + 0, + Opcode_xsr_dbreakc0_encode_fns, 0, 0 }, + { "rsr.dbreaka1", ICLASS_xt_iclass_rsr_dbreaka1, + 0, + Opcode_rsr_dbreaka1_encode_fns, 0, 0 }, + { "wsr.dbreaka1", ICLASS_xt_iclass_wsr_dbreaka1, + 0, + Opcode_wsr_dbreaka1_encode_fns, 0, 0 }, + { "xsr.dbreaka1", ICLASS_xt_iclass_xsr_dbreaka1, + 0, + Opcode_xsr_dbreaka1_encode_fns, 0, 0 }, + { "rsr.dbreakc1", ICLASS_xt_iclass_rsr_dbreakc1, + 0, + Opcode_rsr_dbreakc1_encode_fns, 0, 0 }, + { "wsr.dbreakc1", ICLASS_xt_iclass_wsr_dbreakc1, + 0, + Opcode_wsr_dbreakc1_encode_fns, 0, 0 }, + { "xsr.dbreakc1", ICLASS_xt_iclass_xsr_dbreakc1, + 0, + Opcode_xsr_dbreakc1_encode_fns, 0, 0 }, + { "rsr.ibreaka0", ICLASS_xt_iclass_rsr_ibreaka0, + 0, + Opcode_rsr_ibreaka0_encode_fns, 0, 0 }, + { "wsr.ibreaka0", ICLASS_xt_iclass_wsr_ibreaka0, + 0, + Opcode_wsr_ibreaka0_encode_fns, 0, 0 }, + { "xsr.ibreaka0", ICLASS_xt_iclass_xsr_ibreaka0, + 0, + Opcode_xsr_ibreaka0_encode_fns, 0, 0 }, + { "rsr.ibreaka1", ICLASS_xt_iclass_rsr_ibreaka1, + 0, + Opcode_rsr_ibreaka1_encode_fns, 0, 0 }, + { "wsr.ibreaka1", ICLASS_xt_iclass_wsr_ibreaka1, + 0, + Opcode_wsr_ibreaka1_encode_fns, 0, 0 }, + { "xsr.ibreaka1", ICLASS_xt_iclass_xsr_ibreaka1, + 0, + Opcode_xsr_ibreaka1_encode_fns, 0, 0 }, + { "rsr.ibreakenable", ICLASS_xt_iclass_rsr_ibreakenable, + 0, + Opcode_rsr_ibreakenable_encode_fns, 0, 0 }, + { "wsr.ibreakenable", ICLASS_xt_iclass_wsr_ibreakenable, + 0, + Opcode_wsr_ibreakenable_encode_fns, 0, 0 }, + { "xsr.ibreakenable", ICLASS_xt_iclass_xsr_ibreakenable, + 0, + Opcode_xsr_ibreakenable_encode_fns, 0, 0 }, + { "rsr.debugcause", ICLASS_xt_iclass_rsr_debugcause, + 0, + Opcode_rsr_debugcause_encode_fns, 0, 0 }, + { "wsr.debugcause", ICLASS_xt_iclass_wsr_debugcause, + 0, + Opcode_wsr_debugcause_encode_fns, 0, 0 }, + { "xsr.debugcause", ICLASS_xt_iclass_xsr_debugcause, + 0, + Opcode_xsr_debugcause_encode_fns, 0, 0 }, + { "rsr.icount", ICLASS_xt_iclass_rsr_icount, + 0, + Opcode_rsr_icount_encode_fns, 0, 0 }, + { "wsr.icount", ICLASS_xt_iclass_wsr_icount, + 0, + Opcode_wsr_icount_encode_fns, 0, 0 }, + { "xsr.icount", ICLASS_xt_iclass_xsr_icount, + 0, + Opcode_xsr_icount_encode_fns, 0, 0 }, + { "rsr.icountlevel", ICLASS_xt_iclass_rsr_icountlevel, + 0, + Opcode_rsr_icountlevel_encode_fns, 0, 0 }, + { "wsr.icountlevel", ICLASS_xt_iclass_wsr_icountlevel, + 0, + Opcode_wsr_icountlevel_encode_fns, 0, 0 }, + { "xsr.icountlevel", ICLASS_xt_iclass_xsr_icountlevel, + 0, + Opcode_xsr_icountlevel_encode_fns, 0, 0 }, + { "rsr.ddr", ICLASS_xt_iclass_rsr_ddr, + 0, + Opcode_rsr_ddr_encode_fns, 0, 0 }, + { "wsr.ddr", ICLASS_xt_iclass_wsr_ddr, + 0, + Opcode_wsr_ddr_encode_fns, 0, 0 }, + { "xsr.ddr", ICLASS_xt_iclass_xsr_ddr, + 0, + Opcode_xsr_ddr_encode_fns, 0, 0 }, + { "lddr32.p", ICLASS_xt_iclass_lddr32_p, + 0, + Opcode_lddr32_p_encode_fns, 1, Opcode_lddr32_p_funcUnit_uses }, + { "sddr32.p", ICLASS_xt_iclass_sddr32_p, + 0, + Opcode_sddr32_p_encode_fns, 1, Opcode_sddr32_p_funcUnit_uses }, + { "rfdo", ICLASS_xt_iclass_rfdo, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfdo_encode_fns, 0, 0 }, + { "rfdd", ICLASS_xt_iclass_rfdd, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfdd_encode_fns, 0, 0 }, + { "wsr.mmid", ICLASS_xt_iclass_wsr_mmid, + 0, + Opcode_wsr_mmid_encode_fns, 0, 0 }, + { "andb", ICLASS_xt_iclass_bbool1, + 0, + Opcode_andb_encode_fns, 0, 0 }, + { "andbc", ICLASS_xt_iclass_bbool1, + 0, + Opcode_andbc_encode_fns, 0, 0 }, + { "orb", ICLASS_xt_iclass_bbool1, + 0, + Opcode_orb_encode_fns, 0, 0 }, + { "orbc", ICLASS_xt_iclass_bbool1, + 0, + Opcode_orbc_encode_fns, 0, 0 }, + { "xorb", ICLASS_xt_iclass_bbool1, + 0, + Opcode_xorb_encode_fns, 0, 0 }, + { "all4", ICLASS_xt_iclass_bbool4, + 0, + Opcode_all4_encode_fns, 0, 0 }, + { "any4", ICLASS_xt_iclass_bbool4, + 0, + Opcode_any4_encode_fns, 0, 0 }, + { "all8", ICLASS_xt_iclass_bbool8, + 0, + Opcode_all8_encode_fns, 0, 0 }, + { "any8", ICLASS_xt_iclass_bbool8, + 0, + Opcode_any8_encode_fns, 0, 0 }, + { "bf", ICLASS_xt_iclass_bbranch, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bf_encode_fns, 0, 0 }, + { "bt", ICLASS_xt_iclass_bbranch, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bt_encode_fns, 0, 0 }, + { "movf", ICLASS_xt_iclass_bmove, + 0, + Opcode_movf_encode_fns, 0, 0 }, + { "movt", ICLASS_xt_iclass_bmove, + 0, + Opcode_movt_encode_fns, 0, 0 }, + { "rsr.br", ICLASS_xt_iclass_RSR_BR, + 0, + Opcode_rsr_br_encode_fns, 0, 0 }, + { "wsr.br", ICLASS_xt_iclass_WSR_BR, + 0, + Opcode_wsr_br_encode_fns, 0, 0 }, + { "xsr.br", ICLASS_xt_iclass_XSR_BR, + 0, + Opcode_xsr_br_encode_fns, 0, 0 }, + { "rsr.ccount", ICLASS_xt_iclass_rsr_ccount, + 0, + Opcode_rsr_ccount_encode_fns, 0, 0 }, + { "wsr.ccount", ICLASS_xt_iclass_wsr_ccount, + 0, + Opcode_wsr_ccount_encode_fns, 0, 0 }, + { "xsr.ccount", ICLASS_xt_iclass_xsr_ccount, + 0, + Opcode_xsr_ccount_encode_fns, 0, 0 }, + { "rsr.ccompare0", ICLASS_xt_iclass_rsr_ccompare0, + 0, + Opcode_rsr_ccompare0_encode_fns, 0, 0 }, + { "wsr.ccompare0", ICLASS_xt_iclass_wsr_ccompare0, + 0, + Opcode_wsr_ccompare0_encode_fns, 0, 0 }, + { "xsr.ccompare0", ICLASS_xt_iclass_xsr_ccompare0, + 0, + Opcode_xsr_ccompare0_encode_fns, 0, 0 }, + { "rsr.ccompare1", ICLASS_xt_iclass_rsr_ccompare1, + 0, + Opcode_rsr_ccompare1_encode_fns, 0, 0 }, + { "wsr.ccompare1", ICLASS_xt_iclass_wsr_ccompare1, + 0, + Opcode_wsr_ccompare1_encode_fns, 0, 0 }, + { "xsr.ccompare1", ICLASS_xt_iclass_xsr_ccompare1, + 0, + Opcode_xsr_ccompare1_encode_fns, 0, 0 }, + { "rsr.ccompare2", ICLASS_xt_iclass_rsr_ccompare2, + 0, + Opcode_rsr_ccompare2_encode_fns, 0, 0 }, + { "wsr.ccompare2", ICLASS_xt_iclass_wsr_ccompare2, + 0, + Opcode_wsr_ccompare2_encode_fns, 0, 0 }, + { "xsr.ccompare2", ICLASS_xt_iclass_xsr_ccompare2, + 0, + Opcode_xsr_ccompare2_encode_fns, 0, 0 }, + { "ihi", ICLASS_xt_iclass_icache, + 0, + Opcode_ihi_encode_fns, 0, 0 }, + { "ipf", ICLASS_xt_iclass_icache, + 0, + Opcode_ipf_encode_fns, 0, 0 }, + { "ihu", ICLASS_xt_iclass_icache_lock, + 0, + Opcode_ihu_encode_fns, 0, 0 }, + { "iiu", ICLASS_xt_iclass_icache_lock, + 0, + Opcode_iiu_encode_fns, 0, 0 }, + { "ipfl", ICLASS_xt_iclass_icache_lock, + 0, + Opcode_ipfl_encode_fns, 0, 0 }, + { "iii", ICLASS_xt_iclass_icache_inv, + 0, + Opcode_iii_encode_fns, 0, 0 }, + { "lict", ICLASS_xt_iclass_licx, + 0, + Opcode_lict_encode_fns, 1, Opcode_lict_funcUnit_uses }, + { "licw", ICLASS_xt_iclass_licx, + 0, + Opcode_licw_encode_fns, 1, Opcode_licw_funcUnit_uses }, + { "sict", ICLASS_xt_iclass_sicx, + 0, + Opcode_sict_encode_fns, 1, Opcode_sict_funcUnit_uses }, + { "sicw", ICLASS_xt_iclass_sicx, + 0, + Opcode_sicw_encode_fns, 1, Opcode_sicw_funcUnit_uses }, + { "dhwb", ICLASS_xt_iclass_dcache, + 0, + Opcode_dhwb_encode_fns, 0, 0 }, + { "dhwbi", ICLASS_xt_iclass_dcache, + 0, + Opcode_dhwbi_encode_fns, 0, 0 }, + { "diwbui.p", ICLASS_xt_iclass_dcache_dyn, + 0, + Opcode_diwbui_p_encode_fns, 0, 0 }, + { "diwb", ICLASS_xt_iclass_dcache_ind, + 0, + Opcode_diwb_encode_fns, 0, 0 }, + { "diwbi", ICLASS_xt_iclass_dcache_ind, + 0, + Opcode_diwbi_encode_fns, 0, 0 }, + { "dhi", ICLASS_xt_iclass_dcache_inv, + 0, + Opcode_dhi_encode_fns, 0, 0 }, + { "dii", ICLASS_xt_iclass_dcache_inv, + 0, + Opcode_dii_encode_fns, 0, 0 }, + { "dpfr", ICLASS_xt_iclass_dpf, + 0, + Opcode_dpfr_encode_fns, 0, 0 }, + { "dpfro", ICLASS_xt_iclass_dpf, + 0, + Opcode_dpfro_encode_fns, 0, 0 }, + { "dpfw", ICLASS_xt_iclass_dpf, + 0, + Opcode_dpfw_encode_fns, 0, 0 }, + { "dpfwo", ICLASS_xt_iclass_dpf, + 0, + Opcode_dpfwo_encode_fns, 0, 0 }, + { "dhu", ICLASS_xt_iclass_dcache_lock, + 0, + Opcode_dhu_encode_fns, 0, 0 }, + { "diu", ICLASS_xt_iclass_dcache_lock, + 0, + Opcode_diu_encode_fns, 0, 0 }, + { "dpfl", ICLASS_xt_iclass_dcache_lock, + 0, + Opcode_dpfl_encode_fns, 0, 0 }, + { "sdct", ICLASS_xt_iclass_sdct, + 0, + Opcode_sdct_encode_fns, 1, Opcode_sdct_funcUnit_uses }, + { "ldct", ICLASS_xt_iclass_ldct, + 0, + Opcode_ldct_encode_fns, 1, Opcode_ldct_funcUnit_uses }, + { "sdcw", ICLASS_xt_iclass_sdcw, + 0, + Opcode_sdcw_encode_fns, 1, Opcode_sdcw_funcUnit_uses }, + { "ldcw", ICLASS_xt_iclass_ldcw, + 0, + Opcode_ldcw_encode_fns, 1, Opcode_ldcw_funcUnit_uses }, + { "wsr.ptevaddr", ICLASS_xt_iclass_wsr_ptevaddr, + 0, + Opcode_wsr_ptevaddr_encode_fns, 0, 0 }, + { "rsr.ptevaddr", ICLASS_xt_iclass_rsr_ptevaddr, + 0, + Opcode_rsr_ptevaddr_encode_fns, 0, 0 }, + { "xsr.ptevaddr", ICLASS_xt_iclass_xsr_ptevaddr, + 0, + Opcode_xsr_ptevaddr_encode_fns, 0, 0 }, + { "rsr.rasid", ICLASS_xt_iclass_rsr_rasid, + 0, + Opcode_rsr_rasid_encode_fns, 0, 0 }, + { "wsr.rasid", ICLASS_xt_iclass_wsr_rasid, + 0, + Opcode_wsr_rasid_encode_fns, 0, 0 }, + { "xsr.rasid", ICLASS_xt_iclass_xsr_rasid, + 0, + Opcode_xsr_rasid_encode_fns, 0, 0 }, + { "rsr.itlbcfg", ICLASS_xt_iclass_rsr_itlbcfg, + 0, + Opcode_rsr_itlbcfg_encode_fns, 0, 0 }, + { "wsr.itlbcfg", ICLASS_xt_iclass_wsr_itlbcfg, + 0, + Opcode_wsr_itlbcfg_encode_fns, 0, 0 }, + { "xsr.itlbcfg", ICLASS_xt_iclass_xsr_itlbcfg, + 0, + Opcode_xsr_itlbcfg_encode_fns, 0, 0 }, + { "rsr.dtlbcfg", ICLASS_xt_iclass_rsr_dtlbcfg, + 0, + Opcode_rsr_dtlbcfg_encode_fns, 0, 0 }, + { "wsr.dtlbcfg", ICLASS_xt_iclass_wsr_dtlbcfg, + 0, + Opcode_wsr_dtlbcfg_encode_fns, 0, 0 }, + { "xsr.dtlbcfg", ICLASS_xt_iclass_xsr_dtlbcfg, + 0, + Opcode_xsr_dtlbcfg_encode_fns, 0, 0 }, + { "idtlb", ICLASS_xt_iclass_idtlb, + 0, + Opcode_idtlb_encode_fns, 0, 0 }, + { "pdtlb", ICLASS_xt_iclass_rdtlb, + 0, + Opcode_pdtlb_encode_fns, 0, 0 }, + { "rdtlb0", ICLASS_xt_iclass_rdtlb, + 0, + Opcode_rdtlb0_encode_fns, 0, 0 }, + { "rdtlb1", ICLASS_xt_iclass_rdtlb, + 0, + Opcode_rdtlb1_encode_fns, 0, 0 }, + { "wdtlb", ICLASS_xt_iclass_wdtlb, + 0, + Opcode_wdtlb_encode_fns, 0, 0 }, + { "iitlb", ICLASS_xt_iclass_iitlb, + 0, + Opcode_iitlb_encode_fns, 0, 0 }, + { "pitlb", ICLASS_xt_iclass_ritlb, + 0, + Opcode_pitlb_encode_fns, 0, 0 }, + { "ritlb0", ICLASS_xt_iclass_ritlb, + 0, + Opcode_ritlb0_encode_fns, 0, 0 }, + { "ritlb1", ICLASS_xt_iclass_ritlb, + 0, + Opcode_ritlb1_encode_fns, 0, 0 }, + { "witlb", ICLASS_xt_iclass_witlb, + 0, + Opcode_witlb_encode_fns, 0, 0 }, + { "ldpte", ICLASS_xt_iclass_ldpte, + 0, + Opcode_ldpte_encode_fns, 1, Opcode_ldpte_funcUnit_uses }, + { "hwwitlba", ICLASS_xt_iclass_hwwitlba, + XTENSA_OPCODE_IS_BRANCH, + Opcode_hwwitlba_encode_fns, 0, 0 }, + { "hwwdtlba", ICLASS_xt_iclass_hwwdtlba, + 0, + Opcode_hwwdtlba_encode_fns, 0, 0 }, + { "rsr.cpenable", ICLASS_xt_iclass_rsr_cpenable, + 0, + Opcode_rsr_cpenable_encode_fns, 0, 0 }, + { "wsr.cpenable", ICLASS_xt_iclass_wsr_cpenable, + 0, + Opcode_wsr_cpenable_encode_fns, 0, 0 }, + { "xsr.cpenable", ICLASS_xt_iclass_xsr_cpenable, + 0, + Opcode_xsr_cpenable_encode_fns, 0, 0 }, + { "clamps", ICLASS_xt_iclass_clamp, + 0, + Opcode_clamps_encode_fns, 0, 0 }, + { "max", ICLASS_xt_iclass_minmax, + 0, + Opcode_max_encode_fns, 0, 0 }, + { "maxu", ICLASS_xt_iclass_minmax, + 0, + Opcode_maxu_encode_fns, 0, 0 }, + { "min", ICLASS_xt_iclass_minmax, + 0, + Opcode_min_encode_fns, 0, 0 }, + { "minu", ICLASS_xt_iclass_minmax, + 0, + Opcode_minu_encode_fns, 0, 0 }, + { "nsa", ICLASS_xt_iclass_nsa, + 0, + Opcode_nsa_encode_fns, 0, 0 }, + { "nsau", ICLASS_xt_iclass_nsa, + 0, + Opcode_nsau_encode_fns, 0, 0 }, + { "sext", ICLASS_xt_iclass_sx, + 0, + Opcode_sext_encode_fns, 0, 0 }, + { "l32ai", ICLASS_xt_iclass_l32ai, + 0, + Opcode_l32ai_encode_fns, 1, Opcode_l32ai_funcUnit_uses }, + { "s32ri", ICLASS_xt_iclass_s32ri, + 0, + Opcode_s32ri_encode_fns, 1, Opcode_s32ri_funcUnit_uses }, + { "s32c1i", ICLASS_xt_iclass_s32c1i, + 0, + Opcode_s32c1i_encode_fns, 1, Opcode_s32c1i_funcUnit_uses }, + { "rsr.scompare1", ICLASS_xt_iclass_rsr_scompare1, + 0, + Opcode_rsr_scompare1_encode_fns, 0, 0 }, + { "wsr.scompare1", ICLASS_xt_iclass_wsr_scompare1, + 0, + Opcode_wsr_scompare1_encode_fns, 0, 0 }, + { "xsr.scompare1", ICLASS_xt_iclass_xsr_scompare1, + 0, + Opcode_xsr_scompare1_encode_fns, 0, 0 }, + { "rsr.atomctl", ICLASS_xt_iclass_rsr_atomctl, + 0, + Opcode_rsr_atomctl_encode_fns, 0, 0 }, + { "wsr.atomctl", ICLASS_xt_iclass_wsr_atomctl, + 0, + Opcode_wsr_atomctl_encode_fns, 0, 0 }, + { "xsr.atomctl", ICLASS_xt_iclass_xsr_atomctl, + 0, + Opcode_xsr_atomctl_encode_fns, 0, 0 }, + { "quos", ICLASS_xt_iclass_div, + 0, + Opcode_quos_encode_fns, 0, 0 }, + { "quou", ICLASS_xt_iclass_div, + 0, + Opcode_quou_encode_fns, 0, 0 }, + { "rems", ICLASS_xt_iclass_div, + 0, + Opcode_rems_encode_fns, 0, 0 }, + { "remu", ICLASS_xt_iclass_div, + 0, + Opcode_remu_encode_fns, 0, 0 }, + { "rsr.eraccess", ICLASS_xt_iclass_rsr_eraccess, + 0, + Opcode_rsr_eraccess_encode_fns, 0, 0 }, + { "wsr.eraccess", ICLASS_xt_iclass_wsr_eraccess, + 0, + Opcode_wsr_eraccess_encode_fns, 0, 0 }, + { "xsr.eraccess", ICLASS_xt_iclass_xsr_eraccess, + 0, + Opcode_xsr_eraccess_encode_fns, 0, 0 }, + { "rer", ICLASS_xt_iclass_rer, + 0, + Opcode_rer_encode_fns, 0, 0 }, + { "wer", ICLASS_xt_iclass_wer, + 0, + Opcode_wer_encode_fns, 0, 0 }, + { "rur.fcr", ICLASS_rur_fcr, + 0, + Opcode_rur_fcr_encode_fns, 0, 0 }, + { "wur.fcr", ICLASS_wur_fcr, + 0, + Opcode_wur_fcr_encode_fns, 0, 0 }, + { "rur.fsr", ICLASS_rur_fsr, + 0, + Opcode_rur_fsr_encode_fns, 0, 0 }, + { "wur.fsr", ICLASS_wur_fsr, + 0, + Opcode_wur_fsr_encode_fns, 0, 0 }, + { "read_impwire", ICLASS_iclass_READ_IMPWIRE, + 0, + Opcode_read_impwire_encode_fns, 0, 0 }, + { "setb_expstate", ICLASS_iclass_SETB_EXPSTATE, + 0, + Opcode_setb_expstate_encode_fns, 0, 0 }, + { "clrb_expstate", ICLASS_iclass_CLRB_EXPSTATE, + 0, + Opcode_clrb_expstate_encode_fns, 0, 0 }, + { "wrmsk_expstate", ICLASS_iclass_WRMSK_EXPSTATE, + 0, + Opcode_wrmsk_expstate_encode_fns, 0, 0 }, + { "rur.expstate", ICLASS_rur_expstate, + 0, + Opcode_rur_expstate_encode_fns, 0, 0 }, + { "wur.expstate", ICLASS_wur_expstate, + 0, + Opcode_wur_expstate_encode_fns, 0, 0 }, + { "lsi", ICLASS_LSI, + 0, + Opcode_lsi_encode_fns, 1, Opcode_lsi_funcUnit_uses }, + { "lsip", ICLASS_LSIP, + 0, + Opcode_lsip_encode_fns, 1, Opcode_lsip_funcUnit_uses }, + { "lsx", ICLASS_LSX, + 0, + Opcode_lsx_encode_fns, 1, Opcode_lsx_funcUnit_uses }, + { "lsxp", ICLASS_LSXP, + 0, + Opcode_lsxp_encode_fns, 1, Opcode_lsxp_funcUnit_uses }, + { "ssi", ICLASS_SSI, + 0, + Opcode_ssi_encode_fns, 1, Opcode_ssi_funcUnit_uses }, + { "ssip", ICLASS_SSIP, + 0, + Opcode_ssip_encode_fns, 1, Opcode_ssip_funcUnit_uses }, + { "ssx", ICLASS_SSX, + 0, + Opcode_ssx_encode_fns, 1, Opcode_ssx_funcUnit_uses }, + { "ssxp", ICLASS_SSXP, + 0, + Opcode_ssxp_encode_fns, 1, Opcode_ssxp_funcUnit_uses }, + { "ldi", ICLASS_LDI, + 0, + Opcode_ldi_encode_fns, 1, Opcode_ldi_funcUnit_uses }, + { "ldip", ICLASS_LDIP, + 0, + Opcode_ldip_encode_fns, 1, Opcode_ldip_funcUnit_uses }, + { "ldx", ICLASS_LDX, + 0, + Opcode_ldx_encode_fns, 1, Opcode_ldx_funcUnit_uses }, + { "ldxp", ICLASS_LDXP, + 0, + Opcode_ldxp_encode_fns, 1, Opcode_ldxp_funcUnit_uses }, + { "sdi", ICLASS_SDI, + 0, + Opcode_sdi_encode_fns, 1, Opcode_sdi_funcUnit_uses }, + { "sdip", ICLASS_SDIP, + 0, + Opcode_sdip_encode_fns, 1, Opcode_sdip_funcUnit_uses }, + { "sdx", ICLASS_SDX, + 0, + Opcode_sdx_encode_fns, 1, Opcode_sdx_funcUnit_uses }, + { "sdxp", ICLASS_SDXP, + 0, + Opcode_sdxp_encode_fns, 1, Opcode_sdxp_funcUnit_uses }, + { "abs.s", ICLASS_ABS_S, + 0, + Opcode_abs_s_encode_fns, 0, 0 }, + { "neg.s", ICLASS_NEG_S, + 0, + Opcode_neg_s_encode_fns, 0, 0 }, + { "abs.d", ICLASS_ABS_D, + 0, + Opcode_abs_d_encode_fns, 0, 0 }, + { "neg.d", ICLASS_NEG_D, + 0, + Opcode_neg_d_encode_fns, 0, 0 }, + { "mov.s", ICLASS_MOV_S, + 0, + Opcode_mov_s_encode_fns, 0, 0 }, + { "mov.d", ICLASS_MOV_D, + 0, + Opcode_mov_d_encode_fns, 0, 0 }, + { "moveqz.s", ICLASS_MOVEQZ_S, + 0, + Opcode_moveqz_s_encode_fns, 0, 0 }, + { "movnez.s", ICLASS_MOVNEZ_S, + 0, + Opcode_movnez_s_encode_fns, 0, 0 }, + { "movltz.s", ICLASS_MOVLTZ_S, + 0, + Opcode_movltz_s_encode_fns, 0, 0 }, + { "movgez.s", ICLASS_MOVGEZ_S, + 0, + Opcode_movgez_s_encode_fns, 0, 0 }, + { "movf.s", ICLASS_MOVF_S, + 0, + Opcode_movf_s_encode_fns, 0, 0 }, + { "movt.s", ICLASS_MOVT_S, + 0, + Opcode_movt_s_encode_fns, 0, 0 }, + { "wfr", ICLASS_WFR, + 0, + Opcode_wfr_encode_fns, 0, 0 }, + { "rfr", ICLASS_RFR, + 0, + Opcode_rfr_encode_fns, 0, 0 }, + { "rfrd", ICLASS_RFRD, + 0, + Opcode_rfrd_encode_fns, 0, 0 }, + { "wfrd", ICLASS_WFRD, + 0, + Opcode_wfrd_encode_fns, 0, 0 }, + { "round.s", ICLASS_ROUND_S, + 0, + Opcode_round_s_encode_fns, 0, 0 }, + { "round.d", ICLASS_ROUND_D, + 0, + Opcode_round_d_encode_fns, 0, 0 }, + { "ceil.s", ICLASS_CEIL_S, + 0, + Opcode_ceil_s_encode_fns, 0, 0 }, + { "ceil.d", ICLASS_CEIL_D, + 0, + Opcode_ceil_d_encode_fns, 0, 0 }, + { "floor.s", ICLASS_FLOOR_S, + 0, + Opcode_floor_s_encode_fns, 0, 0 }, + { "floor.d", ICLASS_FLOOR_D, + 0, + Opcode_floor_d_encode_fns, 0, 0 }, + { "trunc.s", ICLASS_TRUNC_S, + 0, + Opcode_trunc_s_encode_fns, 0, 0 }, + { "trunc.d", ICLASS_TRUNC_D, + 0, + Opcode_trunc_d_encode_fns, 0, 0 }, + { "utrunc.s", ICLASS_UTRUNC_S, + 0, + Opcode_utrunc_s_encode_fns, 0, 0 }, + { "utrunc.d", ICLASS_UTRUNC_D, + 0, + Opcode_utrunc_d_encode_fns, 0, 0 }, + { "float.s", ICLASS_FLOAT_S, + 0, + Opcode_float_s_encode_fns, 0, 0 }, + { "float.d", ICLASS_FLOAT_D, + 0, + Opcode_float_d_encode_fns, 0, 0 }, + { "ufloat.s", ICLASS_UFLOAT_S, + 0, + Opcode_ufloat_s_encode_fns, 0, 0 }, + { "ufloat.d", ICLASS_UFLOAT_D, + 0, + Opcode_ufloat_d_encode_fns, 0, 0 }, + { "cvtd.s", ICLASS_CVTD_S, + 0, + Opcode_cvtd_s_encode_fns, 0, 0 }, + { "cvts.d", ICLASS_CVTS_D, + 0, + Opcode_cvts_d_encode_fns, 0, 0 }, + { "un.s", ICLASS_UN_S, + 0, + Opcode_un_s_encode_fns, 0, 0 }, + { "un.d", ICLASS_UN_D, + 0, + Opcode_un_d_encode_fns, 0, 0 }, + { "ult.s", ICLASS_ULT_S, + 0, + Opcode_ult_s_encode_fns, 0, 0 }, + { "ult.d", ICLASS_ULT_D, + 0, + Opcode_ult_d_encode_fns, 0, 0 }, + { "ule.s", ICLASS_ULE_S, + 0, + Opcode_ule_s_encode_fns, 0, 0 }, + { "ule.d", ICLASS_ULE_D, + 0, + Opcode_ule_d_encode_fns, 0, 0 }, + { "ueq.s", ICLASS_UEQ_S, + 0, + Opcode_ueq_s_encode_fns, 0, 0 }, + { "ueq.d", ICLASS_UEQ_D, + 0, + Opcode_ueq_d_encode_fns, 0, 0 }, + { "olt.s", ICLASS_OLT_S, + 0, + Opcode_olt_s_encode_fns, 0, 0 }, + { "olt.d", ICLASS_OLT_D, + 0, + Opcode_olt_d_encode_fns, 0, 0 }, + { "ole.s", ICLASS_OLE_S, + 0, + Opcode_ole_s_encode_fns, 0, 0 }, + { "ole.d", ICLASS_OLE_D, + 0, + Opcode_ole_d_encode_fns, 0, 0 }, + { "oeq.s", ICLASS_OEQ_S, + 0, + Opcode_oeq_s_encode_fns, 0, 0 }, + { "oeq.d", ICLASS_OEQ_D, + 0, + Opcode_oeq_d_encode_fns, 0, 0 }, + { "add.s", ICLASS_ADD_S, + 0, + Opcode_add_s_encode_fns, 0, 0 }, + { "add.d", ICLASS_ADD_D, + 0, + Opcode_add_d_encode_fns, 0, 0 }, + { "sub.s", ICLASS_SUB_S, + 0, + Opcode_sub_s_encode_fns, 0, 0 }, + { "sub.d", ICLASS_SUB_D, + 0, + Opcode_sub_d_encode_fns, 0, 0 }, + { "mul.s", ICLASS_MUL_S, + 0, + Opcode_mul_s_encode_fns, 0, 0 }, + { "mul.d", ICLASS_MUL_D, + 0, + Opcode_mul_d_encode_fns, 0, 0 }, + { "madd.s", ICLASS_MADD_S, + 0, + Opcode_madd_s_encode_fns, 0, 0 }, + { "madd.d", ICLASS_MADD_D, + 0, + Opcode_madd_d_encode_fns, 0, 0 }, + { "msub.s", ICLASS_MSUB_S, + 0, + Opcode_msub_s_encode_fns, 0, 0 }, + { "msub.d", ICLASS_MSUB_D, + 0, + Opcode_msub_d_encode_fns, 0, 0 }, + { "sqrt0.s", ICLASS_SQRT0_S, + 0, + Opcode_sqrt0_s_encode_fns, 0, 0 }, + { "sqrt0.d", ICLASS_SQRT0_D, + 0, + Opcode_sqrt0_d_encode_fns, 0, 0 }, + { "div0.s", ICLASS_DIV0_S, + 0, + Opcode_div0_s_encode_fns, 0, 0 }, + { "div0.d", ICLASS_DIV0_D, + 0, + Opcode_div0_d_encode_fns, 0, 0 }, + { "recip0.s", ICLASS_RECIP0_S, + 0, + Opcode_recip0_s_encode_fns, 0, 0 }, + { "recip0.d", ICLASS_RECIP0_D, + 0, + Opcode_recip0_d_encode_fns, 0, 0 }, + { "rsqrt0.s", ICLASS_RSQRT0_S, + 0, + Opcode_rsqrt0_s_encode_fns, 0, 0 }, + { "rsqrt0.d", ICLASS_RSQRT0_D, + 0, + Opcode_rsqrt0_d_encode_fns, 0, 0 }, + { "maddn.s", ICLASS_MADDN_S, + 0, + Opcode_maddn_s_encode_fns, 0, 0 }, + { "maddn.d", ICLASS_MADDN_D, + 0, + Opcode_maddn_d_encode_fns, 0, 0 }, + { "divn.s", ICLASS_DIVN_S, + 0, + Opcode_divn_s_encode_fns, 0, 0 }, + { "divn.d", ICLASS_DIVN_D, + 0, + Opcode_divn_d_encode_fns, 0, 0 }, + { "const.s", ICLASS_CONST_S, + 0, + Opcode_const_s_encode_fns, 0, 0 }, + { "const.d", ICLASS_CONST_D, + 0, + Opcode_const_d_encode_fns, 0, 0 }, + { "nexp01.s", ICLASS_NEXP01_S, + 0, + Opcode_nexp01_s_encode_fns, 0, 0 }, + { "nexp01.d", ICLASS_NEXP01_D, + 0, + Opcode_nexp01_d_encode_fns, 0, 0 }, + { "addexp.s", ICLASS_ADDEXP_S, + 0, + Opcode_addexp_s_encode_fns, 0, 0 }, + { "addexp.d", ICLASS_ADDEXP_D, + 0, + Opcode_addexp_d_encode_fns, 0, 0 }, + { "addexpm.s", ICLASS_ADDEXPM_S, + 0, + Opcode_addexpm_s_encode_fns, 0, 0 }, + { "addexpm.d", ICLASS_ADDEXPM_D, + 0, + Opcode_addexpm_d_encode_fns, 0, 0 }, + { "mkdadj.s", ICLASS_MKDADJ_S, + 0, + Opcode_mkdadj_s_encode_fns, 0, 0 }, + { "mkdadj.d", ICLASS_MKDADJ_D, + 0, + Opcode_mkdadj_d_encode_fns, 0, 0 }, + { "mksadj.s", ICLASS_MKSADJ_S, + 0, + Opcode_mksadj_s_encode_fns, 0, 0 }, + { "mksadj.d", ICLASS_MKSADJ_D, + 0, + Opcode_mksadj_d_encode_fns, 0, 0 } +}; + +enum xtensa_opcode_id { + OPCODE_EXCW, + OPCODE_RFE, + OPCODE_RFDE, + OPCODE_SYSCALL, + OPCODE_CALL12, + OPCODE_CALL8, + OPCODE_CALL4, + OPCODE_CALLX12, + OPCODE_CALLX8, + OPCODE_CALLX4, + OPCODE_ENTRY, + OPCODE_MOVSP, + OPCODE_ROTW, + OPCODE_RETW, + OPCODE_RETW_N, + OPCODE_RFWO, + OPCODE_RFWU, + OPCODE_L32E, + OPCODE_S32E, + OPCODE_RSR_WINDOWBASE, + OPCODE_WSR_WINDOWBASE, + OPCODE_XSR_WINDOWBASE, + OPCODE_RSR_WINDOWSTART, + OPCODE_WSR_WINDOWSTART, + OPCODE_XSR_WINDOWSTART, + OPCODE_ADD_N, + OPCODE_ADDI_N, + OPCODE_BEQZ_N, + OPCODE_BNEZ_N, + OPCODE_ILL_N, + OPCODE_L32I_N, + OPCODE_MOV_N, + OPCODE_MOVI_N, + OPCODE_NOP_N, + OPCODE_RET_N, + OPCODE_S32I_N, + OPCODE_RUR_THREADPTR, + OPCODE_WUR_THREADPTR, + OPCODE_ADDI, + OPCODE_ADDMI, + OPCODE_ADD, + OPCODE_ADDX2, + OPCODE_ADDX4, + OPCODE_ADDX8, + OPCODE_SUB, + OPCODE_SUBX2, + OPCODE_SUBX4, + OPCODE_SUBX8, + OPCODE_AND, + OPCODE_OR, + OPCODE_XOR, + OPCODE_BEQI, + OPCODE_BGEI, + OPCODE_BLTI, + OPCODE_BNEI, + OPCODE_BBCI, + OPCODE_BBSI, + OPCODE_BGEUI, + OPCODE_BLTUI, + OPCODE_BALL, + OPCODE_BANY, + OPCODE_BBC, + OPCODE_BBS, + OPCODE_BEQ, + OPCODE_BGE, + OPCODE_BGEU, + OPCODE_BLT, + OPCODE_BLTU, + OPCODE_BNALL, + OPCODE_BNE, + OPCODE_BNONE, + OPCODE_BEQZ, + OPCODE_BGEZ, + OPCODE_BLTZ, + OPCODE_BNEZ, + OPCODE_CALL0, + OPCODE_CALLX0, + OPCODE_EXTUI, + OPCODE_ILL, + OPCODE_J, + OPCODE_JX, + OPCODE_L16UI, + OPCODE_L16SI, + OPCODE_L32I, + OPCODE_L32R, + OPCODE_L8UI, + OPCODE_LOOP, + OPCODE_LOOPGTZ, + OPCODE_LOOPNEZ, + OPCODE_MOVI, + OPCODE_MOVEQZ, + OPCODE_MOVGEZ, + OPCODE_MOVLTZ, + OPCODE_MOVNEZ, + OPCODE_ABS, + OPCODE_NEG, + OPCODE_NOP, + OPCODE_RET, + OPCODE_SIMCALL, + OPCODE_S16I, + OPCODE_S32I, + OPCODE_S32NB, + OPCODE_S8I, + OPCODE_SSA8B, + OPCODE_SSA8L, + OPCODE_SSL, + OPCODE_SSR, + OPCODE_SSAI, + OPCODE_SLL, + OPCODE_SRC, + OPCODE_SRA, + OPCODE_SRL, + OPCODE_SLLI, + OPCODE_SRAI, + OPCODE_SRLI, + OPCODE_MEMW, + OPCODE_EXTW, + OPCODE_ISYNC, + OPCODE_DSYNC, + OPCODE_ESYNC, + OPCODE_RSYNC, + OPCODE_RSIL, + OPCODE_RSR_LEND, + OPCODE_WSR_LEND, + OPCODE_XSR_LEND, + OPCODE_RSR_LCOUNT, + OPCODE_WSR_LCOUNT, + OPCODE_XSR_LCOUNT, + OPCODE_RSR_LBEG, + OPCODE_WSR_LBEG, + OPCODE_XSR_LBEG, + OPCODE_RSR_SAR, + OPCODE_WSR_SAR, + OPCODE_XSR_SAR, + OPCODE_RSR_MEMCTL, + OPCODE_WSR_MEMCTL, + OPCODE_XSR_MEMCTL, + OPCODE_RSR_CONFIGID0, + OPCODE_WSR_CONFIGID0, + OPCODE_RSR_CONFIGID1, + OPCODE_RSR_PS, + OPCODE_WSR_PS, + OPCODE_XSR_PS, + OPCODE_RSR_EPC1, + OPCODE_WSR_EPC1, + OPCODE_XSR_EPC1, + OPCODE_RSR_EXCSAVE1, + OPCODE_WSR_EXCSAVE1, + OPCODE_XSR_EXCSAVE1, + OPCODE_RSR_EPC2, + OPCODE_WSR_EPC2, + OPCODE_XSR_EPC2, + OPCODE_RSR_EXCSAVE2, + OPCODE_WSR_EXCSAVE2, + OPCODE_XSR_EXCSAVE2, + OPCODE_RSR_EPC3, + OPCODE_WSR_EPC3, + OPCODE_XSR_EPC3, + OPCODE_RSR_EXCSAVE3, + OPCODE_WSR_EXCSAVE3, + OPCODE_XSR_EXCSAVE3, + OPCODE_RSR_EPC4, + OPCODE_WSR_EPC4, + OPCODE_XSR_EPC4, + OPCODE_RSR_EXCSAVE4, + OPCODE_WSR_EXCSAVE4, + OPCODE_XSR_EXCSAVE4, + OPCODE_RSR_EPC5, + OPCODE_WSR_EPC5, + OPCODE_XSR_EPC5, + OPCODE_RSR_EXCSAVE5, + OPCODE_WSR_EXCSAVE5, + OPCODE_XSR_EXCSAVE5, + OPCODE_RSR_EPC6, + OPCODE_WSR_EPC6, + OPCODE_XSR_EPC6, + OPCODE_RSR_EXCSAVE6, + OPCODE_WSR_EXCSAVE6, + OPCODE_XSR_EXCSAVE6, + OPCODE_RSR_EPC7, + OPCODE_WSR_EPC7, + OPCODE_XSR_EPC7, + OPCODE_RSR_EXCSAVE7, + OPCODE_WSR_EXCSAVE7, + OPCODE_XSR_EXCSAVE7, + OPCODE_RSR_EPS2, + OPCODE_WSR_EPS2, + OPCODE_XSR_EPS2, + OPCODE_RSR_EPS3, + OPCODE_WSR_EPS3, + OPCODE_XSR_EPS3, + OPCODE_RSR_EPS4, + OPCODE_WSR_EPS4, + OPCODE_XSR_EPS4, + OPCODE_RSR_EPS5, + OPCODE_WSR_EPS5, + OPCODE_XSR_EPS5, + OPCODE_RSR_EPS6, + OPCODE_WSR_EPS6, + OPCODE_XSR_EPS6, + OPCODE_RSR_EPS7, + OPCODE_WSR_EPS7, + OPCODE_XSR_EPS7, + OPCODE_RSR_EXCVADDR, + OPCODE_WSR_EXCVADDR, + OPCODE_XSR_EXCVADDR, + OPCODE_RSR_DEPC, + OPCODE_WSR_DEPC, + OPCODE_XSR_DEPC, + OPCODE_RSR_EXCCAUSE, + OPCODE_WSR_EXCCAUSE, + OPCODE_XSR_EXCCAUSE, + OPCODE_RSR_MISC0, + OPCODE_WSR_MISC0, + OPCODE_XSR_MISC0, + OPCODE_RSR_MISC1, + OPCODE_WSR_MISC1, + OPCODE_XSR_MISC1, + OPCODE_RSR_PRID, + OPCODE_RSR_VECBASE, + OPCODE_WSR_VECBASE, + OPCODE_XSR_VECBASE, + OPCODE_SALT, + OPCODE_SALTU, + OPCODE_MUL16S, + OPCODE_MUL16U, + OPCODE_MULL, + OPCODE_MUL_AA_HH, + OPCODE_MUL_AA_HL, + OPCODE_MUL_AA_LH, + OPCODE_MUL_AA_LL, + OPCODE_UMUL_AA_HH, + OPCODE_UMUL_AA_HL, + OPCODE_UMUL_AA_LH, + OPCODE_UMUL_AA_LL, + OPCODE_MUL_AD_HH, + OPCODE_MUL_AD_HL, + OPCODE_MUL_AD_LH, + OPCODE_MUL_AD_LL, + OPCODE_MUL_DA_HH, + OPCODE_MUL_DA_HL, + OPCODE_MUL_DA_LH, + OPCODE_MUL_DA_LL, + OPCODE_MUL_DD_HH, + OPCODE_MUL_DD_HL, + OPCODE_MUL_DD_LH, + OPCODE_MUL_DD_LL, + OPCODE_MULA_AA_HH, + OPCODE_MULA_AA_HL, + OPCODE_MULA_AA_LH, + OPCODE_MULA_AA_LL, + OPCODE_MULS_AA_HH, + OPCODE_MULS_AA_HL, + OPCODE_MULS_AA_LH, + OPCODE_MULS_AA_LL, + OPCODE_MULA_AD_HH, + OPCODE_MULA_AD_HL, + OPCODE_MULA_AD_LH, + OPCODE_MULA_AD_LL, + OPCODE_MULS_AD_HH, + OPCODE_MULS_AD_HL, + OPCODE_MULS_AD_LH, + OPCODE_MULS_AD_LL, + OPCODE_MULA_DA_HH, + OPCODE_MULA_DA_HL, + OPCODE_MULA_DA_LH, + OPCODE_MULA_DA_LL, + OPCODE_MULS_DA_HH, + OPCODE_MULS_DA_HL, + OPCODE_MULS_DA_LH, + OPCODE_MULS_DA_LL, + OPCODE_MULA_DD_HH, + OPCODE_MULA_DD_HL, + OPCODE_MULA_DD_LH, + OPCODE_MULA_DD_LL, + OPCODE_MULS_DD_HH, + OPCODE_MULS_DD_HL, + OPCODE_MULS_DD_LH, + OPCODE_MULS_DD_LL, + OPCODE_MULA_DA_HH_LDDEC, + OPCODE_MULA_DA_HH_LDINC, + OPCODE_MULA_DA_HL_LDDEC, + OPCODE_MULA_DA_HL_LDINC, + OPCODE_MULA_DA_LH_LDDEC, + OPCODE_MULA_DA_LH_LDINC, + OPCODE_MULA_DA_LL_LDDEC, + OPCODE_MULA_DA_LL_LDINC, + OPCODE_MULA_DD_HH_LDDEC, + OPCODE_MULA_DD_HH_LDINC, + OPCODE_MULA_DD_HL_LDDEC, + OPCODE_MULA_DD_HL_LDINC, + OPCODE_MULA_DD_LH_LDDEC, + OPCODE_MULA_DD_LH_LDINC, + OPCODE_MULA_DD_LL_LDDEC, + OPCODE_MULA_DD_LL_LDINC, + OPCODE_LDDEC, + OPCODE_LDINC, + OPCODE_RSR_M0, + OPCODE_WSR_M0, + OPCODE_XSR_M0, + OPCODE_RSR_M1, + OPCODE_WSR_M1, + OPCODE_XSR_M1, + OPCODE_RSR_M2, + OPCODE_WSR_M2, + OPCODE_XSR_M2, + OPCODE_RSR_M3, + OPCODE_WSR_M3, + OPCODE_XSR_M3, + OPCODE_RSR_ACCLO, + OPCODE_WSR_ACCLO, + OPCODE_XSR_ACCLO, + OPCODE_RSR_ACCHI, + OPCODE_WSR_ACCHI, + OPCODE_XSR_ACCHI, + OPCODE_RFI, + OPCODE_WAITI, + OPCODE_RSR_INTERRUPT, + OPCODE_WSR_INTSET, + OPCODE_WSR_INTCLEAR, + OPCODE_RSR_INTENABLE, + OPCODE_WSR_INTENABLE, + OPCODE_XSR_INTENABLE, + OPCODE_BREAK, + OPCODE_BREAK_N, + OPCODE_RSR_DBREAKA0, + OPCODE_WSR_DBREAKA0, + OPCODE_XSR_DBREAKA0, + OPCODE_RSR_DBREAKC0, + OPCODE_WSR_DBREAKC0, + OPCODE_XSR_DBREAKC0, + OPCODE_RSR_DBREAKA1, + OPCODE_WSR_DBREAKA1, + OPCODE_XSR_DBREAKA1, + OPCODE_RSR_DBREAKC1, + OPCODE_WSR_DBREAKC1, + OPCODE_XSR_DBREAKC1, + OPCODE_RSR_IBREAKA0, + OPCODE_WSR_IBREAKA0, + OPCODE_XSR_IBREAKA0, + OPCODE_RSR_IBREAKA1, + OPCODE_WSR_IBREAKA1, + OPCODE_XSR_IBREAKA1, + OPCODE_RSR_IBREAKENABLE, + OPCODE_WSR_IBREAKENABLE, + OPCODE_XSR_IBREAKENABLE, + OPCODE_RSR_DEBUGCAUSE, + OPCODE_WSR_DEBUGCAUSE, + OPCODE_XSR_DEBUGCAUSE, + OPCODE_RSR_ICOUNT, + OPCODE_WSR_ICOUNT, + OPCODE_XSR_ICOUNT, + OPCODE_RSR_ICOUNTLEVEL, + OPCODE_WSR_ICOUNTLEVEL, + OPCODE_XSR_ICOUNTLEVEL, + OPCODE_RSR_DDR, + OPCODE_WSR_DDR, + OPCODE_XSR_DDR, + OPCODE_LDDR32_P, + OPCODE_SDDR32_P, + OPCODE_RFDO, + OPCODE_RFDD, + OPCODE_WSR_MMID, + OPCODE_ANDB, + OPCODE_ANDBC, + OPCODE_ORB, + OPCODE_ORBC, + OPCODE_XORB, + OPCODE_ALL4, + OPCODE_ANY4, + OPCODE_ALL8, + OPCODE_ANY8, + OPCODE_BF, + OPCODE_BT, + OPCODE_MOVF, + OPCODE_MOVT, + OPCODE_RSR_BR, + OPCODE_WSR_BR, + OPCODE_XSR_BR, + OPCODE_RSR_CCOUNT, + OPCODE_WSR_CCOUNT, + OPCODE_XSR_CCOUNT, + OPCODE_RSR_CCOMPARE0, + OPCODE_WSR_CCOMPARE0, + OPCODE_XSR_CCOMPARE0, + OPCODE_RSR_CCOMPARE1, + OPCODE_WSR_CCOMPARE1, + OPCODE_XSR_CCOMPARE1, + OPCODE_RSR_CCOMPARE2, + OPCODE_WSR_CCOMPARE2, + OPCODE_XSR_CCOMPARE2, + OPCODE_IHI, + OPCODE_IPF, + OPCODE_IHU, + OPCODE_IIU, + OPCODE_IPFL, + OPCODE_III, + OPCODE_LICT, + OPCODE_LICW, + OPCODE_SICT, + OPCODE_SICW, + OPCODE_DHWB, + OPCODE_DHWBI, + OPCODE_DIWBUI_P, + OPCODE_DIWB, + OPCODE_DIWBI, + OPCODE_DHI, + OPCODE_DII, + OPCODE_DPFR, + OPCODE_DPFRO, + OPCODE_DPFW, + OPCODE_DPFWO, + OPCODE_DHU, + OPCODE_DIU, + OPCODE_DPFL, + OPCODE_SDCT, + OPCODE_LDCT, + OPCODE_SDCW, + OPCODE_LDCW, + OPCODE_WSR_PTEVADDR, + OPCODE_RSR_PTEVADDR, + OPCODE_XSR_PTEVADDR, + OPCODE_RSR_RASID, + OPCODE_WSR_RASID, + OPCODE_XSR_RASID, + OPCODE_RSR_ITLBCFG, + OPCODE_WSR_ITLBCFG, + OPCODE_XSR_ITLBCFG, + OPCODE_RSR_DTLBCFG, + OPCODE_WSR_DTLBCFG, + OPCODE_XSR_DTLBCFG, + OPCODE_IDTLB, + OPCODE_PDTLB, + OPCODE_RDTLB0, + OPCODE_RDTLB1, + OPCODE_WDTLB, + OPCODE_IITLB, + OPCODE_PITLB, + OPCODE_RITLB0, + OPCODE_RITLB1, + OPCODE_WITLB, + OPCODE_LDPTE, + OPCODE_HWWITLBA, + OPCODE_HWWDTLBA, + OPCODE_RSR_CPENABLE, + OPCODE_WSR_CPENABLE, + OPCODE_XSR_CPENABLE, + OPCODE_CLAMPS, + OPCODE_MAX, + OPCODE_MAXU, + OPCODE_MIN, + OPCODE_MINU, + OPCODE_NSA, + OPCODE_NSAU, + OPCODE_SEXT, + OPCODE_L32AI, + OPCODE_S32RI, + OPCODE_S32C1I, + OPCODE_RSR_SCOMPARE1, + OPCODE_WSR_SCOMPARE1, + OPCODE_XSR_SCOMPARE1, + OPCODE_RSR_ATOMCTL, + OPCODE_WSR_ATOMCTL, + OPCODE_XSR_ATOMCTL, + OPCODE_QUOS, + OPCODE_QUOU, + OPCODE_REMS, + OPCODE_REMU, + OPCODE_RSR_ERACCESS, + OPCODE_WSR_ERACCESS, + OPCODE_XSR_ERACCESS, + OPCODE_RER, + OPCODE_WER, + OPCODE_RUR_FCR, + OPCODE_WUR_FCR, + OPCODE_RUR_FSR, + OPCODE_WUR_FSR, + OPCODE_READ_IMPWIRE, + OPCODE_SETB_EXPSTATE, + OPCODE_CLRB_EXPSTATE, + OPCODE_WRMSK_EXPSTATE, + OPCODE_RUR_EXPSTATE, + OPCODE_WUR_EXPSTATE, + OPCODE_LSI, + OPCODE_LSIP, + OPCODE_LSX, + OPCODE_LSXP, + OPCODE_SSI, + OPCODE_SSIP, + OPCODE_SSX, + OPCODE_SSXP, + OPCODE_LDI, + OPCODE_LDIP, + OPCODE_LDX, + OPCODE_LDXP, + OPCODE_SDI, + OPCODE_SDIP, + OPCODE_SDX, + OPCODE_SDXP, + OPCODE_ABS_S, + OPCODE_NEG_S, + OPCODE_ABS_D, + OPCODE_NEG_D, + OPCODE_MOV_S, + OPCODE_MOV_D, + OPCODE_MOVEQZ_S, + OPCODE_MOVNEZ_S, + OPCODE_MOVLTZ_S, + OPCODE_MOVGEZ_S, + OPCODE_MOVF_S, + OPCODE_MOVT_S, + OPCODE_WFR, + OPCODE_RFR, + OPCODE_RFRD, + OPCODE_WFRD, + OPCODE_ROUND_S, + OPCODE_ROUND_D, + OPCODE_CEIL_S, + OPCODE_CEIL_D, + OPCODE_FLOOR_S, + OPCODE_FLOOR_D, + OPCODE_TRUNC_S, + OPCODE_TRUNC_D, + OPCODE_UTRUNC_S, + OPCODE_UTRUNC_D, + OPCODE_FLOAT_S, + OPCODE_FLOAT_D, + OPCODE_UFLOAT_S, + OPCODE_UFLOAT_D, + OPCODE_CVTD_S, + OPCODE_CVTS_D, + OPCODE_UN_S, + OPCODE_UN_D, + OPCODE_ULT_S, + OPCODE_ULT_D, + OPCODE_ULE_S, + OPCODE_ULE_D, + OPCODE_UEQ_S, + OPCODE_UEQ_D, + OPCODE_OLT_S, + OPCODE_OLT_D, + OPCODE_OLE_S, + OPCODE_OLE_D, + OPCODE_OEQ_S, + OPCODE_OEQ_D, + OPCODE_ADD_S, + OPCODE_ADD_D, + OPCODE_SUB_S, + OPCODE_SUB_D, + OPCODE_MUL_S, + OPCODE_MUL_D, + OPCODE_MADD_S, + OPCODE_MADD_D, + OPCODE_MSUB_S, + OPCODE_MSUB_D, + OPCODE_SQRT0_S, + OPCODE_SQRT0_D, + OPCODE_DIV0_S, + OPCODE_DIV0_D, + OPCODE_RECIP0_S, + OPCODE_RECIP0_D, + OPCODE_RSQRT0_S, + OPCODE_RSQRT0_D, + OPCODE_MADDN_S, + OPCODE_MADDN_D, + OPCODE_DIVN_S, + OPCODE_DIVN_D, + OPCODE_CONST_S, + OPCODE_CONST_D, + OPCODE_NEXP01_S, + OPCODE_NEXP01_D, + OPCODE_ADDEXP_S, + OPCODE_ADDEXP_D, + OPCODE_ADDEXPM_S, + OPCODE_ADDEXPM_D, + OPCODE_MKDADJ_S, + OPCODE_MKDADJ_D, + OPCODE_MKSADJ_S, + OPCODE_MKSADJ_D +}; + + +/* Slot-specific opcode decode functions. */ + +static int +Slot_inst_decode (const xtensa_insnbuf insn) +{ + if (Field_op0_Slot_inst_get (insn) == 0) + { + if (Field_op1_Slot_inst_get (insn) == 0) + { + if (Field_op2_Slot_inst_get (insn) == 0) + { + if (Field_r_Slot_inst_get (insn) == 0) + { + if (Field_m_Slot_inst_get (insn) == 0 && + Field_s_Slot_inst_get (insn) == 0 && + Field_n_Slot_inst_get (insn) == 0) + return OPCODE_ILL; + if (Field_m_Slot_inst_get (insn) == 2) + { + if (Field_n_Slot_inst_get (insn) == 0) + return OPCODE_RET; + if (Field_n_Slot_inst_get (insn) == 1) + return OPCODE_RETW; + if (Field_n_Slot_inst_get (insn) == 2) + return OPCODE_JX; + } + if (Field_m_Slot_inst_get (insn) == 3) + { + if (Field_n_Slot_inst_get (insn) == 0) + return OPCODE_CALLX0; + if (Field_n_Slot_inst_get (insn) == 1) + return OPCODE_CALLX4; + if (Field_n_Slot_inst_get (insn) == 2) + return OPCODE_CALLX8; + if (Field_n_Slot_inst_get (insn) == 3) + return OPCODE_CALLX12; + } + } + if (Field_r_Slot_inst_get (insn) == 1) + return OPCODE_MOVSP; + if (Field_r_Slot_inst_get (insn) == 2) + { + if (Field_s_Slot_inst_get (insn) == 0) + { + if (Field_t_Slot_inst_get (insn) == 0) + return OPCODE_ISYNC; + if (Field_t_Slot_inst_get (insn) == 1) + return OPCODE_RSYNC; + if (Field_t_Slot_inst_get (insn) == 2) + return OPCODE_ESYNC; + if (Field_t_Slot_inst_get (insn) == 3) + return OPCODE_DSYNC; + if (Field_t_Slot_inst_get (insn) == 8) + return OPCODE_EXCW; + if (Field_t_Slot_inst_get (insn) == 12) + return OPCODE_MEMW; + if (Field_t_Slot_inst_get (insn) == 13) + return OPCODE_EXTW; + if (Field_t_Slot_inst_get (insn) == 15) + return OPCODE_NOP; + } + } + if (Field_r_Slot_inst_get (insn) == 3) + { + if (Field_t_Slot_inst_get (insn) == 0) + { + if (Field_s_Slot_inst_get (insn) == 0) + return OPCODE_RFE; + if (Field_s_Slot_inst_get (insn) == 2) + return OPCODE_RFDE; + if (Field_s_Slot_inst_get (insn) == 4) + return OPCODE_RFWO; + if (Field_s_Slot_inst_get (insn) == 5) + return OPCODE_RFWU; + } + if (Field_t_Slot_inst_get (insn) == 1) + return OPCODE_RFI; + } + if (Field_r_Slot_inst_get (insn) == 4) + return OPCODE_BREAK; + if (Field_r_Slot_inst_get (insn) == 5) + { + if (Field_s_Slot_inst_get (insn) == 0 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SYSCALL; + if (Field_s_Slot_inst_get (insn) == 1) + return OPCODE_SIMCALL; + } + if (Field_r_Slot_inst_get (insn) == 6) + return OPCODE_RSIL; + if (Field_r_Slot_inst_get (insn) == 7 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_WAITI; + if (Field_r_Slot_inst_get (insn) == 7) + { + if (Field_t_Slot_inst_get (insn) == 14) + return OPCODE_LDDR32_P; + if (Field_t_Slot_inst_get (insn) == 15) + return OPCODE_SDDR32_P; + } + if (Field_r_Slot_inst_get (insn) == 8) + return OPCODE_ANY4; + if (Field_r_Slot_inst_get (insn) == 9) + return OPCODE_ALL4; + if (Field_r_Slot_inst_get (insn) == 10) + return OPCODE_ANY8; + if (Field_r_Slot_inst_get (insn) == 11) + return OPCODE_ALL8; + } + if (Field_op2_Slot_inst_get (insn) == 1) + return OPCODE_AND; + if (Field_op2_Slot_inst_get (insn) == 2) + return OPCODE_OR; + if (Field_op2_Slot_inst_get (insn) == 3) + return OPCODE_XOR; + if (Field_op2_Slot_inst_get (insn) == 4) + { + if (Field_r_Slot_inst_get (insn) == 0 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SSR; + if (Field_r_Slot_inst_get (insn) == 1 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SSL; + if (Field_r_Slot_inst_get (insn) == 2 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SSA8L; + if (Field_r_Slot_inst_get (insn) == 3 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SSA8B; + if (Field_r_Slot_inst_get (insn) == 4 && + Field_thi3_Slot_inst_get (insn) == 0) + return OPCODE_SSAI; + if (Field_r_Slot_inst_get (insn) == 6) + return OPCODE_RER; + if (Field_r_Slot_inst_get (insn) == 7) + return OPCODE_WER; + if (Field_r_Slot_inst_get (insn) == 8 && + Field_s_Slot_inst_get (insn) == 0) + return OPCODE_ROTW; + if (Field_r_Slot_inst_get (insn) == 14) + return OPCODE_NSA; + if (Field_r_Slot_inst_get (insn) == 15) + return OPCODE_NSAU; + } + if (Field_op2_Slot_inst_get (insn) == 5) + { + if (Field_r_Slot_inst_get (insn) == 1) + return OPCODE_HWWITLBA; + if (Field_r_Slot_inst_get (insn) == 3) + return OPCODE_RITLB0; + if (Field_r_Slot_inst_get (insn) == 4 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_IITLB; + if (Field_r_Slot_inst_get (insn) == 5) + return OPCODE_PITLB; + if (Field_r_Slot_inst_get (insn) == 6) + return OPCODE_WITLB; + if (Field_r_Slot_inst_get (insn) == 7) + return OPCODE_RITLB1; + if (Field_r_Slot_inst_get (insn) == 9) + return OPCODE_HWWDTLBA; + if (Field_r_Slot_inst_get (insn) == 11) + return OPCODE_RDTLB0; + if (Field_r_Slot_inst_get (insn) == 12 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_IDTLB; + if (Field_r_Slot_inst_get (insn) == 13) + return OPCODE_PDTLB; + if (Field_r_Slot_inst_get (insn) == 14) + return OPCODE_WDTLB; + if (Field_r_Slot_inst_get (insn) == 15) + return OPCODE_RDTLB1; + } + if (Field_op2_Slot_inst_get (insn) == 6) + { + if (Field_s_Slot_inst_get (insn) == 0) + return OPCODE_NEG; + if (Field_s_Slot_inst_get (insn) == 1) + return OPCODE_ABS; + } + if (Field_op2_Slot_inst_get (insn) == 8) + return OPCODE_ADD; + if (Field_op2_Slot_inst_get (insn) == 9) + return OPCODE_ADDX2; + if (Field_op2_Slot_inst_get (insn) == 10) + return OPCODE_ADDX4; + if (Field_op2_Slot_inst_get (insn) == 11) + return OPCODE_ADDX8; + if (Field_op2_Slot_inst_get (insn) == 12) + return OPCODE_SUB; + if (Field_op2_Slot_inst_get (insn) == 13) + return OPCODE_SUBX2; + if (Field_op2_Slot_inst_get (insn) == 14) + return OPCODE_SUBX4; + if (Field_op2_Slot_inst_get (insn) == 15) + return OPCODE_SUBX8; + } + if (Field_op1_Slot_inst_get (insn) == 1) + { + if ((Field_op2_Slot_inst_get (insn) == 0 || + Field_op2_Slot_inst_get (insn) == 1)) + return OPCODE_SLLI; + if ((Field_op2_Slot_inst_get (insn) == 2 || + Field_op2_Slot_inst_get (insn) == 3)) + return OPCODE_SRAI; + if (Field_op2_Slot_inst_get (insn) == 4) + return OPCODE_SRLI; + if (Field_op2_Slot_inst_get (insn) == 6) + { + if (Field_sr_Slot_inst_get (insn) == 0) + return OPCODE_XSR_LBEG; + if (Field_sr_Slot_inst_get (insn) == 1) + return OPCODE_XSR_LEND; + if (Field_sr_Slot_inst_get (insn) == 2) + return OPCODE_XSR_LCOUNT; + if (Field_sr_Slot_inst_get (insn) == 3) + return OPCODE_XSR_SAR; + if (Field_sr_Slot_inst_get (insn) == 4) + return OPCODE_XSR_BR; + if (Field_sr_Slot_inst_get (insn) == 12) + return OPCODE_XSR_SCOMPARE1; + if (Field_sr_Slot_inst_get (insn) == 16) + return OPCODE_XSR_ACCLO; + if (Field_sr_Slot_inst_get (insn) == 17) + return OPCODE_XSR_ACCHI; + if (Field_sr_Slot_inst_get (insn) == 32) + return OPCODE_XSR_M0; + if (Field_sr_Slot_inst_get (insn) == 33) + return OPCODE_XSR_M1; + if (Field_sr_Slot_inst_get (insn) == 34) + return OPCODE_XSR_M2; + if (Field_sr_Slot_inst_get (insn) == 35) + return OPCODE_XSR_M3; + if (Field_sr_Slot_inst_get (insn) == 72) + return OPCODE_XSR_WINDOWBASE; + if (Field_sr_Slot_inst_get (insn) == 73) + return OPCODE_XSR_WINDOWSTART; + if (Field_sr_Slot_inst_get (insn) == 83) + return OPCODE_XSR_PTEVADDR; + if (Field_sr_Slot_inst_get (insn) == 90) + return OPCODE_XSR_RASID; + if (Field_sr_Slot_inst_get (insn) == 91) + return OPCODE_XSR_ITLBCFG; + if (Field_sr_Slot_inst_get (insn) == 92) + return OPCODE_XSR_DTLBCFG; + if (Field_sr_Slot_inst_get (insn) == 95) + return OPCODE_XSR_ERACCESS; + if (Field_sr_Slot_inst_get (insn) == 96) + return OPCODE_XSR_IBREAKENABLE; + if (Field_sr_Slot_inst_get (insn) == 97) + return OPCODE_XSR_MEMCTL; + if (Field_sr_Slot_inst_get (insn) == 99) + return OPCODE_XSR_ATOMCTL; + if (Field_sr_Slot_inst_get (insn) == 104) + return OPCODE_XSR_DDR; + if (Field_sr_Slot_inst_get (insn) == 128) + return OPCODE_XSR_IBREAKA0; + if (Field_sr_Slot_inst_get (insn) == 129) + return OPCODE_XSR_IBREAKA1; + if (Field_sr_Slot_inst_get (insn) == 144) + return OPCODE_XSR_DBREAKA0; + if (Field_sr_Slot_inst_get (insn) == 145) + return OPCODE_XSR_DBREAKA1; + if (Field_sr_Slot_inst_get (insn) == 160) + return OPCODE_XSR_DBREAKC0; + if (Field_sr_Slot_inst_get (insn) == 161) + return OPCODE_XSR_DBREAKC1; + if (Field_sr_Slot_inst_get (insn) == 177) + return OPCODE_XSR_EPC1; + if (Field_sr_Slot_inst_get (insn) == 178) + return OPCODE_XSR_EPC2; + if (Field_sr_Slot_inst_get (insn) == 179) + return OPCODE_XSR_EPC3; + if (Field_sr_Slot_inst_get (insn) == 180) + return OPCODE_XSR_EPC4; + if (Field_sr_Slot_inst_get (insn) == 181) + return OPCODE_XSR_EPC5; + if (Field_sr_Slot_inst_get (insn) == 182) + return OPCODE_XSR_EPC6; + if (Field_sr_Slot_inst_get (insn) == 183) + return OPCODE_XSR_EPC7; + if (Field_sr_Slot_inst_get (insn) == 192) + return OPCODE_XSR_DEPC; + if (Field_sr_Slot_inst_get (insn) == 194) + return OPCODE_XSR_EPS2; + if (Field_sr_Slot_inst_get (insn) == 195) + return OPCODE_XSR_EPS3; + if (Field_sr_Slot_inst_get (insn) == 196) + return OPCODE_XSR_EPS4; + if (Field_sr_Slot_inst_get (insn) == 197) + return OPCODE_XSR_EPS5; + if (Field_sr_Slot_inst_get (insn) == 198) + return OPCODE_XSR_EPS6; + if (Field_sr_Slot_inst_get (insn) == 199) + return OPCODE_XSR_EPS7; + if (Field_sr_Slot_inst_get (insn) == 209) + return OPCODE_XSR_EXCSAVE1; + if (Field_sr_Slot_inst_get (insn) == 210) + return OPCODE_XSR_EXCSAVE2; + if (Field_sr_Slot_inst_get (insn) == 211) + return OPCODE_XSR_EXCSAVE3; + if (Field_sr_Slot_inst_get (insn) == 212) + return OPCODE_XSR_EXCSAVE4; + if (Field_sr_Slot_inst_get (insn) == 213) + return OPCODE_XSR_EXCSAVE5; + if (Field_sr_Slot_inst_get (insn) == 214) + return OPCODE_XSR_EXCSAVE6; + if (Field_sr_Slot_inst_get (insn) == 215) + return OPCODE_XSR_EXCSAVE7; + if (Field_sr_Slot_inst_get (insn) == 224) + return OPCODE_XSR_CPENABLE; + if (Field_sr_Slot_inst_get (insn) == 228) + return OPCODE_XSR_INTENABLE; + if (Field_sr_Slot_inst_get (insn) == 230) + return OPCODE_XSR_PS; + if (Field_sr_Slot_inst_get (insn) == 231) + return OPCODE_XSR_VECBASE; + if (Field_sr_Slot_inst_get (insn) == 232) + return OPCODE_XSR_EXCCAUSE; + if (Field_sr_Slot_inst_get (insn) == 233) + return OPCODE_XSR_DEBUGCAUSE; + if (Field_sr_Slot_inst_get (insn) == 234) + return OPCODE_XSR_CCOUNT; + if (Field_sr_Slot_inst_get (insn) == 236) + return OPCODE_XSR_ICOUNT; + if (Field_sr_Slot_inst_get (insn) == 237) + return OPCODE_XSR_ICOUNTLEVEL; + if (Field_sr_Slot_inst_get (insn) == 238) + return OPCODE_XSR_EXCVADDR; + if (Field_sr_Slot_inst_get (insn) == 240) + return OPCODE_XSR_CCOMPARE0; + if (Field_sr_Slot_inst_get (insn) == 241) + return OPCODE_XSR_CCOMPARE1; + if (Field_sr_Slot_inst_get (insn) == 242) + return OPCODE_XSR_CCOMPARE2; + if (Field_sr_Slot_inst_get (insn) == 244) + return OPCODE_XSR_MISC0; + if (Field_sr_Slot_inst_get (insn) == 245) + return OPCODE_XSR_MISC1; + } + if (Field_op2_Slot_inst_get (insn) == 8) + return OPCODE_SRC; + if (Field_op2_Slot_inst_get (insn) == 9 && + Field_s_Slot_inst_get (insn) == 0) + return OPCODE_SRL; + if (Field_op2_Slot_inst_get (insn) == 10 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SLL; + if (Field_op2_Slot_inst_get (insn) == 11 && + Field_s_Slot_inst_get (insn) == 0) + return OPCODE_SRA; + if (Field_op2_Slot_inst_get (insn) == 12) + return OPCODE_MUL16U; + if (Field_op2_Slot_inst_get (insn) == 13) + return OPCODE_MUL16S; + if (Field_op2_Slot_inst_get (insn) == 15) + { + if (Field_r_Slot_inst_get (insn) == 0) + return OPCODE_LICT; + if (Field_r_Slot_inst_get (insn) == 1) + return OPCODE_SICT; + if (Field_r_Slot_inst_get (insn) == 2) + return OPCODE_LICW; + if (Field_r_Slot_inst_get (insn) == 3) + return OPCODE_SICW; + if (Field_r_Slot_inst_get (insn) == 8) + return OPCODE_LDCT; + if (Field_r_Slot_inst_get (insn) == 9) + return OPCODE_SDCT; + if (Field_r_Slot_inst_get (insn) == 10) + return OPCODE_LDCW; + if (Field_r_Slot_inst_get (insn) == 11) + return OPCODE_SDCW; + if (Field_r_Slot_inst_get (insn) == 14 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_RFDO; + if (Field_r_Slot_inst_get (insn) == 14 && + Field_t_Slot_inst_get (insn) == 1) + return OPCODE_RFDD; + if (Field_r_Slot_inst_get (insn) == 15) + return OPCODE_LDPTE; + } + } + if (Field_op1_Slot_inst_get (insn) == 2) + { + if (Field_op2_Slot_inst_get (insn) == 0) + return OPCODE_ANDB; + if (Field_op2_Slot_inst_get (insn) == 1) + return OPCODE_ANDBC; + if (Field_op2_Slot_inst_get (insn) == 2) + return OPCODE_ORB; + if (Field_op2_Slot_inst_get (insn) == 3) + return OPCODE_ORBC; + if (Field_op2_Slot_inst_get (insn) == 4) + return OPCODE_XORB; + if (Field_op2_Slot_inst_get (insn) == 6) + return OPCODE_SALTU; + if (Field_op2_Slot_inst_get (insn) == 7) + return OPCODE_SALT; + if (Field_op2_Slot_inst_get (insn) == 8) + return OPCODE_MULL; + if (Field_op2_Slot_inst_get (insn) == 12) + return OPCODE_QUOU; + if (Field_op2_Slot_inst_get (insn) == 13) + return OPCODE_QUOS; + if (Field_op2_Slot_inst_get (insn) == 14) + return OPCODE_REMU; + if (Field_op2_Slot_inst_get (insn) == 15) + return OPCODE_REMS; + } + if (Field_op1_Slot_inst_get (insn) == 3) + { + if (Field_op2_Slot_inst_get (insn) == 0) + { + if (Field_sr_Slot_inst_get (insn) == 0) + return OPCODE_RSR_LBEG; + if (Field_sr_Slot_inst_get (insn) == 1) + return OPCODE_RSR_LEND; + if (Field_sr_Slot_inst_get (insn) == 2) + return OPCODE_RSR_LCOUNT; + if (Field_sr_Slot_inst_get (insn) == 3) + return OPCODE_RSR_SAR; + if (Field_sr_Slot_inst_get (insn) == 4) + return OPCODE_RSR_BR; + if (Field_sr_Slot_inst_get (insn) == 12) + return OPCODE_RSR_SCOMPARE1; + if (Field_sr_Slot_inst_get (insn) == 16) + return OPCODE_RSR_ACCLO; + if (Field_sr_Slot_inst_get (insn) == 17) + return OPCODE_RSR_ACCHI; + if (Field_sr_Slot_inst_get (insn) == 32) + return OPCODE_RSR_M0; + if (Field_sr_Slot_inst_get (insn) == 33) + return OPCODE_RSR_M1; + if (Field_sr_Slot_inst_get (insn) == 34) + return OPCODE_RSR_M2; + if (Field_sr_Slot_inst_get (insn) == 35) + return OPCODE_RSR_M3; + if (Field_sr_Slot_inst_get (insn) == 72) + return OPCODE_RSR_WINDOWBASE; + if (Field_sr_Slot_inst_get (insn) == 73) + return OPCODE_RSR_WINDOWSTART; + if (Field_sr_Slot_inst_get (insn) == 83) + return OPCODE_RSR_PTEVADDR; + if (Field_sr_Slot_inst_get (insn) == 90) + return OPCODE_RSR_RASID; + if (Field_sr_Slot_inst_get (insn) == 91) + return OPCODE_RSR_ITLBCFG; + if (Field_sr_Slot_inst_get (insn) == 92) + return OPCODE_RSR_DTLBCFG; + if (Field_sr_Slot_inst_get (insn) == 95) + return OPCODE_RSR_ERACCESS; + if (Field_sr_Slot_inst_get (insn) == 96) + return OPCODE_RSR_IBREAKENABLE; + if (Field_sr_Slot_inst_get (insn) == 97) + return OPCODE_RSR_MEMCTL; + if (Field_sr_Slot_inst_get (insn) == 99) + return OPCODE_RSR_ATOMCTL; + if (Field_sr_Slot_inst_get (insn) == 104) + return OPCODE_RSR_DDR; + if (Field_sr_Slot_inst_get (insn) == 128) + return OPCODE_RSR_IBREAKA0; + if (Field_sr_Slot_inst_get (insn) == 129) + return OPCODE_RSR_IBREAKA1; + if (Field_sr_Slot_inst_get (insn) == 144) + return OPCODE_RSR_DBREAKA0; + if (Field_sr_Slot_inst_get (insn) == 145) + return OPCODE_RSR_DBREAKA1; + if (Field_sr_Slot_inst_get (insn) == 160) + return OPCODE_RSR_DBREAKC0; + if (Field_sr_Slot_inst_get (insn) == 161) + return OPCODE_RSR_DBREAKC1; + if (Field_sr_Slot_inst_get (insn) == 176) + return OPCODE_RSR_CONFIGID0; + if (Field_sr_Slot_inst_get (insn) == 177) + return OPCODE_RSR_EPC1; + if (Field_sr_Slot_inst_get (insn) == 178) + return OPCODE_RSR_EPC2; + if (Field_sr_Slot_inst_get (insn) == 179) + return OPCODE_RSR_EPC3; + if (Field_sr_Slot_inst_get (insn) == 180) + return OPCODE_RSR_EPC4; + if (Field_sr_Slot_inst_get (insn) == 181) + return OPCODE_RSR_EPC5; + if (Field_sr_Slot_inst_get (insn) == 182) + return OPCODE_RSR_EPC6; + if (Field_sr_Slot_inst_get (insn) == 183) + return OPCODE_RSR_EPC7; + if (Field_sr_Slot_inst_get (insn) == 192) + return OPCODE_RSR_DEPC; + if (Field_sr_Slot_inst_get (insn) == 194) + return OPCODE_RSR_EPS2; + if (Field_sr_Slot_inst_get (insn) == 195) + return OPCODE_RSR_EPS3; + if (Field_sr_Slot_inst_get (insn) == 196) + return OPCODE_RSR_EPS4; + if (Field_sr_Slot_inst_get (insn) == 197) + return OPCODE_RSR_EPS5; + if (Field_sr_Slot_inst_get (insn) == 198) + return OPCODE_RSR_EPS6; + if (Field_sr_Slot_inst_get (insn) == 199) + return OPCODE_RSR_EPS7; + if (Field_sr_Slot_inst_get (insn) == 208) + return OPCODE_RSR_CONFIGID1; + if (Field_sr_Slot_inst_get (insn) == 209) + return OPCODE_RSR_EXCSAVE1; + if (Field_sr_Slot_inst_get (insn) == 210) + return OPCODE_RSR_EXCSAVE2; + if (Field_sr_Slot_inst_get (insn) == 211) + return OPCODE_RSR_EXCSAVE3; + if (Field_sr_Slot_inst_get (insn) == 212) + return OPCODE_RSR_EXCSAVE4; + if (Field_sr_Slot_inst_get (insn) == 213) + return OPCODE_RSR_EXCSAVE5; + if (Field_sr_Slot_inst_get (insn) == 214) + return OPCODE_RSR_EXCSAVE6; + if (Field_sr_Slot_inst_get (insn) == 215) + return OPCODE_RSR_EXCSAVE7; + if (Field_sr_Slot_inst_get (insn) == 224) + return OPCODE_RSR_CPENABLE; + if (Field_sr_Slot_inst_get (insn) == 226) + return OPCODE_RSR_INTERRUPT; + if (Field_sr_Slot_inst_get (insn) == 228) + return OPCODE_RSR_INTENABLE; + if (Field_sr_Slot_inst_get (insn) == 230) + return OPCODE_RSR_PS; + if (Field_sr_Slot_inst_get (insn) == 231) + return OPCODE_RSR_VECBASE; + if (Field_sr_Slot_inst_get (insn) == 232) + return OPCODE_RSR_EXCCAUSE; + if (Field_sr_Slot_inst_get (insn) == 233) + return OPCODE_RSR_DEBUGCAUSE; + if (Field_sr_Slot_inst_get (insn) == 234) + return OPCODE_RSR_CCOUNT; + if (Field_sr_Slot_inst_get (insn) == 235) + return OPCODE_RSR_PRID; + if (Field_sr_Slot_inst_get (insn) == 236) + return OPCODE_RSR_ICOUNT; + if (Field_sr_Slot_inst_get (insn) == 237) + return OPCODE_RSR_ICOUNTLEVEL; + if (Field_sr_Slot_inst_get (insn) == 238) + return OPCODE_RSR_EXCVADDR; + if (Field_sr_Slot_inst_get (insn) == 240) + return OPCODE_RSR_CCOMPARE0; + if (Field_sr_Slot_inst_get (insn) == 241) + return OPCODE_RSR_CCOMPARE1; + if (Field_sr_Slot_inst_get (insn) == 242) + return OPCODE_RSR_CCOMPARE2; + if (Field_sr_Slot_inst_get (insn) == 244) + return OPCODE_RSR_MISC0; + if (Field_sr_Slot_inst_get (insn) == 245) + return OPCODE_RSR_MISC1; + } + if (Field_op2_Slot_inst_get (insn) == 1) + { + if (Field_sr_Slot_inst_get (insn) == 0) + return OPCODE_WSR_LBEG; + if (Field_sr_Slot_inst_get (insn) == 1) + return OPCODE_WSR_LEND; + if (Field_sr_Slot_inst_get (insn) == 2) + return OPCODE_WSR_LCOUNT; + if (Field_sr_Slot_inst_get (insn) == 3) + return OPCODE_WSR_SAR; + if (Field_sr_Slot_inst_get (insn) == 4) + return OPCODE_WSR_BR; + if (Field_sr_Slot_inst_get (insn) == 12) + return OPCODE_WSR_SCOMPARE1; + if (Field_sr_Slot_inst_get (insn) == 16) + return OPCODE_WSR_ACCLO; + if (Field_sr_Slot_inst_get (insn) == 17) + return OPCODE_WSR_ACCHI; + if (Field_sr_Slot_inst_get (insn) == 32) + return OPCODE_WSR_M0; + if (Field_sr_Slot_inst_get (insn) == 33) + return OPCODE_WSR_M1; + if (Field_sr_Slot_inst_get (insn) == 34) + return OPCODE_WSR_M2; + if (Field_sr_Slot_inst_get (insn) == 35) + return OPCODE_WSR_M3; + if (Field_sr_Slot_inst_get (insn) == 72) + return OPCODE_WSR_WINDOWBASE; + if (Field_sr_Slot_inst_get (insn) == 73) + return OPCODE_WSR_WINDOWSTART; + if (Field_sr_Slot_inst_get (insn) == 83) + return OPCODE_WSR_PTEVADDR; + if (Field_sr_Slot_inst_get (insn) == 89) + return OPCODE_WSR_MMID; + if (Field_sr_Slot_inst_get (insn) == 90) + return OPCODE_WSR_RASID; + if (Field_sr_Slot_inst_get (insn) == 91) + return OPCODE_WSR_ITLBCFG; + if (Field_sr_Slot_inst_get (insn) == 92) + return OPCODE_WSR_DTLBCFG; + if (Field_sr_Slot_inst_get (insn) == 95) + return OPCODE_WSR_ERACCESS; + if (Field_sr_Slot_inst_get (insn) == 96) + return OPCODE_WSR_IBREAKENABLE; + if (Field_sr_Slot_inst_get (insn) == 97) + return OPCODE_WSR_MEMCTL; + if (Field_sr_Slot_inst_get (insn) == 99) + return OPCODE_WSR_ATOMCTL; + if (Field_sr_Slot_inst_get (insn) == 104) + return OPCODE_WSR_DDR; + if (Field_sr_Slot_inst_get (insn) == 128) + return OPCODE_WSR_IBREAKA0; + if (Field_sr_Slot_inst_get (insn) == 129) + return OPCODE_WSR_IBREAKA1; + if (Field_sr_Slot_inst_get (insn) == 144) + return OPCODE_WSR_DBREAKA0; + if (Field_sr_Slot_inst_get (insn) == 145) + return OPCODE_WSR_DBREAKA1; + if (Field_sr_Slot_inst_get (insn) == 160) + return OPCODE_WSR_DBREAKC0; + if (Field_sr_Slot_inst_get (insn) == 161) + return OPCODE_WSR_DBREAKC1; + if (Field_sr_Slot_inst_get (insn) == 176) + return OPCODE_WSR_CONFIGID0; + if (Field_sr_Slot_inst_get (insn) == 177) + return OPCODE_WSR_EPC1; + if (Field_sr_Slot_inst_get (insn) == 178) + return OPCODE_WSR_EPC2; + if (Field_sr_Slot_inst_get (insn) == 179) + return OPCODE_WSR_EPC3; + if (Field_sr_Slot_inst_get (insn) == 180) + return OPCODE_WSR_EPC4; + if (Field_sr_Slot_inst_get (insn) == 181) + return OPCODE_WSR_EPC5; + if (Field_sr_Slot_inst_get (insn) == 182) + return OPCODE_WSR_EPC6; + if (Field_sr_Slot_inst_get (insn) == 183) + return OPCODE_WSR_EPC7; + if (Field_sr_Slot_inst_get (insn) == 192) + return OPCODE_WSR_DEPC; + if (Field_sr_Slot_inst_get (insn) == 194) + return OPCODE_WSR_EPS2; + if (Field_sr_Slot_inst_get (insn) == 195) + return OPCODE_WSR_EPS3; + if (Field_sr_Slot_inst_get (insn) == 196) + return OPCODE_WSR_EPS4; + if (Field_sr_Slot_inst_get (insn) == 197) + return OPCODE_WSR_EPS5; + if (Field_sr_Slot_inst_get (insn) == 198) + return OPCODE_WSR_EPS6; + if (Field_sr_Slot_inst_get (insn) == 199) + return OPCODE_WSR_EPS7; + if (Field_sr_Slot_inst_get (insn) == 209) + return OPCODE_WSR_EXCSAVE1; + if (Field_sr_Slot_inst_get (insn) == 210) + return OPCODE_WSR_EXCSAVE2; + if (Field_sr_Slot_inst_get (insn) == 211) + return OPCODE_WSR_EXCSAVE3; + if (Field_sr_Slot_inst_get (insn) == 212) + return OPCODE_WSR_EXCSAVE4; + if (Field_sr_Slot_inst_get (insn) == 213) + return OPCODE_WSR_EXCSAVE5; + if (Field_sr_Slot_inst_get (insn) == 214) + return OPCODE_WSR_EXCSAVE6; + if (Field_sr_Slot_inst_get (insn) == 215) + return OPCODE_WSR_EXCSAVE7; + if (Field_sr_Slot_inst_get (insn) == 224) + return OPCODE_WSR_CPENABLE; + if (Field_sr_Slot_inst_get (insn) == 226) + return OPCODE_WSR_INTSET; + if (Field_sr_Slot_inst_get (insn) == 227) + return OPCODE_WSR_INTCLEAR; + if (Field_sr_Slot_inst_get (insn) == 228) + return OPCODE_WSR_INTENABLE; + if (Field_sr_Slot_inst_get (insn) == 230) + return OPCODE_WSR_PS; + if (Field_sr_Slot_inst_get (insn) == 231) + return OPCODE_WSR_VECBASE; + if (Field_sr_Slot_inst_get (insn) == 232) + return OPCODE_WSR_EXCCAUSE; + if (Field_sr_Slot_inst_get (insn) == 233) + return OPCODE_WSR_DEBUGCAUSE; + if (Field_sr_Slot_inst_get (insn) == 234) + return OPCODE_WSR_CCOUNT; + if (Field_sr_Slot_inst_get (insn) == 236) + return OPCODE_WSR_ICOUNT; + if (Field_sr_Slot_inst_get (insn) == 237) + return OPCODE_WSR_ICOUNTLEVEL; + if (Field_sr_Slot_inst_get (insn) == 238) + return OPCODE_WSR_EXCVADDR; + if (Field_sr_Slot_inst_get (insn) == 240) + return OPCODE_WSR_CCOMPARE0; + if (Field_sr_Slot_inst_get (insn) == 241) + return OPCODE_WSR_CCOMPARE1; + if (Field_sr_Slot_inst_get (insn) == 242) + return OPCODE_WSR_CCOMPARE2; + if (Field_sr_Slot_inst_get (insn) == 244) + return OPCODE_WSR_MISC0; + if (Field_sr_Slot_inst_get (insn) == 245) + return OPCODE_WSR_MISC1; + } + if (Field_op2_Slot_inst_get (insn) == 2) + return OPCODE_SEXT; + if (Field_op2_Slot_inst_get (insn) == 3) + return OPCODE_CLAMPS; + if (Field_op2_Slot_inst_get (insn) == 4) + return OPCODE_MIN; + if (Field_op2_Slot_inst_get (insn) == 5) + return OPCODE_MAX; + if (Field_op2_Slot_inst_get (insn) == 6) + return OPCODE_MINU; + if (Field_op2_Slot_inst_get (insn) == 7) + return OPCODE_MAXU; + if (Field_op2_Slot_inst_get (insn) == 8) + return OPCODE_MOVEQZ; + if (Field_op2_Slot_inst_get (insn) == 9) + return OPCODE_MOVNEZ; + if (Field_op2_Slot_inst_get (insn) == 10) + return OPCODE_MOVLTZ; + if (Field_op2_Slot_inst_get (insn) == 11) + return OPCODE_MOVGEZ; + if (Field_op2_Slot_inst_get (insn) == 12) + return OPCODE_MOVF; + if (Field_op2_Slot_inst_get (insn) == 13) + return OPCODE_MOVT; + if (Field_op2_Slot_inst_get (insn) == 14) + { + if (Field_st_Slot_inst_get (insn) == 230) + return OPCODE_RUR_EXPSTATE; + if (Field_st_Slot_inst_get (insn) == 231) + return OPCODE_RUR_THREADPTR; + if (Field_st_Slot_inst_get (insn) == 232) + return OPCODE_RUR_FCR; + if (Field_st_Slot_inst_get (insn) == 233) + return OPCODE_RUR_FSR; + } + if (Field_op2_Slot_inst_get (insn) == 15) + { + if (Field_sr_Slot_inst_get (insn) == 230) + return OPCODE_WUR_EXPSTATE; + if (Field_sr_Slot_inst_get (insn) == 231) + return OPCODE_WUR_THREADPTR; + if (Field_sr_Slot_inst_get (insn) == 232) + return OPCODE_WUR_FCR; + if (Field_sr_Slot_inst_get (insn) == 233) + return OPCODE_WUR_FSR; + } + } + if ((Field_op1_Slot_inst_get (insn) == 4 || + Field_op1_Slot_inst_get (insn) == 5)) + return OPCODE_EXTUI; + if (Field_op1_Slot_inst_get (insn) == 8) + { + if (Field_op2_Slot_inst_get (insn) == 0) + return OPCODE_LSX; + if (Field_op2_Slot_inst_get (insn) == 1) + return OPCODE_LSXP; + if (Field_op2_Slot_inst_get (insn) == 2) + return OPCODE_LDX; + if (Field_op2_Slot_inst_get (insn) == 3) + return OPCODE_LDXP; + if (Field_op2_Slot_inst_get (insn) == 4) + return OPCODE_SSX; + if (Field_op2_Slot_inst_get (insn) == 5) + return OPCODE_SSXP; + if (Field_op2_Slot_inst_get (insn) == 6) + return OPCODE_SDX; + if (Field_op2_Slot_inst_get (insn) == 7) + return OPCODE_SDXP; + } + if (Field_op1_Slot_inst_get (insn) == 9) + { + if (Field_op2_Slot_inst_get (insn) == 0) + return OPCODE_L32E; + if (Field_op2_Slot_inst_get (insn) == 4) + return OPCODE_S32E; + if (Field_op2_Slot_inst_get (insn) == 5) + return OPCODE_S32NB; + } + if (Field_op1_Slot_inst_get (insn) == 10) + { + if (Field_op2_Slot_inst_get (insn) == 0) + return OPCODE_ADD_S; + if (Field_op2_Slot_inst_get (insn) == 1) + return OPCODE_SUB_S; + if (Field_op2_Slot_inst_get (insn) == 2) + return OPCODE_MUL_S; + if (Field_op2_Slot_inst_get (insn) == 4) + return OPCODE_MADD_S; + if (Field_op2_Slot_inst_get (insn) == 5) + return OPCODE_MSUB_S; + if (Field_op2_Slot_inst_get (insn) == 6) + return OPCODE_MADDN_S; + if (Field_op2_Slot_inst_get (insn) == 7) + return OPCODE_DIVN_S; + if (Field_op2_Slot_inst_get (insn) == 8) + return OPCODE_ROUND_S; + if (Field_op2_Slot_inst_get (insn) == 9) + return OPCODE_TRUNC_S; + if (Field_op2_Slot_inst_get (insn) == 10) + return OPCODE_FLOOR_S; + if (Field_op2_Slot_inst_get (insn) == 11) + return OPCODE_CEIL_S; + if (Field_op2_Slot_inst_get (insn) == 12) + return OPCODE_FLOAT_S; + if (Field_op2_Slot_inst_get (insn) == 13) + return OPCODE_UFLOAT_S; + if (Field_op2_Slot_inst_get (insn) == 14) + return OPCODE_UTRUNC_S; + if (Field_op2_Slot_inst_get (insn) == 15) + { + if (Field_t_Slot_inst_get (insn) == 0) + return OPCODE_MOV_S; + if (Field_t_Slot_inst_get (insn) == 1) + return OPCODE_ABS_S; + if (Field_t_Slot_inst_get (insn) == 2) + return OPCODE_CVTD_S; + if (Field_t_Slot_inst_get (insn) == 3) + return OPCODE_CONST_S; + if (Field_t_Slot_inst_get (insn) == 4) + return OPCODE_RFR; + if (Field_t_Slot_inst_get (insn) == 5) + return OPCODE_WFR; + if (Field_t_Slot_inst_get (insn) == 6) + return OPCODE_NEG_S; + if (Field_t_Slot_inst_get (insn) == 7) + return OPCODE_DIV0_S; + if (Field_t_Slot_inst_get (insn) == 8) + return OPCODE_RECIP0_S; + if (Field_t_Slot_inst_get (insn) == 9) + return OPCODE_SQRT0_S; + if (Field_t_Slot_inst_get (insn) == 10) + return OPCODE_RSQRT0_S; + if (Field_t_Slot_inst_get (insn) == 11) + return OPCODE_NEXP01_S; + if (Field_t_Slot_inst_get (insn) == 12) + return OPCODE_MKSADJ_S; + if (Field_t_Slot_inst_get (insn) == 13) + return OPCODE_MKDADJ_S; + if (Field_t_Slot_inst_get (insn) == 14) + return OPCODE_ADDEXP_S; + if (Field_t_Slot_inst_get (insn) == 15) + return OPCODE_ADDEXPM_S; + } + } + if (Field_op1_Slot_inst_get (insn) == 11) + { + if (Field_op2_Slot_inst_get (insn) == 1) + return OPCODE_UN_S; + if (Field_op2_Slot_inst_get (insn) == 2) + return OPCODE_OEQ_S; + if (Field_op2_Slot_inst_get (insn) == 3) + return OPCODE_UEQ_S; + if (Field_op2_Slot_inst_get (insn) == 4) + return OPCODE_OLT_S; + if (Field_op2_Slot_inst_get (insn) == 5) + return OPCODE_ULT_S; + if (Field_op2_Slot_inst_get (insn) == 6) + return OPCODE_OLE_S; + if (Field_op2_Slot_inst_get (insn) == 7) + return OPCODE_ULE_S; + if (Field_op2_Slot_inst_get (insn) == 8) + return OPCODE_MOVEQZ_S; + if (Field_op2_Slot_inst_get (insn) == 9) + return OPCODE_MOVNEZ_S; + if (Field_op2_Slot_inst_get (insn) == 10) + return OPCODE_MOVLTZ_S; + if (Field_op2_Slot_inst_get (insn) == 11) + return OPCODE_MOVGEZ_S; + if (Field_op2_Slot_inst_get (insn) == 12) + return OPCODE_MOVF_S; + if (Field_op2_Slot_inst_get (insn) == 13) + return OPCODE_MOVT_S; + } + if (Field_op1_Slot_inst_get (insn) == 14) + { + if (Field_op2_Slot_inst_get (insn) == 1) + return OPCODE_UN_D; + if (Field_op2_Slot_inst_get (insn) == 2) + return OPCODE_OEQ_D; + if (Field_op2_Slot_inst_get (insn) == 3) + return OPCODE_UEQ_D; + if (Field_op2_Slot_inst_get (insn) == 4) + return OPCODE_OLT_D; + if (Field_op2_Slot_inst_get (insn) == 5) + return OPCODE_ULT_D; + if (Field_op2_Slot_inst_get (insn) == 6) + return OPCODE_OLE_D; + if (Field_op2_Slot_inst_get (insn) == 7) + return OPCODE_ULE_D; + if (Field_op2_Slot_inst_get (insn) == 8) + return OPCODE_WFRD; + } + if (Field_op1_Slot_inst_get (insn) == 15) + { + if (Field_op2_Slot_inst_get (insn) == 0) + return OPCODE_ADD_D; + if (Field_op2_Slot_inst_get (insn) == 1) + return OPCODE_SUB_D; + if (Field_op2_Slot_inst_get (insn) == 2) + return OPCODE_MUL_D; + if (Field_op2_Slot_inst_get (insn) == 4) + return OPCODE_MADD_D; + if (Field_op2_Slot_inst_get (insn) == 5) + return OPCODE_MSUB_D; + if (Field_op2_Slot_inst_get (insn) == 6) + return OPCODE_MADDN_D; + if (Field_op2_Slot_inst_get (insn) == 7) + return OPCODE_DIVN_D; + if (Field_op2_Slot_inst_get (insn) == 8) + return OPCODE_ROUND_D; + if (Field_op2_Slot_inst_get (insn) == 9) + return OPCODE_TRUNC_D; + if (Field_op2_Slot_inst_get (insn) == 10) + return OPCODE_FLOOR_D; + if (Field_op2_Slot_inst_get (insn) == 11) + return OPCODE_CEIL_D; + if (Field_op2_Slot_inst_get (insn) == 12) + return OPCODE_FLOAT_D; + if (Field_op2_Slot_inst_get (insn) == 13) + return OPCODE_UFLOAT_D; + if (Field_op2_Slot_inst_get (insn) == 14) + return OPCODE_UTRUNC_D; + if (Field_op2_Slot_inst_get (insn) == 15) + { + if (Field_t_Slot_inst_get (insn) == 0) + return OPCODE_MOV_D; + if (Field_t_Slot_inst_get (insn) == 1) + return OPCODE_ABS_D; + if (Field_t_Slot_inst_get (insn) == 2) + return OPCODE_CVTS_D; + if (Field_t_Slot_inst_get (insn) == 3) + return OPCODE_CONST_D; + if (Field_t_Slot_inst_get (insn) == 4) + return OPCODE_RFRD; + if (Field_t_Slot_inst_get (insn) == 6) + return OPCODE_NEG_D; + if (Field_t_Slot_inst_get (insn) == 7) + return OPCODE_DIV0_D; + if (Field_t_Slot_inst_get (insn) == 8) + return OPCODE_RECIP0_D; + if (Field_t_Slot_inst_get (insn) == 9) + return OPCODE_SQRT0_D; + if (Field_t_Slot_inst_get (insn) == 10) + return OPCODE_RSQRT0_D; + if (Field_t_Slot_inst_get (insn) == 11) + return OPCODE_NEXP01_D; + if (Field_t_Slot_inst_get (insn) == 12) + return OPCODE_MKSADJ_D; + if (Field_t_Slot_inst_get (insn) == 13) + return OPCODE_MKDADJ_D; + if (Field_t_Slot_inst_get (insn) == 14) + return OPCODE_ADDEXP_D; + if (Field_t_Slot_inst_get (insn) == 15) + return OPCODE_ADDEXPM_D; + } + } + if (Field_r_Slot_inst_get (insn) == 0 && + Field_s_Slot_inst_get (insn) == 0 && + Field_op2_Slot_inst_get (insn) == 0 && + Field_op1_Slot_inst_get (insn) == 14) + return OPCODE_READ_IMPWIRE; + if (Field_r_Slot_inst_get (insn) == 1 && + Field_s3to1_Slot_inst_get (insn) == 0 && + Field_op2_Slot_inst_get (insn) == 0 && + Field_op1_Slot_inst_get (insn) == 14) + return OPCODE_SETB_EXPSTATE; + if (Field_r_Slot_inst_get (insn) == 1 && + Field_s3to1_Slot_inst_get (insn) == 1 && + Field_op2_Slot_inst_get (insn) == 0 && + Field_op1_Slot_inst_get (insn) == 14) + return OPCODE_CLRB_EXPSTATE; + if (Field_r_Slot_inst_get (insn) == 2 && + Field_op2_Slot_inst_get (insn) == 0 && + Field_op1_Slot_inst_get (insn) == 14) + return OPCODE_WRMSK_EXPSTATE; + } + if (Field_op0_Slot_inst_get (insn) == 1) + return OPCODE_L32R; + if (Field_op0_Slot_inst_get (insn) == 2) + { + if (Field_r_Slot_inst_get (insn) == 0) + return OPCODE_L8UI; + if (Field_r_Slot_inst_get (insn) == 1) + return OPCODE_L16UI; + if (Field_r_Slot_inst_get (insn) == 2) + return OPCODE_L32I; + if (Field_r_Slot_inst_get (insn) == 4) + return OPCODE_S8I; + if (Field_r_Slot_inst_get (insn) == 5) + return OPCODE_S16I; + if (Field_r_Slot_inst_get (insn) == 6) + return OPCODE_S32I; + if (Field_r_Slot_inst_get (insn) == 7) + { + if (Field_t_Slot_inst_get (insn) == 0) + return OPCODE_DPFR; + if (Field_t_Slot_inst_get (insn) == 1) + return OPCODE_DPFW; + if (Field_t_Slot_inst_get (insn) == 2) + return OPCODE_DPFRO; + if (Field_t_Slot_inst_get (insn) == 3) + return OPCODE_DPFWO; + if (Field_t_Slot_inst_get (insn) == 4) + return OPCODE_DHWB; + if (Field_t_Slot_inst_get (insn) == 5) + return OPCODE_DHWBI; + if (Field_t_Slot_inst_get (insn) == 6) + return OPCODE_DHI; + if (Field_t_Slot_inst_get (insn) == 7) + return OPCODE_DII; + if (Field_t_Slot_inst_get (insn) == 8) + { + if (Field_op1_Slot_inst_get (insn) == 0) + return OPCODE_DPFL; + if (Field_op1_Slot_inst_get (insn) == 2) + return OPCODE_DHU; + if (Field_op1_Slot_inst_get (insn) == 3) + return OPCODE_DIU; + if (Field_op1_Slot_inst_get (insn) == 4) + return OPCODE_DIWB; + if (Field_op1_Slot_inst_get (insn) == 5) + return OPCODE_DIWBI; + if (Field_op1_Slot_inst_get (insn) == 15 && + Field_op2_Slot_inst_get (insn) == 0) + return OPCODE_DIWBUI_P; + } + if (Field_t_Slot_inst_get (insn) == 12) + return OPCODE_IPF; + if (Field_t_Slot_inst_get (insn) == 13) + { + if (Field_op1_Slot_inst_get (insn) == 0) + return OPCODE_IPFL; + if (Field_op1_Slot_inst_get (insn) == 2) + return OPCODE_IHU; + if (Field_op1_Slot_inst_get (insn) == 3) + return OPCODE_IIU; + } + if (Field_t_Slot_inst_get (insn) == 14) + return OPCODE_IHI; + if (Field_t_Slot_inst_get (insn) == 15) + return OPCODE_III; + } + if (Field_r_Slot_inst_get (insn) == 9) + return OPCODE_L16SI; + if (Field_r_Slot_inst_get (insn) == 10) + return OPCODE_MOVI; + if (Field_r_Slot_inst_get (insn) == 11) + return OPCODE_L32AI; + if (Field_r_Slot_inst_get (insn) == 12) + return OPCODE_ADDI; + if (Field_r_Slot_inst_get (insn) == 13) + return OPCODE_ADDMI; + if (Field_r_Slot_inst_get (insn) == 14) + return OPCODE_S32C1I; + if (Field_r_Slot_inst_get (insn) == 15) + return OPCODE_S32RI; + } + if (Field_op0_Slot_inst_get (insn) == 3) + { + if (Field_r_Slot_inst_get (insn) == 0) + return OPCODE_LSI; + if (Field_r_Slot_inst_get (insn) == 1) + return OPCODE_LDI; + if (Field_r_Slot_inst_get (insn) == 4) + return OPCODE_SSI; + if (Field_r_Slot_inst_get (insn) == 5) + return OPCODE_SDI; + if (Field_r_Slot_inst_get (insn) == 8) + return OPCODE_LSIP; + if (Field_r_Slot_inst_get (insn) == 9) + return OPCODE_LDIP; + if (Field_r_Slot_inst_get (insn) == 12) + return OPCODE_SSIP; + if (Field_r_Slot_inst_get (insn) == 13) + return OPCODE_SDIP; + } + if (Field_op0_Slot_inst_get (insn) == 4) + { + if (Field_op2_Slot_inst_get (insn) == 0) + { + if (Field_op1_Slot_inst_get (insn) == 8 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_LL_LDINC; + if (Field_op1_Slot_inst_get (insn) == 9 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_HL_LDINC; + if (Field_op1_Slot_inst_get (insn) == 10 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_LH_LDINC; + if (Field_op1_Slot_inst_get (insn) == 11 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_HH_LDINC; + } + if (Field_op2_Slot_inst_get (insn) == 1) + { + if (Field_op1_Slot_inst_get (insn) == 8 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_LL_LDDEC; + if (Field_op1_Slot_inst_get (insn) == 9 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_HL_LDDEC; + if (Field_op1_Slot_inst_get (insn) == 10 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_LH_LDDEC; + if (Field_op1_Slot_inst_get (insn) == 11 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_HH_LDDEC; + } + if (Field_op2_Slot_inst_get (insn) == 2) + { + if (Field_op1_Slot_inst_get (insn) == 4 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MUL_DD_LL; + if (Field_op1_Slot_inst_get (insn) == 5 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MUL_DD_HL; + if (Field_op1_Slot_inst_get (insn) == 6 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MUL_DD_LH; + if (Field_op1_Slot_inst_get (insn) == 7 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MUL_DD_HH; + if (Field_op1_Slot_inst_get (insn) == 8 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_LL; + if (Field_op1_Slot_inst_get (insn) == 9 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_HL; + if (Field_op1_Slot_inst_get (insn) == 10 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_LH; + if (Field_op1_Slot_inst_get (insn) == 11 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_HH; + if (Field_op1_Slot_inst_get (insn) == 12 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULS_DD_LL; + if (Field_op1_Slot_inst_get (insn) == 13 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULS_DD_HL; + if (Field_op1_Slot_inst_get (insn) == 14 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULS_DD_LH; + if (Field_op1_Slot_inst_get (insn) == 15 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULS_DD_HH; + } + if (Field_op2_Slot_inst_get (insn) == 3) + { + if (Field_op1_Slot_inst_get (insn) == 4 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MUL_AD_LL; + if (Field_op1_Slot_inst_get (insn) == 5 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MUL_AD_HL; + if (Field_op1_Slot_inst_get (insn) == 6 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MUL_AD_LH; + if (Field_op1_Slot_inst_get (insn) == 7 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MUL_AD_HH; + if (Field_op1_Slot_inst_get (insn) == 8 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULA_AD_LL; + if (Field_op1_Slot_inst_get (insn) == 9 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULA_AD_HL; + if (Field_op1_Slot_inst_get (insn) == 10 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULA_AD_LH; + if (Field_op1_Slot_inst_get (insn) == 11 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULA_AD_HH; + if (Field_op1_Slot_inst_get (insn) == 12 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULS_AD_LL; + if (Field_op1_Slot_inst_get (insn) == 13 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULS_AD_HL; + if (Field_op1_Slot_inst_get (insn) == 14 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULS_AD_LH; + if (Field_op1_Slot_inst_get (insn) == 15 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULS_AD_HH; + } + if (Field_op2_Slot_inst_get (insn) == 4) + { + if (Field_op1_Slot_inst_get (insn) == 8 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_LL_LDINC; + if (Field_op1_Slot_inst_get (insn) == 9 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_HL_LDINC; + if (Field_op1_Slot_inst_get (insn) == 10 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_LH_LDINC; + if (Field_op1_Slot_inst_get (insn) == 11 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_HH_LDINC; + } + if (Field_op2_Slot_inst_get (insn) == 5) + { + if (Field_op1_Slot_inst_get (insn) == 8 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_LL_LDDEC; + if (Field_op1_Slot_inst_get (insn) == 9 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_HL_LDDEC; + if (Field_op1_Slot_inst_get (insn) == 10 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_LH_LDDEC; + if (Field_op1_Slot_inst_get (insn) == 11 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_HH_LDDEC; + } + if (Field_op2_Slot_inst_get (insn) == 6) + { + if (Field_op1_Slot_inst_get (insn) == 4 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MUL_DA_LL; + if (Field_op1_Slot_inst_get (insn) == 5 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MUL_DA_HL; + if (Field_op1_Slot_inst_get (insn) == 6 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MUL_DA_LH; + if (Field_op1_Slot_inst_get (insn) == 7 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MUL_DA_HH; + if (Field_op1_Slot_inst_get (insn) == 8 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_LL; + if (Field_op1_Slot_inst_get (insn) == 9 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_HL; + if (Field_op1_Slot_inst_get (insn) == 10 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_LH; + if (Field_op1_Slot_inst_get (insn) == 11 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_HH; + if (Field_op1_Slot_inst_get (insn) == 12 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULS_DA_LL; + if (Field_op1_Slot_inst_get (insn) == 13 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULS_DA_HL; + if (Field_op1_Slot_inst_get (insn) == 14 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULS_DA_LH; + if (Field_op1_Slot_inst_get (insn) == 15 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULS_DA_HH; + } + if (Field_op2_Slot_inst_get (insn) == 7) + { + if (Field_op1_Slot_inst_get (insn) == 0 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_UMUL_AA_LL; + if (Field_op1_Slot_inst_get (insn) == 1 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_UMUL_AA_HL; + if (Field_op1_Slot_inst_get (insn) == 2 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_UMUL_AA_LH; + if (Field_op1_Slot_inst_get (insn) == 3 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_UMUL_AA_HH; + if (Field_op1_Slot_inst_get (insn) == 4 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MUL_AA_LL; + if (Field_op1_Slot_inst_get (insn) == 5 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MUL_AA_HL; + if (Field_op1_Slot_inst_get (insn) == 6 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MUL_AA_LH; + if (Field_op1_Slot_inst_get (insn) == 7 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MUL_AA_HH; + if (Field_op1_Slot_inst_get (insn) == 8 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MULA_AA_LL; + if (Field_op1_Slot_inst_get (insn) == 9 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MULA_AA_HL; + if (Field_op1_Slot_inst_get (insn) == 10 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MULA_AA_LH; + if (Field_op1_Slot_inst_get (insn) == 11 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MULA_AA_HH; + if (Field_op1_Slot_inst_get (insn) == 12 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MULS_AA_LL; + if (Field_op1_Slot_inst_get (insn) == 13 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MULS_AA_HL; + if (Field_op1_Slot_inst_get (insn) == 14 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MULS_AA_LH; + if (Field_op1_Slot_inst_get (insn) == 15 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MULS_AA_HH; + } + if (Field_op2_Slot_inst_get (insn) == 8) + { + if (Field_op1_Slot_inst_get (insn) == 0 && + Field_t_Slot_inst_get (insn) == 0 && + Field_rhi_Slot_inst_get (insn) == 0) + return OPCODE_LDINC; + } + if (Field_op2_Slot_inst_get (insn) == 9) + { + if (Field_op1_Slot_inst_get (insn) == 0 && + Field_t_Slot_inst_get (insn) == 0 && + Field_rhi_Slot_inst_get (insn) == 0) + return OPCODE_LDDEC; + } + } + if (Field_op0_Slot_inst_get (insn) == 5) + { + if (Field_n_Slot_inst_get (insn) == 0) + return OPCODE_CALL0; + if (Field_n_Slot_inst_get (insn) == 1) + return OPCODE_CALL4; + if (Field_n_Slot_inst_get (insn) == 2) + return OPCODE_CALL8; + if (Field_n_Slot_inst_get (insn) == 3) + return OPCODE_CALL12; + } + if (Field_op0_Slot_inst_get (insn) == 6) + { + if (Field_n_Slot_inst_get (insn) == 0) + return OPCODE_J; + if (Field_n_Slot_inst_get (insn) == 1) + { + if (Field_m_Slot_inst_get (insn) == 0) + return OPCODE_BEQZ; + if (Field_m_Slot_inst_get (insn) == 1) + return OPCODE_BNEZ; + if (Field_m_Slot_inst_get (insn) == 2) + return OPCODE_BLTZ; + if (Field_m_Slot_inst_get (insn) == 3) + return OPCODE_BGEZ; + } + if (Field_n_Slot_inst_get (insn) == 2) + { + if (Field_m_Slot_inst_get (insn) == 0) + return OPCODE_BEQI; + if (Field_m_Slot_inst_get (insn) == 1) + return OPCODE_BNEI; + if (Field_m_Slot_inst_get (insn) == 2) + return OPCODE_BLTI; + if (Field_m_Slot_inst_get (insn) == 3) + return OPCODE_BGEI; + } + if (Field_n_Slot_inst_get (insn) == 3) + { + if (Field_m_Slot_inst_get (insn) == 0) + return OPCODE_ENTRY; + if (Field_m_Slot_inst_get (insn) == 1) + { + if (Field_r_Slot_inst_get (insn) == 0) + return OPCODE_BF; + if (Field_r_Slot_inst_get (insn) == 1) + return OPCODE_BT; + if (Field_r_Slot_inst_get (insn) == 8) + return OPCODE_LOOP; + if (Field_r_Slot_inst_get (insn) == 9) + return OPCODE_LOOPNEZ; + if (Field_r_Slot_inst_get (insn) == 10) + return OPCODE_LOOPGTZ; + } + if (Field_m_Slot_inst_get (insn) == 2) + return OPCODE_BLTUI; + if (Field_m_Slot_inst_get (insn) == 3) + return OPCODE_BGEUI; + } + } + if (Field_op0_Slot_inst_get (insn) == 7) + { + if (Field_r_Slot_inst_get (insn) == 0) + return OPCODE_BNONE; + if (Field_r_Slot_inst_get (insn) == 1) + return OPCODE_BEQ; + if (Field_r_Slot_inst_get (insn) == 2) + return OPCODE_BLT; + if (Field_r_Slot_inst_get (insn) == 3) + return OPCODE_BLTU; + if (Field_r_Slot_inst_get (insn) == 4) + return OPCODE_BALL; + if (Field_r_Slot_inst_get (insn) == 5) + return OPCODE_BBC; + if ((Field_r_Slot_inst_get (insn) == 6 || + Field_r_Slot_inst_get (insn) == 7)) + return OPCODE_BBCI; + if (Field_r_Slot_inst_get (insn) == 8) + return OPCODE_BANY; + if (Field_r_Slot_inst_get (insn) == 9) + return OPCODE_BNE; + if (Field_r_Slot_inst_get (insn) == 10) + return OPCODE_BGE; + if (Field_r_Slot_inst_get (insn) == 11) + return OPCODE_BGEU; + if (Field_r_Slot_inst_get (insn) == 12) + return OPCODE_BNALL; + if (Field_r_Slot_inst_get (insn) == 13) + return OPCODE_BBS; + if ((Field_r_Slot_inst_get (insn) == 14 || + Field_r_Slot_inst_get (insn) == 15)) + return OPCODE_BBSI; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_inst16b_decode (const xtensa_insnbuf insn) +{ + if (Field_op0_Slot_inst16b_get (insn) == 12) + { + if (Field_i_Slot_inst16b_get (insn) == 0) + return OPCODE_MOVI_N; + if (Field_i_Slot_inst16b_get (insn) == 1) + { + if (Field_z_Slot_inst16b_get (insn) == 0) + return OPCODE_BEQZ_N; + if (Field_z_Slot_inst16b_get (insn) == 1) + return OPCODE_BNEZ_N; + } + } + if (Field_op0_Slot_inst16b_get (insn) == 13) + { + if (Field_r_Slot_inst16b_get (insn) == 0) + return OPCODE_MOV_N; + if (Field_r_Slot_inst16b_get (insn) == 15) + { + if (Field_t_Slot_inst16b_get (insn) == 0) + return OPCODE_RET_N; + if (Field_t_Slot_inst16b_get (insn) == 1) + return OPCODE_RETW_N; + if (Field_t_Slot_inst16b_get (insn) == 2) + return OPCODE_BREAK_N; + if (Field_t_Slot_inst16b_get (insn) == 3 && + Field_s_Slot_inst16b_get (insn) == 0) + return OPCODE_NOP_N; + if (Field_t_Slot_inst16b_get (insn) == 6 && + Field_s_Slot_inst16b_get (insn) == 0) + return OPCODE_ILL_N; + } + } + return XTENSA_UNDEFINED; +} + +static int +Slot_inst16a_decode (const xtensa_insnbuf insn) +{ + if (Field_op0_Slot_inst16a_get (insn) == 8) + return OPCODE_L32I_N; + if (Field_op0_Slot_inst16a_get (insn) == 9) + return OPCODE_S32I_N; + if (Field_op0_Slot_inst16a_get (insn) == 10) + return OPCODE_ADD_N; + if (Field_op0_Slot_inst16a_get (insn) == 11) + return OPCODE_ADDI_N; + return XTENSA_UNDEFINED; +} + + +/* Instruction slots. */ + +static void +Slot_x24_Format_inst_0_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[0] = (insn[0] & 0xffffff); +} + +static void +Slot_x24_Format_inst_0_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0xffffff) | (slotbuf[0] & 0xffffff); +} + +static void +Slot_x16a_Format_inst16a_0_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[0] = (insn[0] & 0xffff); +} + +static void +Slot_x16a_Format_inst16a_0_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0xffff) | (slotbuf[0] & 0xffff); +} + +static void +Slot_x16b_Format_inst16b_0_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[0] = (insn[0] & 0xffff); +} + +static void +Slot_x16b_Format_inst16b_0_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0xffff) | (slotbuf[0] & 0xffff); +} + +static xtensa_get_field_fn +Slot_inst_get_field_fns[] = { + Field_t_Slot_inst_get, + Field_bbi4_Slot_inst_get, + Field_bbi_Slot_inst_get, + Field_imm12_Slot_inst_get, + Field_imm8_Slot_inst_get, + Field_s_Slot_inst_get, + Field_s8_Slot_inst_get, + Field_imms8_Slot_inst_get, + Field_imm12b_Slot_inst_get, + Field_imm16_Slot_inst_get, + Field_m_Slot_inst_get, + Field_n_Slot_inst_get, + Field_offset_Slot_inst_get, + Field_op0_Slot_inst_get, + Field_op1_Slot_inst_get, + Field_op2_Slot_inst_get, + Field_r_Slot_inst_get, + Field_r_disp_Slot_inst_get, + Field_r_3_Slot_inst_get, + Field_sa4_Slot_inst_get, + Field_sae4_Slot_inst_get, + Field_sae_Slot_inst_get, + Field_sal_Slot_inst_get, + Field_sargt_Slot_inst_get, + Field_sas4_Slot_inst_get, + Field_sas_Slot_inst_get, + Field_sr_Slot_inst_get, + Field_st_Slot_inst_get, + Field_thi3_Slot_inst_get, + Field_imm4_Slot_inst_get, + Field_mn_Slot_inst_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r3_Slot_inst_get, + Field_rbit2_Slot_inst_get, + Field_rhi_Slot_inst_get, + Field_t3_Slot_inst_get, + Field_tbit2_Slot_inst_get, + Field_tlo_Slot_inst_get, + Field_w_Slot_inst_get, + Field_y_Slot_inst_get, + Field_x_Slot_inst_get, + Field_t2_Slot_inst_get, + Field_s2_Slot_inst_get, + Field_r2_Slot_inst_get, + Field_t4_Slot_inst_get, + Field_s4_Slot_inst_get, + Field_r4_Slot_inst_get, + Field_t8_Slot_inst_get, + Field_r8_Slot_inst_get, + Field_xt_wbr15_imm_Slot_inst_get, + Field_xt_wbr18_imm_Slot_inst_get, + Field_bitindex_Slot_inst_get, + Field_s3to1_Slot_inst_get, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_mr0_get, + Implicit_Field_mr1_get, + Implicit_Field_mr2_get, + Implicit_Field_mr3_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_inst_set_field_fns[] = { + Field_t_Slot_inst_set, + Field_bbi4_Slot_inst_set, + Field_bbi_Slot_inst_set, + Field_imm12_Slot_inst_set, + Field_imm8_Slot_inst_set, + Field_s_Slot_inst_set, + Field_s8_Slot_inst_set, + Field_imms8_Slot_inst_set, + Field_imm12b_Slot_inst_set, + Field_imm16_Slot_inst_set, + Field_m_Slot_inst_set, + Field_n_Slot_inst_set, + Field_offset_Slot_inst_set, + Field_op0_Slot_inst_set, + Field_op1_Slot_inst_set, + Field_op2_Slot_inst_set, + Field_r_Slot_inst_set, + Field_r_disp_Slot_inst_set, + Field_r_3_Slot_inst_set, + Field_sa4_Slot_inst_set, + Field_sae4_Slot_inst_set, + Field_sae_Slot_inst_set, + Field_sal_Slot_inst_set, + Field_sargt_Slot_inst_set, + Field_sas4_Slot_inst_set, + Field_sas_Slot_inst_set, + Field_sr_Slot_inst_set, + Field_st_Slot_inst_set, + Field_thi3_Slot_inst_set, + Field_imm4_Slot_inst_set, + Field_mn_Slot_inst_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r3_Slot_inst_set, + Field_rbit2_Slot_inst_set, + Field_rhi_Slot_inst_set, + Field_t3_Slot_inst_set, + Field_tbit2_Slot_inst_set, + Field_tlo_Slot_inst_set, + Field_w_Slot_inst_set, + Field_y_Slot_inst_set, + Field_x_Slot_inst_set, + Field_t2_Slot_inst_set, + Field_s2_Slot_inst_set, + Field_r2_Slot_inst_set, + Field_t4_Slot_inst_set, + Field_s4_Slot_inst_set, + Field_r4_Slot_inst_set, + Field_t8_Slot_inst_set, + Field_r8_Slot_inst_set, + Field_xt_wbr15_imm_Slot_inst_set, + Field_xt_wbr18_imm_Slot_inst_set, + Field_bitindex_Slot_inst_set, + Field_s3to1_Slot_inst_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_inst16a_get_field_fns[] = { + Field_t_Slot_inst16a_get, + 0, + 0, + 0, + 0, + Field_s_Slot_inst16a_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_Slot_inst16a_get, + 0, + 0, + Field_r_Slot_inst16a_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_i_Slot_inst16a_get, + Field_imm6lo_Slot_inst16a_get, + Field_imm6hi_Slot_inst16a_get, + Field_imm7lo_Slot_inst16a_get, + Field_imm7hi_Slot_inst16a_get, + Field_z_Slot_inst16a_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_mr0_get, + Implicit_Field_mr1_get, + Implicit_Field_mr2_get, + Implicit_Field_mr3_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_inst16a_set_field_fns[] = { + Field_t_Slot_inst16a_set, + 0, + 0, + 0, + 0, + Field_s_Slot_inst16a_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_Slot_inst16a_set, + 0, + 0, + Field_r_Slot_inst16a_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_i_Slot_inst16a_set, + Field_imm6lo_Slot_inst16a_set, + Field_imm6hi_Slot_inst16a_set, + Field_imm7lo_Slot_inst16a_set, + Field_imm7hi_Slot_inst16a_set, + Field_z_Slot_inst16a_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_inst16b_get_field_fns[] = { + Field_t_Slot_inst16b_get, + 0, + 0, + 0, + 0, + Field_s_Slot_inst16b_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_Slot_inst16b_get, + 0, + 0, + Field_r_Slot_inst16b_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_i_Slot_inst16b_get, + Field_imm6lo_Slot_inst16b_get, + Field_imm6hi_Slot_inst16b_get, + Field_imm7lo_Slot_inst16b_get, + Field_imm7hi_Slot_inst16b_get, + Field_z_Slot_inst16b_get, + Field_imm6_Slot_inst16b_get, + Field_imm7_Slot_inst16b_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_mr0_get, + Implicit_Field_mr1_get, + Implicit_Field_mr2_get, + Implicit_Field_mr3_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_inst16b_set_field_fns[] = { + Field_t_Slot_inst16b_set, + 0, + 0, + 0, + 0, + Field_s_Slot_inst16b_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_Slot_inst16b_set, + 0, + 0, + Field_r_Slot_inst16b_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_i_Slot_inst16b_set, + Field_imm6lo_Slot_inst16b_set, + Field_imm6hi_Slot_inst16b_set, + Field_imm7lo_Slot_inst16b_set, + Field_imm7hi_Slot_inst16b_set, + Field_z_Slot_inst16b_set, + Field_imm6_Slot_inst16b_set, + Field_imm7_Slot_inst16b_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_slot_internal slots[] = { + { "Inst", "x24", 0, + Slot_x24_Format_inst_0_get, Slot_x24_Format_inst_0_set, + Slot_inst_get_field_fns, Slot_inst_set_field_fns, + Slot_inst_decode, "nop" }, + { "Inst16a", "x16a", 0, + Slot_x16a_Format_inst16a_0_get, Slot_x16a_Format_inst16a_0_set, + Slot_inst16a_get_field_fns, Slot_inst16a_set_field_fns, + Slot_inst16a_decode, "" }, + { "Inst16b", "x16b", 0, + Slot_x16b_Format_inst16b_0_get, Slot_x16b_Format_inst16b_0_set, + Slot_inst16b_get_field_fns, Slot_inst16b_set_field_fns, + Slot_inst16b_decode, "nop.n" } +}; + + +/* Instruction formats. */ + +static void +Format_x24_encode (xtensa_insnbuf insn) +{ + insn[0] = 0; +} + +static void +Format_x16a_encode (xtensa_insnbuf insn) +{ + insn[0] = 0x8; +} + +static void +Format_x16b_encode (xtensa_insnbuf insn) +{ + insn[0] = 0xc; +} + +static int Format_x24_slots[] = { 0 }; + +static int Format_x16a_slots[] = { 1 }; + +static int Format_x16b_slots[] = { 2 }; + +static xtensa_format_internal formats[] = { + { "x24", 3, Format_x24_encode, 1, Format_x24_slots }, + { "x16a", 2, Format_x16a_encode, 1, Format_x16a_slots }, + { "x16b", 2, Format_x16b_encode, 1, Format_x16b_slots } +}; + + +static int +format_decoder (const xtensa_insnbuf insn) +{ + if ((insn[0] & 0x8) == 0) + return 0; /* x24 */ + if ((insn[0] & 0xc) == 0x8) + return 1; /* x16a */ + if ((insn[0] & 0xe) == 0xc) + return 2; /* x16b */ + return -1; +} + +static int length_table[256] = { + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1 +}; + +static int +length_decoder (const unsigned char *insn) +{ + int l = insn[0]; + return length_table[l]; +} + + +/* Top-level ISA structure. */ + +xtensa_isa_internal xtensa_modules = { + 0 /* little-endian */, + 3 /* insn_size */, 0, + 3, formats, format_decoder, length_decoder, + 3, slots, + 72 /* num_fields */, + 132, operands, + 444, iclasses, + 579, opcodes, 0, + 8, regfiles, + NUM_STATES, states, 0, + NUM_SYSREGS, sysregs, 0, + { MAX_SPECIAL_REG, MAX_USER_REG }, { 0, 0 }, + 1, interfaces, 0, + 1, funcUnits, 0 +}; diff --git a/target/xtensa/core-dsp3400.c b/target/xtensa/core-dsp3400.c new file mode 100644 index 0000000000000000000000000000000000000000..4e0bc8a8c46cf96e2e727d9703c3d086c69eaf37 --- /dev/null +++ b/target/xtensa/core-dsp3400.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020, Max Filippov, Open Source and Linux Lab. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Open Source and Linux Lab nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/gdbstub.h" +#include "qemu-common.h" +#include "qemu/host-utils.h" + +#include "core-dsp3400/core-isa.h" +#include "core-dsp3400/core-matmap.h" +#include "overlay_tool.h" + +#define xtensa_modules xtensa_modules_dsp3400 +#include "core-dsp3400/xtensa-modules.c.inc" + +static XtensaConfig dsp3400 __attribute__((unused)) = { + .name = "dsp3400", + .gdb_regmap = { + .reg = { +#include "core-dsp3400/gdb-config.c.inc" + } + }, + .isa_internal = &xtensa_modules, + .clock_freq_khz = 40000, + .opcode_translators = (const XtensaOpcodeTranslators *[]){ + &xtensa_core_opcodes, + &xtensa_fpu2000_opcodes, + NULL, + }, + DEFAULT_SECTIONS +}; + +REGISTER_CORE(dsp3400) diff --git a/target/xtensa/core-dsp3400/core-isa.h b/target/xtensa/core-dsp3400/core-isa.h new file mode 100644 index 0000000000000000000000000000000000000000..336b2467c6ac8c18bdbbd29f725c394f71b77dab --- /dev/null +++ b/target/xtensa/core-dsp3400/core-isa.h @@ -0,0 +1,452 @@ +/* + * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa + * processor CORE configuration + * + * See , which includes this file, for more details. + */ + +/* Xtensa processor core configuration information. + + Copyright (c) 1999-2010 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _XTENSA_CORE_CONFIGURATION_H +#define _XTENSA_CORE_CONFIGURATION_H + + +/**************************************************************************** + Parameters Useful for Any Code, USER or PRIVILEGED + ****************************************************************************/ + +/* + * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is + * configured, and a value of 0 otherwise. These macros are always defined. + */ + + +/*---------------------------------------------------------------------- + ISA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ +#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ +#define XCHAL_NUM_AREGS 32 /* num of physical addr regs */ +#define XCHAL_NUM_AREGS_LOG2 5 /* log2(XCHAL_NUM_AREGS) */ +#define XCHAL_MAX_INSTRUCTION_SIZE 8 /* max instr bytes (3..8) */ +#define XCHAL_HAVE_DEBUG 1 /* debug option */ +#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ +#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ +#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ +#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ +#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ +#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ +#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ +#define XCHAL_HAVE_MUL32 0 /* MULL instruction */ +#define XCHAL_HAVE_MUL32_HIGH 0 /* MULUH/MULSH instructions */ +#define XCHAL_HAVE_DIV32 0 /* QUOS/QUOU/REMS/REMU instructions */ +#define XCHAL_HAVE_L32R 1 /* L32R instruction */ +#define XCHAL_HAVE_ABSOLUTE_LITERALS 1 /* non-PC-rel (extended) L32R */ +#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ +#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ +#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ +#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ +#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ +#define XCHAL_HAVE_ABS 1 /* ABS instruction */ +/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */ +/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */ +#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ +#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ +#define XCHAL_HAVE_SPECULATION 0 /* speculation */ +#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ +#define XCHAL_NUM_CONTEXTS 1 /* */ +#define XCHAL_NUM_MISC_REGS 0 /* num of scratch regs (0..4) */ +#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ +#define XCHAL_HAVE_PRID 1 /* processor ID register */ +#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ +#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ +#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ +#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ +#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ +#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ +#define XCHAL_CP_MAXCFG 4 /* max allowed cp id plus one */ +#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ +#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ +#define XCHAL_HAVE_FP 1 /* floating point pkg */ +#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ +#define XCHAL_HAVE_DFP_accel 0 /* double precision FP acceleration pkg */ +#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ +#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ +#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ +#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ +#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ +#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ +#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ +#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ +#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ +#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ +#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ +#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ +#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ + + +/*---------------------------------------------------------------------- + MISC + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_WRITEBUFFER_ENTRIES 8 /* size of write buffer */ +#define XCHAL_INST_FETCH_WIDTH 8 /* instr-fetch width in bytes */ +#define XCHAL_DATA_WIDTH 16 /* data width in bytes */ +/* In T1050, applies to selected core load and store instructions (see ISA): */ +#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ +#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ +#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */ +#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/ + +#define XCHAL_SW_VERSION 800002 /* sw version of this header */ + +#define XCHAL_CORE_ID "dsp3400_RC2" /* alphanum core name + (CoreID) set in the Xtensa + Processor Generator */ + +#define XCHAL_BUILD_UNIQUE_ID 0x0002DC22 /* 22-bit sw build ID */ + +/* + * These definitions describe the hardware targeted by this software. + */ +#define XCHAL_HW_CONFIGID0 0xC3F3DBFE /* ConfigID hi 32 bits*/ +#define XCHAL_HW_CONFIGID1 0x1082C3B0 /* ConfigID lo 32 bits*/ +#define XCHAL_HW_VERSION_NAME "LX3.0.1" /* full version name */ +#define XCHAL_HW_VERSION_MAJOR 2300 /* major ver# of targeted hw */ +#define XCHAL_HW_VERSION_MINOR 1 /* minor ver# of targeted hw */ +#define XCHAL_HW_VERSION 230001 /* major*100+minor */ +#define XCHAL_HW_REL_LX3 1 +#define XCHAL_HW_REL_LX3_0 1 +#define XCHAL_HW_REL_LX3_0_1 1 +#define XCHAL_HW_CONFIGID_RELIABLE 1 +/* If software targets a *range* of hardware versions, these are the bounds: */ +#define XCHAL_HW_MIN_VERSION_MAJOR 2300 /* major v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MINOR 1 /* minor v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION 230001 /* earliest targeted hw */ +#define XCHAL_HW_MAX_VERSION_MAJOR 2300 /* major v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MINOR 1 /* minor v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION 230001 /* latest targeted hw */ + + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_ICACHE_LINESIZE 32 /* I-cache line size in bytes */ +#define XCHAL_DCACHE_LINESIZE 32 /* D-cache line size in bytes */ +#define XCHAL_ICACHE_LINEWIDTH 5 /* log2(I line size in bytes) */ +#define XCHAL_DCACHE_LINEWIDTH 5 /* log2(D line size in bytes) */ + +#define XCHAL_ICACHE_SIZE 8192 /* I-cache size in bytes or 0 */ +#define XCHAL_DCACHE_SIZE 8192 /* D-cache size in bytes or 0 */ + +#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ +#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ + +#define XCHAL_HAVE_PREFETCH 0 /* PREFCTL register */ + + + + +/**************************************************************************** + Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_PIF 1 /* any outbound PIF present */ + +/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ + +/* Number of cache sets in log2(lines per way): */ +#define XCHAL_ICACHE_SETWIDTH 7 +#define XCHAL_DCACHE_SETWIDTH 7 + +/* Cache set associativity (number of ways): */ +#define XCHAL_ICACHE_WAYS 2 +#define XCHAL_DCACHE_WAYS 2 + +/* Cache features: */ +#define XCHAL_ICACHE_LINE_LOCKABLE 1 +#define XCHAL_DCACHE_LINE_LOCKABLE 1 +#define XCHAL_ICACHE_ECC_PARITY 0 +#define XCHAL_DCACHE_ECC_PARITY 0 + +/* Cache access size in bytes (affects operation of SICW instruction): */ +#define XCHAL_ICACHE_ACCESS_SIZE 8 +#define XCHAL_DCACHE_ACCESS_SIZE 16 + +/* Number of encoded cache attr bits (see for decoded bits): */ +#define XCHAL_CA_BITS 4 + + +/*---------------------------------------------------------------------- + INTERNAL I/D RAM/ROMs and XLMI + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ +#define XCHAL_NUM_INSTRAM 2 /* number of core instr. RAMs */ +#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ +#define XCHAL_NUM_DATARAM 2 /* number of core data RAMs */ +#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ +#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ + +/* Instruction RAM 0: */ +#define XCHAL_INSTRAM0_VADDR 0x5FFE0000 +#define XCHAL_INSTRAM0_PADDR 0x5FFE0000 +#define XCHAL_INSTRAM0_SIZE 65536 +#define XCHAL_INSTRAM0_ECC_PARITY 0 + +/* Instruction RAM 1: */ +#define XCHAL_INSTRAM1_VADDR 0x5FFF0000 +#define XCHAL_INSTRAM1_PADDR 0x5FFF0000 +#define XCHAL_INSTRAM1_SIZE 65536 +#define XCHAL_INSTRAM1_ECC_PARITY 0 + +/* Data RAM 0: */ +#define XCHAL_DATARAM0_VADDR 0x5FFD0000 +#define XCHAL_DATARAM0_PADDR 0x5FFD0000 +#define XCHAL_DATARAM0_SIZE 32768 +#define XCHAL_DATARAM0_ECC_PARITY 0 + +/* Data RAM 1: */ +#define XCHAL_DATARAM1_VADDR 0x5FFD8000 +#define XCHAL_DATARAM1_PADDR 0x5FFD8000 +#define XCHAL_DATARAM1_SIZE 32768 +#define XCHAL_DATARAM1_ECC_PARITY 0 + + +/*---------------------------------------------------------------------- + INTERRUPTS and TIMERS + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ +#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ +#define XCHAL_HAVE_NMI 0 /* non-maskable interrupt */ +#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ +#define XCHAL_NUM_TIMERS 2 /* number of CCOMPAREn regs */ +#define XCHAL_NUM_INTERRUPTS 13 /* number of interrupts */ +#define XCHAL_NUM_INTERRUPTS_LOG2 4 /* ceil(log2(NUM_INTERRUPTS)) */ +#define XCHAL_NUM_EXTINTERRUPTS 9 /* num of external interrupts */ +#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels + (not including level zero) */ +#define XCHAL_EXCM_LEVEL 4 /* level masked by PS.EXCM */ + /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ + +/* Masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL1_MASK 0x00001200 +#define XCHAL_INTLEVEL2_MASK 0x00000980 +#define XCHAL_INTLEVEL3_MASK 0x00000460 +#define XCHAL_INTLEVEL4_MASK 0x00000019 +#define XCHAL_INTLEVEL5_MASK 0x00000006 +#define XCHAL_INTLEVEL6_MASK 0x00000000 +#define XCHAL_INTLEVEL7_MASK 0x00000000 + +/* Masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x00001200 +#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x00001B80 +#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x00001FE0 +#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x00001FF9 +#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x00001FFF +#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x00001FFF +#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x00001FFF + +/* Level of each interrupt: */ +#define XCHAL_INT0_LEVEL 4 +#define XCHAL_INT1_LEVEL 5 +#define XCHAL_INT2_LEVEL 5 +#define XCHAL_INT3_LEVEL 4 +#define XCHAL_INT4_LEVEL 4 +#define XCHAL_INT5_LEVEL 3 +#define XCHAL_INT6_LEVEL 3 +#define XCHAL_INT7_LEVEL 2 +#define XCHAL_INT8_LEVEL 2 +#define XCHAL_INT9_LEVEL 1 +#define XCHAL_INT10_LEVEL 3 +#define XCHAL_INT11_LEVEL 2 +#define XCHAL_INT12_LEVEL 1 +#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ +#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ + +/* Type of each interrupt: */ +#define XCHAL_INT0_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT6_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT7_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT10_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT11_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT12_TYPE XTHAL_INTTYPE_WRITE_ERROR + +/* Masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFFFE000 +#define XCHAL_INTTYPE_MASK_SOFTWARE 0x00000400 +#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000000 +#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x000003FE +#define XCHAL_INTTYPE_MASK_TIMER 0x00000801 +#define XCHAL_INTTYPE_MASK_NMI 0x00000000 +#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00001000 + +/* Interrupt numbers assigned to specific interrupt sources: */ +#define XCHAL_TIMER0_INTERRUPT 0 /* CCOMPARE0 */ +#define XCHAL_TIMER1_INTERRUPT 11 /* CCOMPARE1 */ +#define XCHAL_TIMER2_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_WRITE_ERROR_INTERRUPT 12 /* write-error interrupt */ + +/* Interrupt numbers for levels at which only one interrupt is configured: */ +/* (There are many interrupts each at level(s) 1, 2, 3, 4, 5.) */ + + +/* + * External interrupt vectors/levels. + * These macros describe how Xtensa processor interrupt numbers + * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) + * map to external BInterrupt pins, for those interrupts + * configured as external (level-triggered, edge-triggered, or NMI). + * See the Xtensa processor databook for more details. + */ + +/* Core interrupt numbers mapped to each EXTERNAL interrupt number: */ +#define XCHAL_EXTINT0_NUM 1 /* (intlevel 5) */ +#define XCHAL_EXTINT1_NUM 2 /* (intlevel 5) */ +#define XCHAL_EXTINT2_NUM 3 /* (intlevel 4) */ +#define XCHAL_EXTINT3_NUM 4 /* (intlevel 4) */ +#define XCHAL_EXTINT4_NUM 5 /* (intlevel 3) */ +#define XCHAL_EXTINT5_NUM 6 /* (intlevel 3) */ +#define XCHAL_EXTINT6_NUM 7 /* (intlevel 2) */ +#define XCHAL_EXTINT7_NUM 8 /* (intlevel 2) */ +#define XCHAL_EXTINT8_NUM 9 /* (intlevel 1) */ + + +/*---------------------------------------------------------------------- + EXCEPTIONS and VECTORS + ----------------------------------------------------------------------*/ + +#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture + number: 1 == XEA1 (old) + 2 == XEA2 (new) + 0 == XEAX (extern) */ +#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ +#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ +#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ +#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ +#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ +#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ +#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ +#define XCHAL_VECBASE_RESET_VADDR 0x5FFE0400 /* VECBASE reset value */ +#define XCHAL_VECBASE_RESET_PADDR 0x5FFE0400 +#define XCHAL_RESET_VECBASE_OVERLAP 0 + +#define XCHAL_RESET_VECTOR0_VADDR 0x5FFE0000 +#define XCHAL_RESET_VECTOR0_PADDR 0x5FFE0000 +#define XCHAL_RESET_VECTOR1_VADDR 0xFFFF1000 +#define XCHAL_RESET_VECTOR1_PADDR 0xFFFF1000 +#define XCHAL_RESET_VECTOR_VADDR 0x5FFE0000 +#define XCHAL_RESET_VECTOR_PADDR 0x5FFE0000 +#define XCHAL_USER_VECOFS 0x0000023C +#define XCHAL_USER_VECTOR_VADDR 0x5FFE063C +#define XCHAL_USER_VECTOR_PADDR 0x5FFE063C +#define XCHAL_KERNEL_VECOFS 0x0000021C +#define XCHAL_KERNEL_VECTOR_VADDR 0x5FFE061C +#define XCHAL_KERNEL_VECTOR_PADDR 0x5FFE061C +#define XCHAL_DOUBLEEXC_VECOFS 0x0000025C +#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x5FFE065C +#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x5FFE065C +#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 +#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 +#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 +#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 +#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 +#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 +#define XCHAL_WINDOW_VECTORS_VADDR 0x5FFE0400 +#define XCHAL_WINDOW_VECTORS_PADDR 0x5FFE0400 +#define XCHAL_INTLEVEL2_VECOFS 0x0000017C +#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x5FFE057C +#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x5FFE057C +#define XCHAL_INTLEVEL3_VECOFS 0x0000019C +#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x5FFE059C +#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x5FFE059C +#define XCHAL_INTLEVEL4_VECOFS 0x000001BC +#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x5FFE05BC +#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x5FFE05BC +#define XCHAL_INTLEVEL5_VECOFS 0x000001DC +#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x5FFE05DC +#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x5FFE05DC +#define XCHAL_INTLEVEL6_VECOFS 0x000001FC +#define XCHAL_INTLEVEL6_VECTOR_VADDR 0x5FFE05FC +#define XCHAL_INTLEVEL6_VECTOR_PADDR 0x5FFE05FC +#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS +#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR +#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR + + +/*---------------------------------------------------------------------- + DEBUG + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ +#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ +#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ +#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* See core-matmap.h header file for more details. */ + +#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ +#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ +#define XCHAL_SPANNING_WAY 0 /* TLB spanning way number */ +#define XCHAL_HAVE_IDENTITY_MAP 0 /* vaddr == paddr always */ +#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ +#define XCHAL_HAVE_MIMIC_CACHEATTR 0 /* region protection */ +#define XCHAL_HAVE_XLT_CACHEATTR 1 /* region prot. w/translation */ +#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table + [autorefill] and protection) + usable for an MMU-based OS */ +/* If none of the above last 4 are set, it's a custom TLB configuration. */ + +#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ +#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ +#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ + +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + + +#endif /* _XTENSA_CORE_CONFIGURATION_H */ + diff --git a/target/xtensa/core-dsp3400/core-matmap.h b/target/xtensa/core-dsp3400/core-matmap.h new file mode 100644 index 0000000000000000000000000000000000000000..8d1aa8336ec68b847c03526250ba85cf1665e114 --- /dev/null +++ b/target/xtensa/core-dsp3400/core-matmap.h @@ -0,0 +1,312 @@ +/* + * xtensa/config/core-matmap.h -- Memory access and translation mapping + * parameters (CHAL) of the Xtensa processor core configuration. + * + * If you are using Xtensa Tools, see (which includes + * this file) for more details. + * + * In the Xtensa processor products released to date, all parameters + * defined in this file are derivable (at least in theory) from + * information contained in the core-isa.h header file. + * In particular, the following core configuration parameters are relevant: + * XCHAL_HAVE_CACHEATTR + * XCHAL_HAVE_MIMIC_CACHEATTR + * XCHAL_HAVE_XLT_CACHEATTR + * XCHAL_HAVE_PTP_MMU + * XCHAL_ITLB_ARF_ENTRIES_LOG2 + * XCHAL_DTLB_ARF_ENTRIES_LOG2 + * XCHAL_DCACHE_IS_WRITEBACK + * XCHAL_ICACHE_SIZE (presence of I-cache) + * XCHAL_DCACHE_SIZE (presence of D-cache) + * XCHAL_HW_VERSION_MAJOR + * XCHAL_HW_VERSION_MINOR + */ + +/* Copyright (c) 1999-2010 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + + +#ifndef XTENSA_CONFIG_CORE_MATMAP_H +#define XTENSA_CONFIG_CORE_MATMAP_H + + +/*---------------------------------------------------------------------- + CACHE (MEMORY ACCESS) ATTRIBUTES + ----------------------------------------------------------------------*/ + + +/* Cache Attribute encodings -- lists of access modes for each cache attribute: */ +#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION +#define XCHAL_LCA_LIST XTHAL_LAM_CACHED_NOALLOC XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_ISOLATE XCHAL_SEP \ + XTHAL_LAM_EXCEPTION +#define XCHAL_SCA_LIST XTHAL_SAM_WRITETHRU XCHAL_SEP \ + XTHAL_SAM_WRITETHRU XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_WRITEBACK XCHAL_SEP \ + XTHAL_SAM_WRITEBACK_NOALLOC XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_ISOLATE XCHAL_SEP \ + XTHAL_SAM_EXCEPTION + + +/* + * Specific encoded cache attribute values of general interest. + * If a specific cache mode is not available, the closest available + * one is returned instead (eg. writethru instead of writeback, + * bypass instead of writethru). + */ +#define XCHAL_CA_BYPASS 2 /* cache disabled (bypassed) mode */ +#define XCHAL_CA_WRITETHRU 1 /* cache enabled (write-through) mode */ +#define XCHAL_CA_WRITEBACK 4 /* cache enabled (write-back) mode */ +#define XCHAL_CA_WRITEBACK_NOALLOC 4 /* cache enabled (write-back no-allocate) mode */ +#define XCHAL_CA_ILLEGAL 15 /* no access allowed (all cause exceptions) mode */ +#define XCHAL_CA_ISOLATE 14 /* cache isolate (accesses go to cache not memory) mode */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* + * General notes on MMU parameters. + * + * Terminology: + * ASID = address-space ID (acts as an "extension" of virtual addresses) + * VPN = virtual page number + * PPN = physical page number + * CA = encoded cache attribute (access modes) + * TLB = translation look-aside buffer (term is stretched somewhat here) + * I = instruction (fetch accesses) + * D = data (load and store accesses) + * way = each TLB (ITLB and DTLB) consists of a number of "ways" + * that simultaneously match the virtual address of an access; + * a TLB successfully translates a virtual address if exactly + * one way matches the vaddr; if none match, it is a miss; + * if multiple match, one gets a "multihit" exception; + * each way can be independently configured in terms of number of + * entries, page sizes, which fields are writable or constant, etc. + * set = group of contiguous ways with exactly identical parameters + * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE + * from the page table and storing it in one of the auto-refill ways; + * if this PTE load also misses, a miss exception is posted for s/w. + * min-wired = a "min-wired" way can be used to map a single (minimum-sized) + * page arbitrarily under program control; it has a single entry, + * is non-auto-refill (some other way(s) must be auto-refill), + * all its fields (VPN, PPN, ASID, CA) are all writable, and it + * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current + * restriction is that this be the only page size it supports). + * + * TLB way entries are virtually indexed. + * TLB ways that support multiple page sizes: + * - must have all writable VPN and PPN fields; + * - can only use one page size at any given time (eg. setup at startup), + * selected by the respective ITLBCFG or DTLBCFG special register, + * whose bits n*4+3 .. n*4 index the list of page sizes for way n + * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n); + * this list may be sparse for auto-refill ways because auto-refill + * ways have independent lists of supported page sizes sharing a + * common encoding with PTE entries; the encoding is the index into + * this list; unsupported sizes for a given way are zero in the list; + * selecting unsupported sizes results in undefined hardware behaviour; + * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition). + */ + +#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */ +#define XCHAL_MMU_ASID_KERNEL 0 /* ASID value indicating kernel (ring 0) address space */ +#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */ +#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */ +#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 29 /* max page size in a PTE structure (log2) */ +#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 29 /* min page size in a PTE structure (log2) */ + + +/*** Instruction TLB: ***/ + +#define XCHAL_ITLB_WAY_BITS 0 /* number of bits holding the ways */ +#define XCHAL_ITLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ +#define XCHAL_ITLB_ARF_WAYS 0 /* number of auto-refill ways */ +#define XCHAL_ITLB_SETS 1 /* number of sets (groups of ways with identical settings) */ + +/* Way set to which each way belongs: */ +#define XCHAL_ITLB_WAY0_SET 0 + +/* Ways sets that are used by hardware auto-refill (ARF): */ +#define XCHAL_ITLB_ARF_SETS 0 /* number of auto-refill sets */ + +/* Way sets that are "min-wired" (see terminology comment above): */ +#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ + + +/* ITLB way set 0 (group of ways 0 thru 0): */ +#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */ +#define XCHAL_ITLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_ITLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ +#define XCHAL_ITLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ +#define XCHAL_ITLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_PPN_RESET 1 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Constant VPN values for each entry of ITLB way set 0 (because VPN_CONSTMASK is non-zero): */ +#define XCHAL_ITLB_SET0_E0_VPN_CONST 0x00000000 +#define XCHAL_ITLB_SET0_E1_VPN_CONST 0x20000000 +#define XCHAL_ITLB_SET0_E2_VPN_CONST 0x40000000 +#define XCHAL_ITLB_SET0_E3_VPN_CONST 0x60000000 +#define XCHAL_ITLB_SET0_E4_VPN_CONST 0x80000000 +#define XCHAL_ITLB_SET0_E5_VPN_CONST 0xA0000000 +#define XCHAL_ITLB_SET0_E6_VPN_CONST 0xC0000000 +#define XCHAL_ITLB_SET0_E7_VPN_CONST 0xE0000000 +/* Reset PPN values for each entry of ITLB way set 0 (because SET0_PPN_RESET is non-zero): */ +#define XCHAL_ITLB_SET0_E0_PPN_RESET 0x00000000 +#define XCHAL_ITLB_SET0_E1_PPN_RESET 0x20000000 +#define XCHAL_ITLB_SET0_E2_PPN_RESET 0x40000000 +#define XCHAL_ITLB_SET0_E3_PPN_RESET 0x60000000 +#define XCHAL_ITLB_SET0_E4_PPN_RESET 0x80000000 +#define XCHAL_ITLB_SET0_E5_PPN_RESET 0xA0000000 +#define XCHAL_ITLB_SET0_E6_PPN_RESET 0xC0000000 +#define XCHAL_ITLB_SET0_E7_PPN_RESET 0xE0000000 +/* Reset CA values for each entry of ITLB way set 0 (because SET0_CA_RESET is non-zero): */ +#define XCHAL_ITLB_SET0_E0_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E1_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E2_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E3_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E4_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E5_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E6_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E7_CA_RESET 0x02 + + +/*** Data TLB: ***/ + +#define XCHAL_DTLB_WAY_BITS 0 /* number of bits holding the ways */ +#define XCHAL_DTLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ +#define XCHAL_DTLB_ARF_WAYS 0 /* number of auto-refill ways */ +#define XCHAL_DTLB_SETS 1 /* number of sets (groups of ways with identical settings) */ + +/* Way set to which each way belongs: */ +#define XCHAL_DTLB_WAY0_SET 0 + +/* Ways sets that are used by hardware auto-refill (ARF): */ +#define XCHAL_DTLB_ARF_SETS 0 /* number of auto-refill sets */ + +/* Way sets that are "min-wired" (see terminology comment above): */ +#define XCHAL_DTLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ + + +/* DTLB way set 0 (group of ways 0 thru 0): */ +#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */ +#define XCHAL_DTLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_DTLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ +#define XCHAL_DTLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ +#define XCHAL_DTLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_PPN_RESET 1 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Constant VPN values for each entry of DTLB way set 0 (because VPN_CONSTMASK is non-zero): */ +#define XCHAL_DTLB_SET0_E0_VPN_CONST 0x00000000 +#define XCHAL_DTLB_SET0_E1_VPN_CONST 0x20000000 +#define XCHAL_DTLB_SET0_E2_VPN_CONST 0x40000000 +#define XCHAL_DTLB_SET0_E3_VPN_CONST 0x60000000 +#define XCHAL_DTLB_SET0_E4_VPN_CONST 0x80000000 +#define XCHAL_DTLB_SET0_E5_VPN_CONST 0xA0000000 +#define XCHAL_DTLB_SET0_E6_VPN_CONST 0xC0000000 +#define XCHAL_DTLB_SET0_E7_VPN_CONST 0xE0000000 +/* Reset PPN values for each entry of DTLB way set 0 (because SET0_PPN_RESET is non-zero): */ +#define XCHAL_DTLB_SET0_E0_PPN_RESET 0x00000000 +#define XCHAL_DTLB_SET0_E1_PPN_RESET 0x20000000 +#define XCHAL_DTLB_SET0_E2_PPN_RESET 0x40000000 +#define XCHAL_DTLB_SET0_E3_PPN_RESET 0x60000000 +#define XCHAL_DTLB_SET0_E4_PPN_RESET 0x80000000 +#define XCHAL_DTLB_SET0_E5_PPN_RESET 0xA0000000 +#define XCHAL_DTLB_SET0_E6_PPN_RESET 0xC0000000 +#define XCHAL_DTLB_SET0_E7_PPN_RESET 0xE0000000 +/* Reset CA values for each entry of DTLB way set 0 (because SET0_CA_RESET is non-zero): */ +#define XCHAL_DTLB_SET0_E0_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E1_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E2_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E3_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E4_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E5_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E6_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E7_CA_RESET 0x02 + + + + +#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ + diff --git a/target/xtensa/core-dsp3400/gdb-config.c.inc b/target/xtensa/core-dsp3400/gdb-config.c.inc new file mode 100644 index 0000000000000000000000000000000000000000..f7f5f75c9875447d78dac023c86559fc266cd4c9 --- /dev/null +++ b/target/xtensa/core-dsp3400/gdb-config.c.inc @@ -0,0 +1,400 @@ +/* Configuration for the Xtensa architecture for GDB, the GNU debugger. + + Copyright (c) 2003-2010 Tensilica Inc. + + 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. */ + XTREG( 0, 0,32, 4, 4,0x0020,0x0006,-2, 9,0x0100,pc, 0,0,0,0,0,0) + XTREG( 1, 4,32, 4, 4,0x0100,0x0006,-2, 1,0x0002,ar0, 0,0,0,0,0,0) + XTREG( 2, 8,32, 4, 4,0x0101,0x0006,-2, 1,0x0002,ar1, 0,0,0,0,0,0) + XTREG( 3, 12,32, 4, 4,0x0102,0x0006,-2, 1,0x0002,ar2, 0,0,0,0,0,0) + XTREG( 4, 16,32, 4, 4,0x0103,0x0006,-2, 1,0x0002,ar3, 0,0,0,0,0,0) + XTREG( 5, 20,32, 4, 4,0x0104,0x0006,-2, 1,0x0002,ar4, 0,0,0,0,0,0) + XTREG( 6, 24,32, 4, 4,0x0105,0x0006,-2, 1,0x0002,ar5, 0,0,0,0,0,0) + XTREG( 7, 28,32, 4, 4,0x0106,0x0006,-2, 1,0x0002,ar6, 0,0,0,0,0,0) + XTREG( 8, 32,32, 4, 4,0x0107,0x0006,-2, 1,0x0002,ar7, 0,0,0,0,0,0) + XTREG( 9, 36,32, 4, 4,0x0108,0x0006,-2, 1,0x0002,ar8, 0,0,0,0,0,0) + XTREG( 10, 40,32, 4, 4,0x0109,0x0006,-2, 1,0x0002,ar9, 0,0,0,0,0,0) + XTREG( 11, 44,32, 4, 4,0x010a,0x0006,-2, 1,0x0002,ar10, 0,0,0,0,0,0) + XTREG( 12, 48,32, 4, 4,0x010b,0x0006,-2, 1,0x0002,ar11, 0,0,0,0,0,0) + XTREG( 13, 52,32, 4, 4,0x010c,0x0006,-2, 1,0x0002,ar12, 0,0,0,0,0,0) + XTREG( 14, 56,32, 4, 4,0x010d,0x0006,-2, 1,0x0002,ar13, 0,0,0,0,0,0) + XTREG( 15, 60,32, 4, 4,0x010e,0x0006,-2, 1,0x0002,ar14, 0,0,0,0,0,0) + XTREG( 16, 64,32, 4, 4,0x010f,0x0006,-2, 1,0x0002,ar15, 0,0,0,0,0,0) + XTREG( 17, 68,32, 4, 4,0x0110,0x0006,-2, 1,0x0002,ar16, 0,0,0,0,0,0) + XTREG( 18, 72,32, 4, 4,0x0111,0x0006,-2, 1,0x0002,ar17, 0,0,0,0,0,0) + XTREG( 19, 76,32, 4, 4,0x0112,0x0006,-2, 1,0x0002,ar18, 0,0,0,0,0,0) + XTREG( 20, 80,32, 4, 4,0x0113,0x0006,-2, 1,0x0002,ar19, 0,0,0,0,0,0) + XTREG( 21, 84,32, 4, 4,0x0114,0x0006,-2, 1,0x0002,ar20, 0,0,0,0,0,0) + XTREG( 22, 88,32, 4, 4,0x0115,0x0006,-2, 1,0x0002,ar21, 0,0,0,0,0,0) + XTREG( 23, 92,32, 4, 4,0x0116,0x0006,-2, 1,0x0002,ar22, 0,0,0,0,0,0) + XTREG( 24, 96,32, 4, 4,0x0117,0x0006,-2, 1,0x0002,ar23, 0,0,0,0,0,0) + XTREG( 25,100,32, 4, 4,0x0118,0x0006,-2, 1,0x0002,ar24, 0,0,0,0,0,0) + XTREG( 26,104,32, 4, 4,0x0119,0x0006,-2, 1,0x0002,ar25, 0,0,0,0,0,0) + XTREG( 27,108,32, 4, 4,0x011a,0x0006,-2, 1,0x0002,ar26, 0,0,0,0,0,0) + XTREG( 28,112,32, 4, 4,0x011b,0x0006,-2, 1,0x0002,ar27, 0,0,0,0,0,0) + XTREG( 29,116,32, 4, 4,0x011c,0x0006,-2, 1,0x0002,ar28, 0,0,0,0,0,0) + XTREG( 30,120,32, 4, 4,0x011d,0x0006,-2, 1,0x0002,ar29, 0,0,0,0,0,0) + XTREG( 31,124,32, 4, 4,0x011e,0x0006,-2, 1,0x0002,ar30, 0,0,0,0,0,0) + XTREG( 32,128,32, 4, 4,0x011f,0x0006,-2, 1,0x0002,ar31, 0,0,0,0,0,0) + XTREG( 33,132,32, 4, 4,0x0200,0x0006,-2, 2,0x1100,lbeg, 0,0,0,0,0,0) + XTREG( 34,136,32, 4, 4,0x0201,0x0006,-2, 2,0x1100,lend, 0,0,0,0,0,0) + XTREG( 35,140,32, 4, 4,0x0202,0x0006,-2, 2,0x1100,lcount, 0,0,0,0,0,0) + XTREG( 36,144, 6, 4, 4,0x0203,0x0006,-2, 2,0x1100,sar, 0,0,0,0,0,0) + XTREG( 37,148,32, 4, 4,0x0205,0x0006,-2, 2,0x1100,litbase, 0,0,0,0,0,0) + XTREG( 38,152, 3, 4, 4,0x0248,0x0006,-2, 2,0x1002,windowbase, 0,0,0,0,0,0) + XTREG( 39,156, 8, 4, 4,0x0249,0x0006,-2, 2,0x1002,windowstart, 0,0,0,0,0,0) + XTREG( 40,160,32, 4, 4,0x02b0,0x0002,-2, 2,0x1000,sr176, 0,0,0,0,0,0) + XTREG( 41,164,32, 4, 4,0x02d0,0x0002,-2, 2,0x1000,sr208, 0,0,0,0,0,0) + XTREG( 42,168,19, 4, 4,0x02e6,0x0006,-2, 2,0x1100,ps, 0,0,0,0,0,0) + XTREG( 43,172,32, 4, 4,0x03e7,0x0006,-2, 3,0x0110,threadptr, 0,0,0,0,0,0) + XTREG( 44,176,16, 4, 4,0x0204,0x0006,-1, 2,0x1100,br, 0,0,0,0,0,0) + XTREG( 45,180,32, 4, 4,0x020c,0x0006,-1, 2,0x1100,scompare1, 0,0,0,0,0,0) + XTREG( 46,184,32, 4, 4,0x0300,0x000e,-1, 3,0x0210,expstate, 0,0,0,0,0,0) + XTREG( 47,188,32, 4, 4,0x0030,0x0006, 0, 4,0x0401,f0, + "03:03:44:00","03:03:04:00",0,0,0,0) + XTREG( 48,192,32, 4, 4,0x0031,0x0006, 0, 4,0x0401,f1, + "03:13:44:00","03:13:04:00",0,0,0,0) + XTREG( 49,196,32, 4, 4,0x0032,0x0006, 0, 4,0x0401,f2, + "03:23:44:00","03:23:04:00",0,0,0,0) + XTREG( 50,200,32, 4, 4,0x0033,0x0006, 0, 4,0x0401,f3, + "03:33:44:00","03:33:04:00",0,0,0,0) + XTREG( 51,204,32, 4, 4,0x0034,0x0006, 0, 4,0x0401,f4, + "03:43:44:00","03:43:04:00",0,0,0,0) + XTREG( 52,208,32, 4, 4,0x0035,0x0006, 0, 4,0x0401,f5, + "03:53:44:00","03:53:04:00",0,0,0,0) + XTREG( 53,212,32, 4, 4,0x0036,0x0006, 0, 4,0x0401,f6, + "03:63:44:00","03:63:04:00",0,0,0,0) + XTREG( 54,216,32, 4, 4,0x0037,0x0006, 0, 4,0x0401,f7, + "03:73:44:00","03:73:04:00",0,0,0,0) + XTREG( 55,220,32, 4, 4,0x0038,0x0006, 0, 4,0x0401,f8, + "03:83:44:00","03:83:04:00",0,0,0,0) + XTREG( 56,224,32, 4, 4,0x0039,0x0006, 0, 4,0x0401,f9, + "03:93:44:00","03:93:04:00",0,0,0,0) + XTREG( 57,228,32, 4, 4,0x003a,0x0006, 0, 4,0x0401,f10, + "03:a3:44:00","03:a3:04:00",0,0,0,0) + XTREG( 58,232,32, 4, 4,0x003b,0x0006, 0, 4,0x0401,f11, + "03:b3:44:00","03:b3:04:00",0,0,0,0) + XTREG( 59,236,32, 4, 4,0x003c,0x0006, 0, 4,0x0401,f12, + "03:c3:44:00","03:c3:04:00",0,0,0,0) + XTREG( 60,240,32, 4, 4,0x003d,0x0006, 0, 4,0x0401,f13, + "03:d3:44:00","03:d3:04:00",0,0,0,0) + XTREG( 61,244,32, 4, 4,0x003e,0x0006, 0, 4,0x0401,f14, + "03:e3:44:00","03:e3:04:00",0,0,0,0) + XTREG( 62,248,32, 4, 4,0x003f,0x0006, 0, 4,0x0401,f15, + "03:f3:44:00","03:f3:04:00",0,0,0,0) + XTREG( 63,252,32, 4, 4,0x03e8,0x0006, 0, 3,0x0100,fcr, 0,0,0,0,0,0) + XTREG( 64,256,32, 4, 4,0x03e9,0x0006, 0, 3,0x0100,fsr, 0,0,0,0,0,0) + XTREG( 65,260, 4, 4, 4,0x0301,0x0006, 2, 3,0x0210,sov, 0,0,0,0,0,0) + XTREG( 66,264, 1, 4, 4,0x0302,0x0006, 2, 3,0x0210,sat_mode, 0,0,0,0,0,0) + XTREG( 67,268, 6, 4, 4,0x0303,0x0006, 2, 3,0x0210,sar0, 0,0,0,0,0,0) + XTREG( 68,272, 6, 4, 4,0x0304,0x0006, 2, 3,0x0210,sar1, 0,0,0,0,0,0) + XTREG( 69,276, 6, 4, 4,0x0305,0x0006, 2, 3,0x0210,sar2, 0,0,0,0,0,0) + XTREG( 70,280, 6, 4, 4,0x0306,0x0006, 2, 3,0x0210,sar3, 0,0,0,0,0,0) + XTREG( 71,284, 6, 4, 4,0x0307,0x0006, 2, 3,0x0210,hsar0, 0,0,0,0,0,0) + XTREG( 72,288, 6, 4, 4,0x0308,0x0006, 2, 3,0x0210,hsar1, 0,0,0,0,0,0) + XTREG( 73,292, 6, 4, 4,0x0309,0x0006, 2, 3,0x0210,hsar2, 0,0,0,0,0,0) + XTREG( 74,296, 6, 4, 4,0x030a,0x0006, 2, 3,0x0210,hsar3, 0,0,0,0,0,0) + XTREG( 75,300,32, 4, 4,0x030b,0x0006, 2, 3,0x0200,max_reg_0, 0,0,0,0,0,0) + XTREG( 76,304,32, 4, 4,0x030c,0x0006, 2, 3,0x0200,max_reg_1, 0,0,0,0,0,0) + XTREG( 77,308,32, 4, 4,0x030d,0x0006, 2, 3,0x0200,max_reg_2, 0,0,0,0,0,0) + XTREG( 78,312,32, 4, 4,0x030e,0x0006, 2, 3,0x0200,max_reg_3, 0,0,0,0,0,0) + XTREG( 79,316,32, 4, 4,0x030f,0x0006, 2, 3,0x0200,arg_max_reg_0,0,0,0,0,0,0) + XTREG( 80,320,32, 4, 4,0x0310,0x0006, 2, 3,0x0200,arg_max_reg_1,0,0,0,0,0,0) + XTREG( 81,324,32, 4, 4,0x0311,0x0006, 2, 3,0x0200,arg_max_reg_2,0,0,0,0,0,0) + XTREG( 82,328,32, 4, 4,0x0312,0x0006, 2, 3,0x0200,arg_max_reg_3,0,0,0,0,0,0) + XTREG( 83,332,32, 4, 4,0x0313,0x0006, 2, 3,0x0200,nco_counter_0,0,0,0,0,0,0) + XTREG( 84,336,32, 4, 4,0x0314,0x0006, 2, 3,0x0200,nco_counter_1,0,0,0,0,0,0) + XTREG( 85,340,32, 4, 4,0x0315,0x0006, 2, 3,0x0200,nco_counter_2,0,0,0,0,0,0) + XTREG( 86,344,32, 4, 4,0x0316,0x0006, 2, 3,0x0200,nco_counter_3,0,0,0,0,0,0) + XTREG( 87,348, 4, 4, 4,0x0317,0x0006, 2, 3,0x0210,interp_ext_n,0,0,0,0,0,0) + XTREG( 88,352, 4, 4, 4,0x0318,0x0006, 2, 3,0x0210,interp_ext_l,0,0,0,0,0,0) + XTREG( 89,356,32, 4, 4,0x0319,0x0006, 2, 3,0x0200,llr_buf_0, 0,0,0,0,0,0) + XTREG( 90,360,32, 4, 4,0x031a,0x0006, 2, 3,0x0200,llr_buf_1, 0,0,0,0,0,0) + XTREG( 91,364,32, 4, 4,0x031b,0x0006, 2, 3,0x0200,llr_buf_2, 0,0,0,0,0,0) + XTREG( 92,368,32, 4, 4,0x031c,0x0006, 2, 3,0x0200,llr_buf_3, 0,0,0,0,0,0) + XTREG( 93,372,32, 4, 4,0x031d,0x0006, 2, 3,0x0200,llr_buf_4, 0,0,0,0,0,0) + XTREG( 94,376,32, 4, 4,0x031e,0x0006, 2, 3,0x0200,llr_buf_5, 0,0,0,0,0,0) + XTREG( 95,380,32, 4, 4,0x031f,0x0006, 2, 3,0x0200,llr_buf_6, 0,0,0,0,0,0) + XTREG( 96,384,32, 4, 4,0x0320,0x0006, 2, 3,0x0200,llr_buf_7, 0,0,0,0,0,0) + XTREG( 97,388,32, 4, 4,0x0321,0x0006, 2, 3,0x0200,llr_buf_8, 0,0,0,0,0,0) + XTREG( 98,392,32, 4, 4,0x0322,0x0006, 2, 3,0x0200,llr_buf_9, 0,0,0,0,0,0) + XTREG( 99,396,32, 4, 4,0x0323,0x0006, 2, 3,0x0200,llr_buf_10, 0,0,0,0,0,0) + XTREG(100,400,32, 4, 4,0x0324,0x0006, 2, 3,0x0200,llr_buf_11, 0,0,0,0,0,0) + XTREG(101,404,32, 4, 4,0x0325,0x0006, 2, 3,0x0200,llr_buf_12, 0,0,0,0,0,0) + XTREG(102,408,32, 4, 4,0x0326,0x0006, 2, 3,0x0200,llr_buf_13, 0,0,0,0,0,0) + XTREG(103,412,32, 4, 4,0x0327,0x0006, 2, 3,0x0200,llr_buf_14, 0,0,0,0,0,0) + XTREG(104,416,32, 4, 4,0x0328,0x0006, 2, 3,0x0200,llr_buf_15, 0,0,0,0,0,0) + XTREG(105,420,32, 4, 4,0x0329,0x0006, 2, 3,0x0200,llr_buf_16, 0,0,0,0,0,0) + XTREG(106,424,32, 4, 4,0x032a,0x0006, 2, 3,0x0200,llr_buf_17, 0,0,0,0,0,0) + XTREG(107,428,32, 4, 4,0x032b,0x0006, 2, 3,0x0200,llr_buf_18, 0,0,0,0,0,0) + XTREG(108,432,32, 4, 4,0x032c,0x0006, 2, 3,0x0200,llr_buf_19, 0,0,0,0,0,0) + XTREG(109,436,32, 4, 4,0x032d,0x0006, 2, 3,0x0200,llr_buf_20, 0,0,0,0,0,0) + XTREG(110,440,32, 4, 4,0x032e,0x0006, 2, 3,0x0200,llr_buf_21, 0,0,0,0,0,0) + XTREG(111,444,32, 4, 4,0x032f,0x0006, 2, 3,0x0200,llr_buf_22, 0,0,0,0,0,0) + XTREG(112,448,32, 4, 4,0x0330,0x0006, 2, 3,0x0200,llr_buf_23, 0,0,0,0,0,0) + XTREG(113,452,32, 4, 4,0x0331,0x0006, 2, 3,0x0200,smod_buf_0, 0,0,0,0,0,0) + XTREG(114,456,32, 4, 4,0x0332,0x0006, 2, 3,0x0200,smod_buf_1, 0,0,0,0,0,0) + XTREG(115,460,32, 4, 4,0x0333,0x0006, 2, 3,0x0200,smod_buf_2, 0,0,0,0,0,0) + XTREG(116,464,32, 4, 4,0x0334,0x0006, 2, 3,0x0200,smod_buf_3, 0,0,0,0,0,0) + XTREG(117,468,32, 4, 4,0x0335,0x0006, 2, 3,0x0200,smod_buf_4, 0,0,0,0,0,0) + XTREG(118,472,32, 4, 4,0x0336,0x0006, 2, 3,0x0200,smod_buf_5, 0,0,0,0,0,0) + XTREG(119,476,32, 4, 4,0x0337,0x0006, 2, 3,0x0200,smod_buf_6, 0,0,0,0,0,0) + XTREG(120,480,32, 4, 4,0x0338,0x0006, 2, 3,0x0200,smod_buf_7, 0,0,0,0,0,0) + XTREG(121,484, 8, 4, 4,0x0339,0x0006, 2, 3,0x0210,weight_reg, 0,0,0,0,0,0) + XTREG(122,488, 5, 4, 4,0x033a,0x0006, 2, 3,0x0210,scale_reg, 0,0,0,0,0,0) + XTREG(123,492, 6, 4, 4,0x033b,0x0006, 2, 3,0x0210,llr_pos, 0,0,0,0,0,0) + XTREG(124,496, 7, 4, 4,0x033c,0x0006, 2, 3,0x0210,smod_pos, 0,0,0,0,0,0) + XTREG(125,500,32, 4, 4,0x033d,0x0006, 2, 3,0x0210,perm_reg, 0,0,0,0,0,0) + XTREG(126,504,32, 4, 4,0x033e,0x0006, 2, 3,0x0200,smod_offset_table_0,0,0,0,0,0,0) + XTREG(127,508,32, 4, 4,0x033f,0x0006, 2, 3,0x0200,smod_offset_table_1,0,0,0,0,0,0) + XTREG(128,512,32, 4, 4,0x0340,0x0006, 2, 3,0x0200,smod_offset_table_2,0,0,0,0,0,0) + XTREG(129,516,32, 4, 4,0x0341,0x0006, 2, 3,0x0200,smod_offset_table_3,0,0,0,0,0,0) + XTREG(130,520, 4, 4, 4,0x0342,0x0006, 2, 3,0x0210,phasor_n, 0,0,0,0,0,0) + XTREG(131,524,16, 4, 4,0x0343,0x0006, 2, 3,0x0210,phasor_offset,0,0,0,0,0,0) + XTREG(132,528,320,64,16,0x1008,0x0006, 2, 4,0x0201,acu0, + "03:00:84:f8:03:10:84:8d:03:20:84:9d:03:30:84:ac","03:43:20:08:03:43:28:03:03:43:20:33:03:43:28:25",0,0,0,0) + XTREG(133,592,320,64,16,0x1009,0x0006, 2, 4,0x0201,acu1, + "03:00:94:f8:03:10:94:8d:03:20:94:9d:03:30:94:ac","03:43:21:08:03:43:29:03:03:43:21:33:03:43:29:25",0,0,0,0) + XTREG(134,656,320,64,16,0x100a,0x0006, 2, 4,0x0201,acu2, + "03:00:a4:f8:03:10:a4:8d:03:20:a4:9d:03:30:a4:ac","03:43:22:08:03:43:2a:03:03:43:22:33:03:43:2a:25",0,0,0,0) + XTREG(135,720,320,64,16,0x100b,0x0006, 2, 4,0x0201,acu3, + "03:00:b4:f8:03:10:b4:8d:03:20:b4:9d:03:30:b4:ac","03:43:23:08:03:43:2b:03:03:43:23:33:03:43:2b:25",0,0,0,0) + XTREG(136,784,320,64,16,0x100c,0x0006, 2, 4,0x0201,acu4, + "03:00:c4:f8:03:10:c4:8d:03:20:c4:9d:03:30:c4:ac","03:43:24:08:03:43:2c:03:03:43:24:33:03:43:2c:25",0,0,0,0) + XTREG(137,848,320,64,16,0x100d,0x0006, 2, 4,0x0201,acu5, + "03:00:d4:f8:03:10:d4:8d:03:20:d4:9d:03:30:d4:ac","03:43:25:08:03:43:2d:03:03:43:25:33:03:43:2d:25",0,0,0,0) + XTREG(138,912,320,64,16,0x100e,0x0006, 2, 4,0x0201,acu6, + "03:00:e4:f8:03:10:e4:8d:03:20:e4:9d:03:30:e4:ac","03:43:26:08:03:43:2e:03:03:43:26:33:03:43:2e:25",0,0,0,0) + XTREG(139,976,320,64,16,0x100f,0x0006, 2, 4,0x0201,acu7, + "03:00:f4:f8:03:10:f4:8d:03:20:f4:9d:03:30:f4:ac","03:43:27:08:03:43:2f:03:03:43:27:33:03:43:2f:25",0,0,0,0) + XTREG(140,1040,128,16,16,0x1010,0x0006, 2, 4,0x0201,cm0, + "03:00:04:5d","03:40:03:07",0,0,0,0) + XTREG(141,1056,128,16,16,0x1011,0x0006, 2, 4,0x0201,cm1, + "03:00:14:5d","03:40:13:07",0,0,0,0) + XTREG(142,1072,128,16,16,0x1012,0x0006, 2, 4,0x0201,cm2, + "03:00:24:5d","03:40:23:07",0,0,0,0) + XTREG(143,1088,128,16,16,0x1013,0x0006, 2, 4,0x0201,cm3, + "03:00:34:5d","03:40:33:07",0,0,0,0) + XTREG(144,1104,128,16,16,0x1014,0x0006, 2, 4,0x0201,cm4, + "03:00:44:5d","03:40:43:07",0,0,0,0) + XTREG(145,1120,128,16,16,0x1015,0x0006, 2, 4,0x0201,cm5, + "03:00:54:5d","03:40:53:07",0,0,0,0) + XTREG(146,1136,128,16,16,0x1016,0x0006, 2, 4,0x0201,cm6, + "03:00:64:5d","03:40:63:07",0,0,0,0) + XTREG(147,1152,128,16,16,0x1017,0x0006, 2, 4,0x0201,cm7, + "03:00:74:5d","03:40:73:07",0,0,0,0) + XTREG(148,1168,128,16,16,0x1018,0x0006, 2, 4,0x0201,cm8, + "03:00:84:5d","03:40:83:07",0,0,0,0) + XTREG(149,1184,128,16,16,0x1019,0x0006, 2, 4,0x0201,cm9, + "03:00:94:5d","03:40:93:07",0,0,0,0) + XTREG(150,1200,128,16,16,0x101a,0x0006, 2, 4,0x0201,cm10, + "03:00:a4:5d","03:40:a3:07",0,0,0,0) + XTREG(151,1216,128,16,16,0x101b,0x0006, 2, 4,0x0201,cm11, + "03:00:b4:5d","03:40:b3:07",0,0,0,0) + XTREG(152,1232,128,16,16,0x101c,0x0006, 2, 4,0x0201,cm12, + "03:00:c4:5d","03:40:c3:07",0,0,0,0) + XTREG(153,1248,128,16,16,0x101d,0x0006, 2, 4,0x0201,cm13, + "03:00:d4:5d","03:40:d3:07",0,0,0,0) + XTREG(154,1264,128,16,16,0x101e,0x0006, 2, 4,0x0201,cm14, + "03:00:e4:5d","03:40:e3:07",0,0,0,0) + XTREG(155,1280,128,16,16,0x101f,0x0006, 2, 4,0x0201,cm15, + "03:00:f4:5d","03:40:f3:07",0,0,0,0) + XTREG(156,1296,256,32,16,0x1020,0x0006, 2, 4,0x0201,pq0, + "03:00:04:7c:03:10:04:cc","03:40:02:07:03:40:0c:07",0,0,0,0) + XTREG(157,1328,256,32,16,0x1021,0x0006, 2, 4,0x0201,pq1, + "03:00:14:7c:03:10:14:cc","03:40:12:07:03:40:1c:07",0,0,0,0) + XTREG(158,1360,256,32,16,0x1022,0x0006, 2, 4,0x0201,pq2, + "03:00:24:7c:03:10:24:cc","03:40:22:07:03:40:2c:07",0,0,0,0) + XTREG(159,1392,256,32,16,0x1023,0x0006, 2, 4,0x0201,pq3, + "03:00:34:7c:03:10:34:cc","03:40:32:07:03:40:3c:07",0,0,0,0) + XTREG(160,1424,256,32,16,0x1024,0x0006, 2, 4,0x0201,pq4, + "03:00:44:7c:03:10:44:cc","03:40:42:07:03:40:4c:07",0,0,0,0) + XTREG(161,1456,256,32,16,0x1025,0x0006, 2, 4,0x0201,pq5, + "03:00:54:7c:03:10:54:cc","03:40:52:07:03:40:5c:07",0,0,0,0) + XTREG(162,1488,256,32,16,0x1026,0x0006, 2, 4,0x0201,pq6, + "03:00:64:7c:03:10:64:cc","03:40:62:07:03:40:6c:07",0,0,0,0) + XTREG(163,1520,256,32,16,0x1027,0x0006, 2, 4,0x0201,pq7, + "03:00:74:7c:03:10:74:cc","03:40:72:07:03:40:7c:07",0,0,0,0) + XTREG(164,1552,256,32,16,0x1028,0x0006, 2, 4,0x0201,pq8, + "03:00:84:7c:03:10:84:cc","03:40:82:07:03:40:8c:07",0,0,0,0) + XTREG(165,1584,256,32,16,0x1029,0x0006, 2, 4,0x0201,pq9, + "03:00:94:7c:03:10:94:cc","03:40:92:07:03:40:9c:07",0,0,0,0) + XTREG(166,1616,256,32,16,0x102a,0x0006, 2, 4,0x0201,pq10, + "03:00:a4:7c:03:10:a4:cc","03:40:a2:07:03:40:ac:07",0,0,0,0) + XTREG(167,1648,256,32,16,0x102b,0x0006, 2, 4,0x0201,pq11, + "03:00:b4:7c:03:10:b4:cc","03:40:b2:07:03:40:bc:07",0,0,0,0) + XTREG(168,1680,256,32,16,0x102c,0x0006, 2, 4,0x0201,pq12, + "03:00:c4:7c:03:10:c4:cc","03:40:c2:07:03:40:cc:07",0,0,0,0) + XTREG(169,1712,256,32,16,0x102d,0x0006, 2, 4,0x0201,pq13, + "03:00:d4:7c:03:10:d4:cc","03:40:d2:07:03:40:dc:07",0,0,0,0) + XTREG(170,1744,256,32,16,0x102e,0x0006, 2, 4,0x0201,pq14, + "03:00:e4:7c:03:10:e4:cc","03:40:e2:07:03:40:ec:07",0,0,0,0) + XTREG(171,1776,256,32,16,0x102f,0x0006, 2, 4,0x0201,pq15, + "03:00:f4:7c:03:10:f4:cc","03:40:f2:07:03:40:fc:07",0,0,0,0) + XTREG(172,1808,32, 4, 4,0x0259,0x000d,-2, 2,0x1000,mmid, 0,0,0,0,0,0) + XTREG(173,1812, 2, 4, 4,0x0260,0x0007,-2, 2,0x1000,ibreakenable,0,0,0,0,0,0) + XTREG(174,1816, 6, 4, 4,0x0263,0x0007,-2, 2,0x1000,atomctl, 0,0,0,0,0,0) + XTREG(175,1820,32, 4, 4,0x0268,0x0007,-2, 2,0x1000,ddr, 0,0,0,0,0,0) + XTREG(176,1824,32, 4, 4,0x0280,0x0007,-2, 2,0x1000,ibreaka0, 0,0,0,0,0,0) + XTREG(177,1828,32, 4, 4,0x0281,0x0007,-2, 2,0x1000,ibreaka1, 0,0,0,0,0,0) + XTREG(178,1832,32, 4, 4,0x0290,0x0007,-2, 2,0x1000,dbreaka0, 0,0,0,0,0,0) + XTREG(179,1836,32, 4, 4,0x0291,0x0007,-2, 2,0x1000,dbreaka1, 0,0,0,0,0,0) + XTREG(180,1840,32, 4, 4,0x02a0,0x0007,-2, 2,0x1000,dbreakc0, 0,0,0,0,0,0) + XTREG(181,1844,32, 4, 4,0x02a1,0x0007,-2, 2,0x1000,dbreakc1, 0,0,0,0,0,0) + XTREG(182,1848,32, 4, 4,0x02b1,0x0007,-2, 2,0x1000,epc1, 0,0,0,0,0,0) + XTREG(183,1852,32, 4, 4,0x02b2,0x0007,-2, 2,0x1000,epc2, 0,0,0,0,0,0) + XTREG(184,1856,32, 4, 4,0x02b3,0x0007,-2, 2,0x1000,epc3, 0,0,0,0,0,0) + XTREG(185,1860,32, 4, 4,0x02b4,0x0007,-2, 2,0x1000,epc4, 0,0,0,0,0,0) + XTREG(186,1864,32, 4, 4,0x02b5,0x0007,-2, 2,0x1000,epc5, 0,0,0,0,0,0) + XTREG(187,1868,32, 4, 4,0x02b6,0x0007,-2, 2,0x1000,epc6, 0,0,0,0,0,0) + XTREG(188,1872,32, 4, 4,0x02c0,0x0007,-2, 2,0x1000,depc, 0,0,0,0,0,0) + XTREG(189,1876,19, 4, 4,0x02c2,0x0007,-2, 2,0x1000,eps2, 0,0,0,0,0,0) + XTREG(190,1880,19, 4, 4,0x02c3,0x0007,-2, 2,0x1000,eps3, 0,0,0,0,0,0) + XTREG(191,1884,19, 4, 4,0x02c4,0x0007,-2, 2,0x1000,eps4, 0,0,0,0,0,0) + XTREG(192,1888,19, 4, 4,0x02c5,0x0007,-2, 2,0x1000,eps5, 0,0,0,0,0,0) + XTREG(193,1892,19, 4, 4,0x02c6,0x0007,-2, 2,0x1000,eps6, 0,0,0,0,0,0) + XTREG(194,1896,32, 4, 4,0x02d1,0x0007,-2, 2,0x1000,excsave1, 0,0,0,0,0,0) + XTREG(195,1900,32, 4, 4,0x02d2,0x0007,-2, 2,0x1000,excsave2, 0,0,0,0,0,0) + XTREG(196,1904,32, 4, 4,0x02d3,0x0007,-2, 2,0x1000,excsave3, 0,0,0,0,0,0) + XTREG(197,1908,32, 4, 4,0x02d4,0x0007,-2, 2,0x1000,excsave4, 0,0,0,0,0,0) + XTREG(198,1912,32, 4, 4,0x02d5,0x0007,-2, 2,0x1000,excsave5, 0,0,0,0,0,0) + XTREG(199,1916,32, 4, 4,0x02d6,0x0007,-2, 2,0x1000,excsave6, 0,0,0,0,0,0) + XTREG(200,1920, 4, 4, 4,0x02e0,0x0007,-2, 2,0x1000,cpenable, 0,0,0,0,0,0) + XTREG(201,1924,13, 4, 4,0x02e2,0x000b,-2, 2,0x1000,interrupt, 0,0,0,0,0,0) + XTREG(202,1928,13, 4, 4,0x02e2,0x000d,-2, 2,0x1000,intset, 0,0,0,0,0,0) + XTREG(203,1932,13, 4, 4,0x02e3,0x000d,-2, 2,0x1000,intclear, 0,0,0,0,0,0) + XTREG(204,1936,13, 4, 4,0x02e4,0x0007,-2, 2,0x1000,intenable, 0,0,0,0,0,0) + XTREG(205,1940,32, 4, 4,0x02e7,0x0007,-2, 2,0x1000,vecbase, 0,0,0,0,0,0) + XTREG(206,1944, 6, 4, 4,0x02e8,0x0007,-2, 2,0x1000,exccause, 0,0,0,0,0,0) + XTREG(207,1948,12, 4, 4,0x02e9,0x0003,-2, 2,0x1000,debugcause, 0,0,0,0,0,0) + XTREG(208,1952,32, 4, 4,0x02ea,0x000f,-2, 2,0x1000,ccount, 0,0,0,0,0,0) + XTREG(209,1956,32, 4, 4,0x02eb,0x0003,-2, 2,0x1000,prid, 0,0,0,0,0,0) + XTREG(210,1960,32, 4, 4,0x02ec,0x000f,-2, 2,0x1000,icount, 0,0,0,0,0,0) + XTREG(211,1964, 4, 4, 4,0x02ed,0x0007,-2, 2,0x1000,icountlevel, 0,0,0,0,0,0) + XTREG(212,1968,32, 4, 4,0x02ee,0x0007,-2, 2,0x1000,excvaddr, 0,0,0,0,0,0) + XTREG(213,1972,32, 4, 4,0x02f0,0x000f,-2, 2,0x1000,ccompare0, 0,0,0,0,0,0) + XTREG(214,1976,32, 4, 4,0x02f1,0x000f,-2, 2,0x1000,ccompare1, 0,0,0,0,0,0) + XTREG(215,1980,32, 4, 4,0x0000,0x0006,-2, 8,0x0100,a0, 0,0,0,0,0,0) + XTREG(216,1984,32, 4, 4,0x0001,0x0006,-2, 8,0x0100,a1, 0,0,0,0,0,0) + XTREG(217,1988,32, 4, 4,0x0002,0x0006,-2, 8,0x0100,a2, 0,0,0,0,0,0) + XTREG(218,1992,32, 4, 4,0x0003,0x0006,-2, 8,0x0100,a3, 0,0,0,0,0,0) + XTREG(219,1996,32, 4, 4,0x0004,0x0006,-2, 8,0x0100,a4, 0,0,0,0,0,0) + XTREG(220,2000,32, 4, 4,0x0005,0x0006,-2, 8,0x0100,a5, 0,0,0,0,0,0) + XTREG(221,2004,32, 4, 4,0x0006,0x0006,-2, 8,0x0100,a6, 0,0,0,0,0,0) + XTREG(222,2008,32, 4, 4,0x0007,0x0006,-2, 8,0x0100,a7, 0,0,0,0,0,0) + XTREG(223,2012,32, 4, 4,0x0008,0x0006,-2, 8,0x0100,a8, 0,0,0,0,0,0) + XTREG(224,2016,32, 4, 4,0x0009,0x0006,-2, 8,0x0100,a9, 0,0,0,0,0,0) + XTREG(225,2020,32, 4, 4,0x000a,0x0006,-2, 8,0x0100,a10, 0,0,0,0,0,0) + XTREG(226,2024,32, 4, 4,0x000b,0x0006,-2, 8,0x0100,a11, 0,0,0,0,0,0) + XTREG(227,2028,32, 4, 4,0x000c,0x0006,-2, 8,0x0100,a12, 0,0,0,0,0,0) + XTREG(228,2032,32, 4, 4,0x000d,0x0006,-2, 8,0x0100,a13, 0,0,0,0,0,0) + XTREG(229,2036,32, 4, 4,0x000e,0x0006,-2, 8,0x0100,a14, 0,0,0,0,0,0) + XTREG(230,2040,32, 4, 4,0x000f,0x0006,-2, 8,0x0100,a15, 0,0,0,0,0,0) + XTREG(231,2044, 1, 1, 1,0x0010,0x0006,-2, 6,0x1010,b0, + 0,0,&xtensa_mask0,0,0,0) + XTREG(232,2045, 1, 1, 1,0x0011,0x0006,-2, 6,0x1010,b1, + 0,0,&xtensa_mask1,0,0,0) + XTREG(233,2046, 1, 1, 1,0x0012,0x0006,-2, 6,0x1010,b2, + 0,0,&xtensa_mask2,0,0,0) + XTREG(234,2047, 1, 1, 1,0x0013,0x0006,-2, 6,0x1010,b3, + 0,0,&xtensa_mask3,0,0,0) + XTREG(235,2048, 1, 1, 1,0x0014,0x0006,-2, 6,0x1010,b4, + 0,0,&xtensa_mask4,0,0,0) + XTREG(236,2049, 1, 1, 1,0x0015,0x0006,-2, 6,0x1010,b5, + 0,0,&xtensa_mask5,0,0,0) + XTREG(237,2050, 1, 1, 1,0x0016,0x0006,-2, 6,0x1010,b6, + 0,0,&xtensa_mask6,0,0,0) + XTREG(238,2051, 1, 1, 1,0x0017,0x0006,-2, 6,0x1010,b7, + 0,0,&xtensa_mask7,0,0,0) + XTREG(239,2052, 1, 1, 1,0x0018,0x0006,-2, 6,0x1010,b8, + 0,0,&xtensa_mask8,0,0,0) + XTREG(240,2053, 1, 1, 1,0x0019,0x0006,-2, 6,0x1010,b9, + 0,0,&xtensa_mask9,0,0,0) + XTREG(241,2054, 1, 1, 1,0x001a,0x0006,-2, 6,0x1010,b10, + 0,0,&xtensa_mask10,0,0,0) + XTREG(242,2055, 1, 1, 1,0x001b,0x0006,-2, 6,0x1010,b11, + 0,0,&xtensa_mask11,0,0,0) + XTREG(243,2056, 1, 1, 1,0x001c,0x0006,-2, 6,0x1010,b12, + 0,0,&xtensa_mask12,0,0,0) + XTREG(244,2057, 1, 1, 1,0x001d,0x0006,-2, 6,0x1010,b13, + 0,0,&xtensa_mask13,0,0,0) + XTREG(245,2058, 1, 1, 1,0x001e,0x0006,-2, 6,0x1010,b14, + 0,0,&xtensa_mask14,0,0,0) + XTREG(246,2059, 1, 1, 1,0x001f,0x0006,-2, 6,0x1010,b15, + 0,0,&xtensa_mask15,0,0,0) + XTREG(247,2060, 4, 4, 4,0x2007,0x0006,-2, 6,0x1010,psintlevel, + 0,0,&xtensa_mask16,0,0,0) + XTREG(248,2064, 1, 4, 4,0x2008,0x0006,-2, 6,0x1010,psum, + 0,0,&xtensa_mask17,0,0,0) + XTREG(249,2068, 1, 4, 4,0x2009,0x0006,-2, 6,0x1010,pswoe, + 0,0,&xtensa_mask18,0,0,0) + XTREG(250,2072, 1, 4, 4,0x200a,0x0006,-2, 6,0x1010,psexcm, + 0,0,&xtensa_mask19,0,0,0) + XTREG(251,2076, 2, 4, 4,0x200b,0x0006,-2, 6,0x1010,pscallinc, + 0,0,&xtensa_mask20,0,0,0) + XTREG(252,2080, 4, 4, 4,0x200c,0x0006,-2, 6,0x1010,psowb, + 0,0,&xtensa_mask21,0,0,0) + XTREG(253,2084,20, 4, 4,0x200d,0x0006,-2, 6,0x1010,litbaddr, + 0,0,&xtensa_mask22,0,0,0) + XTREG(254,2088, 1, 4, 4,0x200e,0x0006,-2, 6,0x1010,litben, + 0,0,&xtensa_mask23,0,0,0) + XTREG(255,2092, 4, 4, 4,0x2013,0x0006,-2, 6,0x1010,dbnum, + 0,0,&xtensa_mask24,0,0,0) + XTREG(256,2096, 2, 4, 4,0x2014,0x0006, 0, 5,0x1010,roundmode, + 0,0,&xtensa_mask25,0,0,0) + XTREG(257,2100, 1, 4, 4,0x2015,0x0006, 0, 5,0x1010,invalidenable, + 0,0,&xtensa_mask26,0,0,0) + XTREG(258,2104, 1, 4, 4,0x2016,0x0006, 0, 5,0x1010,divzeroenable, + 0,0,&xtensa_mask27,0,0,0) + XTREG(259,2108, 1, 4, 4,0x2017,0x0006, 0, 5,0x1010,overflowenable, + 0,0,&xtensa_mask28,0,0,0) + XTREG(260,2112, 1, 4, 4,0x2018,0x0006, 0, 5,0x1010,underflowenable, + 0,0,&xtensa_mask29,0,0,0) + XTREG(261,2116, 1, 4, 4,0x2019,0x0006, 0, 5,0x1010,inexactenable, + 0,0,&xtensa_mask30,0,0,0) + XTREG(262,2120, 1, 4, 4,0x201a,0x0006, 0, 5,0x1010,invalidflag, + 0,0,&xtensa_mask31,0,0,0) + XTREG(263,2124, 1, 4, 4,0x201b,0x0006, 0, 5,0x1010,divzeroflag, + 0,0,&xtensa_mask32,0,0,0) + XTREG(264,2128, 1, 4, 4,0x201c,0x0006, 0, 5,0x1010,overflowflag, + 0,0,&xtensa_mask33,0,0,0) + XTREG(265,2132, 1, 4, 4,0x201d,0x0006, 0, 5,0x1010,underflowflag, + 0,0,&xtensa_mask34,0,0,0) + XTREG(266,2136, 1, 4, 4,0x201e,0x0006, 0, 5,0x1010,inexactflag, + 0,0,&xtensa_mask35,0,0,0) + XTREG(267,2140,20, 4, 4,0x201f,0x0006, 0, 5,0x1010,fpreserved20, + 0,0,&xtensa_mask36,0,0,0) + XTREG(268,2144,20, 4, 4,0x2020,0x0006, 0, 5,0x1010,fpreserved20a, + 0,0,&xtensa_mask37,0,0,0) + XTREG(269,2148, 5, 4, 4,0x2021,0x0006, 0, 5,0x1010,fpreserved5, + 0,0,&xtensa_mask38,0,0,0) + XTREG(270,2152, 7, 4, 4,0x2022,0x0006, 0, 5,0x1010,fpreserved7, + 0,0,&xtensa_mask39,0,0,0) + XTREG(271,2156,128,16, 4,0x2023,0x0006, 2, 5,0x0210,max_reg, + 0,0,&xtensa_mask40,0,0,0) + XTREG(272,2172,128,16, 4,0x2024,0x0006, 2, 5,0x0210,arg_max_reg, + 0,0,&xtensa_mask41,0,0,0) + XTREG(273,2188,128,16, 4,0x2025,0x0006, 2, 5,0x0210,nco_counter, + 0,0,&xtensa_mask42,0,0,0) + XTREG(274,2204,768,96, 4,0x2026,0x0006, 2, 5,0x0210,llr_buf, + 0,0,&xtensa_mask43,0,0,0) + XTREG(275,2300,256,32, 4,0x2027,0x0006, 2, 5,0x0210,smod_buf, + 0,0,&xtensa_mask44,0,0,0) + XTREG_END diff --git a/target/xtensa/core-dsp3400/xtensa-modules.c.inc b/target/xtensa/core-dsp3400/xtensa-modules.c.inc new file mode 100644 index 0000000000000000000000000000000000000000..28ea3d75fef03a2e1f819f5d0f49d6221b549e70 --- /dev/null +++ b/target/xtensa/core-dsp3400/xtensa-modules.c.inc @@ -0,0 +1,171906 @@ +/* Xtensa configuration-specific ISA information. + + Copyright (c) 2003-2010 Tensilica Inc. + + 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 "xtensa-isa.h" +#include "xtensa-isa-internal.h" + + +/* Sysregs. */ + +static xtensa_sysreg_internal sysregs[] = { + { "LBEG", 0, 0 }, + { "LEND", 1, 0 }, + { "LCOUNT", 2, 0 }, + { "BR", 4, 0 }, + { "MMID", 89, 0 }, + { "DDR", 104, 0 }, + { "176", 176, 0 }, + { "208", 208, 0 }, + { "INTERRUPT", 226, 0 }, + { "INTCLEAR", 227, 0 }, + { "CCOUNT", 234, 0 }, + { "PRID", 235, 0 }, + { "ICOUNT", 236, 0 }, + { "CCOMPARE0", 240, 0 }, + { "CCOMPARE1", 241, 0 }, + { "VECBASE", 231, 0 }, + { "EPC1", 177, 0 }, + { "EPC2", 178, 0 }, + { "EPC3", 179, 0 }, + { "EPC4", 180, 0 }, + { "EPC5", 181, 0 }, + { "EPC6", 182, 0 }, + { "EXCSAVE1", 209, 0 }, + { "EXCSAVE2", 210, 0 }, + { "EXCSAVE3", 211, 0 }, + { "EXCSAVE4", 212, 0 }, + { "EXCSAVE5", 213, 0 }, + { "EXCSAVE6", 214, 0 }, + { "EPS2", 194, 0 }, + { "EPS3", 195, 0 }, + { "EPS4", 196, 0 }, + { "EPS5", 197, 0 }, + { "EPS6", 198, 0 }, + { "EXCCAUSE", 232, 0 }, + { "DEPC", 192, 0 }, + { "EXCVADDR", 238, 0 }, + { "WINDOWBASE", 72, 0 }, + { "WINDOWSTART", 73, 0 }, + { "SAR", 3, 0 }, + { "LITBASE", 5, 0 }, + { "PS", 230, 0 }, + { "INTENABLE", 228, 0 }, + { "DBREAKA0", 144, 0 }, + { "DBREAKC0", 160, 0 }, + { "DBREAKA1", 145, 0 }, + { "DBREAKC1", 161, 0 }, + { "IBREAKA0", 128, 0 }, + { "IBREAKA1", 129, 0 }, + { "IBREAKENABLE", 96, 0 }, + { "ICOUNTLEVEL", 237, 0 }, + { "DEBUGCAUSE", 233, 0 }, + { "CPENABLE", 224, 0 }, + { "SCOMPARE1", 12, 0 }, + { "ATOMCTL", 99, 0 }, + { "THREADPTR", 231, 1 }, + { "FCR", 232, 1 }, + { "FSR", 233, 1 }, + { "EXPSTATE", 0, 1 }, + { "SOV", 1, 1 }, + { "SAT_MODE", 2, 1 }, + { "SAR0", 3, 1 }, + { "SAR1", 4, 1 }, + { "SAR2", 5, 1 }, + { "SAR3", 6, 1 }, + { "HSAR0", 7, 1 }, + { "HSAR1", 8, 1 }, + { "HSAR2", 9, 1 }, + { "HSAR3", 10, 1 }, + { "MAX_REG_0", 11, 1 }, + { "MAX_REG_1", 12, 1 }, + { "MAX_REG_2", 13, 1 }, + { "MAX_REG_3", 14, 1 }, + { "ARG_MAX_REG_0", 15, 1 }, + { "ARG_MAX_REG_1", 16, 1 }, + { "ARG_MAX_REG_2", 17, 1 }, + { "ARG_MAX_REG_3", 18, 1 }, + { "NCO_COUNTER_0", 19, 1 }, + { "NCO_COUNTER_1", 20, 1 }, + { "NCO_COUNTER_2", 21, 1 }, + { "NCO_COUNTER_3", 22, 1 }, + { "INTERP_EXT_N", 23, 1 }, + { "INTERP_EXT_L", 24, 1 }, + { "LLR_BUF_0", 25, 1 }, + { "LLR_BUF_1", 26, 1 }, + { "LLR_BUF_2", 27, 1 }, + { "LLR_BUF_3", 28, 1 }, + { "LLR_BUF_4", 29, 1 }, + { "LLR_BUF_5", 30, 1 }, + { "LLR_BUF_6", 31, 1 }, + { "LLR_BUF_7", 32, 1 }, + { "LLR_BUF_8", 33, 1 }, + { "LLR_BUF_9", 34, 1 }, + { "LLR_BUF_10", 35, 1 }, + { "LLR_BUF_11", 36, 1 }, + { "LLR_BUF_12", 37, 1 }, + { "LLR_BUF_13", 38, 1 }, + { "LLR_BUF_14", 39, 1 }, + { "LLR_BUF_15", 40, 1 }, + { "LLR_BUF_16", 41, 1 }, + { "LLR_BUF_17", 42, 1 }, + { "LLR_BUF_18", 43, 1 }, + { "LLR_BUF_19", 44, 1 }, + { "LLR_BUF_20", 45, 1 }, + { "LLR_BUF_21", 46, 1 }, + { "LLR_BUF_22", 47, 1 }, + { "LLR_BUF_23", 48, 1 }, + { "SMOD_BUF_0", 49, 1 }, + { "SMOD_BUF_1", 50, 1 }, + { "SMOD_BUF_2", 51, 1 }, + { "SMOD_BUF_3", 52, 1 }, + { "SMOD_BUF_4", 53, 1 }, + { "SMOD_BUF_5", 54, 1 }, + { "SMOD_BUF_6", 55, 1 }, + { "SMOD_BUF_7", 56, 1 }, + { "WEIGHT_REG", 57, 1 }, + { "SCALE_REG", 58, 1 }, + { "LLR_POS", 59, 1 }, + { "SMOD_POS", 60, 1 }, + { "PERM_REG", 61, 1 }, + { "SMOD_OFFSET_TABLE_0", 62, 1 }, + { "SMOD_OFFSET_TABLE_1", 63, 1 }, + { "SMOD_OFFSET_TABLE_2", 64, 1 }, + { "SMOD_OFFSET_TABLE_3", 65, 1 }, + { "PHASOR_N", 66, 1 }, + { "PHASOR_OFFSET", 67, 1 } +}; + +#define NUM_SYSREGS 125 +#define MAX_SPECIAL_REG 241 +#define MAX_USER_REG 233 + + +/* Processor states. */ + +static xtensa_state_internal states[] = { + { "LCOUNT", 32, 0 }, + { "PC", 32, 0 }, + { "ICOUNT", 32, 0 }, + { "DDR", 32, 0 }, + { "INTERRUPT", 13, 0 }, + { "CCOUNT", 32, 0 }, + { "XTSYNC", 1, 0 }, + { "VECBASE", 22, 0 }, + { "EPC1", 32, 0 }, + { "EPC2", 32, 0 }, + { "EPC3", 32, 0 }, + { "EPC4", 32, 0 }, + { "EPC5", 32, 0 }, + { "EPC6", 32, 0 }, + { "EXCSAVE1", 32, 0 }, + { "EXCSAVE2", 32, 0 }, + { "EXCSAVE3", 32, 0 }, + { "EXCSAVE4", 32, 0 }, + { "EXCSAVE5", 32, 0 }, + { "EXCSAVE6", 32, 0 }, + { "EPS2", 13, 0 }, + { "EPS3", 13, 0 }, + { "EPS4", 13, 0 }, + { "EPS5", 13, 0 }, + { "EPS6", 13, 0 }, + { "EXCCAUSE", 6, 0 }, + { "PSINTLEVEL", 4, 0 }, + { "PSUM", 1, 0 }, + { "PSWOE", 1, 0 }, + { "PSEXCM", 1, 0 }, + { "DEPC", 32, 0 }, + { "EXCVADDR", 32, 0 }, + { "WindowBase", 3, 0 }, + { "WindowStart", 8, 0 }, + { "PSCALLINC", 2, 0 }, + { "PSOWB", 4, 0 }, + { "LBEG", 32, 0 }, + { "LEND", 32, 0 }, + { "SAR", 6, 0 }, + { "THREADPTR", 32, 0 }, + { "LITBADDR", 20, 0 }, + { "LITBEN", 1, 0 }, + { "InOCDMode", 1, 0 }, + { "INTENABLE", 13, 0 }, + { "DBREAKA0", 32, 0 }, + { "DBREAKC0", 8, 0 }, + { "DBREAKA1", 32, 0 }, + { "DBREAKC1", 8, 0 }, + { "IBREAKA0", 32, 0 }, + { "IBREAKA1", 32, 0 }, + { "IBREAKENABLE", 2, 0 }, + { "ICOUNTLEVEL", 4, 0 }, + { "DEBUGCAUSE", 6, 0 }, + { "DBNUM", 4, 0 }, + { "CCOMPARE0", 32, 0 }, + { "CCOMPARE1", 32, 0 }, + { "CPENABLE", 4, 0 }, + { "SCOMPARE1", 32, 0 }, + { "ATOMCTL", 6, 0 }, + { "RoundMode", 2, 0 }, + { "InvalidEnable", 1, 0 }, + { "DivZeroEnable", 1, 0 }, + { "OverflowEnable", 1, 0 }, + { "UnderflowEnable", 1, 0 }, + { "InexactEnable", 1, 0 }, + { "InvalidFlag", 1, 0 }, + { "DivZeroFlag", 1, 0 }, + { "OverflowFlag", 1, 0 }, + { "UnderflowFlag", 1, 0 }, + { "InexactFlag", 1, 0 }, + { "FPreserved20", 20, 0 }, + { "FPreserved20a", 20, 0 }, + { "FPreserved5", 5, 0 }, + { "FPreserved7", 7, 0 }, + { "EXPSTATE", 32, XTENSA_STATE_IS_EXPORTED }, + { "SOV", 4, XTENSA_STATE_IS_SHARED_OR }, + { "SAT_MODE", 1, 0 }, + { "SAR0", 6, 0 }, + { "SAR1", 6, 0 }, + { "SAR2", 6, 0 }, + { "SAR3", 6, 0 }, + { "HSAR0", 6, 0 }, + { "HSAR1", 6, 0 }, + { "HSAR2", 6, 0 }, + { "HSAR3", 6, 0 }, + { "MAX_REG", 128, 0 }, + { "ARG_MAX_REG", 128, 0 }, + { "NCO_COUNTER", 128, 0 }, + { "INTERP_EXT_N", 4, 0 }, + { "INTERP_EXT_L", 4, 0 }, + { "LLR_BUF", 768, 0 }, + { "SMOD_BUF", 256, 0 }, + { "WEIGHT_REG", 8, 0 }, + { "SCALE_REG", 5, 0 }, + { "LLR_POS", 6, 0 }, + { "SMOD_POS", 7, 0 }, + { "PERM_REG", 32, 0 }, + { "SMOD_OFFSET_TABLE", 128, 0 }, + { "PHASOR_N", 4, 0 }, + { "PHASOR_OFFSET", 16, 0 } +}; + +#define NUM_STATES 100 + +enum xtensa_state_id { + STATE_LCOUNT, + STATE_PC, + STATE_ICOUNT, + STATE_DDR, + STATE_INTERRUPT, + STATE_CCOUNT, + STATE_XTSYNC, + STATE_VECBASE, + STATE_EPC1, + STATE_EPC2, + STATE_EPC3, + STATE_EPC4, + STATE_EPC5, + STATE_EPC6, + STATE_EXCSAVE1, + STATE_EXCSAVE2, + STATE_EXCSAVE3, + STATE_EXCSAVE4, + STATE_EXCSAVE5, + STATE_EXCSAVE6, + STATE_EPS2, + STATE_EPS3, + STATE_EPS4, + STATE_EPS5, + STATE_EPS6, + STATE_EXCCAUSE, + STATE_PSINTLEVEL, + STATE_PSUM, + STATE_PSWOE, + STATE_PSEXCM, + STATE_DEPC, + STATE_EXCVADDR, + STATE_WindowBase, + STATE_WindowStart, + STATE_PSCALLINC, + STATE_PSOWB, + STATE_LBEG, + STATE_LEND, + STATE_SAR, + STATE_THREADPTR, + STATE_LITBADDR, + STATE_LITBEN, + STATE_InOCDMode, + STATE_INTENABLE, + STATE_DBREAKA0, + STATE_DBREAKC0, + STATE_DBREAKA1, + STATE_DBREAKC1, + STATE_IBREAKA0, + STATE_IBREAKA1, + STATE_IBREAKENABLE, + STATE_ICOUNTLEVEL, + STATE_DEBUGCAUSE, + STATE_DBNUM, + STATE_CCOMPARE0, + STATE_CCOMPARE1, + STATE_CPENABLE, + STATE_SCOMPARE1, + STATE_ATOMCTL, + STATE_RoundMode, + STATE_InvalidEnable, + STATE_DivZeroEnable, + STATE_OverflowEnable, + STATE_UnderflowEnable, + STATE_InexactEnable, + STATE_InvalidFlag, + STATE_DivZeroFlag, + STATE_OverflowFlag, + STATE_UnderflowFlag, + STATE_InexactFlag, + STATE_FPreserved20, + STATE_FPreserved20a, + STATE_FPreserved5, + STATE_FPreserved7, + STATE_EXPSTATE, + STATE_SOV, + STATE_SAT_MODE, + STATE_SAR0, + STATE_SAR1, + STATE_SAR2, + STATE_SAR3, + STATE_HSAR0, + STATE_HSAR1, + STATE_HSAR2, + STATE_HSAR3, + STATE_MAX_REG, + STATE_ARG_MAX_REG, + STATE_NCO_COUNTER, + STATE_INTERP_EXT_N, + STATE_INTERP_EXT_L, + STATE_LLR_BUF, + STATE_SMOD_BUF, + STATE_WEIGHT_REG, + STATE_SCALE_REG, + STATE_LLR_POS, + STATE_SMOD_POS, + STATE_PERM_REG, + STATE_SMOD_OFFSET_TABLE, + STATE_PHASOR_N, + STATE_PHASOR_OFFSET +}; + + +/* Field definitions. */ + +static unsigned +Field_t_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_t_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); +} + +static unsigned +Field_s_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_s_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_r_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_r_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_op2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + return tie_t; +} + +static void +Field_op2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_op1_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + return tie_t; +} + +static void +Field_op1_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_op0_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 28) >> 28); + return tie_t; +} + +static void +Field_op0_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf) | (tie_t << 0); +} + +static unsigned +Field_n_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_n_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_m_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_m_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_sr_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_sr_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_st_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_st_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_thi3_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 24) >> 29); + return tie_t; +} + +static void +Field_thi3_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe0) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2098inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 16) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2098inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff00) | (tie_t << 8); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_sae4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_sae4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld2019_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 12) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2019_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld2100inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 16) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2100inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff00) | (tie_t << 8); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2102inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 16) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2102inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff00) | (tie_t << 8); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2186inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2186inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2185inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2185inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2149inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 17) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2149inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x6000) | (tie_t << 13); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3627inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 10) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 19) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3627inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x1800) | (tie_t << 11); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0x300000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2187inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2187inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2101inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 16) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2101inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff00) | (tie_t << 8); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2103inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 16) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2103inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff00) | (tie_t << 8); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2189inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2189inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2188inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2188inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2104inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 16) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2104inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff00) | (tie_t << 8); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2190inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2190inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2094inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 7) | ((insn[0] << 16) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2094inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0xfe00) | (tie_t << 9); + tie_t = (val << 21) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2105inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 16) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2105inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff00) | (tie_t << 8); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2191inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2191inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2192inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2192inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2194inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2194inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2197inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2197inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2160inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2160inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2173inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 5) | ((insn[0] << 20) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2173inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0xf80) | (tie_t << 7); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2112inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2112inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2199inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2199inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2200inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2200inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2114inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2114inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2113inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2113inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2201inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2201inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2115inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2115inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2215inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2215inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3630inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3630inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); +} + +static unsigned +Field_dsp340050b49a6c_fld2203inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 5) | ((insn[0] << 20) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2203inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0xf80) | (tie_t << 7); + tie_t = (val << 22) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2254_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 25) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2254_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x60) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2116inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2116inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2117inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2117inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2119inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2119inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2048_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 17) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2048_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x7000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2089inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 12) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2089inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80000) | (tie_t << 19); +} + +static unsigned +Field_r2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + return tie_t; +} + +static void +Field_r2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); +} + +static unsigned +Field_bbi4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + return tie_t; +} + +static void +Field_bbi4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3631inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 13) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3631inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x70000) | (tie_t << 16); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2085inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 11) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2085inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x1f0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld2088inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 12) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2088inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0xc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3633inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 14) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3633inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20000) | (tie_t << 17); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2082inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2082inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld2083inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2083inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld2084inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2084inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld2086inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 12) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2086inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0xc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3634_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 14) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3634_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld2156inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 21) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2156inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x700) | (tie_t << 8); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2037_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 21) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2037_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x700) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld2021_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2021_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_sa4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + return tie_t; +} + +static void +Field_sa4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2035_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 21) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2035_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x600) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld2047_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 23) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2047_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x100) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld2225inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2225inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2226inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2226inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2228inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2228inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2230inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2230inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2222inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2222inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld2221inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2221inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2238inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 15) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2238inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18000) | (tie_t << 15); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2239inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 15) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2239inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18000) | (tie_t << 15); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2241inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 15) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2241inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18000) | (tie_t << 15); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2223inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2223inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld2232inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + tie_t = (tie_t << 2) | ((insn[0] << 15) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2232inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18000) | (tie_t << 15); + tie_t = (val << 27) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld2234inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + tie_t = (tie_t << 2) | ((insn[0] << 15) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2234inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18000) | (tie_t << 15); + tie_t = (val << 27) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld2237inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + tie_t = (tie_t << 2) | ((insn[0] << 15) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2237inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18000) | (tie_t << 15); + tie_t = (val << 27) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld2240inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + tie_t = (tie_t << 2) | ((insn[0] << 15) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2240inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18000) | (tie_t << 15); + tie_t = (val << 27) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld2229inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2229inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2224inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2224inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld2227inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2227inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld2231inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2231inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2247inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2247inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2091inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2091inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2153inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2153inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3635inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3635inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld2154inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2154inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3636inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3636inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld2155inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2155inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3637inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3637inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld2134inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + tie_t = (tie_t << 2) | ((insn[0] << 23) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2134inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x180) | (tie_t << 7); + tie_t = (val << 27) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2050_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 19) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2050_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x1e00) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld2096inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 16) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2096inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff00) | (tie_t << 8); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2244inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2244inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2245inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2245inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2246inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2246inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3638inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3638inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2235inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2235inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2157inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2157inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2253inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 25) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2253inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x60) | (tie_t << 5); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3639inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3639inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2255inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2255inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3640inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3640inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2171inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 5) | ((insn[0] << 20) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2171inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0xf80) | (tie_t << 7); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 22) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2172inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 5) | ((insn[0] << 20) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2172inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0xf80) | (tie_t << 7); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 22) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2174inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 5) | ((insn[0] << 20) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2174inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0xf80) | (tie_t << 7); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 22) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2158inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2158inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2205inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2205inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2159inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2159inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2161inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2161inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2168inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2168inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2136inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + tie_t = (tie_t << 2) | ((insn[0] << 23) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2136inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x180) | (tie_t << 7); + tie_t = (val << 27) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2090inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2090inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2184inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 5) | ((insn[0] << 20) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2184inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0xf80) | (tie_t << 7); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3642inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3642inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2252inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 25) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2252inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x70) | (tie_t << 4); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3643inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3643inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2092inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 7) | ((insn[0] << 16) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2092inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0xfe00) | (tie_t << 9); + tie_t = (val << 21) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2216inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 21) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2216inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x600) | (tie_t << 9); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3644inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 10) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3644inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0x300000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2217inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 8) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 21) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2217inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x600) | (tie_t << 9); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x800000) | (tie_t << 23); +} + +static unsigned +Field_dsp340050b49a6c_fld3645inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 9) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3645inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 27) >> 29; + insn[0] = (insn[0] & ~0x700000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2208inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2208inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2209inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2209inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2210inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2210inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2212inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2212inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2213inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 21) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2213inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x600) | (tie_t << 9); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3647inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3647inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2214inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2214inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3648inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3648inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2120inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 12) | ((insn[0] << 16) >> 20); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2120inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0xfff0) | (tie_t << 4); + tie_t = (val << 16) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2122inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 12) | ((insn[0] << 16) >> 20); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2122inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0xfff0) | (tie_t << 4); + tie_t = (val << 16) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2123inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 12) | ((insn[0] << 16) >> 20); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2123inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0xfff0) | (tie_t << 4); + tie_t = (val << 16) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2125inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 12) | ((insn[0] << 16) >> 20); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2125inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0xfff0) | (tie_t << 4); + tie_t = (val << 16) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2129inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 5) | ((insn[0] << 16) >> 27); + tie_t = (tie_t << 5) | ((insn[0] << 23) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2129inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x1f0) | (tie_t << 4); + tie_t = (val << 22) >> 27; + insn[0] = (insn[0] & ~0xf800) | (tie_t << 11); + tie_t = (val << 18) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2124inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 12) | ((insn[0] << 16) >> 20); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2124inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0xfff0) | (tie_t << 4); + tie_t = (val << 16) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2126inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 12) | ((insn[0] << 16) >> 20); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2126inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0xfff0) | (tie_t << 4); + tie_t = (val << 16) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2127inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 12) | ((insn[0] << 16) >> 20); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2127inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0xfff0) | (tie_t << 4); + tie_t = (val << 16) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2128inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 12) | ((insn[0] << 16) >> 20); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2128inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0xfff0) | (tie_t << 4); + tie_t = (val << 16) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2131inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 5) | ((insn[0] << 16) >> 27); + tie_t = (tie_t << 5) | ((insn[0] << 23) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2131inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x1f0) | (tie_t << 4); + tie_t = (val << 22) >> 27; + insn[0] = (insn[0] & ~0xf800) | (tie_t << 11); + tie_t = (val << 18) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2138inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 16) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2138inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff00) | (tie_t << 8); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2146inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2146inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3649inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 19) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3649inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x1f00) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld2147inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 17) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2147inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x6000) | (tie_t << 13); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3650inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 5) | ((insn[0] << 19) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3650inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x1f00) | (tie_t << 8); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2139inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 16) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2139inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff00) | (tie_t << 8); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2140inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 16) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2140inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff00) | (tie_t << 8); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2142inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 16) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2142inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff00) | (tie_t << 8); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2248inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2248inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3651inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3651inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2250inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2250inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3653inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3653inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2257inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2257inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld3654inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 15) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3654inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0x18000) | (tie_t << 15); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2249inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2249inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3655inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3655inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2107inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2107inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); + tie_t = (val << 21) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2118inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2118inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); + tie_t = (val << 21) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2108inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2108inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); + tie_t = (val << 21) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2109inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2109inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); + tie_t = (val << 21) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2111inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2111inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); + tie_t = (val << 21) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2110inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2110inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); + tie_t = (val << 21) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2145inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 5) | ((insn[0] << 16) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2145inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0xf800) | (tie_t << 11); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2141inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 16) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2141inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff00) | (tie_t << 8); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2143inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 16) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2143inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff00) | (tie_t << 8); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2144inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 7) | ((insn[0] << 16) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2144inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0xfe00) | (tie_t << 9); + tie_t = (val << 21) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2204inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 21) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2204inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x700) | (tie_t << 8); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3656inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3656inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2195inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2195inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2196inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2196inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2198inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2198inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2169inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 5) | ((insn[0] << 20) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2169inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0xf80) | (tie_t << 7); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2220inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2220inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2106inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2106inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2151inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 8) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 17) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2151inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x6000) | (tie_t << 13); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x800000) | (tie_t << 23); +} + +static unsigned +Field_dsp340050b49a6c_fld3657inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 9) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 24) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3657inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe0) | (tie_t << 5); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x700000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2251inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 25) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2251inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x70) | (tie_t << 4); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3658inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3658inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2206inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2206inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2202inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 5) | ((insn[0] << 20) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2202inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0xf80) | (tie_t << 7); + tie_t = (val << 22) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2095inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 7) | ((insn[0] << 16) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2095inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0xfe00) | (tie_t << 9); + tie_t = (val << 21) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2132inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + tie_t = (tie_t << 3) | ((insn[0] << 24) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2132inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe0) | (tie_t << 5); + tie_t = (val << 26) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); + tie_t = (val << 22) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3659inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3659inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2099inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 7) | ((insn[0] << 16) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2099inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0xfe00) | (tie_t << 9); + tie_t = (val << 21) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2137inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2137inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2133inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2133inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); + tie_t = (val << 27) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3660inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3660inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2175inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2175inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 19) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2177inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2177inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 19) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2242inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 15) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2242inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18000) | (tie_t << 15); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3661inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3661inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2162inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2162inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2164inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2164inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2163inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2163inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2218inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2218inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2219inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2219inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2207inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2207inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2211inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2211inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2165inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2165inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2166inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2166inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2178inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2178inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 19) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2180inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2180inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 19) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2179inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2179inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 19) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2181inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2181inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 19) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2167inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2167inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2193inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2193inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3662inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3662inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2236inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2236inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2243inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2243inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2182inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2182inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 19) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2183inst_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 20) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2183inst_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0) | (tie_t << 4); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 19) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_op0_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 28) >> 28); + return tie_t; +} + +static void +Field_op0_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf) | (tie_t << 0); +} + +static unsigned +Field_t_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_t_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); +} + +static unsigned +Field_r_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_r_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_op0_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 28) >> 28); + return tie_t; +} + +static void +Field_op0_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf) | (tie_t << 0); +} + +static unsigned +Field_z_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_z_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); +} + +static unsigned +Field_i_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_i_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_s_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_s_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_sae_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + return tie_t; +} + +static void +Field_sae_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_op0_s3_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s3_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); +} + +static unsigned +Field_dsp340050b49a6c_fld2260gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2260gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 23) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2258gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2258gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2282gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2282gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2281gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2281gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2266gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 14) | ((insn[0] << 13) >> 18); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2266gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 17) >> 18; + insn[0] = (insn[0] & ~0x7ffe0) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2302_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 27) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2302_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2312gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2312gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2386_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2386_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2283gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2283gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2286gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2286gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2287gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2287gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2289gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2289gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2293gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2293gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2288gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2288gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2290gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2290gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2359gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 11) | ((insn[0] << 19) >> 21); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2359gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 21) >> 21; + insn[0] = (insn[0] & ~0x1ffc) | (tie_t << 2); + tie_t = (val << 20) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2384_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2384_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2361gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 11) | ((insn[0] << 19) >> 21); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2361gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 21) >> 21; + insn[0] = (insn[0] & ~0x1ffc) | (tie_t << 2); + tie_t = (val << 20) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2362gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 10) | ((insn[0] << 19) >> 22); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2362gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 22) >> 22; + insn[0] = (insn[0] & ~0x1ff8) | (tie_t << 3); + tie_t = (val << 21) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3663gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3663gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2364gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 19) >> 30); + tie_t = (tie_t << 7) | ((insn[0] << 22) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2364gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x3f8) | (tie_t << 3); + tie_t = (val << 23) >> 30; + insn[0] = (insn[0] & ~0x1800) | (tie_t << 11); + tie_t = (val << 22) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3664gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3664gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2366gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + tie_t = (tie_t << 7) | ((insn[0] << 22) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2366gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x3f8) | (tie_t << 3); + tie_t = (val << 24) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3665gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3665gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2308gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2308gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2259gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2259gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 25) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2262gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 13) | ((insn[0] << 13) >> 19); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2262gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 19) >> 19; + insn[0] = (insn[0] & ~0x7ffc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2284gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2284gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2275gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2275gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 25) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2354gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2354gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2333gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2333gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2310gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2310gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 25) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3667gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3667gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2357gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2357gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2376gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 23) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2376gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x180) | (tie_t << 7); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 25) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2313_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2313_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld2343gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2343gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2342gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2342gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2344gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2344gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2345gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2345gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2346gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2346gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2373gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2373gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2374gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2374gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2375gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2375gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2335gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2335gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2339gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2339gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2334gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2334gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2336gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2336gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2337gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2337gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2338gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2338gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2340gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2340gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2341gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2341gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2369gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2369gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3668gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3668gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2280gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2280gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2309gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2309gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2261gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 13) >> 20); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2261gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0x7ff80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2321gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2321gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2322gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2322gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2355gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2355gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2324gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2324gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2372gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2372gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3669gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3669gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2263gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 17) | ((insn[0] << 13) >> 15); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2263gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 15) >> 15; + insn[0] = (insn[0] & ~0x7fffc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2044_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 25) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2044_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2264gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 14) | ((insn[0] << 13) >> 18); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2264gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 17) >> 18; + insn[0] = (insn[0] & ~0x7ffe0) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2368gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2368gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3670gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3670gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2291gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2291gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2292gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2292gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2294gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2294gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2295gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2295gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2297gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2297gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2296gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2296gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2301gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 2) | ((insn[0] << 27) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2301gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18) | (tie_t << 3); + tie_t = (val << 25) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2272_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2272_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2277gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2277gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2279gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2279gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2278gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2278gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2267gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2267gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2268gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2268gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2269gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2269gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2271gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 28) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2271gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8) | (tie_t << 3); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 21) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2305_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2305_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); +} + +static unsigned +Field_dsp340050b49a6c_fld2270gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2270gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2273gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 28) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2273gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8) | (tie_t << 3); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 21) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2298gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2298gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2299gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2299gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2300gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2300gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2303gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 2) | ((insn[0] << 27) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2303gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18) | (tie_t << 3); + tie_t = (val << 25) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3671gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 22) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3671gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0x3e0) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2379gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 23) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2379gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x100) | (tie_t << 8); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3673gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3673gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld2274gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 13) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2274gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x7f800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2056_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2056_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2306gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2306gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2304gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2304gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3674gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 22) >> 27); + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3674gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); + tie_t = (val << 25) >> 27; + insn[0] = (insn[0] & ~0x3e0) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2353gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2353gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2371gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2371gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3675gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3675gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2314gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2314gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2316gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2316gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2317gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2317gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2319gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2319gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2378gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 23) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2378gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x180) | (tie_t << 7); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 25) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3676gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3676gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld2323gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2323gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2331gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2331gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2347gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2347gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2383gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2383gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3678gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 19) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3678gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x1f00) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld2318gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2318gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2332gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2332gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2348gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2348gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2349gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2349gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2351gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2351gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2370gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2370gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2032_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2032_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2320gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2320gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2350gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2350gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2352gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2352gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2325gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2325gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2327gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2327gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2326gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2326gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2328gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2328gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2356gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2356gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2329gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2329gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2381gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2381gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3666_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3666_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2330gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2330gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2385gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2385gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2387gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2387gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2388gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 23) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2388gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x180) | (tie_t << 7); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3679gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3679gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld2358gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2358gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2389gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 23) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2389gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x100) | (tie_t << 8); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3680gp_slot2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3680gp_slot2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld2399gp_slot1_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2399gp_slot1_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_op0_s4_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 15) >> 29); + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s4_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); + tie_t = (val << 27) >> 29; + insn[0] = (insn[0] & ~0x1c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3681gp_slot1_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 19) >> 25); + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3681gp_slot1_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); + tie_t = (val << 23) >> 25; + insn[0] = (insn[0] & ~0x1fc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2395gp_slot1_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2395gp_slot1_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2394gp_slot1_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2394gp_slot1_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2397gp_slot1_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2397gp_slot1_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2400gp_slot1_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2400gp_slot1_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3683gp_slot1_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3683gp_slot1_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld2402gp_slot1_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2402gp_slot1_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2403gp_slot1_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 23) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2403gp_slot1_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x180) | (tie_t << 7); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3684gp_slot1_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3684gp_slot1_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld2405gp_slot1_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 23) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2405gp_slot1_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x100) | (tie_t << 8); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3686gp_slot1_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3686gp_slot1_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld2398gp_slot1_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2398gp_slot1_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_sae_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + return tie_t; +} + +static void +Field_sae_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_op0_s5_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s5_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); +} + +static unsigned +Field_dsp340050b49a6c_fld2447gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 13) >> 29); + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2447gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); + tie_t = (val << 27) >> 29; + insn[0] = (insn[0] & ~0x70000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3688gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3688gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2449gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 13) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2449gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0x60000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3689gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 15) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3689gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2418gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2418gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 23) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2462_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2462_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2464gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2464gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2454gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2454gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2436gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2436gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 21) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3690gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3690gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2438gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 13) | ((insn[0] << 13) >> 19); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2438gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 19) >> 19; + insn[0] = (insn[0] & ~0x7ffc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2437gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 13) >> 20); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2437gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0x7ff80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2526gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2526gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2460gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2460gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2459gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2459gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2445_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 13) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2445_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x78000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2427gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2427gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 21) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2420gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2420gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2424gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2424gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2425gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2425gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2480gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2480gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2479gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2479gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2419gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2419gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 22) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2481gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2481gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2483gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2483gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2487gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2487gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2482gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2482gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2426gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2426gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2484gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2484gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2422gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2422gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2429gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2429gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2485gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2485gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2486gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2486gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2488gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2488gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2531gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2531gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3691gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 23) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3691gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x1e0) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2493gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2493gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2506gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 2) | ((insn[0] << 27) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2506gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18) | (tie_t << 3); + tie_t = (val << 25) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3692gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 22) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3692gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x3e0) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2494gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2494gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2407gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2407gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2413gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2413gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2415gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2415gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2417gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2417gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2441gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2441gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3693gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3693gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2409gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2409gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2410gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2410gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2416gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2416gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2411gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2411gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2412gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2412gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2453gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2453gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2451gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2451gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2452gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2452gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2516gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 13) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2516gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x78000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2512gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 13) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2512gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x78000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2514gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 13) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2514gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x78000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2515gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 13) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2515gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x78000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2443gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 13) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2443gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x7f000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2444gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 13) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2444gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x78000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2067_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2067_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2439gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 13) >> 20); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2439gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 19) >> 20; + insn[0] = (insn[0] & ~0x7ff80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld3695gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3695gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2423gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2423gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2508gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2508gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2058_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 14) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2058_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2509gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2509gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2510gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2510gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3696gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 14) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3696gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x38000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2496gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2496gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_s8_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_s8_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2527gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2527gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2036_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2036_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2528gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2528gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3697gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 25) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3697gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x60) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2523gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2523gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); + tie_t = (val << 24) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3698gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3698gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld2455gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2455gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2456gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2456gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2458gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2458gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2457gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2457gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2440gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 13) >> 20); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2440gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 19) >> 20; + insn[0] = (insn[0] & ~0x7ff80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2524gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2524gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); + tie_t = (val << 25) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3699gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 25) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3699gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x60) | (tie_t << 5); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld2503gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2503gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2507gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 13) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 27) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2507gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18) | (tie_t << 3); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0x60000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3700gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 15) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3700gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0x18000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2498gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2498gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2500gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2500gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2501gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2501gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2502gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2502gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2504gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2504gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2505gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 27) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2505gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18) | (tie_t << 3); + tie_t = (val << 24) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2433gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2433gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2430gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2430gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2431gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2431gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2432gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2432gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2434gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2434gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2435gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2435gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2517gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2517gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 24) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2518gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2518gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 24) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2519gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2519gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 24) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2520gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2520gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 24) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2489gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2489gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2491gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2491gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2490gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2490gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2492gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2492gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2529gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2529gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 25) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3702gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 24) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3702gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe0) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2468gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2468gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2470gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2470gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2448_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 13) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2448_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x70000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3703gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3703gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 27) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2521gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2521gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); + tie_t = (val << 24) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2530_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2530_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld2461gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2461gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2463gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2463gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2497gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2497gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2499gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2499gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2465gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2465gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2467gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2467gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2471gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2471gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2473gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2473gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2477gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2477gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 21) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3705gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3705gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2472gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2472gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2495gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 13) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2495gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x70000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3706gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3706gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2466gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2466gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2474gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2474gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2475gp_slot0_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2475gp_slot0_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 19) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2595dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 12) >> 25); + tie_t = (tie_t << 9) | ((insn[0] << 21) >> 23); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2595dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 23) >> 23; + insn[0] = (insn[0] & ~0x7fc) | (tie_t << 2); + tie_t = (val << 16) >> 25; + insn[0] = (insn[0] & ~0xfe000) | (tie_t << 13); +} + +static unsigned +Field_op0_s6_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s6_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); +} + +static unsigned +Field_dsp340050b49a6c_fld3708dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 19) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3708dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x1800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2579dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2579dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2580dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2580dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2582dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2582dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2586dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2586dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2581dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2581dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2583dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2583dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2599dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 10) | ((insn[0] << 20) >> 22); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2599dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 22) >> 22; + insn[0] = (insn[0] & ~0xffc) | (tie_t << 2); + tie_t = (val << 20) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3709dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3709dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2614_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2614_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 22) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2604dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2604dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 23) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3710dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3710dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2606dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2606dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 24) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3711dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3711dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2601dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 10) | ((insn[0] << 20) >> 22); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2601dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 22) >> 22; + insn[0] = (insn[0] & ~0xffc) | (tie_t << 2); + tie_t = (val << 20) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2602dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2602dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); + tie_t = (val << 21) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3713dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3713dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2645dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 12) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2645dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3714dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 14) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3714dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x30000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld2658dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2658dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3716dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 12) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3716dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0xe0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3717dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 12) >> 29); + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3717dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); + tie_t = (val << 26) >> 29; + insn[0] = (insn[0] & ~0xe0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld2636dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 14) | ((insn[0] << 12) >> 18); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2636dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 18) >> 18; + insn[0] = (insn[0] & ~0xfffc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2577dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2577dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2635dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2635dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3719dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3719dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld2571dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2571dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2547dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2547dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2646dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 12) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2646dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x80000) | (tie_t << 19); +} + +static unsigned +Field_dsp340050b49a6c_fld3721dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 13) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3721dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x70000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld2574dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2574dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2655dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2655dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2029_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2029_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2557dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2557dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2558dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2558dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2560dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2560dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2559dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2559dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2561dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2561dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2562dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2562dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2563dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2563dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2647dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2647dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2549dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2549dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2550dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2550dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2552dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2552dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2556dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2556dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2551dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2551dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2553dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2553dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2554dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2554dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2555dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2555dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2573dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2573dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2628dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 12) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2628dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x80000) | (tie_t << 19); +} + +static unsigned +Field_dsp340050b49a6c_fld3722_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 13) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3722_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x70000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld2642dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 12) >> 23); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2642dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 22) >> 23; + insn[0] = (insn[0] & ~0xff800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2605_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2605_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2539dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2539dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2578_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2578_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2541dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2541dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2572dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2572dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2542dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2542dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3723dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 18) >> 22); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3723dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 22) >> 22; + insn[0] = (insn[0] & ~0x3ff0) | (tie_t << 4); +} + +static unsigned +Field_dsp340050b49a6c_fld2591dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 18) | ((insn[0] << 12) >> 14); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2591dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 14) >> 14; + insn[0] = (insn[0] & ~0xffffc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2596dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 12) >> 29); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2596dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 19) >> 29; + insn[0] = (insn[0] & ~0xe0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3724dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3724dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld2592dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 12) >> 25); + tie_t = (tie_t << 9) | ((insn[0] << 21) >> 23); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2592dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 23) >> 23; + insn[0] = (insn[0] & ~0x7fc) | (tie_t << 2); + tie_t = (val << 16) >> 25; + insn[0] = (insn[0] & ~0xfe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2598dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2598dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2584dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2584dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2585dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2585dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2587dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2587dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2588dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2588dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2590dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2590dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2589dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2589dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2608dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2608dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2609dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2609dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2610dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2610dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2626dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 12) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2626dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 25) >> 30; + insn[0] = (insn[0] & ~0xc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3715_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 14) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3715_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld2613dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2613dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 19) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2616dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2616dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 19) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2621dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2621dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 19) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2615dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2615dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 19) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2617dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2617dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 19) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2618dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2618dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 19) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2637dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 12) >> 20); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2637dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 19) >> 20; + insn[0] = (insn[0] & ~0xfff00) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld3725dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3725dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2641dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 11) | ((insn[0] << 12) >> 21); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2641dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 21) >> 21; + insn[0] = (insn[0] & ~0xffe00) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld3726dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3726dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2619dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2619dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 18) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2620dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2620dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 18) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2622dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2622dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 19) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2047_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2047_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2623dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 12) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2623dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0xff800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3727dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3727dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2654dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 5) | ((insn[0] << 21) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2654dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c0) | (tie_t << 6); + tie_t = (val << 25) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3728dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3728dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2611dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 12) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2611dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0xff800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2612_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 12) >> 23); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2612_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 23) >> 23; + insn[0] = (insn[0] & ~0xff800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2624dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 12) >> 24); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2624dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 21) >> 24; + insn[0] = (insn[0] & ~0xff000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3729dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3729dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2625_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 12) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2625_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3731dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3731dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2643dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 12) >> 23); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2643dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 22) >> 23; + insn[0] = (insn[0] & ~0xff800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2640dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 12) >> 20); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2640dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 19) >> 20; + insn[0] = (insn[0] & ~0xfff00) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld2569dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2569dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2632dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2632dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_t_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_t_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2532dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2532dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2644dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 12) >> 29); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2644dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 27) >> 29; + insn[0] = (insn[0] & ~0xe0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3732dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3732dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld2533dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2533dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2534dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2534dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2536dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2536dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2652dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 5) | ((insn[0] << 21) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2652dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c0) | (tie_t << 6); + tie_t = (val << 25) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3718_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3718_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2540dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2540dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2548dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2548dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2564dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2564dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2657dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2657dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2535dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2535dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2537dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2537dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2565dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2565dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2566dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2566dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2568dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2568dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2630dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2630dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2032_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2032_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2538dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2538dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2633dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2633dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3733dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3733dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2567dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2567dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2544dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2544dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2543dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2543dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2545dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2545dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2546dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2546dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2575dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2575dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2049_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2049_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2648dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2648dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2649dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2649dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2651dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2651dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2656dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2656dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3712_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3712_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2576dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2576dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2650dot_slot2_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2650dot_slot2_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_op0_s7_Slot_dot_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 12) >> 29); + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s7_Slot_dot_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); + tie_t = (val << 27) >> 29; + insn[0] = (insn[0] & ~0xe0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3734dot_slot1_Slot_dot_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 15) | ((insn[0] << 15) >> 17); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3734dot_slot1_Slot_dot_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 17) >> 17; + insn[0] = (insn[0] & ~0x1fffc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2068_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2068_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_op0_s8_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 15) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s8_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0x18000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2668dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2668dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2666dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 17) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2666dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x6000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2674dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2674dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2688dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 17) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2688dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 25) >> 30; + insn[0] = (insn[0] & ~0x6000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3735dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 19) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3735dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x1800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2705dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2705dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3737dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3737dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2677dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2677dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2678dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2678dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2679dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2679dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2690dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2690dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2680dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2680dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_t_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_t_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2697dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2697dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3738dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3738dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2667dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 17) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2667dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x7000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2704dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 17) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2704dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x7800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3739dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 21) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3739dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0x7e0) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2689dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2689dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_r_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_r_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2669dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2669dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2671dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2671dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2675dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2675dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2672dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2672dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2673dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2673dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2676dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2676dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2682dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2682dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2686dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 17) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2686dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 25) >> 30; + insn[0] = (insn[0] & ~0x6000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3736_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 19) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3736_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x1800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2681dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2681dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2683dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2683dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2684dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2684dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2685dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2685dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2699dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2699dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3740dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3740dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2692dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2692dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2693dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2693dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 24) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2695dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2695dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 25) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3741dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3741dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3742dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3742dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2700dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2700dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2702dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2702dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2047_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2047_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2701dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2701dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2703dot_slot0_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2703dot_slot0_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_sae_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + return tie_t; +} + +static void +Field_sae_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_op0_s9_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s9_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); +} + +static unsigned +Field_dsp340050b49a6c_fld2707pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2707pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 23) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2817_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2817_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2739pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2739pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3744pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3744pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2717pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2717pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2713pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 14) | ((insn[0] << 13) >> 18); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2713pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 17) >> 18; + insn[0] = (insn[0] & ~0x7ffe0) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld3745pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 27) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3745pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18) | (tie_t << 3); +} + +static unsigned +Field_t_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_t_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2718pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2718pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2721pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2721pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2722pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2722pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2724pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2724pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2728pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2728pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2736pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2736pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 22) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2819_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2819_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2723pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2723pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2793pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 11) | ((insn[0] << 19) >> 21); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2793pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 21) >> 21; + insn[0] = (insn[0] & ~0x1ffc) | (tie_t << 2); + tie_t = (val << 20) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2795pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 11) | ((insn[0] << 19) >> 21); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2795pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 21) >> 21; + insn[0] = (insn[0] & ~0x1ffc) | (tie_t << 2); + tie_t = (val << 20) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2796pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 10) | ((insn[0] << 19) >> 22); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2796pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 22) >> 22; + insn[0] = (insn[0] & ~0x1ff8) | (tie_t << 3); + tie_t = (val << 21) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3746pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3746pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2798pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 19) >> 30); + tie_t = (tie_t << 7) | ((insn[0] << 22) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2798pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x3f8) | (tie_t << 3); + tie_t = (val << 23) >> 30; + insn[0] = (insn[0] & ~0x1800) | (tie_t << 11); + tie_t = (val << 22) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3747pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3747pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2801pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + tie_t = (tie_t << 7) | ((insn[0] << 22) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2801pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x3f8) | (tie_t << 3); + tie_t = (val << 24) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3749pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3749pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2743pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2743pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3750pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3750pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2706pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 13) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2706pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x7f000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2709pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 13) | ((insn[0] << 13) >> 19); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2709pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 19) >> 19; + insn[0] = (insn[0] & ~0x7ffc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2719pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2719pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2715pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2715pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 25) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2788pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2788pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2747pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2747pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2791pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2791pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2775pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2775pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2777pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2777pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2776pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2776pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2778pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2778pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2779pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2779pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2780pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2780pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2810pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2810pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2811pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2811pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2767pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2767pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2769pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2769pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2773pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2773pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2768pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2768pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2770pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2770pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2771pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2771pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2772pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2772pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2774pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2774pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2805pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2805pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3751pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3751pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2741pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2741pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2746pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2746pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3752pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 20) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3752pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0xf80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2755pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2755pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2756pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2756pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2789pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2789pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2758pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2758pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2809pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2809pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3753pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3753pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2710pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 17) | ((insn[0] << 13) >> 15); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2710pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 15) >> 15; + insn[0] = (insn[0] & ~0x7fffc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2711pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 14) | ((insn[0] << 13) >> 18); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2711pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 17) >> 18; + insn[0] = (insn[0] & ~0x7ffe0) | (tie_t << 5); +} + +static unsigned +Field_s_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_s_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2803pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2803pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3754pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3754pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2725pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2725pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2726pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2726pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2727pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2727pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2729pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2729pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2730pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2730pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2732pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2732pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2731pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2731pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2733pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2733pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2734pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2734pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2735pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2735pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2807pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2807pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3756pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 28) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3756pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8) | (tie_t << 3); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2742pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2742pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2738pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2738pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 22) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2708pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 13) >> 20); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2708pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0x7ff80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2714pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 13) >> 22); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2714pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 22) >> 22; + insn[0] = (insn[0] & ~0x7fe00) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld2787pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2787pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2808pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2808pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3757pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3757pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2748pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2748pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2750pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2750pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2751pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2751pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2753pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2753pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2816pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2816pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_imm7_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 19) >> 25); + return tie_t; +} + +static void +Field_imm7_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2757pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2757pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2765pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2765pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2781pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2781pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2814pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2814pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3758pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3758pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld2752pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2752pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2766pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2766pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2782pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2782pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2783pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2783pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2785pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2785pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2806pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2806pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2025_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 28) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2025_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2754pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2754pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2784pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2784pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2786pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2786pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2759pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2759pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2761pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2761pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2760pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2760pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2762pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2762pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2790pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2790pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2763pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2763pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2812pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2812pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3748_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3748_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2764pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2764pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2818pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2818pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2737_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2737_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld2820pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2820pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2821pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 23) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2821pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x180) | (tie_t << 7); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3759pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3759pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld2792pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2792pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2823pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 23) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2823pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x100) | (tie_t << 8); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3760pq_slot2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3760pq_slot2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld2826pq_slot1_Slot_pq_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2826pq_slot1_Slot_pq_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_op0_s10_Slot_pq_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s10_Slot_pq_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); +} + +static unsigned +Field_dsp340050b49a6c_fld3761pq_slot1_Slot_pq_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 7) | ((insn[0] << 23) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3761pq_slot1_Slot_pq_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc) | (tie_t << 2); + tie_t = (val << 21) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2825pq_slot1_Slot_pq_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2825pq_slot1_Slot_pq_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); +} + +static unsigned +Field_sae_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + return tie_t; +} + +static void +Field_sae_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_op0_s11_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s11_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); +} + +static unsigned +Field_dsp340050b49a6c_fld2867pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 13) >> 29); + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2867pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); + tie_t = (val << 27) >> 29; + insn[0] = (insn[0] & ~0x70000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3763pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3763pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2869pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 13) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2869pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0x60000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3764pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 15) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3764pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2838pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2838pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 23) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2882_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2882_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2884pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2884pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2874pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2874pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2856pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2856pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 21) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3765pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3765pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2858pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 13) | ((insn[0] << 13) >> 19); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2858pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 19) >> 19; + insn[0] = (insn[0] & ~0x7ffc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2857pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 13) >> 20); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2857pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0x7ff80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2946pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2946pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2880pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2880pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2879pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2879pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2865_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 13) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2865_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x78000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2847pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2847pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 21) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2840pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2840pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2844pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2844pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2845pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2845pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2900pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2900pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2899pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2899pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2839pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2839pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 22) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2901pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2901pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2903pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2903pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2907pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2907pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2902pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2902pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2846pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2846pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2904pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2904pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2842pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2842pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2849pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2849pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2905pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2905pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2906pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2906pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2908pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2908pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2950pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2950pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3766pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 23) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3766pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x1e0) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2913pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2913pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2926pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 2) | ((insn[0] << 27) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2926pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18) | (tie_t << 3); + tie_t = (val << 25) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3767pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 22) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3767pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x3e0) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2914pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2914pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2827pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2827pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2833pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2833pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2835pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2835pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2837pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2837pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2861pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2861pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3768pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3768pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2829pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2829pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2830pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2830pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2836pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2836pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2831pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2831pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2832pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2832pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2873pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2873pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2871pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2871pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2872pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2872pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2936pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 13) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2936pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x78000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2932pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 13) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2932pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x78000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2934pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 13) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2934pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x78000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2935pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 13) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2935pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x78000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2863pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 13) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2863pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x7f000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2864pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 13) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2864pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x78000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2069_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2069_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2859pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 13) >> 20); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2859pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 19) >> 20; + insn[0] = (insn[0] & ~0x7ff80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2940_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2940_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2843pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2843pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2928pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2928pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2059_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 14) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2059_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2929pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2929pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2930pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2930pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3769pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 14) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3769pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x38000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2916pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2916pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_s8_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_s8_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2947pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2947pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2036_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2036_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2948pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2948pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3770pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 25) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3770pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x60) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2942pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2942pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 25) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2875pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2875pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2876pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2876pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2878pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2878pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2877pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2877pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2860pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 13) >> 20); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2860pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 19) >> 20; + insn[0] = (insn[0] & ~0x7ff80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2941pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2941pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3771pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3771pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2923pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2923pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2927pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 13) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 27) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2927pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18) | (tie_t << 3); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0x60000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3773pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 15) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3773pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0x18000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2918pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2918pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2920pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2920pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2921pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2921pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2922pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2922pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2924pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2924pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2925pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 27) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2925pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18) | (tie_t << 3); + tie_t = (val << 24) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2853pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2853pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2850pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2850pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2851pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2851pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2852pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2852pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2854pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2854pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2855pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2855pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2943pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2943pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 25) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3775pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3775pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3776pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3776pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3777pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3777pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2945pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2945pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 25) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2909pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2909pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2911pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2911pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2910pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2910pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2912pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2912pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2949pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2949pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 25) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3778pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 24) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3778pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe0) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2888pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2888pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2890pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2890pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2937pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2937pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 24) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2939pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2939pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3772_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3772_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2881pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2881pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2883pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2883pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2917pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2917pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2919pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2919pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2885pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2885pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2887pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2887pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2891pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2891pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2893pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2893pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2897pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2897pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 21) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3779pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3779pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2892pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2892pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2915pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 13) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2915pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x70000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3780pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3780pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2886pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2886pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2894pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2894pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2895pq_slot0_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2895pq_slot0_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 19) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2953acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 22) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2953acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x3e0) | (tie_t << 5); +} + +static unsigned +Field_op0_s12_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s12_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3782acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3782acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2956acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2956acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_s_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_s_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2967acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2967acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2056_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2056_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2966acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2966acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_dsp340050b49a6c_fld3783acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3783acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2957acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2957acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2958acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2958acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2960acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2960acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 25) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3784acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3784acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2964acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2964acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3785acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3785acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2959acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2959acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2963acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2963acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 25) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2045_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2045_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2046_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2046_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2954acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2954acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld3786acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3786acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2955acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2955acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld3788acc2_slot2_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3788acc2_slot2_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2969acc2_slot1_Slot_acc2_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2969acc2_slot1_Slot_acc2_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_op0_s13_Slot_acc2_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s13_Slot_acc2_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); +} + +static unsigned +Field_dsp340050b49a6c_fld3790acc2_slot1_Slot_acc2_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 14) | ((insn[0] << 8) >> 18); + tie_t = (tie_t << 7) | ((insn[0] << 23) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3790acc2_slot1_Slot_acc2_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc) | (tie_t << 2); + tie_t = (val << 11) >> 18; + insn[0] = (insn[0] & ~0xfffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2968acc2_slot1_Slot_acc2_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2968acc2_slot1_Slot_acc2_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld3793acc2_slot1_Slot_acc2_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 11) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 6) | ((insn[0] << 24) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3793acc2_slot1_Slot_acc2_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc) | (tie_t << 2); + tie_t = (val << 22) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 18) >> 28; + insn[0] = (insn[0] & ~0x1e0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld2075_Slot_acc2_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2075_Slot_acc2_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2031_Slot_acc2_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 11) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2031_Slot_acc2_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x1e0000) | (tie_t << 17); +} + +static unsigned +Field_op0_s14_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s14_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_r_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_r_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2973acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2973acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2047_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2047_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld3795acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3795acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2980acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 18) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2980acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0x3e00) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld3796acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 23) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3796acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x180) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2976acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 18) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2976acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc0) | (tie_t << 6); +} + +static unsigned +Field_t_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_t_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2989acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2989acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld3798acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3798acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2056_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2056_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2990acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2990acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld3799acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3799acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2977acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 18) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2977acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0x3e00) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld3797_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 23) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3797_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x180) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2981acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2981acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3800acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 20) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3800acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0xf80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2975acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 18) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2975acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x3f80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2982acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2982acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3801acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3801acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2984acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2984acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2985acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 27) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2985acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18) | (tie_t << 3); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3802acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3802acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2987acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2987acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3803acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3803acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2039_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 25) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2039_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x78) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2974acc2_slot0_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 18) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2974acc2_slot0_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0x3f00) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld3043smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 12) >> 31); + tie_t = (tie_t << 15) | ((insn[0] << 15) >> 17); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3043smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 17) >> 17; + insn[0] = (insn[0] & ~0x1fffc) | (tie_t << 2); + tie_t = (val << 16) >> 31; + insn[0] = (insn[0] & ~0x80000) | (tie_t << 19); +} + +static unsigned +Field_op0_s15_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s15_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); +} + +static unsigned +Field_dsp340050b49a6c_fld3805smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 13) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3805smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x60000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3061smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3061smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 23) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3806smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3806smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3063smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3063smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 24) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3807smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3807smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3049smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3049smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3050smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3050smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3052smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3052smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3056smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 12) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3056smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); + tie_t = (val << 19) >> 31; + insn[0] = (insn[0] & ~0x80000) | (tie_t << 19); +} + +static unsigned +Field_dsp340050b49a6c_fld3809smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3809smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3038smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 14) | ((insn[0] << 16) >> 18); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3038smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 18) >> 18; + insn[0] = (insn[0] & ~0xfffc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld3091smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 12) >> 23); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3091smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 23) >> 23; + insn[0] = (insn[0] & ~0xff800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2041_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2041_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3102smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 12) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3102smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3810smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 14) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3810smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x30000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3116smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3116smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3812smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 12) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3812smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0xe0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3813smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 12) >> 29); + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3813smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); + tie_t = (val << 26) >> 29; + insn[0] = (insn[0] & ~0xe0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3092smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 14) | ((insn[0] << 12) >> 18); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3092smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 18) >> 18; + insn[0] = (insn[0] & ~0xfffc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3047smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3047smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3090smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3090smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3814smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3814smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3030smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3030smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3006smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3006smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3104smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 12) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3104smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x80000) | (tie_t << 19); +} + +static unsigned +Field_dsp340050b49a6c_fld3816smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 13) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3816smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x70000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3033smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3033smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3111smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 21) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3111smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x780) | (tie_t << 7); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2056_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2056_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3016smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3016smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3017smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3017smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3019smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3019smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3018smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3018smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3020smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3020smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3021smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3021smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3022smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3022smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3105smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3105smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3008smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3008smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3009smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3009smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3011smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3011smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3015smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3015smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3010smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3010smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3012smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3012smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3013smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3013smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3014smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3014smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3070_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3070_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 22) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3032smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3032smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3084smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 12) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3084smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x80000) | (tie_t << 19); +} + +static unsigned +Field_dsp340050b49a6c_fld3817_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 13) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3817_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x70000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3098smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 12) >> 23); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3098smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 22) >> 23; + insn[0] = (insn[0] & ~0xff800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3062_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3062_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2998smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2998smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3048_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3048_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3000smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3000smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3031smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3031smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3001smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3001smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3818smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 18) >> 22); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3818smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 22) >> 22; + insn[0] = (insn[0] & ~0x3ff0) | (tie_t << 4); +} + +static unsigned +Field_dsp340050b49a6c_fld3039smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 18) | ((insn[0] << 12) >> 14); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3039smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 14) >> 14; + insn[0] = (insn[0] & ~0xffffc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld3044smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + tie_t = (tie_t << 9) | ((insn[0] << 21) >> 23); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3044smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 23) >> 23; + insn[0] = (insn[0] & ~0x7fc) | (tie_t << 2); + tie_t = (val << 19) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3819smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3819smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3040smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 12) >> 31); + tie_t = (tie_t << 15) | ((insn[0] << 15) >> 17); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3040smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 17) >> 17; + insn[0] = (insn[0] & ~0x1fffc) | (tie_t << 2); + tie_t = (val << 16) >> 31; + insn[0] = (insn[0] & ~0x80000) | (tie_t << 19); +} + +static unsigned +Field_dsp340050b49a6c_fld3046smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3046smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3051smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3051smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3053smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3053smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3054smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3054smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3055smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3055smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3058smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 12) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3058smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); + tie_t = (val << 19) >> 31; + insn[0] = (insn[0] & ~0x80000) | (tie_t << 19); +} + +static unsigned +Field_dsp340050b49a6c_fld3059smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 12) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 14) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3059smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 21) >> 31; + insn[0] = (insn[0] & ~0x20000) | (tie_t << 17); + tie_t = (val << 20) >> 31; + insn[0] = (insn[0] & ~0x80000) | (tie_t << 19); +} + +static unsigned +Field_dsp340050b49a6c_fld3821smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3821smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3065smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3065smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3066smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3066smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3067smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3067smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3080smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3080smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3069smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3069smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 19) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3071smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3071smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 19) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3072smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3072smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 19) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3074smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3074smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 19) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3073smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3073smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 19) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3075smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3075smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 19) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3093smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 12) >> 20); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3093smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 19) >> 20; + insn[0] = (insn[0] & ~0xfff00) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld3822smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3822smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld3097smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 11) | ((insn[0] << 12) >> 21); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3097smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 21) >> 21; + insn[0] = (insn[0] & ~0xffe00) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld3823smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3823smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3076smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3076smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 18) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3077smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3077smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 18) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3078smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3078smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 18) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3079smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 12) >> 22); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3079smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 18) >> 22; + insn[0] = (insn[0] & ~0xffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3036smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 9) | ((insn[0] << 21) >> 23); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3036smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 23) >> 23; + insn[0] = (insn[0] & ~0x7fc) | (tie_t << 2); + tie_t = (val << 21) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3068smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3068smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3081smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3081smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3082smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 12) >> 29); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3082smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 24) >> 29; + insn[0] = (insn[0] & ~0xe0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3824smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3824smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3100smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 12) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3100smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3825smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3825smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3106smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3106smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3099smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 12) >> 23); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3099smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 22) >> 23; + insn[0] = (insn[0] & ~0xff800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3096smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 12) >> 20); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3096smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 19) >> 20; + insn[0] = (insn[0] & ~0xfff00) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld3028smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3028smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3087smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3087smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_t_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_t_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2991smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2991smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3101smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 12) >> 29); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3101smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 27) >> 29; + insn[0] = (insn[0] & ~0xe0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3826smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3826smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld2992smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2992smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2993smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2993smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2995smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2995smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3113smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 21) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3113smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x780) | (tie_t << 7); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3827smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3827smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2999smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2999smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3007smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3007smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3023smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3023smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3115smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3115smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2029_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2029_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2994smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2994smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2996smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2996smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3024smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3024smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3025smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3025smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3027smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3027smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3085smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3085smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2032_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2032_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2997smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2997smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3088smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3088smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3828smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3828smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld3026smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3026smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3003smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3003smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3002smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3002smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3004smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3004smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3005smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3005smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3034smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3034smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2049_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2049_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3107smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3107smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3109smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3109smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3114smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3114smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3808_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3808_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3108smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3108smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3035smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3035smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3110smod_slot2_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3110smod_slot2_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3118smod_slot1_Slot_smod_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3118smod_slot1_Slot_smod_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_op0_s16_Slot_smod_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s16_Slot_smod_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); +} + +static unsigned +Field_dsp340050b49a6c_fld3829smod_slot1_Slot_smod_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 16) >> 26); + tie_t = (tie_t << 7) | ((insn[0] << 23) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3829smod_slot1_Slot_smod_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc) | (tie_t << 2); + tie_t = (val << 19) >> 26; + insn[0] = (insn[0] & ~0xfc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3117smod_slot1_Slot_smod_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3117smod_slot1_Slot_smod_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2080_Slot_smod_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2080_Slot_smod_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_sae_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + return tie_t; +} + +static void +Field_sae_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_op0_s17_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s17_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); +} + +static unsigned +Field_dsp340050b49a6c_fld3120smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 13) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3120smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x7f000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3122smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3122smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 23) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3121smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3121smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3131smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3131smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3126smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3126smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3148smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 13) >> 25); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3148smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 21) >> 25; + insn[0] = (insn[0] & ~0x7f000) | (tie_t << 12); +} + +static unsigned +Field_imm6_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 20) >> 26); + return tie_t; +} + +static void +Field_imm6_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3164smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 11) | ((insn[0] << 13) >> 21); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3164smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 20) >> 21; + insn[0] = (insn[0] & ~0x7ff00) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld3832smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3832smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld3160smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 13) | ((insn[0] << 13) >> 19); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3160smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 19) >> 19; + insn[0] = (insn[0] & ~0x7ffc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3161smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 11) | ((insn[0] << 13) >> 21); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3161smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 20) >> 21; + insn[0] = (insn[0] & ~0x7ff00) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld3159smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 13) >> 20); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3159smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0x7ff80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld3165smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3165smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3135smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3135smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3133smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3133smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3119smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 13) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3119smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x78000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3155smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3155smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 25) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3833smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3833smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3149smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3149smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3834_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3834_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3137smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3137smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3138smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3138smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3184smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3184smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 25) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3836smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 24) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3836smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld3182smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3182smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_sas_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 25) >> 27); + return tie_t; +} + +static void +Field_sas_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld3153smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3153smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 25) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3186smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3186smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3837smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 23) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3837smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld3168smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3168smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3171smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3171smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3175smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3175smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3140smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3140smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3170smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3170smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3152smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3152smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3144smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3144smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3172smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3172smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3173smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3173smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3174smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3174smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3188smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 13) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3188smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x70000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3838smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 5) | ((insn[0] << 22) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3838smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x3e0) | (tie_t << 5); + tie_t = (val << 25) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3180smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3180smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3166smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 7) | ((insn[0] << 22) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3166smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x3f8) | (tie_t << 3); + tie_t = (val << 20) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3181smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 7) | ((insn[0] << 22) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3181smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x3f8) | (tie_t << 3); + tie_t = (val << 20) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_s8_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_s8_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld3136smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3136smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3123smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3123smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 25) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3134smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3134smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 25) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3125smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3125smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 25) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3127smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3127smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3128smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3128smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3130smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3130smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3129smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3129smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3132smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3132smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3139smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3139smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3141smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3141smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3142smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3142smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3143smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3143smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3145smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3145smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3146smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 13) >> 24); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3146smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 20) >> 24; + insn[0] = (insn[0] & ~0x7f800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3150_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3150_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3156smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3156smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 24) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3157smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3157smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 24) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3158smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3158smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 24) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2049_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2049_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3176smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3176smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3177smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3177smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3179smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3179smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3178smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3178smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 19) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3841smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 5) | ((insn[0] << 22) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3841smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x3e0) | (tie_t << 5); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3842smod_slot0_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3842smod_slot0_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3208llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 14) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3208llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); + tie_t = (val << 18) >> 27; + insn[0] = (insn[0] & ~0x3e000) | (tie_t << 13); +} + +static unsigned +Field_op0_s18_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s18_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3843llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3843llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3193llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3193llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3194llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3194llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3196llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3196llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3200llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3200llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3213llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 14) >> 31); + tie_t = (tie_t << 7) | ((insn[0] << 22) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3213llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x3f8) | (tie_t << 3); + tie_t = (val << 24) >> 31; + insn[0] = (insn[0] & ~0x20000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3845llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 15) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3845llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x1c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3195llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3195llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3206_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 20) >> 22); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3206_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 22) >> 22; + insn[0] = (insn[0] & ~0xffc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld3225_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3225_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3205_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 14) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3205_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x3e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3847llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3847llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3212_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 22) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3212_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x3f8) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld3848llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3848llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3216llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3216llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 26) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld3849llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3849llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3215llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3215llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3850llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3850llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3234llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3234llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3232llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3232llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3237llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 14) >> 25); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3237llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 21) >> 25; + insn[0] = (insn[0] & ~0x3f800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2074_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2074_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3192llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3192llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2046_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2046_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3230_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3230_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_dsp340050b49a6c_fld3191llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3191llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld3243llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 14) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3243llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc00) | (tie_t << 10); +} + +static unsigned +Field_t_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_t_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3218llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3218llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld3851llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3851llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3244llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 14) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3244llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3853llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3853llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3242llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3242llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3855llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3855llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); + tie_t = (val << 26) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3231llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 23) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3231llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x100) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld3856llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 18) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3856llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x3e00) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld3203llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 16) | ((insn[0] << 14) >> 16); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3203llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 16) >> 16; + insn[0] = (insn[0] & ~0x3fffc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld3204llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 14) >> 27); + tie_t = (tie_t << 10) | ((insn[0] << 20) >> 22); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3204llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 22) >> 22; + insn[0] = (insn[0] & ~0xffc) | (tie_t << 2); + tie_t = (val << 17) >> 27; + insn[0] = (insn[0] & ~0x3e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3844_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3844_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3207llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 14) >> 27); + tie_t = (tie_t << 10) | ((insn[0] << 20) >> 22); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3207llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 22) >> 22; + insn[0] = (insn[0] & ~0xffc) | (tie_t << 2); + tie_t = (val << 17) >> 27; + insn[0] = (insn[0] & ~0x3e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3197llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3197llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3198llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3198llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3199llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3199llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3201llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3201llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3202llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3202llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3210llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 14) >> 29); + tie_t = (tie_t << 7) | ((insn[0] << 22) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3210llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x3f8) | (tie_t << 3); + tie_t = (val << 22) >> 29; + insn[0] = (insn[0] & ~0x38000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3857llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3857llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3217_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3217_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld3859llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 14) >> 24); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3859llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 23) >> 24; + insn[0] = (insn[0] & ~0x3fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3221llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3221llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3222llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3222llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3860llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3860llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3224llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3224llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3861llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3861llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3220llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3220llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3246_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3246_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3214_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 14) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3214_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3863llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 15) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3863llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0x1f800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3226llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3226llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3864llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3864llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3235llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 14) >> 25); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3235llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 21) >> 25; + insn[0] = (insn[0] & ~0x3f800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3238llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 14) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3238llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0x3f000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3862_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3862_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3241llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3241llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3865llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3865llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3236_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 14) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3236_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x3f800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3240llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 14) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3240llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x3e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3228llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 23) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3228llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x100) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld3866llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3866llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); +} + +static unsigned +Field_dsp340050b49a6c_fld3247llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3247llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld3867llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3867llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_s_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_s_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld3233_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3233_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld2029_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2029_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3245llr_slot2_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3245llr_slot2_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld3868_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3868_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2049_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2049_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3250llr_slot1_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3250llr_slot1_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); +} + +static unsigned +Field_op0_s19_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s19_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); +} + +static unsigned +Field_dsp340050b49a6c_fld3869llr_slot1_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 19) >> 30); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3869llr_slot1_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 22) >> 30; + insn[0] = (insn[0] & ~0x1800) | (tie_t << 11); + tie_t = (val << 18) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3254llr_slot1_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3254llr_slot1_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3872llr_slot1_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 17) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3872llr_slot1_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 25) >> 30; + insn[0] = (insn[0] & ~0x6000) | (tie_t << 13); + tie_t = (val << 21) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3252llr_slot1_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3252llr_slot1_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3875llr_slot1_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3875llr_slot1_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3253llr_slot1_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3253llr_slot1_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3876llr_slot1_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + tie_t = (tie_t << 5) | ((insn[0] << 18) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3876llr_slot1_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x3e00) | (tie_t << 9); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3251llr_slot1_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3251llr_slot1_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3878llr_slot1_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3878llr_slot1_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3248llr_slot1_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3248llr_slot1_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3870_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 19) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3870_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x1800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2071_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2071_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_op0_s20_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 15) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s20_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0x18000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3260llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3260llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3258llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 17) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3258llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x6000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3266llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3266llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3286llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 5) | ((insn[0] << 25) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3286llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c) | (tie_t << 2); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 25) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3879llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 23) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3879llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x180) | (tie_t << 7); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3303llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3303llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3269llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3269llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3293llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3293llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3297llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3297llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3881llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3881llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3272llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3272llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3274llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3274llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3302llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 17) >> 30); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3302llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0x6000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3883llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3883llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3275llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3275llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3289llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3289llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3292llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3292llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3277llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3277llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3276llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3276llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3270llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 5) | ((insn[0] << 25) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3270llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c) | (tie_t << 2); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3312llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3312llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3885llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3885llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3304llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 7) | ((insn[0] << 19) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3304llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc0) | (tie_t << 6); + tie_t = (val << 24) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3887llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3887llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3283llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3283llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3310llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3310llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3888llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3888llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3288llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 25) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3288llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x78) | (tie_t << 3); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2056_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2056_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld3284llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + tie_t = (tie_t << 5) | ((insn[0] << 25) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3284llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c) | (tie_t << 2); + tie_t = (val << 25) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 24) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2041_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2041_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld3305llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 7) | ((insn[0] << 19) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3305llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc0) | (tie_t << 6); + tie_t = (val << 24) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3306llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 19) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3306llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x1800) | (tie_t << 11); + tie_t = (val << 25) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3890llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3890llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3259llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 17) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3259llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x7000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3291llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3291llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3261llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3261llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3263llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3263llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3267llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3267llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3264llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3264llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3265llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3265llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3268llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3268llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3308llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3308llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3892llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3892llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3294llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3294llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3295llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3295llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3296llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3296llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3298llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3298llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3299llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3299llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2047_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2047_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld3300llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 17) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3300llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x7800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3893llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3893llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3278llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3278llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3279llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3279llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3280llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3280llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3282llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3282llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3281llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 5) | ((insn[0] << 25) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3281llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c) | (tie_t << 2); + tie_t = (val << 26) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3311llr_slot0_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3311llr_slot0_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_r_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_r_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3364_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3364_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 22) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_op0_s21_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s21_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); +} + +static unsigned +Field_dsp340050b49a6c_fld3464dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3464dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3894dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 10) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3894dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0x3f0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3465dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3465dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3895dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 10) >> 26); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3895dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 25) >> 26; + insn[0] = (insn[0] & ~0x3f0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3459dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3459dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld3896dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 11) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3896dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3468dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 9) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3468dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x400000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3897dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 8) >> 31); + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3897dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x800000) | (tie_t << 23); +} + +static unsigned +Field_dsp340050b49a6c_fld3467dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 9) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3467dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x400000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3899dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 8) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3899dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x800000) | (tie_t << 23); +} + +static unsigned +Field_dsp340050b49a6c_fld3414dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3414dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3313dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3313dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3316dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3316dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3334dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3334dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_t_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_t_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3314_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3314_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3418dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3418dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3425dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3425dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3408dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 9) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3408dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x400000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3901dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 8) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3901dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x800000) | (tie_t << 23); +} + +static unsigned +Field_dsp340050b49a6c_fld3315dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3315dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3421dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3421dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3443dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3443dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3420dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3420dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3423dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3423dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3422dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3422dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3424dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3424dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3416dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3416dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3461dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3461dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld2049_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2049_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3415dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3415dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3426dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3426dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3417dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3417dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3419dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3419dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3318_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3318_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3904dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3904dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3482dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3482dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld3903dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 11) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3903dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x180000) | (tie_t << 19); +} + +static unsigned +Field_dsp340050b49a6c_fld2044_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 8) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2044_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0xf80000) | (tie_t << 19); +} + +static unsigned +Field_dsp340050b49a6c_fld3407_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 8) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3407_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800000) | (tie_t << 23); +} + +static unsigned +Field_dsp340050b49a6c_fld3905dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 9) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3905dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3479dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3479dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 23) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3906dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3906dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3475dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3475dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 20) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3898dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 14) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3898dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3353dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 8) >> 25); + tie_t = (tie_t << 13) | ((insn[0] << 17) >> 19); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3353dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 19) >> 19; + insn[0] = (insn[0] & ~0x7ffc) | (tie_t << 2); + tie_t = (val << 12) >> 25; + insn[0] = (insn[0] & ~0xfe0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3907dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 15) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3907dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3388dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 13) | ((insn[0] << 8) >> 19); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3388dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 15) >> 19; + insn[0] = (insn[0] & ~0xfff800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3913dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3913dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3387dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 18) | ((insn[0] << 8) >> 14); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3387dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 14) >> 14; + insn[0] = (insn[0] & ~0xffffc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3396dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 8) >> 25); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3396dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 21) >> 25; + insn[0] = (insn[0] & ~0xfe0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3909dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 15) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3909dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3404dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 12) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3404dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x80000) | (tie_t << 19); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3910dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 10) >> 30); + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3910dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 23) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); + tie_t = (val << 21) >> 30; + insn[0] = (insn[0] & ~0x300000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3385dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3385dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 18) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3478dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3478dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 21) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3908dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 14) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3908dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0x30000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3477dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3477dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 20) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3469dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 8) >> 23); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3469dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 23) >> 23; + insn[0] = (insn[0] & ~0xff8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3484dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 13) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3484dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40000) | (tie_t << 18); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld3916dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 11) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3916dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x180000) | (tie_t << 19); +} + +static unsigned +Field_dsp340050b49a6c_fld3451dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3451dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 21) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3914dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3914dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3450dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3450dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 19) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2046_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2046_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3453dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 14) | ((insn[0] << 8) >> 18); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3453dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 18) >> 18; + insn[0] = (insn[0] & ~0xfffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3365dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3365dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 14) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3366dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3366dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 14) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3368dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3368dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 14) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3372dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3372dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 14) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3367dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3367dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 14) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3369dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3369dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 14) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3345dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 12) | ((insn[0] << 18) >> 20); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3345dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0x3ffc) | (tie_t << 2); + tie_t = (val << 14) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3457dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 8) >> 25); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3457dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 21) >> 25; + insn[0] = (insn[0] & ~0xfe0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3917dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 15) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3917dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3358dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 6) | ((insn[0] << 22) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3358dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0x3f0) | (tie_t << 4); + tie_t = (val << 25) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 19) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3918dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3918dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); + tie_t = (val << 27) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3347dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 12) | ((insn[0] << 18) >> 20); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3347dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0x3ffc) | (tie_t << 2); + tie_t = (val << 14) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3348dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 12) | ((insn[0] << 18) >> 20); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3348dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0x3ffc) | (tie_t << 2); + tie_t = (val << 14) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3354dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 10) | ((insn[0] << 18) >> 22); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3354dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 22) >> 22; + insn[0] = (insn[0] & ~0x3ff0) | (tie_t << 4); + tie_t = (val << 16) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_s4_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_s4_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld3397dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3397dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3919dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3919dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3462dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3462dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3394dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 8) >> 24); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3394dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 20) >> 24; + insn[0] = (insn[0] & ~0xff0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3920dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 16) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3920dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3363dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3363dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 14) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3481dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3481dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 24) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3339dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3339dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3384dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3384dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 18) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3360dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3360dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3437dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3437dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3439dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3439dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3438dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3438dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3440dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3440dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3441dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3441dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3442dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3442dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3444dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3444dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3460dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3460dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3921dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3921dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3429dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3429dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3431dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3431dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3435dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3435dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3430dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3430dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3432dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3432dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3433dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3433dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3434dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3434dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3436dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3436dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3361dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3361dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3403dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 12) >> 30); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3403dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0xc0000) | (tie_t << 18); + tie_t = (val << 25) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3922dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 10) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3922dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x300000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3386dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3386dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 18) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2056_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2056_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld3923dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 5) | ((insn[0] << 25) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3923dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c) | (tie_t << 2); + tie_t = (val << 18) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3324dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3324dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3325dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3325dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3340dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3340dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3327dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3327dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3342dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + tie_t = (tie_t << 6) | ((insn[0] << 22) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3342dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0x3f0) | (tie_t << 4); + tie_t = (val << 24) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3356dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + tie_t = (tie_t << 6) | ((insn[0] << 22) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3356dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0x3f0) | (tie_t << 4); + tie_t = (val << 23) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); + tie_t = (val << 17) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3924dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3924dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3349dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 22) | ((insn[0] << 8) >> 10); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3349dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 10) >> 10; + insn[0] = (insn[0] & ~0xfffffc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld3350dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 8) >> 25); + tie_t = (tie_t << 13) | ((insn[0] << 17) >> 19); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3350dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 19) >> 19; + insn[0] = (insn[0] & ~0x7ffc) | (tie_t << 2); + tie_t = (val << 12) >> 25; + insn[0] = (insn[0] & ~0xfe0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3341dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3341dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3370dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3370dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 14) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3371dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3371dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 14) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3373dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3373dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 14) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3374dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3374dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 14) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3376dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3376dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 14) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3375dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3375dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 14) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3377dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3377dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 14) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3378dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3378dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 14) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3379dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 8) >> 22); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3379dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 14) >> 22; + insn[0] = (insn[0] & ~0xffc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3381dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3381dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3448dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3448dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 19) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3925dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3925dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3454dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 8) >> 24); + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3454dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); + tie_t = (val << 19) >> 24; + insn[0] = (insn[0] & ~0xff0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3466_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3466_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3412dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3412dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3927dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3927dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3382dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 7) | ((insn[0] << 22) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3382dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x3f8) | (tie_t << 3); + tie_t = (val << 19) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3928dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3928dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3410_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3410_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld3929dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 6) | ((insn[0] << 24) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3929dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc) | (tie_t << 2); + tie_t = (val << 17) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3390dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 8) >> 20); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3390dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 16) >> 20; + insn[0] = (insn[0] & ~0xfff000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3413dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3413dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3930dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 13) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3930dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x7fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3456dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 8) >> 24); + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3456dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); + tie_t = (val << 19) >> 24; + insn[0] = (insn[0] & ~0xff0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3392dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 11) | ((insn[0] << 8) >> 21); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3392dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 17) >> 21; + insn[0] = (insn[0] & ~0xffe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3900_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3900_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3337dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3337dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3446dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3446dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 20) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3317dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3317dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3458dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3458dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3319dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3319dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3320dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3320dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3322dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3322dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3399dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3399dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld3931dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 11) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3931dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x1c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3326dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3326dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3427dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3427dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3470dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3470dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3411dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 9) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3411dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x400000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3933dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 8) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3933dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); + tie_t = (val << 23) >> 31; + insn[0] = (insn[0] & ~0x800000) | (tie_t << 23); +} + +static unsigned +Field_dsp340050b49a6c_fld3321dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3321dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3428dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3428dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_s_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_s_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_r_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_r_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3471dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3471dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3472dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3472dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3474dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3474dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3323dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3323dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3480dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3480dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 24) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3473dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3473dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3328dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3328dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3330dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3330dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3329dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3329dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3331dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3331dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3362dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3362dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3332dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3332dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3445dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3445dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3333dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3333dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3335dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3335dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3401dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 12) >> 30); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3401dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 27) >> 30; + insn[0] = (insn[0] & ~0xc0000) | (tie_t << 18); + tie_t = (val << 25) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3934dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 10) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3934dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0x300000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3406dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 8) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3406dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x800000) | (tie_t << 23); +} + +static unsigned +Field_dsp340050b49a6c_fld3935dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 9) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3935dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0x7c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3380dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3380dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 18) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3336dual_slot2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 8) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3336dual_slot2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0xfc0000) | (tie_t << 18); +} + +static unsigned +Field_op0_s22_Slot_dual_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 31) >> 31); + return tie_t; +} + +static void +Field_op0_s22_Slot_dual_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x1) | (tie_t << 0); +} + +static unsigned +Field_imm8_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + return tie_t; +} + +static void +Field_imm8_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_op0_s23_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 9) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 30) >> 30); + return tie_t; +} + +static void +Field_op0_s23_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3) | (tie_t << 0); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x400000) | (tie_t << 22); +} + +static unsigned +Field_dsp340050b49a6c_fld3532dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 10) >> 26); + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3532dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); + tie_t = (val << 24) >> 26; + insn[0] = (insn[0] & ~0x3f0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3602_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3602_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3533dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 10) >> 27); + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3533dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); + tie_t = (val << 25) >> 27; + insn[0] = (insn[0] & ~0x3e0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3936dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 15) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3936dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2057_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2057_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3625dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 10) >> 26); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3625dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 25) >> 26; + insn[0] = (insn[0] & ~0x3f0000) | (tie_t << 16); +} + +static unsigned +Field_r_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_r_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_t_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_t_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3487dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 18) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3487dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x3800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld3584_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3584_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld3937dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3937dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3489dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3489dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3488dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 10) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3488dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380000) | (tie_t << 19); +} + +static unsigned +Field_dsp340050b49a6c_fld3620dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3620dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2048_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2048_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3588dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 10) >> 27); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3588dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x3e0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3938dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 15) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3938dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x1c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3544dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3544dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 20) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3519dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3519dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 18) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3939dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3939dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3523dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 11) | ((insn[0] << 10) >> 21); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3523dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 21) >> 21; + insn[0] = (insn[0] & ~0x3ff800) | (tie_t << 11); +} + +static unsigned +Field_bbi_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 21) >> 27); + return tie_t; +} + +static void +Field_bbi_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3520dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3520dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 19) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2056_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2056_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld3507dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 16) | ((insn[0] << 10) >> 16); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3507dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 16) >> 16; + insn[0] = (insn[0] & ~0x3fffc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld3506dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 15) | ((insn[0] << 10) >> 17); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3506dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 17) >> 17; + insn[0] = (insn[0] & ~0x3fff80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld3614dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3614dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2079_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2079_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3550dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3550dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 20) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3549dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3549dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 20) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3531_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 10) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3531_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x3f8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3500dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3500dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 18) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3502dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3502dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 17) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3606dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3606dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 20) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3607dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3607dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 20) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3608dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3608dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 20) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_sae_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + return tie_t; +} + +static void +Field_sae_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3619_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 10) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3619_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x200000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld3940dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 11) >> 25); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3940dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3613dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 10) >> 27); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3613dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 23) >> 27; + insn[0] = (insn[0] & ~0x3e0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3509dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3509dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 16) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3510dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3510dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 16) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3562dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3562dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 16) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3560dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3560dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 16) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3499dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3499dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 19) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3563dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3563dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 16) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3565dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3565dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 16) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3564dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3564dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 16) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3566dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3566dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 16) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3512dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3512dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 16) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3567dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3567dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 16) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3504dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3504dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 17) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3516dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3516dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 16) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3568dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3568dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 16) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3570dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3570dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 16) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3580dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3580dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 16) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3559dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 5) | ((insn[0] << 25) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3559dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c) | (tie_t << 2); + tie_t = (val << 19) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3573dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3573dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 16) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3599dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 10) >> 26); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3599dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0x3f0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3941dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3941dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3575dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3575dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 16) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3535dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3535dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2066_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2066_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3494dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3494dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3497dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3497dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3496dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3496dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3498dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 5) | ((insn[0] << 17) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3498dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c00) | (tie_t << 10); + tie_t = (val << 23) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3490dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3490dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3491dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3491dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3493dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3493dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3527dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3527dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); + tie_t = (val << 26) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2049_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2049_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3492dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3492dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3589dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 27) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3589dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18) | (tie_t << 3); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_s8_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_s8_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld3541dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3541dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2037_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2037_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld3542dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3542dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3543dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3543dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3552_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3552_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 23) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3626dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 10) >> 26); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3626dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 25) >> 26; + insn[0] = (insn[0] & ~0x3f0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3621dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 10) >> 25); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3621dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 24) >> 25; + insn[0] = (insn[0] & ~0x3f8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3623dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 10) >> 25); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3623dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 24) >> 25; + insn[0] = (insn[0] & ~0x3f8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3622dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 10) >> 25); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3622dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 24) >> 25; + insn[0] = (insn[0] & ~0x3f8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3624dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 10) >> 25); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3624dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 24) >> 25; + insn[0] = (insn[0] & ~0x3f8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3529dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 10) | ((insn[0] << 10) >> 22); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3529dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 22) >> 22; + insn[0] = (insn[0] & ~0x3ff000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld3530dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 10) >> 25); + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3530dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); + tie_t = (val << 23) >> 25; + insn[0] = (insn[0] & ~0x3f8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2072_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2072_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3524dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 10) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 17) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3524dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x7800) | (tie_t << 11); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0x3f0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3943dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 6) | ((insn[0] << 21) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3943dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0x7e0) | (tie_t << 5); + tie_t = (val << 25) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3508dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3508dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 16) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3601dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3601dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3945dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 14) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3945dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3603dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3603dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3604dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3604dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3946dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 14) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3946dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0x30000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3545dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3545dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 20) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3616dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 10) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3616dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x300000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld3947dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 12) >> 26); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3947dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 25) >> 26; + insn[0] = (insn[0] & ~0xfc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3618dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 10) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3618dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x200000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld3949dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 11) >> 25); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3949dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 24) >> 25; + insn[0] = (insn[0] & ~0x1fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3609dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 5) | ((insn[0] << 22) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3609dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x3e0) | (tie_t << 5); + tie_t = (val << 19) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3546dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3546dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 20) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3548dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3548dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 20) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3554dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3554dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 20) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3547dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3547dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 20) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3522dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3522dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 19) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3950dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3950dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld3611dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 5) | ((insn[0] << 22) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3611dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x3e0) | (tie_t << 5); + tie_t = (val << 19) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3592dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3592dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3594dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3594dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3598dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 10) >> 26); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3598dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0x3f0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3951dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3951dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3600dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 10) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 27) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3600dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18) | (tie_t << 3); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 24) >> 27; + insn[0] = (insn[0] & ~0x3e0000) | (tie_t << 17); +} + +static unsigned +Field_dsp340050b49a6c_fld3952dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 15) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3952dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0x18000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3593dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3593dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3595dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3595dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3596dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3596dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3597dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3597dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3511dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3511dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 16) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3513dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3513dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 16) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3514dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3514dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 16) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3515dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3515dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 16) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3517dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3517dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 16) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3518dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3518dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 17) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld3536dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 17) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3536dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0x6000) | (tie_t << 13); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld2060_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 14) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2060_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3539dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3539dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3954dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 14) >> 27); + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3954dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); + tie_t = (val << 26) >> 27; + insn[0] = (insn[0] & ~0x3e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3537dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 2) | ((insn[0] << 17) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3537dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0x6000) | (tie_t << 13); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3538dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 10) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3538dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c0000) | (tie_t << 18); +} + +static unsigned +Field_dsp340050b49a6c_fld3957dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 14) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3957dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x38000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld3587dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3587dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 21) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3610_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 22) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3610_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x3e0) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld3571dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3571dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 16) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3572dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3572dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 16) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3574dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3574dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 16) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3569dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 5) | ((insn[0] << 25) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3569dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c) | (tie_t << 2); + tie_t = (val << 19) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3505dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 14) | ((insn[0] << 10) >> 18); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3505dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 18) >> 18; + insn[0] = (insn[0] & ~0x3fff00) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld3612dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 10) >> 26); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3612dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 22) >> 26; + insn[0] = (insn[0] & ~0x3f0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld3576dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3576dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 15) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3577dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3577dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 15) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3615dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 10) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3615dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x380000) | (tie_t << 19); +} + +static unsigned +Field_dsp340050b49a6c_fld3958dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 13) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3958dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0x7e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3551dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3551dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3553dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3553dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3590dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3590dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3591dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3591dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); + tie_t = (val << 20) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3555dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3555dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3557dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3557dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3578dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3578dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 15) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3579dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3579dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 15) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3581dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 8) | ((insn[0] << 22) >> 24); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3581dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc) | (tie_t << 2); + tie_t = (val << 16) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3582dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3582dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 25) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 17) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3959dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3959dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3556dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3556dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3558dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 9) | ((insn[0] << 10) >> 23); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3558dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 19) >> 23; + insn[0] = (insn[0] & ~0x3fe000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3583dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3583dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); + tie_t = (val << 18) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3960dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3960dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); + tie_t = (val << 29) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld3585dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + tie_t = (tie_t << 1) | ((insn[0] << 22) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3585dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x200) | (tie_t << 9); + tie_t = (val << 19) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld3961dual_slot0_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 18) >> 31); + tie_t = (tie_t << 2) | ((insn[0] << 23) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld3961dual_slot0_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0x180) | (tie_t << 7); + tie_t = (val << 28) >> 31; + insn[0] = (insn[0] & ~0x2000) | (tie_t << 13); +} + +static unsigned +Field_t_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_t_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); +} + +static unsigned +Field_t_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_t_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_t_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_t_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_t_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_t_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_t_Slot_acc2_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_t_Slot_acc2_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_t_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_t_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_t_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_t_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_bbi_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_bbi_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_bbi_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 21) >> 27); + return tie_t; +} + +static void +Field_bbi_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c0) | (tie_t << 6); +} + +static unsigned +Field_imm12_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 8) >> 20); + return tie_t; +} + +static void +Field_imm12_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0xfff000) | (tie_t << 12); +} + +static unsigned +Field_imm12_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 14) >> 20); + return tie_t; +} + +static void +Field_imm12_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0x3ffc0) | (tie_t << 6); +} + +static unsigned +Field_imm12_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 14) >> 20); + return tie_t; +} + +static void +Field_imm12_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0x3ffc0) | (tie_t << 6); +} + +static unsigned +Field_imm8_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 8) >> 24); + return tie_t; +} + +static void +Field_imm8_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0000) | (tie_t << 16); +} + +static unsigned +Field_imm8_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 10) >> 24); + return tie_t; +} + +static void +Field_imm8_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc000) | (tie_t << 14); +} + +static unsigned +Field_s_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_s_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_s_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_s_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_s_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_s_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_s_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_s_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_s_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_s_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_s_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_s_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_s_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_s_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_s_Slot_acc2_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_s_Slot_acc2_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_s_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_s_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_s_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_s_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_s_Slot_smod_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_s_Slot_smod_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_s_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_s_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_s_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_s_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_s_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_s_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_imm12b_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 8) >> 24); + return tie_t; +} + +static void +Field_imm12b_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0000) | (tie_t << 16); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_imm12b_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 14) >> 24); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_imm12b_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 20) >> 24; + insn[0] = (insn[0] & ~0x3fc00) | (tie_t << 10); +} + +static unsigned +Field_imm12b_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 14) >> 24); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_imm12b_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 20) >> 24; + insn[0] = (insn[0] & ~0x3fc00) | (tie_t << 10); +} + +static unsigned +Field_imm16_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 16) | ((insn[0] << 8) >> 16); + return tie_t; +} + +static void +Field_imm16_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 16) >> 16; + insn[0] = (insn[0] & ~0xffff00) | (tie_t << 8); +} + +static unsigned +Field_imm16_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 10) >> 20); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_imm16_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 16) >> 20; + insn[0] = (insn[0] & ~0x3ffc00) | (tie_t << 10); +} + +static unsigned +Field_offset_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 18) | ((insn[0] << 8) >> 14); + return tie_t; +} + +static void +Field_offset_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 14) >> 14; + insn[0] = (insn[0] & ~0xffffc0) | (tie_t << 6); +} + +static unsigned +Field_op2_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_op2_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_op2_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_op2_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_op2_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_op2_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_op2_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_op2_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_op2_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_op2_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_op2_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_op2_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_op2_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_op2_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_r_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_r_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_r_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_r_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_r_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_r_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_r_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_r_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_r_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_r_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_r_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_r_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_r_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_r_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_r_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_r_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_r_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_r_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_r_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_r_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_sae_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_sae_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); +} + +static unsigned +Field_sae_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + return tie_t; +} + +static void +Field_sae_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_sal_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_sal_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_sal_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_sal_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_sal_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_sal_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_sal_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_sal_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_sal_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_sal_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_sal_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_sal_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_sal_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_sal_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_sal_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_sal_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_sargt_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_sargt_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_sargt_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_sargt_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_sargt_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_sargt_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_sargt_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_sargt_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_sargt_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_sargt_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_sargt_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_sargt_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_sargt_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_sargt_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_sargt_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_sargt_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_sas4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_sas4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); +} + +static unsigned +Field_sas_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_sas_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); +} + +static unsigned +Field_sas_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 25) >> 27); + return tie_t; +} + +static void +Field_sas_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c) | (tie_t << 2); +} + +static unsigned +Field_sas_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 25) >> 27); + return tie_t; +} + +static void +Field_sas_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c) | (tie_t << 2); +} + +static unsigned +Field_sas_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 25) >> 27); + return tie_t; +} + +static void +Field_sas_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c) | (tie_t << 2); +} + +static unsigned +Field_sas_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 25) >> 27); + return tie_t; +} + +static void +Field_sas_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c) | (tie_t << 2); +} + +static unsigned +Field_sr_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_sr_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_sr_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_sr_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_st_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_st_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_st_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_st_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_imm4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_imm4_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm4_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_imm4_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm4_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_mn_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_mn_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_i_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_i_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_imm6lo_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm6lo_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_imm6lo_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm6lo_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_imm6hi_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_imm6hi_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_imm6hi_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_imm6hi_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_imm7lo_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm7lo_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_imm7lo_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm7lo_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_imm7hi_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 25) >> 29); + return tie_t; +} + +static void +Field_imm7hi_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x70) | (tie_t << 4); +} + +static unsigned +Field_imm7hi_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 25) >> 29); + return tie_t; +} + +static void +Field_imm7hi_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x70) | (tie_t << 4); +} + +static unsigned +Field_z_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_z_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); +} + +static unsigned +Field_imm6_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm6_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_imm6_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm6_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_imm6_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 20) >> 26); + return tie_t; +} + +static void +Field_imm6_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc0) | (tie_t << 6); +} + +static unsigned +Field_imm6_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 20) >> 26); + return tie_t; +} + +static void +Field_imm6_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc0) | (tie_t << 6); +} + +static unsigned +Field_imm6_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 20) >> 26); + return tie_t; +} + +static void +Field_imm6_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc0) | (tie_t << 6); +} + +static unsigned +Field_imm6_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 20) >> 26); + return tie_t; +} + +static void +Field_imm6_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc0) | (tie_t << 6); +} + +static unsigned +Field_imm7_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 25) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm7_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x70) | (tie_t << 4); +} + +static unsigned +Field_imm7_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 25) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm7_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x70) | (tie_t << 4); +} + +static unsigned +Field_imm7_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 19) >> 25); + return tie_t; +} + +static void +Field_imm7_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc0) | (tie_t << 6); +} + +static unsigned +Field_imm7_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 19) >> 25); + return tie_t; +} + +static void +Field_imm7_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc0) | (tie_t << 6); +} + +static unsigned +Field_imm7_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 19) >> 25); + return tie_t; +} + +static void +Field_imm7_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc0) | (tie_t << 6); +} + +static unsigned +Field_imm7_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 19) >> 25); + return tie_t; +} + +static void +Field_imm7_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc0) | (tie_t << 6); +} + +static unsigned +Field_imm7_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 19) >> 25); + return tie_t; +} + +static void +Field_imm7_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc0) | (tie_t << 6); +} + +static unsigned +Field_imm7_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 19) >> 25); + return tie_t; +} + +static void +Field_imm7_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc0) | (tie_t << 6); +} + +static unsigned +Field_imm7_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 19) >> 25); + return tie_t; +} + +static void +Field_imm7_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc0) | (tie_t << 6); +} + +static unsigned +Field_imm7_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 19) >> 25); + return tie_t; +} + +static void +Field_imm7_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc0) | (tie_t << 6); +} + +static unsigned +Field_imm7_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 7) | ((insn[0] << 19) >> 25); + return tie_t; +} + +static void +Field_imm7_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 25) >> 25; + insn[0] = (insn[0] & ~0x1fc0) | (tie_t << 6); +} + +static unsigned +Field_t2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 24) >> 29); + return tie_t; +} + +static void +Field_t2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe0) | (tie_t << 5); +} + +static unsigned +Field_t2_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 24) >> 29); + return tie_t; +} + +static void +Field_t2_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe0) | (tie_t << 5); +} + +static unsigned +Field_t2_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 24) >> 29); + return tie_t; +} + +static void +Field_t2_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe0) | (tie_t << 5); +} + +static unsigned +Field_s2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_s2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); +} + +static unsigned +Field_s2_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_s2_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); +} + +static unsigned +Field_s2_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_s2_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); +} + +static unsigned +Field_r2_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + return tie_t; +} + +static void +Field_r2_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); +} + +static unsigned +Field_r2_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + return tie_t; +} + +static void +Field_r2_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); +} + +static unsigned +Field_t4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_t4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_t4_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_t4_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_t4_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_t4_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_s4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_s4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_s4_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_s4_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_s4_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_s4_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_s4_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_s4_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_s4_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_s4_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_s4_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_s4_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_s4_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_s4_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_r4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_r4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_r4_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_r4_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_r4_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_r4_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_t8_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_t8_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_t8_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_t8_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_t8_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_t8_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_s8_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_s8_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); +} + +static unsigned +Field_s8_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_s8_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); +} + +static unsigned +Field_s8_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_s8_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); +} + +static unsigned +Field_s8_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_s8_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_r8_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_r8_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_r8_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_r8_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_r8_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_r8_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_xt_wbr15_imm_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 15) | ((insn[0] << 8) >> 17); + return tie_t; +} + +static void +Field_xt_wbr15_imm_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 17) >> 17; + insn[0] = (insn[0] & ~0xfffe00) | (tie_t << 9); +} + +static unsigned +Field_xt_wbr18_imm_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 18) | ((insn[0] << 8) >> 14); + return tie_t; +} + +static void +Field_xt_wbr18_imm_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 14) >> 14; + insn[0] = (insn[0] & ~0xffffc0) | (tie_t << 6); +} + +static unsigned +Field_fimm8_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 8) >> 24); + return tie_t; +} + +static void +Field_fimm8_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0000) | (tie_t << 16); +} + +static unsigned +Field_fimm8_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 14) >> 24); + return tie_t; +} + +static void +Field_fimm8_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0x3fc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2029_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2029_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); +} + +static unsigned +Field_dsp340050b49a6c_fld2029_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2029_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2029_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2029_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2029_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2029_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2029_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2029_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2029_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2029_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2029_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2029_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2029_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2029_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2029_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2029_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2029_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2029_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2030_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2030_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); +} + +static unsigned +Field_dsp340050b49a6c_fld2030_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2030_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2030_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2030_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2030_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2030_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2030_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2030_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2030_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2030_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2030_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2030_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2030_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2030_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2030_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2030_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2030_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2030_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2032_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 22) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2032_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300) | (tie_t << 8); +} + +static unsigned +Field_dsp340050b49a6c_fld2032_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2032_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2032_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2032_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2032_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2032_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2032_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2032_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2032_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2032_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2032_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2032_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2032_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2032_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2032_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2032_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2032_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2032_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2035_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 27) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2035_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2035_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2035_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2035_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 27) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2035_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2035_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 27) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2035_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x18) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2036_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2036_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2036_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2036_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2036_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2036_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2037_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2037_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2037_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2037_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2037_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2037_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2037_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2037_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2038_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2038_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld2038_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 14) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2038_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x38000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2038_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2038_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2038_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 14) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2038_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x38000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2038_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2038_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2038_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2038_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2038_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 14) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2038_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x38000) | (tie_t << 15); +} + +static unsigned +Field_dsp340050b49a6c_fld2039_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2039_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); +} + +static unsigned +Field_dsp340050b49a6c_fld2039_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 25) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2039_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x78) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2039_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 25) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2039_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x78) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2039_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 25) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2039_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x78) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2039_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 25) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2039_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x78) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2040_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2040_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2040_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2040_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2040_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2040_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2040_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2040_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2040_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2040_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2041_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2041_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); +} + +static unsigned +Field_dsp340050b49a6c_fld2041_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2041_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2041_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2041_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2041_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2041_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2041_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2041_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2042_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2042_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); + tie_t = (val << 30) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2042_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 17) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2042_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x6000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2042_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 17) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2042_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x6000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2042_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 17) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2042_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x6000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2043_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2043_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2043_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2043_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2043_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2043_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2043_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2043_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2043_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2043_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2043_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2043_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2043_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2043_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2044_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 23) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2044_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x1f0) | (tie_t << 4); +} + +static unsigned +Field_dsp340050b49a6c_fld2044_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2044_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2044_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 25) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2044_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2044_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2044_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2044_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 21) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2044_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x400) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2045_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2045_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); +} + +static unsigned +Field_dsp340050b49a6c_fld2045_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2045_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2045_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2045_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2045_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2045_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2045_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2045_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2045_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2045_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2045_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2045_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2045_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2045_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2045_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2045_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2045_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2045_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2045_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2045_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2045_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2045_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2045_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2045_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2045_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2045_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2046_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2046_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2046_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2046_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2046_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2046_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2046_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2046_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2046_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2046_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld2046_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2046_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2046_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2046_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2046_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2046_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2046_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2046_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2046_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2046_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld2046_Slot_smod_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2046_Slot_smod_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2046_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2046_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2046_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2046_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2046_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2046_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2047_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2047_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2047_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2047_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2047_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2047_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2047_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2047_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2047_Slot_acc2_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2047_Slot_acc2_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2047_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2047_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2047_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2047_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2047_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2047_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2047_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2047_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); +} + +static unsigned +Field_dsp340050b49a6c_fld2047_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2047_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2047_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2047_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2048_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2048_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2048_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2048_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2048_Slot_dot_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2048_Slot_dot_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2048_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2048_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2048_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2048_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2048_Slot_acc2_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2048_Slot_acc2_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dsp340050b49a6c_fld2048_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2048_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2048_Slot_smod_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2048_Slot_smod_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2048_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2048_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2049_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2049_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2049_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 19) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2049_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x1800) | (tie_t << 11); +} + +static unsigned +Field_dsp340050b49a6c_fld2049_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 28) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2049_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2049_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2049_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2049_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2049_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2049_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2049_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2049_Slot_pq_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2049_Slot_pq_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2049_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2049_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2049_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2049_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2050_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2050_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2050_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2050_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2050_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2050_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2050_Slot_dot_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 15) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2050_Slot_dot_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x1e000) | (tie_t << 13); +} + +static unsigned +Field_dsp340050b49a6c_fld2050_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 25) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2050_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x78) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2050_Slot_pq_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2050_Slot_pq_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2050_Slot_acc2_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 25) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2050_Slot_acc2_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x78) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2050_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 25) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2050_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x78) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2050_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2050_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2050_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 25) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2050_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x78) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2050_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 25) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2050_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x78) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2050_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 25) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2050_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x78) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2050_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 25) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2050_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x78) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2051_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 22) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2051_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0x3f0) | (tie_t << 4); +} + +static unsigned +Field_dsp340050b49a6c_fld2051_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 24) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2051_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2051_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 24) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2051_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2051_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 24) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2051_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2051_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 24) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2051_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2051_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 24) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2051_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2051_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 24) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2051_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2051_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 24) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2051_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2051_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 24) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2051_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2051_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 6) | ((insn[0] << 24) >> 26); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2051_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 26) >> 26; + insn[0] = (insn[0] & ~0xfc) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2052_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2052_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_dsp340050b49a6c_fld2052_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2052_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2052_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2052_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2052_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2052_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2052_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2052_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2052_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2052_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2052_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2052_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2052_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2052_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2052_Slot_acc2_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + tie_t = (tie_t << 1) | ((insn[0] << 29) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2052_Slot_acc2_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4) | (tie_t << 2); + tie_t = (val << 28) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2052_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2052_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2052_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2052_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2052_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2052_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2052_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2052_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2052_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2052_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2052_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2052_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2053_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2053_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dsp340050b49a6c_fld2053_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2053_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2053_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2053_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2053_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2053_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2053_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2053_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2053_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2053_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2053_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 5) | ((insn[0] << 13) >> 27); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2053_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 27) >> 27; + insn[0] = (insn[0] & ~0x7c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2053_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 14) >> 28); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2053_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 27) >> 28; + insn[0] = (insn[0] & ~0x3c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2054_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 25) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2054_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x70) | (tie_t << 4); +} + +static unsigned +Field_dsp340050b49a6c_fld2054_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2054_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2054_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2054_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2054_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2054_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2054_Slot_smod_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + tie_t = (tie_t << 1) | ((insn[0] << 26) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2054_Slot_smod_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x20) | (tie_t << 5); + tie_t = (val << 29) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2054_Slot_llr_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2054_Slot_llr_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2054_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2054_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2055_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2055_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); +} + +static unsigned +Field_dsp340050b49a6c_fld2055_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2055_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2055_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2055_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2055_Slot_acc2_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2055_Slot_acc2_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2055_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2055_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2055_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2055_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_dsp340050b49a6c_fld2055_Slot_dual_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2055_Slot_dual_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2056_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 25) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2056_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x70) | (tie_t << 4); +} + +static unsigned +Field_dsp340050b49a6c_fld2056_Slot_gp_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2056_Slot_gp_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2056_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 26) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2056_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x38) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2056_Slot_dot_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2056_Slot_dot_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2056_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2056_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2056_Slot_pq_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2056_Slot_pq_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2056_Slot_smod_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2056_Slot_smod_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2056_Slot_smod_slot0_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2056_Slot_smod_slot0_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2056_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 22) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2056_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x380) | (tie_t << 7); +} + +static unsigned +Field_dsp340050b49a6c_fld2056_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2056_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2025_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 28) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2025_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2025_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 28) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2025_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2025_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 28) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2025_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2025_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 28) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2025_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2025_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 28) >> 31); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2025_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8) | (tie_t << 3); +} + +static unsigned +Field_dsp340050b49a6c_fld2027_Slot_gp_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2027_Slot_gp_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2027_Slot_dot_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2027_Slot_dot_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2027_Slot_pq_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2027_Slot_pq_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2027_Slot_acc2_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2027_Slot_acc2_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2027_Slot_smod_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2027_Slot_smod_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2027_Slot_llr_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2027_Slot_llr_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2027_Slot_dual_slot2_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2027_Slot_dual_slot2_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2026_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2026_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2026_Slot_dot_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2026_Slot_dot_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2026_Slot_pq_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2026_Slot_pq_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2026_Slot_acc2_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 18) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2026_Slot_acc2_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2026_Slot_smod_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2026_Slot_smod_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2026_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2026_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2031_Slot_gp_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2031_Slot_gp_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2031_Slot_dot_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2031_Slot_dot_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2031_Slot_pq_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2031_Slot_pq_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2031_Slot_smod_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 26) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2031_Slot_smod_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2031_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 22) >> 28); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2031_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0x3c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2028_Slot_acc2_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 15) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2028_Slot_acc2_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c000) | (tie_t << 14); +} + +static unsigned +Field_dsp340050b49a6c_fld2028_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 27) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2028_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c) | (tie_t << 2); +} + +static unsigned +Field_dsp340050b49a6c_fld2033_Slot_smod_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 23) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2033_Slot_smod_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c0) | (tie_t << 6); +} + +static unsigned +Field_dsp340050b49a6c_fld2033_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 19) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2033_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x1c00) | (tie_t << 10); +} + +static unsigned +Field_dsp340050b49a6c_fld2034_Slot_llr_slot1_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + return tie_t; +} + +static void +Field_dsp340050b49a6c_fld2034_Slot_llr_slot1_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); +} + +static void +Implicit_Field_set (xtensa_insnbuf insn ATTRIBUTE_UNUSED, + uint32 val ATTRIBUTE_UNUSED) +{ + /* Do nothing. */ +} + +static unsigned +Implicit_Field_ar0_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +static unsigned +Implicit_Field_ar4_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 4; +} + +static unsigned +Implicit_Field_ar8_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 8; +} + +static unsigned +Implicit_Field_ar12_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 12; +} + +static unsigned +Implicit_Field_bt16_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +static unsigned +Implicit_Field_bs16_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +static unsigned +Implicit_Field_br16_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +static unsigned +Implicit_Field_brall_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +enum xtensa_field_id { + FIELD_t, + FIELD_bbi4, + FIELD_bbi, + FIELD_imm12, + FIELD_imm8, + FIELD_s, + FIELD_imm12b, + FIELD_imm16, + FIELD_m, + FIELD_n, + FIELD_offset, + FIELD_op0, + FIELD_op1, + FIELD_op2, + FIELD_r, + FIELD_sa4, + FIELD_sae4, + FIELD_sae, + FIELD_sal, + FIELD_sargt, + FIELD_sas4, + FIELD_sas, + FIELD_sr, + FIELD_st, + FIELD_thi3, + FIELD_imm4, + FIELD_mn, + FIELD_i, + FIELD_imm6lo, + FIELD_imm6hi, + FIELD_imm7lo, + FIELD_imm7hi, + FIELD_z, + FIELD_imm6, + FIELD_imm7, + FIELD_t2, + FIELD_s2, + FIELD_r2, + FIELD_t4, + FIELD_s4, + FIELD_r4, + FIELD_t8, + FIELD_s8, + FIELD_r8, + FIELD_xt_wbr15_imm, + FIELD_xt_wbr18_imm, + FIELD_fimm8, + FIELD_dsp340050b49a6c_fld2019, + FIELD_dsp340050b49a6c_fld2021, + FIELD_dsp340050b49a6c_fld2029, + FIELD_dsp340050b49a6c_fld2030, + FIELD_dsp340050b49a6c_fld2032, + FIELD_dsp340050b49a6c_fld2035, + FIELD_dsp340050b49a6c_fld2036, + FIELD_dsp340050b49a6c_fld2037, + FIELD_dsp340050b49a6c_fld2038, + FIELD_dsp340050b49a6c_fld2039, + FIELD_dsp340050b49a6c_fld2040, + FIELD_dsp340050b49a6c_fld2041, + FIELD_dsp340050b49a6c_fld2042, + FIELD_dsp340050b49a6c_fld2043, + FIELD_dsp340050b49a6c_fld2044, + FIELD_dsp340050b49a6c_fld2045, + FIELD_dsp340050b49a6c_fld2046, + FIELD_dsp340050b49a6c_fld2047, + FIELD_dsp340050b49a6c_fld2048, + FIELD_dsp340050b49a6c_fld2049, + FIELD_dsp340050b49a6c_fld2050, + FIELD_dsp340050b49a6c_fld2051, + FIELD_dsp340050b49a6c_fld2052, + FIELD_dsp340050b49a6c_fld2053, + FIELD_dsp340050b49a6c_fld2054, + FIELD_dsp340050b49a6c_fld2055, + FIELD_dsp340050b49a6c_fld2056, + FIELD_dsp340050b49a6c_fld2082Inst, + FIELD_dsp340050b49a6c_fld2083Inst, + FIELD_dsp340050b49a6c_fld2084Inst, + FIELD_dsp340050b49a6c_fld2085Inst, + FIELD_dsp340050b49a6c_fld2086Inst, + FIELD_dsp340050b49a6c_fld2088Inst, + FIELD_dsp340050b49a6c_fld2089Inst, + FIELD_dsp340050b49a6c_fld2090Inst, + FIELD_dsp340050b49a6c_fld2091Inst, + FIELD_dsp340050b49a6c_fld2092Inst, + FIELD_dsp340050b49a6c_fld2094Inst, + FIELD_dsp340050b49a6c_fld2095Inst, + FIELD_dsp340050b49a6c_fld2096Inst, + FIELD_dsp340050b49a6c_fld2098Inst, + FIELD_dsp340050b49a6c_fld2099Inst, + FIELD_dsp340050b49a6c_fld2100Inst, + FIELD_dsp340050b49a6c_fld2101Inst, + FIELD_dsp340050b49a6c_fld2102Inst, + FIELD_dsp340050b49a6c_fld2103Inst, + FIELD_dsp340050b49a6c_fld2104Inst, + FIELD_dsp340050b49a6c_fld2105Inst, + FIELD_dsp340050b49a6c_fld2106Inst, + FIELD_dsp340050b49a6c_fld2107Inst, + FIELD_dsp340050b49a6c_fld2108Inst, + FIELD_dsp340050b49a6c_fld2109Inst, + FIELD_dsp340050b49a6c_fld2110Inst, + FIELD_dsp340050b49a6c_fld2111Inst, + FIELD_dsp340050b49a6c_fld2112Inst, + FIELD_dsp340050b49a6c_fld2113Inst, + FIELD_dsp340050b49a6c_fld2114Inst, + FIELD_dsp340050b49a6c_fld2115Inst, + FIELD_dsp340050b49a6c_fld2116Inst, + FIELD_dsp340050b49a6c_fld2117Inst, + FIELD_dsp340050b49a6c_fld2118Inst, + FIELD_dsp340050b49a6c_fld2119Inst, + FIELD_dsp340050b49a6c_fld2120Inst, + FIELD_dsp340050b49a6c_fld2122Inst, + FIELD_dsp340050b49a6c_fld2123Inst, + FIELD_dsp340050b49a6c_fld2124Inst, + FIELD_dsp340050b49a6c_fld2125Inst, + FIELD_dsp340050b49a6c_fld2126Inst, + FIELD_dsp340050b49a6c_fld2127Inst, + FIELD_dsp340050b49a6c_fld2128Inst, + FIELD_dsp340050b49a6c_fld2129Inst, + FIELD_dsp340050b49a6c_fld2131Inst, + FIELD_dsp340050b49a6c_fld2132Inst, + FIELD_dsp340050b49a6c_fld2133Inst, + FIELD_dsp340050b49a6c_fld2134Inst, + FIELD_dsp340050b49a6c_fld2136Inst, + FIELD_dsp340050b49a6c_fld2137Inst, + FIELD_dsp340050b49a6c_fld2138Inst, + FIELD_dsp340050b49a6c_fld2139Inst, + FIELD_dsp340050b49a6c_fld2140Inst, + FIELD_dsp340050b49a6c_fld2141Inst, + FIELD_dsp340050b49a6c_fld2142Inst, + FIELD_dsp340050b49a6c_fld2143Inst, + FIELD_dsp340050b49a6c_fld2144Inst, + FIELD_dsp340050b49a6c_fld2145Inst, + FIELD_dsp340050b49a6c_fld2146Inst, + FIELD_dsp340050b49a6c_fld2147Inst, + FIELD_dsp340050b49a6c_fld2149Inst, + FIELD_dsp340050b49a6c_fld2151Inst, + FIELD_dsp340050b49a6c_fld2153Inst, + FIELD_dsp340050b49a6c_fld2154Inst, + FIELD_dsp340050b49a6c_fld2155Inst, + FIELD_dsp340050b49a6c_fld2156Inst, + FIELD_dsp340050b49a6c_fld2157Inst, + FIELD_dsp340050b49a6c_fld2158Inst, + FIELD_dsp340050b49a6c_fld2159Inst, + FIELD_dsp340050b49a6c_fld2160Inst, + FIELD_dsp340050b49a6c_fld2161Inst, + FIELD_dsp340050b49a6c_fld2162Inst, + FIELD_dsp340050b49a6c_fld2163Inst, + FIELD_dsp340050b49a6c_fld2164Inst, + FIELD_dsp340050b49a6c_fld2165Inst, + FIELD_dsp340050b49a6c_fld2166Inst, + FIELD_dsp340050b49a6c_fld2167Inst, + FIELD_dsp340050b49a6c_fld2168Inst, + FIELD_dsp340050b49a6c_fld2169Inst, + FIELD_dsp340050b49a6c_fld2171Inst, + FIELD_dsp340050b49a6c_fld2172Inst, + FIELD_dsp340050b49a6c_fld2173Inst, + FIELD_dsp340050b49a6c_fld2174Inst, + FIELD_dsp340050b49a6c_fld2175Inst, + FIELD_dsp340050b49a6c_fld2177Inst, + FIELD_dsp340050b49a6c_fld2178Inst, + FIELD_dsp340050b49a6c_fld2179Inst, + FIELD_dsp340050b49a6c_fld2180Inst, + FIELD_dsp340050b49a6c_fld2181Inst, + FIELD_dsp340050b49a6c_fld2182Inst, + FIELD_dsp340050b49a6c_fld2183Inst, + FIELD_dsp340050b49a6c_fld2184Inst, + FIELD_dsp340050b49a6c_fld2185Inst, + FIELD_dsp340050b49a6c_fld2186Inst, + FIELD_dsp340050b49a6c_fld2187Inst, + FIELD_dsp340050b49a6c_fld2188Inst, + FIELD_dsp340050b49a6c_fld2189Inst, + FIELD_dsp340050b49a6c_fld2190Inst, + FIELD_dsp340050b49a6c_fld2191Inst, + FIELD_dsp340050b49a6c_fld2192Inst, + FIELD_dsp340050b49a6c_fld2193Inst, + FIELD_dsp340050b49a6c_fld2194Inst, + FIELD_dsp340050b49a6c_fld2195Inst, + FIELD_dsp340050b49a6c_fld2196Inst, + FIELD_dsp340050b49a6c_fld2197Inst, + FIELD_dsp340050b49a6c_fld2198Inst, + FIELD_dsp340050b49a6c_fld2199Inst, + FIELD_dsp340050b49a6c_fld2200Inst, + FIELD_dsp340050b49a6c_fld2201Inst, + FIELD_dsp340050b49a6c_fld2202Inst, + FIELD_dsp340050b49a6c_fld2203Inst, + FIELD_dsp340050b49a6c_fld2204Inst, + FIELD_dsp340050b49a6c_fld2205Inst, + FIELD_dsp340050b49a6c_fld2206Inst, + FIELD_dsp340050b49a6c_fld2207Inst, + FIELD_dsp340050b49a6c_fld2208Inst, + FIELD_dsp340050b49a6c_fld2209Inst, + FIELD_dsp340050b49a6c_fld2210Inst, + FIELD_dsp340050b49a6c_fld2211Inst, + FIELD_dsp340050b49a6c_fld2212Inst, + FIELD_dsp340050b49a6c_fld2213Inst, + FIELD_dsp340050b49a6c_fld2214Inst, + FIELD_dsp340050b49a6c_fld2215Inst, + FIELD_dsp340050b49a6c_fld2216Inst, + FIELD_dsp340050b49a6c_fld2217Inst, + FIELD_dsp340050b49a6c_fld2218Inst, + FIELD_dsp340050b49a6c_fld2219Inst, + FIELD_dsp340050b49a6c_fld2220Inst, + FIELD_dsp340050b49a6c_fld2221Inst, + FIELD_dsp340050b49a6c_fld2222Inst, + FIELD_dsp340050b49a6c_fld2223Inst, + FIELD_dsp340050b49a6c_fld2224Inst, + FIELD_dsp340050b49a6c_fld2225Inst, + FIELD_dsp340050b49a6c_fld2226Inst, + FIELD_dsp340050b49a6c_fld2227Inst, + FIELD_dsp340050b49a6c_fld2228Inst, + FIELD_dsp340050b49a6c_fld2229Inst, + FIELD_dsp340050b49a6c_fld2230Inst, + FIELD_dsp340050b49a6c_fld2231Inst, + FIELD_dsp340050b49a6c_fld2232Inst, + FIELD_dsp340050b49a6c_fld2234Inst, + FIELD_dsp340050b49a6c_fld2235Inst, + FIELD_dsp340050b49a6c_fld2236Inst, + FIELD_dsp340050b49a6c_fld2237Inst, + FIELD_dsp340050b49a6c_fld2238Inst, + FIELD_dsp340050b49a6c_fld2239Inst, + FIELD_dsp340050b49a6c_fld2240Inst, + FIELD_dsp340050b49a6c_fld2241Inst, + FIELD_dsp340050b49a6c_fld2242Inst, + FIELD_dsp340050b49a6c_fld2243Inst, + FIELD_dsp340050b49a6c_fld2244Inst, + FIELD_dsp340050b49a6c_fld2245Inst, + FIELD_dsp340050b49a6c_fld2246Inst, + FIELD_dsp340050b49a6c_fld2247Inst, + FIELD_dsp340050b49a6c_fld2248Inst, + FIELD_dsp340050b49a6c_fld2249Inst, + FIELD_dsp340050b49a6c_fld2250Inst, + FIELD_dsp340050b49a6c_fld2251Inst, + FIELD_dsp340050b49a6c_fld2252Inst, + FIELD_dsp340050b49a6c_fld2253Inst, + FIELD_dsp340050b49a6c_fld2254, + FIELD_dsp340050b49a6c_fld2255Inst, + FIELD_dsp340050b49a6c_fld2257Inst, + FIELD_dsp340050b49a6c_fld3627Inst, + FIELD_dsp340050b49a6c_fld3630Inst, + FIELD_dsp340050b49a6c_fld3631Inst, + FIELD_dsp340050b49a6c_fld3633Inst, + FIELD_dsp340050b49a6c_fld3634, + FIELD_dsp340050b49a6c_fld3635Inst, + FIELD_dsp340050b49a6c_fld3636Inst, + FIELD_dsp340050b49a6c_fld3637Inst, + FIELD_dsp340050b49a6c_fld3638Inst, + FIELD_dsp340050b49a6c_fld3639Inst, + FIELD_dsp340050b49a6c_fld3640Inst, + FIELD_dsp340050b49a6c_fld3642Inst, + FIELD_dsp340050b49a6c_fld3643Inst, + FIELD_dsp340050b49a6c_fld3644Inst, + FIELD_dsp340050b49a6c_fld3645Inst, + FIELD_dsp340050b49a6c_fld3647Inst, + FIELD_dsp340050b49a6c_fld3648Inst, + FIELD_dsp340050b49a6c_fld3649Inst, + FIELD_dsp340050b49a6c_fld3650Inst, + FIELD_dsp340050b49a6c_fld3651Inst, + FIELD_dsp340050b49a6c_fld3653Inst, + FIELD_dsp340050b49a6c_fld3654Inst, + FIELD_dsp340050b49a6c_fld3655Inst, + FIELD_dsp340050b49a6c_fld3656Inst, + FIELD_dsp340050b49a6c_fld3657Inst, + FIELD_dsp340050b49a6c_fld3658Inst, + FIELD_dsp340050b49a6c_fld3659Inst, + FIELD_dsp340050b49a6c_fld3660Inst, + FIELD_dsp340050b49a6c_fld3661Inst, + FIELD_dsp340050b49a6c_fld3662Inst, + FIELD_op0_s3, + FIELD_dsp340050b49a6c_fld2025, + FIELD_dsp340050b49a6c_fld2027, + FIELD_dsp340050b49a6c_fld2258GP_slot2, + FIELD_dsp340050b49a6c_fld2259GP_slot2, + FIELD_dsp340050b49a6c_fld2260GP_slot2, + FIELD_dsp340050b49a6c_fld2261GP_slot2, + FIELD_dsp340050b49a6c_fld2262GP_slot2, + FIELD_dsp340050b49a6c_fld2263GP_slot2, + FIELD_dsp340050b49a6c_fld2264GP_slot2, + FIELD_dsp340050b49a6c_fld2266GP_slot2, + FIELD_dsp340050b49a6c_fld2267GP_slot2, + FIELD_dsp340050b49a6c_fld2268GP_slot2, + FIELD_dsp340050b49a6c_fld2269GP_slot2, + FIELD_dsp340050b49a6c_fld2270GP_slot2, + FIELD_dsp340050b49a6c_fld2271GP_slot2, + FIELD_dsp340050b49a6c_fld2272, + FIELD_dsp340050b49a6c_fld2273GP_slot2, + FIELD_dsp340050b49a6c_fld2274GP_slot2, + FIELD_dsp340050b49a6c_fld2275GP_slot2, + FIELD_dsp340050b49a6c_fld2277GP_slot2, + FIELD_dsp340050b49a6c_fld2278GP_slot2, + FIELD_dsp340050b49a6c_fld2279GP_slot2, + FIELD_dsp340050b49a6c_fld2280GP_slot2, + FIELD_dsp340050b49a6c_fld2281GP_slot2, + FIELD_dsp340050b49a6c_fld2282GP_slot2, + FIELD_dsp340050b49a6c_fld2283GP_slot2, + FIELD_dsp340050b49a6c_fld2284GP_slot2, + FIELD_dsp340050b49a6c_fld2286GP_slot2, + FIELD_dsp340050b49a6c_fld2287GP_slot2, + FIELD_dsp340050b49a6c_fld2288GP_slot2, + FIELD_dsp340050b49a6c_fld2289GP_slot2, + FIELD_dsp340050b49a6c_fld2290GP_slot2, + FIELD_dsp340050b49a6c_fld2291GP_slot2, + FIELD_dsp340050b49a6c_fld2292GP_slot2, + FIELD_dsp340050b49a6c_fld2293GP_slot2, + FIELD_dsp340050b49a6c_fld2294GP_slot2, + FIELD_dsp340050b49a6c_fld2295GP_slot2, + FIELD_dsp340050b49a6c_fld2296GP_slot2, + FIELD_dsp340050b49a6c_fld2297GP_slot2, + FIELD_dsp340050b49a6c_fld2298GP_slot2, + FIELD_dsp340050b49a6c_fld2299GP_slot2, + FIELD_dsp340050b49a6c_fld2300GP_slot2, + FIELD_dsp340050b49a6c_fld2301GP_slot2, + FIELD_dsp340050b49a6c_fld2302, + FIELD_dsp340050b49a6c_fld2303GP_slot2, + FIELD_dsp340050b49a6c_fld2304GP_slot2, + FIELD_dsp340050b49a6c_fld2305, + FIELD_dsp340050b49a6c_fld2306GP_slot2, + FIELD_dsp340050b49a6c_fld2308GP_slot2, + FIELD_dsp340050b49a6c_fld2309GP_slot2, + FIELD_dsp340050b49a6c_fld2310GP_slot2, + FIELD_dsp340050b49a6c_fld2312GP_slot2, + FIELD_dsp340050b49a6c_fld2313, + FIELD_dsp340050b49a6c_fld2314GP_slot2, + FIELD_dsp340050b49a6c_fld2316GP_slot2, + FIELD_dsp340050b49a6c_fld2317GP_slot2, + FIELD_dsp340050b49a6c_fld2318GP_slot2, + FIELD_dsp340050b49a6c_fld2319GP_slot2, + FIELD_dsp340050b49a6c_fld2320GP_slot2, + FIELD_dsp340050b49a6c_fld2321GP_slot2, + FIELD_dsp340050b49a6c_fld2322GP_slot2, + FIELD_dsp340050b49a6c_fld2323GP_slot2, + FIELD_dsp340050b49a6c_fld2324GP_slot2, + FIELD_dsp340050b49a6c_fld2325GP_slot2, + FIELD_dsp340050b49a6c_fld2326GP_slot2, + FIELD_dsp340050b49a6c_fld2327GP_slot2, + FIELD_dsp340050b49a6c_fld2328GP_slot2, + FIELD_dsp340050b49a6c_fld2329GP_slot2, + FIELD_dsp340050b49a6c_fld2330GP_slot2, + FIELD_dsp340050b49a6c_fld2331GP_slot2, + FIELD_dsp340050b49a6c_fld2332GP_slot2, + FIELD_dsp340050b49a6c_fld2333GP_slot2, + FIELD_dsp340050b49a6c_fld2334GP_slot2, + FIELD_dsp340050b49a6c_fld2335GP_slot2, + FIELD_dsp340050b49a6c_fld2336GP_slot2, + FIELD_dsp340050b49a6c_fld2337GP_slot2, + FIELD_dsp340050b49a6c_fld2338GP_slot2, + FIELD_dsp340050b49a6c_fld2339GP_slot2, + FIELD_dsp340050b49a6c_fld2340GP_slot2, + FIELD_dsp340050b49a6c_fld2341GP_slot2, + FIELD_dsp340050b49a6c_fld2342GP_slot2, + FIELD_dsp340050b49a6c_fld2343GP_slot2, + FIELD_dsp340050b49a6c_fld2344GP_slot2, + FIELD_dsp340050b49a6c_fld2345GP_slot2, + FIELD_dsp340050b49a6c_fld2346GP_slot2, + FIELD_dsp340050b49a6c_fld2347GP_slot2, + FIELD_dsp340050b49a6c_fld2348GP_slot2, + FIELD_dsp340050b49a6c_fld2349GP_slot2, + FIELD_dsp340050b49a6c_fld2350GP_slot2, + FIELD_dsp340050b49a6c_fld2351GP_slot2, + FIELD_dsp340050b49a6c_fld2352GP_slot2, + FIELD_dsp340050b49a6c_fld2353GP_slot2, + FIELD_dsp340050b49a6c_fld2354GP_slot2, + FIELD_dsp340050b49a6c_fld2355GP_slot2, + FIELD_dsp340050b49a6c_fld2356GP_slot2, + FIELD_dsp340050b49a6c_fld2357GP_slot2, + FIELD_dsp340050b49a6c_fld2358GP_slot2, + FIELD_dsp340050b49a6c_fld2359GP_slot2, + FIELD_dsp340050b49a6c_fld2361GP_slot2, + FIELD_dsp340050b49a6c_fld2362GP_slot2, + FIELD_dsp340050b49a6c_fld2364GP_slot2, + FIELD_dsp340050b49a6c_fld2366GP_slot2, + FIELD_dsp340050b49a6c_fld2368GP_slot2, + FIELD_dsp340050b49a6c_fld2369GP_slot2, + FIELD_dsp340050b49a6c_fld2370GP_slot2, + FIELD_dsp340050b49a6c_fld2371GP_slot2, + FIELD_dsp340050b49a6c_fld2372GP_slot2, + FIELD_dsp340050b49a6c_fld2373GP_slot2, + FIELD_dsp340050b49a6c_fld2374GP_slot2, + FIELD_dsp340050b49a6c_fld2375GP_slot2, + FIELD_dsp340050b49a6c_fld2376GP_slot2, + FIELD_dsp340050b49a6c_fld2378GP_slot2, + FIELD_dsp340050b49a6c_fld2379GP_slot2, + FIELD_dsp340050b49a6c_fld2381GP_slot2, + FIELD_dsp340050b49a6c_fld2383GP_slot2, + FIELD_dsp340050b49a6c_fld2384, + FIELD_dsp340050b49a6c_fld2385GP_slot2, + FIELD_dsp340050b49a6c_fld2386, + FIELD_dsp340050b49a6c_fld2387GP_slot2, + FIELD_dsp340050b49a6c_fld2388GP_slot2, + FIELD_dsp340050b49a6c_fld2389GP_slot2, + FIELD_dsp340050b49a6c_fld3663GP_slot2, + FIELD_dsp340050b49a6c_fld3664GP_slot2, + FIELD_dsp340050b49a6c_fld3665GP_slot2, + FIELD_dsp340050b49a6c_fld3666, + FIELD_dsp340050b49a6c_fld3667GP_slot2, + FIELD_dsp340050b49a6c_fld3668GP_slot2, + FIELD_dsp340050b49a6c_fld3669GP_slot2, + FIELD_dsp340050b49a6c_fld3670GP_slot2, + FIELD_dsp340050b49a6c_fld3671GP_slot2, + FIELD_dsp340050b49a6c_fld3673GP_slot2, + FIELD_dsp340050b49a6c_fld3674GP_slot2, + FIELD_dsp340050b49a6c_fld3675GP_slot2, + FIELD_dsp340050b49a6c_fld3676GP_slot2, + FIELD_dsp340050b49a6c_fld3678GP_slot2, + FIELD_dsp340050b49a6c_fld3679GP_slot2, + FIELD_dsp340050b49a6c_fld3680GP_slot2, + FIELD_op0_s4, + FIELD_dsp340050b49a6c_fld2026, + FIELD_dsp340050b49a6c_fld2031, + FIELD_dsp340050b49a6c_fld2394GP_slot1, + FIELD_dsp340050b49a6c_fld2395GP_slot1, + FIELD_dsp340050b49a6c_fld2397GP_slot1, + FIELD_dsp340050b49a6c_fld2398GP_slot1, + FIELD_dsp340050b49a6c_fld2399GP_slot1, + FIELD_dsp340050b49a6c_fld2400GP_slot1, + FIELD_dsp340050b49a6c_fld2402GP_slot1, + FIELD_dsp340050b49a6c_fld2403GP_slot1, + FIELD_dsp340050b49a6c_fld2405GP_slot1, + FIELD_dsp340050b49a6c_fld3681GP_slot1, + FIELD_dsp340050b49a6c_fld3683GP_slot1, + FIELD_dsp340050b49a6c_fld3684GP_slot1, + FIELD_dsp340050b49a6c_fld3686GP_slot1, + FIELD_op0_s5, + FIELD_dsp340050b49a6c_fld2058, + FIELD_dsp340050b49a6c_fld2067, + FIELD_dsp340050b49a6c_fld2407GP_slot0, + FIELD_dsp340050b49a6c_fld2409GP_slot0, + FIELD_dsp340050b49a6c_fld2410GP_slot0, + FIELD_dsp340050b49a6c_fld2411GP_slot0, + FIELD_dsp340050b49a6c_fld2412GP_slot0, + FIELD_dsp340050b49a6c_fld2413GP_slot0, + FIELD_dsp340050b49a6c_fld2415GP_slot0, + FIELD_dsp340050b49a6c_fld2416GP_slot0, + FIELD_dsp340050b49a6c_fld2417GP_slot0, + FIELD_dsp340050b49a6c_fld2418GP_slot0, + FIELD_dsp340050b49a6c_fld2419GP_slot0, + FIELD_dsp340050b49a6c_fld2420GP_slot0, + FIELD_dsp340050b49a6c_fld2422GP_slot0, + FIELD_dsp340050b49a6c_fld2423GP_slot0, + FIELD_dsp340050b49a6c_fld2424GP_slot0, + FIELD_dsp340050b49a6c_fld2425GP_slot0, + FIELD_dsp340050b49a6c_fld2426GP_slot0, + FIELD_dsp340050b49a6c_fld2427GP_slot0, + FIELD_dsp340050b49a6c_fld2429GP_slot0, + FIELD_dsp340050b49a6c_fld2430GP_slot0, + FIELD_dsp340050b49a6c_fld2431GP_slot0, + FIELD_dsp340050b49a6c_fld2432GP_slot0, + FIELD_dsp340050b49a6c_fld2433GP_slot0, + FIELD_dsp340050b49a6c_fld2434GP_slot0, + FIELD_dsp340050b49a6c_fld2435GP_slot0, + FIELD_dsp340050b49a6c_fld2436GP_slot0, + FIELD_dsp340050b49a6c_fld2437GP_slot0, + FIELD_dsp340050b49a6c_fld2438GP_slot0, + FIELD_dsp340050b49a6c_fld2439GP_slot0, + FIELD_dsp340050b49a6c_fld2440GP_slot0, + FIELD_dsp340050b49a6c_fld2441GP_slot0, + FIELD_dsp340050b49a6c_fld2443GP_slot0, + FIELD_dsp340050b49a6c_fld2444GP_slot0, + FIELD_dsp340050b49a6c_fld2445, + FIELD_dsp340050b49a6c_fld2447GP_slot0, + FIELD_dsp340050b49a6c_fld2448, + FIELD_dsp340050b49a6c_fld2449GP_slot0, + FIELD_dsp340050b49a6c_fld2451GP_slot0, + FIELD_dsp340050b49a6c_fld2452GP_slot0, + FIELD_dsp340050b49a6c_fld2453GP_slot0, + FIELD_dsp340050b49a6c_fld2454GP_slot0, + FIELD_dsp340050b49a6c_fld2455GP_slot0, + FIELD_dsp340050b49a6c_fld2456GP_slot0, + FIELD_dsp340050b49a6c_fld2457GP_slot0, + FIELD_dsp340050b49a6c_fld2458GP_slot0, + FIELD_dsp340050b49a6c_fld2459GP_slot0, + FIELD_dsp340050b49a6c_fld2460GP_slot0, + FIELD_dsp340050b49a6c_fld2461GP_slot0, + FIELD_dsp340050b49a6c_fld2462, + FIELD_dsp340050b49a6c_fld2463GP_slot0, + FIELD_dsp340050b49a6c_fld2464GP_slot0, + FIELD_dsp340050b49a6c_fld2465GP_slot0, + FIELD_dsp340050b49a6c_fld2466GP_slot0, + FIELD_dsp340050b49a6c_fld2467GP_slot0, + FIELD_dsp340050b49a6c_fld2468GP_slot0, + FIELD_dsp340050b49a6c_fld2470GP_slot0, + FIELD_dsp340050b49a6c_fld2471GP_slot0, + FIELD_dsp340050b49a6c_fld2472GP_slot0, + FIELD_dsp340050b49a6c_fld2473GP_slot0, + FIELD_dsp340050b49a6c_fld2474GP_slot0, + FIELD_dsp340050b49a6c_fld2475GP_slot0, + FIELD_dsp340050b49a6c_fld2477GP_slot0, + FIELD_dsp340050b49a6c_fld2479GP_slot0, + FIELD_dsp340050b49a6c_fld2480GP_slot0, + FIELD_dsp340050b49a6c_fld2481GP_slot0, + FIELD_dsp340050b49a6c_fld2482GP_slot0, + FIELD_dsp340050b49a6c_fld2483GP_slot0, + FIELD_dsp340050b49a6c_fld2484GP_slot0, + FIELD_dsp340050b49a6c_fld2485GP_slot0, + FIELD_dsp340050b49a6c_fld2486GP_slot0, + FIELD_dsp340050b49a6c_fld2487GP_slot0, + FIELD_dsp340050b49a6c_fld2488GP_slot0, + FIELD_dsp340050b49a6c_fld2489GP_slot0, + FIELD_dsp340050b49a6c_fld2490GP_slot0, + FIELD_dsp340050b49a6c_fld2491GP_slot0, + FIELD_dsp340050b49a6c_fld2492GP_slot0, + FIELD_dsp340050b49a6c_fld2493GP_slot0, + FIELD_dsp340050b49a6c_fld2494GP_slot0, + FIELD_dsp340050b49a6c_fld2495GP_slot0, + FIELD_dsp340050b49a6c_fld2496GP_slot0, + FIELD_dsp340050b49a6c_fld2497GP_slot0, + FIELD_dsp340050b49a6c_fld2498GP_slot0, + FIELD_dsp340050b49a6c_fld2499GP_slot0, + FIELD_dsp340050b49a6c_fld2500GP_slot0, + FIELD_dsp340050b49a6c_fld2501GP_slot0, + FIELD_dsp340050b49a6c_fld2502GP_slot0, + FIELD_dsp340050b49a6c_fld2503GP_slot0, + FIELD_dsp340050b49a6c_fld2504GP_slot0, + FIELD_dsp340050b49a6c_fld2505GP_slot0, + FIELD_dsp340050b49a6c_fld2506GP_slot0, + FIELD_dsp340050b49a6c_fld2507GP_slot0, + FIELD_dsp340050b49a6c_fld2508GP_slot0, + FIELD_dsp340050b49a6c_fld2509GP_slot0, + FIELD_dsp340050b49a6c_fld2510GP_slot0, + FIELD_dsp340050b49a6c_fld2512GP_slot0, + FIELD_dsp340050b49a6c_fld2514GP_slot0, + FIELD_dsp340050b49a6c_fld2515GP_slot0, + FIELD_dsp340050b49a6c_fld2516GP_slot0, + FIELD_dsp340050b49a6c_fld2517GP_slot0, + FIELD_dsp340050b49a6c_fld2518GP_slot0, + FIELD_dsp340050b49a6c_fld2519GP_slot0, + FIELD_dsp340050b49a6c_fld2520GP_slot0, + FIELD_dsp340050b49a6c_fld2521GP_slot0, + FIELD_dsp340050b49a6c_fld2523GP_slot0, + FIELD_dsp340050b49a6c_fld2524GP_slot0, + FIELD_dsp340050b49a6c_fld2526GP_slot0, + FIELD_dsp340050b49a6c_fld2527GP_slot0, + FIELD_dsp340050b49a6c_fld2528GP_slot0, + FIELD_dsp340050b49a6c_fld2529GP_slot0, + FIELD_dsp340050b49a6c_fld2530, + FIELD_dsp340050b49a6c_fld2531GP_slot0, + FIELD_dsp340050b49a6c_fld3688GP_slot0, + FIELD_dsp340050b49a6c_fld3689GP_slot0, + FIELD_dsp340050b49a6c_fld3690GP_slot0, + FIELD_dsp340050b49a6c_fld3691GP_slot0, + FIELD_dsp340050b49a6c_fld3692GP_slot0, + FIELD_dsp340050b49a6c_fld3693GP_slot0, + FIELD_dsp340050b49a6c_fld3695GP_slot0, + FIELD_dsp340050b49a6c_fld3696GP_slot0, + FIELD_dsp340050b49a6c_fld3697GP_slot0, + FIELD_dsp340050b49a6c_fld3698GP_slot0, + FIELD_dsp340050b49a6c_fld3699GP_slot0, + FIELD_dsp340050b49a6c_fld3700GP_slot0, + FIELD_dsp340050b49a6c_fld3702GP_slot0, + FIELD_dsp340050b49a6c_fld3703GP_slot0, + FIELD_dsp340050b49a6c_fld3705GP_slot0, + FIELD_dsp340050b49a6c_fld3706GP_slot0, + FIELD_op0_s6, + FIELD_dsp340050b49a6c_fld2532DOT_slot2, + FIELD_dsp340050b49a6c_fld2533DOT_slot2, + FIELD_dsp340050b49a6c_fld2534DOT_slot2, + FIELD_dsp340050b49a6c_fld2535DOT_slot2, + FIELD_dsp340050b49a6c_fld2536DOT_slot2, + FIELD_dsp340050b49a6c_fld2537DOT_slot2, + FIELD_dsp340050b49a6c_fld2538DOT_slot2, + FIELD_dsp340050b49a6c_fld2539DOT_slot2, + FIELD_dsp340050b49a6c_fld2540DOT_slot2, + FIELD_dsp340050b49a6c_fld2541DOT_slot2, + FIELD_dsp340050b49a6c_fld2542DOT_slot2, + FIELD_dsp340050b49a6c_fld2543DOT_slot2, + FIELD_dsp340050b49a6c_fld2544DOT_slot2, + FIELD_dsp340050b49a6c_fld2545DOT_slot2, + FIELD_dsp340050b49a6c_fld2546DOT_slot2, + FIELD_dsp340050b49a6c_fld2547DOT_slot2, + FIELD_dsp340050b49a6c_fld2548DOT_slot2, + FIELD_dsp340050b49a6c_fld2549DOT_slot2, + FIELD_dsp340050b49a6c_fld2550DOT_slot2, + FIELD_dsp340050b49a6c_fld2551DOT_slot2, + FIELD_dsp340050b49a6c_fld2552DOT_slot2, + FIELD_dsp340050b49a6c_fld2553DOT_slot2, + FIELD_dsp340050b49a6c_fld2554DOT_slot2, + FIELD_dsp340050b49a6c_fld2555DOT_slot2, + FIELD_dsp340050b49a6c_fld2556DOT_slot2, + FIELD_dsp340050b49a6c_fld2557DOT_slot2, + FIELD_dsp340050b49a6c_fld2558DOT_slot2, + FIELD_dsp340050b49a6c_fld2559DOT_slot2, + FIELD_dsp340050b49a6c_fld2560DOT_slot2, + FIELD_dsp340050b49a6c_fld2561DOT_slot2, + FIELD_dsp340050b49a6c_fld2562DOT_slot2, + FIELD_dsp340050b49a6c_fld2563DOT_slot2, + FIELD_dsp340050b49a6c_fld2564DOT_slot2, + FIELD_dsp340050b49a6c_fld2565DOT_slot2, + FIELD_dsp340050b49a6c_fld2566DOT_slot2, + FIELD_dsp340050b49a6c_fld2567DOT_slot2, + FIELD_dsp340050b49a6c_fld2568DOT_slot2, + FIELD_dsp340050b49a6c_fld2569DOT_slot2, + FIELD_dsp340050b49a6c_fld2571DOT_slot2, + FIELD_dsp340050b49a6c_fld2572DOT_slot2, + FIELD_dsp340050b49a6c_fld2573DOT_slot2, + FIELD_dsp340050b49a6c_fld2574DOT_slot2, + FIELD_dsp340050b49a6c_fld2575DOT_slot2, + FIELD_dsp340050b49a6c_fld2576DOT_slot2, + FIELD_dsp340050b49a6c_fld2577DOT_slot2, + FIELD_dsp340050b49a6c_fld2578, + FIELD_dsp340050b49a6c_fld2579DOT_slot2, + FIELD_dsp340050b49a6c_fld2580DOT_slot2, + FIELD_dsp340050b49a6c_fld2581DOT_slot2, + FIELD_dsp340050b49a6c_fld2582DOT_slot2, + FIELD_dsp340050b49a6c_fld2583DOT_slot2, + FIELD_dsp340050b49a6c_fld2584DOT_slot2, + FIELD_dsp340050b49a6c_fld2585DOT_slot2, + FIELD_dsp340050b49a6c_fld2586DOT_slot2, + FIELD_dsp340050b49a6c_fld2587DOT_slot2, + FIELD_dsp340050b49a6c_fld2588DOT_slot2, + FIELD_dsp340050b49a6c_fld2589DOT_slot2, + FIELD_dsp340050b49a6c_fld2590DOT_slot2, + FIELD_dsp340050b49a6c_fld2591DOT_slot2, + FIELD_dsp340050b49a6c_fld2592DOT_slot2, + FIELD_dsp340050b49a6c_fld2595DOT_slot2, + FIELD_dsp340050b49a6c_fld2596DOT_slot2, + FIELD_dsp340050b49a6c_fld2598DOT_slot2, + FIELD_dsp340050b49a6c_fld2599DOT_slot2, + FIELD_dsp340050b49a6c_fld2601DOT_slot2, + FIELD_dsp340050b49a6c_fld2602DOT_slot2, + FIELD_dsp340050b49a6c_fld2604DOT_slot2, + FIELD_dsp340050b49a6c_fld2605, + FIELD_dsp340050b49a6c_fld2606DOT_slot2, + FIELD_dsp340050b49a6c_fld2608DOT_slot2, + FIELD_dsp340050b49a6c_fld2609DOT_slot2, + FIELD_dsp340050b49a6c_fld2610DOT_slot2, + FIELD_dsp340050b49a6c_fld2611DOT_slot2, + FIELD_dsp340050b49a6c_fld2612, + FIELD_dsp340050b49a6c_fld2613DOT_slot2, + FIELD_dsp340050b49a6c_fld2614, + FIELD_dsp340050b49a6c_fld2615DOT_slot2, + FIELD_dsp340050b49a6c_fld2616DOT_slot2, + FIELD_dsp340050b49a6c_fld2617DOT_slot2, + FIELD_dsp340050b49a6c_fld2618DOT_slot2, + FIELD_dsp340050b49a6c_fld2619DOT_slot2, + FIELD_dsp340050b49a6c_fld2620DOT_slot2, + FIELD_dsp340050b49a6c_fld2621DOT_slot2, + FIELD_dsp340050b49a6c_fld2622DOT_slot2, + FIELD_dsp340050b49a6c_fld2623DOT_slot2, + FIELD_dsp340050b49a6c_fld2624DOT_slot2, + FIELD_dsp340050b49a6c_fld2625, + FIELD_dsp340050b49a6c_fld2626DOT_slot2, + FIELD_dsp340050b49a6c_fld2628DOT_slot2, + FIELD_dsp340050b49a6c_fld2630DOT_slot2, + FIELD_dsp340050b49a6c_fld2632DOT_slot2, + FIELD_dsp340050b49a6c_fld2633DOT_slot2, + FIELD_dsp340050b49a6c_fld2635DOT_slot2, + FIELD_dsp340050b49a6c_fld2636DOT_slot2, + FIELD_dsp340050b49a6c_fld2637DOT_slot2, + FIELD_dsp340050b49a6c_fld2640DOT_slot2, + FIELD_dsp340050b49a6c_fld2641DOT_slot2, + FIELD_dsp340050b49a6c_fld2642DOT_slot2, + FIELD_dsp340050b49a6c_fld2643DOT_slot2, + FIELD_dsp340050b49a6c_fld2644DOT_slot2, + FIELD_dsp340050b49a6c_fld2645DOT_slot2, + FIELD_dsp340050b49a6c_fld2646DOT_slot2, + FIELD_dsp340050b49a6c_fld2647DOT_slot2, + FIELD_dsp340050b49a6c_fld2648DOT_slot2, + FIELD_dsp340050b49a6c_fld2649DOT_slot2, + FIELD_dsp340050b49a6c_fld2650DOT_slot2, + FIELD_dsp340050b49a6c_fld2651DOT_slot2, + FIELD_dsp340050b49a6c_fld2652DOT_slot2, + FIELD_dsp340050b49a6c_fld2654DOT_slot2, + FIELD_dsp340050b49a6c_fld2655DOT_slot2, + FIELD_dsp340050b49a6c_fld2656DOT_slot2, + FIELD_dsp340050b49a6c_fld2657DOT_slot2, + FIELD_dsp340050b49a6c_fld2658DOT_slot2, + FIELD_dsp340050b49a6c_fld3708DOT_slot2, + FIELD_dsp340050b49a6c_fld3709DOT_slot2, + FIELD_dsp340050b49a6c_fld3710DOT_slot2, + FIELD_dsp340050b49a6c_fld3711DOT_slot2, + FIELD_dsp340050b49a6c_fld3712, + FIELD_dsp340050b49a6c_fld3713DOT_slot2, + FIELD_dsp340050b49a6c_fld3714DOT_slot2, + FIELD_dsp340050b49a6c_fld3715, + FIELD_dsp340050b49a6c_fld3716DOT_slot2, + FIELD_dsp340050b49a6c_fld3717DOT_slot2, + FIELD_dsp340050b49a6c_fld3718, + FIELD_dsp340050b49a6c_fld3719DOT_slot2, + FIELD_dsp340050b49a6c_fld3721DOT_slot2, + FIELD_dsp340050b49a6c_fld3722, + FIELD_dsp340050b49a6c_fld3723DOT_slot2, + FIELD_dsp340050b49a6c_fld3724DOT_slot2, + FIELD_dsp340050b49a6c_fld3725DOT_slot2, + FIELD_dsp340050b49a6c_fld3726DOT_slot2, + FIELD_dsp340050b49a6c_fld3727DOT_slot2, + FIELD_dsp340050b49a6c_fld3728DOT_slot2, + FIELD_dsp340050b49a6c_fld3729DOT_slot2, + FIELD_dsp340050b49a6c_fld3731DOT_slot2, + FIELD_dsp340050b49a6c_fld3732DOT_slot2, + FIELD_dsp340050b49a6c_fld3733DOT_slot2, + FIELD_op0_s7, + FIELD_dsp340050b49a6c_fld3734DOT_slot1, + FIELD_op0_s8, + FIELD_dsp340050b49a6c_fld2068, + FIELD_dsp340050b49a6c_fld2666DOT_slot0, + FIELD_dsp340050b49a6c_fld2667DOT_slot0, + FIELD_dsp340050b49a6c_fld2668DOT_slot0, + FIELD_dsp340050b49a6c_fld2669DOT_slot0, + FIELD_dsp340050b49a6c_fld2671DOT_slot0, + FIELD_dsp340050b49a6c_fld2672DOT_slot0, + FIELD_dsp340050b49a6c_fld2673DOT_slot0, + FIELD_dsp340050b49a6c_fld2674DOT_slot0, + FIELD_dsp340050b49a6c_fld2675DOT_slot0, + FIELD_dsp340050b49a6c_fld2676DOT_slot0, + FIELD_dsp340050b49a6c_fld2677DOT_slot0, + FIELD_dsp340050b49a6c_fld2678DOT_slot0, + FIELD_dsp340050b49a6c_fld2679DOT_slot0, + FIELD_dsp340050b49a6c_fld2680DOT_slot0, + FIELD_dsp340050b49a6c_fld2681DOT_slot0, + FIELD_dsp340050b49a6c_fld2682DOT_slot0, + FIELD_dsp340050b49a6c_fld2683DOT_slot0, + FIELD_dsp340050b49a6c_fld2684DOT_slot0, + FIELD_dsp340050b49a6c_fld2685DOT_slot0, + FIELD_dsp340050b49a6c_fld2686DOT_slot0, + FIELD_dsp340050b49a6c_fld2688DOT_slot0, + FIELD_dsp340050b49a6c_fld2689DOT_slot0, + FIELD_dsp340050b49a6c_fld2690DOT_slot0, + FIELD_dsp340050b49a6c_fld2692DOT_slot0, + FIELD_dsp340050b49a6c_fld2693DOT_slot0, + FIELD_dsp340050b49a6c_fld2695DOT_slot0, + FIELD_dsp340050b49a6c_fld2697DOT_slot0, + FIELD_dsp340050b49a6c_fld2699DOT_slot0, + FIELD_dsp340050b49a6c_fld2700DOT_slot0, + FIELD_dsp340050b49a6c_fld2701DOT_slot0, + FIELD_dsp340050b49a6c_fld2702DOT_slot0, + FIELD_dsp340050b49a6c_fld2703DOT_slot0, + FIELD_dsp340050b49a6c_fld2704DOT_slot0, + FIELD_dsp340050b49a6c_fld2705DOT_slot0, + FIELD_dsp340050b49a6c_fld3735DOT_slot0, + FIELD_dsp340050b49a6c_fld3736, + FIELD_dsp340050b49a6c_fld3737DOT_slot0, + FIELD_dsp340050b49a6c_fld3738DOT_slot0, + FIELD_dsp340050b49a6c_fld3739DOT_slot0, + FIELD_dsp340050b49a6c_fld3740DOT_slot0, + FIELD_dsp340050b49a6c_fld3741DOT_slot0, + FIELD_dsp340050b49a6c_fld3742DOT_slot0, + FIELD_op0_s9, + FIELD_dsp340050b49a6c_fld2706PQ_slot2, + FIELD_dsp340050b49a6c_fld2707PQ_slot2, + FIELD_dsp340050b49a6c_fld2708PQ_slot2, + FIELD_dsp340050b49a6c_fld2709PQ_slot2, + FIELD_dsp340050b49a6c_fld2710PQ_slot2, + FIELD_dsp340050b49a6c_fld2711PQ_slot2, + FIELD_dsp340050b49a6c_fld2713PQ_slot2, + FIELD_dsp340050b49a6c_fld2714PQ_slot2, + FIELD_dsp340050b49a6c_fld2715PQ_slot2, + FIELD_dsp340050b49a6c_fld2717PQ_slot2, + FIELD_dsp340050b49a6c_fld2718PQ_slot2, + FIELD_dsp340050b49a6c_fld2719PQ_slot2, + FIELD_dsp340050b49a6c_fld2721PQ_slot2, + FIELD_dsp340050b49a6c_fld2722PQ_slot2, + FIELD_dsp340050b49a6c_fld2723PQ_slot2, + FIELD_dsp340050b49a6c_fld2724PQ_slot2, + FIELD_dsp340050b49a6c_fld2725PQ_slot2, + FIELD_dsp340050b49a6c_fld2726PQ_slot2, + FIELD_dsp340050b49a6c_fld2727PQ_slot2, + FIELD_dsp340050b49a6c_fld2728PQ_slot2, + FIELD_dsp340050b49a6c_fld2729PQ_slot2, + FIELD_dsp340050b49a6c_fld2730PQ_slot2, + FIELD_dsp340050b49a6c_fld2731PQ_slot2, + FIELD_dsp340050b49a6c_fld2732PQ_slot2, + FIELD_dsp340050b49a6c_fld2733PQ_slot2, + FIELD_dsp340050b49a6c_fld2734PQ_slot2, + FIELD_dsp340050b49a6c_fld2735PQ_slot2, + FIELD_dsp340050b49a6c_fld2736PQ_slot2, + FIELD_dsp340050b49a6c_fld2737, + FIELD_dsp340050b49a6c_fld2738PQ_slot2, + FIELD_dsp340050b49a6c_fld2739PQ_slot2, + FIELD_dsp340050b49a6c_fld2741PQ_slot2, + FIELD_dsp340050b49a6c_fld2742PQ_slot2, + FIELD_dsp340050b49a6c_fld2743PQ_slot2, + FIELD_dsp340050b49a6c_fld2746PQ_slot2, + FIELD_dsp340050b49a6c_fld2747PQ_slot2, + FIELD_dsp340050b49a6c_fld2748PQ_slot2, + FIELD_dsp340050b49a6c_fld2750PQ_slot2, + FIELD_dsp340050b49a6c_fld2751PQ_slot2, + FIELD_dsp340050b49a6c_fld2752PQ_slot2, + FIELD_dsp340050b49a6c_fld2753PQ_slot2, + FIELD_dsp340050b49a6c_fld2754PQ_slot2, + FIELD_dsp340050b49a6c_fld2755PQ_slot2, + FIELD_dsp340050b49a6c_fld2756PQ_slot2, + FIELD_dsp340050b49a6c_fld2757PQ_slot2, + FIELD_dsp340050b49a6c_fld2758PQ_slot2, + FIELD_dsp340050b49a6c_fld2759PQ_slot2, + FIELD_dsp340050b49a6c_fld2760PQ_slot2, + FIELD_dsp340050b49a6c_fld2761PQ_slot2, + FIELD_dsp340050b49a6c_fld2762PQ_slot2, + FIELD_dsp340050b49a6c_fld2763PQ_slot2, + FIELD_dsp340050b49a6c_fld2764PQ_slot2, + FIELD_dsp340050b49a6c_fld2765PQ_slot2, + FIELD_dsp340050b49a6c_fld2766PQ_slot2, + FIELD_dsp340050b49a6c_fld2767PQ_slot2, + FIELD_dsp340050b49a6c_fld2768PQ_slot2, + FIELD_dsp340050b49a6c_fld2769PQ_slot2, + FIELD_dsp340050b49a6c_fld2770PQ_slot2, + FIELD_dsp340050b49a6c_fld2771PQ_slot2, + FIELD_dsp340050b49a6c_fld2772PQ_slot2, + FIELD_dsp340050b49a6c_fld2773PQ_slot2, + FIELD_dsp340050b49a6c_fld2774PQ_slot2, + FIELD_dsp340050b49a6c_fld2775PQ_slot2, + FIELD_dsp340050b49a6c_fld2776PQ_slot2, + FIELD_dsp340050b49a6c_fld2777PQ_slot2, + FIELD_dsp340050b49a6c_fld2778PQ_slot2, + FIELD_dsp340050b49a6c_fld2779PQ_slot2, + FIELD_dsp340050b49a6c_fld2780PQ_slot2, + FIELD_dsp340050b49a6c_fld2781PQ_slot2, + FIELD_dsp340050b49a6c_fld2782PQ_slot2, + FIELD_dsp340050b49a6c_fld2783PQ_slot2, + FIELD_dsp340050b49a6c_fld2784PQ_slot2, + FIELD_dsp340050b49a6c_fld2785PQ_slot2, + FIELD_dsp340050b49a6c_fld2786PQ_slot2, + FIELD_dsp340050b49a6c_fld2787PQ_slot2, + FIELD_dsp340050b49a6c_fld2788PQ_slot2, + FIELD_dsp340050b49a6c_fld2789PQ_slot2, + FIELD_dsp340050b49a6c_fld2790PQ_slot2, + FIELD_dsp340050b49a6c_fld2791PQ_slot2, + FIELD_dsp340050b49a6c_fld2792PQ_slot2, + FIELD_dsp340050b49a6c_fld2793PQ_slot2, + FIELD_dsp340050b49a6c_fld2795PQ_slot2, + FIELD_dsp340050b49a6c_fld2796PQ_slot2, + FIELD_dsp340050b49a6c_fld2798PQ_slot2, + FIELD_dsp340050b49a6c_fld2801PQ_slot2, + FIELD_dsp340050b49a6c_fld2803PQ_slot2, + FIELD_dsp340050b49a6c_fld2805PQ_slot2, + FIELD_dsp340050b49a6c_fld2806PQ_slot2, + FIELD_dsp340050b49a6c_fld2807PQ_slot2, + FIELD_dsp340050b49a6c_fld2808PQ_slot2, + FIELD_dsp340050b49a6c_fld2809PQ_slot2, + FIELD_dsp340050b49a6c_fld2810PQ_slot2, + FIELD_dsp340050b49a6c_fld2811PQ_slot2, + FIELD_dsp340050b49a6c_fld2812PQ_slot2, + FIELD_dsp340050b49a6c_fld2814PQ_slot2, + FIELD_dsp340050b49a6c_fld2816PQ_slot2, + FIELD_dsp340050b49a6c_fld2817, + FIELD_dsp340050b49a6c_fld2818PQ_slot2, + FIELD_dsp340050b49a6c_fld2819, + FIELD_dsp340050b49a6c_fld2820PQ_slot2, + FIELD_dsp340050b49a6c_fld2821PQ_slot2, + FIELD_dsp340050b49a6c_fld2823PQ_slot2, + FIELD_dsp340050b49a6c_fld3744PQ_slot2, + FIELD_dsp340050b49a6c_fld3745PQ_slot2, + FIELD_dsp340050b49a6c_fld3746PQ_slot2, + FIELD_dsp340050b49a6c_fld3747PQ_slot2, + FIELD_dsp340050b49a6c_fld3748, + FIELD_dsp340050b49a6c_fld3749PQ_slot2, + FIELD_dsp340050b49a6c_fld3750PQ_slot2, + FIELD_dsp340050b49a6c_fld3751PQ_slot2, + FIELD_dsp340050b49a6c_fld3752PQ_slot2, + FIELD_dsp340050b49a6c_fld3753PQ_slot2, + FIELD_dsp340050b49a6c_fld3754PQ_slot2, + FIELD_dsp340050b49a6c_fld3756PQ_slot2, + FIELD_dsp340050b49a6c_fld3757PQ_slot2, + FIELD_dsp340050b49a6c_fld3758PQ_slot2, + FIELD_dsp340050b49a6c_fld3759PQ_slot2, + FIELD_dsp340050b49a6c_fld3760PQ_slot2, + FIELD_op0_s10, + FIELD_dsp340050b49a6c_fld2825PQ_slot1, + FIELD_dsp340050b49a6c_fld2826PQ_slot1, + FIELD_dsp340050b49a6c_fld3761PQ_slot1, + FIELD_op0_s11, + FIELD_dsp340050b49a6c_fld2059, + FIELD_dsp340050b49a6c_fld2069, + FIELD_dsp340050b49a6c_fld2827PQ_slot0, + FIELD_dsp340050b49a6c_fld2829PQ_slot0, + FIELD_dsp340050b49a6c_fld2830PQ_slot0, + FIELD_dsp340050b49a6c_fld2831PQ_slot0, + FIELD_dsp340050b49a6c_fld2832PQ_slot0, + FIELD_dsp340050b49a6c_fld2833PQ_slot0, + FIELD_dsp340050b49a6c_fld2835PQ_slot0, + FIELD_dsp340050b49a6c_fld2836PQ_slot0, + FIELD_dsp340050b49a6c_fld2837PQ_slot0, + FIELD_dsp340050b49a6c_fld2838PQ_slot0, + FIELD_dsp340050b49a6c_fld2839PQ_slot0, + FIELD_dsp340050b49a6c_fld2840PQ_slot0, + FIELD_dsp340050b49a6c_fld2842PQ_slot0, + FIELD_dsp340050b49a6c_fld2843PQ_slot0, + FIELD_dsp340050b49a6c_fld2844PQ_slot0, + FIELD_dsp340050b49a6c_fld2845PQ_slot0, + FIELD_dsp340050b49a6c_fld2846PQ_slot0, + FIELD_dsp340050b49a6c_fld2847PQ_slot0, + FIELD_dsp340050b49a6c_fld2849PQ_slot0, + FIELD_dsp340050b49a6c_fld2850PQ_slot0, + FIELD_dsp340050b49a6c_fld2851PQ_slot0, + FIELD_dsp340050b49a6c_fld2852PQ_slot0, + FIELD_dsp340050b49a6c_fld2853PQ_slot0, + FIELD_dsp340050b49a6c_fld2854PQ_slot0, + FIELD_dsp340050b49a6c_fld2855PQ_slot0, + FIELD_dsp340050b49a6c_fld2856PQ_slot0, + FIELD_dsp340050b49a6c_fld2857PQ_slot0, + FIELD_dsp340050b49a6c_fld2858PQ_slot0, + FIELD_dsp340050b49a6c_fld2859PQ_slot0, + FIELD_dsp340050b49a6c_fld2860PQ_slot0, + FIELD_dsp340050b49a6c_fld2861PQ_slot0, + FIELD_dsp340050b49a6c_fld2863PQ_slot0, + FIELD_dsp340050b49a6c_fld2864PQ_slot0, + FIELD_dsp340050b49a6c_fld2865, + FIELD_dsp340050b49a6c_fld2867PQ_slot0, + FIELD_dsp340050b49a6c_fld2869PQ_slot0, + FIELD_dsp340050b49a6c_fld2871PQ_slot0, + FIELD_dsp340050b49a6c_fld2872PQ_slot0, + FIELD_dsp340050b49a6c_fld2873PQ_slot0, + FIELD_dsp340050b49a6c_fld2874PQ_slot0, + FIELD_dsp340050b49a6c_fld2875PQ_slot0, + FIELD_dsp340050b49a6c_fld2876PQ_slot0, + FIELD_dsp340050b49a6c_fld2877PQ_slot0, + FIELD_dsp340050b49a6c_fld2878PQ_slot0, + FIELD_dsp340050b49a6c_fld2879PQ_slot0, + FIELD_dsp340050b49a6c_fld2880PQ_slot0, + FIELD_dsp340050b49a6c_fld2881PQ_slot0, + FIELD_dsp340050b49a6c_fld2882, + FIELD_dsp340050b49a6c_fld2883PQ_slot0, + FIELD_dsp340050b49a6c_fld2884PQ_slot0, + FIELD_dsp340050b49a6c_fld2885PQ_slot0, + FIELD_dsp340050b49a6c_fld2886PQ_slot0, + FIELD_dsp340050b49a6c_fld2887PQ_slot0, + FIELD_dsp340050b49a6c_fld2888PQ_slot0, + FIELD_dsp340050b49a6c_fld2890PQ_slot0, + FIELD_dsp340050b49a6c_fld2891PQ_slot0, + FIELD_dsp340050b49a6c_fld2892PQ_slot0, + FIELD_dsp340050b49a6c_fld2893PQ_slot0, + FIELD_dsp340050b49a6c_fld2894PQ_slot0, + FIELD_dsp340050b49a6c_fld2895PQ_slot0, + FIELD_dsp340050b49a6c_fld2897PQ_slot0, + FIELD_dsp340050b49a6c_fld2899PQ_slot0, + FIELD_dsp340050b49a6c_fld2900PQ_slot0, + FIELD_dsp340050b49a6c_fld2901PQ_slot0, + FIELD_dsp340050b49a6c_fld2902PQ_slot0, + FIELD_dsp340050b49a6c_fld2903PQ_slot0, + FIELD_dsp340050b49a6c_fld2904PQ_slot0, + FIELD_dsp340050b49a6c_fld2905PQ_slot0, + FIELD_dsp340050b49a6c_fld2906PQ_slot0, + FIELD_dsp340050b49a6c_fld2907PQ_slot0, + FIELD_dsp340050b49a6c_fld2908PQ_slot0, + FIELD_dsp340050b49a6c_fld2909PQ_slot0, + FIELD_dsp340050b49a6c_fld2910PQ_slot0, + FIELD_dsp340050b49a6c_fld2911PQ_slot0, + FIELD_dsp340050b49a6c_fld2912PQ_slot0, + FIELD_dsp340050b49a6c_fld2913PQ_slot0, + FIELD_dsp340050b49a6c_fld2914PQ_slot0, + FIELD_dsp340050b49a6c_fld2915PQ_slot0, + FIELD_dsp340050b49a6c_fld2916PQ_slot0, + FIELD_dsp340050b49a6c_fld2917PQ_slot0, + FIELD_dsp340050b49a6c_fld2918PQ_slot0, + FIELD_dsp340050b49a6c_fld2919PQ_slot0, + FIELD_dsp340050b49a6c_fld2920PQ_slot0, + FIELD_dsp340050b49a6c_fld2921PQ_slot0, + FIELD_dsp340050b49a6c_fld2922PQ_slot0, + FIELD_dsp340050b49a6c_fld2923PQ_slot0, + FIELD_dsp340050b49a6c_fld2924PQ_slot0, + FIELD_dsp340050b49a6c_fld2925PQ_slot0, + FIELD_dsp340050b49a6c_fld2926PQ_slot0, + FIELD_dsp340050b49a6c_fld2927PQ_slot0, + FIELD_dsp340050b49a6c_fld2928PQ_slot0, + FIELD_dsp340050b49a6c_fld2929PQ_slot0, + FIELD_dsp340050b49a6c_fld2930PQ_slot0, + FIELD_dsp340050b49a6c_fld2932PQ_slot0, + FIELD_dsp340050b49a6c_fld2934PQ_slot0, + FIELD_dsp340050b49a6c_fld2935PQ_slot0, + FIELD_dsp340050b49a6c_fld2936PQ_slot0, + FIELD_dsp340050b49a6c_fld2937PQ_slot0, + FIELD_dsp340050b49a6c_fld2939PQ_slot0, + FIELD_dsp340050b49a6c_fld2940, + FIELD_dsp340050b49a6c_fld2941PQ_slot0, + FIELD_dsp340050b49a6c_fld2942PQ_slot0, + FIELD_dsp340050b49a6c_fld2943PQ_slot0, + FIELD_dsp340050b49a6c_fld2945PQ_slot0, + FIELD_dsp340050b49a6c_fld2946PQ_slot0, + FIELD_dsp340050b49a6c_fld2947PQ_slot0, + FIELD_dsp340050b49a6c_fld2948PQ_slot0, + FIELD_dsp340050b49a6c_fld2949PQ_slot0, + FIELD_dsp340050b49a6c_fld2950PQ_slot0, + FIELD_dsp340050b49a6c_fld3763PQ_slot0, + FIELD_dsp340050b49a6c_fld3764PQ_slot0, + FIELD_dsp340050b49a6c_fld3765PQ_slot0, + FIELD_dsp340050b49a6c_fld3766PQ_slot0, + FIELD_dsp340050b49a6c_fld3767PQ_slot0, + FIELD_dsp340050b49a6c_fld3768PQ_slot0, + FIELD_dsp340050b49a6c_fld3769PQ_slot0, + FIELD_dsp340050b49a6c_fld3770PQ_slot0, + FIELD_dsp340050b49a6c_fld3771PQ_slot0, + FIELD_dsp340050b49a6c_fld3772, + FIELD_dsp340050b49a6c_fld3773PQ_slot0, + FIELD_dsp340050b49a6c_fld3775PQ_slot0, + FIELD_dsp340050b49a6c_fld3776PQ_slot0, + FIELD_dsp340050b49a6c_fld3777PQ_slot0, + FIELD_dsp340050b49a6c_fld3778PQ_slot0, + FIELD_dsp340050b49a6c_fld3779PQ_slot0, + FIELD_dsp340050b49a6c_fld3780PQ_slot0, + FIELD_op0_s12, + FIELD_dsp340050b49a6c_fld2953ACC2_slot2, + FIELD_dsp340050b49a6c_fld2954ACC2_slot2, + FIELD_dsp340050b49a6c_fld2955ACC2_slot2, + FIELD_dsp340050b49a6c_fld2956ACC2_slot2, + FIELD_dsp340050b49a6c_fld2957ACC2_slot2, + FIELD_dsp340050b49a6c_fld2958ACC2_slot2, + FIELD_dsp340050b49a6c_fld2959ACC2_slot2, + FIELD_dsp340050b49a6c_fld2960ACC2_slot2, + FIELD_dsp340050b49a6c_fld2963ACC2_slot2, + FIELD_dsp340050b49a6c_fld2964ACC2_slot2, + FIELD_dsp340050b49a6c_fld2966ACC2_slot2, + FIELD_dsp340050b49a6c_fld2967ACC2_slot2, + FIELD_dsp340050b49a6c_fld3782ACC2_slot2, + FIELD_dsp340050b49a6c_fld3783ACC2_slot2, + FIELD_dsp340050b49a6c_fld3784ACC2_slot2, + FIELD_dsp340050b49a6c_fld3785ACC2_slot2, + FIELD_dsp340050b49a6c_fld3786ACC2_slot2, + FIELD_dsp340050b49a6c_fld3788ACC2_slot2, + FIELD_op0_s13, + FIELD_dsp340050b49a6c_fld2028, + FIELD_dsp340050b49a6c_fld2075, + FIELD_dsp340050b49a6c_fld2968ACC2_slot1, + FIELD_dsp340050b49a6c_fld2969ACC2_slot1, + FIELD_dsp340050b49a6c_fld3790ACC2_slot1, + FIELD_dsp340050b49a6c_fld3793ACC2_slot1, + FIELD_op0_s14, + FIELD_dsp340050b49a6c_fld2973ACC2_slot0, + FIELD_dsp340050b49a6c_fld2974ACC2_slot0, + FIELD_dsp340050b49a6c_fld2975ACC2_slot0, + FIELD_dsp340050b49a6c_fld2976ACC2_slot0, + FIELD_dsp340050b49a6c_fld2977ACC2_slot0, + FIELD_dsp340050b49a6c_fld2980ACC2_slot0, + FIELD_dsp340050b49a6c_fld2981ACC2_slot0, + FIELD_dsp340050b49a6c_fld2982ACC2_slot0, + FIELD_dsp340050b49a6c_fld2984ACC2_slot0, + FIELD_dsp340050b49a6c_fld2985ACC2_slot0, + FIELD_dsp340050b49a6c_fld2987ACC2_slot0, + FIELD_dsp340050b49a6c_fld2989ACC2_slot0, + FIELD_dsp340050b49a6c_fld2990ACC2_slot0, + FIELD_dsp340050b49a6c_fld3795ACC2_slot0, + FIELD_dsp340050b49a6c_fld3796ACC2_slot0, + FIELD_dsp340050b49a6c_fld3797, + FIELD_dsp340050b49a6c_fld3798ACC2_slot0, + FIELD_dsp340050b49a6c_fld3799ACC2_slot0, + FIELD_dsp340050b49a6c_fld3800ACC2_slot0, + FIELD_dsp340050b49a6c_fld3801ACC2_slot0, + FIELD_dsp340050b49a6c_fld3802ACC2_slot0, + FIELD_dsp340050b49a6c_fld3803ACC2_slot0, + FIELD_op0_s15, + FIELD_dsp340050b49a6c_fld2991SMOD_slot2, + FIELD_dsp340050b49a6c_fld2992SMOD_slot2, + FIELD_dsp340050b49a6c_fld2993SMOD_slot2, + FIELD_dsp340050b49a6c_fld2994SMOD_slot2, + FIELD_dsp340050b49a6c_fld2995SMOD_slot2, + FIELD_dsp340050b49a6c_fld2996SMOD_slot2, + FIELD_dsp340050b49a6c_fld2997SMOD_slot2, + FIELD_dsp340050b49a6c_fld2998SMOD_slot2, + FIELD_dsp340050b49a6c_fld2999SMOD_slot2, + FIELD_dsp340050b49a6c_fld3000SMOD_slot2, + FIELD_dsp340050b49a6c_fld3001SMOD_slot2, + FIELD_dsp340050b49a6c_fld3002SMOD_slot2, + FIELD_dsp340050b49a6c_fld3003SMOD_slot2, + FIELD_dsp340050b49a6c_fld3004SMOD_slot2, + FIELD_dsp340050b49a6c_fld3005SMOD_slot2, + FIELD_dsp340050b49a6c_fld3006SMOD_slot2, + FIELD_dsp340050b49a6c_fld3007SMOD_slot2, + FIELD_dsp340050b49a6c_fld3008SMOD_slot2, + FIELD_dsp340050b49a6c_fld3009SMOD_slot2, + FIELD_dsp340050b49a6c_fld3010SMOD_slot2, + FIELD_dsp340050b49a6c_fld3011SMOD_slot2, + FIELD_dsp340050b49a6c_fld3012SMOD_slot2, + FIELD_dsp340050b49a6c_fld3013SMOD_slot2, + FIELD_dsp340050b49a6c_fld3014SMOD_slot2, + FIELD_dsp340050b49a6c_fld3015SMOD_slot2, + FIELD_dsp340050b49a6c_fld3016SMOD_slot2, + FIELD_dsp340050b49a6c_fld3017SMOD_slot2, + FIELD_dsp340050b49a6c_fld3018SMOD_slot2, + FIELD_dsp340050b49a6c_fld3019SMOD_slot2, + FIELD_dsp340050b49a6c_fld3020SMOD_slot2, + FIELD_dsp340050b49a6c_fld3021SMOD_slot2, + FIELD_dsp340050b49a6c_fld3022SMOD_slot2, + FIELD_dsp340050b49a6c_fld3023SMOD_slot2, + FIELD_dsp340050b49a6c_fld3024SMOD_slot2, + FIELD_dsp340050b49a6c_fld3025SMOD_slot2, + FIELD_dsp340050b49a6c_fld3026SMOD_slot2, + FIELD_dsp340050b49a6c_fld3027SMOD_slot2, + FIELD_dsp340050b49a6c_fld3028SMOD_slot2, + FIELD_dsp340050b49a6c_fld3030SMOD_slot2, + FIELD_dsp340050b49a6c_fld3031SMOD_slot2, + FIELD_dsp340050b49a6c_fld3032SMOD_slot2, + FIELD_dsp340050b49a6c_fld3033SMOD_slot2, + FIELD_dsp340050b49a6c_fld3034SMOD_slot2, + FIELD_dsp340050b49a6c_fld3035SMOD_slot2, + FIELD_dsp340050b49a6c_fld3036SMOD_slot2, + FIELD_dsp340050b49a6c_fld3038SMOD_slot2, + FIELD_dsp340050b49a6c_fld3039SMOD_slot2, + FIELD_dsp340050b49a6c_fld3040SMOD_slot2, + FIELD_dsp340050b49a6c_fld3043SMOD_slot2, + FIELD_dsp340050b49a6c_fld3044SMOD_slot2, + FIELD_dsp340050b49a6c_fld3046SMOD_slot2, + FIELD_dsp340050b49a6c_fld3047SMOD_slot2, + FIELD_dsp340050b49a6c_fld3048, + FIELD_dsp340050b49a6c_fld3049SMOD_slot2, + FIELD_dsp340050b49a6c_fld3050SMOD_slot2, + FIELD_dsp340050b49a6c_fld3051SMOD_slot2, + FIELD_dsp340050b49a6c_fld3052SMOD_slot2, + FIELD_dsp340050b49a6c_fld3053SMOD_slot2, + FIELD_dsp340050b49a6c_fld3054SMOD_slot2, + FIELD_dsp340050b49a6c_fld3055SMOD_slot2, + FIELD_dsp340050b49a6c_fld3056SMOD_slot2, + FIELD_dsp340050b49a6c_fld3058SMOD_slot2, + FIELD_dsp340050b49a6c_fld3059SMOD_slot2, + FIELD_dsp340050b49a6c_fld3061SMOD_slot2, + FIELD_dsp340050b49a6c_fld3062, + FIELD_dsp340050b49a6c_fld3063SMOD_slot2, + FIELD_dsp340050b49a6c_fld3065SMOD_slot2, + FIELD_dsp340050b49a6c_fld3066SMOD_slot2, + FIELD_dsp340050b49a6c_fld3067SMOD_slot2, + FIELD_dsp340050b49a6c_fld3068SMOD_slot2, + FIELD_dsp340050b49a6c_fld3069SMOD_slot2, + FIELD_dsp340050b49a6c_fld3070, + FIELD_dsp340050b49a6c_fld3071SMOD_slot2, + FIELD_dsp340050b49a6c_fld3072SMOD_slot2, + FIELD_dsp340050b49a6c_fld3073SMOD_slot2, + FIELD_dsp340050b49a6c_fld3074SMOD_slot2, + FIELD_dsp340050b49a6c_fld3075SMOD_slot2, + FIELD_dsp340050b49a6c_fld3076SMOD_slot2, + FIELD_dsp340050b49a6c_fld3077SMOD_slot2, + FIELD_dsp340050b49a6c_fld3078SMOD_slot2, + FIELD_dsp340050b49a6c_fld3079SMOD_slot2, + FIELD_dsp340050b49a6c_fld3080SMOD_slot2, + FIELD_dsp340050b49a6c_fld3081SMOD_slot2, + FIELD_dsp340050b49a6c_fld3082SMOD_slot2, + FIELD_dsp340050b49a6c_fld3084SMOD_slot2, + FIELD_dsp340050b49a6c_fld3085SMOD_slot2, + FIELD_dsp340050b49a6c_fld3087SMOD_slot2, + FIELD_dsp340050b49a6c_fld3088SMOD_slot2, + FIELD_dsp340050b49a6c_fld3090SMOD_slot2, + FIELD_dsp340050b49a6c_fld3091SMOD_slot2, + FIELD_dsp340050b49a6c_fld3092SMOD_slot2, + FIELD_dsp340050b49a6c_fld3093SMOD_slot2, + FIELD_dsp340050b49a6c_fld3096SMOD_slot2, + FIELD_dsp340050b49a6c_fld3097SMOD_slot2, + FIELD_dsp340050b49a6c_fld3098SMOD_slot2, + FIELD_dsp340050b49a6c_fld3099SMOD_slot2, + FIELD_dsp340050b49a6c_fld3100SMOD_slot2, + FIELD_dsp340050b49a6c_fld3101SMOD_slot2, + FIELD_dsp340050b49a6c_fld3102SMOD_slot2, + FIELD_dsp340050b49a6c_fld3104SMOD_slot2, + FIELD_dsp340050b49a6c_fld3105SMOD_slot2, + FIELD_dsp340050b49a6c_fld3106SMOD_slot2, + FIELD_dsp340050b49a6c_fld3107SMOD_slot2, + FIELD_dsp340050b49a6c_fld3108SMOD_slot2, + FIELD_dsp340050b49a6c_fld3109SMOD_slot2, + FIELD_dsp340050b49a6c_fld3110SMOD_slot2, + FIELD_dsp340050b49a6c_fld3111SMOD_slot2, + FIELD_dsp340050b49a6c_fld3113SMOD_slot2, + FIELD_dsp340050b49a6c_fld3114SMOD_slot2, + FIELD_dsp340050b49a6c_fld3115SMOD_slot2, + FIELD_dsp340050b49a6c_fld3116SMOD_slot2, + FIELD_dsp340050b49a6c_fld3805SMOD_slot2, + FIELD_dsp340050b49a6c_fld3806SMOD_slot2, + FIELD_dsp340050b49a6c_fld3807SMOD_slot2, + FIELD_dsp340050b49a6c_fld3808, + FIELD_dsp340050b49a6c_fld3809SMOD_slot2, + FIELD_dsp340050b49a6c_fld3810SMOD_slot2, + FIELD_dsp340050b49a6c_fld3812SMOD_slot2, + FIELD_dsp340050b49a6c_fld3813SMOD_slot2, + FIELD_dsp340050b49a6c_fld3814SMOD_slot2, + FIELD_dsp340050b49a6c_fld3816SMOD_slot2, + FIELD_dsp340050b49a6c_fld3817, + FIELD_dsp340050b49a6c_fld3818SMOD_slot2, + FIELD_dsp340050b49a6c_fld3819SMOD_slot2, + FIELD_dsp340050b49a6c_fld3821SMOD_slot2, + FIELD_dsp340050b49a6c_fld3822SMOD_slot2, + FIELD_dsp340050b49a6c_fld3823SMOD_slot2, + FIELD_dsp340050b49a6c_fld3824SMOD_slot2, + FIELD_dsp340050b49a6c_fld3825SMOD_slot2, + FIELD_dsp340050b49a6c_fld3826SMOD_slot2, + FIELD_dsp340050b49a6c_fld3827SMOD_slot2, + FIELD_dsp340050b49a6c_fld3828SMOD_slot2, + FIELD_op0_s16, + FIELD_dsp340050b49a6c_fld2033, + FIELD_dsp340050b49a6c_fld2080, + FIELD_dsp340050b49a6c_fld3117SMOD_slot1, + FIELD_dsp340050b49a6c_fld3118SMOD_slot1, + FIELD_dsp340050b49a6c_fld3829SMOD_slot1, + FIELD_op0_s17, + FIELD_dsp340050b49a6c_fld3119SMOD_slot0, + FIELD_dsp340050b49a6c_fld3120SMOD_slot0, + FIELD_dsp340050b49a6c_fld3121SMOD_slot0, + FIELD_dsp340050b49a6c_fld3122SMOD_slot0, + FIELD_dsp340050b49a6c_fld3123SMOD_slot0, + FIELD_dsp340050b49a6c_fld3125SMOD_slot0, + FIELD_dsp340050b49a6c_fld3126SMOD_slot0, + FIELD_dsp340050b49a6c_fld3127SMOD_slot0, + FIELD_dsp340050b49a6c_fld3128SMOD_slot0, + FIELD_dsp340050b49a6c_fld3129SMOD_slot0, + FIELD_dsp340050b49a6c_fld3130SMOD_slot0, + FIELD_dsp340050b49a6c_fld3131SMOD_slot0, + FIELD_dsp340050b49a6c_fld3132SMOD_slot0, + FIELD_dsp340050b49a6c_fld3133SMOD_slot0, + FIELD_dsp340050b49a6c_fld3134SMOD_slot0, + FIELD_dsp340050b49a6c_fld3135SMOD_slot0, + FIELD_dsp340050b49a6c_fld3136SMOD_slot0, + FIELD_dsp340050b49a6c_fld3137SMOD_slot0, + FIELD_dsp340050b49a6c_fld3138SMOD_slot0, + FIELD_dsp340050b49a6c_fld3139SMOD_slot0, + FIELD_dsp340050b49a6c_fld3140SMOD_slot0, + FIELD_dsp340050b49a6c_fld3141SMOD_slot0, + FIELD_dsp340050b49a6c_fld3142SMOD_slot0, + FIELD_dsp340050b49a6c_fld3143SMOD_slot0, + FIELD_dsp340050b49a6c_fld3144SMOD_slot0, + FIELD_dsp340050b49a6c_fld3145SMOD_slot0, + FIELD_dsp340050b49a6c_fld3146SMOD_slot0, + FIELD_dsp340050b49a6c_fld3148SMOD_slot0, + FIELD_dsp340050b49a6c_fld3149SMOD_slot0, + FIELD_dsp340050b49a6c_fld3150, + FIELD_dsp340050b49a6c_fld3152SMOD_slot0, + FIELD_dsp340050b49a6c_fld3153SMOD_slot0, + FIELD_dsp340050b49a6c_fld3155SMOD_slot0, + FIELD_dsp340050b49a6c_fld3156SMOD_slot0, + FIELD_dsp340050b49a6c_fld3157SMOD_slot0, + FIELD_dsp340050b49a6c_fld3158SMOD_slot0, + FIELD_dsp340050b49a6c_fld3159SMOD_slot0, + FIELD_dsp340050b49a6c_fld3160SMOD_slot0, + FIELD_dsp340050b49a6c_fld3161SMOD_slot0, + FIELD_dsp340050b49a6c_fld3164SMOD_slot0, + FIELD_dsp340050b49a6c_fld3165SMOD_slot0, + FIELD_dsp340050b49a6c_fld3166SMOD_slot0, + FIELD_dsp340050b49a6c_fld3168SMOD_slot0, + FIELD_dsp340050b49a6c_fld3170SMOD_slot0, + FIELD_dsp340050b49a6c_fld3171SMOD_slot0, + FIELD_dsp340050b49a6c_fld3172SMOD_slot0, + FIELD_dsp340050b49a6c_fld3173SMOD_slot0, + FIELD_dsp340050b49a6c_fld3174SMOD_slot0, + FIELD_dsp340050b49a6c_fld3175SMOD_slot0, + FIELD_dsp340050b49a6c_fld3176SMOD_slot0, + FIELD_dsp340050b49a6c_fld3177SMOD_slot0, + FIELD_dsp340050b49a6c_fld3178SMOD_slot0, + FIELD_dsp340050b49a6c_fld3179SMOD_slot0, + FIELD_dsp340050b49a6c_fld3180SMOD_slot0, + FIELD_dsp340050b49a6c_fld3181SMOD_slot0, + FIELD_dsp340050b49a6c_fld3182SMOD_slot0, + FIELD_dsp340050b49a6c_fld3184SMOD_slot0, + FIELD_dsp340050b49a6c_fld3186SMOD_slot0, + FIELD_dsp340050b49a6c_fld3188SMOD_slot0, + FIELD_dsp340050b49a6c_fld3832SMOD_slot0, + FIELD_dsp340050b49a6c_fld3833SMOD_slot0, + FIELD_dsp340050b49a6c_fld3834, + FIELD_dsp340050b49a6c_fld3836SMOD_slot0, + FIELD_dsp340050b49a6c_fld3837SMOD_slot0, + FIELD_dsp340050b49a6c_fld3838SMOD_slot0, + FIELD_dsp340050b49a6c_fld3841SMOD_slot0, + FIELD_dsp340050b49a6c_fld3842SMOD_slot0, + FIELD_op0_s18, + FIELD_dsp340050b49a6c_fld2074, + FIELD_dsp340050b49a6c_fld3191LLR_slot2, + FIELD_dsp340050b49a6c_fld3192LLR_slot2, + FIELD_dsp340050b49a6c_fld3193LLR_slot2, + FIELD_dsp340050b49a6c_fld3194LLR_slot2, + FIELD_dsp340050b49a6c_fld3195LLR_slot2, + FIELD_dsp340050b49a6c_fld3196LLR_slot2, + FIELD_dsp340050b49a6c_fld3197LLR_slot2, + FIELD_dsp340050b49a6c_fld3198LLR_slot2, + FIELD_dsp340050b49a6c_fld3199LLR_slot2, + FIELD_dsp340050b49a6c_fld3200LLR_slot2, + FIELD_dsp340050b49a6c_fld3201LLR_slot2, + FIELD_dsp340050b49a6c_fld3202LLR_slot2, + FIELD_dsp340050b49a6c_fld3203LLR_slot2, + FIELD_dsp340050b49a6c_fld3204LLR_slot2, + FIELD_dsp340050b49a6c_fld3205, + FIELD_dsp340050b49a6c_fld3206, + FIELD_dsp340050b49a6c_fld3207LLR_slot2, + FIELD_dsp340050b49a6c_fld3208LLR_slot2, + FIELD_dsp340050b49a6c_fld3210LLR_slot2, + FIELD_dsp340050b49a6c_fld3212, + FIELD_dsp340050b49a6c_fld3213LLR_slot2, + FIELD_dsp340050b49a6c_fld3214, + FIELD_dsp340050b49a6c_fld3215LLR_slot2, + FIELD_dsp340050b49a6c_fld3216LLR_slot2, + FIELD_dsp340050b49a6c_fld3217, + FIELD_dsp340050b49a6c_fld3218LLR_slot2, + FIELD_dsp340050b49a6c_fld3220LLR_slot2, + FIELD_dsp340050b49a6c_fld3221LLR_slot2, + FIELD_dsp340050b49a6c_fld3222LLR_slot2, + FIELD_dsp340050b49a6c_fld3224LLR_slot2, + FIELD_dsp340050b49a6c_fld3225, + FIELD_dsp340050b49a6c_fld3226LLR_slot2, + FIELD_dsp340050b49a6c_fld3228LLR_slot2, + FIELD_dsp340050b49a6c_fld3230, + FIELD_dsp340050b49a6c_fld3231LLR_slot2, + FIELD_dsp340050b49a6c_fld3232LLR_slot2, + FIELD_dsp340050b49a6c_fld3233, + FIELD_dsp340050b49a6c_fld3234LLR_slot2, + FIELD_dsp340050b49a6c_fld3235LLR_slot2, + FIELD_dsp340050b49a6c_fld3236, + FIELD_dsp340050b49a6c_fld3237LLR_slot2, + FIELD_dsp340050b49a6c_fld3238LLR_slot2, + FIELD_dsp340050b49a6c_fld3240LLR_slot2, + FIELD_dsp340050b49a6c_fld3241LLR_slot2, + FIELD_dsp340050b49a6c_fld3242LLR_slot2, + FIELD_dsp340050b49a6c_fld3243LLR_slot2, + FIELD_dsp340050b49a6c_fld3244LLR_slot2, + FIELD_dsp340050b49a6c_fld3245LLR_slot2, + FIELD_dsp340050b49a6c_fld3246, + FIELD_dsp340050b49a6c_fld3247LLR_slot2, + FIELD_dsp340050b49a6c_fld3843LLR_slot2, + FIELD_dsp340050b49a6c_fld3844, + FIELD_dsp340050b49a6c_fld3845LLR_slot2, + FIELD_dsp340050b49a6c_fld3847LLR_slot2, + FIELD_dsp340050b49a6c_fld3848LLR_slot2, + FIELD_dsp340050b49a6c_fld3849LLR_slot2, + FIELD_dsp340050b49a6c_fld3850LLR_slot2, + FIELD_dsp340050b49a6c_fld3851LLR_slot2, + FIELD_dsp340050b49a6c_fld3853LLR_slot2, + FIELD_dsp340050b49a6c_fld3855LLR_slot2, + FIELD_dsp340050b49a6c_fld3856LLR_slot2, + FIELD_dsp340050b49a6c_fld3857LLR_slot2, + FIELD_dsp340050b49a6c_fld3859LLR_slot2, + FIELD_dsp340050b49a6c_fld3860LLR_slot2, + FIELD_dsp340050b49a6c_fld3861LLR_slot2, + FIELD_dsp340050b49a6c_fld3862, + FIELD_dsp340050b49a6c_fld3863LLR_slot2, + FIELD_dsp340050b49a6c_fld3864LLR_slot2, + FIELD_dsp340050b49a6c_fld3865LLR_slot2, + FIELD_dsp340050b49a6c_fld3866LLR_slot2, + FIELD_dsp340050b49a6c_fld3867LLR_slot2, + FIELD_dsp340050b49a6c_fld3868, + FIELD_op0_s19, + FIELD_dsp340050b49a6c_fld2034, + FIELD_dsp340050b49a6c_fld3248LLR_slot1, + FIELD_dsp340050b49a6c_fld3250LLR_slot1, + FIELD_dsp340050b49a6c_fld3251LLR_slot1, + FIELD_dsp340050b49a6c_fld3252LLR_slot1, + FIELD_dsp340050b49a6c_fld3253LLR_slot1, + FIELD_dsp340050b49a6c_fld3254LLR_slot1, + FIELD_dsp340050b49a6c_fld3869LLR_slot1, + FIELD_dsp340050b49a6c_fld3870, + FIELD_dsp340050b49a6c_fld3872LLR_slot1, + FIELD_dsp340050b49a6c_fld3875LLR_slot1, + FIELD_dsp340050b49a6c_fld3876LLR_slot1, + FIELD_dsp340050b49a6c_fld3878LLR_slot1, + FIELD_op0_s20, + FIELD_dsp340050b49a6c_fld2071, + FIELD_dsp340050b49a6c_fld3258LLR_slot0, + FIELD_dsp340050b49a6c_fld3259LLR_slot0, + FIELD_dsp340050b49a6c_fld3260LLR_slot0, + FIELD_dsp340050b49a6c_fld3261LLR_slot0, + FIELD_dsp340050b49a6c_fld3263LLR_slot0, + FIELD_dsp340050b49a6c_fld3264LLR_slot0, + FIELD_dsp340050b49a6c_fld3265LLR_slot0, + FIELD_dsp340050b49a6c_fld3266LLR_slot0, + FIELD_dsp340050b49a6c_fld3267LLR_slot0, + FIELD_dsp340050b49a6c_fld3268LLR_slot0, + FIELD_dsp340050b49a6c_fld3269LLR_slot0, + FIELD_dsp340050b49a6c_fld3270LLR_slot0, + FIELD_dsp340050b49a6c_fld3272LLR_slot0, + FIELD_dsp340050b49a6c_fld3274LLR_slot0, + FIELD_dsp340050b49a6c_fld3275LLR_slot0, + FIELD_dsp340050b49a6c_fld3276LLR_slot0, + FIELD_dsp340050b49a6c_fld3277LLR_slot0, + FIELD_dsp340050b49a6c_fld3278LLR_slot0, + FIELD_dsp340050b49a6c_fld3279LLR_slot0, + FIELD_dsp340050b49a6c_fld3280LLR_slot0, + FIELD_dsp340050b49a6c_fld3281LLR_slot0, + FIELD_dsp340050b49a6c_fld3282LLR_slot0, + FIELD_dsp340050b49a6c_fld3283LLR_slot0, + FIELD_dsp340050b49a6c_fld3284LLR_slot0, + FIELD_dsp340050b49a6c_fld3286LLR_slot0, + FIELD_dsp340050b49a6c_fld3288LLR_slot0, + FIELD_dsp340050b49a6c_fld3289LLR_slot0, + FIELD_dsp340050b49a6c_fld3291LLR_slot0, + FIELD_dsp340050b49a6c_fld3292LLR_slot0, + FIELD_dsp340050b49a6c_fld3293LLR_slot0, + FIELD_dsp340050b49a6c_fld3294LLR_slot0, + FIELD_dsp340050b49a6c_fld3295LLR_slot0, + FIELD_dsp340050b49a6c_fld3296LLR_slot0, + FIELD_dsp340050b49a6c_fld3297LLR_slot0, + FIELD_dsp340050b49a6c_fld3298LLR_slot0, + FIELD_dsp340050b49a6c_fld3299LLR_slot0, + FIELD_dsp340050b49a6c_fld3300LLR_slot0, + FIELD_dsp340050b49a6c_fld3302LLR_slot0, + FIELD_dsp340050b49a6c_fld3303LLR_slot0, + FIELD_dsp340050b49a6c_fld3304LLR_slot0, + FIELD_dsp340050b49a6c_fld3305LLR_slot0, + FIELD_dsp340050b49a6c_fld3306LLR_slot0, + FIELD_dsp340050b49a6c_fld3308LLR_slot0, + FIELD_dsp340050b49a6c_fld3310LLR_slot0, + FIELD_dsp340050b49a6c_fld3311LLR_slot0, + FIELD_dsp340050b49a6c_fld3312LLR_slot0, + FIELD_dsp340050b49a6c_fld3879LLR_slot0, + FIELD_dsp340050b49a6c_fld3881LLR_slot0, + FIELD_dsp340050b49a6c_fld3883LLR_slot0, + FIELD_dsp340050b49a6c_fld3885LLR_slot0, + FIELD_dsp340050b49a6c_fld3887LLR_slot0, + FIELD_dsp340050b49a6c_fld3888LLR_slot0, + FIELD_dsp340050b49a6c_fld3890LLR_slot0, + FIELD_dsp340050b49a6c_fld3892LLR_slot0, + FIELD_dsp340050b49a6c_fld3893LLR_slot0, + FIELD_op0_s21, + FIELD_dsp340050b49a6c_fld3313DUAL_slot2, + FIELD_dsp340050b49a6c_fld3314, + FIELD_dsp340050b49a6c_fld3315DUAL_slot2, + FIELD_dsp340050b49a6c_fld3316DUAL_slot2, + FIELD_dsp340050b49a6c_fld3317DUAL_slot2, + FIELD_dsp340050b49a6c_fld3318, + FIELD_dsp340050b49a6c_fld3319DUAL_slot2, + FIELD_dsp340050b49a6c_fld3320DUAL_slot2, + FIELD_dsp340050b49a6c_fld3321DUAL_slot2, + FIELD_dsp340050b49a6c_fld3322DUAL_slot2, + FIELD_dsp340050b49a6c_fld3323DUAL_slot2, + FIELD_dsp340050b49a6c_fld3324DUAL_slot2, + FIELD_dsp340050b49a6c_fld3325DUAL_slot2, + FIELD_dsp340050b49a6c_fld3326DUAL_slot2, + FIELD_dsp340050b49a6c_fld3327DUAL_slot2, + FIELD_dsp340050b49a6c_fld3328DUAL_slot2, + FIELD_dsp340050b49a6c_fld3329DUAL_slot2, + FIELD_dsp340050b49a6c_fld3330DUAL_slot2, + FIELD_dsp340050b49a6c_fld3331DUAL_slot2, + FIELD_dsp340050b49a6c_fld3332DUAL_slot2, + FIELD_dsp340050b49a6c_fld3333DUAL_slot2, + FIELD_dsp340050b49a6c_fld3334DUAL_slot2, + FIELD_dsp340050b49a6c_fld3335DUAL_slot2, + FIELD_dsp340050b49a6c_fld3336DUAL_slot2, + FIELD_dsp340050b49a6c_fld3337DUAL_slot2, + FIELD_dsp340050b49a6c_fld3339DUAL_slot2, + FIELD_dsp340050b49a6c_fld3340DUAL_slot2, + FIELD_dsp340050b49a6c_fld3341DUAL_slot2, + FIELD_dsp340050b49a6c_fld3342DUAL_slot2, + FIELD_dsp340050b49a6c_fld3345DUAL_slot2, + FIELD_dsp340050b49a6c_fld3347DUAL_slot2, + FIELD_dsp340050b49a6c_fld3348DUAL_slot2, + FIELD_dsp340050b49a6c_fld3349DUAL_slot2, + FIELD_dsp340050b49a6c_fld3350DUAL_slot2, + FIELD_dsp340050b49a6c_fld3353DUAL_slot2, + FIELD_dsp340050b49a6c_fld3354DUAL_slot2, + FIELD_dsp340050b49a6c_fld3356DUAL_slot2, + FIELD_dsp340050b49a6c_fld3358DUAL_slot2, + FIELD_dsp340050b49a6c_fld3360DUAL_slot2, + FIELD_dsp340050b49a6c_fld3361DUAL_slot2, + FIELD_dsp340050b49a6c_fld3362DUAL_slot2, + FIELD_dsp340050b49a6c_fld3363DUAL_slot2, + FIELD_dsp340050b49a6c_fld3364, + FIELD_dsp340050b49a6c_fld3365DUAL_slot2, + FIELD_dsp340050b49a6c_fld3366DUAL_slot2, + FIELD_dsp340050b49a6c_fld3367DUAL_slot2, + FIELD_dsp340050b49a6c_fld3368DUAL_slot2, + FIELD_dsp340050b49a6c_fld3369DUAL_slot2, + FIELD_dsp340050b49a6c_fld3370DUAL_slot2, + FIELD_dsp340050b49a6c_fld3371DUAL_slot2, + FIELD_dsp340050b49a6c_fld3372DUAL_slot2, + FIELD_dsp340050b49a6c_fld3373DUAL_slot2, + FIELD_dsp340050b49a6c_fld3374DUAL_slot2, + FIELD_dsp340050b49a6c_fld3375DUAL_slot2, + FIELD_dsp340050b49a6c_fld3376DUAL_slot2, + FIELD_dsp340050b49a6c_fld3377DUAL_slot2, + FIELD_dsp340050b49a6c_fld3378DUAL_slot2, + FIELD_dsp340050b49a6c_fld3379DUAL_slot2, + FIELD_dsp340050b49a6c_fld3380DUAL_slot2, + FIELD_dsp340050b49a6c_fld3381DUAL_slot2, + FIELD_dsp340050b49a6c_fld3382DUAL_slot2, + FIELD_dsp340050b49a6c_fld3384DUAL_slot2, + FIELD_dsp340050b49a6c_fld3385DUAL_slot2, + FIELD_dsp340050b49a6c_fld3386DUAL_slot2, + FIELD_dsp340050b49a6c_fld3387DUAL_slot2, + FIELD_dsp340050b49a6c_fld3388DUAL_slot2, + FIELD_dsp340050b49a6c_fld3390DUAL_slot2, + FIELD_dsp340050b49a6c_fld3392DUAL_slot2, + FIELD_dsp340050b49a6c_fld3394DUAL_slot2, + FIELD_dsp340050b49a6c_fld3396DUAL_slot2, + FIELD_dsp340050b49a6c_fld3397DUAL_slot2, + FIELD_dsp340050b49a6c_fld3399DUAL_slot2, + FIELD_dsp340050b49a6c_fld3401DUAL_slot2, + FIELD_dsp340050b49a6c_fld3403DUAL_slot2, + FIELD_dsp340050b49a6c_fld3404DUAL_slot2, + FIELD_dsp340050b49a6c_fld3406DUAL_slot2, + FIELD_dsp340050b49a6c_fld3407, + FIELD_dsp340050b49a6c_fld3408DUAL_slot2, + FIELD_dsp340050b49a6c_fld3410, + FIELD_dsp340050b49a6c_fld3411DUAL_slot2, + FIELD_dsp340050b49a6c_fld3412DUAL_slot2, + FIELD_dsp340050b49a6c_fld3413DUAL_slot2, + FIELD_dsp340050b49a6c_fld3414DUAL_slot2, + FIELD_dsp340050b49a6c_fld3415DUAL_slot2, + FIELD_dsp340050b49a6c_fld3416DUAL_slot2, + FIELD_dsp340050b49a6c_fld3417DUAL_slot2, + FIELD_dsp340050b49a6c_fld3418DUAL_slot2, + FIELD_dsp340050b49a6c_fld3419DUAL_slot2, + FIELD_dsp340050b49a6c_fld3420DUAL_slot2, + FIELD_dsp340050b49a6c_fld3421DUAL_slot2, + FIELD_dsp340050b49a6c_fld3422DUAL_slot2, + FIELD_dsp340050b49a6c_fld3423DUAL_slot2, + FIELD_dsp340050b49a6c_fld3424DUAL_slot2, + FIELD_dsp340050b49a6c_fld3425DUAL_slot2, + FIELD_dsp340050b49a6c_fld3426DUAL_slot2, + FIELD_dsp340050b49a6c_fld3427DUAL_slot2, + FIELD_dsp340050b49a6c_fld3428DUAL_slot2, + FIELD_dsp340050b49a6c_fld3429DUAL_slot2, + FIELD_dsp340050b49a6c_fld3430DUAL_slot2, + FIELD_dsp340050b49a6c_fld3431DUAL_slot2, + FIELD_dsp340050b49a6c_fld3432DUAL_slot2, + FIELD_dsp340050b49a6c_fld3433DUAL_slot2, + FIELD_dsp340050b49a6c_fld3434DUAL_slot2, + FIELD_dsp340050b49a6c_fld3435DUAL_slot2, + FIELD_dsp340050b49a6c_fld3436DUAL_slot2, + FIELD_dsp340050b49a6c_fld3437DUAL_slot2, + FIELD_dsp340050b49a6c_fld3438DUAL_slot2, + FIELD_dsp340050b49a6c_fld3439DUAL_slot2, + FIELD_dsp340050b49a6c_fld3440DUAL_slot2, + FIELD_dsp340050b49a6c_fld3441DUAL_slot2, + FIELD_dsp340050b49a6c_fld3442DUAL_slot2, + FIELD_dsp340050b49a6c_fld3443DUAL_slot2, + FIELD_dsp340050b49a6c_fld3444DUAL_slot2, + FIELD_dsp340050b49a6c_fld3445DUAL_slot2, + FIELD_dsp340050b49a6c_fld3446DUAL_slot2, + FIELD_dsp340050b49a6c_fld3448DUAL_slot2, + FIELD_dsp340050b49a6c_fld3450DUAL_slot2, + FIELD_dsp340050b49a6c_fld3451DUAL_slot2, + FIELD_dsp340050b49a6c_fld3453DUAL_slot2, + FIELD_dsp340050b49a6c_fld3454DUAL_slot2, + FIELD_dsp340050b49a6c_fld3456DUAL_slot2, + FIELD_dsp340050b49a6c_fld3457DUAL_slot2, + FIELD_dsp340050b49a6c_fld3458DUAL_slot2, + FIELD_dsp340050b49a6c_fld3459DUAL_slot2, + FIELD_dsp340050b49a6c_fld3460DUAL_slot2, + FIELD_dsp340050b49a6c_fld3461DUAL_slot2, + FIELD_dsp340050b49a6c_fld3462DUAL_slot2, + FIELD_dsp340050b49a6c_fld3464DUAL_slot2, + FIELD_dsp340050b49a6c_fld3465DUAL_slot2, + FIELD_dsp340050b49a6c_fld3466, + FIELD_dsp340050b49a6c_fld3467DUAL_slot2, + FIELD_dsp340050b49a6c_fld3468DUAL_slot2, + FIELD_dsp340050b49a6c_fld3469DUAL_slot2, + FIELD_dsp340050b49a6c_fld3470DUAL_slot2, + FIELD_dsp340050b49a6c_fld3471DUAL_slot2, + FIELD_dsp340050b49a6c_fld3472DUAL_slot2, + FIELD_dsp340050b49a6c_fld3473DUAL_slot2, + FIELD_dsp340050b49a6c_fld3474DUAL_slot2, + FIELD_dsp340050b49a6c_fld3475DUAL_slot2, + FIELD_dsp340050b49a6c_fld3477DUAL_slot2, + FIELD_dsp340050b49a6c_fld3478DUAL_slot2, + FIELD_dsp340050b49a6c_fld3479DUAL_slot2, + FIELD_dsp340050b49a6c_fld3480DUAL_slot2, + FIELD_dsp340050b49a6c_fld3481DUAL_slot2, + FIELD_dsp340050b49a6c_fld3482DUAL_slot2, + FIELD_dsp340050b49a6c_fld3484DUAL_slot2, + FIELD_dsp340050b49a6c_fld3894DUAL_slot2, + FIELD_dsp340050b49a6c_fld3895DUAL_slot2, + FIELD_dsp340050b49a6c_fld3896DUAL_slot2, + FIELD_dsp340050b49a6c_fld3897DUAL_slot2, + FIELD_dsp340050b49a6c_fld3898DUAL_slot2, + FIELD_dsp340050b49a6c_fld3899DUAL_slot2, + FIELD_dsp340050b49a6c_fld3900, + FIELD_dsp340050b49a6c_fld3901DUAL_slot2, + FIELD_dsp340050b49a6c_fld3903DUAL_slot2, + FIELD_dsp340050b49a6c_fld3904DUAL_slot2, + FIELD_dsp340050b49a6c_fld3905DUAL_slot2, + FIELD_dsp340050b49a6c_fld3906DUAL_slot2, + FIELD_dsp340050b49a6c_fld3907DUAL_slot2, + FIELD_dsp340050b49a6c_fld3908DUAL_slot2, + FIELD_dsp340050b49a6c_fld3909DUAL_slot2, + FIELD_dsp340050b49a6c_fld3910DUAL_slot2, + FIELD_dsp340050b49a6c_fld3913DUAL_slot2, + FIELD_dsp340050b49a6c_fld3914DUAL_slot2, + FIELD_dsp340050b49a6c_fld3916DUAL_slot2, + FIELD_dsp340050b49a6c_fld3917DUAL_slot2, + FIELD_dsp340050b49a6c_fld3918DUAL_slot2, + FIELD_dsp340050b49a6c_fld3919DUAL_slot2, + FIELD_dsp340050b49a6c_fld3920DUAL_slot2, + FIELD_dsp340050b49a6c_fld3921DUAL_slot2, + FIELD_dsp340050b49a6c_fld3922DUAL_slot2, + FIELD_dsp340050b49a6c_fld3923DUAL_slot2, + FIELD_dsp340050b49a6c_fld3924DUAL_slot2, + FIELD_dsp340050b49a6c_fld3925DUAL_slot2, + FIELD_dsp340050b49a6c_fld3927DUAL_slot2, + FIELD_dsp340050b49a6c_fld3928DUAL_slot2, + FIELD_dsp340050b49a6c_fld3929DUAL_slot2, + FIELD_dsp340050b49a6c_fld3930DUAL_slot2, + FIELD_dsp340050b49a6c_fld3931DUAL_slot2, + FIELD_dsp340050b49a6c_fld3933DUAL_slot2, + FIELD_dsp340050b49a6c_fld3934DUAL_slot2, + FIELD_dsp340050b49a6c_fld3935DUAL_slot2, + FIELD_op0_s22, + FIELD_op0_s23, + FIELD_dsp340050b49a6c_fld2057, + FIELD_dsp340050b49a6c_fld2060, + FIELD_dsp340050b49a6c_fld2066, + FIELD_dsp340050b49a6c_fld2072, + FIELD_dsp340050b49a6c_fld2079, + FIELD_dsp340050b49a6c_fld3487DUAL_slot0, + FIELD_dsp340050b49a6c_fld3488DUAL_slot0, + FIELD_dsp340050b49a6c_fld3489DUAL_slot0, + FIELD_dsp340050b49a6c_fld3490DUAL_slot0, + FIELD_dsp340050b49a6c_fld3491DUAL_slot0, + FIELD_dsp340050b49a6c_fld3492DUAL_slot0, + FIELD_dsp340050b49a6c_fld3493DUAL_slot0, + FIELD_dsp340050b49a6c_fld3494DUAL_slot0, + FIELD_dsp340050b49a6c_fld3496DUAL_slot0, + FIELD_dsp340050b49a6c_fld3497DUAL_slot0, + FIELD_dsp340050b49a6c_fld3498DUAL_slot0, + FIELD_dsp340050b49a6c_fld3499DUAL_slot0, + FIELD_dsp340050b49a6c_fld3500DUAL_slot0, + FIELD_dsp340050b49a6c_fld3502DUAL_slot0, + FIELD_dsp340050b49a6c_fld3504DUAL_slot0, + FIELD_dsp340050b49a6c_fld3505DUAL_slot0, + FIELD_dsp340050b49a6c_fld3506DUAL_slot0, + FIELD_dsp340050b49a6c_fld3507DUAL_slot0, + FIELD_dsp340050b49a6c_fld3508DUAL_slot0, + FIELD_dsp340050b49a6c_fld3509DUAL_slot0, + FIELD_dsp340050b49a6c_fld3510DUAL_slot0, + FIELD_dsp340050b49a6c_fld3511DUAL_slot0, + FIELD_dsp340050b49a6c_fld3512DUAL_slot0, + FIELD_dsp340050b49a6c_fld3513DUAL_slot0, + FIELD_dsp340050b49a6c_fld3514DUAL_slot0, + FIELD_dsp340050b49a6c_fld3515DUAL_slot0, + FIELD_dsp340050b49a6c_fld3516DUAL_slot0, + FIELD_dsp340050b49a6c_fld3517DUAL_slot0, + FIELD_dsp340050b49a6c_fld3518DUAL_slot0, + FIELD_dsp340050b49a6c_fld3519DUAL_slot0, + FIELD_dsp340050b49a6c_fld3520DUAL_slot0, + FIELD_dsp340050b49a6c_fld3522DUAL_slot0, + FIELD_dsp340050b49a6c_fld3523DUAL_slot0, + FIELD_dsp340050b49a6c_fld3524DUAL_slot0, + FIELD_dsp340050b49a6c_fld3527DUAL_slot0, + FIELD_dsp340050b49a6c_fld3529DUAL_slot0, + FIELD_dsp340050b49a6c_fld3530DUAL_slot0, + FIELD_dsp340050b49a6c_fld3531, + FIELD_dsp340050b49a6c_fld3532DUAL_slot0, + FIELD_dsp340050b49a6c_fld3533DUAL_slot0, + FIELD_dsp340050b49a6c_fld3535DUAL_slot0, + FIELD_dsp340050b49a6c_fld3536DUAL_slot0, + FIELD_dsp340050b49a6c_fld3537DUAL_slot0, + FIELD_dsp340050b49a6c_fld3538DUAL_slot0, + FIELD_dsp340050b49a6c_fld3539DUAL_slot0, + FIELD_dsp340050b49a6c_fld3541DUAL_slot0, + FIELD_dsp340050b49a6c_fld3542DUAL_slot0, + FIELD_dsp340050b49a6c_fld3543DUAL_slot0, + FIELD_dsp340050b49a6c_fld3544DUAL_slot0, + FIELD_dsp340050b49a6c_fld3545DUAL_slot0, + FIELD_dsp340050b49a6c_fld3546DUAL_slot0, + FIELD_dsp340050b49a6c_fld3547DUAL_slot0, + FIELD_dsp340050b49a6c_fld3548DUAL_slot0, + FIELD_dsp340050b49a6c_fld3549DUAL_slot0, + FIELD_dsp340050b49a6c_fld3550DUAL_slot0, + FIELD_dsp340050b49a6c_fld3551DUAL_slot0, + FIELD_dsp340050b49a6c_fld3552, + FIELD_dsp340050b49a6c_fld3553DUAL_slot0, + FIELD_dsp340050b49a6c_fld3554DUAL_slot0, + FIELD_dsp340050b49a6c_fld3555DUAL_slot0, + FIELD_dsp340050b49a6c_fld3556DUAL_slot0, + FIELD_dsp340050b49a6c_fld3557DUAL_slot0, + FIELD_dsp340050b49a6c_fld3558DUAL_slot0, + FIELD_dsp340050b49a6c_fld3559DUAL_slot0, + FIELD_dsp340050b49a6c_fld3560DUAL_slot0, + FIELD_dsp340050b49a6c_fld3562DUAL_slot0, + FIELD_dsp340050b49a6c_fld3563DUAL_slot0, + FIELD_dsp340050b49a6c_fld3564DUAL_slot0, + FIELD_dsp340050b49a6c_fld3565DUAL_slot0, + FIELD_dsp340050b49a6c_fld3566DUAL_slot0, + FIELD_dsp340050b49a6c_fld3567DUAL_slot0, + FIELD_dsp340050b49a6c_fld3568DUAL_slot0, + FIELD_dsp340050b49a6c_fld3569DUAL_slot0, + FIELD_dsp340050b49a6c_fld3570DUAL_slot0, + FIELD_dsp340050b49a6c_fld3571DUAL_slot0, + FIELD_dsp340050b49a6c_fld3572DUAL_slot0, + FIELD_dsp340050b49a6c_fld3573DUAL_slot0, + FIELD_dsp340050b49a6c_fld3574DUAL_slot0, + FIELD_dsp340050b49a6c_fld3575DUAL_slot0, + FIELD_dsp340050b49a6c_fld3576DUAL_slot0, + FIELD_dsp340050b49a6c_fld3577DUAL_slot0, + FIELD_dsp340050b49a6c_fld3578DUAL_slot0, + FIELD_dsp340050b49a6c_fld3579DUAL_slot0, + FIELD_dsp340050b49a6c_fld3580DUAL_slot0, + FIELD_dsp340050b49a6c_fld3581DUAL_slot0, + FIELD_dsp340050b49a6c_fld3582DUAL_slot0, + FIELD_dsp340050b49a6c_fld3583DUAL_slot0, + FIELD_dsp340050b49a6c_fld3584, + FIELD_dsp340050b49a6c_fld3585DUAL_slot0, + FIELD_dsp340050b49a6c_fld3587DUAL_slot0, + FIELD_dsp340050b49a6c_fld3588DUAL_slot0, + FIELD_dsp340050b49a6c_fld3589DUAL_slot0, + FIELD_dsp340050b49a6c_fld3590DUAL_slot0, + FIELD_dsp340050b49a6c_fld3591DUAL_slot0, + FIELD_dsp340050b49a6c_fld3592DUAL_slot0, + FIELD_dsp340050b49a6c_fld3593DUAL_slot0, + FIELD_dsp340050b49a6c_fld3594DUAL_slot0, + FIELD_dsp340050b49a6c_fld3595DUAL_slot0, + FIELD_dsp340050b49a6c_fld3596DUAL_slot0, + FIELD_dsp340050b49a6c_fld3597DUAL_slot0, + FIELD_dsp340050b49a6c_fld3598DUAL_slot0, + FIELD_dsp340050b49a6c_fld3599DUAL_slot0, + FIELD_dsp340050b49a6c_fld3600DUAL_slot0, + FIELD_dsp340050b49a6c_fld3601DUAL_slot0, + FIELD_dsp340050b49a6c_fld3602, + FIELD_dsp340050b49a6c_fld3603DUAL_slot0, + FIELD_dsp340050b49a6c_fld3604DUAL_slot0, + FIELD_dsp340050b49a6c_fld3606DUAL_slot0, + FIELD_dsp340050b49a6c_fld3607DUAL_slot0, + FIELD_dsp340050b49a6c_fld3608DUAL_slot0, + FIELD_dsp340050b49a6c_fld3609DUAL_slot0, + FIELD_dsp340050b49a6c_fld3610, + FIELD_dsp340050b49a6c_fld3611DUAL_slot0, + FIELD_dsp340050b49a6c_fld3612DUAL_slot0, + FIELD_dsp340050b49a6c_fld3613DUAL_slot0, + FIELD_dsp340050b49a6c_fld3614DUAL_slot0, + FIELD_dsp340050b49a6c_fld3615DUAL_slot0, + FIELD_dsp340050b49a6c_fld3616DUAL_slot0, + FIELD_dsp340050b49a6c_fld3618DUAL_slot0, + FIELD_dsp340050b49a6c_fld3619, + FIELD_dsp340050b49a6c_fld3620DUAL_slot0, + FIELD_dsp340050b49a6c_fld3621DUAL_slot0, + FIELD_dsp340050b49a6c_fld3622DUAL_slot0, + FIELD_dsp340050b49a6c_fld3623DUAL_slot0, + FIELD_dsp340050b49a6c_fld3624DUAL_slot0, + FIELD_dsp340050b49a6c_fld3625DUAL_slot0, + FIELD_dsp340050b49a6c_fld3626DUAL_slot0, + FIELD_dsp340050b49a6c_fld3936DUAL_slot0, + FIELD_dsp340050b49a6c_fld3937DUAL_slot0, + FIELD_dsp340050b49a6c_fld3938DUAL_slot0, + FIELD_dsp340050b49a6c_fld3939DUAL_slot0, + FIELD_dsp340050b49a6c_fld3940DUAL_slot0, + FIELD_dsp340050b49a6c_fld3941DUAL_slot0, + FIELD_dsp340050b49a6c_fld3943DUAL_slot0, + FIELD_dsp340050b49a6c_fld3945DUAL_slot0, + FIELD_dsp340050b49a6c_fld3946DUAL_slot0, + FIELD_dsp340050b49a6c_fld3947DUAL_slot0, + FIELD_dsp340050b49a6c_fld3949DUAL_slot0, + FIELD_dsp340050b49a6c_fld3950DUAL_slot0, + FIELD_dsp340050b49a6c_fld3951DUAL_slot0, + FIELD_dsp340050b49a6c_fld3952DUAL_slot0, + FIELD_dsp340050b49a6c_fld3954DUAL_slot0, + FIELD_dsp340050b49a6c_fld3957DUAL_slot0, + FIELD_dsp340050b49a6c_fld3958DUAL_slot0, + FIELD_dsp340050b49a6c_fld3959DUAL_slot0, + FIELD_dsp340050b49a6c_fld3960DUAL_slot0, + FIELD_dsp340050b49a6c_fld3961DUAL_slot0, + FIELD__ar0, + FIELD__ar4, + FIELD__ar8, + FIELD__ar12, + FIELD__bt16, + FIELD__bs16, + FIELD__br16, + FIELD__brall +}; + + +/* Functional units. */ + +static xtensa_funcUnit_internal funcUnits[] = { + +}; + + +/* Register files. */ + +enum xtensa_regfile_id { + REGFILE_AR, + REGFILE_BR, + REGFILE_FR, + REGFILE_ACU, + REGFILE_CM, + REGFILE_PQ, + REGFILE_BR2, + REGFILE_BR4, + REGFILE_BR8, + REGFILE_BR16 +}; + +static xtensa_regfile_internal regfiles[] = { + { "AR", "a", REGFILE_AR, 32, 32 }, + { "BR", "b", REGFILE_BR, 1, 16 }, + { "FR", "f", REGFILE_FR, 32, 16 }, + { "ACU", "ACU", REGFILE_ACU, 320, 8 }, + { "CM", "CM", REGFILE_CM, 128, 16 }, + { "PQ", "PQ", REGFILE_PQ, 256, 16 }, + { "BR2", "b", REGFILE_BR, 2, 8 }, + { "BR4", "b", REGFILE_BR, 4, 4 }, + { "BR8", "b", REGFILE_BR, 8, 2 }, + { "BR16", "b", REGFILE_BR, 16, 1 } +}; + + +/* Interfaces. */ + +static xtensa_interface_internal interfaces[] = { + { "INQ0_32_Empty", 1, 0, 0, 'i' }, + { "INQ0_32", 32, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 0, 'i' }, + { "INQ0_32_NOTRDY", 1, 0, 0, 'i' }, + { "INQ0_32_KILL", 1, 0, 0, 'o' }, + { "INQ1_32_Empty", 1, 0, 1, 'i' }, + { "INQ1_32", 32, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 1, 'i' }, + { "INQ1_32_NOTRDY", 1, 0, 1, 'i' }, + { "INQ1_32_KILL", 1, 0, 1, 'o' }, + { "INQ2_32_Empty", 1, 0, 2, 'i' }, + { "INQ2_32", 32, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 2, 'i' }, + { "INQ2_32_NOTRDY", 1, 0, 2, 'i' }, + { "INQ2_32_KILL", 1, 0, 2, 'o' }, + { "INQ3_32_Empty", 1, 0, 3, 'i' }, + { "INQ3_32", 32, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 3, 'i' }, + { "INQ3_32_NOTRDY", 1, 0, 3, 'i' }, + { "INQ3_32_KILL", 1, 0, 3, 'o' }, + { "OUTQ0_32_Full", 1, 0, 4, 'i' }, + { "OUTQ0_32", 32, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 4, 'o' }, + { "OUTQ0_32_NOTRDY", 1, 0, 4, 'i' }, + { "OUTQ0_32_KILL", 1, 0, 4, 'o' }, + { "OUTQ1_32_Full", 1, 0, 5, 'i' }, + { "OUTQ1_32", 32, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 5, 'o' }, + { "OUTQ1_32_NOTRDY", 1, 0, 5, 'i' }, + { "OUTQ1_32_KILL", 1, 0, 5, 'o' }, + { "OUTQ2_32_Full", 1, 0, 6, 'i' }, + { "OUTQ2_32", 32, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 6, 'o' }, + { "OUTQ2_32_NOTRDY", 1, 0, 6, 'i' }, + { "OUTQ2_32_KILL", 1, 0, 6, 'o' }, + { "OUTQ3_32_Full", 1, 0, 7, 'i' }, + { "OUTQ3_32", 32, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 7, 'o' }, + { "OUTQ3_32_NOTRDY", 1, 0, 7, 'i' }, + { "OUTQ3_32_KILL", 1, 0, 7, 'o' }, + { "OUTQ4_32_Full", 1, 0, 8, 'i' }, + { "OUTQ4_32", 32, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 8, 'o' }, + { "OUTQ4_32_NOTRDY", 1, 0, 8, 'i' }, + { "OUTQ4_32_KILL", 1, 0, 8, 'o' }, + { "OUTQ5_32_Full", 1, 0, 9, 'i' }, + { "OUTQ5_32", 32, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 9, 'o' }, + { "OUTQ5_32_NOTRDY", 1, 0, 9, 'i' }, + { "OUTQ5_32_KILL", 1, 0, 9, 'o' }, + { "SIGNALQ_Full", 1, 0, 10, 'i' }, + { "SIGNALQ", 32, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 10, 'o' }, + { "SIGNALQ_NOTRDY", 1, 0, 10, 'i' }, + { "SIGNALQ_KILL", 1, 0, 10, 'o' }, + { "INQ0_128_Empty", 1, 0, 11, 'i' }, + { "INQ0_128", 128, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 11, 'i' }, + { "INQ0_128_NOTRDY", 1, 0, 11, 'i' }, + { "INQ0_128_KILL", 1, 0, 11, 'o' }, + { "INQ1_128_Empty", 1, 0, 12, 'i' }, + { "INQ1_128", 128, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 12, 'i' }, + { "INQ1_128_NOTRDY", 1, 0, 12, 'i' }, + { "INQ1_128_KILL", 1, 0, 12, 'o' }, + { "INQ2_128_Empty", 1, 0, 13, 'i' }, + { "INQ2_128", 128, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 13, 'i' }, + { "INQ2_128_NOTRDY", 1, 0, 13, 'i' }, + { "INQ2_128_KILL", 1, 0, 13, 'o' }, + { "INQ3_128_Empty", 1, 0, 14, 'i' }, + { "INQ3_128", 128, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 14, 'i' }, + { "INQ3_128_NOTRDY", 1, 0, 14, 'i' }, + { "INQ3_128_KILL", 1, 0, 14, 'o' }, + { "INQ4_128_Empty", 1, 0, 15, 'i' }, + { "INQ4_128", 128, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 15, 'i' }, + { "INQ4_128_NOTRDY", 1, 0, 15, 'i' }, + { "INQ4_128_KILL", 1, 0, 15, 'o' }, + { "INQ5_128_Empty", 1, 0, 16, 'i' }, + { "INQ5_128", 128, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 16, 'i' }, + { "INQ5_128_NOTRDY", 1, 0, 16, 'i' }, + { "INQ5_128_KILL", 1, 0, 16, 'o' }, + { "OUTQ0_128_Full", 1, 0, 17, 'i' }, + { "OUTQ0_128", 128, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 17, 'o' }, + { "OUTQ0_128_NOTRDY", 1, 0, 17, 'i' }, + { "OUTQ0_128_KILL", 1, 0, 17, 'o' }, + { "OUTQ1_128_Full", 1, 0, 18, 'i' }, + { "OUTQ1_128", 128, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 18, 'o' }, + { "OUTQ1_128_NOTRDY", 1, 0, 18, 'i' }, + { "OUTQ1_128_KILL", 1, 0, 18, 'o' }, + { "OUTQ2_128_Full", 1, 0, 19, 'i' }, + { "OUTQ2_128", 128, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 19, 'o' }, + { "OUTQ2_128_NOTRDY", 1, 0, 19, 'i' }, + { "OUTQ2_128_KILL", 1, 0, 19, 'o' }, + { "OUTQ3_128_Full", 1, 0, 20, 'i' }, + { "OUTQ3_128", 128, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 20, 'o' }, + { "OUTQ3_128_NOTRDY", 1, 0, 20, 'i' }, + { "OUTQ3_128_KILL", 1, 0, 20, 'o' }, + { "OUTQ4_128_Full", 1, 0, 21, 'i' }, + { "OUTQ4_128", 128, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 21, 'o' }, + { "OUTQ4_128_NOTRDY", 1, 0, 21, 'i' }, + { "OUTQ4_128_KILL", 1, 0, 21, 'o' }, + { "OUTQ5_128_Full", 1, 0, 22, 'i' }, + { "OUTQ5_128", 128, XTENSA_INTERFACE_HAS_SIDE_EFFECT, 22, 'o' }, + { "OUTQ5_128_NOTRDY", 1, 0, 22, 'i' }, + { "OUTQ5_128_KILL", 1, 0, 22, 'o' }, + { "IMPWIRE", 32, 0, 23, 'i' }, + { "LU128_Out", 128, 0, 24, 'o' }, + { "LU128_In", 128, 0, 25, 'i' } +}; + +enum xtensa_interface_id { + INTERFACE_INQ0_32_Empty, + INTERFACE_INQ0_32, + INTERFACE_INQ0_32_NOTRDY, + INTERFACE_INQ0_32_KILL, + INTERFACE_INQ1_32_Empty, + INTERFACE_INQ1_32, + INTERFACE_INQ1_32_NOTRDY, + INTERFACE_INQ1_32_KILL, + INTERFACE_INQ2_32_Empty, + INTERFACE_INQ2_32, + INTERFACE_INQ2_32_NOTRDY, + INTERFACE_INQ2_32_KILL, + INTERFACE_INQ3_32_Empty, + INTERFACE_INQ3_32, + INTERFACE_INQ3_32_NOTRDY, + INTERFACE_INQ3_32_KILL, + INTERFACE_OUTQ0_32_Full, + INTERFACE_OUTQ0_32, + INTERFACE_OUTQ0_32_NOTRDY, + INTERFACE_OUTQ0_32_KILL, + INTERFACE_OUTQ1_32_Full, + INTERFACE_OUTQ1_32, + INTERFACE_OUTQ1_32_NOTRDY, + INTERFACE_OUTQ1_32_KILL, + INTERFACE_OUTQ2_32_Full, + INTERFACE_OUTQ2_32, + INTERFACE_OUTQ2_32_NOTRDY, + INTERFACE_OUTQ2_32_KILL, + INTERFACE_OUTQ3_32_Full, + INTERFACE_OUTQ3_32, + INTERFACE_OUTQ3_32_NOTRDY, + INTERFACE_OUTQ3_32_KILL, + INTERFACE_OUTQ4_32_Full, + INTERFACE_OUTQ4_32, + INTERFACE_OUTQ4_32_NOTRDY, + INTERFACE_OUTQ4_32_KILL, + INTERFACE_OUTQ5_32_Full, + INTERFACE_OUTQ5_32, + INTERFACE_OUTQ5_32_NOTRDY, + INTERFACE_OUTQ5_32_KILL, + INTERFACE_SIGNALQ_Full, + INTERFACE_SIGNALQ, + INTERFACE_SIGNALQ_NOTRDY, + INTERFACE_SIGNALQ_KILL, + INTERFACE_INQ0_128_Empty, + INTERFACE_INQ0_128, + INTERFACE_INQ0_128_NOTRDY, + INTERFACE_INQ0_128_KILL, + INTERFACE_INQ1_128_Empty, + INTERFACE_INQ1_128, + INTERFACE_INQ1_128_NOTRDY, + INTERFACE_INQ1_128_KILL, + INTERFACE_INQ2_128_Empty, + INTERFACE_INQ2_128, + INTERFACE_INQ2_128_NOTRDY, + INTERFACE_INQ2_128_KILL, + INTERFACE_INQ3_128_Empty, + INTERFACE_INQ3_128, + INTERFACE_INQ3_128_NOTRDY, + INTERFACE_INQ3_128_KILL, + INTERFACE_INQ4_128_Empty, + INTERFACE_INQ4_128, + INTERFACE_INQ4_128_NOTRDY, + INTERFACE_INQ4_128_KILL, + INTERFACE_INQ5_128_Empty, + INTERFACE_INQ5_128, + INTERFACE_INQ5_128_NOTRDY, + INTERFACE_INQ5_128_KILL, + INTERFACE_OUTQ0_128_Full, + INTERFACE_OUTQ0_128, + INTERFACE_OUTQ0_128_NOTRDY, + INTERFACE_OUTQ0_128_KILL, + INTERFACE_OUTQ1_128_Full, + INTERFACE_OUTQ1_128, + INTERFACE_OUTQ1_128_NOTRDY, + INTERFACE_OUTQ1_128_KILL, + INTERFACE_OUTQ2_128_Full, + INTERFACE_OUTQ2_128, + INTERFACE_OUTQ2_128_NOTRDY, + INTERFACE_OUTQ2_128_KILL, + INTERFACE_OUTQ3_128_Full, + INTERFACE_OUTQ3_128, + INTERFACE_OUTQ3_128_NOTRDY, + INTERFACE_OUTQ3_128_KILL, + INTERFACE_OUTQ4_128_Full, + INTERFACE_OUTQ4_128, + INTERFACE_OUTQ4_128_NOTRDY, + INTERFACE_OUTQ4_128_KILL, + INTERFACE_OUTQ5_128_Full, + INTERFACE_OUTQ5_128, + INTERFACE_OUTQ5_128_NOTRDY, + INTERFACE_OUTQ5_128_KILL, + INTERFACE_IMPWIRE, + INTERFACE_LU128_Out, + INTERFACE_LU128_In +}; + + +/* Constant tables. */ + +/* constant table ai4c */ +static const unsigned CONST_TBL_ai4c_0[] = { + 0xffffffff, + 0x1, + 0x2, + 0x3, + 0x4, + 0x5, + 0x6, + 0x7, + 0x8, + 0x9, + 0xa, + 0xb, + 0xc, + 0xd, + 0xe, + 0xf, + 0 +}; + +/* constant table b4c */ +static const unsigned CONST_TBL_b4c_0[] = { + 0xffffffff, + 0x1, + 0x2, + 0x3, + 0x4, + 0x5, + 0x6, + 0x7, + 0x8, + 0xa, + 0xc, + 0x10, + 0x20, + 0x40, + 0x80, + 0x100, + 0 +}; + +/* constant table b4cu */ +static const unsigned CONST_TBL_b4cu_0[] = { + 0x8000, + 0x10000, + 0x2, + 0x3, + 0x4, + 0x5, + 0x6, + 0x7, + 0x8, + 0xa, + 0xc, + 0x10, + 0x20, + 0x40, + 0x80, + 0x100, + 0 +}; + +/* constant table LLR_CONSTELLATION_TABLE */ +static const unsigned CONST_TBL_LLR_CONSTELLATION_TABLE_0[] = { + 0x1 & 0xf, + 0x2 & 0xf, + 0x8 & 0xf, + 0x4 & 0xf, + 0x8 & 0xf, + 0x6 & 0xf, + 0x8 & 0xf, + 0x8 & 0xf, + 0 +}; + + +/* Instruction operands. */ + +static int +Operand_soffsetx4_decode (uint32 *valp) +{ + unsigned soffsetx4_0, offset_0; + offset_0 = *valp & 0x3ffff; + soffsetx4_0 = 0x4 + ((((int) offset_0 << 14) >> 14) << 2); + *valp = soffsetx4_0; + return 0; +} + +static int +Operand_soffsetx4_encode (uint32 *valp) +{ + unsigned offset_0, soffsetx4_0; + soffsetx4_0 = *valp; + offset_0 = ((soffsetx4_0 - 0x4) >> 2) & 0x3ffff; + *valp = offset_0; + return 0; +} + +static int +Operand_soffsetx4_ator (uint32 *valp, uint32 pc) +{ + *valp -= (pc & ~0x3); + return 0; +} + +static int +Operand_soffsetx4_rtoa (uint32 *valp, uint32 pc) +{ + *valp += (pc & ~0x3); + return 0; +} + +static int +Operand_uimm12x8_decode (uint32 *valp) +{ + unsigned uimm12x8_0, imm12_0; + imm12_0 = *valp & 0xfff; + uimm12x8_0 = imm12_0 << 3; + *valp = uimm12x8_0; + return 0; +} + +static int +Operand_uimm12x8_encode (uint32 *valp) +{ + unsigned imm12_0, uimm12x8_0; + uimm12x8_0 = *valp; + imm12_0 = ((uimm12x8_0 >> 3) & 0xfff); + *valp = imm12_0; + return 0; +} + +static int +Operand_simm4_decode (uint32 *valp) +{ + unsigned simm4_0, mn_0; + mn_0 = *valp & 0xf; + simm4_0 = ((int) mn_0 << 28) >> 28; + *valp = simm4_0; + return 0; +} + +static int +Operand_simm4_encode (uint32 *valp) +{ + unsigned mn_0, simm4_0; + simm4_0 = *valp; + mn_0 = (simm4_0 & 0xf); + *valp = mn_0; + return 0; +} + +static int +Operand_arr_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_arr_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_ars_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_ars_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_art_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_art_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_ar0_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_ar0_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0x1f) != 0; + return error; +} + +static int +Operand_ar4_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_ar4_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0x1f) != 0; + return error; +} + +static int +Operand_ar8_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_ar8_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0x1f) != 0; + return error; +} + +static int +Operand_ar12_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_ar12_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0x1f) != 0; + return error; +} + +static int +Operand_ars_entry_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_ars_entry_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0x1f) != 0; + return error; +} + +static int +Operand_immrx4_decode (uint32 *valp) +{ + unsigned immrx4_0, r_0; + r_0 = *valp & 0xf; + immrx4_0 = (((0xfffffff) << 4) | r_0) << 2; + *valp = immrx4_0; + return 0; +} + +static int +Operand_immrx4_encode (uint32 *valp) +{ + unsigned r_0, immrx4_0; + immrx4_0 = *valp; + r_0 = ((immrx4_0 >> 2) & 0xf); + *valp = r_0; + return 0; +} + +static int +Operand_lsi4x4_decode (uint32 *valp) +{ + unsigned lsi4x4_0, r_0; + r_0 = *valp & 0xf; + lsi4x4_0 = r_0 << 2; + *valp = lsi4x4_0; + return 0; +} + +static int +Operand_lsi4x4_encode (uint32 *valp) +{ + unsigned r_0, lsi4x4_0; + lsi4x4_0 = *valp; + r_0 = ((lsi4x4_0 >> 2) & 0xf); + *valp = r_0; + return 0; +} + +static int +Operand_simm7_decode (uint32 *valp) +{ + unsigned simm7_0, imm7_0; + imm7_0 = *valp & 0x7f; + simm7_0 = ((((-((((imm7_0 >> 6) & 1)) & (((imm7_0 >> 5) & 1)))) & 0x1ffffff)) << 7) | imm7_0; + *valp = simm7_0; + return 0; +} + +static int +Operand_simm7_encode (uint32 *valp) +{ + unsigned imm7_0, simm7_0; + simm7_0 = *valp; + imm7_0 = (simm7_0 & 0x7f); + *valp = imm7_0; + return 0; +} + +static int +Operand_uimm6_decode (uint32 *valp) +{ + unsigned uimm6_0, imm6_0; + imm6_0 = *valp & 0x3f; + uimm6_0 = 0x4 + (((0) << 6) | imm6_0); + *valp = uimm6_0; + return 0; +} + +static int +Operand_uimm6_encode (uint32 *valp) +{ + unsigned imm6_0, uimm6_0; + uimm6_0 = *valp; + imm6_0 = (uimm6_0 - 0x4) & 0x3f; + *valp = imm6_0; + return 0; +} + +static int +Operand_uimm6_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_uimm6_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_ai4const_decode (uint32 *valp) +{ + unsigned ai4const_0, t_0; + t_0 = *valp & 0xf; + ai4const_0 = CONST_TBL_ai4c_0[t_0 & 0xf]; + *valp = ai4const_0; + return 0; +} + +static int +Operand_ai4const_encode (uint32 *valp) +{ + unsigned t_0, ai4const_0; + ai4const_0 = *valp; + switch (ai4const_0) + { + case 0xffffffff: t_0 = 0; break; + case 0x1: t_0 = 0x1; break; + case 0x2: t_0 = 0x2; break; + case 0x3: t_0 = 0x3; break; + case 0x4: t_0 = 0x4; break; + case 0x5: t_0 = 0x5; break; + case 0x6: t_0 = 0x6; break; + case 0x7: t_0 = 0x7; break; + case 0x8: t_0 = 0x8; break; + case 0x9: t_0 = 0x9; break; + case 0xa: t_0 = 0xa; break; + case 0xb: t_0 = 0xb; break; + case 0xc: t_0 = 0xc; break; + case 0xd: t_0 = 0xd; break; + case 0xe: t_0 = 0xe; break; + default: t_0 = 0xf; break; + } + *valp = t_0; + return 0; +} + +static int +Operand_b4const_decode (uint32 *valp) +{ + unsigned b4const_0, r_0; + r_0 = *valp & 0xf; + b4const_0 = CONST_TBL_b4c_0[r_0 & 0xf]; + *valp = b4const_0; + return 0; +} + +static int +Operand_b4const_encode (uint32 *valp) +{ + unsigned r_0, b4const_0; + b4const_0 = *valp; + switch (b4const_0) + { + case 0xffffffff: r_0 = 0; break; + case 0x1: r_0 = 0x1; break; + case 0x2: r_0 = 0x2; break; + case 0x3: r_0 = 0x3; break; + case 0x4: r_0 = 0x4; break; + case 0x5: r_0 = 0x5; break; + case 0x6: r_0 = 0x6; break; + case 0x7: r_0 = 0x7; break; + case 0x8: r_0 = 0x8; break; + case 0xa: r_0 = 0x9; break; + case 0xc: r_0 = 0xa; break; + case 0x10: r_0 = 0xb; break; + case 0x20: r_0 = 0xc; break; + case 0x40: r_0 = 0xd; break; + case 0x80: r_0 = 0xe; break; + default: r_0 = 0xf; break; + } + *valp = r_0; + return 0; +} + +static int +Operand_b4constu_decode (uint32 *valp) +{ + unsigned b4constu_0, r_0; + r_0 = *valp & 0xf; + b4constu_0 = CONST_TBL_b4cu_0[r_0 & 0xf]; + *valp = b4constu_0; + return 0; +} + +static int +Operand_b4constu_encode (uint32 *valp) +{ + unsigned r_0, b4constu_0; + b4constu_0 = *valp; + switch (b4constu_0) + { + case 0x8000: r_0 = 0; break; + case 0x10000: r_0 = 0x1; break; + case 0x2: r_0 = 0x2; break; + case 0x3: r_0 = 0x3; break; + case 0x4: r_0 = 0x4; break; + case 0x5: r_0 = 0x5; break; + case 0x6: r_0 = 0x6; break; + case 0x7: r_0 = 0x7; break; + case 0x8: r_0 = 0x8; break; + case 0xa: r_0 = 0x9; break; + case 0xc: r_0 = 0xa; break; + case 0x10: r_0 = 0xb; break; + case 0x20: r_0 = 0xc; break; + case 0x40: r_0 = 0xd; break; + case 0x80: r_0 = 0xe; break; + default: r_0 = 0xf; break; + } + *valp = r_0; + return 0; +} + +static int +Operand_uimm8_decode (uint32 *valp) +{ + unsigned uimm8_0, imm8_0; + imm8_0 = *valp & 0xff; + uimm8_0 = imm8_0; + *valp = uimm8_0; + return 0; +} + +static int +Operand_uimm8_encode (uint32 *valp) +{ + unsigned imm8_0, uimm8_0; + uimm8_0 = *valp; + imm8_0 = (uimm8_0 & 0xff); + *valp = imm8_0; + return 0; +} + +static int +Operand_uimm8x2_decode (uint32 *valp) +{ + unsigned uimm8x2_0, imm8_0; + imm8_0 = *valp & 0xff; + uimm8x2_0 = imm8_0 << 1; + *valp = uimm8x2_0; + return 0; +} + +static int +Operand_uimm8x2_encode (uint32 *valp) +{ + unsigned imm8_0, uimm8x2_0; + uimm8x2_0 = *valp; + imm8_0 = ((uimm8x2_0 >> 1) & 0xff); + *valp = imm8_0; + return 0; +} + +static int +Operand_uimm8x4_decode (uint32 *valp) +{ + unsigned uimm8x4_0, imm8_0; + imm8_0 = *valp & 0xff; + uimm8x4_0 = imm8_0 << 2; + *valp = uimm8x4_0; + return 0; +} + +static int +Operand_uimm8x4_encode (uint32 *valp) +{ + unsigned imm8_0, uimm8x4_0; + uimm8x4_0 = *valp; + imm8_0 = ((uimm8x4_0 >> 2) & 0xff); + *valp = imm8_0; + return 0; +} + +static int +Operand_uimm4x16_decode (uint32 *valp) +{ + unsigned uimm4x16_0, op2_0; + op2_0 = *valp & 0xf; + uimm4x16_0 = op2_0 << 4; + *valp = uimm4x16_0; + return 0; +} + +static int +Operand_uimm4x16_encode (uint32 *valp) +{ + unsigned op2_0, uimm4x16_0; + uimm4x16_0 = *valp; + op2_0 = ((uimm4x16_0 >> 4) & 0xf); + *valp = op2_0; + return 0; +} + +static int +Operand_simm8_decode (uint32 *valp) +{ + unsigned simm8_0, imm8_0; + imm8_0 = *valp & 0xff; + simm8_0 = ((int) imm8_0 << 24) >> 24; + *valp = simm8_0; + return 0; +} + +static int +Operand_simm8_encode (uint32 *valp) +{ + unsigned imm8_0, simm8_0; + simm8_0 = *valp; + imm8_0 = (simm8_0 & 0xff); + *valp = imm8_0; + return 0; +} + +static int +Operand_simm8x256_decode (uint32 *valp) +{ + unsigned simm8x256_0, imm8_0; + imm8_0 = *valp & 0xff; + simm8x256_0 = (((int) imm8_0 << 24) >> 24) << 8; + *valp = simm8x256_0; + return 0; +} + +static int +Operand_simm8x256_encode (uint32 *valp) +{ + unsigned imm8_0, simm8x256_0; + simm8x256_0 = *valp; + imm8_0 = ((simm8x256_0 >> 8) & 0xff); + *valp = imm8_0; + return 0; +} + +static int +Operand_simm12b_decode (uint32 *valp) +{ + unsigned simm12b_0, imm12b_0; + imm12b_0 = *valp & 0xfff; + simm12b_0 = ((int) imm12b_0 << 20) >> 20; + *valp = simm12b_0; + return 0; +} + +static int +Operand_simm12b_encode (uint32 *valp) +{ + unsigned imm12b_0, simm12b_0; + simm12b_0 = *valp; + imm12b_0 = (simm12b_0 & 0xfff); + *valp = imm12b_0; + return 0; +} + +static int +Operand_msalp32_decode (uint32 *valp) +{ + unsigned msalp32_0, sal_0; + sal_0 = *valp & 0x1f; + msalp32_0 = 0x20 - sal_0; + *valp = msalp32_0; + return 0; +} + +static int +Operand_msalp32_encode (uint32 *valp) +{ + unsigned sal_0, msalp32_0; + msalp32_0 = *valp; + sal_0 = (0x20 - msalp32_0) & 0x1f; + *valp = sal_0; + return 0; +} + +static int +Operand_op2p1_decode (uint32 *valp) +{ + unsigned op2p1_0, op2_0; + op2_0 = *valp & 0xf; + op2p1_0 = op2_0 + 0x1; + *valp = op2p1_0; + return 0; +} + +static int +Operand_op2p1_encode (uint32 *valp) +{ + unsigned op2_0, op2p1_0; + op2p1_0 = *valp; + op2_0 = (op2p1_0 - 0x1) & 0xf; + *valp = op2_0; + return 0; +} + +static int +Operand_label8_decode (uint32 *valp) +{ + unsigned label8_0, imm8_0; + imm8_0 = *valp & 0xff; + label8_0 = 0x4 + (((int) imm8_0 << 24) >> 24); + *valp = label8_0; + return 0; +} + +static int +Operand_label8_encode (uint32 *valp) +{ + unsigned imm8_0, label8_0; + label8_0 = *valp; + imm8_0 = (label8_0 - 0x4) & 0xff; + *valp = imm8_0; + return 0; +} + +static int +Operand_label8_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_label8_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_ulabel8_decode (uint32 *valp) +{ + unsigned ulabel8_0, imm8_0; + imm8_0 = *valp & 0xff; + ulabel8_0 = 0x4 + (((0) << 8) | imm8_0); + *valp = ulabel8_0; + return 0; +} + +static int +Operand_ulabel8_encode (uint32 *valp) +{ + unsigned imm8_0, ulabel8_0; + ulabel8_0 = *valp; + imm8_0 = (ulabel8_0 - 0x4) & 0xff; + *valp = imm8_0; + return 0; +} + +static int +Operand_ulabel8_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_ulabel8_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_label12_decode (uint32 *valp) +{ + unsigned label12_0, imm12_0; + imm12_0 = *valp & 0xfff; + label12_0 = 0x4 + (((int) imm12_0 << 20) >> 20); + *valp = label12_0; + return 0; +} + +static int +Operand_label12_encode (uint32 *valp) +{ + unsigned imm12_0, label12_0; + label12_0 = *valp; + imm12_0 = (label12_0 - 0x4) & 0xfff; + *valp = imm12_0; + return 0; +} + +static int +Operand_label12_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_label12_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_soffset_decode (uint32 *valp) +{ + unsigned soffset_0, offset_0; + offset_0 = *valp & 0x3ffff; + soffset_0 = 0x4 + (((int) offset_0 << 14) >> 14); + *valp = soffset_0; + return 0; +} + +static int +Operand_soffset_encode (uint32 *valp) +{ + unsigned offset_0, soffset_0; + soffset_0 = *valp; + offset_0 = (soffset_0 - 0x4) & 0x3ffff; + *valp = offset_0; + return 0; +} + +static int +Operand_soffset_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_soffset_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_uimm16x4_decode (uint32 *valp) +{ + unsigned uimm16x4_0, imm16_0; + imm16_0 = *valp & 0xffff; + uimm16x4_0 = (((0xffff) << 16) | imm16_0) << 2; + *valp = uimm16x4_0; + return 0; +} + +static int +Operand_uimm16x4_encode (uint32 *valp) +{ + unsigned imm16_0, uimm16x4_0; + uimm16x4_0 = *valp; + imm16_0 = (uimm16x4_0 >> 2) & 0xffff; + *valp = imm16_0; + return 0; +} + +static int +Operand_uimm16x4_ator (uint32 *valp, uint32 pc) +{ + *valp -= ((pc + 3) & ~0x3); + return 0; +} + +static int +Operand_uimm16x4_rtoa (uint32 *valp, uint32 pc) +{ + *valp += ((pc + 3) & ~0x3); + return 0; +} + +static int +Operand_immt_decode (uint32 *valp) +{ + unsigned immt_0, t_0; + t_0 = *valp & 0xf; + immt_0 = t_0; + *valp = immt_0; + return 0; +} + +static int +Operand_immt_encode (uint32 *valp) +{ + unsigned t_0, immt_0; + immt_0 = *valp; + t_0 = immt_0 & 0xf; + *valp = t_0; + return 0; +} + +static int +Operand_imms_decode (uint32 *valp) +{ + unsigned imms_0, s_0; + s_0 = *valp & 0xf; + imms_0 = s_0; + *valp = imms_0; + return 0; +} + +static int +Operand_imms_encode (uint32 *valp) +{ + unsigned s_0, imms_0; + imms_0 = *valp; + s_0 = imms_0 & 0xf; + *valp = s_0; + return 0; +} + +static int +Operand_bt_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_bt_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_bs_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_bs_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_br_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_br_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_bt2_decode (uint32 *valp) +{ + *valp = *valp << 1; + return 0; +} + +static int +Operand_bt2_encode (uint32 *valp) +{ + int error; + error = (*valp & ~(0x7 << 1)) != 0; + *valp = *valp >> 1; + return error; +} + +static int +Operand_bs2_decode (uint32 *valp) +{ + *valp = *valp << 1; + return 0; +} + +static int +Operand_bs2_encode (uint32 *valp) +{ + int error; + error = (*valp & ~(0x7 << 1)) != 0; + *valp = *valp >> 1; + return error; +} + +static int +Operand_br2_decode (uint32 *valp) +{ + *valp = *valp << 1; + return 0; +} + +static int +Operand_br2_encode (uint32 *valp) +{ + int error; + error = (*valp & ~(0x7 << 1)) != 0; + *valp = *valp >> 1; + return error; +} + +static int +Operand_bt4_decode (uint32 *valp) +{ + *valp = *valp << 2; + return 0; +} + +static int +Operand_bt4_encode (uint32 *valp) +{ + int error; + error = (*valp & ~(0x3 << 2)) != 0; + *valp = *valp >> 2; + return error; +} + +static int +Operand_bs4_decode (uint32 *valp) +{ + *valp = *valp << 2; + return 0; +} + +static int +Operand_bs4_encode (uint32 *valp) +{ + int error; + error = (*valp & ~(0x3 << 2)) != 0; + *valp = *valp >> 2; + return error; +} + +static int +Operand_br4_decode (uint32 *valp) +{ + *valp = *valp << 2; + return 0; +} + +static int +Operand_br4_encode (uint32 *valp) +{ + int error; + error = (*valp & ~(0x3 << 2)) != 0; + *valp = *valp >> 2; + return error; +} + +static int +Operand_bt8_decode (uint32 *valp) +{ + *valp = *valp << 3; + return 0; +} + +static int +Operand_bt8_encode (uint32 *valp) +{ + int error; + error = (*valp & ~(0x1 << 3)) != 0; + *valp = *valp >> 3; + return error; +} + +static int +Operand_bs8_decode (uint32 *valp) +{ + *valp = *valp << 3; + return 0; +} + +static int +Operand_bs8_encode (uint32 *valp) +{ + int error; + error = (*valp & ~(0x1 << 3)) != 0; + *valp = *valp >> 3; + return error; +} + +static int +Operand_br8_decode (uint32 *valp) +{ + *valp = *valp << 3; + return 0; +} + +static int +Operand_br8_encode (uint32 *valp) +{ + int error; + error = (*valp & ~(0x1 << 3)) != 0; + *valp = *valp >> 3; + return error; +} + +static int +Operand_bt16_decode (uint32 *valp) +{ + *valp = *valp << 4; + return 0; +} + +static int +Operand_bt16_encode (uint32 *valp) +{ + int error; + error = (*valp & ~(0 << 4)) != 0; + *valp = *valp >> 4; + return error; +} + +static int +Operand_bs16_decode (uint32 *valp) +{ + *valp = *valp << 4; + return 0; +} + +static int +Operand_bs16_encode (uint32 *valp) +{ + int error; + error = (*valp & ~(0 << 4)) != 0; + *valp = *valp >> 4; + return error; +} + +static int +Operand_br16_decode (uint32 *valp) +{ + *valp = *valp << 4; + return 0; +} + +static int +Operand_br16_encode (uint32 *valp) +{ + int error; + error = (*valp & ~(0 << 4)) != 0; + *valp = *valp >> 4; + return error; +} + +static int +Operand_brall_decode (uint32 *valp) +{ + *valp = *valp << 4; + return 0; +} + +static int +Operand_brall_encode (uint32 *valp) +{ + int error; + error = (*valp & ~(0 << 4)) != 0; + *valp = *valp >> 4; + return error; +} + +static int +Operand_tp7_decode (uint32 *valp) +{ + unsigned tp7_0, t_0; + t_0 = *valp & 0xf; + tp7_0 = t_0 + 0x7; + *valp = tp7_0; + return 0; +} + +static int +Operand_tp7_encode (uint32 *valp) +{ + unsigned t_0, tp7_0; + tp7_0 = *valp; + t_0 = (tp7_0 - 0x7) & 0xf; + *valp = t_0; + return 0; +} + +static int +Operand_xt_wbr15_label_decode (uint32 *valp) +{ + unsigned xt_wbr15_label_0, xt_wbr15_imm_0; + xt_wbr15_imm_0 = *valp & 0x7fff; + xt_wbr15_label_0 = 0x4 + (((int) xt_wbr15_imm_0 << 17) >> 17); + *valp = xt_wbr15_label_0; + return 0; +} + +static int +Operand_xt_wbr15_label_encode (uint32 *valp) +{ + unsigned xt_wbr15_imm_0, xt_wbr15_label_0; + xt_wbr15_label_0 = *valp; + xt_wbr15_imm_0 = (xt_wbr15_label_0 - 0x4) & 0x7fff; + *valp = xt_wbr15_imm_0; + return 0; +} + +static int +Operand_xt_wbr15_label_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_xt_wbr15_label_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_xt_wbr18_label_decode (uint32 *valp) +{ + unsigned xt_wbr18_label_0, xt_wbr18_imm_0; + xt_wbr18_imm_0 = *valp & 0x3ffff; + xt_wbr18_label_0 = 0x4 + (((int) xt_wbr18_imm_0 << 14) >> 14); + *valp = xt_wbr18_label_0; + return 0; +} + +static int +Operand_xt_wbr18_label_encode (uint32 *valp) +{ + unsigned xt_wbr18_imm_0, xt_wbr18_label_0; + xt_wbr18_label_0 = *valp; + xt_wbr18_imm_0 = (xt_wbr18_label_0 - 0x4) & 0x3ffff; + *valp = xt_wbr18_imm_0; + return 0; +} + +static int +Operand_xt_wbr18_label_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_xt_wbr18_label_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_cimm8x4_decode (uint32 *valp) +{ + unsigned cimm8x4_0, fimm8_0; + fimm8_0 = *valp & 0xff; + cimm8x4_0 = (fimm8_0 << 2) | 0; + *valp = cimm8x4_0; + return 0; +} + +static int +Operand_cimm8x4_encode (uint32 *valp) +{ + unsigned fimm8_0, cimm8x4_0; + cimm8x4_0 = *valp; + fimm8_0 = (cimm8x4_0 >> 2) & 0xff; + *valp = fimm8_0; + return 0; +} + +static int +Operand_frr_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_frr_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_frs_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_frs_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_frt_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_frt_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper45_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper45_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper46_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper46_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper47_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper47_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper48_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper48_imm_0, dsp340050b49a6c_fld2047_0; + dsp340050b49a6c_fld2047_0 = *valp & 0x1; + dsp340050b49a6c_oper48_imm_0 = (0 << 1) | dsp340050b49a6c_fld2047_0; + *valp = dsp340050b49a6c_oper48_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper48_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2047_0, dsp340050b49a6c_oper48_imm_0; + dsp340050b49a6c_oper48_imm_0 = *valp; + dsp340050b49a6c_fld2047_0 = (((dsp340050b49a6c_oper48_imm_0 >> 0) & 1)) & 0x1; + *valp = dsp340050b49a6c_fld2047_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper49_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper49_imm_0, dsp340050b49a6c_fld2025_0; + dsp340050b49a6c_fld2025_0 = *valp & 0x1; + dsp340050b49a6c_oper49_imm_0 = (0 << 1) | dsp340050b49a6c_fld2025_0; + *valp = dsp340050b49a6c_oper49_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper49_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2025_0, dsp340050b49a6c_oper49_imm_0; + dsp340050b49a6c_oper49_imm_0 = *valp; + dsp340050b49a6c_fld2025_0 = (((dsp340050b49a6c_oper49_imm_0 >> 0) & 1)) & 0x1; + *valp = dsp340050b49a6c_fld2025_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper50_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper50_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper51_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper51_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0x7) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper52_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper52_imm_0, dsp340050b49a6c_fld2049_0; + dsp340050b49a6c_fld2049_0 = *valp & 0x3; + dsp340050b49a6c_oper52_imm_0 = (0 << 2) | dsp340050b49a6c_fld2049_0; + *valp = dsp340050b49a6c_oper52_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper52_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2049_0, dsp340050b49a6c_oper52_imm_0; + dsp340050b49a6c_oper52_imm_0 = *valp; + dsp340050b49a6c_fld2049_0 = (dsp340050b49a6c_oper52_imm_0 & 0x3); + *valp = dsp340050b49a6c_fld2049_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper53_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper53_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper54_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper54_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0x7) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper55_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper55_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper56_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper56_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper57_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper57_imm_0, dsp340050b49a6c_fld2041_0; + dsp340050b49a6c_fld2041_0 = *valp & 0x1; + dsp340050b49a6c_oper57_imm_0 = (0 << 1) | dsp340050b49a6c_fld2041_0; + *valp = dsp340050b49a6c_oper57_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper57_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2041_0, dsp340050b49a6c_oper57_imm_0; + dsp340050b49a6c_oper57_imm_0 = *valp; + dsp340050b49a6c_fld2041_0 = (((dsp340050b49a6c_oper57_imm_0 >> 0) & 1)) & 0x1; + *valp = dsp340050b49a6c_fld2041_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper58_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper58_imm_0, dsp340050b49a6c_fld2051_0; + dsp340050b49a6c_fld2051_0 = *valp & 0x3f; + dsp340050b49a6c_oper58_imm_0 = ((int) dsp340050b49a6c_fld2051_0 << 26) >> 26; + *valp = dsp340050b49a6c_oper58_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper58_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2051_0, dsp340050b49a6c_oper58_imm_0; + dsp340050b49a6c_oper58_imm_0 = *valp; + dsp340050b49a6c_fld2051_0 = (dsp340050b49a6c_oper58_imm_0 & 0x3f); + *valp = dsp340050b49a6c_fld2051_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper59_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper59_imm_0, dsp340050b49a6c_fld2052_0; + dsp340050b49a6c_fld2052_0 = *valp & 0xf; + dsp340050b49a6c_oper59_imm_0 = (0 << 4) | dsp340050b49a6c_fld2052_0; + *valp = dsp340050b49a6c_oper59_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper59_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2052_0, dsp340050b49a6c_oper59_imm_0; + dsp340050b49a6c_oper59_imm_0 = *valp; + dsp340050b49a6c_fld2052_0 = (dsp340050b49a6c_oper59_imm_0 & 0xf); + *valp = dsp340050b49a6c_fld2052_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper60_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper60_imm_0, dsp340050b49a6c_fld2053_0; + dsp340050b49a6c_fld2053_0 = *valp & 0x1f; + dsp340050b49a6c_oper60_imm_0 = (0 << 5) | dsp340050b49a6c_fld2053_0; + *valp = dsp340050b49a6c_oper60_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper60_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2053_0, dsp340050b49a6c_oper60_imm_0; + dsp340050b49a6c_oper60_imm_0 = *valp; + dsp340050b49a6c_fld2053_0 = (dsp340050b49a6c_oper60_imm_0 & 0x1f); + *valp = dsp340050b49a6c_fld2053_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper61_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper61_imm_0, dsp340050b49a6c_fld2044_0; + dsp340050b49a6c_fld2044_0 = *valp & 0x1f; + dsp340050b49a6c_oper61_imm_0 = (0 << 5) | dsp340050b49a6c_fld2044_0; + *valp = dsp340050b49a6c_oper61_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper61_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2044_0, dsp340050b49a6c_oper61_imm_0; + dsp340050b49a6c_oper61_imm_0 = *valp; + dsp340050b49a6c_fld2044_0 = (dsp340050b49a6c_oper61_imm_0 & 0x1f); + *valp = dsp340050b49a6c_fld2044_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper62_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper62_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper63_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper63_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0x7) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper64_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper64_imm_0, dsp340050b49a6c_fld2032_0; + dsp340050b49a6c_fld2032_0 = *valp & 0x3; + dsp340050b49a6c_oper64_imm_0 = (0 << 2) | dsp340050b49a6c_fld2032_0; + *valp = dsp340050b49a6c_oper64_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper64_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2032_0, dsp340050b49a6c_oper64_imm_0; + dsp340050b49a6c_oper64_imm_0 = *valp; + dsp340050b49a6c_fld2032_0 = (dsp340050b49a6c_oper64_imm_0 & 0x3); + *valp = dsp340050b49a6c_fld2032_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper65_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper65_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper66_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper66_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0x7) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper67_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper67_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0x7) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper68_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper68_imm_0, dsp340050b49a6c_fld2035_0; + dsp340050b49a6c_fld2035_0 = *valp & 0x3; + dsp340050b49a6c_oper68_imm_0 = (0 << 2) | dsp340050b49a6c_fld2035_0; + *valp = dsp340050b49a6c_oper68_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper68_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2035_0, dsp340050b49a6c_oper68_imm_0; + dsp340050b49a6c_oper68_imm_0 = *valp; + dsp340050b49a6c_fld2035_0 = (dsp340050b49a6c_oper68_imm_0 & 0x3); + *valp = dsp340050b49a6c_fld2035_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper69_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper69_imm_0, dsp340050b49a6c_fld2036_0; + dsp340050b49a6c_fld2036_0 = *valp & 0x1; + dsp340050b49a6c_oper69_imm_0 = (0 << 1) | dsp340050b49a6c_fld2036_0; + *valp = dsp340050b49a6c_oper69_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper69_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2036_0, dsp340050b49a6c_oper69_imm_0; + dsp340050b49a6c_oper69_imm_0 = *valp; + dsp340050b49a6c_fld2036_0 = (((dsp340050b49a6c_oper69_imm_0 >> 0) & 1)) & 0x1; + *valp = dsp340050b49a6c_fld2036_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper70_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper70_imm_0, dsp340050b49a6c_fld2037_0; + dsp340050b49a6c_fld2037_0 = *valp & 0x7; + dsp340050b49a6c_oper70_imm_0 = (0 << 3) | dsp340050b49a6c_fld2037_0; + *valp = dsp340050b49a6c_oper70_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper70_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2037_0, dsp340050b49a6c_oper70_imm_0; + dsp340050b49a6c_oper70_imm_0 = *valp; + dsp340050b49a6c_fld2037_0 = (dsp340050b49a6c_oper70_imm_0 & 0x7); + *valp = dsp340050b49a6c_fld2037_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper71_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper71_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0x7) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper72_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper72_imm_0, dsp340050b49a6c_fld2042_0; + dsp340050b49a6c_fld2042_0 = *valp & 0x3; + dsp340050b49a6c_oper72_imm_0 = (0 << 2) | dsp340050b49a6c_fld2042_0; + *valp = dsp340050b49a6c_oper72_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper72_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2042_0, dsp340050b49a6c_oper72_imm_0; + dsp340050b49a6c_oper72_imm_0 = *valp; + dsp340050b49a6c_fld2042_0 = (dsp340050b49a6c_oper72_imm_0 & 0x3); + *valp = dsp340050b49a6c_fld2042_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper73_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper73_imm_0, dsp340050b49a6c_fld2038_0; + dsp340050b49a6c_fld2038_0 = *valp & 0xf; + dsp340050b49a6c_oper73_imm_0 = ((0 << 4) | dsp340050b49a6c_fld2038_0) << 3; + *valp = dsp340050b49a6c_oper73_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper73_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2038_0, dsp340050b49a6c_oper73_imm_0; + dsp340050b49a6c_oper73_imm_0 = *valp; + dsp340050b49a6c_fld2038_0 = ((dsp340050b49a6c_oper73_imm_0 >> 3) & 0xf); + *valp = dsp340050b49a6c_fld2038_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper74_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper74_imm_0, dsp340050b49a6c_fld2038_0; + dsp340050b49a6c_fld2038_0 = *valp & 0xf; + dsp340050b49a6c_oper74_imm_0 = ((0 << 4) | dsp340050b49a6c_fld2038_0) << 4; + *valp = dsp340050b49a6c_oper74_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper74_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2038_0, dsp340050b49a6c_oper74_imm_0; + dsp340050b49a6c_oper74_imm_0 = *valp; + dsp340050b49a6c_fld2038_0 = ((dsp340050b49a6c_oper74_imm_0 >> 4) & 0xf); + *valp = dsp340050b49a6c_fld2038_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper75_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper75_imm_0, dsp340050b49a6c_fld2038_0; + dsp340050b49a6c_fld2038_0 = *valp & 0xf; + dsp340050b49a6c_oper75_imm_0 = ((0 << 4) | dsp340050b49a6c_fld2038_0) << 2; + *valp = dsp340050b49a6c_oper75_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper75_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2038_0, dsp340050b49a6c_oper75_imm_0; + dsp340050b49a6c_oper75_imm_0 = *valp; + dsp340050b49a6c_fld2038_0 = ((dsp340050b49a6c_oper75_imm_0 >> 2) & 0xf); + *valp = dsp340050b49a6c_fld2038_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper76_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper76_imm_0, dsp340050b49a6c_fld2053_0; + dsp340050b49a6c_fld2053_0 = *valp & 0x1f; + dsp340050b49a6c_oper76_imm_0 = ((0 << 5) | dsp340050b49a6c_fld2053_0) << 4; + *valp = dsp340050b49a6c_oper76_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper76_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2053_0, dsp340050b49a6c_oper76_imm_0; + dsp340050b49a6c_oper76_imm_0 = *valp; + dsp340050b49a6c_fld2053_0 = ((dsp340050b49a6c_oper76_imm_0 >> 4) & 0x1f); + *valp = dsp340050b49a6c_fld2053_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper77_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper77_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper78_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper78_imm_0, dsp340050b49a6c_fld2056_0; + dsp340050b49a6c_fld2056_0 = *valp & 0x7; + dsp340050b49a6c_oper78_imm_0 = (0 << 3) | dsp340050b49a6c_fld2056_0; + *valp = dsp340050b49a6c_oper78_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper78_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2056_0, dsp340050b49a6c_oper78_imm_0; + dsp340050b49a6c_oper78_imm_0 = *valp; + dsp340050b49a6c_fld2056_0 = (dsp340050b49a6c_oper78_imm_0 & 0x7); + *valp = dsp340050b49a6c_fld2056_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper79_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper79_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper80_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper80_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper81_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper81_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper82_reg_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +Operand_dsp340050b49a6c_oper82_reg_encode (uint32 *valp) +{ + int error; + error = (*valp & ~0xf) != 0; + return error; +} + +static int +Operand_dsp340050b49a6c_oper83_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper83_imm_0, dsp340050b49a6c_fld2040_0; + dsp340050b49a6c_fld2040_0 = *valp & 0x1f; + dsp340050b49a6c_oper83_imm_0 = ((0 << 5) | dsp340050b49a6c_fld2040_0) << 4; + *valp = dsp340050b49a6c_oper83_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper83_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2040_0, dsp340050b49a6c_oper83_imm_0; + dsp340050b49a6c_oper83_imm_0 = *valp; + dsp340050b49a6c_fld2040_0 = ((dsp340050b49a6c_oper83_imm_0 >> 4) & 0x1f); + *valp = dsp340050b49a6c_fld2040_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper84_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper84_imm_0, dsp340050b49a6c_fld2029_0; + dsp340050b49a6c_fld2029_0 = *valp & 0xf; + dsp340050b49a6c_oper84_imm_0 = ((0 << 4) | dsp340050b49a6c_fld2029_0) << 3; + *valp = dsp340050b49a6c_oper84_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper84_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2029_0, dsp340050b49a6c_oper84_imm_0; + dsp340050b49a6c_oper84_imm_0 = *valp; + dsp340050b49a6c_fld2029_0 = ((dsp340050b49a6c_oper84_imm_0 >> 3) & 0xf); + *valp = dsp340050b49a6c_fld2029_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper85_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper85_imm_0, dsp340050b49a6c_fld2029_0; + dsp340050b49a6c_fld2029_0 = *valp & 0xf; + dsp340050b49a6c_oper85_imm_0 = ((0 << 4) | dsp340050b49a6c_fld2029_0) << 4; + *valp = dsp340050b49a6c_oper85_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper85_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2029_0, dsp340050b49a6c_oper85_imm_0; + dsp340050b49a6c_oper85_imm_0 = *valp; + dsp340050b49a6c_fld2029_0 = ((dsp340050b49a6c_oper85_imm_0 >> 4) & 0xf); + *valp = dsp340050b49a6c_fld2029_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper86_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper86_imm_0, dsp340050b49a6c_fld2029_0; + dsp340050b49a6c_fld2029_0 = *valp & 0xf; + dsp340050b49a6c_oper86_imm_0 = ((0 << 4) | dsp340050b49a6c_fld2029_0) << 2; + *valp = dsp340050b49a6c_oper86_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper86_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2029_0, dsp340050b49a6c_oper86_imm_0; + dsp340050b49a6c_oper86_imm_0 = *valp; + dsp340050b49a6c_fld2029_0 = ((dsp340050b49a6c_oper86_imm_0 >> 2) & 0xf); + *valp = dsp340050b49a6c_fld2029_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper87_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper87_imm_0, dsp340050b49a6c_fld2043_0; + dsp340050b49a6c_fld2043_0 = *valp & 0x1f; + dsp340050b49a6c_oper87_imm_0 = ((0 << 5) | dsp340050b49a6c_fld2043_0) << 4; + *valp = dsp340050b49a6c_oper87_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper87_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2043_0, dsp340050b49a6c_oper87_imm_0; + dsp340050b49a6c_oper87_imm_0 = *valp; + dsp340050b49a6c_fld2043_0 = ((dsp340050b49a6c_oper87_imm_0 >> 4) & 0x1f); + *valp = dsp340050b49a6c_fld2043_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper88_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper88_imm_0, dsp340050b49a6c_fld2030_0; + dsp340050b49a6c_fld2030_0 = *valp & 0xf; + dsp340050b49a6c_oper88_imm_0 = (0 << 4) | dsp340050b49a6c_fld2030_0; + *valp = dsp340050b49a6c_oper88_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper88_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2030_0, dsp340050b49a6c_oper88_imm_0; + dsp340050b49a6c_oper88_imm_0 = *valp; + dsp340050b49a6c_fld2030_0 = (dsp340050b49a6c_oper88_imm_0 & 0xf); + *valp = dsp340050b49a6c_fld2030_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper89_imm_decode (uint32 *valp) +{ + unsigned dsp340050b49a6c_oper89_imm_0, dsp340050b49a6c_fld2052_0; + dsp340050b49a6c_fld2052_0 = *valp & 0xf; + dsp340050b49a6c_oper89_imm_0 = ((0 << 4) | dsp340050b49a6c_fld2052_0) << 2; + *valp = dsp340050b49a6c_oper89_imm_0; + return 0; +} + +static int +Operand_dsp340050b49a6c_oper89_imm_encode (uint32 *valp) +{ + unsigned dsp340050b49a6c_fld2052_0, dsp340050b49a6c_oper89_imm_0; + dsp340050b49a6c_oper89_imm_0 = *valp; + dsp340050b49a6c_fld2052_0 = ((dsp340050b49a6c_oper89_imm_0 >> 2) & 0xf); + *valp = dsp340050b49a6c_fld2052_0; + return 0; +} + +static xtensa_operand_internal operands[] = { + { "soffsetx4", FIELD_offset, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + Operand_soffsetx4_encode, Operand_soffsetx4_decode, + Operand_soffsetx4_ator, Operand_soffsetx4_rtoa }, + { "uimm12x8", FIELD_imm12, -1, 0, + 0, + Operand_uimm12x8_encode, Operand_uimm12x8_decode, + 0, 0 }, + { "simm4", FIELD_mn, -1, 0, + 0, + Operand_simm4_encode, Operand_simm4_decode, + 0, 0 }, + { "arr", FIELD_r, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_arr_encode, Operand_arr_decode, + 0, 0 }, + { "ars", FIELD_s, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_ars_encode, Operand_ars_decode, + 0, 0 }, + { "*ars_invisible", FIELD_s, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + Operand_ars_encode, Operand_ars_decode, + 0, 0 }, + { "art", FIELD_t, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_art_encode, Operand_art_decode, + 0, 0 }, + { "ar0", FIELD__ar0, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + Operand_ar0_encode, Operand_ar0_decode, + 0, 0 }, + { "ar4", FIELD__ar4, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + Operand_ar4_encode, Operand_ar4_decode, + 0, 0 }, + { "ar8", FIELD__ar8, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + Operand_ar8_encode, Operand_ar8_decode, + 0, 0 }, + { "ar12", FIELD__ar12, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + Operand_ar12_encode, Operand_ar12_decode, + 0, 0 }, + { "ars_entry", FIELD_s, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_ars_entry_encode, Operand_ars_entry_decode, + 0, 0 }, + { "immrx4", FIELD_r, -1, 0, + 0, + Operand_immrx4_encode, Operand_immrx4_decode, + 0, 0 }, + { "lsi4x4", FIELD_r, -1, 0, + 0, + Operand_lsi4x4_encode, Operand_lsi4x4_decode, + 0, 0 }, + { "simm7", FIELD_imm7, -1, 0, + 0, + Operand_simm7_encode, Operand_simm7_decode, + 0, 0 }, + { "uimm6", FIELD_imm6, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + Operand_uimm6_encode, Operand_uimm6_decode, + Operand_uimm6_ator, Operand_uimm6_rtoa }, + { "ai4const", FIELD_t, -1, 0, + 0, + Operand_ai4const_encode, Operand_ai4const_decode, + 0, 0 }, + { "b4const", FIELD_r, -1, 0, + 0, + Operand_b4const_encode, Operand_b4const_decode, + 0, 0 }, + { "b4constu", FIELD_r, -1, 0, + 0, + Operand_b4constu_encode, Operand_b4constu_decode, + 0, 0 }, + { "uimm8", FIELD_imm8, -1, 0, + 0, + Operand_uimm8_encode, Operand_uimm8_decode, + 0, 0 }, + { "uimm8x2", FIELD_imm8, -1, 0, + 0, + Operand_uimm8x2_encode, Operand_uimm8x2_decode, + 0, 0 }, + { "uimm8x4", FIELD_imm8, -1, 0, + 0, + Operand_uimm8x4_encode, Operand_uimm8x4_decode, + 0, 0 }, + { "uimm4x16", FIELD_op2, -1, 0, + 0, + Operand_uimm4x16_encode, Operand_uimm4x16_decode, + 0, 0 }, + { "simm8", FIELD_imm8, -1, 0, + 0, + Operand_simm8_encode, Operand_simm8_decode, + 0, 0 }, + { "simm8x256", FIELD_imm8, -1, 0, + 0, + Operand_simm8x256_encode, Operand_simm8x256_decode, + 0, 0 }, + { "simm12b", FIELD_imm12b, -1, 0, + 0, + Operand_simm12b_encode, Operand_simm12b_decode, + 0, 0 }, + { "msalp32", FIELD_sal, -1, 0, + 0, + Operand_msalp32_encode, Operand_msalp32_decode, + 0, 0 }, + { "op2p1", FIELD_op2, -1, 0, + 0, + Operand_op2p1_encode, Operand_op2p1_decode, + 0, 0 }, + { "label8", FIELD_imm8, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + Operand_label8_encode, Operand_label8_decode, + Operand_label8_ator, Operand_label8_rtoa }, + { "ulabel8", FIELD_imm8, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + Operand_ulabel8_encode, Operand_ulabel8_decode, + Operand_ulabel8_ator, Operand_ulabel8_rtoa }, + { "label12", FIELD_imm12, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + Operand_label12_encode, Operand_label12_decode, + Operand_label12_ator, Operand_label12_rtoa }, + { "soffset", FIELD_offset, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + Operand_soffset_encode, Operand_soffset_decode, + Operand_soffset_ator, Operand_soffset_rtoa }, + { "uimm16x4", FIELD_imm16, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + Operand_uimm16x4_encode, Operand_uimm16x4_decode, + Operand_uimm16x4_ator, Operand_uimm16x4_rtoa }, + { "immt", FIELD_t, -1, 0, + 0, + Operand_immt_encode, Operand_immt_decode, + 0, 0 }, + { "imms", FIELD_s, -1, 0, + 0, + Operand_imms_encode, Operand_imms_decode, + 0, 0 }, + { "bt", FIELD_t, REGFILE_BR, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_bt_encode, Operand_bt_decode, + 0, 0 }, + { "bs", FIELD_s, REGFILE_BR, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_bs_encode, Operand_bs_decode, + 0, 0 }, + { "br", FIELD_r, REGFILE_BR, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_br_encode, Operand_br_decode, + 0, 0 }, + { "bt2", FIELD_t2, REGFILE_BR, 2, + XTENSA_OPERAND_IS_REGISTER, + Operand_bt2_encode, Operand_bt2_decode, + 0, 0 }, + { "bs2", FIELD_s2, REGFILE_BR, 2, + XTENSA_OPERAND_IS_REGISTER, + Operand_bs2_encode, Operand_bs2_decode, + 0, 0 }, + { "br2", FIELD_r2, REGFILE_BR, 2, + XTENSA_OPERAND_IS_REGISTER, + Operand_br2_encode, Operand_br2_decode, + 0, 0 }, + { "bt4", FIELD_t4, REGFILE_BR, 4, + XTENSA_OPERAND_IS_REGISTER, + Operand_bt4_encode, Operand_bt4_decode, + 0, 0 }, + { "bs4", FIELD_s4, REGFILE_BR, 4, + XTENSA_OPERAND_IS_REGISTER, + Operand_bs4_encode, Operand_bs4_decode, + 0, 0 }, + { "br4", FIELD_r4, REGFILE_BR, 4, + XTENSA_OPERAND_IS_REGISTER, + Operand_br4_encode, Operand_br4_decode, + 0, 0 }, + { "bt8", FIELD_t8, REGFILE_BR, 8, + XTENSA_OPERAND_IS_REGISTER, + Operand_bt8_encode, Operand_bt8_decode, + 0, 0 }, + { "bs8", FIELD_s8, REGFILE_BR, 8, + XTENSA_OPERAND_IS_REGISTER, + Operand_bs8_encode, Operand_bs8_decode, + 0, 0 }, + { "br8", FIELD_r8, REGFILE_BR, 8, + XTENSA_OPERAND_IS_REGISTER, + Operand_br8_encode, Operand_br8_decode, + 0, 0 }, + { "bt16", FIELD__bt16, REGFILE_BR, 16, + XTENSA_OPERAND_IS_REGISTER, + Operand_bt16_encode, Operand_bt16_decode, + 0, 0 }, + { "bs16", FIELD__bs16, REGFILE_BR, 16, + XTENSA_OPERAND_IS_REGISTER, + Operand_bs16_encode, Operand_bs16_decode, + 0, 0 }, + { "br16", FIELD__br16, REGFILE_BR, 16, + XTENSA_OPERAND_IS_REGISTER, + Operand_br16_encode, Operand_br16_decode, + 0, 0 }, + { "brall", FIELD__brall, REGFILE_BR, 16, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + Operand_brall_encode, Operand_brall_decode, + 0, 0 }, + { "tp7", FIELD_t, -1, 0, + 0, + Operand_tp7_encode, Operand_tp7_decode, + 0, 0 }, + { "xt_wbr15_label", FIELD_xt_wbr15_imm, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + Operand_xt_wbr15_label_encode, Operand_xt_wbr15_label_decode, + Operand_xt_wbr15_label_ator, Operand_xt_wbr15_label_rtoa }, + { "xt_wbr18_label", FIELD_xt_wbr18_imm, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + Operand_xt_wbr18_label_encode, Operand_xt_wbr18_label_decode, + Operand_xt_wbr18_label_ator, Operand_xt_wbr18_label_rtoa }, + { "cimm8x4", FIELD_fimm8, -1, 0, + 0, + Operand_cimm8x4_encode, Operand_cimm8x4_decode, + 0, 0 }, + { "frr", FIELD_r, REGFILE_FR, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_frr_encode, Operand_frr_decode, + 0, 0 }, + { "frs", FIELD_s, REGFILE_FR, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_frs_encode, Operand_frs_decode, + 0, 0 }, + { "frt", FIELD_t, REGFILE_FR, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_frt_encode, Operand_frt_decode, + 0, 0 }, + { "dsp340050b49a6c_oper45_reg", FIELD_dsp340050b49a6c_fld2045, REGFILE_CM, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper45_reg_encode, Operand_dsp340050b49a6c_oper45_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper46_reg", FIELD_dsp340050b49a6c_fld2046, REGFILE_CM, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper46_reg_encode, Operand_dsp340050b49a6c_oper46_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper47_reg", FIELD_dsp340050b49a6c_fld2029, REGFILE_CM, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper47_reg_encode, Operand_dsp340050b49a6c_oper47_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper48_imm", FIELD_dsp340050b49a6c_fld2047, -1, 0, + 0, + Operand_dsp340050b49a6c_oper48_imm_encode, Operand_dsp340050b49a6c_oper48_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper49_imm", FIELD_dsp340050b49a6c_fld2025, -1, 0, + 0, + Operand_dsp340050b49a6c_oper49_imm_encode, Operand_dsp340050b49a6c_oper49_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper50_reg", FIELD_dsp340050b49a6c_fld2026, REGFILE_CM, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper50_reg_encode, Operand_dsp340050b49a6c_oper50_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper51_reg", FIELD_dsp340050b49a6c_fld2048, REGFILE_ACU, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper51_reg_encode, Operand_dsp340050b49a6c_oper51_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper52_imm", FIELD_dsp340050b49a6c_fld2049, -1, 0, + 0, + Operand_dsp340050b49a6c_oper52_imm_encode, Operand_dsp340050b49a6c_oper52_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper53_reg", FIELD_dsp340050b49a6c_fld2027, REGFILE_CM, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper53_reg_encode, Operand_dsp340050b49a6c_oper53_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper54_reg", FIELD_dsp340050b49a6c_fld2028, REGFILE_ACU, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper54_reg_encode, Operand_dsp340050b49a6c_oper54_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper55_reg", FIELD_dsp340050b49a6c_fld2030, REGFILE_CM, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper55_reg_encode, Operand_dsp340050b49a6c_oper55_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper56_reg", FIELD_dsp340050b49a6c_fld2050, REGFILE_PQ, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper56_reg_encode, Operand_dsp340050b49a6c_oper56_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper57_imm", FIELD_dsp340050b49a6c_fld2041, -1, 0, + 0, + Operand_dsp340050b49a6c_oper57_imm_encode, Operand_dsp340050b49a6c_oper57_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper58_imm", FIELD_dsp340050b49a6c_fld2051, -1, 0, + 0, + Operand_dsp340050b49a6c_oper58_imm_encode, Operand_dsp340050b49a6c_oper58_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper59_imm", FIELD_dsp340050b49a6c_fld2052, -1, 0, + 0, + Operand_dsp340050b49a6c_oper59_imm_encode, Operand_dsp340050b49a6c_oper59_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper60_imm", FIELD_dsp340050b49a6c_fld2053, -1, 0, + 0, + Operand_dsp340050b49a6c_oper60_imm_encode, Operand_dsp340050b49a6c_oper60_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper61_imm", FIELD_dsp340050b49a6c_fld2044, -1, 0, + 0, + Operand_dsp340050b49a6c_oper61_imm_encode, Operand_dsp340050b49a6c_oper61_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper62_reg", FIELD_dsp340050b49a6c_fld2031, REGFILE_CM, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper62_reg_encode, Operand_dsp340050b49a6c_oper62_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper63_reg", FIELD_dsp340050b49a6c_fld2054, REGFILE_ACU, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper63_reg_encode, Operand_dsp340050b49a6c_oper63_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper64_imm", FIELD_dsp340050b49a6c_fld2032, -1, 0, + 0, + Operand_dsp340050b49a6c_oper64_imm_encode, Operand_dsp340050b49a6c_oper64_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper65_reg", FIELD_dsp340050b49a6c_fld2055, REGFILE_PQ, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper65_reg_encode, Operand_dsp340050b49a6c_oper65_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper66_reg", FIELD_dsp340050b49a6c_fld2033, REGFILE_ACU, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper66_reg_encode, Operand_dsp340050b49a6c_oper66_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper67_reg", FIELD_dsp340050b49a6c_fld2034, REGFILE_ACU, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper67_reg_encode, Operand_dsp340050b49a6c_oper67_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper68_imm", FIELD_dsp340050b49a6c_fld2035, -1, 0, + 0, + Operand_dsp340050b49a6c_oper68_imm_encode, Operand_dsp340050b49a6c_oper68_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper69_imm", FIELD_dsp340050b49a6c_fld2036, -1, 0, + 0, + Operand_dsp340050b49a6c_oper69_imm_encode, Operand_dsp340050b49a6c_oper69_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper70_imm", FIELD_dsp340050b49a6c_fld2037, -1, 0, + 0, + Operand_dsp340050b49a6c_oper70_imm_encode, Operand_dsp340050b49a6c_oper70_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper71_reg", FIELD_dsp340050b49a6c_fld2037, REGFILE_ACU, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper71_reg_encode, Operand_dsp340050b49a6c_oper71_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper72_imm", FIELD_dsp340050b49a6c_fld2042, -1, 0, + 0, + Operand_dsp340050b49a6c_oper72_imm_encode, Operand_dsp340050b49a6c_oper72_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper73_imm", FIELD_dsp340050b49a6c_fld2038, -1, 0, + 0, + Operand_dsp340050b49a6c_oper73_imm_encode, Operand_dsp340050b49a6c_oper73_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper74_imm", FIELD_dsp340050b49a6c_fld2038, -1, 0, + 0, + Operand_dsp340050b49a6c_oper74_imm_encode, Operand_dsp340050b49a6c_oper74_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper75_imm", FIELD_dsp340050b49a6c_fld2038, -1, 0, + 0, + Operand_dsp340050b49a6c_oper75_imm_encode, Operand_dsp340050b49a6c_oper75_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper76_imm", FIELD_dsp340050b49a6c_fld2053, -1, 0, + 0, + Operand_dsp340050b49a6c_oper76_imm_encode, Operand_dsp340050b49a6c_oper76_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper77_reg", FIELD_r, REGFILE_CM, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper77_reg_encode, Operand_dsp340050b49a6c_oper77_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper78_imm", FIELD_dsp340050b49a6c_fld2056, -1, 0, + 0, + Operand_dsp340050b49a6c_oper78_imm_encode, Operand_dsp340050b49a6c_oper78_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper79_reg", FIELD_r, REGFILE_PQ, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper79_reg_encode, Operand_dsp340050b49a6c_oper79_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper80_reg", FIELD_s, REGFILE_CM, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper80_reg_encode, Operand_dsp340050b49a6c_oper80_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper81_reg", FIELD_dsp340050b49a6c_fld2039, REGFILE_PQ, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper81_reg_encode, Operand_dsp340050b49a6c_oper81_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper82_reg", FIELD_dsp340050b49a6c_fld2052, REGFILE_CM, 1, + XTENSA_OPERAND_IS_REGISTER, + Operand_dsp340050b49a6c_oper82_reg_encode, Operand_dsp340050b49a6c_oper82_reg_decode, + 0, 0 }, + { "dsp340050b49a6c_oper83_imm", FIELD_dsp340050b49a6c_fld2040, -1, 0, + 0, + Operand_dsp340050b49a6c_oper83_imm_encode, Operand_dsp340050b49a6c_oper83_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper84_imm", FIELD_dsp340050b49a6c_fld2029, -1, 0, + 0, + Operand_dsp340050b49a6c_oper84_imm_encode, Operand_dsp340050b49a6c_oper84_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper85_imm", FIELD_dsp340050b49a6c_fld2029, -1, 0, + 0, + Operand_dsp340050b49a6c_oper85_imm_encode, Operand_dsp340050b49a6c_oper85_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper86_imm", FIELD_dsp340050b49a6c_fld2029, -1, 0, + 0, + Operand_dsp340050b49a6c_oper86_imm_encode, Operand_dsp340050b49a6c_oper86_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper87_imm", FIELD_dsp340050b49a6c_fld2043, -1, 0, + 0, + Operand_dsp340050b49a6c_oper87_imm_encode, Operand_dsp340050b49a6c_oper87_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper88_imm", FIELD_dsp340050b49a6c_fld2030, -1, 0, + 0, + Operand_dsp340050b49a6c_oper88_imm_encode, Operand_dsp340050b49a6c_oper88_imm_decode, + 0, 0 }, + { "dsp340050b49a6c_oper89_imm", FIELD_dsp340050b49a6c_fld2052, -1, 0, + 0, + Operand_dsp340050b49a6c_oper89_imm_encode, Operand_dsp340050b49a6c_oper89_imm_decode, + 0, 0 }, + { "t", FIELD_t, -1, 0, 0, 0, 0, 0, 0 }, + { "bbi4", FIELD_bbi4, -1, 0, 0, 0, 0, 0, 0 }, + { "bbi", FIELD_bbi, -1, 0, 0, 0, 0, 0, 0 }, + { "imm12", FIELD_imm12, -1, 0, 0, 0, 0, 0, 0 }, + { "imm8", FIELD_imm8, -1, 0, 0, 0, 0, 0, 0 }, + { "s", FIELD_s, -1, 0, 0, 0, 0, 0, 0 }, + { "imm12b", FIELD_imm12b, -1, 0, 0, 0, 0, 0, 0 }, + { "imm16", FIELD_imm16, -1, 0, 0, 0, 0, 0, 0 }, + { "m", FIELD_m, -1, 0, 0, 0, 0, 0, 0 }, + { "n", FIELD_n, -1, 0, 0, 0, 0, 0, 0 }, + { "offset", FIELD_offset, -1, 0, 0, 0, 0, 0, 0 }, + { "op0", FIELD_op0, -1, 0, 0, 0, 0, 0, 0 }, + { "op1", FIELD_op1, -1, 0, 0, 0, 0, 0, 0 }, + { "op2", FIELD_op2, -1, 0, 0, 0, 0, 0, 0 }, + { "r", FIELD_r, -1, 0, 0, 0, 0, 0, 0 }, + { "sa4", FIELD_sa4, -1, 0, 0, 0, 0, 0, 0 }, + { "sae4", FIELD_sae4, -1, 0, 0, 0, 0, 0, 0 }, + { "sae", FIELD_sae, -1, 0, 0, 0, 0, 0, 0 }, + { "sal", FIELD_sal, -1, 0, 0, 0, 0, 0, 0 }, + { "sargt", FIELD_sargt, -1, 0, 0, 0, 0, 0, 0 }, + { "sas4", FIELD_sas4, -1, 0, 0, 0, 0, 0, 0 }, + { "sas", FIELD_sas, -1, 0, 0, 0, 0, 0, 0 }, + { "sr", FIELD_sr, -1, 0, 0, 0, 0, 0, 0 }, + { "st", FIELD_st, -1, 0, 0, 0, 0, 0, 0 }, + { "thi3", FIELD_thi3, -1, 0, 0, 0, 0, 0, 0 }, + { "imm4", FIELD_imm4, -1, 0, 0, 0, 0, 0, 0 }, + { "mn", FIELD_mn, -1, 0, 0, 0, 0, 0, 0 }, + { "i", FIELD_i, -1, 0, 0, 0, 0, 0, 0 }, + { "imm6lo", FIELD_imm6lo, -1, 0, 0, 0, 0, 0, 0 }, + { "imm6hi", FIELD_imm6hi, -1, 0, 0, 0, 0, 0, 0 }, + { "imm7lo", FIELD_imm7lo, -1, 0, 0, 0, 0, 0, 0 }, + { "imm7hi", FIELD_imm7hi, -1, 0, 0, 0, 0, 0, 0 }, + { "z", FIELD_z, -1, 0, 0, 0, 0, 0, 0 }, + { "imm6", FIELD_imm6, -1, 0, 0, 0, 0, 0, 0 }, + { "imm7", FIELD_imm7, -1, 0, 0, 0, 0, 0, 0 }, + { "t2", FIELD_t2, -1, 0, 0, 0, 0, 0, 0 }, + { "s2", FIELD_s2, -1, 0, 0, 0, 0, 0, 0 }, + { "r2", FIELD_r2, -1, 0, 0, 0, 0, 0, 0 }, + { "t4", FIELD_t4, -1, 0, 0, 0, 0, 0, 0 }, + { "s4", FIELD_s4, -1, 0, 0, 0, 0, 0, 0 }, + { "r4", FIELD_r4, -1, 0, 0, 0, 0, 0, 0 }, + { "t8", FIELD_t8, -1, 0, 0, 0, 0, 0, 0 }, + { "s8", FIELD_s8, -1, 0, 0, 0, 0, 0, 0 }, + { "r8", FIELD_r8, -1, 0, 0, 0, 0, 0, 0 }, + { "xt_wbr15_imm", FIELD_xt_wbr15_imm, -1, 0, 0, 0, 0, 0, 0 }, + { "xt_wbr18_imm", FIELD_xt_wbr18_imm, -1, 0, 0, 0, 0, 0, 0 }, + { "fimm8", FIELD_fimm8, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2019", FIELD_dsp340050b49a6c_fld2019, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2021", FIELD_dsp340050b49a6c_fld2021, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2029", FIELD_dsp340050b49a6c_fld2029, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2030", FIELD_dsp340050b49a6c_fld2030, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2032", FIELD_dsp340050b49a6c_fld2032, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2035", FIELD_dsp340050b49a6c_fld2035, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2036", FIELD_dsp340050b49a6c_fld2036, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2037", FIELD_dsp340050b49a6c_fld2037, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2038", FIELD_dsp340050b49a6c_fld2038, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2039", FIELD_dsp340050b49a6c_fld2039, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2040", FIELD_dsp340050b49a6c_fld2040, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2041", FIELD_dsp340050b49a6c_fld2041, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2042", FIELD_dsp340050b49a6c_fld2042, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2043", FIELD_dsp340050b49a6c_fld2043, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2044", FIELD_dsp340050b49a6c_fld2044, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2045", FIELD_dsp340050b49a6c_fld2045, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2046", FIELD_dsp340050b49a6c_fld2046, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2047", FIELD_dsp340050b49a6c_fld2047, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2048", FIELD_dsp340050b49a6c_fld2048, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2049", FIELD_dsp340050b49a6c_fld2049, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2050", FIELD_dsp340050b49a6c_fld2050, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2051", FIELD_dsp340050b49a6c_fld2051, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2052", FIELD_dsp340050b49a6c_fld2052, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2053", FIELD_dsp340050b49a6c_fld2053, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2054", FIELD_dsp340050b49a6c_fld2054, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2055", FIELD_dsp340050b49a6c_fld2055, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2056", FIELD_dsp340050b49a6c_fld2056, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2082Inst", FIELD_dsp340050b49a6c_fld2082Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2083Inst", FIELD_dsp340050b49a6c_fld2083Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2084Inst", FIELD_dsp340050b49a6c_fld2084Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2085Inst", FIELD_dsp340050b49a6c_fld2085Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2086Inst", FIELD_dsp340050b49a6c_fld2086Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2088Inst", FIELD_dsp340050b49a6c_fld2088Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2089Inst", FIELD_dsp340050b49a6c_fld2089Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2090Inst", FIELD_dsp340050b49a6c_fld2090Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2091Inst", FIELD_dsp340050b49a6c_fld2091Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2092Inst", FIELD_dsp340050b49a6c_fld2092Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2094Inst", FIELD_dsp340050b49a6c_fld2094Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2095Inst", FIELD_dsp340050b49a6c_fld2095Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2096Inst", FIELD_dsp340050b49a6c_fld2096Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2098Inst", FIELD_dsp340050b49a6c_fld2098Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2099Inst", FIELD_dsp340050b49a6c_fld2099Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2100Inst", FIELD_dsp340050b49a6c_fld2100Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2101Inst", FIELD_dsp340050b49a6c_fld2101Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2102Inst", FIELD_dsp340050b49a6c_fld2102Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2103Inst", FIELD_dsp340050b49a6c_fld2103Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2104Inst", FIELD_dsp340050b49a6c_fld2104Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2105Inst", FIELD_dsp340050b49a6c_fld2105Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2106Inst", FIELD_dsp340050b49a6c_fld2106Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2107Inst", FIELD_dsp340050b49a6c_fld2107Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2108Inst", FIELD_dsp340050b49a6c_fld2108Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2109Inst", FIELD_dsp340050b49a6c_fld2109Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2110Inst", FIELD_dsp340050b49a6c_fld2110Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2111Inst", FIELD_dsp340050b49a6c_fld2111Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2112Inst", FIELD_dsp340050b49a6c_fld2112Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2113Inst", FIELD_dsp340050b49a6c_fld2113Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2114Inst", FIELD_dsp340050b49a6c_fld2114Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2115Inst", FIELD_dsp340050b49a6c_fld2115Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2116Inst", FIELD_dsp340050b49a6c_fld2116Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2117Inst", FIELD_dsp340050b49a6c_fld2117Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2118Inst", FIELD_dsp340050b49a6c_fld2118Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2119Inst", FIELD_dsp340050b49a6c_fld2119Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2120Inst", FIELD_dsp340050b49a6c_fld2120Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2122Inst", FIELD_dsp340050b49a6c_fld2122Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2123Inst", FIELD_dsp340050b49a6c_fld2123Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2124Inst", FIELD_dsp340050b49a6c_fld2124Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2125Inst", FIELD_dsp340050b49a6c_fld2125Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2126Inst", FIELD_dsp340050b49a6c_fld2126Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2127Inst", FIELD_dsp340050b49a6c_fld2127Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2128Inst", FIELD_dsp340050b49a6c_fld2128Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2129Inst", FIELD_dsp340050b49a6c_fld2129Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2131Inst", FIELD_dsp340050b49a6c_fld2131Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2132Inst", FIELD_dsp340050b49a6c_fld2132Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2133Inst", FIELD_dsp340050b49a6c_fld2133Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2134Inst", FIELD_dsp340050b49a6c_fld2134Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2136Inst", FIELD_dsp340050b49a6c_fld2136Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2137Inst", FIELD_dsp340050b49a6c_fld2137Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2138Inst", FIELD_dsp340050b49a6c_fld2138Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2139Inst", FIELD_dsp340050b49a6c_fld2139Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2140Inst", FIELD_dsp340050b49a6c_fld2140Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2141Inst", FIELD_dsp340050b49a6c_fld2141Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2142Inst", FIELD_dsp340050b49a6c_fld2142Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2143Inst", FIELD_dsp340050b49a6c_fld2143Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2144Inst", FIELD_dsp340050b49a6c_fld2144Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2145Inst", FIELD_dsp340050b49a6c_fld2145Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2146Inst", FIELD_dsp340050b49a6c_fld2146Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2147Inst", FIELD_dsp340050b49a6c_fld2147Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2149Inst", FIELD_dsp340050b49a6c_fld2149Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2151Inst", FIELD_dsp340050b49a6c_fld2151Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2153Inst", FIELD_dsp340050b49a6c_fld2153Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2154Inst", FIELD_dsp340050b49a6c_fld2154Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2155Inst", FIELD_dsp340050b49a6c_fld2155Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2156Inst", FIELD_dsp340050b49a6c_fld2156Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2157Inst", FIELD_dsp340050b49a6c_fld2157Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2158Inst", FIELD_dsp340050b49a6c_fld2158Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2159Inst", FIELD_dsp340050b49a6c_fld2159Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2160Inst", FIELD_dsp340050b49a6c_fld2160Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2161Inst", FIELD_dsp340050b49a6c_fld2161Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2162Inst", FIELD_dsp340050b49a6c_fld2162Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2163Inst", FIELD_dsp340050b49a6c_fld2163Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2164Inst", FIELD_dsp340050b49a6c_fld2164Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2165Inst", FIELD_dsp340050b49a6c_fld2165Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2166Inst", FIELD_dsp340050b49a6c_fld2166Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2167Inst", FIELD_dsp340050b49a6c_fld2167Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2168Inst", FIELD_dsp340050b49a6c_fld2168Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2169Inst", FIELD_dsp340050b49a6c_fld2169Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2171Inst", FIELD_dsp340050b49a6c_fld2171Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2172Inst", FIELD_dsp340050b49a6c_fld2172Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2173Inst", FIELD_dsp340050b49a6c_fld2173Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2174Inst", FIELD_dsp340050b49a6c_fld2174Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2175Inst", FIELD_dsp340050b49a6c_fld2175Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2177Inst", FIELD_dsp340050b49a6c_fld2177Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2178Inst", FIELD_dsp340050b49a6c_fld2178Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2179Inst", FIELD_dsp340050b49a6c_fld2179Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2180Inst", FIELD_dsp340050b49a6c_fld2180Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2181Inst", FIELD_dsp340050b49a6c_fld2181Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2182Inst", FIELD_dsp340050b49a6c_fld2182Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2183Inst", FIELD_dsp340050b49a6c_fld2183Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2184Inst", FIELD_dsp340050b49a6c_fld2184Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2185Inst", FIELD_dsp340050b49a6c_fld2185Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2186Inst", FIELD_dsp340050b49a6c_fld2186Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2187Inst", FIELD_dsp340050b49a6c_fld2187Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2188Inst", FIELD_dsp340050b49a6c_fld2188Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2189Inst", FIELD_dsp340050b49a6c_fld2189Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2190Inst", FIELD_dsp340050b49a6c_fld2190Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2191Inst", FIELD_dsp340050b49a6c_fld2191Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2192Inst", FIELD_dsp340050b49a6c_fld2192Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2193Inst", FIELD_dsp340050b49a6c_fld2193Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2194Inst", FIELD_dsp340050b49a6c_fld2194Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2195Inst", FIELD_dsp340050b49a6c_fld2195Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2196Inst", FIELD_dsp340050b49a6c_fld2196Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2197Inst", FIELD_dsp340050b49a6c_fld2197Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2198Inst", FIELD_dsp340050b49a6c_fld2198Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2199Inst", FIELD_dsp340050b49a6c_fld2199Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2200Inst", FIELD_dsp340050b49a6c_fld2200Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2201Inst", FIELD_dsp340050b49a6c_fld2201Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2202Inst", FIELD_dsp340050b49a6c_fld2202Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2203Inst", FIELD_dsp340050b49a6c_fld2203Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2204Inst", FIELD_dsp340050b49a6c_fld2204Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2205Inst", FIELD_dsp340050b49a6c_fld2205Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2206Inst", FIELD_dsp340050b49a6c_fld2206Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2207Inst", FIELD_dsp340050b49a6c_fld2207Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2208Inst", FIELD_dsp340050b49a6c_fld2208Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2209Inst", FIELD_dsp340050b49a6c_fld2209Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2210Inst", FIELD_dsp340050b49a6c_fld2210Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2211Inst", FIELD_dsp340050b49a6c_fld2211Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2212Inst", FIELD_dsp340050b49a6c_fld2212Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2213Inst", FIELD_dsp340050b49a6c_fld2213Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2214Inst", FIELD_dsp340050b49a6c_fld2214Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2215Inst", FIELD_dsp340050b49a6c_fld2215Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2216Inst", FIELD_dsp340050b49a6c_fld2216Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2217Inst", FIELD_dsp340050b49a6c_fld2217Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2218Inst", FIELD_dsp340050b49a6c_fld2218Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2219Inst", FIELD_dsp340050b49a6c_fld2219Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2220Inst", FIELD_dsp340050b49a6c_fld2220Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2221Inst", FIELD_dsp340050b49a6c_fld2221Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2222Inst", FIELD_dsp340050b49a6c_fld2222Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2223Inst", FIELD_dsp340050b49a6c_fld2223Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2224Inst", FIELD_dsp340050b49a6c_fld2224Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2225Inst", FIELD_dsp340050b49a6c_fld2225Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2226Inst", FIELD_dsp340050b49a6c_fld2226Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2227Inst", FIELD_dsp340050b49a6c_fld2227Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2228Inst", FIELD_dsp340050b49a6c_fld2228Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2229Inst", FIELD_dsp340050b49a6c_fld2229Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2230Inst", FIELD_dsp340050b49a6c_fld2230Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2231Inst", FIELD_dsp340050b49a6c_fld2231Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2232Inst", FIELD_dsp340050b49a6c_fld2232Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2234Inst", FIELD_dsp340050b49a6c_fld2234Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2235Inst", FIELD_dsp340050b49a6c_fld2235Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2236Inst", FIELD_dsp340050b49a6c_fld2236Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2237Inst", FIELD_dsp340050b49a6c_fld2237Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2238Inst", FIELD_dsp340050b49a6c_fld2238Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2239Inst", FIELD_dsp340050b49a6c_fld2239Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2240Inst", FIELD_dsp340050b49a6c_fld2240Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2241Inst", FIELD_dsp340050b49a6c_fld2241Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2242Inst", FIELD_dsp340050b49a6c_fld2242Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2243Inst", FIELD_dsp340050b49a6c_fld2243Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2244Inst", FIELD_dsp340050b49a6c_fld2244Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2245Inst", FIELD_dsp340050b49a6c_fld2245Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2246Inst", FIELD_dsp340050b49a6c_fld2246Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2247Inst", FIELD_dsp340050b49a6c_fld2247Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2248Inst", FIELD_dsp340050b49a6c_fld2248Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2249Inst", FIELD_dsp340050b49a6c_fld2249Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2250Inst", FIELD_dsp340050b49a6c_fld2250Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2251Inst", FIELD_dsp340050b49a6c_fld2251Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2252Inst", FIELD_dsp340050b49a6c_fld2252Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2253Inst", FIELD_dsp340050b49a6c_fld2253Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2254", FIELD_dsp340050b49a6c_fld2254, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2255Inst", FIELD_dsp340050b49a6c_fld2255Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2257Inst", FIELD_dsp340050b49a6c_fld2257Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3627Inst", FIELD_dsp340050b49a6c_fld3627Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3630Inst", FIELD_dsp340050b49a6c_fld3630Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3631Inst", FIELD_dsp340050b49a6c_fld3631Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3633Inst", FIELD_dsp340050b49a6c_fld3633Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3634", FIELD_dsp340050b49a6c_fld3634, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3635Inst", FIELD_dsp340050b49a6c_fld3635Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3636Inst", FIELD_dsp340050b49a6c_fld3636Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3637Inst", FIELD_dsp340050b49a6c_fld3637Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3638Inst", FIELD_dsp340050b49a6c_fld3638Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3639Inst", FIELD_dsp340050b49a6c_fld3639Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3640Inst", FIELD_dsp340050b49a6c_fld3640Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3642Inst", FIELD_dsp340050b49a6c_fld3642Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3643Inst", FIELD_dsp340050b49a6c_fld3643Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3644Inst", FIELD_dsp340050b49a6c_fld3644Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3645Inst", FIELD_dsp340050b49a6c_fld3645Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3647Inst", FIELD_dsp340050b49a6c_fld3647Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3648Inst", FIELD_dsp340050b49a6c_fld3648Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3649Inst", FIELD_dsp340050b49a6c_fld3649Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3650Inst", FIELD_dsp340050b49a6c_fld3650Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3651Inst", FIELD_dsp340050b49a6c_fld3651Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3653Inst", FIELD_dsp340050b49a6c_fld3653Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3654Inst", FIELD_dsp340050b49a6c_fld3654Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3655Inst", FIELD_dsp340050b49a6c_fld3655Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3656Inst", FIELD_dsp340050b49a6c_fld3656Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3657Inst", FIELD_dsp340050b49a6c_fld3657Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3658Inst", FIELD_dsp340050b49a6c_fld3658Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3659Inst", FIELD_dsp340050b49a6c_fld3659Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3660Inst", FIELD_dsp340050b49a6c_fld3660Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3661Inst", FIELD_dsp340050b49a6c_fld3661Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3662Inst", FIELD_dsp340050b49a6c_fld3662Inst, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s3", FIELD_op0_s3, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2025", FIELD_dsp340050b49a6c_fld2025, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2027", FIELD_dsp340050b49a6c_fld2027, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2258GP_slot2", FIELD_dsp340050b49a6c_fld2258GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2259GP_slot2", FIELD_dsp340050b49a6c_fld2259GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2260GP_slot2", FIELD_dsp340050b49a6c_fld2260GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2261GP_slot2", FIELD_dsp340050b49a6c_fld2261GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2262GP_slot2", FIELD_dsp340050b49a6c_fld2262GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2263GP_slot2", FIELD_dsp340050b49a6c_fld2263GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2264GP_slot2", FIELD_dsp340050b49a6c_fld2264GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2266GP_slot2", FIELD_dsp340050b49a6c_fld2266GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2267GP_slot2", FIELD_dsp340050b49a6c_fld2267GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2268GP_slot2", FIELD_dsp340050b49a6c_fld2268GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2269GP_slot2", FIELD_dsp340050b49a6c_fld2269GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2270GP_slot2", FIELD_dsp340050b49a6c_fld2270GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2271GP_slot2", FIELD_dsp340050b49a6c_fld2271GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2272", FIELD_dsp340050b49a6c_fld2272, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2273GP_slot2", FIELD_dsp340050b49a6c_fld2273GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2274GP_slot2", FIELD_dsp340050b49a6c_fld2274GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2275GP_slot2", FIELD_dsp340050b49a6c_fld2275GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2277GP_slot2", FIELD_dsp340050b49a6c_fld2277GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2278GP_slot2", FIELD_dsp340050b49a6c_fld2278GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2279GP_slot2", FIELD_dsp340050b49a6c_fld2279GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2280GP_slot2", FIELD_dsp340050b49a6c_fld2280GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2281GP_slot2", FIELD_dsp340050b49a6c_fld2281GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2282GP_slot2", FIELD_dsp340050b49a6c_fld2282GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2283GP_slot2", FIELD_dsp340050b49a6c_fld2283GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2284GP_slot2", FIELD_dsp340050b49a6c_fld2284GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2286GP_slot2", FIELD_dsp340050b49a6c_fld2286GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2287GP_slot2", FIELD_dsp340050b49a6c_fld2287GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2288GP_slot2", FIELD_dsp340050b49a6c_fld2288GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2289GP_slot2", FIELD_dsp340050b49a6c_fld2289GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2290GP_slot2", FIELD_dsp340050b49a6c_fld2290GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2291GP_slot2", FIELD_dsp340050b49a6c_fld2291GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2292GP_slot2", FIELD_dsp340050b49a6c_fld2292GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2293GP_slot2", FIELD_dsp340050b49a6c_fld2293GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2294GP_slot2", FIELD_dsp340050b49a6c_fld2294GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2295GP_slot2", FIELD_dsp340050b49a6c_fld2295GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2296GP_slot2", FIELD_dsp340050b49a6c_fld2296GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2297GP_slot2", FIELD_dsp340050b49a6c_fld2297GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2298GP_slot2", FIELD_dsp340050b49a6c_fld2298GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2299GP_slot2", FIELD_dsp340050b49a6c_fld2299GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2300GP_slot2", FIELD_dsp340050b49a6c_fld2300GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2301GP_slot2", FIELD_dsp340050b49a6c_fld2301GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2302", FIELD_dsp340050b49a6c_fld2302, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2303GP_slot2", FIELD_dsp340050b49a6c_fld2303GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2304GP_slot2", FIELD_dsp340050b49a6c_fld2304GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2305", FIELD_dsp340050b49a6c_fld2305, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2306GP_slot2", FIELD_dsp340050b49a6c_fld2306GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2308GP_slot2", FIELD_dsp340050b49a6c_fld2308GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2309GP_slot2", FIELD_dsp340050b49a6c_fld2309GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2310GP_slot2", FIELD_dsp340050b49a6c_fld2310GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2312GP_slot2", FIELD_dsp340050b49a6c_fld2312GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2313", FIELD_dsp340050b49a6c_fld2313, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2314GP_slot2", FIELD_dsp340050b49a6c_fld2314GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2316GP_slot2", FIELD_dsp340050b49a6c_fld2316GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2317GP_slot2", FIELD_dsp340050b49a6c_fld2317GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2318GP_slot2", FIELD_dsp340050b49a6c_fld2318GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2319GP_slot2", FIELD_dsp340050b49a6c_fld2319GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2320GP_slot2", FIELD_dsp340050b49a6c_fld2320GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2321GP_slot2", FIELD_dsp340050b49a6c_fld2321GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2322GP_slot2", FIELD_dsp340050b49a6c_fld2322GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2323GP_slot2", FIELD_dsp340050b49a6c_fld2323GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2324GP_slot2", FIELD_dsp340050b49a6c_fld2324GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2325GP_slot2", FIELD_dsp340050b49a6c_fld2325GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2326GP_slot2", FIELD_dsp340050b49a6c_fld2326GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2327GP_slot2", FIELD_dsp340050b49a6c_fld2327GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2328GP_slot2", FIELD_dsp340050b49a6c_fld2328GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2329GP_slot2", FIELD_dsp340050b49a6c_fld2329GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2330GP_slot2", FIELD_dsp340050b49a6c_fld2330GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2331GP_slot2", FIELD_dsp340050b49a6c_fld2331GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2332GP_slot2", FIELD_dsp340050b49a6c_fld2332GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2333GP_slot2", FIELD_dsp340050b49a6c_fld2333GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2334GP_slot2", FIELD_dsp340050b49a6c_fld2334GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2335GP_slot2", FIELD_dsp340050b49a6c_fld2335GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2336GP_slot2", FIELD_dsp340050b49a6c_fld2336GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2337GP_slot2", FIELD_dsp340050b49a6c_fld2337GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2338GP_slot2", FIELD_dsp340050b49a6c_fld2338GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2339GP_slot2", FIELD_dsp340050b49a6c_fld2339GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2340GP_slot2", FIELD_dsp340050b49a6c_fld2340GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2341GP_slot2", FIELD_dsp340050b49a6c_fld2341GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2342GP_slot2", FIELD_dsp340050b49a6c_fld2342GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2343GP_slot2", FIELD_dsp340050b49a6c_fld2343GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2344GP_slot2", FIELD_dsp340050b49a6c_fld2344GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2345GP_slot2", FIELD_dsp340050b49a6c_fld2345GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2346GP_slot2", FIELD_dsp340050b49a6c_fld2346GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2347GP_slot2", FIELD_dsp340050b49a6c_fld2347GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2348GP_slot2", FIELD_dsp340050b49a6c_fld2348GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2349GP_slot2", FIELD_dsp340050b49a6c_fld2349GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2350GP_slot2", FIELD_dsp340050b49a6c_fld2350GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2351GP_slot2", FIELD_dsp340050b49a6c_fld2351GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2352GP_slot2", FIELD_dsp340050b49a6c_fld2352GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2353GP_slot2", FIELD_dsp340050b49a6c_fld2353GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2354GP_slot2", FIELD_dsp340050b49a6c_fld2354GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2355GP_slot2", FIELD_dsp340050b49a6c_fld2355GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2356GP_slot2", FIELD_dsp340050b49a6c_fld2356GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2357GP_slot2", FIELD_dsp340050b49a6c_fld2357GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2358GP_slot2", FIELD_dsp340050b49a6c_fld2358GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2359GP_slot2", FIELD_dsp340050b49a6c_fld2359GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2361GP_slot2", FIELD_dsp340050b49a6c_fld2361GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2362GP_slot2", FIELD_dsp340050b49a6c_fld2362GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2364GP_slot2", FIELD_dsp340050b49a6c_fld2364GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2366GP_slot2", FIELD_dsp340050b49a6c_fld2366GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2368GP_slot2", FIELD_dsp340050b49a6c_fld2368GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2369GP_slot2", FIELD_dsp340050b49a6c_fld2369GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2370GP_slot2", FIELD_dsp340050b49a6c_fld2370GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2371GP_slot2", FIELD_dsp340050b49a6c_fld2371GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2372GP_slot2", FIELD_dsp340050b49a6c_fld2372GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2373GP_slot2", FIELD_dsp340050b49a6c_fld2373GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2374GP_slot2", FIELD_dsp340050b49a6c_fld2374GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2375GP_slot2", FIELD_dsp340050b49a6c_fld2375GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2376GP_slot2", FIELD_dsp340050b49a6c_fld2376GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2378GP_slot2", FIELD_dsp340050b49a6c_fld2378GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2379GP_slot2", FIELD_dsp340050b49a6c_fld2379GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2381GP_slot2", FIELD_dsp340050b49a6c_fld2381GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2383GP_slot2", FIELD_dsp340050b49a6c_fld2383GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2384", FIELD_dsp340050b49a6c_fld2384, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2385GP_slot2", FIELD_dsp340050b49a6c_fld2385GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2386", FIELD_dsp340050b49a6c_fld2386, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2387GP_slot2", FIELD_dsp340050b49a6c_fld2387GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2388GP_slot2", FIELD_dsp340050b49a6c_fld2388GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2389GP_slot2", FIELD_dsp340050b49a6c_fld2389GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3663GP_slot2", FIELD_dsp340050b49a6c_fld3663GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3664GP_slot2", FIELD_dsp340050b49a6c_fld3664GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3665GP_slot2", FIELD_dsp340050b49a6c_fld3665GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3666", FIELD_dsp340050b49a6c_fld3666, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3667GP_slot2", FIELD_dsp340050b49a6c_fld3667GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3668GP_slot2", FIELD_dsp340050b49a6c_fld3668GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3669GP_slot2", FIELD_dsp340050b49a6c_fld3669GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3670GP_slot2", FIELD_dsp340050b49a6c_fld3670GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3671GP_slot2", FIELD_dsp340050b49a6c_fld3671GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3673GP_slot2", FIELD_dsp340050b49a6c_fld3673GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3674GP_slot2", FIELD_dsp340050b49a6c_fld3674GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3675GP_slot2", FIELD_dsp340050b49a6c_fld3675GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3676GP_slot2", FIELD_dsp340050b49a6c_fld3676GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3678GP_slot2", FIELD_dsp340050b49a6c_fld3678GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3679GP_slot2", FIELD_dsp340050b49a6c_fld3679GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3680GP_slot2", FIELD_dsp340050b49a6c_fld3680GP_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s4", FIELD_op0_s4, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2026", FIELD_dsp340050b49a6c_fld2026, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2031", FIELD_dsp340050b49a6c_fld2031, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2394GP_slot1", FIELD_dsp340050b49a6c_fld2394GP_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2395GP_slot1", FIELD_dsp340050b49a6c_fld2395GP_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2397GP_slot1", FIELD_dsp340050b49a6c_fld2397GP_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2398GP_slot1", FIELD_dsp340050b49a6c_fld2398GP_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2399GP_slot1", FIELD_dsp340050b49a6c_fld2399GP_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2400GP_slot1", FIELD_dsp340050b49a6c_fld2400GP_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2402GP_slot1", FIELD_dsp340050b49a6c_fld2402GP_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2403GP_slot1", FIELD_dsp340050b49a6c_fld2403GP_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2405GP_slot1", FIELD_dsp340050b49a6c_fld2405GP_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3681GP_slot1", FIELD_dsp340050b49a6c_fld3681GP_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3683GP_slot1", FIELD_dsp340050b49a6c_fld3683GP_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3684GP_slot1", FIELD_dsp340050b49a6c_fld3684GP_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3686GP_slot1", FIELD_dsp340050b49a6c_fld3686GP_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s5", FIELD_op0_s5, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2058", FIELD_dsp340050b49a6c_fld2058, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2067", FIELD_dsp340050b49a6c_fld2067, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2407GP_slot0", FIELD_dsp340050b49a6c_fld2407GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2409GP_slot0", FIELD_dsp340050b49a6c_fld2409GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2410GP_slot0", FIELD_dsp340050b49a6c_fld2410GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2411GP_slot0", FIELD_dsp340050b49a6c_fld2411GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2412GP_slot0", FIELD_dsp340050b49a6c_fld2412GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2413GP_slot0", FIELD_dsp340050b49a6c_fld2413GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2415GP_slot0", FIELD_dsp340050b49a6c_fld2415GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2416GP_slot0", FIELD_dsp340050b49a6c_fld2416GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2417GP_slot0", FIELD_dsp340050b49a6c_fld2417GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2418GP_slot0", FIELD_dsp340050b49a6c_fld2418GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2419GP_slot0", FIELD_dsp340050b49a6c_fld2419GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2420GP_slot0", FIELD_dsp340050b49a6c_fld2420GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2422GP_slot0", FIELD_dsp340050b49a6c_fld2422GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2423GP_slot0", FIELD_dsp340050b49a6c_fld2423GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2424GP_slot0", FIELD_dsp340050b49a6c_fld2424GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2425GP_slot0", FIELD_dsp340050b49a6c_fld2425GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2426GP_slot0", FIELD_dsp340050b49a6c_fld2426GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2427GP_slot0", FIELD_dsp340050b49a6c_fld2427GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2429GP_slot0", FIELD_dsp340050b49a6c_fld2429GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2430GP_slot0", FIELD_dsp340050b49a6c_fld2430GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2431GP_slot0", FIELD_dsp340050b49a6c_fld2431GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2432GP_slot0", FIELD_dsp340050b49a6c_fld2432GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2433GP_slot0", FIELD_dsp340050b49a6c_fld2433GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2434GP_slot0", FIELD_dsp340050b49a6c_fld2434GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2435GP_slot0", FIELD_dsp340050b49a6c_fld2435GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2436GP_slot0", FIELD_dsp340050b49a6c_fld2436GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2437GP_slot0", FIELD_dsp340050b49a6c_fld2437GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2438GP_slot0", FIELD_dsp340050b49a6c_fld2438GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2439GP_slot0", FIELD_dsp340050b49a6c_fld2439GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2440GP_slot0", FIELD_dsp340050b49a6c_fld2440GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2441GP_slot0", FIELD_dsp340050b49a6c_fld2441GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2443GP_slot0", FIELD_dsp340050b49a6c_fld2443GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2444GP_slot0", FIELD_dsp340050b49a6c_fld2444GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2445", FIELD_dsp340050b49a6c_fld2445, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2447GP_slot0", FIELD_dsp340050b49a6c_fld2447GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2448", FIELD_dsp340050b49a6c_fld2448, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2449GP_slot0", FIELD_dsp340050b49a6c_fld2449GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2451GP_slot0", FIELD_dsp340050b49a6c_fld2451GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2452GP_slot0", FIELD_dsp340050b49a6c_fld2452GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2453GP_slot0", FIELD_dsp340050b49a6c_fld2453GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2454GP_slot0", FIELD_dsp340050b49a6c_fld2454GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2455GP_slot0", FIELD_dsp340050b49a6c_fld2455GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2456GP_slot0", FIELD_dsp340050b49a6c_fld2456GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2457GP_slot0", FIELD_dsp340050b49a6c_fld2457GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2458GP_slot0", FIELD_dsp340050b49a6c_fld2458GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2459GP_slot0", FIELD_dsp340050b49a6c_fld2459GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2460GP_slot0", FIELD_dsp340050b49a6c_fld2460GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2461GP_slot0", FIELD_dsp340050b49a6c_fld2461GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2462", FIELD_dsp340050b49a6c_fld2462, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2463GP_slot0", FIELD_dsp340050b49a6c_fld2463GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2464GP_slot0", FIELD_dsp340050b49a6c_fld2464GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2465GP_slot0", FIELD_dsp340050b49a6c_fld2465GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2466GP_slot0", FIELD_dsp340050b49a6c_fld2466GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2467GP_slot0", FIELD_dsp340050b49a6c_fld2467GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2468GP_slot0", FIELD_dsp340050b49a6c_fld2468GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2470GP_slot0", FIELD_dsp340050b49a6c_fld2470GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2471GP_slot0", FIELD_dsp340050b49a6c_fld2471GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2472GP_slot0", FIELD_dsp340050b49a6c_fld2472GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2473GP_slot0", FIELD_dsp340050b49a6c_fld2473GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2474GP_slot0", FIELD_dsp340050b49a6c_fld2474GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2475GP_slot0", FIELD_dsp340050b49a6c_fld2475GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2477GP_slot0", FIELD_dsp340050b49a6c_fld2477GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2479GP_slot0", FIELD_dsp340050b49a6c_fld2479GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2480GP_slot0", FIELD_dsp340050b49a6c_fld2480GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2481GP_slot0", FIELD_dsp340050b49a6c_fld2481GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2482GP_slot0", FIELD_dsp340050b49a6c_fld2482GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2483GP_slot0", FIELD_dsp340050b49a6c_fld2483GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2484GP_slot0", FIELD_dsp340050b49a6c_fld2484GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2485GP_slot0", FIELD_dsp340050b49a6c_fld2485GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2486GP_slot0", FIELD_dsp340050b49a6c_fld2486GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2487GP_slot0", FIELD_dsp340050b49a6c_fld2487GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2488GP_slot0", FIELD_dsp340050b49a6c_fld2488GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2489GP_slot0", FIELD_dsp340050b49a6c_fld2489GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2490GP_slot0", FIELD_dsp340050b49a6c_fld2490GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2491GP_slot0", FIELD_dsp340050b49a6c_fld2491GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2492GP_slot0", FIELD_dsp340050b49a6c_fld2492GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2493GP_slot0", FIELD_dsp340050b49a6c_fld2493GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2494GP_slot0", FIELD_dsp340050b49a6c_fld2494GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2495GP_slot0", FIELD_dsp340050b49a6c_fld2495GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2496GP_slot0", FIELD_dsp340050b49a6c_fld2496GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2497GP_slot0", FIELD_dsp340050b49a6c_fld2497GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2498GP_slot0", FIELD_dsp340050b49a6c_fld2498GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2499GP_slot0", FIELD_dsp340050b49a6c_fld2499GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2500GP_slot0", FIELD_dsp340050b49a6c_fld2500GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2501GP_slot0", FIELD_dsp340050b49a6c_fld2501GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2502GP_slot0", FIELD_dsp340050b49a6c_fld2502GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2503GP_slot0", FIELD_dsp340050b49a6c_fld2503GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2504GP_slot0", FIELD_dsp340050b49a6c_fld2504GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2505GP_slot0", FIELD_dsp340050b49a6c_fld2505GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2506GP_slot0", FIELD_dsp340050b49a6c_fld2506GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2507GP_slot0", FIELD_dsp340050b49a6c_fld2507GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2508GP_slot0", FIELD_dsp340050b49a6c_fld2508GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2509GP_slot0", FIELD_dsp340050b49a6c_fld2509GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2510GP_slot0", FIELD_dsp340050b49a6c_fld2510GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2512GP_slot0", FIELD_dsp340050b49a6c_fld2512GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2514GP_slot0", FIELD_dsp340050b49a6c_fld2514GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2515GP_slot0", FIELD_dsp340050b49a6c_fld2515GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2516GP_slot0", FIELD_dsp340050b49a6c_fld2516GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2517GP_slot0", FIELD_dsp340050b49a6c_fld2517GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2518GP_slot0", FIELD_dsp340050b49a6c_fld2518GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2519GP_slot0", FIELD_dsp340050b49a6c_fld2519GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2520GP_slot0", FIELD_dsp340050b49a6c_fld2520GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2521GP_slot0", FIELD_dsp340050b49a6c_fld2521GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2523GP_slot0", FIELD_dsp340050b49a6c_fld2523GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2524GP_slot0", FIELD_dsp340050b49a6c_fld2524GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2526GP_slot0", FIELD_dsp340050b49a6c_fld2526GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2527GP_slot0", FIELD_dsp340050b49a6c_fld2527GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2528GP_slot0", FIELD_dsp340050b49a6c_fld2528GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2529GP_slot0", FIELD_dsp340050b49a6c_fld2529GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2530", FIELD_dsp340050b49a6c_fld2530, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2531GP_slot0", FIELD_dsp340050b49a6c_fld2531GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3688GP_slot0", FIELD_dsp340050b49a6c_fld3688GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3689GP_slot0", FIELD_dsp340050b49a6c_fld3689GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3690GP_slot0", FIELD_dsp340050b49a6c_fld3690GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3691GP_slot0", FIELD_dsp340050b49a6c_fld3691GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3692GP_slot0", FIELD_dsp340050b49a6c_fld3692GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3693GP_slot0", FIELD_dsp340050b49a6c_fld3693GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3695GP_slot0", FIELD_dsp340050b49a6c_fld3695GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3696GP_slot0", FIELD_dsp340050b49a6c_fld3696GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3697GP_slot0", FIELD_dsp340050b49a6c_fld3697GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3698GP_slot0", FIELD_dsp340050b49a6c_fld3698GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3699GP_slot0", FIELD_dsp340050b49a6c_fld3699GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3700GP_slot0", FIELD_dsp340050b49a6c_fld3700GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3702GP_slot0", FIELD_dsp340050b49a6c_fld3702GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3703GP_slot0", FIELD_dsp340050b49a6c_fld3703GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3705GP_slot0", FIELD_dsp340050b49a6c_fld3705GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3706GP_slot0", FIELD_dsp340050b49a6c_fld3706GP_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s6", FIELD_op0_s6, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2532DOT_slot2", FIELD_dsp340050b49a6c_fld2532DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2533DOT_slot2", FIELD_dsp340050b49a6c_fld2533DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2534DOT_slot2", FIELD_dsp340050b49a6c_fld2534DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2535DOT_slot2", FIELD_dsp340050b49a6c_fld2535DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2536DOT_slot2", FIELD_dsp340050b49a6c_fld2536DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2537DOT_slot2", FIELD_dsp340050b49a6c_fld2537DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2538DOT_slot2", FIELD_dsp340050b49a6c_fld2538DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2539DOT_slot2", FIELD_dsp340050b49a6c_fld2539DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2540DOT_slot2", FIELD_dsp340050b49a6c_fld2540DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2541DOT_slot2", FIELD_dsp340050b49a6c_fld2541DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2542DOT_slot2", FIELD_dsp340050b49a6c_fld2542DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2543DOT_slot2", FIELD_dsp340050b49a6c_fld2543DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2544DOT_slot2", FIELD_dsp340050b49a6c_fld2544DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2545DOT_slot2", FIELD_dsp340050b49a6c_fld2545DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2546DOT_slot2", FIELD_dsp340050b49a6c_fld2546DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2547DOT_slot2", FIELD_dsp340050b49a6c_fld2547DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2548DOT_slot2", FIELD_dsp340050b49a6c_fld2548DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2549DOT_slot2", FIELD_dsp340050b49a6c_fld2549DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2550DOT_slot2", FIELD_dsp340050b49a6c_fld2550DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2551DOT_slot2", FIELD_dsp340050b49a6c_fld2551DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2552DOT_slot2", FIELD_dsp340050b49a6c_fld2552DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2553DOT_slot2", FIELD_dsp340050b49a6c_fld2553DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2554DOT_slot2", FIELD_dsp340050b49a6c_fld2554DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2555DOT_slot2", FIELD_dsp340050b49a6c_fld2555DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2556DOT_slot2", FIELD_dsp340050b49a6c_fld2556DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2557DOT_slot2", FIELD_dsp340050b49a6c_fld2557DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2558DOT_slot2", FIELD_dsp340050b49a6c_fld2558DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2559DOT_slot2", FIELD_dsp340050b49a6c_fld2559DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2560DOT_slot2", FIELD_dsp340050b49a6c_fld2560DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2561DOT_slot2", FIELD_dsp340050b49a6c_fld2561DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2562DOT_slot2", FIELD_dsp340050b49a6c_fld2562DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2563DOT_slot2", FIELD_dsp340050b49a6c_fld2563DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2564DOT_slot2", FIELD_dsp340050b49a6c_fld2564DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2565DOT_slot2", FIELD_dsp340050b49a6c_fld2565DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2566DOT_slot2", FIELD_dsp340050b49a6c_fld2566DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2567DOT_slot2", FIELD_dsp340050b49a6c_fld2567DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2568DOT_slot2", FIELD_dsp340050b49a6c_fld2568DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2569DOT_slot2", FIELD_dsp340050b49a6c_fld2569DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2571DOT_slot2", FIELD_dsp340050b49a6c_fld2571DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2572DOT_slot2", FIELD_dsp340050b49a6c_fld2572DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2573DOT_slot2", FIELD_dsp340050b49a6c_fld2573DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2574DOT_slot2", FIELD_dsp340050b49a6c_fld2574DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2575DOT_slot2", FIELD_dsp340050b49a6c_fld2575DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2576DOT_slot2", FIELD_dsp340050b49a6c_fld2576DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2577DOT_slot2", FIELD_dsp340050b49a6c_fld2577DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2578", FIELD_dsp340050b49a6c_fld2578, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2579DOT_slot2", FIELD_dsp340050b49a6c_fld2579DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2580DOT_slot2", FIELD_dsp340050b49a6c_fld2580DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2581DOT_slot2", FIELD_dsp340050b49a6c_fld2581DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2582DOT_slot2", FIELD_dsp340050b49a6c_fld2582DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2583DOT_slot2", FIELD_dsp340050b49a6c_fld2583DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2584DOT_slot2", FIELD_dsp340050b49a6c_fld2584DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2585DOT_slot2", FIELD_dsp340050b49a6c_fld2585DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2586DOT_slot2", FIELD_dsp340050b49a6c_fld2586DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2587DOT_slot2", FIELD_dsp340050b49a6c_fld2587DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2588DOT_slot2", FIELD_dsp340050b49a6c_fld2588DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2589DOT_slot2", FIELD_dsp340050b49a6c_fld2589DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2590DOT_slot2", FIELD_dsp340050b49a6c_fld2590DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2591DOT_slot2", FIELD_dsp340050b49a6c_fld2591DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2592DOT_slot2", FIELD_dsp340050b49a6c_fld2592DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2595DOT_slot2", FIELD_dsp340050b49a6c_fld2595DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2596DOT_slot2", FIELD_dsp340050b49a6c_fld2596DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2598DOT_slot2", FIELD_dsp340050b49a6c_fld2598DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2599DOT_slot2", FIELD_dsp340050b49a6c_fld2599DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2601DOT_slot2", FIELD_dsp340050b49a6c_fld2601DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2602DOT_slot2", FIELD_dsp340050b49a6c_fld2602DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2604DOT_slot2", FIELD_dsp340050b49a6c_fld2604DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2605", FIELD_dsp340050b49a6c_fld2605, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2606DOT_slot2", FIELD_dsp340050b49a6c_fld2606DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2608DOT_slot2", FIELD_dsp340050b49a6c_fld2608DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2609DOT_slot2", FIELD_dsp340050b49a6c_fld2609DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2610DOT_slot2", FIELD_dsp340050b49a6c_fld2610DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2611DOT_slot2", FIELD_dsp340050b49a6c_fld2611DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2612", FIELD_dsp340050b49a6c_fld2612, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2613DOT_slot2", FIELD_dsp340050b49a6c_fld2613DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2614", FIELD_dsp340050b49a6c_fld2614, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2615DOT_slot2", FIELD_dsp340050b49a6c_fld2615DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2616DOT_slot2", FIELD_dsp340050b49a6c_fld2616DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2617DOT_slot2", FIELD_dsp340050b49a6c_fld2617DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2618DOT_slot2", FIELD_dsp340050b49a6c_fld2618DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2619DOT_slot2", FIELD_dsp340050b49a6c_fld2619DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2620DOT_slot2", FIELD_dsp340050b49a6c_fld2620DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2621DOT_slot2", FIELD_dsp340050b49a6c_fld2621DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2622DOT_slot2", FIELD_dsp340050b49a6c_fld2622DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2623DOT_slot2", FIELD_dsp340050b49a6c_fld2623DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2624DOT_slot2", FIELD_dsp340050b49a6c_fld2624DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2625", FIELD_dsp340050b49a6c_fld2625, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2626DOT_slot2", FIELD_dsp340050b49a6c_fld2626DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2628DOT_slot2", FIELD_dsp340050b49a6c_fld2628DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2630DOT_slot2", FIELD_dsp340050b49a6c_fld2630DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2632DOT_slot2", FIELD_dsp340050b49a6c_fld2632DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2633DOT_slot2", FIELD_dsp340050b49a6c_fld2633DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2635DOT_slot2", FIELD_dsp340050b49a6c_fld2635DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2636DOT_slot2", FIELD_dsp340050b49a6c_fld2636DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2637DOT_slot2", FIELD_dsp340050b49a6c_fld2637DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2640DOT_slot2", FIELD_dsp340050b49a6c_fld2640DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2641DOT_slot2", FIELD_dsp340050b49a6c_fld2641DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2642DOT_slot2", FIELD_dsp340050b49a6c_fld2642DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2643DOT_slot2", FIELD_dsp340050b49a6c_fld2643DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2644DOT_slot2", FIELD_dsp340050b49a6c_fld2644DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2645DOT_slot2", FIELD_dsp340050b49a6c_fld2645DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2646DOT_slot2", FIELD_dsp340050b49a6c_fld2646DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2647DOT_slot2", FIELD_dsp340050b49a6c_fld2647DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2648DOT_slot2", FIELD_dsp340050b49a6c_fld2648DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2649DOT_slot2", FIELD_dsp340050b49a6c_fld2649DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2650DOT_slot2", FIELD_dsp340050b49a6c_fld2650DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2651DOT_slot2", FIELD_dsp340050b49a6c_fld2651DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2652DOT_slot2", FIELD_dsp340050b49a6c_fld2652DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2654DOT_slot2", FIELD_dsp340050b49a6c_fld2654DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2655DOT_slot2", FIELD_dsp340050b49a6c_fld2655DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2656DOT_slot2", FIELD_dsp340050b49a6c_fld2656DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2657DOT_slot2", FIELD_dsp340050b49a6c_fld2657DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2658DOT_slot2", FIELD_dsp340050b49a6c_fld2658DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3708DOT_slot2", FIELD_dsp340050b49a6c_fld3708DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3709DOT_slot2", FIELD_dsp340050b49a6c_fld3709DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3710DOT_slot2", FIELD_dsp340050b49a6c_fld3710DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3711DOT_slot2", FIELD_dsp340050b49a6c_fld3711DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3712", FIELD_dsp340050b49a6c_fld3712, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3713DOT_slot2", FIELD_dsp340050b49a6c_fld3713DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3714DOT_slot2", FIELD_dsp340050b49a6c_fld3714DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3715", FIELD_dsp340050b49a6c_fld3715, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3716DOT_slot2", FIELD_dsp340050b49a6c_fld3716DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3717DOT_slot2", FIELD_dsp340050b49a6c_fld3717DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3718", FIELD_dsp340050b49a6c_fld3718, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3719DOT_slot2", FIELD_dsp340050b49a6c_fld3719DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3721DOT_slot2", FIELD_dsp340050b49a6c_fld3721DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3722", FIELD_dsp340050b49a6c_fld3722, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3723DOT_slot2", FIELD_dsp340050b49a6c_fld3723DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3724DOT_slot2", FIELD_dsp340050b49a6c_fld3724DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3725DOT_slot2", FIELD_dsp340050b49a6c_fld3725DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3726DOT_slot2", FIELD_dsp340050b49a6c_fld3726DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3727DOT_slot2", FIELD_dsp340050b49a6c_fld3727DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3728DOT_slot2", FIELD_dsp340050b49a6c_fld3728DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3729DOT_slot2", FIELD_dsp340050b49a6c_fld3729DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3731DOT_slot2", FIELD_dsp340050b49a6c_fld3731DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3732DOT_slot2", FIELD_dsp340050b49a6c_fld3732DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3733DOT_slot2", FIELD_dsp340050b49a6c_fld3733DOT_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s7", FIELD_op0_s7, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3734DOT_slot1", FIELD_dsp340050b49a6c_fld3734DOT_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s8", FIELD_op0_s8, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2068", FIELD_dsp340050b49a6c_fld2068, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2666DOT_slot0", FIELD_dsp340050b49a6c_fld2666DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2667DOT_slot0", FIELD_dsp340050b49a6c_fld2667DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2668DOT_slot0", FIELD_dsp340050b49a6c_fld2668DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2669DOT_slot0", FIELD_dsp340050b49a6c_fld2669DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2671DOT_slot0", FIELD_dsp340050b49a6c_fld2671DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2672DOT_slot0", FIELD_dsp340050b49a6c_fld2672DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2673DOT_slot0", FIELD_dsp340050b49a6c_fld2673DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2674DOT_slot0", FIELD_dsp340050b49a6c_fld2674DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2675DOT_slot0", FIELD_dsp340050b49a6c_fld2675DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2676DOT_slot0", FIELD_dsp340050b49a6c_fld2676DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2677DOT_slot0", FIELD_dsp340050b49a6c_fld2677DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2678DOT_slot0", FIELD_dsp340050b49a6c_fld2678DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2679DOT_slot0", FIELD_dsp340050b49a6c_fld2679DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2680DOT_slot0", FIELD_dsp340050b49a6c_fld2680DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2681DOT_slot0", FIELD_dsp340050b49a6c_fld2681DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2682DOT_slot0", FIELD_dsp340050b49a6c_fld2682DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2683DOT_slot0", FIELD_dsp340050b49a6c_fld2683DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2684DOT_slot0", FIELD_dsp340050b49a6c_fld2684DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2685DOT_slot0", FIELD_dsp340050b49a6c_fld2685DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2686DOT_slot0", FIELD_dsp340050b49a6c_fld2686DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2688DOT_slot0", FIELD_dsp340050b49a6c_fld2688DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2689DOT_slot0", FIELD_dsp340050b49a6c_fld2689DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2690DOT_slot0", FIELD_dsp340050b49a6c_fld2690DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2692DOT_slot0", FIELD_dsp340050b49a6c_fld2692DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2693DOT_slot0", FIELD_dsp340050b49a6c_fld2693DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2695DOT_slot0", FIELD_dsp340050b49a6c_fld2695DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2697DOT_slot0", FIELD_dsp340050b49a6c_fld2697DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2699DOT_slot0", FIELD_dsp340050b49a6c_fld2699DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2700DOT_slot0", FIELD_dsp340050b49a6c_fld2700DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2701DOT_slot0", FIELD_dsp340050b49a6c_fld2701DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2702DOT_slot0", FIELD_dsp340050b49a6c_fld2702DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2703DOT_slot0", FIELD_dsp340050b49a6c_fld2703DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2704DOT_slot0", FIELD_dsp340050b49a6c_fld2704DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2705DOT_slot0", FIELD_dsp340050b49a6c_fld2705DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3735DOT_slot0", FIELD_dsp340050b49a6c_fld3735DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3736", FIELD_dsp340050b49a6c_fld3736, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3737DOT_slot0", FIELD_dsp340050b49a6c_fld3737DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3738DOT_slot0", FIELD_dsp340050b49a6c_fld3738DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3739DOT_slot0", FIELD_dsp340050b49a6c_fld3739DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3740DOT_slot0", FIELD_dsp340050b49a6c_fld3740DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3741DOT_slot0", FIELD_dsp340050b49a6c_fld3741DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3742DOT_slot0", FIELD_dsp340050b49a6c_fld3742DOT_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s9", FIELD_op0_s9, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2706PQ_slot2", FIELD_dsp340050b49a6c_fld2706PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2707PQ_slot2", FIELD_dsp340050b49a6c_fld2707PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2708PQ_slot2", FIELD_dsp340050b49a6c_fld2708PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2709PQ_slot2", FIELD_dsp340050b49a6c_fld2709PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2710PQ_slot2", FIELD_dsp340050b49a6c_fld2710PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2711PQ_slot2", FIELD_dsp340050b49a6c_fld2711PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2713PQ_slot2", FIELD_dsp340050b49a6c_fld2713PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2714PQ_slot2", FIELD_dsp340050b49a6c_fld2714PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2715PQ_slot2", FIELD_dsp340050b49a6c_fld2715PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2717PQ_slot2", FIELD_dsp340050b49a6c_fld2717PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2718PQ_slot2", FIELD_dsp340050b49a6c_fld2718PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2719PQ_slot2", FIELD_dsp340050b49a6c_fld2719PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2721PQ_slot2", FIELD_dsp340050b49a6c_fld2721PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2722PQ_slot2", FIELD_dsp340050b49a6c_fld2722PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2723PQ_slot2", FIELD_dsp340050b49a6c_fld2723PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2724PQ_slot2", FIELD_dsp340050b49a6c_fld2724PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2725PQ_slot2", FIELD_dsp340050b49a6c_fld2725PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2726PQ_slot2", FIELD_dsp340050b49a6c_fld2726PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2727PQ_slot2", FIELD_dsp340050b49a6c_fld2727PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2728PQ_slot2", FIELD_dsp340050b49a6c_fld2728PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2729PQ_slot2", FIELD_dsp340050b49a6c_fld2729PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2730PQ_slot2", FIELD_dsp340050b49a6c_fld2730PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2731PQ_slot2", FIELD_dsp340050b49a6c_fld2731PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2732PQ_slot2", FIELD_dsp340050b49a6c_fld2732PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2733PQ_slot2", FIELD_dsp340050b49a6c_fld2733PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2734PQ_slot2", FIELD_dsp340050b49a6c_fld2734PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2735PQ_slot2", FIELD_dsp340050b49a6c_fld2735PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2736PQ_slot2", FIELD_dsp340050b49a6c_fld2736PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2737", FIELD_dsp340050b49a6c_fld2737, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2738PQ_slot2", FIELD_dsp340050b49a6c_fld2738PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2739PQ_slot2", FIELD_dsp340050b49a6c_fld2739PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2741PQ_slot2", FIELD_dsp340050b49a6c_fld2741PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2742PQ_slot2", FIELD_dsp340050b49a6c_fld2742PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2743PQ_slot2", FIELD_dsp340050b49a6c_fld2743PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2746PQ_slot2", FIELD_dsp340050b49a6c_fld2746PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2747PQ_slot2", FIELD_dsp340050b49a6c_fld2747PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2748PQ_slot2", FIELD_dsp340050b49a6c_fld2748PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2750PQ_slot2", FIELD_dsp340050b49a6c_fld2750PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2751PQ_slot2", FIELD_dsp340050b49a6c_fld2751PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2752PQ_slot2", FIELD_dsp340050b49a6c_fld2752PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2753PQ_slot2", FIELD_dsp340050b49a6c_fld2753PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2754PQ_slot2", FIELD_dsp340050b49a6c_fld2754PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2755PQ_slot2", FIELD_dsp340050b49a6c_fld2755PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2756PQ_slot2", FIELD_dsp340050b49a6c_fld2756PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2757PQ_slot2", FIELD_dsp340050b49a6c_fld2757PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2758PQ_slot2", FIELD_dsp340050b49a6c_fld2758PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2759PQ_slot2", FIELD_dsp340050b49a6c_fld2759PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2760PQ_slot2", FIELD_dsp340050b49a6c_fld2760PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2761PQ_slot2", FIELD_dsp340050b49a6c_fld2761PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2762PQ_slot2", FIELD_dsp340050b49a6c_fld2762PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2763PQ_slot2", FIELD_dsp340050b49a6c_fld2763PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2764PQ_slot2", FIELD_dsp340050b49a6c_fld2764PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2765PQ_slot2", FIELD_dsp340050b49a6c_fld2765PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2766PQ_slot2", FIELD_dsp340050b49a6c_fld2766PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2767PQ_slot2", FIELD_dsp340050b49a6c_fld2767PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2768PQ_slot2", FIELD_dsp340050b49a6c_fld2768PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2769PQ_slot2", FIELD_dsp340050b49a6c_fld2769PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2770PQ_slot2", FIELD_dsp340050b49a6c_fld2770PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2771PQ_slot2", FIELD_dsp340050b49a6c_fld2771PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2772PQ_slot2", FIELD_dsp340050b49a6c_fld2772PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2773PQ_slot2", FIELD_dsp340050b49a6c_fld2773PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2774PQ_slot2", FIELD_dsp340050b49a6c_fld2774PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2775PQ_slot2", FIELD_dsp340050b49a6c_fld2775PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2776PQ_slot2", FIELD_dsp340050b49a6c_fld2776PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2777PQ_slot2", FIELD_dsp340050b49a6c_fld2777PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2778PQ_slot2", FIELD_dsp340050b49a6c_fld2778PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2779PQ_slot2", FIELD_dsp340050b49a6c_fld2779PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2780PQ_slot2", FIELD_dsp340050b49a6c_fld2780PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2781PQ_slot2", FIELD_dsp340050b49a6c_fld2781PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2782PQ_slot2", FIELD_dsp340050b49a6c_fld2782PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2783PQ_slot2", FIELD_dsp340050b49a6c_fld2783PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2784PQ_slot2", FIELD_dsp340050b49a6c_fld2784PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2785PQ_slot2", FIELD_dsp340050b49a6c_fld2785PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2786PQ_slot2", FIELD_dsp340050b49a6c_fld2786PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2787PQ_slot2", FIELD_dsp340050b49a6c_fld2787PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2788PQ_slot2", FIELD_dsp340050b49a6c_fld2788PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2789PQ_slot2", FIELD_dsp340050b49a6c_fld2789PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2790PQ_slot2", FIELD_dsp340050b49a6c_fld2790PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2791PQ_slot2", FIELD_dsp340050b49a6c_fld2791PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2792PQ_slot2", FIELD_dsp340050b49a6c_fld2792PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2793PQ_slot2", FIELD_dsp340050b49a6c_fld2793PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2795PQ_slot2", FIELD_dsp340050b49a6c_fld2795PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2796PQ_slot2", FIELD_dsp340050b49a6c_fld2796PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2798PQ_slot2", FIELD_dsp340050b49a6c_fld2798PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2801PQ_slot2", FIELD_dsp340050b49a6c_fld2801PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2803PQ_slot2", FIELD_dsp340050b49a6c_fld2803PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2805PQ_slot2", FIELD_dsp340050b49a6c_fld2805PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2806PQ_slot2", FIELD_dsp340050b49a6c_fld2806PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2807PQ_slot2", FIELD_dsp340050b49a6c_fld2807PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2808PQ_slot2", FIELD_dsp340050b49a6c_fld2808PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2809PQ_slot2", FIELD_dsp340050b49a6c_fld2809PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2810PQ_slot2", FIELD_dsp340050b49a6c_fld2810PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2811PQ_slot2", FIELD_dsp340050b49a6c_fld2811PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2812PQ_slot2", FIELD_dsp340050b49a6c_fld2812PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2814PQ_slot2", FIELD_dsp340050b49a6c_fld2814PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2816PQ_slot2", FIELD_dsp340050b49a6c_fld2816PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2817", FIELD_dsp340050b49a6c_fld2817, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2818PQ_slot2", FIELD_dsp340050b49a6c_fld2818PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2819", FIELD_dsp340050b49a6c_fld2819, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2820PQ_slot2", FIELD_dsp340050b49a6c_fld2820PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2821PQ_slot2", FIELD_dsp340050b49a6c_fld2821PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2823PQ_slot2", FIELD_dsp340050b49a6c_fld2823PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3744PQ_slot2", FIELD_dsp340050b49a6c_fld3744PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3745PQ_slot2", FIELD_dsp340050b49a6c_fld3745PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3746PQ_slot2", FIELD_dsp340050b49a6c_fld3746PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3747PQ_slot2", FIELD_dsp340050b49a6c_fld3747PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3748", FIELD_dsp340050b49a6c_fld3748, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3749PQ_slot2", FIELD_dsp340050b49a6c_fld3749PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3750PQ_slot2", FIELD_dsp340050b49a6c_fld3750PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3751PQ_slot2", FIELD_dsp340050b49a6c_fld3751PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3752PQ_slot2", FIELD_dsp340050b49a6c_fld3752PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3753PQ_slot2", FIELD_dsp340050b49a6c_fld3753PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3754PQ_slot2", FIELD_dsp340050b49a6c_fld3754PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3756PQ_slot2", FIELD_dsp340050b49a6c_fld3756PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3757PQ_slot2", FIELD_dsp340050b49a6c_fld3757PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3758PQ_slot2", FIELD_dsp340050b49a6c_fld3758PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3759PQ_slot2", FIELD_dsp340050b49a6c_fld3759PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3760PQ_slot2", FIELD_dsp340050b49a6c_fld3760PQ_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s10", FIELD_op0_s10, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2825PQ_slot1", FIELD_dsp340050b49a6c_fld2825PQ_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2826PQ_slot1", FIELD_dsp340050b49a6c_fld2826PQ_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3761PQ_slot1", FIELD_dsp340050b49a6c_fld3761PQ_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s11", FIELD_op0_s11, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2059", FIELD_dsp340050b49a6c_fld2059, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2069", FIELD_dsp340050b49a6c_fld2069, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2827PQ_slot0", FIELD_dsp340050b49a6c_fld2827PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2829PQ_slot0", FIELD_dsp340050b49a6c_fld2829PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2830PQ_slot0", FIELD_dsp340050b49a6c_fld2830PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2831PQ_slot0", FIELD_dsp340050b49a6c_fld2831PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2832PQ_slot0", FIELD_dsp340050b49a6c_fld2832PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2833PQ_slot0", FIELD_dsp340050b49a6c_fld2833PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2835PQ_slot0", FIELD_dsp340050b49a6c_fld2835PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2836PQ_slot0", FIELD_dsp340050b49a6c_fld2836PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2837PQ_slot0", FIELD_dsp340050b49a6c_fld2837PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2838PQ_slot0", FIELD_dsp340050b49a6c_fld2838PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2839PQ_slot0", FIELD_dsp340050b49a6c_fld2839PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2840PQ_slot0", FIELD_dsp340050b49a6c_fld2840PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2842PQ_slot0", FIELD_dsp340050b49a6c_fld2842PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2843PQ_slot0", FIELD_dsp340050b49a6c_fld2843PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2844PQ_slot0", FIELD_dsp340050b49a6c_fld2844PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2845PQ_slot0", FIELD_dsp340050b49a6c_fld2845PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2846PQ_slot0", FIELD_dsp340050b49a6c_fld2846PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2847PQ_slot0", FIELD_dsp340050b49a6c_fld2847PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2849PQ_slot0", FIELD_dsp340050b49a6c_fld2849PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2850PQ_slot0", FIELD_dsp340050b49a6c_fld2850PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2851PQ_slot0", FIELD_dsp340050b49a6c_fld2851PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2852PQ_slot0", FIELD_dsp340050b49a6c_fld2852PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2853PQ_slot0", FIELD_dsp340050b49a6c_fld2853PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2854PQ_slot0", FIELD_dsp340050b49a6c_fld2854PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2855PQ_slot0", FIELD_dsp340050b49a6c_fld2855PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2856PQ_slot0", FIELD_dsp340050b49a6c_fld2856PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2857PQ_slot0", FIELD_dsp340050b49a6c_fld2857PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2858PQ_slot0", FIELD_dsp340050b49a6c_fld2858PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2859PQ_slot0", FIELD_dsp340050b49a6c_fld2859PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2860PQ_slot0", FIELD_dsp340050b49a6c_fld2860PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2861PQ_slot0", FIELD_dsp340050b49a6c_fld2861PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2863PQ_slot0", FIELD_dsp340050b49a6c_fld2863PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2864PQ_slot0", FIELD_dsp340050b49a6c_fld2864PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2865", FIELD_dsp340050b49a6c_fld2865, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2867PQ_slot0", FIELD_dsp340050b49a6c_fld2867PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2869PQ_slot0", FIELD_dsp340050b49a6c_fld2869PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2871PQ_slot0", FIELD_dsp340050b49a6c_fld2871PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2872PQ_slot0", FIELD_dsp340050b49a6c_fld2872PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2873PQ_slot0", FIELD_dsp340050b49a6c_fld2873PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2874PQ_slot0", FIELD_dsp340050b49a6c_fld2874PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2875PQ_slot0", FIELD_dsp340050b49a6c_fld2875PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2876PQ_slot0", FIELD_dsp340050b49a6c_fld2876PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2877PQ_slot0", FIELD_dsp340050b49a6c_fld2877PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2878PQ_slot0", FIELD_dsp340050b49a6c_fld2878PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2879PQ_slot0", FIELD_dsp340050b49a6c_fld2879PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2880PQ_slot0", FIELD_dsp340050b49a6c_fld2880PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2881PQ_slot0", FIELD_dsp340050b49a6c_fld2881PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2882", FIELD_dsp340050b49a6c_fld2882, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2883PQ_slot0", FIELD_dsp340050b49a6c_fld2883PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2884PQ_slot0", FIELD_dsp340050b49a6c_fld2884PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2885PQ_slot0", FIELD_dsp340050b49a6c_fld2885PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2886PQ_slot0", FIELD_dsp340050b49a6c_fld2886PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2887PQ_slot0", FIELD_dsp340050b49a6c_fld2887PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2888PQ_slot0", FIELD_dsp340050b49a6c_fld2888PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2890PQ_slot0", FIELD_dsp340050b49a6c_fld2890PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2891PQ_slot0", FIELD_dsp340050b49a6c_fld2891PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2892PQ_slot0", FIELD_dsp340050b49a6c_fld2892PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2893PQ_slot0", FIELD_dsp340050b49a6c_fld2893PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2894PQ_slot0", FIELD_dsp340050b49a6c_fld2894PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2895PQ_slot0", FIELD_dsp340050b49a6c_fld2895PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2897PQ_slot0", FIELD_dsp340050b49a6c_fld2897PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2899PQ_slot0", FIELD_dsp340050b49a6c_fld2899PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2900PQ_slot0", FIELD_dsp340050b49a6c_fld2900PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2901PQ_slot0", FIELD_dsp340050b49a6c_fld2901PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2902PQ_slot0", FIELD_dsp340050b49a6c_fld2902PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2903PQ_slot0", FIELD_dsp340050b49a6c_fld2903PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2904PQ_slot0", FIELD_dsp340050b49a6c_fld2904PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2905PQ_slot0", FIELD_dsp340050b49a6c_fld2905PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2906PQ_slot0", FIELD_dsp340050b49a6c_fld2906PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2907PQ_slot0", FIELD_dsp340050b49a6c_fld2907PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2908PQ_slot0", FIELD_dsp340050b49a6c_fld2908PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2909PQ_slot0", FIELD_dsp340050b49a6c_fld2909PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2910PQ_slot0", FIELD_dsp340050b49a6c_fld2910PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2911PQ_slot0", FIELD_dsp340050b49a6c_fld2911PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2912PQ_slot0", FIELD_dsp340050b49a6c_fld2912PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2913PQ_slot0", FIELD_dsp340050b49a6c_fld2913PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2914PQ_slot0", FIELD_dsp340050b49a6c_fld2914PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2915PQ_slot0", FIELD_dsp340050b49a6c_fld2915PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2916PQ_slot0", FIELD_dsp340050b49a6c_fld2916PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2917PQ_slot0", FIELD_dsp340050b49a6c_fld2917PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2918PQ_slot0", FIELD_dsp340050b49a6c_fld2918PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2919PQ_slot0", FIELD_dsp340050b49a6c_fld2919PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2920PQ_slot0", FIELD_dsp340050b49a6c_fld2920PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2921PQ_slot0", FIELD_dsp340050b49a6c_fld2921PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2922PQ_slot0", FIELD_dsp340050b49a6c_fld2922PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2923PQ_slot0", FIELD_dsp340050b49a6c_fld2923PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2924PQ_slot0", FIELD_dsp340050b49a6c_fld2924PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2925PQ_slot0", FIELD_dsp340050b49a6c_fld2925PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2926PQ_slot0", FIELD_dsp340050b49a6c_fld2926PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2927PQ_slot0", FIELD_dsp340050b49a6c_fld2927PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2928PQ_slot0", FIELD_dsp340050b49a6c_fld2928PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2929PQ_slot0", FIELD_dsp340050b49a6c_fld2929PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2930PQ_slot0", FIELD_dsp340050b49a6c_fld2930PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2932PQ_slot0", FIELD_dsp340050b49a6c_fld2932PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2934PQ_slot0", FIELD_dsp340050b49a6c_fld2934PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2935PQ_slot0", FIELD_dsp340050b49a6c_fld2935PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2936PQ_slot0", FIELD_dsp340050b49a6c_fld2936PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2937PQ_slot0", FIELD_dsp340050b49a6c_fld2937PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2939PQ_slot0", FIELD_dsp340050b49a6c_fld2939PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2940", FIELD_dsp340050b49a6c_fld2940, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2941PQ_slot0", FIELD_dsp340050b49a6c_fld2941PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2942PQ_slot0", FIELD_dsp340050b49a6c_fld2942PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2943PQ_slot0", FIELD_dsp340050b49a6c_fld2943PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2945PQ_slot0", FIELD_dsp340050b49a6c_fld2945PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2946PQ_slot0", FIELD_dsp340050b49a6c_fld2946PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2947PQ_slot0", FIELD_dsp340050b49a6c_fld2947PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2948PQ_slot0", FIELD_dsp340050b49a6c_fld2948PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2949PQ_slot0", FIELD_dsp340050b49a6c_fld2949PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2950PQ_slot0", FIELD_dsp340050b49a6c_fld2950PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3763PQ_slot0", FIELD_dsp340050b49a6c_fld3763PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3764PQ_slot0", FIELD_dsp340050b49a6c_fld3764PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3765PQ_slot0", FIELD_dsp340050b49a6c_fld3765PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3766PQ_slot0", FIELD_dsp340050b49a6c_fld3766PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3767PQ_slot0", FIELD_dsp340050b49a6c_fld3767PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3768PQ_slot0", FIELD_dsp340050b49a6c_fld3768PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3769PQ_slot0", FIELD_dsp340050b49a6c_fld3769PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3770PQ_slot0", FIELD_dsp340050b49a6c_fld3770PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3771PQ_slot0", FIELD_dsp340050b49a6c_fld3771PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3772", FIELD_dsp340050b49a6c_fld3772, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3773PQ_slot0", FIELD_dsp340050b49a6c_fld3773PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3775PQ_slot0", FIELD_dsp340050b49a6c_fld3775PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3776PQ_slot0", FIELD_dsp340050b49a6c_fld3776PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3777PQ_slot0", FIELD_dsp340050b49a6c_fld3777PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3778PQ_slot0", FIELD_dsp340050b49a6c_fld3778PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3779PQ_slot0", FIELD_dsp340050b49a6c_fld3779PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3780PQ_slot0", FIELD_dsp340050b49a6c_fld3780PQ_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s12", FIELD_op0_s12, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2953ACC2_slot2", FIELD_dsp340050b49a6c_fld2953ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2954ACC2_slot2", FIELD_dsp340050b49a6c_fld2954ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2955ACC2_slot2", FIELD_dsp340050b49a6c_fld2955ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2956ACC2_slot2", FIELD_dsp340050b49a6c_fld2956ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2957ACC2_slot2", FIELD_dsp340050b49a6c_fld2957ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2958ACC2_slot2", FIELD_dsp340050b49a6c_fld2958ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2959ACC2_slot2", FIELD_dsp340050b49a6c_fld2959ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2960ACC2_slot2", FIELD_dsp340050b49a6c_fld2960ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2963ACC2_slot2", FIELD_dsp340050b49a6c_fld2963ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2964ACC2_slot2", FIELD_dsp340050b49a6c_fld2964ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2966ACC2_slot2", FIELD_dsp340050b49a6c_fld2966ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2967ACC2_slot2", FIELD_dsp340050b49a6c_fld2967ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3782ACC2_slot2", FIELD_dsp340050b49a6c_fld3782ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3783ACC2_slot2", FIELD_dsp340050b49a6c_fld3783ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3784ACC2_slot2", FIELD_dsp340050b49a6c_fld3784ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3785ACC2_slot2", FIELD_dsp340050b49a6c_fld3785ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3786ACC2_slot2", FIELD_dsp340050b49a6c_fld3786ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3788ACC2_slot2", FIELD_dsp340050b49a6c_fld3788ACC2_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s13", FIELD_op0_s13, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2028", FIELD_dsp340050b49a6c_fld2028, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2075", FIELD_dsp340050b49a6c_fld2075, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2968ACC2_slot1", FIELD_dsp340050b49a6c_fld2968ACC2_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2969ACC2_slot1", FIELD_dsp340050b49a6c_fld2969ACC2_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3790ACC2_slot1", FIELD_dsp340050b49a6c_fld3790ACC2_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3793ACC2_slot1", FIELD_dsp340050b49a6c_fld3793ACC2_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s14", FIELD_op0_s14, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2973ACC2_slot0", FIELD_dsp340050b49a6c_fld2973ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2974ACC2_slot0", FIELD_dsp340050b49a6c_fld2974ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2975ACC2_slot0", FIELD_dsp340050b49a6c_fld2975ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2976ACC2_slot0", FIELD_dsp340050b49a6c_fld2976ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2977ACC2_slot0", FIELD_dsp340050b49a6c_fld2977ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2980ACC2_slot0", FIELD_dsp340050b49a6c_fld2980ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2981ACC2_slot0", FIELD_dsp340050b49a6c_fld2981ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2982ACC2_slot0", FIELD_dsp340050b49a6c_fld2982ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2984ACC2_slot0", FIELD_dsp340050b49a6c_fld2984ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2985ACC2_slot0", FIELD_dsp340050b49a6c_fld2985ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2987ACC2_slot0", FIELD_dsp340050b49a6c_fld2987ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2989ACC2_slot0", FIELD_dsp340050b49a6c_fld2989ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2990ACC2_slot0", FIELD_dsp340050b49a6c_fld2990ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3795ACC2_slot0", FIELD_dsp340050b49a6c_fld3795ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3796ACC2_slot0", FIELD_dsp340050b49a6c_fld3796ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3797", FIELD_dsp340050b49a6c_fld3797, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3798ACC2_slot0", FIELD_dsp340050b49a6c_fld3798ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3799ACC2_slot0", FIELD_dsp340050b49a6c_fld3799ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3800ACC2_slot0", FIELD_dsp340050b49a6c_fld3800ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3801ACC2_slot0", FIELD_dsp340050b49a6c_fld3801ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3802ACC2_slot0", FIELD_dsp340050b49a6c_fld3802ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3803ACC2_slot0", FIELD_dsp340050b49a6c_fld3803ACC2_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s15", FIELD_op0_s15, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2991SMOD_slot2", FIELD_dsp340050b49a6c_fld2991SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2992SMOD_slot2", FIELD_dsp340050b49a6c_fld2992SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2993SMOD_slot2", FIELD_dsp340050b49a6c_fld2993SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2994SMOD_slot2", FIELD_dsp340050b49a6c_fld2994SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2995SMOD_slot2", FIELD_dsp340050b49a6c_fld2995SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2996SMOD_slot2", FIELD_dsp340050b49a6c_fld2996SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2997SMOD_slot2", FIELD_dsp340050b49a6c_fld2997SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2998SMOD_slot2", FIELD_dsp340050b49a6c_fld2998SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2999SMOD_slot2", FIELD_dsp340050b49a6c_fld2999SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3000SMOD_slot2", FIELD_dsp340050b49a6c_fld3000SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3001SMOD_slot2", FIELD_dsp340050b49a6c_fld3001SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3002SMOD_slot2", FIELD_dsp340050b49a6c_fld3002SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3003SMOD_slot2", FIELD_dsp340050b49a6c_fld3003SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3004SMOD_slot2", FIELD_dsp340050b49a6c_fld3004SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3005SMOD_slot2", FIELD_dsp340050b49a6c_fld3005SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3006SMOD_slot2", FIELD_dsp340050b49a6c_fld3006SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3007SMOD_slot2", FIELD_dsp340050b49a6c_fld3007SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3008SMOD_slot2", FIELD_dsp340050b49a6c_fld3008SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3009SMOD_slot2", FIELD_dsp340050b49a6c_fld3009SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3010SMOD_slot2", FIELD_dsp340050b49a6c_fld3010SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3011SMOD_slot2", FIELD_dsp340050b49a6c_fld3011SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3012SMOD_slot2", FIELD_dsp340050b49a6c_fld3012SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3013SMOD_slot2", FIELD_dsp340050b49a6c_fld3013SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3014SMOD_slot2", FIELD_dsp340050b49a6c_fld3014SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3015SMOD_slot2", FIELD_dsp340050b49a6c_fld3015SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3016SMOD_slot2", FIELD_dsp340050b49a6c_fld3016SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3017SMOD_slot2", FIELD_dsp340050b49a6c_fld3017SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3018SMOD_slot2", FIELD_dsp340050b49a6c_fld3018SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3019SMOD_slot2", FIELD_dsp340050b49a6c_fld3019SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3020SMOD_slot2", FIELD_dsp340050b49a6c_fld3020SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3021SMOD_slot2", FIELD_dsp340050b49a6c_fld3021SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3022SMOD_slot2", FIELD_dsp340050b49a6c_fld3022SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3023SMOD_slot2", FIELD_dsp340050b49a6c_fld3023SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3024SMOD_slot2", FIELD_dsp340050b49a6c_fld3024SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3025SMOD_slot2", FIELD_dsp340050b49a6c_fld3025SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3026SMOD_slot2", FIELD_dsp340050b49a6c_fld3026SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3027SMOD_slot2", FIELD_dsp340050b49a6c_fld3027SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3028SMOD_slot2", FIELD_dsp340050b49a6c_fld3028SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3030SMOD_slot2", FIELD_dsp340050b49a6c_fld3030SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3031SMOD_slot2", FIELD_dsp340050b49a6c_fld3031SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3032SMOD_slot2", FIELD_dsp340050b49a6c_fld3032SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3033SMOD_slot2", FIELD_dsp340050b49a6c_fld3033SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3034SMOD_slot2", FIELD_dsp340050b49a6c_fld3034SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3035SMOD_slot2", FIELD_dsp340050b49a6c_fld3035SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3036SMOD_slot2", FIELD_dsp340050b49a6c_fld3036SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3038SMOD_slot2", FIELD_dsp340050b49a6c_fld3038SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3039SMOD_slot2", FIELD_dsp340050b49a6c_fld3039SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3040SMOD_slot2", FIELD_dsp340050b49a6c_fld3040SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3043SMOD_slot2", FIELD_dsp340050b49a6c_fld3043SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3044SMOD_slot2", FIELD_dsp340050b49a6c_fld3044SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3046SMOD_slot2", FIELD_dsp340050b49a6c_fld3046SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3047SMOD_slot2", FIELD_dsp340050b49a6c_fld3047SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3048", FIELD_dsp340050b49a6c_fld3048, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3049SMOD_slot2", FIELD_dsp340050b49a6c_fld3049SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3050SMOD_slot2", FIELD_dsp340050b49a6c_fld3050SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3051SMOD_slot2", FIELD_dsp340050b49a6c_fld3051SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3052SMOD_slot2", FIELD_dsp340050b49a6c_fld3052SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3053SMOD_slot2", FIELD_dsp340050b49a6c_fld3053SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3054SMOD_slot2", FIELD_dsp340050b49a6c_fld3054SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3055SMOD_slot2", FIELD_dsp340050b49a6c_fld3055SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3056SMOD_slot2", FIELD_dsp340050b49a6c_fld3056SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3058SMOD_slot2", FIELD_dsp340050b49a6c_fld3058SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3059SMOD_slot2", FIELD_dsp340050b49a6c_fld3059SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3061SMOD_slot2", FIELD_dsp340050b49a6c_fld3061SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3062", FIELD_dsp340050b49a6c_fld3062, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3063SMOD_slot2", FIELD_dsp340050b49a6c_fld3063SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3065SMOD_slot2", FIELD_dsp340050b49a6c_fld3065SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3066SMOD_slot2", FIELD_dsp340050b49a6c_fld3066SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3067SMOD_slot2", FIELD_dsp340050b49a6c_fld3067SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3068SMOD_slot2", FIELD_dsp340050b49a6c_fld3068SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3069SMOD_slot2", FIELD_dsp340050b49a6c_fld3069SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3070", FIELD_dsp340050b49a6c_fld3070, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3071SMOD_slot2", FIELD_dsp340050b49a6c_fld3071SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3072SMOD_slot2", FIELD_dsp340050b49a6c_fld3072SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3073SMOD_slot2", FIELD_dsp340050b49a6c_fld3073SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3074SMOD_slot2", FIELD_dsp340050b49a6c_fld3074SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3075SMOD_slot2", FIELD_dsp340050b49a6c_fld3075SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3076SMOD_slot2", FIELD_dsp340050b49a6c_fld3076SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3077SMOD_slot2", FIELD_dsp340050b49a6c_fld3077SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3078SMOD_slot2", FIELD_dsp340050b49a6c_fld3078SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3079SMOD_slot2", FIELD_dsp340050b49a6c_fld3079SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3080SMOD_slot2", FIELD_dsp340050b49a6c_fld3080SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3081SMOD_slot2", FIELD_dsp340050b49a6c_fld3081SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3082SMOD_slot2", FIELD_dsp340050b49a6c_fld3082SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3084SMOD_slot2", FIELD_dsp340050b49a6c_fld3084SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3085SMOD_slot2", FIELD_dsp340050b49a6c_fld3085SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3087SMOD_slot2", FIELD_dsp340050b49a6c_fld3087SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3088SMOD_slot2", FIELD_dsp340050b49a6c_fld3088SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3090SMOD_slot2", FIELD_dsp340050b49a6c_fld3090SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3091SMOD_slot2", FIELD_dsp340050b49a6c_fld3091SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3092SMOD_slot2", FIELD_dsp340050b49a6c_fld3092SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3093SMOD_slot2", FIELD_dsp340050b49a6c_fld3093SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3096SMOD_slot2", FIELD_dsp340050b49a6c_fld3096SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3097SMOD_slot2", FIELD_dsp340050b49a6c_fld3097SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3098SMOD_slot2", FIELD_dsp340050b49a6c_fld3098SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3099SMOD_slot2", FIELD_dsp340050b49a6c_fld3099SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3100SMOD_slot2", FIELD_dsp340050b49a6c_fld3100SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3101SMOD_slot2", FIELD_dsp340050b49a6c_fld3101SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3102SMOD_slot2", FIELD_dsp340050b49a6c_fld3102SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3104SMOD_slot2", FIELD_dsp340050b49a6c_fld3104SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3105SMOD_slot2", FIELD_dsp340050b49a6c_fld3105SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3106SMOD_slot2", FIELD_dsp340050b49a6c_fld3106SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3107SMOD_slot2", FIELD_dsp340050b49a6c_fld3107SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3108SMOD_slot2", FIELD_dsp340050b49a6c_fld3108SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3109SMOD_slot2", FIELD_dsp340050b49a6c_fld3109SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3110SMOD_slot2", FIELD_dsp340050b49a6c_fld3110SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3111SMOD_slot2", FIELD_dsp340050b49a6c_fld3111SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3113SMOD_slot2", FIELD_dsp340050b49a6c_fld3113SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3114SMOD_slot2", FIELD_dsp340050b49a6c_fld3114SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3115SMOD_slot2", FIELD_dsp340050b49a6c_fld3115SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3116SMOD_slot2", FIELD_dsp340050b49a6c_fld3116SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3805SMOD_slot2", FIELD_dsp340050b49a6c_fld3805SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3806SMOD_slot2", FIELD_dsp340050b49a6c_fld3806SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3807SMOD_slot2", FIELD_dsp340050b49a6c_fld3807SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3808", FIELD_dsp340050b49a6c_fld3808, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3809SMOD_slot2", FIELD_dsp340050b49a6c_fld3809SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3810SMOD_slot2", FIELD_dsp340050b49a6c_fld3810SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3812SMOD_slot2", FIELD_dsp340050b49a6c_fld3812SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3813SMOD_slot2", FIELD_dsp340050b49a6c_fld3813SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3814SMOD_slot2", FIELD_dsp340050b49a6c_fld3814SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3816SMOD_slot2", FIELD_dsp340050b49a6c_fld3816SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3817", FIELD_dsp340050b49a6c_fld3817, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3818SMOD_slot2", FIELD_dsp340050b49a6c_fld3818SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3819SMOD_slot2", FIELD_dsp340050b49a6c_fld3819SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3821SMOD_slot2", FIELD_dsp340050b49a6c_fld3821SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3822SMOD_slot2", FIELD_dsp340050b49a6c_fld3822SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3823SMOD_slot2", FIELD_dsp340050b49a6c_fld3823SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3824SMOD_slot2", FIELD_dsp340050b49a6c_fld3824SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3825SMOD_slot2", FIELD_dsp340050b49a6c_fld3825SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3826SMOD_slot2", FIELD_dsp340050b49a6c_fld3826SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3827SMOD_slot2", FIELD_dsp340050b49a6c_fld3827SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3828SMOD_slot2", FIELD_dsp340050b49a6c_fld3828SMOD_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s16", FIELD_op0_s16, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2033", FIELD_dsp340050b49a6c_fld2033, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2080", FIELD_dsp340050b49a6c_fld2080, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3117SMOD_slot1", FIELD_dsp340050b49a6c_fld3117SMOD_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3118SMOD_slot1", FIELD_dsp340050b49a6c_fld3118SMOD_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3829SMOD_slot1", FIELD_dsp340050b49a6c_fld3829SMOD_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s17", FIELD_op0_s17, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3119SMOD_slot0", FIELD_dsp340050b49a6c_fld3119SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3120SMOD_slot0", FIELD_dsp340050b49a6c_fld3120SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3121SMOD_slot0", FIELD_dsp340050b49a6c_fld3121SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3122SMOD_slot0", FIELD_dsp340050b49a6c_fld3122SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3123SMOD_slot0", FIELD_dsp340050b49a6c_fld3123SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3125SMOD_slot0", FIELD_dsp340050b49a6c_fld3125SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3126SMOD_slot0", FIELD_dsp340050b49a6c_fld3126SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3127SMOD_slot0", FIELD_dsp340050b49a6c_fld3127SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3128SMOD_slot0", FIELD_dsp340050b49a6c_fld3128SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3129SMOD_slot0", FIELD_dsp340050b49a6c_fld3129SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3130SMOD_slot0", FIELD_dsp340050b49a6c_fld3130SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3131SMOD_slot0", FIELD_dsp340050b49a6c_fld3131SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3132SMOD_slot0", FIELD_dsp340050b49a6c_fld3132SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3133SMOD_slot0", FIELD_dsp340050b49a6c_fld3133SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3134SMOD_slot0", FIELD_dsp340050b49a6c_fld3134SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3135SMOD_slot0", FIELD_dsp340050b49a6c_fld3135SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3136SMOD_slot0", FIELD_dsp340050b49a6c_fld3136SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3137SMOD_slot0", FIELD_dsp340050b49a6c_fld3137SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3138SMOD_slot0", FIELD_dsp340050b49a6c_fld3138SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3139SMOD_slot0", FIELD_dsp340050b49a6c_fld3139SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3140SMOD_slot0", FIELD_dsp340050b49a6c_fld3140SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3141SMOD_slot0", FIELD_dsp340050b49a6c_fld3141SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3142SMOD_slot0", FIELD_dsp340050b49a6c_fld3142SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3143SMOD_slot0", FIELD_dsp340050b49a6c_fld3143SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3144SMOD_slot0", FIELD_dsp340050b49a6c_fld3144SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3145SMOD_slot0", FIELD_dsp340050b49a6c_fld3145SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3146SMOD_slot0", FIELD_dsp340050b49a6c_fld3146SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3148SMOD_slot0", FIELD_dsp340050b49a6c_fld3148SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3149SMOD_slot0", FIELD_dsp340050b49a6c_fld3149SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3150", FIELD_dsp340050b49a6c_fld3150, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3152SMOD_slot0", FIELD_dsp340050b49a6c_fld3152SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3153SMOD_slot0", FIELD_dsp340050b49a6c_fld3153SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3155SMOD_slot0", FIELD_dsp340050b49a6c_fld3155SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3156SMOD_slot0", FIELD_dsp340050b49a6c_fld3156SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3157SMOD_slot0", FIELD_dsp340050b49a6c_fld3157SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3158SMOD_slot0", FIELD_dsp340050b49a6c_fld3158SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3159SMOD_slot0", FIELD_dsp340050b49a6c_fld3159SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3160SMOD_slot0", FIELD_dsp340050b49a6c_fld3160SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3161SMOD_slot0", FIELD_dsp340050b49a6c_fld3161SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3164SMOD_slot0", FIELD_dsp340050b49a6c_fld3164SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3165SMOD_slot0", FIELD_dsp340050b49a6c_fld3165SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3166SMOD_slot0", FIELD_dsp340050b49a6c_fld3166SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3168SMOD_slot0", FIELD_dsp340050b49a6c_fld3168SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3170SMOD_slot0", FIELD_dsp340050b49a6c_fld3170SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3171SMOD_slot0", FIELD_dsp340050b49a6c_fld3171SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3172SMOD_slot0", FIELD_dsp340050b49a6c_fld3172SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3173SMOD_slot0", FIELD_dsp340050b49a6c_fld3173SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3174SMOD_slot0", FIELD_dsp340050b49a6c_fld3174SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3175SMOD_slot0", FIELD_dsp340050b49a6c_fld3175SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3176SMOD_slot0", FIELD_dsp340050b49a6c_fld3176SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3177SMOD_slot0", FIELD_dsp340050b49a6c_fld3177SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3178SMOD_slot0", FIELD_dsp340050b49a6c_fld3178SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3179SMOD_slot0", FIELD_dsp340050b49a6c_fld3179SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3180SMOD_slot0", FIELD_dsp340050b49a6c_fld3180SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3181SMOD_slot0", FIELD_dsp340050b49a6c_fld3181SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3182SMOD_slot0", FIELD_dsp340050b49a6c_fld3182SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3184SMOD_slot0", FIELD_dsp340050b49a6c_fld3184SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3186SMOD_slot0", FIELD_dsp340050b49a6c_fld3186SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3188SMOD_slot0", FIELD_dsp340050b49a6c_fld3188SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3832SMOD_slot0", FIELD_dsp340050b49a6c_fld3832SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3833SMOD_slot0", FIELD_dsp340050b49a6c_fld3833SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3834", FIELD_dsp340050b49a6c_fld3834, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3836SMOD_slot0", FIELD_dsp340050b49a6c_fld3836SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3837SMOD_slot0", FIELD_dsp340050b49a6c_fld3837SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3838SMOD_slot0", FIELD_dsp340050b49a6c_fld3838SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3841SMOD_slot0", FIELD_dsp340050b49a6c_fld3841SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3842SMOD_slot0", FIELD_dsp340050b49a6c_fld3842SMOD_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s18", FIELD_op0_s18, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2074", FIELD_dsp340050b49a6c_fld2074, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3191LLR_slot2", FIELD_dsp340050b49a6c_fld3191LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3192LLR_slot2", FIELD_dsp340050b49a6c_fld3192LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3193LLR_slot2", FIELD_dsp340050b49a6c_fld3193LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3194LLR_slot2", FIELD_dsp340050b49a6c_fld3194LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3195LLR_slot2", FIELD_dsp340050b49a6c_fld3195LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3196LLR_slot2", FIELD_dsp340050b49a6c_fld3196LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3197LLR_slot2", FIELD_dsp340050b49a6c_fld3197LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3198LLR_slot2", FIELD_dsp340050b49a6c_fld3198LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3199LLR_slot2", FIELD_dsp340050b49a6c_fld3199LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3200LLR_slot2", FIELD_dsp340050b49a6c_fld3200LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3201LLR_slot2", FIELD_dsp340050b49a6c_fld3201LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3202LLR_slot2", FIELD_dsp340050b49a6c_fld3202LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3203LLR_slot2", FIELD_dsp340050b49a6c_fld3203LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3204LLR_slot2", FIELD_dsp340050b49a6c_fld3204LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3205", FIELD_dsp340050b49a6c_fld3205, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3206", FIELD_dsp340050b49a6c_fld3206, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3207LLR_slot2", FIELD_dsp340050b49a6c_fld3207LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3208LLR_slot2", FIELD_dsp340050b49a6c_fld3208LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3210LLR_slot2", FIELD_dsp340050b49a6c_fld3210LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3212", FIELD_dsp340050b49a6c_fld3212, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3213LLR_slot2", FIELD_dsp340050b49a6c_fld3213LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3214", FIELD_dsp340050b49a6c_fld3214, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3215LLR_slot2", FIELD_dsp340050b49a6c_fld3215LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3216LLR_slot2", FIELD_dsp340050b49a6c_fld3216LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3217", FIELD_dsp340050b49a6c_fld3217, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3218LLR_slot2", FIELD_dsp340050b49a6c_fld3218LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3220LLR_slot2", FIELD_dsp340050b49a6c_fld3220LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3221LLR_slot2", FIELD_dsp340050b49a6c_fld3221LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3222LLR_slot2", FIELD_dsp340050b49a6c_fld3222LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3224LLR_slot2", FIELD_dsp340050b49a6c_fld3224LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3225", FIELD_dsp340050b49a6c_fld3225, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3226LLR_slot2", FIELD_dsp340050b49a6c_fld3226LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3228LLR_slot2", FIELD_dsp340050b49a6c_fld3228LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3230", FIELD_dsp340050b49a6c_fld3230, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3231LLR_slot2", FIELD_dsp340050b49a6c_fld3231LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3232LLR_slot2", FIELD_dsp340050b49a6c_fld3232LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3233", FIELD_dsp340050b49a6c_fld3233, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3234LLR_slot2", FIELD_dsp340050b49a6c_fld3234LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3235LLR_slot2", FIELD_dsp340050b49a6c_fld3235LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3236", FIELD_dsp340050b49a6c_fld3236, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3237LLR_slot2", FIELD_dsp340050b49a6c_fld3237LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3238LLR_slot2", FIELD_dsp340050b49a6c_fld3238LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3240LLR_slot2", FIELD_dsp340050b49a6c_fld3240LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3241LLR_slot2", FIELD_dsp340050b49a6c_fld3241LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3242LLR_slot2", FIELD_dsp340050b49a6c_fld3242LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3243LLR_slot2", FIELD_dsp340050b49a6c_fld3243LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3244LLR_slot2", FIELD_dsp340050b49a6c_fld3244LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3245LLR_slot2", FIELD_dsp340050b49a6c_fld3245LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3246", FIELD_dsp340050b49a6c_fld3246, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3247LLR_slot2", FIELD_dsp340050b49a6c_fld3247LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3843LLR_slot2", FIELD_dsp340050b49a6c_fld3843LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3844", FIELD_dsp340050b49a6c_fld3844, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3845LLR_slot2", FIELD_dsp340050b49a6c_fld3845LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3847LLR_slot2", FIELD_dsp340050b49a6c_fld3847LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3848LLR_slot2", FIELD_dsp340050b49a6c_fld3848LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3849LLR_slot2", FIELD_dsp340050b49a6c_fld3849LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3850LLR_slot2", FIELD_dsp340050b49a6c_fld3850LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3851LLR_slot2", FIELD_dsp340050b49a6c_fld3851LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3853LLR_slot2", FIELD_dsp340050b49a6c_fld3853LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3855LLR_slot2", FIELD_dsp340050b49a6c_fld3855LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3856LLR_slot2", FIELD_dsp340050b49a6c_fld3856LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3857LLR_slot2", FIELD_dsp340050b49a6c_fld3857LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3859LLR_slot2", FIELD_dsp340050b49a6c_fld3859LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3860LLR_slot2", FIELD_dsp340050b49a6c_fld3860LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3861LLR_slot2", FIELD_dsp340050b49a6c_fld3861LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3862", FIELD_dsp340050b49a6c_fld3862, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3863LLR_slot2", FIELD_dsp340050b49a6c_fld3863LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3864LLR_slot2", FIELD_dsp340050b49a6c_fld3864LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3865LLR_slot2", FIELD_dsp340050b49a6c_fld3865LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3866LLR_slot2", FIELD_dsp340050b49a6c_fld3866LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3867LLR_slot2", FIELD_dsp340050b49a6c_fld3867LLR_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3868", FIELD_dsp340050b49a6c_fld3868, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s19", FIELD_op0_s19, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2034", FIELD_dsp340050b49a6c_fld2034, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3248LLR_slot1", FIELD_dsp340050b49a6c_fld3248LLR_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3250LLR_slot1", FIELD_dsp340050b49a6c_fld3250LLR_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3251LLR_slot1", FIELD_dsp340050b49a6c_fld3251LLR_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3252LLR_slot1", FIELD_dsp340050b49a6c_fld3252LLR_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3253LLR_slot1", FIELD_dsp340050b49a6c_fld3253LLR_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3254LLR_slot1", FIELD_dsp340050b49a6c_fld3254LLR_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3869LLR_slot1", FIELD_dsp340050b49a6c_fld3869LLR_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3870", FIELD_dsp340050b49a6c_fld3870, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3872LLR_slot1", FIELD_dsp340050b49a6c_fld3872LLR_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3875LLR_slot1", FIELD_dsp340050b49a6c_fld3875LLR_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3876LLR_slot1", FIELD_dsp340050b49a6c_fld3876LLR_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3878LLR_slot1", FIELD_dsp340050b49a6c_fld3878LLR_slot1, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s20", FIELD_op0_s20, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2071", FIELD_dsp340050b49a6c_fld2071, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3258LLR_slot0", FIELD_dsp340050b49a6c_fld3258LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3259LLR_slot0", FIELD_dsp340050b49a6c_fld3259LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3260LLR_slot0", FIELD_dsp340050b49a6c_fld3260LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3261LLR_slot0", FIELD_dsp340050b49a6c_fld3261LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3263LLR_slot0", FIELD_dsp340050b49a6c_fld3263LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3264LLR_slot0", FIELD_dsp340050b49a6c_fld3264LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3265LLR_slot0", FIELD_dsp340050b49a6c_fld3265LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3266LLR_slot0", FIELD_dsp340050b49a6c_fld3266LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3267LLR_slot0", FIELD_dsp340050b49a6c_fld3267LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3268LLR_slot0", FIELD_dsp340050b49a6c_fld3268LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3269LLR_slot0", FIELD_dsp340050b49a6c_fld3269LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3270LLR_slot0", FIELD_dsp340050b49a6c_fld3270LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3272LLR_slot0", FIELD_dsp340050b49a6c_fld3272LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3274LLR_slot0", FIELD_dsp340050b49a6c_fld3274LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3275LLR_slot0", FIELD_dsp340050b49a6c_fld3275LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3276LLR_slot0", FIELD_dsp340050b49a6c_fld3276LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3277LLR_slot0", FIELD_dsp340050b49a6c_fld3277LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3278LLR_slot0", FIELD_dsp340050b49a6c_fld3278LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3279LLR_slot0", FIELD_dsp340050b49a6c_fld3279LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3280LLR_slot0", FIELD_dsp340050b49a6c_fld3280LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3281LLR_slot0", FIELD_dsp340050b49a6c_fld3281LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3282LLR_slot0", FIELD_dsp340050b49a6c_fld3282LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3283LLR_slot0", FIELD_dsp340050b49a6c_fld3283LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3284LLR_slot0", FIELD_dsp340050b49a6c_fld3284LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3286LLR_slot0", FIELD_dsp340050b49a6c_fld3286LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3288LLR_slot0", FIELD_dsp340050b49a6c_fld3288LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3289LLR_slot0", FIELD_dsp340050b49a6c_fld3289LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3291LLR_slot0", FIELD_dsp340050b49a6c_fld3291LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3292LLR_slot0", FIELD_dsp340050b49a6c_fld3292LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3293LLR_slot0", FIELD_dsp340050b49a6c_fld3293LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3294LLR_slot0", FIELD_dsp340050b49a6c_fld3294LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3295LLR_slot0", FIELD_dsp340050b49a6c_fld3295LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3296LLR_slot0", FIELD_dsp340050b49a6c_fld3296LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3297LLR_slot0", FIELD_dsp340050b49a6c_fld3297LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3298LLR_slot0", FIELD_dsp340050b49a6c_fld3298LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3299LLR_slot0", FIELD_dsp340050b49a6c_fld3299LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3300LLR_slot0", FIELD_dsp340050b49a6c_fld3300LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3302LLR_slot0", FIELD_dsp340050b49a6c_fld3302LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3303LLR_slot0", FIELD_dsp340050b49a6c_fld3303LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3304LLR_slot0", FIELD_dsp340050b49a6c_fld3304LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3305LLR_slot0", FIELD_dsp340050b49a6c_fld3305LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3306LLR_slot0", FIELD_dsp340050b49a6c_fld3306LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3308LLR_slot0", FIELD_dsp340050b49a6c_fld3308LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3310LLR_slot0", FIELD_dsp340050b49a6c_fld3310LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3311LLR_slot0", FIELD_dsp340050b49a6c_fld3311LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3312LLR_slot0", FIELD_dsp340050b49a6c_fld3312LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3879LLR_slot0", FIELD_dsp340050b49a6c_fld3879LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3881LLR_slot0", FIELD_dsp340050b49a6c_fld3881LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3883LLR_slot0", FIELD_dsp340050b49a6c_fld3883LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3885LLR_slot0", FIELD_dsp340050b49a6c_fld3885LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3887LLR_slot0", FIELD_dsp340050b49a6c_fld3887LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3888LLR_slot0", FIELD_dsp340050b49a6c_fld3888LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3890LLR_slot0", FIELD_dsp340050b49a6c_fld3890LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3892LLR_slot0", FIELD_dsp340050b49a6c_fld3892LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3893LLR_slot0", FIELD_dsp340050b49a6c_fld3893LLR_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s21", FIELD_op0_s21, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3313DUAL_slot2", FIELD_dsp340050b49a6c_fld3313DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3314", FIELD_dsp340050b49a6c_fld3314, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3315DUAL_slot2", FIELD_dsp340050b49a6c_fld3315DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3316DUAL_slot2", FIELD_dsp340050b49a6c_fld3316DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3317DUAL_slot2", FIELD_dsp340050b49a6c_fld3317DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3318", FIELD_dsp340050b49a6c_fld3318, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3319DUAL_slot2", FIELD_dsp340050b49a6c_fld3319DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3320DUAL_slot2", FIELD_dsp340050b49a6c_fld3320DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3321DUAL_slot2", FIELD_dsp340050b49a6c_fld3321DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3322DUAL_slot2", FIELD_dsp340050b49a6c_fld3322DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3323DUAL_slot2", FIELD_dsp340050b49a6c_fld3323DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3324DUAL_slot2", FIELD_dsp340050b49a6c_fld3324DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3325DUAL_slot2", FIELD_dsp340050b49a6c_fld3325DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3326DUAL_slot2", FIELD_dsp340050b49a6c_fld3326DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3327DUAL_slot2", FIELD_dsp340050b49a6c_fld3327DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3328DUAL_slot2", FIELD_dsp340050b49a6c_fld3328DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3329DUAL_slot2", FIELD_dsp340050b49a6c_fld3329DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3330DUAL_slot2", FIELD_dsp340050b49a6c_fld3330DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3331DUAL_slot2", FIELD_dsp340050b49a6c_fld3331DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3332DUAL_slot2", FIELD_dsp340050b49a6c_fld3332DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3333DUAL_slot2", FIELD_dsp340050b49a6c_fld3333DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3334DUAL_slot2", FIELD_dsp340050b49a6c_fld3334DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3335DUAL_slot2", FIELD_dsp340050b49a6c_fld3335DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3336DUAL_slot2", FIELD_dsp340050b49a6c_fld3336DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3337DUAL_slot2", FIELD_dsp340050b49a6c_fld3337DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3339DUAL_slot2", FIELD_dsp340050b49a6c_fld3339DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3340DUAL_slot2", FIELD_dsp340050b49a6c_fld3340DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3341DUAL_slot2", FIELD_dsp340050b49a6c_fld3341DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3342DUAL_slot2", FIELD_dsp340050b49a6c_fld3342DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3345DUAL_slot2", FIELD_dsp340050b49a6c_fld3345DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3347DUAL_slot2", FIELD_dsp340050b49a6c_fld3347DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3348DUAL_slot2", FIELD_dsp340050b49a6c_fld3348DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3349DUAL_slot2", FIELD_dsp340050b49a6c_fld3349DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3350DUAL_slot2", FIELD_dsp340050b49a6c_fld3350DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3353DUAL_slot2", FIELD_dsp340050b49a6c_fld3353DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3354DUAL_slot2", FIELD_dsp340050b49a6c_fld3354DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3356DUAL_slot2", FIELD_dsp340050b49a6c_fld3356DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3358DUAL_slot2", FIELD_dsp340050b49a6c_fld3358DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3360DUAL_slot2", FIELD_dsp340050b49a6c_fld3360DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3361DUAL_slot2", FIELD_dsp340050b49a6c_fld3361DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3362DUAL_slot2", FIELD_dsp340050b49a6c_fld3362DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3363DUAL_slot2", FIELD_dsp340050b49a6c_fld3363DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3364", FIELD_dsp340050b49a6c_fld3364, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3365DUAL_slot2", FIELD_dsp340050b49a6c_fld3365DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3366DUAL_slot2", FIELD_dsp340050b49a6c_fld3366DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3367DUAL_slot2", FIELD_dsp340050b49a6c_fld3367DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3368DUAL_slot2", FIELD_dsp340050b49a6c_fld3368DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3369DUAL_slot2", FIELD_dsp340050b49a6c_fld3369DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3370DUAL_slot2", FIELD_dsp340050b49a6c_fld3370DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3371DUAL_slot2", FIELD_dsp340050b49a6c_fld3371DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3372DUAL_slot2", FIELD_dsp340050b49a6c_fld3372DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3373DUAL_slot2", FIELD_dsp340050b49a6c_fld3373DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3374DUAL_slot2", FIELD_dsp340050b49a6c_fld3374DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3375DUAL_slot2", FIELD_dsp340050b49a6c_fld3375DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3376DUAL_slot2", FIELD_dsp340050b49a6c_fld3376DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3377DUAL_slot2", FIELD_dsp340050b49a6c_fld3377DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3378DUAL_slot2", FIELD_dsp340050b49a6c_fld3378DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3379DUAL_slot2", FIELD_dsp340050b49a6c_fld3379DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3380DUAL_slot2", FIELD_dsp340050b49a6c_fld3380DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3381DUAL_slot2", FIELD_dsp340050b49a6c_fld3381DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3382DUAL_slot2", FIELD_dsp340050b49a6c_fld3382DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3384DUAL_slot2", FIELD_dsp340050b49a6c_fld3384DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3385DUAL_slot2", FIELD_dsp340050b49a6c_fld3385DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3386DUAL_slot2", FIELD_dsp340050b49a6c_fld3386DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3387DUAL_slot2", FIELD_dsp340050b49a6c_fld3387DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3388DUAL_slot2", FIELD_dsp340050b49a6c_fld3388DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3390DUAL_slot2", FIELD_dsp340050b49a6c_fld3390DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3392DUAL_slot2", FIELD_dsp340050b49a6c_fld3392DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3394DUAL_slot2", FIELD_dsp340050b49a6c_fld3394DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3396DUAL_slot2", FIELD_dsp340050b49a6c_fld3396DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3397DUAL_slot2", FIELD_dsp340050b49a6c_fld3397DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3399DUAL_slot2", FIELD_dsp340050b49a6c_fld3399DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3401DUAL_slot2", FIELD_dsp340050b49a6c_fld3401DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3403DUAL_slot2", FIELD_dsp340050b49a6c_fld3403DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3404DUAL_slot2", FIELD_dsp340050b49a6c_fld3404DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3406DUAL_slot2", FIELD_dsp340050b49a6c_fld3406DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3407", FIELD_dsp340050b49a6c_fld3407, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3408DUAL_slot2", FIELD_dsp340050b49a6c_fld3408DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3410", FIELD_dsp340050b49a6c_fld3410, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3411DUAL_slot2", FIELD_dsp340050b49a6c_fld3411DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3412DUAL_slot2", FIELD_dsp340050b49a6c_fld3412DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3413DUAL_slot2", FIELD_dsp340050b49a6c_fld3413DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3414DUAL_slot2", FIELD_dsp340050b49a6c_fld3414DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3415DUAL_slot2", FIELD_dsp340050b49a6c_fld3415DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3416DUAL_slot2", FIELD_dsp340050b49a6c_fld3416DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3417DUAL_slot2", FIELD_dsp340050b49a6c_fld3417DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3418DUAL_slot2", FIELD_dsp340050b49a6c_fld3418DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3419DUAL_slot2", FIELD_dsp340050b49a6c_fld3419DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3420DUAL_slot2", FIELD_dsp340050b49a6c_fld3420DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3421DUAL_slot2", FIELD_dsp340050b49a6c_fld3421DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3422DUAL_slot2", FIELD_dsp340050b49a6c_fld3422DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3423DUAL_slot2", FIELD_dsp340050b49a6c_fld3423DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3424DUAL_slot2", FIELD_dsp340050b49a6c_fld3424DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3425DUAL_slot2", FIELD_dsp340050b49a6c_fld3425DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3426DUAL_slot2", FIELD_dsp340050b49a6c_fld3426DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3427DUAL_slot2", FIELD_dsp340050b49a6c_fld3427DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3428DUAL_slot2", FIELD_dsp340050b49a6c_fld3428DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3429DUAL_slot2", FIELD_dsp340050b49a6c_fld3429DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3430DUAL_slot2", FIELD_dsp340050b49a6c_fld3430DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3431DUAL_slot2", FIELD_dsp340050b49a6c_fld3431DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3432DUAL_slot2", FIELD_dsp340050b49a6c_fld3432DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3433DUAL_slot2", FIELD_dsp340050b49a6c_fld3433DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3434DUAL_slot2", FIELD_dsp340050b49a6c_fld3434DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3435DUAL_slot2", FIELD_dsp340050b49a6c_fld3435DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3436DUAL_slot2", FIELD_dsp340050b49a6c_fld3436DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3437DUAL_slot2", FIELD_dsp340050b49a6c_fld3437DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3438DUAL_slot2", FIELD_dsp340050b49a6c_fld3438DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3439DUAL_slot2", FIELD_dsp340050b49a6c_fld3439DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3440DUAL_slot2", FIELD_dsp340050b49a6c_fld3440DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3441DUAL_slot2", FIELD_dsp340050b49a6c_fld3441DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3442DUAL_slot2", FIELD_dsp340050b49a6c_fld3442DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3443DUAL_slot2", FIELD_dsp340050b49a6c_fld3443DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3444DUAL_slot2", FIELD_dsp340050b49a6c_fld3444DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3445DUAL_slot2", FIELD_dsp340050b49a6c_fld3445DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3446DUAL_slot2", FIELD_dsp340050b49a6c_fld3446DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3448DUAL_slot2", FIELD_dsp340050b49a6c_fld3448DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3450DUAL_slot2", FIELD_dsp340050b49a6c_fld3450DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3451DUAL_slot2", FIELD_dsp340050b49a6c_fld3451DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3453DUAL_slot2", FIELD_dsp340050b49a6c_fld3453DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3454DUAL_slot2", FIELD_dsp340050b49a6c_fld3454DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3456DUAL_slot2", FIELD_dsp340050b49a6c_fld3456DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3457DUAL_slot2", FIELD_dsp340050b49a6c_fld3457DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3458DUAL_slot2", FIELD_dsp340050b49a6c_fld3458DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3459DUAL_slot2", FIELD_dsp340050b49a6c_fld3459DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3460DUAL_slot2", FIELD_dsp340050b49a6c_fld3460DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3461DUAL_slot2", FIELD_dsp340050b49a6c_fld3461DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3462DUAL_slot2", FIELD_dsp340050b49a6c_fld3462DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3464DUAL_slot2", FIELD_dsp340050b49a6c_fld3464DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3465DUAL_slot2", FIELD_dsp340050b49a6c_fld3465DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3466", FIELD_dsp340050b49a6c_fld3466, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3467DUAL_slot2", FIELD_dsp340050b49a6c_fld3467DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3468DUAL_slot2", FIELD_dsp340050b49a6c_fld3468DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3469DUAL_slot2", FIELD_dsp340050b49a6c_fld3469DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3470DUAL_slot2", FIELD_dsp340050b49a6c_fld3470DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3471DUAL_slot2", FIELD_dsp340050b49a6c_fld3471DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3472DUAL_slot2", FIELD_dsp340050b49a6c_fld3472DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3473DUAL_slot2", FIELD_dsp340050b49a6c_fld3473DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3474DUAL_slot2", FIELD_dsp340050b49a6c_fld3474DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3475DUAL_slot2", FIELD_dsp340050b49a6c_fld3475DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3477DUAL_slot2", FIELD_dsp340050b49a6c_fld3477DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3478DUAL_slot2", FIELD_dsp340050b49a6c_fld3478DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3479DUAL_slot2", FIELD_dsp340050b49a6c_fld3479DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3480DUAL_slot2", FIELD_dsp340050b49a6c_fld3480DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3481DUAL_slot2", FIELD_dsp340050b49a6c_fld3481DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3482DUAL_slot2", FIELD_dsp340050b49a6c_fld3482DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3484DUAL_slot2", FIELD_dsp340050b49a6c_fld3484DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3894DUAL_slot2", FIELD_dsp340050b49a6c_fld3894DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3895DUAL_slot2", FIELD_dsp340050b49a6c_fld3895DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3896DUAL_slot2", FIELD_dsp340050b49a6c_fld3896DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3897DUAL_slot2", FIELD_dsp340050b49a6c_fld3897DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3898DUAL_slot2", FIELD_dsp340050b49a6c_fld3898DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3899DUAL_slot2", FIELD_dsp340050b49a6c_fld3899DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3900", FIELD_dsp340050b49a6c_fld3900, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3901DUAL_slot2", FIELD_dsp340050b49a6c_fld3901DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3903DUAL_slot2", FIELD_dsp340050b49a6c_fld3903DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3904DUAL_slot2", FIELD_dsp340050b49a6c_fld3904DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3905DUAL_slot2", FIELD_dsp340050b49a6c_fld3905DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3906DUAL_slot2", FIELD_dsp340050b49a6c_fld3906DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3907DUAL_slot2", FIELD_dsp340050b49a6c_fld3907DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3908DUAL_slot2", FIELD_dsp340050b49a6c_fld3908DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3909DUAL_slot2", FIELD_dsp340050b49a6c_fld3909DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3910DUAL_slot2", FIELD_dsp340050b49a6c_fld3910DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3913DUAL_slot2", FIELD_dsp340050b49a6c_fld3913DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3914DUAL_slot2", FIELD_dsp340050b49a6c_fld3914DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3916DUAL_slot2", FIELD_dsp340050b49a6c_fld3916DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3917DUAL_slot2", FIELD_dsp340050b49a6c_fld3917DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3918DUAL_slot2", FIELD_dsp340050b49a6c_fld3918DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3919DUAL_slot2", FIELD_dsp340050b49a6c_fld3919DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3920DUAL_slot2", FIELD_dsp340050b49a6c_fld3920DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3921DUAL_slot2", FIELD_dsp340050b49a6c_fld3921DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3922DUAL_slot2", FIELD_dsp340050b49a6c_fld3922DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3923DUAL_slot2", FIELD_dsp340050b49a6c_fld3923DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3924DUAL_slot2", FIELD_dsp340050b49a6c_fld3924DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3925DUAL_slot2", FIELD_dsp340050b49a6c_fld3925DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3927DUAL_slot2", FIELD_dsp340050b49a6c_fld3927DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3928DUAL_slot2", FIELD_dsp340050b49a6c_fld3928DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3929DUAL_slot2", FIELD_dsp340050b49a6c_fld3929DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3930DUAL_slot2", FIELD_dsp340050b49a6c_fld3930DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3931DUAL_slot2", FIELD_dsp340050b49a6c_fld3931DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3933DUAL_slot2", FIELD_dsp340050b49a6c_fld3933DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3934DUAL_slot2", FIELD_dsp340050b49a6c_fld3934DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3935DUAL_slot2", FIELD_dsp340050b49a6c_fld3935DUAL_slot2, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s22", FIELD_op0_s22, -1, 0, 0, 0, 0, 0, 0 }, + { "op0_s23", FIELD_op0_s23, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2057", FIELD_dsp340050b49a6c_fld2057, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2060", FIELD_dsp340050b49a6c_fld2060, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2066", FIELD_dsp340050b49a6c_fld2066, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2072", FIELD_dsp340050b49a6c_fld2072, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld2079", FIELD_dsp340050b49a6c_fld2079, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3487DUAL_slot0", FIELD_dsp340050b49a6c_fld3487DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3488DUAL_slot0", FIELD_dsp340050b49a6c_fld3488DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3489DUAL_slot0", FIELD_dsp340050b49a6c_fld3489DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3490DUAL_slot0", FIELD_dsp340050b49a6c_fld3490DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3491DUAL_slot0", FIELD_dsp340050b49a6c_fld3491DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3492DUAL_slot0", FIELD_dsp340050b49a6c_fld3492DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3493DUAL_slot0", FIELD_dsp340050b49a6c_fld3493DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3494DUAL_slot0", FIELD_dsp340050b49a6c_fld3494DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3496DUAL_slot0", FIELD_dsp340050b49a6c_fld3496DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3497DUAL_slot0", FIELD_dsp340050b49a6c_fld3497DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3498DUAL_slot0", FIELD_dsp340050b49a6c_fld3498DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3499DUAL_slot0", FIELD_dsp340050b49a6c_fld3499DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3500DUAL_slot0", FIELD_dsp340050b49a6c_fld3500DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3502DUAL_slot0", FIELD_dsp340050b49a6c_fld3502DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3504DUAL_slot0", FIELD_dsp340050b49a6c_fld3504DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3505DUAL_slot0", FIELD_dsp340050b49a6c_fld3505DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3506DUAL_slot0", FIELD_dsp340050b49a6c_fld3506DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3507DUAL_slot0", FIELD_dsp340050b49a6c_fld3507DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3508DUAL_slot0", FIELD_dsp340050b49a6c_fld3508DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3509DUAL_slot0", FIELD_dsp340050b49a6c_fld3509DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3510DUAL_slot0", FIELD_dsp340050b49a6c_fld3510DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3511DUAL_slot0", FIELD_dsp340050b49a6c_fld3511DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3512DUAL_slot0", FIELD_dsp340050b49a6c_fld3512DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3513DUAL_slot0", FIELD_dsp340050b49a6c_fld3513DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3514DUAL_slot0", FIELD_dsp340050b49a6c_fld3514DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3515DUAL_slot0", FIELD_dsp340050b49a6c_fld3515DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3516DUAL_slot0", FIELD_dsp340050b49a6c_fld3516DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3517DUAL_slot0", FIELD_dsp340050b49a6c_fld3517DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3518DUAL_slot0", FIELD_dsp340050b49a6c_fld3518DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3519DUAL_slot0", FIELD_dsp340050b49a6c_fld3519DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3520DUAL_slot0", FIELD_dsp340050b49a6c_fld3520DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3522DUAL_slot0", FIELD_dsp340050b49a6c_fld3522DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3523DUAL_slot0", FIELD_dsp340050b49a6c_fld3523DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3524DUAL_slot0", FIELD_dsp340050b49a6c_fld3524DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3527DUAL_slot0", FIELD_dsp340050b49a6c_fld3527DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3529DUAL_slot0", FIELD_dsp340050b49a6c_fld3529DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3530DUAL_slot0", FIELD_dsp340050b49a6c_fld3530DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3531", FIELD_dsp340050b49a6c_fld3531, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3532DUAL_slot0", FIELD_dsp340050b49a6c_fld3532DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3533DUAL_slot0", FIELD_dsp340050b49a6c_fld3533DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3535DUAL_slot0", FIELD_dsp340050b49a6c_fld3535DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3536DUAL_slot0", FIELD_dsp340050b49a6c_fld3536DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3537DUAL_slot0", FIELD_dsp340050b49a6c_fld3537DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3538DUAL_slot0", FIELD_dsp340050b49a6c_fld3538DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3539DUAL_slot0", FIELD_dsp340050b49a6c_fld3539DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3541DUAL_slot0", FIELD_dsp340050b49a6c_fld3541DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3542DUAL_slot0", FIELD_dsp340050b49a6c_fld3542DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3543DUAL_slot0", FIELD_dsp340050b49a6c_fld3543DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3544DUAL_slot0", FIELD_dsp340050b49a6c_fld3544DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3545DUAL_slot0", FIELD_dsp340050b49a6c_fld3545DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3546DUAL_slot0", FIELD_dsp340050b49a6c_fld3546DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3547DUAL_slot0", FIELD_dsp340050b49a6c_fld3547DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3548DUAL_slot0", FIELD_dsp340050b49a6c_fld3548DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3549DUAL_slot0", FIELD_dsp340050b49a6c_fld3549DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3550DUAL_slot0", FIELD_dsp340050b49a6c_fld3550DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3551DUAL_slot0", FIELD_dsp340050b49a6c_fld3551DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3552", FIELD_dsp340050b49a6c_fld3552, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3553DUAL_slot0", FIELD_dsp340050b49a6c_fld3553DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3554DUAL_slot0", FIELD_dsp340050b49a6c_fld3554DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3555DUAL_slot0", FIELD_dsp340050b49a6c_fld3555DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3556DUAL_slot0", FIELD_dsp340050b49a6c_fld3556DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3557DUAL_slot0", FIELD_dsp340050b49a6c_fld3557DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3558DUAL_slot0", FIELD_dsp340050b49a6c_fld3558DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3559DUAL_slot0", FIELD_dsp340050b49a6c_fld3559DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3560DUAL_slot0", FIELD_dsp340050b49a6c_fld3560DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3562DUAL_slot0", FIELD_dsp340050b49a6c_fld3562DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3563DUAL_slot0", FIELD_dsp340050b49a6c_fld3563DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3564DUAL_slot0", FIELD_dsp340050b49a6c_fld3564DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3565DUAL_slot0", FIELD_dsp340050b49a6c_fld3565DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3566DUAL_slot0", FIELD_dsp340050b49a6c_fld3566DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3567DUAL_slot0", FIELD_dsp340050b49a6c_fld3567DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3568DUAL_slot0", FIELD_dsp340050b49a6c_fld3568DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3569DUAL_slot0", FIELD_dsp340050b49a6c_fld3569DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3570DUAL_slot0", FIELD_dsp340050b49a6c_fld3570DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3571DUAL_slot0", FIELD_dsp340050b49a6c_fld3571DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3572DUAL_slot0", FIELD_dsp340050b49a6c_fld3572DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3573DUAL_slot0", FIELD_dsp340050b49a6c_fld3573DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3574DUAL_slot0", FIELD_dsp340050b49a6c_fld3574DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3575DUAL_slot0", FIELD_dsp340050b49a6c_fld3575DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3576DUAL_slot0", FIELD_dsp340050b49a6c_fld3576DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3577DUAL_slot0", FIELD_dsp340050b49a6c_fld3577DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3578DUAL_slot0", FIELD_dsp340050b49a6c_fld3578DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3579DUAL_slot0", FIELD_dsp340050b49a6c_fld3579DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3580DUAL_slot0", FIELD_dsp340050b49a6c_fld3580DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3581DUAL_slot0", FIELD_dsp340050b49a6c_fld3581DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3582DUAL_slot0", FIELD_dsp340050b49a6c_fld3582DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3583DUAL_slot0", FIELD_dsp340050b49a6c_fld3583DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3584", FIELD_dsp340050b49a6c_fld3584, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3585DUAL_slot0", FIELD_dsp340050b49a6c_fld3585DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3587DUAL_slot0", FIELD_dsp340050b49a6c_fld3587DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3588DUAL_slot0", FIELD_dsp340050b49a6c_fld3588DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3589DUAL_slot0", FIELD_dsp340050b49a6c_fld3589DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3590DUAL_slot0", FIELD_dsp340050b49a6c_fld3590DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3591DUAL_slot0", FIELD_dsp340050b49a6c_fld3591DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3592DUAL_slot0", FIELD_dsp340050b49a6c_fld3592DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3593DUAL_slot0", FIELD_dsp340050b49a6c_fld3593DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3594DUAL_slot0", FIELD_dsp340050b49a6c_fld3594DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3595DUAL_slot0", FIELD_dsp340050b49a6c_fld3595DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3596DUAL_slot0", FIELD_dsp340050b49a6c_fld3596DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3597DUAL_slot0", FIELD_dsp340050b49a6c_fld3597DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3598DUAL_slot0", FIELD_dsp340050b49a6c_fld3598DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3599DUAL_slot0", FIELD_dsp340050b49a6c_fld3599DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3600DUAL_slot0", FIELD_dsp340050b49a6c_fld3600DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3601DUAL_slot0", FIELD_dsp340050b49a6c_fld3601DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3602", FIELD_dsp340050b49a6c_fld3602, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3603DUAL_slot0", FIELD_dsp340050b49a6c_fld3603DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3604DUAL_slot0", FIELD_dsp340050b49a6c_fld3604DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3606DUAL_slot0", FIELD_dsp340050b49a6c_fld3606DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3607DUAL_slot0", FIELD_dsp340050b49a6c_fld3607DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3608DUAL_slot0", FIELD_dsp340050b49a6c_fld3608DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3609DUAL_slot0", FIELD_dsp340050b49a6c_fld3609DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3610", FIELD_dsp340050b49a6c_fld3610, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3611DUAL_slot0", FIELD_dsp340050b49a6c_fld3611DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3612DUAL_slot0", FIELD_dsp340050b49a6c_fld3612DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3613DUAL_slot0", FIELD_dsp340050b49a6c_fld3613DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3614DUAL_slot0", FIELD_dsp340050b49a6c_fld3614DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3615DUAL_slot0", FIELD_dsp340050b49a6c_fld3615DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3616DUAL_slot0", FIELD_dsp340050b49a6c_fld3616DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3618DUAL_slot0", FIELD_dsp340050b49a6c_fld3618DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3619", FIELD_dsp340050b49a6c_fld3619, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3620DUAL_slot0", FIELD_dsp340050b49a6c_fld3620DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3621DUAL_slot0", FIELD_dsp340050b49a6c_fld3621DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3622DUAL_slot0", FIELD_dsp340050b49a6c_fld3622DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3623DUAL_slot0", FIELD_dsp340050b49a6c_fld3623DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3624DUAL_slot0", FIELD_dsp340050b49a6c_fld3624DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3625DUAL_slot0", FIELD_dsp340050b49a6c_fld3625DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3626DUAL_slot0", FIELD_dsp340050b49a6c_fld3626DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3936DUAL_slot0", FIELD_dsp340050b49a6c_fld3936DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3937DUAL_slot0", FIELD_dsp340050b49a6c_fld3937DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3938DUAL_slot0", FIELD_dsp340050b49a6c_fld3938DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3939DUAL_slot0", FIELD_dsp340050b49a6c_fld3939DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3940DUAL_slot0", FIELD_dsp340050b49a6c_fld3940DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3941DUAL_slot0", FIELD_dsp340050b49a6c_fld3941DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3943DUAL_slot0", FIELD_dsp340050b49a6c_fld3943DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3945DUAL_slot0", FIELD_dsp340050b49a6c_fld3945DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3946DUAL_slot0", FIELD_dsp340050b49a6c_fld3946DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3947DUAL_slot0", FIELD_dsp340050b49a6c_fld3947DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3949DUAL_slot0", FIELD_dsp340050b49a6c_fld3949DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3950DUAL_slot0", FIELD_dsp340050b49a6c_fld3950DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3951DUAL_slot0", FIELD_dsp340050b49a6c_fld3951DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3952DUAL_slot0", FIELD_dsp340050b49a6c_fld3952DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3954DUAL_slot0", FIELD_dsp340050b49a6c_fld3954DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3957DUAL_slot0", FIELD_dsp340050b49a6c_fld3957DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3958DUAL_slot0", FIELD_dsp340050b49a6c_fld3958DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3959DUAL_slot0", FIELD_dsp340050b49a6c_fld3959DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3960DUAL_slot0", FIELD_dsp340050b49a6c_fld3960DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 }, + { "dsp340050b49a6c_fld3961DUAL_slot0", FIELD_dsp340050b49a6c_fld3961DUAL_slot0, -1, 0, 0, 0, 0, 0, 0 } +}; + +enum xtensa_operand_id { + OPERAND_soffsetx4, + OPERAND_uimm12x8, + OPERAND_simm4, + OPERAND_arr, + OPERAND_ars, + OPERAND__ars_invisible, + OPERAND_art, + OPERAND_ar0, + OPERAND_ar4, + OPERAND_ar8, + OPERAND_ar12, + OPERAND_ars_entry, + OPERAND_immrx4, + OPERAND_lsi4x4, + OPERAND_simm7, + OPERAND_uimm6, + OPERAND_ai4const, + OPERAND_b4const, + OPERAND_b4constu, + OPERAND_uimm8, + OPERAND_uimm8x2, + OPERAND_uimm8x4, + OPERAND_uimm4x16, + OPERAND_simm8, + OPERAND_simm8x256, + OPERAND_simm12b, + OPERAND_msalp32, + OPERAND_op2p1, + OPERAND_label8, + OPERAND_ulabel8, + OPERAND_label12, + OPERAND_soffset, + OPERAND_uimm16x4, + OPERAND_immt, + OPERAND_imms, + OPERAND_bt, + OPERAND_bs, + OPERAND_br, + OPERAND_bt2, + OPERAND_bs2, + OPERAND_br2, + OPERAND_bt4, + OPERAND_bs4, + OPERAND_br4, + OPERAND_bt8, + OPERAND_bs8, + OPERAND_br8, + OPERAND_bt16, + OPERAND_bs16, + OPERAND_br16, + OPERAND_brall, + OPERAND_tp7, + OPERAND_xt_wbr15_label, + OPERAND_xt_wbr18_label, + OPERAND_cimm8x4, + OPERAND_frr, + OPERAND_frs, + OPERAND_frt, + OPERAND_dsp340050b49a6c_oper45_reg, + OPERAND_dsp340050b49a6c_oper46_reg, + OPERAND_dsp340050b49a6c_oper47_reg, + OPERAND_dsp340050b49a6c_oper48_imm, + OPERAND_dsp340050b49a6c_oper49_imm, + OPERAND_dsp340050b49a6c_oper50_reg, + OPERAND_dsp340050b49a6c_oper51_reg, + OPERAND_dsp340050b49a6c_oper52_imm, + OPERAND_dsp340050b49a6c_oper53_reg, + OPERAND_dsp340050b49a6c_oper54_reg, + OPERAND_dsp340050b49a6c_oper55_reg, + OPERAND_dsp340050b49a6c_oper56_reg, + OPERAND_dsp340050b49a6c_oper57_imm, + OPERAND_dsp340050b49a6c_oper58_imm, + OPERAND_dsp340050b49a6c_oper59_imm, + OPERAND_dsp340050b49a6c_oper60_imm, + OPERAND_dsp340050b49a6c_oper61_imm, + OPERAND_dsp340050b49a6c_oper62_reg, + OPERAND_dsp340050b49a6c_oper63_reg, + OPERAND_dsp340050b49a6c_oper64_imm, + OPERAND_dsp340050b49a6c_oper65_reg, + OPERAND_dsp340050b49a6c_oper66_reg, + OPERAND_dsp340050b49a6c_oper67_reg, + OPERAND_dsp340050b49a6c_oper68_imm, + OPERAND_dsp340050b49a6c_oper69_imm, + OPERAND_dsp340050b49a6c_oper70_imm, + OPERAND_dsp340050b49a6c_oper71_reg, + OPERAND_dsp340050b49a6c_oper72_imm, + OPERAND_dsp340050b49a6c_oper73_imm, + OPERAND_dsp340050b49a6c_oper74_imm, + OPERAND_dsp340050b49a6c_oper75_imm, + OPERAND_dsp340050b49a6c_oper76_imm, + OPERAND_dsp340050b49a6c_oper77_reg, + OPERAND_dsp340050b49a6c_oper78_imm, + OPERAND_dsp340050b49a6c_oper79_reg, + OPERAND_dsp340050b49a6c_oper80_reg, + OPERAND_dsp340050b49a6c_oper81_reg, + OPERAND_dsp340050b49a6c_oper82_reg, + OPERAND_dsp340050b49a6c_oper83_imm, + OPERAND_dsp340050b49a6c_oper84_imm, + OPERAND_dsp340050b49a6c_oper85_imm, + OPERAND_dsp340050b49a6c_oper86_imm, + OPERAND_dsp340050b49a6c_oper87_imm, + OPERAND_dsp340050b49a6c_oper88_imm, + OPERAND_dsp340050b49a6c_oper89_imm, + OPERAND_t, + OPERAND_bbi4, + OPERAND_bbi, + OPERAND_imm12, + OPERAND_imm8, + OPERAND_s, + OPERAND_imm12b, + OPERAND_imm16, + OPERAND_m, + OPERAND_n, + OPERAND_offset, + OPERAND_op0, + OPERAND_op1, + OPERAND_op2, + OPERAND_r, + OPERAND_sa4, + OPERAND_sae4, + OPERAND_sae, + OPERAND_sal, + OPERAND_sargt, + OPERAND_sas4, + OPERAND_sas, + OPERAND_sr, + OPERAND_st, + OPERAND_thi3, + OPERAND_imm4, + OPERAND_mn, + OPERAND_i, + OPERAND_imm6lo, + OPERAND_imm6hi, + OPERAND_imm7lo, + OPERAND_imm7hi, + OPERAND_z, + OPERAND_imm6, + OPERAND_imm7, + OPERAND_t2, + OPERAND_s2, + OPERAND_r2, + OPERAND_t4, + OPERAND_s4, + OPERAND_r4, + OPERAND_t8, + OPERAND_s8, + OPERAND_r8, + OPERAND_xt_wbr15_imm, + OPERAND_xt_wbr18_imm, + OPERAND_fimm8, + OPERAND_dsp340050b49a6c_fld2019, + OPERAND_dsp340050b49a6c_fld2021, + OPERAND_dsp340050b49a6c_fld2029, + OPERAND_dsp340050b49a6c_fld2030, + OPERAND_dsp340050b49a6c_fld2032, + OPERAND_dsp340050b49a6c_fld2035, + OPERAND_dsp340050b49a6c_fld2036, + OPERAND_dsp340050b49a6c_fld2037, + OPERAND_dsp340050b49a6c_fld2038, + OPERAND_dsp340050b49a6c_fld2039, + OPERAND_dsp340050b49a6c_fld2040, + OPERAND_dsp340050b49a6c_fld2041, + OPERAND_dsp340050b49a6c_fld2042, + OPERAND_dsp340050b49a6c_fld2043, + OPERAND_dsp340050b49a6c_fld2044, + OPERAND_dsp340050b49a6c_fld2045, + OPERAND_dsp340050b49a6c_fld2046, + OPERAND_dsp340050b49a6c_fld2047, + OPERAND_dsp340050b49a6c_fld2048, + OPERAND_dsp340050b49a6c_fld2049, + OPERAND_dsp340050b49a6c_fld2050, + OPERAND_dsp340050b49a6c_fld2051, + OPERAND_dsp340050b49a6c_fld2052, + OPERAND_dsp340050b49a6c_fld2053, + OPERAND_dsp340050b49a6c_fld2054, + OPERAND_dsp340050b49a6c_fld2055, + OPERAND_dsp340050b49a6c_fld2056, + OPERAND_dsp340050b49a6c_fld2082Inst, + OPERAND_dsp340050b49a6c_fld2083Inst, + OPERAND_dsp340050b49a6c_fld2084Inst, + OPERAND_dsp340050b49a6c_fld2085Inst, + OPERAND_dsp340050b49a6c_fld2086Inst, + OPERAND_dsp340050b49a6c_fld2088Inst, + OPERAND_dsp340050b49a6c_fld2089Inst, + OPERAND_dsp340050b49a6c_fld2090Inst, + OPERAND_dsp340050b49a6c_fld2091Inst, + OPERAND_dsp340050b49a6c_fld2092Inst, + OPERAND_dsp340050b49a6c_fld2094Inst, + OPERAND_dsp340050b49a6c_fld2095Inst, + OPERAND_dsp340050b49a6c_fld2096Inst, + OPERAND_dsp340050b49a6c_fld2098Inst, + OPERAND_dsp340050b49a6c_fld2099Inst, + OPERAND_dsp340050b49a6c_fld2100Inst, + OPERAND_dsp340050b49a6c_fld2101Inst, + OPERAND_dsp340050b49a6c_fld2102Inst, + OPERAND_dsp340050b49a6c_fld2103Inst, + OPERAND_dsp340050b49a6c_fld2104Inst, + OPERAND_dsp340050b49a6c_fld2105Inst, + OPERAND_dsp340050b49a6c_fld2106Inst, + OPERAND_dsp340050b49a6c_fld2107Inst, + OPERAND_dsp340050b49a6c_fld2108Inst, + OPERAND_dsp340050b49a6c_fld2109Inst, + OPERAND_dsp340050b49a6c_fld2110Inst, + OPERAND_dsp340050b49a6c_fld2111Inst, + OPERAND_dsp340050b49a6c_fld2112Inst, + OPERAND_dsp340050b49a6c_fld2113Inst, + OPERAND_dsp340050b49a6c_fld2114Inst, + OPERAND_dsp340050b49a6c_fld2115Inst, + OPERAND_dsp340050b49a6c_fld2116Inst, + OPERAND_dsp340050b49a6c_fld2117Inst, + OPERAND_dsp340050b49a6c_fld2118Inst, + OPERAND_dsp340050b49a6c_fld2119Inst, + OPERAND_dsp340050b49a6c_fld2120Inst, + OPERAND_dsp340050b49a6c_fld2122Inst, + OPERAND_dsp340050b49a6c_fld2123Inst, + OPERAND_dsp340050b49a6c_fld2124Inst, + OPERAND_dsp340050b49a6c_fld2125Inst, + OPERAND_dsp340050b49a6c_fld2126Inst, + OPERAND_dsp340050b49a6c_fld2127Inst, + OPERAND_dsp340050b49a6c_fld2128Inst, + OPERAND_dsp340050b49a6c_fld2129Inst, + OPERAND_dsp340050b49a6c_fld2131Inst, + OPERAND_dsp340050b49a6c_fld2132Inst, + OPERAND_dsp340050b49a6c_fld2133Inst, + OPERAND_dsp340050b49a6c_fld2134Inst, + OPERAND_dsp340050b49a6c_fld2136Inst, + OPERAND_dsp340050b49a6c_fld2137Inst, + OPERAND_dsp340050b49a6c_fld2138Inst, + OPERAND_dsp340050b49a6c_fld2139Inst, + OPERAND_dsp340050b49a6c_fld2140Inst, + OPERAND_dsp340050b49a6c_fld2141Inst, + OPERAND_dsp340050b49a6c_fld2142Inst, + OPERAND_dsp340050b49a6c_fld2143Inst, + OPERAND_dsp340050b49a6c_fld2144Inst, + OPERAND_dsp340050b49a6c_fld2145Inst, + OPERAND_dsp340050b49a6c_fld2146Inst, + OPERAND_dsp340050b49a6c_fld2147Inst, + OPERAND_dsp340050b49a6c_fld2149Inst, + OPERAND_dsp340050b49a6c_fld2151Inst, + OPERAND_dsp340050b49a6c_fld2153Inst, + OPERAND_dsp340050b49a6c_fld2154Inst, + OPERAND_dsp340050b49a6c_fld2155Inst, + OPERAND_dsp340050b49a6c_fld2156Inst, + OPERAND_dsp340050b49a6c_fld2157Inst, + OPERAND_dsp340050b49a6c_fld2158Inst, + OPERAND_dsp340050b49a6c_fld2159Inst, + OPERAND_dsp340050b49a6c_fld2160Inst, + OPERAND_dsp340050b49a6c_fld2161Inst, + OPERAND_dsp340050b49a6c_fld2162Inst, + OPERAND_dsp340050b49a6c_fld2163Inst, + OPERAND_dsp340050b49a6c_fld2164Inst, + OPERAND_dsp340050b49a6c_fld2165Inst, + OPERAND_dsp340050b49a6c_fld2166Inst, + OPERAND_dsp340050b49a6c_fld2167Inst, + OPERAND_dsp340050b49a6c_fld2168Inst, + OPERAND_dsp340050b49a6c_fld2169Inst, + OPERAND_dsp340050b49a6c_fld2171Inst, + OPERAND_dsp340050b49a6c_fld2172Inst, + OPERAND_dsp340050b49a6c_fld2173Inst, + OPERAND_dsp340050b49a6c_fld2174Inst, + OPERAND_dsp340050b49a6c_fld2175Inst, + OPERAND_dsp340050b49a6c_fld2177Inst, + OPERAND_dsp340050b49a6c_fld2178Inst, + OPERAND_dsp340050b49a6c_fld2179Inst, + OPERAND_dsp340050b49a6c_fld2180Inst, + OPERAND_dsp340050b49a6c_fld2181Inst, + OPERAND_dsp340050b49a6c_fld2182Inst, + OPERAND_dsp340050b49a6c_fld2183Inst, + OPERAND_dsp340050b49a6c_fld2184Inst, + OPERAND_dsp340050b49a6c_fld2185Inst, + OPERAND_dsp340050b49a6c_fld2186Inst, + OPERAND_dsp340050b49a6c_fld2187Inst, + OPERAND_dsp340050b49a6c_fld2188Inst, + OPERAND_dsp340050b49a6c_fld2189Inst, + OPERAND_dsp340050b49a6c_fld2190Inst, + OPERAND_dsp340050b49a6c_fld2191Inst, + OPERAND_dsp340050b49a6c_fld2192Inst, + OPERAND_dsp340050b49a6c_fld2193Inst, + OPERAND_dsp340050b49a6c_fld2194Inst, + OPERAND_dsp340050b49a6c_fld2195Inst, + OPERAND_dsp340050b49a6c_fld2196Inst, + OPERAND_dsp340050b49a6c_fld2197Inst, + OPERAND_dsp340050b49a6c_fld2198Inst, + OPERAND_dsp340050b49a6c_fld2199Inst, + OPERAND_dsp340050b49a6c_fld2200Inst, + OPERAND_dsp340050b49a6c_fld2201Inst, + OPERAND_dsp340050b49a6c_fld2202Inst, + OPERAND_dsp340050b49a6c_fld2203Inst, + OPERAND_dsp340050b49a6c_fld2204Inst, + OPERAND_dsp340050b49a6c_fld2205Inst, + OPERAND_dsp340050b49a6c_fld2206Inst, + OPERAND_dsp340050b49a6c_fld2207Inst, + OPERAND_dsp340050b49a6c_fld2208Inst, + OPERAND_dsp340050b49a6c_fld2209Inst, + OPERAND_dsp340050b49a6c_fld2210Inst, + OPERAND_dsp340050b49a6c_fld2211Inst, + OPERAND_dsp340050b49a6c_fld2212Inst, + OPERAND_dsp340050b49a6c_fld2213Inst, + OPERAND_dsp340050b49a6c_fld2214Inst, + OPERAND_dsp340050b49a6c_fld2215Inst, + OPERAND_dsp340050b49a6c_fld2216Inst, + OPERAND_dsp340050b49a6c_fld2217Inst, + OPERAND_dsp340050b49a6c_fld2218Inst, + OPERAND_dsp340050b49a6c_fld2219Inst, + OPERAND_dsp340050b49a6c_fld2220Inst, + OPERAND_dsp340050b49a6c_fld2221Inst, + OPERAND_dsp340050b49a6c_fld2222Inst, + OPERAND_dsp340050b49a6c_fld2223Inst, + OPERAND_dsp340050b49a6c_fld2224Inst, + OPERAND_dsp340050b49a6c_fld2225Inst, + OPERAND_dsp340050b49a6c_fld2226Inst, + OPERAND_dsp340050b49a6c_fld2227Inst, + OPERAND_dsp340050b49a6c_fld2228Inst, + OPERAND_dsp340050b49a6c_fld2229Inst, + OPERAND_dsp340050b49a6c_fld2230Inst, + OPERAND_dsp340050b49a6c_fld2231Inst, + OPERAND_dsp340050b49a6c_fld2232Inst, + OPERAND_dsp340050b49a6c_fld2234Inst, + OPERAND_dsp340050b49a6c_fld2235Inst, + OPERAND_dsp340050b49a6c_fld2236Inst, + OPERAND_dsp340050b49a6c_fld2237Inst, + OPERAND_dsp340050b49a6c_fld2238Inst, + OPERAND_dsp340050b49a6c_fld2239Inst, + OPERAND_dsp340050b49a6c_fld2240Inst, + OPERAND_dsp340050b49a6c_fld2241Inst, + OPERAND_dsp340050b49a6c_fld2242Inst, + OPERAND_dsp340050b49a6c_fld2243Inst, + OPERAND_dsp340050b49a6c_fld2244Inst, + OPERAND_dsp340050b49a6c_fld2245Inst, + OPERAND_dsp340050b49a6c_fld2246Inst, + OPERAND_dsp340050b49a6c_fld2247Inst, + OPERAND_dsp340050b49a6c_fld2248Inst, + OPERAND_dsp340050b49a6c_fld2249Inst, + OPERAND_dsp340050b49a6c_fld2250Inst, + OPERAND_dsp340050b49a6c_fld2251Inst, + OPERAND_dsp340050b49a6c_fld2252Inst, + OPERAND_dsp340050b49a6c_fld2253Inst, + OPERAND_dsp340050b49a6c_fld2254, + OPERAND_dsp340050b49a6c_fld2255Inst, + OPERAND_dsp340050b49a6c_fld2257Inst, + OPERAND_dsp340050b49a6c_fld3627Inst, + OPERAND_dsp340050b49a6c_fld3630Inst, + OPERAND_dsp340050b49a6c_fld3631Inst, + OPERAND_dsp340050b49a6c_fld3633Inst, + OPERAND_dsp340050b49a6c_fld3634, + OPERAND_dsp340050b49a6c_fld3635Inst, + OPERAND_dsp340050b49a6c_fld3636Inst, + OPERAND_dsp340050b49a6c_fld3637Inst, + OPERAND_dsp340050b49a6c_fld3638Inst, + OPERAND_dsp340050b49a6c_fld3639Inst, + OPERAND_dsp340050b49a6c_fld3640Inst, + OPERAND_dsp340050b49a6c_fld3642Inst, + OPERAND_dsp340050b49a6c_fld3643Inst, + OPERAND_dsp340050b49a6c_fld3644Inst, + OPERAND_dsp340050b49a6c_fld3645Inst, + OPERAND_dsp340050b49a6c_fld3647Inst, + OPERAND_dsp340050b49a6c_fld3648Inst, + OPERAND_dsp340050b49a6c_fld3649Inst, + OPERAND_dsp340050b49a6c_fld3650Inst, + OPERAND_dsp340050b49a6c_fld3651Inst, + OPERAND_dsp340050b49a6c_fld3653Inst, + OPERAND_dsp340050b49a6c_fld3654Inst, + OPERAND_dsp340050b49a6c_fld3655Inst, + OPERAND_dsp340050b49a6c_fld3656Inst, + OPERAND_dsp340050b49a6c_fld3657Inst, + OPERAND_dsp340050b49a6c_fld3658Inst, + OPERAND_dsp340050b49a6c_fld3659Inst, + OPERAND_dsp340050b49a6c_fld3660Inst, + OPERAND_dsp340050b49a6c_fld3661Inst, + OPERAND_dsp340050b49a6c_fld3662Inst, + OPERAND_op0_s3, + OPERAND_dsp340050b49a6c_fld2025, + OPERAND_dsp340050b49a6c_fld2027, + OPERAND_dsp340050b49a6c_fld2258GP_slot2, + OPERAND_dsp340050b49a6c_fld2259GP_slot2, + OPERAND_dsp340050b49a6c_fld2260GP_slot2, + OPERAND_dsp340050b49a6c_fld2261GP_slot2, + OPERAND_dsp340050b49a6c_fld2262GP_slot2, + OPERAND_dsp340050b49a6c_fld2263GP_slot2, + OPERAND_dsp340050b49a6c_fld2264GP_slot2, + OPERAND_dsp340050b49a6c_fld2266GP_slot2, + OPERAND_dsp340050b49a6c_fld2267GP_slot2, + OPERAND_dsp340050b49a6c_fld2268GP_slot2, + OPERAND_dsp340050b49a6c_fld2269GP_slot2, + OPERAND_dsp340050b49a6c_fld2270GP_slot2, + OPERAND_dsp340050b49a6c_fld2271GP_slot2, + OPERAND_dsp340050b49a6c_fld2272, + OPERAND_dsp340050b49a6c_fld2273GP_slot2, + OPERAND_dsp340050b49a6c_fld2274GP_slot2, + OPERAND_dsp340050b49a6c_fld2275GP_slot2, + OPERAND_dsp340050b49a6c_fld2277GP_slot2, + OPERAND_dsp340050b49a6c_fld2278GP_slot2, + OPERAND_dsp340050b49a6c_fld2279GP_slot2, + OPERAND_dsp340050b49a6c_fld2280GP_slot2, + OPERAND_dsp340050b49a6c_fld2281GP_slot2, + OPERAND_dsp340050b49a6c_fld2282GP_slot2, + OPERAND_dsp340050b49a6c_fld2283GP_slot2, + OPERAND_dsp340050b49a6c_fld2284GP_slot2, + OPERAND_dsp340050b49a6c_fld2286GP_slot2, + OPERAND_dsp340050b49a6c_fld2287GP_slot2, + OPERAND_dsp340050b49a6c_fld2288GP_slot2, + OPERAND_dsp340050b49a6c_fld2289GP_slot2, + OPERAND_dsp340050b49a6c_fld2290GP_slot2, + OPERAND_dsp340050b49a6c_fld2291GP_slot2, + OPERAND_dsp340050b49a6c_fld2292GP_slot2, + OPERAND_dsp340050b49a6c_fld2293GP_slot2, + OPERAND_dsp340050b49a6c_fld2294GP_slot2, + OPERAND_dsp340050b49a6c_fld2295GP_slot2, + OPERAND_dsp340050b49a6c_fld2296GP_slot2, + OPERAND_dsp340050b49a6c_fld2297GP_slot2, + OPERAND_dsp340050b49a6c_fld2298GP_slot2, + OPERAND_dsp340050b49a6c_fld2299GP_slot2, + OPERAND_dsp340050b49a6c_fld2300GP_slot2, + OPERAND_dsp340050b49a6c_fld2301GP_slot2, + OPERAND_dsp340050b49a6c_fld2302, + OPERAND_dsp340050b49a6c_fld2303GP_slot2, + OPERAND_dsp340050b49a6c_fld2304GP_slot2, + OPERAND_dsp340050b49a6c_fld2305, + OPERAND_dsp340050b49a6c_fld2306GP_slot2, + OPERAND_dsp340050b49a6c_fld2308GP_slot2, + OPERAND_dsp340050b49a6c_fld2309GP_slot2, + OPERAND_dsp340050b49a6c_fld2310GP_slot2, + OPERAND_dsp340050b49a6c_fld2312GP_slot2, + OPERAND_dsp340050b49a6c_fld2313, + OPERAND_dsp340050b49a6c_fld2314GP_slot2, + OPERAND_dsp340050b49a6c_fld2316GP_slot2, + OPERAND_dsp340050b49a6c_fld2317GP_slot2, + OPERAND_dsp340050b49a6c_fld2318GP_slot2, + OPERAND_dsp340050b49a6c_fld2319GP_slot2, + OPERAND_dsp340050b49a6c_fld2320GP_slot2, + OPERAND_dsp340050b49a6c_fld2321GP_slot2, + OPERAND_dsp340050b49a6c_fld2322GP_slot2, + OPERAND_dsp340050b49a6c_fld2323GP_slot2, + OPERAND_dsp340050b49a6c_fld2324GP_slot2, + OPERAND_dsp340050b49a6c_fld2325GP_slot2, + OPERAND_dsp340050b49a6c_fld2326GP_slot2, + OPERAND_dsp340050b49a6c_fld2327GP_slot2, + OPERAND_dsp340050b49a6c_fld2328GP_slot2, + OPERAND_dsp340050b49a6c_fld2329GP_slot2, + OPERAND_dsp340050b49a6c_fld2330GP_slot2, + OPERAND_dsp340050b49a6c_fld2331GP_slot2, + OPERAND_dsp340050b49a6c_fld2332GP_slot2, + OPERAND_dsp340050b49a6c_fld2333GP_slot2, + OPERAND_dsp340050b49a6c_fld2334GP_slot2, + OPERAND_dsp340050b49a6c_fld2335GP_slot2, + OPERAND_dsp340050b49a6c_fld2336GP_slot2, + OPERAND_dsp340050b49a6c_fld2337GP_slot2, + OPERAND_dsp340050b49a6c_fld2338GP_slot2, + OPERAND_dsp340050b49a6c_fld2339GP_slot2, + OPERAND_dsp340050b49a6c_fld2340GP_slot2, + OPERAND_dsp340050b49a6c_fld2341GP_slot2, + OPERAND_dsp340050b49a6c_fld2342GP_slot2, + OPERAND_dsp340050b49a6c_fld2343GP_slot2, + OPERAND_dsp340050b49a6c_fld2344GP_slot2, + OPERAND_dsp340050b49a6c_fld2345GP_slot2, + OPERAND_dsp340050b49a6c_fld2346GP_slot2, + OPERAND_dsp340050b49a6c_fld2347GP_slot2, + OPERAND_dsp340050b49a6c_fld2348GP_slot2, + OPERAND_dsp340050b49a6c_fld2349GP_slot2, + OPERAND_dsp340050b49a6c_fld2350GP_slot2, + OPERAND_dsp340050b49a6c_fld2351GP_slot2, + OPERAND_dsp340050b49a6c_fld2352GP_slot2, + OPERAND_dsp340050b49a6c_fld2353GP_slot2, + OPERAND_dsp340050b49a6c_fld2354GP_slot2, + OPERAND_dsp340050b49a6c_fld2355GP_slot2, + OPERAND_dsp340050b49a6c_fld2356GP_slot2, + OPERAND_dsp340050b49a6c_fld2357GP_slot2, + OPERAND_dsp340050b49a6c_fld2358GP_slot2, + OPERAND_dsp340050b49a6c_fld2359GP_slot2, + OPERAND_dsp340050b49a6c_fld2361GP_slot2, + OPERAND_dsp340050b49a6c_fld2362GP_slot2, + OPERAND_dsp340050b49a6c_fld2364GP_slot2, + OPERAND_dsp340050b49a6c_fld2366GP_slot2, + OPERAND_dsp340050b49a6c_fld2368GP_slot2, + OPERAND_dsp340050b49a6c_fld2369GP_slot2, + OPERAND_dsp340050b49a6c_fld2370GP_slot2, + OPERAND_dsp340050b49a6c_fld2371GP_slot2, + OPERAND_dsp340050b49a6c_fld2372GP_slot2, + OPERAND_dsp340050b49a6c_fld2373GP_slot2, + OPERAND_dsp340050b49a6c_fld2374GP_slot2, + OPERAND_dsp340050b49a6c_fld2375GP_slot2, + OPERAND_dsp340050b49a6c_fld2376GP_slot2, + OPERAND_dsp340050b49a6c_fld2378GP_slot2, + OPERAND_dsp340050b49a6c_fld2379GP_slot2, + OPERAND_dsp340050b49a6c_fld2381GP_slot2, + OPERAND_dsp340050b49a6c_fld2383GP_slot2, + OPERAND_dsp340050b49a6c_fld2384, + OPERAND_dsp340050b49a6c_fld2385GP_slot2, + OPERAND_dsp340050b49a6c_fld2386, + OPERAND_dsp340050b49a6c_fld2387GP_slot2, + OPERAND_dsp340050b49a6c_fld2388GP_slot2, + OPERAND_dsp340050b49a6c_fld2389GP_slot2, + OPERAND_dsp340050b49a6c_fld3663GP_slot2, + OPERAND_dsp340050b49a6c_fld3664GP_slot2, + OPERAND_dsp340050b49a6c_fld3665GP_slot2, + OPERAND_dsp340050b49a6c_fld3666, + OPERAND_dsp340050b49a6c_fld3667GP_slot2, + OPERAND_dsp340050b49a6c_fld3668GP_slot2, + OPERAND_dsp340050b49a6c_fld3669GP_slot2, + OPERAND_dsp340050b49a6c_fld3670GP_slot2, + OPERAND_dsp340050b49a6c_fld3671GP_slot2, + OPERAND_dsp340050b49a6c_fld3673GP_slot2, + OPERAND_dsp340050b49a6c_fld3674GP_slot2, + OPERAND_dsp340050b49a6c_fld3675GP_slot2, + OPERAND_dsp340050b49a6c_fld3676GP_slot2, + OPERAND_dsp340050b49a6c_fld3678GP_slot2, + OPERAND_dsp340050b49a6c_fld3679GP_slot2, + OPERAND_dsp340050b49a6c_fld3680GP_slot2, + OPERAND_op0_s4, + OPERAND_dsp340050b49a6c_fld2026, + OPERAND_dsp340050b49a6c_fld2031, + OPERAND_dsp340050b49a6c_fld2394GP_slot1, + OPERAND_dsp340050b49a6c_fld2395GP_slot1, + OPERAND_dsp340050b49a6c_fld2397GP_slot1, + OPERAND_dsp340050b49a6c_fld2398GP_slot1, + OPERAND_dsp340050b49a6c_fld2399GP_slot1, + OPERAND_dsp340050b49a6c_fld2400GP_slot1, + OPERAND_dsp340050b49a6c_fld2402GP_slot1, + OPERAND_dsp340050b49a6c_fld2403GP_slot1, + OPERAND_dsp340050b49a6c_fld2405GP_slot1, + OPERAND_dsp340050b49a6c_fld3681GP_slot1, + OPERAND_dsp340050b49a6c_fld3683GP_slot1, + OPERAND_dsp340050b49a6c_fld3684GP_slot1, + OPERAND_dsp340050b49a6c_fld3686GP_slot1, + OPERAND_op0_s5, + OPERAND_dsp340050b49a6c_fld2058, + OPERAND_dsp340050b49a6c_fld2067, + OPERAND_dsp340050b49a6c_fld2407GP_slot0, + OPERAND_dsp340050b49a6c_fld2409GP_slot0, + OPERAND_dsp340050b49a6c_fld2410GP_slot0, + OPERAND_dsp340050b49a6c_fld2411GP_slot0, + OPERAND_dsp340050b49a6c_fld2412GP_slot0, + OPERAND_dsp340050b49a6c_fld2413GP_slot0, + OPERAND_dsp340050b49a6c_fld2415GP_slot0, + OPERAND_dsp340050b49a6c_fld2416GP_slot0, + OPERAND_dsp340050b49a6c_fld2417GP_slot0, + OPERAND_dsp340050b49a6c_fld2418GP_slot0, + OPERAND_dsp340050b49a6c_fld2419GP_slot0, + OPERAND_dsp340050b49a6c_fld2420GP_slot0, + OPERAND_dsp340050b49a6c_fld2422GP_slot0, + OPERAND_dsp340050b49a6c_fld2423GP_slot0, + OPERAND_dsp340050b49a6c_fld2424GP_slot0, + OPERAND_dsp340050b49a6c_fld2425GP_slot0, + OPERAND_dsp340050b49a6c_fld2426GP_slot0, + OPERAND_dsp340050b49a6c_fld2427GP_slot0, + OPERAND_dsp340050b49a6c_fld2429GP_slot0, + OPERAND_dsp340050b49a6c_fld2430GP_slot0, + OPERAND_dsp340050b49a6c_fld2431GP_slot0, + OPERAND_dsp340050b49a6c_fld2432GP_slot0, + OPERAND_dsp340050b49a6c_fld2433GP_slot0, + OPERAND_dsp340050b49a6c_fld2434GP_slot0, + OPERAND_dsp340050b49a6c_fld2435GP_slot0, + OPERAND_dsp340050b49a6c_fld2436GP_slot0, + OPERAND_dsp340050b49a6c_fld2437GP_slot0, + OPERAND_dsp340050b49a6c_fld2438GP_slot0, + OPERAND_dsp340050b49a6c_fld2439GP_slot0, + OPERAND_dsp340050b49a6c_fld2440GP_slot0, + OPERAND_dsp340050b49a6c_fld2441GP_slot0, + OPERAND_dsp340050b49a6c_fld2443GP_slot0, + OPERAND_dsp340050b49a6c_fld2444GP_slot0, + OPERAND_dsp340050b49a6c_fld2445, + OPERAND_dsp340050b49a6c_fld2447GP_slot0, + OPERAND_dsp340050b49a6c_fld2448, + OPERAND_dsp340050b49a6c_fld2449GP_slot0, + OPERAND_dsp340050b49a6c_fld2451GP_slot0, + OPERAND_dsp340050b49a6c_fld2452GP_slot0, + OPERAND_dsp340050b49a6c_fld2453GP_slot0, + OPERAND_dsp340050b49a6c_fld2454GP_slot0, + OPERAND_dsp340050b49a6c_fld2455GP_slot0, + OPERAND_dsp340050b49a6c_fld2456GP_slot0, + OPERAND_dsp340050b49a6c_fld2457GP_slot0, + OPERAND_dsp340050b49a6c_fld2458GP_slot0, + OPERAND_dsp340050b49a6c_fld2459GP_slot0, + OPERAND_dsp340050b49a6c_fld2460GP_slot0, + OPERAND_dsp340050b49a6c_fld2461GP_slot0, + OPERAND_dsp340050b49a6c_fld2462, + OPERAND_dsp340050b49a6c_fld2463GP_slot0, + OPERAND_dsp340050b49a6c_fld2464GP_slot0, + OPERAND_dsp340050b49a6c_fld2465GP_slot0, + OPERAND_dsp340050b49a6c_fld2466GP_slot0, + OPERAND_dsp340050b49a6c_fld2467GP_slot0, + OPERAND_dsp340050b49a6c_fld2468GP_slot0, + OPERAND_dsp340050b49a6c_fld2470GP_slot0, + OPERAND_dsp340050b49a6c_fld2471GP_slot0, + OPERAND_dsp340050b49a6c_fld2472GP_slot0, + OPERAND_dsp340050b49a6c_fld2473GP_slot0, + OPERAND_dsp340050b49a6c_fld2474GP_slot0, + OPERAND_dsp340050b49a6c_fld2475GP_slot0, + OPERAND_dsp340050b49a6c_fld2477GP_slot0, + OPERAND_dsp340050b49a6c_fld2479GP_slot0, + OPERAND_dsp340050b49a6c_fld2480GP_slot0, + OPERAND_dsp340050b49a6c_fld2481GP_slot0, + OPERAND_dsp340050b49a6c_fld2482GP_slot0, + OPERAND_dsp340050b49a6c_fld2483GP_slot0, + OPERAND_dsp340050b49a6c_fld2484GP_slot0, + OPERAND_dsp340050b49a6c_fld2485GP_slot0, + OPERAND_dsp340050b49a6c_fld2486GP_slot0, + OPERAND_dsp340050b49a6c_fld2487GP_slot0, + OPERAND_dsp340050b49a6c_fld2488GP_slot0, + OPERAND_dsp340050b49a6c_fld2489GP_slot0, + OPERAND_dsp340050b49a6c_fld2490GP_slot0, + OPERAND_dsp340050b49a6c_fld2491GP_slot0, + OPERAND_dsp340050b49a6c_fld2492GP_slot0, + OPERAND_dsp340050b49a6c_fld2493GP_slot0, + OPERAND_dsp340050b49a6c_fld2494GP_slot0, + OPERAND_dsp340050b49a6c_fld2495GP_slot0, + OPERAND_dsp340050b49a6c_fld2496GP_slot0, + OPERAND_dsp340050b49a6c_fld2497GP_slot0, + OPERAND_dsp340050b49a6c_fld2498GP_slot0, + OPERAND_dsp340050b49a6c_fld2499GP_slot0, + OPERAND_dsp340050b49a6c_fld2500GP_slot0, + OPERAND_dsp340050b49a6c_fld2501GP_slot0, + OPERAND_dsp340050b49a6c_fld2502GP_slot0, + OPERAND_dsp340050b49a6c_fld2503GP_slot0, + OPERAND_dsp340050b49a6c_fld2504GP_slot0, + OPERAND_dsp340050b49a6c_fld2505GP_slot0, + OPERAND_dsp340050b49a6c_fld2506GP_slot0, + OPERAND_dsp340050b49a6c_fld2507GP_slot0, + OPERAND_dsp340050b49a6c_fld2508GP_slot0, + OPERAND_dsp340050b49a6c_fld2509GP_slot0, + OPERAND_dsp340050b49a6c_fld2510GP_slot0, + OPERAND_dsp340050b49a6c_fld2512GP_slot0, + OPERAND_dsp340050b49a6c_fld2514GP_slot0, + OPERAND_dsp340050b49a6c_fld2515GP_slot0, + OPERAND_dsp340050b49a6c_fld2516GP_slot0, + OPERAND_dsp340050b49a6c_fld2517GP_slot0, + OPERAND_dsp340050b49a6c_fld2518GP_slot0, + OPERAND_dsp340050b49a6c_fld2519GP_slot0, + OPERAND_dsp340050b49a6c_fld2520GP_slot0, + OPERAND_dsp340050b49a6c_fld2521GP_slot0, + OPERAND_dsp340050b49a6c_fld2523GP_slot0, + OPERAND_dsp340050b49a6c_fld2524GP_slot0, + OPERAND_dsp340050b49a6c_fld2526GP_slot0, + OPERAND_dsp340050b49a6c_fld2527GP_slot0, + OPERAND_dsp340050b49a6c_fld2528GP_slot0, + OPERAND_dsp340050b49a6c_fld2529GP_slot0, + OPERAND_dsp340050b49a6c_fld2530, + OPERAND_dsp340050b49a6c_fld2531GP_slot0, + OPERAND_dsp340050b49a6c_fld3688GP_slot0, + OPERAND_dsp340050b49a6c_fld3689GP_slot0, + OPERAND_dsp340050b49a6c_fld3690GP_slot0, + OPERAND_dsp340050b49a6c_fld3691GP_slot0, + OPERAND_dsp340050b49a6c_fld3692GP_slot0, + OPERAND_dsp340050b49a6c_fld3693GP_slot0, + OPERAND_dsp340050b49a6c_fld3695GP_slot0, + OPERAND_dsp340050b49a6c_fld3696GP_slot0, + OPERAND_dsp340050b49a6c_fld3697GP_slot0, + OPERAND_dsp340050b49a6c_fld3698GP_slot0, + OPERAND_dsp340050b49a6c_fld3699GP_slot0, + OPERAND_dsp340050b49a6c_fld3700GP_slot0, + OPERAND_dsp340050b49a6c_fld3702GP_slot0, + OPERAND_dsp340050b49a6c_fld3703GP_slot0, + OPERAND_dsp340050b49a6c_fld3705GP_slot0, + OPERAND_dsp340050b49a6c_fld3706GP_slot0, + OPERAND_op0_s6, + OPERAND_dsp340050b49a6c_fld2532DOT_slot2, + OPERAND_dsp340050b49a6c_fld2533DOT_slot2, + OPERAND_dsp340050b49a6c_fld2534DOT_slot2, + OPERAND_dsp340050b49a6c_fld2535DOT_slot2, + OPERAND_dsp340050b49a6c_fld2536DOT_slot2, + OPERAND_dsp340050b49a6c_fld2537DOT_slot2, + OPERAND_dsp340050b49a6c_fld2538DOT_slot2, + OPERAND_dsp340050b49a6c_fld2539DOT_slot2, + OPERAND_dsp340050b49a6c_fld2540DOT_slot2, + OPERAND_dsp340050b49a6c_fld2541DOT_slot2, + OPERAND_dsp340050b49a6c_fld2542DOT_slot2, + OPERAND_dsp340050b49a6c_fld2543DOT_slot2, + OPERAND_dsp340050b49a6c_fld2544DOT_slot2, + OPERAND_dsp340050b49a6c_fld2545DOT_slot2, + OPERAND_dsp340050b49a6c_fld2546DOT_slot2, + OPERAND_dsp340050b49a6c_fld2547DOT_slot2, + OPERAND_dsp340050b49a6c_fld2548DOT_slot2, + OPERAND_dsp340050b49a6c_fld2549DOT_slot2, + OPERAND_dsp340050b49a6c_fld2550DOT_slot2, + OPERAND_dsp340050b49a6c_fld2551DOT_slot2, + OPERAND_dsp340050b49a6c_fld2552DOT_slot2, + OPERAND_dsp340050b49a6c_fld2553DOT_slot2, + OPERAND_dsp340050b49a6c_fld2554DOT_slot2, + OPERAND_dsp340050b49a6c_fld2555DOT_slot2, + OPERAND_dsp340050b49a6c_fld2556DOT_slot2, + OPERAND_dsp340050b49a6c_fld2557DOT_slot2, + OPERAND_dsp340050b49a6c_fld2558DOT_slot2, + OPERAND_dsp340050b49a6c_fld2559DOT_slot2, + OPERAND_dsp340050b49a6c_fld2560DOT_slot2, + OPERAND_dsp340050b49a6c_fld2561DOT_slot2, + OPERAND_dsp340050b49a6c_fld2562DOT_slot2, + OPERAND_dsp340050b49a6c_fld2563DOT_slot2, + OPERAND_dsp340050b49a6c_fld2564DOT_slot2, + OPERAND_dsp340050b49a6c_fld2565DOT_slot2, + OPERAND_dsp340050b49a6c_fld2566DOT_slot2, + OPERAND_dsp340050b49a6c_fld2567DOT_slot2, + OPERAND_dsp340050b49a6c_fld2568DOT_slot2, + OPERAND_dsp340050b49a6c_fld2569DOT_slot2, + OPERAND_dsp340050b49a6c_fld2571DOT_slot2, + OPERAND_dsp340050b49a6c_fld2572DOT_slot2, + OPERAND_dsp340050b49a6c_fld2573DOT_slot2, + OPERAND_dsp340050b49a6c_fld2574DOT_slot2, + OPERAND_dsp340050b49a6c_fld2575DOT_slot2, + OPERAND_dsp340050b49a6c_fld2576DOT_slot2, + OPERAND_dsp340050b49a6c_fld2577DOT_slot2, + OPERAND_dsp340050b49a6c_fld2578, + OPERAND_dsp340050b49a6c_fld2579DOT_slot2, + OPERAND_dsp340050b49a6c_fld2580DOT_slot2, + OPERAND_dsp340050b49a6c_fld2581DOT_slot2, + OPERAND_dsp340050b49a6c_fld2582DOT_slot2, + OPERAND_dsp340050b49a6c_fld2583DOT_slot2, + OPERAND_dsp340050b49a6c_fld2584DOT_slot2, + OPERAND_dsp340050b49a6c_fld2585DOT_slot2, + OPERAND_dsp340050b49a6c_fld2586DOT_slot2, + OPERAND_dsp340050b49a6c_fld2587DOT_slot2, + OPERAND_dsp340050b49a6c_fld2588DOT_slot2, + OPERAND_dsp340050b49a6c_fld2589DOT_slot2, + OPERAND_dsp340050b49a6c_fld2590DOT_slot2, + OPERAND_dsp340050b49a6c_fld2591DOT_slot2, + OPERAND_dsp340050b49a6c_fld2592DOT_slot2, + OPERAND_dsp340050b49a6c_fld2595DOT_slot2, + OPERAND_dsp340050b49a6c_fld2596DOT_slot2, + OPERAND_dsp340050b49a6c_fld2598DOT_slot2, + OPERAND_dsp340050b49a6c_fld2599DOT_slot2, + OPERAND_dsp340050b49a6c_fld2601DOT_slot2, + OPERAND_dsp340050b49a6c_fld2602DOT_slot2, + OPERAND_dsp340050b49a6c_fld2604DOT_slot2, + OPERAND_dsp340050b49a6c_fld2605, + OPERAND_dsp340050b49a6c_fld2606DOT_slot2, + OPERAND_dsp340050b49a6c_fld2608DOT_slot2, + OPERAND_dsp340050b49a6c_fld2609DOT_slot2, + OPERAND_dsp340050b49a6c_fld2610DOT_slot2, + OPERAND_dsp340050b49a6c_fld2611DOT_slot2, + OPERAND_dsp340050b49a6c_fld2612, + OPERAND_dsp340050b49a6c_fld2613DOT_slot2, + OPERAND_dsp340050b49a6c_fld2614, + OPERAND_dsp340050b49a6c_fld2615DOT_slot2, + OPERAND_dsp340050b49a6c_fld2616DOT_slot2, + OPERAND_dsp340050b49a6c_fld2617DOT_slot2, + OPERAND_dsp340050b49a6c_fld2618DOT_slot2, + OPERAND_dsp340050b49a6c_fld2619DOT_slot2, + OPERAND_dsp340050b49a6c_fld2620DOT_slot2, + OPERAND_dsp340050b49a6c_fld2621DOT_slot2, + OPERAND_dsp340050b49a6c_fld2622DOT_slot2, + OPERAND_dsp340050b49a6c_fld2623DOT_slot2, + OPERAND_dsp340050b49a6c_fld2624DOT_slot2, + OPERAND_dsp340050b49a6c_fld2625, + OPERAND_dsp340050b49a6c_fld2626DOT_slot2, + OPERAND_dsp340050b49a6c_fld2628DOT_slot2, + OPERAND_dsp340050b49a6c_fld2630DOT_slot2, + OPERAND_dsp340050b49a6c_fld2632DOT_slot2, + OPERAND_dsp340050b49a6c_fld2633DOT_slot2, + OPERAND_dsp340050b49a6c_fld2635DOT_slot2, + OPERAND_dsp340050b49a6c_fld2636DOT_slot2, + OPERAND_dsp340050b49a6c_fld2637DOT_slot2, + OPERAND_dsp340050b49a6c_fld2640DOT_slot2, + OPERAND_dsp340050b49a6c_fld2641DOT_slot2, + OPERAND_dsp340050b49a6c_fld2642DOT_slot2, + OPERAND_dsp340050b49a6c_fld2643DOT_slot2, + OPERAND_dsp340050b49a6c_fld2644DOT_slot2, + OPERAND_dsp340050b49a6c_fld2645DOT_slot2, + OPERAND_dsp340050b49a6c_fld2646DOT_slot2, + OPERAND_dsp340050b49a6c_fld2647DOT_slot2, + OPERAND_dsp340050b49a6c_fld2648DOT_slot2, + OPERAND_dsp340050b49a6c_fld2649DOT_slot2, + OPERAND_dsp340050b49a6c_fld2650DOT_slot2, + OPERAND_dsp340050b49a6c_fld2651DOT_slot2, + OPERAND_dsp340050b49a6c_fld2652DOT_slot2, + OPERAND_dsp340050b49a6c_fld2654DOT_slot2, + OPERAND_dsp340050b49a6c_fld2655DOT_slot2, + OPERAND_dsp340050b49a6c_fld2656DOT_slot2, + OPERAND_dsp340050b49a6c_fld2657DOT_slot2, + OPERAND_dsp340050b49a6c_fld2658DOT_slot2, + OPERAND_dsp340050b49a6c_fld3708DOT_slot2, + OPERAND_dsp340050b49a6c_fld3709DOT_slot2, + OPERAND_dsp340050b49a6c_fld3710DOT_slot2, + OPERAND_dsp340050b49a6c_fld3711DOT_slot2, + OPERAND_dsp340050b49a6c_fld3712, + OPERAND_dsp340050b49a6c_fld3713DOT_slot2, + OPERAND_dsp340050b49a6c_fld3714DOT_slot2, + OPERAND_dsp340050b49a6c_fld3715, + OPERAND_dsp340050b49a6c_fld3716DOT_slot2, + OPERAND_dsp340050b49a6c_fld3717DOT_slot2, + OPERAND_dsp340050b49a6c_fld3718, + OPERAND_dsp340050b49a6c_fld3719DOT_slot2, + OPERAND_dsp340050b49a6c_fld3721DOT_slot2, + OPERAND_dsp340050b49a6c_fld3722, + OPERAND_dsp340050b49a6c_fld3723DOT_slot2, + OPERAND_dsp340050b49a6c_fld3724DOT_slot2, + OPERAND_dsp340050b49a6c_fld3725DOT_slot2, + OPERAND_dsp340050b49a6c_fld3726DOT_slot2, + OPERAND_dsp340050b49a6c_fld3727DOT_slot2, + OPERAND_dsp340050b49a6c_fld3728DOT_slot2, + OPERAND_dsp340050b49a6c_fld3729DOT_slot2, + OPERAND_dsp340050b49a6c_fld3731DOT_slot2, + OPERAND_dsp340050b49a6c_fld3732DOT_slot2, + OPERAND_dsp340050b49a6c_fld3733DOT_slot2, + OPERAND_op0_s7, + OPERAND_dsp340050b49a6c_fld3734DOT_slot1, + OPERAND_op0_s8, + OPERAND_dsp340050b49a6c_fld2068, + OPERAND_dsp340050b49a6c_fld2666DOT_slot0, + OPERAND_dsp340050b49a6c_fld2667DOT_slot0, + OPERAND_dsp340050b49a6c_fld2668DOT_slot0, + OPERAND_dsp340050b49a6c_fld2669DOT_slot0, + OPERAND_dsp340050b49a6c_fld2671DOT_slot0, + OPERAND_dsp340050b49a6c_fld2672DOT_slot0, + OPERAND_dsp340050b49a6c_fld2673DOT_slot0, + OPERAND_dsp340050b49a6c_fld2674DOT_slot0, + OPERAND_dsp340050b49a6c_fld2675DOT_slot0, + OPERAND_dsp340050b49a6c_fld2676DOT_slot0, + OPERAND_dsp340050b49a6c_fld2677DOT_slot0, + OPERAND_dsp340050b49a6c_fld2678DOT_slot0, + OPERAND_dsp340050b49a6c_fld2679DOT_slot0, + OPERAND_dsp340050b49a6c_fld2680DOT_slot0, + OPERAND_dsp340050b49a6c_fld2681DOT_slot0, + OPERAND_dsp340050b49a6c_fld2682DOT_slot0, + OPERAND_dsp340050b49a6c_fld2683DOT_slot0, + OPERAND_dsp340050b49a6c_fld2684DOT_slot0, + OPERAND_dsp340050b49a6c_fld2685DOT_slot0, + OPERAND_dsp340050b49a6c_fld2686DOT_slot0, + OPERAND_dsp340050b49a6c_fld2688DOT_slot0, + OPERAND_dsp340050b49a6c_fld2689DOT_slot0, + OPERAND_dsp340050b49a6c_fld2690DOT_slot0, + OPERAND_dsp340050b49a6c_fld2692DOT_slot0, + OPERAND_dsp340050b49a6c_fld2693DOT_slot0, + OPERAND_dsp340050b49a6c_fld2695DOT_slot0, + OPERAND_dsp340050b49a6c_fld2697DOT_slot0, + OPERAND_dsp340050b49a6c_fld2699DOT_slot0, + OPERAND_dsp340050b49a6c_fld2700DOT_slot0, + OPERAND_dsp340050b49a6c_fld2701DOT_slot0, + OPERAND_dsp340050b49a6c_fld2702DOT_slot0, + OPERAND_dsp340050b49a6c_fld2703DOT_slot0, + OPERAND_dsp340050b49a6c_fld2704DOT_slot0, + OPERAND_dsp340050b49a6c_fld2705DOT_slot0, + OPERAND_dsp340050b49a6c_fld3735DOT_slot0, + OPERAND_dsp340050b49a6c_fld3736, + OPERAND_dsp340050b49a6c_fld3737DOT_slot0, + OPERAND_dsp340050b49a6c_fld3738DOT_slot0, + OPERAND_dsp340050b49a6c_fld3739DOT_slot0, + OPERAND_dsp340050b49a6c_fld3740DOT_slot0, + OPERAND_dsp340050b49a6c_fld3741DOT_slot0, + OPERAND_dsp340050b49a6c_fld3742DOT_slot0, + OPERAND_op0_s9, + OPERAND_dsp340050b49a6c_fld2706PQ_slot2, + OPERAND_dsp340050b49a6c_fld2707PQ_slot2, + OPERAND_dsp340050b49a6c_fld2708PQ_slot2, + OPERAND_dsp340050b49a6c_fld2709PQ_slot2, + OPERAND_dsp340050b49a6c_fld2710PQ_slot2, + OPERAND_dsp340050b49a6c_fld2711PQ_slot2, + OPERAND_dsp340050b49a6c_fld2713PQ_slot2, + OPERAND_dsp340050b49a6c_fld2714PQ_slot2, + OPERAND_dsp340050b49a6c_fld2715PQ_slot2, + OPERAND_dsp340050b49a6c_fld2717PQ_slot2, + OPERAND_dsp340050b49a6c_fld2718PQ_slot2, + OPERAND_dsp340050b49a6c_fld2719PQ_slot2, + OPERAND_dsp340050b49a6c_fld2721PQ_slot2, + OPERAND_dsp340050b49a6c_fld2722PQ_slot2, + OPERAND_dsp340050b49a6c_fld2723PQ_slot2, + OPERAND_dsp340050b49a6c_fld2724PQ_slot2, + OPERAND_dsp340050b49a6c_fld2725PQ_slot2, + OPERAND_dsp340050b49a6c_fld2726PQ_slot2, + OPERAND_dsp340050b49a6c_fld2727PQ_slot2, + OPERAND_dsp340050b49a6c_fld2728PQ_slot2, + OPERAND_dsp340050b49a6c_fld2729PQ_slot2, + OPERAND_dsp340050b49a6c_fld2730PQ_slot2, + OPERAND_dsp340050b49a6c_fld2731PQ_slot2, + OPERAND_dsp340050b49a6c_fld2732PQ_slot2, + OPERAND_dsp340050b49a6c_fld2733PQ_slot2, + OPERAND_dsp340050b49a6c_fld2734PQ_slot2, + OPERAND_dsp340050b49a6c_fld2735PQ_slot2, + OPERAND_dsp340050b49a6c_fld2736PQ_slot2, + OPERAND_dsp340050b49a6c_fld2737, + OPERAND_dsp340050b49a6c_fld2738PQ_slot2, + OPERAND_dsp340050b49a6c_fld2739PQ_slot2, + OPERAND_dsp340050b49a6c_fld2741PQ_slot2, + OPERAND_dsp340050b49a6c_fld2742PQ_slot2, + OPERAND_dsp340050b49a6c_fld2743PQ_slot2, + OPERAND_dsp340050b49a6c_fld2746PQ_slot2, + OPERAND_dsp340050b49a6c_fld2747PQ_slot2, + OPERAND_dsp340050b49a6c_fld2748PQ_slot2, + OPERAND_dsp340050b49a6c_fld2750PQ_slot2, + OPERAND_dsp340050b49a6c_fld2751PQ_slot2, + OPERAND_dsp340050b49a6c_fld2752PQ_slot2, + OPERAND_dsp340050b49a6c_fld2753PQ_slot2, + OPERAND_dsp340050b49a6c_fld2754PQ_slot2, + OPERAND_dsp340050b49a6c_fld2755PQ_slot2, + OPERAND_dsp340050b49a6c_fld2756PQ_slot2, + OPERAND_dsp340050b49a6c_fld2757PQ_slot2, + OPERAND_dsp340050b49a6c_fld2758PQ_slot2, + OPERAND_dsp340050b49a6c_fld2759PQ_slot2, + OPERAND_dsp340050b49a6c_fld2760PQ_slot2, + OPERAND_dsp340050b49a6c_fld2761PQ_slot2, + OPERAND_dsp340050b49a6c_fld2762PQ_slot2, + OPERAND_dsp340050b49a6c_fld2763PQ_slot2, + OPERAND_dsp340050b49a6c_fld2764PQ_slot2, + OPERAND_dsp340050b49a6c_fld2765PQ_slot2, + OPERAND_dsp340050b49a6c_fld2766PQ_slot2, + OPERAND_dsp340050b49a6c_fld2767PQ_slot2, + OPERAND_dsp340050b49a6c_fld2768PQ_slot2, + OPERAND_dsp340050b49a6c_fld2769PQ_slot2, + OPERAND_dsp340050b49a6c_fld2770PQ_slot2, + OPERAND_dsp340050b49a6c_fld2771PQ_slot2, + OPERAND_dsp340050b49a6c_fld2772PQ_slot2, + OPERAND_dsp340050b49a6c_fld2773PQ_slot2, + OPERAND_dsp340050b49a6c_fld2774PQ_slot2, + OPERAND_dsp340050b49a6c_fld2775PQ_slot2, + OPERAND_dsp340050b49a6c_fld2776PQ_slot2, + OPERAND_dsp340050b49a6c_fld2777PQ_slot2, + OPERAND_dsp340050b49a6c_fld2778PQ_slot2, + OPERAND_dsp340050b49a6c_fld2779PQ_slot2, + OPERAND_dsp340050b49a6c_fld2780PQ_slot2, + OPERAND_dsp340050b49a6c_fld2781PQ_slot2, + OPERAND_dsp340050b49a6c_fld2782PQ_slot2, + OPERAND_dsp340050b49a6c_fld2783PQ_slot2, + OPERAND_dsp340050b49a6c_fld2784PQ_slot2, + OPERAND_dsp340050b49a6c_fld2785PQ_slot2, + OPERAND_dsp340050b49a6c_fld2786PQ_slot2, + OPERAND_dsp340050b49a6c_fld2787PQ_slot2, + OPERAND_dsp340050b49a6c_fld2788PQ_slot2, + OPERAND_dsp340050b49a6c_fld2789PQ_slot2, + OPERAND_dsp340050b49a6c_fld2790PQ_slot2, + OPERAND_dsp340050b49a6c_fld2791PQ_slot2, + OPERAND_dsp340050b49a6c_fld2792PQ_slot2, + OPERAND_dsp340050b49a6c_fld2793PQ_slot2, + OPERAND_dsp340050b49a6c_fld2795PQ_slot2, + OPERAND_dsp340050b49a6c_fld2796PQ_slot2, + OPERAND_dsp340050b49a6c_fld2798PQ_slot2, + OPERAND_dsp340050b49a6c_fld2801PQ_slot2, + OPERAND_dsp340050b49a6c_fld2803PQ_slot2, + OPERAND_dsp340050b49a6c_fld2805PQ_slot2, + OPERAND_dsp340050b49a6c_fld2806PQ_slot2, + OPERAND_dsp340050b49a6c_fld2807PQ_slot2, + OPERAND_dsp340050b49a6c_fld2808PQ_slot2, + OPERAND_dsp340050b49a6c_fld2809PQ_slot2, + OPERAND_dsp340050b49a6c_fld2810PQ_slot2, + OPERAND_dsp340050b49a6c_fld2811PQ_slot2, + OPERAND_dsp340050b49a6c_fld2812PQ_slot2, + OPERAND_dsp340050b49a6c_fld2814PQ_slot2, + OPERAND_dsp340050b49a6c_fld2816PQ_slot2, + OPERAND_dsp340050b49a6c_fld2817, + OPERAND_dsp340050b49a6c_fld2818PQ_slot2, + OPERAND_dsp340050b49a6c_fld2819, + OPERAND_dsp340050b49a6c_fld2820PQ_slot2, + OPERAND_dsp340050b49a6c_fld2821PQ_slot2, + OPERAND_dsp340050b49a6c_fld2823PQ_slot2, + OPERAND_dsp340050b49a6c_fld3744PQ_slot2, + OPERAND_dsp340050b49a6c_fld3745PQ_slot2, + OPERAND_dsp340050b49a6c_fld3746PQ_slot2, + OPERAND_dsp340050b49a6c_fld3747PQ_slot2, + OPERAND_dsp340050b49a6c_fld3748, + OPERAND_dsp340050b49a6c_fld3749PQ_slot2, + OPERAND_dsp340050b49a6c_fld3750PQ_slot2, + OPERAND_dsp340050b49a6c_fld3751PQ_slot2, + OPERAND_dsp340050b49a6c_fld3752PQ_slot2, + OPERAND_dsp340050b49a6c_fld3753PQ_slot2, + OPERAND_dsp340050b49a6c_fld3754PQ_slot2, + OPERAND_dsp340050b49a6c_fld3756PQ_slot2, + OPERAND_dsp340050b49a6c_fld3757PQ_slot2, + OPERAND_dsp340050b49a6c_fld3758PQ_slot2, + OPERAND_dsp340050b49a6c_fld3759PQ_slot2, + OPERAND_dsp340050b49a6c_fld3760PQ_slot2, + OPERAND_op0_s10, + OPERAND_dsp340050b49a6c_fld2825PQ_slot1, + OPERAND_dsp340050b49a6c_fld2826PQ_slot1, + OPERAND_dsp340050b49a6c_fld3761PQ_slot1, + OPERAND_op0_s11, + OPERAND_dsp340050b49a6c_fld2059, + OPERAND_dsp340050b49a6c_fld2069, + OPERAND_dsp340050b49a6c_fld2827PQ_slot0, + OPERAND_dsp340050b49a6c_fld2829PQ_slot0, + OPERAND_dsp340050b49a6c_fld2830PQ_slot0, + OPERAND_dsp340050b49a6c_fld2831PQ_slot0, + OPERAND_dsp340050b49a6c_fld2832PQ_slot0, + OPERAND_dsp340050b49a6c_fld2833PQ_slot0, + OPERAND_dsp340050b49a6c_fld2835PQ_slot0, + OPERAND_dsp340050b49a6c_fld2836PQ_slot0, + OPERAND_dsp340050b49a6c_fld2837PQ_slot0, + OPERAND_dsp340050b49a6c_fld2838PQ_slot0, + OPERAND_dsp340050b49a6c_fld2839PQ_slot0, + OPERAND_dsp340050b49a6c_fld2840PQ_slot0, + OPERAND_dsp340050b49a6c_fld2842PQ_slot0, + OPERAND_dsp340050b49a6c_fld2843PQ_slot0, + OPERAND_dsp340050b49a6c_fld2844PQ_slot0, + OPERAND_dsp340050b49a6c_fld2845PQ_slot0, + OPERAND_dsp340050b49a6c_fld2846PQ_slot0, + OPERAND_dsp340050b49a6c_fld2847PQ_slot0, + OPERAND_dsp340050b49a6c_fld2849PQ_slot0, + OPERAND_dsp340050b49a6c_fld2850PQ_slot0, + OPERAND_dsp340050b49a6c_fld2851PQ_slot0, + OPERAND_dsp340050b49a6c_fld2852PQ_slot0, + OPERAND_dsp340050b49a6c_fld2853PQ_slot0, + OPERAND_dsp340050b49a6c_fld2854PQ_slot0, + OPERAND_dsp340050b49a6c_fld2855PQ_slot0, + OPERAND_dsp340050b49a6c_fld2856PQ_slot0, + OPERAND_dsp340050b49a6c_fld2857PQ_slot0, + OPERAND_dsp340050b49a6c_fld2858PQ_slot0, + OPERAND_dsp340050b49a6c_fld2859PQ_slot0, + OPERAND_dsp340050b49a6c_fld2860PQ_slot0, + OPERAND_dsp340050b49a6c_fld2861PQ_slot0, + OPERAND_dsp340050b49a6c_fld2863PQ_slot0, + OPERAND_dsp340050b49a6c_fld2864PQ_slot0, + OPERAND_dsp340050b49a6c_fld2865, + OPERAND_dsp340050b49a6c_fld2867PQ_slot0, + OPERAND_dsp340050b49a6c_fld2869PQ_slot0, + OPERAND_dsp340050b49a6c_fld2871PQ_slot0, + OPERAND_dsp340050b49a6c_fld2872PQ_slot0, + OPERAND_dsp340050b49a6c_fld2873PQ_slot0, + OPERAND_dsp340050b49a6c_fld2874PQ_slot0, + OPERAND_dsp340050b49a6c_fld2875PQ_slot0, + OPERAND_dsp340050b49a6c_fld2876PQ_slot0, + OPERAND_dsp340050b49a6c_fld2877PQ_slot0, + OPERAND_dsp340050b49a6c_fld2878PQ_slot0, + OPERAND_dsp340050b49a6c_fld2879PQ_slot0, + OPERAND_dsp340050b49a6c_fld2880PQ_slot0, + OPERAND_dsp340050b49a6c_fld2881PQ_slot0, + OPERAND_dsp340050b49a6c_fld2882, + OPERAND_dsp340050b49a6c_fld2883PQ_slot0, + OPERAND_dsp340050b49a6c_fld2884PQ_slot0, + OPERAND_dsp340050b49a6c_fld2885PQ_slot0, + OPERAND_dsp340050b49a6c_fld2886PQ_slot0, + OPERAND_dsp340050b49a6c_fld2887PQ_slot0, + OPERAND_dsp340050b49a6c_fld2888PQ_slot0, + OPERAND_dsp340050b49a6c_fld2890PQ_slot0, + OPERAND_dsp340050b49a6c_fld2891PQ_slot0, + OPERAND_dsp340050b49a6c_fld2892PQ_slot0, + OPERAND_dsp340050b49a6c_fld2893PQ_slot0, + OPERAND_dsp340050b49a6c_fld2894PQ_slot0, + OPERAND_dsp340050b49a6c_fld2895PQ_slot0, + OPERAND_dsp340050b49a6c_fld2897PQ_slot0, + OPERAND_dsp340050b49a6c_fld2899PQ_slot0, + OPERAND_dsp340050b49a6c_fld2900PQ_slot0, + OPERAND_dsp340050b49a6c_fld2901PQ_slot0, + OPERAND_dsp340050b49a6c_fld2902PQ_slot0, + OPERAND_dsp340050b49a6c_fld2903PQ_slot0, + OPERAND_dsp340050b49a6c_fld2904PQ_slot0, + OPERAND_dsp340050b49a6c_fld2905PQ_slot0, + OPERAND_dsp340050b49a6c_fld2906PQ_slot0, + OPERAND_dsp340050b49a6c_fld2907PQ_slot0, + OPERAND_dsp340050b49a6c_fld2908PQ_slot0, + OPERAND_dsp340050b49a6c_fld2909PQ_slot0, + OPERAND_dsp340050b49a6c_fld2910PQ_slot0, + OPERAND_dsp340050b49a6c_fld2911PQ_slot0, + OPERAND_dsp340050b49a6c_fld2912PQ_slot0, + OPERAND_dsp340050b49a6c_fld2913PQ_slot0, + OPERAND_dsp340050b49a6c_fld2914PQ_slot0, + OPERAND_dsp340050b49a6c_fld2915PQ_slot0, + OPERAND_dsp340050b49a6c_fld2916PQ_slot0, + OPERAND_dsp340050b49a6c_fld2917PQ_slot0, + OPERAND_dsp340050b49a6c_fld2918PQ_slot0, + OPERAND_dsp340050b49a6c_fld2919PQ_slot0, + OPERAND_dsp340050b49a6c_fld2920PQ_slot0, + OPERAND_dsp340050b49a6c_fld2921PQ_slot0, + OPERAND_dsp340050b49a6c_fld2922PQ_slot0, + OPERAND_dsp340050b49a6c_fld2923PQ_slot0, + OPERAND_dsp340050b49a6c_fld2924PQ_slot0, + OPERAND_dsp340050b49a6c_fld2925PQ_slot0, + OPERAND_dsp340050b49a6c_fld2926PQ_slot0, + OPERAND_dsp340050b49a6c_fld2927PQ_slot0, + OPERAND_dsp340050b49a6c_fld2928PQ_slot0, + OPERAND_dsp340050b49a6c_fld2929PQ_slot0, + OPERAND_dsp340050b49a6c_fld2930PQ_slot0, + OPERAND_dsp340050b49a6c_fld2932PQ_slot0, + OPERAND_dsp340050b49a6c_fld2934PQ_slot0, + OPERAND_dsp340050b49a6c_fld2935PQ_slot0, + OPERAND_dsp340050b49a6c_fld2936PQ_slot0, + OPERAND_dsp340050b49a6c_fld2937PQ_slot0, + OPERAND_dsp340050b49a6c_fld2939PQ_slot0, + OPERAND_dsp340050b49a6c_fld2940, + OPERAND_dsp340050b49a6c_fld2941PQ_slot0, + OPERAND_dsp340050b49a6c_fld2942PQ_slot0, + OPERAND_dsp340050b49a6c_fld2943PQ_slot0, + OPERAND_dsp340050b49a6c_fld2945PQ_slot0, + OPERAND_dsp340050b49a6c_fld2946PQ_slot0, + OPERAND_dsp340050b49a6c_fld2947PQ_slot0, + OPERAND_dsp340050b49a6c_fld2948PQ_slot0, + OPERAND_dsp340050b49a6c_fld2949PQ_slot0, + OPERAND_dsp340050b49a6c_fld2950PQ_slot0, + OPERAND_dsp340050b49a6c_fld3763PQ_slot0, + OPERAND_dsp340050b49a6c_fld3764PQ_slot0, + OPERAND_dsp340050b49a6c_fld3765PQ_slot0, + OPERAND_dsp340050b49a6c_fld3766PQ_slot0, + OPERAND_dsp340050b49a6c_fld3767PQ_slot0, + OPERAND_dsp340050b49a6c_fld3768PQ_slot0, + OPERAND_dsp340050b49a6c_fld3769PQ_slot0, + OPERAND_dsp340050b49a6c_fld3770PQ_slot0, + OPERAND_dsp340050b49a6c_fld3771PQ_slot0, + OPERAND_dsp340050b49a6c_fld3772, + OPERAND_dsp340050b49a6c_fld3773PQ_slot0, + OPERAND_dsp340050b49a6c_fld3775PQ_slot0, + OPERAND_dsp340050b49a6c_fld3776PQ_slot0, + OPERAND_dsp340050b49a6c_fld3777PQ_slot0, + OPERAND_dsp340050b49a6c_fld3778PQ_slot0, + OPERAND_dsp340050b49a6c_fld3779PQ_slot0, + OPERAND_dsp340050b49a6c_fld3780PQ_slot0, + OPERAND_op0_s12, + OPERAND_dsp340050b49a6c_fld2953ACC2_slot2, + OPERAND_dsp340050b49a6c_fld2954ACC2_slot2, + OPERAND_dsp340050b49a6c_fld2955ACC2_slot2, + OPERAND_dsp340050b49a6c_fld2956ACC2_slot2, + OPERAND_dsp340050b49a6c_fld2957ACC2_slot2, + OPERAND_dsp340050b49a6c_fld2958ACC2_slot2, + OPERAND_dsp340050b49a6c_fld2959ACC2_slot2, + OPERAND_dsp340050b49a6c_fld2960ACC2_slot2, + OPERAND_dsp340050b49a6c_fld2963ACC2_slot2, + OPERAND_dsp340050b49a6c_fld2964ACC2_slot2, + OPERAND_dsp340050b49a6c_fld2966ACC2_slot2, + OPERAND_dsp340050b49a6c_fld2967ACC2_slot2, + OPERAND_dsp340050b49a6c_fld3782ACC2_slot2, + OPERAND_dsp340050b49a6c_fld3783ACC2_slot2, + OPERAND_dsp340050b49a6c_fld3784ACC2_slot2, + OPERAND_dsp340050b49a6c_fld3785ACC2_slot2, + OPERAND_dsp340050b49a6c_fld3786ACC2_slot2, + OPERAND_dsp340050b49a6c_fld3788ACC2_slot2, + OPERAND_op0_s13, + OPERAND_dsp340050b49a6c_fld2028, + OPERAND_dsp340050b49a6c_fld2075, + OPERAND_dsp340050b49a6c_fld2968ACC2_slot1, + OPERAND_dsp340050b49a6c_fld2969ACC2_slot1, + OPERAND_dsp340050b49a6c_fld3790ACC2_slot1, + OPERAND_dsp340050b49a6c_fld3793ACC2_slot1, + OPERAND_op0_s14, + OPERAND_dsp340050b49a6c_fld2973ACC2_slot0, + OPERAND_dsp340050b49a6c_fld2974ACC2_slot0, + OPERAND_dsp340050b49a6c_fld2975ACC2_slot0, + OPERAND_dsp340050b49a6c_fld2976ACC2_slot0, + OPERAND_dsp340050b49a6c_fld2977ACC2_slot0, + OPERAND_dsp340050b49a6c_fld2980ACC2_slot0, + OPERAND_dsp340050b49a6c_fld2981ACC2_slot0, + OPERAND_dsp340050b49a6c_fld2982ACC2_slot0, + OPERAND_dsp340050b49a6c_fld2984ACC2_slot0, + OPERAND_dsp340050b49a6c_fld2985ACC2_slot0, + OPERAND_dsp340050b49a6c_fld2987ACC2_slot0, + OPERAND_dsp340050b49a6c_fld2989ACC2_slot0, + OPERAND_dsp340050b49a6c_fld2990ACC2_slot0, + OPERAND_dsp340050b49a6c_fld3795ACC2_slot0, + OPERAND_dsp340050b49a6c_fld3796ACC2_slot0, + OPERAND_dsp340050b49a6c_fld3797, + OPERAND_dsp340050b49a6c_fld3798ACC2_slot0, + OPERAND_dsp340050b49a6c_fld3799ACC2_slot0, + OPERAND_dsp340050b49a6c_fld3800ACC2_slot0, + OPERAND_dsp340050b49a6c_fld3801ACC2_slot0, + OPERAND_dsp340050b49a6c_fld3802ACC2_slot0, + OPERAND_dsp340050b49a6c_fld3803ACC2_slot0, + OPERAND_op0_s15, + OPERAND_dsp340050b49a6c_fld2991SMOD_slot2, + OPERAND_dsp340050b49a6c_fld2992SMOD_slot2, + OPERAND_dsp340050b49a6c_fld2993SMOD_slot2, + OPERAND_dsp340050b49a6c_fld2994SMOD_slot2, + OPERAND_dsp340050b49a6c_fld2995SMOD_slot2, + OPERAND_dsp340050b49a6c_fld2996SMOD_slot2, + OPERAND_dsp340050b49a6c_fld2997SMOD_slot2, + OPERAND_dsp340050b49a6c_fld2998SMOD_slot2, + OPERAND_dsp340050b49a6c_fld2999SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3000SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3001SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3002SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3003SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3004SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3005SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3006SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3007SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3008SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3009SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3010SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3011SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3012SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3013SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3014SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3015SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3016SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3017SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3018SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3019SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3020SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3021SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3022SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3023SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3024SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3025SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3026SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3027SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3028SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3030SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3031SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3032SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3033SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3034SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3035SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3036SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3038SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3039SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3040SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3043SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3044SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3046SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3047SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3048, + OPERAND_dsp340050b49a6c_fld3049SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3050SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3051SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3052SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3053SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3054SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3055SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3056SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3058SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3059SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3061SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3062, + OPERAND_dsp340050b49a6c_fld3063SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3065SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3066SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3067SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3068SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3069SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3070, + OPERAND_dsp340050b49a6c_fld3071SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3072SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3073SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3074SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3075SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3076SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3077SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3078SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3079SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3080SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3081SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3082SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3084SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3085SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3087SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3088SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3090SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3091SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3092SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3093SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3096SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3097SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3098SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3099SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3100SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3101SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3102SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3104SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3105SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3106SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3107SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3108SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3109SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3110SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3111SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3113SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3114SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3115SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3116SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3805SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3806SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3807SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3808, + OPERAND_dsp340050b49a6c_fld3809SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3810SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3812SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3813SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3814SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3816SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3817, + OPERAND_dsp340050b49a6c_fld3818SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3819SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3821SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3822SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3823SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3824SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3825SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3826SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3827SMOD_slot2, + OPERAND_dsp340050b49a6c_fld3828SMOD_slot2, + OPERAND_op0_s16, + OPERAND_dsp340050b49a6c_fld2033, + OPERAND_dsp340050b49a6c_fld2080, + OPERAND_dsp340050b49a6c_fld3117SMOD_slot1, + OPERAND_dsp340050b49a6c_fld3118SMOD_slot1, + OPERAND_dsp340050b49a6c_fld3829SMOD_slot1, + OPERAND_op0_s17, + OPERAND_dsp340050b49a6c_fld3119SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3120SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3121SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3122SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3123SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3125SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3126SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3127SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3128SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3129SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3130SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3131SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3132SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3133SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3134SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3135SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3136SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3137SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3138SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3139SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3140SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3141SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3142SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3143SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3144SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3145SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3146SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3148SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3149SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3150, + OPERAND_dsp340050b49a6c_fld3152SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3153SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3155SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3156SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3157SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3158SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3159SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3160SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3161SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3164SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3165SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3166SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3168SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3170SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3171SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3172SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3173SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3174SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3175SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3176SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3177SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3178SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3179SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3180SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3181SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3182SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3184SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3186SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3188SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3832SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3833SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3834, + OPERAND_dsp340050b49a6c_fld3836SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3837SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3838SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3841SMOD_slot0, + OPERAND_dsp340050b49a6c_fld3842SMOD_slot0, + OPERAND_op0_s18, + OPERAND_dsp340050b49a6c_fld2074, + OPERAND_dsp340050b49a6c_fld3191LLR_slot2, + OPERAND_dsp340050b49a6c_fld3192LLR_slot2, + OPERAND_dsp340050b49a6c_fld3193LLR_slot2, + OPERAND_dsp340050b49a6c_fld3194LLR_slot2, + OPERAND_dsp340050b49a6c_fld3195LLR_slot2, + OPERAND_dsp340050b49a6c_fld3196LLR_slot2, + OPERAND_dsp340050b49a6c_fld3197LLR_slot2, + OPERAND_dsp340050b49a6c_fld3198LLR_slot2, + OPERAND_dsp340050b49a6c_fld3199LLR_slot2, + OPERAND_dsp340050b49a6c_fld3200LLR_slot2, + OPERAND_dsp340050b49a6c_fld3201LLR_slot2, + OPERAND_dsp340050b49a6c_fld3202LLR_slot2, + OPERAND_dsp340050b49a6c_fld3203LLR_slot2, + OPERAND_dsp340050b49a6c_fld3204LLR_slot2, + OPERAND_dsp340050b49a6c_fld3205, + OPERAND_dsp340050b49a6c_fld3206, + OPERAND_dsp340050b49a6c_fld3207LLR_slot2, + OPERAND_dsp340050b49a6c_fld3208LLR_slot2, + OPERAND_dsp340050b49a6c_fld3210LLR_slot2, + OPERAND_dsp340050b49a6c_fld3212, + OPERAND_dsp340050b49a6c_fld3213LLR_slot2, + OPERAND_dsp340050b49a6c_fld3214, + OPERAND_dsp340050b49a6c_fld3215LLR_slot2, + OPERAND_dsp340050b49a6c_fld3216LLR_slot2, + OPERAND_dsp340050b49a6c_fld3217, + OPERAND_dsp340050b49a6c_fld3218LLR_slot2, + OPERAND_dsp340050b49a6c_fld3220LLR_slot2, + OPERAND_dsp340050b49a6c_fld3221LLR_slot2, + OPERAND_dsp340050b49a6c_fld3222LLR_slot2, + OPERAND_dsp340050b49a6c_fld3224LLR_slot2, + OPERAND_dsp340050b49a6c_fld3225, + OPERAND_dsp340050b49a6c_fld3226LLR_slot2, + OPERAND_dsp340050b49a6c_fld3228LLR_slot2, + OPERAND_dsp340050b49a6c_fld3230, + OPERAND_dsp340050b49a6c_fld3231LLR_slot2, + OPERAND_dsp340050b49a6c_fld3232LLR_slot2, + OPERAND_dsp340050b49a6c_fld3233, + OPERAND_dsp340050b49a6c_fld3234LLR_slot2, + OPERAND_dsp340050b49a6c_fld3235LLR_slot2, + OPERAND_dsp340050b49a6c_fld3236, + OPERAND_dsp340050b49a6c_fld3237LLR_slot2, + OPERAND_dsp340050b49a6c_fld3238LLR_slot2, + OPERAND_dsp340050b49a6c_fld3240LLR_slot2, + OPERAND_dsp340050b49a6c_fld3241LLR_slot2, + OPERAND_dsp340050b49a6c_fld3242LLR_slot2, + OPERAND_dsp340050b49a6c_fld3243LLR_slot2, + OPERAND_dsp340050b49a6c_fld3244LLR_slot2, + OPERAND_dsp340050b49a6c_fld3245LLR_slot2, + OPERAND_dsp340050b49a6c_fld3246, + OPERAND_dsp340050b49a6c_fld3247LLR_slot2, + OPERAND_dsp340050b49a6c_fld3843LLR_slot2, + OPERAND_dsp340050b49a6c_fld3844, + OPERAND_dsp340050b49a6c_fld3845LLR_slot2, + OPERAND_dsp340050b49a6c_fld3847LLR_slot2, + OPERAND_dsp340050b49a6c_fld3848LLR_slot2, + OPERAND_dsp340050b49a6c_fld3849LLR_slot2, + OPERAND_dsp340050b49a6c_fld3850LLR_slot2, + OPERAND_dsp340050b49a6c_fld3851LLR_slot2, + OPERAND_dsp340050b49a6c_fld3853LLR_slot2, + OPERAND_dsp340050b49a6c_fld3855LLR_slot2, + OPERAND_dsp340050b49a6c_fld3856LLR_slot2, + OPERAND_dsp340050b49a6c_fld3857LLR_slot2, + OPERAND_dsp340050b49a6c_fld3859LLR_slot2, + OPERAND_dsp340050b49a6c_fld3860LLR_slot2, + OPERAND_dsp340050b49a6c_fld3861LLR_slot2, + OPERAND_dsp340050b49a6c_fld3862, + OPERAND_dsp340050b49a6c_fld3863LLR_slot2, + OPERAND_dsp340050b49a6c_fld3864LLR_slot2, + OPERAND_dsp340050b49a6c_fld3865LLR_slot2, + OPERAND_dsp340050b49a6c_fld3866LLR_slot2, + OPERAND_dsp340050b49a6c_fld3867LLR_slot2, + OPERAND_dsp340050b49a6c_fld3868, + OPERAND_op0_s19, + OPERAND_dsp340050b49a6c_fld2034, + OPERAND_dsp340050b49a6c_fld3248LLR_slot1, + OPERAND_dsp340050b49a6c_fld3250LLR_slot1, + OPERAND_dsp340050b49a6c_fld3251LLR_slot1, + OPERAND_dsp340050b49a6c_fld3252LLR_slot1, + OPERAND_dsp340050b49a6c_fld3253LLR_slot1, + OPERAND_dsp340050b49a6c_fld3254LLR_slot1, + OPERAND_dsp340050b49a6c_fld3869LLR_slot1, + OPERAND_dsp340050b49a6c_fld3870, + OPERAND_dsp340050b49a6c_fld3872LLR_slot1, + OPERAND_dsp340050b49a6c_fld3875LLR_slot1, + OPERAND_dsp340050b49a6c_fld3876LLR_slot1, + OPERAND_dsp340050b49a6c_fld3878LLR_slot1, + OPERAND_op0_s20, + OPERAND_dsp340050b49a6c_fld2071, + OPERAND_dsp340050b49a6c_fld3258LLR_slot0, + OPERAND_dsp340050b49a6c_fld3259LLR_slot0, + OPERAND_dsp340050b49a6c_fld3260LLR_slot0, + OPERAND_dsp340050b49a6c_fld3261LLR_slot0, + OPERAND_dsp340050b49a6c_fld3263LLR_slot0, + OPERAND_dsp340050b49a6c_fld3264LLR_slot0, + OPERAND_dsp340050b49a6c_fld3265LLR_slot0, + OPERAND_dsp340050b49a6c_fld3266LLR_slot0, + OPERAND_dsp340050b49a6c_fld3267LLR_slot0, + OPERAND_dsp340050b49a6c_fld3268LLR_slot0, + OPERAND_dsp340050b49a6c_fld3269LLR_slot0, + OPERAND_dsp340050b49a6c_fld3270LLR_slot0, + OPERAND_dsp340050b49a6c_fld3272LLR_slot0, + OPERAND_dsp340050b49a6c_fld3274LLR_slot0, + OPERAND_dsp340050b49a6c_fld3275LLR_slot0, + OPERAND_dsp340050b49a6c_fld3276LLR_slot0, + OPERAND_dsp340050b49a6c_fld3277LLR_slot0, + OPERAND_dsp340050b49a6c_fld3278LLR_slot0, + OPERAND_dsp340050b49a6c_fld3279LLR_slot0, + OPERAND_dsp340050b49a6c_fld3280LLR_slot0, + OPERAND_dsp340050b49a6c_fld3281LLR_slot0, + OPERAND_dsp340050b49a6c_fld3282LLR_slot0, + OPERAND_dsp340050b49a6c_fld3283LLR_slot0, + OPERAND_dsp340050b49a6c_fld3284LLR_slot0, + OPERAND_dsp340050b49a6c_fld3286LLR_slot0, + OPERAND_dsp340050b49a6c_fld3288LLR_slot0, + OPERAND_dsp340050b49a6c_fld3289LLR_slot0, + OPERAND_dsp340050b49a6c_fld3291LLR_slot0, + OPERAND_dsp340050b49a6c_fld3292LLR_slot0, + OPERAND_dsp340050b49a6c_fld3293LLR_slot0, + OPERAND_dsp340050b49a6c_fld3294LLR_slot0, + OPERAND_dsp340050b49a6c_fld3295LLR_slot0, + OPERAND_dsp340050b49a6c_fld3296LLR_slot0, + OPERAND_dsp340050b49a6c_fld3297LLR_slot0, + OPERAND_dsp340050b49a6c_fld3298LLR_slot0, + OPERAND_dsp340050b49a6c_fld3299LLR_slot0, + OPERAND_dsp340050b49a6c_fld3300LLR_slot0, + OPERAND_dsp340050b49a6c_fld3302LLR_slot0, + OPERAND_dsp340050b49a6c_fld3303LLR_slot0, + OPERAND_dsp340050b49a6c_fld3304LLR_slot0, + OPERAND_dsp340050b49a6c_fld3305LLR_slot0, + OPERAND_dsp340050b49a6c_fld3306LLR_slot0, + OPERAND_dsp340050b49a6c_fld3308LLR_slot0, + OPERAND_dsp340050b49a6c_fld3310LLR_slot0, + OPERAND_dsp340050b49a6c_fld3311LLR_slot0, + OPERAND_dsp340050b49a6c_fld3312LLR_slot0, + OPERAND_dsp340050b49a6c_fld3879LLR_slot0, + OPERAND_dsp340050b49a6c_fld3881LLR_slot0, + OPERAND_dsp340050b49a6c_fld3883LLR_slot0, + OPERAND_dsp340050b49a6c_fld3885LLR_slot0, + OPERAND_dsp340050b49a6c_fld3887LLR_slot0, + OPERAND_dsp340050b49a6c_fld3888LLR_slot0, + OPERAND_dsp340050b49a6c_fld3890LLR_slot0, + OPERAND_dsp340050b49a6c_fld3892LLR_slot0, + OPERAND_dsp340050b49a6c_fld3893LLR_slot0, + OPERAND_op0_s21, + OPERAND_dsp340050b49a6c_fld3313DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3314, + OPERAND_dsp340050b49a6c_fld3315DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3316DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3317DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3318, + OPERAND_dsp340050b49a6c_fld3319DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3320DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3321DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3322DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3323DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3324DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3325DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3326DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3327DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3328DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3329DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3330DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3331DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3332DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3333DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3334DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3335DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3336DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3337DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3339DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3340DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3341DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3342DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3345DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3347DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3348DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3349DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3350DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3353DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3354DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3356DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3358DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3360DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3361DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3362DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3363DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3364, + OPERAND_dsp340050b49a6c_fld3365DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3366DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3367DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3368DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3369DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3370DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3371DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3372DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3373DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3374DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3375DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3376DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3377DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3378DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3379DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3380DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3381DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3382DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3384DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3385DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3386DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3387DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3388DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3390DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3392DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3394DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3396DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3397DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3399DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3401DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3403DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3404DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3406DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3407, + OPERAND_dsp340050b49a6c_fld3408DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3410, + OPERAND_dsp340050b49a6c_fld3411DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3412DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3413DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3414DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3415DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3416DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3417DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3418DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3419DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3420DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3421DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3422DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3423DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3424DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3425DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3426DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3427DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3428DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3429DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3430DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3431DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3432DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3433DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3434DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3435DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3436DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3437DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3438DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3439DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3440DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3441DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3442DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3443DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3444DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3445DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3446DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3448DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3450DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3451DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3453DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3454DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3456DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3457DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3458DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3459DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3460DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3461DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3462DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3464DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3465DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3466, + OPERAND_dsp340050b49a6c_fld3467DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3468DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3469DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3470DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3471DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3472DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3473DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3474DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3475DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3477DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3478DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3479DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3480DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3481DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3482DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3484DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3894DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3895DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3896DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3897DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3898DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3899DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3900, + OPERAND_dsp340050b49a6c_fld3901DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3903DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3904DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3905DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3906DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3907DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3908DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3909DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3910DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3913DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3914DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3916DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3917DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3918DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3919DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3920DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3921DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3922DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3923DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3924DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3925DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3927DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3928DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3929DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3930DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3931DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3933DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3934DUAL_slot2, + OPERAND_dsp340050b49a6c_fld3935DUAL_slot2, + OPERAND_op0_s22, + OPERAND_op0_s23, + OPERAND_dsp340050b49a6c_fld2057, + OPERAND_dsp340050b49a6c_fld2060, + OPERAND_dsp340050b49a6c_fld2066, + OPERAND_dsp340050b49a6c_fld2072, + OPERAND_dsp340050b49a6c_fld2079, + OPERAND_dsp340050b49a6c_fld3487DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3488DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3489DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3490DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3491DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3492DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3493DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3494DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3496DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3497DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3498DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3499DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3500DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3502DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3504DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3505DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3506DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3507DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3508DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3509DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3510DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3511DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3512DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3513DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3514DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3515DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3516DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3517DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3518DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3519DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3520DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3522DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3523DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3524DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3527DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3529DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3530DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3531, + OPERAND_dsp340050b49a6c_fld3532DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3533DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3535DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3536DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3537DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3538DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3539DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3541DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3542DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3543DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3544DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3545DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3546DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3547DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3548DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3549DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3550DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3551DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3552, + OPERAND_dsp340050b49a6c_fld3553DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3554DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3555DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3556DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3557DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3558DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3559DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3560DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3562DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3563DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3564DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3565DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3566DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3567DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3568DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3569DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3570DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3571DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3572DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3573DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3574DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3575DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3576DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3577DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3578DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3579DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3580DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3581DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3582DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3583DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3584, + OPERAND_dsp340050b49a6c_fld3585DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3587DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3588DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3589DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3590DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3591DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3592DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3593DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3594DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3595DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3596DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3597DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3598DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3599DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3600DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3601DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3602, + OPERAND_dsp340050b49a6c_fld3603DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3604DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3606DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3607DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3608DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3609DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3610, + OPERAND_dsp340050b49a6c_fld3611DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3612DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3613DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3614DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3615DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3616DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3618DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3619, + OPERAND_dsp340050b49a6c_fld3620DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3621DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3622DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3623DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3624DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3625DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3626DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3936DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3937DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3938DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3939DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3940DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3941DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3943DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3945DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3946DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3947DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3949DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3950DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3951DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3952DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3954DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3957DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3958DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3959DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3960DUAL_slot0, + OPERAND_dsp340050b49a6c_fld3961DUAL_slot0 +}; + + +/* Iclass table. */ + +static xtensa_arg_internal Iclass_xt_iclass_rfe_stateArgs[] = { + { { STATE_PSEXCM }, 'o' }, + { { STATE_EPC1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfde_stateArgs[] = { + { { STATE_DEPC }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call12_args[] = { + { { OPERAND_soffsetx4 }, 'i' }, + { { OPERAND_ar12 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call12_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call8_args[] = { + { { OPERAND_soffsetx4 }, 'i' }, + { { OPERAND_ar8 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call8_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call4_args[] = { + { { OPERAND_soffsetx4 }, 'i' }, + { { OPERAND_ar4 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call4_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx12_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ar12 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx12_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx8_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ar8 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx8_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx4_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ar4 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx4_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_entry_args[] = { + { { OPERAND_ars_entry }, 's' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm12x8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_entry_stateArgs[] = { + { { STATE_PSCALLINC }, 'i' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSWOE }, 'i' }, + { { STATE_WindowBase }, 'm' }, + { { STATE_WindowStart }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_movsp_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_movsp_stateArgs[] = { + { { STATE_WindowBase }, 'i' }, + { { STATE_WindowStart }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rotw_args[] = { + { { OPERAND_simm4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rotw_stateArgs[] = { + { { STATE_WindowBase }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_retw_args[] = { + { { OPERAND__ars_invisible }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_retw_stateArgs[] = { + { { STATE_WindowBase }, 'm' }, + { { STATE_WindowStart }, 'm' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSWOE }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfwou_stateArgs[] = { + { { STATE_EPC1 }, 'i' }, + { { STATE_PSEXCM }, 'o' }, + { { STATE_WindowBase }, 'm' }, + { { STATE_WindowStart }, 'm' }, + { { STATE_PSOWB }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l32e_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_immrx4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32e_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_immrx4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_windowbase_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_windowbase_stateArgs[] = { + { { STATE_WindowBase }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_windowbase_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_windowbase_stateArgs[] = { + { { STATE_WindowBase }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_windowbase_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_windowbase_stateArgs[] = { + { { STATE_WindowBase }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_windowstart_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_windowstart_stateArgs[] = { + { { STATE_WindowStart }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_windowstart_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_windowstart_stateArgs[] = { + { { STATE_WindowStart }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_windowstart_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_windowstart_stateArgs[] = { + { { STATE_WindowStart }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_add_n_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_addi_n_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_ai4const }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bz6_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm6 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_loadi4_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_lsi4x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mov_n_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_movi_n_args[] = { + { { OPERAND_ars }, 'o' }, + { { OPERAND_simm7 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_retn_args[] = { + { { OPERAND__ars_invisible }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_storei4_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_lsi4x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_threadptr_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_threadptr_stateArgs[] = { + { { STATE_THREADPTR }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_threadptr_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_threadptr_stateArgs[] = { + { { STATE_THREADPTR }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_addi_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_simm8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_addmi_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_simm8x256 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_addsub_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bit_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bsi8_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_b4const }, 'i' }, + { { OPERAND_label8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bsi8b_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_bbi }, 'i' }, + { { OPERAND_label8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bsi8u_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_b4constu }, 'i' }, + { { OPERAND_label8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bst8_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_label8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bsz12_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_label12 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call0_args[] = { + { { OPERAND_soffsetx4 }, 'i' }, + { { OPERAND_ar0 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx0_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ar0 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_exti_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_sae }, 'i' }, + { { OPERAND_op2p1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_jump_args[] = { + { { OPERAND_soffset }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_jumpx_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l16ui_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l16si_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l32i_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l32r_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_uimm16x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l32r_stateArgs[] = { + { { STATE_LITBADDR }, 'i' }, + { { STATE_LITBEN }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l8i_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_loop_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ulabel8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_loop_stateArgs[] = { + { { STATE_LBEG }, 'o' }, + { { STATE_LEND }, 'o' }, + { { STATE_LCOUNT }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_loopz_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ulabel8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_loopz_stateArgs[] = { + { { STATE_LBEG }, 'o' }, + { { STATE_LEND }, 'o' }, + { { STATE_LCOUNT }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_movi_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_simm12b }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_movz_args[] = { + { { OPERAND_arr }, 'm' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_neg_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_return_args[] = { + { { OPERAND__ars_invisible }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s16i_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32i_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s8i_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sar_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sar_stateArgs[] = { + { { STATE_SAR }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sari_args[] = { + { { OPERAND_sas }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sari_stateArgs[] = { + { { STATE_SAR }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shifts_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shifts_stateArgs[] = { + { { STATE_SAR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shiftst_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shiftst_stateArgs[] = { + { { STATE_SAR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shiftt_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shiftt_stateArgs[] = { + { { STATE_SAR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_slli_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_msalp32 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_srai_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_sargt }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_srli_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_s }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sync_stateArgs[] = { + { { STATE_XTSYNC }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsil_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_s }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsil_stateArgs[] = { + { { STATE_PSWOE }, 'i' }, + { { STATE_PSCALLINC }, 'i' }, + { { STATE_PSOWB }, 'i' }, + { { STATE_PSUM }, 'i' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSINTLEVEL }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lend_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lend_stateArgs[] = { + { { STATE_LEND }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lend_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lend_stateArgs[] = { + { { STATE_LEND }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lend_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lend_stateArgs[] = { + { { STATE_LEND }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lcount_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lcount_stateArgs[] = { + { { STATE_LCOUNT }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lcount_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lcount_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_LCOUNT }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lcount_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lcount_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_LCOUNT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lbeg_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lbeg_stateArgs[] = { + { { STATE_LBEG }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lbeg_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lbeg_stateArgs[] = { + { { STATE_LBEG }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lbeg_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lbeg_stateArgs[] = { + { { STATE_LBEG }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_sar_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_sar_stateArgs[] = { + { { STATE_SAR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_sar_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_sar_stateArgs[] = { + { { STATE_SAR }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_sar_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_sar_stateArgs[] = { + { { STATE_SAR }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_litbase_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_litbase_stateArgs[] = { + { { STATE_LITBADDR }, 'i' }, + { { STATE_LITBEN }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_litbase_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_litbase_stateArgs[] = { + { { STATE_LITBADDR }, 'o' }, + { { STATE_LITBEN }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_litbase_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_litbase_stateArgs[] = { + { { STATE_LITBADDR }, 'm' }, + { { STATE_LITBEN }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_176_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_176_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_208_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ps_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ps_stateArgs[] = { + { { STATE_PSWOE }, 'i' }, + { { STATE_PSCALLINC }, 'i' }, + { { STATE_PSOWB }, 'i' }, + { { STATE_PSUM }, 'i' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSINTLEVEL }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ps_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ps_stateArgs[] = { + { { STATE_PSWOE }, 'o' }, + { { STATE_PSCALLINC }, 'o' }, + { { STATE_PSOWB }, 'o' }, + { { STATE_PSUM }, 'o' }, + { { STATE_PSEXCM }, 'o' }, + { { STATE_PSINTLEVEL }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ps_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ps_stateArgs[] = { + { { STATE_PSWOE }, 'm' }, + { { STATE_PSCALLINC }, 'm' }, + { { STATE_PSOWB }, 'm' }, + { { STATE_PSUM }, 'm' }, + { { STATE_PSEXCM }, 'm' }, + { { STATE_PSINTLEVEL }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc1_stateArgs[] = { + { { STATE_EPC1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc1_stateArgs[] = { + { { STATE_EPC1 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc1_stateArgs[] = { + { { STATE_EPC1 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave1_stateArgs[] = { + { { STATE_EXCSAVE1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave1_stateArgs[] = { + { { STATE_EXCSAVE1 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave1_stateArgs[] = { + { { STATE_EXCSAVE1 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc2_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc2_stateArgs[] = { + { { STATE_EPC2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc2_stateArgs[] = { + { { STATE_EPC2 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc2_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc2_stateArgs[] = { + { { STATE_EPC2 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave2_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave2_stateArgs[] = { + { { STATE_EXCSAVE2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave2_stateArgs[] = { + { { STATE_EXCSAVE2 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave2_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave2_stateArgs[] = { + { { STATE_EXCSAVE2 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc3_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc3_stateArgs[] = { + { { STATE_EPC3 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc3_stateArgs[] = { + { { STATE_EPC3 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc3_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc3_stateArgs[] = { + { { STATE_EPC3 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave3_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave3_stateArgs[] = { + { { STATE_EXCSAVE3 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave3_stateArgs[] = { + { { STATE_EXCSAVE3 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave3_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave3_stateArgs[] = { + { { STATE_EXCSAVE3 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc4_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc4_stateArgs[] = { + { { STATE_EPC4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc4_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc4_stateArgs[] = { + { { STATE_EPC4 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc4_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc4_stateArgs[] = { + { { STATE_EPC4 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave4_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave4_stateArgs[] = { + { { STATE_EXCSAVE4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave4_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave4_stateArgs[] = { + { { STATE_EXCSAVE4 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave4_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave4_stateArgs[] = { + { { STATE_EXCSAVE4 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc5_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc5_stateArgs[] = { + { { STATE_EPC5 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc5_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc5_stateArgs[] = { + { { STATE_EPC5 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc5_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc5_stateArgs[] = { + { { STATE_EPC5 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave5_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave5_stateArgs[] = { + { { STATE_EXCSAVE5 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave5_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave5_stateArgs[] = { + { { STATE_EXCSAVE5 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave5_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave5_stateArgs[] = { + { { STATE_EXCSAVE5 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc6_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc6_stateArgs[] = { + { { STATE_EPC6 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc6_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc6_stateArgs[] = { + { { STATE_EPC6 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc6_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc6_stateArgs[] = { + { { STATE_EPC6 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave6_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave6_stateArgs[] = { + { { STATE_EXCSAVE6 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave6_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave6_stateArgs[] = { + { { STATE_EXCSAVE6 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave6_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave6_stateArgs[] = { + { { STATE_EXCSAVE6 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps2_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps2_stateArgs[] = { + { { STATE_EPS2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps2_stateArgs[] = { + { { STATE_EPS2 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps2_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps2_stateArgs[] = { + { { STATE_EPS2 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps3_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps3_stateArgs[] = { + { { STATE_EPS3 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps3_stateArgs[] = { + { { STATE_EPS3 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps3_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps3_stateArgs[] = { + { { STATE_EPS3 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps4_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps4_stateArgs[] = { + { { STATE_EPS4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps4_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps4_stateArgs[] = { + { { STATE_EPS4 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps4_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps4_stateArgs[] = { + { { STATE_EPS4 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps5_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps5_stateArgs[] = { + { { STATE_EPS5 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps5_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps5_stateArgs[] = { + { { STATE_EPS5 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps5_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps5_stateArgs[] = { + { { STATE_EPS5 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps6_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps6_stateArgs[] = { + { { STATE_EPS6 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps6_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps6_stateArgs[] = { + { { STATE_EPS6 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps6_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps6_stateArgs[] = { + { { STATE_EPS6 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excvaddr_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excvaddr_stateArgs[] = { + { { STATE_EXCVADDR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excvaddr_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excvaddr_stateArgs[] = { + { { STATE_EXCVADDR }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excvaddr_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excvaddr_stateArgs[] = { + { { STATE_EXCVADDR }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_depc_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_depc_stateArgs[] = { + { { STATE_DEPC }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_depc_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_depc_stateArgs[] = { + { { STATE_DEPC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_depc_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_depc_stateArgs[] = { + { { STATE_DEPC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_exccause_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_exccause_stateArgs[] = { + { { STATE_EXCCAUSE }, 'i' }, + { { STATE_XTSYNC }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_exccause_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_exccause_stateArgs[] = { + { { STATE_EXCCAUSE }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_exccause_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_exccause_stateArgs[] = { + { { STATE_EXCCAUSE }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_prid_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_vecbase_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_vecbase_stateArgs[] = { + { { STATE_VECBASE }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_vecbase_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_vecbase_stateArgs[] = { + { { STATE_VECBASE }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_vecbase_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_vecbase_stateArgs[] = { + { { STATE_VECBASE }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_mul16_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfi_args[] = { + { { OPERAND_s }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfi_stateArgs[] = { + { { STATE_PSWOE }, 'o' }, + { { STATE_PSCALLINC }, 'o' }, + { { STATE_PSOWB }, 'o' }, + { { STATE_PSUM }, 'o' }, + { { STATE_PSEXCM }, 'o' }, + { { STATE_PSINTLEVEL }, 'o' }, + { { STATE_EPC1 }, 'i' }, + { { STATE_EPC2 }, 'i' }, + { { STATE_EPC3 }, 'i' }, + { { STATE_EPC4 }, 'i' }, + { { STATE_EPC5 }, 'i' }, + { { STATE_EPC6 }, 'i' }, + { { STATE_EPS2 }, 'i' }, + { { STATE_EPS3 }, 'i' }, + { { STATE_EPS4 }, 'i' }, + { { STATE_EPS5 }, 'i' }, + { { STATE_EPS6 }, 'i' }, + { { STATE_InOCDMode }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wait_args[] = { + { { OPERAND_s }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wait_stateArgs[] = { + { { STATE_PSINTLEVEL }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_interrupt_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_interrupt_stateArgs[] = { + { { STATE_INTERRUPT }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intset_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intset_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intclear_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intclear_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_intenable_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_intenable_stateArgs[] = { + { { STATE_INTENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intenable_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intenable_stateArgs[] = { + { { STATE_INTENABLE }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_intenable_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_intenable_stateArgs[] = { + { { STATE_INTENABLE }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_break_args[] = { + { { OPERAND_imms }, 'i' }, + { { OPERAND_immt }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_break_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSINTLEVEL }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_break_n_args[] = { + { { OPERAND_imms }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_break_n_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSINTLEVEL }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreaka0_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreaka0_stateArgs[] = { + { { STATE_DBREAKA0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreaka0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreaka0_stateArgs[] = { + { { STATE_DBREAKA0 }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreaka0_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreaka0_stateArgs[] = { + { { STATE_DBREAKA0 }, 'm' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreakc0_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreakc0_stateArgs[] = { + { { STATE_DBREAKC0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreakc0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreakc0_stateArgs[] = { + { { STATE_DBREAKC0 }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreakc0_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreakc0_stateArgs[] = { + { { STATE_DBREAKC0 }, 'm' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreaka1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreaka1_stateArgs[] = { + { { STATE_DBREAKA1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreaka1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreaka1_stateArgs[] = { + { { STATE_DBREAKA1 }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreaka1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreaka1_stateArgs[] = { + { { STATE_DBREAKA1 }, 'm' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreakc1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreakc1_stateArgs[] = { + { { STATE_DBREAKC1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreakc1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreakc1_stateArgs[] = { + { { STATE_DBREAKC1 }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreakc1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreakc1_stateArgs[] = { + { { STATE_DBREAKC1 }, 'm' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreaka0_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreaka0_stateArgs[] = { + { { STATE_IBREAKA0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreaka0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreaka0_stateArgs[] = { + { { STATE_IBREAKA0 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreaka0_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreaka0_stateArgs[] = { + { { STATE_IBREAKA0 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreaka1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreaka1_stateArgs[] = { + { { STATE_IBREAKA1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreaka1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreaka1_stateArgs[] = { + { { STATE_IBREAKA1 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreaka1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreaka1_stateArgs[] = { + { { STATE_IBREAKA1 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreakenable_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreakenable_stateArgs[] = { + { { STATE_IBREAKENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreakenable_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreakenable_stateArgs[] = { + { { STATE_IBREAKENABLE }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreakenable_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreakenable_stateArgs[] = { + { { STATE_IBREAKENABLE }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_debugcause_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_debugcause_stateArgs[] = { + { { STATE_DEBUGCAUSE }, 'i' }, + { { STATE_DBNUM }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_debugcause_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_debugcause_stateArgs[] = { + { { STATE_DEBUGCAUSE }, 'o' }, + { { STATE_DBNUM }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_debugcause_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_debugcause_stateArgs[] = { + { { STATE_DEBUGCAUSE }, 'm' }, + { { STATE_DBNUM }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_icount_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_icount_stateArgs[] = { + { { STATE_ICOUNT }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_icount_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_icount_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_ICOUNT }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_icount_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_icount_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_ICOUNT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_icountlevel_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_icountlevel_stateArgs[] = { + { { STATE_ICOUNTLEVEL }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_icountlevel_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_icountlevel_stateArgs[] = { + { { STATE_ICOUNTLEVEL }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_icountlevel_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_icountlevel_stateArgs[] = { + { { STATE_ICOUNTLEVEL }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ddr_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ddr_stateArgs[] = { + { { STATE_DDR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ddr_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ddr_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_DDR }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ddr_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ddr_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_DDR }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfdo_args[] = { + { { OPERAND_imms }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfdo_stateArgs[] = { + { { STATE_InOCDMode }, 'm' }, + { { STATE_EPC6 }, 'i' }, + { { STATE_PSWOE }, 'o' }, + { { STATE_PSCALLINC }, 'o' }, + { { STATE_PSOWB }, 'o' }, + { { STATE_PSUM }, 'o' }, + { { STATE_PSEXCM }, 'o' }, + { { STATE_PSINTLEVEL }, 'o' }, + { { STATE_EPS6 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfdd_stateArgs[] = { + { { STATE_InOCDMode }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_mmid_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_mmid_stateArgs[] = { + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bbool1_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_bs }, 'i' }, + { { OPERAND_bt }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bbool4_args[] = { + { { OPERAND_bt }, 'o' }, + { { OPERAND_bs4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bbool8_args[] = { + { { OPERAND_bt }, 'o' }, + { { OPERAND_bs8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bbranch_args[] = { + { { OPERAND_bs }, 'i' }, + { { OPERAND_label8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bmove_args[] = { + { { OPERAND_arr }, 'm' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_bt }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_RSR_BR_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_brall }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_WSR_BR_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_brall }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_XSR_BR_args[] = { + { { OPERAND_art }, 'm' }, + { { OPERAND_brall }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccount_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccount_stateArgs[] = { + { { STATE_CCOUNT }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccount_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccount_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_CCOUNT }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccount_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccount_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_CCOUNT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccompare0_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccompare0_stateArgs[] = { + { { STATE_CCOMPARE0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccompare0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccompare0_stateArgs[] = { + { { STATE_CCOMPARE0 }, 'o' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccompare0_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccompare0_stateArgs[] = { + { { STATE_CCOMPARE0 }, 'm' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccompare1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccompare1_stateArgs[] = { + { { STATE_CCOMPARE1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccompare1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccompare1_stateArgs[] = { + { { STATE_CCOMPARE1 }, 'o' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccompare1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccompare1_stateArgs[] = { + { { STATE_CCOMPARE1 }, 'm' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_icache_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_icache_lock_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm4x16 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_icache_inv_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_licx_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sicx_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_dcache_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_dcache_ind_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm4x16 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_dcache_inv_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_dpf_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_dcache_lock_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm4x16 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sdct_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_ldct_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_idtlb_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_idtlb_stateArgs[] = { + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rdtlb_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wdtlb_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wdtlb_stateArgs[] = { + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_iitlb_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_ritlb_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_witlb_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_cpenable_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_cpenable_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_cpenable_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_cpenable_stateArgs[] = { + { { STATE_CPENABLE }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_cpenable_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_cpenable_stateArgs[] = { + { { STATE_CPENABLE }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_clamp_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_tp7 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_minmax_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_nsa_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sx_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_tp7 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l32ai_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32ri_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32c1i_args[] = { + { { OPERAND_art }, 'm' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32c1i_stateArgs[] = { + { { STATE_SCOMPARE1 }, 'i' }, + { { STATE_XTSYNC }, 'i' }, + { { STATE_SCOMPARE1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_scompare1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_scompare1_stateArgs[] = { + { { STATE_SCOMPARE1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_scompare1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_scompare1_stateArgs[] = { + { { STATE_SCOMPARE1 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_scompare1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_scompare1_stateArgs[] = { + { { STATE_SCOMPARE1 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_atomctl_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_atomctl_stateArgs[] = { + { { STATE_ATOMCTL }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_atomctl_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_atomctl_stateArgs[] = { + { { STATE_ATOMCTL }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_atomctl_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_atomctl_stateArgs[] = { + { { STATE_ATOMCTL }, 'm' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_fcr_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_fcr_stateArgs[] = { + { { STATE_RoundMode }, 'i' }, + { { STATE_InvalidEnable }, 'i' }, + { { STATE_DivZeroEnable }, 'i' }, + { { STATE_OverflowEnable }, 'i' }, + { { STATE_UnderflowEnable }, 'i' }, + { { STATE_InexactEnable }, 'i' }, + { { STATE_FPreserved20 }, 'i' }, + { { STATE_FPreserved5 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_fcr_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_fcr_stateArgs[] = { + { { STATE_RoundMode }, 'o' }, + { { STATE_InvalidEnable }, 'o' }, + { { STATE_DivZeroEnable }, 'o' }, + { { STATE_OverflowEnable }, 'o' }, + { { STATE_UnderflowEnable }, 'o' }, + { { STATE_InexactEnable }, 'o' }, + { { STATE_FPreserved20 }, 'o' }, + { { STATE_FPreserved5 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_fsr_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_fsr_stateArgs[] = { + { { STATE_InvalidFlag }, 'i' }, + { { STATE_DivZeroFlag }, 'i' }, + { { STATE_OverflowFlag }, 'i' }, + { { STATE_UnderflowFlag }, 'i' }, + { { STATE_InexactFlag }, 'i' }, + { { STATE_FPreserved20a }, 'i' }, + { { STATE_FPreserved7 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_fsr_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_fsr_stateArgs[] = { + { { STATE_InvalidFlag }, 'o' }, + { { STATE_DivZeroFlag }, 'o' }, + { { STATE_OverflowFlag }, 'o' }, + { { STATE_UnderflowFlag }, 'o' }, + { { STATE_InexactFlag }, 'o' }, + { { STATE_FPreserved20a }, 'o' }, + { { STATE_FPreserved7 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_stateArgs[] = { + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_mac_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_mac_stateArgs[] = { + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_cmov_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_bt }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_cmov_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_mov_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_mov_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_mov2_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_mov2_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_cmp_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_cmp_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_float_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_float_stateArgs[] = { + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_int_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_int_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_rfr_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_rfr_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_wfr_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_wfr_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_lsi_args[] = { + { { OPERAND_frt }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_cimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_lsi_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_lsiu_args[] = { + { { OPERAND_frt }, 'o' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_cimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_lsiu_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_lsx_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_lsx_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_lsxu_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_lsxu_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_ssi_args[] = { + { { OPERAND_frt }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_cimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_ssi_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_ssiu_args[] = { + { { OPERAND_frt }, 'i' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_cimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_ssiu_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_ssx_args[] = { + { { OPERAND_frr }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_ssx_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_ssxu_args[] = { + { { OPERAND_frr }, 'i' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_fp_ssxu_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_ARGMAX_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_ARGMAX_stateArgs[] = { + { { STATE_ARG_MAX_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_HSAR_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_HSAR_stateArgs[] = { + { { STATE_HSAR3 }, 'i' }, + { { STATE_HSAR2 }, 'i' }, + { { STATE_HSAR1 }, 'i' }, + { { STATE_HSAR0 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_HSAR2SAR_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_HSAR2SAR_stateArgs[] = { + { { STATE_SAR3 }, 'o' }, + { { STATE_SAR2 }, 'o' }, + { { STATE_SAR1 }, 'o' }, + { { STATE_SAR0 }, 'o' }, + { { STATE_HSAR3 }, 'i' }, + { { STATE_HSAR2 }, 'i' }, + { { STATE_HSAR1 }, 'i' }, + { { STATE_HSAR0 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_INTERP_EXT_N_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_INTERP_EXT_N_stateArgs[] = { + { { STATE_INTERP_EXT_N }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_INTERP_EXT_L_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_INTERP_EXT_L_stateArgs[] = { + { { STATE_INTERP_EXT_L }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_LLR_BUF_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper70_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_LLR_BUF_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_LLR_POS_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_LLR_POS_stateArgs[] = { + { { STATE_LLR_POS }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_MAX_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_MAX_stateArgs[] = { + { { STATE_MAX_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_NCO_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_NCO_stateArgs[] = { + { { STATE_NCO_COUNTER }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_PERM_REG_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_PERM_REG_stateArgs[] = { + { { STATE_PERM_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_PHASOR_N_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_PHASOR_N_stateArgs[] = { + { { STATE_PHASOR_N }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_PHASOR_OFFSET_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_PHASOR_OFFSET_stateArgs[] = { + { { STATE_PHASOR_OFFSET }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_SAR_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_SAR_stateArgs[] = { + { { STATE_SAR3 }, 'i' }, + { { STATE_SAR2 }, 'i' }, + { { STATE_SAR1 }, 'i' }, + { { STATE_SAR0 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_SCALE_REG_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_SCALE_REG_stateArgs[] = { + { { STATE_SCALE_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_SMOD_BUF_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_SMOD_BUF_stateArgs[] = { + { { STATE_SMOD_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_SMOD_OFFSET_TABLE_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_SMOD_OFFSET_TABLE_stateArgs[] = { + { { STATE_SMOD_OFFSET_TABLE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_SMOD_POS_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_SMOD_POS_stateArgs[] = { + { { STATE_SMOD_POS }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_SOV_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_SOV_stateArgs[] = { + { { STATE_SOV }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_WGHT_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_GET_WGHT_stateArgs[] = { + { { STATE_WEIGHT_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_ARGMAX_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_ARGMAX_stateArgs[] = { + { { STATE_ARG_MAX_REG }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_EXT_REGS_args[] = { + { { OPERAND_dsp340050b49a6c_oper88_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper59_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_EXT_REGS_stateArgs[] = { + { { STATE_INTERP_EXT_N }, 'o' }, + { { STATE_INTERP_EXT_L }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_HSAR_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_HSAR_stateArgs[] = { + { { STATE_HSAR0 }, 'o' }, + { { STATE_HSAR1 }, 'o' }, + { { STATE_HSAR2 }, 'o' }, + { { STATE_HSAR3 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_LLR_BUF_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper78_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_LLR_BUF_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_LLR_POS_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_LLR_POS_stateArgs[] = { + { { STATE_LLR_POS }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_MAX_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_MAX_stateArgs[] = { + { { STATE_MAX_REG }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_NCO_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_NCO_stateArgs[] = { + { { STATE_NCO_COUNTER }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_PERM_REG_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_PERM_REG_stateArgs[] = { + { { STATE_PERM_REG }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_PHASOR_N_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_PHASOR_N_stateArgs[] = { + { { STATE_PHASOR_N }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_PHASOR_OFFSET_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_PHASOR_OFFSET_stateArgs[] = { + { { STATE_PHASOR_OFFSET }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_SAR_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_SAR_stateArgs[] = { + { { STATE_SAR0 }, 'o' }, + { { STATE_SAR1 }, 'o' }, + { { STATE_SAR2 }, 'o' }, + { { STATE_SAR3 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_SCALE_REG_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_SCALE_REG_stateArgs[] = { + { { STATE_SCALE_REG }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_SMOD_BUF_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_SMOD_BUF_stateArgs[] = { + { { STATE_SMOD_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_SMOD_OFFSET_TABLE_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_SMOD_OFFSET_TABLE_stateArgs[] = { + { { STATE_SMOD_OFFSET_TABLE }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_SMOD_POS_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_SMOD_POS_stateArgs[] = { + { { STATE_SMOD_POS }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_SOV_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_SOV_stateArgs[] = { + { { STATE_SOV }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_WGHT_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SET_WGHT_stateArgs[] = { + { { STATE_WEIGHT_REG }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC2X32_args[] = { + { { OPERAND_dsp340050b49a6c_oper71_reg }, 'm' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper72_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper73_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC2X32_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC2X64_0_args[] = { + { { OPERAND_dsp340050b49a6c_oper71_reg }, 'm' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper74_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC2X64_0_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC2X64_1_args[] = { + { { OPERAND_dsp340050b49a6c_oper71_reg }, 'm' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper74_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC2X64_1_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC2X64_2_args[] = { + { { OPERAND_dsp340050b49a6c_oper71_reg }, 'm' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper74_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC2X64_2_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC2X64_3_args[] = { + { { OPERAND_dsp340050b49a6c_oper71_reg }, 'm' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper74_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC2X64_3_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC32_R_args[] = { + { { OPERAND_dsp340050b49a6c_oper71_reg }, 'm' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper72_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper75_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC32_R_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC_IH_args[] = { + { { OPERAND_dsp340050b49a6c_oper71_reg }, 'm' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper76_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC_IH_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC_IL_args[] = { + { { OPERAND_dsp340050b49a6c_oper71_reg }, 'm' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper76_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC_IL_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC_RH_args[] = { + { { OPERAND_dsp340050b49a6c_oper71_reg }, 'm' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper76_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC_RH_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC_RL_args[] = { + { { OPERAND_dsp340050b49a6c_oper71_reg }, 'm' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper76_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LAC_RL_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LCM_args[] = { + { { OPERAND_dsp340050b49a6c_oper77_reg }, 'o' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper74_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LCM_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LCM_PINC_args[] = { + { { OPERAND_dsp340050b49a6c_oper77_reg }, 'o' }, + { { OPERAND_art }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper76_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LCM_PINC_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LCM_PINC_X_args[] = { + { { OPERAND_dsp340050b49a6c_oper77_reg }, 'o' }, + { { OPERAND_art }, 'm' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LCM_PINC_X_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LCM_U_args[] = { + { { OPERAND_dsp340050b49a6c_oper77_reg }, 'o' }, + { { OPERAND_art }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper76_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LCM_U_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LCM_X_args[] = { + { { OPERAND_dsp340050b49a6c_oper77_reg }, 'o' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LCM_X_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LCM_XU_args[] = { + { { OPERAND_dsp340050b49a6c_oper77_reg }, 'o' }, + { { OPERAND_art }, 'm' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LCM_XU_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LP_args[] = { + { { OPERAND_dsp340050b49a6c_oper79_reg }, 'm' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper76_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LP_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LP_X_args[] = { + { { OPERAND_dsp340050b49a6c_oper79_reg }, 'm' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LP_X_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LQ_args[] = { + { { OPERAND_dsp340050b49a6c_oper79_reg }, 'm' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper76_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LQ_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LQ_X_args[] = { + { { OPERAND_dsp340050b49a6c_oper79_reg }, 'm' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LQ_X_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LUT0_args[] = { + { { OPERAND_dsp340050b49a6c_oper77_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper80_reg }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LUT0_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LUT1_args[] = { + { { OPERAND_dsp340050b49a6c_oper77_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper80_reg }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LUT1_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LUT2_args[] = { + { { OPERAND_dsp340050b49a6c_oper77_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper80_reg }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LUT2_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LUT3_args[] = { + { { OPERAND_dsp340050b49a6c_oper77_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper80_reg }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LUT3_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC2X32_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper72_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper84_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC2X32_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC2X64_0_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper85_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC2X64_0_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC2X64_1_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper85_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC2X64_1_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC2X64_2_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper85_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC2X64_2_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC2X64_3_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper85_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC2X64_3_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC32_R_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper72_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper86_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC32_R_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC_IH_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper87_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC_IH_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC_IL_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper87_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC_IL_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC_RH_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper87_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC_RH_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC_RL_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper87_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SAC_RL_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SCM_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper85_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SCM_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SCM_PINC_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper87_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SCM_PINC_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SCM_PINC_X_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SCM_PINC_X_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SCM_U_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper87_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SCM_U_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SCM_X_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SCM_X_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SCM_XU_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SCM_XU_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_STORE_P_args[] = { + { { OPERAND_dsp340050b49a6c_oper79_reg }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper85_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_STORE_P_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_STORE_Q_args[] = { + { { OPERAND_dsp340050b49a6c_oper79_reg }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper85_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_STORE_Q_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_AR2CM_DUP_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_AR2CM_DUP_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_AR2CM_LN_args[] = { + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'm' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper52_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_AR2CM_LN_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_AR2CM_LN_I_args[] = { + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'm' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper52_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_AR2CM_LN_I_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_AR2CM_LN_R_args[] = { + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'm' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper52_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_AR2CM_LN_R_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_AR2PQ_LN_args[] = { + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'm' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper52_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper57_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_AR2PQ_LN_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_AR2SAR_DUP_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_AR2SAR_DUP_stateArgs[] = { + { { STATE_SAR3 }, 'o' }, + { { STATE_SAR2 }, 'o' }, + { { STATE_SAR1 }, 'o' }, + { { STATE_SAR0 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CLRAC_args[] = { + { { OPERAND_dsp340050b49a6c_oper63_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_CLRAC_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CLRCM_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_CLRCM_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CM2AR_LN_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper64_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CM2AR_LN_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CM2AR_LN_I_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper64_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CM2AR_LN_I_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CM2AR_LN_R_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper64_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CM2AR_LN_R_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_COMB_AR_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CONJ_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CONJ_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOV2AC32_I_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper71_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_MOV2AC32_I_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOV2AC32_R_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper71_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_MOV2AC32_R_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOV2CM2PQ_args[] = { + { { OPERAND_dsp340050b49a6c_oper65_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOV2CM2PQ_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVAC_args[] = { + { { OPERAND_dsp340050b49a6c_oper63_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVAC_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVAC_I_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper66_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVAC_I_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVAC_I2R_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper63_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVAC_I2R_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVAC_R_args[] = { + { { OPERAND_dsp340050b49a6c_oper66_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVAC_R_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVAC_R2I_args[] = { + { { OPERAND_dsp340050b49a6c_oper63_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVAC_R2I_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVAR2_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCM_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCM_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCM2PQ_args[] = { + { { OPERAND_dsp340050b49a6c_oper81_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCM2PQ_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND_0_args[] = { + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND_0_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND_1_args[] = { + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND_1_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND_2_args[] = { + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND_2_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND_3_args[] = { + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND_3_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND_4_args[] = { + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND_4_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND_5_args[] = { + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND_5_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND_6_args[] = { + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND_6_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND_7_args[] = { + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND_7_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND8_0_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND8_0_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND8_1_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND8_1_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND8_2_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND8_2_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND8_3_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND8_3_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND8_4_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND8_4_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND8_5_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND8_5_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND8_6_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND8_6_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND8_7_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVCND8_7_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOV_I_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOV_I_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVPQ2PQ_args[] = { + { { OPERAND_dsp340050b49a6c_oper65_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOVPQ2PQ_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOV_R_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOV_R_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_NEGCM_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_NEGCM_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_POP16LLR_1_args[] = { + { { OPERAND_dsp340050b49a6c_oper63_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_POP16LLR_1_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_LLR_POS }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_PQ2CM_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_PQ2CM_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SWAPAC_R_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper54_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_SWAPAC_R_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SWAPAC_RI_args[] = { + { { OPERAND_dsp340050b49a6c_oper63_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SWAPAC_RI_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SWAPB_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ADD2AC_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper52_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ADD2AC_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAR0 }, 'i' }, + { { STATE_SAR1 }, 'i' }, + { { STATE_SAR2 }, 'i' }, + { { STATE_SAR3 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ADDAC_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper54_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ADDAC_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CDOT_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_CDOT_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CDOTAC_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_CDOTAC_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CDOTACS_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_CDOTACS_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CMAC_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_CMAC_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CMACS_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_CMACS_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CMPY_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_CMPY_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CMPY2CM_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CMPY2CM_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CMPY2PQ_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_CMPY2PQ_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CMPYS_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_CMPYS_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CMPYXP2PQ_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper52_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CMPYXP2PQ_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_COMB32_args[] = { + { { OPERAND_dsp340050b49a6c_oper65_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper66_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper67_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_COMB32_stateArgs[] = { + { { STATE_WEIGHT_REG }, 'i' }, + { { STATE_SCALE_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_DOT_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_DOT_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_DOTAC_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_DOTAC_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_DOTACS_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_DOTACS_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LIN_INT_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LIN_INT_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_INTERP_EXT_L }, 'i' }, + { { STATE_INTERP_EXT_N }, 'i' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_SCALE_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LLRPRE1_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper54_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_LLRPRE1_stateArgs[] = { + { { STATE_PERM_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LLRPRE2_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper66_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper78_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LLRPRE2_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_LLR_POS }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MAC_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_MAC_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MAC8_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_MAC8_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MACD8_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_MACD8_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MACPQXP_0_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_MACPQXP_0_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MACPQXP_1_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_MACPQXP_1_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MACPQXP_2_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_MACPQXP_2_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MACPQXP_3_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_MACPQXP_3_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MACS_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_MACS_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MACXP2_0_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_MACXP2_0_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MACXP2_1_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_MACXP2_1_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MACXP_0_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_MACXP_0_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MACXP_1_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_MACXP_1_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MACXP_2_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_MACXP_2_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MACXP_3_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_MACXP_3_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOV2AC_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper52_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MOV2AC_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAR0 }, 'i' }, + { { STATE_SAR1 }, 'i' }, + { { STATE_SAR2 }, 'i' }, + { { STATE_SAR3 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPY_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_MPY_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPY2CM_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPY2CM_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPY2PQ_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_MPY2PQ_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPY8_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_MPY8_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYADD8_2CM_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYADD8_2CM_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYD8_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYD8_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYPQXP_0_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYPQXP_0_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYPQXP_1_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYPQXP_1_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYPQXP_2_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYPQXP_2_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYPQXP_3_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYPQXP_3_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYS_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYS_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYXP2PQ_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper52_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYXP2PQ_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYXP2_0_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYXP2_0_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYXP2_1_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYXP2_1_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYXP_0_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYXP_0_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYXP_1_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYXP_1_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYXP_2_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYXP_2_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYXP_3_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_MPYXP_3_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_NORMACD_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_NORMACD_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_NORMACPQ_I_args[] = { + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_NORMACPQ_I_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_NORMACPQ_R_args[] = { + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_NORMACPQ_R_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_NORMD_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_NORMD_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_NORMPYPQ_I_args[] = { + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_NORMPYPQ_I_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_NORMPYPQ_R_args[] = { + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_NORMPYPQ_R_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RCMAC_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_RCMAC_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RCMPY_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_RCMPY_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RCMPY2CM_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RCMPY2CM_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RFIR_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper54_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper59_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RFIR_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RFIRA_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper54_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper59_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RFIRA_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RFIRD_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper54_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RFIRD_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RFIRDA_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper54_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RFIRDA_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RMAC_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_RMAC_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RMPY_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_RMPY_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RMPY2CM_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RMPY2CM_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SMOD_ALIGN_args[] = { + { { OPERAND_dsp340050b49a6c_oper63_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper78_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SMOD_ALIGN_stateArgs[] = { + { { STATE_SMOD_BUF }, 'm' }, + { { STATE_SMOD_POS }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SMOD_SCR_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper66_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SMOD_SCR_stateArgs[] = { + { { STATE_PERM_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SUB2AC_args[] = { + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper52_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SUB2AC_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAR0 }, 'i' }, + { { STATE_SAR1 }, 'i' }, + { { STATE_SAR2 }, 'i' }, + { { STATE_SAR3 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_WGHT32_args[] = { + { { OPERAND_dsp340050b49a6c_oper65_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper50_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper62_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_WGHT32_stateArgs[] = { + { { STATE_WEIGHT_REG }, 'i' }, + { { STATE_SCALE_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CLRTIEP_args[] = { + { { OPERAND_dsp340050b49a6c_oper61_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CLRTIEP_stateArgs[] = { + { { STATE_EXPSTATE }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_EXT_2FIFO_0_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXT_2FIFO_0_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_EXT_2FIFO_0_intfArgs[] = { + INTERFACE_OUTQ0_128 +}; + +static xtensa_arg_internal Iclass_iclass_EXT_2FIFO_1_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXT_2FIFO_1_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_EXT_2FIFO_1_intfArgs[] = { + INTERFACE_OUTQ1_128 +}; + +static xtensa_arg_internal Iclass_iclass_EXT_2FIFO_2_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXT_2FIFO_2_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_EXT_2FIFO_2_intfArgs[] = { + INTERFACE_OUTQ2_128 +}; + +static xtensa_arg_internal Iclass_iclass_EXT_2FIFO_3_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXT_2FIFO_3_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_EXT_2FIFO_3_intfArgs[] = { + INTERFACE_OUTQ3_128 +}; + +static xtensa_arg_internal Iclass_iclass_EXT_R2FIFO_0_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXT_R2FIFO_0_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_EXT_R2FIFO_0_intfArgs[] = { + INTERFACE_OUTQ0_128 +}; + +static xtensa_arg_internal Iclass_iclass_EXT_R2FIFO_1_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXT_R2FIFO_1_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_EXT_R2FIFO_1_intfArgs[] = { + INTERFACE_OUTQ1_128 +}; + +static xtensa_arg_internal Iclass_iclass_EXT_R2FIFO_2_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXT_R2FIFO_2_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_EXT_R2FIFO_2_intfArgs[] = { + INTERFACE_OUTQ2_128 +}; + +static xtensa_arg_internal Iclass_iclass_EXT_R2FIFO_3_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXT_R2FIFO_3_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_EXT_R2FIFO_3_intfArgs[] = { + INTERFACE_OUTQ3_128 +}; + +static xtensa_arg_internal Iclass_iclass_LUT_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LUT_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_LUT_intfArgs[] = { + INTERFACE_LU128_Out, + INTERFACE_LU128_In +}; + +static xtensa_arg_internal Iclass_iclass_LUT_AR_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LUT_AR_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_LUT_AR_intfArgs[] = { + INTERFACE_LU128_Out, + INTERFACE_LU128_In +}; + +static xtensa_arg_internal Iclass_iclass_LUT_IEXT_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LUT_IEXT_stateArgs[] = { + { { STATE_INTERP_EXT_L }, 'i' }, + { { STATE_INTERP_EXT_N }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_LUT_IEXT_intfArgs[] = { + INTERFACE_LU128_Out, + INTERFACE_LU128_In +}; + +static xtensa_arg_internal Iclass_iclass_LUT_PHASOR_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LUT_PHASOR_stateArgs[] = { + { { STATE_PHASOR_N }, 'i' }, + { { STATE_PHASOR_OFFSET }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_LUT_PHASOR_intfArgs[] = { + INTERFACE_LU128_Out, + INTERFACE_LU128_In +}; + +static xtensa_arg_internal Iclass_iclass_LUT_REXT_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LUT_REXT_stateArgs[] = { + { { STATE_INTERP_EXT_L }, 'i' }, + { { STATE_INTERP_EXT_N }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_LUT_REXT_intfArgs[] = { + INTERFACE_LU128_Out, + INTERFACE_LU128_In +}; + +static xtensa_arg_internal Iclass_iclass_LUT_WRITE_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper64_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper52_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LUT_WRITE_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_LUT_WRITE_intfArgs[] = { + INTERFACE_LU128_Out, + INTERFACE_LU128_In +}; + +static xtensa_interface Iclass_iclass_MOVEQ128_0_intfArgs[] = { + INTERFACE_OUTQ0_128, + INTERFACE_INQ0_128 +}; + +static xtensa_interface Iclass_iclass_MOVEQ128_1_intfArgs[] = { + INTERFACE_OUTQ1_128, + INTERFACE_INQ1_128 +}; + +static xtensa_interface Iclass_iclass_MOVEQ128_2_intfArgs[] = { + INTERFACE_OUTQ2_128, + INTERFACE_INQ2_128 +}; + +static xtensa_interface Iclass_iclass_MOVEQ128_3_intfArgs[] = { + INTERFACE_OUTQ3_128, + INTERFACE_INQ3_128 +}; + +static xtensa_interface Iclass_iclass_MOVEQ128_4_intfArgs[] = { + INTERFACE_OUTQ4_128, + INTERFACE_INQ4_128 +}; + +static xtensa_interface Iclass_iclass_MOVEQ128_5_intfArgs[] = { + INTERFACE_OUTQ5_128, + INTERFACE_INQ5_128 +}; + +static xtensa_interface Iclass_iclass_MOVEQ32_0_intfArgs[] = { + INTERFACE_OUTQ0_32, + INTERFACE_INQ0_32 +}; + +static xtensa_interface Iclass_iclass_MOVEQ32_1_intfArgs[] = { + INTERFACE_OUTQ1_32, + INTERFACE_INQ1_32 +}; + +static xtensa_interface Iclass_iclass_MOVEQ32_2_intfArgs[] = { + INTERFACE_OUTQ2_32, + INTERFACE_INQ2_32 +}; + +static xtensa_interface Iclass_iclass_MOVEQ32_3_intfArgs[] = { + INTERFACE_OUTQ3_32, + INTERFACE_INQ3_32 +}; + +static xtensa_arg_internal Iclass_iclass_NCO_UPDATE_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_NCO_UPDATE_stateArgs[] = { + { { STATE_NCO_COUNTER }, 'm' }, + { { STATE_PHASOR_N }, 'i' }, + { { STATE_PHASOR_OFFSET }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_NCO_UPDATE_intfArgs[] = { + INTERFACE_LU128_Out, + INTERFACE_LU128_In +}; + +static xtensa_arg_internal Iclass_iclass_POP128_0_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_POP128_0_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_0_intfArgs[] = { + INTERFACE_INQ0_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_1_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_POP128_1_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_1_intfArgs[] = { + INTERFACE_INQ1_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_2_intfArgs[] = { + INTERFACE_INQ2_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_3_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_POP128_3_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_3_intfArgs[] = { + INTERFACE_INQ3_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_4_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_POP128_4_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_4_intfArgs[] = { + INTERFACE_INQ4_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_5_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_POP128_5_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_5_intfArgs[] = { + INTERFACE_INQ5_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2CMPQ_0_args[] = { + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2CMPQ_0_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_2CMPQ_0_intfArgs[] = { + INTERFACE_INQ0_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2CMPQ_1_args[] = { + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2CMPQ_1_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_2CMPQ_1_intfArgs[] = { + INTERFACE_INQ1_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2CMPQ_2_args[] = { + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2CMPQ_2_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_2CMPQ_2_intfArgs[] = { + INTERFACE_INQ2_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2CMPQ_3_args[] = { + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2CMPQ_3_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_2CMPQ_3_intfArgs[] = { + INTERFACE_INQ3_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2M_0_args[] = { + { { OPERAND_ars }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper83_imm }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_2M_0_intfArgs[] = { + INTERFACE_INQ0_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2M_1_args[] = { + { { OPERAND_ars }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper83_imm }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_2M_1_intfArgs[] = { + INTERFACE_INQ1_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2M_2_args[] = { + { { OPERAND_ars }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper83_imm }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_2M_2_intfArgs[] = { + INTERFACE_INQ2_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2M_3_args[] = { + { { OPERAND_ars }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper83_imm }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_2M_3_intfArgs[] = { + INTERFACE_INQ3_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2PQ_0_args[] = { + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2PQ_0_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_2PQ_0_intfArgs[] = { + INTERFACE_INQ0_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2PQ_1_args[] = { + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2PQ_1_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_2PQ_1_intfArgs[] = { + INTERFACE_INQ1_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2PQ_2_args[] = { + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2PQ_2_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_2PQ_2_intfArgs[] = { + INTERFACE_INQ2_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2PQ_3_args[] = { + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2PQ_3_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_2PQ_3_intfArgs[] = { + INTERFACE_INQ3_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2PQ_4_args[] = { + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2PQ_4_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_2PQ_4_intfArgs[] = { + INTERFACE_INQ4_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2PQ_5_args[] = { + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_POP128_2PQ_5_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP128_2PQ_5_intfArgs[] = { + INTERFACE_INQ5_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP2X128_2PQ_01_args[] = { + { { OPERAND_dsp340050b49a6c_oper65_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_POP2X128_2PQ_01_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP2X128_2PQ_01_intfArgs[] = { + INTERFACE_INQ0_128, + INTERFACE_INQ1_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP2X128_2PQ_03_args[] = { + { { OPERAND_dsp340050b49a6c_oper65_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_POP2X128_2PQ_03_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP2X128_2PQ_03_intfArgs[] = { + INTERFACE_INQ0_128, + INTERFACE_INQ3_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP2X128_2PQ_21_args[] = { + { { OPERAND_dsp340050b49a6c_oper65_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_POP2X128_2PQ_21_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP2X128_2PQ_21_intfArgs[] = { + INTERFACE_INQ2_128, + INTERFACE_INQ1_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP2X128_2PQ_23_args[] = { + { { OPERAND_dsp340050b49a6c_oper65_reg }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_POP2X128_2PQ_23_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_POP2X128_2PQ_23_intfArgs[] = { + INTERFACE_INQ2_128, + INTERFACE_INQ3_128 +}; + +static xtensa_arg_internal Iclass_iclass_POP32_0_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_interface Iclass_iclass_POP32_0_intfArgs[] = { + INTERFACE_INQ0_32 +}; + +static xtensa_arg_internal Iclass_iclass_POP32_1_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_interface Iclass_iclass_POP32_1_intfArgs[] = { + INTERFACE_INQ1_32 +}; + +static xtensa_arg_internal Iclass_iclass_POP32_2_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_interface Iclass_iclass_POP32_2_intfArgs[] = { + INTERFACE_INQ2_32 +}; + +static xtensa_arg_internal Iclass_iclass_POP32_3_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_interface Iclass_iclass_POP32_3_intfArgs[] = { + INTERFACE_INQ3_32 +}; + +static xtensa_arg_internal Iclass_iclass_PUSH128_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper78_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_PUSH128_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_PUSH128_intfArgs[] = { + INTERFACE_OUTQ0_128, + INTERFACE_OUTQ0_128_KILL, + INTERFACE_OUTQ1_128, + INTERFACE_OUTQ1_128_KILL, + INTERFACE_OUTQ2_128, + INTERFACE_OUTQ2_128_KILL, + INTERFACE_OUTQ3_128, + INTERFACE_OUTQ3_128_KILL, + INTERFACE_OUTQ4_128, + INTERFACE_OUTQ4_128_KILL, + INTERFACE_OUTQ5_128, + INTERFACE_OUTQ5_128_KILL +}; + +static xtensa_arg_internal Iclass_iclass_PUSH128_M_args[] = { + { { OPERAND_ars }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper52_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper83_imm }, 'i' } +}; + +static xtensa_interface Iclass_iclass_PUSH128_M_intfArgs[] = { + INTERFACE_OUTQ0_128, + INTERFACE_OUTQ0_128_KILL, + INTERFACE_OUTQ1_128, + INTERFACE_OUTQ1_128_KILL, + INTERFACE_OUTQ2_128, + INTERFACE_OUTQ2_128_KILL, + INTERFACE_OUTQ3_128, + INTERFACE_OUTQ3_128_KILL +}; + +static xtensa_arg_internal Iclass_iclass_PUSH128_PQ_args[] = { + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper78_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_PUSH128_PQ_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_PUSH128_PQ_intfArgs[] = { + INTERFACE_OUTQ0_128, + INTERFACE_OUTQ0_128_KILL, + INTERFACE_OUTQ1_128, + INTERFACE_OUTQ1_128_KILL, + INTERFACE_OUTQ2_128, + INTERFACE_OUTQ2_128_KILL, + INTERFACE_OUTQ3_128, + INTERFACE_OUTQ3_128_KILL, + INTERFACE_OUTQ4_128, + INTERFACE_OUTQ4_128_KILL, + INTERFACE_OUTQ5_128, + INTERFACE_OUTQ5_128_KILL +}; + +static xtensa_arg_internal Iclass_iclass_PUSH2X128_PQ_args[] = { + { { OPERAND_dsp340050b49a6c_oper56_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper57_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_PUSH2X128_PQ_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_PUSH2X128_PQ_intfArgs[] = { + INTERFACE_OUTQ0_128, + INTERFACE_OUTQ1_128, + INTERFACE_OUTQ2_128, + INTERFACE_OUTQ3_128, + INTERFACE_OUTQ0_128_KILL, + INTERFACE_OUTQ1_128_KILL, + INTERFACE_OUTQ2_128_KILL, + INTERFACE_OUTQ3_128_KILL +}; + +static xtensa_arg_internal Iclass_iclass_PUSH32_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper59_imm }, 'i' } +}; + +static xtensa_interface Iclass_iclass_PUSH32_intfArgs[] = { + INTERFACE_OUTQ0_32, + INTERFACE_OUTQ0_32_KILL, + INTERFACE_OUTQ1_32, + INTERFACE_OUTQ1_32_KILL, + INTERFACE_OUTQ2_32, + INTERFACE_OUTQ2_32_KILL, + INTERFACE_OUTQ3_32, + INTERFACE_OUTQ3_32_KILL, + INTERFACE_OUTQ4_32, + INTERFACE_OUTQ4_32_KILL, + INTERFACE_OUTQ5_32, + INTERFACE_OUTQ5_32_KILL +}; + +static xtensa_arg_internal Iclass_iclass_QREADY_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper61_imm }, 'i' } +}; + +static xtensa_interface Iclass_iclass_QREADY_intfArgs[] = { + INTERFACE_INQ0_32_NOTRDY, + INTERFACE_INQ1_32_NOTRDY, + INTERFACE_INQ2_32_NOTRDY, + INTERFACE_INQ3_32_NOTRDY, + INTERFACE_OUTQ0_32_NOTRDY, + INTERFACE_OUTQ1_32_NOTRDY, + INTERFACE_OUTQ2_32_NOTRDY, + INTERFACE_OUTQ3_32_NOTRDY, + INTERFACE_OUTQ4_32_NOTRDY, + INTERFACE_OUTQ5_32_NOTRDY, + INTERFACE_INQ0_128_NOTRDY, + INTERFACE_INQ1_128_NOTRDY, + INTERFACE_INQ2_128_NOTRDY, + INTERFACE_INQ3_128_NOTRDY, + INTERFACE_INQ4_128_NOTRDY, + INTERFACE_INQ5_128_NOTRDY, + INTERFACE_OUTQ0_128_NOTRDY, + INTERFACE_OUTQ1_128_NOTRDY, + INTERFACE_OUTQ2_128_NOTRDY, + INTERFACE_OUTQ3_128_NOTRDY, + INTERFACE_OUTQ4_128_NOTRDY, + INTERFACE_OUTQ5_128_NOTRDY, + INTERFACE_SIGNALQ_NOTRDY +}; + +static xtensa_arg_internal Iclass_iclass_RDTIEP_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_interface Iclass_iclass_RDTIEP_intfArgs[] = { + INTERFACE_IMPWIRE +}; + +static xtensa_arg_internal Iclass_iclass_SETTIEP_args[] = { + { { OPERAND_dsp340050b49a6c_oper61_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SETTIEP_stateArgs[] = { + { { STATE_EXPSTATE }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_SMOD_LUT_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper78_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper57_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SMOD_LUT_stateArgs[] = { + { { STATE_SMOD_OFFSET_TABLE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_interface Iclass_iclass_SMOD_LUT_intfArgs[] = { + INTERFACE_LU128_Out, + INTERFACE_LU128_In +}; + +static xtensa_arg_internal Iclass_iclass_WRTBSIGQ_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_interface Iclass_iclass_WRTBSIGQ_intfArgs[] = { + INTERFACE_SIGNALQ +}; + +static xtensa_arg_internal Iclass_iclass_WRTBSIGQM_args[] = { + { { OPERAND_dsp340050b49a6c_oper61_imm }, 'i' } +}; + +static xtensa_interface Iclass_iclass_WRTBSIGQM_intfArgs[] = { + INTERFACE_SIGNALQ +}; + +static xtensa_arg_internal Iclass_iclass_WRTIEP_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_WRTIEP_stateArgs[] = { + { { STATE_EXPSTATE }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_WRTSIGQ_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_interface Iclass_iclass_WRTSIGQ_intfArgs[] = { + INTERFACE_SIGNALQ +}; + +static xtensa_arg_internal Iclass_iclass_ABS8_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ABS8_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ADD16_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper49_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ADD16_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ADD32_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper53_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ADD32_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ADDAC_I2R_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_ADDAC_I2R_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ADDAC_R2I_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_ADDAC_R2I_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ADDAR2_args[] = { + { { OPERAND_ars }, 'm' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ADDCM_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper53_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ADDCM_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ADDWRP_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper55_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ADDWRP_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_AND128_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper55_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_AND128_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ARGMAX8_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper53_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ARGMAX8_stateArgs[] = { + { { STATE_MAX_REG }, 'm' }, + { { STATE_ARG_MAX_REG }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASL_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper53_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASL_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASL32_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper55_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASL32_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASLACM_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper58_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASLACM_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASLM_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper59_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASLM_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASLM32_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper58_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASLM32_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASR_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper53_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASR_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASR32_args[] = { + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper55_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASR32_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASRAC_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper55_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASRAC_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASRM_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper59_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_ASRM_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_BITFEXT_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper60_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper61_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_BITFINS_args[] = { + { { OPERAND_art }, 'm' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper61_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper60_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CLB_C_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CLB_C_stateArgs[] = { + { { STATE_SAR3 }, 'o' }, + { { STATE_SAR2 }, 'o' }, + { { STATE_SAR1 }, 'o' }, + { { STATE_SAR0 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CLB_R_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CLB_R_stateArgs[] = { + { { STATE_SAR3 }, 'o' }, + { { STATE_SAR2 }, 'o' }, + { { STATE_SAR1 }, 'o' }, + { { STATE_SAR0 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CMP8_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CMP8_stateArgs[] = { + { { STATE_SOV }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CMP_I_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CMP_I_stateArgs[] = { + { { STATE_SOV }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CMP_R_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper47_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CMP_R_stateArgs[] = { + { { STATE_SOV }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXT_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper68_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper69_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXT_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAR3 }, 'i' }, + { { STATE_SAR2 }, 'i' }, + { { STATE_SAR1 }, 'i' }, + { { STATE_SAR0 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXT_R_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper68_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper69_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXT_R_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAR3 }, 'i' }, + { { STATE_SAR2 }, 'i' }, + { { STATE_SAR1 }, 'i' }, + { { STATE_SAR0 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXT32_I_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXT32_I_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXT32_R_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper48_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXT32_R_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXTUI4_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_EXTUI4_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LSLM_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper59_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LSLM_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LSRM_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper59_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_LSRM_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MAX8_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper55_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MAX8_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MEAN_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper55_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MEAN_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MEAN32_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper53_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MEAN32_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MIN8_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper55_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MIN8_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MINCLB_C_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MINCLB_C_stateArgs[] = { + { { STATE_HSAR3 }, 'm' }, + { { STATE_HSAR2 }, 'm' }, + { { STATE_HSAR1 }, 'm' }, + { { STATE_HSAR0 }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MINCLB_R_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_MINCLB_R_stateArgs[] = { + { { STATE_HSAR3 }, 'm' }, + { { STATE_HSAR2 }, 'm' }, + { { STATE_HSAR1 }, 'm' }, + { { STATE_HSAR0 }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_NOT128_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_NOT128_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_OR128_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper55_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_OR128_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_PERM_args[] = { + { { OPERAND_dsp340050b49a6c_oper82_reg }, 'm' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_PERM_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_REDAC_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_REDAC_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_REDAC2_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_REDAC2_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_REDAC4_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_REDAC4_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_REDACS_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_REDACS_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SMINCLB_C_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SMINCLB_C_stateArgs[] = { + { { STATE_HSAR3 }, 'o' }, + { { STATE_HSAR2 }, 'o' }, + { { STATE_HSAR1 }, 'o' }, + { { STATE_HSAR0 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SMINCLB_R_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SMINCLB_R_stateArgs[] = { + { { STATE_HSAR3 }, 'o' }, + { { STATE_HSAR2 }, 'o' }, + { { STATE_HSAR1 }, 'o' }, + { { STATE_HSAR0 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_STSWAPBM_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper89_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_STSWAPBMU_args[] = { + { { OPERAND_art }, 'm' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper89_imm }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SUB32_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper53_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SUB32_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SUBAC_I2R_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_SUBAC_I2R_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SUBAC_R2I_args[] = { + { { OPERAND_dsp340050b49a6c_oper51_reg }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_SUBAC_R2I_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SUBARX_args[] = { + { { OPERAND_ars }, 'm' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SUBCM_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper55_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SUBCM_stateArgs[] = { + { { STATE_SOV }, 'm' }, + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SUBMEAN_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper55_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SUBMEAN_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SUBWRP_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper55_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SUBWRP_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_TRANS_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_TRANS_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_XOR128_args[] = { + { { OPERAND_dsp340050b49a6c_oper45_reg }, 'o' }, + { { OPERAND_dsp340050b49a6c_oper55_reg }, 'i' }, + { { OPERAND_dsp340050b49a6c_oper46_reg }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_XOR128_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_expstate_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_expstate_stateArgs[] = { + { { STATE_EXPSTATE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_expstate_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_expstate_stateArgs[] = { + { { STATE_EXPSTATE }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_sov_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_sov_stateArgs[] = { + { { STATE_SOV }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_sov_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_sov_stateArgs[] = { + { { STATE_SOV }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_sat_mode_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_sat_mode_stateArgs[] = { + { { STATE_SAT_MODE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_sat_mode_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_sat_mode_stateArgs[] = { + { { STATE_SAT_MODE }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_sar0_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_sar0_stateArgs[] = { + { { STATE_SAR0 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_sar0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_sar0_stateArgs[] = { + { { STATE_SAR0 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_sar1_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_sar1_stateArgs[] = { + { { STATE_SAR1 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_sar1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_sar1_stateArgs[] = { + { { STATE_SAR1 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_sar2_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_sar2_stateArgs[] = { + { { STATE_SAR2 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_sar2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_sar2_stateArgs[] = { + { { STATE_SAR2 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_sar3_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_sar3_stateArgs[] = { + { { STATE_SAR3 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_sar3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_sar3_stateArgs[] = { + { { STATE_SAR3 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_hsar0_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_hsar0_stateArgs[] = { + { { STATE_HSAR0 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_hsar0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_hsar0_stateArgs[] = { + { { STATE_HSAR0 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_hsar1_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_hsar1_stateArgs[] = { + { { STATE_HSAR1 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_hsar1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_hsar1_stateArgs[] = { + { { STATE_HSAR1 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_hsar2_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_hsar2_stateArgs[] = { + { { STATE_HSAR2 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_hsar2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_hsar2_stateArgs[] = { + { { STATE_HSAR2 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_hsar3_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_hsar3_stateArgs[] = { + { { STATE_HSAR3 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_hsar3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_hsar3_stateArgs[] = { + { { STATE_HSAR3 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_max_reg_0_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_max_reg_0_stateArgs[] = { + { { STATE_MAX_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_max_reg_0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_max_reg_0_stateArgs[] = { + { { STATE_MAX_REG }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_max_reg_1_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_max_reg_1_stateArgs[] = { + { { STATE_MAX_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_max_reg_1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_max_reg_1_stateArgs[] = { + { { STATE_MAX_REG }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_max_reg_2_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_max_reg_2_stateArgs[] = { + { { STATE_MAX_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_max_reg_2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_max_reg_2_stateArgs[] = { + { { STATE_MAX_REG }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_max_reg_3_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_max_reg_3_stateArgs[] = { + { { STATE_MAX_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_max_reg_3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_max_reg_3_stateArgs[] = { + { { STATE_MAX_REG }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_arg_max_reg_0_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_arg_max_reg_0_stateArgs[] = { + { { STATE_ARG_MAX_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_arg_max_reg_0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_arg_max_reg_0_stateArgs[] = { + { { STATE_ARG_MAX_REG }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_arg_max_reg_1_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_arg_max_reg_1_stateArgs[] = { + { { STATE_ARG_MAX_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_arg_max_reg_1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_arg_max_reg_1_stateArgs[] = { + { { STATE_ARG_MAX_REG }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_arg_max_reg_2_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_arg_max_reg_2_stateArgs[] = { + { { STATE_ARG_MAX_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_arg_max_reg_2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_arg_max_reg_2_stateArgs[] = { + { { STATE_ARG_MAX_REG }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_arg_max_reg_3_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_arg_max_reg_3_stateArgs[] = { + { { STATE_ARG_MAX_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_arg_max_reg_3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_arg_max_reg_3_stateArgs[] = { + { { STATE_ARG_MAX_REG }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_nco_counter_0_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_nco_counter_0_stateArgs[] = { + { { STATE_NCO_COUNTER }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_nco_counter_0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_nco_counter_0_stateArgs[] = { + { { STATE_NCO_COUNTER }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_nco_counter_1_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_nco_counter_1_stateArgs[] = { + { { STATE_NCO_COUNTER }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_nco_counter_1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_nco_counter_1_stateArgs[] = { + { { STATE_NCO_COUNTER }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_nco_counter_2_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_nco_counter_2_stateArgs[] = { + { { STATE_NCO_COUNTER }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_nco_counter_2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_nco_counter_2_stateArgs[] = { + { { STATE_NCO_COUNTER }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_nco_counter_3_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_nco_counter_3_stateArgs[] = { + { { STATE_NCO_COUNTER }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_nco_counter_3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_nco_counter_3_stateArgs[] = { + { { STATE_NCO_COUNTER }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_interp_ext_n_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_interp_ext_n_stateArgs[] = { + { { STATE_INTERP_EXT_N }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_interp_ext_n_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_interp_ext_n_stateArgs[] = { + { { STATE_INTERP_EXT_N }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_interp_ext_l_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_interp_ext_l_stateArgs[] = { + { { STATE_INTERP_EXT_L }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_interp_ext_l_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_interp_ext_l_stateArgs[] = { + { { STATE_INTERP_EXT_L }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_0_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_0_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_0_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_1_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_1_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_1_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_2_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_2_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_2_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_3_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_3_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_3_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_4_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_4_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_4_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_4_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_5_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_5_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_5_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_5_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_6_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_6_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_6_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_6_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_7_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_7_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_7_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_7_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_8_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_8_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_8_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_8_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_9_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_9_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_9_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_9_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_10_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_10_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_10_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_10_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_11_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_11_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_11_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_11_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_12_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_12_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_12_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_12_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_13_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_13_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_13_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_13_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_14_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_14_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_14_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_14_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_15_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_15_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_15_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_15_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_16_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_16_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_16_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_16_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_17_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_17_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_17_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_17_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_18_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_18_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_18_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_18_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_19_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_19_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_19_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_19_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_20_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_20_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_20_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_20_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_21_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_21_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_21_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_21_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_22_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_22_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_22_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_22_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_23_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_buf_23_stateArgs[] = { + { { STATE_LLR_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_23_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_buf_23_stateArgs[] = { + { { STATE_LLR_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_smod_buf_0_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_smod_buf_0_stateArgs[] = { + { { STATE_SMOD_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_buf_0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_buf_0_stateArgs[] = { + { { STATE_SMOD_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_smod_buf_1_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_smod_buf_1_stateArgs[] = { + { { STATE_SMOD_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_buf_1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_buf_1_stateArgs[] = { + { { STATE_SMOD_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_smod_buf_2_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_smod_buf_2_stateArgs[] = { + { { STATE_SMOD_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_buf_2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_buf_2_stateArgs[] = { + { { STATE_SMOD_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_smod_buf_3_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_smod_buf_3_stateArgs[] = { + { { STATE_SMOD_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_buf_3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_buf_3_stateArgs[] = { + { { STATE_SMOD_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_smod_buf_4_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_smod_buf_4_stateArgs[] = { + { { STATE_SMOD_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_buf_4_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_buf_4_stateArgs[] = { + { { STATE_SMOD_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_smod_buf_5_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_smod_buf_5_stateArgs[] = { + { { STATE_SMOD_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_buf_5_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_buf_5_stateArgs[] = { + { { STATE_SMOD_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_smod_buf_6_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_smod_buf_6_stateArgs[] = { + { { STATE_SMOD_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_buf_6_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_buf_6_stateArgs[] = { + { { STATE_SMOD_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_smod_buf_7_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_smod_buf_7_stateArgs[] = { + { { STATE_SMOD_BUF }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_buf_7_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_buf_7_stateArgs[] = { + { { STATE_SMOD_BUF }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_weight_reg_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_weight_reg_stateArgs[] = { + { { STATE_WEIGHT_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_weight_reg_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_weight_reg_stateArgs[] = { + { { STATE_WEIGHT_REG }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_scale_reg_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_scale_reg_stateArgs[] = { + { { STATE_SCALE_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_scale_reg_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_scale_reg_stateArgs[] = { + { { STATE_SCALE_REG }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_llr_pos_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_llr_pos_stateArgs[] = { + { { STATE_LLR_POS }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_pos_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_llr_pos_stateArgs[] = { + { { STATE_LLR_POS }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_smod_pos_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_smod_pos_stateArgs[] = { + { { STATE_SMOD_POS }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_pos_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_pos_stateArgs[] = { + { { STATE_SMOD_POS }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_perm_reg_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_perm_reg_stateArgs[] = { + { { STATE_PERM_REG }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_perm_reg_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_perm_reg_stateArgs[] = { + { { STATE_PERM_REG }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_smod_offset_table_0_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_smod_offset_table_0_stateArgs[] = { + { { STATE_SMOD_OFFSET_TABLE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_offset_table_0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_offset_table_0_stateArgs[] = { + { { STATE_SMOD_OFFSET_TABLE }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_smod_offset_table_1_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_smod_offset_table_1_stateArgs[] = { + { { STATE_SMOD_OFFSET_TABLE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_offset_table_1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_offset_table_1_stateArgs[] = { + { { STATE_SMOD_OFFSET_TABLE }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_smod_offset_table_2_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_smod_offset_table_2_stateArgs[] = { + { { STATE_SMOD_OFFSET_TABLE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_offset_table_2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_offset_table_2_stateArgs[] = { + { { STATE_SMOD_OFFSET_TABLE }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_smod_offset_table_3_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_smod_offset_table_3_stateArgs[] = { + { { STATE_SMOD_OFFSET_TABLE }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_offset_table_3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_smod_offset_table_3_stateArgs[] = { + { { STATE_SMOD_OFFSET_TABLE }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_phasor_n_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_phasor_n_stateArgs[] = { + { { STATE_PHASOR_N }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_phasor_n_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_phasor_n_stateArgs[] = { + { { STATE_PHASOR_N }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_phasor_offset_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_phasor_offset_stateArgs[] = { + { { STATE_PHASOR_OFFSET }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_phasor_offset_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_phasor_offset_stateArgs[] = { + { { STATE_PHASOR_OFFSET }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_iclass_internal iclasses[] = { + { 0, 0 /* xt_iclass_excw */, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_rfe */, + 2, Iclass_xt_iclass_rfe_stateArgs, 0, 0 }, + { 0, 0 /* xt_iclass_rfde */, + 1, Iclass_xt_iclass_rfde_stateArgs, 0, 0 }, + { 0, 0 /* xt_iclass_syscall */, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_simcall */, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_call12_args, + 1, Iclass_xt_iclass_call12_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_call8_args, + 1, Iclass_xt_iclass_call8_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_call4_args, + 1, Iclass_xt_iclass_call4_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_callx12_args, + 1, Iclass_xt_iclass_callx12_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_callx8_args, + 1, Iclass_xt_iclass_callx8_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_callx4_args, + 1, Iclass_xt_iclass_callx4_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_entry_args, + 5, Iclass_xt_iclass_entry_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_movsp_args, + 2, Iclass_xt_iclass_movsp_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rotw_args, + 1, Iclass_xt_iclass_rotw_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_retw_args, + 4, Iclass_xt_iclass_retw_stateArgs, 0, 0 }, + { 0, 0 /* xt_iclass_rfwou */, + 5, Iclass_xt_iclass_rfwou_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_l32e_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s32e_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_windowbase_args, + 1, Iclass_xt_iclass_rsr_windowbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_windowbase_args, + 1, Iclass_xt_iclass_wsr_windowbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_windowbase_args, + 1, Iclass_xt_iclass_xsr_windowbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_windowstart_args, + 1, Iclass_xt_iclass_rsr_windowstart_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_windowstart_args, + 1, Iclass_xt_iclass_wsr_windowstart_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_windowstart_args, + 1, Iclass_xt_iclass_xsr_windowstart_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_add_n_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_addi_n_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_bz6_args, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_ill_n */, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_loadi4_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_mov_n_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_movi_n_args, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_nopn */, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_retn_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_storei4_args, + 0, 0, 0, 0 }, + { 1, Iclass_rur_threadptr_args, + 1, Iclass_rur_threadptr_stateArgs, 0, 0 }, + { 1, Iclass_wur_threadptr_args, + 1, Iclass_wur_threadptr_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_addi_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_addmi_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_addsub_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bit_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bsi8_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bsi8b_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bsi8u_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bst8_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_bsz12_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_call0_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_callx0_args, + 0, 0, 0, 0 }, + { 4, Iclass_xt_iclass_exti_args, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_ill */, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_jump_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_jumpx_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_l16ui_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_l16si_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_l32i_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_l32r_args, + 2, Iclass_xt_iclass_l32r_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_l8i_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_loop_args, + 3, Iclass_xt_iclass_loop_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_loopz_args, + 3, Iclass_xt_iclass_loopz_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_movi_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_movz_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_neg_args, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_nop */, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_return_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s16i_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s32i_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s8i_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_sar_args, + 1, Iclass_xt_iclass_sar_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_sari_args, + 1, Iclass_xt_iclass_sari_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_shifts_args, + 1, Iclass_xt_iclass_shifts_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_shiftst_args, + 1, Iclass_xt_iclass_shiftst_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_shiftt_args, + 1, Iclass_xt_iclass_shiftt_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_slli_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_srai_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_srli_args, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_memw */, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_extw */, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_isync */, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_sync */, + 1, Iclass_xt_iclass_sync_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_rsil_args, + 6, Iclass_xt_iclass_rsil_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_lend_args, + 1, Iclass_xt_iclass_rsr_lend_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_lend_args, + 1, Iclass_xt_iclass_wsr_lend_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_lend_args, + 1, Iclass_xt_iclass_xsr_lend_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_lcount_args, + 1, Iclass_xt_iclass_rsr_lcount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_lcount_args, + 2, Iclass_xt_iclass_wsr_lcount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_lcount_args, + 2, Iclass_xt_iclass_xsr_lcount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_lbeg_args, + 1, Iclass_xt_iclass_rsr_lbeg_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_lbeg_args, + 1, Iclass_xt_iclass_wsr_lbeg_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_lbeg_args, + 1, Iclass_xt_iclass_xsr_lbeg_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_sar_args, + 1, Iclass_xt_iclass_rsr_sar_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_sar_args, + 2, Iclass_xt_iclass_wsr_sar_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_sar_args, + 1, Iclass_xt_iclass_xsr_sar_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_litbase_args, + 2, Iclass_xt_iclass_rsr_litbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_litbase_args, + 2, Iclass_xt_iclass_wsr_litbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_litbase_args, + 2, Iclass_xt_iclass_xsr_litbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_176_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_176_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_208_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ps_args, + 6, Iclass_xt_iclass_rsr_ps_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ps_args, + 6, Iclass_xt_iclass_wsr_ps_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ps_args, + 6, Iclass_xt_iclass_xsr_ps_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc1_args, + 1, Iclass_xt_iclass_rsr_epc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc1_args, + 1, Iclass_xt_iclass_wsr_epc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc1_args, + 1, Iclass_xt_iclass_xsr_epc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave1_args, + 1, Iclass_xt_iclass_rsr_excsave1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave1_args, + 1, Iclass_xt_iclass_wsr_excsave1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave1_args, + 1, Iclass_xt_iclass_xsr_excsave1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc2_args, + 1, Iclass_xt_iclass_rsr_epc2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc2_args, + 1, Iclass_xt_iclass_wsr_epc2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc2_args, + 1, Iclass_xt_iclass_xsr_epc2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave2_args, + 1, Iclass_xt_iclass_rsr_excsave2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave2_args, + 1, Iclass_xt_iclass_wsr_excsave2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave2_args, + 1, Iclass_xt_iclass_xsr_excsave2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc3_args, + 1, Iclass_xt_iclass_rsr_epc3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc3_args, + 1, Iclass_xt_iclass_wsr_epc3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc3_args, + 1, Iclass_xt_iclass_xsr_epc3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave3_args, + 1, Iclass_xt_iclass_rsr_excsave3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave3_args, + 1, Iclass_xt_iclass_wsr_excsave3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave3_args, + 1, Iclass_xt_iclass_xsr_excsave3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc4_args, + 1, Iclass_xt_iclass_rsr_epc4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc4_args, + 1, Iclass_xt_iclass_wsr_epc4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc4_args, + 1, Iclass_xt_iclass_xsr_epc4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave4_args, + 1, Iclass_xt_iclass_rsr_excsave4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave4_args, + 1, Iclass_xt_iclass_wsr_excsave4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave4_args, + 1, Iclass_xt_iclass_xsr_excsave4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc5_args, + 1, Iclass_xt_iclass_rsr_epc5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc5_args, + 1, Iclass_xt_iclass_wsr_epc5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc5_args, + 1, Iclass_xt_iclass_xsr_epc5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave5_args, + 1, Iclass_xt_iclass_rsr_excsave5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave5_args, + 1, Iclass_xt_iclass_wsr_excsave5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave5_args, + 1, Iclass_xt_iclass_xsr_excsave5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc6_args, + 1, Iclass_xt_iclass_rsr_epc6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc6_args, + 1, Iclass_xt_iclass_wsr_epc6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc6_args, + 1, Iclass_xt_iclass_xsr_epc6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave6_args, + 1, Iclass_xt_iclass_rsr_excsave6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave6_args, + 1, Iclass_xt_iclass_wsr_excsave6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave6_args, + 1, Iclass_xt_iclass_xsr_excsave6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eps2_args, + 1, Iclass_xt_iclass_rsr_eps2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eps2_args, + 1, Iclass_xt_iclass_wsr_eps2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eps2_args, + 1, Iclass_xt_iclass_xsr_eps2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eps3_args, + 1, Iclass_xt_iclass_rsr_eps3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eps3_args, + 1, Iclass_xt_iclass_wsr_eps3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eps3_args, + 1, Iclass_xt_iclass_xsr_eps3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eps4_args, + 1, Iclass_xt_iclass_rsr_eps4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eps4_args, + 1, Iclass_xt_iclass_wsr_eps4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eps4_args, + 1, Iclass_xt_iclass_xsr_eps4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eps5_args, + 1, Iclass_xt_iclass_rsr_eps5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eps5_args, + 1, Iclass_xt_iclass_wsr_eps5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eps5_args, + 1, Iclass_xt_iclass_xsr_eps5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eps6_args, + 1, Iclass_xt_iclass_rsr_eps6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eps6_args, + 1, Iclass_xt_iclass_wsr_eps6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eps6_args, + 1, Iclass_xt_iclass_xsr_eps6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excvaddr_args, + 1, Iclass_xt_iclass_rsr_excvaddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excvaddr_args, + 1, Iclass_xt_iclass_wsr_excvaddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excvaddr_args, + 1, Iclass_xt_iclass_xsr_excvaddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_depc_args, + 1, Iclass_xt_iclass_rsr_depc_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_depc_args, + 1, Iclass_xt_iclass_wsr_depc_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_depc_args, + 1, Iclass_xt_iclass_xsr_depc_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_exccause_args, + 2, Iclass_xt_iclass_rsr_exccause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_exccause_args, + 1, Iclass_xt_iclass_wsr_exccause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_exccause_args, + 1, Iclass_xt_iclass_xsr_exccause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_prid_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_vecbase_args, + 1, Iclass_xt_iclass_rsr_vecbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_vecbase_args, + 1, Iclass_xt_iclass_wsr_vecbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_vecbase_args, + 1, Iclass_xt_iclass_xsr_vecbase_stateArgs, 0, 0 }, + { 3, Iclass_xt_mul16_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rfi_args, + 18, Iclass_xt_iclass_rfi_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wait_args, + 1, Iclass_xt_iclass_wait_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_interrupt_args, + 1, Iclass_xt_iclass_rsr_interrupt_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_intset_args, + 2, Iclass_xt_iclass_wsr_intset_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_intclear_args, + 2, Iclass_xt_iclass_wsr_intclear_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_intenable_args, + 1, Iclass_xt_iclass_rsr_intenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_intenable_args, + 1, Iclass_xt_iclass_wsr_intenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_intenable_args, + 1, Iclass_xt_iclass_xsr_intenable_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_break_args, + 2, Iclass_xt_iclass_break_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_break_n_args, + 2, Iclass_xt_iclass_break_n_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_dbreaka0_args, + 1, Iclass_xt_iclass_rsr_dbreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_dbreaka0_args, + 2, Iclass_xt_iclass_wsr_dbreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_dbreaka0_args, + 2, Iclass_xt_iclass_xsr_dbreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_dbreakc0_args, + 1, Iclass_xt_iclass_rsr_dbreakc0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_dbreakc0_args, + 2, Iclass_xt_iclass_wsr_dbreakc0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_dbreakc0_args, + 2, Iclass_xt_iclass_xsr_dbreakc0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_dbreaka1_args, + 1, Iclass_xt_iclass_rsr_dbreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_dbreaka1_args, + 2, Iclass_xt_iclass_wsr_dbreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_dbreaka1_args, + 2, Iclass_xt_iclass_xsr_dbreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_dbreakc1_args, + 1, Iclass_xt_iclass_rsr_dbreakc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_dbreakc1_args, + 2, Iclass_xt_iclass_wsr_dbreakc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_dbreakc1_args, + 2, Iclass_xt_iclass_xsr_dbreakc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ibreaka0_args, + 1, Iclass_xt_iclass_rsr_ibreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ibreaka0_args, + 1, Iclass_xt_iclass_wsr_ibreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ibreaka0_args, + 1, Iclass_xt_iclass_xsr_ibreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ibreaka1_args, + 1, Iclass_xt_iclass_rsr_ibreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ibreaka1_args, + 1, Iclass_xt_iclass_wsr_ibreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ibreaka1_args, + 1, Iclass_xt_iclass_xsr_ibreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ibreakenable_args, + 1, Iclass_xt_iclass_rsr_ibreakenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ibreakenable_args, + 1, Iclass_xt_iclass_wsr_ibreakenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ibreakenable_args, + 1, Iclass_xt_iclass_xsr_ibreakenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_debugcause_args, + 2, Iclass_xt_iclass_rsr_debugcause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_debugcause_args, + 2, Iclass_xt_iclass_wsr_debugcause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_debugcause_args, + 2, Iclass_xt_iclass_xsr_debugcause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_icount_args, + 1, Iclass_xt_iclass_rsr_icount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_icount_args, + 2, Iclass_xt_iclass_wsr_icount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_icount_args, + 2, Iclass_xt_iclass_xsr_icount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_icountlevel_args, + 1, Iclass_xt_iclass_rsr_icountlevel_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_icountlevel_args, + 1, Iclass_xt_iclass_wsr_icountlevel_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_icountlevel_args, + 1, Iclass_xt_iclass_xsr_icountlevel_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ddr_args, + 1, Iclass_xt_iclass_rsr_ddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ddr_args, + 2, Iclass_xt_iclass_wsr_ddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ddr_args, + 2, Iclass_xt_iclass_xsr_ddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rfdo_args, + 9, Iclass_xt_iclass_rfdo_stateArgs, 0, 0 }, + { 0, 0 /* xt_iclass_rfdd */, + 1, Iclass_xt_iclass_rfdd_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_mmid_args, + 1, Iclass_xt_iclass_wsr_mmid_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_bbool1_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_bbool4_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_bbool8_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_bbranch_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bmove_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_RSR_BR_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_WSR_BR_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_XSR_BR_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ccount_args, + 1, Iclass_xt_iclass_rsr_ccount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ccount_args, + 2, Iclass_xt_iclass_wsr_ccount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ccount_args, + 2, Iclass_xt_iclass_xsr_ccount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ccompare0_args, + 1, Iclass_xt_iclass_rsr_ccompare0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ccompare0_args, + 2, Iclass_xt_iclass_wsr_ccompare0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ccompare0_args, + 2, Iclass_xt_iclass_xsr_ccompare0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ccompare1_args, + 1, Iclass_xt_iclass_rsr_ccompare1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ccompare1_args, + 2, Iclass_xt_iclass_wsr_ccompare1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ccompare1_args, + 2, Iclass_xt_iclass_xsr_ccompare1_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_icache_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_icache_lock_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_icache_inv_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_licx_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_sicx_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_dcache_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_dcache_ind_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_dcache_inv_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_dpf_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_dcache_lock_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_sdct_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_ldct_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_idtlb_args, + 1, Iclass_xt_iclass_idtlb_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_rdtlb_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_wdtlb_args, + 1, Iclass_xt_iclass_wdtlb_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_iitlb_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_ritlb_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_witlb_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_cpenable_args, + 1, Iclass_xt_iclass_rsr_cpenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_cpenable_args, + 1, Iclass_xt_iclass_wsr_cpenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_cpenable_args, + 1, Iclass_xt_iclass_xsr_cpenable_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_clamp_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_minmax_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_nsa_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_sx_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_l32ai_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s32ri_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s32c1i_args, + 3, Iclass_xt_iclass_s32c1i_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_scompare1_args, + 1, Iclass_xt_iclass_rsr_scompare1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_scompare1_args, + 1, Iclass_xt_iclass_wsr_scompare1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_scompare1_args, + 1, Iclass_xt_iclass_xsr_scompare1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_atomctl_args, + 1, Iclass_xt_iclass_rsr_atomctl_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_atomctl_args, + 2, Iclass_xt_iclass_wsr_atomctl_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_atomctl_args, + 2, Iclass_xt_iclass_xsr_atomctl_stateArgs, 0, 0 }, + { 0, 0 /* xt_iclass_rer */, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_wer */, + 0, 0, 0, 0 }, + { 1, Iclass_rur_fcr_args, + 9, Iclass_rur_fcr_stateArgs, 0, 0 }, + { 1, Iclass_wur_fcr_args, + 9, Iclass_wur_fcr_stateArgs, 0, 0 }, + { 1, Iclass_rur_fsr_args, + 8, Iclass_rur_fsr_stateArgs, 0, 0 }, + { 1, Iclass_wur_fsr_args, + 8, Iclass_wur_fsr_stateArgs, 0, 0 }, + { 3, Iclass_fp_args, + 2, Iclass_fp_stateArgs, 0, 0 }, + { 3, Iclass_fp_mac_args, + 2, Iclass_fp_mac_stateArgs, 0, 0 }, + { 3, Iclass_fp_cmov_args, + 1, Iclass_fp_cmov_stateArgs, 0, 0 }, + { 3, Iclass_fp_mov_args, + 1, Iclass_fp_mov_stateArgs, 0, 0 }, + { 2, Iclass_fp_mov2_args, + 1, Iclass_fp_mov2_stateArgs, 0, 0 }, + { 3, Iclass_fp_cmp_args, + 1, Iclass_fp_cmp_stateArgs, 0, 0 }, + { 3, Iclass_fp_float_args, + 2, Iclass_fp_float_stateArgs, 0, 0 }, + { 3, Iclass_fp_int_args, + 1, Iclass_fp_int_stateArgs, 0, 0 }, + { 2, Iclass_fp_rfr_args, + 1, Iclass_fp_rfr_stateArgs, 0, 0 }, + { 2, Iclass_fp_wfr_args, + 1, Iclass_fp_wfr_stateArgs, 0, 0 }, + { 3, Iclass_fp_lsi_args, + 1, Iclass_fp_lsi_stateArgs, 0, 0 }, + { 3, Iclass_fp_lsiu_args, + 1, Iclass_fp_lsiu_stateArgs, 0, 0 }, + { 3, Iclass_fp_lsx_args, + 1, Iclass_fp_lsx_stateArgs, 0, 0 }, + { 3, Iclass_fp_lsxu_args, + 1, Iclass_fp_lsxu_stateArgs, 0, 0 }, + { 3, Iclass_fp_ssi_args, + 1, Iclass_fp_ssi_stateArgs, 0, 0 }, + { 3, Iclass_fp_ssiu_args, + 1, Iclass_fp_ssiu_stateArgs, 0, 0 }, + { 3, Iclass_fp_ssx_args, + 1, Iclass_fp_ssx_stateArgs, 0, 0 }, + { 3, Iclass_fp_ssxu_args, + 1, Iclass_fp_ssxu_stateArgs, 0, 0 }, + { 1, Iclass_iclass_GET_ARGMAX_args, + 2, Iclass_iclass_GET_ARGMAX_stateArgs, 0, 0 }, + { 1, Iclass_iclass_GET_HSAR_args, + 5, Iclass_iclass_GET_HSAR_stateArgs, 0, 0 }, + { 1, Iclass_iclass_GET_HSAR2SAR_args, + 9, Iclass_iclass_GET_HSAR2SAR_stateArgs, 0, 0 }, + { 1, Iclass_iclass_GET_INTERP_EXT_N_args, + 2, Iclass_iclass_GET_INTERP_EXT_N_stateArgs, 0, 0 }, + { 1, Iclass_iclass_GET_INTERP_EXT_L_args, + 2, Iclass_iclass_GET_INTERP_EXT_L_stateArgs, 0, 0 }, + { 2, Iclass_iclass_GET_LLR_BUF_args, + 2, Iclass_iclass_GET_LLR_BUF_stateArgs, 0, 0 }, + { 1, Iclass_iclass_GET_LLR_POS_args, + 2, Iclass_iclass_GET_LLR_POS_stateArgs, 0, 0 }, + { 1, Iclass_iclass_GET_MAX_args, + 2, Iclass_iclass_GET_MAX_stateArgs, 0, 0 }, + { 1, Iclass_iclass_GET_NCO_args, + 2, Iclass_iclass_GET_NCO_stateArgs, 0, 0 }, + { 1, Iclass_iclass_GET_PERM_REG_args, + 2, Iclass_iclass_GET_PERM_REG_stateArgs, 0, 0 }, + { 1, Iclass_iclass_GET_PHASOR_N_args, + 2, Iclass_iclass_GET_PHASOR_N_stateArgs, 0, 0 }, + { 1, Iclass_iclass_GET_PHASOR_OFFSET_args, + 2, Iclass_iclass_GET_PHASOR_OFFSET_stateArgs, 0, 0 }, + { 1, Iclass_iclass_GET_SAR_args, + 5, Iclass_iclass_GET_SAR_stateArgs, 0, 0 }, + { 1, Iclass_iclass_GET_SCALE_REG_args, + 2, Iclass_iclass_GET_SCALE_REG_stateArgs, 0, 0 }, + { 2, Iclass_iclass_GET_SMOD_BUF_args, + 2, Iclass_iclass_GET_SMOD_BUF_stateArgs, 0, 0 }, + { 1, Iclass_iclass_GET_SMOD_OFFSET_TABLE_args, + 2, Iclass_iclass_GET_SMOD_OFFSET_TABLE_stateArgs, 0, 0 }, + { 1, Iclass_iclass_GET_SMOD_POS_args, + 2, Iclass_iclass_GET_SMOD_POS_stateArgs, 0, 0 }, + { 1, Iclass_iclass_GET_SOV_args, + 2, Iclass_iclass_GET_SOV_stateArgs, 0, 0 }, + { 1, Iclass_iclass_GET_WGHT_args, + 2, Iclass_iclass_GET_WGHT_stateArgs, 0, 0 }, + { 1, Iclass_iclass_SET_ARGMAX_args, + 2, Iclass_iclass_SET_ARGMAX_stateArgs, 0, 0 }, + { 2, Iclass_iclass_SET_EXT_REGS_args, + 3, Iclass_iclass_SET_EXT_REGS_stateArgs, 0, 0 }, + { 1, Iclass_iclass_SET_HSAR_args, + 5, Iclass_iclass_SET_HSAR_stateArgs, 0, 0 }, + { 2, Iclass_iclass_SET_LLR_BUF_args, + 2, Iclass_iclass_SET_LLR_BUF_stateArgs, 0, 0 }, + { 1, Iclass_iclass_SET_LLR_POS_args, + 2, Iclass_iclass_SET_LLR_POS_stateArgs, 0, 0 }, + { 1, Iclass_iclass_SET_MAX_args, + 2, Iclass_iclass_SET_MAX_stateArgs, 0, 0 }, + { 1, Iclass_iclass_SET_NCO_args, + 2, Iclass_iclass_SET_NCO_stateArgs, 0, 0 }, + { 1, Iclass_iclass_SET_PERM_REG_args, + 2, Iclass_iclass_SET_PERM_REG_stateArgs, 0, 0 }, + { 1, Iclass_iclass_SET_PHASOR_N_args, + 2, Iclass_iclass_SET_PHASOR_N_stateArgs, 0, 0 }, + { 1, Iclass_iclass_SET_PHASOR_OFFSET_args, + 2, Iclass_iclass_SET_PHASOR_OFFSET_stateArgs, 0, 0 }, + { 1, Iclass_iclass_SET_SAR_args, + 5, Iclass_iclass_SET_SAR_stateArgs, 0, 0 }, + { 1, Iclass_iclass_SET_SCALE_REG_args, + 2, Iclass_iclass_SET_SCALE_REG_stateArgs, 0, 0 }, + { 2, Iclass_iclass_SET_SMOD_BUF_args, + 2, Iclass_iclass_SET_SMOD_BUF_stateArgs, 0, 0 }, + { 1, Iclass_iclass_SET_SMOD_OFFSET_TABLE_args, + 2, Iclass_iclass_SET_SMOD_OFFSET_TABLE_stateArgs, 0, 0 }, + { 1, Iclass_iclass_SET_SMOD_POS_args, + 2, Iclass_iclass_SET_SMOD_POS_stateArgs, 0, 0 }, + { 1, Iclass_iclass_SET_SOV_args, + 2, Iclass_iclass_SET_SOV_stateArgs, 0, 0 }, + { 1, Iclass_iclass_SET_WGHT_args, + 2, Iclass_iclass_SET_WGHT_stateArgs, 0, 0 }, + { 4, Iclass_iclass_LAC2X32_args, + 1, Iclass_iclass_LAC2X32_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LAC2X64_0_args, + 1, Iclass_iclass_LAC2X64_0_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LAC2X64_1_args, + 1, Iclass_iclass_LAC2X64_1_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LAC2X64_2_args, + 1, Iclass_iclass_LAC2X64_2_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LAC2X64_3_args, + 1, Iclass_iclass_LAC2X64_3_stateArgs, 0, 0 }, + { 4, Iclass_iclass_LAC32_R_args, + 1, Iclass_iclass_LAC32_R_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LAC_IH_args, + 1, Iclass_iclass_LAC_IH_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LAC_IL_args, + 1, Iclass_iclass_LAC_IL_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LAC_RH_args, + 1, Iclass_iclass_LAC_RH_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LAC_RL_args, + 1, Iclass_iclass_LAC_RL_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LCM_args, + 1, Iclass_iclass_LCM_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LCM_PINC_args, + 1, Iclass_iclass_LCM_PINC_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LCM_PINC_X_args, + 1, Iclass_iclass_LCM_PINC_X_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LCM_U_args, + 1, Iclass_iclass_LCM_U_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LCM_X_args, + 1, Iclass_iclass_LCM_X_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LCM_XU_args, + 1, Iclass_iclass_LCM_XU_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LP_args, + 1, Iclass_iclass_LP_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LP_X_args, + 1, Iclass_iclass_LP_X_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LQ_args, + 1, Iclass_iclass_LQ_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LQ_X_args, + 1, Iclass_iclass_LQ_X_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LUT0_args, + 1, Iclass_iclass_LUT0_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LUT1_args, + 1, Iclass_iclass_LUT1_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LUT2_args, + 1, Iclass_iclass_LUT2_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LUT3_args, + 1, Iclass_iclass_LUT3_stateArgs, 0, 0 }, + { 4, Iclass_iclass_SAC2X32_args, + 1, Iclass_iclass_SAC2X32_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SAC2X64_0_args, + 1, Iclass_iclass_SAC2X64_0_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SAC2X64_1_args, + 1, Iclass_iclass_SAC2X64_1_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SAC2X64_2_args, + 1, Iclass_iclass_SAC2X64_2_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SAC2X64_3_args, + 1, Iclass_iclass_SAC2X64_3_stateArgs, 0, 0 }, + { 4, Iclass_iclass_SAC32_R_args, + 1, Iclass_iclass_SAC32_R_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SAC_IH_args, + 1, Iclass_iclass_SAC_IH_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SAC_IL_args, + 1, Iclass_iclass_SAC_IL_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SAC_RH_args, + 1, Iclass_iclass_SAC_RH_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SAC_RL_args, + 1, Iclass_iclass_SAC_RL_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SCM_args, + 1, Iclass_iclass_SCM_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SCM_PINC_args, + 1, Iclass_iclass_SCM_PINC_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SCM_PINC_X_args, + 1, Iclass_iclass_SCM_PINC_X_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SCM_U_args, + 1, Iclass_iclass_SCM_U_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SCM_X_args, + 1, Iclass_iclass_SCM_X_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SCM_XU_args, + 1, Iclass_iclass_SCM_XU_stateArgs, 0, 0 }, + { 3, Iclass_iclass_STORE_P_args, + 1, Iclass_iclass_STORE_P_stateArgs, 0, 0 }, + { 3, Iclass_iclass_STORE_Q_args, + 1, Iclass_iclass_STORE_Q_stateArgs, 0, 0 }, + { 2, Iclass_iclass_AR2CM_DUP_args, + 1, Iclass_iclass_AR2CM_DUP_stateArgs, 0, 0 }, + { 3, Iclass_iclass_AR2CM_LN_args, + 1, Iclass_iclass_AR2CM_LN_stateArgs, 0, 0 }, + { 3, Iclass_iclass_AR2CM_LN_I_args, + 1, Iclass_iclass_AR2CM_LN_I_stateArgs, 0, 0 }, + { 3, Iclass_iclass_AR2CM_LN_R_args, + 1, Iclass_iclass_AR2CM_LN_R_stateArgs, 0, 0 }, + { 4, Iclass_iclass_AR2PQ_LN_args, + 1, Iclass_iclass_AR2PQ_LN_stateArgs, 0, 0 }, + { 1, Iclass_iclass_AR2SAR_DUP_args, + 5, Iclass_iclass_AR2SAR_DUP_stateArgs, 0, 0 }, + { 1, Iclass_iclass_CLRAC_args, + 1, Iclass_iclass_CLRAC_stateArgs, 0, 0 }, + { 1, Iclass_iclass_CLRCM_args, + 1, Iclass_iclass_CLRCM_stateArgs, 0, 0 }, + { 3, Iclass_iclass_CM2AR_LN_args, + 1, Iclass_iclass_CM2AR_LN_stateArgs, 0, 0 }, + { 3, Iclass_iclass_CM2AR_LN_I_args, + 1, Iclass_iclass_CM2AR_LN_I_stateArgs, 0, 0 }, + { 3, Iclass_iclass_CM2AR_LN_R_args, + 1, Iclass_iclass_CM2AR_LN_R_stateArgs, 0, 0 }, + { 3, Iclass_iclass_COMB_AR_args, + 0, 0, 0, 0 }, + { 2, Iclass_iclass_CONJ_args, + 1, Iclass_iclass_CONJ_stateArgs, 0, 0 }, + { 2, Iclass_iclass_MOV2AC32_I_args, + 1, Iclass_iclass_MOV2AC32_I_stateArgs, 0, 0 }, + { 2, Iclass_iclass_MOV2AC32_R_args, + 1, Iclass_iclass_MOV2AC32_R_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOV2CM2PQ_args, + 1, Iclass_iclass_MOV2CM2PQ_stateArgs, 0, 0 }, + { 2, Iclass_iclass_MOVAC_args, + 1, Iclass_iclass_MOVAC_stateArgs, 0, 0 }, + { 2, Iclass_iclass_MOVAC_I_args, + 1, Iclass_iclass_MOVAC_I_stateArgs, 0, 0 }, + { 2, Iclass_iclass_MOVAC_I2R_args, + 1, Iclass_iclass_MOVAC_I2R_stateArgs, 0, 0 }, + { 2, Iclass_iclass_MOVAC_R_args, + 1, Iclass_iclass_MOVAC_R_stateArgs, 0, 0 }, + { 2, Iclass_iclass_MOVAC_R2I_args, + 1, Iclass_iclass_MOVAC_R2I_stateArgs, 0, 0 }, + { 2, Iclass_iclass_MOVAR2_args, + 0, 0, 0, 0 }, + { 2, Iclass_iclass_MOVCM_args, + 1, Iclass_iclass_MOVCM_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOVCM2PQ_args, + 1, Iclass_iclass_MOVCM2PQ_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOVCND_0_args, + 1, Iclass_iclass_MOVCND_0_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOVCND_1_args, + 1, Iclass_iclass_MOVCND_1_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOVCND_2_args, + 1, Iclass_iclass_MOVCND_2_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOVCND_3_args, + 1, Iclass_iclass_MOVCND_3_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOVCND_4_args, + 1, Iclass_iclass_MOVCND_4_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOVCND_5_args, + 1, Iclass_iclass_MOVCND_5_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOVCND_6_args, + 1, Iclass_iclass_MOVCND_6_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOVCND_7_args, + 1, Iclass_iclass_MOVCND_7_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOVCND8_0_args, + 1, Iclass_iclass_MOVCND8_0_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOVCND8_1_args, + 1, Iclass_iclass_MOVCND8_1_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOVCND8_2_args, + 1, Iclass_iclass_MOVCND8_2_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOVCND8_3_args, + 1, Iclass_iclass_MOVCND8_3_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOVCND8_4_args, + 1, Iclass_iclass_MOVCND8_4_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOVCND8_5_args, + 1, Iclass_iclass_MOVCND8_5_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOVCND8_6_args, + 1, Iclass_iclass_MOVCND8_6_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOVCND8_7_args, + 1, Iclass_iclass_MOVCND8_7_stateArgs, 0, 0 }, + { 2, Iclass_iclass_MOV_I_args, + 1, Iclass_iclass_MOV_I_stateArgs, 0, 0 }, + { 2, Iclass_iclass_MOVPQ2PQ_args, + 1, Iclass_iclass_MOVPQ2PQ_stateArgs, 0, 0 }, + { 2, Iclass_iclass_MOV_R_args, + 1, Iclass_iclass_MOV_R_stateArgs, 0, 0 }, + { 2, Iclass_iclass_NEGCM_args, + 1, Iclass_iclass_NEGCM_stateArgs, 0, 0 }, + { 1, Iclass_iclass_POP16LLR_1_args, + 3, Iclass_iclass_POP16LLR_1_stateArgs, 0, 0 }, + { 3, Iclass_iclass_PQ2CM_args, + 1, Iclass_iclass_PQ2CM_stateArgs, 0, 0 }, + { 2, Iclass_iclass_SWAPAC_R_args, + 1, Iclass_iclass_SWAPAC_R_stateArgs, 0, 0 }, + { 2, Iclass_iclass_SWAPAC_RI_args, + 1, Iclass_iclass_SWAPAC_RI_stateArgs, 0, 0 }, + { 2, Iclass_iclass_SWAPB_args, + 0, 0, 0, 0 }, + { 3, Iclass_iclass_ADD2AC_args, + 6, Iclass_iclass_ADD2AC_stateArgs, 0, 0 }, + { 3, Iclass_iclass_ADDAC_args, + 3, Iclass_iclass_ADDAC_stateArgs, 0, 0 }, + { 4, Iclass_iclass_CDOT_args, + 2, Iclass_iclass_CDOT_stateArgs, 0, 0 }, + { 4, Iclass_iclass_CDOTAC_args, + 3, Iclass_iclass_CDOTAC_stateArgs, 0, 0 }, + { 4, Iclass_iclass_CDOTACS_args, + 3, Iclass_iclass_CDOTACS_stateArgs, 0, 0 }, + { 3, Iclass_iclass_CMAC_args, + 3, Iclass_iclass_CMAC_stateArgs, 0, 0 }, + { 3, Iclass_iclass_CMACS_args, + 3, Iclass_iclass_CMACS_stateArgs, 0, 0 }, + { 3, Iclass_iclass_CMPY_args, + 2, Iclass_iclass_CMPY_stateArgs, 0, 0 }, + { 3, Iclass_iclass_CMPY2CM_args, + 3, Iclass_iclass_CMPY2CM_stateArgs, 0, 0 }, + { 3, Iclass_iclass_CMPY2PQ_args, + 3, Iclass_iclass_CMPY2PQ_stateArgs, 0, 0 }, + { 3, Iclass_iclass_CMPYS_args, + 2, Iclass_iclass_CMPYS_stateArgs, 0, 0 }, + { 3, Iclass_iclass_CMPYXP2PQ_args, + 3, Iclass_iclass_CMPYXP2PQ_stateArgs, 0, 0 }, + { 5, Iclass_iclass_COMB32_args, + 3, Iclass_iclass_COMB32_stateArgs, 0, 0 }, + { 4, Iclass_iclass_DOT_args, + 2, Iclass_iclass_DOT_stateArgs, 0, 0 }, + { 4, Iclass_iclass_DOTAC_args, + 3, Iclass_iclass_DOTAC_stateArgs, 0, 0 }, + { 4, Iclass_iclass_DOTACS_args, + 3, Iclass_iclass_DOTACS_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LIN_INT_args, + 6, Iclass_iclass_LIN_INT_stateArgs, 0, 0 }, + { 6, Iclass_iclass_LLRPRE1_args, + 2, Iclass_iclass_LLRPRE1_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LLRPRE2_args, + 3, Iclass_iclass_LLRPRE2_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MAC_args, + 3, Iclass_iclass_MAC_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MAC8_args, + 3, Iclass_iclass_MAC8_stateArgs, 0, 0 }, + { 4, Iclass_iclass_MACD8_args, + 3, Iclass_iclass_MACD8_stateArgs, 0, 0 }, + { 4, Iclass_iclass_MACPQXP_0_args, + 3, Iclass_iclass_MACPQXP_0_stateArgs, 0, 0 }, + { 4, Iclass_iclass_MACPQXP_1_args, + 3, Iclass_iclass_MACPQXP_1_stateArgs, 0, 0 }, + { 4, Iclass_iclass_MACPQXP_2_args, + 3, Iclass_iclass_MACPQXP_2_stateArgs, 0, 0 }, + { 4, Iclass_iclass_MACPQXP_3_args, + 3, Iclass_iclass_MACPQXP_3_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MACS_args, + 3, Iclass_iclass_MACS_stateArgs, 0, 0 }, + { 4, Iclass_iclass_MACXP2_0_args, + 3, Iclass_iclass_MACXP2_0_stateArgs, 0, 0 }, + { 4, Iclass_iclass_MACXP2_1_args, + 3, Iclass_iclass_MACXP2_1_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MACXP_0_args, + 3, Iclass_iclass_MACXP_0_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MACXP_1_args, + 3, Iclass_iclass_MACXP_1_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MACXP_2_args, + 3, Iclass_iclass_MACXP_2_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MACXP_3_args, + 3, Iclass_iclass_MACXP_3_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MOV2AC_args, + 6, Iclass_iclass_MOV2AC_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MPY_args, + 2, Iclass_iclass_MPY_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MPY2CM_args, + 3, Iclass_iclass_MPY2CM_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MPY2PQ_args, + 3, Iclass_iclass_MPY2PQ_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MPY8_args, + 2, Iclass_iclass_MPY8_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MPYADD8_2CM_args, + 3, Iclass_iclass_MPYADD8_2CM_stateArgs, 0, 0 }, + { 4, Iclass_iclass_MPYD8_args, + 2, Iclass_iclass_MPYD8_stateArgs, 0, 0 }, + { 4, Iclass_iclass_MPYPQXP_0_args, + 2, Iclass_iclass_MPYPQXP_0_stateArgs, 0, 0 }, + { 4, Iclass_iclass_MPYPQXP_1_args, + 2, Iclass_iclass_MPYPQXP_1_stateArgs, 0, 0 }, + { 4, Iclass_iclass_MPYPQXP_2_args, + 2, Iclass_iclass_MPYPQXP_2_stateArgs, 0, 0 }, + { 4, Iclass_iclass_MPYPQXP_3_args, + 2, Iclass_iclass_MPYPQXP_3_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MPYS_args, + 2, Iclass_iclass_MPYS_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MPYXP2PQ_args, + 3, Iclass_iclass_MPYXP2PQ_stateArgs, 0, 0 }, + { 4, Iclass_iclass_MPYXP2_0_args, + 2, Iclass_iclass_MPYXP2_0_stateArgs, 0, 0 }, + { 4, Iclass_iclass_MPYXP2_1_args, + 2, Iclass_iclass_MPYXP2_1_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MPYXP_0_args, + 2, Iclass_iclass_MPYXP_0_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MPYXP_1_args, + 2, Iclass_iclass_MPYXP_1_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MPYXP_2_args, + 2, Iclass_iclass_MPYXP_2_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MPYXP_3_args, + 2, Iclass_iclass_MPYXP_3_stateArgs, 0, 0 }, + { 3, Iclass_iclass_NORMACD_args, + 3, Iclass_iclass_NORMACD_stateArgs, 0, 0 }, + { 2, Iclass_iclass_NORMACPQ_I_args, + 3, Iclass_iclass_NORMACPQ_I_stateArgs, 0, 0 }, + { 2, Iclass_iclass_NORMACPQ_R_args, + 3, Iclass_iclass_NORMACPQ_R_stateArgs, 0, 0 }, + { 3, Iclass_iclass_NORMD_args, + 2, Iclass_iclass_NORMD_stateArgs, 0, 0 }, + { 2, Iclass_iclass_NORMPYPQ_I_args, + 2, Iclass_iclass_NORMPYPQ_I_stateArgs, 0, 0 }, + { 2, Iclass_iclass_NORMPYPQ_R_args, + 2, Iclass_iclass_NORMPYPQ_R_stateArgs, 0, 0 }, + { 3, Iclass_iclass_RCMAC_args, + 3, Iclass_iclass_RCMAC_stateArgs, 0, 0 }, + { 3, Iclass_iclass_RCMPY_args, + 2, Iclass_iclass_RCMPY_stateArgs, 0, 0 }, + { 3, Iclass_iclass_RCMPY2CM_args, + 1, Iclass_iclass_RCMPY2CM_stateArgs, 0, 0 }, + { 6, Iclass_iclass_RFIR_args, + 3, Iclass_iclass_RFIR_stateArgs, 0, 0 }, + { 6, Iclass_iclass_RFIRA_args, + 3, Iclass_iclass_RFIRA_stateArgs, 0, 0 }, + { 5, Iclass_iclass_RFIRD_args, + 3, Iclass_iclass_RFIRD_stateArgs, 0, 0 }, + { 5, Iclass_iclass_RFIRDA_args, + 3, Iclass_iclass_RFIRDA_stateArgs, 0, 0 }, + { 3, Iclass_iclass_RMAC_args, + 3, Iclass_iclass_RMAC_stateArgs, 0, 0 }, + { 3, Iclass_iclass_RMPY_args, + 2, Iclass_iclass_RMPY_stateArgs, 0, 0 }, + { 3, Iclass_iclass_RMPY2CM_args, + 1, Iclass_iclass_RMPY2CM_stateArgs, 0, 0 }, + { 4, Iclass_iclass_SMOD_ALIGN_args, + 3, Iclass_iclass_SMOD_ALIGN_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SMOD_SCR_args, + 2, Iclass_iclass_SMOD_SCR_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SUB2AC_args, + 6, Iclass_iclass_SUB2AC_stateArgs, 0, 0 }, + { 3, Iclass_iclass_WGHT32_args, + 3, Iclass_iclass_WGHT32_stateArgs, 0, 0 }, + { 1, Iclass_iclass_CLRTIEP_args, + 1, Iclass_iclass_CLRTIEP_stateArgs, 0, 0 }, + { 3, Iclass_iclass_EXT_2FIFO_0_args, + 1, Iclass_iclass_EXT_2FIFO_0_stateArgs, 1, Iclass_iclass_EXT_2FIFO_0_intfArgs }, + { 3, Iclass_iclass_EXT_2FIFO_1_args, + 1, Iclass_iclass_EXT_2FIFO_1_stateArgs, 1, Iclass_iclass_EXT_2FIFO_1_intfArgs }, + { 3, Iclass_iclass_EXT_2FIFO_2_args, + 1, Iclass_iclass_EXT_2FIFO_2_stateArgs, 1, Iclass_iclass_EXT_2FIFO_2_intfArgs }, + { 3, Iclass_iclass_EXT_2FIFO_3_args, + 1, Iclass_iclass_EXT_2FIFO_3_stateArgs, 1, Iclass_iclass_EXT_2FIFO_3_intfArgs }, + { 3, Iclass_iclass_EXT_R2FIFO_0_args, + 1, Iclass_iclass_EXT_R2FIFO_0_stateArgs, 1, Iclass_iclass_EXT_R2FIFO_0_intfArgs }, + { 3, Iclass_iclass_EXT_R2FIFO_1_args, + 1, Iclass_iclass_EXT_R2FIFO_1_stateArgs, 1, Iclass_iclass_EXT_R2FIFO_1_intfArgs }, + { 3, Iclass_iclass_EXT_R2FIFO_2_args, + 1, Iclass_iclass_EXT_R2FIFO_2_stateArgs, 1, Iclass_iclass_EXT_R2FIFO_2_intfArgs }, + { 3, Iclass_iclass_EXT_R2FIFO_3_args, + 1, Iclass_iclass_EXT_R2FIFO_3_stateArgs, 1, Iclass_iclass_EXT_R2FIFO_3_intfArgs }, + { 3, Iclass_iclass_LUT_args, + 1, Iclass_iclass_LUT_stateArgs, 2, Iclass_iclass_LUT_intfArgs }, + { 3, Iclass_iclass_LUT_AR_args, + 1, Iclass_iclass_LUT_AR_stateArgs, 2, Iclass_iclass_LUT_AR_intfArgs }, + { 3, Iclass_iclass_LUT_IEXT_args, + 3, Iclass_iclass_LUT_IEXT_stateArgs, 2, Iclass_iclass_LUT_IEXT_intfArgs }, + { 2, Iclass_iclass_LUT_PHASOR_args, + 3, Iclass_iclass_LUT_PHASOR_stateArgs, 2, Iclass_iclass_LUT_PHASOR_intfArgs }, + { 3, Iclass_iclass_LUT_REXT_args, + 3, Iclass_iclass_LUT_REXT_stateArgs, 2, Iclass_iclass_LUT_REXT_intfArgs }, + { 3, Iclass_iclass_LUT_WRITE_args, + 1, Iclass_iclass_LUT_WRITE_stateArgs, 2, Iclass_iclass_LUT_WRITE_intfArgs }, + { 0, 0 /* iclass_MOVEQ128_0 */, + 0, 0, 2, Iclass_iclass_MOVEQ128_0_intfArgs }, + { 0, 0 /* iclass_MOVEQ128_1 */, + 0, 0, 2, Iclass_iclass_MOVEQ128_1_intfArgs }, + { 0, 0 /* iclass_MOVEQ128_2 */, + 0, 0, 2, Iclass_iclass_MOVEQ128_2_intfArgs }, + { 0, 0 /* iclass_MOVEQ128_3 */, + 0, 0, 2, Iclass_iclass_MOVEQ128_3_intfArgs }, + { 0, 0 /* iclass_MOVEQ128_4 */, + 0, 0, 2, Iclass_iclass_MOVEQ128_4_intfArgs }, + { 0, 0 /* iclass_MOVEQ128_5 */, + 0, 0, 2, Iclass_iclass_MOVEQ128_5_intfArgs }, + { 0, 0 /* iclass_MOVEQ32_0 */, + 0, 0, 2, Iclass_iclass_MOVEQ32_0_intfArgs }, + { 0, 0 /* iclass_MOVEQ32_1 */, + 0, 0, 2, Iclass_iclass_MOVEQ32_1_intfArgs }, + { 0, 0 /* iclass_MOVEQ32_2 */, + 0, 0, 2, Iclass_iclass_MOVEQ32_2_intfArgs }, + { 0, 0 /* iclass_MOVEQ32_3 */, + 0, 0, 2, Iclass_iclass_MOVEQ32_3_intfArgs }, + { 2, Iclass_iclass_NCO_UPDATE_args, + 4, Iclass_iclass_NCO_UPDATE_stateArgs, 2, Iclass_iclass_NCO_UPDATE_intfArgs }, + { 1, Iclass_iclass_POP128_0_args, + 1, Iclass_iclass_POP128_0_stateArgs, 1, Iclass_iclass_POP128_0_intfArgs }, + { 1, Iclass_iclass_POP128_1_args, + 1, Iclass_iclass_POP128_1_stateArgs, 1, Iclass_iclass_POP128_1_intfArgs }, + { 1, Iclass_iclass_POP128_2_args, + 1, Iclass_iclass_POP128_2_stateArgs, 1, Iclass_iclass_POP128_2_intfArgs }, + { 1, Iclass_iclass_POP128_3_args, + 1, Iclass_iclass_POP128_3_stateArgs, 1, Iclass_iclass_POP128_3_intfArgs }, + { 1, Iclass_iclass_POP128_4_args, + 1, Iclass_iclass_POP128_4_stateArgs, 1, Iclass_iclass_POP128_4_intfArgs }, + { 1, Iclass_iclass_POP128_5_args, + 1, Iclass_iclass_POP128_5_stateArgs, 1, Iclass_iclass_POP128_5_intfArgs }, + { 3, Iclass_iclass_POP128_2CMPQ_0_args, + 1, Iclass_iclass_POP128_2CMPQ_0_stateArgs, 1, Iclass_iclass_POP128_2CMPQ_0_intfArgs }, + { 3, Iclass_iclass_POP128_2CMPQ_1_args, + 1, Iclass_iclass_POP128_2CMPQ_1_stateArgs, 1, Iclass_iclass_POP128_2CMPQ_1_intfArgs }, + { 3, Iclass_iclass_POP128_2CMPQ_2_args, + 1, Iclass_iclass_POP128_2CMPQ_2_stateArgs, 1, Iclass_iclass_POP128_2CMPQ_2_intfArgs }, + { 3, Iclass_iclass_POP128_2CMPQ_3_args, + 1, Iclass_iclass_POP128_2CMPQ_3_stateArgs, 1, Iclass_iclass_POP128_2CMPQ_3_intfArgs }, + { 2, Iclass_iclass_POP128_2M_0_args, + 0, 0, 1, Iclass_iclass_POP128_2M_0_intfArgs }, + { 2, Iclass_iclass_POP128_2M_1_args, + 0, 0, 1, Iclass_iclass_POP128_2M_1_intfArgs }, + { 2, Iclass_iclass_POP128_2M_2_args, + 0, 0, 1, Iclass_iclass_POP128_2M_2_intfArgs }, + { 2, Iclass_iclass_POP128_2M_3_args, + 0, 0, 1, Iclass_iclass_POP128_2M_3_intfArgs }, + { 2, Iclass_iclass_POP128_2PQ_0_args, + 1, Iclass_iclass_POP128_2PQ_0_stateArgs, 1, Iclass_iclass_POP128_2PQ_0_intfArgs }, + { 2, Iclass_iclass_POP128_2PQ_1_args, + 1, Iclass_iclass_POP128_2PQ_1_stateArgs, 1, Iclass_iclass_POP128_2PQ_1_intfArgs }, + { 2, Iclass_iclass_POP128_2PQ_2_args, + 1, Iclass_iclass_POP128_2PQ_2_stateArgs, 1, Iclass_iclass_POP128_2PQ_2_intfArgs }, + { 2, Iclass_iclass_POP128_2PQ_3_args, + 1, Iclass_iclass_POP128_2PQ_3_stateArgs, 1, Iclass_iclass_POP128_2PQ_3_intfArgs }, + { 2, Iclass_iclass_POP128_2PQ_4_args, + 1, Iclass_iclass_POP128_2PQ_4_stateArgs, 1, Iclass_iclass_POP128_2PQ_4_intfArgs }, + { 2, Iclass_iclass_POP128_2PQ_5_args, + 1, Iclass_iclass_POP128_2PQ_5_stateArgs, 1, Iclass_iclass_POP128_2PQ_5_intfArgs }, + { 1, Iclass_iclass_POP2X128_2PQ_01_args, + 1, Iclass_iclass_POP2X128_2PQ_01_stateArgs, 2, Iclass_iclass_POP2X128_2PQ_01_intfArgs }, + { 1, Iclass_iclass_POP2X128_2PQ_03_args, + 1, Iclass_iclass_POP2X128_2PQ_03_stateArgs, 2, Iclass_iclass_POP2X128_2PQ_03_intfArgs }, + { 1, Iclass_iclass_POP2X128_2PQ_21_args, + 1, Iclass_iclass_POP2X128_2PQ_21_stateArgs, 2, Iclass_iclass_POP2X128_2PQ_21_intfArgs }, + { 1, Iclass_iclass_POP2X128_2PQ_23_args, + 1, Iclass_iclass_POP2X128_2PQ_23_stateArgs, 2, Iclass_iclass_POP2X128_2PQ_23_intfArgs }, + { 1, Iclass_iclass_POP32_0_args, + 0, 0, 1, Iclass_iclass_POP32_0_intfArgs }, + { 1, Iclass_iclass_POP32_1_args, + 0, 0, 1, Iclass_iclass_POP32_1_intfArgs }, + { 1, Iclass_iclass_POP32_2_args, + 0, 0, 1, Iclass_iclass_POP32_2_intfArgs }, + { 1, Iclass_iclass_POP32_3_args, + 0, 0, 1, Iclass_iclass_POP32_3_intfArgs }, + { 2, Iclass_iclass_PUSH128_args, + 1, Iclass_iclass_PUSH128_stateArgs, 12, Iclass_iclass_PUSH128_intfArgs }, + { 3, Iclass_iclass_PUSH128_M_args, + 0, 0, 8, Iclass_iclass_PUSH128_M_intfArgs }, + { 3, Iclass_iclass_PUSH128_PQ_args, + 1, Iclass_iclass_PUSH128_PQ_stateArgs, 12, Iclass_iclass_PUSH128_PQ_intfArgs }, + { 3, Iclass_iclass_PUSH2X128_PQ_args, + 1, Iclass_iclass_PUSH2X128_PQ_stateArgs, 8, Iclass_iclass_PUSH2X128_PQ_intfArgs }, + { 2, Iclass_iclass_PUSH32_args, + 0, 0, 12, Iclass_iclass_PUSH32_intfArgs }, + { 2, Iclass_iclass_QREADY_args, + 0, 0, 23, Iclass_iclass_QREADY_intfArgs }, + { 1, Iclass_iclass_RDTIEP_args, + 0, 0, 1, Iclass_iclass_RDTIEP_intfArgs }, + { 1, Iclass_iclass_SETTIEP_args, + 1, Iclass_iclass_SETTIEP_stateArgs, 0, 0 }, + { 5, Iclass_iclass_SMOD_LUT_args, + 2, Iclass_iclass_SMOD_LUT_stateArgs, 2, Iclass_iclass_SMOD_LUT_intfArgs }, + { 1, Iclass_iclass_WRTBSIGQ_args, + 0, 0, 1, Iclass_iclass_WRTBSIGQ_intfArgs }, + { 1, Iclass_iclass_WRTBSIGQM_args, + 0, 0, 1, Iclass_iclass_WRTBSIGQM_intfArgs }, + { 2, Iclass_iclass_WRTIEP_args, + 1, Iclass_iclass_WRTIEP_stateArgs, 0, 0 }, + { 1, Iclass_iclass_WRTSIGQ_args, + 0, 0, 1, Iclass_iclass_WRTSIGQ_intfArgs }, + { 2, Iclass_iclass_ABS8_args, + 1, Iclass_iclass_ABS8_stateArgs, 0, 0 }, + { 4, Iclass_iclass_ADD16_args, + 3, Iclass_iclass_ADD16_stateArgs, 0, 0 }, + { 3, Iclass_iclass_ADD32_args, + 3, Iclass_iclass_ADD32_stateArgs, 0, 0 }, + { 1, Iclass_iclass_ADDAC_I2R_args, + 3, Iclass_iclass_ADDAC_I2R_stateArgs, 0, 0 }, + { 1, Iclass_iclass_ADDAC_R2I_args, + 3, Iclass_iclass_ADDAC_R2I_stateArgs, 0, 0 }, + { 2, Iclass_iclass_ADDAR2_args, + 0, 0, 0, 0 }, + { 3, Iclass_iclass_ADDCM_args, + 3, Iclass_iclass_ADDCM_stateArgs, 0, 0 }, + { 3, Iclass_iclass_ADDWRP_args, + 1, Iclass_iclass_ADDWRP_stateArgs, 0, 0 }, + { 3, Iclass_iclass_AND128_args, + 1, Iclass_iclass_AND128_stateArgs, 0, 0 }, + { 2, Iclass_iclass_ARGMAX8_args, + 3, Iclass_iclass_ARGMAX8_stateArgs, 0, 0 }, + { 3, Iclass_iclass_ASL_args, + 3, Iclass_iclass_ASL_stateArgs, 0, 0 }, + { 3, Iclass_iclass_ASL32_args, + 3, Iclass_iclass_ASL32_stateArgs, 0, 0 }, + { 2, Iclass_iclass_ASLACM_args, + 3, Iclass_iclass_ASLACM_stateArgs, 0, 0 }, + { 3, Iclass_iclass_ASLM_args, + 3, Iclass_iclass_ASLM_stateArgs, 0, 0 }, + { 2, Iclass_iclass_ASLM32_args, + 3, Iclass_iclass_ASLM32_stateArgs, 0, 0 }, + { 3, Iclass_iclass_ASR_args, + 3, Iclass_iclass_ASR_stateArgs, 0, 0 }, + { 3, Iclass_iclass_ASR32_args, + 3, Iclass_iclass_ASR32_stateArgs, 0, 0 }, + { 2, Iclass_iclass_ASRAC_args, + 3, Iclass_iclass_ASRAC_stateArgs, 0, 0 }, + { 3, Iclass_iclass_ASRM_args, + 3, Iclass_iclass_ASRM_stateArgs, 0, 0 }, + { 4, Iclass_iclass_BITFEXT_args, + 0, 0, 0, 0 }, + { 4, Iclass_iclass_BITFINS_args, + 0, 0, 0, 0 }, + { 2, Iclass_iclass_CLB_C_args, + 5, Iclass_iclass_CLB_C_stateArgs, 0, 0 }, + { 2, Iclass_iclass_CLB_R_args, + 5, Iclass_iclass_CLB_R_stateArgs, 0, 0 }, + { 3, Iclass_iclass_CMP8_args, + 2, Iclass_iclass_CMP8_stateArgs, 0, 0 }, + { 3, Iclass_iclass_CMP_I_args, + 2, Iclass_iclass_CMP_I_stateArgs, 0, 0 }, + { 3, Iclass_iclass_CMP_R_args, + 2, Iclass_iclass_CMP_R_stateArgs, 0, 0 }, + { 5, Iclass_iclass_EXT_args, + 6, Iclass_iclass_EXT_stateArgs, 0, 0 }, + { 5, Iclass_iclass_EXT_R_args, + 6, Iclass_iclass_EXT_R_stateArgs, 0, 0 }, + { 3, Iclass_iclass_EXT32_I_args, + 2, Iclass_iclass_EXT32_I_stateArgs, 0, 0 }, + { 3, Iclass_iclass_EXT32_R_args, + 2, Iclass_iclass_EXT32_R_stateArgs, 0, 0 }, + { 3, Iclass_iclass_EXTUI4_args, + 1, Iclass_iclass_EXTUI4_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LSLM_args, + 1, Iclass_iclass_LSLM_stateArgs, 0, 0 }, + { 3, Iclass_iclass_LSRM_args, + 1, Iclass_iclass_LSRM_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MAX8_args, + 1, Iclass_iclass_MAX8_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MEAN_args, + 1, Iclass_iclass_MEAN_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MEAN32_args, + 1, Iclass_iclass_MEAN32_stateArgs, 0, 0 }, + { 3, Iclass_iclass_MIN8_args, + 1, Iclass_iclass_MIN8_stateArgs, 0, 0 }, + { 2, Iclass_iclass_MINCLB_C_args, + 5, Iclass_iclass_MINCLB_C_stateArgs, 0, 0 }, + { 2, Iclass_iclass_MINCLB_R_args, + 5, Iclass_iclass_MINCLB_R_stateArgs, 0, 0 }, + { 2, Iclass_iclass_NOT128_args, + 1, Iclass_iclass_NOT128_stateArgs, 0, 0 }, + { 3, Iclass_iclass_OR128_args, + 1, Iclass_iclass_OR128_stateArgs, 0, 0 }, + { 3, Iclass_iclass_PERM_args, + 1, Iclass_iclass_PERM_stateArgs, 0, 0 }, + { 1, Iclass_iclass_REDAC_args, + 3, Iclass_iclass_REDAC_stateArgs, 0, 0 }, + { 1, Iclass_iclass_REDAC2_args, + 3, Iclass_iclass_REDAC2_stateArgs, 0, 0 }, + { 1, Iclass_iclass_REDAC4_args, + 3, Iclass_iclass_REDAC4_stateArgs, 0, 0 }, + { 1, Iclass_iclass_REDACS_args, + 3, Iclass_iclass_REDACS_stateArgs, 0, 0 }, + { 2, Iclass_iclass_SMINCLB_C_args, + 5, Iclass_iclass_SMINCLB_C_stateArgs, 0, 0 }, + { 2, Iclass_iclass_SMINCLB_R_args, + 5, Iclass_iclass_SMINCLB_R_stateArgs, 0, 0 }, + { 3, Iclass_iclass_STSWAPBM_args, + 0, 0, 0, 0 }, + { 3, Iclass_iclass_STSWAPBMU_args, + 0, 0, 0, 0 }, + { 3, Iclass_iclass_SUB32_args, + 3, Iclass_iclass_SUB32_stateArgs, 0, 0 }, + { 1, Iclass_iclass_SUBAC_I2R_args, + 3, Iclass_iclass_SUBAC_I2R_stateArgs, 0, 0 }, + { 1, Iclass_iclass_SUBAC_R2I_args, + 3, Iclass_iclass_SUBAC_R2I_stateArgs, 0, 0 }, + { 2, Iclass_iclass_SUBARX_args, + 0, 0, 0, 0 }, + { 3, Iclass_iclass_SUBCM_args, + 3, Iclass_iclass_SUBCM_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SUBMEAN_args, + 1, Iclass_iclass_SUBMEAN_stateArgs, 0, 0 }, + { 3, Iclass_iclass_SUBWRP_args, + 1, Iclass_iclass_SUBWRP_stateArgs, 0, 0 }, + { 2, Iclass_iclass_TRANS_args, + 1, Iclass_iclass_TRANS_stateArgs, 0, 0 }, + { 3, Iclass_iclass_XOR128_args, + 1, Iclass_iclass_XOR128_stateArgs, 0, 0 }, + { 1, Iclass_rur_expstate_args, + 1, Iclass_rur_expstate_stateArgs, 0, 0 }, + { 1, Iclass_wur_expstate_args, + 1, Iclass_wur_expstate_stateArgs, 0, 0 }, + { 1, Iclass_rur_sov_args, + 2, Iclass_rur_sov_stateArgs, 0, 0 }, + { 1, Iclass_wur_sov_args, + 2, Iclass_wur_sov_stateArgs, 0, 0 }, + { 1, Iclass_rur_sat_mode_args, + 2, Iclass_rur_sat_mode_stateArgs, 0, 0 }, + { 1, Iclass_wur_sat_mode_args, + 2, Iclass_wur_sat_mode_stateArgs, 0, 0 }, + { 1, Iclass_rur_sar0_args, + 2, Iclass_rur_sar0_stateArgs, 0, 0 }, + { 1, Iclass_wur_sar0_args, + 2, Iclass_wur_sar0_stateArgs, 0, 0 }, + { 1, Iclass_rur_sar1_args, + 2, Iclass_rur_sar1_stateArgs, 0, 0 }, + { 1, Iclass_wur_sar1_args, + 2, Iclass_wur_sar1_stateArgs, 0, 0 }, + { 1, Iclass_rur_sar2_args, + 2, Iclass_rur_sar2_stateArgs, 0, 0 }, + { 1, Iclass_wur_sar2_args, + 2, Iclass_wur_sar2_stateArgs, 0, 0 }, + { 1, Iclass_rur_sar3_args, + 2, Iclass_rur_sar3_stateArgs, 0, 0 }, + { 1, Iclass_wur_sar3_args, + 2, Iclass_wur_sar3_stateArgs, 0, 0 }, + { 1, Iclass_rur_hsar0_args, + 2, Iclass_rur_hsar0_stateArgs, 0, 0 }, + { 1, Iclass_wur_hsar0_args, + 2, Iclass_wur_hsar0_stateArgs, 0, 0 }, + { 1, Iclass_rur_hsar1_args, + 2, Iclass_rur_hsar1_stateArgs, 0, 0 }, + { 1, Iclass_wur_hsar1_args, + 2, Iclass_wur_hsar1_stateArgs, 0, 0 }, + { 1, Iclass_rur_hsar2_args, + 2, Iclass_rur_hsar2_stateArgs, 0, 0 }, + { 1, Iclass_wur_hsar2_args, + 2, Iclass_wur_hsar2_stateArgs, 0, 0 }, + { 1, Iclass_rur_hsar3_args, + 2, Iclass_rur_hsar3_stateArgs, 0, 0 }, + { 1, Iclass_wur_hsar3_args, + 2, Iclass_wur_hsar3_stateArgs, 0, 0 }, + { 1, Iclass_rur_max_reg_0_args, + 2, Iclass_rur_max_reg_0_stateArgs, 0, 0 }, + { 1, Iclass_wur_max_reg_0_args, + 2, Iclass_wur_max_reg_0_stateArgs, 0, 0 }, + { 1, Iclass_rur_max_reg_1_args, + 2, Iclass_rur_max_reg_1_stateArgs, 0, 0 }, + { 1, Iclass_wur_max_reg_1_args, + 2, Iclass_wur_max_reg_1_stateArgs, 0, 0 }, + { 1, Iclass_rur_max_reg_2_args, + 2, Iclass_rur_max_reg_2_stateArgs, 0, 0 }, + { 1, Iclass_wur_max_reg_2_args, + 2, Iclass_wur_max_reg_2_stateArgs, 0, 0 }, + { 1, Iclass_rur_max_reg_3_args, + 2, Iclass_rur_max_reg_3_stateArgs, 0, 0 }, + { 1, Iclass_wur_max_reg_3_args, + 2, Iclass_wur_max_reg_3_stateArgs, 0, 0 }, + { 1, Iclass_rur_arg_max_reg_0_args, + 2, Iclass_rur_arg_max_reg_0_stateArgs, 0, 0 }, + { 1, Iclass_wur_arg_max_reg_0_args, + 2, Iclass_wur_arg_max_reg_0_stateArgs, 0, 0 }, + { 1, Iclass_rur_arg_max_reg_1_args, + 2, Iclass_rur_arg_max_reg_1_stateArgs, 0, 0 }, + { 1, Iclass_wur_arg_max_reg_1_args, + 2, Iclass_wur_arg_max_reg_1_stateArgs, 0, 0 }, + { 1, Iclass_rur_arg_max_reg_2_args, + 2, Iclass_rur_arg_max_reg_2_stateArgs, 0, 0 }, + { 1, Iclass_wur_arg_max_reg_2_args, + 2, Iclass_wur_arg_max_reg_2_stateArgs, 0, 0 }, + { 1, Iclass_rur_arg_max_reg_3_args, + 2, Iclass_rur_arg_max_reg_3_stateArgs, 0, 0 }, + { 1, Iclass_wur_arg_max_reg_3_args, + 2, Iclass_wur_arg_max_reg_3_stateArgs, 0, 0 }, + { 1, Iclass_rur_nco_counter_0_args, + 2, Iclass_rur_nco_counter_0_stateArgs, 0, 0 }, + { 1, Iclass_wur_nco_counter_0_args, + 2, Iclass_wur_nco_counter_0_stateArgs, 0, 0 }, + { 1, Iclass_rur_nco_counter_1_args, + 2, Iclass_rur_nco_counter_1_stateArgs, 0, 0 }, + { 1, Iclass_wur_nco_counter_1_args, + 2, Iclass_wur_nco_counter_1_stateArgs, 0, 0 }, + { 1, Iclass_rur_nco_counter_2_args, + 2, Iclass_rur_nco_counter_2_stateArgs, 0, 0 }, + { 1, Iclass_wur_nco_counter_2_args, + 2, Iclass_wur_nco_counter_2_stateArgs, 0, 0 }, + { 1, Iclass_rur_nco_counter_3_args, + 2, Iclass_rur_nco_counter_3_stateArgs, 0, 0 }, + { 1, Iclass_wur_nco_counter_3_args, + 2, Iclass_wur_nco_counter_3_stateArgs, 0, 0 }, + { 1, Iclass_rur_interp_ext_n_args, + 2, Iclass_rur_interp_ext_n_stateArgs, 0, 0 }, + { 1, Iclass_wur_interp_ext_n_args, + 2, Iclass_wur_interp_ext_n_stateArgs, 0, 0 }, + { 1, Iclass_rur_interp_ext_l_args, + 2, Iclass_rur_interp_ext_l_stateArgs, 0, 0 }, + { 1, Iclass_wur_interp_ext_l_args, + 2, Iclass_wur_interp_ext_l_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_0_args, + 2, Iclass_rur_llr_buf_0_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_0_args, + 2, Iclass_wur_llr_buf_0_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_1_args, + 2, Iclass_rur_llr_buf_1_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_1_args, + 2, Iclass_wur_llr_buf_1_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_2_args, + 2, Iclass_rur_llr_buf_2_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_2_args, + 2, Iclass_wur_llr_buf_2_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_3_args, + 2, Iclass_rur_llr_buf_3_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_3_args, + 2, Iclass_wur_llr_buf_3_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_4_args, + 2, Iclass_rur_llr_buf_4_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_4_args, + 2, Iclass_wur_llr_buf_4_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_5_args, + 2, Iclass_rur_llr_buf_5_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_5_args, + 2, Iclass_wur_llr_buf_5_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_6_args, + 2, Iclass_rur_llr_buf_6_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_6_args, + 2, Iclass_wur_llr_buf_6_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_7_args, + 2, Iclass_rur_llr_buf_7_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_7_args, + 2, Iclass_wur_llr_buf_7_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_8_args, + 2, Iclass_rur_llr_buf_8_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_8_args, + 2, Iclass_wur_llr_buf_8_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_9_args, + 2, Iclass_rur_llr_buf_9_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_9_args, + 2, Iclass_wur_llr_buf_9_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_10_args, + 2, Iclass_rur_llr_buf_10_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_10_args, + 2, Iclass_wur_llr_buf_10_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_11_args, + 2, Iclass_rur_llr_buf_11_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_11_args, + 2, Iclass_wur_llr_buf_11_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_12_args, + 2, Iclass_rur_llr_buf_12_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_12_args, + 2, Iclass_wur_llr_buf_12_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_13_args, + 2, Iclass_rur_llr_buf_13_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_13_args, + 2, Iclass_wur_llr_buf_13_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_14_args, + 2, Iclass_rur_llr_buf_14_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_14_args, + 2, Iclass_wur_llr_buf_14_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_15_args, + 2, Iclass_rur_llr_buf_15_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_15_args, + 2, Iclass_wur_llr_buf_15_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_16_args, + 2, Iclass_rur_llr_buf_16_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_16_args, + 2, Iclass_wur_llr_buf_16_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_17_args, + 2, Iclass_rur_llr_buf_17_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_17_args, + 2, Iclass_wur_llr_buf_17_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_18_args, + 2, Iclass_rur_llr_buf_18_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_18_args, + 2, Iclass_wur_llr_buf_18_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_19_args, + 2, Iclass_rur_llr_buf_19_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_19_args, + 2, Iclass_wur_llr_buf_19_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_20_args, + 2, Iclass_rur_llr_buf_20_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_20_args, + 2, Iclass_wur_llr_buf_20_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_21_args, + 2, Iclass_rur_llr_buf_21_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_21_args, + 2, Iclass_wur_llr_buf_21_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_22_args, + 2, Iclass_rur_llr_buf_22_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_22_args, + 2, Iclass_wur_llr_buf_22_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_buf_23_args, + 2, Iclass_rur_llr_buf_23_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_buf_23_args, + 2, Iclass_wur_llr_buf_23_stateArgs, 0, 0 }, + { 1, Iclass_rur_smod_buf_0_args, + 2, Iclass_rur_smod_buf_0_stateArgs, 0, 0 }, + { 1, Iclass_wur_smod_buf_0_args, + 2, Iclass_wur_smod_buf_0_stateArgs, 0, 0 }, + { 1, Iclass_rur_smod_buf_1_args, + 2, Iclass_rur_smod_buf_1_stateArgs, 0, 0 }, + { 1, Iclass_wur_smod_buf_1_args, + 2, Iclass_wur_smod_buf_1_stateArgs, 0, 0 }, + { 1, Iclass_rur_smod_buf_2_args, + 2, Iclass_rur_smod_buf_2_stateArgs, 0, 0 }, + { 1, Iclass_wur_smod_buf_2_args, + 2, Iclass_wur_smod_buf_2_stateArgs, 0, 0 }, + { 1, Iclass_rur_smod_buf_3_args, + 2, Iclass_rur_smod_buf_3_stateArgs, 0, 0 }, + { 1, Iclass_wur_smod_buf_3_args, + 2, Iclass_wur_smod_buf_3_stateArgs, 0, 0 }, + { 1, Iclass_rur_smod_buf_4_args, + 2, Iclass_rur_smod_buf_4_stateArgs, 0, 0 }, + { 1, Iclass_wur_smod_buf_4_args, + 2, Iclass_wur_smod_buf_4_stateArgs, 0, 0 }, + { 1, Iclass_rur_smod_buf_5_args, + 2, Iclass_rur_smod_buf_5_stateArgs, 0, 0 }, + { 1, Iclass_wur_smod_buf_5_args, + 2, Iclass_wur_smod_buf_5_stateArgs, 0, 0 }, + { 1, Iclass_rur_smod_buf_6_args, + 2, Iclass_rur_smod_buf_6_stateArgs, 0, 0 }, + { 1, Iclass_wur_smod_buf_6_args, + 2, Iclass_wur_smod_buf_6_stateArgs, 0, 0 }, + { 1, Iclass_rur_smod_buf_7_args, + 2, Iclass_rur_smod_buf_7_stateArgs, 0, 0 }, + { 1, Iclass_wur_smod_buf_7_args, + 2, Iclass_wur_smod_buf_7_stateArgs, 0, 0 }, + { 1, Iclass_rur_weight_reg_args, + 2, Iclass_rur_weight_reg_stateArgs, 0, 0 }, + { 1, Iclass_wur_weight_reg_args, + 2, Iclass_wur_weight_reg_stateArgs, 0, 0 }, + { 1, Iclass_rur_scale_reg_args, + 2, Iclass_rur_scale_reg_stateArgs, 0, 0 }, + { 1, Iclass_wur_scale_reg_args, + 2, Iclass_wur_scale_reg_stateArgs, 0, 0 }, + { 1, Iclass_rur_llr_pos_args, + 2, Iclass_rur_llr_pos_stateArgs, 0, 0 }, + { 1, Iclass_wur_llr_pos_args, + 2, Iclass_wur_llr_pos_stateArgs, 0, 0 }, + { 1, Iclass_rur_smod_pos_args, + 2, Iclass_rur_smod_pos_stateArgs, 0, 0 }, + { 1, Iclass_wur_smod_pos_args, + 2, Iclass_wur_smod_pos_stateArgs, 0, 0 }, + { 1, Iclass_rur_perm_reg_args, + 2, Iclass_rur_perm_reg_stateArgs, 0, 0 }, + { 1, Iclass_wur_perm_reg_args, + 2, Iclass_wur_perm_reg_stateArgs, 0, 0 }, + { 1, Iclass_rur_smod_offset_table_0_args, + 2, Iclass_rur_smod_offset_table_0_stateArgs, 0, 0 }, + { 1, Iclass_wur_smod_offset_table_0_args, + 2, Iclass_wur_smod_offset_table_0_stateArgs, 0, 0 }, + { 1, Iclass_rur_smod_offset_table_1_args, + 2, Iclass_rur_smod_offset_table_1_stateArgs, 0, 0 }, + { 1, Iclass_wur_smod_offset_table_1_args, + 2, Iclass_wur_smod_offset_table_1_stateArgs, 0, 0 }, + { 1, Iclass_rur_smod_offset_table_2_args, + 2, Iclass_rur_smod_offset_table_2_stateArgs, 0, 0 }, + { 1, Iclass_wur_smod_offset_table_2_args, + 2, Iclass_wur_smod_offset_table_2_stateArgs, 0, 0 }, + { 1, Iclass_rur_smod_offset_table_3_args, + 2, Iclass_rur_smod_offset_table_3_stateArgs, 0, 0 }, + { 1, Iclass_wur_smod_offset_table_3_args, + 2, Iclass_wur_smod_offset_table_3_stateArgs, 0, 0 }, + { 1, Iclass_rur_phasor_n_args, + 2, Iclass_rur_phasor_n_stateArgs, 0, 0 }, + { 1, Iclass_wur_phasor_n_args, + 2, Iclass_wur_phasor_n_stateArgs, 0, 0 }, + { 1, Iclass_rur_phasor_offset_args, + 2, Iclass_rur_phasor_offset_stateArgs, 0, 0 }, + { 1, Iclass_wur_phasor_offset_args, + 2, Iclass_wur_phasor_offset_stateArgs, 0, 0 } +}; + +enum xtensa_iclass_id { + ICLASS_xt_iclass_excw, + ICLASS_xt_iclass_rfe, + ICLASS_xt_iclass_rfde, + ICLASS_xt_iclass_syscall, + ICLASS_xt_iclass_simcall, + ICLASS_xt_iclass_call12, + ICLASS_xt_iclass_call8, + ICLASS_xt_iclass_call4, + ICLASS_xt_iclass_callx12, + ICLASS_xt_iclass_callx8, + ICLASS_xt_iclass_callx4, + ICLASS_xt_iclass_entry, + ICLASS_xt_iclass_movsp, + ICLASS_xt_iclass_rotw, + ICLASS_xt_iclass_retw, + ICLASS_xt_iclass_rfwou, + ICLASS_xt_iclass_l32e, + ICLASS_xt_iclass_s32e, + ICLASS_xt_iclass_rsr_windowbase, + ICLASS_xt_iclass_wsr_windowbase, + ICLASS_xt_iclass_xsr_windowbase, + ICLASS_xt_iclass_rsr_windowstart, + ICLASS_xt_iclass_wsr_windowstart, + ICLASS_xt_iclass_xsr_windowstart, + ICLASS_xt_iclass_add_n, + ICLASS_xt_iclass_addi_n, + ICLASS_xt_iclass_bz6, + ICLASS_xt_iclass_ill_n, + ICLASS_xt_iclass_loadi4, + ICLASS_xt_iclass_mov_n, + ICLASS_xt_iclass_movi_n, + ICLASS_xt_iclass_nopn, + ICLASS_xt_iclass_retn, + ICLASS_xt_iclass_storei4, + ICLASS_rur_threadptr, + ICLASS_wur_threadptr, + ICLASS_xt_iclass_addi, + ICLASS_xt_iclass_addmi, + ICLASS_xt_iclass_addsub, + ICLASS_xt_iclass_bit, + ICLASS_xt_iclass_bsi8, + ICLASS_xt_iclass_bsi8b, + ICLASS_xt_iclass_bsi8u, + ICLASS_xt_iclass_bst8, + ICLASS_xt_iclass_bsz12, + ICLASS_xt_iclass_call0, + ICLASS_xt_iclass_callx0, + ICLASS_xt_iclass_exti, + ICLASS_xt_iclass_ill, + ICLASS_xt_iclass_jump, + ICLASS_xt_iclass_jumpx, + ICLASS_xt_iclass_l16ui, + ICLASS_xt_iclass_l16si, + ICLASS_xt_iclass_l32i, + ICLASS_xt_iclass_l32r, + ICLASS_xt_iclass_l8i, + ICLASS_xt_iclass_loop, + ICLASS_xt_iclass_loopz, + ICLASS_xt_iclass_movi, + ICLASS_xt_iclass_movz, + ICLASS_xt_iclass_neg, + ICLASS_xt_iclass_nop, + ICLASS_xt_iclass_return, + ICLASS_xt_iclass_s16i, + ICLASS_xt_iclass_s32i, + ICLASS_xt_iclass_s8i, + ICLASS_xt_iclass_sar, + ICLASS_xt_iclass_sari, + ICLASS_xt_iclass_shifts, + ICLASS_xt_iclass_shiftst, + ICLASS_xt_iclass_shiftt, + ICLASS_xt_iclass_slli, + ICLASS_xt_iclass_srai, + ICLASS_xt_iclass_srli, + ICLASS_xt_iclass_memw, + ICLASS_xt_iclass_extw, + ICLASS_xt_iclass_isync, + ICLASS_xt_iclass_sync, + ICLASS_xt_iclass_rsil, + ICLASS_xt_iclass_rsr_lend, + ICLASS_xt_iclass_wsr_lend, + ICLASS_xt_iclass_xsr_lend, + ICLASS_xt_iclass_rsr_lcount, + ICLASS_xt_iclass_wsr_lcount, + ICLASS_xt_iclass_xsr_lcount, + ICLASS_xt_iclass_rsr_lbeg, + ICLASS_xt_iclass_wsr_lbeg, + ICLASS_xt_iclass_xsr_lbeg, + ICLASS_xt_iclass_rsr_sar, + ICLASS_xt_iclass_wsr_sar, + ICLASS_xt_iclass_xsr_sar, + ICLASS_xt_iclass_rsr_litbase, + ICLASS_xt_iclass_wsr_litbase, + ICLASS_xt_iclass_xsr_litbase, + ICLASS_xt_iclass_rsr_176, + ICLASS_xt_iclass_wsr_176, + ICLASS_xt_iclass_rsr_208, + ICLASS_xt_iclass_rsr_ps, + ICLASS_xt_iclass_wsr_ps, + ICLASS_xt_iclass_xsr_ps, + ICLASS_xt_iclass_rsr_epc1, + ICLASS_xt_iclass_wsr_epc1, + ICLASS_xt_iclass_xsr_epc1, + ICLASS_xt_iclass_rsr_excsave1, + ICLASS_xt_iclass_wsr_excsave1, + ICLASS_xt_iclass_xsr_excsave1, + ICLASS_xt_iclass_rsr_epc2, + ICLASS_xt_iclass_wsr_epc2, + ICLASS_xt_iclass_xsr_epc2, + ICLASS_xt_iclass_rsr_excsave2, + ICLASS_xt_iclass_wsr_excsave2, + ICLASS_xt_iclass_xsr_excsave2, + ICLASS_xt_iclass_rsr_epc3, + ICLASS_xt_iclass_wsr_epc3, + ICLASS_xt_iclass_xsr_epc3, + ICLASS_xt_iclass_rsr_excsave3, + ICLASS_xt_iclass_wsr_excsave3, + ICLASS_xt_iclass_xsr_excsave3, + ICLASS_xt_iclass_rsr_epc4, + ICLASS_xt_iclass_wsr_epc4, + ICLASS_xt_iclass_xsr_epc4, + ICLASS_xt_iclass_rsr_excsave4, + ICLASS_xt_iclass_wsr_excsave4, + ICLASS_xt_iclass_xsr_excsave4, + ICLASS_xt_iclass_rsr_epc5, + ICLASS_xt_iclass_wsr_epc5, + ICLASS_xt_iclass_xsr_epc5, + ICLASS_xt_iclass_rsr_excsave5, + ICLASS_xt_iclass_wsr_excsave5, + ICLASS_xt_iclass_xsr_excsave5, + ICLASS_xt_iclass_rsr_epc6, + ICLASS_xt_iclass_wsr_epc6, + ICLASS_xt_iclass_xsr_epc6, + ICLASS_xt_iclass_rsr_excsave6, + ICLASS_xt_iclass_wsr_excsave6, + ICLASS_xt_iclass_xsr_excsave6, + ICLASS_xt_iclass_rsr_eps2, + ICLASS_xt_iclass_wsr_eps2, + ICLASS_xt_iclass_xsr_eps2, + ICLASS_xt_iclass_rsr_eps3, + ICLASS_xt_iclass_wsr_eps3, + ICLASS_xt_iclass_xsr_eps3, + ICLASS_xt_iclass_rsr_eps4, + ICLASS_xt_iclass_wsr_eps4, + ICLASS_xt_iclass_xsr_eps4, + ICLASS_xt_iclass_rsr_eps5, + ICLASS_xt_iclass_wsr_eps5, + ICLASS_xt_iclass_xsr_eps5, + ICLASS_xt_iclass_rsr_eps6, + ICLASS_xt_iclass_wsr_eps6, + ICLASS_xt_iclass_xsr_eps6, + ICLASS_xt_iclass_rsr_excvaddr, + ICLASS_xt_iclass_wsr_excvaddr, + ICLASS_xt_iclass_xsr_excvaddr, + ICLASS_xt_iclass_rsr_depc, + ICLASS_xt_iclass_wsr_depc, + ICLASS_xt_iclass_xsr_depc, + ICLASS_xt_iclass_rsr_exccause, + ICLASS_xt_iclass_wsr_exccause, + ICLASS_xt_iclass_xsr_exccause, + ICLASS_xt_iclass_rsr_prid, + ICLASS_xt_iclass_rsr_vecbase, + ICLASS_xt_iclass_wsr_vecbase, + ICLASS_xt_iclass_xsr_vecbase, + ICLASS_xt_mul16, + ICLASS_xt_iclass_rfi, + ICLASS_xt_iclass_wait, + ICLASS_xt_iclass_rsr_interrupt, + ICLASS_xt_iclass_wsr_intset, + ICLASS_xt_iclass_wsr_intclear, + ICLASS_xt_iclass_rsr_intenable, + ICLASS_xt_iclass_wsr_intenable, + ICLASS_xt_iclass_xsr_intenable, + ICLASS_xt_iclass_break, + ICLASS_xt_iclass_break_n, + ICLASS_xt_iclass_rsr_dbreaka0, + ICLASS_xt_iclass_wsr_dbreaka0, + ICLASS_xt_iclass_xsr_dbreaka0, + ICLASS_xt_iclass_rsr_dbreakc0, + ICLASS_xt_iclass_wsr_dbreakc0, + ICLASS_xt_iclass_xsr_dbreakc0, + ICLASS_xt_iclass_rsr_dbreaka1, + ICLASS_xt_iclass_wsr_dbreaka1, + ICLASS_xt_iclass_xsr_dbreaka1, + ICLASS_xt_iclass_rsr_dbreakc1, + ICLASS_xt_iclass_wsr_dbreakc1, + ICLASS_xt_iclass_xsr_dbreakc1, + ICLASS_xt_iclass_rsr_ibreaka0, + ICLASS_xt_iclass_wsr_ibreaka0, + ICLASS_xt_iclass_xsr_ibreaka0, + ICLASS_xt_iclass_rsr_ibreaka1, + ICLASS_xt_iclass_wsr_ibreaka1, + ICLASS_xt_iclass_xsr_ibreaka1, + ICLASS_xt_iclass_rsr_ibreakenable, + ICLASS_xt_iclass_wsr_ibreakenable, + ICLASS_xt_iclass_xsr_ibreakenable, + ICLASS_xt_iclass_rsr_debugcause, + ICLASS_xt_iclass_wsr_debugcause, + ICLASS_xt_iclass_xsr_debugcause, + ICLASS_xt_iclass_rsr_icount, + ICLASS_xt_iclass_wsr_icount, + ICLASS_xt_iclass_xsr_icount, + ICLASS_xt_iclass_rsr_icountlevel, + ICLASS_xt_iclass_wsr_icountlevel, + ICLASS_xt_iclass_xsr_icountlevel, + ICLASS_xt_iclass_rsr_ddr, + ICLASS_xt_iclass_wsr_ddr, + ICLASS_xt_iclass_xsr_ddr, + ICLASS_xt_iclass_rfdo, + ICLASS_xt_iclass_rfdd, + ICLASS_xt_iclass_wsr_mmid, + ICLASS_xt_iclass_bbool1, + ICLASS_xt_iclass_bbool4, + ICLASS_xt_iclass_bbool8, + ICLASS_xt_iclass_bbranch, + ICLASS_xt_iclass_bmove, + ICLASS_xt_iclass_RSR_BR, + ICLASS_xt_iclass_WSR_BR, + ICLASS_xt_iclass_XSR_BR, + ICLASS_xt_iclass_rsr_ccount, + ICLASS_xt_iclass_wsr_ccount, + ICLASS_xt_iclass_xsr_ccount, + ICLASS_xt_iclass_rsr_ccompare0, + ICLASS_xt_iclass_wsr_ccompare0, + ICLASS_xt_iclass_xsr_ccompare0, + ICLASS_xt_iclass_rsr_ccompare1, + ICLASS_xt_iclass_wsr_ccompare1, + ICLASS_xt_iclass_xsr_ccompare1, + ICLASS_xt_iclass_icache, + ICLASS_xt_iclass_icache_lock, + ICLASS_xt_iclass_icache_inv, + ICLASS_xt_iclass_licx, + ICLASS_xt_iclass_sicx, + ICLASS_xt_iclass_dcache, + ICLASS_xt_iclass_dcache_ind, + ICLASS_xt_iclass_dcache_inv, + ICLASS_xt_iclass_dpf, + ICLASS_xt_iclass_dcache_lock, + ICLASS_xt_iclass_sdct, + ICLASS_xt_iclass_ldct, + ICLASS_xt_iclass_idtlb, + ICLASS_xt_iclass_rdtlb, + ICLASS_xt_iclass_wdtlb, + ICLASS_xt_iclass_iitlb, + ICLASS_xt_iclass_ritlb, + ICLASS_xt_iclass_witlb, + ICLASS_xt_iclass_rsr_cpenable, + ICLASS_xt_iclass_wsr_cpenable, + ICLASS_xt_iclass_xsr_cpenable, + ICLASS_xt_iclass_clamp, + ICLASS_xt_iclass_minmax, + ICLASS_xt_iclass_nsa, + ICLASS_xt_iclass_sx, + ICLASS_xt_iclass_l32ai, + ICLASS_xt_iclass_s32ri, + ICLASS_xt_iclass_s32c1i, + ICLASS_xt_iclass_rsr_scompare1, + ICLASS_xt_iclass_wsr_scompare1, + ICLASS_xt_iclass_xsr_scompare1, + ICLASS_xt_iclass_rsr_atomctl, + ICLASS_xt_iclass_wsr_atomctl, + ICLASS_xt_iclass_xsr_atomctl, + ICLASS_xt_iclass_rer, + ICLASS_xt_iclass_wer, + ICLASS_rur_fcr, + ICLASS_wur_fcr, + ICLASS_rur_fsr, + ICLASS_wur_fsr, + ICLASS_fp, + ICLASS_fp_mac, + ICLASS_fp_cmov, + ICLASS_fp_mov, + ICLASS_fp_mov2, + ICLASS_fp_cmp, + ICLASS_fp_float, + ICLASS_fp_int, + ICLASS_fp_rfr, + ICLASS_fp_wfr, + ICLASS_fp_lsi, + ICLASS_fp_lsiu, + ICLASS_fp_lsx, + ICLASS_fp_lsxu, + ICLASS_fp_ssi, + ICLASS_fp_ssiu, + ICLASS_fp_ssx, + ICLASS_fp_ssxu, + ICLASS_iclass_GET_ARGMAX, + ICLASS_iclass_GET_HSAR, + ICLASS_iclass_GET_HSAR2SAR, + ICLASS_iclass_GET_INTERP_EXT_N, + ICLASS_iclass_GET_INTERP_EXT_L, + ICLASS_iclass_GET_LLR_BUF, + ICLASS_iclass_GET_LLR_POS, + ICLASS_iclass_GET_MAX, + ICLASS_iclass_GET_NCO, + ICLASS_iclass_GET_PERM_REG, + ICLASS_iclass_GET_PHASOR_N, + ICLASS_iclass_GET_PHASOR_OFFSET, + ICLASS_iclass_GET_SAR, + ICLASS_iclass_GET_SCALE_REG, + ICLASS_iclass_GET_SMOD_BUF, + ICLASS_iclass_GET_SMOD_OFFSET_TABLE, + ICLASS_iclass_GET_SMOD_POS, + ICLASS_iclass_GET_SOV, + ICLASS_iclass_GET_WGHT, + ICLASS_iclass_SET_ARGMAX, + ICLASS_iclass_SET_EXT_REGS, + ICLASS_iclass_SET_HSAR, + ICLASS_iclass_SET_LLR_BUF, + ICLASS_iclass_SET_LLR_POS, + ICLASS_iclass_SET_MAX, + ICLASS_iclass_SET_NCO, + ICLASS_iclass_SET_PERM_REG, + ICLASS_iclass_SET_PHASOR_N, + ICLASS_iclass_SET_PHASOR_OFFSET, + ICLASS_iclass_SET_SAR, + ICLASS_iclass_SET_SCALE_REG, + ICLASS_iclass_SET_SMOD_BUF, + ICLASS_iclass_SET_SMOD_OFFSET_TABLE, + ICLASS_iclass_SET_SMOD_POS, + ICLASS_iclass_SET_SOV, + ICLASS_iclass_SET_WGHT, + ICLASS_iclass_LAC2X32, + ICLASS_iclass_LAC2X64_0, + ICLASS_iclass_LAC2X64_1, + ICLASS_iclass_LAC2X64_2, + ICLASS_iclass_LAC2X64_3, + ICLASS_iclass_LAC32_R, + ICLASS_iclass_LAC_IH, + ICLASS_iclass_LAC_IL, + ICLASS_iclass_LAC_RH, + ICLASS_iclass_LAC_RL, + ICLASS_iclass_LCM, + ICLASS_iclass_LCM_PINC, + ICLASS_iclass_LCM_PINC_X, + ICLASS_iclass_LCM_U, + ICLASS_iclass_LCM_X, + ICLASS_iclass_LCM_XU, + ICLASS_iclass_LP, + ICLASS_iclass_LP_X, + ICLASS_iclass_LQ, + ICLASS_iclass_LQ_X, + ICLASS_iclass_LUT0, + ICLASS_iclass_LUT1, + ICLASS_iclass_LUT2, + ICLASS_iclass_LUT3, + ICLASS_iclass_SAC2X32, + ICLASS_iclass_SAC2X64_0, + ICLASS_iclass_SAC2X64_1, + ICLASS_iclass_SAC2X64_2, + ICLASS_iclass_SAC2X64_3, + ICLASS_iclass_SAC32_R, + ICLASS_iclass_SAC_IH, + ICLASS_iclass_SAC_IL, + ICLASS_iclass_SAC_RH, + ICLASS_iclass_SAC_RL, + ICLASS_iclass_SCM, + ICLASS_iclass_SCM_PINC, + ICLASS_iclass_SCM_PINC_X, + ICLASS_iclass_SCM_U, + ICLASS_iclass_SCM_X, + ICLASS_iclass_SCM_XU, + ICLASS_iclass_STORE_P, + ICLASS_iclass_STORE_Q, + ICLASS_iclass_AR2CM_DUP, + ICLASS_iclass_AR2CM_LN, + ICLASS_iclass_AR2CM_LN_I, + ICLASS_iclass_AR2CM_LN_R, + ICLASS_iclass_AR2PQ_LN, + ICLASS_iclass_AR2SAR_DUP, + ICLASS_iclass_CLRAC, + ICLASS_iclass_CLRCM, + ICLASS_iclass_CM2AR_LN, + ICLASS_iclass_CM2AR_LN_I, + ICLASS_iclass_CM2AR_LN_R, + ICLASS_iclass_COMB_AR, + ICLASS_iclass_CONJ, + ICLASS_iclass_MOV2AC32_I, + ICLASS_iclass_MOV2AC32_R, + ICLASS_iclass_MOV2CM2PQ, + ICLASS_iclass_MOVAC, + ICLASS_iclass_MOVAC_I, + ICLASS_iclass_MOVAC_I2R, + ICLASS_iclass_MOVAC_R, + ICLASS_iclass_MOVAC_R2I, + ICLASS_iclass_MOVAR2, + ICLASS_iclass_MOVCM, + ICLASS_iclass_MOVCM2PQ, + ICLASS_iclass_MOVCND_0, + ICLASS_iclass_MOVCND_1, + ICLASS_iclass_MOVCND_2, + ICLASS_iclass_MOVCND_3, + ICLASS_iclass_MOVCND_4, + ICLASS_iclass_MOVCND_5, + ICLASS_iclass_MOVCND_6, + ICLASS_iclass_MOVCND_7, + ICLASS_iclass_MOVCND8_0, + ICLASS_iclass_MOVCND8_1, + ICLASS_iclass_MOVCND8_2, + ICLASS_iclass_MOVCND8_3, + ICLASS_iclass_MOVCND8_4, + ICLASS_iclass_MOVCND8_5, + ICLASS_iclass_MOVCND8_6, + ICLASS_iclass_MOVCND8_7, + ICLASS_iclass_MOV_I, + ICLASS_iclass_MOVPQ2PQ, + ICLASS_iclass_MOV_R, + ICLASS_iclass_NEGCM, + ICLASS_iclass_POP16LLR_1, + ICLASS_iclass_PQ2CM, + ICLASS_iclass_SWAPAC_R, + ICLASS_iclass_SWAPAC_RI, + ICLASS_iclass_SWAPB, + ICLASS_iclass_ADD2AC, + ICLASS_iclass_ADDAC, + ICLASS_iclass_CDOT, + ICLASS_iclass_CDOTAC, + ICLASS_iclass_CDOTACS, + ICLASS_iclass_CMAC, + ICLASS_iclass_CMACS, + ICLASS_iclass_CMPY, + ICLASS_iclass_CMPY2CM, + ICLASS_iclass_CMPY2PQ, + ICLASS_iclass_CMPYS, + ICLASS_iclass_CMPYXP2PQ, + ICLASS_iclass_COMB32, + ICLASS_iclass_DOT, + ICLASS_iclass_DOTAC, + ICLASS_iclass_DOTACS, + ICLASS_iclass_LIN_INT, + ICLASS_iclass_LLRPRE1, + ICLASS_iclass_LLRPRE2, + ICLASS_iclass_MAC, + ICLASS_iclass_MAC8, + ICLASS_iclass_MACD8, + ICLASS_iclass_MACPQXP_0, + ICLASS_iclass_MACPQXP_1, + ICLASS_iclass_MACPQXP_2, + ICLASS_iclass_MACPQXP_3, + ICLASS_iclass_MACS, + ICLASS_iclass_MACXP2_0, + ICLASS_iclass_MACXP2_1, + ICLASS_iclass_MACXP_0, + ICLASS_iclass_MACXP_1, + ICLASS_iclass_MACXP_2, + ICLASS_iclass_MACXP_3, + ICLASS_iclass_MOV2AC, + ICLASS_iclass_MPY, + ICLASS_iclass_MPY2CM, + ICLASS_iclass_MPY2PQ, + ICLASS_iclass_MPY8, + ICLASS_iclass_MPYADD8_2CM, + ICLASS_iclass_MPYD8, + ICLASS_iclass_MPYPQXP_0, + ICLASS_iclass_MPYPQXP_1, + ICLASS_iclass_MPYPQXP_2, + ICLASS_iclass_MPYPQXP_3, + ICLASS_iclass_MPYS, + ICLASS_iclass_MPYXP2PQ, + ICLASS_iclass_MPYXP2_0, + ICLASS_iclass_MPYXP2_1, + ICLASS_iclass_MPYXP_0, + ICLASS_iclass_MPYXP_1, + ICLASS_iclass_MPYXP_2, + ICLASS_iclass_MPYXP_3, + ICLASS_iclass_NORMACD, + ICLASS_iclass_NORMACPQ_I, + ICLASS_iclass_NORMACPQ_R, + ICLASS_iclass_NORMD, + ICLASS_iclass_NORMPYPQ_I, + ICLASS_iclass_NORMPYPQ_R, + ICLASS_iclass_RCMAC, + ICLASS_iclass_RCMPY, + ICLASS_iclass_RCMPY2CM, + ICLASS_iclass_RFIR, + ICLASS_iclass_RFIRA, + ICLASS_iclass_RFIRD, + ICLASS_iclass_RFIRDA, + ICLASS_iclass_RMAC, + ICLASS_iclass_RMPY, + ICLASS_iclass_RMPY2CM, + ICLASS_iclass_SMOD_ALIGN, + ICLASS_iclass_SMOD_SCR, + ICLASS_iclass_SUB2AC, + ICLASS_iclass_WGHT32, + ICLASS_iclass_CLRTIEP, + ICLASS_iclass_EXT_2FIFO_0, + ICLASS_iclass_EXT_2FIFO_1, + ICLASS_iclass_EXT_2FIFO_2, + ICLASS_iclass_EXT_2FIFO_3, + ICLASS_iclass_EXT_R2FIFO_0, + ICLASS_iclass_EXT_R2FIFO_1, + ICLASS_iclass_EXT_R2FIFO_2, + ICLASS_iclass_EXT_R2FIFO_3, + ICLASS_iclass_LUT, + ICLASS_iclass_LUT_AR, + ICLASS_iclass_LUT_IEXT, + ICLASS_iclass_LUT_PHASOR, + ICLASS_iclass_LUT_REXT, + ICLASS_iclass_LUT_WRITE, + ICLASS_iclass_MOVEQ128_0, + ICLASS_iclass_MOVEQ128_1, + ICLASS_iclass_MOVEQ128_2, + ICLASS_iclass_MOVEQ128_3, + ICLASS_iclass_MOVEQ128_4, + ICLASS_iclass_MOVEQ128_5, + ICLASS_iclass_MOVEQ32_0, + ICLASS_iclass_MOVEQ32_1, + ICLASS_iclass_MOVEQ32_2, + ICLASS_iclass_MOVEQ32_3, + ICLASS_iclass_NCO_UPDATE, + ICLASS_iclass_POP128_0, + ICLASS_iclass_POP128_1, + ICLASS_iclass_POP128_2, + ICLASS_iclass_POP128_3, + ICLASS_iclass_POP128_4, + ICLASS_iclass_POP128_5, + ICLASS_iclass_POP128_2CMPQ_0, + ICLASS_iclass_POP128_2CMPQ_1, + ICLASS_iclass_POP128_2CMPQ_2, + ICLASS_iclass_POP128_2CMPQ_3, + ICLASS_iclass_POP128_2M_0, + ICLASS_iclass_POP128_2M_1, + ICLASS_iclass_POP128_2M_2, + ICLASS_iclass_POP128_2M_3, + ICLASS_iclass_POP128_2PQ_0, + ICLASS_iclass_POP128_2PQ_1, + ICLASS_iclass_POP128_2PQ_2, + ICLASS_iclass_POP128_2PQ_3, + ICLASS_iclass_POP128_2PQ_4, + ICLASS_iclass_POP128_2PQ_5, + ICLASS_iclass_POP2X128_2PQ_01, + ICLASS_iclass_POP2X128_2PQ_03, + ICLASS_iclass_POP2X128_2PQ_21, + ICLASS_iclass_POP2X128_2PQ_23, + ICLASS_iclass_POP32_0, + ICLASS_iclass_POP32_1, + ICLASS_iclass_POP32_2, + ICLASS_iclass_POP32_3, + ICLASS_iclass_PUSH128, + ICLASS_iclass_PUSH128_M, + ICLASS_iclass_PUSH128_PQ, + ICLASS_iclass_PUSH2X128_PQ, + ICLASS_iclass_PUSH32, + ICLASS_iclass_QREADY, + ICLASS_iclass_RDTIEP, + ICLASS_iclass_SETTIEP, + ICLASS_iclass_SMOD_LUT, + ICLASS_iclass_WRTBSIGQ, + ICLASS_iclass_WRTBSIGQM, + ICLASS_iclass_WRTIEP, + ICLASS_iclass_WRTSIGQ, + ICLASS_iclass_ABS8, + ICLASS_iclass_ADD16, + ICLASS_iclass_ADD32, + ICLASS_iclass_ADDAC_I2R, + ICLASS_iclass_ADDAC_R2I, + ICLASS_iclass_ADDAR2, + ICLASS_iclass_ADDCM, + ICLASS_iclass_ADDWRP, + ICLASS_iclass_AND128, + ICLASS_iclass_ARGMAX8, + ICLASS_iclass_ASL, + ICLASS_iclass_ASL32, + ICLASS_iclass_ASLACM, + ICLASS_iclass_ASLM, + ICLASS_iclass_ASLM32, + ICLASS_iclass_ASR, + ICLASS_iclass_ASR32, + ICLASS_iclass_ASRAC, + ICLASS_iclass_ASRM, + ICLASS_iclass_BITFEXT, + ICLASS_iclass_BITFINS, + ICLASS_iclass_CLB_C, + ICLASS_iclass_CLB_R, + ICLASS_iclass_CMP8, + ICLASS_iclass_CMP_I, + ICLASS_iclass_CMP_R, + ICLASS_iclass_EXT, + ICLASS_iclass_EXT_R, + ICLASS_iclass_EXT32_I, + ICLASS_iclass_EXT32_R, + ICLASS_iclass_EXTUI4, + ICLASS_iclass_LSLM, + ICLASS_iclass_LSRM, + ICLASS_iclass_MAX8, + ICLASS_iclass_MEAN, + ICLASS_iclass_MEAN32, + ICLASS_iclass_MIN8, + ICLASS_iclass_MINCLB_C, + ICLASS_iclass_MINCLB_R, + ICLASS_iclass_NOT128, + ICLASS_iclass_OR128, + ICLASS_iclass_PERM, + ICLASS_iclass_REDAC, + ICLASS_iclass_REDAC2, + ICLASS_iclass_REDAC4, + ICLASS_iclass_REDACS, + ICLASS_iclass_SMINCLB_C, + ICLASS_iclass_SMINCLB_R, + ICLASS_iclass_STSWAPBM, + ICLASS_iclass_STSWAPBMU, + ICLASS_iclass_SUB32, + ICLASS_iclass_SUBAC_I2R, + ICLASS_iclass_SUBAC_R2I, + ICLASS_iclass_SUBARX, + ICLASS_iclass_SUBCM, + ICLASS_iclass_SUBMEAN, + ICLASS_iclass_SUBWRP, + ICLASS_iclass_TRANS, + ICLASS_iclass_XOR128, + ICLASS_rur_expstate, + ICLASS_wur_expstate, + ICLASS_rur_sov, + ICLASS_wur_sov, + ICLASS_rur_sat_mode, + ICLASS_wur_sat_mode, + ICLASS_rur_sar0, + ICLASS_wur_sar0, + ICLASS_rur_sar1, + ICLASS_wur_sar1, + ICLASS_rur_sar2, + ICLASS_wur_sar2, + ICLASS_rur_sar3, + ICLASS_wur_sar3, + ICLASS_rur_hsar0, + ICLASS_wur_hsar0, + ICLASS_rur_hsar1, + ICLASS_wur_hsar1, + ICLASS_rur_hsar2, + ICLASS_wur_hsar2, + ICLASS_rur_hsar3, + ICLASS_wur_hsar3, + ICLASS_rur_max_reg_0, + ICLASS_wur_max_reg_0, + ICLASS_rur_max_reg_1, + ICLASS_wur_max_reg_1, + ICLASS_rur_max_reg_2, + ICLASS_wur_max_reg_2, + ICLASS_rur_max_reg_3, + ICLASS_wur_max_reg_3, + ICLASS_rur_arg_max_reg_0, + ICLASS_wur_arg_max_reg_0, + ICLASS_rur_arg_max_reg_1, + ICLASS_wur_arg_max_reg_1, + ICLASS_rur_arg_max_reg_2, + ICLASS_wur_arg_max_reg_2, + ICLASS_rur_arg_max_reg_3, + ICLASS_wur_arg_max_reg_3, + ICLASS_rur_nco_counter_0, + ICLASS_wur_nco_counter_0, + ICLASS_rur_nco_counter_1, + ICLASS_wur_nco_counter_1, + ICLASS_rur_nco_counter_2, + ICLASS_wur_nco_counter_2, + ICLASS_rur_nco_counter_3, + ICLASS_wur_nco_counter_3, + ICLASS_rur_interp_ext_n, + ICLASS_wur_interp_ext_n, + ICLASS_rur_interp_ext_l, + ICLASS_wur_interp_ext_l, + ICLASS_rur_llr_buf_0, + ICLASS_wur_llr_buf_0, + ICLASS_rur_llr_buf_1, + ICLASS_wur_llr_buf_1, + ICLASS_rur_llr_buf_2, + ICLASS_wur_llr_buf_2, + ICLASS_rur_llr_buf_3, + ICLASS_wur_llr_buf_3, + ICLASS_rur_llr_buf_4, + ICLASS_wur_llr_buf_4, + ICLASS_rur_llr_buf_5, + ICLASS_wur_llr_buf_5, + ICLASS_rur_llr_buf_6, + ICLASS_wur_llr_buf_6, + ICLASS_rur_llr_buf_7, + ICLASS_wur_llr_buf_7, + ICLASS_rur_llr_buf_8, + ICLASS_wur_llr_buf_8, + ICLASS_rur_llr_buf_9, + ICLASS_wur_llr_buf_9, + ICLASS_rur_llr_buf_10, + ICLASS_wur_llr_buf_10, + ICLASS_rur_llr_buf_11, + ICLASS_wur_llr_buf_11, + ICLASS_rur_llr_buf_12, + ICLASS_wur_llr_buf_12, + ICLASS_rur_llr_buf_13, + ICLASS_wur_llr_buf_13, + ICLASS_rur_llr_buf_14, + ICLASS_wur_llr_buf_14, + ICLASS_rur_llr_buf_15, + ICLASS_wur_llr_buf_15, + ICLASS_rur_llr_buf_16, + ICLASS_wur_llr_buf_16, + ICLASS_rur_llr_buf_17, + ICLASS_wur_llr_buf_17, + ICLASS_rur_llr_buf_18, + ICLASS_wur_llr_buf_18, + ICLASS_rur_llr_buf_19, + ICLASS_wur_llr_buf_19, + ICLASS_rur_llr_buf_20, + ICLASS_wur_llr_buf_20, + ICLASS_rur_llr_buf_21, + ICLASS_wur_llr_buf_21, + ICLASS_rur_llr_buf_22, + ICLASS_wur_llr_buf_22, + ICLASS_rur_llr_buf_23, + ICLASS_wur_llr_buf_23, + ICLASS_rur_smod_buf_0, + ICLASS_wur_smod_buf_0, + ICLASS_rur_smod_buf_1, + ICLASS_wur_smod_buf_1, + ICLASS_rur_smod_buf_2, + ICLASS_wur_smod_buf_2, + ICLASS_rur_smod_buf_3, + ICLASS_wur_smod_buf_3, + ICLASS_rur_smod_buf_4, + ICLASS_wur_smod_buf_4, + ICLASS_rur_smod_buf_5, + ICLASS_wur_smod_buf_5, + ICLASS_rur_smod_buf_6, + ICLASS_wur_smod_buf_6, + ICLASS_rur_smod_buf_7, + ICLASS_wur_smod_buf_7, + ICLASS_rur_weight_reg, + ICLASS_wur_weight_reg, + ICLASS_rur_scale_reg, + ICLASS_wur_scale_reg, + ICLASS_rur_llr_pos, + ICLASS_wur_llr_pos, + ICLASS_rur_smod_pos, + ICLASS_wur_smod_pos, + ICLASS_rur_perm_reg, + ICLASS_wur_perm_reg, + ICLASS_rur_smod_offset_table_0, + ICLASS_wur_smod_offset_table_0, + ICLASS_rur_smod_offset_table_1, + ICLASS_wur_smod_offset_table_1, + ICLASS_rur_smod_offset_table_2, + ICLASS_wur_smod_offset_table_2, + ICLASS_rur_smod_offset_table_3, + ICLASS_wur_smod_offset_table_3, + ICLASS_rur_phasor_n, + ICLASS_wur_phasor_n, + ICLASS_rur_phasor_offset, + ICLASS_wur_phasor_offset +}; + + +/* Opcode encodings. */ + +static void +Opcode_excw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2080; +} + +static void +Opcode_rfe_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3000; +} + +static void +Opcode_rfde_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3200; +} + +static void +Opcode_syscall_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5000; +} + +static void +Opcode_simcall_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5100; +} + +static void +Opcode_call12_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35; +} + +static void +Opcode_call8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x25; +} + +static void +Opcode_call4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x15; +} + +static void +Opcode_callx12_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf0; +} + +static void +Opcode_callx8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe0; +} + +static void +Opcode_callx4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd0; +} + +static void +Opcode_entry_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x36; +} + +static void +Opcode_movsp_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1000; +} + +static void +Opcode_rotw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x408000; +} + +static void +Opcode_retw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x90; +} + +static void +Opcode_retw_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf01d; +} + +static void +Opcode_rfwo_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3400; +} + +static void +Opcode_rfwu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3500; +} + +static void +Opcode_l32e_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x90000; +} + +static void +Opcode_s32e_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x490000; +} + +static void +Opcode_rsr_windowbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34800; +} + +static void +Opcode_wsr_windowbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x134800; +} + +static void +Opcode_xsr_windowbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x614800; +} + +static void +Opcode_rsr_windowstart_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34900; +} + +static void +Opcode_wsr_windowstart_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x134900; +} + +static void +Opcode_xsr_windowstart_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x614900; +} + +static void +Opcode_add_n_Slot_inst16a_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa; +} + +static void +Opcode_addi_n_Slot_inst16a_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb; +} + +static void +Opcode_addi_n_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000; +} + +static void +Opcode_addi_n_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30001; +} + +static void +Opcode_addi_n_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000; +} + +static void +Opcode_addi_n_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000; +} + +static void +Opcode_addi_n_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30001; +} + +static void +Opcode_addi_n_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000; +} + +static void +Opcode_addi_n_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30000; +} + +static void +Opcode_addi_n_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000; +} + +static void +Opcode_addi_n_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe0002; +} + +static void +Opcode_addi_n_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f8001; +} + +static void +Opcode_beqz_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8c; +} + +static void +Opcode_beqz_n_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13000; +} + +static void +Opcode_beqz_n_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13000; +} + +static void +Opcode_beqz_n_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4f001; +} + +static void +Opcode_beqz_n_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc05001; +} + +static void +Opcode_beqz_n_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d3001; +} + +static void +Opcode_bnez_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcc; +} + +static void +Opcode_bnez_n_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x23000; +} + +static void +Opcode_bnez_n_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x23000; +} + +static void +Opcode_bnez_n_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x52001; +} + +static void +Opcode_bnez_n_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc09001; +} + +static void +Opcode_bnez_n_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2e3001; +} + +static void +Opcode_ill_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf06d; +} + +static void +Opcode_l32i_n_Slot_inst16a_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8; +} + +static void +Opcode_l32i_n_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4c001; +} + +static void +Opcode_l32i_n_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4c001; +} + +static void +Opcode_l32i_n_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4c000; +} + +static void +Opcode_l32i_n_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4001; +} + +static void +Opcode_l32i_n_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40c000; +} + +static void +Opcode_mov_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd; +} + +static void +Opcode_mov_n_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2ec00; +} + +static void +Opcode_mov_n_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd400; +} + +static void +Opcode_mov_n_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd803; +} + +static void +Opcode_mov_n_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2e000; +} + +static void +Opcode_mov_n_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd400; +} + +static void +Opcode_mov_n_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2000; +} + +static void +Opcode_mov_n_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x53401; +} + +static void +Opcode_mov_n_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb403; +} + +static void +Opcode_mov_n_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x601401; +} + +static void +Opcode_mov_n_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c6c01; +} + +static void +Opcode_movi_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc; +} + +static void +Opcode_movi_n_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c000; +} + +static void +Opcode_movi_n_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x42002; +} + +static void +Opcode_movi_n_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc002; +} + +static void +Opcode_movi_n_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30000; +} + +static void +Opcode_movi_n_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x42002; +} + +static void +Opcode_movi_n_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_movi_n_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50001; +} + +static void +Opcode_movi_n_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8003; +} + +static void +Opcode_movi_n_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x402001; +} + +static void +Opcode_movi_n_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x530000; +} + +static void +Opcode_nop_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf03d; +} + +static void +Opcode_ret_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf00d; +} + +static void +Opcode_s32i_n_Slot_inst16a_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9; +} + +static void +Opcode_s32i_n_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20002; +} + +static void +Opcode_s32i_n_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20002; +} + +static void +Opcode_s32i_n_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40001; +} + +static void +Opcode_s32i_n_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8000; +} + +static void +Opcode_s32i_n_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4a4000; +} + +static void +Opcode_rur_threadptr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30e70; +} + +static void +Opcode_wur_threadptr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf3e700; +} + +static void +Opcode_addi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc002; +} + +static void +Opcode_addi_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2001; +} + +static void +Opcode_addi_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1000; +} + +static void +Opcode_addmi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd002; +} + +static void +Opcode_addmi_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x401; +} + +static void +Opcode_addmi_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2000; +} + +static void +Opcode_add_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800000; +} + +static void +Opcode_add_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_add_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x28001; +} + +static void +Opcode_add_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_add_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_add_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x28001; +} + +static void +Opcode_add_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_add_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x28000; +} + +static void +Opcode_add_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_add_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd0002; +} + +static void +Opcode_add_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f0001; +} + +static void +Opcode_sub_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc00000; +} + +static void +Opcode_sub_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x24000; +} + +static void +Opcode_sub_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x48002; +} + +static void +Opcode_sub_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8001; +} + +static void +Opcode_sub_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x24000; +} + +static void +Opcode_sub_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x60002; +} + +static void +Opcode_sub_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8001; +} + +static void +Opcode_sub_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c001; +} + +static void +Opcode_sub_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8002; +} + +static void +Opcode_sub_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1f0002; +} + +static void +Opcode_sub_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4ec000; +} + +static void +Opcode_addx2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x900000; +} + +static void +Opcode_addx2_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c001; +} + +static void +Opcode_addx2_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c001; +} + +static void +Opcode_addx2_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c000; +} + +static void +Opcode_addx2_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd4002; +} + +static void +Opcode_addx2_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3fc001; +} + +static void +Opcode_addx4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa00000; +} + +static void +Opcode_addx4_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34001; +} + +static void +Opcode_addx4_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34001; +} + +static void +Opcode_addx4_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34000; +} + +static void +Opcode_addx4_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd8002; +} + +static void +Opcode_addx4_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400000; +} + +static void +Opcode_addx8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb00000; +} + +static void +Opcode_addx8_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38001; +} + +static void +Opcode_addx8_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38001; +} + +static void +Opcode_addx8_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38000; +} + +static void +Opcode_addx8_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xdc002; +} + +static void +Opcode_addx8_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x404000; +} + +static void +Opcode_subx2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd00000; +} + +static void +Opcode_subx2_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50002; +} + +static void +Opcode_subx2_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4c002; +} + +static void +Opcode_subx2_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34001; +} + +static void +Opcode_subx2_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1ec002; +} + +static void +Opcode_subx2_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4f8000; +} + +static void +Opcode_subx4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe00000; +} + +static void +Opcode_subx4_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x60002; +} + +static void +Opcode_subx4_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x54002; +} + +static void +Opcode_subx4_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38001; +} + +static void +Opcode_subx4_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1f4002; +} + +static void +Opcode_subx4_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4fc000; +} + +static void +Opcode_subx8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf00000; +} + +static void +Opcode_subx8_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4c002; +} + +static void +Opcode_subx8_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x58002; +} + +static void +Opcode_subx8_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c001; +} + +static void +Opcode_subx8_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1f8002; +} + +static void +Opcode_subx8_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x504000; +} + +static void +Opcode_and_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x100000; +} + +static void +Opcode_and_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8000; +} + +static void +Opcode_and_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c001; +} + +static void +Opcode_and_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_and_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8000; +} + +static void +Opcode_and_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c001; +} + +static void +Opcode_and_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c000; +} + +static void +Opcode_and_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_and_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe4002; +} + +static void +Opcode_and_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x408000; +} + +static void +Opcode_or_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x200000; +} + +static void +Opcode_or_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1c000; +} + +static void +Opcode_or_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8002; +} + +static void +Opcode_or_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_or_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1c000; +} + +static void +Opcode_or_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8002; +} + +static void +Opcode_or_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10001; +} + +static void +Opcode_or_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4003; +} + +static void +Opcode_or_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1d4002; +} + +static void +Opcode_or_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x494000; +} + +static void +Opcode_xor_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x300000; +} + +static void +Opcode_xor_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x28000; +} + +static void +Opcode_xor_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x54002; +} + +static void +Opcode_xor_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc001; +} + +static void +Opcode_xor_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x28000; +} + +static void +Opcode_xor_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5c002; +} + +static void +Opcode_xor_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x44001; +} + +static void +Opcode_xor_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc002; +} + +static void +Opcode_xor_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1fc002; +} + +static void +Opcode_xor_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x518000; +} + +static void +Opcode_beqi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x26; +} + +static void +Opcode_beqi_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40; +} + +static void +Opcode_beqi_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_bnei_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x66; +} + +static void +Opcode_bnei_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800040; +} + +static void +Opcode_bnei_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc2; +} + +static void +Opcode_bgei_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe6; +} + +static void +Opcode_bgei_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80; +} + +static void +Opcode_bgei_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x42; +} + +static void +Opcode_blti_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa6; +} + +static void +Opcode_blti_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x200; +} + +static void +Opcode_blti_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x102; +} + +static void +Opcode_bbci_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6007; +} + +static void +Opcode_bbci_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x801; +} + +static void +Opcode_bbci_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_bbsi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe007; +} + +static void +Opcode_bbsi_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1001; +} + +static void +Opcode_bbsi_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800; +} + +static void +Opcode_bgeui_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf6; +} + +static void +Opcode_bgeui_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x100; +} + +static void +Opcode_bgeui_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x82; +} + +static void +Opcode_bltui_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb6; +} + +static void +Opcode_bltui_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400040; +} + +static void +Opcode_bltui_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x202; +} + +static void +Opcode_beq_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1007; +} + +static void +Opcode_beq_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800801; +} + +static void +Opcode_beq_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2800; +} + +static void +Opcode_bne_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9007; +} + +static void +Opcode_bne_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x401001; +} + +static void +Opcode_bne_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_bge_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa007; +} + +static void +Opcode_bge_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400c01; +} + +static void +Opcode_bge_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3000; +} + +static void +Opcode_blt_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2007; +} + +static void +Opcode_blt_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc00801; +} + +static void +Opcode_blt_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3400; +} + +static void +Opcode_bgeu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb007; +} + +static void +Opcode_bgeu_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800c01; +} + +static void +Opcode_bgeu_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c00; +} + +static void +Opcode_bltu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3007; +} + +static void +Opcode_bltu_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc00c01; +} + +static void +Opcode_bltu_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3800; +} + +static void +Opcode_bany_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8007; +} + +static void +Opcode_bany_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800401; +} + +static void +Opcode_bany_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1800; +} + +static void +Opcode_bnone_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7; +} + +static void +Opcode_bnone_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x801001; +} + +static void +Opcode_bnone_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x403; +} + +static void +Opcode_ball_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4007; +} + +static void +Opcode_ball_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400401; +} + +static void +Opcode_ball_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1400; +} + +static void +Opcode_bnall_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc007; +} + +static void +Opcode_bnall_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1801; +} + +static void +Opcode_bnall_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c00; +} + +static void +Opcode_bbc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5007; +} + +static void +Opcode_bbc_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc00401; +} + +static void +Opcode_bbc_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1c00; +} + +static void +Opcode_bbs_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd007; +} + +static void +Opcode_bbs_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400801; +} + +static void +Opcode_bbs_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2400; +} + +static void +Opcode_beqz_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16; +} + +static void +Opcode_beqz_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80002; +} + +static void +Opcode_beqz_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80001; +} + +static void +Opcode_bnez_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x56; +} + +static void +Opcode_bnez_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400002; +} + +static void +Opcode_bnez_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc0001; +} + +static void +Opcode_bgez_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd6; +} + +static void +Opcode_bgez_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x100002; +} + +static void +Opcode_bgez_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x100001; +} + +static void +Opcode_bltz_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x96; +} + +static void +Opcode_bltz_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x200002; +} + +static void +Opcode_bltz_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x200001; +} + +static void +Opcode_call0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5; +} + +static void +Opcode_callx0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc0; +} + +static void +Opcode_extui_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40000; +} + +static void +Opcode_extui_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_extui_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_extui_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_extui_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_extui_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_extui_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_extui_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_ill_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_j_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6; +} + +static void +Opcode_jx_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa0; +} + +static void +Opcode_l16ui_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1002; +} + +static void +Opcode_l16ui_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1003; +} + +static void +Opcode_l16si_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9002; +} + +static void +Opcode_l16si_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x803; +} + +static void +Opcode_l32i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2002; +} + +static void +Opcode_l32i_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2003; +} + +static void +Opcode_l32r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_l32r_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400001; +} + +static void +Opcode_l8ui_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_l8ui_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc03; +} + +static void +Opcode_loop_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8076; +} + +static void +Opcode_loopnez_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9076; +} + +static void +Opcode_loopgtz_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa076; +} + +static void +Opcode_movi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa002; +} + +static void +Opcode_movi_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800002; +} + +static void +Opcode_movi_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1c0001; +} + +static void +Opcode_moveqz_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x830000; +} + +static void +Opcode_moveqz_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20000; +} + +static void +Opcode_moveqz_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x74001; +} + +static void +Opcode_moveqz_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20000; +} + +static void +Opcode_moveqz_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x74001; +} + +static void +Opcode_moveqz_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x78000; +} + +static void +Opcode_moveqz_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1c4002; +} + +static void +Opcode_moveqz_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x454000; +} + +static void +Opcode_movnez_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x930000; +} + +static void +Opcode_movnez_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x18000; +} + +static void +Opcode_movnez_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_movnez_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x18000; +} + +static void +Opcode_movnez_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_movnez_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4001; +} + +static void +Opcode_movnez_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1e0002; +} + +static void +Opcode_movnez_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x474000; +} + +static void +Opcode_movltz_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa30000; +} + +static void +Opcode_movltz_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x14000; +} + +static void +Opcode_movltz_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7c001; +} + +static void +Opcode_movltz_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x14000; +} + +static void +Opcode_movltz_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7c001; +} + +static void +Opcode_movltz_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_movltz_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1d0002; +} + +static void +Opcode_movltz_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x470000; +} + +static void +Opcode_movgez_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb30000; +} + +static void +Opcode_movgez_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc000; +} + +static void +Opcode_movgez_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x78001; +} + +static void +Opcode_movgez_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc000; +} + +static void +Opcode_movgez_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x78001; +} + +static void +Opcode_movgez_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7c000; +} + +static void +Opcode_movgez_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1c8002; +} + +static void +Opcode_movgez_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x464000; +} + +static void +Opcode_neg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x600000; +} + +static void +Opcode_neg_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34034; +} + +static void +Opcode_neg_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6000c; +} + +static void +Opcode_neg_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x801f; +} + +static void +Opcode_neg_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34020; +} + +static void +Opcode_neg_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6000c; +} + +static void +Opcode_neg_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_neg_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x54035; +} + +static void +Opcode_neg_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc01f; +} + +static void +Opcode_neg_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x14001a; +} + +static void +Opcode_neg_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x36000d; +} + +static void +Opcode_abs_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x600100; +} + +static void +Opcode_abs_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34030; +} + +static void +Opcode_abs_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000c; +} + +static void +Opcode_abs_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34010; +} + +static void +Opcode_abs_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000c; +} + +static void +Opcode_abs_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x54021; +} + +static void +Opcode_abs_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x140016; +} + +static void +Opcode_abs_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34000d; +} + +static void +Opcode_nop_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20f0; +} + +static void +Opcode_nop_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32f64; +} + +static void +Opcode_nop_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc030; +} + +static void +Opcode_nop_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35430; +} + +static void +Opcode_nop_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xda5d4; +} + +static void +Opcode_nop_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa0000; +} + +static void +Opcode_nop_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa42f; +} + +static void +Opcode_nop_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2eda4; +} + +static void +Opcode_nop_Slot_pq_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x200; +} + +static void +Opcode_nop_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35430; +} + +static void +Opcode_nop_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x60; +} + +static void +Opcode_nop_Slot_acc2_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x200; +} + +static void +Opcode_nop_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2e40; +} + +static void +Opcode_nop_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9add4; +} + +static void +Opcode_nop_Slot_smod_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x202; +} + +static void +Opcode_nop_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5b015; +} + +static void +Opcode_nop_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x168dd; +} + +static void +Opcode_nop_Slot_llr_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400; +} + +static void +Opcode_nop_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc237; +} + +static void +Opcode_nop_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa50dc; +} + +static void +Opcode_nop_Slot_dual_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_nop_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2dec31; +} + +static void +Opcode_ret_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80; +} + +static void +Opcode_s16i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5002; +} + +static void +Opcode_s16i_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1403; +} + +static void +Opcode_s32i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6002; +} + +static void +Opcode_s32i_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1803; +} + +static void +Opcode_s8i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4002; +} + +static void +Opcode_s8i_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1c03; +} + +static void +Opcode_ssr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400000; +} + +static void +Opcode_ssr_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d740; +} + +static void +Opcode_ssr_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d740; +} + +static void +Opcode_ssr_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5df41; +} + +static void +Opcode_ssr_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcc8c0; +} + +static void +Opcode_ssr_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2ee801; +} + +static void +Opcode_ssl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x401000; +} + +static void +Opcode_ssl_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d6c0; +} + +static void +Opcode_ssl_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d6c0; +} + +static void +Opcode_ssl_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5dec1; +} + +static void +Opcode_ssl_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcc4c0; +} + +static void +Opcode_ssl_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2e6c01; +} + +static void +Opcode_ssa8l_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x402000; +} + +static void +Opcode_ssa8l_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d700; +} + +static void +Opcode_ssa8l_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d700; +} + +static void +Opcode_ssa8l_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5df01; +} + +static void +Opcode_ssa8l_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcc0c0; +} + +static void +Opcode_ssa8l_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2debc1; +} + +static void +Opcode_ssa8b_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x403000; +} + +static void +Opcode_ssa8b_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d680; +} + +static void +Opcode_ssa8b_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d680; +} + +static void +Opcode_ssa8b_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5de81; +} + +static void +Opcode_ssa8b_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe00c0; +} + +static void +Opcode_ssa8b_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2deb81; +} + +static void +Opcode_ssai_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x404000; +} + +static void +Opcode_ssai_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d400; +} + +static void +Opcode_ssai_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d400; +} + +static void +Opcode_ssai_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5dc01; +} + +static void +Opcode_ssai_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x480080; +} + +static void +Opcode_ssai_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d6f81; +} + +static void +Opcode_sll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa10000; +} + +static void +Opcode_sll_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c200; +} + +static void +Opcode_sll_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6c002; +} + +static void +Opcode_sll_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10000; +} + +static void +Opcode_sll_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c000; +} + +static void +Opcode_sll_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7c002; +} + +static void +Opcode_sll_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64001; +} + +static void +Opcode_sll_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10000; +} + +static void +Opcode_sll_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc40c0; +} + +static void +Opcode_sll_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40142; +} + +static void +Opcode_src_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x810000; +} + +static void +Opcode_src_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38002; +} + +static void +Opcode_src_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38002; +} + +static void +Opcode_src_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x28001; +} + +static void +Opcode_src_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1e4002; +} + +static void +Opcode_src_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4e0000; +} + +static void +Opcode_srl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x910000; +} + +static void +Opcode_srl_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5800c; +} + +static void +Opcode_srl_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5800c; +} + +static void +Opcode_srl_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x58011; +} + +static void +Opcode_srl_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x148016; +} + +static void +Opcode_srl_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34c00d; +} + +static void +Opcode_sra_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb10000; +} + +static void +Opcode_sra_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34038; +} + +static void +Opcode_sra_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5002c; +} + +static void +Opcode_sra_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x802b; +} + +static void +Opcode_sra_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34014; +} + +static void +Opcode_sra_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5002c; +} + +static void +Opcode_sra_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5403d; +} + +static void +Opcode_sra_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc02b; +} + +static void +Opcode_sra_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x144016; +} + +static void +Opcode_sra_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34802d; +} + +static void +Opcode_slli_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10000; +} + +static void +Opcode_slli_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40001; +} + +static void +Opcode_slli_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10003; +} + +static void +Opcode_slli_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40001; +} + +static void +Opcode_slli_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40000; +} + +static void +Opcode_slli_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10003; +} + +static void +Opcode_slli_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc0002; +} + +static void +Opcode_slli_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d8001; +} + +static void +Opcode_srai_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x210000; +} + +static void +Opcode_srai_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x18001; +} + +static void +Opcode_srai_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x18000; +} + +static void +Opcode_srai_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x18001; +} + +static void +Opcode_srai_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x18000; +} + +static void +Opcode_srai_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x18000; +} + +static void +Opcode_srai_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc8002; +} + +static void +Opcode_srai_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e8001; +} + +static void +Opcode_srli_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x410000; +} + +static void +Opcode_srli_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c002; +} + +static void +Opcode_srli_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c002; +} + +static void +Opcode_srli_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30001; +} + +static void +Opcode_srli_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1e8002; +} + +static void +Opcode_srli_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4cc000; +} + +static void +Opcode_memw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20c0; +} + +static void +Opcode_extw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20d0; +} + +static void +Opcode_isync_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2000; +} + +static void +Opcode_rsync_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2010; +} + +static void +Opcode_esync_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2020; +} + +static void +Opcode_dsync_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2030; +} + +static void +Opcode_rsil_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6000; +} + +static void +Opcode_rsr_lend_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30100; +} + +static void +Opcode_wsr_lend_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130100; +} + +static void +Opcode_xsr_lend_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610100; +} + +static void +Opcode_rsr_lcount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30200; +} + +static void +Opcode_wsr_lcount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130200; +} + +static void +Opcode_xsr_lcount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610200; +} + +static void +Opcode_rsr_lbeg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30000; +} + +static void +Opcode_wsr_lbeg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130000; +} + +static void +Opcode_xsr_lbeg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610000; +} + +static void +Opcode_rsr_sar_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30300; +} + +static void +Opcode_wsr_sar_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130300; +} + +static void +Opcode_xsr_sar_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610300; +} + +static void +Opcode_rsr_litbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30500; +} + +static void +Opcode_wsr_litbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130500; +} + +static void +Opcode_xsr_litbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610500; +} + +static void +Opcode_rsr_176_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b000; +} + +static void +Opcode_wsr_176_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b000; +} + +static void +Opcode_rsr_208_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d000; +} + +static void +Opcode_rsr_ps_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e600; +} + +static void +Opcode_wsr_ps_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e600; +} + +static void +Opcode_xsr_ps_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e600; +} + +static void +Opcode_rsr_epc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b100; +} + +static void +Opcode_wsr_epc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b100; +} + +static void +Opcode_xsr_epc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b100; +} + +static void +Opcode_rsr_excsave1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d100; +} + +static void +Opcode_wsr_excsave1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d100; +} + +static void +Opcode_xsr_excsave1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d100; +} + +static void +Opcode_rsr_epc2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b200; +} + +static void +Opcode_wsr_epc2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b200; +} + +static void +Opcode_xsr_epc2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b200; +} + +static void +Opcode_rsr_excsave2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d200; +} + +static void +Opcode_wsr_excsave2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d200; +} + +static void +Opcode_xsr_excsave2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d200; +} + +static void +Opcode_rsr_epc3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b300; +} + +static void +Opcode_wsr_epc3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b300; +} + +static void +Opcode_xsr_epc3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b300; +} + +static void +Opcode_rsr_excsave3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d300; +} + +static void +Opcode_wsr_excsave3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d300; +} + +static void +Opcode_xsr_excsave3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d300; +} + +static void +Opcode_rsr_epc4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b400; +} + +static void +Opcode_wsr_epc4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b400; +} + +static void +Opcode_xsr_epc4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b400; +} + +static void +Opcode_rsr_excsave4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d400; +} + +static void +Opcode_wsr_excsave4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d400; +} + +static void +Opcode_xsr_excsave4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d400; +} + +static void +Opcode_rsr_epc5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b500; +} + +static void +Opcode_wsr_epc5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b500; +} + +static void +Opcode_xsr_epc5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b500; +} + +static void +Opcode_rsr_excsave5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d500; +} + +static void +Opcode_wsr_excsave5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d500; +} + +static void +Opcode_xsr_excsave5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d500; +} + +static void +Opcode_rsr_epc6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b600; +} + +static void +Opcode_wsr_epc6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b600; +} + +static void +Opcode_xsr_epc6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b600; +} + +static void +Opcode_rsr_excsave6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d600; +} + +static void +Opcode_wsr_excsave6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d600; +} + +static void +Opcode_xsr_excsave6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d600; +} + +static void +Opcode_rsr_eps2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c200; +} + +static void +Opcode_wsr_eps2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c200; +} + +static void +Opcode_xsr_eps2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c200; +} + +static void +Opcode_rsr_eps3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c300; +} + +static void +Opcode_wsr_eps3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c300; +} + +static void +Opcode_xsr_eps3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c300; +} + +static void +Opcode_rsr_eps4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c400; +} + +static void +Opcode_wsr_eps4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c400; +} + +static void +Opcode_xsr_eps4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c400; +} + +static void +Opcode_rsr_eps5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c500; +} + +static void +Opcode_wsr_eps5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c500; +} + +static void +Opcode_xsr_eps5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c500; +} + +static void +Opcode_rsr_eps6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c600; +} + +static void +Opcode_wsr_eps6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c600; +} + +static void +Opcode_xsr_eps6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c600; +} + +static void +Opcode_rsr_excvaddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3ee00; +} + +static void +Opcode_wsr_excvaddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13ee00; +} + +static void +Opcode_xsr_excvaddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61ee00; +} + +static void +Opcode_rsr_depc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c000; +} + +static void +Opcode_wsr_depc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c000; +} + +static void +Opcode_xsr_depc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c000; +} + +static void +Opcode_rsr_exccause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e800; +} + +static void +Opcode_wsr_exccause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e800; +} + +static void +Opcode_xsr_exccause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e800; +} + +static void +Opcode_rsr_prid_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3eb00; +} + +static void +Opcode_rsr_vecbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e700; +} + +static void +Opcode_wsr_vecbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e700; +} + +static void +Opcode_xsr_vecbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e700; +} + +static void +Opcode_mul16u_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc10000; +} + +static void +Opcode_mul16s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd10000; +} + +static void +Opcode_rfi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3010; +} + +static void +Opcode_waiti_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7000; +} + +static void +Opcode_rsr_interrupt_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e200; +} + +static void +Opcode_wsr_intset_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e200; +} + +static void +Opcode_wsr_intclear_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e300; +} + +static void +Opcode_rsr_intenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e400; +} + +static void +Opcode_wsr_intenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e400; +} + +static void +Opcode_xsr_intenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e400; +} + +static void +Opcode_break_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000; +} + +static void +Opcode_break_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf02d; +} + +static void +Opcode_rsr_dbreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x39000; +} + +static void +Opcode_wsr_dbreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x139000; +} + +static void +Opcode_xsr_dbreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x619000; +} + +static void +Opcode_rsr_dbreakc0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3a000; +} + +static void +Opcode_wsr_dbreakc0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13a000; +} + +static void +Opcode_xsr_dbreakc0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61a000; +} + +static void +Opcode_rsr_dbreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x39100; +} + +static void +Opcode_wsr_dbreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x139100; +} + +static void +Opcode_xsr_dbreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x619100; +} + +static void +Opcode_rsr_dbreakc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3a100; +} + +static void +Opcode_wsr_dbreakc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13a100; +} + +static void +Opcode_xsr_dbreakc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61a100; +} + +static void +Opcode_rsr_ibreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38000; +} + +static void +Opcode_wsr_ibreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x138000; +} + +static void +Opcode_xsr_ibreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x618000; +} + +static void +Opcode_rsr_ibreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38100; +} + +static void +Opcode_wsr_ibreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x138100; +} + +static void +Opcode_xsr_ibreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x618100; +} + +static void +Opcode_rsr_ibreakenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x36000; +} + +static void +Opcode_wsr_ibreakenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x136000; +} + +static void +Opcode_xsr_ibreakenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x616000; +} + +static void +Opcode_rsr_debugcause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e900; +} + +static void +Opcode_wsr_debugcause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e900; +} + +static void +Opcode_xsr_debugcause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e900; +} + +static void +Opcode_rsr_icount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3ec00; +} + +static void +Opcode_wsr_icount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13ec00; +} + +static void +Opcode_xsr_icount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61ec00; +} + +static void +Opcode_rsr_icountlevel_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3ed00; +} + +static void +Opcode_wsr_icountlevel_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13ed00; +} + +static void +Opcode_xsr_icountlevel_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61ed00; +} + +static void +Opcode_rsr_ddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x36800; +} + +static void +Opcode_wsr_ddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x136800; +} + +static void +Opcode_xsr_ddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x616800; +} + +static void +Opcode_rfdo_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf1e000; +} + +static void +Opcode_rfdd_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf1e010; +} + +static void +Opcode_wsr_mmid_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x135900; +} + +static void +Opcode_andb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20000; +} + +static void +Opcode_andb_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x48001; +} + +static void +Opcode_andb_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x48001; +} + +static void +Opcode_andb_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x48000; +} + +static void +Opcode_andb_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe8002; +} + +static void +Opcode_andb_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x410000; +} + +static void +Opcode_andbc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x120000; +} + +static void +Opcode_orb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x220000; +} + +static void +Opcode_orb_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10002; +} + +static void +Opcode_orb_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10002; +} + +static void +Opcode_orb_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20001; +} + +static void +Opcode_orb_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1d8002; +} + +static void +Opcode_orb_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x498000; +} + +static void +Opcode_orbc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x320000; +} + +static void +Opcode_xorb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x420000; +} + +static void +Opcode_xorb_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x58002; +} + +static void +Opcode_xorb_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64002; +} + +static void +Opcode_xorb_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x48001; +} + +static void +Opcode_xorb_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x240002; +} + +static void +Opcode_xorb_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x51c000; +} + +static void +Opcode_any4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8000; +} + +static void +Opcode_any4_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35400; +} + +static void +Opcode_any4_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35400; +} + +static void +Opcode_any4_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x58421; +} + +static void +Opcode_any4_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x481421; +} + +static void +Opcode_any4_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2cec21; +} + +static void +Opcode_all4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9000; +} + +static void +Opcode_any8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa000; +} + +static void +Opcode_any8_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d420; +} + +static void +Opcode_any8_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d420; +} + +static void +Opcode_any8_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x58019; +} + +static void +Opcode_any8_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x481419; +} + +static void +Opcode_any8_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2cec31; +} + +static void +Opcode_all8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb000; +} + +static void +Opcode_bf_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x76; +} + +static void +Opcode_bt_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1076; +} + +static void +Opcode_movf_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc30000; +} + +static void +Opcode_movt_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd30000; +} + +static void +Opcode_movt_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4002; +} + +static void +Opcode_movt_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4002; +} + +static void +Opcode_movt_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8001; +} + +static void +Opcode_movt_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1cc002; +} + +static void +Opcode_movt_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x47c000; +} + +static void +Opcode_rsr_br_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30400; +} + +static void +Opcode_wsr_br_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130400; +} + +static void +Opcode_xsr_br_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610400; +} + +static void +Opcode_rsr_ccount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3ea00; +} + +static void +Opcode_wsr_ccount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13ea00; +} + +static void +Opcode_xsr_ccount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61ea00; +} + +static void +Opcode_rsr_ccompare0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f000; +} + +static void +Opcode_wsr_ccompare0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13f000; +} + +static void +Opcode_xsr_ccompare0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61f000; +} + +static void +Opcode_rsr_ccompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f100; +} + +static void +Opcode_wsr_ccompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13f100; +} + +static void +Opcode_xsr_ccompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61f100; +} + +static void +Opcode_ipf_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70c2; +} + +static void +Opcode_ihi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70e2; +} + +static void +Opcode_ipfl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70d2; +} + +static void +Opcode_ihu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x270d2; +} + +static void +Opcode_iiu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x370d2; +} + +static void +Opcode_iii_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70f2; +} + +static void +Opcode_lict_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf10000; +} + +static void +Opcode_licw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf12000; +} + +static void +Opcode_sict_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf11000; +} + +static void +Opcode_sicw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf13000; +} + +static void +Opcode_dhwb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7042; +} + +static void +Opcode_dhwbi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7052; +} + +static void +Opcode_diwb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x47082; +} + +static void +Opcode_diwbi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x57082; +} + +static void +Opcode_dhi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7062; +} + +static void +Opcode_dii_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7072; +} + +static void +Opcode_dpfr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7002; +} + +static void +Opcode_dpfw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7012; +} + +static void +Opcode_dpfro_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7022; +} + +static void +Opcode_dpfwo_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7032; +} + +static void +Opcode_dpfl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7082; +} + +static void +Opcode_dhu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x27082; +} + +static void +Opcode_diu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x37082; +} + +static void +Opcode_sdct_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf19000; +} + +static void +Opcode_ldct_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf18000; +} + +static void +Opcode_idtlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50c000; +} + +static void +Opcode_pdtlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50d000; +} + +static void +Opcode_rdtlb0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50b000; +} + +static void +Opcode_rdtlb1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50f000; +} + +static void +Opcode_wdtlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50e000; +} + +static void +Opcode_iitlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x504000; +} + +static void +Opcode_pitlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x505000; +} + +static void +Opcode_ritlb0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x503000; +} + +static void +Opcode_ritlb1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x507000; +} + +static void +Opcode_witlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x506000; +} + +static void +Opcode_rsr_cpenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e000; +} + +static void +Opcode_wsr_cpenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e000; +} + +static void +Opcode_xsr_cpenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e000; +} + +static void +Opcode_clamps_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x330000; +} + +static void +Opcode_clamps_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50001; +} + +static void +Opcode_clamps_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50001; +} + +static void +Opcode_clamps_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50000; +} + +static void +Opcode_clamps_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf0002; +} + +static void +Opcode_clamps_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x440000; +} + +static void +Opcode_min_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x430000; +} + +static void +Opcode_min_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70001; +} + +static void +Opcode_min_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70001; +} + +static void +Opcode_min_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6c000; +} + +static void +Opcode_min_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfc002; +} + +static void +Opcode_min_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x460000; +} + +static void +Opcode_max_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x530000; +} + +static void +Opcode_max_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64001; +} + +static void +Opcode_max_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64001; +} + +static void +Opcode_max_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x68000; +} + +static void +Opcode_max_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf4002; +} + +static void +Opcode_max_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x448000; +} + +static void +Opcode_minu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x630000; +} + +static void +Opcode_minu_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6c001; +} + +static void +Opcode_minu_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6c001; +} + +static void +Opcode_minu_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x74000; +} + +static void +Opcode_minu_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1c0002; +} + +static void +Opcode_minu_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x44c000; +} + +static void +Opcode_maxu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x730000; +} + +static void +Opcode_maxu_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x68001; +} + +static void +Opcode_maxu_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x68001; +} + +static void +Opcode_maxu_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70000; +} + +static void +Opcode_maxu_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf8002; +} + +static void +Opcode_maxu_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x450000; +} + +static void +Opcode_nsa_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40e000; +} + +static void +Opcode_nsa_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x15400; +} + +static void +Opcode_nsa_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x15400; +} + +static void +Opcode_nsa_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x53801; +} + +static void +Opcode_nsa_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4c1401; +} + +static void +Opcode_nsa_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2ce801; +} + +static void +Opcode_nsau_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40f000; +} + +static void +Opcode_nsau_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x25400; +} + +static void +Opcode_nsau_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x25400; +} + +static void +Opcode_nsau_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x53c01; +} + +static void +Opcode_nsau_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4c5401; +} + +static void +Opcode_nsau_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d6801; +} + +static void +Opcode_sext_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x230000; +} + +static void +Opcode_sext_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34002; +} + +static void +Opcode_sext_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34002; +} + +static void +Opcode_sext_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x24001; +} + +static void +Opcode_sext_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1dc002; +} + +static void +Opcode_sext_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4d0000; +} + +static void +Opcode_l32ai_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb002; +} + +static void +Opcode_s32ri_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf002; +} + +static void +Opcode_s32c1i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe002; +} + +static void +Opcode_rsr_scompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30c00; +} + +static void +Opcode_wsr_scompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130c00; +} + +static void +Opcode_xsr_scompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610c00; +} + +static void +Opcode_rsr_atomctl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x36300; +} + +static void +Opcode_wsr_atomctl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x136300; +} + +static void +Opcode_xsr_atomctl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x616300; +} + +static void +Opcode_rer_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x406000; +} + +static void +Opcode_wer_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x407000; +} + +static void +Opcode_rur_fcr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30e80; +} + +static void +Opcode_wur_fcr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf3e800; +} + +static void +Opcode_rur_fsr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30e90; +} + +static void +Opcode_wur_fsr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf3e900; +} + +static void +Opcode_add_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa0000; +} + +static void +Opcode_add_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f4001; +} + +static void +Opcode_sub_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1a0000; +} + +static void +Opcode_sub_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4f4000; +} + +static void +Opcode_mul_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2a0000; +} + +static void +Opcode_mul_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x490000; +} + +static void +Opcode_madd_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4a0000; +} + +static void +Opcode_madd_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x444000; +} + +static void +Opcode_msub_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5a0000; +} + +static void +Opcode_msub_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x488000; +} + +static void +Opcode_movf_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcb0000; +} + +static void +Opcode_movf_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x45c000; +} + +static void +Opcode_movt_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xdb0000; +} + +static void +Opcode_movt_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x484000; +} + +static void +Opcode_moveqz_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8b0000; +} + +static void +Opcode_moveqz_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x458000; +} + +static void +Opcode_movnez_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9b0000; +} + +static void +Opcode_movnez_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x478000; +} + +static void +Opcode_movltz_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xab0000; +} + +static void +Opcode_movltz_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x46c000; +} + +static void +Opcode_movgez_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xbb0000; +} + +static void +Opcode_movgez_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x468000; +} + +static void +Opcode_abs_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0010; +} + +static void +Opcode_abs_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x142; +} + +static void +Opcode_mov_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0000; +} + +static void +Opcode_mov_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4142; +} + +static void +Opcode_neg_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0060; +} + +static void +Opcode_neg_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8142; +} + +static void +Opcode_un_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1b0000; +} + +static void +Opcode_un_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50c000; +} + +static void +Opcode_oeq_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2b0000; +} + +static void +Opcode_oeq_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4a0000; +} + +static void +Opcode_ueq_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b0000; +} + +static void +Opcode_ueq_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x510000; +} + +static void +Opcode_olt_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4b0000; +} + +static void +Opcode_olt_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x48c000; +} + +static void +Opcode_ult_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5b0000; +} + +static void +Opcode_ult_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x580000; +} + +static void +Opcode_ole_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6b0000; +} + +static void +Opcode_ole_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4c0000; +} + +static void +Opcode_ule_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7b0000; +} + +static void +Opcode_ule_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x540000; +} + +static void +Opcode_float_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xca0000; +} + +static void +Opcode_float_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x500000; +} + +static void +Opcode_ufloat_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xda0000; +} + +static void +Opcode_ufloat_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x520000; +} + +static void +Opcode_round_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8a0000; +} + +static void +Opcode_round_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x49c000; +} + +static void +Opcode_ceil_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xba0000; +} + +static void +Opcode_ceil_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x420000; +} + +static void +Opcode_floor_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xaa0000; +} + +static void +Opcode_floor_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x600000; +} + +static void +Opcode_trunc_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9a0000; +} + +static void +Opcode_trunc_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x508000; +} + +static void +Opcode_utrunc_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xea0000; +} + +static void +Opcode_utrunc_s_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x514000; +} + +static void +Opcode_rfr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0040; +} + +static void +Opcode_rfr_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20142; +} + +static void +Opcode_wfr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0050; +} + +static void +Opcode_lsi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_lsi_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x140001; +} + +static void +Opcode_lsiu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8003; +} + +static void +Opcode_lsiu_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x180001; +} + +static void +Opcode_lsx_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80000; +} + +static void +Opcode_lsxu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x180000; +} + +static void +Opcode_lsxu_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x430000; +} + +static void +Opcode_ssi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4003; +} + +static void +Opcode_ssi_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x240001; +} + +static void +Opcode_ssiu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc003; +} + +static void +Opcode_ssiu_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x280001; +} + +static void +Opcode_ssx_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x480000; +} + +static void +Opcode_ssx_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4d4000; +} + +static void +Opcode_ssxu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x580000; +} + +static void +Opcode_ssxu_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4d8000; +} + +static void +Opcode_get_argmax_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6b700; +} + +static void +Opcode_get_argmax_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3407c; +} + +static void +Opcode_get_argmax_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x181d4; +} + +static void +Opcode_get_argmax_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3401c; +} + +static void +Opcode_get_argmax_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8294; +} + +static void +Opcode_get_argmax_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xdd; +} + +static void +Opcode_get_argmax_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x840ec; +} + +static void +Opcode_get_hsar_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6ba00; +} + +static void +Opcode_get_hsar_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x340bc; +} + +static void +Opcode_get_hsar_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d434; +} + +static void +Opcode_get_hsar_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x281d4; +} + +static void +Opcode_get_hsar_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x802f; +} + +static void +Opcode_get_hsar_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34058; +} + +static void +Opcode_get_hsar_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d434; +} + +static void +Opcode_get_hsar_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8314; +} + +static void +Opcode_get_hsar_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x58415; +} + +static void +Opcode_get_hsar_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40d9; +} + +static void +Opcode_get_hsar_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc83b; +} + +static void +Opcode_get_hsar_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x880ec; +} + +static void +Opcode_get_hsar_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2dec05; +} + +static void +Opcode_get_hsar2sar_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6bc00; +} + +static void +Opcode_get_hsar2sar_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3413c; +} + +static void +Opcode_get_hsar2sar_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d438; +} + +static void +Opcode_get_hsar2sar_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x481d4; +} + +static void +Opcode_get_hsar2sar_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x842f; +} + +static void +Opcode_get_hsar2sar_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34098; +} + +static void +Opcode_get_hsar2sar_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d438; +} + +static void +Opcode_get_hsar2sar_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x18254; +} + +static void +Opcode_get_hsar2sar_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x58815; +} + +static void +Opcode_get_hsar2sar_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80d9; +} + +static void +Opcode_get_hsar2sar_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd03b; +} + +static void +Opcode_get_hsar2sar_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x900ec; +} + +static void +Opcode_get_hsar2sar_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2dec09; +} + +static void +Opcode_get_interp_ext_n_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb70b90; +} + +static void +Opcode_get_interp_ext_n_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6806c; +} + +static void +Opcode_get_interp_ext_n_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6806c; +} + +static void +Opcode_get_interp_ext_n_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64101; +} + +static void +Opcode_get_interp_ext_n_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3540ed; +} + +static void +Opcode_get_interp_ext_l_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb70b80; +} + +static void +Opcode_get_interp_ext_l_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6802c; +} + +static void +Opcode_get_interp_ext_l_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6802c; +} + +static void +Opcode_get_interp_ext_l_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64081; +} + +static void +Opcode_get_interp_ext_l_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35406d; +} + +static void +Opcode_get_llr_buf_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x462000; +} + +static void +Opcode_get_llr_buf_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d400; +} + +static void +Opcode_get_llr_buf_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d400; +} + +static void +Opcode_get_llr_buf_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x58021; +} + +static void +Opcode_get_llr_buf_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x14000; +} + +static void +Opcode_get_llr_buf_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2cec01; +} + +static void +Opcode_get_llr_pos_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb70ba0; +} + +static void +Opcode_get_llr_pos_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x680ac; +} + +static void +Opcode_get_llr_pos_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x680ac; +} + +static void +Opcode_get_llr_pos_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64201; +} + +static void +Opcode_get_llr_pos_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc06f; +} + +static void +Opcode_get_llr_pos_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35416d; +} + +static void +Opcode_get_max_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6bb00; +} + +static void +Opcode_get_max_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3423c; +} + +static void +Opcode_get_max_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x881d4; +} + +static void +Opcode_get_max_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34118; +} + +static void +Opcode_get_max_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x28254; +} + +static void +Opcode_get_max_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x100d9; +} + +static void +Opcode_get_max_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa00ec; +} + +static void +Opcode_get_nco_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6bd00; +} + +static void +Opcode_get_nco_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x340fc; +} + +static void +Opcode_get_nco_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x381d4; +} + +static void +Opcode_get_nco_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34218; +} + +static void +Opcode_get_nco_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x48254; +} + +static void +Opcode_get_nco_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x200d9; +} + +static void +Opcode_get_nco_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8c0ec; +} + +static void +Opcode_get_perm_reg_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6812c; +} + +static void +Opcode_get_perm_reg_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8037; +} + +static void +Opcode_get_perm_reg_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6812c; +} + +static void +Opcode_get_perm_reg_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64049; +} + +static void +Opcode_get_perm_reg_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc0ef; +} + +static void +Opcode_get_perm_reg_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35426d; +} + +static void +Opcode_get_phasor_n_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb70bc0; +} + +static void +Opcode_get_phasor_n_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6822c; +} + +static void +Opcode_get_phasor_n_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6822c; +} + +static void +Opcode_get_phasor_n_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64051; +} + +static void +Opcode_get_phasor_n_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3541ed; +} + +static void +Opcode_get_phasor_offset_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb70bb0; +} + +static void +Opcode_get_phasor_offset_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x680ec; +} + +static void +Opcode_get_phasor_offset_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x680ec; +} + +static void +Opcode_get_phasor_offset_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64061; +} + +static void +Opcode_get_phasor_offset_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3542ed; +} + +static void +Opcode_get_sar_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6be00; +} + +static void +Opcode_get_sar_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3417c; +} + +static void +Opcode_get_sar_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d43c; +} + +static void +Opcode_get_sar_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x581d4; +} + +static void +Opcode_get_sar_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x882f; +} + +static void +Opcode_get_sar_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3405c; +} + +static void +Opcode_get_sar_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d43c; +} + +static void +Opcode_get_sar_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x88254; +} + +static void +Opcode_get_sar_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x59015; +} + +static void +Opcode_get_sar_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40dd; +} + +static void +Opcode_get_sar_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe03b; +} + +static void +Opcode_get_sar_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x940ec; +} + +static void +Opcode_get_sar_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2dec11; +} + +static void +Opcode_get_scale_reg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb70bd0; +} + +static void +Opcode_get_scale_reg_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6816c; +} + +static void +Opcode_get_scale_reg_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6816c; +} + +static void +Opcode_get_scale_reg_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6404d; +} + +static void +Opcode_get_scale_reg_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc16f; +} + +static void +Opcode_get_scale_reg_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35436d; +} + +static void +Opcode_get_smod_buf_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6b200; +} + +static void +Opcode_get_smod_buf_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d428; +} + +static void +Opcode_get_smod_buf_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d428; +} + +static void +Opcode_get_smod_buf_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x58419; +} + +static void +Opcode_get_smod_buf_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc03b; +} + +static void +Opcode_get_smod_buf_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2cec39; +} + +static void +Opcode_get_smod_offset_table_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6bf00; +} + +static void +Opcode_get_smod_offset_table_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35410; +} + +static void +Opcode_get_smod_offset_table_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35410; +} + +static void +Opcode_get_smod_offset_table_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5a015; +} + +static void +Opcode_get_smod_offset_table_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc43f; +} + +static void +Opcode_get_smod_offset_table_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2dec21; +} + +static void +Opcode_get_smod_pos_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb70be0; +} + +static void +Opcode_get_smod_pos_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x681ac; +} + +static void +Opcode_get_smod_pos_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x681ac; +} + +static void +Opcode_get_smod_pos_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64055; +} + +static void +Opcode_get_smod_pos_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc26f; +} + +static void +Opcode_get_smod_pos_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3543ed; +} + +static void +Opcode_get_sov_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb70bf0; +} + +static void +Opcode_get_sov_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x681ec; +} + +static void +Opcode_get_sov_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x681ec; +} + +static void +Opcode_get_sov_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64059; +} + +static void +Opcode_get_sov_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35802d; +} + +static void +Opcode_get_wght_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd70b00; +} + +static void +Opcode_get_wght_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6826c; +} + +static void +Opcode_get_wght_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6826c; +} + +static void +Opcode_get_wght_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6405d; +} + +static void +Opcode_get_wght_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc1ef; +} + +static void +Opcode_get_wght_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35804d; +} + +static void +Opcode_set_argmax_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd70b30; +} + +static void +Opcode_set_argmax_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400d9; +} + +static void +Opcode_set_argmax_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8254; +} + +static void +Opcode_set_argmax_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400d9; +} + +static void +Opcode_set_argmax_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x85d4; +} + +static void +Opcode_set_argmax_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11d; +} + +static void +Opcode_set_argmax_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x810d0; +} + +static void +Opcode_set_ext_regs_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x370b00; +} + +static void +Opcode_set_ext_regs_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32400; +} + +static void +Opcode_set_ext_regs_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10c01; +} + +static void +Opcode_set_ext_regs_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2dc00; +} + +static void +Opcode_set_ext_regs_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x12001; +} + +static void +Opcode_set_ext_regs_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe002; +} + +static void +Opcode_set_ext_regs_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4e1401; +} + +static void +Opcode_set_hsar_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400dd; +} + +static void +Opcode_set_hsar_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8294; +} + +static void +Opcode_set_hsar_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400dd; +} + +static void +Opcode_set_hsar_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8dd4; +} + +static void +Opcode_set_hsar_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x159; +} + +static void +Opcode_set_hsar_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x820d0; +} + +static void +Opcode_set_llr_buf_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb70300; +} + +static void +Opcode_set_llr_buf_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6c202; +} + +static void +Opcode_set_llr_buf_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7c202; +} + +static void +Opcode_set_llr_buf_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70001; +} + +static void +Opcode_set_llr_buf_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc02f; +} + +static void +Opcode_set_llr_buf_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35402d; +} + +static void +Opcode_set_llr_pos_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1620d0; +} + +static void +Opcode_set_llr_pos_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d480; +} + +static void +Opcode_set_llr_pos_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d480; +} + +static void +Opcode_set_llr_pos_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5dc81; +} + +static void +Opcode_set_llr_pos_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10200; +} + +static void +Opcode_set_llr_pos_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2de941; +} + +static void +Opcode_set_max_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd70b50; +} + +static void +Opcode_set_max_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x404d9; +} + +static void +Opcode_set_max_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8314; +} + +static void +Opcode_set_max_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x404d9; +} + +static void +Opcode_set_max_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x95d4; +} + +static void +Opcode_set_max_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x199; +} + +static void +Opcode_set_max_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x810d4; +} + +static void +Opcode_set_nco_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd70b60; +} + +static void +Opcode_set_nco_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x408d9; +} + +static void +Opcode_set_nco_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8654; +} + +static void +Opcode_set_nco_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x408d9; +} + +static void +Opcode_set_nco_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa5d4; +} + +static void +Opcode_set_nco_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x51d; +} + +static void +Opcode_set_nco_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x810d8; +} + +static void +Opcode_set_perm_reg_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d500; +} + +static void +Opcode_set_perm_reg_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf403; +} + +static void +Opcode_set_perm_reg_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d500; +} + +static void +Opcode_set_perm_reg_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5dd01; +} + +static void +Opcode_set_perm_reg_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10040; +} + +static void +Opcode_set_perm_reg_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2de981; +} + +static void +Opcode_set_phasor_n_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1620e0; +} + +static void +Opcode_set_phasor_n_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d600; +} + +static void +Opcode_set_phasor_n_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d600; +} + +static void +Opcode_set_phasor_n_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5de01; +} + +static void +Opcode_set_phasor_n_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2de9c1; +} + +static void +Opcode_set_phasor_offset_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1630d0; +} + +static void +Opcode_set_phasor_offset_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d4c0; +} + +static void +Opcode_set_phasor_offset_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d4c0; +} + +static void +Opcode_set_phasor_offset_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5dcc1; +} + +static void +Opcode_set_phasor_offset_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2dea41; +} + +static void +Opcode_set_sar_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd70b70; +} + +static void +Opcode_set_sar_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x410d9; +} + +static void +Opcode_set_sar_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x683ac; +} + +static void +Opcode_set_sar_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8a54; +} + +static void +Opcode_set_sar_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8237; +} + +static void +Opcode_set_sar_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x410d9; +} + +static void +Opcode_set_sar_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x683ac; +} + +static void +Opcode_set_sar_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9dd4; +} + +static void +Opcode_set_sar_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64075; +} + +static void +Opcode_set_sar_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x91d; +} + +static void +Opcode_set_sar_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc0b7; +} + +static void +Opcode_set_sar_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x814d0; +} + +static void +Opcode_set_sar_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3581ad; +} + +static void +Opcode_set_scale_reg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1620f0; +} + +static void +Opcode_set_scale_reg_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d540; +} + +static void +Opcode_set_scale_reg_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d540; +} + +static void +Opcode_set_scale_reg_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5dd41; +} + +static void +Opcode_set_scale_reg_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10080; +} + +static void +Opcode_set_scale_reg_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2dea81; +} + +static void +Opcode_set_smod_buf_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x370e00; +} + +static void +Opcode_set_smod_buf_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5c008; +} + +static void +Opcode_set_smod_buf_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5c008; +} + +static void +Opcode_set_smod_buf_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64041; +} + +static void +Opcode_set_smod_buf_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc073; +} + +static void +Opcode_set_smod_buf_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x350039; +} + +static void +Opcode_set_smod_offset_table_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd70b90; +} + +static void +Opcode_set_smod_offset_table_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x683ec; +} + +static void +Opcode_set_smod_offset_table_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x683ec; +} + +static void +Opcode_set_smod_offset_table_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64079; +} + +static void +Opcode_set_smod_offset_table_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc137; +} + +static void +Opcode_set_smod_offset_table_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3582ad; +} + +static void +Opcode_set_smod_pos_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1630e0; +} + +static void +Opcode_set_smod_pos_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d580; +} + +static void +Opcode_set_smod_pos_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d580; +} + +static void +Opcode_set_smod_pos_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5dd81; +} + +static void +Opcode_set_smod_pos_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10440; +} + +static void +Opcode_set_smod_pos_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2deb01; +} + +static void +Opcode_set_sov_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1630f0; +} + +static void +Opcode_set_sov_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d5c0; +} + +static void +Opcode_set_sov_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d5c0; +} + +static void +Opcode_set_sov_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5ddc1; +} + +static void +Opcode_set_sov_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2deac1; +} + +static void +Opcode_set_wght_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16a010; +} + +static void +Opcode_set_wght_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d640; +} + +static void +Opcode_set_wght_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d640; +} + +static void +Opcode_set_wght_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5de41; +} + +static void +Opcode_set_wght_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10840; +} + +static void +Opcode_set_wght_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2deb41; +} + +static void +Opcode_lac2x32_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x60000; +} + +static void +Opcode_lac2x32_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_lac2x32_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_lac2x32_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x300001; +} + +static void +Opcode_lac2x64_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x82003; +} + +static void +Opcode_lac2x64_0_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c00; +} + +static void +Opcode_lac2x64_0_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c00; +} + +static void +Opcode_lac2x64_0_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c0c01; +} + +static void +Opcode_lac2x64_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32003; +} + +static void +Opcode_lac2x64_1_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6c00; +} + +static void +Opcode_lac2x64_1_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6c00; +} + +static void +Opcode_lac2x64_1_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c2801; +} + +static void +Opcode_lac2x64_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x132003; +} + +static void +Opcode_lac2x64_2_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1400; +} + +static void +Opcode_lac2x64_2_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1400; +} + +static void +Opcode_lac2x64_2_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c4c01; +} + +static void +Opcode_lac2x64_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x52003; +} + +static void +Opcode_lac2x64_3_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1800; +} + +static void +Opcode_lac2x64_3_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1800; +} + +static void +Opcode_lac2x64_3_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c2c01; +} + +static void +Opcode_lac32_r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61000; +} + +static void +Opcode_lac32_r_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400; +} + +static void +Opcode_lac32_r_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400; +} + +static void +Opcode_lac32_r_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c0001; +} + +static void +Opcode_lac_ih_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2003; +} + +static void +Opcode_lac_ih_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800; +} + +static void +Opcode_lac_ih_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800; +} + +static void +Opcode_lac_ih_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c0401; +} + +static void +Opcode_lac_il_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x12003; +} + +static void +Opcode_lac_il_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1000; +} + +static void +Opcode_lac_il_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1000; +} + +static void +Opcode_lac_il_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c0801; +} + +static void +Opcode_lac_rh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x22003; +} + +static void +Opcode_lac_rh_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc00; +} + +static void +Opcode_lac_rh_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc00; +} + +static void +Opcode_lac_rh_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c1001; +} + +static void +Opcode_lac_rl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x42003; +} + +static void +Opcode_lac_rl_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2800; +} + +static void +Opcode_lac_rl_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2800; +} + +static void +Opcode_lac_rl_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c2401; +} + +static void +Opcode_lcm_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70300; +} + +static void +Opcode_lcm_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40008; +} + +static void +Opcode_lcm_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4001; +} + +static void +Opcode_lcm_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40008; +} + +static void +Opcode_lcm_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x54000; +} + +static void +Opcode_lcm_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_lcm_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x340011; +} + +static void +Opcode_lcm_pinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70000; +} + +static void +Opcode_lcm_pinc_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40000; +} + +static void +Opcode_lcm_pinc_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40000; +} + +static void +Opcode_lcm_pinc_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_lcm_pinc_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x340001; +} + +static void +Opcode_lcm_pinc_x_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x680000; +} + +static void +Opcode_lcm_pinc_x_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x54001; +} + +static void +Opcode_lcm_pinc_x_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x54001; +} + +static void +Opcode_lcm_pinc_x_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x58000; +} + +static void +Opcode_lcm_pinc_x_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x414000; +} + +static void +Opcode_lcm_u_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70100; +} + +static void +Opcode_lcm_u_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40004; +} + +static void +Opcode_lcm_u_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10001; +} + +static void +Opcode_lcm_u_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40004; +} + +static void +Opcode_lcm_u_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8000; +} + +static void +Opcode_lcm_u_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10001; +} + +static void +Opcode_lcm_u_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x380001; +} + +static void +Opcode_lcm_x_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x880000; +} + +static void +Opcode_lcm_x_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x58001; +} + +static void +Opcode_lcm_x_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_lcm_x_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x58001; +} + +static void +Opcode_lcm_x_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4001; +} + +static void +Opcode_lcm_x_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5c000; +} + +static void +Opcode_lcm_x_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4002; +} + +static void +Opcode_lcm_x_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x418000; +} + +static void +Opcode_lcm_xu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa80000; +} + +static void +Opcode_lcm_xu_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5c001; +} + +static void +Opcode_lcm_xu_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4002; +} + +static void +Opcode_lcm_xu_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5c001; +} + +static void +Opcode_lcm_xu_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4002; +} + +static void +Opcode_lcm_xu_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64000; +} + +static void +Opcode_lcm_xu_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_lcm_xu_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x41c000; +} + +static void +Opcode_lp_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70200; +} + +static void +Opcode_lp_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x340005; +} + +static void +Opcode_lp_x_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc80000; +} + +static void +Opcode_lp_x_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x424000; +} + +static void +Opcode_lq_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70400; +} + +static void +Opcode_lq_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x340009; +} + +static void +Opcode_lq_x_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe80000; +} + +static void +Opcode_lq_x_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x428000; +} + +static void +Opcode_lut0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d0000; +} + +static void +Opcode_lut0_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x42c000; +} + +static void +Opcode_lut1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d0000; +} + +static void +Opcode_lut1_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x434000; +} + +static void +Opcode_lut2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4d0000; +} + +static void +Opcode_lut2_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x438000; +} + +static void +Opcode_lut3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6c0000; +} + +static void +Opcode_lut3_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x43c000; +} + +static void +Opcode_sac2x32_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc0000; +} + +static void +Opcode_sac2x32_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_sac2x32_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_sac2x32_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c0001; +} + +static void +Opcode_sac2x64_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf88000; +} + +static void +Opcode_sac2x64_0_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5c002; +} + +static void +Opcode_sac2x64_0_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x68002; +} + +static void +Opcode_sac2x64_0_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x52a000; +} + +static void +Opcode_sac2x64_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8d8000; +} + +static void +Opcode_sac2x64_1_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5e002; +} + +static void +Opcode_sac2x64_1_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70002; +} + +static void +Opcode_sac2x64_1_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x52c000; +} + +static void +Opcode_sac2x64_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9d8000; +} + +static void +Opcode_sac2x64_2_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64002; +} + +static void +Opcode_sac2x64_2_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a002; +} + +static void +Opcode_sac2x64_2_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x52e000; +} + +static void +Opcode_sac2x64_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xac8000; +} + +static void +Opcode_sac2x64_3_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x68002; +} + +static void +Opcode_sac2x64_3_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6c002; +} + +static void +Opcode_sac2x64_3_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x532000; +} + +static void +Opcode_sac32_r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd0000; +} + +static void +Opcode_sac32_r_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8001; +} + +static void +Opcode_sac32_r_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8001; +} + +static void +Opcode_sac32_r_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c8001; +} + +static void +Opcode_sac_ih_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6d0000; +} + +static void +Opcode_sac_ih_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40002; +} + +static void +Opcode_sac_ih_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40002; +} + +static void +Opcode_sac_ih_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4a8000; +} + +static void +Opcode_sac_il_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6d8000; +} + +static void +Opcode_sac_il_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x18002; +} + +static void +Opcode_sac_il_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x18002; +} + +static void +Opcode_sac_il_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4b0000; +} + +static void +Opcode_sac_rh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8d0000; +} + +static void +Opcode_sac_rh_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1a002; +} + +static void +Opcode_sac_rh_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1a002; +} + +static void +Opcode_sac_rh_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4aa000; +} + +static void +Opcode_sac_rl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xac0000; +} + +static void +Opcode_sac_rl_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x28002; +} + +static void +Opcode_sac_rl_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x28002; +} + +static void +Opcode_sac_rl_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4b2000; +} + +static void +Opcode_scm_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5d0000; +} + +static void +Opcode_scm_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc002; +} + +static void +Opcode_scm_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4003; +} + +static void +Opcode_scm_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc002; +} + +static void +Opcode_scm_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc001; +} + +static void +Opcode_scm_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc000; +} + +static void +Opcode_scm_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4b8000; +} + +static void +Opcode_scm_pinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c0000; +} + +static void +Opcode_scm_pinc_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10001; +} + +static void +Opcode_scm_pinc_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10001; +} + +static void +Opcode_scm_pinc_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10000; +} + +static void +Opcode_scm_pinc_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d0001; +} + +static void +Opcode_scm_pinc_x_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x780000; +} + +static void +Opcode_scm_pinc_x_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x14002; +} + +static void +Opcode_scm_pinc_x_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x14002; +} + +static void +Opcode_scm_pinc_x_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x14001; +} + +static void +Opcode_scm_pinc_x_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4bc000; +} + +static void +Opcode_scm_u_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4c0000; +} + +static void +Opcode_scm_u_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20001; +} + +static void +Opcode_scm_u_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10002; +} + +static void +Opcode_scm_u_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20001; +} + +static void +Opcode_scm_u_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20000; +} + +static void +Opcode_scm_u_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10002; +} + +static void +Opcode_scm_u_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e0001; +} + +static void +Opcode_scm_x_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x980000; +} + +static void +Opcode_scm_x_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30002; +} + +static void +Opcode_scm_x_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8000; +} + +static void +Opcode_scm_x_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30002; +} + +static void +Opcode_scm_x_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4003; +} + +static void +Opcode_scm_x_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x18001; +} + +static void +Opcode_scm_x_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8001; +} + +static void +Opcode_scm_x_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4c4000; +} + +static void +Opcode_scm_xu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb80000; +} + +static void +Opcode_scm_xu_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x24002; +} + +static void +Opcode_scm_xu_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc000; +} + +static void +Opcode_scm_xu_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x24002; +} + +static void +Opcode_scm_xu_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8000; +} + +static void +Opcode_scm_xu_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1c001; +} + +static void +Opcode_scm_xu_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc001; +} + +static void +Opcode_scm_xu_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4c8000; +} + +static void +Opcode_store_p_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7c0000; +} + +static void +Opcode_store_p_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x48002; +} + +static void +Opcode_store_p_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4dc000; +} + +static void +Opcode_store_q_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcc0000; +} + +static void +Opcode_store_q_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50002; +} + +static void +Opcode_store_q_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4e4000; +} + +static void +Opcode_ar2cm_dup_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a000; +} + +static void +Opcode_ar2cm_dup_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c080; +} + +static void +Opcode_ar2cm_dup_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5400; +} + +static void +Opcode_ar2cm_dup_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40001; +} + +static void +Opcode_ar2cm_dup_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf002; +} + +static void +Opcode_ar2cm_dup_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38100; +} + +static void +Opcode_ar2cm_dup_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5400; +} + +static void +Opcode_ar2cm_dup_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40001; +} + +static void +Opcode_ar2cm_dup_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x53001; +} + +static void +Opcode_ar2cm_dup_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4102; +} + +static void +Opcode_ar2cm_dup_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb003; +} + +static void +Opcode_ar2cm_dup_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1000c0; +} + +static void +Opcode_ar2cm_dup_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c6801; +} + +static void +Opcode_ar2cm_ln_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64000; +} + +static void +Opcode_ar2cm_ln_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2e000; +} + +static void +Opcode_ar2cm_ln_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3000; +} + +static void +Opcode_ar2cm_ln_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10002; +} + +static void +Opcode_ar2cm_ln_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe002; +} + +static void +Opcode_ar2cm_ln_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c000; +} + +static void +Opcode_ar2cm_ln_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3000; +} + +static void +Opcode_ar2cm_ln_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10002; +} + +static void +Opcode_ar2cm_ln_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4c001; +} + +static void +Opcode_ar2cm_ln_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4002; +} + +static void +Opcode_ar2cm_ln_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa003; +} + +static void +Opcode_ar2cm_ln_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc01001; +} + +static void +Opcode_ar2cm_ln_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c3001; +} + +static void +Opcode_ar2cm_ln_i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6c000; +} + +static void +Opcode_ar2cm_ln_i_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7000; +} + +static void +Opcode_ar2cm_ln_i_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7000; +} + +static void +Opcode_ar2cm_ln_i_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4d001; +} + +static void +Opcode_ar2cm_ln_i_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c7001; +} + +static void +Opcode_ar2cm_ln_r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x164000; +} + +static void +Opcode_ar2cm_ln_r_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb000; +} + +static void +Opcode_ar2cm_ln_r_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb000; +} + +static void +Opcode_ar2cm_ln_r_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4e001; +} + +static void +Opcode_ar2cm_ln_r_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2cb001; +} + +static void +Opcode_ar2pq_ln_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30000; +} + +static void +Opcode_ar2pq_ln_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_ar2pq_ln_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_ar2sar_dup_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32e00; +} + +static void +Opcode_ar2sar_dup_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x12401; +} + +static void +Opcode_ar2sar_dup_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2ed00; +} + +static void +Opcode_ar2sar_dup_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11c01; +} + +static void +Opcode_ar2sar_dup_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4942; +} + +static void +Opcode_ar2sar_dup_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd00c0; +} + +static void +Opcode_clrac_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16a080; +} + +static void +Opcode_clrac_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d780; +} + +static void +Opcode_clrac_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf803; +} + +static void +Opcode_clrac_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d780; +} + +static void +Opcode_clrac_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2f6801; +} + +static void +Opcode_clrcm_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6b600; +} + +static void +Opcode_clrcm_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3403c; +} + +static void +Opcode_clrcm_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d430; +} + +static void +Opcode_clrcm_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x81d4; +} + +static void +Opcode_clrcm_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8033; +} + +static void +Opcode_clrcm_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34018; +} + +static void +Opcode_clrcm_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d430; +} + +static void +Opcode_clrcm_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd; +} + +static void +Opcode_clrcm_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2b00; +} + +static void +Opcode_clrcm_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8254; +} + +static void +Opcode_clrcm_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x58015; +} + +static void +Opcode_clrcm_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd9; +} + +static void +Opcode_clrcm_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc43b; +} + +static void +Opcode_clrcm_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800ec; +} + +static void +Opcode_clrcm_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2dec01; +} + +static void +Opcode_cm2ar_ln_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xbd0000; +} + +static void +Opcode_cm2ar_ln_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34000; +} + +static void +Opcode_cm2ar_ln_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40010; +} + +static void +Opcode_cm2ar_ln_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc010; +} + +static void +Opcode_cm2ar_ln_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8003; +} + +static void +Opcode_cm2ar_ln_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34000; +} + +static void +Opcode_cm2ar_ln_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40010; +} + +static void +Opcode_cm2ar_ln_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc010; +} + +static void +Opcode_cm2ar_ln_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x54001; +} + +static void +Opcode_cm2ar_ln_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8002; +} + +static void +Opcode_cm2ar_ln_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc003; +} + +static void +Opcode_cm2ar_ln_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x140032; +} + +static void +Opcode_cm2ar_ln_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x344011; +} + +static void +Opcode_cm2ar_ln_i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xbd0400; +} + +static void +Opcode_cm2ar_ln_i_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40030; +} + +static void +Opcode_cm2ar_ln_i_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40030; +} + +static void +Opcode_cm2ar_ln_i_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x58001; +} + +static void +Opcode_cm2ar_ln_i_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x344031; +} + +static void +Opcode_cm2ar_ln_r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xbd0800; +} + +static void +Opcode_cm2ar_ln_r_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x44010; +} + +static void +Opcode_cm2ar_ln_r_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x44010; +} + +static void +Opcode_cm2ar_ln_r_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x54011; +} + +static void +Opcode_cm2ar_ln_r_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34c011; +} + +static void +Opcode_comb_ar_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8c0000; +} + +static void +Opcode_comb_ar_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x60001; +} + +static void +Opcode_comb_ar_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x60001; +} + +static void +Opcode_comb_ar_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x60000; +} + +static void +Opcode_comb_ar_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x480000; +} + +static void +Opcode_conj_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x170300; +} + +static void +Opcode_conj_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4001d; +} + +static void +Opcode_conj_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x44008; +} + +static void +Opcode_conj_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8054; +} + +static void +Opcode_conj_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8013; +} + +static void +Opcode_conj_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4001d; +} + +static void +Opcode_conj_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x44008; +} + +static void +Opcode_conj_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_conj_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x81; +} + +static void +Opcode_conj_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8054; +} + +static void +Opcode_conj_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x54025; +} + +static void +Opcode_conj_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1d; +} + +static void +Opcode_conj_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc013; +} + +static void +Opcode_conj_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800c4; +} + +static void +Opcode_conj_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34002d; +} + +static void +Opcode_mov2ac32_i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xdd0020; +} + +static void +Opcode_mov2ac32_i_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6c042; +} + +static void +Opcode_mov2ac32_i_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7c042; +} + +static void +Opcode_mov2ac32_i_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x100142; +} + +static void +Opcode_mov2ac32_r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xdd0040; +} + +static void +Opcode_mov2ac32_r_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6c082; +} + +static void +Opcode_mov2ac32_r_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7c082; +} + +static void +Opcode_mov2ac32_r_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x200142; +} + +static void +Opcode_mov2cm2pq_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x801; +} + +static void +Opcode_mov2cm2pq_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c0; +} + +static void +Opcode_mov2cm2pq_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c0; +} + +static void +Opcode_movac_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x970b80; +} + +static void +Opcode_movac_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a042; +} + +static void +Opcode_movac_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6e202; +} + +static void +Opcode_movac_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc142; +} + +static void +Opcode_movac_i_Slot_llr_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8000; +} + +static void +Opcode_movac_i2r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x978b80; +} + +static void +Opcode_movac_r_Slot_llr_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2020; +} + +static void +Opcode_movac_r2i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb70380; +} + +static void +Opcode_movar2_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c100; +} + +static void +Opcode_movar2_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80001; +} + +static void +Opcode_movar2_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38200; +} + +static void +Opcode_movar2_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80001; +} + +static void +Opcode_movar2_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc402; +} + +static void +Opcode_movar2_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc00c0; +} + +static void +Opcode_movcm_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x170b00; +} + +static void +Opcode_movcm_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40099; +} + +static void +Opcode_movcm_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4002c; +} + +static void +Opcode_movcm_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8114; +} + +static void +Opcode_movcm_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8023; +} + +static void +Opcode_movcm_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40099; +} + +static void +Opcode_movcm_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4002c; +} + +static void +Opcode_movcm_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9; +} + +static void +Opcode_movcm_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x101; +} + +static void +Opcode_movcm_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8114; +} + +static void +Opcode_movcm_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x54029; +} + +static void +Opcode_movcm_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x99; +} + +static void +Opcode_movcm_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc023; +} + +static void +Opcode_movcm_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800e0; +} + +static void +Opcode_movcm_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34400d; +} + +static void +Opcode_movcm2pq_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70600; +} + +static void +Opcode_movcm2pq_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc02; +} + +static void +Opcode_movcm2pq_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4181; +} + +static void +Opcode_movcm2pq_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_movcm2pq_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4181; +} + +static void +Opcode_movcm2pq_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x182; +} + +static void +Opcode_movcnd_0_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3001; +} + +static void +Opcode_movcnd_0_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4240; +} + +static void +Opcode_movcnd_0_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2801; +} + +static void +Opcode_movcnd_0_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4240; +} + +static void +Opcode_movcnd_0_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1c3; +} + +static void +Opcode_movcnd_0_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x281c01; +} + +static void +Opcode_movcnd_1_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c01; +} + +static void +Opcode_movcnd_1_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4280; +} + +static void +Opcode_movcnd_1_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3001; +} + +static void +Opcode_movcnd_1_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4280; +} + +static void +Opcode_movcnd_1_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x243; +} + +static void +Opcode_movcnd_1_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x301c01; +} + +static void +Opcode_movcnd_2_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3401; +} + +static void +Opcode_movcnd_2_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4300; +} + +static void +Opcode_movcnd_2_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c01; +} + +static void +Opcode_movcnd_2_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4300; +} + +static void +Opcode_movcnd_2_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x283; +} + +static void +Opcode_movcnd_2_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c1c01; +} + +static void +Opcode_movcnd_3_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3801; +} + +static void +Opcode_movcnd_3_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x42c0; +} + +static void +Opcode_movcnd_3_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3401; +} + +static void +Opcode_movcnd_3_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x42c0; +} + +static void +Opcode_movcnd_3_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x303; +} + +static void +Opcode_movcnd_3_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x341c01; +} + +static void +Opcode_movcnd_4_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c01; +} + +static void +Opcode_movcnd_4_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4340; +} + +static void +Opcode_movcnd_4_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3801; +} + +static void +Opcode_movcnd_4_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4340; +} + +static void +Opcode_movcnd_4_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c3; +} + +static void +Opcode_movcnd_4_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x381c01; +} + +static void +Opcode_movcnd_5_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_movcnd_5_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4380; +} + +static void +Opcode_movcnd_5_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c01; +} + +static void +Opcode_movcnd_5_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4380; +} + +static void +Opcode_movcnd_5_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x343; +} + +static void +Opcode_movcnd_5_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c1c01; +} + +static void +Opcode_movcnd_6_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x402; +} + +static void +Opcode_movcnd_6_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x43c0; +} + +static void +Opcode_movcnd_6_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_movcnd_6_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x43c0; +} + +static void +Opcode_movcnd_6_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x383; +} + +static void +Opcode_movcnd_6_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x401401; +} + +static void +Opcode_movcnd_7_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x802; +} + +static void +Opcode_movcnd_7_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4001; +} + +static void +Opcode_movcnd_7_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x402; +} + +static void +Opcode_movcnd_7_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4001; +} + +static void +Opcode_movcnd_7_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c3; +} + +static void +Opcode_movcnd_7_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x401801; +} + +static void +Opcode_movcnd8_0_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1001; +} + +static void +Opcode_movcnd8_0_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4040; +} + +static void +Opcode_movcnd8_0_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x801; +} + +static void +Opcode_movcnd8_0_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4040; +} + +static void +Opcode_movcnd8_0_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_movcnd8_0_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x81c01; +} + +static void +Opcode_movcnd8_1_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2001; +} + +static void +Opcode_movcnd8_1_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4080; +} + +static void +Opcode_movcnd8_1_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1001; +} + +static void +Opcode_movcnd8_1_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4080; +} + +static void +Opcode_movcnd8_1_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x43; +} + +static void +Opcode_movcnd8_1_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x101c01; +} + +static void +Opcode_movcnd8_2_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc01; +} + +static void +Opcode_movcnd8_2_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4100; +} + +static void +Opcode_movcnd8_2_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2001; +} + +static void +Opcode_movcnd8_2_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4100; +} + +static void +Opcode_movcnd8_2_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x83; +} + +static void +Opcode_movcnd8_2_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x201c01; +} + +static void +Opcode_movcnd8_3_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1401; +} + +static void +Opcode_movcnd8_3_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4200; +} + +static void +Opcode_movcnd8_3_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc01; +} + +static void +Opcode_movcnd8_3_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4200; +} + +static void +Opcode_movcnd8_3_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x103; +} + +static void +Opcode_movcnd8_3_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc1c01; +} + +static void +Opcode_movcnd8_4_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1801; +} + +static void +Opcode_movcnd8_4_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40c0; +} + +static void +Opcode_movcnd8_4_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1401; +} + +static void +Opcode_movcnd8_4_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40c0; +} + +static void +Opcode_movcnd8_4_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x203; +} + +static void +Opcode_movcnd8_4_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x141c01; +} + +static void +Opcode_movcnd8_5_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1c01; +} + +static void +Opcode_movcnd8_5_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4140; +} + +static void +Opcode_movcnd8_5_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1801; +} + +static void +Opcode_movcnd8_5_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4140; +} + +static void +Opcode_movcnd8_5_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc3; +} + +static void +Opcode_movcnd8_5_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x181c01; +} + +static void +Opcode_movcnd8_6_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2401; +} + +static void +Opcode_movcnd8_6_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4180; +} + +static void +Opcode_movcnd8_6_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1c01; +} + +static void +Opcode_movcnd8_6_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4180; +} + +static void +Opcode_movcnd8_6_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x143; +} + +static void +Opcode_movcnd8_6_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1c1c01; +} + +static void +Opcode_movcnd8_7_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2801; +} + +static void +Opcode_movcnd8_7_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x41c0; +} + +static void +Opcode_movcnd8_7_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2401; +} + +static void +Opcode_movcnd8_7_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x41c0; +} + +static void +Opcode_movcnd8_7_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x183; +} + +static void +Opcode_movcnd8_7_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x241c01; +} + +static void +Opcode_mov_i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x370300; +} + +static void +Opcode_mov_i_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4800c; +} + +static void +Opcode_mov_i_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8017; +} + +static void +Opcode_mov_i_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4800c; +} + +static void +Opcode_mov_i_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x54031; +} + +static void +Opcode_mov_i_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc017; +} + +static void +Opcode_mov_i_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34800d; +} + +static void +Opcode_movpq2pq_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2f400; +} + +static void +Opcode_movpq2pq_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10801; +} + +static void +Opcode_movpq2pq_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10801; +} + +static void +Opcode_mov_r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x570300; +} + +static void +Opcode_mov_r_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5000c; +} + +static void +Opcode_mov_r_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x801b; +} + +static void +Opcode_mov_r_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5000c; +} + +static void +Opcode_mov_r_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5402d; +} + +static void +Opcode_mov_r_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc01b; +} + +static void +Opcode_mov_r_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35000d; +} + +static void +Opcode_negcm_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x970300; +} + +static void +Opcode_negcm_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40219; +} + +static void +Opcode_negcm_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4802c; +} + +static void +Opcode_negcm_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80d4; +} + +static void +Opcode_negcm_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8027; +} + +static void +Opcode_negcm_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40219; +} + +static void +Opcode_negcm_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4802c; +} + +static void +Opcode_negcm_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x21; +} + +static void +Opcode_negcm_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x201; +} + +static void +Opcode_negcm_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80d4; +} + +static void +Opcode_negcm_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x54039; +} + +static void +Opcode_negcm_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x219; +} + +static void +Opcode_negcm_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc027; +} + +static void +Opcode_negcm_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800e4; +} + +static void +Opcode_negcm_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34402d; +} + +static void +Opcode_pop16llr_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16a180; +} + +static void +Opcode_pop16llr_1_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d7a0; +} + +static void +Opcode_pop16llr_1_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d7a0; +} + +static void +Opcode_pop16llr_1_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11040; +} + +static void +Opcode_pop16llr_1_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2e6c41; +} + +static void +Opcode_pq2cm_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x62000; +} + +static void +Opcode_pq2cm_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34028; +} + +static void +Opcode_pq2cm_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x88018; +} + +static void +Opcode_pq2cm_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38000; +} + +static void +Opcode_pq2cm_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x88018; +} + +static void +Opcode_pq2cm_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10002; +} + +static void +Opcode_pq2cm_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x440080; +} + +static void +Opcode_swapac_r_Slot_acc2_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x100; +} + +static void +Opcode_swapac_ri_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb70b00; +} + +static void +Opcode_swapac_ri_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a082; +} + +static void +Opcode_swapac_ri_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6e142; +} + +static void +Opcode_swapac_ri_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc162; +} + +static void +Opcode_swapb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xdd0010; +} + +static void +Opcode_swapb_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c0c0; +} + +static void +Opcode_swapb_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11801; +} + +static void +Opcode_swapb_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38140; +} + +static void +Opcode_swapb_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11401; +} + +static void +Opcode_swapb_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd402; +} + +static void +Opcode_swapb_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc80c0; +} + +static void +Opcode_add2ac_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc000; +} + +static void +Opcode_addac_Slot_llr_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000; +} + +static void +Opcode_cdot_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_cdotac_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_cdotacs_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_cmac_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_cmac_Slot_smod_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4001; +} + +static void +Opcode_cmacs_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2000; +} + +static void +Opcode_cmpy_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_cmpy_Slot_smod_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8001; +} + +static void +Opcode_cmpy2cm_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc001; +} + +static void +Opcode_cmpy2cm_Slot_smod_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_cmpy2pq_Slot_pq_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_cmpys_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2001; +} + +static void +Opcode_cmpyxp2pq_Slot_pq_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_comb32_Slot_llr_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_dot_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_dotac_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20000; +} + +static void +Opcode_dotacs_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20001; +} + +static void +Opcode_lin_int_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc002; +} + +static void +Opcode_llrpre1_Slot_acc2_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_llrpre2_Slot_llr_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2000; +} + +static void +Opcode_mac_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_mac_Slot_smod_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6001; +} + +static void +Opcode_mac8_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2002; +} + +static void +Opcode_macd8_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20002; +} + +static void +Opcode_macpqxp_0_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20003; +} + +static void +Opcode_macpqxp_1_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40000; +} + +static void +Opcode_macpqxp_2_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40001; +} + +static void +Opcode_macpqxp_3_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40002; +} + +static void +Opcode_macs_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_macxp2_0_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40003; +} + +static void +Opcode_macxp2_1_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x60000; +} + +static void +Opcode_macxp_0_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2003; +} + +static void +Opcode_macxp_1_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000; +} + +static void +Opcode_macxp_2_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6000; +} + +static void +Opcode_macxp_3_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4001; +} + +static void +Opcode_mov2ac_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc010; +} + +static void +Opcode_mpy_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6001; +} + +static void +Opcode_mpy_Slot_smod_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa001; +} + +static void +Opcode_mpy2cm_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc003; +} + +static void +Opcode_mpy2cm_Slot_smod_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000; +} + +static void +Opcode_mpy2pq_Slot_pq_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_mpy8_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4002; +} + +static void +Opcode_mpyadd8_2cm_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10000; +} + +static void +Opcode_mpyadd8_2cm_Slot_smod_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8000; +} + +static void +Opcode_mpyd8_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x60001; +} + +static void +Opcode_mpypqxp_0_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x60002; +} + +static void +Opcode_mpypqxp_1_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x60003; +} + +static void +Opcode_mpypqxp_2_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80000; +} + +static void +Opcode_mpypqxp_3_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80001; +} + +static void +Opcode_mpys_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6002; +} + +static void +Opcode_mpyxp2pq_Slot_pq_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x100; +} + +static void +Opcode_mpyxp2_0_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80002; +} + +static void +Opcode_mpyxp2_1_Slot_dot_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80003; +} + +static void +Opcode_mpyxp_0_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4003; +} + +static void +Opcode_mpyxp_1_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6003; +} + +static void +Opcode_mpyxp_2_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8000; +} + +static void +Opcode_mpyxp_3_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa000; +} + +static void +Opcode_normacd_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8001; +} + +static void +Opcode_normacd_Slot_smod_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc001; +} + +static void +Opcode_normacpq_i_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe000; +} + +static void +Opcode_normacpq_r_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe040; +} + +static void +Opcode_normd_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa001; +} + +static void +Opcode_normd_Slot_smod_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe001; +} + +static void +Opcode_normpypq_i_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe080; +} + +static void +Opcode_normpypq_r_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe100; +} + +static void +Opcode_rcmac_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8002; +} + +static void +Opcode_rcmpy_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa002; +} + +static void +Opcode_rcmpy2cm_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10001; +} + +static void +Opcode_rcmpy2cm_Slot_smod_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc000; +} + +static void +Opcode_rfir_Slot_acc2_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_rfira_Slot_acc2_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_rfird_Slot_acc2_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_rfirda_Slot_acc2_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80; +} + +static void +Opcode_rmac_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8003; +} + +static void +Opcode_rmpy_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa003; +} + +static void +Opcode_rmpy2cm_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10002; +} + +static void +Opcode_rmpy2cm_Slot_smod_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_smod_align_Slot_smod_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_smod_scr_Slot_smod_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_sub2ac_Slot_gp_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc020; +} + +static void +Opcode_wght32_Slot_llr_slot1_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_clrtiep_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6b000; +} + +static void +Opcode_clrtiep_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32c00; +} + +static void +Opcode_clrtiep_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x12801; +} + +static void +Opcode_clrtiep_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2f000; +} + +static void +Opcode_clrtiep_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x12801; +} + +static void +Opcode_clrtiep_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4202; +} + +static void +Opcode_clrtiep_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x280; +} + +static void +Opcode_ext_2fifo_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x470600; +} + +static void +Opcode_ext_2fifo_0_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x54008; +} + +static void +Opcode_ext_2fifo_0_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfc02; +} + +static void +Opcode_ext_2fifo_0_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x54008; +} + +static void +Opcode_ext_2fifo_0_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x342019; +} + +static void +Opcode_ext_2fifo_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x870600; +} + +static void +Opcode_ext_2fifo_1_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64008; +} + +static void +Opcode_ext_2fifo_1_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc003; +} + +static void +Opcode_ext_2fifo_1_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64008; +} + +static void +Opcode_ext_2fifo_1_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x348019; +} + +static void +Opcode_ext_2fifo_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x170e00; +} + +static void +Opcode_ext_2fifo_2_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x46028; +} + +static void +Opcode_ext_2fifo_2_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc403; +} + +static void +Opcode_ext_2fifo_2_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x46028; +} + +static void +Opcode_ext_2fifo_2_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x350019; +} + +static void +Opcode_ext_2fifo_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x178600; +} + +static void +Opcode_ext_2fifo_3_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4c028; +} + +static void +Opcode_ext_2fifo_3_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc803; +} + +static void +Opcode_ext_2fifo_3_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4c028; +} + +static void +Opcode_ext_2fifo_3_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x360019; +} + +static void +Opcode_ext_r2fifo_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x178e00; +} + +static void +Opcode_ext_r2fifo_0_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4e008; +} + +static void +Opcode_ext_r2fifo_0_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd003; +} + +static void +Opcode_ext_r2fifo_0_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4e008; +} + +static void +Opcode_ext_r2fifo_0_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x342039; +} + +static void +Opcode_ext_r2fifo_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x270e00; +} + +static void +Opcode_ext_r2fifo_1_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4e028; +} + +static void +Opcode_ext_r2fifo_1_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe003; +} + +static void +Opcode_ext_r2fifo_1_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4e028; +} + +static void +Opcode_ext_r2fifo_1_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x348039; +} + +static void +Opcode_ext_r2fifo_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x278600; +} + +static void +Opcode_ext_r2fifo_2_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x54028; +} + +static void +Opcode_ext_r2fifo_2_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcc03; +} + +static void +Opcode_ext_r2fifo_2_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x54028; +} + +static void +Opcode_ext_r2fifo_2_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34a019; +} + +static void +Opcode_ext_r2fifo_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x370600; +} + +static void +Opcode_ext_r2fifo_3_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x56008; +} + +static void +Opcode_ext_r2fifo_3_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd403; +} + +static void +Opcode_ext_r2fifo_3_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x56008; +} + +static void +Opcode_ext_r2fifo_3_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34a039; +} + +static void +Opcode_lut_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40180; +} + +static void +Opcode_lut_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1c0; +} + +static void +Opcode_lut_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40180; +} + +static void +Opcode_lut_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1c0; +} + +static void +Opcode_lut_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x240; +} + +static void +Opcode_lut_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd80040; +} + +static void +Opcode_lut_ar_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10000; +} + +static void +Opcode_lut_ar_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_lut_ar_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10000; +} + +static void +Opcode_lut_ar_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_lut_ar_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_lut_ar_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xec002; +} + +static void +Opcode_lut_iext_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x401c0; +} + +static void +Opcode_lut_iext_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x240; +} + +static void +Opcode_lut_iext_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x401c0; +} + +static void +Opcode_lut_iext_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4002; +} + +static void +Opcode_lut_iext_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x240; +} + +static void +Opcode_lut_iext_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x280; +} + +static void +Opcode_lut_iext_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xdc0040; +} + +static void +Opcode_lut_phasor_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40059; +} + +static void +Opcode_lut_phasor_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8094; +} + +static void +Opcode_lut_phasor_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40059; +} + +static void +Opcode_lut_phasor_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5; +} + +static void +Opcode_lut_phasor_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8094; +} + +static void +Opcode_lut_phasor_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x59; +} + +static void +Opcode_lut_phasor_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800c8; +} + +static void +Opcode_lut_rext_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40240; +} + +static void +Opcode_lut_rext_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x280; +} + +static void +Opcode_lut_rext_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40240; +} + +static void +Opcode_lut_rext_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x280; +} + +static void +Opcode_lut_rext_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x300; +} + +static void +Opcode_lut_rext_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe40040; +} + +static void +Opcode_lut_write_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40431; +} + +static void +Opcode_lut_write_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_lut_write_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x41031; +} + +static void +Opcode_lut_write_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_lut_write_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x131; +} + +static void +Opcode_lut_write_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800d0; +} + +static void +Opcode_moveq128_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16b010; +} + +static void +Opcode_moveq128_0_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32f40; +} + +static void +Opcode_moveq128_0_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd81d4; +} + +static void +Opcode_moveq128_0_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2ed80; +} + +static void +Opcode_moveq128_0_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xadd4; +} + +static void +Opcode_moveq128_0_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x140dd; +} + +static void +Opcode_moveq128_0_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x818d0; +} + +static void +Opcode_moveq128_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16b110; +} + +static void +Opcode_moveq128_1_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32f80; +} + +static void +Opcode_moveq128_1_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe81d4; +} + +static void +Opcode_moveq128_1_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2ed84; +} + +static void +Opcode_moveq128_1_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb5d4; +} + +static void +Opcode_moveq128_1_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x144dd; +} + +static void +Opcode_moveq128_1_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x810dc; +} + +static void +Opcode_moveq128_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16b210; +} + +static void +Opcode_moveq128_2_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32f44; +} + +static void +Opcode_moveq128_2_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd85d4; +} + +static void +Opcode_moveq128_2_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2ed88; +} + +static void +Opcode_moveq128_2_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1add4; +} + +static void +Opcode_moveq128_2_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x148dd; +} + +static void +Opcode_moveq128_2_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x850dc; +} + +static void +Opcode_moveq128_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16b410; +} + +static void +Opcode_moveq128_3_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32f48; +} + +static void +Opcode_moveq128_3_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd89d4; +} + +static void +Opcode_moveq128_3_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2ed90; +} + +static void +Opcode_moveq128_3_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2add4; +} + +static void +Opcode_moveq128_3_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x150dd; +} + +static void +Opcode_moveq128_3_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x890dc; +} + +static void +Opcode_moveq128_4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16b810; +} + +static void +Opcode_moveq128_4_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32f50; +} + +static void +Opcode_moveq128_4_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd91d4; +} + +static void +Opcode_moveq128_4_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2eda0; +} + +static void +Opcode_moveq128_4_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4add4; +} + +static void +Opcode_moveq128_4_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x160dd; +} + +static void +Opcode_moveq128_4_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x910dc; +} + +static void +Opcode_moveq128_5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16b310; +} + +static void +Opcode_moveq128_5_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32f60; +} + +static void +Opcode_moveq128_5_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xda1d4; +} + +static void +Opcode_moveq128_5_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2edc0; +} + +static void +Opcode_moveq128_5_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8add4; +} + +static void +Opcode_moveq128_5_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x14cdd; +} + +static void +Opcode_moveq128_5_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa10dc; +} + +static void +Opcode_moveq32_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16b510; +} + +static void +Opcode_moveq32_0_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32f4c; +} + +static void +Opcode_moveq32_0_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd8dd4; +} + +static void +Opcode_moveq32_0_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2ed8c; +} + +static void +Opcode_moveq32_0_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3add4; +} + +static void +Opcode_moveq32_0_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x154dd; +} + +static void +Opcode_moveq32_0_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8d0dc; +} + +static void +Opcode_moveq32_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16b610; +} + +static void +Opcode_moveq32_1_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32f54; +} + +static void +Opcode_moveq32_1_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd95d4; +} + +static void +Opcode_moveq32_1_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2ed94; +} + +static void +Opcode_moveq32_1_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5add4; +} + +static void +Opcode_moveq32_1_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x158dd; +} + +static void +Opcode_moveq32_1_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x950dc; +} + +static void +Opcode_moveq32_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16b710; +} + +static void +Opcode_moveq32_2_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32f58; +} + +static void +Opcode_moveq32_2_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd99d4; +} + +static void +Opcode_moveq32_2_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2ed98; +} + +static void +Opcode_moveq32_2_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6add4; +} + +static void +Opcode_moveq32_2_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x15cdd; +} + +static void +Opcode_moveq32_2_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x990dc; +} + +static void +Opcode_moveq32_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16b910; +} + +static void +Opcode_moveq32_3_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32f5c; +} + +static void +Opcode_moveq32_3_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd9dd4; +} + +static void +Opcode_moveq32_3_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2ed9c; +} + +static void +Opcode_moveq32_3_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7add4; +} + +static void +Opcode_moveq32_3_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x164dd; +} + +static void +Opcode_moveq32_3_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9d0dc; +} + +static void +Opcode_nco_update_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40119; +} + +static void +Opcode_nco_update_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8214; +} + +static void +Opcode_nco_update_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40119; +} + +static void +Opcode_nco_update_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11; +} + +static void +Opcode_nco_update_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8214; +} + +static void +Opcode_nco_update_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x119; +} + +static void +Opcode_nco_update_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800cc; +} + +static void +Opcode_pop128_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x263000; +} + +static void +Opcode_pop128_0_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x341bc; +} + +static void +Opcode_pop128_0_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35420; +} + +static void +Opcode_pop128_0_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x681d4; +} + +static void +Opcode_pop128_0_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x902f; +} + +static void +Opcode_pop128_0_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3409c; +} + +static void +Opcode_pop128_0_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35420; +} + +static void +Opcode_pop128_0_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40d; +} + +static void +Opcode_pop128_0_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2b40; +} + +static void +Opcode_pop128_0_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38254; +} + +static void +Opcode_pop128_0_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x58c15; +} + +static void +Opcode_pop128_0_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80dd; +} + +static void +Opcode_pop128_0_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc83f; +} + +static void +Opcode_pop128_0_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x980ec; +} + +static void +Opcode_pop128_0_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2dec0d; +} + +static void +Opcode_pop128_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x26a000; +} + +static void +Opcode_pop128_1_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x341fc; +} + +static void +Opcode_pop128_1_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35414; +} + +static void +Opcode_pop128_1_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x781d4; +} + +static void +Opcode_pop128_1_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa02f; +} + +static void +Opcode_pop128_1_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x340d8; +} + +static void +Opcode_pop128_1_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35414; +} + +static void +Opcode_pop128_1_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80d; +} + +static void +Opcode_pop128_1_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2b80; +} + +static void +Opcode_pop128_1_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x58254; +} + +static void +Opcode_pop128_1_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x59415; +} + +static void +Opcode_pop128_1_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc0d9; +} + +static void +Opcode_pop128_1_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcc3b; +} + +static void +Opcode_pop128_1_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9c0ec; +} + +static void +Opcode_pop128_1_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2dec15; +} + +static void +Opcode_pop128_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x362000; +} + +static void +Opcode_pop128_2_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3427c; +} + +static void +Opcode_pop128_2_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35418; +} + +static void +Opcode_pop128_2_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x981d4; +} + +static void +Opcode_pop128_2_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8c2f; +} + +static void +Opcode_pop128_2_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x340dc; +} + +static void +Opcode_pop128_2_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35418; +} + +static void +Opcode_pop128_2_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x100d; +} + +static void +Opcode_pop128_2_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2bc0; +} + +static void +Opcode_pop128_2_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x68254; +} + +static void +Opcode_pop128_2_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x59815; +} + +static void +Opcode_pop128_2_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc0dd; +} + +static void +Opcode_pop128_2_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcc3f; +} + +static void +Opcode_pop128_2_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa40ec; +} + +static void +Opcode_pop128_2_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2dec19; +} + +static void +Opcode_pop128_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x263100; +} + +static void +Opcode_pop128_3_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x342bc; +} + +static void +Opcode_pop128_3_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3541c; +} + +static void +Opcode_pop128_3_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa81d4; +} + +static void +Opcode_pop128_3_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x942f; +} + +static void +Opcode_pop128_3_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3411c; +} + +static void +Opcode_pop128_3_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3541c; +} + +static void +Opcode_pop128_3_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x200d; +} + +static void +Opcode_pop128_3_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c80; +} + +static void +Opcode_pop128_3_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x78254; +} + +static void +Opcode_pop128_3_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x59c15; +} + +static void +Opcode_pop128_3_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x100dd; +} + +static void +Opcode_pop128_3_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd03f; +} + +static void +Opcode_pop128_3_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa80ec; +} + +static void +Opcode_pop128_3_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2dec1d; +} + +static void +Opcode_pop128_4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x263200; +} + +static void +Opcode_pop128_4_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3433c; +} + +static void +Opcode_pop128_4_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35424; +} + +static void +Opcode_pop128_4_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc81d4; +} + +static void +Opcode_pop128_4_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x982f; +} + +static void +Opcode_pop128_4_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34158; +} + +static void +Opcode_pop128_4_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35424; +} + +static void +Opcode_pop128_4_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc0d; +} + +static void +Opcode_pop128_4_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d00; +} + +static void +Opcode_pop128_4_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x98254; +} + +static void +Opcode_pop128_4_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5a415; +} + +static void +Opcode_pop128_4_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x140d9; +} + +static void +Opcode_pop128_4_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd43b; +} + +static void +Opcode_pop128_4_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb00ec; +} + +static void +Opcode_pop128_4_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2dec25; +} + +static void +Opcode_pop128_5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x263400; +} + +static void +Opcode_pop128_5_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x342fc; +} + +static void +Opcode_pop128_5_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35428; +} + +static void +Opcode_pop128_5_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb81d4; +} + +static void +Opcode_pop128_5_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9c2f; +} + +static void +Opcode_pop128_5_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34198; +} + +static void +Opcode_pop128_5_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35428; +} + +static void +Opcode_pop128_5_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x140d; +} + +static void +Opcode_pop128_5_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2e00; +} + +static void +Opcode_pop128_5_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa8254; +} + +static void +Opcode_pop128_5_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5a815; +} + +static void +Opcode_pop128_5_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x180d9; +} + +static void +Opcode_pop128_5_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd83b; +} + +static void +Opcode_pop128_5_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xac0ec; +} + +static void +Opcode_pop128_5_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2dec29; +} + +static void +Opcode_pop128_2cmpq_0_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38000; +} + +static void +Opcode_pop128_2cmpq_0_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8018; +} + +static void +Opcode_pop128_2cmpq_0_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8018; +} + +static void +Opcode_pop128_2cmpq_1_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34010; +} + +static void +Opcode_pop128_2cmpq_1_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x18018; +} + +static void +Opcode_pop128_2cmpq_1_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x18018; +} + +static void +Opcode_pop128_2cmpq_2_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34020; +} + +static void +Opcode_pop128_2cmpq_2_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x28018; +} + +static void +Opcode_pop128_2cmpq_2_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x28018; +} + +static void +Opcode_pop128_2cmpq_3_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34018; +} + +static void +Opcode_pop128_2cmpq_3_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x48018; +} + +static void +Opcode_pop128_2cmpq_3_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x48018; +} + +static void +Opcode_pop128_2m_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcd0000; +} + +static void +Opcode_pop128_2m_0_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x66002; +} + +static void +Opcode_pop128_2m_0_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x72002; +} + +static void +Opcode_pop128_2m_0_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5c001; +} + +static void +Opcode_pop128_2m_0_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x300401; +} + +static void +Opcode_pop128_2m_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xdc0000; +} + +static void +Opcode_pop128_2m_1_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x66402; +} + +static void +Opcode_pop128_2m_1_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x74002; +} + +static void +Opcode_pop128_2m_1_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5c401; +} + +static void +Opcode_pop128_2m_1_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x300801; +} + +static void +Opcode_pop128_2m_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xec0000; +} + +static void +Opcode_pop128_2m_2_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x66802; +} + +static void +Opcode_pop128_2m_2_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x78002; +} + +static void +Opcode_pop128_2m_2_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5c801; +} + +static void +Opcode_pop128_2m_2_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x302401; +} + +static void +Opcode_pop128_2m_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcd1000; +} + +static void +Opcode_pop128_2m_3_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x66c02; +} + +static void +Opcode_pop128_2m_3_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x72402; +} + +static void +Opcode_pop128_2m_3_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5e001; +} + +static void +Opcode_pop128_2m_3_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x304401; +} + +static void +Opcode_pop128_2pq_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x162080; +} + +static void +Opcode_pop128_2pq_0_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x33400; +} + +static void +Opcode_pop128_2pq_0_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38818; +} + +static void +Opcode_pop128_2pq_0_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3000; +} + +static void +Opcode_pop128_2pq_0_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38418; +} + +static void +Opcode_pop128_2pq_0_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2de801; +} + +static void +Opcode_pop128_2pq_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16a000; +} + +static void +Opcode_pop128_2pq_1_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x33408; +} + +static void +Opcode_pop128_2pq_1_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x39018; +} + +static void +Opcode_pop128_2pq_1_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2900; +} + +static void +Opcode_pop128_2pq_1_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38c18; +} + +static void +Opcode_pop128_2pq_1_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d6d01; +} + +static void +Opcode_pop128_2pq_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x162090; +} + +static void +Opcode_pop128_2pq_2_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x33410; +} + +static void +Opcode_pop128_2pq_2_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3a018; +} + +static void +Opcode_pop128_2pq_2_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2a00; +} + +static void +Opcode_pop128_2pq_2_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x39418; +} + +static void +Opcode_pop128_2pq_2_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d6e01; +} + +static void +Opcode_pop128_2pq_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1620a0; +} + +static void +Opcode_pop128_2pq_3_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x33420; +} + +static void +Opcode_pop128_2pq_3_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38c18; +} + +static void +Opcode_pop128_2pq_3_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c00; +} + +static void +Opcode_pop128_2pq_3_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3a418; +} + +static void +Opcode_pop128_2pq_3_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d6d81; +} + +static void +Opcode_pop128_2pq_4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1620c0; +} + +static void +Opcode_pop128_2pq_4_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x33418; +} + +static void +Opcode_pop128_2pq_4_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x39418; +} + +static void +Opcode_pop128_2pq_4_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2980; +} + +static void +Opcode_pop128_2pq_4_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x39c18; +} + +static void +Opcode_pop128_2pq_4_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d6e81; +} + +static void +Opcode_pop128_2pq_5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1620b0; +} + +static void +Opcode_pop128_2pq_5_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x33428; +} + +static void +Opcode_pop128_2pq_5_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x39818; +} + +static void +Opcode_pop128_2pq_5_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2a80; +} + +static void +Opcode_pop128_2pq_5_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3ac18; +} + +static void +Opcode_pop128_2pq_5_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d6f01; +} + +static void +Opcode_pop2x128_2pq_01_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x263800; +} + +static void +Opcode_pop2x128_2pq_01_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32d80; +} + +static void +Opcode_pop2x128_2pq_01_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x12441; +} + +static void +Opcode_pop2x128_2pq_01_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2cc0; +} + +static void +Opcode_pop2x128_2pq_01_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11c41; +} + +static void +Opcode_pop2x128_2pq_01_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2de881; +} + +static void +Opcode_pop2x128_2pq_03_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x263300; +} + +static void +Opcode_pop2x128_2pq_03_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32dc0; +} + +static void +Opcode_pop2x128_2pq_03_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x12481; +} + +static void +Opcode_pop2x128_2pq_03_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d40; +} + +static void +Opcode_pop2x128_2pq_03_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11c81; +} + +static void +Opcode_pop2x128_2pq_03_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2de901; +} + +static void +Opcode_pop2x128_2pq_21_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x263500; +} + +static void +Opcode_pop2x128_2pq_21_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32e40; +} + +static void +Opcode_pop2x128_2pq_21_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x12501; +} + +static void +Opcode_pop2x128_2pq_21_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d80; +} + +static void +Opcode_pop2x128_2pq_21_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11d01; +} + +static void +Opcode_pop2x128_2pq_21_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2dea01; +} + +static void +Opcode_pop2x128_2pq_23_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x263600; +} + +static void +Opcode_pop2x128_2pq_23_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32e80; +} + +static void +Opcode_pop2x128_2pq_23_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x12601; +} + +static void +Opcode_pop2x128_2pq_23_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2dc0; +} + +static void +Opcode_pop2x128_2pq_23_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11e01; +} + +static void +Opcode_pop2x128_2pq_23_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2de8c1; +} + +static void +Opcode_pop32_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf70300; +} + +static void +Opcode_pop32_0_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3437c; +} + +static void +Opcode_pop32_0_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x682ac; +} + +static void +Opcode_pop32_0_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x39c18; +} + +static void +Opcode_pop32_0_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x803b; +} + +static void +Opcode_pop32_0_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3415c; +} + +static void +Opcode_pop32_0_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x682ac; +} + +static void +Opcode_pop32_0_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80; +} + +static void +Opcode_pop32_0_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc1; +} + +static void +Opcode_pop32_0_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b418; +} + +static void +Opcode_pop32_0_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64065; +} + +static void +Opcode_pop32_0_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x29; +} + +static void +Opcode_pop32_0_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc2ef; +} + +static void +Opcode_pop32_0_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb40ec; +} + +static void +Opcode_pop32_0_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35c00d; +} + +static void +Opcode_pop32_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd70b10; +} + +static void +Opcode_pop32_1_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x343bc; +} + +static void +Opcode_pop32_1_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6832c; +} + +static void +Opcode_pop32_1_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x39c1c; +} + +static void +Opcode_pop32_1_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8077; +} + +static void +Opcode_pop32_1_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3419c; +} + +static void +Opcode_pop32_1_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6832c; +} + +static void +Opcode_pop32_1_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x100; +} + +static void +Opcode_pop32_1_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc5; +} + +static void +Opcode_pop32_1_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b41c; +} + +static void +Opcode_pop32_1_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64069; +} + +static void +Opcode_pop32_1_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x425; +} + +static void +Opcode_pop32_1_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc36f; +} + +static void +Opcode_pop32_1_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb80ec; +} + +static void +Opcode_pop32_1_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3580ad; +} + +static void +Opcode_pop32_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd70b20; +} + +static void +Opcode_pop32_2_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x343fc; +} + +static void +Opcode_pop32_2_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x682ec; +} + +static void +Opcode_pop32_2_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3a418; +} + +static void +Opcode_pop32_2_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80b7; +} + +static void +Opcode_pop32_2_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x341d8; +} + +static void +Opcode_pop32_2_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x682ec; +} + +static void +Opcode_pop32_2_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x200; +} + +static void +Opcode_pop32_2_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc9; +} + +static void +Opcode_pop32_2_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3bc18; +} + +static void +Opcode_pop32_2_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x64071; +} + +static void +Opcode_pop32_2_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x825; +} + +static void +Opcode_pop32_2_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc3ef; +} + +static void +Opcode_pop32_2_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xbc0ec; +} + +static void +Opcode_pop32_2_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35812d; +} + +static void +Opcode_pop32_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd70b40; +} + +static void +Opcode_pop32_3_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38008; +} + +static void +Opcode_pop32_3_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6836c; +} + +static void +Opcode_pop32_3_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3a818; +} + +static void +Opcode_pop32_3_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8137; +} + +static void +Opcode_pop32_3_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x341dc; +} + +static void +Opcode_pop32_3_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6836c; +} + +static void +Opcode_pop32_3_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc0; +} + +static void +Opcode_pop32_3_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd1; +} + +static void +Opcode_pop32_3_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3bc1c; +} + +static void +Opcode_pop32_3_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6406d; +} + +static void +Opcode_pop32_3_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1025; +} + +static void +Opcode_pop32_3_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc037; +} + +static void +Opcode_pop32_3_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800f4; +} + +static void +Opcode_pop32_3_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35822d; +} + +static void +Opcode_push128_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x970b00; +} + +static void +Opcode_push128_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd02; +} + +static void +Opcode_push128_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6c102; +} + +static void +Opcode_push128_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4541; +} + +static void +Opcode_push128_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10040; +} + +static void +Opcode_push128_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40025; +} + +static void +Opcode_push128_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7c102; +} + +static void +Opcode_push128_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40; +} + +static void +Opcode_push128_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6; +} + +static void +Opcode_push128_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x81d4; +} + +static void +Opcode_push128_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x68001; +} + +static void +Opcode_push128_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x25; +} + +static void +Opcode_push128_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc033; +} + +static void +Opcode_push128_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x481411; +} + +static void +Opcode_push128_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35800d; +} + +static void +Opcode_push128_m_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf80000; +} + +static void +Opcode_push128_m_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x46002; +} + +static void +Opcode_push128_m_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x46002; +} + +static void +Opcode_push128_m_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x60001; +} + +static void +Opcode_push128_m_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x526000; +} + +static void +Opcode_push128_pq_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x162000; +} + +static void +Opcode_push128_pq_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2fc00; +} + +static void +Opcode_push128_pq_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11001; +} + +static void +Opcode_push128_pq_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d400; +} + +static void +Opcode_push128_pq_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2400; +} + +static void +Opcode_push128_pq_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38018; +} + +static void +Opcode_push128_pq_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc802; +} + +static void +Opcode_push128_pq_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb803; +} + +static void +Opcode_push128_pq_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4c9401; +} + +static void +Opcode_push128_pq_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2e6801; +} + +static void +Opcode_push2x128_pq_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x862000; +} + +static void +Opcode_push2x128_pq_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x33800; +} + +static void +Opcode_push2x128_pq_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38018; +} + +static void +Opcode_push2x128_pq_Slot_acc2_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2800; +} + +static void +Opcode_push2x128_pq_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x58018; +} + +static void +Opcode_push2x128_pq_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10100; +} + +static void +Opcode_push2x128_pq_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d6c01; +} + +static void +Opcode_push32_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xdd0000; +} + +static void +Opcode_push32_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32000; +} + +static void +Opcode_push32_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1d400; +} + +static void +Opcode_push32_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x12001; +} + +static void +Opcode_push32_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xdc03; +} + +static void +Opcode_push32_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d800; +} + +static void +Opcode_push32_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1d400; +} + +static void +Opcode_push32_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_push32_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11001; +} + +static void +Opcode_push32_Slot_smod_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5cc01; +} + +static void +Opcode_push32_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd002; +} + +static void +Opcode_push32_Slot_llr_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xbc03; +} + +static void +Opcode_push32_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4d1401; +} + +static void +Opcode_push32_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10142; +} + +static void +Opcode_qready_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70e00; +} + +static void +Opcode_qready_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c000; +} + +static void +Opcode_qready_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10001; +} + +static void +Opcode_qready_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38080; +} + +static void +Opcode_qready_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10001; +} + +static void +Opcode_qready_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20002; +} + +static void +Opcode_qready_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x240; +} + +static void +Opcode_rdtiep_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd70b80; +} + +static void +Opcode_rdtiep_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38010; +} + +static void +Opcode_rdtiep_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b018; +} + +static void +Opcode_rdtiep_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3421c; +} + +static void +Opcode_rdtiep_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x68018; +} + +static void +Opcode_rdtiep_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2025; +} + +static void +Opcode_rdtiep_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800f8; +} + +static void +Opcode_settiep_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6b400; +} + +static void +Opcode_settiep_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32c80; +} + +static void +Opcode_settiep_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13001; +} + +static void +Opcode_settiep_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2ec00; +} + +static void +Opcode_settiep_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13001; +} + +static void +Opcode_settiep_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4142; +} + +static void +Opcode_settiep_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x300; +} + +static void +Opcode_smod_lut_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4041; +} + +static void +Opcode_wrtbsigq_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16a020; +} + +static void +Opcode_wrtbsigq_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32f00; +} + +static void +Opcode_wrtbsigq_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x124c1; +} + +static void +Opcode_wrtbsigq_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2ee00; +} + +static void +Opcode_wrtbsigq_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11cc1; +} + +static void +Opcode_wrtbsigq_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5142; +} + +static void +Opcode_wrtbsigq_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcd0c0; +} + +static void +Opcode_wrtbsigqm_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6b800; +} + +static void +Opcode_wrtbsigqm_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32d00; +} + +static void +Opcode_wrtbsigqm_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x12841; +} + +static void +Opcode_wrtbsigqm_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2ec80; +} + +static void +Opcode_wrtbsigqm_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x12841; +} + +static void +Opcode_wrtbsigqm_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4182; +} + +static void +Opcode_wrtbsigqm_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x244; +} + +static void +Opcode_wrtiep_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x262000; +} + +static void +Opcode_wrtiep_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x33000; +} + +static void +Opcode_wrtiep_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11c01; +} + +static void +Opcode_wrtiep_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2e800; +} + +static void +Opcode_wrtiep_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11801; +} + +static void +Opcode_wrtiep_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd802; +} + +static void +Opcode_wrtiep_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4d5401; +} + +static void +Opcode_wrtsigq_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16a040; +} + +static void +Opcode_wrtsigq_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32ec0; +} + +static void +Opcode_wrtsigq_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x12541; +} + +static void +Opcode_wrtsigq_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2ed40; +} + +static void +Opcode_wrtsigq_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11d41; +} + +static void +Opcode_wrtsigq_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6142; +} + +static void +Opcode_wrtsigq_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xce0c0; +} + +static void +Opcode_abs8_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40019; +} + +static void +Opcode_abs8_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8014; +} + +static void +Opcode_abs8_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40019; +} + +static void +Opcode_abs8_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8014; +} + +static void +Opcode_abs8_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x19; +} + +static void +Opcode_abs8_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800c0; +} + +static void +Opcode_add16_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40031; +} + +static void +Opcode_add16_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8030; +} + +static void +Opcode_add16_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40031; +} + +static void +Opcode_add16_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8030; +} + +static void +Opcode_add16_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x31; +} + +static void +Opcode_add16_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x481401; +} + +static void +Opcode_add32_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40000; +} + +static void +Opcode_add32_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_add32_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40000; +} + +static void +Opcode_add32_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_add32_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_add32_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_add32_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc00040; +} + +static void +Opcode_addac_i2r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb78380; +} + +static void +Opcode_addac_i2r_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a00c; +} + +static void +Opcode_addac_i2r_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a00c; +} + +static void +Opcode_addac_i2r_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35832d; +} + +static void +Opcode_addac_r2i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb78390; +} + +static void +Opcode_addac_r2i_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a04c; +} + +static void +Opcode_addac_r2i_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a04c; +} + +static void +Opcode_addac_r2i_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3583ad; +} + +static void +Opcode_addar2_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2e400; +} + +static void +Opcode_addar2_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20001; +} + +static void +Opcode_addar2_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d000; +} + +static void +Opcode_addar2_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20001; +} + +static void +Opcode_addar2_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc002; +} + +static void +Opcode_addar2_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x501401; +} + +static void +Opcode_addcm_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40040; +} + +static void +Opcode_addcm_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40; +} + +static void +Opcode_addcm_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40040; +} + +static void +Opcode_addcm_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000; +} + +static void +Opcode_addcm_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40; +} + +static void +Opcode_addcm_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40; +} + +static void +Opcode_addcm_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc40040; +} + +static void +Opcode_addwrp_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40080; +} + +static void +Opcode_addwrp_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80; +} + +static void +Opcode_addwrp_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40080; +} + +static void +Opcode_addwrp_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80; +} + +static void +Opcode_addwrp_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80; +} + +static void +Opcode_addwrp_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc80040; +} + +static void +Opcode_and128_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40100; +} + +static void +Opcode_and128_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x100; +} + +static void +Opcode_and128_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40100; +} + +static void +Opcode_and128_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x100; +} + +static void +Opcode_and128_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x100; +} + +static void +Opcode_and128_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd00040; +} + +static void +Opcode_argmax8_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc82; +} + +static void +Opcode_argmax8_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4141; +} + +static void +Opcode_argmax8_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2002; +} + +static void +Opcode_argmax8_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_argmax8_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4581; +} + +static void +Opcode_argmax8_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40140; +} + +static void +Opcode_argmax8_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2000c0; +} + +static void +Opcode_asl_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40200; +} + +static void +Opcode_asl_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x200; +} + +static void +Opcode_asl_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40200; +} + +static void +Opcode_asl_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x200; +} + +static void +Opcode_asl_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x200; +} + +static void +Opcode_asl_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe00040; +} + +static void +Opcode_asl32_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_asl32_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000; +} + +static void +Opcode_asl32_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_asl32_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000; +} + +static void +Opcode_asl32_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc0; +} + +static void +Opcode_asl32_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1c01; +} + +static void +Opcode_aslacm_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xbc8000; +} + +static void +Opcode_aslacm_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70002; +} + +static void +Opcode_aslacm_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6e002; +} + +static void +Opcode_aslacm_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x302; +} + +static void +Opcode_aslm_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40001; +} + +static void +Opcode_aslm_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8000; +} + +static void +Opcode_aslm_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40001; +} + +static void +Opcode_aslm_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8000; +} + +static void +Opcode_aslm_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_aslm_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x140002; +} + +static void +Opcode_aslm32_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2002; +} + +static void +Opcode_aslm32_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4301; +} + +static void +Opcode_aslm32_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1002; +} + +static void +Opcode_aslm32_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4301; +} + +static void +Opcode_aslm32_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40300; +} + +static void +Opcode_aslm32_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400100; +} + +static void +Opcode_asr_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400c0; +} + +static void +Opcode_asr_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc0; +} + +static void +Opcode_asr_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400c0; +} + +static void +Opcode_asr_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4001; +} + +static void +Opcode_asr_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc0; +} + +static void +Opcode_asr_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x140; +} + +static void +Opcode_asr_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcc0040; +} + +static void +Opcode_asr32_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x401; +} + +static void +Opcode_asr32_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x140; +} + +static void +Opcode_asr32_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x401; +} + +static void +Opcode_asr32_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x140; +} + +static void +Opcode_asr32_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x180; +} + +static void +Opcode_asr32_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x41c01; +} + +static void +Opcode_asrac_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x570b00; +} + +static void +Opcode_asrac_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a002; +} + +static void +Opcode_asrac_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6e102; +} + +static void +Opcode_asrac_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80142; +} + +static void +Opcode_asrm_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40005; +} + +static void +Opcode_asrm_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8004; +} + +static void +Opcode_asrm_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40005; +} + +static void +Opcode_asrm_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8004; +} + +static void +Opcode_asrm_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5; +} + +static void +Opcode_asrm_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x180002; +} + +static void +Opcode_bitfext_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_bitfins_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_clb_c_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x770300; +} + +static void +Opcode_clb_c_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5802c; +} + +static void +Opcode_clb_c_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe403; +} + +static void +Opcode_clb_c_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5802c; +} + +static void +Opcode_clb_c_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34c02d; +} + +static void +Opcode_clb_r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x578b00; +} + +static void +Opcode_clb_r_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5a02c; +} + +static void +Opcode_clb_r_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe803; +} + +static void +Opcode_clb_r_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5a02c; +} + +static void +Opcode_clb_r_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34e02d; +} + +static void +Opcode_cmp8_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40009; +} + +static void +Opcode_cmp8_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8008; +} + +static void +Opcode_cmp8_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40009; +} + +static void +Opcode_cmp8_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8008; +} + +static void +Opcode_cmp8_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9; +} + +static void +Opcode_cmp8_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x140006; +} + +static void +Opcode_cmp_i_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40011; +} + +static void +Opcode_cmp_i_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8010; +} + +static void +Opcode_cmp_i_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40011; +} + +static void +Opcode_cmp_i_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8010; +} + +static void +Opcode_cmp_i_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11; +} + +static void +Opcode_cmp_i_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x14000a; +} + +static void +Opcode_cmp_r_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40021; +} + +static void +Opcode_cmp_r_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8020; +} + +static void +Opcode_cmp_r_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40021; +} + +static void +Opcode_cmp_r_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8020; +} + +static void +Opcode_cmp_r_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x21; +} + +static void +Opcode_cmp_r_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x140012; +} + +static void +Opcode_ext_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd80000; +} + +static void +Opcode_ext_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2a002; +} + +static void +Opcode_ext_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8002; +} + +static void +Opcode_ext_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2a002; +} + +static void +Opcode_ext_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x524000; +} + +static void +Opcode_ext_r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd88000; +} + +static void +Opcode_ext_r_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2e002; +} + +static void +Opcode_ext_r_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa002; +} + +static void +Opcode_ext_r_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2e002; +} + +static void +Opcode_ext_r_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x528000; +} + +static void +Opcode_ext32_i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x170600; +} + +static void +Opcode_ext32_i_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x44028; +} + +static void +Opcode_ext32_i_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf402; +} + +static void +Opcode_ext32_i_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x44028; +} + +static void +Opcode_ext32_i_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x340019; +} + +static void +Opcode_ext32_r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x270600; +} + +static void +Opcode_ext32_r_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4c008; +} + +static void +Opcode_ext32_r_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf802; +} + +static void +Opcode_ext32_r_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4c008; +} + +static void +Opcode_ext32_r_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x340039; +} + +static void +Opcode_extui4_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40140; +} + +static void +Opcode_extui4_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x180; +} + +static void +Opcode_extui4_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40140; +} + +static void +Opcode_extui4_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x180; +} + +static void +Opcode_extui4_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1c0; +} + +static void +Opcode_extui4_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd40040; +} + +static void +Opcode_lslm_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000d; +} + +static void +Opcode_lslm_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc000; +} + +static void +Opcode_lslm_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000d; +} + +static void +Opcode_lslm_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc000; +} + +static void +Opcode_lslm_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd; +} + +static void +Opcode_lslm_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x140022; +} + +static void +Opcode_lsrm_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40015; +} + +static void +Opcode_lsrm_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800c; +} + +static void +Opcode_lsrm_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40015; +} + +static void +Opcode_lsrm_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800c; +} + +static void +Opcode_lsrm_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x15; +} + +static void +Opcode_lsrm_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x14000e; +} + +static void +Opcode_max8_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40280; +} + +static void +Opcode_max8_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x300; +} + +static void +Opcode_max8_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40280; +} + +static void +Opcode_max8_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x300; +} + +static void +Opcode_max8_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c0; +} + +static void +Opcode_max8_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe80040; +} + +static void +Opcode_mean_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40300; +} + +static void +Opcode_mean_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c0; +} + +static void +Opcode_mean_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40300; +} + +static void +Opcode_mean_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c0; +} + +static void +Opcode_mean_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x340; +} + +static void +Opcode_mean_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf00040; +} + +static void +Opcode_mean32_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x402c0; +} + +static void +Opcode_mean32_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x340; +} + +static void +Opcode_mean32_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x402c0; +} + +static void +Opcode_mean32_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x340; +} + +static void +Opcode_mean32_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x380; +} + +static void +Opcode_mean32_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xec0040; +} + +static void +Opcode_min8_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40340; +} + +static void +Opcode_min8_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x380; +} + +static void +Opcode_min8_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40340; +} + +static void +Opcode_min8_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x380; +} + +static void +Opcode_min8_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c0; +} + +static void +Opcode_min8_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf40040; +} + +static void +Opcode_minclb_c_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x770b00; +} + +static void +Opcode_minclb_c_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6002c; +} + +static void +Opcode_minclb_c_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf003; +} + +static void +Opcode_minclb_c_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6002c; +} + +static void +Opcode_minclb_c_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35002d; +} + +static void +Opcode_minclb_r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x778300; +} + +static void +Opcode_minclb_r_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6800c; +} + +static void +Opcode_minclb_r_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe407; +} + +static void +Opcode_minclb_r_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6800c; +} + +static void +Opcode_minclb_r_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35400d; +} + +static void +Opcode_not128_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4005d; +} + +static void +Opcode_not128_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8154; +} + +static void +Opcode_not128_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4005d; +} + +static void +Opcode_not128_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8154; +} + +static void +Opcode_not128_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5d; +} + +static void +Opcode_not128_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800e8; +} + +static void +Opcode_or128_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40380; +} + +static void +Opcode_or128_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8001; +} + +static void +Opcode_or128_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40380; +} + +static void +Opcode_or128_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8001; +} + +static void +Opcode_or128_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40000; +} + +static void +Opcode_or128_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf80040; +} + +static void +Opcode_perm_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1002; +} + +static void +Opcode_perm_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc001; +} + +static void +Opcode_perm_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x802; +} + +static void +Opcode_perm_Slot_acc2_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4003; +} + +static void +Opcode_perm_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc001; +} + +static void +Opcode_perm_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40001; +} + +static void +Opcode_perm_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x441401; +} + +static void +Opcode_redac_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb783a0; +} + +static void +Opcode_redac_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a08c; +} + +static void +Opcode_redac_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a08c; +} + +static void +Opcode_redac_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35a32d; +} + +static void +Opcode_redac2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb783c0; +} + +static void +Opcode_redac2_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a10c; +} + +static void +Opcode_redac2_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a10c; +} + +static void +Opcode_redac2_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35a3ad; +} + +static void +Opcode_redac4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb783b0; +} + +static void +Opcode_redac4_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a20c; +} + +static void +Opcode_redac4_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a20c; +} + +static void +Opcode_redac4_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35806d; +} + +static void +Opcode_redacs_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb783d0; +} + +static void +Opcode_redacs_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a0cc; +} + +static void +Opcode_redacs_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a0cc; +} + +static void +Opcode_redacs_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3580cd; +} + +static void +Opcode_sminclb_c_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x778b00; +} + +static void +Opcode_sminclb_c_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7000c; +} + +static void +Opcode_sminclb_c_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe807; +} + +static void +Opcode_sminclb_c_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7000c; +} + +static void +Opcode_sminclb_c_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35202d; +} + +static void +Opcode_sminclb_r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd70300; +} + +static void +Opcode_sminclb_r_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6202c; +} + +static void +Opcode_sminclb_r_Slot_dot_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xec03; +} + +static void +Opcode_sminclb_r_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6202c; +} + +static void +Opcode_sminclb_r_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35600d; +} + +static void +Opcode_stswapbm_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9c0000; +} + +static void +Opcode_stswapbm_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4e8000; +} + +static void +Opcode_stswapbmu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xad0000; +} + +static void +Opcode_stswapbmu_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4f0000; +} + +static void +Opcode_sub32_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x403c0; +} + +static void +Opcode_sub32_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4041; +} + +static void +Opcode_sub32_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x403c0; +} + +static void +Opcode_sub32_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4081; +} + +static void +Opcode_sub32_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40040; +} + +static void +Opcode_sub32_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfc0040; +} + +static void +Opcode_subac_i2r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb783e0; +} + +static void +Opcode_subac_i2r_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a14c; +} + +static void +Opcode_subac_i2r_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a14c; +} + +static void +Opcode_subac_i2r_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35814d; +} + +static void +Opcode_subac_r2i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb783f0; +} + +static void +Opcode_subac_r2i_Slot_gp_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a18c; +} + +static void +Opcode_subac_r2i_Slot_pq_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a18c; +} + +static void +Opcode_subac_r2i_Slot_dual_slot0_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35824d; +} + +static void +Opcode_subarx_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32800; +} + +static void +Opcode_subarx_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x11401; +} + +static void +Opcode_subarx_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2e400; +} + +static void +Opcode_subarx_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10c01; +} + +static void +Opcode_subarx_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcc02; +} + +static void +Opcode_subarx_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4cd401; +} + +static void +Opcode_subcm_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40002; +} + +static void +Opcode_subcm_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4081; +} + +static void +Opcode_subcm_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40002; +} + +static void +Opcode_subcm_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4101; +} + +static void +Opcode_subcm_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40080; +} + +static void +Opcode_subcm_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc0; +} + +static void +Opcode_submean_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40042; +} + +static void +Opcode_submean_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4101; +} + +static void +Opcode_submean_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40042; +} + +static void +Opcode_submean_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4201; +} + +static void +Opcode_submean_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40100; +} + +static void +Opcode_submean_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400080; +} + +static void +Opcode_subwrp_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40082; +} + +static void +Opcode_subwrp_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4201; +} + +static void +Opcode_subwrp_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40082; +} + +static void +Opcode_subwrp_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40c1; +} + +static void +Opcode_subwrp_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40200; +} + +static void +Opcode_subwrp_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800080; +} + +static void +Opcode_trans_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4009d; +} + +static void +Opcode_trans_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8194; +} + +static void +Opcode_trans_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4009d; +} + +static void +Opcode_trans_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8194; +} + +static void +Opcode_trans_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9d; +} + +static void +Opcode_trans_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800f0; +} + +static void +Opcode_xor128_Slot_gp_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40102; +} + +static void +Opcode_xor128_Slot_dot_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40c1; +} + +static void +Opcode_xor128_Slot_pq_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40102; +} + +static void +Opcode_xor128_Slot_smod_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4141; +} + +static void +Opcode_xor128_Slot_llr_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400c0; +} + +static void +Opcode_xor128_Slot_dual_slot2_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400c0; +} + +static void +Opcode_rur_expstate_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30000; +} + +static void +Opcode_wur_expstate_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf30000; +} + +static void +Opcode_rur_sov_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30010; +} + +static void +Opcode_wur_sov_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf30100; +} + +static void +Opcode_rur_sat_mode_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30020; +} + +static void +Opcode_wur_sat_mode_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf30200; +} + +static void +Opcode_rur_sar0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30030; +} + +static void +Opcode_wur_sar0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf30300; +} + +static void +Opcode_rur_sar1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30040; +} + +static void +Opcode_wur_sar1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf30400; +} + +static void +Opcode_rur_sar2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30050; +} + +static void +Opcode_wur_sar2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf30500; +} + +static void +Opcode_rur_sar3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30060; +} + +static void +Opcode_wur_sar3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf30600; +} + +static void +Opcode_rur_hsar0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30070; +} + +static void +Opcode_wur_hsar0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf30700; +} + +static void +Opcode_rur_hsar1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30080; +} + +static void +Opcode_wur_hsar1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf30800; +} + +static void +Opcode_rur_hsar2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30090; +} + +static void +Opcode_wur_hsar2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf30900; +} + +static void +Opcode_rur_hsar3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe300a0; +} + +static void +Opcode_wur_hsar3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf30a00; +} + +static void +Opcode_rur_max_reg_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe300b0; +} + +static void +Opcode_wur_max_reg_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf30b00; +} + +static void +Opcode_rur_max_reg_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe300c0; +} + +static void +Opcode_wur_max_reg_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf30c00; +} + +static void +Opcode_rur_max_reg_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe300d0; +} + +static void +Opcode_wur_max_reg_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf30d00; +} + +static void +Opcode_rur_max_reg_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe300e0; +} + +static void +Opcode_wur_max_reg_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf30e00; +} + +static void +Opcode_rur_arg_max_reg_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe300f0; +} + +static void +Opcode_wur_arg_max_reg_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf30f00; +} + +static void +Opcode_rur_arg_max_reg_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30100; +} + +static void +Opcode_wur_arg_max_reg_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf31000; +} + +static void +Opcode_rur_arg_max_reg_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30110; +} + +static void +Opcode_wur_arg_max_reg_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf31100; +} + +static void +Opcode_rur_arg_max_reg_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30120; +} + +static void +Opcode_wur_arg_max_reg_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf31200; +} + +static void +Opcode_rur_nco_counter_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30130; +} + +static void +Opcode_wur_nco_counter_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf31300; +} + +static void +Opcode_rur_nco_counter_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30140; +} + +static void +Opcode_wur_nco_counter_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf31400; +} + +static void +Opcode_rur_nco_counter_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30150; +} + +static void +Opcode_wur_nco_counter_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf31500; +} + +static void +Opcode_rur_nco_counter_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30160; +} + +static void +Opcode_wur_nco_counter_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf31600; +} + +static void +Opcode_rur_interp_ext_n_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30170; +} + +static void +Opcode_wur_interp_ext_n_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf31700; +} + +static void +Opcode_rur_interp_ext_l_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30180; +} + +static void +Opcode_wur_interp_ext_l_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf31800; +} + +static void +Opcode_rur_llr_buf_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30190; +} + +static void +Opcode_wur_llr_buf_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf31900; +} + +static void +Opcode_rur_llr_buf_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe301a0; +} + +static void +Opcode_wur_llr_buf_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf31a00; +} + +static void +Opcode_rur_llr_buf_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe301b0; +} + +static void +Opcode_wur_llr_buf_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf31b00; +} + +static void +Opcode_rur_llr_buf_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe301c0; +} + +static void +Opcode_wur_llr_buf_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf31c00; +} + +static void +Opcode_rur_llr_buf_4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe301d0; +} + +static void +Opcode_wur_llr_buf_4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf31d00; +} + +static void +Opcode_rur_llr_buf_5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe301e0; +} + +static void +Opcode_wur_llr_buf_5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf31e00; +} + +static void +Opcode_rur_llr_buf_6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe301f0; +} + +static void +Opcode_wur_llr_buf_6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf31f00; +} + +static void +Opcode_rur_llr_buf_7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30200; +} + +static void +Opcode_wur_llr_buf_7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf32000; +} + +static void +Opcode_rur_llr_buf_8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30210; +} + +static void +Opcode_wur_llr_buf_8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf32100; +} + +static void +Opcode_rur_llr_buf_9_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30220; +} + +static void +Opcode_wur_llr_buf_9_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf32200; +} + +static void +Opcode_rur_llr_buf_10_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30230; +} + +static void +Opcode_wur_llr_buf_10_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf32300; +} + +static void +Opcode_rur_llr_buf_11_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30240; +} + +static void +Opcode_wur_llr_buf_11_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf32400; +} + +static void +Opcode_rur_llr_buf_12_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30250; +} + +static void +Opcode_wur_llr_buf_12_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf32500; +} + +static void +Opcode_rur_llr_buf_13_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30260; +} + +static void +Opcode_wur_llr_buf_13_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf32600; +} + +static void +Opcode_rur_llr_buf_14_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30270; +} + +static void +Opcode_wur_llr_buf_14_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf32700; +} + +static void +Opcode_rur_llr_buf_15_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30280; +} + +static void +Opcode_wur_llr_buf_15_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf32800; +} + +static void +Opcode_rur_llr_buf_16_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30290; +} + +static void +Opcode_wur_llr_buf_16_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf32900; +} + +static void +Opcode_rur_llr_buf_17_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe302a0; +} + +static void +Opcode_wur_llr_buf_17_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf32a00; +} + +static void +Opcode_rur_llr_buf_18_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe302b0; +} + +static void +Opcode_wur_llr_buf_18_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf32b00; +} + +static void +Opcode_rur_llr_buf_19_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe302c0; +} + +static void +Opcode_wur_llr_buf_19_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf32c00; +} + +static void +Opcode_rur_llr_buf_20_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe302d0; +} + +static void +Opcode_wur_llr_buf_20_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf32d00; +} + +static void +Opcode_rur_llr_buf_21_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe302e0; +} + +static void +Opcode_wur_llr_buf_21_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf32e00; +} + +static void +Opcode_rur_llr_buf_22_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe302f0; +} + +static void +Opcode_wur_llr_buf_22_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf32f00; +} + +static void +Opcode_rur_llr_buf_23_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30300; +} + +static void +Opcode_wur_llr_buf_23_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf33000; +} + +static void +Opcode_rur_smod_buf_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30310; +} + +static void +Opcode_wur_smod_buf_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf33100; +} + +static void +Opcode_rur_smod_buf_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30320; +} + +static void +Opcode_wur_smod_buf_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf33200; +} + +static void +Opcode_rur_smod_buf_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30330; +} + +static void +Opcode_wur_smod_buf_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf33300; +} + +static void +Opcode_rur_smod_buf_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30340; +} + +static void +Opcode_wur_smod_buf_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf33400; +} + +static void +Opcode_rur_smod_buf_4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30350; +} + +static void +Opcode_wur_smod_buf_4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf33500; +} + +static void +Opcode_rur_smod_buf_5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30360; +} + +static void +Opcode_wur_smod_buf_5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf33600; +} + +static void +Opcode_rur_smod_buf_6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30370; +} + +static void +Opcode_wur_smod_buf_6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf33700; +} + +static void +Opcode_rur_smod_buf_7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30380; +} + +static void +Opcode_wur_smod_buf_7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf33800; +} + +static void +Opcode_rur_weight_reg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30390; +} + +static void +Opcode_wur_weight_reg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf33900; +} + +static void +Opcode_rur_scale_reg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe303a0; +} + +static void +Opcode_wur_scale_reg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf33a00; +} + +static void +Opcode_rur_llr_pos_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe303b0; +} + +static void +Opcode_wur_llr_pos_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf33b00; +} + +static void +Opcode_rur_smod_pos_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe303c0; +} + +static void +Opcode_wur_smod_pos_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf33c00; +} + +static void +Opcode_rur_perm_reg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe303d0; +} + +static void +Opcode_wur_perm_reg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf33d00; +} + +static void +Opcode_rur_smod_offset_table_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe303e0; +} + +static void +Opcode_wur_smod_offset_table_0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf33e00; +} + +static void +Opcode_rur_smod_offset_table_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe303f0; +} + +static void +Opcode_wur_smod_offset_table_1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf33f00; +} + +static void +Opcode_rur_smod_offset_table_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30400; +} + +static void +Opcode_wur_smod_offset_table_2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf34000; +} + +static void +Opcode_rur_smod_offset_table_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30410; +} + +static void +Opcode_wur_smod_offset_table_3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf34100; +} + +static void +Opcode_rur_phasor_n_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30420; +} + +static void +Opcode_wur_phasor_n_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf34200; +} + +static void +Opcode_rur_phasor_offset_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30430; +} + +static void +Opcode_wur_phasor_offset_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf34300; +} + +static xtensa_opcode_encode_fn Opcode_excw_encode_fns[] = { + Opcode_excw_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfe_encode_fns[] = { + Opcode_rfe_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfde_encode_fns[] = { + Opcode_rfde_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_syscall_encode_fns[] = { + Opcode_syscall_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_simcall_encode_fns[] = { + Opcode_simcall_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_call12_encode_fns[] = { + Opcode_call12_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_call8_encode_fns[] = { + Opcode_call8_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_call4_encode_fns[] = { + Opcode_call4_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_callx12_encode_fns[] = { + Opcode_callx12_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_callx8_encode_fns[] = { + Opcode_callx8_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_callx4_encode_fns[] = { + Opcode_callx4_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_entry_encode_fns[] = { + Opcode_entry_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movsp_encode_fns[] = { + Opcode_movsp_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rotw_encode_fns[] = { + Opcode_rotw_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_retw_encode_fns[] = { + Opcode_retw_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_retw_n_encode_fns[] = { + 0, 0, Opcode_retw_n_Slot_inst16b_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfwo_encode_fns[] = { + Opcode_rfwo_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfwu_encode_fns[] = { + Opcode_rfwu_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_l32e_encode_fns[] = { + Opcode_l32e_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s32e_encode_fns[] = { + Opcode_s32e_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_windowbase_encode_fns[] = { + Opcode_rsr_windowbase_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_windowbase_encode_fns[] = { + Opcode_wsr_windowbase_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_windowbase_encode_fns[] = { + Opcode_xsr_windowbase_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_windowstart_encode_fns[] = { + Opcode_rsr_windowstart_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_windowstart_encode_fns[] = { + Opcode_wsr_windowstart_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_windowstart_encode_fns[] = { + Opcode_xsr_windowstart_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_add_n_encode_fns[] = { + 0, Opcode_add_n_Slot_inst16a_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addi_n_encode_fns[] = { + 0, Opcode_addi_n_Slot_inst16a_encode, 0, Opcode_addi_n_Slot_gp_slot2_encode, 0, Opcode_addi_n_Slot_gp_slot0_encode, 0, 0, Opcode_addi_n_Slot_dot_slot0_encode, Opcode_addi_n_Slot_pq_slot2_encode, 0, Opcode_addi_n_Slot_pq_slot0_encode, 0, 0, Opcode_addi_n_Slot_acc2_slot0_encode, 0, 0, Opcode_addi_n_Slot_smod_slot0_encode, 0, 0, Opcode_addi_n_Slot_llr_slot0_encode, Opcode_addi_n_Slot_dual_slot2_encode, 0, Opcode_addi_n_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_beqz_n_encode_fns[] = { + 0, 0, Opcode_beqz_n_Slot_inst16b_encode, 0, 0, Opcode_beqz_n_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_beqz_n_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_beqz_n_Slot_smod_slot0_encode, 0, 0, 0, Opcode_beqz_n_Slot_dual_slot2_encode, 0, Opcode_beqz_n_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bnez_n_encode_fns[] = { + 0, 0, Opcode_bnez_n_Slot_inst16b_encode, 0, 0, Opcode_bnez_n_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_bnez_n_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_bnez_n_Slot_smod_slot0_encode, 0, 0, 0, Opcode_bnez_n_Slot_dual_slot2_encode, 0, Opcode_bnez_n_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ill_n_encode_fns[] = { + 0, 0, Opcode_ill_n_Slot_inst16b_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_l32i_n_encode_fns[] = { + 0, Opcode_l32i_n_Slot_inst16a_encode, 0, 0, 0, Opcode_l32i_n_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_l32i_n_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_l32i_n_Slot_smod_slot0_encode, 0, 0, Opcode_l32i_n_Slot_llr_slot0_encode, 0, 0, Opcode_l32i_n_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_mov_n_encode_fns[] = { + 0, 0, Opcode_mov_n_Slot_inst16b_encode, Opcode_mov_n_Slot_gp_slot2_encode, 0, Opcode_mov_n_Slot_gp_slot0_encode, 0, 0, Opcode_mov_n_Slot_dot_slot0_encode, Opcode_mov_n_Slot_pq_slot2_encode, 0, Opcode_mov_n_Slot_pq_slot0_encode, 0, 0, Opcode_mov_n_Slot_acc2_slot0_encode, 0, 0, Opcode_mov_n_Slot_smod_slot0_encode, 0, 0, Opcode_mov_n_Slot_llr_slot0_encode, Opcode_mov_n_Slot_dual_slot2_encode, 0, Opcode_mov_n_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_movi_n_encode_fns[] = { + 0, 0, Opcode_movi_n_Slot_inst16b_encode, Opcode_movi_n_Slot_gp_slot2_encode, 0, Opcode_movi_n_Slot_gp_slot0_encode, 0, 0, Opcode_movi_n_Slot_dot_slot0_encode, Opcode_movi_n_Slot_pq_slot2_encode, 0, Opcode_movi_n_Slot_pq_slot0_encode, 0, 0, Opcode_movi_n_Slot_acc2_slot0_encode, 0, 0, Opcode_movi_n_Slot_smod_slot0_encode, 0, 0, Opcode_movi_n_Slot_llr_slot0_encode, Opcode_movi_n_Slot_dual_slot2_encode, 0, Opcode_movi_n_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_nop_n_encode_fns[] = { + 0, 0, Opcode_nop_n_Slot_inst16b_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ret_n_encode_fns[] = { + 0, 0, Opcode_ret_n_Slot_inst16b_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s32i_n_encode_fns[] = { + 0, Opcode_s32i_n_Slot_inst16a_encode, 0, 0, 0, Opcode_s32i_n_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_s32i_n_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_s32i_n_Slot_smod_slot0_encode, 0, 0, Opcode_s32i_n_Slot_llr_slot0_encode, 0, 0, Opcode_s32i_n_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_rur_threadptr_encode_fns[] = { + Opcode_rur_threadptr_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_threadptr_encode_fns[] = { + Opcode_wur_threadptr_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addi_encode_fns[] = { + Opcode_addi_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_addi_Slot_dual_slot2_encode, 0, Opcode_addi_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_addmi_encode_fns[] = { + Opcode_addmi_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_addmi_Slot_dual_slot2_encode, 0, Opcode_addmi_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_add_encode_fns[] = { + Opcode_add_Slot_inst_encode, 0, 0, Opcode_add_Slot_gp_slot2_encode, 0, Opcode_add_Slot_gp_slot0_encode, 0, 0, Opcode_add_Slot_dot_slot0_encode, Opcode_add_Slot_pq_slot2_encode, 0, Opcode_add_Slot_pq_slot0_encode, 0, 0, Opcode_add_Slot_acc2_slot0_encode, 0, 0, Opcode_add_Slot_smod_slot0_encode, 0, 0, Opcode_add_Slot_llr_slot0_encode, Opcode_add_Slot_dual_slot2_encode, 0, Opcode_add_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sub_encode_fns[] = { + Opcode_sub_Slot_inst_encode, 0, 0, Opcode_sub_Slot_gp_slot2_encode, 0, Opcode_sub_Slot_gp_slot0_encode, 0, 0, Opcode_sub_Slot_dot_slot0_encode, Opcode_sub_Slot_pq_slot2_encode, 0, Opcode_sub_Slot_pq_slot0_encode, 0, 0, Opcode_sub_Slot_acc2_slot0_encode, 0, 0, Opcode_sub_Slot_smod_slot0_encode, 0, 0, Opcode_sub_Slot_llr_slot0_encode, Opcode_sub_Slot_dual_slot2_encode, 0, Opcode_sub_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_addx2_encode_fns[] = { + Opcode_addx2_Slot_inst_encode, 0, 0, 0, 0, Opcode_addx2_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_addx2_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_addx2_Slot_smod_slot0_encode, 0, 0, 0, Opcode_addx2_Slot_dual_slot2_encode, 0, Opcode_addx2_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_addx4_encode_fns[] = { + Opcode_addx4_Slot_inst_encode, 0, 0, 0, 0, Opcode_addx4_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_addx4_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_addx4_Slot_smod_slot0_encode, 0, 0, 0, Opcode_addx4_Slot_dual_slot2_encode, 0, Opcode_addx4_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_addx8_encode_fns[] = { + Opcode_addx8_Slot_inst_encode, 0, 0, 0, 0, Opcode_addx8_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_addx8_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_addx8_Slot_smod_slot0_encode, 0, 0, 0, Opcode_addx8_Slot_dual_slot2_encode, 0, Opcode_addx8_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_subx2_encode_fns[] = { + Opcode_subx2_Slot_inst_encode, 0, 0, 0, 0, Opcode_subx2_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_subx2_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_subx2_Slot_smod_slot0_encode, 0, 0, 0, Opcode_subx2_Slot_dual_slot2_encode, 0, Opcode_subx2_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_subx4_encode_fns[] = { + Opcode_subx4_Slot_inst_encode, 0, 0, 0, 0, Opcode_subx4_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_subx4_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_subx4_Slot_smod_slot0_encode, 0, 0, 0, Opcode_subx4_Slot_dual_slot2_encode, 0, Opcode_subx4_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_subx8_encode_fns[] = { + Opcode_subx8_Slot_inst_encode, 0, 0, 0, 0, Opcode_subx8_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_subx8_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_subx8_Slot_smod_slot0_encode, 0, 0, 0, Opcode_subx8_Slot_dual_slot2_encode, 0, Opcode_subx8_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_and_encode_fns[] = { + Opcode_and_Slot_inst_encode, 0, 0, Opcode_and_Slot_gp_slot2_encode, 0, Opcode_and_Slot_gp_slot0_encode, 0, 0, Opcode_and_Slot_dot_slot0_encode, Opcode_and_Slot_pq_slot2_encode, 0, Opcode_and_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_and_Slot_smod_slot0_encode, 0, 0, Opcode_and_Slot_llr_slot0_encode, Opcode_and_Slot_dual_slot2_encode, 0, Opcode_and_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_or_encode_fns[] = { + Opcode_or_Slot_inst_encode, 0, 0, Opcode_or_Slot_gp_slot2_encode, 0, Opcode_or_Slot_gp_slot0_encode, 0, 0, Opcode_or_Slot_dot_slot0_encode, Opcode_or_Slot_pq_slot2_encode, 0, Opcode_or_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_or_Slot_smod_slot0_encode, 0, 0, Opcode_or_Slot_llr_slot0_encode, Opcode_or_Slot_dual_slot2_encode, 0, Opcode_or_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_xor_encode_fns[] = { + Opcode_xor_Slot_inst_encode, 0, 0, Opcode_xor_Slot_gp_slot2_encode, 0, Opcode_xor_Slot_gp_slot0_encode, 0, 0, Opcode_xor_Slot_dot_slot0_encode, Opcode_xor_Slot_pq_slot2_encode, 0, Opcode_xor_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_xor_Slot_smod_slot0_encode, 0, 0, Opcode_xor_Slot_llr_slot0_encode, Opcode_xor_Slot_dual_slot2_encode, 0, Opcode_xor_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_beqi_encode_fns[] = { + Opcode_beqi_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_beqi_Slot_dual_slot2_encode, 0, Opcode_beqi_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bnei_encode_fns[] = { + Opcode_bnei_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bnei_Slot_dual_slot2_encode, 0, Opcode_bnei_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bgei_encode_fns[] = { + Opcode_bgei_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bgei_Slot_dual_slot2_encode, 0, Opcode_bgei_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_blti_encode_fns[] = { + Opcode_blti_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_blti_Slot_dual_slot2_encode, 0, Opcode_blti_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bbci_encode_fns[] = { + Opcode_bbci_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bbci_Slot_dual_slot2_encode, 0, Opcode_bbci_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bbsi_encode_fns[] = { + Opcode_bbsi_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bbsi_Slot_dual_slot2_encode, 0, Opcode_bbsi_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bgeui_encode_fns[] = { + Opcode_bgeui_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bgeui_Slot_dual_slot2_encode, 0, Opcode_bgeui_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bltui_encode_fns[] = { + Opcode_bltui_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bltui_Slot_dual_slot2_encode, 0, Opcode_bltui_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_beq_encode_fns[] = { + Opcode_beq_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_beq_Slot_dual_slot2_encode, 0, Opcode_beq_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bne_encode_fns[] = { + Opcode_bne_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bne_Slot_dual_slot2_encode, 0, Opcode_bne_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bge_encode_fns[] = { + Opcode_bge_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bge_Slot_dual_slot2_encode, 0, Opcode_bge_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_blt_encode_fns[] = { + Opcode_blt_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_blt_Slot_dual_slot2_encode, 0, Opcode_blt_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bgeu_encode_fns[] = { + Opcode_bgeu_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bgeu_Slot_dual_slot2_encode, 0, Opcode_bgeu_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bltu_encode_fns[] = { + Opcode_bltu_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bltu_Slot_dual_slot2_encode, 0, Opcode_bltu_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bany_encode_fns[] = { + Opcode_bany_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bany_Slot_dual_slot2_encode, 0, Opcode_bany_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bnone_encode_fns[] = { + Opcode_bnone_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bnone_Slot_dual_slot2_encode, 0, Opcode_bnone_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ball_encode_fns[] = { + Opcode_ball_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ball_Slot_dual_slot2_encode, 0, Opcode_ball_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bnall_encode_fns[] = { + Opcode_bnall_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bnall_Slot_dual_slot2_encode, 0, Opcode_bnall_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bbc_encode_fns[] = { + Opcode_bbc_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bbc_Slot_dual_slot2_encode, 0, Opcode_bbc_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bbs_encode_fns[] = { + Opcode_bbs_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bbs_Slot_dual_slot2_encode, 0, Opcode_bbs_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_beqz_encode_fns[] = { + Opcode_beqz_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_beqz_Slot_dual_slot2_encode, 0, Opcode_beqz_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bnez_encode_fns[] = { + Opcode_bnez_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bnez_Slot_dual_slot2_encode, 0, Opcode_bnez_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bgez_encode_fns[] = { + Opcode_bgez_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bgez_Slot_dual_slot2_encode, 0, Opcode_bgez_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_bltz_encode_fns[] = { + Opcode_bltz_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bltz_Slot_dual_slot2_encode, 0, Opcode_bltz_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_call0_encode_fns[] = { + Opcode_call0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_callx0_encode_fns[] = { + Opcode_callx0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_extui_encode_fns[] = { + Opcode_extui_Slot_inst_encode, 0, 0, Opcode_extui_Slot_gp_slot2_encode, 0, Opcode_extui_Slot_gp_slot0_encode, 0, 0, 0, Opcode_extui_Slot_pq_slot2_encode, 0, Opcode_extui_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_extui_Slot_smod_slot0_encode, 0, 0, 0, Opcode_extui_Slot_dual_slot2_encode, 0, Opcode_extui_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ill_encode_fns[] = { + Opcode_ill_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_j_encode_fns[] = { + Opcode_j_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_jx_encode_fns[] = { + Opcode_jx_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_l16ui_encode_fns[] = { + Opcode_l16ui_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_l16ui_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_l16si_encode_fns[] = { + Opcode_l16si_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_l16si_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_l32i_encode_fns[] = { + Opcode_l32i_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_l32i_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_l32r_encode_fns[] = { + Opcode_l32r_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_l32r_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_l8ui_encode_fns[] = { + Opcode_l8ui_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_l8ui_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_loop_encode_fns[] = { + Opcode_loop_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_loopnez_encode_fns[] = { + Opcode_loopnez_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_loopgtz_encode_fns[] = { + Opcode_loopgtz_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movi_encode_fns[] = { + Opcode_movi_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_movi_Slot_dual_slot2_encode, 0, Opcode_movi_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_moveqz_encode_fns[] = { + Opcode_moveqz_Slot_inst_encode, 0, 0, Opcode_moveqz_Slot_gp_slot2_encode, 0, Opcode_moveqz_Slot_gp_slot0_encode, 0, 0, 0, Opcode_moveqz_Slot_pq_slot2_encode, 0, Opcode_moveqz_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_moveqz_Slot_smod_slot0_encode, 0, 0, 0, Opcode_moveqz_Slot_dual_slot2_encode, 0, Opcode_moveqz_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_movnez_encode_fns[] = { + Opcode_movnez_Slot_inst_encode, 0, 0, Opcode_movnez_Slot_gp_slot2_encode, 0, Opcode_movnez_Slot_gp_slot0_encode, 0, 0, 0, Opcode_movnez_Slot_pq_slot2_encode, 0, Opcode_movnez_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_movnez_Slot_smod_slot0_encode, 0, 0, 0, Opcode_movnez_Slot_dual_slot2_encode, 0, Opcode_movnez_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_movltz_encode_fns[] = { + Opcode_movltz_Slot_inst_encode, 0, 0, Opcode_movltz_Slot_gp_slot2_encode, 0, Opcode_movltz_Slot_gp_slot0_encode, 0, 0, 0, Opcode_movltz_Slot_pq_slot2_encode, 0, Opcode_movltz_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_movltz_Slot_smod_slot0_encode, 0, 0, 0, Opcode_movltz_Slot_dual_slot2_encode, 0, Opcode_movltz_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_movgez_encode_fns[] = { + Opcode_movgez_Slot_inst_encode, 0, 0, Opcode_movgez_Slot_gp_slot2_encode, 0, Opcode_movgez_Slot_gp_slot0_encode, 0, 0, 0, Opcode_movgez_Slot_pq_slot2_encode, 0, Opcode_movgez_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_movgez_Slot_smod_slot0_encode, 0, 0, 0, Opcode_movgez_Slot_dual_slot2_encode, 0, Opcode_movgez_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_neg_encode_fns[] = { + Opcode_neg_Slot_inst_encode, 0, 0, Opcode_neg_Slot_gp_slot2_encode, 0, Opcode_neg_Slot_gp_slot0_encode, 0, 0, Opcode_neg_Slot_dot_slot0_encode, Opcode_neg_Slot_pq_slot2_encode, 0, Opcode_neg_Slot_pq_slot0_encode, 0, 0, Opcode_neg_Slot_acc2_slot0_encode, 0, 0, Opcode_neg_Slot_smod_slot0_encode, 0, 0, Opcode_neg_Slot_llr_slot0_encode, Opcode_neg_Slot_dual_slot2_encode, 0, Opcode_neg_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_abs_encode_fns[] = { + Opcode_abs_Slot_inst_encode, 0, 0, Opcode_abs_Slot_gp_slot2_encode, 0, Opcode_abs_Slot_gp_slot0_encode, 0, 0, 0, Opcode_abs_Slot_pq_slot2_encode, 0, Opcode_abs_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_abs_Slot_smod_slot0_encode, 0, 0, 0, Opcode_abs_Slot_dual_slot2_encode, 0, Opcode_abs_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_nop_encode_fns[] = { + Opcode_nop_Slot_inst_encode, 0, 0, Opcode_nop_Slot_gp_slot2_encode, Opcode_nop_Slot_gp_slot1_encode, Opcode_nop_Slot_gp_slot0_encode, Opcode_nop_Slot_dot_slot2_encode, Opcode_nop_Slot_dot_slot1_encode, Opcode_nop_Slot_dot_slot0_encode, Opcode_nop_Slot_pq_slot2_encode, Opcode_nop_Slot_pq_slot1_encode, Opcode_nop_Slot_pq_slot0_encode, Opcode_nop_Slot_acc2_slot2_encode, Opcode_nop_Slot_acc2_slot1_encode, Opcode_nop_Slot_acc2_slot0_encode, Opcode_nop_Slot_smod_slot2_encode, Opcode_nop_Slot_smod_slot1_encode, Opcode_nop_Slot_smod_slot0_encode, Opcode_nop_Slot_llr_slot2_encode, Opcode_nop_Slot_llr_slot1_encode, Opcode_nop_Slot_llr_slot0_encode, Opcode_nop_Slot_dual_slot2_encode, Opcode_nop_Slot_dual_slot1_encode, Opcode_nop_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ret_encode_fns[] = { + Opcode_ret_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s16i_encode_fns[] = { + Opcode_s16i_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_s16i_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_s32i_encode_fns[] = { + Opcode_s32i_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_s32i_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_s8i_encode_fns[] = { + Opcode_s8i_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_s8i_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ssr_encode_fns[] = { + Opcode_ssr_Slot_inst_encode, 0, 0, 0, 0, Opcode_ssr_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_ssr_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_ssr_Slot_smod_slot0_encode, 0, 0, 0, Opcode_ssr_Slot_dual_slot2_encode, 0, Opcode_ssr_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ssl_encode_fns[] = { + Opcode_ssl_Slot_inst_encode, 0, 0, 0, 0, Opcode_ssl_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_ssl_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_ssl_Slot_smod_slot0_encode, 0, 0, 0, Opcode_ssl_Slot_dual_slot2_encode, 0, Opcode_ssl_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ssa8l_encode_fns[] = { + Opcode_ssa8l_Slot_inst_encode, 0, 0, 0, 0, Opcode_ssa8l_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_ssa8l_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_ssa8l_Slot_smod_slot0_encode, 0, 0, 0, Opcode_ssa8l_Slot_dual_slot2_encode, 0, Opcode_ssa8l_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ssa8b_encode_fns[] = { + Opcode_ssa8b_Slot_inst_encode, 0, 0, 0, 0, Opcode_ssa8b_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_ssa8b_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_ssa8b_Slot_smod_slot0_encode, 0, 0, 0, Opcode_ssa8b_Slot_dual_slot2_encode, 0, Opcode_ssa8b_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ssai_encode_fns[] = { + Opcode_ssai_Slot_inst_encode, 0, 0, 0, 0, Opcode_ssai_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_ssai_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_ssai_Slot_smod_slot0_encode, 0, 0, 0, Opcode_ssai_Slot_dual_slot2_encode, 0, Opcode_ssai_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sll_encode_fns[] = { + Opcode_sll_Slot_inst_encode, 0, 0, Opcode_sll_Slot_gp_slot2_encode, 0, Opcode_sll_Slot_gp_slot0_encode, 0, 0, Opcode_sll_Slot_dot_slot0_encode, Opcode_sll_Slot_pq_slot2_encode, 0, Opcode_sll_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_sll_Slot_smod_slot0_encode, 0, 0, Opcode_sll_Slot_llr_slot0_encode, Opcode_sll_Slot_dual_slot2_encode, 0, Opcode_sll_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_src_encode_fns[] = { + Opcode_src_Slot_inst_encode, 0, 0, 0, 0, Opcode_src_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_src_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_src_Slot_smod_slot0_encode, 0, 0, 0, Opcode_src_Slot_dual_slot2_encode, 0, Opcode_src_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_srl_encode_fns[] = { + Opcode_srl_Slot_inst_encode, 0, 0, 0, 0, Opcode_srl_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_srl_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_srl_Slot_smod_slot0_encode, 0, 0, 0, Opcode_srl_Slot_dual_slot2_encode, 0, Opcode_srl_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sra_encode_fns[] = { + Opcode_sra_Slot_inst_encode, 0, 0, Opcode_sra_Slot_gp_slot2_encode, 0, Opcode_sra_Slot_gp_slot0_encode, 0, 0, Opcode_sra_Slot_dot_slot0_encode, Opcode_sra_Slot_pq_slot2_encode, 0, Opcode_sra_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_sra_Slot_smod_slot0_encode, 0, 0, Opcode_sra_Slot_llr_slot0_encode, Opcode_sra_Slot_dual_slot2_encode, 0, Opcode_sra_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_slli_encode_fns[] = { + Opcode_slli_Slot_inst_encode, 0, 0, 0, 0, Opcode_slli_Slot_gp_slot0_encode, 0, 0, Opcode_slli_Slot_dot_slot0_encode, 0, 0, Opcode_slli_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_slli_Slot_smod_slot0_encode, 0, 0, Opcode_slli_Slot_llr_slot0_encode, Opcode_slli_Slot_dual_slot2_encode, 0, Opcode_slli_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_srai_encode_fns[] = { + Opcode_srai_Slot_inst_encode, 0, 0, 0, 0, Opcode_srai_Slot_gp_slot0_encode, 0, 0, Opcode_srai_Slot_dot_slot0_encode, 0, 0, Opcode_srai_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_srai_Slot_smod_slot0_encode, 0, 0, Opcode_srai_Slot_llr_slot0_encode, Opcode_srai_Slot_dual_slot2_encode, 0, Opcode_srai_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_srli_encode_fns[] = { + Opcode_srli_Slot_inst_encode, 0, 0, 0, 0, Opcode_srli_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_srli_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_srli_Slot_smod_slot0_encode, 0, 0, 0, Opcode_srli_Slot_dual_slot2_encode, 0, Opcode_srli_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_memw_encode_fns[] = { + Opcode_memw_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_extw_encode_fns[] = { + Opcode_extw_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_isync_encode_fns[] = { + Opcode_isync_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsync_encode_fns[] = { + Opcode_rsync_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_esync_encode_fns[] = { + Opcode_esync_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dsync_encode_fns[] = { + Opcode_dsync_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsil_encode_fns[] = { + Opcode_rsil_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_lend_encode_fns[] = { + Opcode_rsr_lend_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_lend_encode_fns[] = { + Opcode_wsr_lend_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_lend_encode_fns[] = { + Opcode_xsr_lend_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_lcount_encode_fns[] = { + Opcode_rsr_lcount_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_lcount_encode_fns[] = { + Opcode_wsr_lcount_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_lcount_encode_fns[] = { + Opcode_xsr_lcount_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_lbeg_encode_fns[] = { + Opcode_rsr_lbeg_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_lbeg_encode_fns[] = { + Opcode_wsr_lbeg_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_lbeg_encode_fns[] = { + Opcode_xsr_lbeg_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_sar_encode_fns[] = { + Opcode_rsr_sar_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_sar_encode_fns[] = { + Opcode_wsr_sar_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_sar_encode_fns[] = { + Opcode_xsr_sar_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_litbase_encode_fns[] = { + Opcode_rsr_litbase_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_litbase_encode_fns[] = { + Opcode_wsr_litbase_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_litbase_encode_fns[] = { + Opcode_xsr_litbase_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_176_encode_fns[] = { + Opcode_rsr_176_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_176_encode_fns[] = { + Opcode_wsr_176_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_208_encode_fns[] = { + Opcode_rsr_208_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ps_encode_fns[] = { + Opcode_rsr_ps_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ps_encode_fns[] = { + Opcode_wsr_ps_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ps_encode_fns[] = { + Opcode_xsr_ps_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc1_encode_fns[] = { + Opcode_rsr_epc1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc1_encode_fns[] = { + Opcode_wsr_epc1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc1_encode_fns[] = { + Opcode_xsr_epc1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave1_encode_fns[] = { + Opcode_rsr_excsave1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave1_encode_fns[] = { + Opcode_wsr_excsave1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave1_encode_fns[] = { + Opcode_xsr_excsave1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc2_encode_fns[] = { + Opcode_rsr_epc2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc2_encode_fns[] = { + Opcode_wsr_epc2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc2_encode_fns[] = { + Opcode_xsr_epc2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave2_encode_fns[] = { + Opcode_rsr_excsave2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave2_encode_fns[] = { + Opcode_wsr_excsave2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave2_encode_fns[] = { + Opcode_xsr_excsave2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc3_encode_fns[] = { + Opcode_rsr_epc3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc3_encode_fns[] = { + Opcode_wsr_epc3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc3_encode_fns[] = { + Opcode_xsr_epc3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave3_encode_fns[] = { + Opcode_rsr_excsave3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave3_encode_fns[] = { + Opcode_wsr_excsave3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave3_encode_fns[] = { + Opcode_xsr_excsave3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc4_encode_fns[] = { + Opcode_rsr_epc4_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc4_encode_fns[] = { + Opcode_wsr_epc4_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc4_encode_fns[] = { + Opcode_xsr_epc4_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave4_encode_fns[] = { + Opcode_rsr_excsave4_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave4_encode_fns[] = { + Opcode_wsr_excsave4_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave4_encode_fns[] = { + Opcode_xsr_excsave4_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc5_encode_fns[] = { + Opcode_rsr_epc5_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc5_encode_fns[] = { + Opcode_wsr_epc5_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc5_encode_fns[] = { + Opcode_xsr_epc5_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave5_encode_fns[] = { + Opcode_rsr_excsave5_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave5_encode_fns[] = { + Opcode_wsr_excsave5_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave5_encode_fns[] = { + Opcode_xsr_excsave5_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc6_encode_fns[] = { + Opcode_rsr_epc6_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc6_encode_fns[] = { + Opcode_wsr_epc6_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc6_encode_fns[] = { + Opcode_xsr_epc6_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave6_encode_fns[] = { + Opcode_rsr_excsave6_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave6_encode_fns[] = { + Opcode_wsr_excsave6_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave6_encode_fns[] = { + Opcode_xsr_excsave6_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eps2_encode_fns[] = { + Opcode_rsr_eps2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eps2_encode_fns[] = { + Opcode_wsr_eps2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eps2_encode_fns[] = { + Opcode_xsr_eps2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eps3_encode_fns[] = { + Opcode_rsr_eps3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eps3_encode_fns[] = { + Opcode_wsr_eps3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eps3_encode_fns[] = { + Opcode_xsr_eps3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eps4_encode_fns[] = { + Opcode_rsr_eps4_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eps4_encode_fns[] = { + Opcode_wsr_eps4_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eps4_encode_fns[] = { + Opcode_xsr_eps4_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eps5_encode_fns[] = { + Opcode_rsr_eps5_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eps5_encode_fns[] = { + Opcode_wsr_eps5_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eps5_encode_fns[] = { + Opcode_xsr_eps5_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eps6_encode_fns[] = { + Opcode_rsr_eps6_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eps6_encode_fns[] = { + Opcode_wsr_eps6_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eps6_encode_fns[] = { + Opcode_xsr_eps6_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excvaddr_encode_fns[] = { + Opcode_rsr_excvaddr_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excvaddr_encode_fns[] = { + Opcode_wsr_excvaddr_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excvaddr_encode_fns[] = { + Opcode_xsr_excvaddr_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_depc_encode_fns[] = { + Opcode_rsr_depc_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_depc_encode_fns[] = { + Opcode_wsr_depc_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_depc_encode_fns[] = { + Opcode_xsr_depc_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_exccause_encode_fns[] = { + Opcode_rsr_exccause_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_exccause_encode_fns[] = { + Opcode_wsr_exccause_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_exccause_encode_fns[] = { + Opcode_xsr_exccause_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_prid_encode_fns[] = { + Opcode_rsr_prid_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_vecbase_encode_fns[] = { + Opcode_rsr_vecbase_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_vecbase_encode_fns[] = { + Opcode_wsr_vecbase_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_vecbase_encode_fns[] = { + Opcode_xsr_vecbase_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul16u_encode_fns[] = { + Opcode_mul16u_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul16s_encode_fns[] = { + Opcode_mul16s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfi_encode_fns[] = { + Opcode_rfi_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_waiti_encode_fns[] = { + Opcode_waiti_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_interrupt_encode_fns[] = { + Opcode_rsr_interrupt_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_intset_encode_fns[] = { + Opcode_wsr_intset_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_intclear_encode_fns[] = { + Opcode_wsr_intclear_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_intenable_encode_fns[] = { + Opcode_rsr_intenable_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_intenable_encode_fns[] = { + Opcode_wsr_intenable_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_intenable_encode_fns[] = { + Opcode_xsr_intenable_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_break_encode_fns[] = { + Opcode_break_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_break_n_encode_fns[] = { + 0, 0, Opcode_break_n_Slot_inst16b_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_dbreaka0_encode_fns[] = { + Opcode_rsr_dbreaka0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_dbreaka0_encode_fns[] = { + Opcode_wsr_dbreaka0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_dbreaka0_encode_fns[] = { + Opcode_xsr_dbreaka0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_dbreakc0_encode_fns[] = { + Opcode_rsr_dbreakc0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_dbreakc0_encode_fns[] = { + Opcode_wsr_dbreakc0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_dbreakc0_encode_fns[] = { + Opcode_xsr_dbreakc0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_dbreaka1_encode_fns[] = { + Opcode_rsr_dbreaka1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_dbreaka1_encode_fns[] = { + Opcode_wsr_dbreaka1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_dbreaka1_encode_fns[] = { + Opcode_xsr_dbreaka1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_dbreakc1_encode_fns[] = { + Opcode_rsr_dbreakc1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_dbreakc1_encode_fns[] = { + Opcode_wsr_dbreakc1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_dbreakc1_encode_fns[] = { + Opcode_xsr_dbreakc1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ibreaka0_encode_fns[] = { + Opcode_rsr_ibreaka0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ibreaka0_encode_fns[] = { + Opcode_wsr_ibreaka0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ibreaka0_encode_fns[] = { + Opcode_xsr_ibreaka0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ibreaka1_encode_fns[] = { + Opcode_rsr_ibreaka1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ibreaka1_encode_fns[] = { + Opcode_wsr_ibreaka1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ibreaka1_encode_fns[] = { + Opcode_xsr_ibreaka1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ibreakenable_encode_fns[] = { + Opcode_rsr_ibreakenable_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ibreakenable_encode_fns[] = { + Opcode_wsr_ibreakenable_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ibreakenable_encode_fns[] = { + Opcode_xsr_ibreakenable_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_debugcause_encode_fns[] = { + Opcode_rsr_debugcause_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_debugcause_encode_fns[] = { + Opcode_wsr_debugcause_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_debugcause_encode_fns[] = { + Opcode_xsr_debugcause_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_icount_encode_fns[] = { + Opcode_rsr_icount_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_icount_encode_fns[] = { + Opcode_wsr_icount_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_icount_encode_fns[] = { + Opcode_xsr_icount_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_icountlevel_encode_fns[] = { + Opcode_rsr_icountlevel_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_icountlevel_encode_fns[] = { + Opcode_wsr_icountlevel_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_icountlevel_encode_fns[] = { + Opcode_xsr_icountlevel_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ddr_encode_fns[] = { + Opcode_rsr_ddr_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ddr_encode_fns[] = { + Opcode_wsr_ddr_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ddr_encode_fns[] = { + Opcode_xsr_ddr_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfdo_encode_fns[] = { + Opcode_rfdo_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfdd_encode_fns[] = { + Opcode_rfdd_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_mmid_encode_fns[] = { + Opcode_wsr_mmid_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_andb_encode_fns[] = { + Opcode_andb_Slot_inst_encode, 0, 0, 0, 0, Opcode_andb_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_andb_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_andb_Slot_smod_slot0_encode, 0, 0, 0, Opcode_andb_Slot_dual_slot2_encode, 0, Opcode_andb_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_andbc_encode_fns[] = { + Opcode_andbc_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_orb_encode_fns[] = { + Opcode_orb_Slot_inst_encode, 0, 0, 0, 0, Opcode_orb_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_orb_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_orb_Slot_smod_slot0_encode, 0, 0, 0, Opcode_orb_Slot_dual_slot2_encode, 0, Opcode_orb_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_orbc_encode_fns[] = { + Opcode_orbc_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xorb_encode_fns[] = { + Opcode_xorb_Slot_inst_encode, 0, 0, 0, 0, Opcode_xorb_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_xorb_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_xorb_Slot_smod_slot0_encode, 0, 0, 0, Opcode_xorb_Slot_dual_slot2_encode, 0, Opcode_xorb_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_any4_encode_fns[] = { + Opcode_any4_Slot_inst_encode, 0, 0, 0, 0, Opcode_any4_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_any4_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_any4_Slot_smod_slot0_encode, 0, 0, 0, Opcode_any4_Slot_dual_slot2_encode, 0, Opcode_any4_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_all4_encode_fns[] = { + Opcode_all4_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_any8_encode_fns[] = { + Opcode_any8_Slot_inst_encode, 0, 0, 0, 0, Opcode_any8_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_any8_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_any8_Slot_smod_slot0_encode, 0, 0, 0, Opcode_any8_Slot_dual_slot2_encode, 0, Opcode_any8_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_all8_encode_fns[] = { + Opcode_all8_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bf_encode_fns[] = { + Opcode_bf_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bt_encode_fns[] = { + Opcode_bt_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movf_encode_fns[] = { + Opcode_movf_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movt_encode_fns[] = { + Opcode_movt_Slot_inst_encode, 0, 0, 0, 0, Opcode_movt_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_movt_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_movt_Slot_smod_slot0_encode, 0, 0, 0, Opcode_movt_Slot_dual_slot2_encode, 0, Opcode_movt_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_rsr_br_encode_fns[] = { + Opcode_rsr_br_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_br_encode_fns[] = { + Opcode_wsr_br_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_br_encode_fns[] = { + Opcode_xsr_br_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ccount_encode_fns[] = { + Opcode_rsr_ccount_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ccount_encode_fns[] = { + Opcode_wsr_ccount_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ccount_encode_fns[] = { + Opcode_xsr_ccount_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ccompare0_encode_fns[] = { + Opcode_rsr_ccompare0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ccompare0_encode_fns[] = { + Opcode_wsr_ccompare0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ccompare0_encode_fns[] = { + Opcode_xsr_ccompare0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ccompare1_encode_fns[] = { + Opcode_rsr_ccompare1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ccompare1_encode_fns[] = { + Opcode_wsr_ccompare1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ccompare1_encode_fns[] = { + Opcode_xsr_ccompare1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ipf_encode_fns[] = { + Opcode_ipf_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ihi_encode_fns[] = { + Opcode_ihi_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ipfl_encode_fns[] = { + Opcode_ipfl_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ihu_encode_fns[] = { + Opcode_ihu_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_iiu_encode_fns[] = { + Opcode_iiu_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_iii_encode_fns[] = { + Opcode_iii_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lict_encode_fns[] = { + Opcode_lict_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_licw_encode_fns[] = { + Opcode_licw_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sict_encode_fns[] = { + Opcode_sict_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sicw_encode_fns[] = { + Opcode_sicw_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dhwb_encode_fns[] = { + Opcode_dhwb_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dhwbi_encode_fns[] = { + Opcode_dhwbi_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_diwb_encode_fns[] = { + Opcode_diwb_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_diwbi_encode_fns[] = { + Opcode_diwbi_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dhi_encode_fns[] = { + Opcode_dhi_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dii_encode_fns[] = { + Opcode_dii_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dpfr_encode_fns[] = { + Opcode_dpfr_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dpfw_encode_fns[] = { + Opcode_dpfw_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dpfro_encode_fns[] = { + Opcode_dpfro_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dpfwo_encode_fns[] = { + Opcode_dpfwo_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dpfl_encode_fns[] = { + Opcode_dpfl_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dhu_encode_fns[] = { + Opcode_dhu_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_diu_encode_fns[] = { + Opcode_diu_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sdct_encode_fns[] = { + Opcode_sdct_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ldct_encode_fns[] = { + Opcode_ldct_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_idtlb_encode_fns[] = { + Opcode_idtlb_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_pdtlb_encode_fns[] = { + Opcode_pdtlb_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rdtlb0_encode_fns[] = { + Opcode_rdtlb0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rdtlb1_encode_fns[] = { + Opcode_rdtlb1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wdtlb_encode_fns[] = { + Opcode_wdtlb_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_iitlb_encode_fns[] = { + Opcode_iitlb_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_pitlb_encode_fns[] = { + Opcode_pitlb_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ritlb0_encode_fns[] = { + Opcode_ritlb0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ritlb1_encode_fns[] = { + Opcode_ritlb1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_witlb_encode_fns[] = { + Opcode_witlb_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_cpenable_encode_fns[] = { + Opcode_rsr_cpenable_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_cpenable_encode_fns[] = { + Opcode_wsr_cpenable_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_cpenable_encode_fns[] = { + Opcode_xsr_cpenable_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_clamps_encode_fns[] = { + Opcode_clamps_Slot_inst_encode, 0, 0, 0, 0, Opcode_clamps_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_clamps_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_clamps_Slot_smod_slot0_encode, 0, 0, 0, Opcode_clamps_Slot_dual_slot2_encode, 0, Opcode_clamps_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_min_encode_fns[] = { + Opcode_min_Slot_inst_encode, 0, 0, 0, 0, Opcode_min_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_min_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_min_Slot_smod_slot0_encode, 0, 0, 0, Opcode_min_Slot_dual_slot2_encode, 0, Opcode_min_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_max_encode_fns[] = { + Opcode_max_Slot_inst_encode, 0, 0, 0, 0, Opcode_max_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_max_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_max_Slot_smod_slot0_encode, 0, 0, 0, Opcode_max_Slot_dual_slot2_encode, 0, Opcode_max_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_minu_encode_fns[] = { + Opcode_minu_Slot_inst_encode, 0, 0, 0, 0, Opcode_minu_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_minu_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_minu_Slot_smod_slot0_encode, 0, 0, 0, Opcode_minu_Slot_dual_slot2_encode, 0, Opcode_minu_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_maxu_encode_fns[] = { + Opcode_maxu_Slot_inst_encode, 0, 0, 0, 0, Opcode_maxu_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_maxu_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_maxu_Slot_smod_slot0_encode, 0, 0, 0, Opcode_maxu_Slot_dual_slot2_encode, 0, Opcode_maxu_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_nsa_encode_fns[] = { + Opcode_nsa_Slot_inst_encode, 0, 0, 0, 0, Opcode_nsa_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_nsa_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_nsa_Slot_smod_slot0_encode, 0, 0, 0, Opcode_nsa_Slot_dual_slot2_encode, 0, Opcode_nsa_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_nsau_encode_fns[] = { + Opcode_nsau_Slot_inst_encode, 0, 0, 0, 0, Opcode_nsau_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_nsau_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_nsau_Slot_smod_slot0_encode, 0, 0, 0, Opcode_nsau_Slot_dual_slot2_encode, 0, Opcode_nsau_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sext_encode_fns[] = { + Opcode_sext_Slot_inst_encode, 0, 0, 0, 0, Opcode_sext_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_sext_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_sext_Slot_smod_slot0_encode, 0, 0, 0, Opcode_sext_Slot_dual_slot2_encode, 0, Opcode_sext_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_l32ai_encode_fns[] = { + Opcode_l32ai_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s32ri_encode_fns[] = { + Opcode_s32ri_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s32c1i_encode_fns[] = { + Opcode_s32c1i_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_scompare1_encode_fns[] = { + Opcode_rsr_scompare1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_scompare1_encode_fns[] = { + Opcode_wsr_scompare1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_scompare1_encode_fns[] = { + Opcode_xsr_scompare1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_atomctl_encode_fns[] = { + Opcode_rsr_atomctl_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_atomctl_encode_fns[] = { + Opcode_wsr_atomctl_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_atomctl_encode_fns[] = { + Opcode_xsr_atomctl_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rer_encode_fns[] = { + Opcode_rer_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wer_encode_fns[] = { + Opcode_wer_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_fcr_encode_fns[] = { + Opcode_rur_fcr_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_fcr_encode_fns[] = { + Opcode_wur_fcr_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_fsr_encode_fns[] = { + Opcode_rur_fsr_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_fsr_encode_fns[] = { + Opcode_wur_fsr_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_add_s_encode_fns[] = { + Opcode_add_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_add_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sub_s_encode_fns[] = { + Opcode_sub_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_sub_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_mul_s_encode_fns[] = { + Opcode_mul_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_mul_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_madd_s_encode_fns[] = { + Opcode_madd_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_madd_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_msub_s_encode_fns[] = { + Opcode_msub_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_msub_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_movf_s_encode_fns[] = { + Opcode_movf_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_movf_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_movt_s_encode_fns[] = { + Opcode_movt_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_movt_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_moveqz_s_encode_fns[] = { + Opcode_moveqz_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_moveqz_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_movnez_s_encode_fns[] = { + Opcode_movnez_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_movnez_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_movltz_s_encode_fns[] = { + Opcode_movltz_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_movltz_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_movgez_s_encode_fns[] = { + Opcode_movgez_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_movgez_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_abs_s_encode_fns[] = { + Opcode_abs_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_abs_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_mov_s_encode_fns[] = { + Opcode_mov_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_mov_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_neg_s_encode_fns[] = { + Opcode_neg_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_neg_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_un_s_encode_fns[] = { + Opcode_un_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_un_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_oeq_s_encode_fns[] = { + Opcode_oeq_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_oeq_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ueq_s_encode_fns[] = { + Opcode_ueq_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ueq_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_olt_s_encode_fns[] = { + Opcode_olt_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_olt_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ult_s_encode_fns[] = { + Opcode_ult_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ult_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ole_s_encode_fns[] = { + Opcode_ole_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ole_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ule_s_encode_fns[] = { + Opcode_ule_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ule_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_float_s_encode_fns[] = { + Opcode_float_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_float_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ufloat_s_encode_fns[] = { + Opcode_ufloat_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ufloat_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_round_s_encode_fns[] = { + Opcode_round_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_round_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ceil_s_encode_fns[] = { + Opcode_ceil_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ceil_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_floor_s_encode_fns[] = { + Opcode_floor_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_floor_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_trunc_s_encode_fns[] = { + Opcode_trunc_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_trunc_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_utrunc_s_encode_fns[] = { + Opcode_utrunc_s_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_utrunc_s_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_rfr_encode_fns[] = { + Opcode_rfr_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_rfr_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_wfr_encode_fns[] = { + Opcode_wfr_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lsi_encode_fns[] = { + Opcode_lsi_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lsi_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lsiu_encode_fns[] = { + Opcode_lsiu_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lsiu_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lsx_encode_fns[] = { + Opcode_lsx_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lsxu_encode_fns[] = { + Opcode_lsxu_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lsxu_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ssi_encode_fns[] = { + Opcode_ssi_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ssi_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ssiu_encode_fns[] = { + Opcode_ssiu_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ssiu_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ssx_encode_fns[] = { + Opcode_ssx_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ssx_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ssxu_encode_fns[] = { + Opcode_ssxu_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ssxu_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_get_argmax_encode_fns[] = { + Opcode_get_argmax_Slot_inst_encode, 0, 0, Opcode_get_argmax_Slot_gp_slot2_encode, 0, 0, Opcode_get_argmax_Slot_dot_slot2_encode, 0, 0, Opcode_get_argmax_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_get_argmax_Slot_smod_slot2_encode, 0, 0, Opcode_get_argmax_Slot_llr_slot2_encode, 0, 0, Opcode_get_argmax_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_get_hsar_encode_fns[] = { + Opcode_get_hsar_Slot_inst_encode, 0, 0, Opcode_get_hsar_Slot_gp_slot2_encode, 0, Opcode_get_hsar_Slot_gp_slot0_encode, Opcode_get_hsar_Slot_dot_slot2_encode, 0, Opcode_get_hsar_Slot_dot_slot0_encode, Opcode_get_hsar_Slot_pq_slot2_encode, 0, Opcode_get_hsar_Slot_pq_slot0_encode, 0, 0, 0, Opcode_get_hsar_Slot_smod_slot2_encode, 0, Opcode_get_hsar_Slot_smod_slot0_encode, Opcode_get_hsar_Slot_llr_slot2_encode, 0, Opcode_get_hsar_Slot_llr_slot0_encode, Opcode_get_hsar_Slot_dual_slot2_encode, 0, Opcode_get_hsar_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_get_hsar2sar_encode_fns[] = { + Opcode_get_hsar2sar_Slot_inst_encode, 0, 0, Opcode_get_hsar2sar_Slot_gp_slot2_encode, 0, Opcode_get_hsar2sar_Slot_gp_slot0_encode, Opcode_get_hsar2sar_Slot_dot_slot2_encode, 0, Opcode_get_hsar2sar_Slot_dot_slot0_encode, Opcode_get_hsar2sar_Slot_pq_slot2_encode, 0, Opcode_get_hsar2sar_Slot_pq_slot0_encode, 0, 0, 0, Opcode_get_hsar2sar_Slot_smod_slot2_encode, 0, Opcode_get_hsar2sar_Slot_smod_slot0_encode, Opcode_get_hsar2sar_Slot_llr_slot2_encode, 0, Opcode_get_hsar2sar_Slot_llr_slot0_encode, Opcode_get_hsar2sar_Slot_dual_slot2_encode, 0, Opcode_get_hsar2sar_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_get_interp_ext_n_encode_fns[] = { + Opcode_get_interp_ext_n_Slot_inst_encode, 0, 0, 0, 0, Opcode_get_interp_ext_n_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_interp_ext_n_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_interp_ext_n_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_interp_ext_n_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_get_interp_ext_l_encode_fns[] = { + Opcode_get_interp_ext_l_Slot_inst_encode, 0, 0, 0, 0, Opcode_get_interp_ext_l_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_interp_ext_l_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_interp_ext_l_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_interp_ext_l_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_get_llr_buf_encode_fns[] = { + Opcode_get_llr_buf_Slot_inst_encode, 0, 0, 0, 0, Opcode_get_llr_buf_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_llr_buf_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_llr_buf_Slot_smod_slot0_encode, 0, 0, Opcode_get_llr_buf_Slot_llr_slot0_encode, 0, 0, Opcode_get_llr_buf_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_get_llr_pos_encode_fns[] = { + Opcode_get_llr_pos_Slot_inst_encode, 0, 0, 0, 0, Opcode_get_llr_pos_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_llr_pos_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_llr_pos_Slot_smod_slot0_encode, 0, 0, Opcode_get_llr_pos_Slot_llr_slot0_encode, 0, 0, Opcode_get_llr_pos_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_get_max_encode_fns[] = { + Opcode_get_max_Slot_inst_encode, 0, 0, Opcode_get_max_Slot_gp_slot2_encode, 0, 0, Opcode_get_max_Slot_dot_slot2_encode, 0, 0, Opcode_get_max_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_get_max_Slot_smod_slot2_encode, 0, 0, Opcode_get_max_Slot_llr_slot2_encode, 0, 0, Opcode_get_max_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_get_nco_encode_fns[] = { + Opcode_get_nco_Slot_inst_encode, 0, 0, Opcode_get_nco_Slot_gp_slot2_encode, 0, 0, Opcode_get_nco_Slot_dot_slot2_encode, 0, 0, Opcode_get_nco_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_get_nco_Slot_smod_slot2_encode, 0, 0, Opcode_get_nco_Slot_llr_slot2_encode, 0, 0, Opcode_get_nco_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_get_perm_reg_encode_fns[] = { + 0, 0, 0, 0, 0, Opcode_get_perm_reg_Slot_gp_slot0_encode, 0, 0, Opcode_get_perm_reg_Slot_dot_slot0_encode, 0, 0, Opcode_get_perm_reg_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_perm_reg_Slot_smod_slot0_encode, 0, 0, Opcode_get_perm_reg_Slot_llr_slot0_encode, 0, 0, Opcode_get_perm_reg_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_get_phasor_n_encode_fns[] = { + Opcode_get_phasor_n_Slot_inst_encode, 0, 0, 0, 0, Opcode_get_phasor_n_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_phasor_n_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_phasor_n_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_phasor_n_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_get_phasor_offset_encode_fns[] = { + Opcode_get_phasor_offset_Slot_inst_encode, 0, 0, 0, 0, Opcode_get_phasor_offset_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_phasor_offset_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_phasor_offset_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_phasor_offset_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_get_sar_encode_fns[] = { + Opcode_get_sar_Slot_inst_encode, 0, 0, Opcode_get_sar_Slot_gp_slot2_encode, 0, Opcode_get_sar_Slot_gp_slot0_encode, Opcode_get_sar_Slot_dot_slot2_encode, 0, Opcode_get_sar_Slot_dot_slot0_encode, Opcode_get_sar_Slot_pq_slot2_encode, 0, Opcode_get_sar_Slot_pq_slot0_encode, 0, 0, 0, Opcode_get_sar_Slot_smod_slot2_encode, 0, Opcode_get_sar_Slot_smod_slot0_encode, Opcode_get_sar_Slot_llr_slot2_encode, 0, Opcode_get_sar_Slot_llr_slot0_encode, Opcode_get_sar_Slot_dual_slot2_encode, 0, Opcode_get_sar_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_get_scale_reg_encode_fns[] = { + Opcode_get_scale_reg_Slot_inst_encode, 0, 0, 0, 0, Opcode_get_scale_reg_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_scale_reg_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_scale_reg_Slot_smod_slot0_encode, 0, 0, Opcode_get_scale_reg_Slot_llr_slot0_encode, 0, 0, Opcode_get_scale_reg_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_get_smod_buf_encode_fns[] = { + Opcode_get_smod_buf_Slot_inst_encode, 0, 0, 0, 0, Opcode_get_smod_buf_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_smod_buf_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_smod_buf_Slot_smod_slot0_encode, 0, 0, Opcode_get_smod_buf_Slot_llr_slot0_encode, 0, 0, Opcode_get_smod_buf_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_get_smod_offset_table_encode_fns[] = { + Opcode_get_smod_offset_table_Slot_inst_encode, 0, 0, 0, 0, Opcode_get_smod_offset_table_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_smod_offset_table_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_smod_offset_table_Slot_smod_slot0_encode, 0, 0, Opcode_get_smod_offset_table_Slot_llr_slot0_encode, 0, 0, Opcode_get_smod_offset_table_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_get_smod_pos_encode_fns[] = { + Opcode_get_smod_pos_Slot_inst_encode, 0, 0, 0, 0, Opcode_get_smod_pos_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_smod_pos_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_smod_pos_Slot_smod_slot0_encode, 0, 0, Opcode_get_smod_pos_Slot_llr_slot0_encode, 0, 0, Opcode_get_smod_pos_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_get_sov_encode_fns[] = { + Opcode_get_sov_Slot_inst_encode, 0, 0, 0, 0, Opcode_get_sov_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_sov_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_sov_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_sov_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_get_wght_encode_fns[] = { + Opcode_get_wght_Slot_inst_encode, 0, 0, 0, 0, Opcode_get_wght_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_wght_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_get_wght_Slot_smod_slot0_encode, 0, 0, Opcode_get_wght_Slot_llr_slot0_encode, 0, 0, Opcode_get_wght_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_set_argmax_encode_fns[] = { + Opcode_set_argmax_Slot_inst_encode, 0, 0, Opcode_set_argmax_Slot_gp_slot2_encode, 0, 0, Opcode_set_argmax_Slot_dot_slot2_encode, 0, 0, Opcode_set_argmax_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_set_argmax_Slot_smod_slot2_encode, 0, 0, Opcode_set_argmax_Slot_llr_slot2_encode, 0, 0, Opcode_set_argmax_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_set_ext_regs_encode_fns[] = { + Opcode_set_ext_regs_Slot_inst_encode, 0, 0, Opcode_set_ext_regs_Slot_gp_slot2_encode, 0, 0, Opcode_set_ext_regs_Slot_dot_slot2_encode, 0, 0, Opcode_set_ext_regs_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_set_ext_regs_Slot_smod_slot2_encode, 0, 0, Opcode_set_ext_regs_Slot_llr_slot2_encode, 0, 0, Opcode_set_ext_regs_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_set_hsar_encode_fns[] = { + 0, 0, 0, Opcode_set_hsar_Slot_gp_slot2_encode, 0, 0, Opcode_set_hsar_Slot_dot_slot2_encode, 0, 0, Opcode_set_hsar_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_set_hsar_Slot_smod_slot2_encode, 0, 0, Opcode_set_hsar_Slot_llr_slot2_encode, 0, 0, Opcode_set_hsar_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_set_llr_buf_encode_fns[] = { + Opcode_set_llr_buf_Slot_inst_encode, 0, 0, 0, 0, Opcode_set_llr_buf_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_llr_buf_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_llr_buf_Slot_smod_slot0_encode, 0, 0, Opcode_set_llr_buf_Slot_llr_slot0_encode, 0, 0, Opcode_set_llr_buf_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_set_llr_pos_encode_fns[] = { + Opcode_set_llr_pos_Slot_inst_encode, 0, 0, 0, 0, Opcode_set_llr_pos_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_llr_pos_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_llr_pos_Slot_smod_slot0_encode, 0, 0, Opcode_set_llr_pos_Slot_llr_slot0_encode, 0, 0, Opcode_set_llr_pos_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_set_max_encode_fns[] = { + Opcode_set_max_Slot_inst_encode, 0, 0, Opcode_set_max_Slot_gp_slot2_encode, 0, 0, Opcode_set_max_Slot_dot_slot2_encode, 0, 0, Opcode_set_max_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_set_max_Slot_smod_slot2_encode, 0, 0, Opcode_set_max_Slot_llr_slot2_encode, 0, 0, Opcode_set_max_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_set_nco_encode_fns[] = { + Opcode_set_nco_Slot_inst_encode, 0, 0, Opcode_set_nco_Slot_gp_slot2_encode, 0, 0, Opcode_set_nco_Slot_dot_slot2_encode, 0, 0, Opcode_set_nco_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_set_nco_Slot_smod_slot2_encode, 0, 0, Opcode_set_nco_Slot_llr_slot2_encode, 0, 0, Opcode_set_nco_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_set_perm_reg_encode_fns[] = { + 0, 0, 0, 0, 0, Opcode_set_perm_reg_Slot_gp_slot0_encode, 0, 0, Opcode_set_perm_reg_Slot_dot_slot0_encode, 0, 0, Opcode_set_perm_reg_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_perm_reg_Slot_smod_slot0_encode, 0, 0, Opcode_set_perm_reg_Slot_llr_slot0_encode, 0, 0, Opcode_set_perm_reg_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_set_phasor_n_encode_fns[] = { + Opcode_set_phasor_n_Slot_inst_encode, 0, 0, 0, 0, Opcode_set_phasor_n_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_phasor_n_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_phasor_n_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_phasor_n_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_set_phasor_offset_encode_fns[] = { + Opcode_set_phasor_offset_Slot_inst_encode, 0, 0, 0, 0, Opcode_set_phasor_offset_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_phasor_offset_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_phasor_offset_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_phasor_offset_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_set_sar_encode_fns[] = { + Opcode_set_sar_Slot_inst_encode, 0, 0, Opcode_set_sar_Slot_gp_slot2_encode, 0, Opcode_set_sar_Slot_gp_slot0_encode, Opcode_set_sar_Slot_dot_slot2_encode, 0, Opcode_set_sar_Slot_dot_slot0_encode, Opcode_set_sar_Slot_pq_slot2_encode, 0, Opcode_set_sar_Slot_pq_slot0_encode, 0, 0, 0, Opcode_set_sar_Slot_smod_slot2_encode, 0, Opcode_set_sar_Slot_smod_slot0_encode, Opcode_set_sar_Slot_llr_slot2_encode, 0, Opcode_set_sar_Slot_llr_slot0_encode, Opcode_set_sar_Slot_dual_slot2_encode, 0, Opcode_set_sar_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_set_scale_reg_encode_fns[] = { + Opcode_set_scale_reg_Slot_inst_encode, 0, 0, 0, 0, Opcode_set_scale_reg_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_scale_reg_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_scale_reg_Slot_smod_slot0_encode, 0, 0, Opcode_set_scale_reg_Slot_llr_slot0_encode, 0, 0, Opcode_set_scale_reg_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_set_smod_buf_encode_fns[] = { + Opcode_set_smod_buf_Slot_inst_encode, 0, 0, 0, 0, Opcode_set_smod_buf_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_smod_buf_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_smod_buf_Slot_smod_slot0_encode, 0, 0, Opcode_set_smod_buf_Slot_llr_slot0_encode, 0, 0, Opcode_set_smod_buf_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_set_smod_offset_table_encode_fns[] = { + Opcode_set_smod_offset_table_Slot_inst_encode, 0, 0, 0, 0, Opcode_set_smod_offset_table_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_smod_offset_table_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_smod_offset_table_Slot_smod_slot0_encode, 0, 0, Opcode_set_smod_offset_table_Slot_llr_slot0_encode, 0, 0, Opcode_set_smod_offset_table_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_set_smod_pos_encode_fns[] = { + Opcode_set_smod_pos_Slot_inst_encode, 0, 0, 0, 0, Opcode_set_smod_pos_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_smod_pos_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_smod_pos_Slot_smod_slot0_encode, 0, 0, Opcode_set_smod_pos_Slot_llr_slot0_encode, 0, 0, Opcode_set_smod_pos_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_set_sov_encode_fns[] = { + Opcode_set_sov_Slot_inst_encode, 0, 0, 0, 0, Opcode_set_sov_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_sov_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_sov_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_sov_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_set_wght_encode_fns[] = { + Opcode_set_wght_Slot_inst_encode, 0, 0, 0, 0, Opcode_set_wght_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_wght_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_set_wght_Slot_smod_slot0_encode, 0, 0, Opcode_set_wght_Slot_llr_slot0_encode, 0, 0, Opcode_set_wght_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lac2x32_encode_fns[] = { + Opcode_lac2x32_Slot_inst_encode, 0, 0, 0, 0, Opcode_lac2x32_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_lac2x32_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lac2x32_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lac2x64_0_encode_fns[] = { + Opcode_lac2x64_0_Slot_inst_encode, 0, 0, 0, 0, Opcode_lac2x64_0_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_lac2x64_0_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lac2x64_0_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lac2x64_1_encode_fns[] = { + Opcode_lac2x64_1_Slot_inst_encode, 0, 0, 0, 0, Opcode_lac2x64_1_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_lac2x64_1_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lac2x64_1_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lac2x64_2_encode_fns[] = { + Opcode_lac2x64_2_Slot_inst_encode, 0, 0, 0, 0, Opcode_lac2x64_2_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_lac2x64_2_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lac2x64_2_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lac2x64_3_encode_fns[] = { + Opcode_lac2x64_3_Slot_inst_encode, 0, 0, 0, 0, Opcode_lac2x64_3_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_lac2x64_3_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lac2x64_3_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lac32_r_encode_fns[] = { + Opcode_lac32_r_Slot_inst_encode, 0, 0, 0, 0, Opcode_lac32_r_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_lac32_r_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lac32_r_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lac_ih_encode_fns[] = { + Opcode_lac_ih_Slot_inst_encode, 0, 0, 0, 0, Opcode_lac_ih_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_lac_ih_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lac_ih_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lac_il_encode_fns[] = { + Opcode_lac_il_Slot_inst_encode, 0, 0, 0, 0, Opcode_lac_il_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_lac_il_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lac_il_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lac_rh_encode_fns[] = { + Opcode_lac_rh_Slot_inst_encode, 0, 0, 0, 0, Opcode_lac_rh_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_lac_rh_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lac_rh_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lac_rl_encode_fns[] = { + Opcode_lac_rl_Slot_inst_encode, 0, 0, 0, 0, Opcode_lac_rl_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_lac_rl_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lac_rl_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lcm_encode_fns[] = { + Opcode_lcm_Slot_inst_encode, 0, 0, 0, 0, Opcode_lcm_Slot_gp_slot0_encode, 0, 0, Opcode_lcm_Slot_dot_slot0_encode, 0, 0, Opcode_lcm_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_lcm_Slot_smod_slot0_encode, 0, 0, Opcode_lcm_Slot_llr_slot0_encode, 0, 0, Opcode_lcm_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lcm_pinc_encode_fns[] = { + Opcode_lcm_pinc_Slot_inst_encode, 0, 0, 0, 0, Opcode_lcm_pinc_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_lcm_pinc_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_lcm_pinc_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_lcm_pinc_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lcm_pinc_x_encode_fns[] = { + Opcode_lcm_pinc_x_Slot_inst_encode, 0, 0, 0, 0, Opcode_lcm_pinc_x_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_lcm_pinc_x_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_lcm_pinc_x_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_lcm_pinc_x_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lcm_u_encode_fns[] = { + Opcode_lcm_u_Slot_inst_encode, 0, 0, 0, 0, Opcode_lcm_u_Slot_gp_slot0_encode, 0, 0, Opcode_lcm_u_Slot_dot_slot0_encode, 0, 0, Opcode_lcm_u_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_lcm_u_Slot_smod_slot0_encode, 0, 0, Opcode_lcm_u_Slot_llr_slot0_encode, 0, 0, Opcode_lcm_u_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lcm_x_encode_fns[] = { + Opcode_lcm_x_Slot_inst_encode, 0, 0, 0, 0, Opcode_lcm_x_Slot_gp_slot0_encode, 0, 0, Opcode_lcm_x_Slot_dot_slot0_encode, 0, 0, Opcode_lcm_x_Slot_pq_slot0_encode, 0, 0, Opcode_lcm_x_Slot_acc2_slot0_encode, 0, 0, Opcode_lcm_x_Slot_smod_slot0_encode, 0, 0, Opcode_lcm_x_Slot_llr_slot0_encode, 0, 0, Opcode_lcm_x_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lcm_xu_encode_fns[] = { + Opcode_lcm_xu_Slot_inst_encode, 0, 0, 0, 0, Opcode_lcm_xu_Slot_gp_slot0_encode, 0, 0, Opcode_lcm_xu_Slot_dot_slot0_encode, 0, 0, Opcode_lcm_xu_Slot_pq_slot0_encode, 0, 0, Opcode_lcm_xu_Slot_acc2_slot0_encode, 0, 0, Opcode_lcm_xu_Slot_smod_slot0_encode, 0, 0, Opcode_lcm_xu_Slot_llr_slot0_encode, 0, 0, Opcode_lcm_xu_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lp_encode_fns[] = { + Opcode_lp_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lp_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lp_x_encode_fns[] = { + Opcode_lp_x_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lp_x_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lq_encode_fns[] = { + Opcode_lq_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lq_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lq_x_encode_fns[] = { + Opcode_lq_x_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lq_x_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lut0_encode_fns[] = { + Opcode_lut0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lut0_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lut1_encode_fns[] = { + Opcode_lut1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lut1_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lut2_encode_fns[] = { + Opcode_lut2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lut2_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lut3_encode_fns[] = { + Opcode_lut3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_lut3_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sac2x32_encode_fns[] = { + Opcode_sac2x32_Slot_inst_encode, 0, 0, 0, 0, Opcode_sac2x32_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_sac2x32_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_sac2x32_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sac2x64_0_encode_fns[] = { + Opcode_sac2x64_0_Slot_inst_encode, 0, 0, 0, 0, Opcode_sac2x64_0_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_sac2x64_0_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_sac2x64_0_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sac2x64_1_encode_fns[] = { + Opcode_sac2x64_1_Slot_inst_encode, 0, 0, 0, 0, Opcode_sac2x64_1_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_sac2x64_1_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_sac2x64_1_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sac2x64_2_encode_fns[] = { + Opcode_sac2x64_2_Slot_inst_encode, 0, 0, 0, 0, Opcode_sac2x64_2_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_sac2x64_2_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_sac2x64_2_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sac2x64_3_encode_fns[] = { + Opcode_sac2x64_3_Slot_inst_encode, 0, 0, 0, 0, Opcode_sac2x64_3_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_sac2x64_3_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_sac2x64_3_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sac32_r_encode_fns[] = { + Opcode_sac32_r_Slot_inst_encode, 0, 0, 0, 0, Opcode_sac32_r_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_sac32_r_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_sac32_r_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sac_ih_encode_fns[] = { + Opcode_sac_ih_Slot_inst_encode, 0, 0, 0, 0, Opcode_sac_ih_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_sac_ih_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_sac_ih_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sac_il_encode_fns[] = { + Opcode_sac_il_Slot_inst_encode, 0, 0, 0, 0, Opcode_sac_il_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_sac_il_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_sac_il_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sac_rh_encode_fns[] = { + Opcode_sac_rh_Slot_inst_encode, 0, 0, 0, 0, Opcode_sac_rh_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_sac_rh_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_sac_rh_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sac_rl_encode_fns[] = { + Opcode_sac_rl_Slot_inst_encode, 0, 0, 0, 0, Opcode_sac_rl_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_sac_rl_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_sac_rl_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_scm_encode_fns[] = { + Opcode_scm_Slot_inst_encode, 0, 0, 0, 0, Opcode_scm_Slot_gp_slot0_encode, 0, 0, Opcode_scm_Slot_dot_slot0_encode, 0, 0, Opcode_scm_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_scm_Slot_smod_slot0_encode, 0, 0, Opcode_scm_Slot_llr_slot0_encode, 0, 0, Opcode_scm_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_scm_pinc_encode_fns[] = { + Opcode_scm_pinc_Slot_inst_encode, 0, 0, 0, 0, Opcode_scm_pinc_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_scm_pinc_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_scm_pinc_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_scm_pinc_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_scm_pinc_x_encode_fns[] = { + Opcode_scm_pinc_x_Slot_inst_encode, 0, 0, 0, 0, Opcode_scm_pinc_x_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_scm_pinc_x_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_scm_pinc_x_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_scm_pinc_x_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_scm_u_encode_fns[] = { + Opcode_scm_u_Slot_inst_encode, 0, 0, 0, 0, Opcode_scm_u_Slot_gp_slot0_encode, 0, 0, Opcode_scm_u_Slot_dot_slot0_encode, 0, 0, Opcode_scm_u_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_scm_u_Slot_smod_slot0_encode, 0, 0, Opcode_scm_u_Slot_llr_slot0_encode, 0, 0, Opcode_scm_u_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_scm_x_encode_fns[] = { + Opcode_scm_x_Slot_inst_encode, 0, 0, 0, 0, Opcode_scm_x_Slot_gp_slot0_encode, 0, 0, Opcode_scm_x_Slot_dot_slot0_encode, 0, 0, Opcode_scm_x_Slot_pq_slot0_encode, 0, 0, Opcode_scm_x_Slot_acc2_slot0_encode, 0, 0, Opcode_scm_x_Slot_smod_slot0_encode, 0, 0, Opcode_scm_x_Slot_llr_slot0_encode, 0, 0, Opcode_scm_x_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_scm_xu_encode_fns[] = { + Opcode_scm_xu_Slot_inst_encode, 0, 0, 0, 0, Opcode_scm_xu_Slot_gp_slot0_encode, 0, 0, Opcode_scm_xu_Slot_dot_slot0_encode, 0, 0, Opcode_scm_xu_Slot_pq_slot0_encode, 0, 0, Opcode_scm_xu_Slot_acc2_slot0_encode, 0, 0, Opcode_scm_xu_Slot_smod_slot0_encode, 0, 0, Opcode_scm_xu_Slot_llr_slot0_encode, 0, 0, Opcode_scm_xu_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_store_p_encode_fns[] = { + Opcode_store_p_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_store_p_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_store_p_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_store_q_encode_fns[] = { + Opcode_store_q_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_store_q_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_store_q_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ar2cm_dup_encode_fns[] = { + Opcode_ar2cm_dup_Slot_inst_encode, 0, 0, Opcode_ar2cm_dup_Slot_gp_slot2_encode, 0, Opcode_ar2cm_dup_Slot_gp_slot0_encode, Opcode_ar2cm_dup_Slot_dot_slot2_encode, 0, Opcode_ar2cm_dup_Slot_dot_slot0_encode, Opcode_ar2cm_dup_Slot_pq_slot2_encode, 0, Opcode_ar2cm_dup_Slot_pq_slot0_encode, 0, 0, 0, Opcode_ar2cm_dup_Slot_smod_slot2_encode, 0, Opcode_ar2cm_dup_Slot_smod_slot0_encode, Opcode_ar2cm_dup_Slot_llr_slot2_encode, 0, Opcode_ar2cm_dup_Slot_llr_slot0_encode, Opcode_ar2cm_dup_Slot_dual_slot2_encode, 0, Opcode_ar2cm_dup_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ar2cm_ln_encode_fns[] = { + Opcode_ar2cm_ln_Slot_inst_encode, 0, 0, Opcode_ar2cm_ln_Slot_gp_slot2_encode, 0, Opcode_ar2cm_ln_Slot_gp_slot0_encode, Opcode_ar2cm_ln_Slot_dot_slot2_encode, 0, Opcode_ar2cm_ln_Slot_dot_slot0_encode, Opcode_ar2cm_ln_Slot_pq_slot2_encode, 0, Opcode_ar2cm_ln_Slot_pq_slot0_encode, 0, 0, 0, Opcode_ar2cm_ln_Slot_smod_slot2_encode, 0, Opcode_ar2cm_ln_Slot_smod_slot0_encode, Opcode_ar2cm_ln_Slot_llr_slot2_encode, 0, Opcode_ar2cm_ln_Slot_llr_slot0_encode, Opcode_ar2cm_ln_Slot_dual_slot2_encode, 0, Opcode_ar2cm_ln_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ar2cm_ln_i_encode_fns[] = { + Opcode_ar2cm_ln_i_Slot_inst_encode, 0, 0, 0, 0, Opcode_ar2cm_ln_i_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_ar2cm_ln_i_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_ar2cm_ln_i_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_ar2cm_ln_i_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ar2cm_ln_r_encode_fns[] = { + Opcode_ar2cm_ln_r_Slot_inst_encode, 0, 0, 0, 0, Opcode_ar2cm_ln_r_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_ar2cm_ln_r_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_ar2cm_ln_r_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_ar2cm_ln_r_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ar2pq_ln_encode_fns[] = { + 0, 0, 0, Opcode_ar2pq_ln_Slot_gp_slot2_encode, 0, 0, Opcode_ar2pq_ln_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ar2pq_ln_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ar2sar_dup_encode_fns[] = { + 0, 0, 0, Opcode_ar2sar_dup_Slot_gp_slot2_encode, 0, 0, Opcode_ar2sar_dup_Slot_dot_slot2_encode, 0, 0, Opcode_ar2sar_dup_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_ar2sar_dup_Slot_smod_slot2_encode, 0, 0, Opcode_ar2sar_dup_Slot_llr_slot2_encode, 0, 0, Opcode_ar2sar_dup_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_clrac_encode_fns[] = { + Opcode_clrac_Slot_inst_encode, 0, 0, 0, 0, Opcode_clrac_Slot_gp_slot0_encode, 0, 0, Opcode_clrac_Slot_dot_slot0_encode, 0, 0, Opcode_clrac_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_clrac_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_clrcm_encode_fns[] = { + Opcode_clrcm_Slot_inst_encode, 0, 0, Opcode_clrcm_Slot_gp_slot2_encode, 0, Opcode_clrcm_Slot_gp_slot0_encode, Opcode_clrcm_Slot_dot_slot2_encode, 0, Opcode_clrcm_Slot_dot_slot0_encode, Opcode_clrcm_Slot_pq_slot2_encode, 0, Opcode_clrcm_Slot_pq_slot0_encode, Opcode_clrcm_Slot_acc2_slot2_encode, 0, Opcode_clrcm_Slot_acc2_slot0_encode, Opcode_clrcm_Slot_smod_slot2_encode, 0, Opcode_clrcm_Slot_smod_slot0_encode, Opcode_clrcm_Slot_llr_slot2_encode, 0, Opcode_clrcm_Slot_llr_slot0_encode, Opcode_clrcm_Slot_dual_slot2_encode, 0, Opcode_clrcm_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_cm2ar_ln_encode_fns[] = { + Opcode_cm2ar_ln_Slot_inst_encode, 0, 0, Opcode_cm2ar_ln_Slot_gp_slot2_encode, 0, Opcode_cm2ar_ln_Slot_gp_slot0_encode, Opcode_cm2ar_ln_Slot_dot_slot2_encode, 0, Opcode_cm2ar_ln_Slot_dot_slot0_encode, Opcode_cm2ar_ln_Slot_pq_slot2_encode, 0, Opcode_cm2ar_ln_Slot_pq_slot0_encode, 0, 0, 0, Opcode_cm2ar_ln_Slot_smod_slot2_encode, 0, Opcode_cm2ar_ln_Slot_smod_slot0_encode, Opcode_cm2ar_ln_Slot_llr_slot2_encode, 0, Opcode_cm2ar_ln_Slot_llr_slot0_encode, Opcode_cm2ar_ln_Slot_dual_slot2_encode, 0, Opcode_cm2ar_ln_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_cm2ar_ln_i_encode_fns[] = { + Opcode_cm2ar_ln_i_Slot_inst_encode, 0, 0, 0, 0, Opcode_cm2ar_ln_i_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_cm2ar_ln_i_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_cm2ar_ln_i_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_cm2ar_ln_i_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_cm2ar_ln_r_encode_fns[] = { + Opcode_cm2ar_ln_r_Slot_inst_encode, 0, 0, 0, 0, Opcode_cm2ar_ln_r_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_cm2ar_ln_r_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_cm2ar_ln_r_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_cm2ar_ln_r_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_comb_ar_encode_fns[] = { + Opcode_comb_ar_Slot_inst_encode, 0, 0, 0, 0, Opcode_comb_ar_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_comb_ar_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_comb_ar_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_comb_ar_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_conj_encode_fns[] = { + Opcode_conj_Slot_inst_encode, 0, 0, Opcode_conj_Slot_gp_slot2_encode, 0, Opcode_conj_Slot_gp_slot0_encode, Opcode_conj_Slot_dot_slot2_encode, 0, Opcode_conj_Slot_dot_slot0_encode, Opcode_conj_Slot_pq_slot2_encode, 0, Opcode_conj_Slot_pq_slot0_encode, Opcode_conj_Slot_acc2_slot2_encode, 0, Opcode_conj_Slot_acc2_slot0_encode, Opcode_conj_Slot_smod_slot2_encode, 0, Opcode_conj_Slot_smod_slot0_encode, Opcode_conj_Slot_llr_slot2_encode, 0, Opcode_conj_Slot_llr_slot0_encode, Opcode_conj_Slot_dual_slot2_encode, 0, Opcode_conj_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_mov2ac32_i_encode_fns[] = { + Opcode_mov2ac32_i_Slot_inst_encode, 0, 0, 0, 0, Opcode_mov2ac32_i_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_mov2ac32_i_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_mov2ac32_i_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_mov2ac32_r_encode_fns[] = { + Opcode_mov2ac32_r_Slot_inst_encode, 0, 0, 0, 0, Opcode_mov2ac32_r_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_mov2ac32_r_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_mov2ac32_r_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_mov2cm2pq_encode_fns[] = { + 0, 0, 0, Opcode_mov2cm2pq_Slot_gp_slot2_encode, 0, 0, Opcode_mov2cm2pq_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_mov2cm2pq_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movac_encode_fns[] = { + Opcode_movac_Slot_inst_encode, 0, 0, 0, 0, Opcode_movac_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_movac_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_movac_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_movac_i_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_movac_i_Slot_llr_slot1_encode, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movac_i2r_encode_fns[] = { + Opcode_movac_i2r_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movac_r_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_movac_r_Slot_llr_slot1_encode, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movac_r2i_encode_fns[] = { + Opcode_movac_r2i_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movar2_encode_fns[] = { + 0, 0, 0, Opcode_movar2_Slot_gp_slot2_encode, 0, 0, Opcode_movar2_Slot_dot_slot2_encode, 0, 0, Opcode_movar2_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_movar2_Slot_smod_slot2_encode, 0, 0, Opcode_movar2_Slot_llr_slot2_encode, 0, 0, Opcode_movar2_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movcm_encode_fns[] = { + Opcode_movcm_Slot_inst_encode, 0, 0, Opcode_movcm_Slot_gp_slot2_encode, 0, Opcode_movcm_Slot_gp_slot0_encode, Opcode_movcm_Slot_dot_slot2_encode, 0, Opcode_movcm_Slot_dot_slot0_encode, Opcode_movcm_Slot_pq_slot2_encode, 0, Opcode_movcm_Slot_pq_slot0_encode, Opcode_movcm_Slot_acc2_slot2_encode, 0, Opcode_movcm_Slot_acc2_slot0_encode, Opcode_movcm_Slot_smod_slot2_encode, 0, Opcode_movcm_Slot_smod_slot0_encode, Opcode_movcm_Slot_llr_slot2_encode, 0, Opcode_movcm_Slot_llr_slot0_encode, Opcode_movcm_Slot_dual_slot2_encode, 0, Opcode_movcm_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_movcm2pq_encode_fns[] = { + Opcode_movcm2pq_Slot_inst_encode, 0, 0, Opcode_movcm2pq_Slot_gp_slot2_encode, 0, 0, Opcode_movcm2pq_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_movcm2pq_Slot_acc2_slot0_encode, Opcode_movcm2pq_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_movcm2pq_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_movcnd_0_encode_fns[] = { + 0, 0, 0, Opcode_movcnd_0_Slot_gp_slot2_encode, 0, 0, Opcode_movcnd_0_Slot_dot_slot2_encode, 0, 0, Opcode_movcnd_0_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_movcnd_0_Slot_smod_slot2_encode, 0, 0, Opcode_movcnd_0_Slot_llr_slot2_encode, 0, 0, Opcode_movcnd_0_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movcnd_1_encode_fns[] = { + 0, 0, 0, Opcode_movcnd_1_Slot_gp_slot2_encode, 0, 0, Opcode_movcnd_1_Slot_dot_slot2_encode, 0, 0, Opcode_movcnd_1_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_movcnd_1_Slot_smod_slot2_encode, 0, 0, Opcode_movcnd_1_Slot_llr_slot2_encode, 0, 0, Opcode_movcnd_1_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movcnd_2_encode_fns[] = { + 0, 0, 0, Opcode_movcnd_2_Slot_gp_slot2_encode, 0, 0, Opcode_movcnd_2_Slot_dot_slot2_encode, 0, 0, Opcode_movcnd_2_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_movcnd_2_Slot_smod_slot2_encode, 0, 0, Opcode_movcnd_2_Slot_llr_slot2_encode, 0, 0, Opcode_movcnd_2_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movcnd_3_encode_fns[] = { + 0, 0, 0, Opcode_movcnd_3_Slot_gp_slot2_encode, 0, 0, Opcode_movcnd_3_Slot_dot_slot2_encode, 0, 0, Opcode_movcnd_3_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_movcnd_3_Slot_smod_slot2_encode, 0, 0, Opcode_movcnd_3_Slot_llr_slot2_encode, 0, 0, Opcode_movcnd_3_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movcnd_4_encode_fns[] = { + 0, 0, 0, Opcode_movcnd_4_Slot_gp_slot2_encode, 0, 0, Opcode_movcnd_4_Slot_dot_slot2_encode, 0, 0, Opcode_movcnd_4_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_movcnd_4_Slot_smod_slot2_encode, 0, 0, Opcode_movcnd_4_Slot_llr_slot2_encode, 0, 0, Opcode_movcnd_4_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movcnd_5_encode_fns[] = { + 0, 0, 0, Opcode_movcnd_5_Slot_gp_slot2_encode, 0, 0, Opcode_movcnd_5_Slot_dot_slot2_encode, 0, 0, Opcode_movcnd_5_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_movcnd_5_Slot_smod_slot2_encode, 0, 0, Opcode_movcnd_5_Slot_llr_slot2_encode, 0, 0, Opcode_movcnd_5_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movcnd_6_encode_fns[] = { + 0, 0, 0, Opcode_movcnd_6_Slot_gp_slot2_encode, 0, 0, Opcode_movcnd_6_Slot_dot_slot2_encode, 0, 0, Opcode_movcnd_6_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_movcnd_6_Slot_smod_slot2_encode, 0, 0, Opcode_movcnd_6_Slot_llr_slot2_encode, 0, 0, Opcode_movcnd_6_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movcnd_7_encode_fns[] = { + 0, 0, 0, Opcode_movcnd_7_Slot_gp_slot2_encode, 0, 0, Opcode_movcnd_7_Slot_dot_slot2_encode, 0, 0, Opcode_movcnd_7_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_movcnd_7_Slot_smod_slot2_encode, 0, 0, Opcode_movcnd_7_Slot_llr_slot2_encode, 0, 0, Opcode_movcnd_7_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movcnd8_0_encode_fns[] = { + 0, 0, 0, Opcode_movcnd8_0_Slot_gp_slot2_encode, 0, 0, Opcode_movcnd8_0_Slot_dot_slot2_encode, 0, 0, Opcode_movcnd8_0_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_movcnd8_0_Slot_smod_slot2_encode, 0, 0, Opcode_movcnd8_0_Slot_llr_slot2_encode, 0, 0, Opcode_movcnd8_0_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movcnd8_1_encode_fns[] = { + 0, 0, 0, Opcode_movcnd8_1_Slot_gp_slot2_encode, 0, 0, Opcode_movcnd8_1_Slot_dot_slot2_encode, 0, 0, Opcode_movcnd8_1_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_movcnd8_1_Slot_smod_slot2_encode, 0, 0, Opcode_movcnd8_1_Slot_llr_slot2_encode, 0, 0, Opcode_movcnd8_1_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movcnd8_2_encode_fns[] = { + 0, 0, 0, Opcode_movcnd8_2_Slot_gp_slot2_encode, 0, 0, Opcode_movcnd8_2_Slot_dot_slot2_encode, 0, 0, Opcode_movcnd8_2_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_movcnd8_2_Slot_smod_slot2_encode, 0, 0, Opcode_movcnd8_2_Slot_llr_slot2_encode, 0, 0, Opcode_movcnd8_2_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movcnd8_3_encode_fns[] = { + 0, 0, 0, Opcode_movcnd8_3_Slot_gp_slot2_encode, 0, 0, Opcode_movcnd8_3_Slot_dot_slot2_encode, 0, 0, Opcode_movcnd8_3_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_movcnd8_3_Slot_smod_slot2_encode, 0, 0, Opcode_movcnd8_3_Slot_llr_slot2_encode, 0, 0, Opcode_movcnd8_3_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movcnd8_4_encode_fns[] = { + 0, 0, 0, Opcode_movcnd8_4_Slot_gp_slot2_encode, 0, 0, Opcode_movcnd8_4_Slot_dot_slot2_encode, 0, 0, Opcode_movcnd8_4_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_movcnd8_4_Slot_smod_slot2_encode, 0, 0, Opcode_movcnd8_4_Slot_llr_slot2_encode, 0, 0, Opcode_movcnd8_4_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movcnd8_5_encode_fns[] = { + 0, 0, 0, Opcode_movcnd8_5_Slot_gp_slot2_encode, 0, 0, Opcode_movcnd8_5_Slot_dot_slot2_encode, 0, 0, Opcode_movcnd8_5_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_movcnd8_5_Slot_smod_slot2_encode, 0, 0, Opcode_movcnd8_5_Slot_llr_slot2_encode, 0, 0, Opcode_movcnd8_5_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movcnd8_6_encode_fns[] = { + 0, 0, 0, Opcode_movcnd8_6_Slot_gp_slot2_encode, 0, 0, Opcode_movcnd8_6_Slot_dot_slot2_encode, 0, 0, Opcode_movcnd8_6_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_movcnd8_6_Slot_smod_slot2_encode, 0, 0, Opcode_movcnd8_6_Slot_llr_slot2_encode, 0, 0, Opcode_movcnd8_6_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movcnd8_7_encode_fns[] = { + 0, 0, 0, Opcode_movcnd8_7_Slot_gp_slot2_encode, 0, 0, Opcode_movcnd8_7_Slot_dot_slot2_encode, 0, 0, Opcode_movcnd8_7_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_movcnd8_7_Slot_smod_slot2_encode, 0, 0, Opcode_movcnd8_7_Slot_llr_slot2_encode, 0, 0, Opcode_movcnd8_7_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mov_i_encode_fns[] = { + Opcode_mov_i_Slot_inst_encode, 0, 0, 0, 0, Opcode_mov_i_Slot_gp_slot0_encode, 0, 0, Opcode_mov_i_Slot_dot_slot0_encode, 0, 0, Opcode_mov_i_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_mov_i_Slot_smod_slot0_encode, 0, 0, Opcode_mov_i_Slot_llr_slot0_encode, 0, 0, Opcode_mov_i_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_movpq2pq_encode_fns[] = { + 0, 0, 0, Opcode_movpq2pq_Slot_gp_slot2_encode, 0, 0, Opcode_movpq2pq_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_movpq2pq_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mov_r_encode_fns[] = { + Opcode_mov_r_Slot_inst_encode, 0, 0, 0, 0, Opcode_mov_r_Slot_gp_slot0_encode, 0, 0, Opcode_mov_r_Slot_dot_slot0_encode, 0, 0, Opcode_mov_r_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_mov_r_Slot_smod_slot0_encode, 0, 0, Opcode_mov_r_Slot_llr_slot0_encode, 0, 0, Opcode_mov_r_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_negcm_encode_fns[] = { + Opcode_negcm_Slot_inst_encode, 0, 0, Opcode_negcm_Slot_gp_slot2_encode, 0, Opcode_negcm_Slot_gp_slot0_encode, Opcode_negcm_Slot_dot_slot2_encode, 0, Opcode_negcm_Slot_dot_slot0_encode, Opcode_negcm_Slot_pq_slot2_encode, 0, Opcode_negcm_Slot_pq_slot0_encode, Opcode_negcm_Slot_acc2_slot2_encode, 0, Opcode_negcm_Slot_acc2_slot0_encode, Opcode_negcm_Slot_smod_slot2_encode, 0, Opcode_negcm_Slot_smod_slot0_encode, Opcode_negcm_Slot_llr_slot2_encode, 0, Opcode_negcm_Slot_llr_slot0_encode, Opcode_negcm_Slot_dual_slot2_encode, 0, Opcode_negcm_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop16llr_1_encode_fns[] = { + Opcode_pop16llr_1_Slot_inst_encode, 0, 0, 0, 0, Opcode_pop16llr_1_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_pop16llr_1_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_pop16llr_1_Slot_llr_slot0_encode, 0, 0, Opcode_pop16llr_1_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pq2cm_encode_fns[] = { + Opcode_pq2cm_Slot_inst_encode, 0, 0, Opcode_pq2cm_Slot_gp_slot2_encode, 0, 0, Opcode_pq2cm_Slot_dot_slot2_encode, 0, 0, Opcode_pq2cm_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_pq2cm_Slot_smod_slot2_encode, 0, 0, Opcode_pq2cm_Slot_llr_slot2_encode, 0, 0, Opcode_pq2cm_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_swapac_r_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_swapac_r_Slot_acc2_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_swapac_ri_encode_fns[] = { + Opcode_swapac_ri_Slot_inst_encode, 0, 0, 0, 0, Opcode_swapac_ri_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_swapac_ri_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_swapac_ri_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_swapb_encode_fns[] = { + Opcode_swapb_Slot_inst_encode, 0, 0, Opcode_swapb_Slot_gp_slot2_encode, 0, 0, Opcode_swapb_Slot_dot_slot2_encode, 0, 0, Opcode_swapb_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_swapb_Slot_smod_slot2_encode, 0, 0, Opcode_swapb_Slot_llr_slot2_encode, 0, 0, Opcode_swapb_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_add2ac_encode_fns[] = { + 0, 0, 0, 0, Opcode_add2ac_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addac_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_addac_Slot_llr_slot1_encode, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_cdot_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_cdot_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_cdotac_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_cdotac_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_cdotacs_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_cdotacs_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_cmac_encode_fns[] = { + 0, 0, 0, 0, Opcode_cmac_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_cmac_Slot_smod_slot1_encode, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_cmacs_encode_fns[] = { + 0, 0, 0, 0, Opcode_cmacs_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_cmpy_encode_fns[] = { + 0, 0, 0, 0, Opcode_cmpy_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_cmpy_Slot_smod_slot1_encode, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_cmpy2cm_encode_fns[] = { + 0, 0, 0, 0, Opcode_cmpy2cm_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_cmpy2cm_Slot_smod_slot1_encode, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_cmpy2pq_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_cmpy2pq_Slot_pq_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_cmpys_encode_fns[] = { + 0, 0, 0, 0, Opcode_cmpys_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_cmpyxp2pq_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_cmpyxp2pq_Slot_pq_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_comb32_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_comb32_Slot_llr_slot1_encode, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dot_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_dot_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dotac_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_dotac_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dotacs_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_dotacs_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lin_int_encode_fns[] = { + 0, 0, 0, 0, Opcode_lin_int_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_llrpre1_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_llrpre1_Slot_acc2_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_llrpre2_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_llrpre2_Slot_llr_slot1_encode, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mac_encode_fns[] = { + 0, 0, 0, 0, Opcode_mac_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_mac_Slot_smod_slot1_encode, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mac8_encode_fns[] = { + 0, 0, 0, 0, Opcode_mac8_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_macd8_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_macd8_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_macpqxp_0_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_macpqxp_0_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_macpqxp_1_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_macpqxp_1_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_macpqxp_2_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_macpqxp_2_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_macpqxp_3_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_macpqxp_3_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_macs_encode_fns[] = { + 0, 0, 0, 0, Opcode_macs_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_macxp2_0_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_macxp2_0_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_macxp2_1_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_macxp2_1_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_macxp_0_encode_fns[] = { + 0, 0, 0, 0, Opcode_macxp_0_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_macxp_1_encode_fns[] = { + 0, 0, 0, 0, Opcode_macxp_1_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_macxp_2_encode_fns[] = { + 0, 0, 0, 0, Opcode_macxp_2_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_macxp_3_encode_fns[] = { + 0, 0, 0, 0, Opcode_macxp_3_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mov2ac_encode_fns[] = { + 0, 0, 0, 0, Opcode_mov2ac_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpy_encode_fns[] = { + 0, 0, 0, 0, Opcode_mpy_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_mpy_Slot_smod_slot1_encode, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpy2cm_encode_fns[] = { + 0, 0, 0, 0, Opcode_mpy2cm_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_mpy2cm_Slot_smod_slot1_encode, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpy2pq_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_mpy2pq_Slot_pq_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpy8_encode_fns[] = { + 0, 0, 0, 0, Opcode_mpy8_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpyadd8_2cm_encode_fns[] = { + 0, 0, 0, 0, Opcode_mpyadd8_2cm_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_mpyadd8_2cm_Slot_smod_slot1_encode, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpyd8_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_mpyd8_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpypqxp_0_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_mpypqxp_0_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpypqxp_1_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_mpypqxp_1_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpypqxp_2_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_mpypqxp_2_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpypqxp_3_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_mpypqxp_3_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpys_encode_fns[] = { + 0, 0, 0, 0, Opcode_mpys_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpyxp2pq_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_mpyxp2pq_Slot_pq_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpyxp2_0_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_mpyxp2_0_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpyxp2_1_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, Opcode_mpyxp2_1_Slot_dot_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpyxp_0_encode_fns[] = { + 0, 0, 0, 0, Opcode_mpyxp_0_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpyxp_1_encode_fns[] = { + 0, 0, 0, 0, Opcode_mpyxp_1_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpyxp_2_encode_fns[] = { + 0, 0, 0, 0, Opcode_mpyxp_2_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mpyxp_3_encode_fns[] = { + 0, 0, 0, 0, Opcode_mpyxp_3_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_normacd_encode_fns[] = { + 0, 0, 0, 0, Opcode_normacd_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_normacd_Slot_smod_slot1_encode, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_normacpq_i_encode_fns[] = { + 0, 0, 0, 0, Opcode_normacpq_i_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_normacpq_r_encode_fns[] = { + 0, 0, 0, 0, Opcode_normacpq_r_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_normd_encode_fns[] = { + 0, 0, 0, 0, Opcode_normd_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_normd_Slot_smod_slot1_encode, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_normpypq_i_encode_fns[] = { + 0, 0, 0, 0, Opcode_normpypq_i_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_normpypq_r_encode_fns[] = { + 0, 0, 0, 0, Opcode_normpypq_r_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rcmac_encode_fns[] = { + 0, 0, 0, 0, Opcode_rcmac_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rcmpy_encode_fns[] = { + 0, 0, 0, 0, Opcode_rcmpy_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rcmpy2cm_encode_fns[] = { + 0, 0, 0, 0, Opcode_rcmpy2cm_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_rcmpy2cm_Slot_smod_slot1_encode, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfir_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_rfir_Slot_acc2_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfira_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_rfira_Slot_acc2_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfird_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_rfird_Slot_acc2_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfirda_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_rfirda_Slot_acc2_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rmac_encode_fns[] = { + 0, 0, 0, 0, Opcode_rmac_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rmpy_encode_fns[] = { + 0, 0, 0, 0, Opcode_rmpy_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rmpy2cm_encode_fns[] = { + 0, 0, 0, 0, Opcode_rmpy2cm_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_rmpy2cm_Slot_smod_slot1_encode, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_smod_align_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_smod_align_Slot_smod_slot1_encode, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_smod_scr_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_smod_scr_Slot_smod_slot1_encode, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sub2ac_encode_fns[] = { + 0, 0, 0, 0, Opcode_sub2ac_Slot_gp_slot1_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wght32_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_wght32_Slot_llr_slot1_encode, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_clrtiep_encode_fns[] = { + Opcode_clrtiep_Slot_inst_encode, 0, 0, Opcode_clrtiep_Slot_gp_slot2_encode, 0, 0, Opcode_clrtiep_Slot_dot_slot2_encode, 0, 0, Opcode_clrtiep_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_clrtiep_Slot_smod_slot2_encode, 0, 0, Opcode_clrtiep_Slot_llr_slot2_encode, 0, 0, Opcode_clrtiep_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ext_2fifo_0_encode_fns[] = { + Opcode_ext_2fifo_0_Slot_inst_encode, 0, 0, 0, 0, Opcode_ext_2fifo_0_Slot_gp_slot0_encode, 0, 0, Opcode_ext_2fifo_0_Slot_dot_slot0_encode, 0, 0, Opcode_ext_2fifo_0_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ext_2fifo_0_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ext_2fifo_1_encode_fns[] = { + Opcode_ext_2fifo_1_Slot_inst_encode, 0, 0, 0, 0, Opcode_ext_2fifo_1_Slot_gp_slot0_encode, 0, 0, Opcode_ext_2fifo_1_Slot_dot_slot0_encode, 0, 0, Opcode_ext_2fifo_1_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ext_2fifo_1_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ext_2fifo_2_encode_fns[] = { + Opcode_ext_2fifo_2_Slot_inst_encode, 0, 0, 0, 0, Opcode_ext_2fifo_2_Slot_gp_slot0_encode, 0, 0, Opcode_ext_2fifo_2_Slot_dot_slot0_encode, 0, 0, Opcode_ext_2fifo_2_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ext_2fifo_2_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ext_2fifo_3_encode_fns[] = { + Opcode_ext_2fifo_3_Slot_inst_encode, 0, 0, 0, 0, Opcode_ext_2fifo_3_Slot_gp_slot0_encode, 0, 0, Opcode_ext_2fifo_3_Slot_dot_slot0_encode, 0, 0, Opcode_ext_2fifo_3_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ext_2fifo_3_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ext_r2fifo_0_encode_fns[] = { + Opcode_ext_r2fifo_0_Slot_inst_encode, 0, 0, 0, 0, Opcode_ext_r2fifo_0_Slot_gp_slot0_encode, 0, 0, Opcode_ext_r2fifo_0_Slot_dot_slot0_encode, 0, 0, Opcode_ext_r2fifo_0_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ext_r2fifo_0_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ext_r2fifo_1_encode_fns[] = { + Opcode_ext_r2fifo_1_Slot_inst_encode, 0, 0, 0, 0, Opcode_ext_r2fifo_1_Slot_gp_slot0_encode, 0, 0, Opcode_ext_r2fifo_1_Slot_dot_slot0_encode, 0, 0, Opcode_ext_r2fifo_1_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ext_r2fifo_1_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ext_r2fifo_2_encode_fns[] = { + Opcode_ext_r2fifo_2_Slot_inst_encode, 0, 0, 0, 0, Opcode_ext_r2fifo_2_Slot_gp_slot0_encode, 0, 0, Opcode_ext_r2fifo_2_Slot_dot_slot0_encode, 0, 0, Opcode_ext_r2fifo_2_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ext_r2fifo_2_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ext_r2fifo_3_encode_fns[] = { + Opcode_ext_r2fifo_3_Slot_inst_encode, 0, 0, 0, 0, Opcode_ext_r2fifo_3_Slot_gp_slot0_encode, 0, 0, Opcode_ext_r2fifo_3_Slot_dot_slot0_encode, 0, 0, Opcode_ext_r2fifo_3_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ext_r2fifo_3_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_lut_encode_fns[] = { + 0, 0, 0, Opcode_lut_Slot_gp_slot2_encode, 0, 0, Opcode_lut_Slot_dot_slot2_encode, 0, 0, Opcode_lut_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_lut_Slot_smod_slot2_encode, 0, 0, Opcode_lut_Slot_llr_slot2_encode, 0, 0, Opcode_lut_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lut_ar_encode_fns[] = { + 0, 0, 0, Opcode_lut_ar_Slot_gp_slot2_encode, 0, 0, Opcode_lut_ar_Slot_dot_slot2_encode, 0, 0, Opcode_lut_ar_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_lut_ar_Slot_smod_slot2_encode, 0, 0, Opcode_lut_ar_Slot_llr_slot2_encode, 0, 0, Opcode_lut_ar_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lut_iext_encode_fns[] = { + 0, 0, 0, Opcode_lut_iext_Slot_gp_slot2_encode, 0, 0, Opcode_lut_iext_Slot_dot_slot2_encode, 0, 0, Opcode_lut_iext_Slot_pq_slot2_encode, 0, 0, Opcode_lut_iext_Slot_acc2_slot2_encode, 0, 0, Opcode_lut_iext_Slot_smod_slot2_encode, 0, 0, Opcode_lut_iext_Slot_llr_slot2_encode, 0, 0, Opcode_lut_iext_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lut_phasor_encode_fns[] = { + 0, 0, 0, Opcode_lut_phasor_Slot_gp_slot2_encode, 0, 0, Opcode_lut_phasor_Slot_dot_slot2_encode, 0, 0, Opcode_lut_phasor_Slot_pq_slot2_encode, 0, 0, Opcode_lut_phasor_Slot_acc2_slot2_encode, 0, 0, Opcode_lut_phasor_Slot_smod_slot2_encode, 0, 0, Opcode_lut_phasor_Slot_llr_slot2_encode, 0, 0, Opcode_lut_phasor_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lut_rext_encode_fns[] = { + 0, 0, 0, Opcode_lut_rext_Slot_gp_slot2_encode, 0, 0, Opcode_lut_rext_Slot_dot_slot2_encode, 0, 0, Opcode_lut_rext_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_lut_rext_Slot_smod_slot2_encode, 0, 0, Opcode_lut_rext_Slot_llr_slot2_encode, 0, 0, Opcode_lut_rext_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lut_write_encode_fns[] = { + 0, 0, 0, Opcode_lut_write_Slot_gp_slot2_encode, 0, 0, Opcode_lut_write_Slot_dot_slot2_encode, 0, 0, Opcode_lut_write_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_lut_write_Slot_smod_slot2_encode, 0, 0, Opcode_lut_write_Slot_llr_slot2_encode, 0, 0, Opcode_lut_write_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_moveq128_0_encode_fns[] = { + Opcode_moveq128_0_Slot_inst_encode, 0, 0, Opcode_moveq128_0_Slot_gp_slot2_encode, 0, 0, Opcode_moveq128_0_Slot_dot_slot2_encode, 0, 0, Opcode_moveq128_0_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_moveq128_0_Slot_smod_slot2_encode, 0, 0, Opcode_moveq128_0_Slot_llr_slot2_encode, 0, 0, Opcode_moveq128_0_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_moveq128_1_encode_fns[] = { + Opcode_moveq128_1_Slot_inst_encode, 0, 0, Opcode_moveq128_1_Slot_gp_slot2_encode, 0, 0, Opcode_moveq128_1_Slot_dot_slot2_encode, 0, 0, Opcode_moveq128_1_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_moveq128_1_Slot_smod_slot2_encode, 0, 0, Opcode_moveq128_1_Slot_llr_slot2_encode, 0, 0, Opcode_moveq128_1_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_moveq128_2_encode_fns[] = { + Opcode_moveq128_2_Slot_inst_encode, 0, 0, Opcode_moveq128_2_Slot_gp_slot2_encode, 0, 0, Opcode_moveq128_2_Slot_dot_slot2_encode, 0, 0, Opcode_moveq128_2_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_moveq128_2_Slot_smod_slot2_encode, 0, 0, Opcode_moveq128_2_Slot_llr_slot2_encode, 0, 0, Opcode_moveq128_2_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_moveq128_3_encode_fns[] = { + Opcode_moveq128_3_Slot_inst_encode, 0, 0, Opcode_moveq128_3_Slot_gp_slot2_encode, 0, 0, Opcode_moveq128_3_Slot_dot_slot2_encode, 0, 0, Opcode_moveq128_3_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_moveq128_3_Slot_smod_slot2_encode, 0, 0, Opcode_moveq128_3_Slot_llr_slot2_encode, 0, 0, Opcode_moveq128_3_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_moveq128_4_encode_fns[] = { + Opcode_moveq128_4_Slot_inst_encode, 0, 0, Opcode_moveq128_4_Slot_gp_slot2_encode, 0, 0, Opcode_moveq128_4_Slot_dot_slot2_encode, 0, 0, Opcode_moveq128_4_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_moveq128_4_Slot_smod_slot2_encode, 0, 0, Opcode_moveq128_4_Slot_llr_slot2_encode, 0, 0, Opcode_moveq128_4_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_moveq128_5_encode_fns[] = { + Opcode_moveq128_5_Slot_inst_encode, 0, 0, Opcode_moveq128_5_Slot_gp_slot2_encode, 0, 0, Opcode_moveq128_5_Slot_dot_slot2_encode, 0, 0, Opcode_moveq128_5_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_moveq128_5_Slot_smod_slot2_encode, 0, 0, Opcode_moveq128_5_Slot_llr_slot2_encode, 0, 0, Opcode_moveq128_5_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_moveq32_0_encode_fns[] = { + Opcode_moveq32_0_Slot_inst_encode, 0, 0, Opcode_moveq32_0_Slot_gp_slot2_encode, 0, 0, Opcode_moveq32_0_Slot_dot_slot2_encode, 0, 0, Opcode_moveq32_0_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_moveq32_0_Slot_smod_slot2_encode, 0, 0, Opcode_moveq32_0_Slot_llr_slot2_encode, 0, 0, Opcode_moveq32_0_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_moveq32_1_encode_fns[] = { + Opcode_moveq32_1_Slot_inst_encode, 0, 0, Opcode_moveq32_1_Slot_gp_slot2_encode, 0, 0, Opcode_moveq32_1_Slot_dot_slot2_encode, 0, 0, Opcode_moveq32_1_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_moveq32_1_Slot_smod_slot2_encode, 0, 0, Opcode_moveq32_1_Slot_llr_slot2_encode, 0, 0, Opcode_moveq32_1_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_moveq32_2_encode_fns[] = { + Opcode_moveq32_2_Slot_inst_encode, 0, 0, Opcode_moveq32_2_Slot_gp_slot2_encode, 0, 0, Opcode_moveq32_2_Slot_dot_slot2_encode, 0, 0, Opcode_moveq32_2_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_moveq32_2_Slot_smod_slot2_encode, 0, 0, Opcode_moveq32_2_Slot_llr_slot2_encode, 0, 0, Opcode_moveq32_2_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_moveq32_3_encode_fns[] = { + Opcode_moveq32_3_Slot_inst_encode, 0, 0, Opcode_moveq32_3_Slot_gp_slot2_encode, 0, 0, Opcode_moveq32_3_Slot_dot_slot2_encode, 0, 0, Opcode_moveq32_3_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_moveq32_3_Slot_smod_slot2_encode, 0, 0, Opcode_moveq32_3_Slot_llr_slot2_encode, 0, 0, Opcode_moveq32_3_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_nco_update_encode_fns[] = { + 0, 0, 0, Opcode_nco_update_Slot_gp_slot2_encode, 0, 0, Opcode_nco_update_Slot_dot_slot2_encode, 0, 0, Opcode_nco_update_Slot_pq_slot2_encode, 0, 0, Opcode_nco_update_Slot_acc2_slot2_encode, 0, 0, Opcode_nco_update_Slot_smod_slot2_encode, 0, 0, Opcode_nco_update_Slot_llr_slot2_encode, 0, 0, Opcode_nco_update_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_pop128_0_encode_fns[] = { + Opcode_pop128_0_Slot_inst_encode, 0, 0, Opcode_pop128_0_Slot_gp_slot2_encode, 0, Opcode_pop128_0_Slot_gp_slot0_encode, Opcode_pop128_0_Slot_dot_slot2_encode, 0, Opcode_pop128_0_Slot_dot_slot0_encode, Opcode_pop128_0_Slot_pq_slot2_encode, 0, Opcode_pop128_0_Slot_pq_slot0_encode, Opcode_pop128_0_Slot_acc2_slot2_encode, 0, Opcode_pop128_0_Slot_acc2_slot0_encode, Opcode_pop128_0_Slot_smod_slot2_encode, 0, Opcode_pop128_0_Slot_smod_slot0_encode, Opcode_pop128_0_Slot_llr_slot2_encode, 0, Opcode_pop128_0_Slot_llr_slot0_encode, Opcode_pop128_0_Slot_dual_slot2_encode, 0, Opcode_pop128_0_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop128_1_encode_fns[] = { + Opcode_pop128_1_Slot_inst_encode, 0, 0, Opcode_pop128_1_Slot_gp_slot2_encode, 0, Opcode_pop128_1_Slot_gp_slot0_encode, Opcode_pop128_1_Slot_dot_slot2_encode, 0, Opcode_pop128_1_Slot_dot_slot0_encode, Opcode_pop128_1_Slot_pq_slot2_encode, 0, Opcode_pop128_1_Slot_pq_slot0_encode, Opcode_pop128_1_Slot_acc2_slot2_encode, 0, Opcode_pop128_1_Slot_acc2_slot0_encode, Opcode_pop128_1_Slot_smod_slot2_encode, 0, Opcode_pop128_1_Slot_smod_slot0_encode, Opcode_pop128_1_Slot_llr_slot2_encode, 0, Opcode_pop128_1_Slot_llr_slot0_encode, Opcode_pop128_1_Slot_dual_slot2_encode, 0, Opcode_pop128_1_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop128_2_encode_fns[] = { + Opcode_pop128_2_Slot_inst_encode, 0, 0, Opcode_pop128_2_Slot_gp_slot2_encode, 0, Opcode_pop128_2_Slot_gp_slot0_encode, Opcode_pop128_2_Slot_dot_slot2_encode, 0, Opcode_pop128_2_Slot_dot_slot0_encode, Opcode_pop128_2_Slot_pq_slot2_encode, 0, Opcode_pop128_2_Slot_pq_slot0_encode, Opcode_pop128_2_Slot_acc2_slot2_encode, 0, Opcode_pop128_2_Slot_acc2_slot0_encode, Opcode_pop128_2_Slot_smod_slot2_encode, 0, Opcode_pop128_2_Slot_smod_slot0_encode, Opcode_pop128_2_Slot_llr_slot2_encode, 0, Opcode_pop128_2_Slot_llr_slot0_encode, Opcode_pop128_2_Slot_dual_slot2_encode, 0, Opcode_pop128_2_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop128_3_encode_fns[] = { + Opcode_pop128_3_Slot_inst_encode, 0, 0, Opcode_pop128_3_Slot_gp_slot2_encode, 0, Opcode_pop128_3_Slot_gp_slot0_encode, Opcode_pop128_3_Slot_dot_slot2_encode, 0, Opcode_pop128_3_Slot_dot_slot0_encode, Opcode_pop128_3_Slot_pq_slot2_encode, 0, Opcode_pop128_3_Slot_pq_slot0_encode, Opcode_pop128_3_Slot_acc2_slot2_encode, 0, Opcode_pop128_3_Slot_acc2_slot0_encode, Opcode_pop128_3_Slot_smod_slot2_encode, 0, Opcode_pop128_3_Slot_smod_slot0_encode, Opcode_pop128_3_Slot_llr_slot2_encode, 0, Opcode_pop128_3_Slot_llr_slot0_encode, Opcode_pop128_3_Slot_dual_slot2_encode, 0, Opcode_pop128_3_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop128_4_encode_fns[] = { + Opcode_pop128_4_Slot_inst_encode, 0, 0, Opcode_pop128_4_Slot_gp_slot2_encode, 0, Opcode_pop128_4_Slot_gp_slot0_encode, Opcode_pop128_4_Slot_dot_slot2_encode, 0, Opcode_pop128_4_Slot_dot_slot0_encode, Opcode_pop128_4_Slot_pq_slot2_encode, 0, Opcode_pop128_4_Slot_pq_slot0_encode, Opcode_pop128_4_Slot_acc2_slot2_encode, 0, Opcode_pop128_4_Slot_acc2_slot0_encode, Opcode_pop128_4_Slot_smod_slot2_encode, 0, Opcode_pop128_4_Slot_smod_slot0_encode, Opcode_pop128_4_Slot_llr_slot2_encode, 0, Opcode_pop128_4_Slot_llr_slot0_encode, Opcode_pop128_4_Slot_dual_slot2_encode, 0, Opcode_pop128_4_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop128_5_encode_fns[] = { + Opcode_pop128_5_Slot_inst_encode, 0, 0, Opcode_pop128_5_Slot_gp_slot2_encode, 0, Opcode_pop128_5_Slot_gp_slot0_encode, Opcode_pop128_5_Slot_dot_slot2_encode, 0, Opcode_pop128_5_Slot_dot_slot0_encode, Opcode_pop128_5_Slot_pq_slot2_encode, 0, Opcode_pop128_5_Slot_pq_slot0_encode, Opcode_pop128_5_Slot_acc2_slot2_encode, 0, Opcode_pop128_5_Slot_acc2_slot0_encode, Opcode_pop128_5_Slot_smod_slot2_encode, 0, Opcode_pop128_5_Slot_smod_slot0_encode, Opcode_pop128_5_Slot_llr_slot2_encode, 0, Opcode_pop128_5_Slot_llr_slot0_encode, Opcode_pop128_5_Slot_dual_slot2_encode, 0, Opcode_pop128_5_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop128_2cmpq_0_encode_fns[] = { + 0, 0, 0, Opcode_pop128_2cmpq_0_Slot_gp_slot2_encode, 0, 0, Opcode_pop128_2cmpq_0_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_pop128_2cmpq_0_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_pop128_2cmpq_1_encode_fns[] = { + 0, 0, 0, Opcode_pop128_2cmpq_1_Slot_gp_slot2_encode, 0, 0, Opcode_pop128_2cmpq_1_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_pop128_2cmpq_1_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_pop128_2cmpq_2_encode_fns[] = { + 0, 0, 0, Opcode_pop128_2cmpq_2_Slot_gp_slot2_encode, 0, 0, Opcode_pop128_2cmpq_2_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_pop128_2cmpq_2_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_pop128_2cmpq_3_encode_fns[] = { + 0, 0, 0, Opcode_pop128_2cmpq_3_Slot_gp_slot2_encode, 0, 0, Opcode_pop128_2cmpq_3_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_pop128_2cmpq_3_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_pop128_2m_0_encode_fns[] = { + Opcode_pop128_2m_0_Slot_inst_encode, 0, 0, 0, 0, Opcode_pop128_2m_0_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_pop128_2m_0_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_pop128_2m_0_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_pop128_2m_0_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop128_2m_1_encode_fns[] = { + Opcode_pop128_2m_1_Slot_inst_encode, 0, 0, 0, 0, Opcode_pop128_2m_1_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_pop128_2m_1_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_pop128_2m_1_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_pop128_2m_1_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop128_2m_2_encode_fns[] = { + Opcode_pop128_2m_2_Slot_inst_encode, 0, 0, 0, 0, Opcode_pop128_2m_2_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_pop128_2m_2_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_pop128_2m_2_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_pop128_2m_2_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop128_2m_3_encode_fns[] = { + Opcode_pop128_2m_3_Slot_inst_encode, 0, 0, 0, 0, Opcode_pop128_2m_3_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_pop128_2m_3_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_pop128_2m_3_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_pop128_2m_3_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop128_2pq_0_encode_fns[] = { + Opcode_pop128_2pq_0_Slot_inst_encode, 0, 0, Opcode_pop128_2pq_0_Slot_gp_slot2_encode, 0, 0, Opcode_pop128_2pq_0_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop128_2pq_0_Slot_acc2_slot0_encode, Opcode_pop128_2pq_0_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop128_2pq_0_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop128_2pq_1_encode_fns[] = { + Opcode_pop128_2pq_1_Slot_inst_encode, 0, 0, Opcode_pop128_2pq_1_Slot_gp_slot2_encode, 0, 0, Opcode_pop128_2pq_1_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop128_2pq_1_Slot_acc2_slot0_encode, Opcode_pop128_2pq_1_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop128_2pq_1_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop128_2pq_2_encode_fns[] = { + Opcode_pop128_2pq_2_Slot_inst_encode, 0, 0, Opcode_pop128_2pq_2_Slot_gp_slot2_encode, 0, 0, Opcode_pop128_2pq_2_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop128_2pq_2_Slot_acc2_slot0_encode, Opcode_pop128_2pq_2_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop128_2pq_2_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop128_2pq_3_encode_fns[] = { + Opcode_pop128_2pq_3_Slot_inst_encode, 0, 0, Opcode_pop128_2pq_3_Slot_gp_slot2_encode, 0, 0, Opcode_pop128_2pq_3_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop128_2pq_3_Slot_acc2_slot0_encode, Opcode_pop128_2pq_3_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop128_2pq_3_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop128_2pq_4_encode_fns[] = { + Opcode_pop128_2pq_4_Slot_inst_encode, 0, 0, Opcode_pop128_2pq_4_Slot_gp_slot2_encode, 0, 0, Opcode_pop128_2pq_4_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop128_2pq_4_Slot_acc2_slot0_encode, Opcode_pop128_2pq_4_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop128_2pq_4_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop128_2pq_5_encode_fns[] = { + Opcode_pop128_2pq_5_Slot_inst_encode, 0, 0, Opcode_pop128_2pq_5_Slot_gp_slot2_encode, 0, 0, Opcode_pop128_2pq_5_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop128_2pq_5_Slot_acc2_slot0_encode, Opcode_pop128_2pq_5_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop128_2pq_5_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop2x128_2pq_01_encode_fns[] = { + Opcode_pop2x128_2pq_01_Slot_inst_encode, 0, 0, Opcode_pop2x128_2pq_01_Slot_gp_slot2_encode, 0, 0, Opcode_pop2x128_2pq_01_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop2x128_2pq_01_Slot_acc2_slot0_encode, Opcode_pop2x128_2pq_01_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop2x128_2pq_01_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop2x128_2pq_03_encode_fns[] = { + Opcode_pop2x128_2pq_03_Slot_inst_encode, 0, 0, Opcode_pop2x128_2pq_03_Slot_gp_slot2_encode, 0, 0, Opcode_pop2x128_2pq_03_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop2x128_2pq_03_Slot_acc2_slot0_encode, Opcode_pop2x128_2pq_03_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop2x128_2pq_03_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop2x128_2pq_21_encode_fns[] = { + Opcode_pop2x128_2pq_21_Slot_inst_encode, 0, 0, Opcode_pop2x128_2pq_21_Slot_gp_slot2_encode, 0, 0, Opcode_pop2x128_2pq_21_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop2x128_2pq_21_Slot_acc2_slot0_encode, Opcode_pop2x128_2pq_21_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop2x128_2pq_21_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop2x128_2pq_23_encode_fns[] = { + Opcode_pop2x128_2pq_23_Slot_inst_encode, 0, 0, Opcode_pop2x128_2pq_23_Slot_gp_slot2_encode, 0, 0, Opcode_pop2x128_2pq_23_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop2x128_2pq_23_Slot_acc2_slot0_encode, Opcode_pop2x128_2pq_23_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_pop2x128_2pq_23_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop32_0_encode_fns[] = { + Opcode_pop32_0_Slot_inst_encode, 0, 0, Opcode_pop32_0_Slot_gp_slot2_encode, 0, Opcode_pop32_0_Slot_gp_slot0_encode, Opcode_pop32_0_Slot_dot_slot2_encode, 0, Opcode_pop32_0_Slot_dot_slot0_encode, Opcode_pop32_0_Slot_pq_slot2_encode, 0, Opcode_pop32_0_Slot_pq_slot0_encode, Opcode_pop32_0_Slot_acc2_slot2_encode, 0, Opcode_pop32_0_Slot_acc2_slot0_encode, Opcode_pop32_0_Slot_smod_slot2_encode, 0, Opcode_pop32_0_Slot_smod_slot0_encode, Opcode_pop32_0_Slot_llr_slot2_encode, 0, Opcode_pop32_0_Slot_llr_slot0_encode, Opcode_pop32_0_Slot_dual_slot2_encode, 0, Opcode_pop32_0_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop32_1_encode_fns[] = { + Opcode_pop32_1_Slot_inst_encode, 0, 0, Opcode_pop32_1_Slot_gp_slot2_encode, 0, Opcode_pop32_1_Slot_gp_slot0_encode, Opcode_pop32_1_Slot_dot_slot2_encode, 0, Opcode_pop32_1_Slot_dot_slot0_encode, Opcode_pop32_1_Slot_pq_slot2_encode, 0, Opcode_pop32_1_Slot_pq_slot0_encode, Opcode_pop32_1_Slot_acc2_slot2_encode, 0, Opcode_pop32_1_Slot_acc2_slot0_encode, Opcode_pop32_1_Slot_smod_slot2_encode, 0, Opcode_pop32_1_Slot_smod_slot0_encode, Opcode_pop32_1_Slot_llr_slot2_encode, 0, Opcode_pop32_1_Slot_llr_slot0_encode, Opcode_pop32_1_Slot_dual_slot2_encode, 0, Opcode_pop32_1_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop32_2_encode_fns[] = { + Opcode_pop32_2_Slot_inst_encode, 0, 0, Opcode_pop32_2_Slot_gp_slot2_encode, 0, Opcode_pop32_2_Slot_gp_slot0_encode, Opcode_pop32_2_Slot_dot_slot2_encode, 0, Opcode_pop32_2_Slot_dot_slot0_encode, Opcode_pop32_2_Slot_pq_slot2_encode, 0, Opcode_pop32_2_Slot_pq_slot0_encode, Opcode_pop32_2_Slot_acc2_slot2_encode, 0, Opcode_pop32_2_Slot_acc2_slot0_encode, Opcode_pop32_2_Slot_smod_slot2_encode, 0, Opcode_pop32_2_Slot_smod_slot0_encode, Opcode_pop32_2_Slot_llr_slot2_encode, 0, Opcode_pop32_2_Slot_llr_slot0_encode, Opcode_pop32_2_Slot_dual_slot2_encode, 0, Opcode_pop32_2_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_pop32_3_encode_fns[] = { + Opcode_pop32_3_Slot_inst_encode, 0, 0, Opcode_pop32_3_Slot_gp_slot2_encode, 0, Opcode_pop32_3_Slot_gp_slot0_encode, Opcode_pop32_3_Slot_dot_slot2_encode, 0, Opcode_pop32_3_Slot_dot_slot0_encode, Opcode_pop32_3_Slot_pq_slot2_encode, 0, Opcode_pop32_3_Slot_pq_slot0_encode, Opcode_pop32_3_Slot_acc2_slot2_encode, 0, Opcode_pop32_3_Slot_acc2_slot0_encode, Opcode_pop32_3_Slot_smod_slot2_encode, 0, Opcode_pop32_3_Slot_smod_slot0_encode, Opcode_pop32_3_Slot_llr_slot2_encode, 0, Opcode_pop32_3_Slot_llr_slot0_encode, Opcode_pop32_3_Slot_dual_slot2_encode, 0, Opcode_pop32_3_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_push128_encode_fns[] = { + Opcode_push128_Slot_inst_encode, 0, 0, Opcode_push128_Slot_gp_slot2_encode, 0, Opcode_push128_Slot_gp_slot0_encode, Opcode_push128_Slot_dot_slot2_encode, 0, Opcode_push128_Slot_dot_slot0_encode, Opcode_push128_Slot_pq_slot2_encode, 0, Opcode_push128_Slot_pq_slot0_encode, Opcode_push128_Slot_acc2_slot2_encode, 0, Opcode_push128_Slot_acc2_slot0_encode, Opcode_push128_Slot_smod_slot2_encode, 0, Opcode_push128_Slot_smod_slot0_encode, Opcode_push128_Slot_llr_slot2_encode, 0, Opcode_push128_Slot_llr_slot0_encode, Opcode_push128_Slot_dual_slot2_encode, 0, Opcode_push128_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_push128_m_encode_fns[] = { + Opcode_push128_m_Slot_inst_encode, 0, 0, 0, 0, Opcode_push128_m_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_push128_m_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, Opcode_push128_m_Slot_smod_slot0_encode, 0, 0, 0, 0, 0, Opcode_push128_m_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_push128_pq_encode_fns[] = { + Opcode_push128_pq_Slot_inst_encode, 0, 0, Opcode_push128_pq_Slot_gp_slot2_encode, 0, 0, Opcode_push128_pq_Slot_dot_slot2_encode, 0, 0, Opcode_push128_pq_Slot_pq_slot2_encode, 0, 0, 0, 0, Opcode_push128_pq_Slot_acc2_slot0_encode, Opcode_push128_pq_Slot_smod_slot2_encode, 0, 0, Opcode_push128_pq_Slot_llr_slot2_encode, 0, Opcode_push128_pq_Slot_llr_slot0_encode, Opcode_push128_pq_Slot_dual_slot2_encode, 0, Opcode_push128_pq_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_push2x128_pq_encode_fns[] = { + Opcode_push2x128_pq_Slot_inst_encode, 0, 0, Opcode_push2x128_pq_Slot_gp_slot2_encode, 0, 0, Opcode_push2x128_pq_Slot_dot_slot2_encode, 0, 0, 0, 0, 0, 0, 0, Opcode_push2x128_pq_Slot_acc2_slot0_encode, Opcode_push2x128_pq_Slot_smod_slot2_encode, 0, 0, 0, 0, Opcode_push2x128_pq_Slot_llr_slot0_encode, 0, 0, Opcode_push2x128_pq_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_push32_encode_fns[] = { + Opcode_push32_Slot_inst_encode, 0, 0, Opcode_push32_Slot_gp_slot2_encode, 0, Opcode_push32_Slot_gp_slot0_encode, Opcode_push32_Slot_dot_slot2_encode, 0, Opcode_push32_Slot_dot_slot0_encode, Opcode_push32_Slot_pq_slot2_encode, 0, Opcode_push32_Slot_pq_slot0_encode, Opcode_push32_Slot_acc2_slot2_encode, 0, 0, Opcode_push32_Slot_smod_slot2_encode, 0, Opcode_push32_Slot_smod_slot0_encode, Opcode_push32_Slot_llr_slot2_encode, 0, Opcode_push32_Slot_llr_slot0_encode, Opcode_push32_Slot_dual_slot2_encode, 0, Opcode_push32_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_qready_encode_fns[] = { + Opcode_qready_Slot_inst_encode, 0, 0, Opcode_qready_Slot_gp_slot2_encode, 0, 0, Opcode_qready_Slot_dot_slot2_encode, 0, 0, Opcode_qready_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_qready_Slot_smod_slot2_encode, 0, 0, Opcode_qready_Slot_llr_slot2_encode, 0, 0, Opcode_qready_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rdtiep_encode_fns[] = { + Opcode_rdtiep_Slot_inst_encode, 0, 0, Opcode_rdtiep_Slot_gp_slot2_encode, 0, 0, Opcode_rdtiep_Slot_dot_slot2_encode, 0, 0, Opcode_rdtiep_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_rdtiep_Slot_smod_slot2_encode, 0, 0, Opcode_rdtiep_Slot_llr_slot2_encode, 0, 0, Opcode_rdtiep_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_settiep_encode_fns[] = { + Opcode_settiep_Slot_inst_encode, 0, 0, Opcode_settiep_Slot_gp_slot2_encode, 0, 0, Opcode_settiep_Slot_dot_slot2_encode, 0, 0, Opcode_settiep_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_settiep_Slot_smod_slot2_encode, 0, 0, Opcode_settiep_Slot_llr_slot2_encode, 0, 0, Opcode_settiep_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_smod_lut_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_smod_lut_Slot_smod_slot2_encode, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wrtbsigq_encode_fns[] = { + Opcode_wrtbsigq_Slot_inst_encode, 0, 0, Opcode_wrtbsigq_Slot_gp_slot2_encode, 0, 0, Opcode_wrtbsigq_Slot_dot_slot2_encode, 0, 0, Opcode_wrtbsigq_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_wrtbsigq_Slot_smod_slot2_encode, 0, 0, Opcode_wrtbsigq_Slot_llr_slot2_encode, 0, 0, Opcode_wrtbsigq_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wrtbsigqm_encode_fns[] = { + Opcode_wrtbsigqm_Slot_inst_encode, 0, 0, Opcode_wrtbsigqm_Slot_gp_slot2_encode, 0, 0, Opcode_wrtbsigqm_Slot_dot_slot2_encode, 0, 0, Opcode_wrtbsigqm_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_wrtbsigqm_Slot_smod_slot2_encode, 0, 0, Opcode_wrtbsigqm_Slot_llr_slot2_encode, 0, 0, Opcode_wrtbsigqm_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wrtiep_encode_fns[] = { + Opcode_wrtiep_Slot_inst_encode, 0, 0, Opcode_wrtiep_Slot_gp_slot2_encode, 0, 0, Opcode_wrtiep_Slot_dot_slot2_encode, 0, 0, Opcode_wrtiep_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_wrtiep_Slot_smod_slot2_encode, 0, 0, Opcode_wrtiep_Slot_llr_slot2_encode, 0, 0, Opcode_wrtiep_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wrtsigq_encode_fns[] = { + Opcode_wrtsigq_Slot_inst_encode, 0, 0, Opcode_wrtsigq_Slot_gp_slot2_encode, 0, 0, Opcode_wrtsigq_Slot_dot_slot2_encode, 0, 0, Opcode_wrtsigq_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_wrtsigq_Slot_smod_slot2_encode, 0, 0, Opcode_wrtsigq_Slot_llr_slot2_encode, 0, 0, Opcode_wrtsigq_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_abs8_encode_fns[] = { + 0, 0, 0, Opcode_abs8_Slot_gp_slot2_encode, 0, 0, Opcode_abs8_Slot_dot_slot2_encode, 0, 0, Opcode_abs8_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_abs8_Slot_smod_slot2_encode, 0, 0, Opcode_abs8_Slot_llr_slot2_encode, 0, 0, Opcode_abs8_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_add16_encode_fns[] = { + 0, 0, 0, Opcode_add16_Slot_gp_slot2_encode, 0, 0, Opcode_add16_Slot_dot_slot2_encode, 0, 0, Opcode_add16_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_add16_Slot_smod_slot2_encode, 0, 0, Opcode_add16_Slot_llr_slot2_encode, 0, 0, Opcode_add16_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_add32_encode_fns[] = { + 0, 0, 0, Opcode_add32_Slot_gp_slot2_encode, 0, 0, Opcode_add32_Slot_dot_slot2_encode, 0, 0, Opcode_add32_Slot_pq_slot2_encode, 0, 0, Opcode_add32_Slot_acc2_slot2_encode, 0, 0, Opcode_add32_Slot_smod_slot2_encode, 0, 0, Opcode_add32_Slot_llr_slot2_encode, 0, 0, Opcode_add32_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addac_i2r_encode_fns[] = { + Opcode_addac_i2r_Slot_inst_encode, 0, 0, 0, 0, Opcode_addac_i2r_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_addac_i2r_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_addac_i2r_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_addac_r2i_encode_fns[] = { + Opcode_addac_r2i_Slot_inst_encode, 0, 0, 0, 0, Opcode_addac_r2i_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_addac_r2i_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_addac_r2i_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_addar2_encode_fns[] = { + 0, 0, 0, Opcode_addar2_Slot_gp_slot2_encode, 0, 0, Opcode_addar2_Slot_dot_slot2_encode, 0, 0, Opcode_addar2_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_addar2_Slot_smod_slot2_encode, 0, 0, Opcode_addar2_Slot_llr_slot2_encode, 0, 0, Opcode_addar2_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addcm_encode_fns[] = { + 0, 0, 0, Opcode_addcm_Slot_gp_slot2_encode, 0, 0, Opcode_addcm_Slot_dot_slot2_encode, 0, 0, Opcode_addcm_Slot_pq_slot2_encode, 0, 0, Opcode_addcm_Slot_acc2_slot2_encode, 0, 0, Opcode_addcm_Slot_smod_slot2_encode, 0, 0, Opcode_addcm_Slot_llr_slot2_encode, 0, 0, Opcode_addcm_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addwrp_encode_fns[] = { + 0, 0, 0, Opcode_addwrp_Slot_gp_slot2_encode, 0, 0, Opcode_addwrp_Slot_dot_slot2_encode, 0, 0, Opcode_addwrp_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_addwrp_Slot_smod_slot2_encode, 0, 0, Opcode_addwrp_Slot_llr_slot2_encode, 0, 0, Opcode_addwrp_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_and128_encode_fns[] = { + 0, 0, 0, Opcode_and128_Slot_gp_slot2_encode, 0, 0, Opcode_and128_Slot_dot_slot2_encode, 0, 0, Opcode_and128_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_and128_Slot_smod_slot2_encode, 0, 0, Opcode_and128_Slot_llr_slot2_encode, 0, 0, Opcode_and128_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_argmax8_encode_fns[] = { + 0, 0, 0, Opcode_argmax8_Slot_gp_slot2_encode, 0, 0, Opcode_argmax8_Slot_dot_slot2_encode, 0, 0, Opcode_argmax8_Slot_pq_slot2_encode, 0, 0, Opcode_argmax8_Slot_acc2_slot2_encode, 0, 0, Opcode_argmax8_Slot_smod_slot2_encode, 0, 0, Opcode_argmax8_Slot_llr_slot2_encode, 0, 0, Opcode_argmax8_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_asl_encode_fns[] = { + 0, 0, 0, Opcode_asl_Slot_gp_slot2_encode, 0, 0, Opcode_asl_Slot_dot_slot2_encode, 0, 0, Opcode_asl_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_asl_Slot_smod_slot2_encode, 0, 0, Opcode_asl_Slot_llr_slot2_encode, 0, 0, Opcode_asl_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_asl32_encode_fns[] = { + 0, 0, 0, Opcode_asl32_Slot_gp_slot2_encode, 0, 0, Opcode_asl32_Slot_dot_slot2_encode, 0, 0, Opcode_asl32_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_asl32_Slot_smod_slot2_encode, 0, 0, Opcode_asl32_Slot_llr_slot2_encode, 0, 0, Opcode_asl32_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_aslacm_encode_fns[] = { + Opcode_aslacm_Slot_inst_encode, 0, 0, 0, 0, Opcode_aslacm_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_aslacm_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_aslacm_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_aslm_encode_fns[] = { + 0, 0, 0, Opcode_aslm_Slot_gp_slot2_encode, 0, 0, Opcode_aslm_Slot_dot_slot2_encode, 0, 0, Opcode_aslm_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_aslm_Slot_smod_slot2_encode, 0, 0, Opcode_aslm_Slot_llr_slot2_encode, 0, 0, Opcode_aslm_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_aslm32_encode_fns[] = { + 0, 0, 0, Opcode_aslm32_Slot_gp_slot2_encode, 0, 0, Opcode_aslm32_Slot_dot_slot2_encode, 0, 0, Opcode_aslm32_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_aslm32_Slot_smod_slot2_encode, 0, 0, Opcode_aslm32_Slot_llr_slot2_encode, 0, 0, Opcode_aslm32_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_asr_encode_fns[] = { + 0, 0, 0, Opcode_asr_Slot_gp_slot2_encode, 0, 0, Opcode_asr_Slot_dot_slot2_encode, 0, 0, Opcode_asr_Slot_pq_slot2_encode, 0, 0, Opcode_asr_Slot_acc2_slot2_encode, 0, 0, Opcode_asr_Slot_smod_slot2_encode, 0, 0, Opcode_asr_Slot_llr_slot2_encode, 0, 0, Opcode_asr_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_asr32_encode_fns[] = { + 0, 0, 0, Opcode_asr32_Slot_gp_slot2_encode, 0, 0, Opcode_asr32_Slot_dot_slot2_encode, 0, 0, Opcode_asr32_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_asr32_Slot_smod_slot2_encode, 0, 0, Opcode_asr32_Slot_llr_slot2_encode, 0, 0, Opcode_asr32_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_asrac_encode_fns[] = { + Opcode_asrac_Slot_inst_encode, 0, 0, 0, 0, Opcode_asrac_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_asrac_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_asrac_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_asrm_encode_fns[] = { + 0, 0, 0, Opcode_asrm_Slot_gp_slot2_encode, 0, 0, Opcode_asrm_Slot_dot_slot2_encode, 0, 0, Opcode_asrm_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_asrm_Slot_smod_slot2_encode, 0, 0, Opcode_asrm_Slot_llr_slot2_encode, 0, 0, Opcode_asrm_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bitfext_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bitfext_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bitfins_encode_fns[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_bitfins_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_clb_c_encode_fns[] = { + Opcode_clb_c_Slot_inst_encode, 0, 0, 0, 0, Opcode_clb_c_Slot_gp_slot0_encode, 0, 0, Opcode_clb_c_Slot_dot_slot0_encode, 0, 0, Opcode_clb_c_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_clb_c_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_clb_r_encode_fns[] = { + Opcode_clb_r_Slot_inst_encode, 0, 0, 0, 0, Opcode_clb_r_Slot_gp_slot0_encode, 0, 0, Opcode_clb_r_Slot_dot_slot0_encode, 0, 0, Opcode_clb_r_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_clb_r_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_cmp8_encode_fns[] = { + 0, 0, 0, Opcode_cmp8_Slot_gp_slot2_encode, 0, 0, Opcode_cmp8_Slot_dot_slot2_encode, 0, 0, Opcode_cmp8_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_cmp8_Slot_smod_slot2_encode, 0, 0, Opcode_cmp8_Slot_llr_slot2_encode, 0, 0, Opcode_cmp8_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_cmp_i_encode_fns[] = { + 0, 0, 0, Opcode_cmp_i_Slot_gp_slot2_encode, 0, 0, Opcode_cmp_i_Slot_dot_slot2_encode, 0, 0, Opcode_cmp_i_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_cmp_i_Slot_smod_slot2_encode, 0, 0, Opcode_cmp_i_Slot_llr_slot2_encode, 0, 0, Opcode_cmp_i_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_cmp_r_encode_fns[] = { + 0, 0, 0, Opcode_cmp_r_Slot_gp_slot2_encode, 0, 0, Opcode_cmp_r_Slot_dot_slot2_encode, 0, 0, Opcode_cmp_r_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_cmp_r_Slot_smod_slot2_encode, 0, 0, Opcode_cmp_r_Slot_llr_slot2_encode, 0, 0, Opcode_cmp_r_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ext_encode_fns[] = { + Opcode_ext_Slot_inst_encode, 0, 0, 0, 0, Opcode_ext_Slot_gp_slot0_encode, 0, 0, Opcode_ext_Slot_dot_slot0_encode, 0, 0, Opcode_ext_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ext_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ext_r_encode_fns[] = { + Opcode_ext_r_Slot_inst_encode, 0, 0, 0, 0, Opcode_ext_r_Slot_gp_slot0_encode, 0, 0, Opcode_ext_r_Slot_dot_slot0_encode, 0, 0, Opcode_ext_r_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ext_r_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ext32_i_encode_fns[] = { + Opcode_ext32_i_Slot_inst_encode, 0, 0, 0, 0, Opcode_ext32_i_Slot_gp_slot0_encode, 0, 0, Opcode_ext32_i_Slot_dot_slot0_encode, 0, 0, Opcode_ext32_i_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ext32_i_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_ext32_r_encode_fns[] = { + Opcode_ext32_r_Slot_inst_encode, 0, 0, 0, 0, Opcode_ext32_r_Slot_gp_slot0_encode, 0, 0, Opcode_ext32_r_Slot_dot_slot0_encode, 0, 0, Opcode_ext32_r_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_ext32_r_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_extui4_encode_fns[] = { + 0, 0, 0, Opcode_extui4_Slot_gp_slot2_encode, 0, 0, Opcode_extui4_Slot_dot_slot2_encode, 0, 0, Opcode_extui4_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_extui4_Slot_smod_slot2_encode, 0, 0, Opcode_extui4_Slot_llr_slot2_encode, 0, 0, Opcode_extui4_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lslm_encode_fns[] = { + 0, 0, 0, Opcode_lslm_Slot_gp_slot2_encode, 0, 0, Opcode_lslm_Slot_dot_slot2_encode, 0, 0, Opcode_lslm_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_lslm_Slot_smod_slot2_encode, 0, 0, Opcode_lslm_Slot_llr_slot2_encode, 0, 0, Opcode_lslm_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lsrm_encode_fns[] = { + 0, 0, 0, Opcode_lsrm_Slot_gp_slot2_encode, 0, 0, Opcode_lsrm_Slot_dot_slot2_encode, 0, 0, Opcode_lsrm_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_lsrm_Slot_smod_slot2_encode, 0, 0, Opcode_lsrm_Slot_llr_slot2_encode, 0, 0, Opcode_lsrm_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_max8_encode_fns[] = { + 0, 0, 0, Opcode_max8_Slot_gp_slot2_encode, 0, 0, Opcode_max8_Slot_dot_slot2_encode, 0, 0, Opcode_max8_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_max8_Slot_smod_slot2_encode, 0, 0, Opcode_max8_Slot_llr_slot2_encode, 0, 0, Opcode_max8_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mean_encode_fns[] = { + 0, 0, 0, Opcode_mean_Slot_gp_slot2_encode, 0, 0, Opcode_mean_Slot_dot_slot2_encode, 0, 0, Opcode_mean_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_mean_Slot_smod_slot2_encode, 0, 0, Opcode_mean_Slot_llr_slot2_encode, 0, 0, Opcode_mean_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mean32_encode_fns[] = { + 0, 0, 0, Opcode_mean32_Slot_gp_slot2_encode, 0, 0, Opcode_mean32_Slot_dot_slot2_encode, 0, 0, Opcode_mean32_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_mean32_Slot_smod_slot2_encode, 0, 0, Opcode_mean32_Slot_llr_slot2_encode, 0, 0, Opcode_mean32_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_min8_encode_fns[] = { + 0, 0, 0, Opcode_min8_Slot_gp_slot2_encode, 0, 0, Opcode_min8_Slot_dot_slot2_encode, 0, 0, Opcode_min8_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_min8_Slot_smod_slot2_encode, 0, 0, Opcode_min8_Slot_llr_slot2_encode, 0, 0, Opcode_min8_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_minclb_c_encode_fns[] = { + Opcode_minclb_c_Slot_inst_encode, 0, 0, 0, 0, Opcode_minclb_c_Slot_gp_slot0_encode, 0, 0, Opcode_minclb_c_Slot_dot_slot0_encode, 0, 0, Opcode_minclb_c_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_minclb_c_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_minclb_r_encode_fns[] = { + Opcode_minclb_r_Slot_inst_encode, 0, 0, 0, 0, Opcode_minclb_r_Slot_gp_slot0_encode, 0, 0, Opcode_minclb_r_Slot_dot_slot0_encode, 0, 0, Opcode_minclb_r_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_minclb_r_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_not128_encode_fns[] = { + 0, 0, 0, Opcode_not128_Slot_gp_slot2_encode, 0, 0, Opcode_not128_Slot_dot_slot2_encode, 0, 0, Opcode_not128_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_not128_Slot_smod_slot2_encode, 0, 0, Opcode_not128_Slot_llr_slot2_encode, 0, 0, Opcode_not128_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_or128_encode_fns[] = { + 0, 0, 0, Opcode_or128_Slot_gp_slot2_encode, 0, 0, Opcode_or128_Slot_dot_slot2_encode, 0, 0, Opcode_or128_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_or128_Slot_smod_slot2_encode, 0, 0, Opcode_or128_Slot_llr_slot2_encode, 0, 0, Opcode_or128_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_perm_encode_fns[] = { + 0, 0, 0, Opcode_perm_Slot_gp_slot2_encode, 0, 0, Opcode_perm_Slot_dot_slot2_encode, 0, 0, Opcode_perm_Slot_pq_slot2_encode, 0, 0, Opcode_perm_Slot_acc2_slot2_encode, 0, 0, Opcode_perm_Slot_smod_slot2_encode, 0, 0, Opcode_perm_Slot_llr_slot2_encode, 0, 0, Opcode_perm_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_redac_encode_fns[] = { + Opcode_redac_Slot_inst_encode, 0, 0, 0, 0, Opcode_redac_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_redac_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_redac_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_redac2_encode_fns[] = { + Opcode_redac2_Slot_inst_encode, 0, 0, 0, 0, Opcode_redac2_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_redac2_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_redac2_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_redac4_encode_fns[] = { + Opcode_redac4_Slot_inst_encode, 0, 0, 0, 0, Opcode_redac4_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_redac4_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_redac4_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_redacs_encode_fns[] = { + Opcode_redacs_Slot_inst_encode, 0, 0, 0, 0, Opcode_redacs_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_redacs_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_redacs_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sminclb_c_encode_fns[] = { + Opcode_sminclb_c_Slot_inst_encode, 0, 0, 0, 0, Opcode_sminclb_c_Slot_gp_slot0_encode, 0, 0, Opcode_sminclb_c_Slot_dot_slot0_encode, 0, 0, Opcode_sminclb_c_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_sminclb_c_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sminclb_r_encode_fns[] = { + Opcode_sminclb_r_Slot_inst_encode, 0, 0, 0, 0, Opcode_sminclb_r_Slot_gp_slot0_encode, 0, 0, Opcode_sminclb_r_Slot_dot_slot0_encode, 0, 0, Opcode_sminclb_r_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_sminclb_r_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_stswapbm_encode_fns[] = { + Opcode_stswapbm_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_stswapbm_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_stswapbmu_encode_fns[] = { + Opcode_stswapbmu_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_stswapbmu_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_sub32_encode_fns[] = { + 0, 0, 0, Opcode_sub32_Slot_gp_slot2_encode, 0, 0, Opcode_sub32_Slot_dot_slot2_encode, 0, 0, Opcode_sub32_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_sub32_Slot_smod_slot2_encode, 0, 0, Opcode_sub32_Slot_llr_slot2_encode, 0, 0, Opcode_sub32_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_subac_i2r_encode_fns[] = { + Opcode_subac_i2r_Slot_inst_encode, 0, 0, 0, 0, Opcode_subac_i2r_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_subac_i2r_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_subac_i2r_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_subac_r2i_encode_fns[] = { + Opcode_subac_r2i_Slot_inst_encode, 0, 0, 0, 0, Opcode_subac_r2i_Slot_gp_slot0_encode, 0, 0, 0, 0, 0, Opcode_subac_r2i_Slot_pq_slot0_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Opcode_subac_r2i_Slot_dual_slot0_encode +}; + +static xtensa_opcode_encode_fn Opcode_subarx_encode_fns[] = { + 0, 0, 0, Opcode_subarx_Slot_gp_slot2_encode, 0, 0, Opcode_subarx_Slot_dot_slot2_encode, 0, 0, Opcode_subarx_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_subarx_Slot_smod_slot2_encode, 0, 0, Opcode_subarx_Slot_llr_slot2_encode, 0, 0, Opcode_subarx_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_subcm_encode_fns[] = { + 0, 0, 0, Opcode_subcm_Slot_gp_slot2_encode, 0, 0, Opcode_subcm_Slot_dot_slot2_encode, 0, 0, Opcode_subcm_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_subcm_Slot_smod_slot2_encode, 0, 0, Opcode_subcm_Slot_llr_slot2_encode, 0, 0, Opcode_subcm_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_submean_encode_fns[] = { + 0, 0, 0, Opcode_submean_Slot_gp_slot2_encode, 0, 0, Opcode_submean_Slot_dot_slot2_encode, 0, 0, Opcode_submean_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_submean_Slot_smod_slot2_encode, 0, 0, Opcode_submean_Slot_llr_slot2_encode, 0, 0, Opcode_submean_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_subwrp_encode_fns[] = { + 0, 0, 0, Opcode_subwrp_Slot_gp_slot2_encode, 0, 0, Opcode_subwrp_Slot_dot_slot2_encode, 0, 0, Opcode_subwrp_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_subwrp_Slot_smod_slot2_encode, 0, 0, Opcode_subwrp_Slot_llr_slot2_encode, 0, 0, Opcode_subwrp_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_trans_encode_fns[] = { + 0, 0, 0, Opcode_trans_Slot_gp_slot2_encode, 0, 0, Opcode_trans_Slot_dot_slot2_encode, 0, 0, Opcode_trans_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_trans_Slot_smod_slot2_encode, 0, 0, Opcode_trans_Slot_llr_slot2_encode, 0, 0, Opcode_trans_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xor128_encode_fns[] = { + 0, 0, 0, Opcode_xor128_Slot_gp_slot2_encode, 0, 0, Opcode_xor128_Slot_dot_slot2_encode, 0, 0, Opcode_xor128_Slot_pq_slot2_encode, 0, 0, 0, 0, 0, Opcode_xor128_Slot_smod_slot2_encode, 0, 0, Opcode_xor128_Slot_llr_slot2_encode, 0, 0, Opcode_xor128_Slot_dual_slot2_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_expstate_encode_fns[] = { + Opcode_rur_expstate_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_expstate_encode_fns[] = { + Opcode_wur_expstate_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_sov_encode_fns[] = { + Opcode_rur_sov_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_sov_encode_fns[] = { + Opcode_wur_sov_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_sat_mode_encode_fns[] = { + Opcode_rur_sat_mode_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_sat_mode_encode_fns[] = { + Opcode_wur_sat_mode_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_sar0_encode_fns[] = { + Opcode_rur_sar0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_sar0_encode_fns[] = { + Opcode_wur_sar0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_sar1_encode_fns[] = { + Opcode_rur_sar1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_sar1_encode_fns[] = { + Opcode_wur_sar1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_sar2_encode_fns[] = { + Opcode_rur_sar2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_sar2_encode_fns[] = { + Opcode_wur_sar2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_sar3_encode_fns[] = { + Opcode_rur_sar3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_sar3_encode_fns[] = { + Opcode_wur_sar3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_hsar0_encode_fns[] = { + Opcode_rur_hsar0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_hsar0_encode_fns[] = { + Opcode_wur_hsar0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_hsar1_encode_fns[] = { + Opcode_rur_hsar1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_hsar1_encode_fns[] = { + Opcode_wur_hsar1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_hsar2_encode_fns[] = { + Opcode_rur_hsar2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_hsar2_encode_fns[] = { + Opcode_wur_hsar2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_hsar3_encode_fns[] = { + Opcode_rur_hsar3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_hsar3_encode_fns[] = { + Opcode_wur_hsar3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_max_reg_0_encode_fns[] = { + Opcode_rur_max_reg_0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_max_reg_0_encode_fns[] = { + Opcode_wur_max_reg_0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_max_reg_1_encode_fns[] = { + Opcode_rur_max_reg_1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_max_reg_1_encode_fns[] = { + Opcode_wur_max_reg_1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_max_reg_2_encode_fns[] = { + Opcode_rur_max_reg_2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_max_reg_2_encode_fns[] = { + Opcode_wur_max_reg_2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_max_reg_3_encode_fns[] = { + Opcode_rur_max_reg_3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_max_reg_3_encode_fns[] = { + Opcode_wur_max_reg_3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_arg_max_reg_0_encode_fns[] = { + Opcode_rur_arg_max_reg_0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_arg_max_reg_0_encode_fns[] = { + Opcode_wur_arg_max_reg_0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_arg_max_reg_1_encode_fns[] = { + Opcode_rur_arg_max_reg_1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_arg_max_reg_1_encode_fns[] = { + Opcode_wur_arg_max_reg_1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_arg_max_reg_2_encode_fns[] = { + Opcode_rur_arg_max_reg_2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_arg_max_reg_2_encode_fns[] = { + Opcode_wur_arg_max_reg_2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_arg_max_reg_3_encode_fns[] = { + Opcode_rur_arg_max_reg_3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_arg_max_reg_3_encode_fns[] = { + Opcode_wur_arg_max_reg_3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_nco_counter_0_encode_fns[] = { + Opcode_rur_nco_counter_0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_nco_counter_0_encode_fns[] = { + Opcode_wur_nco_counter_0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_nco_counter_1_encode_fns[] = { + Opcode_rur_nco_counter_1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_nco_counter_1_encode_fns[] = { + Opcode_wur_nco_counter_1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_nco_counter_2_encode_fns[] = { + Opcode_rur_nco_counter_2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_nco_counter_2_encode_fns[] = { + Opcode_wur_nco_counter_2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_nco_counter_3_encode_fns[] = { + Opcode_rur_nco_counter_3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_nco_counter_3_encode_fns[] = { + Opcode_wur_nco_counter_3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_interp_ext_n_encode_fns[] = { + Opcode_rur_interp_ext_n_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_interp_ext_n_encode_fns[] = { + Opcode_wur_interp_ext_n_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_interp_ext_l_encode_fns[] = { + Opcode_rur_interp_ext_l_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_interp_ext_l_encode_fns[] = { + Opcode_wur_interp_ext_l_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_0_encode_fns[] = { + Opcode_rur_llr_buf_0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_0_encode_fns[] = { + Opcode_wur_llr_buf_0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_1_encode_fns[] = { + Opcode_rur_llr_buf_1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_1_encode_fns[] = { + Opcode_wur_llr_buf_1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_2_encode_fns[] = { + Opcode_rur_llr_buf_2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_2_encode_fns[] = { + Opcode_wur_llr_buf_2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_3_encode_fns[] = { + Opcode_rur_llr_buf_3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_3_encode_fns[] = { + Opcode_wur_llr_buf_3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_4_encode_fns[] = { + Opcode_rur_llr_buf_4_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_4_encode_fns[] = { + Opcode_wur_llr_buf_4_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_5_encode_fns[] = { + Opcode_rur_llr_buf_5_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_5_encode_fns[] = { + Opcode_wur_llr_buf_5_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_6_encode_fns[] = { + Opcode_rur_llr_buf_6_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_6_encode_fns[] = { + Opcode_wur_llr_buf_6_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_7_encode_fns[] = { + Opcode_rur_llr_buf_7_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_7_encode_fns[] = { + Opcode_wur_llr_buf_7_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_8_encode_fns[] = { + Opcode_rur_llr_buf_8_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_8_encode_fns[] = { + Opcode_wur_llr_buf_8_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_9_encode_fns[] = { + Opcode_rur_llr_buf_9_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_9_encode_fns[] = { + Opcode_wur_llr_buf_9_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_10_encode_fns[] = { + Opcode_rur_llr_buf_10_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_10_encode_fns[] = { + Opcode_wur_llr_buf_10_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_11_encode_fns[] = { + Opcode_rur_llr_buf_11_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_11_encode_fns[] = { + Opcode_wur_llr_buf_11_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_12_encode_fns[] = { + Opcode_rur_llr_buf_12_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_12_encode_fns[] = { + Opcode_wur_llr_buf_12_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_13_encode_fns[] = { + Opcode_rur_llr_buf_13_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_13_encode_fns[] = { + Opcode_wur_llr_buf_13_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_14_encode_fns[] = { + Opcode_rur_llr_buf_14_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_14_encode_fns[] = { + Opcode_wur_llr_buf_14_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_15_encode_fns[] = { + Opcode_rur_llr_buf_15_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_15_encode_fns[] = { + Opcode_wur_llr_buf_15_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_16_encode_fns[] = { + Opcode_rur_llr_buf_16_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_16_encode_fns[] = { + Opcode_wur_llr_buf_16_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_17_encode_fns[] = { + Opcode_rur_llr_buf_17_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_17_encode_fns[] = { + Opcode_wur_llr_buf_17_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_18_encode_fns[] = { + Opcode_rur_llr_buf_18_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_18_encode_fns[] = { + Opcode_wur_llr_buf_18_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_19_encode_fns[] = { + Opcode_rur_llr_buf_19_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_19_encode_fns[] = { + Opcode_wur_llr_buf_19_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_20_encode_fns[] = { + Opcode_rur_llr_buf_20_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_20_encode_fns[] = { + Opcode_wur_llr_buf_20_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_21_encode_fns[] = { + Opcode_rur_llr_buf_21_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_21_encode_fns[] = { + Opcode_wur_llr_buf_21_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_22_encode_fns[] = { + Opcode_rur_llr_buf_22_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_22_encode_fns[] = { + Opcode_wur_llr_buf_22_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_buf_23_encode_fns[] = { + Opcode_rur_llr_buf_23_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_buf_23_encode_fns[] = { + Opcode_wur_llr_buf_23_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_smod_buf_0_encode_fns[] = { + Opcode_rur_smod_buf_0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_smod_buf_0_encode_fns[] = { + Opcode_wur_smod_buf_0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_smod_buf_1_encode_fns[] = { + Opcode_rur_smod_buf_1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_smod_buf_1_encode_fns[] = { + Opcode_wur_smod_buf_1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_smod_buf_2_encode_fns[] = { + Opcode_rur_smod_buf_2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_smod_buf_2_encode_fns[] = { + Opcode_wur_smod_buf_2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_smod_buf_3_encode_fns[] = { + Opcode_rur_smod_buf_3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_smod_buf_3_encode_fns[] = { + Opcode_wur_smod_buf_3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_smod_buf_4_encode_fns[] = { + Opcode_rur_smod_buf_4_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_smod_buf_4_encode_fns[] = { + Opcode_wur_smod_buf_4_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_smod_buf_5_encode_fns[] = { + Opcode_rur_smod_buf_5_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_smod_buf_5_encode_fns[] = { + Opcode_wur_smod_buf_5_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_smod_buf_6_encode_fns[] = { + Opcode_rur_smod_buf_6_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_smod_buf_6_encode_fns[] = { + Opcode_wur_smod_buf_6_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_smod_buf_7_encode_fns[] = { + Opcode_rur_smod_buf_7_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_smod_buf_7_encode_fns[] = { + Opcode_wur_smod_buf_7_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_weight_reg_encode_fns[] = { + Opcode_rur_weight_reg_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_weight_reg_encode_fns[] = { + Opcode_wur_weight_reg_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_scale_reg_encode_fns[] = { + Opcode_rur_scale_reg_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_scale_reg_encode_fns[] = { + Opcode_wur_scale_reg_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_llr_pos_encode_fns[] = { + Opcode_rur_llr_pos_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_llr_pos_encode_fns[] = { + Opcode_wur_llr_pos_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_smod_pos_encode_fns[] = { + Opcode_rur_smod_pos_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_smod_pos_encode_fns[] = { + Opcode_wur_smod_pos_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_perm_reg_encode_fns[] = { + Opcode_rur_perm_reg_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_perm_reg_encode_fns[] = { + Opcode_wur_perm_reg_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_smod_offset_table_0_encode_fns[] = { + Opcode_rur_smod_offset_table_0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_smod_offset_table_0_encode_fns[] = { + Opcode_wur_smod_offset_table_0_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_smod_offset_table_1_encode_fns[] = { + Opcode_rur_smod_offset_table_1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_smod_offset_table_1_encode_fns[] = { + Opcode_wur_smod_offset_table_1_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_smod_offset_table_2_encode_fns[] = { + Opcode_rur_smod_offset_table_2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_smod_offset_table_2_encode_fns[] = { + Opcode_wur_smod_offset_table_2_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_smod_offset_table_3_encode_fns[] = { + Opcode_rur_smod_offset_table_3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_smod_offset_table_3_encode_fns[] = { + Opcode_wur_smod_offset_table_3_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_phasor_n_encode_fns[] = { + Opcode_rur_phasor_n_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_phasor_n_encode_fns[] = { + Opcode_wur_phasor_n_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_phasor_offset_encode_fns[] = { + Opcode_rur_phasor_offset_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_phasor_offset_encode_fns[] = { + Opcode_wur_phasor_offset_Slot_inst_encode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + + +/* Opcode table. */ + +static xtensa_opcode_internal opcodes[] = { + { "excw", ICLASS_xt_iclass_excw, + 0, + Opcode_excw_encode_fns, 0, 0 }, + { "rfe", ICLASS_xt_iclass_rfe, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfe_encode_fns, 0, 0 }, + { "rfde", ICLASS_xt_iclass_rfde, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfde_encode_fns, 0, 0 }, + { "syscall", ICLASS_xt_iclass_syscall, + 0, + Opcode_syscall_encode_fns, 0, 0 }, + { "simcall", ICLASS_xt_iclass_simcall, + 0, + Opcode_simcall_encode_fns, 0, 0 }, + { "call12", ICLASS_xt_iclass_call12, + XTENSA_OPCODE_IS_CALL, + Opcode_call12_encode_fns, 0, 0 }, + { "call8", ICLASS_xt_iclass_call8, + XTENSA_OPCODE_IS_CALL, + Opcode_call8_encode_fns, 0, 0 }, + { "call4", ICLASS_xt_iclass_call4, + XTENSA_OPCODE_IS_CALL, + Opcode_call4_encode_fns, 0, 0 }, + { "callx12", ICLASS_xt_iclass_callx12, + XTENSA_OPCODE_IS_CALL, + Opcode_callx12_encode_fns, 0, 0 }, + { "callx8", ICLASS_xt_iclass_callx8, + XTENSA_OPCODE_IS_CALL, + Opcode_callx8_encode_fns, 0, 0 }, + { "callx4", ICLASS_xt_iclass_callx4, + XTENSA_OPCODE_IS_CALL, + Opcode_callx4_encode_fns, 0, 0 }, + { "entry", ICLASS_xt_iclass_entry, + 0, + Opcode_entry_encode_fns, 0, 0 }, + { "movsp", ICLASS_xt_iclass_movsp, + 0, + Opcode_movsp_encode_fns, 0, 0 }, + { "rotw", ICLASS_xt_iclass_rotw, + 0, + Opcode_rotw_encode_fns, 0, 0 }, + { "retw", ICLASS_xt_iclass_retw, + XTENSA_OPCODE_IS_JUMP, + Opcode_retw_encode_fns, 0, 0 }, + { "retw.n", ICLASS_xt_iclass_retw, + XTENSA_OPCODE_IS_JUMP, + Opcode_retw_n_encode_fns, 0, 0 }, + { "rfwo", ICLASS_xt_iclass_rfwou, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfwo_encode_fns, 0, 0 }, + { "rfwu", ICLASS_xt_iclass_rfwou, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfwu_encode_fns, 0, 0 }, + { "l32e", ICLASS_xt_iclass_l32e, + 0, + Opcode_l32e_encode_fns, 0, 0 }, + { "s32e", ICLASS_xt_iclass_s32e, + 0, + Opcode_s32e_encode_fns, 0, 0 }, + { "rsr.windowbase", ICLASS_xt_iclass_rsr_windowbase, + 0, + Opcode_rsr_windowbase_encode_fns, 0, 0 }, + { "wsr.windowbase", ICLASS_xt_iclass_wsr_windowbase, + 0, + Opcode_wsr_windowbase_encode_fns, 0, 0 }, + { "xsr.windowbase", ICLASS_xt_iclass_xsr_windowbase, + 0, + Opcode_xsr_windowbase_encode_fns, 0, 0 }, + { "rsr.windowstart", ICLASS_xt_iclass_rsr_windowstart, + 0, + Opcode_rsr_windowstart_encode_fns, 0, 0 }, + { "wsr.windowstart", ICLASS_xt_iclass_wsr_windowstart, + 0, + Opcode_wsr_windowstart_encode_fns, 0, 0 }, + { "xsr.windowstart", ICLASS_xt_iclass_xsr_windowstart, + 0, + Opcode_xsr_windowstart_encode_fns, 0, 0 }, + { "add.n", ICLASS_xt_iclass_add_n, + 0, + Opcode_add_n_encode_fns, 0, 0 }, + { "addi.n", ICLASS_xt_iclass_addi_n, + 0, + Opcode_addi_n_encode_fns, 0, 0 }, + { "beqz.n", ICLASS_xt_iclass_bz6, + XTENSA_OPCODE_IS_BRANCH, + Opcode_beqz_n_encode_fns, 0, 0 }, + { "bnez.n", ICLASS_xt_iclass_bz6, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bnez_n_encode_fns, 0, 0 }, + { "ill.n", ICLASS_xt_iclass_ill_n, + 0, + Opcode_ill_n_encode_fns, 0, 0 }, + { "l32i.n", ICLASS_xt_iclass_loadi4, + 0, + Opcode_l32i_n_encode_fns, 0, 0 }, + { "mov.n", ICLASS_xt_iclass_mov_n, + 0, + Opcode_mov_n_encode_fns, 0, 0 }, + { "movi.n", ICLASS_xt_iclass_movi_n, + 0, + Opcode_movi_n_encode_fns, 0, 0 }, + { "nop.n", ICLASS_xt_iclass_nopn, + 0, + Opcode_nop_n_encode_fns, 0, 0 }, + { "ret.n", ICLASS_xt_iclass_retn, + XTENSA_OPCODE_IS_JUMP, + Opcode_ret_n_encode_fns, 0, 0 }, + { "s32i.n", ICLASS_xt_iclass_storei4, + 0, + Opcode_s32i_n_encode_fns, 0, 0 }, + { "rur.threadptr", ICLASS_rur_threadptr, + 0, + Opcode_rur_threadptr_encode_fns, 0, 0 }, + { "wur.threadptr", ICLASS_wur_threadptr, + 0, + Opcode_wur_threadptr_encode_fns, 0, 0 }, + { "addi", ICLASS_xt_iclass_addi, + 0, + Opcode_addi_encode_fns, 0, 0 }, + { "addmi", ICLASS_xt_iclass_addmi, + 0, + Opcode_addmi_encode_fns, 0, 0 }, + { "add", ICLASS_xt_iclass_addsub, + 0, + Opcode_add_encode_fns, 0, 0 }, + { "sub", ICLASS_xt_iclass_addsub, + 0, + Opcode_sub_encode_fns, 0, 0 }, + { "addx2", ICLASS_xt_iclass_addsub, + 0, + Opcode_addx2_encode_fns, 0, 0 }, + { "addx4", ICLASS_xt_iclass_addsub, + 0, + Opcode_addx4_encode_fns, 0, 0 }, + { "addx8", ICLASS_xt_iclass_addsub, + 0, + Opcode_addx8_encode_fns, 0, 0 }, + { "subx2", ICLASS_xt_iclass_addsub, + 0, + Opcode_subx2_encode_fns, 0, 0 }, + { "subx4", ICLASS_xt_iclass_addsub, + 0, + Opcode_subx4_encode_fns, 0, 0 }, + { "subx8", ICLASS_xt_iclass_addsub, + 0, + Opcode_subx8_encode_fns, 0, 0 }, + { "and", ICLASS_xt_iclass_bit, + 0, + Opcode_and_encode_fns, 0, 0 }, + { "or", ICLASS_xt_iclass_bit, + 0, + Opcode_or_encode_fns, 0, 0 }, + { "xor", ICLASS_xt_iclass_bit, + 0, + Opcode_xor_encode_fns, 0, 0 }, + { "beqi", ICLASS_xt_iclass_bsi8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_beqi_encode_fns, 0, 0 }, + { "bnei", ICLASS_xt_iclass_bsi8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bnei_encode_fns, 0, 0 }, + { "bgei", ICLASS_xt_iclass_bsi8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bgei_encode_fns, 0, 0 }, + { "blti", ICLASS_xt_iclass_bsi8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_blti_encode_fns, 0, 0 }, + { "bbci", ICLASS_xt_iclass_bsi8b, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bbci_encode_fns, 0, 0 }, + { "bbsi", ICLASS_xt_iclass_bsi8b, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bbsi_encode_fns, 0, 0 }, + { "bgeui", ICLASS_xt_iclass_bsi8u, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bgeui_encode_fns, 0, 0 }, + { "bltui", ICLASS_xt_iclass_bsi8u, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bltui_encode_fns, 0, 0 }, + { "beq", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_beq_encode_fns, 0, 0 }, + { "bne", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bne_encode_fns, 0, 0 }, + { "bge", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bge_encode_fns, 0, 0 }, + { "blt", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_blt_encode_fns, 0, 0 }, + { "bgeu", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bgeu_encode_fns, 0, 0 }, + { "bltu", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bltu_encode_fns, 0, 0 }, + { "bany", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bany_encode_fns, 0, 0 }, + { "bnone", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bnone_encode_fns, 0, 0 }, + { "ball", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_ball_encode_fns, 0, 0 }, + { "bnall", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bnall_encode_fns, 0, 0 }, + { "bbc", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bbc_encode_fns, 0, 0 }, + { "bbs", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bbs_encode_fns, 0, 0 }, + { "beqz", ICLASS_xt_iclass_bsz12, + XTENSA_OPCODE_IS_BRANCH, + Opcode_beqz_encode_fns, 0, 0 }, + { "bnez", ICLASS_xt_iclass_bsz12, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bnez_encode_fns, 0, 0 }, + { "bgez", ICLASS_xt_iclass_bsz12, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bgez_encode_fns, 0, 0 }, + { "bltz", ICLASS_xt_iclass_bsz12, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bltz_encode_fns, 0, 0 }, + { "call0", ICLASS_xt_iclass_call0, + XTENSA_OPCODE_IS_CALL, + Opcode_call0_encode_fns, 0, 0 }, + { "callx0", ICLASS_xt_iclass_callx0, + XTENSA_OPCODE_IS_CALL, + Opcode_callx0_encode_fns, 0, 0 }, + { "extui", ICLASS_xt_iclass_exti, + 0, + Opcode_extui_encode_fns, 0, 0 }, + { "ill", ICLASS_xt_iclass_ill, + 0, + Opcode_ill_encode_fns, 0, 0 }, + { "j", ICLASS_xt_iclass_jump, + XTENSA_OPCODE_IS_JUMP, + Opcode_j_encode_fns, 0, 0 }, + { "jx", ICLASS_xt_iclass_jumpx, + XTENSA_OPCODE_IS_JUMP, + Opcode_jx_encode_fns, 0, 0 }, + { "l16ui", ICLASS_xt_iclass_l16ui, + 0, + Opcode_l16ui_encode_fns, 0, 0 }, + { "l16si", ICLASS_xt_iclass_l16si, + 0, + Opcode_l16si_encode_fns, 0, 0 }, + { "l32i", ICLASS_xt_iclass_l32i, + 0, + Opcode_l32i_encode_fns, 0, 0 }, + { "l32r", ICLASS_xt_iclass_l32r, + 0, + Opcode_l32r_encode_fns, 0, 0 }, + { "l8ui", ICLASS_xt_iclass_l8i, + 0, + Opcode_l8ui_encode_fns, 0, 0 }, + { "loop", ICLASS_xt_iclass_loop, + XTENSA_OPCODE_IS_LOOP, + Opcode_loop_encode_fns, 0, 0 }, + { "loopnez", ICLASS_xt_iclass_loopz, + XTENSA_OPCODE_IS_LOOP, + Opcode_loopnez_encode_fns, 0, 0 }, + { "loopgtz", ICLASS_xt_iclass_loopz, + XTENSA_OPCODE_IS_LOOP, + Opcode_loopgtz_encode_fns, 0, 0 }, + { "movi", ICLASS_xt_iclass_movi, + 0, + Opcode_movi_encode_fns, 0, 0 }, + { "moveqz", ICLASS_xt_iclass_movz, + 0, + Opcode_moveqz_encode_fns, 0, 0 }, + { "movnez", ICLASS_xt_iclass_movz, + 0, + Opcode_movnez_encode_fns, 0, 0 }, + { "movltz", ICLASS_xt_iclass_movz, + 0, + Opcode_movltz_encode_fns, 0, 0 }, + { "movgez", ICLASS_xt_iclass_movz, + 0, + Opcode_movgez_encode_fns, 0, 0 }, + { "neg", ICLASS_xt_iclass_neg, + 0, + Opcode_neg_encode_fns, 0, 0 }, + { "abs", ICLASS_xt_iclass_neg, + 0, + Opcode_abs_encode_fns, 0, 0 }, + { "nop", ICLASS_xt_iclass_nop, + 0, + Opcode_nop_encode_fns, 0, 0 }, + { "ret", ICLASS_xt_iclass_return, + XTENSA_OPCODE_IS_JUMP, + Opcode_ret_encode_fns, 0, 0 }, + { "s16i", ICLASS_xt_iclass_s16i, + 0, + Opcode_s16i_encode_fns, 0, 0 }, + { "s32i", ICLASS_xt_iclass_s32i, + 0, + Opcode_s32i_encode_fns, 0, 0 }, + { "s8i", ICLASS_xt_iclass_s8i, + 0, + Opcode_s8i_encode_fns, 0, 0 }, + { "ssr", ICLASS_xt_iclass_sar, + 0, + Opcode_ssr_encode_fns, 0, 0 }, + { "ssl", ICLASS_xt_iclass_sar, + 0, + Opcode_ssl_encode_fns, 0, 0 }, + { "ssa8l", ICLASS_xt_iclass_sar, + 0, + Opcode_ssa8l_encode_fns, 0, 0 }, + { "ssa8b", ICLASS_xt_iclass_sar, + 0, + Opcode_ssa8b_encode_fns, 0, 0 }, + { "ssai", ICLASS_xt_iclass_sari, + 0, + Opcode_ssai_encode_fns, 0, 0 }, + { "sll", ICLASS_xt_iclass_shifts, + 0, + Opcode_sll_encode_fns, 0, 0 }, + { "src", ICLASS_xt_iclass_shiftst, + 0, + Opcode_src_encode_fns, 0, 0 }, + { "srl", ICLASS_xt_iclass_shiftt, + 0, + Opcode_srl_encode_fns, 0, 0 }, + { "sra", ICLASS_xt_iclass_shiftt, + 0, + Opcode_sra_encode_fns, 0, 0 }, + { "slli", ICLASS_xt_iclass_slli, + 0, + Opcode_slli_encode_fns, 0, 0 }, + { "srai", ICLASS_xt_iclass_srai, + 0, + Opcode_srai_encode_fns, 0, 0 }, + { "srli", ICLASS_xt_iclass_srli, + 0, + Opcode_srli_encode_fns, 0, 0 }, + { "memw", ICLASS_xt_iclass_memw, + 0, + Opcode_memw_encode_fns, 0, 0 }, + { "extw", ICLASS_xt_iclass_extw, + 0, + Opcode_extw_encode_fns, 0, 0 }, + { "isync", ICLASS_xt_iclass_isync, + 0, + Opcode_isync_encode_fns, 0, 0 }, + { "rsync", ICLASS_xt_iclass_sync, + 0, + Opcode_rsync_encode_fns, 0, 0 }, + { "esync", ICLASS_xt_iclass_sync, + 0, + Opcode_esync_encode_fns, 0, 0 }, + { "dsync", ICLASS_xt_iclass_sync, + 0, + Opcode_dsync_encode_fns, 0, 0 }, + { "rsil", ICLASS_xt_iclass_rsil, + 0, + Opcode_rsil_encode_fns, 0, 0 }, + { "rsr.lend", ICLASS_xt_iclass_rsr_lend, + 0, + Opcode_rsr_lend_encode_fns, 0, 0 }, + { "wsr.lend", ICLASS_xt_iclass_wsr_lend, + 0, + Opcode_wsr_lend_encode_fns, 0, 0 }, + { "xsr.lend", ICLASS_xt_iclass_xsr_lend, + 0, + Opcode_xsr_lend_encode_fns, 0, 0 }, + { "rsr.lcount", ICLASS_xt_iclass_rsr_lcount, + 0, + Opcode_rsr_lcount_encode_fns, 0, 0 }, + { "wsr.lcount", ICLASS_xt_iclass_wsr_lcount, + 0, + Opcode_wsr_lcount_encode_fns, 0, 0 }, + { "xsr.lcount", ICLASS_xt_iclass_xsr_lcount, + 0, + Opcode_xsr_lcount_encode_fns, 0, 0 }, + { "rsr.lbeg", ICLASS_xt_iclass_rsr_lbeg, + 0, + Opcode_rsr_lbeg_encode_fns, 0, 0 }, + { "wsr.lbeg", ICLASS_xt_iclass_wsr_lbeg, + 0, + Opcode_wsr_lbeg_encode_fns, 0, 0 }, + { "xsr.lbeg", ICLASS_xt_iclass_xsr_lbeg, + 0, + Opcode_xsr_lbeg_encode_fns, 0, 0 }, + { "rsr.sar", ICLASS_xt_iclass_rsr_sar, + 0, + Opcode_rsr_sar_encode_fns, 0, 0 }, + { "wsr.sar", ICLASS_xt_iclass_wsr_sar, + 0, + Opcode_wsr_sar_encode_fns, 0, 0 }, + { "xsr.sar", ICLASS_xt_iclass_xsr_sar, + 0, + Opcode_xsr_sar_encode_fns, 0, 0 }, + { "rsr.litbase", ICLASS_xt_iclass_rsr_litbase, + 0, + Opcode_rsr_litbase_encode_fns, 0, 0 }, + { "wsr.litbase", ICLASS_xt_iclass_wsr_litbase, + 0, + Opcode_wsr_litbase_encode_fns, 0, 0 }, + { "xsr.litbase", ICLASS_xt_iclass_xsr_litbase, + 0, + Opcode_xsr_litbase_encode_fns, 0, 0 }, + { "rsr.176", ICLASS_xt_iclass_rsr_176, + 0, + Opcode_rsr_176_encode_fns, 0, 0 }, + { "wsr.176", ICLASS_xt_iclass_wsr_176, + 0, + Opcode_wsr_176_encode_fns, 0, 0 }, + { "rsr.208", ICLASS_xt_iclass_rsr_208, + 0, + Opcode_rsr_208_encode_fns, 0, 0 }, + { "rsr.ps", ICLASS_xt_iclass_rsr_ps, + 0, + Opcode_rsr_ps_encode_fns, 0, 0 }, + { "wsr.ps", ICLASS_xt_iclass_wsr_ps, + 0, + Opcode_wsr_ps_encode_fns, 0, 0 }, + { "xsr.ps", ICLASS_xt_iclass_xsr_ps, + 0, + Opcode_xsr_ps_encode_fns, 0, 0 }, + { "rsr.epc1", ICLASS_xt_iclass_rsr_epc1, + 0, + Opcode_rsr_epc1_encode_fns, 0, 0 }, + { "wsr.epc1", ICLASS_xt_iclass_wsr_epc1, + 0, + Opcode_wsr_epc1_encode_fns, 0, 0 }, + { "xsr.epc1", ICLASS_xt_iclass_xsr_epc1, + 0, + Opcode_xsr_epc1_encode_fns, 0, 0 }, + { "rsr.excsave1", ICLASS_xt_iclass_rsr_excsave1, + 0, + Opcode_rsr_excsave1_encode_fns, 0, 0 }, + { "wsr.excsave1", ICLASS_xt_iclass_wsr_excsave1, + 0, + Opcode_wsr_excsave1_encode_fns, 0, 0 }, + { "xsr.excsave1", ICLASS_xt_iclass_xsr_excsave1, + 0, + Opcode_xsr_excsave1_encode_fns, 0, 0 }, + { "rsr.epc2", ICLASS_xt_iclass_rsr_epc2, + 0, + Opcode_rsr_epc2_encode_fns, 0, 0 }, + { "wsr.epc2", ICLASS_xt_iclass_wsr_epc2, + 0, + Opcode_wsr_epc2_encode_fns, 0, 0 }, + { "xsr.epc2", ICLASS_xt_iclass_xsr_epc2, + 0, + Opcode_xsr_epc2_encode_fns, 0, 0 }, + { "rsr.excsave2", ICLASS_xt_iclass_rsr_excsave2, + 0, + Opcode_rsr_excsave2_encode_fns, 0, 0 }, + { "wsr.excsave2", ICLASS_xt_iclass_wsr_excsave2, + 0, + Opcode_wsr_excsave2_encode_fns, 0, 0 }, + { "xsr.excsave2", ICLASS_xt_iclass_xsr_excsave2, + 0, + Opcode_xsr_excsave2_encode_fns, 0, 0 }, + { "rsr.epc3", ICLASS_xt_iclass_rsr_epc3, + 0, + Opcode_rsr_epc3_encode_fns, 0, 0 }, + { "wsr.epc3", ICLASS_xt_iclass_wsr_epc3, + 0, + Opcode_wsr_epc3_encode_fns, 0, 0 }, + { "xsr.epc3", ICLASS_xt_iclass_xsr_epc3, + 0, + Opcode_xsr_epc3_encode_fns, 0, 0 }, + { "rsr.excsave3", ICLASS_xt_iclass_rsr_excsave3, + 0, + Opcode_rsr_excsave3_encode_fns, 0, 0 }, + { "wsr.excsave3", ICLASS_xt_iclass_wsr_excsave3, + 0, + Opcode_wsr_excsave3_encode_fns, 0, 0 }, + { "xsr.excsave3", ICLASS_xt_iclass_xsr_excsave3, + 0, + Opcode_xsr_excsave3_encode_fns, 0, 0 }, + { "rsr.epc4", ICLASS_xt_iclass_rsr_epc4, + 0, + Opcode_rsr_epc4_encode_fns, 0, 0 }, + { "wsr.epc4", ICLASS_xt_iclass_wsr_epc4, + 0, + Opcode_wsr_epc4_encode_fns, 0, 0 }, + { "xsr.epc4", ICLASS_xt_iclass_xsr_epc4, + 0, + Opcode_xsr_epc4_encode_fns, 0, 0 }, + { "rsr.excsave4", ICLASS_xt_iclass_rsr_excsave4, + 0, + Opcode_rsr_excsave4_encode_fns, 0, 0 }, + { "wsr.excsave4", ICLASS_xt_iclass_wsr_excsave4, + 0, + Opcode_wsr_excsave4_encode_fns, 0, 0 }, + { "xsr.excsave4", ICLASS_xt_iclass_xsr_excsave4, + 0, + Opcode_xsr_excsave4_encode_fns, 0, 0 }, + { "rsr.epc5", ICLASS_xt_iclass_rsr_epc5, + 0, + Opcode_rsr_epc5_encode_fns, 0, 0 }, + { "wsr.epc5", ICLASS_xt_iclass_wsr_epc5, + 0, + Opcode_wsr_epc5_encode_fns, 0, 0 }, + { "xsr.epc5", ICLASS_xt_iclass_xsr_epc5, + 0, + Opcode_xsr_epc5_encode_fns, 0, 0 }, + { "rsr.excsave5", ICLASS_xt_iclass_rsr_excsave5, + 0, + Opcode_rsr_excsave5_encode_fns, 0, 0 }, + { "wsr.excsave5", ICLASS_xt_iclass_wsr_excsave5, + 0, + Opcode_wsr_excsave5_encode_fns, 0, 0 }, + { "xsr.excsave5", ICLASS_xt_iclass_xsr_excsave5, + 0, + Opcode_xsr_excsave5_encode_fns, 0, 0 }, + { "rsr.epc6", ICLASS_xt_iclass_rsr_epc6, + 0, + Opcode_rsr_epc6_encode_fns, 0, 0 }, + { "wsr.epc6", ICLASS_xt_iclass_wsr_epc6, + 0, + Opcode_wsr_epc6_encode_fns, 0, 0 }, + { "xsr.epc6", ICLASS_xt_iclass_xsr_epc6, + 0, + Opcode_xsr_epc6_encode_fns, 0, 0 }, + { "rsr.excsave6", ICLASS_xt_iclass_rsr_excsave6, + 0, + Opcode_rsr_excsave6_encode_fns, 0, 0 }, + { "wsr.excsave6", ICLASS_xt_iclass_wsr_excsave6, + 0, + Opcode_wsr_excsave6_encode_fns, 0, 0 }, + { "xsr.excsave6", ICLASS_xt_iclass_xsr_excsave6, + 0, + Opcode_xsr_excsave6_encode_fns, 0, 0 }, + { "rsr.eps2", ICLASS_xt_iclass_rsr_eps2, + 0, + Opcode_rsr_eps2_encode_fns, 0, 0 }, + { "wsr.eps2", ICLASS_xt_iclass_wsr_eps2, + 0, + Opcode_wsr_eps2_encode_fns, 0, 0 }, + { "xsr.eps2", ICLASS_xt_iclass_xsr_eps2, + 0, + Opcode_xsr_eps2_encode_fns, 0, 0 }, + { "rsr.eps3", ICLASS_xt_iclass_rsr_eps3, + 0, + Opcode_rsr_eps3_encode_fns, 0, 0 }, + { "wsr.eps3", ICLASS_xt_iclass_wsr_eps3, + 0, + Opcode_wsr_eps3_encode_fns, 0, 0 }, + { "xsr.eps3", ICLASS_xt_iclass_xsr_eps3, + 0, + Opcode_xsr_eps3_encode_fns, 0, 0 }, + { "rsr.eps4", ICLASS_xt_iclass_rsr_eps4, + 0, + Opcode_rsr_eps4_encode_fns, 0, 0 }, + { "wsr.eps4", ICLASS_xt_iclass_wsr_eps4, + 0, + Opcode_wsr_eps4_encode_fns, 0, 0 }, + { "xsr.eps4", ICLASS_xt_iclass_xsr_eps4, + 0, + Opcode_xsr_eps4_encode_fns, 0, 0 }, + { "rsr.eps5", ICLASS_xt_iclass_rsr_eps5, + 0, + Opcode_rsr_eps5_encode_fns, 0, 0 }, + { "wsr.eps5", ICLASS_xt_iclass_wsr_eps5, + 0, + Opcode_wsr_eps5_encode_fns, 0, 0 }, + { "xsr.eps5", ICLASS_xt_iclass_xsr_eps5, + 0, + Opcode_xsr_eps5_encode_fns, 0, 0 }, + { "rsr.eps6", ICLASS_xt_iclass_rsr_eps6, + 0, + Opcode_rsr_eps6_encode_fns, 0, 0 }, + { "wsr.eps6", ICLASS_xt_iclass_wsr_eps6, + 0, + Opcode_wsr_eps6_encode_fns, 0, 0 }, + { "xsr.eps6", ICLASS_xt_iclass_xsr_eps6, + 0, + Opcode_xsr_eps6_encode_fns, 0, 0 }, + { "rsr.excvaddr", ICLASS_xt_iclass_rsr_excvaddr, + 0, + Opcode_rsr_excvaddr_encode_fns, 0, 0 }, + { "wsr.excvaddr", ICLASS_xt_iclass_wsr_excvaddr, + 0, + Opcode_wsr_excvaddr_encode_fns, 0, 0 }, + { "xsr.excvaddr", ICLASS_xt_iclass_xsr_excvaddr, + 0, + Opcode_xsr_excvaddr_encode_fns, 0, 0 }, + { "rsr.depc", ICLASS_xt_iclass_rsr_depc, + 0, + Opcode_rsr_depc_encode_fns, 0, 0 }, + { "wsr.depc", ICLASS_xt_iclass_wsr_depc, + 0, + Opcode_wsr_depc_encode_fns, 0, 0 }, + { "xsr.depc", ICLASS_xt_iclass_xsr_depc, + 0, + Opcode_xsr_depc_encode_fns, 0, 0 }, + { "rsr.exccause", ICLASS_xt_iclass_rsr_exccause, + 0, + Opcode_rsr_exccause_encode_fns, 0, 0 }, + { "wsr.exccause", ICLASS_xt_iclass_wsr_exccause, + 0, + Opcode_wsr_exccause_encode_fns, 0, 0 }, + { "xsr.exccause", ICLASS_xt_iclass_xsr_exccause, + 0, + Opcode_xsr_exccause_encode_fns, 0, 0 }, + { "rsr.prid", ICLASS_xt_iclass_rsr_prid, + 0, + Opcode_rsr_prid_encode_fns, 0, 0 }, + { "rsr.vecbase", ICLASS_xt_iclass_rsr_vecbase, + 0, + Opcode_rsr_vecbase_encode_fns, 0, 0 }, + { "wsr.vecbase", ICLASS_xt_iclass_wsr_vecbase, + 0, + Opcode_wsr_vecbase_encode_fns, 0, 0 }, + { "xsr.vecbase", ICLASS_xt_iclass_xsr_vecbase, + 0, + Opcode_xsr_vecbase_encode_fns, 0, 0 }, + { "mul16u", ICLASS_xt_mul16, + 0, + Opcode_mul16u_encode_fns, 0, 0 }, + { "mul16s", ICLASS_xt_mul16, + 0, + Opcode_mul16s_encode_fns, 0, 0 }, + { "rfi", ICLASS_xt_iclass_rfi, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfi_encode_fns, 0, 0 }, + { "waiti", ICLASS_xt_iclass_wait, + 0, + Opcode_waiti_encode_fns, 0, 0 }, + { "rsr.interrupt", ICLASS_xt_iclass_rsr_interrupt, + 0, + Opcode_rsr_interrupt_encode_fns, 0, 0 }, + { "wsr.intset", ICLASS_xt_iclass_wsr_intset, + 0, + Opcode_wsr_intset_encode_fns, 0, 0 }, + { "wsr.intclear", ICLASS_xt_iclass_wsr_intclear, + 0, + Opcode_wsr_intclear_encode_fns, 0, 0 }, + { "rsr.intenable", ICLASS_xt_iclass_rsr_intenable, + 0, + Opcode_rsr_intenable_encode_fns, 0, 0 }, + { "wsr.intenable", ICLASS_xt_iclass_wsr_intenable, + 0, + Opcode_wsr_intenable_encode_fns, 0, 0 }, + { "xsr.intenable", ICLASS_xt_iclass_xsr_intenable, + 0, + Opcode_xsr_intenable_encode_fns, 0, 0 }, + { "break", ICLASS_xt_iclass_break, + 0, + Opcode_break_encode_fns, 0, 0 }, + { "break.n", ICLASS_xt_iclass_break_n, + 0, + Opcode_break_n_encode_fns, 0, 0 }, + { "rsr.dbreaka0", ICLASS_xt_iclass_rsr_dbreaka0, + 0, + Opcode_rsr_dbreaka0_encode_fns, 0, 0 }, + { "wsr.dbreaka0", ICLASS_xt_iclass_wsr_dbreaka0, + 0, + Opcode_wsr_dbreaka0_encode_fns, 0, 0 }, + { "xsr.dbreaka0", ICLASS_xt_iclass_xsr_dbreaka0, + 0, + Opcode_xsr_dbreaka0_encode_fns, 0, 0 }, + { "rsr.dbreakc0", ICLASS_xt_iclass_rsr_dbreakc0, + 0, + Opcode_rsr_dbreakc0_encode_fns, 0, 0 }, + { "wsr.dbreakc0", ICLASS_xt_iclass_wsr_dbreakc0, + 0, + Opcode_wsr_dbreakc0_encode_fns, 0, 0 }, + { "xsr.dbreakc0", ICLASS_xt_iclass_xsr_dbreakc0, + 0, + Opcode_xsr_dbreakc0_encode_fns, 0, 0 }, + { "rsr.dbreaka1", ICLASS_xt_iclass_rsr_dbreaka1, + 0, + Opcode_rsr_dbreaka1_encode_fns, 0, 0 }, + { "wsr.dbreaka1", ICLASS_xt_iclass_wsr_dbreaka1, + 0, + Opcode_wsr_dbreaka1_encode_fns, 0, 0 }, + { "xsr.dbreaka1", ICLASS_xt_iclass_xsr_dbreaka1, + 0, + Opcode_xsr_dbreaka1_encode_fns, 0, 0 }, + { "rsr.dbreakc1", ICLASS_xt_iclass_rsr_dbreakc1, + 0, + Opcode_rsr_dbreakc1_encode_fns, 0, 0 }, + { "wsr.dbreakc1", ICLASS_xt_iclass_wsr_dbreakc1, + 0, + Opcode_wsr_dbreakc1_encode_fns, 0, 0 }, + { "xsr.dbreakc1", ICLASS_xt_iclass_xsr_dbreakc1, + 0, + Opcode_xsr_dbreakc1_encode_fns, 0, 0 }, + { "rsr.ibreaka0", ICLASS_xt_iclass_rsr_ibreaka0, + 0, + Opcode_rsr_ibreaka0_encode_fns, 0, 0 }, + { "wsr.ibreaka0", ICLASS_xt_iclass_wsr_ibreaka0, + 0, + Opcode_wsr_ibreaka0_encode_fns, 0, 0 }, + { "xsr.ibreaka0", ICLASS_xt_iclass_xsr_ibreaka0, + 0, + Opcode_xsr_ibreaka0_encode_fns, 0, 0 }, + { "rsr.ibreaka1", ICLASS_xt_iclass_rsr_ibreaka1, + 0, + Opcode_rsr_ibreaka1_encode_fns, 0, 0 }, + { "wsr.ibreaka1", ICLASS_xt_iclass_wsr_ibreaka1, + 0, + Opcode_wsr_ibreaka1_encode_fns, 0, 0 }, + { "xsr.ibreaka1", ICLASS_xt_iclass_xsr_ibreaka1, + 0, + Opcode_xsr_ibreaka1_encode_fns, 0, 0 }, + { "rsr.ibreakenable", ICLASS_xt_iclass_rsr_ibreakenable, + 0, + Opcode_rsr_ibreakenable_encode_fns, 0, 0 }, + { "wsr.ibreakenable", ICLASS_xt_iclass_wsr_ibreakenable, + 0, + Opcode_wsr_ibreakenable_encode_fns, 0, 0 }, + { "xsr.ibreakenable", ICLASS_xt_iclass_xsr_ibreakenable, + 0, + Opcode_xsr_ibreakenable_encode_fns, 0, 0 }, + { "rsr.debugcause", ICLASS_xt_iclass_rsr_debugcause, + 0, + Opcode_rsr_debugcause_encode_fns, 0, 0 }, + { "wsr.debugcause", ICLASS_xt_iclass_wsr_debugcause, + 0, + Opcode_wsr_debugcause_encode_fns, 0, 0 }, + { "xsr.debugcause", ICLASS_xt_iclass_xsr_debugcause, + 0, + Opcode_xsr_debugcause_encode_fns, 0, 0 }, + { "rsr.icount", ICLASS_xt_iclass_rsr_icount, + 0, + Opcode_rsr_icount_encode_fns, 0, 0 }, + { "wsr.icount", ICLASS_xt_iclass_wsr_icount, + 0, + Opcode_wsr_icount_encode_fns, 0, 0 }, + { "xsr.icount", ICLASS_xt_iclass_xsr_icount, + 0, + Opcode_xsr_icount_encode_fns, 0, 0 }, + { "rsr.icountlevel", ICLASS_xt_iclass_rsr_icountlevel, + 0, + Opcode_rsr_icountlevel_encode_fns, 0, 0 }, + { "wsr.icountlevel", ICLASS_xt_iclass_wsr_icountlevel, + 0, + Opcode_wsr_icountlevel_encode_fns, 0, 0 }, + { "xsr.icountlevel", ICLASS_xt_iclass_xsr_icountlevel, + 0, + Opcode_xsr_icountlevel_encode_fns, 0, 0 }, + { "rsr.ddr", ICLASS_xt_iclass_rsr_ddr, + 0, + Opcode_rsr_ddr_encode_fns, 0, 0 }, + { "wsr.ddr", ICLASS_xt_iclass_wsr_ddr, + 0, + Opcode_wsr_ddr_encode_fns, 0, 0 }, + { "xsr.ddr", ICLASS_xt_iclass_xsr_ddr, + 0, + Opcode_xsr_ddr_encode_fns, 0, 0 }, + { "rfdo", ICLASS_xt_iclass_rfdo, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfdo_encode_fns, 0, 0 }, + { "rfdd", ICLASS_xt_iclass_rfdd, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfdd_encode_fns, 0, 0 }, + { "wsr.mmid", ICLASS_xt_iclass_wsr_mmid, + 0, + Opcode_wsr_mmid_encode_fns, 0, 0 }, + { "andb", ICLASS_xt_iclass_bbool1, + 0, + Opcode_andb_encode_fns, 0, 0 }, + { "andbc", ICLASS_xt_iclass_bbool1, + 0, + Opcode_andbc_encode_fns, 0, 0 }, + { "orb", ICLASS_xt_iclass_bbool1, + 0, + Opcode_orb_encode_fns, 0, 0 }, + { "orbc", ICLASS_xt_iclass_bbool1, + 0, + Opcode_orbc_encode_fns, 0, 0 }, + { "xorb", ICLASS_xt_iclass_bbool1, + 0, + Opcode_xorb_encode_fns, 0, 0 }, + { "any4", ICLASS_xt_iclass_bbool4, + 0, + Opcode_any4_encode_fns, 0, 0 }, + { "all4", ICLASS_xt_iclass_bbool4, + 0, + Opcode_all4_encode_fns, 0, 0 }, + { "any8", ICLASS_xt_iclass_bbool8, + 0, + Opcode_any8_encode_fns, 0, 0 }, + { "all8", ICLASS_xt_iclass_bbool8, + 0, + Opcode_all8_encode_fns, 0, 0 }, + { "bf", ICLASS_xt_iclass_bbranch, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bf_encode_fns, 0, 0 }, + { "bt", ICLASS_xt_iclass_bbranch, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bt_encode_fns, 0, 0 }, + { "movf", ICLASS_xt_iclass_bmove, + 0, + Opcode_movf_encode_fns, 0, 0 }, + { "movt", ICLASS_xt_iclass_bmove, + 0, + Opcode_movt_encode_fns, 0, 0 }, + { "rsr.br", ICLASS_xt_iclass_RSR_BR, + 0, + Opcode_rsr_br_encode_fns, 0, 0 }, + { "wsr.br", ICLASS_xt_iclass_WSR_BR, + 0, + Opcode_wsr_br_encode_fns, 0, 0 }, + { "xsr.br", ICLASS_xt_iclass_XSR_BR, + 0, + Opcode_xsr_br_encode_fns, 0, 0 }, + { "rsr.ccount", ICLASS_xt_iclass_rsr_ccount, + 0, + Opcode_rsr_ccount_encode_fns, 0, 0 }, + { "wsr.ccount", ICLASS_xt_iclass_wsr_ccount, + 0, + Opcode_wsr_ccount_encode_fns, 0, 0 }, + { "xsr.ccount", ICLASS_xt_iclass_xsr_ccount, + 0, + Opcode_xsr_ccount_encode_fns, 0, 0 }, + { "rsr.ccompare0", ICLASS_xt_iclass_rsr_ccompare0, + 0, + Opcode_rsr_ccompare0_encode_fns, 0, 0 }, + { "wsr.ccompare0", ICLASS_xt_iclass_wsr_ccompare0, + 0, + Opcode_wsr_ccompare0_encode_fns, 0, 0 }, + { "xsr.ccompare0", ICLASS_xt_iclass_xsr_ccompare0, + 0, + Opcode_xsr_ccompare0_encode_fns, 0, 0 }, + { "rsr.ccompare1", ICLASS_xt_iclass_rsr_ccompare1, + 0, + Opcode_rsr_ccompare1_encode_fns, 0, 0 }, + { "wsr.ccompare1", ICLASS_xt_iclass_wsr_ccompare1, + 0, + Opcode_wsr_ccompare1_encode_fns, 0, 0 }, + { "xsr.ccompare1", ICLASS_xt_iclass_xsr_ccompare1, + 0, + Opcode_xsr_ccompare1_encode_fns, 0, 0 }, + { "ipf", ICLASS_xt_iclass_icache, + 0, + Opcode_ipf_encode_fns, 0, 0 }, + { "ihi", ICLASS_xt_iclass_icache, + 0, + Opcode_ihi_encode_fns, 0, 0 }, + { "ipfl", ICLASS_xt_iclass_icache_lock, + 0, + Opcode_ipfl_encode_fns, 0, 0 }, + { "ihu", ICLASS_xt_iclass_icache_lock, + 0, + Opcode_ihu_encode_fns, 0, 0 }, + { "iiu", ICLASS_xt_iclass_icache_lock, + 0, + Opcode_iiu_encode_fns, 0, 0 }, + { "iii", ICLASS_xt_iclass_icache_inv, + 0, + Opcode_iii_encode_fns, 0, 0 }, + { "lict", ICLASS_xt_iclass_licx, + 0, + Opcode_lict_encode_fns, 0, 0 }, + { "licw", ICLASS_xt_iclass_licx, + 0, + Opcode_licw_encode_fns, 0, 0 }, + { "sict", ICLASS_xt_iclass_sicx, + 0, + Opcode_sict_encode_fns, 0, 0 }, + { "sicw", ICLASS_xt_iclass_sicx, + 0, + Opcode_sicw_encode_fns, 0, 0 }, + { "dhwb", ICLASS_xt_iclass_dcache, + 0, + Opcode_dhwb_encode_fns, 0, 0 }, + { "dhwbi", ICLASS_xt_iclass_dcache, + 0, + Opcode_dhwbi_encode_fns, 0, 0 }, + { "diwb", ICLASS_xt_iclass_dcache_ind, + 0, + Opcode_diwb_encode_fns, 0, 0 }, + { "diwbi", ICLASS_xt_iclass_dcache_ind, + 0, + Opcode_diwbi_encode_fns, 0, 0 }, + { "dhi", ICLASS_xt_iclass_dcache_inv, + 0, + Opcode_dhi_encode_fns, 0, 0 }, + { "dii", ICLASS_xt_iclass_dcache_inv, + 0, + Opcode_dii_encode_fns, 0, 0 }, + { "dpfr", ICLASS_xt_iclass_dpf, + 0, + Opcode_dpfr_encode_fns, 0, 0 }, + { "dpfw", ICLASS_xt_iclass_dpf, + 0, + Opcode_dpfw_encode_fns, 0, 0 }, + { "dpfro", ICLASS_xt_iclass_dpf, + 0, + Opcode_dpfro_encode_fns, 0, 0 }, + { "dpfwo", ICLASS_xt_iclass_dpf, + 0, + Opcode_dpfwo_encode_fns, 0, 0 }, + { "dpfl", ICLASS_xt_iclass_dcache_lock, + 0, + Opcode_dpfl_encode_fns, 0, 0 }, + { "dhu", ICLASS_xt_iclass_dcache_lock, + 0, + Opcode_dhu_encode_fns, 0, 0 }, + { "diu", ICLASS_xt_iclass_dcache_lock, + 0, + Opcode_diu_encode_fns, 0, 0 }, + { "sdct", ICLASS_xt_iclass_sdct, + 0, + Opcode_sdct_encode_fns, 0, 0 }, + { "ldct", ICLASS_xt_iclass_ldct, + 0, + Opcode_ldct_encode_fns, 0, 0 }, + { "idtlb", ICLASS_xt_iclass_idtlb, + 0, + Opcode_idtlb_encode_fns, 0, 0 }, + { "pdtlb", ICLASS_xt_iclass_rdtlb, + 0, + Opcode_pdtlb_encode_fns, 0, 0 }, + { "rdtlb0", ICLASS_xt_iclass_rdtlb, + 0, + Opcode_rdtlb0_encode_fns, 0, 0 }, + { "rdtlb1", ICLASS_xt_iclass_rdtlb, + 0, + Opcode_rdtlb1_encode_fns, 0, 0 }, + { "wdtlb", ICLASS_xt_iclass_wdtlb, + 0, + Opcode_wdtlb_encode_fns, 0, 0 }, + { "iitlb", ICLASS_xt_iclass_iitlb, + 0, + Opcode_iitlb_encode_fns, 0, 0 }, + { "pitlb", ICLASS_xt_iclass_ritlb, + 0, + Opcode_pitlb_encode_fns, 0, 0 }, + { "ritlb0", ICLASS_xt_iclass_ritlb, + 0, + Opcode_ritlb0_encode_fns, 0, 0 }, + { "ritlb1", ICLASS_xt_iclass_ritlb, + 0, + Opcode_ritlb1_encode_fns, 0, 0 }, + { "witlb", ICLASS_xt_iclass_witlb, + 0, + Opcode_witlb_encode_fns, 0, 0 }, + { "rsr.cpenable", ICLASS_xt_iclass_rsr_cpenable, + 0, + Opcode_rsr_cpenable_encode_fns, 0, 0 }, + { "wsr.cpenable", ICLASS_xt_iclass_wsr_cpenable, + 0, + Opcode_wsr_cpenable_encode_fns, 0, 0 }, + { "xsr.cpenable", ICLASS_xt_iclass_xsr_cpenable, + 0, + Opcode_xsr_cpenable_encode_fns, 0, 0 }, + { "clamps", ICLASS_xt_iclass_clamp, + 0, + Opcode_clamps_encode_fns, 0, 0 }, + { "min", ICLASS_xt_iclass_minmax, + 0, + Opcode_min_encode_fns, 0, 0 }, + { "max", ICLASS_xt_iclass_minmax, + 0, + Opcode_max_encode_fns, 0, 0 }, + { "minu", ICLASS_xt_iclass_minmax, + 0, + Opcode_minu_encode_fns, 0, 0 }, + { "maxu", ICLASS_xt_iclass_minmax, + 0, + Opcode_maxu_encode_fns, 0, 0 }, + { "nsa", ICLASS_xt_iclass_nsa, + 0, + Opcode_nsa_encode_fns, 0, 0 }, + { "nsau", ICLASS_xt_iclass_nsa, + 0, + Opcode_nsau_encode_fns, 0, 0 }, + { "sext", ICLASS_xt_iclass_sx, + 0, + Opcode_sext_encode_fns, 0, 0 }, + { "l32ai", ICLASS_xt_iclass_l32ai, + 0, + Opcode_l32ai_encode_fns, 0, 0 }, + { "s32ri", ICLASS_xt_iclass_s32ri, + 0, + Opcode_s32ri_encode_fns, 0, 0 }, + { "s32c1i", ICLASS_xt_iclass_s32c1i, + 0, + Opcode_s32c1i_encode_fns, 0, 0 }, + { "rsr.scompare1", ICLASS_xt_iclass_rsr_scompare1, + 0, + Opcode_rsr_scompare1_encode_fns, 0, 0 }, + { "wsr.scompare1", ICLASS_xt_iclass_wsr_scompare1, + 0, + Opcode_wsr_scompare1_encode_fns, 0, 0 }, + { "xsr.scompare1", ICLASS_xt_iclass_xsr_scompare1, + 0, + Opcode_xsr_scompare1_encode_fns, 0, 0 }, + { "rsr.atomctl", ICLASS_xt_iclass_rsr_atomctl, + 0, + Opcode_rsr_atomctl_encode_fns, 0, 0 }, + { "wsr.atomctl", ICLASS_xt_iclass_wsr_atomctl, + 0, + Opcode_wsr_atomctl_encode_fns, 0, 0 }, + { "xsr.atomctl", ICLASS_xt_iclass_xsr_atomctl, + 0, + Opcode_xsr_atomctl_encode_fns, 0, 0 }, + { "rer", ICLASS_xt_iclass_rer, + 0, + Opcode_rer_encode_fns, 0, 0 }, + { "wer", ICLASS_xt_iclass_wer, + 0, + Opcode_wer_encode_fns, 0, 0 }, + { "rur.fcr", ICLASS_rur_fcr, + 0, + Opcode_rur_fcr_encode_fns, 0, 0 }, + { "wur.fcr", ICLASS_wur_fcr, + 0, + Opcode_wur_fcr_encode_fns, 0, 0 }, + { "rur.fsr", ICLASS_rur_fsr, + 0, + Opcode_rur_fsr_encode_fns, 0, 0 }, + { "wur.fsr", ICLASS_wur_fsr, + 0, + Opcode_wur_fsr_encode_fns, 0, 0 }, + { "add.s", ICLASS_fp, + 0, + Opcode_add_s_encode_fns, 0, 0 }, + { "sub.s", ICLASS_fp, + 0, + Opcode_sub_s_encode_fns, 0, 0 }, + { "mul.s", ICLASS_fp, + 0, + Opcode_mul_s_encode_fns, 0, 0 }, + { "madd.s", ICLASS_fp_mac, + 0, + Opcode_madd_s_encode_fns, 0, 0 }, + { "msub.s", ICLASS_fp_mac, + 0, + Opcode_msub_s_encode_fns, 0, 0 }, + { "movf.s", ICLASS_fp_cmov, + 0, + Opcode_movf_s_encode_fns, 0, 0 }, + { "movt.s", ICLASS_fp_cmov, + 0, + Opcode_movt_s_encode_fns, 0, 0 }, + { "moveqz.s", ICLASS_fp_mov, + 0, + Opcode_moveqz_s_encode_fns, 0, 0 }, + { "movnez.s", ICLASS_fp_mov, + 0, + Opcode_movnez_s_encode_fns, 0, 0 }, + { "movltz.s", ICLASS_fp_mov, + 0, + Opcode_movltz_s_encode_fns, 0, 0 }, + { "movgez.s", ICLASS_fp_mov, + 0, + Opcode_movgez_s_encode_fns, 0, 0 }, + { "abs.s", ICLASS_fp_mov2, + 0, + Opcode_abs_s_encode_fns, 0, 0 }, + { "mov.s", ICLASS_fp_mov2, + 0, + Opcode_mov_s_encode_fns, 0, 0 }, + { "neg.s", ICLASS_fp_mov2, + 0, + Opcode_neg_s_encode_fns, 0, 0 }, + { "un.s", ICLASS_fp_cmp, + 0, + Opcode_un_s_encode_fns, 0, 0 }, + { "oeq.s", ICLASS_fp_cmp, + 0, + Opcode_oeq_s_encode_fns, 0, 0 }, + { "ueq.s", ICLASS_fp_cmp, + 0, + Opcode_ueq_s_encode_fns, 0, 0 }, + { "olt.s", ICLASS_fp_cmp, + 0, + Opcode_olt_s_encode_fns, 0, 0 }, + { "ult.s", ICLASS_fp_cmp, + 0, + Opcode_ult_s_encode_fns, 0, 0 }, + { "ole.s", ICLASS_fp_cmp, + 0, + Opcode_ole_s_encode_fns, 0, 0 }, + { "ule.s", ICLASS_fp_cmp, + 0, + Opcode_ule_s_encode_fns, 0, 0 }, + { "float.s", ICLASS_fp_float, + 0, + Opcode_float_s_encode_fns, 0, 0 }, + { "ufloat.s", ICLASS_fp_float, + 0, + Opcode_ufloat_s_encode_fns, 0, 0 }, + { "round.s", ICLASS_fp_int, + 0, + Opcode_round_s_encode_fns, 0, 0 }, + { "ceil.s", ICLASS_fp_int, + 0, + Opcode_ceil_s_encode_fns, 0, 0 }, + { "floor.s", ICLASS_fp_int, + 0, + Opcode_floor_s_encode_fns, 0, 0 }, + { "trunc.s", ICLASS_fp_int, + 0, + Opcode_trunc_s_encode_fns, 0, 0 }, + { "utrunc.s", ICLASS_fp_int, + 0, + Opcode_utrunc_s_encode_fns, 0, 0 }, + { "rfr", ICLASS_fp_rfr, + 0, + Opcode_rfr_encode_fns, 0, 0 }, + { "wfr", ICLASS_fp_wfr, + 0, + Opcode_wfr_encode_fns, 0, 0 }, + { "lsi", ICLASS_fp_lsi, + 0, + Opcode_lsi_encode_fns, 0, 0 }, + { "lsiu", ICLASS_fp_lsiu, + 0, + Opcode_lsiu_encode_fns, 0, 0 }, + { "lsx", ICLASS_fp_lsx, + 0, + Opcode_lsx_encode_fns, 0, 0 }, + { "lsxu", ICLASS_fp_lsxu, + 0, + Opcode_lsxu_encode_fns, 0, 0 }, + { "ssi", ICLASS_fp_ssi, + 0, + Opcode_ssi_encode_fns, 0, 0 }, + { "ssiu", ICLASS_fp_ssiu, + 0, + Opcode_ssiu_encode_fns, 0, 0 }, + { "ssx", ICLASS_fp_ssx, + 0, + Opcode_ssx_encode_fns, 0, 0 }, + { "ssxu", ICLASS_fp_ssxu, + 0, + Opcode_ssxu_encode_fns, 0, 0 }, + { "get_argmax", ICLASS_iclass_GET_ARGMAX, + 0, + Opcode_get_argmax_encode_fns, 0, 0 }, + { "get_hsar", ICLASS_iclass_GET_HSAR, + 0, + Opcode_get_hsar_encode_fns, 0, 0 }, + { "get_hsar2sar", ICLASS_iclass_GET_HSAR2SAR, + 0, + Opcode_get_hsar2sar_encode_fns, 0, 0 }, + { "get_interp_ext_n", ICLASS_iclass_GET_INTERP_EXT_N, + 0, + Opcode_get_interp_ext_n_encode_fns, 0, 0 }, + { "get_interp_ext_l", ICLASS_iclass_GET_INTERP_EXT_L, + 0, + Opcode_get_interp_ext_l_encode_fns, 0, 0 }, + { "get_llr_buf", ICLASS_iclass_GET_LLR_BUF, + 0, + Opcode_get_llr_buf_encode_fns, 0, 0 }, + { "get_llr_pos", ICLASS_iclass_GET_LLR_POS, + 0, + Opcode_get_llr_pos_encode_fns, 0, 0 }, + { "get_max", ICLASS_iclass_GET_MAX, + 0, + Opcode_get_max_encode_fns, 0, 0 }, + { "get_nco", ICLASS_iclass_GET_NCO, + 0, + Opcode_get_nco_encode_fns, 0, 0 }, + { "get_perm_reg", ICLASS_iclass_GET_PERM_REG, + 0, + Opcode_get_perm_reg_encode_fns, 0, 0 }, + { "get_phasor_n", ICLASS_iclass_GET_PHASOR_N, + 0, + Opcode_get_phasor_n_encode_fns, 0, 0 }, + { "get_phasor_offset", ICLASS_iclass_GET_PHASOR_OFFSET, + 0, + Opcode_get_phasor_offset_encode_fns, 0, 0 }, + { "get_sar", ICLASS_iclass_GET_SAR, + 0, + Opcode_get_sar_encode_fns, 0, 0 }, + { "get_scale_reg", ICLASS_iclass_GET_SCALE_REG, + 0, + Opcode_get_scale_reg_encode_fns, 0, 0 }, + { "get_smod_buf", ICLASS_iclass_GET_SMOD_BUF, + 0, + Opcode_get_smod_buf_encode_fns, 0, 0 }, + { "get_smod_offset_table", ICLASS_iclass_GET_SMOD_OFFSET_TABLE, + 0, + Opcode_get_smod_offset_table_encode_fns, 0, 0 }, + { "get_smod_pos", ICLASS_iclass_GET_SMOD_POS, + 0, + Opcode_get_smod_pos_encode_fns, 0, 0 }, + { "get_sov", ICLASS_iclass_GET_SOV, + 0, + Opcode_get_sov_encode_fns, 0, 0 }, + { "get_wght", ICLASS_iclass_GET_WGHT, + 0, + Opcode_get_wght_encode_fns, 0, 0 }, + { "set_argmax", ICLASS_iclass_SET_ARGMAX, + 0, + Opcode_set_argmax_encode_fns, 0, 0 }, + { "set_ext_regs", ICLASS_iclass_SET_EXT_REGS, + 0, + Opcode_set_ext_regs_encode_fns, 0, 0 }, + { "set_hsar", ICLASS_iclass_SET_HSAR, + 0, + Opcode_set_hsar_encode_fns, 0, 0 }, + { "set_llr_buf", ICLASS_iclass_SET_LLR_BUF, + 0, + Opcode_set_llr_buf_encode_fns, 0, 0 }, + { "set_llr_pos", ICLASS_iclass_SET_LLR_POS, + 0, + Opcode_set_llr_pos_encode_fns, 0, 0 }, + { "set_max", ICLASS_iclass_SET_MAX, + 0, + Opcode_set_max_encode_fns, 0, 0 }, + { "set_nco", ICLASS_iclass_SET_NCO, + 0, + Opcode_set_nco_encode_fns, 0, 0 }, + { "set_perm_reg", ICLASS_iclass_SET_PERM_REG, + 0, + Opcode_set_perm_reg_encode_fns, 0, 0 }, + { "set_phasor_n", ICLASS_iclass_SET_PHASOR_N, + 0, + Opcode_set_phasor_n_encode_fns, 0, 0 }, + { "set_phasor_offset", ICLASS_iclass_SET_PHASOR_OFFSET, + 0, + Opcode_set_phasor_offset_encode_fns, 0, 0 }, + { "set_sar", ICLASS_iclass_SET_SAR, + 0, + Opcode_set_sar_encode_fns, 0, 0 }, + { "set_scale_reg", ICLASS_iclass_SET_SCALE_REG, + 0, + Opcode_set_scale_reg_encode_fns, 0, 0 }, + { "set_smod_buf", ICLASS_iclass_SET_SMOD_BUF, + 0, + Opcode_set_smod_buf_encode_fns, 0, 0 }, + { "set_smod_offset_table", ICLASS_iclass_SET_SMOD_OFFSET_TABLE, + 0, + Opcode_set_smod_offset_table_encode_fns, 0, 0 }, + { "set_smod_pos", ICLASS_iclass_SET_SMOD_POS, + 0, + Opcode_set_smod_pos_encode_fns, 0, 0 }, + { "set_sov", ICLASS_iclass_SET_SOV, + 0, + Opcode_set_sov_encode_fns, 0, 0 }, + { "set_wght", ICLASS_iclass_SET_WGHT, + 0, + Opcode_set_wght_encode_fns, 0, 0 }, + { "lac2x32", ICLASS_iclass_LAC2X32, + 0, + Opcode_lac2x32_encode_fns, 0, 0 }, + { "lac2x64_0", ICLASS_iclass_LAC2X64_0, + 0, + Opcode_lac2x64_0_encode_fns, 0, 0 }, + { "lac2x64_1", ICLASS_iclass_LAC2X64_1, + 0, + Opcode_lac2x64_1_encode_fns, 0, 0 }, + { "lac2x64_2", ICLASS_iclass_LAC2X64_2, + 0, + Opcode_lac2x64_2_encode_fns, 0, 0 }, + { "lac2x64_3", ICLASS_iclass_LAC2X64_3, + 0, + Opcode_lac2x64_3_encode_fns, 0, 0 }, + { "lac32_r", ICLASS_iclass_LAC32_R, + 0, + Opcode_lac32_r_encode_fns, 0, 0 }, + { "lac_ih", ICLASS_iclass_LAC_IH, + 0, + Opcode_lac_ih_encode_fns, 0, 0 }, + { "lac_il", ICLASS_iclass_LAC_IL, + 0, + Opcode_lac_il_encode_fns, 0, 0 }, + { "lac_rh", ICLASS_iclass_LAC_RH, + 0, + Opcode_lac_rh_encode_fns, 0, 0 }, + { "lac_rl", ICLASS_iclass_LAC_RL, + 0, + Opcode_lac_rl_encode_fns, 0, 0 }, + { "lcm", ICLASS_iclass_LCM, + 0, + Opcode_lcm_encode_fns, 0, 0 }, + { "lcm_pinc", ICLASS_iclass_LCM_PINC, + 0, + Opcode_lcm_pinc_encode_fns, 0, 0 }, + { "lcm_pinc_x", ICLASS_iclass_LCM_PINC_X, + 0, + Opcode_lcm_pinc_x_encode_fns, 0, 0 }, + { "lcm_u", ICLASS_iclass_LCM_U, + 0, + Opcode_lcm_u_encode_fns, 0, 0 }, + { "lcm_x", ICLASS_iclass_LCM_X, + 0, + Opcode_lcm_x_encode_fns, 0, 0 }, + { "lcm_xu", ICLASS_iclass_LCM_XU, + 0, + Opcode_lcm_xu_encode_fns, 0, 0 }, + { "lp", ICLASS_iclass_LP, + 0, + Opcode_lp_encode_fns, 0, 0 }, + { "lp_x", ICLASS_iclass_LP_X, + 0, + Opcode_lp_x_encode_fns, 0, 0 }, + { "lq", ICLASS_iclass_LQ, + 0, + Opcode_lq_encode_fns, 0, 0 }, + { "lq_x", ICLASS_iclass_LQ_X, + 0, + Opcode_lq_x_encode_fns, 0, 0 }, + { "lut0", ICLASS_iclass_LUT0, + 0, + Opcode_lut0_encode_fns, 0, 0 }, + { "lut1", ICLASS_iclass_LUT1, + 0, + Opcode_lut1_encode_fns, 0, 0 }, + { "lut2", ICLASS_iclass_LUT2, + 0, + Opcode_lut2_encode_fns, 0, 0 }, + { "lut3", ICLASS_iclass_LUT3, + 0, + Opcode_lut3_encode_fns, 0, 0 }, + { "sac2x32", ICLASS_iclass_SAC2X32, + 0, + Opcode_sac2x32_encode_fns, 0, 0 }, + { "sac2x64_0", ICLASS_iclass_SAC2X64_0, + 0, + Opcode_sac2x64_0_encode_fns, 0, 0 }, + { "sac2x64_1", ICLASS_iclass_SAC2X64_1, + 0, + Opcode_sac2x64_1_encode_fns, 0, 0 }, + { "sac2x64_2", ICLASS_iclass_SAC2X64_2, + 0, + Opcode_sac2x64_2_encode_fns, 0, 0 }, + { "sac2x64_3", ICLASS_iclass_SAC2X64_3, + 0, + Opcode_sac2x64_3_encode_fns, 0, 0 }, + { "sac32_r", ICLASS_iclass_SAC32_R, + 0, + Opcode_sac32_r_encode_fns, 0, 0 }, + { "sac_ih", ICLASS_iclass_SAC_IH, + 0, + Opcode_sac_ih_encode_fns, 0, 0 }, + { "sac_il", ICLASS_iclass_SAC_IL, + 0, + Opcode_sac_il_encode_fns, 0, 0 }, + { "sac_rh", ICLASS_iclass_SAC_RH, + 0, + Opcode_sac_rh_encode_fns, 0, 0 }, + { "sac_rl", ICLASS_iclass_SAC_RL, + 0, + Opcode_sac_rl_encode_fns, 0, 0 }, + { "scm", ICLASS_iclass_SCM, + 0, + Opcode_scm_encode_fns, 0, 0 }, + { "scm_pinc", ICLASS_iclass_SCM_PINC, + 0, + Opcode_scm_pinc_encode_fns, 0, 0 }, + { "scm_pinc_x", ICLASS_iclass_SCM_PINC_X, + 0, + Opcode_scm_pinc_x_encode_fns, 0, 0 }, + { "scm_u", ICLASS_iclass_SCM_U, + 0, + Opcode_scm_u_encode_fns, 0, 0 }, + { "scm_x", ICLASS_iclass_SCM_X, + 0, + Opcode_scm_x_encode_fns, 0, 0 }, + { "scm_xu", ICLASS_iclass_SCM_XU, + 0, + Opcode_scm_xu_encode_fns, 0, 0 }, + { "store_p", ICLASS_iclass_STORE_P, + 0, + Opcode_store_p_encode_fns, 0, 0 }, + { "store_q", ICLASS_iclass_STORE_Q, + 0, + Opcode_store_q_encode_fns, 0, 0 }, + { "ar2cm_dup", ICLASS_iclass_AR2CM_DUP, + 0, + Opcode_ar2cm_dup_encode_fns, 0, 0 }, + { "ar2cm_ln", ICLASS_iclass_AR2CM_LN, + 0, + Opcode_ar2cm_ln_encode_fns, 0, 0 }, + { "ar2cm_ln_i", ICLASS_iclass_AR2CM_LN_I, + 0, + Opcode_ar2cm_ln_i_encode_fns, 0, 0 }, + { "ar2cm_ln_r", ICLASS_iclass_AR2CM_LN_R, + 0, + Opcode_ar2cm_ln_r_encode_fns, 0, 0 }, + { "ar2pq_ln", ICLASS_iclass_AR2PQ_LN, + 0, + Opcode_ar2pq_ln_encode_fns, 0, 0 }, + { "ar2sar_dup", ICLASS_iclass_AR2SAR_DUP, + 0, + Opcode_ar2sar_dup_encode_fns, 0, 0 }, + { "clrac", ICLASS_iclass_CLRAC, + 0, + Opcode_clrac_encode_fns, 0, 0 }, + { "clrcm", ICLASS_iclass_CLRCM, + 0, + Opcode_clrcm_encode_fns, 0, 0 }, + { "cm2ar_ln", ICLASS_iclass_CM2AR_LN, + 0, + Opcode_cm2ar_ln_encode_fns, 0, 0 }, + { "cm2ar_ln_i", ICLASS_iclass_CM2AR_LN_I, + 0, + Opcode_cm2ar_ln_i_encode_fns, 0, 0 }, + { "cm2ar_ln_r", ICLASS_iclass_CM2AR_LN_R, + 0, + Opcode_cm2ar_ln_r_encode_fns, 0, 0 }, + { "comb_ar", ICLASS_iclass_COMB_AR, + 0, + Opcode_comb_ar_encode_fns, 0, 0 }, + { "conj", ICLASS_iclass_CONJ, + 0, + Opcode_conj_encode_fns, 0, 0 }, + { "mov2ac32_i", ICLASS_iclass_MOV2AC32_I, + 0, + Opcode_mov2ac32_i_encode_fns, 0, 0 }, + { "mov2ac32_r", ICLASS_iclass_MOV2AC32_R, + 0, + Opcode_mov2ac32_r_encode_fns, 0, 0 }, + { "mov2cm2pq", ICLASS_iclass_MOV2CM2PQ, + 0, + Opcode_mov2cm2pq_encode_fns, 0, 0 }, + { "movac", ICLASS_iclass_MOVAC, + 0, + Opcode_movac_encode_fns, 0, 0 }, + { "movac_i", ICLASS_iclass_MOVAC_I, + 0, + Opcode_movac_i_encode_fns, 0, 0 }, + { "movac_i2r", ICLASS_iclass_MOVAC_I2R, + 0, + Opcode_movac_i2r_encode_fns, 0, 0 }, + { "movac_r", ICLASS_iclass_MOVAC_R, + 0, + Opcode_movac_r_encode_fns, 0, 0 }, + { "movac_r2i", ICLASS_iclass_MOVAC_R2I, + 0, + Opcode_movac_r2i_encode_fns, 0, 0 }, + { "movar2", ICLASS_iclass_MOVAR2, + 0, + Opcode_movar2_encode_fns, 0, 0 }, + { "movcm", ICLASS_iclass_MOVCM, + 0, + Opcode_movcm_encode_fns, 0, 0 }, + { "movcm2pq", ICLASS_iclass_MOVCM2PQ, + 0, + Opcode_movcm2pq_encode_fns, 0, 0 }, + { "movcnd_0", ICLASS_iclass_MOVCND_0, + 0, + Opcode_movcnd_0_encode_fns, 0, 0 }, + { "movcnd_1", ICLASS_iclass_MOVCND_1, + 0, + Opcode_movcnd_1_encode_fns, 0, 0 }, + { "movcnd_2", ICLASS_iclass_MOVCND_2, + 0, + Opcode_movcnd_2_encode_fns, 0, 0 }, + { "movcnd_3", ICLASS_iclass_MOVCND_3, + 0, + Opcode_movcnd_3_encode_fns, 0, 0 }, + { "movcnd_4", ICLASS_iclass_MOVCND_4, + 0, + Opcode_movcnd_4_encode_fns, 0, 0 }, + { "movcnd_5", ICLASS_iclass_MOVCND_5, + 0, + Opcode_movcnd_5_encode_fns, 0, 0 }, + { "movcnd_6", ICLASS_iclass_MOVCND_6, + 0, + Opcode_movcnd_6_encode_fns, 0, 0 }, + { "movcnd_7", ICLASS_iclass_MOVCND_7, + 0, + Opcode_movcnd_7_encode_fns, 0, 0 }, + { "movcnd8_0", ICLASS_iclass_MOVCND8_0, + 0, + Opcode_movcnd8_0_encode_fns, 0, 0 }, + { "movcnd8_1", ICLASS_iclass_MOVCND8_1, + 0, + Opcode_movcnd8_1_encode_fns, 0, 0 }, + { "movcnd8_2", ICLASS_iclass_MOVCND8_2, + 0, + Opcode_movcnd8_2_encode_fns, 0, 0 }, + { "movcnd8_3", ICLASS_iclass_MOVCND8_3, + 0, + Opcode_movcnd8_3_encode_fns, 0, 0 }, + { "movcnd8_4", ICLASS_iclass_MOVCND8_4, + 0, + Opcode_movcnd8_4_encode_fns, 0, 0 }, + { "movcnd8_5", ICLASS_iclass_MOVCND8_5, + 0, + Opcode_movcnd8_5_encode_fns, 0, 0 }, + { "movcnd8_6", ICLASS_iclass_MOVCND8_6, + 0, + Opcode_movcnd8_6_encode_fns, 0, 0 }, + { "movcnd8_7", ICLASS_iclass_MOVCND8_7, + 0, + Opcode_movcnd8_7_encode_fns, 0, 0 }, + { "mov_i", ICLASS_iclass_MOV_I, + 0, + Opcode_mov_i_encode_fns, 0, 0 }, + { "movpq2pq", ICLASS_iclass_MOVPQ2PQ, + 0, + Opcode_movpq2pq_encode_fns, 0, 0 }, + { "mov_r", ICLASS_iclass_MOV_R, + 0, + Opcode_mov_r_encode_fns, 0, 0 }, + { "negcm", ICLASS_iclass_NEGCM, + 0, + Opcode_negcm_encode_fns, 0, 0 }, + { "pop16llr_1", ICLASS_iclass_POP16LLR_1, + 0, + Opcode_pop16llr_1_encode_fns, 0, 0 }, + { "pq2cm", ICLASS_iclass_PQ2CM, + 0, + Opcode_pq2cm_encode_fns, 0, 0 }, + { "swapac_r", ICLASS_iclass_SWAPAC_R, + 0, + Opcode_swapac_r_encode_fns, 0, 0 }, + { "swapac_ri", ICLASS_iclass_SWAPAC_RI, + 0, + Opcode_swapac_ri_encode_fns, 0, 0 }, + { "swapb", ICLASS_iclass_SWAPB, + 0, + Opcode_swapb_encode_fns, 0, 0 }, + { "add2ac", ICLASS_iclass_ADD2AC, + 0, + Opcode_add2ac_encode_fns, 0, 0 }, + { "addac", ICLASS_iclass_ADDAC, + 0, + Opcode_addac_encode_fns, 0, 0 }, + { "cdot", ICLASS_iclass_CDOT, + 0, + Opcode_cdot_encode_fns, 0, 0 }, + { "cdotac", ICLASS_iclass_CDOTAC, + 0, + Opcode_cdotac_encode_fns, 0, 0 }, + { "cdotacs", ICLASS_iclass_CDOTACS, + 0, + Opcode_cdotacs_encode_fns, 0, 0 }, + { "cmac", ICLASS_iclass_CMAC, + 0, + Opcode_cmac_encode_fns, 0, 0 }, + { "cmacs", ICLASS_iclass_CMACS, + 0, + Opcode_cmacs_encode_fns, 0, 0 }, + { "cmpy", ICLASS_iclass_CMPY, + 0, + Opcode_cmpy_encode_fns, 0, 0 }, + { "cmpy2cm", ICLASS_iclass_CMPY2CM, + 0, + Opcode_cmpy2cm_encode_fns, 0, 0 }, + { "cmpy2pq", ICLASS_iclass_CMPY2PQ, + 0, + Opcode_cmpy2pq_encode_fns, 0, 0 }, + { "cmpys", ICLASS_iclass_CMPYS, + 0, + Opcode_cmpys_encode_fns, 0, 0 }, + { "cmpyxp2pq", ICLASS_iclass_CMPYXP2PQ, + 0, + Opcode_cmpyxp2pq_encode_fns, 0, 0 }, + { "comb32", ICLASS_iclass_COMB32, + 0, + Opcode_comb32_encode_fns, 0, 0 }, + { "dot", ICLASS_iclass_DOT, + 0, + Opcode_dot_encode_fns, 0, 0 }, + { "dotac", ICLASS_iclass_DOTAC, + 0, + Opcode_dotac_encode_fns, 0, 0 }, + { "dotacs", ICLASS_iclass_DOTACS, + 0, + Opcode_dotacs_encode_fns, 0, 0 }, + { "lin_int", ICLASS_iclass_LIN_INT, + 0, + Opcode_lin_int_encode_fns, 0, 0 }, + { "llrpre1", ICLASS_iclass_LLRPRE1, + 0, + Opcode_llrpre1_encode_fns, 0, 0 }, + { "llrpre2", ICLASS_iclass_LLRPRE2, + 0, + Opcode_llrpre2_encode_fns, 0, 0 }, + { "mac", ICLASS_iclass_MAC, + 0, + Opcode_mac_encode_fns, 0, 0 }, + { "mac8", ICLASS_iclass_MAC8, + 0, + Opcode_mac8_encode_fns, 0, 0 }, + { "macd8", ICLASS_iclass_MACD8, + 0, + Opcode_macd8_encode_fns, 0, 0 }, + { "macpqxp_0", ICLASS_iclass_MACPQXP_0, + 0, + Opcode_macpqxp_0_encode_fns, 0, 0 }, + { "macpqxp_1", ICLASS_iclass_MACPQXP_1, + 0, + Opcode_macpqxp_1_encode_fns, 0, 0 }, + { "macpqxp_2", ICLASS_iclass_MACPQXP_2, + 0, + Opcode_macpqxp_2_encode_fns, 0, 0 }, + { "macpqxp_3", ICLASS_iclass_MACPQXP_3, + 0, + Opcode_macpqxp_3_encode_fns, 0, 0 }, + { "macs", ICLASS_iclass_MACS, + 0, + Opcode_macs_encode_fns, 0, 0 }, + { "macxp2_0", ICLASS_iclass_MACXP2_0, + 0, + Opcode_macxp2_0_encode_fns, 0, 0 }, + { "macxp2_1", ICLASS_iclass_MACXP2_1, + 0, + Opcode_macxp2_1_encode_fns, 0, 0 }, + { "macxp_0", ICLASS_iclass_MACXP_0, + 0, + Opcode_macxp_0_encode_fns, 0, 0 }, + { "macxp_1", ICLASS_iclass_MACXP_1, + 0, + Opcode_macxp_1_encode_fns, 0, 0 }, + { "macxp_2", ICLASS_iclass_MACXP_2, + 0, + Opcode_macxp_2_encode_fns, 0, 0 }, + { "macxp_3", ICLASS_iclass_MACXP_3, + 0, + Opcode_macxp_3_encode_fns, 0, 0 }, + { "mov2ac", ICLASS_iclass_MOV2AC, + 0, + Opcode_mov2ac_encode_fns, 0, 0 }, + { "mpy", ICLASS_iclass_MPY, + 0, + Opcode_mpy_encode_fns, 0, 0 }, + { "mpy2cm", ICLASS_iclass_MPY2CM, + 0, + Opcode_mpy2cm_encode_fns, 0, 0 }, + { "mpy2pq", ICLASS_iclass_MPY2PQ, + 0, + Opcode_mpy2pq_encode_fns, 0, 0 }, + { "mpy8", ICLASS_iclass_MPY8, + 0, + Opcode_mpy8_encode_fns, 0, 0 }, + { "mpyadd8_2cm", ICLASS_iclass_MPYADD8_2CM, + 0, + Opcode_mpyadd8_2cm_encode_fns, 0, 0 }, + { "mpyd8", ICLASS_iclass_MPYD8, + 0, + Opcode_mpyd8_encode_fns, 0, 0 }, + { "mpypqxp_0", ICLASS_iclass_MPYPQXP_0, + 0, + Opcode_mpypqxp_0_encode_fns, 0, 0 }, + { "mpypqxp_1", ICLASS_iclass_MPYPQXP_1, + 0, + Opcode_mpypqxp_1_encode_fns, 0, 0 }, + { "mpypqxp_2", ICLASS_iclass_MPYPQXP_2, + 0, + Opcode_mpypqxp_2_encode_fns, 0, 0 }, + { "mpypqxp_3", ICLASS_iclass_MPYPQXP_3, + 0, + Opcode_mpypqxp_3_encode_fns, 0, 0 }, + { "mpys", ICLASS_iclass_MPYS, + 0, + Opcode_mpys_encode_fns, 0, 0 }, + { "mpyxp2pq", ICLASS_iclass_MPYXP2PQ, + 0, + Opcode_mpyxp2pq_encode_fns, 0, 0 }, + { "mpyxp2_0", ICLASS_iclass_MPYXP2_0, + 0, + Opcode_mpyxp2_0_encode_fns, 0, 0 }, + { "mpyxp2_1", ICLASS_iclass_MPYXP2_1, + 0, + Opcode_mpyxp2_1_encode_fns, 0, 0 }, + { "mpyxp_0", ICLASS_iclass_MPYXP_0, + 0, + Opcode_mpyxp_0_encode_fns, 0, 0 }, + { "mpyxp_1", ICLASS_iclass_MPYXP_1, + 0, + Opcode_mpyxp_1_encode_fns, 0, 0 }, + { "mpyxp_2", ICLASS_iclass_MPYXP_2, + 0, + Opcode_mpyxp_2_encode_fns, 0, 0 }, + { "mpyxp_3", ICLASS_iclass_MPYXP_3, + 0, + Opcode_mpyxp_3_encode_fns, 0, 0 }, + { "normacd", ICLASS_iclass_NORMACD, + 0, + Opcode_normacd_encode_fns, 0, 0 }, + { "normacpq_i", ICLASS_iclass_NORMACPQ_I, + 0, + Opcode_normacpq_i_encode_fns, 0, 0 }, + { "normacpq_r", ICLASS_iclass_NORMACPQ_R, + 0, + Opcode_normacpq_r_encode_fns, 0, 0 }, + { "normd", ICLASS_iclass_NORMD, + 0, + Opcode_normd_encode_fns, 0, 0 }, + { "normpypq_i", ICLASS_iclass_NORMPYPQ_I, + 0, + Opcode_normpypq_i_encode_fns, 0, 0 }, + { "normpypq_r", ICLASS_iclass_NORMPYPQ_R, + 0, + Opcode_normpypq_r_encode_fns, 0, 0 }, + { "rcmac", ICLASS_iclass_RCMAC, + 0, + Opcode_rcmac_encode_fns, 0, 0 }, + { "rcmpy", ICLASS_iclass_RCMPY, + 0, + Opcode_rcmpy_encode_fns, 0, 0 }, + { "rcmpy2cm", ICLASS_iclass_RCMPY2CM, + 0, + Opcode_rcmpy2cm_encode_fns, 0, 0 }, + { "rfir", ICLASS_iclass_RFIR, + 0, + Opcode_rfir_encode_fns, 0, 0 }, + { "rfira", ICLASS_iclass_RFIRA, + 0, + Opcode_rfira_encode_fns, 0, 0 }, + { "rfird", ICLASS_iclass_RFIRD, + 0, + Opcode_rfird_encode_fns, 0, 0 }, + { "rfirda", ICLASS_iclass_RFIRDA, + 0, + Opcode_rfirda_encode_fns, 0, 0 }, + { "rmac", ICLASS_iclass_RMAC, + 0, + Opcode_rmac_encode_fns, 0, 0 }, + { "rmpy", ICLASS_iclass_RMPY, + 0, + Opcode_rmpy_encode_fns, 0, 0 }, + { "rmpy2cm", ICLASS_iclass_RMPY2CM, + 0, + Opcode_rmpy2cm_encode_fns, 0, 0 }, + { "smod_align", ICLASS_iclass_SMOD_ALIGN, + 0, + Opcode_smod_align_encode_fns, 0, 0 }, + { "smod_scr", ICLASS_iclass_SMOD_SCR, + 0, + Opcode_smod_scr_encode_fns, 0, 0 }, + { "sub2ac", ICLASS_iclass_SUB2AC, + 0, + Opcode_sub2ac_encode_fns, 0, 0 }, + { "wght32", ICLASS_iclass_WGHT32, + 0, + Opcode_wght32_encode_fns, 0, 0 }, + { "clrtiep", ICLASS_iclass_CLRTIEP, + 0, + Opcode_clrtiep_encode_fns, 0, 0 }, + { "ext_2fifo_0", ICLASS_iclass_EXT_2FIFO_0, + 0, + Opcode_ext_2fifo_0_encode_fns, 0, 0 }, + { "ext_2fifo_1", ICLASS_iclass_EXT_2FIFO_1, + 0, + Opcode_ext_2fifo_1_encode_fns, 0, 0 }, + { "ext_2fifo_2", ICLASS_iclass_EXT_2FIFO_2, + 0, + Opcode_ext_2fifo_2_encode_fns, 0, 0 }, + { "ext_2fifo_3", ICLASS_iclass_EXT_2FIFO_3, + 0, + Opcode_ext_2fifo_3_encode_fns, 0, 0 }, + { "ext_r2fifo_0", ICLASS_iclass_EXT_R2FIFO_0, + 0, + Opcode_ext_r2fifo_0_encode_fns, 0, 0 }, + { "ext_r2fifo_1", ICLASS_iclass_EXT_R2FIFO_1, + 0, + Opcode_ext_r2fifo_1_encode_fns, 0, 0 }, + { "ext_r2fifo_2", ICLASS_iclass_EXT_R2FIFO_2, + 0, + Opcode_ext_r2fifo_2_encode_fns, 0, 0 }, + { "ext_r2fifo_3", ICLASS_iclass_EXT_R2FIFO_3, + 0, + Opcode_ext_r2fifo_3_encode_fns, 0, 0 }, + { "lut", ICLASS_iclass_LUT, + 0, + Opcode_lut_encode_fns, 0, 0 }, + { "lut_ar", ICLASS_iclass_LUT_AR, + 0, + Opcode_lut_ar_encode_fns, 0, 0 }, + { "lut_iext", ICLASS_iclass_LUT_IEXT, + 0, + Opcode_lut_iext_encode_fns, 0, 0 }, + { "lut_phasor", ICLASS_iclass_LUT_PHASOR, + 0, + Opcode_lut_phasor_encode_fns, 0, 0 }, + { "lut_rext", ICLASS_iclass_LUT_REXT, + 0, + Opcode_lut_rext_encode_fns, 0, 0 }, + { "lut_write", ICLASS_iclass_LUT_WRITE, + 0, + Opcode_lut_write_encode_fns, 0, 0 }, + { "moveq128_0", ICLASS_iclass_MOVEQ128_0, + 0, + Opcode_moveq128_0_encode_fns, 0, 0 }, + { "moveq128_1", ICLASS_iclass_MOVEQ128_1, + 0, + Opcode_moveq128_1_encode_fns, 0, 0 }, + { "moveq128_2", ICLASS_iclass_MOVEQ128_2, + 0, + Opcode_moveq128_2_encode_fns, 0, 0 }, + { "moveq128_3", ICLASS_iclass_MOVEQ128_3, + 0, + Opcode_moveq128_3_encode_fns, 0, 0 }, + { "moveq128_4", ICLASS_iclass_MOVEQ128_4, + 0, + Opcode_moveq128_4_encode_fns, 0, 0 }, + { "moveq128_5", ICLASS_iclass_MOVEQ128_5, + 0, + Opcode_moveq128_5_encode_fns, 0, 0 }, + { "moveq32_0", ICLASS_iclass_MOVEQ32_0, + 0, + Opcode_moveq32_0_encode_fns, 0, 0 }, + { "moveq32_1", ICLASS_iclass_MOVEQ32_1, + 0, + Opcode_moveq32_1_encode_fns, 0, 0 }, + { "moveq32_2", ICLASS_iclass_MOVEQ32_2, + 0, + Opcode_moveq32_2_encode_fns, 0, 0 }, + { "moveq32_3", ICLASS_iclass_MOVEQ32_3, + 0, + Opcode_moveq32_3_encode_fns, 0, 0 }, + { "nco_update", ICLASS_iclass_NCO_UPDATE, + 0, + Opcode_nco_update_encode_fns, 0, 0 }, + { "pop128_0", ICLASS_iclass_POP128_0, + 0, + Opcode_pop128_0_encode_fns, 0, 0 }, + { "pop128_1", ICLASS_iclass_POP128_1, + 0, + Opcode_pop128_1_encode_fns, 0, 0 }, + { "pop128_2", ICLASS_iclass_POP128_2, + 0, + Opcode_pop128_2_encode_fns, 0, 0 }, + { "pop128_3", ICLASS_iclass_POP128_3, + 0, + Opcode_pop128_3_encode_fns, 0, 0 }, + { "pop128_4", ICLASS_iclass_POP128_4, + 0, + Opcode_pop128_4_encode_fns, 0, 0 }, + { "pop128_5", ICLASS_iclass_POP128_5, + 0, + Opcode_pop128_5_encode_fns, 0, 0 }, + { "pop128_2cmpq_0", ICLASS_iclass_POP128_2CMPQ_0, + 0, + Opcode_pop128_2cmpq_0_encode_fns, 0, 0 }, + { "pop128_2cmpq_1", ICLASS_iclass_POP128_2CMPQ_1, + 0, + Opcode_pop128_2cmpq_1_encode_fns, 0, 0 }, + { "pop128_2cmpq_2", ICLASS_iclass_POP128_2CMPQ_2, + 0, + Opcode_pop128_2cmpq_2_encode_fns, 0, 0 }, + { "pop128_2cmpq_3", ICLASS_iclass_POP128_2CMPQ_3, + 0, + Opcode_pop128_2cmpq_3_encode_fns, 0, 0 }, + { "pop128_2m_0", ICLASS_iclass_POP128_2M_0, + 0, + Opcode_pop128_2m_0_encode_fns, 0, 0 }, + { "pop128_2m_1", ICLASS_iclass_POP128_2M_1, + 0, + Opcode_pop128_2m_1_encode_fns, 0, 0 }, + { "pop128_2m_2", ICLASS_iclass_POP128_2M_2, + 0, + Opcode_pop128_2m_2_encode_fns, 0, 0 }, + { "pop128_2m_3", ICLASS_iclass_POP128_2M_3, + 0, + Opcode_pop128_2m_3_encode_fns, 0, 0 }, + { "pop128_2pq_0", ICLASS_iclass_POP128_2PQ_0, + 0, + Opcode_pop128_2pq_0_encode_fns, 0, 0 }, + { "pop128_2pq_1", ICLASS_iclass_POP128_2PQ_1, + 0, + Opcode_pop128_2pq_1_encode_fns, 0, 0 }, + { "pop128_2pq_2", ICLASS_iclass_POP128_2PQ_2, + 0, + Opcode_pop128_2pq_2_encode_fns, 0, 0 }, + { "pop128_2pq_3", ICLASS_iclass_POP128_2PQ_3, + 0, + Opcode_pop128_2pq_3_encode_fns, 0, 0 }, + { "pop128_2pq_4", ICLASS_iclass_POP128_2PQ_4, + 0, + Opcode_pop128_2pq_4_encode_fns, 0, 0 }, + { "pop128_2pq_5", ICLASS_iclass_POP128_2PQ_5, + 0, + Opcode_pop128_2pq_5_encode_fns, 0, 0 }, + { "pop2x128_2pq_01", ICLASS_iclass_POP2X128_2PQ_01, + 0, + Opcode_pop2x128_2pq_01_encode_fns, 0, 0 }, + { "pop2x128_2pq_03", ICLASS_iclass_POP2X128_2PQ_03, + 0, + Opcode_pop2x128_2pq_03_encode_fns, 0, 0 }, + { "pop2x128_2pq_21", ICLASS_iclass_POP2X128_2PQ_21, + 0, + Opcode_pop2x128_2pq_21_encode_fns, 0, 0 }, + { "pop2x128_2pq_23", ICLASS_iclass_POP2X128_2PQ_23, + 0, + Opcode_pop2x128_2pq_23_encode_fns, 0, 0 }, + { "pop32_0", ICLASS_iclass_POP32_0, + 0, + Opcode_pop32_0_encode_fns, 0, 0 }, + { "pop32_1", ICLASS_iclass_POP32_1, + 0, + Opcode_pop32_1_encode_fns, 0, 0 }, + { "pop32_2", ICLASS_iclass_POP32_2, + 0, + Opcode_pop32_2_encode_fns, 0, 0 }, + { "pop32_3", ICLASS_iclass_POP32_3, + 0, + Opcode_pop32_3_encode_fns, 0, 0 }, + { "push128", ICLASS_iclass_PUSH128, + 0, + Opcode_push128_encode_fns, 0, 0 }, + { "push128_m", ICLASS_iclass_PUSH128_M, + 0, + Opcode_push128_m_encode_fns, 0, 0 }, + { "push128_pq", ICLASS_iclass_PUSH128_PQ, + 0, + Opcode_push128_pq_encode_fns, 0, 0 }, + { "push2x128_pq", ICLASS_iclass_PUSH2X128_PQ, + 0, + Opcode_push2x128_pq_encode_fns, 0, 0 }, + { "push32", ICLASS_iclass_PUSH32, + 0, + Opcode_push32_encode_fns, 0, 0 }, + { "qready", ICLASS_iclass_QREADY, + 0, + Opcode_qready_encode_fns, 0, 0 }, + { "rdtiep", ICLASS_iclass_RDTIEP, + 0, + Opcode_rdtiep_encode_fns, 0, 0 }, + { "settiep", ICLASS_iclass_SETTIEP, + 0, + Opcode_settiep_encode_fns, 0, 0 }, + { "smod_lut", ICLASS_iclass_SMOD_LUT, + 0, + Opcode_smod_lut_encode_fns, 0, 0 }, + { "wrtbsigq", ICLASS_iclass_WRTBSIGQ, + 0, + Opcode_wrtbsigq_encode_fns, 0, 0 }, + { "wrtbsigqm", ICLASS_iclass_WRTBSIGQM, + 0, + Opcode_wrtbsigqm_encode_fns, 0, 0 }, + { "wrtiep", ICLASS_iclass_WRTIEP, + 0, + Opcode_wrtiep_encode_fns, 0, 0 }, + { "wrtsigq", ICLASS_iclass_WRTSIGQ, + 0, + Opcode_wrtsigq_encode_fns, 0, 0 }, + { "abs8", ICLASS_iclass_ABS8, + 0, + Opcode_abs8_encode_fns, 0, 0 }, + { "add16", ICLASS_iclass_ADD16, + 0, + Opcode_add16_encode_fns, 0, 0 }, + { "add32", ICLASS_iclass_ADD32, + 0, + Opcode_add32_encode_fns, 0, 0 }, + { "addac_i2r", ICLASS_iclass_ADDAC_I2R, + 0, + Opcode_addac_i2r_encode_fns, 0, 0 }, + { "addac_r2i", ICLASS_iclass_ADDAC_R2I, + 0, + Opcode_addac_r2i_encode_fns, 0, 0 }, + { "addar2", ICLASS_iclass_ADDAR2, + 0, + Opcode_addar2_encode_fns, 0, 0 }, + { "addcm", ICLASS_iclass_ADDCM, + 0, + Opcode_addcm_encode_fns, 0, 0 }, + { "addwrp", ICLASS_iclass_ADDWRP, + 0, + Opcode_addwrp_encode_fns, 0, 0 }, + { "and128", ICLASS_iclass_AND128, + 0, + Opcode_and128_encode_fns, 0, 0 }, + { "argmax8", ICLASS_iclass_ARGMAX8, + 0, + Opcode_argmax8_encode_fns, 0, 0 }, + { "asl", ICLASS_iclass_ASL, + 0, + Opcode_asl_encode_fns, 0, 0 }, + { "asl32", ICLASS_iclass_ASL32, + 0, + Opcode_asl32_encode_fns, 0, 0 }, + { "aslacm", ICLASS_iclass_ASLACM, + 0, + Opcode_aslacm_encode_fns, 0, 0 }, + { "aslm", ICLASS_iclass_ASLM, + 0, + Opcode_aslm_encode_fns, 0, 0 }, + { "aslm32", ICLASS_iclass_ASLM32, + 0, + Opcode_aslm32_encode_fns, 0, 0 }, + { "asr", ICLASS_iclass_ASR, + 0, + Opcode_asr_encode_fns, 0, 0 }, + { "asr32", ICLASS_iclass_ASR32, + 0, + Opcode_asr32_encode_fns, 0, 0 }, + { "asrac", ICLASS_iclass_ASRAC, + 0, + Opcode_asrac_encode_fns, 0, 0 }, + { "asrm", ICLASS_iclass_ASRM, + 0, + Opcode_asrm_encode_fns, 0, 0 }, + { "bitfext", ICLASS_iclass_BITFEXT, + 0, + Opcode_bitfext_encode_fns, 0, 0 }, + { "bitfins", ICLASS_iclass_BITFINS, + 0, + Opcode_bitfins_encode_fns, 0, 0 }, + { "clb_c", ICLASS_iclass_CLB_C, + 0, + Opcode_clb_c_encode_fns, 0, 0 }, + { "clb_r", ICLASS_iclass_CLB_R, + 0, + Opcode_clb_r_encode_fns, 0, 0 }, + { "cmp8", ICLASS_iclass_CMP8, + 0, + Opcode_cmp8_encode_fns, 0, 0 }, + { "cmp_i", ICLASS_iclass_CMP_I, + 0, + Opcode_cmp_i_encode_fns, 0, 0 }, + { "cmp_r", ICLASS_iclass_CMP_R, + 0, + Opcode_cmp_r_encode_fns, 0, 0 }, + { "ext", ICLASS_iclass_EXT, + 0, + Opcode_ext_encode_fns, 0, 0 }, + { "ext_r", ICLASS_iclass_EXT_R, + 0, + Opcode_ext_r_encode_fns, 0, 0 }, + { "ext32_i", ICLASS_iclass_EXT32_I, + 0, + Opcode_ext32_i_encode_fns, 0, 0 }, + { "ext32_r", ICLASS_iclass_EXT32_R, + 0, + Opcode_ext32_r_encode_fns, 0, 0 }, + { "extui4", ICLASS_iclass_EXTUI4, + 0, + Opcode_extui4_encode_fns, 0, 0 }, + { "lslm", ICLASS_iclass_LSLM, + 0, + Opcode_lslm_encode_fns, 0, 0 }, + { "lsrm", ICLASS_iclass_LSRM, + 0, + Opcode_lsrm_encode_fns, 0, 0 }, + { "max8", ICLASS_iclass_MAX8, + 0, + Opcode_max8_encode_fns, 0, 0 }, + { "mean", ICLASS_iclass_MEAN, + 0, + Opcode_mean_encode_fns, 0, 0 }, + { "mean32", ICLASS_iclass_MEAN32, + 0, + Opcode_mean32_encode_fns, 0, 0 }, + { "min8", ICLASS_iclass_MIN8, + 0, + Opcode_min8_encode_fns, 0, 0 }, + { "minclb_c", ICLASS_iclass_MINCLB_C, + 0, + Opcode_minclb_c_encode_fns, 0, 0 }, + { "minclb_r", ICLASS_iclass_MINCLB_R, + 0, + Opcode_minclb_r_encode_fns, 0, 0 }, + { "not128", ICLASS_iclass_NOT128, + 0, + Opcode_not128_encode_fns, 0, 0 }, + { "or128", ICLASS_iclass_OR128, + 0, + Opcode_or128_encode_fns, 0, 0 }, + { "perm", ICLASS_iclass_PERM, + 0, + Opcode_perm_encode_fns, 0, 0 }, + { "redac", ICLASS_iclass_REDAC, + 0, + Opcode_redac_encode_fns, 0, 0 }, + { "redac2", ICLASS_iclass_REDAC2, + 0, + Opcode_redac2_encode_fns, 0, 0 }, + { "redac4", ICLASS_iclass_REDAC4, + 0, + Opcode_redac4_encode_fns, 0, 0 }, + { "redacs", ICLASS_iclass_REDACS, + 0, + Opcode_redacs_encode_fns, 0, 0 }, + { "sminclb_c", ICLASS_iclass_SMINCLB_C, + 0, + Opcode_sminclb_c_encode_fns, 0, 0 }, + { "sminclb_r", ICLASS_iclass_SMINCLB_R, + 0, + Opcode_sminclb_r_encode_fns, 0, 0 }, + { "stswapbm", ICLASS_iclass_STSWAPBM, + 0, + Opcode_stswapbm_encode_fns, 0, 0 }, + { "stswapbmu", ICLASS_iclass_STSWAPBMU, + 0, + Opcode_stswapbmu_encode_fns, 0, 0 }, + { "sub32", ICLASS_iclass_SUB32, + 0, + Opcode_sub32_encode_fns, 0, 0 }, + { "subac_i2r", ICLASS_iclass_SUBAC_I2R, + 0, + Opcode_subac_i2r_encode_fns, 0, 0 }, + { "subac_r2i", ICLASS_iclass_SUBAC_R2I, + 0, + Opcode_subac_r2i_encode_fns, 0, 0 }, + { "subarx", ICLASS_iclass_SUBARX, + 0, + Opcode_subarx_encode_fns, 0, 0 }, + { "subcm", ICLASS_iclass_SUBCM, + 0, + Opcode_subcm_encode_fns, 0, 0 }, + { "submean", ICLASS_iclass_SUBMEAN, + 0, + Opcode_submean_encode_fns, 0, 0 }, + { "subwrp", ICLASS_iclass_SUBWRP, + 0, + Opcode_subwrp_encode_fns, 0, 0 }, + { "trans", ICLASS_iclass_TRANS, + 0, + Opcode_trans_encode_fns, 0, 0 }, + { "xor128", ICLASS_iclass_XOR128, + 0, + Opcode_xor128_encode_fns, 0, 0 }, + { "rur.expstate", ICLASS_rur_expstate, + 0, + Opcode_rur_expstate_encode_fns, 0, 0 }, + { "wur.expstate", ICLASS_wur_expstate, + 0, + Opcode_wur_expstate_encode_fns, 0, 0 }, + { "rur.sov", ICLASS_rur_sov, + 0, + Opcode_rur_sov_encode_fns, 0, 0 }, + { "wur.sov", ICLASS_wur_sov, + 0, + Opcode_wur_sov_encode_fns, 0, 0 }, + { "rur.sat_mode", ICLASS_rur_sat_mode, + 0, + Opcode_rur_sat_mode_encode_fns, 0, 0 }, + { "wur.sat_mode", ICLASS_wur_sat_mode, + 0, + Opcode_wur_sat_mode_encode_fns, 0, 0 }, + { "rur.sar0", ICLASS_rur_sar0, + 0, + Opcode_rur_sar0_encode_fns, 0, 0 }, + { "wur.sar0", ICLASS_wur_sar0, + 0, + Opcode_wur_sar0_encode_fns, 0, 0 }, + { "rur.sar1", ICLASS_rur_sar1, + 0, + Opcode_rur_sar1_encode_fns, 0, 0 }, + { "wur.sar1", ICLASS_wur_sar1, + 0, + Opcode_wur_sar1_encode_fns, 0, 0 }, + { "rur.sar2", ICLASS_rur_sar2, + 0, + Opcode_rur_sar2_encode_fns, 0, 0 }, + { "wur.sar2", ICLASS_wur_sar2, + 0, + Opcode_wur_sar2_encode_fns, 0, 0 }, + { "rur.sar3", ICLASS_rur_sar3, + 0, + Opcode_rur_sar3_encode_fns, 0, 0 }, + { "wur.sar3", ICLASS_wur_sar3, + 0, + Opcode_wur_sar3_encode_fns, 0, 0 }, + { "rur.hsar0", ICLASS_rur_hsar0, + 0, + Opcode_rur_hsar0_encode_fns, 0, 0 }, + { "wur.hsar0", ICLASS_wur_hsar0, + 0, + Opcode_wur_hsar0_encode_fns, 0, 0 }, + { "rur.hsar1", ICLASS_rur_hsar1, + 0, + Opcode_rur_hsar1_encode_fns, 0, 0 }, + { "wur.hsar1", ICLASS_wur_hsar1, + 0, + Opcode_wur_hsar1_encode_fns, 0, 0 }, + { "rur.hsar2", ICLASS_rur_hsar2, + 0, + Opcode_rur_hsar2_encode_fns, 0, 0 }, + { "wur.hsar2", ICLASS_wur_hsar2, + 0, + Opcode_wur_hsar2_encode_fns, 0, 0 }, + { "rur.hsar3", ICLASS_rur_hsar3, + 0, + Opcode_rur_hsar3_encode_fns, 0, 0 }, + { "wur.hsar3", ICLASS_wur_hsar3, + 0, + Opcode_wur_hsar3_encode_fns, 0, 0 }, + { "rur.max_reg_0", ICLASS_rur_max_reg_0, + 0, + Opcode_rur_max_reg_0_encode_fns, 0, 0 }, + { "wur.max_reg_0", ICLASS_wur_max_reg_0, + 0, + Opcode_wur_max_reg_0_encode_fns, 0, 0 }, + { "rur.max_reg_1", ICLASS_rur_max_reg_1, + 0, + Opcode_rur_max_reg_1_encode_fns, 0, 0 }, + { "wur.max_reg_1", ICLASS_wur_max_reg_1, + 0, + Opcode_wur_max_reg_1_encode_fns, 0, 0 }, + { "rur.max_reg_2", ICLASS_rur_max_reg_2, + 0, + Opcode_rur_max_reg_2_encode_fns, 0, 0 }, + { "wur.max_reg_2", ICLASS_wur_max_reg_2, + 0, + Opcode_wur_max_reg_2_encode_fns, 0, 0 }, + { "rur.max_reg_3", ICLASS_rur_max_reg_3, + 0, + Opcode_rur_max_reg_3_encode_fns, 0, 0 }, + { "wur.max_reg_3", ICLASS_wur_max_reg_3, + 0, + Opcode_wur_max_reg_3_encode_fns, 0, 0 }, + { "rur.arg_max_reg_0", ICLASS_rur_arg_max_reg_0, + 0, + Opcode_rur_arg_max_reg_0_encode_fns, 0, 0 }, + { "wur.arg_max_reg_0", ICLASS_wur_arg_max_reg_0, + 0, + Opcode_wur_arg_max_reg_0_encode_fns, 0, 0 }, + { "rur.arg_max_reg_1", ICLASS_rur_arg_max_reg_1, + 0, + Opcode_rur_arg_max_reg_1_encode_fns, 0, 0 }, + { "wur.arg_max_reg_1", ICLASS_wur_arg_max_reg_1, + 0, + Opcode_wur_arg_max_reg_1_encode_fns, 0, 0 }, + { "rur.arg_max_reg_2", ICLASS_rur_arg_max_reg_2, + 0, + Opcode_rur_arg_max_reg_2_encode_fns, 0, 0 }, + { "wur.arg_max_reg_2", ICLASS_wur_arg_max_reg_2, + 0, + Opcode_wur_arg_max_reg_2_encode_fns, 0, 0 }, + { "rur.arg_max_reg_3", ICLASS_rur_arg_max_reg_3, + 0, + Opcode_rur_arg_max_reg_3_encode_fns, 0, 0 }, + { "wur.arg_max_reg_3", ICLASS_wur_arg_max_reg_3, + 0, + Opcode_wur_arg_max_reg_3_encode_fns, 0, 0 }, + { "rur.nco_counter_0", ICLASS_rur_nco_counter_0, + 0, + Opcode_rur_nco_counter_0_encode_fns, 0, 0 }, + { "wur.nco_counter_0", ICLASS_wur_nco_counter_0, + 0, + Opcode_wur_nco_counter_0_encode_fns, 0, 0 }, + { "rur.nco_counter_1", ICLASS_rur_nco_counter_1, + 0, + Opcode_rur_nco_counter_1_encode_fns, 0, 0 }, + { "wur.nco_counter_1", ICLASS_wur_nco_counter_1, + 0, + Opcode_wur_nco_counter_1_encode_fns, 0, 0 }, + { "rur.nco_counter_2", ICLASS_rur_nco_counter_2, + 0, + Opcode_rur_nco_counter_2_encode_fns, 0, 0 }, + { "wur.nco_counter_2", ICLASS_wur_nco_counter_2, + 0, + Opcode_wur_nco_counter_2_encode_fns, 0, 0 }, + { "rur.nco_counter_3", ICLASS_rur_nco_counter_3, + 0, + Opcode_rur_nco_counter_3_encode_fns, 0, 0 }, + { "wur.nco_counter_3", ICLASS_wur_nco_counter_3, + 0, + Opcode_wur_nco_counter_3_encode_fns, 0, 0 }, + { "rur.interp_ext_n", ICLASS_rur_interp_ext_n, + 0, + Opcode_rur_interp_ext_n_encode_fns, 0, 0 }, + { "wur.interp_ext_n", ICLASS_wur_interp_ext_n, + 0, + Opcode_wur_interp_ext_n_encode_fns, 0, 0 }, + { "rur.interp_ext_l", ICLASS_rur_interp_ext_l, + 0, + Opcode_rur_interp_ext_l_encode_fns, 0, 0 }, + { "wur.interp_ext_l", ICLASS_wur_interp_ext_l, + 0, + Opcode_wur_interp_ext_l_encode_fns, 0, 0 }, + { "rur.llr_buf_0", ICLASS_rur_llr_buf_0, + 0, + Opcode_rur_llr_buf_0_encode_fns, 0, 0 }, + { "wur.llr_buf_0", ICLASS_wur_llr_buf_0, + 0, + Opcode_wur_llr_buf_0_encode_fns, 0, 0 }, + { "rur.llr_buf_1", ICLASS_rur_llr_buf_1, + 0, + Opcode_rur_llr_buf_1_encode_fns, 0, 0 }, + { "wur.llr_buf_1", ICLASS_wur_llr_buf_1, + 0, + Opcode_wur_llr_buf_1_encode_fns, 0, 0 }, + { "rur.llr_buf_2", ICLASS_rur_llr_buf_2, + 0, + Opcode_rur_llr_buf_2_encode_fns, 0, 0 }, + { "wur.llr_buf_2", ICLASS_wur_llr_buf_2, + 0, + Opcode_wur_llr_buf_2_encode_fns, 0, 0 }, + { "rur.llr_buf_3", ICLASS_rur_llr_buf_3, + 0, + Opcode_rur_llr_buf_3_encode_fns, 0, 0 }, + { "wur.llr_buf_3", ICLASS_wur_llr_buf_3, + 0, + Opcode_wur_llr_buf_3_encode_fns, 0, 0 }, + { "rur.llr_buf_4", ICLASS_rur_llr_buf_4, + 0, + Opcode_rur_llr_buf_4_encode_fns, 0, 0 }, + { "wur.llr_buf_4", ICLASS_wur_llr_buf_4, + 0, + Opcode_wur_llr_buf_4_encode_fns, 0, 0 }, + { "rur.llr_buf_5", ICLASS_rur_llr_buf_5, + 0, + Opcode_rur_llr_buf_5_encode_fns, 0, 0 }, + { "wur.llr_buf_5", ICLASS_wur_llr_buf_5, + 0, + Opcode_wur_llr_buf_5_encode_fns, 0, 0 }, + { "rur.llr_buf_6", ICLASS_rur_llr_buf_6, + 0, + Opcode_rur_llr_buf_6_encode_fns, 0, 0 }, + { "wur.llr_buf_6", ICLASS_wur_llr_buf_6, + 0, + Opcode_wur_llr_buf_6_encode_fns, 0, 0 }, + { "rur.llr_buf_7", ICLASS_rur_llr_buf_7, + 0, + Opcode_rur_llr_buf_7_encode_fns, 0, 0 }, + { "wur.llr_buf_7", ICLASS_wur_llr_buf_7, + 0, + Opcode_wur_llr_buf_7_encode_fns, 0, 0 }, + { "rur.llr_buf_8", ICLASS_rur_llr_buf_8, + 0, + Opcode_rur_llr_buf_8_encode_fns, 0, 0 }, + { "wur.llr_buf_8", ICLASS_wur_llr_buf_8, + 0, + Opcode_wur_llr_buf_8_encode_fns, 0, 0 }, + { "rur.llr_buf_9", ICLASS_rur_llr_buf_9, + 0, + Opcode_rur_llr_buf_9_encode_fns, 0, 0 }, + { "wur.llr_buf_9", ICLASS_wur_llr_buf_9, + 0, + Opcode_wur_llr_buf_9_encode_fns, 0, 0 }, + { "rur.llr_buf_10", ICLASS_rur_llr_buf_10, + 0, + Opcode_rur_llr_buf_10_encode_fns, 0, 0 }, + { "wur.llr_buf_10", ICLASS_wur_llr_buf_10, + 0, + Opcode_wur_llr_buf_10_encode_fns, 0, 0 }, + { "rur.llr_buf_11", ICLASS_rur_llr_buf_11, + 0, + Opcode_rur_llr_buf_11_encode_fns, 0, 0 }, + { "wur.llr_buf_11", ICLASS_wur_llr_buf_11, + 0, + Opcode_wur_llr_buf_11_encode_fns, 0, 0 }, + { "rur.llr_buf_12", ICLASS_rur_llr_buf_12, + 0, + Opcode_rur_llr_buf_12_encode_fns, 0, 0 }, + { "wur.llr_buf_12", ICLASS_wur_llr_buf_12, + 0, + Opcode_wur_llr_buf_12_encode_fns, 0, 0 }, + { "rur.llr_buf_13", ICLASS_rur_llr_buf_13, + 0, + Opcode_rur_llr_buf_13_encode_fns, 0, 0 }, + { "wur.llr_buf_13", ICLASS_wur_llr_buf_13, + 0, + Opcode_wur_llr_buf_13_encode_fns, 0, 0 }, + { "rur.llr_buf_14", ICLASS_rur_llr_buf_14, + 0, + Opcode_rur_llr_buf_14_encode_fns, 0, 0 }, + { "wur.llr_buf_14", ICLASS_wur_llr_buf_14, + 0, + Opcode_wur_llr_buf_14_encode_fns, 0, 0 }, + { "rur.llr_buf_15", ICLASS_rur_llr_buf_15, + 0, + Opcode_rur_llr_buf_15_encode_fns, 0, 0 }, + { "wur.llr_buf_15", ICLASS_wur_llr_buf_15, + 0, + Opcode_wur_llr_buf_15_encode_fns, 0, 0 }, + { "rur.llr_buf_16", ICLASS_rur_llr_buf_16, + 0, + Opcode_rur_llr_buf_16_encode_fns, 0, 0 }, + { "wur.llr_buf_16", ICLASS_wur_llr_buf_16, + 0, + Opcode_wur_llr_buf_16_encode_fns, 0, 0 }, + { "rur.llr_buf_17", ICLASS_rur_llr_buf_17, + 0, + Opcode_rur_llr_buf_17_encode_fns, 0, 0 }, + { "wur.llr_buf_17", ICLASS_wur_llr_buf_17, + 0, + Opcode_wur_llr_buf_17_encode_fns, 0, 0 }, + { "rur.llr_buf_18", ICLASS_rur_llr_buf_18, + 0, + Opcode_rur_llr_buf_18_encode_fns, 0, 0 }, + { "wur.llr_buf_18", ICLASS_wur_llr_buf_18, + 0, + Opcode_wur_llr_buf_18_encode_fns, 0, 0 }, + { "rur.llr_buf_19", ICLASS_rur_llr_buf_19, + 0, + Opcode_rur_llr_buf_19_encode_fns, 0, 0 }, + { "wur.llr_buf_19", ICLASS_wur_llr_buf_19, + 0, + Opcode_wur_llr_buf_19_encode_fns, 0, 0 }, + { "rur.llr_buf_20", ICLASS_rur_llr_buf_20, + 0, + Opcode_rur_llr_buf_20_encode_fns, 0, 0 }, + { "wur.llr_buf_20", ICLASS_wur_llr_buf_20, + 0, + Opcode_wur_llr_buf_20_encode_fns, 0, 0 }, + { "rur.llr_buf_21", ICLASS_rur_llr_buf_21, + 0, + Opcode_rur_llr_buf_21_encode_fns, 0, 0 }, + { "wur.llr_buf_21", ICLASS_wur_llr_buf_21, + 0, + Opcode_wur_llr_buf_21_encode_fns, 0, 0 }, + { "rur.llr_buf_22", ICLASS_rur_llr_buf_22, + 0, + Opcode_rur_llr_buf_22_encode_fns, 0, 0 }, + { "wur.llr_buf_22", ICLASS_wur_llr_buf_22, + 0, + Opcode_wur_llr_buf_22_encode_fns, 0, 0 }, + { "rur.llr_buf_23", ICLASS_rur_llr_buf_23, + 0, + Opcode_rur_llr_buf_23_encode_fns, 0, 0 }, + { "wur.llr_buf_23", ICLASS_wur_llr_buf_23, + 0, + Opcode_wur_llr_buf_23_encode_fns, 0, 0 }, + { "rur.smod_buf_0", ICLASS_rur_smod_buf_0, + 0, + Opcode_rur_smod_buf_0_encode_fns, 0, 0 }, + { "wur.smod_buf_0", ICLASS_wur_smod_buf_0, + 0, + Opcode_wur_smod_buf_0_encode_fns, 0, 0 }, + { "rur.smod_buf_1", ICLASS_rur_smod_buf_1, + 0, + Opcode_rur_smod_buf_1_encode_fns, 0, 0 }, + { "wur.smod_buf_1", ICLASS_wur_smod_buf_1, + 0, + Opcode_wur_smod_buf_1_encode_fns, 0, 0 }, + { "rur.smod_buf_2", ICLASS_rur_smod_buf_2, + 0, + Opcode_rur_smod_buf_2_encode_fns, 0, 0 }, + { "wur.smod_buf_2", ICLASS_wur_smod_buf_2, + 0, + Opcode_wur_smod_buf_2_encode_fns, 0, 0 }, + { "rur.smod_buf_3", ICLASS_rur_smod_buf_3, + 0, + Opcode_rur_smod_buf_3_encode_fns, 0, 0 }, + { "wur.smod_buf_3", ICLASS_wur_smod_buf_3, + 0, + Opcode_wur_smod_buf_3_encode_fns, 0, 0 }, + { "rur.smod_buf_4", ICLASS_rur_smod_buf_4, + 0, + Opcode_rur_smod_buf_4_encode_fns, 0, 0 }, + { "wur.smod_buf_4", ICLASS_wur_smod_buf_4, + 0, + Opcode_wur_smod_buf_4_encode_fns, 0, 0 }, + { "rur.smod_buf_5", ICLASS_rur_smod_buf_5, + 0, + Opcode_rur_smod_buf_5_encode_fns, 0, 0 }, + { "wur.smod_buf_5", ICLASS_wur_smod_buf_5, + 0, + Opcode_wur_smod_buf_5_encode_fns, 0, 0 }, + { "rur.smod_buf_6", ICLASS_rur_smod_buf_6, + 0, + Opcode_rur_smod_buf_6_encode_fns, 0, 0 }, + { "wur.smod_buf_6", ICLASS_wur_smod_buf_6, + 0, + Opcode_wur_smod_buf_6_encode_fns, 0, 0 }, + { "rur.smod_buf_7", ICLASS_rur_smod_buf_7, + 0, + Opcode_rur_smod_buf_7_encode_fns, 0, 0 }, + { "wur.smod_buf_7", ICLASS_wur_smod_buf_7, + 0, + Opcode_wur_smod_buf_7_encode_fns, 0, 0 }, + { "rur.weight_reg", ICLASS_rur_weight_reg, + 0, + Opcode_rur_weight_reg_encode_fns, 0, 0 }, + { "wur.weight_reg", ICLASS_wur_weight_reg, + 0, + Opcode_wur_weight_reg_encode_fns, 0, 0 }, + { "rur.scale_reg", ICLASS_rur_scale_reg, + 0, + Opcode_rur_scale_reg_encode_fns, 0, 0 }, + { "wur.scale_reg", ICLASS_wur_scale_reg, + 0, + Opcode_wur_scale_reg_encode_fns, 0, 0 }, + { "rur.llr_pos", ICLASS_rur_llr_pos, + 0, + Opcode_rur_llr_pos_encode_fns, 0, 0 }, + { "wur.llr_pos", ICLASS_wur_llr_pos, + 0, + Opcode_wur_llr_pos_encode_fns, 0, 0 }, + { "rur.smod_pos", ICLASS_rur_smod_pos, + 0, + Opcode_rur_smod_pos_encode_fns, 0, 0 }, + { "wur.smod_pos", ICLASS_wur_smod_pos, + 0, + Opcode_wur_smod_pos_encode_fns, 0, 0 }, + { "rur.perm_reg", ICLASS_rur_perm_reg, + 0, + Opcode_rur_perm_reg_encode_fns, 0, 0 }, + { "wur.perm_reg", ICLASS_wur_perm_reg, + 0, + Opcode_wur_perm_reg_encode_fns, 0, 0 }, + { "rur.smod_offset_table_0", ICLASS_rur_smod_offset_table_0, + 0, + Opcode_rur_smod_offset_table_0_encode_fns, 0, 0 }, + { "wur.smod_offset_table_0", ICLASS_wur_smod_offset_table_0, + 0, + Opcode_wur_smod_offset_table_0_encode_fns, 0, 0 }, + { "rur.smod_offset_table_1", ICLASS_rur_smod_offset_table_1, + 0, + Opcode_rur_smod_offset_table_1_encode_fns, 0, 0 }, + { "wur.smod_offset_table_1", ICLASS_wur_smod_offset_table_1, + 0, + Opcode_wur_smod_offset_table_1_encode_fns, 0, 0 }, + { "rur.smod_offset_table_2", ICLASS_rur_smod_offset_table_2, + 0, + Opcode_rur_smod_offset_table_2_encode_fns, 0, 0 }, + { "wur.smod_offset_table_2", ICLASS_wur_smod_offset_table_2, + 0, + Opcode_wur_smod_offset_table_2_encode_fns, 0, 0 }, + { "rur.smod_offset_table_3", ICLASS_rur_smod_offset_table_3, + 0, + Opcode_rur_smod_offset_table_3_encode_fns, 0, 0 }, + { "wur.smod_offset_table_3", ICLASS_wur_smod_offset_table_3, + 0, + Opcode_wur_smod_offset_table_3_encode_fns, 0, 0 }, + { "rur.phasor_n", ICLASS_rur_phasor_n, + 0, + Opcode_rur_phasor_n_encode_fns, 0, 0 }, + { "wur.phasor_n", ICLASS_wur_phasor_n, + 0, + Opcode_wur_phasor_n_encode_fns, 0, 0 }, + { "rur.phasor_offset", ICLASS_rur_phasor_offset, + 0, + Opcode_rur_phasor_offset_encode_fns, 0, 0 }, + { "wur.phasor_offset", ICLASS_wur_phasor_offset, + 0, + Opcode_wur_phasor_offset_encode_fns, 0, 0 } +}; + +enum xtensa_opcode_id { + OPCODE_EXCW, + OPCODE_RFE, + OPCODE_RFDE, + OPCODE_SYSCALL, + OPCODE_SIMCALL, + OPCODE_CALL12, + OPCODE_CALL8, + OPCODE_CALL4, + OPCODE_CALLX12, + OPCODE_CALLX8, + OPCODE_CALLX4, + OPCODE_ENTRY, + OPCODE_MOVSP, + OPCODE_ROTW, + OPCODE_RETW, + OPCODE_RETW_N, + OPCODE_RFWO, + OPCODE_RFWU, + OPCODE_L32E, + OPCODE_S32E, + OPCODE_RSR_WINDOWBASE, + OPCODE_WSR_WINDOWBASE, + OPCODE_XSR_WINDOWBASE, + OPCODE_RSR_WINDOWSTART, + OPCODE_WSR_WINDOWSTART, + OPCODE_XSR_WINDOWSTART, + OPCODE_ADD_N, + OPCODE_ADDI_N, + OPCODE_BEQZ_N, + OPCODE_BNEZ_N, + OPCODE_ILL_N, + OPCODE_L32I_N, + OPCODE_MOV_N, + OPCODE_MOVI_N, + OPCODE_NOP_N, + OPCODE_RET_N, + OPCODE_S32I_N, + OPCODE_RUR_THREADPTR, + OPCODE_WUR_THREADPTR, + OPCODE_ADDI, + OPCODE_ADDMI, + OPCODE_ADD, + OPCODE_SUB, + OPCODE_ADDX2, + OPCODE_ADDX4, + OPCODE_ADDX8, + OPCODE_SUBX2, + OPCODE_SUBX4, + OPCODE_SUBX8, + OPCODE_AND, + OPCODE_OR, + OPCODE_XOR, + OPCODE_BEQI, + OPCODE_BNEI, + OPCODE_BGEI, + OPCODE_BLTI, + OPCODE_BBCI, + OPCODE_BBSI, + OPCODE_BGEUI, + OPCODE_BLTUI, + OPCODE_BEQ, + OPCODE_BNE, + OPCODE_BGE, + OPCODE_BLT, + OPCODE_BGEU, + OPCODE_BLTU, + OPCODE_BANY, + OPCODE_BNONE, + OPCODE_BALL, + OPCODE_BNALL, + OPCODE_BBC, + OPCODE_BBS, + OPCODE_BEQZ, + OPCODE_BNEZ, + OPCODE_BGEZ, + OPCODE_BLTZ, + OPCODE_CALL0, + OPCODE_CALLX0, + OPCODE_EXTUI, + OPCODE_ILL, + OPCODE_J, + OPCODE_JX, + OPCODE_L16UI, + OPCODE_L16SI, + OPCODE_L32I, + OPCODE_L32R, + OPCODE_L8UI, + OPCODE_LOOP, + OPCODE_LOOPNEZ, + OPCODE_LOOPGTZ, + OPCODE_MOVI, + OPCODE_MOVEQZ, + OPCODE_MOVNEZ, + OPCODE_MOVLTZ, + OPCODE_MOVGEZ, + OPCODE_NEG, + OPCODE_ABS, + OPCODE_NOP, + OPCODE_RET, + OPCODE_S16I, + OPCODE_S32I, + OPCODE_S8I, + OPCODE_SSR, + OPCODE_SSL, + OPCODE_SSA8L, + OPCODE_SSA8B, + OPCODE_SSAI, + OPCODE_SLL, + OPCODE_SRC, + OPCODE_SRL, + OPCODE_SRA, + OPCODE_SLLI, + OPCODE_SRAI, + OPCODE_SRLI, + OPCODE_MEMW, + OPCODE_EXTW, + OPCODE_ISYNC, + OPCODE_RSYNC, + OPCODE_ESYNC, + OPCODE_DSYNC, + OPCODE_RSIL, + OPCODE_RSR_LEND, + OPCODE_WSR_LEND, + OPCODE_XSR_LEND, + OPCODE_RSR_LCOUNT, + OPCODE_WSR_LCOUNT, + OPCODE_XSR_LCOUNT, + OPCODE_RSR_LBEG, + OPCODE_WSR_LBEG, + OPCODE_XSR_LBEG, + OPCODE_RSR_SAR, + OPCODE_WSR_SAR, + OPCODE_XSR_SAR, + OPCODE_RSR_LITBASE, + OPCODE_WSR_LITBASE, + OPCODE_XSR_LITBASE, + OPCODE_RSR_176, + OPCODE_WSR_176, + OPCODE_RSR_208, + OPCODE_RSR_PS, + OPCODE_WSR_PS, + OPCODE_XSR_PS, + OPCODE_RSR_EPC1, + OPCODE_WSR_EPC1, + OPCODE_XSR_EPC1, + OPCODE_RSR_EXCSAVE1, + OPCODE_WSR_EXCSAVE1, + OPCODE_XSR_EXCSAVE1, + OPCODE_RSR_EPC2, + OPCODE_WSR_EPC2, + OPCODE_XSR_EPC2, + OPCODE_RSR_EXCSAVE2, + OPCODE_WSR_EXCSAVE2, + OPCODE_XSR_EXCSAVE2, + OPCODE_RSR_EPC3, + OPCODE_WSR_EPC3, + OPCODE_XSR_EPC3, + OPCODE_RSR_EXCSAVE3, + OPCODE_WSR_EXCSAVE3, + OPCODE_XSR_EXCSAVE3, + OPCODE_RSR_EPC4, + OPCODE_WSR_EPC4, + OPCODE_XSR_EPC4, + OPCODE_RSR_EXCSAVE4, + OPCODE_WSR_EXCSAVE4, + OPCODE_XSR_EXCSAVE4, + OPCODE_RSR_EPC5, + OPCODE_WSR_EPC5, + OPCODE_XSR_EPC5, + OPCODE_RSR_EXCSAVE5, + OPCODE_WSR_EXCSAVE5, + OPCODE_XSR_EXCSAVE5, + OPCODE_RSR_EPC6, + OPCODE_WSR_EPC6, + OPCODE_XSR_EPC6, + OPCODE_RSR_EXCSAVE6, + OPCODE_WSR_EXCSAVE6, + OPCODE_XSR_EXCSAVE6, + OPCODE_RSR_EPS2, + OPCODE_WSR_EPS2, + OPCODE_XSR_EPS2, + OPCODE_RSR_EPS3, + OPCODE_WSR_EPS3, + OPCODE_XSR_EPS3, + OPCODE_RSR_EPS4, + OPCODE_WSR_EPS4, + OPCODE_XSR_EPS4, + OPCODE_RSR_EPS5, + OPCODE_WSR_EPS5, + OPCODE_XSR_EPS5, + OPCODE_RSR_EPS6, + OPCODE_WSR_EPS6, + OPCODE_XSR_EPS6, + OPCODE_RSR_EXCVADDR, + OPCODE_WSR_EXCVADDR, + OPCODE_XSR_EXCVADDR, + OPCODE_RSR_DEPC, + OPCODE_WSR_DEPC, + OPCODE_XSR_DEPC, + OPCODE_RSR_EXCCAUSE, + OPCODE_WSR_EXCCAUSE, + OPCODE_XSR_EXCCAUSE, + OPCODE_RSR_PRID, + OPCODE_RSR_VECBASE, + OPCODE_WSR_VECBASE, + OPCODE_XSR_VECBASE, + OPCODE_MUL16U, + OPCODE_MUL16S, + OPCODE_RFI, + OPCODE_WAITI, + OPCODE_RSR_INTERRUPT, + OPCODE_WSR_INTSET, + OPCODE_WSR_INTCLEAR, + OPCODE_RSR_INTENABLE, + OPCODE_WSR_INTENABLE, + OPCODE_XSR_INTENABLE, + OPCODE_BREAK, + OPCODE_BREAK_N, + OPCODE_RSR_DBREAKA0, + OPCODE_WSR_DBREAKA0, + OPCODE_XSR_DBREAKA0, + OPCODE_RSR_DBREAKC0, + OPCODE_WSR_DBREAKC0, + OPCODE_XSR_DBREAKC0, + OPCODE_RSR_DBREAKA1, + OPCODE_WSR_DBREAKA1, + OPCODE_XSR_DBREAKA1, + OPCODE_RSR_DBREAKC1, + OPCODE_WSR_DBREAKC1, + OPCODE_XSR_DBREAKC1, + OPCODE_RSR_IBREAKA0, + OPCODE_WSR_IBREAKA0, + OPCODE_XSR_IBREAKA0, + OPCODE_RSR_IBREAKA1, + OPCODE_WSR_IBREAKA1, + OPCODE_XSR_IBREAKA1, + OPCODE_RSR_IBREAKENABLE, + OPCODE_WSR_IBREAKENABLE, + OPCODE_XSR_IBREAKENABLE, + OPCODE_RSR_DEBUGCAUSE, + OPCODE_WSR_DEBUGCAUSE, + OPCODE_XSR_DEBUGCAUSE, + OPCODE_RSR_ICOUNT, + OPCODE_WSR_ICOUNT, + OPCODE_XSR_ICOUNT, + OPCODE_RSR_ICOUNTLEVEL, + OPCODE_WSR_ICOUNTLEVEL, + OPCODE_XSR_ICOUNTLEVEL, + OPCODE_RSR_DDR, + OPCODE_WSR_DDR, + OPCODE_XSR_DDR, + OPCODE_RFDO, + OPCODE_RFDD, + OPCODE_WSR_MMID, + OPCODE_ANDB, + OPCODE_ANDBC, + OPCODE_ORB, + OPCODE_ORBC, + OPCODE_XORB, + OPCODE_ANY4, + OPCODE_ALL4, + OPCODE_ANY8, + OPCODE_ALL8, + OPCODE_BF, + OPCODE_BT, + OPCODE_MOVF, + OPCODE_MOVT, + OPCODE_RSR_BR, + OPCODE_WSR_BR, + OPCODE_XSR_BR, + OPCODE_RSR_CCOUNT, + OPCODE_WSR_CCOUNT, + OPCODE_XSR_CCOUNT, + OPCODE_RSR_CCOMPARE0, + OPCODE_WSR_CCOMPARE0, + OPCODE_XSR_CCOMPARE0, + OPCODE_RSR_CCOMPARE1, + OPCODE_WSR_CCOMPARE1, + OPCODE_XSR_CCOMPARE1, + OPCODE_IPF, + OPCODE_IHI, + OPCODE_IPFL, + OPCODE_IHU, + OPCODE_IIU, + OPCODE_III, + OPCODE_LICT, + OPCODE_LICW, + OPCODE_SICT, + OPCODE_SICW, + OPCODE_DHWB, + OPCODE_DHWBI, + OPCODE_DIWB, + OPCODE_DIWBI, + OPCODE_DHI, + OPCODE_DII, + OPCODE_DPFR, + OPCODE_DPFW, + OPCODE_DPFRO, + OPCODE_DPFWO, + OPCODE_DPFL, + OPCODE_DHU, + OPCODE_DIU, + OPCODE_SDCT, + OPCODE_LDCT, + OPCODE_IDTLB, + OPCODE_PDTLB, + OPCODE_RDTLB0, + OPCODE_RDTLB1, + OPCODE_WDTLB, + OPCODE_IITLB, + OPCODE_PITLB, + OPCODE_RITLB0, + OPCODE_RITLB1, + OPCODE_WITLB, + OPCODE_RSR_CPENABLE, + OPCODE_WSR_CPENABLE, + OPCODE_XSR_CPENABLE, + OPCODE_CLAMPS, + OPCODE_MIN, + OPCODE_MAX, + OPCODE_MINU, + OPCODE_MAXU, + OPCODE_NSA, + OPCODE_NSAU, + OPCODE_SEXT, + OPCODE_L32AI, + OPCODE_S32RI, + OPCODE_S32C1I, + OPCODE_RSR_SCOMPARE1, + OPCODE_WSR_SCOMPARE1, + OPCODE_XSR_SCOMPARE1, + OPCODE_RSR_ATOMCTL, + OPCODE_WSR_ATOMCTL, + OPCODE_XSR_ATOMCTL, + OPCODE_RER, + OPCODE_WER, + OPCODE_RUR_FCR, + OPCODE_WUR_FCR, + OPCODE_RUR_FSR, + OPCODE_WUR_FSR, + OPCODE_ADD_S, + OPCODE_SUB_S, + OPCODE_MUL_S, + OPCODE_MADD_S, + OPCODE_MSUB_S, + OPCODE_MOVF_S, + OPCODE_MOVT_S, + OPCODE_MOVEQZ_S, + OPCODE_MOVNEZ_S, + OPCODE_MOVLTZ_S, + OPCODE_MOVGEZ_S, + OPCODE_ABS_S, + OPCODE_MOV_S, + OPCODE_NEG_S, + OPCODE_UN_S, + OPCODE_OEQ_S, + OPCODE_UEQ_S, + OPCODE_OLT_S, + OPCODE_ULT_S, + OPCODE_OLE_S, + OPCODE_ULE_S, + OPCODE_FLOAT_S, + OPCODE_UFLOAT_S, + OPCODE_ROUND_S, + OPCODE_CEIL_S, + OPCODE_FLOOR_S, + OPCODE_TRUNC_S, + OPCODE_UTRUNC_S, + OPCODE_RFR, + OPCODE_WFR, + OPCODE_LSI, + OPCODE_LSIU, + OPCODE_LSX, + OPCODE_LSXU, + OPCODE_SSI, + OPCODE_SSIU, + OPCODE_SSX, + OPCODE_SSXU, + OPCODE_GET_ARGMAX, + OPCODE_GET_HSAR, + OPCODE_GET_HSAR2SAR, + OPCODE_GET_INTERP_EXT_N, + OPCODE_GET_INTERP_EXT_L, + OPCODE_GET_LLR_BUF, + OPCODE_GET_LLR_POS, + OPCODE_GET_MAX, + OPCODE_GET_NCO, + OPCODE_GET_PERM_REG, + OPCODE_GET_PHASOR_N, + OPCODE_GET_PHASOR_OFFSET, + OPCODE_GET_SAR, + OPCODE_GET_SCALE_REG, + OPCODE_GET_SMOD_BUF, + OPCODE_GET_SMOD_OFFSET_TABLE, + OPCODE_GET_SMOD_POS, + OPCODE_GET_SOV, + OPCODE_GET_WGHT, + OPCODE_SET_ARGMAX, + OPCODE_SET_EXT_REGS, + OPCODE_SET_HSAR, + OPCODE_SET_LLR_BUF, + OPCODE_SET_LLR_POS, + OPCODE_SET_MAX, + OPCODE_SET_NCO, + OPCODE_SET_PERM_REG, + OPCODE_SET_PHASOR_N, + OPCODE_SET_PHASOR_OFFSET, + OPCODE_SET_SAR, + OPCODE_SET_SCALE_REG, + OPCODE_SET_SMOD_BUF, + OPCODE_SET_SMOD_OFFSET_TABLE, + OPCODE_SET_SMOD_POS, + OPCODE_SET_SOV, + OPCODE_SET_WGHT, + OPCODE_LAC2X32, + OPCODE_LAC2X64_0, + OPCODE_LAC2X64_1, + OPCODE_LAC2X64_2, + OPCODE_LAC2X64_3, + OPCODE_LAC32_R, + OPCODE_LAC_IH, + OPCODE_LAC_IL, + OPCODE_LAC_RH, + OPCODE_LAC_RL, + OPCODE_LCM, + OPCODE_LCM_PINC, + OPCODE_LCM_PINC_X, + OPCODE_LCM_U, + OPCODE_LCM_X, + OPCODE_LCM_XU, + OPCODE_LP, + OPCODE_LP_X, + OPCODE_LQ, + OPCODE_LQ_X, + OPCODE_LUT0, + OPCODE_LUT1, + OPCODE_LUT2, + OPCODE_LUT3, + OPCODE_SAC2X32, + OPCODE_SAC2X64_0, + OPCODE_SAC2X64_1, + OPCODE_SAC2X64_2, + OPCODE_SAC2X64_3, + OPCODE_SAC32_R, + OPCODE_SAC_IH, + OPCODE_SAC_IL, + OPCODE_SAC_RH, + OPCODE_SAC_RL, + OPCODE_SCM, + OPCODE_SCM_PINC, + OPCODE_SCM_PINC_X, + OPCODE_SCM_U, + OPCODE_SCM_X, + OPCODE_SCM_XU, + OPCODE_STORE_P, + OPCODE_STORE_Q, + OPCODE_AR2CM_DUP, + OPCODE_AR2CM_LN, + OPCODE_AR2CM_LN_I, + OPCODE_AR2CM_LN_R, + OPCODE_AR2PQ_LN, + OPCODE_AR2SAR_DUP, + OPCODE_CLRAC, + OPCODE_CLRCM, + OPCODE_CM2AR_LN, + OPCODE_CM2AR_LN_I, + OPCODE_CM2AR_LN_R, + OPCODE_COMB_AR, + OPCODE_CONJ, + OPCODE_MOV2AC32_I, + OPCODE_MOV2AC32_R, + OPCODE_MOV2CM2PQ, + OPCODE_MOVAC, + OPCODE_MOVAC_I, + OPCODE_MOVAC_I2R, + OPCODE_MOVAC_R, + OPCODE_MOVAC_R2I, + OPCODE_MOVAR2, + OPCODE_MOVCM, + OPCODE_MOVCM2PQ, + OPCODE_MOVCND_0, + OPCODE_MOVCND_1, + OPCODE_MOVCND_2, + OPCODE_MOVCND_3, + OPCODE_MOVCND_4, + OPCODE_MOVCND_5, + OPCODE_MOVCND_6, + OPCODE_MOVCND_7, + OPCODE_MOVCND8_0, + OPCODE_MOVCND8_1, + OPCODE_MOVCND8_2, + OPCODE_MOVCND8_3, + OPCODE_MOVCND8_4, + OPCODE_MOVCND8_5, + OPCODE_MOVCND8_6, + OPCODE_MOVCND8_7, + OPCODE_MOV_I, + OPCODE_MOVPQ2PQ, + OPCODE_MOV_R, + OPCODE_NEGCM, + OPCODE_POP16LLR_1, + OPCODE_PQ2CM, + OPCODE_SWAPAC_R, + OPCODE_SWAPAC_RI, + OPCODE_SWAPB, + OPCODE_ADD2AC, + OPCODE_ADDAC, + OPCODE_CDOT, + OPCODE_CDOTAC, + OPCODE_CDOTACS, + OPCODE_CMAC, + OPCODE_CMACS, + OPCODE_CMPY, + OPCODE_CMPY2CM, + OPCODE_CMPY2PQ, + OPCODE_CMPYS, + OPCODE_CMPYXP2PQ, + OPCODE_COMB32, + OPCODE_DOT, + OPCODE_DOTAC, + OPCODE_DOTACS, + OPCODE_LIN_INT, + OPCODE_LLRPRE1, + OPCODE_LLRPRE2, + OPCODE_MAC, + OPCODE_MAC8, + OPCODE_MACD8, + OPCODE_MACPQXP_0, + OPCODE_MACPQXP_1, + OPCODE_MACPQXP_2, + OPCODE_MACPQXP_3, + OPCODE_MACS, + OPCODE_MACXP2_0, + OPCODE_MACXP2_1, + OPCODE_MACXP_0, + OPCODE_MACXP_1, + OPCODE_MACXP_2, + OPCODE_MACXP_3, + OPCODE_MOV2AC, + OPCODE_MPY, + OPCODE_MPY2CM, + OPCODE_MPY2PQ, + OPCODE_MPY8, + OPCODE_MPYADD8_2CM, + OPCODE_MPYD8, + OPCODE_MPYPQXP_0, + OPCODE_MPYPQXP_1, + OPCODE_MPYPQXP_2, + OPCODE_MPYPQXP_3, + OPCODE_MPYS, + OPCODE_MPYXP2PQ, + OPCODE_MPYXP2_0, + OPCODE_MPYXP2_1, + OPCODE_MPYXP_0, + OPCODE_MPYXP_1, + OPCODE_MPYXP_2, + OPCODE_MPYXP_3, + OPCODE_NORMACD, + OPCODE_NORMACPQ_I, + OPCODE_NORMACPQ_R, + OPCODE_NORMD, + OPCODE_NORMPYPQ_I, + OPCODE_NORMPYPQ_R, + OPCODE_RCMAC, + OPCODE_RCMPY, + OPCODE_RCMPY2CM, + OPCODE_RFIR, + OPCODE_RFIRA, + OPCODE_RFIRD, + OPCODE_RFIRDA, + OPCODE_RMAC, + OPCODE_RMPY, + OPCODE_RMPY2CM, + OPCODE_SMOD_ALIGN, + OPCODE_SMOD_SCR, + OPCODE_SUB2AC, + OPCODE_WGHT32, + OPCODE_CLRTIEP, + OPCODE_EXT_2FIFO_0, + OPCODE_EXT_2FIFO_1, + OPCODE_EXT_2FIFO_2, + OPCODE_EXT_2FIFO_3, + OPCODE_EXT_R2FIFO_0, + OPCODE_EXT_R2FIFO_1, + OPCODE_EXT_R2FIFO_2, + OPCODE_EXT_R2FIFO_3, + OPCODE_LUT, + OPCODE_LUT_AR, + OPCODE_LUT_IEXT, + OPCODE_LUT_PHASOR, + OPCODE_LUT_REXT, + OPCODE_LUT_WRITE, + OPCODE_MOVEQ128_0, + OPCODE_MOVEQ128_1, + OPCODE_MOVEQ128_2, + OPCODE_MOVEQ128_3, + OPCODE_MOVEQ128_4, + OPCODE_MOVEQ128_5, + OPCODE_MOVEQ32_0, + OPCODE_MOVEQ32_1, + OPCODE_MOVEQ32_2, + OPCODE_MOVEQ32_3, + OPCODE_NCO_UPDATE, + OPCODE_POP128_0, + OPCODE_POP128_1, + OPCODE_POP128_2, + OPCODE_POP128_3, + OPCODE_POP128_4, + OPCODE_POP128_5, + OPCODE_POP128_2CMPQ_0, + OPCODE_POP128_2CMPQ_1, + OPCODE_POP128_2CMPQ_2, + OPCODE_POP128_2CMPQ_3, + OPCODE_POP128_2M_0, + OPCODE_POP128_2M_1, + OPCODE_POP128_2M_2, + OPCODE_POP128_2M_3, + OPCODE_POP128_2PQ_0, + OPCODE_POP128_2PQ_1, + OPCODE_POP128_2PQ_2, + OPCODE_POP128_2PQ_3, + OPCODE_POP128_2PQ_4, + OPCODE_POP128_2PQ_5, + OPCODE_POP2X128_2PQ_01, + OPCODE_POP2X128_2PQ_03, + OPCODE_POP2X128_2PQ_21, + OPCODE_POP2X128_2PQ_23, + OPCODE_POP32_0, + OPCODE_POP32_1, + OPCODE_POP32_2, + OPCODE_POP32_3, + OPCODE_PUSH128, + OPCODE_PUSH128_M, + OPCODE_PUSH128_PQ, + OPCODE_PUSH2X128_PQ, + OPCODE_PUSH32, + OPCODE_QREADY, + OPCODE_RDTIEP, + OPCODE_SETTIEP, + OPCODE_SMOD_LUT, + OPCODE_WRTBSIGQ, + OPCODE_WRTBSIGQM, + OPCODE_WRTIEP, + OPCODE_WRTSIGQ, + OPCODE_ABS8, + OPCODE_ADD16, + OPCODE_ADD32, + OPCODE_ADDAC_I2R, + OPCODE_ADDAC_R2I, + OPCODE_ADDAR2, + OPCODE_ADDCM, + OPCODE_ADDWRP, + OPCODE_AND128, + OPCODE_ARGMAX8, + OPCODE_ASL, + OPCODE_ASL32, + OPCODE_ASLACM, + OPCODE_ASLM, + OPCODE_ASLM32, + OPCODE_ASR, + OPCODE_ASR32, + OPCODE_ASRAC, + OPCODE_ASRM, + OPCODE_BITFEXT, + OPCODE_BITFINS, + OPCODE_CLB_C, + OPCODE_CLB_R, + OPCODE_CMP8, + OPCODE_CMP_I, + OPCODE_CMP_R, + OPCODE_EXT, + OPCODE_EXT_R, + OPCODE_EXT32_I, + OPCODE_EXT32_R, + OPCODE_EXTUI4, + OPCODE_LSLM, + OPCODE_LSRM, + OPCODE_MAX8, + OPCODE_MEAN, + OPCODE_MEAN32, + OPCODE_MIN8, + OPCODE_MINCLB_C, + OPCODE_MINCLB_R, + OPCODE_NOT128, + OPCODE_OR128, + OPCODE_PERM, + OPCODE_REDAC, + OPCODE_REDAC2, + OPCODE_REDAC4, + OPCODE_REDACS, + OPCODE_SMINCLB_C, + OPCODE_SMINCLB_R, + OPCODE_STSWAPBM, + OPCODE_STSWAPBMU, + OPCODE_SUB32, + OPCODE_SUBAC_I2R, + OPCODE_SUBAC_R2I, + OPCODE_SUBARX, + OPCODE_SUBCM, + OPCODE_SUBMEAN, + OPCODE_SUBWRP, + OPCODE_TRANS, + OPCODE_XOR128, + OPCODE_RUR_EXPSTATE, + OPCODE_WUR_EXPSTATE, + OPCODE_RUR_SOV, + OPCODE_WUR_SOV, + OPCODE_RUR_SAT_MODE, + OPCODE_WUR_SAT_MODE, + OPCODE_RUR_SAR0, + OPCODE_WUR_SAR0, + OPCODE_RUR_SAR1, + OPCODE_WUR_SAR1, + OPCODE_RUR_SAR2, + OPCODE_WUR_SAR2, + OPCODE_RUR_SAR3, + OPCODE_WUR_SAR3, + OPCODE_RUR_HSAR0, + OPCODE_WUR_HSAR0, + OPCODE_RUR_HSAR1, + OPCODE_WUR_HSAR1, + OPCODE_RUR_HSAR2, + OPCODE_WUR_HSAR2, + OPCODE_RUR_HSAR3, + OPCODE_WUR_HSAR3, + OPCODE_RUR_MAX_REG_0, + OPCODE_WUR_MAX_REG_0, + OPCODE_RUR_MAX_REG_1, + OPCODE_WUR_MAX_REG_1, + OPCODE_RUR_MAX_REG_2, + OPCODE_WUR_MAX_REG_2, + OPCODE_RUR_MAX_REG_3, + OPCODE_WUR_MAX_REG_3, + OPCODE_RUR_ARG_MAX_REG_0, + OPCODE_WUR_ARG_MAX_REG_0, + OPCODE_RUR_ARG_MAX_REG_1, + OPCODE_WUR_ARG_MAX_REG_1, + OPCODE_RUR_ARG_MAX_REG_2, + OPCODE_WUR_ARG_MAX_REG_2, + OPCODE_RUR_ARG_MAX_REG_3, + OPCODE_WUR_ARG_MAX_REG_3, + OPCODE_RUR_NCO_COUNTER_0, + OPCODE_WUR_NCO_COUNTER_0, + OPCODE_RUR_NCO_COUNTER_1, + OPCODE_WUR_NCO_COUNTER_1, + OPCODE_RUR_NCO_COUNTER_2, + OPCODE_WUR_NCO_COUNTER_2, + OPCODE_RUR_NCO_COUNTER_3, + OPCODE_WUR_NCO_COUNTER_3, + OPCODE_RUR_INTERP_EXT_N, + OPCODE_WUR_INTERP_EXT_N, + OPCODE_RUR_INTERP_EXT_L, + OPCODE_WUR_INTERP_EXT_L, + OPCODE_RUR_LLR_BUF_0, + OPCODE_WUR_LLR_BUF_0, + OPCODE_RUR_LLR_BUF_1, + OPCODE_WUR_LLR_BUF_1, + OPCODE_RUR_LLR_BUF_2, + OPCODE_WUR_LLR_BUF_2, + OPCODE_RUR_LLR_BUF_3, + OPCODE_WUR_LLR_BUF_3, + OPCODE_RUR_LLR_BUF_4, + OPCODE_WUR_LLR_BUF_4, + OPCODE_RUR_LLR_BUF_5, + OPCODE_WUR_LLR_BUF_5, + OPCODE_RUR_LLR_BUF_6, + OPCODE_WUR_LLR_BUF_6, + OPCODE_RUR_LLR_BUF_7, + OPCODE_WUR_LLR_BUF_7, + OPCODE_RUR_LLR_BUF_8, + OPCODE_WUR_LLR_BUF_8, + OPCODE_RUR_LLR_BUF_9, + OPCODE_WUR_LLR_BUF_9, + OPCODE_RUR_LLR_BUF_10, + OPCODE_WUR_LLR_BUF_10, + OPCODE_RUR_LLR_BUF_11, + OPCODE_WUR_LLR_BUF_11, + OPCODE_RUR_LLR_BUF_12, + OPCODE_WUR_LLR_BUF_12, + OPCODE_RUR_LLR_BUF_13, + OPCODE_WUR_LLR_BUF_13, + OPCODE_RUR_LLR_BUF_14, + OPCODE_WUR_LLR_BUF_14, + OPCODE_RUR_LLR_BUF_15, + OPCODE_WUR_LLR_BUF_15, + OPCODE_RUR_LLR_BUF_16, + OPCODE_WUR_LLR_BUF_16, + OPCODE_RUR_LLR_BUF_17, + OPCODE_WUR_LLR_BUF_17, + OPCODE_RUR_LLR_BUF_18, + OPCODE_WUR_LLR_BUF_18, + OPCODE_RUR_LLR_BUF_19, + OPCODE_WUR_LLR_BUF_19, + OPCODE_RUR_LLR_BUF_20, + OPCODE_WUR_LLR_BUF_20, + OPCODE_RUR_LLR_BUF_21, + OPCODE_WUR_LLR_BUF_21, + OPCODE_RUR_LLR_BUF_22, + OPCODE_WUR_LLR_BUF_22, + OPCODE_RUR_LLR_BUF_23, + OPCODE_WUR_LLR_BUF_23, + OPCODE_RUR_SMOD_BUF_0, + OPCODE_WUR_SMOD_BUF_0, + OPCODE_RUR_SMOD_BUF_1, + OPCODE_WUR_SMOD_BUF_1, + OPCODE_RUR_SMOD_BUF_2, + OPCODE_WUR_SMOD_BUF_2, + OPCODE_RUR_SMOD_BUF_3, + OPCODE_WUR_SMOD_BUF_3, + OPCODE_RUR_SMOD_BUF_4, + OPCODE_WUR_SMOD_BUF_4, + OPCODE_RUR_SMOD_BUF_5, + OPCODE_WUR_SMOD_BUF_5, + OPCODE_RUR_SMOD_BUF_6, + OPCODE_WUR_SMOD_BUF_6, + OPCODE_RUR_SMOD_BUF_7, + OPCODE_WUR_SMOD_BUF_7, + OPCODE_RUR_WEIGHT_REG, + OPCODE_WUR_WEIGHT_REG, + OPCODE_RUR_SCALE_REG, + OPCODE_WUR_SCALE_REG, + OPCODE_RUR_LLR_POS, + OPCODE_WUR_LLR_POS, + OPCODE_RUR_SMOD_POS, + OPCODE_WUR_SMOD_POS, + OPCODE_RUR_PERM_REG, + OPCODE_WUR_PERM_REG, + OPCODE_RUR_SMOD_OFFSET_TABLE_0, + OPCODE_WUR_SMOD_OFFSET_TABLE_0, + OPCODE_RUR_SMOD_OFFSET_TABLE_1, + OPCODE_WUR_SMOD_OFFSET_TABLE_1, + OPCODE_RUR_SMOD_OFFSET_TABLE_2, + OPCODE_WUR_SMOD_OFFSET_TABLE_2, + OPCODE_RUR_SMOD_OFFSET_TABLE_3, + OPCODE_WUR_SMOD_OFFSET_TABLE_3, + OPCODE_RUR_PHASOR_N, + OPCODE_WUR_PHASOR_N, + OPCODE_RUR_PHASOR_OFFSET, + OPCODE_WUR_PHASOR_OFFSET +}; + + +/* Slot-specific opcode decode functions. */ + +static int +Slot_inst_decode (const xtensa_insnbuf insn) +{ + switch (Field_dsp340050b49a6c_fld2021_Slot_inst_get (insn)) + { + case 3: + if (Field_sa4_Slot_inst_get (insn) == 0 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 4 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_LCM_PINC_X; + if (Field_sa4_Slot_inst_get (insn) == 1 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 4 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SCM_PINC_X; + break; + case 4: + if (Field_sa4_Slot_inst_get (insn) == 0 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 4 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_LCM_X; + if (Field_sa4_Slot_inst_get (insn) == 1 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 4 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SCM_X; + break; + case 5: + if (Field_sa4_Slot_inst_get (insn) == 0 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 4 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_LCM_XU; + if (Field_sa4_Slot_inst_get (insn) == 1 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 4 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SCM_XU; + break; + case 6: + if (Field_sa4_Slot_inst_get (insn) == 0 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 4 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_LP_X; + break; + case 7: + if (Field_sa4_Slot_inst_get (insn) == 0 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 4 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_LQ_X; + break; + } + if (Field_dsp340050b49a6c_fld2035_Slot_inst_get (insn) == 2 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2047_Slot_inst_get (insn) == 0) + return OPCODE_LQ; + switch (Field_dsp340050b49a6c_fld2037_Slot_inst_get (insn)) + { + case 0: + if (Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_LCM_PINC; + break; + case 1: + if (Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_LCM_U; + break; + case 2: + if (Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_LP; + break; + } + switch (Field_dsp340050b49a6c_fld2048_Slot_inst_get (insn)) + { + case 0: + if (Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_LAC2X32; + break; + case 1: + if (Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_LAC32_R; + break; + } + if (Field_dsp340050b49a6c_fld2082inst_Slot_inst_get (insn) == 0 && + Field_r2_Slot_inst_get (insn) == 1 && + Field_bbi4_Slot_inst_get (insn) == 0 && + Field_op0_Slot_inst_get (insn) == 3) + return OPCODE_LAC_IH; + if (Field_dsp340050b49a6c_fld2083inst_Slot_inst_get (insn) == 1 && + Field_r2_Slot_inst_get (insn) == 1 && + Field_bbi4_Slot_inst_get (insn) == 0 && + Field_op0_Slot_inst_get (insn) == 3) + return OPCODE_LAC_IL; + if (Field_dsp340050b49a6c_fld2084inst_Slot_inst_get (insn) == 2 && + Field_r2_Slot_inst_get (insn) == 1 && + Field_bbi4_Slot_inst_get (insn) == 0 && + Field_op0_Slot_inst_get (insn) == 3) + return OPCODE_LAC_RH; + switch (Field_dsp340050b49a6c_fld2085inst_Slot_inst_get (insn)) + { + case 3: + if (Field_r2_Slot_inst_get (insn) == 1 && + Field_bbi4_Slot_inst_get (insn) == 0 && + Field_op0_Slot_inst_get (insn) == 3) + return OPCODE_LAC2X64_1; + break; + case 19: + if (Field_r2_Slot_inst_get (insn) == 1 && + Field_bbi4_Slot_inst_get (insn) == 0 && + Field_op0_Slot_inst_get (insn) == 3) + return OPCODE_LAC2X64_2; + break; + } + if (Field_dsp340050b49a6c_fld2086inst_Slot_inst_get (insn) == 2 && + Field_r2_Slot_inst_get (insn) == 1 && + Field_bbi4_Slot_inst_get (insn) == 0 && + Field_op0_Slot_inst_get (insn) == 3 && + Field_dsp340050b49a6c_fld3634_Slot_inst_get (insn) == 0) + return OPCODE_LAC_RL; + if (Field_dsp340050b49a6c_fld2088inst_Slot_inst_get (insn) == 3 && + Field_r2_Slot_inst_get (insn) == 1 && + Field_bbi4_Slot_inst_get (insn) == 0 && + Field_op0_Slot_inst_get (insn) == 3 && + Field_dsp340050b49a6c_fld3633inst_Slot_inst_get (insn) == 0) + return OPCODE_LAC2X64_3; + if (Field_dsp340050b49a6c_fld2089inst_Slot_inst_get (insn) == 1 && + Field_r2_Slot_inst_get (insn) == 1 && + Field_bbi4_Slot_inst_get (insn) == 0 && + Field_op0_Slot_inst_get (insn) == 3 && + Field_dsp340050b49a6c_fld3631inst_Slot_inst_get (insn) == 0) + return OPCODE_LAC2X64_0; + if (Field_dsp340050b49a6c_fld2090inst_Slot_inst_get (insn) == 1 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_PQ2CM; + if (Field_dsp340050b49a6c_fld2091inst_Slot_inst_get (insn) == 10 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_AR2CM_DUP; + if (Field_dsp340050b49a6c_fld2092inst_Slot_inst_get (insn) == 88 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_CLRTIEP; + if (Field_dsp340050b49a6c_fld2094inst_Slot_inst_get (insn) == 89 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_GET_SMOD_BUF; + if (Field_dsp340050b49a6c_fld2095inst_Slot_inst_get (insn) == 90 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SETTIEP; + if (Field_dsp340050b49a6c_fld2096inst_Slot_inst_get (insn) == 182 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_CLRCM; + if (Field_dsp340050b49a6c_fld2098inst_Slot_inst_get (insn) == 183 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_GET_ARGMAX; + if (Field_dsp340050b49a6c_fld2099inst_Slot_inst_get (insn) == 92 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_WRTBSIGQM; + if (Field_dsp340050b49a6c_fld2100inst_Slot_inst_get (insn) == 186 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_GET_HSAR; + if (Field_dsp340050b49a6c_fld2101inst_Slot_inst_get (insn) == 187 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_GET_MAX; + if (Field_dsp340050b49a6c_fld2102inst_Slot_inst_get (insn) == 188 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_GET_HSAR2SAR; + if (Field_dsp340050b49a6c_fld2103inst_Slot_inst_get (insn) == 189 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_GET_NCO; + if (Field_dsp340050b49a6c_fld2104inst_Slot_inst_get (insn) == 190 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_GET_SAR; + if (Field_dsp340050b49a6c_fld2105inst_Slot_inst_get (insn) == 191 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_GET_SMOD_OFFSET_TABLE; + if (Field_dsp340050b49a6c_fld2106inst_Slot_inst_get (insn) == 18 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_PUSH128_PQ; + if (Field_dsp340050b49a6c_fld2107inst_Slot_inst_get (insn) == 152 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_POP128_2PQ_0; + if (Field_dsp340050b49a6c_fld2108inst_Slot_inst_get (insn) == 153 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_POP128_2PQ_2; + if (Field_dsp340050b49a6c_fld2109inst_Slot_inst_get (insn) == 154 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_POP128_2PQ_3; + if (Field_dsp340050b49a6c_fld2110inst_Slot_inst_get (insn) == 155 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_POP128_2PQ_5; + if (Field_dsp340050b49a6c_fld2111inst_Slot_inst_get (insn) == 156 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_POP128_2PQ_4; + if (Field_dsp340050b49a6c_fld2112inst_Slot_inst_get (insn) == 301 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SET_LLR_POS; + if (Field_dsp340050b49a6c_fld2113inst_Slot_inst_get (insn) == 317 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SET_PHASOR_OFFSET; + if (Field_dsp340050b49a6c_fld2114inst_Slot_inst_get (insn) == 302 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SET_PHASOR_N; + if (Field_dsp340050b49a6c_fld2115inst_Slot_inst_get (insn) == 303 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SET_SCALE_REG; + if (Field_dsp340050b49a6c_fld2116inst_Slot_inst_get (insn) == 318 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SET_SMOD_POS; + if (Field_dsp340050b49a6c_fld2117inst_Slot_inst_get (insn) == 319 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SET_SOV; + if (Field_dsp340050b49a6c_fld2118inst_Slot_inst_get (insn) == 208 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_POP128_2PQ_1; + if (Field_dsp340050b49a6c_fld2119inst_Slot_inst_get (insn) == 417 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SET_WGHT; + if (Field_dsp340050b49a6c_fld2120inst_Slot_inst_get (insn) == 6913 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_MOVEQ128_0; + if (Field_dsp340050b49a6c_fld2122inst_Slot_inst_get (insn) == 6929 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_MOVEQ128_1; + if (Field_dsp340050b49a6c_fld2123inst_Slot_inst_get (insn) == 6945 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_MOVEQ128_2; + if (Field_dsp340050b49a6c_fld2124inst_Slot_inst_get (insn) == 6961 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_MOVEQ128_5; + if (Field_dsp340050b49a6c_fld2125inst_Slot_inst_get (insn) == 6977 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_MOVEQ128_3; + if (Field_dsp340050b49a6c_fld2126inst_Slot_inst_get (insn) == 6993 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_MOVEQ32_0; + if (Field_dsp340050b49a6c_fld2127inst_Slot_inst_get (insn) == 7009 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_MOVEQ32_1; + if (Field_dsp340050b49a6c_fld2128inst_Slot_inst_get (insn) == 7025 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_MOVEQ32_2; + if (Field_dsp340050b49a6c_fld2129inst_Slot_inst_get (insn) == 1761 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2035_Slot_inst_get (insn) == 0) + return OPCODE_MOVEQ128_4; + if (Field_dsp340050b49a6c_fld2131inst_Slot_inst_get (insn) == 1777 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2035_Slot_inst_get (insn) == 0) + return OPCODE_MOVEQ32_3; + if (Field_dsp340050b49a6c_fld2132inst_Slot_inst_get (insn) == 105 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3659inst_Slot_inst_get (insn) == 0) + return OPCODE_WRTBSIGQ; + if (Field_dsp340050b49a6c_fld2133inst_Slot_inst_get (insn) == 53 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3660inst_Slot_inst_get (insn) == 0) + return OPCODE_WRTSIGQ; + if (Field_dsp340050b49a6c_fld2134inst_Slot_inst_get (insn) == 53 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2050_Slot_inst_get (insn) == 0) + return OPCODE_CLRAC; + if (Field_dsp340050b49a6c_fld2136inst_Slot_inst_get (insn) == 55 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2050_Slot_inst_get (insn) == 0) + return OPCODE_POP16LLR_1; + if (Field_dsp340050b49a6c_fld2137inst_Slot_inst_get (insn) == 34 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_WRTIEP; + if (Field_dsp340050b49a6c_fld2138inst_Slot_inst_get (insn) == 560 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_POP128_0; + if (Field_dsp340050b49a6c_fld2139inst_Slot_inst_get (insn) == 561 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_POP128_3; + if (Field_dsp340050b49a6c_fld2140inst_Slot_inst_get (insn) == 562 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_POP128_4; + if (Field_dsp340050b49a6c_fld2141inst_Slot_inst_get (insn) == 563 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_POP2X128_2PQ_03; + if (Field_dsp340050b49a6c_fld2142inst_Slot_inst_get (insn) == 564 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_POP128_5; + if (Field_dsp340050b49a6c_fld2143inst_Slot_inst_get (insn) == 565 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_POP2X128_2PQ_21; + if (Field_dsp340050b49a6c_fld2144inst_Slot_inst_get (insn) == 283 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2047_Slot_inst_get (insn) == 0) + return OPCODE_POP2X128_2PQ_23; + if (Field_dsp340050b49a6c_fld2145inst_Slot_inst_get (insn) == 71 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2037_Slot_inst_get (insn) == 0) + return OPCODE_POP2X128_2PQ_01; + if (Field_dsp340050b49a6c_fld2146inst_Slot_inst_get (insn) == 21 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3649inst_Slot_inst_get (insn) == 0) + return OPCODE_POP128_1; + if (Field_dsp340050b49a6c_fld2147inst_Slot_inst_get (insn) == 13 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3650inst_Slot_inst_get (insn) == 0) + return OPCODE_POP128_2; + if (Field_dsp340050b49a6c_fld2149inst_Slot_inst_get (insn) == 5 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3627inst_Slot_inst_get (insn) == 0) + return OPCODE_GET_LLR_BUF; + if (Field_dsp340050b49a6c_fld2151inst_Slot_inst_get (insn) == 5 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3657inst_Slot_inst_get (insn) == 0) + return OPCODE_PUSH2X128_PQ; + if (Field_dsp340050b49a6c_fld2153inst_Slot_inst_get (insn) == 1 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3635inst_Slot_inst_get (insn) == 0) + return OPCODE_AR2CM_LN; + if (Field_dsp340050b49a6c_fld2154inst_Slot_inst_get (insn) == 3 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3636inst_Slot_inst_get (insn) == 0) + return OPCODE_AR2CM_LN_I; + if (Field_dsp340050b49a6c_fld2155inst_Slot_inst_get (insn) == 3 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3637inst_Slot_inst_get (insn) == 0) + return OPCODE_AR2CM_LN_R; + if (Field_dsp340050b49a6c_fld2156inst_Slot_inst_get (insn) == 3 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_LCM; + if (Field_dsp340050b49a6c_fld2157inst_Slot_inst_get (insn) == 19 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_CONJ; + if (Field_dsp340050b49a6c_fld2158inst_Slot_inst_get (insn) == 27 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_MOVCM; + if (Field_dsp340050b49a6c_fld2159inst_Slot_inst_get (insn) == 51 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_MOV_I; + if (Field_dsp340050b49a6c_fld2160inst_Slot_inst_get (insn) == 59 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SET_EXT_REGS; + if (Field_dsp340050b49a6c_fld2161inst_Slot_inst_get (insn) == 83 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_MOV_R; + if (Field_dsp340050b49a6c_fld2162inst_Slot_inst_get (insn) == 171 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_ASRAC; + if (Field_dsp340050b49a6c_fld2163inst_Slot_inst_get (insn) == 187 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_CLB_R; + if (Field_dsp340050b49a6c_fld2164inst_Slot_inst_get (insn) == 227 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_CLB_C; + if (Field_dsp340050b49a6c_fld2165inst_Slot_inst_get (insn) == 235 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_MINCLB_C; + if (Field_dsp340050b49a6c_fld2166inst_Slot_inst_get (insn) == 243 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_MINCLB_R; + if (Field_dsp340050b49a6c_fld2167inst_Slot_inst_get (insn) == 251 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SMINCLB_C; + if (Field_dsp340050b49a6c_fld2168inst_Slot_inst_get (insn) == 147 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_NEGCM; + if (Field_dsp340050b49a6c_fld2169inst_Slot_inst_get (insn) == 310 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_PUSH128; + if (Field_dsp340050b49a6c_fld2171inst_Slot_inst_get (insn) == 599 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_MOVAC; + if (Field_dsp340050b49a6c_fld2172inst_Slot_inst_get (insn) == 631 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_MOVAC_I2R; + if (Field_dsp340050b49a6c_fld2173inst_Slot_inst_get (insn) == 358 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SET_LLR_BUF; + if (Field_dsp340050b49a6c_fld2174inst_Slot_inst_get (insn) == 711 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_MOVAC_R2I; + if (Field_dsp340050b49a6c_fld2175inst_Slot_inst_get (insn) == 5944 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_ADDAC_I2R; + if (Field_dsp340050b49a6c_fld2177inst_Slot_inst_get (insn) == 5945 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_ADDAC_R2I; + if (Field_dsp340050b49a6c_fld2178inst_Slot_inst_get (insn) == 5946 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_REDAC; + if (Field_dsp340050b49a6c_fld2179inst_Slot_inst_get (insn) == 5947 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_REDAC4; + if (Field_dsp340050b49a6c_fld2180inst_Slot_inst_get (insn) == 5948 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_REDAC2; + if (Field_dsp340050b49a6c_fld2181inst_Slot_inst_get (insn) == 5949 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_REDACS; + if (Field_dsp340050b49a6c_fld2182inst_Slot_inst_get (insn) == 5950 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SUBAC_I2R; + if (Field_dsp340050b49a6c_fld2183inst_Slot_inst_get (insn) == 5951 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SUBAC_R2I; + if (Field_dsp340050b49a6c_fld2184inst_Slot_inst_get (insn) == 374 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3642inst_Slot_inst_get (insn) == 0) + return OPCODE_SWAPAC_RI; + if (Field_dsp340050b49a6c_fld2185inst_Slot_inst_get (insn) == 3000 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_GET_INTERP_EXT_L; + if (Field_dsp340050b49a6c_fld2186inst_Slot_inst_get (insn) == 3001 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_GET_INTERP_EXT_N; + if (Field_dsp340050b49a6c_fld2187inst_Slot_inst_get (insn) == 3002 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_GET_LLR_POS; + if (Field_dsp340050b49a6c_fld2188inst_Slot_inst_get (insn) == 3003 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_GET_PHASOR_OFFSET; + if (Field_dsp340050b49a6c_fld2189inst_Slot_inst_get (insn) == 3004 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_GET_PHASOR_N; + if (Field_dsp340050b49a6c_fld2190inst_Slot_inst_get (insn) == 3005 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_GET_SCALE_REG; + if (Field_dsp340050b49a6c_fld2191inst_Slot_inst_get (insn) == 3006 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_GET_SMOD_POS; + if (Field_dsp340050b49a6c_fld2192inst_Slot_inst_get (insn) == 3007 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_GET_SOV; + if (Field_dsp340050b49a6c_fld2193inst_Slot_inst_get (insn) == 211 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3662inst_Slot_inst_get (insn) == 0) + return OPCODE_SMINCLB_R; + if (Field_dsp340050b49a6c_fld2194inst_Slot_inst_get (insn) == 3504 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_GET_WGHT; + if (Field_dsp340050b49a6c_fld2195inst_Slot_inst_get (insn) == 3505 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_POP32_1; + if (Field_dsp340050b49a6c_fld2196inst_Slot_inst_get (insn) == 3506 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_POP32_2; + if (Field_dsp340050b49a6c_fld2197inst_Slot_inst_get (insn) == 3507 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SET_ARGMAX; + if (Field_dsp340050b49a6c_fld2198inst_Slot_inst_get (insn) == 3508 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_POP32_3; + if (Field_dsp340050b49a6c_fld2199inst_Slot_inst_get (insn) == 3509 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SET_MAX; + if (Field_dsp340050b49a6c_fld2200inst_Slot_inst_get (insn) == 3510 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SET_NCO; + if (Field_dsp340050b49a6c_fld2201inst_Slot_inst_get (insn) == 3511 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SET_SAR; + if (Field_dsp340050b49a6c_fld2202inst_Slot_inst_get (insn) == 878 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2254_Slot_inst_get (insn) == 0) + return OPCODE_RDTIEP; + if (Field_dsp340050b49a6c_fld2203inst_Slot_inst_get (insn) == 879 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2254_Slot_inst_get (insn) == 0) + return OPCODE_SET_SMOD_OFFSET_TABLE; + if (Field_dsp340050b49a6c_fld2204inst_Slot_inst_get (insn) == 123 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3656inst_Slot_inst_get (insn) == 0) + return OPCODE_POP32_0; + if (Field_dsp340050b49a6c_fld2205inst_Slot_inst_get (insn) == 3 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_MOVCM2PQ; + if (Field_dsp340050b49a6c_fld2206inst_Slot_inst_get (insn) == 7 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_QREADY; + if (Field_dsp340050b49a6c_fld2207inst_Slot_inst_get (insn) == 19 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_EXT32_I; + if (Field_dsp340050b49a6c_fld2208inst_Slot_inst_get (insn) == 23 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_EXT_2FIFO_2; + if (Field_dsp340050b49a6c_fld2209inst_Slot_inst_get (insn) == 27 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_EXT_2FIFO_3; + if (Field_dsp340050b49a6c_fld2210inst_Slot_inst_get (insn) == 31 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_EXT_R2FIFO_0; + if (Field_dsp340050b49a6c_fld2211inst_Slot_inst_get (insn) == 35 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_EXT32_R; + if (Field_dsp340050b49a6c_fld2212inst_Slot_inst_get (insn) == 39 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_EXT_R2FIFO_1; + if (Field_dsp340050b49a6c_fld2213inst_Slot_inst_get (insn) == 23 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3647inst_Slot_inst_get (insn) == 0) + return OPCODE_EXT_R2FIFO_2; + if (Field_dsp340050b49a6c_fld2214inst_Slot_inst_get (insn) == 27 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3648inst_Slot_inst_get (insn) == 0) + return OPCODE_EXT_R2FIFO_3; + if (Field_dsp340050b49a6c_fld2215inst_Slot_inst_get (insn) == 31 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3630inst_Slot_inst_get (insn) == 0) + return OPCODE_SET_SMOD_BUF; + if (Field_dsp340050b49a6c_fld2216inst_Slot_inst_get (insn) == 7 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3644inst_Slot_inst_get (insn) == 0) + return OPCODE_EXT_2FIFO_0; + if (Field_dsp340050b49a6c_fld2217inst_Slot_inst_get (insn) == 7 && + Field_sae4_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 3 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3645inst_Slot_inst_get (insn) == 0) + return OPCODE_EXT_2FIFO_1; + if (Field_dsp340050b49a6c_fld2218inst_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2021_Slot_inst_get (insn) == 6 && + Field_sa4_Slot_inst_get (insn) == 1 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 4 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_EXT; + if (Field_dsp340050b49a6c_fld2219inst_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2021_Slot_inst_get (insn) == 6 && + Field_sa4_Slot_inst_get (insn) == 1 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 4 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_EXT_R; + if (Field_dsp340050b49a6c_fld2220inst_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2021_Slot_inst_get (insn) == 7 && + Field_sa4_Slot_inst_get (insn) == 1 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 4 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_PUSH128_M; + if (Field_dsp340050b49a6c_fld2221inst_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2021_Slot_inst_get (insn) == 7 && + Field_sa4_Slot_inst_get (insn) == 1 && + Field_sae4_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 4 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SAC2X64_0; + if (Field_dsp340050b49a6c_fld2222inst_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SAC2X32; + if (Field_dsp340050b49a6c_fld2223inst_Slot_inst_get (insn) == 1 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SAC32_R; + if (Field_dsp340050b49a6c_fld2224inst_Slot_inst_get (insn) == 2 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SCM_PINC; + if (Field_dsp340050b49a6c_fld2225inst_Slot_inst_get (insn) == 5 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_LUT0; + if (Field_dsp340050b49a6c_fld2226inst_Slot_inst_get (insn) == 7 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_LUT1; + if (Field_dsp340050b49a6c_fld2227inst_Slot_inst_get (insn) == 4 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SCM_U; + if (Field_dsp340050b49a6c_fld2228inst_Slot_inst_get (insn) == 9 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_LUT2; + if (Field_dsp340050b49a6c_fld2229inst_Slot_inst_get (insn) == 11 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SCM; + if (Field_dsp340050b49a6c_fld2230inst_Slot_inst_get (insn) == 12 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_LUT3; + if (Field_dsp340050b49a6c_fld2231inst_Slot_inst_get (insn) == 14 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_STORE_P; + if (Field_dsp340050b49a6c_fld2232inst_Slot_inst_get (insn) == 14 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SAC_IH; + if (Field_dsp340050b49a6c_fld2234inst_Slot_inst_get (insn) == 15 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SAC_IL; + if (Field_dsp340050b49a6c_fld2235inst_Slot_inst_get (insn) == 16 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_COMB_AR; + if (Field_dsp340050b49a6c_fld2236inst_Slot_inst_get (insn) == 18 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_STSWAPBM; + if (Field_dsp340050b49a6c_fld2237inst_Slot_inst_get (insn) == 18 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SAC_RH; + if (Field_dsp340050b49a6c_fld2238inst_Slot_inst_get (insn) == 35 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SAC2X64_1; + if (Field_dsp340050b49a6c_fld2239inst_Slot_inst_get (insn) == 39 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SAC2X64_2; + if (Field_dsp340050b49a6c_fld2240inst_Slot_inst_get (insn) == 20 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SAC_RL; + if (Field_dsp340050b49a6c_fld2241inst_Slot_inst_get (insn) == 41 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_SAC2X64_3; + if (Field_dsp340050b49a6c_fld2242inst_Slot_inst_get (insn) == 45 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3661inst_Slot_inst_get (insn) == 0) + return OPCODE_ASLACM; + if (Field_dsp340050b49a6c_fld2243inst_Slot_inst_get (insn) == 21 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_STSWAPBMU; + if (Field_dsp340050b49a6c_fld2244inst_Slot_inst_get (insn) == 92 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_CM2AR_LN; + if (Field_dsp340050b49a6c_fld2245inst_Slot_inst_get (insn) == 93 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_CM2AR_LN_I; + if (Field_dsp340050b49a6c_fld2246inst_Slot_inst_get (insn) == 47 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3638inst_Slot_inst_get (insn) == 0) + return OPCODE_CM2AR_LN_R; + if (Field_dsp340050b49a6c_fld2247inst_Slot_inst_get (insn) == 24 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0) + return OPCODE_STORE_Q; + if (Field_dsp340050b49a6c_fld2248inst_Slot_inst_get (insn) == 50 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3651inst_Slot_inst_get (insn) == 0) + return OPCODE_POP128_2M_0; + if (Field_dsp340050b49a6c_fld2249inst_Slot_inst_get (insn) == 51 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3655inst_Slot_inst_get (insn) == 0) + return OPCODE_POP128_2M_3; + if (Field_dsp340050b49a6c_fld2250inst_Slot_inst_get (insn) == 26 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3653inst_Slot_inst_get (insn) == 0) + return OPCODE_POP128_2M_1; + if (Field_dsp340050b49a6c_fld2251inst_Slot_inst_get (insn) == 216 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3658inst_Slot_inst_get (insn) == 0) + return OPCODE_PUSH32; + if (Field_dsp340050b49a6c_fld2252inst_Slot_inst_get (insn) == 217 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3643inst_Slot_inst_get (insn) == 0) + return OPCODE_SWAPB; + if (Field_dsp340050b49a6c_fld2253inst_Slot_inst_get (insn) == 109 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3639inst_Slot_inst_get (insn) == 0) + return OPCODE_MOV2AC32_I; + if (Field_dsp340050b49a6c_fld2255inst_Slot_inst_get (insn) == 55 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3640inst_Slot_inst_get (insn) == 0) + return OPCODE_MOV2AC32_R; + if (Field_dsp340050b49a6c_fld2257inst_Slot_inst_get (insn) == 7 && + Field_dsp340050b49a6c_fld2019_Slot_inst_get (insn) == 6 && + Field_op0_Slot_inst_get (insn) == 0 && + Field_dsp340050b49a6c_fld3654inst_Slot_inst_get (insn) == 0) + return OPCODE_POP128_2M_2; + switch (Field_op0_Slot_inst_get (insn)) + { + case 0: + switch (Field_op1_Slot_inst_get (insn)) + { + case 0: + switch (Field_op2_Slot_inst_get (insn)) + { + case 0: + switch (Field_r_Slot_inst_get (insn)) + { + case 0: + switch (Field_m_Slot_inst_get (insn)) + { + case 0: + if (Field_s_Slot_inst_get (insn) == 0 && + Field_n_Slot_inst_get (insn) == 0) + return OPCODE_ILL; + break; + case 2: + switch (Field_n_Slot_inst_get (insn)) + { + case 0: + return OPCODE_RET; + case 1: + return OPCODE_RETW; + case 2: + return OPCODE_JX; + } + break; + case 3: + switch (Field_n_Slot_inst_get (insn)) + { + case 0: + return OPCODE_CALLX0; + case 1: + return OPCODE_CALLX4; + case 2: + return OPCODE_CALLX8; + case 3: + return OPCODE_CALLX12; + } + break; + } + break; + case 1: + return OPCODE_MOVSP; + case 2: + if (Field_s_Slot_inst_get (insn) == 0) + { + switch (Field_t_Slot_inst_get (insn)) + { + case 0: + return OPCODE_ISYNC; + case 1: + return OPCODE_RSYNC; + case 2: + return OPCODE_ESYNC; + case 3: + return OPCODE_DSYNC; + case 8: + return OPCODE_EXCW; + case 12: + return OPCODE_MEMW; + case 13: + return OPCODE_EXTW; + case 15: + return OPCODE_NOP; + } + } + break; + case 3: + switch (Field_t_Slot_inst_get (insn)) + { + case 0: + switch (Field_s_Slot_inst_get (insn)) + { + case 0: + return OPCODE_RFE; + case 2: + return OPCODE_RFDE; + case 4: + return OPCODE_RFWO; + case 5: + return OPCODE_RFWU; + } + break; + case 1: + return OPCODE_RFI; + } + break; + case 4: + return OPCODE_BREAK; + case 5: + switch (Field_s_Slot_inst_get (insn)) + { + case 0: + if (Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SYSCALL; + break; + case 1: + if (Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SIMCALL; + break; + } + break; + case 6: + return OPCODE_RSIL; + case 7: + if (Field_t_Slot_inst_get (insn) == 0) + return OPCODE_WAITI; + break; + case 8: + return OPCODE_ANY4; + case 9: + return OPCODE_ALL4; + case 10: + return OPCODE_ANY8; + case 11: + return OPCODE_ALL8; + } + break; + case 1: + return OPCODE_AND; + case 2: + return OPCODE_OR; + case 3: + return OPCODE_XOR; + case 4: + switch (Field_r_Slot_inst_get (insn)) + { + case 0: + if (Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SSR; + break; + case 1: + if (Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SSL; + break; + case 2: + if (Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SSA8L; + break; + case 3: + if (Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SSA8B; + break; + case 4: + if (Field_thi3_Slot_inst_get (insn) == 0) + return OPCODE_SSAI; + break; + case 6: + return OPCODE_RER; + case 7: + return OPCODE_WER; + case 8: + if (Field_s_Slot_inst_get (insn) == 0) + return OPCODE_ROTW; + break; + case 14: + return OPCODE_NSA; + case 15: + return OPCODE_NSAU; + } + break; + case 5: + switch (Field_r_Slot_inst_get (insn)) + { + case 3: + return OPCODE_RITLB0; + case 4: + if (Field_t_Slot_inst_get (insn) == 0) + return OPCODE_IITLB; + break; + case 5: + return OPCODE_PITLB; + case 6: + return OPCODE_WITLB; + case 7: + return OPCODE_RITLB1; + case 11: + return OPCODE_RDTLB0; + case 12: + if (Field_t_Slot_inst_get (insn) == 0) + return OPCODE_IDTLB; + break; + case 13: + return OPCODE_PDTLB; + case 14: + return OPCODE_WDTLB; + case 15: + return OPCODE_RDTLB1; + } + break; + case 6: + switch (Field_s_Slot_inst_get (insn)) + { + case 0: + return OPCODE_NEG; + case 1: + return OPCODE_ABS; + } + break; + case 8: + return OPCODE_ADD; + case 9: + return OPCODE_ADDX2; + case 10: + return OPCODE_ADDX4; + case 11: + return OPCODE_ADDX8; + case 12: + return OPCODE_SUB; + case 13: + return OPCODE_SUBX2; + case 14: + return OPCODE_SUBX4; + case 15: + return OPCODE_SUBX8; + } + break; + case 1: + switch (Field_op2_Slot_inst_get (insn)) + { + case 0: + case 1: + return OPCODE_SLLI; + case 2: + case 3: + return OPCODE_SRAI; + case 4: + return OPCODE_SRLI; + case 6: + switch (Field_sr_Slot_inst_get (insn)) + { + case 0: + return OPCODE_XSR_LBEG; + case 1: + return OPCODE_XSR_LEND; + case 2: + return OPCODE_XSR_LCOUNT; + case 3: + return OPCODE_XSR_SAR; + case 4: + return OPCODE_XSR_BR; + case 5: + return OPCODE_XSR_LITBASE; + case 12: + return OPCODE_XSR_SCOMPARE1; + case 72: + return OPCODE_XSR_WINDOWBASE; + case 73: + return OPCODE_XSR_WINDOWSTART; + case 96: + return OPCODE_XSR_IBREAKENABLE; + case 99: + return OPCODE_XSR_ATOMCTL; + case 104: + return OPCODE_XSR_DDR; + case 128: + return OPCODE_XSR_IBREAKA0; + case 129: + return OPCODE_XSR_IBREAKA1; + case 144: + return OPCODE_XSR_DBREAKA0; + case 145: + return OPCODE_XSR_DBREAKA1; + case 160: + return OPCODE_XSR_DBREAKC0; + case 161: + return OPCODE_XSR_DBREAKC1; + case 177: + return OPCODE_XSR_EPC1; + case 178: + return OPCODE_XSR_EPC2; + case 179: + return OPCODE_XSR_EPC3; + case 180: + return OPCODE_XSR_EPC4; + case 181: + return OPCODE_XSR_EPC5; + case 182: + return OPCODE_XSR_EPC6; + case 192: + return OPCODE_XSR_DEPC; + case 194: + return OPCODE_XSR_EPS2; + case 195: + return OPCODE_XSR_EPS3; + case 196: + return OPCODE_XSR_EPS4; + case 197: + return OPCODE_XSR_EPS5; + case 198: + return OPCODE_XSR_EPS6; + case 209: + return OPCODE_XSR_EXCSAVE1; + case 210: + return OPCODE_XSR_EXCSAVE2; + case 211: + return OPCODE_XSR_EXCSAVE3; + case 212: + return OPCODE_XSR_EXCSAVE4; + case 213: + return OPCODE_XSR_EXCSAVE5; + case 214: + return OPCODE_XSR_EXCSAVE6; + case 224: + return OPCODE_XSR_CPENABLE; + case 228: + return OPCODE_XSR_INTENABLE; + case 230: + return OPCODE_XSR_PS; + case 231: + return OPCODE_XSR_VECBASE; + case 232: + return OPCODE_XSR_EXCCAUSE; + case 233: + return OPCODE_XSR_DEBUGCAUSE; + case 234: + return OPCODE_XSR_CCOUNT; + case 236: + return OPCODE_XSR_ICOUNT; + case 237: + return OPCODE_XSR_ICOUNTLEVEL; + case 238: + return OPCODE_XSR_EXCVADDR; + case 240: + return OPCODE_XSR_CCOMPARE0; + case 241: + return OPCODE_XSR_CCOMPARE1; + } + break; + case 8: + return OPCODE_SRC; + case 9: + if (Field_s_Slot_inst_get (insn) == 0) + return OPCODE_SRL; + break; + case 10: + if (Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SLL; + break; + case 11: + if (Field_s_Slot_inst_get (insn) == 0) + return OPCODE_SRA; + break; + case 12: + return OPCODE_MUL16U; + case 13: + return OPCODE_MUL16S; + case 15: + switch (Field_r_Slot_inst_get (insn)) + { + case 0: + return OPCODE_LICT; + case 1: + return OPCODE_SICT; + case 2: + return OPCODE_LICW; + case 3: + return OPCODE_SICW; + case 8: + return OPCODE_LDCT; + case 9: + return OPCODE_SDCT; + case 14: + if (Field_t_Slot_inst_get (insn) == 0) + return OPCODE_RFDO; + if (Field_t_Slot_inst_get (insn) == 1) + return OPCODE_RFDD; + break; + } + break; + } + break; + case 2: + switch (Field_op2_Slot_inst_get (insn)) + { + case 0: + return OPCODE_ANDB; + case 1: + return OPCODE_ANDBC; + case 2: + return OPCODE_ORB; + case 3: + return OPCODE_ORBC; + case 4: + return OPCODE_XORB; + } + break; + case 3: + switch (Field_op2_Slot_inst_get (insn)) + { + case 0: + switch (Field_sr_Slot_inst_get (insn)) + { + case 0: + return OPCODE_RSR_LBEG; + case 1: + return OPCODE_RSR_LEND; + case 2: + return OPCODE_RSR_LCOUNT; + case 3: + return OPCODE_RSR_SAR; + case 4: + return OPCODE_RSR_BR; + case 5: + return OPCODE_RSR_LITBASE; + case 12: + return OPCODE_RSR_SCOMPARE1; + case 72: + return OPCODE_RSR_WINDOWBASE; + case 73: + return OPCODE_RSR_WINDOWSTART; + case 96: + return OPCODE_RSR_IBREAKENABLE; + case 99: + return OPCODE_RSR_ATOMCTL; + case 104: + return OPCODE_RSR_DDR; + case 128: + return OPCODE_RSR_IBREAKA0; + case 129: + return OPCODE_RSR_IBREAKA1; + case 144: + return OPCODE_RSR_DBREAKA0; + case 145: + return OPCODE_RSR_DBREAKA1; + case 160: + return OPCODE_RSR_DBREAKC0; + case 161: + return OPCODE_RSR_DBREAKC1; + case 176: + return OPCODE_RSR_176; + case 177: + return OPCODE_RSR_EPC1; + case 178: + return OPCODE_RSR_EPC2; + case 179: + return OPCODE_RSR_EPC3; + case 180: + return OPCODE_RSR_EPC4; + case 181: + return OPCODE_RSR_EPC5; + case 182: + return OPCODE_RSR_EPC6; + case 192: + return OPCODE_RSR_DEPC; + case 194: + return OPCODE_RSR_EPS2; + case 195: + return OPCODE_RSR_EPS3; + case 196: + return OPCODE_RSR_EPS4; + case 197: + return OPCODE_RSR_EPS5; + case 198: + return OPCODE_RSR_EPS6; + case 208: + return OPCODE_RSR_208; + case 209: + return OPCODE_RSR_EXCSAVE1; + case 210: + return OPCODE_RSR_EXCSAVE2; + case 211: + return OPCODE_RSR_EXCSAVE3; + case 212: + return OPCODE_RSR_EXCSAVE4; + case 213: + return OPCODE_RSR_EXCSAVE5; + case 214: + return OPCODE_RSR_EXCSAVE6; + case 224: + return OPCODE_RSR_CPENABLE; + case 226: + return OPCODE_RSR_INTERRUPT; + case 228: + return OPCODE_RSR_INTENABLE; + case 230: + return OPCODE_RSR_PS; + case 231: + return OPCODE_RSR_VECBASE; + case 232: + return OPCODE_RSR_EXCCAUSE; + case 233: + return OPCODE_RSR_DEBUGCAUSE; + case 234: + return OPCODE_RSR_CCOUNT; + case 235: + return OPCODE_RSR_PRID; + case 236: + return OPCODE_RSR_ICOUNT; + case 237: + return OPCODE_RSR_ICOUNTLEVEL; + case 238: + return OPCODE_RSR_EXCVADDR; + case 240: + return OPCODE_RSR_CCOMPARE0; + case 241: + return OPCODE_RSR_CCOMPARE1; + } + break; + case 1: + switch (Field_sr_Slot_inst_get (insn)) + { + case 0: + return OPCODE_WSR_LBEG; + case 1: + return OPCODE_WSR_LEND; + case 2: + return OPCODE_WSR_LCOUNT; + case 3: + return OPCODE_WSR_SAR; + case 4: + return OPCODE_WSR_BR; + case 5: + return OPCODE_WSR_LITBASE; + case 12: + return OPCODE_WSR_SCOMPARE1; + case 72: + return OPCODE_WSR_WINDOWBASE; + case 73: + return OPCODE_WSR_WINDOWSTART; + case 89: + return OPCODE_WSR_MMID; + case 96: + return OPCODE_WSR_IBREAKENABLE; + case 99: + return OPCODE_WSR_ATOMCTL; + case 104: + return OPCODE_WSR_DDR; + case 128: + return OPCODE_WSR_IBREAKA0; + case 129: + return OPCODE_WSR_IBREAKA1; + case 144: + return OPCODE_WSR_DBREAKA0; + case 145: + return OPCODE_WSR_DBREAKA1; + case 160: + return OPCODE_WSR_DBREAKC0; + case 161: + return OPCODE_WSR_DBREAKC1; + case 176: + return OPCODE_WSR_176; + case 177: + return OPCODE_WSR_EPC1; + case 178: + return OPCODE_WSR_EPC2; + case 179: + return OPCODE_WSR_EPC3; + case 180: + return OPCODE_WSR_EPC4; + case 181: + return OPCODE_WSR_EPC5; + case 182: + return OPCODE_WSR_EPC6; + case 192: + return OPCODE_WSR_DEPC; + case 194: + return OPCODE_WSR_EPS2; + case 195: + return OPCODE_WSR_EPS3; + case 196: + return OPCODE_WSR_EPS4; + case 197: + return OPCODE_WSR_EPS5; + case 198: + return OPCODE_WSR_EPS6; + case 209: + return OPCODE_WSR_EXCSAVE1; + case 210: + return OPCODE_WSR_EXCSAVE2; + case 211: + return OPCODE_WSR_EXCSAVE3; + case 212: + return OPCODE_WSR_EXCSAVE4; + case 213: + return OPCODE_WSR_EXCSAVE5; + case 214: + return OPCODE_WSR_EXCSAVE6; + case 224: + return OPCODE_WSR_CPENABLE; + case 226: + return OPCODE_WSR_INTSET; + case 227: + return OPCODE_WSR_INTCLEAR; + case 228: + return OPCODE_WSR_INTENABLE; + case 230: + return OPCODE_WSR_PS; + case 231: + return OPCODE_WSR_VECBASE; + case 232: + return OPCODE_WSR_EXCCAUSE; + case 233: + return OPCODE_WSR_DEBUGCAUSE; + case 234: + return OPCODE_WSR_CCOUNT; + case 236: + return OPCODE_WSR_ICOUNT; + case 237: + return OPCODE_WSR_ICOUNTLEVEL; + case 238: + return OPCODE_WSR_EXCVADDR; + case 240: + return OPCODE_WSR_CCOMPARE0; + case 241: + return OPCODE_WSR_CCOMPARE1; + } + break; + case 2: + return OPCODE_SEXT; + case 3: + return OPCODE_CLAMPS; + case 4: + return OPCODE_MIN; + case 5: + return OPCODE_MAX; + case 6: + return OPCODE_MINU; + case 7: + return OPCODE_MAXU; + case 8: + return OPCODE_MOVEQZ; + case 9: + return OPCODE_MOVNEZ; + case 10: + return OPCODE_MOVLTZ; + case 11: + return OPCODE_MOVGEZ; + case 12: + return OPCODE_MOVF; + case 13: + return OPCODE_MOVT; + case 14: + switch (Field_st_Slot_inst_get (insn)) + { + case 0: + return OPCODE_RUR_EXPSTATE; + case 1: + return OPCODE_RUR_SOV; + case 2: + return OPCODE_RUR_SAT_MODE; + case 3: + return OPCODE_RUR_SAR0; + case 4: + return OPCODE_RUR_SAR1; + case 5: + return OPCODE_RUR_SAR2; + case 6: + return OPCODE_RUR_SAR3; + case 7: + return OPCODE_RUR_HSAR0; + case 8: + return OPCODE_RUR_HSAR1; + case 9: + return OPCODE_RUR_HSAR2; + case 10: + return OPCODE_RUR_HSAR3; + case 11: + return OPCODE_RUR_MAX_REG_0; + case 12: + return OPCODE_RUR_MAX_REG_1; + case 13: + return OPCODE_RUR_MAX_REG_2; + case 14: + return OPCODE_RUR_MAX_REG_3; + case 15: + return OPCODE_RUR_ARG_MAX_REG_0; + case 16: + return OPCODE_RUR_ARG_MAX_REG_1; + case 17: + return OPCODE_RUR_ARG_MAX_REG_2; + case 18: + return OPCODE_RUR_ARG_MAX_REG_3; + case 19: + return OPCODE_RUR_NCO_COUNTER_0; + case 20: + return OPCODE_RUR_NCO_COUNTER_1; + case 21: + return OPCODE_RUR_NCO_COUNTER_2; + case 22: + return OPCODE_RUR_NCO_COUNTER_3; + case 23: + return OPCODE_RUR_INTERP_EXT_N; + case 24: + return OPCODE_RUR_INTERP_EXT_L; + case 25: + return OPCODE_RUR_LLR_BUF_0; + case 26: + return OPCODE_RUR_LLR_BUF_1; + case 27: + return OPCODE_RUR_LLR_BUF_2; + case 28: + return OPCODE_RUR_LLR_BUF_3; + case 29: + return OPCODE_RUR_LLR_BUF_4; + case 30: + return OPCODE_RUR_LLR_BUF_5; + case 31: + return OPCODE_RUR_LLR_BUF_6; + case 32: + return OPCODE_RUR_LLR_BUF_7; + case 33: + return OPCODE_RUR_LLR_BUF_8; + case 34: + return OPCODE_RUR_LLR_BUF_9; + case 35: + return OPCODE_RUR_LLR_BUF_10; + case 36: + return OPCODE_RUR_LLR_BUF_11; + case 37: + return OPCODE_RUR_LLR_BUF_12; + case 38: + return OPCODE_RUR_LLR_BUF_13; + case 39: + return OPCODE_RUR_LLR_BUF_14; + case 40: + return OPCODE_RUR_LLR_BUF_15; + case 41: + return OPCODE_RUR_LLR_BUF_16; + case 42: + return OPCODE_RUR_LLR_BUF_17; + case 43: + return OPCODE_RUR_LLR_BUF_18; + case 44: + return OPCODE_RUR_LLR_BUF_19; + case 45: + return OPCODE_RUR_LLR_BUF_20; + case 46: + return OPCODE_RUR_LLR_BUF_21; + case 47: + return OPCODE_RUR_LLR_BUF_22; + case 48: + return OPCODE_RUR_LLR_BUF_23; + case 49: + return OPCODE_RUR_SMOD_BUF_0; + case 50: + return OPCODE_RUR_SMOD_BUF_1; + case 51: + return OPCODE_RUR_SMOD_BUF_2; + case 52: + return OPCODE_RUR_SMOD_BUF_3; + case 53: + return OPCODE_RUR_SMOD_BUF_4; + case 54: + return OPCODE_RUR_SMOD_BUF_5; + case 55: + return OPCODE_RUR_SMOD_BUF_6; + case 56: + return OPCODE_RUR_SMOD_BUF_7; + case 57: + return OPCODE_RUR_WEIGHT_REG; + case 58: + return OPCODE_RUR_SCALE_REG; + case 59: + return OPCODE_RUR_LLR_POS; + case 60: + return OPCODE_RUR_SMOD_POS; + case 61: + return OPCODE_RUR_PERM_REG; + case 62: + return OPCODE_RUR_SMOD_OFFSET_TABLE_0; + case 63: + return OPCODE_RUR_SMOD_OFFSET_TABLE_1; + case 64: + return OPCODE_RUR_SMOD_OFFSET_TABLE_2; + case 65: + return OPCODE_RUR_SMOD_OFFSET_TABLE_3; + case 66: + return OPCODE_RUR_PHASOR_N; + case 67: + return OPCODE_RUR_PHASOR_OFFSET; + case 231: + return OPCODE_RUR_THREADPTR; + case 232: + return OPCODE_RUR_FCR; + case 233: + return OPCODE_RUR_FSR; + } + break; + case 15: + switch (Field_sr_Slot_inst_get (insn)) + { + case 0: + return OPCODE_WUR_EXPSTATE; + case 1: + return OPCODE_WUR_SOV; + case 2: + return OPCODE_WUR_SAT_MODE; + case 3: + return OPCODE_WUR_SAR0; + case 4: + return OPCODE_WUR_SAR1; + case 5: + return OPCODE_WUR_SAR2; + case 6: + return OPCODE_WUR_SAR3; + case 7: + return OPCODE_WUR_HSAR0; + case 8: + return OPCODE_WUR_HSAR1; + case 9: + return OPCODE_WUR_HSAR2; + case 10: + return OPCODE_WUR_HSAR3; + case 11: + return OPCODE_WUR_MAX_REG_0; + case 12: + return OPCODE_WUR_MAX_REG_1; + case 13: + return OPCODE_WUR_MAX_REG_2; + case 14: + return OPCODE_WUR_MAX_REG_3; + case 15: + return OPCODE_WUR_ARG_MAX_REG_0; + case 16: + return OPCODE_WUR_ARG_MAX_REG_1; + case 17: + return OPCODE_WUR_ARG_MAX_REG_2; + case 18: + return OPCODE_WUR_ARG_MAX_REG_3; + case 19: + return OPCODE_WUR_NCO_COUNTER_0; + case 20: + return OPCODE_WUR_NCO_COUNTER_1; + case 21: + return OPCODE_WUR_NCO_COUNTER_2; + case 22: + return OPCODE_WUR_NCO_COUNTER_3; + case 23: + return OPCODE_WUR_INTERP_EXT_N; + case 24: + return OPCODE_WUR_INTERP_EXT_L; + case 25: + return OPCODE_WUR_LLR_BUF_0; + case 26: + return OPCODE_WUR_LLR_BUF_1; + case 27: + return OPCODE_WUR_LLR_BUF_2; + case 28: + return OPCODE_WUR_LLR_BUF_3; + case 29: + return OPCODE_WUR_LLR_BUF_4; + case 30: + return OPCODE_WUR_LLR_BUF_5; + case 31: + return OPCODE_WUR_LLR_BUF_6; + case 32: + return OPCODE_WUR_LLR_BUF_7; + case 33: + return OPCODE_WUR_LLR_BUF_8; + case 34: + return OPCODE_WUR_LLR_BUF_9; + case 35: + return OPCODE_WUR_LLR_BUF_10; + case 36: + return OPCODE_WUR_LLR_BUF_11; + case 37: + return OPCODE_WUR_LLR_BUF_12; + case 38: + return OPCODE_WUR_LLR_BUF_13; + case 39: + return OPCODE_WUR_LLR_BUF_14; + case 40: + return OPCODE_WUR_LLR_BUF_15; + case 41: + return OPCODE_WUR_LLR_BUF_16; + case 42: + return OPCODE_WUR_LLR_BUF_17; + case 43: + return OPCODE_WUR_LLR_BUF_18; + case 44: + return OPCODE_WUR_LLR_BUF_19; + case 45: + return OPCODE_WUR_LLR_BUF_20; + case 46: + return OPCODE_WUR_LLR_BUF_21; + case 47: + return OPCODE_WUR_LLR_BUF_22; + case 48: + return OPCODE_WUR_LLR_BUF_23; + case 49: + return OPCODE_WUR_SMOD_BUF_0; + case 50: + return OPCODE_WUR_SMOD_BUF_1; + case 51: + return OPCODE_WUR_SMOD_BUF_2; + case 52: + return OPCODE_WUR_SMOD_BUF_3; + case 53: + return OPCODE_WUR_SMOD_BUF_4; + case 54: + return OPCODE_WUR_SMOD_BUF_5; + case 55: + return OPCODE_WUR_SMOD_BUF_6; + case 56: + return OPCODE_WUR_SMOD_BUF_7; + case 57: + return OPCODE_WUR_WEIGHT_REG; + case 58: + return OPCODE_WUR_SCALE_REG; + case 59: + return OPCODE_WUR_LLR_POS; + case 60: + return OPCODE_WUR_SMOD_POS; + case 61: + return OPCODE_WUR_PERM_REG; + case 62: + return OPCODE_WUR_SMOD_OFFSET_TABLE_0; + case 63: + return OPCODE_WUR_SMOD_OFFSET_TABLE_1; + case 64: + return OPCODE_WUR_SMOD_OFFSET_TABLE_2; + case 65: + return OPCODE_WUR_SMOD_OFFSET_TABLE_3; + case 66: + return OPCODE_WUR_PHASOR_N; + case 67: + return OPCODE_WUR_PHASOR_OFFSET; + case 231: + return OPCODE_WUR_THREADPTR; + case 232: + return OPCODE_WUR_FCR; + case 233: + return OPCODE_WUR_FSR; + } + break; + } + break; + case 4: + case 5: + return OPCODE_EXTUI; + case 8: + switch (Field_op2_Slot_inst_get (insn)) + { + case 0: + return OPCODE_LSX; + case 1: + return OPCODE_LSXU; + case 4: + return OPCODE_SSX; + case 5: + return OPCODE_SSXU; + } + break; + case 9: + switch (Field_op2_Slot_inst_get (insn)) + { + case 0: + return OPCODE_L32E; + case 4: + return OPCODE_S32E; + } + break; + case 10: + switch (Field_op2_Slot_inst_get (insn)) + { + case 0: + return OPCODE_ADD_S; + case 1: + return OPCODE_SUB_S; + case 2: + return OPCODE_MUL_S; + case 4: + return OPCODE_MADD_S; + case 5: + return OPCODE_MSUB_S; + case 8: + return OPCODE_ROUND_S; + case 9: + return OPCODE_TRUNC_S; + case 10: + return OPCODE_FLOOR_S; + case 11: + return OPCODE_CEIL_S; + case 12: + return OPCODE_FLOAT_S; + case 13: + return OPCODE_UFLOAT_S; + case 14: + return OPCODE_UTRUNC_S; + case 15: + switch (Field_t_Slot_inst_get (insn)) + { + case 0: + return OPCODE_MOV_S; + case 1: + return OPCODE_ABS_S; + case 4: + return OPCODE_RFR; + case 5: + return OPCODE_WFR; + case 6: + return OPCODE_NEG_S; + } + break; + } + break; + case 11: + switch (Field_op2_Slot_inst_get (insn)) + { + case 1: + return OPCODE_UN_S; + case 2: + return OPCODE_OEQ_S; + case 3: + return OPCODE_UEQ_S; + case 4: + return OPCODE_OLT_S; + case 5: + return OPCODE_ULT_S; + case 6: + return OPCODE_OLE_S; + case 7: + return OPCODE_ULE_S; + case 8: + return OPCODE_MOVEQZ_S; + case 9: + return OPCODE_MOVNEZ_S; + case 10: + return OPCODE_MOVLTZ_S; + case 11: + return OPCODE_MOVGEZ_S; + case 12: + return OPCODE_MOVF_S; + case 13: + return OPCODE_MOVT_S; + } + break; + } + break; + case 1: + return OPCODE_L32R; + case 2: + switch (Field_r_Slot_inst_get (insn)) + { + case 0: + return OPCODE_L8UI; + case 1: + return OPCODE_L16UI; + case 2: + return OPCODE_L32I; + case 4: + return OPCODE_S8I; + case 5: + return OPCODE_S16I; + case 6: + return OPCODE_S32I; + case 7: + switch (Field_t_Slot_inst_get (insn)) + { + case 0: + return OPCODE_DPFR; + case 1: + return OPCODE_DPFW; + case 2: + return OPCODE_DPFRO; + case 3: + return OPCODE_DPFWO; + case 4: + return OPCODE_DHWB; + case 5: + return OPCODE_DHWBI; + case 6: + return OPCODE_DHI; + case 7: + return OPCODE_DII; + case 8: + switch (Field_op1_Slot_inst_get (insn)) + { + case 0: + return OPCODE_DPFL; + case 2: + return OPCODE_DHU; + case 3: + return OPCODE_DIU; + case 4: + return OPCODE_DIWB; + case 5: + return OPCODE_DIWBI; + } + break; + case 12: + return OPCODE_IPF; + case 13: + switch (Field_op1_Slot_inst_get (insn)) + { + case 0: + return OPCODE_IPFL; + case 2: + return OPCODE_IHU; + case 3: + return OPCODE_IIU; + } + break; + case 14: + return OPCODE_IHI; + case 15: + return OPCODE_III; + } + break; + case 9: + return OPCODE_L16SI; + case 10: + return OPCODE_MOVI; + case 11: + return OPCODE_L32AI; + case 12: + return OPCODE_ADDI; + case 13: + return OPCODE_ADDMI; + case 14: + return OPCODE_S32C1I; + case 15: + return OPCODE_S32RI; + } + break; + case 3: + switch (Field_r_Slot_inst_get (insn)) + { + case 0: + return OPCODE_LSI; + case 4: + return OPCODE_SSI; + case 8: + return OPCODE_LSIU; + case 12: + return OPCODE_SSIU; + } + break; + case 5: + switch (Field_n_Slot_inst_get (insn)) + { + case 0: + return OPCODE_CALL0; + case 1: + return OPCODE_CALL4; + case 2: + return OPCODE_CALL8; + case 3: + return OPCODE_CALL12; + } + break; + case 6: + switch (Field_n_Slot_inst_get (insn)) + { + case 0: + return OPCODE_J; + case 1: + switch (Field_m_Slot_inst_get (insn)) + { + case 0: + return OPCODE_BEQZ; + case 1: + return OPCODE_BNEZ; + case 2: + return OPCODE_BLTZ; + case 3: + return OPCODE_BGEZ; + } + break; + case 2: + switch (Field_m_Slot_inst_get (insn)) + { + case 0: + return OPCODE_BEQI; + case 1: + return OPCODE_BNEI; + case 2: + return OPCODE_BLTI; + case 3: + return OPCODE_BGEI; + } + break; + case 3: + switch (Field_m_Slot_inst_get (insn)) + { + case 0: + return OPCODE_ENTRY; + case 1: + switch (Field_r_Slot_inst_get (insn)) + { + case 0: + return OPCODE_BF; + case 1: + return OPCODE_BT; + case 8: + return OPCODE_LOOP; + case 9: + return OPCODE_LOOPNEZ; + case 10: + return OPCODE_LOOPGTZ; + } + break; + case 2: + return OPCODE_BLTUI; + case 3: + return OPCODE_BGEUI; + } + break; + } + break; + case 7: + switch (Field_r_Slot_inst_get (insn)) + { + case 0: + return OPCODE_BNONE; + case 1: + return OPCODE_BEQ; + case 2: + return OPCODE_BLT; + case 3: + return OPCODE_BLTU; + case 4: + return OPCODE_BALL; + case 5: + return OPCODE_BBC; + case 6: + case 7: + return OPCODE_BBCI; + case 8: + return OPCODE_BANY; + case 9: + return OPCODE_BNE; + case 10: + return OPCODE_BGE; + case 11: + return OPCODE_BGEU; + case 12: + return OPCODE_BNALL; + case 13: + return OPCODE_BBS; + case 14: + case 15: + return OPCODE_BBSI; + } + break; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_inst16b_decode (const xtensa_insnbuf insn) +{ + switch (Field_op0_Slot_inst16b_get (insn)) + { + case 12: + switch (Field_i_Slot_inst16b_get (insn)) + { + case 0: + return OPCODE_MOVI_N; + case 1: + switch (Field_z_Slot_inst16b_get (insn)) + { + case 0: + return OPCODE_BEQZ_N; + case 1: + return OPCODE_BNEZ_N; + } + break; + } + break; + case 13: + switch (Field_r_Slot_inst16b_get (insn)) + { + case 0: + return OPCODE_MOV_N; + case 15: + switch (Field_t_Slot_inst16b_get (insn)) + { + case 0: + return OPCODE_RET_N; + case 1: + return OPCODE_RETW_N; + case 2: + return OPCODE_BREAK_N; + case 3: + if (Field_s_Slot_inst16b_get (insn) == 0) + return OPCODE_NOP_N; + break; + case 6: + if (Field_s_Slot_inst16b_get (insn) == 0) + return OPCODE_ILL_N; + break; + } + break; + } + break; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_inst16a_decode (const xtensa_insnbuf insn) +{ + switch (Field_op0_Slot_inst16a_get (insn)) + { + case 8: + return OPCODE_L32I_N; + case 9: + return OPCODE_S32I_N; + case 10: + return OPCODE_ADD_N; + case 11: + return OPCODE_ADDI_N; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_gp_slot2_decode (const xtensa_insnbuf insn) +{ + switch (Field_dsp340050b49a6c_fld2258gp_slot2_Slot_gp_slot2_get (insn)) + { + case 22: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVI_N; + break; + case 24: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_AR2PQ_LN; + break; + } + if (Field_dsp340050b49a6c_fld2259gp_slot2_Slot_gp_slot2_get (insn) == 46 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_AR2CM_LN; + switch (Field_dsp340050b49a6c_fld2260gp_slot2_Slot_gp_slot2_get (insn)) + { + case 185: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_ADDAR2; + break; + case 187: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOV_N; + break; + case 189: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVPQ2PQ; + break; + case 191: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_PUSH128_PQ; + break; + case 200: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_PUSH32; + break; + case 201: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_SET_EXT_REGS; + break; + case 202: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_SUBARX; + break; + case 204: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_WRTIEP; + break; + } + switch (Field_dsp340050b49a6c_fld2261gp_slot2_Slot_gp_slot2_get (insn)) + { + case 1624: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_CLRTIEP; + break; + case 1625: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_SETTIEP; + break; + case 1626: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_WRTBSIGQM; + break; + case 1631: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2044_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_1; + break; + } + switch (Field_dsp340050b49a6c_fld2262gp_slot2_Slot_gp_slot2_get (insn)) + { + case 3254: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP2X128_2PQ_01; + break; + case 3255: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP2X128_2PQ_03; + break; + case 3256: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_AR2SAR_DUP; + break; + case 3257: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP2X128_2PQ_21; + break; + case 3258: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP2X128_2PQ_23; + break; + case 3259: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_WRTSIGQ; + break; + case 3260: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_WRTBSIGQ; + break; + } + switch (Field_dsp340050b49a6c_fld2263gp_slot2_Slot_gp_slot2_get (insn)) + { + case 52176: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_0; + break; + case 52177: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_2; + break; + case 52178: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_3; + break; + case 52179: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_0; + break; + case 52180: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_4; + break; + case 52181: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_1; + break; + case 52182: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_2; + break; + case 52183: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_3; + break; + } + if (Field_dsp340050b49a6c_fld2264gp_slot2_Slot_gp_slot2_get (insn) == 13046 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2302_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_5; + if (Field_dsp340050b49a6c_fld2266gp_slot2_Slot_gp_slot2_get (insn) == 13047 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2302_Slot_gp_slot2_get (insn) == 0) + return OPCODE_NOP; + if (Field_dsp340050b49a6c_fld2267gp_slot2_Slot_gp_slot2_get (insn) == 1640 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_0; + if (Field_dsp340050b49a6c_fld2268gp_slot2_Slot_gp_slot2_get (insn) == 1641 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_1; + if (Field_dsp340050b49a6c_fld2269gp_slot2_Slot_gp_slot2_get (insn) == 1642 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_2; + if (Field_dsp340050b49a6c_fld2270gp_slot2_Slot_gp_slot2_get (insn) == 1643 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_4; + if (Field_dsp340050b49a6c_fld2271gp_slot2_Slot_gp_slot2_get (insn) == 822 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2305_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_3; + if (Field_dsp340050b49a6c_fld2273gp_slot2_Slot_gp_slot2_get (insn) == 823 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2305_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_5; + if (Field_dsp340050b49a6c_fld2274gp_slot2_Slot_gp_slot2_get (insn) == 103 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2056_Slot_gp_slot2_get (insn) == 0) + return OPCODE_PUSH2X128_PQ; + if (Field_dsp340050b49a6c_fld2275gp_slot2_Slot_gp_slot2_get (insn) == 52 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_CM2AR_LN; + if (Field_dsp340050b49a6c_fld2277gp_slot2_Slot_gp_slot2_get (insn) == 106 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP128_2CMPQ_1; + if (Field_dsp340050b49a6c_fld2278gp_slot2_Slot_gp_slot2_get (insn) == 107 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP128_2CMPQ_3; + if (Field_dsp340050b49a6c_fld2279gp_slot2_Slot_gp_slot2_get (insn) == 108 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP128_2CMPQ_2; + if (Field_dsp340050b49a6c_fld2280gp_slot2_Slot_gp_slot2_get (insn) == 109 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_PQ2CM; + if (Field_dsp340050b49a6c_fld2281gp_slot2_Slot_gp_slot2_get (insn) == 220 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_ABS; + if (Field_dsp340050b49a6c_fld2282gp_slot2_Slot_gp_slot2_get (insn) == 221 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_NEG; + if (Field_dsp340050b49a6c_fld2283gp_slot2_Slot_gp_slot2_get (insn) == 222 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_SRA; + if (Field_dsp340050b49a6c_fld2284gp_slot2_Slot_gp_slot2_get (insn) == 3343 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_CLRCM; + if (Field_dsp340050b49a6c_fld2286gp_slot2_Slot_gp_slot2_get (insn) == 3359 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_GET_ARGMAX; + if (Field_dsp340050b49a6c_fld2287gp_slot2_Slot_gp_slot2_get (insn) == 3375 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_GET_HSAR; + if (Field_dsp340050b49a6c_fld2288gp_slot2_Slot_gp_slot2_get (insn) == 3391 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_GET_NCO; + if (Field_dsp340050b49a6c_fld2289gp_slot2_Slot_gp_slot2_get (insn) == 3407 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_GET_HSAR2SAR; + if (Field_dsp340050b49a6c_fld2290gp_slot2_Slot_gp_slot2_get (insn) == 3423 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_GET_SAR; + if (Field_dsp340050b49a6c_fld2291gp_slot2_Slot_gp_slot2_get (insn) == 3439 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP128_0; + if (Field_dsp340050b49a6c_fld2292gp_slot2_Slot_gp_slot2_get (insn) == 3455 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP128_1; + if (Field_dsp340050b49a6c_fld2293gp_slot2_Slot_gp_slot2_get (insn) == 3471 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_GET_MAX; + if (Field_dsp340050b49a6c_fld2294gp_slot2_Slot_gp_slot2_get (insn) == 3487 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP128_2; + if (Field_dsp340050b49a6c_fld2295gp_slot2_Slot_gp_slot2_get (insn) == 3503 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP128_3; + if (Field_dsp340050b49a6c_fld2296gp_slot2_Slot_gp_slot2_get (insn) == 3519 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP128_5; + if (Field_dsp340050b49a6c_fld2297gp_slot2_Slot_gp_slot2_get (insn) == 3535 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP128_4; + if (Field_dsp340050b49a6c_fld2298gp_slot2_Slot_gp_slot2_get (insn) == 3551 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP32_0; + if (Field_dsp340050b49a6c_fld2299gp_slot2_Slot_gp_slot2_get (insn) == 3567 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP32_1; + if (Field_dsp340050b49a6c_fld2300gp_slot2_Slot_gp_slot2_get (insn) == 3583 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP32_2; + if (Field_dsp340050b49a6c_fld2301gp_slot2_Slot_gp_slot2_get (insn) == 56 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2272_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP128_2CMPQ_0; + if (Field_dsp340050b49a6c_fld2303gp_slot2_Slot_gp_slot2_get (insn) == 57 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3671gp_slot2_Slot_gp_slot2_get (insn) == 0) + return OPCODE_POP32_3; + if (Field_dsp340050b49a6c_fld2304gp_slot2_Slot_gp_slot2_get (insn) == 29 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3674gp_slot2_Slot_gp_slot2_get (insn) == 0) + return OPCODE_RDTIEP; + if (Field_dsp340050b49a6c_fld2306gp_slot2_Slot_gp_slot2_get (insn) == 120 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_QREADY; + if (Field_dsp340050b49a6c_fld2308gp_slot2_Slot_gp_slot2_get (insn) == 242 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_AR2CM_DUP; + if (Field_dsp340050b49a6c_fld2309gp_slot2_Slot_gp_slot2_get (insn) == 243 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_SWAPB; + if (Field_dsp340050b49a6c_fld2310gp_slot2_Slot_gp_slot2_get (insn) == 61 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3667gp_slot2_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVAR2; + if (Field_dsp340050b49a6c_fld2312gp_slot2_Slot_gp_slot2_get (insn) == 31 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2386_Slot_gp_slot2_get (insn) == 0) + return OPCODE_SLL; + if (Field_dsp340050b49a6c_fld2314gp_slot2_Slot_gp_slot2_get (insn) == 16 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_ADD32; + if (Field_dsp340050b49a6c_fld2316gp_slot2_Slot_gp_slot2_get (insn) == 17 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_ADDCM; + if (Field_dsp340050b49a6c_fld2317gp_slot2_Slot_gp_slot2_get (insn) == 18 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_ADDWRP; + if (Field_dsp340050b49a6c_fld2318gp_slot2_Slot_gp_slot2_get (insn) == 19 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_ASR; + if (Field_dsp340050b49a6c_fld2319gp_slot2_Slot_gp_slot2_get (insn) == 20 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_AND128; + if (Field_dsp340050b49a6c_fld2320gp_slot2_Slot_gp_slot2_get (insn) == 21 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_EXTUI4; + if (Field_dsp340050b49a6c_fld2321gp_slot2_Slot_gp_slot2_get (insn) == 22 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_LUT; + if (Field_dsp340050b49a6c_fld2322gp_slot2_Slot_gp_slot2_get (insn) == 23 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_LUT_IEXT; + if (Field_dsp340050b49a6c_fld2323gp_slot2_Slot_gp_slot2_get (insn) == 24 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_ASL; + if (Field_dsp340050b49a6c_fld2324gp_slot2_Slot_gp_slot2_get (insn) == 25 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_LUT_REXT; + if (Field_dsp340050b49a6c_fld2325gp_slot2_Slot_gp_slot2_get (insn) == 26 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MAX8; + if (Field_dsp340050b49a6c_fld2326gp_slot2_Slot_gp_slot2_get (insn) == 27 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MEAN32; + if (Field_dsp340050b49a6c_fld2327gp_slot2_Slot_gp_slot2_get (insn) == 28 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MEAN; + if (Field_dsp340050b49a6c_fld2328gp_slot2_Slot_gp_slot2_get (insn) == 29 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MIN8; + if (Field_dsp340050b49a6c_fld2329gp_slot2_Slot_gp_slot2_get (insn) == 30 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_OR128; + if (Field_dsp340050b49a6c_fld2330gp_slot2_Slot_gp_slot2_get (insn) == 31 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_SUB32; + if (Field_dsp340050b49a6c_fld2331gp_slot2_Slot_gp_slot2_get (insn) == 0 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_ASL32; + if (Field_dsp340050b49a6c_fld2332gp_slot2_Slot_gp_slot2_get (insn) == 1 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_ASR32; + if (Field_dsp340050b49a6c_fld2333gp_slot2_Slot_gp_slot2_get (insn) == 2 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_MOV2CM2PQ; + if (Field_dsp340050b49a6c_fld2334gp_slot2_Slot_gp_slot2_get (insn) == 3 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_MOVCND8_2; + if (Field_dsp340050b49a6c_fld2335gp_slot2_Slot_gp_slot2_get (insn) == 4 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_MOVCND8_0; + if (Field_dsp340050b49a6c_fld2336gp_slot2_Slot_gp_slot2_get (insn) == 5 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_MOVCND8_3; + if (Field_dsp340050b49a6c_fld2337gp_slot2_Slot_gp_slot2_get (insn) == 6 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_MOVCND8_4; + if (Field_dsp340050b49a6c_fld2338gp_slot2_Slot_gp_slot2_get (insn) == 7 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_MOVCND8_5; + if (Field_dsp340050b49a6c_fld2339gp_slot2_Slot_gp_slot2_get (insn) == 8 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_MOVCND8_1; + if (Field_dsp340050b49a6c_fld2340gp_slot2_Slot_gp_slot2_get (insn) == 9 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_MOVCND8_6; + if (Field_dsp340050b49a6c_fld2341gp_slot2_Slot_gp_slot2_get (insn) == 10 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_MOVCND8_7; + if (Field_dsp340050b49a6c_fld2342gp_slot2_Slot_gp_slot2_get (insn) == 11 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_MOVCND_1; + if (Field_dsp340050b49a6c_fld2343gp_slot2_Slot_gp_slot2_get (insn) == 12 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_MOVCND_0; + if (Field_dsp340050b49a6c_fld2344gp_slot2_Slot_gp_slot2_get (insn) == 13 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_MOVCND_2; + if (Field_dsp340050b49a6c_fld2345gp_slot2_Slot_gp_slot2_get (insn) == 14 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_MOVCND_3; + if (Field_dsp340050b49a6c_fld2346gp_slot2_Slot_gp_slot2_get (insn) == 15 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_MOVCND_4; + if (Field_dsp340050b49a6c_fld2347gp_slot2_Slot_gp_slot2_get (insn) == 16 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_ASLM; + if (Field_dsp340050b49a6c_fld2348gp_slot2_Slot_gp_slot2_get (insn) == 17 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_ASRM; + if (Field_dsp340050b49a6c_fld2349gp_slot2_Slot_gp_slot2_get (insn) == 18 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_CMP8; + if (Field_dsp340050b49a6c_fld2350gp_slot2_Slot_gp_slot2_get (insn) == 19 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_LSLM; + if (Field_dsp340050b49a6c_fld2351gp_slot2_Slot_gp_slot2_get (insn) == 20 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_CMP_I; + if (Field_dsp340050b49a6c_fld2352gp_slot2_Slot_gp_slot2_get (insn) == 21 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_LSRM; + if (Field_dsp340050b49a6c_fld2353gp_slot2_Slot_gp_slot2_get (insn) == 262 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_ABS8; + if (Field_dsp340050b49a6c_fld2354gp_slot2_Slot_gp_slot2_get (insn) == 263 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_CONJ; + if (Field_dsp340050b49a6c_fld2355gp_slot2_Slot_gp_slot2_get (insn) == 278 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_LUT_PHASOR; + if (Field_dsp340050b49a6c_fld2356gp_slot2_Slot_gp_slot2_get (insn) == 279 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_NOT128; + if (Field_dsp340050b49a6c_fld2357gp_slot2_Slot_gp_slot2_get (insn) == 294 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_MOVCM; + if (Field_dsp340050b49a6c_fld2358gp_slot2_Slot_gp_slot2_get (insn) == 295 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1) + return OPCODE_TRANS; + if (Field_dsp340050b49a6c_fld2359gp_slot2_Slot_gp_slot2_get (insn) == 2102 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2384_Slot_gp_slot2_get (insn) == 0) + return OPCODE_SET_ARGMAX; + if (Field_dsp340050b49a6c_fld2361gp_slot2_Slot_gp_slot2_get (insn) == 2103 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2384_Slot_gp_slot2_get (insn) == 0) + return OPCODE_SET_HSAR; + if (Field_dsp340050b49a6c_fld2362gp_slot2_Slot_gp_slot2_get (insn) == 1179 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3663gp_slot2_Slot_gp_slot2_get (insn) == 0) + return OPCODE_SET_MAX; + if (Field_dsp340050b49a6c_fld2364gp_slot2_Slot_gp_slot2_get (insn) == 667 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3664gp_slot2_Slot_gp_slot2_get (insn) == 0) + return OPCODE_SET_NCO; + if (Field_dsp340050b49a6c_fld2366gp_slot2_Slot_gp_slot2_get (insn) == 411 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3665gp_slot2_Slot_gp_slot2_get (insn) == 0) + return OPCODE_SET_SAR; + if (Field_dsp340050b49a6c_fld2368gp_slot2_Slot_gp_slot2_get (insn) == 43 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3670gp_slot2_Slot_gp_slot2_get (insn) == 0) + return OPCODE_NCO_UPDATE; + if (Field_dsp340050b49a6c_fld2369gp_slot2_Slot_gp_slot2_get (insn) == 27 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3668gp_slot2_Slot_gp_slot2_get (insn) == 0) + return OPCODE_NEGCM; + if (Field_dsp340050b49a6c_fld2370gp_slot2_Slot_gp_slot2_get (insn) == 6 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2032_Slot_gp_slot2_get (insn) == 0) + return OPCODE_CMP_R; + if (Field_dsp340050b49a6c_fld2371gp_slot2_Slot_gp_slot2_get (insn) == 11 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3675gp_slot2_Slot_gp_slot2_get (insn) == 0) + return OPCODE_ADD16; + if (Field_dsp340050b49a6c_fld2372gp_slot2_Slot_gp_slot2_get (insn) == 15 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3669gp_slot2_Slot_gp_slot2_get (insn) == 0) + return OPCODE_LUT_WRITE; + if (Field_dsp340050b49a6c_fld2373gp_slot2_Slot_gp_slot2_get (insn) == 0 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 2) + return OPCODE_MOVCND_5; + if (Field_dsp340050b49a6c_fld2374gp_slot2_Slot_gp_slot2_get (insn) == 1 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 2) + return OPCODE_MOVCND_6; + if (Field_dsp340050b49a6c_fld2375gp_slot2_Slot_gp_slot2_get (insn) == 2 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 2) + return OPCODE_MOVCND_7; + if (Field_dsp340050b49a6c_fld2376gp_slot2_Slot_gp_slot2_get (insn) == 12 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld2313_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVCM2PQ; + if (Field_dsp340050b49a6c_fld2378gp_slot2_Slot_gp_slot2_get (insn) == 13 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3676gp_slot2_Slot_gp_slot2_get (insn) == 0) + return OPCODE_ARGMAX8; + if (Field_dsp340050b49a6c_fld2379gp_slot2_Slot_gp_slot2_get (insn) == 7 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3673gp_slot2_Slot_gp_slot2_get (insn) == 0) + return OPCODE_PUSH128; + if (Field_dsp340050b49a6c_fld2381gp_slot2_Slot_gp_slot2_get (insn) == 1 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3666_Slot_gp_slot2_get (insn) == 0) + return OPCODE_PERM; + if (Field_dsp340050b49a6c_fld2383gp_slot2_Slot_gp_slot2_get (insn) == 1 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3678gp_slot2_Slot_gp_slot2_get (insn) == 0) + return OPCODE_ASLM32; + if (Field_dsp340050b49a6c_fld2385gp_slot2_Slot_gp_slot2_get (insn) == 8 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld2313_Slot_gp_slot2_get (insn) == 0) + return OPCODE_SUBCM; + if (Field_dsp340050b49a6c_fld2387gp_slot2_Slot_gp_slot2_get (insn) == 9 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld2313_Slot_gp_slot2_get (insn) == 0) + return OPCODE_SUBMEAN; + if (Field_dsp340050b49a6c_fld2388gp_slot2_Slot_gp_slot2_get (insn) == 5 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3679gp_slot2_Slot_gp_slot2_get (insn) == 0) + return OPCODE_SUBWRP; + if (Field_dsp340050b49a6c_fld2389gp_slot2_Slot_gp_slot2_get (insn) == 3 && + Field_op0_s3_Slot_gp_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3680gp_slot2_Slot_gp_slot2_get (insn) == 0) + return OPCODE_XOR128; + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 3) + return OPCODE_EXTUI; + switch (Field_sae_Slot_gp_slot2_get (insn)) + { + case 0: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_ADD; + break; + case 1: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_ADDI_N; + break; + case 2: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_AND; + break; + case 3: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVGEZ; + break; + case 4: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_LUT_AR; + break; + case 5: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVLTZ; + break; + case 6: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVNEZ; + break; + case 7: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_OR; + break; + case 8: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_MOVEQZ; + break; + case 9: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_SUB; + break; + case 10: + if (Field_op0_s3_Slot_gp_slot2_get (insn) == 0) + return OPCODE_XOR; + break; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_gp_slot0_decode (const xtensa_insnbuf insn) +{ + if (Field_dsp340050b49a6c_fld2407gp_slot0_Slot_gp_slot0_get (insn) == 0 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_LAC2X32; + if (Field_dsp340050b49a6c_fld2409gp_slot0_Slot_gp_slot0_get (insn) == 1 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_LAC32_R; + if (Field_dsp340050b49a6c_fld2410gp_slot0_Slot_gp_slot0_get (insn) == 2 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_LAC_IH; + if (Field_dsp340050b49a6c_fld2411gp_slot0_Slot_gp_slot0_get (insn) == 3 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_LAC_RH; + if (Field_dsp340050b49a6c_fld2412gp_slot0_Slot_gp_slot0_get (insn) == 10 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_LAC_RL; + if (Field_dsp340050b49a6c_fld2413gp_slot0_Slot_gp_slot0_get (insn) == 11 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_LAC2X64_0; + if (Field_dsp340050b49a6c_fld2415gp_slot0_Slot_gp_slot0_get (insn) == 27 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_LAC2X64_1; + if (Field_dsp340050b49a6c_fld2416gp_slot0_Slot_gp_slot0_get (insn) == 4 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_LAC_IL; + if (Field_dsp340050b49a6c_fld2417gp_slot0_Slot_gp_slot0_get (insn) == 5 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_LAC2X64_2; + switch (Field_dsp340050b49a6c_fld2418gp_slot0_Slot_gp_slot0_get (insn)) + { + case 21: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_AR2CM_DUP; + break; + case 53: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_MOV_N; + break; + case 85: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_NSA; + break; + case 117: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_PUSH32; + break; + case 149: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_NSAU; + break; + } + if (Field_dsp340050b49a6c_fld2419gp_slot0_Slot_gp_slot0_get (insn) == 362 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_GET_LLR_BUF; + if (Field_dsp340050b49a6c_fld2420gp_slot0_Slot_gp_slot0_get (insn) == 1452 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_ANY8; + if (Field_dsp340050b49a6c_fld2422gp_slot0_Slot_gp_slot0_get (insn) == 1453 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_GET_SMOD_BUF; + if (Field_dsp340050b49a6c_fld2423gp_slot0_Slot_gp_slot0_get (insn) == 2908 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_CLRCM; + if (Field_dsp340050b49a6c_fld2424gp_slot0_Slot_gp_slot0_get (insn) == 2909 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_GET_HSAR; + if (Field_dsp340050b49a6c_fld2425gp_slot0_Slot_gp_slot0_get (insn) == 2910 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_GET_HSAR2SAR; + if (Field_dsp340050b49a6c_fld2426gp_slot0_Slot_gp_slot0_get (insn) == 2911 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_GET_SAR; + if (Field_dsp340050b49a6c_fld2427gp_slot0_Slot_gp_slot0_get (insn) == 852 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_ANY4; + if (Field_dsp340050b49a6c_fld2429gp_slot0_Slot_gp_slot0_get (insn) == 3412 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_GET_SMOD_OFFSET_TABLE; + if (Field_dsp340050b49a6c_fld2430gp_slot0_Slot_gp_slot0_get (insn) == 3413 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_POP128_1; + if (Field_dsp340050b49a6c_fld2431gp_slot0_Slot_gp_slot0_get (insn) == 3414 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_POP128_2; + if (Field_dsp340050b49a6c_fld2432gp_slot0_Slot_gp_slot0_get (insn) == 3415 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_POP128_3; + if (Field_dsp340050b49a6c_fld2433gp_slot0_Slot_gp_slot0_get (insn) == 3416 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_POP128_0; + if (Field_dsp340050b49a6c_fld2434gp_slot0_Slot_gp_slot0_get (insn) == 3417 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_POP128_4; + if (Field_dsp340050b49a6c_fld2435gp_slot0_Slot_gp_slot0_get (insn) == 1709 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_s8_Slot_gp_slot0_get (insn) == 0) + return OPCODE_POP128_5; + if (Field_dsp340050b49a6c_fld2436gp_slot0_Slot_gp_slot0_get (insn) == 855 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3690gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_NOP; + if (Field_dsp340050b49a6c_fld2437gp_slot0_Slot_gp_slot0_get (insn) == 1960 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SSAI; + switch (Field_dsp340050b49a6c_fld2438gp_slot0_Slot_gp_slot0_get (insn)) + { + case 3922: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SET_LLR_POS; + break; + case 3923: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SET_PHASOR_OFFSET; + break; + case 3924: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SET_PERM_REG; + break; + case 3925: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SET_SCALE_REG; + break; + case 3926: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SET_SMOD_POS; + break; + case 3927: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SET_SOV; + break; + case 3928: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SET_PHASOR_N; + break; + case 3929: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SET_WGHT; + break; + case 3930: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SSA8B; + break; + case 3931: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SSL; + break; + case 3932: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SSA8L; + break; + case 3933: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SSR; + break; + } + if (Field_dsp340050b49a6c_fld2439gp_slot0_Slot_gp_slot0_get (insn) == 3934 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3695gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_CLRAC; + if (Field_dsp340050b49a6c_fld2440gp_slot0_Slot_gp_slot0_get (insn) == 3935 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3695gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_POP16LLR_1; + if (Field_dsp340050b49a6c_fld2441gp_slot0_Slot_gp_slot0_get (insn) == 3 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3693gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_LAC2X64_3; + switch (Field_dsp340050b49a6c_fld2443gp_slot0_Slot_gp_slot0_get (insn)) + { + case 3: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_AR2CM_LN; + break; + case 7: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_AR2CM_LN_I; + break; + } + if (Field_dsp340050b49a6c_fld2444gp_slot0_Slot_gp_slot0_get (insn) == 7 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld2067_Slot_gp_slot0_get (insn) == 0) + return OPCODE_AR2CM_LN_R; + switch (Field_dsp340050b49a6c_fld2445_Slot_gp_slot0_get (insn)) + { + case 0: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_SAC2X32; + break; + case 1: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_SAC32_R; + break; + case 2: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_SCM_PINC; + break; + case 3: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_SRAI; + break; + case 4: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_SCM_U; + break; + case 8: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_SLLI; + break; + } + if (Field_dsp340050b49a6c_fld2447gp_slot0_Slot_gp_slot0_get (insn) == 7 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3688gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_BEQZ_N; + if (Field_dsp340050b49a6c_fld2448_Slot_gp_slot0_get (insn) == 7 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3703gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_ASLACM; + if (Field_dsp340050b49a6c_fld2449gp_slot0_Slot_gp_slot0_get (insn) == 7 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3689gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_BNEZ_N; + if (Field_dsp340050b49a6c_fld2451gp_slot0_Slot_gp_slot0_get (insn) == 8 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_LCM_PINC; + if (Field_dsp340050b49a6c_fld2452gp_slot0_Slot_gp_slot0_get (insn) == 9 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_LCM_U; + if (Field_dsp340050b49a6c_fld2453gp_slot0_Slot_gp_slot0_get (insn) == 18 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_LCM; + if (Field_dsp340050b49a6c_fld2454gp_slot0_Slot_gp_slot0_get (insn) == 259 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_ABS; + if (Field_dsp340050b49a6c_fld2455gp_slot0_Slot_gp_slot0_get (insn) == 267 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_MOVCM; + if (Field_dsp340050b49a6c_fld2456gp_slot0_Slot_gp_slot0_get (insn) == 291 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_MOV_I; + if (Field_dsp340050b49a6c_fld2457gp_slot0_Slot_gp_slot0_get (insn) == 299 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_NEGCM; + if (Field_dsp340050b49a6c_fld2458gp_slot0_Slot_gp_slot0_get (insn) == 323 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_MOV_R; + if (Field_dsp340050b49a6c_fld2459gp_slot0_Slot_gp_slot0_get (insn) == 331 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SRA; + if (Field_dsp340050b49a6c_fld2460gp_slot0_Slot_gp_slot0_get (insn) == 355 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SRL; + if (Field_dsp340050b49a6c_fld2461gp_slot0_Slot_gp_slot0_get (insn) == 715 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_CLB_C; + switch (Field_dsp340050b49a6c_fld2462_Slot_gp_slot0_get (insn)) + { + case 21: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_EXT; + break; + case 23: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_EXT_R; + break; + case 33: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_MOVI_N; + break; + case 35: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_PUSH128_M; + break; + case 46: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SAC2X64_0; + break; + case 47: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SAC2X64_1; + break; + case 50: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SAC2X64_2; + break; + case 52: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SAC2X64_3; + break; + } + if (Field_dsp340050b49a6c_fld2463gp_slot0_Slot_gp_slot0_get (insn) == 731 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_CLB_R; + if (Field_dsp340050b49a6c_fld2464gp_slot0_Slot_gp_slot0_get (insn) == 387 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_NEG; + if (Field_dsp340050b49a6c_fld2465gp_slot0_Slot_gp_slot0_get (insn) == 779 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_MINCLB_C; + if (Field_dsp340050b49a6c_fld2466gp_slot0_Slot_gp_slot0_get (insn) == 795 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SMINCLB_R; + if (Field_dsp340050b49a6c_fld2467gp_slot0_Slot_gp_slot0_get (insn) == 835 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_MINCLB_R; + if (Field_dsp340050b49a6c_fld2468gp_slot0_Slot_gp_slot0_get (insn) == 13571 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_ADDAC_I2R; + if (Field_dsp340050b49a6c_fld2470gp_slot0_Slot_gp_slot0_get (insn) == 13587 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_ADDAC_R2I; + if (Field_dsp340050b49a6c_fld2471gp_slot0_Slot_gp_slot0_get (insn) == 13603 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_REDAC; + if (Field_dsp340050b49a6c_fld2472gp_slot0_Slot_gp_slot0_get (insn) == 13619 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_REDACS; + if (Field_dsp340050b49a6c_fld2473gp_slot0_Slot_gp_slot0_get (insn) == 13635 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_REDAC2; + if (Field_dsp340050b49a6c_fld2474gp_slot0_Slot_gp_slot0_get (insn) == 13651 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SUBAC_I2R; + if (Field_dsp340050b49a6c_fld2475gp_slot0_Slot_gp_slot0_get (insn) == 6835 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3695gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SUBAC_R2I; + if (Field_dsp340050b49a6c_fld2477gp_slot0_Slot_gp_slot0_get (insn) == 1715 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3705gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_REDAC4; + if (Field_dsp340050b49a6c_fld2479gp_slot0_Slot_gp_slot0_get (insn) == 6667 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_GET_INTERP_EXT_L; + if (Field_dsp340050b49a6c_fld2480gp_slot0_Slot_gp_slot0_get (insn) == 6683 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_GET_INTERP_EXT_N; + if (Field_dsp340050b49a6c_fld2481gp_slot0_Slot_gp_slot0_get (insn) == 6699 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_GET_LLR_POS; + if (Field_dsp340050b49a6c_fld2482gp_slot0_Slot_gp_slot0_get (insn) == 6715 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_GET_PHASOR_OFFSET; + if (Field_dsp340050b49a6c_fld2483gp_slot0_Slot_gp_slot0_get (insn) == 6731 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_GET_PERM_REG; + if (Field_dsp340050b49a6c_fld2484gp_slot0_Slot_gp_slot0_get (insn) == 6747 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_GET_SCALE_REG; + if (Field_dsp340050b49a6c_fld2485gp_slot0_Slot_gp_slot0_get (insn) == 6763 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_GET_SMOD_POS; + if (Field_dsp340050b49a6c_fld2486gp_slot0_Slot_gp_slot0_get (insn) == 6779 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_GET_SOV; + if (Field_dsp340050b49a6c_fld2487gp_slot0_Slot_gp_slot0_get (insn) == 6795 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_GET_PHASOR_N; + if (Field_dsp340050b49a6c_fld2488gp_slot0_Slot_gp_slot0_get (insn) == 6811 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_GET_WGHT; + if (Field_dsp340050b49a6c_fld2489gp_slot0_Slot_gp_slot0_get (insn) == 6827 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_POP32_0; + if (Field_dsp340050b49a6c_fld2490gp_slot0_Slot_gp_slot0_get (insn) == 6843 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_POP32_2; + if (Field_dsp340050b49a6c_fld2491gp_slot0_Slot_gp_slot0_get (insn) == 6859 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_POP32_1; + if (Field_dsp340050b49a6c_fld2492gp_slot0_Slot_gp_slot0_get (insn) == 6875 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_POP32_3; + if (Field_dsp340050b49a6c_fld2493gp_slot0_Slot_gp_slot0_get (insn) == 6891 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SET_SAR; + if (Field_dsp340050b49a6c_fld2494gp_slot0_Slot_gp_slot0_get (insn) == 6907 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SET_SMOD_OFFSET_TABLE; + if (Field_dsp340050b49a6c_fld2495gp_slot0_Slot_gp_slot0_get (insn) == 115 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3706gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SMINCLB_C; + if (Field_dsp340050b49a6c_fld2496gp_slot0_Slot_gp_slot0_get (insn) == 137 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_s8_Slot_gp_slot0_get (insn) == 0) + return OPCODE_CONJ; + if (Field_dsp340050b49a6c_fld2497gp_slot0_Slot_gp_slot0_get (insn) == 277 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_EXT32_I; + if (Field_dsp340050b49a6c_fld2498gp_slot0_Slot_gp_slot0_get (insn) == 285 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_EXT_2FIFO_2; + if (Field_dsp340050b49a6c_fld2499gp_slot0_Slot_gp_slot0_get (insn) == 305 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_EXT32_R; + if (Field_dsp340050b49a6c_fld2500gp_slot0_Slot_gp_slot0_get (insn) == 309 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_EXT_2FIFO_3; + if (Field_dsp340050b49a6c_fld2501gp_slot0_Slot_gp_slot0_get (insn) == 313 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_EXT_R2FIFO_0; + if (Field_dsp340050b49a6c_fld2502gp_slot0_Slot_gp_slot0_get (insn) == 317 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_EXT_R2FIFO_1; + if (Field_dsp340050b49a6c_fld2503gp_slot0_Slot_gp_slot0_get (insn) == 337 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_EXT_2FIFO_0; + if (Field_dsp340050b49a6c_fld2504gp_slot0_Slot_gp_slot0_get (insn) == 341 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0) + return OPCODE_EXT_R2FIFO_2; + if (Field_dsp340050b49a6c_fld2505gp_slot0_Slot_gp_slot0_get (insn) == 173 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld2036_Slot_gp_slot0_get (insn) == 0) + return OPCODE_EXT_R2FIFO_3; + if (Field_dsp340050b49a6c_fld2506gp_slot0_Slot_gp_slot0_get (insn) == 93 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3692gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SET_SMOD_BUF; + if (Field_dsp340050b49a6c_fld2507gp_slot0_Slot_gp_slot0_get (insn) == 29 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3700gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_EXT_2FIFO_1; + if (Field_dsp340050b49a6c_fld2508gp_slot0_Slot_gp_slot0_get (insn) == 9 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld2058_Slot_gp_slot0_get (insn) == 0) + return OPCODE_CM2AR_LN; + if (Field_dsp340050b49a6c_fld2509gp_slot0_Slot_gp_slot0_get (insn) == 11 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld2058_Slot_gp_slot0_get (insn) == 0) + return OPCODE_CM2AR_LN_I; + if (Field_dsp340050b49a6c_fld2510gp_slot0_Slot_gp_slot0_get (insn) == 7 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3696gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_CM2AR_LN_R; + if (Field_dsp340050b49a6c_fld2512gp_slot0_Slot_gp_slot0_get (insn) == 6 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SAC_IL; + if (Field_dsp340050b49a6c_fld2514gp_slot0_Slot_gp_slot0_get (insn) == 7 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SAC_RH; + if (Field_dsp340050b49a6c_fld2515gp_slot0_Slot_gp_slot0_get (insn) == 10 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SAC_RL; + if (Field_dsp340050b49a6c_fld2516gp_slot0_Slot_gp_slot0_get (insn) == 16 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SAC_IH; + if (Field_dsp340050b49a6c_fld2517gp_slot0_Slot_gp_slot0_get (insn) == 204 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_POP128_2M_0; + if (Field_dsp340050b49a6c_fld2518gp_slot0_Slot_gp_slot0_get (insn) == 205 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_POP128_2M_1; + if (Field_dsp340050b49a6c_fld2519gp_slot0_Slot_gp_slot0_get (insn) == 206 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_POP128_2M_2; + if (Field_dsp340050b49a6c_fld2520gp_slot0_Slot_gp_slot0_get (insn) == 207 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_POP128_2M_3; + if (Field_dsp340050b49a6c_fld2521gp_slot0_Slot_gp_slot0_get (insn) == 212 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld2530_Slot_gp_slot0_get (insn) == 0) + return OPCODE_ASRAC; + if (Field_dsp340050b49a6c_fld2523gp_slot0_Slot_gp_slot0_get (insn) == 213 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3698gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_MOVAC; + if (Field_dsp340050b49a6c_fld2524gp_slot0_Slot_gp_slot0_get (insn) == 107 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3699gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SWAPAC_RI; + if (Field_dsp340050b49a6c_fld2526gp_slot0_Slot_gp_slot0_get (insn) == 432 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SLL; + if (Field_dsp340050b49a6c_fld2527gp_slot0_Slot_gp_slot0_get (insn) == 433 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld2036_Slot_gp_slot0_get (insn) == 0) + return OPCODE_MOV2AC32_I; + if (Field_dsp340050b49a6c_fld2528gp_slot0_Slot_gp_slot0_get (insn) == 217 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3697gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_MOV2AC32_R; + if (Field_dsp340050b49a6c_fld2529gp_slot0_Slot_gp_slot0_get (insn) == 109 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3702gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_PUSH128; + if (Field_dsp340050b49a6c_fld2531gp_slot0_Slot_gp_slot0_get (insn) == 55 && + Field_op0_s5_Slot_gp_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3691gp_slot0_Slot_gp_slot0_get (insn) == 0) + return OPCODE_SET_LLR_BUF; + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 3) + return OPCODE_EXTUI; + switch (Field_sae_Slot_gp_slot0_get (insn)) + { + case 0: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_MOVNEZ; + break; + case 1: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_MOVT; + break; + case 2: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_OR; + break; + case 3: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SCM; + break; + case 4: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_ORB; + break; + case 5: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SCM_PINC_X; + break; + case 8: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_S32I_N; + break; + case 9: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SCM_XU; + break; + case 10: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_ADD; + break; + case 11: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_ADDX2; + break; + case 12: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_ADDI_N; + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SCM_X; + break; + case 13: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_ADDX4; + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SEXT; + break; + case 14: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_ADDX8; + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SRC; + break; + case 15: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_AND; + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SRLI; + break; + case 18: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SUB; + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_ANDB; + break; + case 19: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_L32I_N; + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SUBX8; + break; + case 20: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SUBX2; + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_CLAMPS; + break; + case 21: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_XOR; + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_LCM_PINC_X; + break; + case 22: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_XORB; + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_LCM_X; + break; + case 23: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_LCM_XU; + break; + case 24: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 2) + return OPCODE_SUBX4; + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_COMB_AR; + break; + case 25: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_MAX; + break; + case 26: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_MAXU; + break; + case 27: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_MINU; + break; + case 28: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_MIN; + break; + case 29: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_MOVEQZ; + break; + case 30: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_MOVGEZ; + break; + case 31: + if (Field_op0_s5_Slot_gp_slot0_get (insn) == 1) + return OPCODE_MOVLTZ; + break; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_dot_slot0_decode (const xtensa_insnbuf insn) +{ + switch (Field_dsp340050b49a6c_fld2068_Slot_dot_slot0_get (insn)) + { + case 0: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 0) + return OPCODE_ADD; + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 5) + return OPCODE_SUB; + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 1) + return OPCODE_AND; + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 3) + return OPCODE_OR; + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 2) + return OPCODE_LCM_X; + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 4) + return OPCODE_SCM_X; + break; + case 1: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 0) + return OPCODE_ADDI_N; + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 5) + return OPCODE_XOR; + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 1) + return OPCODE_LCM; + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 2) + return OPCODE_LCM_XU; + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 3) + return OPCODE_SCM; + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 4) + return OPCODE_SCM_XU; + break; + } + switch (Field_dsp340050b49a6c_fld2666dot_slot0_Slot_dot_slot0_get (insn)) + { + case 0: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 6) + return OPCODE_EXT; + break; + case 1: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 6) + return OPCODE_EXT_R; + break; + case 2: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 6) + return OPCODE_MOVI_N; + break; + } + if (Field_dsp340050b49a6c_fld2667dot_slot0_Slot_dot_slot0_get (insn) == 6 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 6) + return OPCODE_AR2CM_LN; + switch (Field_dsp340050b49a6c_fld2668dot_slot0_Slot_dot_slot0_get (insn)) + { + case 16: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_EXT_2FIFO_1; + break; + case 17: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_EXT_2FIFO_2; + break; + case 18: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_EXT_2FIFO_3; + break; + case 19: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_EXT_R2FIFO_2; + break; + case 20: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_EXT_R2FIFO_0; + break; + case 21: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_EXT_R2FIFO_3; + break; + case 22: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_MOV_N; + break; + case 23: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_PUSH32; + break; + case 24: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_EXT_R2FIFO_1; + break; + case 27: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 7 && + Field_dsp340050b49a6c_fld2047_Slot_dot_slot0_get (insn) == 0) + return OPCODE_SMINCLB_R; + break; + case 28: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 6) + return OPCODE_AR2CM_DUP; + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 7 && + Field_dsp340050b49a6c_fld2047_Slot_dot_slot0_get (insn) == 0) + return OPCODE_MINCLB_C; + break; + case 29: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 7 && + Field_t_Slot_dot_slot0_get (insn) == 0) + return OPCODE_SET_PERM_REG; + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 6) + return OPCODE_EXT32_I; + break; + case 30: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 6) + return OPCODE_EXT32_R; + break; + case 31: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 6) + return OPCODE_EXT_2FIFO_0; + break; + } + if (Field_dsp340050b49a6c_fld2669dot_slot0_Slot_dot_slot0_get (insn) == 0 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_CM2AR_LN; + if (Field_dsp340050b49a6c_fld2671dot_slot0_Slot_dot_slot0_get (insn) == 4 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_CONJ; + if (Field_dsp340050b49a6c_fld2672dot_slot0_Slot_dot_slot0_get (insn) == 5 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_MOV_I; + if (Field_dsp340050b49a6c_fld2673dot_slot0_Slot_dot_slot0_get (insn) == 6 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_MOV_R; + if (Field_dsp340050b49a6c_fld2674dot_slot0_Slot_dot_slot0_get (insn) == 7 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_NEG; + if (Field_dsp340050b49a6c_fld2675dot_slot0_Slot_dot_slot0_get (insn) == 8 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_MOVCM; + if (Field_dsp340050b49a6c_fld2676dot_slot0_Slot_dot_slot0_get (insn) == 9 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_NEGCM; + if (Field_dsp340050b49a6c_fld2677dot_slot0_Slot_dot_slot0_get (insn) == 10 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_SRA; + if (Field_dsp340050b49a6c_fld2678dot_slot0_Slot_dot_slot0_get (insn) == 11 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_GET_HSAR; + if (Field_dsp340050b49a6c_fld2679dot_slot0_Slot_dot_slot0_get (insn) == 27 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_GET_HSAR2SAR; + if (Field_dsp340050b49a6c_fld2680dot_slot0_Slot_dot_slot0_get (insn) == 43 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_GET_SAR; + if (Field_dsp340050b49a6c_fld2681dot_slot0_Slot_dot_slot0_get (insn) == 59 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_POP128_2; + if (Field_dsp340050b49a6c_fld2682dot_slot0_Slot_dot_slot0_get (insn) == 75 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_POP128_0; + if (Field_dsp340050b49a6c_fld2683dot_slot0_Slot_dot_slot0_get (insn) == 91 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_POP128_3; + if (Field_dsp340050b49a6c_fld2684dot_slot0_Slot_dot_slot0_get (insn) == 107 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_POP128_4; + if (Field_dsp340050b49a6c_fld2685dot_slot0_Slot_dot_slot0_get (insn) == 123 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_POP128_5; + if (Field_dsp340050b49a6c_fld2686dot_slot0_Slot_dot_slot0_get (insn) == 43 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7 && + Field_dsp340050b49a6c_fld3736_Slot_dot_slot0_get (insn) == 0) + return OPCODE_POP128_1; + if (Field_dsp340050b49a6c_fld2688dot_slot0_Slot_dot_slot0_get (insn) == 59 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7 && + Field_dsp340050b49a6c_fld3735dot_slot0_Slot_dot_slot0_get (insn) == 0) + return OPCODE_NOP; + if (Field_dsp340050b49a6c_fld2689dot_slot0_Slot_dot_slot0_get (insn) == 12 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7 && + Field_r_Slot_dot_slot0_get (insn) == 0) + return OPCODE_CLRCM; + if (Field_dsp340050b49a6c_fld2690dot_slot0_Slot_dot_slot0_get (insn) == 13 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_GET_PERM_REG; + if (Field_dsp340050b49a6c_fld2692dot_slot0_Slot_dot_slot0_get (insn) == 29 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_POP32_1; + if (Field_dsp340050b49a6c_fld2693dot_slot0_Slot_dot_slot0_get (insn) == 29 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7 && + Field_dsp340050b49a6c_fld2705dot_slot0_Slot_dot_slot0_get (insn) == 0) + return OPCODE_POP32_2; + if (Field_dsp340050b49a6c_fld2695dot_slot0_Slot_dot_slot0_get (insn) == 29 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7 && + Field_dsp340050b49a6c_fld3741dot_slot0_Slot_dot_slot0_get (insn) == 0) + return OPCODE_POP32_3; + if (Field_dsp340050b49a6c_fld2697dot_slot0_Slot_dot_slot0_get (insn) == 29 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7 && + Field_dsp340050b49a6c_fld3738dot_slot0_Slot_dot_slot0_get (insn) == 0) + return OPCODE_SET_SAR; + if (Field_dsp340050b49a6c_fld2699dot_slot0_Slot_dot_slot0_get (insn) == 7 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7 && + Field_dsp340050b49a6c_fld3740dot_slot0_Slot_dot_slot0_get (insn) == 0) + return OPCODE_POP32_0; + if (Field_dsp340050b49a6c_fld2700dot_slot0_Slot_dot_slot0_get (insn) == 50 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_CLB_C; + if (Field_dsp340050b49a6c_fld2701dot_slot0_Slot_dot_slot0_get (insn) == 51 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_MINCLB_R; + if (Field_dsp340050b49a6c_fld2702dot_slot0_Slot_dot_slot0_get (insn) == 52 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_CLB_R; + if (Field_dsp340050b49a6c_fld2703dot_slot0_Slot_dot_slot0_get (insn) == 53 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7) + return OPCODE_SMINCLB_C; + if (Field_dsp340050b49a6c_fld2704dot_slot0_Slot_dot_slot0_get (insn) == 15 && + Field_op0_s8_Slot_dot_slot0_get (insn) == 7 && + Field_dsp340050b49a6c_fld3739dot_slot0_Slot_dot_slot0_get (insn) == 0) + return OPCODE_CLRAC; + switch (Field_dsp340050b49a6c_fld2705dot_slot0_Slot_dot_slot0_get (insn)) + { + case 0: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 8 && + Field_dsp340050b49a6c_fld3737dot_slot0_Slot_dot_slot0_get (insn) == 0) + return OPCODE_SLL; + break; + case 1: + if (Field_op0_s8_Slot_dot_slot0_get (insn) == 8 && + Field_dsp340050b49a6c_fld3742dot_slot0_Slot_dot_slot0_get (insn) == 0) + return OPCODE_PUSH128; + break; + } + switch (Field_op0_s8_Slot_dot_slot0_get (insn)) + { + case 9: + return OPCODE_LCM_U; + case 10: + return OPCODE_SCM_U; + case 11: + return OPCODE_SLLI; + case 12: + return OPCODE_SRAI; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_pq_slot2_decode (const xtensa_insnbuf insn) +{ + switch (Field_dsp340050b49a6c_fld2706pq_slot2_Slot_pq_slot2_get (insn)) + { + case 44: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_AR2CM_LN; + break; + case 47: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3752pq_slot2_Slot_pq_slot2_get (insn) == 0) + return OPCODE_CLRTIEP; + break; + } + switch (Field_dsp340050b49a6c_fld2707pq_slot2_Slot_pq_slot2_get (insn)) + { + case 180: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_ADDAR2; + break; + case 181: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_PUSH128_PQ; + break; + case 182: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_PUSH32; + break; + case 183: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_SET_EXT_REGS; + break; + case 184: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MOV_N; + break; + case 185: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_SUBARX; + break; + case 186: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_WRTIEP; + break; + } + switch (Field_dsp340050b49a6c_fld2708pq_slot2_Slot_pq_slot2_get (insn)) + { + case 1496: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_SETTIEP; + break; + case 1497: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_WRTBSIGQM; + break; + } + switch (Field_dsp340050b49a6c_fld2709pq_slot2_Slot_pq_slot2_get (insn)) + { + case 2996: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_AR2SAR_DUP; + break; + case 2997: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_WRTSIGQ; + break; + case 2999: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0 && + Field_s_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_5; + break; + } + switch (Field_dsp340050b49a6c_fld2710pq_slot2_Slot_pq_slot2_get (insn)) + { + case 47968: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_0; + break; + case 47969: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_1; + break; + case 47970: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_2; + break; + case 47971: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_0; + break; + case 47972: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_3; + break; + case 47973: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_1; + break; + case 47974: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_2; + break; + case 47975: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_3; + break; + } + if (Field_dsp340050b49a6c_fld2711pq_slot2_Slot_pq_slot2_get (insn) == 11994 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3745pq_slot2_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_4; + if (Field_dsp340050b49a6c_fld2713pq_slot2_Slot_pq_slot2_get (insn) == 11995 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3745pq_slot2_Slot_pq_slot2_get (insn) == 0) + return OPCODE_NOP; + if (Field_dsp340050b49a6c_fld2714pq_slot2_Slot_pq_slot2_get (insn) == 375 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2819_Slot_pq_slot2_get (insn) == 0) + return OPCODE_WRTBSIGQ; + if (Field_dsp340050b49a6c_fld2715pq_slot2_Slot_pq_slot2_get (insn) == 52 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_CM2AR_LN; + if (Field_dsp340050b49a6c_fld2717pq_slot2_Slot_pq_slot2_get (insn) == 212 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_ABS; + if (Field_dsp340050b49a6c_fld2718pq_slot2_Slot_pq_slot2_get (insn) == 213 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_SRA; + if (Field_dsp340050b49a6c_fld2719pq_slot2_Slot_pq_slot2_get (insn) == 3334 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_CLRCM; + if (Field_dsp340050b49a6c_fld2721pq_slot2_Slot_pq_slot2_get (insn) == 3335 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_GET_ARGMAX; + if (Field_dsp340050b49a6c_fld2722pq_slot2_Slot_pq_slot2_get (insn) == 3350 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_GET_HSAR; + if (Field_dsp340050b49a6c_fld2723pq_slot2_Slot_pq_slot2_get (insn) == 3351 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_GET_SAR; + if (Field_dsp340050b49a6c_fld2724pq_slot2_Slot_pq_slot2_get (insn) == 3366 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_GET_HSAR2SAR; + if (Field_dsp340050b49a6c_fld2725pq_slot2_Slot_pq_slot2_get (insn) == 3367 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_POP128_0; + if (Field_dsp340050b49a6c_fld2726pq_slot2_Slot_pq_slot2_get (insn) == 3382 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_POP128_1; + if (Field_dsp340050b49a6c_fld2727pq_slot2_Slot_pq_slot2_get (insn) == 3383 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_POP128_2; + if (Field_dsp340050b49a6c_fld2728pq_slot2_Slot_pq_slot2_get (insn) == 3398 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_GET_MAX; + if (Field_dsp340050b49a6c_fld2729pq_slot2_Slot_pq_slot2_get (insn) == 3399 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_POP128_3; + if (Field_dsp340050b49a6c_fld2730pq_slot2_Slot_pq_slot2_get (insn) == 3414 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_POP128_4; + if (Field_dsp340050b49a6c_fld2731pq_slot2_Slot_pq_slot2_get (insn) == 3415 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_POP32_0; + if (Field_dsp340050b49a6c_fld2732pq_slot2_Slot_pq_slot2_get (insn) == 3430 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_POP128_5; + if (Field_dsp340050b49a6c_fld2733pq_slot2_Slot_pq_slot2_get (insn) == 3431 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_POP32_1; + if (Field_dsp340050b49a6c_fld2734pq_slot2_Slot_pq_slot2_get (insn) == 3446 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_POP32_2; + if (Field_dsp340050b49a6c_fld2735pq_slot2_Slot_pq_slot2_get (insn) == 3447 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_POP32_3; + if (Field_dsp340050b49a6c_fld2736pq_slot2_Slot_pq_slot2_get (insn) == 438 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2819_Slot_pq_slot2_get (insn) == 0) + return OPCODE_GET_NCO; + if (Field_dsp340050b49a6c_fld2738pq_slot2_Slot_pq_slot2_get (insn) == 439 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2819_Slot_pq_slot2_get (insn) == 0) + return OPCODE_RDTIEP; + if (Field_dsp340050b49a6c_fld2739pq_slot2_Slot_pq_slot2_get (insn) == 27 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3744pq_slot2_Slot_pq_slot2_get (insn) == 0) + return OPCODE_NEG; + if (Field_dsp340050b49a6c_fld2741pq_slot2_Slot_pq_slot2_get (insn) == 112 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_PQ2CM; + if (Field_dsp340050b49a6c_fld2742pq_slot2_Slot_pq_slot2_get (insn) == 113 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_QREADY; + if (Field_dsp340050b49a6c_fld2743pq_slot2_Slot_pq_slot2_get (insn) == 114 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3750pq_slot2_Slot_pq_slot2_get (insn) == 0) + return OPCODE_AR2CM_DUP; + if (Field_dsp340050b49a6c_fld2746pq_slot2_Slot_pq_slot2_get (insn) == 115 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3750pq_slot2_Slot_pq_slot2_get (insn) == 0) + return OPCODE_SWAPB; + if (Field_dsp340050b49a6c_fld2747pq_slot2_Slot_pq_slot2_get (insn) == 29 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2819_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MOVAR2; + if (Field_dsp340050b49a6c_fld2748pq_slot2_Slot_pq_slot2_get (insn) == 16 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_ADD32; + if (Field_dsp340050b49a6c_fld2750pq_slot2_Slot_pq_slot2_get (insn) == 17 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_ADDCM; + if (Field_dsp340050b49a6c_fld2751pq_slot2_Slot_pq_slot2_get (insn) == 18 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_ADDWRP; + if (Field_dsp340050b49a6c_fld2752pq_slot2_Slot_pq_slot2_get (insn) == 19 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_ASR; + if (Field_dsp340050b49a6c_fld2753pq_slot2_Slot_pq_slot2_get (insn) == 20 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_AND128; + if (Field_dsp340050b49a6c_fld2754pq_slot2_Slot_pq_slot2_get (insn) == 21 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_EXTUI4; + if (Field_dsp340050b49a6c_fld2755pq_slot2_Slot_pq_slot2_get (insn) == 22 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_LUT; + if (Field_dsp340050b49a6c_fld2756pq_slot2_Slot_pq_slot2_get (insn) == 23 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_LUT_IEXT; + if (Field_dsp340050b49a6c_fld2757pq_slot2_Slot_pq_slot2_get (insn) == 24 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_ASL; + if (Field_dsp340050b49a6c_fld2758pq_slot2_Slot_pq_slot2_get (insn) == 25 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_LUT_REXT; + if (Field_dsp340050b49a6c_fld2759pq_slot2_Slot_pq_slot2_get (insn) == 26 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MAX8; + if (Field_dsp340050b49a6c_fld2760pq_slot2_Slot_pq_slot2_get (insn) == 27 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MEAN32; + if (Field_dsp340050b49a6c_fld2761pq_slot2_Slot_pq_slot2_get (insn) == 28 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MEAN; + if (Field_dsp340050b49a6c_fld2762pq_slot2_Slot_pq_slot2_get (insn) == 29 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MIN8; + if (Field_dsp340050b49a6c_fld2763pq_slot2_Slot_pq_slot2_get (insn) == 30 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_OR128; + if (Field_dsp340050b49a6c_fld2764pq_slot2_Slot_pq_slot2_get (insn) == 31 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_SUB32; + if (Field_dsp340050b49a6c_fld2765pq_slot2_Slot_pq_slot2_get (insn) == 0 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_ASL32; + if (Field_dsp340050b49a6c_fld2766pq_slot2_Slot_pq_slot2_get (insn) == 1 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_ASR32; + if (Field_dsp340050b49a6c_fld2767pq_slot2_Slot_pq_slot2_get (insn) == 2 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_MOVCND8_0; + if (Field_dsp340050b49a6c_fld2768pq_slot2_Slot_pq_slot2_get (insn) == 3 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_MOVCND8_3; + if (Field_dsp340050b49a6c_fld2769pq_slot2_Slot_pq_slot2_get (insn) == 4 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_MOVCND8_1; + if (Field_dsp340050b49a6c_fld2770pq_slot2_Slot_pq_slot2_get (insn) == 5 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_MOVCND8_4; + if (Field_dsp340050b49a6c_fld2771pq_slot2_Slot_pq_slot2_get (insn) == 6 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_MOVCND8_5; + if (Field_dsp340050b49a6c_fld2772pq_slot2_Slot_pq_slot2_get (insn) == 7 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_MOVCND8_6; + if (Field_dsp340050b49a6c_fld2773pq_slot2_Slot_pq_slot2_get (insn) == 8 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_MOVCND8_2; + if (Field_dsp340050b49a6c_fld2774pq_slot2_Slot_pq_slot2_get (insn) == 9 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_MOVCND8_7; + if (Field_dsp340050b49a6c_fld2775pq_slot2_Slot_pq_slot2_get (insn) == 10 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_MOVCND_0; + if (Field_dsp340050b49a6c_fld2776pq_slot2_Slot_pq_slot2_get (insn) == 11 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_MOVCND_2; + if (Field_dsp340050b49a6c_fld2777pq_slot2_Slot_pq_slot2_get (insn) == 12 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_MOVCND_1; + if (Field_dsp340050b49a6c_fld2778pq_slot2_Slot_pq_slot2_get (insn) == 13 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_MOVCND_3; + if (Field_dsp340050b49a6c_fld2779pq_slot2_Slot_pq_slot2_get (insn) == 14 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_MOVCND_4; + if (Field_dsp340050b49a6c_fld2780pq_slot2_Slot_pq_slot2_get (insn) == 15 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_MOVCND_5; + if (Field_dsp340050b49a6c_fld2781pq_slot2_Slot_pq_slot2_get (insn) == 16 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_ASLM; + if (Field_dsp340050b49a6c_fld2782pq_slot2_Slot_pq_slot2_get (insn) == 17 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_ASRM; + if (Field_dsp340050b49a6c_fld2783pq_slot2_Slot_pq_slot2_get (insn) == 18 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_CMP8; + if (Field_dsp340050b49a6c_fld2784pq_slot2_Slot_pq_slot2_get (insn) == 19 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_LSLM; + if (Field_dsp340050b49a6c_fld2785pq_slot2_Slot_pq_slot2_get (insn) == 20 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_CMP_I; + if (Field_dsp340050b49a6c_fld2786pq_slot2_Slot_pq_slot2_get (insn) == 21 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_LSRM; + if (Field_dsp340050b49a6c_fld2787pq_slot2_Slot_pq_slot2_get (insn) == 262 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_ABS8; + if (Field_dsp340050b49a6c_fld2788pq_slot2_Slot_pq_slot2_get (insn) == 263 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_CONJ; + if (Field_dsp340050b49a6c_fld2789pq_slot2_Slot_pq_slot2_get (insn) == 278 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_LUT_PHASOR; + if (Field_dsp340050b49a6c_fld2790pq_slot2_Slot_pq_slot2_get (insn) == 279 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_NOT128; + if (Field_dsp340050b49a6c_fld2791pq_slot2_Slot_pq_slot2_get (insn) == 294 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_MOVCM; + if (Field_dsp340050b49a6c_fld2792pq_slot2_Slot_pq_slot2_get (insn) == 295 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1) + return OPCODE_TRANS; + if (Field_dsp340050b49a6c_fld2793pq_slot2_Slot_pq_slot2_get (insn) == 2102 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2817_Slot_pq_slot2_get (insn) == 0) + return OPCODE_SET_ARGMAX; + if (Field_dsp340050b49a6c_fld2795pq_slot2_Slot_pq_slot2_get (insn) == 2103 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2817_Slot_pq_slot2_get (insn) == 0) + return OPCODE_SET_HSAR; + if (Field_dsp340050b49a6c_fld2796pq_slot2_Slot_pq_slot2_get (insn) == 1179 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3746pq_slot2_Slot_pq_slot2_get (insn) == 0) + return OPCODE_SET_MAX; + if (Field_dsp340050b49a6c_fld2798pq_slot2_Slot_pq_slot2_get (insn) == 667 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3747pq_slot2_Slot_pq_slot2_get (insn) == 0) + return OPCODE_SET_NCO; + if (Field_dsp340050b49a6c_fld2801pq_slot2_Slot_pq_slot2_get (insn) == 411 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3749pq_slot2_Slot_pq_slot2_get (insn) == 0) + return OPCODE_SET_SAR; + if (Field_dsp340050b49a6c_fld2803pq_slot2_Slot_pq_slot2_get (insn) == 43 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3754pq_slot2_Slot_pq_slot2_get (insn) == 0) + return OPCODE_NCO_UPDATE; + if (Field_dsp340050b49a6c_fld2805pq_slot2_Slot_pq_slot2_get (insn) == 27 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3751pq_slot2_Slot_pq_slot2_get (insn) == 0) + return OPCODE_NEGCM; + if (Field_dsp340050b49a6c_fld2806pq_slot2_Slot_pq_slot2_get (insn) == 12 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2025_Slot_pq_slot2_get (insn) == 0) + return OPCODE_CMP_R; + if (Field_dsp340050b49a6c_fld2807pq_slot2_Slot_pq_slot2_get (insn) == 13 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3756pq_slot2_Slot_pq_slot2_get (insn) == 0) + return OPCODE_PUSH128; + if (Field_dsp340050b49a6c_fld2808pq_slot2_Slot_pq_slot2_get (insn) == 11 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3757pq_slot2_Slot_pq_slot2_get (insn) == 0) + return OPCODE_ADD16; + if (Field_dsp340050b49a6c_fld2809pq_slot2_Slot_pq_slot2_get (insn) == 15 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3753pq_slot2_Slot_pq_slot2_get (insn) == 0) + return OPCODE_LUT_WRITE; + if (Field_dsp340050b49a6c_fld2810pq_slot2_Slot_pq_slot2_get (insn) == 0 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 2) + return OPCODE_MOVCND_6; + if (Field_dsp340050b49a6c_fld2811pq_slot2_Slot_pq_slot2_get (insn) == 1 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 2) + return OPCODE_MOVCND_7; + if (Field_dsp340050b49a6c_fld2812pq_slot2_Slot_pq_slot2_get (insn) == 1 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3748_Slot_pq_slot2_get (insn) == 0) + return OPCODE_PERM; + if (Field_dsp340050b49a6c_fld2814pq_slot2_Slot_pq_slot2_get (insn) == 1 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3758pq_slot2_Slot_pq_slot2_get (insn) == 0) + return OPCODE_ASLM32; + if (Field_dsp340050b49a6c_fld2816pq_slot2_Slot_pq_slot2_get (insn) == 1 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 2 && + Field_imm7_Slot_pq_slot2_get (insn) == 0) + return OPCODE_ARGMAX8; + if (Field_dsp340050b49a6c_fld2818pq_slot2_Slot_pq_slot2_get (insn) == 8 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld2737_Slot_pq_slot2_get (insn) == 0) + return OPCODE_SUBCM; + if (Field_dsp340050b49a6c_fld2820pq_slot2_Slot_pq_slot2_get (insn) == 9 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld2737_Slot_pq_slot2_get (insn) == 0) + return OPCODE_SUBMEAN; + if (Field_dsp340050b49a6c_fld2821pq_slot2_Slot_pq_slot2_get (insn) == 5 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3759pq_slot2_Slot_pq_slot2_get (insn) == 0) + return OPCODE_SUBWRP; + if (Field_dsp340050b49a6c_fld2823pq_slot2_Slot_pq_slot2_get (insn) == 3 && + Field_op0_s9_Slot_pq_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3760pq_slot2_Slot_pq_slot2_get (insn) == 0) + return OPCODE_XOR128; + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 3) + return OPCODE_EXTUI; + switch (Field_sae_Slot_pq_slot2_get (insn)) + { + case 0: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_ADD; + break; + case 1: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_ADDI_N; + break; + case 2: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_AND; + break; + case 3: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MOVGEZ; + break; + case 4: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_LUT_AR; + break; + case 5: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MOVLTZ; + break; + case 6: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MOVNEZ; + break; + case 7: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_OR; + break; + case 8: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MOVEQZ; + break; + case 9: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_SUB; + break; + case 10: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0) + return OPCODE_XOR; + break; + case 12: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2817_Slot_pq_slot2_get (insn) == 0) + return OPCODE_MOVI_N; + break; + case 15: + if (Field_op0_s9_Slot_pq_slot2_get (insn) == 0 && + Field_t_Slot_pq_slot2_get (insn) == 0) + return OPCODE_SLL; + break; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_pq_slot0_decode (const xtensa_insnbuf insn) +{ + if (Field_dsp340050b49a6c_fld2827pq_slot0_Slot_pq_slot0_get (insn) == 0 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_LAC2X32; + if (Field_dsp340050b49a6c_fld2829pq_slot0_Slot_pq_slot0_get (insn) == 1 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_LAC32_R; + if (Field_dsp340050b49a6c_fld2830pq_slot0_Slot_pq_slot0_get (insn) == 2 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_LAC_IH; + if (Field_dsp340050b49a6c_fld2831pq_slot0_Slot_pq_slot0_get (insn) == 3 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_LAC_RH; + if (Field_dsp340050b49a6c_fld2832pq_slot0_Slot_pq_slot0_get (insn) == 10 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_LAC_RL; + if (Field_dsp340050b49a6c_fld2833pq_slot0_Slot_pq_slot0_get (insn) == 11 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_LAC2X64_0; + if (Field_dsp340050b49a6c_fld2835pq_slot0_Slot_pq_slot0_get (insn) == 27 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_LAC2X64_1; + if (Field_dsp340050b49a6c_fld2836pq_slot0_Slot_pq_slot0_get (insn) == 4 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_LAC_IL; + if (Field_dsp340050b49a6c_fld2837pq_slot0_Slot_pq_slot0_get (insn) == 5 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_LAC2X64_2; + switch (Field_dsp340050b49a6c_fld2838pq_slot0_Slot_pq_slot0_get (insn)) + { + case 21: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_AR2CM_DUP; + break; + case 53: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_MOV_N; + break; + case 85: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_NSA; + break; + case 117: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_PUSH32; + break; + case 149: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_NSAU; + break; + } + if (Field_dsp340050b49a6c_fld2839pq_slot0_Slot_pq_slot0_get (insn) == 362 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_GET_LLR_BUF; + if (Field_dsp340050b49a6c_fld2840pq_slot0_Slot_pq_slot0_get (insn) == 1452 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_ANY8; + if (Field_dsp340050b49a6c_fld2842pq_slot0_Slot_pq_slot0_get (insn) == 1453 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_GET_SMOD_BUF; + if (Field_dsp340050b49a6c_fld2843pq_slot0_Slot_pq_slot0_get (insn) == 2908 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_CLRCM; + if (Field_dsp340050b49a6c_fld2844pq_slot0_Slot_pq_slot0_get (insn) == 2909 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_GET_HSAR; + if (Field_dsp340050b49a6c_fld2845pq_slot0_Slot_pq_slot0_get (insn) == 2910 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_GET_HSAR2SAR; + if (Field_dsp340050b49a6c_fld2846pq_slot0_Slot_pq_slot0_get (insn) == 2911 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_GET_SAR; + if (Field_dsp340050b49a6c_fld2847pq_slot0_Slot_pq_slot0_get (insn) == 852 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_ANY4; + if (Field_dsp340050b49a6c_fld2849pq_slot0_Slot_pq_slot0_get (insn) == 3412 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_GET_SMOD_OFFSET_TABLE; + if (Field_dsp340050b49a6c_fld2850pq_slot0_Slot_pq_slot0_get (insn) == 3413 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_POP128_1; + if (Field_dsp340050b49a6c_fld2851pq_slot0_Slot_pq_slot0_get (insn) == 3414 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_POP128_2; + if (Field_dsp340050b49a6c_fld2852pq_slot0_Slot_pq_slot0_get (insn) == 3415 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_POP128_3; + if (Field_dsp340050b49a6c_fld2853pq_slot0_Slot_pq_slot0_get (insn) == 3416 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_POP128_0; + if (Field_dsp340050b49a6c_fld2854pq_slot0_Slot_pq_slot0_get (insn) == 3417 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_POP128_4; + if (Field_dsp340050b49a6c_fld2855pq_slot0_Slot_pq_slot0_get (insn) == 1709 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_s8_Slot_pq_slot0_get (insn) == 0) + return OPCODE_POP128_5; + if (Field_dsp340050b49a6c_fld2856pq_slot0_Slot_pq_slot0_get (insn) == 855 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3765pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_NOP; + if (Field_dsp340050b49a6c_fld2857pq_slot0_Slot_pq_slot0_get (insn) == 1960 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SSAI; + switch (Field_dsp340050b49a6c_fld2858pq_slot0_Slot_pq_slot0_get (insn)) + { + case 3922: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SET_LLR_POS; + break; + case 3923: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SET_PHASOR_OFFSET; + break; + case 3924: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SET_PERM_REG; + break; + case 3925: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SET_SCALE_REG; + break; + case 3926: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SET_SMOD_POS; + break; + case 3927: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SET_SOV; + break; + case 3928: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SET_PHASOR_N; + break; + case 3929: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SET_WGHT; + break; + case 3930: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SSA8B; + break; + case 3931: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SSL; + break; + case 3932: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SSA8L; + break; + case 3933: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SSR; + break; + } + if (Field_dsp340050b49a6c_fld2859pq_slot0_Slot_pq_slot0_get (insn) == 3934 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld2940_Slot_pq_slot0_get (insn) == 0) + return OPCODE_CLRAC; + if (Field_dsp340050b49a6c_fld2860pq_slot0_Slot_pq_slot0_get (insn) == 3935 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld2940_Slot_pq_slot0_get (insn) == 0) + return OPCODE_POP16LLR_1; + if (Field_dsp340050b49a6c_fld2861pq_slot0_Slot_pq_slot0_get (insn) == 3 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3768pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_LAC2X64_3; + switch (Field_dsp340050b49a6c_fld2863pq_slot0_Slot_pq_slot0_get (insn)) + { + case 3: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_AR2CM_LN; + break; + case 7: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_AR2CM_LN_I; + break; + } + if (Field_dsp340050b49a6c_fld2864pq_slot0_Slot_pq_slot0_get (insn) == 7 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld2069_Slot_pq_slot0_get (insn) == 0) + return OPCODE_AR2CM_LN_R; + switch (Field_dsp340050b49a6c_fld2865_Slot_pq_slot0_get (insn)) + { + case 0: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_SAC2X32; + break; + case 1: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_SAC32_R; + break; + case 2: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_SCM_PINC; + break; + case 3: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_SRAI; + break; + case 4: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_SCM_U; + break; + case 8: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_SLLI; + break; + } + if (Field_dsp340050b49a6c_fld2867pq_slot0_Slot_pq_slot0_get (insn) == 7 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3763pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_BEQZ_N; + if (Field_dsp340050b49a6c_fld2869pq_slot0_Slot_pq_slot0_get (insn) == 7 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3764pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_BNEZ_N; + if (Field_dsp340050b49a6c_fld2871pq_slot0_Slot_pq_slot0_get (insn) == 8 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_LCM_PINC; + if (Field_dsp340050b49a6c_fld2872pq_slot0_Slot_pq_slot0_get (insn) == 9 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_LCM_U; + if (Field_dsp340050b49a6c_fld2873pq_slot0_Slot_pq_slot0_get (insn) == 18 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_LCM; + if (Field_dsp340050b49a6c_fld2874pq_slot0_Slot_pq_slot0_get (insn) == 259 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_ABS; + if (Field_dsp340050b49a6c_fld2875pq_slot0_Slot_pq_slot0_get (insn) == 267 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_MOVCM; + if (Field_dsp340050b49a6c_fld2876pq_slot0_Slot_pq_slot0_get (insn) == 291 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_MOV_I; + if (Field_dsp340050b49a6c_fld2877pq_slot0_Slot_pq_slot0_get (insn) == 299 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_NEGCM; + if (Field_dsp340050b49a6c_fld2878pq_slot0_Slot_pq_slot0_get (insn) == 323 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_MOV_R; + if (Field_dsp340050b49a6c_fld2879pq_slot0_Slot_pq_slot0_get (insn) == 331 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SRA; + if (Field_dsp340050b49a6c_fld2880pq_slot0_Slot_pq_slot0_get (insn) == 355 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SRL; + if (Field_dsp340050b49a6c_fld2881pq_slot0_Slot_pq_slot0_get (insn) == 715 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_CLB_C; + switch (Field_dsp340050b49a6c_fld2882_Slot_pq_slot0_get (insn)) + { + case 21: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_EXT; + break; + case 23: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_EXT_R; + break; + case 33: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_MOVI_N; + break; + case 35: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_PUSH128_M; + break; + case 52: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SAC2X64_0; + break; + case 53: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SAC2X64_2; + break; + case 54: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SAC2X64_3; + break; + case 56: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SAC2X64_1; + break; + } + if (Field_dsp340050b49a6c_fld2883pq_slot0_Slot_pq_slot0_get (insn) == 731 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_CLB_R; + if (Field_dsp340050b49a6c_fld2884pq_slot0_Slot_pq_slot0_get (insn) == 387 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_NEG; + if (Field_dsp340050b49a6c_fld2885pq_slot0_Slot_pq_slot0_get (insn) == 779 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_MINCLB_C; + if (Field_dsp340050b49a6c_fld2886pq_slot0_Slot_pq_slot0_get (insn) == 795 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SMINCLB_R; + if (Field_dsp340050b49a6c_fld2887pq_slot0_Slot_pq_slot0_get (insn) == 835 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_MINCLB_R; + if (Field_dsp340050b49a6c_fld2888pq_slot0_Slot_pq_slot0_get (insn) == 13571 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_ADDAC_I2R; + if (Field_dsp340050b49a6c_fld2890pq_slot0_Slot_pq_slot0_get (insn) == 13587 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_ADDAC_R2I; + if (Field_dsp340050b49a6c_fld2891pq_slot0_Slot_pq_slot0_get (insn) == 13603 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_REDAC; + if (Field_dsp340050b49a6c_fld2892pq_slot0_Slot_pq_slot0_get (insn) == 13619 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_REDACS; + if (Field_dsp340050b49a6c_fld2893pq_slot0_Slot_pq_slot0_get (insn) == 13635 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_REDAC2; + if (Field_dsp340050b49a6c_fld2894pq_slot0_Slot_pq_slot0_get (insn) == 13651 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SUBAC_I2R; + if (Field_dsp340050b49a6c_fld2895pq_slot0_Slot_pq_slot0_get (insn) == 6835 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld2940_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SUBAC_R2I; + if (Field_dsp340050b49a6c_fld2897pq_slot0_Slot_pq_slot0_get (insn) == 1715 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3779pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_REDAC4; + if (Field_dsp340050b49a6c_fld2899pq_slot0_Slot_pq_slot0_get (insn) == 6667 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_GET_INTERP_EXT_L; + if (Field_dsp340050b49a6c_fld2900pq_slot0_Slot_pq_slot0_get (insn) == 6683 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_GET_INTERP_EXT_N; + if (Field_dsp340050b49a6c_fld2901pq_slot0_Slot_pq_slot0_get (insn) == 6699 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_GET_LLR_POS; + if (Field_dsp340050b49a6c_fld2902pq_slot0_Slot_pq_slot0_get (insn) == 6715 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_GET_PHASOR_OFFSET; + if (Field_dsp340050b49a6c_fld2903pq_slot0_Slot_pq_slot0_get (insn) == 6731 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_GET_PERM_REG; + if (Field_dsp340050b49a6c_fld2904pq_slot0_Slot_pq_slot0_get (insn) == 6747 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_GET_SCALE_REG; + if (Field_dsp340050b49a6c_fld2905pq_slot0_Slot_pq_slot0_get (insn) == 6763 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_GET_SMOD_POS; + if (Field_dsp340050b49a6c_fld2906pq_slot0_Slot_pq_slot0_get (insn) == 6779 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_GET_SOV; + if (Field_dsp340050b49a6c_fld2907pq_slot0_Slot_pq_slot0_get (insn) == 6795 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_GET_PHASOR_N; + if (Field_dsp340050b49a6c_fld2908pq_slot0_Slot_pq_slot0_get (insn) == 6811 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_GET_WGHT; + if (Field_dsp340050b49a6c_fld2909pq_slot0_Slot_pq_slot0_get (insn) == 6827 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_POP32_0; + if (Field_dsp340050b49a6c_fld2910pq_slot0_Slot_pq_slot0_get (insn) == 6843 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_POP32_2; + if (Field_dsp340050b49a6c_fld2911pq_slot0_Slot_pq_slot0_get (insn) == 6859 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_POP32_1; + if (Field_dsp340050b49a6c_fld2912pq_slot0_Slot_pq_slot0_get (insn) == 6875 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_POP32_3; + if (Field_dsp340050b49a6c_fld2913pq_slot0_Slot_pq_slot0_get (insn) == 6891 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SET_SAR; + if (Field_dsp340050b49a6c_fld2914pq_slot0_Slot_pq_slot0_get (insn) == 6907 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SET_SMOD_OFFSET_TABLE; + if (Field_dsp340050b49a6c_fld2915pq_slot0_Slot_pq_slot0_get (insn) == 115 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3780pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SMINCLB_C; + if (Field_dsp340050b49a6c_fld2916pq_slot0_Slot_pq_slot0_get (insn) == 137 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_s8_Slot_pq_slot0_get (insn) == 0) + return OPCODE_CONJ; + if (Field_dsp340050b49a6c_fld2917pq_slot0_Slot_pq_slot0_get (insn) == 277 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_EXT32_I; + if (Field_dsp340050b49a6c_fld2918pq_slot0_Slot_pq_slot0_get (insn) == 285 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_EXT_2FIFO_2; + if (Field_dsp340050b49a6c_fld2919pq_slot0_Slot_pq_slot0_get (insn) == 305 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_EXT32_R; + if (Field_dsp340050b49a6c_fld2920pq_slot0_Slot_pq_slot0_get (insn) == 309 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_EXT_2FIFO_3; + if (Field_dsp340050b49a6c_fld2921pq_slot0_Slot_pq_slot0_get (insn) == 313 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_EXT_R2FIFO_0; + if (Field_dsp340050b49a6c_fld2922pq_slot0_Slot_pq_slot0_get (insn) == 317 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_EXT_R2FIFO_1; + if (Field_dsp340050b49a6c_fld2923pq_slot0_Slot_pq_slot0_get (insn) == 337 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_EXT_2FIFO_0; + if (Field_dsp340050b49a6c_fld2924pq_slot0_Slot_pq_slot0_get (insn) == 341 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0) + return OPCODE_EXT_R2FIFO_2; + if (Field_dsp340050b49a6c_fld2925pq_slot0_Slot_pq_slot0_get (insn) == 173 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld2036_Slot_pq_slot0_get (insn) == 0) + return OPCODE_EXT_R2FIFO_3; + if (Field_dsp340050b49a6c_fld2926pq_slot0_Slot_pq_slot0_get (insn) == 93 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3767pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SET_SMOD_BUF; + if (Field_dsp340050b49a6c_fld2927pq_slot0_Slot_pq_slot0_get (insn) == 29 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3773pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_EXT_2FIFO_1; + if (Field_dsp340050b49a6c_fld2928pq_slot0_Slot_pq_slot0_get (insn) == 9 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld2059_Slot_pq_slot0_get (insn) == 0) + return OPCODE_CM2AR_LN; + if (Field_dsp340050b49a6c_fld2929pq_slot0_Slot_pq_slot0_get (insn) == 11 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld2059_Slot_pq_slot0_get (insn) == 0) + return OPCODE_CM2AR_LN_I; + if (Field_dsp340050b49a6c_fld2930pq_slot0_Slot_pq_slot0_get (insn) == 7 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3769pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_CM2AR_LN_R; + if (Field_dsp340050b49a6c_fld2932pq_slot0_Slot_pq_slot0_get (insn) == 6 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SAC_IL; + if (Field_dsp340050b49a6c_fld2934pq_slot0_Slot_pq_slot0_get (insn) == 7 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SAC_RH; + if (Field_dsp340050b49a6c_fld2935pq_slot0_Slot_pq_slot0_get (insn) == 10 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SAC_RL; + if (Field_dsp340050b49a6c_fld2936pq_slot0_Slot_pq_slot0_get (insn) == 16 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SAC_IH; + if (Field_dsp340050b49a6c_fld2937pq_slot0_Slot_pq_slot0_get (insn) == 220 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_ASLACM; + if (Field_dsp340050b49a6c_fld2939pq_slot0_Slot_pq_slot0_get (insn) == 442 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3772_Slot_pq_slot0_get (insn) == 0) + return OPCODE_ASRAC; + if (Field_dsp340050b49a6c_fld2941pq_slot0_Slot_pq_slot0_get (insn) == 443 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3771pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SWAPAC_RI; + if (Field_dsp340050b49a6c_fld2942pq_slot0_Slot_pq_slot0_get (insn) == 111 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3766pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_MOVAC; + if (Field_dsp340050b49a6c_fld2943pq_slot0_Slot_pq_slot0_get (insn) == 114 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3775pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_POP128_2M_0; + if (Field_dsp340050b49a6c_fld2945pq_slot0_Slot_pq_slot0_get (insn) == 115 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3775pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_POP128_2M_3; + if (Field_dsp340050b49a6c_fld2946pq_slot0_Slot_pq_slot0_get (insn) == 496 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SLL; + if (Field_dsp340050b49a6c_fld2947pq_slot0_Slot_pq_slot0_get (insn) == 497 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld2036_Slot_pq_slot0_get (insn) == 0) + return OPCODE_MOV2AC32_I; + if (Field_dsp340050b49a6c_fld2948pq_slot0_Slot_pq_slot0_get (insn) == 249 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3770pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_MOV2AC32_R; + if (Field_dsp340050b49a6c_fld2949pq_slot0_Slot_pq_slot0_get (insn) == 125 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3778pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_PUSH128; + if (Field_dsp340050b49a6c_fld2950pq_slot0_Slot_pq_slot0_get (insn) == 63 && + Field_op0_s11_Slot_pq_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3766pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_SET_LLR_BUF; + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 3) + return OPCODE_EXTUI; + switch (Field_sae_Slot_pq_slot0_get (insn)) + { + case 0: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_MOVNEZ; + break; + case 1: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_MOVT; + break; + case 2: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_OR; + break; + case 3: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SCM; + break; + case 4: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_ORB; + break; + case 5: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SCM_PINC_X; + break; + case 8: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_S32I_N; + break; + case 9: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SCM_XU; + break; + case 10: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_ADD; + break; + case 11: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_ADDX2; + break; + case 12: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_ADDI_N; + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SCM_X; + break; + case 13: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_ADDX4; + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SEXT; + break; + case 14: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_ADDX8; + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SRC; + break; + case 15: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_AND; + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SRLI; + break; + case 18: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_ANDB; + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_STORE_P; + break; + case 19: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_L32I_N; + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SUBX2; + break; + case 20: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_CLAMPS; + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_STORE_Q; + break; + case 21: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SUBX4; + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_LCM_PINC_X; + break; + case 22: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SUBX8; + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_LCM_X; + break; + case 23: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_XOR; + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_LCM_XU; + break; + case 24: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_SUB; + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_COMB_AR; + break; + case 25: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2) + return OPCODE_XORB; + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_MAX; + break; + case 26: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_MAXU; + break; + case 27: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_MINU; + break; + case 28: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_MIN; + break; + case 29: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_MOVEQZ; + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3776pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_POP128_2M_1; + break; + case 30: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_MOVGEZ; + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3777pq_slot0_Slot_pq_slot0_get (insn) == 0) + return OPCODE_POP128_2M_2; + break; + case 31: + if (Field_op0_s11_Slot_pq_slot0_get (insn) == 1) + return OPCODE_MOVLTZ; + break; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_acc2_slot0_decode (const xtensa_insnbuf insn) +{ + switch (Field_dsp340050b49a6c_fld2047_Slot_acc2_slot0_get (insn)) + { + case 0: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3795acc2_slot0_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_NEG; + break; + case 1: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld2039_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_PUSH128; + break; + } + if (Field_dsp340050b49a6c_fld2056_Slot_acc2_slot0_get (insn) == 0 && + Field_op0_s14_Slot_acc2_slot0_get (insn) == 1) + return OPCODE_MOVCM2PQ; + if (Field_dsp340050b49a6c_fld2973acc2_slot0_Slot_acc2_slot0_get (insn) == 0 && + Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_MOVI_N; + if (Field_dsp340050b49a6c_fld2974acc2_slot0_Slot_acc2_slot0_get (insn) == 40 && + Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_PUSH2X128_PQ; + switch (Field_dsp340050b49a6c_fld2975acc2_slot0_Slot_acc2_slot0_get (insn)) + { + case 82: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP128_2PQ_1; + break; + case 83: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP128_2PQ_4; + break; + case 84: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP128_2PQ_2; + break; + case 85: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP128_2PQ_5; + break; + case 88: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP128_2PQ_3; + break; + } + switch (Field_dsp340050b49a6c_fld2976acc2_slot0_Slot_acc2_slot0_get (insn)) + { + case 172: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_CLRCM; + break; + case 173: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP128_0; + break; + case 174: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP128_1; + break; + case 175: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP128_2; + break; + case 178: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP128_3; + break; + case 179: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP2X128_2PQ_01; + break; + case 180: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP128_4; + break; + case 181: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP2X128_2PQ_03; + break; + case 182: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP2X128_2PQ_21; + break; + case 183: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP2X128_2PQ_23; + break; + } + if (Field_dsp340050b49a6c_fld2977acc2_slot0_Slot_acc2_slot0_get (insn) == 46 && + Field_op0_s14_Slot_acc2_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3797_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP128_5; + if (Field_dsp340050b49a6c_fld2980acc2_slot0_Slot_acc2_slot0_get (insn) == 47 && + Field_op0_s14_Slot_acc2_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3796acc2_slot0_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_NOP; + if (Field_dsp340050b49a6c_fld2981acc2_slot0_Slot_acc2_slot0_get (insn) == 3 && + Field_op0_s14_Slot_acc2_slot0_get (insn) == 0 && + Field_dsp340050b49a6c_fld3800acc2_slot0_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP128_2PQ_0; + if (Field_dsp340050b49a6c_fld2982acc2_slot0_Slot_acc2_slot0_get (insn) == 24 && + Field_op0_s14_Slot_acc2_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3801acc2_slot0_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP32_0; + if (Field_dsp340050b49a6c_fld2984acc2_slot0_Slot_acc2_slot0_get (insn) == 25 && + Field_op0_s14_Slot_acc2_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3801acc2_slot0_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP32_1; + if (Field_dsp340050b49a6c_fld2985acc2_slot0_Slot_acc2_slot0_get (insn) == 13 && + Field_op0_s14_Slot_acc2_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3802acc2_slot0_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP32_2; + if (Field_dsp340050b49a6c_fld2987acc2_slot0_Slot_acc2_slot0_get (insn) == 7 && + Field_op0_s14_Slot_acc2_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3803acc2_slot0_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_POP32_3; + if (Field_dsp340050b49a6c_fld2989acc2_slot0_Slot_acc2_slot0_get (insn) == 1 && + Field_op0_s14_Slot_acc2_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3798acc2_slot0_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_MOVCM; + if (Field_dsp340050b49a6c_fld2990acc2_slot0_Slot_acc2_slot0_get (insn) == 1 && + Field_op0_s14_Slot_acc2_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3799acc2_slot0_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_NEGCM; + switch (Field_op0_s14_Slot_acc2_slot0_get (insn)) + { + case 3: + return OPCODE_ADD; + case 4: + return OPCODE_ADDI_N; + case 5: + return OPCODE_LCM_X; + case 6: + return OPCODE_LCM_XU; + case 7: + return OPCODE_SCM_X; + case 8: + return OPCODE_SCM_XU; + case 9: + return OPCODE_SUB; + } + switch (Field_r_Slot_acc2_slot0_get (insn)) + { + case 8: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_MOV_N; + break; + case 9: + if (Field_op0_s14_Slot_acc2_slot0_get (insn) == 0) + return OPCODE_PUSH128_PQ; + break; + } + if (Field_t_Slot_acc2_slot0_get (insn) == 2 && + Field_op0_s14_Slot_acc2_slot0_get (insn) == 1) + return OPCODE_CONJ; + return XTENSA_UNDEFINED; +} + +static int +Slot_smod_slot0_decode (const xtensa_insnbuf insn) +{ + switch (Field_dsp340050b49a6c_fld3119smod_slot0_Slot_smod_slot0_get (insn)) + { + case 0: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_LCM_PINC; + break; + case 1: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_LCM_U; + break; + case 2: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_SCM_PINC; + break; + case 3: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_SRAI; + break; + case 4: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_SCM_U; + break; + case 8: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_SLLI; + break; + case 13: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3841smod_slot0_Slot_smod_slot0_get (insn) == 0) + return OPCODE_PUSH128; + break; + } + switch (Field_dsp340050b49a6c_fld3120smod_slot0_Slot_smod_slot0_get (insn)) + { + case 76: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_AR2CM_LN; + break; + case 77: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_AR2CM_LN_I; + break; + case 78: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_AR2CM_LN_R; + break; + case 79: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_BEQZ_N; + break; + case 82: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_BNEZ_N; + break; + } + switch (Field_dsp340050b49a6c_fld3121smod_slot0_Slot_smod_slot0_get (insn)) + { + case 40: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_MOVI_N; + break; + case 47: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld2049_Slot_smod_slot0_get (insn) == 0) + return OPCODE_POP128_2M_3; + break; + } + switch (Field_dsp340050b49a6c_fld3122smod_slot0_Slot_smod_slot0_get (insn)) + { + case 332: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_AR2CM_DUP; + break; + case 333: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_MOV_N; + break; + case 334: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_NSA; + break; + case 335: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_NSAU; + break; + case 371: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_PUSH32; + break; + } + if (Field_dsp340050b49a6c_fld3123smod_slot0_Slot_smod_slot0_get (insn) == 84 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_CM2AR_LN; + if (Field_dsp340050b49a6c_fld3125smod_slot0_Slot_smod_slot0_get (insn) == 85 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_CM2AR_LN_R; + if (Field_dsp340050b49a6c_fld3126smod_slot0_Slot_smod_slot0_get (insn) == 344 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_ABS; + if (Field_dsp340050b49a6c_fld3127smod_slot0_Slot_smod_slot0_get (insn) == 345 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_CONJ; + if (Field_dsp340050b49a6c_fld3128smod_slot0_Slot_smod_slot0_get (insn) == 346 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_MOVCM; + if (Field_dsp340050b49a6c_fld3129smod_slot0_Slot_smod_slot0_get (insn) == 347 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_MOV_R; + if (Field_dsp340050b49a6c_fld3130smod_slot0_Slot_smod_slot0_get (insn) == 348 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_MOV_I; + if (Field_dsp340050b49a6c_fld3131smod_slot0_Slot_smod_slot0_get (insn) == 349 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_NEG; + if (Field_dsp340050b49a6c_fld3132smod_slot0_Slot_smod_slot0_get (insn) == 350 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_NEGCM; + if (Field_dsp340050b49a6c_fld3133smod_slot0_Slot_smod_slot0_get (insn) == 351 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SRA; + if (Field_dsp340050b49a6c_fld3134smod_slot0_Slot_smod_slot0_get (insn) == 88 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_CM2AR_LN_I; + if (Field_dsp340050b49a6c_fld3135smod_slot0_Slot_smod_slot0_get (insn) == 356 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SRL; + if (Field_dsp340050b49a6c_fld3136smod_slot0_Slot_smod_slot0_get (insn) == 5637 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_CLRCM; + if (Field_dsp340050b49a6c_fld3137smod_slot0_Slot_smod_slot0_get (insn) == 5653 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_GET_HSAR; + if (Field_dsp340050b49a6c_fld3138smod_slot0_Slot_smod_slot0_get (insn) == 5669 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_GET_HSAR2SAR; + if (Field_dsp340050b49a6c_fld3139smod_slot0_Slot_smod_slot0_get (insn) == 5685 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_POP128_0; + if (Field_dsp340050b49a6c_fld3140smod_slot0_Slot_smod_slot0_get (insn) == 5701 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_GET_SAR; + if (Field_dsp340050b49a6c_fld3141smod_slot0_Slot_smod_slot0_get (insn) == 5717 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_POP128_1; + if (Field_dsp340050b49a6c_fld3142smod_slot0_Slot_smod_slot0_get (insn) == 5733 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_POP128_2; + if (Field_dsp340050b49a6c_fld3143smod_slot0_Slot_smod_slot0_get (insn) == 5749 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_POP128_3; + if (Field_dsp340050b49a6c_fld3144smod_slot0_Slot_smod_slot0_get (insn) == 5765 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_GET_SMOD_OFFSET_TABLE; + if (Field_dsp340050b49a6c_fld3145smod_slot0_Slot_smod_slot0_get (insn) == 5781 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_POP128_4; + if (Field_dsp340050b49a6c_fld3146smod_slot0_Slot_smod_slot0_get (insn) == 2901 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3150_Slot_smod_slot0_get (insn) == 0) + return OPCODE_POP128_5; + if (Field_dsp340050b49a6c_fld3148smod_slot0_Slot_smod_slot0_get (insn) == 1461 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1 && + Field_imm6_Slot_smod_slot0_get (insn) == 0) + return OPCODE_NOP; + if (Field_dsp340050b49a6c_fld3149smod_slot0_Slot_smod_slot0_get (insn) == 355 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3834_Slot_smod_slot0_get (insn) == 0) + return OPCODE_ANY8; + if (Field_dsp340050b49a6c_fld3152smod_slot0_Slot_smod_slot0_get (insn) == 363 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3834_Slot_smod_slot0_get (insn) == 0) + return OPCODE_GET_SMOD_BUF; + if (Field_dsp340050b49a6c_fld3153smod_slot0_Slot_smod_slot0_get (insn) == 89 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3834_Slot_smod_slot0_get (insn) == 0) + return OPCODE_GET_LLR_BUF; + if (Field_dsp340050b49a6c_fld3155smod_slot0_Slot_smod_slot0_get (insn) == 91 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3833smod_slot0_Slot_smod_slot0_get (insn) == 0) + return OPCODE_ANY4; + if (Field_dsp340050b49a6c_fld3156smod_slot0_Slot_smod_slot0_get (insn) == 184 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_POP128_2M_0; + if (Field_dsp340050b49a6c_fld3157smod_slot0_Slot_smod_slot0_get (insn) == 185 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_POP128_2M_1; + if (Field_dsp340050b49a6c_fld3158smod_slot0_Slot_smod_slot0_get (insn) == 186 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_POP128_2M_2; + if (Field_dsp340050b49a6c_fld3159smod_slot0_Slot_smod_slot0_get (insn) == 3000 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SSAI; + switch (Field_dsp340050b49a6c_fld3160smod_slot0_Slot_smod_slot0_get (insn)) + { + case 6002: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SET_LLR_POS; + break; + case 6003: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SET_PHASOR_OFFSET; + break; + case 6004: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SET_PERM_REG; + break; + case 6005: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SET_SCALE_REG; + break; + case 6006: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SET_SMOD_POS; + break; + case 6007: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SET_SOV; + break; + case 6008: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SET_PHASOR_N; + break; + case 6009: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SET_WGHT; + break; + case 6010: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SSA8B; + break; + case 6011: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SSL; + break; + } + if (Field_dsp340050b49a6c_fld3161smod_slot0_Slot_smod_slot0_get (insn) == 3006 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3832smod_slot0_Slot_smod_slot0_get (insn) == 0) + return OPCODE_SSA8L; + if (Field_dsp340050b49a6c_fld3164smod_slot0_Slot_smod_slot0_get (insn) == 3007 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3832smod_slot0_Slot_smod_slot0_get (insn) == 0) + return OPCODE_SSR; + if (Field_dsp340050b49a6c_fld3165smod_slot0_Slot_smod_slot0_get (insn) == 400 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SLL; + if (Field_dsp340050b49a6c_fld3166smod_slot0_Slot_smod_slot0_get (insn) == 3208 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SET_SMOD_BUF; + if (Field_dsp340050b49a6c_fld3168smod_slot0_Slot_smod_slot0_get (insn) == 6418 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_GET_PERM_REG; + if (Field_dsp340050b49a6c_fld3170smod_slot0_Slot_smod_slot0_get (insn) == 6419 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_GET_SCALE_REG; + if (Field_dsp340050b49a6c_fld3171smod_slot0_Slot_smod_slot0_get (insn) == 6420 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_GET_PHASOR_N; + if (Field_dsp340050b49a6c_fld3172smod_slot0_Slot_smod_slot0_get (insn) == 6421 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_GET_SMOD_POS; + if (Field_dsp340050b49a6c_fld3173smod_slot0_Slot_smod_slot0_get (insn) == 6422 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_GET_SOV; + if (Field_dsp340050b49a6c_fld3174smod_slot0_Slot_smod_slot0_get (insn) == 6423 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_GET_WGHT; + if (Field_dsp340050b49a6c_fld3175smod_slot0_Slot_smod_slot0_get (insn) == 6424 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_GET_PHASOR_OFFSET; + if (Field_dsp340050b49a6c_fld3176smod_slot0_Slot_smod_slot0_get (insn) == 6425 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_POP32_0; + if (Field_dsp340050b49a6c_fld3177smod_slot0_Slot_smod_slot0_get (insn) == 6426 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_POP32_1; + if (Field_dsp340050b49a6c_fld3178smod_slot0_Slot_smod_slot0_get (insn) == 6427 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_POP32_3; + if (Field_dsp340050b49a6c_fld3179smod_slot0_Slot_smod_slot0_get (insn) == 6428 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_POP32_2; + if (Field_dsp340050b49a6c_fld3180smod_slot0_Slot_smod_slot0_get (insn) == 6429 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SET_SAR; + if (Field_dsp340050b49a6c_fld3181smod_slot0_Slot_smod_slot0_get (insn) == 3215 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1 && + Field_s8_Slot_smod_slot0_get (insn) == 0) + return OPCODE_SET_SMOD_OFFSET_TABLE; + if (Field_dsp340050b49a6c_fld3182smod_slot0_Slot_smod_slot0_get (insn) == 201 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1 && + Field_sas_Slot_smod_slot0_get (insn) == 0) + return OPCODE_GET_INTERP_EXT_L; + if (Field_dsp340050b49a6c_fld3184smod_slot0_Slot_smod_slot0_get (insn) == 101 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3836smod_slot0_Slot_smod_slot0_get (insn) == 0) + return OPCODE_GET_INTERP_EXT_N; + if (Field_dsp340050b49a6c_fld3186smod_slot0_Slot_smod_slot0_get (insn) == 51 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3837smod_slot0_Slot_smod_slot0_get (insn) == 0) + return OPCODE_GET_LLR_POS; + if (Field_dsp340050b49a6c_fld3188smod_slot0_Slot_smod_slot0_get (insn) == 7 && + Field_op0_s17_Slot_smod_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3838smod_slot0_Slot_smod_slot0_get (insn) == 0) + return OPCODE_SET_LLR_BUF; + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 2) + return OPCODE_EXTUI; + switch (Field_sae_Slot_smod_slot0_get (insn)) + { + case 0: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_MOVLTZ; + break; + case 1: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_MOVNEZ; + break; + case 2: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_MOVT; + break; + case 3: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SCM; + break; + case 4: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_OR; + break; + case 5: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SCM_PINC_X; + break; + case 6: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SCM_X; + break; + case 7: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SCM_XU; + break; + case 8: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_ORB; + break; + case 9: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SEXT; + break; + case 10: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_ADD; + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SRC; + break; + case 11: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SUB; + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_ADDX2; + break; + case 12: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_ADDI_N; + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SRLI; + break; + case 13: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_ADDX4; + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SUBX2; + break; + case 14: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_ADDX8; + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SUBX4; + break; + case 15: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_SUBX8; + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_AND; + break; + case 16: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_S32I_N; + break; + case 17: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_XOR; + break; + case 18: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_ANDB; + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1) + return OPCODE_XORB; + break; + case 19: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_L32I_N; + break; + case 20: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_CLAMPS; + break; + case 21: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_LCM; + break; + case 22: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_LCM_PINC_X; + break; + case 23: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_LCM_X; + break; + case 24: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_COMB_AR; + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3842smod_slot0_Slot_smod_slot0_get (insn) == 0) + return OPCODE_PUSH128_M; + break; + case 25: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_LCM_XU; + break; + case 26: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_MAX; + break; + case 27: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_MIN; + break; + case 28: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_MAXU; + break; + case 29: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_MINU; + break; + case 30: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_MOVEQZ; + break; + case 31: + if (Field_op0_s17_Slot_smod_slot0_get (insn) == 0) + return OPCODE_MOVGEZ; + break; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_llr_slot0_decode (const xtensa_insnbuf insn) +{ + switch (Field_dsp340050b49a6c_fld2071_Slot_llr_slot0_get (insn)) + { + case 0: + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 4) + return OPCODE_S32I_N; + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 0) + return OPCODE_ADD; + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 6) + return OPCODE_SUB; + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 1) + return OPCODE_AND; + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 2) + return OPCODE_LCM; + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 3) + return OPCODE_LCM_XU; + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 5) + return OPCODE_SCM_X; + break; + case 1: + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 0) + return OPCODE_ADDI_N; + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 1) + return OPCODE_L32I_N; + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 3) + return OPCODE_OR; + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 6) + return OPCODE_XOR; + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 8 && + Field_dsp340050b49a6c_fld3881llr_slot0_Slot_llr_slot0_get (insn) == 0) + return OPCODE_GET_LLR_BUF; + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 2) + return OPCODE_LCM_X; + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 4) + return OPCODE_SCM; + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 5) + return OPCODE_SCM_XU; + break; + } + if (Field_dsp340050b49a6c_fld3258llr_slot0_Slot_llr_slot0_get (insn) == 0 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_MOVI_N; + if (Field_dsp340050b49a6c_fld3259llr_slot0_Slot_llr_slot0_get (insn) == 2 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_AR2CM_LN; + switch (Field_dsp340050b49a6c_fld3260llr_slot0_Slot_llr_slot0_get (insn)) + { + case 12: + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_AR2CM_DUP; + break; + case 13: + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_MOV_N; + break; + case 14: + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_PUSH128_PQ; + break; + case 15: + if (Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_PUSH32; + break; + } + if (Field_dsp340050b49a6c_fld3261llr_slot0_Slot_llr_slot0_get (insn) == 4 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_CM2AR_LN; + if (Field_dsp340050b49a6c_fld3263llr_slot0_Slot_llr_slot0_get (insn) == 20 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_CONJ; + if (Field_dsp340050b49a6c_fld3264llr_slot0_Slot_llr_slot0_get (insn) == 21 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_MOV_I; + if (Field_dsp340050b49a6c_fld3265llr_slot0_Slot_llr_slot0_get (insn) == 22 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_MOV_R; + if (Field_dsp340050b49a6c_fld3266llr_slot0_Slot_llr_slot0_get (insn) == 23 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_NEG; + if (Field_dsp340050b49a6c_fld3267llr_slot0_Slot_llr_slot0_get (insn) == 24 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_MOVCM; + if (Field_dsp340050b49a6c_fld3268llr_slot0_Slot_llr_slot0_get (insn) == 25 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_NEGCM; + if (Field_dsp340050b49a6c_fld3269llr_slot0_Slot_llr_slot0_get (insn) == 26 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_SRA; + if (Field_dsp340050b49a6c_fld3270llr_slot0_Slot_llr_slot0_get (insn) == 43 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_SET_LLR_BUF; + if (Field_dsp340050b49a6c_fld3272llr_slot0_Slot_llr_slot0_get (insn) == 283 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_GET_LLR_POS; + if (Field_dsp340050b49a6c_fld3274llr_slot0_Slot_llr_slot0_get (insn) == 315 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_GET_PERM_REG; + if (Field_dsp340050b49a6c_fld3275llr_slot0_Slot_llr_slot0_get (insn) == 347 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_GET_SCALE_REG; + if (Field_dsp340050b49a6c_fld3276llr_slot0_Slot_llr_slot0_get (insn) == 379 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_GET_WGHT; + if (Field_dsp340050b49a6c_fld3277llr_slot0_Slot_llr_slot0_get (insn) == 411 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_GET_SMOD_POS; + if (Field_dsp340050b49a6c_fld3278llr_slot0_Slot_llr_slot0_get (insn) == 443 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_POP32_0; + if (Field_dsp340050b49a6c_fld3279llr_slot0_Slot_llr_slot0_get (insn) == 475 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_POP32_1; + if (Field_dsp340050b49a6c_fld3280llr_slot0_Slot_llr_slot0_get (insn) == 507 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_POP32_2; + if (Field_dsp340050b49a6c_fld3281llr_slot0_Slot_llr_slot0_get (insn) == 44 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_PUSH128; + if (Field_dsp340050b49a6c_fld3282llr_slot0_Slot_llr_slot0_get (insn) == 269 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_POP32_3; + if (Field_dsp340050b49a6c_fld3283llr_slot0_Slot_llr_slot0_get (insn) == 301 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_SET_SAR; + if (Field_dsp340050b49a6c_fld3284llr_slot0_Slot_llr_slot0_get (insn) == 173 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7 && + Field_dsp340050b49a6c_fld2041_Slot_llr_slot0_get (insn) == 0) + return OPCODE_SET_SMOD_OFFSET_TABLE; + if (Field_dsp340050b49a6c_fld3286llr_slot0_Slot_llr_slot0_get (insn) == 109 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7 && + Field_dsp340050b49a6c_fld3879llr_slot0_Slot_llr_slot0_get (insn) == 0) + return OPCODE_NOP; + if (Field_dsp340050b49a6c_fld3288llr_slot0_Slot_llr_slot0_get (insn) == 30 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7 && + Field_dsp340050b49a6c_fld2056_Slot_llr_slot0_get (insn) == 0) + return OPCODE_SET_SMOD_BUF; + if (Field_dsp340050b49a6c_fld3289llr_slot0_Slot_llr_slot0_get (insn) == 135 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_GET_SMOD_BUF; + if (Field_dsp340050b49a6c_fld3291llr_slot0_Slot_llr_slot0_get (insn) == 286 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_CLRCM; + if (Field_dsp340050b49a6c_fld3292llr_slot0_Slot_llr_slot0_get (insn) == 287 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_GET_SMOD_OFFSET_TABLE; + if (Field_dsp340050b49a6c_fld3293llr_slot0_Slot_llr_slot0_get (insn) == 302 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_GET_HSAR; + if (Field_dsp340050b49a6c_fld3294llr_slot0_Slot_llr_slot0_get (insn) == 303 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_POP128_0; + if (Field_dsp340050b49a6c_fld3295llr_slot0_Slot_llr_slot0_get (insn) == 318 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_POP128_1; + if (Field_dsp340050b49a6c_fld3296llr_slot0_Slot_llr_slot0_get (insn) == 319 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_POP128_2; + if (Field_dsp340050b49a6c_fld3297llr_slot0_Slot_llr_slot0_get (insn) == 334 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_GET_HSAR2SAR; + if (Field_dsp340050b49a6c_fld3298llr_slot0_Slot_llr_slot0_get (insn) == 335 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7) + return OPCODE_POP128_3; + if (Field_dsp340050b49a6c_fld3299llr_slot0_Slot_llr_slot0_get (insn) == 175 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7 && + Field_dsp340050b49a6c_fld2047_Slot_llr_slot0_get (insn) == 0) + return OPCODE_POP128_4; + if (Field_dsp340050b49a6c_fld3300llr_slot0_Slot_llr_slot0_get (insn) == 95 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7 && + Field_dsp340050b49a6c_fld3893llr_slot0_Slot_llr_slot0_get (insn) == 0) + return OPCODE_POP128_5; + if (Field_dsp340050b49a6c_fld3302llr_slot0_Slot_llr_slot0_get (insn) == 31 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 7 && + Field_dsp340050b49a6c_fld3883llr_slot0_Slot_llr_slot0_get (insn) == 0) + return OPCODE_GET_SAR; + if (Field_dsp340050b49a6c_fld3303llr_slot0_Slot_llr_slot0_get (insn) == 0 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 8) + return OPCODE_SLL; + if (Field_dsp340050b49a6c_fld3304llr_slot0_Slot_llr_slot0_get (insn) == 1 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 8 && + Field_dsp340050b49a6c_fld3887llr_slot0_Slot_llr_slot0_get (insn) == 0) + return OPCODE_SET_PERM_REG; + if (Field_dsp340050b49a6c_fld3305llr_slot0_Slot_llr_slot0_get (insn) == 17 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 8 && + Field_dsp340050b49a6c_fld3887llr_slot0_Slot_llr_slot0_get (insn) == 0) + return OPCODE_SET_SMOD_POS; + if (Field_dsp340050b49a6c_fld3306llr_slot0_Slot_llr_slot0_get (insn) == 17 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 8 && + Field_dsp340050b49a6c_fld3890llr_slot0_Slot_llr_slot0_get (insn) == 0) + return OPCODE_SET_WGHT; + if (Field_dsp340050b49a6c_fld3308llr_slot0_Slot_llr_slot0_get (insn) == 17 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 8 && + Field_dsp340050b49a6c_fld3892llr_slot0_Slot_llr_slot0_get (insn) == 0) + return OPCODE_POP16LLR_1; + if (Field_dsp340050b49a6c_fld3310llr_slot0_Slot_llr_slot0_get (insn) == 1 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 8 && + Field_dsp340050b49a6c_fld3888llr_slot0_Slot_llr_slot0_get (insn) == 0) + return OPCODE_SET_SCALE_REG; + if (Field_dsp340050b49a6c_fld3311llr_slot0_Slot_llr_slot0_get (insn) == 1 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 8 && + Field_r_Slot_llr_slot0_get (insn) == 0) + return OPCODE_PUSH2X128_PQ; + if (Field_dsp340050b49a6c_fld3312llr_slot0_Slot_llr_slot0_get (insn) == 1 && + Field_op0_s20_Slot_llr_slot0_get (insn) == 8 && + Field_dsp340050b49a6c_fld3885llr_slot0_Slot_llr_slot0_get (insn) == 0) + return OPCODE_SET_LLR_POS; + switch (Field_op0_s20_Slot_llr_slot0_get (insn)) + { + case 9: + return OPCODE_LCM_U; + case 10: + return OPCODE_SCM_U; + case 11: + return OPCODE_SLLI; + case 12: + return OPCODE_SRAI; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_dual_slot2_decode (const xtensa_insnbuf insn) +{ + if (Field_dsp340050b49a6c_fld2044_Slot_dual_slot2_get (insn) == 0 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_EXTUI; + if (Field_dsp340050b49a6c_fld2056_Slot_dual_slot2_get (insn) == 5 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3923dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_CLRTIEP; + if (Field_dsp340050b49a6c_fld3313dual_slot2_Slot_dual_slot2_get (insn) == 1 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_BEQI; + if (Field_dsp340050b49a6c_fld3314_Slot_dual_slot2_get (insn) == 1 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3904dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_BNEZ; + if (Field_dsp340050b49a6c_fld3315dual_slot2_Slot_dual_slot2_get (insn) == 17 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_BLTUI; + if (Field_dsp340050b49a6c_fld3316dual_slot2_Slot_dual_slot2_get (insn) == 33 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_BNEI; + if (Field_dsp340050b49a6c_fld3317dual_slot2_Slot_dual_slot2_get (insn) == 769 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_ADD32; + switch (Field_dsp340050b49a6c_fld3318_Slot_dual_slot2_get (insn)) + { + case 2: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_BEQZ; + break; + case 4: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_BGEZ; + break; + case 6: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2 && + Field_s_Slot_dual_slot2_get (insn) == 0) + return OPCODE_ASRM; + break; + } + if (Field_dsp340050b49a6c_fld3319dual_slot2_Slot_dual_slot2_get (insn) == 785 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_ADDCM; + if (Field_dsp340050b49a6c_fld3320dual_slot2_Slot_dual_slot2_get (insn) == 801 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_ADDWRP; + if (Field_dsp340050b49a6c_fld3321dual_slot2_Slot_dual_slot2_get (insn) == 817 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_ASR; + if (Field_dsp340050b49a6c_fld3322dual_slot2_Slot_dual_slot2_get (insn) == 833 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_AND128; + if (Field_dsp340050b49a6c_fld3323dual_slot2_Slot_dual_slot2_get (insn) == 849 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_EXTUI4; + if (Field_dsp340050b49a6c_fld3324dual_slot2_Slot_dual_slot2_get (insn) == 865 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_LUT; + if (Field_dsp340050b49a6c_fld3325dual_slot2_Slot_dual_slot2_get (insn) == 881 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_LUT_IEXT; + if (Field_dsp340050b49a6c_fld3326dual_slot2_Slot_dual_slot2_get (insn) == 897 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_ASL; + if (Field_dsp340050b49a6c_fld3327dual_slot2_Slot_dual_slot2_get (insn) == 913 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_LUT_REXT; + if (Field_dsp340050b49a6c_fld3328dual_slot2_Slot_dual_slot2_get (insn) == 929 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MAX8; + if (Field_dsp340050b49a6c_fld3329dual_slot2_Slot_dual_slot2_get (insn) == 945 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MEAN32; + if (Field_dsp340050b49a6c_fld3330dual_slot2_Slot_dual_slot2_get (insn) == 961 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MEAN; + if (Field_dsp340050b49a6c_fld3331dual_slot2_Slot_dual_slot2_get (insn) == 977 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MIN8; + if (Field_dsp340050b49a6c_fld3332dual_slot2_Slot_dual_slot2_get (insn) == 993 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_OR128; + if (Field_dsp340050b49a6c_fld3333dual_slot2_Slot_dual_slot2_get (insn) == 1009 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SUB32; + if (Field_dsp340050b49a6c_fld3334dual_slot2_Slot_dual_slot2_get (insn) == 2 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_BGEI; + if (Field_dsp340050b49a6c_fld3335dual_slot2_Slot_dual_slot2_get (insn) == 3 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SUBCM; + if (Field_dsp340050b49a6c_fld3336dual_slot2_Slot_dual_slot2_get (insn) == 19 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_XOR128; + if (Field_dsp340050b49a6c_fld3337dual_slot2_Slot_dual_slot2_get (insn) == 560 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_ABS8; + if (Field_dsp340050b49a6c_fld3339dual_slot2_Slot_dual_slot2_get (insn) == 561 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_CONJ; + if (Field_dsp340050b49a6c_fld3340dual_slot2_Slot_dual_slot2_get (insn) == 562 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_LUT_PHASOR; + if (Field_dsp340050b49a6c_fld3341dual_slot2_Slot_dual_slot2_get (insn) == 563 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_NCO_UPDATE; + if (Field_dsp340050b49a6c_fld3342dual_slot2_Slot_dual_slot2_get (insn) == 525 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_LUT_WRITE; + if (Field_dsp340050b49a6c_fld3345dual_slot2_Slot_dual_slot2_get (insn) == 9268 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SET_ARGMAX; + if (Field_dsp340050b49a6c_fld3347dual_slot2_Slot_dual_slot2_get (insn) == 9269 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SET_MAX; + if (Field_dsp340050b49a6c_fld3348dual_slot2_Slot_dual_slot2_get (insn) == 9270 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SET_NCO; + switch (Field_dsp340050b49a6c_fld3349dual_slot2_Slot_dual_slot2_get (insn)) + { + case 132151: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_1; + break; + case 136247: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_2; + break; + case 140343: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_3; + break; + case 144439: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_0; + break; + case 148535: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_4; + break; + case 152631: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_1; + break; + case 156727: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_2; + break; + case 160823: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_3; + break; + } + if (Field_dsp340050b49a6c_fld3350dual_slot2_Slot_dual_slot2_get (insn) == 42039 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3907dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_5; + if (Field_dsp340050b49a6c_fld3353dual_slot2_Slot_dual_slot2_get (insn) == 46135 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3907dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_NOP; + if (Field_dsp340050b49a6c_fld3354dual_slot2_Slot_dual_slot2_get (insn) == 2381 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_s4_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SET_SAR; + if (Field_dsp340050b49a6c_fld3356dual_slot2_Slot_dual_slot2_get (insn) == 1229 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3924dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_0; + if (Field_dsp340050b49a6c_fld3358dual_slot2_Slot_dual_slot2_get (insn) == 333 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3918dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SET_HSAR; + if (Field_dsp340050b49a6c_fld3360dual_slot2_Slot_dual_slot2_get (insn) == 568 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MOVCM; + if (Field_dsp340050b49a6c_fld3361dual_slot2_Slot_dual_slot2_get (insn) == 569 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_NEGCM; + if (Field_dsp340050b49a6c_fld3362dual_slot2_Slot_dual_slot2_get (insn) == 570 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_NOT128; + if (Field_dsp340050b49a6c_fld3363dual_slot2_Slot_dual_slot2_get (insn) == 8251 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_CLRCM; + switch (Field_dsp340050b49a6c_fld3364_Slot_dual_slot2_get (insn)) + { + case 52: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_ADD; + break; + case 53: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_ADDX2; + break; + case 54: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_ADDX4; + break; + case 55: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_ADDX8; + break; + case 56: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_ADDI_N; + break; + case 57: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_AND; + break; + case 58: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_ANDB; + break; + case 59: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_LUT_AR; + break; + case 60: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_CLAMPS; + break; + case 61: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_MAX; + break; + case 62: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_MAXU; + break; + case 63: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_MIN; + break; + case 112: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_MINU; + break; + case 113: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_MOVEQZ; + break; + case 114: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_MOVGEZ; + break; + case 115: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_MOVT; + break; + case 116: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_MOVLTZ; + break; + case 117: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_OR; + break; + case 118: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_ORB; + break; + case 119: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_SEXT; + break; + case 120: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_MOVNEZ; + break; + case 121: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_SRC; + break; + case 122: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_SRLI; + break; + case 123: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_SUBX2; + break; + case 124: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_SUB; + break; + case 125: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_SUBX4; + break; + case 126: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_SUBX8; + break; + case 127: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_XOR; + break; + } + if (Field_dsp340050b49a6c_fld3365dual_slot2_Slot_dual_slot2_get (insn) == 8507 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_GET_ARGMAX; + if (Field_dsp340050b49a6c_fld3366dual_slot2_Slot_dual_slot2_get (insn) == 8763 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_GET_HSAR; + if (Field_dsp340050b49a6c_fld3367dual_slot2_Slot_dual_slot2_get (insn) == 9019 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_GET_NCO; + if (Field_dsp340050b49a6c_fld3368dual_slot2_Slot_dual_slot2_get (insn) == 9275 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_GET_HSAR2SAR; + if (Field_dsp340050b49a6c_fld3369dual_slot2_Slot_dual_slot2_get (insn) == 9531 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_GET_SAR; + if (Field_dsp340050b49a6c_fld3370dual_slot2_Slot_dual_slot2_get (insn) == 9787 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_POP128_0; + if (Field_dsp340050b49a6c_fld3371dual_slot2_Slot_dual_slot2_get (insn) == 10043 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_POP128_1; + if (Field_dsp340050b49a6c_fld3372dual_slot2_Slot_dual_slot2_get (insn) == 10299 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_GET_MAX; + if (Field_dsp340050b49a6c_fld3373dual_slot2_Slot_dual_slot2_get (insn) == 10555 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_POP128_2; + if (Field_dsp340050b49a6c_fld3374dual_slot2_Slot_dual_slot2_get (insn) == 10811 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_POP128_3; + if (Field_dsp340050b49a6c_fld3375dual_slot2_Slot_dual_slot2_get (insn) == 11067 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_POP128_5; + if (Field_dsp340050b49a6c_fld3376dual_slot2_Slot_dual_slot2_get (insn) == 11323 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_POP128_4; + if (Field_dsp340050b49a6c_fld3377dual_slot2_Slot_dual_slot2_get (insn) == 11579 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_POP32_0; + if (Field_dsp340050b49a6c_fld3378dual_slot2_Slot_dual_slot2_get (insn) == 11835 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_POP32_1; + if (Field_dsp340050b49a6c_fld3379dual_slot2_Slot_dual_slot2_get (insn) == 12091 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_POP32_2; + if (Field_dsp340050b49a6c_fld3380dual_slot2_Slot_dual_slot2_get (insn) == 572 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_TRANS; + if (Field_dsp340050b49a6c_fld3381dual_slot2_Slot_dual_slot2_get (insn) == 573 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2046_Slot_dual_slot2_get (insn) == 0) + return OPCODE_POP32_3; + if (Field_dsp340050b49a6c_fld3382dual_slot2_Slot_dual_slot2_get (insn) == 287 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3928dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_RDTIEP; + if (Field_dsp340050b49a6c_fld3384dual_slot2_Slot_dual_slot2_get (insn) == 771 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MOVAR2; + if (Field_dsp340050b49a6c_fld3385dual_slot2_Slot_dual_slot2_get (insn) == 787 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SLL; + if (Field_dsp340050b49a6c_fld3386dual_slot2_Slot_dual_slot2_get (insn) == 803 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SWAPB; + switch (Field_dsp340050b49a6c_fld3387dual_slot2_Slot_dual_slot2_get (insn)) + { + case 13059: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SSA8L; + break; + case 13075: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SSL; + break; + } + if (Field_dsp340050b49a6c_fld3388dual_slot2_Slot_dual_slot2_get (insn) == 6547 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3913dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SSR; + if (Field_dsp340050b49a6c_fld3390dual_slot2_Slot_dual_slot2_get (insn) == 3283 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2049_Slot_dual_slot2_get (insn) == 0) + return OPCODE_WRTBSIGQ; + if (Field_dsp340050b49a6c_fld3392dual_slot2_Slot_dual_slot2_get (insn) == 1651 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3900_Slot_dual_slot2_get (insn) == 0) + return OPCODE_WRTSIGQ; + if (Field_dsp340050b49a6c_fld3394dual_slot2_Slot_dual_slot2_get (insn) == 211 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3920dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_AR2SAR_DUP; + if (Field_dsp340050b49a6c_fld3396dual_slot2_Slot_dual_slot2_get (insn) == 115 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3909dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SSA8B; + if (Field_dsp340050b49a6c_fld3397dual_slot2_Slot_dual_slot2_get (insn) == 19 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3919dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_AR2CM_DUP; + if (Field_dsp340050b49a6c_fld3399dual_slot2_Slot_dual_slot2_get (insn) == 19 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3931dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_ARGMAX8; + if (Field_dsp340050b49a6c_fld3401dual_slot2_Slot_dual_slot2_get (insn) == 33 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3934dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SUBMEAN; + if (Field_dsp340050b49a6c_fld3403dual_slot2_Slot_dual_slot2_get (insn) == 41 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3922dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_PQ2CM; + if (Field_dsp340050b49a6c_fld3404dual_slot2_Slot_dual_slot2_get (insn) == 25 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3910dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SSAI; + if (Field_dsp340050b49a6c_fld3406dual_slot2_Slot_dual_slot2_get (insn) == 9 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3935dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SUBWRP; + if (Field_dsp340050b49a6c_fld3407_Slot_dual_slot2_get (insn) == 1 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3905dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MOVI; + if (Field_dsp340050b49a6c_fld3408dual_slot2_Slot_dual_slot2_get (insn) == 1 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3901dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_BGEUI; + if (Field_dsp340050b49a6c_fld3410_Slot_dual_slot2_get (insn) == 3 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3929dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SETTIEP; + if (Field_dsp340050b49a6c_fld3411dual_slot2_Slot_dual_slot2_get (insn) == 5 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3933dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_ASLM32; + if (Field_dsp340050b49a6c_fld3412dual_slot2_Slot_dual_slot2_get (insn) == 18 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3927dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_QREADY; + if (Field_dsp340050b49a6c_fld3413dual_slot2_Slot_dual_slot2_get (insn) == 19 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3930dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_WRTBSIGQM; + if (Field_dsp340050b49a6c_fld3414dual_slot2_Slot_dual_slot2_get (insn) == 1 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_ADDMI; + if (Field_dsp340050b49a6c_fld3415dual_slot2_Slot_dual_slot2_get (insn) == 17 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_BALL; + if (Field_dsp340050b49a6c_fld3416dual_slot2_Slot_dual_slot2_get (insn) == 33 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_BANY; + if (Field_dsp340050b49a6c_fld3417dual_slot2_Slot_dual_slot2_get (insn) == 49 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_BBC; + if (Field_dsp340050b49a6c_fld3418dual_slot2_Slot_dual_slot2_get (insn) == 1 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_BBCI; + if (Field_dsp340050b49a6c_fld3419dual_slot2_Slot_dual_slot2_get (insn) == 18 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_BBS; + if (Field_dsp340050b49a6c_fld3420dual_slot2_Slot_dual_slot2_get (insn) == 19 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_BGE; + if (Field_dsp340050b49a6c_fld3421dual_slot2_Slot_dual_slot2_get (insn) == 34 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_BEQ; + if (Field_dsp340050b49a6c_fld3422dual_slot2_Slot_dual_slot2_get (insn) == 35 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_BGEU; + if (Field_dsp340050b49a6c_fld3423dual_slot2_Slot_dual_slot2_get (insn) == 50 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_BLT; + if (Field_dsp340050b49a6c_fld3424dual_slot2_Slot_dual_slot2_get (insn) == 51 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_BLTU; + if (Field_dsp340050b49a6c_fld3425dual_slot2_Slot_dual_slot2_get (insn) == 2 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_BBSI; + if (Field_dsp340050b49a6c_fld3426dual_slot2_Slot_dual_slot2_get (insn) == 6 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_BNALL; + if (Field_dsp340050b49a6c_fld3427dual_slot2_Slot_dual_slot2_get (insn) == 7 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_ASL32; + if (Field_dsp340050b49a6c_fld3428dual_slot2_Slot_dual_slot2_get (insn) == 23 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_ASR32; + if (Field_dsp340050b49a6c_fld3429dual_slot2_Slot_dual_slot2_get (insn) == 39 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_MOVCND8_0; + if (Field_dsp340050b49a6c_fld3430dual_slot2_Slot_dual_slot2_get (insn) == 55 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_MOVCND8_3; + if (Field_dsp340050b49a6c_fld3431dual_slot2_Slot_dual_slot2_get (insn) == 71 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_MOVCND8_1; + if (Field_dsp340050b49a6c_fld3432dual_slot2_Slot_dual_slot2_get (insn) == 87 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_MOVCND8_4; + if (Field_dsp340050b49a6c_fld3433dual_slot2_Slot_dual_slot2_get (insn) == 103 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_MOVCND8_5; + if (Field_dsp340050b49a6c_fld3434dual_slot2_Slot_dual_slot2_get (insn) == 119 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_MOVCND8_6; + if (Field_dsp340050b49a6c_fld3435dual_slot2_Slot_dual_slot2_get (insn) == 135 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_MOVCND8_2; + if (Field_dsp340050b49a6c_fld3436dual_slot2_Slot_dual_slot2_get (insn) == 151 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_MOVCND8_7; + if (Field_dsp340050b49a6c_fld3437dual_slot2_Slot_dual_slot2_get (insn) == 167 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_MOVCND_0; + if (Field_dsp340050b49a6c_fld3438dual_slot2_Slot_dual_slot2_get (insn) == 183 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_MOVCND_2; + if (Field_dsp340050b49a6c_fld3439dual_slot2_Slot_dual_slot2_get (insn) == 199 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_MOVCND_1; + if (Field_dsp340050b49a6c_fld3440dual_slot2_Slot_dual_slot2_get (insn) == 215 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_MOVCND_3; + if (Field_dsp340050b49a6c_fld3441dual_slot2_Slot_dual_slot2_get (insn) == 231 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_MOVCND_4; + if (Field_dsp340050b49a6c_fld3442dual_slot2_Slot_dual_slot2_get (insn) == 247 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_MOVCND_5; + if (Field_dsp340050b49a6c_fld3443dual_slot2_Slot_dual_slot2_get (insn) == 20 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_BNE; + if (Field_dsp340050b49a6c_fld3444dual_slot2_Slot_dual_slot2_get (insn) == 261 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_MOVCND_6; + if (Field_dsp340050b49a6c_fld3445dual_slot2_Slot_dual_slot2_get (insn) == 277 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_PERM; + if (Field_dsp340050b49a6c_fld3446dual_slot2_Slot_dual_slot2_get (insn) == 1172 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_ADD16; + if (Field_dsp340050b49a6c_fld3448dual_slot2_Slot_dual_slot2_get (insn) == 2346 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3925dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_PUSH128; + if (Field_dsp340050b49a6c_fld3450dual_slot2_Slot_dual_slot2_get (insn) == 2347 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2046_Slot_dual_slot2_get (insn) == 0) + return OPCODE_ANY8; + if (Field_dsp340050b49a6c_fld3451dual_slot2_Slot_dual_slot2_get (insn) == 587 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3914dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_ANY4; + switch (Field_dsp340050b49a6c_fld3453dual_slot2_Slot_dual_slot2_get (insn)) + { + case 4869: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_NSA; + break; + case 4885: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_NSAU; + break; + case 4901: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_PUSH128_PQ; + break; + case 4917: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_SUBARX; + break; + } + if (Field_dsp340050b49a6c_fld3454dual_slot2_Slot_dual_slot2_get (insn) == 2469 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3466_Slot_dual_slot2_get (insn) == 0) + return OPCODE_PUSH32; + if (Field_dsp340050b49a6c_fld3456dual_slot2_Slot_dual_slot2_get (insn) == 2485 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3466_Slot_dual_slot2_get (insn) == 0) + return OPCODE_WRTIEP; + if (Field_dsp340050b49a6c_fld3457dual_slot2_Slot_dual_slot2_get (insn) == 629 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3917dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SET_EXT_REGS; + if (Field_dsp340050b49a6c_fld3458dual_slot2_Slot_dual_slot2_get (insn) == 85 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3919dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_ADDAR2; + if (Field_dsp340050b49a6c_fld3459dual_slot2_Slot_dual_slot2_get (insn) == 53 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3896dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MOV_N; + if (Field_dsp340050b49a6c_fld3460dual_slot2_Slot_dual_slot2_get (insn) == 11 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3921dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MOVCND_7; + if (Field_dsp340050b49a6c_fld3461dual_slot2_Slot_dual_slot2_get (insn) == 9 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2049_Slot_dual_slot2_get (insn) == 0) + return OPCODE_BNONE; + if (Field_dsp340050b49a6c_fld3462dual_slot2_Slot_dual_slot2_get (insn) == 49 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3894dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_AR2CM_LN; + if (Field_dsp340050b49a6c_fld3464dual_slot2_Slot_dual_slot2_get (insn) == 53 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3894dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_BEQZ_N; + if (Field_dsp340050b49a6c_fld3465dual_slot2_Slot_dual_slot2_get (insn) == 29 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3895dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_BNEZ_N; + if (Field_dsp340050b49a6c_fld3467dual_slot2_Slot_dual_slot2_get (insn) == 1 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3899dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_ADDI; + if (Field_dsp340050b49a6c_fld3468dual_slot2_Slot_dual_slot2_get (insn) == 3 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3897dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_MOVI_N; + switch (Field_dsp340050b49a6c_fld3469dual_slot2_Slot_dual_slot2_get (insn)) + { + case 24: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_SLLI; + break; + case 25: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_SRAI; + break; + } + if (Field_dsp340050b49a6c_fld3470dual_slot2_Slot_dual_slot2_get (insn) == 80 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_ASLM; + if (Field_dsp340050b49a6c_fld3471dual_slot2_Slot_dual_slot2_get (insn) == 81 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_CMP8; + if (Field_dsp340050b49a6c_fld3472dual_slot2_Slot_dual_slot2_get (insn) == 82 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_CMP_I; + if (Field_dsp340050b49a6c_fld3473dual_slot2_Slot_dual_slot2_get (insn) == 83 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_LSRM; + if (Field_dsp340050b49a6c_fld3474dual_slot2_Slot_dual_slot2_get (insn) == 84 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 2) + return OPCODE_CMP_R; + if (Field_dsp340050b49a6c_fld3475dual_slot2_Slot_dual_slot2_get (insn) == 325 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3898dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_ABS; + if (Field_dsp340050b49a6c_fld3477dual_slot2_Slot_dual_slot2_get (insn) == 341 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3898dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SRA; + if (Field_dsp340050b49a6c_fld3478dual_slot2_Slot_dual_slot2_get (insn) == 181 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3908dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_SRL; + if (Field_dsp340050b49a6c_fld3479dual_slot2_Slot_dual_slot2_get (insn) == 43 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3906dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_NEG; + if (Field_dsp340050b49a6c_fld3480dual_slot2_Slot_dual_slot2_get (insn) == 22 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 2 && + Field_s4_Slot_dual_slot2_get (insn) == 0) + return OPCODE_LSLM; + if (Field_dsp340050b49a6c_fld3481dual_slot2_Slot_dual_slot2_get (insn) == 23 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld2046_Slot_dual_slot2_get (insn) == 0) + return OPCODE_CM2AR_LN; + if (Field_dsp340050b49a6c_fld3482dual_slot2_Slot_dual_slot2_get (insn) == 2 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3903dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_BLTZ; + if (Field_dsp340050b49a6c_fld3484dual_slot2_Slot_dual_slot2_get (insn) == 3 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3916dual_slot2_Slot_dual_slot2_get (insn) == 0) + return OPCODE_XORB; + if (Field_r_Slot_dual_slot2_get (insn) == 0 && + Field_op0_s21_Slot_dual_slot2_get (insn) == 1) + return OPCODE_BITFINS; + switch (Field_t_Slot_dual_slot2_get (insn)) + { + case 0: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 0) + return OPCODE_BITFEXT; + break; + case 8: + if (Field_op0_s21_Slot_dual_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3314_Slot_dual_slot2_get (insn) == 0) + return OPCODE_BLTI; + break; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_dual_slot0_decode (const xtensa_insnbuf insn) +{ + if (Field_dsp340050b49a6c_fld2056_Slot_dual_slot0_get (insn) == 3 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 2 && + Field_imm8_Slot_dual_slot0_get (insn) == 0) + return OPCODE_MOVCM2PQ; + switch (Field_dsp340050b49a6c_fld2057_Slot_dual_slot0_get (insn)) + { + case 2842: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_AR2CM_DUP; + break; + case 2843: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_MOV_N; + break; + case 2874: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_NSA; + break; + case 2906: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_NSAU; + break; + case 2970: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_PUSH128_PQ; + break; + } + switch (Field_dsp340050b49a6c_fld3487dual_slot0_Slot_dual_slot0_get (insn)) + { + case 0: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 0) + return OPCODE_BBCI; + break; + case 1: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 0) + return OPCODE_BBSI; + break; + } + switch (Field_dsp340050b49a6c_fld3488dual_slot0_Slot_dual_slot0_get (insn)) + { + case 0: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_EXTUI; + break; + case 3: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4 && + Field_sae_Slot_dual_slot0_get (insn) == 0) + return OPCODE_ULT_S; + break; + } + switch (Field_dsp340050b49a6c_fld3489dual_slot0_Slot_dual_slot0_get (insn)) + { + case 2: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_BEQZ; + break; + case 3: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_BNEZ; + break; + case 4: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_BGEZ; + break; + case 5: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4 && + Field_dsp340050b49a6c_fld2079_Slot_dual_slot0_get (insn) == 0) + return OPCODE_ULE_S; + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_LSI; + break; + case 6: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_LSIU; + break; + case 7: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_MOVI; + break; + case 8: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_BLTZ; + break; + case 9: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SSI; + break; + case 10: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SSIU; + break; + case 14: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld2037_Slot_dual_slot0_get (insn) == 0) + return OPCODE_LCM_U; + break; + } + if (Field_dsp340050b49a6c_fld3490dual_slot0_Slot_dual_slot0_get (insn) == 88 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_LAC32_R; + if (Field_dsp340050b49a6c_fld3491dual_slot0_Slot_dual_slot0_get (insn) == 177 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_LAC_IH; + if (Field_dsp340050b49a6c_fld3492dual_slot0_Slot_dual_slot0_get (insn) == 185 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_LAC_RL; + if (Field_dsp340050b49a6c_fld3493dual_slot0_Slot_dual_slot0_get (insn) == 178 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_LAC_IL; + if (Field_dsp340050b49a6c_fld3494dual_slot0_Slot_dual_slot0_get (insn) == 355 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_LAC2X64_0; + if (Field_dsp340050b49a6c_fld3496dual_slot0_Slot_dual_slot0_get (insn) == 371 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_LAC2X64_2; + if (Field_dsp340050b49a6c_fld3497dual_slot0_Slot_dual_slot0_get (insn) == 362 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_LAC2X64_1; + if (Field_dsp340050b49a6c_fld3498dual_slot0_Slot_dual_slot0_get (insn) == 363 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_LAC2X64_3; + if (Field_dsp340050b49a6c_fld3499dual_slot0_Slot_dual_slot0_get (insn) == 5750 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_GET_LLR_BUF; + if (Field_dsp340050b49a6c_fld3500dual_slot0_Slot_dual_slot0_get (insn) == 11502 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_ANY4; + if (Field_dsp340050b49a6c_fld3502dual_slot0_Slot_dual_slot0_get (insn) == 23006 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_ANY8; + if (Field_dsp340050b49a6c_fld3504dual_slot0_Slot_dual_slot0_get (insn) == 23007 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_GET_SMOD_BUF; + if (Field_dsp340050b49a6c_fld3505dual_slot0_Slot_dual_slot0_get (insn) == 11628 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_PUSH2X128_PQ; + switch (Field_dsp340050b49a6c_fld3506dual_slot0_Slot_dual_slot0_get (insn)) + { + case 23258: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP128_2PQ_1; + break; + case 23259: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP128_2PQ_3; + break; + case 23260: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP128_2PQ_2; + break; + case 23261: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP128_2PQ_4; + break; + case 23262: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP128_2PQ_5; + break; + case 23263: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SSAI; + break; + case 23504: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP128_2PQ_0; + break; + } + switch (Field_dsp340050b49a6c_fld3507dual_slot0_Slot_dual_slot0_get (insn)) + { + case 47010: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP2X128_2PQ_01; + break; + case 47011: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP2X128_2PQ_23; + break; + case 47012: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP2X128_2PQ_03; + break; + case 47013: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SET_LLR_POS; + break; + case 47014: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SET_PERM_REG; + break; + case 47015: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SET_PHASOR_N; + break; + case 47016: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP2X128_2PQ_21; + break; + case 47017: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SET_PHASOR_OFFSET; + break; + case 47018: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SET_SCALE_REG; + break; + case 47019: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SET_SOV; + break; + case 47020: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SET_SMOD_POS; + break; + case 47021: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SET_WGHT; + break; + case 47022: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SSA8B; + break; + case 47023: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SSA8L; + break; + } + if (Field_dsp340050b49a6c_fld3508dual_slot0_Slot_dual_slot0_get (insn) == 47024 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_CLRCM; + if (Field_dsp340050b49a6c_fld3509dual_slot0_Slot_dual_slot0_get (insn) == 47025 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_GET_HSAR; + if (Field_dsp340050b49a6c_fld3510dual_slot0_Slot_dual_slot0_get (insn) == 47026 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_GET_HSAR2SAR; + if (Field_dsp340050b49a6c_fld3511dual_slot0_Slot_dual_slot0_get (insn) == 47027 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP128_0; + if (Field_dsp340050b49a6c_fld3512dual_slot0_Slot_dual_slot0_get (insn) == 47028 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_GET_SAR; + if (Field_dsp340050b49a6c_fld3513dual_slot0_Slot_dual_slot0_get (insn) == 47029 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP128_1; + if (Field_dsp340050b49a6c_fld3514dual_slot0_Slot_dual_slot0_get (insn) == 47030 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP128_2; + if (Field_dsp340050b49a6c_fld3515dual_slot0_Slot_dual_slot0_get (insn) == 47031 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP128_3; + if (Field_dsp340050b49a6c_fld3516dual_slot0_Slot_dual_slot0_get (insn) == 47032 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_GET_SMOD_OFFSET_TABLE; + if (Field_dsp340050b49a6c_fld3517dual_slot0_Slot_dual_slot0_get (insn) == 47033 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP128_4; + if (Field_dsp340050b49a6c_fld3518dual_slot0_Slot_dual_slot0_get (insn) == 23517 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_s8_Slot_dual_slot0_get (insn) == 0) + return OPCODE_POP128_5; + if (Field_dsp340050b49a6c_fld3519dual_slot0_Slot_dual_slot0_get (insn) == 11759 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3939dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_NOP; + if (Field_dsp340050b49a6c_fld3520dual_slot0_Slot_dual_slot0_get (insn) == 5942 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld2056_Slot_dual_slot0_get (insn) == 0) + return OPCODE_SSL; + if (Field_dsp340050b49a6c_fld3522dual_slot0_Slot_dual_slot0_get (insn) == 5943 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3950dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_POP16LLR_1; + if (Field_dsp340050b49a6c_fld3523dual_slot0_Slot_dual_slot0_get (insn) == 1501 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_bbi_Slot_dual_slot0_get (insn) == 0) + return OPCODE_SSR; + if (Field_dsp340050b49a6c_fld3524dual_slot0_Slot_dual_slot0_get (insn) == 765 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3943dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_CLRAC; + if (Field_dsp340050b49a6c_fld3527dual_slot0_Slot_dual_slot0_get (insn) == 45 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld2049_Slot_dual_slot0_get (insn) == 0) + return OPCODE_LAC_RH; + switch (Field_dsp340050b49a6c_fld3529dual_slot0_Slot_dual_slot0_get (insn)) + { + case 707: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_AR2CM_LN; + break; + case 711: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_AR2CM_LN_I; + break; + } + if (Field_dsp340050b49a6c_fld3530dual_slot0_Slot_dual_slot0_get (insn) == 359 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld2072_Slot_dual_slot0_get (insn) == 0) + return OPCODE_AR2CM_LN_R; + switch (Field_dsp340050b49a6c_fld3531_Slot_dual_slot0_get (insn)) + { + case 120: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SAC2X32; + break; + case 121: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SAC32_R; + break; + case 122: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SCM_PINC; + break; + case 123: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SLLI; + break; + case 124: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SCM_U; + break; + case 125: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SRAI; + break; + } + if (Field_dsp340050b49a6c_fld3532dual_slot0_Slot_dual_slot0_get (insn) == 183 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3602_Slot_dual_slot0_get (insn) == 0) + return OPCODE_BEQZ_N; + if (Field_dsp340050b49a6c_fld3533dual_slot0_Slot_dual_slot0_get (insn) == 95 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3936dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_BNEZ_N; + if (Field_dsp340050b49a6c_fld3535dual_slot0_Slot_dual_slot0_get (insn) == 48 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld2066_Slot_dual_slot0_get (insn) == 0) + return OPCODE_LAC2X32; + if (Field_dsp340050b49a6c_fld3536dual_slot0_Slot_dual_slot0_get (insn) == 193 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld2060_Slot_dual_slot0_get (insn) == 0) + return OPCODE_POP128_2M_0; + if (Field_dsp340050b49a6c_fld3537dual_slot0_Slot_dual_slot0_get (insn) == 197 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld2060_Slot_dual_slot0_get (insn) == 0) + return OPCODE_POP128_2M_2; + if (Field_dsp340050b49a6c_fld3538dual_slot0_Slot_dual_slot0_get (insn) == 101 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3957dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_POP128_2M_3; + if (Field_dsp340050b49a6c_fld3539dual_slot0_Slot_dual_slot0_get (insn) == 25 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3954dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_POP128_2M_1; + if (Field_dsp340050b49a6c_fld3541dual_slot0_Slot_dual_slot0_get (insn) == 104 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_LCM_PINC; + if (Field_dsp340050b49a6c_fld3542dual_slot0_Slot_dual_slot0_get (insn) == 105 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_LP; + if (Field_dsp340050b49a6c_fld3543dual_slot0_Slot_dual_slot0_get (insn) == 106 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_LQ; + if (Field_dsp340050b49a6c_fld3544dual_slot0_Slot_dual_slot0_get (insn) == 3331 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_ABS; + if (Field_dsp340050b49a6c_fld3545dual_slot0_Slot_dual_slot0_get (insn) == 3339 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_CONJ; + if (Field_dsp340050b49a6c_fld3546dual_slot0_Slot_dual_slot0_get (insn) == 3347 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_MOVCM; + if (Field_dsp340050b49a6c_fld3547dual_slot0_Slot_dual_slot0_get (insn) == 3355 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_NEGCM; + if (Field_dsp340050b49a6c_fld3548dual_slot0_Slot_dual_slot0_get (insn) == 3363 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_MOV_I; + if (Field_dsp340050b49a6c_fld3549dual_slot0_Slot_dual_slot0_get (insn) == 3371 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SRA; + if (Field_dsp340050b49a6c_fld3550dual_slot0_Slot_dual_slot0_get (insn) == 3379 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SRL; + if (Field_dsp340050b49a6c_fld3551dual_slot0_Slot_dual_slot0_get (insn) == 6763 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_CLB_C; + switch (Field_dsp340050b49a6c_fld3552_Slot_dual_slot0_get (insn)) + { + case 146: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_EXT; + break; + case 147: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_PUSH128_M; + break; + case 148: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_EXT_R; + break; + case 149: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SAC2X64_0; + break; + case 150: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SAC2X64_1; + break; + case 151: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SAC2X64_2; + break; + } + if (Field_dsp340050b49a6c_fld3553dual_slot0_Slot_dual_slot0_get (insn) == 6779 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_CLB_R; + if (Field_dsp340050b49a6c_fld3554dual_slot0_Slot_dual_slot0_get (insn) == 3395 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_MOV_R; + if (Field_dsp340050b49a6c_fld3555dual_slot0_Slot_dual_slot0_get (insn) == 6795 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_MINCLB_C; + if (Field_dsp340050b49a6c_fld3556dual_slot0_Slot_dual_slot0_get (insn) == 6811 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SMINCLB_C; + if (Field_dsp340050b49a6c_fld3557dual_slot0_Slot_dual_slot0_get (insn) == 6819 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_MINCLB_R; + if (Field_dsp340050b49a6c_fld3558dual_slot0_Slot_dual_slot0_get (insn) == 6835 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SMINCLB_R; + if (Field_dsp340050b49a6c_fld3559dual_slot0_Slot_dual_slot0_get (insn) == 6827 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SET_LLR_BUF; + if (Field_dsp340050b49a6c_fld3560dual_slot0_Slot_dual_slot0_get (insn) == 54555 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_GET_INTERP_EXT_L; + if (Field_dsp340050b49a6c_fld3562dual_slot0_Slot_dual_slot0_get (insn) == 54587 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_GET_INTERP_EXT_N; + if (Field_dsp340050b49a6c_fld3563dual_slot0_Slot_dual_slot0_get (insn) == 54619 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_GET_LLR_POS; + if (Field_dsp340050b49a6c_fld3564dual_slot0_Slot_dual_slot0_get (insn) == 54651 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_GET_PHASOR_N; + if (Field_dsp340050b49a6c_fld3565dual_slot0_Slot_dual_slot0_get (insn) == 54683 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_GET_PERM_REG; + if (Field_dsp340050b49a6c_fld3566dual_slot0_Slot_dual_slot0_get (insn) == 54715 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_GET_PHASOR_OFFSET; + if (Field_dsp340050b49a6c_fld3567dual_slot0_Slot_dual_slot0_get (insn) == 54747 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_GET_SCALE_REG; + if (Field_dsp340050b49a6c_fld3568dual_slot0_Slot_dual_slot0_get (insn) == 54779 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_GET_SMOD_POS; + if (Field_dsp340050b49a6c_fld3569dual_slot0_Slot_dual_slot0_get (insn) == 6851 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_PUSH128; + if (Field_dsp340050b49a6c_fld3570dual_slot0_Slot_dual_slot0_get (insn) == 54795 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_GET_SOV; + if (Field_dsp340050b49a6c_fld3571dual_slot0_Slot_dual_slot0_get (insn) == 54827 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP32_1; + if (Field_dsp340050b49a6c_fld3572dual_slot0_Slot_dual_slot0_get (insn) == 54859 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP32_2; + if (Field_dsp340050b49a6c_fld3573dual_slot0_Slot_dual_slot0_get (insn) == 54891 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SET_SAR; + if (Field_dsp340050b49a6c_fld3574dual_slot0_Slot_dual_slot0_get (insn) == 54923 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_POP32_3; + if (Field_dsp340050b49a6c_fld3575dual_slot0_Slot_dual_slot0_get (insn) == 54955 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_SET_SMOD_OFFSET_TABLE; + if (Field_dsp340050b49a6c_fld3576dual_slot0_Slot_dual_slot0_get (insn) == 109771 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_ADDAC_I2R; + if (Field_dsp340050b49a6c_fld3577dual_slot0_Slot_dual_slot0_get (insn) == 109803 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_ADDAC_R2I; + if (Field_dsp340050b49a6c_fld3578dual_slot0_Slot_dual_slot0_get (insn) == 110027 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_REDAC; + if (Field_dsp340050b49a6c_fld3579dual_slot0_Slot_dual_slot0_get (insn) == 110059 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_REDAC2; + if (Field_dsp340050b49a6c_fld3580dual_slot0_Slot_dual_slot0_get (insn) == 54803 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_GET_WGHT; + if (Field_dsp340050b49a6c_fld3581dual_slot0_Slot_dual_slot0_get (insn) == 54811 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3620dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_REDAC4; + if (Field_dsp340050b49a6c_fld3582dual_slot0_Slot_dual_slot0_get (insn) == 27419 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3959dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_REDACS; + if (Field_dsp340050b49a6c_fld3583dual_slot0_Slot_dual_slot0_get (insn) == 13723 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3960dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_SUBAC_I2R; + switch (Field_dsp340050b49a6c_fld3584_Slot_dual_slot0_get (insn)) + { + case 2: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3937dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_BLTUI; + break; + case 3: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3552_Slot_dual_slot0_get (insn) == 0) + return OPCODE_ASLACM; + break; + } + if (Field_dsp340050b49a6c_fld3585dual_slot0_Slot_dual_slot0_get (insn) == 6875 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3961dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_SUBAC_R2I; + if (Field_dsp340050b49a6c_fld3587dual_slot0_Slot_dual_slot0_get (insn) == 1723 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3610_Slot_dual_slot0_get (insn) == 0) + return OPCODE_POP32_0; + if (Field_dsp340050b49a6c_fld3588dual_slot0_Slot_dual_slot0_get (insn) == 219 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3938dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_NEG; + if (Field_dsp340050b49a6c_fld3589dual_slot0_Slot_dual_slot0_get (insn) == 106 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_s8_Slot_dual_slot0_get (insn) == 0) + return OPCODE_LCM; + if (Field_dsp340050b49a6c_fld3590dual_slot0_Slot_dual_slot0_get (insn) == 3331 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_EXT32_I; + if (Field_dsp340050b49a6c_fld3591dual_slot0_Slot_dual_slot0_get (insn) == 3335 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_EXT32_R; + if (Field_dsp340050b49a6c_fld3592dual_slot0_Slot_dual_slot0_get (insn) == 3339 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_EXT_2FIFO_0; + if (Field_dsp340050b49a6c_fld3593dual_slot0_Slot_dual_slot0_get (insn) == 3343 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_EXT_R2FIFO_0; + if (Field_dsp340050b49a6c_fld3594dual_slot0_Slot_dual_slot0_get (insn) == 3363 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_EXT_2FIFO_1; + if (Field_dsp340050b49a6c_fld3595dual_slot0_Slot_dual_slot0_get (insn) == 3367 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_EXT_R2FIFO_1; + if (Field_dsp340050b49a6c_fld3596dual_slot0_Slot_dual_slot0_get (insn) == 3371 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_EXT_R2FIFO_2; + if (Field_dsp340050b49a6c_fld3597dual_slot0_Slot_dual_slot0_get (insn) == 3375 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_EXT_R2FIFO_3; + if (Field_dsp340050b49a6c_fld3598dual_slot0_Slot_dual_slot0_get (insn) == 851 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3951dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_EXT_2FIFO_2; + if (Field_dsp340050b49a6c_fld3599dual_slot0_Slot_dual_slot0_get (insn) == 855 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3941dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_SET_SMOD_BUF; + if (Field_dsp340050b49a6c_fld3600dual_slot0_Slot_dual_slot0_get (insn) == 219 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3952dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_EXT_2FIFO_3; + if (Field_dsp340050b49a6c_fld3601dual_slot0_Slot_dual_slot0_get (insn) == 213 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3945dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_CM2AR_LN; + if (Field_dsp340050b49a6c_fld3603dual_slot0_Slot_dual_slot0_get (insn) == 215 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3945dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_CM2AR_LN_I; + if (Field_dsp340050b49a6c_fld3604dual_slot0_Slot_dual_slot0_get (insn) == 111 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 1 && + Field_dsp340050b49a6c_fld3946dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_CM2AR_LN_R; + if (Field_dsp340050b49a6c_fld3606dual_slot0_Slot_dual_slot0_get (insn) == 5 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 2) + return OPCODE_ABS_S; + if (Field_dsp340050b49a6c_fld3607dual_slot0_Slot_dual_slot0_get (insn) == 21 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 2) + return OPCODE_MOV_S; + if (Field_dsp340050b49a6c_fld3608dual_slot0_Slot_dual_slot0_get (insn) == 37 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 2) + return OPCODE_NEG_S; + if (Field_dsp340050b49a6c_fld3609dual_slot0_Slot_dual_slot0_get (insn) == 106 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3620dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_MOVAC; + if (Field_dsp340050b49a6c_fld3611dual_slot0_Slot_dual_slot0_get (insn) == 107 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3620dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_SWAPAC_RI; + if (Field_dsp340050b49a6c_fld3612dual_slot0_Slot_dual_slot0_get (insn) == 21 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3602_Slot_dual_slot0_get (insn) == 0) + return OPCODE_PUSH32; + if (Field_dsp340050b49a6c_fld3613dual_slot0_Slot_dual_slot0_get (insn) == 21 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3936dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_RFR; + if (Field_dsp340050b49a6c_fld3614dual_slot0_Slot_dual_slot0_get (insn) == 21 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld2079_Slot_dual_slot0_get (insn) == 0) + return OPCODE_SLL; + if (Field_dsp340050b49a6c_fld3615dual_slot0_Slot_dual_slot0_get (insn) == 21 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3958dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_ASRAC; + if (Field_dsp340050b49a6c_fld3616dual_slot0_Slot_dual_slot0_get (insn) == 21 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3947dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_MOV2AC32_I; + if (Field_dsp340050b49a6c_fld3618dual_slot0_Slot_dual_slot0_get (insn) == 21 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 2 && + Field_dsp340050b49a6c_fld3949dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_MOV2AC32_R; + if (Field_dsp340050b49a6c_fld3619_Slot_dual_slot0_get (insn) == 1 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 4 && + Field_dsp340050b49a6c_fld3940dual_slot0_Slot_dual_slot0_get (insn) == 0) + return OPCODE_FLOOR_S; + if (Field_dsp340050b49a6c_fld3620dual_slot0_Slot_dual_slot0_get (insn) == 1 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 3 && + Field_dsp340050b49a6c_fld2048_Slot_dual_slot0_get (insn) == 0) + return OPCODE_L32I; + if (Field_dsp340050b49a6c_fld3621dual_slot0_Slot_dual_slot0_get (insn) == 42 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SAC_IH; + if (Field_dsp340050b49a6c_fld3622dual_slot0_Slot_dual_slot0_get (insn) == 43 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SAC_RH; + if (Field_dsp340050b49a6c_fld3623dual_slot0_Slot_dual_slot0_get (insn) == 44 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SAC_IL; + if (Field_dsp340050b49a6c_fld3624dual_slot0_Slot_dual_slot0_get (insn) == 45 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SAC_RL; + if (Field_dsp340050b49a6c_fld3625dual_slot0_Slot_dual_slot0_get (insn) == 38 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 4 && + Field_dsp340050b49a6c_fld3602_Slot_dual_slot0_get (insn) == 0) + return OPCODE_MOVI_N; + if (Field_dsp340050b49a6c_fld3626dual_slot0_Slot_dual_slot0_get (insn) == 39 && + Field_op0_s23_Slot_dual_slot0_get (insn) == 4 && + Field_dsp340050b49a6c_fld3602_Slot_dual_slot0_get (insn) == 0) + return OPCODE_SAC2X64_3; + switch (Field_imm8_Slot_dual_slot0_get (insn)) + { + case 0: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_ADDX4; + break; + case 1: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_ADDX8; + break; + case 2: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_AND; + break; + case 3: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_L32I_N; + break; + case 4: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_ANDB; + break; + case 5: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_LCM_PINC_X; + break; + case 6: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_LCM_X; + break; + case 7: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_LCM_XU; + break; + case 8: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_CEIL_S; + break; + case 9: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_LP_X; + break; + case 10: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_LQ_X; + break; + case 11: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_LUT0; + break; + case 12: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_LSXU; + break; + case 13: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_LUT1; + break; + case 14: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_LUT2; + break; + case 15: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_LUT3; + break; + case 16: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_CLAMPS; + break; + case 17: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MADD_S; + break; + case 18: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MAX; + break; + case 19: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MINU; + break; + case 20: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MAXU; + break; + case 21: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MOVEQZ; + break; + case 22: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MOVEQZ_S; + break; + case 23: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MOVF_S; + break; + case 24: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MIN; + break; + case 25: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MOVGEZ; + break; + case 26: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MOVGEZ_S; + break; + case 27: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MOVLTZ_S; + break; + case 28: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MOVLTZ; + break; + case 29: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MOVNEZ; + break; + case 30: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MOVNEZ_S; + break; + case 31: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MOVT; + break; + case 32: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_COMB_AR; + break; + case 33: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MOVT_S; + break; + case 34: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MSUB_S; + break; + case 35: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_OLT_S; + break; + case 36: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_MUL_S; + break; + case 37: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_OR; + break; + case 38: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_ORB; + break; + case 39: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_ROUND_S; + break; + case 40: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_OEQ_S; + break; + case 41: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_S32I_N; + break; + case 46: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SCM; + break; + case 47: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SCM_PINC_X; + break; + case 48: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_OLE_S; + break; + case 49: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SCM_X; + break; + case 50: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SCM_XU; + break; + case 51: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SRLI; + break; + case 52: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SEXT; + break; + case 53: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SSX; + break; + case 54: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SSXU; + break; + case 55: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_STORE_P; + break; + case 56: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SRC; + break; + case 57: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_STORE_Q; + break; + case 58: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_STSWAPBM; + break; + case 59: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SUB; + break; + case 60: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_STSWAPBMU; + break; + case 61: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SUB_S; + break; + case 62: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SUBX2; + break; + case 63: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SUBX4; + break; + case 64: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_FLOAT_S; + break; + case 65: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_SUBX8; + break; + case 66: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_TRUNC_S; + break; + case 67: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_UN_S; + break; + case 68: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_UEQ_S; + break; + case 69: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_UTRUNC_S; + break; + case 70: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_XOR; + break; + case 71: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_XORB; + break; + case 72: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 4) + return OPCODE_UFLOAT_S; + break; + case 252: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_ADD; + break; + case 253: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_ADD_S; + break; + case 254: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_ADDI_N; + break; + case 255: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 1) + return OPCODE_ADDX2; + break; + } + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 5) + return OPCODE_L32R; + switch (Field_r_Slot_dual_slot0_get (insn)) + { + case 0: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 3) + return OPCODE_BNE; + break; + case 1: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 3) + return OPCODE_BNONE; + break; + case 2: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 3) + return OPCODE_L16SI; + break; + case 3: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 3) + return OPCODE_L8UI; + break; + case 4: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 0) + return OPCODE_ADDI; + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 3) + return OPCODE_L16UI; + break; + case 5: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 0) + return OPCODE_BALL; + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 3) + return OPCODE_S16I; + break; + case 6: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 0) + return OPCODE_BANY; + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 3) + return OPCODE_S32I; + break; + case 7: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 0) + return OPCODE_BBC; + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 3) + return OPCODE_S8I; + break; + case 8: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 0) + return OPCODE_ADDMI; + break; + case 9: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 0) + return OPCODE_BBS; + break; + case 10: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 0) + return OPCODE_BEQ; + break; + case 11: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 0) + return OPCODE_BGEU; + break; + case 12: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 0) + return OPCODE_BGE; + break; + case 13: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 0) + return OPCODE_BLT; + break; + case 14: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 0) + return OPCODE_BLTU; + break; + case 15: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 0) + return OPCODE_BNALL; + break; + } + switch (Field_t_Slot_dual_slot0_get (insn)) + { + case 0: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 2) + return OPCODE_BEQI; + break; + case 1: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 2) + return OPCODE_BGEI; + break; + case 2: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 2) + return OPCODE_BGEUI; + break; + case 3: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 2) + return OPCODE_BNEI; + break; + case 4: + if (Field_op0_s23_Slot_dual_slot0_get (insn) == 2) + return OPCODE_BLTI; + break; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_gp_slot1_decode (const xtensa_insnbuf insn) +{ + switch (Field_dsp340050b49a6c_fld2394gp_slot1_Slot_gp_slot1_get (insn)) + { + case 0: + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 0) + return OPCODE_CMAC; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 1) + return OPCODE_CMPY; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 2) + return OPCODE_MAC; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 3) + return OPCODE_MACS; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 4) + return OPCODE_MACXP_1; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 5) + return OPCODE_MACXP_3; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 6) + return OPCODE_MPY8; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 7) + return OPCODE_MPYXP_0; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 8) + return OPCODE_MPYXP_2; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 9) + return OPCODE_NORMACD; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 10) + return OPCODE_RCMAC; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 11) + return OPCODE_RMAC; + break; + case 1: + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 0) + return OPCODE_CMACS; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 1) + return OPCODE_CMPYS; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 2) + return OPCODE_MAC8; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 3) + return OPCODE_MACXP_0; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 4) + return OPCODE_MACXP_2; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 5) + return OPCODE_MPY; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 6) + return OPCODE_MPYS; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 7) + return OPCODE_MPYXP_1; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 8) + return OPCODE_MPYXP_3; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 9) + return OPCODE_NORMD; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 10) + return OPCODE_RCMPY; + if (Field_op0_s4_Slot_gp_slot1_get (insn) == 11) + return OPCODE_RMPY; + break; + } + if (Field_dsp340050b49a6c_fld2395gp_slot1_Slot_gp_slot1_get (insn) == 0 && + Field_op0_s4_Slot_gp_slot1_get (insn) == 12) + return OPCODE_ADD2AC; + if (Field_dsp340050b49a6c_fld2397gp_slot1_Slot_gp_slot1_get (insn) == 1 && + Field_op0_s4_Slot_gp_slot1_get (insn) == 12) + return OPCODE_MOV2AC; + if (Field_dsp340050b49a6c_fld2398gp_slot1_Slot_gp_slot1_get (insn) == 2 && + Field_op0_s4_Slot_gp_slot1_get (insn) == 12) + return OPCODE_SUB2AC; + if (Field_dsp340050b49a6c_fld2399gp_slot1_Slot_gp_slot1_get (insn) == 3 && + Field_op0_s4_Slot_gp_slot1_get (insn) == 12 && + Field_dsp340050b49a6c_fld3681gp_slot1_Slot_gp_slot1_get (insn) == 0) + return OPCODE_NOP; + if (Field_dsp340050b49a6c_fld2400gp_slot1_Slot_gp_slot1_get (insn) == 8 && + Field_op0_s4_Slot_gp_slot1_get (insn) == 12 && + Field_dsp340050b49a6c_fld3683gp_slot1_Slot_gp_slot1_get (insn) == 0) + return OPCODE_NORMACPQ_I; + if (Field_dsp340050b49a6c_fld2402gp_slot1_Slot_gp_slot1_get (insn) == 9 && + Field_op0_s4_Slot_gp_slot1_get (insn) == 12 && + Field_dsp340050b49a6c_fld3683gp_slot1_Slot_gp_slot1_get (insn) == 0) + return OPCODE_NORMACPQ_R; + if (Field_dsp340050b49a6c_fld2403gp_slot1_Slot_gp_slot1_get (insn) == 5 && + Field_op0_s4_Slot_gp_slot1_get (insn) == 12 && + Field_dsp340050b49a6c_fld3684gp_slot1_Slot_gp_slot1_get (insn) == 0) + return OPCODE_NORMPYPQ_I; + if (Field_dsp340050b49a6c_fld2405gp_slot1_Slot_gp_slot1_get (insn) == 3 && + Field_op0_s4_Slot_gp_slot1_get (insn) == 12 && + Field_dsp340050b49a6c_fld3686gp_slot1_Slot_gp_slot1_get (insn) == 0) + return OPCODE_NORMPYPQ_R; + switch (Field_op0_s4_Slot_gp_slot1_get (insn)) + { + case 13: + return OPCODE_CMPY2CM; + case 14: + return OPCODE_LIN_INT; + case 15: + return OPCODE_MPY2CM; + case 16: + return OPCODE_MPYADD8_2CM; + case 17: + return OPCODE_RCMPY2CM; + case 18: + return OPCODE_RMPY2CM; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_dot_slot2_decode (const xtensa_insnbuf insn) +{ + switch (Field_dsp340050b49a6c_fld2049_Slot_dot_slot2_get (insn)) + { + case 2: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 1 && + Field_t_Slot_dot_slot2_get (insn) == 0) + return OPCODE_OR128; + break; + case 3: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2029_Slot_dot_slot2_get (insn) == 0) + return OPCODE_PERM; + break; + } + if (Field_dsp340050b49a6c_fld2532dot_slot2_Slot_dot_slot2_get (insn) == 0 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_ADD32; + if (Field_dsp340050b49a6c_fld2533dot_slot2_Slot_dot_slot2_get (insn) == 1 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_ADDCM; + if (Field_dsp340050b49a6c_fld2534dot_slot2_Slot_dot_slot2_get (insn) == 2 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_ADDWRP; + if (Field_dsp340050b49a6c_fld2535dot_slot2_Slot_dot_slot2_get (insn) == 3 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_ASR; + if (Field_dsp340050b49a6c_fld2536dot_slot2_Slot_dot_slot2_get (insn) == 4 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_AND128; + if (Field_dsp340050b49a6c_fld2537dot_slot2_Slot_dot_slot2_get (insn) == 5 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_ASR32; + if (Field_dsp340050b49a6c_fld2538dot_slot2_Slot_dot_slot2_get (insn) == 6 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_EXTUI4; + if (Field_dsp340050b49a6c_fld2539dot_slot2_Slot_dot_slot2_get (insn) == 7 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_LUT; + if (Field_dsp340050b49a6c_fld2540dot_slot2_Slot_dot_slot2_get (insn) == 8 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_ASL; + if (Field_dsp340050b49a6c_fld2541dot_slot2_Slot_dot_slot2_get (insn) == 9 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_LUT_IEXT; + if (Field_dsp340050b49a6c_fld2542dot_slot2_Slot_dot_slot2_get (insn) == 10 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_LUT_REXT; + if (Field_dsp340050b49a6c_fld2543dot_slot2_Slot_dot_slot2_get (insn) == 11 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MEAN; + if (Field_dsp340050b49a6c_fld2544dot_slot2_Slot_dot_slot2_get (insn) == 12 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MAX8; + if (Field_dsp340050b49a6c_fld2545dot_slot2_Slot_dot_slot2_get (insn) == 13 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MEAN32; + if (Field_dsp340050b49a6c_fld2546dot_slot2_Slot_dot_slot2_get (insn) == 14 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MIN8; + if (Field_dsp340050b49a6c_fld2547dot_slot2_Slot_dot_slot2_get (insn) == 15 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOV2CM2PQ; + if (Field_dsp340050b49a6c_fld2548dot_slot2_Slot_dot_slot2_get (insn) == 16 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_ASL32; + if (Field_dsp340050b49a6c_fld2549dot_slot2_Slot_dot_slot2_get (insn) == 17 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVCND8_0; + if (Field_dsp340050b49a6c_fld2550dot_slot2_Slot_dot_slot2_get (insn) == 18 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVCND8_1; + if (Field_dsp340050b49a6c_fld2551dot_slot2_Slot_dot_slot2_get (insn) == 19 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVCND8_4; + if (Field_dsp340050b49a6c_fld2552dot_slot2_Slot_dot_slot2_get (insn) == 20 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVCND8_2; + if (Field_dsp340050b49a6c_fld2553dot_slot2_Slot_dot_slot2_get (insn) == 21 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVCND8_5; + if (Field_dsp340050b49a6c_fld2554dot_slot2_Slot_dot_slot2_get (insn) == 22 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVCND8_6; + if (Field_dsp340050b49a6c_fld2555dot_slot2_Slot_dot_slot2_get (insn) == 23 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVCND8_7; + if (Field_dsp340050b49a6c_fld2556dot_slot2_Slot_dot_slot2_get (insn) == 24 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVCND8_3; + if (Field_dsp340050b49a6c_fld2557dot_slot2_Slot_dot_slot2_get (insn) == 25 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVCND_0; + if (Field_dsp340050b49a6c_fld2558dot_slot2_Slot_dot_slot2_get (insn) == 26 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVCND_1; + if (Field_dsp340050b49a6c_fld2559dot_slot2_Slot_dot_slot2_get (insn) == 27 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVCND_3; + if (Field_dsp340050b49a6c_fld2560dot_slot2_Slot_dot_slot2_get (insn) == 28 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVCND_2; + if (Field_dsp340050b49a6c_fld2561dot_slot2_Slot_dot_slot2_get (insn) == 29 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVCND_4; + if (Field_dsp340050b49a6c_fld2562dot_slot2_Slot_dot_slot2_get (insn) == 30 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVCND_5; + if (Field_dsp340050b49a6c_fld2563dot_slot2_Slot_dot_slot2_get (insn) == 31 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVCND_6; + if (Field_dsp340050b49a6c_fld2564dot_slot2_Slot_dot_slot2_get (insn) == 32 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_ASLM; + if (Field_dsp340050b49a6c_fld2565dot_slot2_Slot_dot_slot2_get (insn) == 33 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_ASRM; + if (Field_dsp340050b49a6c_fld2566dot_slot2_Slot_dot_slot2_get (insn) == 34 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_CMP8; + if (Field_dsp340050b49a6c_fld2567dot_slot2_Slot_dot_slot2_get (insn) == 35 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_LSRM; + if (Field_dsp340050b49a6c_fld2568dot_slot2_Slot_dot_slot2_get (insn) == 36 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_CMP_I; + if (Field_dsp340050b49a6c_fld2569dot_slot2_Slot_dot_slot2_get (insn) == 517 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_ABS8; + if (Field_dsp340050b49a6c_fld2571dot_slot2_Slot_dot_slot2_get (insn) == 533 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_CONJ; + if (Field_dsp340050b49a6c_fld2572dot_slot2_Slot_dot_slot2_get (insn) == 549 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_LUT_PHASOR; + if (Field_dsp340050b49a6c_fld2573dot_slot2_Slot_dot_slot2_get (insn) == 565 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_NEGCM; + if (Field_dsp340050b49a6c_fld2574dot_slot2_Slot_dot_slot2_get (insn) == 581 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVCM; + if (Field_dsp340050b49a6c_fld2575dot_slot2_Slot_dot_slot2_get (insn) == 597 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_NOT128; + if (Field_dsp340050b49a6c_fld2576dot_slot2_Slot_dot_slot2_get (insn) == 613 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_TRANS; + if (Field_dsp340050b49a6c_fld2577dot_slot2_Slot_dot_slot2_get (insn) == 629 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_CLRCM; + if (Field_dsp340050b49a6c_fld2578_Slot_dot_slot2_get (insn) == 0 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_LUT_AR; + if (Field_dsp340050b49a6c_fld2579dot_slot2_Slot_dot_slot2_get (insn) == 1653 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_GET_ARGMAX; + if (Field_dsp340050b49a6c_fld2580dot_slot2_Slot_dot_slot2_get (insn) == 2677 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_GET_HSAR; + if (Field_dsp340050b49a6c_fld2581dot_slot2_Slot_dot_slot2_get (insn) == 3701 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_GET_NCO; + if (Field_dsp340050b49a6c_fld2582dot_slot2_Slot_dot_slot2_get (insn) == 4725 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_GET_HSAR2SAR; + if (Field_dsp340050b49a6c_fld2583dot_slot2_Slot_dot_slot2_get (insn) == 5749 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_GET_SAR; + if (Field_dsp340050b49a6c_fld2584dot_slot2_Slot_dot_slot2_get (insn) == 6773 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP128_0; + if (Field_dsp340050b49a6c_fld2585dot_slot2_Slot_dot_slot2_get (insn) == 7797 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP128_1; + if (Field_dsp340050b49a6c_fld2586dot_slot2_Slot_dot_slot2_get (insn) == 8821 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_GET_MAX; + if (Field_dsp340050b49a6c_fld2587dot_slot2_Slot_dot_slot2_get (insn) == 9845 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP128_2; + if (Field_dsp340050b49a6c_fld2588dot_slot2_Slot_dot_slot2_get (insn) == 10869 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP128_3; + if (Field_dsp340050b49a6c_fld2589dot_slot2_Slot_dot_slot2_get (insn) == 11893 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP128_5; + if (Field_dsp340050b49a6c_fld2590dot_slot2_Slot_dot_slot2_get (insn) == 12917 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP128_4; + switch (Field_dsp340050b49a6c_fld2591dot_slot2_Slot_dot_slot2_get (insn)) + { + case 221301: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_0; + break; + case 221557: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_2; + break; + case 221813: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_3; + break; + case 222069: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_0; + break; + case 222325: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_4; + break; + case 222581: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_1; + break; + case 222837: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_2; + break; + case 223093: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_3; + break; + } + if (Field_dsp340050b49a6c_fld2592dot_slot2_Slot_dot_slot2_get (insn) == 55925 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3708dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_5; + if (Field_dsp340050b49a6c_fld2595dot_slot2_Slot_dot_slot2_get (insn) == 56181 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3708dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_NOP; + if (Field_dsp340050b49a6c_fld2596dot_slot2_Slot_dot_slot2_get (insn) == 7797 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3724dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_1; + if (Field_dsp340050b49a6c_fld2598dot_slot2_Slot_dot_slot2_get (insn) == 645 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_NCO_UPDATE; + if (Field_dsp340050b49a6c_fld2599dot_slot2_Slot_dot_slot2_get (insn) == 2197 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3709dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_SET_ARGMAX; + if (Field_dsp340050b49a6c_fld2601dot_slot2_Slot_dot_slot2_get (insn) == 2453 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3709dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_SET_NCO; + if (Field_dsp340050b49a6c_fld2602dot_slot2_Slot_dot_slot2_get (insn) == 1429 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3713dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_SET_SAR; + if (Field_dsp340050b49a6c_fld2604dot_slot2_Slot_dot_slot2_get (insn) == 341 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3710dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_SET_HSAR; + if (Field_dsp340050b49a6c_fld2606dot_slot2_Slot_dot_slot2_get (insn) == 181 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3711dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_SET_MAX; + if (Field_dsp340050b49a6c_fld2608dot_slot2_Slot_dot_slot2_get (insn) == 19 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP128_2CMPQ_0; + if (Field_dsp340050b49a6c_fld2609dot_slot2_Slot_dot_slot2_get (insn) == 51 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP128_2CMPQ_1; + if (Field_dsp340050b49a6c_fld2610dot_slot2_Slot_dot_slot2_get (insn) == 83 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP128_2CMPQ_2; + if (Field_dsp340050b49a6c_fld2611dot_slot2_Slot_dot_slot2_get (insn) == 899 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_PUSH2X128_PQ; + if (Field_dsp340050b49a6c_fld2612_Slot_dot_slot2_get (insn) == 32 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_QREADY; + if (Field_dsp340050b49a6c_fld2613dot_slot2_Slot_dot_slot2_get (insn) == 1811 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_0; + switch (Field_dsp340050b49a6c_fld2614_Slot_dot_slot2_get (insn)) + { + case 66: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_MOVPQ2PQ; + break; + case 67: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_SET_EXT_REGS; + break; + case 68: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_PUSH128_PQ; + break; + case 69: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_SUBARX; + break; + case 70: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_SWAPB; + break; + case 71: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_WRTIEP; + break; + case 72: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_PUSH32; + break; + } + if (Field_dsp340050b49a6c_fld2615dot_slot2_Slot_dot_slot2_get (insn) == 1819 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_3; + if (Field_dsp340050b49a6c_fld2616dot_slot2_Slot_dot_slot2_get (insn) == 1827 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_1; + if (Field_dsp340050b49a6c_fld2617dot_slot2_Slot_dot_slot2_get (insn) == 1835 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_4; + if (Field_dsp340050b49a6c_fld2618dot_slot2_Slot_dot_slot2_get (insn) == 1843 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_5; + if (Field_dsp340050b49a6c_fld2619dot_slot2_Slot_dot_slot2_get (insn) == 3702 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP32_0; + if (Field_dsp340050b49a6c_fld2620dot_slot2_Slot_dot_slot2_get (insn) == 3703 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP32_1; + if (Field_dsp340050b49a6c_fld2621dot_slot2_Slot_dot_slot2_get (insn) == 1859 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_2; + if (Field_dsp340050b49a6c_fld2622dot_slot2_Slot_dot_slot2_get (insn) == 1867 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2047_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP32_2; + if (Field_dsp340050b49a6c_fld2623dot_slot2_Slot_dot_slot2_get (insn) == 939 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3727dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP32_3; + if (Field_dsp340050b49a6c_fld2624dot_slot2_Slot_dot_slot2_get (insn) == 475 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3729dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_RDTIEP; + if (Field_dsp340050b49a6c_fld2625_Slot_dot_slot2_get (insn) == 19 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3731dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_SETTIEP; + if (Field_dsp340050b49a6c_fld2626dot_slot2_Slot_dot_slot2_get (insn) == 51 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3715_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP128_2CMPQ_3; + if (Field_dsp340050b49a6c_fld2628dot_slot2_Slot_dot_slot2_get (insn) == 51 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3722_Slot_dot_slot2_get (insn) == 0) + return OPCODE_PQ2CM; + if (Field_dsp340050b49a6c_fld2630dot_slot2_Slot_dot_slot2_get (insn) == 10 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2032_Slot_dot_slot2_get (insn) == 0) + return OPCODE_CMP_R; + if (Field_dsp340050b49a6c_fld2632dot_slot2_Slot_dot_slot2_get (insn) == 11 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0 && + Field_t_Slot_dot_slot2_get (insn) == 0) + return OPCODE_ADD16; + if (Field_dsp340050b49a6c_fld2633dot_slot2_Slot_dot_slot2_get (insn) == 6 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3733dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_LSLM; + if (Field_dsp340050b49a6c_fld2635dot_slot2_Slot_dot_slot2_get (insn) == 7 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3719dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_CM2AR_LN; + switch (Field_dsp340050b49a6c_fld2636dot_slot2_Slot_dot_slot2_get (insn)) + { + case 1168: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_AR2SAR_DUP; + break; + case 1169: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_POP2X128_2PQ_01; + break; + case 1170: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_POP2X128_2PQ_03; + break; + case 1171: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_WRTBSIGQ; + break; + } + if (Field_dsp340050b49a6c_fld2637dot_slot2_Slot_dot_slot2_get (insn) == 586 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3725dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP2X128_2PQ_21; + if (Field_dsp340050b49a6c_fld2640dot_slot2_Slot_dot_slot2_get (insn) == 587 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3725dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_WRTSIGQ; + if (Field_dsp340050b49a6c_fld2641dot_slot2_Slot_dot_slot2_get (insn) == 147 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3726dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_POP2X128_2PQ_23; + if (Field_dsp340050b49a6c_fld2642dot_slot2_Slot_dot_slot2_get (insn) == 74 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2605_Slot_dot_slot2_get (insn) == 0) + return OPCODE_CLRTIEP; + if (Field_dsp340050b49a6c_fld2643dot_slot2_Slot_dot_slot2_get (insn) == 75 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2605_Slot_dot_slot2_get (insn) == 0) + return OPCODE_WRTBSIGQM; + if (Field_dsp340050b49a6c_fld2644dot_slot2_Slot_dot_slot2_get (insn) == 4 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3732dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_ADDAR2; + if (Field_dsp340050b49a6c_fld2645dot_slot2_Slot_dot_slot2_get (insn) == 4 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3714dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_AR2CM_DUP; + if (Field_dsp340050b49a6c_fld2646dot_slot2_Slot_dot_slot2_get (insn) == 4 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3721dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVAR2; + if (Field_dsp340050b49a6c_fld2647dot_slot2_Slot_dot_slot2_get (insn) == 16 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_MOVCND_7; + if (Field_dsp340050b49a6c_fld2648dot_slot2_Slot_dot_slot2_get (insn) == 17 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_SUB32; + if (Field_dsp340050b49a6c_fld2649dot_slot2_Slot_dot_slot2_get (insn) == 18 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_SUBCM; + if (Field_dsp340050b49a6c_fld2650dot_slot2_Slot_dot_slot2_get (insn) == 19 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_XOR128; + if (Field_dsp340050b49a6c_fld2651dot_slot2_Slot_dot_slot2_get (insn) == 20 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1) + return OPCODE_SUBMEAN; + if (Field_dsp340050b49a6c_fld2652dot_slot2_Slot_dot_slot2_get (insn) == 37 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3718_Slot_dot_slot2_get (insn) == 0) + return OPCODE_ARGMAX8; + if (Field_dsp340050b49a6c_fld2654dot_slot2_Slot_dot_slot2_get (insn) == 53 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3728dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_PUSH128; + if (Field_dsp340050b49a6c_fld2655dot_slot2_Slot_dot_slot2_get (insn) == 11 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2029_Slot_dot_slot2_get (insn) == 0) + return OPCODE_MOVCM2PQ; + if (Field_dsp340050b49a6c_fld2656dot_slot2_Slot_dot_slot2_get (insn) == 6 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3712_Slot_dot_slot2_get (insn) == 0) + return OPCODE_SUBWRP; + if (Field_dsp340050b49a6c_fld2657dot_slot2_Slot_dot_slot2_get (insn) == 7 && + Field_op0_s6_Slot_dot_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2029_Slot_dot_slot2_get (insn) == 0) + return OPCODE_ASLM32; + switch (Field_dsp340050b49a6c_fld2658dot_slot2_Slot_dot_slot2_get (insn)) + { + case 0: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3717dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_AR2PQ_LN; + break; + case 1: + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3716dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_AR2CM_LN; + break; + } + if (Field_op0_s6_Slot_dot_slot2_get (insn) == 3 && + Field_dsp340050b49a6c_fld3723dot_slot2_Slot_dot_slot2_get (insn) == 0) + return OPCODE_LUT_WRITE; + return XTENSA_UNDEFINED; +} + +static int +Slot_dot_slot1_decode (const xtensa_insnbuf insn) +{ + switch (Field_op0_s7_Slot_dot_slot1_get (insn)) + { + case 0: + return OPCODE_CDOT; + case 1: + return OPCODE_CDOTAC; + case 2: + return OPCODE_CDOTACS; + case 3: + return OPCODE_DOT; + case 4: + return OPCODE_DOTAC; + case 5: + return OPCODE_DOTACS; + case 6: + return OPCODE_MACD8; + case 7: + return OPCODE_MACPQXP_0; + case 8: + return OPCODE_MACPQXP_1; + case 9: + return OPCODE_MACPQXP_2; + case 10: + return OPCODE_MACPQXP_3; + case 11: + return OPCODE_MACXP2_0; + case 12: + return OPCODE_MACXP2_1; + case 13: + return OPCODE_MPYD8; + case 14: + return OPCODE_MPYPQXP_0; + case 15: + return OPCODE_MPYPQXP_1; + case 16: + return OPCODE_MPYPQXP_2; + case 17: + return OPCODE_MPYPQXP_3; + case 18: + return OPCODE_MPYXP2_0; + case 19: + return OPCODE_MPYXP2_1; + case 20: + if (Field_dsp340050b49a6c_fld3734dot_slot1_Slot_dot_slot1_get (insn) == 0) + return OPCODE_NOP; + break; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_pq_slot1_decode (const xtensa_insnbuf insn) +{ + switch (Field_dsp340050b49a6c_fld2825pq_slot1_Slot_pq_slot1_get (insn)) + { + case 0: + if (Field_op0_s10_Slot_pq_slot1_get (insn) == 0) + return OPCODE_CMPYXP2PQ; + break; + case 1: + if (Field_op0_s10_Slot_pq_slot1_get (insn) == 0) + return OPCODE_MPYXP2PQ; + break; + } + if (Field_dsp340050b49a6c_fld2826pq_slot1_Slot_pq_slot1_get (insn) == 1 && + Field_op0_s10_Slot_pq_slot1_get (insn) == 0 && + Field_dsp340050b49a6c_fld3761pq_slot1_Slot_pq_slot1_get (insn) == 0) + return OPCODE_NOP; + switch (Field_op0_s10_Slot_pq_slot1_get (insn)) + { + case 1: + return OPCODE_CMPY2PQ; + case 2: + return OPCODE_MPY2PQ; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_acc2_slot2_decode (const xtensa_insnbuf insn) +{ + switch (Field_dsp340050b49a6c_fld2045_Slot_acc2_slot2_get (insn)) + { + case 0: + if (Field_op0_s12_Slot_acc2_slot2_get (insn) == 0) + return OPCODE_ARGMAX8; + break; + case 2: + if (Field_op0_s12_Slot_acc2_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2046_Slot_acc2_slot2_get (insn) == 0) + return OPCODE_POP32_0; + break; + case 3: + if (Field_op0_s12_Slot_acc2_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2046_Slot_acc2_slot2_get (insn) == 0) + return OPCODE_POP32_3; + break; + } + switch (Field_dsp340050b49a6c_fld2953acc2_slot2_Slot_acc2_slot2_get (insn)) + { + case 2: + if (Field_op0_s12_Slot_acc2_slot2_get (insn) == 0) + return OPCODE_PUSH128; + break; + case 3: + if (Field_op0_s12_Slot_acc2_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3782acc2_slot2_Slot_acc2_slot2_get (insn) == 0) + return OPCODE_NOP; + break; + } + if (Field_dsp340050b49a6c_fld2954acc2_slot2_Slot_acc2_slot2_get (insn) == 1 && + Field_op0_s12_Slot_acc2_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3786acc2_slot2_Slot_acc2_slot2_get (insn) == 0) + return OPCODE_POP32_1; + if (Field_dsp340050b49a6c_fld2955acc2_slot2_Slot_acc2_slot2_get (insn) == 1 && + Field_op0_s12_Slot_acc2_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3788acc2_slot2_Slot_acc2_slot2_get (insn) == 0) + return OPCODE_POP32_2; + if (Field_dsp340050b49a6c_fld2956acc2_slot2_Slot_acc2_slot2_get (insn) == 3 && + Field_op0_s12_Slot_acc2_slot2_get (insn) == 1) + return OPCODE_CLRCM; + if (Field_dsp340050b49a6c_fld2957acc2_slot2_Slot_acc2_slot2_get (insn) == 19 && + Field_op0_s12_Slot_acc2_slot2_get (insn) == 1) + return OPCODE_POP128_0; + if (Field_dsp340050b49a6c_fld2958acc2_slot2_Slot_acc2_slot2_get (insn) == 35 && + Field_op0_s12_Slot_acc2_slot2_get (insn) == 1) + return OPCODE_POP128_1; + if (Field_dsp340050b49a6c_fld2959acc2_slot2_Slot_acc2_slot2_get (insn) == 51 && + Field_op0_s12_Slot_acc2_slot2_get (insn) == 1) + return OPCODE_POP128_4; + if (Field_dsp340050b49a6c_fld2960acc2_slot2_Slot_acc2_slot2_get (insn) == 35 && + Field_op0_s12_Slot_acc2_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3784acc2_slot2_Slot_acc2_slot2_get (insn) == 0) + return OPCODE_POP128_2; + if (Field_dsp340050b49a6c_fld2963acc2_slot2_Slot_acc2_slot2_get (insn) == 51 && + Field_op0_s12_Slot_acc2_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3784acc2_slot2_Slot_acc2_slot2_get (insn) == 0) + return OPCODE_POP128_5; + if (Field_dsp340050b49a6c_fld2964acc2_slot2_Slot_acc2_slot2_get (insn) == 19 && + Field_op0_s12_Slot_acc2_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3785acc2_slot2_Slot_acc2_slot2_get (insn) == 0) + return OPCODE_POP128_3; + if (Field_dsp340050b49a6c_fld2966acc2_slot2_Slot_acc2_slot2_get (insn) == 1 && + Field_op0_s12_Slot_acc2_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3783acc2_slot2_Slot_acc2_slot2_get (insn) == 0) + return OPCODE_NCO_UPDATE; + if (Field_dsp340050b49a6c_fld2967acc2_slot2_Slot_acc2_slot2_get (insn) == 1 && + Field_op0_s12_Slot_acc2_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2056_Slot_acc2_slot2_get (insn) == 0) + return OPCODE_NEGCM; + switch (Field_op0_s12_Slot_acc2_slot2_get (insn)) + { + case 2: + if (Field_dsp340050b49a6c_fld2046_Slot_acc2_slot2_get (insn) == 0) + return OPCODE_PUSH32; + break; + case 3: + return OPCODE_ADD32; + case 4: + return OPCODE_ADDCM; + case 5: + return OPCODE_ASR; + case 6: + return OPCODE_LUT_IEXT; + case 7: + return OPCODE_PERM; + } + switch (Field_s_Slot_acc2_slot2_get (insn)) + { + case 0: + if (Field_op0_s12_Slot_acc2_slot2_get (insn) == 1) + return OPCODE_CONJ; + break; + case 1: + if (Field_op0_s12_Slot_acc2_slot2_get (insn) == 1) + return OPCODE_LUT_PHASOR; + break; + case 2: + if (Field_op0_s12_Slot_acc2_slot2_get (insn) == 1) + return OPCODE_MOVCM; + break; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_acc2_slot1_decode (const xtensa_insnbuf insn) +{ + switch (Field_dsp340050b49a6c_fld2075_Slot_acc2_slot1_get (insn)) + { + case 0: + if (Field_op0_s13_Slot_acc2_slot1_get (insn) == 0 && + Field_dsp340050b49a6c_fld2031_Slot_acc2_slot1_get (insn) == 0) + return OPCODE_RFIRD; + break; + case 1: + if (Field_op0_s13_Slot_acc2_slot1_get (insn) == 0 && + Field_dsp340050b49a6c_fld2031_Slot_acc2_slot1_get (insn) == 0) + return OPCODE_RFIRDA; + break; + } + if (Field_dsp340050b49a6c_fld2968acc2_slot1_Slot_acc2_slot1_get (insn) == 1 && + Field_op0_s13_Slot_acc2_slot1_get (insn) == 0 && + Field_dsp340050b49a6c_fld3793acc2_slot1_Slot_acc2_slot1_get (insn) == 0) + return OPCODE_SWAPAC_R; + if (Field_dsp340050b49a6c_fld2969acc2_slot1_Slot_acc2_slot1_get (insn) == 1 && + Field_op0_s13_Slot_acc2_slot1_get (insn) == 0 && + Field_dsp340050b49a6c_fld3790acc2_slot1_Slot_acc2_slot1_get (insn) == 0) + return OPCODE_NOP; + switch (Field_op0_s13_Slot_acc2_slot1_get (insn)) + { + case 1: + return OPCODE_LLRPRE1; + case 2: + return OPCODE_RFIR; + case 3: + return OPCODE_RFIRA; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_smod_slot2_decode (const xtensa_insnbuf insn) +{ + switch (Field_dsp340050b49a6c_fld2049_Slot_smod_slot2_get (insn)) + { + case 2: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 1 && + Field_t_Slot_smod_slot2_get (insn) == 0) + return OPCODE_OR128; + break; + case 3: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2029_Slot_smod_slot2_get (insn) == 0) + return OPCODE_PERM; + break; + } + if (Field_dsp340050b49a6c_fld2991smod_slot2_Slot_smod_slot2_get (insn) == 0 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_ADD32; + if (Field_dsp340050b49a6c_fld2992smod_slot2_Slot_smod_slot2_get (insn) == 1 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_ADDCM; + if (Field_dsp340050b49a6c_fld2993smod_slot2_Slot_smod_slot2_get (insn) == 2 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_ADDWRP; + if (Field_dsp340050b49a6c_fld2994smod_slot2_Slot_smod_slot2_get (insn) == 3 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_ASR; + if (Field_dsp340050b49a6c_fld2995smod_slot2_Slot_smod_slot2_get (insn) == 4 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_AND128; + if (Field_dsp340050b49a6c_fld2996smod_slot2_Slot_smod_slot2_get (insn) == 5 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_ASR32; + if (Field_dsp340050b49a6c_fld2997smod_slot2_Slot_smod_slot2_get (insn) == 6 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_EXTUI4; + if (Field_dsp340050b49a6c_fld2998smod_slot2_Slot_smod_slot2_get (insn) == 7 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_LUT; + if (Field_dsp340050b49a6c_fld2999smod_slot2_Slot_smod_slot2_get (insn) == 8 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_ASL; + if (Field_dsp340050b49a6c_fld3000smod_slot2_Slot_smod_slot2_get (insn) == 9 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_LUT_IEXT; + if (Field_dsp340050b49a6c_fld3001smod_slot2_Slot_smod_slot2_get (insn) == 10 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_LUT_REXT; + if (Field_dsp340050b49a6c_fld3002smod_slot2_Slot_smod_slot2_get (insn) == 11 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MEAN; + if (Field_dsp340050b49a6c_fld3003smod_slot2_Slot_smod_slot2_get (insn) == 12 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MAX8; + if (Field_dsp340050b49a6c_fld3004smod_slot2_Slot_smod_slot2_get (insn) == 13 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MEAN32; + if (Field_dsp340050b49a6c_fld3005smod_slot2_Slot_smod_slot2_get (insn) == 14 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MIN8; + if (Field_dsp340050b49a6c_fld3006smod_slot2_Slot_smod_slot2_get (insn) == 15 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOV2CM2PQ; + if (Field_dsp340050b49a6c_fld3007smod_slot2_Slot_smod_slot2_get (insn) == 16 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_ASL32; + if (Field_dsp340050b49a6c_fld3008smod_slot2_Slot_smod_slot2_get (insn) == 17 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVCND8_0; + if (Field_dsp340050b49a6c_fld3009smod_slot2_Slot_smod_slot2_get (insn) == 18 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVCND8_1; + if (Field_dsp340050b49a6c_fld3010smod_slot2_Slot_smod_slot2_get (insn) == 19 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVCND8_4; + if (Field_dsp340050b49a6c_fld3011smod_slot2_Slot_smod_slot2_get (insn) == 20 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVCND8_2; + if (Field_dsp340050b49a6c_fld3012smod_slot2_Slot_smod_slot2_get (insn) == 21 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVCND8_5; + if (Field_dsp340050b49a6c_fld3013smod_slot2_Slot_smod_slot2_get (insn) == 22 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVCND8_6; + if (Field_dsp340050b49a6c_fld3014smod_slot2_Slot_smod_slot2_get (insn) == 23 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVCND8_7; + if (Field_dsp340050b49a6c_fld3015smod_slot2_Slot_smod_slot2_get (insn) == 24 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVCND8_3; + if (Field_dsp340050b49a6c_fld3016smod_slot2_Slot_smod_slot2_get (insn) == 25 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVCND_0; + if (Field_dsp340050b49a6c_fld3017smod_slot2_Slot_smod_slot2_get (insn) == 26 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVCND_1; + if (Field_dsp340050b49a6c_fld3018smod_slot2_Slot_smod_slot2_get (insn) == 27 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVCND_3; + if (Field_dsp340050b49a6c_fld3019smod_slot2_Slot_smod_slot2_get (insn) == 28 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVCND_2; + if (Field_dsp340050b49a6c_fld3020smod_slot2_Slot_smod_slot2_get (insn) == 29 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVCND_4; + if (Field_dsp340050b49a6c_fld3021smod_slot2_Slot_smod_slot2_get (insn) == 30 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVCND_5; + if (Field_dsp340050b49a6c_fld3022smod_slot2_Slot_smod_slot2_get (insn) == 31 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVCND_6; + if (Field_dsp340050b49a6c_fld3023smod_slot2_Slot_smod_slot2_get (insn) == 32 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_ASLM; + if (Field_dsp340050b49a6c_fld3024smod_slot2_Slot_smod_slot2_get (insn) == 33 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_ASRM; + if (Field_dsp340050b49a6c_fld3025smod_slot2_Slot_smod_slot2_get (insn) == 34 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_CMP8; + if (Field_dsp340050b49a6c_fld3026smod_slot2_Slot_smod_slot2_get (insn) == 35 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_LSRM; + if (Field_dsp340050b49a6c_fld3027smod_slot2_Slot_smod_slot2_get (insn) == 36 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_CMP_I; + if (Field_dsp340050b49a6c_fld3028smod_slot2_Slot_smod_slot2_get (insn) == 517 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_ABS8; + if (Field_dsp340050b49a6c_fld3030smod_slot2_Slot_smod_slot2_get (insn) == 533 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_CONJ; + if (Field_dsp340050b49a6c_fld3031smod_slot2_Slot_smod_slot2_get (insn) == 549 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_LUT_PHASOR; + if (Field_dsp340050b49a6c_fld3032smod_slot2_Slot_smod_slot2_get (insn) == 565 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_NEGCM; + if (Field_dsp340050b49a6c_fld3033smod_slot2_Slot_smod_slot2_get (insn) == 581 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVCM; + if (Field_dsp340050b49a6c_fld3034smod_slot2_Slot_smod_slot2_get (insn) == 597 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_NOT128; + if (Field_dsp340050b49a6c_fld3035smod_slot2_Slot_smod_slot2_get (insn) == 613 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_TRANS; + if (Field_dsp340050b49a6c_fld3036smod_slot2_Slot_smod_slot2_get (insn) == 1141 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_PUSH128; + switch (Field_dsp340050b49a6c_fld3038smod_slot2_Slot_smod_slot2_get (insn)) + { + case 8565: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_SET_ARGMAX; + break; + case 9077: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_SET_HSAR; + break; + case 9589: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_SET_MAX; + break; + case 10101: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_SET_SAR; + break; + case 10613: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_SET_NCO; + break; + } + switch (Field_dsp340050b49a6c_fld3039smod_slot2_Slot_smod_slot2_get (insn)) + { + case 11125: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_0; + break; + case 27509: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_2; + break; + case 43893: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_3; + break; + case 60277: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_0; + break; + case 76661: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_4; + break; + case 93045: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_1; + break; + case 109429: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_2; + break; + case 125813: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_3; + break; + } + if (Field_dsp340050b49a6c_fld3040smod_slot2_Slot_smod_slot2_get (insn) == 43893 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3805smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_5; + if (Field_dsp340050b49a6c_fld3043smod_slot2_Slot_smod_slot2_get (insn) == 60277 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3805smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_NOP; + if (Field_dsp340050b49a6c_fld3044smod_slot2_Slot_smod_slot2_get (insn) == 6005 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3819smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_1; + if (Field_dsp340050b49a6c_fld3046smod_slot2_Slot_smod_slot2_get (insn) == 645 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_NCO_UPDATE; + if (Field_dsp340050b49a6c_fld3047smod_slot2_Slot_smod_slot2_get (insn) == 661 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_CLRCM; + if (Field_dsp340050b49a6c_fld3048_Slot_smod_slot2_get (insn) == 0 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1) + return OPCODE_LUT_AR; + if (Field_dsp340050b49a6c_fld3049smod_slot2_Slot_smod_slot2_get (insn) == 1685 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_GET_HSAR2SAR; + if (Field_dsp340050b49a6c_fld3050smod_slot2_Slot_smod_slot2_get (insn) == 2709 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_GET_MAX; + if (Field_dsp340050b49a6c_fld3051smod_slot2_Slot_smod_slot2_get (insn) == 3733 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP128_0; + if (Field_dsp340050b49a6c_fld3052smod_slot2_Slot_smod_slot2_get (insn) == 4757 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_GET_NCO; + if (Field_dsp340050b49a6c_fld3053smod_slot2_Slot_smod_slot2_get (insn) == 5781 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP128_1; + if (Field_dsp340050b49a6c_fld3054smod_slot2_Slot_smod_slot2_get (insn) == 6805 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP128_2; + if (Field_dsp340050b49a6c_fld3055smod_slot2_Slot_smod_slot2_get (insn) == 7829 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP128_3; + if (Field_dsp340050b49a6c_fld3056smod_slot2_Slot_smod_slot2_get (insn) == 4757 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3809smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_GET_SAR; + if (Field_dsp340050b49a6c_fld3058smod_slot2_Slot_smod_slot2_get (insn) == 5781 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3809smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP128_4; + if (Field_dsp340050b49a6c_fld3059smod_slot2_Slot_smod_slot2_get (insn) == 3733 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3821smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP128_5; + if (Field_dsp340050b49a6c_fld3061smod_slot2_Slot_smod_slot2_get (insn) == 341 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3806smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_GET_ARGMAX; + if (Field_dsp340050b49a6c_fld3063smod_slot2_Slot_smod_slot2_get (insn) == 181 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3807smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_GET_HSAR; + if (Field_dsp340050b49a6c_fld3065smod_slot2_Slot_smod_slot2_get (insn) == 19 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP128_2CMPQ_0; + if (Field_dsp340050b49a6c_fld3066smod_slot2_Slot_smod_slot2_get (insn) == 51 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP128_2CMPQ_1; + if (Field_dsp340050b49a6c_fld3067smod_slot2_Slot_smod_slot2_get (insn) == 83 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP128_2CMPQ_2; + if (Field_dsp340050b49a6c_fld3068smod_slot2_Slot_smod_slot2_get (insn) == 227 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_PUSH128_PQ; + if (Field_dsp340050b49a6c_fld3069smod_slot2_Slot_smod_slot2_get (insn) == 1803 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_0; + switch (Field_dsp340050b49a6c_fld3070_Slot_smod_slot2_get (insn)) + { + case 66: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 1) + return OPCODE_MOVPQ2PQ; + break; + case 67: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 1) + return OPCODE_SUBARX; + break; + case 68: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 1) + return OPCODE_PUSH32; + break; + case 69: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 1) + return OPCODE_SWAPB; + break; + case 70: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 1) + return OPCODE_WRTIEP; + break; + } + if (Field_dsp340050b49a6c_fld3071smod_slot2_Slot_smod_slot2_get (insn) == 1819 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_1; + if (Field_dsp340050b49a6c_fld3072smod_slot2_Slot_smod_slot2_get (insn) == 1835 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_2; + if (Field_dsp340050b49a6c_fld3073smod_slot2_Slot_smod_slot2_get (insn) == 1851 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_4; + if (Field_dsp340050b49a6c_fld3074smod_slot2_Slot_smod_slot2_get (insn) == 1867 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_3; + if (Field_dsp340050b49a6c_fld3075smod_slot2_Slot_smod_slot2_get (insn) == 1883 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP128_2PQ_5; + if (Field_dsp340050b49a6c_fld3076smod_slot2_Slot_smod_slot2_get (insn) == 3798 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP32_0; + if (Field_dsp340050b49a6c_fld3077smod_slot2_Slot_smod_slot2_get (insn) == 3799 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP32_1; + if (Field_dsp340050b49a6c_fld3078smod_slot2_Slot_smod_slot2_get (insn) == 3830 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP32_2; + if (Field_dsp340050b49a6c_fld3079smod_slot2_Slot_smod_slot2_get (insn) == 3831 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP32_3; + if (Field_dsp340050b49a6c_fld3080smod_slot2_Slot_smod_slot2_get (insn) == 147 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP128_2CMPQ_3; + if (Field_dsp340050b49a6c_fld3081smod_slot2_Slot_smod_slot2_get (insn) == 179 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2056_Slot_smod_slot2_get (insn) == 0) + return OPCODE_PUSH2X128_PQ; + if (Field_dsp340050b49a6c_fld3082smod_slot2_Slot_smod_slot2_get (insn) == 115 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3824smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_RDTIEP; + if (Field_dsp340050b49a6c_fld3084smod_slot2_Slot_smod_slot2_get (insn) == 51 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3817_Slot_smod_slot2_get (insn) == 0) + return OPCODE_PQ2CM; + if (Field_dsp340050b49a6c_fld3085smod_slot2_Slot_smod_slot2_get (insn) == 10 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld2032_Slot_smod_slot2_get (insn) == 0) + return OPCODE_CMP_R; + if (Field_dsp340050b49a6c_fld3087smod_slot2_Slot_smod_slot2_get (insn) == 11 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0 && + Field_t_Slot_smod_slot2_get (insn) == 0) + return OPCODE_ADD16; + if (Field_dsp340050b49a6c_fld3088smod_slot2_Slot_smod_slot2_get (insn) == 6 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3828smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_LSLM; + if (Field_dsp340050b49a6c_fld3090smod_slot2_Slot_smod_slot2_get (insn) == 7 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 0 && + Field_dsp340050b49a6c_fld3814smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_CM2AR_LN; + switch (Field_dsp340050b49a6c_fld3091smod_slot2_Slot_smod_slot2_get (insn)) + { + case 32: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 1) + return OPCODE_QREADY; + break; + case 36: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2041_Slot_smod_slot2_get (insn) == 0) + return OPCODE_SET_EXT_REGS; + break; + } + switch (Field_dsp340050b49a6c_fld3092smod_slot2_Slot_smod_slot2_get (insn)) + { + case 1136: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 1) + return OPCODE_AR2SAR_DUP; + break; + case 1137: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 1) + return OPCODE_POP2X128_2PQ_01; + break; + case 1138: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 1) + return OPCODE_POP2X128_2PQ_03; + break; + case 1139: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 1) + return OPCODE_WRTBSIGQ; + break; + } + if (Field_dsp340050b49a6c_fld3093smod_slot2_Slot_smod_slot2_get (insn) == 570 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3822smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP2X128_2PQ_21; + if (Field_dsp340050b49a6c_fld3096smod_slot2_Slot_smod_slot2_get (insn) == 571 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3822smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_WRTSIGQ; + if (Field_dsp340050b49a6c_fld3097smod_slot2_Slot_smod_slot2_get (insn) == 143 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3823smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_POP2X128_2PQ_23; + if (Field_dsp340050b49a6c_fld3098smod_slot2_Slot_smod_slot2_get (insn) == 74 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3062_Slot_smod_slot2_get (insn) == 0) + return OPCODE_CLRTIEP; + if (Field_dsp340050b49a6c_fld3099smod_slot2_Slot_smod_slot2_get (insn) == 75 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3062_Slot_smod_slot2_get (insn) == 0) + return OPCODE_WRTBSIGQM; + if (Field_dsp340050b49a6c_fld3100smod_slot2_Slot_smod_slot2_get (insn) == 19 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3825smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_SETTIEP; + if (Field_dsp340050b49a6c_fld3101smod_slot2_Slot_smod_slot2_get (insn) == 4 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3826smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_ADDAR2; + if (Field_dsp340050b49a6c_fld3102smod_slot2_Slot_smod_slot2_get (insn) == 4 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3810smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_AR2CM_DUP; + if (Field_dsp340050b49a6c_fld3104smod_slot2_Slot_smod_slot2_get (insn) == 4 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3816smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVAR2; + if (Field_dsp340050b49a6c_fld3105smod_slot2_Slot_smod_slot2_get (insn) == 16 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1) + return OPCODE_MOVCND_7; + if (Field_dsp340050b49a6c_fld3106smod_slot2_Slot_smod_slot2_get (insn) == 17 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1) + return OPCODE_SMOD_LUT; + if (Field_dsp340050b49a6c_fld3107smod_slot2_Slot_smod_slot2_get (insn) == 18 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1) + return OPCODE_SUB32; + if (Field_dsp340050b49a6c_fld3108smod_slot2_Slot_smod_slot2_get (insn) == 19 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1) + return OPCODE_SUBWRP; + if (Field_dsp340050b49a6c_fld3109smod_slot2_Slot_smod_slot2_get (insn) == 20 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1) + return OPCODE_SUBCM; + if (Field_dsp340050b49a6c_fld3110smod_slot2_Slot_smod_slot2_get (insn) == 21 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1) + return OPCODE_XOR128; + if (Field_dsp340050b49a6c_fld3111smod_slot2_Slot_smod_slot2_get (insn) == 19 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2056_Slot_smod_slot2_get (insn) == 0) + return OPCODE_MOVCM2PQ; + if (Field_dsp340050b49a6c_fld3113smod_slot2_Slot_smod_slot2_get (insn) == 27 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3827smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_ARGMAX8; + if (Field_dsp340050b49a6c_fld3114smod_slot2_Slot_smod_slot2_get (insn) == 6 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3808_Slot_smod_slot2_get (insn) == 0) + return OPCODE_SUBMEAN; + if (Field_dsp340050b49a6c_fld3115smod_slot2_Slot_smod_slot2_get (insn) == 7 && + Field_op0_s15_Slot_smod_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2029_Slot_smod_slot2_get (insn) == 0) + return OPCODE_ASLM32; + switch (Field_dsp340050b49a6c_fld3116smod_slot2_Slot_smod_slot2_get (insn)) + { + case 0: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3813smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_AR2PQ_LN; + break; + case 1: + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3812smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_AR2CM_LN; + break; + } + if (Field_op0_s15_Slot_smod_slot2_get (insn) == 3 && + Field_dsp340050b49a6c_fld3818smod_slot2_Slot_smod_slot2_get (insn) == 0) + return OPCODE_LUT_WRITE; + return XTENSA_UNDEFINED; +} + +static int +Slot_smod_slot1_decode (const xtensa_insnbuf insn) +{ + switch (Field_dsp340050b49a6c_fld2080_Slot_smod_slot1_get (insn)) + { + case 0: + if (Field_op0_s16_Slot_smod_slot1_get (insn) == 0) + return OPCODE_CMPY2CM; + if (Field_op0_s16_Slot_smod_slot1_get (insn) == 1) + return OPCODE_RMPY2CM; + break; + case 1: + if (Field_op0_s16_Slot_smod_slot1_get (insn) == 0) + return OPCODE_MPY2CM; + break; + case 2: + if (Field_op0_s16_Slot_smod_slot1_get (insn) == 0) + return OPCODE_MPYADD8_2CM; + break; + case 3: + if (Field_op0_s16_Slot_smod_slot1_get (insn) == 0) + return OPCODE_RCMPY2CM; + break; + } + switch (Field_dsp340050b49a6c_fld3117smod_slot1_Slot_smod_slot1_get (insn)) + { + case 2: + if (Field_op0_s16_Slot_smod_slot1_get (insn) == 1) + return OPCODE_CMAC; + break; + case 3: + if (Field_op0_s16_Slot_smod_slot1_get (insn) == 1) + return OPCODE_MAC; + break; + case 4: + if (Field_op0_s16_Slot_smod_slot1_get (insn) == 1) + return OPCODE_CMPY; + break; + case 5: + if (Field_op0_s16_Slot_smod_slot1_get (insn) == 1) + return OPCODE_MPY; + break; + case 6: + if (Field_op0_s16_Slot_smod_slot1_get (insn) == 1) + return OPCODE_NORMACD; + break; + case 7: + if (Field_op0_s16_Slot_smod_slot1_get (insn) == 1) + return OPCODE_NORMD; + break; + } + switch (Field_dsp340050b49a6c_fld3118smod_slot1_Slot_smod_slot1_get (insn)) + { + case 0: + if (Field_op0_s16_Slot_smod_slot1_get (insn) == 2 && + Field_dsp340050b49a6c_fld3117smod_slot1_Slot_smod_slot1_get (insn) == 0) + return OPCODE_SMOD_SCR; + break; + case 1: + if (Field_op0_s16_Slot_smod_slot1_get (insn) == 2 && + Field_dsp340050b49a6c_fld3829smod_slot1_Slot_smod_slot1_get (insn) == 0) + return OPCODE_NOP; + break; + } + if (Field_op0_s16_Slot_smod_slot1_get (insn) == 3) + return OPCODE_SMOD_ALIGN; + return XTENSA_UNDEFINED; +} + +static int +Slot_llr_slot2_decode (const xtensa_insnbuf insn) +{ + switch (Field_dsp340050b49a6c_fld2046_Slot_llr_slot2_get (insn)) + { + case 0: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 2) + return OPCODE_LUT_AR; + break; + case 2: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3230_Slot_llr_slot2_get (insn) == 0) + return OPCODE_CM2AR_LN; + break; + } + switch (Field_dsp340050b49a6c_fld3191llr_slot2_Slot_llr_slot2_get (insn)) + { + case 6: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_ABS8; + break; + case 7: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_CONJ; + break; + case 22: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_LUT_PHASOR; + break; + case 23: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_NOT128; + break; + case 38: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_MOVCM; + break; + case 39: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_TRANS; + break; + case 70: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_NCO_UPDATE; + break; + } + if (Field_dsp340050b49a6c_fld3192llr_slot2_Slot_llr_slot2_get (insn) == 54 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_CLRCM; + if (Field_dsp340050b49a6c_fld3193llr_slot2_Slot_llr_slot2_get (insn) == 55 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_GET_ARGMAX; + if (Field_dsp340050b49a6c_fld3194llr_slot2_Slot_llr_slot2_get (insn) == 310 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_GET_HSAR; + if (Field_dsp340050b49a6c_fld3195llr_slot2_Slot_llr_slot2_get (insn) == 311 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_GET_SAR; + if (Field_dsp340050b49a6c_fld3196llr_slot2_Slot_llr_slot2_get (insn) == 566 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_GET_HSAR2SAR; + if (Field_dsp340050b49a6c_fld3197llr_slot2_Slot_llr_slot2_get (insn) == 567 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_POP128_0; + if (Field_dsp340050b49a6c_fld3198llr_slot2_Slot_llr_slot2_get (insn) == 822 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_POP128_1; + if (Field_dsp340050b49a6c_fld3199llr_slot2_Slot_llr_slot2_get (insn) == 823 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_POP128_2; + if (Field_dsp340050b49a6c_fld3200llr_slot2_Slot_llr_slot2_get (insn) == 1078 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_GET_MAX; + if (Field_dsp340050b49a6c_fld3201llr_slot2_Slot_llr_slot2_get (insn) == 1079 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_POP128_3; + if (Field_dsp340050b49a6c_fld3202llr_slot2_Slot_llr_slot2_get (insn) == 1334 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_POP128_4; + switch (Field_dsp340050b49a6c_fld3203llr_slot2_Slot_llr_slot2_get (insn)) + { + case 20535: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_MOVEQ128_0; + break; + case 20791: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_MOVEQ128_1; + break; + case 21047: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_MOVEQ128_2; + break; + case 21303: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_MOVEQ128_5; + break; + case 21559: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_MOVEQ128_3; + break; + case 21815: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_MOVEQ32_0; + break; + case 22071: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_MOVEQ32_1; + break; + case 22327: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_MOVEQ32_2; + break; + } + if (Field_dsp340050b49a6c_fld3204llr_slot2_Slot_llr_slot2_get (insn) == 11319 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3844_Slot_llr_slot2_get (insn) == 0) + return OPCODE_MOVEQ128_4; + if (Field_dsp340050b49a6c_fld3205_Slot_llr_slot2_get (insn) == 7 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3847llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_SET_EXT_REGS; + switch (Field_dsp340050b49a6c_fld3206_Slot_llr_slot2_get (insn)) + { + case 71: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3225_Slot_llr_slot2_get (insn) == 0) + return OPCODE_SET_ARGMAX; + break; + case 327: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3225_Slot_llr_slot2_get (insn) == 0) + return OPCODE_SET_NCO; + break; + } + if (Field_dsp340050b49a6c_fld3207llr_slot2_Slot_llr_slot2_get (insn) == 11575 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3844_Slot_llr_slot2_get (insn) == 0) + return OPCODE_MOVEQ32_3; + if (Field_dsp340050b49a6c_fld3208llr_slot2_Slot_llr_slot2_get (insn) == 5943 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3843llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_NOP; + if (Field_dsp340050b49a6c_fld3210llr_slot2_Slot_llr_slot2_get (insn) == 411 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3857llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_POP128_5; + if (Field_dsp340050b49a6c_fld3212_Slot_llr_slot2_get (insn) == 43 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3848llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_SET_HSAR; + if (Field_dsp340050b49a6c_fld3213llr_slot2_Slot_llr_slot2_get (insn) == 155 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3845llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_GET_NCO; + if (Field_dsp340050b49a6c_fld3214_Slot_llr_slot2_get (insn) == 1 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3863llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_QREADY; + if (Field_dsp340050b49a6c_fld3215llr_slot2_Slot_llr_slot2_get (insn) == 327 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3850llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_SET_SAR; + if (Field_dsp340050b49a6c_fld3216llr_slot2_Slot_llr_slot2_get (insn) == 27 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3849llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_SET_MAX; + if (Field_dsp340050b49a6c_fld3217_Slot_llr_slot2_get (insn) == 5 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3859llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_POP32_0; + if (Field_dsp340050b49a6c_fld3218llr_slot2_Slot_llr_slot2_get (insn) == 11 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3851llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_NEGCM; + if (Field_dsp340050b49a6c_fld3220llr_slot2_Slot_llr_slot2_get (insn) == 9 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3246_Slot_llr_slot2_get (insn) == 0) + return OPCODE_PUSH128; + if (Field_dsp340050b49a6c_fld3221llr_slot2_Slot_llr_slot2_get (insn) == 25 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld2046_Slot_llr_slot2_get (insn) == 0) + return OPCODE_POP32_1; + if (Field_dsp340050b49a6c_fld3222llr_slot2_Slot_llr_slot2_get (insn) == 25 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3860llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_POP32_2; + if (Field_dsp340050b49a6c_fld3224llr_slot2_Slot_llr_slot2_get (insn) == 25 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3861llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_POP32_3; + if (Field_dsp340050b49a6c_fld3226llr_slot2_Slot_llr_slot2_get (insn) == 25 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3864llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_RDTIEP; + if (Field_dsp340050b49a6c_fld3228llr_slot2_Slot_llr_slot2_get (insn) == 3 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3866llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_ADD16; + if (Field_dsp340050b49a6c_fld3231llr_slot2_Slot_llr_slot2_get (insn) == 7 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 1 && + Field_dsp340050b49a6c_fld3856llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_LUT_WRITE; + if (Field_dsp340050b49a6c_fld3232llr_slot2_Slot_llr_slot2_get (insn) == 4 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 2) + return OPCODE_AR2CM_LN; + switch (Field_dsp340050b49a6c_fld3233_Slot_llr_slot2_get (insn)) + { + case 2: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 4 && + Field_dsp340050b49a6c_fld2049_Slot_llr_slot2_get (insn) == 0) + return OPCODE_SUBWRP; + break; + case 3: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 4 && + Field_dsp340050b49a6c_fld2029_Slot_llr_slot2_get (insn) == 0) + return OPCODE_ASLM32; + break; + } + if (Field_dsp340050b49a6c_fld3234llr_slot2_Slot_llr_slot2_get (insn) == 20 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 2) + return OPCODE_AR2CM_DUP; + if (Field_dsp340050b49a6c_fld3235llr_slot2_Slot_llr_slot2_get (insn) == 133 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 2) + return OPCODE_SETTIEP; + if (Field_dsp340050b49a6c_fld3236_Slot_llr_slot2_get (insn) == 27 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld2074_Slot_llr_slot2_get (insn) == 0) + return OPCODE_WRTIEP; + if (Field_dsp340050b49a6c_fld3237llr_slot2_Slot_llr_slot2_get (insn) == 149 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld2074_Slot_llr_slot2_get (insn) == 0) + return OPCODE_AR2SAR_DUP; + if (Field_dsp340050b49a6c_fld3238llr_slot2_Slot_llr_slot2_get (insn) == 85 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3862_Slot_llr_slot2_get (insn) == 0) + return OPCODE_WRTBSIGQ; + if (Field_dsp340050b49a6c_fld3240llr_slot2_Slot_llr_slot2_get (insn) == 53 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3847llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_WRTSIGQ; + if (Field_dsp340050b49a6c_fld3241llr_slot2_Slot_llr_slot2_get (insn) == 11 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3865llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_WRTBSIGQM; + if (Field_dsp340050b49a6c_fld3242llr_slot2_Slot_llr_slot2_get (insn) == 3 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3855llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_CLRTIEP; + switch (Field_dsp340050b49a6c_fld3243llr_slot2_Slot_llr_slot2_get (insn)) + { + case 48: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 2) + return OPCODE_ADDAR2; + break; + case 49: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 2) + return OPCODE_MOVAR2; + break; + case 50: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 2) + return OPCODE_PUSH128_PQ; + break; + case 51: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 2) + return OPCODE_SUBARX; + break; + case 52: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 2) + return OPCODE_PUSH32; + break; + case 53: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 2) + return OPCODE_SWAPB; + break; + } + if (Field_dsp340050b49a6c_fld3244llr_slot2_Slot_llr_slot2_get (insn) == 1 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 2 && + Field_dsp340050b49a6c_fld3853llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_PQ2CM; + if (Field_dsp340050b49a6c_fld3245llr_slot2_Slot_llr_slot2_get (insn) == 2 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 4 && + Field_dsp340050b49a6c_fld3868_Slot_llr_slot2_get (insn) == 0) + return OPCODE_SUBMEAN; + if (Field_dsp340050b49a6c_fld3247llr_slot2_Slot_llr_slot2_get (insn) == 3 && + Field_op0_s18_Slot_llr_slot2_get (insn) == 4 && + Field_dsp340050b49a6c_fld3867llr_slot2_Slot_llr_slot2_get (insn) == 0) + return OPCODE_ARGMAX8; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 5 && + Field_dsp340050b49a6c_fld2029_Slot_llr_slot2_get (insn) == 0) + return OPCODE_PERM; + switch (Field_s_Slot_llr_slot2_get (insn)) + { + case 0: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_ASLM; + break; + case 1: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_ASRM; + break; + case 2: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_CMP8; + break; + case 3: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_LSLM; + break; + case 4: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_CMP_I; + break; + case 5: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_LSRM; + break; + case 8: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 1) + return OPCODE_CMP_R; + break; + } + switch (Field_t_Slot_llr_slot2_get (insn)) + { + case 0: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 3) + return OPCODE_MOVCND8_0; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 0) + return OPCODE_ADD32; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 4) + return OPCODE_OR128; + break; + case 1: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 3) + return OPCODE_MOVCND8_1; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 0) + return OPCODE_ADDCM; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 4) + return OPCODE_SUB32; + break; + case 2: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 3) + return OPCODE_MOVCND8_2; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 0) + return OPCODE_ADDWRP; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 4) + return OPCODE_SUBCM; + break; + case 3: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 3) + return OPCODE_MOVCND8_5; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 0) + return OPCODE_ASL32; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 4) + return OPCODE_XOR128; + break; + case 4: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 3) + return OPCODE_MOVCND8_3; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 0) + return OPCODE_AND128; + break; + case 5: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 3) + return OPCODE_MOVCND8_6; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 0) + return OPCODE_ASR; + break; + case 6: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 3) + return OPCODE_MOVCND8_7; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 0) + return OPCODE_ASR32; + break; + case 7: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 3) + return OPCODE_MOVCND_0; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 0) + return OPCODE_EXTUI4; + break; + case 8: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 3) + return OPCODE_MOVCND8_4; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 0) + return OPCODE_ASL; + break; + case 9: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 3) + return OPCODE_MOVCND_1; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 0) + return OPCODE_LUT; + break; + case 10: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 3) + return OPCODE_MOVCND_2; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 0) + return OPCODE_LUT_IEXT; + break; + case 11: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 3) + return OPCODE_MOVCND_4; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 0) + return OPCODE_MAX8; + break; + case 12: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 3) + return OPCODE_MOVCND_3; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 0) + return OPCODE_LUT_REXT; + break; + case 13: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 3) + return OPCODE_MOVCND_5; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 0) + return OPCODE_MEAN; + break; + case 14: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 3) + return OPCODE_MOVCND_6; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 0) + return OPCODE_MEAN32; + break; + case 15: + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 3) + return OPCODE_MOVCND_7; + if (Field_op0_s18_Slot_llr_slot2_get (insn) == 0) + return OPCODE_MIN8; + break; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_llr_slot1_decode (const xtensa_insnbuf insn) +{ + if (Field_dsp340050b49a6c_fld3248llr_slot1_Slot_llr_slot1_get (insn) == 0 && + Field_op0_s19_Slot_llr_slot1_get (insn) == 0 && + Field_dsp340050b49a6c_fld3870_Slot_llr_slot1_get (insn) == 0) + return OPCODE_WGHT32; + if (Field_dsp340050b49a6c_fld3250llr_slot1_Slot_llr_slot1_get (insn) == 1 && + Field_op0_s19_Slot_llr_slot1_get (insn) == 0 && + Field_dsp340050b49a6c_fld3869llr_slot1_Slot_llr_slot1_get (insn) == 0) + return OPCODE_NOP; + if (Field_dsp340050b49a6c_fld3251llr_slot1_Slot_llr_slot1_get (insn) == 2 && + Field_op0_s19_Slot_llr_slot1_get (insn) == 0 && + Field_dsp340050b49a6c_fld3878llr_slot1_Slot_llr_slot1_get (insn) == 0) + return OPCODE_LLRPRE2; + if (Field_dsp340050b49a6c_fld3252llr_slot1_Slot_llr_slot1_get (insn) == 3 && + Field_op0_s19_Slot_llr_slot1_get (insn) == 0 && + Field_dsp340050b49a6c_fld3875llr_slot1_Slot_llr_slot1_get (insn) == 0) + return OPCODE_MOVAC_R; + if (Field_dsp340050b49a6c_fld3253llr_slot1_Slot_llr_slot1_get (insn) == 1 && + Field_op0_s19_Slot_llr_slot1_get (insn) == 0 && + Field_dsp340050b49a6c_fld3876llr_slot1_Slot_llr_slot1_get (insn) == 0) + return OPCODE_ADDAC; + if (Field_dsp340050b49a6c_fld3254llr_slot1_Slot_llr_slot1_get (insn) == 1 && + Field_op0_s19_Slot_llr_slot1_get (insn) == 0 && + Field_dsp340050b49a6c_fld3872llr_slot1_Slot_llr_slot1_get (insn) == 0) + return OPCODE_MOVAC_I; + if (Field_op0_s19_Slot_llr_slot1_get (insn) == 1) + return OPCODE_COMB32; + return XTENSA_UNDEFINED; +} + +static int +Slot_dual_slot1_decode (const xtensa_insnbuf insn) +{ + if (Field_op0_s22_Slot_dual_slot1_get (insn) == 0) + return OPCODE_NOP; + return XTENSA_UNDEFINED; +} + + +/* Instruction slots. */ + +static void +Slot_x24_Format_inst_0_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = (insn[0] & 0xffffff); +} + +static void +Slot_x24_Format_inst_0_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0xffffff) | (slotbuf[0] & 0xffffff); +} + +static void +Slot_x16a_Format_inst16a_0_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = (insn[0] & 0xffff); +} + +static void +Slot_x16a_Format_inst16a_0_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0xffff) | (slotbuf[0] & 0xffff); +} + +static void +Slot_x16b_Format_inst16b_0_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = (insn[0] & 0xffff); +} + +static void +Slot_x16b_Format_inst16b_0_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0xffff) | (slotbuf[0] & 0xffff); +} + +static void +Slot_gp_Format_gp_slot2_43_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[1] & 0x3ffff800) >> 11); +} + +static void +Slot_gp_Format_gp_slot2_43_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[1] = (insn[1] & ~0x3ffff800) | ((slotbuf[0] & 0x7ffff) << 11); +} + +static void +Slot_gp_Format_gp_slot1_26_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[0] & 0xfc000000) >> 26); + slotbuf[0] = (slotbuf[0] & ~0x1ffc0) | ((insn[1] & 0x7ff) << 6); +} + +static void +Slot_gp_Format_gp_slot1_26_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0xfc000000) | ((slotbuf[0] & 0x3f) << 26); + insn[1] = (insn[1] & ~0x7ff) | ((slotbuf[0] & 0x1ffc0) >> 6); +} + +static void +Slot_gp_Format_gp_slot0_7_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[0] & 0x3ffff80) >> 7); +} + +static void +Slot_gp_Format_gp_slot0_7_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0x3ffff80) | ((slotbuf[0] & 0x7ffff) << 7); +} + +static void +Slot_dot_Format_dot_slot2_44_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[1] & 0xfffff000) >> 12); +} + +static void +Slot_dot_Format_dot_slot2_44_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[1] = (insn[1] & ~0xfffff000) | ((slotbuf[0] & 0xfffff) << 12); +} + +static void +Slot_dot_Format_dot_slot1_24_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[0] & 0xff000000) >> 24); + slotbuf[0] = (slotbuf[0] & ~0xfff00) | ((insn[1] & 0xfff) << 8); +} + +static void +Slot_dot_Format_dot_slot1_24_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0xff000000) | ((slotbuf[0] & 0xff) << 24); + insn[1] = (insn[1] & ~0xfff) | ((slotbuf[0] & 0xfff00) >> 8); +} + +static void +Slot_dot_Format_dot_slot0_7_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[0] & 0xffff80) >> 7); +} + +static void +Slot_dot_Format_dot_slot0_7_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0xffff80) | ((slotbuf[0] & 0x1ffff) << 7); +} + +static void +Slot_pq_Format_pq_slot2_40_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[1] & 0x7ffff00) >> 8); +} + +static void +Slot_pq_Format_pq_slot2_40_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[1] = (insn[1] & ~0x7ffff00) | ((slotbuf[0] & 0x7ffff) << 8); +} + +static void +Slot_pq_Format_pq_slot1_26_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[0] & 0xfc000000) >> 26); + slotbuf[0] = (slotbuf[0] & ~0x3fc0) | ((insn[1] & 0xff) << 6); +} + +static void +Slot_pq_Format_pq_slot1_26_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0xfc000000) | ((slotbuf[0] & 0x3f) << 26); + insn[1] = (insn[1] & ~0xff) | ((slotbuf[0] & 0x3fc0) >> 6); +} + +static void +Slot_pq_Format_pq_slot0_7_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[0] & 0x3ffff80) >> 7); +} + +static void +Slot_pq_Format_pq_slot0_7_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0x3ffff80) | ((slotbuf[0] & 0x7ffff) << 7); +} + +static void +Slot_acc2_Format_acc2_slot2_47_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[1] & 0x3fff8000) >> 15); +} + +static void +Slot_acc2_Format_acc2_slot2_47_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[1] = (insn[1] & ~0x3fff8000) | ((slotbuf[0] & 0x7fff) << 15); +} + +static void +Slot_acc2_Format_acc2_slot1_23_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[0] & 0xff800000) >> 23); + slotbuf[0] = (slotbuf[0] & ~0xfffe00) | ((insn[1] & 0x7fff) << 9); +} + +static void +Slot_acc2_Format_acc2_slot1_23_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0xff800000) | ((slotbuf[0] & 0x1ff) << 23); + insn[1] = (insn[1] & ~0x7fff) | ((slotbuf[0] & 0xfffe00) >> 9); +} + +static void +Slot_acc2_Format_acc2_slot0_7_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[0] & 0x7fff80) >> 7); +} + +static void +Slot_acc2_Format_acc2_slot0_7_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0x7fff80) | ((slotbuf[0] & 0xffff) << 7); +} + +static void +Slot_smod_Format_smod_slot2_42_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[1] & 0x3ffffc00) >> 10); +} + +static void +Slot_smod_Format_smod_slot2_42_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[1] = (insn[1] & ~0x3ffffc00) | ((slotbuf[0] & 0xfffff) << 10); +} + +static void +Slot_smod_Format_smod_slot1_26_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[0] & 0xfc000000) >> 26); + slotbuf[0] = (slotbuf[0] & ~0xffc0) | ((insn[1] & 0x3ff) << 6); +} + +static void +Slot_smod_Format_smod_slot1_26_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0xfc000000) | ((slotbuf[0] & 0x3f) << 26); + insn[1] = (insn[1] & ~0x3ff) | ((slotbuf[0] & 0xffc0) >> 6); +} + +static void +Slot_smod_Format_smod_slot0_7_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[0] & 0x3ffff80) >> 7); +} + +static void +Slot_smod_Format_smod_slot0_7_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0x3ffff80) | ((slotbuf[0] & 0x7ffff) << 7); +} + +static void +Slot_llr_Format_llr_slot2_44_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[1] & 0x7ffff000) >> 12); +} + +static void +Slot_llr_Format_llr_slot2_44_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[1] = (insn[1] & ~0x7ffff000) | ((slotbuf[0] & 0x7ffff) << 12); +} + +static void +Slot_llr_Format_llr_slot1_24_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[0] & 0xff000000) >> 24); + slotbuf[0] = (slotbuf[0] & ~0xfff00) | ((insn[1] & 0xfff) << 8); +} + +static void +Slot_llr_Format_llr_slot1_24_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0xff000000) | ((slotbuf[0] & 0xff) << 24); + insn[1] = (insn[1] & ~0xfff) | ((slotbuf[0] & 0xfff00) >> 8); +} + +static void +Slot_llr_Format_llr_slot0_7_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[0] & 0xffff80) >> 7); +} + +static void +Slot_llr_Format_llr_slot0_7_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0xffff80) | ((slotbuf[0] & 0x1ffff) << 7); +} + +static void +Slot_dual_Format_dual_slot2_31_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[0] & 0x80000000) >> 31); + slotbuf[0] = (slotbuf[0] & ~0xfffffe) | ((insn[1] & 0x7fffff) << 1); +} + +static void +Slot_dual_Format_dual_slot2_31_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0x80000000) | ((slotbuf[0] & 0x1) << 31); + insn[1] = (insn[1] & ~0x7fffff) | ((slotbuf[0] & 0xfffffe) >> 1); +} + +static void +Slot_dual_Format_dual_slot1_30_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[0] & 0x40000000) >> 30); +} + +static void +Slot_dual_Format_dual_slot1_30_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0x40000000) | ((slotbuf[0] & 0x1) << 30); +} + +static void +Slot_dual_Format_dual_slot0_7_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[1] = 0; + slotbuf[0] = ((insn[0] & 0x3fffff80) >> 7); +} + +static void +Slot_dual_Format_dual_slot0_7_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0x3fffff80) | ((slotbuf[0] & 0x7fffff) << 7); +} + +static xtensa_get_field_fn +Slot_inst_get_field_fns[] = { + Field_t_Slot_inst_get, + Field_bbi4_Slot_inst_get, + Field_bbi_Slot_inst_get, + Field_imm12_Slot_inst_get, + Field_imm8_Slot_inst_get, + Field_s_Slot_inst_get, + Field_imm12b_Slot_inst_get, + Field_imm16_Slot_inst_get, + Field_m_Slot_inst_get, + Field_n_Slot_inst_get, + Field_offset_Slot_inst_get, + Field_op0_Slot_inst_get, + Field_op1_Slot_inst_get, + Field_op2_Slot_inst_get, + Field_r_Slot_inst_get, + Field_sa4_Slot_inst_get, + Field_sae4_Slot_inst_get, + Field_sae_Slot_inst_get, + Field_sal_Slot_inst_get, + Field_sargt_Slot_inst_get, + Field_sas4_Slot_inst_get, + Field_sas_Slot_inst_get, + Field_sr_Slot_inst_get, + Field_st_Slot_inst_get, + Field_thi3_Slot_inst_get, + Field_imm4_Slot_inst_get, + Field_mn_Slot_inst_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_t2_Slot_inst_get, + Field_s2_Slot_inst_get, + Field_r2_Slot_inst_get, + Field_t4_Slot_inst_get, + Field_s4_Slot_inst_get, + Field_r4_Slot_inst_get, + Field_t8_Slot_inst_get, + Field_s8_Slot_inst_get, + Field_r8_Slot_inst_get, + Field_xt_wbr15_imm_Slot_inst_get, + Field_xt_wbr18_imm_Slot_inst_get, + Field_fimm8_Slot_inst_get, + Field_dsp340050b49a6c_fld2019_Slot_inst_get, + Field_dsp340050b49a6c_fld2021_Slot_inst_get, + Field_dsp340050b49a6c_fld2029_Slot_inst_get, + Field_dsp340050b49a6c_fld2030_Slot_inst_get, + Field_dsp340050b49a6c_fld2032_Slot_inst_get, + Field_dsp340050b49a6c_fld2035_Slot_inst_get, + Field_dsp340050b49a6c_fld2036_Slot_inst_get, + Field_dsp340050b49a6c_fld2037_Slot_inst_get, + Field_dsp340050b49a6c_fld2038_Slot_inst_get, + Field_dsp340050b49a6c_fld2039_Slot_inst_get, + Field_dsp340050b49a6c_fld2040_Slot_inst_get, + Field_dsp340050b49a6c_fld2041_Slot_inst_get, + Field_dsp340050b49a6c_fld2042_Slot_inst_get, + Field_dsp340050b49a6c_fld2043_Slot_inst_get, + Field_dsp340050b49a6c_fld2044_Slot_inst_get, + Field_dsp340050b49a6c_fld2045_Slot_inst_get, + Field_dsp340050b49a6c_fld2046_Slot_inst_get, + Field_dsp340050b49a6c_fld2047_Slot_inst_get, + Field_dsp340050b49a6c_fld2048_Slot_inst_get, + Field_dsp340050b49a6c_fld2049_Slot_inst_get, + Field_dsp340050b49a6c_fld2050_Slot_inst_get, + Field_dsp340050b49a6c_fld2051_Slot_inst_get, + Field_dsp340050b49a6c_fld2052_Slot_inst_get, + Field_dsp340050b49a6c_fld2053_Slot_inst_get, + Field_dsp340050b49a6c_fld2054_Slot_inst_get, + Field_dsp340050b49a6c_fld2055_Slot_inst_get, + Field_dsp340050b49a6c_fld2056_Slot_inst_get, + Field_dsp340050b49a6c_fld2082inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2083inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2084inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2085inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2086inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2088inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2089inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2090inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2091inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2092inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2094inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2095inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2096inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2098inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2099inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2100inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2101inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2102inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2103inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2104inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2105inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2106inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2107inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2108inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2109inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2110inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2111inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2112inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2113inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2114inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2115inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2116inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2117inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2118inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2119inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2120inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2122inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2123inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2124inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2125inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2126inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2127inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2128inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2129inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2131inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2132inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2133inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2134inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2136inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2137inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2138inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2139inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2140inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2141inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2142inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2143inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2144inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2145inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2146inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2147inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2149inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2151inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2153inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2154inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2155inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2156inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2157inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2158inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2159inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2160inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2161inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2162inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2163inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2164inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2165inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2166inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2167inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2168inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2169inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2171inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2172inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2173inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2174inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2175inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2177inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2178inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2179inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2180inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2181inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2182inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2183inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2184inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2185inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2186inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2187inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2188inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2189inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2190inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2191inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2192inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2193inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2194inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2195inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2196inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2197inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2198inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2199inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2200inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2201inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2202inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2203inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2204inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2205inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2206inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2207inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2208inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2209inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2210inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2211inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2212inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2213inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2214inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2215inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2216inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2217inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2218inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2219inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2220inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2221inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2222inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2223inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2224inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2225inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2226inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2227inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2228inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2229inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2230inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2231inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2232inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2234inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2235inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2236inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2237inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2238inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2239inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2240inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2241inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2242inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2243inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2244inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2245inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2246inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2247inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2248inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2249inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2250inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2251inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2252inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2253inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2254_Slot_inst_get, + Field_dsp340050b49a6c_fld2255inst_Slot_inst_get, + Field_dsp340050b49a6c_fld2257inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3627inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3630inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3631inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3633inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3634_Slot_inst_get, + Field_dsp340050b49a6c_fld3635inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3636inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3637inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3638inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3639inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3640inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3642inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3643inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3644inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3645inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3647inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3648inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3649inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3650inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3651inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3653inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3654inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3655inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3656inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3657inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3658inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3659inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3660inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3661inst_Slot_inst_get, + Field_dsp340050b49a6c_fld3662inst_Slot_inst_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_inst_set_field_fns[] = { + Field_t_Slot_inst_set, + Field_bbi4_Slot_inst_set, + Field_bbi_Slot_inst_set, + Field_imm12_Slot_inst_set, + Field_imm8_Slot_inst_set, + Field_s_Slot_inst_set, + Field_imm12b_Slot_inst_set, + Field_imm16_Slot_inst_set, + Field_m_Slot_inst_set, + Field_n_Slot_inst_set, + Field_offset_Slot_inst_set, + Field_op0_Slot_inst_set, + Field_op1_Slot_inst_set, + Field_op2_Slot_inst_set, + Field_r_Slot_inst_set, + Field_sa4_Slot_inst_set, + Field_sae4_Slot_inst_set, + Field_sae_Slot_inst_set, + Field_sal_Slot_inst_set, + Field_sargt_Slot_inst_set, + Field_sas4_Slot_inst_set, + Field_sas_Slot_inst_set, + Field_sr_Slot_inst_set, + Field_st_Slot_inst_set, + Field_thi3_Slot_inst_set, + Field_imm4_Slot_inst_set, + Field_mn_Slot_inst_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_t2_Slot_inst_set, + Field_s2_Slot_inst_set, + Field_r2_Slot_inst_set, + Field_t4_Slot_inst_set, + Field_s4_Slot_inst_set, + Field_r4_Slot_inst_set, + Field_t8_Slot_inst_set, + Field_s8_Slot_inst_set, + Field_r8_Slot_inst_set, + Field_xt_wbr15_imm_Slot_inst_set, + Field_xt_wbr18_imm_Slot_inst_set, + Field_fimm8_Slot_inst_set, + Field_dsp340050b49a6c_fld2019_Slot_inst_set, + Field_dsp340050b49a6c_fld2021_Slot_inst_set, + Field_dsp340050b49a6c_fld2029_Slot_inst_set, + Field_dsp340050b49a6c_fld2030_Slot_inst_set, + Field_dsp340050b49a6c_fld2032_Slot_inst_set, + Field_dsp340050b49a6c_fld2035_Slot_inst_set, + Field_dsp340050b49a6c_fld2036_Slot_inst_set, + Field_dsp340050b49a6c_fld2037_Slot_inst_set, + Field_dsp340050b49a6c_fld2038_Slot_inst_set, + Field_dsp340050b49a6c_fld2039_Slot_inst_set, + Field_dsp340050b49a6c_fld2040_Slot_inst_set, + Field_dsp340050b49a6c_fld2041_Slot_inst_set, + Field_dsp340050b49a6c_fld2042_Slot_inst_set, + Field_dsp340050b49a6c_fld2043_Slot_inst_set, + Field_dsp340050b49a6c_fld2044_Slot_inst_set, + Field_dsp340050b49a6c_fld2045_Slot_inst_set, + Field_dsp340050b49a6c_fld2046_Slot_inst_set, + Field_dsp340050b49a6c_fld2047_Slot_inst_set, + Field_dsp340050b49a6c_fld2048_Slot_inst_set, + Field_dsp340050b49a6c_fld2049_Slot_inst_set, + Field_dsp340050b49a6c_fld2050_Slot_inst_set, + Field_dsp340050b49a6c_fld2051_Slot_inst_set, + Field_dsp340050b49a6c_fld2052_Slot_inst_set, + Field_dsp340050b49a6c_fld2053_Slot_inst_set, + Field_dsp340050b49a6c_fld2054_Slot_inst_set, + Field_dsp340050b49a6c_fld2055_Slot_inst_set, + Field_dsp340050b49a6c_fld2056_Slot_inst_set, + Field_dsp340050b49a6c_fld2082inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2083inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2084inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2085inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2086inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2088inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2089inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2090inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2091inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2092inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2094inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2095inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2096inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2098inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2099inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2100inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2101inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2102inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2103inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2104inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2105inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2106inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2107inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2108inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2109inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2110inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2111inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2112inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2113inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2114inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2115inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2116inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2117inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2118inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2119inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2120inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2122inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2123inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2124inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2125inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2126inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2127inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2128inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2129inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2131inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2132inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2133inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2134inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2136inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2137inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2138inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2139inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2140inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2141inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2142inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2143inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2144inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2145inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2146inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2147inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2149inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2151inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2153inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2154inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2155inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2156inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2157inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2158inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2159inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2160inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2161inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2162inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2163inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2164inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2165inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2166inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2167inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2168inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2169inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2171inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2172inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2173inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2174inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2175inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2177inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2178inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2179inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2180inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2181inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2182inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2183inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2184inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2185inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2186inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2187inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2188inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2189inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2190inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2191inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2192inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2193inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2194inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2195inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2196inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2197inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2198inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2199inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2200inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2201inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2202inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2203inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2204inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2205inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2206inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2207inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2208inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2209inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2210inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2211inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2212inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2213inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2214inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2215inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2216inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2217inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2218inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2219inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2220inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2221inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2222inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2223inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2224inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2225inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2226inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2227inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2228inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2229inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2230inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2231inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2232inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2234inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2235inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2236inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2237inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2238inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2239inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2240inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2241inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2242inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2243inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2244inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2245inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2246inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2247inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2248inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2249inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2250inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2251inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2252inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2253inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2254_Slot_inst_set, + Field_dsp340050b49a6c_fld2255inst_Slot_inst_set, + Field_dsp340050b49a6c_fld2257inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3627inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3630inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3631inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3633inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3634_Slot_inst_set, + Field_dsp340050b49a6c_fld3635inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3636inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3637inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3638inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3639inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3640inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3642inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3643inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3644inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3645inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3647inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3648inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3649inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3650inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3651inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3653inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3654inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3655inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3656inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3657inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3658inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3659inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3660inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3661inst_Slot_inst_set, + Field_dsp340050b49a6c_fld3662inst_Slot_inst_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_inst16a_get_field_fns[] = { + Field_t_Slot_inst16a_get, + 0, + 0, + 0, + 0, + Field_s_Slot_inst16a_get, + 0, + 0, + 0, + 0, + 0, + Field_op0_Slot_inst16a_get, + 0, + 0, + Field_r_Slot_inst16a_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_sr_Slot_inst16a_get, + Field_st_Slot_inst16a_get, + 0, + Field_imm4_Slot_inst16a_get, + 0, + Field_i_Slot_inst16a_get, + Field_imm6lo_Slot_inst16a_get, + Field_imm6hi_Slot_inst16a_get, + Field_imm7lo_Slot_inst16a_get, + Field_imm7hi_Slot_inst16a_get, + Field_z_Slot_inst16a_get, + Field_imm6_Slot_inst16a_get, + Field_imm7_Slot_inst16a_get, + Field_t2_Slot_inst16a_get, + Field_s2_Slot_inst16a_get, + Field_r2_Slot_inst16a_get, + Field_t4_Slot_inst16a_get, + Field_s4_Slot_inst16a_get, + Field_r4_Slot_inst16a_get, + Field_t8_Slot_inst16a_get, + Field_s8_Slot_inst16a_get, + Field_r8_Slot_inst16a_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_inst16a_set_field_fns[] = { + Field_t_Slot_inst16a_set, + 0, + 0, + 0, + 0, + Field_s_Slot_inst16a_set, + 0, + 0, + 0, + 0, + 0, + Field_op0_Slot_inst16a_set, + 0, + 0, + Field_r_Slot_inst16a_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_sr_Slot_inst16a_set, + Field_st_Slot_inst16a_set, + 0, + Field_imm4_Slot_inst16a_set, + 0, + Field_i_Slot_inst16a_set, + Field_imm6lo_Slot_inst16a_set, + Field_imm6hi_Slot_inst16a_set, + Field_imm7lo_Slot_inst16a_set, + Field_imm7hi_Slot_inst16a_set, + Field_z_Slot_inst16a_set, + Field_imm6_Slot_inst16a_set, + Field_imm7_Slot_inst16a_set, + Field_t2_Slot_inst16a_set, + Field_s2_Slot_inst16a_set, + Field_r2_Slot_inst16a_set, + Field_t4_Slot_inst16a_set, + Field_s4_Slot_inst16a_set, + Field_r4_Slot_inst16a_set, + Field_t8_Slot_inst16a_set, + Field_s8_Slot_inst16a_set, + Field_r8_Slot_inst16a_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_inst16b_get_field_fns[] = { + Field_t_Slot_inst16b_get, + 0, + 0, + 0, + 0, + Field_s_Slot_inst16b_get, + 0, + 0, + 0, + 0, + 0, + Field_op0_Slot_inst16b_get, + 0, + 0, + Field_r_Slot_inst16b_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_sr_Slot_inst16b_get, + Field_st_Slot_inst16b_get, + 0, + Field_imm4_Slot_inst16b_get, + 0, + Field_i_Slot_inst16b_get, + Field_imm6lo_Slot_inst16b_get, + Field_imm6hi_Slot_inst16b_get, + Field_imm7lo_Slot_inst16b_get, + Field_imm7hi_Slot_inst16b_get, + Field_z_Slot_inst16b_get, + Field_imm6_Slot_inst16b_get, + Field_imm7_Slot_inst16b_get, + Field_t2_Slot_inst16b_get, + Field_s2_Slot_inst16b_get, + Field_r2_Slot_inst16b_get, + Field_t4_Slot_inst16b_get, + Field_s4_Slot_inst16b_get, + Field_r4_Slot_inst16b_get, + Field_t8_Slot_inst16b_get, + Field_s8_Slot_inst16b_get, + Field_r8_Slot_inst16b_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_inst16b_set_field_fns[] = { + Field_t_Slot_inst16b_set, + 0, + 0, + 0, + 0, + Field_s_Slot_inst16b_set, + 0, + 0, + 0, + 0, + 0, + Field_op0_Slot_inst16b_set, + 0, + 0, + Field_r_Slot_inst16b_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_sr_Slot_inst16b_set, + Field_st_Slot_inst16b_set, + 0, + Field_imm4_Slot_inst16b_set, + 0, + Field_i_Slot_inst16b_set, + Field_imm6lo_Slot_inst16b_set, + Field_imm6hi_Slot_inst16b_set, + Field_imm7lo_Slot_inst16b_set, + Field_imm7hi_Slot_inst16b_set, + Field_z_Slot_inst16b_set, + Field_imm6_Slot_inst16b_set, + Field_imm7_Slot_inst16b_set, + Field_t2_Slot_inst16b_set, + Field_s2_Slot_inst16b_set, + Field_r2_Slot_inst16b_set, + Field_t4_Slot_inst16b_set, + Field_s4_Slot_inst16b_set, + Field_r4_Slot_inst16b_set, + Field_t8_Slot_inst16b_set, + Field_s8_Slot_inst16b_set, + Field_r8_Slot_inst16b_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_gp_slot2_get_field_fns[] = { + Field_t_Slot_gp_slot2_get, + 0, + 0, + 0, + 0, + Field_s_Slot_gp_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op2_Slot_gp_slot2_get, + Field_r_Slot_gp_slot2_get, + 0, + 0, + Field_sae_Slot_gp_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm7_Slot_gp_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2030_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2032_Slot_gp_slot2_get, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2039_Slot_gp_slot2_get, + 0, + Field_dsp340050b49a6c_fld2041_Slot_gp_slot2_get, + 0, + 0, + Field_dsp340050b49a6c_fld2044_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2045_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2046_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2047_Slot_gp_slot2_get, + 0, + Field_dsp340050b49a6c_fld2049_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2050_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2051_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2052_Slot_gp_slot2_get, + 0, + 0, + Field_dsp340050b49a6c_fld2055_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2056_Slot_gp_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s3_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2025_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2027_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2258gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2259gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2260gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2261gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2262gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2263gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2264gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2266gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2267gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2268gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2269gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2270gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2271gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2272_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2273gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2274gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2275gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2277gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2278gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2279gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2280gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2281gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2282gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2283gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2284gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2286gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2287gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2288gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2289gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2290gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2291gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2292gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2293gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2294gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2295gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2296gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2297gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2298gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2299gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2300gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2301gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2302_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2303gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2304gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2305_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2306gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2308gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2309gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2310gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2312gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2313_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2314gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2316gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2317gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2318gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2319gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2320gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2321gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2322gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2323gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2324gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2325gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2326gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2327gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2328gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2329gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2330gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2331gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2332gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2333gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2334gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2335gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2336gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2337gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2338gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2339gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2340gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2341gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2342gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2343gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2344gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2345gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2346gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2347gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2348gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2349gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2350gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2351gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2352gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2353gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2354gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2355gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2356gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2357gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2358gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2359gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2361gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2362gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2364gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2366gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2368gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2369gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2370gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2371gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2372gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2373gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2374gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2375gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2376gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2378gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2379gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2381gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2383gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2384_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2385gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2386_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2387gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2388gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld2389gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld3663gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld3664gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld3665gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld3666_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld3667gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld3668gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld3669gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld3670gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld3671gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld3673gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld3674gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld3675gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld3676gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld3678gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld3679gp_slot2_Slot_gp_slot2_get, + Field_dsp340050b49a6c_fld3680gp_slot2_Slot_gp_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_gp_slot2_set_field_fns[] = { + Field_t_Slot_gp_slot2_set, + 0, + 0, + 0, + 0, + Field_s_Slot_gp_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op2_Slot_gp_slot2_set, + Field_r_Slot_gp_slot2_set, + 0, + 0, + Field_sae_Slot_gp_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm7_Slot_gp_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2030_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2032_Slot_gp_slot2_set, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2039_Slot_gp_slot2_set, + 0, + Field_dsp340050b49a6c_fld2041_Slot_gp_slot2_set, + 0, + 0, + Field_dsp340050b49a6c_fld2044_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2045_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2046_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2047_Slot_gp_slot2_set, + 0, + Field_dsp340050b49a6c_fld2049_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2050_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2051_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2052_Slot_gp_slot2_set, + 0, + 0, + Field_dsp340050b49a6c_fld2055_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2056_Slot_gp_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s3_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2025_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2027_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2258gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2259gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2260gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2261gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2262gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2263gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2264gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2266gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2267gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2268gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2269gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2270gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2271gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2272_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2273gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2274gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2275gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2277gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2278gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2279gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2280gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2281gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2282gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2283gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2284gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2286gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2287gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2288gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2289gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2290gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2291gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2292gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2293gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2294gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2295gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2296gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2297gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2298gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2299gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2300gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2301gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2302_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2303gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2304gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2305_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2306gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2308gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2309gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2310gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2312gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2313_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2314gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2316gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2317gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2318gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2319gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2320gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2321gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2322gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2323gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2324gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2325gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2326gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2327gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2328gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2329gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2330gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2331gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2332gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2333gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2334gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2335gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2336gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2337gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2338gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2339gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2340gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2341gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2342gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2343gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2344gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2345gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2346gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2347gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2348gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2349gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2350gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2351gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2352gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2353gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2354gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2355gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2356gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2357gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2358gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2359gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2361gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2362gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2364gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2366gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2368gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2369gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2370gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2371gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2372gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2373gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2374gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2375gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2376gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2378gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2379gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2381gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2383gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2384_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2385gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2386_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2387gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2388gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld2389gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld3663gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld3664gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld3665gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld3666_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld3667gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld3668gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld3669gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld3670gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld3671gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld3673gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld3674gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld3675gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld3676gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld3678gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld3679gp_slot2_Slot_gp_slot2_set, + Field_dsp340050b49a6c_fld3680gp_slot2_Slot_gp_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_gp_slot1_get_field_fns[] = { + 0, + 0, + 0, + 0, + 0, + Field_s_Slot_gp_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2046_Slot_gp_slot1_get, + 0, + Field_dsp340050b49a6c_fld2048_Slot_gp_slot1_get, + Field_dsp340050b49a6c_fld2049_Slot_gp_slot1_get, + Field_dsp340050b49a6c_fld2050_Slot_gp_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s4_Slot_gp_slot1_get, + Field_dsp340050b49a6c_fld2026_Slot_gp_slot1_get, + Field_dsp340050b49a6c_fld2031_Slot_gp_slot1_get, + Field_dsp340050b49a6c_fld2394gp_slot1_Slot_gp_slot1_get, + Field_dsp340050b49a6c_fld2395gp_slot1_Slot_gp_slot1_get, + Field_dsp340050b49a6c_fld2397gp_slot1_Slot_gp_slot1_get, + Field_dsp340050b49a6c_fld2398gp_slot1_Slot_gp_slot1_get, + Field_dsp340050b49a6c_fld2399gp_slot1_Slot_gp_slot1_get, + Field_dsp340050b49a6c_fld2400gp_slot1_Slot_gp_slot1_get, + Field_dsp340050b49a6c_fld2402gp_slot1_Slot_gp_slot1_get, + Field_dsp340050b49a6c_fld2403gp_slot1_Slot_gp_slot1_get, + Field_dsp340050b49a6c_fld2405gp_slot1_Slot_gp_slot1_get, + Field_dsp340050b49a6c_fld3681gp_slot1_Slot_gp_slot1_get, + Field_dsp340050b49a6c_fld3683gp_slot1_Slot_gp_slot1_get, + Field_dsp340050b49a6c_fld3684gp_slot1_Slot_gp_slot1_get, + Field_dsp340050b49a6c_fld3686gp_slot1_Slot_gp_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_gp_slot1_set_field_fns[] = { + 0, + 0, + 0, + 0, + 0, + Field_s_Slot_gp_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2046_Slot_gp_slot1_set, + 0, + Field_dsp340050b49a6c_fld2048_Slot_gp_slot1_set, + Field_dsp340050b49a6c_fld2049_Slot_gp_slot1_set, + Field_dsp340050b49a6c_fld2050_Slot_gp_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s4_Slot_gp_slot1_set, + Field_dsp340050b49a6c_fld2026_Slot_gp_slot1_set, + Field_dsp340050b49a6c_fld2031_Slot_gp_slot1_set, + Field_dsp340050b49a6c_fld2394gp_slot1_Slot_gp_slot1_set, + Field_dsp340050b49a6c_fld2395gp_slot1_Slot_gp_slot1_set, + Field_dsp340050b49a6c_fld2397gp_slot1_Slot_gp_slot1_set, + Field_dsp340050b49a6c_fld2398gp_slot1_Slot_gp_slot1_set, + Field_dsp340050b49a6c_fld2399gp_slot1_Slot_gp_slot1_set, + Field_dsp340050b49a6c_fld2400gp_slot1_Slot_gp_slot1_set, + Field_dsp340050b49a6c_fld2402gp_slot1_Slot_gp_slot1_set, + Field_dsp340050b49a6c_fld2403gp_slot1_Slot_gp_slot1_set, + Field_dsp340050b49a6c_fld2405gp_slot1_Slot_gp_slot1_set, + Field_dsp340050b49a6c_fld3681gp_slot1_Slot_gp_slot1_set, + Field_dsp340050b49a6c_fld3683gp_slot1_Slot_gp_slot1_set, + Field_dsp340050b49a6c_fld3684gp_slot1_Slot_gp_slot1_set, + Field_dsp340050b49a6c_fld3686gp_slot1_Slot_gp_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_gp_slot0_get_field_fns[] = { + Field_t_Slot_gp_slot0_get, + 0, + 0, + 0, + 0, + Field_s_Slot_gp_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op2_Slot_gp_slot0_get, + Field_r_Slot_gp_slot0_get, + 0, + 0, + Field_sae_Slot_gp_slot0_get, + Field_sal_Slot_gp_slot0_get, + Field_sargt_Slot_gp_slot0_get, + 0, + Field_sas_Slot_gp_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm6_Slot_gp_slot0_get, + Field_imm7_Slot_gp_slot0_get, + 0, + 0, + 0, + 0, + Field_s4_Slot_gp_slot0_get, + 0, + 0, + Field_s8_Slot_gp_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2030_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2032_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2035_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2036_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2037_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2038_Slot_gp_slot0_get, + 0, + Field_dsp340050b49a6c_fld2040_Slot_gp_slot0_get, + 0, + Field_dsp340050b49a6c_fld2042_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2043_Slot_gp_slot0_get, + 0, + Field_dsp340050b49a6c_fld2045_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2046_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2047_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2048_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2049_Slot_gp_slot0_get, + 0, + Field_dsp340050b49a6c_fld2051_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2052_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2053_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2054_Slot_gp_slot0_get, + 0, + Field_dsp340050b49a6c_fld2056_Slot_gp_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s5_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2058_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2067_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2407gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2409gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2410gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2411gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2412gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2413gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2415gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2416gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2417gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2418gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2419gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2420gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2422gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2423gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2424gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2425gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2426gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2427gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2429gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2430gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2431gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2432gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2433gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2434gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2435gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2436gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2437gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2438gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2439gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2440gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2441gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2443gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2444gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2445_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2447gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2448_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2449gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2451gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2452gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2453gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2454gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2455gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2456gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2457gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2458gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2459gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2460gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2461gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2462_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2463gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2464gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2465gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2466gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2467gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2468gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2470gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2471gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2472gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2473gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2474gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2475gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2477gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2479gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2480gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2481gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2482gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2483gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2484gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2485gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2486gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2487gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2488gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2489gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2490gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2491gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2492gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2493gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2494gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2495gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2496gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2497gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2498gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2499gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2500gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2501gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2502gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2503gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2504gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2505gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2506gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2507gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2508gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2509gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2510gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2512gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2514gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2515gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2516gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2517gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2518gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2519gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2520gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2521gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2523gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2524gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2526gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2527gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2528gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2529gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2530_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld2531gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld3688gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld3689gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld3690gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld3691gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld3692gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld3693gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld3695gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld3696gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld3697gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld3698gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld3699gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld3700gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld3702gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld3703gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld3705gp_slot0_Slot_gp_slot0_get, + Field_dsp340050b49a6c_fld3706gp_slot0_Slot_gp_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_gp_slot0_set_field_fns[] = { + Field_t_Slot_gp_slot0_set, + 0, + 0, + 0, + 0, + Field_s_Slot_gp_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op2_Slot_gp_slot0_set, + Field_r_Slot_gp_slot0_set, + 0, + 0, + Field_sae_Slot_gp_slot0_set, + Field_sal_Slot_gp_slot0_set, + Field_sargt_Slot_gp_slot0_set, + 0, + Field_sas_Slot_gp_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm6_Slot_gp_slot0_set, + Field_imm7_Slot_gp_slot0_set, + 0, + 0, + 0, + 0, + Field_s4_Slot_gp_slot0_set, + 0, + 0, + Field_s8_Slot_gp_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2030_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2032_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2035_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2036_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2037_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2038_Slot_gp_slot0_set, + 0, + Field_dsp340050b49a6c_fld2040_Slot_gp_slot0_set, + 0, + Field_dsp340050b49a6c_fld2042_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2043_Slot_gp_slot0_set, + 0, + Field_dsp340050b49a6c_fld2045_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2046_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2047_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2048_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2049_Slot_gp_slot0_set, + 0, + Field_dsp340050b49a6c_fld2051_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2052_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2053_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2054_Slot_gp_slot0_set, + 0, + Field_dsp340050b49a6c_fld2056_Slot_gp_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s5_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2058_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2067_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2407gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2409gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2410gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2411gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2412gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2413gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2415gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2416gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2417gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2418gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2419gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2420gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2422gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2423gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2424gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2425gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2426gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2427gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2429gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2430gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2431gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2432gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2433gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2434gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2435gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2436gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2437gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2438gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2439gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2440gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2441gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2443gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2444gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2445_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2447gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2448_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2449gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2451gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2452gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2453gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2454gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2455gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2456gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2457gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2458gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2459gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2460gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2461gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2462_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2463gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2464gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2465gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2466gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2467gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2468gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2470gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2471gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2472gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2473gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2474gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2475gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2477gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2479gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2480gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2481gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2482gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2483gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2484gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2485gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2486gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2487gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2488gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2489gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2490gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2491gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2492gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2493gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2494gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2495gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2496gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2497gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2498gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2499gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2500gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2501gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2502gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2503gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2504gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2505gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2506gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2507gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2508gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2509gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2510gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2512gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2514gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2515gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2516gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2517gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2518gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2519gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2520gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2521gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2523gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2524gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2526gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2527gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2528gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2529gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2530_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld2531gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld3688gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld3689gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld3690gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld3691gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld3692gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld3693gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld3695gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld3696gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld3697gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld3698gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld3699gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld3700gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld3702gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld3703gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld3705gp_slot0_Slot_gp_slot0_set, + Field_dsp340050b49a6c_fld3706gp_slot0_Slot_gp_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_dot_slot2_get_field_fns[] = { + Field_t_Slot_dot_slot2_get, + 0, + 0, + 0, + 0, + Field_s_Slot_dot_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r_Slot_dot_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2030_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2032_Slot_dot_slot2_get, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2039_Slot_dot_slot2_get, + 0, + Field_dsp340050b49a6c_fld2041_Slot_dot_slot2_get, + 0, + 0, + Field_dsp340050b49a6c_fld2044_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2045_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2046_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2047_Slot_dot_slot2_get, + 0, + Field_dsp340050b49a6c_fld2049_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2050_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2051_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2052_Slot_dot_slot2_get, + 0, + 0, + Field_dsp340050b49a6c_fld2055_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2056_Slot_dot_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2025_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2027_Slot_dot_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s6_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2532dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2533dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2534dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2535dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2536dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2537dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2538dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2539dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2540dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2541dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2542dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2543dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2544dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2545dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2546dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2547dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2548dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2549dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2550dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2551dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2552dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2553dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2554dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2555dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2556dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2557dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2558dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2559dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2560dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2561dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2562dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2563dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2564dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2565dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2566dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2567dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2568dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2569dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2571dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2572dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2573dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2574dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2575dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2576dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2577dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2578_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2579dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2580dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2581dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2582dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2583dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2584dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2585dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2586dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2587dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2588dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2589dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2590dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2591dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2592dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2595dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2596dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2598dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2599dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2601dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2602dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2604dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2605_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2606dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2608dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2609dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2610dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2611dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2612_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2613dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2614_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2615dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2616dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2617dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2618dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2619dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2620dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2621dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2622dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2623dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2624dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2625_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2626dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2628dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2630dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2632dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2633dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2635dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2636dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2637dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2640dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2641dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2642dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2643dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2644dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2645dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2646dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2647dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2648dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2649dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2650dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2651dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2652dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2654dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2655dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2656dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2657dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld2658dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3708dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3709dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3710dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3711dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3712_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3713dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3714dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3715_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3716dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3717dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3718_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3719dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3721dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3722_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3723dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3724dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3725dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3726dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3727dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3728dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3729dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3731dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3732dot_slot2_Slot_dot_slot2_get, + Field_dsp340050b49a6c_fld3733dot_slot2_Slot_dot_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_dot_slot2_set_field_fns[] = { + Field_t_Slot_dot_slot2_set, + 0, + 0, + 0, + 0, + Field_s_Slot_dot_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r_Slot_dot_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2030_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2032_Slot_dot_slot2_set, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2039_Slot_dot_slot2_set, + 0, + Field_dsp340050b49a6c_fld2041_Slot_dot_slot2_set, + 0, + 0, + Field_dsp340050b49a6c_fld2044_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2045_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2046_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2047_Slot_dot_slot2_set, + 0, + Field_dsp340050b49a6c_fld2049_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2050_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2051_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2052_Slot_dot_slot2_set, + 0, + 0, + Field_dsp340050b49a6c_fld2055_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2056_Slot_dot_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2025_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2027_Slot_dot_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s6_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2532dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2533dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2534dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2535dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2536dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2537dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2538dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2539dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2540dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2541dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2542dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2543dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2544dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2545dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2546dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2547dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2548dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2549dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2550dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2551dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2552dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2553dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2554dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2555dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2556dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2557dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2558dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2559dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2560dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2561dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2562dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2563dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2564dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2565dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2566dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2567dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2568dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2569dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2571dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2572dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2573dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2574dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2575dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2576dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2577dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2578_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2579dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2580dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2581dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2582dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2583dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2584dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2585dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2586dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2587dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2588dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2589dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2590dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2591dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2592dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2595dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2596dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2598dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2599dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2601dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2602dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2604dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2605_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2606dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2608dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2609dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2610dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2611dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2612_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2613dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2614_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2615dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2616dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2617dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2618dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2619dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2620dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2621dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2622dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2623dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2624dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2625_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2626dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2628dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2630dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2632dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2633dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2635dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2636dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2637dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2640dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2641dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2642dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2643dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2644dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2645dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2646dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2647dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2648dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2649dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2650dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2651dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2652dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2654dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2655dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2656dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2657dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld2658dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3708dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3709dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3710dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3711dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3712_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3713dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3714dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3715_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3716dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3717dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3718_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3719dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3721dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3722_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3723dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3724dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3725dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3726dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3727dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3728dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3729dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3731dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3732dot_slot2_Slot_dot_slot2_set, + Field_dsp340050b49a6c_fld3733dot_slot2_Slot_dot_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_dot_slot1_get_field_fns[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2048_Slot_dot_slot1_get, + 0, + Field_dsp340050b49a6c_fld2050_Slot_dot_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2026_Slot_dot_slot1_get, + Field_dsp340050b49a6c_fld2031_Slot_dot_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s7_Slot_dot_slot1_get, + Field_dsp340050b49a6c_fld3734dot_slot1_Slot_dot_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_dot_slot1_set_field_fns[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2048_Slot_dot_slot1_set, + 0, + Field_dsp340050b49a6c_fld2050_Slot_dot_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2026_Slot_dot_slot1_set, + Field_dsp340050b49a6c_fld2031_Slot_dot_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s7_Slot_dot_slot1_set, + Field_dsp340050b49a6c_fld3734dot_slot1_Slot_dot_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_dot_slot0_get_field_fns[] = { + Field_t_Slot_dot_slot0_get, + 0, + 0, + 0, + 0, + Field_s_Slot_dot_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r_Slot_dot_slot0_get, + 0, + 0, + 0, + Field_sal_Slot_dot_slot0_get, + Field_sargt_Slot_dot_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm7_Slot_dot_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_dot_slot0_get, + 0, + Field_dsp340050b49a6c_fld2032_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2035_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2036_Slot_dot_slot0_get, + 0, + Field_dsp340050b49a6c_fld2038_Slot_dot_slot0_get, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2043_Slot_dot_slot0_get, + 0, + Field_dsp340050b49a6c_fld2045_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2046_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2047_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2048_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2049_Slot_dot_slot0_get, + 0, + 0, + Field_dsp340050b49a6c_fld2052_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2053_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2054_Slot_dot_slot0_get, + 0, + Field_dsp340050b49a6c_fld2056_Slot_dot_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s8_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2068_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2666dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2667dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2668dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2669dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2671dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2672dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2673dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2674dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2675dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2676dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2677dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2678dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2679dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2680dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2681dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2682dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2683dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2684dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2685dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2686dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2688dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2689dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2690dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2692dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2693dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2695dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2697dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2699dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2700dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2701dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2702dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2703dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2704dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld2705dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld3735dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld3736_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld3737dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld3738dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld3739dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld3740dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld3741dot_slot0_Slot_dot_slot0_get, + Field_dsp340050b49a6c_fld3742dot_slot0_Slot_dot_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_dot_slot0_set_field_fns[] = { + Field_t_Slot_dot_slot0_set, + 0, + 0, + 0, + 0, + Field_s_Slot_dot_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r_Slot_dot_slot0_set, + 0, + 0, + 0, + Field_sal_Slot_dot_slot0_set, + Field_sargt_Slot_dot_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm7_Slot_dot_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_dot_slot0_set, + 0, + Field_dsp340050b49a6c_fld2032_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2035_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2036_Slot_dot_slot0_set, + 0, + Field_dsp340050b49a6c_fld2038_Slot_dot_slot0_set, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2043_Slot_dot_slot0_set, + 0, + Field_dsp340050b49a6c_fld2045_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2046_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2047_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2048_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2049_Slot_dot_slot0_set, + 0, + 0, + Field_dsp340050b49a6c_fld2052_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2053_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2054_Slot_dot_slot0_set, + 0, + Field_dsp340050b49a6c_fld2056_Slot_dot_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s8_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2068_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2666dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2667dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2668dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2669dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2671dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2672dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2673dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2674dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2675dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2676dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2677dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2678dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2679dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2680dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2681dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2682dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2683dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2684dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2685dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2686dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2688dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2689dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2690dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2692dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2693dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2695dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2697dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2699dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2700dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2701dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2702dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2703dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2704dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld2705dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld3735dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld3736_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld3737dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld3738dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld3739dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld3740dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld3741dot_slot0_Slot_dot_slot0_set, + Field_dsp340050b49a6c_fld3742dot_slot0_Slot_dot_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_pq_slot2_get_field_fns[] = { + Field_t_Slot_pq_slot2_get, + 0, + 0, + 0, + 0, + Field_s_Slot_pq_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op2_Slot_pq_slot2_get, + Field_r_Slot_pq_slot2_get, + 0, + 0, + Field_sae_Slot_pq_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm7_Slot_pq_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2030_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2032_Slot_pq_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2044_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2045_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2046_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2047_Slot_pq_slot2_get, + 0, + Field_dsp340050b49a6c_fld2049_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2050_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2051_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2052_Slot_pq_slot2_get, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2056_Slot_pq_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2025_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2027_Slot_pq_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s9_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2706pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2707pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2708pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2709pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2710pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2711pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2713pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2714pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2715pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2717pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2718pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2719pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2721pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2722pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2723pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2724pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2725pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2726pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2727pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2728pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2729pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2730pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2731pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2732pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2733pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2734pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2735pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2736pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2737_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2738pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2739pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2741pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2742pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2743pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2746pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2747pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2748pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2750pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2751pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2752pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2753pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2754pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2755pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2756pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2757pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2758pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2759pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2760pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2761pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2762pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2763pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2764pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2765pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2766pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2767pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2768pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2769pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2770pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2771pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2772pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2773pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2774pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2775pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2776pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2777pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2778pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2779pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2780pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2781pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2782pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2783pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2784pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2785pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2786pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2787pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2788pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2789pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2790pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2791pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2792pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2793pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2795pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2796pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2798pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2801pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2803pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2805pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2806pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2807pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2808pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2809pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2810pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2811pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2812pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2814pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2816pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2817_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2818pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2819_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2820pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2821pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld2823pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld3744pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld3745pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld3746pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld3747pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld3748_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld3749pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld3750pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld3751pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld3752pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld3753pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld3754pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld3756pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld3757pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld3758pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld3759pq_slot2_Slot_pq_slot2_get, + Field_dsp340050b49a6c_fld3760pq_slot2_Slot_pq_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_pq_slot2_set_field_fns[] = { + Field_t_Slot_pq_slot2_set, + 0, + 0, + 0, + 0, + Field_s_Slot_pq_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op2_Slot_pq_slot2_set, + Field_r_Slot_pq_slot2_set, + 0, + 0, + Field_sae_Slot_pq_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm7_Slot_pq_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2030_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2032_Slot_pq_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2044_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2045_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2046_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2047_Slot_pq_slot2_set, + 0, + Field_dsp340050b49a6c_fld2049_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2050_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2051_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2052_Slot_pq_slot2_set, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2056_Slot_pq_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2025_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2027_Slot_pq_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s9_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2706pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2707pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2708pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2709pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2710pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2711pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2713pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2714pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2715pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2717pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2718pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2719pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2721pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2722pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2723pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2724pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2725pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2726pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2727pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2728pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2729pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2730pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2731pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2732pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2733pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2734pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2735pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2736pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2737_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2738pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2739pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2741pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2742pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2743pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2746pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2747pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2748pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2750pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2751pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2752pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2753pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2754pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2755pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2756pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2757pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2758pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2759pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2760pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2761pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2762pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2763pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2764pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2765pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2766pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2767pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2768pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2769pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2770pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2771pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2772pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2773pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2774pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2775pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2776pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2777pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2778pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2779pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2780pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2781pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2782pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2783pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2784pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2785pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2786pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2787pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2788pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2789pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2790pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2791pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2792pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2793pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2795pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2796pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2798pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2801pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2803pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2805pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2806pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2807pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2808pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2809pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2810pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2811pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2812pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2814pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2816pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2817_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2818pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2819_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2820pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2821pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld2823pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld3744pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld3745pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld3746pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld3747pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld3748_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld3749pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld3750pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld3751pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld3752pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld3753pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld3754pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld3756pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld3757pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld3758pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld3759pq_slot2_Slot_pq_slot2_set, + Field_dsp340050b49a6c_fld3760pq_slot2_Slot_pq_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_pq_slot1_get_field_fns[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2049_Slot_pq_slot1_get, + Field_dsp340050b49a6c_fld2050_Slot_pq_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2026_Slot_pq_slot1_get, + Field_dsp340050b49a6c_fld2031_Slot_pq_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s10_Slot_pq_slot1_get, + Field_dsp340050b49a6c_fld2825pq_slot1_Slot_pq_slot1_get, + Field_dsp340050b49a6c_fld2826pq_slot1_Slot_pq_slot1_get, + Field_dsp340050b49a6c_fld3761pq_slot1_Slot_pq_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_pq_slot1_set_field_fns[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2049_Slot_pq_slot1_set, + Field_dsp340050b49a6c_fld2050_Slot_pq_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2026_Slot_pq_slot1_set, + Field_dsp340050b49a6c_fld2031_Slot_pq_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s10_Slot_pq_slot1_set, + Field_dsp340050b49a6c_fld2825pq_slot1_Slot_pq_slot1_set, + Field_dsp340050b49a6c_fld2826pq_slot1_Slot_pq_slot1_set, + Field_dsp340050b49a6c_fld3761pq_slot1_Slot_pq_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_pq_slot0_get_field_fns[] = { + Field_t_Slot_pq_slot0_get, + 0, + 0, + 0, + 0, + Field_s_Slot_pq_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op2_Slot_pq_slot0_get, + Field_r_Slot_pq_slot0_get, + 0, + 0, + Field_sae_Slot_pq_slot0_get, + Field_sal_Slot_pq_slot0_get, + Field_sargt_Slot_pq_slot0_get, + 0, + Field_sas_Slot_pq_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm6_Slot_pq_slot0_get, + Field_imm7_Slot_pq_slot0_get, + 0, + 0, + 0, + 0, + Field_s4_Slot_pq_slot0_get, + 0, + 0, + Field_s8_Slot_pq_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2030_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2032_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2035_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2036_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2037_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2038_Slot_pq_slot0_get, + 0, + Field_dsp340050b49a6c_fld2040_Slot_pq_slot0_get, + 0, + Field_dsp340050b49a6c_fld2042_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2043_Slot_pq_slot0_get, + 0, + Field_dsp340050b49a6c_fld2045_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2046_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2047_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2048_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2049_Slot_pq_slot0_get, + 0, + Field_dsp340050b49a6c_fld2051_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2052_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2053_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2054_Slot_pq_slot0_get, + 0, + Field_dsp340050b49a6c_fld2056_Slot_pq_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s11_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2059_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2069_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2827pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2829pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2830pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2831pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2832pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2833pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2835pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2836pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2837pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2838pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2839pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2840pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2842pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2843pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2844pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2845pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2846pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2847pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2849pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2850pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2851pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2852pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2853pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2854pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2855pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2856pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2857pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2858pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2859pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2860pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2861pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2863pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2864pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2865_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2867pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2869pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2871pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2872pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2873pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2874pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2875pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2876pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2877pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2878pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2879pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2880pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2881pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2882_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2883pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2884pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2885pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2886pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2887pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2888pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2890pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2891pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2892pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2893pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2894pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2895pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2897pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2899pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2900pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2901pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2902pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2903pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2904pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2905pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2906pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2907pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2908pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2909pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2910pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2911pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2912pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2913pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2914pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2915pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2916pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2917pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2918pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2919pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2920pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2921pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2922pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2923pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2924pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2925pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2926pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2927pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2928pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2929pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2930pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2932pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2934pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2935pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2936pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2937pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2939pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2940_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2941pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2942pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2943pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2945pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2946pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2947pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2948pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2949pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld2950pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld3763pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld3764pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld3765pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld3766pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld3767pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld3768pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld3769pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld3770pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld3771pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld3772_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld3773pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld3775pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld3776pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld3777pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld3778pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld3779pq_slot0_Slot_pq_slot0_get, + Field_dsp340050b49a6c_fld3780pq_slot0_Slot_pq_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_pq_slot0_set_field_fns[] = { + Field_t_Slot_pq_slot0_set, + 0, + 0, + 0, + 0, + Field_s_Slot_pq_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op2_Slot_pq_slot0_set, + Field_r_Slot_pq_slot0_set, + 0, + 0, + Field_sae_Slot_pq_slot0_set, + Field_sal_Slot_pq_slot0_set, + Field_sargt_Slot_pq_slot0_set, + 0, + Field_sas_Slot_pq_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm6_Slot_pq_slot0_set, + Field_imm7_Slot_pq_slot0_set, + 0, + 0, + 0, + 0, + Field_s4_Slot_pq_slot0_set, + 0, + 0, + Field_s8_Slot_pq_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2030_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2032_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2035_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2036_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2037_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2038_Slot_pq_slot0_set, + 0, + Field_dsp340050b49a6c_fld2040_Slot_pq_slot0_set, + 0, + Field_dsp340050b49a6c_fld2042_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2043_Slot_pq_slot0_set, + 0, + Field_dsp340050b49a6c_fld2045_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2046_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2047_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2048_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2049_Slot_pq_slot0_set, + 0, + Field_dsp340050b49a6c_fld2051_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2052_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2053_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2054_Slot_pq_slot0_set, + 0, + Field_dsp340050b49a6c_fld2056_Slot_pq_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s11_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2059_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2069_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2827pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2829pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2830pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2831pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2832pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2833pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2835pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2836pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2837pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2838pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2839pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2840pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2842pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2843pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2844pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2845pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2846pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2847pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2849pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2850pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2851pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2852pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2853pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2854pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2855pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2856pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2857pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2858pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2859pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2860pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2861pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2863pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2864pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2865_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2867pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2869pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2871pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2872pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2873pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2874pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2875pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2876pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2877pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2878pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2879pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2880pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2881pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2882_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2883pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2884pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2885pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2886pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2887pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2888pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2890pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2891pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2892pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2893pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2894pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2895pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2897pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2899pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2900pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2901pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2902pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2903pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2904pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2905pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2906pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2907pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2908pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2909pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2910pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2911pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2912pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2913pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2914pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2915pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2916pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2917pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2918pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2919pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2920pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2921pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2922pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2923pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2924pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2925pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2926pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2927pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2928pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2929pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2930pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2932pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2934pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2935pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2936pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2937pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2939pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2940_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2941pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2942pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2943pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2945pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2946pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2947pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2948pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2949pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld2950pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld3763pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld3764pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld3765pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld3766pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld3767pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld3768pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld3769pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld3770pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld3771pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld3772_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld3773pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld3775pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld3776pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld3777pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld3778pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld3779pq_slot0_Slot_pq_slot0_set, + Field_dsp340050b49a6c_fld3780pq_slot0_Slot_pq_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_acc2_slot2_get_field_fns[] = { + 0, + 0, + 0, + 0, + 0, + Field_s_Slot_acc2_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r_Slot_acc2_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2045_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld2046_Slot_acc2_slot2_get, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2052_Slot_acc2_slot2_get, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2056_Slot_acc2_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2027_Slot_acc2_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s12_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld2953acc2_slot2_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld2954acc2_slot2_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld2955acc2_slot2_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld2956acc2_slot2_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld2957acc2_slot2_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld2958acc2_slot2_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld2959acc2_slot2_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld2960acc2_slot2_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld2963acc2_slot2_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld2964acc2_slot2_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld2966acc2_slot2_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld2967acc2_slot2_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld3782acc2_slot2_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld3783acc2_slot2_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld3784acc2_slot2_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld3785acc2_slot2_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld3786acc2_slot2_Slot_acc2_slot2_get, + Field_dsp340050b49a6c_fld3788acc2_slot2_Slot_acc2_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_acc2_slot2_set_field_fns[] = { + 0, + 0, + 0, + 0, + 0, + Field_s_Slot_acc2_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r_Slot_acc2_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2045_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld2046_Slot_acc2_slot2_set, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2052_Slot_acc2_slot2_set, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2056_Slot_acc2_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2027_Slot_acc2_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s12_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld2953acc2_slot2_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld2954acc2_slot2_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld2955acc2_slot2_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld2956acc2_slot2_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld2957acc2_slot2_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld2958acc2_slot2_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld2959acc2_slot2_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld2960acc2_slot2_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld2963acc2_slot2_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld2964acc2_slot2_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld2966acc2_slot2_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld2967acc2_slot2_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld3782acc2_slot2_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld3783acc2_slot2_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld3784acc2_slot2_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld3785acc2_slot2_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld3786acc2_slot2_Slot_acc2_slot2_set, + Field_dsp340050b49a6c_fld3788acc2_slot2_Slot_acc2_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_acc2_slot1_get_field_fns[] = { + Field_t_Slot_acc2_slot1_get, + 0, + 0, + 0, + 0, + Field_s_Slot_acc2_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2047_Slot_acc2_slot1_get, + Field_dsp340050b49a6c_fld2048_Slot_acc2_slot1_get, + 0, + Field_dsp340050b49a6c_fld2050_Slot_acc2_slot1_get, + 0, + Field_dsp340050b49a6c_fld2052_Slot_acc2_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2026_Slot_acc2_slot1_get, + Field_dsp340050b49a6c_fld2031_Slot_acc2_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s13_Slot_acc2_slot1_get, + Field_dsp340050b49a6c_fld2028_Slot_acc2_slot1_get, + Field_dsp340050b49a6c_fld2075_Slot_acc2_slot1_get, + Field_dsp340050b49a6c_fld2968acc2_slot1_Slot_acc2_slot1_get, + Field_dsp340050b49a6c_fld2969acc2_slot1_Slot_acc2_slot1_get, + Field_dsp340050b49a6c_fld3790acc2_slot1_Slot_acc2_slot1_get, + Field_dsp340050b49a6c_fld3793acc2_slot1_Slot_acc2_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_acc2_slot1_set_field_fns[] = { + Field_t_Slot_acc2_slot1_set, + 0, + 0, + 0, + 0, + Field_s_Slot_acc2_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2047_Slot_acc2_slot1_set, + Field_dsp340050b49a6c_fld2048_Slot_acc2_slot1_set, + 0, + Field_dsp340050b49a6c_fld2050_Slot_acc2_slot1_set, + 0, + Field_dsp340050b49a6c_fld2052_Slot_acc2_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2026_Slot_acc2_slot1_set, + Field_dsp340050b49a6c_fld2031_Slot_acc2_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s13_Slot_acc2_slot1_set, + Field_dsp340050b49a6c_fld2028_Slot_acc2_slot1_set, + Field_dsp340050b49a6c_fld2075_Slot_acc2_slot1_set, + Field_dsp340050b49a6c_fld2968acc2_slot1_Slot_acc2_slot1_set, + Field_dsp340050b49a6c_fld2969acc2_slot1_Slot_acc2_slot1_set, + Field_dsp340050b49a6c_fld3790acc2_slot1_Slot_acc2_slot1_set, + Field_dsp340050b49a6c_fld3793acc2_slot1_Slot_acc2_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_acc2_slot0_get_field_fns[] = { + Field_t_Slot_acc2_slot0_get, + 0, + 0, + 0, + 0, + Field_s_Slot_acc2_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r_Slot_acc2_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm7_Slot_acc2_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2039_Slot_acc2_slot0_get, + 0, + Field_dsp340050b49a6c_fld2041_Slot_acc2_slot0_get, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2045_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld2046_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld2047_Slot_acc2_slot0_get, + 0, + 0, + Field_dsp340050b49a6c_fld2050_Slot_acc2_slot0_get, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2055_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld2056_Slot_acc2_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s14_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld2973acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld2974acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld2975acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld2976acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld2977acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld2980acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld2981acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld2982acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld2984acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld2985acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld2987acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld2989acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld2990acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld3795acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld3796acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld3797_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld3798acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld3799acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld3800acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld3801acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld3802acc2_slot0_Slot_acc2_slot0_get, + Field_dsp340050b49a6c_fld3803acc2_slot0_Slot_acc2_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_acc2_slot0_set_field_fns[] = { + Field_t_Slot_acc2_slot0_set, + 0, + 0, + 0, + 0, + Field_s_Slot_acc2_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r_Slot_acc2_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm7_Slot_acc2_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2039_Slot_acc2_slot0_set, + 0, + Field_dsp340050b49a6c_fld2041_Slot_acc2_slot0_set, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2045_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld2046_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld2047_Slot_acc2_slot0_set, + 0, + 0, + Field_dsp340050b49a6c_fld2050_Slot_acc2_slot0_set, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2055_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld2056_Slot_acc2_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s14_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld2973acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld2974acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld2975acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld2976acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld2977acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld2980acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld2981acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld2982acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld2984acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld2985acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld2987acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld2989acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld2990acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld3795acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld3796acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld3797_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld3798acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld3799acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld3800acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld3801acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld3802acc2_slot0_Slot_acc2_slot0_set, + Field_dsp340050b49a6c_fld3803acc2_slot0_Slot_acc2_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_smod_slot2_get_field_fns[] = { + Field_t_Slot_smod_slot2_get, + 0, + 0, + 0, + 0, + Field_s_Slot_smod_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r_Slot_smod_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2030_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2032_Slot_smod_slot2_get, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2039_Slot_smod_slot2_get, + 0, + Field_dsp340050b49a6c_fld2041_Slot_smod_slot2_get, + 0, + 0, + Field_dsp340050b49a6c_fld2044_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2045_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2046_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2047_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2048_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2049_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2050_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2051_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2052_Slot_smod_slot2_get, + 0, + 0, + Field_dsp340050b49a6c_fld2055_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2056_Slot_smod_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2025_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2027_Slot_smod_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s15_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2991smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2992smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2993smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2994smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2995smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2996smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2997smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2998smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld2999smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3000smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3001smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3002smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3003smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3004smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3005smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3006smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3007smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3008smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3009smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3010smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3011smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3012smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3013smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3014smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3015smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3016smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3017smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3018smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3019smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3020smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3021smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3022smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3023smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3024smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3025smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3026smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3027smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3028smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3030smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3031smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3032smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3033smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3034smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3035smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3036smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3038smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3039smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3040smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3043smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3044smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3046smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3047smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3048_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3049smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3050smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3051smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3052smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3053smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3054smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3055smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3056smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3058smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3059smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3061smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3062_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3063smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3065smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3066smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3067smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3068smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3069smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3070_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3071smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3072smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3073smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3074smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3075smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3076smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3077smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3078smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3079smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3080smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3081smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3082smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3084smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3085smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3087smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3088smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3090smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3091smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3092smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3093smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3096smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3097smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3098smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3099smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3100smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3101smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3102smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3104smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3105smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3106smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3107smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3108smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3109smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3110smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3111smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3113smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3114smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3115smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3116smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3805smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3806smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3807smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3808_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3809smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3810smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3812smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3813smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3814smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3816smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3817_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3818smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3819smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3821smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3822smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3823smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3824smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3825smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3826smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3827smod_slot2_Slot_smod_slot2_get, + Field_dsp340050b49a6c_fld3828smod_slot2_Slot_smod_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_smod_slot2_set_field_fns[] = { + Field_t_Slot_smod_slot2_set, + 0, + 0, + 0, + 0, + Field_s_Slot_smod_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r_Slot_smod_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2030_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2032_Slot_smod_slot2_set, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2039_Slot_smod_slot2_set, + 0, + Field_dsp340050b49a6c_fld2041_Slot_smod_slot2_set, + 0, + 0, + Field_dsp340050b49a6c_fld2044_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2045_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2046_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2047_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2048_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2049_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2050_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2051_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2052_Slot_smod_slot2_set, + 0, + 0, + Field_dsp340050b49a6c_fld2055_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2056_Slot_smod_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2025_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2027_Slot_smod_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s15_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2991smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2992smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2993smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2994smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2995smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2996smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2997smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2998smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld2999smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3000smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3001smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3002smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3003smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3004smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3005smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3006smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3007smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3008smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3009smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3010smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3011smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3012smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3013smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3014smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3015smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3016smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3017smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3018smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3019smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3020smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3021smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3022smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3023smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3024smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3025smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3026smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3027smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3028smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3030smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3031smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3032smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3033smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3034smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3035smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3036smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3038smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3039smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3040smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3043smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3044smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3046smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3047smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3048_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3049smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3050smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3051smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3052smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3053smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3054smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3055smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3056smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3058smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3059smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3061smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3062_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3063smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3065smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3066smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3067smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3068smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3069smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3070_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3071smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3072smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3073smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3074smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3075smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3076smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3077smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3078smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3079smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3080smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3081smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3082smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3084smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3085smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3087smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3088smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3090smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3091smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3092smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3093smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3096smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3097smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3098smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3099smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3100smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3101smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3102smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3104smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3105smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3106smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3107smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3108smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3109smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3110smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3111smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3113smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3114smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3115smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3116smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3805smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3806smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3807smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3808_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3809smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3810smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3812smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3813smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3814smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3816smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3817_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3818smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3819smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3821smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3822smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3823smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3824smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3825smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3826smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3827smod_slot2_Slot_smod_slot2_set, + Field_dsp340050b49a6c_fld3828smod_slot2_Slot_smod_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_smod_slot1_get_field_fns[] = { + 0, + 0, + 0, + 0, + 0, + Field_s_Slot_smod_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2046_Slot_smod_slot1_get, + 0, + Field_dsp340050b49a6c_fld2048_Slot_smod_slot1_get, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2054_Slot_smod_slot1_get, + 0, + Field_dsp340050b49a6c_fld2056_Slot_smod_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2026_Slot_smod_slot1_get, + Field_dsp340050b49a6c_fld2031_Slot_smod_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s16_Slot_smod_slot1_get, + Field_dsp340050b49a6c_fld2033_Slot_smod_slot1_get, + Field_dsp340050b49a6c_fld2080_Slot_smod_slot1_get, + Field_dsp340050b49a6c_fld3117smod_slot1_Slot_smod_slot1_get, + Field_dsp340050b49a6c_fld3118smod_slot1_Slot_smod_slot1_get, + Field_dsp340050b49a6c_fld3829smod_slot1_Slot_smod_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_smod_slot1_set_field_fns[] = { + 0, + 0, + 0, + 0, + 0, + Field_s_Slot_smod_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2046_Slot_smod_slot1_set, + 0, + Field_dsp340050b49a6c_fld2048_Slot_smod_slot1_set, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2054_Slot_smod_slot1_set, + 0, + Field_dsp340050b49a6c_fld2056_Slot_smod_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2026_Slot_smod_slot1_set, + Field_dsp340050b49a6c_fld2031_Slot_smod_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s16_Slot_smod_slot1_set, + Field_dsp340050b49a6c_fld2033_Slot_smod_slot1_set, + Field_dsp340050b49a6c_fld2080_Slot_smod_slot1_set, + Field_dsp340050b49a6c_fld3117smod_slot1_Slot_smod_slot1_set, + Field_dsp340050b49a6c_fld3118smod_slot1_Slot_smod_slot1_set, + Field_dsp340050b49a6c_fld3829smod_slot1_Slot_smod_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_smod_slot0_get_field_fns[] = { + Field_t_Slot_smod_slot0_get, + 0, + 0, + 0, + 0, + Field_s_Slot_smod_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op2_Slot_smod_slot0_get, + Field_r_Slot_smod_slot0_get, + 0, + 0, + Field_sae_Slot_smod_slot0_get, + Field_sal_Slot_smod_slot0_get, + Field_sargt_Slot_smod_slot0_get, + 0, + Field_sas_Slot_smod_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm6_Slot_smod_slot0_get, + Field_imm7_Slot_smod_slot0_get, + 0, + 0, + 0, + 0, + Field_s4_Slot_smod_slot0_get, + 0, + 0, + Field_s8_Slot_smod_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_smod_slot0_get, + 0, + Field_dsp340050b49a6c_fld2032_Slot_smod_slot0_get, + 0, + 0, + Field_dsp340050b49a6c_fld2037_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld2038_Slot_smod_slot0_get, + 0, + Field_dsp340050b49a6c_fld2040_Slot_smod_slot0_get, + 0, + 0, + Field_dsp340050b49a6c_fld2043_Slot_smod_slot0_get, + 0, + Field_dsp340050b49a6c_fld2045_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld2046_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld2047_Slot_smod_slot0_get, + 0, + Field_dsp340050b49a6c_fld2049_Slot_smod_slot0_get, + 0, + 0, + Field_dsp340050b49a6c_fld2052_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld2053_Slot_smod_slot0_get, + 0, + 0, + Field_dsp340050b49a6c_fld2056_Slot_smod_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s17_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3119smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3120smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3121smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3122smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3123smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3125smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3126smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3127smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3128smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3129smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3130smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3131smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3132smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3133smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3134smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3135smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3136smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3137smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3138smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3139smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3140smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3141smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3142smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3143smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3144smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3145smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3146smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3148smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3149smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3150_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3152smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3153smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3155smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3156smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3157smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3158smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3159smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3160smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3161smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3164smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3165smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3166smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3168smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3170smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3171smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3172smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3173smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3174smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3175smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3176smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3177smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3178smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3179smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3180smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3181smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3182smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3184smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3186smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3188smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3832smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3833smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3834_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3836smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3837smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3838smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3841smod_slot0_Slot_smod_slot0_get, + Field_dsp340050b49a6c_fld3842smod_slot0_Slot_smod_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_smod_slot0_set_field_fns[] = { + Field_t_Slot_smod_slot0_set, + 0, + 0, + 0, + 0, + Field_s_Slot_smod_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op2_Slot_smod_slot0_set, + Field_r_Slot_smod_slot0_set, + 0, + 0, + Field_sae_Slot_smod_slot0_set, + Field_sal_Slot_smod_slot0_set, + Field_sargt_Slot_smod_slot0_set, + 0, + Field_sas_Slot_smod_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm6_Slot_smod_slot0_set, + Field_imm7_Slot_smod_slot0_set, + 0, + 0, + 0, + 0, + Field_s4_Slot_smod_slot0_set, + 0, + 0, + Field_s8_Slot_smod_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_smod_slot0_set, + 0, + Field_dsp340050b49a6c_fld2032_Slot_smod_slot0_set, + 0, + 0, + Field_dsp340050b49a6c_fld2037_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld2038_Slot_smod_slot0_set, + 0, + Field_dsp340050b49a6c_fld2040_Slot_smod_slot0_set, + 0, + 0, + Field_dsp340050b49a6c_fld2043_Slot_smod_slot0_set, + 0, + Field_dsp340050b49a6c_fld2045_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld2046_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld2047_Slot_smod_slot0_set, + 0, + Field_dsp340050b49a6c_fld2049_Slot_smod_slot0_set, + 0, + 0, + Field_dsp340050b49a6c_fld2052_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld2053_Slot_smod_slot0_set, + 0, + 0, + Field_dsp340050b49a6c_fld2056_Slot_smod_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s17_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3119smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3120smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3121smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3122smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3123smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3125smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3126smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3127smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3128smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3129smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3130smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3131smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3132smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3133smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3134smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3135smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3136smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3137smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3138smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3139smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3140smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3141smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3142smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3143smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3144smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3145smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3146smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3148smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3149smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3150_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3152smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3153smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3155smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3156smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3157smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3158smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3159smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3160smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3161smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3164smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3165smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3166smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3168smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3170smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3171smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3172smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3173smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3174smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3175smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3176smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3177smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3178smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3179smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3180smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3181smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3182smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3184smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3186smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3188smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3832smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3833smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3834_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3836smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3837smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3838smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3841smod_slot0_Slot_smod_slot0_set, + Field_dsp340050b49a6c_fld3842smod_slot0_Slot_smod_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_llr_slot2_get_field_fns[] = { + Field_t_Slot_llr_slot2_get, + 0, + 0, + 0, + 0, + Field_s_Slot_llr_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r_Slot_llr_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld2030_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld2032_Slot_llr_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2044_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld2045_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld2046_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld2047_Slot_llr_slot2_get, + 0, + Field_dsp340050b49a6c_fld2049_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld2050_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld2051_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld2052_Slot_llr_slot2_get, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2056_Slot_llr_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2025_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld2027_Slot_llr_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s18_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld2074_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3191llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3192llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3193llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3194llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3195llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3196llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3197llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3198llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3199llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3200llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3201llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3202llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3203llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3204llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3205_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3206_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3207llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3208llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3210llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3212_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3213llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3214_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3215llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3216llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3217_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3218llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3220llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3221llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3222llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3224llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3225_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3226llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3228llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3230_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3231llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3232llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3233_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3234llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3235llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3236_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3237llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3238llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3240llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3241llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3242llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3243llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3244llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3245llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3246_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3247llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3843llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3844_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3845llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3847llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3848llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3849llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3850llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3851llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3853llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3855llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3856llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3857llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3859llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3860llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3861llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3862_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3863llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3864llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3865llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3866llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3867llr_slot2_Slot_llr_slot2_get, + Field_dsp340050b49a6c_fld3868_Slot_llr_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_llr_slot2_set_field_fns[] = { + Field_t_Slot_llr_slot2_set, + 0, + 0, + 0, + 0, + Field_s_Slot_llr_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r_Slot_llr_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld2030_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld2032_Slot_llr_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2044_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld2045_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld2046_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld2047_Slot_llr_slot2_set, + 0, + Field_dsp340050b49a6c_fld2049_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld2050_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld2051_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld2052_Slot_llr_slot2_set, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2056_Slot_llr_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2025_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld2027_Slot_llr_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s18_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld2074_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3191llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3192llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3193llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3194llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3195llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3196llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3197llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3198llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3199llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3200llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3201llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3202llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3203llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3204llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3205_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3206_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3207llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3208llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3210llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3212_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3213llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3214_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3215llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3216llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3217_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3218llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3220llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3221llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3222llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3224llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3225_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3226llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3228llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3230_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3231llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3232llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3233_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3234llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3235llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3236_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3237llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3238llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3240llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3241llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3242llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3243llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3244llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3245llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3246_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3247llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3843llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3844_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3845llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3847llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3848llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3849llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3850llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3851llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3853llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3855llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3856llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3857llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3859llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3860llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3861llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3862_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3863llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3864llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3865llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3866llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3867llr_slot2_Slot_llr_slot2_set, + Field_dsp340050b49a6c_fld3868_Slot_llr_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_llr_slot1_get_field_fns[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2047_Slot_llr_slot1_get, + Field_dsp340050b49a6c_fld2048_Slot_llr_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2055_Slot_llr_slot1_get, + Field_dsp340050b49a6c_fld2056_Slot_llr_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2026_Slot_llr_slot1_get, + Field_dsp340050b49a6c_fld2031_Slot_llr_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2028_Slot_llr_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2033_Slot_llr_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s19_Slot_llr_slot1_get, + Field_dsp340050b49a6c_fld2034_Slot_llr_slot1_get, + Field_dsp340050b49a6c_fld3248llr_slot1_Slot_llr_slot1_get, + Field_dsp340050b49a6c_fld3250llr_slot1_Slot_llr_slot1_get, + Field_dsp340050b49a6c_fld3251llr_slot1_Slot_llr_slot1_get, + Field_dsp340050b49a6c_fld3252llr_slot1_Slot_llr_slot1_get, + Field_dsp340050b49a6c_fld3253llr_slot1_Slot_llr_slot1_get, + Field_dsp340050b49a6c_fld3254llr_slot1_Slot_llr_slot1_get, + Field_dsp340050b49a6c_fld3869llr_slot1_Slot_llr_slot1_get, + Field_dsp340050b49a6c_fld3870_Slot_llr_slot1_get, + Field_dsp340050b49a6c_fld3872llr_slot1_Slot_llr_slot1_get, + Field_dsp340050b49a6c_fld3875llr_slot1_Slot_llr_slot1_get, + Field_dsp340050b49a6c_fld3876llr_slot1_Slot_llr_slot1_get, + Field_dsp340050b49a6c_fld3878llr_slot1_Slot_llr_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_llr_slot1_set_field_fns[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2047_Slot_llr_slot1_set, + Field_dsp340050b49a6c_fld2048_Slot_llr_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2055_Slot_llr_slot1_set, + Field_dsp340050b49a6c_fld2056_Slot_llr_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2026_Slot_llr_slot1_set, + Field_dsp340050b49a6c_fld2031_Slot_llr_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2028_Slot_llr_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2033_Slot_llr_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s19_Slot_llr_slot1_set, + Field_dsp340050b49a6c_fld2034_Slot_llr_slot1_set, + Field_dsp340050b49a6c_fld3248llr_slot1_Slot_llr_slot1_set, + Field_dsp340050b49a6c_fld3250llr_slot1_Slot_llr_slot1_set, + Field_dsp340050b49a6c_fld3251llr_slot1_Slot_llr_slot1_set, + Field_dsp340050b49a6c_fld3252llr_slot1_Slot_llr_slot1_set, + Field_dsp340050b49a6c_fld3253llr_slot1_Slot_llr_slot1_set, + Field_dsp340050b49a6c_fld3254llr_slot1_Slot_llr_slot1_set, + Field_dsp340050b49a6c_fld3869llr_slot1_Slot_llr_slot1_set, + Field_dsp340050b49a6c_fld3870_Slot_llr_slot1_set, + Field_dsp340050b49a6c_fld3872llr_slot1_Slot_llr_slot1_set, + Field_dsp340050b49a6c_fld3875llr_slot1_Slot_llr_slot1_set, + Field_dsp340050b49a6c_fld3876llr_slot1_Slot_llr_slot1_set, + Field_dsp340050b49a6c_fld3878llr_slot1_Slot_llr_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_llr_slot0_get_field_fns[] = { + Field_t_Slot_llr_slot0_get, + 0, + 0, + 0, + 0, + Field_s_Slot_llr_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r_Slot_llr_slot0_get, + 0, + 0, + 0, + Field_sal_Slot_llr_slot0_get, + Field_sargt_Slot_llr_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm7_Slot_llr_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_llr_slot0_get, + 0, + Field_dsp340050b49a6c_fld2032_Slot_llr_slot0_get, + 0, + 0, + Field_dsp340050b49a6c_fld2037_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld2038_Slot_llr_slot0_get, + 0, + 0, + Field_dsp340050b49a6c_fld2041_Slot_llr_slot0_get, + 0, + Field_dsp340050b49a6c_fld2043_Slot_llr_slot0_get, + 0, + Field_dsp340050b49a6c_fld2045_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld2046_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld2047_Slot_llr_slot0_get, + 0, + Field_dsp340050b49a6c_fld2049_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld2050_Slot_llr_slot0_get, + 0, + Field_dsp340050b49a6c_fld2052_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld2053_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld2054_Slot_llr_slot0_get, + 0, + Field_dsp340050b49a6c_fld2056_Slot_llr_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s20_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld2071_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3258llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3259llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3260llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3261llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3263llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3264llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3265llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3266llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3267llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3268llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3269llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3270llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3272llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3274llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3275llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3276llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3277llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3278llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3279llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3280llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3281llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3282llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3283llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3284llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3286llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3288llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3289llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3291llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3292llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3293llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3294llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3295llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3296llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3297llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3298llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3299llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3300llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3302llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3303llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3304llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3305llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3306llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3308llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3310llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3311llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3312llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3879llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3881llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3883llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3885llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3887llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3888llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3890llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3892llr_slot0_Slot_llr_slot0_get, + Field_dsp340050b49a6c_fld3893llr_slot0_Slot_llr_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_llr_slot0_set_field_fns[] = { + Field_t_Slot_llr_slot0_set, + 0, + 0, + 0, + 0, + Field_s_Slot_llr_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r_Slot_llr_slot0_set, + 0, + 0, + 0, + Field_sal_Slot_llr_slot0_set, + Field_sargt_Slot_llr_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm7_Slot_llr_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_llr_slot0_set, + 0, + Field_dsp340050b49a6c_fld2032_Slot_llr_slot0_set, + 0, + 0, + Field_dsp340050b49a6c_fld2037_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld2038_Slot_llr_slot0_set, + 0, + 0, + Field_dsp340050b49a6c_fld2041_Slot_llr_slot0_set, + 0, + Field_dsp340050b49a6c_fld2043_Slot_llr_slot0_set, + 0, + Field_dsp340050b49a6c_fld2045_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld2046_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld2047_Slot_llr_slot0_set, + 0, + Field_dsp340050b49a6c_fld2049_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld2050_Slot_llr_slot0_set, + 0, + Field_dsp340050b49a6c_fld2052_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld2053_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld2054_Slot_llr_slot0_set, + 0, + Field_dsp340050b49a6c_fld2056_Slot_llr_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s20_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld2071_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3258llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3259llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3260llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3261llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3263llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3264llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3265llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3266llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3267llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3268llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3269llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3270llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3272llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3274llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3275llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3276llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3277llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3278llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3279llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3280llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3281llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3282llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3283llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3284llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3286llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3288llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3289llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3291llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3292llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3293llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3294llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3295llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3296llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3297llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3298llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3299llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3300llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3302llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3303llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3304llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3305llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3306llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3308llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3310llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3311llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3312llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3879llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3881llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3883llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3885llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3887llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3888llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3890llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3892llr_slot0_Slot_llr_slot0_set, + Field_dsp340050b49a6c_fld3893llr_slot0_Slot_llr_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_dual_slot2_get_field_fns[] = { + Field_t_Slot_dual_slot2_get, + 0, + Field_bbi_Slot_dual_slot2_get, + Field_imm12_Slot_dual_slot2_get, + Field_imm8_Slot_dual_slot2_get, + Field_s_Slot_dual_slot2_get, + Field_imm12b_Slot_dual_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op2_Slot_dual_slot2_get, + Field_r_Slot_dual_slot2_get, + 0, + 0, + Field_sae_Slot_dual_slot2_get, + Field_sal_Slot_dual_slot2_get, + Field_sargt_Slot_dual_slot2_get, + 0, + Field_sas_Slot_dual_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm6_Slot_dual_slot2_get, + Field_imm7_Slot_dual_slot2_get, + 0, + 0, + 0, + 0, + Field_s4_Slot_dual_slot2_get, + 0, + 0, + Field_s8_Slot_dual_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld2030_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld2032_Slot_dual_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2044_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld2045_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld2046_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld2047_Slot_dual_slot2_get, + 0, + Field_dsp340050b49a6c_fld2049_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld2050_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld2051_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld2052_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld2053_Slot_dual_slot2_get, + 0, + 0, + Field_dsp340050b49a6c_fld2056_Slot_dual_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2025_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld2027_Slot_dual_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s21_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3313dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3314_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3315dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3316dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3317dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3318_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3319dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3320dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3321dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3322dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3323dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3324dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3325dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3326dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3327dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3328dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3329dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3330dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3331dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3332dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3333dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3334dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3335dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3336dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3337dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3339dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3340dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3341dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3342dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3345dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3347dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3348dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3349dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3350dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3353dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3354dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3356dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3358dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3360dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3361dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3362dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3363dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3364_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3365dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3366dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3367dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3368dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3369dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3370dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3371dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3372dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3373dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3374dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3375dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3376dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3377dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3378dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3379dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3380dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3381dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3382dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3384dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3385dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3386dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3387dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3388dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3390dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3392dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3394dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3396dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3397dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3399dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3401dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3403dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3404dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3406dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3407_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3408dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3410_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3411dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3412dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3413dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3414dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3415dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3416dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3417dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3418dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3419dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3420dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3421dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3422dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3423dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3424dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3425dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3426dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3427dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3428dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3429dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3430dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3431dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3432dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3433dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3434dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3435dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3436dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3437dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3438dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3439dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3440dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3441dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3442dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3443dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3444dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3445dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3446dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3448dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3450dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3451dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3453dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3454dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3456dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3457dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3458dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3459dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3460dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3461dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3462dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3464dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3465dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3466_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3467dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3468dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3469dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3470dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3471dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3472dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3473dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3474dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3475dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3477dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3478dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3479dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3480dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3481dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3482dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3484dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3894dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3895dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3896dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3897dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3898dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3899dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3900_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3901dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3903dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3904dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3905dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3906dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3907dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3908dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3909dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3910dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3913dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3914dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3916dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3917dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3918dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3919dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3920dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3921dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3922dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3923dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3924dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3925dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3927dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3928dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3929dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3930dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3931dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3933dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3934dual_slot2_Slot_dual_slot2_get, + Field_dsp340050b49a6c_fld3935dual_slot2_Slot_dual_slot2_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_dual_slot2_set_field_fns[] = { + Field_t_Slot_dual_slot2_set, + 0, + Field_bbi_Slot_dual_slot2_set, + Field_imm12_Slot_dual_slot2_set, + Field_imm8_Slot_dual_slot2_set, + Field_s_Slot_dual_slot2_set, + Field_imm12b_Slot_dual_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op2_Slot_dual_slot2_set, + Field_r_Slot_dual_slot2_set, + 0, + 0, + Field_sae_Slot_dual_slot2_set, + Field_sal_Slot_dual_slot2_set, + Field_sargt_Slot_dual_slot2_set, + 0, + Field_sas_Slot_dual_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm6_Slot_dual_slot2_set, + Field_imm7_Slot_dual_slot2_set, + 0, + 0, + 0, + 0, + Field_s4_Slot_dual_slot2_set, + 0, + 0, + Field_s8_Slot_dual_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld2030_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld2032_Slot_dual_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2044_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld2045_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld2046_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld2047_Slot_dual_slot2_set, + 0, + Field_dsp340050b49a6c_fld2049_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld2050_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld2051_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld2052_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld2053_Slot_dual_slot2_set, + 0, + 0, + Field_dsp340050b49a6c_fld2056_Slot_dual_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_dsp340050b49a6c_fld2025_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld2027_Slot_dual_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s21_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3313dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3314_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3315dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3316dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3317dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3318_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3319dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3320dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3321dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3322dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3323dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3324dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3325dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3326dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3327dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3328dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3329dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3330dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3331dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3332dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3333dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3334dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3335dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3336dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3337dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3339dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3340dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3341dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3342dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3345dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3347dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3348dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3349dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3350dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3353dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3354dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3356dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3358dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3360dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3361dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3362dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3363dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3364_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3365dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3366dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3367dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3368dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3369dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3370dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3371dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3372dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3373dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3374dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3375dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3376dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3377dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3378dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3379dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3380dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3381dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3382dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3384dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3385dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3386dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3387dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3388dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3390dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3392dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3394dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3396dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3397dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3399dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3401dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3403dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3404dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3406dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3407_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3408dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3410_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3411dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3412dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3413dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3414dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3415dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3416dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3417dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3418dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3419dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3420dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3421dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3422dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3423dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3424dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3425dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3426dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3427dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3428dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3429dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3430dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3431dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3432dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3433dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3434dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3435dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3436dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3437dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3438dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3439dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3440dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3441dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3442dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3443dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3444dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3445dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3446dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3448dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3450dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3451dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3453dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3454dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3456dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3457dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3458dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3459dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3460dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3461dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3462dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3464dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3465dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3466_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3467dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3468dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3469dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3470dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3471dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3472dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3473dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3474dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3475dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3477dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3478dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3479dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3480dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3481dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3482dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3484dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3894dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3895dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3896dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3897dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3898dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3899dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3900_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3901dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3903dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3904dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3905dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3906dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3907dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3908dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3909dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3910dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3913dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3914dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3916dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3917dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3918dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3919dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3920dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3921dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3922dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3923dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3924dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3925dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3927dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3928dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3929dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3930dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3931dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3933dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3934dual_slot2_Slot_dual_slot2_set, + Field_dsp340050b49a6c_fld3935dual_slot2_Slot_dual_slot2_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_dual_slot1_get_field_fns[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s22_Slot_dual_slot1_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_dual_slot1_set_field_fns[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s22_Slot_dual_slot1_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_dual_slot0_get_field_fns[] = { + Field_t_Slot_dual_slot0_get, + 0, + Field_bbi_Slot_dual_slot0_get, + Field_imm12_Slot_dual_slot0_get, + Field_imm8_Slot_dual_slot0_get, + Field_s_Slot_dual_slot0_get, + Field_imm12b_Slot_dual_slot0_get, + Field_imm16_Slot_dual_slot0_get, + 0, + 0, + 0, + 0, + 0, + Field_op2_Slot_dual_slot0_get, + Field_r_Slot_dual_slot0_get, + 0, + 0, + Field_sae_Slot_dual_slot0_get, + Field_sal_Slot_dual_slot0_get, + Field_sargt_Slot_dual_slot0_get, + 0, + Field_sas_Slot_dual_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm6_Slot_dual_slot0_get, + Field_imm7_Slot_dual_slot0_get, + 0, + 0, + 0, + 0, + Field_s4_Slot_dual_slot0_get, + 0, + 0, + Field_s8_Slot_dual_slot0_get, + 0, + 0, + 0, + Field_fimm8_Slot_dual_slot0_get, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2030_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2032_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2035_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2036_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2037_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2038_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2039_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2040_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2041_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2042_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2043_Slot_dual_slot0_get, + 0, + Field_dsp340050b49a6c_fld2045_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2046_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2047_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2048_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2049_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2050_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2051_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2052_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2053_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2054_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2055_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2056_Slot_dual_slot0_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s23_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2057_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2060_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2066_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2072_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld2079_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3487dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3488dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3489dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3490dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3491dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3492dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3493dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3494dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3496dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3497dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3498dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3499dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3500dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3502dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3504dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3505dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3506dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3507dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3508dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3509dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3510dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3511dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3512dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3513dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3514dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3515dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3516dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3517dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3518dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3519dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3520dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3522dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3523dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3524dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3527dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3529dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3530dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3531_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3532dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3533dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3535dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3536dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3537dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3538dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3539dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3541dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3542dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3543dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3544dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3545dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3546dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3547dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3548dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3549dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3550dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3551dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3552_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3553dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3554dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3555dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3556dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3557dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3558dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3559dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3560dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3562dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3563dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3564dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3565dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3566dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3567dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3568dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3569dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3570dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3571dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3572dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3573dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3574dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3575dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3576dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3577dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3578dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3579dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3580dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3581dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3582dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3583dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3584_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3585dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3587dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3588dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3589dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3590dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3591dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3592dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3593dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3594dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3595dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3596dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3597dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3598dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3599dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3600dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3601dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3602_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3603dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3604dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3606dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3607dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3608dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3609dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3610_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3611dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3612dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3613dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3614dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3615dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3616dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3618dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3619_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3620dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3621dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3622dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3623dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3624dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3625dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3626dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3936dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3937dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3938dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3939dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3940dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3941dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3943dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3945dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3946dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3947dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3949dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3950dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3951dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3952dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3954dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3957dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3958dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3959dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3960dual_slot0_Slot_dual_slot0_get, + Field_dsp340050b49a6c_fld3961dual_slot0_Slot_dual_slot0_get, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_dual_slot0_set_field_fns[] = { + Field_t_Slot_dual_slot0_set, + 0, + Field_bbi_Slot_dual_slot0_set, + Field_imm12_Slot_dual_slot0_set, + Field_imm8_Slot_dual_slot0_set, + Field_s_Slot_dual_slot0_set, + Field_imm12b_Slot_dual_slot0_set, + Field_imm16_Slot_dual_slot0_set, + 0, + 0, + 0, + 0, + 0, + Field_op2_Slot_dual_slot0_set, + Field_r_Slot_dual_slot0_set, + 0, + 0, + Field_sae_Slot_dual_slot0_set, + Field_sal_Slot_dual_slot0_set, + Field_sargt_Slot_dual_slot0_set, + 0, + Field_sas_Slot_dual_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_imm6_Slot_dual_slot0_set, + Field_imm7_Slot_dual_slot0_set, + 0, + 0, + 0, + 0, + Field_s4_Slot_dual_slot0_set, + 0, + 0, + Field_s8_Slot_dual_slot0_set, + 0, + 0, + 0, + Field_fimm8_Slot_dual_slot0_set, + 0, + 0, + Field_dsp340050b49a6c_fld2029_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2030_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2032_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2035_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2036_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2037_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2038_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2039_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2040_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2041_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2042_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2043_Slot_dual_slot0_set, + 0, + Field_dsp340050b49a6c_fld2045_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2046_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2047_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2048_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2049_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2050_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2051_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2052_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2053_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2054_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2055_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2056_Slot_dual_slot0_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_op0_s23_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2057_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2060_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2066_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2072_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld2079_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3487dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3488dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3489dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3490dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3491dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3492dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3493dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3494dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3496dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3497dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3498dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3499dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3500dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3502dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3504dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3505dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3506dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3507dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3508dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3509dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3510dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3511dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3512dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3513dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3514dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3515dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3516dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3517dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3518dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3519dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3520dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3522dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3523dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3524dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3527dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3529dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3530dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3531_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3532dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3533dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3535dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3536dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3537dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3538dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3539dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3541dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3542dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3543dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3544dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3545dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3546dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3547dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3548dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3549dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3550dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3551dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3552_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3553dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3554dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3555dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3556dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3557dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3558dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3559dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3560dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3562dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3563dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3564dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3565dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3566dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3567dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3568dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3569dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3570dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3571dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3572dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3573dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3574dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3575dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3576dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3577dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3578dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3579dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3580dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3581dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3582dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3583dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3584_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3585dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3587dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3588dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3589dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3590dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3591dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3592dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3593dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3594dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3595dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3596dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3597dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3598dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3599dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3600dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3601dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3602_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3603dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3604dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3606dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3607dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3608dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3609dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3610_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3611dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3612dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3613dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3614dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3615dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3616dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3618dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3619_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3620dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3621dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3622dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3623dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3624dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3625dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3626dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3936dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3937dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3938dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3939dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3940dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3941dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3943dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3945dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3946dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3947dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3949dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3950dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3951dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3952dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3954dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3957dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3958dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3959dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3960dual_slot0_Slot_dual_slot0_set, + Field_dsp340050b49a6c_fld3961dual_slot0_Slot_dual_slot0_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_slot_internal slots[] = { + { "Inst", "x24", 0, + Slot_x24_Format_inst_0_get, Slot_x24_Format_inst_0_set, + Slot_inst_get_field_fns, Slot_inst_set_field_fns, + Slot_inst_decode, "nop" }, + { "Inst16a", "x16a", 0, + Slot_x16a_Format_inst16a_0_get, Slot_x16a_Format_inst16a_0_set, + Slot_inst16a_get_field_fns, Slot_inst16a_set_field_fns, + Slot_inst16a_decode, "" }, + { "Inst16b", "x16b", 0, + Slot_x16b_Format_inst16b_0_get, Slot_x16b_Format_inst16b_0_set, + Slot_inst16b_get_field_fns, Slot_inst16b_set_field_fns, + Slot_inst16b_decode, "nop.n" }, + { "GP_slot2", "GP", 2, + Slot_gp_Format_gp_slot2_43_get, Slot_gp_Format_gp_slot2_43_set, + Slot_gp_slot2_get_field_fns, Slot_gp_slot2_set_field_fns, + Slot_gp_slot2_decode, "nop" }, + { "GP_slot1", "GP", 1, + Slot_gp_Format_gp_slot1_26_get, Slot_gp_Format_gp_slot1_26_set, + Slot_gp_slot1_get_field_fns, Slot_gp_slot1_set_field_fns, + Slot_gp_slot1_decode, "nop" }, + { "GP_slot0", "GP", 0, + Slot_gp_Format_gp_slot0_7_get, Slot_gp_Format_gp_slot0_7_set, + Slot_gp_slot0_get_field_fns, Slot_gp_slot0_set_field_fns, + Slot_gp_slot0_decode, "nop" }, + { "DOT_slot2", "DOT", 2, + Slot_dot_Format_dot_slot2_44_get, Slot_dot_Format_dot_slot2_44_set, + Slot_dot_slot2_get_field_fns, Slot_dot_slot2_set_field_fns, + Slot_dot_slot2_decode, "nop" }, + { "DOT_slot1", "DOT", 1, + Slot_dot_Format_dot_slot1_24_get, Slot_dot_Format_dot_slot1_24_set, + Slot_dot_slot1_get_field_fns, Slot_dot_slot1_set_field_fns, + Slot_dot_slot1_decode, "nop" }, + { "DOT_slot0", "DOT", 0, + Slot_dot_Format_dot_slot0_7_get, Slot_dot_Format_dot_slot0_7_set, + Slot_dot_slot0_get_field_fns, Slot_dot_slot0_set_field_fns, + Slot_dot_slot0_decode, "nop" }, + { "PQ_slot2", "PQ", 2, + Slot_pq_Format_pq_slot2_40_get, Slot_pq_Format_pq_slot2_40_set, + Slot_pq_slot2_get_field_fns, Slot_pq_slot2_set_field_fns, + Slot_pq_slot2_decode, "nop" }, + { "PQ_slot1", "PQ", 1, + Slot_pq_Format_pq_slot1_26_get, Slot_pq_Format_pq_slot1_26_set, + Slot_pq_slot1_get_field_fns, Slot_pq_slot1_set_field_fns, + Slot_pq_slot1_decode, "nop" }, + { "PQ_slot0", "PQ", 0, + Slot_pq_Format_pq_slot0_7_get, Slot_pq_Format_pq_slot0_7_set, + Slot_pq_slot0_get_field_fns, Slot_pq_slot0_set_field_fns, + Slot_pq_slot0_decode, "nop" }, + { "ACC2_slot2", "ACC2", 2, + Slot_acc2_Format_acc2_slot2_47_get, Slot_acc2_Format_acc2_slot2_47_set, + Slot_acc2_slot2_get_field_fns, Slot_acc2_slot2_set_field_fns, + Slot_acc2_slot2_decode, "nop" }, + { "ACC2_slot1", "ACC2", 1, + Slot_acc2_Format_acc2_slot1_23_get, Slot_acc2_Format_acc2_slot1_23_set, + Slot_acc2_slot1_get_field_fns, Slot_acc2_slot1_set_field_fns, + Slot_acc2_slot1_decode, "nop" }, + { "ACC2_slot0", "ACC2", 0, + Slot_acc2_Format_acc2_slot0_7_get, Slot_acc2_Format_acc2_slot0_7_set, + Slot_acc2_slot0_get_field_fns, Slot_acc2_slot0_set_field_fns, + Slot_acc2_slot0_decode, "nop" }, + { "SMOD_slot2", "SMOD", 2, + Slot_smod_Format_smod_slot2_42_get, Slot_smod_Format_smod_slot2_42_set, + Slot_smod_slot2_get_field_fns, Slot_smod_slot2_set_field_fns, + Slot_smod_slot2_decode, "nop" }, + { "SMOD_slot1", "SMOD", 1, + Slot_smod_Format_smod_slot1_26_get, Slot_smod_Format_smod_slot1_26_set, + Slot_smod_slot1_get_field_fns, Slot_smod_slot1_set_field_fns, + Slot_smod_slot1_decode, "nop" }, + { "SMOD_slot0", "SMOD", 0, + Slot_smod_Format_smod_slot0_7_get, Slot_smod_Format_smod_slot0_7_set, + Slot_smod_slot0_get_field_fns, Slot_smod_slot0_set_field_fns, + Slot_smod_slot0_decode, "nop" }, + { "LLR_slot2", "LLR", 2, + Slot_llr_Format_llr_slot2_44_get, Slot_llr_Format_llr_slot2_44_set, + Slot_llr_slot2_get_field_fns, Slot_llr_slot2_set_field_fns, + Slot_llr_slot2_decode, "nop" }, + { "LLR_slot1", "LLR", 1, + Slot_llr_Format_llr_slot1_24_get, Slot_llr_Format_llr_slot1_24_set, + Slot_llr_slot1_get_field_fns, Slot_llr_slot1_set_field_fns, + Slot_llr_slot1_decode, "nop" }, + { "LLR_slot0", "LLR", 0, + Slot_llr_Format_llr_slot0_7_get, Slot_llr_Format_llr_slot0_7_set, + Slot_llr_slot0_get_field_fns, Slot_llr_slot0_set_field_fns, + Slot_llr_slot0_decode, "nop" }, + { "DUAL_slot2", "DUAL", 2, + Slot_dual_Format_dual_slot2_31_get, Slot_dual_Format_dual_slot2_31_set, + Slot_dual_slot2_get_field_fns, Slot_dual_slot2_set_field_fns, + Slot_dual_slot2_decode, "nop" }, + { "DUAL_slot1", "DUAL", 1, + Slot_dual_Format_dual_slot1_30_get, Slot_dual_Format_dual_slot1_30_set, + Slot_dual_slot1_get_field_fns, Slot_dual_slot1_set_field_fns, + Slot_dual_slot1_decode, "nop" }, + { "DUAL_slot0", "DUAL", 0, + Slot_dual_Format_dual_slot0_7_get, Slot_dual_Format_dual_slot0_7_set, + Slot_dual_slot0_get_field_fns, Slot_dual_slot0_set_field_fns, + Slot_dual_slot0_decode, "nop" } +}; + + +/* Instruction formats. */ + +static void +Format_x24_encode (xtensa_insnbuf insn) +{ + insn[0] = 0; + insn[1] = 0; +} + +static void +Format_x16a_encode (xtensa_insnbuf insn) +{ + insn[0] = 0x8; + insn[1] = 0; +} + +static void +Format_x16b_encode (xtensa_insnbuf insn) +{ + insn[0] = 0xc; + insn[1] = 0; +} + +static void +Format_GP_encode (xtensa_insnbuf insn) +{ + insn[0] = 0xf; + insn[1] = 0; +} + +static void +Format_DOT_encode (xtensa_insnbuf insn) +{ + insn[0] = 0x1f; + insn[1] = 0; +} + +static void +Format_PQ_encode (xtensa_insnbuf insn) +{ + insn[0] = 0x2f; + insn[1] = 0; +} + +static void +Format_ACC2_encode (xtensa_insnbuf insn) +{ + insn[0] = 0x3f; + insn[1] = 0; +} + +static void +Format_SMOD_encode (xtensa_insnbuf insn) +{ + insn[0] = 0x4f; + insn[1] = 0; +} + +static void +Format_LLR_encode (xtensa_insnbuf insn) +{ + insn[0] = 0x5f; + insn[1] = 0; +} + +static void +Format_DUAL_encode (xtensa_insnbuf insn) +{ + insn[0] = 0x6f; + insn[1] = 0; +} + +static int Format_x24_slots[] = { 0 }; + +static int Format_x16a_slots[] = { 1 }; + +static int Format_x16b_slots[] = { 2 }; + +static int Format_GP_slots[] = { 5, 4, 3 }; + +static int Format_DOT_slots[] = { 8, 7, 6 }; + +static int Format_PQ_slots[] = { 11, 10, 9 }; + +static int Format_ACC2_slots[] = { 14, 13, 12 }; + +static int Format_SMOD_slots[] = { 17, 16, 15 }; + +static int Format_LLR_slots[] = { 20, 19, 18 }; + +static int Format_DUAL_slots[] = { 23, 22, 21 }; + +static xtensa_format_internal formats[] = { + { "x24", 3, Format_x24_encode, 1, Format_x24_slots }, + { "x16a", 2, Format_x16a_encode, 1, Format_x16a_slots }, + { "x16b", 2, Format_x16b_encode, 1, Format_x16b_slots }, + { "GP", 8, Format_GP_encode, 3, Format_GP_slots }, + { "DOT", 8, Format_DOT_encode, 3, Format_DOT_slots }, + { "PQ", 8, Format_PQ_encode, 3, Format_PQ_slots }, + { "ACC2", 8, Format_ACC2_encode, 3, Format_ACC2_slots }, + { "SMOD", 8, Format_SMOD_encode, 3, Format_SMOD_slots }, + { "LLR", 8, Format_LLR_encode, 3, Format_LLR_slots }, + { "DUAL", 8, Format_DUAL_encode, 3, Format_DUAL_slots } +}; + + +static int +format_decoder (const xtensa_insnbuf insn) +{ + if ((insn[0] & 0x8) == 0 && (insn[1] & 0) == 0) + return 0; /* x24 */ + if ((insn[0] & 0xc) == 0x8 && (insn[1] & 0) == 0) + return 1; /* x16a */ + if ((insn[0] & 0xe) == 0xc && (insn[1] & 0) == 0) + return 2; /* x16b */ + if ((insn[0] & 0x7f) == 0xf && (insn[1] & 0) == 0) + return 3; /* GP */ + if ((insn[0] & 0x7f) == 0x1f && (insn[1] & 0) == 0) + return 4; /* DOT */ + if ((insn[0] & 0x7f) == 0x2f && (insn[1] & 0) == 0) + return 5; /* PQ */ + if ((insn[0] & 0x7f) == 0x3f && (insn[1] & 0) == 0) + return 6; /* ACC2 */ + if ((insn[0] & 0x7f) == 0x4f && (insn[1] & 0) == 0) + return 7; /* SMOD */ + if ((insn[0] & 0x7f) == 0x5f && (insn[1] & 0) == 0) + return 8; /* LLR */ + if ((insn[0] & 0x7f) == 0x6f && (insn[1] & 0) == 0) + return 9; /* DUAL */ + return -1; +} + +static int length_table[16] = { + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + 8 +}; + +static int +length_decoder (const unsigned char *insn) +{ + int op0 = insn[0] & 0xf; + return length_table[op0]; +} + + +/* Top-level ISA structure. */ + +xtensa_isa_internal xtensa_modules = { + 0 /* little-endian */, + 8 /* insn_size */, 0, + 10, formats, format_decoder, length_decoder, + 24, slots, + 1733 /* num_fields */, + 1828, operands, + 747, iclasses, + 839, opcodes, 0, + 10, regfiles, + NUM_STATES, states, 0, + NUM_SYSREGS, sysregs, 0, + { MAX_SPECIAL_REG, MAX_USER_REG }, { 0, 0 }, + 95, interfaces, 0, + 0, funcUnits, 0 +}; diff --git a/target/xtensa/core-fsf.c b/target/xtensa/core-fsf.c index 1221a296fa9a9c5f535941be5ff57d9822f2bd99..3327c50b4fb2d1a93e3422b43743e1ad0766dda2 100644 --- a/target/xtensa/core-fsf.c +++ b/target/xtensa/core-fsf.c @@ -34,7 +34,7 @@ #include "overlay_tool.h" #define xtensa_modules xtensa_modules_fsf -#include "core-fsf/xtensa-modules.inc.c" +#include "core-fsf/xtensa-modules.c.inc" static XtensaConfig fsf __attribute__((unused)) = { .name = "fsf", diff --git a/target/xtensa/core-fsf/xtensa-modules.inc.c b/target/xtensa/core-fsf/xtensa-modules.c.inc similarity index 100% rename from target/xtensa/core-fsf/xtensa-modules.inc.c rename to target/xtensa/core-fsf/xtensa-modules.c.inc diff --git a/target/xtensa/core-sample_controller.c b/target/xtensa/core-sample_controller.c index a1d220bb9a71c62620083b441187320ba84e3586..fd5de5576bab8890bd9e5d64bd6b97fb08e4371f 100644 --- a/target/xtensa/core-sample_controller.c +++ b/target/xtensa/core-sample_controller.c @@ -34,13 +34,13 @@ #include "overlay_tool.h" #define xtensa_modules xtensa_modules_sample_controller -#include "core-sample_controller/xtensa-modules.inc.c" +#include "core-sample_controller/xtensa-modules.c.inc" static XtensaConfig sample_controller __attribute__((unused)) = { .name = "sample_controller", .gdb_regmap = { .reg = { -#include "core-sample_controller/gdb-config.inc.c" +#include "core-sample_controller/gdb-config.c.inc" } }, .isa_internal = &xtensa_modules, diff --git a/target/xtensa/core-sample_controller/gdb-config.inc.c b/target/xtensa/core-sample_controller/gdb-config.c.inc similarity index 100% rename from target/xtensa/core-sample_controller/gdb-config.inc.c rename to target/xtensa/core-sample_controller/gdb-config.c.inc diff --git a/target/xtensa/core-sample_controller/xtensa-modules.inc.c b/target/xtensa/core-sample_controller/xtensa-modules.c.inc similarity index 100% rename from target/xtensa/core-sample_controller/xtensa-modules.inc.c rename to target/xtensa/core-sample_controller/xtensa-modules.c.inc diff --git a/target/xtensa/core-test_kc705_be.c b/target/xtensa/core-test_kc705_be.c index ab73c3885f35973e2403ef5e0ca07fad77c4083a..294c16f2f441c04d86c49e5ada79334a11837c7c 100644 --- a/target/xtensa/core-test_kc705_be.c +++ b/target/xtensa/core-test_kc705_be.c @@ -34,13 +34,13 @@ #include "overlay_tool.h" #define xtensa_modules xtensa_modules_test_kc705_be -#include "core-test_kc705_be/xtensa-modules.inc.c" +#include "core-test_kc705_be/xtensa-modules.c.inc" static XtensaConfig test_kc705_be __attribute__((unused)) = { .name = "test_kc705_be", .gdb_regmap = { .reg = { -#include "core-test_kc705_be/gdb-config.inc.c" +#include "core-test_kc705_be/gdb-config.c.inc" } }, .isa_internal = &xtensa_modules, diff --git a/target/xtensa/core-test_kc705_be/gdb-config.inc.c b/target/xtensa/core-test_kc705_be/gdb-config.c.inc similarity index 100% rename from target/xtensa/core-test_kc705_be/gdb-config.inc.c rename to target/xtensa/core-test_kc705_be/gdb-config.c.inc diff --git a/target/xtensa/core-test_kc705_be/xtensa-modules.inc.c b/target/xtensa/core-test_kc705_be/xtensa-modules.c.inc similarity index 100% rename from target/xtensa/core-test_kc705_be/xtensa-modules.inc.c rename to target/xtensa/core-test_kc705_be/xtensa-modules.c.inc diff --git a/target/xtensa/core-test_mmuhifi_c3.c b/target/xtensa/core-test_mmuhifi_c3.c index 089ed7da5d37084837dcf157fde6f226467e3d87..123c630b0da7dd25607b8c7f078f1ac886df36ba 100644 --- a/target/xtensa/core-test_mmuhifi_c3.c +++ b/target/xtensa/core-test_mmuhifi_c3.c @@ -35,13 +35,13 @@ #include "overlay_tool.h" #define xtensa_modules xtensa_modules_test_mmuhifi_c3 -#include "core-test_mmuhifi_c3/xtensa-modules.inc.c" +#include "core-test_mmuhifi_c3/xtensa-modules.c.inc" static XtensaConfig test_mmuhifi_c3 __attribute__((unused)) = { .name = "test_mmuhifi_c3", .gdb_regmap = { .reg = { -#include "core-test_mmuhifi_c3/gdb-config.inc.c" +#include "core-test_mmuhifi_c3/gdb-config.c.inc" } }, .isa_internal = &xtensa_modules, diff --git a/target/xtensa/core-test_mmuhifi_c3/gdb-config.inc.c b/target/xtensa/core-test_mmuhifi_c3/gdb-config.c.inc similarity index 100% rename from target/xtensa/core-test_mmuhifi_c3/gdb-config.inc.c rename to target/xtensa/core-test_mmuhifi_c3/gdb-config.c.inc diff --git a/target/xtensa/core-test_mmuhifi_c3/xtensa-modules.inc.c b/target/xtensa/core-test_mmuhifi_c3/xtensa-modules.c.inc similarity index 100% rename from target/xtensa/core-test_mmuhifi_c3/xtensa-modules.inc.c rename to target/xtensa/core-test_mmuhifi_c3/xtensa-modules.c.inc diff --git a/target/xtensa/cpu-qom.h b/target/xtensa/cpu-qom.h index 3ea93ce1f937a05d4233be80fd404e842c14d6af..41d985967342e1911b1a89c1621b456effb0f338 100644 --- a/target/xtensa/cpu-qom.h +++ b/target/xtensa/cpu-qom.h @@ -30,15 +30,12 @@ #define QEMU_XTENSA_CPU_QOM_H #include "hw/core/cpu.h" +#include "qom/object.h" #define TYPE_XTENSA_CPU "xtensa-cpu" -#define XTENSA_CPU_CLASS(class) \ - OBJECT_CLASS_CHECK(XtensaCPUClass, (class), TYPE_XTENSA_CPU) -#define XTENSA_CPU(obj) \ - OBJECT_CHECK(XtensaCPU, (obj), TYPE_XTENSA_CPU) -#define XTENSA_CPU_GET_CLASS(obj) \ - OBJECT_GET_CLASS(XtensaCPUClass, (obj), TYPE_XTENSA_CPU) +OBJECT_DECLARE_TYPE(XtensaCPU, XtensaCPUClass, + XTENSA_CPU) typedef struct XtensaConfig XtensaConfig; @@ -50,7 +47,7 @@ typedef struct XtensaConfig XtensaConfig; * * An Xtensa CPU model. */ -typedef struct XtensaCPUClass { +struct XtensaCPUClass { /*< private >*/ CPUClass parent_class; /*< public >*/ @@ -59,8 +56,7 @@ typedef struct XtensaCPUClass { DeviceReset parent_reset; const XtensaConfig *config; -} XtensaCPUClass; +}; -typedef struct XtensaCPU XtensaCPU; #endif diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c index 82c2ee0679f8f04cab54eb5971c44022887016a9..88a32268a18b952a4befa678b2581a09a272f47d 100644 --- a/target/xtensa/cpu.c +++ b/target/xtensa/cpu.c @@ -31,6 +31,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "cpu.h" +#include "fpu/softfloat.h" #include "qemu/module.h" #include "migration/vmstate.h" @@ -73,6 +74,8 @@ static void xtensa_cpu_reset(DeviceState *dev) XtensaCPU *cpu = XTENSA_CPU(s); XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(cpu); CPUXtensaState *env = &cpu->env; + bool dfpu = xtensa_option_enabled(env->config, + XTENSA_OPTION_DFP_COPROCESSOR); xcc->parent_reset(dev); @@ -90,6 +93,7 @@ static void xtensa_cpu_reset(DeviceState *dev) !xtensa_abi_call0()) { env->sregs[PS] |= PS_WOE; } + env->sregs[CPENABLE] = 0xff; #endif env->sregs[VECBASE] = env->config->vecbase; env->sregs[IBREAKENABLE] = 0; @@ -104,6 +108,8 @@ static void xtensa_cpu_reset(DeviceState *dev) reset_mmu(env); s->halted = env->runstall; #endif + set_no_signaling_nans(!dfpu, &env->fp_status); + set_use_first_nan(!dfpu, &env->fp_status); } static ObjectClass *xtensa_cpu_class_by_name(const char *cpu_model) diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h index 7a46dccbe11b05e9565192b9e24271f0d7b0f24b..3bd4f691c1a0a60e9e7e2900c31ea7e6ee767995 100644 --- a/target/xtensa/cpu.h +++ b/target/xtensa/cpu.h @@ -52,6 +52,8 @@ enum { XTENSA_OPTION_COPROCESSOR, XTENSA_OPTION_BOOLEAN, XTENSA_OPTION_FP_COPROCESSOR, + XTENSA_OPTION_DFP_COPROCESSOR, + XTENSA_OPTION_DFPU_SINGLE_ONLY, XTENSA_OPTION_MP_SYNCHRO, XTENSA_OPTION_CONDITIONAL_STORE, XTENSA_OPTION_ATOMCTL, @@ -359,14 +361,12 @@ typedef struct opcode_arg { uint32_t raw_imm; void *in; void *out; + uint32_t num_bits; } OpcodeArg; typedef struct DisasContext DisasContext; typedef void (*XtensaOpcodeOp)(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]); -typedef bool (*XtensaOpcodeBoolTest)(DisasContext *dc, - const OpcodeArg arg[], - const uint32_t par[]); typedef uint32_t (*XtensaOpcodeUintTest)(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]); @@ -408,7 +408,7 @@ enum { typedef struct XtensaOpcodeOps { const void *name; XtensaOpcodeOp translate; - XtensaOpcodeBoolTest test_ill; + XtensaOpcodeUintTest test_exceptions; XtensaOpcodeUintTest test_overflow; const uint32_t *par; uint32_t op_flags; @@ -422,6 +422,7 @@ typedef struct XtensaOpcodeTranslators { extern const XtensaOpcodeTranslators xtensa_core_opcodes; extern const XtensaOpcodeTranslators xtensa_fpu2000_opcodes; +extern const XtensaOpcodeTranslators xtensa_fpu_opcodes; struct XtensaConfig { const char *name; @@ -436,6 +437,7 @@ struct XtensaConfig { uint32_t exception_vector[EXC_MAX]; unsigned ninterrupt; unsigned nlevel; + unsigned nmi_level; uint32_t interrupt_vector[MAX_NLEVEL + MAX_NNMI + 1]; uint32_t level_mask[MAX_NLEVEL + MAX_NNMI + 1]; uint32_t inttype_mask[INTTYPE_MAX]; @@ -464,6 +466,7 @@ struct XtensaConfig { XtensaMemory sysrom; XtensaMemory sysram; + unsigned hw_version; uint32_t configid[2]; void *isa_internal; @@ -482,6 +485,8 @@ struct XtensaConfig { unsigned n_mpu_fg_segments; unsigned n_mpu_bg_segments; const xtensa_mpu_entry *mpu_bg; + + bool use_first_nan; }; typedef struct XtensaConfigList { @@ -599,7 +604,7 @@ void xtensa_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, void xtensa_collect_sr_names(const XtensaConfig *config); void xtensa_translate_init(void); -void **xtensa_get_regfile_by_name(const char *name); +void **xtensa_get_regfile_by_name(const char *name, int entries, int bits); void xtensa_breakpoint_handler(CPUState *cs); void xtensa_register_core(XtensaConfigList *node); void xtensa_sim_open_console(Chardev *chr); diff --git a/target/xtensa/exc_helper.c b/target/xtensa/exc_helper.c index 601341d13aa07eef64b0ac183cc2e3998a4fbbff..2f032bc053334b8603d2b5ce87b4a3707d49c6b2 100644 --- a/target/xtensa/exc_helper.c +++ b/target/xtensa/exc_helper.c @@ -128,15 +128,19 @@ void HELPER(check_interrupts)(CPUXtensaState *env) void HELPER(intset)(CPUXtensaState *env, uint32_t v) { - atomic_or(&env->sregs[INTSET], + qatomic_or(&env->sregs[INTSET], v & env->config->inttype_mask[INTTYPE_SOFTWARE]); } +static void intclear(CPUXtensaState *env, uint32_t v) +{ + qatomic_and(&env->sregs[INTSET], ~v); +} + void HELPER(intclear)(CPUXtensaState *env, uint32_t v) { - atomic_and(&env->sregs[INTSET], - ~(v & (env->config->inttype_mask[INTTYPE_SOFTWARE] | - env->config->inttype_mask[INTTYPE_EDGE]))); + intclear(env, v & (env->config->inttype_mask[INTTYPE_SOFTWARE] | + env->config->inttype_mask[INTTYPE_EDGE])); } static uint32_t relocated_vector(CPUXtensaState *env, uint32_t vector) @@ -159,11 +163,11 @@ static void handle_interrupt(CPUXtensaState *env) { int level = env->pending_irq_level; - if (level > xtensa_get_cintlevel(env) && - level <= env->config->nlevel && - (env->config->level_mask[level] & - env->sregs[INTSET] & - env->sregs[INTENABLE])) { + if ((level > xtensa_get_cintlevel(env) && + level <= env->config->nlevel && + (env->config->level_mask[level] & + env->sregs[INTSET] & env->sregs[INTENABLE])) || + level == env->config->nmi_level) { CPUState *cs = env_cpu(env); if (level > 1) { @@ -173,6 +177,9 @@ static void handle_interrupt(CPUXtensaState *env) (env->sregs[PS] & ~PS_INTLEVEL) | level | PS_EXCM; env->pc = relocated_vector(env, env->config->interrupt_vector[level]); + if (level == env->config->nmi_level) { + intclear(env, env->config->inttype_mask[INTTYPE_NMI]); + } } else { env->sregs[EXCCAUSE] = LEVEL1_INTERRUPT_CAUSE; diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c index 87487293f9a15f3f13e386df1cd3937e7d562c88..ba3c29d19d9171cac5f304c3281980db753c460b 100644 --- a/target/xtensa/fpu_helper.c +++ b/target/xtensa/fpu_helper.c @@ -33,7 +33,31 @@ #include "exec/exec-all.h" #include "fpu/softfloat.h" -void HELPER(wur_fcr)(CPUXtensaState *env, uint32_t v) +enum { + XTENSA_FP_I = 0x1, + XTENSA_FP_U = 0x2, + XTENSA_FP_O = 0x4, + XTENSA_FP_Z = 0x8, + XTENSA_FP_V = 0x10, +}; + +enum { + XTENSA_FCR_FLAGS_SHIFT = 2, + XTENSA_FSR_FLAGS_SHIFT = 7, +}; + +static const struct { + uint32_t xtensa_fp_flag; + int softfloat_fp_flag; +} xtensa_fp_flag_map[] = { + { XTENSA_FP_I, float_flag_inexact, }, + { XTENSA_FP_U, float_flag_underflow, }, + { XTENSA_FP_O, float_flag_overflow, }, + { XTENSA_FP_Z, float_flag_divbyzero, }, + { XTENSA_FP_V, float_flag_invalid, }, +}; + +void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v) { static const int rounding_mode[] = { float_round_nearest_even, @@ -46,121 +70,379 @@ void HELPER(wur_fcr)(CPUXtensaState *env, uint32_t v) set_float_rounding_mode(rounding_mode[v & 3], &env->fp_status); } +void HELPER(wur_fpu_fcr)(CPUXtensaState *env, uint32_t v) +{ + static const int rounding_mode[] = { + float_round_nearest_even, + float_round_to_zero, + float_round_up, + float_round_down, + }; + + if (v & 0xfffff000) { + qemu_log_mask(LOG_GUEST_ERROR, + "MBZ field of FCR is written non-zero: %08x\n", v); + } + env->uregs[FCR] = v & 0x0000007f; + set_float_rounding_mode(rounding_mode[v & 3], &env->fp_status); +} + +void HELPER(wur_fpu_fsr)(CPUXtensaState *env, uint32_t v) +{ + uint32_t flags = v >> XTENSA_FSR_FLAGS_SHIFT; + int fef = 0; + unsigned i; + + if (v & 0xfffff000) { + qemu_log_mask(LOG_GUEST_ERROR, + "MBZ field of FSR is written non-zero: %08x\n", v); + } + env->uregs[FSR] = v & 0x00000f80; + for (i = 0; i < ARRAY_SIZE(xtensa_fp_flag_map); ++i) { + if (flags & xtensa_fp_flag_map[i].xtensa_fp_flag) { + fef |= xtensa_fp_flag_map[i].softfloat_fp_flag; + } + } + set_float_exception_flags(fef, &env->fp_status); +} + +uint32_t HELPER(rur_fpu_fsr)(CPUXtensaState *env) +{ + uint32_t flags = 0; + int fef = get_float_exception_flags(&env->fp_status); + unsigned i; + + for (i = 0; i < ARRAY_SIZE(xtensa_fp_flag_map); ++i) { + if (fef & xtensa_fp_flag_map[i].softfloat_fp_flag) { + flags |= xtensa_fp_flag_map[i].xtensa_fp_flag; + } + } + env->uregs[FSR] = flags << XTENSA_FSR_FLAGS_SHIFT; + return flags << XTENSA_FSR_FLAGS_SHIFT; +} + +float64 HELPER(abs_d)(float64 v) +{ + return float64_abs(v); +} + float32 HELPER(abs_s)(float32 v) { return float32_abs(v); } +float64 HELPER(neg_d)(float64 v) +{ + return float64_chs(v); +} + float32 HELPER(neg_s)(float32 v) { return float32_chs(v); } +float32 HELPER(fpu2k_add_s)(CPUXtensaState *env, float32 a, float32 b) +{ + return float32_add(a, b, &env->fp_status); +} + +float32 HELPER(fpu2k_sub_s)(CPUXtensaState *env, float32 a, float32 b) +{ + return float32_sub(a, b, &env->fp_status); +} + +float32 HELPER(fpu2k_mul_s)(CPUXtensaState *env, float32 a, float32 b) +{ + return float32_mul(a, b, &env->fp_status); +} + +float32 HELPER(fpu2k_madd_s)(CPUXtensaState *env, + float32 a, float32 b, float32 c) +{ + return float32_muladd(b, c, a, 0, &env->fp_status); +} + +float32 HELPER(fpu2k_msub_s)(CPUXtensaState *env, + float32 a, float32 b, float32 c) +{ + return float32_muladd(b, c, a, float_muladd_negate_product, + &env->fp_status); +} + +float64 HELPER(add_d)(CPUXtensaState *env, float64 a, float64 b) +{ + set_use_first_nan(true, &env->fp_status); + return float64_add(a, b, &env->fp_status); +} + float32 HELPER(add_s)(CPUXtensaState *env, float32 a, float32 b) { + set_use_first_nan(env->config->use_first_nan, &env->fp_status); return float32_add(a, b, &env->fp_status); } +float64 HELPER(sub_d)(CPUXtensaState *env, float64 a, float64 b) +{ + set_use_first_nan(true, &env->fp_status); + return float64_sub(a, b, &env->fp_status); +} + float32 HELPER(sub_s)(CPUXtensaState *env, float32 a, float32 b) { + set_use_first_nan(env->config->use_first_nan, &env->fp_status); return float32_sub(a, b, &env->fp_status); } +float64 HELPER(mul_d)(CPUXtensaState *env, float64 a, float64 b) +{ + set_use_first_nan(true, &env->fp_status); + return float64_mul(a, b, &env->fp_status); +} + float32 HELPER(mul_s)(CPUXtensaState *env, float32 a, float32 b) { + set_use_first_nan(env->config->use_first_nan, &env->fp_status); return float32_mul(a, b, &env->fp_status); } +float64 HELPER(madd_d)(CPUXtensaState *env, float64 a, float64 b, float64 c) +{ + set_use_first_nan(env->config->use_first_nan, &env->fp_status); + return float64_muladd(b, c, a, 0, &env->fp_status); +} + float32 HELPER(madd_s)(CPUXtensaState *env, float32 a, float32 b, float32 c) { + set_use_first_nan(env->config->use_first_nan, &env->fp_status); return float32_muladd(b, c, a, 0, &env->fp_status); } +float64 HELPER(msub_d)(CPUXtensaState *env, float64 a, float64 b, float64 c) +{ + set_use_first_nan(env->config->use_first_nan, &env->fp_status); + return float64_muladd(b, c, a, float_muladd_negate_product, + &env->fp_status); +} + float32 HELPER(msub_s)(CPUXtensaState *env, float32 a, float32 b, float32 c) { + set_use_first_nan(env->config->use_first_nan, &env->fp_status); return float32_muladd(b, c, a, float_muladd_negate_product, &env->fp_status); } -uint32_t HELPER(ftoi)(float32 v, uint32_t rounding_mode, uint32_t scale) +float64 HELPER(mkdadj_d)(CPUXtensaState *env, float64 a, float64 b) +{ + set_use_first_nan(true, &env->fp_status); + return float64_div(b, a, &env->fp_status); +} + +float32 HELPER(mkdadj_s)(CPUXtensaState *env, float32 a, float32 b) +{ + set_use_first_nan(env->config->use_first_nan, &env->fp_status); + return float32_div(b, a, &env->fp_status); +} + +float64 HELPER(mksadj_d)(CPUXtensaState *env, float64 v) +{ + set_use_first_nan(true, &env->fp_status); + return float64_sqrt(v, &env->fp_status); +} + +float32 HELPER(mksadj_s)(CPUXtensaState *env, float32 v) +{ + set_use_first_nan(env->config->use_first_nan, &env->fp_status); + return float32_sqrt(v, &env->fp_status); +} + +uint32_t HELPER(ftoi_d)(CPUXtensaState *env, float64 v, + uint32_t rounding_mode, uint32_t scale) +{ + float_status fp_status = env->fp_status; + uint32_t res; + + set_float_rounding_mode(rounding_mode, &fp_status); + res = float64_to_int32(float64_scalbn(v, scale, &fp_status), &fp_status); + set_float_exception_flags(get_float_exception_flags(&fp_status), + &env->fp_status); + return res; +} + +uint32_t HELPER(ftoi_s)(CPUXtensaState *env, float32 v, + uint32_t rounding_mode, uint32_t scale) { - float_status fp_status = {0}; + float_status fp_status = env->fp_status; + uint32_t res; set_float_rounding_mode(rounding_mode, &fp_status); - return float32_to_int32(float32_scalbn(v, scale, &fp_status), &fp_status); + res = float32_to_int32(float32_scalbn(v, scale, &fp_status), &fp_status); + set_float_exception_flags(get_float_exception_flags(&fp_status), + &env->fp_status); + return res; } -uint32_t HELPER(ftoui)(float32 v, uint32_t rounding_mode, uint32_t scale) +uint32_t HELPER(ftoui_d)(CPUXtensaState *env, float64 v, + uint32_t rounding_mode, uint32_t scale) { - float_status fp_status = {0}; + float_status fp_status = env->fp_status; + float64 res; + uint32_t rv; + + set_float_rounding_mode(rounding_mode, &fp_status); + + res = float64_scalbn(v, scale, &fp_status); + + if (float64_is_neg(v) && !float64_is_any_nan(v)) { + set_float_exception_flags(float_flag_invalid, &fp_status); + rv = float64_to_int32(res, &fp_status); + } else { + rv = float64_to_uint32(res, &fp_status); + } + set_float_exception_flags(get_float_exception_flags(&fp_status), + &env->fp_status); + return rv; +} + +uint32_t HELPER(ftoui_s)(CPUXtensaState *env, float32 v, + uint32_t rounding_mode, uint32_t scale) +{ + float_status fp_status = env->fp_status; float32 res; + uint32_t rv; set_float_rounding_mode(rounding_mode, &fp_status); res = float32_scalbn(v, scale, &fp_status); if (float32_is_neg(v) && !float32_is_any_nan(v)) { - return float32_to_int32(res, &fp_status); + rv = float32_to_int32(res, &fp_status); + if (rv) { + set_float_exception_flags(float_flag_invalid, &fp_status); + } } else { - return float32_to_uint32(res, &fp_status); + rv = float32_to_uint32(res, &fp_status); } + set_float_exception_flags(get_float_exception_flags(&fp_status), + &env->fp_status); + return rv; +} + +float64 HELPER(itof_d)(CPUXtensaState *env, uint32_t v, uint32_t scale) +{ + return float64_scalbn(int32_to_float64(v, &env->fp_status), + (int32_t)scale, &env->fp_status); } -float32 HELPER(itof)(CPUXtensaState *env, uint32_t v, uint32_t scale) +float32 HELPER(itof_s)(CPUXtensaState *env, uint32_t v, uint32_t scale) { return float32_scalbn(int32_to_float32(v, &env->fp_status), (int32_t)scale, &env->fp_status); } -float32 HELPER(uitof)(CPUXtensaState *env, uint32_t v, uint32_t scale) +float64 HELPER(uitof_d)(CPUXtensaState *env, uint32_t v, uint32_t scale) +{ + return float64_scalbn(uint32_to_float64(v, &env->fp_status), + (int32_t)scale, &env->fp_status); +} + +float32 HELPER(uitof_s)(CPUXtensaState *env, uint32_t v, uint32_t scale) { return float32_scalbn(uint32_to_float32(v, &env->fp_status), (int32_t)scale, &env->fp_status); } -static inline void set_br(CPUXtensaState *env, bool v, uint32_t br) +float64 HELPER(cvtd_s)(CPUXtensaState *env, float32 v) { - if (v) { - env->sregs[BR] |= br; - } else { - env->sregs[BR] &= ~br; - } + return float32_to_float64(v, &env->fp_status); +} + +float32 HELPER(cvts_d)(CPUXtensaState *env, float64 v) +{ + return float64_to_float32(v, &env->fp_status); +} + +uint32_t HELPER(un_d)(CPUXtensaState *env, float64 a, float64 b) +{ + return float64_unordered_quiet(a, b, &env->fp_status); } -void HELPER(un_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) +uint32_t HELPER(un_s)(CPUXtensaState *env, float32 a, float32 b) { - set_br(env, float32_unordered_quiet(a, b, &env->fp_status), br); + return float32_unordered_quiet(a, b, &env->fp_status); } -void HELPER(oeq_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) +uint32_t HELPER(oeq_d)(CPUXtensaState *env, float64 a, float64 b) { - set_br(env, float32_eq_quiet(a, b, &env->fp_status), br); + return float64_eq_quiet(a, b, &env->fp_status); } -void HELPER(ueq_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) +uint32_t HELPER(oeq_s)(CPUXtensaState *env, float32 a, float32 b) +{ + return float32_eq_quiet(a, b, &env->fp_status); +} + +uint32_t HELPER(ueq_d)(CPUXtensaState *env, float64 a, float64 b) +{ + FloatRelation v = float64_compare_quiet(a, b, &env->fp_status); + + return v == float_relation_equal || + v == float_relation_unordered; +} + +uint32_t HELPER(ueq_s)(CPUXtensaState *env, float32 a, float32 b) { FloatRelation v = float32_compare_quiet(a, b, &env->fp_status); - set_br(env, v == float_relation_equal || v == float_relation_unordered, br); + + return v == float_relation_equal || + v == float_relation_unordered; } -void HELPER(olt_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) +uint32_t HELPER(olt_d)(CPUXtensaState *env, float64 a, float64 b) { - set_br(env, float32_lt_quiet(a, b, &env->fp_status), br); + return float64_lt(a, b, &env->fp_status); } -void HELPER(ult_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) +uint32_t HELPER(olt_s)(CPUXtensaState *env, float32 a, float32 b) +{ + return float32_lt(a, b, &env->fp_status); +} + +uint32_t HELPER(ult_d)(CPUXtensaState *env, float64 a, float64 b) +{ + FloatRelation v = float64_compare_quiet(a, b, &env->fp_status); + + return v == float_relation_less || + v == float_relation_unordered; +} + +uint32_t HELPER(ult_s)(CPUXtensaState *env, float32 a, float32 b) { FloatRelation v = float32_compare_quiet(a, b, &env->fp_status); - set_br(env, v == float_relation_less || v == float_relation_unordered, br); + + return v == float_relation_less || + v == float_relation_unordered; } -void HELPER(ole_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) +uint32_t HELPER(ole_d)(CPUXtensaState *env, float64 a, float64 b) { - set_br(env, float32_le_quiet(a, b, &env->fp_status), br); + return float64_le(a, b, &env->fp_status); } -void HELPER(ule_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b) +uint32_t HELPER(ole_s)(CPUXtensaState *env, float32 a, float32 b) +{ + return float32_le(a, b, &env->fp_status); +} + +uint32_t HELPER(ule_d)(CPUXtensaState *env, float64 a, float64 b) +{ + FloatRelation v = float64_compare_quiet(a, b, &env->fp_status); + + return v != float_relation_greater; +} + +uint32_t HELPER(ule_s)(CPUXtensaState *env, float32 a, float32 b) { FloatRelation v = float32_compare_quiet(a, b, &env->fp_status); - set_br(env, v != float_relation_greater, br); + + return v != float_relation_greater; } diff --git a/target/xtensa/gdbstub.c b/target/xtensa/gdbstub.c index 4d43f1340ae6a497fcdcf8a25257aa20eae801cc..b6696063e5e6793b0e1d161966a0412375d59e29 100644 --- a/target/xtensa/gdbstub.c +++ b/target/xtensa/gdbstub.c @@ -7,7 +7,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c index 7073381f03b2469d9958d2bc1afbae2096b0475b..05e2b7f70a1e7bc8cc77cdb0c1130d0ebe009727 100644 --- a/target/xtensa/helper.c +++ b/target/xtensa/helper.c @@ -133,8 +133,10 @@ static void init_libisa(XtensaConfig *config) config->regfile = g_new(void **, regfiles); for (i = 0; i < regfiles; ++i) { const char *name = xtensa_regfile_name(config->isa, i); + int entries = xtensa_regfile_num_entries(config->isa, i); + int bits = xtensa_regfile_num_bits(config->isa, i); - config->regfile[i] = xtensa_get_regfile_by_name(name); + config->regfile[i] = xtensa_get_regfile_by_name(name, entries, bits); #ifdef DEBUG if (config->regfile[i] == NULL) { fprintf(stderr, "regfile '%s' not found for %s\n", diff --git a/target/xtensa/helper.h b/target/xtensa/helper.h index 8532de0b35f5160400d6e4e76309e91ca55f9865..ae938ceedb801fb6b69456c8e2262c4157dfd805 100644 --- a/target/xtensa/helper.h +++ b/target/xtensa/helper.h @@ -46,26 +46,60 @@ DEF_HELPER_3(wsr_dbreaka, void, env, i32, i32) DEF_HELPER_3(wsr_dbreakc, void, env, i32, i32) #endif -DEF_HELPER_2(wur_fcr, void, env, i32) +DEF_HELPER_2(wur_fpu2k_fcr, void, env, i32) DEF_HELPER_FLAGS_1(abs_s, TCG_CALL_NO_RWG_SE, f32, f32) DEF_HELPER_FLAGS_1(neg_s, TCG_CALL_NO_RWG_SE, f32, f32) +DEF_HELPER_3(fpu2k_add_s, f32, env, f32, f32) +DEF_HELPER_3(fpu2k_sub_s, f32, env, f32, f32) +DEF_HELPER_3(fpu2k_mul_s, f32, env, f32, f32) +DEF_HELPER_4(fpu2k_madd_s, f32, env, f32, f32, f32) +DEF_HELPER_4(fpu2k_msub_s, f32, env, f32, f32, f32) +DEF_HELPER_4(ftoi_s, i32, env, f32, i32, i32) +DEF_HELPER_4(ftoui_s, i32, env, f32, i32, i32) +DEF_HELPER_3(itof_s, f32, env, i32, i32) +DEF_HELPER_3(uitof_s, f32, env, i32, i32) +DEF_HELPER_2(cvtd_s, f64, env, f32) + +DEF_HELPER_3(un_s, i32, env, f32, f32) +DEF_HELPER_3(oeq_s, i32, env, f32, f32) +DEF_HELPER_3(ueq_s, i32, env, f32, f32) +DEF_HELPER_3(olt_s, i32, env, f32, f32) +DEF_HELPER_3(ult_s, i32, env, f32, f32) +DEF_HELPER_3(ole_s, i32, env, f32, f32) +DEF_HELPER_3(ule_s, i32, env, f32, f32) + +DEF_HELPER_2(wur_fpu_fcr, void, env, i32) +DEF_HELPER_1(rur_fpu_fsr, i32, env) +DEF_HELPER_2(wur_fpu_fsr, void, env, i32) +DEF_HELPER_FLAGS_1(abs_d, TCG_CALL_NO_RWG_SE, f64, f64) +DEF_HELPER_FLAGS_1(neg_d, TCG_CALL_NO_RWG_SE, f64, f64) +DEF_HELPER_3(add_d, f64, env, f64, f64) DEF_HELPER_3(add_s, f32, env, f32, f32) +DEF_HELPER_3(sub_d, f64, env, f64, f64) DEF_HELPER_3(sub_s, f32, env, f32, f32) +DEF_HELPER_3(mul_d, f64, env, f64, f64) DEF_HELPER_3(mul_s, f32, env, f32, f32) +DEF_HELPER_4(madd_d, f64, env, f64, f64, f64) DEF_HELPER_4(madd_s, f32, env, f32, f32, f32) +DEF_HELPER_4(msub_d, f64, env, f64, f64, f64) DEF_HELPER_4(msub_s, f32, env, f32, f32, f32) -DEF_HELPER_FLAGS_3(ftoi, TCG_CALL_NO_RWG_SE, i32, f32, i32, i32) -DEF_HELPER_FLAGS_3(ftoui, TCG_CALL_NO_RWG_SE, i32, f32, i32, i32) -DEF_HELPER_3(itof, f32, env, i32, i32) -DEF_HELPER_3(uitof, f32, env, i32, i32) +DEF_HELPER_3(mkdadj_d, f64, env, f64, f64) +DEF_HELPER_3(mkdadj_s, f32, env, f32, f32) +DEF_HELPER_2(mksadj_d, f64, env, f64) +DEF_HELPER_2(mksadj_s, f32, env, f32) +DEF_HELPER_4(ftoi_d, i32, env, f64, i32, i32) +DEF_HELPER_4(ftoui_d, i32, env, f64, i32, i32) +DEF_HELPER_3(itof_d, f64, env, i32, i32) +DEF_HELPER_3(uitof_d, f64, env, i32, i32) +DEF_HELPER_2(cvts_d, f32, env, f64) -DEF_HELPER_4(un_s, void, env, i32, f32, f32) -DEF_HELPER_4(oeq_s, void, env, i32, f32, f32) -DEF_HELPER_4(ueq_s, void, env, i32, f32, f32) -DEF_HELPER_4(olt_s, void, env, i32, f32, f32) -DEF_HELPER_4(ult_s, void, env, i32, f32, f32) -DEF_HELPER_4(ole_s, void, env, i32, f32, f32) -DEF_HELPER_4(ule_s, void, env, i32, f32, f32) +DEF_HELPER_3(un_d, i32, env, f64, f64) +DEF_HELPER_3(oeq_d, i32, env, f64, f64) +DEF_HELPER_3(ueq_d, i32, env, f64, f64) +DEF_HELPER_3(olt_d, i32, env, f64, f64) +DEF_HELPER_3(ult_d, i32, env, f64, f64) +DEF_HELPER_3(ole_d, i32, env, f64, f64) +DEF_HELPER_3(ule_d, i32, env, f64, f64) DEF_HELPER_2(rer, i32, env, i32) DEF_HELPER_3(wer, void, env, i32, i32) diff --git a/target/xtensa/import_core.sh b/target/xtensa/import_core.sh index 8f844cf9e2a6c3f0bc0789fd5861deb748aace13..c8626a8c02ebb41e2ab9aab3648f1311e329b85e 100755 --- a/target/xtensa/import_core.sh +++ b/target/xtensa/import_core.sh @@ -23,7 +23,7 @@ tar -xf "$OVERLAY" -C "$TARGET" --strip-components=2 \ xtensa/config/core-isa.h \ xtensa/config/core-matmap.h tar -xf "$OVERLAY" -O gdb/xtensa-config.c | \ - sed -n '1,/*\//p;/XTREG/,/XTREG_END/p' > "$TARGET"/gdb-config.inc.c + sed -n '1,/*\//p;/XTREG/,/XTREG_END/p' > "$TARGET"/gdb-config.c.inc # # Fix up known issues in the xtensa-modules.c # @@ -35,7 +35,7 @@ tar -xf "$OVERLAY" -O binutils/xtensa-modules.c | \ -e '/^#include "ansidecl.h"/d' \ -e '/^Slot_[a-zA-Z0-9_]\+_decode (const xtensa_insnbuf insn)/,/^}/s/^ return 0;$/ return XTENSA_UNDEFINED;/' \ -e 's/#include /#include "xtensa-isa.h"/' \ - > "$TARGET"/xtensa-modules.inc.c + > "$TARGET"/xtensa-modules.c.inc cat < "${TARGET}.c" #include "qemu/osdep.h" @@ -49,13 +49,13 @@ cat < "${TARGET}.c" #include "overlay_tool.h" #define xtensa_modules xtensa_modules_$NAME -#include "core-$NAME/xtensa-modules.inc.c" +#include "core-$NAME/xtensa-modules.c.inc" static XtensaConfig $NAME __attribute__((unused)) = { .name = "$NAME", .gdb_regmap = { .reg = { -#include "core-$NAME/gdb-config.inc.c" +#include "core-$NAME/gdb-config.c.inc" } }, .isa_internal = &xtensa_modules, diff --git a/target/xtensa/meson.build b/target/xtensa/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..dd750a977ef9c046a12e16415b587e85d77e6e76 --- /dev/null +++ b/target/xtensa/meson.build @@ -0,0 +1,32 @@ +xtensa_ss = ss.source_set() +xtensa_ss.add(files( + 'core-dc232b.c', + 'core-dc233c.c', + 'core-de212.c', + 'core-de233_fpu.c', + 'core-dsp3400.c', + 'core-fsf.c', + 'core-sample_controller.c', + 'core-test_kc705_be.c', + 'core-test_mmuhifi_c3.c', + 'cpu.c', + 'exc_helper.c', + 'fpu_helper.c', + 'gdbstub.c', + 'helper.c', + 'op_helper.c', + 'translate.c', + 'win_helper.c', + 'xtensa-isa.c', +)) + +xtensa_softmmu_ss = ss.source_set() +xtensa_softmmu_ss.add(files( + 'dbg_helper.c', + 'mmu_helper.c', + 'monitor.c', + 'xtensa-semi.c', +)) + +target_arch += {'xtensa': xtensa_ss} +target_softmmu_arch += {'xtensa': xtensa_softmmu_ss} diff --git a/target/xtensa/monitor.c b/target/xtensa/monitor.c index 608173c238f9a6c60f8c97f4d53e432cea52e733..fbf60d55530722c5edb9186f036f1a9b1dd98fa7 100644 --- a/target/xtensa/monitor.c +++ b/target/xtensa/monitor.c @@ -29,7 +29,7 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict) { - CPUArchState *env1 = mon_get_cpu_env(); + CPUArchState *env1 = mon_get_cpu_env(mon); if (!env1) { monitor_printf(mon, "No CPU available\n"); diff --git a/target/xtensa/op_helper.c b/target/xtensa/op_helper.c index 09f4962d008a465d52f810ce5a732c4684fffdf2..143476849fb7d1890e3b21164af33ebc30ec4c81 100644 --- a/target/xtensa/op_helper.c +++ b/target/xtensa/op_helper.c @@ -62,7 +62,7 @@ void HELPER(update_ccompare)(CPUXtensaState *env, uint32_t i) { uint64_t dcc; - atomic_and(&env->sregs[INTSET], + qatomic_and(&env->sregs[INTSET], ~(1u << env->config->timerint[i])); HELPER(update_ccount)(env); dcc = (uint64_t)(env->sregs[CCOMPARE + i] - env->sregs[CCOUNT] - 1) + 1; diff --git a/target/xtensa/overlay_tool.h b/target/xtensa/overlay_tool.h index cab532095c9e982b816a94fd152f2809452bcb86..78720734fe92c3fd7d14502d3614567edd6f5177 100644 --- a/target/xtensa/overlay_tool.h +++ b/target/xtensa/overlay_tool.h @@ -39,6 +39,26 @@ #define XCHAL_HAVE_DEPBITS 0 #endif +#ifndef XCHAL_HAVE_DFP +#define XCHAL_HAVE_DFP 0 +#endif + +#ifndef XCHAL_HAVE_DFPU_SINGLE_ONLY +#define XCHAL_HAVE_DFPU_SINGLE_ONLY 0 +#endif + +#ifndef XCHAL_HAVE_DFPU_SINGLE_DOUBLE +#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE XCHAL_HAVE_DFP +#endif + +/* + * We need to know the type of FP unit, not only its precision. + * Unfortunately XCHAL macros don't tell this explicitly. + */ +#define XCHAL_HAVE_DFPU (XCHAL_HAVE_DFP || \ + XCHAL_HAVE_DFPU_SINGLE_ONLY || \ + XCHAL_HAVE_DFPU_SINGLE_DOUBLE) + #ifndef XCHAL_HAVE_DIV32 #define XCHAL_HAVE_DIV32 0 #endif @@ -60,8 +80,9 @@ #define XCHAL_RESET_VECTOR1_VADDR XCHAL_RESET_VECTOR_VADDR #endif -#ifndef XCHAL_HW_MIN_VERSION -#define XCHAL_HW_MIN_VERSION 0 +#ifndef XCHAL_HW_VERSION +#define XCHAL_HW_VERSION (XCHAL_HW_VERSION_MAJOR * 100 \ + + XCHAL_HW_VERSION_MINOR) #endif #ifndef XCHAL_LOOP_BUFFER_SIZE @@ -98,9 +119,12 @@ XCHAL_OPTION(XCHAL_HAVE_CP, XTENSA_OPTION_COPROCESSOR) | \ XCHAL_OPTION(XCHAL_HAVE_BOOLEANS, XTENSA_OPTION_BOOLEAN) | \ XCHAL_OPTION(XCHAL_HAVE_FP, XTENSA_OPTION_FP_COPROCESSOR) | \ + XCHAL_OPTION(XCHAL_HAVE_DFPU, XTENSA_OPTION_DFP_COPROCESSOR) | \ + XCHAL_OPTION(XCHAL_HAVE_DFPU_SINGLE_ONLY, \ + XTENSA_OPTION_DFPU_SINGLE_ONLY) | \ XCHAL_OPTION(XCHAL_HAVE_RELEASE_SYNC, XTENSA_OPTION_MP_SYNCHRO) | \ XCHAL_OPTION(XCHAL_HAVE_S32C1I, XTENSA_OPTION_CONDITIONAL_STORE) | \ - XCHAL_OPTION(((XCHAL_HAVE_S32C1I && XCHAL_HW_MIN_VERSION >= 230000) || \ + XCHAL_OPTION(((XCHAL_HAVE_S32C1I && XCHAL_HW_VERSION >= 230000) || \ XCHAL_HAVE_EXCLUSIVE), XTENSA_OPTION_ATOMCTL) | \ XCHAL_OPTION(XCHAL_HAVE_DEPBITS, XTENSA_OPTION_DEPBITS) | \ /* Interrupts and exceptions */ \ @@ -215,6 +239,9 @@ #define XTHAL_INTTYPE_IDMA_ERR INTTYPE_IDMA_ERR #define XTHAL_INTTYPE_GS_ERR INTTYPE_GS_ERR +#ifndef XCHAL_NMILEVEL +#define XCHAL_NMILEVEL (XCHAL_NUM_INTLEVELS + 1) +#endif #define INTERRUPT(i) { \ .level = XCHAL_INT ## i ## _LEVEL, \ @@ -304,7 +331,8 @@ #define INTERRUPTS_SECTION \ .ninterrupt = XCHAL_NUM_INTERRUPTS, \ - .nlevel = XCHAL_NUM_INTLEVELS, \ + .nlevel = XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI, \ + .nmi_level = XCHAL_NMILEVEL, \ .interrupt_vector = INTERRUPT_VECTORS, \ .level_mask = LEVEL_MASKS, \ .inttype_mask = INTTYPE_MASKS, \ @@ -498,6 +526,7 @@ } #define CONFIG_SECTION \ + .hw_version = XCHAL_HW_VERSION, \ .configid = { \ XCHAL_HW_CONFIGID0, \ XCHAL_HW_CONFIGID1, \ @@ -509,6 +538,7 @@ .ndepc = (XCHAL_XEA_VERSION >= 2), \ .inst_fetch_width = XCHAL_INST_FETCH_WIDTH, \ .max_insn_size = XCHAL_MAX_INSTRUCTION_SIZE, \ + .use_first_nan = !XCHAL_HAVE_DFPU, \ EXCEPTIONS_SECTION, \ INTERRUPTS_SECTION, \ TLB_SECTION, \ diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index e0beaf7abbbd2e7d3305bb9275915804cd533755..944a157747cdd7300c22274f2b2bcb6511ce5931 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -79,6 +79,7 @@ struct DisasContext { static TCGv_i32 cpu_pc; static TCGv_i32 cpu_R[16]; static TCGv_i32 cpu_FR[16]; +static TCGv_i64 cpu_FRD[16]; static TCGv_i32 cpu_MR[4]; static TCGv_i32 cpu_BR[16]; static TCGv_i32 cpu_BR4[4]; @@ -169,6 +170,13 @@ void xtensa_translate_init(void) fregnames[i]); } + for (i = 0; i < 16; i++) { + cpu_FRD[i] = tcg_global_mem_new_i64(cpu_env, + offsetof(CPUXtensaState, + fregs[i].f64), + fregnames[i]); + } + for (i = 0; i < 4; i++) { cpu_MR[i] = tcg_global_mem_new_i32(cpu_env, offsetof(CPUXtensaState, @@ -227,24 +235,45 @@ void xtensa_translate_init(void) "exclusive_val"); } -void **xtensa_get_regfile_by_name(const char *name) +void **xtensa_get_regfile_by_name(const char *name, int entries, int bits) { + char *geometry_name; + void **res; + if (xtensa_regfile_table == NULL) { xtensa_regfile_table = g_hash_table_new(g_str_hash, g_str_equal); + /* + * AR is special. Xtensa translator uses it as a current register + * window, but configuration overlays represent it as a complete + * physical register file. + */ + g_hash_table_insert(xtensa_regfile_table, + (void *)"AR 16x32", (void *)cpu_R); + g_hash_table_insert(xtensa_regfile_table, + (void *)"AR 32x32", (void *)cpu_R); + g_hash_table_insert(xtensa_regfile_table, + (void *)"AR 64x32", (void *)cpu_R); + g_hash_table_insert(xtensa_regfile_table, - (void *)"AR", (void *)cpu_R); + (void *)"MR 4x32", (void *)cpu_MR); + g_hash_table_insert(xtensa_regfile_table, - (void *)"MR", (void *)cpu_MR); + (void *)"FR 16x32", (void *)cpu_FR); g_hash_table_insert(xtensa_regfile_table, - (void *)"FR", (void *)cpu_FR); + (void *)"FR 16x64", (void *)cpu_FRD); + g_hash_table_insert(xtensa_regfile_table, - (void *)"BR", (void *)cpu_BR); + (void *)"BR 16x1", (void *)cpu_BR); g_hash_table_insert(xtensa_regfile_table, - (void *)"BR4", (void *)cpu_BR4); + (void *)"BR4 4x4", (void *)cpu_BR4); g_hash_table_insert(xtensa_regfile_table, - (void *)"BR8", (void *)cpu_BR8); + (void *)"BR8 2x8", (void *)cpu_BR8); } - return (void **)g_hash_table_lookup(xtensa_regfile_table, (void *)name); + + geometry_name = g_strdup_printf("%s %dx%d", name, entries, bits); + res = (void **)g_hash_table_lookup(xtensa_regfile_table, geometry_name); + g_free(geometry_name); + return res; } static inline bool option_enabled(DisasContext *dc, int opt) @@ -459,22 +488,26 @@ static void gen_brcondi(DisasContext *dc, TCGCond cond, tcg_temp_free(tmp); } -static bool test_ill_sr(DisasContext *dc, const OpcodeArg arg[], - const uint32_t par[]) +static uint32_t test_exceptions_sr(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) { - return !xtensa_option_enabled(dc->config, par[1]); + return xtensa_option_enabled(dc->config, par[1]) ? 0 : XTENSA_OP_ILL; } -static bool test_ill_ccompare(DisasContext *dc, const OpcodeArg arg[], - const uint32_t par[]) +static uint32_t test_exceptions_ccompare(DisasContext *dc, + const OpcodeArg arg[], + const uint32_t par[]) { unsigned n = par[0] - CCOMPARE; - return test_ill_sr(dc, arg, par) || n >= dc->config->nccompare; + if (n >= dc->config->nccompare) { + return XTENSA_OP_ILL; + } + return test_exceptions_sr(dc, arg, par); } -static bool test_ill_dbreak(DisasContext *dc, const OpcodeArg arg[], - const uint32_t par[]) +static uint32_t test_exceptions_dbreak(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) { unsigned n = MAX_NDBREAK; @@ -484,19 +517,25 @@ static bool test_ill_dbreak(DisasContext *dc, const OpcodeArg arg[], if (par[0] >= DBREAKC && par[0] < DBREAKC + MAX_NDBREAK) { n = par[0] - DBREAKC; } - return test_ill_sr(dc, arg, par) || n >= dc->config->ndbreak; + if (n >= dc->config->ndbreak) { + return XTENSA_OP_ILL; + } + return test_exceptions_sr(dc, arg, par); } -static bool test_ill_ibreak(DisasContext *dc, const OpcodeArg arg[], - const uint32_t par[]) +static uint32_t test_exceptions_ibreak(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) { unsigned n = par[0] - IBREAKA; - return test_ill_sr(dc, arg, par) || n >= dc->config->nibreak; + if (n >= dc->config->nibreak) { + return XTENSA_OP_ILL; + } + return test_exceptions_sr(dc, arg, par); } -static bool test_ill_hpi(DisasContext *dc, const OpcodeArg arg[], - const uint32_t par[]) +static uint32_t test_exceptions_hpi(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) { unsigned n = MAX_NLEVEL + 1; @@ -509,7 +548,10 @@ static bool test_ill_hpi(DisasContext *dc, const OpcodeArg arg[], if (par[0] >= EPS2 && par[0] < EPS2 + MAX_NLEVEL - 1) { n = par[0] - EPS2 + 2; } - return test_ill_sr(dc, arg, par) || n > dc->config->nlevel; + if (n > dc->config->nlevel) { + return XTENSA_OP_ILL; + } + return test_exceptions_sr(dc, arg, par); } static void gen_load_store_alignment(DisasContext *dc, int shift, @@ -595,9 +637,6 @@ static int gen_postprocess(DisasContext *dc, int slot) gen_io_start(); } gen_helper_check_interrupts(cpu_env); - if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { - gen_io_end(); - } } #endif if (op_flags & XTENSA_OP_SYNC_REGISTER_WINDOW) { @@ -914,10 +953,10 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) for (opnd = vopnd = 0; opnd < opnds; ++opnd) { void **register_file = NULL; + xtensa_regfile rf; if (xtensa_operand_is_register(isa, opc, opnd)) { - xtensa_regfile rf = xtensa_operand_regfile(isa, opc, opnd); - + rf = xtensa_operand_regfile(isa, opc, opnd); register_file = dc->config->regfile[rf]; if (rf == dc->config->a_regfile) { @@ -943,6 +982,9 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) if (register_file) { arg[vopnd].in = register_file[v]; arg[vopnd].out = register_file[v]; + arg[vopnd].num_bits = xtensa_regfile_num_bits(isa, rf); + } else { + arg[vopnd].num_bits = 32; } ++vopnd; } @@ -952,18 +994,20 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) if (ops) { op_flags |= ops->op_flags; + if (ops->test_exceptions) { + op_flags |= ops->test_exceptions(dc, arg, ops->par); + } } else { qemu_log_mask(LOG_UNIMP, "unimplemented opcode '%s' in slot %d (pc = %08x)\n", xtensa_opcode_name(isa, opc), slot, dc->pc); op_flags |= XTENSA_OP_ILL; } - if ((op_flags & XTENSA_OP_ILL) || - (ops && ops->test_ill && ops->test_ill(dc, arg, ops->par))) { + if (op_flags & XTENSA_OP_ILL) { gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); return; } - if (ops->op_flags & XTENSA_OP_DEBUG_BREAK) { + if (op_flags & XTENSA_OP_DEBUG_BREAK) { debug_cause |= ops->par[0]; } if (ops->test_overflow) { @@ -1080,8 +1124,15 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) for (i = j = 0; i < n_arg_copy; ++i) { if (i == 0 || arg_copy[i].resource != resource) { resource = arg_copy[i].resource; - temp = tcg_temp_local_new(); - tcg_gen_mov_i32(temp, arg_copy[i].arg->in); + if (arg_copy[i].arg->num_bits <= 32) { + temp = tcg_temp_local_new_i32(); + tcg_gen_mov_i32(temp, arg_copy[i].arg->in); + } else if (arg_copy[i].arg->num_bits <= 64) { + temp = tcg_temp_local_new_i64(); + tcg_gen_mov_i64(temp, arg_copy[i].arg->in); + } else { + g_assert_not_reached(); + } arg_copy[i].temp = temp; if (i != j) { @@ -1112,7 +1163,13 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) } for (i = 0; i < n_arg_copy; ++i) { - tcg_temp_free(arg_copy[i].temp); + if (arg_copy[i].arg->num_bits <= 32) { + tcg_temp_free_i32(arg_copy[i].temp); + } else if (arg_copy[i].arg->num_bits <= 64) { + tcg_temp_free_i64(arg_copy[i].temp); + } else { + g_assert_not_reached(); + } } if (dc->base.is_jmp == DISAS_NEXT) { @@ -1351,12 +1408,25 @@ void xtensa_cpu_dump_state(CPUState *cs, FILE *f, int flags) qemu_fprintf(f, "\n"); for (i = 0; i < 16; ++i) { - qemu_fprintf(f, "F%02d=%08x (%+10.8e)%c", i, + qemu_fprintf(f, "F%02d=%08x (%-+15.8e)%c", i, float32_val(env->fregs[i].f32[FP_F32_LOW]), *(float *)(env->fregs[i].f32 + FP_F32_LOW), (i % 2) == 1 ? '\n' : ' '); } } + + if ((flags & CPU_DUMP_FPU) && + xtensa_option_enabled(env->config, XTENSA_OPTION_DFP_COPROCESSOR) && + !xtensa_option_enabled(env->config, XTENSA_OPTION_DFPU_SINGLE_ONLY)) { + qemu_fprintf(f, "\n"); + + for (i = 0; i < 16; ++i) { + qemu_fprintf(f, "F%02d=%016"PRIx64" (%-+24.16le)%c", i, + float64_val(env->fregs[i].f64), + *(double *)(&env->fregs[i].f64), + (i % 2) == 1 ? '\n' : ' '); + } + } } void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, @@ -1622,15 +1692,15 @@ static void translate_diwbuip(DisasContext *dc, const OpcodeArg arg[], tcg_gen_addi_i32(arg[0].out, arg[0].in, dc->config->dcache_line_bytes); } -static bool test_ill_entry(DisasContext *dc, const OpcodeArg arg[], - const uint32_t par[]) +static uint32_t test_exceptions_entry(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) { if (arg[0].imm > 3 || !dc->cwoe) { qemu_log_mask(LOG_GUEST_ERROR, "Illegal entry instruction(pc = %08x)\n", dc->pc); - return true; + return XTENSA_OP_ILL; } else { - return false; + return 0; } } @@ -2103,19 +2173,19 @@ static void translate_ret(DisasContext *dc, const OpcodeArg arg[], gen_jump(dc, cpu_R[0]); } -static bool test_ill_retw(DisasContext *dc, const OpcodeArg arg[], - const uint32_t par[]) +static uint32_t test_exceptions_retw(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) { if (!dc->cwoe) { qemu_log_mask(LOG_GUEST_ERROR, "Illegal retw instruction(pc = %08x)\n", dc->pc); - return true; + return XTENSA_OP_ILL; } else { TCGv_i32 tmp = tcg_const_i32(dc->pc); gen_helper_test_ill_retw(cpu_env, tmp); tcg_temp_free(tmp); - return false; + return 0; } } @@ -2191,7 +2261,11 @@ static void translate_rsil(DisasContext *dc, const OpcodeArg arg[], static void translate_rsr(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { - tcg_gen_mov_i32(arg[0].out, cpu_SR[par[0]]); + if (sr_name[par[0]]) { + tcg_gen_mov_i32(arg[0].out, cpu_SR[par[0]]); + } else { + tcg_gen_movi_i32(arg[0].out, 0); + } } static void translate_rsr_ccount(DisasContext *dc, const OpcodeArg arg[], @@ -2357,25 +2431,29 @@ static void translate_sext(DisasContext *dc, const OpcodeArg arg[], } } -static bool test_ill_simcall(DisasContext *dc, const OpcodeArg arg[], - const uint32_t par[]) +static uint32_t test_exceptions_simcall(DisasContext *dc, + const OpcodeArg arg[], + const uint32_t par[]) { #ifdef CONFIG_USER_ONLY bool ill = true; #else - bool ill = !semihosting_enabled(); + /* Between RE.2 and RE.3 simcall opcode's become nop for the hardware. */ + bool ill = dc->config->hw_version <= 250002 && !semihosting_enabled(); #endif - if (ill) { + if (ill || !semihosting_enabled()) { qemu_log_mask(LOG_GUEST_ERROR, "SIMCALL but semihosting is disabled\n"); } - return ill; + return ill ? XTENSA_OP_ILL : 0; } static void translate_simcall(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { #ifndef CONFIG_USER_ONLY - gen_helper_simcall(cpu_env); + if (semihosting_enabled()) { + gen_helper_simcall(cpu_env); + } #endif } @@ -2563,13 +2641,17 @@ static void translate_wrmsk_expstate(DisasContext *dc, const OpcodeArg arg[], static void translate_wsr(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { - tcg_gen_mov_i32(cpu_SR[par[0]], arg[0].in); + if (sr_name[par[0]]) { + tcg_gen_mov_i32(cpu_SR[par[0]], arg[0].in); + } } static void translate_wsr_mask(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { - tcg_gen_andi_i32(cpu_SR[par[0]], arg[0].in, par[2]); + if (sr_name[par[0]]) { + tcg_gen_andi_i32(cpu_SR[par[0]], arg[0].in, par[2]); + } } static void translate_wsr_acchi(DisasContext *dc, const OpcodeArg arg[], @@ -2754,18 +2836,6 @@ static void translate_wur(DisasContext *dc, const OpcodeArg arg[], tcg_gen_mov_i32(cpu_UR[par[0]], arg[0].in); } -static void translate_wur_fcr(DisasContext *dc, const OpcodeArg arg[], - const uint32_t par[]) -{ - gen_helper_wur_fcr(cpu_env, arg[0].in); -} - -static void translate_wur_fsr(DisasContext *dc, const OpcodeArg arg[], - const uint32_t par[]) -{ - tcg_gen_andi_i32(cpu_UR[par[0]], arg[0].in, 0xffffff80); -} - static void translate_xor(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { @@ -2775,23 +2845,31 @@ static void translate_xor(DisasContext *dc, const OpcodeArg arg[], static void translate_xsr(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { - TCGv_i32 tmp = tcg_temp_new_i32(); + if (sr_name[par[0]]) { + TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_mov_i32(tmp, arg[0].in); - tcg_gen_mov_i32(arg[0].out, cpu_SR[par[0]]); - tcg_gen_mov_i32(cpu_SR[par[0]], tmp); - tcg_temp_free(tmp); + tcg_gen_mov_i32(tmp, arg[0].in); + tcg_gen_mov_i32(arg[0].out, cpu_SR[par[0]]); + tcg_gen_mov_i32(cpu_SR[par[0]], tmp); + tcg_temp_free(tmp); + } else { + tcg_gen_movi_i32(arg[0].out, 0); + } } static void translate_xsr_mask(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { - TCGv_i32 tmp = tcg_temp_new_i32(); + if (sr_name[par[0]]) { + TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_mov_i32(tmp, arg[0].in); - tcg_gen_mov_i32(arg[0].out, cpu_SR[par[0]]); - tcg_gen_andi_i32(cpu_SR[par[0]], tmp, par[2]); - tcg_temp_free(tmp); + tcg_gen_mov_i32(tmp, arg[0].in); + tcg_gen_mov_i32(arg[0].out, cpu_SR[par[0]]); + tcg_gen_andi_i32(cpu_SR[par[0]], tmp, par[2]); + tcg_temp_free(tmp); + } else { + tcg_gen_movi_i32(arg[0].out, 0); + } } static void translate_xsr_ccount(DisasContext *dc, const OpcodeArg arg[], @@ -2819,7 +2897,11 @@ static void translate_xsr_ccount(DisasContext *dc, const OpcodeArg arg[], { \ TCGv_i32 tmp = tcg_temp_new_i32(); \ \ - tcg_gen_mov_i32(tmp, cpu_SR[par[0]]); \ + if (sr_name[par[0]]) { \ + tcg_gen_mov_i32(tmp, cpu_SR[par[0]]); \ + } else { \ + tcg_gen_movi_i32(tmp, 0); \ + } \ translate_wsr_##name(dc, arg, par); \ tcg_gen_mov_i32(arg[0].out, tmp); \ tcg_temp_free(tmp); \ @@ -3214,7 +3296,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "entry", .translate = translate_entry, - .test_ill = test_ill_entry, + .test_exceptions = test_exceptions_entry, .test_overflow = test_overflow_entry, .op_flags = XTENSA_OP_EXIT_TB_M1 | XTENSA_OP_SYNC_REGISTER_WINDOW, @@ -3789,7 +3871,7 @@ static const XtensaOpcodeOps core_ops[] = { "retw", "retw.n", NULL, }, .translate = translate_retw, - .test_ill = test_ill_retw, + .test_exceptions = test_exceptions_retw, .op_flags = XTENSA_OP_UNDERFLOW | XTENSA_OP_NAME_ARRAY, }, { .name = "rfdd", @@ -3863,7 +3945,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.acchi", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ACCHI, XTENSA_OPTION_MAC16, @@ -3871,7 +3953,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.acclo", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ACCLO, XTENSA_OPTION_MAC16, @@ -3879,7 +3961,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.atomctl", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ATOMCTL, XTENSA_OPTION_ATOMCTL, @@ -3888,7 +3970,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.br", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ BR, XTENSA_OPTION_BOOLEAN, @@ -3896,7 +3978,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.cacheadrdis", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ CACHEADRDIS, XTENSA_OPTION_MPU, @@ -3905,7 +3987,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.cacheattr", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ CACHEATTR, XTENSA_OPTION_CACHEATTR, @@ -3914,7 +3996,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.ccompare0", .translate = translate_rsr, - .test_ill = test_ill_ccompare, + .test_exceptions = test_exceptions_ccompare, .par = (const uint32_t[]){ CCOMPARE, XTENSA_OPTION_TIMER_INTERRUPT, @@ -3923,7 +4005,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.ccompare1", .translate = translate_rsr, - .test_ill = test_ill_ccompare, + .test_exceptions = test_exceptions_ccompare, .par = (const uint32_t[]){ CCOMPARE + 1, XTENSA_OPTION_TIMER_INTERRUPT, @@ -3932,7 +4014,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.ccompare2", .translate = translate_rsr, - .test_ill = test_ill_ccompare, + .test_exceptions = test_exceptions_ccompare, .par = (const uint32_t[]){ CCOMPARE + 2, XTENSA_OPTION_TIMER_INTERRUPT, @@ -3941,7 +4023,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.ccount", .translate = translate_rsr_ccount, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ CCOUNT, XTENSA_OPTION_TIMER_INTERRUPT, @@ -3960,7 +4042,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.cpenable", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ CPENABLE, XTENSA_OPTION_COPROCESSOR, @@ -3969,7 +4051,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.dbreaka0", .translate = translate_rsr, - .test_ill = test_ill_dbreak, + .test_exceptions = test_exceptions_dbreak, .par = (const uint32_t[]){ DBREAKA, XTENSA_OPTION_DEBUG, @@ -3978,7 +4060,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.dbreaka1", .translate = translate_rsr, - .test_ill = test_ill_dbreak, + .test_exceptions = test_exceptions_dbreak, .par = (const uint32_t[]){ DBREAKA + 1, XTENSA_OPTION_DEBUG, @@ -3987,7 +4069,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.dbreakc0", .translate = translate_rsr, - .test_ill = test_ill_dbreak, + .test_exceptions = test_exceptions_dbreak, .par = (const uint32_t[]){ DBREAKC, XTENSA_OPTION_DEBUG, @@ -3996,7 +4078,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.dbreakc1", .translate = translate_rsr, - .test_ill = test_ill_dbreak, + .test_exceptions = test_exceptions_dbreak, .par = (const uint32_t[]){ DBREAKC + 1, XTENSA_OPTION_DEBUG, @@ -4005,7 +4087,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.ddr", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ DDR, XTENSA_OPTION_DEBUG, @@ -4014,7 +4096,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.debugcause", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ DEBUGCAUSE, XTENSA_OPTION_DEBUG, @@ -4023,7 +4105,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.depc", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ DEPC, XTENSA_OPTION_EXCEPTION, @@ -4032,7 +4114,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.dtlbcfg", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ DTLBCFG, XTENSA_OPTION_MMU, @@ -4041,7 +4123,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.epc1", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ EPC1, XTENSA_OPTION_EXCEPTION, @@ -4050,7 +4132,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.epc2", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 1, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4059,7 +4141,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.epc3", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 2, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4068,7 +4150,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.epc4", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 3, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4077,7 +4159,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.epc5", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 4, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4086,7 +4168,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.epc6", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 5, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4095,7 +4177,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.epc7", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 6, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4104,7 +4186,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.eps2", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4113,7 +4195,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.eps3", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2 + 1, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4122,7 +4204,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.eps4", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2 + 2, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4131,7 +4213,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.eps5", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2 + 3, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4140,7 +4222,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.eps6", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2 + 4, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4149,7 +4231,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.eps7", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2 + 5, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4163,7 +4245,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.exccause", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ EXCCAUSE, XTENSA_OPTION_EXCEPTION, @@ -4172,7 +4254,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.excsave1", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ EXCSAVE1, XTENSA_OPTION_EXCEPTION, @@ -4181,7 +4263,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.excsave2", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 1, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4190,7 +4272,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.excsave3", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 2, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4199,7 +4281,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.excsave4", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 3, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4208,7 +4290,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.excsave5", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 4, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4217,7 +4299,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.excsave6", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 5, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4226,7 +4308,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.excsave7", .translate = translate_rsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 6, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4235,7 +4317,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.excvaddr", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ EXCVADDR, XTENSA_OPTION_EXCEPTION, @@ -4244,7 +4326,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.ibreaka0", .translate = translate_rsr, - .test_ill = test_ill_ibreak, + .test_exceptions = test_exceptions_ibreak, .par = (const uint32_t[]){ IBREAKA, XTENSA_OPTION_DEBUG, @@ -4253,7 +4335,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.ibreaka1", .translate = translate_rsr, - .test_ill = test_ill_ibreak, + .test_exceptions = test_exceptions_ibreak, .par = (const uint32_t[]){ IBREAKA + 1, XTENSA_OPTION_DEBUG, @@ -4262,7 +4344,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.ibreakenable", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ IBREAKENABLE, XTENSA_OPTION_DEBUG, @@ -4271,7 +4353,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.icount", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ICOUNT, XTENSA_OPTION_DEBUG, @@ -4280,7 +4362,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.icountlevel", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ICOUNTLEVEL, XTENSA_OPTION_DEBUG, @@ -4289,7 +4371,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.intclear", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ INTCLEAR, XTENSA_OPTION_INTERRUPT, @@ -4298,7 +4380,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.intenable", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ INTENABLE, XTENSA_OPTION_INTERRUPT, @@ -4307,7 +4389,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.interrupt", .translate = translate_rsr_ccount, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ INTSET, XTENSA_OPTION_INTERRUPT, @@ -4316,7 +4398,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.intset", .translate = translate_rsr_ccount, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ INTSET, XTENSA_OPTION_INTERRUPT, @@ -4325,7 +4407,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.itlbcfg", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ITLBCFG, XTENSA_OPTION_MMU, @@ -4334,7 +4416,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.lbeg", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ LBEG, XTENSA_OPTION_LOOP, @@ -4342,7 +4424,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.lcount", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ LCOUNT, XTENSA_OPTION_LOOP, @@ -4350,7 +4432,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.lend", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ LEND, XTENSA_OPTION_LOOP, @@ -4358,7 +4440,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.litbase", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ LITBASE, XTENSA_OPTION_EXTENDED_L32R, @@ -4366,7 +4448,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.m0", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MR, XTENSA_OPTION_MAC16, @@ -4374,7 +4456,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.m1", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MR + 1, XTENSA_OPTION_MAC16, @@ -4382,7 +4464,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.m2", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MR + 2, XTENSA_OPTION_MAC16, @@ -4390,7 +4472,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.m3", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MR + 3, XTENSA_OPTION_MAC16, @@ -4403,7 +4485,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.mecr", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MECR, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -4412,7 +4494,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.mepc", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MEPC, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -4421,7 +4503,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.meps", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MEPS, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -4430,7 +4512,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.mesave", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MESAVE, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -4439,7 +4521,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.mesr", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MESR, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -4448,7 +4530,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.mevaddr", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MESR, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -4457,7 +4539,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.misc0", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MISC, XTENSA_OPTION_MISC_SR, @@ -4466,7 +4548,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.misc1", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MISC + 1, XTENSA_OPTION_MISC_SR, @@ -4475,7 +4557,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.misc2", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MISC + 2, XTENSA_OPTION_MISC_SR, @@ -4484,7 +4566,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.misc3", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MISC + 3, XTENSA_OPTION_MISC_SR, @@ -4493,7 +4575,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.mpucfg", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MPUCFG, XTENSA_OPTION_MPU, @@ -4502,7 +4584,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.mpuenb", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MPUENB, XTENSA_OPTION_MPU, @@ -4515,7 +4597,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.prid", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ PRID, XTENSA_OPTION_PROCESSOR_ID, @@ -4524,7 +4606,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.ps", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ PS, XTENSA_OPTION_EXCEPTION, @@ -4533,7 +4615,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.ptevaddr", .translate = translate_rsr_ptevaddr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ PTEVADDR, XTENSA_OPTION_MMU, @@ -4542,7 +4624,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.rasid", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ RASID, XTENSA_OPTION_MMU, @@ -4555,7 +4637,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.scompare1", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ SCOMPARE1, XTENSA_OPTION_CONDITIONAL_STORE, @@ -4563,7 +4645,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.vecbase", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ VECBASE, XTENSA_OPTION_RELOCATABLE_VECTOR, @@ -4572,7 +4654,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.windowbase", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ WINDOW_BASE, XTENSA_OPTION_WINDOWED_REGISTER, @@ -4581,7 +4663,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.windowstart", .translate = translate_rsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ WINDOW_START, XTENSA_OPTION_WINDOWED_REGISTER, @@ -4594,16 +4676,6 @@ static const XtensaOpcodeOps core_ops[] = { .name = "rur.expstate", .translate = translate_rur, .par = (const uint32_t[]){EXPSTATE}, - }, { - .name = "rur.fcr", - .translate = translate_rur, - .par = (const uint32_t[]){FCR}, - .coprocessor = 0x1, - }, { - .name = "rur.fsr", - .translate = translate_rur, - .par = (const uint32_t[]){FSR}, - .coprocessor = 0x1, }, { .name = "rur.threadptr", .translate = translate_rur, @@ -4659,7 +4731,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "simcall", .translate = translate_simcall, - .test_ill = test_ill_simcall, + .test_exceptions = test_exceptions_simcall, .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "sll", @@ -4765,7 +4837,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.acchi", .translate = translate_wsr_acchi, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ACCHI, XTENSA_OPTION_MAC16, @@ -4773,7 +4845,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.acclo", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ACCLO, XTENSA_OPTION_MAC16, @@ -4781,7 +4853,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.atomctl", .translate = translate_wsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ATOMCTL, XTENSA_OPTION_ATOMCTL, @@ -4791,7 +4863,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.br", .translate = translate_wsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ BR, XTENSA_OPTION_BOOLEAN, @@ -4800,7 +4872,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.cacheadrdis", .translate = translate_wsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ CACHEADRDIS, XTENSA_OPTION_MPU, @@ -4810,7 +4882,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.cacheattr", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ CACHEATTR, XTENSA_OPTION_CACHEATTR, @@ -4819,7 +4891,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.ccompare0", .translate = translate_wsr_ccompare, - .test_ill = test_ill_ccompare, + .test_exceptions = test_exceptions_ccompare, .par = (const uint32_t[]){ CCOMPARE, XTENSA_OPTION_TIMER_INTERRUPT, @@ -4828,7 +4900,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.ccompare1", .translate = translate_wsr_ccompare, - .test_ill = test_ill_ccompare, + .test_exceptions = test_exceptions_ccompare, .par = (const uint32_t[]){ CCOMPARE + 1, XTENSA_OPTION_TIMER_INTERRUPT, @@ -4837,7 +4909,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.ccompare2", .translate = translate_wsr_ccompare, - .test_ill = test_ill_ccompare, + .test_exceptions = test_exceptions_ccompare, .par = (const uint32_t[]){ CCOMPARE + 2, XTENSA_OPTION_TIMER_INTERRUPT, @@ -4846,7 +4918,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.ccount", .translate = translate_wsr_ccount, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ CCOUNT, XTENSA_OPTION_TIMER_INTERRUPT, @@ -4861,7 +4933,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.cpenable", .translate = translate_wsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ CPENABLE, XTENSA_OPTION_COPROCESSOR, @@ -4871,7 +4943,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.dbreaka0", .translate = translate_wsr_dbreaka, - .test_ill = test_ill_dbreak, + .test_exceptions = test_exceptions_dbreak, .par = (const uint32_t[]){ DBREAKA, XTENSA_OPTION_DEBUG, @@ -4880,7 +4952,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.dbreaka1", .translate = translate_wsr_dbreaka, - .test_ill = test_ill_dbreak, + .test_exceptions = test_exceptions_dbreak, .par = (const uint32_t[]){ DBREAKA + 1, XTENSA_OPTION_DEBUG, @@ -4889,7 +4961,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.dbreakc0", .translate = translate_wsr_dbreakc, - .test_ill = test_ill_dbreak, + .test_exceptions = test_exceptions_dbreak, .par = (const uint32_t[]){ DBREAKC, XTENSA_OPTION_DEBUG, @@ -4898,7 +4970,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.dbreakc1", .translate = translate_wsr_dbreakc, - .test_ill = test_ill_dbreak, + .test_exceptions = test_exceptions_dbreak, .par = (const uint32_t[]){ DBREAKC + 1, XTENSA_OPTION_DEBUG, @@ -4907,7 +4979,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.ddr", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ DDR, XTENSA_OPTION_DEBUG, @@ -4919,7 +4991,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.depc", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ DEPC, XTENSA_OPTION_EXCEPTION, @@ -4928,7 +5000,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.dtlbcfg", .translate = translate_wsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ DTLBCFG, XTENSA_OPTION_MMU, @@ -4938,7 +5010,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.epc1", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ EPC1, XTENSA_OPTION_EXCEPTION, @@ -4947,7 +5019,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.epc2", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 1, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4956,7 +5028,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.epc3", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 2, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4965,7 +5037,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.epc4", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 3, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4974,7 +5046,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.epc5", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 4, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4983,7 +5055,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.epc6", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 5, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -4992,7 +5064,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.epc7", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 6, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5001,7 +5073,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.eps2", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5010,7 +5082,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.eps3", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2 + 1, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5019,7 +5091,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.eps4", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2 + 2, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5028,7 +5100,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.eps5", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2 + 3, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5037,7 +5109,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.eps6", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2 + 4, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5046,7 +5118,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.eps7", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2 + 5, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5064,7 +5136,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.exccause", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ EXCCAUSE, XTENSA_OPTION_EXCEPTION, @@ -5073,7 +5145,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.excsave1", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ EXCSAVE1, XTENSA_OPTION_EXCEPTION, @@ -5082,7 +5154,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.excsave2", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 1, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5091,7 +5163,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.excsave3", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 2, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5100,7 +5172,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.excsave4", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 3, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5109,7 +5181,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.excsave5", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 4, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5118,7 +5190,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.excsave6", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 5, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5127,7 +5199,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.excsave7", .translate = translate_wsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 6, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5136,7 +5208,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.excvaddr", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ EXCVADDR, XTENSA_OPTION_EXCEPTION, @@ -5145,7 +5217,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.ibreaka0", .translate = translate_wsr_ibreaka, - .test_ill = test_ill_ibreak, + .test_exceptions = test_exceptions_ibreak, .par = (const uint32_t[]){ IBREAKA, XTENSA_OPTION_DEBUG, @@ -5154,7 +5226,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.ibreaka1", .translate = translate_wsr_ibreaka, - .test_ill = test_ill_ibreak, + .test_exceptions = test_exceptions_ibreak, .par = (const uint32_t[]){ IBREAKA + 1, XTENSA_OPTION_DEBUG, @@ -5163,7 +5235,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.ibreakenable", .translate = translate_wsr_ibreakenable, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ IBREAKENABLE, XTENSA_OPTION_DEBUG, @@ -5172,7 +5244,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.icount", .translate = translate_wsr_icount, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ICOUNT, XTENSA_OPTION_DEBUG, @@ -5181,7 +5253,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.icountlevel", .translate = translate_wsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ICOUNTLEVEL, XTENSA_OPTION_DEBUG, @@ -5191,7 +5263,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.intclear", .translate = translate_wsr_intclear, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ INTCLEAR, XTENSA_OPTION_INTERRUPT, @@ -5203,7 +5275,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.intenable", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ INTENABLE, XTENSA_OPTION_INTERRUPT, @@ -5215,7 +5287,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.interrupt", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ INTSET, XTENSA_OPTION_INTERRUPT, @@ -5227,7 +5299,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.intset", .translate = translate_wsr_intset, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ INTSET, XTENSA_OPTION_INTERRUPT, @@ -5239,7 +5311,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.itlbcfg", .translate = translate_wsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ITLBCFG, XTENSA_OPTION_MMU, @@ -5249,7 +5321,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.lbeg", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ LBEG, XTENSA_OPTION_LOOP, @@ -5258,7 +5330,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.lcount", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ LCOUNT, XTENSA_OPTION_LOOP, @@ -5266,7 +5338,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.lend", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ LEND, XTENSA_OPTION_LOOP, @@ -5275,7 +5347,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.litbase", .translate = translate_wsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ LITBASE, XTENSA_OPTION_EXTENDED_L32R, @@ -5285,7 +5357,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.m0", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MR, XTENSA_OPTION_MAC16, @@ -5293,7 +5365,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.m1", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MR + 1, XTENSA_OPTION_MAC16, @@ -5301,7 +5373,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.m2", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MR + 2, XTENSA_OPTION_MAC16, @@ -5309,7 +5381,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.m3", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MR + 3, XTENSA_OPTION_MAC16, @@ -5322,7 +5394,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.mecr", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MECR, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -5331,7 +5403,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.mepc", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MEPC, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -5340,7 +5412,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.meps", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MEPS, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -5349,7 +5421,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.mesave", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MESAVE, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -5358,7 +5430,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.mesr", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MESR, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -5367,7 +5439,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.mevaddr", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MESR, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -5376,7 +5448,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.misc0", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MISC, XTENSA_OPTION_MISC_SR, @@ -5385,7 +5457,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.misc1", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MISC + 1, XTENSA_OPTION_MISC_SR, @@ -5394,7 +5466,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.misc2", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MISC + 2, XTENSA_OPTION_MISC_SR, @@ -5403,7 +5475,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.misc3", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MISC + 3, XTENSA_OPTION_MISC_SR, @@ -5412,7 +5484,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.mmid", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MMID, XTENSA_OPTION_TRACE_PORT, @@ -5421,7 +5493,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.mpuenb", .translate = translate_wsr_mpuenb, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MPUENB, XTENSA_OPTION_MPU, @@ -5437,7 +5509,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.ps", .translate = translate_wsr_ps, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ PS, XTENSA_OPTION_EXCEPTION, @@ -5449,7 +5521,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.ptevaddr", .translate = translate_wsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ PTEVADDR, XTENSA_OPTION_MMU, @@ -5459,7 +5531,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.rasid", .translate = translate_wsr_rasid, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ RASID, XTENSA_OPTION_MMU, @@ -5472,7 +5544,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.scompare1", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ SCOMPARE1, XTENSA_OPTION_CONDITIONAL_STORE, @@ -5480,7 +5552,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.vecbase", .translate = translate_wsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ VECBASE, XTENSA_OPTION_RELOCATABLE_VECTOR, @@ -5489,7 +5561,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.windowbase", .translate = translate_wsr_windowbase, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ WINDOW_BASE, XTENSA_OPTION_WINDOWED_REGISTER, @@ -5500,7 +5572,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.windowstart", .translate = translate_wsr_windowstart, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ WINDOW_START, XTENSA_OPTION_WINDOWED_REGISTER, @@ -5510,16 +5582,6 @@ static const XtensaOpcodeOps core_ops[] = { .name = "wur.expstate", .translate = translate_wur, .par = (const uint32_t[]){EXPSTATE}, - }, { - .name = "wur.fcr", - .translate = translate_wur_fcr, - .par = (const uint32_t[]){FCR}, - .coprocessor = 0x1, - }, { - .name = "wur.fsr", - .translate = translate_wur_fsr, - .par = (const uint32_t[]){FSR}, - .coprocessor = 0x1, }, { .name = "wur.threadptr", .translate = translate_wur, @@ -5540,7 +5602,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.acchi", .translate = translate_xsr_acchi, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ACCHI, XTENSA_OPTION_MAC16, @@ -5548,7 +5610,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.acclo", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ACCLO, XTENSA_OPTION_MAC16, @@ -5556,7 +5618,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.atomctl", .translate = translate_xsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ATOMCTL, XTENSA_OPTION_ATOMCTL, @@ -5566,7 +5628,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.br", .translate = translate_xsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ BR, XTENSA_OPTION_BOOLEAN, @@ -5575,7 +5637,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.cacheadrdis", .translate = translate_xsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ CACHEADRDIS, XTENSA_OPTION_MPU, @@ -5585,7 +5647,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.cacheattr", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ CACHEATTR, XTENSA_OPTION_CACHEATTR, @@ -5594,7 +5656,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.ccompare0", .translate = translate_xsr_ccompare, - .test_ill = test_ill_ccompare, + .test_exceptions = test_exceptions_ccompare, .par = (const uint32_t[]){ CCOMPARE, XTENSA_OPTION_TIMER_INTERRUPT, @@ -5603,7 +5665,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.ccompare1", .translate = translate_xsr_ccompare, - .test_ill = test_ill_ccompare, + .test_exceptions = test_exceptions_ccompare, .par = (const uint32_t[]){ CCOMPARE + 1, XTENSA_OPTION_TIMER_INTERRUPT, @@ -5612,7 +5674,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.ccompare2", .translate = translate_xsr_ccompare, - .test_ill = test_ill_ccompare, + .test_exceptions = test_exceptions_ccompare, .par = (const uint32_t[]){ CCOMPARE + 2, XTENSA_OPTION_TIMER_INTERRUPT, @@ -5621,7 +5683,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.ccount", .translate = translate_xsr_ccount, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ CCOUNT, XTENSA_OPTION_TIMER_INTERRUPT, @@ -5636,7 +5698,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.cpenable", .translate = translate_xsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ CPENABLE, XTENSA_OPTION_COPROCESSOR, @@ -5646,7 +5708,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.dbreaka0", .translate = translate_xsr_dbreaka, - .test_ill = test_ill_dbreak, + .test_exceptions = test_exceptions_dbreak, .par = (const uint32_t[]){ DBREAKA, XTENSA_OPTION_DEBUG, @@ -5655,7 +5717,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.dbreaka1", .translate = translate_xsr_dbreaka, - .test_ill = test_ill_dbreak, + .test_exceptions = test_exceptions_dbreak, .par = (const uint32_t[]){ DBREAKA + 1, XTENSA_OPTION_DEBUG, @@ -5664,7 +5726,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.dbreakc0", .translate = translate_xsr_dbreakc, - .test_ill = test_ill_dbreak, + .test_exceptions = test_exceptions_dbreak, .par = (const uint32_t[]){ DBREAKC, XTENSA_OPTION_DEBUG, @@ -5673,7 +5735,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.dbreakc1", .translate = translate_xsr_dbreakc, - .test_ill = test_ill_dbreak, + .test_exceptions = test_exceptions_dbreak, .par = (const uint32_t[]){ DBREAKC + 1, XTENSA_OPTION_DEBUG, @@ -5682,7 +5744,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.ddr", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ DDR, XTENSA_OPTION_DEBUG, @@ -5694,7 +5756,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.depc", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ DEPC, XTENSA_OPTION_EXCEPTION, @@ -5703,7 +5765,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.dtlbcfg", .translate = translate_xsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ DTLBCFG, XTENSA_OPTION_MMU, @@ -5713,7 +5775,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.epc1", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ EPC1, XTENSA_OPTION_EXCEPTION, @@ -5722,7 +5784,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.epc2", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 1, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5731,7 +5793,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.epc3", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 2, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5740,7 +5802,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.epc4", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 3, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5749,7 +5811,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.epc5", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 4, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5758,7 +5820,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.epc6", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 5, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5767,7 +5829,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.epc7", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPC1 + 6, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5776,7 +5838,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.eps2", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5785,7 +5847,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.eps3", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2 + 1, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5794,7 +5856,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.eps4", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2 + 2, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5803,7 +5865,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.eps5", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2 + 3, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5812,7 +5874,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.eps6", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2 + 4, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5821,7 +5883,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.eps7", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EPS2 + 5, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5839,7 +5901,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.exccause", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ EXCCAUSE, XTENSA_OPTION_EXCEPTION, @@ -5848,7 +5910,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.excsave1", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ EXCSAVE1, XTENSA_OPTION_EXCEPTION, @@ -5857,7 +5919,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.excsave2", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 1, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5866,7 +5928,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.excsave3", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 2, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5875,7 +5937,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.excsave4", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 3, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5884,7 +5946,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.excsave5", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 4, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5893,7 +5955,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.excsave6", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 5, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5902,7 +5964,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.excsave7", .translate = translate_xsr, - .test_ill = test_ill_hpi, + .test_exceptions = test_exceptions_hpi, .par = (const uint32_t[]){ EXCSAVE1 + 6, XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, @@ -5911,7 +5973,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.excvaddr", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ EXCVADDR, XTENSA_OPTION_EXCEPTION, @@ -5920,7 +5982,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.ibreaka0", .translate = translate_xsr_ibreaka, - .test_ill = test_ill_ibreak, + .test_exceptions = test_exceptions_ibreak, .par = (const uint32_t[]){ IBREAKA, XTENSA_OPTION_DEBUG, @@ -5929,7 +5991,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.ibreaka1", .translate = translate_xsr_ibreaka, - .test_ill = test_ill_ibreak, + .test_exceptions = test_exceptions_ibreak, .par = (const uint32_t[]){ IBREAKA + 1, XTENSA_OPTION_DEBUG, @@ -5938,7 +6000,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.ibreakenable", .translate = translate_xsr_ibreakenable, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ IBREAKENABLE, XTENSA_OPTION_DEBUG, @@ -5947,7 +6009,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.icount", .translate = translate_xsr_icount, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ICOUNT, XTENSA_OPTION_DEBUG, @@ -5956,7 +6018,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.icountlevel", .translate = translate_xsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ICOUNTLEVEL, XTENSA_OPTION_DEBUG, @@ -5969,7 +6031,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.intenable", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ INTENABLE, XTENSA_OPTION_INTERRUPT, @@ -5987,7 +6049,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.itlbcfg", .translate = translate_xsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ ITLBCFG, XTENSA_OPTION_MMU, @@ -5997,7 +6059,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.lbeg", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ LBEG, XTENSA_OPTION_LOOP, @@ -6006,7 +6068,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.lcount", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ LCOUNT, XTENSA_OPTION_LOOP, @@ -6014,7 +6076,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.lend", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ LEND, XTENSA_OPTION_LOOP, @@ -6023,7 +6085,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.litbase", .translate = translate_xsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ LITBASE, XTENSA_OPTION_EXTENDED_L32R, @@ -6033,7 +6095,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.m0", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MR, XTENSA_OPTION_MAC16, @@ -6041,7 +6103,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.m1", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MR + 1, XTENSA_OPTION_MAC16, @@ -6049,7 +6111,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.m2", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MR + 2, XTENSA_OPTION_MAC16, @@ -6057,7 +6119,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.m3", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MR + 3, XTENSA_OPTION_MAC16, @@ -6070,7 +6132,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.mecr", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MECR, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -6079,7 +6141,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.mepc", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MEPC, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -6088,7 +6150,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.meps", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MEPS, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -6097,7 +6159,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.mesave", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MESAVE, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -6106,7 +6168,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.mesr", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MESR, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -6115,7 +6177,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.mevaddr", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MESR, XTENSA_OPTION_MEMORY_ECC_PARITY, @@ -6124,7 +6186,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.misc0", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MISC, XTENSA_OPTION_MISC_SR, @@ -6133,7 +6195,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.misc1", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MISC + 1, XTENSA_OPTION_MISC_SR, @@ -6142,7 +6204,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.misc2", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MISC + 2, XTENSA_OPTION_MISC_SR, @@ -6151,7 +6213,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.misc3", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MISC + 3, XTENSA_OPTION_MISC_SR, @@ -6160,7 +6222,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.mpuenb", .translate = translate_xsr_mpuenb, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ MPUENB, XTENSA_OPTION_MPU, @@ -6176,7 +6238,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.ps", .translate = translate_xsr_ps, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ PS, XTENSA_OPTION_EXCEPTION, @@ -6188,7 +6250,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.ptevaddr", .translate = translate_xsr_mask, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ PTEVADDR, XTENSA_OPTION_MMU, @@ -6198,7 +6260,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.rasid", .translate = translate_xsr_rasid, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ RASID, XTENSA_OPTION_MMU, @@ -6211,7 +6273,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.scompare1", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ SCOMPARE1, XTENSA_OPTION_CONDITIONAL_STORE, @@ -6219,7 +6281,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.vecbase", .translate = translate_xsr, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ VECBASE, XTENSA_OPTION_RELOCATABLE_VECTOR, @@ -6228,7 +6290,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.windowbase", .translate = translate_xsr_windowbase, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ WINDOW_BASE, XTENSA_OPTION_WINDOWED_REGISTER, @@ -6239,7 +6301,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.windowstart", .translate = translate_xsr_windowstart, - .test_ill = test_ill_sr, + .test_exceptions = test_exceptions_sr, .par = (const uint32_t[]){ WINDOW_START, XTENSA_OPTION_WINDOWED_REGISTER, @@ -6254,17 +6316,145 @@ const XtensaOpcodeTranslators xtensa_core_opcodes = { }; -static void translate_abs_s(DisasContext *dc, const OpcodeArg arg[], +static inline void get_f32_o1_i3(const OpcodeArg *arg, OpcodeArg *arg32, + int o0, int i0, int i1, int i2) +{ + if ((i0 >= 0 && arg[i0].num_bits == 64) || + (o0 >= 0 && arg[o0].num_bits == 64)) { + if (o0 >= 0) { + arg32[o0].out = tcg_temp_new_i32(); + } + if (i0 >= 0) { + arg32[i0].in = tcg_temp_new_i32(); + tcg_gen_extrl_i64_i32(arg32[i0].in, arg[i0].in); + } + if (i1 >= 0) { + arg32[i1].in = tcg_temp_new_i32(); + tcg_gen_extrl_i64_i32(arg32[i1].in, arg[i1].in); + } + if (i2 >= 0) { + arg32[i2].in = tcg_temp_new_i32(); + tcg_gen_extrl_i64_i32(arg32[i2].in, arg[i2].in); + } + } else { + if (o0 >= 0) { + arg32[o0].out = arg[o0].out; + } + if (i0 >= 0) { + arg32[i0].in = arg[i0].in; + } + if (i1 >= 0) { + arg32[i1].in = arg[i1].in; + } + if (i2 >= 0) { + arg32[i2].in = arg[i2].in; + } + } +} + +static inline void put_f32_o1_i3(const OpcodeArg *arg, const OpcodeArg *arg32, + int o0, int i0, int i1, int i2) +{ + if ((i0 >= 0 && arg[i0].num_bits == 64) || + (o0 >= 0 && arg[o0].num_bits == 64)) { + if (o0 >= 0) { + tcg_gen_extu_i32_i64(arg[o0].out, arg32[o0].out); + tcg_temp_free_i32(arg32[o0].out); + } + if (i0 >= 0) { + tcg_temp_free_i32(arg32[i0].in); + } + if (i1 >= 0) { + tcg_temp_free_i32(arg32[i1].in); + } + if (i2 >= 0) { + tcg_temp_free_i32(arg32[i2].in); + } + } +} + +static inline void get_f32_o1_i2(const OpcodeArg *arg, OpcodeArg *arg32, + int o0, int i0, int i1) +{ + get_f32_o1_i3(arg, arg32, o0, i0, i1, -1); +} + +static inline void put_f32_o1_i2(const OpcodeArg *arg, const OpcodeArg *arg32, + int o0, int i0, int i1) +{ + put_f32_o1_i3(arg, arg32, o0, i0, i1, -1); +} + +static inline void get_f32_o1_i1(const OpcodeArg *arg, OpcodeArg *arg32, + int o0, int i0) +{ + get_f32_o1_i2(arg, arg32, o0, i0, -1); +} + +static inline void put_f32_o1_i1(const OpcodeArg *arg, const OpcodeArg *arg32, + int o0, int i0) +{ + put_f32_o1_i2(arg, arg32, o0, i0, -1); +} + +static inline void get_f32_o1(const OpcodeArg *arg, OpcodeArg *arg32, + int o0) +{ + get_f32_o1_i1(arg, arg32, o0, -1); +} + +static inline void put_f32_o1(const OpcodeArg *arg, const OpcodeArg *arg32, + int o0) +{ + put_f32_o1_i1(arg, arg32, o0, -1); +} + +static inline void get_f32_i2(const OpcodeArg *arg, OpcodeArg *arg32, + int i0, int i1) +{ + get_f32_o1_i2(arg, arg32, -1, i0, i1); +} + +static inline void put_f32_i2(const OpcodeArg *arg, const OpcodeArg *arg32, + int i0, int i1) +{ + put_f32_o1_i2(arg, arg32, -1, i0, i1); +} + +static inline void get_f32_i1(const OpcodeArg *arg, OpcodeArg *arg32, + int i0) +{ + get_f32_i2(arg, arg32, i0, -1); +} + +static inline void put_f32_i1(const OpcodeArg *arg, const OpcodeArg *arg32, + int i0) +{ + put_f32_i2(arg, arg32, i0, -1); +} + + +static void translate_abs_d(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { - gen_helper_abs_s(arg[0].out, arg[1].in); + gen_helper_abs_d(arg[0].out, arg[1].in); } -static void translate_add_s(DisasContext *dc, const OpcodeArg arg[], +static void translate_abs_s(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { - gen_helper_add_s(arg[0].out, cpu_env, - arg[1].in, arg[2].in); + OpcodeArg arg32[2]; + + get_f32_o1_i1(arg, arg32, 0, 1); + gen_helper_abs_s(arg32[0].out, arg32[1].in); + put_f32_o1_i1(arg, arg32, 0, 1); +} + +static void translate_fpu2k_add_s(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + gen_helper_fpu2k_add_s(arg[0].out, cpu_env, + arg[1].in, arg[2].in); } enum { @@ -6277,10 +6467,41 @@ enum { COMPARE_ULE, }; +static void translate_compare_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + static void (* const helper[])(TCGv_i32 res, TCGv_env env, + TCGv_i64 s, TCGv_i64 t) = { + [COMPARE_UN] = gen_helper_un_d, + [COMPARE_OEQ] = gen_helper_oeq_d, + [COMPARE_UEQ] = gen_helper_ueq_d, + [COMPARE_OLT] = gen_helper_olt_d, + [COMPARE_ULT] = gen_helper_ult_d, + [COMPARE_OLE] = gen_helper_ole_d, + [COMPARE_ULE] = gen_helper_ule_d, + }; + TCGv_i32 zero = tcg_const_i32(0); + TCGv_i32 res = tcg_temp_new_i32(); + TCGv_i32 set_br = tcg_temp_new_i32(); + TCGv_i32 clr_br = tcg_temp_new_i32(); + + tcg_gen_ori_i32(set_br, arg[0].in, 1 << arg[0].imm); + tcg_gen_andi_i32(clr_br, arg[0].in, ~(1 << arg[0].imm)); + + helper[par[0]](res, cpu_env, arg[1].in, arg[2].in); + tcg_gen_movcond_i32(TCG_COND_NE, + arg[0].out, res, zero, + set_br, clr_br); + tcg_temp_free(zero); + tcg_temp_free(res); + tcg_temp_free(set_br); + tcg_temp_free(clr_br); +} + static void translate_compare_s(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { - static void (* const helper[])(TCGv_env env, TCGv_i32 bit, + static void (* const helper[])(TCGv_i32 res, TCGv_env env, TCGv_i32 s, TCGv_i32 t) = { [COMPARE_UN] = gen_helper_un_s, [COMPARE_OEQ] = gen_helper_oeq_s, @@ -6290,22 +6511,110 @@ static void translate_compare_s(DisasContext *dc, const OpcodeArg arg[], [COMPARE_OLE] = gen_helper_ole_s, [COMPARE_ULE] = gen_helper_ule_s, }; - TCGv_i32 bit = tcg_const_i32(1 << arg[0].imm); + OpcodeArg arg32[3]; + TCGv_i32 zero = tcg_const_i32(0); + TCGv_i32 res = tcg_temp_new_i32(); + TCGv_i32 set_br = tcg_temp_new_i32(); + TCGv_i32 clr_br = tcg_temp_new_i32(); + + tcg_gen_ori_i32(set_br, arg[0].in, 1 << arg[0].imm); + tcg_gen_andi_i32(clr_br, arg[0].in, ~(1 << arg[0].imm)); + + get_f32_i2(arg, arg32, 1, 2); + helper[par[0]](res, cpu_env, arg32[1].in, arg32[2].in); + tcg_gen_movcond_i32(TCG_COND_NE, + arg[0].out, res, zero, + set_br, clr_br); + put_f32_i2(arg, arg32, 1, 2); + tcg_temp_free(zero); + tcg_temp_free(res); + tcg_temp_free(set_br); + tcg_temp_free(clr_br); +} + +static void translate_const_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + static const uint64_t v[] = { + UINT64_C(0x0000000000000000), + UINT64_C(0x3ff0000000000000), + UINT64_C(0x4000000000000000), + UINT64_C(0x3fe0000000000000), + }; - helper[par[0]](cpu_env, bit, arg[1].in, arg[2].in); - tcg_temp_free(bit); + tcg_gen_movi_i64(arg[0].out, v[arg[1].imm % ARRAY_SIZE(v)]); + if (arg[1].imm >= ARRAY_SIZE(v)) { + qemu_log_mask(LOG_GUEST_ERROR, + "const.d f%d, #%d, immediate value is reserved\n", + arg[0].imm, arg[1].imm); + } +} + +static void translate_const_s(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + static const uint32_t v[] = { + 0x00000000, + 0x3f800000, + 0x40000000, + 0x3f000000, + }; + + if (arg[0].num_bits == 32) { + tcg_gen_movi_i32(arg[0].out, v[arg[1].imm % ARRAY_SIZE(v)]); + } else { + tcg_gen_movi_i64(arg[0].out, v[arg[1].imm % ARRAY_SIZE(v)]); + } + if (arg[1].imm >= ARRAY_SIZE(v)) { + qemu_log_mask(LOG_GUEST_ERROR, + "const.s f%d, #%d, immediate value is reserved\n", + arg[0].imm, arg[1].imm); + } +} + +static void translate_float_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + TCGv_i32 scale = tcg_const_i32(-arg[2].imm); + + if (par[0]) { + gen_helper_uitof_d(arg[0].out, cpu_env, arg[1].in, scale); + } else { + gen_helper_itof_d(arg[0].out, cpu_env, arg[1].in, scale); + } + tcg_temp_free(scale); } static void translate_float_s(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { TCGv_i32 scale = tcg_const_i32(-arg[2].imm); + OpcodeArg arg32[1]; + get_f32_o1(arg, arg32, 0); if (par[0]) { - gen_helper_uitof(arg[0].out, cpu_env, arg[1].in, scale); + gen_helper_uitof_s(arg32[0].out, cpu_env, arg[1].in, scale); + } else { + gen_helper_itof_s(arg32[0].out, cpu_env, arg[1].in, scale); + } + put_f32_o1(arg, arg32, 0); + tcg_temp_free(scale); +} + +static void translate_ftoi_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + TCGv_i32 rounding_mode = tcg_const_i32(par[0]); + TCGv_i32 scale = tcg_const_i32(arg[2].imm); + + if (par[1]) { + gen_helper_ftoui_d(arg[0].out, cpu_env, arg[1].in, + rounding_mode, scale); } else { - gen_helper_itof(arg[0].out, cpu_env, arg[1].in, scale); + gen_helper_ftoi_d(arg[0].out, cpu_env, arg[1].in, + rounding_mode, scale); } + tcg_temp_free(rounding_mode); tcg_temp_free(scale); } @@ -6314,14 +6623,17 @@ static void translate_ftoi_s(DisasContext *dc, const OpcodeArg arg[], { TCGv_i32 rounding_mode = tcg_const_i32(par[0]); TCGv_i32 scale = tcg_const_i32(arg[2].imm); + OpcodeArg arg32[2]; + get_f32_i1(arg, arg32, 1); if (par[1]) { - gen_helper_ftoui(arg[0].out, arg[1].in, - rounding_mode, scale); + gen_helper_ftoui_s(arg[0].out, cpu_env, arg32[1].in, + rounding_mode, scale); } else { - gen_helper_ftoi(arg[0].out, arg[1].in, - rounding_mode, scale); + gen_helper_ftoi_s(arg[0].out, cpu_env, arg32[1].in, + rounding_mode, scale); } + put_f32_i1(arg, arg32, 1); tcg_temp_free(rounding_mode); tcg_temp_free(scale); } @@ -6362,81 +6674,172 @@ static void translate_ldstx(DisasContext *dc, const OpcodeArg arg[], tcg_temp_free(addr); } -static void translate_madd_s(DisasContext *dc, const OpcodeArg arg[], - const uint32_t par[]) +static void translate_fpu2k_madd_s(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) { - gen_helper_madd_s(arg[0].out, cpu_env, - arg[0].in, arg[1].in, arg[2].in); + gen_helper_fpu2k_madd_s(arg[0].out, cpu_env, + arg[0].in, arg[1].in, arg[2].in); +} + +static void translate_mov_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + tcg_gen_mov_i64(arg[0].out, arg[1].in); } static void translate_mov_s(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { - tcg_gen_mov_i32(arg[0].out, arg[1].in); + if (arg[0].num_bits == 32) { + tcg_gen_mov_i32(arg[0].out, arg[1].in); + } else { + tcg_gen_mov_i64(arg[0].out, arg[1].in); + } } -static void translate_movcond_s(DisasContext *dc, const OpcodeArg arg[], +static void translate_movcond_d(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { - TCGv_i32 zero = tcg_const_i32(0); + TCGv_i64 zero = tcg_const_i64(0); + TCGv_i64 arg2 = tcg_temp_new_i64(); - tcg_gen_movcond_i32(par[0], arg[0].out, - arg[2].in, zero, + tcg_gen_ext_i32_i64(arg2, arg[2].in); + tcg_gen_movcond_i64(par[0], arg[0].out, + arg2, zero, arg[1].in, arg[0].in); - tcg_temp_free(zero); + tcg_temp_free_i64(zero); + tcg_temp_free_i64(arg2); } -static void translate_movp_s(DisasContext *dc, const OpcodeArg arg[], - const uint32_t par[]) +static void translate_movcond_s(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) { - TCGv_i32 zero = tcg_const_i32(0); - TCGv_i32 tmp = tcg_temp_new_i32(); + if (arg[0].num_bits == 32) { + TCGv_i32 zero = tcg_const_i32(0); - tcg_gen_andi_i32(tmp, arg[2].in, 1 << arg[2].imm); - tcg_gen_movcond_i32(par[0], - arg[0].out, tmp, zero, - arg[1].in, arg[0].in); - tcg_temp_free(tmp); - tcg_temp_free(zero); + tcg_gen_movcond_i32(par[0], arg[0].out, + arg[2].in, zero, + arg[1].in, arg[0].in); + tcg_temp_free(zero); + } else { + translate_movcond_d(dc, arg, par); + } } -static void translate_mul_s(DisasContext *dc, const OpcodeArg arg[], - const uint32_t par[]) +static void translate_movp_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) { - gen_helper_mul_s(arg[0].out, cpu_env, - arg[1].in, arg[2].in); + TCGv_i64 zero = tcg_const_i64(0); + TCGv_i32 tmp1 = tcg_temp_new_i32(); + TCGv_i64 tmp2 = tcg_temp_new_i64(); + + tcg_gen_andi_i32(tmp1, arg[2].in, 1 << arg[2].imm); + tcg_gen_extu_i32_i64(tmp2, tmp1); + tcg_gen_movcond_i64(par[0], + arg[0].out, tmp2, zero, + arg[1].in, arg[0].in); + tcg_temp_free_i64(zero); + tcg_temp_free_i32(tmp1); + tcg_temp_free_i64(tmp2); } -static void translate_msub_s(DisasContext *dc, const OpcodeArg arg[], +static void translate_movp_s(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { - gen_helper_msub_s(arg[0].out, cpu_env, - arg[0].in, arg[1].in, arg[2].in); + if (arg[0].num_bits == 32) { + TCGv_i32 zero = tcg_const_i32(0); + TCGv_i32 tmp = tcg_temp_new_i32(); + + tcg_gen_andi_i32(tmp, arg[2].in, 1 << arg[2].imm); + tcg_gen_movcond_i32(par[0], + arg[0].out, tmp, zero, + arg[1].in, arg[0].in); + tcg_temp_free(tmp); + tcg_temp_free(zero); + } else { + translate_movp_d(dc, arg, par); + } +} + +static void translate_fpu2k_mul_s(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + gen_helper_fpu2k_mul_s(arg[0].out, cpu_env, + arg[1].in, arg[2].in); +} + +static void translate_fpu2k_msub_s(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + gen_helper_fpu2k_msub_s(arg[0].out, cpu_env, + arg[0].in, arg[1].in, arg[2].in); +} + +static void translate_neg_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + gen_helper_neg_d(arg[0].out, arg[1].in); } static void translate_neg_s(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { - gen_helper_neg_s(arg[0].out, arg[1].in); + OpcodeArg arg32[2]; + + get_f32_o1_i1(arg, arg32, 0, 1); + gen_helper_neg_s(arg32[0].out, arg32[1].in); + put_f32_o1_i1(arg, arg32, 0, 1); +} + +static void translate_rfr_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + tcg_gen_extrh_i64_i32(arg[0].out, arg[1].in); } static void translate_rfr_s(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { - tcg_gen_mov_i32(arg[0].out, arg[1].in); + if (arg[1].num_bits == 32) { + tcg_gen_mov_i32(arg[0].out, arg[1].in); + } else { + tcg_gen_extrl_i64_i32(arg[0].out, arg[1].in); + } } -static void translate_sub_s(DisasContext *dc, const OpcodeArg arg[], +static void translate_fpu2k_sub_s(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + gen_helper_fpu2k_sub_s(arg[0].out, cpu_env, + arg[1].in, arg[2].in); +} + +static void translate_wfr_d(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { - gen_helper_sub_s(arg[0].out, cpu_env, - arg[1].in, arg[2].in); + tcg_gen_concat_i32_i64(arg[0].out, arg[2].in, arg[1].in); } static void translate_wfr_s(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { - tcg_gen_mov_i32(arg[0].out, arg[1].in); + if (arg[0].num_bits == 32) { + tcg_gen_mov_i32(arg[0].out, arg[1].in); + } else { + tcg_gen_ext_i32_i64(arg[0].out, arg[1].in); + } +} + +static void translate_wur_fpu2k_fcr(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + gen_helper_wur_fpu2k_fcr(cpu_env, arg[0].in); +} + +static void translate_wur_fpu2k_fsr(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + tcg_gen_andi_i32(cpu_UR[par[0]], arg[0].in, 0xffffff80); } static const XtensaOpcodeOps fpu2000_ops[] = { @@ -6446,7 +6849,7 @@ static const XtensaOpcodeOps fpu2000_ops[] = { .coprocessor = 0x1, }, { .name = "add.s", - .translate = translate_add_s, + .translate = translate_fpu2k_add_s, .coprocessor = 0x1, }, { .name = "ceil.s", @@ -6489,7 +6892,7 @@ static const XtensaOpcodeOps fpu2000_ops[] = { .coprocessor = 0x1, }, { .name = "madd.s", - .translate = translate_madd_s, + .translate = translate_fpu2k_madd_s, .coprocessor = 0x1, }, { .name = "mov.s", @@ -6527,11 +6930,11 @@ static const XtensaOpcodeOps fpu2000_ops[] = { .coprocessor = 0x1, }, { .name = "msub.s", - .translate = translate_msub_s, + .translate = translate_fpu2k_msub_s, .coprocessor = 0x1, }, { .name = "mul.s", - .translate = translate_mul_s, + .translate = translate_fpu2k_mul_s, .coprocessor = 0x1, }, { .name = "neg.s", @@ -6561,6 +6964,16 @@ static const XtensaOpcodeOps fpu2000_ops[] = { .translate = translate_ftoi_s, .par = (const uint32_t[]){float_round_nearest_even, false}, .coprocessor = 0x1, + }, { + .name = "rur.fcr", + .translate = translate_rur, + .par = (const uint32_t[]){FCR}, + .coprocessor = 0x1, + }, { + .name = "rur.fsr", + .translate = translate_rur, + .par = (const uint32_t[]){FSR}, + .coprocessor = 0x1, }, { .name = "ssi", .translate = translate_ldsti, @@ -6587,7 +7000,7 @@ static const XtensaOpcodeOps fpu2000_ops[] = { .coprocessor = 0x1, }, { .name = "sub.s", - .translate = translate_sub_s, + .translate = translate_fpu2k_sub_s, .coprocessor = 0x1, }, { .name = "trunc.s", @@ -6628,6 +7041,16 @@ static const XtensaOpcodeOps fpu2000_ops[] = { .name = "wfr", .translate = translate_wfr_s, .coprocessor = 0x1, + }, { + .name = "wur.fcr", + .translate = translate_wur_fpu2k_fcr, + .par = (const uint32_t[]){FCR}, + .coprocessor = 0x1, + }, { + .name = "wur.fsr", + .translate = translate_wur_fpu2k_fsr, + .par = (const uint32_t[]){FSR}, + .coprocessor = 0x1, }, }; @@ -6635,3 +7058,847 @@ const XtensaOpcodeTranslators xtensa_fpu2000_opcodes = { .num_opcodes = ARRAY_SIZE(fpu2000_ops), .opcode = fpu2000_ops, }; + +static void translate_add_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + gen_helper_add_d(arg[0].out, cpu_env, arg[1].in, arg[2].in); +} + +static void translate_add_s(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + if (option_enabled(dc, XTENSA_OPTION_DFPU_SINGLE_ONLY)) { + gen_helper_fpu2k_add_s(arg[0].out, cpu_env, + arg[1].in, arg[2].in); + } else { + OpcodeArg arg32[3]; + + get_f32_o1_i2(arg, arg32, 0, 1, 2); + gen_helper_add_s(arg32[0].out, cpu_env, arg32[1].in, arg32[2].in); + put_f32_o1_i2(arg, arg32, 0, 1, 2); + } +} + +static void translate_cvtd_s(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + TCGv_i32 v = tcg_temp_new_i32(); + + tcg_gen_extrl_i64_i32(v, arg[1].in); + gen_helper_cvtd_s(arg[0].out, cpu_env, v); + tcg_temp_free_i32(v); +} + +static void translate_cvts_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + TCGv_i32 v = tcg_temp_new_i32(); + + gen_helper_cvts_d(v, cpu_env, arg[1].in); + tcg_gen_extu_i32_i64(arg[0].out, v); + tcg_temp_free_i32(v); +} + +static void translate_ldsti_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + TCGv_i32 addr; + + if (par[1]) { + addr = tcg_temp_new_i32(); + tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm); + } else { + addr = arg[1].in; + } + gen_load_store_alignment(dc, 3, addr, false); + if (par[0]) { + tcg_gen_qemu_st64(arg[0].in, addr, dc->cring); + } else { + tcg_gen_qemu_ld64(arg[0].out, addr, dc->cring); + } + if (par[2]) { + if (par[1]) { + tcg_gen_mov_i32(arg[1].out, addr); + } else { + tcg_gen_addi_i32(arg[1].out, arg[1].in, arg[2].imm); + } + } + if (par[1]) { + tcg_temp_free(addr); + } +} + +static void translate_ldsti_s(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + TCGv_i32 addr; + OpcodeArg arg32[1]; + + if (par[1]) { + addr = tcg_temp_new_i32(); + tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm); + } else { + addr = arg[1].in; + } + gen_load_store_alignment(dc, 2, addr, false); + if (par[0]) { + get_f32_i1(arg, arg32, 0); + tcg_gen_qemu_st32(arg32[0].in, addr, dc->cring); + put_f32_i1(arg, arg32, 0); + } else { + get_f32_o1(arg, arg32, 0); + tcg_gen_qemu_ld32u(arg32[0].out, addr, dc->cring); + put_f32_o1(arg, arg32, 0); + } + if (par[2]) { + if (par[1]) { + tcg_gen_mov_i32(arg[1].out, addr); + } else { + tcg_gen_addi_i32(arg[1].out, arg[1].in, arg[2].imm); + } + } + if (par[1]) { + tcg_temp_free(addr); + } +} + +static void translate_ldstx_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + TCGv_i32 addr; + + if (par[1]) { + addr = tcg_temp_new_i32(); + tcg_gen_add_i32(addr, arg[1].in, arg[2].in); + } else { + addr = arg[1].in; + } + gen_load_store_alignment(dc, 3, addr, false); + if (par[0]) { + tcg_gen_qemu_st64(arg[0].in, addr, dc->cring); + } else { + tcg_gen_qemu_ld64(arg[0].out, addr, dc->cring); + } + if (par[2]) { + if (par[1]) { + tcg_gen_mov_i32(arg[1].out, addr); + } else { + tcg_gen_add_i32(arg[1].out, arg[1].in, arg[2].in); + } + } + if (par[1]) { + tcg_temp_free(addr); + } +} + +static void translate_ldstx_s(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + TCGv_i32 addr; + OpcodeArg arg32[1]; + + if (par[1]) { + addr = tcg_temp_new_i32(); + tcg_gen_add_i32(addr, arg[1].in, arg[2].in); + } else { + addr = arg[1].in; + } + gen_load_store_alignment(dc, 2, addr, false); + if (par[0]) { + get_f32_i1(arg, arg32, 0); + tcg_gen_qemu_st32(arg32[0].in, addr, dc->cring); + put_f32_i1(arg, arg32, 0); + } else { + get_f32_o1(arg, arg32, 0); + tcg_gen_qemu_ld32u(arg32[0].out, addr, dc->cring); + put_f32_o1(arg, arg32, 0); + } + if (par[2]) { + if (par[1]) { + tcg_gen_mov_i32(arg[1].out, addr); + } else { + tcg_gen_add_i32(arg[1].out, arg[1].in, arg[2].in); + } + } + if (par[1]) { + tcg_temp_free(addr); + } +} + +static void translate_madd_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + gen_helper_madd_d(arg[0].out, cpu_env, + arg[0].in, arg[1].in, arg[2].in); +} + +static void translate_madd_s(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + if (option_enabled(dc, XTENSA_OPTION_DFPU_SINGLE_ONLY)) { + gen_helper_fpu2k_madd_s(arg[0].out, cpu_env, + arg[0].in, arg[1].in, arg[2].in); + } else { + OpcodeArg arg32[3]; + + get_f32_o1_i3(arg, arg32, 0, 0, 1, 2); + gen_helper_madd_s(arg32[0].out, cpu_env, + arg32[0].in, arg32[1].in, arg32[2].in); + put_f32_o1_i3(arg, arg32, 0, 0, 1, 2); + } +} + +static void translate_mul_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + gen_helper_mul_d(arg[0].out, cpu_env, arg[1].in, arg[2].in); +} + +static void translate_mul_s(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + if (option_enabled(dc, XTENSA_OPTION_DFPU_SINGLE_ONLY)) { + gen_helper_fpu2k_mul_s(arg[0].out, cpu_env, + arg[1].in, arg[2].in); + } else { + OpcodeArg arg32[3]; + + get_f32_o1_i2(arg, arg32, 0, 1, 2); + gen_helper_mul_s(arg32[0].out, cpu_env, arg32[1].in, arg32[2].in); + put_f32_o1_i2(arg, arg32, 0, 1, 2); + } +} + +static void translate_msub_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + gen_helper_msub_d(arg[0].out, cpu_env, + arg[0].in, arg[1].in, arg[2].in); +} + +static void translate_msub_s(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + if (option_enabled(dc, XTENSA_OPTION_DFPU_SINGLE_ONLY)) { + gen_helper_fpu2k_msub_s(arg[0].out, cpu_env, + arg[0].in, arg[1].in, arg[2].in); + } else { + OpcodeArg arg32[3]; + + get_f32_o1_i3(arg, arg32, 0, 0, 1, 2); + gen_helper_msub_s(arg32[0].out, cpu_env, + arg32[0].in, arg32[1].in, arg32[2].in); + put_f32_o1_i3(arg, arg32, 0, 0, 1, 2); + } +} + +static void translate_sub_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + gen_helper_sub_d(arg[0].out, cpu_env, arg[1].in, arg[2].in); +} + +static void translate_sub_s(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + if (option_enabled(dc, XTENSA_OPTION_DFPU_SINGLE_ONLY)) { + gen_helper_fpu2k_sub_s(arg[0].out, cpu_env, + arg[1].in, arg[2].in); + } else { + OpcodeArg arg32[3]; + + get_f32_o1_i2(arg, arg32, 0, 1, 2); + gen_helper_sub_s(arg32[0].out, cpu_env, arg32[1].in, arg32[2].in); + put_f32_o1_i2(arg, arg32, 0, 1, 2); + } +} + +static void translate_mkdadj_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + gen_helper_mkdadj_d(arg[0].out, cpu_env, arg[0].in, arg[1].in); +} + +static void translate_mkdadj_s(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + OpcodeArg arg32[2]; + + get_f32_o1_i2(arg, arg32, 0, 0, 1); + gen_helper_mkdadj_s(arg32[0].out, cpu_env, arg32[0].in, arg32[1].in); + put_f32_o1_i2(arg, arg32, 0, 0, 1); +} + +static void translate_mksadj_d(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + gen_helper_mksadj_d(arg[0].out, cpu_env, arg[1].in); +} + +static void translate_mksadj_s(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + OpcodeArg arg32[2]; + + get_f32_o1_i1(arg, arg32, 0, 1); + gen_helper_mksadj_s(arg32[0].out, cpu_env, arg32[1].in); + put_f32_o1_i1(arg, arg32, 0, 1); +} + +static void translate_wur_fpu_fcr(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + gen_helper_wur_fpu_fcr(cpu_env, arg[0].in); +} + +static void translate_rur_fpu_fsr(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + gen_helper_rur_fpu_fsr(arg[0].out, cpu_env); +} + +static void translate_wur_fpu_fsr(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + gen_helper_wur_fpu_fsr(cpu_env, arg[0].in); +} + +static const XtensaOpcodeOps fpu_ops[] = { + { + .name = "abs.d", + .translate = translate_abs_d, + .coprocessor = 0x1, + }, { + .name = "abs.s", + .translate = translate_abs_s, + .coprocessor = 0x1, + }, { + .name = "add.d", + .translate = translate_add_d, + .coprocessor = 0x1, + }, { + .name = "add.s", + .translate = translate_add_s, + .coprocessor = 0x1, + }, { + .name = "addexp.d", + .translate = translate_nop, + .coprocessor = 0x1, + }, { + .name = "addexp.s", + .translate = translate_nop, + .coprocessor = 0x1, + }, { + .name = "addexpm.d", + .translate = translate_mov_s, + .coprocessor = 0x1, + }, { + .name = "addexpm.s", + .translate = translate_mov_s, + .coprocessor = 0x1, + }, { + .name = "ceil.d", + .translate = translate_ftoi_d, + .par = (const uint32_t[]){float_round_up, false}, + .coprocessor = 0x1, + }, { + .name = "ceil.s", + .translate = translate_ftoi_s, + .par = (const uint32_t[]){float_round_up, false}, + .coprocessor = 0x1, + }, { + .name = "const.d", + .translate = translate_const_d, + .coprocessor = 0x1, + }, { + .name = "const.s", + .translate = translate_const_s, + .coprocessor = 0x1, + }, { + .name = "cvtd.s", + .translate = translate_cvtd_s, + .coprocessor = 0x1, + }, { + .name = "cvts.d", + .translate = translate_cvts_d, + .coprocessor = 0x1, + }, { + .name = "div0.d", + .translate = translate_nop, + .coprocessor = 0x1, + }, { + .name = "div0.s", + .translate = translate_nop, + .coprocessor = 0x1, + }, { + .name = "divn.d", + .translate = translate_nop, + .coprocessor = 0x1, + }, { + .name = "divn.s", + .translate = translate_nop, + .coprocessor = 0x1, + }, { + .name = "float.d", + .translate = translate_float_d, + .par = (const uint32_t[]){false}, + .coprocessor = 0x1, + }, { + .name = "float.s", + .translate = translate_float_s, + .par = (const uint32_t[]){false}, + .coprocessor = 0x1, + }, { + .name = "floor.d", + .translate = translate_ftoi_d, + .par = (const uint32_t[]){float_round_down, false}, + .coprocessor = 0x1, + }, { + .name = "floor.s", + .translate = translate_ftoi_s, + .par = (const uint32_t[]){float_round_down, false}, + .coprocessor = 0x1, + }, { + .name = "ldi", + .translate = translate_ldsti_d, + .par = (const uint32_t[]){false, true, false}, + .op_flags = XTENSA_OP_LOAD, + .coprocessor = 0x1, + }, { + .name = "ldip", + .translate = translate_ldsti_d, + .par = (const uint32_t[]){false, false, true}, + .op_flags = XTENSA_OP_LOAD, + .coprocessor = 0x1, + }, { + .name = "ldiu", + .translate = translate_ldsti_d, + .par = (const uint32_t[]){false, true, true}, + .op_flags = XTENSA_OP_LOAD, + .coprocessor = 0x1, + }, { + .name = "ldx", + .translate = translate_ldstx_d, + .par = (const uint32_t[]){false, true, false}, + .op_flags = XTENSA_OP_LOAD, + .coprocessor = 0x1, + }, { + .name = "ldxp", + .translate = translate_ldstx_d, + .par = (const uint32_t[]){false, false, true}, + .op_flags = XTENSA_OP_LOAD, + .coprocessor = 0x1, + }, { + .name = "ldxu", + .translate = translate_ldstx_d, + .par = (const uint32_t[]){false, true, true}, + .op_flags = XTENSA_OP_LOAD, + .coprocessor = 0x1, + }, { + .name = "lsi", + .translate = translate_ldsti_s, + .par = (const uint32_t[]){false, true, false}, + .op_flags = XTENSA_OP_LOAD, + .coprocessor = 0x1, + }, { + .name = "lsip", + .translate = translate_ldsti_s, + .par = (const uint32_t[]){false, false, true}, + .op_flags = XTENSA_OP_LOAD, + .coprocessor = 0x1, + }, { + .name = "lsiu", + .translate = translate_ldsti_s, + .par = (const uint32_t[]){false, true, true}, + .op_flags = XTENSA_OP_LOAD, + .coprocessor = 0x1, + }, { + .name = "lsx", + .translate = translate_ldstx_s, + .par = (const uint32_t[]){false, true, false}, + .op_flags = XTENSA_OP_LOAD, + .coprocessor = 0x1, + }, { + .name = "lsxp", + .translate = translate_ldstx_s, + .par = (const uint32_t[]){false, false, true}, + .op_flags = XTENSA_OP_LOAD, + .coprocessor = 0x1, + }, { + .name = "lsxu", + .translate = translate_ldstx_s, + .par = (const uint32_t[]){false, true, true}, + .op_flags = XTENSA_OP_LOAD, + .coprocessor = 0x1, + }, { + .name = "madd.d", + .translate = translate_madd_d, + .coprocessor = 0x1, + }, { + .name = "madd.s", + .translate = translate_madd_s, + .coprocessor = 0x1, + }, { + .name = "maddn.d", + .translate = translate_nop, + .coprocessor = 0x1, + }, { + .name = "maddn.s", + .translate = translate_nop, + .coprocessor = 0x1, + }, { + .name = "mkdadj.d", + .translate = translate_mkdadj_d, + .coprocessor = 0x1, + }, { + .name = "mkdadj.s", + .translate = translate_mkdadj_s, + .coprocessor = 0x1, + }, { + .name = "mksadj.d", + .translate = translate_mksadj_d, + .coprocessor = 0x1, + }, { + .name = "mksadj.s", + .translate = translate_mksadj_s, + .coprocessor = 0x1, + }, { + .name = "mov.d", + .translate = translate_mov_d, + .coprocessor = 0x1, + }, { + .name = "mov.s", + .translate = translate_mov_s, + .coprocessor = 0x1, + }, { + .name = "moveqz.d", + .translate = translate_movcond_d, + .par = (const uint32_t[]){TCG_COND_EQ}, + .coprocessor = 0x1, + }, { + .name = "moveqz.s", + .translate = translate_movcond_s, + .par = (const uint32_t[]){TCG_COND_EQ}, + .coprocessor = 0x1, + }, { + .name = "movf.d", + .translate = translate_movp_d, + .par = (const uint32_t[]){TCG_COND_EQ}, + .coprocessor = 0x1, + }, { + .name = "movf.s", + .translate = translate_movp_s, + .par = (const uint32_t[]){TCG_COND_EQ}, + .coprocessor = 0x1, + }, { + .name = "movgez.d", + .translate = translate_movcond_d, + .par = (const uint32_t[]){TCG_COND_GE}, + .coprocessor = 0x1, + }, { + .name = "movgez.s", + .translate = translate_movcond_s, + .par = (const uint32_t[]){TCG_COND_GE}, + .coprocessor = 0x1, + }, { + .name = "movltz.d", + .translate = translate_movcond_d, + .par = (const uint32_t[]){TCG_COND_LT}, + .coprocessor = 0x1, + }, { + .name = "movltz.s", + .translate = translate_movcond_s, + .par = (const uint32_t[]){TCG_COND_LT}, + .coprocessor = 0x1, + }, { + .name = "movnez.d", + .translate = translate_movcond_d, + .par = (const uint32_t[]){TCG_COND_NE}, + .coprocessor = 0x1, + }, { + .name = "movnez.s", + .translate = translate_movcond_s, + .par = (const uint32_t[]){TCG_COND_NE}, + .coprocessor = 0x1, + }, { + .name = "movt.d", + .translate = translate_movp_d, + .par = (const uint32_t[]){TCG_COND_NE}, + .coprocessor = 0x1, + }, { + .name = "movt.s", + .translate = translate_movp_s, + .par = (const uint32_t[]){TCG_COND_NE}, + .coprocessor = 0x1, + }, { + .name = "msub.d", + .translate = translate_msub_d, + .coprocessor = 0x1, + }, { + .name = "msub.s", + .translate = translate_msub_s, + .coprocessor = 0x1, + }, { + .name = "mul.d", + .translate = translate_mul_d, + .coprocessor = 0x1, + }, { + .name = "mul.s", + .translate = translate_mul_s, + .coprocessor = 0x1, + }, { + .name = "neg.d", + .translate = translate_neg_d, + .coprocessor = 0x1, + }, { + .name = "neg.s", + .translate = translate_neg_s, + .coprocessor = 0x1, + }, { + .name = "nexp01.d", + .translate = translate_nop, + .coprocessor = 0x1, + }, { + .name = "nexp01.s", + .translate = translate_nop, + .coprocessor = 0x1, + }, { + .name = "oeq.d", + .translate = translate_compare_d, + .par = (const uint32_t[]){COMPARE_OEQ}, + .coprocessor = 0x1, + }, { + .name = "oeq.s", + .translate = translate_compare_s, + .par = (const uint32_t[]){COMPARE_OEQ}, + .coprocessor = 0x1, + }, { + .name = "ole.d", + .translate = translate_compare_d, + .par = (const uint32_t[]){COMPARE_OLE}, + .coprocessor = 0x1, + }, { + .name = "ole.s", + .translate = translate_compare_s, + .par = (const uint32_t[]){COMPARE_OLE}, + .coprocessor = 0x1, + }, { + .name = "olt.d", + .translate = translate_compare_d, + .par = (const uint32_t[]){COMPARE_OLT}, + .coprocessor = 0x1, + }, { + .name = "olt.s", + .translate = translate_compare_s, + .par = (const uint32_t[]){COMPARE_OLT}, + .coprocessor = 0x1, + }, { + .name = "rfr", + .translate = translate_rfr_s, + .coprocessor = 0x1, + }, { + .name = "rfrd", + .translate = translate_rfr_d, + .coprocessor = 0x1, + }, { + .name = "round.d", + .translate = translate_ftoi_d, + .par = (const uint32_t[]){float_round_nearest_even, false}, + .coprocessor = 0x1, + }, { + .name = "round.s", + .translate = translate_ftoi_s, + .par = (const uint32_t[]){float_round_nearest_even, false}, + .coprocessor = 0x1, + }, { + .name = "rur.fcr", + .translate = translate_rur, + .par = (const uint32_t[]){FCR}, + .coprocessor = 0x1, + }, { + .name = "rur.fsr", + .translate = translate_rur_fpu_fsr, + .coprocessor = 0x1, + }, { + .name = "sdi", + .translate = translate_ldsti_d, + .par = (const uint32_t[]){true, true, false}, + .op_flags = XTENSA_OP_STORE, + .coprocessor = 0x1, + }, { + .name = "sdip", + .translate = translate_ldsti_d, + .par = (const uint32_t[]){true, false, true}, + .op_flags = XTENSA_OP_STORE, + .coprocessor = 0x1, + }, { + .name = "sdiu", + .translate = translate_ldsti_d, + .par = (const uint32_t[]){true, true, true}, + .op_flags = XTENSA_OP_STORE, + .coprocessor = 0x1, + }, { + .name = "sdx", + .translate = translate_ldstx_d, + .par = (const uint32_t[]){true, true, false}, + .op_flags = XTENSA_OP_STORE, + .coprocessor = 0x1, + }, { + .name = "sdxp", + .translate = translate_ldstx_d, + .par = (const uint32_t[]){true, false, true}, + .op_flags = XTENSA_OP_STORE, + .coprocessor = 0x1, + }, { + .name = "sdxu", + .translate = translate_ldstx_d, + .par = (const uint32_t[]){true, true, true}, + .op_flags = XTENSA_OP_STORE, + .coprocessor = 0x1, + }, { + .name = "sqrt0.d", + .translate = translate_nop, + .coprocessor = 0x1, + }, { + .name = "sqrt0.s", + .translate = translate_nop, + .coprocessor = 0x1, + }, { + .name = "ssi", + .translate = translate_ldsti_s, + .par = (const uint32_t[]){true, true, false}, + .op_flags = XTENSA_OP_STORE, + .coprocessor = 0x1, + }, { + .name = "ssip", + .translate = translate_ldsti_s, + .par = (const uint32_t[]){true, false, true}, + .op_flags = XTENSA_OP_STORE, + .coprocessor = 0x1, + }, { + .name = "ssiu", + .translate = translate_ldsti_s, + .par = (const uint32_t[]){true, true, true}, + .op_flags = XTENSA_OP_STORE, + .coprocessor = 0x1, + }, { + .name = "ssx", + .translate = translate_ldstx_s, + .par = (const uint32_t[]){true, true, false}, + .op_flags = XTENSA_OP_STORE, + .coprocessor = 0x1, + }, { + .name = "ssxp", + .translate = translate_ldstx_s, + .par = (const uint32_t[]){true, false, true}, + .op_flags = XTENSA_OP_STORE, + .coprocessor = 0x1, + }, { + .name = "ssxu", + .translate = translate_ldstx_s, + .par = (const uint32_t[]){true, true, true}, + .op_flags = XTENSA_OP_STORE, + .coprocessor = 0x1, + }, { + .name = "sub.d", + .translate = translate_sub_d, + .coprocessor = 0x1, + }, { + .name = "sub.s", + .translate = translate_sub_s, + .coprocessor = 0x1, + }, { + .name = "trunc.d", + .translate = translate_ftoi_d, + .par = (const uint32_t[]){float_round_to_zero, false}, + .coprocessor = 0x1, + }, { + .name = "trunc.s", + .translate = translate_ftoi_s, + .par = (const uint32_t[]){float_round_to_zero, false}, + .coprocessor = 0x1, + }, { + .name = "ueq.d", + .translate = translate_compare_d, + .par = (const uint32_t[]){COMPARE_UEQ}, + .coprocessor = 0x1, + }, { + .name = "ueq.s", + .translate = translate_compare_s, + .par = (const uint32_t[]){COMPARE_UEQ}, + .coprocessor = 0x1, + }, { + .name = "ufloat.d", + .translate = translate_float_d, + .par = (const uint32_t[]){true}, + .coprocessor = 0x1, + }, { + .name = "ufloat.s", + .translate = translate_float_s, + .par = (const uint32_t[]){true}, + .coprocessor = 0x1, + }, { + .name = "ule.d", + .translate = translate_compare_d, + .par = (const uint32_t[]){COMPARE_ULE}, + .coprocessor = 0x1, + }, { + .name = "ule.s", + .translate = translate_compare_s, + .par = (const uint32_t[]){COMPARE_ULE}, + .coprocessor = 0x1, + }, { + .name = "ult.d", + .translate = translate_compare_d, + .par = (const uint32_t[]){COMPARE_ULT}, + .coprocessor = 0x1, + }, { + .name = "ult.s", + .translate = translate_compare_s, + .par = (const uint32_t[]){COMPARE_ULT}, + .coprocessor = 0x1, + }, { + .name = "un.d", + .translate = translate_compare_d, + .par = (const uint32_t[]){COMPARE_UN}, + .coprocessor = 0x1, + }, { + .name = "un.s", + .translate = translate_compare_s, + .par = (const uint32_t[]){COMPARE_UN}, + .coprocessor = 0x1, + }, { + .name = "utrunc.d", + .translate = translate_ftoi_d, + .par = (const uint32_t[]){float_round_to_zero, true}, + .coprocessor = 0x1, + }, { + .name = "utrunc.s", + .translate = translate_ftoi_s, + .par = (const uint32_t[]){float_round_to_zero, true}, + .coprocessor = 0x1, + }, { + .name = "wfr", + .translate = translate_wfr_s, + .coprocessor = 0x1, + }, { + .name = "wfrd", + .translate = translate_wfr_d, + .coprocessor = 0x1, + }, { + .name = "wur.fcr", + .translate = translate_wur_fpu_fcr, + .par = (const uint32_t[]){FCR}, + .coprocessor = 0x1, + }, { + .name = "wur.fsr", + .translate = translate_wur_fpu_fsr, + .coprocessor = 0x1, + }, +}; + +const XtensaOpcodeTranslators xtensa_fpu_opcodes = { + .num_opcodes = ARRAY_SIZE(fpu_ops), + .opcode = fpu_ops, +}; diff --git a/tcg/README b/tcg/README index bfa2e4ed246c829b4f7b15bf359754a85623e88d..2f051e5c970977ac4d7d0155f50215da44f6e738 100644 --- a/tcg/README +++ b/tcg/README @@ -605,10 +605,11 @@ E.g. VECL=1 -> 64 << 1 -> v128, and VECE=2 -> 1 << 2 -> i32. * shri_vec v0, v1, i2 * sari_vec v0, v1, i2 +* rotli_vec v0, v1, i2 * shrs_vec v0, v1, s2 * sars_vec v0, v1, s2 - Similarly for logical and arithmetic right shift. + Similarly for logical and arithmetic right shift, and left rotate. * shlv_vec v0, v1, v2 @@ -620,8 +621,10 @@ E.g. VECL=1 -> 64 << 1 -> v128, and VECE=2 -> 1 << 2 -> i32. * shrv_vec v0, v1, v2 * sarv_vec v0, v1, v2 +* rotlv_vec v0, v1, v2 +* rotrv_vec v0, v1, v2 - Similarly for logical and arithmetic right shift. + Similarly for logical and arithmetic right shift, and rotates. * cmp_vec v0, v1, v2, cond @@ -649,7 +652,7 @@ function tcg_gen_xxx(args). 4) Backend -tcg-target.h contains the target specific definitions. tcg-target.inc.c +tcg-target.h contains the target specific definitions. tcg-target.c.inc contains the target specific code; it is #included by tcg/tcg.c, rather than being a standalone C file. diff --git a/tcg/aarch64/tcg-target.inc.c b/tcg/aarch64/tcg-target.c.inc similarity index 97% rename from tcg/aarch64/tcg-target.inc.c rename to tcg/aarch64/tcg-target.c.inc index 843fd0ca6991ad4fd6c3d0db8691fe6946088fee..26f71cb599e7217194854c1f02083d0640ee327c 100644 --- a/tcg/aarch64/tcg-target.inc.c +++ b/tcg/aarch64/tcg-target.c.inc @@ -10,7 +10,7 @@ * See the COPYING file in the top-level directory for details. */ -#include "../tcg-pool.inc.c" +#include "../tcg-pool.c.inc" #include "qemu/bitops.h" /* We're going to re-use TCGType in setting of the SF bit, which controls @@ -128,23 +128,20 @@ static const char *target_parse_constraint(TCGArgConstraint *ct, { switch (*ct_str++) { case 'r': /* general registers */ - ct->ct |= TCG_CT_REG; - ct->u.regs |= 0xffffffffu; + ct->regs |= 0xffffffffu; break; case 'w': /* advsimd registers */ - ct->ct |= TCG_CT_REG; - ct->u.regs |= 0xffffffff00000000ull; + ct->regs |= 0xffffffff00000000ull; break; case 'l': /* qemu_ld / qemu_st address, data_reg */ - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xffffffffu; + ct->regs = 0xffffffffu; #ifdef CONFIG_SOFTMMU /* x0 and x1 will be overwritten when reading the tlb entry, and x2, and x3 for helper args, better to avoid using them. */ - tcg_regset_reset_reg(ct->u.regs, TCG_REG_X0); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_X1); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_X2); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_X3); + tcg_regset_reset_reg(ct->regs, TCG_REG_X0); + tcg_regset_reset_reg(ct->regs, TCG_REG_X1); + tcg_regset_reset_reg(ct->regs, TCG_REG_X2); + tcg_regset_reset_reg(ct->regs, TCG_REG_X3); #endif break; case 'A': /* Valid for arithmetic immediate (positive or negative). */ @@ -557,6 +554,7 @@ typedef enum { I3614_SSHR = 0x0f000400, I3614_SSRA = 0x0f001400, I3614_SHL = 0x0f005400, + I3614_SLI = 0x2f005400, I3614_USHR = 0x2f000400, I3614_USRA = 0x2f001400, @@ -1364,7 +1362,7 @@ void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr, i2 = I3401_ADDI | rt << 31 | (addr & 0xfff) << 10 | rd << 5 | rd; } pair = (uint64_t)i2 << 32 | i1; - atomic_set((uint64_t *)jmp_addr, pair); + qatomic_set((uint64_t *)jmp_addr, pair); flush_icache_range(jmp_addr, jmp_addr + 8); } @@ -1541,7 +1539,7 @@ static void tcg_out_cltz(TCGContext *s, TCGType ext, TCGReg d, } #ifdef CONFIG_SOFTMMU -#include "../tcg-ldst.inc.c" +#include "../tcg-ldst.c.inc" /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr, * TCGMemOpIdx oi, uintptr_t ra) @@ -2411,6 +2409,9 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc, case INDEX_op_sari_vec: tcg_out_insn(s, 3614, SSHR, is_q, a0, a1, (16 << vece) - a2); break; + case INDEX_op_aa64_sli_vec: + tcg_out_insn(s, 3614, SLI, is_q, a0, a2, args[3] + (8 << vece)); + break; case INDEX_op_shlv_vec: tcg_out_insn(s, 3616, USHL, is_q, vece, a0, a1, a2); break; @@ -2498,8 +2499,11 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece) case INDEX_op_shlv_vec: case INDEX_op_bitsel_vec: return 1; + case INDEX_op_rotli_vec: case INDEX_op_shrv_vec: case INDEX_op_sarv_vec: + case INDEX_op_rotlv_vec: + case INDEX_op_rotrv_vec: return -1; case INDEX_op_mul_vec: case INDEX_op_smax_vec: @@ -2517,14 +2521,24 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, TCGArg a0, ...) { va_list va; - TCGv_vec v0, v1, v2, t1; + TCGv_vec v0, v1, v2, t1, t2; + TCGArg a2; va_start(va, a0); v0 = temp_tcgv_vec(arg_temp(a0)); v1 = temp_tcgv_vec(arg_temp(va_arg(va, TCGArg))); - v2 = temp_tcgv_vec(arg_temp(va_arg(va, TCGArg))); + a2 = va_arg(va, TCGArg); + v2 = temp_tcgv_vec(arg_temp(a2)); switch (opc) { + case INDEX_op_rotli_vec: + t1 = tcg_temp_new_vec(type); + tcg_gen_shri_vec(vece, t1, v1, -a2 & ((8 << vece) - 1)); + vec_gen_4(INDEX_op_aa64_sli_vec, type, vece, + tcgv_vec_arg(v0), tcgv_vec_arg(t1), tcgv_vec_arg(v1), a2); + tcg_temp_free_vec(t1); + break; + case INDEX_op_shrv_vec: case INDEX_op_sarv_vec: /* Right shifts are negative left shifts for AArch64. */ @@ -2537,6 +2551,35 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, tcg_temp_free_vec(t1); break; + case INDEX_op_rotlv_vec: + t1 = tcg_temp_new_vec(type); + tcg_gen_dupi_vec(vece, t1, 8 << vece); + tcg_gen_sub_vec(vece, t1, v2, t1); + /* Right shifts are negative left shifts for AArch64. */ + vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(t1), + tcgv_vec_arg(v1), tcgv_vec_arg(t1)); + vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(v0), + tcgv_vec_arg(v1), tcgv_vec_arg(v2)); + tcg_gen_or_vec(vece, v0, v0, t1); + tcg_temp_free_vec(t1); + break; + + case INDEX_op_rotrv_vec: + t1 = tcg_temp_new_vec(type); + t2 = tcg_temp_new_vec(type); + tcg_gen_neg_vec(vece, t1, v2); + tcg_gen_dupi_vec(vece, t2, 8 << vece); + tcg_gen_add_vec(vece, t2, t1, t2); + /* Right shifts are negative left shifts for AArch64. */ + vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(t1), + tcgv_vec_arg(v1), tcgv_vec_arg(t1)); + vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(t2), + tcgv_vec_arg(v1), tcgv_vec_arg(t2)); + tcg_gen_or_vec(vece, v0, t1, t2); + tcg_temp_free_vec(t1); + tcg_temp_free_vec(t2); + break; + default: g_assert_not_reached(); } @@ -2557,6 +2600,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op) static const TCGTargetOpDef lZ_l = { .args_ct_str = { "lZ", "l" } }; static const TCGTargetOpDef r_r_r = { .args_ct_str = { "r", "r", "r" } }; static const TCGTargetOpDef w_w_w = { .args_ct_str = { "w", "w", "w" } }; + static const TCGTargetOpDef w_0_w = { .args_ct_str = { "w", "0", "w" } }; static const TCGTargetOpDef w_w_wO = { .args_ct_str = { "w", "w", "wO" } }; static const TCGTargetOpDef w_w_wN = { .args_ct_str = { "w", "w", "wN" } }; static const TCGTargetOpDef w_w_wZ = { .args_ct_str = { "w", "w", "wZ" } }; @@ -2751,6 +2795,8 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op) return &w_w_wZ; case INDEX_op_bitsel_vec: return &w_w_w_w; + case INDEX_op_aa64_sli_vec: + return &w_0_w; default: return NULL; diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h index ca214f6909f1aef5d91fb451f574b607eaae5f38..663dd0b95edc617baba70648d2f6811b85003272 100644 --- a/tcg/aarch64/tcg-target.h +++ b/tcg/aarch64/tcg-target.h @@ -133,10 +133,12 @@ typedef enum { #define TCG_TARGET_HAS_not_vec 1 #define TCG_TARGET_HAS_neg_vec 1 #define TCG_TARGET_HAS_abs_vec 1 +#define TCG_TARGET_HAS_roti_vec 0 +#define TCG_TARGET_HAS_rots_vec 0 +#define TCG_TARGET_HAS_rotv_vec 0 #define TCG_TARGET_HAS_shi_vec 1 #define TCG_TARGET_HAS_shs_vec 0 #define TCG_TARGET_HAS_shv_vec 1 -#define TCG_TARGET_HAS_cmp_vec 1 #define TCG_TARGET_HAS_mul_vec 1 #define TCG_TARGET_HAS_sat_vec 1 #define TCG_TARGET_HAS_minmax_vec 1 diff --git a/tcg/aarch64/tcg-target.opc.h b/tcg/aarch64/tcg-target.opc.h index 26bfd9c4609367a50c3acdd324d97ca6c1dbe2f6..bce30accd9366f1665c58141616ca5e4e56c9f35 100644 --- a/tcg/aarch64/tcg-target.opc.h +++ b/tcg/aarch64/tcg-target.opc.h @@ -12,3 +12,4 @@ */ DEF(aa64_sshl_vec, 1, 2, 0, IMPLVEC) +DEF(aa64_sli_vec, 1, 2, 1, IMPLVEC) diff --git a/tcg/arm/tcg-target.inc.c b/tcg/arm/tcg-target.c.inc similarity index 99% rename from tcg/arm/tcg-target.inc.c rename to tcg/arm/tcg-target.c.inc index 6aa7757aac630a4f5cd7dcf3fbee7ec123abf2a3..62c37a954b88481ead92e987a7ee44e9cdacfbe3 100644 --- a/tcg/arm/tcg-target.inc.c +++ b/tcg/arm/tcg-target.c.inc @@ -23,7 +23,7 @@ */ #include "elf.h" -#include "../tcg-pool.inc.c" +#include "../tcg-pool.c.inc" int arm_arch = __ARM_ARCH; @@ -253,41 +253,38 @@ static const char *target_parse_constraint(TCGArgConstraint *ct, break; case 'r': - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xffff; + ct->regs = 0xffff; break; /* qemu_ld address */ case 'l': - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xffff; + ct->regs = 0xffff; #ifdef CONFIG_SOFTMMU /* r0-r2,lr will be overwritten when reading the tlb entry, so don't use these. */ - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14); + tcg_regset_reset_reg(ct->regs, TCG_REG_R0); + tcg_regset_reset_reg(ct->regs, TCG_REG_R1); + tcg_regset_reset_reg(ct->regs, TCG_REG_R2); + tcg_regset_reset_reg(ct->regs, TCG_REG_R3); + tcg_regset_reset_reg(ct->regs, TCG_REG_R14); #endif break; /* qemu_st address & data */ case 's': - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xffff; + ct->regs = 0xffff; /* r0-r2 will be overwritten when reading the tlb entry (softmmu only) and r0-r1 doing the byte swapping, so don't use these. */ - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1); + tcg_regset_reset_reg(ct->regs, TCG_REG_R0); + tcg_regset_reset_reg(ct->regs, TCG_REG_R1); #if defined(CONFIG_SOFTMMU) /* Avoid clashes with registers being used for helper args */ - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2); + tcg_regset_reset_reg(ct->regs, TCG_REG_R2); #if TARGET_LONG_BITS == 64 /* Avoid clashes with registers being used for helper args */ - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3); + tcg_regset_reset_reg(ct->regs, TCG_REG_R3); #endif - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14); + tcg_regset_reset_reg(ct->regs, TCG_REG_R14); #endif break; @@ -1131,7 +1128,7 @@ static TCGCond tcg_out_cmp2(TCGContext *s, const TCGArg *args, } #ifdef CONFIG_SOFTMMU -#include "../tcg-ldst.inc.c" +#include "../tcg-ldst.c.inc" /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr, * int mmu_idx, uintptr_t ra) diff --git a/tcg/i386/tcg-target.inc.c b/tcg/i386/tcg-target.c.inc similarity index 96% rename from tcg/i386/tcg-target.inc.c rename to tcg/i386/tcg-target.c.inc index ec083bddcfb7737512e8f1095b7dfcac8178e07d..d8797ed3987dde73baf62bca4c401364dda81d07 100644 --- a/tcg/i386/tcg-target.inc.c +++ b/tcg/i386/tcg-target.c.inc @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "../tcg-pool.inc.c" +#include "../tcg-pool.c.inc" #ifdef CONFIG_DEBUG_TCG static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { @@ -208,43 +208,34 @@ static const char *target_parse_constraint(TCGArgConstraint *ct, { switch(*ct_str++) { case 'a': - ct->ct |= TCG_CT_REG; - tcg_regset_set_reg(ct->u.regs, TCG_REG_EAX); + tcg_regset_set_reg(ct->regs, TCG_REG_EAX); break; case 'b': - ct->ct |= TCG_CT_REG; - tcg_regset_set_reg(ct->u.regs, TCG_REG_EBX); + tcg_regset_set_reg(ct->regs, TCG_REG_EBX); break; case 'c': - ct->ct |= TCG_CT_REG; - tcg_regset_set_reg(ct->u.regs, TCG_REG_ECX); + tcg_regset_set_reg(ct->regs, TCG_REG_ECX); break; case 'd': - ct->ct |= TCG_CT_REG; - tcg_regset_set_reg(ct->u.regs, TCG_REG_EDX); + tcg_regset_set_reg(ct->regs, TCG_REG_EDX); break; case 'S': - ct->ct |= TCG_CT_REG; - tcg_regset_set_reg(ct->u.regs, TCG_REG_ESI); + tcg_regset_set_reg(ct->regs, TCG_REG_ESI); break; case 'D': - ct->ct |= TCG_CT_REG; - tcg_regset_set_reg(ct->u.regs, TCG_REG_EDI); + tcg_regset_set_reg(ct->regs, TCG_REG_EDI); break; case 'q': /* A register that can be used as a byte operand. */ - ct->ct |= TCG_CT_REG; - ct->u.regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xf; + ct->regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xf; break; case 'Q': /* A register with an addressable second byte (e.g. %ah). */ - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xf; + ct->regs = 0xf; break; case 'r': /* A general register. */ - ct->ct |= TCG_CT_REG; - ct->u.regs |= ALL_GENERAL_REGS; + ct->regs |= ALL_GENERAL_REGS; break; case 'W': /* With TZCNT/LZCNT, we can have operand-size as an input. */ @@ -252,16 +243,14 @@ static const char *target_parse_constraint(TCGArgConstraint *ct, break; case 'x': /* A vector register. */ - ct->ct |= TCG_CT_REG; - ct->u.regs |= ALL_VECTOR_REGS; + ct->regs |= ALL_VECTOR_REGS; break; /* qemu_ld/st address constraint */ case 'L': - ct->ct |= TCG_CT_REG; - ct->u.regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xff; - tcg_regset_reset_reg(ct->u.regs, TCG_REG_L0); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_L1); + ct->regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xff; + tcg_regset_reset_reg(ct->regs, TCG_REG_L0); + tcg_regset_reset_reg(ct->regs, TCG_REG_L1); break; case 'e': @@ -969,7 +958,7 @@ static void tcg_out_dupi_vec(TCGContext *s, TCGType type, new_pool_label(s, arg, R_386_PC32, s->code_ptr - 4, -4); } else { if (have_avx2) { - tcg_out_vex_modrm_pool(s, OPC_VPBROADCASTW + vex_l, ret); + tcg_out_vex_modrm_pool(s, OPC_VPBROADCASTD + vex_l, ret); } else { tcg_out_vex_modrm_pool(s, OPC_VBROADCASTSS, ret); } @@ -1647,7 +1636,7 @@ static void tcg_out_nopn(TCGContext *s, int n) } #if defined(CONFIG_SOFTMMU) -#include "../tcg-ldst.inc.c" +#include "../tcg-ldst.c.inc" /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr, * int mmu_idx, uintptr_t ra) @@ -3233,6 +3222,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op) case INDEX_op_shls_vec: case INDEX_op_shrs_vec: case INDEX_op_sars_vec: + case INDEX_op_rotls_vec: case INDEX_op_cmp_vec: case INDEX_op_x86_shufps_vec: case INDEX_op_x86_blend_vec: @@ -3271,6 +3261,7 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece) case INDEX_op_xor_vec: case INDEX_op_andc_vec: return 1; + case INDEX_op_rotli_vec: case INDEX_op_cmp_vec: case INDEX_op_cmpsel_vec: return -1; @@ -3297,12 +3288,17 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece) return vece >= MO_16; case INDEX_op_sars_vec: return vece >= MO_16 && vece <= MO_32; + case INDEX_op_rotls_vec: + return vece >= MO_16 ? -1 : 0; case INDEX_op_shlv_vec: case INDEX_op_shrv_vec: return have_avx2 && vece >= MO_32; case INDEX_op_sarv_vec: return have_avx2 && vece == MO_32; + case INDEX_op_rotlv_vec: + case INDEX_op_rotrv_vec: + return have_avx2 && vece >= MO_32 ? -1 : 0; case INDEX_op_mul_vec: if (vece == MO_8) { @@ -3331,7 +3327,7 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece) } } -static void expand_vec_shi(TCGType type, unsigned vece, bool shr, +static void expand_vec_shi(TCGType type, unsigned vece, TCGOpcode opc, TCGv_vec v0, TCGv_vec v1, TCGArg imm) { TCGv_vec t1, t2; @@ -3341,26 +3337,31 @@ static void expand_vec_shi(TCGType type, unsigned vece, bool shr, t1 = tcg_temp_new_vec(type); t2 = tcg_temp_new_vec(type); - /* Unpack to W, shift, and repack. Tricky bits: - (1) Use punpck*bw x,x to produce DDCCBBAA, - i.e. duplicate in other half of the 16-bit lane. - (2) For right-shift, add 8 so that the high half of - the lane becomes zero. For left-shift, we must - shift up and down again. - (3) Step 2 leaves high half zero such that PACKUSWB - (pack with unsigned saturation) does not modify - the quantity. */ + /* + * Unpack to W, shift, and repack. Tricky bits: + * (1) Use punpck*bw x,x to produce DDCCBBAA, + * i.e. duplicate in other half of the 16-bit lane. + * (2) For right-shift, add 8 so that the high half of the lane + * becomes zero. For left-shift, and left-rotate, we must + * shift up and down again. + * (3) Step 2 leaves high half zero such that PACKUSWB + * (pack with unsigned saturation) does not modify + * the quantity. + */ vec_gen_3(INDEX_op_x86_punpckl_vec, type, MO_8, tcgv_vec_arg(t1), tcgv_vec_arg(v1), tcgv_vec_arg(v1)); vec_gen_3(INDEX_op_x86_punpckh_vec, type, MO_8, tcgv_vec_arg(t2), tcgv_vec_arg(v1), tcgv_vec_arg(v1)); - if (shr) { - tcg_gen_shri_vec(MO_16, t1, t1, imm + 8); - tcg_gen_shri_vec(MO_16, t2, t2, imm + 8); + if (opc != INDEX_op_rotli_vec) { + imm += 8; + } + if (opc == INDEX_op_shri_vec) { + tcg_gen_shri_vec(MO_16, t1, t1, imm); + tcg_gen_shri_vec(MO_16, t2, t2, imm); } else { - tcg_gen_shli_vec(MO_16, t1, t1, imm + 8); - tcg_gen_shli_vec(MO_16, t2, t2, imm + 8); + tcg_gen_shli_vec(MO_16, t1, t1, imm); + tcg_gen_shli_vec(MO_16, t2, t2, imm); tcg_gen_shri_vec(MO_16, t1, t1, 8); tcg_gen_shri_vec(MO_16, t2, t2, 8); } @@ -3427,6 +3428,61 @@ static void expand_vec_sari(TCGType type, unsigned vece, } } +static void expand_vec_rotli(TCGType type, unsigned vece, + TCGv_vec v0, TCGv_vec v1, TCGArg imm) +{ + TCGv_vec t; + + if (vece == MO_8) { + expand_vec_shi(type, vece, INDEX_op_rotli_vec, v0, v1, imm); + return; + } + + t = tcg_temp_new_vec(type); + tcg_gen_shli_vec(vece, t, v1, imm); + tcg_gen_shri_vec(vece, v0, v1, (8 << vece) - imm); + tcg_gen_or_vec(vece, v0, v0, t); + tcg_temp_free_vec(t); +} + +static void expand_vec_rotls(TCGType type, unsigned vece, + TCGv_vec v0, TCGv_vec v1, TCGv_i32 lsh) +{ + TCGv_i32 rsh; + TCGv_vec t; + + tcg_debug_assert(vece != MO_8); + + t = tcg_temp_new_vec(type); + rsh = tcg_temp_new_i32(); + + tcg_gen_neg_i32(rsh, lsh); + tcg_gen_andi_i32(rsh, rsh, (8 << vece) - 1); + tcg_gen_shls_vec(vece, t, v1, lsh); + tcg_gen_shrs_vec(vece, v0, v1, rsh); + tcg_gen_or_vec(vece, v0, v0, t); + tcg_temp_free_vec(t); + tcg_temp_free_i32(rsh); +} + +static void expand_vec_rotv(TCGType type, unsigned vece, TCGv_vec v0, + TCGv_vec v1, TCGv_vec sh, bool right) +{ + TCGv_vec t = tcg_temp_new_vec(type); + + tcg_gen_dupi_vec(vece, t, 8 << vece); + tcg_gen_sub_vec(vece, t, t, sh); + if (right) { + tcg_gen_shlv_vec(vece, t, v1, t); + tcg_gen_shrv_vec(vece, v0, v1, sh); + } else { + tcg_gen_shrv_vec(vece, t, v1, t); + tcg_gen_shlv_vec(vece, v0, v1, sh); + } + tcg_gen_or_vec(vece, v0, v0, t); + tcg_temp_free_vec(t); +} + static void expand_vec_mul(TCGType type, unsigned vece, TCGv_vec v0, TCGv_vec v1, TCGv_vec v2) { @@ -3636,13 +3692,30 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, switch (opc) { case INDEX_op_shli_vec: case INDEX_op_shri_vec: - expand_vec_shi(type, vece, opc == INDEX_op_shri_vec, v0, v1, a2); + expand_vec_shi(type, vece, opc, v0, v1, a2); break; case INDEX_op_sari_vec: expand_vec_sari(type, vece, v0, v1, a2); break; + case INDEX_op_rotli_vec: + expand_vec_rotli(type, vece, v0, v1, a2); + break; + + case INDEX_op_rotls_vec: + expand_vec_rotls(type, vece, v0, v1, temp_tcgv_i32(arg_temp(a2))); + break; + + case INDEX_op_rotlv_vec: + v2 = temp_tcgv_vec(arg_temp(a2)); + expand_vec_rotv(type, vece, v0, v1, v2, false); + break; + case INDEX_op_rotrv_vec: + v2 = temp_tcgv_vec(arg_temp(a2)); + expand_vec_rotv(type, vece, v0, v1, v2, true); + break; + case INDEX_op_mul_vec: v2 = temp_tcgv_vec(arg_temp(a2)); expand_vec_mul(type, vece, v0, v1, v2); diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index bfb3f5f6e9e263316aabfdb5fcba244fa88dd40c..abd4ac7fc08fa1e2e0ddde7fa3a7a614d439dbe6 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -183,10 +183,12 @@ extern bool have_avx2; #define TCG_TARGET_HAS_not_vec 0 #define TCG_TARGET_HAS_neg_vec 0 #define TCG_TARGET_HAS_abs_vec 1 +#define TCG_TARGET_HAS_roti_vec 0 +#define TCG_TARGET_HAS_rots_vec 0 +#define TCG_TARGET_HAS_rotv_vec 0 #define TCG_TARGET_HAS_shi_vec 1 #define TCG_TARGET_HAS_shs_vec 1 #define TCG_TARGET_HAS_shv_vec have_avx2 -#define TCG_TARGET_HAS_cmp_vec 1 #define TCG_TARGET_HAS_mul_vec 1 #define TCG_TARGET_HAS_sat_vec 1 #define TCG_TARGET_HAS_minmax_vec 1 @@ -212,7 +214,7 @@ static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr, uintptr_t addr) { /* patch the branch destination */ - atomic_set((int32_t *)jmp_addr, addr - (jmp_addr + 4)); + qatomic_set((int32_t *)jmp_addr, addr - (jmp_addr + 4)); /* no need to flush icache explicitly */ } diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.c.inc similarity index 99% rename from tcg/mips/tcg-target.inc.c rename to tcg/mips/tcg-target.c.inc index 4d32ebc1df60cfe1f4d2fe63414c13ff431f7790..41be574e89d6b493107c1b94ee4156e1916f4ca6 100644 --- a/tcg/mips/tcg-target.inc.c +++ b/tcg/mips/tcg-target.c.inc @@ -195,29 +195,26 @@ static const char *target_parse_constraint(TCGArgConstraint *ct, { switch(*ct_str++) { case 'r': - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xffffffff; + ct->regs = 0xffffffff; break; case 'L': /* qemu_ld input arg constraint */ - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xffffffff; - tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0); + ct->regs = 0xffffffff; + tcg_regset_reset_reg(ct->regs, TCG_REG_A0); #if defined(CONFIG_SOFTMMU) if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { - tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2); + tcg_regset_reset_reg(ct->regs, TCG_REG_A2); } #endif break; case 'S': /* qemu_st constraint */ - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xffffffff; - tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0); + ct->regs = 0xffffffff; + tcg_regset_reset_reg(ct->regs, TCG_REG_A0); #if defined(CONFIG_SOFTMMU) if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { - tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3); + tcg_regset_reset_reg(ct->regs, TCG_REG_A2); + tcg_regset_reset_reg(ct->regs, TCG_REG_A3); } else { - tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1); + tcg_regset_reset_reg(ct->regs, TCG_REG_A1); } #endif break; @@ -1107,7 +1104,7 @@ static void tcg_out_call(TCGContext *s, tcg_insn_unit *arg) } #if defined(CONFIG_SOFTMMU) -#include "../tcg-ldst.inc.c" +#include "../tcg-ldst.c.inc" static void * const qemu_ld_helpers[16] = { [MO_UB] = helper_ret_ldub_mmu, @@ -2662,7 +2659,7 @@ static void tcg_target_init(TCGContext *s) void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr, uintptr_t addr) { - atomic_set((uint32_t *)jmp_addr, deposit32(OPC_J, 0, 26, addr >> 2)); + qatomic_set((uint32_t *)jmp_addr, deposit32(OPC_J, 0, 26, addr >> 2)); flush_icache_range(jmp_addr, jmp_addr + 4); } diff --git a/tcg/optimize.c b/tcg/optimize.c index 53aa8e53292e3881052fcf33dba0701fc8a45cc9..220f4601d5a3e50d9b7124fb460469f6e60f3157 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -1109,6 +1109,21 @@ void tcg_optimize(TCGContext *s) } goto do_default; + case INDEX_op_dup2_vec: + assert(TCG_TARGET_REG_BITS == 32); + if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) { + tmp = arg_info(op->args[1])->val; + if (tmp == arg_info(op->args[2])->val) { + tcg_opt_gen_movi(s, op, op->args[0], tmp); + break; + } + } else if (args_are_copies(op->args[1], op->args[2])) { + op->opc = INDEX_op_dup_vec; + TCGOP_VECE(op) = MO_32; + nb_iargs = 1; + } + goto do_default; + CASE_OP_32_64(not): CASE_OP_32_64(neg): CASE_OP_32_64(ext8s): diff --git a/tcg/ppc/tcg-target.inc.c b/tcg/ppc/tcg-target.c.inc similarity index 98% rename from tcg/ppc/tcg-target.inc.c rename to tcg/ppc/tcg-target.c.inc index ee1f9227c15a2af2bace2cc1a3b0b798a88df78c..18ee989f95c7ae897fcd440132124b9925281f73 100644 --- a/tcg/ppc/tcg-target.inc.c +++ b/tcg/ppc/tcg-target.c.inc @@ -23,7 +23,7 @@ */ #include "elf.h" -#include "../tcg-pool.inc.c" +#include "../tcg-pool.c.inc" #if defined _CALL_DARWIN || defined __APPLE__ #define TCG_TARGET_CALL_DARWIN @@ -224,34 +224,29 @@ static const char *target_parse_constraint(TCGArgConstraint *ct, { switch (*ct_str++) { case 'A': case 'B': case 'C': case 'D': - ct->ct |= TCG_CT_REG; - tcg_regset_set_reg(ct->u.regs, 3 + ct_str[0] - 'A'); + tcg_regset_set_reg(ct->regs, 3 + ct_str[0] - 'A'); break; case 'r': - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xffffffff; + ct->regs = 0xffffffff; break; case 'v': - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xffffffff00000000ull; + ct->regs = 0xffffffff00000000ull; break; case 'L': /* qemu_ld constraint */ - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xffffffff; - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3); + ct->regs = 0xffffffff; + tcg_regset_reset_reg(ct->regs, TCG_REG_R3); #ifdef CONFIG_SOFTMMU - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5); + tcg_regset_reset_reg(ct->regs, TCG_REG_R4); + tcg_regset_reset_reg(ct->regs, TCG_REG_R5); #endif break; case 'S': /* qemu_st constraint */ - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xffffffff; - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3); + ct->regs = 0xffffffff; + tcg_regset_reset_reg(ct->regs, TCG_REG_R3); #ifdef CONFIG_SOFTMMU - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6); + tcg_regset_reset_reg(ct->regs, TCG_REG_R4); + tcg_regset_reset_reg(ct->regs, TCG_REG_R5); + tcg_regset_reset_reg(ct->regs, TCG_REG_R6); #endif break; case 'I': @@ -564,6 +559,7 @@ static int tcg_target_const_match(tcg_target_long val, TCGType type, #define VMULOUH VX4(72) #define VMULOUW VX4(136) /* v2.07 */ #define VMULUWM VX4(137) /* v2.07 */ +#define VMULLD VX4(457) /* v3.10 */ #define VMSUMUHM VX4(38) #define VMRGHB VX4(12) @@ -1755,13 +1751,13 @@ void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr, #endif /* As per the enclosing if, this is ppc64. Avoid the _Static_assert - within atomic_set that would fail to build a ppc32 host. */ - atomic_set__nocheck((uint64_t *)jmp_addr, pair); + within qatomic_set that would fail to build a ppc32 host. */ + qatomic_set__nocheck((uint64_t *)jmp_addr, pair); flush_icache_range(jmp_addr, jmp_addr + 8); } else { intptr_t diff = addr - jmp_addr; tcg_debug_assert(in_range_b(diff)); - atomic_set((uint32_t *)jmp_addr, B | (diff & 0x3fffffc)); + qatomic_set((uint32_t *)jmp_addr, B | (diff & 0x3fffffc)); flush_icache_range(jmp_addr, jmp_addr + 4); } } @@ -1845,7 +1841,7 @@ static const uint32_t qemu_exts_opc[4] = { }; #if defined (CONFIG_SOFTMMU) -#include "../tcg-ldst.inc.c" +#include "../tcg-ldst.c.inc" /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, * int mmu_idx, uintptr_t ra) @@ -2610,21 +2606,24 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_shl_i32: if (const_args[2]) { - tcg_out_shli32(s, args[0], args[1], args[2]); + /* Limit immediate shift count lest we create an illegal insn. */ + tcg_out_shli32(s, args[0], args[1], args[2] & 31); } else { tcg_out32(s, SLW | SAB(args[1], args[0], args[2])); } break; case INDEX_op_shr_i32: if (const_args[2]) { - tcg_out_shri32(s, args[0], args[1], args[2]); + /* Limit immediate shift count lest we create an illegal insn. */ + tcg_out_shri32(s, args[0], args[1], args[2] & 31); } else { tcg_out32(s, SRW | SAB(args[1], args[0], args[2])); } break; case INDEX_op_sar_i32: if (const_args[2]) { - tcg_out32(s, SRAWI | RS(args[1]) | RA(args[0]) | SH(args[2])); + /* Limit immediate shift count lest we create an illegal insn. */ + tcg_out32(s, SRAWI | RS(args[1]) | RA(args[0]) | SH(args[2] & 31)); } else { tcg_out32(s, SRAW | SAB(args[1], args[0], args[2])); } @@ -2696,14 +2695,16 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_shl_i64: if (const_args[2]) { - tcg_out_shli64(s, args[0], args[1], args[2]); + /* Limit immediate shift count lest we create an illegal insn. */ + tcg_out_shli64(s, args[0], args[1], args[2] & 63); } else { tcg_out32(s, SLD | SAB(args[1], args[0], args[2])); } break; case INDEX_op_shr_i64: if (const_args[2]) { - tcg_out_shri64(s, args[0], args[1], args[2]); + /* Limit immediate shift count lest we create an illegal insn. */ + tcg_out_shri64(s, args[0], args[1], args[2] & 63); } else { tcg_out32(s, SRD | SAB(args[1], args[0], args[2])); } @@ -2995,6 +2996,7 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece) case INDEX_op_shlv_vec: case INDEX_op_shrv_vec: case INDEX_op_sarv_vec: + case INDEX_op_rotlv_vec: return vece <= MO_32 || have_isa_2_07; case INDEX_op_ssadd_vec: case INDEX_op_sssub_vec: @@ -3005,6 +3007,7 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece) case INDEX_op_shli_vec: case INDEX_op_shri_vec: case INDEX_op_sari_vec: + case INDEX_op_rotli_vec: return vece <= MO_32 || have_isa_2_07 ? -1 : 0; case INDEX_op_neg_vec: return vece >= MO_32 && have_isa_3_00; @@ -3015,10 +3018,14 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece) return -1; case MO_32: return have_isa_2_07 ? 1 : -1; + case MO_64: + return have_isa_3_10; } return 0; case INDEX_op_bitsel_vec: return have_vsx; + case INDEX_op_rotrv_vec: + return -1; default: return 0; } @@ -3149,6 +3156,7 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc, static const uint32_t add_op[4] = { VADDUBM, VADDUHM, VADDUWM, VADDUDM }, sub_op[4] = { VSUBUBM, VSUBUHM, VSUBUWM, VSUBUDM }, + mul_op[4] = { 0, 0, VMULUWM, VMULLD }, neg_op[4] = { 0, 0, VNEGW, VNEGD }, eq_op[4] = { VCMPEQUB, VCMPEQUH, VCMPEQUW, VCMPEQUD }, ne_op[4] = { VCMPNEB, VCMPNEH, VCMPNEW, 0 }, @@ -3199,8 +3207,7 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc, a1 = 0; break; case INDEX_op_mul_vec: - tcg_debug_assert(vece == MO_32 && have_isa_2_07); - insn = VMULUWM; + insn = mul_op[vece]; break; case INDEX_op_ssadd_vec: insn = ssadd_op[vece]; @@ -3301,7 +3308,7 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc, case INDEX_op_ppc_pkum_vec: insn = pkum_op[vece]; break; - case INDEX_op_ppc_rotl_vec: + case INDEX_op_rotlv_vec: insn = rotl_op[vece]; break; case INDEX_op_ppc_msum_vec: @@ -3409,7 +3416,7 @@ static void expand_vec_mul(TCGType type, unsigned vece, TCGv_vec v0, t3 = tcg_temp_new_vec(type); t4 = tcg_temp_new_vec(type); tcg_gen_dupi_vec(MO_8, t4, -16); - vec_gen_3(INDEX_op_ppc_rotl_vec, type, MO_32, tcgv_vec_arg(t1), + vec_gen_3(INDEX_op_rotlv_vec, type, MO_32, tcgv_vec_arg(t1), tcgv_vec_arg(v2), tcgv_vec_arg(t4)); vec_gen_3(INDEX_op_ppc_mulou_vec, type, MO_16, tcgv_vec_arg(t2), tcgv_vec_arg(v1), tcgv_vec_arg(v2)); @@ -3434,7 +3441,7 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, TCGArg a0, ...) { va_list va; - TCGv_vec v0, v1, v2; + TCGv_vec v0, v1, v2, t0; TCGArg a2; va_start(va, a0); @@ -3452,6 +3459,9 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, case INDEX_op_sari_vec: expand_vec_shi(type, vece, v0, v1, a2, INDEX_op_sarv_vec); break; + case INDEX_op_rotli_vec: + expand_vec_shi(type, vece, v0, v1, a2, INDEX_op_rotlv_vec); + break; case INDEX_op_cmp_vec: v2 = temp_tcgv_vec(arg_temp(a2)); expand_vec_cmp(type, vece, v0, v1, v2, va_arg(va, TCGArg)); @@ -3460,6 +3470,13 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, v2 = temp_tcgv_vec(arg_temp(a2)); expand_vec_mul(type, vece, v0, v1, v2); break; + case INDEX_op_rotlv_vec: + v2 = temp_tcgv_vec(arg_temp(a2)); + t0 = tcg_temp_new_vec(type); + tcg_gen_neg_vec(vece, t0, v2); + tcg_gen_rotlv_vec(vece, v0, v1, t0); + tcg_temp_free_vec(t0); + break; default: g_assert_not_reached(); } @@ -3664,12 +3681,13 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op) case INDEX_op_shlv_vec: case INDEX_op_shrv_vec: case INDEX_op_sarv_vec: + case INDEX_op_rotlv_vec: + case INDEX_op_rotrv_vec: case INDEX_op_ppc_mrgh_vec: case INDEX_op_ppc_mrgl_vec: case INDEX_op_ppc_muleu_vec: case INDEX_op_ppc_mulou_vec: case INDEX_op_ppc_pkum_vec: - case INDEX_op_ppc_rotl_vec: case INDEX_op_dup2_vec: return &v_v_v; case INDEX_op_not_vec: @@ -3709,6 +3727,11 @@ static void tcg_target_init(TCGContext *s) have_isa = tcg_isa_3_00; } #endif +#ifdef PPC_FEATURE2_ARCH_3_10 + if (hwcap2 & PPC_FEATURE2_ARCH_3_10) { + have_isa = tcg_isa_3_10; + } +#endif #ifdef PPC_FEATURE2_HAS_ISEL /* Prefer explicit instruction from the kernel. */ diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h index 4fa21f0e71bf0b2b910e0caa092f6cb526aa3d4e..be1036395680c8d9c9b337c57312a47a874df8a6 100644 --- a/tcg/ppc/tcg-target.h +++ b/tcg/ppc/tcg-target.h @@ -63,6 +63,7 @@ typedef enum { tcg_isa_2_06, tcg_isa_2_07, tcg_isa_3_00, + tcg_isa_3_10, } TCGPowerISA; extern TCGPowerISA have_isa; @@ -72,6 +73,7 @@ extern bool have_vsx; #define have_isa_2_06 (have_isa >= tcg_isa_2_06) #define have_isa_2_07 (have_isa >= tcg_isa_2_07) #define have_isa_3_00 (have_isa >= tcg_isa_3_00) +#define have_isa_3_10 (have_isa >= tcg_isa_3_10) /* optional instructions automatically implemented */ #define TCG_TARGET_HAS_ext8u_i32 0 /* andi */ @@ -161,10 +163,12 @@ extern bool have_vsx; #define TCG_TARGET_HAS_not_vec 1 #define TCG_TARGET_HAS_neg_vec have_isa_3_00 #define TCG_TARGET_HAS_abs_vec 0 +#define TCG_TARGET_HAS_roti_vec 0 +#define TCG_TARGET_HAS_rots_vec 0 +#define TCG_TARGET_HAS_rotv_vec 1 #define TCG_TARGET_HAS_shi_vec 0 #define TCG_TARGET_HAS_shs_vec 0 #define TCG_TARGET_HAS_shv_vec 1 -#define TCG_TARGET_HAS_cmp_vec 1 #define TCG_TARGET_HAS_mul_vec 1 #define TCG_TARGET_HAS_sat_vec 1 #define TCG_TARGET_HAS_minmax_vec 1 diff --git a/tcg/ppc/tcg-target.opc.h b/tcg/ppc/tcg-target.opc.h index 1373f77e82f87ba579d2d4b1a9153a8faa9007be..db514403c3f562f47d6948e43a5271d92c464131 100644 --- a/tcg/ppc/tcg-target.opc.h +++ b/tcg/ppc/tcg-target.opc.h @@ -30,4 +30,3 @@ DEF(ppc_msum_vec, 1, 3, 0, IMPLVEC) DEF(ppc_muleu_vec, 1, 2, 0, IMPLVEC) DEF(ppc_mulou_vec, 1, 2, 0, IMPLVEC) DEF(ppc_pkum_vec, 1, 2, 0, IMPLVEC) -DEF(ppc_rotl_vec, 1, 2, 0, IMPLVEC) diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.c.inc similarity index 98% rename from tcg/riscv/tcg-target.inc.c rename to tcg/riscv/tcg-target.c.inc index 2bc0ba71f2834885e14b0ec0264322de4290844d..d536f3ccc17cb336361aefefeb34b6d481d78993 100644 --- a/tcg/riscv/tcg-target.inc.c +++ b/tcg/riscv/tcg-target.c.inc @@ -27,7 +27,7 @@ * THE SOFTWARE. */ -#include "../tcg-pool.inc.c" +#include "../tcg-pool.c.inc" #ifdef CONFIG_DEBUG_TCG static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { @@ -137,20 +137,18 @@ static const char *target_parse_constraint(TCGArgConstraint *ct, { switch (*ct_str++) { case 'r': - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xffffffff; + ct->regs = 0xffffffff; break; case 'L': /* qemu_ld/qemu_st constraint */ - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xffffffff; + ct->regs = 0xffffffff; /* qemu_ld/qemu_st uses TCG_REG_TMP0 */ #if defined(CONFIG_SOFTMMU) - tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[0]); - tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[1]); - tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[2]); - tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[3]); - tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[4]); + tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[0]); + tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[1]); + tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[2]); + tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[3]); + tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[4]); #endif break; case 'I': @@ -502,10 +500,8 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type, break; case R_RISCV_JAL: return reloc_jimm20(code_ptr, (tcg_insn_unit *)value); - break; case R_RISCV_CALL: return reloc_call(code_ptr, (tcg_insn_unit *)value); - break; default: tcg_abort(); } @@ -921,7 +917,7 @@ static void tcg_out_mb(TCGContext *s, TCGArg a0) */ #if defined(CONFIG_SOFTMMU) -#include "../tcg-ldst.inc.c" +#include "../tcg-ldst.c.inc" /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr, * TCGMemOpIdx oi, uintptr_t ra) diff --git a/tcg/s390/tcg-target.inc.c b/tcg/s390/tcg-target.c.inc similarity index 99% rename from tcg/s390/tcg-target.inc.c rename to tcg/s390/tcg-target.c.inc index b07e9ff7d66c747d9f9aa2b8386d42909b032d19..c5e096449b304b7bf14f5a2b6461a99137f99468 100644 --- a/tcg/s390/tcg-target.inc.c +++ b/tcg/s390/tcg-target.c.inc @@ -29,7 +29,7 @@ #error "unsupported code generation mode" #endif -#include "../tcg-pool.inc.c" +#include "../tcg-pool.c.inc" #include "elf.h" /* ??? The translation blocks produced by TCG are generally small enough to @@ -408,25 +408,21 @@ static const char *target_parse_constraint(TCGArgConstraint *ct, { switch (*ct_str++) { case 'r': /* all registers */ - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xffff; + ct->regs = 0xffff; break; case 'L': /* qemu_ld/st constraint */ - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xffff; - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4); + ct->regs = 0xffff; + tcg_regset_reset_reg(ct->regs, TCG_REG_R2); + tcg_regset_reset_reg(ct->regs, TCG_REG_R3); + tcg_regset_reset_reg(ct->regs, TCG_REG_R4); break; case 'a': /* force R2 for division */ - ct->ct |= TCG_CT_REG; - ct->u.regs = 0; - tcg_regset_set_reg(ct->u.regs, TCG_REG_R2); + ct->regs = 0; + tcg_regset_set_reg(ct->regs, TCG_REG_R2); break; case 'b': /* force R3 for division */ - ct->ct |= TCG_CT_REG; - ct->u.regs = 0; - tcg_regset_set_reg(ct->u.regs, TCG_REG_R3); + ct->regs = 0; + tcg_regset_set_reg(ct->regs, TCG_REG_R3); break; case 'A': ct->ct |= TCG_CT_CONST_S33; @@ -1536,7 +1532,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, MemOp opc, TCGReg data, } #if defined(CONFIG_SOFTMMU) -#include "../tcg-ldst.inc.c" +#include "../tcg-ldst.c.inc" /* We're expecting to use a 20-bit negative offset on the tlb memory ops. */ QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0); diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h index 07accabbd1515a1aec70805e12bcfa9c19a0ab33..63c8797bd3587891699ee2add4b83e671d92e94e 100644 --- a/tcg/s390/tcg-target.h +++ b/tcg/s390/tcg-target.h @@ -154,7 +154,7 @@ static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, { /* patch the branch destination */ intptr_t disp = addr - (jmp_addr - 2); - atomic_set((int32_t *)jmp_addr, disp / 2); + qatomic_set((int32_t *)jmp_addr, disp / 2); /* no need to flush icache explicitly */ } diff --git a/tcg/sparc/tcg-target.inc.c b/tcg/sparc/tcg-target.c.inc similarity index 98% rename from tcg/sparc/tcg-target.inc.c rename to tcg/sparc/tcg-target.c.inc index 65fddb310d4b42a0986657de45c3fc15be648e29..6775bd30fc9fba63800ed9aac9e71dddc8154f70 100644 --- a/tcg/sparc/tcg-target.inc.c +++ b/tcg/sparc/tcg-target.c.inc @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "../tcg-pool.inc.c" +#include "../tcg-pool.c.inc" #ifdef CONFIG_DEBUG_TCG static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { @@ -325,28 +325,23 @@ static const char *target_parse_constraint(TCGArgConstraint *ct, { switch (*ct_str++) { case 'r': - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xffffffff; + ct->regs = 0xffffffff; break; case 'R': - ct->ct |= TCG_CT_REG; - ct->u.regs = ALL_64; + ct->regs = ALL_64; break; case 'A': /* qemu_ld/st address constraint */ - ct->ct |= TCG_CT_REG; - ct->u.regs = TARGET_LONG_BITS == 64 ? ALL_64 : 0xffffffff; + ct->regs = TARGET_LONG_BITS == 64 ? ALL_64 : 0xffffffff; reserve_helpers: - tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2); + tcg_regset_reset_reg(ct->regs, TCG_REG_O0); + tcg_regset_reset_reg(ct->regs, TCG_REG_O1); + tcg_regset_reset_reg(ct->regs, TCG_REG_O2); break; case 's': /* qemu_st data 32-bit constraint */ - ct->ct |= TCG_CT_REG; - ct->u.regs = 0xffffffff; + ct->regs = 0xffffffff; goto reserve_helpers; case 'S': /* qemu_st data 64-bit constraint */ - ct->ct |= TCG_CT_REG; - ct->u.regs = ALL_64; + ct->regs = ALL_64; goto reserve_helpers; case 'I': ct->ct |= TCG_CT_CONST_S11; @@ -1839,7 +1834,8 @@ void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr, tcg_debug_assert(br_disp == (int32_t)br_disp); if (!USE_REG_TB) { - atomic_set((uint32_t *)jmp_addr, deposit32(CALL, 0, 30, br_disp >> 2)); + qatomic_set((uint32_t *)jmp_addr, + deposit32(CALL, 0, 30, br_disp >> 2)); flush_icache_range(jmp_addr, jmp_addr + 4); return; } @@ -1863,6 +1859,6 @@ void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr, | INSN_IMM13((tb_disp & 0x3ff) | -0x400)); } - atomic_set((uint64_t *)jmp_addr, deposit64(i2, 32, 32, i1)); + qatomic_set((uint64_t *)jmp_addr, deposit64(i2, 32, 32, i1)); flush_icache_range(jmp_addr, jmp_addr + 8); } diff --git a/tcg/tcg-ldst.inc.c b/tcg/tcg-ldst.c.inc similarity index 100% rename from tcg/tcg-ldst.inc.c rename to tcg/tcg-ldst.c.inc diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c index 049a55e700f50e17c0210ddb730be51ec653d9db..ddbe06b71a81fad997c6348b68d9a1f233553118 100644 --- a/tcg/tcg-op-gvec.c +++ b/tcg/tcg-op-gvec.c @@ -37,11 +37,21 @@ static const TCGOpcode vecop_list_empty[1] = { 0 }; of the operand offsets so that we can check them all at once. */ static void check_size_align(uint32_t oprsz, uint32_t maxsz, uint32_t ofs) { - uint32_t opr_align = oprsz >= 16 ? 15 : 7; - uint32_t max_align = maxsz >= 16 || oprsz >= 16 ? 15 : 7; - tcg_debug_assert(oprsz > 0); - tcg_debug_assert(oprsz <= maxsz); - tcg_debug_assert((oprsz & opr_align) == 0); + uint32_t max_align; + + switch (oprsz) { + case 8: + case 16: + case 32: + tcg_debug_assert(oprsz <= maxsz); + break; + default: + tcg_debug_assert(oprsz == maxsz); + break; + } + tcg_debug_assert(maxsz <= (8 << SIMD_MAXSZ_BITS)); + + max_align = maxsz >= 16 ? 15 : 7; tcg_debug_assert((maxsz & max_align) == 0); tcg_debug_assert((ofs & max_align) == 0); } @@ -77,12 +87,21 @@ uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t data) { uint32_t desc = 0; - assert(oprsz % 8 == 0 && oprsz <= (8 << SIMD_OPRSZ_BITS)); - assert(maxsz % 8 == 0 && maxsz <= (8 << SIMD_MAXSZ_BITS)); - assert(data == sextract32(data, 0, SIMD_DATA_BITS)); + check_size_align(oprsz, maxsz, 0); + tcg_debug_assert(data == sextract32(data, 0, SIMD_DATA_BITS)); oprsz = (oprsz / 8) - 1; maxsz = (maxsz / 8) - 1; + + /* + * We have just asserted in check_size_align that either + * oprsz is {8,16,32} or matches maxsz. Encode the final + * case with '2', as that would otherwise map to 24. + */ + if (oprsz == maxsz) { + oprsz = 2; + } + desc = deposit32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS, oprsz); desc = deposit32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS, maxsz); desc = deposit32(desc, SIMD_DATA_SHIFT, SIMD_DATA_BITS, data); @@ -1570,18 +1589,16 @@ void tcg_gen_gvec_dup_mem(unsigned vece, uint32_t dofs, uint32_t aofs, do_dup(vece, dofs, oprsz, maxsz, NULL, in, 0); tcg_temp_free_i64(in); } - } else { + } else if (vece == 4) { /* 128-bit duplicate. */ - /* ??? Dup to 256-bit vector. */ int i; - tcg_debug_assert(vece == 4); tcg_debug_assert(oprsz >= 16); if (TCG_TARGET_HAS_v128) { TCGv_vec in = tcg_temp_new_vec(TCG_TYPE_V128); tcg_gen_ld_vec(in, cpu_env, aofs); - for (i = 0; i < oprsz; i += 16) { + for (i = (aofs == dofs) * 16; i < oprsz; i += 16) { tcg_gen_st_vec(in, cpu_env, dofs + i); } tcg_temp_free_vec(in); @@ -1591,7 +1608,7 @@ void tcg_gen_gvec_dup_mem(unsigned vece, uint32_t dofs, uint32_t aofs, tcg_gen_ld_i64(in0, cpu_env, aofs); tcg_gen_ld_i64(in1, cpu_env, aofs + 8); - for (i = 0; i < oprsz; i += 16) { + for (i = (aofs == dofs) * 16; i < oprsz; i += 16) { tcg_gen_st_i64(in0, cpu_env, dofs + i); tcg_gen_st_i64(in1, cpu_env, dofs + i + 8); } @@ -1601,6 +1618,54 @@ void tcg_gen_gvec_dup_mem(unsigned vece, uint32_t dofs, uint32_t aofs, if (oprsz < maxsz) { expand_clr(dofs + oprsz, maxsz - oprsz); } + } else if (vece == 5) { + /* 256-bit duplicate. */ + int i; + + tcg_debug_assert(oprsz >= 32); + tcg_debug_assert(oprsz % 32 == 0); + if (TCG_TARGET_HAS_v256) { + TCGv_vec in = tcg_temp_new_vec(TCG_TYPE_V256); + + tcg_gen_ld_vec(in, cpu_env, aofs); + for (i = (aofs == dofs) * 32; i < oprsz; i += 32) { + tcg_gen_st_vec(in, cpu_env, dofs + i); + } + tcg_temp_free_vec(in); + } else if (TCG_TARGET_HAS_v128) { + TCGv_vec in0 = tcg_temp_new_vec(TCG_TYPE_V128); + TCGv_vec in1 = tcg_temp_new_vec(TCG_TYPE_V128); + + tcg_gen_ld_vec(in0, cpu_env, aofs); + tcg_gen_ld_vec(in1, cpu_env, aofs + 16); + for (i = (aofs == dofs) * 32; i < oprsz; i += 32) { + tcg_gen_st_vec(in0, cpu_env, dofs + i); + tcg_gen_st_vec(in1, cpu_env, dofs + i + 16); + } + tcg_temp_free_vec(in0); + tcg_temp_free_vec(in1); + } else { + TCGv_i64 in[4]; + int j; + + for (j = 0; j < 4; ++j) { + in[j] = tcg_temp_new_i64(); + tcg_gen_ld_i64(in[j], cpu_env, aofs + j * 8); + } + for (i = (aofs == dofs) * 32; i < oprsz; i += 32) { + for (j = 0; j < 4; ++j) { + tcg_gen_st_i64(in[j], cpu_env, dofs + i + j * 8); + } + } + for (j = 0; j < 4; ++j) { + tcg_temp_free_i64(in[j]); + } + } + if (oprsz < maxsz) { + expand_clr(dofs + oprsz, maxsz - oprsz); + } + } else { + g_assert_not_reached(); } } @@ -2264,12 +2329,13 @@ static void gen_absv_mask(TCGv_i64 d, TCGv_i64 b, unsigned vece) tcg_gen_muli_i64(t, t, (1 << nbit) - 1); /* - * Invert (via xor -1) and add one (via sub -1). + * Invert (via xor -1) and add one. * Because of the ordering the msb is cleared, * so we never have carry into the next element. */ tcg_gen_xor_i64(d, b, t); - tcg_gen_sub_i64(d, d, t); + tcg_gen_andi_i64(t, t, dup_const(vece, 1)); + tcg_gen_add_i64(d, d, t); tcg_temp_free_i64(t); } @@ -2694,6 +2760,74 @@ void tcg_gen_gvec_sari(unsigned vece, uint32_t dofs, uint32_t aofs, } } +void tcg_gen_vec_rotl8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) +{ + uint64_t mask = dup_const(MO_8, 0xff << c); + + tcg_gen_shli_i64(d, a, c); + tcg_gen_shri_i64(a, a, 8 - c); + tcg_gen_andi_i64(d, d, mask); + tcg_gen_andi_i64(a, a, ~mask); + tcg_gen_or_i64(d, d, a); +} + +void tcg_gen_vec_rotl16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c) +{ + uint64_t mask = dup_const(MO_16, 0xffff << c); + + tcg_gen_shli_i64(d, a, c); + tcg_gen_shri_i64(a, a, 16 - c); + tcg_gen_andi_i64(d, d, mask); + tcg_gen_andi_i64(a, a, ~mask); + tcg_gen_or_i64(d, d, a); +} + +void tcg_gen_gvec_rotli(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t shift, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_rotli_vec, 0 }; + static const GVecGen2i g[4] = { + { .fni8 = tcg_gen_vec_rotl8i_i64, + .fniv = tcg_gen_rotli_vec, + .fno = gen_helper_gvec_rotl8i, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fni8 = tcg_gen_vec_rotl16i_i64, + .fniv = tcg_gen_rotli_vec, + .fno = gen_helper_gvec_rotl16i, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_rotli_i32, + .fniv = tcg_gen_rotli_vec, + .fno = gen_helper_gvec_rotl32i, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_rotli_i64, + .fniv = tcg_gen_rotli_vec, + .fno = gen_helper_gvec_rotl64i, + .opt_opc = vecop_list, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_debug_assert(shift >= 0 && shift < (8 << vece)); + if (shift == 0) { + tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz); + } else { + tcg_gen_gvec_2i(dofs, aofs, oprsz, maxsz, shift, &g[vece]); + } +} + +void tcg_gen_gvec_rotri(unsigned vece, uint32_t dofs, uint32_t aofs, + int64_t shift, uint32_t oprsz, uint32_t maxsz) +{ + tcg_debug_assert(vece <= MO_64); + tcg_debug_assert(shift >= 0 && shift < (8 << vece)); + tcg_gen_gvec_rotli(vece, dofs, aofs, -shift & ((8 << vece) - 1), + oprsz, maxsz); +} + /* * Specialized generation vector shifts by a non-constant scalar. */ @@ -2908,6 +3042,28 @@ void tcg_gen_gvec_sars(unsigned vece, uint32_t dofs, uint32_t aofs, do_gvec_shifts(vece, dofs, aofs, shift, oprsz, maxsz, &g); } +void tcg_gen_gvec_rotls(unsigned vece, uint32_t dofs, uint32_t aofs, + TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz) +{ + static const GVecGen2sh g = { + .fni4 = tcg_gen_rotl_i32, + .fni8 = tcg_gen_rotl_i64, + .fniv_s = tcg_gen_rotls_vec, + .fniv_v = tcg_gen_rotlv_vec, + .fno = { + gen_helper_gvec_rotl8i, + gen_helper_gvec_rotl16i, + gen_helper_gvec_rotl32i, + gen_helper_gvec_rotl64i, + }, + .s_list = { INDEX_op_rotls_vec, 0 }, + .v_list = { INDEX_op_rotlv_vec, 0 }, + }; + + tcg_debug_assert(vece <= MO_64); + do_gvec_shifts(vece, dofs, aofs, shift, oprsz, maxsz, &g); +} + /* * Expand D = A << (B % element bits) * @@ -3103,6 +3259,128 @@ void tcg_gen_gvec_sarv(unsigned vece, uint32_t dofs, uint32_t aofs, tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); } +/* + * Similarly for rotates. + */ + +static void tcg_gen_rotlv_mod_vec(unsigned vece, TCGv_vec d, + TCGv_vec a, TCGv_vec b) +{ + TCGv_vec t = tcg_temp_new_vec_matching(d); + + tcg_gen_dupi_vec(vece, t, (8 << vece) - 1); + tcg_gen_and_vec(vece, t, t, b); + tcg_gen_rotlv_vec(vece, d, a, t); + tcg_temp_free_vec(t); +} + +static void tcg_gen_rotl_mod_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) +{ + TCGv_i32 t = tcg_temp_new_i32(); + + tcg_gen_andi_i32(t, b, 31); + tcg_gen_rotl_i32(d, a, t); + tcg_temp_free_i32(t); +} + +static void tcg_gen_rotl_mod_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) +{ + TCGv_i64 t = tcg_temp_new_i64(); + + tcg_gen_andi_i64(t, b, 63); + tcg_gen_rotl_i64(d, a, t); + tcg_temp_free_i64(t); +} + +void tcg_gen_gvec_rotlv(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_rotlv_vec, 0 }; + static const GVecGen3 g[4] = { + { .fniv = tcg_gen_rotlv_mod_vec, + .fno = gen_helper_gvec_rotl8v, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fniv = tcg_gen_rotlv_mod_vec, + .fno = gen_helper_gvec_rotl16v, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_rotl_mod_i32, + .fniv = tcg_gen_rotlv_mod_vec, + .fno = gen_helper_gvec_rotl32v, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_rotl_mod_i64, + .fniv = tcg_gen_rotlv_mod_vec, + .fno = gen_helper_gvec_rotl64v, + .opt_opc = vecop_list, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + +static void tcg_gen_rotrv_mod_vec(unsigned vece, TCGv_vec d, + TCGv_vec a, TCGv_vec b) +{ + TCGv_vec t = tcg_temp_new_vec_matching(d); + + tcg_gen_dupi_vec(vece, t, (8 << vece) - 1); + tcg_gen_and_vec(vece, t, t, b); + tcg_gen_rotrv_vec(vece, d, a, t); + tcg_temp_free_vec(t); +} + +static void tcg_gen_rotr_mod_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) +{ + TCGv_i32 t = tcg_temp_new_i32(); + + tcg_gen_andi_i32(t, b, 31); + tcg_gen_rotr_i32(d, a, t); + tcg_temp_free_i32(t); +} + +static void tcg_gen_rotr_mod_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) +{ + TCGv_i64 t = tcg_temp_new_i64(); + + tcg_gen_andi_i64(t, b, 63); + tcg_gen_rotr_i64(d, a, t); + tcg_temp_free_i64(t); +} + +void tcg_gen_gvec_rotrv(unsigned vece, uint32_t dofs, uint32_t aofs, + uint32_t bofs, uint32_t oprsz, uint32_t maxsz) +{ + static const TCGOpcode vecop_list[] = { INDEX_op_rotrv_vec, 0 }; + static const GVecGen3 g[4] = { + { .fniv = tcg_gen_rotrv_mod_vec, + .fno = gen_helper_gvec_rotr8v, + .opt_opc = vecop_list, + .vece = MO_8 }, + { .fniv = tcg_gen_rotrv_mod_vec, + .fno = gen_helper_gvec_rotr16v, + .opt_opc = vecop_list, + .vece = MO_16 }, + { .fni4 = tcg_gen_rotr_mod_i32, + .fniv = tcg_gen_rotrv_mod_vec, + .fno = gen_helper_gvec_rotr32v, + .opt_opc = vecop_list, + .vece = MO_32 }, + { .fni8 = tcg_gen_rotr_mod_i64, + .fniv = tcg_gen_rotrv_mod_vec, + .fno = gen_helper_gvec_rotr64v, + .opt_opc = vecop_list, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, + }; + + tcg_debug_assert(vece <= MO_64); + tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]); +} + /* Expand OPSZ bytes worth of three-operand operations using i32 elements. */ static void expand_cmp_i32(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, TCGCond cond) diff --git a/tcg/tcg-op-vec.c b/tcg/tcg-op-vec.c index b6937e8d6484cbdce9c59c805708eb6b3b5c14f3..cdbf11c573edb9b21b0f7e591aad5093182011d9 100644 --- a/tcg/tcg-op-vec.c +++ b/tcg/tcg-op-vec.c @@ -252,10 +252,10 @@ TCGv_vec tcg_const_ones_vec_matching(TCGv_vec m) void tcg_gen_dup64i_vec(TCGv_vec r, uint64_t a) { - if (TCG_TARGET_REG_BITS == 32 && a == deposit64(a, 32, 32, a)) { - do_dupi_vec(r, MO_32, a); - } else if (TCG_TARGET_REG_BITS == 64 || a == (uint64_t)(int32_t)a) { + if (TCG_TARGET_REG_BITS == 64) { do_dupi_vec(r, MO_64, a); + } else if (a == dup_const(MO_32, a)) { + do_dupi_vec(r, MO_32, a); } else { TCGv_i64 c = tcg_const_i64(a); tcg_gen_dup_i64_vec(MO_64, r, c); @@ -280,7 +280,11 @@ void tcg_gen_dup8i_vec(TCGv_vec r, uint32_t a) void tcg_gen_dupi_vec(unsigned vece, TCGv_vec r, uint64_t a) { - do_dupi_vec(r, MO_REG, dup_const(vece, a)); + if (vece == MO_64) { + tcg_gen_dup64i_vec(r, a); + } else { + do_dupi_vec(r, MO_REG, dup_const(vece, a)); + } } void tcg_gen_dup_i64_vec(unsigned vece, TCGv_vec r, TCGv_i64 a) @@ -545,6 +549,18 @@ void tcg_gen_sari_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i) do_shifti(INDEX_op_sari_vec, vece, r, a, i); } +void tcg_gen_rotli_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i) +{ + do_shifti(INDEX_op_rotli_vec, vece, r, a, i); +} + +void tcg_gen_rotri_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i) +{ + int bits = 8 << vece; + tcg_debug_assert(i >= 0 && i < bits); + do_shifti(INDEX_op_rotli_vec, vece, r, a, -i & (bits - 1)); +} + void tcg_gen_cmp_vec(TCGCond cond, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { @@ -645,7 +661,9 @@ static void do_minmax(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b, TCGOpcode opc, TCGCond cond) { if (!do_op3(vece, r, a, b, opc)) { + const TCGOpcode *hold_list = tcg_swap_vecop_list(NULL); tcg_gen_cmpsel_vec(cond, vece, r, a, b, a, b); + tcg_swap_vecop_list(hold_list); } } @@ -684,8 +702,18 @@ void tcg_gen_sarv_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) do_op3_nofail(vece, r, a, b, INDEX_op_sarv_vec); } +void tcg_gen_rotlv_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) +{ + do_op3_nofail(vece, r, a, b, INDEX_op_rotlv_vec); +} + +void tcg_gen_rotrv_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) +{ + do_op3_nofail(vece, r, a, b, INDEX_op_rotrv_vec); +} + static void do_shifts(unsigned vece, TCGv_vec r, TCGv_vec a, - TCGv_i32 s, TCGOpcode opc_s, TCGOpcode opc_v) + TCGv_i32 s, TCGOpcode opc) { TCGTemp *rt = tcgv_vec_temp(r); TCGTemp *at = tcgv_vec_temp(a); @@ -694,48 +722,40 @@ static void do_shifts(unsigned vece, TCGv_vec r, TCGv_vec a, TCGArg ai = temp_arg(at); TCGArg si = temp_arg(st); TCGType type = rt->base_type; - const TCGOpcode *hold_list; int can; tcg_debug_assert(at->base_type >= type); - tcg_assert_listed_vecop(opc_s); - hold_list = tcg_swap_vecop_list(NULL); - - can = tcg_can_emit_vec_op(opc_s, type, vece); + tcg_assert_listed_vecop(opc); + can = tcg_can_emit_vec_op(opc, type, vece); if (can > 0) { - vec_gen_3(opc_s, type, vece, ri, ai, si); + vec_gen_3(opc, type, vece, ri, ai, si); } else if (can < 0) { - tcg_expand_vec_op(opc_s, type, vece, ri, ai, si); + const TCGOpcode *hold_list = tcg_swap_vecop_list(NULL); + tcg_expand_vec_op(opc, type, vece, ri, ai, si); + tcg_swap_vecop_list(hold_list); } else { - TCGv_vec vec_s = tcg_temp_new_vec(type); - - if (vece == MO_64) { - TCGv_i64 s64 = tcg_temp_new_i64(); - tcg_gen_extu_i32_i64(s64, s); - tcg_gen_dup_i64_vec(MO_64, vec_s, s64); - tcg_temp_free_i64(s64); - } else { - tcg_gen_dup_i32_vec(vece, vec_s, s); - } - do_op3_nofail(vece, r, a, vec_s, opc_v); - tcg_temp_free_vec(vec_s); + g_assert_not_reached(); } - tcg_swap_vecop_list(hold_list); } void tcg_gen_shls_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_i32 b) { - do_shifts(vece, r, a, b, INDEX_op_shls_vec, INDEX_op_shlv_vec); + do_shifts(vece, r, a, b, INDEX_op_shls_vec); } void tcg_gen_shrs_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_i32 b) { - do_shifts(vece, r, a, b, INDEX_op_shrs_vec, INDEX_op_shrv_vec); + do_shifts(vece, r, a, b, INDEX_op_shrs_vec); } void tcg_gen_sars_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_i32 b) { - do_shifts(vece, r, a, b, INDEX_op_sars_vec, INDEX_op_sarv_vec); + do_shifts(vece, r, a, b, INDEX_op_sars_vec); +} + +void tcg_gen_rotls_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_i32 s) +{ + do_shifts(vece, r, a, s, INDEX_op_rotls_vec); } void tcg_gen_bitsel_vec(unsigned vece, TCGv_vec r, TCGv_vec a, diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c index e60b74fb82d4e17966f0573c8ed109209b503f43..4b8a473fad3cb7277b688116ba729cd360a69e53 100644 --- a/tcg/tcg-op.c +++ b/tcg/tcg-op.c @@ -3189,8 +3189,9 @@ static void do_nonatomic_op_i32(TCGv_i32 ret, TCGv addr, TCGv_i32 val, memop = tcg_canonicalize_memop(memop, 0, 0); - tcg_gen_qemu_ld_i32(t1, addr, idx, memop & ~MO_SIGN); - gen(t2, t1, val); + tcg_gen_qemu_ld_i32(t1, addr, idx, memop); + tcg_gen_ext_i32(t2, val, memop); + gen(t2, t1, t2); tcg_gen_qemu_st_i32(t2, addr, idx, memop); tcg_gen_ext_i32(ret, (new_val ? t2 : t1), memop); @@ -3232,8 +3233,9 @@ static void do_nonatomic_op_i64(TCGv_i64 ret, TCGv addr, TCGv_i64 val, memop = tcg_canonicalize_memop(memop, 1, 0); - tcg_gen_qemu_ld_i64(t1, addr, idx, memop & ~MO_SIGN); - gen(t2, t1, val); + tcg_gen_qemu_ld_i64(t1, addr, idx, memop); + tcg_gen_ext_i64(t2, val, memop); + gen(t2, t1, t2); tcg_gen_qemu_st_i64(t2, addr, idx, memop); tcg_gen_ext_i64(ret, (new_val ? t2 : t1), memop); diff --git a/tcg/tcg-pool.inc.c b/tcg/tcg-pool.c.inc similarity index 99% rename from tcg/tcg-pool.inc.c rename to tcg/tcg-pool.c.inc index 4eaa84b63191854dc10044d40c34344b8920d364..82cbcc89bd83e9fe5bff38c6956d3f6a7ebd96d3 100644 --- a/tcg/tcg-pool.inc.c +++ b/tcg/tcg-pool.c.inc @@ -118,7 +118,7 @@ static inline void new_pool_l8(TCGContext *s, int rtype, tcg_insn_unit *label, new_pool_insert(s, n); } -/* To be provided by cpu/tcg-target.inc.c. */ +/* To be provided by cpu/tcg-target.c.inc. */ static void tcg_out_nop_fill(tcg_insn_unit *p, int count); static int tcg_out_pool_finalize(TCGContext *s) diff --git a/tcg/tcg.c b/tcg/tcg.c index a2268d9db0ab91ec7a4795ba1e9120efe509d7cf..43c6cf8f525202e94661c4ead6db02126b262bfc 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -65,7 +65,7 @@ #include "exec/log.h" #include "sysemu/sysemu.h" -/* Forward declarations for functions declared in tcg-target.inc.c and +/* Forward declarations for functions declared in tcg-target.c.inc and used here. */ static void tcg_target_init(TCGContext *s); static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode); @@ -101,7 +101,7 @@ static void tcg_register_jit_int(void *buf, size_t size, size_t debug_frame_size) __attribute__((unused)); -/* Forward declarations for functions declared and used in tcg-target.inc.c. */ +/* Forward declarations for functions declared and used in tcg-target.c.inc. */ static const char *target_parse_constraint(TCGArgConstraint *ct, const char *ct_str, TCGType type); static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, @@ -335,13 +335,14 @@ static bool tcg_resolve_relocs(TCGContext *s) static void set_jmp_reset_offset(TCGContext *s, int which) { - size_t off = tcg_current_code_size(s); - s->tb_jmp_reset_offset[which] = off; - /* Make sure that we didn't overflow the stored offset. */ - assert(s->tb_jmp_reset_offset[which] == off); + /* + * We will check for overflow at the end of the opcode loop in + * tcg_gen_code, where we bound tcg_current_code_size to UINT16_MAX. + */ + s->tb_jmp_reset_offset[which] = tcg_current_code_size(s); } -#include "tcg-target.inc.c" +#include "tcg-target.c.inc" /* compare a pointer @ptr and a tb_tc @s */ static int ptr_cmp_tb_tc(const void *ptr, const struct tb_tc *s) @@ -502,6 +503,14 @@ size_t tcg_nb_tbs(void) return nb_tbs; } +static gboolean tcg_region_tree_traverse(gpointer k, gpointer v, gpointer data) +{ + TranslationBlock *tb = v; + + tb_destroy(tb); + return FALSE; +} + static void tcg_region_tree_reset_all(void) { size_t i; @@ -510,6 +519,7 @@ static void tcg_region_tree_reset_all(void) for (i = 0; i < region.n; i++) { struct tcg_region_tree *rt = region_trees + i * tree_size; + g_tree_foreach(rt->tree, tcg_region_tree_traverse, NULL); /* Increment the refcount first so that destroy acts as a reset */ g_tree_ref(rt->tree); g_tree_destroy(rt->tree); @@ -588,7 +598,7 @@ static inline bool tcg_region_initial_alloc__locked(TCGContext *s) /* Call from a safe-work context */ void tcg_region_reset_all(void) { - unsigned int n_ctxs = atomic_read(&n_tcg_ctxs); + unsigned int n_ctxs = qatomic_read(&n_tcg_ctxs); unsigned int i; qemu_mutex_lock(®ion.lock); @@ -596,7 +606,7 @@ void tcg_region_reset_all(void) region.agg_size_full = 0; for (i = 0; i < n_ctxs; i++) { - TCGContext *s = atomic_read(&tcg_ctxs[i]); + TCGContext *s = qatomic_read(&tcg_ctxs[i]); bool err = tcg_region_initial_alloc__locked(s); g_assert(!err); @@ -785,9 +795,9 @@ void tcg_register_thread(void) } /* Claim an entry in tcg_ctxs */ - n = atomic_fetch_inc(&n_tcg_ctxs); + n = qatomic_fetch_inc(&n_tcg_ctxs); g_assert(n < ms->smp.max_cpus); - atomic_set(&tcg_ctxs[n], s); + qatomic_set(&tcg_ctxs[n], s); if (n > 0) { alloc_tcg_plugin_context(s); @@ -810,17 +820,17 @@ void tcg_register_thread(void) */ size_t tcg_code_size(void) { - unsigned int n_ctxs = atomic_read(&n_tcg_ctxs); + unsigned int n_ctxs = qatomic_read(&n_tcg_ctxs); unsigned int i; size_t total; qemu_mutex_lock(®ion.lock); total = region.agg_size_full; for (i = 0; i < n_ctxs; i++) { - const TCGContext *s = atomic_read(&tcg_ctxs[i]); + const TCGContext *s = qatomic_read(&tcg_ctxs[i]); size_t size; - size = atomic_read(&s->code_gen_ptr) - s->code_gen_buffer; + size = qatomic_read(&s->code_gen_ptr) - s->code_gen_buffer; g_assert(size <= s->code_gen_buffer_size); total += size; } @@ -846,14 +856,14 @@ size_t tcg_code_capacity(void) size_t tcg_tb_phys_invalidate_count(void) { - unsigned int n_ctxs = atomic_read(&n_tcg_ctxs); + unsigned int n_ctxs = qatomic_read(&n_tcg_ctxs); unsigned int i; size_t total = 0; for (i = 0; i < n_ctxs; i++) { - const TCGContext *s = atomic_read(&tcg_ctxs[i]); + const TCGContext *s = qatomic_read(&tcg_ctxs[i]); - total += atomic_read(&s->tb_phys_invalidate_count); + total += qatomic_read(&s->tb_phys_invalidate_count); } return total; } @@ -935,7 +945,6 @@ void tcg_context_init(TCGContext *s) int op, total_args, n, i; TCGOpDef *def; TCGArgConstraint *args_ct; - int *sorted_args; TCGTemp *ts; memset(s, 0, sizeof(*s)); @@ -950,15 +959,12 @@ void tcg_context_init(TCGContext *s) total_args += n; } - args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args); - sorted_args = g_malloc(sizeof(int) * total_args); + args_ct = g_new0(TCGArgConstraint, total_args); for(op = 0; op < NB_OPS; op++) { def = &tcg_op_defs[op]; def->args_ct = args_ct; - def->sorted_args = sorted_args; n = def->nb_iargs + def->nb_oargs; - sorted_args += n; args_ct += n; } @@ -1032,7 +1038,7 @@ TranslationBlock *tcg_tb_alloc(TCGContext *s) } goto retry; } - atomic_set(&s->code_gen_ptr, next); + qatomic_set(&s->code_gen_ptr, next); s->data_gen_ptr = NULL; return tb; } @@ -1092,7 +1098,7 @@ void tcg_prologue_init(TCGContext *s) size_t data_size = prologue_size - code_size; size_t i; - log_disas(buf0, code_size, NULL); + log_disas(buf0, code_size); for (i = 0; i < data_size; i += sizeof(tcg_target_ulong)) { if (sizeof(tcg_target_ulong) == 8) { @@ -1106,7 +1112,7 @@ void tcg_prologue_init(TCGContext *s) } } } else { - log_disas(buf0, prologue_size, NULL); + log_disas(buf0, prologue_size); } qemu_log("\n"); qemu_log_flush(); @@ -1661,6 +1667,13 @@ bool tcg_op_supported(TCGOpcode op) case INDEX_op_shrv_vec: case INDEX_op_sarv_vec: return have_vec && TCG_TARGET_HAS_shv_vec; + case INDEX_op_rotli_vec: + return have_vec && TCG_TARGET_HAS_roti_vec; + case INDEX_op_rotls_vec: + return have_vec && TCG_TARGET_HAS_rots_vec; + case INDEX_op_rotlv_vec: + case INDEX_op_rotrv_vec: + return have_vec && TCG_TARGET_HAS_rotv_vec; case INDEX_op_ssadd_vec: case INDEX_op_usadd_vec: case INDEX_op_sssub_vec: @@ -2118,7 +2131,7 @@ static void tcg_dump_ops(TCGContext *s, bool have_prefs) QemuLogFile *logfile; rcu_read_lock(); - logfile = atomic_rcu_read(&qemu_logfile); + logfile = qatomic_rcu_read(&qemu_logfile); if (logfile) { for (; col < 40; ++col) { putc(' ', logfile->fd); @@ -2182,21 +2195,14 @@ static void tcg_dump_ops(TCGContext *s, bool have_prefs) /* we give more priority to constraints with less registers */ static int get_constraint_priority(const TCGOpDef *def, int k) { - const TCGArgConstraint *arg_ct; + const TCGArgConstraint *arg_ct = &def->args_ct[k]; + int n; - int i, n; - arg_ct = &def->args_ct[k]; - if (arg_ct->ct & TCG_CT_ALIAS) { + if (arg_ct->oalias) { /* an alias is equivalent to a single register */ n = 1; } else { - if (!(arg_ct->ct & TCG_CT_REG)) - return 0; - n = 0; - for(i = 0; i < TCG_TARGET_NB_REGS; i++) { - if (tcg_regset_test_reg(arg_ct->u.regs, i)) - n++; - } + n = ctpop64(arg_ct->regs); } return TCG_TARGET_NB_REGS - n + 1; } @@ -2204,20 +2210,23 @@ static int get_constraint_priority(const TCGOpDef *def, int k) /* sort from highest priority to lowest */ static void sort_constraints(TCGOpDef *def, int start, int n) { - int i, j, p1, p2, tmp; + int i, j; + TCGArgConstraint *a = def->args_ct; - for(i = 0; i < n; i++) - def->sorted_args[start + i] = start + i; - if (n <= 1) + for (i = 0; i < n; i++) { + a[start + i].sort_index = start + i; + } + if (n <= 1) { return; - for(i = 0; i < n - 1; i++) { - for(j = i + 1; j < n; j++) { - p1 = get_constraint_priority(def, def->sorted_args[start + i]); - p2 = get_constraint_priority(def, def->sorted_args[start + j]); + } + for (i = 0; i < n - 1; i++) { + for (j = i + 1; j < n; j++) { + int p1 = get_constraint_priority(def, a[start + i].sort_index); + int p2 = get_constraint_priority(def, a[start + j].sort_index); if (p1 < p2) { - tmp = def->sorted_args[start + i]; - def->sorted_args[start + i] = def->sorted_args[start + j]; - def->sorted_args[start + j] = tmp; + int tmp = a[start + i].sort_index; + a[start + i].sort_index = a[start + j].sort_index; + a[start + j].sort_index = tmp; } } } @@ -2252,8 +2261,6 @@ static void process_op_defs(TCGContext *s) /* Incomplete TCGTargetOpDef entry. */ tcg_debug_assert(ct_str != NULL); - def->args_ct[i].u.regs = 0; - def->args_ct[i].ct = 0; while (*ct_str != '\0') { switch(*ct_str) { case '0' ... '9': @@ -2261,19 +2268,19 @@ static void process_op_defs(TCGContext *s) int oarg = *ct_str - '0'; tcg_debug_assert(ct_str == tdefs->args_ct_str[i]); tcg_debug_assert(oarg < def->nb_oargs); - tcg_debug_assert(def->args_ct[oarg].ct & TCG_CT_REG); - /* TCG_CT_ALIAS is for the output arguments. - The input is tagged with TCG_CT_IALIAS. */ + tcg_debug_assert(def->args_ct[oarg].regs != 0); def->args_ct[i] = def->args_ct[oarg]; - def->args_ct[oarg].ct |= TCG_CT_ALIAS; + /* The output sets oalias. */ + def->args_ct[oarg].oalias = true; def->args_ct[oarg].alias_index = i; - def->args_ct[i].ct |= TCG_CT_IALIAS; + /* The input sets ialias. */ + def->args_ct[i].ialias = true; def->args_ct[i].alias_index = oarg; } ct_str++; break; case '&': - def->args_ct[i].ct |= TCG_CT_NEWREG; + def->args_ct[i].newreg = true; ct_str++; break; case 'i': @@ -2325,7 +2332,7 @@ void tcg_op_remove(TCGContext *s, TCGOp *op) s->nb_ops--; #ifdef CONFIG_PROFILER - atomic_set(&s->prof.del_op_count, s->prof.del_op_count + 1); + qatomic_set(&s->prof.del_op_count, s->prof.del_op_count + 1); #endif } @@ -2513,6 +2520,28 @@ static void la_global_sync(TCGContext *s, int ng) } } +/* + * liveness analysis: conditional branch: all temps are dead, + * globals and local temps should be synced. + */ +static void la_bb_sync(TCGContext *s, int ng, int nt) +{ + la_global_sync(s, ng); + + for (int i = ng; i < nt; ++i) { + if (s->temps[i].temp_local) { + int state = s->temps[i].state; + s->temps[i].state = state | TS_MEM; + if (state != TS_DEAD) { + continue; + } + } else { + s->temps[i].state = TS_DEAD; + } + la_reset_pref(&s->temps[i]); + } +} + /* liveness analysis: sync globals back to memory and kill. */ static void la_global_kill(TCGContext *s, int ng) { @@ -2789,6 +2818,8 @@ static void liveness_pass_1(TCGContext *s) /* If end of basic block, update. */ if (def->flags & TCG_OPF_BB_EXIT) { la_func_end(s, nb_globals, nb_temps); + } else if (def->flags & TCG_OPF_COND_BRANCH) { + la_bb_sync(s, nb_globals, nb_temps); } else if (def->flags & TCG_OPF_BB_END) { la_bb_end(s, nb_globals, nb_temps); } else if (def->flags & TCG_OPF_SIDE_EFFECTS) { @@ -2839,13 +2870,13 @@ static void liveness_pass_1(TCGContext *s) pset = la_temp_pref(ts); set = *pset; - set &= ct->u.regs; - if (ct->ct & TCG_CT_IALIAS) { + set &= ct->regs; + if (ct->ialias) { set &= op->output_pref[ct->alias_index]; } /* If the combination is not possible, restart. */ if (set == 0) { - set = ct->u.regs; + set = ct->regs; } *pset = set; } @@ -2901,7 +2932,10 @@ static bool liveness_pass_2(TCGContext *s) nb_oargs = def->nb_oargs; /* Set flags similar to how calls require. */ - if (def->flags & TCG_OPF_BB_END) { + if (def->flags & TCG_OPF_COND_BRANCH) { + /* Like reading globals: sync_globals */ + call_flags = TCG_CALL_NO_WRITE_GLOBALS; + } else if (def->flags & TCG_OPF_BB_END) { /* Like writing globals: save_globals */ call_flags = 0; } else if (def->flags & TCG_OPF_SIDE_EFFECTS) { @@ -2975,34 +3009,68 @@ static bool liveness_pass_2(TCGContext *s) } /* Outputs become available. */ - for (i = 0; i < nb_oargs; i++) { - arg_ts = arg_temp(op->args[i]); + if (opc == INDEX_op_mov_i32 || opc == INDEX_op_mov_i64) { + arg_ts = arg_temp(op->args[0]); dir_ts = arg_ts->state_ptr; - if (!dir_ts) { - continue; + if (dir_ts) { + op->args[0] = temp_arg(dir_ts); + changes = true; + + /* The output is now live and modified. */ + arg_ts->state = 0; + + if (NEED_SYNC_ARG(0)) { + TCGOpcode sopc = (arg_ts->type == TCG_TYPE_I32 + ? INDEX_op_st_i32 + : INDEX_op_st_i64); + TCGOp *sop = tcg_op_insert_after(s, op, sopc); + TCGTemp *out_ts = dir_ts; + + if (IS_DEAD_ARG(0)) { + out_ts = arg_temp(op->args[1]); + arg_ts->state = TS_DEAD; + tcg_op_remove(s, op); + } else { + arg_ts->state = TS_MEM; + } + + sop->args[0] = temp_arg(out_ts); + sop->args[1] = temp_arg(arg_ts->mem_base); + sop->args[2] = arg_ts->mem_offset; + } else { + tcg_debug_assert(!IS_DEAD_ARG(0)); + } } - op->args[i] = temp_arg(dir_ts); - changes = true; + } else { + for (i = 0; i < nb_oargs; i++) { + arg_ts = arg_temp(op->args[i]); + dir_ts = arg_ts->state_ptr; + if (!dir_ts) { + continue; + } + op->args[i] = temp_arg(dir_ts); + changes = true; - /* The output is now live and modified. */ - arg_ts->state = 0; + /* The output is now live and modified. */ + arg_ts->state = 0; - /* Sync outputs upon their last write. */ - if (NEED_SYNC_ARG(i)) { - TCGOpcode sopc = (arg_ts->type == TCG_TYPE_I32 - ? INDEX_op_st_i32 - : INDEX_op_st_i64); - TCGOp *sop = tcg_op_insert_after(s, op, sopc); + /* Sync outputs upon their last write. */ + if (NEED_SYNC_ARG(i)) { + TCGOpcode sopc = (arg_ts->type == TCG_TYPE_I32 + ? INDEX_op_st_i32 + : INDEX_op_st_i64); + TCGOp *sop = tcg_op_insert_after(s, op, sopc); - sop->args[0] = temp_arg(dir_ts); - sop->args[1] = temp_arg(arg_ts->mem_base); - sop->args[2] = arg_ts->mem_offset; + sop->args[0] = temp_arg(dir_ts); + sop->args[1] = temp_arg(arg_ts->mem_base); + sop->args[2] = arg_ts->mem_offset; - arg_ts->state = TS_MEM; - } - /* Drop outputs that are dead. */ - if (IS_DEAD_ARG(i)) { - arg_ts->state = TS_DEAD; + arg_ts->state = TS_MEM; + } + /* Drop outputs that are dead. */ + if (IS_DEAD_ARG(i)) { + arg_ts->state = TS_DEAD; + } } } } @@ -3339,6 +3407,28 @@ static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs) save_globals(s, allocated_regs); } +/* + * At a conditional branch, we assume all temporaries are dead and + * all globals and local temps are synced to their location. + */ +static void tcg_reg_alloc_cbranch(TCGContext *s, TCGRegSet allocated_regs) +{ + sync_globals(s, allocated_regs); + + for (int i = s->nb_globals; i < s->nb_temps; i++) { + TCGTemp *ts = &s->temps[i]; + /* + * The liveness analysis already ensures that temps are dead. + * Keep tcg_debug_asserts for safety. + */ + if (ts->temp_local) { + tcg_debug_assert(ts->val_type != TEMP_VAL_REG || ts->mem_coherent); + } else { + tcg_debug_assert(ts->val_type == TEMP_VAL_DEAD); + } + } +} + /* * Specialized code generation for INDEX_op_movi_*. */ @@ -3501,8 +3591,8 @@ static void tcg_reg_alloc_dup(TCGContext *s, const TCGOp *op) return; } - dup_out_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[0].u.regs; - dup_in_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[1].u.regs; + dup_out_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[0].regs; + dup_in_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[1].regs; /* Allocate the output register now. */ if (ots->val_type != TEMP_VAL_REG) { @@ -3609,7 +3699,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) for (k = 0; k < nb_iargs; k++) { TCGRegSet i_preferred_regs, o_preferred_regs; - i = def->sorted_args[nb_oargs + k]; + i = def->args_ct[nb_oargs + k].sort_index; arg = op->args[i]; arg_ct = &def->args_ct[i]; ts = arg_temp(arg); @@ -3623,7 +3713,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) } i_preferred_regs = o_preferred_regs = 0; - if (arg_ct->ct & TCG_CT_IALIAS) { + if (arg_ct->ialias) { o_preferred_regs = op->output_pref[arg_ct->alias_index]; if (ts->fixed_reg) { /* if fixed register, we must allocate a new register @@ -3645,9 +3735,8 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) int k2, i2; reg = ts->reg; for (k2 = 0 ; k2 < k ; k2++) { - i2 = def->sorted_args[nb_oargs + k2]; - if ((def->args_ct[i2].ct & TCG_CT_IALIAS) && - reg == new_args[i2]) { + i2 = def->args_ct[nb_oargs + k2].sort_index; + if (def->args_ct[i2].ialias && reg == new_args[i2]) { goto allocate_in_reg; } } @@ -3656,10 +3745,10 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) } } - temp_load(s, ts, arg_ct->u.regs, i_allocated_regs, i_preferred_regs); + temp_load(s, ts, arg_ct->regs, i_allocated_regs, i_preferred_regs); reg = ts->reg; - if (tcg_regset_test_reg(arg_ct->u.regs, reg)) { + if (tcg_regset_test_reg(arg_ct->regs, reg)) { /* nothing to do : the constraint is satisfied */ } else { allocate_in_reg: @@ -3667,7 +3756,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) and move the temporary register into it */ temp_load(s, ts, tcg_target_available_regs[ts->type], i_allocated_regs, 0); - reg = tcg_reg_alloc(s, arg_ct->u.regs, i_allocated_regs, + reg = tcg_reg_alloc(s, arg_ct->regs, i_allocated_regs, o_preferred_regs, ts->indirect_base); if (!tcg_out_mov(s, ts->type, reg, ts->reg)) { /* @@ -3691,7 +3780,9 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) } } - if (def->flags & TCG_OPF_BB_END) { + if (def->flags & TCG_OPF_COND_BRANCH) { + tcg_reg_alloc_cbranch(s, i_allocated_regs); + } else if (def->flags & TCG_OPF_BB_END) { tcg_reg_alloc_bb_end(s, i_allocated_regs); } else { if (def->flags & TCG_OPF_CALL_CLOBBER) { @@ -3710,7 +3801,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) /* satisfy the output constraints */ for(k = 0; k < nb_oargs; k++) { - i = def->sorted_args[k]; + i = def->args_ct[k].sort_index; arg = op->args[i]; arg_ct = &def->args_ct[i]; ts = arg_temp(arg); @@ -3718,15 +3809,14 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) /* ENV should not be modified. */ tcg_debug_assert(!ts->fixed_reg); - if ((arg_ct->ct & TCG_CT_ALIAS) - && !const_args[arg_ct->alias_index]) { + if (arg_ct->oalias && !const_args[arg_ct->alias_index]) { reg = new_args[arg_ct->alias_index]; - } else if (arg_ct->ct & TCG_CT_NEWREG) { - reg = tcg_reg_alloc(s, arg_ct->u.regs, + } else if (arg_ct->newreg) { + reg = tcg_reg_alloc(s, arg_ct->regs, i_allocated_regs | o_allocated_regs, op->output_pref[k], ts->indirect_base); } else { - reg = tcg_reg_alloc(s, arg_ct->u.regs, o_allocated_regs, + reg = tcg_reg_alloc(s, arg_ct->regs, o_allocated_regs, op->output_pref[k], ts->indirect_base); } tcg_regset_set_reg(o_allocated_regs, reg); @@ -3914,12 +4004,12 @@ static void tcg_reg_alloc_call(TCGContext *s, TCGOp *op) /* avoid copy/paste errors */ #define PROF_ADD(to, from, field) \ do { \ - (to)->field += atomic_read(&((from)->field)); \ + (to)->field += qatomic_read(&((from)->field)); \ } while (0) #define PROF_MAX(to, from, field) \ do { \ - typeof((from)->field) val__ = atomic_read(&((from)->field)); \ + typeof((from)->field) val__ = qatomic_read(&((from)->field)); \ if (val__ > (to)->field) { \ (to)->field = val__; \ } \ @@ -3929,11 +4019,11 @@ static void tcg_reg_alloc_call(TCGContext *s, TCGOp *op) static inline void tcg_profile_snapshot(TCGProfile *prof, bool counters, bool table) { - unsigned int n_ctxs = atomic_read(&n_tcg_ctxs); + unsigned int n_ctxs = qatomic_read(&n_tcg_ctxs); unsigned int i; for (i = 0; i < n_ctxs; i++) { - TCGContext *s = atomic_read(&tcg_ctxs[i]); + TCGContext *s = qatomic_read(&tcg_ctxs[i]); const TCGProfile *orig = &s->prof; if (counters) { @@ -3992,15 +4082,15 @@ void tcg_dump_op_count(void) int64_t tcg_cpu_exec_time(void) { - unsigned int n_ctxs = atomic_read(&n_tcg_ctxs); + unsigned int n_ctxs = qatomic_read(&n_tcg_ctxs); unsigned int i; int64_t ret = 0; for (i = 0; i < n_ctxs; i++) { - const TCGContext *s = atomic_read(&tcg_ctxs[i]); + const TCGContext *s = qatomic_read(&tcg_ctxs[i]); const TCGProfile *prof = &s->prof; - ret += atomic_read(&prof->cpu_exec_time); + ret += qatomic_read(&prof->cpu_exec_time); } return ret; } @@ -4033,15 +4123,15 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) QTAILQ_FOREACH(op, &s->ops, link) { n++; } - atomic_set(&prof->op_count, prof->op_count + n); + qatomic_set(&prof->op_count, prof->op_count + n); if (n > prof->op_count_max) { - atomic_set(&prof->op_count_max, n); + qatomic_set(&prof->op_count_max, n); } n = s->nb_temps; - atomic_set(&prof->temp_count, prof->temp_count + n); + qatomic_set(&prof->temp_count, prof->temp_count + n); if (n > prof->temp_count_max) { - atomic_set(&prof->temp_count_max, n); + qatomic_set(&prof->temp_count_max, n); } } #endif @@ -4075,7 +4165,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) #endif #ifdef CONFIG_PROFILER - atomic_set(&prof->opt_time, prof->opt_time - profile_getclock()); + qatomic_set(&prof->opt_time, prof->opt_time - profile_getclock()); #endif #ifdef USE_TCG_OPTIMIZATIONS @@ -4083,8 +4173,8 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) #endif #ifdef CONFIG_PROFILER - atomic_set(&prof->opt_time, prof->opt_time + profile_getclock()); - atomic_set(&prof->la_time, prof->la_time - profile_getclock()); + qatomic_set(&prof->opt_time, prof->opt_time + profile_getclock()); + qatomic_set(&prof->la_time, prof->la_time - profile_getclock()); #endif reachable_code_pass(s); @@ -4109,7 +4199,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) } #ifdef CONFIG_PROFILER - atomic_set(&prof->la_time, prof->la_time + profile_getclock()); + qatomic_set(&prof->la_time, prof->la_time + profile_getclock()); #endif #ifdef DEBUG_DISAS @@ -4140,7 +4230,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) TCGOpcode opc = op->opc; #ifdef CONFIG_PROFILER - atomic_set(&prof->table_op_count[opc], prof->table_op_count[opc] + 1); + qatomic_set(&prof->table_op_count[opc], prof->table_op_count[opc] + 1); #endif switch (opc) { diff --git a/tcg/tci.c b/tcg/tci.c index 46fe9ce63f990f3150370dd9fcfde80c6719f2a1..82039fd163d4540507e691f4e8369bf1d9b1943e 100644 --- a/tcg/tci.c +++ b/tcg/tci.c @@ -1115,7 +1115,7 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) case INDEX_op_goto_tb: /* Jump address is aligned */ tb_ptr = QEMU_ALIGN_PTR_UP(tb_ptr, 4); - t0 = atomic_read((int32_t *)tb_ptr); + t0 = qatomic_read((int32_t *)tb_ptr); tb_ptr += sizeof(int32_t); tci_assert(tb_ptr == old_code_ptr + op_size); tb_ptr += (int32_t)t0; diff --git a/tcg/tci/README b/tcg/tci/README index 386c3c7507547b598d48b3b3e2d5729e51e514d6..9bb7d7a5d399e6d1e0dff56354f053e94d9fcdc6 100644 --- a/tcg/tci/README +++ b/tcg/tci/README @@ -21,7 +21,7 @@ This is what TCI (Tiny Code Interpreter) does. 2) Implementation Like each TCG host frontend, TCI implements the code generator in -tcg-target.inc.c, tcg-target.h. Both files are in directory tcg/tci. +tcg-target.c.inc, tcg-target.h. Both files are in directory tcg/tci. The additional file tcg/tci.c adds the interpreter. @@ -123,7 +123,7 @@ u1 = linux-user-test works would also improve speed for hosts which support byte alignment). * A better disassembler for the pseudo code would be nice (a very primitive - disassembler is included in tcg-target.inc.c). + disassembler is included in tcg-target.c.inc). * It might be useful to have a runtime option which selects the native TCG or TCI, so QEMU would have to include two TCGs. Today, selecting TCI diff --git a/tcg/tci/tcg-target.inc.c b/tcg/tci/tcg-target.c.inc similarity index 99% rename from tcg/tci/tcg-target.inc.c rename to tcg/tci/tcg-target.c.inc index 992d50cb1eb310da54dccafcd39760c9bee3b40c..231b9b1775bd76acbadd177278d8723156bbe204 100644 --- a/tcg/tci/tcg-target.inc.c +++ b/tcg/tci/tcg-target.c.inc @@ -392,8 +392,7 @@ static const char *target_parse_constraint(TCGArgConstraint *ct, case 'r': case 'L': /* qemu_ld constraint */ case 'S': /* qemu_st constraint */ - ct->ct |= TCG_CT_REG; - ct->u.regs = BIT(TCG_TARGET_NB_REGS) - 1; + ct->regs = BIT(TCG_TARGET_NB_REGS) - 1; break; default: return NULL; diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h index 8b90ab71cb7407fbae4ae56a21a3d9a96313a7d1..8c1c1d265da55c65b28219817183e7918aca1f7c 100644 --- a/tcg/tci/tcg-target.h +++ b/tcg/tci/tcg-target.h @@ -206,7 +206,7 @@ static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr, uintptr_t addr) { /* patch the branch destination */ - atomic_set((int32_t *)jmp_addr, addr - (jmp_addr + 4)); + qatomic_set((int32_t *)jmp_addr, addr - (jmp_addr + 4)); /* no need to flush icache explicitly */ } diff --git a/tests/.gitignore b/tests/.gitignore deleted file mode 100644 index d03c037d772da6dbfe0ba04d63892e3b4dff965a..0000000000000000000000000000000000000000 --- a/tests/.gitignore +++ /dev/null @@ -1,32 +0,0 @@ -atomic_add-bench -benchmark-crypto-cipher -benchmark-crypto-hash -benchmark-crypto-hmac -check-* -!check-*.c -!check-*.sh -fp/*.out -qht-bench -rcutorture -test-* -!test-*.c -!test-*.py -!docker/test-* -test-qapi-commands.[ch] -test-qapi-init-commands.[ch] -include/test-qapi-commands-sub-module.[ch] -test-qapi-commands-sub-sub-module.[ch] -test-qapi-emit-events.[ch] -test-qapi-events.[ch] -include/test-qapi-events-sub-module.[ch] -test-qapi-events-sub-sub-module.[ch] -test-qapi-types.[ch] -include/test-qapi-types-sub-module.[ch] -test-qapi-types-sub-sub-module.[ch] -test-qapi-visit.[ch] -include/test-qapi-visit-sub-module.[ch] -test-qapi-visit-sub-sub-module.[ch] -test-qapi-introspect.[ch] -*-test -qapi-schema/*.test.* -vm/*.img diff --git a/tests/Makefile.include b/tests/Makefile.include index 03a74b60f6b2e2a17b4d031cea14a90dccbda00b..3a0524ce740b2437af0e27743de6373b6788d246 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -4,7 +4,7 @@ check-help: @echo "Regression testing targets:" @echo - @echo " $(MAKE) check Run unit, qapi-schema, qtest and decodetree" + @echo " $(MAKE) check Run block, qapi-schema, unit, softfloat, qtest and decodetree tests" @echo @echo " $(MAKE) check-qtest-TARGET Run qtest tests for given target" @echo " $(MAKE) check-qtest Run qtest tests" @@ -12,14 +12,18 @@ check-help: @echo " $(MAKE) check-speed Run qobject speed tests" @echo " $(MAKE) check-qapi-schema Run QAPI schema tests" @echo " $(MAKE) check-block Run block tests" +ifeq ($(CONFIG_TCG),y) @echo " $(MAKE) check-tcg Run TCG tests" @echo " $(MAKE) check-softfloat Run FPU emulation tests" +endif @echo " $(MAKE) check-acceptance Run all acceptance (functional) tests" @echo @echo " $(MAKE) check-report.tap Generates an aggregated TAP test report" @echo " $(MAKE) check-venv Creates a Python venv for tests" @echo " $(MAKE) check-clean Clean the tests and related data" @echo + @echo "The following are useful for CI builds" + @echo " $(MAKE) check-build Build most test binaris" @echo " $(MAKE) get-vm-images Downloads all images used by acceptance tests, according to configured targets (~350 MB each, 1.5 GB max)" @echo @echo @@ -30,775 +34,12 @@ check-help: ifneq ($(wildcard config-host.mak),) export SRC_PATH -# TODO don't duplicate $(SRC_PATH)/Makefile's qapi-py here -qapi-py = $(SRC_PATH)/scripts/qapi/__init__.py \ -$(SRC_PATH)/scripts/qapi/commands.py \ -$(SRC_PATH)/scripts/qapi/common.py \ -$(SRC_PATH)/scripts/qapi/doc.py \ -$(SRC_PATH)/scripts/qapi/error.py \ -$(SRC_PATH)/scripts/qapi/events.py \ -$(SRC_PATH)/scripts/qapi/expr.py \ -$(SRC_PATH)/scripts/qapi/gen.py \ -$(SRC_PATH)/scripts/qapi/introspect.py \ -$(SRC_PATH)/scripts/qapi/parser.py \ -$(SRC_PATH)/scripts/qapi/schema.py \ -$(SRC_PATH)/scripts/qapi/source.py \ -$(SRC_PATH)/scripts/qapi/types.py \ -$(SRC_PATH)/scripts/qapi/visit.py \ -$(SRC_PATH)/scripts/qapi-gen.py - # Get the list of all supported sysemu targets SYSEMU_TARGET_LIST := $(subst -softmmu.mak,,$(notdir \ $(wildcard $(SRC_PATH)/default-configs/*-softmmu.mak))) -check-unit-y += tests/check-qdict$(EXESUF) -check-unit-y += tests/check-block-qdict$(EXESUF) -check-unit-$(CONFIG_SOFTMMU) += tests/test-char$(EXESUF) -check-unit-y += tests/check-qnum$(EXESUF) -check-unit-y += tests/check-qstring$(EXESUF) -check-unit-y += tests/check-qlist$(EXESUF) -check-unit-y += tests/check-qnull$(EXESUF) -check-unit-y += tests/check-qobject$(EXESUF) -check-unit-y += tests/check-qjson$(EXESUF) -check-unit-y += tests/check-qlit$(EXESUF) -check-unit-y += tests/test-qobject-output-visitor$(EXESUF) -check-unit-y += tests/test-clone-visitor$(EXESUF) -check-unit-y += tests/test-qobject-input-visitor$(EXESUF) -check-unit-y += tests/test-qmp-cmds$(EXESUF) -check-unit-y += tests/test-string-input-visitor$(EXESUF) -check-unit-y += tests/test-string-output-visitor$(EXESUF) -check-unit-y += tests/test-qmp-event$(EXESUF) -check-unit-y += tests/test-opts-visitor$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-coroutine$(EXESUF) -check-unit-y += tests/test-visitor-serialization$(EXESUF) -check-unit-y += tests/test-iov$(EXESUF) -check-unit-y += tests/test-bitmap$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-aio$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-aio-multithread$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-throttle$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-thread-pool$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-hbitmap$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-bdrv-drain$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-bdrv-graph-mod$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-blockjob$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-blockjob-txn$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-block-backend$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-block-iothread$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-image-locking$(EXESUF) -check-unit-y += tests/test-x86-cpuid$(EXESUF) -# all code tested by test-x86-cpuid is inside topology.h -ifeq ($(CONFIG_SOFTMMU),y) -check-unit-y += tests/test-xbzrle$(EXESUF) -check-unit-$(CONFIG_POSIX) += tests/test-vmstate$(EXESUF) -endif -check-unit-y += tests/test-cutils$(EXESUF) -check-unit-y += tests/test-shift128$(EXESUF) -check-unit-y += tests/test-mul64$(EXESUF) -check-unit-y += tests/test-int128$(EXESUF) -# all code tested by test-int128 is inside int128.h -check-unit-y += tests/rcutorture$(EXESUF) -check-unit-y += tests/test-rcu-list$(EXESUF) -check-unit-y += tests/test-rcu-simpleq$(EXESUF) -check-unit-y += tests/test-rcu-tailq$(EXESUF) -check-unit-y += tests/test-rcu-slist$(EXESUF) -check-unit-y += tests/test-qdist$(EXESUF) -check-unit-y += tests/test-qht$(EXESUF) -check-unit-y += tests/test-qht-par$(EXESUF) -check-unit-y += tests/test-bitops$(EXESUF) -check-unit-y += tests/test-bitcnt$(EXESUF) -check-unit-y += tests/test-qdev-global-props$(EXESUF) -check-unit-y += tests/check-qom-interface$(EXESUF) -check-unit-y += tests/check-qom-proplist$(EXESUF) -check-unit-y += tests/test-qemu-opts$(EXESUF) -check-unit-y += tests/test-keyval$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-write-threshold$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-crypto-hash$(EXESUF) -check-speed-$(CONFIG_BLOCK) += tests/benchmark-crypto-hash$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-crypto-hmac$(EXESUF) -check-speed-$(CONFIG_BLOCK) += tests/benchmark-crypto-hmac$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-crypto-cipher$(EXESUF) -check-speed-$(CONFIG_BLOCK) += tests/benchmark-crypto-cipher$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-crypto-secret$(EXESUF) -check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_GNUTLS)) += tests/test-crypto-tlscredsx509$(EXESUF) -check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_GNUTLS)) += tests/test-crypto-tlssession$(EXESUF) -ifneq (,$(findstring qemu-ga,$(TOOLS))) -check-unit-$(call land,$(CONFIG_LINUX),$(CONFIG_VIRTIO_SERIAL)) += tests/test-qga$(EXESUF) -endif -check-unit-y += tests/test-timed-average$(EXESUF) -check-unit-$(CONFIG_INOTIFY1) += tests/test-util-filemonitor$(EXESUF) -check-unit-y += tests/test-util-sockets$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-authz-simple$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-authz-list$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-authz-listfile$(EXESUF) -check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_AUTH_PAM)) += tests/test-authz-pam$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-io-task$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-io-channel-socket$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-io-channel-file$(EXESUF) -check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_GNUTLS)) += tests/test-io-channel-tls$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-io-channel-command$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-io-channel-buffer$(EXESUF) -check-unit-y += tests/test-base64$(EXESUF) -check-unit-$(call land,$(CONFIG_BLOCK),$(if $(CONFIG_NETTLE),y,$(CONFIG_GCRYPT))) += tests/test-crypto-pbkdf$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-crypto-ivgen$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-crypto-afsplit$(EXESUF) -check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_QEMU_PRIVATE_XTS)) += tests/test-crypto-xts$(EXESUF) -check-unit-$(CONFIG_BLOCK) += tests/test-crypto-block$(EXESUF) -check-unit-y += tests/test-logging$(EXESUF) -check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_REPLICATION)) += tests/test-replication$(EXESUF) -check-unit-y += tests/test-bufferiszero$(EXESUF) -check-unit-y += tests/test-uuid$(EXESUF) -check-unit-y += tests/ptimer-test$(EXESUF) -check-unit-y += tests/test-qapi-util$(EXESUF) - -check-block-$(call land,$(CONFIG_POSIX),$(CONFIG_SOFTMMU)) += tests/check-block.sh - -qapi-schema += alternate-any.json -qapi-schema += alternate-array.json -qapi-schema += alternate-base.json -qapi-schema += alternate-branch-if-invalid.json -qapi-schema += alternate-clash.json -qapi-schema += alternate-conflict-dict.json -qapi-schema += alternate-conflict-enum-bool.json -qapi-schema += alternate-conflict-enum-int.json -qapi-schema += alternate-conflict-string.json -qapi-schema += alternate-conflict-bool-string.json -qapi-schema += alternate-conflict-num-string.json -qapi-schema += alternate-empty.json -qapi-schema += alternate-invalid-dict.json -qapi-schema += alternate-nested.json -qapi-schema += alternate-unknown.json -qapi-schema += args-alternate.json -qapi-schema += args-any.json -qapi-schema += args-array-empty.json -qapi-schema += args-array-unknown.json -qapi-schema += args-bad-boxed.json -qapi-schema += args-boxed-anon.json -qapi-schema += args-boxed-string.json -qapi-schema += args-int.json -qapi-schema += args-invalid.json -qapi-schema += args-member-array-bad.json -qapi-schema += args-member-case.json -qapi-schema += args-member-unknown.json -qapi-schema += args-name-clash.json -qapi-schema += args-union.json -qapi-schema += args-unknown.json -qapi-schema += bad-base.json -qapi-schema += bad-data.json -qapi-schema += bad-ident.json -qapi-schema += bad-if.json -qapi-schema += bad-if-empty.json -qapi-schema += bad-if-empty-list.json -qapi-schema += bad-if-list.json -qapi-schema += bad-type-bool.json -qapi-schema += bad-type-dict.json -qapi-schema += bad-type-int.json -qapi-schema += base-cycle-direct.json -qapi-schema += base-cycle-indirect.json -qapi-schema += command-int.json -qapi-schema += comments.json -qapi-schema += doc-bad-alternate-member.json -qapi-schema += doc-bad-boxed-command-arg.json -qapi-schema += doc-bad-command-arg.json -qapi-schema += doc-bad-enum-member.json -qapi-schema += doc-bad-event-arg.json -qapi-schema += doc-bad-feature.json -qapi-schema += doc-bad-section.json -qapi-schema += doc-bad-symbol.json -qapi-schema += doc-bad-union-member.json -qapi-schema += doc-before-include.json -qapi-schema += doc-before-pragma.json -qapi-schema += doc-duplicated-arg.json -qapi-schema += doc-duplicated-return.json -qapi-schema += doc-duplicated-since.json -qapi-schema += doc-empty-arg.json -qapi-schema += doc-empty-section.json -qapi-schema += doc-empty-symbol.json -qapi-schema += doc-good.json -qapi-schema += doc-interleaved-section.json -qapi-schema += doc-invalid-end.json -qapi-schema += doc-invalid-end2.json -qapi-schema += doc-invalid-return.json -qapi-schema += doc-invalid-section.json -qapi-schema += doc-invalid-start.json -qapi-schema += doc-missing-colon.json -qapi-schema += doc-missing-expr.json -qapi-schema += doc-missing-space.json -qapi-schema += doc-missing.json -qapi-schema += doc-no-symbol.json -qapi-schema += doc-undoc-feature.json -qapi-schema += double-type.json -qapi-schema += duplicate-key.json -qapi-schema += empty.json -qapi-schema += enum-bad-member.json -qapi-schema += enum-bad-name.json -qapi-schema += enum-bad-prefix.json -qapi-schema += enum-clash-member.json -qapi-schema += enum-dict-member-unknown.json -qapi-schema += enum-if-invalid.json -qapi-schema += enum-int-member.json -qapi-schema += enum-member-case.json -qapi-schema += enum-missing-data.json -qapi-schema += enum-wrong-data.json -qapi-schema += event-boxed-empty.json -qapi-schema += event-case.json -qapi-schema += event-member-invalid-dict.json -qapi-schema += event-nest-struct.json -qapi-schema += features-bad-type.json -qapi-schema += features-deprecated-type.json -qapi-schema += features-duplicate-name.json -qapi-schema += features-if-invalid.json -qapi-schema += features-missing-name.json -qapi-schema += features-name-bad-type.json -qapi-schema += features-no-list.json -qapi-schema += features-unknown-key.json -qapi-schema += flat-union-array-branch.json -qapi-schema += flat-union-bad-base.json -qapi-schema += flat-union-bad-discriminator.json -qapi-schema += flat-union-base-any.json -qapi-schema += flat-union-base-union.json -qapi-schema += flat-union-clash-member.json -qapi-schema += flat-union-discriminator-bad-name.json -qapi-schema += flat-union-empty.json -qapi-schema += flat-union-inline.json -qapi-schema += flat-union-inline-invalid-dict.json -qapi-schema += flat-union-int-branch.json -qapi-schema += flat-union-invalid-branch-key.json -qapi-schema += flat-union-invalid-discriminator.json -qapi-schema += flat-union-invalid-if-discriminator.json -qapi-schema += flat-union-no-base.json -qapi-schema += flat-union-optional-discriminator.json -qapi-schema += flat-union-string-discriminator.json -qapi-schema += funny-char.json -qapi-schema += funny-word.json -qapi-schema += ident-with-escape.json -qapi-schema += include-before-err.json -qapi-schema += include-cycle.json -qapi-schema += include-extra-junk.json -qapi-schema += include-nested-err.json -qapi-schema += include-no-file.json -qapi-schema += include-non-file.json -qapi-schema += include-repetition.json -qapi-schema += include-self-cycle.json -qapi-schema += include-simple.json -qapi-schema += indented-expr.json -qapi-schema += leading-comma-list.json -qapi-schema += leading-comma-object.json -qapi-schema += missing-colon.json -qapi-schema += missing-comma-list.json -qapi-schema += missing-comma-object.json -qapi-schema += missing-type.json -qapi-schema += nested-struct-data.json -qapi-schema += nested-struct-data-invalid-dict.json -qapi-schema += non-objects.json -qapi-schema += oob-test.json -qapi-schema += allow-preconfig-test.json -qapi-schema += pragma-doc-required-crap.json -qapi-schema += pragma-extra-junk.json -qapi-schema += pragma-name-case-whitelist-crap.json -qapi-schema += pragma-non-dict.json -qapi-schema += pragma-unknown.json -qapi-schema += pragma-returns-whitelist-crap.json -qapi-schema += qapi-schema-test.json -qapi-schema += quoted-structural-chars.json -qapi-schema += redefined-builtin.json -qapi-schema += redefined-command.json -qapi-schema += redefined-event.json -qapi-schema += redefined-type.json -qapi-schema += reserved-command-q.json -qapi-schema += reserved-enum-q.json -qapi-schema += reserved-member-has.json -qapi-schema += reserved-member-q.json -qapi-schema += reserved-member-u.json -qapi-schema += reserved-member-underscore.json -qapi-schema += reserved-type-kind.json -qapi-schema += reserved-type-list.json -qapi-schema += returns-alternate.json -qapi-schema += returns-array-bad.json -qapi-schema += returns-dict.json -qapi-schema += returns-unknown.json -qapi-schema += returns-whitelist.json -qapi-schema += string-code-point-31.json -qapi-schema += string-code-point-127.json -qapi-schema += struct-base-clash-deep.json -qapi-schema += struct-base-clash.json -qapi-schema += struct-data-invalid.json -qapi-schema += struct-member-if-invalid.json -qapi-schema += struct-member-invalid-dict.json -qapi-schema += struct-member-invalid.json -qapi-schema += trailing-comma-list.json -qapi-schema += trailing-comma-object.json -qapi-schema += type-bypass-bad-gen.json -qapi-schema += unclosed-list.json -qapi-schema += unclosed-object.json -qapi-schema += unclosed-string.json -qapi-schema += union-base-empty.json -qapi-schema += union-base-no-discriminator.json -qapi-schema += union-branch-case.json -qapi-schema += union-branch-if-invalid.json -qapi-schema += union-branch-invalid-dict.json -qapi-schema += union-clash-branches.json -qapi-schema += union-empty.json -qapi-schema += union-invalid-base.json -qapi-schema += union-optional-branch.json -qapi-schema += union-unknown.json -qapi-schema += unknown-escape.json -qapi-schema += unknown-expr-key.json - - -check-qapi-schema-y := $(addprefix tests/qapi-schema/, $(qapi-schema)) - -generated-files-y += tests/test-qapi-types.h -generated-files-y += tests/include/test-qapi-types-sub-module.h -generated-files-y += tests/test-qapi-types-sub-sub-module.h -generated-files-y += tests/test-qapi-visit.h -generated-files-y += tests/include/test-qapi-visit-sub-module.h -generated-files-y += tests/test-qapi-visit-sub-sub-module.h -generated-files-y += tests/test-qapi-commands.h -generated-files-y += tests/test-qapi-init-commands.h -generated-files-y += tests/include/test-qapi-commands-sub-module.h -generated-files-y += tests/test-qapi-commands-sub-sub-module.h -generated-files-y += tests/test-qapi-emit-events.h -generated-files-y += tests/test-qapi-events.h -generated-files-y += tests/include/test-qapi-events-sub-module.h -generated-files-y += tests/test-qapi-events-sub-sub-module.h -generated-files-y += tests/test-qapi-introspect.h - -QEMU_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest - - -# Deps that are common to various different sets of tests below -test-util-obj-y = libqemuutil.a -test-qom-obj-y = $(qom-obj-y) $(test-util-obj-y) -test-qapi-obj-y = tests/test-qapi-types.o \ - tests/include/test-qapi-types-sub-module.o \ - tests/test-qapi-types-sub-sub-module.o \ - tests/test-qapi-visit.o \ - tests/include/test-qapi-visit-sub-module.o \ - tests/test-qapi-visit-sub-sub-module.o \ - tests/test-qapi-introspect.o \ - $(test-qom-obj-y) -benchmark-crypto-obj-$(CONFIG_BLOCK) = $(authz-obj-y) $(crypto-obj-y) $(test-qom-obj-y) -test-crypto-obj-$(CONFIG_BLOCK) = $(authz-obj-y) $(crypto-obj-y) $(test-qom-obj-y) -test-io-obj-$(CONFIG_BLOCK) = $(io-obj-y) $(test-crypto-obj-y) -test-authz-obj-$(CONFIG_BLOCK) = $(test-qom-obj-y) $(authz-obj-y) -test-block-obj-$(CONFIG_BLOCK) = $(block-obj-y) $(test-io-obj-y) tests/iothread.o - -tests/check-qnum$(EXESUF): tests/check-qnum.o $(test-util-obj-y) -tests/check-qstring$(EXESUF): tests/check-qstring.o $(test-util-obj-y) -tests/check-qdict$(EXESUF): tests/check-qdict.o $(test-util-obj-y) -tests/check-block-qdict$(EXESUF): tests/check-block-qdict.o $(test-util-obj-y) -tests/check-qlist$(EXESUF): tests/check-qlist.o $(test-util-obj-y) -tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y) -tests/check-qobject$(EXESUF): tests/check-qobject.o $(test-util-obj-y) -tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y) -tests/check-qlit$(EXESUF): tests/check-qlit.o $(test-util-obj-y) -tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y) -tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y) - -tests/test-char$(EXESUF): tests/test-char.o $(test-util-obj-y) $(test-io-obj-y) $(chardev-obj-y) tests/socket-helpers.o -tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y) -tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y) -tests/test-aio-multithread$(EXESUF): tests/test-aio-multithread.o $(test-block-obj-y) -tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y) -tests/test-bdrv-drain$(EXESUF): tests/test-bdrv-drain.o $(test-block-obj-y) $(test-util-obj-y) -tests/test-bdrv-graph-mod$(EXESUF): tests/test-bdrv-graph-mod.o $(test-block-obj-y) $(test-util-obj-y) -tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y) -tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y) -tests/test-block-backend$(EXESUF): tests/test-block-backend.o $(test-block-obj-y) $(test-util-obj-y) -tests/test-block-iothread$(EXESUF): tests/test-block-iothread.o $(test-block-obj-y) $(test-util-obj-y) -tests/test-image-locking$(EXESUF): tests/test-image-locking.o $(test-block-obj-y) $(test-util-obj-y) -tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y) -tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y) -tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y) $(test-crypto-obj-y) -tests/test-bitmap$(EXESUF): tests/test-bitmap.o $(test-util-obj-y) -tests/test-x86-cpuid$(EXESUF): tests/test-x86-cpuid.o -tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o migration/xbzrle.o migration/page_cache.o $(test-util-obj-y) -tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o $(test-util-obj-y) -tests/test-int128$(EXESUF): tests/test-int128.o -tests/rcutorture$(EXESUF): tests/rcutorture.o $(test-util-obj-y) -tests/test-rcu-list$(EXESUF): tests/test-rcu-list.o $(test-util-obj-y) -tests/test-rcu-simpleq$(EXESUF): tests/test-rcu-simpleq.o $(test-util-obj-y) -tests/test-rcu-tailq$(EXESUF): tests/test-rcu-tailq.o $(test-util-obj-y) -tests/test-rcu-slist$(EXESUF): tests/test-rcu-slist.o $(test-util-obj-y) -tests/test-qdist$(EXESUF): tests/test-qdist.o $(test-util-obj-y) -tests/test-qht$(EXESUF): tests/test-qht.o $(test-util-obj-y) -tests/test-qht-par$(EXESUF): tests/test-qht-par.o tests/qht-bench$(EXESUF) $(test-util-obj-y) -tests/qht-bench$(EXESUF): tests/qht-bench.o $(test-util-obj-y) -tests/test-bufferiszero$(EXESUF): tests/test-bufferiszero.o $(test-util-obj-y) -tests/atomic_add-bench$(EXESUF): tests/atomic_add-bench.o $(test-util-obj-y) -tests/atomic64-bench$(EXESUF): tests/atomic64-bench.o $(test-util-obj-y) - -tests/fp/%: - $(MAKE) -C $(dir $@) $(notdir $@) - -tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \ - hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\ - hw/core/bus.o \ - hw/core/resettable.o \ - hw/core/irq.o \ - hw/core/fw-path-provider.o \ - hw/core/reset.o \ - hw/core/vmstate-if.o \ - hw/core/clock.o hw/core/qdev-clock.o \ - $(test-qapi-obj-y) -tests/test-vmstate$(EXESUF): tests/test-vmstate.o \ - migration/vmstate.o migration/vmstate-types.o migration/qemu-file.o \ - migration/qemu-file-channel.o migration/qjson.o \ - $(test-io-obj-y) -tests/test-timed-average$(EXESUF): tests/test-timed-average.o $(test-util-obj-y) -tests/test-base64$(EXESUF): tests/test-base64.o $(test-util-obj-y) -tests/ptimer-test$(EXESUF): tests/ptimer-test.o tests/ptimer-test-stubs.o hw/core/ptimer.o -tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o $(test-util-obj-y) -tests/test-keyval$(EXESUF): tests/test-keyval.o $(test-util-obj-y) $(test-qapi-obj-y) -tests/test-write-threshold$(EXESUF): tests/test-write-threshold.o $(test-block-obj-y) -tests/test-uuid$(EXESUF): tests/test-uuid.o $(test-util-obj-y) -tests/test-qapi-util$(EXESUF): tests/test-qapi-util.o $(test-util-obj-y) - -tests/test-logging$(EXESUF): tests/test-logging.o $(test-util-obj-y) - -tests/test-replication$(EXESUF): tests/test-replication.o $(test-util-obj-y) \ - $(test-block-obj-y) - -tests/test-qapi-types.c tests/test-qapi-types.h \ -tests/include/test-qapi-types-sub-module.c \ -tests/include/test-qapi-types-sub-module.h \ -tests/test-qapi-types-sub-sub-module.c \ -tests/test-qapi-types-sub-sub-module.h \ -tests/test-qapi-visit.c tests/test-qapi-visit.h \ -tests/include/test-qapi-visit-sub-module.c \ -tests/include/test-qapi-visit-sub-module.h \ -tests/test-qapi-visit-sub-sub-module.c \ -tests/test-qapi-visit-sub-sub-module.h \ -tests/test-qapi-commands.h tests/test-qapi-commands.c \ -tests/include/test-qapi-commands-sub-module.h \ -tests/include/test-qapi-commands-sub-module.c \ -tests/test-qapi-commands-sub-sub-module.h \ -tests/test-qapi-commands-sub-sub-module.c \ -tests/test-qapi-emit-events.c tests/test-qapi-emit-events.h \ -tests/test-qapi-events.c tests/test-qapi-events.h \ -tests/test-qapi-init-commands.c \ -tests/test-qapi-init-commands.h \ -tests/include/test-qapi-events-sub-module.c \ -tests/include/test-qapi-events-sub-module.h \ -tests/test-qapi-events-sub-sub-module.c \ -tests/test-qapi-events-sub-sub-module.h \ -tests/test-qapi-introspect.c tests/test-qapi-introspect.h: \ -tests/test-qapi-gen-timestamp ; -tests/test-qapi-gen-timestamp: \ - $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json \ - $(SRC_PATH)/tests/qapi-schema/include/sub-module.json \ - $(SRC_PATH)/tests/qapi-schema/sub-sub-module.json \ - $(qapi-py) - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \ - -o tests -p "test-" $<, \ - "GEN","$(@:%-timestamp=%)") - @rm -f tests/test-qapi-doc.texi - @>$@ - -tests/qapi-schema/doc-good.test.texi: $(SRC_PATH)/tests/qapi-schema/doc-good.json $(qapi-py) - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \ - -o tests/qapi-schema -p "doc-good-" $<, \ - "GEN","$@") - @mv tests/qapi-schema/doc-good-qapi-doc.texi $@ - @rm -f tests/qapi-schema/doc-good-qapi-*.[ch] tests/qapi-schema/doc-good-qmp-*.[ch] - -tests/qtest/dbus-vmstate1.h tests/qtest/dbus-vmstate1.c: tests/qtest/dbus-vmstate1-gen-timestamp ; -tests/qtest/dbus-vmstate1-gen-timestamp: $(SRC_PATH)/tests/qtest/dbus-vmstate1.xml - $(call quiet-command,$(GDBUS_CODEGEN) $< \ - --interface-prefix org.qemu --generate-c-code tests/qtest/dbus-vmstate1, \ - "GEN","$(@:%-timestamp=%)") - @>$@ - -tests/qtest/dbus-vmstate-test.o-cflags := -DSRCDIR="$(SRC_PATH)" -tests/qtest/dbus-vmstate1.o-cflags := $(GIO_CFLAGS) -tests/qtest/dbus-vmstate1.o-libs := $(GIO_LIBS) - -tests/qtest/dbus-vmstate-test.o: tests/qtest/dbus-vmstate1.h - -tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y) -tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y) -tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o $(test-qapi-obj-y) tests/test-qapi-emit-events.o tests/test-qapi-events.o -tests/test-qobject-output-visitor$(EXESUF): tests/test-qobject-output-visitor.o $(test-qapi-obj-y) -tests/test-clone-visitor$(EXESUF): tests/test-clone-visitor.o $(test-qapi-obj-y) -tests/test-qobject-input-visitor$(EXESUF): tests/test-qobject-input-visitor.o $(test-qapi-obj-y) -tests/test-qmp-cmds$(EXESUF): tests/test-qmp-cmds.o tests/test-qapi-commands.o tests/test-qapi-init-commands.o $(test-qapi-obj-y) -tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y) -tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y) - -tests/test-shift128$(EXESUF): tests/test-shift128.o $(test-util-obj-y) -tests/test-mul64$(EXESUF): tests/test-mul64.o $(test-util-obj-y) -tests/test-bitops$(EXESUF): tests/test-bitops.o $(test-util-obj-y) -tests/test-bitcnt$(EXESUF): tests/test-bitcnt.o $(test-util-obj-y) -tests/test-crypto-hash$(EXESUF): tests/test-crypto-hash.o $(test-crypto-obj-y) -tests/benchmark-crypto-hash$(EXESUF): tests/benchmark-crypto-hash.o $(test-crypto-obj-y) -tests/test-crypto-hmac$(EXESUF): tests/test-crypto-hmac.o $(test-crypto-obj-y) -tests/benchmark-crypto-hmac$(EXESUF): tests/benchmark-crypto-hmac.o $(test-crypto-obj-y) -tests/test-crypto-cipher$(EXESUF): tests/test-crypto-cipher.o $(test-crypto-obj-y) -tests/benchmark-crypto-cipher$(EXESUF): tests/benchmark-crypto-cipher.o $(test-crypto-obj-y) -tests/test-crypto-secret$(EXESUF): tests/test-crypto-secret.o $(test-crypto-obj-y) -tests/test-crypto-xts$(EXESUF): tests/test-crypto-xts.o $(test-crypto-obj-y) - -tests/crypto-tls-x509-helpers.o-cflags := $(TASN1_CFLAGS) -tests/crypto-tls-x509-helpers.o-libs := $(TASN1_LIBS) -tests/pkix_asn1_tab.o-cflags := $(TASN1_CFLAGS) - -tests/test-crypto-tlscredsx509.o-cflags := $(TASN1_CFLAGS) -tests/test-crypto-tlscredsx509$(EXESUF): tests/test-crypto-tlscredsx509.o \ - tests/crypto-tls-x509-helpers.o tests/pkix_asn1_tab.o $(test-crypto-obj-y) - -tests/test-crypto-tlssession.o-cflags := $(TASN1_CFLAGS) -tests/test-crypto-tlssession$(EXESUF): tests/test-crypto-tlssession.o \ - tests/crypto-tls-x509-helpers.o tests/pkix_asn1_tab.o \ - tests/crypto-tls-psk-helpers.o \ - $(test-crypto-obj-y) -tests/test-util-filemonitor$(EXESUF): tests/test-util-filemonitor.o \ - $(test-util-obj-y) -tests/test-util-sockets$(EXESUF): tests/test-util-sockets.o \ - tests/socket-helpers.o $(test-util-obj-y) -tests/test-authz-simple$(EXESUF): tests/test-authz-simple.o $(test-authz-obj-y) -tests/test-authz-list$(EXESUF): tests/test-authz-list.o $(test-authz-obj-y) -tests/test-authz-listfile$(EXESUF): tests/test-authz-listfile.o $(test-authz-obj-y) -tests/test-authz-pam$(EXESUF): tests/test-authz-pam.o $(test-authz-obj-y) -tests/test-io-task$(EXESUF): tests/test-io-task.o $(test-io-obj-y) -tests/test-io-channel-socket$(EXESUF): tests/test-io-channel-socket.o \ - tests/io-channel-helpers.o tests/socket-helpers.o $(test-io-obj-y) -tests/test-io-channel-file$(EXESUF): tests/test-io-channel-file.o \ - tests/io-channel-helpers.o $(test-io-obj-y) -tests/test-io-channel-tls$(EXESUF): tests/test-io-channel-tls.o \ - tests/crypto-tls-x509-helpers.o tests/pkix_asn1_tab.o \ - tests/io-channel-helpers.o $(test-io-obj-y) -tests/test-io-channel-command$(EXESUF): tests/test-io-channel-command.o \ - tests/io-channel-helpers.o $(test-io-obj-y) -tests/test-io-channel-buffer$(EXESUF): tests/test-io-channel-buffer.o \ - tests/io-channel-helpers.o $(test-io-obj-y) -tests/test-crypto-pbkdf$(EXESUF): tests/test-crypto-pbkdf.o $(test-crypto-obj-y) -tests/test-crypto-ivgen$(EXESUF): tests/test-crypto-ivgen.o $(test-crypto-obj-y) -tests/test-crypto-afsplit$(EXESUF): tests/test-crypto-afsplit.o $(test-crypto-obj-y) -tests/test-crypto-block$(EXESUF): tests/test-crypto-block.o $(test-crypto-obj-y) - -tests/migration/stress$(EXESUF): tests/migration/stress.o - $(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ,"LINK","$(TARGET_DIR)$@") - -INITRD_WORK_DIR=tests/migration/initrd - -tests/migration/initrd-stress.img: tests/migration/stress$(EXESUF) - mkdir -p $(INITRD_WORK_DIR) - cp $< $(INITRD_WORK_DIR)/init - (cd $(INITRD_WORK_DIR) && (find | cpio --quiet -o -H newc | gzip -9)) > $@ - rm $(INITRD_WORK_DIR)/init - rmdir $(INITRD_WORK_DIR) - -include $(SRC_PATH)/tests/qtest/Makefile.include - -tests/test-qga$(EXESUF): qemu-ga$(EXESUF) -tests/test-qga$(EXESUF): tests/test-qga.o $(qtest-obj-y) -tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o $(test-util-obj-y) libvhost-user.a -tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o - SPEED = quick -# gtester tests, possibly with verbose output -# do_test_tap runs all tests, even if some of them fail, while do_test_human -# stops at the first failure unless -k is given on the command line - -define do_test_human_k - $(quiet-@)rc=0; $(foreach COMMAND, $1, \ - $(call quiet-command-run, \ - export MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$(( $${RANDOM:-0} % 255 + 1))} $2; \ - $(COMMAND) -m=$(SPEED) -k --tap < /dev/null \ - | ./scripts/tap-driver.pl --test-name="$(notdir $(COMMAND))" $(if $(V),, --show-failures-only) \ - || rc=$$?;, "TEST", "$@: $(COMMAND)")) exit $$rc -endef -define do_test_human_no_k - $(foreach COMMAND, $1, \ - $(call quiet-command, \ - MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$(( $${RANDOM:-0} % 255 + 1))} $2 \ - $(COMMAND) -m=$(SPEED) -k --tap < /dev/null \ - | ./scripts/tap-driver.pl --test-name="$(notdir $(COMMAND))" $(if $(V),, --show-failures-only), \ - "TEST", "$@: $(COMMAND)") -) -endef -do_test_human = \ - $(if $(findstring k, $(MAKEFLAGS)), $(do_test_human_k), $(do_test_human_no_k)) - -define do_test_tap - $(call quiet-command, \ - { export MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$(( $${RANDOM:-0} % 255 + 1))} $2; \ - $(foreach COMMAND, $1, \ - $(COMMAND) -m=$(SPEED) -k --tap < /dev/null \ - | sed "s/^[a-z][a-z]* [0-9]* /&$(notdir $(COMMAND)) /" || true; ) } \ - | ./scripts/tap-merge.pl | tee "$@" \ - | ./scripts/tap-driver.pl $(if $(V),, --show-failures-only), \ - "TAP","$@") -endef - -.PHONY: $(patsubst %, check-qtest-%, $(QTEST_TARGETS)) -$(patsubst %, check-qtest-%, $(QTEST_TARGETS)): check-qtest-%: %-softmmu/all $(check-qtest-y) - $(call do_test_human,$(check-qtest-$*-y:%=tests/qtest/%$(EXESUF)) $(check-qtest-generic-y:%=tests/qtest/%$(EXESUF)), \ - QTEST_QEMU_BINARY=$*-softmmu/qemu-system-$* \ - QTEST_QEMU_IMG=qemu-img$(EXESUF)) - -check-unit: $(check-unit-y) - $(call do_test_human, $^) - -check-speed: $(check-speed-y) - $(call do_test_human, $^) - -# gtester tests with TAP output - -$(patsubst %, check-report-qtest-%.tap, $(QTEST_TARGETS)): check-report-qtest-%.tap: %-softmmu/all $(check-qtest-y) - $(call do_test_tap, $(check-qtest-$*-y:%=tests/qtest/%$(EXESUF)) $(check-qtest-generic-y:%=tests/qtest/%$(EXESUF)), \ - QTEST_QEMU_BINARY=$*-softmmu/qemu-system-$* \ - QTEST_QEMU_IMG=qemu-img$(EXESUF)) - -check-report-unit.tap: $(check-unit-y) - $(call do_test_tap,$^) - -# Reports and overall runs - -check-report.tap: $(patsubst %,check-report-qtest-%.tap, $(QTEST_TARGETS)) check-report-unit.tap - $(call quiet-command, cat $^ | scripts/tap-merge.pl >$@,"GEN","$@") - -# FPU Emulation tests (aka softfloat) -# -# As we still have some places that need fixing the rules are a little -# more complex than they need to be and have to override some of the -# generic Makefile expansions. Once we are cleanly passing all -# the tests we can simplify the make syntax. - -FP_TEST_BIN=$(BUILD_DIR)/tests/fp/fp-test - -# the build dir is created by configure -.PHONY: $(FP_TEST_BIN) -$(FP_TEST_BIN): config-host.h $(test-util-obj-y) - $(call quiet-command, \ - $(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" $(notdir $@), \ - "BUILD", "$(notdir $@)") - -# The full test suite can take a bit of time, default to a quick run -# "-l 2 -r all" can take more than a day for some operations and is best -# run manually -FP_TL=-l 1 -r all - -# $1 = tests, $2 = description, $3 = test flags -test-softfloat = $(call quiet-command, \ - cd $(BUILD_DIR)/tests/fp && \ - ./fp-test -s $(if $3,$3,$(FP_TL)) $1 > $2.out 2>&1 || \ - (cat $2.out && exit 1;), \ - "FLOAT TEST", $2) - -# Conversion Routines: -# FIXME: i32_to_extF80 (broken), i64_to_extF80 (broken) -# ui32_to_f128 (not implemented), extF80_roundToInt (broken) -# -check-softfloat-conv: $(FP_TEST_BIN) - $(call test-softfloat, \ - i32_to_f16 i64_to_f16 \ - i32_to_f32 i64_to_f32 \ - i32_to_f64 i64_to_f64 \ - i32_to_f128 i64_to_f128, int-to-float) - $(call test-softfloat, \ - ui32_to_f16 ui64_to_f16 \ - ui32_to_f32 ui64_to_f32 \ - ui32_to_f64 ui64_to_f64 \ - ui64_to_f128, uint-to-float) - $(call test-softfloat, \ - f16_to_i32 f16_to_i32_r_minMag \ - f32_to_i32 f32_to_i32_r_minMag \ - f64_to_i32 f64_to_i32_r_minMag \ - extF80_to_i32 extF80_to_i32_r_minMag \ - f128_to_i32 f128_to_i32_r_minMag \ - f16_to_i64 f16_to_i64_r_minMag \ - f32_to_i64 f32_to_i64_r_minMag \ - f64_to_i64 f64_to_i64_r_minMag \ - extF80_to_i64 extF80_to_i64_r_minMag \ - f128_to_i64 f128_to_i64_r_minMag, \ - float-to-int) - $(call test-softfloat, \ - f16_to_ui32 f16_to_ui32_r_minMag \ - f32_to_ui32 f32_to_ui32_r_minMag \ - f64_to_ui32 f64_to_ui32_r_minMag \ - f128_to_ui32 f128_to_ui32_r_minMag \ - f16_to_ui64 f16_to_ui64_r_minMag \ - f32_to_ui64 f32_to_ui64_r_minMag \ - f64_to_ui64 f64_to_ui64_r_minMag \ - f128_to_ui64 f128_to_ui64_r_minMag, \ - float-to-uint) - $(call test-softfloat, \ - f16_roundToInt f32_roundToInt \ - f64_roundToInt f128_roundToInt, \ - round-to-integer) - -# Generic rule for all float operations -# -# Some patterns are overidden due to broken or missing tests. -# Hopefully these can be removed over time. - -check-softfloat-%: $(FP_TEST_BIN) - $(call test-softfloat, f16_$* f32_$* f64_$* extF80_$* f128_$*, $*) - -# Float Compare routines -SF_COMPARE_OPS=eq eq_signaling le le_quiet lt_quiet -SF_COMPARE_RULES=$(patsubst %,check-softfloat-%, $(SF_COMPARE_OPS)) - -# FIXME: extF80_le_quiet (broken) -check-softfloat-le_quiet: $(FP_TEST_BIN) - $(call test-softfloat, \ - f16_le_quiet f32_le_quiet f64_le_quiet \ - f128_le_quiet, \ - le_quiet) - -# FIXME: extF80_lt_quiet (broken) -check-softfloat-lt_quiet: $(FP_TEST_BIN) - $(call test-softfloat, \ - f16_lt_quiet f32_lt_quiet f64_lt_quiet \ - f128_lt_quiet, \ - lt_quiet) - -.PHONY: check-softfloat-compare -check-softfloat-compare: $(SF_COMPARE_RULES) - -# Math Operations - -# FIXME: extF80_mulAdd (missing) -check-softfloat-mulAdd: $(FP_TEST_BIN) - $(call test-softfloat, \ - f16_mulAdd f32_mulAdd f64_mulAdd f128_mulAdd, \ - mulAdd,-l 1) - -# FIXME: extF80_rem (broken) -check-softfloat-rem: $(FP_TEST_BIN) - $(call test-softfloat, \ - f16_rem f32_rem f64_rem f128_rem, \ - rem) - -SF_MATH_OPS=add sub mul mulAdd div rem sqrt -SF_MATH_RULES=$(patsubst %,check-softfloat-%, $(SF_MATH_OPS)) - -.PHONY: check-softfloat-ops -check-softfloat-ops: $(SF_MATH_RULES) - -# Finally a generic rule to test all of softfoat. If TCG isnt't -# enabled we define a null operation which skips the tests. - -.PHONY: check-softfloat -ifeq ($(CONFIG_TCG),y) -check-softfloat: check-softfloat-conv check-softfloat-compare check-softfloat-ops -else -check-softfloat: - $(call quiet-command, /bin/true, "FLOAT TEST", \ - "SKIPPED for non-TCG builds") -endif - -# Plugins -ifeq ($(CONFIG_PLUGIN),y) -.PHONY: plugins -plugins: - $(call quiet-command,\ - $(MAKE) $(SUBDIR_MAKEFLAGS) -C tests/plugin V="$(V)", \ - "BUILD", "plugins") -endif - # Per guest TCG tests BUILD_TCG_TARGET_RULES=$(patsubst %,build-tcg-tests-%, $(TARGET_DIRS)) @@ -809,21 +50,21 @@ RUN_TCG_TARGET_RULES=$(patsubst %,run-tcg-tests-%, $(TARGET_DIRS)) $(foreach PROBE_TARGET,$(TARGET_DIRS), \ $(eval -include $(SRC_PATH)/tests/tcg/Makefile.prereqs)) -build-tcg-tests-%: $(if $(CONFIG_PLUGIN),plugins) +$(BUILD_TCG_TARGET_RULES): build-tcg-tests-%: $(if $(CONFIG_PLUGIN),test-plugins) $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) \ -f $(SRC_PATH)/tests/tcg/Makefile.qemu \ SRC_PATH=$(SRC_PATH) \ V="$(V)" TARGET="$*" guest-tests, \ "BUILD", "TCG tests for $*") -run-tcg-tests-%: build-tcg-tests-% %/all +$(RUN_TCG_TARGET_RULES): run-tcg-tests-%: build-tcg-tests-% all $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) \ -f $(SRC_PATH)/tests/tcg/Makefile.qemu \ SRC_PATH=$(SRC_PATH) SPEED="$(SPEED)" \ V="$(V)" TARGET="$*" run-guest-tests, \ "RUN", "TCG tests for $*") -clean-tcg-tests-%: +$(CLEAN_TCG_TARGET_RULES): clean-tcg-tests-%: $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) \ -f $(SRC_PATH)/tests/tcg/Makefile.qemu \ SRC_PATH=$(SRC_PATH) TARGET="$*" clean-guest-tests, \ @@ -838,33 +79,6 @@ check-tcg: $(RUN_TCG_TARGET_RULES) .PHONY: clean-tcg clean-tcg: $(CLEAN_TCG_TARGET_RULES) -# Other tests - -QEMU_IOTESTS_HELPERS-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_LINUX)) = tests/qemu-iotests/socket_scm_helper$(EXESUF) - -.PHONY: check-tests/check-block.sh -check-tests/check-block.sh: tests/check-block.sh qemu-img$(EXESUF) \ - qemu-io$(EXESUF) qemu-nbd$(EXESUF) $(QEMU_IOTESTS_HELPERS-y) \ - $(patsubst %,%/all,$(filter %-softmmu,$(TARGET_DIRS))) - @$< - -.PHONY: check-tests/qapi-schema/frontend -check-tests/qapi-schema/frontend: $(addprefix $(SRC_PATH)/, $(check-qapi-schema-y)) - $(call quiet-command, PYTHONPATH=$(SRC_PATH)/scripts \ - PYTHONIOENCODING=utf-8 $(PYTHON) $(SRC_PATH)/tests/qapi-schema/test-qapi.py $^, \ - TEST, check-qapi-schema) - -.PHONY: check-tests/qapi-schema/doc-good.texi -check-tests/qapi-schema/doc-good.texi: tests/qapi-schema/doc-good.test.texi - @diff -u $(SRC_PATH)/tests/qapi-schema/doc-good.texi $< - -.PHONY: check-decodetree -check-decodetree: - $(call quiet-command, \ - cd $(SRC_PATH)/tests/decode && \ - ./check.sh "$(PYTHON)" "$(SRC_PATH)/scripts/decodetree.py", \ - TEST, decodetree.py) - # Python venv for running tests .PHONY: check-venv check-acceptance @@ -913,33 +127,32 @@ check-acceptance: check-venv $(TESTS_RESULTS_DIR) get-vm-images --show=$(AVOCADO_SHOW) run --job-results-dir=$(TESTS_RESULTS_DIR) \ --filter-by-tags-include-empty --filter-by-tags-include-empty-key \ $(AVOCADO_TAGS) \ - --failfast=on tests/acceptance, \ + $(if $(GITLAB_CI),,--failfast) tests/acceptance, \ "AVOCADO", "tests/acceptance") # Consolidated targets -.PHONY: check-block check-qapi-schema check-qtest check-unit check check-clean get-vm-images -check-qapi-schema: check-tests/qapi-schema/frontend check-tests/qapi-schema/doc-good.texi -check-qtest: $(patsubst %,check-qtest-%, $(QTEST_TARGETS)) -ifeq ($(CONFIG_TOOLS),y) -check-block: $(patsubst %,check-%, $(check-block-y)) +.PHONY: check-block check check-clean get-vm-images +check: + +ifeq ($(CONFIG_TOOLS)$(CONFIG_POSIX),yy) +QEMU_IOTESTS_HELPERS-$(CONFIG_LINUX) = tests/qemu-iotests/socket_scm_helper$(EXESUF) +check: check-block +check-block: $(SRC_PATH)/tests/check-block.sh qemu-img$(EXESUF) \ + qemu-io$(EXESUF) qemu-nbd$(EXESUF) $(QEMU_IOTESTS_HELPERS-y) \ + $(filter qemu-system-%, $(ninja-targets)) + @$< endif -check: check-block check-qapi-schema check-unit check-softfloat check-qtest check-decodetree + +check-build: $(QEMU_IOTESTS_HELPERS-y) + check-clean: - rm -rf $(check-unit-y) tests/*.o tests/*/*.o $(QEMU_IOTESTS_HELPERS-y) - rm -rf $(sort $(foreach target,$(SYSEMU_TARGET_LIST), $(check-qtest-$(target)-y:%=tests/qtest/%$(EXESUF))) $(check-qtest-generic-y:%=tests/qtest/%$(EXESUF))) - rm -f tests/test-qapi-gen-timestamp - rm -f tests/qtest/dbus-vmstate1-gen-timestamp rm -rf $(TESTS_VENV_DIR) $(TESTS_RESULTS_DIR) clean: check-clean -# Build the help program automatically - -all: $(QEMU_IOTESTS_HELPERS-y) +# For backwards compatibility --include $(wildcard tests/*.d) --include $(wildcard tests/qtest/*.d) --include $(wildcard tests/qtest/libqos/*.d) +check-speed: bench-speed endif diff --git a/tests/acceptance/avocado_qemu/__init__.py b/tests/acceptance/avocado_qemu/__init__.py index 59e7b4f7631f5bed1d4a7c0063750da9133f9cff..bf54e419da2c1d9a653aa17b51b9ef5ac247050e 100644 --- a/tests/acceptance/avocado_qemu/__init__.py +++ b/tests/acceptance/avocado_qemu/__init__.py @@ -57,8 +57,7 @@ def pick_default_qemu_bin(arch=None): # qemu binary path does not match arch for powerpc, handle it if 'ppc64le' in arch: arch = 'ppc64' - qemu_bin_relative_path = os.path.join("%s-softmmu" % arch, - "qemu-system-%s" % arch) + qemu_bin_relative_path = "./qemu-system-%s" % arch if is_readable_executable_file(qemu_bin_relative_path): return qemu_bin_relative_path @@ -69,13 +68,15 @@ def pick_default_qemu_bin(arch=None): def _console_interaction(test, success_message, failure_message, - send_string, keep_sending=False): + send_string, keep_sending=False, vm=None): assert not keep_sending or send_string - console = test.vm.console_socket.makefile() + if vm is None: + vm = test.vm + console = vm.console_socket.makefile() console_logger = logging.getLogger('console') while True: if send_string: - test.vm.console_socket.sendall(send_string.encode()) + vm.console_socket.sendall(send_string.encode()) if not keep_sending: send_string = None # send only once msg = console.readline().strip() @@ -115,7 +116,8 @@ def interrupt_interactive_console_until_pattern(test, success_message, _console_interaction(test, success_message, failure_message, interrupt_string, True) -def wait_for_console_pattern(test, success_message, failure_message=None): +def wait_for_console_pattern(test, success_message, failure_message=None, + vm=None): """ Waits for messages to appear on the console, while logging the content @@ -125,7 +127,7 @@ def wait_for_console_pattern(test, success_message, failure_message=None): :param success_message: if this message appears, test succeeds :param failure_message: if this message appears, test fails """ - _console_interaction(test, success_message, failure_message, None) + _console_interaction(test, success_message, failure_message, None, vm=vm) def exec_command_and_wait_for_pattern(test, command, success_message, failure_message=None): @@ -169,7 +171,8 @@ def setUp(self): self.cancel("No QEMU binary defined or found in the build tree") def _new_vm(self, *args): - vm = QEMUMachine(self.qemu_bin, sock_dir=tempfile.mkdtemp()) + self._sd = tempfile.TemporaryDirectory(prefix="avo_qemu_sock_") + vm = QEMUMachine(self.qemu_bin, sock_dir=self._sd.name) if args: vm.add_args(*args) return vm @@ -190,3 +193,16 @@ def get_vm(self, *args, name=None): def tearDown(self): for vm in self._vms.values(): vm.shutdown() + self._sd = None + + def fetch_asset(self, name, + asset_hash=None, algorithm=None, + locations=None, expire=None, + find_only=False, cancel_on_missing=True): + return super(Test, self).fetch_asset(name, + asset_hash=asset_hash, + algorithm=algorithm, + locations=locations, + expire=expire, + find_only=find_only, + cancel_on_missing=cancel_on_missing) diff --git a/tests/acceptance/boot_linux.py b/tests/acceptance/boot_linux.py index 075a386300d30dee68446c48d709257b8ee1533e..1da4a53d6a1f7bc0d2fa8ebcd974e0dbd93a6d5a 100644 --- a/tests/acceptance/boot_linux.py +++ b/tests/acceptance/boot_linux.py @@ -20,28 +20,15 @@ from avocado.utils import vmimage from avocado.utils import datadrainer from avocado.utils.path import find_command +from avocado import skipIf ACCEL_NOT_AVAILABLE_FMT = "%s accelerator does not seem to be available" KVM_NOT_AVAILABLE = ACCEL_NOT_AVAILABLE_FMT % "KVM" TCG_NOT_AVAILABLE = ACCEL_NOT_AVAILABLE_FMT % "TCG" -class BootLinux(Test): - """ - Boots a Linux system, checking for a successful initialization - """ - - timeout = 900 - chksum = None - - def setUp(self): - super(BootLinux, self).setUp() - self.vm.add_args('-smp', '2') - self.vm.add_args('-m', '1024') - self.prepare_boot() - self.prepare_cloudinit() - - def prepare_boot(self): +class BootLinuxBase(Test): + def download_boot(self): self.log.debug('Looking for and selecting a qemu-img binary to be ' 'used to create the bootable snapshot image') # If qemu-img has been built, use it, otherwise the system wide one @@ -60,17 +47,17 @@ def prepare_boot(self): if image_arch == 'ppc64': image_arch = 'ppc64le' try: - self.boot = vmimage.get( + boot = vmimage.get( 'fedora', arch=image_arch, version='31', checksum=self.chksum, algorithm='sha256', cache_dir=self.cache_dirs[0], snapshot_dir=self.workdir) - self.vm.add_args('-drive', 'file=%s' % self.boot.path) except: self.cancel('Failed to download/prepare boot image') + return boot.path - def prepare_cloudinit(self): + def download_cloudinit(self, ssh_pubkey=None): self.log.info('Preparing cloudinit image') try: cloudinit_iso = os.path.join(self.workdir, 'cloudinit.iso') @@ -80,10 +67,34 @@ def prepare_cloudinit(self): password='password', # QEMU's hard coded usermode router address phone_home_host='10.0.2.2', - phone_home_port=self.phone_home_port) - self.vm.add_args('-drive', 'file=%s,format=raw' % cloudinit_iso) + phone_home_port=self.phone_home_port, + authorized_key=ssh_pubkey) except Exception: self.cancel('Failed to prepared cloudinit image') + return cloudinit_iso + +class BootLinux(BootLinuxBase): + """ + Boots a Linux system, checking for a successful initialization + """ + + timeout = 900 + chksum = None + + def setUp(self, ssh_pubkey=None): + super(BootLinux, self).setUp() + self.vm.add_args('-smp', '2') + self.vm.add_args('-m', '1024') + self.prepare_boot() + self.prepare_cloudinit(ssh_pubkey) + + def prepare_boot(self): + path = self.download_boot() + self.vm.add_args('-drive', 'file=%s' % path) + + def prepare_cloudinit(self, ssh_pubkey=None): + cloudinit_iso = self.download_cloudinit(ssh_pubkey) + self.vm.add_args('-drive', 'file=%s,format=raw' % cloudinit_iso) def launch_and_wait(self): self.vm.set_console() @@ -172,10 +183,11 @@ def test_virt_tcg(self): self.add_common_args() self.launch_and_wait() - def test_virt_kvm(self): + def test_virt_kvm_gicv2(self): """ :avocado: tags=accel:kvm :avocado: tags=cpu:host + :avocado: tags=device:gicv2 """ if not kvm_available(self.arch, self.qemu_bin): self.cancel(KVM_NOT_AVAILABLE) @@ -185,6 +197,20 @@ def test_virt_kvm(self): self.add_common_args() self.launch_and_wait() + def test_virt_kvm_gicv3(self): + """ + :avocado: tags=accel:kvm + :avocado: tags=cpu:host + :avocado: tags=device:gicv3 + """ + if not kvm_available(self.arch, self.qemu_bin): + self.cancel(KVM_NOT_AVAILABLE) + self.vm.add_args("-accel", "kvm") + self.vm.add_args("-cpu", "host") + self.vm.add_args("-machine", "virt,gic-version=3") + self.add_common_args() + self.launch_and_wait() + class BootLinuxPPC64(BootLinux): """ @@ -211,6 +237,7 @@ class BootLinuxS390X(BootLinux): chksum = '4caaab5a434fd4d1079149a072fdc7891e354f834d355069ca982fdcaf5a122d' + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') def test_s390_ccw_virtio_tcg(self): """ :avocado: tags=machine:s390-ccw-virtio diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py index c6b06a1a138ff84a8c9f94c5b46b27d49fa7f32d..cc6ec0f8c1588fd0c017e483f528e56d24789fba 100644 --- a/tests/acceptance/boot_linux_console.py +++ b/tests/acceptance/boot_linux_console.py @@ -13,6 +13,7 @@ import gzip import shutil +from avocado import skip from avocado import skipUnless from avocado_qemu import Test from avocado_qemu import exec_command_and_wait_for_pattern @@ -28,19 +29,29 @@ except CmdNotFoundError: P7ZIP_AVAILABLE = False -class BootLinuxConsole(Test): - """ - Boots a Linux kernel and checks that the console is operational and the - kernel command line is properly passed from QEMU to the kernel - """ - - timeout = 90 - +""" +Round up to next power of 2 +""" +def pow2ceil(x): + return 1 if x == 0 else 2**(x - 1).bit_length() + +""" +Expand file size to next power of 2 +""" +def image_pow2ceil_expand(path): + size = os.path.getsize(path) + size_aligned = pow2ceil(size) + if size != size_aligned: + with open(path, 'ab+') as fd: + fd.truncate(size_aligned) + +class LinuxKernelTest(Test): KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - def wait_for_console_pattern(self, success_message): + def wait_for_console_pattern(self, success_message, vm=None): wait_for_console_pattern(self, success_message, - failure_message='Kernel panic - not syncing') + failure_message='Kernel panic - not syncing', + vm=vm) def extract_from_deb(self, deb, path): """ @@ -79,6 +90,13 @@ def extract_from_rpm(self, rpm, path): os.chdir(cwd) return os.path.normpath(os.path.join(self.workdir, path)) +class BootLinuxConsole(LinuxKernelTest): + """ + Boots a Linux kernel and checks that the console is operational and the + kernel command line is properly passed from QEMU to the kernel + """ + timeout = 90 + def test_x86_64_pc(self): """ :avocado: tags=arch:x86_64 @@ -190,6 +208,8 @@ def test_mips_malta_cpio(self): 'Debian') exec_command_and_wait_for_pattern(self, 'reboot', 'reboot: Restarting system') + # Wait for VM to shut down gracefully + self.vm.wait() @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') def test_mips64el_malta_5KEc_cpio(self): @@ -230,6 +250,8 @@ def test_mips64el_malta_5KEc_cpio(self): '3.19.3.mtoman.20150408') exec_command_and_wait_for_pattern(self, 'reboot', 'reboot: Restarting system') + # Wait for VM to shut down gracefully + self.vm.wait() def do_test_mips_malta32el_nanomips(self, kernel_url, kernel_hash): kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash) @@ -307,6 +329,31 @@ def test_aarch64_virt(self): console_pattern = 'Kernel command line: %s' % kernel_command_line self.wait_for_console_pattern(console_pattern) + def test_aarch64_xlnx_versal_virt(self): + """ + :avocado: tags=arch:aarch64 + :avocado: tags=machine:xlnx-versal-virt + :avocado: tags=device:pl011 + :avocado: tags=device:arm_gicv3 + """ + images_url = ('http://ports.ubuntu.com/ubuntu-ports/dists/' + 'bionic-updates/main/installer-arm64/' + '20101020ubuntu543.15/images/') + kernel_url = images_url + 'netboot/ubuntu-installer/arm64/linux' + kernel_hash = '5bfc54cf7ed8157d93f6e5b0241e727b6dc22c50' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + initrd_url = images_url + 'netboot/ubuntu-installer/arm64/initrd.gz' + initrd_hash = 'd385d3e88d53e2004c5d43cbe668b458a094f772' + initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + + self.vm.set_console() + self.vm.add_args('-m', '2G', + '-kernel', kernel_path, + '-initrd', initrd_path) + self.vm.launch() + self.wait_for_console_pattern('Checked W+X mappings: passed') + def test_arm_virt(self): """ :avocado: tags=arch:arm @@ -378,13 +425,18 @@ def do_test_arm_raspi2(self, uart_id): self.vm.set_console() kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - serial_kernel_cmdline[uart_id]) + serial_kernel_cmdline[uart_id] + + ' root=/dev/mmcblk0p2 rootwait ' + + 'dwc_otg.fiq_fsm_enable=0') self.vm.add_args('-kernel', kernel_path, '-dtb', dtb_path, - '-append', kernel_command_line) + '-append', kernel_command_line, + '-device', 'usb-kbd') self.vm.launch() console_pattern = 'Kernel command line: %s' % kernel_command_line self.wait_for_console_pattern(console_pattern) + console_pattern = 'Product: QEMU USB Keyboard' + self.wait_for_console_pattern(console_pattern) def test_arm_raspi2_uart0(self): """ @@ -434,6 +486,8 @@ def test_arm_exynos4210_initrd(self): self.wait_for_console_pattern('Boot successful.') # TODO user command, for now the uart is stuck + @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'), + 'Test artifacts fetched from unreliable apt.armbian.com') def test_arm_cubieboard_initrd(self): """ :avocado: tags=arch:arm @@ -472,9 +526,10 @@ def test_arm_cubieboard_initrd(self): 'Allwinner sun4i/sun5i') exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', 'system-control@1c00000') - exec_command_and_wait_for_pattern(self, 'reboot', - 'reboot: Restarting system') + # cubieboard's reboot is not functioning; omit reboot test. + @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'), + 'Test artifacts fetched from unreliable apt.armbian.com') def test_arm_cubieboard_sata(self): """ :avocado: tags=arch:arm @@ -516,9 +571,94 @@ def test_arm_cubieboard_sata(self): 'Allwinner sun4i/sun5i') exec_command_and_wait_for_pattern(self, 'cat /proc/partitions', 'sda') - exec_command_and_wait_for_pattern(self, 'reboot', - 'reboot: Restarting system') + # cubieboard's reboot is not functioning; omit reboot test. + @skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') + def test_arm_quanta_gsj(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:quanta-gsj + """ + # 25 MiB compressed, 32 MiB uncompressed. + image_url = ( + 'https://github.com/hskinnemoen/openbmc/releases/download/' + '20200711-gsj-qemu-0/obmc-phosphor-image-gsj.static.mtd.gz') + image_hash = '14895e634923345cb5c8776037ff7876df96f6b1' + image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash) + image_name = 'obmc.mtd' + image_path = os.path.join(self.workdir, image_name) + archive.gzip_uncompress(image_path_gz, image_path) + + self.vm.set_console() + drive_args = 'file=' + image_path + ',if=mtd,bus=0,unit=0' + self.vm.add_args('-drive', drive_args) + self.vm.launch() + + # Disable drivers and services that stall for a long time during boot, + # to avoid running past the 90-second timeout. These may be removed + # as the corresponding device support is added. + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + ( + 'console=${console} ' + 'mem=${mem} ' + 'initcall_blacklist=npcm_i2c_bus_driver_init ' + 'systemd.mask=systemd-random-seed.service ' + 'systemd.mask=dropbearkey.service ' + ) + + self.wait_for_console_pattern('> BootBlock by Nuvoton') + self.wait_for_console_pattern('>Device: Poleg BMC NPCM730') + self.wait_for_console_pattern('>Skip DDR init.') + self.wait_for_console_pattern('U-Boot ') + interrupt_interactive_console_until_pattern( + self, 'Hit any key to stop autoboot:', 'U-Boot>') + exec_command_and_wait_for_pattern( + self, "setenv bootargs ${bootargs} " + kernel_command_line, + 'U-Boot>') + exec_command_and_wait_for_pattern( + self, 'run romboot', 'Booting Kernel from flash') + self.wait_for_console_pattern('Booting Linux on physical CPU 0x0') + self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0') + self.wait_for_console_pattern('OpenBMC Project Reference Distro') + self.wait_for_console_pattern('gsj login:') + + def test_arm_quanta_gsj_initrd(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:quanta-gsj + """ + initrd_url = ( + 'https://github.com/hskinnemoen/openbmc/releases/download/' + '20200711-gsj-qemu-0/obmc-phosphor-initramfs-gsj.cpio.xz') + initrd_hash = '98fefe5d7e56727b1eb17d5c00311b1b5c945300' + initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + kernel_url = ( + 'https://github.com/hskinnemoen/openbmc/releases/download/' + '20200711-gsj-qemu-0/uImage-gsj.bin') + kernel_hash = 'fa67b2f141d56d39b3c54305c0e8a899c99eb2c7' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + dtb_url = ( + 'https://github.com/hskinnemoen/openbmc/releases/download/' + '20200711-gsj-qemu-0/nuvoton-npcm730-gsj.dtb') + dtb_hash = '18315f7006d7b688d8312d5c727eecd819aa36a4' + dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200n8 ' + 'earlycon=uart8250,mmio32,0xf0001000') + self.vm.add_args('-kernel', kernel_path, + '-initrd', initrd_path, + '-dtb', dtb_path, + '-append', kernel_command_line) + self.vm.launch() + + self.wait_for_console_pattern('Booting Linux on physical CPU 0x0') + self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0') + self.wait_for_console_pattern( + 'Give root password for system maintenance') + + @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'), + 'Test artifacts fetched from unreliable apt.armbian.com') def test_arm_orangepi(self): """ :avocado: tags=arch:arm @@ -544,6 +684,8 @@ def test_arm_orangepi(self): console_pattern = 'Kernel command line: %s' % kernel_command_line self.wait_for_console_pattern(console_pattern) + @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'), + 'Test artifacts fetched from unreliable apt.armbian.com') def test_arm_orangepi_initrd(self): """ :avocado: tags=arch:arm @@ -583,11 +725,16 @@ def test_arm_orangepi_initrd(self): 'system-control@1c00000') exec_command_and_wait_for_pattern(self, 'reboot', 'reboot: Restarting system') + # Wait for VM to shut down gracefully + self.vm.wait() + @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'), + 'Test artifacts fetched from unreliable apt.armbian.com') def test_arm_orangepi_sd(self): """ :avocado: tags=arch:arm :avocado: tags=machine:orangepi-pc + :avocado: tags=device:sd """ deb_url = ('https://apt.armbian.com/pool/main/l/' 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb') @@ -603,6 +750,7 @@ def test_arm_orangepi_sd(self): rootfs_path_xz = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash) rootfs_path = os.path.join(self.workdir, 'rootfs.cpio') archive.lzma_uncompress(rootfs_path_xz, rootfs_path) + image_pow2ceil_expand(rootfs_path) self.vm.set_console() kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + @@ -630,16 +778,21 @@ def test_arm_orangepi_sd(self): '3 packets transmitted, 3 packets received, 0% packet loss') exec_command_and_wait_for_pattern(self, 'reboot', 'reboot: Restarting system') + # Wait for VM to shut down gracefully + self.vm.wait() + @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'), + 'Test artifacts fetched from unreliable dl.armbian.com') @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited') @skipUnless(P7ZIP_AVAILABLE, '7z not installed') def test_arm_orangepi_bionic(self): """ :avocado: tags=arch:arm :avocado: tags=machine:orangepi-pc + :avocado: tags=device:sd """ - # This test download a 196MB compressed image and expand it to 932MB... + # This test download a 196MB compressed image and expand it to 1GB image_url = ('https://dl.armbian.com/orangepipc/archive/' 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.7z') image_hash = '196a8ffb72b0123d92cea4a070894813d305c71e' @@ -647,6 +800,7 @@ def test_arm_orangepi_bionic(self): image_name = 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.img' image_path = os.path.join(self.workdir, image_name) process.run("7z e -o%s %s" % (self.workdir, image_path_7z)) + image_pow2ceil_expand(image_path) self.vm.set_console() self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw', @@ -678,8 +832,9 @@ def test_arm_orangepi_uboot_netbsd9(self): """ :avocado: tags=arch:arm :avocado: tags=machine:orangepi-pc + :avocado: tags=device:sd """ - # This test download a 304MB compressed image and expand it to 1.3GB... + # This test download a 304MB compressed image and expand it to 2GB deb_url = ('http://snapshot.debian.org/archive/debian/' '20200108T145233Z/pool/main/u/u-boot/' 'u-boot-sunxi_2020.01%2Bdfsg-1_armhf.deb') @@ -696,8 +851,9 @@ def test_arm_orangepi_uboot_netbsd9(self): image_hash = '2babb29d36d8360adcb39c09e31060945259917a' image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash) image_path = os.path.join(self.workdir, 'armv7.img') - image_drive_args = 'if=sd,format=raw,snapshot=on,file=' + image_path archive.gzip_uncompress(image_path_gz, image_path) + image_pow2ceil_expand(image_path) + image_drive_args = 'if=sd,format=raw,snapshot=on,file=' + image_path # dd if=u-boot-sunxi-with-spl.bin of=armv7.img bs=1K seek=8 conv=notrunc with open(uboot_path, 'rb') as f_in: @@ -705,12 +861,6 @@ def test_arm_orangepi_uboot_netbsd9(self): f_out.seek(8 * 1024) shutil.copyfileobj(f_in, f_out) - # Extend image, to avoid that NetBSD thinks the partition - # inside the image is larger than device size itself - f_out.seek(0, 2) - f_out.seek(64 * 1024 * 1024, 1) - f_out.write(bytearray([0x00])) - self.vm.set_console() self.vm.add_args('-nic', 'user', '-drive', image_drive_args, @@ -742,6 +892,28 @@ def test_arm_orangepi_uboot_netbsd9(self): # Wait for user-space wait_for_console_pattern(self, 'Starting root file system check') + def test_aarch64_raspi3_atf(self): + """ + :avocado: tags=arch:aarch64 + :avocado: tags=machine:raspi3 + :avocado: tags=cpu:cortex-a53 + :avocado: tags=device:pl011 + :avocado: tags=atf + """ + zip_url = ('https://github.com/pbatard/RPi3/releases/download/' + 'v1.15/RPi3_UEFI_Firmware_v1.15.zip') + zip_hash = '74b3bd0de92683cadb14e008a7575e1d0c3cafb9' + zip_path = self.fetch_asset(zip_url, asset_hash=zip_hash) + + archive.extract(zip_path, self.workdir) + efi_fd = os.path.join(self.workdir, 'RPI_EFI.fd') + + self.vm.set_console(console_index=1) + self.vm.add_args('-nodefaults', + '-device', 'loader,file=%s,force-raw=true' % efi_fd) + self.vm.launch() + self.wait_for_console_pattern('version UEFI Firmware v1.15') + def test_s390x_s390_ccw_virtio(self): """ :avocado: tags=arch:s390x @@ -768,7 +940,7 @@ def test_alpha_clipper(self): :avocado: tags=machine:clipper """ kernel_url = ('http://archive.debian.org/debian/dists/lenny/main/' - 'installer-alpha/current/images/cdrom/vmlinuz') + 'installer-alpha/20090123lenny10/images/cdrom/vmlinuz') kernel_hash = '3a943149335529e2ed3e74d0d787b85fb5671ba3' kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) @@ -826,12 +998,12 @@ def test_m68k_q800(self): console_pattern = 'No filesystem could mount root' self.wait_for_console_pattern(console_pattern) - def do_test_advcal_2018(self, day, tar_hash, kernel_name): + def do_test_advcal_2018(self, day, tar_hash, kernel_name, console=0): tar_url = ('https://www.qemu-advent-calendar.org' '/2018/download/day' + day + '.tar.xz') file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) archive.extract(file_path, self.workdir) - self.vm.set_console() + self.vm.set_console(console_index=console) self.vm.add_args('-kernel', self.workdir + '/day' + day + '/' + kernel_name) self.vm.launch() @@ -854,6 +1026,7 @@ def test_m68k_mcf5208evb(self): tar_hash = 'ac688fd00561a2b6ce1359f9ff6aa2b98c9a570c' self.do_test_advcal_2018('07', tar_hash, 'sanity-clause.elf') + @skip("Test currently broken") # Console stuck as of 5.2-rc1 def test_microblaze_s3adsp1800(self): """ :avocado: tags=arch:microblaze @@ -905,6 +1078,15 @@ def test_ppc_mac99(self): self.vm.add_args('-M', 'graphics=off') self.do_test_advcal_2018('15', tar_hash, 'invaders.elf') + def test_sh4_r2d(self): + """ + :avocado: tags=arch:sh4 + :avocado: tags=machine:r2d + """ + tar_hash = 'fe06a4fd8ccbf2e27928d64472939d47829d4c7e' + self.vm.add_args('-append', 'console=ttySC1') + self.do_test_advcal_2018('09', tar_hash, 'zImage', console=1) + def test_sparc_ss20(self): """ :avocado: tags=arch:sparc diff --git a/tests/acceptance/linux_initrd.py b/tests/acceptance/linux_initrd.py index a3e54d3fc915ad45a0913a1ae704b257be752121..a249e2f14a2436cb14a3df91948fd3195d9183a6 100644 --- a/tests/acceptance/linux_initrd.py +++ b/tests/acceptance/linux_initrd.py @@ -8,10 +8,12 @@ # 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 import logging import tempfile from avocado_qemu import Test +from avocado import skipIf class LinuxInitrd(Test): @@ -51,6 +53,7 @@ def test_with_2gib_file_should_exit_error_msg_with_linux_v3_6(self): max_size + 1) self.assertRegex(self.vm.get_log(), expected_msg) + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') def test_with_2gib_file_should_work_with_linux_v4_16(self): """ QEMU has supported up to 4 GiB initrd for recent kernel diff --git a/tests/acceptance/linux_ssh_mips_malta.py b/tests/acceptance/linux_ssh_mips_malta.py index 90d7f2f167a2a4f2241c24fe272375327bb9d607..25c5c5f74118289247a463d631701566c7d94e4f 100644 --- a/tests/acceptance/linux_ssh_mips_malta.py +++ b/tests/acceptance/linux_ssh_mips_malta.py @@ -212,6 +212,8 @@ def check_mips_malta(self, uname_m, endianess): self.run_common_commands(wordsize) self.shutdown_via_ssh() + # Wait for VM to shut down gracefully + self.vm.wait() def test_mips_malta32eb_kernel3_2_0(self): """ diff --git a/tests/acceptance/machine_avr6.py b/tests/acceptance/machine_avr6.py new file mode 100644 index 0000000000000000000000000000000000000000..6baf4e9c7f3c018a1c21d8290f461e49ad62ca5a --- /dev/null +++ b/tests/acceptance/machine_avr6.py @@ -0,0 +1,50 @@ +# +# QEMU AVR acceptance tests +# +# Copyright (c) 2019-2020 Michael Rolnik +# +# 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 . +# + +import time + +from avocado_qemu import Test + +class AVR6Machine(Test): + timeout = 5 + + def test_freertos(self): + """ + :avocado: tags=arch:avr + :avocado: tags=machine:arduino-mega-2560-v3 + """ + """ + https://github.com/seharris/qemu-avr-tests/raw/master/free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf + constantly prints out 'ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWX' + """ + rom_url = ('https://github.com/seharris/qemu-avr-tests' + '/raw/36c3e67b8755dcf/free-rtos/Demo' + '/AVR_ATMega2560_GCC/demo.elf') + rom_hash = '7eb521f511ca8f2622e0a3c5e8dd686efbb911d4' + rom_path = self.fetch_asset(rom_url, asset_hash=rom_hash) + + self.vm.add_args('-bios', rom_path) + self.vm.add_args('-nographic') + self.vm.launch() + + time.sleep(2) + self.vm.shutdown() + + self.assertIn('ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWX', + self.vm.get_log()) diff --git a/tests/acceptance/machine_m68k_nextcube.py b/tests/acceptance/machine_m68k_nextcube.py index 32cf571f948259663941f496005449f115800a7f..2baba5fdc269a704159044c5d222e16623d06761 100644 --- a/tests/acceptance/machine_m68k_nextcube.py +++ b/tests/acceptance/machine_m68k_nextcube.py @@ -9,7 +9,6 @@ import re import time import logging -import distutils.spawn from avocado_qemu import Test from avocado import skipUnless @@ -70,7 +69,7 @@ def check_bootrom_framebuffer(self, screenshot_path): @skipUnless(PIL_AVAILABLE, 'Python PIL not installed') def test_bootrom_framebuffer_size(self): - screenshot_path = os.path.join(self.workdir, "dump.png") + screenshot_path = os.path.join(self.workdir, "dump.ppm") self.check_bootrom_framebuffer(screenshot_path) width, height = Image.open(screenshot_path).size @@ -79,7 +78,7 @@ def test_bootrom_framebuffer_size(self): @skipUnless(tesseract_available(3), 'tesseract v3 OCR tool not available') def test_bootrom_framebuffer_ocr_with_tesseract_v3(self): - screenshot_path = os.path.join(self.workdir, "dump.png") + screenshot_path = os.path.join(self.workdir, "dump.ppm") self.check_bootrom_framebuffer(screenshot_path) console_logger = logging.getLogger('console') @@ -95,7 +94,7 @@ def test_bootrom_framebuffer_ocr_with_tesseract_v3(self): # that it is still alpha-level software. @skipUnless(tesseract_available(4), 'tesseract v4 OCR tool not available') def test_bootrom_framebuffer_ocr_with_tesseract_v4(self): - screenshot_path = os.path.join(self.workdir, "dump.png") + screenshot_path = os.path.join(self.workdir, "dump.ppm") self.check_bootrom_framebuffer(screenshot_path) console_logger = logging.getLogger('console') diff --git a/tests/acceptance/machine_mips_malta.py b/tests/acceptance/machine_mips_malta.py index 92b4f28a1123bb0b09ce3acdb67c0ff24ac89254..7c9a4ee4d2d6bdd39b4adeaf187e8acfd22ba8d5 100644 --- a/tests/acceptance/machine_mips_malta.py +++ b/tests/acceptance/machine_mips_malta.py @@ -15,6 +15,7 @@ from avocado_qemu import Test from avocado_qemu import wait_for_console_pattern from avocado.utils import archive +from avocado import skipIf NUMPY_AVAILABLE = True @@ -99,6 +100,7 @@ def test_mips_malta_i6400_framebuffer_logo_1core(self): """ self.do_test_i6400_framebuffer_logo(1) + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') def test_mips_malta_i6400_framebuffer_logo_7cores(self): """ :avocado: tags=arch:mips64el @@ -108,6 +110,7 @@ def test_mips_malta_i6400_framebuffer_logo_7cores(self): """ self.do_test_i6400_framebuffer_logo(7) + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') def test_mips_malta_i6400_framebuffer_logo_8cores(self): """ :avocado: tags=arch:mips64el diff --git a/tests/acceptance/machine_rx_gdbsim.py b/tests/acceptance/machine_rx_gdbsim.py new file mode 100644 index 0000000000000000000000000000000000000000..32b737b6d85bebcecf66eee69fb4ad3438abf1ef --- /dev/null +++ b/tests/acceptance/machine_rx_gdbsim.py @@ -0,0 +1,73 @@ +# Functional test that boots a Linux kernel and checks the console +# +# Copyright (c) 2018 Red Hat, Inc. +# +# Author: +# Cleber Rosa +# +# 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 Test +from avocado_qemu import exec_command_and_wait_for_pattern +from avocado_qemu import wait_for_console_pattern +from avocado.utils import archive + + +class RxGdbSimMachine(Test): + + timeout = 30 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + def test_uboot(self): + """ + U-Boot and checks that the console is operational. + + :avocado: tags=arch:rx + :avocado: tags=machine:gdbsim-r5f562n8 + :avocado: tags=endian:little + """ + uboot_url = ('https://acc.dl.osdn.jp/users/23/23888/u-boot.bin.gz') + uboot_hash = '9b78dbd43b40b2526848c0b1ce9de02c24f4dcdb' + uboot_path = self.fetch_asset(uboot_url, asset_hash=uboot_hash) + uboot_path = archive.uncompress(uboot_path, self.workdir) + + self.vm.set_console() + self.vm.add_args('-bios', uboot_path, + '-no-reboot') + self.vm.launch() + uboot_version = 'U-Boot 2016.05-rc3-23705-ga1ef3c71cb-dirty' + wait_for_console_pattern(self, uboot_version) + gcc_version = 'rx-unknown-linux-gcc (GCC) 9.0.0 20181105 (experimental)' + # FIXME limit baudrate on chardev, else we type too fast + #exec_command_and_wait_for_pattern(self, 'version', gcc_version) + + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + def test_linux_sash(self): + """ + Boots a Linux kernel and checks that the console is operational. + + :avocado: tags=arch:rx + :avocado: tags=machine:gdbsim-r5f562n7 + :avocado: tags=endian:little + """ + dtb_url = ('https://acc.dl.osdn.jp/users/23/23887/rx-virt.dtb') + dtb_hash = '7b4e4e2c71905da44e86ce47adee2210b026ac18' + dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash) + kernel_url = ('http://acc.dl.osdn.jp/users/23/23845/zImage') + kernel_hash = '39a81067f8d72faad90866ddfefa19165d68fc99' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'earlycon' + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-no-reboot') + self.vm.launch() + wait_for_console_pattern(self, 'Sash command shell (version 1.1.1)', + failure_message='Kernel panic - not syncing') + exec_command_and_wait_for_pattern(self, 'printenv', 'TERM=linux') diff --git a/tests/acceptance/machine_sparc64_sun4u.py b/tests/acceptance/machine_sparc64_sun4u.py new file mode 100644 index 0000000000000000000000000000000000000000..458165500ec440477688d3a4e53bf2397b805e9f --- /dev/null +++ b/tests/acceptance/machine_sparc64_sun4u.py @@ -0,0 +1,36 @@ +# Functional test that boots a Linux kernel and checks the console +# +# Copyright (c) 2020 Red Hat, Inc. +# +# Author: +# Thomas Huth +# +# 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_qemu import wait_for_console_pattern +from avocado.utils import archive +from boot_linux_console import LinuxKernelTest + +class Sun4uMachine(LinuxKernelTest): + """Boots the Linux kernel and checks that the console is operational""" + + timeout = 90 + + def test_sparc64_sun4u(self): + """ + :avocado: tags=arch:sparc64 + :avocado: tags=machine:sun4u + """ + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day23.tar.xz') + tar_hash = '142db83cd974ffadc4f75c8a5cad5bcc5722c240' + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + archive.extract(file_path, self.workdir) + self.vm.set_console() + self.vm.add_args('-kernel', self.workdir + '/day23/vmlinux', + '-append', self.KERNEL_COMMON_COMMAND_LINE) + self.vm.launch() + wait_for_console_pattern(self, 'Starting logging: OK') diff --git a/tests/acceptance/migration.py b/tests/acceptance/migration.py index 0365289cda85cf9b4ce1878de174f69c00a6a95f..792639cb693a4a3a6af53a805e6652839c598488 100644 --- a/tests/acceptance/migration.py +++ b/tests/acceptance/migration.py @@ -35,6 +35,10 @@ def assert_migration(self, src_vm, dst_vm): timeout=self.timeout, step=0.1, args=(src_vm,)) + wait.wait_for(self.migration_finished, + timeout=self.timeout, + step=0.1, + args=(dst_vm,)) self.assertEqual(src_vm.command('query-migrate')['status'], 'completed') self.assertEqual(dst_vm.command('query-migrate')['status'], 'completed') self.assertEqual(dst_vm.command('query-status')['status'], 'running') diff --git a/tests/acceptance/pc_cpu_hotplug_props.py b/tests/acceptance/pc_cpu_hotplug_props.py index 08b7e632c60c06313c7e862cb9104deba6becc8b..e49bf33fc5a1b6d1064e7e6d6a46639478f8dc2f 100644 --- a/tests/acceptance/pc_cpu_hotplug_props.py +++ b/tests/acceptance/pc_cpu_hotplug_props.py @@ -9,7 +9,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/acceptance/ppc_prep_40p.py b/tests/acceptance/ppc_prep_40p.py index 151556124915923d91a695035aa5a83b9cd8f569..96ba13b8943315ae05a1469e0ba8f91e9f342c8f 100644 --- a/tests/acceptance/ppc_prep_40p.py +++ b/tests/acceptance/ppc_prep_40p.py @@ -22,7 +22,6 @@ class IbmPrep40pMachine(Test): # All rights reserved. # U.S. Government Users Restricted Rights - Use, duplication or disclosure # restricted by GSA ADP Schedule Contract with IBM Corp. - @skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI') @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') def test_factory_firmware_and_netbsd(self): """ @@ -35,7 +34,7 @@ def test_factory_firmware_and_netbsd(self): '7020-40p/P12H0456.IMG') bios_hash = '1775face4e6dc27f3a6ed955ef6eb331bf817f03' bios_path = self.fetch_asset(bios_url, asset_hash=bios_hash) - drive_url = ('https://cdn.netbsd.org/pub/NetBSD/NetBSD-archive/' + drive_url = ('https://archive.netbsd.org/pub/NetBSD-archive/' 'NetBSD-4.0/prep/installation/floppy/generic_com0.fs') drive_hash = 'dbcfc09912e71bd5f0d82c7c1ee43082fb596ceb' drive_path = self.fetch_asset(drive_url, asset_hash=drive_hash) @@ -61,7 +60,6 @@ def test_openbios_192m(self): wait_for_console_pattern(self, '>> Memory: 192M') wait_for_console_pattern(self, '>> CPU type PowerPC,604') - @skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI') def test_openbios_and_netbsd(self): """ :avocado: tags=arch:ppc diff --git a/tests/acceptance/replay_kernel.py b/tests/acceptance/replay_kernel.py new file mode 100644 index 0000000000000000000000000000000000000000..772633b01da7966d6a95d1399b1eb97b64ba61ad --- /dev/null +++ b/tests/acceptance/replay_kernel.py @@ -0,0 +1,471 @@ +# Record/replay test that boots a Linux kernel +# +# Copyright (c) 2020 ISP RAS +# +# Author: +# Pavel Dovgalyuk +# +# 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 +import lzma +import shutil +import logging +import time + +from avocado import skip +from avocado import skipIf +from avocado import skipUnless +from avocado_qemu import wait_for_console_pattern +from avocado.utils import archive +from avocado.utils import process +from boot_linux_console import LinuxKernelTest + +class ReplayKernelBase(LinuxKernelTest): + """ + Boots a Linux kernel in record mode and checks that the console + is operational and the kernel command line is properly passed + from QEMU to the kernel. + Then replays the same scenario and verifies, that QEMU correctly + terminates. + """ + + timeout = 90 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=1 panic=-1 ' + + def run_vm(self, kernel_path, kernel_command_line, console_pattern, + record, shift, args, replay_path): + logger = logging.getLogger('replay') + start_time = time.time() + vm = self.get_vm() + vm.set_console() + if record: + logger.info('recording the execution...') + mode = 'record' + else: + logger.info('replaying the execution...') + mode = 'replay' + vm.add_args('-icount', 'shift=%s,rr=%s,rrfile=%s' % + (shift, mode, replay_path), + '-kernel', kernel_path, + '-append', kernel_command_line, + '-net', 'none', + '-no-reboot') + if args: + vm.add_args(*args) + vm.launch() + self.wait_for_console_pattern(console_pattern, vm) + if record: + vm.shutdown() + logger.info('finished the recording with log size %s bytes' + % os.path.getsize(replay_path)) + else: + vm.wait() + logger.info('successfully finished the replay') + elapsed = time.time() - start_time + logger.info('elapsed time %.2f sec' % elapsed) + return elapsed + + def run_rr(self, kernel_path, kernel_command_line, console_pattern, + shift=7, args=None): + replay_path = os.path.join(self.workdir, 'replay.bin') + t1 = self.run_vm(kernel_path, kernel_command_line, console_pattern, + True, shift, args, replay_path) + t2 = self.run_vm(kernel_path, kernel_command_line, console_pattern, + False, shift, args, replay_path) + logger = logging.getLogger('replay') + logger.info('replay overhead {:.2%}'.format(t2 / t1 - 1)) + +class ReplayKernelNormal(ReplayKernelBase): + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + def test_x86_64_pc(self): + """ + :avocado: tags=arch:x86_64 + :avocado: tags=machine:pc + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/29/Everything/x86_64/os/images/pxeboot' + '/vmlinuz') + kernel_hash = '23bebd2680757891cf7adedb033532163a792495' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + console_pattern = 'VFS: Cannot open root device' + + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) + + def test_mips_malta(self): + """ + :avocado: tags=arch:mips + :avocado: tags=machine:malta + :avocado: tags=endian:big + """ + deb_url = ('http://snapshot.debian.org/archive/debian/' + '20130217T032700Z/pool/main/l/linux-2.6/' + 'linux-image-2.6.32-5-4kc-malta_2.6.32-48_mips.deb') + deb_hash = 'a8cfc28ad8f45f54811fc6cf74fc43ffcfe0ba04' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinux-2.6.32-5-4kc-malta') + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + console_pattern = 'Kernel command line: %s' % kernel_command_line + + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) + + def test_mips64el_malta(self): + """ + This test requires the ar tool to extract "data.tar.gz" from + the Debian package. + + The kernel can be rebuilt using this Debian kernel source [1] and + following the instructions on [2]. + + [1] http://snapshot.debian.org/package/linux-2.6/2.6.32-48/ + #linux-source-2.6.32_2.6.32-48 + [2] https://kernel-team.pages.debian.net/kernel-handbook/ + ch-common-tasks.html#s-common-official + + :avocado: tags=arch:mips64el + :avocado: tags=machine:malta + """ + deb_url = ('http://snapshot.debian.org/archive/debian/' + '20130217T032700Z/pool/main/l/linux-2.6/' + 'linux-image-2.6.32-5-5kc-malta_2.6.32-48_mipsel.deb') + deb_hash = '1aaec92083bf22fda31e0d27fa8d9a388e5fc3d5' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinux-2.6.32-5-5kc-malta') + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) + + def test_aarch64_virt(self): + """ + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt + :avocado: tags=cpu:cortex-a53 + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/29/Everything/aarch64/os/images/pxeboot' + '/vmlinuz') + kernel_hash = '8c73e469fc6ea06a58dc83a628fc695b693b8493' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0') + console_pattern = 'VFS: Cannot open root device' + + self.run_rr(kernel_path, kernel_command_line, console_pattern, + args=('-cpu', 'cortex-a53')) + + def test_arm_virt(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:virt + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/29/Everything/armhfp/os/images/pxeboot' + '/vmlinuz') + kernel_hash = 'e9826d741b4fb04cadba8d4824d1ed3b7fb8b4d4' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0') + console_pattern = 'VFS: Cannot open root device' + + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1) + + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'), + 'Test artifacts fetched from unreliable apt.armbian.com') + def test_arm_cubieboard_initrd(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:cubieboard + """ + deb_url = ('https://apt.armbian.com/pool/main/l/' + 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb') + deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinuz-4.20.7-sunxi') + dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb' + dtb_path = self.extract_from_deb(deb_path, dtb_path) + initrd_url = ('https://github.com/groeck/linux-build-test/raw/' + '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' + 'arm/rootfs-armv5.cpio.gz') + initrd_hash = '2b50f1873e113523967806f4da2afe385462ff9b' + initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + initrd_path = os.path.join(self.workdir, 'rootfs.cpio') + archive.gzip_uncompress(initrd_path_gz, initrd_path) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + 'usbcore.nousb ' + 'panic=-1 noreboot') + console_pattern = 'Boot successful.' + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1, + args=('-dtb', dtb_path, + '-initrd', initrd_path, + '-no-reboot')) + + def test_ppc64_pseries(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:pseries + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/29/Everything/ppc64le/os' + '/ppc/ppc64/vmlinuz') + kernel_hash = '3fe04abfc852b66653b8c3c897a59a689270bc77' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=hvc0' + # icount is not good enough for PPC64 for complete boot yet + console_pattern = 'Kernel command line: %s' % kernel_command_line + 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) + + def do_test_advcal_2018(self, file_path, kernel_name, args=None): + archive.extract(file_path, self.workdir) + + for entry in os.scandir(self.workdir): + if entry.name.startswith('day') and entry.is_dir(): + kernel_path = os.path.join(entry.path, kernel_name) + break + + kernel_command_line = '' + console_pattern = 'QEMU advent calendar' + self.run_rr(kernel_path, kernel_command_line, console_pattern, + args=args) + + def test_arm_vexpressa9(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:vexpress-a9 + """ + tar_hash = '32b7677ce8b6f1471fb0059865f451169934245b' + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day16.tar.xz') + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + dtb_path = self.workdir + '/day16/vexpress-v2p-ca9.dtb' + self.do_test_advcal_2018(file_path, 'winter.zImage', + args=('-dtb', dtb_path)) + + def test_m68k_mcf5208evb(self): + """ + :avocado: tags=arch:m68k + :avocado: tags=machine:mcf5208evb + """ + tar_hash = 'ac688fd00561a2b6ce1359f9ff6aa2b98c9a570c' + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day07.tar.xz') + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + self.do_test_advcal_2018(file_path, 'sanity-clause.elf') + + @skip("Test currently broken") # Console stuck as of 5.2-rc1 + def test_microblaze_s3adsp1800(self): + """ + :avocado: tags=arch:microblaze + :avocado: tags=machine:petalogix-s3adsp1800 + """ + tar_hash = '08bf3e3bfb6b6c7ce1e54ab65d54e189f2caf13f' + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day17.tar.xz') + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + self.do_test_advcal_2018(file_path, 'ballerina.bin') + + def test_ppc64_e500(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:ppce500 + :avocado: tags=cpu:e5500 + """ + tar_hash = '6951d86d644b302898da2fd701739c9406527fe1' + 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')) + + def test_ppc_g3beige(self): + """ + :avocado: tags=arch:ppc + :avocado: tags=machine:g3beige + """ + tar_hash = 'e0b872a5eb8fdc5bed19bd43ffe863900ebcedfc' + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day15.tar.xz') + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + self.do_test_advcal_2018(file_path, 'invaders.elf', + args=('-M', 'graphics=off')) + + def test_ppc_mac99(self): + """ + :avocado: tags=arch:ppc + :avocado: tags=machine:mac99 + """ + tar_hash = 'e0b872a5eb8fdc5bed19bd43ffe863900ebcedfc' + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day15.tar.xz') + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + self.do_test_advcal_2018(file_path, 'invaders.elf', + args=('-M', 'graphics=off')) + + def test_sparc_ss20(self): + """ + :avocado: tags=arch:sparc + :avocado: tags=machine:SS-20 + """ + tar_hash = 'b18550d5d61c7615d989a06edace051017726a9f' + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day11.tar.xz') + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + self.do_test_advcal_2018(file_path, 'zImage.elf') + + def test_xtensa_lx60(self): + """ + :avocado: tags=arch:xtensa + :avocado: tags=machine:lx60 + :avocado: tags=cpu:dc233c + """ + tar_hash = '49e88d9933742f0164b60839886c9739cb7a0d34' + 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')) + +@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') +class ReplayKernelSlow(ReplayKernelBase): + # Override the timeout, because this kernel includes an inner + # loop which is executed with TB recompilings during replay, + # making it very slow. + timeout = 180 + + def test_mips_malta_cpio(self): + """ + :avocado: tags=arch:mips + :avocado: tags=machine:malta + :avocado: tags=endian:big + :avocado: tags=slowness:high + """ + deb_url = ('http://snapshot.debian.org/archive/debian/' + '20160601T041800Z/pool/main/l/linux/' + 'linux-image-4.5.0-2-4kc-malta_4.5.5-1_mips.deb') + deb_hash = 'a3c84f3e88b54e06107d65a410d1d1e8e0f340f8' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinux-4.5.0-2-4kc-malta') + initrd_url = ('https://github.com/groeck/linux-build-test/raw/' + '8584a59ed9e5eb5ee7ca91f6d74bbb06619205b8/rootfs/' + 'mips/rootfs.cpio.gz') + initrd_hash = 'bf806e17009360a866bf537f6de66590de349a99' + initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + initrd_path = self.workdir + "rootfs.cpio" + archive.gzip_uncompress(initrd_path_gz, initrd_path) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 console=tty ' + 'rdinit=/sbin/init noreboot') + console_pattern = 'Boot successful.' + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, + args=('-initrd', initrd_path)) + + @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + def test_mips64el_malta_5KEc_cpio(self): + """ + :avocado: tags=arch:mips64el + :avocado: tags=machine:malta + :avocado: tags=endian:little + :avocado: tags=slowness:high + """ + kernel_url = ('https://github.com/philmd/qemu-testing-blob/' + 'raw/9ad2df38/mips/malta/mips64el/' + 'vmlinux-3.19.3.mtoman.20150408') + kernel_hash = '00d1d268fb9f7d8beda1de6bebcc46e884d71754' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + initrd_url = ('https://github.com/groeck/linux-build-test/' + 'raw/8584a59e/rootfs/' + 'mipsel64/rootfs.mipsel64r1.cpio.gz') + initrd_hash = '1dbb8a396e916847325284dbe2151167' + initrd_path_gz = self.fetch_asset(initrd_url, algorithm='md5', + asset_hash=initrd_hash) + initrd_path = self.workdir + "rootfs.cpio" + archive.gzip_uncompress(initrd_path_gz, initrd_path) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 console=tty ' + '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')) + + def do_test_mips_malta32el_nanomips(self, kernel_path_xz): + kernel_path = self.workdir + "kernel" + with lzma.open(kernel_path_xz, 'rb') as f_in: + with open(kernel_path, 'wb') as f_out: + shutil.copyfileobj(f_in, f_out) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + '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')) + + def test_mips_malta32el_nanomips_4k(self): + """ + :avocado: tags=arch:mipsel + :avocado: tags=machine:malta + :avocado: tags=endian:little + """ + kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page4k.xz') + kernel_hash = '477456aafd2a0f1ddc9482727f20fe9575565dd6' + kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.do_test_mips_malta32el_nanomips(kernel_path_xz) + + def test_mips_malta32el_nanomips_16k_up(self): + """ + :avocado: tags=arch:mipsel + :avocado: tags=machine:malta + :avocado: tags=endian:little + """ + kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page16k_up.xz') + kernel_hash = 'e882868f944c71c816e832e2303b7874d044a7bc' + kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.do_test_mips_malta32el_nanomips(kernel_path_xz) + + def test_mips_malta32el_nanomips_64k_dbg(self): + """ + :avocado: tags=arch:mipsel + :avocado: tags=machine:malta + :avocado: tags=endian:little + """ + kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page64k_dbg.xz') + kernel_hash = '18d1c68f2e23429e266ca39ba5349ccd0aeb7180' + kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.do_test_mips_malta32el_nanomips(kernel_path_xz) diff --git a/tests/acceptance/reverse_debugging.py b/tests/acceptance/reverse_debugging.py new file mode 100644 index 0000000000000000000000000000000000000000..be01aca21765b9dc18f2ff89df8d60e3a15e0801 --- /dev/null +++ b/tests/acceptance/reverse_debugging.py @@ -0,0 +1,210 @@ +# Reverse debugging test +# +# Copyright (c) 2020 ISP RAS +# +# Author: +# Pavel Dovgalyuk +# +# 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 +import logging + +from avocado import skipIf +from avocado_qemu import BUILD_DIR +from avocado.utils import gdb +from avocado.utils import process +from avocado.utils.network.ports import find_free_port +from avocado.utils.path import find_command +from boot_linux_console import LinuxKernelTest + +class ReverseDebugging(LinuxKernelTest): + """ + Test GDB reverse debugging commands: reverse step and reverse continue. + Recording saves the execution of some instructions and makes an initial + VM snapshot to allow reverse execution. + Replay saves the order of the first instructions and then checks that they + are executed backwards in the correct order. + After that the execution is replayed to the end, and reverse continue + command is checked by setting several breakpoints, and asserting + that the execution is stopped at the last of them. + """ + + timeout = 10 + STEPS = 10 + endian_is_le = True + + def run_vm(self, record, shift, args, replay_path, image_path, port): + logger = logging.getLogger('replay') + vm = self.get_vm() + vm.set_console() + if record: + logger.info('recording the execution...') + mode = 'record' + else: + logger.info('replaying the execution...') + mode = 'replay' + vm.add_args('-gdb', 'tcp::%d' % port, '-S') + vm.add_args('-icount', 'shift=%s,rr=%s,rrfile=%s,rrsnapshot=init' % + (shift, mode, replay_path), + '-net', 'none') + vm.add_args('-drive', 'file=%s,if=none' % image_path) + if args: + vm.add_args(*args) + vm.launch() + return vm + + @staticmethod + def get_reg_le(g, reg): + res = g.cmd(b'p%x' % reg) + num = 0 + for i in range(len(res))[-2::-2]: + num = 0x100 * num + int(res[i:i + 2], 16) + return num + + @staticmethod + def get_reg_be(g, reg): + res = g.cmd(b'p%x' % reg) + return int(res, 16) + + def get_reg(self, g, reg): + # value may be encoded in BE or LE order + if self.endian_is_le: + return self.get_reg_le(g, reg) + else: + return self.get_reg_be(g, reg) + + def get_pc(self, g): + return self.get_reg(g, self.REG_PC) + + def check_pc(self, g, addr): + pc = self.get_pc(g) + if pc != addr: + self.fail('Invalid PC (read %x instead of %x)' % (pc, addr)) + + @staticmethod + def gdb_step(g): + g.cmd(b's', b'T05thread:01;') + + @staticmethod + def gdb_bstep(g): + g.cmd(b'bs', b'T05thread:01;') + + @staticmethod + def vm_get_icount(vm): + return vm.qmp('query-replay')['return']['icount'] + + def reverse_debugging(self, shift=7, args=None): + logger = logging.getLogger('replay') + + # create qcow2 for snapshots + logger.info('creating qcow2 image for VM snapshots') + image_path = os.path.join(self.workdir, 'disk.qcow2') + qemu_img = os.path.join(BUILD_DIR, 'qemu-img') + if not os.path.exists(qemu_img): + qemu_img = find_command('qemu-img', False) + if qemu_img is False: + self.cancel('Could not find "qemu-img", which is required to ' + 'create the temporary qcow2 image') + cmd = '%s create -f qcow2 %s 128M' % (qemu_img, image_path) + process.run(cmd) + + replay_path = os.path.join(self.workdir, 'replay.bin') + port = find_free_port() + + # record the log + vm = self.run_vm(True, shift, args, replay_path, image_path, port) + while self.vm_get_icount(vm) <= self.STEPS: + pass + last_icount = self.vm_get_icount(vm) + vm.shutdown() + + logger.info("recorded log with %s+ steps" % last_icount) + + # replay and run debug commands + vm = self.run_vm(False, shift, args, replay_path, image_path, port) + logger.info('connecting to gdbstub') + g = gdb.GDBRemote('127.0.0.1', port, False, False) + g.connect() + r = g.cmd(b'qSupported') + if b'qXfer:features:read+' in r: + g.cmd(b'qXfer:features:read:target.xml:0,ffb') + if b'ReverseStep+' not in r: + self.fail('Reverse step is not supported by QEMU') + if b'ReverseContinue+' not in r: + self.fail('Reverse continue is not supported by QEMU') + + logger.info('stepping forward') + steps = [] + # record first instruction addresses + for _ in range(self.STEPS): + pc = self.get_pc(g) + logger.info('saving position %x' % pc) + steps.append(pc) + self.gdb_step(g) + + # visit the recorded instruction in reverse order + logger.info('stepping backward') + for addr in steps[::-1]: + self.gdb_bstep(g) + self.check_pc(g, addr) + logger.info('found position %x' % addr) + + logger.info('seeking to the end (icount %s)' % (last_icount - 1)) + vm.qmp('replay-break', icount=last_icount - 1) + # continue - will return after pausing + g.cmd(b'c', b'T02thread:01;') + + logger.info('setting breakpoints') + for addr in steps: + # hardware breakpoint at addr with len=1 + g.cmd(b'Z1,%x,1' % addr, b'OK') + + logger.info('running reverse continue to reach %x' % steps[-1]) + # reverse continue - will return after stopping at the breakpoint + g.cmd(b'bc', b'T05thread:01;') + + # assume that none of the first instructions is executed again + # breaking the order of the breakpoints + self.check_pc(g, steps[-1]) + logger.info('successfully reached %x' % steps[-1]) + + logger.info('exitting gdb and qemu') + vm.shutdown() + +class ReverseDebugging_X86_64(ReverseDebugging): + REG_PC = 0x10 + REG_CS = 0x12 + def get_pc(self, g): + return self.get_reg_le(g, self.REG_PC) \ + + self.get_reg_le(g, self.REG_CS) * 0x10 + + # unidentified gitlab timeout problem + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + def test_x86_64_pc(self): + """ + :avocado: tags=arch:x86_64 + :avocado: tags=machine:pc + """ + # start with BIOS only + self.reverse_debugging() + +class ReverseDebugging_AArch64(ReverseDebugging): + REG_PC = 32 + + # unidentified gitlab timeout problem + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + def test_aarch64_virt(self): + """ + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt + :avocado: tags=cpu:cortex-a53 + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/29/Everything/aarch64/os/images/pxeboot' + '/vmlinuz') + kernel_hash = '8c73e469fc6ea06a58dc83a628fc695b693b8493' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.reverse_debugging( + args=('-kernel', kernel_path, '-cpu', 'cortex-a53')) diff --git a/tests/acceptance/virtiofs_submounts.py b/tests/acceptance/virtiofs_submounts.py new file mode 100644 index 0000000000000000000000000000000000000000..361e5990b65688eb0d165aceb3a0616f154a55bc --- /dev/null +++ b/tests/acceptance/virtiofs_submounts.py @@ -0,0 +1,321 @@ +import logging +import re +import os +import subprocess +import time + +from avocado import skipUnless +from avocado_qemu import Test, BUILD_DIR +from avocado_qemu import wait_for_console_pattern +from avocado.utils import ssh + +from qemu.accel import kvm_available + +from boot_linux import BootLinux + + +def run_cmd(args): + subp = subprocess.Popen(args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True) + stdout, stderr = subp.communicate() + ret = subp.returncode + + return (stdout, stderr, ret) + +def has_cmd(name, args=None): + """ + This function is for use in a @avocado.skipUnless decorator, e.g.: + + @skipUnless(*has_cmd('sudo -n', ('sudo', '-n', 'true'))) + def test_something_that_needs_sudo(self): + ... + """ + + if args is None: + args = ('which', name) + + try: + _, stderr, exitcode = run_cmd(args) + except Exception as e: + exitcode = -1 + stderr = str(e) + + if exitcode != 0: + cmd_line = ' '.join(args) + err = f'{name} required, but "{cmd_line}" failed: {stderr.strip()}' + return (False, err) + else: + return (True, '') + +def has_cmds(*cmds): + """ + This function is for use in a @avocado.skipUnless decorator and + allows checking for the availability of multiple commands, e.g.: + + @skipUnless(*has_cmds(('cmd1', ('cmd1', '--some-parameter')), + 'cmd2', 'cmd3')) + def test_something_that_needs_cmd1_and_cmd2(self): + ... + """ + + for cmd in cmds: + if isinstance(cmd, str): + cmd = (cmd,) + + ok, errstr = has_cmd(*cmd) + if not ok: + return (False, errstr) + + return (True, '') + + +class VirtiofsSubmountsTest(BootLinux): + """ + :avocado: tags=arch:x86_64 + """ + + def get_portfwd(self): + port = None + + res = self.vm.command('human-monitor-command', + command_line='info usernet') + for line in res.split('\r\n'): + match = \ + re.search(r'TCP.HOST_FORWARD.*127\.0\.0\.1\s*(\d+)\s+10\.', + line) + if match is not None: + port = match[1] + break + + self.assertIsNotNone(port) + self.log.debug('sshd listening on port: ' + port) + return port + + def ssh_connect(self, username, keyfile): + self.ssh_logger = logging.getLogger('ssh') + port = self.get_portfwd() + self.ssh_session = ssh.Session('127.0.0.1', port=int(port), + user=username, key=keyfile) + for i in range(10): + try: + self.ssh_session.connect() + return + except: + time.sleep(4) + pass + self.fail('sshd timeout') + + def ssh_command(self, command): + self.ssh_logger.info(command) + result = self.ssh_session.cmd(command) + stdout_lines = [line.rstrip() for line + in result.stdout_text.splitlines()] + for line in stdout_lines: + self.ssh_logger.info(line) + stderr_lines = [line.rstrip() for line + in result.stderr_text.splitlines()] + for line in stderr_lines: + self.ssh_logger.warning(line) + + self.assertEqual(result.exit_status, 0, + f'Guest command failed: {command}') + return stdout_lines, stderr_lines + + def run(self, args, ignore_error=False): + stdout, stderr, ret = run_cmd(args) + + if ret != 0: + cmdline = ' '.join(args) + if not ignore_error: + self.fail(f'{cmdline}: Returned {ret}: {stderr}') + else: + self.log.warn(f'{cmdline}: Returned {ret}: {stderr}') + + return (stdout, stderr, ret) + + def set_up_shared_dir(self): + atwd = os.getenv('AVOCADO_TEST_WORKDIR') + self.shared_dir = os.path.join(atwd, 'virtiofs-shared') + + os.mkdir(self.shared_dir) + + self.run(('cp', self.get_data('guest.sh'), + os.path.join(self.shared_dir, 'check.sh'))) + + self.run(('cp', self.get_data('guest-cleanup.sh'), + os.path.join(self.shared_dir, 'cleanup.sh'))) + + def set_up_virtiofs(self): + attmp = os.getenv('AVOCADO_TESTS_COMMON_TMPDIR') + self.vfsdsock = os.path.join(attmp, 'vfsdsock') + + self.run(('sudo', '-n', 'rm', '-f', self.vfsdsock), ignore_error=True) + + self.virtiofsd = \ + subprocess.Popen(('sudo', '-n', + 'tools/virtiofsd/virtiofsd', + f'--socket-path={self.vfsdsock}', + '-o', f'source={self.shared_dir}', + '-o', 'cache=always', + '-o', 'xattr', + '-o', 'announce_submounts', + '-f'), + stdout=subprocess.DEVNULL, + stderr=subprocess.PIPE, + universal_newlines=True) + + while not os.path.exists(self.vfsdsock): + if self.virtiofsd.poll() is not None: + self.fail('virtiofsd exited prematurely: ' + + self.virtiofsd.communicate()[1]) + time.sleep(0.1) + + self.run(('sudo', '-n', 'chmod', 'go+rw', self.vfsdsock)) + + self.vm.add_args('-chardev', + f'socket,id=vfsdsock,path={self.vfsdsock}', + '-device', + 'vhost-user-fs-pci,queue-size=1024,chardev=vfsdsock' \ + ',tag=host', + '-object', + 'memory-backend-file,id=mem,size=1G,' \ + 'mem-path=/dev/shm,share=on', + '-numa', + 'node,memdev=mem') + + def launch_vm(self): + self.launch_and_wait() + self.ssh_connect('root', self.ssh_key) + + def set_up_nested_mounts(self): + scratch_dir = os.path.join(self.shared_dir, 'scratch') + try: + os.mkdir(scratch_dir) + except FileExistsError: + pass + + args = ['bash', self.get_data('host.sh'), scratch_dir] + if self.seed: + args += [self.seed] + + out, _, _ = self.run(args) + seed = re.search(r'^Seed: \d+', out) + self.log.info(seed[0]) + + def mount_in_guest(self): + self.ssh_command('mkdir -p /mnt/host') + self.ssh_command('mount -t virtiofs host /mnt/host') + + def check_in_guest(self): + self.ssh_command('bash /mnt/host/check.sh /mnt/host/scratch/share') + + def live_cleanup(self): + self.ssh_command('bash /mnt/host/cleanup.sh /mnt/host/scratch') + + # It would be nice if the above was sufficient to make virtiofsd clear + # all references to the mounted directories (so they can be unmounted + # on the host), but unfortunately it is not. To do so, we have to + # resort to a remount. + self.ssh_command('mount -o remount /mnt/host') + + scratch_dir = os.path.join(self.shared_dir, 'scratch') + self.run(('bash', self.get_data('cleanup.sh'), scratch_dir)) + + @skipUnless(*has_cmds(('sudo -n', ('sudo', '-n', 'true')), + 'ssh-keygen', 'bash', 'losetup', 'mkfs.xfs', 'mount')) + def setUp(self): + vmlinuz = self.params.get('vmlinuz') + if vmlinuz is None: + self.cancel('vmlinuz parameter not set; you must point it to a ' + 'Linux kernel binary to test (to run this test with ' \ + 'the on-image kernel, set it to an empty string)') + + self.seed = self.params.get('seed') + + atwd = os.getenv('AVOCADO_TEST_WORKDIR') + self.ssh_key = os.path.join(atwd, 'id_ed25519') + + self.run(('ssh-keygen', '-t', 'ed25519', '-f', self.ssh_key)) + + pubkey = open(self.ssh_key + '.pub').read() + + super(VirtiofsSubmountsTest, self).setUp(pubkey) + + if len(vmlinuz) > 0: + self.vm.add_args('-kernel', vmlinuz, + '-append', 'console=ttyS0 root=/dev/sda1') + + # Allow us to connect to SSH + self.vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22', + '-device', 'e1000,netdev=vnet') + + if not kvm_available(self.arch, self.qemu_bin): + self.cancel(KVM_NOT_AVAILABLE) + self.vm.add_args('-accel', 'kvm') + + def tearDown(self): + try: + self.vm.shutdown() + except: + pass + + scratch_dir = os.path.join(self.shared_dir, 'scratch') + self.run(('bash', self.get_data('cleanup.sh'), scratch_dir), + ignore_error=True) + + def test_pre_virtiofsd_set_up(self): + self.set_up_shared_dir() + + self.set_up_nested_mounts() + + self.set_up_virtiofs() + self.launch_vm() + self.mount_in_guest() + self.check_in_guest() + + def test_pre_launch_set_up(self): + self.set_up_shared_dir() + self.set_up_virtiofs() + + self.set_up_nested_mounts() + + self.launch_vm() + self.mount_in_guest() + self.check_in_guest() + + def test_post_launch_set_up(self): + self.set_up_shared_dir() + self.set_up_virtiofs() + self.launch_vm() + + self.set_up_nested_mounts() + + self.mount_in_guest() + self.check_in_guest() + + def test_post_mount_set_up(self): + self.set_up_shared_dir() + self.set_up_virtiofs() + self.launch_vm() + self.mount_in_guest() + + self.set_up_nested_mounts() + + self.check_in_guest() + + def test_two_runs(self): + self.set_up_shared_dir() + + self.set_up_nested_mounts() + + self.set_up_virtiofs() + self.launch_vm() + self.mount_in_guest() + self.check_in_guest() + + self.live_cleanup() + self.set_up_nested_mounts() + + self.check_in_guest() diff --git a/tests/acceptance/virtiofs_submounts.py.data/cleanup.sh b/tests/acceptance/virtiofs_submounts.py.data/cleanup.sh new file mode 100644 index 0000000000000000000000000000000000000000..2a6579a0fea6cf7333252aa72f82a20f558853d1 --- /dev/null +++ b/tests/acceptance/virtiofs_submounts.py.data/cleanup.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +function print_usage() +{ + if [ -n "$2" ]; then + echo "Error: $2" + echo + fi + echo "Usage: $1 " +} + +scratch_dir=$1 +if [ -z "$scratch_dir" ]; then + print_usage "$0" 'Scratch dir not given' >&2 + exit 1 +fi + +cd "$scratch_dir/share" || exit 1 +mps=(mnt*) +mp_i=0 +for mp in "${mps[@]}"; do + mp_i=$((mp_i + 1)) + printf "Unmounting %i/%i...\r" "$mp_i" "${#mps[@]}" + + sudo umount -R "$mp" + rm -rf "$mp" +done +echo + +rm some-file +cd .. +rmdir share + +imgs=(fs*.img) +img_i=0 +for img in "${imgs[@]}"; do + img_i=$((img_i + 1)) + printf "Detaching and deleting %i/%i...\r" "$img_i" "${#imgs[@]}" + + dev=$(losetup -j "$img" | sed -e 's/:.*//') + sudo losetup -d "$dev" + rm -f "$img" +done +echo + +echo 'Done.' diff --git a/tests/acceptance/virtiofs_submounts.py.data/guest-cleanup.sh b/tests/acceptance/virtiofs_submounts.py.data/guest-cleanup.sh new file mode 100644 index 0000000000000000000000000000000000000000..729cb2d1a5ecc97c99c742dbc67b61837a7b919c --- /dev/null +++ b/tests/acceptance/virtiofs_submounts.py.data/guest-cleanup.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +function print_usage() +{ + if [ -n "$2" ]; then + echo "Error: $2" + echo + fi + echo "Usage: $1 " +} + +scratch_dir=$1 +if [ -z "$scratch_dir" ]; then + print_usage "$0" 'Scratch dir not given' >&2 + exit 1 +fi + +cd "$scratch_dir/share" || exit 1 + +mps=(mnt*) +mp_i=0 +for mp in "${mps[@]}"; do + mp_i=$((mp_i + 1)) + printf "Unmounting %i/%i...\r" "$mp_i" "${#mps[@]}" + + sudo umount -R "$mp" +done +echo + +echo 'Done.' diff --git a/tests/acceptance/virtiofs_submounts.py.data/guest.sh b/tests/acceptance/virtiofs_submounts.py.data/guest.sh new file mode 100644 index 0000000000000000000000000000000000000000..59ba40fde17949005bf4e912f7d6eae5b04b415a --- /dev/null +++ b/tests/acceptance/virtiofs_submounts.py.data/guest.sh @@ -0,0 +1,138 @@ +#!/bin/bash + +function print_usage() +{ + if [ -n "$2" ]; then + echo "Error: $2" + echo + fi + echo "Usage: $1 " + echo '(The shared directory is the "share" directory in the scratch' \ + 'directory)' +} + +shared_dir=$1 +if [ -z "$shared_dir" ]; then + print_usage "$0" 'Shared dir not given' >&2 + exit 1 +fi + +cd "$shared_dir" + +# FIXME: This should not be necessary, but it is. In order for all +# submounts to be proper mount points, we need to visit them. +# (Before we visit them, they will not be auto-mounted, and so just +# appear as normal directories, with the catch that their st_ino will +# be the st_ino of the filesystem they host, while the st_dev will +# still be the st_dev of the parent.) +# `find` does not work, because it will refuse to touch the mount +# points as long as they are not mounted; their st_dev being shared +# with the parent and st_ino just being the root node's inode ID +# will practically ensure that this node exists elsewhere on the +# filesystem, and `find` is required to recognize loops and not to +# follow them. +# Thus, we have to manually visit all nodes first. + +mnt_i=0 + +function recursively_visit() +{ + pushd "$1" >/dev/null + for entry in *; do + if [[ "$entry" == mnt* ]]; then + mnt_i=$((mnt_i + 1)) + printf "Triggering auto-mount $mnt_i...\r" + fi + + if [ -d "$entry" ]; then + recursively_visit "$entry" + fi + done + popd >/dev/null +} + +recursively_visit . +echo + + +if [ -n "$(find -name not-mounted)" ]; then + echo "Error: not-mounted files visible on mount points:" >&2 + find -name not-mounted >&2 + exit 1 +fi + +if [ ! -f some-file -o "$(cat some-file)" != 'root' ]; then + echo "Error: Bad file in the share root" >&2 + exit 1 +fi + +shopt -s nullglob + +function check_submounts() +{ + local base_path=$1 + + for mp in mnt*; do + printf "Checking submount %i...\r" "$((${#devs[@]} + 1))" + + mp_i=$(echo "$mp" | sed -e 's/mnt//') + dev=$(stat -c '%D' "$mp") + + if [ -n "${devs[mp_i]}" ]; then + echo "Error: $mp encountered twice" >&2 + exit 1 + fi + devs[mp_i]=$dev + + pushd "$mp" >/dev/null + path="$base_path$mp" + while true; do + expected_content="$(printf '%s\n%s\n' "$mp_i" "$path")" + if [ ! -f some-file ]; then + echo "Error: $PWD/some-file does not exist" >&2 + exit 1 + fi + + if [ "$(cat some-file)" != "$expected_content" ]; then + echo "Error: Bad content in $PWD/some-file:" >&2 + echo '--- found ---' + cat some-file + echo '--- expected ---' + echo "$expected_content" + exit 1 + fi + if [ "$(stat -c '%D' some-file)" != "$dev" ]; then + echo "Error: $PWD/some-file has the wrong device ID" >&2 + exit 1 + fi + + if [ -d sub ]; then + if [ "$(stat -c '%D' sub)" != "$dev" ]; then + echo "Error: $PWD/some-file has the wrong device ID" >&2 + exit 1 + fi + cd sub + path="$path/sub" + else + if [ -n "$(echo mnt*)" ]; then + check_submounts "$path/" + fi + break + fi + done + popd >/dev/null + done +} + +root_dev=$(stat -c '%D' some-file) +devs=() +check_submounts '' +echo + +reused_devs=$(echo "$root_dev ${devs[@]}" | tr ' ' '\n' | sort | uniq -d) +if [ -n "$reused_devs" ]; then + echo "Error: Reused device IDs: $reused_devs" >&2 + exit 1 +fi + +echo "Test passed for ${#devs[@]} submounts." diff --git a/tests/acceptance/virtiofs_submounts.py.data/host.sh b/tests/acceptance/virtiofs_submounts.py.data/host.sh new file mode 100644 index 0000000000000000000000000000000000000000..d8a9afebdb548d9b74a5261694ea67cb196e3424 --- /dev/null +++ b/tests/acceptance/virtiofs_submounts.py.data/host.sh @@ -0,0 +1,127 @@ +#!/bin/bash + +mount_count=128 + +function print_usage() +{ + if [ -n "$2" ]; then + echo "Error: $2" + echo + fi + echo "Usage: $1 [seed]" + echo "(If no seed is given, it will be randomly generated.)" +} + +scratch_dir=$1 +if [ -z "$scratch_dir" ]; then + print_usage "$0" 'No scratch dir given' >&2 + exit 1 +fi + +if [ ! -d "$scratch_dir" ]; then + print_usage "$0" "$scratch_dir is not a directory" >&2 + exit 1 +fi + +seed=$2 +if [ -z "$seed" ]; then + seed=$RANDOM +fi +RANDOM=$seed + +echo "Seed: $seed" + +set -e +shopt -s nullglob + +cd "$scratch_dir" +if [ -d share ]; then + echo 'Error: This directory seems to be in use already' >&2 + exit 1 +fi + +for ((i = 0; i < $mount_count; i++)); do + printf "Setting up fs %i/%i...\r" "$((i + 1))" "$mount_count" + + rm -f fs$i.img + truncate -s 512M fs$i.img + mkfs.xfs -q fs$i.img + devs[i]=$(sudo losetup -f --show fs$i.img) +done +echo + +top_level_mounts=$((RANDOM % mount_count + 1)) + +mkdir -p share +echo 'root' > share/some-file + +for ((i = 0; i < $top_level_mounts; i++)); do + printf "Mounting fs %i/%i...\r" "$((i + 1))" "$mount_count" + + mkdir -p share/mnt$i + touch share/mnt$i/not-mounted + sudo mount "${devs[i]}" share/mnt$i + sudo chown "$(id -u):$(id -g)" share/mnt$i + + pushd share/mnt$i >/dev/null + path=mnt$i + nesting=$((RANDOM % 4)) + for ((j = 0; j < $nesting; j++)); do + cat > some-file < some-file </dev/null +done + +for ((; i < $mount_count; i++)); do + printf "Mounting fs %i/%i...\r" "$((i + 1))" "$mount_count" + + mp_i=$((i % top_level_mounts)) + + pushd share/mnt$mp_i >/dev/null + path=mnt$mp_i + while true; do + sub_mp="$(echo mnt*)" + if cd sub 2>/dev/null; then + path="$path/sub" + elif [ -n "$sub_mp" ] && cd "$sub_mp" 2>/dev/null; then + path="$path/$sub_mp" + else + break + fi + done + mkdir mnt$i + touch mnt$i/not-mounted + sudo mount "${devs[i]}" mnt$i + sudo chown "$(id -u):$(id -g)" mnt$i + + cd mnt$i + path="$path/mnt$i" + nesting=$((RANDOM % 4)) + for ((j = 0; j < $nesting; j++)); do + cat > some-file < some-file </dev/null +done +echo + +echo 'Done.' diff --git a/tests/acceptance/x86_cpu_model_versions.py b/tests/acceptance/x86_cpu_model_versions.py index 01ff614ec254951706ae323ca38a68f64dd9db48..2b7461bb414eaf6ac0804c7726db7299af0b5d0f 100644 --- a/tests/acceptance/x86_cpu_model_versions.py +++ b/tests/acceptance/x86_cpu_model_versions.py @@ -9,7 +9,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/atomic64-bench.c b/tests/atomic64-bench.c index 121a8c14f4f3a827e21f731a714902d73c002515..e474753d34c9fbcf8ebe674939e55d111211a7b5 100644 --- a/tests/atomic64-bench.c +++ b/tests/atomic64-bench.c @@ -56,17 +56,17 @@ static void *thread_func(void *arg) { struct thread_info *info = arg; - atomic_inc(&n_ready_threads); - while (!atomic_read(&test_start)) { + qatomic_inc(&n_ready_threads); + while (!qatomic_read(&test_start)) { cpu_relax(); } - while (!atomic_read(&test_stop)) { + while (!qatomic_read(&test_stop)) { unsigned int index; info->r = xorshift64star(info->r); index = info->r & (range - 1); - atomic_read_i64(&counts[index].i64); + qatomic_read_i64(&counts[index].i64); info->accesses++; } return NULL; @@ -76,13 +76,13 @@ static void run_test(void) { unsigned int i; - while (atomic_read(&n_ready_threads) != n_threads) { + while (qatomic_read(&n_ready_threads) != n_threads) { cpu_relax(); } - atomic_set(&test_start, true); + qatomic_set(&test_start, true); g_usleep(duration * G_USEC_PER_SEC); - atomic_set(&test_stop, true); + qatomic_set(&test_stop, true); for (i = 0; i < n_threads; i++) { qemu_thread_join(&threads[i]); diff --git a/tests/atomic_add-bench.c b/tests/atomic_add-bench.c index 5666f6bbffbbfc8b7302fdd009a852cf042890b5..f05471ab45c649b200a065da4333b976d42637a3 100644 --- a/tests/atomic_add-bench.c +++ b/tests/atomic_add-bench.c @@ -53,12 +53,12 @@ static void *thread_func(void *arg) { struct thread_info *info = arg; - atomic_inc(&n_ready_threads); - while (!atomic_read(&test_start)) { + qatomic_inc(&n_ready_threads); + while (!qatomic_read(&test_start)) { cpu_relax(); } - while (!atomic_read(&test_stop)) { + while (!qatomic_read(&test_stop)) { unsigned int index; info->r = xorshift64star(info->r); @@ -68,7 +68,7 @@ static void *thread_func(void *arg) counts[index].val += 1; qemu_mutex_unlock(&counts[index].lock); } else { - atomic_inc(&counts[index].val); + qatomic_inc(&counts[index].val); } } return NULL; @@ -78,13 +78,13 @@ static void run_test(void) { unsigned int i; - while (atomic_read(&n_ready_threads) != n_threads) { + while (qatomic_read(&n_ready_threads) != n_threads) { cpu_relax(); } - atomic_set(&test_start, true); + qatomic_set(&test_start, true); g_usleep(duration * G_USEC_PER_SEC); - atomic_set(&test_stop, true); + qatomic_set(&test_stop, true); for (i = 0; i < n_threads; i++) { qemu_thread_join(&threads[i]); diff --git a/tests/benchmark-crypto-cipher.c b/tests/benchmark-crypto-cipher.c index 53032334ec87625cfdd3df46716873da651258bc..c04f0a0fba3711197a66e037ed2a685323495659 100644 --- a/tests/benchmark-crypto-cipher.c +++ b/tests/benchmark-crypto-cipher.c @@ -70,8 +70,10 @@ static void test_cipher_speed(size_t chunk_size, } g_test_timer_elapsed(); - g_print("Enc chunk %zu bytes ", chunk_size); - g_print("%.2f MB/sec ", (double)total / MiB / g_test_timer_last()); + g_test_message("enc(%s-%s) chunk %zu bytes %.2f MB/sec ", + QCryptoCipherAlgorithm_str(alg), + QCryptoCipherMode_str(mode), + chunk_size, (double)total / MiB / g_test_timer_last()); g_test_timer_start(); remain = total; @@ -85,8 +87,10 @@ static void test_cipher_speed(size_t chunk_size, } g_test_timer_elapsed(); - g_print("Dec chunk %zu bytes ", chunk_size); - g_print("%.2f MB/sec ", (double)total / MiB / g_test_timer_last()); + g_test_message("dec(%s-%s) chunk %zu bytes %.2f MB/sec ", + QCryptoCipherAlgorithm_str(alg), + QCryptoCipherMode_str(mode), + chunk_size, (double)total / MiB / g_test_timer_last()); qcrypto_cipher_free(cipher); g_free(plaintext); diff --git a/tests/benchmark-crypto-hash.c b/tests/benchmark-crypto-hash.c index d16837d00a8ae09ed695663cb432bed0d34db9af..927b00bb4d6e1e094703d8233e235a4a366a4f12 100644 --- a/tests/benchmark-crypto-hash.c +++ b/tests/benchmark-crypto-hash.c @@ -48,7 +48,9 @@ static void test_hash_speed(const void *opaque) } g_test_timer_elapsed(); - g_print("%.2f MB/sec ", (double)total / MiB / g_test_timer_last()); + g_test_message("hash(%s): chunk %zu bytes %.2f MB/sec", + QCryptoHashAlgorithm_str(opts->alg), + opts->chunk_size, total / g_test_timer_last()); g_free(out); g_free(in); diff --git a/tests/benchmark-crypto-hmac.c b/tests/benchmark-crypto-hmac.c index f1dfa240cbd1813a2403c9776958e569534844d8..5cca63678972888e3f11f315278d6d9c5c4d2a8d 100644 --- a/tests/benchmark-crypto-hmac.c +++ b/tests/benchmark-crypto-hmac.c @@ -55,10 +55,9 @@ static void test_hmac_speed(const void *opaque) } while (g_test_timer_elapsed() < 5.0); total /= MiB; - g_print("hmac(sha256): "); - g_print("Testing chunk_size %zu bytes ", chunk_size); - g_print("done: %.2f MB in %.2f secs: ", total, g_test_timer_last()); - g_print("%.2f MB/sec\n", total / g_test_timer_last()); + g_test_message("hmac(%s): chunk %zu bytes %.2f MB/sec", + QCryptoHashAlgorithm_str(QCRYPTO_HASH_ALG_SHA256), + chunk_size, total / g_test_timer_last()); g_free(out); g_free(in); diff --git a/tests/check-block-qdict.c b/tests/check-block-qdict.c index 73d3e9f574409f9dcb8a008eadf68fe10637fb46..5a25825093016d1d75c7d77e9b12dc3fd691d801 100644 --- a/tests/check-block-qdict.c +++ b/tests/check-block-qdict.c @@ -610,9 +610,7 @@ static void qdict_rename_keys_test(void) copy = qdict_clone_shallow(dict); qdict_rename_keys(copy, renames, &local_err); - g_assert(local_err != NULL); - error_free(local_err); - local_err = NULL; + error_free_or_abort(&local_err); g_assert_cmpstr(qdict_get_str(copy, "abc"), ==, "foo"); g_assert_cmpstr(qdict_get_str(copy, "abcdef"), ==, "bar"); @@ -649,9 +647,7 @@ static void qdict_crumple_test_bad_inputs(void) qdict_put_str(src, "rule.0.policy", "allow"); g_assert(qdict_crumple(src, &error) == NULL); - g_assert(error != NULL); - error_free(error); - error = NULL; + error_free_or_abort(&error); qobject_unref(src); src = qdict_new(); @@ -660,9 +656,7 @@ static void qdict_crumple_test_bad_inputs(void) qdict_put_str(src, "rule.a", "allow"); g_assert(qdict_crumple(src, &error) == NULL); - g_assert(error != NULL); - error_free(error); - error = NULL; + error_free_or_abort(&error); qobject_unref(src); src = qdict_new(); @@ -673,9 +667,7 @@ static void qdict_crumple_test_bad_inputs(void) qdict_put_str(src, "rule.b", "allow"); g_assert(qdict_crumple(src, &error) == NULL); - g_assert(error != NULL); - error_free(error); - error = NULL; + error_free_or_abort(&error); qobject_unref(src); src = qdict_new(); @@ -684,9 +676,7 @@ static void qdict_crumple_test_bad_inputs(void) qdict_put_str(src, "rule.3", "allow"); g_assert(qdict_crumple(src, &error) == NULL); - g_assert(error != NULL); - error_free(error); - error = NULL; + error_free_or_abort(&error); qobject_unref(src); src = qdict_new(); @@ -695,9 +685,7 @@ static void qdict_crumple_test_bad_inputs(void) qdict_put_str(src, "rule.+1", "allow"); g_assert(qdict_crumple(src, &error) == NULL); - g_assert(error != NULL); - error_free(error); - error = NULL; + error_free_or_abort(&error); qobject_unref(src); } diff --git a/tests/check-block.sh b/tests/check-block.sh index ad320c21baaa550d5c574d5d076772ccb1af59fb..f6b1bda7b97b484291a25576a90922f82acfb88f 100755 --- a/tests/check-block.sh +++ b/tests/check-block.sh @@ -21,7 +21,17 @@ if grep -q "CONFIG_GPROF=y" config-host.mak 2>/dev/null ; then exit 0 fi -if grep -q "CFLAGS.*-fsanitize" config-host.mak 2>/dev/null ; then +# Disable tests with any sanitizer except for SafeStack +CFLAGS=$( grep "CFLAGS.*-fsanitize" config-host.mak 2>/dev/null ) +SANITIZE_FLAGS="" +#Remove all occurrencies of -fsanitize=safe-stack +for i in ${CFLAGS}; do + if [ "${i}" != "-fsanitize=safe-stack" ]; then + SANITIZE_FLAGS="${SANITIZE_FLAGS} ${i}" + fi +done +if echo ${SANITIZE_FLAGS} | grep -q "\-fsanitize" 2>/dev/null; then + # Have a sanitize flag that is not allowed, stop echo "Sanitizers are enabled ==> Not running the qemu-iotests." exit 0 fi @@ -36,6 +46,11 @@ if ! command -v bash >/dev/null 2>&1 ; then exit 0 fi +if LANG=C bash --version | grep -q 'GNU bash, version [123]' ; then + echo "bash version too old ==> Not running the qemu-iotests." + exit 0 +fi + if ! (sed --version | grep 'GNU sed') > /dev/null 2>&1 ; then if ! command -v gsed >/dev/null 2>&1; then echo "GNU sed not available ==> Not running the qemu-iotests." @@ -45,6 +60,9 @@ fi cd tests/qemu-iotests +# QEMU_CHECK_BLOCK_AUTO is used to disable some unstable sub-tests +export QEMU_CHECK_BLOCK_AUTO=1 + ret=0 for fmt in $format_list ; do ./check -makecheck -$fmt $group || ret=1 diff --git a/tests/check-qjson.c b/tests/check-qjson.c index 07a773e6530b561f2ecac7e127ccb8fd690ad740..9a02079099ea2830afc87a6150dfc2dfab2e7115 100644 --- a/tests/check-qjson.c +++ b/tests/check-qjson.c @@ -1415,6 +1415,14 @@ static void invalid_dict_comma(void) g_assert(obj == NULL); } +static void invalid_dict_key(void) +{ + Error *err = NULL; + QObject *obj = qobject_from_json("{32:'abc'}", &err); + error_free_or_abort(&err); + g_assert(obj == NULL); +} + static void unterminated_literal(void) { Error *err = NULL; @@ -1500,6 +1508,7 @@ int main(int argc, char **argv) g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma); g_test_add_func("/errors/invalid_array_comma", invalid_array_comma); g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma); + g_test_add_func("/errors/invalid_dict_key", invalid_dict_key); g_test_add_func("/errors/unterminated/literal", unterminated_literal); g_test_add_func("/errors/limits/nesting", limits_nesting); g_test_add_func("/errors/multiple_values", multiple_values); diff --git a/tests/check-qobject.c b/tests/check-qobject.c index 593c3a0618c4cff5355b27f36b7e41314718344a..6b6deaeb8b33a00bc318fdbe56fdd7f7586b4e12 100644 --- a/tests/check-qobject.c +++ b/tests/check-qobject.c @@ -9,6 +9,7 @@ #include "qemu/osdep.h" #include "block/qdict.h" +#include "qapi/error.h" #include "qapi/qmp/qbool.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qlist.h" @@ -213,7 +214,6 @@ static void qobject_is_equal_list_test(void) static void qobject_is_equal_dict_test(void) { - Error *local_err = NULL; QDict *dict_0, *dict_1, *dict_cloned; QDict *dict_different_key, *dict_different_value, *dict_different_null_key; QDict *dict_longer, *dict_shorter, *dict_nested; @@ -276,8 +276,7 @@ static void qobject_is_equal_dict_test(void) dict_different_null_key, dict_longer, dict_shorter, dict_nested); - dict_crumpled = qobject_to(QDict, qdict_crumple(dict_1, &local_err)); - g_assert(!local_err); + dict_crumpled = qobject_to(QDict, qdict_crumple(dict_1, &error_abort)); check_equal(dict_crumpled, dict_nested); qdict_flatten(dict_nested); diff --git a/tests/check-qom-interface.c b/tests/check-qom-interface.c index 2177f0dce5d2f45ac2e4615a22e28de6b918e7fe..c99be97ed8bc7a1787e68eb2f349cc1643016504 100644 --- a/tests/check-qom-interface.c +++ b/tests/check-qom-interface.c @@ -16,20 +16,19 @@ #define TYPE_TEST_IF "test-interface" -#define TEST_IF_CLASS(klass) \ - OBJECT_CLASS_CHECK(TestIfClass, (klass), TYPE_TEST_IF) -#define TEST_IF_GET_CLASS(obj) \ - OBJECT_GET_CLASS(TestIfClass, (obj), TYPE_TEST_IF) +typedef struct TestIfClass TestIfClass; +DECLARE_CLASS_CHECKERS(TestIfClass, TEST_IF, + TYPE_TEST_IF) #define TEST_IF(obj) \ INTERFACE_CHECK(TestIf, (obj), TYPE_TEST_IF) typedef struct TestIf TestIf; -typedef struct TestIfClass { +struct TestIfClass { InterfaceClass parent_class; uint32_t test; -} TestIfClass; +}; static const TypeInfo test_if_info = { .name = TYPE_TEST_IF, diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c index 13a824cfae0023e12f24dea26755fea72c702303..1b76581980f453a3fd6e22d4b9d8e935d0083a92 100644 --- a/tests/check-qom-proplist.c +++ b/tests/check-qom-proplist.c @@ -33,8 +33,8 @@ typedef struct DummyObject DummyObject; typedef struct DummyObjectClass DummyObjectClass; -#define DUMMY_OBJECT(obj) \ - OBJECT_CHECK(DummyObject, (obj), TYPE_DUMMY) +DECLARE_INSTANCE_CHECKER(DummyObject, DUMMY_OBJECT, + TYPE_DUMMY) typedef enum DummyAnimal DummyAnimal; @@ -196,12 +196,12 @@ typedef struct DummyBackendClass DummyBackendClass; #define TYPE_DUMMY_BUS "qemu-dummy-bus" #define TYPE_DUMMY_BACKEND "qemu-dummy-backend" -#define DUMMY_DEV(obj) \ - OBJECT_CHECK(DummyDev, (obj), TYPE_DUMMY_DEV) -#define DUMMY_BUS(obj) \ - OBJECT_CHECK(DummyBus, (obj), TYPE_DUMMY_BUS) -#define DUMMY_BACKEND(obj) \ - OBJECT_CHECK(DummyBackend, (obj), TYPE_DUMMY_BACKEND) +DECLARE_INSTANCE_CHECKER(DummyDev, DUMMY_DEV, + TYPE_DUMMY_DEV) +DECLARE_INSTANCE_CHECKER(DummyBus, DUMMY_BUS, + TYPE_DUMMY_BUS) +DECLARE_INSTANCE_CHECKER(DummyBackend, DUMMY_BACKEND, + TYPE_DUMMY_BACKEND) struct DummyDev { Object parent_obj; @@ -419,9 +419,7 @@ static void test_dummy_createcmdl(void) g_assert(dobj->bv == true); g_assert(dobj->av == DUMMY_PLATYPUS); - user_creatable_del("dev0", &err); - g_assert(err == NULL); - error_free(err); + user_creatable_del("dev0", &error_abort); object_unref(OBJECT(dobj)); @@ -485,8 +483,7 @@ static void test_dummy_getenum(void) val = object_property_get_enum(OBJECT(dobj), "av", "DummyAnimal", - &err); - g_assert(err == NULL); + &error_abort); g_assert(val == DUMMY_PLATYPUS); /* A bad enum type name */ @@ -494,17 +491,16 @@ static void test_dummy_getenum(void) "av", "BadAnimal", &err); - g_assert(err != NULL); - error_free(err); - err = NULL; + g_assert(val == -1); + error_free_or_abort(&err); /* A non-enum property name */ val = object_property_get_enum(OBJECT(dobj), "iv", "DummyAnimal", &err); - g_assert(err != NULL); - error_free(err); + g_assert(val == -1); + error_free_or_abort(&err); object_unparent(OBJECT(dobj)); } diff --git a/tests/crypto-tls-x509-helpers.c b/tests/crypto-tls-x509-helpers.c index 9b669c2a4bc6473c3016d885751e30bc43e79dbd..01b3daf3585a8bf3028bdb1a0725bf69a2395d04 100644 --- a/tests/crypto-tls-x509-helpers.c +++ b/tests/crypto-tls-x509-helpers.c @@ -37,25 +37,46 @@ ASN1_TYPE pkix_asn1; * here's one we prepared earlier :-) */ gnutls_x509_privkey_t privkey; -# define PRIVATE_KEY \ - "-----BEGIN PRIVATE KEY-----\n" \ - "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALVcr\n" \ - "BL40Tm6yq88FBhJNw1aaoCjmtg0l4dWQZ/e9Fimx4ARxFpT+ji4FE\n" \ - "Cgl9s/SGqC+1nvlkm9ViSo0j7MKDbnDB+VRHDvMAzQhA2X7e8M0n9\n" \ - "rPolUY2lIVC83q0BBaOBkCj2RSmT2xTEbbC2xLukSrg2WP/ihVOxc\n" \ - "kXRuyFtzAgMBAAECgYB7slBexDwXrtItAMIH6m/U+LUpNe0Xx48OL\n" \ - "IOn4a4whNgO/o84uIwygUK27ZGFZT0kAGAk8CdF9hA6ArcbQ62s1H\n" \ - "myxrUbF9/mrLsQw1NEqpuUk9Ay2Tx5U/wPx35S3W/X2AvR/ZpTnCn\n" \ - "2q/7ym9fyiSoj86drD7BTvmKXlOnOwQJBAPOFMp4mMa9NGpGuEssO\n" \ - "m3Uwbp6lhcP0cA9MK+iOmeANpoKWfBdk5O34VbmeXnGYWEkrnX+9J\n" \ - "bM4wVhnnBWtgBMCQQC+qAEmvwcfhauERKYznMVUVksyeuhxhCe7EK\n" \ - "mPh+U2+g0WwdKvGDgO0PPt1gq0ILEjspMDeMHVdTwkaVBo/uMhAkA\n" \ - "Z5SsZyCP2aTOPFDypXRdI4eqRcjaEPOUBq27r3uYb/jeboVb2weLa\n" \ - "L1MmVuHiIHoa5clswPdWVI2y0em2IGoDAkBPSp/v9VKJEZabk9Frd\n" \ - "a+7u4fanrM9QrEjY3KhduslSilXZZSxrWjjAJPyPiqFb3M8XXA26W\n" \ - "nz1KYGnqYKhLcBAkB7dt57n9xfrhDpuyVEv+Uv1D3VVAhZlsaZ5Pp\n" \ - "dcrhrkJn2sa/+O8OKvdrPSeeu/N5WwYhJf61+CPoenMp7IFci\n" \ - "-----END PRIVATE KEY-----\n" +# define PRIVATE_KEY \ + "-----BEGIN RSA PRIVATE KEY-----\n" \ + "MIIG5AIBAAKCAYEAyjWyLSNm5PZvYUKUcDWGqbLX10b2ood+YaFjWSnJrqx/q3qh\n" \ + "rVGBJglD25AJENJsmZF3zPP1oMhfIxsXu63Hdkb6Rdlc2RUoUP34x9VC1izH25mR\n" \ + "6c8DPDp1d6IraZ/llDMI1HsBFz0qGWtvOHgm815XG4PAr/N8rDsuqfv/cJ01KlnO\n" \ + "0OdO5QRXCJf9g/dYd41MPu7wOXk9FqjQlmRoP59HgtJ+zUpE4z+Keruw9cMT9VJj\n" \ + "0oT+pQ9ysenqeZ3gbT224T1khrEhT5kifhtFLNyDssRchUUWH0hiqoOO1vgb+850\n" \ + "W6/1VdxvuPam48py4diSPi1Vip8NITCOBaX9FIpVp4Ruw4rTPVMNMjq9Cpx/DwMP\n" \ + "9MbfXfnaVaZaMrmq67/zPhl0eVbUrecH2hQ3ZB9oIF4GkNskzlWF5+yPy6zqk304\n" \ + "AKaiFR6jRyh3YfHo2XFqV8x/hxdsIEXOtEUGhSIcpynsW+ckUCartzu7xbhXjd4b\n" \ + "kxJT89+riPFYij09AgMBAAECggGBAKyFkaZXXROeejrmHlV6JZGlp+fhgM38gkRz\n" \ + "+Jp7P7rLLAY3E7gXIPQ91WqAAmwazFNdvHPd9USfkCQYmnAi/VoZhrCPmlsQZRxt\n" \ + "A5QjjOnEvSPMa6SrXZxGWDCg6R8uMCb4P+FhrPWR1thnRDZOtRTQ+crc50p3mHgt\n" \ + "6ktXWIJRbqnag8zSfQqCYGtRmhe8sfsWT+Yl4El4+jjaAVU/B364u7+PLmaiphGp\n" \ + "BdJfTsTwEpgtGkPj+osDmhzXcZkfq3V+fz5JLkemsCiQKmn4VJRpg8c3ZmE8NPNt\n" \ + "gRtGWZ4W3WKDvhotT65WpQx4+6R8Duux/blNPBmH1Upmwd7kj7GYFBArbCjgd9PT\n" \ + "xgfCSUZpgOZHHkcgSB+022a8XncXna7WYYij28SLtwImFyu0nNtqECFQHH5u+k6C\n" \ + "LRYBSN+3t3At8dQuk01NVrJBndmjmXRfxpqUtTdeaNgVpdUYRY98s30G68NYGSra\n" \ + "aEvhhRSghkcLNetkobpY9pUgeqW/tQKBwQDZHHK9nDMt/zk1TxtILeUSitPXcv1/\n" \ + "8ufXqO0miHdH23XuXhIEA6Ef26RRVGDGgpjkveDJK/1w5feJ4H/ni4Vclil/cm38\n" \ + "OwRqjjd7ElHJX6JQbsxEx/gNTk5/QW1iAL9TXUalgepsSXYT6AJ0/CJv0jmJSJ36\n" \ + "YoKMOM8uqzb2KhN6i+RlJRi5iY53kUhWTJq5ArWvNhUzQNSYODI4bNxlsKSBL2Ik\n" \ + "LZ5QKHuaEjQet0IlPlfIb4PzMm8CHa/urOcCgcEA7m3zW/lL5bIFoKPjWig5Lbn1\n" \ + "aHfrG2ngqzWtgWtfZqMH8OkZc1Mdhhmvd46titjiLjeI+UP/uHXR0068PnrNngzl\n" \ + "tTgwlakzu+bWzqhBm1F+3/341st/FEk07r0P/3/PhezVjwfO8c8Exj7pLxH4wrH0\n" \ + "ROHgDbClmlJRu6OO78wk1+Vapf5DWa8YfA+q+fdvr7KvgGyytheKMT/b/dsqOq7y\n" \ + "qZPjmaJKWAvV3RWG8lWHFSdHx2IAHMHfGr17Y/w7AoHBALzwZeYebeekiVucGSjq\n" \ + "T8SgLhT7zCIx+JMUPjVfYzaUhP/Iu7Lkma6IzWm9nW6Drpy5pUpMzwUWDCLfzU9q\n" \ + "eseFIl337kEn9wLn+t5OpgAyCqYmlftxbqvdrrBN9uvnrJjWvqk/8wsDrw9JxAGc\n" \ + "fjeD4nBXUqvYWLXApoR9mZoGKedmoH9pFig4zlO9ig8YITnKYuQ0k6SD0b8agJHc\n" \ + "Ir0YSUDnRGgpjvFBGbeOCe+FGbohk/EpItJc3IAh5740lwKBwAdXd2DjokSmYKn7\n" \ + "oeqKxofz6+yVlLW5YuOiuX78sWlVp87xPolgi84vSEnkKM/Xsc8+goc6YstpRVa+\n" \ + "W+mImoA9YW1dF5HkLeWhTAf9AlgoAEIhbeIfTgBv6KNZSv7RDrDPBBxtXx/vAfSg\n" \ + "x0ldwk0scZsVYXLKd67yzfV7KdGUdaX4N/xYgfZm/9gCG3+q8NN2KxVHQ5F71BOE\n" \ + "JeABOaGo9WvnU+DNMIDZjHJMUWVw4MHz/a/UArDf/2CxaPVBNQKBwASg6j4ohSTk\n" \ + "J7aE6RQ3OBmmDDpixcoCJt9u9SjHVYMlbs5CEJGVSczk0SG3y8P1lOWNDSRnMksZ\n" \ + "xWnHdP/ogcuYMuvK7UACNAF0zNddtzOhzcpNmejFj+WCHYY/UmPr2/Kf6t7Cxk2K\n" \ + "3cZ4tqWsiTmBT8Bknmah7L5DrhS+ZBJliDeFAA8fZHdMH0Xjr4UBp9kF90EMTdW1\n" \ + "Xr5uz7ZrMsYpYQI7mmyqV9SSjUg4iBXwVSoag1iDJ1K8Qg/L7Semgg==\n" \ + "-----END RSA PRIVATE KEY-----\n" /* * This loads the private key we defined earlier diff --git a/tests/data/acpi/disassemle-aml.sh b/tests/data/acpi/disassemle-aml.sh new file mode 100755 index 0000000000000000000000000000000000000000..253b7620a074fd029441ce31fa81928851ea49c1 --- /dev/null +++ b/tests/data/acpi/disassemle-aml.sh @@ -0,0 +1,57 @@ +#!/usr/bin/bash + +outdir= +while getopts "o:" arg; do + case ${arg} in + o ) + outdir=$OPTARG + ;; + \? ) + echo "Usage: ./tests/data/acpi/disassemle-aml.sh [-o ]" + exit 1 + ;; + + esac +done + +for machine in tests/data/acpi/* +do + if [[ ! -d "$machine" ]]; + then + continue + fi + + if [[ "${outdir}" ]]; + then + mkdir -p "${outdir}"/${machine} || exit $? + fi + for aml in $machine/* + do + if [[ "$aml" == $machine/*.dsl ]]; + then + continue + fi + if [[ "$aml" == $machine/SSDT*.* ]]; + then + dsdt=${aml/SSDT*./DSDT.} + extra="-e ${dsdt}" + elif [[ "$aml" == $machine/SSDT* ]]; + then + dsdt=${aml/SSDT*/DSDT}; + extra="-e ${dsdt}" + else + extra="" + fi + if [[ "${outdir}" ]]; + then + # iasl strips an extension from prefix if there. + # since we have some files with . in the name, the + # last component gets interpreted as an extension: + # add another extension to work around that. + prefix="-p ${outdir}/${aml}.dsl" + else + prefix="" + fi + iasl ${extra} ${prefix} -d ${aml} + done +done diff --git a/tests/data/acpi/microvm/APIC b/tests/data/acpi/microvm/APIC new file mode 100644 index 0000000000000000000000000000000000000000..7472c7e830b6c7139720e93dd544d4441556661d Binary files /dev/null and b/tests/data/acpi/microvm/APIC differ diff --git a/tests/data/acpi/microvm/APIC.pcie b/tests/data/acpi/microvm/APIC.pcie new file mode 100644 index 0000000000000000000000000000000000000000..6c51081b50beb061c5f4e5baa134585d82db4c39 Binary files /dev/null and b/tests/data/acpi/microvm/APIC.pcie differ diff --git a/tests/data/acpi/microvm/DSDT b/tests/data/acpi/microvm/DSDT new file mode 100644 index 0000000000000000000000000000000000000000..b43f427a222a933d3f34aceab6224a2c6115c365 Binary files /dev/null and b/tests/data/acpi/microvm/DSDT differ diff --git a/tests/data/acpi/microvm/DSDT.pcie b/tests/data/acpi/microvm/DSDT.pcie new file mode 100644 index 0000000000000000000000000000000000000000..4b765541e372f4ba4e25529c14acf696516c8f61 Binary files /dev/null and b/tests/data/acpi/microvm/DSDT.pcie differ diff --git a/tests/data/acpi/microvm/DSDT.rtc b/tests/data/acpi/microvm/DSDT.rtc new file mode 100644 index 0000000000000000000000000000000000000000..5960d6929a2f88d76aaa324b88b80908ff0698dc Binary files /dev/null and b/tests/data/acpi/microvm/DSDT.rtc differ diff --git a/tests/data/acpi/microvm/DSDT.usb b/tests/data/acpi/microvm/DSDT.usb new file mode 100644 index 0000000000000000000000000000000000000000..14423381ea235ed42f6f0f7d98e793c271a4e7c1 Binary files /dev/null and b/tests/data/acpi/microvm/DSDT.usb differ diff --git a/tests/data/acpi/microvm/FACP b/tests/data/acpi/microvm/FACP new file mode 100644 index 0000000000000000000000000000000000000000..0ba5795d622349e1521138e4123544637b4ab9af Binary files /dev/null and b/tests/data/acpi/microvm/FACP differ diff --git a/tests/data/acpi/pc/DSDT b/tests/data/acpi/pc/DSDT index ad4b2d46cc7865e8bafcca2e4e888a03cc5483b5..4ca46e5a2bdb1dfab79dd8630aeeb9a386d8b30e 100644 Binary files a/tests/data/acpi/pc/DSDT and b/tests/data/acpi/pc/DSDT differ diff --git a/tests/data/acpi/pc/DSDT.acpihmat b/tests/data/acpi/pc/DSDT.acpihmat index eff7aadfabe431c3ac2d28e0c6721eb6e322af66..35a74bce8cc152ecb615cb38c4b7f63c7c7d3ab3 100644 Binary files a/tests/data/acpi/pc/DSDT.acpihmat and b/tests/data/acpi/pc/DSDT.acpihmat differ diff --git a/tests/data/acpi/pc/DSDT.bridge b/tests/data/acpi/pc/DSDT.bridge index 92ae808e2e071e367f0b68b3553239bd56b4b766..803d7a8e839ea8b7ac33c4490459ddaede584269 100644 Binary files a/tests/data/acpi/pc/DSDT.bridge and b/tests/data/acpi/pc/DSDT.bridge differ diff --git a/tests/data/acpi/pc/DSDT.cphp b/tests/data/acpi/pc/DSDT.cphp index f3572358510f3fbb3d966047274f7aa7835e7bef..8bab2f506409f2b025a63d8b91c7bfdaa931e626 100644 Binary files a/tests/data/acpi/pc/DSDT.cphp and b/tests/data/acpi/pc/DSDT.cphp differ diff --git a/tests/data/acpi/pc/DSDT.dimmpxm b/tests/data/acpi/pc/DSDT.dimmpxm index 7fa09463c16c2f6b60114591785918b9d96b4f17..e015b4594c96a6e0f34c0668e3383b9a91dff38e 100644 Binary files a/tests/data/acpi/pc/DSDT.dimmpxm and b/tests/data/acpi/pc/DSDT.dimmpxm differ diff --git a/tests/data/acpi/pc/DSDT.hpbridge b/tests/data/acpi/pc/DSDT.hpbridge new file mode 100644 index 0000000000000000000000000000000000000000..56032bcf1ba4e251f16c9028429826090531efdd Binary files /dev/null and b/tests/data/acpi/pc/DSDT.hpbridge differ diff --git a/tests/data/acpi/pc/DSDT.hpbrroot b/tests/data/acpi/pc/DSDT.hpbrroot new file mode 100644 index 0000000000000000000000000000000000000000..36b0a8f2fbf93df47b66107125cd3ce01e017b92 Binary files /dev/null and b/tests/data/acpi/pc/DSDT.hpbrroot differ diff --git a/tests/data/acpi/pc/DSDT.ipmikcs b/tests/data/acpi/pc/DSDT.ipmikcs index 469d13e1f6b873bb9cfa0b3af32d1a3bc58e8f77..ca6630e39f60ebd5c056f57c4c03fdb9d5467577 100644 Binary files a/tests/data/acpi/pc/DSDT.ipmikcs and b/tests/data/acpi/pc/DSDT.ipmikcs differ diff --git a/tests/data/acpi/pc/DSDT.memhp b/tests/data/acpi/pc/DSDT.memhp index aee75bea272cc9983202cceb747aecc297b5104e..43f4e114e2cc48c68c35af47303fa87c9255db40 100644 Binary files a/tests/data/acpi/pc/DSDT.memhp and b/tests/data/acpi/pc/DSDT.memhp differ diff --git a/tests/data/acpi/pc/DSDT.numamem b/tests/data/acpi/pc/DSDT.numamem index 9a747f6f08f61c73b891d8f91db01521e635f811..ba8f7e6c33f9eb0f7a080144fcb4a27d36aa04ae 100644 Binary files a/tests/data/acpi/pc/DSDT.numamem and b/tests/data/acpi/pc/DSDT.numamem differ diff --git a/tests/data/acpi/pc/DSDT.roothp b/tests/data/acpi/pc/DSDT.roothp new file mode 100644 index 0000000000000000000000000000000000000000..18caa0765fc10adb29e01717390ead6c63cd0f3c Binary files /dev/null and b/tests/data/acpi/pc/DSDT.roothp differ diff --git a/tests/data/acpi/pc/SRAT.dimmpxm b/tests/data/acpi/pc/SRAT.dimmpxm index f5c0267ea24bb404b6b4e687390140378fbdc3f1..5a13c61b9041c6045c29643bf93a111fb1c0c76a 100644 Binary files a/tests/data/acpi/pc/SRAT.dimmpxm and b/tests/data/acpi/pc/SRAT.dimmpxm differ diff --git a/tests/data/acpi/q35/DSDT b/tests/data/acpi/q35/DSDT index 9fa4d5a405c2bcd9313b13894917622bf156013e..e7414e78563372fca4d2aab9d16c58c0ff8468f4 100644 Binary files a/tests/data/acpi/q35/DSDT and b/tests/data/acpi/q35/DSDT differ diff --git a/tests/data/acpi/q35/DSDT.acpihmat b/tests/data/acpi/q35/DSDT.acpihmat index 2d834a854ccddc17afd0bc4b4a9e0886feff8e65..88434da261212b15264c892976775acd5c954aea 100644 Binary files a/tests/data/acpi/q35/DSDT.acpihmat and b/tests/data/acpi/q35/DSDT.acpihmat differ diff --git a/tests/data/acpi/q35/DSDT.bridge b/tests/data/acpi/q35/DSDT.bridge index b75122b24a41b8fd58b9e7071032298e0fc2284b..118476ff6101e11d6b1f2d3399241d7fd1a6f634 100644 Binary files a/tests/data/acpi/q35/DSDT.bridge and b/tests/data/acpi/q35/DSDT.bridge differ diff --git a/tests/data/acpi/q35/DSDT.cphp b/tests/data/acpi/q35/DSDT.cphp index c59c19ff46b9bb4fa3e06e9ffbcbeba308a80cd0..69c5edf620529e995461ccba63b76a083f25b2b6 100644 Binary files a/tests/data/acpi/q35/DSDT.cphp and b/tests/data/acpi/q35/DSDT.cphp differ diff --git a/tests/data/acpi/q35/DSDT.dimmpxm b/tests/data/acpi/q35/DSDT.dimmpxm index 9edc104ee6b06dd9d909b65b83c99494d03a137d..af41acba6e0117191ad8495a30ded7b0acc4d2ca 100644 Binary files a/tests/data/acpi/q35/DSDT.dimmpxm and b/tests/data/acpi/q35/DSDT.dimmpxm differ diff --git a/tests/data/acpi/q35/DSDT.ipmibt b/tests/data/acpi/q35/DSDT.ipmibt index 3910e9b767808962b46501da51945229359e3d1d..a650c3041ab9d6688eda843a6a2ab418e1a7ce9b 100644 Binary files a/tests/data/acpi/q35/DSDT.ipmibt and b/tests/data/acpi/q35/DSDT.ipmibt differ diff --git a/tests/data/acpi/q35/DSDT.memhp b/tests/data/acpi/q35/DSDT.memhp index 8461e984c965da916d828884f6629422e83e429c..85598ca3f68f437e8d5048e2cb9815f20b332152 100644 Binary files a/tests/data/acpi/q35/DSDT.memhp and b/tests/data/acpi/q35/DSDT.memhp differ diff --git a/tests/data/acpi/q35/DSDT.mmio64 b/tests/data/acpi/q35/DSDT.mmio64 index fc0cc096baf8aedc0a526978ff796025d7380453..092fdc32628f5a145b510c2a46de8b02222b1951 100644 Binary files a/tests/data/acpi/q35/DSDT.mmio64 and b/tests/data/acpi/q35/DSDT.mmio64 differ diff --git a/tests/data/acpi/q35/DSDT.numamem b/tests/data/acpi/q35/DSDT.numamem index 498c843be1695a0fe1d31d88873b57206d17d758..899946255b9111e077e06c5f78be860e863911b9 100644 Binary files a/tests/data/acpi/q35/DSDT.numamem and b/tests/data/acpi/q35/DSDT.numamem differ diff --git a/tests/data/acpi/q35/DSDT.tis b/tests/data/acpi/q35/DSDT.tis new file mode 100644 index 0000000000000000000000000000000000000000..08802fbd12eae6ad99f03a8db9a0bc7f95e77cb4 Binary files /dev/null and b/tests/data/acpi/q35/DSDT.tis differ diff --git a/tests/data/acpi/q35/SRAT.dimmpxm b/tests/data/acpi/q35/SRAT.dimmpxm index f5c0267ea24bb404b6b4e687390140378fbdc3f1..5a13c61b9041c6045c29643bf93a111fb1c0c76a 100644 Binary files a/tests/data/acpi/q35/SRAT.dimmpxm and b/tests/data/acpi/q35/SRAT.dimmpxm differ diff --git a/tests/data/acpi/q35/TPM2.tis b/tests/data/acpi/q35/TPM2.tis new file mode 100644 index 0000000000000000000000000000000000000000..7878a6e79a6a406d99ca1f5e9a528eb392b8d793 Binary files /dev/null and b/tests/data/acpi/q35/TPM2.tis differ diff --git a/tests/data/acpi/rebuild-expected-aml.sh b/tests/data/acpi/rebuild-expected-aml.sh index 9cbaab1a4d335fb4eaeee6c30fc39bc56fa9b4dd..fc787705446fb19aef46f3964195c778e65614c3 100755 --- a/tests/data/acpi/rebuild-expected-aml.sh +++ b/tests/data/acpi/rebuild-expected-aml.sh @@ -12,7 +12,7 @@ # This work is licensed under the terms of the GNU GPLv2. # See the COPYING.LIB file in the top-level directory. -qemu_bins="x86_64-softmmu/qemu-system-x86_64 aarch64-softmmu/qemu-system-aarch64" +qemu_bins="./qemu-system-x86_64 ./qemu-system-aarch64" if [ ! -e "tests/qtest/bios-tables-test" ]; then echo "Test: bios-tables-test is required! Run make check before this script." @@ -36,6 +36,7 @@ old_allowed_dif=`grep -v -e 'List of comma-separated changed AML files to ignore echo '/* List of comma-separated changed AML files to ignore */' > ${SRC_PATH}/tests/qtest/bios-tables-test-allowed-diff.h echo "The files were rebuilt and can be added to git." +echo "You can use ${SRC_PATH}/tests/data/acpi/disassemle-aml.sh to disassemble them to ASL." if [ -z "$old_allowed_dif" ]; then echo "Note! Please do not commit expected files with source changes" diff --git a/tests/data/acpi/virt/DSDT b/tests/data/acpi/virt/DSDT index d6f5c617881c4247f55d4dcd06581f9693916b2f..bc519abff9cadc1552e4e586b0a3f5f0db498f4a 100644 Binary files a/tests/data/acpi/virt/DSDT and b/tests/data/acpi/virt/DSDT differ diff --git a/tests/data/acpi/virt/DSDT.memhp b/tests/data/acpi/virt/DSDT.memhp index 730e95a46d2cce0af011ffc051d7342beb8f1328..54728e2b4b8b959f3f829386f6a388ef2600e747 100644 Binary files a/tests/data/acpi/virt/DSDT.memhp and b/tests/data/acpi/virt/DSDT.memhp differ diff --git a/tests/data/acpi/virt/DSDT.numamem b/tests/data/acpi/virt/DSDT.numamem index d6f5c617881c4247f55d4dcd06581f9693916b2f..bc519abff9cadc1552e4e586b0a3f5f0db498f4a 100644 Binary files a/tests/data/acpi/virt/DSDT.numamem and b/tests/data/acpi/virt/DSDT.numamem differ diff --git a/tests/data/acpi/virt/SRAT.memhp b/tests/data/acpi/virt/SRAT.memhp index 1b57db2072e7f7e2085c4a427aa31c7383851b71..9a35adb40c6f7cd822e5af37abba8aad033617cb 100644 Binary files a/tests/data/acpi/virt/SRAT.memhp and b/tests/data/acpi/virt/SRAT.memhp differ diff --git a/tests/data/acpi/virt/SSDT.memhp b/tests/data/acpi/virt/SSDT.memhp index db61d6733284c90153e0e2c1d6c2ac25c22b1d84..375d7b6fc85a484f492a26ccd355c205f2c34473 100644 Binary files a/tests/data/acpi/virt/SSDT.memhp and b/tests/data/acpi/virt/SSDT.memhp differ diff --git a/tests/decode/err_pattern_group_nest1.decode b/tests/decode/err_pattern_group_nest1.decode index 92e971c3c55dccebfb4bbc284a8defc429d4a451..7d09891a1c109644e3e08dd74305ba64494c1e24 100644 --- a/tests/decode/err_pattern_group_nest1.decode +++ b/tests/decode/err_pattern_group_nest1.decode @@ -3,11 +3,12 @@ %sub1 0:8 %sub2 8:8 -%sub3 16:8 -%sub4 24:8 -# Groups with no overlap are supposed to fail +# Make sure braces are matched { - top 00000000 00000000 00000000 00000000 - sub4 ........ ........ ........ ........ %sub1 %sub2 %sub3 %sub4 + top 00000000 00000000 00000000 00000000 + [ + sub1 00000000 00000000 00000000 ........ %sub1 + sub2 00000000 00000000 ........ ........ %sub1 %sub2 + } } diff --git a/tests/decode/err_pattern_group_nest2.decode b/tests/decode/err_pattern_group_nest2.decode new file mode 100644 index 0000000000000000000000000000000000000000..c172239e9b6ec5a76ecc1623dc707748bc5e0468 --- /dev/null +++ b/tests/decode/err_pattern_group_nest2.decode @@ -0,0 +1,6 @@ +# This work is licensed under the terms of the GNU LGPL, version 2 or later. +# See the COPYING.LIB file in the top-level directory. + +# Make sure braces are matched +{ + [ diff --git a/tests/decode/err_pattern_group_nest3.decode b/tests/decode/err_pattern_group_nest3.decode new file mode 100644 index 0000000000000000000000000000000000000000..b085d0141034b623e616f98cf4a7e634ef08b823 --- /dev/null +++ b/tests/decode/err_pattern_group_nest3.decode @@ -0,0 +1,14 @@ +# This work is licensed under the terms of the GNU LGPL, version 2 or later. +# See the COPYING.LIB file in the top-level directory. + +%sub1 0:8 +%sub2 8:8 + +# The exclusive group should error for overlap. +{ + top 00000000 00000000 00000000 00000000 + [ + sub1 00000000 00000000 00000000 ........ %sub1 + sub2 00000000 00000000 ........ ........ %sub1 %sub2 + ] +} diff --git a/tests/decode/succ_ident1.decode b/tests/decode/succ_ident1.decode new file mode 100644 index 0000000000000000000000000000000000000000..f15cfbe1470b0e7e6abfe30ccf1e3b08e5f12c82 --- /dev/null +++ b/tests/decode/succ_ident1.decode @@ -0,0 +1,7 @@ +%1f 0:8 +%2f 8:8 +%3f 16:8 + +&3arg a b c +@3arg ........ ........ ........ ........ &3arg a=%1f b=%2f c=%3f +3insn 00000000 ........ ........ ........ @3arg diff --git a/tests/decode/succ_pattern_group_nest2.decode b/tests/decode/succ_pattern_group_nest2.decode new file mode 100644 index 0000000000000000000000000000000000000000..8d5ab4b2d383523c84d514a441927c9dc3c0137a --- /dev/null +++ b/tests/decode/succ_pattern_group_nest2.decode @@ -0,0 +1,13 @@ +# This work is licensed under the terms of the GNU LGPL, version 2 or later. +# See the COPYING.LIB file in the top-level directory. + +%sub1 0:8 +%sub2 8:8 +%sub3 16:8 +%sub4 24:8 + +# Group with complete overlap of the two patterns +{ + top 00000000 00000000 00000000 00000000 + sub4 ........ ........ ........ ........ %sub1 %sub2 %sub3 %sub4 +} diff --git a/tests/decode/succ_pattern_group_nest3.decode b/tests/decode/succ_pattern_group_nest3.decode new file mode 100644 index 0000000000000000000000000000000000000000..156249f090e0ec37ff767af23972dad5ed8292d7 --- /dev/null +++ b/tests/decode/succ_pattern_group_nest3.decode @@ -0,0 +1,11 @@ +# This work is licensed under the terms of the GNU LGPL, version 2 or later. +# See the COPYING.LIB file in the top-level directory. + +{ + [ + sub1 00000000 a:8 b:8 c:8 + sub2 00000001 a:8 b:8 c:8 + sub3 00000010 a:8 b:8 c:8 + ] + sub4 000000 d:2 a:8 b:8 c:8 +} diff --git a/tests/decode/succ_pattern_group_nest4.decode b/tests/decode/succ_pattern_group_nest4.decode new file mode 100644 index 0000000000000000000000000000000000000000..dc54a1d2859a5e7220b5525d152e12363b7d50e1 --- /dev/null +++ b/tests/decode/succ_pattern_group_nest4.decode @@ -0,0 +1,13 @@ +# This work is licensed under the terms of the GNU LGPL, version 2 or later. +# See the COPYING.LIB file in the top-level directory. + +# Verify deeper nesting, and a single element in the groups. +{ + [ + { + [ + sub1 00000000 a:8 b:8 c:8 + ] + } + ] +} diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index 43a867868827994b3d838f0252b62b3f27e75084..02ec92830b839fb8b4eeeeccab9b13998e54df54 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -2,17 +2,22 @@ .PHONY: docker docker-test docker-clean docker-image docker-qemu-src +NULL := +SPACE := $(NULL) # +COMMA := , + HOST_ARCH = $(if $(ARCH),$(ARCH),$(shell uname -m)) DOCKER_SUFFIX := .docker DOCKER_FILES_DIR := $(SRC_PATH)/tests/docker/dockerfiles # we don't run tests on intermediate images (used as base by another image) -DOCKER_PARTIAL_IMAGES := debian9 debian10 +DOCKER_PARTIAL_IMAGES := debian9 debian10 debian11 DOCKER_PARTIAL_IMAGES += debian9-mxe debian-bootstrap DOCKER_IMAGES := $(sort $(notdir $(basename $(wildcard $(DOCKER_FILES_DIR)/*.docker)))) DOCKER_TARGETS := $(patsubst %,docker-image-%,$(DOCKER_IMAGES)) # Use a global constant ccache directory to speed up repetitive builds DOCKER_CCACHE_DIR := $$HOME/.cache/qemu-docker-ccache +DOCKER_REGISTRY := $(if $(REGISTRY),$(REGISTRY),registry.gitlab.com/qemu-project/qemu) DOCKER_TESTS := $(notdir $(shell \ find $(SRC_PATH)/tests/docker/ -name 'test-*' -type f)) @@ -50,13 +55,15 @@ docker-image: ${DOCKER_TARGETS} ifdef SKIP_DOCKER_BUILD docker-image-%: $(DOCKER_FILES_DIR)/%.docker $(call quiet-command, \ - $(DOCKER_SCRIPT) check --quiet qemu:$* $<, \ + $(DOCKER_SCRIPT) check --quiet qemu/$* $<, \ "CHECK", "$*") else docker-image-%: $(DOCKER_FILES_DIR)/%.docker $(call quiet-command,\ - $(DOCKER_SCRIPT) build qemu:$* $< \ - $(if $V,,--quiet) $(if $(NOCACHE),--no-cache) \ + $(DOCKER_SCRIPT) build -t qemu/$* -f $< \ + $(if $V,,--quiet) \ + $(if $(NOCACHE),--no-cache, \ + $(if $(DOCKER_REGISTRY),--registry $(DOCKER_REGISTRY))) \ $(if $(NOUSER),,--add-current-user) \ $(if $(EXTRA_FILES),--extra-files $(EXTRA_FILES))\ $(if $(EXECUTABLE),--include-executable=$(EXECUTABLE)),\ @@ -75,14 +82,14 @@ docker-binfmt-image-debian-%: $(DOCKER_FILES_DIR)/debian-bootstrap.docker DEB_ARCH=$(DEB_ARCH) \ DEB_TYPE=$(DEB_TYPE) \ $(if $(DEB_URL),DEB_URL=$(DEB_URL),) \ - $(DOCKER_SCRIPT) build qemu:debian-$* $< \ + $(DOCKER_SCRIPT) build -t qemu/debian-$* -f $< \ $(if $V,,--quiet) $(if $(NOCACHE),--no-cache) \ $(if $(NOUSER),,--add-current-user) \ $(if $(EXTRA_FILES),--extra-files $(EXTRA_FILES)) \ $(if $(EXECUTABLE),--include-executable=$(EXECUTABLE)), \ "BUILD","binfmt debian-$* (debootstrapped)"), \ $(call quiet-command, \ - $(DOCKER_SCRIPT) check --quiet qemu:debian-$* $< || \ + $(DOCKER_SCRIPT) check --quiet qemu/debian-$* $< || \ { echo "You will need to build $(EXECUTABLE)"; exit 1;},\ "CHECK", "debian-$* exists")) @@ -130,10 +137,13 @@ docker-image-debian-sparc64-cross: docker-image-debian10 docker-image-travis: NOUSER=1 # Specialist build images, sometimes very limited tools -docker-image-tricore-cross: docker-image-debian9 +docker-image-debian-tricore-cross: docker-image-debian10 +docker-image-debian-all-test-cross: docker-image-debian10 +docker-image-debian-arm64-test-cross: docker-image-debian11 # These images may be good enough for building tests but not for test builds DOCKER_PARTIAL_IMAGES += debian-alpha-cross +DOCKER_PARTIAL_IMAGES += debian-arm64-test-cross DOCKER_PARTIAL_IMAGES += debian-hppa-cross DOCKER_PARTIAL_IMAGES += debian-m68k-cross debian-mips64-cross DOCKER_PARTIAL_IMAGES += debian-powerpc-cross debian-ppc64-cross @@ -211,6 +221,7 @@ endif @echo ' Include extra files in image.' @echo ' ENGINE=auto/docker/podman' @echo ' Specify which container engine to run.' + @echo ' REGISTRY=url Cache builds from registry (default:$(DOCKER_REGISTRY))' # This rule if for directly running against an arbitrary docker target. # It is called by the expanded docker targets (e.g. make @@ -232,7 +243,6 @@ docker-run: docker-qemu-src $(DOCKER_SCRIPT) run \ $(if $(NOUSER),,--run-as-current-user) \ --security-opt seccomp=unconfined \ - $(if $V,,--rm) \ $(if $(DEBUG),-ti,) \ $(if $(NETWORK),$(if $(subst $(NETWORK),,1),--net=$(NETWORK)),--net=none) \ -e TARGET_LIST=$(subst $(SPACE),$(COMMA),$(TARGET_LIST)) \ @@ -256,7 +266,7 @@ docker-run: docker-qemu-src docker-run-%: CMD = $(shell echo '$@' | sed -e 's/docker-run-\([^@]*\)@\(.*\)/\1/') docker-run-%: IMAGE = $(shell echo '$@' | sed -e 's/docker-run-\([^@]*\)@\(.*\)/\2/') docker-run-%: - @$(MAKE) docker-run TEST=$(CMD) IMAGE=qemu:$(IMAGE) + @$(MAKE) docker-run TEST=$(CMD) IMAGE=qemu/$(IMAGE) docker-clean: $(call quiet-command, $(DOCKER_SCRIPT) clean) diff --git a/tests/docker/common.rc b/tests/docker/common.rc index 02cd67a8c5e8d385d319d4589fc7d20b37e3dd37..ebc5b97ecf910f41b957f56bd3988217e8676d55 100755 --- a/tests/docker/common.rc +++ b/tests/docker/common.rc @@ -47,7 +47,7 @@ build_qemu() check_qemu() { # default to make check unless the caller specifies - if test -z "$@"; then + if [ $# = 0 ]; then INVOCATION="check" else INVOCATION="$@" diff --git a/tests/docker/docker.py b/tests/docker/docker.py index d8268c11117efd27cc57ea287a16f1b3ec1ff06b..36b786840615b0c501fb638b7f2e08bb91d208c0 100755 --- a/tests/docker/docker.py +++ b/tests/docker/docker.py @@ -24,7 +24,7 @@ import re import signal from tarfile import TarFile, TarInfo -from io import StringIO +from io import StringIO, BytesIO from shutil import copy, rmtree from pwd import getpwuid from datetime import datetime, timedelta @@ -56,15 +56,19 @@ def argparse(s): USE_ENGINE = EngineEnum.AUTO +def _bytes_checksum(bytes): + """Calculate a digest string unique to the text content""" + return hashlib.sha1(bytes).hexdigest() + def _text_checksum(text): """Calculate a digest string unique to the text content""" - return hashlib.sha1(text.encode('utf-8')).hexdigest() + return _bytes_checksum(text.encode('utf-8')) def _read_dockerfile(path): return open(path, 'rt', encoding='utf-8').read() def _file_checksum(filename): - return _text_checksum(_read_dockerfile(filename)) + return _bytes_checksum(open(filename, 'rb').read()) def _guess_engine_command(): @@ -200,7 +204,7 @@ def _dockerfile_preprocess(df): for l in df.splitlines(): if len(l.strip()) == 0 or l.startswith("#"): continue - from_pref = "FROM qemu:" + from_pref = "FROM qemu/" if l.startswith(from_pref): # TODO: Alternatively we could replace this line with "FROM $ID" # where $ID is the image's hex id obtained with @@ -217,6 +221,13 @@ class Docker(object): """ Running Docker commands """ def __init__(self): self._command = _guess_engine_command() + + if "docker" in self._command and "TRAVIS" not in os.environ: + os.environ["DOCKER_BUILDKIT"] = "1" + self._buildkit = True + else: + self._buildkit = False + self._instance = None atexit.register(self._kill_instances) signal.signal(signal.SIGTERM, self._kill_instances) @@ -258,12 +269,13 @@ def _kill_instances(self, *args, **kwargs): return self._do_kill_instances(True) def _output(self, cmd, **kwargs): - if sys.version_info[1] >= 6: + try: return subprocess.check_output(self._command + cmd, stderr=subprocess.STDOUT, encoding='utf-8', **kwargs) - else: + except TypeError: + # 'encoding' argument was added in 3.6+ return subprocess.check_output(self._command + cmd, stderr=subprocess.STDOUT, **kwargs).decode('utf-8') @@ -284,10 +296,29 @@ def get_image_dockerfile_checksum(self, tag): return labels.get("com.qemu.dockerfile-checksum", "") def build_image(self, tag, docker_dir, dockerfile, - quiet=True, user=False, argv=None, extra_files_cksum=[]): + quiet=True, user=False, argv=None, registry=None, + extra_files_cksum=[]): if argv is None: argv = [] + # pre-calculate the docker checksum before any + # substitutions we make for caching + checksum = _text_checksum(_dockerfile_preprocess(dockerfile)) + + if registry is not None: + sources = re.findall("FROM qemu\/(.*)", dockerfile) + # Fetch any cache layers we can, may fail + for s in sources: + pull_args = ["pull", "%s/qemu/%s" % (registry, s)] + if self._do(pull_args, quiet=quiet) != 0: + registry = None + break + # Make substitutions + if registry is not None: + dockerfile = dockerfile.replace("FROM qemu/", + "FROM %s/qemu/" % + (registry)) + tmp_df = tempfile.NamedTemporaryFile(mode="w+t", encoding='utf-8', dir=docker_dir, suffix=".docker") @@ -301,15 +332,25 @@ def build_image(self, tag, docker_dir, dockerfile, (uname, uid, uname)) tmp_df.write("\n") - tmp_df.write("LABEL com.qemu.dockerfile-checksum=%s" % - _text_checksum(_dockerfile_preprocess(dockerfile))) + tmp_df.write("LABEL com.qemu.dockerfile-checksum=%s" % (checksum)) for f, c in extra_files_cksum: tmp_df.write("LABEL com.qemu.%s-checksum=%s" % (f, c)) tmp_df.flush() - self._do_check(["build", "-t", tag, "-f", tmp_df.name] + argv + - [docker_dir], + build_args = ["build", "-t", tag, "-f", tmp_df.name] + if self._buildkit: + build_args += ["--build-arg", "BUILDKIT_INLINE_CACHE=1"] + + if registry is not None: + pull_args = ["pull", "%s/%s" % (registry, tag)] + self._do(pull_args, quiet=quiet) + cache = "%s/%s" % (registry, tag) + build_args += ["--cache-from", cache] + build_args += argv + build_args += [docker_dir] + + self._do_check(build_args, quiet=quiet) def update_image(self, tag, tarball, quiet=True): @@ -336,7 +377,7 @@ def run(self, cmd, keep, quiet, as_user=False): if self._command[0] == "podman": cmd.insert(0, '--userns=keep-id') - ret = self._do_check(["run", "--label", + ret = self._do_check(["run", "--rm", "--label", "com.qemu.instance.uuid=" + label] + cmd, quiet=quiet) if not keep: @@ -391,16 +432,18 @@ def args(self, parser): help="""Specify a binary that will be copied to the container together with all its dependent libraries""") - parser.add_argument("--extra-files", "-f", nargs='*', + parser.add_argument("--extra-files", nargs='*', help="""Specify files that will be copied in the Docker image, fulfilling the ADD directive from the Dockerfile""") parser.add_argument("--add-current-user", "-u", dest="user", action="store_true", help="Add the current user to image's passwd") - parser.add_argument("tag", + parser.add_argument("--registry", "-r", + help="cache from docker registry") + parser.add_argument("-t", dest="tag", help="Image Tag") - parser.add_argument("dockerfile", + parser.add_argument("-f", dest="dockerfile", help="Dockerfile name") def run(self, args, argv): @@ -453,7 +496,8 @@ def run(self, args, argv): for k, v in os.environ.items() if k.lower() in FILTERED_ENV_NAMES] dkr.build_image(tag, docker_dir, dockerfile, - quiet=args.quiet, user=args.user, argv=argv, + quiet=args.quiet, user=args.user, + argv=argv, registry=args.registry, extra_files_cksum=cksum) rmtree(docker_dir) @@ -497,13 +541,14 @@ def run(self, args, argv): # Create a Docker buildfile df = StringIO() - df.write("FROM %s\n" % args.tag) - df.write("ADD . /\n") - df.seek(0) + df.write(u"FROM %s\n" % args.tag) + df.write(u"ADD . /\n") + + df_bytes = BytesIO(bytes(df.getvalue(), "UTF-8")) df_tar = TarInfo(name="Dockerfile") - df_tar.size = len(df.buf) - tmp_tar.addfile(df_tar, fileobj=df) + df_tar.size = df_bytes.getbuffer().nbytes + tmp_tar.addfile(df_tar, fileobj=df_bytes) tmp_tar.close() @@ -571,7 +616,7 @@ def run(self, args, argv): if argv and argv[0] == "--": argv = argv[1:] cwd = os.getcwd() - cmd = ["--rm", "-w", cwd, + cmd = ["-w", cwd, "-v", "%s:%s:rw" % (cwd, cwd)] if args.paths: for p in args.paths: diff --git a/tests/docker/dockerfiles/centos7.docker b/tests/docker/dockerfiles/centos7.docker index 9a2a2e515d7386566d472a6bf82d272c37bbe58a..6f11af1989ee4c7a7c121c2cff9519a9f72fb92e 100644 --- a/tests/docker/dockerfiles/centos7.docker +++ b/tests/docker/dockerfiles/centos7.docker @@ -5,21 +5,21 @@ RUN yum -y update # Please keep this list sorted alphabetically ENV PACKAGES \ - bison \ bzip2 \ bzip2-devel \ ccache \ csnappy-devel \ dbus-daemon \ - flex \ gcc-c++ \ gcc \ gettext \ git \ glib2-devel \ + gnutls-devel \ libaio-devel \ libepoxy-devel \ libfdt-devel \ + libgcrypt-devel \ librdmacm-devel \ libzstd-devel \ lzo-devel \ @@ -27,10 +27,11 @@ ENV PACKAGES \ mesa-libEGL-devel \ mesa-libgbm-devel \ nettle-devel \ + ninja-build \ perl-Test-Harness \ pixman-devel \ python3 \ - SDL-devel \ + SDL2-devel \ spice-glib-devel \ spice-server-devel \ tar \ diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerfiles/centos8.docker index bfa0d33c9c8e0ed2784a5a603b9beaa821ef9f76..54bc6d54cd80f74aeb84f5bb33a7f949be770a33 100644 --- a/tests/docker/dockerfiles/centos8.docker +++ b/tests/docker/dockerfiles/centos8.docker @@ -2,23 +2,25 @@ FROM centos:8.1.1911 RUN dnf -y update ENV PACKAGES \ - SDL-devel \ - bison \ + SDL2-devel \ bzip2 \ bzip2-devel \ dbus-daemon \ - flex \ gcc \ gcc-c++ \ + genisoimage \ gettext \ git \ glib2-devel \ libaio-devel \ libepoxy-devel \ + libgcrypt-devel \ lzo-devel \ make \ mesa-libEGL-devel \ + nmap-ncat \ nettle-devel \ + ninja-build \ perl-Test-Harness \ pixman-devel \ python36 \ @@ -28,5 +30,7 @@ ENV PACKAGES \ tar \ zlib-devel -RUN dnf install -y $PACKAGES +RUN dnf install -y dnf-plugins-core && \ + dnf config-manager --set-enabled PowerTools && \ + dnf install -y $PACKAGES RUN rpm -q $PACKAGES | sort > /packages.txt diff --git a/tests/docker/dockerfiles/debian-all-test-cross.docker b/tests/docker/dockerfiles/debian-all-test-cross.docker new file mode 100644 index 0000000000000000000000000000000000000000..dedcea58b4670de4e3030117923e385198b753e9 --- /dev/null +++ b/tests/docker/dockerfiles/debian-all-test-cross.docker @@ -0,0 +1,53 @@ +# +# Docker all cross-compiler target (tests only) +# +# While the normal cross builds take care to setup proper multiarch +# build environments which can cross build QEMU this just installs the +# basic compilers for as many targets as possible. We shall use this +# to build and run linux-user tests on GitLab +# +FROM qemu/debian10 + +# What we need to build QEMU itself +RUN apt update && \ + DEBIAN_FRONTEND=noninteractive eatmydata \ + apt build-dep -yy qemu + +# Add the foreign architecture we want and install dependencies +RUN DEBIAN_FRONTEND=noninteractive eatmydata \ + apt install -y --no-install-recommends \ + gcc-aarch64-linux-gnu \ + libc6-dev-arm64-cross \ + gcc-alpha-linux-gnu \ + libc6.1-dev-alpha-cross \ + gcc-arm-linux-gnueabihf \ + libc6-dev-armhf-cross \ + gcc-hppa-linux-gnu \ + libc6-dev-hppa-cross \ + gcc-m68k-linux-gnu \ + libc6-dev-m68k-cross \ + gcc-mips-linux-gnu \ + libc6-dev-mips-cross \ + gcc-mips64-linux-gnuabi64 \ + libc6-dev-mips64-cross \ + gcc-mips64el-linux-gnuabi64 \ + libc6-dev-mips64el-cross \ + gcc-mipsel-linux-gnu \ + libc6-dev-mipsel-cross \ + gcc-powerpc-linux-gnu \ + libc6-dev-powerpc-cross \ + gcc-powerpc64-linux-gnu \ + libc6-dev-ppc64-cross \ + gcc-powerpc64le-linux-gnu \ + libc6-dev-ppc64el-cross \ + gcc-riscv64-linux-gnu \ + libc6-dev-riscv64-cross \ + gcc-s390x-linux-gnu \ + libc6-dev-s390x-cross \ + gcc-sh4-linux-gnu \ + libc6-dev-sh4-cross \ + gcc-sparc64-linux-gnu \ + libc6-dev-sparc64-cross + +ENV QEMU_CONFIGURE_OPTS --disable-system --disable-docs --disable-tools +ENV DEF_TARGET_LIST aarch64-linux-user,alpha-linux-user,arm-linux-user,hppa-linux-user,i386-linux-user,m68k-linux-user,mips-linux-user,mips64-linux-user,mips64el-linux-user,mipsel-linux-user,ppc-linux-user,ppc64-linux-user,ppc64le-linux-user,riscv64-linux-user,s390x-linux-user,sh4-linux-user,sparc64-linux-user diff --git a/tests/docker/dockerfiles/debian-alpha-cross.docker b/tests/docker/dockerfiles/debian-alpha-cross.docker index 74bcabfdb12ba7bd30280879cd0126a28912e32f..10fe30df0dd1c964eb9736fdda25e464eaaae4b7 100644 --- a/tests/docker/dockerfiles/debian-alpha-cross.docker +++ b/tests/docker/dockerfiles/debian-alpha-cross.docker @@ -3,7 +3,7 @@ # # This docker target builds on the debian Buster base image. # -FROM qemu:debian10 +FROM qemu/debian10 RUN apt update && \ DEBIAN_FRONTEND=noninteractive eatmydata \ diff --git a/tests/docker/dockerfiles/debian-amd64-cross.docker b/tests/docker/dockerfiles/debian-amd64-cross.docker index 5d890419251931e918f316691efdda1bfb783a37..870109ef6afe3a26385a306cbb0e925f1f83ae31 100644 --- a/tests/docker/dockerfiles/debian-amd64-cross.docker +++ b/tests/docker/dockerfiles/debian-amd64-cross.docker @@ -4,7 +4,7 @@ # This docker target is used on non-x86_64 machines which need the # x86_64 cross compilers installed. # -FROM qemu:debian10 +FROM qemu/debian10 MAINTAINER Alex BennĂ©e # Add the foreign architecture we want and install dependencies diff --git a/tests/docker/dockerfiles/debian-amd64.docker b/tests/docker/dockerfiles/debian-amd64.docker index 957f0bc2e79b5247beea73508eb0cb156930258c..55075d9fce55c0461977136efb5412c79b5542b1 100644 --- a/tests/docker/dockerfiles/debian-amd64.docker +++ b/tests/docker/dockerfiles/debian-amd64.docker @@ -4,7 +4,7 @@ # This docker target builds on the debian Stretch base image. Further # libraries which are not widely available are installed by hand. # -FROM qemu:debian10 +FROM qemu/debian10 MAINTAINER Philippe Mathieu-DaudĂ© RUN apt update && \ @@ -14,13 +14,19 @@ RUN apt update && \ RUN apt update && \ DEBIAN_FRONTEND=noninteractive eatmydata \ apt install -y --no-install-recommends \ + genisoimage \ libbz2-dev \ liblzo2-dev \ libgcrypt20-dev \ librdmacm-dev \ libsasl2-dev \ libsnappy-dev \ - libvte-dev + libvte-dev \ + netcat-openbsd \ + openssh-client \ + python3-numpy \ + python3-opencv \ + python3-venv # virgl RUN apt update && \ diff --git a/tests/docker/dockerfiles/debian-arm64-cross.docker b/tests/docker/dockerfiles/debian-arm64-cross.docker index 09ca0a1ba7972fdb1a665613f1f4aa5a452b403b..166e24df138c08eb18c3308456d5148144ae618a 100644 --- a/tests/docker/dockerfiles/debian-arm64-cross.docker +++ b/tests/docker/dockerfiles/debian-arm64-cross.docker @@ -3,7 +3,7 @@ # # This docker target builds on the debian Buster base image. # -FROM qemu:debian10 +FROM qemu/debian10 # Add the foreign architecture we want and install dependencies RUN dpkg --add-architecture arm64 diff --git a/tests/docker/dockerfiles/debian-arm64-test-cross.docker b/tests/docker/dockerfiles/debian-arm64-test-cross.docker new file mode 100644 index 0000000000000000000000000000000000000000..53a9012beb8a8dcebe416e45b0196933107e18a5 --- /dev/null +++ b/tests/docker/dockerfiles/debian-arm64-test-cross.docker @@ -0,0 +1,13 @@ +# +# Docker arm64 cross-compiler target (tests only) +# +# This docker target builds on the debian Bullseye base image. +# +FROM qemu/debian11 + +# Add the foreign architecture we want and install dependencies +RUN dpkg --add-architecture arm64 +RUN apt update && \ + DEBIAN_FRONTEND=noninteractive eatmydata \ + apt install -y --no-install-recommends \ + crossbuild-essential-arm64 gcc-10-aarch64-linux-gnu diff --git a/tests/docker/dockerfiles/debian-armel-cross.docker b/tests/docker/dockerfiles/debian-armel-cross.docker index e3794a61c9594cb96087f5eb400b01f6bb047282..b7b1a3585f8ddbea79dbd2f65e4d5ee91cffb35c 100644 --- a/tests/docker/dockerfiles/debian-armel-cross.docker +++ b/tests/docker/dockerfiles/debian-armel-cross.docker @@ -3,7 +3,7 @@ # # This docker target builds on the debian Stretch base image. # -FROM qemu:debian10 +FROM qemu/debian10 MAINTAINER Philippe Mathieu-DaudĂ© # Add the foreign architecture we want and install dependencies diff --git a/tests/docker/dockerfiles/debian-armhf-cross.docker b/tests/docker/dockerfiles/debian-armhf-cross.docker index e163b8b956992a4d9408af47c580d7ec5f59f249..25d76188337f77d214ffdfa3dc3d887cbbe2ecb3 100644 --- a/tests/docker/dockerfiles/debian-armhf-cross.docker +++ b/tests/docker/dockerfiles/debian-armhf-cross.docker @@ -3,7 +3,7 @@ # # This docker target builds on the debian Stretch base image. # -FROM qemu:debian10 +FROM qemu/debian10 # Add the foreign architecture we want and install dependencies RUN dpkg --add-architecture armhf diff --git a/tests/docker/dockerfiles/debian-bootstrap.pre b/tests/docker/dockerfiles/debian-bootstrap.pre index c164778c302127b7044dab0921b11cca815b5cfd..35c85f7db8a1bab2e4f7aeeabab42ddde6d179af 100755 --- a/tests/docker/dockerfiles/debian-bootstrap.pre +++ b/tests/docker/dockerfiles/debian-bootstrap.pre @@ -79,6 +79,13 @@ else fi fi +# +# Add optional args +# +if [ -n "${DEB_KEYRING}" ]; then + DEBOOTSTRAP="${DEBOOTSTRAP} --keyring=${DEB_KEYRING}" +fi + # # Finally check to see if any qemu's are installed # diff --git a/tests/docker/dockerfiles/debian-hppa-cross.docker b/tests/docker/dockerfiles/debian-hppa-cross.docker index 5c68b2d3304ad3f16086e507a6099a0e4ad5684b..3d6c65a3efcf96f762f4f69891624ec6a5bcb575 100644 --- a/tests/docker/dockerfiles/debian-hppa-cross.docker +++ b/tests/docker/dockerfiles/debian-hppa-cross.docker @@ -3,7 +3,7 @@ # # This docker target builds on the debian Buster base image. # -FROM qemu:debian10 +FROM qemu/debian10 RUN apt update && \ DEBIAN_FRONTEND=noninteractive eatmydata \ diff --git a/tests/docker/dockerfiles/debian-m68k-cross.docker b/tests/docker/dockerfiles/debian-m68k-cross.docker index 25edc80e9a3d18ea5a17c8b5a4508049afef2c0a..fcb10e353475ce8aacff88f782c57b5eb66850d1 100644 --- a/tests/docker/dockerfiles/debian-m68k-cross.docker +++ b/tests/docker/dockerfiles/debian-m68k-cross.docker @@ -3,7 +3,7 @@ # # This docker target builds on the debian Buster base image. # -FROM qemu:debian10 +FROM qemu/debian10 RUN apt update && \ DEBIAN_FRONTEND=noninteractive eatmydata \ diff --git a/tests/docker/dockerfiles/debian-mips-cross.docker b/tests/docker/dockerfiles/debian-mips-cross.docker index 08a8e1c29ccaec69a2f3b8528fe6f06d2b53bc7b..26c154014db2a60777609d8953a5b9f244f73329 100644 --- a/tests/docker/dockerfiles/debian-mips-cross.docker +++ b/tests/docker/dockerfiles/debian-mips-cross.docker @@ -3,7 +3,7 @@ # # This docker target builds on the debian Buster base image. # -FROM qemu:debian10 +FROM qemu/debian10 MAINTAINER Philippe Mathieu-DaudĂ© diff --git a/tests/docker/dockerfiles/debian-mips64-cross.docker b/tests/docker/dockerfiles/debian-mips64-cross.docker index 1a79505d696aaeadc0efa7650a4fd1df4cd02146..09c2ba584e51506bba0ab4c33e6578273332fe32 100644 --- a/tests/docker/dockerfiles/debian-mips64-cross.docker +++ b/tests/docker/dockerfiles/debian-mips64-cross.docker @@ -3,7 +3,7 @@ # # This docker target builds on the debian Buster base image. # -FROM qemu:debian10 +FROM qemu/debian10 RUN apt update && \ DEBIAN_FRONTEND=noninteractive eatmydata \ diff --git a/tests/docker/dockerfiles/debian-mips64el-cross.docker b/tests/docker/dockerfiles/debian-mips64el-cross.docker index 453b53ef72c8e92fd7f428d7b4430e7ad9b582c7..c990b683b7a1d0f4d7aa17e2e631da7be3df13c6 100644 --- a/tests/docker/dockerfiles/debian-mips64el-cross.docker +++ b/tests/docker/dockerfiles/debian-mips64el-cross.docker @@ -4,7 +4,7 @@ # This docker target builds on the debian Stretch base image. # -FROM qemu:debian10 +FROM qemu/debian10 MAINTAINER Philippe Mathieu-DaudĂ© diff --git a/tests/docker/dockerfiles/debian-mipsel-cross.docker b/tests/docker/dockerfiles/debian-mipsel-cross.docker index 3b6e975c686d6ea906bc5a1103e4fd0580f6d82e..0e5dd42d3c4bfaac30e7474c205be4847a90161f 100644 --- a/tests/docker/dockerfiles/debian-mipsel-cross.docker +++ b/tests/docker/dockerfiles/debian-mipsel-cross.docker @@ -3,7 +3,7 @@ # # This docker target builds on the debian Stretch base image. # -FROM qemu:debian10 +FROM qemu/debian10 MAINTAINER Philippe Mathieu-DaudĂ© diff --git a/tests/docker/dockerfiles/debian-powerpc-cross.docker b/tests/docker/dockerfiles/debian-powerpc-cross.docker index 89dd4fbf87081138245a8cca93e4dd665a34bcd4..07e1789650b77cf18fa60e226cfc23ea3bc88049 100644 --- a/tests/docker/dockerfiles/debian-powerpc-cross.docker +++ b/tests/docker/dockerfiles/debian-powerpc-cross.docker @@ -3,7 +3,7 @@ # # This docker target builds on the debian Buster base image. # -FROM qemu:debian10 +FROM qemu/debian10 RUN apt update && \ DEBIAN_FRONTEND=noninteractive eatmydata \ diff --git a/tests/docker/dockerfiles/debian-ppc64-cross.docker b/tests/docker/dockerfiles/debian-ppc64-cross.docker index 4bf88ab02dd01dd4a71cb116a1ff71561e859dcf..8efe68874ed62bababb0ebc8eb778ec7ed89cc84 100644 --- a/tests/docker/dockerfiles/debian-ppc64-cross.docker +++ b/tests/docker/dockerfiles/debian-ppc64-cross.docker @@ -2,7 +2,7 @@ # Docker ppc64 cross-compiler target # # This docker target builds on the debian Buster base image. -FROM qemu:debian10 +FROM qemu/debian10 RUN apt update && \ DEBIAN_FRONTEND=noninteractive eatmydata \ diff --git a/tests/docker/dockerfiles/debian-ppc64el-cross.docker b/tests/docker/dockerfiles/debian-ppc64el-cross.docker index cd386f01d93c7d24ff64eefcec23231c779a35d0..1146a06be625673a14d23c0f80c388cedb016dee 100644 --- a/tests/docker/dockerfiles/debian-ppc64el-cross.docker +++ b/tests/docker/dockerfiles/debian-ppc64el-cross.docker @@ -3,7 +3,7 @@ # # This docker target builds on the debian Stretch base image. # -FROM qemu:debian10 +FROM qemu/debian10 # Add the foreign architecture we want and install dependencies RUN dpkg --add-architecture ppc64el && \ diff --git a/tests/docker/dockerfiles/debian-riscv64-cross.docker b/tests/docker/dockerfiles/debian-riscv64-cross.docker index 5e2d6ddb60043b27ae3b6f80fc4cfc17255ef71d..2bbff19772a3963c8785d84a0e1d22821c4625fd 100644 --- a/tests/docker/dockerfiles/debian-riscv64-cross.docker +++ b/tests/docker/dockerfiles/debian-riscv64-cross.docker @@ -3,7 +3,7 @@ # # This docker target builds on the debian Buster base image. # -FROM qemu:debian10 +FROM qemu/debian10 RUN apt update && \ DEBIAN_FRONTEND=noninteractive eatmydata \ diff --git a/tests/docker/dockerfiles/debian-s390x-cross.docker b/tests/docker/dockerfiles/debian-s390x-cross.docker index 43fe59836f25505b0ef7aa6be11fcfda99c05313..9f2ab51eb09af4c2a8fbeb29d529b28394178689 100644 --- a/tests/docker/dockerfiles/debian-s390x-cross.docker +++ b/tests/docker/dockerfiles/debian-s390x-cross.docker @@ -3,7 +3,7 @@ # # This docker target builds on the debian Stretch base image. # -FROM qemu:debian10 +FROM qemu/debian10 # Add the s390x architecture RUN dpkg --add-architecture s390x diff --git a/tests/docker/dockerfiles/debian-sh4-cross.docker b/tests/docker/dockerfiles/debian-sh4-cross.docker index 9d7663764e4d44d4620e5aea3ad7ae292d2e4a46..fd3af89575961396792967fbc1c125e110ec3a08 100644 --- a/tests/docker/dockerfiles/debian-sh4-cross.docker +++ b/tests/docker/dockerfiles/debian-sh4-cross.docker @@ -3,7 +3,7 @@ # # This docker target builds on the debian Buster base image. # -FROM qemu:debian10 +FROM qemu/debian10 RUN apt update && \ DEBIAN_FRONTEND=noninteractive eatmydata \ diff --git a/tests/docker/dockerfiles/debian-sparc64-cross.docker b/tests/docker/dockerfiles/debian-sparc64-cross.docker index 31fd34f120b2fdcb591255b7f084800479e0e5f6..f4bb9b561cfa915e14ff549448812f27a5dd3806 100644 --- a/tests/docker/dockerfiles/debian-sparc64-cross.docker +++ b/tests/docker/dockerfiles/debian-sparc64-cross.docker @@ -3,7 +3,7 @@ # # This docker target builds on the debian Buster base image. # -FROM qemu:debian10 +FROM qemu/debian10 RUN apt update && \ DEBIAN_FRONTEND=noninteractive eatmydata \ diff --git a/tests/docker/dockerfiles/debian-tricore-cross.docker b/tests/docker/dockerfiles/debian-tricore-cross.docker index 4a0f7706a39a02b5ff51561c4a96ca70617c0e2d..985925134c674c699bd0f01a5b3dceabbfa17aad 100644 --- a/tests/docker/dockerfiles/debian-tricore-cross.docker +++ b/tests/docker/dockerfiles/debian-tricore-cross.docker @@ -7,7 +7,7 @@ # # SPDX-License-Identifier: GPL-2.0-or-later # -FROM qemu:debian9 +FROM qemu/debian10 MAINTAINER Philippe Mathieu-DaudĂ© diff --git a/tests/docker/dockerfiles/debian-win32-cross.docker b/tests/docker/dockerfiles/debian-win32-cross.docker deleted file mode 100644 index d16d6431bc8b9c0a0701e35cb81f897240461a42..0000000000000000000000000000000000000000 --- a/tests/docker/dockerfiles/debian-win32-cross.docker +++ /dev/null @@ -1,38 +0,0 @@ -# -# Docker mingw32 cross-compiler target -# -# This docker target builds on the debian Stretch MXE base image. -# -FROM qemu:debian9-mxe - -MAINTAINER Philippe Mathieu-DaudĂ© - -ENV TARGET i686 - -ENV PATH $PATH:/usr/lib/mxe/usr/bin:/usr/lib/mxe/usr/$TARGET-w64-mingw32.shared/bin - -ENV PKG_CONFIG_PATH \ - $PKG_CONFIG_PATH:/usr/lib/mxe/usr/$TARGET-w64-mingw32.shared/lib/pkgconfig - -RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt-get install -y --no-install-recommends \ - mxe-$TARGET-w64-mingw32.shared-bzip2 \ - mxe-$TARGET-w64-mingw32.shared-curl \ - mxe-$TARGET-w64-mingw32.shared-glib \ - mxe-$TARGET-w64-mingw32.shared-libgcrypt \ - mxe-$TARGET-w64-mingw32.shared-libusb1 \ - mxe-$TARGET-w64-mingw32.shared-lzo \ - mxe-$TARGET-w64-mingw32.shared-nettle \ - mxe-$TARGET-w64-mingw32.shared-ncurses \ - mxe-$TARGET-w64-mingw32.shared-nsis \ - mxe-$TARGET-w64-mingw32.shared-pixman \ - mxe-$TARGET-w64-mingw32.shared-pkgconf \ - mxe-$TARGET-w64-mingw32.shared-pthreads \ - mxe-$TARGET-w64-mingw32.shared-sdl2 \ - mxe-$TARGET-w64-mingw32.shared-sdl2-mixer \ - mxe-$TARGET-w64-mingw32.shared-sdl2-gfx \ - mxe-$TARGET-w64-mingw32.shared-zlib - -# Specify the cross prefix for this image (see tests/docker/common.rc) -ENV QEMU_CONFIGURE_OPTS --cross-prefix=$TARGET-w64-mingw32.shared- diff --git a/tests/docker/dockerfiles/debian-win64-cross.docker b/tests/docker/dockerfiles/debian-win64-cross.docker deleted file mode 100644 index b0bc960445b7aab42240390afbd634cb3a2afcb9..0000000000000000000000000000000000000000 --- a/tests/docker/dockerfiles/debian-win64-cross.docker +++ /dev/null @@ -1,38 +0,0 @@ -# -# Docker mingw64 cross-compiler target -# -# This docker target builds on the debian Stretch MXE base image. -# -FROM qemu:debian9-mxe - -MAINTAINER Philippe Mathieu-DaudĂ© - -ENV TARGET x86-64 - -ENV PATH $PATH:/usr/lib/mxe/usr/$TARGET-w64-mingw32.shared/bin - -ENV PKG_CONFIG_PATH \ - $PKG_CONFIG_PATH:/usr/lib/mxe/usr/$TARGET-w64-mingw32.shared/lib/pkgconfig - -RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt-get install -y --no-install-recommends \ - mxe-$TARGET-w64-mingw32.shared-bzip2 \ - mxe-$TARGET-w64-mingw32.shared-curl \ - mxe-$TARGET-w64-mingw32.shared-glib \ - mxe-$TARGET-w64-mingw32.shared-libgcrypt \ - mxe-$TARGET-w64-mingw32.shared-libusb1 \ - mxe-$TARGET-w64-mingw32.shared-lzo \ - mxe-$TARGET-w64-mingw32.shared-nettle \ - mxe-$TARGET-w64-mingw32.shared-ncurses \ - mxe-$TARGET-w64-mingw32.shared-nsis \ - mxe-$TARGET-w64-mingw32.shared-pixman \ - mxe-$TARGET-w64-mingw32.shared-pkgconf \ - mxe-$TARGET-w64-mingw32.shared-pthreads \ - mxe-$TARGET-w64-mingw32.shared-sdl2 \ - mxe-$TARGET-w64-mingw32.shared-sdl2-mixer \ - mxe-$TARGET-w64-mingw32.shared-sdl2-gfx \ - mxe-$TARGET-w64-mingw32.shared-zlib - -# Specify the cross prefix for this image (see tests/docker/common.rc) -ENV QEMU_CONFIGURE_OPTS --cross-prefix=x86_64-w64-mingw32.shared- diff --git a/tests/docker/dockerfiles/debian-xtensa-cross.docker b/tests/docker/dockerfiles/debian-xtensa-cross.docker index e6f93f65ee22459683d2c39de8b3b7325d7278ef..ba4148299c5ae8af3776076b3bd2149be95bc0ac 100644 --- a/tests/docker/dockerfiles/debian-xtensa-cross.docker +++ b/tests/docker/dockerfiles/debian-xtensa-cross.docker @@ -11,21 +11,19 @@ RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata && \ DEBIAN_FRONTEND=noninteractive eatmydata \ apt-get install -y --no-install-recommends \ - bison \ build-essential \ ca-certificates \ curl \ - flex \ gettext \ git \ python3-minimal -ENV CPU_LIST csp dc232b dc233c -ENV TOOLCHAIN_RELEASE 2018.02 +ENV CPU_LIST dc232b dc233c de233_fpu dsp3400 +ENV TOOLCHAIN_RELEASE 2020.07 RUN for cpu in $CPU_LIST; do \ curl -#SL http://github.com/foss-xtensa/toolchain/releases/download/$TOOLCHAIN_RELEASE/x86_64-$TOOLCHAIN_RELEASE-xtensa-$cpu-elf.tar.gz \ | tar -xzC /opt; \ done -ENV PATH $PATH:/opt/$TOOLCHAIN_RELEASE/xtensa-dc232b-elf/bin:/opt/$TOOLCHAIN_RELEASE/xtensa-dc233c-elf/bin:/opt/$TOOLCHAIN_RELEASE/xtensa-csp-elf/bin +ENV PATH $PATH:/opt/$TOOLCHAIN_RELEASE/xtensa-dc232b-elf/bin:/opt/$TOOLCHAIN_RELEASE/xtensa-dc233c-elf/bin:/opt/$TOOLCHAIN_RELEASE/xtensa-de233_fpu-elf/bin:/opt/$TOOLCHAIN_RELEASE/xtensa-dsp3400-elf/bin diff --git a/tests/docker/dockerfiles/debian10.docker b/tests/docker/dockerfiles/debian10.docker index 0769700a4165169d576d132fe37158a026bcfeb0..73a3caac9cd21084f17f668c2495b9a76396dad1 100644 --- a/tests/docker/dockerfiles/debian10.docker +++ b/tests/docker/dockerfiles/debian10.docker @@ -18,21 +18,19 @@ RUN apt update && \ DEBIAN_FRONTEND=noninteractive eatmydata \ apt install -y --no-install-recommends \ bc \ - bison \ build-essential \ ca-certificates \ clang \ dbus \ - flex \ gdb-multiarch \ gettext \ git \ libncurses5-dev \ + ninja-build \ pkg-config \ psmisc \ python3 \ python3-sphinx \ - texinfo \ $(apt-get -s build-dep qemu | egrep ^Inst | fgrep '[all]' | cut -d\ -f2) ENV FEATURES docs diff --git a/tests/docker/dockerfiles/debian9.docker b/tests/docker/dockerfiles/debian11.docker similarity index 33% rename from tests/docker/dockerfiles/debian9.docker rename to tests/docker/dockerfiles/debian11.docker index 08cc970feb1d7ec415c41eba52bd67dce9a2dfdc..5adfd62d553c3c35ee872dd1f353a5da482e0009 100644 --- a/tests/docker/dockerfiles/debian9.docker +++ b/tests/docker/dockerfiles/debian11.docker @@ -1,33 +1,18 @@ # # Docker multiarch cross-compiler target # -# This docker target is builds on Debian cross compiler targets to build distro -# with a selection of cross compilers for building test binaries. +# This docker target uses the current development version of Debian as +# a base for cross compilers for building test binaries. We won't +# attempt to build QEMU on it yet given it is still in development. # # On its own you can't build much but the docker-foo-cross targets # build on top of the base debian image. # -FROM debian:stretch-slim +FROM debian:bullseye-slim # Duplicate deb line as deb-src RUN cat /etc/apt/sources.list | sed "s/^deb\ /deb-src /" >> /etc/apt/sources.list # Install common build utilities RUN apt update && \ - DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt install -y --no-install-recommends \ - bc \ - bison \ - build-essential \ - ca-certificates \ - clang \ - flex \ - gdb-multiarch \ - gettext \ - git \ - libncurses5-dev \ - pkg-config \ - psmisc \ - python3 \ - $(apt-get -s build-dep qemu | egrep ^Inst | fgrep '[all]' | cut -d\ -f2) + DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata diff --git a/tests/docker/dockerfiles/debian9-mxe.docker b/tests/docker/dockerfiles/debian9-mxe.docker deleted file mode 100644 index 62ff1cecf2d2e3e6dd6a5731601689fe25e6e417..0000000000000000000000000000000000000000 --- a/tests/docker/dockerfiles/debian9-mxe.docker +++ /dev/null @@ -1,21 +0,0 @@ -# -# Docker mingw cross-compiler target -# -# This docker target builds on the debian Stretch base image. -# -FROM qemu:debian9 - -MAINTAINER Philippe Mathieu-DaudĂ© - -RUN DEBIAN_FRONTEND=noninteractive eatmydata \ - apt install -y --no-install-recommends gnupg dirmngr - -# Add the foreign architecture we want and install dependencies -RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C6BF758A33A3A276 && \ - echo "deb http://pkg.mxe.cc/repos/apt stretch main" > /etc/apt/sources.list.d/mxeapt.list -RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt-get install -y --no-install-recommends \ - $(apt-get -s install -y --no-install-recommends gw32.shared-mingw-w64 | egrep "^Inst mxe-x86-64-unknown-" | cut -d\ -f2) - -ENV PATH $PATH:/usr/lib/mxe/usr/bin/ diff --git a/tests/docker/dockerfiles/fedora-win32-cross.docker b/tests/docker/dockerfiles/fedora-win32-cross.docker new file mode 100644 index 0000000000000000000000000000000000000000..087df598a092c5ba8d1f415f6f054936a522ac33 --- /dev/null +++ b/tests/docker/dockerfiles/fedora-win32-cross.docker @@ -0,0 +1,41 @@ +FROM fedora:32 + +# Please keep this list sorted alphabetically +ENV PACKAGES \ + bc \ + bzip2 \ + diffutils \ + findutils \ + gcc \ + gettext \ + git \ + hostname \ + make \ + 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 \ + perl \ + perl-Test-Harness \ + python3 \ + python3-PyYAML \ + tar \ + which + +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 new file mode 100644 index 0000000000000000000000000000000000000000..d5d2f5f00d61802c65d754589ff900cbddbd3bc3 --- /dev/null +++ b/tests/docker/dockerfiles/fedora-win64-cross.docker @@ -0,0 +1,37 @@ +FROM fedora:32 + +# Please keep this list sorted alphabetically +ENV PACKAGES \ + bc \ + bzip2 \ + diffutils \ + findutils \ + gcc \ + gettext \ + git \ + hostname \ + make \ + meson \ + mingw64-bzip2 \ + mingw64-curl \ + mingw64-glib2 \ + mingw64-gmp \ + mingw64-gtk3 \ + mingw64-libjpeg-turbo \ + mingw64-libpng \ + mingw64-libtasn1 \ + mingw64-pixman \ + mingw64-pkg-config \ + perl \ + perl-Test-Harness \ + python3 \ + python3-PyYAML \ + tar \ + which + +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 179575ecaaa9c413cf0ebfc0d275a0ee316737b4..0b5053f2d090cc6e3fe59b3fe849ee84f952998e 100644 --- a/tests/docker/dockerfiles/fedora.docker +++ b/tests/docker/dockerfiles/fedora.docker @@ -1,9 +1,8 @@ -FROM fedora:30 +FROM fedora:32 # Please keep this list sorted alphabetically ENV PACKAGES \ bc \ - bison \ brlapi-devel \ bzip2 \ bzip2-devel \ @@ -12,10 +11,11 @@ ENV PACKAGES \ cyrus-sasl-devel \ dbus-daemon \ device-mapper-multipath-devel \ + diffutils \ findutils \ - flex \ gcc \ gcc-c++ \ + genisoimage \ gettext \ git \ glib2-devel \ @@ -73,8 +73,10 @@ ENV PACKAGES \ mingw64-pixman \ mingw64-pkg-config \ mingw64-SDL2 \ + nmap-ncat \ ncurses-devel \ nettle-devel \ + ninja-build \ nss-devel \ numactl-devel \ perl \ @@ -82,7 +84,12 @@ ENV PACKAGES \ pixman-devel \ python3 \ python3-PyYAML \ + python3-numpy \ + python3-opencv \ + python3-pillow \ + python3-pip \ python3-sphinx \ + python3-virtualenv \ rdma-core-devel \ SDL2-devel \ snappy-devel \ @@ -91,7 +98,8 @@ ENV PACKAGES \ systemd-devel \ systemtap-sdt-devel \ tar \ - texinfo \ + tesseract \ + tesseract-langpack-eng \ usbredir-devel \ virglrenderer-devel \ vte291-devel \ diff --git a/tests/docker/dockerfiles/travis.docker b/tests/docker/dockerfiles/travis.docker index 591282561bc59241bb71dac370240395cb452127..cd1435a7e98c861c0dcc23ca9204cf6951335816 100644 --- a/tests/docker/dockerfiles/travis.docker +++ b/tests/docker/dockerfiles/travis.docker @@ -9,7 +9,7 @@ ENV LC_ALL en_US.UTF-8 RUN sed -i "s/# deb-src/deb-src/" /etc/apt/sources.list RUN apt-get update RUN apt-get -y build-dep qemu -RUN apt-get -y install device-tree-compiler python3 python3-yaml dh-autoreconf gdb strace lsof net-tools gcovr +RUN apt-get -y install device-tree-compiler python3 python3-yaml dh-autoreconf gdb strace lsof net-tools gcovr ninja-build # Travis tools require PhantomJS / Neo4j / Maven accessible # in their PATH (QEMU build won't access them). ENV PATH /usr/local/phantomjs/bin:/usr/local/phantomjs:/usr/local/neo4j-3.2.7/bin:/usr/local/maven-3.5.2/bin:/usr/local/cmake-3.9.2/bin:/usr/local/clang-5.0.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfiles/ubuntu.docker index eeb3b22bf20f2294ee3495be885f8a4edd83022f..b5ef7a8198aad7930b6d6e519e3eefb3345e2b34 100644 --- a/tests/docker/dockerfiles/ubuntu.docker +++ b/tests/docker/dockerfiles/ubuntu.docker @@ -9,8 +9,8 @@ # system won't pick up that it has changed. # -FROM ubuntu:19.04 -ENV PACKAGES flex bison \ +FROM ubuntu:20.04 +ENV PACKAGES \ ccache \ clang \ dbus \ @@ -60,10 +60,10 @@ ENV PACKAGES flex bison \ libxen-dev \ libzstd-dev \ make \ + ninja-build \ python3-yaml \ python3-sphinx \ sparse \ - texinfo \ xfslibs-dev RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get -y install $PACKAGES diff --git a/tests/docker/dockerfiles/ubuntu1804.docker b/tests/docker/dockerfiles/ubuntu1804.docker index f66b06f4cffaf6b2c34f5147aee161c484c08b34..9b0a19ba5eeb5bc3412cee68721b79667838eb69 100644 --- a/tests/docker/dockerfiles/ubuntu1804.docker +++ b/tests/docker/dockerfiles/ubuntu1804.docker @@ -1,5 +1,5 @@ FROM ubuntu:18.04 -ENV PACKAGES flex bison \ +ENV PACKAGES \ ccache \ clang \ gcc \ @@ -48,8 +48,8 @@ ENV PACKAGES flex bison \ make \ python3-yaml \ python3-sphinx \ + ninja-build \ sparse \ - texinfo \ xfslibs-dev RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get -y install $PACKAGES diff --git a/tests/docker/dockerfiles/ubuntu2004.docker b/tests/docker/dockerfiles/ubuntu2004.docker new file mode 100644 index 0000000000000000000000000000000000000000..ae889d8482c59044ffcc692e186ab42c27ef3934 --- /dev/null +++ b/tests/docker/dockerfiles/ubuntu2004.docker @@ -0,0 +1,73 @@ +FROM ubuntu:20.04 +ENV PACKAGES flex bison \ + ccache \ + clang-10\ + gcc \ + genisoimage \ + 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 \ + liblttng-ust-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 \ + libspice-server-dev \ + libssh-dev \ + libusb-1.0-0-dev \ + libusbredirhost-dev \ + libvdeplug-dev \ + libvte-2.91-dev \ + libxen-dev \ + libzstd-dev \ + make \ + netcat-openbsd \ + ninja-build \ + python3-numpy \ + python3-opencv \ + python3-pil \ + python3-pip \ + python3-sphinx \ + python3-venv \ + python3-yaml \ + rpm2cpio \ + sparse \ + tesseract-ocr \ + tesseract-ocr-eng \ + xfslibs-dev\ + vim +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. +RUN sed -i 's/^const/static const/g' /usr/lib/llvm-10/lib/clang/10.0.0/include/sanitizer/tsan_interface.h diff --git a/tests/docker/test-static b/tests/docker/test-static new file mode 100755 index 0000000000000000000000000000000000000000..372ef6fac7a1b397a76f4c42169b7943fa6ce8de --- /dev/null +++ b/tests/docker/test-static @@ -0,0 +1,24 @@ +#!/bin/bash -e +# +# Compile QEMU user mode emulators as static binaries on Linux. +# +# Copyright (c) 2020 Red Hat Inc. +# +# Authors: +# Paolo Bonzini +# +# This work is licensed under the terms of the GNU GPL, version 2 +# or (at your option) any later version. See the COPYING file in +# the top-level directory. + +. common.rc + +cd "$BUILD_DIR" + +build_qemu \ + --disable-system \ + --disable-tools \ + --disable-guest-agent \ + --disable-docs \ + --static +install_qemu diff --git a/tests/docker/test-tsan b/tests/docker/test-tsan new file mode 100755 index 0000000000000000000000000000000000000000..eb40ac45b7a44da2656ea506867d9e60892ff8a3 --- /dev/null +++ b/tests/docker/test-tsan @@ -0,0 +1,44 @@ +#!/bin/bash -e +# +# This test will use TSan as part of a build and a make check. +# +# Copyright (c) 2020 Linaro +# Copyright (c) 2016 Red Hat Inc. +# +# Authors: +# Robert Foley +# Originally based on test-quick from Fam Zheng +# +# This work is licensed under the terms of the GNU GPL, version 2 +# or (at your option) any later version. See the COPYING file in +# the top-level directory. + +. common.rc + +setup_tsan() +{ + requires clang tsan + tsan_log_dir="/tmp/qemu-test/build/tsan" + mkdir -p $tsan_log_dir > /dev/null || true + EXTRA_CONFIGURE_OPTS="${EXTRA_CONFIGURE_OPTS} --enable-tsan \ + --cc=clang-10 --cxx=clang++-10 \ + --disable-werror --extra-cflags=-O0" + # detect deadlocks is false currently simply because + # TSan crashes immediately with deadlock detector enabled. + # We have maxed out the history size to get the best chance of finding + # warnings during testing. + # Note, to get TSan to fail on warning, use exitcode=66 below. + tsan_opts="suppressions=/tmp/qemu-test/src/tests/tsan/suppressions.tsan\ + detect_deadlocks=false history_size=7\ + halt_on_error=0 exitcode=0 verbose=5\ + log_path=$tsan_log_dir/tsan_warning" + export TSAN_OPTIONS="$tsan_opts" +} + +cd "$BUILD_DIR" + +TARGET_LIST=${TARGET_LIST:-$DEF_TARGET_LIST} \ +setup_tsan +build_qemu +check_qemu +install_qemu diff --git a/tests/fp/.gitignore b/tests/fp/.gitignore deleted file mode 100644 index 704fd429929129eb85e0f64311e3b31d933697ae..0000000000000000000000000000000000000000 --- a/tests/fp/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -fp-test -fp-bench diff --git a/tests/fp/Makefile b/tests/fp/Makefile deleted file mode 100644 index 56768ecfd2ffbb03598a0104b2f5ad3a04d2b55b..0000000000000000000000000000000000000000 --- a/tests/fp/Makefile +++ /dev/null @@ -1,600 +0,0 @@ -BUILD_DIR := $(CURDIR)/../.. - -include $(BUILD_DIR)/config-host.mak -include $(SRC_PATH)/rules.mak - -SOFTFLOAT_DIR := $(SRC_PATH)/tests/fp/berkeley-softfloat-3 -TESTFLOAT_DIR := $(SRC_PATH)/tests/fp/berkeley-testfloat-3 - -SF_SOURCE_DIR := $(SOFTFLOAT_DIR)/source -SF_INCLUDE_DIR := $(SOFTFLOAT_DIR)/source/include -# we could use any specialize here, it doesn't matter -SF_SPECIALIZE := 8086-SSE -SF_SPECIALIZE_DIR := $(SF_SOURCE_DIR)/$(SF_SPECIALIZE) - -TF_SOURCE_DIR := $(TESTFLOAT_DIR)/source - -$(call set-vpath, $(SRC_PATH)/fpu $(SRC_PATH)/tests/fp) - -LIBQEMUUTIL := $(BUILD_DIR)/libqemuutil.a - -# Use this variable to be clear when we pull in our own implementation -# We build the object with a default rule thanks to the vpath above -QEMU_SOFTFLOAT_OBJ := softfloat.o - -QEMU_INCLUDES += -I$(SRC_PATH)/tests/fp -QEMU_INCLUDES += -I$(SF_INCLUDE_DIR) -QEMU_INCLUDES += -I$(SF_SPECIALIZE_DIR) -QEMU_INCLUDES += -I$(TF_SOURCE_DIR) - -# work around TARGET_* poisoning -QEMU_CFLAGS += -DHW_POISON_H -# define a target to match testfloat's implementation-defined choices, such as -# whether to raise the invalid flag when dealing with NaNs in muladd. -QEMU_CFLAGS += -DTARGET_ARM - -# capstone has a platform.h file that clashes with softfloat's -QEMU_CFLAGS := $(filter-out %capstone, $(QEMU_CFLAGS)) - -# softfloat defines -SF_OPTS := -SF_OPTS += -DSOFTFLOAT_ROUND_ODD -SF_OPTS += -DINLINE_LEVEL=5 -SF_OPTS += -DSOFTFLOAT_FAST_DIV32TO16 -SF_OPTS += -DSOFTFLOAT_FAST_DIV64TO32 -SF_OPTS += -DSOFTFLOAT_FAST_INT64 -QEMU_CFLAGS += $(SF_OPTS) - -# silence the build of softfloat objects -SF_CFLAGS += -Wno-missing-prototypes -SF_CFLAGS += -Wno-redundant-decls -SF_CFLAGS += -Wno-return-type -SF_CFLAGS += -Wno-error - -# testfloat defines -TF_OPTS := -TF_OPTS += -DFLOAT16 -TF_OPTS += -DFLOAT64 -TF_OPTS += -DEXTFLOAT80 -TF_OPTS += -DFLOAT128 -TF_OPTS += -DFLOAT_ROUND_ODD -TF_OPTS += -DLONG_DOUBLE_IS_EXTFLOAT80 -QEMU_CFLAGS += $(TF_OPTS) - -# silence the build of testfloat objects -TF_CFLAGS := -TF_CFLAGS += -Wno-strict-prototypes -TF_CFLAGS += -Wno-unknown-pragmas -TF_CFLAGS += -Wno-uninitialized -TF_CFLAGS += -Wno-missing-prototypes -TF_CFLAGS += -Wno-return-type -TF_CFLAGS += -Wno-unused-function -TF_CFLAGS += -Wno-error - -# softfloat objects -SF_OBJS_PRIMITIVES := -SF_OBJS_PRIMITIVES += s_eq128.o -SF_OBJS_PRIMITIVES += s_le128.o -SF_OBJS_PRIMITIVES += s_lt128.o -SF_OBJS_PRIMITIVES += s_shortShiftLeft128.o -SF_OBJS_PRIMITIVES += s_shortShiftRight128.o -SF_OBJS_PRIMITIVES += s_shortShiftRightJam64.o -SF_OBJS_PRIMITIVES += s_shortShiftRightJam64Extra.o -SF_OBJS_PRIMITIVES += s_shortShiftRightJam128.o -SF_OBJS_PRIMITIVES += s_shortShiftRightJam128Extra.o -SF_OBJS_PRIMITIVES += s_shiftRightJam32.o -SF_OBJS_PRIMITIVES += s_shiftRightJam64.o -SF_OBJS_PRIMITIVES += s_shiftRightJam64Extra.o -SF_OBJS_PRIMITIVES += s_shiftRightJam128.o -SF_OBJS_PRIMITIVES += s_shiftRightJam128Extra.o -SF_OBJS_PRIMITIVES += s_shiftRightJam256M.o -SF_OBJS_PRIMITIVES += s_countLeadingZeros8.o -SF_OBJS_PRIMITIVES += s_countLeadingZeros16.o -SF_OBJS_PRIMITIVES += s_countLeadingZeros32.o -SF_OBJS_PRIMITIVES += s_countLeadingZeros64.o -SF_OBJS_PRIMITIVES += s_add128.o -SF_OBJS_PRIMITIVES += s_add256M.o -SF_OBJS_PRIMITIVES += s_sub128.o -SF_OBJS_PRIMITIVES += s_sub256M.o -SF_OBJS_PRIMITIVES += s_mul64ByShifted32To128.o -SF_OBJS_PRIMITIVES += s_mul64To128.o -SF_OBJS_PRIMITIVES += s_mul128By32.o -SF_OBJS_PRIMITIVES += s_mul128To256M.o -SF_OBJS_PRIMITIVES += s_approxRecip_1Ks.o -SF_OBJS_PRIMITIVES += s_approxRecip32_1.o -SF_OBJS_PRIMITIVES += s_approxRecipSqrt_1Ks.o -SF_OBJS_PRIMITIVES += s_approxRecipSqrt32_1.o - -SF_OBJS_SPECIALIZE := -SF_OBJS_SPECIALIZE += softfloat_raiseFlags.o -SF_OBJS_SPECIALIZE += s_f16UIToCommonNaN.o -SF_OBJS_SPECIALIZE += s_commonNaNToF16UI.o -SF_OBJS_SPECIALIZE += s_propagateNaNF16UI.o -SF_OBJS_SPECIALIZE += s_f32UIToCommonNaN.o -SF_OBJS_SPECIALIZE += s_commonNaNToF32UI.o -SF_OBJS_SPECIALIZE += s_propagateNaNF32UI.o -SF_OBJS_SPECIALIZE += s_f64UIToCommonNaN.o -SF_OBJS_SPECIALIZE += s_commonNaNToF64UI.o -SF_OBJS_SPECIALIZE += s_propagateNaNF64UI.o -SF_OBJS_SPECIALIZE += extF80M_isSignalingNaN.o -SF_OBJS_SPECIALIZE += s_extF80UIToCommonNaN.o -SF_OBJS_SPECIALIZE += s_commonNaNToExtF80UI.o -SF_OBJS_SPECIALIZE += s_propagateNaNExtF80UI.o -SF_OBJS_SPECIALIZE += f128M_isSignalingNaN.o -SF_OBJS_SPECIALIZE += s_f128UIToCommonNaN.o -SF_OBJS_SPECIALIZE += s_commonNaNToF128UI.o -SF_OBJS_SPECIALIZE += s_propagateNaNF128UI.o - -SF_OBJS_OTHERS := -SF_OBJS_OTHERS += s_roundToUI32.o -SF_OBJS_OTHERS += s_roundToUI64.o -SF_OBJS_OTHERS += s_roundToI32.o -SF_OBJS_OTHERS += s_roundToI64.o -SF_OBJS_OTHERS += s_normSubnormalF16Sig.o -SF_OBJS_OTHERS += s_roundPackToF16.o -SF_OBJS_OTHERS += s_normRoundPackToF16.o -SF_OBJS_OTHERS += s_addMagsF16.o -SF_OBJS_OTHERS += s_subMagsF16.o -SF_OBJS_OTHERS += s_mulAddF16.o -SF_OBJS_OTHERS += s_normSubnormalF32Sig.o -SF_OBJS_OTHERS += s_roundPackToF32.o -SF_OBJS_OTHERS += s_normRoundPackToF32.o -SF_OBJS_OTHERS += s_addMagsF32.o -SF_OBJS_OTHERS += s_subMagsF32.o -SF_OBJS_OTHERS += s_mulAddF32.o -SF_OBJS_OTHERS += s_normSubnormalF64Sig.o -SF_OBJS_OTHERS += s_roundPackToF64.o -SF_OBJS_OTHERS += s_normRoundPackToF64.o -SF_OBJS_OTHERS += s_addMagsF64.o -SF_OBJS_OTHERS += s_subMagsF64.o -SF_OBJS_OTHERS += s_mulAddF64.o -SF_OBJS_OTHERS += s_normSubnormalExtF80Sig.o -SF_OBJS_OTHERS += s_roundPackToExtF80.o -SF_OBJS_OTHERS += s_normRoundPackToExtF80.o -SF_OBJS_OTHERS += s_addMagsExtF80.o -SF_OBJS_OTHERS += s_subMagsExtF80.o -SF_OBJS_OTHERS += s_normSubnormalF128Sig.o -SF_OBJS_OTHERS += s_roundPackToF128.o -SF_OBJS_OTHERS += s_normRoundPackToF128.o -SF_OBJS_OTHERS += s_addMagsF128.o -SF_OBJS_OTHERS += s_subMagsF128.o -SF_OBJS_OTHERS += s_mulAddF128.o -SF_OBJS_OTHERS += softfloat_state.o -SF_OBJS_OTHERS += ui32_to_f16.o -SF_OBJS_OTHERS += ui32_to_f32.o -SF_OBJS_OTHERS += ui32_to_f64.o -SF_OBJS_OTHERS += ui32_to_extF80.o -SF_OBJS_OTHERS += ui32_to_extF80M.o -SF_OBJS_OTHERS += ui32_to_f128.o -SF_OBJS_OTHERS += ui32_to_f128M.o -SF_OBJS_OTHERS += ui64_to_f16.o -SF_OBJS_OTHERS += ui64_to_f32.o -SF_OBJS_OTHERS += ui64_to_f64.o -SF_OBJS_OTHERS += ui64_to_extF80.o -SF_OBJS_OTHERS += ui64_to_extF80M.o -SF_OBJS_OTHERS += ui64_to_f128.o -SF_OBJS_OTHERS += ui64_to_f128M.o -SF_OBJS_OTHERS += i32_to_f16.o -SF_OBJS_OTHERS += i32_to_f32.o -SF_OBJS_OTHERS += i32_to_f64.o -SF_OBJS_OTHERS += i32_to_extF80.o -SF_OBJS_OTHERS += i32_to_extF80M.o -SF_OBJS_OTHERS += i32_to_f128.o -SF_OBJS_OTHERS += i32_to_f128M.o -SF_OBJS_OTHERS += i64_to_f16.o -SF_OBJS_OTHERS += i64_to_f32.o -SF_OBJS_OTHERS += i64_to_f64.o -SF_OBJS_OTHERS += i64_to_extF80.o -SF_OBJS_OTHERS += i64_to_extF80M.o -SF_OBJS_OTHERS += i64_to_f128.o -SF_OBJS_OTHERS += i64_to_f128M.o -SF_OBJS_OTHERS += f16_to_ui32.o -SF_OBJS_OTHERS += f16_to_ui64.o -SF_OBJS_OTHERS += f16_to_i32.o -SF_OBJS_OTHERS += f16_to_i64.o -SF_OBJS_OTHERS += f16_to_ui32_r_minMag.o -SF_OBJS_OTHERS += f16_to_ui64_r_minMag.o -SF_OBJS_OTHERS += f16_to_i32_r_minMag.o -SF_OBJS_OTHERS += f16_to_i64_r_minMag.o -SF_OBJS_OTHERS += f16_to_f32.o -SF_OBJS_OTHERS += f16_to_f64.o -SF_OBJS_OTHERS += f16_to_extF80.o -SF_OBJS_OTHERS += f16_to_extF80M.o -SF_OBJS_OTHERS += f16_to_f128.o -SF_OBJS_OTHERS += f16_to_f128M.o -SF_OBJS_OTHERS += f16_roundToInt.o -SF_OBJS_OTHERS += f16_add.o -SF_OBJS_OTHERS += f16_sub.o -SF_OBJS_OTHERS += f16_mul.o -SF_OBJS_OTHERS += f16_mulAdd.o -SF_OBJS_OTHERS += f16_div.o -SF_OBJS_OTHERS += f16_rem.o -SF_OBJS_OTHERS += f16_sqrt.o -SF_OBJS_OTHERS += f16_eq.o -SF_OBJS_OTHERS += f16_le.o -SF_OBJS_OTHERS += f16_lt.o -SF_OBJS_OTHERS += f16_eq_signaling.o -SF_OBJS_OTHERS += f16_le_quiet.o -SF_OBJS_OTHERS += f16_lt_quiet.o -SF_OBJS_OTHERS += f16_isSignalingNaN.o -SF_OBJS_OTHERS += f32_to_ui32.o -SF_OBJS_OTHERS += f32_to_ui64.o -SF_OBJS_OTHERS += f32_to_i32.o -SF_OBJS_OTHERS += f32_to_i64.o -SF_OBJS_OTHERS += f32_to_ui32_r_minMag.o -SF_OBJS_OTHERS += f32_to_ui64_r_minMag.o -SF_OBJS_OTHERS += f32_to_i32_r_minMag.o -SF_OBJS_OTHERS += f32_to_i64_r_minMag.o -SF_OBJS_OTHERS += f32_to_f16.o -SF_OBJS_OTHERS += f32_to_f64.o -SF_OBJS_OTHERS += f32_to_extF80.o -SF_OBJS_OTHERS += f32_to_extF80M.o -SF_OBJS_OTHERS += f32_to_f128.o -SF_OBJS_OTHERS += f32_to_f128M.o -SF_OBJS_OTHERS += f32_roundToInt.o -SF_OBJS_OTHERS += f32_add.o -SF_OBJS_OTHERS += f32_sub.o -SF_OBJS_OTHERS += f32_mul.o -SF_OBJS_OTHERS += f32_mulAdd.o -SF_OBJS_OTHERS += f32_div.o -SF_OBJS_OTHERS += f32_rem.o -SF_OBJS_OTHERS += f32_sqrt.o -SF_OBJS_OTHERS += f32_eq.o -SF_OBJS_OTHERS += f32_le.o -SF_OBJS_OTHERS += f32_lt.o -SF_OBJS_OTHERS += f32_eq_signaling.o -SF_OBJS_OTHERS += f32_le_quiet.o -SF_OBJS_OTHERS += f32_lt_quiet.o -SF_OBJS_OTHERS += f32_isSignalingNaN.o -SF_OBJS_OTHERS += f64_to_ui32.o -SF_OBJS_OTHERS += f64_to_ui64.o -SF_OBJS_OTHERS += f64_to_i32.o -SF_OBJS_OTHERS += f64_to_i64.o -SF_OBJS_OTHERS += f64_to_ui32_r_minMag.o -SF_OBJS_OTHERS += f64_to_ui64_r_minMag.o -SF_OBJS_OTHERS += f64_to_i32_r_minMag.o -SF_OBJS_OTHERS += f64_to_i64_r_minMag.o -SF_OBJS_OTHERS += f64_to_f16.o -SF_OBJS_OTHERS += f64_to_f32.o -SF_OBJS_OTHERS += f64_to_extF80.o -SF_OBJS_OTHERS += f64_to_extF80M.o -SF_OBJS_OTHERS += f64_to_f128.o -SF_OBJS_OTHERS += f64_to_f128M.o -SF_OBJS_OTHERS += f64_roundToInt.o -SF_OBJS_OTHERS += f64_add.o -SF_OBJS_OTHERS += f64_sub.o -SF_OBJS_OTHERS += f64_mul.o -SF_OBJS_OTHERS += f64_mulAdd.o -SF_OBJS_OTHERS += f64_div.o -SF_OBJS_OTHERS += f64_rem.o -SF_OBJS_OTHERS += f64_sqrt.o -SF_OBJS_OTHERS += f64_eq.o -SF_OBJS_OTHERS += f64_le.o -SF_OBJS_OTHERS += f64_lt.o -SF_OBJS_OTHERS += f64_eq_signaling.o -SF_OBJS_OTHERS += f64_le_quiet.o -SF_OBJS_OTHERS += f64_lt_quiet.o -SF_OBJS_OTHERS += f64_isSignalingNaN.o -SF_OBJS_OTHERS += extF80_to_ui32.o -SF_OBJS_OTHERS += extF80_to_ui64.o -SF_OBJS_OTHERS += extF80_to_i32.o -SF_OBJS_OTHERS += extF80_to_i64.o -SF_OBJS_OTHERS += extF80_to_ui32_r_minMag.o -SF_OBJS_OTHERS += extF80_to_ui64_r_minMag.o -SF_OBJS_OTHERS += extF80_to_i32_r_minMag.o -SF_OBJS_OTHERS += extF80_to_i64_r_minMag.o -SF_OBJS_OTHERS += extF80_to_f16.o -SF_OBJS_OTHERS += extF80_to_f32.o -SF_OBJS_OTHERS += extF80_to_f64.o -SF_OBJS_OTHERS += extF80_to_f128.o -SF_OBJS_OTHERS += extF80_roundToInt.o -SF_OBJS_OTHERS += extF80_add.o -SF_OBJS_OTHERS += extF80_sub.o -SF_OBJS_OTHERS += extF80_mul.o -SF_OBJS_OTHERS += extF80_div.o -SF_OBJS_OTHERS += extF80_rem.o -SF_OBJS_OTHERS += extF80_sqrt.o -SF_OBJS_OTHERS += extF80_eq.o -SF_OBJS_OTHERS += extF80_le.o -SF_OBJS_OTHERS += extF80_lt.o -SF_OBJS_OTHERS += extF80_eq_signaling.o -SF_OBJS_OTHERS += extF80_le_quiet.o -SF_OBJS_OTHERS += extF80_lt_quiet.o -SF_OBJS_OTHERS += extF80_isSignalingNaN.o -SF_OBJS_OTHERS += extF80M_to_ui32.o -SF_OBJS_OTHERS += extF80M_to_ui64.o -SF_OBJS_OTHERS += extF80M_to_i32.o -SF_OBJS_OTHERS += extF80M_to_i64.o -SF_OBJS_OTHERS += extF80M_to_ui32_r_minMag.o -SF_OBJS_OTHERS += extF80M_to_ui64_r_minMag.o -SF_OBJS_OTHERS += extF80M_to_i32_r_minMag.o -SF_OBJS_OTHERS += extF80M_to_i64_r_minMag.o -SF_OBJS_OTHERS += extF80M_to_f16.o -SF_OBJS_OTHERS += extF80M_to_f32.o -SF_OBJS_OTHERS += extF80M_to_f64.o -SF_OBJS_OTHERS += extF80M_to_f128M.o -SF_OBJS_OTHERS += extF80M_roundToInt.o -SF_OBJS_OTHERS += extF80M_add.o -SF_OBJS_OTHERS += extF80M_sub.o -SF_OBJS_OTHERS += extF80M_mul.o -SF_OBJS_OTHERS += extF80M_div.o -SF_OBJS_OTHERS += extF80M_rem.o -SF_OBJS_OTHERS += extF80M_sqrt.o -SF_OBJS_OTHERS += extF80M_eq.o -SF_OBJS_OTHERS += extF80M_le.o -SF_OBJS_OTHERS += extF80M_lt.o -SF_OBJS_OTHERS += extF80M_eq_signaling.o -SF_OBJS_OTHERS += extF80M_le_quiet.o -SF_OBJS_OTHERS += extF80M_lt_quiet.o -SF_OBJS_OTHERS += f128_to_ui32.o -SF_OBJS_OTHERS += f128_to_ui64.o -SF_OBJS_OTHERS += f128_to_i32.o -SF_OBJS_OTHERS += f128_to_i64.o -SF_OBJS_OTHERS += f128_to_ui32_r_minMag.o -SF_OBJS_OTHERS += f128_to_ui64_r_minMag.o -SF_OBJS_OTHERS += f128_to_i32_r_minMag.o -SF_OBJS_OTHERS += f128_to_i64_r_minMag.o -SF_OBJS_OTHERS += f128_to_f16.o -SF_OBJS_OTHERS += f128_to_f32.o -SF_OBJS_OTHERS += f128_to_extF80.o -SF_OBJS_OTHERS += f128_to_f64.o -SF_OBJS_OTHERS += f128_roundToInt.o -SF_OBJS_OTHERS += f128_add.o -SF_OBJS_OTHERS += f128_sub.o -SF_OBJS_OTHERS += f128_mul.o -SF_OBJS_OTHERS += f128_mulAdd.o -SF_OBJS_OTHERS += f128_div.o -SF_OBJS_OTHERS += f128_rem.o -SF_OBJS_OTHERS += f128_sqrt.o -SF_OBJS_OTHERS += f128_eq.o -SF_OBJS_OTHERS += f128_le.o -SF_OBJS_OTHERS += f128_lt.o -SF_OBJS_OTHERS += f128_eq_signaling.o -SF_OBJS_OTHERS += f128_le_quiet.o -SF_OBJS_OTHERS += f128_lt_quiet.o -SF_OBJS_OTHERS += f128_isSignalingNaN.o -SF_OBJS_OTHERS += f128M_to_ui32.o -SF_OBJS_OTHERS += f128M_to_ui64.o -SF_OBJS_OTHERS += f128M_to_i32.o -SF_OBJS_OTHERS += f128M_to_i64.o -SF_OBJS_OTHERS += f128M_to_ui32_r_minMag.o -SF_OBJS_OTHERS += f128M_to_ui64_r_minMag.o -SF_OBJS_OTHERS += f128M_to_i32_r_minMag.o -SF_OBJS_OTHERS += f128M_to_i64_r_minMag.o -SF_OBJS_OTHERS += f128M_to_f16.o -SF_OBJS_OTHERS += f128M_to_f32.o -SF_OBJS_OTHERS += f128M_to_extF80M.o -SF_OBJS_OTHERS += f128M_to_f64.o -SF_OBJS_OTHERS += f128M_roundToInt.o -SF_OBJS_OTHERS += f128M_add.o -SF_OBJS_OTHERS += f128M_sub.o -SF_OBJS_OTHERS += f128M_mul.o -SF_OBJS_OTHERS += f128M_mulAdd.o -SF_OBJS_OTHERS += f128M_div.o -SF_OBJS_OTHERS += f128M_rem.o -SF_OBJS_OTHERS += f128M_sqrt.o -SF_OBJS_OTHERS += f128M_eq.o -SF_OBJS_OTHERS += f128M_le.o -SF_OBJS_OTHERS += f128M_lt.o -SF_OBJS_OTHERS += f128M_eq_signaling.o -SF_OBJS_OTHERS += f128M_le_quiet.o -SF_OBJS_OTHERS += f128M_lt_quiet.o - -SF_OBJS_ALL_NOSPEC := -SF_OBJS_ALL_NOSPEC += $(SF_OBJS_PRIMITIVES) -SF_OBJS_ALL_NOSPEC += $(SF_OBJS_OTHERS) - -SF_OBJS_ALL := -SF_OBJS_ALL += $(SF_OBJS_ALL_NOSPEC) -SF_OBJS_ALL += $(SF_OBJS_SPECIALIZE) - -# testfloat objects -TF_OBJS_GENCASES := -TF_OBJS_GENCASES += genCases_ui32.o -TF_OBJS_GENCASES += genCases_ui64.o -TF_OBJS_GENCASES += genCases_i32.o -TF_OBJS_GENCASES += genCases_i64.o -TF_OBJS_GENCASES += genCases_f16.o -TF_OBJS_GENCASES += genCases_f32.o -TF_OBJS_GENCASES += genCases_f64.o -TF_OBJS_GENCASES += genCases_extF80.o -TF_OBJS_GENCASES += genCases_f128.o - -TF_OBJS_WRITECASE := -TF_OBJS_WRITECASE += writeCase_a_ui32.o -TF_OBJS_WRITECASE += writeCase_a_ui64.o -TF_OBJS_WRITECASE += writeCase_a_f16.o -TF_OBJS_WRITECASE += writeCase_ab_f16.o -TF_OBJS_WRITECASE += writeCase_abc_f16.o -TF_OBJS_WRITECASE += writeCase_a_f32.o -TF_OBJS_WRITECASE += writeCase_ab_f32.o -TF_OBJS_WRITECASE += writeCase_abc_f32.o -TF_OBJS_WRITECASE += writeCase_a_f64.o -TF_OBJS_WRITECASE += writeCase_ab_f64.o -TF_OBJS_WRITECASE += writeCase_abc_f64.o -TF_OBJS_WRITECASE += writeCase_a_extF80M.o -TF_OBJS_WRITECASE += writeCase_ab_extF80M.o -TF_OBJS_WRITECASE += writeCase_a_f128M.o -TF_OBJS_WRITECASE += writeCase_ab_f128M.o -TF_OBJS_WRITECASE += writeCase_abc_f128M.o -TF_OBJS_WRITECASE += writeCase_z_bool.o -TF_OBJS_WRITECASE += writeCase_z_ui32.o -TF_OBJS_WRITECASE += writeCase_z_ui64.o -TF_OBJS_WRITECASE += writeCase_z_f16.o -TF_OBJS_WRITECASE += writeCase_z_f32.o -TF_OBJS_WRITECASE += writeCase_z_f64.o -TF_OBJS_WRITECASE += writeCase_z_extF80M.o -TF_OBJS_WRITECASE += writeCase_z_f128M.o - -TF_OBJS_TEST := -TF_OBJS_TEST += test_a_ui32_z_f16.o -TF_OBJS_TEST += test_a_ui32_z_f32.o -TF_OBJS_TEST += test_a_ui32_z_f64.o -TF_OBJS_TEST += test_a_ui32_z_extF80.o -TF_OBJS_TEST += test_a_ui32_z_f128.o -TF_OBJS_TEST += test_a_ui64_z_f16.o -TF_OBJS_TEST += test_a_ui64_z_f32.o -TF_OBJS_TEST += test_a_ui64_z_f64.o -TF_OBJS_TEST += test_a_ui64_z_extF80.o -TF_OBJS_TEST += test_a_ui64_z_f128.o -TF_OBJS_TEST += test_a_i32_z_f16.o -TF_OBJS_TEST += test_a_i32_z_f32.o -TF_OBJS_TEST += test_a_i32_z_f64.o -TF_OBJS_TEST += test_a_i32_z_extF80.o -TF_OBJS_TEST += test_a_i32_z_f128.o -TF_OBJS_TEST += test_a_i64_z_f16.o -TF_OBJS_TEST += test_a_i64_z_f32.o -TF_OBJS_TEST += test_a_i64_z_f64.o -TF_OBJS_TEST += test_a_i64_z_extF80.o -TF_OBJS_TEST += test_a_i64_z_f128.o -TF_OBJS_TEST += test_a_f16_z_ui32_rx.o -TF_OBJS_TEST += test_a_f16_z_ui64_rx.o -TF_OBJS_TEST += test_a_f16_z_i32_rx.o -TF_OBJS_TEST += test_a_f16_z_i64_rx.o -TF_OBJS_TEST += test_a_f16_z_ui32_x.o -TF_OBJS_TEST += test_a_f16_z_ui64_x.o -TF_OBJS_TEST += test_a_f16_z_i32_x.o -TF_OBJS_TEST += test_a_f16_z_i64_x.o -TF_OBJS_TEST += test_a_f16_z_f32.o -TF_OBJS_TEST += test_a_f16_z_f64.o -TF_OBJS_TEST += test_a_f16_z_extF80.o -TF_OBJS_TEST += test_a_f16_z_f128.o -TF_OBJS_TEST += test_az_f16.o -TF_OBJS_TEST += test_az_f16_rx.o -TF_OBJS_TEST += test_abz_f16.o -TF_OBJS_TEST += test_abcz_f16.o -TF_OBJS_TEST += test_ab_f16_z_bool.o -TF_OBJS_TEST += test_a_f32_z_ui32_rx.o -TF_OBJS_TEST += test_a_f32_z_ui64_rx.o -TF_OBJS_TEST += test_a_f32_z_i32_rx.o -TF_OBJS_TEST += test_a_f32_z_i64_rx.o -TF_OBJS_TEST += test_a_f32_z_ui32_x.o -TF_OBJS_TEST += test_a_f32_z_ui64_x.o -TF_OBJS_TEST += test_a_f32_z_i32_x.o -TF_OBJS_TEST += test_a_f32_z_i64_x.o -TF_OBJS_TEST += test_a_f32_z_f16.o -TF_OBJS_TEST += test_a_f32_z_f64.o -TF_OBJS_TEST += test_a_f32_z_extF80.o -TF_OBJS_TEST += test_a_f32_z_f128.o -TF_OBJS_TEST += test_az_f32.o -TF_OBJS_TEST += test_az_f32_rx.o -TF_OBJS_TEST += test_abz_f32.o -TF_OBJS_TEST += test_abcz_f32.o -TF_OBJS_TEST += test_ab_f32_z_bool.o -TF_OBJS_TEST += test_a_f64_z_ui32_rx.o -TF_OBJS_TEST += test_a_f64_z_ui64_rx.o -TF_OBJS_TEST += test_a_f64_z_i32_rx.o -TF_OBJS_TEST += test_a_f64_z_i64_rx.o -TF_OBJS_TEST += test_a_f64_z_ui32_x.o -TF_OBJS_TEST += test_a_f64_z_ui64_x.o -TF_OBJS_TEST += test_a_f64_z_i32_x.o -TF_OBJS_TEST += test_a_f64_z_i64_x.o -TF_OBJS_TEST += test_a_f64_z_f16.o -TF_OBJS_TEST += test_a_f64_z_f32.o -TF_OBJS_TEST += test_a_f64_z_extF80.o -TF_OBJS_TEST += test_a_f64_z_f128.o -TF_OBJS_TEST += test_az_f64.o -TF_OBJS_TEST += test_az_f64_rx.o -TF_OBJS_TEST += test_abz_f64.o -TF_OBJS_TEST += test_abcz_f64.o -TF_OBJS_TEST += test_ab_f64_z_bool.o -TF_OBJS_TEST += test_a_extF80_z_ui32_rx.o -TF_OBJS_TEST += test_a_extF80_z_ui64_rx.o -TF_OBJS_TEST += test_a_extF80_z_i32_rx.o -TF_OBJS_TEST += test_a_extF80_z_i64_rx.o -TF_OBJS_TEST += test_a_extF80_z_ui32_x.o -TF_OBJS_TEST += test_a_extF80_z_ui64_x.o -TF_OBJS_TEST += test_a_extF80_z_i32_x.o -TF_OBJS_TEST += test_a_extF80_z_i64_x.o -TF_OBJS_TEST += test_a_extF80_z_f16.o -TF_OBJS_TEST += test_a_extF80_z_f32.o -TF_OBJS_TEST += test_a_extF80_z_f64.o -TF_OBJS_TEST += test_a_extF80_z_f128.o -TF_OBJS_TEST += test_az_extF80.o -TF_OBJS_TEST += test_az_extF80_rx.o -TF_OBJS_TEST += test_abz_extF80.o -TF_OBJS_TEST += test_ab_extF80_z_bool.o -TF_OBJS_TEST += test_a_f128_z_ui32_rx.o -TF_OBJS_TEST += test_a_f128_z_ui64_rx.o -TF_OBJS_TEST += test_a_f128_z_i32_rx.o -TF_OBJS_TEST += test_a_f128_z_i64_rx.o -TF_OBJS_TEST += test_a_f128_z_ui32_x.o -TF_OBJS_TEST += test_a_f128_z_ui64_x.o -TF_OBJS_TEST += test_a_f128_z_i32_x.o -TF_OBJS_TEST += test_a_f128_z_i64_x.o -TF_OBJS_TEST += test_a_f128_z_f16.o -TF_OBJS_TEST += test_a_f128_z_f32.o -TF_OBJS_TEST += test_a_f128_z_f64.o -TF_OBJS_TEST += test_a_f128_z_extF80.o -TF_OBJS_TEST += test_az_f128.o -TF_OBJS_TEST += test_az_f128_rx.o -TF_OBJS_TEST += test_abz_f128.o -TF_OBJS_TEST += test_abcz_f128.o -TF_OBJS_TEST += test_ab_f128_z_bool.o - -TF_OBJS_LIB := -TF_OBJS_LIB += uint128_inline.o -TF_OBJS_LIB += uint128.o -TF_OBJS_LIB += fail.o -TF_OBJS_LIB += functions_common.o -TF_OBJS_LIB += functionInfos.o -TF_OBJS_LIB += standardFunctionInfos.o -TF_OBJS_LIB += random.o -TF_OBJS_LIB += genCases_common.o -TF_OBJS_LIB += $(TF_OBJS_GENCASES) -TF_OBJS_LIB += genCases_writeTestsTotal.o -TF_OBJS_LIB += verCases_inline.o -TF_OBJS_LIB += verCases_common.o -TF_OBJS_LIB += verCases_writeFunctionName.o -TF_OBJS_LIB += readHex.o -TF_OBJS_LIB += writeHex.o -TF_OBJS_LIB += $(TF_OBJS_WRITECASE) -TF_OBJS_LIB += testLoops_common.o -TF_OBJS_LIB += $(TF_OBJS_TEST) - -BINARIES := fp-test$(EXESUF) fp-bench$(EXESUF) - -# We require artefacts from the main build including config-host.h -# because platform.h includes it. Rather than re-invoking the main -# build we just error out if things aren't there. -$(LIBQEMUUTIL) $(BUILD_DIR)/config-host.h: - $(error $@ missing, re-run parent build) - -all: $(BUILD_DIR)/config-host.h $(BINARIES) - -# libtestfloat.a depends on libsoftfloat.a, so specify it first -FP_TEST_LIBS := libtestfloat.a libsoftfloat.a $(LIBQEMUUTIL) - -fp-test$(EXESUF): fp-test.o slowfloat.o $(QEMU_SOFTFLOAT_OBJ) $(FP_TEST_LIBS) - -# Custom rule to build with SF_CFLAGS -SF_BUILD = $(call quiet-command,$(CC) $(QEMU_LOCAL_INCLUDES) $(QEMU_INCLUDES) \ - $(QEMU_CFLAGS) $(SF_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) \ - $($@-cflags) -c -o $@ $<,"CC","$(TARGET_DIR)$@") - -$(SF_OBJS_ALL_NOSPEC): %.o: $(SF_SOURCE_DIR)/%.c - $(SF_BUILD) -$(SF_OBJS_SPECIALIZE): %.o: $(SF_SPECIALIZE_DIR)/%.c - $(SF_BUILD) - -libsoftfloat.a: $(SF_OBJS_ALL) - -# Custom rule to build with TF_CFLAGS -$(TF_OBJS_LIB) slowfloat.o: %.o: $(TF_SOURCE_DIR)/%.c - $(call quiet-command,$(CC) $(QEMU_LOCAL_INCLUDES) $(QEMU_INCLUDES) \ - $(QEMU_CFLAGS) $(TF_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) \ - $($@-cflags) -c -o $@ $<,"CC","$(TARGET_DIR)$@") - -libtestfloat.a: $(TF_OBJS_LIB) - -fp-bench$(EXESUF): fp-bench.o $(QEMU_SOFTFLOAT_OBJ) $(LIBQEMUUTIL) - -clean: - rm -f *.o *.d $(BINARIES) - rm -f *.gcno *.gcda *.gcov - rm -f fp-test$(EXESUF) - rm -f fp-bench$(EXESUF) - rm -f libsoftfloat.a - rm -f libtestfloat.a - --include $(wildcard *.d) diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c index 43ef9628c41c9740b0a8c9e573bfa7142fcc0a31..06ffebd6db17ad5af7fbacc81af5cf800c5d2d66 100644 --- a/tests/fp/fp-test.c +++ b/tests/fp/fp-test.c @@ -116,7 +116,7 @@ static void usage_complete(int argc, char *argv[]) } /* keep wrappers separate but do not bother defining headers for all of them */ -#include "wrap.inc.c" +#include "wrap.c.inc" static void not_implemented(void) { diff --git a/tests/fp/meson.build b/tests/fp/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..3d4fb00f9d840ebb3835cd4aba5338231aab6bec --- /dev/null +++ b/tests/fp/meson.build @@ -0,0 +1,634 @@ +# There are namespace pollution issues on Windows, due to osdep.h +# bringing in Windows headers that define a FLOAT128 type. +if targetos == 'windows' + subdir_done() +endif + +fpcflags = [ + # softfloat defines + '-DSOFTFLOAT_ROUND_ODD', + '-DINLINE_LEVEL=5', + '-DSOFTFLOAT_FAST_DIV32TO16', + '-DSOFTFLOAT_FAST_DIV64TO32', + '-DSOFTFLOAT_FAST_INT64', + # testfloat defines + '-DFLOAT16', + '-DFLOAT64', + '-DEXTFLOAT80', + '-DFLOAT128', + '-DFLOAT_ROUND_ODD', + '-DLONG_DOUBLE_IS_EXTFLOAT80', +] + +sfdir = 'berkeley-softfloat-3/source' +sfspedir = sfdir / '8086-SSE' +tfdir = 'berkeley-testfloat-3/source' + +sfinc = include_directories(sfdir / 'include', sfspedir) + +tfcflags = [ + '-Wno-strict-prototypes', + '-Wno-unknown-pragmas', + '-Wno-uninitialized', + '-Wno-missing-prototypes', + '-Wno-return-type', + '-Wno-unused-function', + '-Wno-error', +] + +tfgencases = [ + tfdir / 'genCases_ui32.c', + tfdir / 'genCases_ui64.c', + tfdir / 'genCases_i32.c', + tfdir / 'genCases_i64.c', + tfdir / 'genCases_f16.c', + tfdir / 'genCases_f32.c', + tfdir / 'genCases_f64.c', + tfdir / 'genCases_extF80.c', + tfdir / 'genCases_f128.c', +] + +tfwritecase = [ + tfdir / 'writeCase_a_ui32.c', + tfdir / 'writeCase_a_ui64.c', + tfdir / 'writeCase_a_f16.c', + tfdir / 'writeCase_ab_f16.c', + tfdir / 'writeCase_abc_f16.c', + tfdir / 'writeCase_a_f32.c', + tfdir / 'writeCase_ab_f32.c', + tfdir / 'writeCase_abc_f32.c', + tfdir / 'writeCase_a_f64.c', + tfdir / 'writeCase_ab_f64.c', + tfdir / 'writeCase_abc_f64.c', + tfdir / 'writeCase_a_extF80M.c', + tfdir / 'writeCase_ab_extF80M.c', + tfdir / 'writeCase_a_f128M.c', + tfdir / 'writeCase_ab_f128M.c', + tfdir / 'writeCase_abc_f128M.c', + tfdir / 'writeCase_z_bool.c', + tfdir / 'writeCase_z_ui32.c', + tfdir / 'writeCase_z_ui64.c', + tfdir / 'writeCase_z_f16.c', + tfdir / 'writeCase_z_f32.c', + tfdir / 'writeCase_z_f64.c', + tfdir / 'writeCase_z_extF80M.c', + tfdir / 'writeCase_z_f128M.c', +] + +tftest = [ + tfdir / 'test_a_ui32_z_f16.c', + tfdir / 'test_a_ui32_z_f32.c', + tfdir / 'test_a_ui32_z_f64.c', + tfdir / 'test_a_ui32_z_extF80.c', + tfdir / 'test_a_ui32_z_f128.c', + tfdir / 'test_a_ui64_z_f16.c', + tfdir / 'test_a_ui64_z_f32.c', + tfdir / 'test_a_ui64_z_f64.c', + tfdir / 'test_a_ui64_z_extF80.c', + tfdir / 'test_a_ui64_z_f128.c', + tfdir / 'test_a_i32_z_f16.c', + tfdir / 'test_a_i32_z_f32.c', + tfdir / 'test_a_i32_z_f64.c', + tfdir / 'test_a_i32_z_extF80.c', + tfdir / 'test_a_i32_z_f128.c', + tfdir / 'test_a_i64_z_f16.c', + tfdir / 'test_a_i64_z_f32.c', + tfdir / 'test_a_i64_z_f64.c', + tfdir / 'test_a_i64_z_extF80.c', + tfdir / 'test_a_i64_z_f128.c', + tfdir / 'test_a_f16_z_ui32_rx.c', + tfdir / 'test_a_f16_z_ui64_rx.c', + tfdir / 'test_a_f16_z_i32_rx.c', + tfdir / 'test_a_f16_z_i64_rx.c', + tfdir / 'test_a_f16_z_ui32_x.c', + tfdir / 'test_a_f16_z_ui64_x.c', + tfdir / 'test_a_f16_z_i32_x.c', + tfdir / 'test_a_f16_z_i64_x.c', + tfdir / 'test_a_f16_z_f32.c', + tfdir / 'test_a_f16_z_f64.c', + tfdir / 'test_a_f16_z_extF80.c', + tfdir / 'test_a_f16_z_f128.c', + tfdir / 'test_az_f16.c', + tfdir / 'test_az_f16_rx.c', + tfdir / 'test_abz_f16.c', + tfdir / 'test_abcz_f16.c', + tfdir / 'test_ab_f16_z_bool.c', + tfdir / 'test_a_f32_z_ui32_rx.c', + tfdir / 'test_a_f32_z_ui64_rx.c', + tfdir / 'test_a_f32_z_i32_rx.c', + tfdir / 'test_a_f32_z_i64_rx.c', + tfdir / 'test_a_f32_z_ui32_x.c', + tfdir / 'test_a_f32_z_ui64_x.c', + tfdir / 'test_a_f32_z_i32_x.c', + tfdir / 'test_a_f32_z_i64_x.c', + tfdir / 'test_a_f32_z_f16.c', + tfdir / 'test_a_f32_z_f64.c', + tfdir / 'test_a_f32_z_extF80.c', + tfdir / 'test_a_f32_z_f128.c', + tfdir / 'test_az_f32.c', + tfdir / 'test_az_f32_rx.c', + tfdir / 'test_abz_f32.c', + tfdir / 'test_abcz_f32.c', + tfdir / 'test_ab_f32_z_bool.c', + tfdir / 'test_a_f64_z_ui32_rx.c', + tfdir / 'test_a_f64_z_ui64_rx.c', + tfdir / 'test_a_f64_z_i32_rx.c', + tfdir / 'test_a_f64_z_i64_rx.c', + tfdir / 'test_a_f64_z_ui32_x.c', + tfdir / 'test_a_f64_z_ui64_x.c', + tfdir / 'test_a_f64_z_i32_x.c', + tfdir / 'test_a_f64_z_i64_x.c', + tfdir / 'test_a_f64_z_f16.c', + tfdir / 'test_a_f64_z_f32.c', + tfdir / 'test_a_f64_z_extF80.c', + tfdir / 'test_a_f64_z_f128.c', + tfdir / 'test_az_f64.c', + tfdir / 'test_az_f64_rx.c', + tfdir / 'test_abz_f64.c', + tfdir / 'test_abcz_f64.c', + tfdir / 'test_ab_f64_z_bool.c', + tfdir / 'test_a_extF80_z_ui32_rx.c', + tfdir / 'test_a_extF80_z_ui64_rx.c', + tfdir / 'test_a_extF80_z_i32_rx.c', + tfdir / 'test_a_extF80_z_i64_rx.c', + tfdir / 'test_a_extF80_z_ui32_x.c', + tfdir / 'test_a_extF80_z_ui64_x.c', + tfdir / 'test_a_extF80_z_i32_x.c', + tfdir / 'test_a_extF80_z_i64_x.c', + tfdir / 'test_a_extF80_z_f16.c', + tfdir / 'test_a_extF80_z_f32.c', + tfdir / 'test_a_extF80_z_f64.c', + tfdir / 'test_a_extF80_z_f128.c', + tfdir / 'test_az_extF80.c', + tfdir / 'test_az_extF80_rx.c', + tfdir / 'test_abz_extF80.c', + tfdir / 'test_ab_extF80_z_bool.c', + tfdir / 'test_a_f128_z_ui32_rx.c', + tfdir / 'test_a_f128_z_ui64_rx.c', + tfdir / 'test_a_f128_z_i32_rx.c', + tfdir / 'test_a_f128_z_i64_rx.c', + tfdir / 'test_a_f128_z_ui32_x.c', + tfdir / 'test_a_f128_z_ui64_x.c', + tfdir / 'test_a_f128_z_i32_x.c', + tfdir / 'test_a_f128_z_i64_x.c', + tfdir / 'test_a_f128_z_f16.c', + tfdir / 'test_a_f128_z_f32.c', + tfdir / 'test_a_f128_z_f64.c', + tfdir / 'test_a_f128_z_extF80.c', + tfdir / 'test_az_f128.c', + tfdir / 'test_az_f128_rx.c', + tfdir / 'test_abz_f128.c', + tfdir / 'test_abcz_f128.c', + tfdir / 'test_ab_f128_z_bool.c', +] + +libtestfloat = static_library( + 'testfloat', + files( + tfdir / 'uint128_inline.c', + tfdir / 'uint128.c', + tfdir / 'fail.c', + tfdir / 'functions_common.c', + tfdir / 'functionInfos.c', + tfdir / 'standardFunctionInfos.c', + tfdir / 'random.c', + tfdir / 'genCases_common.c', + tfgencases, + tfdir / 'genCases_writeTestsTotal.c', + tfdir / 'verCases_inline.c', + tfdir / 'verCases_common.c', + tfdir / 'verCases_writeFunctionName.c', + tfdir / 'readHex.c', + tfdir / 'writeHex.c', + tfwritecase, + tfdir / 'testLoops_common.c', + tftest, + ), + include_directories: sfinc, + c_args: tfcflags + fpcflags, +) + +sfcflags = [ + '-Wno-missing-prototypes', + '-Wno-redundant-decls', + '-Wno-return-type', + '-Wno-error', +] + +libsoftfloat = static_library( + 'softfloat', + files( + # primitives + sfdir / 's_eq128.c', + sfdir / 's_le128.c', + sfdir / 's_lt128.c', + sfdir / 's_shortShiftLeft128.c', + sfdir / 's_shortShiftRight128.c', + sfdir / 's_shortShiftRightJam64.c', + sfdir / 's_shortShiftRightJam64Extra.c', + sfdir / 's_shortShiftRightJam128.c', + sfdir / 's_shortShiftRightJam128Extra.c', + sfdir / 's_shiftRightJam32.c', + sfdir / 's_shiftRightJam64.c', + sfdir / 's_shiftRightJam64Extra.c', + sfdir / 's_shiftRightJam128.c', + sfdir / 's_shiftRightJam128Extra.c', + sfdir / 's_shiftRightJam256M.c', + sfdir / 's_countLeadingZeros8.c', + sfdir / 's_countLeadingZeros16.c', + sfdir / 's_countLeadingZeros32.c', + sfdir / 's_countLeadingZeros64.c', + sfdir / 's_add128.c', + sfdir / 's_add256M.c', + sfdir / 's_sub128.c', + sfdir / 's_sub256M.c', + sfdir / 's_mul64ByShifted32To128.c', + sfdir / 's_mul64To128.c', + sfdir / 's_mul128By32.c', + sfdir / 's_mul128To256M.c', + sfdir / 's_approxRecip_1Ks.c', + sfdir / 's_approxRecip32_1.c', + sfdir / 's_approxRecipSqrt_1Ks.c', + sfdir / 's_approxRecipSqrt32_1.c', + # others + sfdir / 's_roundToUI32.c', + sfdir / 's_roundToUI64.c', + sfdir / 's_roundToI32.c', + sfdir / 's_roundToI64.c', + sfdir / 's_normSubnormalF16Sig.c', + sfdir / 's_roundPackToF16.c', + sfdir / 's_normRoundPackToF16.c', + sfdir / 's_addMagsF16.c', + sfdir / 's_subMagsF16.c', + sfdir / 's_mulAddF16.c', + sfdir / 's_normSubnormalF32Sig.c', + sfdir / 's_roundPackToF32.c', + sfdir / 's_normRoundPackToF32.c', + sfdir / 's_addMagsF32.c', + sfdir / 's_subMagsF32.c', + sfdir / 's_mulAddF32.c', + sfdir / 's_normSubnormalF64Sig.c', + sfdir / 's_roundPackToF64.c', + sfdir / 's_normRoundPackToF64.c', + sfdir / 's_addMagsF64.c', + sfdir / 's_subMagsF64.c', + sfdir / 's_mulAddF64.c', + sfdir / 's_normSubnormalExtF80Sig.c', + sfdir / 's_roundPackToExtF80.c', + sfdir / 's_normRoundPackToExtF80.c', + sfdir / 's_addMagsExtF80.c', + sfdir / 's_subMagsExtF80.c', + sfdir / 's_normSubnormalF128Sig.c', + sfdir / 's_roundPackToF128.c', + sfdir / 's_normRoundPackToF128.c', + sfdir / 's_addMagsF128.c', + sfdir / 's_subMagsF128.c', + sfdir / 's_mulAddF128.c', + sfdir / 'softfloat_state.c', + sfdir / 'ui32_to_f16.c', + sfdir / 'ui32_to_f32.c', + sfdir / 'ui32_to_f64.c', + sfdir / 'ui32_to_extF80.c', + sfdir / 'ui32_to_extF80M.c', + sfdir / 'ui32_to_f128.c', + sfdir / 'ui32_to_f128M.c', + sfdir / 'ui64_to_f16.c', + sfdir / 'ui64_to_f32.c', + sfdir / 'ui64_to_f64.c', + sfdir / 'ui64_to_extF80.c', + sfdir / 'ui64_to_extF80M.c', + sfdir / 'ui64_to_f128.c', + sfdir / 'ui64_to_f128M.c', + sfdir / 'i32_to_f16.c', + sfdir / 'i32_to_f32.c', + sfdir / 'i32_to_f64.c', + sfdir / 'i32_to_extF80.c', + sfdir / 'i32_to_extF80M.c', + sfdir / 'i32_to_f128.c', + sfdir / 'i32_to_f128M.c', + sfdir / 'i64_to_f16.c', + sfdir / 'i64_to_f32.c', + sfdir / 'i64_to_f64.c', + sfdir / 'i64_to_extF80.c', + sfdir / 'i64_to_extF80M.c', + sfdir / 'i64_to_f128.c', + sfdir / 'i64_to_f128M.c', + sfdir / 'f16_to_ui32.c', + sfdir / 'f16_to_ui64.c', + sfdir / 'f16_to_i32.c', + sfdir / 'f16_to_i64.c', + sfdir / 'f16_to_ui32_r_minMag.c', + sfdir / 'f16_to_ui64_r_minMag.c', + sfdir / 'f16_to_i32_r_minMag.c', + sfdir / 'f16_to_i64_r_minMag.c', + sfdir / 'f16_to_f32.c', + sfdir / 'f16_to_f64.c', + sfdir / 'f16_to_extF80.c', + sfdir / 'f16_to_extF80M.c', + sfdir / 'f16_to_f128.c', + sfdir / 'f16_to_f128M.c', + sfdir / 'f16_roundToInt.c', + sfdir / 'f16_add.c', + sfdir / 'f16_sub.c', + sfdir / 'f16_mul.c', + sfdir / 'f16_mulAdd.c', + sfdir / 'f16_div.c', + sfdir / 'f16_rem.c', + sfdir / 'f16_sqrt.c', + sfdir / 'f16_eq.c', + sfdir / 'f16_le.c', + sfdir / 'f16_lt.c', + sfdir / 'f16_eq_signaling.c', + sfdir / 'f16_le_quiet.c', + sfdir / 'f16_lt_quiet.c', + sfdir / 'f16_isSignalingNaN.c', + sfdir / 'f32_to_ui32.c', + sfdir / 'f32_to_ui64.c', + sfdir / 'f32_to_i32.c', + sfdir / 'f32_to_i64.c', + sfdir / 'f32_to_ui32_r_minMag.c', + sfdir / 'f32_to_ui64_r_minMag.c', + sfdir / 'f32_to_i32_r_minMag.c', + sfdir / 'f32_to_i64_r_minMag.c', + sfdir / 'f32_to_f16.c', + sfdir / 'f32_to_f64.c', + sfdir / 'f32_to_extF80.c', + sfdir / 'f32_to_extF80M.c', + sfdir / 'f32_to_f128.c', + sfdir / 'f32_to_f128M.c', + sfdir / 'f32_roundToInt.c', + sfdir / 'f32_add.c', + sfdir / 'f32_sub.c', + sfdir / 'f32_mul.c', + sfdir / 'f32_mulAdd.c', + sfdir / 'f32_div.c', + sfdir / 'f32_rem.c', + sfdir / 'f32_sqrt.c', + sfdir / 'f32_eq.c', + sfdir / 'f32_le.c', + sfdir / 'f32_lt.c', + sfdir / 'f32_eq_signaling.c', + sfdir / 'f32_le_quiet.c', + sfdir / 'f32_lt_quiet.c', + sfdir / 'f32_isSignalingNaN.c', + sfdir / 'f64_to_ui32.c', + sfdir / 'f64_to_ui64.c', + sfdir / 'f64_to_i32.c', + sfdir / 'f64_to_i64.c', + sfdir / 'f64_to_ui32_r_minMag.c', + sfdir / 'f64_to_ui64_r_minMag.c', + sfdir / 'f64_to_i32_r_minMag.c', + sfdir / 'f64_to_i64_r_minMag.c', + sfdir / 'f64_to_f16.c', + sfdir / 'f64_to_f32.c', + sfdir / 'f64_to_extF80.c', + sfdir / 'f64_to_extF80M.c', + sfdir / 'f64_to_f128.c', + sfdir / 'f64_to_f128M.c', + sfdir / 'f64_roundToInt.c', + sfdir / 'f64_add.c', + sfdir / 'f64_sub.c', + sfdir / 'f64_mul.c', + sfdir / 'f64_mulAdd.c', + sfdir / 'f64_div.c', + sfdir / 'f64_rem.c', + sfdir / 'f64_sqrt.c', + sfdir / 'f64_eq.c', + sfdir / 'f64_le.c', + sfdir / 'f64_lt.c', + sfdir / 'f64_eq_signaling.c', + sfdir / 'f64_le_quiet.c', + sfdir / 'f64_lt_quiet.c', + sfdir / 'f64_isSignalingNaN.c', + sfdir / 'extF80_to_ui32.c', + sfdir / 'extF80_to_ui64.c', + sfdir / 'extF80_to_i32.c', + sfdir / 'extF80_to_i64.c', + sfdir / 'extF80_to_ui32_r_minMag.c', + sfdir / 'extF80_to_ui64_r_minMag.c', + sfdir / 'extF80_to_i32_r_minMag.c', + sfdir / 'extF80_to_i64_r_minMag.c', + sfdir / 'extF80_to_f16.c', + sfdir / 'extF80_to_f32.c', + sfdir / 'extF80_to_f64.c', + sfdir / 'extF80_to_f128.c', + sfdir / 'extF80_roundToInt.c', + sfdir / 'extF80_add.c', + sfdir / 'extF80_sub.c', + sfdir / 'extF80_mul.c', + sfdir / 'extF80_div.c', + sfdir / 'extF80_rem.c', + sfdir / 'extF80_sqrt.c', + sfdir / 'extF80_eq.c', + sfdir / 'extF80_le.c', + sfdir / 'extF80_lt.c', + sfdir / 'extF80_eq_signaling.c', + sfdir / 'extF80_le_quiet.c', + sfdir / 'extF80_lt_quiet.c', + sfdir / 'extF80_isSignalingNaN.c', + sfdir / 'extF80M_to_ui32.c', + sfdir / 'extF80M_to_ui64.c', + sfdir / 'extF80M_to_i32.c', + sfdir / 'extF80M_to_i64.c', + sfdir / 'extF80M_to_ui32_r_minMag.c', + sfdir / 'extF80M_to_ui64_r_minMag.c', + sfdir / 'extF80M_to_i32_r_minMag.c', + sfdir / 'extF80M_to_i64_r_minMag.c', + sfdir / 'extF80M_to_f16.c', + sfdir / 'extF80M_to_f32.c', + sfdir / 'extF80M_to_f64.c', + sfdir / 'extF80M_to_f128M.c', + sfdir / 'extF80M_roundToInt.c', + sfdir / 'extF80M_add.c', + sfdir / 'extF80M_sub.c', + sfdir / 'extF80M_mul.c', + sfdir / 'extF80M_div.c', + sfdir / 'extF80M_rem.c', + sfdir / 'extF80M_sqrt.c', + sfdir / 'extF80M_eq.c', + sfdir / 'extF80M_le.c', + sfdir / 'extF80M_lt.c', + sfdir / 'extF80M_eq_signaling.c', + sfdir / 'extF80M_le_quiet.c', + sfdir / 'extF80M_lt_quiet.c', + sfdir / 'f128_to_ui32.c', + sfdir / 'f128_to_ui64.c', + sfdir / 'f128_to_i32.c', + sfdir / 'f128_to_i64.c', + sfdir / 'f128_to_ui32_r_minMag.c', + sfdir / 'f128_to_ui64_r_minMag.c', + sfdir / 'f128_to_i32_r_minMag.c', + sfdir / 'f128_to_i64_r_minMag.c', + sfdir / 'f128_to_f16.c', + sfdir / 'f128_to_f32.c', + sfdir / 'f128_to_extF80.c', + sfdir / 'f128_to_f64.c', + sfdir / 'f128_roundToInt.c', + sfdir / 'f128_add.c', + sfdir / 'f128_sub.c', + sfdir / 'f128_mul.c', + sfdir / 'f128_mulAdd.c', + sfdir / 'f128_div.c', + sfdir / 'f128_rem.c', + sfdir / 'f128_sqrt.c', + sfdir / 'f128_eq.c', + sfdir / 'f128_le.c', + sfdir / 'f128_lt.c', + sfdir / 'f128_eq_signaling.c', + sfdir / 'f128_le_quiet.c', + sfdir / 'f128_lt_quiet.c', + sfdir / 'f128_isSignalingNaN.c', + sfdir / 'f128M_to_ui32.c', + sfdir / 'f128M_to_ui64.c', + sfdir / 'f128M_to_i32.c', + sfdir / 'f128M_to_i64.c', + sfdir / 'f128M_to_ui32_r_minMag.c', + sfdir / 'f128M_to_ui64_r_minMag.c', + sfdir / 'f128M_to_i32_r_minMag.c', + sfdir / 'f128M_to_i64_r_minMag.c', + sfdir / 'f128M_to_f16.c', + sfdir / 'f128M_to_f32.c', + sfdir / 'f128M_to_extF80M.c', + sfdir / 'f128M_to_f64.c', + sfdir / 'f128M_roundToInt.c', + sfdir / 'f128M_add.c', + sfdir / 'f128M_sub.c', + sfdir / 'f128M_mul.c', + sfdir / 'f128M_mulAdd.c', + sfdir / 'f128M_div.c', + sfdir / 'f128M_rem.c', + sfdir / 'f128M_sqrt.c', + sfdir / 'f128M_eq.c', + sfdir / 'f128M_le.c', + sfdir / 'f128M_lt.c', + sfdir / 'f128M_eq_signaling.c', + sfdir / 'f128M_le_quiet.c', + sfdir / 'f128M_lt_quiet.c', + # spe + sfspedir / 'softfloat_raiseFlags.c', + sfspedir / 's_f16UIToCommonNaN.c', + sfspedir / 's_commonNaNToF16UI.c', + sfspedir / 's_propagateNaNF16UI.c', + sfspedir / 's_f32UIToCommonNaN.c', + sfspedir / 's_commonNaNToF32UI.c', + sfspedir / 's_propagateNaNF32UI.c', + sfspedir / 's_f64UIToCommonNaN.c', + sfspedir / 's_commonNaNToF64UI.c', + sfspedir / 's_propagateNaNF64UI.c', + sfspedir / 'extF80M_isSignalingNaN.c', + sfspedir / 's_extF80UIToCommonNaN.c', + sfspedir / 's_commonNaNToExtF80UI.c', + sfspedir / 's_propagateNaNExtF80UI.c', + sfspedir / 'f128M_isSignalingNaN.c', + sfspedir / 's_f128UIToCommonNaN.c', + sfspedir / 's_commonNaNToF128UI.c', + sfspedir / 's_propagateNaNF128UI.c', + ), + include_directories: sfinc, + c_args: sfcflags + fpcflags, +) + +fpcflags += [ + # work around TARGET_* poisoning + '-DHW_POISON_H', + # define a target to match testfloat's implementation-defined choices, such as + # whether to raise the invalid flag when dealing with NaNs in muladd. + '-DTARGET_ARM', + # FIXME: uiZ may be used uninitialized in this function + '-Wno-uninitialized', +] + +fptest = executable( + 'fp-test', + ['fp-test.c', tfdir / 'slowfloat.c', '../../fpu/softfloat.c'], + link_with: [libtestfloat, libsoftfloat], + dependencies: [qemuutil], + include_directories: [sfinc, include_directories(tfdir)], + c_args: fpcflags, +) +softfloat_conv_tests = { + 'float-to-float': 'f16_to_f32 f16_to_f64 f16_to_extF80 f16_to_f128 ' + + 'f32_to_f16 f32_to_f64 f32_to_extF80 ' + + 'f64_to_f16 f64_to_f32 ' + + 'extF80_to_f16 extF80_to_f32 ' + + 'extF80_to_f64 extF80_to_f128 ' + + 'f128_to_f16', + 'int-to-float': 'i32_to_f16 i64_to_f16 i32_to_f32 i64_to_f32 ' + + 'i32_to_f64 i64_to_f64 i32_to_f128 i64_to_f128', + 'uint-to-float': 'ui32_to_f16 ui64_to_f16 ui32_to_f32 ui64_to_f32 ' + + 'ui32_to_f64 ui64_to_f64 ui64_to_f128 ' + + 'ui32_to_extF80 ui64_to_extF80', + 'float-to-int': 'f16_to_i32 f16_to_i32_r_minMag ' + + 'f32_to_i32 f32_to_i32_r_minMag ' + + 'f64_to_i32 f64_to_i32_r_minMag ' + + 'extF80_to_i32 extF80_to_i32_r_minMag ' + + 'f128_to_i32 f128_to_i32_r_minMag ' + + 'f16_to_i64 f16_to_i64_r_minMag ' + + 'f32_to_i64 f32_to_i64_r_minMag ' + + 'f64_to_i64 f64_to_i64_r_minMag ' + + 'extF80_to_i64 extF80_to_i64_r_minMag ' + + 'f128_to_i64 f128_to_i64_r_minMag', + 'float-to-uint': 'f16_to_ui32 f16_to_ui32_r_minMag ' + + 'f32_to_ui32 f32_to_ui32_r_minMag ' + + 'f64_to_ui32 f64_to_ui32_r_minMag ' + + 'extF80_to_ui32 extF80_to_ui32_r_minMag ' + + 'f128_to_ui32 f128_to_ui32_r_minMag ' + + 'f16_to_ui64 f16_to_ui64_r_minMag ' + + 'f32_to_ui64 f32_to_ui64_r_minMag ' + + 'f64_to_ui64 f64_to_ui64_r_minMag ' + + 'extF80_to_ui64 extF80_to_ui64_r_minMag ' + + 'f128_to_ui64 f128_to_ui64_r_minMag', + 'round-to-integer': 'f16_roundToInt f32_roundToInt ' + + 'f64_roundToInt f128_roundToInt' +} +softfloat_tests = { + 'eq_signaling' : 'compare', + 'le' : 'compare', + 'le_quiet' : 'compare', + 'lt_quiet' : 'compare', + 'add': 'ops', + 'sub': 'ops', + 'mul': 'ops', + 'div': 'ops', + 'rem': 'ops', + 'sqrt': 'ops' +} +# The full test suite can take a bit of time, default to a quick run +# "-l 2 -r all" can take more than a day for some operations and is best +# run manually +fptest_args = ['-s', '-l', '1'] +fptest_rounding_args = ['-r', 'all'] + +# Conversion Routines: +# FIXME: i32_to_extF80 (broken), i64_to_extF80 (broken) +# extF80_roundToInt (broken) +foreach k, v : softfloat_conv_tests + test('fp-test-' + k, fptest, + args: fptest_args + fptest_rounding_args + v.split(), + suite: ['softfloat', 'softfloat-conv']) +endforeach + +# FIXME: extF80_{lt_quiet, rem} (broken), +# extF80_{mulAdd} (missing) +foreach k, v : softfloat_tests + extF80_broken = ['lt_quiet', 'rem'].contains(k) + test('fp-test-' + k, fptest, + args: fptest_args + fptest_rounding_args + + ['f16_' + k, 'f32_' + k, 'f64_' + k, 'f128_' + k] + + (extF80_broken ? [] : ['extF80_' + k]), + suite: ['softfloat', 'softfloat-' + v]) +endforeach +test('fp-test-mulAdd', fptest, + # no fptest_rounding_args + args: fptest_args + + ['f16_mulAdd', 'f32_mulAdd', 'f64_mulAdd', 'f128_mulAdd'], + suite: ['softfloat-slow', 'softfloat-ops-slow'], timeout: 60) + +fpbench = executable( + 'fp-bench', + ['fp-bench.c', '../../fpu/softfloat.c'], + link_with: [libtestfloat, libsoftfloat], + dependencies: [qemuutil], + include_directories: [sfinc, include_directories(tfdir)], + c_args: fpcflags, +) diff --git a/tests/fp/wrap.inc.c b/tests/fp/wrap.c.inc similarity index 100% rename from tests/fp/wrap.inc.c rename to tests/fp/wrap.c.inc diff --git a/tests/include/meson.build b/tests/include/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..9abba308fa081bd4c910e429131db3e824ef5724 --- /dev/null +++ b/tests/include/meson.build @@ -0,0 +1,16 @@ +# an extra target to workaround meson limitation on output files location +test_qapi_outputs_extra = [ + 'test-qapi-commands-sub-module.c', + 'test-qapi-commands-sub-module.h', + 'test-qapi-events-sub-module.c', + 'test-qapi-events-sub-module.h', + 'test-qapi-types-sub-module.c', + 'test-qapi-types-sub-module.h', + 'test-qapi-visit-sub-module.c', + 'test-qapi-visit-sub-module.h', +] + +test_qapi_files_extra = custom_target('QAPI test (include)', + output: test_qapi_outputs_extra, + input: test_qapi_files, + command: 'true') diff --git a/tests/io-channel-helpers.c b/tests/io-channel-helpers.c index ab988ef4fe138f3a16f0402b113755954d9ada96..ff156ed3c4a11baf065801faacb14d55f1657bfd 100644 --- a/tests/io-channel-helpers.c +++ b/tests/io-channel-helpers.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/io-channel-helpers.h b/tests/io-channel-helpers.h index bb2de6fbb97962863ba01a3642f4cce032f6f5ee..3d14043710df69714d2c867e3ba20fd38061182e 100644 --- a/tests/io-channel-helpers.h +++ b/tests/io-channel-helpers.h @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/iothread.c b/tests/iothread.c index d3a2ee9a014c3ae88fd9a25aa2e2da66cb932abc..afde12b4efb53d55ff7ed1c69ae1aaa0f8b5e8e7 100644 --- a/tests/iothread.c +++ b/tests/iothread.c @@ -74,7 +74,7 @@ static void *iothread_run(void *opaque) qemu_cond_signal(&iothread->init_done_cond); qemu_mutex_unlock(&iothread->init_done_lock); - while (!atomic_read(&iothread->stopping)) { + while (!qatomic_read(&iothread->stopping)) { aio_poll(iothread->ctx, true); } diff --git a/tests/keys/vagrant b/tests/keys/vagrant new file mode 100644 index 0000000000000000000000000000000000000000..7d6a083909e03080065e9a93a37b4ae7b8cf8ecd --- /dev/null +++ b/tests/keys/vagrant @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzI +w+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoP +kcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2 +hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NO +Td0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcW +yLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQIBIwKCAQEA4iqWPJXtzZA68mKd +ELs4jJsdyky+ewdZeNds5tjcnHU5zUYE25K+ffJED9qUWICcLZDc81TGWjHyAqD1 +Bw7XpgUwFgeUJwUlzQurAv+/ySnxiwuaGJfhFM1CaQHzfXphgVml+fZUvnJUTvzf +TK2Lg6EdbUE9TarUlBf/xPfuEhMSlIE5keb/Zz3/LUlRg8yDqz5w+QWVJ4utnKnK +iqwZN0mwpwU7YSyJhlT4YV1F3n4YjLswM5wJs2oqm0jssQu/BT0tyEXNDYBLEF4A +sClaWuSJ2kjq7KhrrYXzagqhnSei9ODYFShJu8UWVec3Ihb5ZXlzO6vdNQ1J9Xsf +4m+2ywKBgQD6qFxx/Rv9CNN96l/4rb14HKirC2o/orApiHmHDsURs5rUKDx0f9iP +cXN7S1uePXuJRK/5hsubaOCx3Owd2u9gD6Oq0CsMkE4CUSiJcYrMANtx54cGH7Rk +EjFZxK8xAv1ldELEyxrFqkbE4BKd8QOt414qjvTGyAK+OLD3M2QdCQKBgQDtx8pN +CAxR7yhHbIWT1AH66+XWN8bXq7l3RO/ukeaci98JfkbkxURZhtxV/HHuvUhnPLdX +3TwygPBYZFNo4pzVEhzWoTtnEtrFueKxyc3+LjZpuo+mBlQ6ORtfgkr9gBVphXZG +YEzkCD3lVdl8L4cw9BVpKrJCs1c5taGjDgdInQKBgHm/fVvv96bJxc9x1tffXAcj +3OVdUN0UgXNCSaf/3A/phbeBQe9xS+3mpc4r6qvx+iy69mNBeNZ0xOitIjpjBo2+ +dBEjSBwLk5q5tJqHmy/jKMJL4n9ROlx93XS+njxgibTvU6Fp9w+NOFD/HvxB3Tcz +6+jJF85D5BNAG3DBMKBjAoGBAOAxZvgsKN+JuENXsST7F89Tck2iTcQIT8g5rwWC +P9Vt74yboe2kDT531w8+egz7nAmRBKNM751U/95P9t88EDacDI/Z2OwnuFQHCPDF +llYOUI+SpLJ6/vURRbHSnnn8a/XG+nzedGH5JGqEJNQsz+xT2axM0/W/CRknmGaJ +kda/AoGANWrLCz708y7VYgAtW2Uf1DPOIYMdvo6fxIB5i9ZfISgcJ/bbCUkFrhoH ++vq/5CIWxCPp0f85R4qxxQ5ihxJ0YDQT9Jpx4TMss4PSavPaBH3RXow5Ohe+bYoQ +NE5OgEXk2wVfZczCZpigBKbKZHNYcelXtTt/nP3rsCuGcM4h53s= +-----END RSA PRIVATE KEY----- diff --git a/tests/keys/vagrant.pub b/tests/keys/vagrant.pub new file mode 100644 index 0000000000000000000000000000000000000000..b8d012d787f5027f70b99ee807ba1d539bfae8e9 --- /dev/null +++ b/tests/keys/vagrant.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== well-known vagrant key for qemu-test, do not use on any machine exposed to an external network diff --git a/tests/meson.build b/tests/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..afeb6be689407feef77fb05c39fb9d5409652c15 --- /dev/null +++ b/tests/meson.build @@ -0,0 +1,290 @@ +py3 = import('python').find_installation() + +qht_bench = executable('qht-bench', + sources: 'qht-bench.c', + dependencies: [qemuutil]) + +executable('atomic_add-bench', + sources: files('atomic_add-bench.c'), + dependencies: [qemuutil], + build_by_default: false) + +executable('atomic64-bench', + sources: files('atomic64-bench.c'), + dependencies: [qemuutil], + build_by_default: false) + +test_qapi_outputs = [ + 'qapi-builtin-types.c', + 'qapi-builtin-types.h', + 'qapi-builtin-visit.c', + 'qapi-builtin-visit.h', + 'test-qapi-commands-sub-sub-module.c', + 'test-qapi-commands-sub-sub-module.h', + 'test-qapi-commands.c', + 'test-qapi-commands.h', + 'test-qapi-emit-events.c', + 'test-qapi-emit-events.h', + 'test-qapi-events-sub-sub-module.c', + 'test-qapi-events-sub-sub-module.h', + 'test-qapi-events.c', + 'test-qapi-events.h', + 'test-qapi-init-commands.c', + 'test-qapi-init-commands.h', + 'test-qapi-introspect.c', + 'test-qapi-introspect.h', + 'test-qapi-types-sub-sub-module.c', + 'test-qapi-types-sub-sub-module.h', + 'test-qapi-types.c', + 'test-qapi-types.h', + 'test-qapi-visit-sub-sub-module.c', + 'test-qapi-visit-sub-sub-module.h', + 'test-qapi-visit.c', + 'test-qapi-visit.h', +] + +test_qapi_files = custom_target('Test QAPI files', + output: test_qapi_outputs, + input: files('qapi-schema/qapi-schema-test.json', + 'qapi-schema/include/sub-module.json', + 'qapi-schema/sub-sub-module.json'), + command: [ qapi_gen, '-o', meson.current_build_dir(), + '-b', '-p', 'test-', '@INPUT0@' ], + depend_files: qapi_gen_depends) + +# meson doesn't like generated output in other directories +# perhaps change qapi_gen to replace / with _, like Meson itself does? +subdir('include') + +test_qapi_sources = [] +test_qapi_headers = [] +i = 0 +foreach o: test_qapi_files.to_list() + test_qapi_files_extra.to_list() + if o.full_path().endswith('.h') + test_qapi_headers += o + endif + test_qapi_sources += o +endforeach + +libtestqapi = static_library('testqapi', sources: [genh, test_qapi_sources]) +testqapi = declare_dependency(link_with: libtestqapi, sources: [genh, test_qapi_headers]) + +testblock = declare_dependency(dependencies: [block], sources: 'iothread.c') + +tests = { + 'check-block-qdict': [], + 'check-qdict': [], + 'check-qnum': [], + 'check-qstring': [], + 'check-qlist': [], + 'check-qnull': [], + 'check-qobject': [], + 'check-qjson': [], + 'check-qlit': [], + 'test-qobject-output-visitor': [testqapi], + 'test-clone-visitor': [testqapi], + 'test-qobject-input-visitor': [testqapi], + 'test-string-input-visitor': [testqapi], + 'test-string-output-visitor': [testqapi], + 'test-qmp-event': [testqapi], + 'test-opts-visitor': [testqapi], + 'test-visitor-serialization': [testqapi], + 'test-bitmap': [], + # all code tested by test-x86-cpuid is inside topology.h + 'test-x86-cpuid': [], + 'test-cutils': [], + 'test-shift128': [], + 'test-mul64': [], + # all code tested by test-int128 is inside int128.h + 'test-int128': [], + 'rcutorture': [], + 'test-rcu-list': [], + 'test-rcu-simpleq': [], + 'test-rcu-tailq': [], + 'test-rcu-slist': [], + 'test-qdist': [], + 'test-qht': [], + 'test-bitops': [], + 'test-bitcnt': [], + 'test-qgraph': ['qtest/libqos/qgraph.c'], + 'check-qom-interface': [qom], + 'check-qom-proplist': [qom], + 'test-qemu-opts': [], + 'test-keyval': [testqapi], + 'test-logging': [], + 'test-uuid': [], + 'ptimer-test': ['ptimer-test-stubs.c', meson.source_root() / 'hw/core/ptimer.c'], + 'test-qapi-util': [], +} + +test_deps = { + 'test-qht-par': qht_bench, +} + +benchs = {} + +if have_block + tests += { + 'test-coroutine': [testblock], + 'test-aio': [testblock], + 'test-aio-multithread': [testblock], + 'test-throttle': [testblock], + 'test-thread-pool': [testblock], + 'test-hbitmap': [testblock], + 'test-bdrv-drain': [testblock], + 'test-bdrv-graph-mod': [testblock], + 'test-blockjob': [testblock], + 'test-blockjob-txn': [testblock], + 'test-block-backend': [testblock], + 'test-block-iothread': [testblock], + 'test-write-threshold': [testblock], + 'test-crypto-hash': [crypto], + 'test-crypto-hmac': [crypto], + 'test-crypto-cipher': [crypto], + 'test-crypto-secret': [crypto, keyutils], + 'test-authz-simple': [authz], + 'test-authz-list': [authz], + 'test-authz-listfile': [authz], + 'test-io-task': [testblock], + 'test-io-channel-socket': ['socket-helpers.c', 'io-channel-helpers.c', io], + 'test-io-channel-file': ['io-channel-helpers.c', io], + 'test-io-channel-command': ['io-channel-helpers.c', io], + 'test-io-channel-buffer': ['io-channel-helpers.c', io], + 'test-crypto-ivgen': [io], + 'test-crypto-afsplit': [io], + 'test-crypto-block': [io], + } + if 'CONFIG_GNUTLS' in config_host and \ + 'CONFIG_TASN1' in config_host and \ + 'CONFIG_POSIX' in config_host + tests += { + 'test-crypto-tlscredsx509': ['crypto-tls-x509-helpers.c', 'pkix_asn1_tab.c', + tasn1, crypto], + 'test-crypto-tlssession': ['crypto-tls-x509-helpers.c', 'pkix_asn1_tab.c', 'crypto-tls-psk-helpers.c', + tasn1, crypto], + 'test-io-channel-tls': ['io-channel-helpers.c', 'crypto-tls-x509-helpers.c', 'pkix_asn1_tab.c', + tasn1, io, crypto]} + endif + if 'CONFIG_AUTH_PAM' in config_host + tests += {'test-authz-pam': [authz]} + endif + if 'CONFIG_QEMU_PRIVATE_XTS' in config_host + tests += {'test-crypto-xts': [crypto, io]} + endif + if 'CONFIG_POSIX' in config_host + tests += {'test-image-locking': [testblock]} + endif + if 'CONFIG_REPLICATION' in config_host + tests += {'test-replication': [testblock]} + endif + if 'CONFIG_NETTLE' in config_host or 'CONFIG_GCRYPT' in config_host + tests += {'test-crypto-pbkdf': [io]} + endif + if 'CONFIG_EPOLL_CREATE1' in config_host + tests += {'test-fdmon-epoll': [testblock]} + endif + benchs += { + 'benchmark-crypto-hash': [crypto], + 'benchmark-crypto-hmac': [crypto], + 'benchmark-crypto-cipher': [crypto], + } +endif + +if have_system + tests += { + 'test-iov': [], + 'test-qmp-cmds': [testqapi], + 'test-xbzrle': [migration], + 'test-timed-average': [], + 'test-util-sockets': ['socket-helpers.c'], + 'test-base64': [], + 'test-bufferiszero': [], + 'test-vmstate': [migration, io] + } + if 'CONFIG_INOTIFY1' in config_host + tests += {'test-util-filemonitor': []} + endif + + # Some tests: test-char, test-qdev-global-props, and test-qga, + # are not runnable under TSan due to a known issue. + # https://github.com/google/sanitizers/issues/1116 + if 'CONFIG_TSAN' not in config_host + if 'CONFIG_POSIX' in config_host + tests += { + 'test-char': ['socket-helpers.c', qom, io, chardev] + } + endif + + tests += { + 'test-qdev-global-props': [qom, hwcore, testqapi] + } + endif +endif + +if 'CONFIG_TSAN' not in config_host and \ + 'CONFIG_GUEST_AGENT' in config_host and \ + 'CONFIG_LINUX' in config_host + tests += {'test-qga': ['qtest/libqtest.c']} + test_deps += {'test-qga': qga} +endif + +test_env = environment() +test_env.set('G_TEST_SRCDIR', meson.current_source_dir()) +test_env.set('G_TEST_BUILDDIR', meson.current_build_dir()) + +foreach test_name, extra: tests + src = [test_name + '.c'] + deps = [qemuutil] + if extra.length() > 0 + # use a sourceset to quickly separate sources and deps + test_ss = ss.source_set() + test_ss.add(extra) + src += test_ss.all_sources() + deps += test_ss.all_dependencies() + endif + exe = executable(test_name, src, genh, dependencies: deps) + + test(test_name, exe, + depends: test_deps.get(test_name, []), + env: test_env, + args: ['--tap', '-k'], + protocol: 'tap', + suite: ['unit']) +endforeach + +foreach bench_name, deps: benchs + exe = executable(bench_name, bench_name + '.c', + dependencies: [qemuutil] + deps) + benchmark(bench_name, exe, + args: ['--tap', '-k'], + protocol: 'tap', + suite: ['speed']) +endforeach + +if have_tools and 'CONFIG_VHOST_USER' in config_host and 'CONFIG_LINUX' in config_host + executable('vhost-user-bridge', + sources: files('vhost-user-bridge.c'), + link_with: [libvhost_user], + dependencies: [qemuutil]) +endif + +if have_system and 'CONFIG_POSIX' in config_host + subdir('qemu-iotests') +endif + +test('decodetree', sh, + args: [ files('decode/check.sh'), config_host['PYTHON'], files('../scripts/decodetree.py') ], + workdir: meson.current_source_dir() / 'decode', + suite: 'decodetree') + +subdir('fp') + +if not get_option('tcg').disabled() + if 'CONFIG_PLUGIN' in config_host + subdir('plugin') + endif +endif + +subdir('qapi-schema') +subdir('qtest') +subdir('migration') diff --git a/tests/migration/.gitignore b/tests/migration/.gitignore deleted file mode 100644 index 84f37552e44ad9623794c42fa298007cda888b40..0000000000000000000000000000000000000000 --- a/tests/migration/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -initrd-stress.img -stress diff --git a/tests/migration/guestperf-batch.py b/tests/migration/guestperf-batch.py index cb150ce804642109ac795c01b20382aa0390a492..ab6bdb9d384415514f570a1ffffaf4111b661de9 100755 --- a/tests/migration/guestperf-batch.py +++ b/tests/migration/guestperf-batch.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # # Migration test batch comparison invokation # @@ -7,7 +7,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/migration/guestperf-plot.py b/tests/migration/guestperf-plot.py index d70bb7a557e792e0bd986358499e1860f1ac2d7a..32977b4bf69c6c315e03410c4a00123ef6561cb6 100755 --- a/tests/migration/guestperf-plot.py +++ b/tests/migration/guestperf-plot.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # # Migration test graph plotting command # @@ -7,7 +7,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/migration/guestperf.py b/tests/migration/guestperf.py index 99b027e8ba36bdcd3d671eeadac34d78a5096ff8..e8cc127fd0280707ade21f0494dba7c8d42ceebe 100755 --- a/tests/migration/guestperf.py +++ b/tests/migration/guestperf.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # # Migration test direct invokation command # @@ -7,7 +7,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/migration/guestperf/comparison.py b/tests/migration/guestperf/comparison.py index d0b7df97c8e69ebd9acd1ac6e5436d870f6eb645..ba2edbe546b70993ee413e0fee5a5d3f20eb8a39 100644 --- a/tests/migration/guestperf/comparison.py +++ b/tests/migration/guestperf/comparison.py @@ -6,7 +6,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/migration/guestperf/engine.py b/tests/migration/guestperf/engine.py index fd63c666015a2a94467de3d966d1c6be1d6d6e3c..e2a214bdab0c024bcf733725d5e42ce52ebcca3d 100644 --- a/tests/migration/guestperf/engine.py +++ b/tests/migration/guestperf/engine.py @@ -6,7 +6,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/migration/guestperf/hardware.py b/tests/migration/guestperf/hardware.py index a66c9dd1808bd9cd788243a9f18be557f560efdf..3145785ffd772a85792b6e03d6b1c0518d786df1 100644 --- a/tests/migration/guestperf/hardware.py +++ b/tests/migration/guestperf/hardware.py @@ -6,7 +6,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/migration/guestperf/plot.py b/tests/migration/guestperf/plot.py index 34cebd54ba376ee7b556d54e4654336a4f097b60..30b3f668d063ffc6061c59ad292af7b1de390efd 100644 --- a/tests/migration/guestperf/plot.py +++ b/tests/migration/guestperf/plot.py @@ -6,7 +6,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/migration/guestperf/progress.py b/tests/migration/guestperf/progress.py index 46d2157b83acfa3ff2a0022d1813989cc45598e4..ab1ee5727399103ff9765537047d68f8a714a95e 100644 --- a/tests/migration/guestperf/progress.py +++ b/tests/migration/guestperf/progress.py @@ -6,7 +6,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/migration/guestperf/report.py b/tests/migration/guestperf/report.py index 6a1f9714966024c170c0b7379cb39518b61c8455..1efd40c8680368b6f0d5f8e48f88213ec25b806a 100644 --- a/tests/migration/guestperf/report.py +++ b/tests/migration/guestperf/report.py @@ -6,7 +6,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/migration/guestperf/scenario.py b/tests/migration/guestperf/scenario.py index 705c2e864fbac3a12e475ebd1e5f030a3a437db6..28ef36c26db251822d2fcfc2622e82ec011b242a 100644 --- a/tests/migration/guestperf/scenario.py +++ b/tests/migration/guestperf/scenario.py @@ -6,7 +6,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/migration/guestperf/shell.py b/tests/migration/guestperf/shell.py index 5bcc066bb9815383813daf72ac8aa453eea11554..f838888809c1199b2234a8b973e666e7b135a256 100644 --- a/tests/migration/guestperf/shell.py +++ b/tests/migration/guestperf/shell.py @@ -6,7 +6,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/migration/guestperf/timings.py b/tests/migration/guestperf/timings.py index f94d80989692fff9bbd1513877244baa9e3309ef..2374010c6c986faf2889564d1250d2e16f645004 100644 --- a/tests/migration/guestperf/timings.py +++ b/tests/migration/guestperf/timings.py @@ -6,7 +6,7 @@ # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/migration/initrd-stress.sh b/tests/migration/initrd-stress.sh new file mode 100755 index 0000000000000000000000000000000000000000..0f20ac29a6c6d86215a3632961d338ece5558ed9 --- /dev/null +++ b/tests/migration/initrd-stress.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +INITRD="$1" +STRESS="$2" + +INITRD_DIR=$(mktemp -d -p '' "initrd-stress.XXXXXX") +trap 'rm -rf $INITRD_DIR' EXIT + +cp "$STRESS" "$INITRD_DIR/init" +(cd "$INITRD_DIR" && (find | cpio --quiet -o -H newc | gzip -9)) > "$INITRD" diff --git a/tests/migration/meson.build b/tests/migration/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..f215ee7d3a38068b4fd2e40ecfca521b463df0dd --- /dev/null +++ b/tests/migration/meson.build @@ -0,0 +1,14 @@ +stress = executable( + 'stress', + files('stress.c'), + dependencies: [glib], + link_args: ['-static'], + build_by_default: false, +) + +custom_target( + 'initrd-stress.img', + output: 'initrd-stress.img', + input: stress, + command: [find_program('initrd-stress.sh'), '@OUTPUT@', '@INPUT@'] +) diff --git a/tests/migration/stress.c b/tests/migration/stress.c index 0c239646934482d097d7d9634f1dd068899aed43..de45e8e49082e9d8fa9d1843210ce8db0173b991 100644 --- a/tests/migration/stress.c +++ b/tests/migration/stress.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -29,10 +29,12 @@ const char *argv0; #define PAGE_SIZE 4096 +#ifndef CONFIG_GETTID static int gettid(void) { return syscall(SYS_gettid); } +#endif static __attribute__((noreturn)) void exit_failure(void) { @@ -47,19 +49,6 @@ static __attribute__((noreturn)) void exit_failure(void) } } -static __attribute__((noreturn)) void exit_success(void) -{ - if (getpid() == 1) { - sync(); - reboot(RB_POWER_OFF); - fprintf(stderr, "%s (%05d): ERROR: cannot reboot: %s\n", - argv0, gettid(), strerror(errno)); - abort(); - } else { - exit(0); - } -} - static int get_command_arg_str(const char *name, char **val) { @@ -167,29 +156,17 @@ static unsigned long long now(void) return (tv.tv_sec * 1000ull) + (tv.tv_usec / 1000ull); } -static int stressone(unsigned long long ramsizeMB) +static void stressone(unsigned long long ramsizeMB) { size_t pagesPerMB = 1024 * 1024 / PAGE_SIZE; - char *ram = malloc(ramsizeMB * 1024 * 1024); + g_autofree char *ram = g_malloc(ramsizeMB * 1024 * 1024); char *ramptr; size_t i, j, k; - char *data = malloc(PAGE_SIZE); + g_autofree char *data = g_malloc(PAGE_SIZE); char *dataptr; size_t nMB = 0; unsigned long long before, after; - if (!ram) { - fprintf(stderr, "%s (%05d): ERROR: cannot allocate %llu MB of RAM: %s\n", - argv0, gettid(), ramsizeMB, strerror(errno)); - return -1; - } - if (!data) { - fprintf(stderr, "%s (%d): ERROR: cannot allocate %d bytes of RAM: %s\n", - argv0, gettid(), PAGE_SIZE, strerror(errno)); - free(ram); - return -1; - } - /* We don't care about initial state, but we do want * to fault it all into RAM, otherwise the first iter * of the loop below will be quite slow. We can't use @@ -198,9 +175,7 @@ static int stressone(unsigned long long ramsizeMB) memset(ram, 0xfe, ramsizeMB * 1024 * 1024); if (random_bytes(data, PAGE_SIZE) < 0) { - free(ram); - free(data); - return -1; + return; } before = now(); @@ -227,9 +202,6 @@ static int stressone(unsigned long long ramsizeMB) } } } - - free(data); - free(ram); } @@ -242,7 +214,7 @@ static void *stressthread(void *arg) return NULL; } -static int stress(unsigned long long ramsizeGB, int ncpus) +static void stress(unsigned long long ramsizeGB, int ncpus) { size_t i; unsigned long long ramsizeMB = ramsizeGB * 1024 / ncpus; @@ -255,8 +227,6 @@ static int stress(unsigned long long ramsizeGB, int ncpus) } stressone(ramsizeMB); - - return 0; } @@ -352,8 +322,7 @@ int main(int argc, char **argv) fprintf(stdout, "%s (%05d): INFO: RAM %llu GiB across %d CPUs\n", argv0, gettid(), ramsizeGB, ncpus); - if (stress(ramsizeGB, ncpus) < 0) - exit_failure(); + stress(ramsizeGB, ncpus); - exit_success(); + exit_failure(); } diff --git a/tests/multiboot/.gitignore b/tests/multiboot/.gitignore deleted file mode 100644 index 93ef99800b6d0f11971f3336e6e7cf8341ca9f02..0000000000000000000000000000000000000000 --- a/tests/multiboot/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.bin -*.elf -test.out diff --git a/tests/multiboot/run_test.sh b/tests/multiboot/run_test.sh index 98df91e6af98451760e55d949686c4712813287a..f968bf797e0a8e31bec3de0e9fd4f2e181dbfc8f 100755 --- a/tests/multiboot/run_test.sh +++ b/tests/multiboot/run_test.sh @@ -20,7 +20,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -QEMU=${QEMU:-"../../x86_64-softmmu/qemu-system-x86_64"} +QEMU=${QEMU:-"../../qemu-system-x86_64"} run_qemu() { local kernel=$1 diff --git a/tests/plugin/bb.c b/tests/plugin/bb.c index df19fd359df3536d2eb9e4bf4dd22bdf30a0c812..de09bdde4e4b14875cebe6886efd7750fb3e8906 100644 --- a/tests/plugin/bb.c +++ b/tests/plugin/bb.c @@ -16,35 +16,79 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; -static uint64_t bb_count; -static uint64_t insn_count; +typedef struct { + GMutex lock; + int index; + uint64_t bb_count; + uint64_t insn_count; +} CPUCount; + +/* Used by the inline & linux-user counts */ static bool do_inline; +static CPUCount inline_count; + +/* Dump running CPU total on idle? */ +static bool idle_report; +static GPtrArray *counts; +static int max_cpus; + +static void gen_one_cpu_report(CPUCount *count, GString *report) +{ + if (count->bb_count) { + g_string_append_printf(report, "CPU%d: " + "bb's: %" PRIu64", insns: %" PRIu64 "\n", + count->index, + count->bb_count, count->insn_count); + } +} static void plugin_exit(qemu_plugin_id_t id, void *p) { - g_autofree gchar *out = g_strdup_printf( - "bb's: %" PRIu64", insns: %" PRIu64 "\n", - bb_count, insn_count); - qemu_plugin_outs(out); + g_autoptr(GString) report = g_string_new(""); + + if (do_inline || !max_cpus) { + g_string_printf(report, "bb's: %" PRIu64", insns: %" PRIu64 "\n", + inline_count.bb_count, inline_count.insn_count); + } else { + g_ptr_array_foreach(counts, (GFunc) gen_one_cpu_report, report); + } + qemu_plugin_outs(report->str); +} + +static void vcpu_idle(qemu_plugin_id_t id, unsigned int cpu_index) +{ + CPUCount *count = g_ptr_array_index(counts, cpu_index); + g_autoptr(GString) report = g_string_new(""); + gen_one_cpu_report(count, report); + + if (report->len > 0) { + g_string_prepend(report, "Idling "); + qemu_plugin_outs(report->str); + } } static void vcpu_tb_exec(unsigned int cpu_index, void *udata) { - unsigned long n_insns = (unsigned long)udata; + CPUCount *count = max_cpus ? + g_ptr_array_index(counts, cpu_index) : &inline_count; - insn_count += n_insns; - bb_count++; + uintptr_t n_insns = (uintptr_t)udata; + g_mutex_lock(&count->lock); + count->insn_count += n_insns; + count->bb_count++; + g_mutex_unlock(&count->lock); } static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) { - unsigned long n_insns = qemu_plugin_tb_n_insns(tb); + size_t n_insns = qemu_plugin_tb_n_insns(tb); if (do_inline) { qemu_plugin_register_vcpu_tb_exec_inline(tb, QEMU_PLUGIN_INLINE_ADD_U64, - &bb_count, 1); + &inline_count.bb_count, 1); qemu_plugin_register_vcpu_tb_exec_inline(tb, QEMU_PLUGIN_INLINE_ADD_U64, - &insn_count, n_insns); + &inline_count.insn_count, + n_insns); } else { qemu_plugin_register_vcpu_tb_exec_cb(tb, vcpu_tb_exec, QEMU_PLUGIN_CB_NO_REGS, @@ -56,8 +100,35 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, int argc, char **argv) { - if (argc && strcmp(argv[0], "inline") == 0) { - do_inline = true; + int i; + + for (i = 0; i < argc; i++) { + char *opt = argv[i]; + if (g_strcmp0(opt, "inline") == 0) { + do_inline = true; + } else if (g_strcmp0(opt, "idle") == 0) { + idle_report = true; + } else { + fprintf(stderr, "option parsing failed: %s\n", opt); + return -1; + } + } + + if (info->system_emulation && !do_inline) { + max_cpus = info->system.max_vcpus; + counts = g_ptr_array_new(); + for (i = 0; i < max_cpus; i++) { + CPUCount *count = g_new0(CPUCount, 1); + g_mutex_init(&count->lock); + count->index = i; + g_ptr_array_add(counts, count); + } + } else if (!do_inline) { + g_mutex_init(&inline_count.lock); + } + + if (idle_report) { + qemu_plugin_register_vcpu_idle_cb(id, vcpu_idle); } qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); diff --git a/tests/plugin/mem.c b/tests/plugin/mem.c index 878abf09d19b256ed9c63a540d52ffbe6c6ba5af..4725bd851d8213ad2e185fc5035cffe1139f36d0 100644 --- a/tests/plugin/mem.c +++ b/tests/plugin/mem.c @@ -28,7 +28,7 @@ static void plugin_exit(qemu_plugin_id_t id, void *p) g_string_printf(out, "mem accesses: %" PRIu64 "\n", mem_count); if (do_haddr) { - g_string_append_printf(out, "io accesses: %" PRIu64 "\n", mem_count); + g_string_append_printf(out, "io accesses: %" PRIu64 "\n", io_count); } qemu_plugin_outs(out->str); } diff --git a/tests/plugin/meson.build b/tests/plugin/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..1eacfa6e35522a9c4dd1326744e8e2e2645bdf7a --- /dev/null +++ b/tests/plugin/meson.build @@ -0,0 +1,7 @@ +t = [] +foreach i : ['bb', 'empty', 'insn', 'mem'] + t += shared_module(i, files(i + '.c'), + include_directories: '../../include/qemu', + dependencies: glib) +endforeach +alias_target('test-plugins', t) diff --git a/tests/ptimer-test-stubs.c b/tests/ptimer-test-stubs.c index ed393d9082e4e6177fa5ca528e48fd12833fde0c..7f801a4d09e2968616604449e806f0be228d1ff5 100644 --- a/tests/ptimer-test-stubs.c +++ b/tests/ptimer-test-stubs.c @@ -12,6 +12,7 @@ #include "qemu/main-loop.h" #include "sysemu/replay.h" #include "migration/vmstate.h" +#include "sysemu/cpu-timers.h" #include "ptimer-test.h" @@ -30,8 +31,8 @@ QEMUTimerListGroup main_loop_tlg; int64_t ptimer_test_time_ns; -/* Do not artificially limit period - see hw/core/ptimer.c. */ -int use_icount = 1; +/* under qtest_enabled(), will not artificially limit period - see hw/core/ptimer.c. */ +int use_icount; bool qtest_allowed; void timer_init_full(QEMUTimer *ts, @@ -121,8 +122,3 @@ void qemu_bh_delete(QEMUBH *bh) { g_free(bh); } - -void replay_bh_schedule_event(QEMUBH *bh) -{ - bh->cb(bh->opaque); -} diff --git a/tests/qapi-schema/doc-bad-indent.err b/tests/qapi-schema/doc-bad-indent.err new file mode 100644 index 0000000000000000000000000000000000000000..67844539bd215e0c57df76e78380dd6a1dc9b18b --- /dev/null +++ b/tests/qapi-schema/doc-bad-indent.err @@ -0,0 +1 @@ +doc-bad-indent.json:6:1: unexpected de-indent (expected at least 4 spaces) diff --git a/tests/qapi-schema/doc-bad-indent.json b/tests/qapi-schema/doc-bad-indent.json new file mode 100644 index 0000000000000000000000000000000000000000..edde8f21dc7104222c85ecdb11615fb6ccba910c --- /dev/null +++ b/tests/qapi-schema/doc-bad-indent.json @@ -0,0 +1,8 @@ +# Multiline doc comments should have consistent indentation + +## +# @foo: +# @a: line one +# line two is wrongly indented +## +{ 'command': 'foo', 'data': { 'a': 'int' } } diff --git a/build/__COVER__ b/tests/qapi-schema/doc-bad-indent.out similarity index 100% rename from build/__COVER__ rename to tests/qapi-schema/doc-bad-indent.out diff --git a/tests/qapi-schema/doc-bad-section.err b/tests/qapi-schema/doc-bad-section.err index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..785cacc08c4987ed677494a1ab33e468876245cc 100644 --- a/tests/qapi-schema/doc-bad-section.err +++ b/tests/qapi-schema/doc-bad-section.err @@ -0,0 +1 @@ +doc-bad-section.json:5:1: unexpected '=' markup in definition documentation diff --git a/tests/qapi-schema/doc-bad-section.json b/tests/qapi-schema/doc-bad-section.json index 560df4b0878547d99ce012a4aa9110b0c0a72837..8175d95867e03692462f6857bc1d505a027e37c2 100644 --- a/tests/qapi-schema/doc-bad-section.json +++ b/tests/qapi-schema/doc-bad-section.json @@ -1,9 +1,8 @@ # = section within an expression comment -# BUG: not rejected ## # @Enum: -# == Produces *invalid* texinfo +# == No good here # @one: The _one_ {and only} # # @two is undocumented diff --git a/tests/qapi-schema/doc-bad-section.out b/tests/qapi-schema/doc-bad-section.out index 367e2a1c3eb2bb5e6054930787e1113f9d0fd41d..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/tests/qapi-schema/doc-bad-section.out +++ b/tests/qapi-schema/doc-bad-section.out @@ -1,24 +0,0 @@ -module None -object q_empty -enum QType - prefix QTYPE - member none - member qnull - member qnum - member qstring - member qdict - member qlist - member qbool -module doc-bad-section.json -enum Enum - member one - member two -doc symbol=Enum - body= -== Produces *invalid* texinfo - arg=one -The _one_ {and only} - arg=two - - section=None -@two is undocumented diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json index ddd89d12334e56cbe4962f721f6bee73b2f22e1d..e9af0857db792dd9151a0b80ac2179682121d205 100644 --- a/tests/qapi-schema/doc-good.json +++ b/tests/qapi-schema/doc-good.json @@ -1,4 +1,6 @@ # -*- Mode: Python -*- +# vim: filetype=python +# # Positive QAPI doc comment tests { 'pragma': { 'doc-required': true } } @@ -8,27 +10,27 @@ # # == Subsection # -# *strong* _with emphasis_ +# *with emphasis* # @var {in braces} +# # * List item one -# - Two, multiple +# * Two, multiple # lines # -# 3. Three -# Still in list +# * Three +# Still in list +# +# Not in list # -# Not in list # - Second list -# Note: still in list +# Note: still in list # # Note: not in list +# # 1. Third list # is numbered # -# - another item -# -# | example -# | multiple lines +# 2. another item # # Returns: the King # Since: the first age @@ -66,7 +68,7 @@ ## # @Base: # @base1: -# the first member +# the first member ## { 'struct': 'Base', 'data': { 'base1': 'Enum' } } @@ -114,7 +116,7 @@ ## # @Alternate: # @i: an integer -# @b is undocumented +# @b is undocumented # # Features: # @alt-feat: a feature @@ -132,7 +134,7 @@ # @arg1: the first argument # # @arg2: the second -# argument +# argument # # Features: # @cmd-feat1: a feature @@ -141,6 +143,7 @@ # Returns: @Object # TODO: frobnicate # Notes: +# # - Lorem ipsum dolor sit amet # - Ut enim ad minim veniam # diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out index 6757dd26a2f30bfa80f93f94fd35899e9c3ed0d9..419284dae29b93083aaf8d3927ee6206c8448e35 100644 --- a/tests/qapi-schema/doc-good.out +++ b/tests/qapi-schema/doc-good.out @@ -69,30 +69,31 @@ event EVT-BOXED Object doc freeform body= = Section - +doc freeform + body= == Subsection -*strong* _with emphasis_ +*with emphasis* @var {in braces} + * List item one -- Two, multiple -lines +* Two, multiple + lines -3. Three -Still in list +* Three + Still in list Not in list + - Second list -Note: still in list + Note: still in list Note: not in list -1. Third list -is numbered -- another item +1. Third list + is numbered -| example -| multiple lines +2. another item Returns: the King Since: the first age diff --git a/tests/qapi-schema/doc-good.rst b/tests/qapi-schema/doc-good.rst new file mode 100644 index 0000000000000000000000000000000000000000..1e4c23305a1e779712603284a170c4d663433faa --- /dev/null +++ b/tests/qapi-schema/doc-good.rst @@ -0,0 +1,5 @@ +.. + Test Sphinx manual that pulls in the test schema file. We will generate + a plain-text output file and compare it against a reference. + +.. qapi-doc:: tests/qapi-schema/doc-good.json diff --git a/tests/qapi-schema/doc-good.texi b/tests/qapi-schema/doc-good.texi deleted file mode 100644 index 7f28fb7a0fb5089f822f6798dfaedcc895f460cb..0000000000000000000000000000000000000000 --- a/tests/qapi-schema/doc-good.texi +++ /dev/null @@ -1,319 +0,0 @@ -@c AUTOMATICALLY GENERATED, DO NOT MODIFY - -@section Section - -@subsection Subsection - -@strong{strong} @emph{with emphasis} -@code{var} @{in braces@} -@itemize @bullet -@item -List item one -@item -Two, multiple -lines - -@item -Three -Still in list - -@end itemize - -Not in list -@itemize @minus -@item -Second list -Note: still in list - -@end itemize - -Note: not in list -@enumerate -@item -Third list -is numbered - -@item -another item - -@example -example -@end example - -@example -multiple lines -@end example - - -@end enumerate - -Returns: the King -Since: the first age -Notes: - -@enumerate -@item -Lorem ipsum dolor sit amet - -@item -Ut enim ad minim veniam - -@end enumerate - -Duis aute irure dolor - -Example: - --> in -<- out -Examples: -@itemize @minus -@item -@strong{verbatim} -@item -@{braces@} -@end itemize - - - -@deftp {Enum} Enum - - - -@b{Values:} -@table @asis -@item @code{one} -The @emph{one} @{and only@} -@*@b{If:} @code{defined(IFONE)} -@item @code{two} -Not documented -@end table - -@b{Features:} -@table @asis -@item @code{enum-feat} -Also @emph{one} @{and only@} -@end table -@code{two} is undocumented - -@b{If:} @code{defined(IFCOND)} -@end deftp - - - -@deftp {Object} Base - - - -@b{Members:} -@table @asis -@item @code{base1: Enum} -the first member -@end table - -@end deftp - - - -@deftp {Object} Variant1 - -A paragraph - -Another paragraph (but no @code{var}: line) - -@b{Members:} -@table @asis -@item @code{var1: string} -Not documented -@*@b{If:} @code{defined(IFSTR)} -@end table - -@b{Features:} -@table @asis -@item @code{variant1-feat} -a feature -@item @code{member-feat} -a member feature -@end table - -@end deftp - - - -@deftp {Object} Variant2 - - - -@end deftp - - - -@deftp {Object} Object - - - -@b{Members:} -@table @asis -@item The members of @code{Base} -@item The members of @code{Variant1} when @code{base1} is @t{"one"} -@item The members of @code{Variant2} when @code{base1} is @t{"two"} (@b{If:} @code{IFTWO}) -@end table - -@b{Features:} -@table @asis -@item @code{union-feat1} -a feature -@end table - -@end deftp - - - -@deftp {Object} SugaredUnion - - - -@b{Members:} -@table @asis -@item @code{type} -One of @t{"one"}, @t{"two"} -@item @code{data: Variant1} when @code{type} is @t{"one"} -@item @code{data: Variant2} when @code{type} is @t{"two"} (@b{If:} @code{IFTWO}) -@end table - -@b{Features:} -@table @asis -@item @code{union-feat2} -a feature -@end table - -@end deftp - - - -@deftp {Alternate} Alternate - - - -@b{Members:} -@table @asis -@item @code{i: int} -an integer -@code{b} is undocumented -@item @code{b: boolean} -Not documented -@end table - -@b{Features:} -@table @asis -@item @code{alt-feat} -a feature -@end table - -@end deftp - - -@subsection Another subsection - - -@deftypefn Command {} cmd - - - -@b{Arguments:} -@table @asis -@item @code{arg1: int} -the first argument -@item @code{arg2: string} (optional) -the second -argument -@item @code{arg3: boolean} -Not documented -@end table - -@b{Features:} -@table @asis -@item @code{cmd-feat1} -a feature -@item @code{cmd-feat2} -another feature -@end table - -@b{Note:} -@code{arg3} is undocumented - -@b{Returns:} -@code{Object} - -@b{TODO:} -frobnicate - -@b{Notes:} -@itemize @minus -@item -Lorem ipsum dolor sit amet -@item -Ut enim ad minim veniam - -@end itemize - -Duis aute irure dolor - -@b{Example:} -@example --> in -<- out -@end example - -@b{Examples:} -@example -- *verbatim* -- @{braces@} -@end example - -@b{Since:} -2.10 - -@end deftypefn - - - -@deftypefn Command {} cmd-boxed - -If you're bored enough to read this, go see a video of boxed cats - -@b{Arguments:} the members of @code{Object} - -@b{Features:} -@table @asis -@item @code{cmd-feat1} -a feature -@item @code{cmd-feat2} -another feature -@end table - -@b{Example:} -@example --> in - -<- out -@end example - -@end deftypefn - - - -@deftypefn Event {} EVT-BOXED - - - -@b{Arguments:} the members of @code{Object} - -@b{Features:} -@table @asis -@item @code{feat3} -a feature -@end table - -@end deftypefn - diff --git a/tests/qapi-schema/doc-good.txt b/tests/qapi-schema/doc-good.txt new file mode 100644 index 0000000000000000000000000000000000000000..6ca03d49d0d56548c9b2bf61da94bfbde9d78916 --- /dev/null +++ b/tests/qapi-schema/doc-good.txt @@ -0,0 +1,288 @@ +Section +******* + + +Subsection +========== + +*with emphasis* "var" {in braces} + +* List item one + +* Two, multiple lines + +* Three Still in list + +Not in list + +* Second list Note: still in list + +Note: not in list + +1. Third list is numbered + +2. another item + +Returns: the King Since: the first age Notes: + +1. Lorem ipsum dolor sit amet + +2. Ut enim ad minim veniam + +Duis aute irure dolor + +Example: + +-> in <- out Examples: - *verbatim* - {braces} + + +"Enum" (Enum) +------------- + + +Values +~~~~~~ + +"one" (**If: **"defined(IFONE)") + The _one_ {and only} + +"two" + Not documented + + +Features +~~~~~~~~ + +"enum-feat" + Also _one_ {and only} + +"two" is undocumented + + +If +~~ + +"defined(IFCOND)" + + +"Base" (Object) +--------------- + + +Members +~~~~~~~ + +"base1": "Enum" + the first member + + +"Variant1" (Object) +------------------- + +A paragraph + +Another paragraph (but no "var": line) + + +Members +~~~~~~~ + +"var1": "string" (**If: **"defined(IFSTR)") + Not documented + + +Features +~~~~~~~~ + +"variant1-feat" + a feature + +"member-feat" + a member feature + + +"Variant2" (Object) +------------------- + + +"Object" (Object) +----------------- + + +Members +~~~~~~~ + +The members of "Base" +The members of "Variant1" when "base1" is ""one"" +The members of "Variant2" when "base1" is ""two"" (**If: **"IFTWO") + +Features +~~~~~~~~ + +"union-feat1" + a feature + + +"SugaredUnion" (Object) +----------------------- + + +Members +~~~~~~~ + +"type" + One of "one", "two" + +"data": "Variant1" when "type" is ""one"" +"data": "Variant2" when "type" is ""two"" (**If: **"IFTWO") + +Features +~~~~~~~~ + +"union-feat2" + a feature + + +"Alternate" (Alternate) +----------------------- + + +Members +~~~~~~~ + +"i": "int" + an integer "b" is undocumented + +"b": "boolean" + Not documented + + +Features +~~~~~~~~ + +"alt-feat" + a feature + + +Another subsection +================== + + +"cmd" (Command) +--------------- + + +Arguments +~~~~~~~~~ + +"arg1": "int" + the first argument + +"arg2": "string" (optional) + the second argument + +"arg3": "boolean" + Not documented + + +Features +~~~~~~~~ + +"cmd-feat1" + a feature + +"cmd-feat2" + another feature + + +Note +~~~~ + +"arg3" is undocumented + + +Returns +~~~~~~~ + +"Object" + + +TODO +~~~~ + +frobnicate + + +Notes +~~~~~ + +* Lorem ipsum dolor sit amet + +* Ut enim ad minim veniam + +Duis aute irure dolor + + +Example +~~~~~~~ + + -> in + <- out + + +Examples +~~~~~~~~ + + - *verbatim* + - {braces} + + +Since +~~~~~ + +2.10 + + +"cmd-boxed" (Command) +--------------------- + +If you're bored enough to read this, go see a video of boxed cats + + +Arguments +~~~~~~~~~ + +The members of "Object" + +Features +~~~~~~~~ + +"cmd-feat1" + a feature + +"cmd-feat2" + another feature + + +Example +~~~~~~~ + + -> in + + <- out + + +"EVT-BOXED" (Event) +------------------- + + +Arguments +~~~~~~~~~ + +The members of "Object" + +Features +~~~~~~~~ + +"feat3" + a feature diff --git a/tests/qapi-schema/include/sub-module.json b/tests/qapi-schema/include/sub-module.json index afdb267228fa332a894a978151312cc07d8bfe85..b9f7b9bb566889cbd7756ca40bec3cabb9105a8f 100644 --- a/tests/qapi-schema/include/sub-module.json +++ b/tests/qapi-schema/include/sub-module.json @@ -1,4 +1,5 @@ # *-*- Mode: Python -*-* +# vim: filetype=python # Sub-module of ../qapi-schema-test.json diff --git a/tests/qapi-schema/meson.build b/tests/qapi-schema/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..304ef939bd5de87099d210c35fb683f737986278 --- /dev/null +++ b/tests/qapi-schema/meson.build @@ -0,0 +1,275 @@ +test_env = environment() +test_env.set('PYTHONPATH', meson.source_root() / 'scripts') +test_env.set('PYTHONIOENCODING', 'utf-8') + +schemas = [ + 'alternate-any.json', + 'alternate-array.json', + 'alternate-base.json', + 'alternate-branch-if-invalid.json', + 'alternate-clash.json', + 'alternate-conflict-dict.json', + 'alternate-conflict-enum-bool.json', + 'alternate-conflict-enum-int.json', + 'alternate-conflict-string.json', + 'alternate-conflict-bool-string.json', + 'alternate-conflict-num-string.json', + 'alternate-empty.json', + 'alternate-invalid-dict.json', + 'alternate-nested.json', + 'alternate-unknown.json', + 'args-alternate.json', + 'args-any.json', + 'args-array-empty.json', + 'args-array-unknown.json', + 'args-bad-boxed.json', + 'args-boxed-anon.json', + 'args-boxed-string.json', + 'args-int.json', + 'args-invalid.json', + 'args-member-array-bad.json', + 'args-member-case.json', + 'args-member-unknown.json', + 'args-name-clash.json', + 'args-union.json', + 'args-unknown.json', + 'bad-base.json', + 'bad-data.json', + 'bad-ident.json', + 'bad-if.json', + 'bad-if-empty.json', + 'bad-if-empty-list.json', + 'bad-if-list.json', + 'bad-type-bool.json', + 'bad-type-dict.json', + 'bad-type-int.json', + 'base-cycle-direct.json', + 'base-cycle-indirect.json', + 'command-int.json', + 'comments.json', + 'doc-bad-alternate-member.json', + 'doc-bad-boxed-command-arg.json', + 'doc-bad-command-arg.json', + 'doc-bad-enum-member.json', + 'doc-bad-event-arg.json', + 'doc-bad-feature.json', + 'doc-bad-indent.json', + 'doc-bad-section.json', + 'doc-bad-symbol.json', + 'doc-bad-union-member.json', + 'doc-before-include.json', + 'doc-before-pragma.json', + 'doc-duplicated-arg.json', + 'doc-duplicated-return.json', + 'doc-duplicated-since.json', + 'doc-empty-arg.json', + 'doc-empty-section.json', + 'doc-empty-symbol.json', + 'doc-good.json', + 'doc-interleaved-section.json', + 'doc-invalid-end.json', + 'doc-invalid-end2.json', + 'doc-invalid-return.json', + 'doc-invalid-section.json', + 'doc-invalid-start.json', + 'doc-missing-colon.json', + 'doc-missing-expr.json', + 'doc-missing-space.json', + 'doc-missing.json', + 'doc-no-symbol.json', + 'doc-undoc-feature.json', + 'double-type.json', + 'duplicate-key.json', + 'empty.json', + 'enum-bad-member.json', + 'enum-bad-name.json', + 'enum-bad-prefix.json', + 'enum-clash-member.json', + 'enum-dict-member-unknown.json', + 'enum-if-invalid.json', + 'enum-int-member.json', + 'enum-member-case.json', + 'enum-missing-data.json', + 'enum-wrong-data.json', + 'event-boxed-empty.json', + 'event-case.json', + 'event-member-invalid-dict.json', + 'event-nest-struct.json', + 'features-bad-type.json', + 'features-deprecated-type.json', + 'features-duplicate-name.json', + 'features-if-invalid.json', + 'features-missing-name.json', + 'features-name-bad-type.json', + 'features-no-list.json', + 'features-unknown-key.json', + 'flat-union-array-branch.json', + 'flat-union-bad-base.json', + 'flat-union-bad-discriminator.json', + 'flat-union-base-any.json', + 'flat-union-base-union.json', + 'flat-union-clash-member.json', + 'flat-union-discriminator-bad-name.json', + 'flat-union-empty.json', + 'flat-union-inline.json', + 'flat-union-inline-invalid-dict.json', + 'flat-union-int-branch.json', + 'flat-union-invalid-branch-key.json', + 'flat-union-invalid-discriminator.json', + 'flat-union-invalid-if-discriminator.json', + 'flat-union-no-base.json', + 'flat-union-optional-discriminator.json', + 'flat-union-string-discriminator.json', + 'funny-char.json', + 'funny-word.json', + 'ident-with-escape.json', + 'include-before-err.json', + 'include-cycle.json', + 'include-extra-junk.json', + 'include-nested-err.json', + 'include-no-file.json', + 'include-non-file.json', + 'include-repetition.json', + 'include-self-cycle.json', + 'include-simple.json', + 'indented-expr.json', + 'leading-comma-list.json', + 'leading-comma-object.json', + 'missing-colon.json', + 'missing-comma-list.json', + 'missing-comma-object.json', + 'missing-type.json', + 'nested-struct-data.json', + 'nested-struct-data-invalid-dict.json', + 'non-objects.json', + 'oob-coroutine.json', + 'oob-test.json', + 'allow-preconfig-test.json', + 'pragma-doc-required-crap.json', + 'pragma-extra-junk.json', + 'pragma-name-case-whitelist-crap.json', + 'pragma-non-dict.json', + 'pragma-unknown.json', + 'pragma-returns-whitelist-crap.json', + 'qapi-schema-test.json', + 'quoted-structural-chars.json', + 'redefined-builtin.json', + 'redefined-command.json', + 'redefined-event.json', + 'redefined-type.json', + 'reserved-command-q.json', + 'reserved-enum-q.json', + 'reserved-member-has.json', + 'reserved-member-q.json', + 'reserved-member-u.json', + 'reserved-member-underscore.json', + 'reserved-type-kind.json', + 'reserved-type-list.json', + 'returns-alternate.json', + 'returns-array-bad.json', + 'returns-dict.json', + 'returns-unknown.json', + 'returns-whitelist.json', + 'string-code-point-31.json', + 'string-code-point-127.json', + 'struct-base-clash-deep.json', + 'struct-base-clash.json', + 'struct-data-invalid.json', + 'struct-member-if-invalid.json', + 'struct-member-invalid-dict.json', + 'struct-member-invalid.json', + 'trailing-comma-list.json', + 'trailing-comma-object.json', + 'type-bypass-bad-gen.json', + 'unclosed-list.json', + 'unclosed-object.json', + 'unclosed-string.json', + 'union-base-empty.json', + 'union-base-no-discriminator.json', + 'union-branch-case.json', + 'union-branch-if-invalid.json', + 'union-branch-invalid-dict.json', + 'union-clash-branches.json', + 'union-empty.json', + 'union-invalid-base.json', + 'union-optional-branch.json', + 'union-unknown.json', + 'unknown-escape.json', + 'unknown-expr-key.json', +] + +# Because people may want to use test-qapi.py from the command line, we +# are not using the "#! /usr/bin/env python3" trick here. See +# docs/devel/build-system.txt +test('QAPI schema regression tests', python, args: files('test-qapi.py', schemas), + env: test_env, suite: ['qapi-schema', 'qapi-frontend']) + +diff = find_program('diff') + +qapi_doc = custom_target('QAPI doc', + output: ['doc-good-qapi-commands.c', 'doc-good-qapi-commands.h', + 'doc-good-qapi-emit-events.c', 'doc-good-qapi-emit-events.h', + 'doc-good-qapi-events.c', 'doc-good-qapi-events.h', + 'doc-good-qapi-init-commands.c', 'doc-good-qapi-init-commands.h', + 'doc-good-qapi-introspect.c', 'doc-good-qapi-introspect.h', + 'doc-good-qapi-types.c', 'doc-good-qapi-types.h', + 'doc-good-qapi-visit.c', 'doc-good-qapi-visit.h' ], + input: files('doc-good.json'), + command: [ qapi_gen, '-o', meson.current_build_dir(), + '-p', 'doc-good-', '@INPUT0@' ], + depend_files: qapi_gen_depends) + +if build_docs + # Test the document-comment document generation code by running a test schema + # file through Sphinx's plain-text builder and comparing the result against + # a golden reference. This is in theory susceptible to failures if Sphinx + # changes its output, but the text output has historically been very stable + # (no changes between Sphinx 1.6 and 3.0), so it is a better bet than + # texinfo or HTML generation, both of which have had changes. We might + # need to add more sophisticated logic here in future for some sort of + # fuzzy comparison if future Sphinx versions produce different text, + # but for now the simple comparison suffices. + qapi_doc_out = custom_target('QAPI rST doc', + output: ['doc-good.txt'], + input: files('doc-good.json', 'doc-good.rst'), + build_by_default: true, + depend_files: sphinx_extn_depends, + # We use -E to suppress Sphinx's caching, because + # we want it to always really run the QAPI doc + # generation code. It also means we don't + # clutter up the build dir with the cache. + command: [SPHINX_ARGS, + '-b', 'text', '-E', + '-c', meson.source_root() / 'docs', + '-D', 'master_doc=doc-good', + meson.current_source_dir(), + meson.current_build_dir()]) + + # Fix possible inconsistency in line endings in generated output and + # in the golden reference (which could otherwise cause test failures + # on Windows hosts). Unfortunately diff --strip-trailing-cr + # is GNU-diff only. The odd-looking perl is because we must avoid + # using an explicit '\' character in the command arguments to + # a custom_target(), as Meson will unhelpfully replace it with a '/' + # (https://github.com/mesonbuild/meson/issues/1564) + qapi_doc_out_nocr = custom_target('QAPI rST doc newline-sanitized', + output: ['doc-good.txt.nocr'], + input: qapi_doc_out[0], + build_by_default: true, + command: ['perl', '-pe', '$x = chr 13; s/$x$//', '@INPUT@'], + capture: true) + + qapi_doc_ref_nocr = custom_target('QAPI rST doc reference newline-sanitized', + output: ['doc-good.ref.nocr'], + input: files('doc-good.txt'), + build_by_default: true, + command: ['perl', '-pe', '$x = chr 13; s/$x$//', '@INPUT@'], + capture: true) + + # "full_path()" needed here to work around + # https://github.com/mesonbuild/meson/issues/7585 + test('QAPI rST doc', diff, args: ['-u', qapi_doc_ref_nocr[0].full_path(), + qapi_doc_out_nocr[0].full_path()], + depends: [qapi_doc_ref_nocr, qapi_doc_out_nocr], + suite: ['qapi-schema', 'qapi-doc']) +endif diff --git a/tests/qapi-schema/oob-coroutine.err b/tests/qapi-schema/oob-coroutine.err new file mode 100644 index 0000000000000000000000000000000000000000..c01a4992bdecdb6dc7d88af43af0f7f6f8e36451 --- /dev/null +++ b/tests/qapi-schema/oob-coroutine.err @@ -0,0 +1,2 @@ +oob-coroutine.json: In command 'oob-command-1': +oob-coroutine.json:2: flags 'allow-oob' and 'coroutine' are incompatible diff --git a/tests/qapi-schema/oob-coroutine.json b/tests/qapi-schema/oob-coroutine.json new file mode 100644 index 0000000000000000000000000000000000000000..0f67663bcd683a5663447388fa405e436af2efd3 --- /dev/null +++ b/tests/qapi-schema/oob-coroutine.json @@ -0,0 +1,2 @@ +# Check that incompatible flags allow-oob and coroutine are rejected +{ 'command': 'oob-command-1', 'allow-oob': true, 'coroutine': true } diff --git a/tests/qapi-schema/oob-coroutine.out b/tests/qapi-schema/oob-coroutine.out new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json index 6b1f05afa7b8c627f2be4440bc84e99c1823e344..63f92adf6834f1730b2dbf76932ed88152fb04b2 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -1,4 +1,5 @@ # *-*- Mode: Python -*-* +# vim: filetype=python # This file is a stress test of supported qapi constructs that must # parse and compile correctly. @@ -147,6 +148,7 @@ 'returns': 'UserDefTwo' } { 'command': 'cmd-success-response', 'data': {}, 'success-response': false } +{ 'command': 'coroutine-cmd', 'data': {}, 'coroutine': true } # Returning a non-dictionary requires a name from the whitelist { 'command': 'guest-get-time', 'data': {'a': 'int', '*b': 'int' }, diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out index 891b4101e037770879dc19033ede3245f7240ca3..8868ca0dca9e4a25552d73e2dbb0edcfd17becf6 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -203,6 +203,8 @@ command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserDefTwo gen=True success_response=True boxed=False oob=False preconfig=False command cmd-success-response None -> None gen=True success_response=False boxed=False oob=False preconfig=False +command coroutine-cmd None -> None + gen=True success_response=True boxed=False oob=False preconfig=False coroutine=True object q_obj_guest-get-time-arg member a: int optional=False member b: int optional=True diff --git a/tests/qapi-schema/sub-sub-module.json b/tests/qapi-schema/sub-sub-module.json index 524ef9b83f59b9da5be90ad0a4b45562119f7ade..94f36ec0b185acd9f4c8b932e82e461ab6d4c027 100644 --- a/tests/qapi-schema/sub-sub-module.json +++ b/tests/qapi-schema/sub-sub-module.json @@ -1,4 +1,5 @@ # *-*- Mode: Python -*-* +# vim: filetype=python # Sub-module of sub-module include/sub-module.json of qapi-schema-test.json diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py index f396b471eb2178780864ecc99b4ce5be47a08c94..e8db9d09d914d880d1dda661f5b5cb0d325ee4f0 100755 --- a/tests/qapi-schema/test-qapi.py +++ b/tests/qapi-schema/test-qapi.py @@ -68,12 +68,13 @@ def visit_alternate_type(self, name, info, ifcond, features, variants): def visit_command(self, name, info, ifcond, features, arg_type, ret_type, gen, success_response, boxed, - allow_oob, allow_preconfig): + allow_oob, allow_preconfig, coroutine): print('command %s %s -> %s' % (name, arg_type and arg_type.name, ret_type and ret_type.name)) - print(' gen=%s success_response=%s boxed=%s oob=%s preconfig=%s' - % (gen, success_response, boxed, allow_oob, allow_preconfig)) + print(' gen=%s success_response=%s boxed=%s oob=%s preconfig=%s%s' + % (gen, success_response, boxed, allow_oob, allow_preconfig, + " coroutine=True" if coroutine else "")) self._print_if(ifcond) self._print_features(features) diff --git a/tests/qemu-iotests/.gitignore b/tests/qemu-iotests/.gitignore deleted file mode 100644 index da62054000086155a8037a58c9bd18fba777aaea..0000000000000000000000000000000000000000 --- a/tests/qemu-iotests/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -check.log -check.time* -common.env -*.out.bad -*.notrun -socket_scm_helper - -# ignore everything in the scratch directory -scratch/ diff --git a/tests/qemu-iotests/017 b/tests/qemu-iotests/017 index 0a4b854e652045a30016184d780535eb8e273526..3413e34f27d5b0c7d35aa3a9f45449a9b71c36bf 100755 --- a/tests/qemu-iotests/017 +++ b/tests/qemu-iotests/017 @@ -40,7 +40,6 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 # Any format supporting backing files _supported_fmt qcow qcow2 vmdk qed _supported_proto generic -_unsupported_proto vxhs _unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat" \ "subformat=streamOptimized" @@ -66,7 +65,7 @@ echo "Creating test image with backing file" echo TEST_IMG=$TEST_IMG_SAVE -_make_test_img -b "$TEST_IMG.base" 6G +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT 6G echo "Filling test image" echo diff --git a/tests/qemu-iotests/017.out b/tests/qemu-iotests/017.out index 8fc9241942e81f1ad7a8174e4d7b56f6056e66fc..f439d3ece3a73abe00b2bf4f7fe81dc740abc85b 100644 --- a/tests/qemu-iotests/017.out +++ b/tests/qemu-iotests/017.out @@ -269,7 +269,7 @@ wrote 65536/65536 bytes at offset 4295032832 No errors were found on the image. Creating test image with backing file -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT Filling test image === IO: pattern 1 diff --git a/tests/qemu-iotests/018 b/tests/qemu-iotests/018 index c69ce0920920a2a5d4d5bc5c1540803a7833b34d..191b461a4d2919ef0098fdb0813145b9cc0181b5 100755 --- a/tests/qemu-iotests/018 +++ b/tests/qemu-iotests/018 @@ -66,7 +66,7 @@ echo "Creating test image with backing file" echo TEST_IMG="$TEST_IMG_SAVE.orig" -_make_test_img -b "$TEST_IMG_SAVE.base" 6G +_make_test_img -b "$TEST_IMG_SAVE.base" -F $IMGFMT 6G echo "Filling test image" echo diff --git a/tests/qemu-iotests/018.out b/tests/qemu-iotests/018.out index 5df966727f98413da1c41779f10bb194f906f4a0..0ab664ca4b4c1a4d657dc94e50fc22bba14f8443 100644 --- a/tests/qemu-iotests/018.out +++ b/tests/qemu-iotests/018.out @@ -269,7 +269,7 @@ wrote 65536/65536 bytes at offset 4295032832 No errors were found on the image. Creating test image with backing file -Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT Filling test image === IO: pattern 1 diff --git a/tests/qemu-iotests/019 b/tests/qemu-iotests/019 index 813a84acac4782ed71179b314f4d65de8c0e813a..d3c11256dc0f6abbced08b981e28fbd67b008b5b 100755 --- a/tests/qemu-iotests/019 +++ b/tests/qemu-iotests/019 @@ -74,7 +74,7 @@ echo "Creating test image with backing file" echo TEST_IMG="$TEST_IMG_SAVE.orig" -_make_test_img -b "$TEST_IMG_SAVE.base" 6G +_make_test_img -b "$TEST_IMG_SAVE.base" -F $IMGFMT 6G echo "Filling test image" echo @@ -98,7 +98,8 @@ for backing_option in "-B " "-o backing_file="; do echo echo Testing conversion with $backing_option"$TEST_IMG.base" | _filter_testdir | _filter_imgfmt echo - $QEMU_IMG convert -f $IMGFMT -O $IMGFMT $backing_option"$TEST_IMG.base" "$TEST_IMG.orig" "$TEST_IMG" + $QEMU_IMG convert -f $IMGFMT -O $IMGFMT $backing_option"$TEST_IMG.base" \ + -o backing_fmt=$IMGFMT "$TEST_IMG.orig" "$TEST_IMG" echo "Checking if backing clusters are allocated when they shouldn't" echo diff --git a/tests/qemu-iotests/019.out b/tests/qemu-iotests/019.out index 17a7c036b9892be7e8257e7af84e227cdc26b243..0fa73bd69ab88272b83433d260e64d65b05efbd5 100644 --- a/tests/qemu-iotests/019.out +++ b/tests/qemu-iotests/019.out @@ -269,7 +269,7 @@ wrote 65536/65536 bytes at offset 4296015872 No errors were found on the image. Creating test image with backing file -Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT Filling test image === IO: pattern 43 diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020 index 20f8f185d0717021a56c06b1218fda1f013dec19..596505be2d89a17172fdda0bf189f69a356851f0 100755 --- a/tests/qemu-iotests/020 +++ b/tests/qemu-iotests/020 @@ -31,6 +31,11 @@ _cleanup() _cleanup_test_img _rm_test_img "$TEST_IMG.base" _rm_test_img "$TEST_IMG.orig" + + _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT.base" + _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT.mid" + _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT" + rmdir "$TEST_DIR/subdir" &> /dev/null } trap "_cleanup; exit \$status" 0 1 2 3 15 @@ -70,7 +75,7 @@ echo "Creating test image with backing file" echo TEST_IMG="$TEST_IMG_SAVE" -_make_test_img -b "$TEST_IMG.base" 6G +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT 6G echo "Filling test image" echo @@ -115,18 +120,23 @@ TEST_IMG="$TEST_IMG.base" _make_test_img 1M # Create an image with a null backing file to which committing will fail (with # ENOSPC so we can distinguish the result from some generic EIO which may be # generated anywhere in the block layer) -_make_test_img -b "json:{'driver': '$IMGFMT', - 'file': { - 'driver': 'blkdebug', - 'inject-error': [{ - 'event': 'write_aio', - 'errno': 28, - 'once': true - }], - 'image': { - 'driver': 'file', - 'filename': '$TEST_IMG.base' - }}}" +backing="json:{'driver': '$IMGFMT', + 'file': { + 'driver': 'blkdebug', + 'inject-error': [{ + 'event': 'write_aio', + 'errno': 28, + 'once': true + }], + 'image': { + 'driver': 'file', + 'filename': '$TEST_IMG.base' + }}}" + +# Filter out newlines and collapse spaces +backing=$(echo "$backing" | tr -d '\n' | tr -s ' ') + +_make_test_img -b "$backing" -F $IMGFMT # Just write anything so committing will not be a no-op $QEMU_IO -c 'writev 0 64k' "$TEST_IMG" | _filter_qemu_io @@ -134,6 +144,45 @@ $QEMU_IO -c 'writev 0 64k' "$TEST_IMG" | _filter_qemu_io $QEMU_IMG commit "$TEST_IMG" _cleanup + +echo +echo 'Testing commit in sub-directory with relative filenames' +echo + +pushd "$TEST_DIR" > /dev/null + +mkdir subdir + +TEST_IMG="subdir/t.$IMGFMT.base" _make_test_img 1M +TEST_IMG="subdir/t.$IMGFMT.mid" _make_test_img -b "t.$IMGFMT.base" -F $IMGFMT +TEST_IMG="subdir/t.$IMGFMT" _make_test_img -b "t.$IMGFMT.mid" -F $IMGFMT + +# Should work +$QEMU_IMG commit -b "t.$IMGFMT.mid" "subdir/t.$IMGFMT" + +# Might theoretically work, but does not in practice (we have to +# decide between this and the above; and since we always represent +# backing file names as relative to the overlay, we go for the above) +$QEMU_IMG commit -b "subdir/t.$IMGFMT.mid" "subdir/t.$IMGFMT" 2>&1 | \ + _filter_imgfmt + +# This should work as well +$QEMU_IMG commit -b "$TEST_DIR/subdir/t.$IMGFMT.mid" "subdir/t.$IMGFMT" + +popd > /dev/null + +# Now let's try with just absolute filenames +# (This will not work with external data files, though, because when +# using relative paths for those, qemu will always resolve them +# relative to its CWD. Therefore, it cannot find those data files now +# that we left $TEST_DIR.) +if _get_data_file '' > /dev/null; then + echo 'Image committed.' # Skip test +else + $QEMU_IMG commit -b "$TEST_DIR/subdir/t.$IMGFMT.mid" \ + "$TEST_DIR/subdir/t.$IMGFMT" +fi + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/020.out b/tests/qemu-iotests/020.out index 4b722b2dd022862127a611e37d6d65720cf405ab..a5db1962ad2b5b5823785e58e994da1d5e0105cb 100644 --- a/tests/qemu-iotests/020.out +++ b/tests/qemu-iotests/020.out @@ -269,7 +269,7 @@ wrote 65536/65536 bytes at offset 4295032832 No errors were found on the image. Creating test image with backing file -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT Filling test image === IO: pattern 1 @@ -1079,19 +1079,18 @@ No errors were found on the image. Testing failing commit Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1048576 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=json:{'driver': 'IMGFMT',, - 'file': { - 'driver': 'blkdebug',, - 'inject-error': [{ - 'event': 'write_aio',, - 'errno': 28,, - 'once': true - }],, - 'image': { - 'driver': 'file',, - 'filename': 'TEST_DIR/t.IMGFMT.base' - }}} +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=json:{'driver': 'IMGFMT',, 'file': { 'driver': 'blkdebug',, 'inject-error': [{ 'event': 'write_aio',, 'errno': 28,, 'once': true }],, 'image': { 'driver': 'file',, 'filename': 'TEST_DIR/t.IMGFMT.base' }}} backing_fmt=IMGFMT wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Block job failed: No space left on device + +Testing commit in sub-directory with relative filenames + +Formatting 'subdir/t.IMGFMT.base', fmt=IMGFMT size=1048576 +Formatting 'subdir/t.IMGFMT.mid', fmt=IMGFMT size=1048576 backing_file=t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'subdir/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=t.IMGFMT.mid backing_fmt=IMGFMT +Image committed. +qemu-img: Did not find 'subdir/t.IMGFMT.mid' in the backing chain of 'subdir/t.IMGFMT' +Image committed. +Image committed. *** done diff --git a/tests/qemu-iotests/024 b/tests/qemu-iotests/024 index e2e766241e1ac9cfc0ef71cf5591adae5246b7ca..12aceb2d41f6a24e71833e690f8df6612ae1cf22 100755 --- a/tests/qemu-iotests/024 +++ b/tests/qemu-iotests/024 @@ -83,7 +83,7 @@ TEST_IMG="$TEST_IMG_SAVE" echo "Creating COW image" echo -_make_test_img -b "$TEST_IMG.base_old" 1G +_make_test_img -b "$TEST_IMG.base_old" -F $IMGFMT 1G io_pattern writev 0 $((4 * CLUSTER_SIZE)) 0 1 0x33 io_pattern writev $((8 * CLUSTER_SIZE)) $((4 * CLUSTER_SIZE)) 0 1 0x33 @@ -109,7 +109,7 @@ io_pattern readv $((15 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x00 echo echo Rebase and test again echo -$QEMU_IMG rebase -b "$TEST_IMG.base_new" "$TEST_IMG" +$QEMU_IMG rebase -b "$TEST_IMG.base_new" -F $IMGFMT "$TEST_IMG" io_pattern readv $((0 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33 io_pattern readv $((1 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33 io_pattern readv $((2 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33 @@ -159,7 +159,7 @@ OVERLAY="$TEST_DIR/$OVERLAY_WREL" TEST_IMG=$BASE_OLD _make_test_img 1M TEST_IMG=$BASE_NEW _make_test_img 1M -TEST_IMG=$OVERLAY _make_test_img -b "$BASE_OLD_OREL" 1M +TEST_IMG=$OVERLAY _make_test_img -b "$BASE_OLD_OREL" -F $IMGFMT 1M echo @@ -176,11 +176,11 @@ $QEMU_IO "$BASE_NEW" \ echo pushd "$TEST_DIR" >/dev/null -$QEMU_IMG rebase -f "$IMGFMT" -b "$BASE_NEW_OREL" "$OVERLAY_WREL" +$QEMU_IMG rebase -f "$IMGFMT" -b "$BASE_NEW_OREL" -F $IMGFMT "$OVERLAY_WREL" popd >/dev/null # Verify the backing path is correct -TEST_IMG=$OVERLAY _img_info | grep '^backing file' +TEST_IMG=$OVERLAY _img_info | grep '^backing file:' echo diff --git a/tests/qemu-iotests/024.out b/tests/qemu-iotests/024.out index 024dc786b3c4df89e8c1d3576b984b413e82c658..973a5a371119490531af3da9767c52b83b823120 100644 --- a/tests/qemu-iotests/024.out +++ b/tests/qemu-iotests/024.out @@ -33,7 +33,7 @@ wrote 131072/131072 bytes at offset 786432 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Creating COW image -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 backing_file=TEST_DIR/t.IMGFMT.base_old +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 backing_file=TEST_DIR/t.IMGFMT.base_old backing_fmt=IMGFMT === IO: pattern 0x33 wrote 262144/262144 bytes at offset 0 256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -146,7 +146,7 @@ read 65536/65536 bytes at offset 983040 Formatting 'TEST_DIR/subdir/t.IMGFMT.base_old', fmt=IMGFMT size=1048576 Formatting 'TEST_DIR/subdir/t.IMGFMT.base_new', fmt=IMGFMT size=1048576 -Formatting 'TEST_DIR/subdir/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=t.IMGFMT.base_old +Formatting 'TEST_DIR/subdir/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=t.IMGFMT.base_old backing_fmt=IMGFMT wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028 index 797dae535042181eff7e28e19b657bb4f7816241..6dd3ae09a35347c5237b637e39ca0aecf35d5faf 100755 --- a/tests/qemu-iotests/028 +++ b/tests/qemu-iotests/028 @@ -76,7 +76,7 @@ echo "Creating test image with backing file" echo TEST_IMG="$TEST_IMG_SAVE" -_make_test_img -b "$TEST_IMG.base" $image_size +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $image_size echo "Filling test image" echo @@ -101,7 +101,7 @@ io_zero readv $(( offset + 32 * 1024 )) 512 1024 32 _check_test_img # Rebase it on top of its base image -$QEMU_IMG rebase -b "$TEST_IMG.base" "$TEST_IMG" +$QEMU_IMG rebase -b "$TEST_IMG.base" -F $IMGFMT "$TEST_IMG" echo echo block-backup @@ -142,6 +142,25 @@ TEST_IMG="${TEST_IMG}.copy" io_zero readv $(( offset + 32 * 1024 )) 512 1024 32 _check_test_img +echo +echo '=== Reading across backing EOF in one operation ===' +echo + +# Use a cluster boundary as the base end here +base_size=$((3 * 1024 * 1024 * 1024)) + +TEST_IMG="$TEST_IMG.base" _make_test_img $base_size +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $image_size + +# Write 16 times 42 at the end of the base image +$QEMU_IO -c "write -P 42 $((base_size - 16)) 16" "$TEST_IMG.base" \ + | _filter_qemu_io + +# Read 32 bytes across the base EOF from the top; +# should be 16 times 0x2a, then 16 times 0x00 +$QEMU_IO -c "read -v $((base_size - 16)) 32" "$TEST_IMG" \ + | _filter_qemu_io + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/028.out b/tests/qemu-iotests/028.out index 37aed8443628eda85537397808614d100b2dd2f6..5a68de5c46490e4ae29b2380290f21c39c879353 100644 --- a/tests/qemu-iotests/028.out +++ b/tests/qemu-iotests/028.out @@ -70,7 +70,7 @@ wrote 512/512 bytes at offset 3221225984 No errors were found on the image. Creating test image with backing file -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294968832 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294968832 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT Filling test image === IO: pattern 196 @@ -730,4 +730,15 @@ read 512/512 bytes at offset 3221257728 read 512/512 bytes at offset 3221258752 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) No errors were found on the image. + +=== Reading across backing EOF in one operation === + +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=3221225472 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294968832 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +wrote 16/16 bytes at offset 3221225456 +16 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +bffffff0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a ................ +c0000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +read 32/32 bytes at offset 3221225456 +32 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) *** done diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029 index 2161a4b87a52333f9711690ec9755d9ea8a7b4c0..61d78c00a4c5975ea5f7c7a8ad385a3f5ad08a96 100755 --- a/tests/qemu-iotests/029 +++ b/tests/qemu-iotests/029 @@ -41,7 +41,6 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 # Any format supporting intenal snapshots _supported_fmt qcow2 _supported_proto generic -_unsupported_proto vxhs # Internal snapshots are (currently) impossible with refcount_bits=1, # and generally impossible with external data files _unsupported_imgopts 'refcount_bits=1[^0-9]' data_file diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030 index 1cdd7e2999f686eccf3e0bcfc143b4b0e53514f9..dcb4b5d6a68ec42b0690196c04ed48b384ae6e22 100755 --- a/tests/qemu-iotests/030 +++ b/tests/qemu-iotests/030 @@ -21,6 +21,7 @@ import time import os import iotests +import unittest from iotests import qemu_img, qemu_io backing_img = os.path.join(iotests.test_dir, 'backing.img') @@ -32,8 +33,12 @@ class TestSingleDrive(iotests.QMPTestCase): def setUp(self): iotests.create_image(backing_img, TestSingleDrive.image_len) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % backing_img, + '-F', 'raw', mid_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % mid_img, + '-F', iotests.imgfmt, test_img) qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 512', backing_img) qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 524288 512', mid_img) self.vm = iotests.VM().add_drive("blkdebug::" + test_img, @@ -199,7 +204,8 @@ class TestParallelOps(iotests.QMPTestCase): iotests.create_image(self.imgs[0], self.image_len) for i in range(1, self.num_imgs): qemu_img('create', '-f', iotests.imgfmt, - '-o', 'backing_file=%s' % self.imgs[i-1], self.imgs[i]) + '-o', 'backing_file=%s' % self.imgs[i-1], + '-F', 'raw' if i == 1 else iotests.imgfmt, self.imgs[i]) # Put data into the images we are copying data from odd_img_indexes = [x for x in reversed(range(self.num_imgs)) if x % 2 == 1] @@ -223,6 +229,7 @@ class TestParallelOps(iotests.QMPTestCase): # Test that it's possible to run several block-stream operations # in parallel in the same snapshot chain + @unittest.skipIf(os.environ.get('QEMU_CHECK_BLOCK_AUTO'), 'disabled in CI') def test_stream_parallel(self): self.assert_no_active_block_jobs() @@ -238,7 +245,7 @@ class TestParallelOps(iotests.QMPTestCase): node_name = 'node%d' % i job_id = 'stream-%s' % node_name pending_jobs.append(job_id) - result = self.vm.qmp('block-stream', device=node_name, job_id=job_id, base=self.imgs[i-2], speed=512*1024) + result = self.vm.qmp('block-stream', device=node_name, job_id=job_id, base=self.imgs[i-2], speed=1024) self.assert_qmp(result, 'return', {}) for job in pending_jobs: @@ -544,7 +551,8 @@ class TestQuorum(iotests.QMPTestCase): qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x55 0 1024', backing_img) qemu_img('create', '-f', iotests.imgfmt, - '-o', 'backing_file=%s' % backing_img, child_img) + '-o', 'backing_file=%s' % backing_img, + '-F', iotests.imgfmt, child_img) opts.append("children.%d.file.filename=%s" % (i, child_img)) opts.append("children.%d.node-name=node%d" % (i, i)) @@ -585,7 +593,9 @@ class TestSmallerBackingFile(iotests.QMPTestCase): def setUp(self): iotests.create_image(backing_img, self.backing_len) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img, str(self.image_len)) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % backing_img, + '-F', 'raw', test_img, str(self.image_len)) self.vm = iotests.VM().add_drive(test_img) self.vm.launch() @@ -848,7 +858,9 @@ class TestStreamStop(iotests.QMPTestCase): def setUp(self): qemu_img('create', backing_img, str(TestStreamStop.image_len)) qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 32M', backing_img) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % backing_img, + '-F', 'raw', test_img) qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 32M 32M', test_img) self.vm = iotests.VM().add_drive("blkdebug::" + test_img) self.vm.launch() @@ -879,7 +891,9 @@ class TestSetSpeed(iotests.QMPTestCase): def setUp(self): qemu_img('create', backing_img, str(TestSetSpeed.image_len)) qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 32M', backing_img) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % backing_img, + '-F', 'raw', test_img) qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 32M 32M', test_img) self.vm = iotests.VM().add_drive('blkdebug::' + test_img) self.vm.launch() diff --git a/tests/qemu-iotests/031.out b/tests/qemu-iotests/031.out index 5a4beda6a23c67c15788e5d4d231e26082a47d86..0054c2ed97de0813c374dc0ce3730b88eff69e45 100644 --- a/tests/qemu-iotests/031.out +++ b/tests/qemu-iotests/031.out @@ -25,7 +25,7 @@ refcount_order 4 header_length 72 Header extension: -magic 0x12345678 +magic 0x12345678 () length 31 data 'This is a test header extension' @@ -53,7 +53,7 @@ refcount_order 4 header_length 72 Header extension: -magic 0x12345678 +magic 0x12345678 () length 31 data 'This is a test header extension' @@ -81,12 +81,12 @@ refcount_order 4 header_length 72 Header extension: -magic 0xe2792aca +magic 0xe2792aca (Backing format) length 11 data 'host_device' Header extension: -magic 0x12345678 +magic 0x12345678 () length 31 data 'This is a test header extension' @@ -116,12 +116,12 @@ refcount_order 4 header_length 112 Header extension: -magic 0x6803f857 -length 336 +magic 0x6803f857 (Feature table) +length 384 data Header extension: -magic 0x12345678 +magic 0x12345678 () length 31 data 'This is a test header extension' @@ -149,12 +149,12 @@ refcount_order 4 header_length 112 Header extension: -magic 0x6803f857 -length 336 +magic 0x6803f857 (Feature table) +length 384 data Header extension: -magic 0x12345678 +magic 0x12345678 () length 31 data 'This is a test header extension' @@ -164,7 +164,7 @@ No errors were found on the image. magic 0x514649fb version 3 -backing_file_offset 0x210 +backing_file_offset 0x240 backing_file_size 0x17 cluster_bits 16 size 67108864 @@ -182,17 +182,17 @@ refcount_order 4 header_length 112 Header extension: -magic 0xe2792aca +magic 0xe2792aca (Backing format) length 11 data 'host_device' Header extension: -magic 0x6803f857 -length 336 +magic 0x6803f857 (Feature table) +length 384 data Header extension: -magic 0x12345678 +magic 0x12345678 () length 31 data 'This is a test header extension' diff --git a/tests/qemu-iotests/034 b/tests/qemu-iotests/034 index da4cea1571e46d972ce0cdfc2c20787e3f09c4f8..ac2d687c71da7e43a1ccc08b0caa8301fa286817 100755 --- a/tests/qemu-iotests/034 +++ b/tests/qemu-iotests/034 @@ -58,7 +58,7 @@ $QEMU_IO -c "write -P 0x55 0 1M" "$TEST_IMG" | _filter_qemu_io TEST_IMG="$TEST_IMG_SAVE" -_make_test_img -b "$TEST_IMG.base" 6G +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT 6G echo echo "== zero write with backing file ==" diff --git a/tests/qemu-iotests/034.out b/tests/qemu-iotests/034.out index 0764ead8b95dd06f2793d006c67e4395e62ba232..478205ad254280a9dabb072b57c65e494d8c03ef 100644 --- a/tests/qemu-iotests/034.out +++ b/tests/qemu-iotests/034.out @@ -4,7 +4,7 @@ QA output created by 034 Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 wrote 1048576/1048576 bytes at offset 0 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT == zero write with backing file == wrote 196608/196608 bytes at offset 65536 diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out index e409acf60e2b9739f0825d443883ba8948c2a4ad..1fa7cad28ddcf46d99a7e78eab8b1d11ff4b9f13 100644 --- a/tests/qemu-iotests/036.out +++ b/tests/qemu-iotests/036.out @@ -25,8 +25,8 @@ incompatible_features [] compatible_features [] autoclear_features [63] Header extension: -magic 0x6803f857 -length 336 +magic 0x6803f857 (Feature table) +length 384 data @@ -37,8 +37,8 @@ incompatible_features [] compatible_features [] autoclear_features [] Header extension: -magic 0x6803f857 -length 336 +magic 0x6803f857 (Feature table) +length 384 data *** done diff --git a/tests/qemu-iotests/037 b/tests/qemu-iotests/037 index e6517acbd4cdf1d69a6711e24b6440d5589af726..e1187ac24a0b41a73734e708768c036b612c9e4c 100755 --- a/tests/qemu-iotests/037 +++ b/tests/qemu-iotests/037 @@ -74,7 +74,7 @@ backing_io 0 256 write | $QEMU_IO "$TEST_IMG" | _filter_qemu_io TEST_IMG="$TEST_IMG_SAVE" -_make_test_img -b "$TEST_IMG.base" 6G +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT 6G echo echo "== COW in a single cluster ==" diff --git a/tests/qemu-iotests/037.out b/tests/qemu-iotests/037.out index cd6710c9016028fce7ad310790beecdaa5cfdfb7..30ef989b64d64d43cc7963cd68ff8958d9b65e66 100644 --- a/tests/qemu-iotests/037.out +++ b/tests/qemu-iotests/037.out @@ -514,7 +514,7 @@ wrote 512/512 bytes at offset 130048 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 512/512 bytes at offset 130560 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT == COW in a single cluster == wrote 2048/2048 bytes at offset 0 diff --git a/tests/qemu-iotests/038 b/tests/qemu-iotests/038 index 707e2d72e92dd527cf3acda860230844b58eb313..a253231f5baf03a68123cfcf539ef289956c96bd 100755 --- a/tests/qemu-iotests/038 +++ b/tests/qemu-iotests/038 @@ -71,7 +71,7 @@ backing_io 0 256 write | $QEMU_IO "$TEST_IMG" | _filter_qemu_io TEST_IMG="$TEST_IMG_SAVE" -_make_test_img -b "$TEST_IMG.base" 6G +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT 6G echo echo "== Some concurrent requests touching the same cluster ==" diff --git a/tests/qemu-iotests/038.out b/tests/qemu-iotests/038.out index 0bdfb19faa639dc0fcb79ba26ca38790c56502d5..fe2108593ae62f6d07ad7b22768101ea3e3c600c 100644 --- a/tests/qemu-iotests/038.out +++ b/tests/qemu-iotests/038.out @@ -514,7 +514,7 @@ wrote 65536/65536 bytes at offset 16646144 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 16711680 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT == Some concurrent requests touching the same cluster == wrote 65536/65536 bytes at offset XXX diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039 index ddce48ab47522efa363e1bffd7f55fd1263125b4..42f65031383afb7a9d63e369c12ef8fb147d8a78 100755 --- a/tests/qemu-iotests/039 +++ b/tests/qemu-iotests/039 @@ -133,7 +133,8 @@ echo "== Committing to a backing file with lazy_refcounts=on ==" TEST_IMG="$TEST_IMG".base _make_test_img -o "compat=1.1,lazy_refcounts=on" $size -_make_test_img -o "compat=1.1,lazy_refcounts=on,backing_file=$TEST_IMG.base" $size +_make_test_img -o "compat=1.1,lazy_refcounts=on,backing_file=$TEST_IMG.base" \ + -F $IMGFMT $size $QEMU_IO -c "write 0 512" "$TEST_IMG" | _filter_qemu_io $QEMU_IMG commit "$TEST_IMG" diff --git a/tests/qemu-iotests/039.out b/tests/qemu-iotests/039.out index bdafa3ace36004c8529c32e002c85d1e2dc19575..e52484d4be1bd66c2fe5e49925d3e618e1b87102 100644 --- a/tests/qemu-iotests/039.out +++ b/tests/qemu-iotests/039.out @@ -66,7 +66,7 @@ No errors were found on the image. == Committing to a backing file with lazy_refcounts=on == Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Image committed. diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040 index 32c82b4ec68a8e4a2469768a69c6db10604fc385..caf286571a34032e0002ba62779a720e6624f6a4 100755 --- a/tests/qemu-iotests/040 +++ b/tests/qemu-iotests/040 @@ -80,8 +80,11 @@ class TestSingleDrive(ImageCommitTestCase): def setUp(self): iotests.create_image(backing_img, self.image_len) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % backing_img, '-F', 'raw', mid_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % mid_img, + '-F', iotests.imgfmt, test_img) qemu_io('-f', 'raw', '-c', 'write -P 0xab 0 524288', backing_img) qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', mid_img) self.vm = iotests.VM().add_drive(test_img, "node-name=top,backing.node-name=mid,backing.backing.node-name=base", interface="none") @@ -305,10 +308,16 @@ class TestRelativePaths(ImageCommitTestCase): if exception.errno != errno.EEXIST: raise iotests.create_image(self.backing_img_abs, TestRelativePaths.image_len) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % self.backing_img_abs, self.mid_img_abs) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % self.mid_img_abs, self.test_img) - qemu_img('rebase', '-u', '-b', self.backing_img, self.mid_img_abs) - qemu_img('rebase', '-u', '-b', self.mid_img, self.test_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % self.backing_img_abs, + '-F', 'raw', self.mid_img_abs) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % self.mid_img_abs, + '-F', iotests.imgfmt, self.test_img) + qemu_img('rebase', '-u', '-b', self.backing_img, + '-F', 'raw', self.mid_img_abs) + qemu_img('rebase', '-u', '-b', self.mid_img, + '-F', iotests.imgfmt, self.test_img) qemu_io('-f', 'raw', '-c', 'write -P 0xab 0 524288', self.backing_img_abs) qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', self.mid_img_abs) self.vm = iotests.VM().add_drive(self.test_img) @@ -371,8 +380,11 @@ class TestSetSpeed(ImageCommitTestCase): def setUp(self): qemu_img('create', backing_img, str(TestSetSpeed.image_len)) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % backing_img, '-F', 'raw', mid_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % mid_img, + '-F', iotests.imgfmt, test_img) qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 0 512', test_img) qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', mid_img) self.vm = iotests.VM().add_drive('blkdebug::' + test_img) @@ -410,9 +422,14 @@ class TestReopenOverlay(ImageCommitTestCase): def setUp(self): iotests.create_image(self.img0, self.image_len) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % self.img0, self.img1) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % self.img1, self.img2) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % self.img2, self.img3) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % self.img0, '-F', 'raw', self.img1) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % self.img1, + '-F', iotests.imgfmt, self.img2) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % self.img2, + '-F', iotests.imgfmt, self.img3) qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xab 0 128K', self.img1) self.vm = iotests.VM().add_drive(self.img3) self.vm.launch() @@ -435,8 +452,12 @@ class TestErrorHandling(iotests.QMPTestCase): def setUp(self): iotests.create_image(backing_img, self.image_len) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % backing_img, + '-F', 'raw', mid_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % mid_img, + '-F', iotests.imgfmt, test_img) qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x11 0 512k', mid_img) qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x22 0 512k', test_img) @@ -713,6 +734,244 @@ class TestErrorHandling(iotests.QMPTestCase): self.assertTrue(iotests.compare_images(mid_img, backing_img, fmt2='raw'), 'target image does not match source after commit') +class TestCommitWithFilters(iotests.QMPTestCase): + img0 = os.path.join(iotests.test_dir, '0.img') + img1 = os.path.join(iotests.test_dir, '1.img') + img2 = os.path.join(iotests.test_dir, '2.img') + img3 = os.path.join(iotests.test_dir, '3.img') + + def do_test_io(self, read_or_write): + for index, pattern_file in enumerate(self.pattern_files): + result = qemu_io('-f', iotests.imgfmt, + '-c', + f'{read_or_write} -P {index + 1} {index}M 1M', + pattern_file) + self.assertFalse('Pattern verification failed' in result) + + def setUp(self): + qemu_img('create', '-f', iotests.imgfmt, self.img0, '64M') + qemu_img('create', '-f', iotests.imgfmt, self.img1, '64M') + qemu_img('create', '-f', iotests.imgfmt, self.img2, '64M') + qemu_img('create', '-f', iotests.imgfmt, self.img3, '64M') + + # Distributions of the patterns in the files; this is checked + # by tearDown() and should be changed by the test cases as is + # necessary + self.pattern_files = [self.img0, self.img1, self.img2, self.img3] + + self.do_test_io('write') + + self.vm = iotests.VM().add_device('virtio-scsi,id=vio-scsi') + self.vm.launch() + + result = self.vm.qmp('object-add', qom_type='throttle-group', id='tg') + self.assert_qmp(result, 'return', {}) + + result = self.vm.qmp('blockdev-add', **{ + 'node-name': 'top-filter', + 'driver': 'throttle', + 'throttle-group': 'tg', + 'file': { + 'node-name': 'cow-3', + 'driver': iotests.imgfmt, + 'file': { + 'driver': 'file', + 'filename': self.img3 + }, + 'backing': { + 'node-name': 'cow-2', + 'driver': iotests.imgfmt, + 'file': { + 'driver': 'file', + 'filename': self.img2 + }, + 'backing': { + 'node-name': 'cow-1', + 'driver': iotests.imgfmt, + 'file': { + 'driver': 'file', + 'filename': self.img1 + }, + 'backing': { + 'node-name': 'bottom-filter', + 'driver': 'throttle', + 'throttle-group': 'tg', + 'file': { + 'node-name': 'cow-0', + 'driver': iotests.imgfmt, + 'file': { + 'driver': 'file', + 'filename': self.img0 + } + } + } + } + } + } + }) + self.assert_qmp(result, 'return', {}) + + def tearDown(self): + self.vm.shutdown() + self.do_test_io('read') + + os.remove(self.img3) + os.remove(self.img2) + os.remove(self.img1) + os.remove(self.img0) + + # Filters make for funny filenames, so we cannot just use + # self.imgX to get them + def get_filename(self, node): + return self.vm.node_info(node)['image']['filename'] + + def test_filterless_commit(self): + result = self.vm.qmp('block-commit', + job_id='commit', + device='top-filter', + top_node='cow-2', + base_node='cow-1') + self.assert_qmp(result, 'return', {}) + self.wait_until_completed(drive='commit') + + self.assertIsNotNone(self.vm.node_info('cow-3')) + self.assertIsNone(self.vm.node_info('cow-2')) + self.assertIsNotNone(self.vm.node_info('cow-1')) + + # 2 has been comitted into 1 + self.pattern_files[2] = self.img1 + + def test_commit_through_filter(self): + result = self.vm.qmp('block-commit', + job_id='commit', + device='top-filter', + top_node='cow-1', + base_node='cow-0') + self.assert_qmp(result, 'return', {}) + self.wait_until_completed(drive='commit') + + self.assertIsNotNone(self.vm.node_info('cow-2')) + self.assertIsNone(self.vm.node_info('cow-1')) + self.assertIsNone(self.vm.node_info('bottom-filter')) + self.assertIsNotNone(self.vm.node_info('cow-0')) + + # 1 has been comitted into 0 + self.pattern_files[1] = self.img0 + + def test_filtered_active_commit_with_filter(self): + # Add a device, so the commit job finds a parent it can change + # to point to the base node (so we can test that top-filter is + # dropped from the graph) + result = self.vm.qmp('device_add', id='drv0', driver='scsi-hd', + bus='vio-scsi.0', drive='top-filter') + self.assert_qmp(result, 'return', {}) + + # Try to release our reference to top-filter; that should not + # work because drv0 uses it + result = self.vm.qmp('blockdev-del', node_name='top-filter') + self.assert_qmp(result, 'error/class', 'GenericError') + self.assert_qmp(result, 'error/desc', 'Node top-filter is in use') + + result = self.vm.qmp('block-commit', + job_id='commit', + device='top-filter', + base_node='cow-2') + self.assert_qmp(result, 'return', {}) + self.complete_and_wait(drive='commit') + + # Try to release our reference to top-filter again + result = self.vm.qmp('blockdev-del', node_name='top-filter') + self.assert_qmp(result, 'return', {}) + + self.assertIsNone(self.vm.node_info('top-filter')) + self.assertIsNone(self.vm.node_info('cow-3')) + self.assertIsNotNone(self.vm.node_info('cow-2')) + + # Check that drv0 is now connected to cow-2 + blockdevs = self.vm.qmp('query-block')['return'] + drv0 = next(dev for dev in blockdevs if dev['qdev'] == 'drv0') + self.assertEqual(drv0['inserted']['node-name'], 'cow-2') + + # 3 has been comitted into 2 + self.pattern_files[3] = self.img2 + + def test_filtered_active_commit_without_filter(self): + result = self.vm.qmp('block-commit', + job_id='commit', + device='top-filter', + top_node='cow-3', + base_node='cow-2') + self.assert_qmp(result, 'return', {}) + self.complete_and_wait(drive='commit') + + self.assertIsNotNone(self.vm.node_info('top-filter')) + self.assertIsNone(self.vm.node_info('cow-3')) + self.assertIsNotNone(self.vm.node_info('cow-2')) + + # 3 has been comitted into 2 + self.pattern_files[3] = self.img2 + +class TestCommitWithOverriddenBacking(iotests.QMPTestCase): + img_base_a = os.path.join(iotests.test_dir, 'base_a.img') + img_base_b = os.path.join(iotests.test_dir, 'base_b.img') + img_top = os.path.join(iotests.test_dir, 'top.img') + + def setUp(self): + qemu_img('create', '-f', iotests.imgfmt, self.img_base_a, '1M') + qemu_img('create', '-f', iotests.imgfmt, self.img_base_b, '1M') + qemu_img('create', '-f', iotests.imgfmt, '-b', self.img_base_a, \ + self.img_top) + + self.vm = iotests.VM() + self.vm.launch() + + # Use base_b instead of base_a as the backing of top + result = self.vm.qmp('blockdev-add', **{ + 'node-name': 'top', + 'driver': iotests.imgfmt, + 'file': { + 'driver': 'file', + 'filename': self.img_top + }, + 'backing': { + 'node-name': 'base', + 'driver': iotests.imgfmt, + 'file': { + 'driver': 'file', + 'filename': self.img_base_b + } + } + }) + self.assert_qmp(result, 'return', {}) + + def tearDown(self): + self.vm.shutdown() + os.remove(self.img_top) + os.remove(self.img_base_a) + os.remove(self.img_base_b) + + def test_commit_to_a(self): + # Try committing to base_a (which should fail, as top's + # backing image is base_b instead) + result = self.vm.qmp('block-commit', + job_id='commit', + device='top', + base=self.img_base_a) + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_commit_to_b(self): + # Try committing to base_b (which should work, since that is + # actually top's backing image) + result = self.vm.qmp('block-commit', + job_id='commit', + device='top', + base=self.img_base_b) + self.assert_qmp(result, 'return', {}) + + self.vm.event_wait('BLOCK_JOB_READY') + self.vm.qmp('block-job-complete', device='commit') + self.vm.event_wait('BLOCK_JOB_COMPLETED') + if __name__ == '__main__': iotests.main(supported_fmts=['qcow2', 'qed'], supported_protocols=['file']) diff --git a/tests/qemu-iotests/040.out b/tests/qemu-iotests/040.out index 6a917130b6ca352ba031072e76aa4d7dabc46b84..1bb1dc5f0eaf608078075a1c0ef0b4f3ce7be5e1 100644 --- a/tests/qemu-iotests/040.out +++ b/tests/qemu-iotests/040.out @@ -1,5 +1,5 @@ -........................................................... +................................................................. ---------------------------------------------------------------------- -Ran 59 tests +Ran 65 tests OK diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 index 601c7561179c64f4a0b808b6a1a0c94e33c79f9a..a7780853cdcce53b6173766b9ea573f9157ac13b 100755 --- a/tests/qemu-iotests/041 +++ b/tests/qemu-iotests/041 @@ -21,8 +21,9 @@ import time import os import re +import json import iotests -from iotests import qemu_img, qemu_io +from iotests import qemu_img, qemu_img_pipe, qemu_io backing_img = os.path.join(iotests.test_dir, 'backing.img') target_backing_img = os.path.join(iotests.test_dir, 'target-backing.img') @@ -44,7 +45,8 @@ class TestSingleDrive(iotests.QMPTestCase): def setUp(self): iotests.create_image(backing_img, self.image_len) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % backing_img, '-F', 'raw', test_img) self.vm = iotests.VM().add_drive(test_img, "node-name=top,backing.node-name=base") if iotests.qemu_default_machine == 'pc': self.vm.add_drive(None, 'media=cdrom', 'ide') @@ -157,7 +159,8 @@ class TestSingleDrive(iotests.QMPTestCase): self.assert_no_active_block_jobs() qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=%d,backing_file=%s' - % (self.image_len, backing_img), target_img) + % (self.image_len, backing_img), + '-F', 'raw', target_img) result = self.vm.qmp(self.qmp_cmd, device='drive0', sync='full', mode='existing', target=self.qmp_target) self.assert_qmp(result, 'return', {}) @@ -227,7 +230,8 @@ class TestSingleBlockdev(TestSingleDrive): def setUp(self): TestSingleDrive.setUp(self) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, target_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % backing_img, '-F', 'raw', target_img) args = {'driver': iotests.imgfmt, 'node-name': self.qmp_target, 'file': { 'filename': target_img, 'driver': 'file' } } @@ -277,6 +281,8 @@ class TestSingleBlockdev(TestSingleDrive): result = self.vm.run_job('job0') self.assertEqual(result, 'Source and target image have different sizes') + # qed does not support shrinking + @iotests.skip_for_formats(('qed')) def test_small_target(self): self.do_test_target_size(self.image_len // 2) @@ -310,7 +316,8 @@ class TestMirrorNoBacking(iotests.QMPTestCase): def setUp(self): iotests.create_image(backing_img, TestMirrorNoBacking.image_len) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % backing_img, '-F', 'raw', test_img) self.vm = iotests.VM().add_drive(test_img) self.vm.launch() @@ -327,7 +334,8 @@ class TestMirrorNoBacking(iotests.QMPTestCase): def test_complete(self): self.assert_no_active_block_jobs() - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, target_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % backing_img, '-F', 'raw', target_img) result = self.vm.qmp('drive-mirror', device='drive0', sync='full', mode='existing', target=target_img) self.assert_qmp(result, 'return', {}) @@ -342,7 +350,8 @@ class TestMirrorNoBacking(iotests.QMPTestCase): def test_cancel(self): self.assert_no_active_block_jobs() - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, target_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % backing_img, '-F', 'raw', target_img) result = self.vm.qmp('drive-mirror', device='drive0', sync='full', mode='existing', target=target_img) self.assert_qmp(result, 'return', {}) @@ -361,7 +370,8 @@ class TestMirrorNoBacking(iotests.QMPTestCase): qemu_img('create', '-f', iotests.imgfmt, '-o', 'size=%d' %(TestMirrorNoBacking.image_len), target_backing_img) qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=%d,backing_file=%s' - % (TestMirrorNoBacking.image_len, target_backing_img), target_img) + % (TestMirrorNoBacking.image_len, target_backing_img), + '-F', iotests.imgfmt, target_img) result = self.vm.qmp('drive-mirror', device='drive0', sync='full', mode='existing', target=target_img) @@ -380,7 +390,8 @@ class TestMirrorResized(iotests.QMPTestCase): def setUp(self): iotests.create_image(backing_img, TestMirrorResized.backing_len) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % backing_img, '-F', 'raw', test_img) qemu_img('resize', test_img, '2M') self.vm = iotests.VM().add_drive(test_img) self.vm.launch() @@ -526,7 +537,9 @@ new_state = "1" # Test COW into the target image. The first half of the # cluster at MIRROR_GRANULARITY has to be copied from # backing_img, even though sync='top'. - qemu_img('create', '-f', iotests.imgfmt, '-ocluster_size=131072,backing_file=%s' %(backing_img), target_img) + qemu_img('create', '-f', iotests.imgfmt, + '-ocluster_size=131072,backing_file=%s' %(backing_img), + '-F', 'raw', target_img) result = self.vm.qmp('drive-mirror', device='drive0', sync='top', on_source_error='ignore', mode='existing', target=target_img) @@ -546,7 +559,8 @@ new_state = "1" self.vm.shutdown() # Detach blkdebug to compare images successfully - qemu_img('rebase', '-f', iotests.imgfmt, '-u', '-b', backing_img, test_img) + qemu_img('rebase', '-f', iotests.imgfmt, '-u', '-b', backing_img, + '-F', 'raw', test_img) self.assertTrue(iotests.compare_images(test_img, target_img), 'target image does not match source after mirroring') @@ -618,7 +632,8 @@ new_state = "1" self.blkdebug_file = target_img + ".blkdebug" iotests.create_image(backing_img, TestWriteErrors.image_len) self.create_blkdebug_file(self.blkdebug_file, "write_aio", 5) - qemu_img('create', '-f', iotests.imgfmt, '-obacking_file=%s' %(backing_img), test_img) + qemu_img('create', '-f', iotests.imgfmt, + '-obacking_file=%s' %(backing_img), '-F', 'raw', test_img) self.vm = iotests.VM().add_drive(test_img) self.target_img = 'blkdebug:%s:%s' % (self.blkdebug_file, target_img) qemu_img('create', '-f', iotests.imgfmt, '-osize=%d' %(TestWriteErrors.image_len), target_img) @@ -713,7 +728,8 @@ class TestSetSpeed(iotests.QMPTestCase): def setUp(self): qemu_img('create', backing_img, str(TestSetSpeed.image_len)) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % backing_img, '-F', 'raw', test_img) self.vm = iotests.VM().add_drive(test_img) self.vm.launch() @@ -1273,6 +1289,149 @@ class TestReplaces(iotests.QMPTestCase): self.vm.assert_block_path('filter0', '/file', 'target') +# Tests for mirror with filters (and how the mirror filter behaves, as +# an example for an implicit filter) +class TestFilters(iotests.QMPTestCase): + def setUp(self): + qemu_img('create', '-f', iotests.imgfmt, backing_img, '1M') + qemu_img('create', '-f', iotests.imgfmt, '-b', backing_img, test_img) + qemu_img('create', '-f', iotests.imgfmt, '-b', backing_img, target_img) + + qemu_io('-c', 'write -P 1 0 512k', backing_img) + qemu_io('-c', 'write -P 2 512k 512k', test_img) + + self.vm = iotests.VM().add_device('virtio-scsi,id=vio-scsi') + self.vm.launch() + + result = self.vm.qmp('blockdev-add', **{ + 'node-name': 'target', + 'driver': iotests.imgfmt, + 'file': { + 'driver': 'file', + 'filename': target_img + }, + 'backing': None + }) + self.assert_qmp(result, 'return', {}) + + self.filterless_chain = { + 'node-name': 'source', + 'driver': iotests.imgfmt, + 'file': { + 'driver': 'file', + 'filename': test_img + }, + 'backing': { + 'node-name': 'backing', + 'driver': iotests.imgfmt, + 'file': { + 'driver': 'file', + 'filename': backing_img + } + } + } + + def tearDown(self): + self.vm.shutdown() + + os.remove(test_img) + os.remove(target_img) + os.remove(backing_img) + + def test_cor(self): + result = self.vm.qmp('blockdev-add', **{ + 'node-name': 'filter', + 'driver': 'copy-on-read', + 'file': self.filterless_chain + }) + self.assert_qmp(result, 'return', {}) + + result = self.vm.qmp('blockdev-mirror', + job_id='mirror', + device='filter', + target='target', + sync='top') + self.assert_qmp(result, 'return', {}) + + self.complete_and_wait('mirror') + + self.vm.qmp('blockdev-del', node_name='target') + + target_map = qemu_img_pipe('map', '--output=json', target_img) + target_map = json.loads(target_map) + + assert target_map[0]['start'] == 0 + assert target_map[0]['length'] == 512 * 1024 + assert target_map[0]['depth'] == 1 + + assert target_map[1]['start'] == 512 * 1024 + assert target_map[1]['length'] == 512 * 1024 + assert target_map[1]['depth'] == 0 + + def test_implicit_mirror_filter(self): + result = self.vm.qmp('blockdev-add', **self.filterless_chain) + self.assert_qmp(result, 'return', {}) + + # We need this so we can query from above the mirror node + result = self.vm.qmp('device_add', + driver='scsi-hd', + id='virtio', + bus='vio-scsi.0', + drive='source') + self.assert_qmp(result, 'return', {}) + + result = self.vm.qmp('blockdev-mirror', + job_id='mirror', + device='source', + target='target', + sync='top') + self.assert_qmp(result, 'return', {}) + + # The mirror filter is now an implicit node, so it should be + # invisible when querying the backing chain + blockdevs = self.vm.qmp('query-block')['return'] + device_info = next(dev for dev in blockdevs if dev['qdev'] == 'virtio') + + assert device_info['inserted']['node-name'] == 'source' + + image_info = device_info['inserted']['image'] + assert image_info['filename'] == test_img + assert image_info['backing-image']['filename'] == backing_img + + self.complete_and_wait('mirror') + + def test_explicit_mirror_filter(self): + # Same test as above, but this time we give the mirror filter + # a node-name so it will not be invisible + result = self.vm.qmp('blockdev-add', **self.filterless_chain) + self.assert_qmp(result, 'return', {}) + + # We need this so we can query from above the mirror node + result = self.vm.qmp('device_add', + driver='scsi-hd', + id='virtio', + bus='vio-scsi.0', + drive='source') + self.assert_qmp(result, 'return', {}) + + result = self.vm.qmp('blockdev-mirror', + job_id='mirror', + device='source', + target='target', + sync='top', + filter_node_name='mirror-filter') + self.assert_qmp(result, 'return', {}) + + # With a node-name given to it, the mirror filter should now + # be visible + blockdevs = self.vm.qmp('query-block')['return'] + device_info = next(dev for dev in blockdevs if dev['qdev'] == 'virtio') + + assert device_info['inserted']['node-name'] == 'mirror-filter' + + self.complete_and_wait('mirror') + + if __name__ == '__main__': iotests.main(supported_fmts=['qcow2', 'qed'], supported_protocols=['file'], diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out index 53abe11d737d2fede8f1f35f5846f5a050ee92ca..46651953e889d3e3d47a038c71d8831101ce0fbe 100644 --- a/tests/qemu-iotests/041.out +++ b/tests/qemu-iotests/041.out @@ -1,5 +1,5 @@ -........................................................................................................ +........................................................................................................... ---------------------------------------------------------------------- -Ran 104 tests +Ran 107 tests OK diff --git a/tests/qemu-iotests/042 b/tests/qemu-iotests/042 index 0e85b356b76a0a9cde88100254318cf15f45288f..e8f23a174ce7e256cb560faa00c54935725311cc 100755 --- a/tests/qemu-iotests/042 +++ b/tests/qemu-iotests/042 @@ -64,8 +64,8 @@ _check_test_img echo echo "== Rebasing the image ==" -$QEMU_IMG rebase -u -b "$TEST_IMG.orig" "$TEST_IMG" -$QEMU_IMG rebase -b "$TEST_IMG.orig" "$TEST_IMG" +$QEMU_IMG rebase -u -b "$TEST_IMG.orig" -F $IMGFMT "$TEST_IMG" +$QEMU_IMG rebase -b "$TEST_IMG.orig" -F $IMGFMT "$TEST_IMG" _check_test_img # success, all done diff --git a/tests/qemu-iotests/043 b/tests/qemu-iotests/043 index b102e49208b820dcbcf893f77c5f69c653229a73..3271737f69cce827393b912320afdb3b5863421b 100755 --- a/tests/qemu-iotests/043 +++ b/tests/qemu-iotests/043 @@ -46,7 +46,7 @@ _supported_proto file size=128M _make_test_img $size -$QEMU_IMG rebase -u -b "$TEST_IMG" "$TEST_IMG" +$QEMU_IMG rebase -u -b "$TEST_IMG" -F $IMGFMT "$TEST_IMG" echo echo "== backing file references self ==" @@ -54,8 +54,8 @@ _img_info --backing-chain _make_test_img $size mv "$TEST_IMG" "$TEST_IMG.base" -_make_test_img -b "$TEST_IMG.base" $size -$QEMU_IMG rebase -u -b "$TEST_IMG" "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $size +$QEMU_IMG rebase -u -b "$TEST_IMG" -F $IMGFMT "$TEST_IMG.base" echo echo "== parent references self ==" @@ -63,12 +63,12 @@ _img_info --backing-chain _make_test_img $size mv "$TEST_IMG" "$TEST_IMG.1.base" -_make_test_img -b "$TEST_IMG.1.base" $size +_make_test_img -b "$TEST_IMG.1.base" -F $IMGFMT $size mv "$TEST_IMG" "$TEST_IMG.2.base" -_make_test_img -b "$TEST_IMG.2.base" $size +_make_test_img -b "$TEST_IMG.2.base" -F $IMGFMT $size mv "$TEST_IMG" "$TEST_IMG.3.base" -_make_test_img -b "$TEST_IMG.3.base" $size -$QEMU_IMG rebase -u -b "$TEST_IMG.2.base" "$TEST_IMG.1.base" +_make_test_img -b "$TEST_IMG.3.base" -F $IMGFMT $size +$QEMU_IMG rebase -u -b "$TEST_IMG.2.base" -F $IMGFMT "$TEST_IMG.1.base" echo echo "== ancestor references another ancestor ==" @@ -76,17 +76,18 @@ _img_info --backing-chain _make_test_img $size mv "$TEST_IMG" "$TEST_IMG.1.base" -_make_test_img -b "$TEST_IMG.1.base" $size +_make_test_img -b "$TEST_IMG.1.base" -F $IMGFMT $size mv "$TEST_IMG" "$TEST_IMG.2.base" -_make_test_img -b "$TEST_IMG.2.base" $size +_make_test_img -b "$TEST_IMG.2.base" -F $IMGFMT $size echo echo "== finite chain of length 3 (human) ==" -_img_info --backing-chain +# Exclude backing format, since qed differs from qcow2 on what gets stored +_img_info --backing-chain | grep -v '^backing file format:' echo echo "== finite chain of length 3 (json) ==" -_img_info --backing-chain --output=json +_img_info --backing-chain --output=json | grep -v 'backing-filename-format' # success, all done echo "*** done" diff --git a/tests/qemu-iotests/043.out b/tests/qemu-iotests/043.out index 0280f999ce12178e83767a8c82571a9949b9b271..63ecb21816905bce0892f793998dd191615d3cb4 100644 --- a/tests/qemu-iotests/043.out +++ b/tests/qemu-iotests/043.out @@ -4,20 +4,20 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 == backing file references self == qemu-img: Backing file 'TEST_DIR/t.IMGFMT' creates an infinite loop. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT == parent references self == qemu-img: Backing file 'TEST_DIR/t.IMGFMT' creates an infinite loop. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.1.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.2.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.3.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.1.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.2.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.3.base backing_fmt=IMGFMT == ancestor references another ancestor == qemu-img: Backing file 'TEST_DIR/t.IMGFMT.2.base' creates an infinite loop. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.1.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.2.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.1.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.2.base backing_fmt=IMGFMT == finite chain of length 3 (human) == image: TEST_DIR/t.IMGFMT diff --git a/tests/qemu-iotests/046 b/tests/qemu-iotests/046 index ecbe5fc0f44354aca343ee5b3cc077576d9fb2ea..88b3363c196d241a195aa4eeef448b2321c0c6a7 100755 --- a/tests/qemu-iotests/046 +++ b/tests/qemu-iotests/046 @@ -69,7 +69,7 @@ backing_io 0 32 write | $QEMU_IO "$TEST_IMG" | _filter_qemu_io mv "$TEST_IMG" "$TEST_IMG.base" -_make_test_img -b "$TEST_IMG.base" 6G +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT 6G echo echo "== Some concurrent requests touching the same cluster ==" diff --git a/tests/qemu-iotests/046.out b/tests/qemu-iotests/046.out index 70783041e237908b7140a77e0a8666f5714b3767..b022bcddd502fa1ccadf6b5b72246fde4bd3f386 100644 --- a/tests/qemu-iotests/046.out +++ b/tests/qemu-iotests/046.out @@ -66,7 +66,7 @@ wrote 65536/65536 bytes at offset 1966080 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 2031616 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT == Some concurrent requests touching the same cluster == blkdebug: Suspended request 'A' diff --git a/tests/qemu-iotests/049 b/tests/qemu-iotests/049 index 051a1c79e07d383367908243f2678aba5f7b4ce3..82b1e6c202211a177423959bf70ef06acf9a2687 100755 --- a/tests/qemu-iotests/049 +++ b/tests/qemu-iotests/049 @@ -119,6 +119,10 @@ test_qemu_img create -f $IMGFMT -o compat=1.1,lazy_refcounts=on "$TEST_IMG" 64M test_qemu_img create -f $IMGFMT -o compat=0.10,lazy_refcounts=off "$TEST_IMG" 64M test_qemu_img create -f $IMGFMT -o compat=0.10,lazy_refcounts=on "$TEST_IMG" 64M +echo "== Expect error when backing file name is empty string ==" +echo +test_qemu_img create -f $IMGFMT -b '' $TEST_IMG 1M + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out index c54ae21b868a1b18a084b3cb84bb8b1ae691315d..b1d8fd9107efc41d1b121121ce1313a360728a7f 100644 --- a/tests/qemu-iotests/049.out +++ b/tests/qemu-iotests/049.out @@ -4,90 +4,90 @@ QA output created by 049 == 1. Traditional size parameter == qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024b -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1k -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1K -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1G -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1073741824 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1T -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1099511627776 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0b -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5k -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5K -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1572864 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5G -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1610612736 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5T -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1649267441664 lazy_refcounts=off refcount_bits=16 == 2. Specifying size via -o == qemu-img create -f qcow2 -o size=1024 TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1024b TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1k TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1K TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1M TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1G TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1073741824 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1T TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1099511627776 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1024.0 TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1024.0b TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1.5k TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1.5K TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1.5M TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1572864 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1.5G TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1610612736 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1.5T TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1649267441664 lazy_refcounts=off refcount_bits=16 == 3. Invalid sizes == @@ -129,84 +129,89 @@ qemu-img: TEST_DIR/t.qcow2: The image size must be specified only once == Check correct interpretation of suffixes for cluster size == qemu-img create -f qcow2 -o cluster_size=1024 TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1024b TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1k TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1K TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1M TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1048576 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1048576 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1024.0 TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1024.0b TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=0.5k TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=512 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=512 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=0.5K TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=512 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=512 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=0.5M TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=524288 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=524288 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 == Check compat level option == qemu-img create -f qcow2 -o compat=0.10 TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o compat=1.1 TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o compat=0.42 TEST_DIR/t.qcow2 64M +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.42 lazy_refcounts=off refcount_bits=16 qemu-img: TEST_DIR/t.qcow2: Invalid parameter '0.42' -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.42 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib qemu-img create -f qcow2 -o compat=foobar TEST_DIR/t.qcow2 64M +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=foobar lazy_refcounts=off refcount_bits=16 qemu-img: TEST_DIR/t.qcow2: Invalid parameter 'foobar' -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=foobar cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib == Check preallocation option == qemu-img create -f qcow2 -o preallocation=off TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=off lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o preallocation=metadata TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=metadata lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=metadata compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o preallocation=1234 TEST_DIR/t.qcow2 64M +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=1234 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 qemu-img: TEST_DIR/t.qcow2: Invalid parameter '1234' -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=1234 lazy_refcounts=off refcount_bits=16 compression_type=zlib == Check encryption option == qemu-img create -f qcow2 -o encryption=off TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 encryption=off cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 --object secret,id=sec0,data=123456 -o encryption=on,encrypt.key-secret=sec0 TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on encrypt.key-secret=sec0 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 encryption=on encrypt.key-secret=sec0 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 == Check lazy_refcounts option (only with v3) == qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=off TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=on TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=on refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=on refcount_bits=16 qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=off TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=on TEST_DIR/t.qcow2 64M +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=on refcount_bits=16 qemu-img: TEST_DIR/t.qcow2: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater) -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=on refcount_bits=16 compression_type=zlib + +== Expect error when backing file name is empty string == + +qemu-img create -f qcow2 -b TEST_DIR/t.qcow2 1M +qemu-img: TEST_DIR/t.qcow2: Expected backing file name, got empty string *** done diff --git a/tests/qemu-iotests/050 b/tests/qemu-iotests/050 index cdc53565410d14d52fc0094fde2134e31313f65a..4b0a390c437c51139427a4f81cdaeb716e3d3447 100755 --- a/tests/qemu-iotests/050 +++ b/tests/qemu-iotests/050 @@ -58,13 +58,13 @@ $QEMU_IO -c "write -P 0x5a 0 1048576" "$TEST_IMG" | _filter_qemu_io TEST_IMG="$TEST_IMG_SAVE" -_make_test_img -b "$TEST_IMG.old" $size +_make_test_img -b "$TEST_IMG.old" -F $IMGFMT $size $QEMU_IO -c "write -z 0 1048576" "$TEST_IMG" | _filter_qemu_io echo echo "== Rebasing the image ==" -$QEMU_IMG rebase -b "$TEST_IMG.new" "$TEST_IMG" +$QEMU_IMG rebase -b "$TEST_IMG.new" -F $IMGFMT "$TEST_IMG" $QEMU_IO -c "read -P 0x00 0 1048576" "$TEST_IMG" | _filter_qemu_io # success, all done diff --git a/tests/qemu-iotests/050.out b/tests/qemu-iotests/050.out index 3602d580dc0596cb396875f55d86e249681c09a1..ab3daeddca3e5f7b8406876ccd7524f84f14cc28 100644 --- a/tests/qemu-iotests/050.out +++ b/tests/qemu-iotests/050.out @@ -7,7 +7,7 @@ wrote 1048576/1048576 bytes at offset 0 Formatting 'TEST_DIR/t.IMGFMT.new', fmt=IMGFMT size=10485760 wrote 1048576/1048576 bytes at offset 0 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=10485760 backing_file=TEST_DIR/t.IMGFMT.old +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=10485760 backing_file=TEST_DIR/t.IMGFMT.old backing_fmt=IMGFMT wrote 1048576/1048576 bytes at offset 0 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 index 034d3a325077b456849ae5d9dd081e088aa398c4..bee26075b207ad9af3f096d7860e19a4927563fc 100755 --- a/tests/qemu-iotests/051 +++ b/tests/qemu-iotests/051 @@ -70,7 +70,7 @@ device_id="drive0" _make_test_img $size cp "$TEST_IMG" "$TEST_IMG.orig" mv "$TEST_IMG" "$TEST_IMG.base" -_make_test_img -b "$TEST_IMG.base" $size +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $size echo echo === Unknown option === diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out index 554c5ca90a02e87de4d045860d62474972a22276..de4771bcb36dc2f4996cf35283a55c2b8cee1257 100644 --- a/tests/qemu-iotests/051.out +++ b/tests/qemu-iotests/051.out @@ -1,6 +1,6 @@ QA output created by 051 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT === Unknown option === diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out index 0ea80d35f0e28041f5460eb211cec266e634fe78..f707471fb00224cfd3c48d5f3f5dce4f1dbcc7be 100644 --- a/tests/qemu-iotests/051.pc.out +++ b/tests/qemu-iotests/051.pc.out @@ -1,6 +1,6 @@ QA output created by 051 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT === Unknown option === @@ -142,7 +142,7 @@ QEMU X.Y.Z monitor - type 'help' for more information Testing: -drive if=ide QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: Initialization of device ide-hd failed: Device needs media, but drive is empty +(qemu) QEMU_PROG: Device needs media, but drive is empty Testing: -drive if=virtio QEMU X.Y.Z monitor - type 'help' for more information @@ -214,7 +214,7 @@ QEMU X.Y.Z monitor - type 'help' for more information Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: Initialization of device ide-hd failed: Block node is read-only +(qemu) QEMU_PROG: Block node is read-only Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on QEMU X.Y.Z monitor - type 'help' for more information diff --git a/tests/qemu-iotests/054.out b/tests/qemu-iotests/054.out index e6ec430edd4771759fab14377542f9acbbe0e47d..71f18bb9876001533d5e847a814f34ac31ae2023 100644 --- a/tests/qemu-iotests/054.out +++ b/tests/qemu-iotests/054.out @@ -1,8 +1,8 @@ QA output created by 054 creating too large image (1 EB) -qemu-img: TEST_DIR/t.IMGFMT: The image size is too large for file format 'IMGFMT' (try using a larger cluster size) Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1152921504606846976 +qemu-img: TEST_DIR/t.IMGFMT: The image size is too large for file format 'IMGFMT' (try using a larger cluster size) creating too large image (1 EB) using qcow2.py Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 diff --git a/tests/qemu-iotests/056 b/tests/qemu-iotests/056 index f73fc74457df3fda93a01f8e5133f6535f69b67c..052456aa003ffceb8f5601582005b98f85eeb28a 100755 --- a/tests/qemu-iotests/056 +++ b/tests/qemu-iotests/056 @@ -54,7 +54,8 @@ class TestSyncModesNoneAndTop(iotests.QMPTestCase): def setUp(self): create_image(backing_img, TestSyncModesNoneAndTop.image_len) - qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) + qemu_img('create', '-f', iotests.imgfmt, + '-o', 'backing_file=%s' % backing_img, '-F', 'raw', test_img) qemu_io('-c', 'write -P0x41 0 512', test_img) qemu_io('-c', 'write -P0xd5 1M 32k', test_img) qemu_io('-c', 'write -P0xdc 32M 124k', test_img) diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059 index 4c90fc03633b594073384d9ebe48a3d621446f00..dcc442be9f3ca5ff8a9505a3b0f5dc42d9952f28 100755 --- a/tests/qemu-iotests/059 +++ b/tests/qemu-iotests/059 @@ -82,7 +82,7 @@ _cleanup_test_img echo echo "=== Testing big twoGbMaxExtentFlat ===" _make_test_img -o "subformat=twoGbMaxExtentFlat" 1000G -$QEMU_IMG info $TEST_IMG | _filter_testdir | sed -e 's/cid: [0-9]*/cid: XXXXXXXX/' +_img_info --format-specific | _filter_img_info --format-specific _cleanup_test_img echo diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out index 39bf7e211d6977cd37a7f0c9ce07563b11e4fd46..2b83c0c8b66b2b92eb50b7ed5b70bab5daf6045a 100644 --- a/tests/qemu-iotests/059.out +++ b/tests/qemu-iotests/059.out @@ -19,2019 +19,2018 @@ file format: IMGFMT virtual size: 2 GiB (2147483648 bytes) === Testing monolithicFlat with zeroed_grain === -qemu-img: TEST_DIR/t.IMGFMT: Flat image can't enable zeroed grain Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648 +qemu-img: TEST_DIR/t.IMGFMT: Flat image can't enable zeroed grain === Testing big twoGbMaxExtentFlat === Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824000 -image: TEST_DIR/t.vmdk -file format: vmdk +image: TEST_DIR/t.IMGFMT +file format: IMGFMT virtual size: 0.977 TiB (1073741824000 bytes) -disk size: 1.97 MiB Format specific information: - cid: XXXXXXXX - parent cid: XXXXXXXX + cid: XXXXXXXXXX + parent cid: XXXXXXXXXX create type: twoGbMaxExtentFlat extents: [0]: virtual size: 2147483648 - filename: TEST_DIR/t-f001.vmdk + filename: TEST_DIR/t-f001.IMGFMT format: FLAT [1]: virtual size: 2147483648 - filename: TEST_DIR/t-f002.vmdk + filename: TEST_DIR/t-f002.IMGFMT format: FLAT [2]: virtual size: 2147483648 - filename: TEST_DIR/t-f003.vmdk + filename: TEST_DIR/t-f003.IMGFMT format: FLAT [3]: virtual size: 2147483648 - filename: TEST_DIR/t-f004.vmdk + filename: TEST_DIR/t-f004.IMGFMT format: FLAT [4]: virtual size: 2147483648 - filename: TEST_DIR/t-f005.vmdk + filename: TEST_DIR/t-f005.IMGFMT format: FLAT [5]: virtual size: 2147483648 - filename: TEST_DIR/t-f006.vmdk + filename: TEST_DIR/t-f006.IMGFMT format: FLAT [6]: virtual size: 2147483648 - filename: TEST_DIR/t-f007.vmdk + filename: TEST_DIR/t-f007.IMGFMT format: FLAT [7]: virtual size: 2147483648 - filename: TEST_DIR/t-f008.vmdk + filename: TEST_DIR/t-f008.IMGFMT format: FLAT [8]: virtual size: 2147483648 - filename: TEST_DIR/t-f009.vmdk + filename: TEST_DIR/t-f009.IMGFMT format: FLAT [9]: virtual size: 2147483648 - filename: TEST_DIR/t-f010.vmdk + filename: TEST_DIR/t-f010.IMGFMT format: FLAT [10]: virtual size: 2147483648 - filename: TEST_DIR/t-f011.vmdk + filename: TEST_DIR/t-f011.IMGFMT format: FLAT [11]: virtual size: 2147483648 - filename: TEST_DIR/t-f012.vmdk + filename: TEST_DIR/t-f012.IMGFMT format: FLAT [12]: virtual size: 2147483648 - filename: TEST_DIR/t-f013.vmdk + filename: TEST_DIR/t-f013.IMGFMT format: FLAT [13]: virtual size: 2147483648 - filename: TEST_DIR/t-f014.vmdk + filename: TEST_DIR/t-f014.IMGFMT format: FLAT [14]: virtual size: 2147483648 - filename: TEST_DIR/t-f015.vmdk + filename: TEST_DIR/t-f015.IMGFMT format: FLAT [15]: virtual size: 2147483648 - filename: TEST_DIR/t-f016.vmdk + filename: TEST_DIR/t-f016.IMGFMT format: FLAT [16]: virtual size: 2147483648 - filename: TEST_DIR/t-f017.vmdk + filename: TEST_DIR/t-f017.IMGFMT format: FLAT [17]: virtual size: 2147483648 - filename: TEST_DIR/t-f018.vmdk + filename: TEST_DIR/t-f018.IMGFMT format: FLAT [18]: virtual size: 2147483648 - filename: TEST_DIR/t-f019.vmdk + filename: TEST_DIR/t-f019.IMGFMT format: FLAT [19]: virtual size: 2147483648 - filename: TEST_DIR/t-f020.vmdk + filename: TEST_DIR/t-f020.IMGFMT format: FLAT [20]: virtual size: 2147483648 - filename: TEST_DIR/t-f021.vmdk + filename: TEST_DIR/t-f021.IMGFMT format: FLAT [21]: virtual size: 2147483648 - filename: TEST_DIR/t-f022.vmdk + filename: TEST_DIR/t-f022.IMGFMT format: FLAT [22]: virtual size: 2147483648 - filename: TEST_DIR/t-f023.vmdk + filename: TEST_DIR/t-f023.IMGFMT format: FLAT [23]: virtual size: 2147483648 - filename: TEST_DIR/t-f024.vmdk + filename: TEST_DIR/t-f024.IMGFMT format: FLAT [24]: virtual size: 2147483648 - filename: TEST_DIR/t-f025.vmdk + filename: TEST_DIR/t-f025.IMGFMT format: FLAT [25]: virtual size: 2147483648 - filename: TEST_DIR/t-f026.vmdk + filename: TEST_DIR/t-f026.IMGFMT format: FLAT [26]: virtual size: 2147483648 - filename: TEST_DIR/t-f027.vmdk + filename: TEST_DIR/t-f027.IMGFMT format: FLAT [27]: virtual size: 2147483648 - filename: TEST_DIR/t-f028.vmdk + filename: TEST_DIR/t-f028.IMGFMT format: FLAT [28]: virtual size: 2147483648 - filename: TEST_DIR/t-f029.vmdk + filename: TEST_DIR/t-f029.IMGFMT format: FLAT [29]: virtual size: 2147483648 - filename: TEST_DIR/t-f030.vmdk + filename: TEST_DIR/t-f030.IMGFMT format: FLAT [30]: virtual size: 2147483648 - filename: TEST_DIR/t-f031.vmdk + filename: TEST_DIR/t-f031.IMGFMT format: FLAT [31]: virtual size: 2147483648 - filename: TEST_DIR/t-f032.vmdk + filename: TEST_DIR/t-f032.IMGFMT format: FLAT [32]: virtual size: 2147483648 - filename: TEST_DIR/t-f033.vmdk + filename: TEST_DIR/t-f033.IMGFMT format: FLAT [33]: virtual size: 2147483648 - filename: TEST_DIR/t-f034.vmdk + filename: TEST_DIR/t-f034.IMGFMT format: FLAT [34]: virtual size: 2147483648 - filename: TEST_DIR/t-f035.vmdk + filename: TEST_DIR/t-f035.IMGFMT format: FLAT [35]: virtual size: 2147483648 - filename: TEST_DIR/t-f036.vmdk + filename: TEST_DIR/t-f036.IMGFMT format: FLAT [36]: virtual size: 2147483648 - filename: TEST_DIR/t-f037.vmdk + filename: TEST_DIR/t-f037.IMGFMT format: FLAT [37]: virtual size: 2147483648 - filename: TEST_DIR/t-f038.vmdk + filename: TEST_DIR/t-f038.IMGFMT format: FLAT [38]: virtual size: 2147483648 - filename: TEST_DIR/t-f039.vmdk + filename: TEST_DIR/t-f039.IMGFMT format: FLAT [39]: virtual size: 2147483648 - filename: TEST_DIR/t-f040.vmdk + filename: TEST_DIR/t-f040.IMGFMT format: FLAT [40]: virtual size: 2147483648 - filename: TEST_DIR/t-f041.vmdk + filename: TEST_DIR/t-f041.IMGFMT format: FLAT [41]: virtual size: 2147483648 - filename: TEST_DIR/t-f042.vmdk + filename: TEST_DIR/t-f042.IMGFMT format: FLAT [42]: virtual size: 2147483648 - filename: TEST_DIR/t-f043.vmdk + filename: TEST_DIR/t-f043.IMGFMT format: FLAT [43]: virtual size: 2147483648 - filename: TEST_DIR/t-f044.vmdk + filename: TEST_DIR/t-f044.IMGFMT format: FLAT [44]: virtual size: 2147483648 - filename: TEST_DIR/t-f045.vmdk + filename: TEST_DIR/t-f045.IMGFMT format: FLAT [45]: virtual size: 2147483648 - filename: TEST_DIR/t-f046.vmdk + filename: TEST_DIR/t-f046.IMGFMT format: FLAT [46]: virtual size: 2147483648 - filename: TEST_DIR/t-f047.vmdk + filename: TEST_DIR/t-f047.IMGFMT format: FLAT [47]: virtual size: 2147483648 - filename: TEST_DIR/t-f048.vmdk + filename: TEST_DIR/t-f048.IMGFMT format: FLAT [48]: virtual size: 2147483648 - filename: TEST_DIR/t-f049.vmdk + filename: TEST_DIR/t-f049.IMGFMT format: FLAT [49]: virtual size: 2147483648 - filename: TEST_DIR/t-f050.vmdk + filename: TEST_DIR/t-f050.IMGFMT format: FLAT [50]: virtual size: 2147483648 - filename: TEST_DIR/t-f051.vmdk + filename: TEST_DIR/t-f051.IMGFMT format: FLAT [51]: virtual size: 2147483648 - filename: TEST_DIR/t-f052.vmdk + filename: TEST_DIR/t-f052.IMGFMT format: FLAT [52]: virtual size: 2147483648 - filename: TEST_DIR/t-f053.vmdk + filename: TEST_DIR/t-f053.IMGFMT format: FLAT [53]: virtual size: 2147483648 - filename: TEST_DIR/t-f054.vmdk + filename: TEST_DIR/t-f054.IMGFMT format: FLAT [54]: virtual size: 2147483648 - filename: TEST_DIR/t-f055.vmdk + filename: TEST_DIR/t-f055.IMGFMT format: FLAT [55]: virtual size: 2147483648 - filename: TEST_DIR/t-f056.vmdk + filename: TEST_DIR/t-f056.IMGFMT format: FLAT [56]: virtual size: 2147483648 - filename: TEST_DIR/t-f057.vmdk + filename: TEST_DIR/t-f057.IMGFMT format: FLAT [57]: virtual size: 2147483648 - filename: TEST_DIR/t-f058.vmdk + filename: TEST_DIR/t-f058.IMGFMT format: FLAT [58]: virtual size: 2147483648 - filename: TEST_DIR/t-f059.vmdk + filename: TEST_DIR/t-f059.IMGFMT format: FLAT [59]: virtual size: 2147483648 - filename: TEST_DIR/t-f060.vmdk + filename: TEST_DIR/t-f060.IMGFMT format: FLAT [60]: virtual size: 2147483648 - filename: TEST_DIR/t-f061.vmdk + filename: TEST_DIR/t-f061.IMGFMT format: FLAT [61]: virtual size: 2147483648 - filename: TEST_DIR/t-f062.vmdk + filename: TEST_DIR/t-f062.IMGFMT format: FLAT [62]: virtual size: 2147483648 - filename: TEST_DIR/t-f063.vmdk + filename: TEST_DIR/t-f063.IMGFMT format: FLAT [63]: virtual size: 2147483648 - filename: TEST_DIR/t-f064.vmdk + filename: TEST_DIR/t-f064.IMGFMT format: FLAT [64]: virtual size: 2147483648 - filename: TEST_DIR/t-f065.vmdk + filename: TEST_DIR/t-f065.IMGFMT format: FLAT [65]: virtual size: 2147483648 - filename: TEST_DIR/t-f066.vmdk + filename: TEST_DIR/t-f066.IMGFMT format: FLAT [66]: virtual size: 2147483648 - filename: TEST_DIR/t-f067.vmdk + filename: TEST_DIR/t-f067.IMGFMT format: FLAT [67]: virtual size: 2147483648 - filename: TEST_DIR/t-f068.vmdk + filename: TEST_DIR/t-f068.IMGFMT format: FLAT [68]: virtual size: 2147483648 - filename: TEST_DIR/t-f069.vmdk + filename: TEST_DIR/t-f069.IMGFMT format: FLAT [69]: virtual size: 2147483648 - filename: TEST_DIR/t-f070.vmdk + filename: TEST_DIR/t-f070.IMGFMT format: FLAT [70]: virtual size: 2147483648 - filename: TEST_DIR/t-f071.vmdk + filename: TEST_DIR/t-f071.IMGFMT format: FLAT [71]: virtual size: 2147483648 - filename: TEST_DIR/t-f072.vmdk + filename: TEST_DIR/t-f072.IMGFMT format: FLAT [72]: virtual size: 2147483648 - filename: TEST_DIR/t-f073.vmdk + filename: TEST_DIR/t-f073.IMGFMT format: FLAT [73]: virtual size: 2147483648 - filename: TEST_DIR/t-f074.vmdk + filename: TEST_DIR/t-f074.IMGFMT format: FLAT [74]: virtual size: 2147483648 - filename: TEST_DIR/t-f075.vmdk + filename: TEST_DIR/t-f075.IMGFMT format: FLAT [75]: virtual size: 2147483648 - filename: TEST_DIR/t-f076.vmdk + filename: TEST_DIR/t-f076.IMGFMT format: FLAT [76]: virtual size: 2147483648 - filename: TEST_DIR/t-f077.vmdk + filename: TEST_DIR/t-f077.IMGFMT format: FLAT [77]: virtual size: 2147483648 - filename: TEST_DIR/t-f078.vmdk + filename: TEST_DIR/t-f078.IMGFMT format: FLAT [78]: virtual size: 2147483648 - filename: TEST_DIR/t-f079.vmdk + filename: TEST_DIR/t-f079.IMGFMT format: FLAT [79]: virtual size: 2147483648 - filename: TEST_DIR/t-f080.vmdk + filename: TEST_DIR/t-f080.IMGFMT format: FLAT [80]: virtual size: 2147483648 - filename: TEST_DIR/t-f081.vmdk + filename: TEST_DIR/t-f081.IMGFMT format: FLAT [81]: virtual size: 2147483648 - filename: TEST_DIR/t-f082.vmdk + filename: TEST_DIR/t-f082.IMGFMT format: FLAT [82]: virtual size: 2147483648 - filename: TEST_DIR/t-f083.vmdk + filename: TEST_DIR/t-f083.IMGFMT format: FLAT [83]: virtual size: 2147483648 - filename: TEST_DIR/t-f084.vmdk + filename: TEST_DIR/t-f084.IMGFMT format: FLAT [84]: virtual size: 2147483648 - filename: TEST_DIR/t-f085.vmdk + filename: TEST_DIR/t-f085.IMGFMT format: FLAT [85]: virtual size: 2147483648 - filename: TEST_DIR/t-f086.vmdk + filename: TEST_DIR/t-f086.IMGFMT format: FLAT [86]: virtual size: 2147483648 - filename: TEST_DIR/t-f087.vmdk + filename: TEST_DIR/t-f087.IMGFMT format: FLAT [87]: virtual size: 2147483648 - filename: TEST_DIR/t-f088.vmdk + filename: TEST_DIR/t-f088.IMGFMT format: FLAT [88]: virtual size: 2147483648 - filename: TEST_DIR/t-f089.vmdk + filename: TEST_DIR/t-f089.IMGFMT format: FLAT [89]: virtual size: 2147483648 - filename: TEST_DIR/t-f090.vmdk + filename: TEST_DIR/t-f090.IMGFMT format: FLAT [90]: virtual size: 2147483648 - filename: TEST_DIR/t-f091.vmdk + filename: TEST_DIR/t-f091.IMGFMT format: FLAT [91]: virtual size: 2147483648 - filename: TEST_DIR/t-f092.vmdk + filename: TEST_DIR/t-f092.IMGFMT format: FLAT [92]: virtual size: 2147483648 - filename: TEST_DIR/t-f093.vmdk + filename: TEST_DIR/t-f093.IMGFMT format: FLAT [93]: virtual size: 2147483648 - filename: TEST_DIR/t-f094.vmdk + filename: TEST_DIR/t-f094.IMGFMT format: FLAT [94]: virtual size: 2147483648 - filename: TEST_DIR/t-f095.vmdk + filename: TEST_DIR/t-f095.IMGFMT format: FLAT [95]: virtual size: 2147483648 - filename: TEST_DIR/t-f096.vmdk + filename: TEST_DIR/t-f096.IMGFMT format: FLAT [96]: virtual size: 2147483648 - filename: TEST_DIR/t-f097.vmdk + filename: TEST_DIR/t-f097.IMGFMT format: FLAT [97]: virtual size: 2147483648 - filename: TEST_DIR/t-f098.vmdk + filename: TEST_DIR/t-f098.IMGFMT format: FLAT [98]: virtual size: 2147483648 - filename: TEST_DIR/t-f099.vmdk + filename: TEST_DIR/t-f099.IMGFMT format: FLAT [99]: virtual size: 2147483648 - filename: TEST_DIR/t-f100.vmdk + filename: TEST_DIR/t-f100.IMGFMT format: FLAT [100]: virtual size: 2147483648 - filename: TEST_DIR/t-f101.vmdk + filename: TEST_DIR/t-f101.IMGFMT format: FLAT [101]: virtual size: 2147483648 - filename: TEST_DIR/t-f102.vmdk + filename: TEST_DIR/t-f102.IMGFMT format: FLAT [102]: virtual size: 2147483648 - filename: TEST_DIR/t-f103.vmdk + filename: TEST_DIR/t-f103.IMGFMT format: FLAT [103]: virtual size: 2147483648 - filename: TEST_DIR/t-f104.vmdk + filename: TEST_DIR/t-f104.IMGFMT format: FLAT [104]: virtual size: 2147483648 - filename: TEST_DIR/t-f105.vmdk + filename: TEST_DIR/t-f105.IMGFMT format: FLAT [105]: virtual size: 2147483648 - filename: TEST_DIR/t-f106.vmdk + filename: TEST_DIR/t-f106.IMGFMT format: FLAT [106]: virtual size: 2147483648 - filename: TEST_DIR/t-f107.vmdk + filename: TEST_DIR/t-f107.IMGFMT format: FLAT [107]: virtual size: 2147483648 - filename: TEST_DIR/t-f108.vmdk + filename: TEST_DIR/t-f108.IMGFMT format: FLAT [108]: virtual size: 2147483648 - filename: TEST_DIR/t-f109.vmdk + filename: TEST_DIR/t-f109.IMGFMT format: FLAT [109]: virtual size: 2147483648 - filename: TEST_DIR/t-f110.vmdk + filename: TEST_DIR/t-f110.IMGFMT format: FLAT [110]: virtual size: 2147483648 - filename: TEST_DIR/t-f111.vmdk + filename: TEST_DIR/t-f111.IMGFMT format: FLAT [111]: virtual size: 2147483648 - filename: TEST_DIR/t-f112.vmdk + filename: TEST_DIR/t-f112.IMGFMT format: FLAT [112]: virtual size: 2147483648 - filename: TEST_DIR/t-f113.vmdk + filename: TEST_DIR/t-f113.IMGFMT format: FLAT [113]: virtual size: 2147483648 - filename: TEST_DIR/t-f114.vmdk + filename: TEST_DIR/t-f114.IMGFMT format: FLAT [114]: virtual size: 2147483648 - filename: TEST_DIR/t-f115.vmdk + filename: TEST_DIR/t-f115.IMGFMT format: FLAT [115]: virtual size: 2147483648 - filename: TEST_DIR/t-f116.vmdk + filename: TEST_DIR/t-f116.IMGFMT format: FLAT [116]: virtual size: 2147483648 - filename: TEST_DIR/t-f117.vmdk + filename: TEST_DIR/t-f117.IMGFMT format: FLAT [117]: virtual size: 2147483648 - filename: TEST_DIR/t-f118.vmdk + filename: TEST_DIR/t-f118.IMGFMT format: FLAT [118]: virtual size: 2147483648 - filename: TEST_DIR/t-f119.vmdk + filename: TEST_DIR/t-f119.IMGFMT format: FLAT [119]: virtual size: 2147483648 - filename: TEST_DIR/t-f120.vmdk + filename: TEST_DIR/t-f120.IMGFMT format: FLAT [120]: virtual size: 2147483648 - filename: TEST_DIR/t-f121.vmdk + filename: TEST_DIR/t-f121.IMGFMT format: FLAT [121]: virtual size: 2147483648 - filename: TEST_DIR/t-f122.vmdk + filename: TEST_DIR/t-f122.IMGFMT format: FLAT [122]: virtual size: 2147483648 - filename: TEST_DIR/t-f123.vmdk + filename: TEST_DIR/t-f123.IMGFMT format: FLAT [123]: virtual size: 2147483648 - filename: TEST_DIR/t-f124.vmdk + filename: TEST_DIR/t-f124.IMGFMT format: FLAT [124]: virtual size: 2147483648 - filename: TEST_DIR/t-f125.vmdk + filename: TEST_DIR/t-f125.IMGFMT format: FLAT [125]: virtual size: 2147483648 - filename: TEST_DIR/t-f126.vmdk + filename: TEST_DIR/t-f126.IMGFMT format: FLAT [126]: virtual size: 2147483648 - filename: TEST_DIR/t-f127.vmdk + filename: TEST_DIR/t-f127.IMGFMT format: FLAT [127]: virtual size: 2147483648 - filename: TEST_DIR/t-f128.vmdk + filename: TEST_DIR/t-f128.IMGFMT format: FLAT [128]: virtual size: 2147483648 - filename: TEST_DIR/t-f129.vmdk + filename: TEST_DIR/t-f129.IMGFMT format: FLAT [129]: virtual size: 2147483648 - filename: TEST_DIR/t-f130.vmdk + filename: TEST_DIR/t-f130.IMGFMT format: FLAT [130]: virtual size: 2147483648 - filename: TEST_DIR/t-f131.vmdk + filename: TEST_DIR/t-f131.IMGFMT format: FLAT [131]: virtual size: 2147483648 - filename: TEST_DIR/t-f132.vmdk + filename: TEST_DIR/t-f132.IMGFMT format: FLAT [132]: virtual size: 2147483648 - filename: TEST_DIR/t-f133.vmdk + filename: TEST_DIR/t-f133.IMGFMT format: FLAT [133]: virtual size: 2147483648 - filename: TEST_DIR/t-f134.vmdk + filename: TEST_DIR/t-f134.IMGFMT format: FLAT [134]: virtual size: 2147483648 - filename: TEST_DIR/t-f135.vmdk + filename: TEST_DIR/t-f135.IMGFMT format: FLAT [135]: virtual size: 2147483648 - filename: TEST_DIR/t-f136.vmdk + filename: TEST_DIR/t-f136.IMGFMT format: FLAT [136]: virtual size: 2147483648 - filename: TEST_DIR/t-f137.vmdk + filename: TEST_DIR/t-f137.IMGFMT format: FLAT [137]: virtual size: 2147483648 - filename: TEST_DIR/t-f138.vmdk + filename: TEST_DIR/t-f138.IMGFMT format: FLAT [138]: virtual size: 2147483648 - filename: TEST_DIR/t-f139.vmdk + filename: TEST_DIR/t-f139.IMGFMT format: FLAT [139]: virtual size: 2147483648 - filename: TEST_DIR/t-f140.vmdk + filename: TEST_DIR/t-f140.IMGFMT format: FLAT [140]: virtual size: 2147483648 - filename: TEST_DIR/t-f141.vmdk + filename: TEST_DIR/t-f141.IMGFMT format: FLAT [141]: virtual size: 2147483648 - filename: TEST_DIR/t-f142.vmdk + filename: TEST_DIR/t-f142.IMGFMT format: FLAT [142]: virtual size: 2147483648 - filename: TEST_DIR/t-f143.vmdk + filename: TEST_DIR/t-f143.IMGFMT format: FLAT [143]: virtual size: 2147483648 - filename: TEST_DIR/t-f144.vmdk + filename: TEST_DIR/t-f144.IMGFMT format: FLAT [144]: virtual size: 2147483648 - filename: TEST_DIR/t-f145.vmdk + filename: TEST_DIR/t-f145.IMGFMT format: FLAT [145]: virtual size: 2147483648 - filename: TEST_DIR/t-f146.vmdk + filename: TEST_DIR/t-f146.IMGFMT format: FLAT [146]: virtual size: 2147483648 - filename: TEST_DIR/t-f147.vmdk + filename: TEST_DIR/t-f147.IMGFMT format: FLAT [147]: virtual size: 2147483648 - filename: TEST_DIR/t-f148.vmdk + filename: TEST_DIR/t-f148.IMGFMT format: FLAT [148]: virtual size: 2147483648 - filename: TEST_DIR/t-f149.vmdk + filename: TEST_DIR/t-f149.IMGFMT format: FLAT [149]: virtual size: 2147483648 - filename: TEST_DIR/t-f150.vmdk + filename: TEST_DIR/t-f150.IMGFMT format: FLAT [150]: virtual size: 2147483648 - filename: TEST_DIR/t-f151.vmdk + filename: TEST_DIR/t-f151.IMGFMT format: FLAT [151]: virtual size: 2147483648 - filename: TEST_DIR/t-f152.vmdk + filename: TEST_DIR/t-f152.IMGFMT format: FLAT [152]: virtual size: 2147483648 - filename: TEST_DIR/t-f153.vmdk + filename: TEST_DIR/t-f153.IMGFMT format: FLAT [153]: virtual size: 2147483648 - filename: TEST_DIR/t-f154.vmdk + filename: TEST_DIR/t-f154.IMGFMT format: FLAT [154]: virtual size: 2147483648 - filename: TEST_DIR/t-f155.vmdk + filename: TEST_DIR/t-f155.IMGFMT format: FLAT [155]: virtual size: 2147483648 - filename: TEST_DIR/t-f156.vmdk + filename: TEST_DIR/t-f156.IMGFMT format: FLAT [156]: virtual size: 2147483648 - filename: TEST_DIR/t-f157.vmdk + filename: TEST_DIR/t-f157.IMGFMT format: FLAT [157]: virtual size: 2147483648 - filename: TEST_DIR/t-f158.vmdk + filename: TEST_DIR/t-f158.IMGFMT format: FLAT [158]: virtual size: 2147483648 - filename: TEST_DIR/t-f159.vmdk + filename: TEST_DIR/t-f159.IMGFMT format: FLAT [159]: virtual size: 2147483648 - filename: TEST_DIR/t-f160.vmdk + filename: TEST_DIR/t-f160.IMGFMT format: FLAT [160]: virtual size: 2147483648 - filename: TEST_DIR/t-f161.vmdk + filename: TEST_DIR/t-f161.IMGFMT format: FLAT [161]: virtual size: 2147483648 - filename: TEST_DIR/t-f162.vmdk + filename: TEST_DIR/t-f162.IMGFMT format: FLAT [162]: virtual size: 2147483648 - filename: TEST_DIR/t-f163.vmdk + filename: TEST_DIR/t-f163.IMGFMT format: FLAT [163]: virtual size: 2147483648 - filename: TEST_DIR/t-f164.vmdk + filename: TEST_DIR/t-f164.IMGFMT format: FLAT [164]: virtual size: 2147483648 - filename: TEST_DIR/t-f165.vmdk + filename: TEST_DIR/t-f165.IMGFMT format: FLAT [165]: virtual size: 2147483648 - filename: TEST_DIR/t-f166.vmdk + filename: TEST_DIR/t-f166.IMGFMT format: FLAT [166]: virtual size: 2147483648 - filename: TEST_DIR/t-f167.vmdk + filename: TEST_DIR/t-f167.IMGFMT format: FLAT [167]: virtual size: 2147483648 - filename: TEST_DIR/t-f168.vmdk + filename: TEST_DIR/t-f168.IMGFMT format: FLAT [168]: virtual size: 2147483648 - filename: TEST_DIR/t-f169.vmdk + filename: TEST_DIR/t-f169.IMGFMT format: FLAT [169]: virtual size: 2147483648 - filename: TEST_DIR/t-f170.vmdk + filename: TEST_DIR/t-f170.IMGFMT format: FLAT [170]: virtual size: 2147483648 - filename: TEST_DIR/t-f171.vmdk + filename: TEST_DIR/t-f171.IMGFMT format: FLAT [171]: virtual size: 2147483648 - filename: TEST_DIR/t-f172.vmdk + filename: TEST_DIR/t-f172.IMGFMT format: FLAT [172]: virtual size: 2147483648 - filename: TEST_DIR/t-f173.vmdk + filename: TEST_DIR/t-f173.IMGFMT format: FLAT [173]: virtual size: 2147483648 - filename: TEST_DIR/t-f174.vmdk + filename: TEST_DIR/t-f174.IMGFMT format: FLAT [174]: virtual size: 2147483648 - filename: TEST_DIR/t-f175.vmdk + filename: TEST_DIR/t-f175.IMGFMT format: FLAT [175]: virtual size: 2147483648 - filename: TEST_DIR/t-f176.vmdk + filename: TEST_DIR/t-f176.IMGFMT format: FLAT [176]: virtual size: 2147483648 - filename: TEST_DIR/t-f177.vmdk + filename: TEST_DIR/t-f177.IMGFMT format: FLAT [177]: virtual size: 2147483648 - filename: TEST_DIR/t-f178.vmdk + filename: TEST_DIR/t-f178.IMGFMT format: FLAT [178]: virtual size: 2147483648 - filename: TEST_DIR/t-f179.vmdk + filename: TEST_DIR/t-f179.IMGFMT format: FLAT [179]: virtual size: 2147483648 - filename: TEST_DIR/t-f180.vmdk + filename: TEST_DIR/t-f180.IMGFMT format: FLAT [180]: virtual size: 2147483648 - filename: TEST_DIR/t-f181.vmdk + filename: TEST_DIR/t-f181.IMGFMT format: FLAT [181]: virtual size: 2147483648 - filename: TEST_DIR/t-f182.vmdk + filename: TEST_DIR/t-f182.IMGFMT format: FLAT [182]: virtual size: 2147483648 - filename: TEST_DIR/t-f183.vmdk + filename: TEST_DIR/t-f183.IMGFMT format: FLAT [183]: virtual size: 2147483648 - filename: TEST_DIR/t-f184.vmdk + filename: TEST_DIR/t-f184.IMGFMT format: FLAT [184]: virtual size: 2147483648 - filename: TEST_DIR/t-f185.vmdk + filename: TEST_DIR/t-f185.IMGFMT format: FLAT [185]: virtual size: 2147483648 - filename: TEST_DIR/t-f186.vmdk + filename: TEST_DIR/t-f186.IMGFMT format: FLAT [186]: virtual size: 2147483648 - filename: TEST_DIR/t-f187.vmdk + filename: TEST_DIR/t-f187.IMGFMT format: FLAT [187]: virtual size: 2147483648 - filename: TEST_DIR/t-f188.vmdk + filename: TEST_DIR/t-f188.IMGFMT format: FLAT [188]: virtual size: 2147483648 - filename: TEST_DIR/t-f189.vmdk + filename: TEST_DIR/t-f189.IMGFMT format: FLAT [189]: virtual size: 2147483648 - filename: TEST_DIR/t-f190.vmdk + filename: TEST_DIR/t-f190.IMGFMT format: FLAT [190]: virtual size: 2147483648 - filename: TEST_DIR/t-f191.vmdk + filename: TEST_DIR/t-f191.IMGFMT format: FLAT [191]: virtual size: 2147483648 - filename: TEST_DIR/t-f192.vmdk + filename: TEST_DIR/t-f192.IMGFMT format: FLAT [192]: virtual size: 2147483648 - filename: TEST_DIR/t-f193.vmdk + filename: TEST_DIR/t-f193.IMGFMT format: FLAT [193]: virtual size: 2147483648 - filename: TEST_DIR/t-f194.vmdk + filename: TEST_DIR/t-f194.IMGFMT format: FLAT [194]: virtual size: 2147483648 - filename: TEST_DIR/t-f195.vmdk + filename: TEST_DIR/t-f195.IMGFMT format: FLAT [195]: virtual size: 2147483648 - filename: TEST_DIR/t-f196.vmdk + filename: TEST_DIR/t-f196.IMGFMT format: FLAT [196]: virtual size: 2147483648 - filename: TEST_DIR/t-f197.vmdk + filename: TEST_DIR/t-f197.IMGFMT format: FLAT [197]: virtual size: 2147483648 - filename: TEST_DIR/t-f198.vmdk + filename: TEST_DIR/t-f198.IMGFMT format: FLAT [198]: virtual size: 2147483648 - filename: TEST_DIR/t-f199.vmdk + filename: TEST_DIR/t-f199.IMGFMT format: FLAT [199]: virtual size: 2147483648 - filename: TEST_DIR/t-f200.vmdk + filename: TEST_DIR/t-f200.IMGFMT format: FLAT [200]: virtual size: 2147483648 - filename: TEST_DIR/t-f201.vmdk + filename: TEST_DIR/t-f201.IMGFMT format: FLAT [201]: virtual size: 2147483648 - filename: TEST_DIR/t-f202.vmdk + filename: TEST_DIR/t-f202.IMGFMT format: FLAT [202]: virtual size: 2147483648 - filename: TEST_DIR/t-f203.vmdk + filename: TEST_DIR/t-f203.IMGFMT format: FLAT [203]: virtual size: 2147483648 - filename: TEST_DIR/t-f204.vmdk + filename: TEST_DIR/t-f204.IMGFMT format: FLAT [204]: virtual size: 2147483648 - filename: TEST_DIR/t-f205.vmdk + filename: TEST_DIR/t-f205.IMGFMT format: FLAT [205]: virtual size: 2147483648 - filename: TEST_DIR/t-f206.vmdk + filename: TEST_DIR/t-f206.IMGFMT format: FLAT [206]: virtual size: 2147483648 - filename: TEST_DIR/t-f207.vmdk + filename: TEST_DIR/t-f207.IMGFMT format: FLAT [207]: virtual size: 2147483648 - filename: TEST_DIR/t-f208.vmdk + filename: TEST_DIR/t-f208.IMGFMT format: FLAT [208]: virtual size: 2147483648 - filename: TEST_DIR/t-f209.vmdk + filename: TEST_DIR/t-f209.IMGFMT format: FLAT [209]: virtual size: 2147483648 - filename: TEST_DIR/t-f210.vmdk + filename: TEST_DIR/t-f210.IMGFMT format: FLAT [210]: virtual size: 2147483648 - filename: TEST_DIR/t-f211.vmdk + filename: TEST_DIR/t-f211.IMGFMT format: FLAT [211]: virtual size: 2147483648 - filename: TEST_DIR/t-f212.vmdk + filename: TEST_DIR/t-f212.IMGFMT format: FLAT [212]: virtual size: 2147483648 - filename: TEST_DIR/t-f213.vmdk + filename: TEST_DIR/t-f213.IMGFMT format: FLAT [213]: virtual size: 2147483648 - filename: TEST_DIR/t-f214.vmdk + filename: TEST_DIR/t-f214.IMGFMT format: FLAT [214]: virtual size: 2147483648 - filename: TEST_DIR/t-f215.vmdk + filename: TEST_DIR/t-f215.IMGFMT format: FLAT [215]: virtual size: 2147483648 - filename: TEST_DIR/t-f216.vmdk + filename: TEST_DIR/t-f216.IMGFMT format: FLAT [216]: virtual size: 2147483648 - filename: TEST_DIR/t-f217.vmdk + filename: TEST_DIR/t-f217.IMGFMT format: FLAT [217]: virtual size: 2147483648 - filename: TEST_DIR/t-f218.vmdk + filename: TEST_DIR/t-f218.IMGFMT format: FLAT [218]: virtual size: 2147483648 - filename: TEST_DIR/t-f219.vmdk + filename: TEST_DIR/t-f219.IMGFMT format: FLAT [219]: virtual size: 2147483648 - filename: TEST_DIR/t-f220.vmdk + filename: TEST_DIR/t-f220.IMGFMT format: FLAT [220]: virtual size: 2147483648 - filename: TEST_DIR/t-f221.vmdk + filename: TEST_DIR/t-f221.IMGFMT format: FLAT [221]: virtual size: 2147483648 - filename: TEST_DIR/t-f222.vmdk + filename: TEST_DIR/t-f222.IMGFMT format: FLAT [222]: virtual size: 2147483648 - filename: TEST_DIR/t-f223.vmdk + filename: TEST_DIR/t-f223.IMGFMT format: FLAT [223]: virtual size: 2147483648 - filename: TEST_DIR/t-f224.vmdk + filename: TEST_DIR/t-f224.IMGFMT format: FLAT [224]: virtual size: 2147483648 - filename: TEST_DIR/t-f225.vmdk + filename: TEST_DIR/t-f225.IMGFMT format: FLAT [225]: virtual size: 2147483648 - filename: TEST_DIR/t-f226.vmdk + filename: TEST_DIR/t-f226.IMGFMT format: FLAT [226]: virtual size: 2147483648 - filename: TEST_DIR/t-f227.vmdk + filename: TEST_DIR/t-f227.IMGFMT format: FLAT [227]: virtual size: 2147483648 - filename: TEST_DIR/t-f228.vmdk + filename: TEST_DIR/t-f228.IMGFMT format: FLAT [228]: virtual size: 2147483648 - filename: TEST_DIR/t-f229.vmdk + filename: TEST_DIR/t-f229.IMGFMT format: FLAT [229]: virtual size: 2147483648 - filename: TEST_DIR/t-f230.vmdk + filename: TEST_DIR/t-f230.IMGFMT format: FLAT [230]: virtual size: 2147483648 - filename: TEST_DIR/t-f231.vmdk + filename: TEST_DIR/t-f231.IMGFMT format: FLAT [231]: virtual size: 2147483648 - filename: TEST_DIR/t-f232.vmdk + filename: TEST_DIR/t-f232.IMGFMT format: FLAT [232]: virtual size: 2147483648 - filename: TEST_DIR/t-f233.vmdk + filename: TEST_DIR/t-f233.IMGFMT format: FLAT [233]: virtual size: 2147483648 - filename: TEST_DIR/t-f234.vmdk + filename: TEST_DIR/t-f234.IMGFMT format: FLAT [234]: virtual size: 2147483648 - filename: TEST_DIR/t-f235.vmdk + filename: TEST_DIR/t-f235.IMGFMT format: FLAT [235]: virtual size: 2147483648 - filename: TEST_DIR/t-f236.vmdk + filename: TEST_DIR/t-f236.IMGFMT format: FLAT [236]: virtual size: 2147483648 - filename: TEST_DIR/t-f237.vmdk + filename: TEST_DIR/t-f237.IMGFMT format: FLAT [237]: virtual size: 2147483648 - filename: TEST_DIR/t-f238.vmdk + filename: TEST_DIR/t-f238.IMGFMT format: FLAT [238]: virtual size: 2147483648 - filename: TEST_DIR/t-f239.vmdk + filename: TEST_DIR/t-f239.IMGFMT format: FLAT [239]: virtual size: 2147483648 - filename: TEST_DIR/t-f240.vmdk + filename: TEST_DIR/t-f240.IMGFMT format: FLAT [240]: virtual size: 2147483648 - filename: TEST_DIR/t-f241.vmdk + filename: TEST_DIR/t-f241.IMGFMT format: FLAT [241]: virtual size: 2147483648 - filename: TEST_DIR/t-f242.vmdk + filename: TEST_DIR/t-f242.IMGFMT format: FLAT [242]: virtual size: 2147483648 - filename: TEST_DIR/t-f243.vmdk + filename: TEST_DIR/t-f243.IMGFMT format: FLAT [243]: virtual size: 2147483648 - filename: TEST_DIR/t-f244.vmdk + filename: TEST_DIR/t-f244.IMGFMT format: FLAT [244]: virtual size: 2147483648 - filename: TEST_DIR/t-f245.vmdk + filename: TEST_DIR/t-f245.IMGFMT format: FLAT [245]: virtual size: 2147483648 - filename: TEST_DIR/t-f246.vmdk + filename: TEST_DIR/t-f246.IMGFMT format: FLAT [246]: virtual size: 2147483648 - filename: TEST_DIR/t-f247.vmdk + filename: TEST_DIR/t-f247.IMGFMT format: FLAT [247]: virtual size: 2147483648 - filename: TEST_DIR/t-f248.vmdk + filename: TEST_DIR/t-f248.IMGFMT format: FLAT [248]: virtual size: 2147483648 - filename: TEST_DIR/t-f249.vmdk + filename: TEST_DIR/t-f249.IMGFMT format: FLAT [249]: virtual size: 2147483648 - filename: TEST_DIR/t-f250.vmdk + filename: TEST_DIR/t-f250.IMGFMT format: FLAT [250]: virtual size: 2147483648 - filename: TEST_DIR/t-f251.vmdk + filename: TEST_DIR/t-f251.IMGFMT format: FLAT [251]: virtual size: 2147483648 - filename: TEST_DIR/t-f252.vmdk + filename: TEST_DIR/t-f252.IMGFMT format: FLAT [252]: virtual size: 2147483648 - filename: TEST_DIR/t-f253.vmdk + filename: TEST_DIR/t-f253.IMGFMT format: FLAT [253]: virtual size: 2147483648 - filename: TEST_DIR/t-f254.vmdk + filename: TEST_DIR/t-f254.IMGFMT format: FLAT [254]: virtual size: 2147483648 - filename: TEST_DIR/t-f255.vmdk + filename: TEST_DIR/t-f255.IMGFMT format: FLAT [255]: virtual size: 2147483648 - filename: TEST_DIR/t-f256.vmdk + filename: TEST_DIR/t-f256.IMGFMT format: FLAT [256]: virtual size: 2147483648 - filename: TEST_DIR/t-f257.vmdk + filename: TEST_DIR/t-f257.IMGFMT format: FLAT [257]: virtual size: 2147483648 - filename: TEST_DIR/t-f258.vmdk + filename: TEST_DIR/t-f258.IMGFMT format: FLAT [258]: virtual size: 2147483648 - filename: TEST_DIR/t-f259.vmdk + filename: TEST_DIR/t-f259.IMGFMT format: FLAT [259]: virtual size: 2147483648 - filename: TEST_DIR/t-f260.vmdk + filename: TEST_DIR/t-f260.IMGFMT format: FLAT [260]: virtual size: 2147483648 - filename: TEST_DIR/t-f261.vmdk + filename: TEST_DIR/t-f261.IMGFMT format: FLAT [261]: virtual size: 2147483648 - filename: TEST_DIR/t-f262.vmdk + filename: TEST_DIR/t-f262.IMGFMT format: FLAT [262]: virtual size: 2147483648 - filename: TEST_DIR/t-f263.vmdk + filename: TEST_DIR/t-f263.IMGFMT format: FLAT [263]: virtual size: 2147483648 - filename: TEST_DIR/t-f264.vmdk + filename: TEST_DIR/t-f264.IMGFMT format: FLAT [264]: virtual size: 2147483648 - filename: TEST_DIR/t-f265.vmdk + filename: TEST_DIR/t-f265.IMGFMT format: FLAT [265]: virtual size: 2147483648 - filename: TEST_DIR/t-f266.vmdk + filename: TEST_DIR/t-f266.IMGFMT format: FLAT [266]: virtual size: 2147483648 - filename: TEST_DIR/t-f267.vmdk + filename: TEST_DIR/t-f267.IMGFMT format: FLAT [267]: virtual size: 2147483648 - filename: TEST_DIR/t-f268.vmdk + filename: TEST_DIR/t-f268.IMGFMT format: FLAT [268]: virtual size: 2147483648 - filename: TEST_DIR/t-f269.vmdk + filename: TEST_DIR/t-f269.IMGFMT format: FLAT [269]: virtual size: 2147483648 - filename: TEST_DIR/t-f270.vmdk + filename: TEST_DIR/t-f270.IMGFMT format: FLAT [270]: virtual size: 2147483648 - filename: TEST_DIR/t-f271.vmdk + filename: TEST_DIR/t-f271.IMGFMT format: FLAT [271]: virtual size: 2147483648 - filename: TEST_DIR/t-f272.vmdk + filename: TEST_DIR/t-f272.IMGFMT format: FLAT [272]: virtual size: 2147483648 - filename: TEST_DIR/t-f273.vmdk + filename: TEST_DIR/t-f273.IMGFMT format: FLAT [273]: virtual size: 2147483648 - filename: TEST_DIR/t-f274.vmdk + filename: TEST_DIR/t-f274.IMGFMT format: FLAT [274]: virtual size: 2147483648 - filename: TEST_DIR/t-f275.vmdk + filename: TEST_DIR/t-f275.IMGFMT format: FLAT [275]: virtual size: 2147483648 - filename: TEST_DIR/t-f276.vmdk + filename: TEST_DIR/t-f276.IMGFMT format: FLAT [276]: virtual size: 2147483648 - filename: TEST_DIR/t-f277.vmdk + filename: TEST_DIR/t-f277.IMGFMT format: FLAT [277]: virtual size: 2147483648 - filename: TEST_DIR/t-f278.vmdk + filename: TEST_DIR/t-f278.IMGFMT format: FLAT [278]: virtual size: 2147483648 - filename: TEST_DIR/t-f279.vmdk + filename: TEST_DIR/t-f279.IMGFMT format: FLAT [279]: virtual size: 2147483648 - filename: TEST_DIR/t-f280.vmdk + filename: TEST_DIR/t-f280.IMGFMT format: FLAT [280]: virtual size: 2147483648 - filename: TEST_DIR/t-f281.vmdk + filename: TEST_DIR/t-f281.IMGFMT format: FLAT [281]: virtual size: 2147483648 - filename: TEST_DIR/t-f282.vmdk + filename: TEST_DIR/t-f282.IMGFMT format: FLAT [282]: virtual size: 2147483648 - filename: TEST_DIR/t-f283.vmdk + filename: TEST_DIR/t-f283.IMGFMT format: FLAT [283]: virtual size: 2147483648 - filename: TEST_DIR/t-f284.vmdk + filename: TEST_DIR/t-f284.IMGFMT format: FLAT [284]: virtual size: 2147483648 - filename: TEST_DIR/t-f285.vmdk + filename: TEST_DIR/t-f285.IMGFMT format: FLAT [285]: virtual size: 2147483648 - filename: TEST_DIR/t-f286.vmdk + filename: TEST_DIR/t-f286.IMGFMT format: FLAT [286]: virtual size: 2147483648 - filename: TEST_DIR/t-f287.vmdk + filename: TEST_DIR/t-f287.IMGFMT format: FLAT [287]: virtual size: 2147483648 - filename: TEST_DIR/t-f288.vmdk + filename: TEST_DIR/t-f288.IMGFMT format: FLAT [288]: virtual size: 2147483648 - filename: TEST_DIR/t-f289.vmdk + filename: TEST_DIR/t-f289.IMGFMT format: FLAT [289]: virtual size: 2147483648 - filename: TEST_DIR/t-f290.vmdk + filename: TEST_DIR/t-f290.IMGFMT format: FLAT [290]: virtual size: 2147483648 - filename: TEST_DIR/t-f291.vmdk + filename: TEST_DIR/t-f291.IMGFMT format: FLAT [291]: virtual size: 2147483648 - filename: TEST_DIR/t-f292.vmdk + filename: TEST_DIR/t-f292.IMGFMT format: FLAT [292]: virtual size: 2147483648 - filename: TEST_DIR/t-f293.vmdk + filename: TEST_DIR/t-f293.IMGFMT format: FLAT [293]: virtual size: 2147483648 - filename: TEST_DIR/t-f294.vmdk + filename: TEST_DIR/t-f294.IMGFMT format: FLAT [294]: virtual size: 2147483648 - filename: TEST_DIR/t-f295.vmdk + filename: TEST_DIR/t-f295.IMGFMT format: FLAT [295]: virtual size: 2147483648 - filename: TEST_DIR/t-f296.vmdk + filename: TEST_DIR/t-f296.IMGFMT format: FLAT [296]: virtual size: 2147483648 - filename: TEST_DIR/t-f297.vmdk + filename: TEST_DIR/t-f297.IMGFMT format: FLAT [297]: virtual size: 2147483648 - filename: TEST_DIR/t-f298.vmdk + filename: TEST_DIR/t-f298.IMGFMT format: FLAT [298]: virtual size: 2147483648 - filename: TEST_DIR/t-f299.vmdk + filename: TEST_DIR/t-f299.IMGFMT format: FLAT [299]: virtual size: 2147483648 - filename: TEST_DIR/t-f300.vmdk + filename: TEST_DIR/t-f300.IMGFMT format: FLAT [300]: virtual size: 2147483648 - filename: TEST_DIR/t-f301.vmdk + filename: TEST_DIR/t-f301.IMGFMT format: FLAT [301]: virtual size: 2147483648 - filename: TEST_DIR/t-f302.vmdk + filename: TEST_DIR/t-f302.IMGFMT format: FLAT [302]: virtual size: 2147483648 - filename: TEST_DIR/t-f303.vmdk + filename: TEST_DIR/t-f303.IMGFMT format: FLAT [303]: virtual size: 2147483648 - filename: TEST_DIR/t-f304.vmdk + filename: TEST_DIR/t-f304.IMGFMT format: FLAT [304]: virtual size: 2147483648 - filename: TEST_DIR/t-f305.vmdk + filename: TEST_DIR/t-f305.IMGFMT format: FLAT [305]: virtual size: 2147483648 - filename: TEST_DIR/t-f306.vmdk + filename: TEST_DIR/t-f306.IMGFMT format: FLAT [306]: virtual size: 2147483648 - filename: TEST_DIR/t-f307.vmdk + filename: TEST_DIR/t-f307.IMGFMT format: FLAT [307]: virtual size: 2147483648 - filename: TEST_DIR/t-f308.vmdk + filename: TEST_DIR/t-f308.IMGFMT format: FLAT [308]: virtual size: 2147483648 - filename: TEST_DIR/t-f309.vmdk + filename: TEST_DIR/t-f309.IMGFMT format: FLAT [309]: virtual size: 2147483648 - filename: TEST_DIR/t-f310.vmdk + filename: TEST_DIR/t-f310.IMGFMT format: FLAT [310]: virtual size: 2147483648 - filename: TEST_DIR/t-f311.vmdk + filename: TEST_DIR/t-f311.IMGFMT format: FLAT [311]: virtual size: 2147483648 - filename: TEST_DIR/t-f312.vmdk + filename: TEST_DIR/t-f312.IMGFMT format: FLAT [312]: virtual size: 2147483648 - filename: TEST_DIR/t-f313.vmdk + filename: TEST_DIR/t-f313.IMGFMT format: FLAT [313]: virtual size: 2147483648 - filename: TEST_DIR/t-f314.vmdk + filename: TEST_DIR/t-f314.IMGFMT format: FLAT [314]: virtual size: 2147483648 - filename: TEST_DIR/t-f315.vmdk + filename: TEST_DIR/t-f315.IMGFMT format: FLAT [315]: virtual size: 2147483648 - filename: TEST_DIR/t-f316.vmdk + filename: TEST_DIR/t-f316.IMGFMT format: FLAT [316]: virtual size: 2147483648 - filename: TEST_DIR/t-f317.vmdk + filename: TEST_DIR/t-f317.IMGFMT format: FLAT [317]: virtual size: 2147483648 - filename: TEST_DIR/t-f318.vmdk + filename: TEST_DIR/t-f318.IMGFMT format: FLAT [318]: virtual size: 2147483648 - filename: TEST_DIR/t-f319.vmdk + filename: TEST_DIR/t-f319.IMGFMT format: FLAT [319]: virtual size: 2147483648 - filename: TEST_DIR/t-f320.vmdk + filename: TEST_DIR/t-f320.IMGFMT format: FLAT [320]: virtual size: 2147483648 - filename: TEST_DIR/t-f321.vmdk + filename: TEST_DIR/t-f321.IMGFMT format: FLAT [321]: virtual size: 2147483648 - filename: TEST_DIR/t-f322.vmdk + filename: TEST_DIR/t-f322.IMGFMT format: FLAT [322]: virtual size: 2147483648 - filename: TEST_DIR/t-f323.vmdk + filename: TEST_DIR/t-f323.IMGFMT format: FLAT [323]: virtual size: 2147483648 - filename: TEST_DIR/t-f324.vmdk + filename: TEST_DIR/t-f324.IMGFMT format: FLAT [324]: virtual size: 2147483648 - filename: TEST_DIR/t-f325.vmdk + filename: TEST_DIR/t-f325.IMGFMT format: FLAT [325]: virtual size: 2147483648 - filename: TEST_DIR/t-f326.vmdk + filename: TEST_DIR/t-f326.IMGFMT format: FLAT [326]: virtual size: 2147483648 - filename: TEST_DIR/t-f327.vmdk + filename: TEST_DIR/t-f327.IMGFMT format: FLAT [327]: virtual size: 2147483648 - filename: TEST_DIR/t-f328.vmdk + filename: TEST_DIR/t-f328.IMGFMT format: FLAT [328]: virtual size: 2147483648 - filename: TEST_DIR/t-f329.vmdk + filename: TEST_DIR/t-f329.IMGFMT format: FLAT [329]: virtual size: 2147483648 - filename: TEST_DIR/t-f330.vmdk + filename: TEST_DIR/t-f330.IMGFMT format: FLAT [330]: virtual size: 2147483648 - filename: TEST_DIR/t-f331.vmdk + filename: TEST_DIR/t-f331.IMGFMT format: FLAT [331]: virtual size: 2147483648 - filename: TEST_DIR/t-f332.vmdk + filename: TEST_DIR/t-f332.IMGFMT format: FLAT [332]: virtual size: 2147483648 - filename: TEST_DIR/t-f333.vmdk + filename: TEST_DIR/t-f333.IMGFMT format: FLAT [333]: virtual size: 2147483648 - filename: TEST_DIR/t-f334.vmdk + filename: TEST_DIR/t-f334.IMGFMT format: FLAT [334]: virtual size: 2147483648 - filename: TEST_DIR/t-f335.vmdk + filename: TEST_DIR/t-f335.IMGFMT format: FLAT [335]: virtual size: 2147483648 - filename: TEST_DIR/t-f336.vmdk + filename: TEST_DIR/t-f336.IMGFMT format: FLAT [336]: virtual size: 2147483648 - filename: TEST_DIR/t-f337.vmdk + filename: TEST_DIR/t-f337.IMGFMT format: FLAT [337]: virtual size: 2147483648 - filename: TEST_DIR/t-f338.vmdk + filename: TEST_DIR/t-f338.IMGFMT format: FLAT [338]: virtual size: 2147483648 - filename: TEST_DIR/t-f339.vmdk + filename: TEST_DIR/t-f339.IMGFMT format: FLAT [339]: virtual size: 2147483648 - filename: TEST_DIR/t-f340.vmdk + filename: TEST_DIR/t-f340.IMGFMT format: FLAT [340]: virtual size: 2147483648 - filename: TEST_DIR/t-f341.vmdk + filename: TEST_DIR/t-f341.IMGFMT format: FLAT [341]: virtual size: 2147483648 - filename: TEST_DIR/t-f342.vmdk + filename: TEST_DIR/t-f342.IMGFMT format: FLAT [342]: virtual size: 2147483648 - filename: TEST_DIR/t-f343.vmdk + filename: TEST_DIR/t-f343.IMGFMT format: FLAT [343]: virtual size: 2147483648 - filename: TEST_DIR/t-f344.vmdk + filename: TEST_DIR/t-f344.IMGFMT format: FLAT [344]: virtual size: 2147483648 - filename: TEST_DIR/t-f345.vmdk + filename: TEST_DIR/t-f345.IMGFMT format: FLAT [345]: virtual size: 2147483648 - filename: TEST_DIR/t-f346.vmdk + filename: TEST_DIR/t-f346.IMGFMT format: FLAT [346]: virtual size: 2147483648 - filename: TEST_DIR/t-f347.vmdk + filename: TEST_DIR/t-f347.IMGFMT format: FLAT [347]: virtual size: 2147483648 - filename: TEST_DIR/t-f348.vmdk + filename: TEST_DIR/t-f348.IMGFMT format: FLAT [348]: virtual size: 2147483648 - filename: TEST_DIR/t-f349.vmdk + filename: TEST_DIR/t-f349.IMGFMT format: FLAT [349]: virtual size: 2147483648 - filename: TEST_DIR/t-f350.vmdk + filename: TEST_DIR/t-f350.IMGFMT format: FLAT [350]: virtual size: 2147483648 - filename: TEST_DIR/t-f351.vmdk + filename: TEST_DIR/t-f351.IMGFMT format: FLAT [351]: virtual size: 2147483648 - filename: TEST_DIR/t-f352.vmdk + filename: TEST_DIR/t-f352.IMGFMT format: FLAT [352]: virtual size: 2147483648 - filename: TEST_DIR/t-f353.vmdk + filename: TEST_DIR/t-f353.IMGFMT format: FLAT [353]: virtual size: 2147483648 - filename: TEST_DIR/t-f354.vmdk + filename: TEST_DIR/t-f354.IMGFMT format: FLAT [354]: virtual size: 2147483648 - filename: TEST_DIR/t-f355.vmdk + filename: TEST_DIR/t-f355.IMGFMT format: FLAT [355]: virtual size: 2147483648 - filename: TEST_DIR/t-f356.vmdk + filename: TEST_DIR/t-f356.IMGFMT format: FLAT [356]: virtual size: 2147483648 - filename: TEST_DIR/t-f357.vmdk + filename: TEST_DIR/t-f357.IMGFMT format: FLAT [357]: virtual size: 2147483648 - filename: TEST_DIR/t-f358.vmdk + filename: TEST_DIR/t-f358.IMGFMT format: FLAT [358]: virtual size: 2147483648 - filename: TEST_DIR/t-f359.vmdk + filename: TEST_DIR/t-f359.IMGFMT format: FLAT [359]: virtual size: 2147483648 - filename: TEST_DIR/t-f360.vmdk + filename: TEST_DIR/t-f360.IMGFMT format: FLAT [360]: virtual size: 2147483648 - filename: TEST_DIR/t-f361.vmdk + filename: TEST_DIR/t-f361.IMGFMT format: FLAT [361]: virtual size: 2147483648 - filename: TEST_DIR/t-f362.vmdk + filename: TEST_DIR/t-f362.IMGFMT format: FLAT [362]: virtual size: 2147483648 - filename: TEST_DIR/t-f363.vmdk + filename: TEST_DIR/t-f363.IMGFMT format: FLAT [363]: virtual size: 2147483648 - filename: TEST_DIR/t-f364.vmdk + filename: TEST_DIR/t-f364.IMGFMT format: FLAT [364]: virtual size: 2147483648 - filename: TEST_DIR/t-f365.vmdk + filename: TEST_DIR/t-f365.IMGFMT format: FLAT [365]: virtual size: 2147483648 - filename: TEST_DIR/t-f366.vmdk + filename: TEST_DIR/t-f366.IMGFMT format: FLAT [366]: virtual size: 2147483648 - filename: TEST_DIR/t-f367.vmdk + filename: TEST_DIR/t-f367.IMGFMT format: FLAT [367]: virtual size: 2147483648 - filename: TEST_DIR/t-f368.vmdk + filename: TEST_DIR/t-f368.IMGFMT format: FLAT [368]: virtual size: 2147483648 - filename: TEST_DIR/t-f369.vmdk + filename: TEST_DIR/t-f369.IMGFMT format: FLAT [369]: virtual size: 2147483648 - filename: TEST_DIR/t-f370.vmdk + filename: TEST_DIR/t-f370.IMGFMT format: FLAT [370]: virtual size: 2147483648 - filename: TEST_DIR/t-f371.vmdk + filename: TEST_DIR/t-f371.IMGFMT format: FLAT [371]: virtual size: 2147483648 - filename: TEST_DIR/t-f372.vmdk + filename: TEST_DIR/t-f372.IMGFMT format: FLAT [372]: virtual size: 2147483648 - filename: TEST_DIR/t-f373.vmdk + filename: TEST_DIR/t-f373.IMGFMT format: FLAT [373]: virtual size: 2147483648 - filename: TEST_DIR/t-f374.vmdk + filename: TEST_DIR/t-f374.IMGFMT format: FLAT [374]: virtual size: 2147483648 - filename: TEST_DIR/t-f375.vmdk + filename: TEST_DIR/t-f375.IMGFMT format: FLAT [375]: virtual size: 2147483648 - filename: TEST_DIR/t-f376.vmdk + filename: TEST_DIR/t-f376.IMGFMT format: FLAT [376]: virtual size: 2147483648 - filename: TEST_DIR/t-f377.vmdk + filename: TEST_DIR/t-f377.IMGFMT format: FLAT [377]: virtual size: 2147483648 - filename: TEST_DIR/t-f378.vmdk + filename: TEST_DIR/t-f378.IMGFMT format: FLAT [378]: virtual size: 2147483648 - filename: TEST_DIR/t-f379.vmdk + filename: TEST_DIR/t-f379.IMGFMT format: FLAT [379]: virtual size: 2147483648 - filename: TEST_DIR/t-f380.vmdk + filename: TEST_DIR/t-f380.IMGFMT format: FLAT [380]: virtual size: 2147483648 - filename: TEST_DIR/t-f381.vmdk + filename: TEST_DIR/t-f381.IMGFMT format: FLAT [381]: virtual size: 2147483648 - filename: TEST_DIR/t-f382.vmdk + filename: TEST_DIR/t-f382.IMGFMT format: FLAT [382]: virtual size: 2147483648 - filename: TEST_DIR/t-f383.vmdk + filename: TEST_DIR/t-f383.IMGFMT format: FLAT [383]: virtual size: 2147483648 - filename: TEST_DIR/t-f384.vmdk + filename: TEST_DIR/t-f384.IMGFMT format: FLAT [384]: virtual size: 2147483648 - filename: TEST_DIR/t-f385.vmdk + filename: TEST_DIR/t-f385.IMGFMT format: FLAT [385]: virtual size: 2147483648 - filename: TEST_DIR/t-f386.vmdk + filename: TEST_DIR/t-f386.IMGFMT format: FLAT [386]: virtual size: 2147483648 - filename: TEST_DIR/t-f387.vmdk + filename: TEST_DIR/t-f387.IMGFMT format: FLAT [387]: virtual size: 2147483648 - filename: TEST_DIR/t-f388.vmdk + filename: TEST_DIR/t-f388.IMGFMT format: FLAT [388]: virtual size: 2147483648 - filename: TEST_DIR/t-f389.vmdk + filename: TEST_DIR/t-f389.IMGFMT format: FLAT [389]: virtual size: 2147483648 - filename: TEST_DIR/t-f390.vmdk + filename: TEST_DIR/t-f390.IMGFMT format: FLAT [390]: virtual size: 2147483648 - filename: TEST_DIR/t-f391.vmdk + filename: TEST_DIR/t-f391.IMGFMT format: FLAT [391]: virtual size: 2147483648 - filename: TEST_DIR/t-f392.vmdk + filename: TEST_DIR/t-f392.IMGFMT format: FLAT [392]: virtual size: 2147483648 - filename: TEST_DIR/t-f393.vmdk + filename: TEST_DIR/t-f393.IMGFMT format: FLAT [393]: virtual size: 2147483648 - filename: TEST_DIR/t-f394.vmdk + filename: TEST_DIR/t-f394.IMGFMT format: FLAT [394]: virtual size: 2147483648 - filename: TEST_DIR/t-f395.vmdk + filename: TEST_DIR/t-f395.IMGFMT format: FLAT [395]: virtual size: 2147483648 - filename: TEST_DIR/t-f396.vmdk + filename: TEST_DIR/t-f396.IMGFMT format: FLAT [396]: virtual size: 2147483648 - filename: TEST_DIR/t-f397.vmdk + filename: TEST_DIR/t-f397.IMGFMT format: FLAT [397]: virtual size: 2147483648 - filename: TEST_DIR/t-f398.vmdk + filename: TEST_DIR/t-f398.IMGFMT format: FLAT [398]: virtual size: 2147483648 - filename: TEST_DIR/t-f399.vmdk + filename: TEST_DIR/t-f399.IMGFMT format: FLAT [399]: virtual size: 2147483648 - filename: TEST_DIR/t-f400.vmdk + filename: TEST_DIR/t-f400.IMGFMT format: FLAT [400]: virtual size: 2147483648 - filename: TEST_DIR/t-f401.vmdk + filename: TEST_DIR/t-f401.IMGFMT format: FLAT [401]: virtual size: 2147483648 - filename: TEST_DIR/t-f402.vmdk + filename: TEST_DIR/t-f402.IMGFMT format: FLAT [402]: virtual size: 2147483648 - filename: TEST_DIR/t-f403.vmdk + filename: TEST_DIR/t-f403.IMGFMT format: FLAT [403]: virtual size: 2147483648 - filename: TEST_DIR/t-f404.vmdk + filename: TEST_DIR/t-f404.IMGFMT format: FLAT [404]: virtual size: 2147483648 - filename: TEST_DIR/t-f405.vmdk + filename: TEST_DIR/t-f405.IMGFMT format: FLAT [405]: virtual size: 2147483648 - filename: TEST_DIR/t-f406.vmdk + filename: TEST_DIR/t-f406.IMGFMT format: FLAT [406]: virtual size: 2147483648 - filename: TEST_DIR/t-f407.vmdk + filename: TEST_DIR/t-f407.IMGFMT format: FLAT [407]: virtual size: 2147483648 - filename: TEST_DIR/t-f408.vmdk + filename: TEST_DIR/t-f408.IMGFMT format: FLAT [408]: virtual size: 2147483648 - filename: TEST_DIR/t-f409.vmdk + filename: TEST_DIR/t-f409.IMGFMT format: FLAT [409]: virtual size: 2147483648 - filename: TEST_DIR/t-f410.vmdk + filename: TEST_DIR/t-f410.IMGFMT format: FLAT [410]: virtual size: 2147483648 - filename: TEST_DIR/t-f411.vmdk + filename: TEST_DIR/t-f411.IMGFMT format: FLAT [411]: virtual size: 2147483648 - filename: TEST_DIR/t-f412.vmdk + filename: TEST_DIR/t-f412.IMGFMT format: FLAT [412]: virtual size: 2147483648 - filename: TEST_DIR/t-f413.vmdk + filename: TEST_DIR/t-f413.IMGFMT format: FLAT [413]: virtual size: 2147483648 - filename: TEST_DIR/t-f414.vmdk + filename: TEST_DIR/t-f414.IMGFMT format: FLAT [414]: virtual size: 2147483648 - filename: TEST_DIR/t-f415.vmdk + filename: TEST_DIR/t-f415.IMGFMT format: FLAT [415]: virtual size: 2147483648 - filename: TEST_DIR/t-f416.vmdk + filename: TEST_DIR/t-f416.IMGFMT format: FLAT [416]: virtual size: 2147483648 - filename: TEST_DIR/t-f417.vmdk + filename: TEST_DIR/t-f417.IMGFMT format: FLAT [417]: virtual size: 2147483648 - filename: TEST_DIR/t-f418.vmdk + filename: TEST_DIR/t-f418.IMGFMT format: FLAT [418]: virtual size: 2147483648 - filename: TEST_DIR/t-f419.vmdk + filename: TEST_DIR/t-f419.IMGFMT format: FLAT [419]: virtual size: 2147483648 - filename: TEST_DIR/t-f420.vmdk + filename: TEST_DIR/t-f420.IMGFMT format: FLAT [420]: virtual size: 2147483648 - filename: TEST_DIR/t-f421.vmdk + filename: TEST_DIR/t-f421.IMGFMT format: FLAT [421]: virtual size: 2147483648 - filename: TEST_DIR/t-f422.vmdk + filename: TEST_DIR/t-f422.IMGFMT format: FLAT [422]: virtual size: 2147483648 - filename: TEST_DIR/t-f423.vmdk + filename: TEST_DIR/t-f423.IMGFMT format: FLAT [423]: virtual size: 2147483648 - filename: TEST_DIR/t-f424.vmdk + filename: TEST_DIR/t-f424.IMGFMT format: FLAT [424]: virtual size: 2147483648 - filename: TEST_DIR/t-f425.vmdk + filename: TEST_DIR/t-f425.IMGFMT format: FLAT [425]: virtual size: 2147483648 - filename: TEST_DIR/t-f426.vmdk + filename: TEST_DIR/t-f426.IMGFMT format: FLAT [426]: virtual size: 2147483648 - filename: TEST_DIR/t-f427.vmdk + filename: TEST_DIR/t-f427.IMGFMT format: FLAT [427]: virtual size: 2147483648 - filename: TEST_DIR/t-f428.vmdk + filename: TEST_DIR/t-f428.IMGFMT format: FLAT [428]: virtual size: 2147483648 - filename: TEST_DIR/t-f429.vmdk + filename: TEST_DIR/t-f429.IMGFMT format: FLAT [429]: virtual size: 2147483648 - filename: TEST_DIR/t-f430.vmdk + filename: TEST_DIR/t-f430.IMGFMT format: FLAT [430]: virtual size: 2147483648 - filename: TEST_DIR/t-f431.vmdk + filename: TEST_DIR/t-f431.IMGFMT format: FLAT [431]: virtual size: 2147483648 - filename: TEST_DIR/t-f432.vmdk + filename: TEST_DIR/t-f432.IMGFMT format: FLAT [432]: virtual size: 2147483648 - filename: TEST_DIR/t-f433.vmdk + filename: TEST_DIR/t-f433.IMGFMT format: FLAT [433]: virtual size: 2147483648 - filename: TEST_DIR/t-f434.vmdk + filename: TEST_DIR/t-f434.IMGFMT format: FLAT [434]: virtual size: 2147483648 - filename: TEST_DIR/t-f435.vmdk + filename: TEST_DIR/t-f435.IMGFMT format: FLAT [435]: virtual size: 2147483648 - filename: TEST_DIR/t-f436.vmdk + filename: TEST_DIR/t-f436.IMGFMT format: FLAT [436]: virtual size: 2147483648 - filename: TEST_DIR/t-f437.vmdk + filename: TEST_DIR/t-f437.IMGFMT format: FLAT [437]: virtual size: 2147483648 - filename: TEST_DIR/t-f438.vmdk + filename: TEST_DIR/t-f438.IMGFMT format: FLAT [438]: virtual size: 2147483648 - filename: TEST_DIR/t-f439.vmdk + filename: TEST_DIR/t-f439.IMGFMT format: FLAT [439]: virtual size: 2147483648 - filename: TEST_DIR/t-f440.vmdk + filename: TEST_DIR/t-f440.IMGFMT format: FLAT [440]: virtual size: 2147483648 - filename: TEST_DIR/t-f441.vmdk + filename: TEST_DIR/t-f441.IMGFMT format: FLAT [441]: virtual size: 2147483648 - filename: TEST_DIR/t-f442.vmdk + filename: TEST_DIR/t-f442.IMGFMT format: FLAT [442]: virtual size: 2147483648 - filename: TEST_DIR/t-f443.vmdk + filename: TEST_DIR/t-f443.IMGFMT format: FLAT [443]: virtual size: 2147483648 - filename: TEST_DIR/t-f444.vmdk + filename: TEST_DIR/t-f444.IMGFMT format: FLAT [444]: virtual size: 2147483648 - filename: TEST_DIR/t-f445.vmdk + filename: TEST_DIR/t-f445.IMGFMT format: FLAT [445]: virtual size: 2147483648 - filename: TEST_DIR/t-f446.vmdk + filename: TEST_DIR/t-f446.IMGFMT format: FLAT [446]: virtual size: 2147483648 - filename: TEST_DIR/t-f447.vmdk + filename: TEST_DIR/t-f447.IMGFMT format: FLAT [447]: virtual size: 2147483648 - filename: TEST_DIR/t-f448.vmdk + filename: TEST_DIR/t-f448.IMGFMT format: FLAT [448]: virtual size: 2147483648 - filename: TEST_DIR/t-f449.vmdk + filename: TEST_DIR/t-f449.IMGFMT format: FLAT [449]: virtual size: 2147483648 - filename: TEST_DIR/t-f450.vmdk + filename: TEST_DIR/t-f450.IMGFMT format: FLAT [450]: virtual size: 2147483648 - filename: TEST_DIR/t-f451.vmdk + filename: TEST_DIR/t-f451.IMGFMT format: FLAT [451]: virtual size: 2147483648 - filename: TEST_DIR/t-f452.vmdk + filename: TEST_DIR/t-f452.IMGFMT format: FLAT [452]: virtual size: 2147483648 - filename: TEST_DIR/t-f453.vmdk + filename: TEST_DIR/t-f453.IMGFMT format: FLAT [453]: virtual size: 2147483648 - filename: TEST_DIR/t-f454.vmdk + filename: TEST_DIR/t-f454.IMGFMT format: FLAT [454]: virtual size: 2147483648 - filename: TEST_DIR/t-f455.vmdk + filename: TEST_DIR/t-f455.IMGFMT format: FLAT [455]: virtual size: 2147483648 - filename: TEST_DIR/t-f456.vmdk + filename: TEST_DIR/t-f456.IMGFMT format: FLAT [456]: virtual size: 2147483648 - filename: TEST_DIR/t-f457.vmdk + filename: TEST_DIR/t-f457.IMGFMT format: FLAT [457]: virtual size: 2147483648 - filename: TEST_DIR/t-f458.vmdk + filename: TEST_DIR/t-f458.IMGFMT format: FLAT [458]: virtual size: 2147483648 - filename: TEST_DIR/t-f459.vmdk + filename: TEST_DIR/t-f459.IMGFMT format: FLAT [459]: virtual size: 2147483648 - filename: TEST_DIR/t-f460.vmdk + filename: TEST_DIR/t-f460.IMGFMT format: FLAT [460]: virtual size: 2147483648 - filename: TEST_DIR/t-f461.vmdk + filename: TEST_DIR/t-f461.IMGFMT format: FLAT [461]: virtual size: 2147483648 - filename: TEST_DIR/t-f462.vmdk + filename: TEST_DIR/t-f462.IMGFMT format: FLAT [462]: virtual size: 2147483648 - filename: TEST_DIR/t-f463.vmdk + filename: TEST_DIR/t-f463.IMGFMT format: FLAT [463]: virtual size: 2147483648 - filename: TEST_DIR/t-f464.vmdk + filename: TEST_DIR/t-f464.IMGFMT format: FLAT [464]: virtual size: 2147483648 - filename: TEST_DIR/t-f465.vmdk + filename: TEST_DIR/t-f465.IMGFMT format: FLAT [465]: virtual size: 2147483648 - filename: TEST_DIR/t-f466.vmdk + filename: TEST_DIR/t-f466.IMGFMT format: FLAT [466]: virtual size: 2147483648 - filename: TEST_DIR/t-f467.vmdk + filename: TEST_DIR/t-f467.IMGFMT format: FLAT [467]: virtual size: 2147483648 - filename: TEST_DIR/t-f468.vmdk + filename: TEST_DIR/t-f468.IMGFMT format: FLAT [468]: virtual size: 2147483648 - filename: TEST_DIR/t-f469.vmdk + filename: TEST_DIR/t-f469.IMGFMT format: FLAT [469]: virtual size: 2147483648 - filename: TEST_DIR/t-f470.vmdk + filename: TEST_DIR/t-f470.IMGFMT format: FLAT [470]: virtual size: 2147483648 - filename: TEST_DIR/t-f471.vmdk + filename: TEST_DIR/t-f471.IMGFMT format: FLAT [471]: virtual size: 2147483648 - filename: TEST_DIR/t-f472.vmdk + filename: TEST_DIR/t-f472.IMGFMT format: FLAT [472]: virtual size: 2147483648 - filename: TEST_DIR/t-f473.vmdk + filename: TEST_DIR/t-f473.IMGFMT format: FLAT [473]: virtual size: 2147483648 - filename: TEST_DIR/t-f474.vmdk + filename: TEST_DIR/t-f474.IMGFMT format: FLAT [474]: virtual size: 2147483648 - filename: TEST_DIR/t-f475.vmdk + filename: TEST_DIR/t-f475.IMGFMT format: FLAT [475]: virtual size: 2147483648 - filename: TEST_DIR/t-f476.vmdk + filename: TEST_DIR/t-f476.IMGFMT format: FLAT [476]: virtual size: 2147483648 - filename: TEST_DIR/t-f477.vmdk + filename: TEST_DIR/t-f477.IMGFMT format: FLAT [477]: virtual size: 2147483648 - filename: TEST_DIR/t-f478.vmdk + filename: TEST_DIR/t-f478.IMGFMT format: FLAT [478]: virtual size: 2147483648 - filename: TEST_DIR/t-f479.vmdk + filename: TEST_DIR/t-f479.IMGFMT format: FLAT [479]: virtual size: 2147483648 - filename: TEST_DIR/t-f480.vmdk + filename: TEST_DIR/t-f480.IMGFMT format: FLAT [480]: virtual size: 2147483648 - filename: TEST_DIR/t-f481.vmdk + filename: TEST_DIR/t-f481.IMGFMT format: FLAT [481]: virtual size: 2147483648 - filename: TEST_DIR/t-f482.vmdk + filename: TEST_DIR/t-f482.IMGFMT format: FLAT [482]: virtual size: 2147483648 - filename: TEST_DIR/t-f483.vmdk + filename: TEST_DIR/t-f483.IMGFMT format: FLAT [483]: virtual size: 2147483648 - filename: TEST_DIR/t-f484.vmdk + filename: TEST_DIR/t-f484.IMGFMT format: FLAT [484]: virtual size: 2147483648 - filename: TEST_DIR/t-f485.vmdk + filename: TEST_DIR/t-f485.IMGFMT format: FLAT [485]: virtual size: 2147483648 - filename: TEST_DIR/t-f486.vmdk + filename: TEST_DIR/t-f486.IMGFMT format: FLAT [486]: virtual size: 2147483648 - filename: TEST_DIR/t-f487.vmdk + filename: TEST_DIR/t-f487.IMGFMT format: FLAT [487]: virtual size: 2147483648 - filename: TEST_DIR/t-f488.vmdk + filename: TEST_DIR/t-f488.IMGFMT format: FLAT [488]: virtual size: 2147483648 - filename: TEST_DIR/t-f489.vmdk + filename: TEST_DIR/t-f489.IMGFMT format: FLAT [489]: virtual size: 2147483648 - filename: TEST_DIR/t-f490.vmdk + filename: TEST_DIR/t-f490.IMGFMT format: FLAT [490]: virtual size: 2147483648 - filename: TEST_DIR/t-f491.vmdk + filename: TEST_DIR/t-f491.IMGFMT format: FLAT [491]: virtual size: 2147483648 - filename: TEST_DIR/t-f492.vmdk + filename: TEST_DIR/t-f492.IMGFMT format: FLAT [492]: virtual size: 2147483648 - filename: TEST_DIR/t-f493.vmdk + filename: TEST_DIR/t-f493.IMGFMT format: FLAT [493]: virtual size: 2147483648 - filename: TEST_DIR/t-f494.vmdk + filename: TEST_DIR/t-f494.IMGFMT format: FLAT [494]: virtual size: 2147483648 - filename: TEST_DIR/t-f495.vmdk + filename: TEST_DIR/t-f495.IMGFMT format: FLAT [495]: virtual size: 2147483648 - filename: TEST_DIR/t-f496.vmdk + filename: TEST_DIR/t-f496.IMGFMT format: FLAT [496]: virtual size: 2147483648 - filename: TEST_DIR/t-f497.vmdk + filename: TEST_DIR/t-f497.IMGFMT format: FLAT [497]: virtual size: 2147483648 - filename: TEST_DIR/t-f498.vmdk + filename: TEST_DIR/t-f498.IMGFMT format: FLAT [498]: virtual size: 2147483648 - filename: TEST_DIR/t-f499.vmdk + filename: TEST_DIR/t-f499.IMGFMT format: FLAT [499]: virtual size: 2147483648 - filename: TEST_DIR/t-f500.vmdk + filename: TEST_DIR/t-f500.IMGFMT format: FLAT === Testing malformed VMFS extent description line === diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060 index 32c0ecce9ec3c150ac3ca2d2565f2ae2ed90a75b..94c0d5accc16ee29065c2fd08251563e142fdf37 100755 --- a/tests/qemu-iotests/060 +++ b/tests/qemu-iotests/060 @@ -160,7 +160,7 @@ TEST_IMG=$BACKING_IMG _make_test_img 1G $QEMU_IO -c 'write 0k 64k' "$BACKING_IMG" | _filter_qemu_io -_make_test_img -b "$BACKING_IMG" 1G +_make_test_img -b "$BACKING_IMG" -F $IMGFMT 1G # Write two clusters, the second one enforces creation of an L2 table after # the first data cluster. $QEMU_IO -c 'write 0k 64k' -c 'write 512M 64k' "$TEST_IMG" | _filter_qemu_io diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out index be5f8707a3c2ecb46ec6025ff36576cba04141d2..b74540bafbe84ff721fc0197d21c4907d52cce70 100644 --- a/tests/qemu-iotests/060.out +++ b/tests/qemu-iotests/060.out @@ -21,6 +21,7 @@ Format specific information: lazy refcounts: false refcount bits: 16 corrupt: true + extended l2: false qemu-io: can't open device TEST_DIR/t.IMGFMT: IMGFMT: Image is corrupt; cannot be opened read/write no file open, try 'help open' read 512/512 bytes at offset 0 @@ -101,7 +102,7 @@ read 512/512 bytes at offset 0 Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1073741824 wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 536870912 @@ -320,7 +321,7 @@ discard 65536/65536 bytes at offset 0 qcow2: Marking image as corrupt: Preallocated zero cluster offset 0x2a00 unaligned (guest offset: 0); further corruption events will be suppressed write failed: Input/output error --- Repairing --- -Repairing offset=2a00: Preallocated zero cluster is not properly aligned; L2 entry corrupted. +Repairing offset=2a00: Preallocated cluster is not properly aligned; L2 entry corrupted. The following inconsistencies were found and repaired: 0 leaked clusters diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061 index 10eb24316461decfc67a8e7416c6cff15a64694d..5747beb7ed60cd96f2ce6f836589b8872ab60c42 100755 --- a/tests/qemu-iotests/061 +++ b/tests/qemu-iotests/061 @@ -224,7 +224,7 @@ echo "=== Testing zero expansion on backed image ===" echo TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 64M $QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io -_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 64M +_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" -F $IMGFMT 64M $QEMU_IO -c "read -P 0x2a 0 128k" -c "write -z 0 64k" "$TEST_IMG" | _filter_qemu_io $QEMU_IMG amend -o "compat=0.10" "$TEST_IMG" _check_test_img @@ -235,7 +235,7 @@ echo "=== Testing zero expansion on backed inactive clusters ===" echo TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 64M $QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io -_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 64M +_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" -F $IMGFMT 64M $QEMU_IO -c "write -z 0 64k" "$TEST_IMG" | _filter_qemu_io $QEMU_IMG snapshot -c foo "$TEST_IMG" $QEMU_IO -c "write -P 0x42 0 128k" "$TEST_IMG" | _filter_qemu_io @@ -251,7 +251,7 @@ echo "=== Testing zero expansion on backed image with shared L2 table ===" echo TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 64M $QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io -_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 64M +_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" -F $IMGFMT 64M $QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io $QEMU_IMG snapshot -c foo "$TEST_IMG" $QEMU_IMG amend -o "compat=0.10" "$TEST_IMG" @@ -274,7 +274,7 @@ echo echo "=== Testing progress report without snapshot ===" echo TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 4G -_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 4G +_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" -F $IMGFMT 4G $QEMU_IO -c "write -z 0 64k" \ -c "write -z 1G 64k" \ -c "write -z 2G 64k" \ @@ -286,7 +286,7 @@ echo echo "=== Testing progress report with snapshot ===" echo TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 4G -_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 4G +_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" -F $IMGFMT 4G $QEMU_IO -c "write -z 0 64k" \ -c "write -z 1G 64k" \ -c "write -z 2G 64k" \ @@ -303,6 +303,12 @@ $QEMU_IMG amend -o "compat=0.10" "$TEST_IMG" _img_info --format-specific _check_test_img +echo +echo "=== Testing version downgrade with extended L2 entries ===" +echo +_make_test_img -o "compat=1.1,extended_l2=on" 64M +$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG" + echo echo "=== Try changing the external data file ===" echo diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out index a51ad1b5ba528390e3bff00f129bcc0aff7fd133..ee30da266514537bd3e6885a59588ce5d3077bb2 100644 --- a/tests/qemu-iotests/061.out +++ b/tests/qemu-iotests/061.out @@ -25,8 +25,8 @@ refcount_order 4 header_length 112 Header extension: -magic 0x6803f857 -length 336 +magic 0x6803f857 (Feature table) +length 384 data magic 0x514649fb @@ -83,8 +83,8 @@ refcount_order 4 header_length 112 Header extension: -magic 0x6803f857 -length 336 +magic 0x6803f857 (Feature table) +length 384 data magic 0x514649fb @@ -139,8 +139,8 @@ refcount_order 4 header_length 112 Header extension: -magic 0x6803f857 -length 336 +magic 0x6803f857 (Feature table) +length 384 data ERROR cluster 5 refcount=0 reference=1 @@ -194,8 +194,8 @@ refcount_order 4 header_length 112 Header extension: -magic 0x6803f857 -length 336 +magic 0x6803f857 (Feature table) +length 384 data magic 0x514649fb @@ -263,8 +263,8 @@ refcount_order 4 header_length 112 Header extension: -magic 0x6803f857 -length 336 +magic 0x6803f857 (Feature table) +length 384 data read 65536/65536 bytes at offset 44040192 @@ -325,8 +325,8 @@ refcount_order 4 header_length 112 Header extension: -magic 0x6803f857 -length 336 +magic 0x6803f857 (Feature table) +length 384 data ERROR cluster 5 refcount=0 reference=1 @@ -354,8 +354,8 @@ refcount_order 4 header_length 112 Header extension: -magic 0x6803f857 -length 336 +magic 0x6803f857 (Feature table) +length 384 data read 131072/131072 bytes at offset 0 @@ -370,6 +370,7 @@ wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-img: warning: Deprecated use of amend to alter the backing file; use qemu-img rebase instead read 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) No errors were found on the image. @@ -381,16 +382,20 @@ qemu-img: Lazy refcounts only supported with compatibility level 1.1 and above ( qemu-img: Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater) qemu-img: Unknown compatibility level 0.42 qemu-img: Invalid parameter 'foo' -qemu-img: Changing the cluster size is not supported -qemu-img: Changing the encryption flag is not supported -qemu-img: Cannot change preallocation mode +qemu-img: Invalid parameter 'cluster_size' +This option is only supported for image creation +qemu-img: Invalid parameter 'encryption' +This option is only supported for image creation +qemu-img: Invalid parameter 'preallocation' +This option is only supported for image creation === Testing correct handling of unset value === Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 Should work: Should not work: -qemu-img: Changing the cluster size is not supported +qemu-img: Invalid parameter 'cluster_size' +This option is only supported for image creation === Testing zero expansion on inactive clusters === @@ -423,7 +428,7 @@ read 131072/131072 bytes at offset 0 Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT read 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 0 @@ -439,7 +444,7 @@ read 65536/65536 bytes at offset 65536 Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 0 @@ -458,7 +463,7 @@ read 65536/65536 bytes at offset 65536 Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) No errors were found on the image. @@ -482,7 +487,7 @@ read 67108864/67108864 bytes at offset 0 === Testing progress report without snapshot === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=4294967296 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 1073741824 @@ -497,7 +502,7 @@ No errors were found on the image. === Testing progress report with snapshot === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=4294967296 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 1073741824 @@ -525,8 +530,14 @@ Format specific information: data file: TEST_DIR/t.IMGFMT.data data file raw: false corrupt: false + extended l2: false No errors were found on the image. +=== Testing version downgrade with extended L2 entries === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-img: Cannot downgrade an image with incompatible features 0x10 set + === Try changing the external data file === Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 @@ -546,6 +557,7 @@ Format specific information: data file: foo data file raw: false corrupt: false + extended l2: false qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'data-file' is required for this image image: TEST_DIR/t.IMGFMT @@ -559,6 +571,7 @@ Format specific information: refcount bits: 16 data file raw: false corrupt: false + extended l2: false === Clearing and setting data-file-raw === @@ -575,6 +588,7 @@ Format specific information: data file: TEST_DIR/t.IMGFMT.data data file raw: true corrupt: false + extended l2: false No errors were found on the image. image: TEST_DIR/t.IMGFMT file format: IMGFMT @@ -588,6 +602,7 @@ Format specific information: data file: TEST_DIR/t.IMGFMT.data data file raw: false corrupt: false + extended l2: false No errors were found on the image. qemu-img: data-file-raw cannot be set on existing images image: TEST_DIR/t.IMGFMT @@ -602,5 +617,6 @@ Format specific information: data file: TEST_DIR/t.IMGFMT.data data file raw: false corrupt: false + extended l2: false No errors were found on the image. *** done diff --git a/tests/qemu-iotests/065 b/tests/qemu-iotests/065 index 18dc488c7a1e01f5d5f3ba78fa8b5f8494e8075d..29a7f7ad60c9baf6796f3027ec74bc4ec7b41ee9 100755 --- a/tests/qemu-iotests/065 +++ b/tests/qemu-iotests/065 @@ -98,20 +98,20 @@ class TestQCow3NotLazy(TestQemuImgInfo): img_options = 'compat=1.1,lazy_refcounts=off' json_compare = { 'compat': '1.1', 'lazy-refcounts': False, 'refcount-bits': 16, 'corrupt': False, - 'compression-type': 'zlib' } + 'compression-type': 'zlib', 'extended-l2': False } human_compare = [ 'compat: 1.1', 'compression type: zlib', 'lazy refcounts: false', 'refcount bits: 16', - 'corrupt: false' ] + 'corrupt: false', 'extended l2: false' ] class TestQCow3Lazy(TestQemuImgInfo): '''Testing a qcow2 version 3 image with lazy refcounts enabled''' img_options = 'compat=1.1,lazy_refcounts=on' json_compare = { 'compat': '1.1', 'lazy-refcounts': True, 'refcount-bits': 16, 'corrupt': False, - 'compression-type': 'zlib' } + 'compression-type': 'zlib', 'extended-l2': False } human_compare = [ 'compat: 1.1', 'compression type: zlib', 'lazy refcounts: true', 'refcount bits: 16', - 'corrupt: false' ] + 'corrupt: false', 'extended l2: false' ] class TestQCow3NotLazyQMP(TestQMP): '''Testing a qcow2 version 3 image with lazy refcounts disabled, opening @@ -120,7 +120,7 @@ class TestQCow3NotLazyQMP(TestQMP): qemu_options = 'lazy-refcounts=on' compare = { 'compat': '1.1', 'lazy-refcounts': False, 'refcount-bits': 16, 'corrupt': False, - 'compression-type': 'zlib' } + 'compression-type': 'zlib', 'extended-l2': False } class TestQCow3LazyQMP(TestQMP): @@ -130,7 +130,7 @@ class TestQCow3LazyQMP(TestQMP): qemu_options = 'lazy-refcounts=off' compare = { 'compat': '1.1', 'lazy-refcounts': True, 'refcount-bits': 16, 'corrupt': False, - 'compression-type': 'zlib' } + 'compression-type': 'zlib', 'extended-l2': False } TestImageInfoSpecific = None TestQemuImgInfo = None diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067 deleted file mode 100755 index a63be9cabf78fae09b790f6b30d8a7288a9f5b84..0000000000000000000000000000000000000000 --- a/tests/qemu-iotests/067 +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/env bash -# -# Test automatic deletion of BDSes created by -drive/drive_add -# -# Copyright (C) 2013 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! - -# get standard environment, filters and checks -. ./common.rc -. ./common.filter - -_supported_fmt qcow2 -_supported_proto file -# Because anything other than 16 would change the output of query-block, -# and external data files would change the output of -# query-named-block-nodes -_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file - -do_run_qemu() -{ - echo Testing: "$@" - $QEMU -nographic -qmp-pretty stdio -serial none "$@" - echo -} - -# Remove QMP events from (pretty-printed) output. Doesn't handle -# nested dicts correctly, but we don't get any of those in this test. -_filter_qmp_events() -{ - tr '\n' '\t' | sed -e \ - 's/{\s*"timestamp":\s*{[^}]*},\s*"event":[^,}]*\(,\s*"data":\s*{[^}]*}\)\?\s*}\s*//g' \ - | tr '\t' '\n' -} - -run_qemu() -{ - do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp | _filter_qemu \ - | _filter_actual_image_size \ - | _filter_generated_node_ids | _filter_qmp_events \ - | _filter_img_info -} - -size=128M - -_make_test_img $size - -echo -echo === -drive/-device and device_del === -echo - -run_qemu -drive file=$TEST_IMG,format=$IMGFMT,if=none,id=disk -device virtio-blk,drive=disk,id=virtio0 <&1 | _filter_testdir | _filter_imgfmt diff --git a/tests/qemu-iotests/069.out b/tests/qemu-iotests/069.out index c78e8c2b720419d184f452c7f0d8f39f59adddc7..126b4d2d519b9026709fdcbbab067989255d97a9 100644 --- a/tests/qemu-iotests/069.out +++ b/tests/qemu-iotests/069.out @@ -3,6 +3,6 @@ QA output created by 069 === Creating an image with a backing file and deleting that file === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=131072 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open backing file: Could not open 'TEST_DIR/t.IMGFMT.base': No such file or directory *** done diff --git a/tests/qemu-iotests/073 b/tests/qemu-iotests/073 index 23a1bdf8905623958f1dd13372d2efc7fefc6720..68517821e875aed4384de94ee3b1cc3c2c66d8a4 100755 --- a/tests/qemu-iotests/073 +++ b/tests/qemu-iotests/073 @@ -38,7 +38,6 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto generic -_unsupported_proto vxhs # External data files do not support compressed clusters # (TODO: Consider writing a version for external data files that does # not test compressed clusters) @@ -52,7 +51,7 @@ echo "== creating backing file ==" TEST_IMG="$TEST_IMG.base" _make_test_img $size -_make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $QEMU_IO -c "write -P 0xa5 0 $size" "$TEST_IMG.base" | _filter_qemu_io echo diff --git a/tests/qemu-iotests/073.out b/tests/qemu-iotests/073.out index de5452492c70ae60b9c5bb8b80e26e973cdb72fb..7a718b525e6891771cd68503aefb7a32598a886c 100644 --- a/tests/qemu-iotests/073.out +++ b/tests/qemu-iotests/073.out @@ -2,7 +2,7 @@ QA output created by 073 == creating backing file == Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 134217728/134217728 bytes at offset 0 128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/079.out b/tests/qemu-iotests/079.out index aab922fb369b6007a4ce1113079d439e324eed06..f65a9ca84feac8a21efebcfe42d8ecaafca7e93a 100644 --- a/tests/qemu-iotests/079.out +++ b/tests/qemu-iotests/079.out @@ -9,6 +9,6 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation=metadat Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation=metadata Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation=metadata Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation=metadata -qemu-img: TEST_DIR/t.IMGFMT: Cluster size must be a power of two between 512 and 2048k Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation=metadata +qemu-img: TEST_DIR/t.IMGFMT: Cluster size must be a power of two between 512 and 2048k *** done diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081 index 537d40dfd5ca8bd46d3f73e7f186fcc03977f1fd..4e199729317135b492cbe185cd07bd158f42e020 100755 --- a/tests/qemu-iotests/081 +++ b/tests/qemu-iotests/081 @@ -42,18 +42,20 @@ _supported_fmt raw _supported_proto file _supported_os Linux _require_drivers quorum +_require_devices virtio-scsi do_run_qemu() { - echo Testing: "$@" | _filter_imgfmt + echo Testing: "$@" $QEMU -nographic -qmp stdio -serial none "$@" echo } run_qemu() { - do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp\ - | _filter_qemu_io | _filter_generated_node_ids + do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_imgfmt | _filter_qemu \ + | _filter_qmp | _filter_qemu_io \ + | _filter_generated_node_ids } quorum="driver=raw,file.driver=quorum,file.vote-threshold=2" @@ -154,6 +156,59 @@ echo "== checking that quorum has corrected the corrupted file ==" $QEMU_IO -c "read -P 0x32 0 $size" "$TEST_DIR/2.raw" | _filter_qemu_io +echo +echo "== using quorum rewrite corrupted mode without WRITE permission ==" + +# The same as above, but this time, do it on a quorum node whose only +# parent will not take the WRITE permission + +echo '-- corrupting --' +# Only corrupt a portion: The guest device (scsi-hd on virtio-scsi) +# will read some data (looking for a partition table to guess the +# disk's geometry), which would trigger a quorum mismatch if the +# beginning of the image was corrupted. The subsequent +# QUORUM_REPORT_BAD event would be suppressed (because at that point, +# there cannot have been a qmp_capabilities on the monitor). Because +# that event is rate-limited, the next QUORUM_REPORT_BAD that happens +# thanks to our qemu-io read (which should trigger a mismatch) would +# then be delayed past the VM quit and not appear in the output. +# So we keep the first 1M intact to see a QUORUM_REPORT_BAD resulting +# from the qemu-io invocation. +$QEMU_IO -c "write -P 0x42 1M 1M" "$TEST_DIR/2.raw" | _filter_qemu_io + +# Fix the corruption (on a read-only quorum node, i.e. without taking +# the WRITE permission on it -- its child nodes need to be R/W OTOH, +# so that rewrite-corrupted works) +echo +echo '-- running quorum --' +run_qemu \ + -blockdev file,node-name=file1,filename="$TEST_DIR/1.raw" \ + -blockdev file,node-name=file2,filename="$TEST_DIR/2.raw" \ + -blockdev file,node-name=file3,filename="$TEST_DIR/3.raw" \ + -blockdev '{ + "driver": "quorum", + "node-name": "quorum", + "read-only": true, + "vote-threshold": 2, + "rewrite-corrupted": true, + "children": [ "file1", "file2", "file3" ] + }' \ + -device virtio-scsi,id=scsi \ + -device scsi-hd,id=quorum-drive,bus=scsi.0,drive=quorum \ + < - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables + extent_size_hint= - Extent size hint for the image file, 0 to disable lazy_refcounts= - Postpone refcount updates nocow= - Turn off copy-on-write (valid only on btrfs) preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) @@ -86,6 +90,8 @@ Supported options: encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables + extent_size_hint= - Extent size hint for the image file, 0 to disable lazy_refcounts= - Postpone refcount updates nocow= - Turn off copy-on-write (valid only on btrfs) preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) @@ -110,6 +116,8 @@ Supported options: encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables + extent_size_hint= - Extent size hint for the image file, 0 to disable lazy_refcounts= - Postpone refcount updates nocow= - Turn off copy-on-write (valid only on btrfs) preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) @@ -134,6 +142,8 @@ Supported options: encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables + extent_size_hint= - Extent size hint for the image file, 0 to disable lazy_refcounts= - Postpone refcount updates nocow= - Turn off copy-on-write (valid only on btrfs) preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) @@ -158,6 +168,8 @@ Supported options: encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables + extent_size_hint= - Extent size hint for the image file, 0 to disable lazy_refcounts= - Postpone refcount updates nocow= - Turn off copy-on-write (valid only on btrfs) preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) @@ -182,6 +194,8 @@ Supported options: encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables + extent_size_hint= - Extent size hint for the image file, 0 to disable lazy_refcounts= - Postpone refcount updates nocow= - Turn off copy-on-write (valid only on btrfs) preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) @@ -206,6 +220,8 @@ Supported options: encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables + extent_size_hint= - Extent size hint for the image file, 0 to disable lazy_refcounts= - Postpone refcount updates nocow= - Turn off copy-on-write (valid only on btrfs) preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) @@ -230,17 +246,19 @@ Supported options: encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables + extent_size_hint= - Extent size hint for the image file, 0 to disable lazy_refcounts= - Postpone refcount updates nocow= - Turn off copy-on-write (valid only on btrfs) preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) refcount_bits= - Width of a reference count entry in bits size= - Virtual disk size -Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,help cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,help -F qcow2 TEST_DIR/t.qcow2 128M +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2,,help backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 -Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,? TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,? cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,? -F qcow2 TEST_DIR/t.qcow2 128M +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2,,? backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2, -o help TEST_DIR/t.qcow2 128M qemu-img: Invalid option list: backing_file=TEST_DIR/t.qcow2, @@ -269,6 +287,7 @@ Supported qcow2 options: encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables lazy_refcounts= - Postpone refcount updates preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) refcount_bits= - Width of a reference count entry in bits @@ -290,7 +309,7 @@ qemu-img: Format driver 'bochs' does not support image creation === convert: Options specified more than once === Testing: create -f qcow2 TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16 Testing: convert -f foo -f qcow2 TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base image: TEST_DIR/t.IMGFMT.base @@ -314,6 +333,7 @@ Format specific information: lazy refcounts: true refcount bits: 16 corrupt: false + extended l2: false Testing: convert -O qcow2 -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base image: TEST_DIR/t.IMGFMT.base @@ -326,6 +346,7 @@ Format specific information: lazy refcounts: true refcount bits: 16 corrupt: false + extended l2: false Testing: convert -O qcow2 -o cluster_size=4k,cluster_size=8k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base image: TEST_DIR/t.IMGFMT.base @@ -353,6 +374,8 @@ Supported options: encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables + extent_size_hint= - Extent size hint for the image file, 0 to disable lazy_refcounts= - Postpone refcount updates nocow= - Turn off copy-on-write (valid only on btrfs) preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) @@ -377,6 +400,8 @@ Supported options: encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables + extent_size_hint= - Extent size hint for the image file, 0 to disable lazy_refcounts= - Postpone refcount updates nocow= - Turn off copy-on-write (valid only on btrfs) preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) @@ -401,6 +426,8 @@ Supported options: encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables + extent_size_hint= - Extent size hint for the image file, 0 to disable lazy_refcounts= - Postpone refcount updates nocow= - Turn off copy-on-write (valid only on btrfs) preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) @@ -425,6 +452,8 @@ Supported options: encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables + extent_size_hint= - Extent size hint for the image file, 0 to disable lazy_refcounts= - Postpone refcount updates nocow= - Turn off copy-on-write (valid only on btrfs) preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) @@ -449,6 +478,8 @@ Supported options: encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables + extent_size_hint= - Extent size hint for the image file, 0 to disable lazy_refcounts= - Postpone refcount updates nocow= - Turn off copy-on-write (valid only on btrfs) preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) @@ -473,6 +504,8 @@ Supported options: encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables + extent_size_hint= - Extent size hint for the image file, 0 to disable lazy_refcounts= - Postpone refcount updates nocow= - Turn off copy-on-write (valid only on btrfs) preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) @@ -497,6 +530,8 @@ Supported options: encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables + extent_size_hint= - Extent size hint for the image file, 0 to disable lazy_refcounts= - Postpone refcount updates nocow= - Turn off copy-on-write (valid only on btrfs) preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) @@ -521,16 +556,18 @@ Supported options: encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables + extent_size_hint= - Extent size hint for the image file, 0 to disable lazy_refcounts= - Postpone refcount updates nocow= - Turn off copy-on-write (valid only on btrfs) preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) refcount_bits= - Width of a reference count entry in bits size= - Virtual disk size -Testing: convert -O qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base +Testing: convert -O qcow2 -o backing_fmt=qcow2,backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base qemu-img: Could not open 'TEST_DIR/t.qcow2.base': Could not open backing file: Could not open 'TEST_DIR/t.qcow2,help': No such file or directory -Testing: convert -O qcow2 -o backing_file=TEST_DIR/t.qcow2,,? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base +Testing: convert -O qcow2 -o backing_fmt=qcow2,backing_file=TEST_DIR/t.qcow2,,? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base qemu-img: Could not open 'TEST_DIR/t.qcow2.base': Could not open backing file: Could not open 'TEST_DIR/t.qcow2,?': No such file or directory Testing: convert -O qcow2 -o backing_file=TEST_DIR/t.qcow2, -o help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base @@ -560,6 +597,7 @@ Supported qcow2 options: encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + extended_l2= - Extended L2 tables lazy_refcounts= - Postpone refcount updates preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) refcount_bits= - Width of a reference count entry in bits @@ -605,6 +643,7 @@ Format specific information: lazy refcounts: true refcount bits: 16 corrupt: false + extended l2: false Testing: amend -f qcow2 -o size=130M -o lazy_refcounts=off TEST_DIR/t.qcow2 image: TEST_DIR/t.IMGFMT @@ -617,6 +656,7 @@ Format specific information: lazy refcounts: false refcount bits: 16 corrupt: false + extended l2: false Testing: amend -f qcow2 -o size=8M -o lazy_refcounts=on -o size=132M TEST_DIR/t.qcow2 image: TEST_DIR/t.IMGFMT @@ -629,6 +669,7 @@ Format specific information: lazy refcounts: true refcount bits: 16 corrupt: false + extended l2: false Testing: amend -f qcow2 -o size=4M,size=148M TEST_DIR/t.qcow2 image: TEST_DIR/t.IMGFMT @@ -639,210 +680,140 @@ cluster_size: 65536 === amend: help for -o === Testing: amend -f qcow2 -o help TEST_DIR/t.qcow2 -Creation options for 'qcow2': +Amend options for 'qcow2': backing_file= - File name of a base image backing_fmt= - Image format of the base image - cluster_size= - qcow2 cluster size compat= - Compatibility level (v2 [0.10] or v3 [1.1]) - compression_type= - Compression method used for image cluster compression data_file= - File name of an external data file data_file_raw= - The external data file must stay valid as a raw image - encrypt.cipher-alg= - Name of encryption cipher algorithm - encrypt.cipher-mode= - Name of encryption cipher mode - encrypt.format= - Encrypt the image, format choices: 'aes', 'luks' - encrypt.hash-alg= - Name of encryption hash algorithm encrypt.iter-time= - Time to spend in PBKDF in milliseconds - encrypt.ivgen-alg= - Name of IV generator algorithm - encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm - encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase - encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + encrypt.keyslot= - Select a single keyslot to modify explicitly + encrypt.new-secret= - New secret to set in the matching keyslots. Empty string to erase + encrypt.old-secret= - Select all keyslots that match this password + encrypt.state= - Select new state of affected keyslots (active/inactive) lazy_refcounts= - Postpone refcount updates - preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) refcount_bits= - Width of a reference count entry in bits size= - Virtual disk size -Note that not all of these options may be amendable. - Testing: amend -f qcow2 -o ? TEST_DIR/t.qcow2 -Creation options for 'qcow2': +Amend options for 'qcow2': backing_file= - File name of a base image backing_fmt= - Image format of the base image - cluster_size= - qcow2 cluster size compat= - Compatibility level (v2 [0.10] or v3 [1.1]) - compression_type= - Compression method used for image cluster compression data_file= - File name of an external data file data_file_raw= - The external data file must stay valid as a raw image - encrypt.cipher-alg= - Name of encryption cipher algorithm - encrypt.cipher-mode= - Name of encryption cipher mode - encrypt.format= - Encrypt the image, format choices: 'aes', 'luks' - encrypt.hash-alg= - Name of encryption hash algorithm encrypt.iter-time= - Time to spend in PBKDF in milliseconds - encrypt.ivgen-alg= - Name of IV generator algorithm - encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm - encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase - encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + encrypt.keyslot= - Select a single keyslot to modify explicitly + encrypt.new-secret= - New secret to set in the matching keyslots. Empty string to erase + encrypt.old-secret= - Select all keyslots that match this password + encrypt.state= - Select new state of affected keyslots (active/inactive) lazy_refcounts= - Postpone refcount updates - preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) refcount_bits= - Width of a reference count entry in bits size= - Virtual disk size -Note that not all of these options may be amendable. - Testing: amend -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2 -Creation options for 'qcow2': +Amend options for 'qcow2': backing_file= - File name of a base image backing_fmt= - Image format of the base image - cluster_size= - qcow2 cluster size compat= - Compatibility level (v2 [0.10] or v3 [1.1]) - compression_type= - Compression method used for image cluster compression data_file= - File name of an external data file data_file_raw= - The external data file must stay valid as a raw image - encrypt.cipher-alg= - Name of encryption cipher algorithm - encrypt.cipher-mode= - Name of encryption cipher mode - encrypt.format= - Encrypt the image, format choices: 'aes', 'luks' - encrypt.hash-alg= - Name of encryption hash algorithm encrypt.iter-time= - Time to spend in PBKDF in milliseconds - encrypt.ivgen-alg= - Name of IV generator algorithm - encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm - encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase - encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + encrypt.keyslot= - Select a single keyslot to modify explicitly + encrypt.new-secret= - New secret to set in the matching keyslots. Empty string to erase + encrypt.old-secret= - Select all keyslots that match this password + encrypt.state= - Select new state of affected keyslots (active/inactive) lazy_refcounts= - Postpone refcount updates - preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) refcount_bits= - Width of a reference count entry in bits size= - Virtual disk size -Note that not all of these options may be amendable. - Testing: amend -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2 -Creation options for 'qcow2': +Amend options for 'qcow2': backing_file= - File name of a base image backing_fmt= - Image format of the base image - cluster_size= - qcow2 cluster size compat= - Compatibility level (v2 [0.10] or v3 [1.1]) - compression_type= - Compression method used for image cluster compression data_file= - File name of an external data file data_file_raw= - The external data file must stay valid as a raw image - encrypt.cipher-alg= - Name of encryption cipher algorithm - encrypt.cipher-mode= - Name of encryption cipher mode - encrypt.format= - Encrypt the image, format choices: 'aes', 'luks' - encrypt.hash-alg= - Name of encryption hash algorithm encrypt.iter-time= - Time to spend in PBKDF in milliseconds - encrypt.ivgen-alg= - Name of IV generator algorithm - encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm - encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase - encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + encrypt.keyslot= - Select a single keyslot to modify explicitly + encrypt.new-secret= - New secret to set in the matching keyslots. Empty string to erase + encrypt.old-secret= - Select all keyslots that match this password + encrypt.state= - Select new state of affected keyslots (active/inactive) lazy_refcounts= - Postpone refcount updates - preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) refcount_bits= - Width of a reference count entry in bits size= - Virtual disk size -Note that not all of these options may be amendable. - Testing: amend -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2 -Creation options for 'qcow2': +Amend options for 'qcow2': backing_file= - File name of a base image backing_fmt= - Image format of the base image - cluster_size= - qcow2 cluster size compat= - Compatibility level (v2 [0.10] or v3 [1.1]) - compression_type= - Compression method used for image cluster compression data_file= - File name of an external data file data_file_raw= - The external data file must stay valid as a raw image - encrypt.cipher-alg= - Name of encryption cipher algorithm - encrypt.cipher-mode= - Name of encryption cipher mode - encrypt.format= - Encrypt the image, format choices: 'aes', 'luks' - encrypt.hash-alg= - Name of encryption hash algorithm encrypt.iter-time= - Time to spend in PBKDF in milliseconds - encrypt.ivgen-alg= - Name of IV generator algorithm - encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm - encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase - encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + encrypt.keyslot= - Select a single keyslot to modify explicitly + encrypt.new-secret= - New secret to set in the matching keyslots. Empty string to erase + encrypt.old-secret= - Select all keyslots that match this password + encrypt.state= - Select new state of affected keyslots (active/inactive) lazy_refcounts= - Postpone refcount updates - preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) refcount_bits= - Width of a reference count entry in bits size= - Virtual disk size -Note that not all of these options may be amendable. - Testing: amend -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2 -Creation options for 'qcow2': +Amend options for 'qcow2': backing_file= - File name of a base image backing_fmt= - Image format of the base image - cluster_size= - qcow2 cluster size compat= - Compatibility level (v2 [0.10] or v3 [1.1]) - compression_type= - Compression method used for image cluster compression data_file= - File name of an external data file data_file_raw= - The external data file must stay valid as a raw image - encrypt.cipher-alg= - Name of encryption cipher algorithm - encrypt.cipher-mode= - Name of encryption cipher mode - encrypt.format= - Encrypt the image, format choices: 'aes', 'luks' - encrypt.hash-alg= - Name of encryption hash algorithm encrypt.iter-time= - Time to spend in PBKDF in milliseconds - encrypt.ivgen-alg= - Name of IV generator algorithm - encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm - encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase - encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + encrypt.keyslot= - Select a single keyslot to modify explicitly + encrypt.new-secret= - New secret to set in the matching keyslots. Empty string to erase + encrypt.old-secret= - Select all keyslots that match this password + encrypt.state= - Select new state of affected keyslots (active/inactive) lazy_refcounts= - Postpone refcount updates - preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) refcount_bits= - Width of a reference count entry in bits size= - Virtual disk size -Note that not all of these options may be amendable. - Testing: amend -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2 -Creation options for 'qcow2': +Amend options for 'qcow2': backing_file= - File name of a base image backing_fmt= - Image format of the base image - cluster_size= - qcow2 cluster size compat= - Compatibility level (v2 [0.10] or v3 [1.1]) - compression_type= - Compression method used for image cluster compression data_file= - File name of an external data file data_file_raw= - The external data file must stay valid as a raw image - encrypt.cipher-alg= - Name of encryption cipher algorithm - encrypt.cipher-mode= - Name of encryption cipher mode - encrypt.format= - Encrypt the image, format choices: 'aes', 'luks' - encrypt.hash-alg= - Name of encryption hash algorithm encrypt.iter-time= - Time to spend in PBKDF in milliseconds - encrypt.ivgen-alg= - Name of IV generator algorithm - encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm - encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase - encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + encrypt.keyslot= - Select a single keyslot to modify explicitly + encrypt.new-secret= - New secret to set in the matching keyslots. Empty string to erase + encrypt.old-secret= - Select all keyslots that match this password + encrypt.state= - Select new state of affected keyslots (active/inactive) lazy_refcounts= - Postpone refcount updates - preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) refcount_bits= - Width of a reference count entry in bits size= - Virtual disk size -Note that not all of these options may be amendable. - Testing: amend -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2 -Creation options for 'qcow2': +Amend options for 'qcow2': backing_file= - File name of a base image backing_fmt= - Image format of the base image - cluster_size= - qcow2 cluster size compat= - Compatibility level (v2 [0.10] or v3 [1.1]) - compression_type= - Compression method used for image cluster compression data_file= - File name of an external data file data_file_raw= - The external data file must stay valid as a raw image - encrypt.cipher-alg= - Name of encryption cipher algorithm - encrypt.cipher-mode= - Name of encryption cipher mode - encrypt.format= - Encrypt the image, format choices: 'aes', 'luks' - encrypt.hash-alg= - Name of encryption hash algorithm encrypt.iter-time= - Time to spend in PBKDF in milliseconds - encrypt.ivgen-alg= - Name of IV generator algorithm - encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm - encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase - encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + encrypt.keyslot= - Select a single keyslot to modify explicitly + encrypt.new-secret= - New secret to set in the matching keyslots. Empty string to erase + encrypt.old-secret= - Select all keyslots that match this password + encrypt.state= - Select new state of affected keyslots (active/inactive) lazy_refcounts= - Postpone refcount updates - preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) refcount_bits= - Width of a reference count entry in bits size= - Virtual disk size -Note that not all of these options may be amendable. - Testing: amend -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 +qemu-img: warning: Deprecated use of amend to alter the backing file; use qemu-img rebase instead Testing: rebase -u -b -f qcow2 TEST_DIR/t.qcow2 Testing: amend -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,? TEST_DIR/t.qcow2 +qemu-img: warning: Deprecated use of amend to alter the backing file; use qemu-img rebase instead Testing: rebase -u -b -f qcow2 TEST_DIR/t.qcow2 @@ -856,30 +827,21 @@ Testing: amend -f qcow2 -o backing_file=TEST_DIR/t.qcow2 -o ,, -o help TEST_DIR/ qemu-img: Invalid option list: ,, Testing: amend -f qcow2 -o help -Creation options for 'qcow2': +Amend options for 'qcow2': backing_file= - File name of a base image backing_fmt= - Image format of the base image - cluster_size= - qcow2 cluster size compat= - Compatibility level (v2 [0.10] or v3 [1.1]) - compression_type= - Compression method used for image cluster compression data_file= - File name of an external data file data_file_raw= - The external data file must stay valid as a raw image - encrypt.cipher-alg= - Name of encryption cipher algorithm - encrypt.cipher-mode= - Name of encryption cipher mode - encrypt.format= - Encrypt the image, format choices: 'aes', 'luks' - encrypt.hash-alg= - Name of encryption hash algorithm encrypt.iter-time= - Time to spend in PBKDF in milliseconds - encrypt.ivgen-alg= - Name of IV generator algorithm - encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm - encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase - encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) + encrypt.keyslot= - Select a single keyslot to modify explicitly + encrypt.new-secret= - New secret to set in the matching keyslots. Empty string to erase + encrypt.old-secret= - Select all keyslots that match this password + encrypt.state= - Select new state of affected keyslots (active/inactive) lazy_refcounts= - Postpone refcount updates - preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) refcount_bits= - Width of a reference count entry in bits size= - Virtual disk size -Note that not all of these options may be amendable. - Testing: amend -o help qemu-img: Expecting one image file name diff --git a/tests/qemu-iotests/085 b/tests/qemu-iotests/085 index dd3c993a2d579ed484403afe303673f3600de5ed..e99eb44581e8549dc7700b9a33f8f071a7f11895 100755 --- a/tests/qemu-iotests/085 +++ b/tests/qemu-iotests/085 @@ -106,7 +106,7 @@ add_snapshot_image() { base_image="${TEST_DIR}/$((${1}-1))-${snapshot_virt0}" snapshot_file="${TEST_DIR}/${1}-${snapshot_virt0}" - TEST_IMG=$snapshot_file _make_test_img -u -b "${base_image}" "$size" + TEST_IMG=$snapshot_file _make_test_img -u -b "${base_image}" -F $IMGFMT "$size" do_blockdev_add "$1" "'backing': null, " "${snapshot_file}" } @@ -225,7 +225,7 @@ echo SNAPSHOTS=$((${SNAPSHOTS}+1)) TEST_IMG="$TEST_IMG.base" _make_test_img "$size" -_make_test_img -b "${TEST_IMG}.base" "$size" +_make_test_img -b "${TEST_IMG}.base" -F $IMGFMT "$size" do_blockdev_add ${SNAPSHOTS} "" "${TEST_IMG}" blockdev_snapshot ${SNAPSHOTS} error diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out index a822ff4ef6d86429930405cac0c36cd86258d554..7fc44b1c610c29222837daeefef03f151f5237e7 100644 --- a/tests/qemu-iotests/085.out +++ b/tests/qemu-iotests/085.out @@ -13,7 +13,7 @@ Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=134217728 === Create a single snapshot on virtio0 === { 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/1-snapshot-v0.IMGFMT', 'format': 'IMGFMT' } } -Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 {"return": {}} === Invalid command - missing device and nodename === @@ -30,50 +30,50 @@ Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file === Create several transactional group snapshots === { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/2-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/2-snapshot-v1.IMGFMT' } } ] } } -Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib -Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 {"return": {}} { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/3-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/3-snapshot-v1.IMGFMT' } } ] } } -Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib -Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 {"return": {}} { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/4-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/4-snapshot-v1.IMGFMT' } } ] } } -Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib -Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 {"return": {}} { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/5-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/5-snapshot-v1.IMGFMT' } } ] } } -Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib -Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 {"return": {}} { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/6-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/6-snapshot-v1.IMGFMT' } } ] } } -Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib -Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 {"return": {}} { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/7-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/7-snapshot-v1.IMGFMT' } } ] } } -Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib -Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 {"return": {}} { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/8-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/8-snapshot-v1.IMGFMT' } } ] } } -Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib -Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 {"return": {}} { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/9-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/9-snapshot-v1.IMGFMT' } } ] } } -Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib -Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 {"return": {}} { 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/10-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/10-snapshot-v1.IMGFMT' } } ] } } -Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib -Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 {"return": {}} === Create a couple of snapshots using blockdev-snapshot === -Formatting 'TEST_DIR/11-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/10-snapshot-v0.IMGFMT +Formatting 'TEST_DIR/11-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/10-snapshot-v0.IMGFMT backing_fmt=IMGFMT { 'execute': 'blockdev-add', 'arguments': { 'driver': 'IMGFMT', 'node-name': 'snap_11', 'backing': null, 'file': { 'driver': 'file', 'filename': 'TEST_DIR/11-snapshot-v0.IMGFMT', 'node-name': 'file_11' } } } {"return": {}} { 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_11' } } {"return": {}} -Formatting 'TEST_DIR/12-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/11-snapshot-v0.IMGFMT +Formatting 'TEST_DIR/12-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/11-snapshot-v0.IMGFMT backing_fmt=IMGFMT { 'execute': 'blockdev-add', 'arguments': { 'driver': 'IMGFMT', 'node-name': 'snap_12', 'backing': null, 'file': { 'driver': 'file', 'filename': 'TEST_DIR/12-snapshot-v0.IMGFMT', 'node-name': 'file_12' } } } {"return": {}} { 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_12' } } @@ -101,7 +101,7 @@ Formatting 'TEST_DIR/12-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_f === Invalid command - snapshot node has a backing image === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT { 'execute': 'blockdev-add', 'arguments': { 'driver': 'IMGFMT', 'node-name': 'snap_13', 'file': { 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'node-name': 'file_13' } } } {"return": {}} { 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_13' } } diff --git a/tests/qemu-iotests/087 b/tests/qemu-iotests/087 index bdfdad3454e3b5e1f950f4bc55baff58210a817e..678e748c58c737de8d035c8d2ed7d5bcc375e027 100755 --- a/tests/qemu-iotests/087 +++ b/tests/qemu-iotests/087 @@ -39,6 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto file _supported_os Linux +_require_working_luks do_run_qemu() { diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out index 2d92ea847b01031cca5bd25e9dbdf70a2ba58176..b61ba638af2686f981072675147f81e519968dea 100644 --- a/tests/qemu-iotests/087.out +++ b/tests/qemu-iotests/087.out @@ -34,7 +34,7 @@ QMP_VERSION === Encrypted image QCow === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on Testing: QMP_VERSION {"return": {}} @@ -46,7 +46,7 @@ QMP_VERSION === Encrypted image LUKS === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encrypt.format=luks encrypt.key-secret=sec0 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 Testing: QMP_VERSION {"return": {}} @@ -58,7 +58,7 @@ QMP_VERSION === Missing driver === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on Testing: -S QMP_VERSION {"return": {}} diff --git a/tests/qemu-iotests/089 b/tests/qemu-iotests/089 index 059ad75e28d67d8597bd7592d75940e3a76beb41..66c5415abe8ca63f4f8dddedf9b1d5bc0c30f650 100755 --- a/tests/qemu-iotests/089 +++ b/tests/qemu-iotests/089 @@ -84,7 +84,7 @@ echo echo "=== Testing correct handling of 'backing':null ===" echo -_make_test_img -b "$TEST_IMG.base" $IMG_SIZE +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $IMG_SIZE # This should read 42 $QEMU_IO -c 'read -P 42 0 512' "$TEST_IMG" | _filter_qemu_io diff --git a/tests/qemu-iotests/089.out b/tests/qemu-iotests/089.out index 20c8ce8f0ef48d12f7917b0491830eb36a5cf28c..15682c28862a8ded3a356960a0b47217cacffb9c 100644 --- a/tests/qemu-iotests/089.out +++ b/tests/qemu-iotests/089.out @@ -21,7 +21,7 @@ read 512/512 bytes at offset 0 === Testing correct handling of 'backing':null === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 512/512 bytes at offset 0 diff --git a/tests/qemu-iotests/095 b/tests/qemu-iotests/095 index 155ae86aa7805a064fdd5cba4b2019a0baa1b2f0..77a5f0f3f597bcf9f53e0cfbfe8151d618c048af 100755 --- a/tests/qemu-iotests/095 +++ b/tests/qemu-iotests/095 @@ -51,9 +51,9 @@ size_larger=100M TEST_IMG="$TEST_IMG.base" _make_test_img $size_smaller -TEST_IMG="$TEST_IMG.snp1" _make_test_img -b "$TEST_IMG.base" $size_larger +TEST_IMG="$TEST_IMG.snp1" _make_test_img -b "$TEST_IMG.base" -F $IMGFMT $size_larger -_make_test_img -b "${TEST_IMG}.snp1" $size_larger +_make_test_img -b "${TEST_IMG}.snp1" -F $IMGFMT $size_larger echo echo "=== Base image info before commit and resize ===" diff --git a/tests/qemu-iotests/095.out b/tests/qemu-iotests/095.out index 614e5ccbbb3837a3d2e908c270c59ce3878293ea..e66ced58f85528d74ed621a4872f6c984fb3ef57 100644 --- a/tests/qemu-iotests/095.out +++ b/tests/qemu-iotests/095.out @@ -1,7 +1,7 @@ QA output created by 095 Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=5242880 -Formatting 'TEST_DIR/t.IMGFMT.snp1', fmt=IMGFMT size=104857600 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=104857600 backing_file=TEST_DIR/t.IMGFMT.snp1 +Formatting 'TEST_DIR/t.IMGFMT.snp1', fmt=IMGFMT size=104857600 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=104857600 backing_file=TEST_DIR/t.IMGFMT.snp1 backing_fmt=IMGFMT === Base image info before commit and resize === image: TEST_DIR/t.IMGFMT.base diff --git a/tests/qemu-iotests/097 b/tests/qemu-iotests/097 index 690f3d3ce1ed2058f0d73a3ceed3280d981fc196..d910a8b107ea57d58b3f02f64da0eb6dbb75acca 100755 --- a/tests/qemu-iotests/097 +++ b/tests/qemu-iotests/097 @@ -67,8 +67,8 @@ echo len=$((2100 * 1024 * 1024 + 512)) # larger than 2G, and not cluster aligned TEST_IMG="$TEST_IMG.base" _make_test_img $len -TEST_IMG="$TEST_IMG.itmd" _make_test_img -b "$TEST_IMG.base" $len -_make_test_img -b "$TEST_IMG.itmd" $len +TEST_IMG="$TEST_IMG.itmd" _make_test_img -b "$TEST_IMG.base" -F $IMGFMT $len +_make_test_img -b "$TEST_IMG.itmd" -F $IMGFMT $len $QEMU_IO -c "write -P 1 0x7ffd0000 192k" "$TEST_IMG.base" | _filter_qemu_io $QEMU_IO -c "write -P 2 0x7ffe0000 128k" "$TEST_IMG.itmd" | _filter_qemu_io diff --git a/tests/qemu-iotests/097.out b/tests/qemu-iotests/097.out index f6705a1cc74a90c5529cdb0dda847c18cbb8f61a..3038ddab3100be39391cb61e18bec3daf7704b15 100644 --- a/tests/qemu-iotests/097.out +++ b/tests/qemu-iotests/097.out @@ -3,8 +3,8 @@ QA output created by 097 === Test pass 0 === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd backing_fmt=IMGFMT wrote 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 2147352576 @@ -40,8 +40,8 @@ Offset Length File === Test pass 1 === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd backing_fmt=IMGFMT wrote 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 2147352576 @@ -78,8 +78,8 @@ Offset Length File === Test pass 2 === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd backing_fmt=IMGFMT wrote 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 2147352576 @@ -116,8 +116,8 @@ Offset Length File === Test pass 3 === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd backing_fmt=IMGFMT wrote 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 2147352576 diff --git a/tests/qemu-iotests/098 b/tests/qemu-iotests/098 index 1e29d96b3d7e7088429f5237585da26d25cc3a34..f2ccdd790980747d8d9ee2e894cd0cd582ff1f44 100755 --- a/tests/qemu-iotests/098 +++ b/tests/qemu-iotests/098 @@ -52,7 +52,7 @@ echo "=== $event ===" echo TEST_IMG="$TEST_IMG.base" _make_test_img 64M -_make_test_img -b "$TEST_IMG.base" 64M +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT 64M # Some data that can be leaked when emptying the top image $QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io diff --git a/tests/qemu-iotests/098.out b/tests/qemu-iotests/098.out index 23cf371f53f049368e60bdd7942ad25297662908..6c73dd0977fbce53c00243b723d7e95612756ee1 100644 --- a/tests/qemu-iotests/098.out +++ b/tests/qemu-iotests/098.out @@ -3,7 +3,7 @@ QA output created by 098 === l1_update === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error @@ -12,7 +12,7 @@ No errors were found on the image. === empty_image_prepare === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error @@ -25,7 +25,7 @@ No errors were found on the image. === reftable_update === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error @@ -39,7 +39,7 @@ No errors were found on the image. === refblock_alloc === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error diff --git a/tests/qemu-iotests/106 b/tests/qemu-iotests/106 index b5d1ec407824dc3d881873f581fd1f94efb098ae..a20659d443803591615b3ff37b087afb9025fac5 100755 --- a/tests/qemu-iotests/106 +++ b/tests/qemu-iotests/106 @@ -51,7 +51,10 @@ for create_mode in off falloc full; do echo echo "--- create_mode=$create_mode growth_mode=$growth_mode ---" - _make_test_img -o "preallocation=$create_mode" ${CREATION_SIZE}K + # Our calculation below assumes kilobytes as unit for the actual size. + # Disable the extent size hint because it would give us a result in + # megabytes. + _make_test_img -o "preallocation=$create_mode,extent_size_hint=0" ${CREATION_SIZE}K $QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K expected_size=0 @@ -98,7 +101,7 @@ for growth_mode in falloc full; do # plain int. We should use the correct type for the result, and # this tests we do. - _make_test_img 2G + _make_test_img -o "extent_size_hint=0" 2G $QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size') diff --git a/tests/qemu-iotests/110 b/tests/qemu-iotests/110 index 139c02c2cf6ba49bb1c86a59eee6c8b0a50d06ae..f1813d0dfb50e5675e1aef5028018040e4b5ebec 100755 --- a/tests/qemu-iotests/110 +++ b/tests/qemu-iotests/110 @@ -50,7 +50,7 @@ echo '=== Reconstructable filename ===' echo TEST_IMG="$TEST_IMG.base" _make_test_img 64M -_make_test_img -b "$TEST_IMG_REL.base" 64M +_make_test_img -b "$TEST_IMG_REL.base" -F $IMGFMT 64M # qemu should be able to reconstruct the filename, so relative backing names # should work # (We have to filter the backing file format because vmdk always @@ -91,7 +91,7 @@ echo '=== Backing name is always relative to the backed image ===' echo # omit the image size; it should work anyway -_make_test_img -b "$TEST_IMG_REL.base" +_make_test_img -b "$TEST_IMG_REL.base" -F $IMGFMT echo echo '=== Nodes without a common directory ===' diff --git a/tests/qemu-iotests/110.out b/tests/qemu-iotests/110.out index f835553a9930209cef3aae6486957aa54c8c9691..cf8f6c025d6062b94edb2e044daebb35e66c8b5a 100644 --- a/tests/qemu-iotests/110.out +++ b/tests/qemu-iotests/110.out @@ -3,7 +3,7 @@ QA output created by 110 === Reconstructable filename === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.base backing_fmt=IMGFMT image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 64 MiB (67108864 bytes) @@ -18,7 +18,7 @@ backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base) === Backing name is always relative to the backed image === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.base backing_fmt=IMGFMT === Nodes without a common directory === diff --git a/tests/qemu-iotests/111.out b/tests/qemu-iotests/111.out index 5279c462fc21b7c7f2dd05a32b0f758df2663515..ba034e5c588637ee0ca02b5771f250f192bfebcf 100644 --- a/tests/qemu-iotests/111.out +++ b/tests/qemu-iotests/111.out @@ -1,4 +1,4 @@ QA output created by 111 qemu-img: TEST_DIR/t.IMGFMT: Could not open 'TEST_DIR/t.IMGFMT.inexistent': No such file or directory -Could not open backing image to determine size. +Could not open backing image. *** done diff --git a/tests/qemu-iotests/112.out b/tests/qemu-iotests/112.out index ae0318cabea681c992f4d95d946bccc4b4a73211..dd3cc4383c12898b179954be6fd3d7e717614968 100644 --- a/tests/qemu-iotests/112.out +++ b/tests/qemu-iotests/112.out @@ -2,14 +2,14 @@ QA output created by 112 === refcount_bits limits === -qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 refcount_bits=-1 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 refcount bits: 1 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 @@ -21,10 +21,10 @@ refcount bits: 16 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 refcount bits: 16 -qemu-img: TEST_DIR/t.IMGFMT: Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater) Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-img: TEST_DIR/t.IMGFMT: Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater) Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-img: TEST_DIR/t.IMGFMT: Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater) === Snapshot limit on refcount_bits=1 === diff --git a/tests/qemu-iotests/114 b/tests/qemu-iotests/114 index 26104fff6c6720866dc8312f0b1cb817500ad88d..80e5e5e5910eb8298aced88d8fa7994223d43d32 100755 --- a/tests/qemu-iotests/114 +++ b/tests/qemu-iotests/114 @@ -38,13 +38,21 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto generic -_unsupported_proto vxhs +# At least OpenBSD doesn't seem to have truncate +_supported_os Linux # qcow2.py does not work too well with external data files _unsupported_imgopts data_file +# Intentionally specify backing file without backing format; demonstrate +# the difference in warning messages when backing file could be probed. +# Note that only a non-raw probe result will affect the resulting image. +truncate -s $((64 * 1024 * 1024)) "$TEST_IMG.orig" +_make_test_img -b "$TEST_IMG.orig" 64M TEST_IMG="$TEST_IMG.base" _make_test_img 64M +$QEMU_IMG convert -O qcow2 -B "$TEST_IMG.orig" "$TEST_IMG.orig" "$TEST_IMG" _make_test_img -b "$TEST_IMG.base" 64M +_make_test_img -u -b "$TEST_IMG.base" 64M # Set an invalid backing file format $PYTHON qcow2.py "$TEST_IMG" add-header-ext 0xE2792ACA "foo" @@ -55,6 +63,11 @@ _img_info $QEMU_IO -c "open $TEST_IMG" -c "read 0 4k" 2>&1 | _filter_qemu_io | _filter_testdir $QEMU_IO -c "open -o backing.driver=$IMGFMT $TEST_IMG" -c "read 0 4k" | _filter_qemu_io +# Rebase the image, to show that omitting backing format triggers a warning, +# but probing now lets us use the backing file. +$QEMU_IMG rebase -u -b "$TEST_IMG.base" "$TEST_IMG" +$QEMU_IO -c "open $TEST_IMG" -c "read 0 4k" 2>&1 | _filter_qemu_io | _filter_testdir + # success, all done echo '*** done' rm -f $seq.full diff --git a/tests/qemu-iotests/114.out b/tests/qemu-iotests/114.out index 67adef37a4f6a5106ae545cb49b504bb843fa4cd..0a37d20c82a95d6d5ea9fc9635e7a9c8a34ea58b 100644 --- a/tests/qemu-iotests/114.out +++ b/tests/qemu-iotests/114.out @@ -1,5 +1,11 @@ QA output created by 114 +qemu-img: warning: Deprecated use of backing file without explicit backing format (detected format of raw) +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.orig Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +qemu-img: warning: Deprecated use of backing file without explicit backing format +qemu-img: warning: Deprecated use of backing file without explicit backing format (detected format of IMGFMT) +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +qemu-img: warning: Deprecated use of unopened backing file without explicit backing format, use of this image requires potentially unsafe format probing Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base image: TEST_DIR/t.IMGFMT file format: IMGFMT @@ -11,4 +17,7 @@ qemu-io: can't open device TEST_DIR/t.qcow2: Could not open backing file: Unknow no file open, try 'help open' read 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-img: warning: Deprecated use of backing file without explicit backing format, use of this image requires potentially unsafe format probing +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) *** done diff --git a/tests/qemu-iotests/118 b/tests/qemu-iotests/118 index adc8a848b500b37f5c215e0d142224537b7c1b5e..2350929fd833f4ec2b4640a7891c7cc7a8bd1876 100755 --- a/tests/qemu-iotests/118 +++ b/tests/qemu-iotests/118 @@ -683,11 +683,10 @@ class TestBlockJobsAfterCycle(ChangeBaseClass): except OSError: pass + # We need backing file support + @iotests.skip_for_formats(('vpc', 'parallels', 'qcow', 'vdi', 'vmdk', 'raw', + 'vhdx')) def test_snapshot_and_commit(self): - # We need backing file support - if iotests.imgfmt != 'qcow2' and iotests.imgfmt != 'qed': - return - result = self.vm.qmp('blockdev-snapshot-sync', device='drive0', snapshot_file=new_img, format=iotests.imgfmt) diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122 index f7a3ae684a7c1b298d3f4a2d808b9f3e671c5fce..0f3d4ca851bfe26b05770a9864bb0fe0373d4f91 100755 --- a/tests/qemu-iotests/122 +++ b/tests/qemu-iotests/122 @@ -52,9 +52,10 @@ echo echo "=== Check allocation status regression with -B ===" echo -_make_test_img -b "$TEST_IMG".base +_make_test_img -b "$TEST_IMG".base -F $IMGFMT $QEMU_IO -c "write -P 0x22 0 3M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir -$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base "$TEST_IMG" "$TEST_IMG".orig +$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base \ + -o backing_fmt=$IMGFMT "$TEST_IMG" "$TEST_IMG".orig $QEMU_IMG map "$TEST_IMG".orig | _filter_qemu_img_map @@ -62,18 +63,22 @@ echo echo "=== Check that zero clusters are kept in overlay ===" echo -_make_test_img -b "$TEST_IMG".base +_make_test_img -b "$TEST_IMG".base -F $IMGFMT $QEMU_IO -c "write -P 0 0 3M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir -$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base "$TEST_IMG" "$TEST_IMG".orig +$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base -o backing_fmt=$IMGFMT \ + "$TEST_IMG" "$TEST_IMG".orig $QEMU_IO -c "read -P 0 0 3M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir -$QEMU_IMG convert -O $IMGFMT -c -B "$TEST_IMG".base "$TEST_IMG" "$TEST_IMG".orig +$QEMU_IMG convert -O $IMGFMT -c -B "$TEST_IMG".base -o backing_fmt=$IMGFMT \ + "$TEST_IMG" "$TEST_IMG".orig $QEMU_IO -c "read -P 0 0 3M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir $QEMU_IO -c "write -z 0 3M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir -$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base "$TEST_IMG" "$TEST_IMG".orig +$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base -o backing_fmt=$IMGFMT \ + "$TEST_IMG" "$TEST_IMG".orig $QEMU_IO -c "read -P 0 0 3M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir -$QEMU_IMG convert -O $IMGFMT -c -B "$TEST_IMG".base "$TEST_IMG" "$TEST_IMG".orig +$QEMU_IMG convert -O $IMGFMT -c -B "$TEST_IMG".base -o backing_fmt=$IMGFMT \ + "$TEST_IMG" "$TEST_IMG".orig $QEMU_IO -c "read -P 0 0 3M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir @@ -94,11 +99,11 @@ TEST_IMG="$TEST_IMG".base _make_test_img 256M # We do not want such a zero write, however, because we are past the # end of the backing file on the target as well, so we do not need to # write anything there. -_make_test_img -b "$TEST_IMG".base 768M +_make_test_img -b "$TEST_IMG".base 768M -F $IMGFMT # Use compat=0.10 as the output so there is no zero cluster support $QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base -o compat=0.10 \ - "$TEST_IMG" "$TEST_IMG".orig + -o backing_fmt=$IMGFMT "$TEST_IMG" "$TEST_IMG".orig # See that nothing has been allocated past 64M $QEMU_IMG map "$TEST_IMG".orig | _filter_qemu_img_map @@ -110,7 +115,7 @@ $QEMU_IO -c 'write -P 0x11 255M 1M' "$TEST_IMG".base 2>&1 | _filter_qemu_io $QEMU_IO -c 'write -P 0x22 600M 1M' "$TEST_IMG" 2>&1 | _filter_qemu_io $QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base -o compat=0.10 \ - "$TEST_IMG" "$TEST_IMG".orig + -o backing_fmt=$IMGFMT "$TEST_IMG" "$TEST_IMG".orig $QEMU_IMG map "$TEST_IMG".orig | _filter_qemu_img_map $QEMU_IO -c 'read -P 0x11 255M 1M' \ @@ -199,7 +204,7 @@ $QEMU_IMG map --output=json "$TEST_IMG".orig | _filter_qemu_img_map TEST_IMG="$TEST_IMG".base _make_test_img 64M $QEMU_IO -c "write -P 0x11 0 32M" "$TEST_IMG".base 2>&1 | _filter_qemu_io | _filter_testdir -_make_test_img -b "$TEST_IMG".base 64M +_make_test_img -b "$TEST_IMG".base 64M -F $IMGFMT $QEMU_IO -c "write -P 0x22 0 3M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir echo @@ -276,6 +281,36 @@ $QEMU_IMG convert -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG".orig $QEMU_IMG compare "$TEST_IMG" "$TEST_IMG".orig +echo +echo '=== -n to an empty image ===' +echo + +TEST_IMG="$TEST_IMG".orig _make_test_img 64M + +# Convert with -n, which should not result in a fully allocated image, not even +# with compat=0.10 (because the target doesn't have a backing file) +for compat in "1.1" "0.10"; do + IMGOPTS="compat=$compat" _make_test_img 64M + $QEMU_IMG convert -O $IMGFMT -n "$TEST_IMG".orig "$TEST_IMG" + $QEMU_IMG map --output=json "$TEST_IMG" +done + +echo +echo '=== -n to an empty image with a backing file ===' +echo + +TEST_IMG="$TEST_IMG".orig _make_test_img 64M +TEST_IMG="$TEST_IMG".base _make_test_img 64M + +# Convert with -n, which should still not result in a fully allocated image for +# compat=1.1 (because it can use zero clusters), but it should be fully +# allocated with compat=0.10 +for compat in "1.1" "0.10"; do + IMGOPTS="compat=$compat" _make_test_img -b "$TEST_IMG".base -F $IMGFMT 64M + $QEMU_IMG convert -O $IMGFMT -n "$TEST_IMG".orig "$TEST_IMG" + $QEMU_IMG map --output=json "$TEST_IMG" +done + echo echo '=== -n -B to an image without a backing file ===' echo @@ -290,6 +325,13 @@ TEST_IMG="$TEST_IMG".orig _make_test_img 64M # backing file" $QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base -n "$TEST_IMG" "$TEST_IMG".orig +echo +echo '=== -n incompatible with -o ===' +echo + +$QEMU_IMG convert -O $IMGFMT -o preallocation=metadata -n \ + "$TEST_IMG" "$TEST_IMG".orig && echo "unexpected success" + # success, all done echo '*** done' rm -f $seq.full diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out index 1a35951a80a8ecee6828e45fb84df35cf743eb96..3a3e121d579dad21384214dc0302b6e8dd274b65 100644 --- a/tests/qemu-iotests/122.out +++ b/tests/qemu-iotests/122.out @@ -5,7 +5,7 @@ wrote 67108864/67108864 bytes at offset 0 === Check allocation status regression with -B === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 3145728/3145728 bytes at offset 0 3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Offset Length File @@ -14,7 +14,7 @@ Offset Length File === Check that zero clusters are kept in overlay === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 3145728/3145728 bytes at offset 0 3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 3145728/3145728 bytes at offset 0 @@ -31,7 +31,7 @@ read 3145728/3145728 bytes at offset 0 === Converting to an overlay larger than its backing file === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=268435456 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=805306368 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=805306368 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT Offset Length File wrote 1048576/1048576 bytes at offset 267386880 @@ -141,7 +141,7 @@ read 63963136/63963136 bytes at offset 3145728 Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 wrote 33554432/33554432 bytes at offset 0 32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 3145728/3145728 bytes at offset 0 3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -229,8 +229,29 @@ wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Images are identical. +=== -n to an empty image === + +Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +[{ "start": 0, "length": 67108864, "depth": 0, "zero": true, "data": false}] +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +[{ "start": 0, "length": 67108864, "depth": 0, "zero": true, "data": false}] + +=== -n to an empty image with a backing file === + +Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +[{ "start": 0, "length": 67108864, "depth": 0, "zero": true, "data": false}] +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +[{ "start": 0, "length": 67108864, "depth": 0, "zero": false, "data": true, "offset": 327680}] + === -n -B to an image without a backing file === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=67108864 + +=== -n incompatible with -o === + +qemu-img: -o has no effect when skipping image creation *** done diff --git a/tests/qemu-iotests/125 b/tests/qemu-iotests/125 index d51098404534dc213231d5d6ed3d35a95a92f587..5720e86dcef2152e6d8ff7cd0e1da95e79be0f20 100755 --- a/tests/qemu-iotests/125 +++ b/tests/qemu-iotests/125 @@ -43,6 +43,10 @@ get_image_size_on_host() _supported_fmt qcow2 _supported_proto file +# Growing a file with a backing file (without preallocation=full or +# =falloc) requires zeroing the newly added area, which is impossible +# to do quickly for v2 images, and hence is unsupported. +_unsupported_imgopts 'compat=0.10' if [ -z "$TEST_IMG_FILE" ]; then TEST_IMG_FILE=$TEST_IMG @@ -164,6 +168,34 @@ for GROWTH_SIZE in 16 48 80; do done done +# Test image resizing using preallocation and unaligned offsets +$QEMU_IMG create -f raw "$TEST_IMG.base" 128k | _filter_img_create +$QEMU_IO -c 'write -q -P 1 0 128k' -f raw "$TEST_IMG.base" +for orig_size in 31k 33k; do + for dst_size in 96k 128k; do + for prealloc in metadata full; do + echo "--- Resizing image from $orig_size to $dst_size (preallocation=$prealloc) ---" + _make_test_img -F raw -b "$TEST_IMG.base" -o cluster_size=64k "$orig_size" + $QEMU_IMG resize -f "$IMGFMT" --preallocation="$prealloc" "$TEST_IMG" "$dst_size" + # The first part of the image should contain data from the backing file + $QEMU_IO -c "read -q -P 1 0 ${orig_size}" "$TEST_IMG" + # The resized part of the image should contain zeroes + $QEMU_IO -c "read -q -P 0 ${orig_size} 63k" "$TEST_IMG" + # If the image does not have an external data file we can also verify its + # actual size. The resized image should have 7 clusters: + # header, L1 table, L2 table, refcount table, refcount block, 2 data clusters + if ! _get_data_file "$TEST_IMG" > /dev/null; then + expected_file_length=$((65536 * 7)) + file_length=$(stat -c '%s' "$TEST_IMG_FILE") + if [ "$file_length" != "$expected_file_length" ]; then + echo "ERROR: file length $file_length (expected $expected_file_length)" + fi + fi + echo + done + done +done + # success, all done echo '*** done' rm -f $seq.full diff --git a/tests/qemu-iotests/125.out b/tests/qemu-iotests/125.out index 596905f533945d9686ac92bf09207e7254f8b683..63a6e9e8a958720c69f28a2cd07704bca798b8ec 100644 --- a/tests/qemu-iotests/125.out +++ b/tests/qemu-iotests/125.out @@ -767,4 +767,37 @@ wrote 2048000/2048000 bytes at offset 0 wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=raw size=131072 +--- Resizing image from 31k to 96k (preallocation=metadata) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=31744 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 31k to 96k (preallocation=full) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=31744 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 31k to 128k (preallocation=metadata) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=31744 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 31k to 128k (preallocation=full) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=31744 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 33k to 96k (preallocation=metadata) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33792 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 33k to 96k (preallocation=full) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33792 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 33k to 128k (preallocation=metadata) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33792 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 33k to 128k (preallocation=full) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33792 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + *** done diff --git a/tests/qemu-iotests/126 b/tests/qemu-iotests/126 index b7fce1e59dd3cc3c7f1cec83a3ea51ed61ad9d7d..dd5a2112278d97497020f94d507a6cd66191ae54 100755 --- a/tests/qemu-iotests/126 +++ b/tests/qemu-iotests/126 @@ -61,7 +61,7 @@ BASE_IMG="$TEST_DIR/image:base.$IMGFMT" TOP_IMG="$TEST_DIR/image:top.$IMGFMT" TEST_IMG=$BASE_IMG _make_test_img 64M -TEST_IMG=$TOP_IMG _make_test_img -b ./image:base.$IMGFMT +TEST_IMG=$TOP_IMG _make_test_img -b ./image:base.$IMGFMT -F $IMGFMT # (1) The default cluster size depends on the image format # (2) vmdk only supports vmdk backing files, so it always reports the @@ -82,7 +82,7 @@ BASE_IMG="base.$IMGFMT" TOP_IMG="file:image:top.$IMGFMT" TEST_IMG=$BASE_IMG _make_test_img 64M -TEST_IMG=$TOP_IMG _make_test_img -b "$BASE_IMG" +TEST_IMG=$TOP_IMG _make_test_img -b "$BASE_IMG" -F $IMGFMT TEST_IMG=$TOP_IMG _img_info | grep -ve 'cluster_size' -e 'backing file format' diff --git a/tests/qemu-iotests/126.out b/tests/qemu-iotests/126.out index e3c4d619162dd105397be8c66c0a5475c3d6ecc5..7d6634685eb5d3a652aa6cad688ebf1191c90f58 100644 --- a/tests/qemu-iotests/126.out +++ b/tests/qemu-iotests/126.out @@ -8,14 +8,14 @@ Formatting 'file:TEST_DIR/a:b.IMGFMT', fmt=IMGFMT size=67108864 === Testing relative backing filename resolution === Formatting 'TEST_DIR/image:base.IMGFMT', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/image:top.IMGFMT', fmt=IMGFMT size=67108864 backing_file=./image:base.IMGFMT +Formatting 'TEST_DIR/image:top.IMGFMT', fmt=IMGFMT size=67108864 backing_file=./image:base.IMGFMT backing_fmt=IMGFMT image: TEST_DIR/image:top.IMGFMT file format: IMGFMT virtual size: 64 MiB (67108864 bytes) backing file: ./image:base.IMGFMT (actual path: TEST_DIR/./image:base.IMGFMT) Formatting 'base.IMGFMT', fmt=IMGFMT size=67108864 -Formatting 'file:image:top.IMGFMT', fmt=IMGFMT size=67108864 backing_file=base.IMGFMT +Formatting 'file:image:top.IMGFMT', fmt=IMGFMT size=67108864 backing_file=base.IMGFMT backing_fmt=IMGFMT image: ./image:top.IMGFMT file format: IMGFMT virtual size: 64 MiB (67108864 bytes) diff --git a/tests/qemu-iotests/127 b/tests/qemu-iotests/127 index a4fc8660381b7674b79ec7d52d096e84856e02a0..e2ac2f55364dcd882b766dbf960e1cbffe5af177 100755 --- a/tests/qemu-iotests/127 +++ b/tests/qemu-iotests/127 @@ -48,8 +48,8 @@ _require_devices virtio-scsi scsi-hd IMG_SIZE=64K _make_test_img $IMG_SIZE -TEST_IMG="$TEST_IMG.overlay0" _make_test_img -b "$TEST_IMG" $IMG_SIZE -TEST_IMG="$TEST_IMG.overlay1" _make_test_img -b "$TEST_IMG" $IMG_SIZE +TEST_IMG="$TEST_IMG.overlay0" _make_test_img -b "$TEST_IMG" -F $IMGFMT $IMG_SIZE +TEST_IMG="$TEST_IMG.overlay1" _make_test_img -b "$TEST_IMG" -F $IMGFMT $IMG_SIZE # So that we actually have something to mirror and the job does not return # immediately (which may be bad because then we cannot know whether the diff --git a/tests/qemu-iotests/127.out b/tests/qemu-iotests/127.out index 623d52bbd150860e5a766566c716144bf1cfb1be..efd6cb327fe579db3bf5d7a8c0f93370975ca797 100644 --- a/tests/qemu-iotests/127.out +++ b/tests/qemu-iotests/127.out @@ -1,7 +1,7 @@ QA output created by 127 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536 -Formatting 'TEST_DIR/t.IMGFMT.overlay0', fmt=IMGFMT size=65536 backing_file=TEST_DIR/t.IMGFMT -Formatting 'TEST_DIR/t.IMGFMT.overlay1', fmt=IMGFMT size=65536 backing_file=TEST_DIR/t.IMGFMT +Formatting 'TEST_DIR/t.IMGFMT.overlay0', fmt=IMGFMT size=65536 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT.overlay1', fmt=IMGFMT size=65536 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT wrote 42/42 bytes at offset 0 42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { 'execute': 'qmp_capabilities' } diff --git a/tests/qemu-iotests/129 b/tests/qemu-iotests/129 index b0da4a5541abef0d3df295e80c140a4e342a6f86..0e13244d850e62cff5289e97182fae7e830482fd 100755 --- a/tests/qemu-iotests/129 +++ b/tests/qemu-iotests/129 @@ -29,7 +29,8 @@ class TestStopWithBlockJob(iotests.QMPTestCase): def setUp(self): iotests.qemu_img('create', '-f', iotests.imgfmt, self.base_img, "1G") - iotests.qemu_img('create', '-f', iotests.imgfmt, self.test_img, "-b", self.base_img) + iotests.qemu_img('create', '-f', iotests.imgfmt, self.test_img, + "-b", self.base_img, '-F', iotests.imgfmt) iotests.qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x5d 1M 128M', self.test_img) self.vm = iotests.VM().add_drive(self.test_img) self.vm.launch() diff --git a/tests/qemu-iotests/130 b/tests/qemu-iotests/130 index 77ad2aa13a06094f26d2c8991e4862bba62eaa9c..a7b365701c490b4b4894eb0c26a8d997620e7454 100755 --- a/tests/qemu-iotests/130 +++ b/tests/qemu-iotests/130 @@ -42,7 +42,6 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto generic -_unsupported_proto vxhs _supported_os Linux # We are going to use lazy-refcounts _unsupported_imgopts 'compat=0.10' diff --git a/tests/qemu-iotests/133 b/tests/qemu-iotests/133 index 6f7cacc0910b456aba199d742b3bc316ad232e66..4070fd9457b2e183db4a0fda0d07cf4bc86a5a47 100755 --- a/tests/qemu-iotests/133 +++ b/tests/qemu-iotests/133 @@ -40,7 +40,7 @@ _supported_fmt qcow2 _supported_proto file TEST_IMG="$TEST_IMG.base" _make_test_img 64M -_make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT echo echo "=== Check that node-name can't be changed ===" diff --git a/tests/qemu-iotests/133.out b/tests/qemu-iotests/133.out index 1491ef45a984dfc6a2e216011876467d4424a4b8..d70c2e8041ced2c40d0889b6ad69257ecbb33cb1 100644 --- a/tests/qemu-iotests/133.out +++ b/tests/qemu-iotests/133.out @@ -1,6 +1,6 @@ QA output created by 133 Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT === Check that node-name can't be changed === diff --git a/tests/qemu-iotests/134 b/tests/qemu-iotests/134 index 5162d21662488b230a27e29816b763a548f4bd4a..17fe1d6ed48d7fe42c0bc21054dc42ba259e94ac 100755 --- a/tests/qemu-iotests/134 +++ b/tests/qemu-iotests/134 @@ -38,7 +38,6 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow qcow2 _supported_proto generic -_unsupported_proto vxhs size=128M diff --git a/tests/qemu-iotests/134.out b/tests/qemu-iotests/134.out index 09d46f6b1724e6921f5d5965657e5fb0a6256c11..4abc5b5f7da6540283248b242125acf2b6580254 100644 --- a/tests/qemu-iotests/134.out +++ b/tests/qemu-iotests/134.out @@ -1,5 +1,5 @@ QA output created by 134 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on == reading whole image == read 134217728/134217728 bytes at offset 0 diff --git a/tests/qemu-iotests/139 b/tests/qemu-iotests/139 index 7120d3142b7757a9ba609c5854c071a0698fb964..1452fd24b335ce045f5a7f48dc96eb9d50c66cd7 100755 --- a/tests/qemu-iotests/139 +++ b/tests/qemu-iotests/139 @@ -71,7 +71,7 @@ class TestBlockdevDel(iotests.QMPTestCase): def addBlockDriverStateOverlay(self, node): self.checkBlockDriverState(node, False) iotests.qemu_img('create', '-u', '-f', iotests.imgfmt, - '-b', base_img, new_img, '1M') + '-b', base_img, '-F', iotests.imgfmt, new_img, '1M') opts = {'driver': iotests.imgfmt, 'node-name': node, 'backing': None, diff --git a/tests/qemu-iotests/140 b/tests/qemu-iotests/140 index 8d2ce5d9e36fdb97936980464137655cbd913120..309b177e77f5b0ecae727620d66d699016a5adec 100755 --- a/tests/qemu-iotests/140 +++ b/tests/qemu-iotests/140 @@ -81,10 +81,17 @@ $QEMU_IO_PROG -f raw -r -c 'read -P 42 0 64k' \ "nbd+unix:///drv?socket=$SOCK_DIR/nbd" 2>&1 \ | _filter_qemu_io | _filter_nbd +# The order of 'return' and the BLOCK_EXPORT_DELETED event is undefined. Just +# wait until we've twice seen one of them. Filter the 'return' line out so that +# the output is defined. _send_qemu_cmd $QEMU_HANDLE \ "{ 'execute': 'eject', 'arguments': { 'device': 'drv' }}" \ - 'return' + 'return\|BLOCK_EXPORT_DELETED' | + grep -v 'return' + +_send_qemu_cmd $QEMU_HANDLE '' 'return\|BLOCK_EXPORT_DELETED' | + grep -v 'return' $QEMU_IO_PROG -f raw -r -c close \ "nbd+unix:///drv?socket=$SOCK_DIR/nbd" 2>&1 \ diff --git a/tests/qemu-iotests/140.out b/tests/qemu-iotests/140.out index 86b985da75bee19133d7fe4dc6f994f9dda8abc9..62d9c3ab3c7bd8de35c322207a5311829e175c69 100644 --- a/tests/qemu-iotests/140.out +++ b/tests/qemu-iotests/140.out @@ -11,7 +11,7 @@ wrote 65536/65536 bytes at offset 0 read 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { 'execute': 'eject', 'arguments': { 'device': 'drv' }} -{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "drv"}} qemu-io: can't open device nbd+unix:///drv?socket=SOCK_DIR/nbd: Requested export not available server reported: export 'drv' not present { 'execute': 'quit' } diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141 index 5192d256e31462f051c3203325a27eb53e5b88cb..21aa0b42d81333d96ac38ef1e59a3cff3834883d 100755 --- a/tests/qemu-iotests/141 +++ b/tests/qemu-iotests/141 @@ -89,8 +89,8 @@ test_blockjob() TEST_IMG="$TEST_DIR/b.$IMGFMT" _make_test_img 1M -TEST_IMG="$TEST_DIR/m.$IMGFMT" _make_test_img -b "$TEST_DIR/b.$IMGFMT" 1M -_make_test_img -b "$TEST_DIR/m.$IMGFMT" 1M +TEST_IMG="$TEST_DIR/m.$IMGFMT" _make_test_img -b "$TEST_DIR/b.$IMGFMT" -F $IMGFMT 1M +_make_test_img -b "$TEST_DIR/m.$IMGFMT" 1M -F $IMGFMT _launch_qemu -nodefaults diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out index 263b680bdfb3c5f5c3bc3e4009e4e295caba6b3d..08e0aecd65f4b335a76f18f0f617c9cc89fb59ee 100644 --- a/tests/qemu-iotests/141.out +++ b/tests/qemu-iotests/141.out @@ -1,7 +1,7 @@ QA output created by 141 Formatting 'TEST_DIR/b.IMGFMT', fmt=IMGFMT size=1048576 -Formatting 'TEST_DIR/m.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/b.IMGFMT -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.IMGFMT +Formatting 'TEST_DIR/m.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/b.IMGFMT backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.IMGFMT backing_fmt=IMGFMT {'execute': 'qmp_capabilities'} {"return": {}} diff --git a/tests/qemu-iotests/142 b/tests/qemu-iotests/142 index daefcbaa5878f6696a92586ed34915d0770e6c26..69fd10ef5103803159cf948cf955a851ba809fab 100755 --- a/tests/qemu-iotests/142 +++ b/tests/qemu-iotests/142 @@ -67,7 +67,7 @@ size=128M TEST_IMG="$TEST_IMG.base" _make_test_img $size TEST_IMG="$TEST_IMG.snap" _make_test_img $size -_make_test_img -b "$TEST_IMG.base" $size +_make_test_img -b "$TEST_IMG.base" $size -F $IMGFMT echo echo === Simple test for all cache modes === diff --git a/tests/qemu-iotests/142.out b/tests/qemu-iotests/142.out index 3667e38def8aa4881474e5263578650282b010a9..a92b948edd953069f465f53143bed170bc5f272d 100644 --- a/tests/qemu-iotests/142.out +++ b/tests/qemu-iotests/142.out @@ -1,7 +1,7 @@ QA output created by 142 Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 Formatting 'TEST_DIR/t.IMGFMT.snap', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT === Simple test for all cache modes === diff --git a/tests/qemu-iotests/143 b/tests/qemu-iotests/143 index f649b36195011e9b0f19e4b51a8d6bb3aafd565d..d2349903b1b5fa1b48ffc3e7a00dec91ab45abf1 100755 --- a/tests/qemu-iotests/143 +++ b/tests/qemu-iotests/143 @@ -58,6 +58,10 @@ _send_qemu_cmd $QEMU_HANDLE \ $QEMU_IO_PROG -f raw -c quit \ "nbd+unix:///no_such_export?socket=$SOCK_DIR/nbd" 2>&1 \ | _filter_qemu_io | _filter_nbd +# Likewise, with longest possible name permitted in NBD protocol +$QEMU_IO_PROG -f raw -c quit \ + "nbd+unix:///$(printf %4096d 1 | tr ' ' a)?socket=$SOCK_DIR/nbd" 2>&1 \ + | _filter_qemu_io | _filter_nbd | sed 's/aaaa*aa/aa--aa/' _send_qemu_cmd $QEMU_HANDLE \ "{ 'execute': 'quit' }" \ diff --git a/tests/qemu-iotests/143.out b/tests/qemu-iotests/143.out index 1f4001c6013137a13d90f64b4f861e81de341691..fc9c0a761fa107a5c800d27af843333b2050ab0b 100644 --- a/tests/qemu-iotests/143.out +++ b/tests/qemu-iotests/143.out @@ -5,6 +5,8 @@ QA output created by 143 {"return": {}} qemu-io: can't open device nbd+unix:///no_such_export?socket=SOCK_DIR/nbd: Requested export not available server reported: export 'no_such_export' not present +qemu-io: can't open device nbd+unix:///aa--aa1?socket=SOCK_DIR/nbd: Requested export not available +server reported: export 'aa--aa...' not present { 'execute': 'quit' } {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} diff --git a/tests/qemu-iotests/144.out b/tests/qemu-iotests/144.out index 885a8874a5dc7f548ed2074f52d62db16bdcae22..13e0c4f5a7dce51094fcbb77d0692446029b76fe 100644 --- a/tests/qemu-iotests/144.out +++ b/tests/qemu-iotests/144.out @@ -9,7 +9,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=536870912 { 'execute': 'qmp_capabilities' } {"return": {}} { 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp.IMGFMT', 'format': 'IMGFMT' } } -Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 {"return": {}} === Performing block-commit on active layer === @@ -31,6 +31,6 @@ Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/ === Performing Live Snapshot 2 === { 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp2.IMGFMT', 'format': 'IMGFMT' } } -Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 {"return": {}} *** done diff --git a/tests/qemu-iotests/146 b/tests/qemu-iotests/146 index 2e43abddfc5c97072f8f8fe2e897de13a1051ecf..ddc3c1fd8041c3750ce49f7594b1fb6ed3b17095 100755 --- a/tests/qemu-iotests/146 +++ b/tests/qemu-iotests/146 @@ -51,19 +51,25 @@ echo === Testing VPC Autodetect === echo _use_sample_img virtualpc-dynamic.vhd.bz2 -${QEMU_IO} -c "open -o driver=vpc ${TEST_IMG}" -c 'map' +$QEMU_IMG map --output=json --image-opts \ + "driver=vpc,file.filename=$TEST_IMG" \ + | _filter_qemu_img_map echo echo === Testing VPC with current_size force === echo -${QEMU_IO} -c "open -o driver=vpc,force_size_calc=current_size ${TEST_IMG}" -c 'map' +$QEMU_IMG map --output=json --image-opts \ + "driver=vpc,force_size_calc=current_size,file.filename=$TEST_IMG" \ + | _filter_qemu_img_map echo echo === Testing VPC with chs force === echo -${QEMU_IO} -c "open -o driver=vpc,force_size_calc=chs ${TEST_IMG}" -c 'map' +$QEMU_IMG map --output=json --image-opts \ + "driver=vpc,force_size_calc=chs,file.filename=$TEST_IMG" \ + | _filter_qemu_img_map _cleanup_test_img @@ -72,19 +78,25 @@ echo === Testing Hyper-V Autodetect === echo _use_sample_img hyperv2012r2-dynamic.vhd.bz2 -${QEMU_IO} -c "open -o driver=vpc ${TEST_IMG}" -c 'map' +$QEMU_IMG map --output=json --image-opts \ + "driver=vpc,file.filename=$TEST_IMG" \ + | _filter_qemu_img_map echo echo === Testing Hyper-V with current_size force === echo -${QEMU_IO} -c "open -o driver=vpc,force_size_calc=current_size ${TEST_IMG}" -c 'map' +$QEMU_IMG map --output=json --image-opts \ + "driver=vpc,force_size_calc=current_size,file.filename=$TEST_IMG" \ + | _filter_qemu_img_map echo echo === Testing Hyper-V with chs force === echo -${QEMU_IO} -c "open -o driver=vpc,force_size_calc=chs ${TEST_IMG}" -c 'map' +$QEMU_IMG map --output=json --image-opts \ + "driver=vpc,force_size_calc=chs,file.filename=$TEST_IMG" \ + | _filter_qemu_img_map _cleanup_test_img @@ -93,19 +105,25 @@ echo === Testing d2v Autodetect === echo _use_sample_img d2v-zerofilled.vhd.bz2 -${QEMU_IO} -c "open -o driver=vpc ${TEST_IMG}" -c 'map' +$QEMU_IMG map --output=json --image-opts \ + "driver=vpc,file.filename=$TEST_IMG" \ + | _filter_qemu_img_map echo echo === Testing d2v with current_size force === echo -${QEMU_IO} -c "open -o driver=vpc,force_size_calc=current_size ${TEST_IMG}" -c 'map' +$QEMU_IMG map --output=json --image-opts \ + "driver=vpc,force_size_calc=current_size,file.filename=$TEST_IMG" \ + | _filter_qemu_img_map echo echo === Testing d2v with chs force === echo -${QEMU_IO} -c "open -o driver=vpc,force_size_calc=chs ${TEST_IMG}" -c 'map' +$QEMU_IMG map --output=json --image-opts \ + "driver=vpc,force_size_calc=chs,file.filename=$TEST_IMG" \ + | _filter_qemu_img_map _cleanup_test_img @@ -121,19 +139,25 @@ echo echo === Read created image, default opts ==== echo -${QEMU_IO} -c "open -o driver=vpc ${TEST_IMG}" -c 'map' +$QEMU_IMG map --output=json --image-opts \ + "driver=vpc,file.filename=$TEST_IMG" \ + | _filter_qemu_img_map echo echo === Read created image, force_size_calc=chs ==== echo -${QEMU_IO} -c "open -o driver=vpc,force_size_calc=chs ${TEST_IMG}" -c 'map' +$QEMU_IMG map --output=json --image-opts \ + "driver=vpc,force_size_calc=chs,file.filename=$TEST_IMG" \ + | _filter_qemu_img_map echo echo === Read created image, force_size_calc=current_size ==== echo -${QEMU_IO} -c "open -o driver=vpc,force_size_calc=current_size ${TEST_IMG}" -c 'map' +$QEMU_IMG map --output=json --image-opts \ + "driver=vpc,force_size_calc=current_size,file.filename=$TEST_IMG" \ + | _filter_qemu_img_map echo echo === Testing Image create, force_size === @@ -145,19 +169,25 @@ echo echo === Read created image, default opts ==== echo -${QEMU_IO} -c "open -o driver=vpc ${TEST_IMG}" -c 'map' +$QEMU_IMG map --output=json --image-opts \ + "driver=vpc,file.filename=$TEST_IMG" \ + | _filter_qemu_img_map echo echo === Read created image, force_size_calc=chs ==== echo -${QEMU_IO} -c "open -o driver=vpc,force_size_calc=chs ${TEST_IMG}" -c 'map' +$QEMU_IMG map --output=json --image-opts \ + "driver=vpc,force_size_calc=chs,file.filename=$TEST_IMG" \ + | _filter_qemu_img_map echo echo === Read created image, force_size_calc=current_size ==== echo -${QEMU_IO} -c "open -o driver=vpc,force_size_calc=current_size ${TEST_IMG}" -c 'map' +$QEMU_IMG map --output=json --image-opts \ + "driver=vpc,force_size_calc=current_size,file.filename=$TEST_IMG" \ + | _filter_qemu_img_map echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/146.out b/tests/qemu-iotests/146.out index 1332189d878ebc40117f0734cfe896ce79014e4e..80513cdd0683a3b80183e748886e608a864ff25f 100644 --- a/tests/qemu-iotests/146.out +++ b/tests/qemu-iotests/146.out @@ -2,39 +2,414 @@ QA output created by 146 === Testing VPC Autodetect === -126.998 GiB (0x1fbfe04000) bytes not allocated at offset 0 bytes (0x0) +[{ "start": 0, "length": 136363130880, "depth": 0, "zero": true, "data": false }] === Testing VPC with current_size force === -127 GiB (0x1fc0000000) bytes not allocated at offset 0 bytes (0x0) +[{ "start": 0, "length": 136365211648, "depth": 0, "zero": true, "data": false }] === Testing VPC with chs force === -126.998 GiB (0x1fbfe04000) bytes not allocated at offset 0 bytes (0x0) +[{ "start": 0, "length": 136363130880, "depth": 0, "zero": true, "data": false }] === Testing Hyper-V Autodetect === -127 GiB (0x1fc0000000) bytes not allocated at offset 0 bytes (0x0) +[{ "start": 0, "length": 136365211648, "depth": 0, "zero": true, "data": false }] === Testing Hyper-V with current_size force === -127 GiB (0x1fc0000000) bytes not allocated at offset 0 bytes (0x0) +[{ "start": 0, "length": 136365211648, "depth": 0, "zero": true, "data": false }] === Testing Hyper-V with chs force === -126.998 GiB (0x1fbfe04000) bytes not allocated at offset 0 bytes (0x0) +[{ "start": 0, "length": 136363130880, "depth": 0, "zero": true, "data": false }] === Testing d2v Autodetect === -251.250 MiB (0xfb40000) bytes allocated at offset 0 bytes (0x0) +[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 4194304, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 6291456, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 8388608, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 10485760, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 12582912, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 14680064, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 16777216, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 18874368, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 20971520, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 23068672, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 25165824, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 27262976, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 29360128, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 31457280, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 33554432, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 35651584, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 37748736, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 39845888, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 41943040, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 44040192, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 46137344, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 48234496, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 50331648, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 52428800, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 54525952, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 56623104, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 58720256, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 60817408, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 62914560, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 65011712, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 67108864, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 69206016, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 71303168, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 73400320, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 75497472, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 77594624, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 79691776, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 81788928, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 83886080, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 85983232, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 88080384, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 90177536, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 92274688, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 94371840, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 96468992, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 98566144, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 100663296, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 102760448, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 104857600, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 106954752, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 109051904, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 111149056, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 113246208, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 115343360, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 117440512, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 119537664, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 121634816, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 123731968, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 125829120, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 127926272, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 130023424, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 132120576, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 134217728, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 136314880, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 138412032, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 140509184, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 142606336, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 144703488, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 146800640, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 148897792, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 150994944, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 153092096, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 155189248, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 157286400, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 159383552, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 161480704, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 163577856, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 165675008, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 167772160, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 169869312, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 171966464, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 174063616, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 176160768, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 178257920, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 180355072, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 182452224, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 184549376, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 186646528, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 188743680, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 190840832, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 192937984, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 195035136, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 197132288, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 199229440, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 201326592, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 203423744, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 205520896, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 207618048, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 209715200, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 211812352, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 213909504, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 216006656, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 218103808, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 220200960, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 222298112, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 224395264, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 226492416, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 228589568, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 230686720, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 232783872, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 234881024, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 236978176, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 239075328, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 241172480, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 243269632, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 245366784, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 247463936, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 249561088, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 251658240, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 253755392, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 255852544, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 257949696, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 260046848, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 262144000, "length": 1310720, "depth": 0, "zero": false, "data": true, "offset": OFFSET }] === Testing d2v with current_size force === -251.250 MiB (0xfb40000) bytes allocated at offset 0 bytes (0x0) +[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 4194304, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 6291456, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 8388608, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 10485760, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 12582912, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 14680064, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 16777216, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 18874368, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 20971520, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 23068672, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 25165824, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 27262976, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 29360128, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 31457280, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 33554432, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 35651584, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 37748736, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 39845888, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 41943040, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 44040192, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 46137344, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 48234496, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 50331648, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 52428800, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 54525952, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 56623104, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 58720256, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 60817408, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 62914560, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 65011712, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 67108864, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 69206016, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 71303168, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 73400320, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 75497472, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 77594624, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 79691776, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 81788928, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 83886080, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 85983232, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 88080384, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 90177536, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 92274688, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 94371840, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 96468992, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 98566144, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 100663296, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 102760448, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 104857600, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 106954752, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 109051904, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 111149056, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 113246208, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 115343360, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 117440512, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 119537664, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 121634816, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 123731968, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 125829120, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 127926272, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 130023424, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 132120576, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 134217728, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 136314880, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 138412032, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 140509184, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 142606336, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 144703488, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 146800640, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 148897792, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 150994944, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 153092096, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 155189248, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 157286400, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 159383552, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 161480704, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 163577856, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 165675008, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 167772160, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 169869312, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 171966464, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 174063616, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 176160768, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 178257920, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 180355072, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 182452224, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 184549376, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 186646528, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 188743680, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 190840832, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 192937984, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 195035136, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 197132288, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 199229440, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 201326592, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 203423744, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 205520896, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 207618048, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 209715200, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 211812352, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 213909504, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 216006656, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 218103808, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 220200960, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 222298112, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 224395264, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 226492416, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 228589568, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 230686720, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 232783872, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 234881024, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 236978176, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 239075328, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 241172480, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 243269632, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 245366784, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 247463936, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 249561088, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 251658240, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 253755392, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 255852544, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 257949696, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 260046848, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 262144000, "length": 1310720, "depth": 0, "zero": false, "data": true, "offset": OFFSET }] === Testing d2v with chs force === -251.250 MiB (0xfb40000) bytes allocated at offset 0 bytes (0x0) +[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 4194304, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 6291456, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 8388608, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 10485760, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 12582912, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 14680064, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 16777216, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 18874368, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 20971520, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 23068672, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 25165824, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 27262976, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 29360128, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 31457280, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 33554432, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 35651584, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 37748736, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 39845888, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 41943040, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 44040192, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 46137344, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 48234496, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 50331648, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 52428800, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 54525952, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 56623104, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 58720256, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 60817408, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 62914560, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 65011712, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 67108864, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 69206016, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 71303168, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 73400320, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 75497472, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 77594624, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 79691776, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 81788928, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 83886080, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 85983232, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 88080384, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 90177536, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 92274688, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 94371840, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 96468992, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 98566144, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 100663296, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 102760448, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 104857600, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 106954752, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 109051904, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 111149056, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 113246208, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 115343360, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 117440512, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 119537664, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 121634816, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 123731968, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 125829120, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 127926272, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 130023424, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 132120576, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 134217728, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 136314880, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 138412032, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 140509184, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 142606336, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 144703488, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 146800640, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 148897792, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 150994944, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 153092096, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 155189248, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 157286400, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 159383552, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 161480704, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 163577856, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 165675008, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 167772160, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 169869312, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 171966464, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 174063616, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 176160768, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 178257920, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 180355072, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 182452224, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 184549376, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 186646528, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 188743680, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 190840832, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 192937984, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 195035136, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 197132288, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 199229440, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 201326592, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 203423744, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 205520896, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 207618048, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 209715200, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 211812352, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 213909504, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 216006656, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 218103808, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 220200960, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 222298112, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 224395264, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 226492416, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 228589568, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 230686720, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 232783872, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 234881024, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 236978176, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 239075328, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 241172480, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 243269632, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 245366784, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 247463936, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 249561088, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 251658240, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 253755392, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 255852544, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 257949696, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 260046848, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET }, +{ "start": 262144000, "length": 1310720, "depth": 0, "zero": false, "data": true, "offset": OFFSET }] === Testing Image create, default === @@ -42,15 +417,15 @@ Formatting 'TEST_DIR/IMGFMT-create-test.IMGFMT', fmt=IMGFMT size=4294967296 === Read created image, default opts ==== -4 GiB (0x10007a000) bytes not allocated at offset 0 bytes (0x0) +[{ "start": 0, "length": 4295467008, "depth": 0, "zero": true, "data": false }] === Read created image, force_size_calc=chs ==== -4 GiB (0x10007a000) bytes not allocated at offset 0 bytes (0x0) +[{ "start": 0, "length": 4295467008, "depth": 0, "zero": true, "data": false }] === Read created image, force_size_calc=current_size ==== -4 GiB (0x10007a000) bytes not allocated at offset 0 bytes (0x0) +[{ "start": 0, "length": 4295467008, "depth": 0, "zero": true, "data": false }] === Testing Image create, force_size === @@ -58,13 +433,13 @@ Formatting 'TEST_DIR/IMGFMT-create-test.IMGFMT', fmt=IMGFMT size=4294967296 === Read created image, default opts ==== -4 GiB (0x100000000) bytes not allocated at offset 0 bytes (0x0) +[{ "start": 0, "length": 4294967296, "depth": 0, "zero": true, "data": false }] === Read created image, force_size_calc=chs ==== -4 GiB (0x100000000) bytes not allocated at offset 0 bytes (0x0) +[{ "start": 0, "length": 4294967296, "depth": 0, "zero": true, "data": false }] === Read created image, force_size_calc=current_size ==== -4 GiB (0x100000000) bytes not allocated at offset 0 bytes (0x0) +[{ "start": 0, "length": 4294967296, "depth": 0, "zero": true, "data": false }] *** done diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153 index cf961d3609ebeb5b4d768f393dfc02247ec5b280..34045ea3cfeb5e30acac17ae8a1038bdfb0577b6 100755 --- a/tests/qemu-iotests/153 +++ b/tests/qemu-iotests/153 @@ -94,7 +94,7 @@ for opts1 in "" "read-only=on" "read-only=on,force-share=on"; do echo echo "== Creating test image ==" - _make_test_img -b "${TEST_IMG}.base" + _make_test_img -b "${TEST_IMG}.base" -F $IMGFMT echo echo "== Launching QEMU, opts: '$opts1' ==" @@ -125,7 +125,7 @@ for opts1 in "" "read-only=on" "read-only=on,force-share=on"; do _run_cmd $QEMU_IMG amend -o "size=$size" $L "${TEST_IMG}" _run_cmd $QEMU_IMG commit $L "${TEST_IMG}" _run_cmd $QEMU_IMG resize $L "${TEST_IMG}" $size - _run_cmd $QEMU_IMG rebase $L "${TEST_IMG}" -b "${TEST_IMG}.base" + _run_cmd $QEMU_IMG rebase $L "${TEST_IMG}" -b "${TEST_IMG}.base" -F $IMGFMT _run_cmd $QEMU_IMG snapshot -l $L "${TEST_IMG}" _run_cmd $QEMU_IMG convert $L "${TEST_IMG}" "${TEST_IMG}.convert" _run_cmd $QEMU_IMG dd $L if="${TEST_IMG}" of="${TEST_IMG}.convert" bs=512 count=1 @@ -135,7 +135,7 @@ for opts1 in "" "read-only=on" "read-only=on,force-share=on"; do # qemu-img create does not support -U if [ -z "$L" ]; then _run_cmd $QEMU_IMG create -f $IMGFMT "${TEST_IMG}" \ - -b ${TEST_IMG}.base + -b ${TEST_IMG}.base -F $IMGFMT # Read the file format. It used to be the case that # file-posix simply truncated the file, but the qcow2 # driver then failed to format it because it was unable @@ -167,11 +167,10 @@ done echo echo "== Creating ${TEST_IMG}.[abc] ==" | _filter_testdir -( - $QEMU_IMG create -f qcow2 "${TEST_IMG}.a" -b "${TEST_IMG}" - $QEMU_IMG create -f qcow2 "${TEST_IMG}.b" -b "${TEST_IMG}" - $QEMU_IMG create -f qcow2 "${TEST_IMG}.c" -b "${TEST_IMG}.b" -) | _filter_img_create +$QEMU_IMG create -f qcow2 "${TEST_IMG}.a" -b "${TEST_IMG}" -F $IMGFMT | _filter_img_create +$QEMU_IMG create -f qcow2 "${TEST_IMG}.b" -b "${TEST_IMG}" -F $IMGFMT | _filter_img_create +$QEMU_IMG create -f qcow2 "${TEST_IMG}.c" -b "${TEST_IMG}.b" -F $IMGFMT \ + | _filter_img_create echo echo "== Two devices sharing the same file in backing chain ==" @@ -219,7 +218,7 @@ _send_qemu_cmd $QEMU_HANDLE \ _run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512' echo "Creating overlay with qemu-img when the guest is running should be allowed" -_run_cmd $QEMU_IMG create -f $IMGFMT -b "${TEST_IMG}" "${TEST_IMG}.overlay" +_run_cmd $QEMU_IMG create -f $IMGFMT -b "${TEST_IMG}" -F $IMGFMT "${TEST_IMG}.overlay" echo "== Closing an image should unlock it ==" _send_qemu_cmd $QEMU_HANDLE \ diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out index b2a90caa6b8e1613cee9c1723cc81f82ff87c992..fcaa71aeeebd855d684d8056410f6407130fefc2 100644 --- a/tests/qemu-iotests/153.out +++ b/tests/qemu-iotests/153.out @@ -6,7 +6,7 @@ QEMU_PROG: -drive if=none,file=null-co://,readonly=off,force-share=on: force-sha Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=33554432 == Creating test image == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT == Launching QEMU, opts: '' == @@ -68,7 +68,7 @@ _qemu_img_wrapper resize TEST_DIR/t.qcow2 32M qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock Is another process using the image [TEST_DIR/t.qcow2]? -_qemu_img_wrapper rebase TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base +_qemu_img_wrapper rebase TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base -F qcow2 qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock Is another process using the image [TEST_DIR/t.qcow2]? @@ -92,10 +92,11 @@ _qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2 qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock Is another process using the image [TEST_DIR/t.qcow2]? -_qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base +_qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base -F qcow2 qemu-img: TEST_DIR/t.qcow2: Failed to get "write" lock Is another process using the image [TEST_DIR/t.qcow2]? file format: IMGFMT +backing file format: IMGFMT == Running utility commands -U == @@ -130,7 +131,7 @@ _qemu_img_wrapper resize -U TEST_DIR/t.qcow2 32M qemu-img: unrecognized option '-U' Try 'qemu-img --help' for more information -_qemu_img_wrapper rebase -U TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base +_qemu_img_wrapper rebase -U TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base -F qcow2 qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock Is another process using the image [TEST_DIR/t.qcow2]? @@ -152,7 +153,7 @@ Round done Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=33554432 == Creating test image == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT == Launching QEMU, opts: 'read-only=on' == @@ -199,7 +200,7 @@ _qemu_img_wrapper resize TEST_DIR/t.qcow2 32M qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock Is another process using the image [TEST_DIR/t.qcow2]? -_qemu_img_wrapper rebase TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base +_qemu_img_wrapper rebase TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base -F qcow2 qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock Is another process using the image [TEST_DIR/t.qcow2]? @@ -215,10 +216,11 @@ _qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2 qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock Is another process using the image [TEST_DIR/t.qcow2]? -_qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base +_qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base -F qcow2 qemu-img: TEST_DIR/t.qcow2: Failed to get "write" lock Is another process using the image [TEST_DIR/t.qcow2]? file format: IMGFMT +backing file format: IMGFMT == Running utility commands -U == @@ -253,7 +255,7 @@ _qemu_img_wrapper resize -U TEST_DIR/t.qcow2 32M qemu-img: unrecognized option '-U' Try 'qemu-img --help' for more information -_qemu_img_wrapper rebase -U TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base +_qemu_img_wrapper rebase -U TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base -F qcow2 qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock Is another process using the image [TEST_DIR/t.qcow2]? @@ -275,7 +277,7 @@ Round done Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=33554432 == Creating test image == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT == Launching QEMU, opts: 'read-only=on,force-share=on' == @@ -309,7 +311,7 @@ _qemu_img_wrapper commit TEST_DIR/t.qcow2 _qemu_img_wrapper resize TEST_DIR/t.qcow2 32M -_qemu_img_wrapper rebase TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base +_qemu_img_wrapper rebase TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base -F qcow2 _qemu_img_wrapper snapshot -l TEST_DIR/t.qcow2 @@ -321,8 +323,9 @@ _qemu_img_wrapper bench -c 1 TEST_DIR/t.qcow2 _qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2 -_qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base +_qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base -F qcow2 file format: IMGFMT +backing file format: IMGFMT == Running utility commands -U == @@ -357,7 +360,7 @@ _qemu_img_wrapper resize -U TEST_DIR/t.qcow2 32M qemu-img: unrecognized option '-U' Try 'qemu-img --help' for more information -_qemu_img_wrapper rebase -U TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base +_qemu_img_wrapper rebase -U TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base -F qcow2 _qemu_img_wrapper snapshot -l -U TEST_DIR/t.qcow2 @@ -398,9 +401,9 @@ Is another process using the image [TEST_DIR/t.qcow2]? == Two devices with the same image (read-only=on,force-share=on - read-only=on,force-share=on) == == Creating TEST_DIR/t.qcow2.[abc] == -Formatting 'TEST_DIR/t.IMGFMT.a', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT -Formatting 'TEST_DIR/t.IMGFMT.b', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT -Formatting 'TEST_DIR/t.IMGFMT.c', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.b +Formatting 'TEST_DIR/t.IMGFMT.a', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT.b', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT.c', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.b backing_fmt=IMGFMT == Two devices sharing the same file in backing chain == @@ -430,7 +433,7 @@ qemu-io: can't open device TEST_DIR/t.qcow2: Failed to get "write" lock Is another process using the image [TEST_DIR/t.qcow2]? Creating overlay with qemu-img when the guest is running should be allowed -_qemu_img_wrapper create -f qcow2 -b TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.overlay +_qemu_img_wrapper create -f qcow2 -b TEST_DIR/t.qcow2 -F qcow2 TEST_DIR/t.qcow2.overlay == Closing an image should unlock it == { 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'drive_del d0' } } {"return": ""} @@ -461,7 +464,7 @@ No conflict: image: null-co:// file format: null-co virtual size: 1 GiB (1073741824 bytes) -disk size: unavailable +disk size: 0 B Conflict: qemu-img: --force-share/-U conflicts with image options diff --git a/tests/qemu-iotests/154 b/tests/qemu-iotests/154 index d68f66b9e05867df4c2fe91e356a760881ecafe1..7f1c0d9bd98109cb3fd0c28b6a6ca2b0b821cc6f 100755 --- a/tests/qemu-iotests/154 +++ b/tests/qemu-iotests/154 @@ -50,7 +50,7 @@ echo echo == backing file contains zeros == CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size -_make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT # Make sure that the whole cluster is allocated even for partial write_zeroes # when the backing file contains zeros @@ -74,7 +74,7 @@ echo echo == backing file contains non-zero data before write_zeroes == CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size -_make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT # Single cluster; non-zero data at the cluster start # ... | XX -- 00 -- | ... @@ -97,7 +97,7 @@ echo echo == backing file contains non-zero data after write_zeroes == CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size -_make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT # Single cluster; non-zero data directly after request # ... | -- 00 XX -- | ... @@ -120,7 +120,7 @@ echo echo == write_zeroes covers non-zero data == CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size -_make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT # non-zero data at front of request # Backing file: -- XX -- -- @@ -160,7 +160,7 @@ echo echo == spanning two clusters, non-zero before request == CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size -_make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT # Two clusters; non-zero data before request: # 1. At cluster start: 32k: XX -- -- 00 | 00 -- -- -- @@ -190,7 +190,7 @@ echo echo == spanning two clusters, non-zero after request == CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size -_make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT # Two clusters; non-zero data after request: # 1. Directly after request: 32k: -- -- -- 00 | 00 XX -- -- @@ -220,7 +220,7 @@ echo echo == spanning two clusters, partially overwriting backing file == CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size -_make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT # Backing file: -- -- XX XX | XX XX -- -- # Active layer: -- -- XX 00 | 00 XX -- -- @@ -239,7 +239,7 @@ echo echo == spanning multiple clusters, non-zero in first cluster == CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size -_make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT # Backing file: 64k: XX XX -- -- | -- -- -- -- | -- -- -- -- # Active layer: 64k: XX XX 00 00 | 00 00 00 00 | 00 -- -- -- @@ -255,7 +255,7 @@ echo echo == spanning multiple clusters, non-zero in intermediate cluster == CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size -_make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT # Backing file: 64k: -- -- -- -- | -- XX XX -- | -- -- -- -- # Active layer: 64k: -- -- 00 00 | 00 00 00 00 | 00 -- -- -- @@ -270,7 +270,7 @@ echo echo == spanning multiple clusters, non-zero in final cluster == CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size -_make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT # Backing file: 64k: -- -- -- -- | -- -- -- -- | -- -- XX XX # Active layer: 64k: -- -- 00 00 | 00 00 00 00 | 00 -- XX XX @@ -286,7 +286,7 @@ echo echo == spanning multiple clusters, partially overwriting backing file == CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size -_make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT # Backing file: 64k: -- XX XX XX | XX XX XX XX | XX XX XX -- # Active layer: 64k: -- XX 00 00 | 00 00 00 00 | 00 XX XX -- @@ -338,7 +338,7 @@ CLUSTER_SIZE=2048 TEST_IMG="$TEST_IMG.base" _make_test_img $((size + 1024)) # Write at the front: sector-wise, the request is: # backing: 128m... | -- -- # active: 128m... | 00 -- -- -- -_make_test_img -b "$TEST_IMG.base" $((size + 2048)) +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $((size + 2048)) $QEMU_IO -c "write -z $size 512" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map @@ -346,7 +346,7 @@ $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map # Write at the back: sector-wise, the request is: # backing: 128m... | -- -- # active: 128m... | -- -- -- 00 -_make_test_img -b "$TEST_IMG.base" $((size + 2048)) +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $((size + 2048)) $QEMU_IO -c "write -z $((size + 1536)) 512" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map @@ -354,7 +354,7 @@ $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map # Write at middle: sector-wise, the request is: # backing: 128m... | -- -- # active: 128m... | -- 00 00 -- -_make_test_img -b "$TEST_IMG.base" $((size + 2048)) +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $((size + 2048)) $QEMU_IO -c "write -z $((size + 512)) 1024" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map @@ -362,7 +362,7 @@ $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map # Write entire cluster: sector-wise, the request is: # backing: 128m... | -- -- # active: 128m... | 00 00 00 00 -_make_test_img -b "$TEST_IMG.base" $((size + 2048)) +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $((size + 2048)) $QEMU_IO -c "write -z $size 2048" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map @@ -373,7 +373,7 @@ $QEMU_IO -c "write -z $size 512" "$TEST_IMG.base" | _filter_qemu_io # Write at the front: sector-wise, the request is: # backing: 128m... | 00 00 # active: 128m... | 00 -- -- -- -_make_test_img -b "$TEST_IMG.base" $((size + 2048)) +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $((size + 2048)) $QEMU_IO -c "write -z $size 512" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map @@ -381,7 +381,7 @@ $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map # Write at the back: sector-wise, the request is: # backing: 128m... | 00 00 # active: 128m... | -- -- -- 00 -_make_test_img -b "$TEST_IMG.base" $((size + 2048)) +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $((size + 2048)) $QEMU_IO -c "write -z $((size + 1536)) 512" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map @@ -389,7 +389,7 @@ $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map # Write at middle: sector-wise, the request is: # backing: 128m... | 00 00 # active: 128m... | -- 00 00 -- -_make_test_img -b "$TEST_IMG.base" $((size + 2048)) +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $((size + 2048)) $QEMU_IO -c "write -z $((size + 512)) 1024" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map @@ -397,7 +397,7 @@ $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map # Write entire cluster: sector-wise, the request is: # backing: 128m... | 00 00 # active: 128m... | 00 00 00 00 -_make_test_img -b "$TEST_IMG.base" $((size + 2048)) +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $((size + 2048)) $QEMU_IO -c "write -z $size 2048" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map @@ -427,7 +427,7 @@ echo == unaligned image tail cluster, allocation required == # Backing file: 128m... | XX -- # Active layer: 128m... | -- -- 00 -- CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $((size + 1024)) -_make_test_img -b "$TEST_IMG.base" $((size + 2048)) +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $((size + 2048)) $QEMU_IO -c "write -P 1 $((size)) 512" "$TEST_IMG.base" | _filter_qemu_io $QEMU_IO -c "write -z $((size + 1024)) 512" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "read -P 1 $((size)) 512" "$TEST_IMG" | _filter_qemu_io @@ -438,7 +438,7 @@ $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map # Backing file: 128m: ... | -- XX # Active layer: 128m: ... | 00 -- -- 00 CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $((size + 1024)) -_make_test_img -b "$TEST_IMG.base" $((size + 2048)) +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $((size + 2048)) $QEMU_IO -c "write -P 1 $((size + 512)) 512" "$TEST_IMG.base" | _filter_qemu_io $QEMU_IO -c "write -z $((size)) 512" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "read -P 0 $((size)) 512" "$TEST_IMG" | _filter_qemu_io diff --git a/tests/qemu-iotests/154.out b/tests/qemu-iotests/154.out index fa3673317fd8bdc18761526d8686380eaad37acd..4863e24838649b89f5447f18aa58874fdaf4f597 100644 --- a/tests/qemu-iotests/154.out +++ b/tests/qemu-iotests/154.out @@ -2,7 +2,7 @@ QA output created by 154 == backing file contains zeros == Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 2048/2048 bytes at offset 0 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 2048/2048 bytes at offset 10240 @@ -22,7 +22,7 @@ wrote 2048/2048 bytes at offset 27648 == backing file contains non-zero data before write_zeroes == Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 1024/1024 bytes at offset 32768 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 1024/1024 bytes at offset 34816 @@ -49,7 +49,7 @@ read 2048/2048 bytes at offset 67584 == backing file contains non-zero data after write_zeroes == Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 1024/1024 bytes at offset 34816 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 1024/1024 bytes at offset 33792 @@ -76,7 +76,7 @@ read 3072/3072 bytes at offset 40960 == write_zeroes covers non-zero data == Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 1024/1024 bytes at offset 5120 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 2048/2048 bytes at offset 5120 @@ -113,7 +113,7 @@ read 4096/4096 bytes at offset 28672 == spanning two clusters, non-zero before request == Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 1024/1024 bytes at offset 32768 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 2048/2048 bytes at offset 35840 @@ -155,7 +155,7 @@ read 5120/5120 bytes at offset 68608 == spanning two clusters, non-zero after request == Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 1024/1024 bytes at offset 37888 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 2048/2048 bytes at offset 35840 @@ -197,7 +197,7 @@ read 1024/1024 bytes at offset 72704 == spanning two clusters, partially overwriting backing file == Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 4096/4096 bytes at offset 2048 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 2048/2048 bytes at offset 3072 @@ -217,7 +217,7 @@ read 2048/2048 bytes at offset 6144 == spanning multiple clusters, non-zero in first cluster == Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 2048/2048 bytes at offset 65536 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 7168/7168 bytes at offset 67584 @@ -233,7 +233,7 @@ read 10240/10240 bytes at offset 67584 == spanning multiple clusters, non-zero in intermediate cluster == Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 2048/2048 bytes at offset 70656 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 7168/7168 bytes at offset 67584 @@ -246,7 +246,7 @@ read 12288/12288 bytes at offset 65536 == spanning multiple clusters, non-zero in final cluster == Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 2048/2048 bytes at offset 75776 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 7168/7168 bytes at offset 67584 @@ -262,7 +262,7 @@ read 2048/2048 bytes at offset 75776 == spanning multiple clusters, partially overwriting backing file == Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 10240/10240 bytes at offset 66560 10 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 7168/7168 bytes at offset 67584 @@ -305,25 +305,25 @@ wrote 2048/2048 bytes at offset 134217728 2048/2048 bytes allocated at offset 128 MiB [{ "start": 0, "length": 134219776, "depth": 0, "zero": true, "data": false}] Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134218752 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 512/512 bytes at offset 134217728 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 2048/2048 bytes allocated at offset 128 MiB [{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false}, { "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}] -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 512/512 bytes at offset 134219264 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 2048/2048 bytes allocated at offset 128 MiB [{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false}, { "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}] -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 1024/1024 bytes at offset 134218240 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 2048/2048 bytes allocated at offset 128 MiB [{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false}, { "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}] -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 2048/2048 bytes at offset 134217728 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 2048/2048 bytes allocated at offset 128 MiB @@ -331,25 +331,25 @@ wrote 2048/2048 bytes at offset 134217728 { "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}] wrote 512/512 bytes at offset 134217728 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 512/512 bytes at offset 134217728 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 2048/2048 bytes allocated at offset 128 MiB [{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false}, { "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}] -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 512/512 bytes at offset 134219264 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 2048/2048 bytes allocated at offset 128 MiB [{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false}, { "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}] -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 1024/1024 bytes at offset 134218240 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 2048/2048 bytes allocated at offset 128 MiB [{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false}, { "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}] -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 2048/2048 bytes at offset 134217728 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 2048/2048 bytes allocated at offset 128 MiB @@ -377,7 +377,7 @@ read 1024/1024 bytes at offset 134217728 == unaligned image tail cluster, allocation required == Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134218752 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 512/512 bytes at offset 134217728 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 512/512 bytes at offset 134218752 @@ -389,7 +389,7 @@ read 1536/1536 bytes at offset 134218240 [{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false}, { "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134218752 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 512/512 bytes at offset 134218240 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 512/512 bytes at offset 134217728 diff --git a/tests/qemu-iotests/155 b/tests/qemu-iotests/155 index cb371d464943101d286d9e465cd07e068413ee3b..988f9861447c2ff8feb9d92f5b25044b466bb9f3 100755 --- a/tests/qemu-iotests/155 +++ b/tests/qemu-iotests/155 @@ -60,9 +60,12 @@ class BaseClass(iotests.QMPTestCase): def setUp(self): qemu_img('create', '-f', iotests.imgfmt, back0_img, '1440K') - qemu_img('create', '-f', iotests.imgfmt, '-b', back0_img, back1_img) - qemu_img('create', '-f', iotests.imgfmt, '-b', back1_img, back2_img) - qemu_img('create', '-f', iotests.imgfmt, '-b', back2_img, source_img) + qemu_img('create', '-f', iotests.imgfmt, '-b', back0_img, + '-F', iotests.imgfmt, back1_img) + qemu_img('create', '-f', iotests.imgfmt, '-b', back1_img, + '-F', iotests.imgfmt, back2_img) + qemu_img('create', '-f', iotests.imgfmt, '-b', back2_img, + '-F', iotests.imgfmt, source_img) self.vm = iotests.VM() # Add the BDS via blockdev-add so it stays around after the mirror block @@ -89,7 +92,8 @@ class BaseClass(iotests.QMPTestCase): if self.existing: if self.target_backing: qemu_img('create', '-f', iotests.imgfmt, - '-b', self.target_backing, target_img, '1440K') + '-b', self.target_backing, '-F', 'raw', + target_img, '1440K') else: qemu_img('create', '-f', iotests.imgfmt, target_img, '1440K') diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156 index 5559df63a53ef470101a3e885eae7ab5d5eae62c..9c7878dd2dd30e8226c78125c72cefc43bce3f51 100755 --- a/tests/qemu-iotests/156 +++ b/tests/qemu-iotests/156 @@ -50,13 +50,12 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 qed _supported_proto generic -_unsupported_proto vxhs # Copying files around with cp does not work with external data files _unsupported_imgopts data_file # Create source disk TEST_IMG="$TEST_IMG.backing" _make_test_img 1M -_make_test_img -b "$TEST_IMG.backing" 1M +_make_test_img -b "$TEST_IMG.backing" -F $IMGFMT 1M $QEMU_IO -c 'write -P 1 0 256k' "$TEST_IMG.backing" | _filter_qemu_io $QEMU_IO -c 'write -P 2 64k 192k' "$TEST_IMG" | _filter_qemu_io @@ -68,7 +67,7 @@ _send_qemu_cmd $QEMU_HANDLE \ 'return' # Create snapshot -TEST_IMG="$TEST_IMG.overlay" _make_test_img -u -b "$TEST_IMG" 1M +TEST_IMG="$TEST_IMG.overlay" _make_test_img -u -b "$TEST_IMG" -F $IMGFMT 1M _send_qemu_cmd $QEMU_HANDLE \ "{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'source', @@ -85,7 +84,8 @@ _send_qemu_cmd $QEMU_HANDLE \ 'return' # Create target image -TEST_IMG="$TEST_IMG.target.overlay" _make_test_img -u -b "$TEST_IMG.target" 1M +TEST_IMG="$TEST_IMG.target.overlay" _make_test_img -u -b "$TEST_IMG.target" \ + -F $IMGFMT 1M # Mirror snapshot _send_qemu_cmd $QEMU_HANDLE \ @@ -111,7 +111,7 @@ _send_qemu_cmd $QEMU_HANDLE \ # Copy source backing chain to the target before completing the job cp "$TEST_IMG.backing" "$TEST_IMG.target.backing" cp "$TEST_IMG" "$TEST_IMG.target" -$QEMU_IMG rebase -u -b "$TEST_IMG.target.backing" "$TEST_IMG.target" +$QEMU_IMG rebase -u -b "$TEST_IMG.target.backing" -F $IMGFMT "$TEST_IMG.target" # Complete block job _send_qemu_cmd $QEMU_HANDLE \ diff --git a/tests/qemu-iotests/156.out b/tests/qemu-iotests/156.out index 084be5ad71510c36e11c038b8eb2c908086b68eb..cce167b63fe336e1632d9ce15f3ca8612067ce01 100644 --- a/tests/qemu-iotests/156.out +++ b/tests/qemu-iotests/156.out @@ -1,20 +1,20 @@ QA output created by 156 Formatting 'TEST_DIR/t.IMGFMT.backing', fmt=IMGFMT size=1048576 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.backing +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.backing backing_fmt=IMGFMT wrote 262144/262144 bytes at offset 0 256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 196608/196608 bytes at offset 65536 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { 'execute': 'qmp_capabilities' } {"return": {}} -Formatting 'TEST_DIR/t.IMGFMT.overlay', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT +Formatting 'TEST_DIR/t.IMGFMT.overlay', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT { 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'source', 'snapshot-file': 'TEST_DIR/t.IMGFMT.overlay', 'format': 'IMGFMT', 'mode': 'existing' } } {"return": {}} { 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io source "write -P 3 128k 128k"' } } wrote 131072/131072 bytes at offset 131072 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": ""} -Formatting 'TEST_DIR/t.IMGFMT.target.overlay', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.target +Formatting 'TEST_DIR/t.IMGFMT.target.overlay', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.target backing_fmt=IMGFMT { 'execute': 'drive-mirror', 'arguments': { 'device': 'source', 'target': 'TEST_DIR/t.IMGFMT.target.overlay', 'mode': 'existing', 'sync': 'top' } } {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "source"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "source"}} diff --git a/tests/qemu-iotests/158 b/tests/qemu-iotests/158 index ba4db6116ac36463961c377b3bf8ebdf759993f9..cf23742c5946fadf0f704bd0ad3143acf7393ea1 100755 --- a/tests/qemu-iotests/158 +++ b/tests/qemu-iotests/158 @@ -38,7 +38,6 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow qcow2 _supported_proto generic -_unsupported_proto vxhs size=128M @@ -64,7 +63,7 @@ echo "== verify pattern ==" $QEMU_IO --object $SECRET -c "read -P 0xa 0 $size" --image-opts $IMGSPECBASE | _filter_qemu_io | _filter_testdir echo "== create overlay ==" -_make_test_img -u --object $SECRET -o "encryption=on,encrypt.key-secret=sec0" -b "$TEST_IMG_BASE" $size +_make_test_img -u --object $SECRET -o "encryption=on,encrypt.key-secret=sec0" -b "$TEST_IMG_BASE" -F $IMGFMT $size echo echo "== writing part of a cluster ==" diff --git a/tests/qemu-iotests/158.out b/tests/qemu-iotests/158.out index 6def216e557411d4076c6ed9f3ca9036240bbbac..83f19699bb5efb5f94158bb59d2bdba05ef6d8b4 100644 --- a/tests/qemu-iotests/158.out +++ b/tests/qemu-iotests/158.out @@ -1,6 +1,6 @@ QA output created by 158 == create base == -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 encryption=on == writing whole image == wrote 134217728/134217728 bytes at offset 0 @@ -10,7 +10,7 @@ wrote 134217728/134217728 bytes at offset 0 read 134217728/134217728 bytes at offset 0 128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == create overlay == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base encryption=on encrypt.key-secret=sec0 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT encryption=on == writing part of a cluster == wrote 1024/1024 bytes at offset 0 diff --git a/tests/qemu-iotests/161 b/tests/qemu-iotests/161 index f572a19af28c5d6529b449d2c771ddd0af2aa6ac..e270976d8783603e70df8880eeaca5008ff2e45b 100755 --- a/tests/qemu-iotests/161 +++ b/tests/qemu-iotests/161 @@ -49,8 +49,8 @@ IMG_SIZE=1M # Create the images TEST_IMG="$TEST_IMG.base" _make_test_img $IMG_SIZE | _filter_imgfmt -TEST_IMG="$TEST_IMG.int" _make_test_img -b "$TEST_IMG.base" | _filter_imgfmt -_make_test_img -b "$TEST_IMG.int" | _filter_imgfmt +TEST_IMG="$TEST_IMG.int" _make_test_img -b "$TEST_IMG.base" -F $IMGFMT | _filter_imgfmt +_make_test_img -b "$TEST_IMG.int" -F $IMGFMT -F $IMGFMT | _filter_imgfmt # First test: reopen $TEST.IMG changing the detect-zeroes option on # its backing file ($TEST_IMG.int). @@ -106,8 +106,8 @@ echo "*** Commit and then change an option on the backing file" echo # Create the images again TEST_IMG="$TEST_IMG.base" _make_test_img $IMG_SIZE | _filter_imgfmt -TEST_IMG="$TEST_IMG.int" _make_test_img -b "$TEST_IMG.base" | _filter_imgfmt -_make_test_img -b "$TEST_IMG.int" | _filter_imgfmt +TEST_IMG="$TEST_IMG.int" _make_test_img -b "$TEST_IMG.base" -F $IMGFMT| _filter_imgfmt +_make_test_img -b "$TEST_IMG.int" -F $IMGFMT | _filter_imgfmt _launch_qemu -drive if=none,file="${TEST_IMG}" _send_qemu_cmd $QEMU_HANDLE \ diff --git a/tests/qemu-iotests/161.out b/tests/qemu-iotests/161.out index aef9741ed31cebab7ab539ea699da477b2a6e848..3d8d89a9da3f22a54ec7ad985c9a8a0a2a56e123 100644 --- a/tests/qemu-iotests/161.out +++ b/tests/qemu-iotests/161.out @@ -1,7 +1,7 @@ QA output created by 161 Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1048576 -Formatting 'TEST_DIR/t.IMGFMT.int', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.int +Formatting 'TEST_DIR/t.IMGFMT.int', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.int backing_fmt=IMGFMT *** Change an option on the backing file @@ -29,8 +29,8 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t. *** Commit and then change an option on the backing file Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1048576 -Formatting 'TEST_DIR/t.IMGFMT.int', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.int +Formatting 'TEST_DIR/t.IMGFMT.int', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.int backing_fmt=IMGFMT { 'execute': 'qmp_capabilities' } {"return": {}} { 'execute': 'block-commit', 'arguments': { 'device': 'none0', 'top': 'TEST_DIR/t.IMGFMT.int' } } diff --git a/tests/qemu-iotests/162.out b/tests/qemu-iotests/162.out index 5a00d36d17878376380430dad70527edf45bef2f..f8714cb0d27d2b15d3feaaaf729cb312fb2e5cd8 100644 --- a/tests/qemu-iotests/162.out +++ b/tests/qemu-iotests/162.out @@ -6,8 +6,8 @@ image: nbd://localhost:PORT image: nbd+unix://?socket=42 === SSH === -qemu-img: Could not open 'json:{"driver": "ssh", "host": "localhost", "port": "0", "path": "/foo"}': Failed to connect socket: Connection refused -qemu-img: Could not open 'driver=ssh,host=localhost,port=0,path=/foo': Failed to connect socket: Connection refused +qemu-img: Could not open 'json:{"driver": "ssh", "host": "localhost", "port": "0", "path": "/foo"}': Failed to connect to 'localhost:0': Connection refused +qemu-img: Could not open 'driver=ssh,host=localhost,port=0,path=/foo': Failed to connect to 'localhost:0': Connection refused qemu-img: Could not open 'json:{"driver": "ssh", "host": "localhost", "port": 0.42, "path": "/foo"}': Parameter 'port' expects a number qemu-img: Could not open 'driver=ssh,host=localhost,port=0.42,path=/foo': Parameter 'port' expects a number diff --git a/tests/qemu-iotests/169 b/tests/qemu-iotests/169 index 2c5a132aa31512a18e31b102f38ec2c4f863f47d..40afb15299861a4a8bc0fa3cae60f48313e565cf 100755 --- a/tests/qemu-iotests/169 +++ b/tests/qemu-iotests/169 @@ -24,11 +24,12 @@ import time import itertools import operator import re -from iotests import qemu_img +from iotests import qemu_img, qemu_img_create, Timeout disk_a = os.path.join(iotests.test_dir, 'disk_a') disk_b = os.path.join(iotests.test_dir, 'disk_b') +base_a = os.path.join(iotests.test_dir, 'base_a') size = '1M' mig_file = os.path.join(iotests.test_dir, 'mig_file') mig_cmd = 'exec: cat > ' + mig_file @@ -234,6 +235,67 @@ for cmb in list(itertools.product((True, False), repeat=2)): inject_test_case(TestDirtyBitmapMigration, name, 'do_test_migration_resume_source', *list(cmb)) + +class TestDirtyBitmapBackingMigration(iotests.QMPTestCase): + def setUp(self): + qemu_img_create('-f', iotests.imgfmt, base_a, size) + qemu_img_create('-f', iotests.imgfmt, '-F', iotests.imgfmt, + '-b', base_a, disk_a, size) + + for f in (disk_a, base_a): + qemu_img('bitmap', '--add', f, 'bmap0') + + blockdev = { + 'node-name': 'node0', + 'driver': iotests.imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_a + }, + 'backing': { + 'node-name': 'node0-base', + 'driver': iotests.imgfmt, + 'file': { + 'driver': 'file', + 'filename': base_a + } + } + } + + self.vm = iotests.VM() + self.vm.launch() + + result = self.vm.qmp('blockdev-add', **blockdev) + self.assert_qmp(result, 'return', {}) + + # Check that the bitmaps are there + for node in self.vm.qmp('query-named-block-nodes', flat=True)['return']: + if 'node0' in node['node-name']: + self.assert_qmp(node, 'dirty-bitmaps[0]/name', 'bmap0') + + caps = [{'capability': 'events', 'state': True}] + result = self.vm.qmp('migrate-set-capabilities', capabilities=caps) + self.assert_qmp(result, 'return', {}) + + def tearDown(self): + self.vm.shutdown() + for f in (disk_a, base_a): + os.remove(f) + + def test_cont_on_source(self): + """ + Continue the source after migration. + """ + result = self.vm.qmp('migrate', uri=f'exec: cat > /dev/null') + self.assert_qmp(result, 'return', {}) + + with Timeout(10, 'Migration timeout'): + self.vm.wait_migration('postmigrate') + + result = self.vm.qmp('cont') + self.assert_qmp(result, 'return', {}) + + if __name__ == '__main__': iotests.main(supported_fmts=['qcow2'], supported_protocols=['file']) diff --git a/tests/qemu-iotests/169.out b/tests/qemu-iotests/169.out index 5c26d15c0d0674222f68d281ed19b76ecbfdd28f..cafb8161f7b11e478e2c0834f228257fddcec155 100644 --- a/tests/qemu-iotests/169.out +++ b/tests/qemu-iotests/169.out @@ -1,5 +1,5 @@ -.................................... +..................................... ---------------------------------------------------------------------- -Ran 36 tests +Ran 37 tests OK diff --git a/tests/qemu-iotests/172 b/tests/qemu-iotests/172 index 7195fb895a0bd9802b6f73323d4b0c200fa4761b..3abfa72948f6783d3835979773e397d1a5d884ac 100755 --- a/tests/qemu-iotests/172 +++ b/tests/qemu-iotests/172 @@ -69,9 +69,10 @@ check_floppy_qtree() # # Apply the sed filter to stdout only, but keep the stderr output and # filter the qemu program name in it. - echo "info qtree" | + printf "info qtree\ninfo block\n" | (QEMU_OPTIONS="" do_run_qemu "$@" | - sed -ne '/^ dev: isa-fdc/,/^ dev:/{x;p}' ) 2>&1 | + _filter_testdir |_filter_generated_node_ids | _filter_hmp | + sed -ne '/^ dev: isa-fdc/,/^ dev:/{x;p};/^[a-z][^ ]* (NODE_NAME):* /,/^(qemu)$/{p}') 2>&1 | _filter_win32 | _filter_qemu } @@ -110,6 +111,7 @@ echo === Using -fda/-fdb options === check_floppy_qtree -fda "$TEST_IMG" check_floppy_qtree -fdb "$TEST_IMG" check_floppy_qtree -fda "$TEST_IMG" -fdb "$TEST_IMG.2" +check_floppy_qtree -fdb "" echo @@ -146,9 +148,11 @@ echo === Mixing -fdX and -global === check_floppy_qtree -fda "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -global isa-fdc.driveB=none0 check_floppy_qtree -fdb "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -global isa-fdc.driveA=none0 -# Conflicting (-fdX wins) +# Conflicting check_floppy_qtree -fda "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -global isa-fdc.driveA=none0 check_floppy_qtree -fdb "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -global isa-fdc.driveB=none0 +# Conflicting, -fdX wins +check_floppy_qtree -fda "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -global floppy.drive=none0 echo echo @@ -190,12 +194,29 @@ check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IM -global isa-fdc.driveB=none0 -device floppy,drive=none1 check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \ -global isa-fdc.driveB=none0 -device floppy,drive=none1,unit=0 +check_floppy_qtree -drive if=none,file="$TEST_IMG" \ + -global floppy.drive=none0 -device floppy,unit=0 # Conflicting check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \ -global isa-fdc.driveA=none0 -device floppy,drive=none1,unit=0 check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \ -global isa-fdc.driveB=none0 -device floppy,drive=none1,unit=1 +check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \ + -global floppy.drive=none0 -device floppy,drive=none1,unit=0 + +echo +echo +echo === Attempt to use drive twice === + +# if=none +check_floppy_qtree -drive if=none -device floppy,drive=none0 -device floppy -device floppy,drive=none0 +check_floppy_qtree -drive if=none -global floppy.drive=none0 -device floppy -device floppy +# if=floppy +check_floppy_qtree -fda "" -device floppy,drive=floppy0 +check_floppy_qtree -fda "" -global floppy.drive=floppy0 +# default if=floppy (not found, because it's created later) +check_floppy_qtree -device floppy,drive=floppy0 echo echo diff --git a/tests/qemu-iotests/172.out b/tests/qemu-iotests/172.out index 7abbe82427a6ffbc2b55c24409715d72fca527ae..cca2894af092f5872a79ee31d2e8e13fccbe6a9e 100644 --- a/tests/qemu-iotests/172.out +++ b/tests/qemu-iotests/172.out @@ -24,11 +24,11 @@ Testing: dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "288" @@ -54,14 +54,27 @@ Testing: -fda TEST_DIR/t.qcow2 dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[22] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -fdb TEST_DIR/t.qcow2 @@ -81,25 +94,42 @@ Testing: -fdb TEST_DIR/t.qcow2 dev: floppy, id "" unit = 1 (0x1) drive = "floppy1" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "288" +floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[16] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[23] + Removable device: not locked, tray closed + +floppy0: [not inserted] + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2 @@ -119,25 +149,81 @@ Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2 dev: floppy, id "" unit = 1 (0x1) drive = "floppy1" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +floppy1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) + Attached to: /machine/unattached/device[16] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[23] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + + +Testing: -fdb + + dev: isa-fdc, id "" + iobase = 1008 (0x3f0) + irq = 6 (0x6) + dma = 2 (0x2) + driveA = "" + driveB = "" + check_media_rate = true + fdtypeA = "auto" + fdtypeB = "auto" + fallback = "288" + isa irq 6 + bus: floppy-bus.0 + type floppy-bus + dev: floppy, id "" + unit = 1 (0x1) + drive = "floppy1" + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) + write-cache = "auto" + share-rw = false + drive-type = "288" + dev: floppy, id "" + unit = 0 (0x0) + drive = "floppy0" + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) + write-cache = "auto" + share-rw = false + drive-type = "288" === Using -drive options === @@ -160,14 +246,27 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[22] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1 @@ -187,25 +286,42 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1 dev: floppy, id "" unit = 1 (0x1) drive = "floppy1" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "288" +floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[16] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[23] + Removable device: not locked, tray closed + +floppy0: [not inserted] + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t.qcow2.2,index=1 @@ -225,30 +341,50 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t dev: floppy, id "" unit = 1 (0x1) drive = "floppy1" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +floppy1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) + Attached to: /machine/unattached/device[16] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[23] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + === Using -drive if=none and -global === Testing: -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveA=none0 +QEMU_PROG: warning: warning: property isa-fdc.driveA is deprecated +Use -device floppy,unit=0,drive=... instead. dev: isa-fdc, id "" iobase = 1008 (0x3f0) @@ -266,16 +402,31 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveA=none0 dev: floppy, id "" unit = 0 (0x0) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[22] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveB=none0 +QEMU_PROG: warning: warning: property isa-fdc.driveB is deprecated +Use -device floppy,unit=1,drive=... instead. dev: isa-fdc, id "" iobase = 1008 (0x3f0) @@ -293,16 +444,33 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveB=none0 dev: floppy, id "" unit = 1 (0x1) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[22] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 -global isa-fdc.driveB=none1 +QEMU_PROG: warning: warning: property isa-fdc.driveA is deprecated +Use -device floppy,unit=0,drive=... instead. +QEMU_PROG: warning: warning: property isa-fdc.driveB is deprecated +Use -device floppy,unit=1,drive=... instead. dev: isa-fdc, id "" iobase = 1008 (0x3f0) @@ -320,25 +488,43 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco dev: floppy, id "" unit = 1 (0x1) drive = "none1" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" unit = 0 (0x0) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +none1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) + Attached to: /machine/unattached/device[16] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[23] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + === Using -drive if=none and -device === @@ -361,14 +547,27 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0 dev: floppy, id "" unit = 0 (0x0) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[21] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=1 @@ -388,14 +587,27 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=1 dev: floppy, id "" unit = 1 (0x1) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[21] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0 -device floppy,drive=none1,unit=1 @@ -415,30 +627,50 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco dev: floppy, id "" unit = 1 (0x1) drive = "none1" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" unit = 0 (0x0) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +none1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) + Attached to: /machine/peripheral-anon/device[1] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[21] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + === Mixing -fdX and -global === Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveB=none0 +QEMU_PROG: warning: warning: property isa-fdc.driveB is deprecated +Use -device floppy,unit=1,drive=... instead. dev: isa-fdc, id "" iobase = 1008 (0x3f0) @@ -454,29 +686,49 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global is bus: floppy-bus.0 type floppy-bus dev: floppy, id "" - unit = 1 (0x1) - drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + unit = 0 (0x0) + drive = "floppy0" + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" - unit = 0 (0x0) - drive = "floppy0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + unit = 1 (0x1) + drive = "none0" + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[16] + Removable device: not locked, tray closed + Cache mode: writeback + +none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[23] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 +QEMU_PROG: warning: warning: property isa-fdc.driveA is deprecated +Use -device floppy,unit=0,drive=... instead. dev: isa-fdc, id "" iobase = 1008 (0x3f0) @@ -494,79 +746,56 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global is dev: floppy, id "" unit = 1 (0x1) drive = "floppy1" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" unit = 0 (0x0) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[16] + Removable device: not locked, tray closed + Cache mode: writeback -Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 +none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback - dev: isa-fdc, id "" - iobase = 1008 (0x3f0) - irq = 6 (0x6) - dma = 2 (0x2) - driveA = "" - driveB = "" - check_media_rate = true - fdtypeA = "auto" - fdtypeB = "auto" - fallback = "288" - isa irq 6 - bus: floppy-bus.0 - type floppy-bus - dev: floppy, id "" - unit = 0 (0x0) - drive = "floppy0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) - write-cache = "auto" - share-rw = false - drive-type = "144" +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[23] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + + +Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 +QEMU_PROG: warning: warning: property isa-fdc.driveA is deprecated +Use -device floppy,unit=0,drive=... instead. +QEMU_PROG: Floppy unit 0 is in use Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveB=none0 +QEMU_PROG: warning: warning: property isa-fdc.driveB is deprecated +Use -device floppy,unit=1,drive=... instead. +QEMU_PROG: Floppy unit 1 is in use - dev: isa-fdc, id "" - iobase = 1008 (0x3f0) - irq = 6 (0x6) - dma = 2 (0x2) - driveA = "" - driveB = "" - check_media_rate = true - fdtypeA = "auto" - fdtypeB = "auto" - fallback = "288" - isa irq 6 - bus: floppy-bus.0 - type floppy-bus - dev: floppy, id "" - unit = 1 (0x1) - drive = "floppy1" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) - write-cache = "auto" - share-rw = false - drive-type = "144" +Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global floppy.drive=none0 +QEMU_PROG: -global floppy.drive=... conflicts with drive=floppy0 === Mixing -fdX and -device === @@ -589,25 +818,43 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl dev: floppy, id "" unit = 1 (0x1) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[22] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0,unit=1 @@ -627,25 +874,43 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl dev: floppy, id "" unit = 1 (0x1) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[22] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0 @@ -665,25 +930,43 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl dev: floppy, id "" unit = 0 (0x0) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" unit = 1 (0x1) drive = "floppy1" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[22] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0,unit=0 @@ -703,25 +986,43 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl dev: floppy, id "" unit = 0 (0x0) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" unit = 1 (0x1) drive = "floppy1" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[22] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0,unit=0 QEMU_PROG: -device floppy,drive=none0,unit=0: Floppy unit 0 is in use @@ -750,25 +1051,43 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q dev: floppy, id "" unit = 1 (0x1) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[22] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0,unit=1 @@ -788,25 +1107,43 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q dev: floppy, id "" unit = 1 (0x1) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[22] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device floppy,drive=none0,unit=0 QEMU_PROG: -device floppy,drive=none0,unit=0: Floppy unit 0 is in use @@ -815,6 +1152,8 @@ QEMU_PROG: -device floppy,drive=none0,unit=0: Floppy unit 0 is in use === Mixing -global and -device === Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 -device floppy,drive=none1 +QEMU_PROG: warning: warning: property isa-fdc.driveA is deprecated +Use -device floppy,unit=0,drive=... instead. dev: isa-fdc, id "" iobase = 1008 (0x3f0) @@ -832,27 +1171,47 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco dev: floppy, id "" unit = 1 (0x1) drive = "none1" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" unit = 0 (0x0) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +none1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[22] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 -device floppy,drive=none1,unit=1 +QEMU_PROG: warning: warning: property isa-fdc.driveA is deprecated +Use -device floppy,unit=0,drive=... instead. dev: isa-fdc, id "" iobase = 1008 (0x3f0) @@ -870,27 +1229,47 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco dev: floppy, id "" unit = 1 (0x1) drive = "none1" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" unit = 0 (0x0) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +none1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[22] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveB=none0 -device floppy,drive=none1 +QEMU_PROG: warning: warning: property isa-fdc.driveB is deprecated +Use -device floppy,unit=1,drive=... instead. dev: isa-fdc, id "" iobase = 1008 (0x3f0) @@ -908,27 +1287,47 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco dev: floppy, id "" unit = 0 (0x0) drive = "none1" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" unit = 1 (0x1) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +none1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[22] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveB=none0 -device floppy,drive=none1,unit=0 +QEMU_PROG: warning: warning: property isa-fdc.driveB is deprecated +Use -device floppy,unit=1,drive=... instead. dev: isa-fdc, id "" iobase = 1008 (0x3f0) @@ -946,36 +1345,121 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco dev: floppy, id "" unit = 0 (0x0) drive = "none1" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" dev: floppy, id "" unit = 1 (0x1) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/unattached/device[15] + Removable device: not locked, tray closed + Cache mode: writeback + +none1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[22] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + + +Testing: -drive if=none,file=TEST_DIR/t.qcow2 -global floppy.drive=none0 -device floppy,unit=0 + + dev: isa-fdc, id "" + iobase = 1008 (0x3f0) + irq = 6 (0x6) + dma = 2 (0x2) + driveA = "" + driveB = "" + check_media_rate = true + fdtypeA = "auto" + fdtypeB = "auto" + fallback = "288" + isa irq 6 + bus: floppy-bus.0 + type floppy-bus + dev: floppy, id "" + unit = 0 (0x0) + drive = "none0" + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) + write-cache = "auto" + share-rw = false + drive-type = "144" +none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[21] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 -device floppy,drive=none1,unit=0 +QEMU_PROG: warning: warning: property isa-fdc.driveA is deprecated +Use -device floppy,unit=0,drive=... instead. QEMU_PROG: -device floppy,drive=none1,unit=0: Floppy unit 0 is in use Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveB=none0 -device floppy,drive=none1,unit=1 +QEMU_PROG: warning: warning: property isa-fdc.driveB is deprecated +Use -device floppy,unit=1,drive=... instead. QEMU_PROG: -device floppy,drive=none1,unit=1: Floppy unit 1 is in use +Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global floppy.drive=none0 -device floppy,drive=none1,unit=0 +QEMU_PROG: -device floppy,drive=none1,unit=0: -global floppy.drive=... conflicts with drive=none1 + + +=== Attempt to use drive twice === + +Testing: -drive if=none -device floppy,drive=none0 -device floppy -device floppy,drive=none0 +QEMU_PROG: -device floppy,drive=none0: Drive 'none0' is already in use by another device + +Testing: -drive if=none -global floppy.drive=none0 -device floppy -device floppy +QEMU_PROG: -device floppy: can't apply global floppy.drive=none0: Drive 'none0' is already in use by another device + +Testing: -fda -device floppy,drive=floppy0 +QEMU_PROG: -device floppy,drive=floppy0: Drive 'floppy0' is already in use because it has been automatically connected to another device (did you need 'if=none' in the drive options?) + +Testing: -fda -global floppy.drive=floppy0 +QEMU_PROG: -global floppy.drive=... conflicts with drive=floppy0 + +Testing: -device floppy,drive=floppy0 +QEMU_PROG: -device floppy,drive=floppy0: Property 'floppy.drive' can't find value 'floppy0' + === Too many floppy drives === Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -drive if=none,file=TEST_DIR/t.qcow2.3 -global isa-fdc.driveB=none0 -device floppy,drive=none1 +QEMU_PROG: warning: warning: property isa-fdc.driveB is deprecated +Use -device floppy,unit=1,drive=... instead. QEMU_PROG: -device floppy,drive=none1: Can't create floppy unit 2, bus supports only 2 units @@ -999,11 +1483,11 @@ Testing: -device floppy dev: floppy, id "" unit = 0 (0x0) drive = "" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "288" @@ -1026,11 +1510,11 @@ Testing: -device floppy,drive-type=120 dev: floppy, id "" unit = 0 (0x0) drive = "" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "120" @@ -1053,11 +1537,11 @@ Testing: -device floppy,drive-type=144 dev: floppy, id "" unit = 0 (0x0) drive = "" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" @@ -1080,11 +1564,11 @@ Testing: -device floppy,drive-type=288 dev: floppy, id "" unit = 0 (0x0) drive = "" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "288" @@ -1110,14 +1594,27 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t dev: floppy, id "" unit = 0 (0x0) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "120" +none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[21] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-type=288 @@ -1137,14 +1634,27 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t dev: floppy, id "" unit = 0 (0x0) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "288" +none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[21] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + === Try passing different block sizes === @@ -1167,14 +1677,27 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,logical dev: floppy, id "" unit = 0 (0x0) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[21] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,physical_block_size=512 @@ -1194,17 +1717,30 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,physica dev: floppy, id "" unit = 0 (0x0) drive = "none0" - logical_block_size = 512 (0x200) - physical_block_size = 512 (0x200) - min_io_size = 0 (0x0) - opt_io_size = 0 (0x0) - discard_granularity = 4294967295 (0xffffffff) + logical_block_size = 512 (512 B) + physical_block_size = 512 (512 B) + min_io_size = 0 (0 B) + opt_io_size = 0 (0 B) + discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false drive-type = "144" +none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Attached to: /machine/peripheral-anon/device[0] + Removable device: not locked, tray closed + Cache mode: writeback + +ide1-cd0: [not inserted] + Attached to: /machine/unattached/device[21] + Removable device: not locked, tray closed + +sd0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,logical_block_size=4096 -QEMU_PROG: -device floppy,drive=none0,logical_block_size=4096: Physical and logical block size must be 512 for floppy +QEMU_PROG: -device floppy,drive=none0,logical_block_size=4096: logical_block_size > physical_block_size not supported Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,physical_block_size=1024 QEMU_PROG: -device floppy,drive=none0,physical_block_size=1024: Physical and logical block size must be 512 for floppy diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175 index 020ed8e61fb52456fecb10d7429070219a4ec28f..00a626aa6335c56ebab904e6351c2953a56f6f4b 100755 --- a/tests/qemu-iotests/175 +++ b/tests/qemu-iotests/175 @@ -89,20 +89,20 @@ min_blocks=$(stat -c '%b' "$TEST_DIR/empty") echo echo "== creating image with default preallocation ==" -_make_test_img $size | _filter_imgfmt +_make_test_img -o extent_size_hint=0 $size | _filter_imgfmt stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size for mode in off full falloc; do echo echo "== creating image with preallocation $mode ==" - _make_test_img -o preallocation=$mode $size | _filter_imgfmt + _make_test_img -o preallocation=$mode,extent_size_hint=0 $size | _filter_imgfmt stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size done for new_size in 4096 1048576; do echo echo "== resize empty image with block_resize ==" - _make_test_img 0 | _filter_imgfmt + _make_test_img -o extent_size_hint=0 0 | _filter_imgfmt _block_resize $TEST_IMG $new_size >/dev/null stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $new_size done diff --git a/tests/qemu-iotests/176 b/tests/qemu-iotests/176 index 117c8b695490000ce064055f94cfa2f5cf49553c..2565ff12eef8f281b52a4e0b53760b1c6ea87e92 100755 --- a/tests/qemu-iotests/176 +++ b/tests/qemu-iotests/176 @@ -84,8 +84,8 @@ echo len=$((2100 * 1024 * 1024 + 512)) # larger than 2G, and not cluster aligned TEST_IMG="$TEST_IMG.base" _make_test_img $len -TEST_IMG="$TEST_IMG.itmd" _make_test_img -b "$TEST_IMG.base" $len -_make_test_img -b "$TEST_IMG.itmd" $len +TEST_IMG="$TEST_IMG.itmd" _make_test_img -b "$TEST_IMG.base" -F $IMGFMT $len +_make_test_img -b "$TEST_IMG.itmd" -F $IMGFMT $len # Update the top image to use a feature that is incompatible with fast path case $reason in snapshot) $QEMU_IMG snapshot -c snap "$TEST_IMG" ;; diff --git a/tests/qemu-iotests/176.out b/tests/qemu-iotests/176.out index cc33def96b25943a844e548c81f7e3d2fb79701d..9d09b60452020981a6be338bf1662717074a6bd6 100644 --- a/tests/qemu-iotests/176.out +++ b/tests/qemu-iotests/176.out @@ -3,8 +3,8 @@ QA output created by 176 === Test pass snapshot.0 === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd backing_fmt=IMGFMT wrote 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 2147352576 @@ -43,8 +43,8 @@ ID TAG === Test pass snapshot.1 === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd backing_fmt=IMGFMT wrote 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 2147352576 @@ -84,8 +84,8 @@ ID TAG === Test pass snapshot.2 === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd backing_fmt=IMGFMT wrote 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 2147352576 @@ -125,8 +125,8 @@ ID TAG === Test pass snapshot.3 === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd backing_fmt=IMGFMT wrote 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 2147352576 @@ -163,8 +163,8 @@ ID TAG === Test pass bitmap.0 === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd backing_fmt=IMGFMT QMP_VERSION {"return": {}} {"return": {}} @@ -212,8 +212,8 @@ QMP_VERSION === Test pass bitmap.1 === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd backing_fmt=IMGFMT QMP_VERSION {"return": {}} {"return": {}} @@ -262,8 +262,8 @@ QMP_VERSION === Test pass bitmap.2 === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd backing_fmt=IMGFMT QMP_VERSION {"return": {}} {"return": {}} @@ -312,8 +312,8 @@ QMP_VERSION === Test pass bitmap.3 === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd backing_fmt=IMGFMT QMP_VERSION {"return": {}} {"return": {}} diff --git a/tests/qemu-iotests/177 b/tests/qemu-iotests/177 index eadc2c7ef6a835fd8ff23fd07dafa11f10452c09..5d4a77a6ab4732bc7770249af5c19fde611aeaeb 100755 --- a/tests/qemu-iotests/177 +++ b/tests/qemu-iotests/177 @@ -51,7 +51,7 @@ echo "== setting up files ==" TEST_IMG="$TEST_IMG.base" _make_test_img $size $QEMU_IO -c "write -P 11 0 $size" "$TEST_IMG.base" | _filter_qemu_io -_make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $QEMU_IO -c "write -P 22 0 $size" "$TEST_IMG" | _filter_qemu_io # Limited to 64k max-transfer diff --git a/tests/qemu-iotests/177.out b/tests/qemu-iotests/177.out index e887542678ba0ea6cc869fdc7c9703b671564b2c..ba1e1e212e470a160882626fca1165569b1c09e9 100644 --- a/tests/qemu-iotests/177.out +++ b/tests/qemu-iotests/177.out @@ -4,7 +4,7 @@ QA output created by 177 Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 wrote 134217728/134217728 bytes at offset 0 128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 134217728/134217728 bytes at offset 0 128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/178 b/tests/qemu-iotests/178 index 7cf0e27154d0eee81cf29a1e4382ac301129b3f1..f09b27caacf3eeef0b9d66ce4792f31c9118d675 100755 --- a/tests/qemu-iotests/178 +++ b/tests/qemu-iotests/178 @@ -41,6 +41,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt raw qcow2 _supported_proto file _supported_os Linux +_require_working_luks echo "== Input validation ==" echo diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2 index f59bf4b2fbc4b5d843a8bd6b29a51a546a7a2210..c7997760fd6fa2d03ce98c342986c0c2e5cb6d87 100644 --- a/tests/qemu-iotests/178.out.qcow2 +++ b/tests/qemu-iotests/178.out.qcow2 @@ -13,7 +13,7 @@ qemu-img: Invalid option list: , qemu-img: Invalid parameter 'snapshot.foo' qemu-img: Failed in parsing snapshot param 'snapshot.foo' qemu-img: --output must be used with human or json as argument. -qemu-img: Image size must be less than 8 EiB! +qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807. qemu-img: Unknown file format 'foo' == Size calculation for a new file (human) == @@ -37,6 +37,7 @@ qemu-img: The image size is too large (try using a larger cluster size) Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0 required size: 196608 fully allocated size: 196608 +bitmaps size: 0 converted image file size in bytes: 196608 @@ -45,6 +46,7 @@ converted image file size in bytes: 196608 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 required size: 393216 fully allocated size: 1074135040 +bitmaps size: 0 wrote 512/512 bytes at offset 512 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 65536 @@ -53,6 +55,7 @@ wrote 64512/64512 bytes at offset 134217728 63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) required size: 589824 fully allocated size: 1074135040 +bitmaps size: 0 converted image file size in bytes: 524288 @@ -60,6 +63,7 @@ converted image file size in bytes: 524288 required size: 524288 fully allocated size: 1074135040 +bitmaps size: 0 converted image file size in bytes: 458752 @@ -67,16 +71,19 @@ converted image file size in bytes: 458752 required size: 1074135040 fully allocated size: 1074135040 +bitmaps size: 0 == qcow2 input image and LUKS encryption == required size: 2686976 fully allocated size: 1076232192 +bitmaps size: 0 == qcow2 input image and preallocation (human) == required size: 1074135040 fully allocated size: 1074135040 +bitmaps size: 0 converted image file size in bytes: 1074135040 @@ -87,6 +94,7 @@ wrote 8388608/8388608 bytes at offset 0 8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) required size: 8716288 fully allocated size: 8716288 +bitmaps size: 0 converted image file size in bytes: 8716288 @@ -173,6 +181,7 @@ qemu-img: The image size is too large (try using a larger cluster size) Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0 { + "bitmaps": 0, "required": 196608, "fully-allocated": 196608 } @@ -183,6 +192,7 @@ converted image file size in bytes: 196608 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 { + "bitmaps": 0, "required": 393216, "fully-allocated": 1074135040 } @@ -193,6 +203,7 @@ wrote 65536/65536 bytes at offset 65536 wrote 64512/64512 bytes at offset 134217728 63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { + "bitmaps": 0, "required": 589824, "fully-allocated": 1074135040 } @@ -202,6 +213,7 @@ converted image file size in bytes: 524288 == qcow2 input image with internal snapshot (json) == { + "bitmaps": 0, "required": 524288, "fully-allocated": 1074135040 } @@ -211,6 +223,7 @@ converted image file size in bytes: 458752 == qcow2 input image and a backing file (json) == { + "bitmaps": 0, "required": 1074135040, "fully-allocated": 1074135040 } @@ -218,6 +231,7 @@ converted image file size in bytes: 458752 == qcow2 input image and LUKS encryption == { + "bitmaps": 0, "required": 2686976, "fully-allocated": 1076232192 } @@ -225,6 +239,7 @@ converted image file size in bytes: 458752 == qcow2 input image and preallocation (json) == { + "bitmaps": 0, "required": 1074135040, "fully-allocated": 1074135040 } @@ -237,6 +252,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8388608 wrote 8388608/8388608 bytes at offset 0 8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { + "bitmaps": 0, "required": 8716288, "fully-allocated": 8716288 } diff --git a/tests/qemu-iotests/178.out.raw b/tests/qemu-iotests/178.out.raw index 404ca908d8c2686d2be220d57db6ee6954a72915..20e17da115cb317bef157ff97f8f06e0b71216be 100644 --- a/tests/qemu-iotests/178.out.raw +++ b/tests/qemu-iotests/178.out.raw @@ -13,7 +13,7 @@ qemu-img: Invalid option list: , qemu-img: Invalid parameter 'snapshot.foo' qemu-img: Failed in parsing snapshot param 'snapshot.foo' qemu-img: --output must be used with human or json as argument. -qemu-img: Image size must be less than 8 EiB! +qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807. qemu-img: Unknown file format 'foo' == Size calculation for a new file (human) == diff --git a/tests/qemu-iotests/179 b/tests/qemu-iotests/179 index 9372dc30ef779c51e7d01a9855f7828f5f12d1d1..11a20cb1bfa87928d07bf9808c2da2c9fc3c442c 100755 --- a/tests/qemu-iotests/179 +++ b/tests/qemu-iotests/179 @@ -49,7 +49,7 @@ echo '=== Testing write zeroes with unmap ===' echo TEST_IMG="$TEST_IMG.base" _make_test_img 64M -_make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT # Offsets chosen at or near 2M boundaries so test works at all cluster sizes # 8k and larger (smaller clusters fail due to non-contiguous allocations) diff --git a/tests/qemu-iotests/179.out b/tests/qemu-iotests/179.out index 80722b22891df74b3d773d425d2704a7fe060da6..1f7680002ca6dda11c008e57319ca24aec1e0789 100644 --- a/tests/qemu-iotests/179.out +++ b/tests/qemu-iotests/179.out @@ -3,7 +3,7 @@ QA output created by 179 === Testing write zeroes with unmap === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 2097152/2097152 bytes at offset 2097152 2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 2097152/2097152 bytes at offset 6291456 diff --git a/tests/qemu-iotests/182.out b/tests/qemu-iotests/182.out index ae43654d32819d82f08ad149ac75942b7e94d2ee..ce2334067041172df246eb813d78cb3b7b404e3b 100644 --- a/tests/qemu-iotests/182.out +++ b/tests/qemu-iotests/182.out @@ -13,7 +13,7 @@ Is another process using the image [TEST_DIR/t.qcow2]? {'execute': 'blockdev-add', 'arguments': { 'node-name': 'node0', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } } {"return": {}} {'execute': 'blockdev-snapshot-sync', 'arguments': { 'node-name': 'node0', 'snapshot-file': 'TEST_DIR/t.IMGFMT.overlay', 'snapshot-node-name': 'node1' } } -Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 size=197120 backing_file=TEST_DIR/t.qcow2 backing_fmt=file cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=197120 backing_file=TEST_DIR/t.qcow2 backing_fmt=file lazy_refcounts=off refcount_bits=16 {"return": {}} {'execute': 'blockdev-add', 'arguments': { 'node-name': 'node1', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } } {"return": {}} diff --git a/tests/qemu-iotests/184 b/tests/qemu-iotests/184 index 33dd8d2a4fc8e3c785d100767ecd25c048a81b09..eebb53faedef0289e7e3c05e83191d9701377e45 100755 --- a/tests/qemu-iotests/184 +++ b/tests/qemu-iotests/184 @@ -45,8 +45,7 @@ do_run_qemu() run_qemu() { do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp\ - | _filter_qemu_io | _filter_generated_node_ids \ - | _filter_actual_image_size + | _filter_qemu_io | _filter_generated_node_ids } test_throttle=$($QEMU_IMG --help|grep throttle) diff --git a/tests/qemu-iotests/184.out b/tests/qemu-iotests/184.out index 3deb3cfb941a52b55866e041462ccf5878c1aa68..87c73070e36d64bd489191a974c7862d88aa0f8e 100644 --- a/tests/qemu-iotests/184.out +++ b/tests/qemu-iotests/184.out @@ -27,14 +27,21 @@ Testing: "iops_rd": 0, "detect_zeroes": "off", "image": { + "backing-image": { + "virtual-size": 1073741824, + "filename": "null-co://", + "format": "null-co", + "actual-size": 0 + }, "virtual-size": 1073741824, "filename": "json:{\"throttle-group\": \"group0\", \"driver\": \"throttle\", \"file\": {\"driver\": \"null-co\"}}", - "format": "throttle" + "format": "throttle", + "actual-size": 0 }, "iops_wr": 0, "ro": false, "node-name": "throttle0", - "backing_file_depth": 0, + "backing_file_depth": 1, "drv": "throttle", "iops": 0, "bps_wr": 0, @@ -56,7 +63,8 @@ Testing: "image": { "virtual-size": 1073741824, "filename": "null-co://", - "format": "null-co" + "format": "null-co", + "actual-size": 0 }, "iops_wr": 0, "ro": false, diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out index ac5ab16bc8701cdd7c8e29e34d1c251ef74bc1cd..339438ac682c111ff1cef63f3263a920ce76c221 100644 --- a/tests/qemu-iotests/185.out +++ b/tests/qemu-iotests/185.out @@ -9,14 +9,14 @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 === Creating backing chain === { 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT.mid', 'format': 'IMGFMT', 'mode': 'absolute-paths' } } -Formatting 'TEST_DIR/t.qcow2.mid', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.base backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2.mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 backing_file=TEST_DIR/t.qcow2.base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 {"return": {}} { 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io disk "write 0 4M"' } } wrote 4194304/4194304 bytes at offset 0 4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": ""} { 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'absolute-paths' } } -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.mid backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 backing_file=TEST_DIR/t.qcow2.mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 {"return": {}} === Start commit job and exit qemu === @@ -48,7 +48,7 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.q { 'execute': 'qmp_capabilities' } {"return": {}} { 'execute': 'drive-mirror', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } } -Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} {"return": {}} @@ -62,7 +62,7 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 l { 'execute': 'qmp_capabilities' } {"return": {}} { 'execute': 'drive-backup', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } } -Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}} diff --git a/tests/qemu-iotests/188 b/tests/qemu-iotests/188 index 09b9b6083ab3eab9b9b5f3c051a4877489df0dc6..13b225fded475eb18527af5f1d1c21a56f70bf8a 100755 --- a/tests/qemu-iotests/188 +++ b/tests/qemu-iotests/188 @@ -39,6 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto generic _supported_os Linux +_require_working_luks size=16M diff --git a/tests/qemu-iotests/188.out b/tests/qemu-iotests/188.out index c568ef37014520156d9f296ce50f9a4a7bcf7f71..5426861b180c2f97faa0594cf4a6803b2f6e7ea9 100644 --- a/tests/qemu-iotests/188.out +++ b/tests/qemu-iotests/188.out @@ -1,5 +1,5 @@ QA output created by 188 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216 == reading whole image == read 16777216/16777216 bytes at offset 0 diff --git a/tests/qemu-iotests/189 b/tests/qemu-iotests/189 index c9ce9d3bede3038e367019cea18d73cbf9549c4b..3e5ded14c6c17ad990b1bdd3f105314f76a3e22d 100755 --- a/tests/qemu-iotests/189 +++ b/tests/qemu-iotests/189 @@ -39,6 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto generic _supported_os Linux +_require_working_luks size=16M @@ -65,7 +66,7 @@ echo "== verify pattern ==" $QEMU_IO --object $SECRET0 -c "read -P 0xa 0 $size" --image-opts $IMGSPECBASE | _filter_qemu_io | _filter_testdir echo "== create overlay ==" -_make_test_img --object $SECRET1 -o "encrypt.format=luks,encrypt.key-secret=sec1,encrypt.iter-time=10" -u -b "$TEST_IMG_BASE" $size +_make_test_img --object $SECRET1 -o "encrypt.format=luks,encrypt.key-secret=sec1,encrypt.iter-time=10" -u -b "$TEST_IMG_BASE" -F $IMGFMT $size echo echo "== writing part of a cluster ==" diff --git a/tests/qemu-iotests/189.out b/tests/qemu-iotests/189.out index a0b7c9c24c24cb9c1381f16532eb5621c516f0c1..30af0a86080d5f410111b702c4a7adb4472d2e79 100644 --- a/tests/qemu-iotests/189.out +++ b/tests/qemu-iotests/189.out @@ -1,6 +1,6 @@ QA output created by 189 == create base == -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=16777216 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=16777216 == writing whole image == wrote 16777216/16777216 bytes at offset 0 @@ -10,7 +10,7 @@ wrote 16777216/16777216 bytes at offset 0 read 16777216/16777216 bytes at offset 0 16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == create overlay == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216 backing_file=TEST_DIR/t.IMGFMT.base encrypt.format=luks encrypt.key-secret=sec1 encrypt.iter-time=10 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT == writing part of a cluster == wrote 1024/1024 bytes at offset 0 diff --git a/tests/qemu-iotests/190 b/tests/qemu-iotests/190 index 6d41650438e181bc9a708eac5d217b1fe53c54c3..c22d8d64f924799cea9f0b2d154d2c927b922c27 100755 --- a/tests/qemu-iotests/190 +++ b/tests/qemu-iotests/190 @@ -2,7 +2,7 @@ # # qemu-img measure sub-command tests on huge qcow2 files # -# Copyright (C) 2017 Red Hat, Inc. +# Copyright (C) 2017-2020 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 @@ -41,8 +41,10 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 # See 178 for more extensive tests across more formats _supported_fmt qcow2 _supported_proto file +# compat=0.10 does not support bitmaps +_unsupported_imgopts 'compat=0.10' -echo "== Huge file ==" +echo "== Huge file without bitmaps ==" echo _make_test_img -o 'cluster_size=2M' 2T @@ -51,6 +53,49 @@ $QEMU_IMG measure -O raw -f qcow2 "$TEST_IMG" $QEMU_IMG measure -O qcow2 -o cluster_size=64k -f qcow2 "$TEST_IMG" $QEMU_IMG measure -O qcow2 -o cluster_size=2M -f qcow2 "$TEST_IMG" +echo +echo "== Huge file with bitmaps ==" +echo + +$QEMU_IMG bitmap --add --granularity 512 -f qcow2 "$TEST_IMG" b1 +$QEMU_IMG bitmap --add -g 2M -f qcow2 "$TEST_IMG" b2 + +# No bitmap without a source +$QEMU_IMG measure -O qcow2 --size 10M +# No bitmap output, since raw does not support it +$QEMU_IMG measure -O raw -f qcow2 "$TEST_IMG" +# No bitmap output, since no bitmaps on raw source. Munge required size, as +# some filesystems store the qcow2 file with less sparseness than others +$QEMU_IMG measure -O qcow2 -f raw "$TEST_IMG" | + sed '/^required size:/ s/[0-9][0-9]*/SIZE/' +# No bitmap output, since v2 does not support it +$QEMU_IMG measure -O qcow2 -o compat=0.10 -f qcow2 "$TEST_IMG" + +# Compute expected output: bitmap clusters + bitmap tables + bitmaps directory +echo +val2T=$((2*1024*1024*1024*1024)) +cluster=$((64*1024)) +b1clusters=$(( (val2T/512/8 + cluster - 1) / cluster )) +b2clusters=$(( (val2T/2/1024/1024/8 + cluster - 1) / cluster )) +echo expected bitmap $((b1clusters * cluster + + (b1clusters * 8 + cluster - 1) / cluster * cluster + + b2clusters * cluster + + (b2clusters * 8 + cluster - 1) / cluster * cluster + + cluster)) +$QEMU_IMG measure -O qcow2 -o cluster_size=64k -f qcow2 "$TEST_IMG" + +# Compute expected output: bitmap clusters + bitmap tables + bitmaps directory +echo +cluster=$((2*1024*1024)) +b1clusters=$(( (val2T/512/8 + cluster - 1) / cluster )) +b2clusters=$(( (val2T/2/1024/1024/8 + cluster - 1) / cluster )) +echo expected bitmap $((b1clusters * cluster + + (b1clusters * 8 + cluster - 1) / cluster * cluster + + b2clusters * cluster + + (b2clusters * 8 + cluster - 1) / cluster * cluster + + cluster)) +$QEMU_IMG measure --output=json -O qcow2 -o cluster_size=2M -f qcow2 "$TEST_IMG" + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/190.out b/tests/qemu-iotests/190.out index d001942002db401621537266a55b26f95944e9d4..ed9d8214eb62ce6767aece88497f11919cb1a9a8 100644 --- a/tests/qemu-iotests/190.out +++ b/tests/qemu-iotests/190.out @@ -1,11 +1,36 @@ QA output created by 190 -== Huge file == +== Huge file without bitmaps == Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2199023255552 required size: 2199023255552 fully allocated size: 2199023255552 required size: 335806464 fully allocated size: 2199359062016 +bitmaps size: 0 required size: 18874368 fully allocated size: 2199042129920 +bitmaps size: 0 + +== Huge file with bitmaps == + +required size: 327680 +fully allocated size: 10813440 +required size: 2199023255552 +fully allocated size: 2199023255552 +required size: SIZE +fully allocated size: 17170432 +required size: 335806464 +fully allocated size: 2199359062016 + +expected bitmap 537198592 +required size: 335806464 +fully allocated size: 2199359062016 +bitmaps size: 537198592 + +expected bitmap 545259520 +{ + "bitmaps": 545259520, + "required": 18874368, + "fully-allocated": 2199042129920 +} *** done diff --git a/tests/qemu-iotests/191 b/tests/qemu-iotests/191 index b05db6814157f0bed29004b0dd8df521c18f0d4f..d17462e1e42baac0a59603918ec87506b58eda03 100755 --- a/tests/qemu-iotests/191 +++ b/tests/qemu-iotests/191 @@ -54,8 +54,8 @@ echo TEST_IMG="${TEST_IMG}.base" _make_test_img $size TEST_IMG="${TEST_IMG}.mid" _make_test_img -o "backing_fmt=$IMGFMT" -b "${TEST_IMG}.base" -_make_test_img -b "${TEST_IMG}.mid" -TEST_IMG="${TEST_IMG}.ovl2" _make_test_img -b "${TEST_IMG}.mid" +_make_test_img -b "${TEST_IMG}.mid" -F $IMGFMT +TEST_IMG="${TEST_IMG}.ovl2" _make_test_img -b "${TEST_IMG}.mid" -F $IMGFMT $QEMU_IO -c 'write -P 0x55 1M 64k' "${TEST_IMG}.mid" | _filter_qemu_io @@ -102,10 +102,10 @@ echo === Preparing and starting VM with -drive === echo TEST_IMG="${TEST_IMG}.base" _make_test_img $size -TEST_IMG="${TEST_IMG}.mid" _make_test_img -b "${TEST_IMG}.base" -_make_test_img -b "${TEST_IMG}.mid" -TEST_IMG="${TEST_IMG}.ovl2" _make_test_img -b "${TEST_IMG}.mid" -TEST_IMG="${TEST_IMG}.ovl3" _make_test_img -b "${TEST_IMG}.ovl2" +TEST_IMG="${TEST_IMG}.mid" _make_test_img -b "${TEST_IMG}.base" -F $IMGFMT +_make_test_img -b "${TEST_IMG}.mid" -F $IMGFMT +TEST_IMG="${TEST_IMG}.ovl2" _make_test_img -b "${TEST_IMG}.mid" -F $IMGFMT +TEST_IMG="${TEST_IMG}.ovl3" _make_test_img -b "${TEST_IMG}.ovl2" -F $IMGFMT $QEMU_IO -c 'write -P 0x55 1M 64k' "${TEST_IMG}.mid" | _filter_qemu_io diff --git a/tests/qemu-iotests/191.out b/tests/qemu-iotests/191.out index 34cec7b9ecf34570bd196cd8826a97ac41fb5f0d..11aaf3b691fd23797a7dd0cbd4c223fc54d23e35 100644 --- a/tests/qemu-iotests/191.out +++ b/tests/qemu-iotests/191.out @@ -4,8 +4,8 @@ QA output created by 191 Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 Formatting 'TEST_DIR/t.IMGFMT.mid', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid -Formatting 'TEST_DIR/t.IMGFMT.ovl2', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT.ovl2', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid backing_fmt=IMGFMT wrote 65536/65536 bytes at offset 1048576 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { 'execute': 'qmp_capabilities' } @@ -413,10 +413,10 @@ backing file format: IMGFMT === Preparing and starting VM with -drive === Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT.mid', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid -Formatting 'TEST_DIR/t.IMGFMT.ovl2', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid -Formatting 'TEST_DIR/t.IMGFMT.ovl3', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.ovl2 +Formatting 'TEST_DIR/t.IMGFMT.mid', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT.ovl2', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT.ovl3', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.ovl2 backing_fmt=IMGFMT wrote 65536/65536 bytes at offset 1048576 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { 'execute': 'qmp_capabilities' } diff --git a/tests/qemu-iotests/194 b/tests/qemu-iotests/194 index 8b1f720af4d867aabb000085f32c96fc0eede558..7a4863ab180865fe54748cd9d07e72d01448086c 100755 --- a/tests/qemu-iotests/194 +++ b/tests/qemu-iotests/194 @@ -26,8 +26,8 @@ iotests.script_initialize(supported_fmts=['qcow2', 'qed', 'raw'], with iotests.FilePath('source.img') as source_img_path, \ iotests.FilePath('dest.img') as dest_img_path, \ - iotests.FilePaths(['migration.sock', 'nbd.sock'], iotests.sock_dir) as \ - [migration_sock_path, nbd_sock_path], \ + iotests.FilePath('migration.sock', 'nbd.sock', base_dir=iotests.sock_dir) \ + as (migration_sock_path, nbd_sock_path), \ iotests.VM('source') as source_vm, \ iotests.VM('dest') as dest_vm: @@ -42,6 +42,8 @@ with iotests.FilePath('source.img') as source_img_path, \ .add_incoming('unix:{0}'.format(migration_sock_path)) .launch()) + source_vm.qmp_log('block-dirty-bitmap-add', node='drive0', name='bitmap0') + iotests.log('Launching NBD server on destination...') iotests.log(dest_vm.qmp('nbd-server-start', addr={'type': 'unix', 'data': {'path': nbd_sock_path}})) iotests.log(dest_vm.qmp('nbd-server-add', device='drive0', writable=True)) @@ -61,12 +63,14 @@ with iotests.FilePath('source.img') as source_img_path, \ filters=[iotests.filter_qmp_event]) iotests.log('Starting migration...') - source_vm.qmp('migrate-set-capabilities', - capabilities=[{'capability': 'events', 'state': True}]) - dest_vm.qmp('migrate-set-capabilities', - capabilities=[{'capability': 'events', 'state': True}]) + capabilities = [{'capability': 'events', 'state': True}, + {'capability': 'dirty-bitmaps', 'state': True}] + source_vm.qmp('migrate-set-capabilities', capabilities=capabilities) + dest_vm.qmp('migrate-set-capabilities', capabilities=capabilities) iotests.log(source_vm.qmp('migrate', uri='unix:{0}'.format(migration_sock_path))) + source_vm.qmp_log('migrate-start-postcopy') + while True: event1 = source_vm.event_wait('MIGRATION') iotests.log(event1, filters=[iotests.filter_qmp_event]) @@ -82,3 +86,15 @@ with iotests.FilePath('source.img') as source_img_path, \ iotests.log('Stopping the NBD server on destination...') iotests.log(dest_vm.qmp('nbd-server-stop')) break + + iotests.log('Wait for migration completion on target...') + migr_events = (('MIGRATION', {'data': {'status': 'completed'}}), + ('MIGRATION', {'data': {'status': 'failed'}})) + event = dest_vm.events_wait(migr_events) + iotests.log(event, filters=[iotests.filter_qmp_event]) + + iotests.log('Check bitmaps on source:') + iotests.log(source_vm.qmp('query-block')['return'][0]['dirty-bitmaps']) + + iotests.log('Check bitmaps on target:') + iotests.log(dest_vm.qmp('query-block')['return'][0]['dirty-bitmaps']) diff --git a/tests/qemu-iotests/194.out b/tests/qemu-iotests/194.out index 71857853fb4de10f623b41d04e6da07ff94becea..a51bdb2d4fc94c3dbe39bd741651eb55ef5b1619 100644 --- a/tests/qemu-iotests/194.out +++ b/tests/qemu-iotests/194.out @@ -1,4 +1,6 @@ Launching VMs... +{"execute": "block-dirty-bitmap-add", "arguments": {"name": "bitmap0", "node": "drive0"}} +{"return": {}} Launching NBD server on destination... {"return": {}} {"return": {}} @@ -8,11 +10,20 @@ Waiting for `drive-mirror` to complete... {"data": {"device": "mirror-job0", "len": 1073741824, "offset": 1073741824, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} Starting migration... {"return": {}} +{"execute": "migrate-start-postcopy", "arguments": {}} +{"return": {}} {"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} {"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"status": "postcopy-active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} {"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} Gracefully ending the `drive-mirror` job on source... {"return": {}} {"data": {"device": "mirror-job0", "len": 1073741824, "offset": 1073741824, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} Stopping the NBD server on destination... {"return": {}} +Wait for migration completion on target... +{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +Check bitmaps on source: +[{"busy": false, "count": 0, "granularity": 65536, "name": "bitmap0", "persistent": false, "recording": true, "status": "active"}] +Check bitmaps on target: +[{"busy": false, "count": 0, "granularity": 65536, "name": "bitmap0", "persistent": false, "recording": true, "status": "active"}] diff --git a/tests/qemu-iotests/195 b/tests/qemu-iotests/195 index 48984b7ac1ed9ce020b98ff092d82f207a8c7e77..2351d55fe1f1ed174ed6b0572e54e959492613a3 100755 --- a/tests/qemu-iotests/195 +++ b/tests/qemu-iotests/195 @@ -56,8 +56,8 @@ run_qemu() size=64M TEST_IMG="$TEST_IMG.base" _make_test_img $size -TEST_IMG="$TEST_IMG.mid" _make_test_img -b "$TEST_IMG.base" -_make_test_img -b "$TEST_IMG.mid" +TEST_IMG="$TEST_IMG.mid" _make_test_img -b "$TEST_IMG.base" -F $IMGFMT +_make_test_img -b "$TEST_IMG.mid" -F $IMGFMT echo echo "Change backing file of mid (opened read-only)" @@ -75,7 +75,7 @@ echo echo "Change backing file of top (opened writable)" echo -TEST_IMG="$TEST_IMG.mid" _make_test_img -b "$TEST_IMG.base" +TEST_IMG="$TEST_IMG.mid" _make_test_img -b "$TEST_IMG.base" -F $IMGFMT run_qemu -drive if=none,file="$TEST_IMG",node-name=top < 1: - time.sleep(2) - result = self.vm_b.qmp('query-block'); + match = {'data': {'status': 'completed'}} + e_complete = self.vm_b.event_wait('MIGRATION', match=match) + self.vm_b_events.append(e_complete) - result = self.vm_b.qmp('x-debug-block-dirty-bitmap-sha256', - node='drive0', name='bitmap') + check_bitmaps(self.vm_a, 0) + check_bitmaps(self.vm_b, 0) - self.assert_qmp(result, 'return/sha256', sha256); if __name__ == '__main__': - iotests.main(supported_fmts=['qcow2'], supported_cache_modes=['none'], - supported_protocols=['file']) + iotests.main(supported_fmts=['qcow2']) diff --git a/tests/qemu-iotests/199.out b/tests/qemu-iotests/199.out index ae1213e6f86322c94cf822305444a7316c3b9cab..8d7e996700935285e77f1c1156959cc27a7931bf 100644 --- a/tests/qemu-iotests/199.out +++ b/tests/qemu-iotests/199.out @@ -1,5 +1,5 @@ -. +... ---------------------------------------------------------------------- -Ran 1 tests +Ran 3 tests OK diff --git a/tests/qemu-iotests/204 b/tests/qemu-iotests/204 index abb73dc381c99ddb5e36192abb608f5644c27ed2..6770fa9b96369f38111aa595c8200b3486e145bd 100755 --- a/tests/qemu-iotests/204 +++ b/tests/qemu-iotests/204 @@ -52,7 +52,7 @@ echo "== setting up files ==" TEST_IMG="$TEST_IMG.base" _make_test_img $size $QEMU_IO -c "write -P 11 0 $size" "$TEST_IMG.base" | _filter_qemu_io -_make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $QEMU_IO -c "write -P 22 0 110M" "$TEST_IMG" | _filter_qemu_io # Limited to 64k max-transfer diff --git a/tests/qemu-iotests/204.out b/tests/qemu-iotests/204.out index f3a10fbe90356f707efd209c682b557ed9005920..4d903d20eaaefb968b93687c40fd28ca96724aa3 100644 --- a/tests/qemu-iotests/204.out +++ b/tests/qemu-iotests/204.out @@ -4,7 +4,7 @@ QA output created by 204 Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 wrote 134217728/134217728 bytes at offset 0 128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT wrote 115343360/115343360 bytes at offset 0 110 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -59,5 +59,6 @@ Offset Length File 0x900000 0x2400000 TEST_DIR/t.IMGFMT 0x3c00000 0x1100000 TEST_DIR/t.IMGFMT 0x6a00000 0x400000 TEST_DIR/t.IMGFMT +0x6e00000 0x1200000 TEST_DIR/t.IMGFMT.base No errors were found on the image. *** done diff --git a/tests/qemu-iotests/206 b/tests/qemu-iotests/206 index f42432a8388586951b7b2e34454c268d4af7dd9e..11bc51f25602c081462898edc8213602af39db9e 100755 --- a/tests/qemu-iotests/206 +++ b/tests/qemu-iotests/206 @@ -24,6 +24,7 @@ import iotests from iotests import imgfmt iotests.script_initialize(supported_fmts=['qcow2']) +iotests.verify_working_luks() with iotests.FilePath('t.qcow2') as disk_path, \ iotests.FilePath('t.qcow2.base') as backing_path, \ diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out index 1a14255a8342f70f764c4f18e4626f5f0aec30b4..a100849fcb487daa91ea39f5332ee9fc67a15f23 100644 --- a/tests/qemu-iotests/206.out +++ b/tests/qemu-iotests/206.out @@ -22,6 +22,7 @@ Format specific information: lazy refcounts: false refcount bits: 16 corrupt: false + extended l2: false === Successful image creation (inline blockdev-add, explicit defaults) === @@ -45,6 +46,7 @@ Format specific information: lazy refcounts: false refcount bits: 16 corrupt: false + extended l2: false === Successful image creation (v3 non-default options) === @@ -68,6 +70,7 @@ Format specific information: lazy refcounts: true refcount bits: 1 corrupt: false + extended l2: false === Successful image creation (v2 non-default options) === @@ -146,6 +149,7 @@ Format specific information: payload offset: 528384 master key iters: XXX corrupt: false + extended l2: false === Invalid BlockdevRef === @@ -199,7 +203,7 @@ Job failed: Different refcount widths than 16 bits require compatibility level 1 === Invalid backing file options === {"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", "preallocation": "full", "size": 67108864}}} {"return": {}} -Job failed: Backing file and preallocation cannot be used at the same time +Job failed: Backing file and preallocation can only be used at the same time if extended_l2 is on {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} diff --git a/tests/qemu-iotests/208 b/tests/qemu-iotests/208 index 6cb642f8219e954c11771e0b16992fd1bc094a93..54aa4be2734c889bbdcbe1f66f06ff59684fca65 100755 --- a/tests/qemu-iotests/208 +++ b/tests/qemu-iotests/208 @@ -26,7 +26,7 @@ iotests.script_initialize(supported_fmts=['generic']) with iotests.FilePath('disk.img') as disk_img_path, \ iotests.FilePath('disk-snapshot.img') as disk_snapshot_img_path, \ - iotests.FilePath('nbd.sock', iotests.sock_dir) as nbd_sock_path, \ + iotests.FilePath('nbd.sock', base_dir=iotests.sock_dir) as nbd_sock_path, \ iotests.VM() as vm: img_size = '10M' diff --git a/tests/qemu-iotests/216 b/tests/qemu-iotests/216 index de11d85b5dd5adb049cf666a603e98f30a92b5d8..f93c61aad665a9bc1fa04106be94e72c7fc4c87d 100755 --- a/tests/qemu-iotests/216 +++ b/tests/qemu-iotests/216 @@ -53,7 +53,7 @@ with iotests.FilePath('base.img') as base_img_path, \ assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0 assert qemu_io_silent(base_img_path, '-c', 'write -P 1 0M 1M') == 0 assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path, - top_img_path) == 0 + '-F', iotests.imgfmt, top_img_path) == 0 assert qemu_io_silent(top_img_path, '-c', 'write -P 2 1M 1M') == 0 log('Done') diff --git a/tests/qemu-iotests/222 b/tests/qemu-iotests/222 index 6602f6b4ba324587735160cba8cc546ef7020bd1..14d67c875bd881b628b7c2bbbecc7ab55fbf6023 100755 --- a/tests/qemu-iotests/222 +++ b/tests/qemu-iotests/222 @@ -49,7 +49,7 @@ remainder = [("0xd5", "0x108000", "32k"), # Right-end of partial-left [1] with iotests.FilePath('base.img') as base_img_path, \ iotests.FilePath('fleece.img') as fleece_img_path, \ - iotests.FilePath('nbd.sock', iotests.sock_dir) as nbd_sock_path, \ + iotests.FilePath('nbd.sock', base_dir=iotests.sock_dir) as nbd_sock_path, \ iotests.VM() as vm: log('--- Setting up images ---') diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out index e1eaaedb55b3f6538c40c845afba9ec57c64b002..f6eac23f04cd26409f5048eb2a2899b60cd77452 100644 --- a/tests/qemu-iotests/223.out +++ b/tests/qemu-iotests/223.out @@ -45,7 +45,7 @@ exports available: 0 {"execute":"nbd-server-add", "arguments":{"device":"nosuch"}} {"error": {"class": "GenericError", "desc": "Cannot find device=nosuch nor node_name=nosuch"}} {"execute":"nbd-server-add", "arguments":{"device":"n"}} -{"error": {"class": "GenericError", "desc": "NBD server already has export named 'n'"}} +{"error": {"class": "GenericError", "desc": "Block export id 'n' is already in use"}} {"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "bitmap":"b2"}} {"error": {"class": "GenericError", "desc": "Enabled bitmap 'b2' incompatible with readonly export"}} {"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "bitmap":"b3"}} @@ -102,8 +102,10 @@ read 2097152/2097152 bytes at offset 2097152 {"execute":"nbd-server-remove", "arguments":{"name":"n"}} {"return": {}} {"execute":"nbd-server-remove", "arguments":{"name":"n2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n"}} {"return": {}} {"execute":"nbd-server-remove", "arguments":{"name":"n2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}} {"error": {"class": "GenericError", "desc": "Export 'n2' is not found"}} {"execute":"nbd-server-stop"} {"return": {}} @@ -126,7 +128,7 @@ exports available: 0 {"execute":"nbd-server-add", "arguments":{"device":"nosuch"}} {"error": {"class": "GenericError", "desc": "Cannot find device=nosuch nor node_name=nosuch"}} {"execute":"nbd-server-add", "arguments":{"device":"n"}} -{"error": {"class": "GenericError", "desc": "NBD server already has export named 'n'"}} +{"error": {"class": "GenericError", "desc": "Block export id 'n' is already in use"}} {"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "bitmap":"b2"}} {"error": {"class": "GenericError", "desc": "Enabled bitmap 'b2' incompatible with readonly export"}} {"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "bitmap":"b3"}} @@ -183,8 +185,10 @@ read 2097152/2097152 bytes at offset 2097152 {"execute":"nbd-server-remove", "arguments":{"name":"n"}} {"return": {}} {"execute":"nbd-server-remove", "arguments":{"name":"n2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n"}} {"return": {}} {"execute":"nbd-server-remove", "arguments":{"name":"n2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}} {"error": {"class": "GenericError", "desc": "Export 'n2' is not found"}} {"execute":"nbd-server-stop"} {"return": {}} diff --git a/tests/qemu-iotests/224 b/tests/qemu-iotests/224 index 81ca1e48984ff0b107bdbf4967a6e6996c663bdd..017b0685ba15bc98262771513a49173da4ffa416 100755 --- a/tests/qemu-iotests/224 +++ b/tests/qemu-iotests/224 @@ -49,9 +49,9 @@ for filter_node_name in False, True: assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0 assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path, - mid_img_path) == 0 + '-F', iotests.imgfmt, mid_img_path) == 0 assert qemu_img('create', '-f', iotests.imgfmt, '-b', mid_img_path, - top_img_path) == 0 + '-F', iotests.imgfmt, top_img_path) == 0 # Something to commit assert qemu_io_silent(mid_img_path, '-c', 'write -P 1 0 1M') == 0 diff --git a/tests/qemu-iotests/225 b/tests/qemu-iotests/225 index c9a334c7e998949b9715d2f0e11a0dcefde4e638..0186ec8156606560335f45bb13cffa43910db6da 100755 --- a/tests/qemu-iotests/225 +++ b/tests/qemu-iotests/225 @@ -48,7 +48,7 @@ _unsupported_imgopts "subformat=monolithicFlat" \ TEST_IMG="$TEST_IMG.base" _make_test_img 1M TEST_IMG="$TEST_IMG.not_base" _make_test_img 1M -_make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT make_opts() { diff --git a/tests/qemu-iotests/225.out b/tests/qemu-iotests/225.out index 4dc8ee282fad78722f8f5e5260e72746a0a85d2e..0998ae094c2b85c28aee25fd7e1c7250d0ece7e5 100644 --- a/tests/qemu-iotests/225.out +++ b/tests/qemu-iotests/225.out @@ -1,7 +1,7 @@ QA output created by 225 Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1048576 Formatting 'TEST_DIR/t.IMGFMT.not_base', fmt=IMGFMT size=1048576 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT === Testing fitting VMDK backing image === diff --git a/tests/qemu-iotests/228 b/tests/qemu-iotests/228 index da0900fb82aa7626068ee6952fc097f5fa023c60..266fce6cda2c59faa0cea8f7bfaa9a74a0254f13 100755 --- a/tests/qemu-iotests/228 +++ b/tests/qemu-iotests/228 @@ -36,7 +36,7 @@ def log_node_info(node): log('bs->filename: ' + node['image']['filename'], filters=[filter_testfiles, filter_imgfmt]) - log('bs->backing_file: ' + node['backing_file'], + log('bs->backing_file: ' + node['image']['full-backing-filename'], filters=[filter_testfiles, filter_imgfmt]) if 'backing-image' in node['image']: @@ -56,7 +56,8 @@ with iotests.FilePath('base.img') as base_img_path, \ assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0 # Choose a funny way to describe the backing filename assert qemu_img('create', '-f', iotests.imgfmt, '-b', - 'file:' + base_img_path, top_img_path) == 0 + 'file:' + base_img_path, '-F', iotests.imgfmt, + top_img_path) == 0 vm.launch() @@ -72,8 +73,8 @@ with iotests.FilePath('base.img') as base_img_path, \ }, filters=[filter_qmp_testfiles, filter_qmp_imgfmt]) - # Filename should be plain, and the backing filename should not - # contain the "file:" prefix + # Filename should be plain, and the backing node filename should + # not contain the "file:" prefix log_node_info(vm.node_info('node0')) vm.qmp_log('blockdev-del', node_name='node0') @@ -171,7 +172,7 @@ with iotests.FilePath('base.img') as base_img_path, \ # filename unless the backing file is opened implicitly with the # overlay) assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path, - top_img_path) == 0 + '-F', iotests.imgfmt, top_img_path) == 0 # You can only reliably override backing options by using a node # reference (or by specifying file.filename, but, well...) diff --git a/tests/qemu-iotests/228.out b/tests/qemu-iotests/228.out index 4217df24fe8666f68203d397298760fa746c45d6..8c82009abed140b1146aa4d6a4e7815b2bbc9cbf 100644 --- a/tests/qemu-iotests/228.out +++ b/tests/qemu-iotests/228.out @@ -4,7 +4,7 @@ {"return": {}} bs->filename: TEST_DIR/PID-top.img -bs->backing_file: TEST_DIR/PID-base.img +bs->backing_file: file:TEST_DIR/PID-base.img bs->backing->bs->filename: TEST_DIR/PID-base.img {"execute": "blockdev-del", "arguments": {"node-name": "node0"}} @@ -41,7 +41,7 @@ bs->backing->bs->filename: TEST_DIR/PID-base.img {"return": {}} bs->filename: TEST_DIR/PID-top.img -bs->backing_file: TEST_DIR/PID-base.img +bs->backing_file: file:TEST_DIR/PID-base.img bs->backing->bs->filename: TEST_DIR/PID-base.img {"execute": "blockdev-del", "arguments": {"node-name": "node0"}} @@ -55,7 +55,7 @@ bs->backing->bs->filename: TEST_DIR/PID-base.img {"return": {}} bs->filename: json:{"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}} -bs->backing_file: null-co:// +bs->backing_file: TEST_DIR/PID-base.img bs->backing->bs->filename: null-co:// {"execute": "blockdev-del", "arguments": {"node-name": "node0"}} diff --git a/tests/qemu-iotests/229 b/tests/qemu-iotests/229 index 99acb55ebb03b2d8328ea5bfc3b1143698a9624f..89a5359f3286eb9b17b6365997d5e682fe52c893 100755 --- a/tests/qemu-iotests/229 +++ b/tests/qemu-iotests/229 @@ -46,6 +46,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 qed _supported_proto file _supported_os Linux +# blkdebug can only inject errors on bs->file, so external data files +# do not work with this test +_unsupported_imgopts data_file DEST_IMG="$TEST_DIR/d.$IMGFMT" diff --git a/tests/qemu-iotests/240 b/tests/qemu-iotests/240 index 8b4337b58dd05cccab3c47b1706256e7e794dad6..c0f71f0461f6862632fbfc2846a8236de0c3816b 100755 --- a/tests/qemu-iotests/240 +++ b/tests/qemu-iotests/240 @@ -1,5 +1,5 @@ -#!/usr/bin/env bash -# +#!/usr/bin/env python3 + # Test hot plugging and unplugging with iothreads # # Copyright (C) 2019 Igalia, S.L. @@ -17,133 +17,90 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -# -# creator -owner=berto@igalia.com - -seq=`basename $0` -echo "QA output created by $seq" - -status=1 # failure is the default! - -_cleanup() -{ - rm -f "$SOCK_DIR/nbd" -} -trap "_cleanup; exit \$status" 0 1 2 3 15 - -# get standard environment, filters and checks -. ./common.rc -. ./common.filter - -_supported_fmt generic -_supported_proto generic - -do_run_qemu() -{ - echo Testing: "$@" - $QEMU -nographic -qmp stdio -serial none "$@" - echo -} - -# Remove QMP events from (pretty-printed) output. Doesn't handle -# nested dicts correctly, but we don't get any of those in this test. -_filter_qmp_events() -{ - tr '\n' '\t' | sed -e \ - 's/{\s*"timestamp":\s*{[^}]*},\s*"event":[^,}]*\(,\s*"data":\s*{[^}]*}\)\?\s*}\s*//g' \ - | tr '\t' '\n' -} - -run_qemu() -{ - do_run_qemu "$@" 2>&1 | _filter_qmp | _filter_qmp_events -} - -case "$QEMU_DEFAULT_MACHINE" in - s390-ccw-virtio) - virtio_scsi=virtio-scsi-ccw - ;; - *) - virtio_scsi=virtio-scsi-pci - ;; -esac - -echo -echo === Unplug a SCSI disk and then plug it again === -echo - -run_qemu < {:s}, {:s}'.format( image, reference, @@ -274,10 +275,9 @@ def test_bitmap_sync(bsync_mode, msync_mode='bitmap', failure=None): an incomplete backup. Testing limitations prevent testing competing writes. """ - with iotests.FilePaths(['img', 'bsync1', 'bsync2', - 'fbackup0', 'fbackup1', 'fbackup2']) as \ - (img_path, bsync1, bsync2, - fbackup0, fbackup1, fbackup2), \ + with iotests.FilePath( + 'img', 'bsync1', 'bsync2', 'fbackup0', 'fbackup1', 'fbackup2') as \ + (img_path, bsync1, bsync2, fbackup0, fbackup1, fbackup2), \ iotests.VM() as vm: mode = "Mode {:s}; Bitmap Sync {:s}".format(msync_mode, bsync_mode) @@ -440,8 +440,7 @@ def test_backup_api(): """ Test malformed and prohibited invocations of the backup API. """ - with iotests.FilePaths(['img', 'bsync1']) as \ - (img_path, backup_path), \ + with iotests.FilePath('img', 'bsync1') as (img_path, backup_path), \ iotests.VM() as vm: log("\n=== API failure tests ===\n") diff --git a/tests/qemu-iotests/259.out b/tests/qemu-iotests/259.out index ffed19c2a0af4a484bd110f3ac17b5258a25604d..1aaadfda4ead5f836bc7445721b2df7202d417d1 100644 --- a/tests/qemu-iotests/259.out +++ b/tests/qemu-iotests/259.out @@ -9,6 +9,6 @@ virtual size: 64 MiB (67108864 bytes) disk size: unavailable --- Testing creation for which the node would need to grow --- -qemu-img: TEST_DIR/t.IMGFMT: Could not resize image: Image format driver does not support resize Formatting 'TEST_DIR/t.IMGFMT', fmt=qcow2 size=67108864 preallocation=metadata +qemu-img: TEST_DIR/t.IMGFMT: Could not resize image: Cannot grow NBD nodes *** done diff --git a/tests/qemu-iotests/261 b/tests/qemu-iotests/261 index ddcb04f285dfd49d4bab23d173366f91ad19fbce..847b4c6a3752b8b808a36d3304bf06cc73be26ce 100755 --- a/tests/qemu-iotests/261 +++ b/tests/qemu-iotests/261 @@ -91,7 +91,10 @@ print_snapshot_table() if [ $extra_len -ge 16 ]; then echo " Disk size: $(peek_file_be "$1" $((extra_ofs + 8)) 8)" fi - if [ $extra_len -gt 16 ]; then + if [ $extra_len -ge 24 ]; then + echo " Icount: $(peek_file_be "$1" $((extra_ofs + 16)) 8)" + fi + if [ $extra_len -gt 24 ]; then echo ' Unknown extra data:' \ "$(peek_file_raw "$1" $((extra_ofs + 16)) $((extra_len - 16)) \ | tr -d '\0')" @@ -198,12 +201,12 @@ truncate -s 0 "$TEST_DIR/sn0-extra" truncate -s $(($(snapshot_table_entry_size "$TEST_DIR/sn0-pre") - 40)) \ "$TEST_DIR/sn0-post" -# Set sn1's extra data size to 42 -poke_file "$TEST_DIR/sn1-pre" 36 '\x00\x00\x00\x2a' -truncate -s 42 "$TEST_DIR/sn1-extra" -poke_file "$TEST_DIR/sn1-extra" 16 'very important data' +# Set sn1's extra data size to 50 +poke_file "$TEST_DIR/sn1-pre" 36 '\x00\x00\x00\x32' +truncate -s 50 "$TEST_DIR/sn1-extra" +poke_file "$TEST_DIR/sn1-extra" 24 'very important data' # Grow sn1-post to pad -truncate -s $(($(snapshot_table_entry_size "$TEST_DIR/sn1-pre") - 82)) \ +truncate -s $(($(snapshot_table_entry_size "$TEST_DIR/sn1-pre") - 90)) \ "$TEST_DIR/sn1-post" # Set sn2's extra data size to 8 @@ -389,7 +392,7 @@ _check_test_img -r all echo echo "$((sn_count - 1)) snapshots should remain:" -echo " qemu-img info reports $(_img_info | grep -c '^ \{34\}') snapshots" +echo " qemu-img info reports $(_img_info | grep -c '^ \{32\}') snapshots" echo " Image header reports $(peek_file_be "$TEST_IMG" 60 4) snapshots" echo @@ -516,7 +519,7 @@ _check_test_img -r all echo echo '65536 snapshots should remain:' -echo " qemu-img info reports $(_img_info | grep -c '^ \{34\}') snapshots" +echo " qemu-img info reports $(_img_info | grep -c '^ \{32\}') snapshots" echo " Image header reports $(peek_file_be "$TEST_IMG" 60 4) snapshots" # success, all done diff --git a/tests/qemu-iotests/261.out b/tests/qemu-iotests/261.out index 26003545661301a04827bce9654222903a148b42..612433ae40ad2bfc9771063d854c0333199c1516 100644 --- a/tests/qemu-iotests/261.out +++ b/tests/qemu-iotests/261.out @@ -12,9 +12,10 @@ Snapshots in TEST_DIR/t.IMGFMT.v2.orig: [1] ID: 2 Name: sn1 - Extra data size: 42 + Extra data size: 50 VM state size: 0 Disk size: 67108864 + Icount: 0 Unknown extra data: very important data [2] ID: 3 @@ -29,22 +30,25 @@ Snapshots in TEST_DIR/t.IMGFMT.v3.orig: [0] ID: 1 Name: sn0 - Extra data size: 16 + Extra data size: 24 VM state size: 0 Disk size: 67108864 + Icount: 18446744073709551615 [1] ID: 2 Name: sn1 - Extra data size: 42 + Extra data size: 50 VM state size: 0 Disk size: 67108864 + Icount: 0 Unknown extra data: very important data [2] ID: 3 Name: sn2 - Extra data size: 16 + Extra data size: 24 VM state size: 0 Disk size: 67108864 + Icount: 18446744073709551615 === Repair botched v3 === @@ -61,22 +65,25 @@ Snapshots in TEST_DIR/t.IMGFMT: [0] ID: 1 Name: sn0 - Extra data size: 16 + Extra data size: 24 VM state size: 0 Disk size: 67108864 + Icount: 18446744073709551615 [1] ID: 2 Name: sn1 - Extra data size: 42 + Extra data size: 50 VM state size: 0 Disk size: 67108864 + Icount: 0 Unknown extra data: very important data [2] ID: 3 Name: sn2 - Extra data size: 16 + Extra data size: 24 VM state size: 0 Disk size: 67108864 + Icount: 18446744073709551615 === Add new snapshot === @@ -85,28 +92,32 @@ Snapshots in TEST_DIR/t.IMGFMT: [0] ID: 1 Name: sn0 - Extra data size: 16 + Extra data size: 24 VM state size: 0 Disk size: 67108864 + Icount: 18446744073709551615 [1] ID: 2 Name: sn1 - Extra data size: 42 + Extra data size: 50 VM state size: 0 Disk size: 67108864 + Icount: 0 Unknown extra data: very important data [2] ID: 3 Name: sn2 - Extra data size: 16 + Extra data size: 24 VM state size: 0 Disk size: 67108864 + Icount: 18446744073709551615 [3] ID: 4 Name: sn3 - Extra data size: 16 + Extra data size: 24 VM state size: 0 Disk size: 67108864 + Icount: 0 === Remove different snapshots === @@ -116,16 +127,18 @@ Snapshots in TEST_DIR/t.IMGFMT: [0] ID: 2 Name: sn1 - Extra data size: 42 + Extra data size: 50 VM state size: 0 Disk size: 67108864 + Icount: 0 Unknown extra data: very important data [1] ID: 3 Name: sn2 - Extra data size: 16 + Extra data size: 24 VM state size: 0 Disk size: 67108864 + Icount: 18446744073709551615 --- sn1 --- No errors were found on the image. @@ -133,15 +146,17 @@ Snapshots in TEST_DIR/t.IMGFMT: [0] ID: 1 Name: sn0 - Extra data size: 16 + Extra data size: 24 VM state size: 0 Disk size: 67108864 + Icount: 18446744073709551615 [1] ID: 3 Name: sn2 - Extra data size: 16 + Extra data size: 24 VM state size: 0 Disk size: 67108864 + Icount: 18446744073709551615 --- sn2 --- No errors were found on the image. @@ -149,15 +164,17 @@ Snapshots in TEST_DIR/t.IMGFMT: [0] ID: 1 Name: sn0 - Extra data size: 16 + Extra data size: 24 VM state size: 0 Disk size: 67108864 + Icount: 18446744073709551615 [1] ID: 2 Name: sn1 - Extra data size: 42 + Extra data size: 50 VM state size: 0 Disk size: 67108864 + Icount: 0 Unknown extra data: very important data === Reject too much unknown extra data === diff --git a/tests/qemu-iotests/263 b/tests/qemu-iotests/263 index d2c030fae95f29a58b888c4b1bba8684a2485110..f598a128997453f0a7f1261e2059e12c458d70dc 100755 --- a/tests/qemu-iotests/263 +++ b/tests/qemu-iotests/263 @@ -40,6 +40,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto generic _supported_os Linux +_require_working_luks size=1M diff --git a/tests/qemu-iotests/263.out b/tests/qemu-iotests/263.out index 0c982c55cbc2aab01b7acf88b1c9399c01add777..54bfbeeff8a83e393053feedc2c41f3e03340721 100644 --- a/tests/qemu-iotests/263.out +++ b/tests/qemu-iotests/263.out @@ -2,7 +2,7 @@ QA output created by 263 testing LUKS qcow2 encryption -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 == reading the whole image == read 1048576/1048576 bytes at offset 0 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -21,7 +21,7 @@ read 982528/982528 bytes at offset 66048 testing legacy AES qcow2 encryption -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=aes encrypt.key-secret=sec0 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 == reading the whole image == read 1048576/1048576 bytes at offset 0 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/264 b/tests/qemu-iotests/264 index 304a7443d77f8e440e91b4f38d236720c5bf5bab..666f164ed8f473c6cd9e421ef3777a20b45b6ad5 100755 --- a/tests/qemu-iotests/264 +++ b/tests/qemu-iotests/264 @@ -36,48 +36,32 @@ wait_step = 0.2 qemu_img_create('-f', iotests.imgfmt, disk_a, str(size)) qemu_img_create('-f', iotests.imgfmt, disk_b, str(size)) -srv = qemu_nbd_popen('-k', nbd_sock, '-f', iotests.imgfmt, disk_b) -# Wait for NBD server availability -t = 0 -ok = False -while t < wait_limit: - ok = qemu_io_silent_check('-f', 'raw', '-c', 'read 0 512', nbd_uri) - if ok: - break - time.sleep(wait_step) - t += wait_step +with qemu_nbd_popen('-k', nbd_sock, '-f', iotests.imgfmt, disk_b): + vm = iotests.VM().add_drive(disk_a) + vm.launch() + vm.hmp_qemu_io('drive0', 'write 0 {}'.format(size)) + + vm.qmp_log('blockdev-add', filters=[iotests.filter_qmp_testfiles], + **{'node_name': 'backup0', + 'driver': 'raw', + 'file': {'driver': 'nbd', + 'server': {'type': 'unix', 'path': nbd_sock}, + 'reconnect-delay': 10}}) + vm.qmp_log('blockdev-backup', device='drive0', sync='full', target='backup0', + speed=(1 * 1024 * 1024)) + + # Wait for some progress + t = 0 + while t < wait_limit: + jobs = vm.qmp('query-block-jobs')['return'] + if jobs and jobs[0]['offset'] > 0: + break + time.sleep(wait_step) + t += wait_step -assert ok - -vm = iotests.VM().add_drive(disk_a) -vm.launch() -vm.hmp_qemu_io('drive0', 'write 0 {}'.format(size)) - -vm.qmp_log('blockdev-add', filters=[iotests.filter_qmp_testfiles], - **{'node_name': 'backup0', - 'driver': 'raw', - 'file': {'driver': 'nbd', - 'server': {'type': 'unix', 'path': nbd_sock}, - 'reconnect-delay': 10}}) -vm.qmp_log('blockdev-backup', device='drive0', sync='full', target='backup0', - speed=(1 * 1024 * 1024)) - -# Wait for some progress -t = 0 -while t < wait_limit: - jobs = vm.qmp('query-block-jobs')['return'] if jobs and jobs[0]['offset'] > 0: - break - time.sleep(wait_step) - t += wait_step - -if jobs and jobs[0]['offset'] > 0: - log('Backup job is started') - -log('Kill NBD server') -srv.kill() -srv.wait() + log('Backup job is started') jobs = vm.qmp('query-block-jobs')['return'] if jobs and jobs[0]['offset'] < jobs[0]['len']: @@ -88,12 +72,8 @@ vm.qmp_log('block-job-set-speed', device='drive0', speed=0) # Emulate server down time for 1 second time.sleep(1) -log('Start NBD server') -srv = qemu_nbd_popen('-k', nbd_sock, '-f', iotests.imgfmt, disk_b) - -e = vm.event_wait('BLOCK_JOB_COMPLETED') -log('Backup completed: {}'.format(e['data']['offset'])) - -vm.qmp_log('blockdev-del', node_name='backup0') -srv.kill() -vm.shutdown() +with qemu_nbd_popen('-k', nbd_sock, '-f', iotests.imgfmt, disk_b): + e = vm.event_wait('BLOCK_JOB_COMPLETED') + log('Backup completed: {}'.format(e['data']['offset'])) + vm.qmp_log('blockdev-del', node_name='backup0') + vm.shutdown() diff --git a/tests/qemu-iotests/264.out b/tests/qemu-iotests/264.out index 3000944b099a02edeb8bd1f066e955189aed43a0..c45b1e81ef26360102397a67ed01685403d3008f 100644 --- a/tests/qemu-iotests/264.out +++ b/tests/qemu-iotests/264.out @@ -1,3 +1,4 @@ +Start NBD server {"execute": "blockdev-add", "arguments": {"driver": "raw", "file": {"driver": "nbd", "reconnect-delay": 10, "server": {"path": "TEST_DIR/PID-nbd-sock", "type": "unix"}}, "node-name": "backup0"}} {"return": {}} {"execute": "blockdev-backup", "arguments": {"device": "drive0", "speed": 1048576, "sync": "full", "target": "backup0"}} @@ -11,3 +12,4 @@ Start NBD server Backup completed: 5242880 {"execute": "blockdev-del", "arguments": {"node-name": "backup0"}} {"return": {}} +Kill NBD server diff --git a/tests/qemu-iotests/267 b/tests/qemu-iotests/267 index 3146273eef3335a15cdc8f576148349c9b2fbbd9..e44be49c771d4604567ed9bb29858a8a30707695 100755 --- a/tests/qemu-iotests/267 +++ b/tests/qemu-iotests/267 @@ -73,7 +73,7 @@ size=128M run_test() { if [ -n "$BACKING_FILE" ]; then - _make_test_img -b "$BACKING_FILE" $size + _make_test_img -b "$BACKING_FILE" -F $IMGFMT $size else _make_test_img $size fi @@ -149,7 +149,7 @@ echo echo "=== -blockdev with NBD server on the backing file ===" echo -_make_test_img -b "$TEST_IMG.base" $size +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $size cat < +# +# 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=berto@igalia.com + +seq="$(basename $0)" +echo "QA output created by $seq" + +here="$PWD" +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img + rm -f "$TEST_IMG.raw" +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto file nfs +_supported_os Linux +_unsupported_imgopts extended_l2 compat=0.10 cluster_size data_file refcount_bits=1[^0-9] + +l2_offset=$((0x40000)) + +_verify_img() +{ + $QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.raw" | grep -v 'Images are identical' + $QEMU_IMG check "$TEST_IMG" | _filter_qemu_img_check | \ + grep -v 'No errors were found on the image' +} + +# Compare the bitmap of an extended L2 entry against an expected value +_verify_l2_bitmap() +{ + entry_no="$1" # L2 entry number, starting from 0 + expected_alloc="$alloc" # Space-separated list of allocated subcluster indexes + expected_zero="$zero" # Space-separated list of zero subcluster indexes + + offset=$(($l2_offset + $entry_no * 16)) + entry=$(peek_file_be "$TEST_IMG" $offset 8) + offset=$(($offset + 8)) + bitmap=$(peek_file_be "$TEST_IMG" $offset 8) + + expected_bitmap=0 + for bit in $expected_alloc; do + expected_bitmap=$(($expected_bitmap | (1 << $bit))) + done + for bit in $expected_zero; do + expected_bitmap=$(($expected_bitmap | (1 << (32 + $bit)))) + done + printf -v expected_bitmap "%u" $expected_bitmap # Convert to unsigned + + printf "L2 entry #%d: 0x%016x %016x\n" "$entry_no" "$entry" "$bitmap" + if [ "$bitmap" != "$expected_bitmap" ]; then + printf "ERROR: expecting bitmap 0x%016x\n" "$expected_bitmap" + fi +} + +# This should be called as _run_test c=XXX sc=XXX off=XXX len=XXX cmd=XXX +# c: cluster number (0 if unset) +# sc: subcluster number inside cluster @c (0 if unset) +# off: offset inside subcluster @sc, in kilobytes (0 if unset) +# len: request length, passed directly to qemu-io (e.g: 256, 4k, 1M, ...) +# cmd: the command to pass to qemu-io, must be one of +# write -> write +# zero -> write -z +# unmap -> write -z -u +# compress -> write -c +# discard -> discard +_run_test() +{ + unset c sc off len cmd + for var in "$@"; do eval "$var"; done + case "${cmd:-write}" in + zero) + cmd="write -q -z";; + unmap) + cmd="write -q -z -u";; + compress) + pat=$((${pat:-0} + 1)) + cmd="write -q -c -P ${pat}";; + write) + pat=$((${pat:-0} + 1)) + cmd="write -q -P ${pat}";; + discard) + cmd="discard -q";; + *) + echo "Unknown option $cmd" + exit 1;; + esac + c="${c:-0}" + sc="${sc:-0}" + off="${off:-0}" + offset="$(($c * 64 + $sc * 2 + $off))" + [ "$offset" != 0 ] && offset="${offset}k" + cmd="$cmd ${offset} ${len}" + raw_cmd=$(echo $cmd | sed s/-c//) # Raw images don't support -c + echo $cmd | sed 's/-P [0-9][0-9]\?/-P PATTERN/' + $QEMU_IO -c "$cmd" "$TEST_IMG" | _filter_qemu_io + $QEMU_IO -c "$raw_cmd" -f raw "$TEST_IMG.raw" | _filter_qemu_io + _verify_img + _verify_l2_bitmap "$c" +} + +_reset_img() +{ + size="$1" + $QEMU_IMG create -f raw "$TEST_IMG.raw" "$size" | _filter_img_create + if [ "$use_backing_file" = "yes" ]; then + $QEMU_IMG create -f raw "$TEST_IMG.base" "$size" | _filter_img_create + $QEMU_IO -c "write -q -P 0xFF 0 $size" -f raw "$TEST_IMG.base" | _filter_qemu_io + $QEMU_IO -c "write -q -P 0xFF 0 $size" -f raw "$TEST_IMG.raw" | _filter_qemu_io + _make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" "$size" + else + _make_test_img -o extended_l2=on "$size" + fi +} + +############################################################ +############################################################ +############################################################ + +# Test that writing to an image with subclusters produces the expected +# results, in images with and without backing files +for use_backing_file in yes no; do + echo + echo "### Standard write tests (backing file: $use_backing_file) ###" + echo + _reset_img 1M + ### Write subcluster #0 (beginning of subcluster) ### + alloc="0"; zero="" + _run_test sc=0 len=1k + + ### Write subcluster #1 (middle of subcluster) ### + alloc="0 1"; zero="" + _run_test sc=1 off=1 len=512 + + ### Write subcluster #2 (end of subcluster) ### + alloc="0 1 2"; zero="" + _run_test sc=2 off=1 len=1k + + ### Write subcluster #3 (full subcluster) ### + alloc="0 1 2 3"; zero="" + _run_test sc=3 len=2k + + ### Write subclusters #4-6 (full subclusters) ### + alloc="$(seq 0 6)"; zero="" + _run_test sc=4 len=6k + + ### Write subclusters #7-9 (partial subclusters) ### + alloc="$(seq 0 9)"; zero="" + _run_test sc=7 off=1 len=4k + + ### Write subcluster #16 (partial subcluster) ### + alloc="$(seq 0 9) 16"; zero="" + _run_test sc=16 len=1k + + ### Write subcluster #31-#33 (cluster overlap) ### + alloc="$(seq 0 9) 16 31"; zero="" + _run_test sc=31 off=1 len=4k + alloc="0 1" ; zero="" + _verify_l2_bitmap 1 + + ### Zero subcluster #1 + alloc="0 $(seq 2 9) 16 31"; zero="1" + _run_test sc=1 len=2k cmd=zero + + ### Zero cluster #0 + alloc=""; zero="$(seq 0 31)" + _run_test sc=0 len=64k cmd=zero + + ### Fill cluster #0 with data + alloc="$(seq 0 31)"; zero="" + _run_test sc=0 len=64k + + ### Zero and unmap half of cluster #0 (this won't unmap it) + alloc="$(seq 16 31)"; zero="$(seq 0 15)" + _run_test sc=0 len=32k cmd=unmap + + ### Zero and unmap cluster #0 + alloc=""; zero="$(seq 0 31)" + _run_test sc=0 len=64k cmd=unmap + + ### Write subcluster #1 (middle of subcluster) + alloc="1"; zero="0 $(seq 2 31)" + _run_test sc=1 off=1 len=512 + + ### Fill cluster #0 with data + alloc="$(seq 0 31)"; zero="" + _run_test sc=0 len=64k + + ### Discard cluster #0 + alloc=""; zero="$(seq 0 31)" + _run_test sc=0 len=64k cmd=discard + + ### Write compressed data to cluster #0 + alloc=""; zero="" + _run_test sc=0 len=64k cmd=compress + + ### Write subcluster #1 (middle of subcluster) + alloc="$(seq 0 31)"; zero="" + _run_test sc=1 off=1 len=512 +done + +############################################################ +############################################################ +############################################################ + +# calculate_l2_meta() checks if none of the clusters affected by a +# write operation need COW or changes to their L2 metadata and simply +# returns when they don't. This is a test for that optimization. +# Here clusters #0-#3 are overwritten but only #1 and #2 need changes. +echo +echo '### Overwriting several clusters without COW ###' +echo +use_backing_file="no" _reset_img 1M +# Write cluster #0, subclusters #12-#31 +alloc="$(seq 12 31)"; zero="" +_run_test sc=12 len=40k + +# Write cluster #1, subcluster #13 +alloc="13"; zero="" +_run_test c=1 sc=13 len=2k + +# Zeroize cluster #2, subcluster #14 +alloc="14"; zero="" +_run_test c=2 sc=14 len=2k +alloc=""; zero="14" +_run_test c=2 sc=14 len=2k cmd=zero + +# Write cluster #3, subclusters #0-#16 +alloc="$(seq 0 16)"; zero="" +_run_test c=3 sc=0 len=34k + +# Write from cluster #0, subcluster #12 to cluster #3, subcluster #11 +alloc="$(seq 12 31)"; zero="" +_run_test sc=12 len=192k +alloc="$(seq 0 31)"; zero="" +_verify_l2_bitmap 1 +_verify_l2_bitmap 2 + +alloc="$(seq 0 16)"; zero="" +_verify_l2_bitmap 3 + +############################################################ +############################################################ +############################################################ + +# Test different patterns of writing zeroes +for use_backing_file in yes no; do + echo + echo "### Writing zeroes 1: unallocated clusters (backing file: $use_backing_file) ###" + echo + # Note that the image size is not a multiple of the cluster size + _reset_img 2083k + + # Cluster-aligned request from clusters #0 to #2 + alloc=""; zero="$(seq 0 31)" + _run_test c=0 sc=0 len=192k cmd=zero + _verify_l2_bitmap 1 + _verify_l2_bitmap 2 + + # Subcluster-aligned request from clusters #3 to #5 + alloc=""; zero="$(seq 16 31)" + _run_test c=3 sc=16 len=128k cmd=zero + alloc=""; zero="$(seq 0 31)" + _verify_l2_bitmap 4 + alloc=""; zero="$(seq 0 15)" + _verify_l2_bitmap 5 + + # Unaligned request from clusters #6 to #8 + if [ "$use_backing_file" = "yes" ]; then + alloc="15"; zero="$(seq 16 31)" # copy-on-write happening here + else + alloc=""; zero="$(seq 15 31)" + fi + _run_test c=6 sc=15 off=1 len=128k cmd=zero + alloc=""; zero="$(seq 0 31)" + _verify_l2_bitmap 7 + if [ "$use_backing_file" = "yes" ]; then + alloc="15"; zero="$(seq 0 14)" # copy-on-write happening here + else + alloc=""; zero="$(seq 0 15)" + fi + _verify_l2_bitmap 8 + + echo + echo "### Writing zeroes 2: allocated clusters (backing file: $use_backing_file) ###" + echo + alloc="$(seq 0 31)"; zero="" + _run_test c=9 sc=0 len=576k + _verify_l2_bitmap 10 + _verify_l2_bitmap 11 + _verify_l2_bitmap 12 + _verify_l2_bitmap 13 + _verify_l2_bitmap 14 + _verify_l2_bitmap 15 + _verify_l2_bitmap 16 + _verify_l2_bitmap 17 + + # Cluster-aligned request from clusters #9 to #11 + alloc=""; zero="$(seq 0 31)" + _run_test c=9 sc=0 len=192k cmd=zero + _verify_l2_bitmap 10 + _verify_l2_bitmap 11 + + # Subcluster-aligned request from clusters #12 to #14 + alloc="$(seq 0 15)"; zero="$(seq 16 31)" + _run_test c=12 sc=16 len=128k cmd=zero + alloc=""; zero="$(seq 0 31)" + _verify_l2_bitmap 13 + alloc="$(seq 16 31)"; zero="$(seq 0 15)" + _verify_l2_bitmap 14 + + # Unaligned request from clusters #15 to #17 + alloc="$(seq 0 15)"; zero="$(seq 16 31)" + _run_test c=15 sc=15 off=1 len=128k cmd=zero + alloc=""; zero="$(seq 0 31)" + _verify_l2_bitmap 16 + alloc="$(seq 15 31)"; zero="$(seq 0 14)" + _verify_l2_bitmap 17 + + echo + echo "### Writing zeroes 3: compressed clusters (backing file: $use_backing_file) ###" + echo + alloc=""; zero="" + for c in $(seq 18 28); do + _run_test c=$c sc=0 len=64k cmd=compress + done + + # Cluster-aligned request from clusters #18 to #20 + alloc=""; zero="$(seq 0 31)" + _run_test c=18 sc=0 len=192k cmd=zero + _verify_l2_bitmap 19 + _verify_l2_bitmap 20 + + # Subcluster-aligned request from clusters #21 to #23. + # We cannot partially zero a compressed cluster so the code + # returns -ENOTSUP, which means copy-on-write of the compressed + # data and fill the rest with actual zeroes on disk. + # TODO: cluster #22 should use the 'all zeroes' bits. + alloc="$(seq 0 31)"; zero="" + _run_test c=21 sc=16 len=128k cmd=zero + _verify_l2_bitmap 22 + _verify_l2_bitmap 23 + + # Unaligned request from clusters #24 to #26 + # In this case QEMU internally sends a 1k request followed by a + # subcluster-aligned 128k request. The first request decompresses + # cluster #24, but that's not enough to perform the second request + # efficiently because it partially writes to cluster #26 (which is + # compressed) so we hit the same problem as before. + alloc="$(seq 0 31)"; zero="" + _run_test c=24 sc=15 off=1 len=129k cmd=zero + _verify_l2_bitmap 25 + _verify_l2_bitmap 26 + + # Unaligned request from clusters #27 to #29 + # Similar to the previous case, but this time the tail of the + # request does not correspond to a compressed cluster, so it can + # be zeroed efficiently. + # Note that the very last subcluster is partially written, so if + # there's a backing file we need to perform cow. + alloc="$(seq 0 15)"; zero="$(seq 16 31)" + _run_test c=27 sc=15 off=1 len=128k cmd=zero + alloc=""; zero="$(seq 0 31)" + _verify_l2_bitmap 28 + if [ "$use_backing_file" = "yes" ]; then + alloc="15"; zero="$(seq 0 14)" # copy-on-write happening here + else + alloc=""; zero="$(seq 0 15)" + fi + _verify_l2_bitmap 29 + + echo + echo "### Writing zeroes 4: other tests (backing file: $use_backing_file) ###" + echo + # Unaligned request in the middle of cluster #30. + # If there's a backing file we need to allocate and do + # copy-on-write on the partially zeroed subclusters. + # If not we can set the 'all zeroes' bit on them. + if [ "$use_backing_file" = "yes" ]; then + alloc="15 19"; zero="$(seq 16 18)" # copy-on-write happening here + else + alloc=""; zero="$(seq 15 19)" + fi + _run_test c=30 sc=15 off=1 len=8k cmd=zero + + # Fill the last cluster with zeroes, up to the end of the image + # (the image size is not a multiple of the cluster or subcluster size). + alloc=""; zero="$(seq 0 17)" + _run_test c=32 sc=0 len=35k cmd=zero +done + +############################################################ +############################################################ +############################################################ + +# Zero + unmap +for use_backing_file in yes no; do + echo + echo "### Zero + unmap 1: allocated clusters (backing file: $use_backing_file) ###" + echo + # Note that the image size is not a multiple of the cluster size + _reset_img 2083k + alloc="$(seq 0 31)"; zero="" + _run_test c=9 sc=0 len=576k + _verify_l2_bitmap 10 + _verify_l2_bitmap 11 + _verify_l2_bitmap 12 + _verify_l2_bitmap 13 + _verify_l2_bitmap 14 + _verify_l2_bitmap 15 + _verify_l2_bitmap 16 + _verify_l2_bitmap 17 + + # Cluster-aligned request from clusters #9 to #11 + alloc=""; zero="$(seq 0 31)" + _run_test c=9 sc=0 len=192k cmd=unmap + _verify_l2_bitmap 10 + _verify_l2_bitmap 11 + + # Subcluster-aligned request from clusters #12 to #14 + alloc="$(seq 0 15)"; zero="$(seq 16 31)" + _run_test c=12 sc=16 len=128k cmd=unmap + alloc=""; zero="$(seq 0 31)" + _verify_l2_bitmap 13 + alloc="$(seq 16 31)"; zero="$(seq 0 15)" + _verify_l2_bitmap 14 + + # Unaligned request from clusters #15 to #17 + alloc="$(seq 0 15)"; zero="$(seq 16 31)" + _run_test c=15 sc=15 off=1 len=128k cmd=unmap + alloc=""; zero="$(seq 0 31)" + _verify_l2_bitmap 16 + alloc="$(seq 15 31)"; zero="$(seq 0 14)" + _verify_l2_bitmap 17 + + echo + echo "### Zero + unmap 2: compressed clusters (backing file: $use_backing_file) ###" + echo + alloc=""; zero="" + for c in $(seq 18 28); do + _run_test c=$c sc=0 len=64k cmd=compress + done + + # Cluster-aligned request from clusters #18 to #20 + alloc=""; zero="$(seq 0 31)" + _run_test c=18 sc=0 len=192k cmd=unmap + _verify_l2_bitmap 19 + _verify_l2_bitmap 20 + + # Subcluster-aligned request from clusters #21 to #23. + # We cannot partially zero a compressed cluster so the code + # returns -ENOTSUP, which means copy-on-write of the compressed + # data and fill the rest with actual zeroes on disk. + # TODO: cluster #22 should use the 'all zeroes' bits. + alloc="$(seq 0 31)"; zero="" + _run_test c=21 sc=16 len=128k cmd=unmap + _verify_l2_bitmap 22 + _verify_l2_bitmap 23 + + # Unaligned request from clusters #24 to #26 + # In this case QEMU internally sends a 1k request followed by a + # subcluster-aligned 128k request. The first request decompresses + # cluster #24, but that's not enough to perform the second request + # efficiently because it partially writes to cluster #26 (which is + # compressed) so we hit the same problem as before. + alloc="$(seq 0 31)"; zero="" + _run_test c=24 sc=15 off=1 len=129k cmd=unmap + _verify_l2_bitmap 25 + _verify_l2_bitmap 26 + + # Unaligned request from clusters #27 to #29 + # Similar to the previous case, but this time the tail of the + # request does not correspond to a compressed cluster, so it can + # be zeroed efficiently. + # Note that the very last subcluster is partially written, so if + # there's a backing file we need to perform cow. + alloc="$(seq 0 15)"; zero="$(seq 16 31)" + _run_test c=27 sc=15 off=1 len=128k cmd=unmap + alloc=""; zero="$(seq 0 31)" + _verify_l2_bitmap 28 + if [ "$use_backing_file" = "yes" ]; then + alloc="15"; zero="$(seq 0 14)" # copy-on-write happening here + else + alloc=""; zero="$(seq 0 15)" + fi + _verify_l2_bitmap 29 +done + +############################################################ +############################################################ +############################################################ + +# Test qcow2_cluster_discard() with full and normal discards +for use_backing_file in yes no; do + echo + echo "### Discarding clusters with non-zero bitmaps (backing file: $use_backing_file) ###" + echo + if [ "$use_backing_file" = "yes" ]; then + _make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 1M + else + _make_test_img -o extended_l2=on 1M + fi + # Write clusters #0-#2 and then discard them + $QEMU_IO -c 'write -q 0 128k' "$TEST_IMG" + $QEMU_IO -c 'discard -q 0 128k' "$TEST_IMG" + # 'qemu-io discard' doesn't do a full discard, it zeroizes the + # cluster, so both clusters have all zero bits set now + alloc=""; zero="$(seq 0 31)" + _verify_l2_bitmap 0 + _verify_l2_bitmap 1 + # Now mark the 2nd half of the subclusters from cluster #0 as unallocated + poke_file "$TEST_IMG" $(($l2_offset+8)) "\x00\x00" + # Discard cluster #0 again to see how the zero bits have changed + $QEMU_IO -c 'discard -q 0 64k' "$TEST_IMG" + # And do a full discard of cluster #1 by shrinking and growing the image + $QEMU_IMG resize --shrink "$TEST_IMG" 64k + $QEMU_IMG resize "$TEST_IMG" 1M + # A normal discard sets all 'zero' bits only if the image has a + # backing file, otherwise it won't touch them. + if [ "$use_backing_file" = "yes" ]; then + alloc=""; zero="$(seq 0 31)" + else + alloc=""; zero="$(seq 0 15)" + fi + _verify_l2_bitmap 0 + # A full discard should clear the L2 entry completely. However + # when growing an image with a backing file the new clusters are + # zeroized to hide the stale data from the backing file + if [ "$use_backing_file" = "yes" ]; then + alloc=""; zero="$(seq 0 31)" + else + alloc=""; zero="" + fi + _verify_l2_bitmap 1 +done + +############################################################ +############################################################ +############################################################ + +# Test that corrupted L2 entries are detected in both read and write +# operations +for corruption_test_cmd in read write; do + echo + echo "### Corrupted L2 entries - $corruption_test_cmd test (allocated) ###" + echo + echo "# 'cluster is zero' bit set on the standard cluster descriptor" + echo + # We actually don't consider this a corrupted image. + # The 'cluster is zero' bit is unused in extended L2 entries so + # QEMU ignores it. + # TODO: maybe treat the image as corrupted and make qemu-img check fix it? + _make_test_img -o extended_l2=on 1M + $QEMU_IO -c 'write -q -P 0x11 0 2k' "$TEST_IMG" + poke_file "$TEST_IMG" $(($l2_offset+7)) "\x01" + alloc="0"; zero="" + _verify_l2_bitmap 0 + $QEMU_IO -c "$corruption_test_cmd -q -P 0x11 0 1k" "$TEST_IMG" + if [ "$corruption_test_cmd" = "write" ]; then + alloc="0"; zero="" + fi + _verify_l2_bitmap 0 + + echo + echo "# Both 'subcluster is zero' and 'subcluster is allocated' bits set" + echo + _make_test_img -o extended_l2=on 1M + # Write from the middle of cluster #0 to the middle of cluster #2 + $QEMU_IO -c 'write -q 32k 128k' "$TEST_IMG" + # Corrupt the L2 entry from cluster #1 + poke_file_be "$TEST_IMG" $(($l2_offset+24)) 4 1 + alloc="$(seq 0 31)"; zero="0" + _verify_l2_bitmap 1 + $QEMU_IO -c "$corruption_test_cmd 0 192k" "$TEST_IMG" + + echo + echo "### Corrupted L2 entries - $corruption_test_cmd test (unallocated) ###" + echo + echo "# 'cluster is zero' bit set on the standard cluster descriptor" + echo + # We actually don't consider this a corrupted image. + # The 'cluster is zero' bit is unused in extended L2 entries so + # QEMU ignores it. + # TODO: maybe treat the image as corrupted and make qemu-img check fix it? + _make_test_img -o extended_l2=on 1M + # We want to modify the (empty) L2 entry from cluster #0, + # but we write to #4 in order to initialize the L2 table first + $QEMU_IO -c 'write -q 256k 1k' "$TEST_IMG" + poke_file "$TEST_IMG" $(($l2_offset+7)) "\x01" + alloc=""; zero="" + _verify_l2_bitmap 0 + $QEMU_IO -c "$corruption_test_cmd -q 0 1k" "$TEST_IMG" + if [ "$corruption_test_cmd" = "write" ]; then + alloc="0"; zero="" + fi + _verify_l2_bitmap 0 + + echo + echo "# 'subcluster is allocated' bit set" + echo + _make_test_img -o extended_l2=on 1M + # We want to corrupt the (empty) L2 entry from cluster #0, + # but we write to #4 in order to initialize the L2 table first + $QEMU_IO -c 'write -q 256k 1k' "$TEST_IMG" + poke_file "$TEST_IMG" $(($l2_offset+15)) "\x01" + alloc="0"; zero="" + _verify_l2_bitmap 0 + $QEMU_IO -c "$corruption_test_cmd 0 1k" "$TEST_IMG" + + echo + echo "# Both 'subcluster is zero' and 'subcluster is allocated' bits set" + echo + _make_test_img -o extended_l2=on 1M + # We want to corrupt the (empty) L2 entry from cluster #1, + # but we write to #4 in order to initialize the L2 table first + $QEMU_IO -c 'write -q 256k 1k' "$TEST_IMG" + # Corrupt the L2 entry from cluster #1 + poke_file_be "$TEST_IMG" $(($l2_offset+24)) 8 $(((1 << 32) | 1)) + alloc="0"; zero="0" + _verify_l2_bitmap 1 + $QEMU_IO -c "$corruption_test_cmd 0 192k" "$TEST_IMG" + + echo + echo "### Compressed cluster with subcluster bitmap != 0 - $corruption_test_cmd test ###" + echo + # We actually don't consider this a corrupted image. + # The bitmap in compressed clusters is unused so QEMU should just ignore it. + _make_test_img -o extended_l2=on 1M + $QEMU_IO -c 'write -q -P 11 -c 0 64k' "$TEST_IMG" + # Change the L2 bitmap to allocate subcluster #31 and zeroize subcluster #0 + poke_file "$TEST_IMG" $(($l2_offset+11)) "\x01\x80" + alloc="31"; zero="0" + _verify_l2_bitmap 0 + $QEMU_IO -c "$corruption_test_cmd -P 11 0 64k" "$TEST_IMG" | _filter_qemu_io + # Writing allocates a new uncompressed cluster so we get a new bitmap + if [ "$corruption_test_cmd" = "write" ]; then + alloc="$(seq 0 31)"; zero="" + fi + _verify_l2_bitmap 0 +done + +############################################################ +############################################################ +############################################################ + +echo +echo "### Detect and repair unaligned clusters ###" +echo +# Create a backing file and fill it with data +$QEMU_IMG create -f raw "$TEST_IMG.base" 128k | _filter_img_create +$QEMU_IO -c "write -q -P 0xff 0 128k" -f raw "$TEST_IMG.base" | _filter_qemu_io + +echo "# Corrupted L2 entry, allocated subcluster #" +# Create a new image, allocate a cluster and write some data to it +_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" +$QEMU_IO -c 'write -q -P 1 4k 2k' "$TEST_IMG" +# Corrupt the L2 entry by making the offset unaligned +poke_file "$TEST_IMG" "$(($l2_offset+6))" "\x02" +# This cannot be repaired, qemu-img check will fail to fix it +_check_test_img -r all +# Attempting to read the image will still show that it's corrupted +$QEMU_IO -c 'read -q 0 2k' "$TEST_IMG" + +echo "# Corrupted L2 entry, no allocated subclusters #" +# Create a new image, allocate a cluster and zeroize subcluster #2 +_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" +$QEMU_IO -c 'write -q -P 1 4k 2k' "$TEST_IMG" +$QEMU_IO -c 'write -q -z 4k 2k' "$TEST_IMG" +# Corrupt the L2 entry by making the offset unaligned +poke_file "$TEST_IMG" "$(($l2_offset+6))" "\x02" +# This time none of the subclusters are allocated so we can repair the image +_check_test_img -r all +# And the data can be read normally +$QEMU_IO -c 'read -q -P 0xff 0 4k' "$TEST_IMG" +$QEMU_IO -c 'read -q -P 0x00 4k 2k' "$TEST_IMG" +$QEMU_IO -c 'read -q -P 0xff 6k 122k' "$TEST_IMG" + +############################################################ +############################################################ +############################################################ + +echo +echo "### Image creation options ###" +echo +echo "# cluster_size < 16k" +_make_test_img -o extended_l2=on,cluster_size=8k 1M + +echo "# backing file and preallocation=metadata" +# For preallocation with backing files, create a backing file first +$QEMU_IMG create -f raw "$TEST_IMG.base" 1M | _filter_img_create +$QEMU_IO -c "write -q -P 0xff 0 1M" -f raw "$TEST_IMG.base" | _filter_qemu_io + +_make_test_img -o extended_l2=on,preallocation=metadata -F raw -b "$TEST_IMG.base" 512k +$QEMU_IMG resize "$TEST_IMG" 1M +$QEMU_IO -c 'read -P 0xff 0 512k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c 'read -P 0x00 512k 512k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IMG map "$TEST_IMG" | _filter_testdir + +echo "# backing file and preallocation=falloc" +_make_test_img -o extended_l2=on,preallocation=falloc -F raw -b "$TEST_IMG.base" 512k +$QEMU_IMG resize "$TEST_IMG" 1M +$QEMU_IO -c 'read -P 0xff 0 512k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c 'read -P 0x00 512k 512k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IMG map "$TEST_IMG" | _filter_testdir + +echo "# backing file and preallocation=full" +_make_test_img -o extended_l2=on,preallocation=full -F raw -b "$TEST_IMG.base" 512k +$QEMU_IMG resize "$TEST_IMG" 1M +$QEMU_IO -c 'read -P 0xff 0 512k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c 'read -P 0x00 512k 512k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IMG map "$TEST_IMG" | _filter_testdir + +echo +echo "### Image resizing with preallocation and backing files ###" +echo +# In this case the new subclusters must have the 'all zeroes' bit set +echo "# resize --preallocation=metadata" +_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 503k +$QEMU_IMG resize --preallocation=metadata "$TEST_IMG" 1013k +$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io + +# In this case and the next one the new subclusters must be allocated +echo "# resize --preallocation=falloc" +_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 503k +$QEMU_IMG resize --preallocation=falloc "$TEST_IMG" 1013k +$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io + +echo "# resize --preallocation=full" +_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 503k +$QEMU_IMG resize --preallocation=full "$TEST_IMG" 1013k +$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io + +echo +echo "### Image resizing with preallocation without backing files ###" +echo +# In this case the new subclusters must have the 'all zeroes' bit set +echo "# resize --preallocation=metadata" +_make_test_img -o extended_l2=on 503k +$QEMU_IO -c 'write -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IMG resize --preallocation=metadata "$TEST_IMG" 1013k +$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io + +# In this case and the next one the new subclusters must be allocated +echo "# resize --preallocation=falloc" +_make_test_img -o extended_l2=on 503k +$QEMU_IO -c 'write -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IMG resize --preallocation=falloc "$TEST_IMG" 1013k +$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io + +echo "# resize --preallocation=full" +_make_test_img -o extended_l2=on 503k +$QEMU_IO -c 'write -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IMG resize --preallocation=full "$TEST_IMG" 1013k +$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io + +echo +echo "### qemu-img measure ###" +echo +echo "# 512MB, extended_l2=off" # This needs one L2 table +$QEMU_IMG measure --size 512M -O qcow2 -o extended_l2=off +echo "# 512MB, extended_l2=on" # This needs two L2 tables +$QEMU_IMG measure --size 512M -O qcow2 -o extended_l2=on + +echo "# 16K clusters, 64GB, extended_l2=off" # This needs one full L1 table cluster +$QEMU_IMG measure --size 64G -O qcow2 -o cluster_size=16k,extended_l2=off +echo "# 16K clusters, 64GB, extended_l2=on" # This needs two full L2 table clusters +$QEMU_IMG measure --size 64G -O qcow2 -o cluster_size=16k,extended_l2=on + +echo "# 8k clusters" # This should fail +$QEMU_IMG measure --size 1M -O qcow2 -o cluster_size=8k,extended_l2=on + +echo "# 1024 TB" # Maximum allowed size with extended_l2=on and 64K clusters +$QEMU_IMG measure --size 1024T -O qcow2 -o extended_l2=on +echo "# 1025 TB" # This should fail +$QEMU_IMG measure --size 1025T -O qcow2 -o extended_l2=on + +echo +echo "### qemu-img amend ###" +echo +_make_test_img -o extended_l2=on 1M +$QEMU_IMG amend -o extended_l2=off "$TEST_IMG" && echo "Unexpected pass" + +_make_test_img -o extended_l2=off 1M +$QEMU_IMG amend -o extended_l2=on "$TEST_IMG" && echo "Unexpected pass" + +echo +echo "### Test copy-on-write on an image with snapshots ###" +echo +_make_test_img -o extended_l2=on 1M + +# For each cluster from #0 to #9 this loop zeroes subcluster #7 +# and allocates subclusters #13 and #18. +alloc="13 18"; zero="7" +for c in $(seq 0 9); do + $QEMU_IO -c "write -q -z $((64*$c+14))k 2k" \ + -c "write -q -P $((0xd0+$c)) $((64*$c+26))k 2k" \ + -c "write -q -P $((0xe0+$c)) $((64*$c+36))k 2k" "$TEST_IMG" + _verify_l2_bitmap "$c" +done + +# Create a snapshot and set l2_offset to the new L2 table +$QEMU_IMG snapshot -c snap1 "$TEST_IMG" +l2_offset=$((0x110000)) + +# Write different patterns to each one of the clusters +# in order to see how copy-on-write behaves in each case. +$QEMU_IO -c "write -q -P 0xf0 $((64*0+30))k 1k" \ + -c "write -q -P 0xf1 $((64*1+20))k 1k" \ + -c "write -q -P 0xf2 $((64*2+40))k 1k" \ + -c "write -q -P 0xf3 $((64*3+26))k 1k" \ + -c "write -q -P 0xf4 $((64*4+14))k 1k" \ + -c "write -q -P 0xf5 $((64*5+1))k 1k" \ + -c "write -q -z $((64*6+30))k 3k" \ + -c "write -q -z $((64*7+26))k 2k" \ + -c "write -q -z $((64*8+26))k 1k" \ + -c "write -q -z $((64*9+12))k 1k" \ + "$TEST_IMG" +alloc="$(seq 13 18)"; zero="7" _verify_l2_bitmap 0 +alloc="$(seq 10 18)"; zero="7" _verify_l2_bitmap 1 +alloc="$(seq 13 20)"; zero="7" _verify_l2_bitmap 2 +alloc="$(seq 13 18)"; zero="7" _verify_l2_bitmap 3 +alloc="$(seq 7 18)"; zero="" _verify_l2_bitmap 4 +alloc="$(seq 0 18)"; zero="" _verify_l2_bitmap 5 +alloc="13 18"; zero="7 15 16" _verify_l2_bitmap 6 +alloc="18"; zero="7 13" _verify_l2_bitmap 7 +alloc="$(seq 13 18)"; zero="7" _verify_l2_bitmap 8 +alloc="13 18"; zero="6 7" _verify_l2_bitmap 9 + +echo +echo "### Test concurrent requests ###" +echo + +_concurrent_io() +{ +# Allocate three subclusters in the same cluster. +# This works because handle_dependencies() checks whether the requests +# allocate the same cluster, even if the COW regions don't overlap (in +# this case they don't). +cat < None: iotests.qemu_img_log('create', '-f', iotests.imgfmt, base, str(size_long)) - iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, mid, - str(size_short)) - iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', mid, top, - str(size_long)) + iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, + '-F', iotests.imgfmt, mid, str(size_short)) + iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', mid, + '-F', iotests.imgfmt, top, str(size_long)) iotests.qemu_io_log('-c', 'write -P 1 0 %d' % size_long, base) @@ -115,6 +115,26 @@ with iotests.FilePath('base') as base, \ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid) iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid) + iotests.log('=== Testing qemu-img commit (top -> base) ===') + + create_chain() + iotests.qemu_img_log('commit', '-b', base, top) + iotests.img_info_log(base) + iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, base) + iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), base) + + iotests.log('=== Testing QMP active commit (top -> base) ===') + + create_chain() + with create_vm() as vm: + vm.launch() + vm.qmp_log('block-commit', device='top', base_node='base', + job_id='job0', auto_dismiss=False) + vm.run_job('job0', wait=5) + + iotests.img_info_log(mid) + iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, base) + iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), base) iotests.log('== Resize tests ==') @@ -139,8 +159,8 @@ with iotests.FilePath('base') as base, \ iotests.log('=== preallocation=%s ===' % prealloc) iotests.qemu_img_log('create', '-f', iotests.imgfmt, base, base_size) - iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, top, - top_size_old) + iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, + '-F', iotests.imgfmt, top, top_size_old) iotests.qemu_io_log('-c', 'write -P 1 %s 64k' % off, base) # After this, top_size_old to base_size should be allocated/zeroed. diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out index d24ff681af68b3d675b40626587d1169801066d7..cfe17a865924646fa0f12ba73306452f4acb9df5 100644 --- a/tests/qemu-iotests/274.out +++ b/tests/qemu-iotests/274.out @@ -1,9 +1,9 @@ == Commit tests == -Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 wrote 2097152/2097152 bytes at offset 0 2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -50,12 +50,14 @@ file format: IMGFMT virtual size: 2 MiB (2097152 bytes) cluster_size: 65536 backing file: TEST_DIR/PID-base +backing file format: IMGFMT Format specific information: compat: 1.1 compression type: zlib lazy refcounts: false refcount bits: 16 corrupt: false + extended l2: false read 1048576/1048576 bytes at offset 0 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -64,11 +66,11 @@ read 1048576/1048576 bytes at offset 1048576 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === Testing HMP commit (top -> mid) === -Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 wrote 2097152/2097152 bytes at offset 0 2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -80,12 +82,14 @@ file format: IMGFMT virtual size: 2 MiB (2097152 bytes) cluster_size: 65536 backing file: TEST_DIR/PID-base +backing file format: IMGFMT Format specific information: compat: 1.1 compression type: zlib lazy refcounts: false refcount bits: 16 corrupt: false + extended l2: false read 1048576/1048576 bytes at offset 0 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -94,11 +98,11 @@ read 1048576/1048576 bytes at offset 1048576 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === Testing QMP active commit (top -> mid) === -Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 wrote 2097152/2097152 bytes at offset 0 2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -116,12 +120,82 @@ file format: IMGFMT virtual size: 2 MiB (2097152 bytes) cluster_size: 65536 backing file: TEST_DIR/PID-base +backing file format: IMGFMT Format specific information: compat: 1.1 compression type: zlib lazy refcounts: false refcount bits: 16 corrupt: false + extended l2: false + +read 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +read 1048576/1048576 bytes at offset 1048576 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +=== Testing qemu-img commit (top -> base) === +Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16 + +Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 + +Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 + +wrote 2097152/2097152 bytes at offset 0 +2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +Image committed. + +image: TEST_IMG +file format: IMGFMT +virtual size: 2 MiB (2097152 bytes) +cluster_size: 65536 +Format specific information: + compat: 1.1 + compression type: zlib + lazy refcounts: false + refcount bits: 16 + corrupt: false + extended l2: false + +read 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +read 1048576/1048576 bytes at offset 1048576 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +=== Testing QMP active commit (top -> base) === +Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16 + +Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 + +Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 + +wrote 2097152/2097152 bytes at offset 0 +2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +{"execute": "block-commit", "arguments": {"auto-dismiss": false, "base-node": "base", "device": "top", "job-id": "job0"}} +{"return": {}} +{"execute": "job-complete", "arguments": {"id": "job0"}} +{"return": {}} +{"data": {"device": "job0", "len": 1048576, "offset": 1048576, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"device": "job0", "len": 1048576, "offset": 1048576, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} +image: TEST_IMG +file format: IMGFMT +virtual size: 1 MiB (1048576 bytes) +cluster_size: 65536 +backing file: TEST_DIR/PID-base +backing file format: IMGFMT +Format specific information: + compat: 1.1 + compression type: zlib + lazy refcounts: false + refcount bits: 16 + corrupt: false + extended l2: false read 1048576/1048576 bytes at offset 0 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -131,9 +205,9 @@ read 1048576/1048576 bytes at offset 1048576 == Resize tests == === preallocation=off === -Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=6442450944 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=1073741824 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1073741824 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 wrote 65536/65536 bytes at offset 5368709120 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -150,9 +224,9 @@ read 65536/65536 bytes at offset 5368709120 { "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}] === preallocation=metadata === -Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=34359738368 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=32212254720 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=32212254720 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 wrote 65536/65536 bytes at offset 33285996544 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -174,9 +248,9 @@ read 65536/65536 bytes at offset 33285996544 { "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}] === preallocation=falloc === -Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=10485760 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=5242880 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=5242880 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 wrote 65536/65536 bytes at offset 9437184 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -193,9 +267,9 @@ read 65536/65536 bytes at offset 9437184 { "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}] === preallocation=full === -Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=16777216 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=8388608 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=8388608 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 wrote 65536/65536 bytes at offset 11534336 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -212,9 +286,9 @@ read 65536/65536 bytes at offset 11534336 { "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}] === preallocation=off === -Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=393216 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=259072 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=259072 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 wrote 65536/65536 bytes at offset 259072 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -232,9 +306,9 @@ read 65536/65536 bytes at offset 259072 { "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}] === preallocation=off === -Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=409600 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=409600 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=262144 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 wrote 65536/65536 bytes at offset 344064 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -251,9 +325,9 @@ read 65536/65536 bytes at offset 344064 { "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}] === preallocation=off === -Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=524288 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=524288 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=262144 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16 wrote 65536/65536 bytes at offset 446464 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/279 b/tests/qemu-iotests/279 index 75a4747e6bcde3957e7b6b04fcb7ad2836915900..5515d4ed0138dc4b3bba5070eb661a1a0ffc92be 100755 --- a/tests/qemu-iotests/279 +++ b/tests/qemu-iotests/279 @@ -42,8 +42,8 @@ _unsupported_imgopts "subformat=monolithicFlat" \ "subformat=twoGbMaxExtentFlat" \ TEST_IMG="$TEST_IMG.base" _make_test_img 64M -TEST_IMG="$TEST_IMG.mid" _make_test_img -b "$TEST_IMG.base" -_make_test_img -b "$TEST_IMG.mid" +TEST_IMG="$TEST_IMG.mid" _make_test_img -b "$TEST_IMG.base" -F $IMGFMT +_make_test_img -b "$TEST_IMG.mid" -F $IMGFMT echo echo '== qemu-img info --backing-chain ==' diff --git a/tests/qemu-iotests/279.out b/tests/qemu-iotests/279.out index f4dc6c69cbb3bfe56af75bb2b45c2120c7cdb9ed..adb2e47a1a9cf062f6a7437a69ae74a50a0060f9 100644 --- a/tests/qemu-iotests/279.out +++ b/tests/qemu-iotests/279.out @@ -1,7 +1,7 @@ QA output created by 279 Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/t.IMGFMT.mid', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid +Formatting 'TEST_DIR/t.IMGFMT.mid', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid backing_fmt=IMGFMT == qemu-img info --backing-chain == image: TEST_DIR/t.IMGFMT diff --git a/tests/qemu-iotests/280.out b/tests/qemu-iotests/280.out index 92e4d14079a5f29da839c8ce9a238811c5cb2aff..09a0f1a7cb42ff5934e549530e65ede29a592168 100644 --- a/tests/qemu-iotests/280.out +++ b/tests/qemu-iotests/280.out @@ -1,4 +1,4 @@ -Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib +Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 === Launch VM === Enabling migration QMP events on VM... diff --git a/tests/qemu-iotests/282 b/tests/qemu-iotests/282 index 081eb120802154f90fcb603cd499ee555f7f1202..27da2a002397a61a8c86a78c1ec2310279a947b4 100755 --- a/tests/qemu-iotests/282 +++ b/tests/qemu-iotests/282 @@ -38,7 +38,6 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt luks _supported_proto generic -_unsupported_proto vxhs echo "== Create non-UTF8 secret ==" echo -n -e '\x3a\x3c\x3b\xff' > non_utf8_secret diff --git a/tests/qemu-iotests/282.out b/tests/qemu-iotests/282.out index 5d079dabce1dfd4a9f9ae7043184eae379132ad0..67db7ab15affae3789b5afdc2d190c7eadcdae2c 100644 --- a/tests/qemu-iotests/282.out +++ b/tests/qemu-iotests/282.out @@ -1,11 +1,11 @@ QA output created by 282 == Create non-UTF8 secret == == Throws an error because of invalid UTF-8 secret == -qemu-img: vol.img: Data from secret sec0 is not valid UTF-8 Formatting 'vol.img', fmt=luks size=4194304 key-secret=sec0 +qemu-img: vol.img: Data from secret sec0 is not valid UTF-8 == Image file should not exist after the error == == Create a stub image file and run qemu-img again == -qemu-img: vol.img: Data from secret sec0 is not valid UTF-8 Formatting 'vol.img', fmt=luks size=4194304 key-secret=sec0 +qemu-img: vol.img: Data from secret sec0 is not valid UTF-8 == Pre-existing image file should also be deleted after the error == - *** done +*** done diff --git a/tests/qemu-iotests/284 b/tests/qemu-iotests/284 index 071e89b33e488a1064e3b870914f48e5082f108e..9f6c29a79c5a597d90c64f719c51e6b3716f64bf 100755 --- a/tests/qemu-iotests/284 +++ b/tests/qemu-iotests/284 @@ -39,6 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto generic _supported_os Linux +_require_working_luks size=1M diff --git a/tests/qemu-iotests/284.out b/tests/qemu-iotests/284.out index 48216f57425209fba98b079c1aea07e409620a66..a92923930251f9e7f8720ca8f8e0c21383e4f510 100644 --- a/tests/qemu-iotests/284.out +++ b/tests/qemu-iotests/284.out @@ -2,7 +2,7 @@ QA output created by 284 testing LUKS qcow2 encryption -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 == cluster size 512 == checking image refcounts == @@ -21,7 +21,7 @@ wrote 1/1 bytes at offset 512 == rechecking image refcounts == No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 == cluster size 2048 == checking image refcounts == @@ -40,7 +40,7 @@ wrote 1/1 bytes at offset 2048 == rechecking image refcounts == No errors were found on the image. -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 == cluster size 32768 == checking image refcounts == diff --git a/tests/qemu-iotests/290 b/tests/qemu-iotests/290 index 776b65e915633be9509271d403f3718b01e4e168..01ee14dcfb73921a960adf50832ab1070de57469 100755 --- a/tests/qemu-iotests/290 +++ b/tests/qemu-iotests/290 @@ -71,7 +71,7 @@ $QEMU_IO -c 'write -P 0xff 0 128k' "$BACKING_IMG" | _filter_qemu_io for qcow2_compat in 0.10 1.1; do echo "# Create an image with compat=$qcow2_compat and a backing file" - _make_test_img -o "compat=$qcow2_compat" -b "$BACKING_IMG" + _make_test_img -o "compat=$qcow2_compat" -b "$BACKING_IMG" -F $IMGFMT echo "# Fill all clusters with data and then discard them" $QEMU_IO -c 'write -P 0x01 0 128k' "$TEST_IMG" | _filter_qemu_io diff --git a/tests/qemu-iotests/290.out b/tests/qemu-iotests/290.out index d2259c823bd4eb92c4ff230f10f9eba954c0dd8f..22b476594fb774bb5dfe70307ee80b07ef27da54 100644 --- a/tests/qemu-iotests/290.out +++ b/tests/qemu-iotests/290.out @@ -34,7 +34,7 @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=131072 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Create an image with compat=0.10 and a backing file -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT # Fill all clusters with data and then discard them wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -47,7 +47,7 @@ read 131072/131072 bytes at offset 0 Offset Length Mapped to File 0 0x20000 0x50000 TEST_DIR/t.qcow2 # Create an image with compat=1.1 and a backing file -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT # Fill all clusters with data and then discard them wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/291 b/tests/qemu-iotests/291 new file mode 100755 index 0000000000000000000000000000000000000000..ecef9eec6240869fed27c9257e4fb6f4b87c01fb --- /dev/null +++ b/tests/qemu-iotests/291 @@ -0,0 +1,134 @@ +#!/usr/bin/env bash +# +# Test qemu-img bitmap handling +# +# Copyright (C) 2018-2020 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 . +# + +seq="$(basename $0)" +echo "QA output created by $seq" + +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img + nbd_server_stop +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter +. ./common.nbd + +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux +_require_command QEMU_NBD +# compat=0.10 does not support bitmaps +_unsupported_imgopts 'compat=0.10' + +# Filter irrelevant format-specific information from the qemu-img info +# output (we only want the bitmaps, basically) +_filter_irrelevant_img_info() +{ + grep -v -e 'compat' -e 'compression type' -e 'data file' -e 'extended l2' \ + -e 'lazy refcounts' -e 'refcount bits' +} + +echo +echo "=== Initial image setup ===" +echo + +# Create backing image with one bitmap +TEST_IMG="$TEST_IMG.base" _make_test_img 10M +$QEMU_IMG bitmap --add -f $IMGFMT "$TEST_IMG.base" b0 +$QEMU_IO -c 'w 3M 1M' -f $IMGFMT "$TEST_IMG.base" | _filter_qemu_io + +# Create initial image and populate two bitmaps: one active, one inactive. +ORIG_IMG=$TEST_IMG +TEST_IMG=$TEST_IMG.orig +_make_test_img -b "$ORIG_IMG.base" -F $IMGFMT 10M +$QEMU_IO -c 'w 0 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io +$QEMU_IMG bitmap --add -g 512k -f $IMGFMT "$TEST_IMG" b1 +$QEMU_IMG bitmap --add --disable -f $IMGFMT "$TEST_IMG" b2 +$QEMU_IO -c 'w 3M 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io +$QEMU_IMG bitmap --clear -f $IMGFMT "$TEST_IMG" b1 +$QEMU_IO -c 'w 1M 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io +$QEMU_IMG bitmap --disable -f $IMGFMT "$TEST_IMG" b1 +$QEMU_IMG bitmap --enable -f $IMGFMT "$TEST_IMG" b2 +$QEMU_IO -c 'w 2M 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io + +echo +echo "=== Bitmap preservation not possible to non-qcow2 ===" +echo + +TEST_IMG=$ORIG_IMG +$QEMU_IMG convert --bitmaps -O raw "$TEST_IMG.orig" "$TEST_IMG" && + echo "unexpected success" + +echo +echo "=== Convert with bitmap preservation ===" +echo + +# Only bitmaps from the active layer are copied +$QEMU_IMG convert --bitmaps -O qcow2 "$TEST_IMG.orig" "$TEST_IMG" +_img_info --format-specific | _filter_irrelevant_img_info +# But we can also merge in bitmaps from other layers. This test is a bit +# contrived to cover more code paths, in reality, you could merge directly +# into b0 without going through tmp +$QEMU_IMG bitmap --add --disable -f $IMGFMT "$TEST_IMG" b0 +$QEMU_IMG bitmap --add --merge b0 -b "$TEST_IMG.base" -F $IMGFMT \ + -f $IMGFMT "$TEST_IMG" tmp +$QEMU_IMG bitmap --merge tmp -f $IMGFMT "$TEST_IMG" b0 +$QEMU_IMG bitmap --remove --image-opts \ + driver=$IMGFMT,file.driver=file,file.filename="$TEST_IMG" tmp +_img_info --format-specific | _filter_irrelevant_img_info + +echo +echo "=== Merge from top layer into backing image ===" +echo + +$QEMU_IMG rebase -u -F qcow2 -b "$TEST_IMG.base" "$TEST_IMG" +$QEMU_IMG bitmap --add --merge b2 -b "$TEST_IMG" -F $IMGFMT \ + -f $IMGFMT "$TEST_IMG.base" b3 +_img_info --format-specific --backing-chain | _filter_irrelevant_img_info + +echo +echo "=== Check bitmap contents ===" +echo + +# x-dirty-bitmap is a hack for reading bitmaps; it abuses block status to +# report "data":false for portions of the bitmap which are set +IMG="driver=nbd,server.type=unix,server.path=$nbd_unix_socket" +nbd_server_start_unix_socket -r -f qcow2 \ + -B b0 -B b1 -B b2 -B b3 "$TEST_IMG" +$QEMU_IMG map --output=json --image-opts \ + "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b0" | _filter_qemu_img_map +$QEMU_IMG map --output=json --image-opts \ + "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b1" | _filter_qemu_img_map +$QEMU_IMG map --output=json --image-opts \ + "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b2" | _filter_qemu_img_map +$QEMU_IMG map --output=json --image-opts \ + "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b3" | _filter_qemu_img_map + +nbd_server_stop + +# success, all done +echo '*** done' +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/291.out b/tests/qemu-iotests/291.out new file mode 100644 index 0000000000000000000000000000000000000000..23411c0ff4d9c843b5105177c5e7b7a0913ee716 --- /dev/null +++ b/tests/qemu-iotests/291.out @@ -0,0 +1,118 @@ +QA output created by 291 + +=== Initial image setup === + +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=10485760 +wrote 1048576/1048576 bytes at offset 3145728 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=10485760 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +wrote 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 1048576/1048576 bytes at offset 3145728 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 1048576/1048576 bytes at offset 1048576 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 1048576/1048576 bytes at offset 2097152 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +=== Bitmap preservation not possible to non-qcow2 === + +qemu-img: Format driver 'raw' does not support bitmaps + +=== Convert with bitmap preservation === + +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 10 MiB (10485760 bytes) +cluster_size: 65536 +Format specific information: + bitmaps: + [0]: + flags: + name: b1 + granularity: 524288 + [1]: + flags: + [0]: auto + name: b2 + granularity: 65536 + corrupt: false +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 10 MiB (10485760 bytes) +cluster_size: 65536 +Format specific information: + bitmaps: + [0]: + flags: + name: b1 + granularity: 524288 + [1]: + flags: + [0]: auto + name: b2 + granularity: 65536 + [2]: + flags: + name: b0 + granularity: 65536 + corrupt: false + +=== Merge from top layer into backing image === + +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 10 MiB (10485760 bytes) +cluster_size: 65536 +backing file: TEST_DIR/t.IMGFMT.base +backing file format: IMGFMT +Format specific information: + bitmaps: + [0]: + flags: + name: b1 + granularity: 524288 + [1]: + flags: + [0]: auto + name: b2 + granularity: 65536 + [2]: + flags: + name: b0 + granularity: 65536 + corrupt: false + +image: TEST_DIR/t.IMGFMT.base +file format: IMGFMT +virtual size: 10 MiB (10485760 bytes) +cluster_size: 65536 +Format specific information: + bitmaps: + [0]: + flags: + [0]: auto + name: b0 + granularity: 65536 + [1]: + flags: + [0]: auto + name: b3 + granularity: 65536 + corrupt: false + +=== Check bitmap contents === + +[{ "start": 0, "length": 3145728, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, +{ "start": 3145728, "length": 1048576, "depth": 0, "zero": false, "data": false}, +{ "start": 4194304, "length": 6291456, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] +[{ "start": 0, "length": 1048576, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, +{ "start": 1048576, "length": 1048576, "depth": 0, "zero": false, "data": false}, +{ "start": 2097152, "length": 8388608, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] +[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, +{ "start": 2097152, "length": 1048576, "depth": 0, "zero": false, "data": false}, +{ "start": 3145728, "length": 7340032, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] +[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, +{ "start": 2097152, "length": 1048576, "depth": 0, "zero": false, "data": false}, +{ "start": 3145728, "length": 7340032, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] +*** done diff --git a/tests/qemu-iotests/292 b/tests/qemu-iotests/292 index a2de27cca457f3d148282635281ef47971f6bb9b..83ab19231da2ca0c20a123afebae352eefc96c50 100755 --- a/tests/qemu-iotests/292 +++ b/tests/qemu-iotests/292 @@ -40,6 +40,11 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto file _supported_os Linux +# We need qemu-img map to show the file where the data is allocated, +# but with an external data file, it will show that instead of the +# file we want to check. So just skip this test for external data +# files. +_unsupported_imgopts data_file echo '### Create the backing image' BACKING_IMG="$TEST_IMG.base" diff --git a/tests/qemu-iotests/293 b/tests/qemu-iotests/293 new file mode 100755 index 0000000000000000000000000000000000000000..f86fe3b41375f99e433079f690e984fc342400e4 --- /dev/null +++ b/tests/qemu-iotests/293 @@ -0,0 +1,208 @@ +#!/usr/bin/env bash +# +# Test encryption key management with luks +# Based on 134 +# +# Copyright (C) 2019 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=mlevitsk@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 luks +_supported_proto file #TODO +_require_working_luks + +QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT + +if [ "$IMGFMT" = "qcow2" ] ; then + PR="encrypt." + EXTRA_IMG_ARGS="-o encrypt.format=luks" +fi + + +# secrets: you are supposed to see the password as *******, see :-) +S0="--object secret,id=sec0,data=hunter0" +S1="--object secret,id=sec1,data=hunter1" +S2="--object secret,id=sec2,data=hunter2" +S3="--object secret,id=sec3,data=hunter3" +S4="--object secret,id=sec4,data=hunter4" +SECRETS="$S0 $S1 $S2 $S3 $S4" + +# image with given secret +IMGS0="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,${PR}key-secret=sec0" +IMGS1="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,${PR}key-secret=sec1" +IMGS2="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,${PR}key-secret=sec2" +IMGS3="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,${PR}key-secret=sec3" +IMGS4="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,${PR}key-secret=sec4" + + +echo "== creating a test image ==" +_make_test_img $S0 $EXTRA_IMG_ARGS -o ${PR}key-secret=sec0,${PR}iter-time=10 32M + +echo +echo "== test that key 0 opens the image ==" +$QEMU_IO $S0 -c "read 0 4096" $IMGS0 | _filter_qemu_io | _filter_testdir + +echo +echo "== adding a password to slot 4 ==" +$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=active,${PR}new-secret=sec4,${PR}iter-time=10,${PR}keyslot=4 +echo "== adding a password to slot 1 ==" +$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=active,${PR}new-secret=sec1,${PR}iter-time=10 +echo "== adding a password to slot 3 ==" +$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=active,${PR}new-secret=sec3,${PR}iter-time=10,${PR}keyslot=3 + +echo "== adding a password to slot 2 ==" +$QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=active,${PR}new-secret=sec2,${PR}iter-time=10 + + +echo "== erase slot 4 ==" +$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}keyslot=4 | _filter_img_create + + +echo +echo "== all secrets should work ==" +for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do + $QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir +done + +echo +echo "== erase slot 0 and try it ==" +$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec0 | _filter_img_create +$QEMU_IO $SECRETS -c "read 0 4096" $IMGS0 | _filter_qemu_io | _filter_testdir + +echo +echo "== erase slot 2 and try it ==" +$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}keyslot=2 | _filter_img_create +$QEMU_IO $SECRETS -c "read 0 4096" $IMGS2 | _filter_qemu_io | _filter_testdir + + +# at this point slots 1 and 3 should be active + +echo +echo "== filling 4 slots with secret 2 ==" +for ((i = 0; i < 4; i++)); do + $QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=active,${PR}new-secret=sec2,${PR}iter-time=10 +done + +echo +echo "== adding secret 0 ==" + $QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=active,${PR}new-secret=sec0,${PR}iter-time=10 + +echo +echo "== adding secret 3 (last slot) ==" + $QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=active,${PR}new-secret=sec3,${PR}iter-time=10 + +echo +echo "== trying to add another slot (should fail) ==" +$QEMU_IMG amend $SECRETS $IMGS2 -o ${PR}state=active,${PR}new-secret=sec3,${PR}iter-time=10 + +echo +echo "== all secrets should work again ==" +for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do + $QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir +done + + +echo + +echo "== erase all keys of secret 2==" +$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec2 + +echo "== erase all keys of secret 1==" +$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec1 + +echo "== erase all keys of secret 0==" +$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=inactive,${PR}old-secret=sec0 + +echo "== erasing secret3 will fail now since it is the only secret (in 3 slots) ==" +$QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=inactive,${PR}old-secret=sec3 + +echo +echo "== only secret3 should work now ==" +for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do + $QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir +done + +echo +echo "== add secret0 ==" +$QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=active,${PR}new-secret=sec0,${PR}iter-time=10 + +echo "== erase secret3 ==" +$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=inactive,${PR}old-secret=sec3 + +echo +echo "== only secret0 should work now ==" +for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do + $QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir +done + +echo +echo "== replace secret0 with secret1 (should fail) ==" +$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=active,${PR}new-secret=sec1,${PR}keyslot=0 + +echo +echo "== replace secret0 with secret1 with force (should work) ==" +$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=active,${PR}new-secret=sec1,${PR}iter-time=10,${PR}keyslot=0 --force + +echo +echo "== only secret1 should work now ==" +for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do + $QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir +done + + +echo +echo "== erase last secret (should fail) ==" +$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}keyslot=0 +$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec1 + + +echo "== erase non existing secrets (should fail) ==" +$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec5 --force +$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec0 --force +$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}keyslot=1 --force + +echo +echo "== erase last secret with force by slot (should work) ==" +$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}keyslot=0 --force + +echo +echo "== we have no secrets now, data is lost forever ==" +for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do + $QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir +done + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 + diff --git a/tests/qemu-iotests/293.out b/tests/qemu-iotests/293.out new file mode 100644 index 0000000000000000000000000000000000000000..72607831260cdb42ae0ed97766342a4ade3c2077 --- /dev/null +++ b/tests/qemu-iotests/293.out @@ -0,0 +1,99 @@ +QA output created by 293 +== creating a test image == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 + +== test that key 0 opens the image == +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== adding a password to slot 4 == +== adding a password to slot 1 == +== adding a password to slot 3 == +== adding a password to slot 2 == +== erase slot 4 == + +== all secrets should work == +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== erase slot 0 and try it == +qemu-io: can't open: Invalid password, cannot unlock any keyslot + +== erase slot 2 and try it == +qemu-io: can't open: Invalid password, cannot unlock any keyslot + +== filling 4 slots with secret 2 == + +== adding secret 0 == + +== adding secret 3 (last slot) == + +== trying to add another slot (should fail) == +qemu-img: Can't add a keyslot - all keyslots are in use + +== all secrets should work again == +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== erase all keys of secret 2== +== erase all keys of secret 1== +== erase all keys of secret 0== +== erasing secret3 will fail now since it is the only secret (in 3 slots) == +qemu-img: All the active keyslots match the (old) password that was given and erasing them will erase all the data in the image irreversibly - refusing operation + +== only secret3 should work now == +qemu-io: can't open: Invalid password, cannot unlock any keyslot +qemu-io: can't open: Invalid password, cannot unlock any keyslot +qemu-io: can't open: Invalid password, cannot unlock any keyslot +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== add secret0 == +== erase secret3 == + +== only secret0 should work now == +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-io: can't open: Invalid password, cannot unlock any keyslot +qemu-io: can't open: Invalid password, cannot unlock any keyslot +qemu-io: can't open: Invalid password, cannot unlock any keyslot + +== replace secret0 with secret1 (should fail) == +qemu-img: Refusing to overwrite active keyslot 0 - please erase it first + +== replace secret0 with secret1 with force (should work) == + +== only secret1 should work now == +qemu-io: can't open: Invalid password, cannot unlock any keyslot +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-io: can't open: Invalid password, cannot unlock any keyslot +qemu-io: can't open: Invalid password, cannot unlock any keyslot + +== erase last secret (should fail) == +qemu-img: Attempt to erase the only active keyslot 0 which will erase all the data in the image irreversibly - refusing operation +qemu-img: All the active keyslots match the (old) password that was given and erasing them will erase all the data in the image irreversibly - refusing operation +== erase non existing secrets (should fail) == +qemu-img: No secret with id 'sec5' +qemu-img: No keyslots match given (old) password for erase operation + +== erase last secret with force by slot (should work) == + +== we have no secrets now, data is lost forever == +qemu-io: can't open: Invalid password, cannot unlock any keyslot +qemu-io: can't open: Invalid password, cannot unlock any keyslot +qemu-io: can't open: Invalid password, cannot unlock any keyslot +qemu-io: can't open: Invalid password, cannot unlock any keyslot +*** done diff --git a/tests/qemu-iotests/294 b/tests/qemu-iotests/294 new file mode 100755 index 0000000000000000000000000000000000000000..9c95ed8c9a689c291b7a2f036bd94ebca4c1b0ed --- /dev/null +++ b/tests/qemu-iotests/294 @@ -0,0 +1,90 @@ +# +# Copyright (C) 2019 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=mlevitsk@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt luks +_supported_proto file #TODO + +QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT + +# you are supposed to see the password as *******, see :-) +S0="--object secret,id=sec0,data=hunter0" +S1="--object secret,id=sec1,data=hunter1" +SECRETS="$S0 $S1" + + +IMGS0="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,key-secret=sec0" +IMGS1="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,key-secret=sec1" + +echo "== creating a test image ==" +_make_test_img $S0 -o "key-secret=sec0,iter-time=10" 32M + +echo +echo "== test that key 0 opens the image ==" +$QEMU_IO $S0 -c "read 0 4096" $IMGS0 | _filter_qemu_io | _filter_testdir + +echo +echo "== adding a password to slot 1 ==" +$QEMU_IMG amend $SECRETS $IMGS0 -o state=active,new-secret=sec1,keyslot=1,iter-time=10 + +echo +echo "== 'backup' the image header ==" +dd if=$TEST_IMG_FILE of=${TEST_IMG_FILE}.bk bs=4K skip=0 count=1 + +echo +echo "== erase slot 0 ==" +$QEMU_IMG amend $SECRETS $IMGS1 -o state=inactive,keyslot=0 | _filter_img_create + +echo +echo "== test that key 0 doesn't open the image ==" +$QEMU_IO $S0 -c "read 0 4096" $IMGS0 | _filter_qemu_io | _filter_testdir + +echo +echo "== 'restore' the image header ==" +dd if=${TEST_IMG_FILE}.bk of=${TEST_IMG_FILE} bs=4K skip=0 count=1 conv=notrunc + +echo +echo "== test that key 0 still doesn't open the image (key material is erased) ==" +$QEMU_IO $SECRETS -c "read 0 4096" $IMGS0 | _filter_qemu_io | _filter_testdir + +echo +echo "== test that key 1 still works ==" +$QEMU_IO $SECRETS -c "read 0 4096" $IMGS1 | _filter_qemu_io | _filter_testdir + +echo "*** done" +rm -f $seq.full +status=0 + + +exit 0 diff --git a/tests/qemu-iotests/294.out b/tests/qemu-iotests/294.out new file mode 100644 index 0000000000000000000000000000000000000000..994ae873081c693e03d757d4db725697881b9411 --- /dev/null +++ b/tests/qemu-iotests/294.out @@ -0,0 +1,30 @@ +QA output created by 294 +== creating a test image == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 + +== test that key 0 opens the image == +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== adding a password to slot 1 == + +== 'backup' the image header == +1+0 records in +1+0 records out + +== erase slot 0 == + +== test that key 0 doesn't open the image == +qemu-io: can't open: Invalid password, cannot unlock any keyslot + +== 'restore' the image header == +1+0 records in +1+0 records out + +== test that key 0 still doesn't open the image (key material is erased) == +qemu-io: can't open: Invalid password, cannot unlock any keyslot + +== test that key 1 still works == +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +*** done diff --git a/tests/qemu-iotests/295 b/tests/qemu-iotests/295 new file mode 100755 index 0000000000000000000000000000000000000000..59e674fa85a3bbc72ff923229c0fae807f507ffd --- /dev/null +++ b/tests/qemu-iotests/295 @@ -0,0 +1,280 @@ +#!/usr/bin/env python3 +# +# Test case QMP's encrypted key management +# +# Copyright (C) 2019 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 . +# + +import iotests +import os +import time +import json + +test_img = os.path.join(iotests.test_dir, 'test.img') + +class Secret: + def __init__(self, index): + self._id = "keysec" + str(index) + # you are not supposed to see the password... + self._secret = "hunter" + str(index) + + def id(self): + return self._id + + def secret(self): + return self._secret + + def to_cmdline_object(self): + return [ "secret,id=" + self._id + ",data=" + self._secret] + + def to_qmp_object(self): + return { "qom_type" : "secret", "id": self.id(), + "props": { "data": self.secret() } } + +################################################################################ +class EncryptionSetupTestCase(iotests.QMPTestCase): + + # test case startup + def setUp(self): + # start the VM + self.vm = iotests.VM() + self.vm.launch() + + # create the secrets and load 'em into the VM + self.secrets = [ Secret(i) for i in range(0, 6) ] + for secret in self.secrets: + result = self.vm.qmp("object-add", **secret.to_qmp_object()) + self.assert_qmp(result, 'return', {}) + + if iotests.imgfmt == "qcow2": + self.pfx = "encrypt." + self.img_opts = [ '-o', "encrypt.format=luks" ] + else: + self.pfx = "" + self.img_opts = [] + + # test case shutdown + def tearDown(self): + # stop the VM + self.vm.shutdown() + + ########################################################################### + # create the encrypted block device + def createImg(self, file, secret): + + iotests.qemu_img( + 'create', + '--object', *secret.to_cmdline_object(), + '-f', iotests.imgfmt, + '-o', self.pfx + 'key-secret=' + secret.id(), + '-o', self.pfx + 'iter-time=10', + *self.img_opts, + file, + '1M') + + ########################################################################### + # open an encrypted block device + def openImageQmp(self, id, file, secret, read_only = False): + + encrypt_options = { + 'key-secret' : secret.id() + } + + if iotests.imgfmt == "qcow2": + encrypt_options = { + 'encrypt': { + 'format':'luks', + **encrypt_options + } + } + + result = self.vm.qmp('blockdev-add', ** + { + 'driver': iotests.imgfmt, + 'node-name': id, + 'read-only': read_only, + + **encrypt_options, + + 'file': { + 'driver': 'file', + 'filename': test_img, + } + } + ) + self.assert_qmp(result, 'return', {}) + + # close the encrypted block device + def closeImageQmp(self, id): + result = self.vm.qmp('blockdev-del', **{ 'node-name': id }) + self.assert_qmp(result, 'return', {}) + + ########################################################################### + # add a key to an encrypted block device + def addKeyQmp(self, id, new_secret, secret = None, + slot = None, force = False): + + crypt_options = { + 'state' : 'active', + 'new-secret' : new_secret.id(), + 'iter-time' : 10 + } + + if slot != None: + crypt_options['keyslot'] = slot + + + if secret != None: + crypt_options['secret'] = secret.id() + + if iotests.imgfmt == "qcow2": + crypt_options['format'] = 'luks' + crypt_options = { + 'encrypt': crypt_options + } + + args = { + 'node-name': id, + 'job-id' : 'job_add_key', + 'options' : { + 'driver' : iotests.imgfmt, + **crypt_options + }, + } + + if force == True: + args['force'] = True + + #TODO: check what jobs return + result = self.vm.qmp('x-blockdev-amend', **args) + assert result['return'] == {} + self.vm.run_job('job_add_key') + + # erase a key from an encrypted block device + def eraseKeyQmp(self, id, old_secret = None, slot = None, force = False): + + crypt_options = { + 'state' : 'inactive', + } + + if slot != None: + crypt_options['keyslot'] = slot + if old_secret != None: + crypt_options['old-secret'] = old_secret.id() + + if iotests.imgfmt == "qcow2": + crypt_options['format'] = 'luks' + crypt_options = { + 'encrypt': crypt_options + } + + args = { + 'node-name': id, + 'job-id' : 'job_erase_key', + 'options' : { + 'driver' : iotests.imgfmt, + **crypt_options + }, + } + + if force == True: + args['force'] = True + + result = self.vm.qmp('x-blockdev-amend', **args) + assert result['return'] == {} + self.vm.run_job('job_erase_key') + + ########################################################################### + # create image, and change its key + def testChangeKey(self): + + # create the image with secret0 and open it + self.createImg(test_img, self.secrets[0]); + self.openImageQmp("testdev", test_img, self.secrets[0]) + + # add key to slot 1 + self.addKeyQmp("testdev", new_secret = self.secrets[1]) + + # add key to slot 5 + self.addKeyQmp("testdev", new_secret = self.secrets[2], slot=5) + + # erase key from slot 0 + self.eraseKeyQmp("testdev", old_secret = self.secrets[0]) + + #reopen the image with secret1 + self.closeImageQmp("testdev") + self.openImageQmp("testdev", test_img, self.secrets[1]) + + # close and erase the image for good + self.closeImageQmp("testdev") + os.remove(test_img) + + # test that if we erase the old password, + # we can still change the encryption keys using 'old-secret' + def testOldPassword(self): + + # create the image with secret0 and open it + self.createImg(test_img, self.secrets[0]); + self.openImageQmp("testdev", test_img, self.secrets[0]) + + # add key to slot 1 + self.addKeyQmp("testdev", new_secret = self.secrets[1]) + + # erase key from slot 0 + self.eraseKeyQmp("testdev", old_secret = self.secrets[0]) + + # this will fail as the old password is no longer valid + self.addKeyQmp("testdev", new_secret = self.secrets[2]) + + # this will work + self.addKeyQmp("testdev", new_secret = self.secrets[2], secret = self.secrets[1]) + + # close and erase the image for good + self.closeImageQmp("testdev") + os.remove(test_img) + + def testUseForceLuke(self): + + self.createImg(test_img, self.secrets[0]); + self.openImageQmp("testdev", test_img, self.secrets[0]) + + # Add bunch of secrets + self.addKeyQmp("testdev", new_secret = self.secrets[1], slot=4) + self.addKeyQmp("testdev", new_secret = self.secrets[4], slot=2) + + # overwrite an active secret + self.addKeyQmp("testdev", new_secret = self.secrets[5], slot=2) + self.addKeyQmp("testdev", new_secret = self.secrets[5], slot=2, force=True) + + self.addKeyQmp("testdev", new_secret = self.secrets[0]) + + # Now erase all the secrets + self.eraseKeyQmp("testdev", old_secret = self.secrets[5]) + self.eraseKeyQmp("testdev", slot=4) + + # erase last keyslot + self.eraseKeyQmp("testdev", old_secret = self.secrets[0]) + self.eraseKeyQmp("testdev", old_secret = self.secrets[0], force=True) + + self.closeImageQmp("testdev") + os.remove(test_img) + + +if __name__ == '__main__': + iotests.verify_working_luks() + # Encrypted formats support + iotests.activate_logging() + iotests.main(supported_fmts = ['qcow2', 'luks']) diff --git a/tests/qemu-iotests/295.out b/tests/qemu-iotests/295.out new file mode 100644 index 0000000000000000000000000000000000000000..ad34b2ca2c557b3278a2ed3bff35f66834007078 --- /dev/null +++ b/tests/qemu-iotests/295.out @@ -0,0 +1,40 @@ +{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}} +{"return": {}} +Job failed: Invalid password, cannot unlock any keyslot +{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}} +{"return": {}} +Job failed: Refusing to overwrite active keyslot 2 - please erase it first +{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}} +{"return": {}} +Job failed: All the active keyslots match the (old) password that was given and erasing them will erase all the data in the image irreversibly - refusing operation +{"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}} +{"return": {}} +... +---------------------------------------------------------------------- +Ran 3 tests + +OK diff --git a/tests/qemu-iotests/296 b/tests/qemu-iotests/296 new file mode 100755 index 0000000000000000000000000000000000000000..fb7dec88aa81ed039d598eb10a4568b76fb608cc --- /dev/null +++ b/tests/qemu-iotests/296 @@ -0,0 +1,276 @@ +#!/usr/bin/env python3 +# +# Test case for encryption key management versus image sharing +# +# Copyright (C) 2019 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 . +# + +import iotests +import os +import time +import json + +test_img = os.path.join(iotests.test_dir, 'test.img') + +class Secret: + def __init__(self, index): + self._id = "keysec" + str(index) + # you are not supposed to see the password... + self._secret = "hunter" + str(index) + + def id(self): + return self._id + + def secret(self): + return self._secret + + def to_cmdline_object(self): + return [ "secret,id=" + self._id + ",data=" + self._secret] + + def to_qmp_object(self): + return { "qom_type" : "secret", "id": self.id(), + "props": { "data": self.secret() } } + +################################################################################ + +class EncryptionSetupTestCase(iotests.QMPTestCase): + + # test case startup + def setUp(self): + + # start the VMs + self.vm1 = iotests.VM(path_suffix = 'VM1') + self.vm2 = iotests.VM(path_suffix = 'VM2') + self.vm1.launch() + self.vm2.launch() + + # create the secrets and load 'em into the VMs + self.secrets = [ Secret(i) for i in range(0, 4) ] + for secret in self.secrets: + result = self.vm1.qmp("object-add", **secret.to_qmp_object()) + self.assert_qmp(result, 'return', {}) + result = self.vm2.qmp("object-add", **secret.to_qmp_object()) + self.assert_qmp(result, 'return', {}) + + # test case shutdown + def tearDown(self): + # stop the VM + self.vm1.shutdown() + self.vm2.shutdown() + + ########################################################################### + # create the encrypted block device using qemu-img + def createImg(self, file, secret): + + output = iotests.qemu_img_pipe( + 'create', + '--object', *secret.to_cmdline_object(), + '-f', iotests.imgfmt, + '-o', 'key-secret=' + secret.id(), + '-o', 'iter-time=10', + file, + '1M') + + iotests.log(output, filters=[iotests.filter_test_dir]) + + # attempts to add a key using qemu-img + def addKey(self, file, secret, new_secret): + + image_options = { + 'key-secret' : secret.id(), + 'driver' : iotests.imgfmt, + 'file' : { + 'driver':'file', + 'filename': file, + } + } + + output = iotests.qemu_img_pipe( + 'amend', + '--object', *secret.to_cmdline_object(), + '--object', *new_secret.to_cmdline_object(), + + '-o', 'state=active', + '-o', 'new-secret=' + new_secret.id(), + '-o', 'iter-time=10', + + "json:" + json.dumps(image_options) + ) + + iotests.log(output, filters=[iotests.filter_test_dir]) + + ########################################################################### + # open an encrypted block device + def openImageQmp(self, vm, id, file, secret, + readOnly = False, reOpen = False): + + command = 'x-blockdev-reopen' if reOpen else 'blockdev-add' + + result = vm.qmp(command, ** + { + 'driver': iotests.imgfmt, + 'node-name': id, + 'read-only': readOnly, + 'key-secret' : secret.id(), + 'file': { + 'driver': 'file', + 'filename': test_img, + } + } + ) + self.assert_qmp(result, 'return', {}) + + + ########################################################################### + # add virtio-blk consumer for a block device + def addImageUser(self, vm, id, disk_id, share_rw=False): + result = vm.qmp('device_add', ** + { + 'driver': 'virtio-blk', + 'id': id, + 'drive': disk_id, + 'share-rw' : share_rw + } + ) + + iotests.log(result) + + # close the encrypted block device + def closeImageQmp(self, vm, id): + result = vm.qmp('blockdev-del', **{ 'node-name': id }) + self.assert_qmp(result, 'return', {}) + + ########################################################################### + + # add a key to an encrypted block device + def addKeyQmp(self, vm, id, new_secret): + + args = { + 'node-name': id, + 'job-id' : 'job0', + 'options' : { + 'state' : 'active', + 'driver' : iotests.imgfmt, + 'new-secret': new_secret.id(), + 'iter-time' : 10 + }, + } + + result = vm.qmp('x-blockdev-amend', **args) + assert result['return'] == {} + vm.run_job('job0') + + # test that when the image opened by two qemu processes, + # neither of them can update the encryption keys + def test1(self): + self.createImg(test_img, self.secrets[0]); + + # VM1 opens the image and adds a key + self.openImageQmp(self.vm1, "testdev", test_img, self.secrets[0]) + self.addKeyQmp(self.vm1, "testdev", new_secret = self.secrets[1]) + + + # VM2 opens the image + self.openImageQmp(self.vm2, "testdev", test_img, self.secrets[0]) + + + # neither VMs now should be able to add a key + self.addKeyQmp(self.vm1, "testdev", new_secret = self.secrets[2]) + self.addKeyQmp(self.vm2, "testdev", new_secret = self.secrets[2]) + + + # VM 1 closes the image + self.closeImageQmp(self.vm1, "testdev") + + + # now VM2 can add the key + self.addKeyQmp(self.vm2, "testdev", new_secret = self.secrets[2]) + + + # qemu-img should also not be able to add a key + self.addKey(test_img, self.secrets[0], self.secrets[2]) + + # cleanup + self.closeImageQmp(self.vm2, "testdev") + os.remove(test_img) + + + # test that when the image opened by two qemu processes, + # even if first VM opens it read-only, the second can't update encryption + # keys + def test2(self): + self.createImg(test_img, self.secrets[0]); + + # VM1 opens the image readonly + self.openImageQmp(self.vm1, "testdev", test_img, self.secrets[0], + readOnly = True) + + # VM2 opens the image + self.openImageQmp(self.vm2, "testdev", test_img, self.secrets[0]) + + # VM1 can't add a key since image is readonly + self.addKeyQmp(self.vm1, "testdev", new_secret = self.secrets[2]) + + # VM2 can't add a key since VM is has the image opened + self.addKeyQmp(self.vm2, "testdev", new_secret = self.secrets[2]) + + + #VM1 reopens the image read-write + self.openImageQmp(self.vm1, "testdev", test_img, self.secrets[0], + reOpen = True, readOnly = False) + + # VM1 still can't add the key + self.addKeyQmp(self.vm1, "testdev", new_secret = self.secrets[2]) + + # VM2 gets away + self.closeImageQmp(self.vm2, "testdev") + + # VM1 now can add the key + self.addKeyQmp(self.vm1, "testdev", new_secret = self.secrets[2]) + + self.closeImageQmp(self.vm1, "testdev") + os.remove(test_img) + + # test that two VMs can't open the same luks image by default + # and attach it to a guest device + def test3(self): + self.createImg(test_img, self.secrets[0]); + + self.openImageQmp(self.vm1, "testdev", test_img, self.secrets[0]) + self.addImageUser(self.vm1, "testctrl", "testdev") + + self.openImageQmp(self.vm2, "testdev", test_img, self.secrets[0]) + self.addImageUser(self.vm2, "testctrl", "testdev") + + + # test that two VMs can attach the same luks image to a guest device, + # if both use share-rw=on + def test4(self): + self.createImg(test_img, self.secrets[0]); + + self.openImageQmp(self.vm1, "testdev", test_img, self.secrets[0]) + self.addImageUser(self.vm1, "testctrl", "testdev", share_rw=True) + + self.openImageQmp(self.vm2, "testdev", test_img, self.secrets[0]) + self.addImageUser(self.vm2, "testctrl", "testdev", share_rw=True) + + + +if __name__ == '__main__': + # support only raw luks since luks encrypted qcow2 is a proper + # format driver which doesn't allow any sharing + iotests.activate_logging() + iotests.main(supported_fmts = ['luks']) diff --git a/tests/qemu-iotests/296.out b/tests/qemu-iotests/296.out new file mode 100644 index 0000000000000000000000000000000000000000..cb2859a15c05b96e35668d54d8a5b076cea88fd8 --- /dev/null +++ b/tests/qemu-iotests/296.out @@ -0,0 +1,41 @@ +Formatting 'TEST_DIR/test.img', fmt=luks size=1048576 key-secret=keysec0 iter-time=10 + +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} +Job failed: Failed to get shared "consistent read" lock +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} +Job failed: Failed to get shared "consistent read" lock +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} +qemu-img: Failed to get shared "consistent read" lock +Is another process using the image [TEST_DIR/test.img]? + +Formatting 'TEST_DIR/test.img', fmt=luks size=1048576 key-secret=keysec0 iter-time=10 + +Job failed: Block node is read-only +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} +Job failed: Failed to get shared "consistent read" lock +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} +Job failed: Failed to get shared "consistent read" lock +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} +Formatting 'TEST_DIR/test.img', fmt=luks size=1048576 key-secret=keysec0 iter-time=10 + +{"return": {}} +{"error": {"class": "GenericError", "desc": "Failed to get \"write\" lock"}} +Formatting 'TEST_DIR/test.img', fmt=luks size=1048576 key-secret=keysec0 iter-time=10 + +{"return": {}} +{"return": {}} +.... +---------------------------------------------------------------------- +Ran 4 tests + +OK diff --git a/tests/qemu-iotests/299 b/tests/qemu-iotests/299 new file mode 100644 index 0000000000000000000000000000000000000000..e129c7f7cb9a56ba4207460867f4c9f8576107cf --- /dev/null +++ b/tests/qemu-iotests/299 @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# +# Test shutdown when bitmap is exported through NBD server +# +# Copyright (c) 2020 Virtuozzo International GmbH. +# +# 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 . +# + +import iotests + +# The test is unrelated to formats, restrict it to qcow2 to avoid extra runs +iotests.script_initialize( + supported_fmts=['qcow2'], +) + +nbd_sock = iotests.file_path('nbd.sock', base_dir=iotests.sock_dir) +nbd_uri = 'nbd+unix:///disk?socket=' + nbd_sock +size = 1024 * 1024 + +vm = iotests.VM() +vm.launch() + +vm.qmp_log('blockdev-add', **{ + 'node-name': 'disk', + 'driver': 'null-co', + 'size': 1024 * 1024, +}) + +vm.qmp_log('block-dirty-bitmap-add', **{ + 'node': 'disk', + 'name': 'bitmap0' +}) + +vm.qmp_log('nbd-server-start', **{ + 'addr': { + 'type': 'unix', + 'data': {'path': nbd_sock} + } +}, filters=[iotests.filter_qmp_testfiles]) + +vm.qmp_log('nbd-server-add', **{ + 'device': 'disk', + 'writable': True, + 'bitmap': 'bitmap0' +}) + +p = iotests.QemuIoInteractive('-f', 'raw', nbd_uri) +# wait for connection and check it: +iotests.log(p.cmd('read 0 512').rstrip(), filters=[iotests.filter_qemu_io]) + +vm.shutdown() + +p.close() diff --git a/tests/qemu-iotests/299.out b/tests/qemu-iotests/299.out new file mode 100644 index 0000000000000000000000000000000000000000..bba4252923c69ba964ae250959ecbeac1b316bae --- /dev/null +++ b/tests/qemu-iotests/299.out @@ -0,0 +1,10 @@ +{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "disk", "size": 1048576}} +{"return": {}} +{"execute": "block-dirty-bitmap-add", "arguments": {"name": "bitmap0", "node": "disk"}} +{"return": {}} +{"execute": "nbd-server-start", "arguments": {"addr": {"data": {"path": "SOCK_DIR/PID-nbd.sock"}, "type": "unix"}}} +{"return": {}} +{"execute": "nbd-server-add", "arguments": {"bitmap": "bitmap0", "device": "disk", "writable": true}} +{"return": {}} +read 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/300 b/tests/qemu-iotests/300 new file mode 100755 index 0000000000000000000000000000000000000000..5b75121b8496ea09674b13f9802233bfba040fe8 --- /dev/null +++ b/tests/qemu-iotests/300 @@ -0,0 +1,593 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 Red Hat, Inc. +# +# Tests for dirty bitmaps migration with node aliases +# +# 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 . +# + +import os +import random +import re +from typing import Dict, List, Optional, Union +import iotests +import qemu + +BlockBitmapMapping = List[Dict[str, Union[str, List[Dict[str, str]]]]] + +assert iotests.sock_dir is not None +mig_sock = os.path.join(iotests.sock_dir, 'mig_sock') + + +class TestDirtyBitmapMigration(iotests.QMPTestCase): + src_node_name: str = '' + dst_node_name: str = '' + src_bmap_name: str = '' + dst_bmap_name: str = '' + + def setUp(self) -> None: + self.vm_a = iotests.VM(path_suffix='-a') + self.vm_a.add_blockdev(f'node-name={self.src_node_name},' + 'driver=null-co') + self.vm_a.launch() + + self.vm_b = iotests.VM(path_suffix='-b') + self.vm_b.add_blockdev(f'node-name={self.dst_node_name},' + 'driver=null-co') + self.vm_b.add_incoming(f'unix:{mig_sock}') + self.vm_b.launch() + + result = self.vm_a.qmp('block-dirty-bitmap-add', + node=self.src_node_name, + name=self.src_bmap_name) + self.assert_qmp(result, 'return', {}) + + # Dirty some random megabytes + for _ in range(9): + mb_ofs = random.randrange(1024) + self.vm_a.hmp_qemu_io(self.src_node_name, f'discard {mb_ofs}M 1M') + + result = self.vm_a.qmp('x-debug-block-dirty-bitmap-sha256', + node=self.src_node_name, + name=self.src_bmap_name) + self.bitmap_hash_reference = result['return']['sha256'] + + caps = [{'capability': name, 'state': True} + for name in ('dirty-bitmaps', 'events')] + + for vm in (self.vm_a, self.vm_b): + result = vm.qmp('migrate-set-capabilities', capabilities=caps) + self.assert_qmp(result, 'return', {}) + + def tearDown(self) -> None: + self.vm_a.shutdown() + self.vm_b.shutdown() + try: + os.remove(mig_sock) + except OSError: + pass + + def check_bitmap(self, bitmap_name_valid: bool) -> None: + result = self.vm_b.qmp('x-debug-block-dirty-bitmap-sha256', + node=self.dst_node_name, + name=self.dst_bmap_name) + if bitmap_name_valid: + self.assert_qmp(result, 'return/sha256', + self.bitmap_hash_reference) + else: + self.assert_qmp(result, 'error/desc', + f"Dirty bitmap '{self.dst_bmap_name}' not found") + + def migrate(self, bitmap_name_valid: bool = True, + migration_success: bool = True) -> None: + result = self.vm_a.qmp('migrate', uri=f'unix:{mig_sock}') + self.assert_qmp(result, 'return', {}) + + with iotests.Timeout(5, 'Timeout waiting for migration to complete'): + self.assertEqual(self.vm_a.wait_migration('postmigrate'), + migration_success) + self.assertEqual(self.vm_b.wait_migration('running'), + migration_success) + + if migration_success: + self.check_bitmap(bitmap_name_valid) + + def verify_dest_error(self, msg: Optional[str]) -> None: + """ + Check whether the given error message is present in vm_b's log. + (vm_b is shut down to do so.) + If @msg is None, check that there has not been any error. + """ + self.vm_b.shutdown() + if msg is None: + self.assertNotIn('qemu-system-', self.vm_b.get_log()) + else: + self.assertIn(msg, self.vm_b.get_log()) + + @staticmethod + def mapping(node_name: str, node_alias: str, + bitmap_name: str, bitmap_alias: str) -> BlockBitmapMapping: + return [{ + 'node-name': node_name, + 'alias': node_alias, + 'bitmaps': [{ + 'name': bitmap_name, + 'alias': bitmap_alias + }] + }] + + def set_mapping(self, vm: iotests.VM, mapping: BlockBitmapMapping, + error: Optional[str] = None) -> None: + """ + Invoke migrate-set-parameters on @vm to set the given @mapping. + Check for success if @error is None, or verify the error message + if it is not. + On success, verify that "info migrate_parameters" on HMP returns + our mapping. (Just to check its formatting code.) + """ + result = vm.qmp('migrate-set-parameters', + block_bitmap_mapping=mapping) + + if error is None: + self.assert_qmp(result, 'return', {}) + + result = vm.qmp('human-monitor-command', + command_line='info migrate_parameters') + + m = re.search(r'^block-bitmap-mapping:\r?(\n .*)*\n', + result['return'], flags=re.MULTILINE) + hmp_mapping = m.group(0).replace('\r', '') if m else None + + self.assertEqual(hmp_mapping, self.to_hmp_mapping(mapping)) + else: + self.assert_qmp(result, 'error/desc', error) + + @staticmethod + def to_hmp_mapping(mapping: BlockBitmapMapping) -> str: + result = 'block-bitmap-mapping:\n' + + for node in mapping: + result += f" '{node['node-name']}' -> '{node['alias']}'\n" + + assert isinstance(node['bitmaps'], list) + for bitmap in node['bitmaps']: + result += f" '{bitmap['name']}' -> '{bitmap['alias']}'\n" + + return result + + +class TestAliasMigration(TestDirtyBitmapMigration): + src_node_name = 'node0' + dst_node_name = 'node0' + src_bmap_name = 'bmap0' + dst_bmap_name = 'bmap0' + + def test_migration_without_alias(self) -> None: + self.migrate(self.src_node_name == self.dst_node_name and + self.src_bmap_name == self.dst_bmap_name) + + # Check for error message on the destination + if self.src_node_name != self.dst_node_name: + self.verify_dest_error(f"Cannot find " + f"device={self.src_node_name} nor " + f"node_name={self.src_node_name}") + else: + self.verify_dest_error(None) + + def test_alias_on_src_migration(self) -> None: + mapping = self.mapping(self.src_node_name, self.dst_node_name, + self.src_bmap_name, self.dst_bmap_name) + + self.set_mapping(self.vm_a, mapping) + self.migrate() + self.verify_dest_error(None) + + def test_alias_on_dst_migration(self) -> None: + mapping = self.mapping(self.dst_node_name, self.src_node_name, + self.dst_bmap_name, self.src_bmap_name) + + self.set_mapping(self.vm_b, mapping) + self.migrate() + self.verify_dest_error(None) + + def test_alias_on_both_migration(self) -> None: + src_map = self.mapping(self.src_node_name, 'node-alias', + self.src_bmap_name, 'bmap-alias') + + dst_map = self.mapping(self.dst_node_name, 'node-alias', + self.dst_bmap_name, 'bmap-alias') + + self.set_mapping(self.vm_a, src_map) + self.set_mapping(self.vm_b, dst_map) + self.migrate() + self.verify_dest_error(None) + + +class TestNodeAliasMigration(TestAliasMigration): + src_node_name = 'node-src' + dst_node_name = 'node-dst' + + +class TestBitmapAliasMigration(TestAliasMigration): + src_bmap_name = 'bmap-src' + dst_bmap_name = 'bmap-dst' + + +class TestFullAliasMigration(TestAliasMigration): + src_node_name = 'node-src' + dst_node_name = 'node-dst' + src_bmap_name = 'bmap-src' + dst_bmap_name = 'bmap-dst' + + +class TestLongBitmapNames(TestAliasMigration): + # Giving long bitmap names is OK, as long as there is a short alias for + # migration + src_bmap_name = 'a' * 512 + dst_bmap_name = 'b' * 512 + + # Skip all tests that do not use the intermediate alias + def test_migration_without_alias(self) -> None: + pass + + def test_alias_on_src_migration(self) -> None: + pass + + def test_alias_on_dst_migration(self) -> None: + pass + + +class TestBlockBitmapMappingErrors(TestDirtyBitmapMigration): + src_node_name = 'node0' + dst_node_name = 'node0' + src_bmap_name = 'bmap0' + dst_bmap_name = 'bmap0' + + """ + Note that mapping nodes or bitmaps that do not exist is not an error. + """ + + def test_non_injective_node_mapping(self) -> None: + mapping: BlockBitmapMapping = [ + { + 'node-name': 'node0', + 'alias': 'common-alias', + 'bitmaps': [{ + 'name': 'bmap0', + 'alias': 'bmap-alias0' + }] + }, + { + 'node-name': 'node1', + 'alias': 'common-alias', + 'bitmaps': [{ + 'name': 'bmap1', + 'alias': 'bmap-alias1' + }] + } + ] + + self.set_mapping(self.vm_a, mapping, + "Invalid mapping given for block-bitmap-mapping: " + "The node alias 'common-alias' is used twice") + + def test_non_injective_bitmap_mapping(self) -> None: + mapping: BlockBitmapMapping = [{ + 'node-name': 'node0', + 'alias': 'node-alias0', + 'bitmaps': [ + { + 'name': 'bmap0', + 'alias': 'common-alias' + }, + { + 'name': 'bmap1', + 'alias': 'common-alias' + } + ] + }] + + self.set_mapping(self.vm_a, mapping, + "Invalid mapping given for block-bitmap-mapping: " + "The bitmap alias 'node-alias0'/'common-alias' is " + "used twice") + + def test_ambiguous_node_mapping(self) -> None: + mapping: BlockBitmapMapping = [ + { + 'node-name': 'node0', + 'alias': 'node-alias0', + 'bitmaps': [{ + 'name': 'bmap0', + 'alias': 'bmap-alias0' + }] + }, + { + 'node-name': 'node0', + 'alias': 'node-alias1', + 'bitmaps': [{ + 'name': 'bmap0', + 'alias': 'bmap-alias0' + }] + } + ] + + self.set_mapping(self.vm_a, mapping, + "Invalid mapping given for block-bitmap-mapping: " + "The node name 'node0' is mapped twice") + + def test_ambiguous_bitmap_mapping(self) -> None: + mapping: BlockBitmapMapping = [{ + 'node-name': 'node0', + 'alias': 'node-alias0', + 'bitmaps': [ + { + 'name': 'bmap0', + 'alias': 'bmap-alias0' + }, + { + 'name': 'bmap0', + 'alias': 'bmap-alias1' + } + ] + }] + + self.set_mapping(self.vm_a, mapping, + "Invalid mapping given for block-bitmap-mapping: " + "The bitmap 'node0'/'bmap0' is mapped twice") + + def test_migratee_node_is_not_mapped_on_src(self) -> None: + self.set_mapping(self.vm_a, []) + # Should just ignore all bitmaps on unmapped nodes + self.migrate(False) + self.verify_dest_error(None) + + def test_migratee_node_is_not_mapped_on_dst(self) -> None: + self.set_mapping(self.vm_b, []) + self.migrate(False) + self.verify_dest_error(f"Unknown node alias '{self.src_node_name}'") + + def test_migratee_bitmap_is_not_mapped_on_src(self) -> None: + mapping: BlockBitmapMapping = [{ + 'node-name': self.src_node_name, + 'alias': self.dst_node_name, + 'bitmaps': [] + }] + + self.set_mapping(self.vm_a, mapping) + # Should just ignore all unmapped bitmaps + self.migrate(False) + self.verify_dest_error(None) + + def test_migratee_bitmap_is_not_mapped_on_dst(self) -> None: + mapping: BlockBitmapMapping = [{ + 'node-name': self.dst_node_name, + 'alias': self.src_node_name, + 'bitmaps': [] + }] + + self.set_mapping(self.vm_b, mapping) + self.migrate(False) + self.verify_dest_error(f"Unknown bitmap alias " + f"'{self.src_bmap_name}' " + f"on node '{self.dst_node_name}' " + f"(alias '{self.src_node_name}')") + + def test_unused_mapping_on_dst(self) -> None: + # Let the source not send any bitmaps + self.set_mapping(self.vm_a, []) + + # Establish some mapping on the destination + self.set_mapping(self.vm_b, []) + + # The fact that there is a mapping on B without any bitmaps + # being received should be fine, not fatal + self.migrate(False) + self.verify_dest_error(None) + + def test_non_wellformed_node_alias(self) -> None: + alias = '123-foo' + + mapping: BlockBitmapMapping = [{ + 'node-name': self.src_node_name, + 'alias': alias, + 'bitmaps': [] + }] + + self.set_mapping(self.vm_a, mapping, + f"Invalid mapping given for block-bitmap-mapping: " + f"The node alias '{alias}' is not well-formed") + + def test_node_alias_too_long(self) -> None: + alias = 'a' * 256 + + mapping: BlockBitmapMapping = [{ + 'node-name': self.src_node_name, + 'alias': alias, + 'bitmaps': [] + }] + + self.set_mapping(self.vm_a, mapping, + f"Invalid mapping given for block-bitmap-mapping: " + f"The node alias '{alias}' is longer than 255 bytes") + + def test_bitmap_alias_too_long(self) -> None: + alias = 'a' * 256 + + mapping = self.mapping(self.src_node_name, self.dst_node_name, + self.src_bmap_name, alias) + + self.set_mapping(self.vm_a, mapping, + f"Invalid mapping given for block-bitmap-mapping: " + f"The bitmap alias '{alias}' is longer than 255 " + f"bytes") + + def test_bitmap_name_too_long(self) -> None: + name = 'a' * 256 + + result = self.vm_a.qmp('block-dirty-bitmap-add', + node=self.src_node_name, + name=name) + self.assert_qmp(result, 'return', {}) + + self.migrate(False, False) + + # Check for the error in the source's log + self.vm_a.shutdown() + self.assertIn(f"Cannot migrate bitmap '{name}' on node " + f"'{self.src_node_name}': Name is longer than 255 bytes", + self.vm_a.get_log()) + + # Expect abnormal shutdown of the destination VM because of + # the failed migration + try: + self.vm_b.shutdown() + except qemu.machine.AbnormalShutdown: + pass + + def test_aliased_bitmap_name_too_long(self) -> None: + # Longer than the maximum for bitmap names + self.dst_bmap_name = 'a' * 1024 + + mapping = self.mapping(self.dst_node_name, self.src_node_name, + self.dst_bmap_name, self.src_bmap_name) + + # We would have to create this bitmap during migration, and + # that would fail, because the name is too long. Better to + # catch it early. + self.set_mapping(self.vm_b, mapping, + f"Invalid mapping given for block-bitmap-mapping: " + f"The bitmap name '{self.dst_bmap_name}' is longer " + f"than 1023 bytes") + + def test_node_name_too_long(self) -> None: + # Longer than the maximum for node names + self.dst_node_name = 'a' * 32 + + mapping = self.mapping(self.dst_node_name, self.src_node_name, + self.dst_bmap_name, self.src_bmap_name) + + # During migration, this would appear simply as a node that + # cannot be found. Still better to catch impossible node + # names early (similar to test_non_wellformed_node_alias). + self.set_mapping(self.vm_b, mapping, + f"Invalid mapping given for block-bitmap-mapping: " + f"The node name '{self.dst_node_name}' is longer " + f"than 31 bytes") + + +class TestCrossAliasMigration(TestDirtyBitmapMigration): + """ + Swap aliases, both to see that qemu does not get confused, and + that we can migrate multiple things at once. + + So we migrate this: + node-a.bmap-a -> node-b.bmap-b + node-a.bmap-b -> node-b.bmap-a + node-b.bmap-a -> node-a.bmap-b + node-b.bmap-b -> node-a.bmap-a + """ + + src_node_name = 'node-a' + dst_node_name = 'node-b' + src_bmap_name = 'bmap-a' + dst_bmap_name = 'bmap-b' + + def setUp(self) -> None: + TestDirtyBitmapMigration.setUp(self) + + # Now create another block device and let both have two bitmaps each + result = self.vm_a.qmp('blockdev-add', + node_name='node-b', driver='null-co') + self.assert_qmp(result, 'return', {}) + + result = self.vm_b.qmp('blockdev-add', + node_name='node-a', driver='null-co') + self.assert_qmp(result, 'return', {}) + + bmaps_to_add = (('node-a', 'bmap-b'), + ('node-b', 'bmap-a'), + ('node-b', 'bmap-b')) + + for (node, bmap) in bmaps_to_add: + result = self.vm_a.qmp('block-dirty-bitmap-add', + node=node, name=bmap) + self.assert_qmp(result, 'return', {}) + + @staticmethod + def cross_mapping() -> BlockBitmapMapping: + return [ + { + 'node-name': 'node-a', + 'alias': 'node-b', + 'bitmaps': [ + { + 'name': 'bmap-a', + 'alias': 'bmap-b' + }, + { + 'name': 'bmap-b', + 'alias': 'bmap-a' + } + ] + }, + { + 'node-name': 'node-b', + 'alias': 'node-a', + 'bitmaps': [ + { + 'name': 'bmap-b', + 'alias': 'bmap-a' + }, + { + 'name': 'bmap-a', + 'alias': 'bmap-b' + } + ] + } + ] + + def verify_dest_has_all_bitmaps(self) -> None: + bitmaps = self.vm_b.query_bitmaps() + + # Extract and sort bitmap names + for node in bitmaps: + bitmaps[node] = sorted((bmap['name'] for bmap in bitmaps[node])) + + self.assertEqual(bitmaps, + {'node-a': ['bmap-a', 'bmap-b'], + 'node-b': ['bmap-a', 'bmap-b']}) + + def test_alias_on_src(self) -> None: + self.set_mapping(self.vm_a, self.cross_mapping()) + + # Checks that node-a.bmap-a was migrated to node-b.bmap-b, and + # that is enough + self.migrate() + self.verify_dest_has_all_bitmaps() + self.verify_dest_error(None) + + def test_alias_on_dst(self) -> None: + self.set_mapping(self.vm_b, self.cross_mapping()) + + # Checks that node-a.bmap-a was migrated to node-b.bmap-b, and + # that is enough + self.migrate() + self.verify_dest_has_all_bitmaps() + self.verify_dest_error(None) + + +if __name__ == '__main__': + iotests.main(supported_protocols=['file']) diff --git a/tests/qemu-iotests/300.out b/tests/qemu-iotests/300.out new file mode 100644 index 0000000000000000000000000000000000000000..cafb8161f7b11e478e2c0834f228257fddcec155 --- /dev/null +++ b/tests/qemu-iotests/300.out @@ -0,0 +1,5 @@ +..................................... +---------------------------------------------------------------------- +Ran 37 tests + +OK diff --git a/tests/qemu-iotests/301 b/tests/qemu-iotests/301 new file mode 100755 index 0000000000000000000000000000000000000000..3823e956175a9817e094e8f46eb470a05747fb8b --- /dev/null +++ b/tests/qemu-iotests/301 @@ -0,0 +1,88 @@ +#!/usr/bin/env bash +# +# Test qcow backing file warnings +# +# Copyright (C) 2020 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 . +# + +seq=`basename $0` +echo "QA output created by $seq" + +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img + _rm_test_img "$TEST_IMG.qcow2" +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow +_supported_proto file +_supported_os Linux + +size=32M + +echo +echo "== qcow backed by qcow ==" + +TEST_IMG="$TEST_IMG.base" _make_test_img $size +_make_test_img -b "$TEST_IMG.base" $size +_img_info +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT $size +_img_info + +echo +echo "== mismatched command line detection ==" + +_make_test_img -b "$TEST_IMG.base" -F vmdk +_make_test_img -b "$TEST_IMG.base" -F vmdk $size +echo +# Use of -u bypasses the backing format sanity check +_make_test_img -u -b "$TEST_IMG.base" -F vmdk +_make_test_img -u -b "$TEST_IMG.base" -F vmdk $size +echo +# But the format must still be recognized +_make_test_img -b "$TEST_IMG.base" -F garbage $size +_make_test_img -u -b "$TEST_IMG.base" -F garbage $size +_img_info + +echo +echo "== qcow backed by raw ==" + +rm "$TEST_IMG.base" +truncate --size=$size "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" $size +_img_info +_make_test_img -b "$TEST_IMG.base" -F raw $size +_img_info + +echo +echo "== commit cannot change type of raw backing file ==" +TEST_IMG="$TEST_IMG.qcow2" IMGFMT=qcow2 _make_test_img $size +truncate --size=$size "$TEST_IMG.qcow2" +$QEMU_IMG convert -n -f raw -O $IMGFMT "$TEST_IMG.qcow2" "$TEST_IMG" +$QEMU_IMG commit -f $IMGFMT "$TEST_IMG" && echo "unexpected success" +TEST_IMG="$TEST_IMG.base" _img_info + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/301.out b/tests/qemu-iotests/301.out new file mode 100644 index 0000000000000000000000000000000000000000..9004dad6392f4a0ec685fb4a80d1ac669363fd4d --- /dev/null +++ b/tests/qemu-iotests/301.out @@ -0,0 +1,59 @@ +QA output created by 301 + +== qcow backed by qcow == +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=33554432 +qemu-img: warning: Deprecated use of backing file without explicit backing format (detected format of IMGFMT) +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 32 MiB (33554432 bytes) +cluster_size: 512 +backing file: TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 32 MiB (33554432 bytes) +cluster_size: 512 +backing file: TEST_DIR/t.IMGFMT.base + +== mismatched command line detection == +qemu-img: TEST_DIR/t.IMGFMT: invalid VMDK image descriptor +Could not open backing image. +qemu-img: TEST_DIR/t.IMGFMT: invalid VMDK image descriptor +Could not open backing image. + +qemu-img: TEST_DIR/t.IMGFMT: Image creation needs a size parameter +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=vmdk + +qemu-img: TEST_DIR/t.IMGFMT: Unknown driver 'garbage' +Could not open backing image. +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=garbage +qemu-img: TEST_DIR/t.IMGFMT: unrecognized backing format 'garbage' +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 32 MiB (33554432 bytes) +cluster_size: 512 +backing file: TEST_DIR/t.IMGFMT.base + +== qcow backed by raw == +qemu-img: warning: Deprecated use of backing file without explicit backing format (detected format of raw) +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.base +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 32 MiB (33554432 bytes) +cluster_size: 512 +backing file: TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 32 MiB (33554432 bytes) +cluster_size: 512 +backing file: TEST_DIR/t.IMGFMT.base + +== commit cannot change type of raw backing file == +Formatting 'TEST_DIR/t.qcow.IMGFMT', fmt=IMGFMT size=33554432 +qemu-img: Block job failed: Operation not permitted +image: TEST_DIR/t.IMGFMT.base +file format: raw +virtual size: 32 MiB (33554432 bytes) +*** done diff --git a/tests/qemu-iotests/302 b/tests/qemu-iotests/302 new file mode 100755 index 0000000000000000000000000000000000000000..a8506bda15921c9304fd0ebcc8572995a6b1892c --- /dev/null +++ b/tests/qemu-iotests/302 @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +# +# Tests converting qcow2 compressed to NBD +# +# Copyright (c) 2020 Nir Soffer +# +# 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 . +# +# owner=nirsof@gmail.com + +import io +import tarfile + +import iotests + +from iotests import ( + file_path, + qemu_img, + qemu_img_check, + qemu_img_create, + qemu_img_log, + qemu_img_measure, + qemu_io, + qemu_nbd_popen, +) + +iotests.script_initialize(supported_fmts=["qcow2"]) + +# Create source disk. Using qcow2 to enable strict comparing later, and +# avoid issues with random filesystem on CI environment. +src_disk = file_path("disk.qcow2") +qemu_img_create("-f", iotests.imgfmt, src_disk, "1g") +qemu_io("-f", iotests.imgfmt, "-c", "write 1m 64k", src_disk) + +# The use case is writing qcow2 image directly into an ova file, which +# is a tar file with specific layout. This is tricky since we don't know the +# size of the image before compressing, so we have to do: +# 1. Add an ovf file. +# 2. Find the offset of the next member data. +# 3. Make room for image data, allocating for the worst case. +# 4. Write compressed image data into the tar. +# 5. Add a tar entry with the actual image size. +# 6. Shrink the tar to the actual size, aligned to 512 bytes. + +tar_file = file_path("test.ova") + +with tarfile.open(tar_file, "w") as tar: + + # 1. Add an ovf file. + + ovf_data = b"" + ovf = tarfile.TarInfo("vm.ovf") + ovf.size = len(ovf_data) + tar.addfile(ovf, io.BytesIO(ovf_data)) + + # 2. Find the offset of the next member data. + + offset = tar.fileobj.tell() + 512 + + # 3. Make room for image data, allocating for the worst case. + + measure = qemu_img_measure("-O", "qcow2", src_disk) + tar.fileobj.truncate(offset + measure["required"]) + + # 4. Write compressed image data into the tar. + + nbd_sock = file_path("nbd-sock", base_dir=iotests.sock_dir) + nbd_uri = "nbd+unix:///exp?socket=" + nbd_sock + + # Use raw format to allow creating qcow2 directly into tar file. + with qemu_nbd_popen( + "--socket", nbd_sock, + "--export-name", "exp", + "--format", "raw", + "--offset", str(offset), + tar_file): + + iotests.log("=== Target image info ===") + qemu_img_log("info", nbd_uri) + + qemu_img( + "convert", + "-f", iotests.imgfmt, + "-O", "qcow2", + "-c", + src_disk, + nbd_uri) + + iotests.log("=== Converted image info ===") + qemu_img_log("info", nbd_uri) + + iotests.log("=== Converted image check ===") + qemu_img_log("check", nbd_uri) + + iotests.log("=== Comparing to source disk ===") + qemu_img_log("compare", src_disk, nbd_uri) + + actual_size = qemu_img_check(nbd_uri)["image-end-offset"] + + # 5. Add a tar entry with the actual image size. + + disk = tarfile.TarInfo("disk") + disk.size = actual_size + tar.addfile(disk) + + # 6. Shrink the tar to the actual size, aligned to 512 bytes. + + tar_size = offset + (disk.size + 511) & ~511 + tar.fileobj.seek(tar_size) + tar.fileobj.truncate(tar_size) + +with tarfile.open(tar_file) as tar: + members = [{"name": m.name, "size": m.size, "offset": m.offset_data} + for m in tar] + iotests.log("=== OVA file contents ===") + iotests.log(members) diff --git a/tests/qemu-iotests/302.out b/tests/qemu-iotests/302.out new file mode 100644 index 0000000000000000000000000000000000000000..e2f6077e8330854905882a9175a8f6fc36cbb12b --- /dev/null +++ b/tests/qemu-iotests/302.out @@ -0,0 +1,32 @@ +Start NBD server +=== Target image info === +image: nbd+unix:///exp?socket=SOCK_DIR/PID-nbd-sock +file format: raw +virtual size: 448 KiB (458752 bytes) +disk size: unavailable + +=== Converted image info === +image: nbd+unix:///exp?socket=SOCK_DIR/PID-nbd-sock +file format: qcow2 +virtual size: 1 GiB (1073741824 bytes) +disk size: unavailable +cluster_size: 65536 +Format specific information: + compat: 1.1 + compression type: zlib + lazy refcounts: false + refcount bits: 16 + corrupt: false + extended l2: false + +=== Converted image check === +No errors were found on the image. +1/16384 = 0.01% allocated, 100.00% fragmented, 100.00% compressed clusters +Image end offset: 393216 + +=== Comparing to source disk === +Images are identical. + +Kill NBD server +=== OVA file contents === +[{"name": "vm.ovf", "offset": 512, "size": 6}, {"name": "disk", "offset": 1536, "size": 393216}] diff --git a/tests/qemu-iotests/303 b/tests/qemu-iotests/303 new file mode 100755 index 0000000000000000000000000000000000000000..6c2177448348bb18b36811f3e6332a8e53eceea8 --- /dev/null +++ b/tests/qemu-iotests/303 @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +# +# Test for dumping of qcow2 image metadata +# +# Copyright (c) 2020 Virtuozzo International GmbH +# +# 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 . +# + +import iotests +import subprocess +from iotests import qemu_img_create, qemu_io, file_path, log, filter_qemu_io + +iotests.script_initialize(supported_fmts=['qcow2']) + +disk = file_path('disk') +chunk = 1024 * 1024 + + +def create_bitmap(bitmap_number, disabled): + granularity = 1 << (14 + bitmap_number) + bitmap_name = 'bitmap-' + str(bitmap_number) + args = ['bitmap', '--add', '-g', f'{granularity}', '-f', iotests.imgfmt, + disk, bitmap_name] + if disabled: + args.append('--disable') + + iotests.qemu_img_pipe(*args) + + +def write_to_disk(offset, size): + write = f'write {offset} {size}' + log(qemu_io('-c', write, disk), filters=[filter_qemu_io]) + + +def add_bitmap(num, begin, end, disabled): + log(f'Add bitmap {num}') + create_bitmap(num, disabled) + for i in range(begin, end): + write_to_disk((i) * chunk, chunk) + log('') + + +qemu_img_create('-f', iotests.imgfmt, disk, '10M') + +add_bitmap(1, 0, 6, False) +add_bitmap(2, 6, 8, True) +dump = ['qcow2.py', disk, 'dump-header'] +subprocess.run(dump) +# Dump the metadata in JSON format +dump.append('-j') +subprocess.run(dump) diff --git a/tests/qemu-iotests/303.out b/tests/qemu-iotests/303.out new file mode 100644 index 0000000000000000000000000000000000000000..7c16998587840607918fd777fb99c42625b52d5b --- /dev/null +++ b/tests/qemu-iotests/303.out @@ -0,0 +1,158 @@ +Add bitmap 1 +wrote 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +wrote 1048576/1048576 bytes at offset 1048576 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +wrote 1048576/1048576 bytes at offset 2097152 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +wrote 1048576/1048576 bytes at offset 3145728 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +wrote 1048576/1048576 bytes at offset 4194304 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +wrote 1048576/1048576 bytes at offset 5242880 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + + +Add bitmap 2 +wrote 1048576/1048576 bytes at offset 6291456 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +wrote 1048576/1048576 bytes at offset 7340032 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + + +magic 0x514649fb +version 3 +backing_file_offset 0x0 +backing_file_size 0x0 +cluster_bits 16 +size 10485760 +crypt_method 0 +l1_size 1 +l1_table_offset 0x30000 +refcount_table_offset 0x10000 +refcount_table_clusters 1 +nb_snapshots 0 +snapshot_offset 0x0 +incompatible_features [] +compatible_features [] +autoclear_features [0] +refcount_order 4 +header_length 112 + +Header extension: +magic 0x6803f857 (Feature table) +length 384 +data + +Header extension: +magic 0x23852875 (Bitmaps) +length 24 +nb_bitmaps 2 +reserved32 0 +bitmap_directory_size 0x40 +bitmap_directory_offset 0x9d0000 + +Bitmap name bitmap-1 +bitmap_table_offset 0x9b0000 +bitmap_table_size 1 +flags 0x2 (['auto']) +type 1 +granularity_bits 15 +name_size 8 +extra_data_size 0 +Bitmap table type size offset +0 serialized 65536 10092544 + +Bitmap name bitmap-2 +bitmap_table_offset 0x9c0000 +bitmap_table_size 1 +flags 0x0 ([]) +type 1 +granularity_bits 16 +name_size 8 +extra_data_size 0 +Bitmap table type size offset +0 all-zeroes 0 0 + +{ + "magic": 1363560955, + "version": 3, + "backing_file_offset": 0, + "backing_file_size": 0, + "cluster_bits": 16, + "size": 10485760, + "crypt_method": 0, + "l1_size": 1, + "l1_table_offset": 196608, + "refcount_table_offset": 65536, + "refcount_table_clusters": 1, + "nb_snapshots": 0, + "snapshot_offset": 0, + "incompatible_features": 0, + "compatible_features": 0, + "autoclear_features": 1, + "refcount_order": 4, + "header_length": 112 +} + +[ + { + "name": "Feature table", + "magic": 1745090647, + "length": 384, + "data_str": "" + }, + { + "name": "Bitmaps", + "magic": 595929205, + "length": 24, + "data": { + "nb_bitmaps": 2, + "reserved32": 0, + "bitmap_directory_size": 64, + "bitmap_directory_offset": 10289152, + "bitmap_directory": [ + { + "name": "bitmap-1", + "bitmap_table_offset": 10158080, + "bitmap_table_size": 1, + "flags": 2, + "type": 1, + "granularity_bits": 15, + "name_size": 8, + "extra_data_size": 0, + "bitmap_table": [ + { + "type": "serialized", + "offset": 10092544, + "reserved": 0 + } + ] + }, + { + "name": "bitmap-2", + "bitmap_table_offset": 10223616, + "bitmap_table_size": 1, + "flags": 0, + "type": 1, + "granularity_bits": 16, + "name_size": 8, + "extra_data_size": 0, + "bitmap_table": [ + { + "type": "all-zeroes", + "offset": 0, + "reserved": 0 + } + ] + } + ] + } + } +] diff --git a/tests/qemu-iotests/304 b/tests/qemu-iotests/304 new file mode 100755 index 0000000000000000000000000000000000000000..aaf9e1461728034b7e02bfc6ef6e32002454108d --- /dev/null +++ b/tests/qemu-iotests/304 @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +# +# Tests dirty-bitmap backup with unaligned bitmap granularity +# +# Copyright (c) 2020 Proxmox Server Solutions +# +# 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 . +# +# owner=s.reiter@proxmox.com + +import iotests +from iotests import qemu_img_create, qemu_img_log, file_path + +iotests.script_initialize(supported_fmts=['qcow2'], + supported_protocols=['file']) + +test_img = file_path('test.qcow2') +target_img = file_path('target.qcow2') + +# unaligned by one byte +image_len = 4097 +bitmap_granularity = 4096 + +qemu_img_create('-f', iotests.imgfmt, test_img, str(image_len)) + +# create VM +vm = iotests.VM().add_drive(test_img) +vm.launch() + +# write to the entire image +vm.hmp_qemu_io('drive0', 'write -P0x16 0 4096'); +vm.hmp_qemu_io('drive0', 'write -P0x17 4096 1'); + +# do backup and wait for completion +vm.qmp('drive-backup', **{ + 'device': 'drive0', + 'sync': 'full', + 'target': target_img +}) + +event = vm.event_wait(name='BLOCK_JOB_COMPLETED', + match={'data': {'device': 'drive0'}}, + timeout=5.0) + +# shutdown to sync images +vm.shutdown() + +# backup succeeded, check if image is correct +qemu_img_log('compare', test_img, target_img) diff --git a/tests/qemu-iotests/304.out b/tests/qemu-iotests/304.out new file mode 100644 index 0000000000000000000000000000000000000000..381cc056f7e537b22aa95edb2c444537da966a34 --- /dev/null +++ b/tests/qemu-iotests/304.out @@ -0,0 +1,2 @@ +Images are identical. + diff --git a/tests/qemu-iotests/305 b/tests/qemu-iotests/305 new file mode 100755 index 0000000000000000000000000000000000000000..768818af4a99a021108c65812641b54dd44ce540 --- /dev/null +++ b/tests/qemu-iotests/305 @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +# +# Test the handling of errors in write requests with multiple allocations +# +# Copyright (C) 2020 Igalia, S.L. +# Author: Alberto Garcia +# +# 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=berto@igalia.com + +seq=`basename $0` +echo "QA output created by $seq" + +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux +_unsupported_imgopts cluster_size refcount_bits extended_l2 compat=0.10 data_file + +echo '### Create the image' +_make_test_img -o refcount_bits=64,cluster_size=1k 1M + +# The reference counts of the clusters for the first 123k of this +# write request are stored in the first refcount block. The last +# cluster (guest offset 123k) is referenced in the second refcount +# block. +echo '### Fill the first refcount block and one data cluster from the second' +$QEMU_IO -c 'write 0 124k' "$TEST_IMG" | _filter_qemu_io + +echo '### Discard two of the last data clusters, leave one in the middle' +$QEMU_IO -c 'discard 121k 1k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c 'discard 123k 1k' "$TEST_IMG" | _filter_qemu_io + +echo '### Corrupt the offset of the second refcount block' +refcount_table_offset=$(peek_file_be "$TEST_IMG" 48 8) +poke_file "$TEST_IMG" $(($refcount_table_offset+14)) "\x06" + +# This tries to allocate the two clusters discarded earlier (guest +# offsets 121k and 123k). Their reference counts are in the first and +# second refcount blocks respectively, but only the first one can be +# allocated correctly because the second entry of the refcount table +# is corrupted. +echo '### Try to allocate the discarded clusters again' +$QEMU_IO -c 'write 121k 3k' "$TEST_IMG" | _filter_qemu_io + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/305.out b/tests/qemu-iotests/305.out new file mode 100644 index 0000000000000000000000000000000000000000..538019e72601dbe8ec27731938194ed1768d3477 --- /dev/null +++ b/tests/qemu-iotests/305.out @@ -0,0 +1,16 @@ +QA output created by 305 +### Create the image +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 +### Fill the first refcount block and one data cluster from the second +wrote 126976/126976 bytes at offset 0 +124 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +### Discard two of the last data clusters, leave one in the middle +discard 1024/1024 bytes at offset 123904 +1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +discard 1024/1024 bytes at offset 125952 +1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +### Corrupt the offset of the second refcount block +### Try to allocate the discarded clusters again +qcow2: Marking image as corrupt: Refblock offset 0x20600 unaligned (reftable index: 0x1); further corruption events will be suppressed +write failed: Input/output error +*** done diff --git a/tests/qemu-iotests/307 b/tests/qemu-iotests/307 new file mode 100755 index 0000000000000000000000000000000000000000..de7c25fcfc456739d3262ca1c396f7b8f10e178e --- /dev/null +++ b/tests/qemu-iotests/307 @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 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: Kevin Wolf +# +# Test the block export QAPI interfaces + +import iotests +import os + +# Need a writable image format (but not vpc, which rounds the image size, nor +# luks which requires special command lines) +iotests.script_initialize( + supported_fmts=['generic'], + unsupported_fmts=['luks', 'vpc'], + supported_platforms=['linux'], +) + +with iotests.FilePath('image') as img, \ + iotests.FilePath('socket', base_dir=iotests.sock_dir) as socket, \ + iotests.VM() as vm: + + iotests.qemu_img('create', '-f', iotests.imgfmt, img, '64M') + iotests.qemu_io_log('-f', iotests.imgfmt, '-c', 'write -P 0x11 0 4k', img) + + iotests.log('=== Launch VM ===') + + virtio_scsi_device = iotests.get_virtio_scsi_device() + + vm.add_object('iothread,id=iothread0') + vm.add_blockdev(f'file,filename={img},node-name=file') + vm.add_blockdev(f'{iotests.imgfmt},file=file,node-name=fmt') + vm.add_blockdev('raw,file=file,node-name=ro,read-only=on') + vm.add_device(f'id=scsi0,driver={virtio_scsi_device},iothread=iothread0') + vm.launch() + + vm.qmp_log('nbd-server-start', + addr={'type': 'unix', 'data': {'path': socket}}, + filters=(iotests.filter_qmp_testfiles, )) + vm.qmp_log('query-block-exports') + + iotests.log('\n=== Create a read-only NBD export ===') + + vm.qmp_log('block-export-add', id='export0', type='nbd', node_name='fmt') + vm.qmp_log('query-block-exports') + + iotests.qemu_nbd_list_log('-k', socket) + + iotests.log('\n=== Try a few invalid things ===') + + vm.qmp_log('block-export-add', id='#invalid', type='nbd', node_name='fmt') + vm.qmp_log('block-export-add', id='export0', type='nbd', node_name='fmt') + vm.qmp_log('block-export-add', id='export1', type='nbd', node_name='ro', + writable=True) + vm.qmp_log('block-export-del', id='export1') + vm.qmp_log('query-block-exports') + + iotests.log('\n=== Move export to an iothread ===') + + vm.qmp_log('device_add', id='sda', driver='scsi-hd', drive='fmt') + vm.qmp_log('query-block-exports') + iotests.qemu_nbd_list_log('-k', socket) + + iotests.log('\n=== Add a writable export ===') + + # This fails because share-rw=off + vm.qmp_log('block-export-add', id='export1', type='nbd', node_name='fmt', + name='export1', writable=True, writethrough=True, + description='This is the writable second export') + + vm.qmp_log('device_del', id='sda') + event = vm.event_wait(name="DEVICE_DELETED", + match={'data': {'device': 'sda'}}) + iotests.log(event, filters=[iotests.filter_qmp_event]) + vm.qmp_log('device_add', id='sda', driver='scsi-hd', drive='fmt', + share_rw=True) + + # Now it should work + vm.qmp_log('block-export-add', id='export1', type='nbd', node_name='fmt', + name='export1', writable=True, writethrough=True, + description='This is the writable second export') + + vm.qmp_log('query-block-exports') + iotests.qemu_nbd_list_log('-k', socket) + + iotests.log('\n=== Connect qemu-io to export1, try removing exports ===') + + nbd_url = f'nbd+unix:///export1?socket={socket}' + qemu_io = iotests.QemuIoInteractive('-f', 'raw', nbd_url) + + iotests.log(qemu_io.cmd('read -P 0x11 0 4k'), + filters=[iotests.filter_qemu_io]) + iotests.log(qemu_io.cmd('write -P 0x22 4k 4k'), + filters=[iotests.filter_qemu_io]) + + vm.qmp_log('block-export-del', id='export1') + vm.qmp_log('block-export-del', id='export0') + iotests.log(vm.get_qmp_events_filtered()) + qemu_io.close() + + vm.qmp_log('query-block-exports') + iotests.qemu_nbd_list_log('-k', socket) + + iotests.log('\n=== Connect qemu-io again, try force removing ===') + + qemu_io = iotests.QemuIoInteractive('-f', 'raw', nbd_url) + vm.qmp_log('block-export-del', id='export1') + vm.qmp_log('block-export-del', id='export1', mode='hard') + + # This should fail now + iotests.log(qemu_io.cmd('read -P 0x11 0 4k')) + qemu_io.close() + + vm.qmp_log('query-block-exports') + iotests.qemu_nbd_list_log('-k', socket) + + iotests.log('\n=== Shut down QEMU ===') + vm.shutdown() diff --git a/tests/qemu-iotests/307.out b/tests/qemu-iotests/307.out new file mode 100644 index 0000000000000000000000000000000000000000..daa8ad2da0e94f9d8043bd8f1078af8324b5f127 --- /dev/null +++ b/tests/qemu-iotests/307.out @@ -0,0 +1,124 @@ +wrote 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +=== Launch VM === +{"execute": "nbd-server-start", "arguments": {"addr": {"data": {"path": "SOCK_DIR/PID-socket"}, "type": "unix"}}} +{"return": {}} +{"execute": "query-block-exports", "arguments": {}} +{"return": []} + +=== Create a read-only NBD export === +{"execute": "block-export-add", "arguments": {"id": "export0", "node-name": "fmt", "type": "nbd"}} +{"return": {}} +{"execute": "query-block-exports", "arguments": {}} +{"return": [{"id": "export0", "node-name": "fmt", "shutting-down": false, "type": "nbd"}]} +exports available: 1 + export: 'fmt' + size: 67108864 + flags: 0x58f ( readonly flush fua df multi cache ) + min block: XXX + opt block: XXX + max block: XXX + available meta contexts: 1 + base:allocation + + +=== Try a few invalid things === +{"execute": "block-export-add", "arguments": {"id": "#invalid", "node-name": "fmt", "type": "nbd"}} +{"error": {"class": "GenericError", "desc": "Invalid block export id"}} +{"execute": "block-export-add", "arguments": {"id": "export0", "node-name": "fmt", "type": "nbd"}} +{"error": {"class": "GenericError", "desc": "Block export id 'export0' is already in use"}} +{"execute": "block-export-add", "arguments": {"id": "export1", "node-name": "ro", "type": "nbd", "writable": true}} +{"error": {"class": "GenericError", "desc": "Cannot export read-only node as writable"}} +{"execute": "block-export-del", "arguments": {"id": "export1"}} +{"error": {"class": "GenericError", "desc": "Export 'export1' is not found"}} +{"execute": "query-block-exports", "arguments": {}} +{"return": [{"id": "export0", "node-name": "fmt", "shutting-down": false, "type": "nbd"}]} + +=== Move export to an iothread === +{"execute": "device_add", "arguments": {"drive": "fmt", "driver": "scsi-hd", "id": "sda"}} +{"return": {}} +{"execute": "query-block-exports", "arguments": {}} +{"return": [{"id": "export0", "node-name": "fmt", "shutting-down": false, "type": "nbd"}]} +exports available: 1 + export: 'fmt' + size: 67108864 + flags: 0x58f ( readonly flush fua df multi cache ) + min block: XXX + opt block: XXX + max block: XXX + available meta contexts: 1 + base:allocation + + +=== Add a writable export === +{"execute": "block-export-add", "arguments": {"description": "This is the writable second export", "id": "export1", "name": "export1", "node-name": "fmt", "type": "nbd", "writable": true, "writethrough": true}} +{"error": {"class": "GenericError", "desc": "Conflicts with use by sda as 'root', which does not allow 'write' on fmt"}} +{"execute": "device_del", "arguments": {"id": "sda"}} +{"return": {}} +{"data": {"device": "sda", "path": "/machine/peripheral/sda"}, "event": "DEVICE_DELETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"execute": "device_add", "arguments": {"drive": "fmt", "driver": "scsi-hd", "id": "sda", "share-rw": true}} +{"return": {}} +{"execute": "block-export-add", "arguments": {"description": "This is the writable second export", "id": "export1", "name": "export1", "node-name": "fmt", "type": "nbd", "writable": true, "writethrough": true}} +{"return": {}} +{"execute": "query-block-exports", "arguments": {}} +{"return": [{"id": "export1", "node-name": "fmt", "shutting-down": false, "type": "nbd"}, {"id": "export0", "node-name": "fmt", "shutting-down": false, "type": "nbd"}]} +exports available: 2 + export: 'fmt' + size: 67108864 + flags: 0x58f ( readonly flush fua df multi cache ) + min block: XXX + opt block: XXX + max block: XXX + available meta contexts: 1 + base:allocation + export: 'export1' + description: This is the writable second export + size: 67108864 + flags: 0xced ( flush fua trim zeroes df cache fast-zero ) + min block: XXX + opt block: XXX + max block: XXX + available meta contexts: 1 + base:allocation + + +=== Connect qemu-io to export1, try removing exports === +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +wrote 4096/4096 bytes at offset 4096 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +{"execute": "block-export-del", "arguments": {"id": "export1"}} +{"error": {"class": "GenericError", "desc": "export 'export1' still in use"}} +{"execute": "block-export-del", "arguments": {"id": "export0"}} +{"return": {}} +[{"data": {"id": "export0"}, "event": "BLOCK_EXPORT_DELETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}] +{"execute": "query-block-exports", "arguments": {}} +{"return": [{"id": "export1", "node-name": "fmt", "shutting-down": false, "type": "nbd"}]} +exports available: 1 + export: 'export1' + description: This is the writable second export + size: 67108864 + flags: 0xced ( flush fua trim zeroes df cache fast-zero ) + min block: XXX + opt block: XXX + max block: XXX + available meta contexts: 1 + base:allocation + + +=== Connect qemu-io again, try force removing === +{"execute": "block-export-del", "arguments": {"id": "export1"}} +{"error": {"class": "GenericError", "desc": "export 'export1' still in use"}} +{"execute": "block-export-del", "arguments": {"id": "export1", "mode": "hard"}} +{"return": {}} +read failed: Input/output error + +{"execute": "query-block-exports", "arguments": {}} +{"return": []} +exports available: 0 + + +=== Shut down QEMU === diff --git a/tests/qemu-iotests/309 b/tests/qemu-iotests/309 new file mode 100755 index 0000000000000000000000000000000000000000..fb61157c2e1de39c9927d43c631ca9c8a52946b6 --- /dev/null +++ b/tests/qemu-iotests/309 @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# +# Test qemu-nbd -A +# +# Copyright (C) 2018-2020 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 . +# + +seq="$(basename $0)" +echo "QA output created by $seq" + +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img + nbd_server_stop +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter +. ./common.nbd + +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux +_require_command QEMU_NBD + +echo +echo "=== Initial image setup ===" +echo + +TEST_IMG="$TEST_IMG.base" _make_test_img 4M +$QEMU_IO -c 'w 0 2M' -f $IMGFMT "$TEST_IMG.base" | _filter_qemu_io +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT 4M +$QEMU_IO -c 'w 1M 2M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io + +echo +echo "=== Check allocation over NBD ===" +echo + +$QEMU_IMG map --output=json -f qcow2 "$TEST_IMG" +IMG="driver=nbd,server.type=unix,server.path=$nbd_unix_socket" +nbd_server_start_unix_socket -r -f qcow2 -A "$TEST_IMG" +# Normal -f raw NBD block status loses access to allocation information +$QEMU_IMG map --output=json --image-opts \ + "$IMG" | _filter_qemu_img_map +# But when we use -A, coupled with x-dirty-bitmap in the client for feeding +# 2-bit block status from an alternative NBD metadata context (note that +# the client code for x-dirty-bitmap intentionally collapses all depths +# beyond 2 into a single value), we can determine: +# unallocated (depth 0) => "zero":false, "data":true +# local (depth 1) => "zero":false, "data":false +# backing (depth 2+) => "zero":true, "data":true +$QEMU_IMG map --output=json --image-opts \ + "$IMG,x-dirty-bitmap=qemu:allocation-depth" | _filter_qemu_img_map +# More accurate results can be obtained by other NBD clients such as +# libnbd, but this test works without such external dependencies. + +# success, all done +echo '*** done' +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/309.out b/tests/qemu-iotests/309.out new file mode 100644 index 0000000000000000000000000000000000000000..db75bb6b0df90b78f8fca602893984d93e1b76b7 --- /dev/null +++ b/tests/qemu-iotests/309.out @@ -0,0 +1,22 @@ +QA output created by 309 + +=== Initial image setup === + +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=4194304 +wrote 2097152/2097152 bytes at offset 0 +2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +wrote 2097152/2097152 bytes at offset 1048576 +2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +=== Check allocation over NBD === + +[{ "start": 0, "length": 1048576, "depth": 1, "zero": false, "data": true, "offset": 327680}, +{ "start": 1048576, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": 327680}, +{ "start": 3145728, "length": 1048576, "depth": 1, "zero": true, "data": false}] +[{ "start": 0, "length": 3145728, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, +{ "start": 3145728, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] +[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": true, "offset": OFFSET}, +{ "start": 1048576, "length": 2097152, "depth": 0, "zero": false, "data": false}, +{ "start": 3145728, "length": 1048576, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] +*** done diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check index 9c461cf76de8f9bebd54273349f804df7241d774..678b6e49103a5ebd1abe488f051479510febe1dd 100755 --- a/tests/qemu-iotests/check +++ b/tests/qemu-iotests/check @@ -44,7 +44,7 @@ then _init_error "failed to obtain source tree name from check symlink" fi source_iotests=$(cd "$source_iotests"; pwd) || _init_error "failed to enter source tree" - build_iotests=$PWD + build_iotests=$(cd "$(dirname "$0")"; pwd) else # called from the source tree source_iotests=$PWD @@ -272,7 +272,6 @@ image protocol options -nbd test nbd -ssh test ssh -nfs test nfs - -vxhs test vxhs other options -xdiff graphical mode diff @@ -383,11 +382,6 @@ testlist options xpand=false ;; - -vxhs) - IMGPROTO=vxhs - xpand=false - ;; - -ssh) IMGPROTO=ssh xpand=false @@ -583,11 +577,11 @@ if [ -z "$QEMU_PROG" ] then if [ -x "$build_iotests/qemu" ]; then export QEMU_PROG="$build_iotests/qemu" - elif [ -x "$build_root/${qemu_arch}-softmmu/qemu-system-${qemu_arch}" ]; then - export QEMU_PROG="$build_root/${qemu_arch}-softmmu/qemu-system-${qemu_arch}" + elif [ -x "$build_root/qemu-system-${qemu_arch}" ]; then + export QEMU_PROG="$build_root/qemu-system-${qemu_arch}" else pushd "$build_root" > /dev/null - for binary in *-softmmu/qemu-system-* + for binary in qemu-system-* do if [ -x "$binary" ] then @@ -601,15 +595,19 @@ then fi export QEMU_PROG="$(type -p "$QEMU_PROG")" +export QEMU_OPTIONS="-nodefaults -display none -accel qtest" case "$QEMU_PROG" in *qemu-system-arm|*qemu-system-aarch64) - export QEMU_OPTIONS="-nodefaults -display none -machine virt -accel qtest" + export QEMU_OPTIONS="$QEMU_OPTIONS -machine virt" ;; - *qemu-system-tricore) - export QEMU_OPTIONS="-nodefaults -display none -machine tricore_testboard -accel qtest" + *qemu-system-avr) + export QEMU_OPTIONS="$QEMU_OPTIONS -machine mega2560" ;; - *) - export QEMU_OPTIONS="-nodefaults -display none -accel qtest" + *qemu-system-rx) + export QEMU_OPTIONS="$QEMU_OPTIONS -machine gdbsim-r5f562n8" + ;; + *qemu-system-tricore) + export QEMU_OPTIONS="-$QEMU_OPTIONS -machine tricore_testboard" ;; esac @@ -646,10 +644,6 @@ if [ -z $QEMU_NBD_PROG ]; then fi export QEMU_NBD_PROG="$(type -p "$QEMU_NBD_PROG")" -if [ -z "$QEMU_VXHS_PROG" ]; then - export QEMU_VXHS_PROG="$(set_prog_path qnio_server)" -fi - if [ -x "$build_iotests/socket_scm_helper" ] then export SOCKET_SCM_HELPER="$build_iotests/socket_scm_helper" diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter index 03e4f7180848274c039f946aba590251cba14e69..838ed1579361a0a2aa9acfcfa6ff87fb9c713020 100644 --- a/tests/qemu-iotests/common.filter +++ b/tests/qemu-iotests/common.filter @@ -119,41 +119,89 @@ _filter_actual_image_size() $SED -s 's/\("actual-size":\s*\)[0-9]\+/\1SIZE/g' } -# replace driver-specific options in the "Formatting..." line -_filter_img_create() +# Filename filters for qemu-img create +_filter_img_create_filenames() { - data_file_filter=() - if data_file=$(_get_data_file "$TEST_IMG"); then - data_file_filter=(-e "s# data_file=$data_file##") - fi - - $SED "${data_file_filter[@]}" \ + $SED \ -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ -e "s#$TEST_DIR#TEST_DIR#g" \ -e "s#$SOCK_DIR#SOCK_DIR#g" \ -e "s#$IMGFMT#IMGFMT#g" \ -e 's#nbd:127.0.0.1:[0-9]\\+#TEST_DIR/t.IMGFMT#g' \ - -e 's#nbd+unix:///\??socket=SOCK_DIR/nbd#TEST_DIR/t.IMGFMT#g' \ - -e "s# encryption=off##g" \ - -e "s# cluster_size=[0-9]\\+##g" \ - -e "s# table_size=[0-9]\\+##g" \ - -e "s# compat=[^ ]*##g" \ - -e "s# compat6=\\(on\\|off\\)##g" \ - -e "s# static=\\(on\\|off\\)##g" \ - -e "s# zeroed_grain=\\(on\\|off\\)##g" \ - -e "s# subformat=[^ ]*##g" \ - -e "s# adapter_type=[^ ]*##g" \ - -e "s# hwversion=[^ ]*##g" \ - -e "s# lazy_refcounts=\\(on\\|off\\)##g" \ - -e "s# block_size=[0-9]\\+##g" \ - -e "s# block_state_zero=\\(on\\|off\\)##g" \ - -e "s# log_size=[0-9]\\+##g" \ - -e "s# refcount_bits=[0-9]\\+##g" \ - -e "s# key-secret=[a-zA-Z0-9]\\+##g" \ - -e "s# iter-time=[0-9]\\+##g" \ - -e "s# force_size=\\(on\\|off\\)##g" \ - -e "s# compression_type=[a-zA-Z0-9]\\+##g" + -e 's#nbd+unix:///\??socket=SOCK_DIR/nbd#TEST_DIR/t.IMGFMT#g' +} + +# replace driver-specific options in the "Formatting..." line +_do_filter_img_create() +{ + # Split the line into the pre-options part ($filename_part, which + # precedes ", fmt=") and the options part ($options, which starts + # with "fmt=") + # (And just echo everything before the first "^Formatting") + readarray formatting_line < <($SED -e 's/, fmt=/\n/') + + filename_part=${formatting_line[0]} + unset formatting_line[0] + + options="fmt=${formatting_line[@]}" + + # Set grep_data_file to '\|data_file' to keep it; make it empty + # to drop it. + # We want to drop it if it is part of the global $IMGOPTS, and we + # want to keep it otherwise (if the test specifically wants to + # test data files). + grep_data_file=(-e data_file) + if _get_data_file "$TEST_IMG" > /dev/null; then + grep_data_file=() + fi + + filename_part=$(echo "$filename_part" | _filter_img_create_filenames) + + # Break the option line before each option (preserving pre-existing + # line breaks by replacing them by \0 and restoring them at the end), + # then filter out the options we want to keep and sort them according + # to some order that all block drivers used at the time of writing + # this function. + options=$( + echo "$options" \ + | tr '\n' '\0' \ + | $SED -e 's/ \([a-z0-9_.-]*\)=/\n\1=/g' \ + | grep -a -e '^fmt' -e '^size' -e '^backing' -e '^preallocation' \ + -e '^encryption' "${grep_data_file[@]}" \ + | _filter_img_create_filenames \ + | $SED \ + -e 's/^\(fmt\)/0-\1/' \ + -e 's/^\(size\)/1-\1/' \ + -e 's/^\(backing\)/2-\1/' \ + -e 's/^\(data_file\)/3-\1/' \ + -e 's/^\(encryption\)/4-\1/' \ + -e 's/^\(preallocation\)/8-\1/' \ + | LC_ALL=C sort \ + | $SED -e 's/^[0-9]-//' \ + | tr '\n\0' ' \n' \ + | $SED -e 's/^ *$//' -e 's/ *$//' + ) + + if [ -n "$options" ]; then + echo "$filename_part, $options" + elif [ -n "$filename_part" ]; then + echo "$filename_part" + fi +} + +# Filter qemu-img create output: +# Pipe all ^Formatting lines through _do_filter_img_create, and all +# other lines through _filter_img_create_filenames +_filter_img_create() +{ + while read -r line; do + if echo "$line" | grep -q '^Formatting'; then + echo "$line" | _do_filter_img_create + else + echo "$line" | _filter_img_create_filenames + fi + done } _filter_img_create_size() @@ -179,7 +227,6 @@ _filter_img_info() -e "s#$IMGFMT#IMGFMT#g" \ -e 's#nbd://127.0.0.1:[0-9]\\+$#TEST_DIR/t.IMGFMT#g' \ -e 's#nbd+unix:///\??socket=SOCK_DIR/nbd#TEST_DIR/t.IMGFMT#g' \ - -e 's#json.*vdisk-id.*vxhs"}}#TEST_DIR/t.IMGFMT#' \ -e "/encrypted: yes/d" \ -e "/cluster_size: [0-9]\\+/d" \ -e "/table_size: [0-9]\\+/d" \ @@ -192,6 +239,7 @@ _filter_img_info() -e "/adapter_type: '[^']*'/d" \ -e "/hwversion: '[^']*'/d" \ -e "/lazy_refcounts: \\(on\\|off\\)/d" \ + -e "/extended_l2=\\(on\\|off\\)/d" \ -e "/block_size: [0-9]\\+/d" \ -e "/block_state_zero: \\(on\\|off\\)/d" \ -e "/log_size: [0-9]\\+/d" \ diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index ba912555ca62ab1b19dde07894b6e781909733df..494490a2725ffcb456a93d44142eb83b70039646 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -124,7 +124,6 @@ fi : ${VALGRIND_QEMU_IMG=$VALGRIND_QEMU} : ${VALGRIND_QEMU_IO=$VALGRIND_QEMU} : ${VALGRIND_QEMU_NBD=$VALGRIND_QEMU} -: ${VALGRIND_QEMU_VXHS=$VALGRIND_QEMU} # The Valgrind own parameters may be set with # its environment variable VALGRIND_OPTS, e.g. @@ -212,19 +211,6 @@ _qemu_nbd_wrapper() return $RETVAL } -_qemu_vxhs_wrapper() -{ - local VALGRIND_LOGFILE="${TEST_DIR}"/$$.valgrind - ( - echo $BASHPID > "${TEST_DIR}/qemu-vxhs.pid" - VALGRIND_QEMU="${VALGRIND_QEMU_VXHS}" _qemu_proc_exec "${VALGRIND_LOGFILE}" \ - "$QEMU_VXHS_PROG" $QEMU_VXHS_OPTIONS "$@" - ) - RETVAL=$? - _qemu_proc_valgrind_log "${VALGRIND_LOGFILE}" $RETVAL - return $RETVAL -} - # Valgrind bug #409141 https://bugs.kde.org/show_bug.cgi?id=409141 # Until valgrind 3.16+ is ubiquitous, we must work around a hang in # valgrind when issuing sigkill. Disable valgrind for this invocation. @@ -237,7 +223,6 @@ export QEMU=_qemu_wrapper export QEMU_IMG=_qemu_img_wrapper export QEMU_IO=_qemu_io_wrapper export QEMU_NBD=_qemu_nbd_wrapper -export QEMU_VXHS=_qemu_vxhs_wrapper if [ "$IMGOPTSSYNTAX" = "true" ]; then DRIVER="driver=$IMGFMT" @@ -279,9 +264,6 @@ else TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT REMOTE_TEST_DIR="nfs://127.0.0.1$TEST_DIR" TEST_IMG="nfs://127.0.0.1$TEST_IMG_FILE" - elif [ "$IMGPROTO" = "vxhs" ]; then - TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT - TEST_IMG="vxhs://127.0.0.1:9999/t.$IMGFMT" else TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT fi @@ -436,12 +418,6 @@ _make_test_img() eval "$QEMU_NBD -v -t -k '$SOCK_DIR/nbd' -f $IMGFMT -e 42 -x '' $TEST_IMG_FILE >/dev/null &" sleep 1 # FIXME: qemu-nbd needs to be listening before we continue fi - - # Start QNIO server on image directory for vxhs protocol - if [ $IMGPROTO = "vxhs" ]; then - eval "$QEMU_VXHS -d $TEST_DIR > /dev/null &" - sleep 1 # Wait for server to come up. - fi } _rm_test_img() @@ -468,15 +444,6 @@ _cleanup_test_img() _stop_nbd_server rm -f "$TEST_IMG_FILE" ;; - vxhs) - if [ -f "${TEST_DIR}/qemu-vxhs.pid" ]; then - local QEMU_VXHS_PID - read QEMU_VXHS_PID < "${TEST_DIR}/qemu-vxhs.pid" - kill ${QEMU_VXHS_PID} >/dev/null 2>&1 - rm -f "${TEST_DIR}/qemu-vxhs.pid" - fi - rm -f "$TEST_IMG_FILE" - ;; file) _rm_test_img "$TEST_DIR/t.$IMGFMT" @@ -605,6 +572,9 @@ _supported_fmt() # setting IMGFMT_GENERIC to false. for f; do if [ "$f" = "$IMGFMT" -o "$f" = "generic" -a "$IMGFMT_GENERIC" = "true" ]; then + if [ "$IMGFMT" = "luks" ]; then + _require_working_luks + fi return fi done @@ -740,6 +710,33 @@ _unsupported_imgopts() done } +# Caution: Overwrites $TEST_DIR/t.luks +_require_working_luks() +{ + file="$TEST_DIR/t.luks" + + output=$( + $QEMU_IMG create -f luks \ + --object secret,id=sec0,data=hunter0 \ + -o key-secret=sec0 \ + -o iter-time=10 \ + "$file" \ + 1M \ + 2>&1 + ) + status=$? + + IMGFMT='luks' _rm_test_img "$file" + + if [ $status != 0 ]; then + reason=$(echo "$output" | grep "$file:" | $SED -e "s#.*$file: *##") + if [ -z "$reason" ]; then + reason="Failed to create a LUKS image" + fi + _notrun "$reason" + fi +} + # this test requires that a specified command (executable) exists # _require_command() diff --git a/tests/qemu-iotests/common.tls b/tests/qemu-iotests/common.tls index 54c331d7a5ee9dd0c5e67987214dd0ac06f56d1a..6ba28a78d3c801a6978ac39d318e08a552b67997 100644 --- a/tests/qemu-iotests/common.tls +++ b/tests/qemu-iotests/common.tls @@ -50,24 +50,45 @@ tls_x509_init() # use a fixed key so we don't waste system entropy on # each test run cat > "${tls_dir}/key.pem" <= (3, 6) - -# Type Aliases -QMPResponse = Dict[str, Any] - +from qemu.qmp import QMPMessage # Use this logger for logging messages directly from the iotests module logger = logging.getLogger('qemu.iotests') @@ -67,7 +65,8 @@ qemu_io_args_no_fmt += \ os.environ['QEMU_IO_OPTIONS_NO_FMT'].strip().split(' ') -qemu_nbd_args = [os.environ.get('QEMU_NBD_PROG', 'qemu-nbd')] +qemu_nbd_prog = os.environ.get('QEMU_NBD_PROG', 'qemu-nbd') +qemu_nbd_args = [qemu_nbd_prog] if os.environ.get('QEMU_NBD_OPTIONS'): qemu_nbd_args += os.environ['QEMU_NBD_OPTIONS'].strip().split(' ') @@ -90,15 +89,33 @@ luks_default_key_secret_opt = 'key-secret=keysec0' -def qemu_img(*args): +def qemu_tool_pipe_and_status(tool: str, args: Sequence[str], + connect_stderr: bool = True) -> Tuple[str, int]: + """ + Run a tool and return both its output and its exit code + """ + stderr = subprocess.STDOUT if connect_stderr else None + subp = subprocess.Popen(args, + stdout=subprocess.PIPE, + stderr=stderr, + universal_newlines=True) + output = subp.communicate()[0] + if subp.returncode < 0: + sys.stderr.write('%s received signal %i: %s\n' + % (tool, -subp.returncode, + ' '.join(qemu_img_args + list(args)))) + return (output, subp.returncode) + +def qemu_img_pipe_and_status(*args: str) -> Tuple[str, int]: + """ + Run qemu-img and return both its output and its exit code + """ + full_args = qemu_img_args + list(args) + return qemu_tool_pipe_and_status('qemu-img', full_args) + +def qemu_img(*args: str) -> int: '''Run qemu-img and return the exit code''' - devnull = open('/dev/null', 'r+') - exitcode = subprocess.call(qemu_img_args + list(args), - stdin=devnull, stdout=devnull) - if exitcode < 0: - sys.stderr.write('qemu-img received signal %i: %s\n' - % (-exitcode, ' '.join(qemu_img_args + list(args)))) - return exitcode + return qemu_img_pipe_and_status(*args)[1] def ordered_qmp(qmsg, conv_keys=True): # Dictionaries are not ordered prior to 3.6, therefore: @@ -132,6 +149,12 @@ def qemu_img_create(*args): return qemu_img(*args) +def qemu_img_measure(*args): + return json.loads(qemu_img_pipe("measure", "--output", "json", *args)) + +def qemu_img_check(*args): + return json.loads(qemu_img_pipe("check", "--output", "json", *args)) + def qemu_img_verbose(*args): '''Run qemu-img without suppressing its output and return the exit code''' exitcode = subprocess.call(qemu_img_args + list(args)) @@ -140,17 +163,9 @@ def qemu_img_verbose(*args): % (-exitcode, ' '.join(qemu_img_args + list(args)))) return exitcode -def qemu_img_pipe(*args): +def qemu_img_pipe(*args: str) -> str: '''Run qemu-img and return its output''' - subp = subprocess.Popen(qemu_img_args + list(args), - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - universal_newlines=True) - exitcode = subp.wait() - if exitcode < 0: - sys.stderr.write('qemu-img received signal %i: %s\n' - % (-exitcode, ' '.join(qemu_img_args + list(args)))) - return subp.communicate()[0] + return qemu_img_pipe_and_status(*args)[0] def qemu_img_log(*args): result = qemu_img_pipe(*args) @@ -177,11 +192,11 @@ def qemu_io(*args): subp = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) - exitcode = subp.wait() - if exitcode < 0: + output = subp.communicate()[0] + if subp.returncode < 0: sys.stderr.write('qemu-io received signal %i: %s\n' - % (-exitcode, ' '.join(args))) - return subp.communicate()[0] + % (-subp.returncode, ' '.join(args))) + return output def qemu_io_log(*args): result = qemu_io(*args) @@ -211,12 +226,18 @@ def get_virtio_scsi_device(): class QemuIoInteractive: def __init__(self, *args): - self.args = qemu_io_args + list(args) + self.args = qemu_io_args_no_fmt + list(args) self._p = subprocess.Popen(self.args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) - assert self._p.stdout.read(9) == 'qemu-io> ' + out = self._p.stdout.read(9) + if out != 'qemu-io> ': + # Most probably qemu-io just failed to start. + # Let's collect the whole output and exit. + out += self._p.stdout.read() + self._p.wait(timeout=1) + raise ValueError(out) def close(self): self._p.communicate('q\n') @@ -252,24 +273,45 @@ def qemu_nbd(*args): '''Run qemu-nbd in daemon mode and return the parent's exit code''' return subprocess.call(qemu_nbd_args + ['--fork'] + list(args)) -def qemu_nbd_early_pipe(*args): +def qemu_nbd_early_pipe(*args: str) -> Tuple[int, str]: '''Run qemu-nbd in daemon mode and return both the parent's exit code and its output in case of an error''' - subp = subprocess.Popen(qemu_nbd_args + ['--fork'] + list(args), - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - universal_newlines=True) - exitcode = subp.wait() - if exitcode < 0: - sys.stderr.write('qemu-nbd received signal %i: %s\n' % - (-exitcode, - ' '.join(qemu_nbd_args + ['--fork'] + list(args)))) + full_args = qemu_nbd_args + ['--fork'] + list(args) + output, returncode = qemu_tool_pipe_and_status('qemu-nbd', full_args, + connect_stderr=False) + return returncode, output if returncode else '' + +def qemu_nbd_list_log(*args: str) -> str: + '''Run qemu-nbd to list remote exports''' + full_args = [qemu_nbd_prog, '-L'] + list(args) + output, _ = qemu_tool_pipe_and_status('qemu-nbd', full_args) + log(output, filters=[filter_testfiles, filter_nbd_exports]) + return output + +@contextmanager +def qemu_nbd_popen(*args): + '''Context manager running qemu-nbd within the context''' + pid_file = file_path("pid") - return exitcode, subp.communicate()[0] if exitcode else '' + cmd = list(qemu_nbd_args) + cmd.extend(('--persistent', '--pid-file', pid_file)) + cmd.extend(args) -def qemu_nbd_popen(*args): - '''Run qemu-nbd in daemon mode and return the parent's exit code''' - return subprocess.Popen(qemu_nbd_args + ['--persistent'] + list(args)) + log('Start NBD server') + p = subprocess.Popen(cmd) + try: + while not os.path.exists(pid_file): + if p.poll() is not None: + raise RuntimeError( + "qemu-nbd terminated with exit code {}: {}" + .format(p.returncode, ' '.join(cmd))) + + time.sleep(0.01) + yield + finally: + log('Kill NBD server') + p.kill() + p.wait() def compare_images(img1, img2, fmt1=imgfmt, fmt2=imgfmt): '''Return True if two image files are identical''' @@ -339,8 +381,9 @@ def filter_qmp(qmsg, filter_fn): return qmsg def filter_testfiles(msg): - prefix = os.path.join(test_dir, "%s-" % (os.getpid())) - return msg.replace(prefix, 'TEST_DIR/PID-') + pref1 = os.path.join(test_dir, "%s-" % (os.getpid())) + pref2 = os.path.join(sock_dir, "%s-" % (os.getpid())) + return msg.replace(pref1, 'TEST_DIR/PID-').replace(pref2, 'SOCK_DIR/PID-') def filter_qmp_testfiles(qmsg): def _filter(_key, value): @@ -349,6 +392,16 @@ def _filter(_key, value): return value return filter_qmp(qmsg, _filter) +def filter_virtio_scsi(output: str) -> str: + return re.sub(r'(virtio-scsi)-(ccw|pci)', r'\1', output) + +def filter_qmp_virtio_scsi(qmsg): + def _filter(_key, value): + if is_str(value): + return filter_virtio_scsi(value) + return value + return filter_qmp(qmsg, _filter) + def filter_generated_node_ids(msg): return re.sub("#block[0-9]+", "NODE_NAME", msg) @@ -378,6 +431,9 @@ def _filter(_key, value): return value return filter_qmp(qmsg, _filter) +def filter_nbd_exports(output: str) -> str: + return re.sub(r'((min|opt|max) block): [0-9]+', r'\1: XXX', output) + Msg = TypeVar('Msg', Dict[str, Any], List[Any], str) @@ -414,42 +470,45 @@ def timeout(self, signum, frame): def file_pattern(name): return "{0}-{1}".format(os.getpid(), name) -class FilePaths: +class FilePath: """ - FilePaths is an auto-generated filename that cleans itself up. + Context manager generating multiple file names. The generated files are + removed when exiting the context. + + Example usage: + + with FilePath('a.img', 'b.img') as (img_a, img_b): + # Use img_a and img_b here... + + # a.img and b.img are automatically removed here. + + By default images are created in iotests.test_dir. To create sockets use + iotests.sock_dir: + + with FilePath('a.sock', base_dir=iotests.sock_dir) as sock: - Use this context manager to generate filenames and ensure that the file - gets deleted:: + For convenience, calling with one argument yields a single file instead of + a tuple with one item. - with FilePaths(['test.img']) as img_path: - qemu_img('create', img_path, '1G') - # migration_sock_path is automatically deleted """ - def __init__(self, names, base_dir=test_dir): - self.paths = [] - for name in names: - self.paths.append(os.path.join(base_dir, file_pattern(name))) + def __init__(self, *names, base_dir=test_dir): + self.paths = [os.path.join(base_dir, file_pattern(name)) + for name in names] def __enter__(self): - return self.paths + if len(self.paths) == 1: + return self.paths[0] + else: + return self.paths def __exit__(self, exc_type, exc_val, exc_tb): - try: - for path in self.paths: + for path in self.paths: + try: os.remove(path) - except OSError: - pass + except OSError: + pass return False -class FilePath(FilePaths): - """ - FilePath is a specialization of FilePaths that takes a single filename. - """ - def __init__(self, name, base_dir=test_dir): - super(FilePath, self).__init__([name], base_dir) - - def __enter__(self): - return self.paths[0] def file_path_remover(): for path in reversed(file_path_remover.paths): @@ -494,10 +553,10 @@ class VM(qtest.QEMUQtestMachine): def __init__(self, path_suffix=''): name = "qemu%s-%d" % (path_suffix, os.getpid()) - super(VM, self).__init__(qemu_prog, qemu_opts, name=name, - test_dir=test_dir, - socket_scm_helper=socket_scm_helper, - sock_dir=sock_dir) + super().__init__(qemu_prog, qemu_opts, name=name, + test_dir=test_dir, + socket_scm_helper=socket_scm_helper, + sock_dir=sock_dir) self._num_drives = 0 def add_object(self, opts): @@ -554,9 +613,9 @@ def add_incoming(self, addr): self._args.append(addr) return self - def hmp(self, command_line: str, use_log: bool = False) -> QMPResponse: + def hmp(self, command_line: str, use_log: bool = False) -> QMPMessage: cmd = 'human-monitor-command' - kwargs = {'command-line': command_line} + kwargs: Dict[str, Any] = {'command-line': command_line} if use_log: return self.qmp_log(cmd, **kwargs) else: @@ -575,7 +634,7 @@ def resume_drive(self, drive: str) -> None: self.hmp(f'qemu-io {drive} "remove_break bp_{drive}"') def hmp_qemu_io(self, drive: str, cmd: str, - use_log: bool = False) -> QMPResponse: + use_log: bool = False) -> QMPMessage: """Write to a given drive using an HMP command""" return self.hmp(f'qemu-io {drive} "{cmd}"', use_log=use_log) @@ -695,16 +754,26 @@ def enable_migration_events(self, name): } ])) - def wait_migration(self, expect_runstate): + def wait_migration(self, expect_runstate: Optional[str]) -> bool: while True: event = self.event_wait('MIGRATION') + # We use the default timeout, and with a timeout, event_wait() + # never returns None + assert event + log(event, filters=[filter_qmp_event]) - if event['data']['status'] == 'completed': + if event['data']['status'] in ('completed', 'failed'): break - # The event may occur in finish-migrate, so wait for the expected - # post-migration runstate - while self.qmp('query-status')['return']['status'] != expect_runstate: - pass + + if event['data']['status'] == 'completed': + # The event may occur in finish-migrate, so wait for the expected + # post-migration runstate + runstate = None + while runstate != expect_runstate: + runstate = self.qmp('query-status')['return']['status'] + return True + else: + return False def node_info(self, node_name): nodes = self.qmp('query-named-block-nodes') @@ -932,8 +1001,12 @@ def wait_until_completed(self, drive='drive0', check_offset=True, def wait_ready(self, drive='drive0'): """Wait until a BLOCK_JOB_READY event, and return the event.""" - f = {'data': {'type': 'mirror', 'device': drive}} - return self.vm.event_wait(name='BLOCK_JOB_READY', match=f) + return self.vm.events_wait([ + ('BLOCK_JOB_READY', + {'data': {'type': 'mirror', 'device': drive}}), + ('BLOCK_JOB_READY', + {'data': {'type': 'commit', 'device': drive}}) + ]) def wait_ready_and_cancel(self, drive='drive0'): self.wait_ready(drive=drive) @@ -952,7 +1025,7 @@ def complete_and_wait(self, drive='drive0', wait_ready=True, self.assert_qmp(result, 'return', {}) event = self.wait_until_completed(drive=drive, error=completion_error) - self.assert_qmp(event, 'data/type', 'mirror') + self.assertTrue(event['data']['type'] in ['mirror', 'commit']) def pause_wait(self, job_id='job0'): with Timeout(3, "Timeout waiting for job to pause"): @@ -1003,19 +1076,20 @@ def case_notrun(reason): def _verify_image_format(supported_fmts: Sequence[str] = (), unsupported_fmts: Sequence[str] = ()) -> None: - assert not (supported_fmts and unsupported_fmts) - if 'generic' in supported_fmts and \ os.environ.get('IMGFMT_GENERIC', 'true') == 'true': # similar to # _supported_fmt generic # for bash tests - return + supported_fmts = () not_sup = supported_fmts and (imgfmt not in supported_fmts) if not_sup or (imgfmt in unsupported_fmts): notrun('not suitable for this image format: %s' % imgfmt) + if imgfmt == 'luks': + verify_working_luks() + def _verify_protocol(supported: Sequence[str] = (), unsupported: Sequence[str] = ()) -> None: assert not (supported and unsupported) @@ -1052,21 +1126,54 @@ def verify_quorum(): if not supports_quorum(): notrun('quorum support missing') -def qemu_pipe(*args): +def has_working_luks() -> Tuple[bool, str]: + """ + Check whether our LUKS driver can actually create images + (this extends to LUKS encryption for qcow2). + + If not, return the reason why. + """ + + img_file = f'{test_dir}/luks-test.luks' + (output, status) = \ + qemu_img_pipe_and_status('create', '-f', 'luks', + '--object', luks_default_secret_object, + '-o', luks_default_key_secret_opt, + '-o', 'iter-time=10', + img_file, '1G') + try: + os.remove(img_file) + except OSError: + pass + + if status != 0: + reason = output + for line in output.splitlines(): + if img_file + ':' in line: + reason = line.split(img_file + ':', 1)[1].strip() + break + + return (False, reason) + else: + return (True, '') + +def verify_working_luks(): + """ + Skip test suite if LUKS does not work + """ + (working, reason) = has_working_luks() + if not working: + notrun(reason) + +def qemu_pipe(*args: str) -> str: """ Run qemu with an option to print something and exit (e.g. a help option). :return: QEMU's stdout output. """ - args = [qemu_prog] + qemu_opts + list(args) - subp = subprocess.Popen(args, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - universal_newlines=True) - exitcode = subp.wait() - if exitcode < 0: - sys.stderr.write('qemu received signal %i: %s\n' % - (-exitcode, ' '.join(args))) - return subp.communicate()[0] + full_args = [qemu_prog] + qemu_opts + list(args) + output, _ = qemu_tool_pipe_and_status('qemu', full_args) + return output def supported_formats(read_only=False): '''Set 'read_only' to True to check ro-whitelist @@ -1103,6 +1210,22 @@ def func_wrapper(test_case: QMPTestCase, *args: List[Any], return func_wrapper return skip_test_decorator +def skip_for_formats(formats: Sequence[str] = ()) \ + -> Callable[[Callable[[QMPTestCase, List[Any], Dict[str, Any]], None]], + Callable[[QMPTestCase, List[Any], Dict[str, Any]], None]]: + '''Skip Test Decorator + Skips the test for the given formats''' + def skip_test_decorator(func): + def func_wrapper(test_case: QMPTestCase, *args: List[Any], + **kwargs: Dict[str, Any]) -> None: + if imgfmt in formats: + msg = f'{test_case}: Skipped for format {imgfmt}' + test_case.case_skip(msg) + else: + func(test_case, *args, **kwargs) + return func_wrapper + return skip_test_decorator + def skip_if_user_is_root(func): '''Skip Test Decorator Runs the test only without root permissions''' diff --git a/tests/qemu-iotests/meson.build b/tests/qemu-iotests/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..67aed1e4927846a624a943c7ad974df1cb1b1850 --- /dev/null +++ b/tests/qemu-iotests/meson.build @@ -0,0 +1,5 @@ +if 'CONFIG_LINUX' in config_host + socket_scm_helper = executable('socket_scm_helper', 'socket_scm_helper.c') +else + socket_scm_helper = [] +endif diff --git a/tests/qemu-iotests/nbd-fault-injector.py b/tests/qemu-iotests/nbd-fault-injector.py index 588d62aebf2304a256da3e22d814f1e7defed29e..6e11ef89b8b38075370e705b950af6d0dd4a55b1 100755 --- a/tests/qemu-iotests/nbd-fault-injector.py +++ b/tests/qemu-iotests/nbd-fault-injector.py @@ -47,10 +47,7 @@ import socket import struct import collections -if sys.version_info.major >= 3: - import configparser -else: - import ConfigParser as configparser +import configparser FAKE_DISK_SIZE = 8 * 1024 * 1024 * 1024 # 8 GB @@ -230,7 +227,7 @@ def parse_config(config): def load_rules(filename): config = configparser.RawConfigParser() with open(filename, 'rt') as f: - config.readfp(f, filename) + config.read_file(f, filename) return parse_config(config) def open_socket(path): diff --git a/tests/qemu-iotests/pylintrc b/tests/qemu-iotests/pylintrc index 5481afe52827ee774fe92452f662af12b0b7a77c..cd3702e23c39b513c8293dceeb2d4a1c7ef0ff57 100644 --- a/tests/qemu-iotests/pylintrc +++ b/tests/qemu-iotests/pylintrc @@ -17,6 +17,8 @@ disable=invalid-name, too-many-lines, too-many-locals, too-many-public-methods, + # pylint warns about Optional[] etc. as unsubscriptable in 3.9 + unsubscriptable-object, # These are temporary, and should be removed: missing-docstring, diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py index 94a07b2f6fa2d80c43def1546ddea6e492b2ee8c..77ca59cc663dfb0cfdf35a472864fa656e41633f 100755 --- a/tests/qemu-iotests/qcow2.py +++ b/tests/qemu-iotests/qcow2.py @@ -1,181 +1,55 @@ #!/usr/bin/env python3 +# +# Manipulations with qcow2 image +# +# Copyright (C) 2012 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 . +# import sys -import struct -import string - -class QcowHeaderExtension: - - def __init__(self, magic, length, data): - if length % 8 != 0: - padding = 8 - (length % 8) - data += b"\0" * padding - - self.magic = magic - self.length = length - self.data = data - - @classmethod - def create(cls, magic, data): - return QcowHeaderExtension(magic, len(data), data) - -class QcowHeader: - - uint32_t = 'I' - uint64_t = 'Q' - - fields = [ - # Version 2 header fields - [ uint32_t, '%#x', 'magic' ], - [ uint32_t, '%d', 'version' ], - [ uint64_t, '%#x', 'backing_file_offset' ], - [ uint32_t, '%#x', 'backing_file_size' ], - [ uint32_t, '%d', 'cluster_bits' ], - [ uint64_t, '%d', 'size' ], - [ uint32_t, '%d', 'crypt_method' ], - [ uint32_t, '%d', 'l1_size' ], - [ uint64_t, '%#x', 'l1_table_offset' ], - [ uint64_t, '%#x', 'refcount_table_offset' ], - [ uint32_t, '%d', 'refcount_table_clusters' ], - [ uint32_t, '%d', 'nb_snapshots' ], - [ uint64_t, '%#x', 'snapshot_offset' ], - - # Version 3 header fields - [ uint64_t, 'mask', 'incompatible_features' ], - [ uint64_t, 'mask', 'compatible_features' ], - [ uint64_t, 'mask', 'autoclear_features' ], - [ uint32_t, '%d', 'refcount_order' ], - [ uint32_t, '%d', 'header_length' ], - ]; - - fmt = '>' + ''.join(field[0] for field in fields) - - def __init__(self, fd): - - buf_size = struct.calcsize(QcowHeader.fmt) - - fd.seek(0) - buf = fd.read(buf_size) - - header = struct.unpack(QcowHeader.fmt, buf) - self.__dict__ = dict((field[2], header[i]) - for i, field in enumerate(QcowHeader.fields)) - - self.set_defaults() - self.cluster_size = 1 << self.cluster_bits - - fd.seek(self.header_length) - self.load_extensions(fd) - - if self.backing_file_offset: - fd.seek(self.backing_file_offset) - self.backing_file = fd.read(self.backing_file_size) - else: - self.backing_file = None - - def set_defaults(self): - if self.version == 2: - self.incompatible_features = 0 - self.compatible_features = 0 - self.autoclear_features = 0 - self.refcount_order = 4 - self.header_length = 72 - - def load_extensions(self, fd): - self.extensions = [] - - if self.backing_file_offset != 0: - end = min(self.cluster_size, self.backing_file_offset) - else: - end = self.cluster_size - - while fd.tell() < end: - (magic, length) = struct.unpack('>II', fd.read(8)) - if magic == 0: - break - else: - padded = (length + 7) & ~7 - data = fd.read(padded) - self.extensions.append(QcowHeaderExtension(magic, length, data)) - - def update_extensions(self, fd): - - fd.seek(self.header_length) - extensions = self.extensions - extensions.append(QcowHeaderExtension(0, 0, b"")) - for ex in extensions: - buf = struct.pack('>II', ex.magic, ex.length) - fd.write(buf) - fd.write(ex.data) - - if self.backing_file != None: - self.backing_file_offset = fd.tell() - fd.write(self.backing_file) - - if fd.tell() > self.cluster_size: - raise Exception("I think I just broke the image...") - - - def update(self, fd): - header_bytes = self.header_length - - self.update_extensions(fd) - - fd.seek(0) - header = tuple(self.__dict__[f] for t, p, f in QcowHeader.fields) - buf = struct.pack(QcowHeader.fmt, *header) - buf = buf[0:header_bytes-1] - fd.write(buf) - - def dump(self): - for f in QcowHeader.fields: - value = self.__dict__[f[2]] - if f[1] == 'mask': - bits = [] - for bit in range(64): - if value & (1 << bit): - bits.append(bit) - value_str = str(bits) - else: - value_str = f[1] % value - print("%-25s" % f[2], value_str) - print("") +from qcow2_format import ( + QcowHeader, + QcowHeaderExtension +) - def dump_extensions(self): - for ex in self.extensions: - - data = ex.data[:ex.length] - if all(c in string.printable.encode('ascii') for c in data): - data = "'%s'" % data.decode('ascii') - else: - data = "" - print("Header extension:") - print("%-25s %#x" % ("magic", ex.magic)) - print("%-25s %d" % ("length", ex.length)) - print("%-25s %s" % ("data", data)) - print("") +is_json = False def cmd_dump_header(fd): h = QcowHeader(fd) - h.dump() - h.dump_extensions() + h.dump(is_json) + print() + h.dump_extensions(is_json) + def cmd_dump_header_exts(fd): h = QcowHeader(fd) - h.dump_extensions() + h.dump_extensions(is_json) + def cmd_set_header(fd, name, value): try: value = int(value, 0) - except: + except ValueError: print("'%s' is not a valid number" % value) sys.exit(1) fields = (field[2] for field in QcowHeader.fields) - if not name in fields: + if name not in fields: print("'%s' is not a known header field" % name) sys.exit(1) @@ -183,25 +57,29 @@ def cmd_set_header(fd, name, value): h.__dict__[name] = value h.update(fd) + def cmd_add_header_ext(fd, magic, data): try: magic = int(magic, 0) - except: + except ValueError: print("'%s' is not a valid magic number" % magic) sys.exit(1) h = QcowHeader(fd) - h.extensions.append(QcowHeaderExtension.create(magic, data.encode('ascii'))) + h.extensions.append(QcowHeaderExtension.create(magic, + data.encode('ascii'))) h.update(fd) + def cmd_add_header_ext_stdio(fd, magic): data = sys.stdin.read() cmd_add_header_ext(fd, magic, data) + def cmd_del_header_ext(fd, magic): try: magic = int(magic, 0) - except: + except ValueError: print("'%s' is not a valid magic number" % magic) sys.exit(1) @@ -219,12 +97,13 @@ def cmd_del_header_ext(fd, magic): h.update(fd) + def cmd_set_feature_bit(fd, group, bit): try: bit = int(bit, 0) if bit < 0 or bit >= 64: raise ValueError - except: + except ValueError: print("'%s' is not a valid bit number in range [0, 64)" % bit) sys.exit(1) @@ -236,21 +115,27 @@ def cmd_set_feature_bit(fd, group, bit): elif group == 'autoclear': h.autoclear_features |= 1 << bit else: - print("'%s' is not a valid group, try 'incompatible', 'compatible', or 'autoclear'" % group) + print("'%s' is not a valid group, try " + "'incompatible', 'compatible', or 'autoclear'" % group) sys.exit(1) h.update(fd) + cmds = [ - [ 'dump-header', cmd_dump_header, 0, 'Dump image header and header extensions' ], - [ 'dump-header-exts', cmd_dump_header_exts, 0, 'Dump image header extensions' ], - [ 'set-header', cmd_set_header, 2, 'Set a field in the header'], - [ 'add-header-ext', cmd_add_header_ext, 2, 'Add a header extension' ], - [ 'add-header-ext-stdio', cmd_add_header_ext_stdio, 1, 'Add a header extension, data from stdin' ], - [ 'del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension' ], - [ 'set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'], + ['dump-header', cmd_dump_header, 0, + 'Dump image header and header extensions'], + ['dump-header-exts', cmd_dump_header_exts, 0, + 'Dump image header extensions'], + ['set-header', cmd_set_header, 2, 'Set a field in the header'], + ['add-header-ext', cmd_add_header_ext, 2, 'Add a header extension'], + ['add-header-ext-stdio', cmd_add_header_ext_stdio, 1, + 'Add a header extension, data from stdin'], + ['del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension'], + ['set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'], ] + def main(filename, cmd, args): fd = open(filename, "r+b") try: @@ -267,16 +152,25 @@ def main(filename, cmd, args): finally: fd.close() + def usage(): - print("Usage: %s [, ...]" % sys.argv[0]) + print("Usage: %s [, ...] [, ...]" % sys.argv[0]) print("") print("Supported commands:") for name, handler, num_args, desc in cmds: print(" %-20s - %s" % (name, desc)) + print("") + print("Supported keys:") + print(" %-20s - %s" % ('-j', 'Dump in JSON format')) + if __name__ == '__main__': if len(sys.argv) < 3: usage() sys.exit(1) + is_json = '-j' in sys.argv + if is_json: + sys.argv.remove('-j') + main(sys.argv[1], sys.argv[2], sys.argv[3:]) diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py new file mode 100644 index 0000000000000000000000000000000000000000..8adc9959e10bf637c72a67263186b04cac59bb3c --- /dev/null +++ b/tests/qemu-iotests/qcow2_format.py @@ -0,0 +1,468 @@ +# Library for manipulations with qcow2 image +# +# Copyright (c) 2020 Virtuozzo International GmbH. +# Copyright (C) 2012 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 . +# + +import struct +import string +import json + + +class ComplexEncoder(json.JSONEncoder): + def default(self, obj): + if hasattr(obj, 'to_json'): + return obj.to_json() + else: + return json.JSONEncoder.default(self, obj) + + +class Qcow2Field: + + def __init__(self, value): + self.value = value + + def __str__(self): + return str(self.value) + + +class Flags64(Qcow2Field): + + def __str__(self): + bits = [] + for bit in range(64): + if self.value & (1 << bit): + bits.append(bit) + return str(bits) + + +class BitmapFlags(Qcow2Field): + + flags = { + 0x1: 'in-use', + 0x2: 'auto' + } + + def __str__(self): + bits = [] + for bit in range(64): + flag = self.value & (1 << bit) + if flag: + bits.append(self.flags.get(flag, f'bit-{bit}')) + return f'{self.value:#x} ({bits})' + + +class Enum(Qcow2Field): + + def __str__(self): + return f'{self.value:#x} ({self.mapping.get(self.value, "")})' + + +class Qcow2StructMeta(type): + + # Mapping from c types to python struct format + ctypes = { + 'u8': 'B', + 'u16': 'H', + 'u32': 'I', + 'u64': 'Q' + } + + def __init__(self, name, bases, attrs): + if 'fields' in attrs: + self.fmt = '>' + ''.join(self.ctypes[f[0]] for f in self.fields) + + +class Qcow2Struct(metaclass=Qcow2StructMeta): + + """Qcow2Struct: base class for qcow2 data structures + + Successors should define fields class variable, which is: list of tuples, + each of three elements: + - c-type (one of 'u8', 'u16', 'u32', 'u64') + - format (format_spec to use with .format() when dump or 'mask' to dump + bitmasks) + - field name + """ + + def __init__(self, fd=None, offset=None, data=None): + """ + Two variants: + 1. Specify data. fd and offset must be None. + 2. Specify fd and offset, data must be None. offset may be omitted + in this case, than current position of fd is used. + """ + if data is None: + assert fd is not None + buf_size = struct.calcsize(self.fmt) + if offset is not None: + fd.seek(offset) + data = fd.read(buf_size) + else: + assert fd is None and offset is None + + values = struct.unpack(self.fmt, data) + self.__dict__ = dict((field[2], values[i]) + for i, field in enumerate(self.fields)) + + def dump(self, is_json=False): + if is_json: + print(json.dumps(self.to_json(), indent=4, cls=ComplexEncoder)) + return + + for f in self.fields: + value = self.__dict__[f[2]] + if isinstance(f[1], str): + value_str = f[1].format(value) + else: + value_str = str(f[1](value)) + + print('{:<25} {}'.format(f[2], value_str)) + + def to_json(self): + return dict((f[2], self.__dict__[f[2]]) for f in self.fields) + + +class Qcow2BitmapExt(Qcow2Struct): + + fields = ( + ('u32', '{}', 'nb_bitmaps'), + ('u32', '{}', 'reserved32'), + ('u64', '{:#x}', 'bitmap_directory_size'), + ('u64', '{:#x}', 'bitmap_directory_offset') + ) + + def __init__(self, fd, cluster_size): + super().__init__(fd=fd) + tail = struct.calcsize(self.fmt) % 8 + if tail: + fd.seek(8 - tail, 1) + position = fd.tell() + self.cluster_size = cluster_size + self.read_bitmap_directory(fd) + fd.seek(position) + + def read_bitmap_directory(self, fd): + fd.seek(self.bitmap_directory_offset) + self.bitmap_directory = \ + [Qcow2BitmapDirEntry(fd, cluster_size=self.cluster_size) + for _ in range(self.nb_bitmaps)] + + def dump(self): + super().dump() + for entry in self.bitmap_directory: + print() + entry.dump() + + def to_json(self): + fields_dict = super().to_json() + fields_dict['bitmap_directory'] = self.bitmap_directory + return fields_dict + + +class Qcow2BitmapDirEntry(Qcow2Struct): + + fields = ( + ('u64', '{:#x}', 'bitmap_table_offset'), + ('u32', '{}', 'bitmap_table_size'), + ('u32', BitmapFlags, 'flags'), + ('u8', '{}', 'type'), + ('u8', '{}', 'granularity_bits'), + ('u16', '{}', 'name_size'), + ('u32', '{}', 'extra_data_size') + ) + + def __init__(self, fd, cluster_size): + super().__init__(fd=fd) + self.cluster_size = cluster_size + # Seek relative to the current position in the file + fd.seek(self.extra_data_size, 1) + bitmap_name = fd.read(self.name_size) + self.name = bitmap_name.decode('ascii') + # Move position to the end of the entry in the directory + entry_raw_size = self.bitmap_dir_entry_raw_size() + padding = ((entry_raw_size + 7) & ~7) - entry_raw_size + fd.seek(padding, 1) + self.bitmap_table = Qcow2BitmapTable(fd=fd, + offset=self.bitmap_table_offset, + nb_entries=self.bitmap_table_size, + cluster_size=self.cluster_size) + + def bitmap_dir_entry_raw_size(self): + return struct.calcsize(self.fmt) + self.name_size + \ + self.extra_data_size + + def dump(self): + print(f'{"Bitmap name":<25} {self.name}') + super(Qcow2BitmapDirEntry, self).dump() + self.bitmap_table.dump() + + def to_json(self): + # Put the name ahead of the dict + return { + 'name': self.name, + **super().to_json(), + 'bitmap_table': self.bitmap_table + } + + +class Qcow2BitmapTableEntry(Qcow2Struct): + + fields = ( + ('u64', '{}', 'entry'), + ) + + BME_TABLE_ENTRY_RESERVED_MASK = 0xff000000000001fe + BME_TABLE_ENTRY_OFFSET_MASK = 0x00fffffffffffe00 + BME_TABLE_ENTRY_FLAG_ALL_ONES = 1 + + def __init__(self, fd): + super().__init__(fd=fd) + self.reserved = self.entry & self.BME_TABLE_ENTRY_RESERVED_MASK + self.offset = self.entry & self.BME_TABLE_ENTRY_OFFSET_MASK + if self.offset: + if self.entry & self.BME_TABLE_ENTRY_FLAG_ALL_ONES: + self.type = 'invalid' + else: + self.type = 'serialized' + elif self.entry & self.BME_TABLE_ENTRY_FLAG_ALL_ONES: + self.type = 'all-ones' + else: + self.type = 'all-zeroes' + + def to_json(self): + return {'type': self.type, 'offset': self.offset, + 'reserved': self.reserved} + + +class Qcow2BitmapTable: + + def __init__(self, fd, offset, nb_entries, cluster_size): + self.cluster_size = cluster_size + position = fd.tell() + fd.seek(offset) + self.entries = [Qcow2BitmapTableEntry(fd) for _ in range(nb_entries)] + fd.seek(position) + + def dump(self): + bitmap_table = enumerate(self.entries) + print(f'{"Bitmap table":<14} {"type":<15} {"size":<12} {"offset"}') + for i, entry in bitmap_table: + if entry.type == 'serialized': + size = self.cluster_size + else: + size = 0 + print(f'{i:<14} {entry.type:<15} {size:<12} {entry.offset}') + + def to_json(self): + return self.entries + + +QCOW2_EXT_MAGIC_BITMAPS = 0x23852875 + + +class QcowHeaderExtension(Qcow2Struct): + + class Magic(Enum): + mapping = { + 0xe2792aca: 'Backing format', + 0x6803f857: 'Feature table', + 0x0537be77: 'Crypto header', + QCOW2_EXT_MAGIC_BITMAPS: 'Bitmaps', + 0x44415441: 'Data file' + } + + def to_json(self): + return self.mapping.get(self.value, "") + + fields = ( + ('u32', Magic, 'magic'), + ('u32', '{}', 'length') + # length bytes of data follows + # then padding to next multiply of 8 + ) + + def __init__(self, magic=None, length=None, data=None, fd=None, + cluster_size=None): + """ + Support both loading from fd and creation from user data. + For fd-based creation current position in a file will be used to read + the data. + The cluster_size value may be obtained by dependent structures. + + This should be somehow refactored and functionality should be moved to + superclass (to allow creation of any qcow2 struct), but then, fields + of variable length (data here) should be supported in base class + somehow. Note also, that we probably want to parse different + extensions. Should they be subclasses of this class, or how to do it + better? Should it be something like QAPI union with discriminator field + (magic here). So, it's a TODO. We'll see how to properly refactor this + when we have more qcow2 structures. + """ + if fd is None: + assert all(v is not None for v in (magic, length, data)) + self.magic = magic + self.length = length + if length % 8 != 0: + padding = 8 - (length % 8) + data += b'\0' * padding + self.data = data + else: + assert all(v is None for v in (magic, length, data)) + super().__init__(fd=fd) + if self.magic == QCOW2_EXT_MAGIC_BITMAPS: + self.obj = Qcow2BitmapExt(fd=fd, cluster_size=cluster_size) + self.data = None + else: + padded = (self.length + 7) & ~7 + self.data = fd.read(padded) + assert self.data is not None + self.obj = None + + if self.data is not None: + data_str = self.data[:self.length] + if all(c in string.printable.encode( + 'ascii') for c in data_str): + data_str = f"'{ data_str.decode('ascii') }'" + else: + data_str = '' + self.data_str = data_str + + + def dump(self): + super().dump() + + if self.obj is None: + print(f'{"data":<25} {self.data_str}') + else: + self.obj.dump() + + def to_json(self): + # Put the name ahead of the dict + res = {'name': self.Magic(self.magic), **super().to_json()} + if self.obj is not None: + res['data'] = self.obj + else: + res['data_str'] = self.data_str + + return res + + @classmethod + def create(cls, magic, data): + return QcowHeaderExtension(magic, len(data), data) + + +class QcowHeader(Qcow2Struct): + + fields = ( + # Version 2 header fields + ('u32', '{:#x}', 'magic'), + ('u32', '{}', 'version'), + ('u64', '{:#x}', 'backing_file_offset'), + ('u32', '{:#x}', 'backing_file_size'), + ('u32', '{}', 'cluster_bits'), + ('u64', '{}', 'size'), + ('u32', '{}', 'crypt_method'), + ('u32', '{}', 'l1_size'), + ('u64', '{:#x}', 'l1_table_offset'), + ('u64', '{:#x}', 'refcount_table_offset'), + ('u32', '{}', 'refcount_table_clusters'), + ('u32', '{}', 'nb_snapshots'), + ('u64', '{:#x}', 'snapshot_offset'), + + # Version 3 header fields + ('u64', Flags64, 'incompatible_features'), + ('u64', Flags64, 'compatible_features'), + ('u64', Flags64, 'autoclear_features'), + ('u32', '{}', 'refcount_order'), + ('u32', '{}', 'header_length'), + ) + + def __init__(self, fd): + super().__init__(fd=fd, offset=0) + + self.set_defaults() + self.cluster_size = 1 << self.cluster_bits + + fd.seek(self.header_length) + self.load_extensions(fd) + + if self.backing_file_offset: + fd.seek(self.backing_file_offset) + self.backing_file = fd.read(self.backing_file_size) + else: + self.backing_file = None + + def set_defaults(self): + if self.version == 2: + self.incompatible_features = 0 + self.compatible_features = 0 + self.autoclear_features = 0 + self.refcount_order = 4 + self.header_length = 72 + + def load_extensions(self, fd): + self.extensions = [] + + if self.backing_file_offset != 0: + end = min(self.cluster_size, self.backing_file_offset) + else: + end = self.cluster_size + + while fd.tell() < end: + ext = QcowHeaderExtension(fd=fd, cluster_size=self.cluster_size) + if ext.magic == 0: + break + else: + self.extensions.append(ext) + + def update_extensions(self, fd): + + fd.seek(self.header_length) + extensions = self.extensions + extensions.append(QcowHeaderExtension(0, 0, b'')) + for ex in extensions: + buf = struct.pack('>II', ex.magic, ex.length) + fd.write(buf) + fd.write(ex.data) + + if self.backing_file is not None: + self.backing_file_offset = fd.tell() + fd.write(self.backing_file) + + if fd.tell() > self.cluster_size: + raise Exception('I think I just broke the image...') + + def update(self, fd): + header_bytes = self.header_length + + self.update_extensions(fd) + + fd.seek(0) + header = tuple(self.__dict__[f] for t, p, f in QcowHeader.fields) + buf = struct.pack(QcowHeader.fmt, *header) + buf = buf[0:header_bytes-1] + fd.write(buf) + + def dump_extensions(self, is_json=False): + if is_json: + print(json.dumps(self.extensions, indent=4, cls=ComplexEncoder)) + return + + for ex in self.extensions: + print('Header extension:') + ex.dump() + print() diff --git a/tests/qht-bench.c b/tests/qht-bench.c index e3b512f26f376e3b145bc716af5276424b394d18..2e5b70ccd04345e1a63af9267a2aabb4d8b0ca2e 100644 --- a/tests/qht-bench.c +++ b/tests/qht-bench.c @@ -25,7 +25,13 @@ struct thread_stats { struct thread_info { void (*func)(struct thread_info *); struct thread_stats stats; - uint64_t r; + /* + * Seed is in the range [1..UINT64_MAX], because the RNG requires + * a non-zero seed. To use, subtract 1 and compare against the + * threshold with =. This lets threshold = 0 never match (0% hit), + * and threshold = UINT64_MAX always match (100% hit). + */ + uint64_t seed; bool write_op; /* writes alternate between insertions and removals */ bool resize_down; } QEMU_ALIGNED(64); /* avoid false sharing among threads */ @@ -131,8 +137,9 @@ static uint64_t xorshift64star(uint64_t x) static void do_rz(struct thread_info *info) { struct thread_stats *stats = &info->stats; + uint64_t r = info->seed - 1; - if (info->r < resize_threshold) { + if (r < resize_threshold) { size_t size = info->resize_down ? resize_min : resize_max; bool resized; @@ -151,13 +158,14 @@ static void do_rz(struct thread_info *info) static void do_rw(struct thread_info *info) { struct thread_stats *stats = &info->stats; + uint64_t r = info->seed - 1; uint32_t hash; long *p; - if (info->r >= update_threshold) { + if (r >= update_threshold) { bool read; - p = &keys[info->r & (lookup_range - 1)]; + p = &keys[r & (lookup_range - 1)]; hash = hfunc(*p); read = qht_lookup(&ht, p, hash); if (read) { @@ -166,7 +174,7 @@ static void do_rw(struct thread_info *info) stats->not_rd++; } } else { - p = &keys[info->r & (update_range - 1)]; + p = &keys[r & (update_range - 1)]; hash = hfunc(*p); if (info->write_op) { bool written = false; @@ -201,14 +209,14 @@ static void *thread_func(void *p) rcu_register_thread(); - atomic_inc(&n_ready_threads); - while (!atomic_read(&test_start)) { + qatomic_inc(&n_ready_threads); + while (!qatomic_read(&test_start)) { cpu_relax(); } rcu_read_lock(); - while (!atomic_read(&test_stop)) { - info->r = xorshift64star(info->r); + while (!qatomic_read(&test_stop)) { + info->seed = xorshift64star(info->seed); info->func(info); } rcu_read_unlock(); @@ -221,7 +229,7 @@ static void *thread_func(void *p) static void prepare_thread_info(struct thread_info *info, int i) { /* seed for the RNG; each thread should have a different one */ - info->r = (i + 1) ^ time(NULL); + info->seed = (i + 1) ^ time(NULL); /* the first update will be a write */ info->write_op = true; /* the first resize will be down */ @@ -281,10 +289,25 @@ static void pr_params(void) static void do_threshold(double rate, uint64_t *threshold) { + /* + * For 0 <= rate <= 1, scale to fit in a uint64_t. + * + * Scale by 2**64, with a special case for 1.0. + * The remainder of the possible values are scattered between 0 + * and 0xfffffffffffff800 (nextafter(0x1p64, 0)). + * + * Note that we cannot simply scale by UINT64_MAX, because that + * value is not representable as an IEEE double value. + * + * If we scale by the next largest value, nextafter(0x1p64, 0), + * then the remainder of the possible values are scattered between + * 0 and 0xfffffffffffff000. Which leaves us with a gap between + * the final two inputs that is twice as large as any other. + */ if (rate == 1.0) { *threshold = UINT64_MAX; } else { - *threshold = rate * UINT64_MAX; + *threshold = rate * 0x1p64; } } @@ -400,13 +423,13 @@ static void run_test(void) { int i; - while (atomic_read(&n_ready_threads) != n_rw_threads + n_rz_threads) { + while (qatomic_read(&n_ready_threads) != n_rw_threads + n_rz_threads) { cpu_relax(); } - atomic_set(&test_start, true); + qatomic_set(&test_start, true); g_usleep(duration * G_USEC_PER_SEC); - atomic_set(&test_stop, true); + qatomic_set(&test_stop, true); for (i = 0; i < n_rw_threads; i++) { qemu_thread_join(&rw_threads[i]); diff --git a/tests/qtest/Makefile.include b/tests/qtest/Makefile.include deleted file mode 100644 index 9e5a51d033aed312f1ab41fcb96a21d773481903..0000000000000000000000000000000000000000 --- a/tests/qtest/Makefile.include +++ /dev/null @@ -1,325 +0,0 @@ -# All QTests for now are POSIX-only, but the dependencies are -# really in libqtest, not in the testcases themselves. - -check-qtest-generic-y += cdrom-test -check-qtest-generic-y += device-introspect-test -check-qtest-generic-y += machine-none-test -check-qtest-generic-y += qmp-test -check-qtest-generic-y += qmp-cmd-test -check-qtest-generic-y += qom-test -check-qtest-generic-$(CONFIG_MODULES) += modules-test -check-qtest-generic-y += test-hmp - -check-qtest-pci-$(CONFIG_RTL8139_PCI) += rtl8139-test -check-qtest-pci-$(CONFIG_VGA) += display-vga-test -check-qtest-pci-$(CONFIG_HDA) += intel-hda-test -check-qtest-pci-$(CONFIG_IVSHMEM_DEVICE) += ivshmem-test - -DBUS_DAEMON := $(shell which dbus-daemon 2>/dev/null) -ifneq ($(GDBUS_CODEGEN),) -ifneq ($(DBUS_DAEMON),) -# Temporarily disabled due to Patchew failures: -#check-qtest-pci-$(CONFIG_GIO) += dbus-vmstate-test -endif -endif - -check-qtest-i386-$(CONFIG_ISA_TESTDEV) = endianness-test -check-qtest-i386-y += fdc-test -check-qtest-i386-y += ide-test -check-qtest-i386-$(CONFIG_TOOLS) += ahci-test -check-qtest-i386-y += hd-geo-test -check-qtest-i386-y += boot-order-test -check-qtest-i386-y += bios-tables-test -check-qtest-i386-$(CONFIG_SGA) += boot-serial-test -check-qtest-i386-$(CONFIG_SLIRP) += pxe-test -check-qtest-i386-y += rtc-test -check-qtest-i386-$(CONFIG_ISA_IPMI_KCS) += ipmi-kcs-test -ifdef CONFIG_LINUX -check-qtest-i386-$(CONFIG_ISA_IPMI_BT) += ipmi-bt-test -endif -check-qtest-i386-y += i440fx-test -check-qtest-i386-y += fw_cfg-test -check-qtest-i386-y += device-plug-test -check-qtest-i386-y += drive_del-test -check-qtest-i386-$(CONFIG_WDT_IB700) += wdt_ib700-test -check-qtest-i386-y += tco-test -check-qtest-i386-y += $(check-qtest-pci-y) -check-qtest-i386-$(CONFIG_PVPANIC) += pvpanic-test -check-qtest-i386-$(CONFIG_I82801B11) += i82801b11-test -check-qtest-i386-$(CONFIG_IOH3420) += ioh3420-test -check-qtest-i386-$(CONFIG_USB_UHCI) += usb-hcd-uhci-test -check-qtest-i386-$(call land,$(CONFIG_USB_EHCI),$(CONFIG_USB_UHCI)) += usb-hcd-ehci-test -check-qtest-i386-$(CONFIG_USB_XHCI_NEC) += usb-hcd-xhci-test -check-qtest-i386-y += cpu-plug-test -check-qtest-i386-y += q35-test -check-qtest-i386-y += vmgenid-test -check-qtest-i386-$(CONFIG_TPM_CRB) += tpm-crb-swtpm-test -check-qtest-i386-$(CONFIG_TPM_CRB) += tpm-crb-test -check-qtest-i386-$(CONFIG_TPM_TIS_ISA) += tpm-tis-swtpm-test -check-qtest-i386-$(CONFIG_TPM_TIS_ISA) += tpm-tis-test -check-qtest-i386-$(CONFIG_SLIRP) += test-netfilter -check-qtest-i386-$(CONFIG_POSIX) += test-filter-mirror -check-qtest-i386-$(CONFIG_RTL8139_PCI) += test-filter-redirector -check-qtest-i386-y += migration-test -check-qtest-i386-y += test-x86-cpuid-compat -check-qtest-i386-y += numa-test - -check-qtest-x86_64-y += $(check-qtest-i386-y) - -check-qtest-alpha-y += boot-serial-test -check-qtest-alpha-$(CONFIG_VGA) += display-vga-test - -check-qtest-hppa-y += boot-serial-test -check-qtest-hppa-$(CONFIG_VGA) += display-vga-test - -check-qtest-m68k-y = boot-serial-test - -check-qtest-microblaze-y += boot-serial-test - -check-qtest-mips-$(CONFIG_ISA_TESTDEV) = endianness-test -check-qtest-mips-$(CONFIG_VGA) += display-vga-test - -check-qtest-mips64-$(CONFIG_ISA_TESTDEV) = endianness-test -check-qtest-mips64-$(CONFIG_VGA) += display-vga-test - -check-qtest-mips64el-$(CONFIG_ISA_TESTDEV) = endianness-test -check-qtest-mips64el-$(CONFIG_VGA) += display-vga-test - -check-qtest-moxie-y += boot-serial-test - -check-qtest-ppc-$(CONFIG_ISA_TESTDEV) = endianness-test -check-qtest-ppc-y += boot-order-test -check-qtest-ppc-y += prom-env-test -check-qtest-ppc-y += drive_del-test -check-qtest-ppc-y += boot-serial-test -check-qtest-ppc-$(CONFIG_M48T59) += m48t59-test - -check-qtest-ppc64-y += $(check-qtest-ppc-y) -check-qtest-ppc64-$(CONFIG_PSERIES) += device-plug-test -check-qtest-ppc64-$(CONFIG_POWERNV) += pnv-xscom-test -check-qtest-ppc64-y += migration-test -check-qtest-ppc64-$(CONFIG_PSERIES) += rtas-test -check-qtest-ppc64-$(CONFIG_SLIRP) += pxe-test -check-qtest-ppc64-$(CONFIG_USB_UHCI) += usb-hcd-uhci-test -check-qtest-ppc64-$(CONFIG_USB_XHCI_NEC) += usb-hcd-xhci-test -check-qtest-ppc64-$(CONFIG_SLIRP) += test-netfilter -check-qtest-ppc64-$(CONFIG_POSIX) += test-filter-mirror -check-qtest-ppc64-$(CONFIG_RTL8139_PCI) += test-filter-redirector -check-qtest-ppc64-$(CONFIG_VGA) += display-vga-test -check-qtest-ppc64-y += numa-test -check-qtest-ppc64-$(CONFIG_IVSHMEM_DEVICE) += ivshmem-test -check-qtest-ppc64-y += cpu-plug-test - -check-qtest-sh4-$(CONFIG_ISA_TESTDEV) = endianness-test - -check-qtest-sh4eb-$(CONFIG_ISA_TESTDEV) = endianness-test - -check-qtest-sparc-y += prom-env-test -check-qtest-sparc-y += m48t59-test -check-qtest-sparc-y += boot-serial-test - -check-qtest-sparc64-$(CONFIG_ISA_TESTDEV) = endianness-test -check-qtest-sparc64-y += prom-env-test -check-qtest-sparc64-y += boot-serial-test - -check-qtest-arm-y += arm-cpu-features -check-qtest-arm-y += microbit-test -check-qtest-arm-y += m25p80-test -check-qtest-arm-y += test-arm-mptimer -check-qtest-arm-y += boot-serial-test -check-qtest-arm-y += hexloader-test -check-qtest-arm-$(CONFIG_PFLASH_CFI02) += pflash-cfi02-test - -check-qtest-aarch64-y += arm-cpu-features -check-qtest-aarch64-$(CONFIG_TPM_TIS_SYSBUS) += tpm-tis-device-test -check-qtest-aarch64-$(CONFIG_TPM_TIS_SYSBUS) += tpm-tis-device-swtpm-test -check-qtest-aarch64-y += numa-test -check-qtest-aarch64-y += boot-serial-test -check-qtest-aarch64-y += migration-test - -# TODO: once aarch64 TCG is fixed on ARM 32 bit host, make test unconditional -ifneq ($(ARCH),arm) -check-qtest-aarch64-y += bios-tables-test -endif - -check-qtest-microblazeel-y += $(check-qtest-microblaze-y) - -check-qtest-xtensaeb-y += $(check-qtest-xtensa-y) - -check-qtest-s390x-y = boot-serial-test -check-qtest-s390x-$(CONFIG_SLIRP) += pxe-test -check-qtest-s390x-$(CONFIG_SLIRP) += test-netfilter -check-qtest-s390x-$(CONFIG_POSIX) += test-filter-mirror -check-qtest-s390x-$(CONFIG_POSIX) += test-filter-redirector -check-qtest-s390x-y += drive_del-test -check-qtest-s390x-y += device-plug-test -check-qtest-s390x-y += virtio-ccw-test -check-qtest-s390x-y += cpu-plug-test -check-qtest-s390x-y += migration-test - -# libqos / qgraph : -libqgraph-obj-y = tests/qtest/libqos/qgraph.o - -libqos-core-obj-y = $(libqgraph-obj-y) tests/qtest/libqos/pci.o tests/qtest/libqos/fw_cfg.o -libqos-core-obj-y += tests/qtest/libqos/malloc.o -libqos-core-obj-y += tests/qtest/libqos/libqos.o -libqos-spapr-obj-y = $(libqos-core-obj-y) tests/qtest/libqos/malloc-spapr.o -libqos-spapr-obj-y += tests/qtest/libqos/libqos-spapr.o -libqos-spapr-obj-y += tests/qtest/libqos/rtas.o -libqos-spapr-obj-y += tests/qtest/libqos/pci-spapr.o -libqos-pc-obj-y = $(libqos-core-obj-y) tests/qtest/libqos/pci-pc.o -libqos-pc-obj-y += tests/qtest/libqos/malloc-pc.o tests/qtest/libqos/libqos-pc.o -libqos-pc-obj-y += tests/qtest/libqos/ahci.o -libqos-usb-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/qtest/libqos/usb.o - -# qos devices: -libqos-obj-y = $(libqgraph-obj-y) -libqos-obj-y += $(libqos-pc-obj-y) $(libqos-spapr-obj-y) -libqos-obj-y += tests/qtest/libqos/qos_external.o -libqos-obj-y += tests/qtest/libqos/e1000e.o -libqos-obj-y += tests/qtest/libqos/i2c.o -libqos-obj-y += tests/qtest/libqos/i2c-imx.o -libqos-obj-y += tests/qtest/libqos/i2c-omap.o -libqos-obj-y += tests/qtest/libqos/sdhci.o -libqos-obj-y += tests/qtest/libqos/tpci200.o -libqos-obj-y += tests/qtest/libqos/virtio.o -libqos-obj-$(CONFIG_VIRTFS) += tests/qtest/libqos/virtio-9p.o -libqos-obj-y += tests/qtest/libqos/virtio-balloon.o -libqos-obj-y += tests/qtest/libqos/virtio-blk.o -libqos-obj-y += tests/qtest/libqos/virtio-mmio.o -libqos-obj-y += tests/qtest/libqos/virtio-net.o -libqos-obj-y += tests/qtest/libqos/virtio-pci.o -libqos-obj-y += tests/qtest/libqos/virtio-pci-modern.o -libqos-obj-y += tests/qtest/libqos/virtio-rng.o -libqos-obj-y += tests/qtest/libqos/virtio-scsi.o -libqos-obj-y += tests/qtest/libqos/virtio-serial.o - -# qos machines: -libqos-obj-y += tests/qtest/libqos/aarch64-xlnx-zcu102-machine.o -libqos-obj-y += tests/qtest/libqos/arm-imx25-pdk-machine.o -libqos-obj-y += tests/qtest/libqos/arm-n800-machine.o -libqos-obj-y += tests/qtest/libqos/arm-raspi2-machine.o -libqos-obj-y += tests/qtest/libqos/arm-sabrelite-machine.o -libqos-obj-y += tests/qtest/libqos/arm-smdkc210-machine.o -libqos-obj-y += tests/qtest/libqos/arm-virt-machine.o -libqos-obj-y += tests/qtest/libqos/arm-xilinx-zynq-a9-machine.o -libqos-obj-y += tests/qtest/libqos/ppc64_pseries-machine.o -libqos-obj-y += tests/qtest/libqos/x86_64_pc-machine.o - -# qos tests: -qos-test-obj-y += tests/qtest/qos-test.o -qos-test-obj-y += tests/qtest/ac97-test.o -qos-test-obj-y += tests/qtest/ds1338-test.o -qos-test-obj-y += tests/qtest/e1000-test.o -qos-test-obj-y += tests/qtest/e1000e-test.o -qos-test-obj-y += tests/qtest/eepro100-test.o -qos-test-obj-y += tests/qtest/es1370-test.o -qos-test-obj-y += tests/qtest/ipoctal232-test.o -qos-test-obj-y += tests/qtest/megasas-test.o -qos-test-obj-y += tests/qtest/ne2000-test.o -qos-test-obj-y += tests/qtest/tulip-test.o -qos-test-obj-y += tests/qtest/nvme-test.o -qos-test-obj-y += tests/qtest/pca9552-test.o -qos-test-obj-y += tests/qtest/pci-test.o -qos-test-obj-y += tests/qtest/pcnet-test.o -qos-test-obj-y += tests/qtest/sdhci-test.o -qos-test-obj-y += tests/qtest/spapr-phb-test.o -qos-test-obj-y += tests/qtest/tmp105-test.o -qos-test-obj-y += tests/qtest/usb-hcd-ohci-test.o $(libqos-usb-obj-y) -qos-test-obj-$(CONFIG_VHOST_NET_USER) += tests/qtest/vhost-user-test.o $(chardev-obj-y) $(test-io-obj-y) -qos-test-obj-y += tests/qtest/virtio-test.o -qos-test-obj-$(CONFIG_VIRTFS) += tests/qtest/virtio-9p-test.o -qos-test-obj-y += tests/qtest/virtio-blk-test.o -qos-test-obj-y += tests/qtest/virtio-net-test.o -qos-test-obj-y += tests/qtest/virtio-rng-test.o -qos-test-obj-y += tests/qtest/virtio-scsi-test.o -qos-test-obj-y += tests/qtest/virtio-serial-test.o -qos-test-obj-y += tests/qtest/vmxnet3-test.o - -check-unit-y += tests/test-qgraph$(EXESUF) -tests/test-qgraph$(EXESUF): tests/test-qgraph.o $(libqgraph-obj-y) - -check-qtest-generic-y += qos-test -tests/qtest/qos-test$(EXESUF): $(qos-test-obj-y) $(libqos-obj-y) - -# QTest dependencies: -tests/qtest/qmp-test$(EXESUF): tests/qtest/qmp-test.o -tests/qtest/qmp-cmd-test$(EXESUF): tests/qtest/qmp-cmd-test.o -tests/qtest/device-introspect-test$(EXESUF): tests/qtest/device-introspect-test.o -tests/qtest/rtc-test$(EXESUF): tests/qtest/rtc-test.o -tests/qtest/m48t59-test$(EXESUF): tests/qtest/m48t59-test.o -tests/qtest/hexloader-test$(EXESUF): tests/qtest/hexloader-test.o -tests/qtest/pflash-cfi02$(EXESUF): tests/qtest/pflash-cfi02-test.o -tests/qtest/endianness-test$(EXESUF): tests/qtest/endianness-test.o -tests/qtest/prom-env-test$(EXESUF): tests/qtest/prom-env-test.o $(libqos-obj-y) -tests/qtest/rtas-test$(EXESUF): tests/qtest/rtas-test.o $(libqos-spapr-obj-y) -tests/qtest/fdc-test$(EXESUF): tests/qtest/fdc-test.o -tests/qtest/ide-test$(EXESUF): tests/qtest/ide-test.o $(libqos-pc-obj-y) -tests/qtest/ahci-test$(EXESUF): tests/qtest/ahci-test.o $(libqos-pc-obj-y) qemu-img$(EXESUF) -tests/qtest/ipmi-kcs-test$(EXESUF): tests/qtest/ipmi-kcs-test.o -tests/qtest/ipmi-bt-test$(EXESUF): tests/qtest/ipmi-bt-test.o -tests/qtest/hd-geo-test$(EXESUF): tests/qtest/hd-geo-test.o $(libqos-obj-y) -tests/qtest/boot-order-test$(EXESUF): tests/qtest/boot-order-test.o $(libqos-obj-y) -tests/qtest/boot-serial-test$(EXESUF): tests/qtest/boot-serial-test.o $(libqos-obj-y) -tests/qtest/bios-tables-test$(EXESUF): tests/qtest/bios-tables-test.o \ - tests/qtest/boot-sector.o tests/qtest/acpi-utils.o $(libqos-obj-y) -tests/qtest/pxe-test$(EXESUF): tests/qtest/pxe-test.o tests/qtest/boot-sector.o $(libqos-obj-y) -tests/qtest/microbit-test$(EXESUF): tests/qtest/microbit-test.o -tests/qtest/m25p80-test$(EXESUF): tests/qtest/m25p80-test.o -tests/qtest/i440fx-test$(EXESUF): tests/qtest/i440fx-test.o $(libqos-pc-obj-y) -tests/qtest/q35-test$(EXESUF): tests/qtest/q35-test.o $(libqos-pc-obj-y) -tests/qtest/fw_cfg-test$(EXESUF): tests/qtest/fw_cfg-test.o $(libqos-pc-obj-y) -tests/qtest/rtl8139-test$(EXESUF): tests/qtest/rtl8139-test.o $(libqos-pc-obj-y) -tests/qtest/pnv-xscom-test$(EXESUF): tests/qtest/pnv-xscom-test.o -tests/qtest/wdt_ib700-test$(EXESUF): tests/qtest/wdt_ib700-test.o -tests/qtest/tco-test$(EXESUF): tests/qtest/tco-test.o $(libqos-pc-obj-y) -tests/qtest/virtio-ccw-test$(EXESUF): tests/qtest/virtio-ccw-test.o -tests/qtest/display-vga-test$(EXESUF): tests/qtest/display-vga-test.o -tests/qtest/qom-test$(EXESUF): tests/qtest/qom-test.o -tests/qtest/test-hmp$(EXESUF): tests/qtest/test-hmp.o -tests/qtest/machine-none-test$(EXESUF): tests/qtest/machine-none-test.o -tests/qtest/device-plug-test$(EXESUF): tests/qtest/device-plug-test.o -tests/qtest/drive_del-test$(EXESUF): tests/qtest/drive_del-test.o -tests/qtest/pvpanic-test$(EXESUF): tests/qtest/pvpanic-test.o -tests/qtest/i82801b11-test$(EXESUF): tests/qtest/i82801b11-test.o -tests/qtest/intel-hda-test$(EXESUF): tests/qtest/intel-hda-test.o -tests/qtest/ioh3420-test$(EXESUF): tests/qtest/ioh3420-test.o -tests/qtest/usb-hcd-uhci-test$(EXESUF): tests/qtest/usb-hcd-uhci-test.o $(libqos-usb-obj-y) -tests/qtest/usb-hcd-ehci-test$(EXESUF): tests/qtest/usb-hcd-ehci-test.o $(libqos-usb-obj-y) -tests/qtest/usb-hcd-xhci-test$(EXESUF): tests/qtest/usb-hcd-xhci-test.o $(libqos-usb-obj-y) -tests/qtest/cpu-plug-test$(EXESUF): tests/qtest/cpu-plug-test.o -tests/qtest/migration-test$(EXESUF): tests/qtest/migration-test.o tests/qtest/migration-helpers.o -tests/qtest/test-netfilter$(EXESUF): tests/qtest/test-netfilter.o $(qtest-obj-y) -tests/qtest/test-filter-mirror$(EXESUF): tests/qtest/test-filter-mirror.o $(qtest-obj-y) -tests/qtest/test-filter-redirector$(EXESUF): tests/qtest/test-filter-redirector.o $(qtest-obj-y) -tests/qtest/test-x86-cpuid-compat$(EXESUF): tests/qtest/test-x86-cpuid-compat.o $(qtest-obj-y) -tests/qtest/ivshmem-test$(EXESUF): tests/qtest/ivshmem-test.o contrib/ivshmem-server/ivshmem-server.o $(libqos-pc-obj-y) $(libqos-spapr-obj-y) -tests/qtest/dbus-vmstate-test$(EXESUF): tests/qtest/dbus-vmstate-test.o tests/qtest/migration-helpers.o tests/qtest/dbus-vmstate1.o $(libqos-pc-obj-y) $(libqos-spapr-obj-y) -tests/qtest/test-arm-mptimer$(EXESUF): tests/qtest/test-arm-mptimer.o -tests/qtest/numa-test$(EXESUF): tests/qtest/numa-test.o -tests/qtest/vmgenid-test$(EXESUF): tests/qtest/vmgenid-test.o tests/qtest/boot-sector.o tests/qtest/acpi-utils.o -tests/qtest/cdrom-test$(EXESUF): tests/qtest/cdrom-test.o tests/qtest/boot-sector.o $(libqos-obj-y) -tests/qtest/arm-cpu-features$(EXESUF): tests/qtest/arm-cpu-features.o -tests/qtest/tpm-crb-swtpm-test$(EXESUF): tests/qtest/tpm-crb-swtpm-test.o tests/qtest/tpm-emu.o \ - tests/qtest/tpm-util.o tests/qtest/tpm-tests.o $(test-io-obj-y) -tests/qtest/tpm-crb-test$(EXESUF): tests/qtest/tpm-crb-test.o tests/qtest/tpm-emu.o $(test-io-obj-y) -tests/qtest/tpm-tis-swtpm-test$(EXESUF): tests/qtest/tpm-tis-swtpm-test.o tests/qtest/tpm-emu.o \ - tests/qtest/tpm-util.o tests/qtest/tpm-tests.o $(test-io-obj-y) -tests/qtest/tpm-tis-device-swtpm-test$(EXESUF): tests/qtest/tpm-tis-device-swtpm-test.o tests/qtest/tpm-emu.o \ - tests/qtest/tpm-util.o tests/qtest/tpm-tests.o $(test-io-obj-y) -tests/qtest/tpm-tis-test$(EXESUF): tests/qtest/tpm-tis-test.o tests/qtest/tpm-tis-util.o tests/qtest/tpm-emu.o $(test-io-obj-y) -tests/qtest/tpm-tis-device-test$(EXESUF): tests/qtest/tpm-tis-device-test.o tests/qtest/tpm-tis-util.o tests/qtest/tpm-emu.o $(test-io-obj-y) - -# QTest rules - -TARGETS=$(patsubst %-softmmu,%, $(filter %-softmmu,$(TARGET_DIRS))) -ifeq ($(CONFIG_POSIX),y) -QTEST_TARGETS = $(TARGETS) -check-qtest-y=$(foreach TARGET,$(TARGETS), $(check-qtest-$(TARGET)-y:%=tests/qtest/%$(EXESUF))) -check-qtest-y += $(check-qtest-generic-y:%=tests/qtest/%$(EXESUF)) -else -QTEST_TARGETS = -endif - -qtest-obj-y = tests/qtest/libqtest.o $(test-util-obj-y) -$(check-qtest-y): $(qtest-obj-y) diff --git a/tests/qtest/ac97-test.c b/tests/qtest/ac97-test.c index b084e31bff5ffd05caf58a8be29d85a9db619d7b..e09f2495d24da37cd5a94d83afbe2c2291830087 100644 --- a/tests/qtest/ac97-test.c +++ b/tests/qtest/ac97-test.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/module.h" #include "libqos/qgraph.h" #include "libqos/pci.h" diff --git a/tests/qtest/acpi-utils.h b/tests/qtest/acpi-utils.h index 0c86780689315d76a534f9dd524f72e0c0c74206..261784d251896e923538171f8340b9961e6c501b 100644 --- a/tests/qtest/acpi-utils.h +++ b/tests/qtest/acpi-utils.h @@ -13,7 +13,7 @@ #ifndef TEST_ACPI_UTILS_H #define TEST_ACPI_UTILS_H -#include "libqtest.h" +#include "libqos/libqtest.h" /* DSDT and SSDTs format */ typedef struct { diff --git a/tests/qtest/ahci-test.c b/tests/qtest/ahci-test.c index c8d42ceea0575db645ce62ec2f0bdb87b6b9921f..5e1954852e71af913ce81cd0900fb326d40f882e 100644 --- a/tests/qtest/ahci-test.c +++ b/tests/qtest/ahci-test.c @@ -25,7 +25,7 @@ #include "qemu/osdep.h" #include -#include "libqtest.h" +#include "libqos/libqtest.h" #include "libqos/libqos-pc.h" #include "libqos/ahci.h" #include "libqos/pci-pc.h" @@ -1443,6 +1443,7 @@ static int prepare_iso(size_t size, unsigned char **buf, char **name) ssize_t ret; int fd = mkstemp(cdrom_path); + g_assert(fd != -1); g_assert(buf); g_assert(name); patt = g_malloc(size); diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c index 469217367661811129f642c76778fdc482c00d2a..bc681a95d52110217e467972c648d95506857ce2 100644 --- a/tests/qtest/arm-cpu-features.c +++ b/tests/qtest/arm-cpu-features.c @@ -10,7 +10,7 @@ */ #include "qemu/osdep.h" #include "qemu/bitops.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qjson.h" @@ -159,16 +159,35 @@ static bool resp_get_feature(QDict *resp, const char *feature) qobject_unref(_resp); \ }) -#define assert_feature(qts, cpu_type, feature, expected_value) \ +#define resp_assert_feature(resp, feature, expected_value) \ ({ \ - QDict *_resp, *_props; \ + QDict *_props; \ \ - _resp = do_query_no_props(qts, cpu_type); \ g_assert(_resp); \ g_assert(resp_has_props(_resp)); \ _props = resp_get_props(_resp); \ g_assert(qdict_get(_props, feature)); \ g_assert(qdict_get_bool(_props, feature) == (expected_value)); \ +}) + +#define assert_feature(qts, cpu_type, feature, expected_value) \ +({ \ + QDict *_resp; \ + \ + _resp = do_query_no_props(qts, cpu_type); \ + g_assert(_resp); \ + resp_assert_feature(_resp, feature, expected_value); \ + qobject_unref(_resp); \ +}) + +#define assert_set_feature(qts, cpu_type, feature, value) \ +({ \ + const char *_fmt = (value) ? "{ %s: true }" : "{ %s: false }"; \ + QDict *_resp; \ + \ + _resp = do_query(qts, cpu_type, _fmt, feature); \ + g_assert(_resp); \ + resp_assert_feature(_resp, feature, value); \ qobject_unref(_resp); \ }) @@ -424,11 +443,16 @@ static void test_query_cpu_model_expansion(const void *data) assert_error(qts, "host", "The CPU type 'host' requires KVM", NULL); /* Test expected feature presence/absence for some cpu types */ - assert_has_feature_enabled(qts, "max", "pmu"); assert_has_feature_enabled(qts, "cortex-a15", "pmu"); assert_has_not_feature(qts, "cortex-a15", "aarch64"); + /* Enabling and disabling pmu should always work. */ + assert_has_feature_enabled(qts, "max", "pmu"); + assert_set_feature(qts, "max", "pmu", false); + assert_set_feature(qts, "max", "pmu", true); + assert_has_not_feature(qts, "max", "kvm-no-adjvtime"); + assert_has_not_feature(qts, "max", "kvm-steal-time"); if (g_str_equal(qtest_get_arch(), "aarch64")) { assert_has_feature_enabled(qts, "max", "aarch64"); @@ -464,9 +488,13 @@ static void test_query_cpu_model_expansion_kvm(const void *data) return; } + /* Enabling and disabling kvm-no-adjvtime should always work. */ assert_has_feature_disabled(qts, "host", "kvm-no-adjvtime"); + assert_set_feature(qts, "host", "kvm-no-adjvtime", true); + assert_set_feature(qts, "host", "kvm-no-adjvtime", false); if (g_str_equal(qtest_get_arch(), "aarch64")) { + bool kvm_supports_steal_time; bool kvm_supports_sve; char max_name[8], name[8]; uint32_t max_vq, vq; @@ -474,23 +502,41 @@ static void test_query_cpu_model_expansion_kvm(const void *data) QDict *resp; char *error; - assert_has_feature_enabled(qts, "host", "aarch64"); - assert_has_feature_enabled(qts, "host", "pmu"); - assert_error(qts, "cortex-a15", "We cannot guarantee the CPU type 'cortex-a15' works " "with KVM on this host", NULL); + assert_has_feature_enabled(qts, "host", "aarch64"); + + /* Enabling and disabling pmu should always work. */ + assert_has_feature_enabled(qts, "host", "pmu"); + assert_set_feature(qts, "host", "pmu", false); + assert_set_feature(qts, "host", "pmu", true); + + /* + * Some features would be enabled by default, but they're disabled + * because this instance of KVM doesn't support them. Test that the + * features are present, and, when enabled, issue further tests. + */ + assert_has_feature(qts, "host", "kvm-steal-time"); assert_has_feature(qts, "host", "sve"); + resp = do_query_no_props(qts, "host"); + kvm_supports_steal_time = resp_get_feature(resp, "kvm-steal-time"); kvm_supports_sve = resp_get_feature(resp, "sve"); vls = resp_get_sve_vls(resp); qobject_unref(resp); + if (kvm_supports_steal_time) { + /* If we have steal-time then we should be able to toggle it. */ + assert_set_feature(qts, "host", "kvm-steal-time", false); + assert_set_feature(qts, "host", "kvm-steal-time", true); + } + if (kvm_supports_sve) { g_assert(vls != 0); max_vq = 64 - __builtin_clzll(vls); - sprintf(max_name, "sve%d", max_vq * 128); + sprintf(max_name, "sve%u", max_vq * 128); /* Enabling a supported length is of course fine. */ assert_sve_vls(qts, "host", vls, "{ %s: true }", max_name); @@ -510,7 +556,7 @@ static void test_query_cpu_model_expansion_kvm(const void *data) * unless all larger, supported vector lengths are also * disabled. */ - sprintf(name, "sve%d", vq * 128); + sprintf(name, "sve%u", vq * 128); error = g_strdup_printf("cannot disable %s", name); assert_error(qts, "host", error, "{ %s: true, %s: false }", @@ -523,7 +569,7 @@ static void test_query_cpu_model_expansion_kvm(const void *data) * we need at least one vector length enabled. */ vq = __builtin_ffsll(vls); - sprintf(name, "sve%d", vq * 128); + sprintf(name, "sve%u", vq * 128); error = g_strdup_printf("cannot disable %s", name); assert_error(qts, "host", error, "{ %s: false }", name); g_free(error); @@ -535,7 +581,7 @@ static void test_query_cpu_model_expansion_kvm(const void *data) } } if (vq <= SVE_MAX_VQ) { - sprintf(name, "sve%d", vq * 128); + sprintf(name, "sve%u", vq * 128); error = g_strdup_printf("cannot enable %s", name); assert_error(qts, "host", error, "{ %s: true }", name); g_free(error); @@ -547,6 +593,7 @@ static void test_query_cpu_model_expansion_kvm(const void *data) assert_has_not_feature(qts, "host", "aarch64"); assert_has_not_feature(qts, "host", "pmu"); assert_has_not_feature(qts, "host", "sve"); + assert_has_not_feature(qts, "host", "kvm-steal-time"); } qtest_quit(qts); diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index c9843829b3ddb6dfd00ead6b7944ceb72bfbce73..f23a5335a875694048e0758edbfff984cf355b78 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -11,7 +11,7 @@ */ /* - * How to add or update the tests: + * How to add or update the tests or commit changes that affect ACPI tables: * Contributor: * 1. add empty files for new tables, if any, under tests/data/acpi * 2. list any changed files in tests/qtest/bios-tables-test-allowed-diff.h @@ -38,6 +38,11 @@ * $(SRC_PATH)/tests/data/acpi/rebuild-expected-aml.sh * 6. Now commit any changes to the expected binary, include diff from step 4 * in commit log. + * Expected binary updates needs to be a separate patch from the code that + * introduces changes to ACPI tables. It lets the maintainer drop + * and regenerate binary updates in case of merge conflicts. Further, a code + * change is easily reviewable but a binary blob is not (without doing a + * disassembly). * 7. Before sending patches to the list (Contributor) * or before doing a pull request (Maintainer), make sure * tests/qtest/bios-tables-test-allowed-diff.h is empty - this will ensure @@ -57,6 +62,9 @@ #include "qemu/bitmap.h" #include "acpi-utils.h" #include "boot-sector.h" +#include "tpm-emu.h" +#include "hw/acpi/tpm.h" + #define MACHINE_PC "pc" #define MACHINE_Q35 "q35" @@ -69,6 +77,7 @@ typedef struct { const char *variant; const char *uefi_fl1; const char *uefi_fl2; + const char *blkdev; const char *cd; const uint64_t ram_start; const uint64_t scan_len; @@ -77,6 +86,8 @@ typedef struct { GArray *tables; uint32_t smbios_ep_addr; struct smbios_21_entry_point smbios_ep_table; + uint16_t smbios_cpu_max_speed; + uint16_t smbios_cpu_curr_speed; uint8_t *required_struct_types; int required_struct_types_len; QTestState *qts; @@ -85,7 +96,7 @@ typedef struct { static char disk[] = "tests/acpi-test-disk-XXXXXX"; static const char *data_dir = "tests/data/acpi"; #ifdef CONFIG_IASL -static const char *iasl = stringify(CONFIG_IASL); +static const char *iasl = CONFIG_IASL; #else static const char *iasl; #endif @@ -116,6 +127,9 @@ static void free_test_data(test_data *data) { int i; + if (!data->tables) { + return; + } for (i = 0; i < data->tables->len; ++i) { cleanup_table_descriptor(&g_array_index(data->tables, AcpiSdtTable, i)); } @@ -466,7 +480,7 @@ static void test_acpi_asl(test_data *data) fflush(stderr); if (getenv("V")) { const char *diff_env = getenv("DIFF"); - const char *diff_cmd = diff_env ? diff_env : "diff -u"; + const char *diff_cmd = diff_env ? diff_env : "diff -U 16"; char *diff = g_strdup_printf("%s %s %s", diff_cmd, exp_sdt->asl_file, sdt->asl_file); int out = dup(STDOUT_FILENO); @@ -560,6 +574,31 @@ static inline bool smbios_single_instance(uint8_t type) } } +static bool smbios_cpu_test(test_data *data, uint32_t addr) +{ + uint16_t expect_speed[2]; + uint16_t real; + int offset[2]; + int i; + + /* Check CPU speed for backward compatibility */ + offset[0] = offsetof(struct smbios_type_4, max_speed); + offset[1] = offsetof(struct smbios_type_4, current_speed); + expect_speed[0] = data->smbios_cpu_max_speed ? : 2000; + expect_speed[1] = data->smbios_cpu_curr_speed ? : 2000; + + for (i = 0; i < 2; i++) { + real = qtest_readw(data->qts, addr + offset[i]); + if (real != expect_speed[i]) { + fprintf(stderr, "Unexpected SMBIOS CPU speed: real %u expect %u\n", + real, expect_speed[i]); + return false; + } + } + + return true; +} + static void test_smbios_structs(test_data *data) { DECLARE_BITMAP(struct_bitmap, SMBIOS_MAX_TYPE+1) = { 0 }; @@ -582,6 +621,10 @@ static void test_smbios_structs(test_data *data) } set_bit(type, struct_bitmap); + if (type == 4) { + g_assert(smbios_cpu_test(data, addr)); + } + /* seek to end of unformatted string area of this struct ("\0\0") */ prv = crt = 1; while (prv || crt) { @@ -616,6 +659,13 @@ static void test_acpi_one(const char *params, test_data *data) char *args; bool use_uefi = data->uefi_fl1 && data->uefi_fl2; +#ifndef CONFIG_TCG + if (data->tcg_only) { + g_test_skip("TCG disabled, skipping ACPI tcg_only test"); + return; + } +#endif /* CONFIG_TCG */ + if (use_uefi) { /* * TODO: convert '-drive if=pflash' to new syntax (see e33763be7cd3) @@ -628,13 +678,13 @@ static void test_acpi_one(const char *params, test_data *data) data->uefi_fl1, data->uefi_fl2, data->cd, params ? params : ""); } else { - /* Disable kernel irqchip to be able to override apic irq0. */ - args = g_strdup_printf("-machine %s,kernel-irqchip=off %s -accel tcg " + args = g_strdup_printf("-machine %s %s -accel tcg " "-net none -display none %s " "-drive id=hd0,if=none,file=%s,format=raw " - "-device ide-hd,drive=hd0 ", + "-device %s,drive=hd0 ", data->machine, data->tcg_only ? "" : "-accel kvm", - params ? params : "", disk); + params ? params : "", disk, + data->blkdev ?: "ide-hd"); } data->qts = qtest_init(args); @@ -706,6 +756,49 @@ static void test_acpi_piix4_tcg_bridge(void) free_test_data(&data); } +static void test_acpi_piix4_no_root_hotplug(void) +{ + test_data data; + + memset(&data, 0, sizeof(data)); + data.machine = MACHINE_PC; + data.variant = ".roothp"; + data.required_struct_types = base_required_struct_types; + data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); + test_acpi_one("-global PIIX4_PM.acpi-root-pci-hotplug=off " + "-device pci-bridge,chassis_nr=1", &data); + free_test_data(&data); +} + +static void test_acpi_piix4_no_bridge_hotplug(void) +{ + test_data data; + + memset(&data, 0, sizeof(data)); + data.machine = MACHINE_PC; + data.variant = ".hpbridge"; + data.required_struct_types = base_required_struct_types; + data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); + test_acpi_one("-global PIIX4_PM.acpi-pci-hotplug-with-bridge-support=off " + "-device pci-bridge,chassis_nr=1", &data); + free_test_data(&data); +} + +static void test_acpi_piix4_no_acpi_pci_hotplug(void) +{ + test_data data; + + memset(&data, 0, sizeof(data)); + data.machine = MACHINE_PC; + data.variant = ".hpbrroot"; + data.required_struct_types = base_required_struct_types; + data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); + test_acpi_one("-global PIIX4_PM.acpi-root-pci-hotplug=off " + "-global PIIX4_PM.acpi-pci-hotplug-with-bridge-support=off " + "-device pci-bridge,chassis_nr=1", &data); + free_test_data(&data); +} + static void test_acpi_q35_tcg(void) { test_data data; @@ -716,6 +809,11 @@ static void test_acpi_q35_tcg(void) data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); test_acpi_one(NULL, &data); free_test_data(&data); + + data.smbios_cpu_max_speed = 3000; + data.smbios_cpu_curr_speed = 2600; + test_acpi_one("-smbios type=4,max-speed=3000,current-speed=2600", &data); + free_test_data(&data); } static void test_acpi_q35_tcg_bridge(void) @@ -874,6 +972,65 @@ static void test_acpi_piix4_tcg_numamem(void) free_test_data(&data); } +uint64_t tpm_tis_base_addr; + +static void test_acpi_tcg_tpm(const char *machine, const char *tpm_if, + uint64_t base) +{ +#ifdef CONFIG_TPM + gchar *tmp_dir_name = g_strdup_printf("qemu-test_acpi_%s_tcg_%s.XXXXXX", + machine, tpm_if); + char *tmp_path = g_dir_make_tmp(tmp_dir_name, NULL); + TestState test; + test_data data; + GThread *thread; + char *args, *variant = g_strdup_printf(".%s", tpm_if); + + tpm_tis_base_addr = base; + + module_call_init(MODULE_INIT_QOM); + + test.addr = g_new0(SocketAddress, 1); + test.addr->type = SOCKET_ADDRESS_TYPE_UNIX; + test.addr->u.q_unix.path = g_build_filename(tmp_path, "sock", NULL); + g_mutex_init(&test.data_mutex); + g_cond_init(&test.data_cond); + test.data_cond_signal = false; + + thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test); + tpm_emu_test_wait_cond(&test); + + memset(&data, 0, sizeof(data)); + data.machine = machine; + data.variant = variant; + + args = g_strdup_printf( + " -chardev socket,id=chr,path=%s" + " -tpmdev emulator,id=dev,chardev=chr" + " -device tpm-%s,tpmdev=dev", + test.addr->u.q_unix.path, tpm_if); + + test_acpi_one(args, &data); + + g_thread_join(thread); + g_unlink(test.addr->u.q_unix.path); + qapi_free_SocketAddress(test.addr); + g_rmdir(tmp_path); + g_free(variant); + g_free(tmp_path); + g_free(tmp_dir_name); + g_free(args); + free_test_data(&data); +#else + g_test_skip("TPM disabled"); +#endif +} + +static void test_acpi_q35_tcg_tpm_tis(void) +{ + test_acpi_tcg_tpm("q35", "tis", 0xFED40000); +} + static void test_acpi_tcg_dimm_pxm(const char *machine) { test_data data; @@ -944,6 +1101,59 @@ static void test_acpi_virt_tcg_memhp(void) } +static void test_acpi_microvm_prepare(test_data *data) +{ + memset(data, 0, sizeof(*data)); + data->machine = "microvm"; + data->required_struct_types = NULL; /* no smbios */ + data->required_struct_types_len = 0; + data->blkdev = "virtio-blk-device"; +} + +static void test_acpi_microvm_tcg(void) +{ + test_data data; + + test_acpi_microvm_prepare(&data); + test_acpi_one(" -machine microvm,acpi=on,rtc=off", + &data); + free_test_data(&data); +} + +static void test_acpi_microvm_usb_tcg(void) +{ + test_data data; + + test_acpi_microvm_prepare(&data); + data.variant = ".usb"; + test_acpi_one(" -machine microvm,acpi=on,usb=on,rtc=off", + &data); + free_test_data(&data); +} + +static void test_acpi_microvm_rtc_tcg(void) +{ + test_data data; + + test_acpi_microvm_prepare(&data); + data.variant = ".rtc"; + test_acpi_one(" -machine microvm,acpi=on,rtc=on", + &data); + free_test_data(&data); +} + +static void test_acpi_microvm_pcie_tcg(void) +{ + test_data data; + + test_acpi_microvm_prepare(&data); + data.variant = ".pcie"; + data.tcg_only = true; /* need constant host-phys-bits */ + test_acpi_one(" -machine microvm,acpi=on,rtc=off,pcie=on", + &data); + free_test_data(&data); +} + static void test_acpi_virt_tcg_numamem(void) { test_data data = { @@ -1022,6 +1232,12 @@ static void test_acpi_virt_tcg(void) test_acpi_one("-cpu cortex-a57", &data); free_test_data(&data); + + data.smbios_cpu_max_speed = 2900; + data.smbios_cpu_curr_speed = 2700; + test_acpi_one("-cpu cortex-a57 " + "-smbios type=4,max-speed=2900,current-speed=2700", &data); + free_test_data(&data); } int main(int argc, char *argv[]) @@ -1037,8 +1253,15 @@ int main(int argc, char *argv[]) return ret; } + qtest_add_func("acpi/q35/tpm-tis", test_acpi_q35_tcg_tpm_tis); qtest_add_func("acpi/piix4", test_acpi_piix4_tcg); qtest_add_func("acpi/piix4/bridge", test_acpi_piix4_tcg_bridge); + qtest_add_func("acpi/piix4/pci-hotplug/no_root_hotplug", + test_acpi_piix4_no_root_hotplug); + qtest_add_func("acpi/piix4/pci-hotplug/no_bridge_hotplug", + test_acpi_piix4_no_bridge_hotplug); + qtest_add_func("acpi/piix4/pci-hotplug/off", + test_acpi_piix4_no_acpi_pci_hotplug); qtest_add_func("acpi/q35", test_acpi_q35_tcg); qtest_add_func("acpi/q35/bridge", test_acpi_q35_tcg_bridge); qtest_add_func("acpi/q35/mmio64", test_acpi_q35_tcg_mmio64); @@ -1054,6 +1277,12 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm); qtest_add_func("acpi/piix4/acpihmat", test_acpi_piix4_tcg_acpi_hmat); qtest_add_func("acpi/q35/acpihmat", test_acpi_q35_tcg_acpi_hmat); + qtest_add_func("acpi/microvm", test_acpi_microvm_tcg); + qtest_add_func("acpi/microvm/usb", test_acpi_microvm_usb_tcg); + qtest_add_func("acpi/microvm/rtc", test_acpi_microvm_rtc_tcg); + if (strcmp(arch, "x86_64") == 0) { + qtest_add_func("acpi/microvm/pcie", test_acpi_microvm_pcie_tcg); + } } else if (strcmp(arch, "aarch64") == 0) { qtest_add_func("acpi/virt", test_acpi_virt_tcg); qtest_add_func("acpi/virt/numamem", test_acpi_virt_tcg_numamem); diff --git a/tests/qtest/boot-order-test.c b/tests/qtest/boot-order-test.c index 2f1c07221c0b60a1adb272b47c2354be11158345..fac580d6c45cf8d4e8dc72dd6a02758a881766ba 100644 --- a/tests/qtest/boot-order-test.c +++ b/tests/qtest/boot-order-test.c @@ -12,7 +12,7 @@ #include "qemu/osdep.h" #include "libqos/fw_cfg.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qapi/qmp/qdict.h" #include "standard-headers/linux/qemu_fw_cfg.h" diff --git a/tests/qtest/boot-sector.c b/tests/qtest/boot-sector.c index 9e66c6d0130a35eb4bd7e703d22ab40d1ba037b5..24df5c4734668793c418b448afb5dac55036f7ff 100644 --- a/tests/qtest/boot-sector.c +++ b/tests/qtest/boot-sector.c @@ -13,7 +13,7 @@ #include "qemu/osdep.h" #include "boot-sector.h" #include "qemu-common.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #define LOW(x) ((x) & 0xff) #define HIGH(x) ((x) >> 8) diff --git a/tests/qtest/boot-sector.h b/tests/qtest/boot-sector.h index 6ee6bb4d97f4eb98b694095c20f50d54fc383536..b339fdee4c84c56a5de85c58981896c0b9a61922 100644 --- a/tests/qtest/boot-sector.h +++ b/tests/qtest/boot-sector.h @@ -14,7 +14,7 @@ #ifndef TEST_BOOT_SECTOR_H #define TEST_BOOT_SECTOR_H -#include "libqtest.h" +#include "libqos/libqtest.h" /* Create boot disk file. fname must be a suitable string for mkstemp() */ int boot_sector_init(char *fname); diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c index 85a361428697706545614f588dab095af080b87a..b6b1c23cd01c35893f8d002d9feb6f70de77788e 100644 --- a/tests/qtest/boot-serial-test.c +++ b/tests/qtest/boot-serial-test.c @@ -14,9 +14,18 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "libqos/libqos-spapr.h" +static const uint8_t bios_avr[] = { + 0x88, 0xe0, /* ldi r24, 0x08 */ + 0x80, 0x93, 0xc1, 0x00, /* sts 0x00C1, r24 ; Enable tx */ + 0x86, 0xe0, /* ldi r24, 0x06 */ + 0x80, 0x93, 0xc2, 0x00, /* sts 0x00C2, r24 ; Set the data bits to 8 */ + 0x84, 0xe5, /* ldi r24, 0x54 */ + 0x80, 0x93, 0xc6, 0x00, /* sts 0x00C6, r24 ; Output 'T' */ +}; + static const uint8_t kernel_mcf5208[] = { 0x41, 0xf9, 0xfc, 0x06, 0x00, 0x00, /* lea 0xfc060000,%a0 */ 0x10, 0x3c, 0x00, 0x54, /* move.b #'T',%d0 */ @@ -104,6 +113,8 @@ typedef struct testdef { static testdef_t tests[] = { { "alpha", "clipper", "", "PCI:" }, + { "avr", "arduino-duemilanove", "", "T", sizeof(bios_avr), NULL, bios_avr }, + { "avr", "arduino-mega-2560-v3", "", "T", sizeof(bios_avr), NULL, bios_avr}, { "ppc", "ppce500", "", "U-Boot" }, { "ppc", "40p", "-vga none -boot d", "Trying cd:," }, { "ppc", "g3beige", "", "PowerPC,750" }, diff --git a/tests/qtest/cdrom-test.c b/tests/qtest/cdrom-test.c index 833a0508a14258aa85ba3dd5095a4ea09d34d1b0..5af944a5fb70ce18a6cb76055b853aadc2cf31b9 100644 --- a/tests/qtest/cdrom-test.c +++ b/tests/qtest/cdrom-test.c @@ -11,7 +11,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "boot-sector.h" #include "qapi/qmp/qdict.h" @@ -163,6 +163,18 @@ static void add_s390x_tests(void) qtest_add_data_func("cdrom/boot/virtio-scsi", "-device virtio-scsi -device scsi-cd,drive=cdr " "-blockdev file,node-name=cdr,filename=", test_cdboot); + qtest_add_data_func("cdrom/boot/with-bootindex", + "-device virtio-serial -device virtio-scsi " + "-device virtio-blk,drive=d1 " + "-drive driver=null-co,read-zeroes=on,if=none,id=d1 " + "-device virtio-blk,drive=d2,bootindex=1 " + "-drive if=none,id=d2,media=cdrom,file=", test_cdboot); + qtest_add_data_func("cdrom/boot/without-bootindex", + "-device virtio-scsi -device virtio-serial " + "-device x-terminal3270 -device virtio-blk,drive=d1 " + "-drive driver=null-co,read-zeroes=on,if=none,id=d1 " + "-device virtio-blk,drive=d2 " + "-drive if=none,id=d2,media=cdrom,file=", test_cdboot); } int main(int argc, char **argv) @@ -205,7 +217,7 @@ int main(int argc, char **argv) add_cdrom_param_tests(sparc64machines); } else if (!strncmp(arch, "mips64", 6)) { const char *mips64machines[] = { - "magnum", "malta", "mips", "pica61", NULL + "magnum", "malta", "pica61", NULL }; add_cdrom_param_tests(mips64machines); } else if (g_str_equal(arch, "arm") || g_str_equal(arch, "aarch64")) { diff --git a/tests/qtest/cpu-plug-test.c b/tests/qtest/cpu-plug-test.c index e8ffbbce4b4790cb24339b0904b62f0ad1d2e648..a1c689414be5d03a76624afe80b799f8bf4d572a 100644 --- a/tests/qtest/cpu-plug-test.c +++ b/tests/qtest/cpu-plug-test.c @@ -25,54 +25,6 @@ struct PlugTestData { }; typedef struct PlugTestData PlugTestData; -static void test_plug_with_cpu_add(gconstpointer data) -{ - const PlugTestData *s = data; - char *args; - QDict *response; - unsigned int i; - - args = g_strdup_printf("-machine %s -cpu %s " - "-smp 1,sockets=%u,cores=%u,threads=%u,maxcpus=%u", - s->machine, s->cpu_model, - s->sockets, s->cores, s->threads, s->maxcpus); - qtest_start(args); - - for (i = 1; i < s->maxcpus; i++) { - response = qmp("{ 'execute': 'cpu-add'," - " 'arguments': { 'id': %d } }", i); - g_assert(response); - g_assert(!qdict_haskey(response, "error")); - qobject_unref(response); - } - - qtest_end(); - g_free(args); -} - -static void test_plug_without_cpu_add(gconstpointer data) -{ - const PlugTestData *s = data; - char *args; - QDict *response; - - args = g_strdup_printf("-machine %s -cpu %s " - "-smp 1,sockets=%u,cores=%u,threads=%u,maxcpus=%u", - s->machine, s->cpu_model, - s->sockets, s->cores, s->threads, s->maxcpus); - qtest_start(args); - - response = qmp("{ 'execute': 'cpu-add'," - " 'arguments': { 'id': %d } }", - s->sockets * s->cores * s->threads); - g_assert(response); - g_assert(qdict_haskey(response, "error")); - qobject_unref(response); - - qtest_end(); - g_free(args); -} - static void test_plug_with_device_add(gconstpointer data) { const PlugTestData *td = data; @@ -144,36 +96,13 @@ static void add_pc_test_case(const char *mname) data->cores = 3; data->threads = 2; data->maxcpus = data->sockets * data->cores * data->threads; - if (g_str_has_suffix(mname, "-1.4") || - (strcmp(mname, "pc-1.3") == 0) || - (strcmp(mname, "pc-1.2") == 0) || - (strcmp(mname, "pc-1.1") == 0) || - (strcmp(mname, "pc-1.0") == 0)) { - path = g_strdup_printf("cpu-plug/%s/init/%ux%ux%u&maxcpus=%u", - mname, data->sockets, data->cores, - data->threads, data->maxcpus); - qtest_add_data_func_full(path, data, test_plug_without_cpu_add, - test_data_free); - g_free(path); - } else { - PlugTestData *data2 = g_memdup(data, sizeof(PlugTestData)); - - data2->machine = g_strdup(data->machine); - data2->device_model = g_strdup(data->device_model); - path = g_strdup_printf("cpu-plug/%s/cpu-add/%ux%ux%u&maxcpus=%u", - mname, data->sockets, data->cores, - data->threads, data->maxcpus); - qtest_add_data_func_full(path, data, test_plug_with_cpu_add, - test_data_free); - g_free(path); - path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u", - mname, data2->sockets, data2->cores, - data2->threads, data2->maxcpus); - qtest_add_data_func_full(path, data2, test_plug_with_device_add, - test_data_free); - g_free(path); - } + path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u", + mname, data->sockets, data->cores, + data->threads, data->maxcpus); + qtest_add_data_func_full(path, data, test_plug_with_device_add, + test_data_free); + g_free(path); } static void add_pseries_test_case(const char *mname) @@ -205,7 +134,7 @@ static void add_pseries_test_case(const char *mname) static void add_s390x_test_case(const char *mname) { char *path; - PlugTestData *data, *data2; + PlugTestData *data; if (!g_str_has_prefix(mname, "s390-ccw-virtio-")) { return; @@ -220,21 +149,10 @@ static void add_s390x_test_case(const char *mname) data->threads = 1; data->maxcpus = data->sockets * data->cores * data->threads; - data2 = g_memdup(data, sizeof(PlugTestData)); - data2->machine = g_strdup(data->machine); - data2->device_model = g_strdup(data->device_model); - - path = g_strdup_printf("cpu-plug/%s/cpu-add/%ux%ux%u&maxcpus=%u", + path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u", mname, data->sockets, data->cores, data->threads, data->maxcpus); - qtest_add_data_func_full(path, data, test_plug_with_cpu_add, - test_data_free); - g_free(path); - - path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u", - mname, data2->sockets, data2->cores, - data2->threads, data2->maxcpus); - qtest_add_data_func_full(path, data2, test_plug_with_device_add, + qtest_add_data_func_full(path, data, test_plug_with_device_add, test_data_free); g_free(path); } diff --git a/tests/qtest/dbus-vmstate-test.c b/tests/qtest/dbus-vmstate-test.c index 2e5e47dec28f620bdaa4566e21ddeac16a002498..aca9b98b7a356608092da3fbb0f109ab4d758642 100644 --- a/tests/qtest/dbus-vmstate-test.c +++ b/tests/qtest/dbus-vmstate-test.c @@ -1,7 +1,7 @@ #include "qemu/osdep.h" #include #include -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu-common.h" #include "dbus-vmstate1.h" #include "migration-helpers.h" diff --git a/tests/qtest/device-introspect-test.c b/tests/qtest/device-introspect-test.c index f2c1576caeba474398a35c2bb7b9e1ee4d338b87..bbec166dbc2f1d9344c2f7b1c92cb24033b7d495 100644 --- a/tests/qtest/device-introspect-test.c +++ b/tests/qtest/device-introspect-test.c @@ -22,7 +22,7 @@ #include "qapi/qmp/qstring.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qlist.h" -#include "libqtest.h" +#include "libqos/libqtest.h" const char common_args[] = "-nodefaults -machine none"; @@ -104,37 +104,23 @@ static QList *device_type_list(QTestState *qts, bool abstract) static void test_one_device(QTestState *qts, const char *type) { QDict *resp; - char *help; - char *qom_tree_start, *qom_tree_end; - char *qtree_start, *qtree_end; + char *help, *escaped; + GRegex *comma; g_test_message("Testing device '%s'", type); - qom_tree_start = qtest_hmp(qts, "info qom-tree"); - qtree_start = qtest_hmp(qts, "info qtree"); - resp = qtest_qmp(qts, "{'execute': 'device-list-properties'," " 'arguments': {'typename': %s}}", type); qobject_unref(resp); - help = qtest_hmp(qts, "device_add \"%s,help\"", type); - g_free(help); - - /* - * Some devices leave dangling pointers in QOM behind. - * "info qom-tree" or "info qtree" have a good chance at crashing then. - * Also make sure that the tree did not change. - */ - qom_tree_end = qtest_hmp(qts, "info qom-tree"); - g_assert_cmpstr(qom_tree_start, ==, qom_tree_end); - g_free(qom_tree_start); - g_free(qom_tree_end); + comma = g_regex_new(",", 0, 0, NULL); + escaped = g_regex_replace_literal(comma, type, -1, 0, ",,", 0, NULL); + g_regex_unref(comma); - qtree_end = qtest_hmp(qts, "info qtree"); - g_assert_cmpstr(qtree_start, ==, qtree_end); - g_free(qtree_start); - g_free(qtree_end); + help = qtest_hmp(qts, "device_add \"%s,help\"", escaped); + g_free(help); + g_free(escaped); } static void test_device_intro_list(void) @@ -213,16 +199,38 @@ static void test_qom_list_fields(void) static void test_device_intro_none(void) { QTestState *qts = qtest_init(common_args); + g_autofree char *qom_tree_start = qtest_hmp(qts, "info qom-tree"); + g_autofree char *qom_tree_end = NULL; + g_autofree char *qtree_start = qtest_hmp(qts, "info qtree"); + g_autofree char *qtree_end = NULL; test_one_device(qts, "nonexistent"); + + /* Make sure that really nothing changed in the trees */ + qom_tree_end = qtest_hmp(qts, "info qom-tree"); + g_assert_cmpstr(qom_tree_start, ==, qom_tree_end); + qtree_end = qtest_hmp(qts, "info qtree"); + g_assert_cmpstr(qtree_start, ==, qtree_end); + qtest_quit(qts); } static void test_device_intro_abstract(void) { QTestState *qts = qtest_init(common_args); + g_autofree char *qom_tree_start = qtest_hmp(qts, "info qom-tree"); + g_autofree char *qom_tree_end = NULL; + g_autofree char *qtree_start = qtest_hmp(qts, "info qtree"); + g_autofree char *qtree_end = NULL; test_one_device(qts, "device"); + + /* Make sure that really nothing changed in the trees */ + qom_tree_end = qtest_hmp(qts, "info qom-tree"); + g_assert_cmpstr(qom_tree_start, ==, qom_tree_end); + qtree_end = qtest_hmp(qts, "info qtree"); + g_assert_cmpstr(qtree_start, ==, qtree_end); + qtest_quit(qts); } @@ -231,9 +239,12 @@ static void test_device_intro_concrete(const void *args) QList *types; QListEntry *entry; const char *type; - QTestState *qts; + QTestState *qts = qtest_init(args); + g_autofree char *qom_tree_start = qtest_hmp(qts, "info qom-tree"); + g_autofree char *qom_tree_end = NULL; + g_autofree char *qtree_start = qtest_hmp(qts, "info qtree"); + g_autofree char *qtree_end = NULL; - qts = qtest_init(args); types = device_type_list(qts, false); QLIST_FOREACH_ENTRY(types, entry) { @@ -243,6 +254,17 @@ static void test_device_intro_concrete(const void *args) test_one_device(qts, type); } + /* + * Some devices leave dangling pointers in QOM behind. + * "info qom-tree" or "info qtree" have a good chance at crashing then. + * Also make sure that the tree did not change. + */ + qom_tree_end = qtest_hmp(qts, "info qom-tree"); + g_assert_cmpstr(qom_tree_start, ==, qom_tree_end); + + qtree_end = qtest_hmp(qts, "info qtree"); + g_assert_cmpstr(qtree_start, ==, qtree_end); + qobject_unref(types); qtest_quit(qts); g_free((void *)args); @@ -287,11 +309,6 @@ static void add_machine_test_case(const char *mname) { char *path, *args; - /* Ignore blacklisted machines */ - if (!memcmp("xenfv", mname, 5) || g_str_equal("xenpv", mname)) { - return; - } - path = g_strdup_printf("device/introspect/concrete/defaults/%s", mname); args = g_strdup_printf("-M %s", mname); qtest_add_data_func(path, args, test_device_intro_concrete); diff --git a/tests/qtest/device-plug-test.c b/tests/qtest/device-plug-test.c index 318e422d518c012c2b303d0ec0c19268b7402e42..559d47727af367a13b1b861736f4317a370ef785 100644 --- a/tests/qtest/device-plug-test.c +++ b/tests/qtest/device-plug-test.c @@ -11,30 +11,21 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qstring.h" -static void device_del_start(QTestState *qtest, const char *id) +static void device_del(QTestState *qtest, const char *id) { - qtest_qmp_send(qtest, - "{'execute': 'device_del', 'arguments': { 'id': %s } }", id); -} + QDict *resp; -static void device_del_finish(QTestState *qtest) -{ - QDict *resp = qtest_qmp_receive(qtest); + resp = qtest_qmp(qtest, + "{'execute': 'device_del', 'arguments': { 'id': %s } }", id); g_assert(qdict_haskey(resp, "return")); qobject_unref(resp); } -static void device_del_request(QTestState *qtest, const char *id) -{ - device_del_start(qtest, id); - device_del_finish(qtest); -} - static void system_reset(QTestState *qtest) { QDict *resp; @@ -79,7 +70,7 @@ static void test_pci_unplug_request(void) * be processed. However during system reset, the removal will be * handled, removing the device. */ - device_del_request(qtest, "dev0"); + device_del(qtest, "dev0"); system_reset(qtest); wait_device_deleted_event(qtest, "dev0"); @@ -90,13 +81,8 @@ static void test_ccw_unplug(void) { QTestState *qtest = qtest_initf("-device virtio-balloon-ccw,id=dev0"); - /* - * The DEVICE_DELETED events will be sent before the command - * completes. - */ - device_del_start(qtest, "dev0"); + device_del(qtest, "dev0"); wait_device_deleted_event(qtest, "dev0"); - device_del_finish(qtest); qtest_quit(qtest); } @@ -109,7 +95,7 @@ static void test_spapr_cpu_unplug_request(void) "-device power9_v2.0-spapr-cpu-core,core-id=1,id=dev0"); /* similar to test_pci_unplug_request */ - device_del_request(qtest, "dev0"); + device_del(qtest, "dev0"); system_reset(qtest); wait_device_deleted_event(qtest, "dev0"); @@ -125,7 +111,7 @@ static void test_spapr_memory_unplug_request(void) "-device pc-dimm,id=dev0,memdev=mem0"); /* similar to test_pci_unplug_request */ - device_del_request(qtest, "dev0"); + device_del(qtest, "dev0"); system_reset(qtest); wait_device_deleted_event(qtest, "dev0"); @@ -139,7 +125,7 @@ static void test_spapr_phb_unplug_request(void) qtest = qtest_initf("-device spapr-pci-host-bridge,index=1,id=dev0"); /* similar to test_pci_unplug_request */ - device_del_request(qtest, "dev0"); + device_del(qtest, "dev0"); system_reset(qtest); wait_device_deleted_event(qtest, "dev0"); diff --git a/tests/qtest/drive_del-test.c b/tests/qtest/drive_del-test.c index 5f8839b2320f42d2659e2a58e15f9e9b19d6907f..8d08ee9995d0de3c86fbfcbb29a7d79102e3a287 100644 --- a/tests/qtest/drive_del-test.c +++ b/tests/qtest/drive_del-test.c @@ -11,40 +11,152 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "libqos/virtio.h" #include "qapi/qmp/qdict.h" +#include "qapi/qmp/qlist.h" -/* TODO actually test the results and get rid of this */ -#define qmp_discard_response(q, ...) qobject_unref(qtest_qmp(q, __VA_ARGS__)) +static bool look_for_drive0(QTestState *qts, const char *command, const char *key) +{ + QDict *response; + QList *ret; + QListEntry *entry; + bool found; + + response = qtest_qmp(qts, "{'execute': %s}", command); + g_assert(response && qdict_haskey(response, "return")); + ret = qdict_get_qlist(response, "return"); + + found = false; + QLIST_FOREACH_ENTRY(ret, entry) { + QDict *entry_dict = qobject_to(QDict, entry->value); + if (!strcmp(qdict_get_str(entry_dict, key), "drive0")) { + found = true; + break; + } + } + + qobject_unref(response); + return found; +} + +static bool has_drive(QTestState *qts) +{ + return look_for_drive0(qts, "query-block", "device"); +} + +static bool has_blockdev(QTestState *qts) +{ + return look_for_drive0(qts, "query-named-block-nodes", "node-name"); +} + +static void blockdev_add_with_media(QTestState *qts) +{ + QDict *response; + + response = qtest_qmp(qts, + "{ 'execute': 'blockdev-add'," + " 'arguments': {" + " 'driver': 'raw'," + " 'node-name': 'drive0'," + " 'file': {" + " 'driver': 'null-co'," + " 'read-zeroes': true" + " }" + " }" + "}"); + + g_assert(response); + g_assert(qdict_haskey(response, "return")); + qobject_unref(response); + g_assert(has_blockdev(qts)); +} static void drive_add(QTestState *qts) { char *resp = qtest_hmp(qts, "drive_add 0 if=none,id=drive0"); g_assert_cmpstr(resp, ==, "OK\r\n"); + g_assert(has_drive(qts)); + g_free(resp); +} + +static void drive_add_with_media(QTestState *qts) +{ + char *resp = qtest_hmp(qts, + "drive_add 0 if=none,id=drive0,file=null-co://," + "file.read-zeroes=on,format=raw"); + + g_assert_cmpstr(resp, ==, "OK\r\n"); + g_assert(has_drive(qts)); g_free(resp); } static void drive_del(QTestState *qts) { - char *resp = qtest_hmp(qts, "drive_del drive0"); + char *resp; + g_assert(has_drive(qts)); + resp = qtest_hmp(qts, "drive_del drive0"); g_assert_cmpstr(resp, ==, ""); + g_assert(!has_drive(qts)); g_free(resp); } -static void device_del(QTestState *qts) +/* + * qvirtio_get_dev_type: + * Returns: the preferred virtio bus/device type for the current architecture. + * TODO: delete this + */ +static const char *qvirtio_get_dev_type(void) +{ + const char *arch = qtest_get_arch(); + + if (g_str_equal(arch, "arm") || g_str_equal(arch, "aarch64")) { + return "device"; /* for virtio-mmio */ + } else if (g_str_equal(arch, "s390x")) { + return "ccw"; + } else { + return "pci"; + } +} + +static void device_add(QTestState *qts) { QDict *response; + char driver[32]; + snprintf(driver, sizeof(driver), "virtio-blk-%s", + qvirtio_get_dev_type()); - /* Complication: ignore DEVICE_DELETED event */ - qmp_discard_response(qts, "{'execute': 'device_del'," + response = qtest_qmp(qts, "{'execute': 'device_add'," + " 'arguments': {" + " 'driver': %s," + " 'drive': 'drive0'," + " 'id': 'dev0'" + "}}", driver); + g_assert(response); + g_assert(qdict_haskey(response, "return")); + qobject_unref(response); +} + +static void device_del(QTestState *qts, bool and_reset) +{ + QDict *response; + + response = qtest_qmp(qts, "{'execute': 'device_del'," " 'arguments': { 'id': 'dev0' } }"); - response = qtest_qmp_receive(qts); g_assert(response); g_assert(qdict_haskey(response, "return")); qobject_unref(response); + + if (and_reset) { + response = qtest_qmp(qts, "{'execute': 'system_reset' }"); + g_assert(response); + g_assert(qdict_haskey(response, "return")); + qobject_unref(response); + } + + qtest_qmp_eventwait(qts, "DEVICE_DELETED"); } static void test_drive_without_dev(void) @@ -65,24 +177,6 @@ static void test_drive_without_dev(void) qtest_quit(qts); } -/* - * qvirtio_get_dev_type: - * Returns: the preferred virtio bus/device type for the current architecture. - * TODO: delete this - */ -static const char *qvirtio_get_dev_type(void) -{ - const char *arch = qtest_get_arch(); - - if (g_str_equal(arch, "arm") || g_str_equal(arch, "aarch64")) { - return "device"; /* for virtio-mmio */ - } else if (g_str_equal(arch, "s390x")) { - return "ccw"; - } else { - return "pci"; - } -} - static void test_after_failed_device_add(void) { char driver[32]; @@ -103,7 +197,7 @@ static void test_after_failed_device_add(void) " 'drive': 'drive0'" "}}", driver); g_assert(response); - qmp_assert_error_class(response, "GenericError"); + qmp_expect_error_and_unref(response, "GenericError"); /* Delete the drive */ drive_del(qts); @@ -132,7 +226,93 @@ static void test_drive_del_device_del(void) * Doing it in this order takes notoriously tricky special paths */ drive_del(qts); - device_del(qts); + device_del(qts, false); + g_assert(!has_drive(qts)); + + qtest_quit(qts); +} + +static void test_cli_device_del(void) +{ + QTestState *qts; + + /* + * -drive/-device and device_del. Start with a drive used by a + * device that unplugs after reset. + */ + qts = qtest_initf("-drive if=none,id=drive0,file=null-co://," + "file.read-zeroes=on,format=raw" + " -device virtio-blk-%s,drive=drive0,id=dev0", + qvirtio_get_dev_type()); + + device_del(qts, true); + g_assert(!has_drive(qts)); + + qtest_quit(qts); +} + +static void test_empty_device_del(void) +{ + QTestState *qts; + + /* device_del with no drive plugged. */ + qts = qtest_initf("-device virtio-scsi-%s -device scsi-cd,id=dev0", + qvirtio_get_dev_type()); + + device_del(qts, false); + qtest_quit(qts); +} + +static void test_device_add_and_del(void) +{ + QTestState *qts; + + /* + * -drive/device_add and device_del. Start with a drive used by a + * device that unplugs after reset. + */ + qts = qtest_init("-drive if=none,id=drive0,file=null-co://," + "file.read-zeroes=on,format=raw"); + + device_add(qts); + device_del(qts, true); + g_assert(!has_drive(qts)); + + qtest_quit(qts); +} + +static void test_drive_add_device_add_and_del(void) +{ + QTestState *qts; + + qts = qtest_init(""); + + /* + * drive_add/device_add and device_del. The drive is used by a + * device that unplugs after reset. + */ + drive_add_with_media(qts); + device_add(qts); + device_del(qts, true); + g_assert(!has_drive(qts)); + + qtest_quit(qts); +} + +static void test_blockdev_add_device_add_and_del(void) +{ + QTestState *qts; + + qts = qtest_init(""); + + /* + * blockdev_add/device_add and device_del. The it drive is used by a + * device that unplugs after reset, but it doesn't go away. + */ + blockdev_add_with_media(qts); + device_add(qts); + device_del(qts, true); + g_assert(has_blockdev(qts)); qtest_quit(qts); } @@ -146,8 +326,18 @@ int main(int argc, char **argv) if (qvirtio_get_dev_type() != NULL) { qtest_add_func("/drive_del/after_failed_device_add", test_after_failed_device_add); - qtest_add_func("/blockdev/drive_del_device_del", + qtest_add_func("/drive_del/drive_del_device_del", test_drive_del_device_del); + qtest_add_func("/device_del/drive/cli_device", + test_cli_device_del); + qtest_add_func("/device_del/drive/device_add", + test_device_add_and_del); + qtest_add_func("/device_del/drive/drive_add_device_add", + test_drive_add_device_add_and_del); + qtest_add_func("/device_del/empty", + test_empty_device_del); + qtest_add_func("/device_del/blockdev", + test_blockdev_add_device_add_and_del); } return g_test_run(); diff --git a/tests/qtest/ds1338-test.c b/tests/qtest/ds1338-test.c index f6ade9a050fb50a44a00b8338308234acd765128..c5d46bcc643d40a1d05037587e5d0bfbd65b430b 100644 --- a/tests/qtest/ds1338-test.c +++ b/tests/qtest/ds1338-test.c @@ -18,7 +18,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "libqos/i2c.h" #define DS1338_ADDR 0x68 diff --git a/tests/qtest/e1000-test.c b/tests/qtest/e1000-test.c index c387984ef6d69dbf0361b83f19e96f00e5896775..ea286d1793046b0508ec7ed4714740ee947a84bd 100644 --- a/tests/qtest/e1000-test.c +++ b/tests/qtest/e1000-test.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/module.h" #include "libqos/qgraph.h" #include "libqos/pci.h" diff --git a/tests/qtest/e1000e-test.c b/tests/qtest/e1000e-test.c index 1a232a663ab0d4bd0ff2d5f052f9383fb4f19ddc..fc226fdfeb568711c5e8070e00e410cd27523a95 100644 --- a/tests/qtest/e1000e-test.c +++ b/tests/qtest/e1000e-test.c @@ -12,7 +12,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/qtest/eepro100-test.c b/tests/qtest/eepro100-test.c index 8dbffff0b81b1632a876ad1dcfa7d4623dfa4f4a..d72ad099f1eb7b98988c19a7117a5adb893693ef 100644 --- a/tests/qtest/eepro100-test.c +++ b/tests/qtest/eepro100-test.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/module.h" #include "libqos/qgraph.h" #include "libqos/pci.h" diff --git a/tests/qtest/endianness-test.c b/tests/qtest/endianness-test.c index cc088ac01a3fa8add50375a2d7966ced06845f01..09ecb531f118690859bb772ef3e4629752adbf01 100644 --- a/tests/qtest/endianness-test.c +++ b/tests/qtest/endianness-test.c @@ -13,7 +13,7 @@ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/bswap.h" typedef struct TestCase TestCase; @@ -27,11 +27,9 @@ struct TestCase { static const TestCase test_cases[] = { { "i386", "pc", -1 }, - { "mips", "mips", 0x14000000, .bswap = true }, { "mips", "malta", 0x10000000, .bswap = true }, { "mips64", "magnum", 0x90000000, .bswap = true }, { "mips64", "pica61", 0x90000000, .bswap = true }, - { "mips64", "mips", 0x14000000, .bswap = true }, { "mips64", "malta", 0x10000000, .bswap = true }, { "mips64el", "fuloong2e", 0x1fd00000 }, { "ppc", "g3beige", 0xfe000000, .bswap = true, .superio = "i82378" }, diff --git a/tests/qtest/es1370-test.c b/tests/qtest/es1370-test.c index adccdac1be57ef6df00cfa18d13df28e7f399db4..2fd7fd2d3d3039e64c2e22596d9018b40f488da9 100644 --- a/tests/qtest/es1370-test.c +++ b/tests/qtest/es1370-test.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/module.h" #include "libqos/qgraph.h" #include "libqos/pci.h" diff --git a/tests/qtest/fuzz-test.c b/tests/qtest/fuzz-test.c new file mode 100644 index 0000000000000000000000000000000000000000..9cb4c42bdea5cefa23473ed41b10977a94988e36 --- /dev/null +++ b/tests/qtest/fuzz-test.c @@ -0,0 +1,64 @@ +/* + * QTest testcase for fuzz case + * + * Copyright (c) 2020 Li Qiang + * + * 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 "libqos/libqtest.h" + +/* + * This used to trigger the assert in scsi_dma_complete + * https://bugs.launchpad.net/qemu/+bug/1878263 + */ +static void test_lp1878263_megasas_zero_iov_cnt(void) +{ + QTestState *s; + + s = qtest_init("-nographic -monitor none -serial none " + "-M q35 -device megasas -device scsi-cd,drive=null0 " + "-blockdev driver=null-co,read-zeroes=on,node-name=null0"); + qtest_outl(s, 0xcf8, 0x80001818); + qtest_outl(s, 0xcfc, 0xc101); + qtest_outl(s, 0xcf8, 0x8000181c); + qtest_outl(s, 0xcf8, 0x80001804); + qtest_outw(s, 0xcfc, 0x7); + qtest_outl(s, 0xcf8, 0x8000186a); + qtest_writeb(s, 0x14, 0xfe); + qtest_writeb(s, 0x0, 0x02); + qtest_outb(s, 0xc1c0, 0x17); + qtest_quit(s); +} + +static void test_lp1878642_pci_bus_get_irq_level_assert(void) +{ + QTestState *s; + + s = qtest_init("-M pc-q35-5.0 " + "-nographic -monitor none -serial none " + "-d guest_errors -trace pci*"); + + qtest_outl(s, 0xcf8, 0x8400f841); + qtest_outl(s, 0xcfc, 0xebed205d); + qtest_outl(s, 0x5d02, 0xebed205d); +} + +int main(int argc, char **argv) +{ + const char *arch = qtest_get_arch(); + + g_test_init(&argc, &argv, NULL); + + if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { + qtest_add_func("fuzz/test_lp1878263_megasas_zero_iov_cnt", + test_lp1878263_megasas_zero_iov_cnt); + qtest_add_func("fuzz/test_lp1878642_pci_bus_get_irq_level_assert", + test_lp1878642_pci_bus_get_irq_level_assert); + } + + return g_test_run(); +} diff --git a/tests/qtest/fuzz/Makefile.include b/tests/qtest/fuzz/Makefile.include deleted file mode 100644 index f259d866c97ce5937f8f17b046da56ac1ed06807..0000000000000000000000000000000000000000 --- a/tests/qtest/fuzz/Makefile.include +++ /dev/null @@ -1,18 +0,0 @@ -QEMU_PROG_FUZZ=qemu-fuzz-$(TARGET_NAME)$(EXESUF) - -fuzz-obj-y += tests/qtest/libqtest.o -fuzz-obj-y += $(libqos-obj-y) -fuzz-obj-y += tests/qtest/fuzz/fuzz.o # Fuzzer skeleton -fuzz-obj-y += tests/qtest/fuzz/fork_fuzz.o -fuzz-obj-y += tests/qtest/fuzz/qos_fuzz.o - -# Targets -fuzz-obj-$(CONFIG_PCI_I440FX) += tests/qtest/fuzz/i440fx_fuzz.o -fuzz-obj-$(CONFIG_VIRTIO_NET) += tests/qtest/fuzz/virtio_net_fuzz.o -fuzz-obj-$(CONFIG_SCSI) += tests/qtest/fuzz/virtio_scsi_fuzz.o - -FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest - -# Linker Script to force coverage-counters into known regions which we can mark -# shared -FUZZ_LDFLAGS += -Xlinker -T$(SRC_PATH)/tests/qtest/fuzz/fork_fuzz.ld diff --git a/tests/qtest/fuzz/fork_fuzz.c b/tests/qtest/fuzz/fork_fuzz.c index 2bd0851903d1d89395ce479a3e282d9da1286bf5..6ffb2a79372d6e9377e532dcdd2d01fcb8c63770 100644 --- a/tests/qtest/fuzz/fork_fuzz.c +++ b/tests/qtest/fuzz/fork_fuzz.c @@ -17,39 +17,25 @@ void counter_shm_init(void) { - char *shm_path = g_strdup_printf("/qemu-fuzz-cntrs.%d", getpid()); - int fd = shm_open(shm_path, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); - g_free(shm_path); - - if (fd == -1) { - perror("Error: "); - exit(1); - } - if (ftruncate(fd, &__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START) == -1) { - perror("Error: "); - exit(1); - } - /* Copy what's in the counter region to the shm.. */ - void *rptr = mmap(NULL , - &__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START, - PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - memcpy(rptr, + /* Copy what's in the counter region to a temporary buffer.. */ + void *copy = malloc(&__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START); + memcpy(copy, &__FUZZ_COUNTERS_START, &__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START); - munmap(rptr, &__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START); - - /* And map the shm over the counter region */ - rptr = mmap(&__FUZZ_COUNTERS_START, - &__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START, - PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0); - - close(fd); - - if (!rptr) { + /* Map a shared region over the counter region */ + if (mmap(&__FUZZ_COUNTERS_START, + &__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START, + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, + 0, 0) == MAP_FAILED) { perror("Error: "); exit(1); } + + /* Copy the original data back to the counter-region */ + memcpy(&__FUZZ_COUNTERS_START, copy, + &__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START); + free(copy); } diff --git a/tests/qtest/fuzz/fork_fuzz.ld b/tests/qtest/fuzz/fork_fuzz.ld index e086bba873d869fece6fd8a4225c4ee3559e3153..cfb88b7fdb51eb50f7d64b2cfc3d3f7a97197115 100644 --- a/tests/qtest/fuzz/fork_fuzz.ld +++ b/tests/qtest/fuzz/fork_fuzz.ld @@ -16,6 +16,11 @@ SECTIONS /* Lowest stack counter */ *(__sancov_lowest_stack); } +} +INSERT AFTER .data; + +SECTIONS +{ .data.fuzz_ordered : { /* @@ -28,7 +33,17 @@ SECTIONS /* Internal Libfuzzer TracePC object which contains the ValueProfileMap */ FuzzerTracePC*(.bss*); + /* + * In case the above line fails, explicitly specify the (mangled) name of + * the object we care about + */ + *(.bss._ZN6fuzzer3TPCE); } +} +INSERT AFTER .data.fuzz_start; + +SECTIONS +{ .data.fuzz_end : ALIGN(4K) { __FUZZ_COUNTERS_END = .; @@ -38,4 +53,4 @@ SECTIONS * Don't overwrite the SECTIONS in the default linker script. Instead insert the * above into the default script */ -INSERT AFTER .data; +INSERT AFTER .data.fuzz_ordered; diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c index f5c923852ee67b3499c2f668ae9fc017657359b0..7be7226bc07db74809ce16f954fe56546300363c 100644 --- a/tests/qtest/fuzz/fuzz.c +++ b/tests/qtest/fuzz/fuzz.c @@ -19,7 +19,8 @@ #include "sysemu/runstate.h" #include "sysemu/sysemu.h" #include "qemu/main-loop.h" -#include "tests/qtest/libqtest.h" +#include "qemu/rcu.h" +#include "tests/qtest/libqos/libqtest.h" #include "tests/qtest/libqos/qgraph.h" #include "fuzz.h" @@ -91,7 +92,12 @@ static void usage(char *path) printf(" * %s : %s\n", tmp->target->name, tmp->target->description); } - printf("Alternatively, add -target-FUZZ_TARGET to the executable name\n"); + printf("Alternatively, add -target-FUZZ_TARGET to the executable name\n\n" + "Set the environment variable FUZZ_SERIALIZE_QTEST=1 to serialize\n" + "QTest commands into an ASCII protocol. Useful for building crash\n" + "reproducers, but slows down execution.\n\n" + "Set the environment variable QTEST_LOG=1 to log all qtest commands" + "\n"); exit(0); } @@ -112,6 +118,19 @@ static FuzzTarget *fuzz_get_target(char* name) } +/* Sometimes called by libfuzzer to mutate two inputs into one */ +size_t LLVMFuzzerCustomCrossOver(const uint8_t *data1, size_t size1, + const uint8_t *data2, size_t size2, + uint8_t *out, size_t max_out_size, + unsigned int seed) +{ + if (fuzz_target->crossover) { + return fuzz_target->crossover(data1, size1, data2, size2, out, + max_out_size, seed); + } + return 0; +} + /* Executed for each fuzzing-input */ int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size) { @@ -137,6 +156,9 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp) { char *target_name; + const char *bindir; + char *datadir; + bool serialize = false; /* Initialize qgraph and modules */ qos_graph_init(); @@ -144,9 +166,26 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp) module_call_init(MODULE_INIT_QOM); module_call_init(MODULE_INIT_LIBQOS); + qemu_init_exec_dir(**argv); target_name = strstr(**argv, "-target-"); if (target_name) { /* The binary name specifies the target */ target_name += strlen("-target-"); + /* + * With oss-fuzz, the executable is kept in the root of a directory (we + * cannot assume the path). All data (including bios binaries) must be + * in the same dir, or a subdir. Thus, we cannot place the pc-bios so + * that it would be in exec_dir/../pc-bios. + * As a workaround, oss-fuzz allows us to use argv[0] to get the + * location of the executable. Using this we add exec_dir/pc-bios to + * the datadirs. + */ + bindir = qemu_get_exec_dir(); + datadir = g_build_filename(bindir, "pc-bios", NULL); + if (g_file_test(datadir, G_FILE_TEST_IS_DIR)) { + qemu_add_data_dir(datadir); + } else { + g_free(datadir); + } } else if (*argc > 1) { /* The target is specified as an argument */ target_name = (*argv)[1]; if (!strstr(target_name, "--fuzz-target=")) { @@ -157,6 +196,13 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp) usage(**argv); } + /* Should we always serialize qtest commands? */ + if (getenv("FUZZ_SERIALIZE_QTEST")) { + serialize = true; + } + + fuzz_qtest_set_serialize(serialize); + /* Identify the fuzz target */ fuzz_target = fuzz_get_target(target_name); if (!fuzz_target) { @@ -170,13 +216,27 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp) } /* Run QEMU's softmmu main with the fuzz-target dependent arguments */ - const char *init_cmdline = fuzz_target->get_init_cmdline(fuzz_target); + GString *cmd_line = fuzz_target->get_init_cmdline(fuzz_target); + g_string_append_printf(cmd_line, " %s -qtest /dev/null ", + getenv("QTEST_LOG") ? "" : "-qtest-log none"); /* Split the runcmd into an argv and argc */ wordexp_t result; - wordexp(init_cmdline, &result, 0); + wordexp(cmd_line->str, &result, 0); + g_string_free(cmd_line, true); qemu_init(result.we_wordc, result.we_wordv, NULL); + /* re-enable the rcu atfork, which was previously disabled in qemu_init */ + rcu_enable_atfork(); + + /* + * Disable QEMU's signal handlers, since we manually control the main_loop, + * and don't check for main_loop_should_exit + */ + signal(SIGINT, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGTERM, SIG_DFL); + return 0; } diff --git a/tests/qtest/fuzz/fuzz.h b/tests/qtest/fuzz/fuzz.h index 03901d414e128b5303191091279cf29fb9de19d4..08e9560a795c1c94633cd13e8cb71b19ade697c0 100644 --- a/tests/qtest/fuzz/fuzz.h +++ b/tests/qtest/fuzz/fuzz.h @@ -18,7 +18,7 @@ #include "qemu/units.h" #include "qapi/error.h" -#include "tests/qtest/libqtest.h" +#include "tests/qtest/libqos/libqtest.h" /** * A libfuzzer fuzzing target @@ -50,10 +50,10 @@ typedef struct FuzzTarget { /* - * returns the arg-list that is passed to qemu/softmmu init() - * Cannot be NULL + * Returns the arguments that are passed to qemu/softmmu init(). Freed by + * the caller. */ - const char* (*get_init_cmdline)(struct FuzzTarget *); + GString *(*get_init_cmdline)(struct FuzzTarget *); /* * will run once, prior to running qemu/softmmu init. @@ -77,17 +77,48 @@ typedef struct FuzzTarget { */ void(*fuzz)(QTestState *, const unsigned char *, size_t); + /* + * The fuzzer can specify a "Custom Crossover" function for combining two + * inputs from the corpus. This function is sometimes called by libfuzzer + * when mutating inputs. + * + * data1: location of first input + * size1: length of first input + * data1: location of second input + * size1: length of second input + * out: where to place the resulting, mutated input + * max_out_size: the maximum length of the input that can be placed in out + * seed: the seed that should be used to make mutations deterministic, when + * needed + * + * See libfuzzer's LLVMFuzzerCustomCrossOver API for more info. + * + * Can be NULL + */ + size_t(*crossover)(const uint8_t *data1, size_t size1, + const uint8_t *data2, size_t size2, + uint8_t *out, size_t max_out_size, + unsigned int seed); + + void *opaque; } FuzzTarget; void flush_events(QTestState *); void reboot(QTestState *); +/* Use the QTest ASCII protocol or call address_space API directly?*/ +void fuzz_qtest_set_serialize(bool option); + /* * makes a copy of *target and adds it to the target-list. * i.e. fine to set up target on the caller's stack */ void fuzz_add_target(const FuzzTarget *target); +size_t LLVMFuzzerCustomCrossOver(const uint8_t *data1, size_t size1, + const uint8_t *data2, size_t size2, + uint8_t *out, size_t max_out_size, + unsigned int seed); int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size); int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp); diff --git a/tests/qtest/fuzz/generic_fuzz.c b/tests/qtest/fuzz/generic_fuzz.c new file mode 100644 index 0000000000000000000000000000000000000000..262a963d2e6e4680496b9947ceb41ee9038f4465 --- /dev/null +++ b/tests/qtest/fuzz/generic_fuzz.c @@ -0,0 +1,956 @@ +/* + * Generic Virtual-Device Fuzzing Target + * + * Copyright Red Hat Inc., 2020 + * + * Authors: + * Alexander Bulekov + * + * 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 + +#include "hw/core/cpu.h" +#include "tests/qtest/libqos/libqtest.h" +#include "fuzz.h" +#include "fork_fuzz.h" +#include "exec/address-spaces.h" +#include "string.h" +#include "exec/memory.h" +#include "exec/ramblock.h" +#include "exec/address-spaces.h" +#include "hw/qdev-core.h" +#include "hw/pci/pci.h" +#include "hw/boards.h" +#include "generic_fuzz_configs.h" + +/* + * SEPARATOR is used to separate "operations" in the fuzz input + */ +#define SEPARATOR "FUZZ" + +enum cmds { + OP_IN, + OP_OUT, + OP_READ, + OP_WRITE, + OP_PCI_READ, + OP_PCI_WRITE, + OP_DISABLE_PCI, + OP_ADD_DMA_PATTERN, + OP_CLEAR_DMA_PATTERNS, + OP_CLOCK_STEP, +}; + +#define DEFAULT_TIMEOUT_US 100000 +#define USEC_IN_SEC 1000000000 + +#define MAX_DMA_FILL_SIZE 0x10000 + +#define PCI_HOST_BRIDGE_CFG 0xcf8 +#define PCI_HOST_BRIDGE_DATA 0xcfc + +typedef struct { + ram_addr_t addr; + ram_addr_t size; /* The number of bytes until the end of the I/O region */ +} address_range; + +static useconds_t timeout = DEFAULT_TIMEOUT_US; + +static bool qtest_log_enabled; + +/* + * A pattern used to populate a DMA region or perform a memwrite. This is + * useful for e.g. populating tables of unique addresses. + * Example {.index = 1; .stride = 2; .len = 3; .data = "\x00\x01\x02"} + * Renders as: 00 01 02 00 03 02 00 05 02 00 07 02 ... + */ +typedef struct { + uint8_t index; /* Index of a byte to increment by stride */ + uint8_t stride; /* Increment each index'th byte by this amount */ + size_t len; + const uint8_t *data; +} pattern; + +/* Avoid filling the same DMA region between MMIO/PIO commands ? */ +static bool avoid_double_fetches; + +static QTestState *qts_global; /* Need a global for the DMA callback */ + +/* + * List of memory regions that are children of QOM objects specified by the + * user for fuzzing. + */ +static GHashTable *fuzzable_memoryregions; +static GPtrArray *fuzzable_pci_devices; + +struct get_io_cb_info { + int index; + int found; + address_range result; +}; + +static int get_io_address_cb(Int128 start, Int128 size, + const MemoryRegion *mr, void *opaque) { + struct get_io_cb_info *info = opaque; + if (g_hash_table_lookup(fuzzable_memoryregions, mr)) { + if (info->index == 0) { + info->result.addr = (ram_addr_t)start; + info->result.size = (ram_addr_t)size; + info->found = 1; + return 1; + } + info->index--; + } + return 0; +} + +/* + * List of dma regions populated since the last fuzzing command. Used to ensure + * that we only write to each DMA address once, to avoid race conditions when + * building reproducers. + */ +static GArray *dma_regions; + +static GArray *dma_patterns; +static int dma_pattern_index; +static bool pci_disabled; + +/* + * Allocate a block of memory and populate it with a pattern. + */ +static void *pattern_alloc(pattern p, size_t len) +{ + int i; + uint8_t *buf = g_malloc(len); + uint8_t sum = 0; + + for (i = 0; i < len; ++i) { + buf[i] = p.data[i % p.len]; + if ((i % p.len) == p.index) { + buf[i] += sum; + sum += p.stride; + } + } + return buf; +} + +static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr) +{ + unsigned access_size_max = mr->ops->valid.max_access_size; + + /* + * Regions are assumed to support 1-4 byte accesses unless + * otherwise specified. + */ + if (access_size_max == 0) { + access_size_max = 4; + } + + /* Bound the maximum access by the alignment of the address. */ + if (!mr->ops->impl.unaligned) { + unsigned align_size_max = addr & -addr; + if (align_size_max != 0 && align_size_max < access_size_max) { + access_size_max = align_size_max; + } + } + + /* Don't attempt accesses larger than the maximum. */ + if (l > access_size_max) { + l = access_size_max; + } + l = pow2floor(l); + + return l; +} + +/* + * Call-back for functions that perform DMA reads from guest memory. Confirm + * that the region has not already been populated since the last loop in + * generic_fuzz(), avoiding potential race-conditions, which we don't have + * a good way for reproducing right now. + */ +void fuzz_dma_read_cb(size_t addr, size_t len, MemoryRegion *mr, bool is_write) +{ + /* Are we in the generic-fuzzer or are we using another fuzz-target? */ + if (!qts_global) { + return; + } + + /* + * Return immediately if: + * - We have no DMA patterns defined + * - The length of the DMA read request is zero + * - The DMA read is hitting an MR other than the machine's main RAM + * - The DMA request is not a read (what happens for a address_space_map + * with is_write=True? Can the device use the same pointer to do reads?) + * - The DMA request hits past the bounds of our RAM + */ + if (dma_patterns->len == 0 + || len == 0 + || mr != current_machine->ram + || is_write + || addr > current_machine->ram_size) { + return; + } + + /* + * If we overlap with any existing dma_regions, split the range and only + * populate the non-overlapping parts. + */ + address_range region; + bool double_fetch = false; + for (int i = 0; + i < dma_regions->len && (avoid_double_fetches || qtest_log_enabled); + ++i) { + region = g_array_index(dma_regions, address_range, i); + if (addr < region.addr + region.size && addr + len > region.addr) { + double_fetch = true; + if (addr < region.addr + && avoid_double_fetches) { + fuzz_dma_read_cb(addr, region.addr - addr, mr, is_write); + } + if (addr + len > region.addr + region.size + && avoid_double_fetches) { + fuzz_dma_read_cb(region.addr + region.size, + addr + len - (region.addr + region.size), mr, is_write); + } + return; + } + } + + /* Cap the length of the DMA access to something reasonable */ + len = MIN(len, MAX_DMA_FILL_SIZE); + + address_range ar = {addr, len}; + g_array_append_val(dma_regions, ar); + pattern p = g_array_index(dma_patterns, pattern, dma_pattern_index); + void *buf_base = pattern_alloc(p, ar.size); + void *buf = buf_base; + hwaddr l, addr1; + MemoryRegion *mr1; + while (len > 0) { + l = len; + mr1 = address_space_translate(first_cpu->as, + addr, &addr1, &l, true, + MEMTXATTRS_UNSPECIFIED); + + if (!(memory_region_is_ram(mr1) || + memory_region_is_romd(mr1))) { + l = memory_access_size(mr1, l, addr1); + } else { + /* ROM/RAM case */ + if (qtest_log_enabled) { + /* + * With QTEST_LOG, use a normal, slow QTest memwrite. Prefix the log + * that will be written by qtest.c with a DMA tag, so we can reorder + * the resulting QTest trace so the DMA fills precede the last PIO/MMIO + * command. + */ + fprintf(stderr, "[DMA] "); + if (double_fetch) { + fprintf(stderr, "[DOUBLE-FETCH] "); + } + fflush(stderr); + } + qtest_memwrite(qts_global, addr, buf, l); + } + len -= l; + buf += l; + addr += l; + + } + g_free(buf_base); + + /* Increment the index of the pattern for the next DMA access */ + dma_pattern_index = (dma_pattern_index + 1) % dma_patterns->len; +} + +/* + * Here we want to convert a fuzzer-provided [io-region-index, offset] to + * a physical address. To do this, we iterate over all of the matched + * MemoryRegions. Check whether each region exists within the particular io + * space. Return the absolute address of the offset within the index'th region + * that is a subregion of the io_space and the distance until the end of the + * memory region. + */ +static bool get_io_address(address_range *result, AddressSpace *as, + uint8_t index, + uint32_t offset) { + FlatView *view; + view = as->current_map; + g_assert(view); + struct get_io_cb_info cb_info = {}; + + cb_info.index = index; + + /* + * Loop around the FlatView until we match "index" number of + * fuzzable_memoryregions, or until we know that there are no matching + * memory_regions. + */ + do { + flatview_for_each_range(view, get_io_address_cb , &cb_info); + } while (cb_info.index != index && !cb_info.found); + + *result = cb_info.result; + if (result->size) { + offset = offset % result->size; + result->addr += offset; + result->size -= offset; + } + return cb_info.found; +} + +static bool get_pio_address(address_range *result, + uint8_t index, uint16_t offset) +{ + /* + * PIO BARs can be set past the maximum port address (0xFFFF). Thus, result + * can contain an addr that extends past the PIO space. When we pass this + * address to qtest_in/qtest_out, it is cast to a uint16_t, so we might end + * up fuzzing a completely different MemoryRegion/Device. Therefore, check + * that the address here is within the PIO space limits. + */ + bool found = get_io_address(result, &address_space_io, index, offset); + return result->addr <= 0xFFFF ? found : false; +} + +static bool get_mmio_address(address_range *result, + uint8_t index, uint32_t offset) +{ + return get_io_address(result, &address_space_memory, index, offset); +} + +static void op_in(QTestState *s, const unsigned char * data, size_t len) +{ + enum Sizes {Byte, Word, Long, end_sizes}; + struct { + uint8_t size; + uint8_t base; + uint16_t offset; + } a; + address_range abs; + + if (len < sizeof(a)) { + return; + } + memcpy(&a, data, sizeof(a)); + if (get_pio_address(&abs, a.base, a.offset) == 0) { + return; + } + + switch (a.size %= end_sizes) { + case Byte: + qtest_inb(s, abs.addr); + break; + case Word: + if (abs.size >= 2) { + qtest_inw(s, abs.addr); + } + break; + case Long: + if (abs.size >= 4) { + qtest_inl(s, abs.addr); + } + break; + } +} + +static void op_out(QTestState *s, const unsigned char * data, size_t len) +{ + enum Sizes {Byte, Word, Long, end_sizes}; + struct { + uint8_t size; + uint8_t base; + uint16_t offset; + uint32_t value; + } a; + address_range abs; + + if (len < sizeof(a)) { + return; + } + memcpy(&a, data, sizeof(a)); + + if (get_pio_address(&abs, a.base, a.offset) == 0) { + return; + } + + switch (a.size %= end_sizes) { + case Byte: + qtest_outb(s, abs.addr, a.value & 0xFF); + break; + case Word: + if (abs.size >= 2) { + qtest_outw(s, abs.addr, a.value & 0xFFFF); + } + break; + case Long: + if (abs.size >= 4) { + qtest_outl(s, abs.addr, a.value); + } + break; + } +} + +static void op_read(QTestState *s, const unsigned char * data, size_t len) +{ + enum Sizes {Byte, Word, Long, Quad, end_sizes}; + struct { + uint8_t size; + uint8_t base; + uint32_t offset; + } a; + address_range abs; + + if (len < sizeof(a)) { + return; + } + memcpy(&a, data, sizeof(a)); + + if (get_mmio_address(&abs, a.base, a.offset) == 0) { + return; + } + + switch (a.size %= end_sizes) { + case Byte: + qtest_readb(s, abs.addr); + break; + case Word: + if (abs.size >= 2) { + qtest_readw(s, abs.addr); + } + break; + case Long: + if (abs.size >= 4) { + qtest_readl(s, abs.addr); + } + break; + case Quad: + if (abs.size >= 8) { + qtest_readq(s, abs.addr); + } + break; + } +} + +static void op_write(QTestState *s, const unsigned char * data, size_t len) +{ + enum Sizes {Byte, Word, Long, Quad, end_sizes}; + struct { + uint8_t size; + uint8_t base; + uint32_t offset; + uint64_t value; + } a; + address_range abs; + + if (len < sizeof(a)) { + return; + } + memcpy(&a, data, sizeof(a)); + + if (get_mmio_address(&abs, a.base, a.offset) == 0) { + return; + } + + switch (a.size %= end_sizes) { + case Byte: + qtest_writeb(s, abs.addr, a.value & 0xFF); + break; + case Word: + if (abs.size >= 2) { + qtest_writew(s, abs.addr, a.value & 0xFFFF); + } + break; + case Long: + if (abs.size >= 4) { + qtest_writel(s, abs.addr, a.value & 0xFFFFFFFF); + } + break; + case Quad: + if (abs.size >= 8) { + qtest_writeq(s, abs.addr, a.value); + } + break; + } +} + +static void op_pci_read(QTestState *s, const unsigned char * data, size_t len) +{ + enum Sizes {Byte, Word, Long, end_sizes}; + struct { + uint8_t size; + uint8_t base; + uint8_t offset; + } a; + if (len < sizeof(a) || fuzzable_pci_devices->len == 0 || pci_disabled) { + return; + } + memcpy(&a, data, sizeof(a)); + PCIDevice *dev = g_ptr_array_index(fuzzable_pci_devices, + a.base % fuzzable_pci_devices->len); + int devfn = dev->devfn; + qtest_outl(s, PCI_HOST_BRIDGE_CFG, (1U << 31) | (devfn << 8) | a.offset); + switch (a.size %= end_sizes) { + case Byte: + qtest_inb(s, PCI_HOST_BRIDGE_DATA); + break; + case Word: + qtest_inw(s, PCI_HOST_BRIDGE_DATA); + break; + case Long: + qtest_inl(s, PCI_HOST_BRIDGE_DATA); + break; + } +} + +static void op_pci_write(QTestState *s, const unsigned char * data, size_t len) +{ + enum Sizes {Byte, Word, Long, end_sizes}; + struct { + uint8_t size; + uint8_t base; + uint8_t offset; + uint32_t value; + } a; + if (len < sizeof(a) || fuzzable_pci_devices->len == 0 || pci_disabled) { + return; + } + memcpy(&a, data, sizeof(a)); + PCIDevice *dev = g_ptr_array_index(fuzzable_pci_devices, + a.base % fuzzable_pci_devices->len); + int devfn = dev->devfn; + qtest_outl(s, PCI_HOST_BRIDGE_CFG, (1U << 31) | (devfn << 8) | a.offset); + switch (a.size %= end_sizes) { + case Byte: + qtest_outb(s, PCI_HOST_BRIDGE_DATA, a.value & 0xFF); + break; + case Word: + qtest_outw(s, PCI_HOST_BRIDGE_DATA, a.value & 0xFFFF); + break; + case Long: + qtest_outl(s, PCI_HOST_BRIDGE_DATA, a.value & 0xFFFFFFFF); + break; + } +} + +static void op_add_dma_pattern(QTestState *s, + const unsigned char *data, size_t len) +{ + struct { + /* + * index and stride can be used to increment the index-th byte of the + * pattern by the value stride, for each loop of the pattern. + */ + uint8_t index; + uint8_t stride; + } a; + + if (len < sizeof(a) + 1) { + return; + } + memcpy(&a, data, sizeof(a)); + pattern p = {a.index, a.stride, len - sizeof(a), data + sizeof(a)}; + p.index = a.index % p.len; + g_array_append_val(dma_patterns, p); + return; +} + +static void op_clear_dma_patterns(QTestState *s, + const unsigned char *data, size_t len) +{ + g_array_set_size(dma_patterns, 0); + dma_pattern_index = 0; +} + +static void op_clock_step(QTestState *s, const unsigned char *data, size_t len) +{ + qtest_clock_step_next(s); +} + +static void op_disable_pci(QTestState *s, const unsigned char *data, size_t len) +{ + pci_disabled = true; +} + +static void handle_timeout(int sig) +{ + if (qtest_log_enabled) { + fprintf(stderr, "[Timeout]\n"); + fflush(stderr); + } + _Exit(0); +} + +/* + * Here, we interpret random bytes from the fuzzer, as a sequence of commands. + * Some commands can be variable-width, so we use a separator, SEPARATOR, to + * specify the boundaries between commands. SEPARATOR is used to separate + * "operations" in the fuzz input. Why use a separator, instead of just using + * the operations' length to identify operation boundaries? + * 1. This is a simple way to support variable-length operations + * 2. This adds "stability" to the input. + * For example take the input "AbBcgDefg", where there is no separator and + * Opcodes are capitalized. + * Simply, by removing the first byte, we end up with a very different + * sequence: + * BbcGdefg... + * By adding a separator, we avoid this problem: + * Ab SEP Bcg SEP Defg -> B SEP Bcg SEP Defg + * Since B uses two additional bytes as operands, the first "B" will be + * ignored. The fuzzer actively tries to reduce inputs, so such unused + * bytes are likely to be pruned, eventually. + * + * SEPARATOR is trivial for the fuzzer to discover when using ASan. Optionally, + * SEPARATOR can be manually specified as a dictionary value (see libfuzzer's + * -dict), though this should not be necessary. + * + * As a result, the stream of bytes is converted into a sequence of commands. + * In a simplified example where SEPARATOR is 0xFF: + * 00 01 02 FF 03 04 05 06 FF 01 FF ... + * becomes this sequence of commands: + * 00 01 02 -> op00 (0102) -> in (0102, 2) + * 03 04 05 06 -> op03 (040506) -> write (040506, 3) + * 01 -> op01 (-,0) -> out (-,0) + * ... + * + * Note here that it is the job of the individual opcode functions to check + * that enough data was provided. I.e. in the last command out (,0), out needs + * to check that there is not enough data provided to select an address/value + * for the operation. + */ +static void generic_fuzz(QTestState *s, const unsigned char *Data, size_t Size) +{ + void (*ops[]) (QTestState *s, const unsigned char* , size_t) = { + [OP_IN] = op_in, + [OP_OUT] = op_out, + [OP_READ] = op_read, + [OP_WRITE] = op_write, + [OP_PCI_READ] = op_pci_read, + [OP_PCI_WRITE] = op_pci_write, + [OP_DISABLE_PCI] = op_disable_pci, + [OP_ADD_DMA_PATTERN] = op_add_dma_pattern, + [OP_CLEAR_DMA_PATTERNS] = op_clear_dma_patterns, + [OP_CLOCK_STEP] = op_clock_step, + }; + const unsigned char *cmd = Data; + const unsigned char *nextcmd; + size_t cmd_len; + uint8_t op; + + if (fork() == 0) { + /* + * Sometimes the fuzzer will find inputs that take quite a long time to + * process. Often times, these inputs do not result in new coverage. + * Even if these inputs might be interesting, they can slow down the + * fuzzer, overall. Set a timeout to avoid hurting performance, too much + */ + if (timeout) { + struct sigaction sact; + struct itimerval timer; + + sigemptyset(&sact.sa_mask); + sact.sa_flags = SA_NODEFER; + sact.sa_handler = handle_timeout; + sigaction(SIGALRM, &sact, NULL); + + memset(&timer, 0, sizeof(timer)); + timer.it_value.tv_sec = timeout / USEC_IN_SEC; + timer.it_value.tv_usec = timeout % USEC_IN_SEC; + setitimer(ITIMER_VIRTUAL, &timer, NULL); + } + + op_clear_dma_patterns(s, NULL, 0); + pci_disabled = false; + + while (cmd && Size) { + /* Get the length until the next command or end of input */ + nextcmd = memmem(cmd, Size, SEPARATOR, strlen(SEPARATOR)); + cmd_len = nextcmd ? nextcmd - cmd : Size; + + if (cmd_len > 0) { + /* Interpret the first byte of the command as an opcode */ + op = *cmd % (sizeof(ops) / sizeof((ops)[0])); + ops[op](s, cmd + 1, cmd_len - 1); + + /* Run the main loop */ + flush_events(s); + } + /* Advance to the next command */ + cmd = nextcmd ? nextcmd + sizeof(SEPARATOR) - 1 : nextcmd; + Size = Size - (cmd_len + sizeof(SEPARATOR) - 1); + g_array_set_size(dma_regions, 0); + } + _Exit(0); + } else { + flush_events(s); + wait(0); + } +} + +static void usage(void) +{ + printf("Please specify the following environment variables:\n"); + printf("QEMU_FUZZ_ARGS= the command line arguments passed to qemu\n"); + printf("QEMU_FUZZ_OBJECTS= " + "a space separated list of QOM type names for objects to fuzz\n"); + printf("Optionally: QEMU_AVOID_DOUBLE_FETCH= " + "Try to avoid racy DMA double fetch bugs? %d by default\n", + avoid_double_fetches); + printf("Optionally: QEMU_FUZZ_TIMEOUT= Specify a custom timeout (us). " + "0 to disable. %d by default\n", timeout); + exit(0); +} + +static int locate_fuzz_memory_regions(Object *child, void *opaque) +{ + const char *name; + MemoryRegion *mr; + if (object_dynamic_cast(child, TYPE_MEMORY_REGION)) { + mr = MEMORY_REGION(child); + if ((memory_region_is_ram(mr) || + memory_region_is_ram_device(mr) || + memory_region_is_rom(mr)) == false) { + name = object_get_canonical_path_component(child); + /* + * We don't want duplicate pointers to the same MemoryRegion, so + * try to remove copies of the pointer, before adding it. + */ + g_hash_table_insert(fuzzable_memoryregions, mr, (gpointer)true); + } + } + return 0; +} + +static int locate_fuzz_objects(Object *child, void *opaque) +{ + char *pattern = opaque; + if (g_pattern_match_simple(pattern, object_get_typename(child))) { + /* Find and save ptrs to any child MemoryRegions */ + object_child_foreach_recursive(child, locate_fuzz_memory_regions, NULL); + + /* + * We matched an object. If its a PCI device, store a pointer to it so + * we can map BARs and fuzz its config space. + */ + if (object_dynamic_cast(OBJECT(child), TYPE_PCI_DEVICE)) { + /* + * Don't want duplicate pointers to the same PCIDevice, so remove + * copies of the pointer, before adding it. + */ + g_ptr_array_remove_fast(fuzzable_pci_devices, PCI_DEVICE(child)); + g_ptr_array_add(fuzzable_pci_devices, PCI_DEVICE(child)); + } + } else if (object_dynamic_cast(OBJECT(child), TYPE_MEMORY_REGION)) { + if (g_pattern_match_simple(pattern, + object_get_canonical_path_component(child))) { + MemoryRegion *mr; + mr = MEMORY_REGION(child); + if ((memory_region_is_ram(mr) || + memory_region_is_ram_device(mr) || + memory_region_is_rom(mr)) == false) { + g_hash_table_insert(fuzzable_memoryregions, mr, (gpointer)true); + } + } + } + return 0; +} + +static void generic_pre_fuzz(QTestState *s) +{ + GHashTableIter iter; + MemoryRegion *mr; + char **result; + + if (!getenv("QEMU_FUZZ_OBJECTS")) { + usage(); + } + if (getenv("QTEST_LOG")) { + qtest_log_enabled = 1; + } + if (getenv("QEMU_AVOID_DOUBLE_FETCH")) { + avoid_double_fetches = 1; + } + if (getenv("QEMU_FUZZ_TIMEOUT")) { + timeout = g_ascii_strtoll(getenv("QEMU_FUZZ_TIMEOUT"), NULL, 0); + } + qts_global = s; + + dma_regions = g_array_new(false, false, sizeof(address_range)); + dma_patterns = g_array_new(false, false, sizeof(pattern)); + + fuzzable_memoryregions = g_hash_table_new(NULL, NULL); + fuzzable_pci_devices = g_ptr_array_new(); + + result = g_strsplit(getenv("QEMU_FUZZ_OBJECTS"), " ", -1); + for (int i = 0; result[i] != NULL; i++) { + printf("Matching objects by name %s\n", result[i]); + object_child_foreach_recursive(qdev_get_machine(), + locate_fuzz_objects, + result[i]); + } + g_strfreev(result); + printf("This process will try to fuzz the following MemoryRegions:\n"); + + g_hash_table_iter_init(&iter, fuzzable_memoryregions); + while (g_hash_table_iter_next(&iter, (gpointer)&mr, NULL)) { + printf(" * %s (size %lx)\n", + object_get_canonical_path_component(&(mr->parent_obj)), + (uint64_t)mr->size); + } + + if (!g_hash_table_size(fuzzable_memoryregions)) { + printf("No fuzzable memory regions found...\n"); + exit(1); + } + + counter_shm_init(); +} + +/* + * When libfuzzer gives us two inputs to combine, return a new input with the + * following structure: + * + * Input 1 (data1) + * SEPARATOR + * Clear out the DMA Patterns + * SEPARATOR + * Disable the pci_read/write instructions + * SEPARATOR + * Input 2 (data2) + * + * The idea is to collate the core behaviors of the two inputs. + * For example: + * Input 1: maps a device's BARs, sets up three DMA patterns, and triggers + * device functionality A + * Input 2: maps a device's BARs, sets up one DMA pattern, and triggers device + * functionality B + * + * This function attempts to produce an input that: + * Ouptut: maps a device's BARs, set up three DMA patterns, triggers + * functionality A device, replaces the DMA patterns with a single + * patten, and triggers device functionality B. + */ +static size_t generic_fuzz_crossover(const uint8_t *data1, size_t size1, const + uint8_t *data2, size_t size2, uint8_t *out, + size_t max_out_size, unsigned int seed) +{ + size_t copy_len = 0, size = 0; + + /* Check that we have enough space for data1 and at least part of data2 */ + if (max_out_size <= size1 + strlen(SEPARATOR) * 3 + 2) { + return 0; + } + + /* Copy_Len in the first input */ + copy_len = size1; + memcpy(out + size, data1, copy_len); + size += copy_len; + max_out_size -= copy_len; + + /* Append a separator */ + copy_len = strlen(SEPARATOR); + memcpy(out + size, SEPARATOR, copy_len); + size += copy_len; + max_out_size -= copy_len; + + /* Clear out the DMA Patterns */ + copy_len = 1; + if (copy_len) { + out[size] = OP_CLEAR_DMA_PATTERNS; + } + size += copy_len; + max_out_size -= copy_len; + + /* Append a separator */ + copy_len = strlen(SEPARATOR); + memcpy(out + size, SEPARATOR, copy_len); + size += copy_len; + max_out_size -= copy_len; + + /* Disable PCI ops. Assume data1 took care of setting up PCI */ + copy_len = 1; + if (copy_len) { + out[size] = OP_DISABLE_PCI; + } + size += copy_len; + max_out_size -= copy_len; + + /* Append a separator */ + copy_len = strlen(SEPARATOR); + memcpy(out + size, SEPARATOR, copy_len); + size += copy_len; + max_out_size -= copy_len; + + /* Copy_Len over the second input */ + copy_len = MIN(size2, max_out_size); + memcpy(out + size, data2, copy_len); + size += copy_len; + max_out_size -= copy_len; + + return size; +} + + +static GString *generic_fuzz_cmdline(FuzzTarget *t) +{ + GString *cmd_line = g_string_new(TARGET_NAME); + if (!getenv("QEMU_FUZZ_ARGS")) { + usage(); + } + g_string_append_printf(cmd_line, " -display none \ + -machine accel=qtest, \ + -m 512M %s ", getenv("QEMU_FUZZ_ARGS")); + return cmd_line; +} + +static GString *generic_fuzz_predefined_config_cmdline(FuzzTarget *t) +{ + const generic_fuzz_config *config; + g_assert(t->opaque); + + config = t->opaque; + setenv("QEMU_FUZZ_ARGS", config->args, 1); + setenv("QEMU_FUZZ_OBJECTS", config->objects, 1); + return generic_fuzz_cmdline(t); +} + +static void register_generic_fuzz_targets(void) +{ + fuzz_add_target(&(FuzzTarget){ + .name = "generic-fuzz", + .description = "Fuzz based on any qemu command-line args. ", + .get_init_cmdline = generic_fuzz_cmdline, + .pre_fuzz = generic_pre_fuzz, + .fuzz = generic_fuzz, + .crossover = generic_fuzz_crossover + }); + + GString *name; + const generic_fuzz_config *config; + + for (int i = 0; + i < sizeof(predefined_configs) / sizeof(generic_fuzz_config); + i++) { + config = predefined_configs + i; + name = g_string_new("generic-fuzz"); + g_string_append_printf(name, "-%s", config->name); + fuzz_add_target(&(FuzzTarget){ + .name = name->str, + .description = "Predefined generic-fuzz config.", + .get_init_cmdline = generic_fuzz_predefined_config_cmdline, + .pre_fuzz = generic_pre_fuzz, + .fuzz = generic_fuzz, + .crossover = generic_fuzz_crossover, + .opaque = (void *)config + }); + } +} + +fuzz_target_init(register_generic_fuzz_targets); diff --git a/tests/qtest/fuzz/generic_fuzz_configs.h b/tests/qtest/fuzz/generic_fuzz_configs.h new file mode 100644 index 0000000000000000000000000000000000000000..c4d925f9e6b297cf7bb000f1d69089f5d0095b72 --- /dev/null +++ b/tests/qtest/fuzz/generic_fuzz_configs.h @@ -0,0 +1,121 @@ +/* + * Generic Virtual-Device Fuzzing Target Configs + * + * Copyright Red Hat Inc., 2020 + * + * Authors: + * Alexander Bulekov + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef GENERIC_FUZZ_CONFIGS_H +#define GENERIC_FUZZ_CONFIGS_H + +#include "qemu/osdep.h" + +typedef struct generic_fuzz_config { + const char *name, *args, *objects; +} generic_fuzz_config; + +const generic_fuzz_config predefined_configs[] = { + { + .name = "virtio-net-pci-slirp", + .args = "-M q35 -nodefaults " + "-device virtio-net,netdev=net0 -netdev user,id=net0", + .objects = "virtio*", + },{ + .name = "virtio-blk", + .args = "-machine q35 -device virtio-blk,drive=disk0 " + "-drive file=null-co://,id=disk0,if=none,format=raw", + .objects = "virtio*", + },{ + .name = "virtio-scsi", + .args = "-machine q35 -device virtio-scsi,num_queues=8 " + "-device scsi-hd,drive=disk0 " + "-drive file=null-co://,id=disk0,if=none,format=raw", + .objects = "scsi* virtio*", + },{ + .name = "virtio-gpu", + .args = "-machine q35 -nodefaults -device virtio-gpu", + .objects = "virtio*", + },{ + .name = "virtio-vga", + .args = "-machine q35 -nodefaults -device virtio-vga", + .objects = "virtio*", + },{ + .name = "virtio-rng", + .args = "-machine q35 -nodefaults -device virtio-rng", + .objects = "virtio*", + },{ + .name = "virtio-balloon", + .args = "-machine q35 -nodefaults -device virtio-balloon", + .objects = "virtio*", + },{ + .name = "virtio-serial", + .args = "-machine q35 -nodefaults -device virtio-serial", + .objects = "virtio*", + },{ + .name = "virtio-mouse", + .args = "-machine q35 -nodefaults -device virtio-mouse", + .objects = "virtio*", + },{ + .name = "e1000", + .args = "-M q35 -nodefaults " + "-device e1000,netdev=net0 -netdev user,id=net0", + .objects = "e1000", + },{ + .name = "e1000e", + .args = "-M q35 -nodefaults " + "-device e1000e,netdev=net0 -netdev user,id=net0", + .objects = "e1000e", + },{ + .name = "cirrus-vga", + .args = "-machine q35 -nodefaults -device cirrus-vga", + .objects = "cirrus*", + },{ + .name = "bochs-display", + .args = "-machine q35 -nodefaults -device bochs-display", + .objects = "bochs*", + },{ + .name = "intel-hda", + .args = "-machine q35 -nodefaults -device intel-hda,id=hda0 " + "-device hda-output,bus=hda0.0 -device hda-micro,bus=hda0.0 " + "-device hda-duplex,bus=hda0.0", + .objects = "intel-hda", + },{ + .name = "ide-hd", + .args = "-machine q35 -nodefaults " + "-drive file=null-co://,if=none,format=raw,id=disk0 " + "-device ide-hd,drive=disk0", + .objects = "ahci*", + },{ + .name = "floppy", + .args = "-machine pc -nodefaults -device floppy,id=floppy0 " + "-drive id=disk0,file=null-co://,file.read-zeroes=on,if=none " + "-device floppy,drive=disk0,drive-type=288", + .objects = "fd* floppy*", + },{ + .name = "xhci", + .args = "-machine q35 -nodefaults " + "-drive file=null-co://,if=none,format=raw,id=disk0 " + "-device qemu-xhci,id=xhci -device usb-tablet,bus=xhci.0 " + "-device usb-bot -device usb-storage,drive=disk0 " + "-chardev null,id=cd0 -chardev null,id=cd1 " + "-device usb-braille,chardev=cd0 -device usb-ccid -device usb-ccid " + "-device usb-kbd -device usb-mouse -device usb-serial,chardev=cd1 " + "-device usb-tablet -device usb-wacom-tablet -device usb-audio", + .objects = "*usb* *uhci* *xhci*", + },{ + .name = "pc-i440fx", + .args = "-machine pc", + .objects = "*", + },{ + .name = "pc-q35", + .args = "-machine q35", + .objects = "*", + } +}; + +#endif diff --git a/tests/qtest/fuzz/i440fx_fuzz.c b/tests/qtest/fuzz/i440fx_fuzz.c index bcd6769b4c7af26b197d47dd1f6ca5f5210ff244..86796bff2bca2d4639319fc22fd1a68b2138b2a4 100644 --- a/tests/qtest/fuzz/i440fx_fuzz.c +++ b/tests/qtest/fuzz/i440fx_fuzz.c @@ -13,12 +13,12 @@ #include "qemu/osdep.h" #include "qemu/main-loop.h" -#include "tests/qtest/libqtest.h" +#include "tests/qtest/libqos/libqtest.h" #include "tests/qtest/libqos/pci.h" #include "tests/qtest/libqos/pci-pc.h" #include "fuzz.h" -#include "fuzz/qos_fuzz.h" -#include "fuzz/fork_fuzz.h" +#include "qos_fuzz.h" +#include "fork_fuzz.h" #define I440FX_PCI_HOST_BRIDGE_CFG 0xcf8 @@ -151,15 +151,16 @@ static void i440fx_fuzz_qos_fork(QTestState *s, i440fx_fuzz_qos(s, Data, Size); _Exit(0); } else { + flush_events(s); wait(NULL); } } static const char *i440fx_qtest_argv = TARGET_NAME " -machine accel=qtest" - "-m 0 -display none"; -static const char *i440fx_argv(FuzzTarget *t) + " -m 0 -display none"; +static GString *i440fx_argv(FuzzTarget *t) { - return i440fx_qtest_argv; + return g_string_new(i440fx_qtest_argv); } static void fork_init(void) diff --git a/tests/qtest/fuzz/meson.build b/tests/qtest/fuzz/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..8af6848cd578995e716c7f7752de81cf928e9b93 --- /dev/null +++ b/tests/qtest/fuzz/meson.build @@ -0,0 +1,34 @@ +specific_fuzz_ss.add(files('fuzz.c', 'fork_fuzz.c', 'qos_fuzz.c', + 'qtest_wrappers.c'), qos) + +# Targets +specific_fuzz_ss.add(when: 'CONFIG_I440FX', if_true: files('i440fx_fuzz.c')) +specific_fuzz_ss.add(when: 'CONFIG_VIRTIO_NET', if_true: files('virtio_net_fuzz.c')) +specific_fuzz_ss.add(when: 'CONFIG_VIRTIO_SCSI', if_true: files('virtio_scsi_fuzz.c')) +specific_fuzz_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio_blk_fuzz.c')) +specific_fuzz_ss.add(files('generic_fuzz.c')) + +fork_fuzz = declare_dependency( + link_args: config_host['FUZZ_EXE_LDFLAGS'].split() + + ['-Wl,-wrap,qtest_inb', + '-Wl,-wrap,qtest_inw', + '-Wl,-wrap,qtest_inl', + '-Wl,-wrap,qtest_outb', + '-Wl,-wrap,qtest_outw', + '-Wl,-wrap,qtest_outl', + '-Wl,-wrap,qtest_readb', + '-Wl,-wrap,qtest_readw', + '-Wl,-wrap,qtest_readl', + '-Wl,-wrap,qtest_readq', + '-Wl,-wrap,qtest_writeb', + '-Wl,-wrap,qtest_writew', + '-Wl,-wrap,qtest_writel', + '-Wl,-wrap,qtest_writeq', + '-Wl,-wrap,qtest_memread', + '-Wl,-wrap,qtest_bufread', + '-Wl,-wrap,qtest_memwrite', + '-Wl,-wrap,qtest_bufwrite', + '-Wl,-wrap,qtest_memset'] +) + +specific_fuzz_ss.add(fork_fuzz) diff --git a/tests/qtest/fuzz/qos_fuzz.c b/tests/qtest/fuzz/qos_fuzz.c index 87eadb0889d00481b732b283ba29808be611c944..cee1a2a60f62f70f0f2e1535471f5954998e3c19 100644 --- a/tests/qtest/fuzz/qos_fuzz.c +++ b/tests/qtest/fuzz/qos_fuzz.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,7 +25,7 @@ #include "sysemu/sysemu.h" #include "qemu/main-loop.h" -#include "tests/qtest/libqtest.h" +#include "tests/qtest/libqos/libqtest.h" #include "tests/qtest/libqos/malloc.h" #include "tests/qtest/libqos/qgraph.h" #include "tests/qtest/libqos/qgraph_internal.h" @@ -66,11 +66,11 @@ void *qos_allocate_objects(QTestState *qts, QGuestAllocator **p_alloc) return allocate_objects(qts, current_path + 1, p_alloc); } -static const char *qos_build_main_args(void) +static GString *qos_build_main_args(void) { char **path = fuzz_path_vec; QOSGraphNode *test_node; - GString *cmd_line = g_string_new(path[0]); + GString *cmd_line; void *test_arg; if (!path) { @@ -79,6 +79,7 @@ static const char *qos_build_main_args(void) } /* Before test */ + cmd_line = g_string_new(path[0]); current_path = path; test_node = qos_graph_get_node(path[(g_strv_length(path) - 1)]); test_arg = test_node->u.test.arg; @@ -88,7 +89,7 @@ static const char *qos_build_main_args(void) /* Prepend the arguments that we need */ g_string_prepend(cmd_line, TARGET_NAME " -display none -machine accel=qtest -m 64 "); - return cmd_line->str; + return cmd_line; } /* @@ -189,7 +190,7 @@ static void walk_path(QOSGraphNode *orig_path, int len) g_free(path_str); } -static const char *qos_get_cmdline(FuzzTarget *t) +static GString *qos_get_cmdline(FuzzTarget *t) { /* * Set a global variable that we use to identify the qos_path for our diff --git a/tests/qtest/fuzz/qtest_wrappers.c b/tests/qtest/fuzz/qtest_wrappers.c new file mode 100644 index 0000000000000000000000000000000000000000..0580f8df860fe7ae229cd4eb370db578d7e08eb6 --- /dev/null +++ b/tests/qtest/fuzz/qtest_wrappers.c @@ -0,0 +1,252 @@ +/* + * qtest function wrappers + * + * Copyright Red Hat Inc., 2019 + * + * Authors: + * Alexander Bulekov + * + * 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/core/cpu.h" +#include "exec/ioport.h" + +#include "fuzz.h" + +static bool serialize = true; + +#define WRAP(RET_TYPE, NAME_AND_ARGS)\ + RET_TYPE __wrap_##NAME_AND_ARGS;\ + RET_TYPE __real_##NAME_AND_ARGS; + +WRAP(uint8_t , qtest_inb(QTestState *s, uint16_t addr)) +WRAP(uint16_t , qtest_inw(QTestState *s, uint16_t addr)) +WRAP(uint32_t , qtest_inl(QTestState *s, uint16_t addr)) +WRAP(void , qtest_outb(QTestState *s, uint16_t addr, uint8_t value)) +WRAP(void , qtest_outw(QTestState *s, uint16_t addr, uint16_t value)) +WRAP(void , qtest_outl(QTestState *s, uint16_t addr, uint32_t value)) +WRAP(uint8_t , qtest_readb(QTestState *s, uint64_t addr)) +WRAP(uint16_t , qtest_readw(QTestState *s, uint64_t addr)) +WRAP(uint32_t , qtest_readl(QTestState *s, uint64_t addr)) +WRAP(uint64_t , qtest_readq(QTestState *s, uint64_t addr)) +WRAP(void , qtest_writeb(QTestState *s, uint64_t addr, uint8_t value)) +WRAP(void , qtest_writew(QTestState *s, uint64_t addr, uint16_t value)) +WRAP(void , qtest_writel(QTestState *s, uint64_t addr, uint32_t value)) +WRAP(void , qtest_writeq(QTestState *s, uint64_t addr, uint64_t value)) +WRAP(void , qtest_memread(QTestState *s, uint64_t addr, + void *data, size_t size)) +WRAP(void , qtest_bufread(QTestState *s, uint64_t addr, void *data, + size_t size)) +WRAP(void , qtest_memwrite(QTestState *s, uint64_t addr, const void *data, + size_t size)) +WRAP(void, qtest_bufwrite(QTestState *s, uint64_t addr, + const void *data, size_t size)) +WRAP(void, qtest_memset(QTestState *s, uint64_t addr, + uint8_t patt, size_t size)) + + +uint8_t __wrap_qtest_inb(QTestState *s, uint16_t addr) +{ + if (!serialize) { + return cpu_inb(addr); + } else { + return __real_qtest_inb(s, addr); + } +} + +uint16_t __wrap_qtest_inw(QTestState *s, uint16_t addr) +{ + if (!serialize) { + return cpu_inw(addr); + } else { + return __real_qtest_inw(s, addr); + } +} + +uint32_t __wrap_qtest_inl(QTestState *s, uint16_t addr) +{ + if (!serialize) { + return cpu_inl(addr); + } else { + return __real_qtest_inl(s, addr); + } +} + +void __wrap_qtest_outb(QTestState *s, uint16_t addr, uint8_t value) +{ + if (!serialize) { + cpu_outb(addr, value); + } else { + __real_qtest_outb(s, addr, value); + } +} + +void __wrap_qtest_outw(QTestState *s, uint16_t addr, uint16_t value) +{ + if (!serialize) { + cpu_outw(addr, value); + } else { + __real_qtest_outw(s, addr, value); + } +} + +void __wrap_qtest_outl(QTestState *s, uint16_t addr, uint32_t value) +{ + if (!serialize) { + cpu_outl(addr, value); + } else { + __real_qtest_outl(s, addr, value); + } +} + +uint8_t __wrap_qtest_readb(QTestState *s, uint64_t addr) +{ + uint8_t value; + if (!serialize) { + address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, + &value, 1); + return value; + } else { + return __real_qtest_readb(s, addr); + } +} + +uint16_t __wrap_qtest_readw(QTestState *s, uint64_t addr) +{ + uint16_t value; + if (!serialize) { + address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, + &value, 2); + return value; + } else { + return __real_qtest_readw(s, addr); + } +} + +uint32_t __wrap_qtest_readl(QTestState *s, uint64_t addr) +{ + uint32_t value; + if (!serialize) { + address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, + &value, 4); + return value; + } else { + return __real_qtest_readl(s, addr); + } +} + +uint64_t __wrap_qtest_readq(QTestState *s, uint64_t addr) +{ + uint64_t value; + if (!serialize) { + address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, + &value, 8); + return value; + } else { + return __real_qtest_readq(s, addr); + } +} + +void __wrap_qtest_writeb(QTestState *s, uint64_t addr, uint8_t value) +{ + if (!serialize) { + address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, + &value, 1); + } else { + __real_qtest_writeb(s, addr, value); + } +} + +void __wrap_qtest_writew(QTestState *s, uint64_t addr, uint16_t value) +{ + if (!serialize) { + address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, + &value, 2); + } else { + __real_qtest_writew(s, addr, value); + } +} + +void __wrap_qtest_writel(QTestState *s, uint64_t addr, uint32_t value) +{ + if (!serialize) { + address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, + &value, 4); + } else { + __real_qtest_writel(s, addr, value); + } +} + +void __wrap_qtest_writeq(QTestState *s, uint64_t addr, uint64_t value) +{ + if (!serialize) { + address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, + &value, 8); + } else { + __real_qtest_writeq(s, addr, value); + } +} + +void __wrap_qtest_memread(QTestState *s, uint64_t addr, void *data, size_t size) +{ + if (!serialize) { + address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data, + size); + } else { + __real_qtest_memread(s, addr, data, size); + } +} + +void __wrap_qtest_bufread(QTestState *s, uint64_t addr, void *data, size_t size) +{ + if (!serialize) { + address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data, + size); + } else { + __real_qtest_bufread(s, addr, data, size); + } +} + +void __wrap_qtest_memwrite(QTestState *s, uint64_t addr, const void *data, + size_t size) +{ + if (!serialize) { + address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, + data, size); + } else { + __real_qtest_memwrite(s, addr, data, size); + } +} + +void __wrap_qtest_bufwrite(QTestState *s, uint64_t addr, + const void *data, size_t size) +{ + if (!serialize) { + address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, + data, size); + } else { + __real_qtest_bufwrite(s, addr, data, size); + } +} +void __wrap_qtest_memset(QTestState *s, uint64_t addr, + uint8_t patt, size_t size) +{ + void *data; + if (!serialize) { + data = malloc(size); + memset(data, patt, size); + address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, + data, size); + } else { + __real_qtest_memset(s, addr, patt, size); + } +} + +void fuzz_qtest_set_serialize(bool option) +{ + serialize = option; +} diff --git a/tests/qtest/fuzz/virtio_blk_fuzz.c b/tests/qtest/fuzz/virtio_blk_fuzz.c new file mode 100644 index 0000000000000000000000000000000000000000..623a756fd472c03659ea6b2243e8c01beabbe2e9 --- /dev/null +++ b/tests/qtest/fuzz/virtio_blk_fuzz.c @@ -0,0 +1,234 @@ +/* + * virtio-blk Fuzzing Target + * + * Copyright Red Hat Inc., 2020 + * + * Based on virtio-scsi-fuzz target. + * + * 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 "tests/qtest/libqos/libqtest.h" +#include "tests/qtest/libqos/virtio-blk.h" +#include "tests/qtest/libqos/virtio.h" +#include "tests/qtest/libqos/virtio-pci.h" +#include "standard-headers/linux/virtio_ids.h" +#include "standard-headers/linux/virtio_pci.h" +#include "standard-headers/linux/virtio_blk.h" +#include "fuzz.h" +#include "fork_fuzz.h" +#include "qos_fuzz.h" + +#define TEST_IMAGE_SIZE (64 * 1024 * 1024) +#define PCI_SLOT 0x02 +#define PCI_FN 0x00 + +#define MAX_NUM_QUEUES 64 + +/* Based on tests/qtest/virtio-blk-test.c. */ +typedef struct { + int num_queues; + QVirtQueue *vq[MAX_NUM_QUEUES + 2]; +} QVirtioBlkQueues; + +static QVirtioBlkQueues *qvirtio_blk_init(QVirtioDevice *dev, uint64_t mask) +{ + QVirtioBlkQueues *vs; + uint64_t features; + + vs = g_new0(QVirtioBlkQueues, 1); + + features = qvirtio_get_features(dev); + if (!mask) { + mask = ~((1u << VIRTIO_RING_F_INDIRECT_DESC) | + (1u << VIRTIO_RING_F_EVENT_IDX) | + (1u << VIRTIO_BLK_F_SCSI)); + } + mask |= ~QVIRTIO_F_BAD_FEATURE; + features &= mask; + qvirtio_set_features(dev, features); + + vs->num_queues = 1; + vs->vq[0] = qvirtqueue_setup(dev, fuzz_qos_alloc, 0); + + qvirtio_set_driver_ok(dev); + + return vs; +} + +static void virtio_blk_fuzz(QTestState *s, QVirtioBlkQueues* queues, + const unsigned char *Data, size_t Size) +{ + /* + * Data is a sequence of random bytes. We split them up into "actions", + * followed by data: + * [vqa][dddddddd][vqa][dddd][vqa][dddddddddddd] ... + * The length of the data is specified by the preceding vqa.length + */ + typedef struct vq_action { + uint8_t queue; + uint8_t length; + uint8_t write; + uint8_t next; + uint8_t kick; + } vq_action; + + /* Keep track of the free head for each queue we interact with */ + bool vq_touched[MAX_NUM_QUEUES + 2] = {0}; + uint32_t free_head[MAX_NUM_QUEUES + 2]; + + QGuestAllocator *t_alloc = fuzz_qos_alloc; + + QVirtioBlk *blk = fuzz_qos_obj; + QVirtioDevice *dev = blk->vdev; + QVirtQueue *q; + vq_action vqa; + while (Size >= sizeof(vqa)) { + /* Copy the action, so we can normalize length, queue and flags */ + memcpy(&vqa, Data, sizeof(vqa)); + + Data += sizeof(vqa); + Size -= sizeof(vqa); + + vqa.queue = vqa.queue % queues->num_queues; + /* Cap length at the number of remaining bytes in data */ + vqa.length = vqa.length >= Size ? Size : vqa.length; + vqa.write = vqa.write & 1; + vqa.next = vqa.next & 1; + vqa.kick = vqa.kick & 1; + + q = queues->vq[vqa.queue]; + + /* Copy the data into ram, and place it on the virtqueue */ + uint64_t req_addr = guest_alloc(t_alloc, vqa.length); + qtest_memwrite(s, req_addr, Data, vqa.length); + if (vq_touched[vqa.queue] == 0) { + vq_touched[vqa.queue] = 1; + free_head[vqa.queue] = qvirtqueue_add(s, q, req_addr, vqa.length, + vqa.write, vqa.next); + } else { + qvirtqueue_add(s, q, req_addr, vqa.length, vqa.write , vqa.next); + } + + if (vqa.kick) { + qvirtqueue_kick(s, dev, q, free_head[vqa.queue]); + free_head[vqa.queue] = 0; + } + Data += vqa.length; + Size -= vqa.length; + } + /* In the end, kick each queue we interacted with */ + for (int i = 0; i < MAX_NUM_QUEUES + 2; i++) { + if (vq_touched[i]) { + qvirtqueue_kick(s, dev, queues->vq[i], free_head[i]); + } + } +} + +static void virtio_blk_fork_fuzz(QTestState *s, + const unsigned char *Data, size_t Size) +{ + QVirtioBlk *blk = fuzz_qos_obj; + static QVirtioBlkQueues *queues; + if (!queues) { + queues = qvirtio_blk_init(blk->vdev, 0); + } + if (fork() == 0) { + virtio_blk_fuzz(s, queues, Data, Size); + flush_events(s); + _Exit(0); + } else { + flush_events(s); + wait(NULL); + } +} + +static void virtio_blk_with_flag_fuzz(QTestState *s, + const unsigned char *Data, size_t Size) +{ + QVirtioBlk *blk = fuzz_qos_obj; + static QVirtioBlkQueues *queues; + + if (fork() == 0) { + if (Size >= sizeof(uint64_t)) { + queues = qvirtio_blk_init(blk->vdev, *(uint64_t *)Data); + virtio_blk_fuzz(s, queues, + Data + sizeof(uint64_t), Size - sizeof(uint64_t)); + flush_events(s); + } + _Exit(0); + } else { + flush_events(s); + wait(NULL); + } +} + +static void virtio_blk_pre_fuzz(QTestState *s) +{ + qos_init_path(s); + counter_shm_init(); +} + +static void drive_destroy(void *path) +{ + unlink(path); + g_free(path); +} + +static char *drive_create(void) +{ + int fd, ret; + char *t_path = g_strdup("/tmp/qtest.XXXXXX"); + + /* Create a temporary raw image */ + fd = mkstemp(t_path); + g_assert_cmpint(fd, >=, 0); + ret = ftruncate(fd, TEST_IMAGE_SIZE); + g_assert_cmpint(ret, ==, 0); + close(fd); + + g_test_queue_destroy(drive_destroy, t_path); + return t_path; +} + +static void *virtio_blk_test_setup(GString *cmd_line, void *arg) +{ + char *tmp_path = drive_create(); + + g_string_append_printf(cmd_line, + " -drive if=none,id=drive0,file=%s," + "format=raw,auto-read-only=off ", + tmp_path); + + return arg; +} + +static void register_virtio_blk_fuzz_targets(void) +{ + fuzz_add_qos_target(&(FuzzTarget){ + .name = "virtio-blk-fuzz", + .description = "Fuzz the virtio-blk virtual queues, forking " + "for each fuzz run", + .pre_vm_init = &counter_shm_init, + .pre_fuzz = &virtio_blk_pre_fuzz, + .fuzz = virtio_blk_fork_fuzz,}, + "virtio-blk", + &(QOSGraphTestOptions){.before = virtio_blk_test_setup} + ); + + fuzz_add_qos_target(&(FuzzTarget){ + .name = "virtio-blk-flags-fuzz", + .description = "Fuzz the virtio-blk virtual queues, forking " + "for each fuzz run (also fuzzes the virtio flags)", + .pre_vm_init = &counter_shm_init, + .pre_fuzz = &virtio_blk_pre_fuzz, + .fuzz = virtio_blk_with_flag_fuzz,}, + "virtio-blk", + &(QOSGraphTestOptions){.before = virtio_blk_test_setup} + ); +} + +fuzz_target_init(register_virtio_blk_fuzz_targets); diff --git a/tests/qtest/fuzz/virtio_net_fuzz.c b/tests/qtest/fuzz/virtio_net_fuzz.c index d08a47e278dd8969a30991ac709df086b45faf70..0e873ab8e25ffc63ba9fb3f765d569f037cd0c86 100644 --- a/tests/qtest/fuzz/virtio_net_fuzz.c +++ b/tests/qtest/fuzz/virtio_net_fuzz.c @@ -13,7 +13,7 @@ #include "qemu/osdep.h" #include "standard-headers/linux/virtio_config.h" -#include "tests/qtest/libqtest.h" +#include "tests/qtest/libqos/libqtest.h" #include "tests/qtest/libqos/virtio-net.h" #include "fuzz.h" #include "fork_fuzz.h" @@ -61,7 +61,8 @@ static void virtio_net_fuzz_multi(QTestState *s, * backend. Otherwise, always place the input on a virtqueue. */ if (vqa.rx && sockfds_initialized) { - write(sockfds[0], Data, vqa.length); + int ignored = write(sockfds[0], Data, vqa.length); + (void) ignored; } else { vqa.rx = 0; uint64_t req_addr = guest_alloc(t_alloc, vqa.length); @@ -122,6 +123,7 @@ static void virtio_net_fork_fuzz(QTestState *s, flush_events(s); _Exit(0); } else { + flush_events(s); wait(NULL); } } @@ -134,6 +136,7 @@ static void virtio_net_fork_fuzz_check_used(QTestState *s, flush_events(s); _Exit(0); } else { + flush_events(s); wait(NULL); } } diff --git a/tests/qtest/fuzz/virtio_scsi_fuzz.c b/tests/qtest/fuzz/virtio_scsi_fuzz.c index 3b95247f125c6b4702d47052abc74da04374be06..6ff6fabe4ad3cab78c3dddc602df2118361e59b5 100644 --- a/tests/qtest/fuzz/virtio_scsi_fuzz.c +++ b/tests/qtest/fuzz/virtio_scsi_fuzz.c @@ -12,10 +12,10 @@ #include "qemu/osdep.h" -#include "tests/qtest/libqtest.h" -#include "libqos/virtio-scsi.h" -#include "libqos/virtio.h" -#include "libqos/virtio-pci.h" +#include "tests/qtest/libqos/libqtest.h" +#include "tests/qtest/libqos/virtio-scsi.h" +#include "tests/qtest/libqos/virtio.h" +#include "tests/qtest/libqos/virtio-pci.h" #include "standard-headers/linux/virtio_ids.h" #include "standard-headers/linux/virtio_pci.h" #include "standard-headers/linux/virtio_scsi.h" @@ -145,6 +145,7 @@ static void virtio_scsi_fork_fuzz(QTestState *s, flush_events(s); _Exit(0); } else { + flush_events(s); wait(NULL); } } @@ -164,6 +165,7 @@ static void virtio_scsi_with_flag_fuzz(QTestState *s, } _Exit(0); } else { + flush_events(s); wait(NULL); } } @@ -189,7 +191,7 @@ static void register_virtio_scsi_fuzz_targets(void) { fuzz_add_qos_target(&(FuzzTarget){ .name = "virtio-scsi-fuzz", - .description = "Fuzz the virtio-scsi virtual queues, forking" + .description = "Fuzz the virtio-scsi virtual queues, forking " "for each fuzz run", .pre_vm_init = &counter_shm_init, .pre_fuzz = &virtio_scsi_pre_fuzz, @@ -200,7 +202,7 @@ static void register_virtio_scsi_fuzz_targets(void) fuzz_add_qos_target(&(FuzzTarget){ .name = "virtio-scsi-flags-fuzz", - .description = "Fuzz the virtio-scsi virtual queues, forking" + .description = "Fuzz the virtio-scsi virtual queues, forking " "for each fuzz run (also fuzzes the virtio flags)", .pre_vm_init = &counter_shm_init, .pre_fuzz = &virtio_scsi_pre_fuzz, diff --git a/tests/qtest/fw_cfg-test.c b/tests/qtest/fw_cfg-test.c index 5dc807ba2385398714bfae552ff7366635923bcd..95b3907c18c471f2f946f3cd09798f4b10436a5c 100644 --- a/tests/qtest/fw_cfg-test.c +++ b/tests/qtest/fw_cfg-test.c @@ -12,7 +12,7 @@ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "standard-headers/linux/qemu_fw_cfg.h" #include "libqos/fw_cfg.h" #include "qemu/bswap.h" diff --git a/tests/qtest/hd-geo-test.c b/tests/qtest/hd-geo-test.c index 48e8e02d6ecc02649641f1f1bce6dccd553402a6..f7b7cfbc2d1ac14148f987f186f4bc6673c118fd 100644 --- a/tests/qtest/hd-geo-test.c +++ b/tests/qtest/hd-geo-test.c @@ -19,7 +19,7 @@ #include "qemu-common.h" #include "qemu/bswap.h" #include "qapi/qmp/qlist.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "libqos/fw_cfg.h" #include "libqos/libqos.h" #include "standard-headers/linux/qemu_fw_cfg.h" diff --git a/tests/qtest/hexloader-test.c b/tests/qtest/hexloader-test.c index 8b7aa2d72d0dfda9f5cafb56128206aa9e2382bb..561502052a6748ba75c741de3f36b8e32958b0f4 100644 --- a/tests/qtest/hexloader-test.c +++ b/tests/qtest/hexloader-test.c @@ -10,7 +10,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" /* Load 'test.hex' and verify that the in-memory contents are as expected. * 'test.hex' is a memory test pattern stored in Hexadecimal Object diff --git a/tests/qtest/ide-test.c b/tests/qtest/ide-test.c index 5cfd97f915f74945871affb22fb6726259f962d3..3f8081e77d056f6b5d43a8345bbfc557ffd609f7 100644 --- a/tests/qtest/ide-test.c +++ b/tests/qtest/ide-test.c @@ -25,7 +25,7 @@ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "libqos/libqos.h" #include "libqos/pci-pc.h" #include "libqos/malloc-pc.h" diff --git a/tests/qtest/ipmi-kcs-test.c b/tests/qtest/ipmi-kcs-test.c index 693a6aacb521edbfe5260d478549754bf79dace8..fc0a918c8d1f1bbe67a7897f0b6d0b6e3a4d3df5 100644 --- a/tests/qtest/ipmi-kcs-test.c +++ b/tests/qtest/ipmi-kcs-test.c @@ -81,7 +81,8 @@ static void kcs_wait_obf(void) { unsigned int count = 1000; while (IPMI_KCS_CMDREG_GET_OBF() == 0) { - g_assert(--count != 0); + --count; + g_assert(count != 0); } } diff --git a/tests/qtest/ipoctal232-test.c b/tests/qtest/ipoctal232-test.c index 53a8c9b13ce582764e56a4fa85edafe4fc32d760..65ce10b81befb05396ddd691873bb7999f0accc9 100644 --- a/tests/qtest/ipoctal232-test.c +++ b/tests/qtest/ipoctal232-test.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/module.h" #include "libqos/qgraph.h" diff --git a/tests/qtest/ivshmem-test.c b/tests/qtest/ivshmem-test.c index ecda25647265aa98ca9b59a7c015a5070605cc41..dfa69424ed90ca3bcf2ec441a1fa2df7bdcdd6c2 100644 --- a/tests/qtest/ivshmem-test.c +++ b/tests/qtest/ivshmem-test.c @@ -13,7 +13,7 @@ #include "contrib/ivshmem-server/ivshmem-server.h" #include "libqos/libqos-pc.h" #include "libqos/libqos-spapr.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu-common.h" #define TMPSHMSIZE (1 << 20) @@ -135,7 +135,7 @@ static void setup_vm_cmd(IVState *s, const char *cmd, bool msix) static void setup_vm(IVState *s) { char *cmd = g_strdup_printf("-object memory-backend-file" - ",id=mb1,size=1M,share,mem-path=/dev/shm%s" + ",id=mb1,size=1M,share=on,mem-path=/dev/shm%s" " -device ivshmem-plain,memdev=mb1", tmpshm); setup_vm_cmd(s, cmd, false); diff --git a/tests/qtest/libqos/aarch64-xlnx-zcu102-machine.c b/tests/qtest/libqos/aarch64-xlnx-zcu102-machine.c index 1d5de5af0010f58775c271e0f016ef4d312d90db..79631cc7a9ad87a4f2019dbf05ec3304b0adc4b4 100644 --- a/tests/qtest/libqos/aarch64-xlnx-zcu102-machine.c +++ b/tests/qtest/libqos/aarch64-xlnx-zcu102-machine.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,8 +19,8 @@ #include "qemu/osdep.h" #include "libqtest.h" #include "qemu/module.h" -#include "libqos/malloc.h" -#include "libqos/qgraph.h" +#include "malloc.h" +#include "qgraph.h" #include "sdhci.h" typedef struct QXlnxZCU102Machine QXlnxZCU102Machine; diff --git a/tests/qtest/libqos/ahci.c b/tests/qtest/libqos/ahci.c index cc1b08eabef0e4900448f9e32ffd3b83fdee9e0f..fba3e7a954ed3f62b8b907e8b85f3b5f4a1daebb 100644 --- a/tests/qtest/libqos/ahci.c +++ b/tests/qtest/libqos/ahci.c @@ -25,8 +25,8 @@ #include "qemu/osdep.h" #include "libqtest.h" -#include "libqos/ahci.h" -#include "libqos/pci-pc.h" +#include "ahci.h" +#include "pci-pc.h" #include "qemu-common.h" #include "qemu/host-utils.h" @@ -579,7 +579,7 @@ void ahci_write_fis(AHCIQState *ahci, AHCICommand *cmd) /* NCQ commands use exclusively 8 bit fields and needs no adjustment. * Only the count field needs to be adjusted for non-NCQ commands. * The auxiliary FIS fields are defined per-command and are not currently - * implemented in libqos/ahci.o, but may or may not need to be flipped. */ + * implemented in ahci.o, but may or may not need to be flipped. */ if (!cmd->props->ncq) { tmp.count = cpu_to_le16(tmp.count); } @@ -637,10 +637,13 @@ void ahci_exec(AHCIQState *ahci, uint8_t port, AHCICommand *cmd; int rc; AHCIOpts *opts; + uint64_t buffer_in; opts = g_memdup((opts_in == NULL ? &default_opts : opts_in), sizeof(AHCIOpts)); + buffer_in = opts->buffer; + /* No guest buffer provided, create one. */ if (opts->size && !opts->buffer) { opts->buffer = ahci_alloc(ahci, opts->size); @@ -686,7 +689,7 @@ void ahci_exec(AHCIQState *ahci, uint8_t port, g_assert_cmpint(rc, ==, 0); } ahci_command_free(cmd); - if (opts->buffer != opts_in->buffer) { + if (opts->buffer != buffer_in) { ahci_free(ahci, opts->buffer); } g_free(opts); diff --git a/tests/qtest/libqos/ahci.h b/tests/qtest/libqos/ahci.h index 44ab1104b5e97783b595191807699b173befc367..88835b622830c006cbd0fcbb1151f4fb05d296a5 100644 --- a/tests/qtest/libqos/ahci.h +++ b/tests/qtest/libqos/ahci.h @@ -25,9 +25,9 @@ * THE SOFTWARE. */ -#include "libqos/libqos.h" -#include "libqos/pci.h" -#include "libqos/malloc-pc.h" +#include "libqos.h" +#include "pci.h" +#include "malloc-pc.h" /*** Supplementary PCI Config Space IDs & Masks ***/ #define PCI_DEVICE_ID_INTEL_Q35_AHCI (0x2922) diff --git a/tests/qtest/libqos/arm-imx25-pdk-machine.c b/tests/qtest/libqos/arm-imx25-pdk-machine.c index 25066fb8a9634b748900f9f2249c87cfa065480e..6692adfa4fcb8589e73675d3f0f616ad2d0b8e9a 100644 --- a/tests/qtest/libqos/arm-imx25-pdk-machine.c +++ b/tests/qtest/libqos/arm-imx25-pdk-machine.c @@ -7,7 +7,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,9 +20,9 @@ #include "qemu/osdep.h" #include "libqtest.h" -#include "libqos/malloc.h" -#include "libqos/qgraph.h" -#include "libqos/i2c.h" +#include "malloc.h" +#include "qgraph.h" +#include "i2c.h" #define ARM_PAGE_SIZE 4096 #define IMX25_PDK_RAM_START 0x80000000 diff --git a/tests/qtest/libqos/arm-n800-machine.c b/tests/qtest/libqos/arm-n800-machine.c index 87279bdb26a1c54d15887b9b00c82a7d9ed02894..ff2049c3a7eb38410cee411376058c8d337a5526 100644 --- a/tests/qtest/libqos/arm-n800-machine.c +++ b/tests/qtest/libqos/arm-n800-machine.c @@ -7,7 +7,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,9 +20,9 @@ #include "qemu/osdep.h" #include "libqtest.h" -#include "libqos/malloc.h" -#include "libqos/qgraph.h" -#include "libqos/i2c.h" +#include "malloc.h" +#include "qgraph.h" +#include "i2c.h" #define ARM_PAGE_SIZE 4096 #define N800_RAM_START 0x80000000 diff --git a/tests/qtest/libqos/arm-raspi2-machine.c b/tests/qtest/libqos/arm-raspi2-machine.c index 12a7cb7e4ba7ec6e65a6fe9b39126e3e21e5c1b6..35bb4709a4534a81dddbe1909a3e820d46fa6431 100644 --- a/tests/qtest/libqos/arm-raspi2-machine.c +++ b/tests/qtest/libqos/arm-raspi2-machine.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,8 +19,8 @@ #include "qemu/osdep.h" #include "libqtest.h" #include "qemu/module.h" -#include "libqos/malloc.h" -#include "libqos/qgraph.h" +#include "malloc.h" +#include "qgraph.h" #include "sdhci.h" #define ARM_PAGE_SIZE 4096 diff --git a/tests/qtest/libqos/arm-sabrelite-machine.c b/tests/qtest/libqos/arm-sabrelite-machine.c index e6df43795a7cd0aadb0f64b5a120c71fb2c3b9da..72425f0ad4043905bdd584b6d09181836153e214 100644 --- a/tests/qtest/libqos/arm-sabrelite-machine.c +++ b/tests/qtest/libqos/arm-sabrelite-machine.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,8 +19,8 @@ #include "qemu/osdep.h" #include "libqtest.h" #include "qemu/module.h" -#include "libqos/malloc.h" -#include "libqos/qgraph.h" +#include "malloc.h" +#include "qgraph.h" #include "sdhci.h" #define ARM_PAGE_SIZE 4096 diff --git a/tests/qtest/libqos/arm-smdkc210-machine.c b/tests/qtest/libqos/arm-smdkc210-machine.c index 215b628a7dab8422614132ae4fd1f0c867a808cd..321b8826d4a2b64d8fbda630e30d46e8006e886c 100644 --- a/tests/qtest/libqos/arm-smdkc210-machine.c +++ b/tests/qtest/libqos/arm-smdkc210-machine.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,8 +19,8 @@ #include "qemu/osdep.h" #include "libqtest.h" #include "qemu/module.h" -#include "libqos/malloc.h" -#include "libqos/qgraph.h" +#include "malloc.h" +#include "qgraph.h" #include "sdhci.h" #define ARM_PAGE_SIZE 4096 diff --git a/tests/qtest/libqos/arm-virt-machine.c b/tests/qtest/libqos/arm-virt-machine.c index 96ffe3ee5c42471571f7acd003c55753a48296d9..e0f59322845aeebeb9b7a703185800038c7a9384 100644 --- a/tests/qtest/libqos/arm-virt-machine.c +++ b/tests/qtest/libqos/arm-virt-machine.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,9 +19,9 @@ #include "qemu/osdep.h" #include "libqtest.h" #include "qemu/module.h" -#include "libqos/malloc.h" -#include "libqos/qgraph.h" -#include "libqos/virtio-mmio.h" +#include "malloc.h" +#include "qgraph.h" +#include "virtio-mmio.h" #define ARM_PAGE_SIZE 4096 #define VIRTIO_MMIO_BASE_ADDR 0x0A003E00 diff --git a/tests/qtest/libqos/arm-xilinx-zynq-a9-machine.c b/tests/qtest/libqos/arm-xilinx-zynq-a9-machine.c index 5bc95f2e73a98e8f069f928dd0fc87b0d014e691..56e53c745bffd4f80e9414bc45924ded4a85581e 100644 --- a/tests/qtest/libqos/arm-xilinx-zynq-a9-machine.c +++ b/tests/qtest/libqos/arm-xilinx-zynq-a9-machine.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,8 +19,8 @@ #include "qemu/osdep.h" #include "libqtest.h" #include "qemu/module.h" -#include "libqos/malloc.h" -#include "libqos/qgraph.h" +#include "malloc.h" +#include "qgraph.h" #include "sdhci.h" typedef struct QXilinxZynqA9Machine QXilinxZynqA9Machine; diff --git a/tests/qtest/libqos/e1000e.c b/tests/qtest/libqos/e1000e.c index 560e7a2bb2585f29c1d6ab805173c2835d57ec68..a451f6168f63d8672cc52943801fd9e8562fa71c 100644 --- a/tests/qtest/libqos/e1000e.c +++ b/tests/qtest/libqos/e1000e.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -18,13 +18,13 @@ #include "qemu/osdep.h" #include "libqtest.h" -#include "libqos/pci-pc.h" +#include "pci-pc.h" #include "qemu/sockets.h" #include "qemu/iov.h" #include "qemu/module.h" #include "qemu/bitops.h" -#include "libqos/malloc.h" -#include "libqos/qgraph.h" +#include "malloc.h" +#include "qgraph.h" #include "e1000e.h" #define E1000E_IMS (0x00d0) diff --git a/tests/qtest/libqos/e1000e.h b/tests/qtest/libqos/e1000e.h index dc4ab10f584ada22df359b8e7f45855160d0f8d2..a22f5fdbad0dc0303a14af569da81ab9a68dc06f 100644 --- a/tests/qtest/libqos/e1000e.h +++ b/tests/qtest/libqos/e1000e.h @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,7 +19,7 @@ #ifndef QGRAPH_E1000E_H #define QGRAPH_E1000E_H -#include "libqos/qgraph.h" +#include "qgraph.h" #include "pci.h" #define E1000E_RX0_MSG_ID (0) diff --git a/tests/qtest/libqos/fw_cfg.c b/tests/qtest/libqos/fw_cfg.c index 1f46258f96bfd73ce55b634a6b28815d203331ad..6b8e1babe51e963f95c572bef51c4b2f4ab87b1d 100644 --- a/tests/qtest/libqos/fw_cfg.c +++ b/tests/qtest/libqos/fw_cfg.c @@ -13,7 +13,7 @@ */ #include "qemu/osdep.h" -#include "libqos/fw_cfg.h" +#include "fw_cfg.h" #include "libqtest.h" #include "qemu/bswap.h" #include "hw/nvram/fw_cfg.h" diff --git a/tests/qtest/libqos/i2c-imx.c b/tests/qtest/libqos/i2c-imx.c index f33ece55a37f32c7582212fdfa91d966cb1f72b8..8f9a7e383146694e428e0dc9852e2acea2f425a8 100644 --- a/tests/qtest/libqos/i2c-imx.c +++ b/tests/qtest/libqos/i2c-imx.c @@ -18,7 +18,7 @@ */ #include "qemu/osdep.h" -#include "libqos/i2c.h" +#include "i2c.h" #include "libqtest.h" diff --git a/tests/qtest/libqos/i2c-omap.c b/tests/qtest/libqos/i2c-omap.c index 9ae8214fa802779ee708ec19c0dacc8027c4fa1f..eb4e453485dbdfa7d22e681b1767e54457c65715 100644 --- a/tests/qtest/libqos/i2c-omap.c +++ b/tests/qtest/libqos/i2c-omap.c @@ -7,7 +7,7 @@ * See the COPYING file in the top-level directory. */ #include "qemu/osdep.h" -#include "libqos/i2c.h" +#include "i2c.h" #include "qemu/bswap.h" diff --git a/tests/qtest/libqos/i2c.c b/tests/qtest/libqos/i2c.c index 38f800dbab7246aef77357b609cdf542dc454437..ade1bdb40e05e56bf64da292c57d375cbc4dd439 100644 --- a/tests/qtest/libqos/i2c.c +++ b/tests/qtest/libqos/i2c.c @@ -7,7 +7,7 @@ * See the COPYING file in the top-level directory. */ #include "qemu/osdep.h" -#include "libqos/i2c.h" +#include "i2c.h" #include "libqtest.h" void qi2c_send(QI2CDevice *i2cdev, const uint8_t *buf, uint16_t len) diff --git a/tests/qtest/libqos/i2c.h b/tests/qtest/libqos/i2c.h index c65f0878349ee915ba769f9923a36dae415bb590..1341bac1c599114e61e99d487855e77bb97526ea 100644 --- a/tests/qtest/libqos/i2c.h +++ b/tests/qtest/libqos/i2c.h @@ -10,7 +10,7 @@ #define LIBQOS_I2C_H #include "libqtest.h" -#include "libqos/qgraph.h" +#include "qgraph.h" typedef struct I2CAdapter I2CAdapter; struct I2CAdapter { diff --git a/tests/qtest/libqos/libqos-pc.c b/tests/qtest/libqos/libqos-pc.c index d04abc548bade6a0a3aaa5d9fcc780d702af2c68..db420a596e9afea774ec86641c203e819d7cc0aa 100644 --- a/tests/qtest/libqos/libqos-pc.c +++ b/tests/qtest/libqos/libqos-pc.c @@ -1,7 +1,7 @@ #include "qemu/osdep.h" -#include "libqos/libqos-pc.h" -#include "libqos/malloc-pc.h" -#include "libqos/pci-pc.h" +#include "libqos-pc.h" +#include "malloc-pc.h" +#include "pci-pc.h" static QOSOps qos_ops = { .alloc_init = pc_alloc_init, diff --git a/tests/qtest/libqos/libqos-pc.h b/tests/qtest/libqos/libqos-pc.h index a0e4c45516fbe32a0182347565d0d279673a81d4..1a9923ead42fc134a2c11748ccb517bfe8ebba89 100644 --- a/tests/qtest/libqos/libqos-pc.h +++ b/tests/qtest/libqos/libqos-pc.h @@ -1,7 +1,7 @@ #ifndef LIBQOS_PC_H #define LIBQOS_PC_H -#include "libqos/libqos.h" +#include "libqos.h" QOSState *qtest_pc_vboot(const char *cmdline_fmt, va_list ap); QOSState *qtest_pc_boot(const char *cmdline_fmt, ...); diff --git a/tests/qtest/libqos/libqos-spapr.c b/tests/qtest/libqos/libqos-spapr.c index 8766d543ce59c4471c84731b0f0cef404e8074e9..db0e87ba5c42ddd78ad028da6ecbb68de480ae02 100644 --- a/tests/qtest/libqos/libqos-spapr.c +++ b/tests/qtest/libqos/libqos-spapr.c @@ -1,7 +1,7 @@ #include "qemu/osdep.h" -#include "libqos/libqos-spapr.h" -#include "libqos/malloc-spapr.h" -#include "libqos/pci-spapr.h" +#include "libqos-spapr.h" +#include "malloc-spapr.h" +#include "pci-spapr.h" static QOSOps qos_ops = { .alloc_init = spapr_alloc_init, diff --git a/tests/qtest/libqos/libqos-spapr.h b/tests/qtest/libqos/libqos-spapr.h index 49bd72d20b9756e726a1b1907f887dab013d8e1a..c61338917acd3e00a97344016b30e4148644ed05 100644 --- a/tests/qtest/libqos/libqos-spapr.h +++ b/tests/qtest/libqos/libqos-spapr.h @@ -1,7 +1,7 @@ #ifndef LIBQOS_SPAPR_H #define LIBQOS_SPAPR_H -#include "libqos/libqos.h" +#include "libqos.h" QOSState *qtest_spapr_vboot(const char *cmdline_fmt, va_list ap); QOSState *qtest_spapr_boot(const char *cmdline_fmt, ...); diff --git a/tests/qtest/libqos/libqos.c b/tests/qtest/libqos/libqos.c index f229eb2cb831c95a4f74fa7937d0ff42a021bf3f..2251e864efe1a00c51e41a50ddb8602a2cbd9639 100644 --- a/tests/qtest/libqos/libqos.c +++ b/tests/qtest/libqos/libqos.c @@ -2,8 +2,8 @@ #include #include "libqtest.h" -#include "libqos/libqos.h" -#include "libqos/pci.h" +#include "libqos.h" +#include "pci.h" #include "qapi/qmp/qdict.h" /*** Test Setup & Teardown ***/ diff --git a/tests/qtest/libqos/libqos.h b/tests/qtest/libqos/libqos.h index 8e971c25a3df460f3d89692cbcf5168606b21904..e0b2bfe7caf9071df7a4f9df698522d5c5e1cd72 100644 --- a/tests/qtest/libqos/libqos.h +++ b/tests/qtest/libqos/libqos.h @@ -2,8 +2,8 @@ #define LIBQOS_H #include "libqtest.h" -#include "libqos/pci.h" -#include "libqos/malloc.h" +#include "pci.h" +#include "malloc.h" typedef struct QOSState QOSState; diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqos/libqtest.h similarity index 90% rename from tests/qtest/libqtest.h rename to tests/qtest/libqos/libqtest.h index f5cf93c38629e83e3e6e67ed056afd5b430cdafa..724f65aa947ca7b1bb4a28238418745380031403 100644 --- a/tests/qtest/libqtest.h +++ b/tests/qtest/libqos/libqtest.h @@ -24,7 +24,7 @@ typedef struct QTestState QTestState; /** * qtest_initf: - * @fmt...: Format for creating other arguments to pass to QEMU, formatted + * @fmt: Format for creating other arguments to pass to QEMU, formatted * like sprintf(). * * Convenience wrapper around qtest_init(). @@ -87,8 +87,8 @@ void qtest_quit(QTestState *s); * @s: #QTestState instance to operate on. * @fds: array of file descriptors * @fds_num: number of elements in @fds - * @fmt...: QMP message to send to qemu, formatted like - * qobject_from_jsonf_nofail(). See parse_escape() for what's + * @fmt: QMP message to send to qemu, formatted like + * qobject_from_jsonf_nofail(). See parse_interpolation() for what's * supported after '%'. * * Sends a QMP message to QEMU with fds and returns the response. @@ -100,8 +100,8 @@ QDict *qtest_qmp_fds(QTestState *s, int *fds, size_t fds_num, /** * qtest_qmp: * @s: #QTestState instance to operate on. - * @fmt...: QMP message to send to qemu, formatted like - * qobject_from_jsonf_nofail(). See parse_escape() for what's + * @fmt: QMP message to send to qemu, formatted like + * qobject_from_jsonf_nofail(). See parse_interpolation() for what's * supported after '%'. * * Sends a QMP message to QEMU and returns the response. @@ -112,8 +112,8 @@ QDict *qtest_qmp(QTestState *s, const char *fmt, ...) /** * qtest_qmp_send: * @s: #QTestState instance to operate on. - * @fmt...: QMP message to send to qemu, formatted like - * qobject_from_jsonf_nofail(). See parse_escape() for what's + * @fmt: QMP message to send to qemu, formatted like + * qobject_from_jsonf_nofail(). See parse_interpolation() for what's * supported after '%'. * * Sends a QMP message to QEMU and leaves the response in the stream. @@ -124,7 +124,7 @@ void qtest_qmp_send(QTestState *s, const char *fmt, ...) /** * qtest_qmp_send_raw: * @s: #QTestState instance to operate on. - * @fmt...: text to send, formatted like sprintf() + * @fmt: text to send, formatted like sprintf() * * Sends text to the QMP monitor verbatim. Need not be valid JSON; * this is useful for negative tests. @@ -138,7 +138,7 @@ void qtest_qmp_send_raw(QTestState *s, const char *fmt, ...) * @fds: array of file descriptors * @fds_num: number of elements in @fds * @fmt: QMP message to send to QEMU, formatted like - * qobject_from_jsonf_nofail(). See parse_escape() for what's + * qobject_from_jsonf_nofail(). See parse_interpolation() for what's * supported after '%'. * @ap: QMP message arguments * @@ -152,7 +152,7 @@ QDict *qtest_vqmp_fds(QTestState *s, int *fds, size_t fds_num, * qtest_vqmp: * @s: #QTestState instance to operate on. * @fmt: QMP message to send to QEMU, formatted like - * qobject_from_jsonf_nofail(). See parse_escape() for what's + * qobject_from_jsonf_nofail(). See parse_interpolation() for what's * supported after '%'. * @ap: QMP message arguments * @@ -167,7 +167,7 @@ QDict *qtest_vqmp(QTestState *s, const char *fmt, va_list ap) * @fds: array of file descriptors * @fds_num: number of elements in @fds * @fmt: QMP message to send to QEMU, formatted like - * qobject_from_jsonf_nofail(). See parse_escape() for what's + * qobject_from_jsonf_nofail(). See parse_interpolation() for what's * supported after '%'. * @ap: QMP message arguments * @@ -181,7 +181,7 @@ void qtest_qmp_vsend_fds(QTestState *s, int *fds, size_t fds_num, * qtest_qmp_vsend: * @s: #QTestState instance to operate on. * @fmt: QMP message to send to QEMU, formatted like - * qobject_from_jsonf_nofail(). See parse_escape() for what's + * qobject_from_jsonf_nofail(). See parse_interpolation() for what's * supported after '%'. * @ap: QMP message arguments * @@ -191,17 +191,27 @@ void qtest_qmp_vsend(QTestState *s, const char *fmt, va_list ap) GCC_FMT_ATTR(2, 0); /** - * qtest_receive: + * qtest_qmp_receive_dict: * @s: #QTestState instance to operate on. * * Reads a QMP message from QEMU and returns the response. */ +QDict *qtest_qmp_receive_dict(QTestState *s); + +/** + * qtest_qmp_receive: + * @s: #QTestState instance to operate on. + * + * Reads a QMP message from QEMU and returns the response. + * Buffers all the events received meanwhile, until a + * call to qtest_qmp_eventwait + */ QDict *qtest_qmp_receive(QTestState *s); /** * qtest_qmp_eventwait: * @s: #QTestState instance to operate on. - * @s: #event event to wait for. + * @event: event to wait for. * * Continuously polls for QMP responses until it receives the desired event. */ @@ -210,7 +220,7 @@ void qtest_qmp_eventwait(QTestState *s, const char *event); /** * qtest_qmp_eventwait_ref: * @s: #QTestState instance to operate on. - * @s: #event event to wait for. + * @event: event to wait for. * * Continuously polls for QMP responses until it receives the desired event. * Returns a copy of the event for further investigation. @@ -218,26 +228,22 @@ void qtest_qmp_eventwait(QTestState *s, const char *event); QDict *qtest_qmp_eventwait_ref(QTestState *s, const char *event); /** - * qtest_qmp_receive_success: - * @s: #QTestState instance to operate on - * @event_cb: Event callback - * @opaque: Argument for @event_cb + * qtest_qmp_event_ref: + * @s: #QTestState instance to operate on. + * @event: event to return. + * + * Removes non-matching events from the buffer that was set by + * qtest_qmp_receive, until an event bearing the given name is found, + * and returns it. + * If no event matches, clears the buffer and returns NULL. * - * Poll QMP messages until a command success response is received. - * If @event_cb, call it for each event received, passing @opaque, - * the event's name and data. - * Return the success response's "return" member. */ -QDict *qtest_qmp_receive_success(QTestState *s, - void (*event_cb)(void *opaque, - const char *name, - QDict *data), - void *opaque); +QDict *qtest_qmp_event_ref(QTestState *s, const char *event); /** * qtest_hmp: * @s: #QTestState instance to operate on. - * @fmt...: HMP command to send to QEMU, formats arguments like sprintf(). + * @fmt: HMP command to send to QEMU, formats arguments like sprintf(). * * Send HMP command to QEMU via QMP's human-monitor-command. * QMP events are discarded. @@ -629,8 +635,8 @@ void qtest_add_abrt_handler(GHookFunc fn, const void *data); /** * qtest_qmp_assert_success: * @qts: QTestState instance to operate on - * @fmt...: QMP message to send to qemu, formatted like - * qobject_from_jsonf_nofail(). See parse_escape() for what's + * @fmt: QMP message to send to qemu, formatted like + * qobject_from_jsonf_nofail(). See parse_interpolation() for what's * supported after '%'. * * Sends a QMP message to QEMU and asserts that a 'return' key is present in @@ -676,8 +682,8 @@ void qtest_qmp_device_add_qdict(QTestState *qts, const char *drv, * @qts: QTestState instance to operate on * @driver: Name of the device that should be added * @id: Identification string - * @fmt...: QMP message to send to qemu, formatted like - * qobject_from_jsonf_nofail(). See parse_escape() for what's + * @fmt: QMP message to send to qemu, formatted like + * qobject_from_jsonf_nofail(). See parse_interpolation() for what's * supported after '%'. * * Generic hot-plugging test via the device_add QMP command. @@ -704,13 +710,13 @@ void qtest_qmp_device_del(QTestState *qts, const char *id); bool qmp_rsp_is_err(QDict *rsp); /** - * qmp_assert_error_class: + * qmp_expect_error_and_unref: * @rsp: QMP response to check for error * @class: an error class * * Assert the response has the given error class and discard @rsp. */ -void qmp_assert_error_class(QDict *rsp, const char *class); +void qmp_expect_error_and_unref(QDict *rsp, const char *class); /** * qtest_probe_child: diff --git a/tests/qtest/libqos/malloc-pc.c b/tests/qtest/libqos/malloc-pc.c index 6f92ce41350c8bec1b5c1c3be8666bb7d9c9d377..16ff9609ccc0d9894af5ea4a176b69f158210640 100644 --- a/tests/qtest/libqos/malloc-pc.c +++ b/tests/qtest/libqos/malloc-pc.c @@ -11,8 +11,8 @@ */ #include "qemu/osdep.h" -#include "libqos/malloc-pc.h" -#include "libqos/fw_cfg.h" +#include "malloc-pc.h" +#include "fw_cfg.h" #include "standard-headers/linux/qemu_fw_cfg.h" diff --git a/tests/qtest/libqos/malloc-pc.h b/tests/qtest/libqos/malloc-pc.h index 21e75ae00493eb9aaaabe510b844774784c1a1a7..d8d79853c8442e0bd983de668af4199b4d806f83 100644 --- a/tests/qtest/libqos/malloc-pc.h +++ b/tests/qtest/libqos/malloc-pc.h @@ -13,7 +13,7 @@ #ifndef LIBQOS_MALLOC_PC_H #define LIBQOS_MALLOC_PC_H -#include "libqos/malloc.h" +#include "malloc.h" void pc_alloc_init(QGuestAllocator *s, QTestState *qts, QAllocOpts flags); diff --git a/tests/qtest/libqos/malloc-spapr.c b/tests/qtest/libqos/malloc-spapr.c index 2a6b7e3776a30f26323751a4be48bd53b61fc609..84862e48768a57873a13fb5050d689eb9489eb1c 100644 --- a/tests/qtest/libqos/malloc-spapr.c +++ b/tests/qtest/libqos/malloc-spapr.c @@ -6,7 +6,7 @@ */ #include "qemu/osdep.h" -#include "libqos/malloc-spapr.h" +#include "malloc-spapr.h" #include "qemu-common.h" diff --git a/tests/qtest/libqos/malloc-spapr.h b/tests/qtest/libqos/malloc-spapr.h index e5fe9bfc4b548d811d5375ecaaa6d4cf30010d61..f99572fd71d94944d31da5e4e953857ce0bf1603 100644 --- a/tests/qtest/libqos/malloc-spapr.h +++ b/tests/qtest/libqos/malloc-spapr.h @@ -8,7 +8,7 @@ #ifndef LIBQOS_MALLOC_SPAPR_H #define LIBQOS_MALLOC_SPAPR_H -#include "libqos/malloc.h" +#include "malloc.h" void spapr_alloc_init(QGuestAllocator *s, QTestState *qts, QAllocOpts flags); diff --git a/tests/qtest/libqos/malloc.c b/tests/qtest/libqos/malloc.c index 615422a5c4da4c161f247d410811e991c7127fb7..f708b0143262d287a98591a2b49612803a4f8e09 100644 --- a/tests/qtest/libqos/malloc.c +++ b/tests/qtest/libqos/malloc.c @@ -11,7 +11,7 @@ */ #include "qemu/osdep.h" -#include "libqos/malloc.h" +#include "malloc.h" #include "qemu-common.h" #include "qemu/host-utils.h" diff --git a/tests/qtest/libqos/meson.build b/tests/qtest/libqos/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..1cddf5bdaa1c6a299677c225d85988c547ae3b57 --- /dev/null +++ b/tests/qtest/libqos/meson.build @@ -0,0 +1,60 @@ +libqos_srcs = files('../libqtest.c', + 'qgraph.c', + 'qos_external.c', + 'pci.c', + 'fw_cfg.c', + 'malloc.c', + 'libqos.c', + + # spapr + 'malloc-spapr.c', + 'libqos-spapr.c', + 'rtas.c', + 'pci-spapr.c', + + # pc + 'pci-pc.c', + 'malloc-pc.c', + 'libqos-pc.c', + 'ahci.c', + + # usb + 'usb.c', + + # qgraph devices: + 'e1000e.c', + 'i2c.c', + 'i2c-imx.c', + 'i2c-omap.c', + 'sdhci.c', + 'tpci200.c', + 'virtio.c', + 'virtio-9p.c', + 'virtio-balloon.c', + 'virtio-blk.c', + 'virtio-mmio.c', + 'virtio-net.c', + 'virtio-pci.c', + 'virtio-pci-modern.c', + 'virtio-rng.c', + 'virtio-scsi.c', + 'virtio-serial.c', + + # qgraph machines: + 'aarch64-xlnx-zcu102-machine.c', + 'arm-imx25-pdk-machine.c', + 'arm-n800-machine.c', + 'arm-raspi2-machine.c', + 'arm-sabrelite-machine.c', + 'arm-smdkc210-machine.c', + 'arm-virt-machine.c', + 'arm-xilinx-zynq-a9-machine.c', + 'ppc64_pseries-machine.c', + 'x86_64_pc-machine.c', +) + +libqos = static_library('qos', libqos_srcs + genh, + name_suffix: 'fa', + build_by_default: false) + +qos = declare_dependency(link_whole: libqos) diff --git a/tests/qtest/libqos/pci-pc.c b/tests/qtest/libqos/pci-pc.c index 0bc591d1daff7115b9ae485c16a0eb2a580e3db0..f97844289f138c1d082723ef90ebc5f6d0eb883c 100644 --- a/tests/qtest/libqos/pci-pc.c +++ b/tests/qtest/libqos/pci-pc.c @@ -12,7 +12,7 @@ #include "qemu/osdep.h" #include "libqtest.h" -#include "libqos/pci-pc.h" +#include "pci-pc.h" #include "qapi/qmp/qdict.h" #include "hw/pci/pci_regs.h" @@ -186,7 +186,7 @@ void qpci_unplug_acpi_device_test(QTestState *qts, const char *id, uint8_t slot) g_assert(!qdict_haskey(response, "error")); qobject_unref(response); - qtest_outb(qts, ACPI_PCIHP_ADDR + PCI_EJ_BASE, 1 << slot); + qtest_outl(qts, ACPI_PCIHP_ADDR + PCI_EJ_BASE, 1 << slot); qtest_qmp_eventwait(qts, "DEVICE_DELETED"); } diff --git a/tests/qtest/libqos/pci-pc.h b/tests/qtest/libqos/pci-pc.h index 4690005232342636a6bd01fc5a0838ca9b146b7b..49ec9507f22de21a6c01f6023b39c2ac884cdc86 100644 --- a/tests/qtest/libqos/pci-pc.h +++ b/tests/qtest/libqos/pci-pc.h @@ -13,9 +13,9 @@ #ifndef LIBQOS_PCI_PC_H #define LIBQOS_PCI_PC_H -#include "libqos/pci.h" -#include "libqos/malloc.h" -#include "libqos/qgraph.h" +#include "pci.h" +#include "malloc.h" +#include "qgraph.h" typedef struct QPCIBusPC { QOSGraphObject obj; diff --git a/tests/qtest/libqos/pci-spapr.c b/tests/qtest/libqos/pci-spapr.c index d6f8c01cb7b01fc9f4a396979240f9108a3687ac..262226985f378e8af0c65e12577d7f94e9464115 100644 --- a/tests/qtest/libqos/pci-spapr.c +++ b/tests/qtest/libqos/pci-spapr.c @@ -7,9 +7,9 @@ #include "qemu/osdep.h" #include "libqtest.h" -#include "libqos/pci-spapr.h" -#include "libqos/rtas.h" -#include "libqos/qgraph.h" +#include "pci-spapr.h" +#include "rtas.h" +#include "qgraph.h" #include "hw/pci/pci_regs.h" diff --git a/tests/qtest/libqos/pci-spapr.h b/tests/qtest/libqos/pci-spapr.h index d9e25631c6a9a2c996e0b438ada497b943868cee..20a43718b7dbfce60c4cd568aea61fa00fd0717b 100644 --- a/tests/qtest/libqos/pci-spapr.h +++ b/tests/qtest/libqos/pci-spapr.h @@ -8,9 +8,9 @@ #ifndef LIBQOS_PCI_SPAPR_H #define LIBQOS_PCI_SPAPR_H -#include "libqos/malloc.h" -#include "libqos/pci.h" -#include "libqos/qgraph.h" +#include "malloc.h" +#include "pci.h" +#include "qgraph.h" /* From include/hw/pci-host/spapr.h */ diff --git a/tests/qtest/libqos/pci.c b/tests/qtest/libqos/pci.c index 2309a724e434b0342f9d963e6833a44b607bdf19..e1e96189c821734850901cb6401fb6e219be5636 100644 --- a/tests/qtest/libqos/pci.c +++ b/tests/qtest/libqos/pci.c @@ -11,11 +11,11 @@ */ #include "qemu/osdep.h" -#include "libqos/pci.h" +#include "pci.h" #include "hw/pci/pci_regs.h" #include "qemu/host-utils.h" -#include "libqos/qgraph.h" +#include "qgraph.h" void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id, void (*func)(QPCIDevice *dev, int devfn, void *data), diff --git a/tests/qtest/libqos/pci.h b/tests/qtest/libqos/pci.h index 590c1751906e844161be201e960727ce2f6b272f..ee64fdecbda854381559c638e682d7d90e4a3518 100644 --- a/tests/qtest/libqos/pci.h +++ b/tests/qtest/libqos/pci.h @@ -14,7 +14,7 @@ #define LIBQOS_PCI_H #include "libqtest.h" -#include "libqos/qgraph.h" +#include "qgraph.h" #define QPCI_PIO_LIMIT 0x10000 diff --git a/tests/qtest/libqos/ppc64_pseries-machine.c b/tests/qtest/libqos/ppc64_pseries-machine.c index 867f27a3c81279ac593372a7abece2cea18b7120..24ca1799765f382eef46e61996b68dffec96e352 100644 --- a/tests/qtest/libqos/ppc64_pseries-machine.c +++ b/tests/qtest/libqos/ppc64_pseries-machine.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -18,10 +18,10 @@ #include "qemu/osdep.h" #include "libqtest.h" -#include "libqos/qgraph.h" +#include "qgraph.h" #include "pci-spapr.h" #include "qemu/module.h" -#include "libqos/malloc-spapr.h" +#include "malloc-spapr.h" typedef struct QSPAPR_pci_host QSPAPR_pci_host; typedef struct Qppc64_pseriesMachine Qppc64_pseriesMachine; diff --git a/tests/qtest/libqos/qgraph.c b/tests/qtest/libqos/qgraph.c index ca01de07437b50202605dcd5d61d17f5d88437e8..fc49cfa8794e442440eb396f6a1e03fc4f053bbe 100644 --- a/tests/qtest/libqos/qgraph.c +++ b/tests/qtest/libqos/qgraph.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,8 +19,8 @@ #include "qemu/osdep.h" #include "libqtest.h" #include "qemu/queue.h" -#include "libqos/qgraph_internal.h" -#include "libqos/qgraph.h" +#include "qgraph_internal.h" +#include "qgraph.h" #define QGRAPH_PRINT_DEBUG 0 #define QOS_ROOT "" diff --git a/tests/qtest/libqos/qgraph.h b/tests/qtest/libqos/qgraph.h index 3a25dda4b26c82297a0195601b61229a5b3f7e29..5f63d352ca32ecbd8d3f7a1e3aaa890a4b967085 100644 --- a/tests/qtest/libqos/qgraph.h +++ b/tests/qtest/libqos/qgraph.h @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -106,7 +106,7 @@ typedef void *(*QOSBeforeTest) (GString *cmd_line, void *arg); * * Creating new driver an its interface * - #include "libqos/qgraph.h" + #include "qgraph.h" struct My_driver { QOSGraphObject obj; @@ -190,7 +190,7 @@ typedef void *(*QOSBeforeTest) (GString *cmd_line, void *arg); * * Creating new test * - * #include "libqos/qgraph.h" + * #include "qgraph.h" * * static void my_test_function(void *obj, void *data) * { @@ -226,11 +226,11 @@ typedef void *(*QOSBeforeTest) (GString *cmd_line, void *arg); * my_test <--consumed_by-- my_interface <--produces--+ * * Assuming there the binary is - * QTEST_QEMU_BINARY=x86_64-softmmu/qemu-system-x86_64 + * QTEST_QEMU_BINARY=./qemu-system-x86_64 * a valid test path will be: * "/x86_64/pc/other_node/my_driver/my_interface/my_test". * - * Additional examples are also in libqos/test-qgraph.c + * Additional examples are also in test-qgraph.c * * Command line: * Command line is built by using node names and optional arguments diff --git a/tests/qtest/libqos/qgraph_internal.h b/tests/qtest/libqos/qgraph_internal.h index f4734c8681f316cccb63c2019e495d80c397ad51..968fa6945096c1d8f32fe5886bcdb47cb5d817c1 100644 --- a/tests/qtest/libqos/qgraph_internal.h +++ b/tests/qtest/libqos/qgraph_internal.h @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,11 +20,11 @@ #define QGRAPH_INTERNAL_H /* This header is declaring additional helper functions defined in - * libqos/qgraph.c + * qgraph.c * It should not be included in tests */ -#include "libqos/qgraph.h" +#include "qgraph.h" typedef struct QOSGraphMachine QOSGraphMachine; typedef enum QOSEdgeType QOSEdgeType; diff --git a/tests/qtest/libqos/qos_external.c b/tests/qtest/libqos/qos_external.c index 9f5180e18d2c699cab324e531b66a378790b6f32..10ee0f75b288dc0f270e94a321514323ed1804bf 100644 --- a/tests/qtest/libqos/qos_external.c +++ b/tests/qtest/libqos/qos_external.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -24,10 +24,10 @@ #include "qapi/qmp/qstring.h" #include "qemu/module.h" #include "qapi/qmp/qlist.h" -#include "libqos/malloc.h" -#include "libqos/qgraph.h" -#include "libqos/qgraph_internal.h" -#include "libqos/qos_external.h" +#include "malloc.h" +#include "qgraph.h" +#include "qgraph_internal.h" +#include "qos_external.h" static void machine_apply_to_node(const char *name) { diff --git a/tests/qtest/libqos/qos_external.h b/tests/qtest/libqos/qos_external.h index 72d7f91707e9176383a75c0fc70ee14c58c14a21..8446e3df0b1ceacab01a4fdb186813771d1ea06f 100644 --- a/tests/qtest/libqos/qos_external.h +++ b/tests/qtest/libqos/qos_external.h @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,7 +19,9 @@ #ifndef QOS_EXTERNAL_H #define QOS_EXTERNAL_H -#include "libqos/malloc.h" +#include "qgraph.h" + +#include "malloc.h" #include "qapi/qapi-types-machine.h" #include "qapi/qapi-types-qom.h" diff --git a/tests/qtest/libqos/rtas.c b/tests/qtest/libqos/rtas.c index d81ff4274da0a906e6e4bbb94d73f14e85ca636e..db29d5554dcb51b1d15f315c989125ba1c0440a8 100644 --- a/tests/qtest/libqos/rtas.c +++ b/tests/qtest/libqos/rtas.c @@ -5,7 +5,7 @@ #include "qemu/osdep.h" #include "libqtest.h" -#include "libqos/rtas.h" +#include "rtas.h" static void qrtas_copy_args(QTestState *qts, uint64_t target_args, uint32_t nargs, uint32_t *args) diff --git a/tests/qtest/libqos/rtas.h b/tests/qtest/libqos/rtas.h index 459e23aaf4d02163f811c4d572b84f899b3cd1e5..f38f99dfab84533f47e760b7b8d0f149b5a05802 100644 --- a/tests/qtest/libqos/rtas.h +++ b/tests/qtest/libqos/rtas.h @@ -5,7 +5,7 @@ #ifndef LIBQOS_RTAS_H #define LIBQOS_RTAS_H -#include "libqos/malloc.h" +#include "malloc.h" int qrtas_get_time_of_day(QTestState *qts, QGuestAllocator *alloc, struct tm *tm, uint32_t *ns); diff --git a/tests/qtest/libqos/sdhci.c b/tests/qtest/libqos/sdhci.c index 309794bc52036e83ee56eecb0c8b979ac918e7b2..65f0d07fc5ace15f99f536b7db5e5ab5d9d0ac45 100644 --- a/tests/qtest/libqos/sdhci.c +++ b/tests/qtest/libqos/sdhci.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -18,7 +18,7 @@ #include "qemu/osdep.h" #include "libqtest.h" -#include "libqos/qgraph.h" +#include "qgraph.h" #include "pci.h" #include "qemu/module.h" #include "sdhci.h" diff --git a/tests/qtest/libqos/sdhci.h b/tests/qtest/libqos/sdhci.h index a88b45ae9de079362848976a2d21d16e07198cc6..22d647b1fd51fd06c485c386574bf5abe716e1fb 100644 --- a/tests/qtest/libqos/sdhci.h +++ b/tests/qtest/libqos/sdhci.h @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,7 +19,7 @@ #ifndef QGRAPH_QSDHCI_H #define QGRAPH_QSDHCI_H -#include "libqos/qgraph.h" +#include "qgraph.h" #include "pci.h" typedef struct QSDHCI QSDHCI; diff --git a/tests/qtest/libqos/tpci200.c b/tests/qtest/libqos/tpci200.c index ae590a456ec60e24857091d6ef1d537e6ea40e95..1787b1f188d3d8213aa3b939e6c5eefc2cdb2da9 100644 --- a/tests/qtest/libqos/tpci200.c +++ b/tests/qtest/libqos/tpci200.c @@ -10,8 +10,8 @@ #include "qemu/osdep.h" #include "libqtest.h" #include "qemu/module.h" -#include "libqos/qgraph.h" -#include "libqos/pci.h" +#include "qgraph.h" +#include "pci.h" typedef struct QTpci200 QTpci200; typedef struct QIpack QIpack; diff --git a/tests/qtest/libqos/usb.c b/tests/qtest/libqos/usb.c index d7a9cb3c72a4febd05d03e705f4b9f7da62d5b14..8b45b0298446a1f861f72ac6890cdc39b8d4ef94 100644 --- a/tests/qtest/libqos/usb.c +++ b/tests/qtest/libqos/usb.c @@ -14,7 +14,7 @@ #include "qemu/osdep.h" #include "libqtest.h" #include "hw/usb/uhci-regs.h" -#include "libqos/usb.h" +#include "usb.h" void qusb_pci_init_one(QPCIBus *pcibus, struct qhc *hc, uint32_t devfn, int bar) { diff --git a/tests/qtest/libqos/usb.h b/tests/qtest/libqos/usb.h index eeced39a2f9f06a4e523548e43f2f18c3fe9d90d..50030d7fb112db4e7991793976928d58262b1dc2 100644 --- a/tests/qtest/libqos/usb.h +++ b/tests/qtest/libqos/usb.h @@ -1,7 +1,7 @@ #ifndef LIBQOS_USB_H #define LIBQOS_USB_H -#include "libqos/pci-pc.h" +#include "pci-pc.h" struct qhc { QPCIDevice *dev; diff --git a/tests/qtest/libqos/virtio-9p.c b/tests/qtest/libqos/virtio-9p.c index 77dbfb62ad6acc3860f09c9d3c6094735cf89caf..be91662c6f04b05aa738d9a0aab8a16efcfb0e4a 100644 --- a/tests/qtest/libqos/virtio-9p.c +++ b/tests/qtest/libqos/virtio-9p.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,10 +20,66 @@ #include "libqtest.h" #include "qemu/module.h" #include "standard-headers/linux/virtio_ids.h" -#include "libqos/virtio-9p.h" -#include "libqos/qgraph.h" +#include "virtio-9p.h" +#include "qgraph.h" static QGuestAllocator *alloc; +static char *local_test_path; + +/* Concatenates the passed 2 pathes. Returned result must be freed. */ +static char *concat_path(const char* a, const char* b) +{ + return g_build_filename(a, b, NULL); +} + +static void init_local_test_path(void) +{ + char *pwd = g_get_current_dir(); + char *template = concat_path(pwd, "qtest-9p-local-XXXXXX"); + local_test_path = mkdtemp(template); + if (!local_test_path) { + g_test_message("mkdtemp('%s') failed: %s", template, strerror(errno)); + } + g_assert(local_test_path); + g_free(pwd); +} + +void virtio_9p_create_local_test_dir(void) +{ + struct stat st; + int res; + + init_local_test_path(); + + g_assert(local_test_path != NULL); + res = mkdir(local_test_path, 0777); + if (res < 0) { + g_test_message("mkdir('%s') failed: %s", local_test_path, + strerror(errno)); + } + + /* ensure test directory exists now ... */ + g_assert(stat(local_test_path, &st) == 0); + /* ... and is actually a directory */ + g_assert((st.st_mode & S_IFMT) == S_IFDIR); +} + +void virtio_9p_remove_local_test_dir(void) +{ + g_assert(local_test_path != NULL); + char *cmd = g_strdup_printf("rm -fr '%s'\n", local_test_path); + int res = system(cmd); + if (res < 0) { + /* ignore error, dummy check to prevent compiler error */ + } + g_free(cmd); +} + +char *virtio_9p_test_path(const char *path) +{ + g_assert(local_test_path); + return concat_path(local_test_path, path); +} static void virtio_9p_cleanup(QVirtio9P *interface) { @@ -146,6 +202,55 @@ static void *virtio_9p_pci_create(void *pci_bus, QGuestAllocator *t_alloc, return obj; } +/** + * Performs regular expression based search and replace on @a haystack. + * + * @param haystack - input string to be parsed, result of replacement is + * stored back to @a haystack + * @param pattern - the regular expression pattern for scanning @a haystack + * @param replace_fmt - matches of supplied @a pattern are replaced by this, + * if necessary glib printf format can be used to add + * variable arguments of this function to this + * replacement string + */ +static void regex_replace(GString *haystack, const char *pattern, + const char *replace_fmt, ...) +{ + GRegex *regex; + char *replace, *s; + va_list argp; + + va_start(argp, replace_fmt); + replace = g_strdup_vprintf(replace_fmt, argp); + va_end(argp); + + regex = g_regex_new(pattern, 0, 0, NULL); + s = g_regex_replace(regex, haystack->str, -1, 0, replace, 0, NULL); + g_string_assign(haystack, s); + g_free(s); + g_regex_unref(regex); + g_free(replace); +} + +void virtio_9p_assign_local_driver(GString *cmd_line, const char *args) +{ + g_assert_nonnull(local_test_path); + + /* replace 'synth' driver by 'local' driver */ + regex_replace(cmd_line, "-fsdev synth,", "-fsdev local,"); + + /* append 'path=...' to '-fsdev ...' group */ + regex_replace(cmd_line, "(-fsdev \\w[^ ]*)", "\\1,path='%s'", + local_test_path); + + if (!args) { + return; + } + + /* append passed args to '-fsdev ...' group */ + regex_replace(cmd_line, "(-fsdev \\w[^ ]*)", "\\1,%s", args); +} + static void virtio_9p_register_nodes(void) { const char *str_simple = "fsdev=fsdev0,mount_tag=" MOUNT_TAG; diff --git a/tests/qtest/libqos/virtio-9p.h b/tests/qtest/libqos/virtio-9p.h index b54e89b3a1d94b314109eae9eaa4fea0458a9d55..480727120ea371f3ed51b9a1d4ab04bc791fede7 100644 --- a/tests/qtest/libqos/virtio-9p.h +++ b/tests/qtest/libqos/virtio-9p.h @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,9 +19,9 @@ #ifndef TESTS_LIBQOS_VIRTIO_9P_H #define TESTS_LIBQOS_VIRTIO_9P_H -#include "libqos/qgraph.h" -#include "libqos/virtio.h" -#include "libqos/virtio-pci.h" +#include "qgraph.h" +#include "virtio.h" +#include "virtio-pci.h" typedef struct QVirtio9P QVirtio9P; typedef struct QVirtio9PPCI QVirtio9PPCI; @@ -44,4 +44,24 @@ struct QVirtio9PDevice { QVirtio9P v9p; }; +/** + * Creates the directory for the 9pfs 'local' filesystem driver to access. + */ +void virtio_9p_create_local_test_dir(void); + +/** + * Deletes directory previously created by virtio_9p_create_local_test_dir(). + */ +void virtio_9p_remove_local_test_dir(void); + +/** + * Prepares QEMU command line for 9pfs tests using the 'local' fs driver. + */ +void virtio_9p_assign_local_driver(GString *cmd_line, const char *args); + +/** + * Returns path on host to the passed guest path. Result must be freed. + */ +char *virtio_9p_test_path(const char *path); + #endif diff --git a/tests/qtest/libqos/virtio-balloon.c b/tests/qtest/libqos/virtio-balloon.c index 42a4c5831eada619f3c010288ed757be56a48ae0..a3da5c234d49753fedc77e3288ac1f92d470cc8f 100644 --- a/tests/qtest/libqos/virtio-balloon.c +++ b/tests/qtest/libqos/virtio-balloon.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,8 +19,8 @@ #include "qemu/osdep.h" #include "libqtest.h" #include "qemu/module.h" -#include "libqos/qgraph.h" -#include "libqos/virtio-balloon.h" +#include "qgraph.h" +#include "virtio-balloon.h" /* virtio-balloon-device */ static void *qvirtio_balloon_get_driver(QVirtioBalloon *v_balloon, diff --git a/tests/qtest/libqos/virtio-balloon.h b/tests/qtest/libqos/virtio-balloon.h index 52661cc87dbaca6776085a5933f2425c1e432c60..309894c338c6b097f66c269b051733413f85142f 100644 --- a/tests/qtest/libqos/virtio-balloon.h +++ b/tests/qtest/libqos/virtio-balloon.h @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,9 +19,9 @@ #ifndef TESTS_LIBQOS_VIRTIO_BALLOON_H #define TESTS_LIBQOS_VIRTIO_BALLOON_H -#include "libqos/qgraph.h" -#include "libqos/virtio.h" -#include "libqos/virtio-pci.h" +#include "qgraph.h" +#include "virtio.h" +#include "virtio-pci.h" typedef struct QVirtioBalloon QVirtioBalloon; typedef struct QVirtioBalloonPCI QVirtioBalloonPCI; diff --git a/tests/qtest/libqos/virtio-blk.c b/tests/qtest/libqos/virtio-blk.c index 726e93c5c1e7ae226f593827a31fb0a4d6c07b53..5da02591bcc2c2889b195242231dd4c2dae38da3 100644 --- a/tests/qtest/libqos/virtio-blk.c +++ b/tests/qtest/libqos/virtio-blk.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,8 +20,8 @@ #include "libqtest.h" #include "qemu/module.h" #include "standard-headers/linux/virtio_blk.h" -#include "libqos/qgraph.h" -#include "libqos/virtio-blk.h" +#include "qgraph.h" +#include "virtio-blk.h" #define PCI_SLOT 0x04 #define PCI_FN 0x00 diff --git a/tests/qtest/libqos/virtio-blk.h b/tests/qtest/libqos/virtio-blk.h index c05adc659d7a7aed994f770f27acb58b3311e7ea..dcef38851ea141f65c3ca43512268cab7c95ab2d 100644 --- a/tests/qtest/libqos/virtio-blk.h +++ b/tests/qtest/libqos/virtio-blk.h @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,9 +19,9 @@ #ifndef TESTS_LIBQOS_VIRTIO_BLK_H #define TESTS_LIBQOS_VIRTIO_BLK_H -#include "libqos/qgraph.h" -#include "libqos/virtio.h" -#include "libqos/virtio-pci.h" +#include "qgraph.h" +#include "virtio.h" +#include "virtio-pci.h" typedef struct QVirtioBlk QVirtioBlk; typedef struct QVirtioBlkPCI QVirtioBlkPCI; diff --git a/tests/qtest/libqos/virtio-mmio.c b/tests/qtest/libqos/virtio-mmio.c index e0a2bd7bc631609eab1cd79e419d85809fa95328..75efda30299aab163ad30c162eb6009406cda192 100644 --- a/tests/qtest/libqos/virtio-mmio.c +++ b/tests/qtest/libqos/virtio-mmio.c @@ -10,10 +10,10 @@ #include "qemu/osdep.h" #include "libqtest.h" #include "qemu/module.h" -#include "libqos/virtio.h" -#include "libqos/virtio-mmio.h" -#include "libqos/malloc.h" -#include "libqos/qgraph.h" +#include "virtio.h" +#include "virtio-mmio.h" +#include "malloc.h" +#include "qgraph.h" #include "standard-headers/linux/virtio_ring.h" static uint8_t qvirtio_mmio_config_readb(QVirtioDevice *d, uint64_t off) diff --git a/tests/qtest/libqos/virtio-mmio.h b/tests/qtest/libqos/virtio-mmio.h index 0e45778b07def98adf3998b5bbba3c4d12d0627d..30803bc91cec5427f8006f42ad6977fb927efa79 100644 --- a/tests/qtest/libqos/virtio-mmio.h +++ b/tests/qtest/libqos/virtio-mmio.h @@ -10,8 +10,8 @@ #ifndef LIBQOS_VIRTIO_MMIO_H #define LIBQOS_VIRTIO_MMIO_H -#include "libqos/virtio.h" -#include "libqos/qgraph.h" +#include "virtio.h" +#include "qgraph.h" #define QVIRTIO_MMIO_MAGIC_VALUE 0x000 #define QVIRTIO_MMIO_VERSION 0x004 diff --git a/tests/qtest/libqos/virtio-net.c b/tests/qtest/libqos/virtio-net.c index 710d440c3d482344e2ca9290ba6132e3cd6e6743..1cae07f60d6cb588cbebb94c73d8f6f9510a8b15 100644 --- a/tests/qtest/libqos/virtio-net.c +++ b/tests/qtest/libqos/virtio-net.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,8 +19,8 @@ #include "qemu/osdep.h" #include "libqtest.h" #include "qemu/module.h" -#include "libqos/qgraph.h" -#include "libqos/virtio-net.h" +#include "qgraph.h" +#include "virtio-net.h" #include "hw/virtio/virtio-net.h" diff --git a/tests/qtest/libqos/virtio-net.h b/tests/qtest/libqos/virtio-net.h index 855c67d00f83f9e8f89ce26af71e8d18c81e2748..5ba2161de27adac77cd6f30f3a4893ad8d096a7a 100644 --- a/tests/qtest/libqos/virtio-net.h +++ b/tests/qtest/libqos/virtio-net.h @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,9 +19,9 @@ #ifndef TESTS_LIBQOS_VIRTIO_NET_H #define TESTS_LIBQOS_VIRTIO_NET_H -#include "libqos/qgraph.h" -#include "libqos/virtio.h" -#include "libqos/virtio-pci.h" +#include "qgraph.h" +#include "virtio.h" +#include "virtio-pci.h" typedef struct QVirtioNet QVirtioNet; typedef struct QVirtioNetPCI QVirtioNetPCI; diff --git a/tests/qtest/libqos/virtio-pci.c b/tests/qtest/libqos/virtio-pci.c index 62851c29bb2a5b1a1f0775025f18e1fb7f2164f7..cd3c0f5bf33518ddb9dba995a9a8ada58f98001e 100644 --- a/tests/qtest/libqos/virtio-pci.c +++ b/tests/qtest/libqos/virtio-pci.c @@ -9,13 +9,13 @@ #include "qemu/osdep.h" #include "libqtest.h" -#include "libqos/virtio.h" -#include "libqos/virtio-pci.h" -#include "libqos/pci.h" -#include "libqos/pci-pc.h" -#include "libqos/malloc.h" -#include "libqos/malloc-pc.h" -#include "libqos/qgraph.h" +#include "virtio.h" +#include "virtio-pci.h" +#include "pci.h" +#include "pci-pc.h" +#include "malloc.h" +#include "malloc-pc.h" +#include "qgraph.h" #include "standard-headers/linux/virtio_ring.h" #include "standard-headers/linux/virtio_pci.h" diff --git a/tests/qtest/libqos/virtio-pci.h b/tests/qtest/libqos/virtio-pci.h index 294d5567eebccecbf9a3b7de30376016e39ef070..f5115cacba2b94a6e0b8d5e14cc1d34239edf07a 100644 --- a/tests/qtest/libqos/virtio-pci.h +++ b/tests/qtest/libqos/virtio-pci.h @@ -10,9 +10,9 @@ #ifndef LIBQOS_VIRTIO_PCI_H #define LIBQOS_VIRTIO_PCI_H -#include "libqos/virtio.h" -#include "libqos/pci.h" -#include "libqos/qgraph.h" +#include "virtio.h" +#include "pci.h" +#include "qgraph.h" typedef struct QVirtioPCIMSIXOps QVirtioPCIMSIXOps; diff --git a/tests/qtest/libqos/virtio-rng.c b/tests/qtest/libqos/virtio-rng.c index b86349e2fd1b7b0898134af9cf5998e574a95967..2e09dd7c48cb2669ab1df06df26d37acc5b185b4 100644 --- a/tests/qtest/libqos/virtio-rng.c +++ b/tests/qtest/libqos/virtio-rng.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,8 +19,8 @@ #include "qemu/osdep.h" #include "libqtest.h" #include "qemu/module.h" -#include "libqos/qgraph.h" -#include "libqos/virtio-rng.h" +#include "qgraph.h" +#include "virtio-rng.h" /* virtio-rng-device */ static void *qvirtio_rng_get_driver(QVirtioRng *v_rng, diff --git a/tests/qtest/libqos/virtio-rng.h b/tests/qtest/libqos/virtio-rng.h index 9e192f11f727c0c424168cfe4d3e9d9608dc2ab3..9ca102b59938ebb56d752f4a93916f7dc9a7d045 100644 --- a/tests/qtest/libqos/virtio-rng.h +++ b/tests/qtest/libqos/virtio-rng.h @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,9 +19,9 @@ #ifndef TESTS_LIBQOS_VIRTIO_RNG_H #define TESTS_LIBQOS_VIRTIO_RNG_H -#include "libqos/qgraph.h" -#include "libqos/virtio.h" -#include "libqos/virtio-pci.h" +#include "qgraph.h" +#include "virtio.h" +#include "virtio-pci.h" typedef struct QVirtioRng QVirtioRng; typedef struct QVirtioRngPCI QVirtioRngPCI; diff --git a/tests/qtest/libqos/virtio-scsi.c b/tests/qtest/libqos/virtio-scsi.c index de739bec5f39736fa5a0426501a9fa91a02af602..5644e32fc3194df341f6c11bfe0a865be38c6214 100644 --- a/tests/qtest/libqos/virtio-scsi.c +++ b/tests/qtest/libqos/virtio-scsi.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,8 +20,8 @@ #include "libqtest.h" #include "qemu/module.h" #include "standard-headers/linux/virtio_ids.h" -#include "libqos/qgraph.h" -#include "libqos/virtio-scsi.h" +#include "qgraph.h" +#include "virtio-scsi.h" /* virtio-scsi-device */ static void *qvirtio_scsi_get_driver(QVirtioSCSI *v_scsi, diff --git a/tests/qtest/libqos/virtio-scsi.h b/tests/qtest/libqos/virtio-scsi.h index 4ca19a6a7ac4efa31a397047c26dcd5157b21c8d..531315e6ad466ae64da6ee685c7dbba00677c2e5 100644 --- a/tests/qtest/libqos/virtio-scsi.h +++ b/tests/qtest/libqos/virtio-scsi.h @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,9 +19,9 @@ #ifndef TESTS_LIBQOS_VIRTIO_SCSI_H #define TESTS_LIBQOS_VIRTIO_SCSI_H -#include "libqos/qgraph.h" -#include "libqos/virtio.h" -#include "libqos/virtio-pci.h" +#include "qgraph.h" +#include "virtio.h" +#include "virtio-pci.h" typedef struct QVirtioSCSI QVirtioSCSI; typedef struct QVirtioSCSIPCI QVirtioSCSIPCI; diff --git a/tests/qtest/libqos/virtio-serial.c b/tests/qtest/libqos/virtio-serial.c index 3e5b8b82c743235c92f1798e0ed56cddf882546c..ee34afd95ad8078217443ee3526e8500e95b3992 100644 --- a/tests/qtest/libqos/virtio-serial.c +++ b/tests/qtest/libqos/virtio-serial.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,8 +19,8 @@ #include "qemu/osdep.h" #include "libqtest.h" #include "qemu/module.h" -#include "libqos/qgraph.h" -#include "libqos/virtio-serial.h" +#include "qgraph.h" +#include "virtio-serial.h" static void *qvirtio_serial_get_driver(QVirtioSerial *v_serial, const char *interface) diff --git a/tests/qtest/libqos/virtio-serial.h b/tests/qtest/libqos/virtio-serial.h index 080fa8428d9fd163a2a7cb18e0b007bbc414dd6c..3db43b2bb8807433d5563a57edc98881ee9a9d62 100644 --- a/tests/qtest/libqos/virtio-serial.h +++ b/tests/qtest/libqos/virtio-serial.h @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,9 +19,9 @@ #ifndef TESTS_LIBQOS_VIRTIO_SERIAL_H #define TESTS_LIBQOS_VIRTIO_SERIAL_H -#include "libqos/qgraph.h" -#include "libqos/virtio.h" -#include "libqos/virtio-pci.h" +#include "qgraph.h" +#include "virtio.h" +#include "virtio-pci.h" typedef struct QVirtioSerial QVirtioSerial; typedef struct QVirtioSerialPCI QVirtioSerialPCI; diff --git a/tests/qtest/libqos/virtio.c b/tests/qtest/libqos/virtio.c index 9aa360620c19b413a35b55ee1ad23ee8184ef1ca..6fe7bf9555fca71326ec3b9b3707e71ad36e8c67 100644 --- a/tests/qtest/libqos/virtio.c +++ b/tests/qtest/libqos/virtio.c @@ -10,7 +10,7 @@ #include "qemu/osdep.h" #include "qemu/bswap.h" #include "libqtest.h" -#include "libqos/virtio.h" +#include "virtio.h" #include "standard-headers/linux/virtio_config.h" #include "standard-headers/linux/virtio_ring.h" diff --git a/tests/qtest/libqos/virtio.h b/tests/qtest/libqos/virtio.h index 529ef7555a224603427ede985c0f7fdd5499419e..b8bd06e1b85118dfc83472fb389139aa414e3b2a 100644 --- a/tests/qtest/libqos/virtio.h +++ b/tests/qtest/libqos/virtio.h @@ -10,7 +10,7 @@ #ifndef LIBQOS_VIRTIO_H #define LIBQOS_VIRTIO_H -#include "libqos/malloc.h" +#include "malloc.h" #include "standard-headers/linux/virtio_ring.h" #define QVIRTIO_F_BAD_FEATURE 0x40000000ull diff --git a/tests/qtest/libqos/x86_64_pc-machine.c b/tests/qtest/libqos/x86_64_pc-machine.c index 6dfa705217e6085d31d034bc7fcedab1345def42..ad96742a92d6f0f8fe804fd2ef9f118508cabbde 100644 --- a/tests/qtest/libqos/x86_64_pc-machine.c +++ b/tests/qtest/libqos/x86_64_pc-machine.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -18,7 +18,7 @@ #include "qemu/osdep.h" #include "libqtest.h" -#include "libqos/qgraph.h" +#include "qgraph.h" #include "pci-pc.h" #include "qemu/module.h" #include "malloc-pc.h" diff --git a/tests/qtest/libqtest-single.h b/tests/qtest/libqtest-single.h index 6f1bb1331c5217763d5d49e5d707103ea2fc3b39..0d7f568678e5ff01349ca3480db46d37795a6a76 100644 --- a/tests/qtest/libqtest-single.h +++ b/tests/qtest/libqtest-single.h @@ -11,7 +11,7 @@ #ifndef LIBQTEST_SINGLE_H #define LIBQTEST_SINGLE_H -#include "libqtest.h" +#include "libqos/libqtest.h" QTestState *global_qtest __attribute__((common, weak)); @@ -47,7 +47,7 @@ static inline void qtest_end(void) /** * qmp: * @fmt...: QMP message to send to qemu, formatted like - * qobject_from_jsonf_nofail(). See parse_escape() for what's + * qobject_from_jsonf_nofail(). See parse_interpolation() for what's * supported after '%'. * * Sends a QMP message to QEMU and returns the response. diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c index 49075b55a1bef556f66fa6466af9a5797487d95f..e49f3a1e45f4cd96279241fdb2bbe231029ab922 100644 --- a/tests/qtest/libqtest.c +++ b/tests/qtest/libqtest.c @@ -20,7 +20,7 @@ #include #include -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu-common.h" #include "qemu/ctype.h" #include "qemu/cutils.h" @@ -63,6 +63,7 @@ struct QTestState bool irq_level[MAX_IRQ]; GString *rx; QTestTransportOps ops; + GList *pending_events; }; static GHookList abrt_hooks; @@ -109,8 +110,13 @@ static int socket_accept(int sock) struct timeval timeout = { .tv_sec = SOCKET_TIMEOUT, .tv_usec = 0 }; - setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (void *)&timeout, - sizeof(timeout)); + if (qemu_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, + (void *)&timeout, sizeof(timeout))) { + fprintf(stderr, "%s failed to set SO_RCVTIMEO: %s\n", + __func__, strerror(errno)); + close(sock); + return -1; + } do { addrlen = sizeof(addr); @@ -279,6 +285,7 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args) g_test_message("starting QEMU: %s", command); + s->pending_events = NULL; s->wstatus = 0; s->expected_status = 0; s->qemu_pid = fork(); @@ -386,6 +393,13 @@ void qtest_quit(QTestState *s) close(s->fd); close(s->qmp_fd); g_string_free(s->rx, true); + + for (GList *it = s->pending_events; it != NULL; it = it->next) { + qobject_unref((QDict *)it->data); + } + + g_list_free(s->pending_events); + g_free(s); } @@ -531,6 +545,7 @@ redo: } } else { g_strfreev(words); + words = NULL; } return words; @@ -604,6 +619,19 @@ QDict *qmp_fd_receive(int fd) } QDict *qtest_qmp_receive(QTestState *s) +{ + while (true) { + QDict *response = qtest_qmp_receive_dict(s); + + if (!qdict_get_try_str(response, "event")) { + return response; + } + /* Stash the event for a later consumption */ + s->pending_events = g_list_append(s->pending_events, response); + } +} + +QDict *qtest_qmp_receive_dict(QTestState *s) { return qmp_fd_receive(s->qmp_fd); } @@ -771,12 +799,33 @@ void qtest_qmp_send_raw(QTestState *s, const char *fmt, ...) va_end(ap); } +QDict *qtest_qmp_event_ref(QTestState *s, const char *event) +{ + while (s->pending_events) { + + GList *first = s->pending_events; + QDict *response = (QDict *)first->data; + + s->pending_events = g_list_delete_link(s->pending_events, first); + + if (!strcmp(qdict_get_str(response, "event"), event)) { + return response; + } + qobject_unref(response); + } + return NULL; +} + QDict *qtest_qmp_eventwait_ref(QTestState *s, const char *event) { - QDict *response; + QDict *response = qtest_qmp_event_ref(s, event); + + if (response) { + return response; + } for (;;) { - response = qtest_qmp_receive(s); + response = qtest_qmp_receive_dict(s); if ((qdict_haskey(response, "event")) && (strcmp(qdict_get_str(response, "event"), event) == 0)) { return response; @@ -804,12 +853,6 @@ char *qtest_vhmp(QTestState *s, const char *fmt, va_list ap) " 'arguments': {'command-line': %s}}", cmd); ret = g_strdup(qdict_get_try_str(resp, "return")); - while (ret == NULL && qdict_get_try_str(resp, "event")) { - /* Ignore asynchronous QMP events */ - qobject_unref(resp); - resp = qtest_qmp_receive(s); - ret = g_strdup(qdict_get_try_str(resp, "return")); - } g_assert(ret); qobject_unref(resp); g_free(cmd); @@ -830,9 +873,14 @@ char *qtest_hmp(QTestState *s, const char *fmt, ...) const char *qtest_get_arch(void) { const char *qemu = qtest_qemu_binary(); - const char *end = strrchr(qemu, '/'); + const char *end = strrchr(qemu, '-'); - return end + strlen("/qemu-system-"); + if (!end) { + fprintf(stderr, "Can't determine architecture from binary name.\n"); + abort(); + } + + return end + 1; } bool qtest_get_irq(QTestState *s, int num) @@ -1232,6 +1280,10 @@ void qtest_cb_for_every_machine(void (*cb)(const char *machine), qstr = qobject_to(QString, qobj); g_assert(qstr); mname = qstring_get_str(qstr); + /* Ignore machines that cannot be used for qtests */ + if (!memcmp("xenfv", mname, 5) || g_str_equal("xenpv", mname)) { + continue; + } if (!skip_old_versioned || !qtest_is_old_versioned_machine(mname)) { cb(mname); } @@ -1241,35 +1293,6 @@ void qtest_cb_for_every_machine(void (*cb)(const char *machine), qobject_unref(response); } -QDict *qtest_qmp_receive_success(QTestState *s, - void (*event_cb)(void *opaque, - const char *event, - QDict *data), - void *opaque) -{ - QDict *response, *ret, *data; - const char *event; - - for (;;) { - response = qtest_qmp_receive(s); - g_assert(!qdict_haskey(response, "error")); - ret = qdict_get_qdict(response, "return"); - if (ret) { - break; - } - event = qdict_get_str(response, "event"); - data = qdict_get_qdict(response, "data"); - if (event_cb) { - event_cb(opaque, event, data); - } - qobject_unref(response); - } - - qobject_ref(ret); - qobject_unref(response); - return ret; -} - /* * Generic hot-plugging test via the device_add QMP commands. */ @@ -1305,13 +1328,6 @@ void qtest_qmp_device_add(QTestState *qts, const char *driver, const char *id, qobject_unref(args); } -static void device_deleted_cb(void *opaque, const char *name, QDict *data) -{ - bool *got_event = opaque; - - g_assert_cmpstr(name, ==, "DEVICE_DELETED"); - *got_event = true; -} /* * Generic hot-unplugging test via the device_del QMP command. @@ -1328,24 +1344,17 @@ static void device_deleted_cb(void *opaque, const char *name, QDict *data) * and this one: * * {"return": {}} - * - * But the order of arrival may vary - so we've got to detect both. */ void qtest_qmp_device_del(QTestState *qts, const char *id) { - bool got_event = false; QDict *rsp; - qtest_qmp_send(qts, "{'execute': 'device_del', 'arguments': {'id': %s}}", - id); - rsp = qtest_qmp_receive_success(qts, device_deleted_cb, &got_event); + rsp = qtest_qmp(qts, "{'execute': 'device_del', 'arguments': {'id': %s}}", + id); + + g_assert(qdict_haskey(rsp, "return")); qobject_unref(rsp); - if (!got_event) { - rsp = qtest_qmp_receive(qts); - g_assert_cmpstr(qdict_get_try_str(rsp, "event"), - ==, "DEVICE_DELETED"); - qobject_unref(rsp); - } + qtest_qmp_eventwait(qts, "DEVICE_DELETED"); } bool qmp_rsp_is_err(QDict *rsp) @@ -1355,7 +1364,7 @@ bool qmp_rsp_is_err(QDict *rsp) return !!error; } -void qmp_assert_error_class(QDict *rsp, const char *class) +void qmp_expect_error_and_unref(QDict *rsp, const char *class) { QDict *error = qdict_get_qdict(rsp, "error"); @@ -1399,6 +1408,7 @@ QTestState *qtest_inproc_init(QTestState **s, bool log, const char* arch, { QTestState *qts; qts = g_new0(QTestState, 1); + qts->pending_events = NULL; *s = qts; /* Expose qts early on, since the query endianness relies on it */ qts->wstatus = 0; for (int i = 0; i < MAX_IRQ; i++) { diff --git a/tests/qtest/m48t59-test.c b/tests/qtest/m48t59-test.c index b94a1230f7fdf742102597f402e2ea894689320b..6db3234100a3b8a074b6b3667af453179f95fde0 100644 --- a/tests/qtest/m48t59-test.c +++ b/tests/qtest/m48t59-test.c @@ -14,7 +14,7 @@ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #define RTC_SECONDS 0x9 #define RTC_MINUTES 0xa diff --git a/tests/qtest/machine-none-test.c b/tests/qtest/machine-none-test.c index b52311ec2e3bcbe4184f426bfb8171a892a1bc8c..aab06b9fc2392e36f6031be86e3ca8dca6dd99b4 100644 --- a/tests/qtest/machine-none-test.c +++ b/tests/qtest/machine-none-test.c @@ -14,7 +14,7 @@ #include "qemu-common.h" #include "qemu/cutils.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qapi/qmp/qdict.h" @@ -27,14 +27,15 @@ static struct arch2cpu cpus_map[] = { /* tested targets list */ { "arm", "cortex-a15" }, { "aarch64", "cortex-a57" }, + { "avr", "avr6-avr-cpu" }, { "x86_64", "qemu64,apic-id=0" }, { "i386", "qemu32,apic-id=0" }, { "alpha", "ev67" }, { "cris", "crisv32" }, { "lm32", "lm32-full" }, { "m68k", "m5206" }, - /* FIXME: { "microblaze", "any" }, doesn't work with -M none -cpu any */ - /* FIXME: { "microblazeel", "any" }, doesn't work with -M none -cpu any */ + { "microblaze", "any" }, + { "microblazeel", "any" }, { "mips", "4Kc" }, { "mipsel", "I7200" }, { "mips64", "20Kc" }, @@ -54,8 +55,8 @@ static struct arch2cpu cpus_map[] = { { "xtensa", "dc233c" }, { "xtensaeb", "fsf" }, { "hppa", "hppa" }, - { "riscv64", "sifive-u54" }, - { "riscv32", "sifive-u34" }, + { "riscv64", "rv64" }, + { "riscv32", "rv32" }, { "rx", "rx62n" }, }; @@ -79,10 +80,8 @@ static void test_machine_cpu_cli(void) QTestState *qts; if (!cpu_model) { - if (!(!strcmp(arch, "microblaze") || !strcmp(arch, "microblazeel"))) { - fprintf(stderr, "WARNING: cpu name for target '%s' isn't defined," - " add it to cpus_map\n", arch); - } + fprintf(stderr, "WARNING: cpu name for target '%s' isn't defined," + " add it to cpus_map\n", arch); return; /* TODO: die here to force all targets have a test */ } qts = qtest_initf("-machine none -cpu '%s'", cpu_model); diff --git a/tests/qtest/megasas-test.c b/tests/qtest/megasas-test.c index d6796b9bd74df3a14ee539b26d0f02183c616113..eae70ff95f9c3942a784c165895aca9d6fe80d17 100644 --- a/tests/qtest/megasas-test.c +++ b/tests/qtest/megasas-test.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/bswap.h" #include "qemu/module.h" #include "libqos/qgraph.h" diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..c19f1c85034fd285167cd022505064afd7110842 --- /dev/null +++ b/tests/qtest/meson.build @@ -0,0 +1,267 @@ +# All QTests for now are POSIX-only, but the dependencies are +# really in libqtest, not in the testcases themselves. +if not config_host.has_key('CONFIG_POSIX') + subdir_done() +endif + +qtests_generic = [ + 'cdrom-test', + 'device-introspect-test', + 'machine-none-test', + 'qmp-test', + 'qmp-cmd-test', + 'qom-test', + 'test-hmp', + 'qos-test', +] +if config_host.has_key('CONFIG_MODULES') + qtests_generic += [ 'modules-test' ] +endif + +qtests_pci = \ + (config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : []) + \ + (config_all_devices.has_key('CONFIG_IVSHMEM_DEVICE') ? ['ivshmem-test'] : []) + +qtests_i386 = \ + (slirp.found() ? ['pxe-test', 'test-netfilter'] : []) + \ + (config_host.has_key('CONFIG_POSIX') ? ['test-filter-mirror'] : []) + \ + (have_tools ? ['ahci-test'] : []) + \ + (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \ + (config_all_devices.has_key('CONFIG_SGA') ? ['boot-serial-test'] : []) + \ + (config_all_devices.has_key('CONFIG_RTL8139_PCI') ? ['test-filter-redirector'] : []) + \ + (config_all_devices.has_key('CONFIG_ISA_IPMI_KCS') ? ['ipmi-kcs-test'] : []) + \ + (config_host.has_key('CONFIG_LINUX') and \ + config_all_devices.has_key('CONFIG_ISA_IPMI_BT') ? ['ipmi-bt-test'] : []) + \ + (config_all_devices.has_key('CONFIG_WDT_IB700') ? ['wdt_ib700-test'] : []) + \ + (config_all_devices.has_key('CONFIG_PVPANIC') ? ['pvpanic-test'] : []) + \ + (config_all_devices.has_key('CONFIG_HDA') ? ['intel-hda-test'] : []) + \ + (config_all_devices.has_key('CONFIG_I82801B11') ? ['i82801b11-test'] : []) + \ + (config_all_devices.has_key('CONFIG_IOH3420') ? ['ioh3420-test'] : []) + \ + (config_all_devices.has_key('CONFIG_USB_UHCI') ? ['usb-hcd-uhci-test'] : []) + \ + (config_all_devices.has_key('CONFIG_USB_UHCI') and \ + config_all_devices.has_key('CONFIG_USB_EHCI') ? ['usb-hcd-ehci-test'] : []) + \ + (config_all_devices.has_key('CONFIG_USB_XHCI_NEC') ? ['usb-hcd-xhci-test'] : []) + \ + (config_all_devices.has_key('CONFIG_TPM_CRB') ? ['tpm-crb-test'] : []) + \ + (config_all_devices.has_key('CONFIG_TPM_CRB') ? ['tpm-crb-swtpm-test'] : []) + \ + (config_all_devices.has_key('CONFIG_TPM_TIS_ISA') ? ['tpm-tis-test'] : []) + \ + (config_all_devices.has_key('CONFIG_TPM_TIS_ISA') ? ['tpm-tis-swtpm-test'] : []) + \ + (config_all_devices.has_key('CONFIG_RTL8139_PCI') ? ['rtl8139-test'] : []) + \ + qtests_pci + \ + ['fdc-test', + 'ide-test', + 'hd-geo-test', + 'boot-order-test', + 'bios-tables-test', + 'rtc-test', + 'i440fx-test', + 'fuzz-test', + 'fw_cfg-test', + 'device-plug-test', + 'drive_del-test', + 'tco-test', + 'cpu-plug-test', + 'q35-test', + 'vmgenid-test', + 'migration-test', + 'test-x86-cpuid-compat', + 'numa-test'] + +dbus_daemon = find_program('dbus-daemon', required: false) +if dbus_daemon.found() and config_host.has_key('GDBUS_CODEGEN') + # Temporarily disabled due to Patchew failures: + #qtests_i386 += ['dbus-vmstate-test'] + dbus_vmstate1 = custom_target('dbus-vmstate description', + output: ['dbus-vmstate1.h', 'dbus-vmstate1.c'], + input: files('dbus-vmstate1.xml'), + command: [config_host['GDBUS_CODEGEN'], + '@INPUT@', + '--interface-prefix', 'org.qemu', + '--generate-c-code', '@BASENAME@']).to_list() +else + dbus_vmstate1 = [] +endif + +qtests_x86_64 = qtests_i386 + +qtests_alpha = [ 'boot-serial-test' ] + \ + (config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : []) + +qtests_avr = [ 'boot-serial-test' ] + +qtests_hppa = [ 'boot-serial-test' ] + \ + (config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : []) + +qtests_m68k = [ 'boot-serial-test' ] +qtests_microblaze = [ 'boot-serial-test' ] +qtests_microblazeel = qtests_microblaze + +qtests_mips = \ + (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \ + (config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : []) + +qtests_mips64 = \ + (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \ + (config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : []) + +qtests_mips64el = \ + (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \ + (config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : []) + +qtests_moxie = [ 'boot-serial-test' ] + +qtests_ppc = \ + (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \ + (config_all_devices.has_key('CONFIG_M48T59') ? ['m48t59-test'] : []) + \ + ['boot-order-test', 'prom-env-test', 'boot-serial-test'] \ + +qtests_ppc64 = \ + (config_all_devices.has_key('CONFIG_PSERIES') ? ['device-plug-test'] : []) + \ + (config_all_devices.has_key('CONFIG_POWERNV') ? ['pnv-xscom-test'] : []) + \ + (config_all_devices.has_key('CONFIG_PSERIES') ? ['rtas-test'] : []) + \ + (slirp.found() ? ['pxe-test', 'test-netfilter'] : []) + \ + (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'] : []) + \ + (config_host.has_key('CONFIG_POSIX') ? ['test-filter-mirror'] : []) + \ + qtests_pci + ['migration-test', 'numa-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'] : []) + +qtests_sparc = ['prom-env-test', 'm48t59-test', 'boot-serial-test'] + +qtests_sparc64 = \ + (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \ + ['prom-env-test', 'boot-serial-test'] + +qtests_npcm7xx = \ + ['npcm7xx_gpio-test', + 'npcm7xx_rng-test', + 'npcm7xx_timer-test', + 'npcm7xx_watchdog_timer-test'] +qtests_arm = \ + (config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : []) + \ + (config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \ + ['arm-cpu-features', + 'microbit-test', + 'm25p80-test', + 'test-arm-mptimer', + 'boot-serial-test', + 'hexloader-test'] + +# TODO: once aarch64 TCG is fixed on ARM 32 bit host, make bios-tables-test unconditional +qtests_aarch64 = \ + (cpu != 'arm' ? ['bios-tables-test'] : []) + \ + (config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? ['tpm-tis-device-test'] : []) + \ + (config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? ['tpm-tis-device-swtpm-test'] : []) + \ + ['arm-cpu-features', + 'numa-test', + 'boot-serial-test', + 'migration-test'] + +qtests_s390x = \ + (slirp.found() ? ['pxe-test', 'test-netfilter'] : []) + \ + (config_host.has_key('CONFIG_POSIX') ? ['test-filter-mirror'] : []) + \ + (config_host.has_key('CONFIG_POSIX') ? ['test-filter-redirector'] : []) + \ + ['boot-serial-test', + 'drive_del-test', + 'device-plug-test', + 'virtio-ccw-test', + 'cpu-plug-test', + 'migration-test'] + +qos_test_ss = ss.source_set() +qos_test_ss.add( + 'ac97-test.c', + 'ds1338-test.c', + 'e1000-test.c', + 'e1000e-test.c', + 'eepro100-test.c', + 'es1370-test.c', + 'ipoctal232-test.c', + 'megasas-test.c', + 'ne2000-test.c', + 'tulip-test.c', + 'nvme-test.c', + 'pca9552-test.c', + 'pci-test.c', + 'pcnet-test.c', + 'sdhci-test.c', + 'spapr-phb-test.c', + 'tmp105-test.c', + 'usb-hcd-ohci-test.c', + 'virtio-test.c', + 'virtio-blk-test.c', + 'virtio-net-test.c', + 'virtio-rng-test.c', + 'virtio-scsi-test.c', + 'virtio-serial-test.c', + 'vmxnet3-test.c', +) +qos_test_ss.add(when: 'CONFIG_VIRTFS', if_true: files('virtio-9p-test.c')) +qos_test_ss.add(when: 'CONFIG_VHOST_USER', if_true: files('vhost-user-test.c')) + +tpmemu_files = ['tpm-emu.c', 'tpm-util.c', 'tpm-tests.c'] + +qtests = { + 'bios-tables-test': [io, 'boot-sector.c', 'acpi-utils.c', 'tpm-emu.c'], + 'cdrom-test': files('boot-sector.c'), + 'dbus-vmstate-test': files('migration-helpers.c') + dbus_vmstate1, + 'ivshmem-test': [rt, '../../contrib/ivshmem-server/ivshmem-server.c'], + 'migration-test': files('migration-helpers.c'), + 'pxe-test': files('boot-sector.c'), + 'qos-test': [chardev, io, qos_test_ss.apply(config_host, strict: false).sources()], + 'tpm-crb-swtpm-test': [io, tpmemu_files], + 'tpm-crb-test': [io, tpmemu_files], + 'tpm-tis-swtpm-test': [io, tpmemu_files, 'tpm-tis-util.c'], + 'tpm-tis-test': [io, tpmemu_files, 'tpm-tis-util.c'], + 'tpm-tis-device-swtpm-test': [io, tpmemu_files, 'tpm-tis-util.c'], + 'tpm-tis-device-test': [io, tpmemu_files, 'tpm-tis-util.c'], + 'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'), +} + +qtest_executables = {} +foreach dir : target_dirs + if not dir.endswith('-softmmu') + continue + endif + + target_base = dir.split('-')[0] + qtest_emulator = emulators['qemu-system-' + target_base] + target_qtests = get_variable('qtests_' + target_base, []) + qtests_generic + + test_deps = [] + qtest_env = environment() + if have_tools + qtest_env.set('QTEST_QEMU_IMG', './qemu-img') + test_deps += [qemu_img] + endif + qtest_env.set('G_TEST_DBUS_DAEMON', meson.source_root() / 'tests/dbus-vmstate-daemon.sh') + qtest_env.set('QTEST_QEMU_BINARY', './qemu-system-' + target_base) + + foreach test : target_qtests + # Executables are shared across targets, declare them only the first time we + # encounter them + if not qtest_executables.has_key(test) + src = [test + '.c'] + deps = [qemuutil, qos] + if test in qtests + # use a sourceset to quickly separate sources and deps + test_ss = ss.source_set() + test_ss.add(qtests[test]) + src += test_ss.all_sources() + deps += test_ss.all_dependencies() + endif + qtest_executables += { + test: executable(test, src, dependencies: deps) + } + endif + # FIXME: missing dependency on the emulator binary and qemu-img + test('qtest-@0@/@1@'.format(target_base, test), + qtest_executables[test], + depends: [test_deps, qtest_emulator], + env: qtest_env, + args: ['--tap', '-k'], + protocol: 'tap', + suite: ['qtest', 'qtest-' + target_base]) + endforeach +endforeach diff --git a/tests/qtest/microbit-test.c b/tests/qtest/microbit-test.c index 04e199ec33f452e990802fba6d7d559bfb6c1aa6..2b255579dfddf203d8f3a8b2e0de0f773adc19e5 100644 --- a/tests/qtest/microbit-test.c +++ b/tests/qtest/microbit-test.c @@ -16,7 +16,7 @@ #include "qemu/osdep.h" #include "exec/hwaddr.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "hw/arm/nrf51.h" #include "hw/char/nrf51_uart.h" diff --git a/tests/qtest/migration-helpers.c b/tests/qtest/migration-helpers.c index 516093b39a9e79f06a02ede440802ebe75729047..4ee26014b78322df9a04ad7be2c368726b9f19d8 100644 --- a/tests/qtest/migration-helpers.c +++ b/tests/qtest/migration-helpers.c @@ -17,10 +17,12 @@ bool got_stop; -static void stop_cb(void *opaque, const char *name, QDict *data) +static void check_stop_event(QTestState *who) { - if (!strcmp(name, "STOP")) { + QDict *event = qtest_qmp_event_ref(who, "STOP"); + if (event) { got_stop = true; + qobject_unref(event); } } @@ -30,12 +32,23 @@ static void stop_cb(void *opaque, const char *name, QDict *data) QDict *wait_command_fd(QTestState *who, int fd, const char *command, ...) { va_list ap; + QDict *resp, *ret; va_start(ap, command); qtest_qmp_vsend_fds(who, &fd, 1, command, ap); va_end(ap); - return qtest_qmp_receive_success(who, stop_cb, NULL); + resp = qtest_qmp_receive(who); + check_stop_event(who); + + g_assert(!qdict_haskey(resp, "error")); + g_assert(qdict_haskey(resp, "return")); + + ret = qdict_get_qdict(resp, "return"); + qobject_ref(ret); + qobject_unref(resp); + + return ret; } /* @@ -44,12 +57,22 @@ QDict *wait_command_fd(QTestState *who, int fd, const char *command, ...) QDict *wait_command(QTestState *who, const char *command, ...) { va_list ap; + QDict *resp, *ret; va_start(ap, command); - qtest_qmp_vsend(who, command, ap); + resp = qtest_vqmp(who, command, ap); va_end(ap); - return qtest_qmp_receive_success(who, stop_cb, NULL); + check_stop_event(who); + + g_assert(!qdict_haskey(resp, "error")); + g_assert(qdict_haskey(resp, "return")); + + ret = qdict_get_qdict(resp, "return"); + qobject_ref(ret); + qobject_unref(resp); + + return ret; } /* diff --git a/tests/qtest/migration-helpers.h b/tests/qtest/migration-helpers.h index a11808b3b77c4901cc25904282d2946cd360fbc9..d63bba9630f9572fe4f33a4f606474d7ee63224c 100644 --- a/tests/qtest/migration-helpers.h +++ b/tests/qtest/migration-helpers.h @@ -12,7 +12,7 @@ #ifndef MIGRATION_HELPERS_H_ #define MIGRATION_HELPERS_H_ -#include "libqtest.h" +#include "libqos/libqtest.h" extern bool got_stop; diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 2568c9529c9af020dcffc6af1efe6c825eb137f3..f2142fbd3c93a85c309312cb4ed658aa71c324f0 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -12,7 +12,8 @@ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" +#include "qapi/error.h" #include "qapi/qmp/qdict.h" #include "qemu/module.h" #include "qemu/option.h" @@ -24,7 +25,7 @@ #include "qapi/qobject-output-visitor.h" #include "migration-helpers.h" -#include "migration/migration-test.h" +#include "tests/migration/migration-test.h" /* TODO actually test the results and get rid of this */ #define qtest_qmp_discard_response(...) qobject_unref(qtest_qmp(__VA_ARGS__)) @@ -33,6 +34,9 @@ unsigned start_address; unsigned end_address; static bool uffd_feature_thread_id; +/* A downtime where the test really should converge */ +#define CONVERGE_DOWNTIME 1000 + #if defined(__linux__) #include #include @@ -301,7 +305,6 @@ static char *migrate_get_socket_address(QTestState *who, const char *parameter) { QDict *rsp; char *result; - Error *local_err = NULL; SocketAddressList *addrs; Visitor *iv = NULL; QObject *object; @@ -310,7 +313,7 @@ static char *migrate_get_socket_address(QTestState *who, const char *parameter) object = qdict_get(rsp, parameter); iv = qobject_input_visitor_new(object); - visit_type_SocketAddressList(iv, NULL, &addrs, &local_err); + visit_type_SocketAddressList(iv, NULL, &addrs, &error_abort); visit_free(iv); /* we are only using a single address */ @@ -461,6 +464,10 @@ static void migrate_postcopy_start(QTestState *from, QTestState *to) } typedef struct { + /* + * QTEST_LOG=1 may override this. When QTEST_LOG=1, we always dump errors + * unconditionally, because it means the user would like to be verbose. + */ bool hide_stderr; bool use_shmem; /* only launch the target process */ @@ -554,7 +561,7 @@ static int test_migrate_start(QTestState **from, QTestState **to, g_free(bootpath); - if (args->hide_stderr) { + if (!getenv("QTEST_LOG") && args->hide_stderr) { ignore_stderr = "2>/dev/null"; } else { ignore_stderr = ""; @@ -864,8 +871,7 @@ static void test_precopy_unix(void) wait_for_migration_pass(from); - /* 300 ms should converge */ - migrate_set_parameter_int(from, "downtime-limit", 300); + migrate_set_parameter_int(from, "downtime-limit", CONVERGE_DOWNTIME); if (!got_stop) { qtest_qmp_eventwait(from, "STOP"); @@ -946,10 +952,12 @@ static void test_xbzrle(const char *uri) migrate_qmp(from, uri, "{}"); + wait_for_migration_pass(from); + /* Make sure we have 2 passes, so the xbzrle cache gets a workout */ wait_for_migration_pass(from); - /* 300ms should converge */ - migrate_set_parameter_int(from, "downtime-limit", 300); + /* 1000ms should converge */ + migrate_set_parameter_int(from, "downtime-limit", 1000); if (!got_stop) { qtest_qmp_eventwait(from, "STOP"); @@ -999,8 +1007,7 @@ static void test_precopy_tcp(void) wait_for_migration_pass(from); - /* 300ms should converge */ - migrate_set_parameter_int(from, "downtime-limit", 300); + migrate_set_parameter_int(from, "downtime-limit", CONVERGE_DOWNTIME); if (!got_stop) { qtest_qmp_eventwait(from, "STOP"); @@ -1068,8 +1075,7 @@ static void test_migrate_fd_proto(void) wait_for_migration_pass(from); - /* 300ms should converge */ - migrate_set_parameter_int(from, "downtime-limit", 300); + migrate_set_parameter_int(from, "downtime-limit", CONVERGE_DOWNTIME); if (!got_stop) { qtest_qmp_eventwait(from, "STOP"); @@ -1211,7 +1217,7 @@ static void test_migrate_auto_converge(void) * without throttling. */ migrate_set_parameter_int(from, "downtime-limit", 1); - migrate_set_parameter_int(from, "max-bandwidth", 1000000); /* ~1Mb/s */ + migrate_set_parameter_int(from, "max-bandwidth", 100000000); /* ~100Mb/s */ /* To check remaining size after precopy */ migrate_set_capability(from, "pause-before-switchover", true); @@ -1304,8 +1310,7 @@ static void test_multifd_tcp(const char *method) wait_for_migration_pass(from); - /* 300ms it should converge */ - migrate_set_parameter_int(from, "downtime-limit", 300); + migrate_set_parameter_int(from, "downtime-limit", CONVERGE_DOWNTIME); if (!got_stop) { qtest_qmp_eventwait(from, "STOP"); diff --git a/tests/qtest/modules-test.c b/tests/qtest/modules-test.c index 88217686e14e3924833b3feff87e9b014484029e..c238b3f4221608762b584b33047e53b7a6597e20 100644 --- a/tests/qtest/modules-test.c +++ b/tests/qtest/modules-test.c @@ -1,5 +1,5 @@ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" const char common_args[] = "-nodefaults -machine none"; diff --git a/tests/qtest/ne2000-test.c b/tests/qtest/ne2000-test.c index 3fc0e555d5e25de99ff5c9635c8c336ace19b398..43cfc4535aabe14833ce4a423006254eb8829719 100644 --- a/tests/qtest/ne2000-test.c +++ b/tests/qtest/ne2000-test.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/module.h" #include "libqos/qgraph.h" #include "libqos/pci.h" diff --git a/tests/qtest/npcm7xx_gpio-test.c b/tests/qtest/npcm7xx_gpio-test.c new file mode 100644 index 0000000000000000000000000000000000000000..1004cef8121efad7098d2c7be17efc502f5b3a04 --- /dev/null +++ b/tests/qtest/npcm7xx_gpio-test.c @@ -0,0 +1,385 @@ +/* + * QTest testcase for the Nuvoton NPCM7xx GPIO modules. + * + * Copyright 2020 Google LLC + * + * 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. + */ + +#include "qemu/osdep.h" +#include "libqtest-single.h" + +#define NR_GPIO_DEVICES (8) +#define GPIO(x) (0xf0010000 + (x) * 0x1000) +#define GPIO_IRQ(x) (116 + (x)) + +/* GPIO registers */ +#define GP_N_TLOCK1 0x00 +#define GP_N_DIN 0x04 /* Data IN */ +#define GP_N_POL 0x08 /* Polarity */ +#define GP_N_DOUT 0x0c /* Data OUT */ +#define GP_N_OE 0x10 /* Output Enable */ +#define GP_N_OTYP 0x14 +#define GP_N_MP 0x18 +#define GP_N_PU 0x1c /* Pull-up */ +#define GP_N_PD 0x20 /* Pull-down */ +#define GP_N_DBNC 0x24 /* Debounce */ +#define GP_N_EVTYP 0x28 /* Event Type */ +#define GP_N_EVBE 0x2c /* Event Both Edge */ +#define GP_N_OBL0 0x30 +#define GP_N_OBL1 0x34 +#define GP_N_OBL2 0x38 +#define GP_N_OBL3 0x3c +#define GP_N_EVEN 0x40 /* Event Enable */ +#define GP_N_EVENS 0x44 /* Event Set (enable) */ +#define GP_N_EVENC 0x48 /* Event Clear (disable) */ +#define GP_N_EVST 0x4c /* Event Status */ +#define GP_N_SPLCK 0x50 +#define GP_N_MPLCK 0x54 +#define GP_N_IEM 0x58 /* Input Enable */ +#define GP_N_OSRC 0x5c +#define GP_N_ODSC 0x60 +#define GP_N_DOS 0x68 /* Data OUT Set */ +#define GP_N_DOC 0x6c /* Data OUT Clear */ +#define GP_N_OES 0x70 /* Output Enable Set */ +#define GP_N_OEC 0x74 /* Output Enable Clear */ +#define GP_N_TLOCK2 0x7c + +static void gpio_unlock(int n) +{ + if (readl(GPIO(n) + GP_N_TLOCK1) != 0) { + writel(GPIO(n) + GP_N_TLOCK2, 0xc0de1248); + writel(GPIO(n) + GP_N_TLOCK1, 0xc0defa73); + } +} + +/* Restore the GPIO controller to a sensible default state. */ +static void gpio_reset(int n) +{ + gpio_unlock(0); + + writel(GPIO(n) + GP_N_EVEN, 0x00000000); + writel(GPIO(n) + GP_N_EVST, 0xffffffff); + writel(GPIO(n) + GP_N_POL, 0x00000000); + writel(GPIO(n) + GP_N_DOUT, 0x00000000); + writel(GPIO(n) + GP_N_OE, 0x00000000); + writel(GPIO(n) + GP_N_OTYP, 0x00000000); + writel(GPIO(n) + GP_N_PU, 0xffffffff); + writel(GPIO(n) + GP_N_PD, 0x00000000); + writel(GPIO(n) + GP_N_IEM, 0xffffffff); +} + +static void test_dout_to_din(void) +{ + gpio_reset(0); + + /* When output is enabled, DOUT should be reflected on DIN. */ + writel(GPIO(0) + GP_N_OE, 0xffffffff); + /* PU and PD shouldn't have any impact on DIN. */ + writel(GPIO(0) + GP_N_PU, 0xffff0000); + writel(GPIO(0) + GP_N_PD, 0x0000ffff); + writel(GPIO(0) + GP_N_DOUT, 0x12345678); + g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0x12345678); + g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x12345678); +} + +static void test_pullup_pulldown(void) +{ + gpio_reset(0); + + /* + * When output is disabled, and PD is the inverse of PU, PU should be + * reflected on DIN. If PD is not the inverse of PU, the state of DIN is + * undefined, so we don't test that. + */ + writel(GPIO(0) + GP_N_OE, 0x00000000); + /* DOUT shouldn't have any impact on DIN. */ + writel(GPIO(0) + GP_N_DOUT, 0xffff0000); + writel(GPIO(0) + GP_N_PU, 0x23456789); + writel(GPIO(0) + GP_N_PD, ~0x23456789U); + g_assert_cmphex(readl(GPIO(0) + GP_N_PU), ==, 0x23456789); + g_assert_cmphex(readl(GPIO(0) + GP_N_PD), ==, ~0x23456789U); + g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x23456789); +} + +static void test_output_enable(void) +{ + gpio_reset(0); + + /* + * With all pins weakly pulled down, and DOUT all-ones, OE should be + * reflected on DIN. + */ + writel(GPIO(0) + GP_N_DOUT, 0xffffffff); + writel(GPIO(0) + GP_N_PU, 0x00000000); + writel(GPIO(0) + GP_N_PD, 0xffffffff); + writel(GPIO(0) + GP_N_OE, 0x3456789a); + g_assert_cmphex(readl(GPIO(0) + GP_N_OE), ==, 0x3456789a); + g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x3456789a); + + writel(GPIO(0) + GP_N_OEC, 0x00030002); + g_assert_cmphex(readl(GPIO(0) + GP_N_OE), ==, 0x34547898); + g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x34547898); + + writel(GPIO(0) + GP_N_OES, 0x0000f001); + g_assert_cmphex(readl(GPIO(0) + GP_N_OE), ==, 0x3454f899); + g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x3454f899); +} + +static void test_open_drain(void) +{ + gpio_reset(0); + + /* + * Upper half of DOUT drives a 1 only if the corresponding bit in OTYP is + * not set. If OTYP is set, DIN is determined by PU/PD. Lower half of + * DOUT always drives a 0 regardless of OTYP; PU/PD have no effect. When + * OE is 0, output is determined by PU/PD; OTYP has no effect. + */ + writel(GPIO(0) + GP_N_OTYP, 0x456789ab); + writel(GPIO(0) + GP_N_OE, 0xf0f0f0f0); + writel(GPIO(0) + GP_N_DOUT, 0xffff0000); + writel(GPIO(0) + GP_N_PU, 0xff00ff00); + writel(GPIO(0) + GP_N_PD, 0x00ff00ff); + g_assert_cmphex(readl(GPIO(0) + GP_N_OTYP), ==, 0x456789ab); + g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0xff900f00); +} + +static void test_polarity(void) +{ + gpio_reset(0); + + /* + * In push-pull mode, DIN should reflect DOUT because the signal is + * inverted in both directions. + */ + writel(GPIO(0) + GP_N_OTYP, 0x00000000); + writel(GPIO(0) + GP_N_OE, 0xffffffff); + writel(GPIO(0) + GP_N_DOUT, 0x56789abc); + writel(GPIO(0) + GP_N_POL, 0x6789abcd); + g_assert_cmphex(readl(GPIO(0) + GP_N_POL), ==, 0x6789abcd); + g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x56789abc); + + /* + * When turning off the drivers, DIN should reflect the inverse of the + * pulled-up lines. + */ + writel(GPIO(0) + GP_N_OE, 0x00000000); + writel(GPIO(0) + GP_N_POL, 0xffffffff); + writel(GPIO(0) + GP_N_PU, 0x789abcde); + writel(GPIO(0) + GP_N_PD, ~0x789abcdeU); + g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, ~0x789abcdeU); + + /* + * In open-drain mode, DOUT=1 will appear to drive the pin high (since DIN + * is inverted), while DOUT=0 will leave the pin floating. + */ + writel(GPIO(0) + GP_N_OTYP, 0xffffffff); + writel(GPIO(0) + GP_N_OE, 0xffffffff); + writel(GPIO(0) + GP_N_PU, 0xffff0000); + writel(GPIO(0) + GP_N_PD, 0x0000ffff); + writel(GPIO(0) + GP_N_DOUT, 0xff00ff00); + g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0xff00ffff); +} + +static void test_input_mask(void) +{ + gpio_reset(0); + + /* IEM=0 forces the input to zero before polarity inversion. */ + writel(GPIO(0) + GP_N_OE, 0xffffffff); + writel(GPIO(0) + GP_N_DOUT, 0xff00ff00); + writel(GPIO(0) + GP_N_POL, 0xffff0000); + writel(GPIO(0) + GP_N_IEM, 0x87654321); + g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0xff9a4300); +} + +static void test_temp_lock(void) +{ + gpio_reset(0); + + writel(GPIO(0) + GP_N_DOUT, 0x98765432); + + /* Make sure we're unlocked initially. */ + g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 0); + /* Writing any value to TLOCK1 will lock. */ + writel(GPIO(0) + GP_N_TLOCK1, 0); + g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 1); + writel(GPIO(0) + GP_N_DOUT, 0xa9876543); + g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0x98765432); + /* Now, try to unlock. */ + gpio_unlock(0); + g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 0); + writel(GPIO(0) + GP_N_DOUT, 0xa9876543); + g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0xa9876543); + + /* Try it again, but write TLOCK2 to lock. */ + writel(GPIO(0) + GP_N_TLOCK2, 0); + g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 1); + writel(GPIO(0) + GP_N_DOUT, 0x98765432); + g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0xa9876543); + /* Now, try to unlock. */ + gpio_unlock(0); + g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 0); + writel(GPIO(0) + GP_N_DOUT, 0x98765432); + g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0x98765432); +} + +static void test_events_level(void) +{ + gpio_reset(0); + + writel(GPIO(0) + GP_N_EVTYP, 0x00000000); + writel(GPIO(0) + GP_N_DOUT, 0xba987654); + writel(GPIO(0) + GP_N_OE, 0xffffffff); + writel(GPIO(0) + GP_N_EVST, 0xffffffff); + + g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0xba987654); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0))); + writel(GPIO(0) + GP_N_DOUT, 0x00000000); + g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0xba987654); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0))); + writel(GPIO(0) + GP_N_EVST, 0x00007654); + g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0xba980000); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0))); + writel(GPIO(0) + GP_N_EVST, 0xba980000); + g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0))); +} + +static void test_events_rising_edge(void) +{ + gpio_reset(0); + + writel(GPIO(0) + GP_N_EVTYP, 0xffffffff); + writel(GPIO(0) + GP_N_EVBE, 0x00000000); + writel(GPIO(0) + GP_N_DOUT, 0xffff0000); + writel(GPIO(0) + GP_N_OE, 0xffffffff); + writel(GPIO(0) + GP_N_EVST, 0xffffffff); + + g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0))); + writel(GPIO(0) + GP_N_DOUT, 0xff00ff00); + g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x0000ff00); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0))); + writel(GPIO(0) + GP_N_DOUT, 0x00ff0000); + g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00ffff00); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0))); + writel(GPIO(0) + GP_N_EVST, 0x0000f000); + g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00ff0f00); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0))); + writel(GPIO(0) + GP_N_EVST, 0x00ff0f00); + g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0))); +} + +static void test_events_both_edges(void) +{ + gpio_reset(0); + + writel(GPIO(0) + GP_N_EVTYP, 0xffffffff); + writel(GPIO(0) + GP_N_EVBE, 0xffffffff); + writel(GPIO(0) + GP_N_DOUT, 0xffff0000); + writel(GPIO(0) + GP_N_OE, 0xffffffff); + writel(GPIO(0) + GP_N_EVST, 0xffffffff); + + g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0))); + writel(GPIO(0) + GP_N_DOUT, 0xff00ff00); + g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00ffff00); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0))); + writel(GPIO(0) + GP_N_DOUT, 0xef00ff08); + g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x10ffff08); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0))); + writel(GPIO(0) + GP_N_EVST, 0x0000f000); + g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x10ff0f08); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0))); + writel(GPIO(0) + GP_N_EVST, 0x10ff0f08); + g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0))); +} + +static void test_gpion_irq(gconstpointer test_data) +{ + intptr_t n = (intptr_t)test_data; + + gpio_reset(n); + + writel(GPIO(n) + GP_N_EVTYP, 0x00000000); + writel(GPIO(n) + GP_N_DOUT, 0x00000000); + writel(GPIO(n) + GP_N_OE, 0xffffffff); + writel(GPIO(n) + GP_N_EVST, 0xffffffff); + writel(GPIO(n) + GP_N_EVEN, 0x00000000); + + /* Trigger an event; interrupts are masked. */ + g_assert_cmphex(readl(GPIO(n) + GP_N_EVST), ==, 0x00000000); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(n))); + writel(GPIO(n) + GP_N_DOS, 0x00008000); + g_assert_cmphex(readl(GPIO(n) + GP_N_EVST), ==, 0x00008000); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(n))); + + /* Unmask all event interrupts; verify that the interrupt fired. */ + writel(GPIO(n) + GP_N_EVEN, 0xffffffff); + g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n))); + + /* Clear the current bit, set a new bit, irq stays asserted. */ + writel(GPIO(n) + GP_N_DOC, 0x00008000); + g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n))); + writel(GPIO(n) + GP_N_DOS, 0x00000200); + g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n))); + writel(GPIO(n) + GP_N_EVST, 0x00008000); + g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n))); + + /* Mask/unmask the event that's currently active. */ + writel(GPIO(n) + GP_N_EVENC, 0x00000200); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(n))); + writel(GPIO(n) + GP_N_EVENS, 0x00000200); + g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n))); + + /* Clear the input and the status bit, irq is deasserted. */ + writel(GPIO(n) + GP_N_DOC, 0x00000200); + g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n))); + writel(GPIO(n) + GP_N_EVST, 0x00000200); + g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(n))); +} + +int main(int argc, char **argv) +{ + int ret; + int i; + + g_test_init(&argc, &argv, NULL); + g_test_set_nonfatal_assertions(); + + qtest_add_func("/npcm7xx_gpio/dout_to_din", test_dout_to_din); + qtest_add_func("/npcm7xx_gpio/pullup_pulldown", test_pullup_pulldown); + qtest_add_func("/npcm7xx_gpio/output_enable", test_output_enable); + qtest_add_func("/npcm7xx_gpio/open_drain", test_open_drain); + qtest_add_func("/npcm7xx_gpio/polarity", test_polarity); + qtest_add_func("/npcm7xx_gpio/input_mask", test_input_mask); + qtest_add_func("/npcm7xx_gpio/temp_lock", test_temp_lock); + qtest_add_func("/npcm7xx_gpio/events/level", test_events_level); + qtest_add_func("/npcm7xx_gpio/events/rising_edge", test_events_rising_edge); + qtest_add_func("/npcm7xx_gpio/events/both_edges", test_events_both_edges); + + for (i = 0; i < NR_GPIO_DEVICES; i++) { + g_autofree char *test_name = + g_strdup_printf("/npcm7xx_gpio/gpio[%d]/irq", i); + qtest_add_data_func(test_name, (void *)(intptr_t)i, test_gpion_irq); + } + + qtest_start("-machine npcm750-evb"); + qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic"); + ret = g_test_run(); + qtest_end(); + + return ret; +} diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c new file mode 100644 index 0000000000000000000000000000000000000000..c614968ffcda81152fa348d505174dd9fd881f30 --- /dev/null +++ b/tests/qtest/npcm7xx_rng-test.c @@ -0,0 +1,284 @@ +/* + * QTest testcase for the Nuvoton NPCM7xx Random Number Generator + * + * Copyright 2020 Google LLC + * + * 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. + */ + +#include "qemu/osdep.h" + +#include + +#include "libqtest-single.h" +#include "qemu/bitops.h" + +#define RNG_BASE_ADDR 0xf000b000 + +/* Control and Status Register */ +#define RNGCS 0x00 +# define DVALID BIT(1) /* Data Valid */ +# define RNGE BIT(0) /* RNG Enable */ +/* Data Register */ +#define RNGD 0x04 +/* Mode Register */ +#define RNGMODE 0x08 +# define ROSEL_NORMAL (2) /* RNG only works in this mode */ + +/* Number of bits to collect for randomness tests. */ +#define TEST_INPUT_BITS (128) + +static void rng_writeb(unsigned int offset, uint8_t value) +{ + writeb(RNG_BASE_ADDR + offset, value); +} + +static uint8_t rng_readb(unsigned int offset) +{ + return readb(RNG_BASE_ADDR + offset); +} + +/* Disable RNG and set normal ring oscillator mode. */ +static void rng_reset(void) +{ + rng_writeb(RNGCS, 0); + rng_writeb(RNGMODE, ROSEL_NORMAL); +} + +/* Reset RNG and then enable it. */ +static void rng_reset_enable(void) +{ + rng_reset(); + rng_writeb(RNGCS, RNGE); +} + +/* Wait until Data Valid bit is set. */ +static bool rng_wait_ready(void) +{ + /* qemu_guest_getrandom may fail. Assume it won't fail 10 times in a row. */ + int retries = 10; + + while (retries-- > 0) { + if (rng_readb(RNGCS) & DVALID) { + return true; + } + } + + return false; +} + +/* + * Perform a frequency (monobit) test, as defined by NIST SP 800-22, on the + * sequence in buf and return the P-value. This represents the probability of a + * truly random sequence having the same proportion of zeros and ones as the + * sequence in buf. + * + * An RNG which always returns 0x00 or 0xff, or has some bits stuck at 0 or 1, + * will fail this test. However, an RNG which always returns 0x55, 0xf0 or some + * other value with an equal number of zeroes and ones will pass. + */ +static double calc_monobit_p(const uint8_t *buf, unsigned int len) +{ + unsigned int i; + double s_obs; + int sn = 0; + + for (i = 0; i < len; i++) { + /* + * Each 1 counts as 1, each 0 counts as -1. + * s = cp - (8 - cp) = 2 * cp - 8 + */ + sn += 2 * ctpop8(buf[i]) - 8; + } + + s_obs = abs(sn) / sqrt(len * BITS_PER_BYTE); + + return erfc(s_obs / sqrt(2)); +} + +/* + * Perform a runs test, as defined by NIST SP 800-22, and return the P-value. + * This represents the probability of a truly random sequence having the same + * number of runs (i.e. uninterrupted sequences of identical bits) as the + * sequence in buf. + */ +static double calc_runs_p(const unsigned long *buf, unsigned int nr_bits) +{ + unsigned int j; + unsigned int k; + int nr_ones = 0; + int vn_obs = 0; + double pi; + + g_assert(nr_bits % BITS_PER_LONG == 0); + + for (j = 0; j < nr_bits / BITS_PER_LONG; j++) { + nr_ones += __builtin_popcountl(buf[j]); + } + pi = (double)nr_ones / nr_bits; + + for (k = 0; k < nr_bits - 1; k++) { + vn_obs += (test_bit(k, buf) ^ test_bit(k + 1, buf)); + } + vn_obs += 1; + + return erfc(fabs(vn_obs - 2 * nr_bits * pi * (1.0 - pi)) + / (2 * sqrt(2 * nr_bits) * pi * (1.0 - pi))); +} + +/* + * Verifies that DVALID is clear, and RNGD reads zero, when RNGE is cleared, + * and DVALID eventually becomes set when RNGE is set. + */ +static void test_enable_disable(void) +{ + /* Disable: DVALID should not be set, and RNGD should read zero */ + rng_reset(); + g_assert_cmphex(rng_readb(RNGCS), ==, 0); + g_assert_cmphex(rng_readb(RNGD), ==, 0); + + /* Enable: DVALID should be set, but we can't make assumptions about RNGD */ + rng_writeb(RNGCS, RNGE); + g_assert_true(rng_wait_ready()); + g_assert_cmphex(rng_readb(RNGCS), ==, DVALID | RNGE); + + /* Disable: DVALID should not be set, and RNGD should read zero */ + rng_writeb(RNGCS, 0); + g_assert_cmphex(rng_readb(RNGCS), ==, 0); + g_assert_cmphex(rng_readb(RNGD), ==, 0); +} + +/* + * Verifies that the RNG only produces data when RNGMODE is set to 'normal' + * ring oscillator mode. + */ +static void test_rosel(void) +{ + rng_reset_enable(); + g_assert_true(rng_wait_ready()); + rng_writeb(RNGMODE, 0); + g_assert_false(rng_wait_ready()); + rng_writeb(RNGMODE, ROSEL_NORMAL); + g_assert_true(rng_wait_ready()); + rng_writeb(RNGMODE, 0); + g_assert_false(rng_wait_ready()); +} + +/* + * Verifies that a continuous sequence of bits collected after enabling the RNG + * satisfies a monobit test. + */ +static void test_continuous_monobit(void) +{ + uint8_t buf[TEST_INPUT_BITS / BITS_PER_BYTE]; + unsigned int i; + + rng_reset_enable(); + for (i = 0; i < sizeof(buf); i++) { + g_assert_true(rng_wait_ready()); + buf[i] = rng_readb(RNGD); + } + + g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01); +} + +/* + * Verifies that a continuous sequence of bits collected after enabling the RNG + * satisfies a runs test. + */ +static void test_continuous_runs(void) +{ + union { + unsigned long l[TEST_INPUT_BITS / BITS_PER_LONG]; + uint8_t c[TEST_INPUT_BITS / BITS_PER_BYTE]; + } buf; + unsigned int i; + + rng_reset_enable(); + for (i = 0; i < sizeof(buf); i++) { + g_assert_true(rng_wait_ready()); + buf.c[i] = rng_readb(RNGD); + } + + g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01); +} + +/* + * Verifies that the first data byte collected after enabling the RNG satisfies + * a monobit test. + */ +static void test_first_byte_monobit(void) +{ + /* Enable, collect one byte, disable. Repeat until we have 100 bits. */ + uint8_t buf[TEST_INPUT_BITS / BITS_PER_BYTE]; + unsigned int i; + + rng_reset(); + for (i = 0; i < sizeof(buf); i++) { + rng_writeb(RNGCS, RNGE); + g_assert_true(rng_wait_ready()); + buf[i] = rng_readb(RNGD); + rng_writeb(RNGCS, 0); + } + + g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01); +} + +/* + * Verifies that the first data byte collected after enabling the RNG satisfies + * a runs test. + */ +static void test_first_byte_runs(void) +{ + /* Enable, collect one byte, disable. Repeat until we have 100 bits. */ + union { + unsigned long l[TEST_INPUT_BITS / BITS_PER_LONG]; + uint8_t c[TEST_INPUT_BITS / BITS_PER_BYTE]; + } buf; + unsigned int i; + + rng_reset(); + for (i = 0; i < sizeof(buf); i++) { + rng_writeb(RNGCS, RNGE); + g_assert_true(rng_wait_ready()); + buf.c[i] = rng_readb(RNGD); + rng_writeb(RNGCS, 0); + } + + g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01); +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + g_test_set_nonfatal_assertions(); + + qtest_add_func("npcm7xx_rng/enable_disable", test_enable_disable); + qtest_add_func("npcm7xx_rng/rosel", test_rosel); + /* + * These tests fail intermittently; only run them on explicit + * request until we figure out why. + */ + if (getenv("QEMU_TEST_FLAKY_RNG_TESTS")) { + qtest_add_func("npcm7xx_rng/continuous/monobit", test_continuous_monobit); + qtest_add_func("npcm7xx_rng/continuous/runs", test_continuous_runs); + qtest_add_func("npcm7xx_rng/first_byte/monobit", test_first_byte_monobit); + qtest_add_func("npcm7xx_rng/first_byte/runs", test_first_byte_runs); + } + + qtest_start("-machine npcm750-evb"); + ret = g_test_run(); + qtest_end(); + + return ret; +} diff --git a/tests/qtest/npcm7xx_timer-test.c b/tests/qtest/npcm7xx_timer-test.c new file mode 100644 index 0000000000000000000000000000000000000000..83774a5b903b91fee03f116ca72297d92df34af7 --- /dev/null +++ b/tests/qtest/npcm7xx_timer-test.c @@ -0,0 +1,560 @@ +/* + * QTest testcase for the Nuvoton NPCM7xx Timer + * + * Copyright 2020 Google LLC + * + * 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. + */ + +#include "qemu/osdep.h" +#include "qemu/timer.h" +#include "libqtest-single.h" + +#define TIM_REF_HZ (25000000) + +/* Bits in TCSRx */ +#define CEN BIT(30) +#define IE BIT(29) +#define MODE_ONESHOT (0 << 27) +#define MODE_PERIODIC (1 << 27) +#define CRST BIT(26) +#define CACT BIT(25) +#define PRESCALE(x) (x) + +/* Registers shared between all timers in a module. */ +#define TISR 0x18 +#define WTCR 0x1c +# define WTCLK(x) ((x) << 10) + +/* Power-on default; used to re-initialize timers before each test. */ +#define TCSR_DEFAULT PRESCALE(5) + +/* Register offsets for a timer within a timer block. */ +typedef struct Timer { + unsigned int tcsr_offset; + unsigned int ticr_offset; + unsigned int tdr_offset; +} Timer; + +/* A timer block containing 5 timers. */ +typedef struct TimerBlock { + int irq_base; + uint64_t base_addr; +} TimerBlock; + +/* Testdata for testing a particular timer within a timer block. */ +typedef struct TestData { + const TimerBlock *tim; + const Timer *timer; +} TestData; + +const TimerBlock timer_block[] = { + { + .irq_base = 32, + .base_addr = 0xf0008000, + }, + { + .irq_base = 37, + .base_addr = 0xf0009000, + }, + { + .irq_base = 42, + .base_addr = 0xf000a000, + }, +}; + +const Timer timer[] = { + { + .tcsr_offset = 0x00, + .ticr_offset = 0x08, + .tdr_offset = 0x10, + }, { + .tcsr_offset = 0x04, + .ticr_offset = 0x0c, + .tdr_offset = 0x14, + }, { + .tcsr_offset = 0x20, + .ticr_offset = 0x28, + .tdr_offset = 0x30, + }, { + .tcsr_offset = 0x24, + .ticr_offset = 0x2c, + .tdr_offset = 0x34, + }, { + .tcsr_offset = 0x40, + .ticr_offset = 0x48, + .tdr_offset = 0x50, + }, +}; + +/* Returns the index of the timer block. */ +static int tim_index(const TimerBlock *tim) +{ + ptrdiff_t diff = tim - timer_block; + + g_assert(diff >= 0 && diff < ARRAY_SIZE(timer_block)); + + return diff; +} + +/* Returns the index of a timer within a timer block. */ +static int timer_index(const Timer *t) +{ + ptrdiff_t diff = t - timer; + + g_assert(diff >= 0 && diff < ARRAY_SIZE(timer)); + + return diff; +} + +/* Returns the irq line for a given timer. */ +static int tim_timer_irq(const TestData *td) +{ + return td->tim->irq_base + timer_index(td->timer); +} + +/* Register read/write accessors. */ + +static void tim_write(const TestData *td, + unsigned int offset, uint32_t value) +{ + writel(td->tim->base_addr + offset, value); +} + +static uint32_t tim_read(const TestData *td, unsigned int offset) +{ + return readl(td->tim->base_addr + offset); +} + +static void tim_write_tcsr(const TestData *td, uint32_t value) +{ + tim_write(td, td->timer->tcsr_offset, value); +} + +static uint32_t tim_read_tcsr(const TestData *td) +{ + return tim_read(td, td->timer->tcsr_offset); +} + +static void tim_write_ticr(const TestData *td, uint32_t value) +{ + tim_write(td, td->timer->ticr_offset, value); +} + +static uint32_t tim_read_ticr(const TestData *td) +{ + return tim_read(td, td->timer->ticr_offset); +} + +static uint32_t tim_read_tdr(const TestData *td) +{ + return tim_read(td, td->timer->tdr_offset); +} + +/* Returns the number of nanoseconds to count the given number of cycles. */ +static int64_t tim_calculate_step(uint32_t count, uint32_t prescale) +{ + return (1000000000LL / TIM_REF_HZ) * count * (prescale + 1); +} + +/* Returns a bitmask corresponding to the timer under test. */ +static uint32_t tim_timer_bit(const TestData *td) +{ + return BIT(timer_index(td->timer)); +} + +/* Resets all timers to power-on defaults. */ +static void tim_reset(const TestData *td) +{ + int i, j; + + /* Reset all the timers, in case a previous test left a timer running. */ + for (i = 0; i < ARRAY_SIZE(timer_block); i++) { + for (j = 0; j < ARRAY_SIZE(timer); j++) { + writel(timer_block[i].base_addr + timer[j].tcsr_offset, + CRST | TCSR_DEFAULT); + } + writel(timer_block[i].base_addr + TISR, -1); + } +} + +/* Verifies the reset state of a timer. */ +static void test_reset(gconstpointer test_data) +{ + const TestData *td = test_data; + + tim_reset(td); + + g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT); + g_assert_cmphex(tim_read_ticr(td), ==, 0); + g_assert_cmphex(tim_read_tdr(td), ==, 0); + g_assert_cmphex(tim_read(td, TISR), ==, 0); + g_assert_cmphex(tim_read(td, WTCR), ==, WTCLK(1)); +} + +/* Verifies that CRST wins if both CEN and CRST are set. */ +static void test_reset_overrides_enable(gconstpointer test_data) +{ + const TestData *td = test_data; + + tim_reset(td); + + /* CRST should force CEN to 0 */ + tim_write_tcsr(td, CEN | CRST | TCSR_DEFAULT); + + g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT); + g_assert_cmphex(tim_read_tdr(td), ==, 0); + g_assert_cmphex(tim_read(td, TISR), ==, 0); +} + +/* Verifies the behavior when CEN is set and then cleared. */ +static void test_oneshot_enable_then_disable(gconstpointer test_data) +{ + const TestData *td = test_data; + + tim_reset(td); + + /* Enable the timer with zero initial count, then disable it again. */ + tim_write_tcsr(td, CEN | TCSR_DEFAULT); + tim_write_tcsr(td, TCSR_DEFAULT); + + g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT); + g_assert_cmphex(tim_read_tdr(td), ==, 0); + /* Timer interrupt flag should be set, but interrupts are not enabled. */ + g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td)); + g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td))); +} + +/* Verifies that a one-shot timer fires when expected with prescaler 5. */ +static void test_oneshot_ps5(gconstpointer test_data) +{ + const TestData *td = test_data; + unsigned int count = 256; + unsigned int ps = 5; + + tim_reset(td); + + tim_write_ticr(td, count); + tim_write_tcsr(td, CEN | PRESCALE(ps)); + g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps)); + g_assert_cmpuint(tim_read_tdr(td), ==, count); + + clock_step(tim_calculate_step(count, ps) - 1); + + g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps)); + g_assert_cmpuint(tim_read_tdr(td), <, count); + g_assert_cmphex(tim_read(td, TISR), ==, 0); + + clock_step(1); + + g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps)); + g_assert_cmpuint(tim_read_tdr(td), ==, count); + g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td)); + g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td))); + + /* Clear the interrupt flag. */ + tim_write(td, TISR, tim_timer_bit(td)); + g_assert_cmphex(tim_read(td, TISR), ==, 0); + g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td))); + + /* Verify that this isn't a periodic timer. */ + clock_step(2 * tim_calculate_step(count, ps)); + g_assert_cmphex(tim_read(td, TISR), ==, 0); + g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td))); +} + +/* Verifies that a one-shot timer fires when expected with prescaler 0. */ +static void test_oneshot_ps0(gconstpointer test_data) +{ + const TestData *td = test_data; + unsigned int count = 1; + unsigned int ps = 0; + + tim_reset(td); + + tim_write_ticr(td, count); + tim_write_tcsr(td, CEN | PRESCALE(ps)); + g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps)); + g_assert_cmpuint(tim_read_tdr(td), ==, count); + + clock_step(tim_calculate_step(count, ps) - 1); + + g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps)); + g_assert_cmpuint(tim_read_tdr(td), <, count); + g_assert_cmphex(tim_read(td, TISR), ==, 0); + + clock_step(1); + + g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps)); + g_assert_cmpuint(tim_read_tdr(td), ==, count); + g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td)); + g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td))); +} + +/* Verifies that a one-shot timer fires when expected with highest prescaler. */ +static void test_oneshot_ps255(gconstpointer test_data) +{ + const TestData *td = test_data; + unsigned int count = (1U << 24) - 1; + unsigned int ps = 255; + + tim_reset(td); + + tim_write_ticr(td, count); + tim_write_tcsr(td, CEN | PRESCALE(ps)); + g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps)); + g_assert_cmpuint(tim_read_tdr(td), ==, count); + + clock_step(tim_calculate_step(count, ps) - 1); + + g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps)); + g_assert_cmpuint(tim_read_tdr(td), <, count); + g_assert_cmphex(tim_read(td, TISR), ==, 0); + + clock_step(1); + + g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps)); + g_assert_cmpuint(tim_read_tdr(td), ==, count); + g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td)); + g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td))); +} + +/* Verifies that a oneshot timer fires an interrupt when expected. */ +static void test_oneshot_interrupt(gconstpointer test_data) +{ + const TestData *td = test_data; + unsigned int count = 256; + unsigned int ps = 7; + + tim_reset(td); + + tim_write_ticr(td, count); + tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps)); + + clock_step_next(); + + g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td)); + g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td))); +} + +/* + * Verifies that the timer can be paused and later resumed, and it still fires + * at the right moment. + */ +static void test_pause_resume(gconstpointer test_data) +{ + const TestData *td = test_data; + unsigned int count = 256; + unsigned int ps = 1; + + tim_reset(td); + + tim_write_ticr(td, count); + tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps)); + + /* Pause the timer halfway to expiration. */ + clock_step(tim_calculate_step(count / 2, ps)); + tim_write_tcsr(td, IE | MODE_ONESHOT | PRESCALE(ps)); + g_assert_cmpuint(tim_read_tdr(td), ==, count / 2); + + /* Counter should not advance during the following step. */ + clock_step(2 * tim_calculate_step(count, ps)); + g_assert_cmpuint(tim_read_tdr(td), ==, count / 2); + g_assert_cmphex(tim_read(td, TISR), ==, 0); + g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td))); + + /* Resume the timer and run _almost_ to expiration. */ + tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps)); + clock_step(tim_calculate_step(count / 2, ps) - 1); + g_assert_cmpuint(tim_read_tdr(td), <, count); + g_assert_cmphex(tim_read(td, TISR), ==, 0); + g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td))); + + /* Now, run the rest of the way and verify that the interrupt fires. */ + clock_step(1); + g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td)); + g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td))); +} + +/* Verifies that the prescaler can be changed while the timer is runnin. */ +static void test_prescaler_change(gconstpointer test_data) +{ + const TestData *td = test_data; + unsigned int count = 256; + unsigned int ps = 5; + + tim_reset(td); + + tim_write_ticr(td, count); + tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps)); + + /* Run a quarter of the way, and change the prescaler. */ + clock_step(tim_calculate_step(count / 4, ps)); + g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4); + ps = 2; + tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps)); + /* The counter must not change. */ + g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4); + + /* Run another quarter of the way, and change the prescaler again. */ + clock_step(tim_calculate_step(count / 4, ps)); + g_assert_cmpuint(tim_read_tdr(td), ==, count / 2); + ps = 8; + tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps)); + /* The counter must not change. */ + g_assert_cmpuint(tim_read_tdr(td), ==, count / 2); + + /* Run another quarter of the way, and change the prescaler again. */ + clock_step(tim_calculate_step(count / 4, ps)); + g_assert_cmpuint(tim_read_tdr(td), ==, count / 4); + ps = 0; + tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps)); + /* The counter must not change. */ + g_assert_cmpuint(tim_read_tdr(td), ==, count / 4); + + /* Run almost to expiration, and verify the timer didn't fire yet. */ + clock_step(tim_calculate_step(count / 4, ps) - 1); + g_assert_cmpuint(tim_read_tdr(td), <, count); + g_assert_cmphex(tim_read(td, TISR), ==, 0); + + /* Now, run the rest of the way and verify that the timer fires. */ + clock_step(1); + g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td)); +} + +/* Verifies that a periodic timer automatically restarts after expiration. */ +static void test_periodic_no_interrupt(gconstpointer test_data) +{ + const TestData *td = test_data; + unsigned int count = 2; + unsigned int ps = 3; + int i; + + tim_reset(td); + + tim_write_ticr(td, count); + tim_write_tcsr(td, CEN | MODE_PERIODIC | PRESCALE(ps)); + + for (i = 0; i < 4; i++) { + clock_step_next(); + + g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td)); + g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td))); + + tim_write(td, TISR, tim_timer_bit(td)); + + g_assert_cmphex(tim_read(td, TISR), ==, 0); + g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td))); + } +} + +/* Verifies that a periodict timer fires an interrupt every time it expires. */ +static void test_periodic_interrupt(gconstpointer test_data) +{ + const TestData *td = test_data; + unsigned int count = 65535; + unsigned int ps = 2; + int i; + + tim_reset(td); + + tim_write_ticr(td, count); + tim_write_tcsr(td, CEN | IE | MODE_PERIODIC | PRESCALE(ps)); + + for (i = 0; i < 4; i++) { + clock_step_next(); + + g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td)); + g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td))); + + tim_write(td, TISR, tim_timer_bit(td)); + + g_assert_cmphex(tim_read(td, TISR), ==, 0); + g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td))); + } +} + +/* + * Verifies that the timer behaves correctly when disabled right before and + * exactly when it's supposed to expire. + */ +static void test_disable_on_expiration(gconstpointer test_data) +{ + const TestData *td = test_data; + unsigned int count = 8; + unsigned int ps = 255; + + tim_reset(td); + + tim_write_ticr(td, count); + tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps)); + + clock_step(tim_calculate_step(count, ps) - 1); + + tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps)); + tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps)); + clock_step(1); + tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps)); + g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td)); +} + +/* + * Constructs a name that includes the timer block, timer and testcase name, + * and adds the test to the test suite. + */ +static void tim_add_test(const char *name, const TestData *td, GTestDataFunc fn) +{ + g_autofree char *full_name = g_strdup_printf( + "npcm7xx_timer/tim[%d]/timer[%d]/%s", tim_index(td->tim), + timer_index(td->timer), name); + qtest_add_data_func(full_name, td, fn); +} + +/* Convenience macro for adding a test with a predictable function name. */ +#define add_test(name, td) tim_add_test(#name, td, test_##name) + +int main(int argc, char **argv) +{ + TestData testdata[ARRAY_SIZE(timer_block) * ARRAY_SIZE(timer)]; + int ret; + int i, j; + + g_test_init(&argc, &argv, NULL); + g_test_set_nonfatal_assertions(); + + for (i = 0; i < ARRAY_SIZE(timer_block); i++) { + for (j = 0; j < ARRAY_SIZE(timer); j++) { + TestData *td = &testdata[i * ARRAY_SIZE(timer) + j]; + td->tim = &timer_block[i]; + td->timer = &timer[j]; + + add_test(reset, td); + add_test(reset_overrides_enable, td); + add_test(oneshot_enable_then_disable, td); + add_test(oneshot_ps5, td); + add_test(oneshot_ps0, td); + add_test(oneshot_ps255, td); + add_test(oneshot_interrupt, td); + add_test(pause_resume, td); + add_test(prescaler_change, td); + add_test(periodic_no_interrupt, td); + add_test(periodic_interrupt, td); + add_test(disable_on_expiration, td); + } + } + + qtest_start("-machine npcm750-evb"); + qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic"); + ret = g_test_run(); + qtest_end(); + + return ret; +} diff --git a/tests/qtest/npcm7xx_watchdog_timer-test.c b/tests/qtest/npcm7xx_watchdog_timer-test.c new file mode 100644 index 0000000000000000000000000000000000000000..3aae5a043813d7c87f0f1ef3da8dc8cfb8ddbdcf --- /dev/null +++ b/tests/qtest/npcm7xx_watchdog_timer-test.c @@ -0,0 +1,321 @@ +/* + * QTests for Nuvoton NPCM7xx Timer Watchdog Modules. + * + * Copyright 2020 Google LLC + * + * 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. + */ + +#include "qemu/osdep.h" +#include "qemu/timer.h" + +#include "libqos/libqtest.h" +#include "qapi/qmp/qdict.h" + +#define WTCR_OFFSET 0x1c +#define REF_HZ (25000000) + +/* WTCR bit fields */ +#define WTCLK(rv) ((rv) << 10) +#define WTE BIT(7) +#define WTIE BIT(6) +#define WTIS(rv) ((rv) << 4) +#define WTIF BIT(3) +#define WTRF BIT(2) +#define WTRE BIT(1) +#define WTR BIT(0) + +typedef struct Watchdog { + int irq; + uint64_t base_addr; +} Watchdog; + +static const Watchdog watchdog_list[] = { + { + .irq = 47, + .base_addr = 0xf0008000 + }, + { + .irq = 48, + .base_addr = 0xf0009000 + }, + { + .irq = 49, + .base_addr = 0xf000a000 + } +}; + +static int watchdog_index(const Watchdog *wd) +{ + ptrdiff_t diff = wd - watchdog_list; + + g_assert(diff >= 0 && diff < ARRAY_SIZE(watchdog_list)); + + return diff; +} + +static uint32_t watchdog_read_wtcr(QTestState *qts, const Watchdog *wd) +{ + return qtest_readl(qts, wd->base_addr + WTCR_OFFSET); +} + +static void watchdog_write_wtcr(QTestState *qts, const Watchdog *wd, + uint32_t value) +{ + qtest_writel(qts, wd->base_addr + WTCR_OFFSET, value); +} + +static uint32_t watchdog_prescaler(QTestState *qts, const Watchdog *wd) +{ + switch (extract32(watchdog_read_wtcr(qts, wd), 10, 2)) { + case 0: + return 1; + case 1: + return 256; + case 2: + return 2048; + case 3: + return 65536; + default: + g_assert_not_reached(); + } +} + +static QDict *get_watchdog_action(QTestState *qts) +{ + QDict *ev = qtest_qmp_eventwait_ref(qts, "WATCHDOG"); + QDict *data; + + data = qdict_get_qdict(ev, "data"); + qobject_ref(data); + qobject_unref(ev); + return data; +} + +#define RESET_CYCLES 1024 +static uint32_t watchdog_interrupt_cycles(QTestState *qts, const Watchdog *wd) +{ + uint32_t wtis = extract32(watchdog_read_wtcr(qts, wd), 4, 2); + return 1 << (14 + 2 * wtis); +} + +static int64_t watchdog_calculate_steps(uint32_t count, uint32_t prescale) +{ + return (NANOSECONDS_PER_SECOND / REF_HZ) * count * prescale; +} + +static int64_t watchdog_interrupt_steps(QTestState *qts, const Watchdog *wd) +{ + return watchdog_calculate_steps(watchdog_interrupt_cycles(qts, wd), + watchdog_prescaler(qts, wd)); +} + +/* Check wtcr can be reset to default value */ +static void test_init(gconstpointer watchdog) +{ + const Watchdog *wd = watchdog; + QTestState *qts = qtest_init("-machine quanta-gsj"); + + qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic"); + + watchdog_write_wtcr(qts, wd, WTCLK(1) | WTRF | WTIF | WTR); + g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(1)); + + qtest_quit(qts); +} + +/* Check a watchdog can generate interrupt and reset actions */ +static void test_reset_action(gconstpointer watchdog) +{ + const Watchdog *wd = watchdog; + QTestState *qts = qtest_init("-machine quanta-gsj"); + QDict *ad; + + qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic"); + + watchdog_write_wtcr(qts, wd, + WTCLK(0) | WTE | WTRF | WTRE | WTIF | WTIE | WTR); + g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, + WTCLK(0) | WTE | WTRE | WTIE); + + /* Check a watchdog can generate an interrupt */ + qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd)); + g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, + WTCLK(0) | WTE | WTIF | WTIE | WTRE); + g_assert_true(qtest_get_irq(qts, wd->irq)); + + /* Check a watchdog can generate a reset signal */ + qtest_clock_step(qts, watchdog_calculate_steps(RESET_CYCLES, + watchdog_prescaler(qts, wd))); + ad = get_watchdog_action(qts); + /* The signal is a reset signal */ + g_assert_false(strcmp(qdict_get_str(ad, "action"), "reset")); + qobject_unref(ad); + qtest_qmp_eventwait(qts, "RESET"); + /* + * Make sure WTCR is reset to default except for WTRF bit which shouldn't + * be reset. + */ + g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(1) | WTRF); + qtest_quit(qts); +} + +/* Check a watchdog works with all possible WTCLK prescalers and WTIS cycles */ +static void test_prescaler(gconstpointer watchdog) +{ + const Watchdog *wd = watchdog; + + for (int wtclk = 0; wtclk < 4; ++wtclk) { + for (int wtis = 0; wtis < 4; ++wtis) { + QTestState *qts = qtest_init("-machine quanta-gsj"); + + qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic"); + watchdog_write_wtcr(qts, wd, + WTCLK(wtclk) | WTE | WTIF | WTIS(wtis) | WTIE | WTR); + /* + * The interrupt doesn't fire until watchdog_interrupt_steps() + * cycles passed + */ + qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd) - 1); + g_assert_false(watchdog_read_wtcr(qts, wd) & WTIF); + g_assert_false(qtest_get_irq(qts, wd->irq)); + qtest_clock_step(qts, 1); + g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF); + g_assert_true(qtest_get_irq(qts, wd->irq)); + + qtest_quit(qts); + } + } +} + +/* + * Check a watchdog doesn't fire if corresponding flags (WTIE and WTRE) are not + * set. + */ +static void test_enabling_flags(gconstpointer watchdog) +{ + const Watchdog *wd = watchdog; + QTestState *qts; + QDict *rsp; + + /* Neither WTIE or WTRE is set, no interrupt or reset should happen */ + qts = qtest_init("-machine quanta-gsj"); + qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic"); + watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIF | WTRF | WTR); + qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd)); + g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF); + g_assert_false(qtest_get_irq(qts, wd->irq)); + qtest_clock_step(qts, watchdog_calculate_steps(RESET_CYCLES, + watchdog_prescaler(qts, wd))); + g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF); + g_assert_false(watchdog_read_wtcr(qts, wd) & WTRF); + qtest_quit(qts); + + /* Only WTIE is set, interrupt is triggered but reset should not happen */ + qts = qtest_init("-machine quanta-gsj"); + qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic"); + watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIF | WTIE | WTRF | WTR); + qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd)); + g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF); + g_assert_true(qtest_get_irq(qts, wd->irq)); + qtest_clock_step(qts, watchdog_calculate_steps(RESET_CYCLES, + watchdog_prescaler(qts, wd))); + g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF); + g_assert_false(watchdog_read_wtcr(qts, wd) & WTRF); + qtest_quit(qts); + + /* Only WTRE is set, interrupt is triggered but reset should not happen */ + qts = qtest_init("-machine quanta-gsj"); + qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic"); + watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIF | WTRE | WTRF | WTR); + qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd)); + g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF); + g_assert_false(qtest_get_irq(qts, wd->irq)); + qtest_clock_step(qts, watchdog_calculate_steps(RESET_CYCLES, + watchdog_prescaler(qts, wd))); + rsp = get_watchdog_action(qts); + g_assert_false(strcmp(qdict_get_str(rsp, "action"), "reset")); + qobject_unref(rsp); + qtest_qmp_eventwait(qts, "RESET"); + qtest_quit(qts); + + /* + * The case when both flags are set is already tested in + * test_reset_action(). + */ +} + +/* Check a watchdog can pause and resume by setting WTE bits */ +static void test_pause(gconstpointer watchdog) +{ + const Watchdog *wd = watchdog; + QTestState *qts; + int64_t remaining_steps, steps; + + qts = qtest_init("-machine quanta-gsj"); + qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic"); + watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIF | WTIE | WTRF | WTR); + remaining_steps = watchdog_interrupt_steps(qts, wd); + g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(0) | WTE | WTIE); + + /* Run for half of the execution period. */ + steps = remaining_steps / 2; + remaining_steps -= steps; + qtest_clock_step(qts, steps); + + /* Pause the watchdog */ + watchdog_write_wtcr(qts, wd, WTCLK(0) | WTIE); + g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(0) | WTIE); + + /* Run for a long period of time, the watchdog shouldn't fire */ + qtest_clock_step(qts, steps << 4); + g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(0) | WTIE); + g_assert_false(qtest_get_irq(qts, wd->irq)); + + /* Resume the watchdog */ + watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIE); + g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(0) | WTE | WTIE); + + /* Run for the reset of the execution period, the watchdog should fire */ + qtest_clock_step(qts, remaining_steps); + g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, + WTCLK(0) | WTE | WTIF | WTIE); + g_assert_true(qtest_get_irq(qts, wd->irq)); + + qtest_quit(qts); +} + +static void watchdog_add_test(const char *name, const Watchdog* wd, + GTestDataFunc fn) +{ + g_autofree char *full_name = g_strdup_printf( + "npcm7xx_watchdog_timer[%d]/%s", watchdog_index(wd), name); + qtest_add_data_func(full_name, wd, fn); +} +#define add_test(name, td) watchdog_add_test(#name, td, test_##name) + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + g_test_set_nonfatal_assertions(); + + for (int i = 0; i < ARRAY_SIZE(watchdog_list); ++i) { + const Watchdog *wd = &watchdog_list[i]; + + add_test(init, wd); + add_test(reset_action, wd); + add_test(prescaler, wd); + add_test(enabling_flags, wd); + add_test(pause, wd); + } + + return g_test_run(); +} diff --git a/tests/qtest/numa-test.c b/tests/qtest/numa-test.c index e1ed6d4322bafdbff03bb2721beae5ca62f051c4..b25ebf97d8c52339c74592b2e282d0d3f0e740d7 100644 --- a/tests/qtest/numa-test.c +++ b/tests/qtest/numa-test.c @@ -10,7 +10,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qlist.h" diff --git a/tests/qtest/nvme-test.c b/tests/qtest/nvme-test.c index ff0442150c5bee79847bbc9cf7fc428791999efd..d32c953a3824e429b7d78f761f30995afad7e06b 100644 --- a/tests/qtest/nvme-test.c +++ b/tests/qtest/nvme-test.c @@ -10,7 +10,7 @@ #include "qemu/osdep.h" #include "qemu/module.h" #include "qemu/units.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "libqos/qgraph.h" #include "libqos/pci.h" diff --git a/tests/qtest/pca9552-test.c b/tests/qtest/pca9552-test.c index d80ed93cd3a519fdebe93f9af386fc11fea18007..42a131266512c77cff0440f86b192f965a1613ad 100644 --- a/tests/qtest/pca9552-test.c +++ b/tests/qtest/pca9552-test.c @@ -9,7 +9,7 @@ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "libqos/qgraph.h" #include "libqos/i2c.h" #include "hw/misc/pca9552_regs.h" diff --git a/tests/qtest/pci-test.c b/tests/qtest/pci-test.c index 4b2092b94973abcc3dd704ab5bdd55c1810eb9c4..e15d4d94d1d0c65b20981cd4c5fd350835ce5473 100644 --- a/tests/qtest/pci-test.c +++ b/tests/qtest/pci-test.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/module.h" #include "libqos/qgraph.h" #include "libqos/pci.h" diff --git a/tests/qtest/pcnet-test.c b/tests/qtest/pcnet-test.c index 900944fa7e34c220418bca663240be5fde61b3ba..7583aeb3c38ff3758eaca23e4d72971dd9f2e5de 100644 --- a/tests/qtest/pcnet-test.c +++ b/tests/qtest/pcnet-test.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/module.h" #include "libqos/qgraph.h" #include "libqos/pci.h" diff --git a/tests/qtest/pflash-cfi02-test.c b/tests/qtest/pflash-cfi02-test.c index 17aa669b2eadd8a21a5d2c2c090aa301e5d25b63..afb702b565c816cc8aa70c8c151bfdc580a23cc8 100644 --- a/tests/qtest/pflash-cfi02-test.c +++ b/tests/qtest/pflash-cfi02-test.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" /* * To test the pflash_cfi02 device, we run QEMU with the musicpal machine with diff --git a/tests/qtest/pnv-xscom-test.c b/tests/qtest/pnv-xscom-test.c index 2c46d5cf6de3c9e85e700d6e884ad8c6e01f769a..c8d40433620af77afaa9873282b539b2ff46e83a 100644 --- a/tests/qtest/pnv-xscom-test.c +++ b/tests/qtest/pnv-xscom-test.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" typedef enum PnvChipType { PNV_CHIP_POWER8E, /* AKA Murano (default) */ diff --git a/tests/qtest/prom-env-test.c b/tests/qtest/prom-env-test.c index 60e6ec315335ce59890c54cb62343ee3ec87ad9c..f41d80154a5135799dcbddfff94c5ce54e65268c 100644 --- a/tests/qtest/prom-env-test.c +++ b/tests/qtest/prom-env-test.c @@ -20,7 +20,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "libqos/libqos-spapr.h" #define MAGIC 0xcafec0de diff --git a/tests/qtest/pvpanic-test.c b/tests/qtest/pvpanic-test.c index ff9176adf3ce2ddb60ce7a44b56be6f67520d96f..016b32ebee55297a187b077eef22518855333249 100644 --- a/tests/qtest/pvpanic-test.c +++ b/tests/qtest/pvpanic-test.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qapi/qmp/qdict.h" static void test_panic(void) @@ -20,13 +20,11 @@ static void test_panic(void) qts = qtest_init("-device pvpanic"); val = qtest_inb(qts, 0x505); - g_assert_cmpuint(val, ==, 1); + g_assert_cmpuint(val, ==, 3); qtest_outb(qts, 0x505, 0x1); - response = qtest_qmp_receive(qts); - g_assert(qdict_haskey(response, "event")); - g_assert_cmpstr(qdict_get_str(response, "event"), ==, "GUEST_PANICKED"); + response = qtest_qmp_eventwait_ref(qts, "GUEST_PANICKED"); g_assert(qdict_haskey(response, "data")); data = qdict_get_qdict(response, "data"); g_assert(qdict_haskey(data, "action")); diff --git a/tests/qtest/pxe-test.c b/tests/qtest/pxe-test.c index 1161a773a4a77b429c8887dc913d731e4cf2cda9..32bbae33c5977c700402c6381a8c1d562c32b601 100644 --- a/tests/qtest/pxe-test.c +++ b/tests/qtest/pxe-test.c @@ -15,7 +15,7 @@ #include "qemu/osdep.h" #include #include "qemu-common.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "boot-sector.h" #include "libqos/libqos-spapr.h" diff --git a/tests/qtest/q35-test.c b/tests/qtest/q35-test.c index c922d81bc020739074c86e6c43a152d42d7ec91b..b7cf1449906f568bde04578d63cf29878b7a8e1b 100644 --- a/tests/qtest/q35-test.c +++ b/tests/qtest/q35-test.c @@ -10,7 +10,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "libqos/pci.h" #include "libqos/pci-pc.h" #include "hw/pci-host/q35.h" diff --git a/tests/qtest/qmp-cmd-test.c b/tests/qtest/qmp-cmd-test.c index 9f5228cd99515465cb1f73e2c0a01082285e686f..1c7186e53c82ba6e9a6289d50b75bd00ed00f31a 100644 --- a/tests/qtest/qmp-cmd-test.c +++ b/tests/qtest/qmp-cmd-test.c @@ -11,7 +11,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qapi/error.h" #include "qapi/qapi-visit-introspect.h" #include "qapi/qmp/qdict.h" @@ -31,6 +31,9 @@ static int query_error_class(const char *cmd) #ifndef CONFIG_SPICE { "query-spice", ERROR_CLASS_COMMAND_NOT_FOUND }, #endif +#ifndef CONFIG_TCG + { "query-replay", ERROR_CLASS_COMMAND_NOT_FOUND }, +#endif #ifndef CONFIG_VNC { "query-vnc", ERROR_CLASS_GENERIC_ERROR }, { "query-vnc-servers", ERROR_CLASS_GENERIC_ERROR }, @@ -82,9 +85,9 @@ static void test_query(const void *data) qtest_quit(qts); } -static bool query_is_blacklisted(const char *cmd) +static bool query_is_ignored(const char *cmd) { - const char *blacklist[] = { + const char *ignored[] = { /* Not actually queries: */ "add-fd", /* Success depends on target arch: */ @@ -101,8 +104,8 @@ static bool query_is_blacklisted(const char *cmd) }; int i; - for (i = 0; blacklist[i]; i++) { - if (!strcmp(cmd, blacklist[i])) { + for (i = 0; ignored[i]; i++) { + if (!strcmp(cmd, ignored[i])) { return true; } } @@ -179,7 +182,7 @@ static void add_query_tests(QmpSchema *schema) continue; } - if (query_is_blacklisted(si->name)) { + if (query_is_ignored(si->name)) { continue; } @@ -200,16 +203,129 @@ static void add_query_tests(QmpSchema *schema) } } -static void test_object_add_without_props(void) +static void test_object_add_failure_modes(void) { QTestState *qts; QDict *resp; + /* attempt to create an object without props */ qts = qtest_init(common_args); resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" - " {'qom-type': 'memory-backend-ram', 'id': 'ram1' } }"); + " {'qom-type': 'memory-backend-ram', 'id': 'ram1' } }"); + g_assert_nonnull(resp); + qmp_expect_error_and_unref(resp, "GenericError"); + + /* attempt to create an object without qom-type */ + resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" + " {'id': 'ram1' } }"); + g_assert_nonnull(resp); + qmp_expect_error_and_unref(resp, "GenericError"); + + /* attempt to delete an object that does not exist */ + resp = qtest_qmp(qts, "{'execute': 'object-del', 'arguments':" + " {'id': 'ram1' } }"); + g_assert_nonnull(resp); + qmp_expect_error_and_unref(resp, "GenericError"); + + /* attempt to create 2 objects with duplicate id */ + resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" + " {'qom-type': 'memory-backend-ram', 'id': 'ram1'," + " 'props': {'size': 1048576 } } }"); + g_assert_nonnull(resp); + g_assert(qdict_haskey(resp, "return")); + qobject_unref(resp); + + resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" + " {'qom-type': 'memory-backend-ram', 'id': 'ram1'," + " 'props': {'size': 1048576 } } }"); + g_assert_nonnull(resp); + qmp_expect_error_and_unref(resp, "GenericError"); + + /* delete ram1 object */ + resp = qtest_qmp(qts, "{'execute': 'object-del', 'arguments':" + " {'id': 'ram1' } }"); + g_assert_nonnull(resp); + g_assert(qdict_haskey(resp, "return")); + qobject_unref(resp); + + /* attempt to create an object with a property of a wrong type */ + resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" + " {'qom-type': 'memory-backend-ram', 'id': 'ram1'," + " 'props': {'size': '1048576' } } }"); + g_assert_nonnull(resp); + /* now do it right */ + qmp_expect_error_and_unref(resp, "GenericError"); + + resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" + " {'qom-type': 'memory-backend-ram', 'id': 'ram1'," + " 'props': {'size': 1048576 } } }"); + g_assert_nonnull(resp); + g_assert(qdict_haskey(resp, "return")); + qobject_unref(resp); + + /* delete ram1 object */ + resp = qtest_qmp(qts, "{'execute': 'object-del', 'arguments':" + " {'id': 'ram1' } }"); + g_assert_nonnull(resp); + g_assert(qdict_haskey(resp, "return")); + qobject_unref(resp); + + /* attempt to create an object without the id */ + resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" + " {'qom-type': 'memory-backend-ram'," + " 'props': {'size': 1048576 } } }"); + g_assert_nonnull(resp); + qmp_expect_error_and_unref(resp, "GenericError"); + + /* now do it right */ + resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" + " {'qom-type': 'memory-backend-ram', 'id': 'ram1'," + " 'props': {'size': 1048576 } } }"); + g_assert_nonnull(resp); + g_assert(qdict_haskey(resp, "return")); + qobject_unref(resp); + + /* delete ram1 object */ + resp = qtest_qmp(qts, "{'execute': 'object-del', 'arguments':" + " {'id': 'ram1' } }"); + g_assert_nonnull(resp); + g_assert(qdict_haskey(resp, "return")); + qobject_unref(resp); + + /* attempt to set a non existing property */ + resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" + " {'qom-type': 'memory-backend-ram', 'id': 'ram1'," + " 'props': {'sized': 1048576 } } }"); g_assert_nonnull(resp); - qmp_assert_error_class(resp, "GenericError"); + qmp_expect_error_and_unref(resp, "GenericError"); + + /* now do it right */ + resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" + " {'qom-type': 'memory-backend-ram', 'id': 'ram1'," + " 'props': {'size': 1048576 } } }"); + g_assert_nonnull(resp); + g_assert(qdict_haskey(resp, "return")); + qobject_unref(resp); + + /* delete ram1 object without id */ + resp = qtest_qmp(qts, "{'execute': 'object-del', 'arguments':" + " {'ida': 'ram1' } }"); + g_assert_nonnull(resp); + qobject_unref(resp); + + /* delete ram1 object */ + resp = qtest_qmp(qts, "{'execute': 'object-del', 'arguments':" + " {'id': 'ram1' } }"); + g_assert_nonnull(resp); + g_assert(qdict_haskey(resp, "return")); + qobject_unref(resp); + + /* delete ram1 object that does not exist anymore*/ + resp = qtest_qmp(qts, "{'execute': 'object-del', 'arguments':" + " {'id': 'ram1' } }"); + g_assert_nonnull(resp); + qmp_expect_error_and_unref(resp, "GenericError"); + qtest_quit(qts); } @@ -223,9 +339,8 @@ int main(int argc, char *argv[]) qmp_schema_init(&schema); add_query_tests(&schema); - qtest_add_func("qmp/object-add-without-props", - test_object_add_without_props); - /* TODO: add coverage of generic object-add failure modes */ + qtest_add_func("qmp/object-add-failure-modes", + test_object_add_failure_modes); ret = g_test_run(); diff --git a/tests/qtest/qmp-test.c b/tests/qtest/qmp-test.c index 1a8876b6cacd94d40b408aab1317b026f22fd5d3..eb1cd8abb8c8644714092778cef0ced6a0841a10 100644 --- a/tests/qtest/qmp-test.c +++ b/tests/qtest/qmp-test.c @@ -11,7 +11,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qapi/error.h" #include "qapi/qapi-visit-control.h" #include "qapi/qmp/qdict.h" @@ -38,7 +38,7 @@ static void assert_recovered(QTestState *qts) QDict *resp; resp = qtest_qmp(qts, "{ 'execute': 'no-such-cmd' }"); - qmp_assert_error_class(resp, "CommandNotFound"); + qmp_expect_error_and_unref(resp, "CommandNotFound"); } static void test_malformed(QTestState *qts) @@ -47,59 +47,59 @@ static void test_malformed(QTestState *qts) /* syntax error */ qtest_qmp_send_raw(qts, "{]\n"); - resp = qtest_qmp_receive(qts); - qmp_assert_error_class(resp, "GenericError"); + resp = qtest_qmp_receive_dict(qts); + qmp_expect_error_and_unref(resp, "GenericError"); assert_recovered(qts); /* lexical error: impossible byte outside string */ qtest_qmp_send_raw(qts, "{\xFF"); - resp = qtest_qmp_receive(qts); - qmp_assert_error_class(resp, "GenericError"); + resp = qtest_qmp_receive_dict(qts); + qmp_expect_error_and_unref(resp, "GenericError"); assert_recovered(qts); /* lexical error: funny control character outside string */ qtest_qmp_send_raw(qts, "{\x01"); - resp = qtest_qmp_receive(qts); - qmp_assert_error_class(resp, "GenericError"); + resp = qtest_qmp_receive_dict(qts); + qmp_expect_error_and_unref(resp, "GenericError"); assert_recovered(qts); /* lexical error: impossible byte in string */ qtest_qmp_send_raw(qts, "{'bad \xFF"); - resp = qtest_qmp_receive(qts); - qmp_assert_error_class(resp, "GenericError"); + resp = qtest_qmp_receive_dict(qts); + qmp_expect_error_and_unref(resp, "GenericError"); assert_recovered(qts); /* lexical error: control character in string */ qtest_qmp_send_raw(qts, "{'execute': 'nonexistent', 'id':'\n"); - resp = qtest_qmp_receive(qts); - qmp_assert_error_class(resp, "GenericError"); + resp = qtest_qmp_receive_dict(qts); + qmp_expect_error_and_unref(resp, "GenericError"); assert_recovered(qts); /* lexical error: interpolation */ qtest_qmp_send_raw(qts, "%%p"); - resp = qtest_qmp_receive(qts); - qmp_assert_error_class(resp, "GenericError"); + resp = qtest_qmp_receive_dict(qts); + qmp_expect_error_and_unref(resp, "GenericError"); assert_recovered(qts); /* Not even a dictionary */ resp = qtest_qmp(qts, "null"); - qmp_assert_error_class(resp, "GenericError"); + qmp_expect_error_and_unref(resp, "GenericError"); /* No "execute" key */ resp = qtest_qmp(qts, "{}"); - qmp_assert_error_class(resp, "GenericError"); + qmp_expect_error_and_unref(resp, "GenericError"); /* "execute" isn't a string */ resp = qtest_qmp(qts, "{ 'execute': true }"); - qmp_assert_error_class(resp, "GenericError"); + qmp_expect_error_and_unref(resp, "GenericError"); /* "arguments" isn't a dictionary */ resp = qtest_qmp(qts, "{ 'execute': 'no-such-cmd', 'arguments': [] }"); - qmp_assert_error_class(resp, "GenericError"); + qmp_expect_error_and_unref(resp, "GenericError"); /* extra key */ resp = qtest_qmp(qts, "{ 'execute': 'no-such-cmd', 'extra': true }"); - qmp_assert_error_class(resp, "GenericError"); + qmp_expect_error_and_unref(resp, "GenericError"); } static void test_qmp_protocol(void) @@ -111,7 +111,7 @@ static void test_qmp_protocol(void) qts = qtest_init_without_qmp_handshake(common_args); /* Test greeting */ - resp = qtest_qmp_receive(qts); + resp = qtest_qmp_receive_dict(qts); q = qdict_get_qdict(resp, "QMP"); g_assert(q); test_version(qdict_get(q, "version")); @@ -121,7 +121,7 @@ static void test_qmp_protocol(void) /* Test valid command before handshake */ resp = qtest_qmp(qts, "{ 'execute': 'query-version' }"); - qmp_assert_error_class(resp, "CommandNotFound"); + qmp_expect_error_and_unref(resp, "CommandNotFound"); /* Test malformed commands before handshake */ test_malformed(qts); @@ -134,7 +134,7 @@ static void test_qmp_protocol(void) /* Test repeated handshake */ resp = qtest_qmp(qts, "{ 'execute': 'qmp_capabilities' }"); - qmp_assert_error_class(resp, "CommandNotFound"); + qmp_expect_error_and_unref(resp, "CommandNotFound"); /* Test valid command */ resp = qtest_qmp(qts, "{ 'execute': 'query-version' }"); @@ -154,7 +154,7 @@ static void test_qmp_protocol(void) /* Test command failure with 'id' */ resp = qtest_qmp(qts, "{ 'execute': 'human-monitor-command', 'id': 2 }"); g_assert_cmpint(qdict_get_int(resp, "id"), ==, 2); - qmp_assert_error_class(resp, "GenericError"); + qmp_expect_error_and_unref(resp, "GenericError"); qtest_quit(qts); } @@ -205,7 +205,7 @@ static void send_oob_cmd_that_fails(QTestState *s, const char *id) static void recv_cmd_id(QTestState *s, const char *id) { - QDict *resp = qtest_qmp_receive(s); + QDict *resp = qtest_qmp_receive_dict(s); g_assert_cmpstr(qdict_get_try_str(resp, "id"), ==, id); qobject_unref(resp); @@ -222,7 +222,7 @@ static void test_qmp_oob(void) qts = qtest_init_without_qmp_handshake(common_args); /* Check the greeting message. */ - resp = qtest_qmp_receive(qts); + resp = qtest_qmp_receive_dict(qts); q = qdict_get_qdict(resp, "QMP"); g_assert(q); capabilities = qdict_get_qlist(q, "capabilities"); @@ -327,7 +327,7 @@ static void test_qmp_missing_any_arg(void) resp = qtest_qmp(qts, "{'execute': 'qom-set', 'arguments':" " { 'path': '/machine', 'property': 'rtc-time' } }"); g_assert_nonnull(resp); - qmp_assert_error_class(resp, "GenericError"); + qmp_expect_error_and_unref(resp, "GenericError"); qtest_quit(qts); } diff --git a/tests/qtest/qom-test.c b/tests/qtest/qom-test.c index e338a411945e4073e710c702061f67a0bb6e384b..eb34af843b794dbc028cfb9382ed9184f30fb1eb 100644 --- a/tests/qtest/qom-test.c +++ b/tests/qtest/qom-test.c @@ -13,7 +13,7 @@ #include "qapi/qmp/qdict.h" #include "qapi/qmp/qlist.h" #include "qemu/cutils.h" -#include "libqtest.h" +#include "libqos/libqtest.h" static void test_properties(QTestState *qts, const char *path, bool recurse) { @@ -81,11 +81,6 @@ static void add_machine_test_case(const char *mname) { char *path; - /* Ignore blacklisted machines that have known problems */ - if (!memcmp("xenfv", mname, 5) || g_str_equal("xenpv", mname)) { - return; - } - path = g_strdup_printf("qom/%s", mname); qtest_add_data_func(path, g_strdup(mname), test_machine); g_free(path); diff --git a/tests/qtest/qos-test.c b/tests/qtest/qos-test.c index 3062a13557aeab42113fe0ff6b0072d939fa7b3d..8fdf87b1839bd4382d9dcdf8de03b5834dfb214e 100644 --- a/tests/qtest/qos-test.c +++ b/tests/qtest/qos-test.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/qtest/rtas-test.c b/tests/qtest/rtas-test.c index 167b42db386dcc6212e8ec5f1f0f6ae9a995c517..16751dbd2f55369411d5449cec5732b4fb163acd 100644 --- a/tests/qtest/rtas-test.c +++ b/tests/qtest/rtas-test.c @@ -1,6 +1,6 @@ #include "qemu/osdep.h" #include "qemu/cutils.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "libqos/libqos-spapr.h" #include "libqos/rtas.h" @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) g_test_init(&argc, &argv, NULL); if (strcmp(arch, "ppc64")) { - g_printerr("RTAS requires ppc64-softmmu/qemu-system-ppc64\n"); + g_printerr("RTAS requires qemu-system-ppc64\n"); exit(EXIT_FAILURE); } qtest_add_func("rtas/get-time-of-day", test_rtas_get_time_of_day); diff --git a/tests/qtest/rtc-test.c b/tests/qtest/rtc-test.c index c7af34f6b1b2c124925174e5a8e6a9244d98c139..402ce2c60907233820df7f0c82373b361461d3fe 100644 --- a/tests/qtest/rtc-test.c +++ b/tests/qtest/rtc-test.c @@ -292,7 +292,7 @@ static void alarm_time(void) break; } - clock_step(1000000000); + clock_step(NANOSECONDS_PER_SECOND); } g_assert(get_irq(RTC_ISA_IRQ)); diff --git a/tests/qtest/sdhci-test.c b/tests/qtest/sdhci-test.c index 6275e7626c215638d7647bb2088f59b93a908c3c..a110cfe3219ce2b254218fcda89dbd9dadecdfe4 100644 --- a/tests/qtest/sdhci-test.c +++ b/tests/qtest/sdhci-test.c @@ -10,7 +10,7 @@ #include "qemu/osdep.h" #include "hw/registerfields.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/module.h" #include "libqos/pci-pc.h" #include "hw/pci/pci.h" diff --git a/tests/qtest/spapr-phb-test.c b/tests/qtest/spapr-phb-test.c index 093dc22f2f41d707ffcdbe3af6a8c897669ea0b6..ea8d59650721533b23e3c8836079b2834be314bf 100644 --- a/tests/qtest/spapr-phb-test.c +++ b/tests/qtest/spapr-phb-test.c @@ -9,7 +9,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/module.h" #include "libqos/qgraph.h" diff --git a/tests/qtest/tco-test.c b/tests/qtest/tco-test.c index 254f7353701c788727af9faedce3ad7697519c95..47bc7ad3019d00967ec12403624c1316241e6cdd 100644 --- a/tests/qtest/tco-test.c +++ b/tests/qtest/tco-test.c @@ -9,7 +9,7 @@ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "libqos/pci.h" #include "libqos/pci-pc.h" #include "qapi/qmp/qdict.h" diff --git a/tests/qtest/test-filter-mirror.c b/tests/qtest/test-filter-mirror.c index 1e3ced84a92847ed277f44e5fe5129c758e000c7..bc0dee64dd93b8f6191a61f477b054c653d9e343 100644 --- a/tests/qtest/test-filter-mirror.c +++ b/tests/qtest/test-filter-mirror.c @@ -10,7 +10,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qapi/qmp/qdict.h" #include "qemu/iov.h" #include "qemu/sockets.h" diff --git a/tests/qtest/test-filter-redirector.c b/tests/qtest/test-filter-redirector.c index e4d53220fd6498a524d80f9c4d9aeb2b263461da..829db8c2eaa199aa59779d495bc6cf5334ce9966 100644 --- a/tests/qtest/test-filter-redirector.c +++ b/tests/qtest/test-filter-redirector.c @@ -52,7 +52,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qapi/qmp/qdict.h" #include "qemu/iov.h" #include "qemu/sockets.h" diff --git a/tests/qtest/test-hmp.c b/tests/qtest/test-hmp.c index f8aa5f92c5d714bfeed973b7b2427f482eecb8dc..94a8023173e3f6e4ffd43b259161b503970515f4 100644 --- a/tests/qtest/test-hmp.c +++ b/tests/qtest/test-hmp.c @@ -15,7 +15,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" static int verbose; @@ -27,7 +27,6 @@ static const char *hmp_cmds[] = { "chardev-change testchardev1 ringbuf", "chardev-remove testchardev1", "commit all", - "cpu-add 1", "cpu 0", "device_add ?", "device_add usb-mouse,id=mouse1", @@ -61,6 +60,7 @@ static const char *hmp_cmds[] = { "p $pc + 8", "qom-list /", "qom-set /machine initrd test", + "qom-get /machine initrd", "screendump /dev/null", "sendkey x", "singlestep on", @@ -142,11 +142,6 @@ static void add_machine_test_case(const char *mname) { char *path; - /* Ignore blacklisted machines that have known problems */ - if (!memcmp("xenfv", mname, 5) || g_str_equal("xenpv", mname)) { - return; - } - path = g_strdup_printf("hmp/%s", mname); qtest_add_data_func(path, g_strdup(mname), test_machine); g_free(path); diff --git a/tests/qtest/test-x86-cpuid-compat.c b/tests/qtest/test-x86-cpuid-compat.c index 772287bdb4844035d340c384bb142ca33b5cbf08..7ca1883a299fce22bfaa8ac861ea33a2c947e20d 100644 --- a/tests/qtest/test-x86-cpuid-compat.c +++ b/tests/qtest/test-x86-cpuid-compat.c @@ -256,7 +256,7 @@ int main(int argc, char **argv) "-cpu 486,+invtsc", "xlevel", 0x80000007); /* CPUID[8000_000A].EDX: */ add_cpuid_test("x86/cpuid/auto-xlevel/486/npt", - "-cpu 486,+npt", "xlevel", 0x8000000A); + "-cpu 486,+svm,+npt", "xlevel", 0x8000000A); /* CPUID[C000_0001].EDX: */ add_cpuid_test("x86/cpuid/auto-xlevel2/phenom/xstore", "-cpu phenom,+xstore", "xlevel2", 0xC0000001); @@ -348,7 +348,7 @@ int main(int argc, char **argv) "-machine pc-i440fx-2.4 -cpu SandyBridge,", "xlevel", 0x80000008); add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.4/npt-on", - "-machine pc-i440fx-2.4 -cpu SandyBridge,+npt", + "-machine pc-i440fx-2.4 -cpu SandyBridge,+svm,+npt", "xlevel", 0x80000008); /* Test feature parsing */ diff --git a/tests/qtest/tpm-crb-swtpm-test.c b/tests/qtest/tpm-crb-swtpm-test.c index 55fdb5657d910ca3feaad9b5b762d2471778f6ba..1d82a48c04bec4ca7bb999d0b7f08f2dee425a7c 100644 --- a/tests/qtest/tpm-crb-swtpm-test.c +++ b/tests/qtest/tpm-crb-swtpm-test.c @@ -15,7 +15,7 @@ #include "qemu/osdep.h" #include -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/module.h" #include "tpm-tests.h" #include "hw/acpi/tpm.h" diff --git a/tests/qtest/tpm-emu.c b/tests/qtest/tpm-emu.c index c43ac4aef80a5d11298092adeafd37ab8cd6443e..2e8eb7b94f25d5ab7bb24e9614c7d4cbb9388ba2 100644 --- a/tests/qtest/tpm-emu.c +++ b/tests/qtest/tpm-emu.c @@ -13,7 +13,7 @@ #include "qemu/osdep.h" #include -#include "hw/tpm/tpm_ioctl.h" +#include "backends/tpm/tpm_ioctl.h" #include "io/channel-socket.h" #include "qapi/error.h" #include "tpm-emu.h" @@ -49,7 +49,6 @@ static void *tpm_emu_tpm_thread(void *data) s->tpm_msg->tag = be16_to_cpu(s->tpm_msg->tag); s->tpm_msg->len = be32_to_cpu(s->tpm_msg->len); g_assert_cmpint(s->tpm_msg->len, >=, minhlen); - g_assert_cmpint(s->tpm_msg->tag, ==, TPM2_ST_NO_SESSIONS); s->tpm_msg = g_realloc(s->tpm_msg, s->tpm_msg->len); qio_channel_read(ioc, (char *)&s->tpm_msg->code, diff --git a/tests/qtest/tpm-emu.h b/tests/qtest/tpm-emu.h index a4f1d6422695ec7633b264ca6d27412bdc2ce940..73f3bed0c4bceeefb14b3c8fa219eefa746907ed 100644 --- a/tests/qtest/tpm-emu.h +++ b/tests/qtest/tpm-emu.h @@ -16,6 +16,9 @@ #define TPM_RC_FAILURE 0x101 #define TPM2_ST_NO_SESSIONS 0x8001 +#include "qemu/sockets.h" +#include "io/channel.h" + struct tpm_hdr { uint16_t tag; uint32_t len; diff --git a/tests/qtest/tpm-tests.c b/tests/qtest/tpm-tests.c index a2f2838e15b9b49b892b3c755e1d45e8bb2a2fa1..0da3a8a4df530cae18c25ff4e45ad3b146c5d358 100644 --- a/tests/qtest/tpm-tests.c +++ b/tests/qtest/tpm-tests.c @@ -59,7 +59,7 @@ void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx, tpm_util_startup(s, tx); tpm_util_pcrextend(s, tx); - unsigned char tpm_pcrread_resp[] = + static const unsigned char tpm_pcrread_resp[] = "\x80\x01\x00\x00\x00\x3e\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00" "\x00\x01\x00\x0b\x03\x00\x04\x00\x00\x00\x00\x01\x00\x20\xf6\x85" "\x98\xe5\x86\x8d\xe6\x8b\x97\x29\x99\x60\xf2\x71\x7d\x17\x67\x89" @@ -70,10 +70,8 @@ void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx, qtest_end(); tpm_util_swtpm_kill(swtpm_pid); - if (addr) { - g_unlink(addr->u.q_unix.path); - qapi_free_SocketAddress(addr); - } + g_unlink(addr->u.q_unix.path); + qapi_free_SocketAddress(addr); } void tpm_test_swtpm_migration_test(const char *src_tpm_path, @@ -107,7 +105,7 @@ void tpm_test_swtpm_migration_test(const char *src_tpm_path, tpm_util_startup(src_qemu, tx); tpm_util_pcrextend(src_qemu, tx); - unsigned char tpm_pcrread_resp[] = + static const unsigned char tpm_pcrread_resp[] = "\x80\x01\x00\x00\x00\x3e\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00" "\x00\x01\x00\x0b\x03\x00\x04\x00\x00\x00\x00\x01\x00\x20\xf6\x85" "\x98\xe5\x86\x8d\xe6\x8b\x97\x29\x99\x60\xf2\x71\x7d\x17\x67\x89" diff --git a/tests/qtest/tpm-tis-device-swtpm-test.c b/tests/qtest/tpm-tis-device-swtpm-test.c index 7b200351426a38f3a187f09509d45cd1ded3d7fe..f7126eff9e742098697f0d3f66668fa3b0e06be0 100644 --- a/tests/qtest/tpm-tis-device-swtpm-test.c +++ b/tests/qtest/tpm-tis-device-swtpm-test.c @@ -16,7 +16,7 @@ #include "qemu/osdep.h" #include -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/module.h" #include "tpm-tests.h" #include "hw/acpi/tpm.h" diff --git a/tests/qtest/tpm-tis-swtpm-test.c b/tests/qtest/tpm-tis-swtpm-test.c index 90131cb3c487515f1a3f1124c8b9785296e1a11e..fa590e68f1155da83c1efa7b355fa54091881f83 100644 --- a/tests/qtest/tpm-tis-swtpm-test.c +++ b/tests/qtest/tpm-tis-swtpm-test.c @@ -15,7 +15,7 @@ #include "qemu/osdep.h" #include -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/module.h" #include "tpm-tests.h" #include "hw/acpi/tpm.h" diff --git a/tests/qtest/tpm-util.c b/tests/qtest/tpm-util.c index 34efae8f181d83bc34a62367ebc184a6702863de..5a33a6ef0f5957c961620b55d40cb12c2726a3a1 100644 --- a/tests/qtest/tpm-util.c +++ b/tests/qtest/tpm-util.c @@ -15,7 +15,7 @@ #include "qemu/osdep.h" #include "hw/acpi/tpm.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "tpm-util.h" #include "qapi/qmp/qdict.h" @@ -98,9 +98,9 @@ void tpm_util_tis_transfer(QTestState *s, void tpm_util_startup(QTestState *s, tx_func *tx) { unsigned char buffer[1024]; - unsigned char tpm_startup[] = + static const unsigned char tpm_startup[] = "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00"; - unsigned char tpm_startup_resp[] = + static const unsigned char tpm_startup_resp[] = "\x80\x01\x00\x00\x00\x0a\x00\x00\x00\x00"; tx(s, tpm_startup, sizeof(tpm_startup), buffer, sizeof(buffer)); @@ -112,14 +112,14 @@ void tpm_util_startup(QTestState *s, tx_func *tx) void tpm_util_pcrextend(QTestState *s, tx_func *tx) { unsigned char buffer[1024]; - unsigned char tpm_pcrextend[] = + static const unsigned char tpm_pcrextend[] = "\x80\x02\x00\x00\x00\x41\x00\x00\x01\x82\x00\x00\x00\x0a\x00\x00" "\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" "\x0b\x74\x65\x73\x74\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00"; - unsigned char tpm_pcrextend_resp[] = + static const unsigned char tpm_pcrextend_resp[] = "\x80\x02\x00\x00\x00\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x01\x00\x00"; @@ -133,13 +133,17 @@ void tpm_util_pcrread(QTestState *s, tx_func *tx, const unsigned char *exp_resp, size_t exp_resp_size) { unsigned char buffer[1024]; - unsigned char tpm_pcrread[] = + static const unsigned char tpm_pcrread[] = "\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b" "\x03\x00\x04\x00"; tx(s, tpm_pcrread, sizeof(tpm_pcrread), buffer, sizeof(buffer)); - g_assert_cmpmem(buffer, exp_resp_size, exp_resp, exp_resp_size); + /* skip pcrUpdateCounter (14th byte) in comparison */ + g_assert(exp_resp_size >= 15); + g_assert_cmpmem(buffer, 13, exp_resp, 13); + g_assert_cmpmem(&buffer[14], exp_resp_size - 14, + &exp_resp[14], exp_resp_size - 14); } bool tpm_util_swtpm_has_tpm2(void) @@ -233,12 +237,16 @@ void tpm_util_migrate(QTestState *who, const char *uri) void tpm_util_wait_for_migration_complete(QTestState *who) { while (true) { + QDict *rsp; QDict *rsp_return; bool completed; const char *status; - qtest_qmp_send(who, "{ 'execute': 'query-migrate' }"); - rsp_return = qtest_qmp_receive_success(who, NULL, NULL); + rsp = qtest_qmp(who, "{ 'execute': 'query-migrate' }"); + g_assert(qdict_haskey(rsp, "return")); + rsp_return = qdict_get_qdict(rsp, "return"); + + g_assert(!qdict_haskey(rsp_return, "error")); status = qdict_get_str(rsp_return, "status"); completed = strcmp(status, "completed") == 0; g_assert_cmpstr(status, !=, "failed"); diff --git a/tests/qtest/tulip-test.c b/tests/qtest/tulip-test.c index 2fb6c4d5a781f444ac1eedeb15d35d48af4d5bbc..da16cbfafcc277ab9a7e46d9a4d1627ce7199076 100644 --- a/tests/qtest/tulip-test.c +++ b/tests/qtest/tulip-test.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/module.h" #include "libqos/qgraph.h" #include "libqos/pci.h" diff --git a/tests/qtest/usb-hcd-ehci-test.c b/tests/qtest/usb-hcd-ehci-test.c index 5251d539e90f2ff914f7e8d1a5c51ce6ed68fb4c..c51e8bb223be1679051566438d151e6eb832daff 100644 --- a/tests/qtest/usb-hcd-ehci-test.c +++ b/tests/qtest/usb-hcd-ehci-test.c @@ -96,7 +96,7 @@ static void pci_ehci_port_1(void) static void pci_ehci_config(void) { /* hands over all ports from companion uhci to ehci */ - qpci_io_writew(ehci1.dev, ehci1.bar, 0x60, 1); + qpci_io_writel(ehci1.dev, ehci1.bar, 0x60, 1); } static void pci_uhci_port_2(void) diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c index 9ee0f1e4fd6cc05a46000c5ea84723797b8f7f2d..3df5322614674cd3ee587ad6042effb1b1702a7f 100644 --- a/tests/qtest/vhost-user-test.c +++ b/tests/qtest/vhost-user-test.c @@ -135,6 +135,10 @@ enum { TEST_FLAGS_END, }; +enum { + VHOST_USER_NET, +}; + typedef struct TestServer { gchar *socket_path; gchar *mig_path; @@ -154,10 +158,25 @@ typedef struct TestServer { bool test_fail; int test_flags; int queues; + struct vhost_user_ops *vu_ops; } TestServer; +struct vhost_user_ops { + /* Device types. */ + int type; + void (*append_opts)(TestServer *s, GString *cmd_line, + const char *chr_opts); + + /* VHOST-USER commands. */ + void (*set_features)(TestServer *s, CharBackend *chr, + VhostUserMsg *msg); + void (*get_protocol_features)(TestServer *s, + CharBackend *chr, VhostUserMsg *msg); +}; + static const char *init_hugepagefs(void); -static TestServer *test_server_new(const gchar *name); +static TestServer *test_server_new(const gchar *name, + struct vhost_user_ops *ops); static void test_server_free(TestServer *server); static void test_server_listen(TestServer *server); @@ -167,7 +186,7 @@ enum test_memfd { TEST_MEMFD_NO, }; -static void append_vhost_opts(TestServer *s, GString *cmd_line, +static void append_vhost_net_opts(TestServer *s, GString *cmd_line, const char *chr_opts) { g_string_append_printf(cmd_line, QEMU_CMD_CHR QEMU_CMD_NETDEV, @@ -332,25 +351,15 @@ static void chr_read(void *opaque, const uint8_t *buf, int size) break; case VHOST_USER_SET_FEATURES: - g_assert_cmpint(msg.payload.u64 & (0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES), - !=, 0ULL); - if (s->test_flags == TEST_FLAGS_DISCONNECT) { - qemu_chr_fe_disconnect(chr); - s->test_flags = TEST_FLAGS_BAD; + if (s->vu_ops->set_features) { + s->vu_ops->set_features(s, chr, &msg); } break; case VHOST_USER_GET_PROTOCOL_FEATURES: - /* send back features to qemu */ - msg.flags |= VHOST_USER_REPLY_MASK; - msg.size = sizeof(m.payload.u64); - msg.payload.u64 = 1 << VHOST_USER_PROTOCOL_F_LOG_SHMFD; - msg.payload.u64 |= 1 << VHOST_USER_PROTOCOL_F_CROSS_ENDIAN; - if (s->queues > 1) { - msg.payload.u64 |= 1 << VHOST_USER_PROTOCOL_F_MQ; + if (s->vu_ops->get_protocol_features) { + s->vu_ops->get_protocol_features(s, chr, &msg); } - p = (uint8_t *) &msg; - qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size); break; case VHOST_USER_GET_VRING_BASE: @@ -467,7 +476,8 @@ static const char *init_hugepagefs(void) #endif } -static TestServer *test_server_new(const gchar *name) +static TestServer *test_server_new(const gchar *name, + struct vhost_user_ops *ops) { TestServer *server = g_new0(TestServer, 1); char template[] = "/tmp/vhost-test-XXXXXX"; @@ -495,6 +505,7 @@ static TestServer *test_server_new(const gchar *name) server->log_fd = -1; server->queues = 1; + server->vu_ops = ops; return server; } @@ -669,11 +680,11 @@ static void vhost_user_test_cleanup(void *s) static void *vhost_user_test_setup(GString *cmd_line, void *arg) { - TestServer *server = test_server_new("vhost-user-test"); + TestServer *server = test_server_new("vhost-user-test", arg); test_server_listen(server); append_mem_opts(server, cmd_line, 256, TEST_MEMFD_AUTO); - append_vhost_opts(server, cmd_line, ""); + server->vu_ops->append_opts(server, cmd_line, ""); g_test_queue_destroy(vhost_user_test_cleanup, server); @@ -682,11 +693,11 @@ static void *vhost_user_test_setup(GString *cmd_line, void *arg) static void *vhost_user_test_setup_memfd(GString *cmd_line, void *arg) { - TestServer *server = test_server_new("vhost-user-test"); + TestServer *server = test_server_new("vhost-user-test", arg); test_server_listen(server); append_mem_opts(server, cmd_line, 256, TEST_MEMFD_YES); - append_vhost_opts(server, cmd_line, ""); + server->vu_ops->append_opts(server, cmd_line, ""); g_test_queue_destroy(vhost_user_test_cleanup, server); @@ -720,7 +731,7 @@ static void test_migrate(void *obj, void *arg, QGuestAllocator *alloc) return; } - dest = test_server_new("dest"); + dest = test_server_new("dest", s->vu_ops); dest_cmdline = g_string_new(qos_get_current_command_line()); uri = g_strdup_printf("%s%s", "unix:", dest->mig_path); @@ -730,7 +741,7 @@ static void test_migrate(void *obj, void *arg, QGuestAllocator *alloc) test_server_listen(dest); g_string_append_printf(dest_cmdline, " -incoming %s", uri); append_mem_opts(dest, dest_cmdline, 256, TEST_MEMFD_AUTO); - append_vhost_opts(dest, dest_cmdline, ""); + dest->vu_ops->append_opts(dest, dest_cmdline, ""); to = qtest_init(dest_cmdline->str); /* This would be where you call qos_allocate_objects(to, NULL), if you want @@ -831,11 +842,11 @@ connect_thread(gpointer data) static void *vhost_user_test_setup_reconnect(GString *cmd_line, void *arg) { - TestServer *s = test_server_new("reconnect"); + TestServer *s = test_server_new("reconnect", arg); g_thread_new("connect", connect_thread, s); append_mem_opts(s, cmd_line, 256, TEST_MEMFD_AUTO); - append_vhost_opts(s, cmd_line, ",server"); + s->vu_ops->append_opts(s, cmd_line, ",server"); g_test_queue_destroy(vhost_user_test_cleanup, s); @@ -866,13 +877,13 @@ static void test_reconnect(void *obj, void *arg, QGuestAllocator *alloc) static void *vhost_user_test_setup_connect_fail(GString *cmd_line, void *arg) { - TestServer *s = test_server_new("connect-fail"); + TestServer *s = test_server_new("connect-fail", arg); s->test_fail = true; g_thread_new("connect", connect_thread, s); append_mem_opts(s, cmd_line, 256, TEST_MEMFD_AUTO); - append_vhost_opts(s, cmd_line, ",server"); + s->vu_ops->append_opts(s, cmd_line, ",server"); g_test_queue_destroy(vhost_user_test_cleanup, s); @@ -881,13 +892,13 @@ static void *vhost_user_test_setup_connect_fail(GString *cmd_line, void *arg) static void *vhost_user_test_setup_flags_mismatch(GString *cmd_line, void *arg) { - TestServer *s = test_server_new("flags-mismatch"); + TestServer *s = test_server_new("flags-mismatch", arg); s->test_flags = TEST_FLAGS_DISCONNECT; g_thread_new("connect", connect_thread, s); append_mem_opts(s, cmd_line, 256, TEST_MEMFD_AUTO); - append_vhost_opts(s, cmd_line, ",server"); + s->vu_ops->append_opts(s, cmd_line, ",server"); g_test_queue_destroy(vhost_user_test_cleanup, s); @@ -924,11 +935,47 @@ static void test_multiqueue(void *obj, void *arg, QGuestAllocator *alloc) wait_for_rings_started(s, s->queues * 2); } +static void vu_net_set_features(TestServer *s, CharBackend *chr, + VhostUserMsg *msg) +{ + g_assert_cmpint(msg->payload.u64 & + (0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES), !=, 0ULL); + if (s->test_flags == TEST_FLAGS_DISCONNECT) { + qemu_chr_fe_disconnect(chr); + s->test_flags = TEST_FLAGS_BAD; + } +} + +static void vu_net_get_protocol_features(TestServer *s, CharBackend *chr, + VhostUserMsg *msg) +{ + /* send back features to qemu */ + msg->flags |= VHOST_USER_REPLY_MASK; + msg->size = sizeof(m.payload.u64); + msg->payload.u64 = 1 << VHOST_USER_PROTOCOL_F_LOG_SHMFD; + msg->payload.u64 |= 1 << VHOST_USER_PROTOCOL_F_CROSS_ENDIAN; + if (s->queues > 1) { + msg->payload.u64 |= 1 << VHOST_USER_PROTOCOL_F_MQ; + } + qemu_chr_fe_write_all(chr, (uint8_t *)msg, VHOST_USER_HDR_SIZE + msg->size); +} + +/* Each VHOST-USER device should have its ops structure defined. */ +static struct vhost_user_ops g_vu_net_ops = { + .type = VHOST_USER_NET, + + .append_opts = append_vhost_net_opts, + + .set_features = vu_net_set_features, + .get_protocol_features = vu_net_get_protocol_features, +}; + static void register_vhost_user_test(void) { QOSGraphTestOptions opts = { .before = vhost_user_test_setup, .subprocess = true, + .arg = &g_vu_net_ops, }; qemu_add_opts(&qemu_chardev_opts); diff --git a/tests/qtest/virtio-9p-test.c b/tests/qtest/virtio-9p-test.c index 2167322985ece6478e1be4ff44e79f79af13ac3e..92a498f249257cb0a69a6b8fe6082a38b3a3ae36 100644 --- a/tests/qtest/virtio-9p-test.c +++ b/tests/qtest/virtio-9p-test.c @@ -18,6 +18,62 @@ #define QVIRTIO_9P_TIMEOUT_US (10 * 1000 * 1000) static QGuestAllocator *alloc; +/* + * Used to auto generate new fids. Start with arbitrary high value to avoid + * collision with hard coded fids in basic test code. + */ +static uint32_t fid_generator = 1000; + +static uint32_t genfid(void) +{ + return fid_generator++; +} + +/** + * Splits the @a in string by @a delim into individual (non empty) strings + * and outputs them to @a out. The output array @a out is NULL terminated. + * + * Output array @a out must be freed by calling split_free(). + * + * @returns number of individual elements in output array @a out (without the + * final NULL terminating element) + */ +static int split(const char *in, const char *delim, char ***out) +{ + int n = 0, i = 0; + char *tmp, *p; + + tmp = g_strdup(in); + for (p = strtok(tmp, delim); p != NULL; p = strtok(NULL, delim)) { + if (strlen(p) > 0) { + ++n; + } + } + g_free(tmp); + + *out = g_new0(char *, n + 1); /* last element NULL delimiter */ + + tmp = g_strdup(in); + for (p = strtok(tmp, delim); p != NULL; p = strtok(NULL, delim)) { + if (strlen(p) > 0) { + (*out)[i++] = g_strdup(p); + } + } + g_free(tmp); + + return n; +} + +static void split_free(char ***out) +{ + int i; + for (i = 0; (*out)[i]; ++i) { + g_free((*out)[i]); + } + g_free(*out); + *out = NULL; +} + static void pci_config(void *obj, void *data, QGuestAllocator *t_alloc) { QVirtio9P *v9p = obj; @@ -201,6 +257,11 @@ static const char *rmessage_name(uint8_t id) id == P9_RWALK ? "RWALK" : id == P9_RLOPEN ? "RLOPEN" : id == P9_RWRITE ? "RWRITE" : + id == P9_RMKDIR ? "RMKDIR" : + id == P9_RLCREATE ? "RLCREATE" : + id == P9_RSYMLINK ? "RSYMLINK" : + id == P9_RLINK ? "RLINK" : + id == P9_RUNLINKAT ? "RUNLINKAT" : id == P9_RFLUSH ? "RFLUSH" : id == P9_RREADDIR ? "READDIR" : ""; @@ -510,10 +571,8 @@ static void v9fs_rflush(P9Req *req) v9fs_req_free(req); } -static void fs_version(void *obj, void *data, QGuestAllocator *t_alloc) +static void do_version(QVirtio9P *v9p) { - QVirtio9P *v9p = obj; - alloc = t_alloc; const char *version = "9P2000.L"; uint16_t server_len; char *server_version; @@ -528,18 +587,45 @@ static void fs_version(void *obj, void *data, QGuestAllocator *t_alloc) g_free(server_version); } -static void fs_attach(void *obj, void *data, QGuestAllocator *t_alloc) +/* utility function: walk to requested dir and return fid for that dir */ +static uint32_t do_walk(QVirtio9P *v9p, const char *path) +{ + char **wnames; + P9Req *req; + const uint32_t fid = genfid(); + + int nwnames = split(path, "/", &wnames); + + req = v9fs_twalk(v9p, 0, fid, nwnames, wnames, 0); + v9fs_req_wait_for_reply(req, NULL); + v9fs_rwalk(req, NULL, NULL); + + split_free(&wnames); + return fid; +} + +static void fs_version(void *obj, void *data, QGuestAllocator *t_alloc) { - QVirtio9P *v9p = obj; alloc = t_alloc; + do_version(obj); +} + +static void do_attach(QVirtio9P *v9p) +{ P9Req *req; - fs_version(v9p, NULL, t_alloc); + do_version(v9p); req = v9fs_tattach(v9p, 0, getuid(), 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rattach(req, NULL); } +static void fs_attach(void *obj, void *data, QGuestAllocator *t_alloc) +{ + alloc = t_alloc; + do_attach(obj); +} + static void fs_walk(void *obj, void *data, QGuestAllocator *t_alloc) { QVirtio9P *v9p = obj; @@ -554,7 +640,7 @@ static void fs_walk(void *obj, void *data, QGuestAllocator *t_alloc) wnames[i] = g_strdup_printf(QTEST_V9FS_SYNTH_WALK_FILE, i); } - fs_attach(v9p, NULL, t_alloc); + do_attach(v9p); req = v9fs_twalk(v9p, 0, 1, P9_MAXWELEM, wnames, 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rwalk(req, &nwqid, &wqid); @@ -578,6 +664,165 @@ static bool fs_dirents_contain_name(struct V9fsDirent *e, const char* name) return false; } +/* size[4] Tmkdir tag[2] dfid[4] name[s] mode[4] gid[4] */ +static P9Req *v9fs_tmkdir(QVirtio9P *v9p, uint32_t dfid, const char *name, + uint32_t mode, uint32_t gid, uint16_t tag) +{ + P9Req *req; + + uint32_t body_size = 4 + 4 + 4; + uint16_t string_size = v9fs_string_size(name); + + g_assert_cmpint(body_size, <=, UINT32_MAX - string_size); + body_size += string_size; + + req = v9fs_req_init(v9p, body_size, P9_TMKDIR, tag); + v9fs_uint32_write(req, dfid); + v9fs_string_write(req, name); + v9fs_uint32_write(req, mode); + v9fs_uint32_write(req, gid); + v9fs_req_send(req); + return req; +} + +/* size[4] Rmkdir tag[2] qid[13] */ +static void v9fs_rmkdir(P9Req *req, v9fs_qid *qid) +{ + v9fs_req_recv(req, P9_RMKDIR); + if (qid) { + v9fs_memread(req, qid, 13); + } else { + v9fs_memskip(req, 13); + } + v9fs_req_free(req); +} + +/* size[4] Tlcreate tag[2] fid[4] name[s] flags[4] mode[4] gid[4] */ +static P9Req *v9fs_tlcreate(QVirtio9P *v9p, uint32_t fid, const char *name, + uint32_t flags, uint32_t mode, uint32_t gid, + uint16_t tag) +{ + P9Req *req; + + uint32_t body_size = 4 + 4 + 4 + 4; + uint16_t string_size = v9fs_string_size(name); + + g_assert_cmpint(body_size, <=, UINT32_MAX - string_size); + body_size += string_size; + + req = v9fs_req_init(v9p, body_size, P9_TLCREATE, tag); + v9fs_uint32_write(req, fid); + v9fs_string_write(req, name); + v9fs_uint32_write(req, flags); + v9fs_uint32_write(req, mode); + v9fs_uint32_write(req, gid); + v9fs_req_send(req); + return req; +} + +/* size[4] Rlcreate tag[2] qid[13] iounit[4] */ +static void v9fs_rlcreate(P9Req *req, v9fs_qid *qid, uint32_t *iounit) +{ + v9fs_req_recv(req, P9_RLCREATE); + if (qid) { + v9fs_memread(req, qid, 13); + } else { + v9fs_memskip(req, 13); + } + if (iounit) { + v9fs_uint32_read(req, iounit); + } + v9fs_req_free(req); +} + +/* size[4] Tsymlink tag[2] fid[4] name[s] symtgt[s] gid[4] */ +static P9Req *v9fs_tsymlink(QVirtio9P *v9p, uint32_t fid, const char *name, + const char *symtgt, uint32_t gid, uint16_t tag) +{ + P9Req *req; + + uint32_t body_size = 4 + 4; + uint16_t string_size = v9fs_string_size(name) + v9fs_string_size(symtgt); + + g_assert_cmpint(body_size, <=, UINT32_MAX - string_size); + body_size += string_size; + + req = v9fs_req_init(v9p, body_size, P9_TSYMLINK, tag); + v9fs_uint32_write(req, fid); + v9fs_string_write(req, name); + v9fs_string_write(req, symtgt); + v9fs_uint32_write(req, gid); + v9fs_req_send(req); + return req; +} + +/* size[4] Rsymlink tag[2] qid[13] */ +static void v9fs_rsymlink(P9Req *req, v9fs_qid *qid) +{ + v9fs_req_recv(req, P9_RSYMLINK); + if (qid) { + v9fs_memread(req, qid, 13); + } else { + v9fs_memskip(req, 13); + } + v9fs_req_free(req); +} + +/* size[4] Tlink tag[2] dfid[4] fid[4] name[s] */ +static P9Req *v9fs_tlink(QVirtio9P *v9p, uint32_t dfid, uint32_t fid, + const char *name, uint16_t tag) +{ + P9Req *req; + + uint32_t body_size = 4 + 4; + uint16_t string_size = v9fs_string_size(name); + + g_assert_cmpint(body_size, <=, UINT32_MAX - string_size); + body_size += string_size; + + req = v9fs_req_init(v9p, body_size, P9_TLINK, tag); + v9fs_uint32_write(req, dfid); + v9fs_uint32_write(req, fid); + v9fs_string_write(req, name); + v9fs_req_send(req); + return req; +} + +/* size[4] Rlink tag[2] */ +static void v9fs_rlink(P9Req *req) +{ + v9fs_req_recv(req, P9_RLINK); + v9fs_req_free(req); +} + +/* size[4] Tunlinkat tag[2] dirfd[4] name[s] flags[4] */ +static P9Req *v9fs_tunlinkat(QVirtio9P *v9p, uint32_t dirfd, const char *name, + uint32_t flags, uint16_t tag) +{ + P9Req *req; + + uint32_t body_size = 4 + 4; + uint16_t string_size = v9fs_string_size(name); + + g_assert_cmpint(body_size, <=, UINT32_MAX - string_size); + body_size += string_size; + + req = v9fs_req_init(v9p, body_size, P9_TUNLINKAT, tag); + v9fs_uint32_write(req, dirfd); + v9fs_string_write(req, name); + v9fs_uint32_write(req, flags); + v9fs_req_send(req); + return req; +} + +/* size[4] Runlinkat tag[2] */ +static void v9fs_runlinkat(P9Req *req) +{ + v9fs_req_recv(req, P9_RUNLINKAT); + v9fs_req_free(req); +} + +/* basic readdir test where reply fits into a single response message */ static void fs_readdir(void *obj, void *data, QGuestAllocator *t_alloc) { QVirtio9P *v9p = obj; @@ -589,7 +834,7 @@ static void fs_readdir(void *obj, void *data, QGuestAllocator *t_alloc) struct V9fsDirent *entries = NULL; P9Req *req; - fs_attach(v9p, NULL, t_alloc); + do_attach(v9p); req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rwalk(req, &nqid, NULL); @@ -631,6 +876,86 @@ static void fs_readdir(void *obj, void *data, QGuestAllocator *t_alloc) g_free(wnames[0]); } +/* readdir test where overall request is split over several messages */ +static void do_readdir_split(QVirtio9P *v9p, uint32_t count) +{ + char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_READDIR_DIR) }; + uint16_t nqid; + v9fs_qid qid; + uint32_t nentries, npartialentries; + struct V9fsDirent *entries, *tail, *partialentries; + P9Req *req; + int fid; + uint64_t offset; + + do_attach(v9p); + + fid = 1; + offset = 0; + entries = NULL; + nentries = 0; + tail = NULL; + + req = v9fs_twalk(v9p, 0, fid, 1, wnames, 0); + v9fs_req_wait_for_reply(req, NULL); + v9fs_rwalk(req, &nqid, NULL); + g_assert_cmpint(nqid, ==, 1); + + req = v9fs_tlopen(v9p, fid, O_DIRECTORY, 0); + v9fs_req_wait_for_reply(req, NULL); + v9fs_rlopen(req, &qid, NULL); + + /* + * send as many Treaddir requests as required to get all directory + * entries + */ + while (true) { + npartialentries = 0; + partialentries = NULL; + + req = v9fs_treaddir(v9p, fid, offset, count, 0); + v9fs_req_wait_for_reply(req, NULL); + v9fs_rreaddir(req, &count, &npartialentries, &partialentries); + if (npartialentries > 0 && partialentries) { + if (!entries) { + entries = partialentries; + nentries = npartialentries; + tail = partialentries; + } else { + tail->next = partialentries; + nentries += npartialentries; + } + while (tail->next) { + tail = tail->next; + } + offset = tail->offset; + } else { + break; + } + } + + g_assert_cmpint( + nentries, ==, + QTEST_V9FS_SYNTH_READDIR_NFILES + 2 /* "." and ".." */ + ); + + /* + * Check all file names exist in returned entries, ignore their order + * though. + */ + g_assert_cmpint(fs_dirents_contain_name(entries, "."), ==, true); + g_assert_cmpint(fs_dirents_contain_name(entries, ".."), ==, true); + for (int i = 0; i < QTEST_V9FS_SYNTH_READDIR_NFILES; ++i) { + char *name = g_strdup_printf(QTEST_V9FS_SYNTH_READDIR_FILE, i); + g_assert_cmpint(fs_dirents_contain_name(entries, name), ==, true); + g_free(name); + } + + v9fs_free_dirents(entries); + + g_free(wnames[0]); +} + static void fs_walk_no_slash(void *obj, void *data, QGuestAllocator *t_alloc) { QVirtio9P *v9p = obj; @@ -639,7 +964,7 @@ static void fs_walk_no_slash(void *obj, void *data, QGuestAllocator *t_alloc) P9Req *req; uint32_t err; - fs_attach(v9p, NULL, t_alloc); + do_attach(v9p); req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rlerror(req, &err); @@ -657,7 +982,7 @@ static void fs_walk_dotdot(void *obj, void *data, QGuestAllocator *t_alloc) v9fs_qid root_qid, *wqid; P9Req *req; - fs_version(v9p, NULL, t_alloc); + do_version(v9p); req = v9fs_tattach(v9p, 0, getuid(), 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rattach(req, &root_qid); @@ -679,7 +1004,7 @@ static void fs_lopen(void *obj, void *data, QGuestAllocator *t_alloc) char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_LOPEN_FILE) }; P9Req *req; - fs_attach(v9p, NULL, t_alloc); + do_attach(v9p); req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rwalk(req, NULL, NULL); @@ -701,7 +1026,7 @@ static void fs_write(void *obj, void *data, QGuestAllocator *t_alloc) uint32_t count; P9Req *req; - fs_attach(v9p, NULL, t_alloc); + do_attach(v9p); req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rwalk(req, NULL, NULL); @@ -728,7 +1053,7 @@ static void fs_flush_success(void *obj, void *data, QGuestAllocator *t_alloc) uint32_t reply_len; uint8_t should_block; - fs_attach(v9p, NULL, t_alloc); + do_attach(v9p); req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rwalk(req, NULL, NULL); @@ -765,7 +1090,7 @@ static void fs_flush_ignored(void *obj, void *data, QGuestAllocator *t_alloc) uint32_t count; uint8_t should_block; - fs_attach(v9p, NULL, t_alloc); + do_attach(v9p); req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rwalk(req, NULL, NULL); @@ -793,23 +1118,377 @@ static void fs_flush_ignored(void *obj, void *data, QGuestAllocator *t_alloc) g_free(wnames[0]); } +static void do_mkdir(QVirtio9P *v9p, const char *path, const char *cname) +{ + char *const name = g_strdup(cname); + uint32_t fid; + P9Req *req; + + fid = do_walk(v9p, path); + + req = v9fs_tmkdir(v9p, fid, name, 0750, 0, 0); + v9fs_req_wait_for_reply(req, NULL); + v9fs_rmkdir(req, NULL); + + g_free(name); +} + +/* create a regular file with Tlcreate and return file's fid */ +static uint32_t do_lcreate(QVirtio9P *v9p, const char *path, + const char *cname) +{ + char *const name = g_strdup(cname); + uint32_t fid; + P9Req *req; + + fid = do_walk(v9p, path); + + req = v9fs_tlcreate(v9p, fid, name, 0, 0750, 0, 0); + v9fs_req_wait_for_reply(req, NULL); + v9fs_rlcreate(req, NULL, NULL); + + g_free(name); + return fid; +} + +/* create symlink named @a clink in directory @a path pointing to @a to */ +static void do_symlink(QVirtio9P *v9p, const char *path, const char *clink, + const char *to) +{ + char *const name = g_strdup(clink); + char *const dst = g_strdup(to); + uint32_t fid; + P9Req *req; + + fid = do_walk(v9p, path); + + req = v9fs_tsymlink(v9p, fid, name, dst, 0, 0); + v9fs_req_wait_for_reply(req, NULL); + v9fs_rsymlink(req, NULL); + + g_free(dst); + g_free(name); +} + +/* create a hard link named @a clink in directory @a path pointing to @a to */ +static void do_hardlink(QVirtio9P *v9p, const char *path, const char *clink, + const char *to) +{ + uint32_t dfid, fid; + P9Req *req; + + dfid = do_walk(v9p, path); + fid = do_walk(v9p, to); + + req = v9fs_tlink(v9p, dfid, fid, clink, 0); + v9fs_req_wait_for_reply(req, NULL); + v9fs_rlink(req); +} + +static void do_unlinkat(QVirtio9P *v9p, const char *atpath, const char *rpath, + uint32_t flags) +{ + char *const name = g_strdup(rpath); + uint32_t fid; + P9Req *req; + + fid = do_walk(v9p, atpath); + + req = v9fs_tunlinkat(v9p, fid, name, flags, 0); + v9fs_req_wait_for_reply(req, NULL); + v9fs_runlinkat(req); + + g_free(name); +} + +static void fs_readdir_split_128(void *obj, void *data, + QGuestAllocator *t_alloc) +{ + alloc = t_alloc; + do_readdir_split(obj, 128); +} + +static void fs_readdir_split_256(void *obj, void *data, + QGuestAllocator *t_alloc) +{ + alloc = t_alloc; + do_readdir_split(obj, 256); +} + +static void fs_readdir_split_512(void *obj, void *data, + QGuestAllocator *t_alloc) +{ + alloc = t_alloc; + do_readdir_split(obj, 512); +} + + +/* tests using the 9pfs 'local' fs driver */ + +static void fs_create_dir(void *obj, void *data, QGuestAllocator *t_alloc) +{ + QVirtio9P *v9p = obj; + alloc = t_alloc; + struct stat st; + char *root_path = virtio_9p_test_path(""); + char *new_dir = virtio_9p_test_path("01"); + + g_assert(root_path != NULL); + + do_attach(v9p); + do_mkdir(v9p, "/", "01"); + + /* check if created directory really exists now ... */ + g_assert(stat(new_dir, &st) == 0); + /* ... and is actually a directory */ + g_assert((st.st_mode & S_IFMT) == S_IFDIR); + + g_free(new_dir); + g_free(root_path); +} + +static void fs_unlinkat_dir(void *obj, void *data, QGuestAllocator *t_alloc) +{ + QVirtio9P *v9p = obj; + alloc = t_alloc; + struct stat st; + char *root_path = virtio_9p_test_path(""); + char *new_dir = virtio_9p_test_path("02"); + + g_assert(root_path != NULL); + + do_attach(v9p); + do_mkdir(v9p, "/", "02"); + + /* check if created directory really exists now ... */ + g_assert(stat(new_dir, &st) == 0); + /* ... and is actually a directory */ + g_assert((st.st_mode & S_IFMT) == S_IFDIR); + + do_unlinkat(v9p, "/", "02", AT_REMOVEDIR); + /* directory should be gone now */ + g_assert(stat(new_dir, &st) != 0); + + g_free(new_dir); + g_free(root_path); +} + +static void fs_create_file(void *obj, void *data, QGuestAllocator *t_alloc) +{ + QVirtio9P *v9p = obj; + alloc = t_alloc; + struct stat st; + char *new_file = virtio_9p_test_path("03/1st_file"); + + do_attach(v9p); + do_mkdir(v9p, "/", "03"); + do_lcreate(v9p, "03", "1st_file"); + + /* check if created file exists now ... */ + g_assert(stat(new_file, &st) == 0); + /* ... and is a regular file */ + g_assert((st.st_mode & S_IFMT) == S_IFREG); + + g_free(new_file); +} + +static void fs_unlinkat_file(void *obj, void *data, QGuestAllocator *t_alloc) +{ + QVirtio9P *v9p = obj; + alloc = t_alloc; + struct stat st; + char *new_file = virtio_9p_test_path("04/doa_file"); + + do_attach(v9p); + do_mkdir(v9p, "/", "04"); + do_lcreate(v9p, "04", "doa_file"); + + /* check if created file exists now ... */ + g_assert(stat(new_file, &st) == 0); + /* ... and is a regular file */ + g_assert((st.st_mode & S_IFMT) == S_IFREG); + + do_unlinkat(v9p, "04", "doa_file", 0); + /* file should be gone now */ + g_assert(stat(new_file, &st) != 0); + + g_free(new_file); +} + +static void fs_symlink_file(void *obj, void *data, QGuestAllocator *t_alloc) +{ + QVirtio9P *v9p = obj; + alloc = t_alloc; + struct stat st; + char *real_file = virtio_9p_test_path("05/real_file"); + char *symlink_file = virtio_9p_test_path("05/symlink_file"); + + do_attach(v9p); + do_mkdir(v9p, "/", "05"); + do_lcreate(v9p, "05", "real_file"); + g_assert(stat(real_file, &st) == 0); + g_assert((st.st_mode & S_IFMT) == S_IFREG); + + do_symlink(v9p, "05", "symlink_file", "real_file"); + + /* check if created link exists now */ + g_assert(stat(symlink_file, &st) == 0); + + g_free(symlink_file); + g_free(real_file); +} + +static void fs_unlinkat_symlink(void *obj, void *data, + QGuestAllocator *t_alloc) +{ + QVirtio9P *v9p = obj; + alloc = t_alloc; + struct stat st; + char *real_file = virtio_9p_test_path("06/real_file"); + char *symlink_file = virtio_9p_test_path("06/symlink_file"); + + do_attach(v9p); + do_mkdir(v9p, "/", "06"); + do_lcreate(v9p, "06", "real_file"); + g_assert(stat(real_file, &st) == 0); + g_assert((st.st_mode & S_IFMT) == S_IFREG); + + do_symlink(v9p, "06", "symlink_file", "real_file"); + g_assert(stat(symlink_file, &st) == 0); + + do_unlinkat(v9p, "06", "symlink_file", 0); + /* symlink should be gone now */ + g_assert(stat(symlink_file, &st) != 0); + + g_free(symlink_file); + g_free(real_file); +} + +static void fs_hardlink_file(void *obj, void *data, QGuestAllocator *t_alloc) +{ + QVirtio9P *v9p = obj; + alloc = t_alloc; + struct stat st_real, st_link; + char *real_file = virtio_9p_test_path("07/real_file"); + char *hardlink_file = virtio_9p_test_path("07/hardlink_file"); + + do_attach(v9p); + do_mkdir(v9p, "/", "07"); + do_lcreate(v9p, "07", "real_file"); + g_assert(stat(real_file, &st_real) == 0); + g_assert((st_real.st_mode & S_IFMT) == S_IFREG); + + do_hardlink(v9p, "07", "hardlink_file", "07/real_file"); + + /* check if link exists now ... */ + g_assert(stat(hardlink_file, &st_link) == 0); + /* ... and it's a hard link, right? */ + g_assert((st_link.st_mode & S_IFMT) == S_IFREG); + g_assert(st_link.st_dev == st_real.st_dev); + g_assert(st_link.st_ino == st_real.st_ino); + + g_free(hardlink_file); + g_free(real_file); +} + +static void fs_unlinkat_hardlink(void *obj, void *data, + QGuestAllocator *t_alloc) +{ + QVirtio9P *v9p = obj; + alloc = t_alloc; + struct stat st_real, st_link; + char *real_file = virtio_9p_test_path("08/real_file"); + char *hardlink_file = virtio_9p_test_path("08/hardlink_file"); + + do_attach(v9p); + do_mkdir(v9p, "/", "08"); + do_lcreate(v9p, "08", "real_file"); + g_assert(stat(real_file, &st_real) == 0); + g_assert((st_real.st_mode & S_IFMT) == S_IFREG); + + do_hardlink(v9p, "08", "hardlink_file", "08/real_file"); + g_assert(stat(hardlink_file, &st_link) == 0); + + do_unlinkat(v9p, "08", "hardlink_file", 0); + /* symlink should be gone now */ + g_assert(stat(hardlink_file, &st_link) != 0); + /* and old file should still exist */ + g_assert(stat(real_file, &st_real) == 0); + + g_free(hardlink_file); + g_free(real_file); +} + +static void *assign_9p_local_driver(GString *cmd_line, void *arg) +{ + virtio_9p_assign_local_driver(cmd_line, "security_model=mapped-xattr"); + return arg; +} + static void register_virtio_9p_test(void) { - qos_add_test("config", "virtio-9p", pci_config, NULL); - qos_add_test("fs/version/basic", "virtio-9p", fs_version, NULL); - qos_add_test("fs/attach/basic", "virtio-9p", fs_attach, NULL); - qos_add_test("fs/walk/basic", "virtio-9p", fs_walk, NULL); - qos_add_test("fs/walk/no_slash", "virtio-9p", fs_walk_no_slash, - NULL); - qos_add_test("fs/walk/dotdot_from_root", "virtio-9p", - fs_walk_dotdot, NULL); - qos_add_test("fs/lopen/basic", "virtio-9p", fs_lopen, NULL); - qos_add_test("fs/write/basic", "virtio-9p", fs_write, NULL); - qos_add_test("fs/flush/success", "virtio-9p", fs_flush_success, - NULL); - qos_add_test("fs/flush/ignored", "virtio-9p", fs_flush_ignored, - NULL); - qos_add_test("fs/readdir/basic", "virtio-9p", fs_readdir, NULL); + + QOSGraphTestOptions opts = { + }; + + /* 9pfs test cases using the 'synth' filesystem driver */ + qos_add_test("synth/config", "virtio-9p", pci_config, &opts); + qos_add_test("synth/version/basic", "virtio-9p", fs_version, &opts); + qos_add_test("synth/attach/basic", "virtio-9p", fs_attach, &opts); + qos_add_test("synth/walk/basic", "virtio-9p", fs_walk, &opts); + qos_add_test("synth/walk/no_slash", "virtio-9p", fs_walk_no_slash, + &opts); + qos_add_test("synth/walk/dotdot_from_root", "virtio-9p", + fs_walk_dotdot, &opts); + qos_add_test("synth/lopen/basic", "virtio-9p", fs_lopen, &opts); + qos_add_test("synth/write/basic", "virtio-9p", fs_write, &opts); + qos_add_test("synth/flush/success", "virtio-9p", fs_flush_success, + &opts); + qos_add_test("synth/flush/ignored", "virtio-9p", fs_flush_ignored, + &opts); + qos_add_test("synth/readdir/basic", "virtio-9p", fs_readdir, &opts); + qos_add_test("synth/readdir/split_512", "virtio-9p", + fs_readdir_split_512, &opts); + qos_add_test("synth/readdir/split_256", "virtio-9p", + fs_readdir_split_256, &opts); + qos_add_test("synth/readdir/split_128", "virtio-9p", + fs_readdir_split_128, &opts); + + + /* 9pfs test cases using the 'local' filesystem driver */ + + /* + * XXX: Until we are sure that these tests can run everywhere, + * keep them as "slow" so that they aren't run with "make check". + */ + if (!g_test_slow()) { + return; + } + + opts.before = assign_9p_local_driver; + qos_add_test("local/config", "virtio-9p", pci_config, &opts); + qos_add_test("local/create_dir", "virtio-9p", fs_create_dir, &opts); + qos_add_test("local/unlinkat_dir", "virtio-9p", fs_unlinkat_dir, &opts); + qos_add_test("local/create_file", "virtio-9p", fs_create_file, &opts); + qos_add_test("local/unlinkat_file", "virtio-9p", fs_unlinkat_file, &opts); + qos_add_test("local/symlink_file", "virtio-9p", fs_symlink_file, &opts); + qos_add_test("local/unlinkat_symlink", "virtio-9p", fs_unlinkat_symlink, + &opts); + qos_add_test("local/hardlink_file", "virtio-9p", fs_hardlink_file, &opts); + qos_add_test("local/unlinkat_hardlink", "virtio-9p", fs_unlinkat_hardlink, + &opts); } libqos_init(register_virtio_9p_test); + +static void __attribute__((constructor)) construct_9p_test(void) +{ + /* make sure test dir for the 'local' tests exists */ + virtio_9p_create_local_test_dir(); +} + +static void __attribute__((destructor)) destruct_9p_test(void) +{ + /* remove previously created test dir when test suite completed */ + virtio_9p_remove_local_test_dir(); +} diff --git a/tests/qtest/virtio-rng-test.c b/tests/qtest/virtio-rng-test.c index 092ba130684dfdc378265f17ba1d779aec75fa35..e6b8cd8e0cfa2ef8422cc7317fd99d295559ab4d 100644 --- a/tests/qtest/virtio-rng-test.c +++ b/tests/qtest/virtio-rng-test.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/module.h" #include "libqos/qgraph.h" #include "libqos/virtio-rng.h" diff --git a/tests/qtest/virtio-test.c b/tests/qtest/virtio-test.c index f7c6afdcf11130a173a042db3a04eecc51d68a9b..63134176303a8bae9d946b9a5120e6289a0a4fe8 100644 --- a/tests/qtest/virtio-test.c +++ b/tests/qtest/virtio-test.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/module.h" #include "libqos/qgraph.h" #include "libqos/pci.h" diff --git a/tests/qtest/vmgenid-test.c b/tests/qtest/vmgenid-test.c index efba76e7164e284f0f97920be0ddcb06fb0f4865..6781a514479bc47af0199d5a4705cf94635e0df9 100644 --- a/tests/qtest/vmgenid-test.c +++ b/tests/qtest/vmgenid-test.c @@ -14,7 +14,7 @@ #include "hw/acpi/acpi-defs.h" #include "boot-sector.h" #include "acpi-utils.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qapi/qmp/qdict.h" #define VGID_GUID "324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87" diff --git a/tests/qtest/vmxnet3-test.c b/tests/qtest/vmxnet3-test.c index a81025252c87989952cea07c1c546d55e25639f0..97c23fd3a8f6d133b1cf18dc0573ffeba36d7c92 100644 --- a/tests/qtest/vmxnet3-test.c +++ b/tests/qtest/vmxnet3-test.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qemu/module.h" #include "libqos/qgraph.h" #include "libqos/pci.h" diff --git a/tests/qtest/wdt_ib700-test.c b/tests/qtest/wdt_ib700-test.c index 797288d939fac2fb51f7200bfc3119e824bd29d0..6c36e43fb8358e589255f6822ebfbea15f62fff2 100644 --- a/tests/qtest/wdt_ib700-test.c +++ b/tests/qtest/wdt_ib700-test.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" +#include "libqos/libqtest.h" #include "qapi/qmp/qdict.h" #include "qemu/timer.h" diff --git a/tests/rcutorture.c b/tests/rcutorture.c index 732f03abdaa145f2a3a0a7ab16f3e9d64b0b5183..de6f649058ef2648fef1287816145f883efc39aa 100644 --- a/tests/rcutorture.c +++ b/tests/rcutorture.c @@ -123,7 +123,7 @@ static void *rcu_read_perf_test(void *arg) rcu_register_thread(); *(struct rcu_reader_data **)arg = &rcu_reader; - atomic_inc(&nthreadsrunning); + qatomic_inc(&nthreadsrunning); while (goflag == GOFLAG_INIT) { g_usleep(1000); } @@ -149,7 +149,7 @@ static void *rcu_update_perf_test(void *arg) rcu_register_thread(); *(struct rcu_reader_data **)arg = &rcu_reader; - atomic_inc(&nthreadsrunning); + qatomic_inc(&nthreadsrunning); while (goflag == GOFLAG_INIT) { g_usleep(1000); } @@ -172,7 +172,7 @@ static void perftestinit(void) static void perftestrun(int nthreads, int duration, int nreaders, int nupdaters) { - while (atomic_read(&nthreadsrunning) < nthreads) { + while (qatomic_read(&nthreadsrunning) < nthreads) { g_usleep(1000); } goflag = GOFLAG_RUN; @@ -259,8 +259,8 @@ static void *rcu_read_stress_test(void *arg) } while (goflag == GOFLAG_RUN) { rcu_read_lock(); - p = atomic_rcu_read(&rcu_stress_current); - if (atomic_read(&p->mbtest) == 0) { + p = qatomic_rcu_read(&rcu_stress_current); + if (qatomic_read(&p->mbtest) == 0) { n_mberror++; } rcu_read_lock(); @@ -268,7 +268,7 @@ static void *rcu_read_stress_test(void *arg) garbage++; } rcu_read_unlock(); - pc = atomic_read(&p->age); + pc = qatomic_read(&p->age); rcu_read_unlock(); if ((pc > RCU_STRESS_PIPE_LEN) || (pc < 0)) { pc = RCU_STRESS_PIPE_LEN; @@ -301,7 +301,7 @@ static void *rcu_read_stress_test(void *arg) static void *rcu_update_stress_test(void *arg) { int i, rcu_stress_idx = 0; - struct rcu_stress *cp = atomic_read(&rcu_stress_current); + struct rcu_stress *cp = qatomic_read(&rcu_stress_current); rcu_register_thread(); *(struct rcu_reader_data **)arg = &rcu_reader; @@ -319,11 +319,11 @@ static void *rcu_update_stress_test(void *arg) p = &rcu_stress_array[rcu_stress_idx]; /* catching up with ourselves would be a bug */ assert(p != cp); - atomic_set(&p->mbtest, 0); + qatomic_set(&p->mbtest, 0); smp_mb(); - atomic_set(&p->age, 0); - atomic_set(&p->mbtest, 1); - atomic_rcu_set(&rcu_stress_current, p); + qatomic_set(&p->age, 0); + qatomic_set(&p->mbtest, 1); + qatomic_rcu_set(&rcu_stress_current, p); cp = p; /* * New RCU structure is now live, update pipe counts on old @@ -331,7 +331,7 @@ static void *rcu_update_stress_test(void *arg) */ for (i = 0; i < RCU_STRESS_PIPE_LEN; i++) { if (i != rcu_stress_idx) { - atomic_set(&rcu_stress_array[i].age, + qatomic_set(&rcu_stress_array[i].age, rcu_stress_array[i].age + 1); } } diff --git a/tests/requirements.txt b/tests/requirements.txt index f9c84b4ba1a0466a46aace654b8be04d01c53fef..a1c631fa595dd17ac0a9efd8619b4298b6dbeaa3 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,5 +1,5 @@ # Add Python module requirements, one per line, to be installed # in the tests/venv Python virtual environment. For more info, # refer to: https://pip.pypa.io/en/stable/user_guide/#id1 -avocado-framework==76.0 -pycdlib==1.9.0 +avocado-framework==81.0 +pycdlib==1.11.0 diff --git a/tests/socket-helpers.c b/tests/socket-helpers.c index 19a51e887e437aee70d095a8831497c8e97504d9..f704fd1a69cec3d5c081c5ba9876bfc3587c8a64 100644 --- a/tests/socket-helpers.c +++ b/tests/socket-helpers.c @@ -59,8 +59,7 @@ static int socket_can_bind_connect(const char *hostname, int family) /* lookup */ rc = getaddrinfo(hostname, NULL, &ai, &res); if (rc != 0) { - if (rc == EAI_ADDRFAMILY || - rc == EAI_FAMILY) { + if (rc == EAI_ADDRFAMILY || rc == EAI_FAMILY || rc == EAI_NONAME) { errno = EADDRNOTAVAIL; } else { errno = EINVAL; diff --git a/tests/tcg/.gitignore b/tests/tcg/.gitignore deleted file mode 100644 index 84d7541b286775af30ab147917aff1005039cdde..0000000000000000000000000000000000000000 --- a/tests/tcg/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# These are build artefacts which only appear when you are doing -# builds directly in the source tree. -config-*.mak -*-softmmu/ -*-linux-user/ diff --git a/tests/tcg/Makefile.qemu b/tests/tcg/Makefile.qemu index 9c23aeaa2a6499f221f9add6ed50ef2f31730405..c096c611a2b4ed4572301fa359243c5d9c352809 100644 --- a/tests/tcg/Makefile.qemu +++ b/tests/tcg/Makefile.qemu @@ -8,14 +8,23 @@ # to do it for us. # -include $(SRC_PATH)/rules.mak - # The configure script fills in extra information about # useful docker images or alternative compiler flags. +# Usage: $(call quiet-command,command and args,"NAME","args to print") +# This will run "command and args", and either: +# if V=1 just print the whole command and args +# otherwise print the 'quiet' output in the format " NAME args to print" +# NAME should be a short name of the command, 7 letters or fewer. +# If called with only a single argument, will print nothing in quiet mode. +quiet-command-run = $(if $(V),,$(if $2,printf " %-7s %s\n" $2 $3 && ))$1 +quiet-@ = $(if $(V),,@) +quiet-command = $(quiet-@)$(call quiet-command-run,$1,$2,$3) + CROSS_CC_GUEST:= DOCKER_IMAGE:= --include $(BUILD_DIR)/tests/tcg/config-$(TARGET).mak + +-include tests/tcg/config-$(TARGET).mak GUEST_BUILD= TCG_MAKE=../Makefile.target @@ -47,7 +56,7 @@ ifneq ($(DOCKER_IMAGE),) DOCKER_COMPILE_CMD="$(DOCKER_SCRIPT) cc \ --cc $(DOCKER_CROSS_CC_GUEST) \ - -i qemu:$(DOCKER_IMAGE) \ + -i qemu/$(DOCKER_IMAGE) \ -s $(SRC_PATH) -- " .PHONY: docker-build-guest-tests @@ -57,7 +66,7 @@ docker-build-guest-tests: docker-image-$(DOCKER_IMAGE) $(MAKE) -f $(TCG_MAKE) TARGET="$(TARGET)" CC=$(DOCKER_COMPILE_CMD) \ SRC_PATH="$(SRC_PATH)" BUILD_STATIC=y \ EXTRA_CFLAGS="$(CROSS_CC_GUEST_CFLAGS)"), \ - "BUILD","$(TARGET) guest-tests with docker qemu:$(DOCKER_IMAGE)") + "BUILD","$(TARGET) guest-tests with docker qemu/$(DOCKER_IMAGE)") GUEST_BUILD=docker-build-guest-tests diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target index b3cff3cad1a081f131ba3722cbc3f87510340623..2ae86776cdc16f99719924fc9f0c8c8ab031afe8 100644 --- a/tests/tcg/Makefile.target +++ b/tests/tcg/Makefile.target @@ -126,9 +126,10 @@ RUN_TESTS=$(patsubst %,run-%, $(TESTS)) # If plugins exist also include those in the tests ifeq ($(CONFIG_PLUGIN),y) -PLUGIN_DIR=../../plugin -VPATH+=$(PLUGIN_DIR) -PLUGINS=$(notdir $(wildcard $(PLUGIN_DIR)/*.so)) +PLUGIN_SRC=$(SRC_PATH)/tests/plugin +PLUGIN_LIB=../../plugin +VPATH+=$(PLUGIN_LIB) +PLUGINS=$(patsubst %.c, lib%.so, $(notdir $(wildcard $(PLUGIN_SRC)/*.c))) # We need to ensure expand the run-plugin-TEST-with-PLUGIN # pre-requistes manually here as we can't use stems to handle it. We @@ -152,7 +153,7 @@ run-%: % run-plugin-%: $(call run-test, $@, $(QEMU) $(QEMU_OPTS) \ - -plugin $(PLUGIN_DIR)/$(call extract-plugin,$@) \ + -plugin $(PLUGIN_LIB)/$(call extract-plugin,$@) \ -d plugin -D $*.pout \ $(call strip-plugin,$<), \ "$* on $(TARGET_NAME)") @@ -168,7 +169,7 @@ run-plugin-%: $(call run-test, $@, \ $(QEMU) -monitor none -display none \ -chardev file$(COMMA)path=$@.out$(COMMA)id=output \ - -plugin $(PLUGIN_DIR)/$(call extract-plugin,$@) \ + -plugin $(PLUGIN_LIB)/$(call extract-plugin,$@) \ -d plugin -D $*.pout \ $(QEMU_OPTS) $(call strip-plugin,$<), \ "$* on $(TARGET_NAME)") diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target index 71f72cfbe34de402a575fdea9a6e353c87b25a0b..1057a8ac498b5f96bd7629950c3f0a073a907c59 100644 --- a/tests/tcg/aarch64/Makefile.softmmu-target +++ b/tests/tcg/aarch64/Makefile.softmmu-target @@ -61,7 +61,7 @@ run-memory-replay: memory-replay run-memory-record $(QEMU_OPTS) memory, \ "$< on $(TARGET_NAME)") -EXTRA_TESTS+=memory-record memory-replay +EXTRA_RUNS+=run-memory-replay ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_3),) pauth-3: CFLAGS += -march=armv8.3-a diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target index 312f36cde5f90fbf720d6ef362648b90eab482da..d7d33e293c08dee97d440c6c43bf39bfc8dddfba 100644 --- a/tests/tcg/aarch64/Makefile.target +++ b/tests/tcg/aarch64/Makefile.target @@ -19,10 +19,21 @@ run-fcvt: fcvt # Pauth Tests ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_3),) -AARCH64_TESTS += pauth-1 pauth-2 pauth-4 -run-pauth-%: QEMU_OPTS += -cpu max +AARCH64_TESTS += pauth-1 pauth-2 pauth-4 pauth-5 pauth-%: CFLAGS += -march=armv8.3-a +run-pauth-%: QEMU_OPTS += -cpu max +run-plugin-pauth-%: QEMU_OPTS += -cpu max +endif + +# BTI Tests +# bti-1 tests the elf notes, so we require special compiler support. +ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_BTI),) +AARCH64_TESTS += bti-1 +bti-1: CFLAGS += -mbranch-protection=standard +bti-1: LDFLAGS += -nostdlib endif +# bti-2 tests PROT_BTI, so no special compiler support required. +AARCH64_TESTS += bti-2 # Semihosting smoke test for linux-user AARCH64_TESTS += semihosting @@ -31,7 +42,7 @@ run-semihosting: semihosting run-plugin-semihosting-with-%: $(call run-test, $@, $(QEMU) $(QEMU_OPTS) \ - -plugin $(PLUGIN_DIR)/$(call extract-plugin,$@) \ + -plugin $(PLUGIN_LIB)/$(call extract-plugin,$@) \ $(call strip-plugin,$<) 2> $<.err, \ "$< on $(TARGET_NAME) with $*") diff --git a/tests/tcg/aarch64/bti-1.c b/tests/tcg/aarch64/bti-1.c new file mode 100644 index 0000000000000000000000000000000000000000..61924f0d7a4c4579564e41b70075829dd0162292 --- /dev/null +++ b/tests/tcg/aarch64/bti-1.c @@ -0,0 +1,62 @@ +/* + * Branch target identification, basic notskip cases. + */ + +#include "bti-crt.inc.c" + +static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc) +{ + uc->uc_mcontext.pc += 8; + uc->uc_mcontext.pstate = 1; +} + +#define NOP "nop" +#define BTI_N "hint #32" +#define BTI_C "hint #34" +#define BTI_J "hint #36" +#define BTI_JC "hint #38" + +#define BTYPE_1(DEST) \ + asm("mov %0,#1; adr x16, 1f; br x16; 1: " DEST "; mov %0,#0" \ + : "=r"(skipped) : : "x16") + +#define BTYPE_2(DEST) \ + asm("mov %0,#1; adr x16, 1f; blr x16; 1: " DEST "; mov %0,#0" \ + : "=r"(skipped) : : "x16", "x30") + +#define BTYPE_3(DEST) \ + asm("mov %0,#1; adr x15, 1f; br x15; 1: " DEST "; mov %0,#0" \ + : "=r"(skipped) : : "x15") + +#define TEST(WHICH, DEST, EXPECT) \ + do { WHICH(DEST); fail += skipped ^ EXPECT; } while (0) + + +int main() +{ + int fail = 0; + int skipped; + + /* Signal-like with SA_SIGINFO. */ + signal_info(SIGILL, skip2_sigill); + + TEST(BTYPE_1, NOP, 1); + TEST(BTYPE_1, BTI_N, 1); + TEST(BTYPE_1, BTI_C, 0); + TEST(BTYPE_1, BTI_J, 0); + TEST(BTYPE_1, BTI_JC, 0); + + TEST(BTYPE_2, NOP, 1); + TEST(BTYPE_2, BTI_N, 1); + TEST(BTYPE_2, BTI_C, 0); + TEST(BTYPE_2, BTI_J, 1); + TEST(BTYPE_2, BTI_JC, 0); + + TEST(BTYPE_3, NOP, 1); + TEST(BTYPE_3, BTI_N, 1); + TEST(BTYPE_3, BTI_C, 1); + TEST(BTYPE_3, BTI_J, 0); + TEST(BTYPE_3, BTI_JC, 0); + + return fail; +} diff --git a/tests/tcg/aarch64/bti-2.c b/tests/tcg/aarch64/bti-2.c new file mode 100644 index 0000000000000000000000000000000000000000..65e8e857ddac0f03da2544751b532c3e348a71b4 --- /dev/null +++ b/tests/tcg/aarch64/bti-2.c @@ -0,0 +1,116 @@ +/* + * Branch target identification, basic notskip cases. + */ + +#include +#include +#include +#include +#include + +#ifndef PROT_BTI +#define PROT_BTI 0x10 +#endif + +static void skip2_sigill(int sig, siginfo_t *info, void *vuc) +{ + ucontext_t *uc = vuc; + uc->uc_mcontext.pc += 8; + uc->uc_mcontext.pstate = 1; +} + +#define NOP "nop" +#define BTI_N "hint #32" +#define BTI_C "hint #34" +#define BTI_J "hint #36" +#define BTI_JC "hint #38" + +#define BTYPE_1(DEST) \ + "mov x1, #1\n\t" \ + "adr x16, 1f\n\t" \ + "br x16\n" \ +"1: " DEST "\n\t" \ + "mov x1, #0" + +#define BTYPE_2(DEST) \ + "mov x1, #1\n\t" \ + "adr x16, 1f\n\t" \ + "blr x16\n" \ +"1: " DEST "\n\t" \ + "mov x1, #0" + +#define BTYPE_3(DEST) \ + "mov x1, #1\n\t" \ + "adr x15, 1f\n\t" \ + "br x15\n" \ +"1: " DEST "\n\t" \ + "mov x1, #0" + +#define TEST(WHICH, DEST, EXPECT) \ + WHICH(DEST) "\n" \ + ".if " #EXPECT "\n\t" \ + "eor x1, x1," #EXPECT "\n" \ + ".endif\n\t" \ + "add x0, x0, x1\n\t" + +asm("\n" +"test_begin:\n\t" + BTI_C "\n\t" + "mov x2, x30\n\t" + "mov x0, #0\n\t" + + TEST(BTYPE_1, NOP, 1) + TEST(BTYPE_1, BTI_N, 1) + TEST(BTYPE_1, BTI_C, 0) + TEST(BTYPE_1, BTI_J, 0) + TEST(BTYPE_1, BTI_JC, 0) + + TEST(BTYPE_2, NOP, 1) + TEST(BTYPE_2, BTI_N, 1) + TEST(BTYPE_2, BTI_C, 0) + TEST(BTYPE_2, BTI_J, 1) + TEST(BTYPE_2, BTI_JC, 0) + + TEST(BTYPE_3, NOP, 1) + TEST(BTYPE_3, BTI_N, 1) + TEST(BTYPE_3, BTI_C, 1) + TEST(BTYPE_3, BTI_J, 0) + TEST(BTYPE_3, BTI_JC, 0) + + "ret x2\n" +"test_end:" +); + +int main() +{ + struct sigaction sa; + void *tb, *te; + + void *p = mmap(0, getpagesize(), + PROT_EXEC | PROT_READ | PROT_WRITE | PROT_BTI, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (p == MAP_FAILED) { + perror("mmap"); + return 1; + } + + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = skip2_sigill; + sa.sa_flags = SA_SIGINFO; + if (sigaction(SIGILL, &sa, NULL) < 0) { + perror("sigaction"); + return 1; + } + + /* + * ??? With "extern char test_begin[]", some compiler versions + * will use :got references, and some linker versions will + * resolve this reference to a static symbol incorrectly. + * Bypass this error by using a pc-relative reference directly. + */ + asm("adr %0, test_begin; adr %1, test_end" : "=r"(tb), "=r"(te)); + + memcpy(p, tb, te - tb); + + return ((int (*)(void))p)(); +} diff --git a/tests/tcg/aarch64/bti-crt.inc.c b/tests/tcg/aarch64/bti-crt.inc.c new file mode 100644 index 0000000000000000000000000000000000000000..47805f4e35bb507111439b5ee26574a242053cce --- /dev/null +++ b/tests/tcg/aarch64/bti-crt.inc.c @@ -0,0 +1,51 @@ +/* + * Minimal user-environment for testing BTI. + * + * Normal libc is not (yet) built with BTI support enabled, + * and so could generate a BTI TRAP before ever reaching main. + */ + +#include +#include +#include +#include + +int main(void); + +void _start(void) +{ + exit(main()); +} + +void exit(int ret) +{ + register int x0 __asm__("x0") = ret; + register int x8 __asm__("x8") = __NR_exit; + + asm volatile("svc #0" : : "r"(x0), "r"(x8)); + __builtin_unreachable(); +} + +/* + * Irritatingly, the user API struct sigaction does not match the + * kernel API struct sigaction. So for simplicity, isolate the + * kernel ABI here, and make this act like signal. + */ +void signal_info(int sig, void (*fn)(int, siginfo_t *, ucontext_t *)) +{ + struct kernel_sigaction { + void (*handler)(int, siginfo_t *, ucontext_t *); + unsigned long flags; + unsigned long restorer; + unsigned long mask; + } sa = { fn, SA_SIGINFO, 0, 0 }; + + register int x0 __asm__("x0") = sig; + register void *x1 __asm__("x1") = &sa; + register void *x2 __asm__("x2") = 0; + register int x3 __asm__("x3") = sizeof(unsigned long); + register int x8 __asm__("x8") = __NR_rt_sigaction; + + asm volatile("svc #0" + : : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x8) : "memory"); +} diff --git a/tests/tcg/aarch64/pauth-5.c b/tests/tcg/aarch64/pauth-5.c new file mode 100644 index 0000000000000000000000000000000000000000..67c257918b92c4445fd3422dd7643b96113f21d3 --- /dev/null +++ b/tests/tcg/aarch64/pauth-5.c @@ -0,0 +1,33 @@ +#include + +static int x; + +int main() +{ + int *p0 = &x, *p1, *p2, *p3; + unsigned long salt = 0; + + /* + * With TBI enabled and a 48-bit VA, there are 7 bits of auth, and so + * a 1/128 chance of auth = pac(ptr,key,salt) producing zero. + * Find a salt that creates auth != 0. + */ + do { + salt++; + asm("pacda %0, %1" : "=r"(p1) : "r"(salt), "0"(p0)); + } while (p0 == p1); + + /* + * This pac must fail, because the input pointer bears an encryption, + * and so is not properly extended within bits [55:47]. This will + * toggle bit 54 in the output... + */ + asm("pacda %0, %1" : "=r"(p2) : "r"(salt), "0"(p1)); + + /* ... so that the aut must fail, setting bit 53 in the output ... */ + asm("autda %0, %1" : "=r"(p3) : "r"(salt), "0"(p2)); + + /* ... which means this equality must not hold. */ + assert(p3 != p0); + return 0; +} diff --git a/tests/tcg/arm/Makefile.target b/tests/tcg/arm/Makefile.target index 11c39c601ea538d2a2d211103dbb078aed6af02f..ec951565626b3a319912f90b017fa44103789894 100644 --- a/tests/tcg/arm/Makefile.target +++ b/tests/tcg/arm/Makefile.target @@ -45,7 +45,7 @@ run-semihosting-arm: semihosting-arm run-plugin-semihosting-with-%: $(call run-test, $@, $(QEMU) $(QEMU_OPTS) \ - -plugin $(PLUGIN_DIR)/$(call extract-plugin,$@) \ + -plugin $(PLUGIN_LIB)/$(call extract-plugin,$@) \ $(call strip-plugin,$<) 2> $<.err, \ "$< on $(TARGET_NAME) with $*") @@ -68,6 +68,8 @@ run-semiconsole-arm: semiconsole-arm run-plugin-semiconsole-arm-with-%: $(call skip-test, $<, "MANUAL ONLY") +ARM_TESTS += commpage + TESTS += $(ARM_TESTS) # On ARM Linux only supports 4k pages diff --git a/tests/tcg/arm/commpage.c b/tests/tcg/arm/commpage.c new file mode 100644 index 0000000000000000000000000000000000000000..c76e70cb8bd93f11cd301009e644a3950dba33ba --- /dev/null +++ b/tests/tcg/arm/commpage.c @@ -0,0 +1,61 @@ +/* + * Verify the COMMPAGE emulation + * + * The ARM commpage is a set of user space helper functions provided + * by the kernel in an effort to ease portability of user space code + * between different CPUs with potentially different capabilities. It + * is a 32 bit invention and similar to the vdso segment in many ways. + * + * The ABI is documented in the Linux kernel: + * Documentation/arm/kernel_userspace_helpers.rst + * + * Copyright (c) 2020 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include +#include +#include + +#define ARM_COMMPAGE (0xffff0f00u) +#define ARM_KUSER_VERSION (*(int32_t *)(ARM_COMMPAGE + 0xfc)) +typedef void * (get_tls_fn)(void); +#define ARM_KUSER_GET_TLS (*(get_tls_fn *)(ARM_COMMPAGE + 0xe0)) +typedef int (cmpxchg_fn)(int oldval, int newval, volatile int *ptr); +#define ARM_KUSER_CMPXCHG (*(cmpxchg_fn *)(ARM_COMMPAGE + 0xc0)) +typedef void (dmb_fn)(void); +#define ARM_KUSER_DMB (*(dmb_fn *)(ARM_COMMPAGE + 0xa0)) +typedef int (cmpxchg64_fn)(const int64_t *oldval, + const int64_t *newval, + volatile int64_t *ptr); +#define ARM_KUSER_CMPXCHG64 (*(cmpxchg64_fn *)(ARM_COMMPAGE + 0x60)) + +#define fail_unless(x) \ + do { \ + if (!(x)) { \ + fprintf(stderr, "FAILED at %s:%d\n", __FILE__, __LINE__); \ + exit(EXIT_FAILURE); \ + } \ + } while (0) + + +int main(int argc, char *argv[argc]) +{ + void *kuser_tls; + int val = 1; + const int64_t oldval = 1, newval = 2; + int64_t val64 = 1; + + fail_unless(ARM_KUSER_VERSION == 0x5); + kuser_tls = ARM_KUSER_GET_TLS(); + printf("TLS = %p\n", kuser_tls); + fail_unless(kuser_tls != 0); + fail_unless(ARM_KUSER_CMPXCHG(1, 2, &val) == 0); + printf("val = %d\n", val); + /* this is a crash test, not checking an actual barrier occurs */ + ARM_KUSER_DMB(); + fail_unless(ARM_KUSER_CMPXCHG64(&oldval, &newval, &val64) == 0); + printf("val64 = %lld\n", val64); + return 0; +} diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh index eaaaff6233aac8e77d4ba2e87f39cb52638a1f6a..e1b70e25f2375c8f1f9611995187aa12ec3e547f 100755 --- a/tests/tcg/configure.sh +++ b/tests/tcg/configure.sh @@ -46,20 +46,29 @@ fi : ${cross_cc_aarch64="aarch64-linux-gnu-gcc"} : ${cross_cc_aarch64_be="$cross_cc_aarch64"} : ${cross_cc_cflags_aarch64_be="-mbig-endian"} +: $(cross_cc_alpha="alpha-linux-gnu-gcc") : ${cross_cc_arm="arm-linux-gnueabihf-gcc"} : ${cross_cc_cflags_armeb="-mbig-endian"} +: ${cross_cc_hppa="hppa-linux-gnu-gcc"} : ${cross_cc_i386="i386-pc-linux-gnu-gcc"} : ${cross_cc_cflags_i386="-m32"} -: ${cross_cc_x86_64="x86_64-pc-linux-gnu-gcc"} -: ${cross_cc_cflags_x86_64="-m64"} +: ${cross_cc_m68k="m68k-linux-gnu-gcc"} +: $(cross_cc_mips64el="mips64el-linux-gnuabi64-gcc") +: $(cross_cc_mips64="mips64-linux-gnuabi64-gcc") +: $(cross_cc_mipsel="mipsel-linux-gnu-gcc") +: $(cross_cc_mips="mips-linux-gnu-gcc") : ${cross_cc_ppc="powerpc-linux-gnu-gcc"} : ${cross_cc_cflags_ppc="-m32"} -: ${cross_cc_ppc64="powerpc-linux-gnu-gcc"} -: ${cross_cc_cflags_ppc64="-m64"} +: ${cross_cc_ppc64="powerpc64-linux-gnu-gcc"} : ${cross_cc_ppc64le="powerpc64le-linux-gnu-gcc"} -: ${cross_cc_cflags_s390x="-m64"} +: $(cross_cc_riscv64="riscv64-linux-gnu-gcc") +: ${cross_cc_s390x="s390x-linux-gnu-gcc"} +: $(cross_cc_sh4="sh4-linux-gnu-gcc") : ${cross_cc_cflags_sparc="-m32 -mv8plus -mcpu=ultrasparc"} +: ${cross_cc_sparc64="sparc64-linux-gnu-gcc"} : ${cross_cc_cflags_sparc64="-m64 -mcpu=ultrasparc"} +: ${cross_cc_x86_64="x86_64-pc-linux-gnu-gcc"} +: ${cross_cc_cflags_x86_64="-m64"} for target in $target_list; do arch=${target%%-*} @@ -85,7 +94,7 @@ for target in $target_list; do xtensa|xtensaeb) arches=xtensa ;; - alpha|cris|hppa|i386|lm32|m68k|openrisc|riscv64|s390x|sh4|sparc64) + alpha|cris|hppa|i386|lm32|microblaze|microblazeel|m68k|openrisc|riscv64|s390x|sh4|sparc64) arches=$target ;; *) @@ -97,8 +106,8 @@ for target in $target_list; do case $target in aarch64-*) # We don't have any bigendian build tools so we only use this for AArch64 - container_image=debian-arm64-cross - container_cross_cc=aarch64-linux-gnu-gcc + container_image=debian-arm64-test-cross + container_cross_cc=aarch64-linux-gnu-gcc-10 ;; alpha-*) container_image=debian-alpha-cross @@ -173,7 +182,7 @@ for target in $target_list; do container_image=debian-xtensa-cross # default to the dc232b cpu - container_cross_cc=/opt/2018.02/xtensa-dc232b-elf/bin/xtensa-dc232b-elf-gcc + container_cross_cc=/opt/2020.07/xtensa-dc232b-elf/bin/xtensa-dc232b-elf-gcc ;; esac @@ -184,11 +193,11 @@ for target in $target_list; do case $target in *-linux-user | *-bsd-user) echo "CONFIG_USER_ONLY=y" >> $config_target_mak - echo "QEMU=\$(BUILD_DIR)/$target/qemu-$arch" >> $config_target_mak + echo "QEMU=$PWD/qemu-$arch" >> $config_target_mak ;; *-softmmu) echo "CONFIG_SOFTMMU=y" >> $config_target_mak - echo "QEMU=\$(BUILD_DIR)/$target/qemu-system-$arch" >> $config_target_mak + echo "QEMU=$PWD/qemu-system-$arch" >> $config_target_mak ;; esac @@ -231,6 +240,10 @@ for target in $target_list; do -march=armv8.3-a -o $TMPE $TMPC; then echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak fi + if do_compiler "$target_compiler" $target_compiler_cflags \ + -mbranch-protection=standard -o $TMPE $TMPC; then + echo "CROSS_CC_HAS_ARMV8_BTI=y" >> $config_target_mak + fi ;; esac diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target index 43ee2e181e227ed7e56e3b0acf905d51454e1ad8..a66232a67ddb1bea11a14c55383069b1ca6e2123 100644 --- a/tests/tcg/i386/Makefile.target +++ b/tests/tcg/i386/Makefile.target @@ -10,6 +10,14 @@ ALL_X86_TESTS=$(I386_SRCS:.c=) SKIP_I386_TESTS=test-i386-ssse3 X86_64_TESTS:=$(filter test-i386-ssse3, $(ALL_X86_TESTS)) +test-i386-sse-exceptions: CFLAGS += -msse4.1 -mfpmath=sse +run-test-i386-sse-exceptions: QEMU_OPTS += -cpu max +run-plugin-test-i386-sse-exceptions-%: QEMU_OPTS += -cpu max + +test-i386-pcmpistri: CFLAGS += -msse4.2 +run-test-i386-pcmpistri: QEMU_OPTS += -cpu max +run-plugin-test-i386-pcmpistri-%: QEMU_OPTS += -cpu max + # # hello-i386 is a barebones app # diff --git a/tests/tcg/i386/test-i386-f2xm1.c b/tests/tcg/i386/test-i386-f2xm1.c new file mode 100644 index 0000000000000000000000000000000000000000..4513ed8cc103d8e472b1674159e11b588ce9b85b --- /dev/null +++ b/tests/tcg/i386/test-i386-f2xm1.c @@ -0,0 +1,1140 @@ +/* Test f2xm1 instruction. */ + +#include + +struct test { + long double arg, down, up; +}; + +const struct test tests[] = { + { -1.0L, -0.5L, -0.5L }, + { -0.0L, -0.0L, -0.0L }, + { 0.0L, 0.0L, 0.0L }, + /* Randomly generated tests. */ + { 0x4.1481697ac693aa6p-4L, 0x3.17ec9f8454896518p-4L, 0x3.17ec9f845489651cp-4L }, + { -0xd.84a873b14b9c0e2p-4L, -0x7.1788c46ac260d948p-4L, -0x7.1788c46ac260d94p-4L }, + { 0xa.a3dc18b1eff7e8ap-188L, 0x7.6009241b9e21523p-188L, 0x7.6009241b9e215238p-188L }, + { -0xe.846aeb6f58174d5p-92L, -0xa.1006405817acc33p-92L, -0xa.1006405817acc32p-92L }, + { 0x5.4459f2ac77bb0978p-4L, 0x4.19d3ce7fd5b90ac8p-4L, 0x4.19d3ce7fd5b90adp-4L }, + { -0xb.79bece734a62216p-4L, -0x6.4489a7fc150c0fp-4L, -0x6.4489a7fc150c0ef8p-4L }, + { 0xa.ab48f9ef732f5c4p-4L, 0x9.66acd7d4b7cf015p-4L, 0x9.66acd7d4b7cf016p-4L }, + { -0xb.8204e63359a46e6p-4L, -0x6.48060f0a504e3488p-4L, -0x6.48060f0a504e348p-4L }, + { 0xd.c732865701ae935p-4L, 0xd.103bc1a15cd9f71p-4L, 0xd.103bc1a15cd9f72p-4L }, + { -0x1.6296e8ff499827a2p-4L, -0xe.e8dc973f0bce9d1p-8L, -0xe.e8dc973f0bce9dp-8L }, + { 0x8.3e49377820195c8p-4L, 0x6.ddff7e8caa601a08p-4L, 0x6.ddff7e8caa601a1p-4L }, + { -0x7.ece8699d62a9f76p-4L, -0x4.a6516088a15ab01p-4L, -0x4.a6516088a15ab008p-4L }, + { 0x4.b875c0342c9f86b8p-4L, 0x3.a1709cfaecf11ce8p-4L, 0x3.a1709cfaecf11cecp-4L }, + { -0xe.a37e0fa859e499cp-4L, -0x7.83956f7028853738p-4L, -0x7.83956f702885373p-4L }, + { 0x7.23210d9474f0715p-4L, 0x5.cc1ac556913b5258p-4L, 0x5.cc1ac556913b526p-4L }, + { -0xb.755e74862e61e2bp-4L, -0x6.42b11ec6fd4c00dp-4L, -0x6.42b11ec6fd4c00c8p-4L }, + { 0x3.48cc248e266ab90cp-4L, 0x2.724bd1b7f02d354cp-4L, 0x2.724bd1b7f02d355p-4L }, + { -0xa.9a331b76f8ece94p-4L, -0x5.e47b32e80b1f837p-4L, -0x5.e47b32e80b1f8368p-4L }, + { 0x5.8312ebb25c93d22p-4L, 0x4.50bcc3442a6e832p-4L, 0x4.50bcc3442a6e8328p-4L }, + { -0xa.d41581f0036d233p-4L, -0x5.fdb41cec4e2c108p-4L, -0x5.fdb41cec4e2c1078p-4L }, + { 0x4.84a87d8107c5f408p-4L, 0x3.759419ac694e8798p-4L, 0x3.759419ac694e879cp-4L }, + { -0x1.1a592590e007fap-4L, -0xb.f1b5fdf338edbc1p-8L, -0xb.f1b5fdf338edbcp-8L }, + { 0x2.72f96b27827d2054p-4L, 0x1.ca7a491c0c9ae094p-4L, 0x1.ca7a491c0c9ae096p-4L }, + { -0x8.34634eae18e60c5p-4L, -0x4.c941052638a95e6p-4L, -0x4.c941052638a95e58p-4L }, + { 0x2.f6cff94cffe53048p-180L, 0x2.0df7fb06812da41p-180L, 0x2.0df7fb06812da414p-180L }, + { -0x3.e0779bd58963da5p-120L, -0x2.afed04ed88e2c16cp-120L, -0x2.afed04ed88e2c168p-120L }, + { 0xc.1c72a98f7733051p-4L, 0xb.09ddaf3c3330ff9p-4L, 0xb.09ddaf3c3330ffap-4L }, + { -0x9.6eacf3012c77e7p-4L, -0x5.5df25bc91430e81p-4L, -0x5.5df25bc91430e808p-4L }, + { 0x4.962ce97c4afbc1f8p-4L, 0x3.845e1e9659d35364p-4L, 0x3.845e1e9659d35368p-4L }, + { -0xa.a7735b993f17f55p-4L, -0x5.ea46e99ae5f6dce8p-4L, -0x5.ea46e99ae5f6dcep-4L }, + { 0x5.155f76560f08fccp-4L, 0x3.f1149b22956dff34p-4L, 0x3.f1149b22956dff38p-4L }, + { -0xd.32a453289bd47b3p-4L, -0x6.f7a99ad68a5d961p-4L, -0x6.f7a99ad68a5d9608p-4L }, + { 0xa.9942e7418052b4bp-4L, 0x9.52df2bbafc3218bp-4L, 0x9.52df2bbafc3218cp-4L }, + { -0x5.4f4efad2aff4f76p-4L, -0x3.49afb77e7a12385p-4L, -0x3.49afb77e7a12384cp-4L }, + { 0x3.c9e289d962998608p-4L, 0x2.da96d228ab6c8fd8p-4L, 0x2.da96d228ab6c8fdcp-4L }, + { -0x7.cc295689678770bp-4L, -0x4.962bd983de0367b8p-4L, -0x4.962bd983de0367bp-4L }, + { 0xa.8fc7c1f2a46626cp-4L, 0x9.487a90c858224c9p-4L, 0x9.487a90c858224cap-4L }, + { -0x8.a1d9201d5f09ad6p-4L, -0x4.fdf0ccee86f8d98p-4L, -0x4.fdf0ccee86f8d978p-4L }, + { 0x7.5b8ee6778ad1d64p-4L, 0x6.01a5419abf1cb4f8p-4L, 0x6.01a5419abf1cb5p-4L }, + { -0x9.d20d0f7fc98548p-4L, -0x5.8b571e52bd288448p-4L, -0x5.8b571e52bd28844p-4L }, + { 0x5.f135e81ee2608d4p-4L, 0x4.b293c42ca99fd6e8p-4L, 0x4.b293c42ca99fd6fp-4L }, + { -0x5.d981a42b6b7a36fp-4L, -0x3.94e920725edbe7d4p-4L, -0x3.94e920725edbe7dp-4L }, + { 0xa.edffe301db8be0bp-4L, 0x9.b08144d0a85602p-4L, 0x9.b08144d0a856021p-4L }, + { -0x4.5a026d37f55f1d18p-4L, -0x2.bfc10df32554a28cp-4L, -0x2.bfc10df32554a288p-4L }, + { 0x7.82c193b48128193p-4L, 0x6.2723ac59ee5faf68p-4L, 0x6.2723ac59ee5faf7p-4L }, + { -0xd.2d0fe1cd05a87f4p-4L, -0x6.f57a61e00a5f24bp-4L, -0x6.f57a61e00a5f24a8p-4L }, + { 0x5.e1494f95151c64fp-196L, 0x4.13628f9a498f05d8p-196L, 0x4.13628f9a498f05ep-196L }, + { -0x4.51babb72810e518p-140L, -0x2.fe6ee847d0741a5cp-140L, -0x2.fe6ee847d0741a58p-140L }, + { 0xb.638d8454a685474p-4L, 0xa.34a429815e10dc1p-4L, 0xa.34a429815e10dc2p-4L }, + { -0xb.9ec4e9f266dce49p-4L, -0x6.54194f84395ed2b8p-4L, -0x6.54194f84395ed2bp-4L }, + { 0xe.4b7a4c83290855cp-4L, 0xd.b8a9a282646fa0cp-4L, 0xd.b8a9a282646fa0dp-4L }, + { -0xf.13ec97b6c4f17a7p-4L, -0x7.ac86ac65cc0a8878p-4L, -0x7.ac86ac65cc0a887p-4L }, + { 0x3.8ded178a72c15bcp-4L, 0x2.a9dd11713298de98p-4L, 0x2.a9dd11713298de9cp-4L }, + { -0xd.36a9965916287d1p-4L, -0x6.f93c3981d5369078p-4L, -0x6.f93c3981d536907p-4L }, + { 0x6.b3a10f94dcd70e1p-4L, 0x5.63cd831188f697c8p-4L, 0x5.63cd831188f697dp-4L }, + { -0xc.8517674f15bbcbfp-4L, -0x6.b2be7a8ee34bfc8p-4L, -0x6.b2be7a8ee34bfc78p-4L }, + { 0xb.204e5335e697f73p-4L, 0x9.e8bb034ff53dc6p-4L, 0x9.e8bb034ff53dc61p-4L }, + { -0x8.913a951884085ddp-4L, -0x4.f60101f7884f4f6p-4L, -0x4.f60101f7884f4f58p-4L }, + { 0x4.5861903e9a2c5178p-4L, 0x3.50645bac48af734cp-4L, 0x3.50645bac48af735p-4L }, + { -0x5.24585590086993p-4L, -0x3.31f08d8ca7e0c6e4p-4L, -0x3.31f08d8ca7e0c6ep-4L }, + { 0xf.2ba8f23d35f13f9p-4L, 0xe.dedc34179a9e3acp-4L, 0xe.dedc34179a9e3adp-4L }, + { -0xa.3ecdb386b33fbe5p-4L, -0x5.bc2672b634fa598p-4L, -0x5.bc2672b634fa5978p-4L }, + { 0x9.9b8e544f05c6de4p-8L, 0x6.bf33cd9ab91f6d28p-8L, 0x6.bf33cd9ab91f6d3p-8L }, + { -0x7.abd5585035c4696p-4L, -0x4.862497557f052a6p-4L, -0x4.862497557f052a58p-4L }, + { 0xa.e654e5ca1c1d1fbp-4L, 0x9.a7fa0d5fa5d62cbp-4L, 0x9.a7fa0d5fa5d62ccp-4L }, + { -0x7.8b963b5c9698ae88p-8L, -0x5.2d4a519ba339886p-8L, -0x5.2d4a519ba3398858p-8L }, + { 0xb.ea47beace8589dep-4L, 0xa.cf59bd897bb1319p-4L, 0xa.cf59bd897bb131ap-4L }, + { -0x3.8f66d5a2d60e1fc8p-4L, -0x2.496dee34a71055ap-4L, -0x2.496dee34a710559cp-4L }, + { 0x3.1a53eaa26d0157p-188L, 0x2.269608f745c0b83p-188L, 0x2.269608f745c0b834p-188L }, + { -0x8.6659e1a891ccbd3p-96L, -0x5.d282825fc03c7ca8p-96L, -0x5.d282825fc03c7cap-96L }, + { 0x9.4ae3410622cd598p-4L, 0x7.ee3a22f81622643p-4L, 0x7.ee3a22f816226438p-4L }, + { -0x9.b8fe7ab721fb04cp-4L, -0x5.7ff768a6654000e8p-4L, -0x5.7ff768a6654000ep-4L }, + { 0x4.ee554b54200eeb18p-4L, 0x3.cf77028b579146a8p-4L, 0x3.cf77028b579146acp-4L }, + { -0x1.e1d0727b5f12c23cp-8L, -0x1.4d1e625247cef1dap-8L, -0x1.4d1e625247cef1d8p-8L }, + { 0x8.f3637cea7b9b0b8p-4L, 0x7.942f15c8b77d89c8p-4L, 0x7.942f15c8b77d89dp-4L }, + { -0x2.f3202c602060bd7cp-4L, -0x1.eb59cec0fd5e5b22p-4L, -0x1.eb59cec0fd5e5b2p-4L }, + { 0xc.cdb9d9e3a3a5b61p-4L, 0xb.dcaaf5c009c0684p-4L, 0xb.dcaaf5c009c0685p-4L }, + { -0x5.7ddc79efb147e828p-4L, -0x3.63390bf8b99265d4p-4L, -0x3.63390bf8b99265dp-4L }, + { 0x6.7236b6f8976437ap-4L, 0x5.27852c069a4fd5ep-4L, 0x5.27852c069a4fd5e8p-4L }, + { -0x5.e1ad137b44bc3ad8p-4L, -0x3.994d814216774764p-4L, -0x3.994d81421677476p-4L }, + { 0xb.f5ec1a26fcc9d7ep-4L, 0xa.dce2b2a69a74106p-4L, 0xa.dce2b2a69a74107p-4L }, + { -0xd.dcb826624975b1ep-4L, -0x7.394429db03b0d5e8p-4L, -0x7.394429db03b0d5ep-4L }, + { 0x1.a983e64980e6104p-4L, 0x1.31d2cb35db04030ep-4L, 0x1.31d2cb35db04031p-4L }, + { -0xa.14ebef82079ff92p-4L, -0x5.a9758de717320278p-4L, -0x5.a9758de71732027p-4L }, + { 0x1.e4fcc97f32b404d8p-4L, 0x1.5e5913e4b0dadd5ep-4L, 0x1.5e5913e4b0dadd6p-4L }, + { -0xe.9391126d81ddf25p-4L, -0x7.7db899379b97afep-4L, -0x7.7db899379b97afd8p-4L }, + { 0xb.83be497f42b1776p-8L, 0x8.1b67845064d833ap-8L, 0x8.1b67845064d833bp-8L }, + { -0xb.6c13349b9671c7bp-4L, -0x6.3ec4737bebffb8f8p-4L, -0x6.3ec4737bebffb8fp-4L }, + { 0xd.00d476fab7a907dp-4L, 0xc.1a9e868d759da06p-4L, 0xc.1a9e868d759da07p-4L }, + { -0x3.bf394566ed3e5a44p-4L, -0x2.65b989f46e7a2458p-4L, -0x2.65b989f46e7a2454p-4L }, + { 0x7.4a72aacaec9cd52p-52L, 0x5.0db91de577a1e5c8p-52L, 0x5.0db91de577a1e5dp-52L }, + { -0x4.3354d8429f36037p-24L, -0x2.e95ce5bede67faap-24L, -0x2.e95ce5bede67fa9cp-24L }, + { 0x5.431e650334b97d18p-4L, 0x4.18c10ccaa716c258p-4L, 0x4.18c10ccaa716c26p-4L }, + { -0xf.1eb2c535e06fba3p-4L, -0x7.b068a3edafc6822p-4L, -0x7.b068a3edafc68218p-4L }, + { 0x8.54a857fb1034b62p-4L, 0x6.f433cc318f296fep-4L, 0x6.f433cc318f296fe8p-4L }, + { -0xa.d3c15d582c446d9p-4L, -0x5.fd8fa08a9be23ac8p-4L, -0x5.fd8fa08a9be23acp-4L }, + { 0xc.cb73edcbfcb307fp-4L, 0xb.d9ecb2c64e8df6bp-4L, 0xb.d9ecb2c64e8df6cp-4L }, + { -0x3.fb61f1b2cf35f60cp-4L, -0x2.88fef3c7864d396cp-4L, -0x2.88fef3c7864d3968p-4L }, + { 0x9.d7eb5c50bc8c632p-4L, 0x8.8231f68c5c65f6cp-4L, 0x8.8231f68c5c65f6dp-4L }, + { -0x4.d312891f5f4e786p-4L, -0x3.048b329391356fc8p-4L, -0x3.048b329391356fc4p-4L }, + { 0xe.ae0633b99b178edp-4L, 0xe.389ce9e10301401p-4L, 0xe.389ce9e10301402p-4L }, + { -0x1.39568b7ef55672cp-4L, -0xd.38818f18029f0edp-8L, -0xd.38818f18029f0ecp-8L }, + { 0x4.cf293b1353f539bp-4L, 0x3.b4c86315977b5c7cp-4L, 0x3.b4c86315977b5c8p-4L }, + { -0xd.2b8a9e00126538ap-4L, -0x6.f4e1e5a5bc2731ap-4L, -0x6.f4e1e5a5bc273198p-4L }, + { 0x5.b5eb2a3dcc35826p-8L, 0x3.fd3309c0a1b58598p-8L, 0x3.fd3309c0a1b5859cp-8L }, + { -0xa.db19f19a7ea88bep-4L, -0x6.00be987018657798p-4L, -0x6.00be98701865779p-4L }, + { 0x1.09017c7c80c2c48ap-4L, 0xb.bde7d981fb53b8ep-8L, 0xb.bde7d981fb53b8fp-8L }, + { -0x2.5ae089add9bdff18p-4L, -0x1.8d45d20a5f7c4556p-4L, -0x1.8d45d20a5f7c4554p-4L }, + { 0x6.d211b21df46dcc18p-4L, 0x5.801525b9519ab1cp-4L, 0x5.801525b9519ab1c8p-4L }, + { -0xd.1a64a16c7c8f6d7p-4L, -0x6.ee27813a5adc48a8p-4L, -0x6.ee27813a5adc48ap-4L }, + { 0xc.1ef9ffac1d2c793p-4L, 0xb.0cd41b95ab8f726p-4L, 0xb.0cd41b95ab8f727p-4L }, + { -0x1.67c59b4c06bd7496p-4L, -0xf.1ef71ffc4b3edp-8L, -0xf.1ef71ffc4b3ecffp-8L }, + { 0x8.ba4b4feae22142bp-168L, 0x6.0cb1d8faa6f42ce8p-168L, 0x6.0cb1d8faa6f42cfp-168L }, + { -0x4.d89f7b5a88882dbp-32L, -0x3.5bef2f703124413p-32L, -0x3.5bef2f703124412cp-32L }, + { 0xb.03fa4c349a339d2p-4L, 0x9.c902a02a0215ad1p-4L, 0x9.c902a02a0215ad2p-4L }, + { -0x1.e57ddc8153f3ba8p-8L, -0x1.4fa797d98bce1f74p-8L, -0x1.4fa797d98bce1f72p-8L }, + { 0xc.9c281b57f7d11c8p-4L, 0xb.a11623dd20659ecp-4L, 0xb.a11623dd20659edp-4L }, + { -0x6.8fac6e3f60b61e1p-4L, -0x3.f56b115363b7d2d8p-4L, -0x3.f56b115363b7d2d4p-4L }, + { 0x3.65bed5b32d99326p-4L, 0x2.897c78eee4adc054p-4L, 0x2.897c78eee4adc058p-4L }, + { -0x2.3ef31cc65b2354cp-4L, -0x1.7bc0457bdf14a022p-4L, -0x1.7bc0457bdf14a02p-4L }, + { 0x2.bceec8bc1d31b0ccp-4L, 0x2.03d68f4acad10114p-4L, 0x2.03d68f4acad10118p-4L }, + { -0xd.146217a63673958p-4L, -0x6.ebcaaea4b926a99p-4L, -0x6.ebcaaea4b926a988p-4L }, + { 0x2.17b7fc97b1f46e7cp-4L, 0x1.84af2ad78df6619cp-4L, 0x1.84af2ad78df6619ep-4L }, + { -0x4.49abbcdefc0c959p-4L, -0x2.b65ca46b981930ecp-4L, -0x2.b65ca46b981930e8p-4L }, + { 0x3.efc6f5f489c6c7bcp-4L, 0x2.f9a3671c9c3698fcp-4L, 0x2.f9a3671c9c3699p-4L }, + { -0x8.f7ff40b96f9bd91p-4L, -0x5.26b9d6a96a7c7d4p-4L, -0x5.26b9d6a96a7c7d38p-4L }, + { 0x6.003126d0e9a9acc8p-4L, 0x4.c0070418e60c3eap-4L, 0x4.c0070418e60c3ea8p-4L }, + { -0x5.7be9edcc9dc2a02p-4L, -0x3.6228999b34cd56c8p-4L, -0x3.6228999b34cd56c4p-4L }, + { 0x7.8952a49ff2c2f168p-4L, 0x6.2d71e3ee870f2fp-4L, 0x6.2d71e3ee870f2f08p-4L }, + { -0x3.8a644fc56f9d1fbp-4L, -0x2.4673b0704862205cp-4L, -0x2.4673b07048622058p-4L }, + { 0xf.c1271b0a53a3319p-4L, 0xf.a9563e019f9388ep-4L, 0xf.a9563e019f9388fp-4L }, + { -0x8.a07f742f2a61d18p-4L, -0x4.fd4bef713b1bf35p-4L, -0x4.fd4bef713b1bf348p-4L }, + { 0xf.ce2fc60abd9a47cp-4L, 0xf.bb3bf685a5fb078p-4L, 0xf.bb3bf685a5fb079p-4L }, + { -0x9.e8a3a1c0f885e07p-4L, -0x5.958d6298d2833328p-4L, -0x5.958d6298d283332p-4L }, + { 0xd.11c135742977841p-96L, 0x9.0f19b73e51b46a5p-96L, 0x9.0f19b73e51b46a6p-96L }, + { -0x1.0028929dbde83802p-60L, -0xb.18e376bf8ce7ca1p-64L, -0xb.18e376bf8ce7cap-64L }, + { 0x5.244b484bc9bb7828p-4L, 0x3.fdfcc0ee0ab5b92p-4L, 0x3.fdfcc0ee0ab5b924p-4L }, + { -0x7.02ec4c8b2cc95998p-4L, -0x4.30f4ae1282b41938p-4L, -0x4.30f4ae1282b4193p-4L }, + { 0xa.4d34be63f5bedffp-4L, 0x8.fff7fb1648dba28p-4L, 0x8.fff7fb1648dba29p-4L }, + { -0xf.be786c39b309e8p-4L, -0x7.e929ac0fe4454fbp-4L, -0x7.e929ac0fe4454fa8p-4L }, + { 0x6.16481538d3215558p-4L, 0x4.d3ebea6da53ed4bp-4L, 0x4.d3ebea6da53ed4b8p-4L }, + { -0x8.5ea05eecb9ac14dp-4L, -0x4.ddb34f8925005bf8p-4L, -0x4.ddb34f8925005bfp-4L }, + { 0xd.4be5b4aaf95a52bp-4L, 0xc.7698fe58f5fbc96p-4L, 0xc.7698fe58f5fbc97p-4L }, + { -0x5.505294ddb8af9558p-4L, -0x3.4a3eaba09a1a5584p-4L, -0x3.4a3eaba09a1a558p-4L }, + { 0xf.a2f9540a64c79ap-8L, 0xb.1239629d9548b9ap-8L, 0xb.1239629d9548b9bp-8L }, + { -0x2.b68cfa7df5a80aep-4L, -0x1.c635cc5a0e342052p-4L, -0x1.c635cc5a0e34205p-4L }, + { 0xb.8ac8e4b25441b53p-4L, 0xa.6154102e9f6deb3p-4L, 0xa.6154102e9f6deb4p-4L }, + { -0x2.047a032c2a353b58p-4L, -0x1.56cbb83364a118fcp-4L, -0x1.56cbb83364a118fap-4L }, + { 0x8.eb2ab17c06312d9p-4L, 0x7.8bca95748b755068p-4L, 0x7.8bca95748b75507p-4L }, + { -0xb.932fffb0dfd7537p-4L, -0x6.4f3dd628a0e5cf6p-4L, -0x6.4f3dd628a0e5cf58p-4L }, + { 0x4.e0e6c013f25279bp-4L, 0x3.c3f354fd7de31834p-4L, 0x3.c3f354fd7de31838p-4L }, + { -0xa.7fafcf461e92982p-4L, -0x5.d8d88aa29bb4cebp-4L, -0x5.d8d88aa29bb4cea8p-4L }, + { 0x6.41b8cd66b9392ef8p-4L, 0x4.fb4312effd41adb8p-4L, 0x4.fb4312effd41adcp-4L }, + { -0xf.d372339bf2bef0fp-4L, -0x7.f0801caf476622cp-4L, -0x7.f0801caf476622b8p-4L }, + { 0xf.843d63b0a71eb93p-4L, 0xf.56375011490bccp-4L, 0xf.56375011490bcc1p-4L }, + { -0xe.679784396815117p-4L, -0x7.6d735bc4f5da77p-4L, -0x7.6d735bc4f5da76f8p-4L }, + { 0x2.d7c4bef6577f86p-168L, 0x1.f87361c88ca3f5dcp-168L, 0x1.f87361c88ca3f5dep-168L }, + { -0x3.f871c581e5f5dc24p-128L, -0x2.c08bab62f3684a08p-128L, -0x2.c08bab62f3684a04p-128L }, + { 0x9.f6c4eb5c911111ap-4L, 0x8.a309258b14973d6p-4L, 0x8.a309258b14973d7p-4L }, + { -0xa.08c53e65e98b067p-4L, -0x5.a402f5ec7cf294fp-4L, -0x5.a402f5ec7cf294e8p-4L }, + { 0x4.1a4c613ba5fe16ap-4L, 0x3.1cb7e0a2f57d95e4p-4L, 0x3.1cb7e0a2f57d95e8p-4L }, + { -0xd.36e91d3e54f0432p-4L, -0x6.f95510d133d9ba9p-4L, -0x6.f95510d133d9ba88p-4L }, + { 0xd.1de964de30857a7p-4L, 0xc.3e1d28af4fff2d7p-4L, 0xc.3e1d28af4fff2d8p-4L }, + { -0x8.604a0e63d4f5df1p-4L, -0x4.de809bb2d3dfaec8p-4L, -0x4.de809bb2d3dfaecp-4L }, + { 0xc.6b9d18c70882d52p-4L, 0xb.67389c48f17db3ap-4L, 0xb.67389c48f17db3bp-4L }, + { -0x2.711b4139fbed3dc8p-4L, -0x1.9b290dfa49d31a48p-4L, -0x1.9b290dfa49d31a46p-4L }, + { 0x9.4021cab7a0d78bbp-4L, 0x7.e3162eb6a1bdbe8p-4L, 0x7.e3162eb6a1bdbe88p-4L }, + { -0x8.305eb92b4243ea2p-4L, -0x4.c74d292fe63f0918p-4L, -0x4.c74d292fe63f091p-4L }, + { 0x4.f0330cdb93893948p-4L, 0x3.d111183eddd7d2p-4L, 0x3.d111183eddd7d204p-4L }, + { -0xe.be93c7764505ff9p-8L, -0xa.04ccfff3805ed0dp-8L, -0xa.04ccfff3805ed0cp-8L }, + { 0xd.ea533ffe043e52bp-4L, 0xd.3c980125a65c5dfp-4L, 0xd.3c980125a65c5ep-4L }, + { -0x1.1dd2693fe11489c2p-4L, -0xc.166d57fe9c4abe2p-8L, -0xc.166d57fe9c4abe1p-8L }, + { 0x2.0397d0e9676f1b2p-4L, 0x1.756fb86ebc62a682p-4L, 0x1.756fb86ebc62a684p-4L }, + { -0xa.9002b4ad763bb7cp-4L, -0x5.e0041011e34ae53p-4L, -0x5.e0041011e34ae528p-4L }, + { 0x3.34a5a4894a28659cp-4L, 0x2.623883e4934c92d8p-4L, 0x2.623883e4934c92dcp-4L }, + { -0xd.c27cd78e0864371p-4L, -0x7.2f454c780b622d58p-4L, -0x7.2f454c780b622d5p-4L }, + { 0x9.c7f27c2034ec1cfp-4L, 0x8.714272ce09a4f87p-4L, 0x8.714272ce09a4f88p-4L }, + { -0xa.a9e0aa658eda7dcp-4L, -0x5.eb564d46b128566p-4L, -0x5.eb564d46b1285658p-4L }, + { 0xa.0183ad6b5f24f24p-148L, 0x6.ef81a75cf4925d9p-148L, 0x6.ef81a75cf4925d98p-148L }, + { -0x2.0bdfa7925a4bf4ap-28L, -0x1.6b1f1d70f143adc4p-28L, -0x1.6b1f1d70f143adc2p-28L }, + { 0xa.93e861896961066p-4L, 0x9.4d004c2eac2676fp-4L, 0x9.4d004c2eac2677p-4L }, + { -0xd.4c10bf60bb97196p-4L, -0x7.0196eb9b79274b88p-4L, -0x7.0196eb9b79274b8p-4L }, + { 0x4.ff124c9911f2538p-4L, 0x3.ddd9b3e49fd11e9p-4L, 0x3.ddd9b3e49fd11e94p-4L }, + { -0x8.776b58ba7268d9ep-4L, -0x4.e9a2512b1cd9282p-4L, -0x4.e9a2512b1cd92818p-4L }, + { 0x9.b6f6d16f1d76615p-4L, 0x8.5f4d5e77db1195p-4L, 0x8.5f4d5e77db11951p-4L }, + { -0x9.b667363949a8b6dp-4L, -0x5.7ec9a21714bc48c8p-4L, -0x5.7ec9a21714bc48cp-4L }, + { 0x9.799737c602ebc35p-12L, 0x6.92a3d4df8ac3168p-12L, 0x6.92a3d4df8ac31688p-12L }, + { -0x9.dc0d38d251990e4p-4L, -0x5.8fddc90938b5c8a8p-4L, -0x5.8fddc90938b5c8ap-4L }, + { 0x1.51d68e213ec66d4ep-4L, 0xf.0feacd9b26e94efp-8L, 0xf.0feacd9b26e94fp-8L }, + { -0xd.c78a8c73db2538p-4L, -0x7.313326148c62dbd8p-4L, -0x7.313326148c62dbdp-4L }, + { 0x7.c5f3d0d9d9db89cp-4L, 0x6.67fee55e98a6cf7p-4L, 0x6.67fee55e98a6cf78p-4L }, + { -0x1.6b364994830303c2p-4L, -0xf.42da9bf688d1dbp-8L, -0xf.42da9bf688d1dafp-8L }, + { 0x4.2513fed56a721cp-4L, 0x3.25a6d8fff7773d4cp-4L, 0x3.25a6d8fff7773d5p-4L }, + { -0x3.e183251bd312b9f8p-4L, -0x2.79df44b0dabf9e1p-4L, -0x2.79df44b0dabf9e0cp-4L }, + { 0x5.372c1f6cb3bb4cep-8L, 0x3.a4094f9b223ac4d8p-8L, 0x3.a4094f9b223ac4dcp-8L }, + { -0xc.30d4cc265a07403p-4L, -0x6.908bed536532ac7p-4L, -0x6.908bed536532ac68p-4L }, + { 0xf.7e3aa552d45b234p-4L, 0xf.4e0f6f1aac5a5e6p-4L, 0xf.4e0f6f1aac5a5e7p-4L }, + { -0x3.9a644e95053aaf1cp-4L, -0x2.4ff3cc5ef967d1bcp-4L, -0x2.4ff3cc5ef967d1b8p-4L }, + { 0xe.85839cd58ef2c75p-4L, 0xe.03c1d8a304b280dp-4L, 0xe.03c1d8a304b280ep-4L }, + { -0x7.8809e818c58ede8p-4L, -0x4.744b120d61aa22b8p-4L, -0x4.744b120d61aa22bp-4L }, + { 0xd.d9ee24413681697p-176L, 0x9.99d9ff1a3fe5cecp-176L, 0x9.99d9ff1a3fe5cedp-176L }, + { -0x3.40d11dc412df0dd4p-140L, -0x2.4143c0acd05aa3fcp-140L, -0x2.4143c0acd05aa3f8p-140L }, + { 0x5.0487ddb4070bf26p-4L, 0x3.e28d14d38a11cea8p-4L, 0x3.e28d14d38a11ceacp-4L }, + { -0x5.a0e26438dfac03cp-4L, -0x3.764d74346acb839p-4L, -0x3.764d74346acb838cp-4L }, + { 0x4.cfd480a28c2b6b48p-4L, 0x3.b55a9c63e74d1b2cp-4L, 0x3.b55a9c63e74d1b3p-4L }, + { -0x1.8657dd64795c35ap-4L, -0x1.05d2980556ab36f8p-4L, -0x1.05d2980556ab36f6p-4L }, + { 0x1.262cb60430e5eb9ep-4L, 0xd.11128880978613p-8L, 0xd.111288809786131p-8L }, + { -0x8.0e85fe0bcf8a253p-4L, -0x4.b6ccdbc2803a24p-4L, -0x4.b6ccdbc2803a23f8p-4L }, + { 0x3.cefbd3ecacf92c44p-4L, 0x2.dec16ac730be9dbp-4L, 0x2.dec16ac730be9db4p-4L }, + { -0x5.f20def7196dea63p-4L, -0x3.a216f486f08b5aecp-4L, -0x3.a216f486f08b5ae8p-4L }, + { 0x1.3a394f91198290bcp-4L, 0xd.fb2be9402707d47p-8L, 0xd.fb2be9402707d48p-8L }, + { -0x5.fa0cb4bdfd2d7318p-4L, -0x3.a65ec6a869e7e184p-4L, -0x3.a65ec6a869e7e18p-4L }, + { 0x4.08cc4ee18d971c48p-4L, 0x3.0e3ffd7c5370e6b8p-4L, 0x3.0e3ffd7c5370e6bcp-4L }, + { -0xc.08ff29dce9d081fp-4L, -0x6.8035806826b593e8p-4L, -0x6.8035806826b593ep-4L }, + { 0x8.84e7a8e11ece222p-4L, 0x7.2460415572a2c778p-4L, 0x7.2460415572a2c78p-4L }, + { -0x3.6ac116d0aa98b8bp-4L, -0x2.3397207a04b6d448p-4L, -0x2.3397207a04b6d444p-4L }, + { 0x5.b4cccaf7aee9cd6p-4L, 0x4.7caf8d9a7c39bdf8p-4L, 0x4.7caf8d9a7c39bep-4L }, + { -0xd.08cda37bcd9c8cp-4L, -0x6.e73b932483f4027p-4L, -0x6.e73b932483f40268p-4L }, + { 0xb.d7f74d7d0014f61p-4L, 0xa.ba1cc39b8135ef5p-4L, 0xa.ba1cc39b8135ef6p-4L }, + { -0xa.7263655e0a0ea62p-4L, -0x5.d2fd72c3fb172f98p-4L, -0x5.d2fd72c3fb172f9p-4L }, + { 0x2.47b34fa6f1ad5d68p-4L, 0x1.a93f34ee2980e0cap-4L, 0x1.a93f34ee2980e0ccp-4L }, + { -0x8.fcbb11c22f14e77p-4L, -0x5.28f3257a6e3ab71p-4L, -0x5.28f3257a6e3ab708p-4L }, + { 0xf.9268d3496434d05p-16L, 0xa.cb65631de896653p-16L, 0xa.cb65631de896654p-16L }, + { -0x6.90a7904ae1f6ca48p-172L, -0x4.8cf0e2bc08a21768p-172L, -0x4.8cf0e2bc08a2176p-172L }, + { 0xf.e7cc8c0c8fca8d6p-4L, 0xf.de84d77e096dc2cp-4L, 0xf.de84d77e096dc2dp-4L }, + { -0xb.5766572c78c1636p-4L, -0x6.3603cb668acec5ep-4L, -0x6.3603cb668acec5d8p-4L }, + { 0x7.08271953e92da93p-4L, 0x5.b2b05f792a83ec2p-4L, 0x5.b2b05f792a83ec28p-4L }, + { -0xe.0f6704c35bc87d8p-4L, -0x7.4c742ba7517a322p-4L, -0x7.4c742ba7517a3218p-4L }, + { 0x3.622e5c923b06d66cp-8L, 0x2.5b264a119b7052e8p-8L, 0x2.5b264a119b7052ecp-8L }, + { -0x8.911302b7a344f8ap-4L, -0x4.f5ee153ff9a408ap-4L, -0x4.f5ee153ff9a40898p-4L }, + { 0x5.5234861ad0d016d8p-4L, 0x4.25e7cdeba20def88p-4L, 0x4.25e7cdeba20def9p-4L }, + { -0x8.87063dd41e8a8bbp-4L, -0x4.f11ea0bcf9eb3e7p-4L, -0x4.f11ea0bcf9eb3e68p-4L }, + { 0x4.e1420e7e82cd22dp-4L, 0x3.c44184744892d3ecp-4L, 0x3.c44184744892d3fp-4L }, + { -0xb.db1fc14ef9e7aa3p-4L, -0x6.6d4209f7697a729p-4L, -0x6.6d4209f7697a7288p-4L }, + { 0xc.8346ca25bd9f342p-4L, 0xb.835e70838f32309p-4L, 0xb.835e70838f3230ap-4L }, + { -0x1.51646879b012b5b8p-4L, -0xe.34fbed59aa6c7acp-8L, -0xe.34fbed59aa6c7abp-8L }, + { 0x2.b32d8027c5516654p-4L, 0x1.fc3b2ff7be6c91e6p-4L, 0x1.fc3b2ff7be6c91e8p-4L }, + { -0x6.fd1366df02fe9c5p-4L, -0x4.2df6864ab991689p-4L, -0x4.2df6864ab9916888p-4L }, + { 0x6.c090b4e367d6c7ep-8L, 0x4.b92b6f86425d3ccp-8L, 0x4.b92b6f86425d3cc8p-8L }, + { -0x5.081c001c09df9f3p-4L, -0x3.223d2d4760b053ap-4L, -0x3.223d2d4760b0539cp-4L }, + { 0x7.f9714aab4e09b278p-4L, 0x6.9a31bedda6cc2ab8p-4L, 0x6.9a31bedda6cc2acp-4L }, + { -0x6.4804670d1e062cd8p-4L, -0x3.cfcfa1c45c5a88e8p-4L, -0x3.cfcfa1c45c5a88e4p-4L }, + { 0x9.ef4abcd7f8e696ap-4L, 0x8.9b0f698e7955a9p-4L, 0x8.9b0f698e7955a91p-4L }, + { -0x4.8c4513525f5a0ap-4L, -0x2.dc7be2a249c73a38p-4L, -0x2.dc7be2a249c73a34p-4L }, + { 0x1.7fe67833e1976e6p-168L, 0x1.0a1971aebce11604p-168L, 0x1.0a1971aebce11606p-168L }, + { -0xe.a86b5a2c843f668p-36L, -0xa.28fa9875dd806c6p-36L, -0xa.28fa9875dd806c5p-36L }, + { 0x6.0dd96d442bc44b28p-4L, 0x4.cc518e951f69bd48p-4L, 0x4.cc518e951f69bd5p-4L }, + { -0x3.e88917f9e6c0bb2p-4L, -0x2.7dfc064ecfe2635cp-4L, -0x2.7dfc064ecfe26358p-4L }, + { 0xf.e9c0adcf6e6ebaap-4L, 0xf.e13773c6da26f73p-4L, 0xf.e13773c6da26f74p-4L }, + { -0xe.6049cc9d4ea9c32p-8L, -0x9.c5f8986aafe8b3p-8L, -0x9.c5f8986aafe8b2fp-8L }, + { 0xd.e0ca0ae677c56c7p-4L, 0xd.30868169c79fdeap-4L, 0xd.30868169c79fdebp-4L }, + { -0x3.b604528c1bde4ca8p-4L, -0x2.604b88132e3dceb4p-4L, -0x2.604b88132e3dcebp-4L }, + { 0x9.3e94ea277274ab3p-4L, 0x7.e17b8968152545ep-4L, 0x7.e17b8968152545e8p-4L }, + { -0xf.ec080621a8d9456p-4L, -0x7.f91153ca519955fp-4L, -0x7.f91153ca519955e8p-4L }, + { 0x1.96ef7e6b80e63adep-4L, 0x1.24014f5d43fc1232p-4L, 0x1.24014f5d43fc1234p-4L }, + { -0x2.fd0a9d9f59d83bc8p-4L, -0x1.f164f450f8e2c15p-4L, -0x1.f164f450f8e2c14ep-4L }, + { 0x5.82923d4fd6f683p-4L, 0x4.504b840326d2f688p-4L, 0x4.504b840326d2f69p-4L }, + { -0x2.5fa1d9a3a5a2b664p-4L, -0x1.903f73ce566d8522p-4L, -0x1.903f73ce566d852p-4L }, + { 0xf.b8a161f6eba3189p-4L, 0xf.9da7e29775ea166p-4L, 0xf.9da7e29775ea167p-4L }, + { -0xb.79a14c17c57922dp-4L, -0x6.447d36e53f9fbf98p-4L, -0x6.447d36e53f9fbf9p-4L }, + { 0x9.9b19d045170086ap-4L, 0x8.41f3b9e1fe6130dp-4L, 0x8.41f3b9e1fe6130ep-4L }, + { -0xd.65fbae6f453f5a2p-4L, -0x7.0baa677949607eb8p-4L, -0x7.0baa677949607ebp-4L }, + { 0xc.7a9e15e82248878p-4L, 0xb.790e3f5b2936dc4p-4L, 0xb.790e3f5b2936dc5p-4L }, + { -0x3.f5ec8986cfd785dp-4L, -0x2.85cf707de281dc78p-4L, -0x2.85cf707de281dc74p-4L }, + { 0xa.530c1b060238f06p-4L, 0x9.064c5060f10810bp-4L, 0x9.064c5060f10810cp-4L }, + { -0x3.aa0cc319c013919p-4L, -0x2.59398f9b92fe953p-4L, -0x2.59398f9b92fe952cp-4L }, + { 0x3.c0a4bd100746357p-184L, 0x2.99de0a05056aaf74p-184L, 0x2.99de0a05056aaf78p-184L }, + { -0x6.fd442271482ca6dp-136L, -0x4.d8398bacdf9d28ap-136L, -0x4.d8398bacdf9d2898p-136L }, + { 0x6.67012d8b67014328p-4L, 0x5.1d41e56dafaf995p-4L, 0x5.1d41e56dafaf9958p-4L }, + { -0xa.6b6836f2ff72662p-4L, -0x5.cfe921fda171774p-4L, -0x5.cfe921fda1717738p-4L }, + { 0x9.620bcddbdd20a79p-4L, 0x8.064866d2e843838p-4L, 0x8.064866d2e843839p-4L }, + { -0x4.17376606afdde85p-4L, -0x2.99319a6951355f74p-4L, -0x2.99319a6951355f7p-4L }, + { 0xd.1dc39e358b023ap-4L, 0xc.3deef0997e22f56p-4L, 0xc.3deef0997e22f57p-4L }, + { -0xb.13430c035931444p-4L, -0x6.18f3b1ddbf4bbd98p-4L, -0x6.18f3b1ddbf4bbd9p-4L }, + { 0x3.606617a1673d0184p-4L, 0x2.8531caa9e41d88d8p-4L, 0x2.8531caa9e41d88dcp-4L }, + { -0x8.f017932d188a998p-4L, -0x5.23021a6f15e3204p-4L, -0x5.23021a6f15e32038p-4L }, + { 0x3.cf39982caefbf098p-4L, 0x2.def3e957a9d7b4e8p-4L, 0x2.def3e957a9d7b4ecp-4L }, + { -0x1.8dad3bd8dae62b26p-4L, -0x1.0a93f35dbc547e06p-4L, -0x1.0a93f35dbc547e04p-4L }, + { 0xf.d53ec036950502fp-4L, 0xf.c4f16bfb42b91ebp-4L, 0xf.c4f16bfb42b91ecp-4L }, + { -0xa.9cb0f8ebab4d7f8p-4L, -0x5.e59271c5142a2828p-4L, -0x5.e59271c5142a282p-4L }, + { 0x4.9ff6d398cf5c723p-4L, 0x3.8ca6a81f115945c8p-4L, 0x3.8ca6a81f115945ccp-4L }, + { -0x3.c7ea3c3c2b39e2c8p-4L, -0x2.6ad7b91001b1a278p-4L, -0x2.6ad7b91001b1a274p-4L }, + { 0xf.7206b4c8d50f316p-4L, 0xf.3d872c603dec047p-4L, 0xf.3d872c603dec048p-4L }, + { -0x7.5f74c3dd6c9936dp-4L, -0x4.5fecbd230b7b225p-4L, -0x4.5fecbd230b7b2248p-4L }, + { 0x1.d1a5048e1cfadea8p-4L, 0x1.4fd148e51db81464p-4L, 0x1.4fd148e51db81466p-4L }, + { -0xe.8f9244700df6721p-4L, -0x7.7c3f71d67ca51a2p-4L, -0x7.7c3f71d67ca51a18p-4L }, + { 0x3.99c86ae38d72f47cp-4L, 0x2.b375b38730124248p-4L, 0x2.b375b3873012424cp-4L }, + { -0x5.e2a8926a1f2a69f8p-4L, -0x3.99d49b6de5eb2bfp-4L, -0x3.99d49b6de5eb2becp-4L }, + { 0x2.58e048821c0475f4p-64L, 0x1.a07ede4412af4bbap-64L, 0x1.a07ede4412af4bbcp-64L }, + { -0x1.8989c2560de848e8p-124L, -0x1.10c7a38e60d87138p-124L, -0x1.10c7a38e60d87136p-124L }, + { 0x7.bc19ff559d9831b8p-4L, 0x6.5e7110fac4089518p-4L, 0x6.5e7110fac408952p-4L }, + { -0x6.c87c79c7f39458b8p-4L, -0x4.12e9a15e9bfdadb8p-4L, -0x4.12e9a15e9bfdadbp-4L }, + { 0x2.f5c34056d7c105dp-4L, 0x2.30678a0e37a17cep-4L, 0x2.30678a0e37a17ce4p-4L }, + { -0xd.4a8d8fca0cbe02bp-4L, -0x7.01000b10ed4e999p-4L, -0x7.01000b10ed4e9988p-4L }, + { 0x6.f866735c25236f98p-4L, 0x5.a3e6c10f6f1511fp-4L, 0x5.a3e6c10f6f1511f8p-4L }, + { -0xc.91587f5ff35915fp-4L, -0x6.b7ad5204ea051758p-4L, -0x6.b7ad5204ea05175p-4L }, + { 0x5.8acab0d65d615ap-4L, 0x4.5788c486bedea82p-4L, 0x4.5788c486bedea828p-4L }, + { -0xa.a22cceb5d16a7b9p-4L, -0x5.e7f89a5c228804ap-4L, -0x5.e7f89a5c22880498p-4L }, + { 0x7.9bb3d37308387268p-4L, 0x6.3f21841dccbd4848p-4L, 0x6.3f21841dccbd485p-4L }, + { -0xc.186ea423cfbc56dp-4L, -0x6.868d7eab6a729728p-4L, -0x6.868d7eab6a72972p-4L }, + { 0x2.797cf0eb89b43758p-4L, 0x1.cf80358fed6434cap-4L, 0x1.cf80358fed6434ccp-4L }, + { -0x1.5803a5d39e417564p-4L, -0xe.7a4f6be0f29e7b7p-8L, -0xe.7a4f6be0f29e7b6p-8L }, + { 0xc.a52f12f15058ap-8L, 0x8.eab3287521cf0c3p-8L, 0x8.eab3287521cf0c4p-8L }, + { -0x7.c0b1a87701c336f8p-4L, -0x4.907ee683856ce948p-4L, -0x4.907ee683856ce94p-4L }, + { 0x7.810b603203760db8p-4L, 0x6.257f312ef0f8e4cp-4L, 0x6.257f312ef0f8e4c8p-4L }, + { -0x3.74e32a2c3287777cp-4L, -0x2.39a477aba5f3e36cp-4L, -0x2.39a477aba5f3e368p-4L }, + { 0x7.ce4d4cf62f3cae4p-4L, 0x6.701b2af84891b008p-4L, 0x6.701b2af84891b01p-4L }, + { -0xc.d26229e318f0c64p-4L, -0x6.d1b0028af7ad99e8p-4L, -0x6.d1b0028af7ad99ep-4L }, + { 0x8.457740622adf15fp-4L, 0x6.e51d70eb7475fd68p-4L, 0x6.e51d70eb7475fd7p-4L }, + { -0x7.492c117c47e7f31p-4L, -0x4.54ae45d535c0da2p-4L, -0x4.54ae45d535c0da18p-4L }, + { 0x1.7627671657573188p-68L, 0x1.0357feda17430d52p-68L, 0x1.0357feda17430d54p-68L }, + { -0x1.80b4a26e54c41986p-136L, -0x1.0aa858c341e9388ep-136L, -0x1.0aa858c341e9388cp-136L }, + { 0xf.52d7c0f49c1b5a4p-4L, 0xf.136f9f9fa392aa3p-4L, 0xf.136f9f9fa392aa4p-4L }, + { -0xd.90fb86e4d60004ep-4L, -0x7.1c4914f985d3d1c8p-4L, -0x7.1c4914f985d3d1cp-4L }, + { 0x1.5c0865fc4e06a84ep-4L, 0xf.87bc506c0360beap-8L, 0xf.87bc506c0360bebp-8L }, + { -0xa.2dfc5d1f96be4bcp-4L, -0x5.b4a92468e23a59ep-4L, -0x5.b4a92468e23a59d8p-4L }, + { 0xf.d25ff3331838e0ap-4L, 0xf.c0fe5c5501df211p-4L, 0xf.c0fe5c5501df212p-4L }, + { -0xe.e893761d9d926b2p-4L, -0x7.9cd539ff83893758p-4L, -0x7.9cd539ff8389375p-4L }, + { 0x5.03f2d9b66abed898p-4L, 0x3.e20cb7d716acf19cp-4L, 0x3.e20cb7d716acf1ap-4L }, + { -0xd.e1d2b8730f8408fp-4L, -0x7.3b34b6801908a2d8p-4L, -0x7.3b34b6801908a2dp-4L }, + { 0x3.8052f809aaac9b64p-4L, 0x2.9ee0e2805679d1e8p-4L, 0x2.9ee0e2805679d1ecp-4L }, + { -0xf.ad374726f5b37c2p-4L, -0x7.e31b793e91a5aa08p-4L, -0x7.e31b793e91a5aap-4L }, + { 0x3.48836233e960d588p-4L, 0x2.7211ad27a4176778p-4L, 0x2.7211ad27a417677cp-4L }, + { -0x8.af10e3af7480717p-4L, -0x5.043cabb9514315b8p-4L, -0x5.043cabb9514315bp-4L }, + { 0x2.684f23a780f8d16cp-4L, 0x1.c243ddcaf1137a7ap-4L, 0x1.c243ddcaf1137a7cp-4L }, + { -0x2.956954f33db8ba84p-4L, -0x1.b1bac7e767d6e47p-4L, -0x1.b1bac7e767d6e46ep-4L }, + { 0xe.05c36356f1cc00bp-4L, 0xd.5f6d58c69cd39e4p-4L, 0xd.5f6d58c69cd39e5p-4L }, + { -0x9.851c7f17e3779ebp-4L, -0x5.68430d8fcaf782c8p-4L, -0x5.68430d8fcaf782cp-4L }, + { 0x8.98fecd06210c28ep-8L, 0x6.07827af96e4199d8p-8L, 0x6.07827af96e4199ep-8L }, + { -0xa.944a9ff08e89db6p-4L, -0x5.e1e49752fc61a1f8p-4L, -0x5.e1e49752fc61a1fp-4L }, + { 0xf.069ae41b6f97acbp-4L, 0xe.ad7594fe8b4b59ap-4L, 0xe.ad7594fe8b4b59bp-4L }, + { -0x2.849c2bec428d3088p-4L, -0x1.a74d58f4fabdbfecp-4L, -0x1.a74d58f4fabdbfeap-4L }, + { 0x7.77014ff302ca7f18p-132L, 0x5.2c9b99c7adcd1158p-132L, 0x5.2c9b99c7adcd116p-132L }, + { -0xe.aa11ca5025d7161p-8L, -0x9.f724056ca1ff3ffp-8L, -0x9.f724056ca1ff3fep-8L }, + { 0xe.30a7bdb7d22b3c9p-4L, 0xd.96346f655e1888ep-4L, 0xd.96346f655e1888fp-4L }, + { -0xd.1710819efb6a90bp-4L, -0x6.ecd8990f76e583d8p-4L, -0x6.ecd8990f76e583dp-4L }, + { 0xc.289ab032c02ec2bp-8L, 0x8.91661f345b3b24ap-8L, 0x8.91661f345b3b24bp-8L }, + { -0x9.3c743e33f50fbe3p-8L, -0x6.52977132d3793028p-8L, -0x6.52977132d379302p-8L }, + { 0xc.b983cae10f7203p-4L, 0xb.c45064517003de9p-4L, 0xb.c45064517003deap-4L }, + { -0xb.7422dd3d2b45dc5p-4L, -0x6.422bf2df07d21bc8p-4L, -0x6.422bf2df07d21bcp-4L }, + { 0xa.fbaa8d616ab8d1dp-4L, 0x9.bfbb7af27216907p-4L, 0x9.bfbb7af27216908p-4L }, + { -0xe.926ef7c0fa60c33p-4L, -0x7.7d4da667730b916p-4L, -0x7.7d4da667730b9158p-4L }, + { 0xf.80c7c99d2c6404cp-4L, 0xf.518567961cfcee4p-4L, 0xf.518567961cfcee5p-4L }, + { -0x3.9556369534624858p-8L, -0x2.78c655fc919c92b8p-8L, -0x2.78c655fc919c92b4p-8L }, + { 0xe.80d9a3a08faf173p-4L, 0xd.fdb1f369b283091p-4L, 0xd.fdb1f369b283092p-4L }, + { -0x8.400e8efd60a398p-4L, -0x4.ceeacdda92f4d4f8p-4L, -0x4.ceeacdda92f4d4fp-4L }, + { 0x1.e30b1be4461dcf88p-4L, 0x1.5ce2ab3afe2480fcp-4L, 0x1.5ce2ab3afe2480fep-4L }, + { -0xc.2454aa891f5dba1p-4L, -0x6.8b6e7833d8a9115p-4L, -0x6.8b6e7833d8a91148p-4L }, + { 0x2.c925c1f452e23ebp-4L, 0x2.0d617fc9f8513ef4p-4L, 0x2.0d617fc9f8513ef8p-4L }, + { -0x3.a0caae204aa84214p-4L, -0x2.53bec8ebfa7cc494p-4L, -0x2.53bec8ebfa7cc49p-4L }, + { 0x6.db2d4dd8afa84408p-4L, 0x5.88928d8e125932e8p-4L, 0x5.88928d8e125932fp-4L }, + { -0x8.7fd39596a804d49p-4L, -0x4.edab5a4106ecd58p-4L, -0x4.edab5a4106ecd578p-4L }, + { 0xf.c5af0e065f2eb13p-4L, 0xf.af8ddf3950b244p-4L, 0xf.af8ddf3950b2441p-4L }, + { -0x5.9541e8c20a3e7eep-4L, -0x3.6ffb2642f78d6758p-4L, -0x3.6ffb2642f78d6754p-4L }, + { 0x2.b8baba6727f5d1ep-24L, 0x1.e2efa10b181a1d0cp-24L, 0x1.e2efa10b181a1d0ep-24L }, + { -0x8.db8aa5ad53966d6p-64L, -0x6.23bd7497280c936p-64L, -0x6.23bd7497280c9358p-64L }, + { 0xc.2a19196663e14b4p-4L, 0xb.19dfa4b37a6fc82p-4L, 0xb.19dfa4b37a6fc83p-4L }, + { -0x5.0fb02f7662c3e03p-4L, -0x3.2675eb61e2d86868p-4L, -0x3.2675eb61e2d86864p-4L }, + { 0x6.883e7a1d34914268p-4L, 0x5.3bbf577ebbb3a6e8p-4L, 0x5.3bbf577ebbb3a6fp-4L }, + { -0xb.88a85700deb5549p-4L, -0x6.4ad12b9dbb86aa58p-4L, -0x6.4ad12b9dbb86aa5p-4L }, + { 0xf.2b2a3a311948993p-4L, 0xe.de32bdbd5328a8bp-4L, 0xe.de32bdbd5328a8cp-4L }, + { -0x3.06fe2a10fe55267cp-4L, -0x1.f7730b164f7095cap-4L, -0x1.f7730b164f7095c8p-4L }, + { 0xd.de264368cd7459ap-4L, 0xd.2d302551f4723e2p-4L, 0xd.2d302551f4723e3p-4L }, + { -0x5.567777c9aa2124c8p-4L, -0x3.4da047a5e9ef6524p-4L, -0x3.4da047a5e9ef652p-4L }, + { 0x1.935a9217a5a3024p-4L, 0x1.2158a4e7876f331ep-4L, 0x1.2158a4e7876f332p-4L }, + { -0x7.3ccc7fe1d42ad228p-4L, -0x4.4e6b4b167987ff4p-4L, -0x4.4e6b4b167987ff38p-4L }, + { 0x4.bbff6d1fef17b4c8p-4L, 0x3.a4730f28cbe2fbf4p-4L, 0x3.a4730f28cbe2fbf8p-4L }, + { -0x2.826940b5855fb4cp-4L, -0x1.a5ef6bae7291935p-4L, -0x1.a5ef6bae7291934ep-4L }, + { 0x5.265fe49d84076a68p-4L, 0x3.ffca2018e001a9f4p-4L, 0x3.ffca2018e001a9f8p-4L }, + { -0xc.103986b2d38539dp-4L, -0x6.832e7fadd55aecp-4L, -0x6.832e7fadd55aebf8p-4L }, + { 0x1.70101c108d2f0d0ep-4L, 0x1.073c0b1e50c5d204p-4L, 0x1.073c0b1e50c5d206p-4L }, + { -0x2.66bb0943c921a184p-4L, -0x1.94af43fe62d2cf1ap-4L, -0x1.94af43fe62d2cf18p-4L }, + { 0x7.5a723c24f0c64ebp-4L, 0x6.0095e4fad124e338p-4L, 0x6.0095e4fad124e34p-4L }, + { -0x3.c761bdd9cf2def2cp-4L, -0x2.6a876738e18b6208p-4L, -0x2.6a876738e18b6204p-4L }, + { 0x3.e7acf294cc0ca23cp-8L, 0x2.b89933565f7ae4f4p-8L, 0x2.b89933565f7ae4f8p-8L }, + { -0x7.3c061c9452915b98p-4L, -0x4.4e06c9112a70ca8p-4L, -0x4.4e06c9112a70ca78p-4L }, + { 0x3.0efe779ab69c208p-72L, 0x2.1ebae7521123e438p-72L, 0x2.1ebae7521123e43cp-72L }, + { -0x6.90517ba54103e7cp-172L, -0x4.8cb53818436922b8p-172L, -0x4.8cb53818436922bp-172L }, + { 0xb.dde4e379662aeeap-4L, 0xa.c0facbdff63e577p-4L, 0xa.c0facbdff63e578p-4L }, + { -0xb.0226291c9bc5964p-4L, -0x6.1199984540184bp-4L, -0x6.1199984540184af8p-4L }, + { 0xd.bf9a0da9faa3504p-4L, 0xd.06ad1755cc71cafp-4L, 0xd.06ad1755cc71cbp-4L }, + { -0x5.c1892b0fafe1dc68p-4L, -0x3.87fd1b244474f46p-4L, -0x3.87fd1b244474f45cp-4L }, + { 0x1.44812a3159648466p-4L, 0xe.7384fa316de3657p-8L, 0xe.7384fa316de3658p-8L }, + { -0x3.675c755eb8dbe27cp-4L, -0x2.318fbbc51015422p-4L, -0x2.318fbbc51015421cp-4L }, + { 0x1.e8e8f49835eaacb8p-4L, 0x1.614ce65fa1a17274p-4L, 0x1.614ce65fa1a17276p-4L }, + { -0x9.eac5efdf2c187bdp-4L, -0x5.9683d9aacedb09d8p-4L, -0x5.9683d9aacedb09dp-4L }, + { 0xf.8a9cd502481f327p-4L, 0xf.5edf4b01d85e97fp-4L, 0xf.5edf4b01d85e98p-4L }, + { -0x2.9371a4cdcbd8ac4p-4L, -0x1.b0829193db9b2a82p-4L, -0x1.b0829193db9b2a8p-4L }, + { 0xf.ec9e23f6d0a3bd2p-4L, 0xf.e52cabad2944b2dp-4L, 0xf.e52cabad2944b2ep-4L }, + { -0x4.bfabe9c4786421c8p-4L, -0x2.f99d50346680f5e4p-4L, -0x2.f99d50346680f5ep-4L }, + { 0x6.028525d3aafe4428p-4L, 0x4.c21ee15b144d29a8p-4L, 0x4.c21ee15b144d29bp-4L }, + { -0x4.c2d0568402546a5p-8L, -0x3.47653cfe61fb05p-8L, -0x3.47653cfe61fb04fcp-8L }, + { 0xc.976222dd345048p-4L, 0xb.9b60191b6b95aecp-4L, 0xb.9b60191b6b95aedp-4L }, + { -0xd.6563e961e96fd5dp-4L, -0x7.0b6f86cbdfafbe78p-4L, -0x7.0b6f86cbdfafbe7p-4L }, + { 0x9.e03ff635ae5b0afp-4L, 0x8.8b0bdb10fd8a85fp-4L, 0x8.8b0bdb10fd8a86p-4L }, + { -0xa.42b9f1752ebee14p-4L, -0x5.bde4e29a894df518p-4L, -0x5.bde4e29a894df51p-4L }, + { 0x6.4ef2060125bf954p-4L, 0x5.074b877b025a5c38p-4L, 0x5.074b877b025a5c4p-4L }, + { -0xc.a4d9e356caf3a4ap-4L, -0x6.bf8205df1ee0d508p-4L, -0x6.bf8205df1ee0d5p-4L }, + { 0x7.e842fb7dd3d50cap-196L, 0x5.7b1c7b3b95bed698p-196L, 0x5.7b1c7b3b95bed6ap-196L }, + { -0x1.31f41258f7c01eccp-60L, -0xd.4121c04c9ce13acp-64L, -0xd.4121c04c9ce13abp-64L }, + { 0x2.29f54bce824a24cp-8L, 0x1.811a02ec67bf37aep-8L, 0x1.811a02ec67bf37bp-8L }, + { -0xa.b8f81b679b49916p-4L, -0x5.f1eb5dee53695e5p-4L, -0x5.f1eb5dee53695e48p-4L }, + { 0x2.dfa40c215498cf14p-4L, 0x2.1f01613fffbe7cfcp-4L, 0x2.1f01613fffbe7dp-4L }, + { -0x2.ec02031137509e54p-4L, -0x1.e7019f7577e0055ap-4L, -0x1.e7019f7577e00558p-4L }, + { 0xc.95b28af67c0d0fdp-4L, 0xb.995bfeb5a18fb19p-4L, 0xb.995bfeb5a18fb1ap-4L }, + { -0x3.8b937ee4a5ad9044p-4L, -0x2.4727f0551eb47668p-4L, -0x2.4727f0551eb47664p-4L }, + { 0xc.b61f96c1b9a40fep-8L, 0x8.f6d9fa1cd76287dp-8L, 0x8.f6d9fa1cd76287ep-8L }, + { -0x5.32ac5f2f72c534e8p-4L, -0x3.39e0dcc0490bcf08p-4L, -0x3.39e0dcc0490bcf04p-4L }, + { 0x3.71a836d1385ea83cp-4L, 0x2.930fc44d7c9f0878p-4L, 0x2.930fc44d7c9f087cp-4L }, + { -0x2.98de885b63ec9fap-4L, -0x1.b3df390ab96ff674p-4L, -0x1.b3df390ab96ff672p-4L }, + { 0x2.ec64d50f08792a24p-4L, 0x2.290720411b492388p-4L, 0x2.290720411b49238cp-4L }, + { -0x7.4a3ef749c24694d8p-4L, -0x4.55393aafd5f18ddp-4L, -0x4.55393aafd5f18dc8p-4L }, + { 0x1.c73a886f525db7c4p-4L, 0x1.48033f1818ec4274p-4L, 0x1.48033f1818ec4276p-4L }, + { -0x7.e597e9edb98f8dd8p-4L, -0x4.a2b8122945a3a86p-4L, -0x4.a2b8122945a3a858p-4L }, + { 0x5.b2db0149e01e772p-4L, 0x4.7af5d27da276247p-4L, 0x4.7af5d27da2762478p-4L }, + { -0xa.4e00c5865119715p-4L, -0x5.c2e6944e696561dp-4L, -0x5.c2e6944e696561c8p-4L }, + { 0x3.2d5ce470bbbfc05p-4L, 0x2.5c6c520e75d5dcfp-4L, 0x2.5c6c520e75d5dcf4p-4L }, + { -0x6.fef503b2cde63e88p-4L, -0x4.2eed1c50abe4d0fp-4L, -0x4.2eed1c50abe4d0e8p-4L }, + { 0x9.d7135271cf1adc5p-8L, 0x6.e98f0ad0c8f784bp-8L, 0x6.e98f0ad0c8f784b8p-8L }, + { -0x1.37a6e3f9da2ebc3ap-4L, -0xd.26c4f046ca71bc4p-8L, -0xd.26c4f046ca71bc3p-8L }, + { 0xe.f91909cb851832p-16L, 0xa.611c7fdf8ec95cap-16L, 0xa.611c7fdf8ec95cbp-16L }, + { -0x1.8aec185a037005eap-44L, -0x1.11bd3ef298133bf6p-44L, -0x1.11bd3ef298133bf4p-44L }, + { 0x4.58042455b6631c78p-4L, 0x3.5016317376e61d88p-4L, 0x3.5016317376e61d8cp-4L }, + { -0xf.a5425993c2d22edp-4L, -0x7.e04f162edd1444c8p-4L, -0x7.e04f162edd1444cp-4L }, + { 0xc.cc707747b5d9891p-4L, 0xb.db1d6d0a67ba46dp-4L, 0xb.db1d6d0a67ba46ep-4L }, + { -0x5.6352b9b11a14c48p-4L, -0x3.54b0a77bead101c4p-4L, -0x3.54b0a77bead101cp-4L }, + { 0xb.ddfe2e36f24ba09p-4L, 0xa.c1181c4c96d3b16p-4L, 0xa.c1181c4c96d3b17p-4L }, + { -0xf.ff0d58e82429fafp-4L, -0x7.ffabe56fa53e346p-4L, -0x7.ffabe56fa53e3458p-4L }, + { 0x9.bd53e4167e85b42p-4L, 0x8.6606596f18f0c25p-4L, 0x8.6606596f18f0c26p-4L }, + { -0x5.4c28c9b0b345941p-4L, -0x3.47f39e55e7145a5p-4L, -0x3.47f39e55e7145a4cp-4L }, + { 0x8.fef78aad41a1338p-4L, 0x7.a005c2fb7b575668p-4L, 0x7.a005c2fb7b57567p-4L }, + { -0xf.25b2822b10d9f65p-4L, -0x7.b2ed5c3922a4e83p-4L, -0x7.b2ed5c3922a4e828p-4L }, + { 0x5.cd10c03bcaf10088p-8L, 0x4.0d7eda5d78333cc8p-8L, 0x4.0d7eda5d78333cdp-8L }, + { -0xa.a821812c5f53b52p-4L, -0x5.ea92fddd766193d8p-4L, -0x5.ea92fddd766193dp-4L }, + { 0x5.94e05ec04235ac68p-4L, 0x4.606dcea9678b422p-4L, 0x4.606dcea9678b4228p-4L }, + { -0x5.04ba966a5474e0e8p-4L, -0x3.205aab0b1a291c5cp-4L, -0x3.205aab0b1a291c58p-4L }, + { 0xd.167af1356c9c025p-4L, 0xc.3506efb6e7f748dp-4L, 0xc.3506efb6e7f748ep-4L }, + { -0xf.d0cd204dbb8b533p-4L, -0x7.ef93a0736368116p-4L, -0x7.ef93a07363681158p-4L }, + { 0xa.c0e5742f317f8a3p-4L, 0x9.7e80068401fa255p-4L, 0x9.7e80068401fa256p-4L }, + { -0xe.2242314d427e9c1p-4L, -0x7.538ce8c2b95acc28p-4L, -0x7.538ce8c2b95acc2p-4L }, + { 0x2.37749e13337ef694p-4L, 0x1.9cd5b81ee0f49f52p-4L, 0x1.9cd5b81ee0f49f54p-4L }, + { -0x4.8513915f54085e2p-4L, -0x2.d86313394f7dfa98p-4L, -0x2.d86313394f7dfa94p-4L }, + { 0x7.11d091eb6c5e7f8p-32L, 0x4.e677cd427aff876p-32L, 0x4.e677cd427aff8768p-32L }, + { -0x2.92d0f5e17e14f8ep-176L, -0x1.c8a818bcf03dad22p-176L, -0x1.c8a818bcf03dad2p-176L }, + { 0x9.19d2bf8e626ce94p-4L, 0x7.bb9267aaaf8d16f8p-4L, 0x7.bb9267aaaf8d17p-4L }, + { -0x5.78fee31b1243e6ep-4L, -0x3.6090300d6de230a8p-4L, -0x3.6090300d6de230a4p-4L }, + { 0xe.920450e2df4f23ep-4L, 0xe.14081596bb730e3p-4L, 0xe.14081596bb730e4p-4L }, + { -0x7.8a913f4c29492cdp-4L, -0x4.758ec9da15257a08p-4L, -0x4.758ec9da15257ap-4L }, + { 0xd.f18c68c5e57c1fep-4L, 0xd.45bf8cfdf37d1c1p-4L, 0xd.45bf8cfdf37d1c2p-4L }, + { -0xc.97ed4020a652183p-4L, -0x6.ba5270a397bd198p-4L, -0x6.ba5270a397bd1978p-4L }, + { 0x6.b2da8740f690432p-4L, 0x5.63158e0eca286c4p-4L, 0x5.63158e0eca286c48p-4L }, + { -0x8.d86e55e3f0a94b1p-4L, -0x5.17d9c3b44828322p-4L, -0x5.17d9c3b448283218p-4L }, + { 0x5.0308adabc4a020fp-4L, 0x3.e14306a78e1170ccp-4L, 0x3.e14306a78e1170dp-4L }, + { -0x2.a7d9b961e2c3089p-4L, -0x1.bd23ae2c81af213p-4L, -0x1.bd23ae2c81af212ep-4L }, + { 0xd.227d8e4d09d7251p-4L, 0xc.43b7e073dd24255p-4L, 0xc.43b7e073dd24256p-4L }, + { -0x7.d5608278690935ap-4L, -0x4.9ab96d634d10f6a8p-4L, -0x4.9ab96d634d10f6ap-4L }, + { 0xe.81b27c03c76f499p-4L, 0xd.fecbb5a87bddaadp-4L, 0xd.fecbb5a87bddaaep-4L }, + { -0x2.b154c8162bc04cb4p-4L, -0x1.c2fdf56982dfaa86p-4L, -0x1.c2fdf56982dfaa84p-4L }, + { 0x4.35ecdac82f2a93c8p-4L, 0x3.33a5663cd3ec757cp-4L, 0x3.33a5663cd3ec758p-4L }, + { -0x5.771325ed71c201dp-4L, -0x3.5f833dab5799d678p-4L, -0x3.5f833dab5799d674p-4L }, + { 0xb.d5c2b3ad8490192p-4L, 0xa.b78f2869f7f0d2fp-4L, 0xa.b78f2869f7f0d3p-4L }, + { -0x5.121392f3a25f68p-4L, -0x3.27ca31d087184188p-4L, -0x3.27ca31d087184184p-4L }, + { 0x7.b9734cb7e88bd598p-4L, 0x6.5bdf83f80e502428p-4L, 0x6.5bdf83f80e50243p-4L }, + { -0x1.778ccedfa82f4736p-4L, -0xf.c36523958ccb66dp-8L, -0xf.c36523958ccb66cp-8L }, + { 0x5.9e61f2660d92e2bp-24L, 0x3.e502ce773052c2ep-24L, 0x3.e502ce773052c2e4p-24L }, + { -0xc.ed5cdd95e040dd5p-124L, -0x8.f5e01e66418fdc9p-124L, -0x8.f5e01e66418fdc8p-124L }, + { 0xe.22ec92ad54501adp-4L, 0xd.84a01b636eef0b3p-4L, 0xd.84a01b636eef0b4p-4L }, + { -0x7.ec2bfe55bde275dp-4L, -0x4.a5f4b909907e0218p-4L, -0x4.a5f4b909907e021p-4L }, + { 0xf.d304d6628c01f2ap-4L, 0xf.c1e1328eafdd3bfp-4L, 0xf.c1e1328eafdd3cp-4L }, + { -0x9.352c83f42a1922fp-4L, -0x5.43546e87e016ee88p-4L, -0x5.43546e87e016ee8p-4L }, + { 0x7.4cdb36f2473c8acp-4L, 0x5.f3a5959c53f3ceb8p-4L, 0x5.f3a5959c53f3cecp-4L }, + { -0x1.70792a73178fa0fap-4L, -0xf.79b33e5d77df4c1p-8L, -0xf.79b33e5d77df4cp-8L }, + { 0x5.1ce62b8e10774afp-4L, 0x3.f7962ac86af2f5ecp-4L, 0x3.f7962ac86af2f5fp-4L }, + { -0x7.fa8931ceaf326ac8p-4L, -0x4.ad02e3351c74545p-4L, -0x4.ad02e3351c745448p-4L }, + { 0xb.369caaaa169ce0fp-4L, 0xa.01d090312957af1p-4L, 0xa.01d090312957af2p-4L }, + { -0xa.954d79680ea5909p-4L, -0x5.e25609c7a753185p-4L, -0x5.e25609c7a7531848p-4L }, + { 0xb.432563e5c37e78fp-4L, 0xa.0ff3939e94e53c8p-4L, 0xa.0ff3939e94e53c9p-4L }, + { -0xa.950b0bb7d84c5b3p-4L, -0x5.e238ed18b7fab0bp-4L, -0x5.e238ed18b7fab0a8p-4L }, + { 0x4.3e136fbe7e156658p-4L, 0x3.3a6e53129453d0d4p-4L, 0x3.3a6e53129453d0d8p-4L }, + { -0xb.9930789b19cf8a8p-4L, -0x6.51c2880aa5aa9ff8p-4L, -0x6.51c2880aa5aa9ffp-4L }, + { 0x8.1697784edf6fe07p-8L, 0x5.ab0e426210147018p-8L, 0x5.ab0e42621014702p-8L }, + { -0x2.e9849ddc62c0d374p-4L, -0x1.e57c4324b108422ep-4L, -0x1.e57c4324b108422cp-4L }, + { 0xc.d570e244c0e60bep-4L, 0xb.e5fc70032574c78p-4L, 0xb.e5fc70032574c79p-4L }, + { -0xf.15d04c531718d34p-4L, -0x7.ad351e2ce95c1f88p-4L, -0x7.ad351e2ce95c1f8p-4L }, + { 0x1.e1200b8406eda8fep-4L, 0x1.5b715b4dfb18883p-4L, 0x1.5b715b4dfb188832p-4L }, + { -0x7.995991a529314d5p-4L, -0x4.7cf0755dd5eca728p-4L, -0x4.7cf0755dd5eca72p-4L }, + { 0x9.2cb86254ecdfd09p-192L, 0x6.5c0241febd46c9cp-192L, 0x6.5c0241febd46c9c8p-192L }, + { -0x2.4cc15f58d07c3b1cp-140L, -0x1.981818282e5dbca4p-140L, -0x1.981818282e5dbca2p-140L }, + { 0x3.9173123187f70484p-4L, 0x2.acb691682f6030d4p-4L, 0x2.acb691682f6030d8p-4L }, + { -0x4.e07d3709dbe3fep-4L, -0x3.0c14b7174878c9ecp-4L, -0x3.0c14b7174878c9e8p-4L }, + { 0x5.653d42dac0a5219p-4L, 0x4.368bd2c07053e5ep-4L, 0x4.368bd2c07053e5e8p-4L }, + { -0x9.5f1aff673a041bcp-4L, -0x5.56c3d8c108a0611p-4L, -0x5.56c3d8c108a06108p-4L }, + { 0x8.bcd403a004e1a23p-4L, 0x7.5cb550c524697b8p-4L, 0x7.5cb550c524697b88p-4L }, + { -0x8.1c9d05645c7987cp-4L, -0x4.bdae53d810a91ac8p-4L, -0x4.bdae53d810a91acp-4L }, + { 0xd.13a5ae9285d253dp-4L, 0xc.3190e4f8d4d5582p-4L, 0xc.3190e4f8d4d5583p-4L }, + { -0x9.4cf62e7e77f656p-4L, -0x5.4e5f50857e68f51p-4L, -0x5.4e5f50857e68f508p-4L }, + { 0x2.84d9c1bc69548254p-4L, 0x1.d846c310aa00c054p-4L, 0x1.d846c310aa00c056p-4L }, + { -0x4.21ac0c75a3a7dbe8p-4L, -0x2.9f423cc607a168dcp-4L, -0x2.9f423cc607a168d8p-4L }, + { 0xd.b9bd68e165f831p-4L, 0xc.ff4f076046a69dp-4L, 0xc.ff4f076046a69d1p-4L }, + { -0x8.3fd61ad578cd929p-4L, -0x4.cecf6eabd87b7c9p-4L, -0x4.cecf6eabd87b7c88p-4L }, + { 0xf.30d46d764112444p-4L, 0xe.e5c6f47afffabf2p-4L, 0xe.e5c6f47afffabf3p-4L }, + { -0xb.cd4a73dc359d737p-4L, -0x6.6783a45e4e8dae2p-4L, -0x6.6783a45e4e8dae18p-4L }, + { 0x5.457d60a9148a985p-4L, 0x4.1ad19bfee71e48dp-4L, 0x4.1ad19bfee71e48d8p-4L }, + { -0x5.9e1738c1ccd8a9a8p-4L, -0x3.74c8e8a92c7f7b74p-4L, -0x3.74c8e8a92c7f7b7p-4L }, + { 0x1.497ab915f40b4518p-4L, 0xe.add4c95fb682b23p-8L, 0xe.add4c95fb682b24p-8L }, + { -0x4.8e012f7d7878b01p-4L, -0x2.dd78a1d7e408573cp-4L, -0x2.dd78a1d7e4085738p-4L }, + { 0x5.9d5fb6a6e532323p-4L, 0x4.67ef7a4d5b079348p-4L, 0x4.67ef7a4d5b07935p-4L }, + { -0x7.bc4dc1a54a48fdbp-4L, -0x4.8e51e755a24d00f8p-4L, -0x4.8e51e755a24d00fp-4L }, + { 0x3.fc5a846dfbec9adp-200L, 0x2.c3415566e5a54668p-200L, 0x2.c3415566e5a5466cp-200L }, + { -0x7.6980774d9eb5024p-128L, -0x5.233f7f59341a9e7p-128L, -0x5.233f7f59341a9e68p-128L }, + { 0xc.52f873b5b0d54efp-8L, 0x8.afc12e42adf7bacp-8L, 0x8.afc12e42adf7badp-8L }, + { -0x2.b8137644250c4bbcp-4L, -0x1.c7266a67c6352a0ap-4L, -0x1.c7266a67c6352a08p-4L }, + { 0x8.b13bd917a919d6p-4L, 0x7.50fc3760355aaba8p-4L, 0x7.50fc3760355aabbp-4L }, + { -0xd.a7e60f2da06694ep-4L, -0x7.2517f5997441288p-4L, -0x7.2517f59974412878p-4L }, + { 0x9.6d66afe84b35074p-4L, 0x8.121cbf603f1eb03p-4L, 0x8.121cbf603f1eb04p-4L }, + { -0x8.d45410dc1895ef4p-4L, -0x5.15e9564a5d57b1d8p-4L, -0x5.15e9564a5d57b1dp-4L }, + { 0x8.7112de739485f11p-4L, 0x7.108706705b67e1bp-4L, 0x7.108706705b67e1b8p-4L }, + { -0x5.28bf133fa6f14d3p-4L, -0x3.34615bbf1f08718cp-4L, -0x3.34615bbf1f087188p-4L }, + { 0x5.9ce42450cfaf8ee8p-4L, 0x4.67823dfabf51ea3p-4L, 0x4.67823dfabf51ea38p-4L }, + { -0x6.efb719daf136a1cp-4L, -0x4.271d11505413f6b8p-4L, -0x4.271d11505413f6bp-4L }, + { 0x9.ba0bd38df957e82p-8L, 0x6.d4e5a59f2ab3464p-8L, 0x6.d4e5a59f2ab34648p-8L }, + { -0x7.f37ea4723b67675p-4L, -0x4.a98e0f5848567a48p-4L, -0x4.a98e0f5848567a4p-4L }, + { 0x2.bf5897672b745798p-4L, 0x2.05b8d1dd696925cp-4L, 0x2.05b8d1dd696925c4p-4L }, + { -0x1.2b46b769cd53c99cp-4L, -0xc.a46ee1aa5cf6e29p-8L, -0xc.a46ee1aa5cf6e28p-8L }, + { 0x8.0d256afefef3c89p-4L, 0x6.ad850d0f71e9f0fp-4L, 0x6.ad850d0f71e9f0f8p-4L }, + { -0xa.e23fca6db43882fp-4L, -0x6.03d69b4a9fcb498p-4L, -0x6.03d69b4a9fcb4978p-4L }, + { 0x3.5d7f19c9107b35a4p-4L, 0x2.82ddd03061b78d4p-4L, 0x2.82ddd03061b78d44p-4L }, + { -0x4.0740585229be331p-4L, -0x2.8fe9890e66210b8p-4L, -0x2.8fe9890e66210b7cp-4L }, + { 0xb.2f2372351c33164p-8L, 0x7.deee40d7b054f0a8p-8L, 0x7.deee40d7b054f0bp-8L }, + { -0x1.e98b74b783fe8242p-4L, -0x1.45a6bc169044944ep-4L, -0x1.45a6bc169044944cp-4L }, + { 0x1.ef271536f1acac7cp-116L, 0x1.5736b36e46fd9e2p-116L, 0x1.5736b36e46fd9e22p-116L }, + { -0x2.f2b30898a501e344p-172L, -0x2.0b1e2354091a9a9p-172L, -0x2.0b1e2354091a9a8cp-172L }, + { 0xc.de09271a73942cap-4L, 0xb.f061a10e47f19afp-4L, 0xb.f061a10e47f19bp-4L }, + { -0xd.1fe6e25acc0107ap-4L, -0x6.f0515b52d3bc8b1p-4L, -0x6.f0515b52d3bc8b08p-4L }, + { 0x5.379d21e155802d5p-8L, 0x3.a458c1e822fc87b8p-8L, 0x3.a458c1e822fc87bcp-8L }, + { -0x7.f34a81711f9595fp-4L, -0x4.a974739e5e3c1ecp-4L, -0x4.a974739e5e3c1eb8p-4L }, + { 0x9.8f02fd2b4d10383p-4L, 0x8.3542c1ae328d562p-4L, 0x8.3542c1ae328d563p-4L }, + { -0x3.10d386b4ddaa9bccp-4L, -0x1.fd6c33e550a573ep-4L, -0x1.fd6c33e550a573dep-4L }, + { 0x8.a7f4a483fcced92p-4L, 0x7.479ee5100ad2768p-4L, 0x7.479ee5100ad27688p-4L }, + { -0x8.6ddd524df76f7bdp-4L, -0x4.e50a7bb2dd656468p-4L, -0x4.e50a7bb2dd65646p-4L }, + { 0xc.779757b60637763p-4L, 0xb.757468127d65f88p-4L, 0xb.757468127d65f89p-4L }, + { -0xe.777fe73bf0e9a48p-4L, -0x7.7359b3768a34b5c8p-4L, -0x7.7359b3768a34b5cp-4L }, + { 0x2.31b8036de80e551p-4L, 0x1.9875b4516816bbbep-4L, 0x1.9875b4516816bbcp-4L }, + { -0x9.0b16723fd236994p-4L, -0x5.2faf0a9074dea98p-4L, -0x5.2faf0a9074dea978p-4L }, + { 0x8.9a19522584fca8fp-4L, 0x7.39a98b528df1ef3p-4L, 0x7.39a98b528df1ef38p-4L }, + { -0xf.5402328fd9d6fdfp-4L, -0x7.c38432212a78edbp-4L, -0x7.c38432212a78eda8p-4L }, + { 0x3.39b72eedc5fb39acp-4L, 0x2.664255df780701c4p-4L, 0x2.664255df780701c8p-4L }, + { -0xc.d7d4b25d5ee54a4p-4L, -0x6.d3da67d23282e35p-4L, -0x6.d3da67d23282e348p-4L }, + { 0xf.002b8779c597ceep-4L, 0xe.a4e96c0af56d93ap-4L, 0xe.a4e96c0af56d93bp-4L }, + { -0x7.903eb3c7555e4358p-4L, -0x4.78651e55fe9e325p-4L, -0x4.78651e55fe9e3248p-4L }, + { 0x2.90b7822bc63776fcp-4L, 0x1.e17582d5a09ed40ap-4L, 0x1.e17582d5a09ed40cp-4L }, + { -0xb.887e64736056822p-4L, -0x6.4abf8763ec5ac7ep-4L, -0x6.4abf8763ec5ac7d8p-4L }, + { 0x1.4b3a350eb68541aep-20L, 0xe.596e40ce64dcf5ap-24L, 0xe.596e40ce64dcf5bp-24L }, + { -0x1.aef913a565a8bc1ap-128L, -0x1.2aba49d9af3d613p-128L, -0x1.2aba49d9af3d612ep-128L }, + { 0xc.8b02c285d275bd6p-4L, 0xb.8c97f1c3166348p-4L, 0xb.8c97f1c31663481p-4L }, + { -0x7.2ea947c351044f48p-4L, -0x4.473fa3759df5825p-4L, -0x4.473fa3759df58248p-4L }, + { 0xc.4830d91b64528bdp-4L, 0xb.3d4b68c0a1c1452p-4L, 0xb.3d4b68c0a1c1453p-4L }, + { -0xa.faff5d48675db64p-4L, -0x6.0e8570512dea4ae8p-4L, -0x6.0e8570512dea4aep-4L }, + { 0x1.456f46c72593c416p-4L, 0xe.7e6b02981c8b075p-8L, 0xe.7e6b02981c8b076p-8L }, + { -0x2.cdc53dd42a6cdf4cp-4L, -0x1.d47df5d7bd63c49ep-4L, -0x1.d47df5d7bd63c49cp-4L }, + { 0xd.de830895fc14d25p-4L, 0xd.2da568a29ea15dp-4L, 0xd.2da568a29ea15d1p-4L }, + { -0x1.d696938384c107e8p-4L, -0x1.39897019921dfe5ap-4L, -0x1.39897019921dfe58p-4L }, + { 0x3.5cde202fff810fdp-4L, 0x2.825cba775f96e8d4p-4L, 0x2.825cba775f96e8d8p-4L }, + { -0xb.0173bf64b3af081p-4L, -0x6.114cd4839031f808p-4L, -0x6.114cd4839031f8p-4L }, + { 0x9.ae157e1a5d07d3dp-4L, 0x8.55eee27b4bf2689p-4L, 0x8.55eee27b4bf268ap-4L }, + { -0x4.bded6e2f0ae69668p-4L, -0x2.f8a157b29a4320f8p-4L, -0x2.f8a157b29a4320f4p-4L }, + { 0xb.7b9077a770021aep-4L, 0xa.4ff4d2970ce8214p-4L, 0xa.4ff4d2970ce8215p-4L }, + { -0xe.794bdddad00436cp-4L, -0x7.740408ba771c01d8p-4L, -0x7.740408ba771c01dp-4L }, + { 0x8.bcfd1861de45b01p-4L, 0x7.5cdee4cb7bee481p-4L, 0x7.5cdee4cb7bee4818p-4L }, + { -0xa.ab4ea1951712b09p-4L, -0x5.ebf61acd701b7f68p-4L, -0x5.ebf61acd701b7f6p-4L }, + { 0x6.f81960839d640cdp-4L, 0x5.a39e8005baae39bp-4L, 0x5.a39e8005baae39b8p-4L }, + { -0x7.693a270061cf9de8p-4L, -0x4.64d777196e594488p-4L, -0x4.64d777196e59448p-4L }, + { 0xe.7b0648fc94495aap-4L, 0xd.f6213f610dcf21ep-4L, 0xd.f6213f610dcf21fp-4L }, + { -0xa.916b419fbe9fc1p-4L, -0x5.e0a2312a38c0e318p-4L, -0x5.e0a2312a38c0e31p-4L }, + { 0x1.89bd813bf1f6a1c2p-92L, 0x1.10eb819b2e242b1ep-92L, 0x1.10eb819b2e242b2p-92L }, + { -0x5.9293af393bd5fbfp-184L, -0x3.dcd3e77adc468a94p-184L, -0x3.dcd3e77adc468a9p-184L }, + { 0xd.3ea27eab88fb691p-4L, 0xc.6643216e56bbfb4p-4L, 0xc.6643216e56bbfb5p-4L }, + { -0xe.5d425700b9dfb9p-4L, -0x7.699c2694c5a2105p-4L, -0x7.699c2694c5a21048p-4L }, + { 0x7.ef30d4f5d43c309p-4L, 0x6.902a2db66b7bda78p-4L, 0x6.902a2db66b7bda8p-4L }, + { -0xc.2cc3adaa5f76bd8p-4L, -0x6.8ee23784f80cfdc8p-4L, -0x6.8ee23784f80cfdcp-4L }, + { 0x2.8b29e4e9b1677aap-4L, 0x1.dd28d0729a15749cp-4L, 0x1.dd28d0729a15749ep-4L }, + { -0xb.c9870bb9c74469p-4L, -0x6.65f306cc38bba318p-4L, -0x6.65f306cc38bba31p-4L }, + { 0x3.9b5a02bfcb72b468p-4L, 0x2.b4bb195f6468ceep-4L, 0x2.b4bb195f6468cee4p-4L }, + { -0x3.fcdc007ba74601ap-4L, -0x2.89db741e09207918p-4L, -0x2.89db741e09207914p-4L }, + { 0xf.8ea939c39a2414cp-8L, 0xb.038978e1848fbcep-8L, 0xb.038978e1848fbcfp-8L }, + { -0xd.38eafd3878fe2f4p-12L, -0x9.279f93a09aef86p-12L, -0x9.279f93a09aef85fp-12L }, + { 0x1.c55b237b57929914p-8L, 0x1.3aff3dbaa1f54462p-8L, 0x1.3aff3dbaa1f54464p-8L }, + { -0xe.5512393a7c3aa68p-4L, -0x7.668fce4e8d41ec3p-4L, -0x7.668fce4e8d41ec28p-4L }, + { 0x6.c72dbae38baf489p-4L, 0x5.75f2be10b3da51p-4L, 0x5.75f2be10b3da5108p-4L }, + { -0xa.9efab67bae298c4p-4L, -0x5.e692c461328f2a38p-4L, -0x5.e692c461328f2a3p-4L }, + { 0x6.d6fe2acf94b44bp-4L, 0x5.84abad9d09e7a7dp-4L, 0x5.84abad9d09e7a7d8p-4L }, + { -0x2.1052fcc75fe78e44p-4L, -0x1.5e50254d52c2cb86p-4L, -0x1.5e50254d52c2cb84p-4L }, + { 0xf.5f7e274f7549127p-4L, 0xf.247c06ed64581d2p-4L, 0xf.247c06ed64581d3p-4L }, + { -0xc.e3f378c5ed3afabp-4L, -0x6.d8aa145971328588p-4L, -0x6.d8aa14597132858p-4L }, + { 0x5.ed5d3988224f9748p-4L, 0x4.af2122809de98b08p-4L, 0x4.af2122809de98b1p-4L }, + { -0x3.ceeb00215e0d28fp-4L, -0x2.6ef600bcd292a928p-4L, -0x2.6ef600bcd292a924p-4L }, + { 0x1.81a67feedc219a8cp-160L, 0x1.0b4ffeb467c6a36cp-160L, 0x1.0b4ffeb467c6a36ep-160L }, + { -0x4.1c590bda30ba606p-76L, -0x2.d96e935fdb4f2c6p-76L, -0x2.d96e935fdb4f2c5cp-76L }, + { 0xc.afcea80015980b8p-4L, 0xb.b8a5752c99ff1d2p-4L, 0xb.b8a5752c99ff1d3p-4L }, + { -0xb.d8b227ae135fe8fp-4L, -0x6.6c4030ee2cb63a3p-4L, -0x6.6c4030ee2cb63a28p-4L }, + { 0x8.dc01d8b49232a17p-4L, 0x7.7c58fa948c1ea33p-4L, 0x7.7c58fa948c1ea338p-4L }, + { -0x1.933e5a044e710e98p-4L, -0x1.0e2f0aea0ed3f88ep-4L, -0x1.0e2f0aea0ed3f88cp-4L }, + { 0x1.a467d39df9435c82p-4L, 0x1.2e04d4c090c9af46p-4L, 0x1.2e04d4c090c9af48p-4L }, + { -0xd.177492196d07a44p-4L, -0x6.ecffef80c3115ef8p-4L, -0x6.ecffef80c3115efp-4L }, + { 0xa.8eb53214a5d4d15p-4L, 0x9.474ddcecd909225p-4L, 0x9.474ddcecd909226p-4L }, + { -0x1.8712ead1e57a5c3cp-4L, -0x1.064bf416745202b8p-4L, -0x1.064bf416745202b6p-4L }, + { 0x8.4de1b5d10a110dbp-4L, 0x6.ed77dcb741f173c8p-4L, 0x6.ed77dcb741f173dp-4L }, + { -0x2.5fb6ddfc66521d98p-4L, -0x1.904c98bb8b81f248p-4L, -0x1.904c98bb8b81f246p-4L }, + { 0x9.4d57927720bce2ap-4L, 0x7.f0c5a855860ee5c8p-4L, 0x7.f0c5a855860ee5dp-4L }, + { -0xd.c24a0c2da437c45p-8L, -0x9.5c8c25cb60521fp-8L, -0x9.5c8c25cb60521efp-8L }, + { 0xe.f5d12aeb5942b6bp-8L, 0xa.951ffb20b4a544dp-8L, 0xa.951ffb20b4a544ep-8L }, + { -0x1.6c160eed113f724cp-8L, -0xf.be148f1adb1e1fp-12L, -0xf.be148f1adb1e1efp-12L }, + { 0xe.5e4d4cc7965edb5p-4L, 0xd.d0f05f423ac4ecp-4L, 0xd.d0f05f423ac4ec1p-4L }, + { -0x9.fc2ec0983ea77b3p-4L, -0x5.9e5b37a59c48991p-4L, -0x5.9e5b37a59c489908p-4L }, + { 0xe.add7dabec19d155p-4L, 0xe.38603c1d1ea2234p-4L, 0xe.38603c1d1ea2235p-4L }, + { -0xe.ca8e0a5bcb1909bp-4L, -0x7.91e59560df20b59p-4L, -0x7.91e59560df20b588p-4L }, + { 0xf.3c4d21f42ce9eep-4L, 0xe.f525a7db23c77d2p-4L, 0xe.f525a7db23c77d3p-4L }, + { -0x6.a2b3b3cd69bd69p-4L, -0x3.ff5415c01005cd3p-4L, -0x3.ff5415c01005cd2cp-4L }, + { 0x1.5878b28462452782p-68L, 0xe.ec4f96d55b56cbap-72L, 0xe.ec4f96d55b56cbbp-72L }, + { -0xd.226b6159f1b8274p-176L, -0x9.1aa6ccef2946b71p-176L, -0x9.1aa6ccef2946b7p-176L }, + { 0xd.a2d0231770a0b2fp-4L, 0xc.e29042d0f0148dep-4L, 0xc.e29042d0f0148dfp-4L }, + { -0x5.88f950204ac58c2p-4L, -0x3.6949fabdeff8c62cp-4L, -0x3.6949fabdeff8c628p-4L }, + { 0xd.566e196c5299a76p-4L, 0xc.8398d1f51b7d57bp-4L, 0xc.8398d1f51b7d57cp-4L }, + { -0xd.827bfd05ebedd0fp-4L, -0x7.16b1fb3d30143fdp-4L, -0x7.16b1fb3d30143fc8p-4L }, + { 0xe.690353be92b1ef7p-4L, 0xd.dec96ccbdc54711p-4L, 0xd.dec96ccbdc54712p-4L }, + { -0xc.b40a6525370a3c1p-4L, -0x6.c59691f570ea335p-4L, -0x6.c59691f570ea3348p-4L }, + { 0x4.a16f62e1fb463d7p-4L, 0x3.8de59c3015480afp-4L, 0x3.8de59c3015480af4p-4L }, + { -0xb.6a308232b3be302p-4L, -0x6.3df86ee55414e478p-4L, -0x6.3df86ee55414e47p-4L }, + { 0xa.589c3c563d348fcp-4L, 0x9.0c54f3c1e94b5d5p-4L, 0x9.0c54f3c1e94b5d6p-4L }, + { -0xe.aaf84b1b375592p-4L, -0x7.8654b73051a16d2p-4L, -0x7.8654b73051a16d18p-4L }, + { 0x2.4225b8cb6a3450acp-4L, 0x1.a5000bbb5b20203p-4L, 0x1.a5000bbb5b202032p-4L }, + { -0x5.e1f5a13fb1e038ap-16L, -0x4.13d1b0bbfe40d278p-16L, -0x4.13d1b0bbfe40d27p-16L }, + { 0x6.501f9ed256bec01p-4L, 0x5.085e4ef770a5bbd8p-4L, 0x5.085e4ef770a5bbep-4L }, + { -0xa.0150779e90ebc75p-4L, -0x5.a0a9cac5cfa9e798p-4L, -0x5.a0a9cac5cfa9e79p-4L }, + { 0xd.5de12ee5f0afea5p-4L, 0xc.8cce152f519601bp-4L, 0xc.8cce152f519601cp-4L }, + { -0x8.16fa985eea51244p-4L, -0x4.baee6e9ee24b5858p-4L, -0x4.baee6e9ee24b585p-4L }, + { 0x2.32885a9f2271ac78p-4L, 0x1.991486e0e24975d2p-4L, 0x1.991486e0e24975d4p-4L }, + { -0x9.2c631a27ad6ae34p-4L, -0x5.3f3d59c428297e48p-4L, -0x5.3f3d59c428297e4p-4L }, + { 0xd.5153d9f62ecffddp-4L, 0xc.7d4bf03f0e6d411p-4L, 0xc.7d4bf03f0e6d412p-4L }, + { -0x2.e68bda95c5b3e06cp-4L, -0x1.e3ab538ce3f7ecdap-4L, -0x1.e3ab538ce3f7ecd8p-4L }, + { 0x7.a68b5532b0e7f568p-200L, 0x5.4d8f37527724f7d8p-200L, 0x5.4d8f37527724f7ep-200L }, + { -0x3.cd1483e1b10e99dp-84L, -0x2.a27cdd6c9a12d844p-84L, -0x2.a27cdd6c9a12d84p-84L }, + { 0xc.e8479ca0a43ef6p-8L, 0x9.1ad81877660b242p-8L, 0x9.1ad81877660b243p-8L }, + { -0x9.182ad6a367d08aep-4L, -0x5.35cdecfe5b731ce8p-4L, -0x5.35cdecfe5b731cep-4L }, + { 0x9.3029b8a7e85f35dp-4L, 0x7.d29571a8ad519618p-4L, 0x7.d29571a8ad51962p-4L }, + { -0xa.52ae9411f58887cp-4L, -0x5.c4f9aa019dcb689p-4L, -0x5.c4f9aa019dcb6888p-4L }, + { 0x7.5113a83ec9894cep-4L, 0x5.f7a9702b44563248p-4L, 0x5.f7a9702b4456325p-4L }, + { -0xd.13cf8aa40b87d27p-4L, -0x6.eb9109ecc7f4ddb8p-4L, -0x6.eb9109ecc7f4ddbp-4L }, + { 0xf.2395a1a0df7935bp-4L, 0xe.d411568c149c22fp-4L, 0xe.d411568c149c23p-4L }, + { -0x1.7af3bd8ca1f57c42p-4L, -0xf.e6caba0e492e4c1p-8L, -0xf.e6caba0e492e4cp-8L }, + { 0xd.f33b2053ffa6ae5p-4L, 0xd.47e1d5b0dd7bc76p-4L, 0xd.47e1d5b0dd7bc77p-4L }, + { -0xa.8e75c696dc40c78p-4L, -0x5.df55ef48a4e347e8p-4L, -0x5.df55ef48a4e347ep-4L }, + { 0x9.85d3f0dd48eaf72p-4L, 0x8.2ba30c3f7be89e3p-4L, 0x8.2ba30c3f7be89e4p-4L }, + { -0xd.506b8a6e4aa92acp-4L, -0x7.03491cf2bf49246p-4L, -0x7.03491cf2bf492458p-4L }, + { 0xa.d1883d4b01ef45ap-4L, 0x9.90e6441f511c6d1p-4L, 0x9.90e6441f511c6d2p-4L }, + { -0x3.08af0a00602595fp-4L, -0x1.f87a2c14dd7b7f16p-4L, -0x1.f87a2c14dd7b7f14p-4L }, + { 0xf.cac159b69035579p-4L, 0xf.b684c855d131bb2p-4L, 0xf.b684c855d131bb3p-4L }, + { -0x6.46e719cea85447d8p-4L, -0x3.cf38f95b6009617cp-4L, -0x3.cf38f95b60096178p-4L }, + { 0x5.987b05c45ed8a2ep-4L, 0x4.639c8775c1682ffp-4L, 0x4.639c8775c1682ff8p-4L }, + { -0x6.c4e52aa8d26db038p-4L, -0x4.110e8410a7512478p-4L, -0x4.110e8410a751247p-4L }, + { 0x8.23b5b38feb155f2p-4L, 0x6.c3bac23408a8825p-4L, 0x6.c3bac23408a88258p-4L }, + { -0x8.ad2a11b7f1b5ea6p-4L, -0x5.0354fe71cc130f2p-4L, -0x5.0354fe71cc130f18p-4L }, + { 0xf.af53dc003c2e966p-112L, 0xa.df368663af3dfc2p-112L, 0xa.df368663af3dfc3p-112L }, + { -0x3.f7b5578e89e3d3e8p-128L, -0x2.c0090f63161770cp-128L, -0x2.c0090f63161770bcp-128L }, + { 0x3.73e18f430b288f48p-4L, 0x2.94d9fe08f28f346cp-4L, 0x2.94d9fe08f28f347p-4L }, + { -0xc.f70837877517a74p-4L, -0x6.e03802a500a2e72p-4L, -0x6.e03802a500a2e718p-4L }, + { 0x7.3487f80314c54488p-4L, 0x5.dc8fba31d9f318ep-4L, 0x5.dc8fba31d9f318e8p-4L }, + { -0x5.4eccb9e96eb8967p-4L, -0x3.4967fb3eb0a4d81cp-4L, -0x3.4967fb3eb0a4d818p-4L }, + { 0x9.44460917d619271p-4L, 0x7.e75fbc9c380ed29p-4L, 0x7.e75fbc9c380ed298p-4L }, + { -0xd.5620dcdef8d6adep-4L, -0x7.0581c9d72c7b4df8p-4L, -0x7.0581c9d72c7b4dfp-4L }, + { 0xd.105984ee31d1a19p-4L, 0xc.2d8a202b2771e41p-4L, 0xc.2d8a202b2771e42p-4L }, + { -0xe.cb19e0196a54de2p-4L, -0x7.9218a6517e6df27p-4L, -0x7.9218a6517e6df268p-4L }, + { 0x5.b49471d499a4cf1p-4L, 0x4.7c7d8b0af0f48c28p-4L, 0x4.7c7d8b0af0f48c3p-4L }, + { -0x9.94f5bdecfacab51p-8L, -0x6.8e6561102f3ee5e8p-8L, -0x6.8e6561102f3ee5ep-8L }, + { 0xf.641993c9a620462p-4L, 0xf.2ab3dcfcad4c33ap-4L, 0xf.2ab3dcfcad4c33bp-4L }, + { -0xd.a2dd238869b2787p-4L, -0x7.23294ba101bfcb28p-4L, -0x7.23294ba101bfcb2p-4L }, + { 0xd.4c3f10c6378bac1p-4L, 0xc.77072f3026675d1p-4L, 0xc.77072f3026675d2p-4L }, + { -0xd.a0da38c144c364ap-4L, -0x7.22638fd7197afdbp-4L, -0x7.22638fd7197afda8p-4L }, + { 0x5.9e57359c4cf1067p-4L, 0x4.68ca49a0fa5b5d78p-4L, 0x4.68ca49a0fa5b5d8p-4L }, + { -0xf.5afa51a915c3c2cp-4L, -0x7.c600693d7adedab8p-4L, -0x7.c600693d7adedabp-4L }, + { 0xa.7324ede2d5b774ep-4L, 0x9.29307a00e1a50c1p-4L, 0x9.29307a00e1a50c2p-4L }, + { -0x4.deb94e5dff32647p-4L, -0x3.0b17181ece0d3c68p-4L, -0x3.0b17181ece0d3c64p-4L }, + { 0x6.67af9a1b48f5476p-4L, 0x5.1de173c8b6ffd77p-4L, 0x5.1de173c8b6ffd778p-4L }, + { -0xb.916f204d9b607e2p-4L, -0x6.4e815e5c604ec948p-4L, -0x6.4e815e5c604ec94p-4L }, + { 0x9.a94b7284791aef1p-88L, 0x6.b25b7556a0da05f8p-88L, 0x6.b25b7556a0da06p-88L }, + { -0x7.986b2cd7ddf22268p-132L, -0x5.43c4afc7229c434p-132L, -0x5.43c4afc7229c4338p-132L }, + { 0x1.15035f9ba3aac31ep-4L, 0xc.49523582a5e80c3p-8L, 0xc.49523582a5e80c4p-8L }, + { -0xc.6f90a760827aa89p-4L, -0x6.aa0dc49e51cdac1p-4L, -0x6.aa0dc49e51cdac08p-4L }, + { 0xf.fef4a753b10a076p-4L, 0xf.fe8d6976d07d14bp-4L, 0xf.fe8d6976d07d14cp-4L }, + { -0x6.4c2eb46758106918p-4L, -0x3.d202750df16f62a4p-4L, -0x3.d202750df16f62ap-4L }, + { 0x1.3ef509e0c382df66p-4L, 0xe.328e01d44f681dp-8L, 0xe.328e01d44f681d1p-8L }, + { -0xc.49b63ac9b2b9eaap-4L, -0x6.9ab1ff6082b3beap-4L, -0x6.9ab1ff6082b3be98p-4L }, + { 0x6.d057f880739cc278p-4L, 0x5.7e79c56f2d15b708p-4L, 0x5.7e79c56f2d15b71p-4L }, + { -0xb.1981c21be406601p-4L, -0x6.1ba12bbd58b2c01p-4L, -0x6.1ba12bbd58b2c008p-4L }, + { 0x8.0a6f57c957a28d4p-4L, 0x6.aadb51c6015dbep-4L, 0x6.aadb51c6015dbe08p-4L }, + { -0x5.f3f181c210c8a89p-4L, -0x3.a319fd0750dac56p-4L, -0x3.a319fd0750dac55cp-4L }, + { 0xe.2859c8a2c48c40ap-4L, 0xd.8b91686f98b11bdp-4L, 0xd.8b91686f98b11bep-4L }, + { -0xa.dd44c44ce7a5755p-4L, -0x6.01aed71b7ef78488p-4L, -0x6.01aed71b7ef7848p-4L }, + { 0xb.51ba4b350a61c32p-4L, 0xa.206f7762d17482bp-4L, 0xa.206f7762d17482cp-4L }, + { -0xc.0dfbf7e5e3212ffp-12L, -0x8.58dc6a67dabce9bp-12L, -0x8.58dc6a67dabce9ap-12L }, + { 0x7.6c639e488208ccc8p-4L, 0x6.11b6da6b26aebcd8p-4L, 0x6.11b6da6b26aebcep-4L }, + { -0x3.a1d6c7b434bf3d98p-4L, -0x2.545d932e669d3904p-4L, -0x2.545d932e669d39p-4L }, + { 0x5.c358113ef832c348p-4L, 0x4.899c27db749b1de8p-4L, 0x4.899c27db749b1dfp-4L }, + { -0xb.d7d98c530f97875p-4L, -0x6.6be6509d664dfbbp-4L, -0x6.6be6509d664dfba8p-4L }, + { 0x4.fa42d3ac3bebd7e8p-4L, 0x3.d9b642da220bca6p-4L, 0x3.d9b642da220bca64p-4L }, + { -0xa.5b3f67eed42f35ep-4L, -0x5.c8c4d54ed02eeb08p-4L, -0x5.c8c4d54ed02eebp-4L }, + { 0x8.df34d29839f6cbap-140L, 0x6.2647bfc5682b23d8p-140L, 0x6.2647bfc5682b23ep-140L }, + { -0x4.37cad4bbf2a5aa78p-108L, -0x2.ec747a81313e72acp-108L, -0x2.ec747a81313e72a8p-108L }, + { 0x1.d6566fbbd43703bcp-4L, 0x1.5356ad8698dd1454p-4L, 0x1.5356ad8698dd1456p-4L }, + { -0x5.7c58e6c483f58898p-4L, -0x3.6265408f3b9628d4p-4L, -0x3.6265408f3b9628dp-4L }, + { 0x4.6a4204ea8eeaab98p-4L, 0x3.5f5f5a4b33974f1p-4L, 0x3.5f5f5a4b33974f14p-4L }, + { -0x8.3dccba3b25f76c1p-4L, -0x4.cdd2979cf80fe2a8p-4L, -0x4.cdd2979cf80fe2ap-4L }, + { 0xd.5f0d592ded19983p-4L, 0xc.8e415fdd3807e8fp-4L, 0xc.8e415fdd3807e9p-4L }, + { -0xa.c3b832d5003b707p-8L, -0x7.5a8d2a98b9c25298p-8L, -0x7.5a8d2a98b9c2529p-8L }, + { 0xa.1061f8f22c56a2p-4L, 0x8.be6ebf67d3a8ca6p-4L, 0x8.be6ebf67d3a8ca7p-4L }, + { -0x7.a0e695df486975a8p-4L, -0x4.80b3df37bd2da46p-4L, -0x4.80b3df37bd2da458p-4L }, + { 0x2.0f49c0d924c5ef48p-4L, 0x1.7e4a674b14e39638p-4L, 0x1.7e4a674b14e3963ap-4L }, + { -0x2.98c242e38ab361a4p-4L, -0x1.b3cdb6359889897cp-4L, -0x1.b3cdb6359889897ap-4L }, + { 0xe.a88d8d085eb83b1p-4L, 0xe.3173fc65ba950ccp-4L, 0xe.3173fc65ba950cdp-4L }, + { -0x7.18f85d323644c07p-4L, -0x4.3c36aae8265e794p-4L, -0x4.3c36aae8265e7938p-4L }, + { 0xb.e3d76e1e4bf5645p-8L, 0x8.6028af6e8498d12p-8L, 0x8.6028af6e8498d13p-8L }, + { -0xa.e3f91773dee5cbdp-4L, -0x6.0495789dfe04b06p-4L, -0x6.0495789dfe04b058p-4L }, + { 0x6.64a485a65ba2bb8p-4L, 0x5.1b18ec86f4768a78p-4L, 0x5.1b18ec86f4768a8p-4L }, + { -0xb.ab5d793764e46aap-4L, -0x6.595eea36719ee3p-4L, -0x6.595eea36719ee2f8p-4L }, + { 0x4.180ed04588b6b84p-4L, 0x3.1add121478e2fe34p-4L, 0x3.1add121478e2fe38p-4L }, + { -0x3.1b46b393f7f02654p-4L, -0x2.03c27049f1c5241p-4L, -0x2.03c27049f1c5240cp-4L }, + { 0xb.12b6b696713dd3p-4L, 0x9.d97de4a57a62c6ep-4L, 0x9.d97de4a57a62c6fp-4L }, + { -0x4.65ce2cb3797b29a8p-12L, -0x3.0c0efb555fa20864p-12L, -0x3.0c0efb555fa2086p-12L }, + { 0x2.8d217b257289e3ccp-48L, 0x1.c4b73c33ff87c0a6p-48L, 0x1.c4b73c33ff87c0a8p-48L }, + { -0x6.2775ae1abb4f1b8p-132L, -0x4.44068348b3cc65f8p-132L, -0x4.44068348b3cc65fp-132L }, + { 0x7.9916813ff5ff3cc8p-4L, 0x6.3c9c97e7b3dc5dcp-4L, 0x6.3c9c97e7b3dc5dc8p-4L }, + { -0xe.8cc5489d5bd410dp-4L, -0x7.7b36e89d757a4abp-4L, -0x7.7b36e89d757a4aa8p-4L }, + { 0x4.332914d9e18063ap-4L, 0x3.3158c643f12f4994p-4L, 0x3.3158c643f12f4998p-4L }, + { -0xb.0de0f587f5c107fp-4L, -0x6.16a43bbcf353ca98p-4L, -0x6.16a43bbcf353ca9p-4L }, + { 0x7.8ea9558f03ae0e7p-4L, 0x6.32938e784969b998p-4L, 0x6.32938e784969b9ap-4L }, + { -0xf.dee9088b413455fp-4L, -0x7.f47ff39c1d7b3888p-4L, -0x7.f47ff39c1d7b388p-4L }, + { 0x8.2df8e53739c9b8bp-4L, 0x6.cddbf2a3d58ac5cp-4L, 0x6.cddbf2a3d58ac5c8p-4L }, + { -0xb.237c6168dab68dbp-4L, -0x6.1fe702218f1a48a8p-4L, -0x6.1fe702218f1a48ap-4L }, + { 0xc.ff8006e798ca57dp-4L, 0xc.190015c68329532p-4L, 0xc.190015c68329533p-4L }, + { -0x5.a01080821eed49f8p-4L, -0x3.75db7123ab84cf58p-4L, -0x3.75db7123ab84cf54p-4L }, + { 0x7.837abefd5e55df78p-4L, 0x6.27d5641a6c02fc68p-4L, 0x6.27d5641a6c02fc7p-4L }, + { -0x3.5060ef99941b0558p-4L, -0x2.23c9d923cd4adb98p-4L, -0x2.23c9d923cd4adb94p-4L }, + { 0xe.81ed35e6e8294cep-4L, 0xd.ff1805c791d6424p-4L, 0xd.ff1805c791d6425p-4L }, + { -0x4.bb21255de4a41a5p-4L, -0x2.f70cf4785702e974p-4L, -0x2.f70cf4785702e97p-4L }, + { 0x2.a7771004562ceed4p-4L, 0x1.f31d427f09d18b7cp-4L, 0x1.f31d427f09d18b7ep-4L }, + { -0x1.6959757c92243a3ap-4L, -0xf.2f6ce0c9b166b49p-8L, -0xf.2f6ce0c9b166b48p-8L }, + { 0x6.bbde2a7543c30b38p-4L, 0x5.6b71442a60dd2568p-4L, 0x5.6b71442a60dd257p-4L }, + { -0xb.8edecd5dd38da0cp-4L, -0x6.4d6db28b17aa8588p-4L, -0x6.4d6db28b17aa858p-4L }, + { 0x6.c15f52803f443968p-4L, 0x5.708d7c1ba353e398p-4L, 0x5.708d7c1ba353e3ap-4L }, + { -0x3.918ec1969b0edd88p-4L, -0x2.4ab5c149bf41c4c4p-4L, -0x2.4ab5c149bf41c4cp-4L }, + { 0x7.7b238d3b9d8115e8p-120L, 0x5.2f791dc93f08299p-120L, 0x5.2f791dc93f082998p-120L }, + { -0x1.9f3582a69a86e648p-60L, -0x1.1fcd0c091eb14d28p-60L, -0x1.1fcd0c091eb14d26p-60L }, + { 0x6.81487cec2e861c7p-8L, 0x4.8c82f180777d68f8p-8L, 0x4.8c82f180777d69p-8L }, + { -0x4.87a7a304beeda28p-4L, -0x2.d9db282588789b7cp-4L, -0x2.d9db282588789b78p-4L }, + { 0xd.c7238c1ad3cafc9p-4L, 0xd.1028e60f36ff2b1p-4L, 0xd.1028e60f36ff2b2p-4L }, + { -0xe.ac1774f7032d1ffp-4L, -0x7.86be2433cc1d9da8p-4L, -0x7.86be2433cc1d9dap-4L }, + { 0x8.fc6153c653d77c7p-4L, 0x7.9d6025bd14094ad8p-4L, 0x7.9d6025bd14094aep-4L }, + { -0x1.014e18840001d972p-4L, -0xa.e85ead1a4e78382p-8L, -0xa.e85ead1a4e78381p-8L }, + { 0x5.040eb8c257682f18p-4L, 0x3.e224b9c7d7c0f06cp-4L, 0x3.e224b9c7d7c0f07p-4L }, + { -0xf.7346ad82e18af85p-4L, -0x7.cea4b926fe7c2368p-4L, -0x7.cea4b926fe7c236p-4L }, + { 0x3.c7346df124e8ef98p-4L, 0x2.d8668c024b6308e8p-4L, 0x2.d8668c024b6308ecp-4L }, + { -0xc.f461f50edbbb96fp-4L, -0x6.df2bda27bd06182p-4L, -0x6.df2bda27bd061818p-4L }, + { 0xd.c278b0558bd0b11p-4L, 0xd.0a4916e65159357p-4L, 0xd.0a4916e65159358p-4L }, + { -0x4.b2842fc0d4e29f8p-4L, -0x2.f22eea0353ff92dp-4L, -0x2.f22eea0353ff92ccp-4L }, + { 0xf.a09a22b402060edp-4L, 0xf.7ccfec40ad06d7ep-4L, 0xf.7ccfec40ad06d7fp-4L }, + { -0x8.e32395dc002f9bfp-8L, -0x6.162efd7ddd7ad93p-8L, -0x6.162efd7ddd7ad928p-8L }, + { 0xf.8c0db00bdf53596p-4L, 0xf.60d4a396fb9dadcp-4L, 0xf.60d4a396fb9daddp-4L }, + { -0x5.36e056abcab2faa8p-4L, -0x3.3c3413c718ca2bf4p-4L, -0x3.3c3413c718ca2bfp-4L }, + { 0x7.6c92e56712d5affp-4L, 0x6.11e40e1716fd4fb8p-4L, 0x6.11e40e1716fd4fcp-4L }, + { -0xd.6cb0532deaf2679p-4L, -0x7.0e43f2e8f0654b5p-4L, -0x7.0e43f2e8f0654b48p-4L }, + { 0x1.864d5d5420279f0cp-4L, 0x1.17abd4dea55c6812p-4L, 0x1.17abd4dea55c6814p-4L }, + { -0xa.e4299f2f9dca735p-4L, -0x6.04aa7510ef638d5p-4L, -0x6.04aa7510ef638d48p-4L }, + { 0xe.d132e5394f60034p-128L, 0xa.453ebc4a42e6cb8p-128L, 0xa.453ebc4a42e6cb9p-128L }, + { -0x2.35600cb5057b0fe8p-100L, -0x1.87e3627dc194acb4p-100L, -0x1.87e3627dc194acb2p-100L }, + { 0x9.ea2a7bd17c460dep-4L, 0x8.95993518360a117p-4L, 0x8.95993518360a118p-4L }, + { -0xe.c5d9227ffaac8cfp-4L, -0x7.902d5e9f35d6cfa8p-4L, -0x7.902d5e9f35d6cfap-4L }, + { 0x7.e3d1eea20b324e7p-4L, 0x6.850f961c58bba1cp-4L, 0x6.850f961c58bba1c8p-4L }, + { -0x9.86088a50194e78ap-4L, -0x5.68af5d2483728da8p-4L, -0x5.68af5d2483728dap-4L }, + { 0xf.7fa93e24f531607p-4L, 0xf.5000aaa67e5abb3p-4L, 0xf.5000aaa67e5abb4p-4L }, + { -0x6.3df2b4ad8ed98938p-4L, -0x3.ca7d689c3a04ee1cp-4L, -0x3.ca7d689c3a04ee18p-4L }, + { 0xe.e19314560029718p-4L, 0xe.7c6642b7e0cbddap-4L, 0xe.7c6642b7e0cbddbp-4L }, + { -0xa.e3c3bdecf1dec26p-8L, -0x7.701f272b4e954b3p-8L, -0x7.701f272b4e954b28p-8L }, + { 0x7.13c978b522f9333p-4L, 0x5.bda2c8c3fcf67318p-4L, 0x5.bda2c8c3fcf6732p-4L }, + { -0xd.81aab9ad9044dbbp-4L, -0x7.16613057101cc2e8p-4L, -0x7.16613057101cc2ep-4L }, + { 0x1.1d1ed153b343c44ep-4L, 0xc.a79cde97e744a1p-8L, 0xc.a79cde97e744a11p-8L }, + { -0x7.6fdb8f997549cde8p-8L, -0x5.1a74b0bff8212ac8p-8L, -0x5.1a74b0bff8212acp-8L }, + { 0x9.e81deac115960bcp-4L, 0x8.936a9f1de1dc2c9p-4L, 0x8.936a9f1de1dc2cap-4L }, + { -0xf.6e420d340620fd3p-4L, -0x7.ccdc951843f633f8p-4L, -0x7.ccdc951843f633fp-4L }, + { 0xe.6c4b7e894887c7fp-4L, 0xd.e308edc7c69afe9p-4L, 0xd.e308edc7c69afeap-4L }, + { -0xa.a620eccc4c7480bp-4L, -0x5.e9b3097aa5fb3aep-4L, -0x5.e9b3097aa5fb3ad8p-4L }, + { 0x1.c456c45ad9be2a9p-4L, 0x1.45d98d5ceaac11ecp-4L, 0x1.45d98d5ceaac11eep-4L }, + { -0x3.af9571884b9dea6cp-4L, -0x2.5c7f00327abdcc8cp-4L, -0x2.5c7f00327abdcc88p-4L }, + { 0xb.a0a2f3e13b85a66p-4L, 0xa.7a58fb959132f5p-4L, 0xa.7a58fb959132f51p-4L }, + { -0x1.574d5a4e81cea558p-4L, -0xe.72dbed0cf3f04efp-8L, -0xe.72dbed0cf3f04eep-8L }, + { 0x2.4592a2ef43290dcp-184L, 0x1.931d946725be0bacp-184L, 0x1.931d946725be0baep-184L }, + { -0x2.1340349dc88fe5ap-148L, -0x1.703c28b59101b778p-148L, -0x1.703c28b59101b776p-148L }, + { 0xc.52069130f81cabfp-8L, 0x8.af13d4a97a211afp-8L, 0x8.af13d4a97a211bp-8L }, + { -0x4.20c946d47a37871p-4L, -0x2.9ebecd164da3800cp-4L, -0x2.9ebecd164da38008p-4L }, + { 0xc.ad96dfac7b95172p-4L, 0xb.b5fbb7908197649p-4L, 0xb.b5fbb790819764ap-4L }, + { -0x1.1fc7d37c0ec92196p-4L, -0xc.2b1ec45e46b2f21p-8L, -0xc.2b1ec45e46b2f2p-8L }, + { 0xd.0d8c22a9e6d3c5p-4L, 0xc.2a1e9cdc9f50a83p-4L, 0xc.2a1e9cdc9f50a84p-4L }, + { -0x8.c7054bd7b8a06d5p-4L, -0x5.0f9cb256bb7dc48p-4L, -0x5.0f9cb256bb7dc478p-4L }, + { 0x5.13c1489191b10628p-4L, 0x3.efaed7947e426ea4p-4L, 0x3.efaed7947e426ea8p-4L }, + { -0x9.40268306f3eaf37p-4L, -0x5.486e4611a98deb68p-4L, -0x5.486e4611a98deb6p-4L }, + { 0x4.8b3a84ec2d62ab1p-4L, 0x3.7b1edaf9b2695bacp-4L, 0x3.7b1edaf9b2695bbp-4L }, + { -0x2.971ee88e20aca63cp-4L, -0x1.b2c9edea76d921ap-4L, -0x1.b2c9edea76d9219ep-4L }, + { 0x3.f7343ff72e27615cp-4L, 0x2.ffbf501a1f86d97cp-4L, 0x2.ffbf501a1f86d98p-4L }, + { -0xc.f38290b95d0f886p-4L, -0x6.ded38151017c9f78p-4L, -0x6.ded38151017c9f7p-4L }, + { 0x6.19ec462854667938p-4L, 0x4.d73549a9496846e8p-4L, 0x4.d73549a9496846fp-4L }, + { -0xe.a753d50ad228a17p-4L, -0x7.84fe3ea5ac9675c8p-4L, -0x7.84fe3ea5ac9675cp-4L }, + { 0xb.2326e5c709d8338p-4L, 0x9.ebecfa9a7ed2102p-4L, 0x9.ebecfa9a7ed2103p-4L }, + { -0xe.4cbeeba038e2a66p-4L, -0x7.63754094094d3058p-4L, -0x7.63754094094d305p-4L }, + { 0x9.90137db5d8438f6p-4L, 0x8.36609082c07d8ebp-4L, 0x8.36609082c07d8ecp-4L }, + { -0x8.f6fc2825e1cf803p-4L, -0x5.26400e89ac84512p-4L, -0x5.26400e89ac845118p-4L }, + { 0xb.a6e18f1dc982de2p-4L, 0xa.8183a9b9420a005p-4L, 0xa.8183a9b9420a006p-4L }, + { -0x7.093038cd340d2eap-4L, -0x4.3428c5f7bc4908e8p-4L, -0x4.3428c5f7bc4908ep-4L }, + { 0x1.7d48f31379a2fd94p-16L, 0x1.0849e6ab4023994ep-16L, 0x1.0849e6ab4023995p-16L }, + { -0xe.811989909a6ff03p-172L, -0xa.0db9811ffb53051p-172L, -0xa.0db9811ffb5305p-172L }, + { 0xf.a038fe23264b69fp-4L, 0xf.7c4b6a476a8be7cp-4L, 0xf.7c4b6a476a8be7dp-4L }, + { -0x5.d983ceba22bba45p-4L, -0x3.94ea4ac9f11d384cp-4L, -0x3.94ea4ac9f11d3848p-4L }, + { 0x3.aaf0ce3e734d6f2p-4L, 0x2.c161688c554ee7fcp-4L, 0x2.c161688c554ee8p-4L }, + { -0xf.72f358999238d68p-4L, -0x7.ce872556e868c9d8p-4L, -0x7.ce872556e868c9dp-4L }, + { 0x6.4d100f244be8113p-4L, 0x5.059488ceb9e3a5p-4L, 0x5.059488ceb9e3a508p-4L }, + { -0x8.8a2584d61c785a5p-4L, -0x4.f29d6d10179eb218p-4L, -0x4.f29d6d10179eb21p-4L }, + { 0xd.c98d7189a0303bfp-4L, 0xd.133307457e07c72p-4L, 0xd.133307457e07c73p-4L }, + { -0x1.4471ec132a54d16ap-4L, -0xd.ad37019fa9d9a9p-8L, -0xd.ad37019fa9d9a8fp-8L }, + { 0xb.bac11f4e1e14036p-4L, 0xa.985f73784b37eb5p-4L, 0xa.985f73784b37eb6p-4L }, + { -0x5.f466fe6cbdda3498p-4L, -0x3.a358e8e63a5fba64p-4L, -0x3.a358e8e63a5fba6p-4L }, + { 0xb.650503cc7e3186cp-4L, 0xa.364e81e99eb81f3p-4L, 0xa.364e81e99eb81f4p-4L }, + { -0x1.5d03274c615fac7ep-4L, -0xe.ae956d0835aaf87p-8L, -0xe.ae956d0835aaf86p-8L }, + { 0xf.e3a0ddc922c2768p-4L, 0xf.d8c34a986f967d3p-4L, 0xf.d8c34a986f967d4p-4L }, + { -0xa.669f21ff1f04159p-4L, -0x5.cdcc37c6f732fe1p-4L, -0x5.cdcc37c6f732fe08p-4L }, + { 0x8.ab617e168652f41p-4L, 0x7.4b137892a0c69d88p-4L, 0x7.4b137892a0c69d9p-4L }, + { -0xa.9ceb33ff19c471bp-4L, -0x5.e5abee4fb863c6ep-4L, -0x5.e5abee4fb863c6d8p-4L }, + { 0x7.e712d33d338b3f4p-4L, 0x6.883c6044c3c2bcb8p-4L, 0x6.883c6044c3c2bccp-4L }, + { -0x6.ed724b0ecd1acf48p-4L, -0x4.25f2ea71fb90ba5p-4L, -0x4.25f2ea71fb90ba48p-4L }, + { 0xb.0f353c55a1bc86bp-4L, 0x9.d59127340917f95p-4L, 0x9.d59127340917f96p-4L }, + { -0xa.9ea90fbdcd33289p-4L, -0x5.e66f0ac4d504378p-4L, -0x5.e66f0ac4d5043778p-4L }, + { 0x1.8d57c92ab74b5dbp-36L, 0x1.136ac861af6fd0cep-36L, 0x1.136ac861af6fd0dp-36L }, + { -0x5.db625c7f505b3848p-168L, -0x4.0f4b402286520448p-168L, -0x4.0f4b40228652044p-168L }, + { 0x2.b76e057b32691f28p-4L, 0x1.ff8b9dda8f045aep-4L, 0x1.ff8b9dda8f045ae2p-4L }, + { -0x6.dee852c47ad7ae6p-4L, -0x4.1e798f7b43706028p-4L, -0x4.1e798f7b4370602p-4L }, + { 0x6.bb1bf54be9664e8p-4L, 0x5.6abd10b33410d838p-4L, 0x5.6abd10b33410d84p-4L }, + { -0x6.aee79d84df01a37p-4L, -0x4.05aac336cc0ddf4p-4L, -0x4.05aac336cc0ddf38p-4L }, + { 0xf.db239caa0c58725p-4L, 0xf.cd0f1aa065d9edcp-4L, 0xf.cd0f1aa065d9eddp-4L }, + { -0x6.a15fc994e42a5f98p-4L, -0x3.fea35173a1f28d58p-4L, -0x3.fea35173a1f28d54p-4L }, + { 0xe.d6bf659b8abbf88p-4L, 0xe.6e1d0b3dcc929a2p-4L, 0xe.6e1d0b3dcc929a3p-4L }, + { -0x6.3520edf48c502b48p-4L, -0x3.c5d25806006121bcp-4L, -0x3.c5d25806006121b8p-4L }, + { 0x2.845d2338bd21f05cp-4L, 0x1.d7e66d41d318c988p-4L, 0x1.d7e66d41d318c98ap-4L }, + { -0x1.d3130e0c084f14c8p-4L, -0x1.37497e3ebaa67dcap-4L, -0x1.37497e3ebaa67dc8p-4L }, + { 0x7.e34ef80c4f7e3eep-4L, 0x6.848fd32b674801d8p-4L, 0x6.848fd32b674801ep-4L }, + { -0x5.a8b3cf39973ba25p-4L, -0x3.7a8bd473e711806cp-4L, -0x3.7a8bd473e7118068p-4L }, + { 0xa.b5fcccca163aaedp-4L, 0x9.727686834a4ee16p-4L, 0x9.727686834a4ee17p-4L }, + { -0x9.80fe0cfc3618055p-4L, -0x5.665f01272fca1dfp-4L, -0x5.665f01272fca1de8p-4L }, + { 0x1.deff9f28444c6c38p-4L, 0x1.59d80e0bc88e7a36p-4L, 0x1.59d80e0bc88e7a38p-4L }, + { -0x9.1da1f7cda29486bp-4L, -0x5.385b9fa450441c1p-4L, -0x5.385b9fa450441c08p-4L }, + { 0x9.24964216848ef53p-4L, 0x7.c6a60a15ee989f5p-4L, 0x7.c6a60a15ee989f58p-4L }, + { -0x7.c3b5a7c39208799p-4L, -0x4.91fd41abd0551208p-4L, -0x4.91fd41abd05512p-4L }, + { 0xc.7f839e0758c0fc4p-4L, 0xb.7ee2c8991a66c5bp-4L, 0xb.7ee2c8991a66c5cp-4L }, + { -0xa.04266867c71fecep-4L, -0x5.a1efea5e48c556e8p-4L, -0x5.a1efea5e48c556ep-4L }, + { 0x3.1aa2b36a1fb87f7cp-48L, 0x2.26cca4e6218f7cc8p-48L, 0x2.26cca4e6218f7cccp-48L }, + { -0x1.ba95b94050477ba6p-152L, -0x1.32c6c531dafa9e4p-152L, -0x1.32c6c531dafa9e3ep-152L }, + { 0x6.108af52b9d9b2bp-4L, 0x4.cebef902a16e9c8p-4L, 0x4.cebef902a16e9c88p-4L }, + { -0x3.072eed70b90d2ae8p-4L, -0x1.f790b03dd687e68cp-4L, -0x1.f790b03dd687e68ap-4L }, + { 0xb.ad44f9f8ad944a6p-4L, 0xa.88da98fd452a1b5p-4L, 0xa.88da98fd452a1b6p-4L }, + { -0xb.3fef5d7e57e0805p-4L, -0x6.2c0b5071c8e72768p-4L, -0x6.2c0b5071c8e7276p-4L }, + { 0xe.b53f2b3083d023ep-4L, 0xe.42131e5b55a520bp-4L, 0xe.42131e5b55a520cp-4L }, + { -0xb.f408f69524f06c2p-4L, -0x6.779147008107f7cp-4L, -0x6.779147008107f7b8p-4L }, + { 0x8.03baca4a7357516p-4L, 0x6.a446a2fcb76d806p-4L, 0x6.a446a2fcb76d8068p-4L }, + { -0xa.c1abbb69e26abf7p-4L, -0x5.f5b5017c8517f208p-4L, -0x5.f5b5017c8517f2p-4L }, + { 0x1.d872e7eedaaa637ep-4L, 0x1.54ec695ac1dbc924p-4L, 0x1.54ec695ac1dbc926p-4L }, + { -0x4.495ee30da4659e98p-4L, -0x2.b6306706e0bbaac4p-4L, -0x2.b6306706e0bbaacp-4L }, + { 0xc.150a73ee88aac4bp-4L, 0xb.0131f0d15ff1b5p-4L, 0xb.0131f0d15ff1b51p-4L }, + { -0xa.3e82e32d6766963p-4L, -0x5.bc052d79040a9f88p-4L, -0x5.bc052d79040a9f8p-4L }, + { 0x6.08720c311ad69e78p-4L, 0x4.c773b03aa96a3fc8p-4L, 0x4.c773b03aa96a3fdp-4L }, + { -0x7.3b6b4ffd7b8decp-8L, -0x4.f6d2acdaf77fd21p-8L, -0x4.f6d2acdaf77fd208p-8L }, + { 0x5.80db9fe644d1e708p-4L, 0x4.4ec994b6102856dp-4L, 0x4.4ec994b6102856d8p-4L }, + { -0x1.f640e13ffc2a24cap-4L, -0x1.4dc050898710d058p-4L, -0x1.4dc050898710d056p-4L }, + { 0xb.656227303abf84fp-4L, 0xa.36b8463547f4c73p-4L, 0xa.36b8463547f4c74p-4L }, + { -0x7.b40be4642e982ab8p-4L, -0x4.8a392adbf99bf968p-4L, -0x4.8a392adbf99bf96p-4L }, + { 0x2.8126daf9591a4a78p-4L, 0x1.d56af8b597dab07ep-4L, 0x1.d56af8b597dab08p-4L }, + { -0xf.8481196507714a9p-4L, -0x7.d4bfd1129eebe82p-4L, -0x7.d4bfd1129eebe818p-4L }, + { 0x2.1a154d27c4610f5cp-92L, 0x1.74f88a35a7f80dcep-92L, 0x1.74f88a35a7f80ddp-92L }, + { -0x5.585153da63583088p-12L, -0x3.b40448ded8eb7678p-12L, -0x3.b40448ded8eb7674p-12L }, + { 0x8.4b1f02dac6cd4b9p-4L, 0x6.eaba168a48b0171p-4L, 0x6.eaba168a48b01718p-4L }, + { -0xc.759d3a3d2bb277bp-4L, -0x6.ac7fc087257bf838p-4L, -0x6.ac7fc087257bf83p-4L }, + { 0x9.5efce40ef5c193p-4L, 0x8.0319c4d499a7ca3p-4L, 0x8.0319c4d499a7ca4p-4L }, + { -0x1.3acdec63c75ba85ap-4L, -0xd.47ed2768ca5ede8p-8L, -0xd.47ed2768ca5ede7p-8L }, + { 0x3.a8862397aa33d5bcp-4L, 0x2.bf6ad5c108758048p-4L, 0x2.bf6ad5c10875804cp-4L }, + { -0x8.40b99f3260074bbp-4L, -0x4.cf3dbd131e8a17ap-4L, -0x4.cf3dbd131e8a1798p-4L }, + { 0x1.13ba9d07bc3a2952p-4L, 0xc.3a6591e048e18fep-8L, 0xc.3a6591e048e18ffp-8L }, + { -0x2.71006a8cb34d554cp-4L, -0x1.9b18519a46103f02p-4L, -0x1.9b18519a46103fp-4L }, + { 0x9.1553f4826cd4c82p-4L, 0x7.b6f3ad6001421a68p-4L, 0x7.b6f3ad6001421a7p-4L }, + { -0x5.67cce3baa54af0cp-4L, -0x3.57257d17a151238cp-4L, -0x3.57257d17a1512388p-4L }, + { 0x3.8114a9e190ab791p-4L, 0x2.9f7d24d05db91814p-4L, 0x2.9f7d24d05db91818p-4L }, + { -0x4.9c18fd283d9a589p-4L, -0x2.e57b1e06ca7a4c84p-4L, -0x2.e57b1e06ca7a4c8p-4L }, + { 0xc.05b3f7d8b6f7624p-4L, 0xa.ef465963b3e1fc3p-4L, 0xa.ef465963b3e1fc4p-4L }, + { -0xc.aa597d6d2ed91e3p-4L, -0x6.c1b5f0a62eb977fp-4L, -0x6.c1b5f0a62eb977e8p-4L }, + { 0x5.7aa677b8b3a14efp-4L, 0x4.49543a3a46f57d38p-4L, 0x4.49543a3a46f57d4p-4L }, + { -0x6.8d1b5b54f8172e1p-4L, -0x3.f4143adbee4eb904p-4L, -0x3.f4143adbee4eb9p-4L }, + { 0x4.a8455a7e3a68ed78p-4L, 0x3.93b0e898b77bf4c8p-4L, 0x3.93b0e898b77bf4ccp-4L }, + { -0x8.f684ab518e13e14p-4L, -0x5.2607e33540e678cp-4L, -0x5.2607e33540e678b8p-4L }, + { 0xf.331d018a51a3937p-4L, 0xe.e8d595bf6b18a9ap-4L, 0xe.e8d595bf6b18a9bp-4L }, + { -0x3.eca2bd0c8570369p-4L, -0x2.80620c0582a7ae94p-4L, -0x2.80620c0582a7ae9p-4L }, + { 0xc.a5327c102d01348p-80L, 0x8.c3daa757b84ad52p-80L, 0x8.c3daa757b84ad53p-80L }, + { -0x2.a3c7cec074186df4p-180L, -0x1.d46a5432452e2c9p-180L, -0x1.d46a5432452e2c8ep-180L }, + { 0x2.293460674db2c4p-4L, 0x1.91f96e67e72e8cc2p-4L, 0x1.91f96e67e72e8cc4p-4L }, + { -0xd.ea0bd2fdf3193cep-4L, -0x7.3e53d5de8fa95728p-4L, -0x7.3e53d5de8fa9572p-4L }, + { 0x7.7cc8ad228793eeep-4L, 0x6.2169209a50da8dfp-4L, 0x6.2169209a50da8df8p-4L }, + { -0x3.3eb74cb49c028ad4p-4L, -0x2.192ac814bd5f0c5cp-4L, -0x2.192ac814bd5f0c58p-4L }, + { 0xe.bc5331958998244p-4L, 0xe.4b5bcd8b0908ccfp-4L, 0xe.4b5bcd8b0908cdp-4L }, + { -0x1.2903edbad4d00bdep-4L, -0xc.8c97befaf20c969p-8L, -0xc.8c97befaf20c968p-8L }, + { 0x5.3ee964d9303fef2p-4L, 0x4.1517b8de179c1dap-4L, 0x4.1517b8de179c1da8p-4L }, + { -0x9.0a14cf75dc8c935p-8L, -0x6.30877227885a5f9p-8L, -0x6.30877227885a5f88p-8L }, + { 0x6.e59cd2b304be20bp-8L, 0x4.d353ed698d0eff18p-8L, 0x4.d353ed698d0eff2p-8L }, + { -0xd.25ced593ff0ac61p-4L, -0x6.f2a2932d1abac2d8p-4L, -0x6.f2a2932d1abac2dp-4L }, + { 0x3.1617c019abd659bp-4L, 0x2.49f324ab933e42d8p-4L, 0x2.49f324ab933e42dcp-4L }, + { -0x6.690f39e52d0c90c8p-4L, -0x3.e1358e26e4c35228p-4L, -0x3.e1358e26e4c35224p-4L }, + { 0x9.1050fe64665d025p-4L, 0x7.b1ce2c811fa492bp-4L, 0x7.b1ce2c811fa492b8p-4L }, + { -0x7.f6184dd3447fc3fp-4L, -0x4.aad4f07652aeae78p-4L, -0x4.aad4f07652aeae7p-4L }, + { 0xd.953628a90529c68p-4L, 0xc.d1901b07c97032cp-4L, 0xc.d1901b07c97032dp-4L }, + { -0x7.43be3e30b7e5c7a8p-4L, -0x4.51ef59e61758d838p-4L, -0x4.51ef59e61758d83p-4L }, + { 0x7.a4dabfc6c9e825b8p-4L, 0x6.47f5486a01b237ap-4L, 0x6.47f5486a01b237a8p-4L }, + { -0xb.f01119533e278e8p-4L, -0x6.75ed9a05142d0eap-4L, -0x6.75ed9a05142d0e98p-4L }, + { 0x1.6396f574b56c6172p-4L, 0xf.e0af65687e4b67ep-8L, 0xf.e0af65687e4b67fp-8L }, + { -0xf.b5e4a3223e61c14p-4L, -0x7.e627a04f577a3258p-4L, -0x7.e627a04f577a325p-4L }, + { 0xd.0f395b84573f61dp-192L, 0x9.0d58a8d3ccd5356p-192L, 0x9.0d58a8d3ccd5357p-192L }, + { -0x1.cad34f8832df94b6p-188L, -0x1.3e08970bbbe4953cp-188L, -0x1.3e08970bbbe4953ap-188L }, + { 0xd.a82c5b229e8fe54p-4L, 0xc.e94629ca486873dp-4L, 0xc.e94629ca486873ep-4L }, + { -0xc.337e6ec5ca09cbfp-4L, -0x6.91a27c9fb5331f48p-4L, -0x6.91a27c9fb5331f4p-4L }, + { 0x5.999aa2e2c49c8778p-4L, 0x4.649a9990259a6b08p-4L, 0x4.649a9990259a6b1p-4L }, + { -0x7.b2a783da083648ep-8L, -0x5.47d116a619b453bp-8L, -0x5.47d116a619b453a8p-8L }, + { 0xe.68481349ea07669p-4L, 0xd.ddd72166e76368fp-4L, 0xd.ddd72166e76369p-4L }, + { -0x7.c2d56e73e1215768p-4L, -0x4.918e390065e28458p-4L, -0x4.918e390065e2845p-4L }, + { 0x7.cfb667a4a3914a3p-4L, 0x6.717a3878ea0e60d8p-4L, 0x6.717a3878ea0e60ep-4L }, + { -0x8.d974808af557b0ep-4L, -0x5.1855a0cd14dbe46p-4L, -0x5.1855a0cd14dbe458p-4L }, + { 0xb.439e5356c702ad8p-4L, 0xa.107c2031a79089ep-4L, 0xa.107c2031a79089fp-4L }, + { -0xe.188d98ec6dc463bp-4L, -0x7.4fe68a1b12545d8p-4L, -0x7.4fe68a1b12545d78p-4L }, + { 0xe.d87c88ea04cfc54p-4L, 0xe.7067f2e9706541cp-4L, 0xe.7067f2e9706541dp-4L }, + { -0x7.5df293fec0fa7908p-4L, -0x4.5f2a3838248134f8p-4L, -0x4.5f2a3838248134fp-4L }, + { 0xb.f31341da10838b7p-4L, 0xa.d992b6a99f3586cp-4L, 0xa.d992b6a99f3586dp-4L }, + { -0x4.94201f2127bae1d8p-4L, -0x2.e0f3cbf83592b45cp-4L, -0x2.e0f3cbf83592b458p-4L }, + { 0xf.466813a0cb58997p-4L, 0xf.02b6115e1e0a079p-4L, 0xf.02b6115e1e0a07ap-4L }, + { -0x1.b40206802faf31f8p-4L, -0x1.2356684fa89060dp-4L, -0x1.2356684fa89060cep-4L }, + { 0x5.cfe8b47a3d2bb528p-4L, 0x4.94cd1c5dccf7537p-4L, 0x4.94cd1c5dccf75378p-4L }, + { -0xd.f8e6092df0a67cdp-4L, -0x7.43f462a4ef5a1918p-4L, -0x7.43f462a4ef5a191p-4L }, + { 0xe.c5c2bbb0872eb38p-4L, 0xe.57c07f71f4fb432p-4L, 0xe.57c07f71f4fb433p-4L }, + { -0xe.4ffa3f0dccc1904p-4L, -0x7.64a9d0532f3787bp-4L, -0x7.64a9d0532f3787a8p-4L }, + { 0xd.f51b450c06fa53fp-8L, 0x9.dc151be4407a68ap-8L, 0x9.dc151be4407a68bp-8L }, + { -0x1.eb1cef301d81df08p-52L, -0x1.5469e23dccbca00ep-52L, -0x1.5469e23dccbca00cp-52L }, + { 0x8.5ae9b271c862bd1p-4L, 0x6.fa6d07dce385fccp-4L, 0x6.fa6d07dce385fcc8p-4L }, + { -0xa.8fdf30d83ecd512p-4L, -0x5.dff47c13aa88bb28p-4L, -0x5.dff47c13aa88bb2p-4L }, + { 0x1.e689240cdaba32p-4L, 0x1.5f8358e071a53472p-4L, 0x1.5f8358e071a53474p-4L }, + { -0x7.62f10575934711p-4L, -0x4.61adf89887b9a24p-4L, -0x4.61adf89887b9a238p-4L }, + { 0xf.65a3e9387da5a2fp-4L, 0xf.2cc85c945028fcap-4L, 0xf.2cc85c945028fcbp-4L }, + { -0xb.d4af71c255e18d6p-4L, -0x6.6a9610ee9e87a8cp-4L, -0x6.6a9610ee9e87a8b8p-4L }, + { 0x5.9a9d1446632f3aep-4L, 0x4.657ef16969a055cp-4L, 0x4.657ef16969a055c8p-4L }, + { -0x9.b4e978d15970db2p-4L, -0x5.7e1be34eafa75f3p-4L, -0x5.7e1be34eafa75f28p-4L }, + { 0x8.7aea261756d25f3p-4L, 0x7.1a5e60645036bcb8p-4L, 0x7.1a5e60645036bccp-4L }, + { -0xf.b5a3f9c32315f89p-4L, -0x7.e610eed3517ac508p-4L, -0x7.e610eed3517ac5p-4L }, + { 0xe.7abe135a43a13e6p-4L, 0xd.f5c385f4adc9adbp-4L, 0xd.f5c385f4adc9adcp-4L }, + { -0x7.31920eb4fe1bd628p-4L, -0x4.48b9bee7bd62fefp-4L, -0x4.48b9bee7bd62fee8p-4L }, + { 0x3.2bf2a0a669999b48p-4L, 0x2.5b4c32cabb20c8acp-4L, 0x2.5b4c32cabb20c8bp-4L }, + { -0xa.6bff2a4ca65e178p-4L, -0x5.d02bc0929aebb8c8p-4L, -0x5.d02bc0929aebb8cp-4L }, + { 0x9.8e13ef308c3a17bp-4L, 0x8.3448125bdeacbe9p-4L, 0x8.3448125bdeacbeap-4L }, + { -0x8.4ef4a64c01509a8p-4L, -0x4.d621b783f39f31a8p-4L, -0x4.d621b783f39f31ap-4L }, + { 0x3.765e093b8a1ce118p-4L, 0x2.96da7371ca2fa4f8p-4L, 0x2.96da7371ca2fa4fcp-4L }, + { -0x7.aadaa9cd4105412p-4L, -0x4.85a7f3b0c1e06018p-4L, -0x4.85a7f3b0c1e0601p-4L }, + { 0x1.a2bf59174aca4d52p-4L, 0x1.2cc8f455ff2cea6ap-4L, 0x1.2cc8f455ff2cea6cp-4L }, + { -0x5.8f5a8c1e06358d9p-4L, -0x3.6cc434f58f798508p-4L, -0x3.6cc434f58f798504p-4L }, + { 0x2.8d03b0fea7261144p-156L, 0x1.c4a296285d9fa774p-156L, 0x1.c4a296285d9fa776p-156L }, + { -0xb.4261fc576312e18p-204L, -0x7.cdea5cf7def284b8p-204L, -0x7.cdea5cf7def284bp-204L }, + { 0x4.6d7ef04080b676d8p-4L, 0x3.6217371c0fa676ep-4L, 0x3.6217371c0fa676e4p-4L }, + { -0xb.c0ae25e2a801fc9p-4L, -0x6.62443424ce0cc21p-4L, -0x6.62443424ce0cc208p-4L }, + { 0x9.33aadc610c07076p-4L, 0x7.d6339920da9a3778p-4L, 0x7.d6339920da9a378p-4L }, + { -0xb.62d8d178f4ea271p-4L, -0x6.3add5679a51923bp-4L, -0x6.3add5679a51923a8p-4L }, + { 0xb.de8017b99009994p-4L, 0xa.c1aeb0c257defb4p-4L, 0xa.c1aeb0c257defb5p-4L }, + { -0xc.d14f3f856910093p-4L, -0x6.d142a83bc366c57p-4L, -0x6.d142a83bc366c568p-4L }, + { 0x1.36027b0d8b10a26cp-4L, 0xd.c9e65e03a5bcddcp-8L, 0xd.c9e65e03a5bcdddp-8L }, + { -0xc.5d2d16de94144fcp-4L, -0x6.a29ae09167802018p-4L, -0x6.a29ae0916780201p-4L }, + { 0xd.79e031e02305347p-4L, 0xc.af83870de952b8fp-4L, 0xc.af83870de952b9p-4L }, + { -0xa.c010f18d71bc8c5p-4L, -0x5.f5024e3266fc5898p-4L, -0x5.f5024e3266fc589p-4L }, + { 0x1.9cd7b4a183ae1dcp-4L, 0x1.2864c8400d7852d2p-4L, 0x1.2864c8400d7852d4p-4L }, + { -0x1.720bafd1b399ec82p-4L, -0xf.8a14ed8ba218a08p-8L, -0xf.8a14ed8ba218a07p-8L }, + { 0x4.fac18c7be7e011e8p-4L, 0x3.da233da5c7f9843cp-4L, 0x3.da233da5c7f9844p-4L }, + { -0xe.e7cda687036f7d6p-8L, -0xa.20408f833c406efp-8L, -0xa.20408f833c406eep-8L }, + { 0x9.9c2d0517aeee533p-4L, 0x8.4314f6301d33356p-4L, 0x8.4314f6301d33357p-4L }, + { -0xe.573ec2d151cf156p-4L, -0x7.675f198c15befecp-4L, -0x7.675f198c15befeb8p-4L }, + { 0xe.947a2689d86b12ap-4L, 0xe.173cf492cdc5f07p-4L, 0xe.173cf492cdc5f08p-4L }, + { -0x5.fee8120e5e04be2p-4L, -0x3.a8f7bcd02665b4bcp-4L, -0x3.a8f7bcd02665b4b8p-4L }, + { 0x3.f3364f18a79b3b3cp-4L, 0x2.fc7677f28287f59cp-4L, 0x2.fc7677f28287f5ap-4L }, + { -0xd.acb73d1f464055dp-4L, -0x7.26f0d62a8825fadp-4L, -0x7.26f0d62a8825fac8p-4L }, + { 0x3.72e8ef378d42c014p-136L, 0x2.63fc8bc98f409418p-136L, 0x2.63fc8bc98f40941cp-136L }, + { -0xf.f7a6695a9469f6bp-64L, -0xb.1157d5a78619d6ap-64L, -0xb.1157d5a78619d69p-64L }, + { 0xa.ed0ce5b49afa192p-4L, 0x9.af72dd5f9d309c8p-4L, 0x9.af72dd5f9d309c9p-4L }, + { -0x8.92179a4e3bb69e3p-4L, -0x4.f66ab2d67cb085b8p-4L, -0x4.f66ab2d67cb085bp-4L }, + { 0xb.ed688726df9befap-4L, 0xa.d2fc0f03bbaa3eap-4L, 0xa.d2fc0f03bbaa3ebp-4L }, + { -0x9.3f55bdfddb49b2bp-4L, -0x5.480d56cfe248124p-4L, -0x5.480d56cfe2481238p-4L }, + { 0x7.2ec3f10b51218bfp-4L, 0x5.d71a7e29e3375c08p-4L, 0x5.d71a7e29e3375c1p-4L }, + { -0x7.f78628cdda70a8d8p-8L, -0x5.768d49335e93bc48p-8L, -0x5.768d49335e93bc4p-8L }, + { 0x6.5dbff56825b7dbb8p-4L, 0x5.14cc73903ffab37p-4L, 0x5.14cc73903ffab378p-4L }, + { -0xa.e7a98283fc10855p-4L, -0x6.062dbfc6c13a0cp-4L, -0x6.062dbfc6c13a0bf8p-4L }, + { 0xc.2509016f44e196ap-4L, 0xb.13ee99066e4da51p-4L, 0xb.13ee99066e4da52p-4L }, + { -0x7.861514480ac9199p-4L, -0x4.7350865eeea1ec4p-4L, -0x4.7350865eeea1ec38p-4L }, + { 0xf.17da41cf884346bp-4L, 0xe.c46a3230752f01ep-4L, 0xe.c46a3230752f01fp-4L }, + { -0xc.62d7c253621dcf7p-4L, -0x6.a4e721c955ab92bp-4L, -0x6.a4e721c955ab92a8p-4L }, + { 0x9.845c3e40ed6ad83p-8L, 0x6.aeb3e091a9ca62a8p-8L, 0x6.aeb3e091a9ca62bp-8L }, + { -0xd.68fda9eec5a66c2p-4L, -0x7.0cd5054a8559068p-4L, -0x7.0cd5054a85590678p-4L }, + { 0x8.18f925371b61292p-4L, 0x6.b926981ecb341cc8p-4L, 0x6.b926981ecb341cdp-4L }, + { -0x1.57f7c0849ebb346p-4L, -0xe.79d2f43931febcep-8L, -0xe.79d2f43931febcdp-8L }, + { 0xa.e4ab5281b09d79fp-4L, 0x9.a6211af13affacbp-4L, 0x9.a6211af13affaccp-4L }, + { -0x7.1174b12c13aaf4e8p-4L, -0x4.38619acc6b16c48p-4L, -0x4.38619acc6b16c478p-4L }, + { 0xe.880fef5908d95bdp-4L, 0xe.07123c37decbd2bp-4L, 0xe.07123c37decbd2cp-4L }, + { -0x7.609718a06f5f08ap-4L, -0x4.607ef189a568c048p-4L, -0x4.607ef189a568c04p-4L }, + { 0x6.e2bdbcf507ec4778p-80L, 0x4.c5d6cd2d0554bd38p-80L, 0x4.c5d6cd2d0554bd4p-80L }, + { -0xa.20544abb2f768b5p-172L, -0x7.04dd9fe9c3d0ca4p-172L, -0x7.04dd9fe9c3d0ca38p-172L }, + { 0x6.14aea1523dfe3aa8p-4L, 0x4.d27a84995c90398p-4L, 0x4.d27a84995c903988p-4L }, + { -0xc.97a55c9c85f26f9p-4L, -0x6.ba359004a30e41c8p-4L, -0x6.ba359004a30e41cp-4L }, + { 0x8.680ab975830d106p-4L, 0x7.078281205f71db5p-4L, 0x7.078281205f71db58p-4L }, + { -0x3.7b5dd7324be888fcp-4L, -0x2.3d81bd11bf2f6c4cp-4L, -0x2.3d81bd11bf2f6c48p-4L }, + { 0xd.ff0ee4cab1a5c92p-4L, 0xd.56e662606151cc8p-4L, 0xd.56e662606151cc9p-4L }, + { -0xe.008f2e366ac05f5p-4L, -0x7.46d9fe3c6c7508bp-4L, -0x7.46d9fe3c6c7508a8p-4L }, + { 0xa.b9de710cc3240eap-4L, 0x9.76be49caa91f1f7p-4L, 0x9.76be49caa91f1f8p-4L }, + { -0xd.b8496a7f5a40118p-4L, -0x7.2b5f2502bf92f008p-4L, -0x7.2b5f2502bf92fp-4L }, + { 0xb.c810c87ed94addfp-4L, 0xa.a7ba02e0d048d4bp-4L, 0xa.a7ba02e0d048d4cp-4L }, + { -0x6.0a47a8ab4ac89cd8p-4L, -0x3.af0abdfd7366387cp-4L, -0x3.af0abdfd73663878p-4L }, + { 0xd.694a760f35e0c5cp-4L, 0xc.9aeeb6a65c8040ap-4L, 0xc.9aeeb6a65c8040bp-4L }, + { -0x1.02b5df71e26e7eeep-4L, -0xa.f74a44b0786e5d7p-8L, -0xa.f74a44b0786e5d6p-8L }, + { 0x8.2d4ad8d9b79c26ep-4L, 0x6.cd300350fa1084ep-4L, 0x6.cd300350fa1084e8p-4L }, + { -0x5.d8b77fd6db5f46fp-4L, -0x3.947c5ee25dae93cp-4L, -0x3.947c5ee25dae93bcp-4L }, + { 0x3.b2d5aa2bd4f226c8p-4L, 0x2.c7cc7c21062df578p-4L, 0x2.c7cc7c21062df57cp-4L }, + { -0x1.3d87d39ca205f226p-4L, -0xd.6495ea183c77a34p-8L, -0xd.6495ea183c77a33p-8L }, + { 0x7.58b591427632828p-4L, 0x5.feee1c31635efc6p-4L, 0x5.feee1c31635efc68p-4L }, + { -0xd.51cbb799b3f3a26p-4L, -0x7.03d23697240275b8p-4L, -0x7.03d23697240275bp-4L }, + { 0x9.0e54bb10a5b7912p-4L, 0x7.afc489158099261p-4L, 0x7.afc4891580992618p-4L }, + { -0xa.7e81ca95f58d507p-4L, -0x5.d853b00c0424b748p-4L, -0x5.d853b00c0424b74p-4L }, + { 0xa.38c6b26a97ad959p-144L, 0x7.15cf9ed628b7443p-144L, 0x7.15cf9ed628b74438p-144L }, + { -0xd.8dbb3097e168af8p-16L, -0x9.64dcae1a44ce08fp-16L, -0x9.64dcae1a44ce08ep-16L }, + { 0xf.05da5fd59fc565bp-4L, 0xe.ac75be21fa0a721p-4L, 0xe.ac75be21fa0a722p-4L }, + { -0xd.dd9a1c0c442c4c6p-4L, -0x7.399a1163598e674p-4L, -0x7.399a1163598e6738p-4L }, + { 0x4.61b51c01df55d6d8p-4L, 0x3.5833a282f0757d38p-4L, 0x3.5833a282f0757d3cp-4L }, + { -0xb.dce6fd9bad9f495p-4L, -0x6.6dfecf316daaa2b8p-4L, -0x6.6dfecf316daaa2bp-4L }, + { 0xa.b6f22a1b9f2939fp-4L, 0x9.73850a513137669p-4L, 0x9.73850a51313766ap-4L }, + { -0x3.4bb35afb05788e3p-4L, -0x2.20fa7ab319293c2cp-4L, -0x2.20fa7ab319293c28p-4L }, + { 0xd.0db3afda3c5f8cp-4L, 0xc.2a4edf1f8e608e3p-4L, 0xc.2a4edf1f8e608e4p-4L }, + { -0x2.1ce57b45214ebd74p-4L, -0x1.6646119faf2579e4p-4L, -0x1.6646119faf2579e2p-4L }, + { 0x5.067f9f48fc5b234p-8L, 0x3.81d3c5994dfa29ep-8L, 0x3.81d3c5994dfa29e4p-8L }, + { -0xb.a04244a598be88fp-4L, -0x6.54b9128406b6e57p-4L, -0x6.54b9128406b6e568p-4L }, + { 0xf.d97f1711de15f9cp-4L, 0xf.cacbd7b24bfa344p-4L, 0xf.cacbd7b24bfa345p-4L }, + { -0xf.493b2b477feaaf9p-4L, -0x7.bfaad9fbab559b1p-4L, -0x7.bfaad9fbab559b08p-4L }, + { 0xc.deaf7691740cdefp-8L, 0x9.13f529a0032aecap-8L, 0x9.13f529a0032aecbp-8L }, + { -0xa.59b5d478c821a2ep-4L, -0x5.c816a0d158b46128p-4L, -0x5.c816a0d158b4612p-4L }, + { 0xd.1b186c2e3417901p-4L, 0xc.3aab3f3a165b5b1p-4L, 0xc.3aab3f3a165b5b2p-4L }, + { -0xf.14939428966efa8p-4L, -0x7.acc2e6e3a1c40bfp-4L, -0x7.acc2e6e3a1c40be8p-4L }, + { 0xa.548931dd5b08516p-4L, 0x9.07e9820c45dc918p-4L, 0x9.07e9820c45dc919p-4L }, + { -0x1.86c3057b9088fe1cp-4L, -0x1.06181e6e8d7c4ee6p-4L, -0x1.06181e6e8d7c4ee4p-4L }, + { 0x8.de5082bfa47b272p-8L, 0x6.38b52f74fd4fac9p-8L, 0x6.38b52f74fd4fac98p-8L }, + { -0x6.381df51cf6ba1e58p-4L, -0x3.c7677b23d838f2c4p-4L, -0x3.c7677b23d838f2cp-4L }, + { 0x2.f43f9bb64395d398p-28L, 0x2.0c3105ebb2d3ec1p-28L, 0x2.0c3105ebb2d3ec14p-28L }, + { -0x1.7d1826b58589517p-188L, -0x1.08278b32d446a3dap-188L, -0x1.08278b32d446a3d8p-188L }, + { 0x3.24bd5453a5d96c38p-4L, 0x2.5591a327002dbbfp-4L, 0x2.5591a327002dbbf4p-4L }, + { -0xd.ac66274a591f9a9p-4L, -0x7.26d1c15c81b1be3p-4L, -0x7.26d1c15c81b1be28p-4L }, + { 0x7.4bbb894be77050dp-4L, 0x5.f29408389bbe66ep-4L, 0x5.f29408389bbe66e8p-4L }, + { -0xa.eacc82e14c1610fp-4L, -0x6.0788b0f7dc794f7p-4L, -0x6.0788b0f7dc794f68p-4L }, + { 0x2.a982ac56625aefc4p-4L, 0x1.f4b47ebd7795a254p-4L, 0x1.f4b47ebd7795a256p-4L }, + { -0x8.056940c538fa279p-4L, -0x4.b257711af2be1e78p-4L, -0x4.b257711af2be1e7p-4L }, + { 0x1.66b64b9c9f79a1dep-4L, 0x1.00578a1c0c673a1p-4L, 0x1.00578a1c0c673a12p-4L }, + { -0x3.26b75fa52c7ce30cp-4L, -0x2.0aaf1c1238c99944p-4L, -0x2.0aaf1c1238c9994p-4L }, + { 0x9.da5604fb75e8d87p-4L, 0x8.84c2f5daaacf75ep-4L, 0x8.84c2f5daaacf75fp-4L }, + { -0x8.f39b1339c38973dp-4L, -0x5.24a94b90f03e7ed8p-4L, -0x5.24a94b90f03e7edp-4L }, + { 0x7.677b36d2e1d48358p-4L, 0x6.0d06229c56a97f4p-4L, 0x6.0d06229c56a97f48p-4L }, + { -0xa.996804efaa5460cp-4L, -0x5.e4224415b8782278p-4L, -0x5.e4224415b878227p-4L }, + { 0x6.b6c06e4a29c88afp-4L, 0x5.66b27094b245b1ep-4L, 0x5.66b27094b245b1e8p-4L }, + { -0x5.a5149fe9b18171c8p-4L, -0x3.7894bad1006fb798p-4L, -0x3.7894bad1006fb794p-4L }, + { 0x5.375a31264862647p-4L, 0x4.0e852a933247c008p-4L, 0x4.0e852a933247c01p-4L }, + { -0xc.55651fd1cbee3d4p-4L, -0x6.9f72345b02eab28p-4L, -0x6.9f72345b02eab278p-4L }, + { 0xe.006deb92f93d672p-4L, 0xd.58a49a5d8de28c4p-4L, 0xd.58a49a5d8de28c5p-4L }, + { -0xa.6871090121d471bp-4L, -0x5.ce99fb28aafa5bb8p-4L, -0x5.ce99fb28aafa5bbp-4L }, + { 0xc.8ed445e1ea26da6p-4L, 0xb.9126f62f86bcb47p-4L, 0xb.9126f62f86bcb48p-4L }, + { -0x3.70640030d409ab74p-4L, -0x2.36f53ff3b132cba8p-4L, -0x2.36f53ff3b132cba4p-4L }, + { 0x2.219473696b04364cp-96L, 0x1.7a2acafbc3adc14ep-96L, 0x1.7a2acafbc3adc15p-96L }, + { -0xd.bdc3902e400dcddp-144L, -0x9.865401201b95f7ap-144L, -0x9.865401201b95f79p-144L }, + { 0xb.b53f28201a854efp-4L, 0xa.9207b77bb750cf7p-4L, 0xa.9207b77bb750cf8p-4L }, + { -0x4.28b1a78cc7055bd8p-4L, -0x2.a3536d42907d291p-4L, -0x2.a3536d42907d290cp-4L }, + { 0xd.e2cee7a54e7c7dfp-4L, 0xd.331435f3041bf4fp-4L, 0xd.331435f3041bf5p-4L }, + { -0x9.3f6896a8070ab3ep-4L, -0x5.4816171c316ed77p-4L, -0x5.4816171c316ed768p-4L }, + { 0x1.a1524a334652c37cp-4L, 0x1.2bb95dd5b9658e26p-4L, 0x1.2bb95dd5b9658e28p-4L }, + { -0x1.9b7f6344a4875e14p-4L, -0x1.13861edcadba3e08p-4L, -0x1.13861edcadba3e06p-4L }, + { 0xb.4660bc20f1141f9p-4L, 0xa.1399f4f27c33975p-4L, 0xa.1399f4f27c33976p-4L }, + { -0xd.9888197bcafba2ap-4L, -0x7.1f30db722ee63d78p-4L, -0x7.1f30db722ee63d7p-4L }, + { 0xf.3adad3101e81209p-4L, 0xe.f33515340a557e4p-4L, 0xe.f33515340a557e5p-4L }, + { -0xa.79ea74b25ad8a16p-4L, -0x5.d64e6bad7c9fffc8p-4L, -0x5.d64e6bad7c9fffcp-4L }, + { 0xd.4d87683a39ac568p-4L, 0xc.789c1f6e5dcac31p-4L, 0xc.789c1f6e5dcac32p-4L }, + { -0xd.0f2848388d6bd4fp-4L, -0x6.e9bc44c0f7734168p-4L, -0x6.e9bc44c0f773416p-4L }, + { 0x5.d9fb99a27648b5d8p-4L, 0x4.9dca7407214af058p-4L, 0x4.9dca7407214af06p-4L }, + { -0x1.705dc2d9924977d6p-4L, -0xf.7895af9cd8410b4p-8L, -0xf.7895af9cd8410b3p-8L }, + { 0xe.de1ad3b0df8a929p-4L, 0xe.77d17cd52544381p-4L, 0xe.77d17cd52544382p-4L }, + { -0xe.4bc9f399afa1199p-4L, -0x7.6319db0e3314bc98p-4L, -0x7.6319db0e3314bc9p-4L }, + { 0x9.4bc88b56990e957p-4L, 0x7.ef27dce522664078p-4L, 0x7.ef27dce52266408p-4L }, + { -0xe.2a8337406c02664p-4L, -0x7.56a65648e9cbee38p-4L, -0x7.56a65648e9cbee3p-4L }, +}; + +int check_equal(long double res, long double expected) +{ + if (res != expected) { + return 0; + } + return (__builtin_copysignl(1.0L, res) == + __builtin_copysignl(1.0L, expected)); +} + +int main(void) +{ + int ret = 0; + int i; + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + long double ld_res; + __asm__ volatile ("f2xm1" : "=t" (ld_res) : "0" (tests[i].arg)); + if (!check_equal(ld_res, tests[i].down) && + !check_equal(ld_res, tests[i].up)) { + printf("FAIL: f2xm1 %La, expected %La or %La, got %La\n", + tests[i].arg, tests[i].down, tests[i].up, ld_res); + ret = 1; + } + } + return ret; +} diff --git a/tests/tcg/i386/test-i386-fbstp.c b/tests/tcg/i386/test-i386-fbstp.c new file mode 100644 index 0000000000000000000000000000000000000000..73bf56b9dc3fed01831e0b98b054993034c4298b --- /dev/null +++ b/tests/tcg/i386/test-i386-fbstp.c @@ -0,0 +1,140 @@ +/* Test fbstp instruction. */ + +#include +#include +#include + +union u { + struct { uint64_t sig; uint16_t sign_exp; } s; + long double ld; +}; + +volatile union u ld_invalid_1 = { .s = { 1, 1234 } }; +volatile union u ld_invalid_2 = { .s = { 0, 1234 } }; +volatile union u ld_invalid_3 = { .s = { 0, 0x7fff } }; +volatile union u ld_invalid_4 = { .s = { (UINT64_C(1) << 63) - 1, 0x7fff } }; + +int main(void) +{ + int ret = 0; + unsigned char out[10]; + memset(out, 0xfe, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-0.0L) : "st"); + out[9] &= 0x80; + if (memcmp(out, "\0\0\0\0\0\0\0\0\0\x80", sizeof out) != 0) { + printf("FAIL: fbstp -0\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-0.1L) : "st"); + out[9] &= 0x80; + if (memcmp(out, "\0\0\0\0\0\0\0\0\0\x80", sizeof out) != 0) { + printf("FAIL: fbstp -0.1\n"); + ret = 1; + } + memset(out, 0x1f, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-987654321987654321.0L) : + "st"); + out[9] &= 0x80; + if (memcmp(out, "\x21\x43\x65\x87\x19\x32\x54\x76\x98\x80", + sizeof out) != 0) { + printf("FAIL: fbstp -987654321987654321\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (999999999999999999.5L) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp 999999999999999999.5\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (1000000000000000000.0L) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp 1000000000000000000\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (1e30L) : "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp 1e30\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-999999999999999999.5L) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp -999999999999999999.5\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-1000000000000000000.0L) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp -1000000000000000000\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-1e30L) : "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp -1e30\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (__builtin_infl()) : "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp inf\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-__builtin_infl()) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp -inf\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (__builtin_nanl("")) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp nan\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-__builtin_nanl("")) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp -nan\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_invalid_1.ld) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp invalid 1\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_invalid_2.ld) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp invalid 2\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_invalid_3.ld) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp invalid 3\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_invalid_4.ld) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp invalid 4\n"); + ret = 1; + } + return ret; +} diff --git a/tests/tcg/i386/test-i386-fisttp.c b/tests/tcg/i386/test-i386-fisttp.c new file mode 100644 index 0000000000000000000000000000000000000000..16af59a7749f6dfa3f149b73b390dc4a39351a0b --- /dev/null +++ b/tests/tcg/i386/test-i386-fisttp.c @@ -0,0 +1,100 @@ +/* Test fisttpl and fisttpll instructions. */ + +#include +#include +#include + +union u { + struct { uint64_t sig; uint16_t sign_exp; } s; + long double ld; +}; + +volatile union u ld_invalid_1 = { .s = { 1, 1234 } }; + +int main(void) +{ + int ret = 0; + int32_t res_32; + int64_t res_64; + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (0x1p100L) : "st"); + if (res_32 != INT32_MIN) { + printf("FAIL: fisttpl 0x1p100\n"); + ret = 1; + } + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (-0x1p100L) : "st"); + if (res_32 != INT32_MIN) { + printf("FAIL: fisttpl -0x1p100\n"); + ret = 1; + } + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (__builtin_infl()) : + "st"); + if (res_32 != INT32_MIN) { + printf("FAIL: fisttpl inf\n"); + ret = 1; + } + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (-__builtin_infl()) : + "st"); + if (res_32 != INT32_MIN) { + printf("FAIL: fisttpl -inf\n"); + ret = 1; + } + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (__builtin_nanl("")) : + "st"); + if (res_32 != INT32_MIN) { + printf("FAIL: fisttpl nan\n"); + ret = 1; + } + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : + "t" (-__builtin_nanl("")) : "st"); + if (res_32 != INT32_MIN) { + printf("FAIL: fisttpl -nan\n"); + ret = 1; + } + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (ld_invalid_1.ld) : + "st"); + if (res_32 != INT32_MIN) { + printf("FAIL: fisttpl invalid\n"); + ret = 1; + } + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (0x1p100L) : "st"); + if (res_64 != INT64_MIN) { + printf("FAIL: fisttpll 0x1p100\n"); + ret = 1; + } + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (-0x1p100L) : "st"); + if (res_64 != INT64_MIN) { + printf("FAIL: fisttpll -0x1p100\n"); + ret = 1; + } + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (__builtin_infl()) : + "st"); + if (res_64 != INT64_MIN) { + printf("FAIL: fisttpll inf\n"); + ret = 1; + } + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (-__builtin_infl()) : + "st"); + if (res_64 != INT64_MIN) { + printf("FAIL: fisttpll -inf\n"); + ret = 1; + } + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : + "t" (__builtin_nanl("")) : "st"); + if (res_64 != INT64_MIN) { + printf("FAIL: fisttpll nan\n"); + ret = 1; + } + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : + "t" (-__builtin_nanl("")) : "st"); + if (res_64 != INT64_MIN) { + printf("FAIL: fisttpll -nan\n"); + ret = 1; + } + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (ld_invalid_1.ld) : + "st"); + if (res_64 != INT64_MIN) { + printf("FAIL: fisttpll invalid\n"); + ret = 1; + } + return ret; +} diff --git a/tests/tcg/i386/test-i386-fldcst.c b/tests/tcg/i386/test-i386-fldcst.c new file mode 100644 index 0000000000000000000000000000000000000000..e635432ccfdb5bba5422b46aa7d07d3533022f36 --- /dev/null +++ b/tests/tcg/i386/test-i386-fldcst.c @@ -0,0 +1,199 @@ +/* Test instructions loading floating-point constants. */ + +#include +#include + +volatile long double ld_res; + +int main(void) +{ + short cw; + int ret = 0; + + /* Round to nearest. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x000; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2t" : "=t" (ld_res)); + if (ld_res != 0x3.5269e12f346e2bf8p+0L) { + printf("FAIL: fldl2t N\n"); + ret = 1; + } + /* Round downward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x400; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2t" : "=t" (ld_res)); + if (ld_res != 0x3.5269e12f346e2bf8p+0L) { + printf("FAIL: fldl2t D\n"); + ret = 1; + } + /* Round toward zero. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0xc00; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2t" : "=t" (ld_res)); + if (ld_res != 0x3.5269e12f346e2bf8p+0L) { + printf("FAIL: fldl2t Z\n"); + ret = 1; + } + /* Round upward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x800; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2t" : "=t" (ld_res)); + if (ld_res != 0x3.5269e12f346e2bfcp+0L) { + printf("FAIL: fldl2t U\n"); + ret = 1; + } + + /* Round to nearest. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x000; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2e" : "=t" (ld_res)); + if (ld_res != 0x1.71547652b82fe178p+0L) { + printf("FAIL: fldl2e N\n"); + ret = 1; + } + /* Round downward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x400; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2e" : "=t" (ld_res)); + if (ld_res != 0x1.71547652b82fe176p+0L) { + printf("FAIL: fldl2e D\n"); + ret = 1; + } + /* Round toward zero. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0xc00; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2e" : "=t" (ld_res)); + if (ld_res != 0x1.71547652b82fe176p+0L) { + printf("FAIL: fldl2e Z\n"); + ret = 1; + } + /* Round upward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x800; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2e" : "=t" (ld_res)); + if (ld_res != 0x1.71547652b82fe178p+0L) { + printf("FAIL: fldl2e U\n"); + ret = 1; + } + + /* Round to nearest. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x000; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldpi" : "=t" (ld_res)); + if (ld_res != 0x3.243f6a8885a308d4p+0L) { + printf("FAIL: fldpi N\n"); + ret = 1; + } + /* Round downward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x400; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldpi" : "=t" (ld_res)); + if (ld_res != 0x3.243f6a8885a308dp+0L) { + printf("FAIL: fldpi D\n"); + ret = 1; + } + /* Round toward zero. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0xc00; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldpi" : "=t" (ld_res)); + if (ld_res != 0x3.243f6a8885a308dp+0L) { + printf("FAIL: fldpi Z\n"); + ret = 1; + } + /* Round upward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x800; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldpi" : "=t" (ld_res)); + if (ld_res != 0x3.243f6a8885a308d4p+0L) { + printf("FAIL: fldpi U\n"); + ret = 1; + } + + /* Round to nearest. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x000; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldlg2" : "=t" (ld_res)); + if (ld_res != 0x4.d104d427de7fbcc8p-4L) { + printf("FAIL: fldlg2 N\n"); + ret = 1; + } + /* Round downward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x400; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldlg2" : "=t" (ld_res)); + if (ld_res != 0x4.d104d427de7fbccp-4L) { + printf("FAIL: fldlg2 D\n"); + ret = 1; + } + /* Round toward zero. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0xc00; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldlg2" : "=t" (ld_res)); + if (ld_res != 0x4.d104d427de7fbccp-4L) { + printf("FAIL: fldlg2 Z\n"); + ret = 1; + } + /* Round upward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x800; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldlg2" : "=t" (ld_res)); + if (ld_res != 0x4.d104d427de7fbcc8p-4L) { + printf("FAIL: fldlg2 U\n"); + ret = 1; + } + + /* Round to nearest. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x000; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldln2" : "=t" (ld_res)); + if (ld_res != 0xb.17217f7d1cf79acp-4L) { + printf("FAIL: fldln2 N\n"); + ret = 1; + } + /* Round downward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x400; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldln2" : "=t" (ld_res)); + if (ld_res != 0xb.17217f7d1cf79abp-4L) { + printf("FAIL: fldln2 D\n"); + ret = 1; + } + /* Round toward zero. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0xc00; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldln2" : "=t" (ld_res)); + if (ld_res != 0xb.17217f7d1cf79abp-4L) { + printf("FAIL: fldln2 Z\n"); + ret = 1; + } + /* Round upward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x800; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldln2" : "=t" (ld_res)); + if (ld_res != 0xb.17217f7d1cf79acp-4L) { + printf("FAIL: fldln2 U\n"); + ret = 1; + } + + return ret; +} diff --git a/tests/tcg/i386/test-i386-fp-exceptions.c b/tests/tcg/i386/test-i386-fp-exceptions.c new file mode 100644 index 0000000000000000000000000000000000000000..dfb7117c1789fe6571734d26c639971d9a32e3a6 --- /dev/null +++ b/tests/tcg/i386/test-i386-fp-exceptions.c @@ -0,0 +1,831 @@ +/* Test floating-point exceptions. */ + +#include +#include +#include + +union u { + struct { uint64_t sig; uint16_t sign_exp; } s; + long double ld; +}; + +volatile float f_res; +volatile double d_res; +volatile long double ld_res; +volatile long double ld_res2; + +volatile union u ld_invalid_1 = { .s = { 1, 1234 } }; +volatile float f_snan = __builtin_nansf(""); +volatile double d_snan = __builtin_nans(""); +volatile long double ld_third = 1.0L / 3.0L; +volatile long double ld_snan = __builtin_nansl(""); +volatile long double ld_nan = __builtin_nanl(""); +volatile long double ld_inf = __builtin_infl(); +volatile long double ld_ninf = -__builtin_infl(); +volatile long double ld_one = 1.0L; +volatile long double ld_zero = 0.0L; +volatile long double ld_nzero = -0.0L; +volatile long double ld_min = LDBL_MIN; +volatile long double ld_max = LDBL_MAX; +volatile long double ld_nmax = -LDBL_MAX; + +#define IE (1 << 0) +#define ZE (1 << 2) +#define OE (1 << 3) +#define UE (1 << 4) +#define PE (1 << 5) +#define EXC (IE | ZE | OE | UE | PE) + +int main(void) +{ + short sw; + unsigned char out[10]; + int ret = 0; + int16_t res_16; + int32_t res_32; + int64_t res_64; + + __asm__ volatile ("fnclex"); + ld_res = f_snan; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: widen float snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = d_snan; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: widen double snan\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + f_res = ld_min; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (UE | PE)) { + printf("FAIL: narrow float underflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + d_res = ld_min; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (UE | PE)) { + printf("FAIL: narrow double underflow\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + f_res = ld_max; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (OE | PE)) { + printf("FAIL: narrow float overflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + d_res = ld_max; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (OE | PE)) { + printf("FAIL: narrow double overflow\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + f_res = ld_third; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: narrow float inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + d_res = ld_third; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: narrow double inexact\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + f_res = ld_snan; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: narrow float snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + d_res = ld_snan; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: narrow double snan\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + f_res = ld_invalid_1.ld; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: narrow float invalid\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + d_res = ld_invalid_1.ld; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: narrow double invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("frndint" : "=t" (ld_res) : "0" (ld_min)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: frndint min\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("frndint" : "=t" (ld_res) : "0" (ld_snan)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: frndint snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("frndint" : "=t" (ld_res) : "0" (ld_invalid_1.ld)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: frndint invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fcom" : : "t" (ld_nan), "u" (ld_zero)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fcom nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fucom" : : "t" (ld_nan), "u" (ld_zero)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != 0) { + printf("FAIL: fucom nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fucom" : : "t" (ld_snan), "u" (ld_zero)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fucom snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fucom" : : "t" (1.0L), "u" (ld_invalid_1.ld)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fucom invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + ld_res = ld_max + ld_max; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (OE | PE)) { + printf("FAIL: add overflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_max + ld_min; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: add inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_inf + ld_ninf; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: add inf -inf\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_snan + ld_third; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: add snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_third + ld_invalid_1.ld; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: add invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + ld_res = ld_max - ld_nmax; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (OE | PE)) { + printf("FAIL: sub overflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_max - ld_min; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: sub inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_inf - ld_inf; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: sub inf inf\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_snan - ld_third; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: sub snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_third - ld_invalid_1.ld; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: sub invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + ld_res = ld_max * ld_max; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (OE | PE)) { + printf("FAIL: mul overflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_third * ld_third; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: mul inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_min * ld_min; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (UE | PE)) { + printf("FAIL: mul underflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_inf * ld_zero; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: mul inf 0\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_snan * ld_third; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: mul snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_third * ld_invalid_1.ld; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: mul invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + ld_res = ld_max / ld_min; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (OE | PE)) { + printf("FAIL: div overflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_one / ld_third; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: div inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_min / ld_max; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (UE | PE)) { + printf("FAIL: div underflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_one / ld_zero; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != ZE) { + printf("FAIL: div 1 0\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_inf / ld_zero; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != 0) { + printf("FAIL: div inf 0\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_nan / ld_zero; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != 0) { + printf("FAIL: div nan 0\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_zero / ld_zero; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: div 0 0\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_inf / ld_inf; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: div inf inf\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_snan / ld_third; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: div snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_third / ld_invalid_1.ld; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: div invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fsqrt" : "=t" (ld_res) : "0" (ld_max)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: fsqrt inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fsqrt" : "=t" (ld_res) : "0" (ld_nmax)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fsqrt -max\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fsqrt" : "=t" (ld_res) : "0" (ld_ninf)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fsqrt -inf\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fsqrt" : "=t" (ld_res) : "0" (ld_snan)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fsqrt snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fsqrt" : "=t" (ld_res) : "0" (ld_invalid_1.ld)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fsqrt invalid\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fsqrt" : "=t" (ld_res) : "0" (ld_nzero)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != 0) { + printf("FAIL: fsqrt -0\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fsqrt" : "=t" (ld_res) : "0" (-__builtin_nanl(""))); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != 0) { + printf("FAIL: fsqrt -nan\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistp %0" : "=m" (res_16) : "t" (1.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: fistp inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistp %0" : "=m" (res_16) : "t" (32767.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistp 32767.5\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistp %0" : "=m" (res_16) : "t" (-32768.51L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistp -32768.51\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistp %0" : "=m" (res_16) : "t" (ld_nan) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistp nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistp %0" : "=m" (res_16) : "t" (ld_invalid_1.ld) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistp invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpl %0" : "=m" (res_32) : "t" (1.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: fistpl inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpl %0" : "=m" (res_32) : "t" (2147483647.5L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistpl 2147483647.5\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpl %0" : "=m" (res_32) : "t" (-2147483648.51L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistpl -2147483648.51\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpl %0" : "=m" (res_32) : "t" (ld_nan) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistpl nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpl %0" : "=m" (res_32) : "t" (ld_invalid_1.ld) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistpl invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpll %0" : "=m" (res_64) : "t" (1.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: fistpll inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpll %0" : "=m" (res_64) : "t" (0x1p63) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistpll 0x1p63\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpll %0" : "=m" (res_64) : "t" (-0x1.1p63L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistpll -0x1.1p63\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpll %0" : "=m" (res_64) : "t" (ld_nan) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistpll nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpll %0" : "=m" (res_64) : "t" (ld_invalid_1.ld) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistpll invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (1.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: fisttp inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (32768.0L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttp 32768\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (32768.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttp 32768.5\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (-32769.0L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttp -32769\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (-32769.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttp -32769.5\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (ld_nan) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttp nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (ld_invalid_1.ld) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttp invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (1.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: fisttpl inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (2147483648.0L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttpl 2147483648\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (-2147483649.0L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttpl -2147483649\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (ld_nan) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttpl nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (ld_invalid_1.ld) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttpl invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (1.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: fisttpll inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (0x1p63) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttpll 0x1p63\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (-0x1.1p63L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttpll -0x1.1p63\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (ld_nan) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttpll nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (ld_invalid_1.ld) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttpll invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fxtract" : "=t" (ld_res), "=u" (ld_res2) : + "0" (ld_zero)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != ZE) { + printf("FAIL: fxtract 0\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fxtract" : "=t" (ld_res), "=u" (ld_res2) : + "0" (ld_nzero)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != ZE) { + printf("FAIL: fxtract -0\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fxtract" : "=t" (ld_res), "=u" (ld_res2) : + "0" (ld_inf)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != 0) { + printf("FAIL: fxtract inf\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fxtract" : "=t" (ld_res), "=u" (ld_res2) : + "0" (ld_nan)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != 0) { + printf("FAIL: fxtract nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fxtract" : "=t" (ld_res), "=u" (ld_res2) : + "0" (ld_snan)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fxtract snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fxtract" : "=t" (ld_res), "=u" (ld_res2) : + "0" (ld_invalid_1.ld)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fxtract invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fscale" : "=t" (ld_res) : "0" (ld_min), "u" (ld_max)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (OE | PE)) { + printf("FAIL: fscale overflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fscale" : "=t" (ld_res) : "0" (ld_max), "u" (ld_nmax)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (UE | PE)) { + printf("FAIL: fscale underflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fscale" : "=t" (ld_res) : "0" (ld_zero), "u" (ld_inf)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fscale 0 inf\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fscale" : "=t" (ld_res) : "0" (ld_inf), "u" (ld_ninf)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fscale inf -inf\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fscale" : "=t" (ld_res) : "0" (ld_one), "u" (ld_snan)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fscale 1 snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fscale" : "=t" (ld_res) : "0" (ld_snan), "u" (ld_nan)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fscale snan nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (ld_invalid_1.ld), "u" (ld_one)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fscale invalid 1\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (ld_invalid_1.ld), "u" (ld_nan)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fscale invalid nan\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (1.5L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: fbstp 1.5\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (999999999999999999.5L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fbstp 999999999999999999.5\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-1000000000000000000.0L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fbstp -1000000000000000000\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_inf) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fbstp inf\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_nan) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fbstp nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_snan) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fbstp snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_invalid_1.ld) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fbstp invalid\n"); + ret = 1; + } + + return ret; +} diff --git a/tests/tcg/i386/test-i386-fpatan.c b/tests/tcg/i386/test-i386-fpatan.c new file mode 100644 index 0000000000000000000000000000000000000000..7f1f9853defdb6079bf6b28cf3ab286fb1e61e9d --- /dev/null +++ b/tests/tcg/i386/test-i386-fpatan.c @@ -0,0 +1,1071 @@ +/* Test fpatan instruction. */ + +#include + +struct test { + long double arg0, arg1, down, up; +}; + +const struct test tests[] = { + { -__builtin_infl(), -__builtin_infl(), -0x2.5b2f8fe6643a46ap+0L, -0x2.5b2f8fe6643a469cp+0L }, + { -__builtin_infl(), -1.0L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -__builtin_infl(), -0.0L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -__builtin_infl(), 0.0L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -__builtin_infl(), 1.0L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -__builtin_infl(), __builtin_infl(), 0x2.5b2f8fe6643a469cp+0L, 0x2.5b2f8fe6643a46ap+0L }, + { -1.0L, -__builtin_infl(), -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -1.0L, -0.0L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -1.0L, 0.0L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -1.0L, __builtin_infl(), 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0.0L, -__builtin_infl(), -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0.0L, -1.0L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0.0L, -0.0L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0.0L, 0.0L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0.0L, 1.0L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0.0L, __builtin_infl(), 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0.0L, -__builtin_infl(), -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0.0L, -1.0L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0.0L, -0.0L, -0.0L, -0.0L }, + { 0.0L, 0.0L, 0.0L, 0.0L }, + { 0.0L, 1.0L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0.0L, __builtin_infl(), 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 1.0L, -__builtin_infl(), -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 1.0L, -0.0L, -0.0L, -0.0L }, + { 1.0L, 0.0L, 0.0L, 0.0L }, + { 1.0L, __builtin_infl(), 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { __builtin_infl(), -__builtin_infl(), -0xc.90fdaa22168c235p-4L, -0xc.90fdaa22168c234p-4L }, + { __builtin_infl(), -1.0L, -0.0L, -0.0L }, + { __builtin_infl(), -0.0L, -0.0L, -0.0L }, + { __builtin_infl(), 0.0L, 0.0L, 0.0L }, + { __builtin_infl(), 1.0L, 0.0L, 0.0L }, + { __builtin_infl(), __builtin_infl(), 0xc.90fdaa22168c234p-4L, 0xc.90fdaa22168c235p-4L }, + /* Randomly generated tests. */ + { -0x4.1481697ac693aa6p-4L, 0xd.84a873b14b9c0e2p-4L, 0x1.dd2a294db671468ep+0L, 0x1.dd2a294db671469p+0L }, + { 0x5.51ee0c58f7fbf45p-4L, -0x3.a11abadbd605d354p-4L, -0x9.942ec5a1e6d706ap-4L, -0x9.942ec5a1e6d7069p-4L }, + { -0x5.4459f2ac77bb0978p-4L, -0xb.79bece734a62216p-4L, -0x2.004758bce8469e14p+0L, -0x2.004758bce8469e1p+0L }, + { 0x2.aad23e7bdccbd71p+352L, 0xb.8204e63359a46e6p-4L, 0x4.5081cdc076384b38p-356L, 0x4.5081cdc076384b4p-356L }, + { 0x1.b8e650cae035d26ap+72L, -0x1.6296e8ff499827a2p-4L, -0xc.de2b934dfff2be5p-80L, -0xc.de2b934dfff2be4p-80L }, + { -0x8.3e49377820195c8p-4L, 0x7.ece8699d62a9f76p-4L, 0x2.6037dbebdbb2fd48p+0L, 0x2.6037dbebdbb2fd4cp+0L }, + { -0x4.b875c0342c9f86b8p-4L, 0xe.a37e0fa859e499cp-4L, 0x1.e1fb3a96e1e2071p+0L, 0x1.e1fb3a96e1e20712p+0L }, + { -0x7.23210d9474f0715p-4L, 0xb.755e74862e61e2bp+116L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xd.2330923899aae43p-76L, 0xa.9a331b76f8ece94p+16L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x2.c18975d92e49e91p+72L, 0xa.d41581f0036d233p-4L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x4.84a87d8107c5f408p-4L, -0x4.69649643801fe8p-5424L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x2.72f96b27827d2054p-4L, 0x8.34634eae18e60c5p-4L, 0x1.47dcc6c860bbdaf8p+0L, 0x1.47dcc6c860bbdafap+0L }, + { 0x5.ed9ff299ffca609p-4L, 0x1.f03bcdeac4b1ed28p-4L, 0x5.0e6d2d3ad020af98p-4L, 0x5.0e6d2d3ad020afap-4L }, + { -0x1.838e5531eee660a2p+100L, -0x9.6eacf3012c77e7p-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x4.962ce97c4afbc1f8p-4L, -0xa.a7735b993f17f55p-4L, -0x1.fa318fa84cd3d3c6p+0L, -0x1.fa318fa84cd3d3c4p+0L }, + { 0x5.155f76560f08fccp-4L, 0xd.32a453289bd47b3p-4L, 0x1.340095b1ff56c6e8p+0L, 0x1.340095b1ff56c6eap+0L }, + { 0xa.9942e7418052b4bp-4L, -0x5.4f4efad2aff4f76p-4L, -0x7.6e5556d70c57ac08p-4L, -0x7.6e5556d70c57acp-4L }, + { 0x3.c9e289d962998608p-4L, 0x3.e614ab44b3c3b858p+88L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x1.51f8f83e548cc4d8p-32L, -0x8.a1d9201d5f09ad6p-4L, -0x1.921fb541d06114b2p+0L, -0x1.921fb541d06114bp+0L }, + { 0x7.5b8ee6778ad1d64p-4L, 0x9.d20d0f7fc98548p-4L, 0xe.d84441fe9061ea4p-4L, 0xe.d84441fe9061ea5p-4L }, + { 0x2.f89af40f713046ap+44L, -0x5.d981a42b6b7a36fp-4L, -0x1.f805944fa81791f6p-48L, -0x1.f805944fa81791f4p-48L }, + { 0x1.5dbffc603b717c16p-12056L, 0x4.5a026d37f55f1d18p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x7.82c193b48128193p-4L, -0xd.2d0fe1cd05a87f4p-4L, -0x2.16c178d148863734p+0L, -0x2.16c178d14886373p+0L }, + { 0x1.785253e54547193cp-128L, -0x4.51babb72810e518p-104L, -0x1.921fb4ed226f9e3ep+0L, -0x1.921fb4ed226f9e3cp+0L }, + { 0xb.638d8454a685474p-4L, -0x5.cf6274f9336e7248p+88L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xe.4b7a4c83290855cp+5104L, 0x3.c4fb25edb13c5e9cp-96L, 0x4.3816d5c0af96b0f8p-5204L, 0x4.3816d5c0af96b1p-5204L }, + { -0x1.c6f68bc53960adep+112L, -0xd.36a9965916287d1p-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x6.b3a10f94dcd70e1p-4L, 0xc.8517674f15bbcbfp-4L, 0x1.144e7f18ba67b4fep+0L, 0x1.144e7f18ba67b5p+0L }, + { -0xb.204e5335e697f73p-4L, 0x8.913a951884085ddp-4L, 0x2.7c439b7e5e590704p+0L, 0x2.7c439b7e5e590708p+0L }, + { -0x4.5861903e9a2c5178p-4L, -0x5.24585590086993p-4L, -0x2.45bcbee2a405a1d4p+0L, -0x2.45bcbee2a405a1dp+0L }, + { -0xf.2ba8f23d35f13f9p-4L, 0xa.3ecdb386b33fbe5p-4L, 0x2.8c2ffc8ed89a67b4p+0L, 0x2.8c2ffc8ed89a67b8p+0L }, + { 0x9.9b8e544f05c6de4p-8L, -0x7.abd5585035c4696p-4L, -0x1.7e2035d4e6006922p+0L, -0x1.7e2035d4e600692p+0L }, + { 0x5.732a72e50e0e8fd8p-136L, 0x7.8b963b5c9698ae88p+112L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0xb.ea47beace8589dep-4L, -0x3.8f66d5a2d60e1fc8p-4L, -0x2.d9eb1ca9b45b3eacp+0L, -0x2.d9eb1ca9b45b3ea8p+0L }, + { -0xc.694faa89b4055cp+100L, -0x8.6659e1a891ccbd3p-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x4.a571a0831166accp+14352L, -0x9.b8fe7ab721fb04cp-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x4.ee554b54200eeb18p-4L, -0x1.e1d0727b5f12c23cp-8L, -0x6.1b1657327a7313d8p-8L, -0x6.1b1657327a7313dp-8L }, + { -0x1.1e6c6f9d4f73617p-140L, 0x2.f3202c602060bd7cp-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0xc.cdb9d9e3a3a5b61p-4L, 0x5.7ddc79efb147e828p-4L, 0x2.bc857c5ac09c3d04p+0L, 0x2.bc857c5ac09c3d08p+0L }, + { -0x6.7236b6f8976437ap-4L, 0x5.e1ad137b44bc3ad8p-4L, 0x2.66e6f8a4616f47f8p+0L, 0x2.66e6f8a4616f47fcp+0L }, + { -0xb.f5ec1a26fcc9d7ep-4L, -0x3.772e0998925d6c78p-152L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x1.a983e64980e6104p-4L, 0xa.14ebef82079ff92p-4L, 0x1.684b277673a26358p+0L, 0x1.684b277673a2635ap+0L }, + { 0x1.e4fcc97f32b404d8p+13860L, -0x1.d272224db03bbe4ap-88L, -0xf.6367c3b63ab282p-13952L, -0xf.6367c3b63ab281fp-13952L }, + { 0xb.83be497f42b1776p-8L, -0xb.6c13349b9671c7bp-4L, -0x1.8204013b36ec0acp+0L, -0x1.8204013b36ec0abep+0L }, + { -0xd.00d476fab7a907dp-4L, 0xe.fce5159bb4f9691p+128L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0xe.94e55595d939aa4p-4L, 0x8.66a9b0853e6c06ep-4L, 0x2.9e7077a5a9177248p+0L, 0x2.9e7077a5a917724cp+0L }, + { 0x5.431e650334b97d18p-4L, 0xf.1eb2c535e06fba3p-4L, 0x1.3c627af215641846p+0L, 0x1.3c627af215641848p+0L }, + { -0x8.54a857fb1034b62p-4L, -0xa.d3c15d582c446d9p-4L, -0x2.3a035e85ad032918p+0L, -0x2.3a035e85ad032914p+0L }, + { -0xc.cb73edcbfcb307fp-4L, 0xf.ed87c6cb3cd7d83p-84L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x1.3afd6b8a17918c64p+48L, -0x4.d312891f5f4e786p-4L, -0x3.243f6a8885a2ca18p+0L, -0x3.243f6a8885a2ca14p+0L }, + { 0xe.ae0633b99b178edp-4L, -0x1.39568b7ef55672cp-4L, -0x1.54bad5d8d44c04e4p-4L, -0x1.54bad5d8d44c04e2p-4L }, + { 0x4.cf293b1353f539bp-4L, 0x6.95c54f0009329c5p+116L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x5.b5eb2a3dcc35826p-5716L, -0xa.db19f19a7ea88bep-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x1.09017c7c80c2c48ap-4L, -0x2.5ae089add9bdff18p-4L, -0x1.281a477bf785850cp+0L, -0x1.281a477bf785850ap+0L }, + { -0x6.d211b21df46dcc18p-56L, 0xd.1a64a16c7c8f6d7p-4L, 0x1.921fb54442d18cbcp+0L, 0x1.921fb54442d18cbep+0L }, + { -0xc.1ef9ffac1d2c793p-4L, 0x1.67c59b4c06bd7496p-4L, 0x3.06b2add391c9eb78p+0L, 0x3.06b2add391c9eb7cp+0L }, + { -0x4.5d25a7f57110a158p+268L, -0x2.6c4fbdad444416d8p-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0xb.03fa4c349a339d2p-9120L, 0x1.e57ddc8153f3ba8p-8L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x1.9385036afefa239p+6960L, -0x6.8fac6e3f60b61e1p-4L, -0x4.299d61fcfb4de92p-6964L, -0x4.299d61fcfb4de918p-6964L }, + { -0x3.65bed5b32d99326p+1832L, 0x2.3ef31cc65b2354cp-4L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x2.bceec8bc1d31b0ccp-4L, 0xd.146217a63673958p-4L, 0x1.c6f361fb1067b388p+0L, 0x1.c6f361fb1067b38ap+0L }, + { 0x2.17b7fc97b1f46e7cp-4L, -0x4.49abbcdefc0c959p-4L, -0x1.1de39755c8eb62aep+0L, -0x1.1de39755c8eb62acp+0L }, + { -0x3.efc6f5f489c6c7bcp-4L, 0x8.f7ff40b96f9bd91p+92L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x6.003126d0e9a9acc8p-4L, -0x5.7be9edcc9dc2a02p-4L, -0x2.66b21a740cac5bf4p+0L, -0x2.66b21a740cac5bfp+0L }, + { -0x7.8952a49ff2c2f168p-4L, -0x1.c53227e2b7ce8fd8p-100L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0xf.c1271b0a53a3319p-4L, -0x2.281fdd0bca98746p+36L, -0x1.921fb5443b837dc2p+0L, -0x1.921fb5443b837dcp+0L }, + { 0xf.ce2fc60abd9a47cp-4L, 0x9.e8a3a1c0f885e07p-4L, 0x8.f5ad0c8c16696eap-4L, 0x8.f5ad0c8c16696ebp-4L }, + { 0x6.88e09aba14bbc208p-28L, 0x2.0051253b7bd07004p+9792L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x5.244b484bc9bb7828p-4L, -0x7.02ec4c8b2cc95998p-4L, -0xf.02379007abbea58p-4L, -0xf.02379007abbea57p-4L }, + { -0xa.4d34be63f5bedffp-4L, 0xf.be786c39b309e8p-4L, 0x2.26738a0739adbffcp+0L, 0x2.26738a0739adcp+0L }, + { -0x6.16481538d3215558p-4L, 0x8.5ea05eecb9ac14dp-4L, 0x2.3318a84b9fd18a38p+0L, 0x2.3318a84b9fd18a3cp+0L }, + { -0xd.4be5b4aaf95a52bp-4L, 0x5.505294ddb8af9558p-4L, 0x2.c2eb12ab368a9a94p+0L, 0x2.c2eb12ab368a9a98p+0L }, + { -0x1.f45f2a814c98f34p+80L, 0x2.b68cfa7df5a80aep-4L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x1.71591c964a8836a6p+16L, 0x2.047a032c2a353b58p-4L, 0x3.243f5428e50fb82cp+0L, 0x3.243f5428e50fb83p+0L }, + { -0x8.eb2ab17c06312d9p-4L, 0xb.932fffb0dfd7537p-4L, 0x2.3a3007c5cc9e7d3cp+0L, 0x2.3a3007c5cc9e7d4p+0L }, + { -0x1.3839b004fc949e6cp-120L, 0xa.7fafcf461e92982p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x6.41b8cd66b9392ef8p-4L, 0xf.d372339bf2bef0fp-4L, 0x1.f28133bb63853c52p+0L, 0x1.f28133bb63853c54p+0L }, + { -0xf.843d63b0a71eb93p-4L, -0xe.679784396815117p-4L, -0x2.64b1d552e74bdb24p+0L, -0x2.64b1d552e74bdb2p+0L }, + { -0x1.6be25f7b2bbfc3p-4L, -0xf.e1c7160797d7709p-4L, -0x1.a8f98c5e679f44fep+0L, -0x1.a8f98c5e679f44fcp+0L }, + { -0x9.f6c4eb5c911111ap-4L, -0xa.08c53e65e98b067p-4L, -0x2.5a492049a9cbbe7p+0L, -0x2.5a492049a9cbbe6cp+0L }, + { -0x4.1a4c613ba5fe16ap-4L, -0xd.36e91d3e54f0432p-4L, -0x1.df30682153ea13e8p+0L, -0x1.df30682153ea13e6p+0L }, + { -0xd.1de964de30857a7p-4L, -0x8.604a0e63d4f5df1p-4L, -0x2.92c30d3b7d0de73cp+0L, -0x2.92c30d3b7d0de738p+0L }, + { 0xc.6b9d18c70882d52p-4L, -0x2.711b4139fbed3dc8p-11492L, -0x3.254433723f77f3bcp-11492L, -0x3.254433723f77f3b8p-11492L }, + { 0x9.4021cab7a0d78bbp-4L, 0x8.305eb92b4243ea2p-4L, 0xb.97f7af5268b8f8fp-4L, 0xb.97f7af5268b8f9p-4L }, + { -0x4.f0330cdb93893948p-4L, 0xe.be93c7764505ff9p-8L, 0x2.f504ddece3874ccp+0L, 0x2.f504ddece3874cc4p+0L }, + { -0xd.ea533ffe043e52bp+2296L, 0x1.1dd2693fe11489c2p-4L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { 0x2.0397d0e9676f1b2p-4L, 0x5.48015a56bb1ddbep-136L, 0x2.9f4ab0b2d7a99144p-132L, 0x2.9f4ab0b2d7a99148p-132L }, + { -0x1.9a52d244a51432cep-80L, -0xd.c27cd78e0864371p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x9.c7f27c2034ec1cfp-4L, -0xa.a9e0aa658eda7dcp-4L, -0x2.50244d2439996p+0L, -0x2.50244d2439995ffcp+0L }, + { 0x1.403075ad6be49e48p+104L, 0x8.2f7e9e49692fd28p-4L, 0x6.8b6793c6b839addp-108L, 0x6.8b6793c6b839add8p-108L }, + { -0xa.93e861896961066p-4L, -0xd.4c10bf60bb97196p-4L, -0x2.3e2700333180df34p+0L, -0x2.3e2700333180df3p+0L }, + { 0x4.ff124c9911f2538p-4L, -0x8.776b58ba7268d9ep-4L, -0x1.09a4306282277e7p+0L, -0x1.09a4306282277e6ep+0L }, + { -0x4.db7b68b78ebb30a8p-80L, -0x9.b667363949a8b6dp-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x9.799737c602ebc35p-12L, -0x4.ee069c6928cc872p+68L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xa.8eb47109f6336a7p+7944L, 0x6.e3c54639ed929cp-16L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x7.c5f3d0d9d9db89cp-4L, 0x1.6b364994830303c2p-4L, 0x2.f607d4a28c7c5d2p+0L, 0x2.f607d4a28c7c5d24p+0L }, + { -0x4.2513fed56a721cp-4L, 0x3.e183251bd312b9f8p-4L, 0x2.6399f4ee48a52b1p+0L, 0x2.6399f4ee48a52b14p+0L }, + { 0x5.372c1f6cb3bb4cep-8L, 0xc.30d4cc265a07403p-4L, 0x1.8b47c0312064586p+0L, 0x1.8b47c03120645862p+0L }, + { 0xf.7e3aa552d45b234p-4L, -0x3.9a644e95053aaf1cp-4L, -0x3.a7ef5825b5df9e1p-4L, -0x3.a7ef5825b5df9e0cp-4L }, + { 0xe.85839cd58ef2c75p-4L, 0x1.e2027a063163b7ap+92L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xd.d9ee24413681697p+96L, -0x1.a0688ee2096f86eap-148L, -0x1.e10130aa540fdb18p-248L, -0x1.e10130aa540fdb16p-248L }, + { -0x5.0487ddb4070bf26p-4L, 0xb.41c4c871bf58078p-64L, 0x3.243f6a8885a308acp+0L, 0x3.243f6a8885a308bp+0L }, + { -0x4.cfd480a28c2b6b48p-4L, 0x1.8657dd64795c35ap-4L, 0x2.d5b053c0ec2d5304p+0L, 0x2.d5b053c0ec2d5308p+0L }, + { -0x1.262cb60430e5eb9ep-4L, 0x8.0e85fe0bcf8a253p-4L, 0x1.b66463ab64833336p+0L, 0x1.b66463ab64833338p+0L }, + { -0x3.cefbd3ecacf92c44p-4L, -0x5.f20def7196dea63p-4L, -0x2.23f8c03324b67e44p+0L, -0x2.23f8c03324b67e4p+0L }, + { 0x1.3a394f91198290bcp-4L, -0x5.fa0cb4bdfd2d7318p-4L, -0x1.5e454070508e5eap+0L, -0x1.5e454070508e5e9ep+0L }, + { 0x4.08cc4ee18d971c48p-4L, -0xc.08ff29dce9d081fp-4L, -0x1.3f5281f2c773c0bap+0L, -0x1.3f5281f2c773c0b8p+0L }, + { 0x1.109cf51c23d9c444p-3868L, 0x6.d5822da15531716p-12L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x5.b4cccaf7aee9cd6p-4L, 0xd.08cda37bcd9c8cp-4L, 0x1.287c57a28064102cp+0L, 0x1.287c57a28064102ep+0L }, + { -0xb.d7f74d7d0014f61p-4L, -0xa.7263655e0a0ea62p-4L, -0x2.6b34e32fa133c618p+0L, -0x2.6b34e32fa133c614p+0L }, + { -0x2.47b34fa6f1ad5d68p-4L, -0x4.7e5d88e1178a73b8p+136L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x3.e49a34d2590d3414p-148L, 0x6.90a7904ae1f6ca48p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xf.e7cc8c0c8fca8d6p-4L, 0xb.5766572c78c1636p-4L, 0x9.e930d3e45526457p-4L, 0x9.e930d3e45526458p-4L }, + { -0x3.84138ca9f496d498p+24L, -0x3.83d9c130d6f21f6p-92L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x3.622e5c923b06d66cp-8L, 0x8.911302b7a344f8ap-4L, 0x1.987124e672754176p+0L, 0x1.987124e672754178p+0L }, + { -0x2.a91a430d68680b6cp-132L, -0x8.87063dd41e8a8bbp-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x4.e1420e7e82cd22dp-4L, 0x5.ed8fe0a77cf3d518p-14676L, 0x1.36fb35f69a850f64p-14672L, 0x1.36fb35f69a850f66p-14672L }, + { -0xc.8346ca25bd9f342p-4L, 0xa.8b2343cd8095adcp-10960L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { 0x2.b32d8027c5516654p-3772L, 0x6.fd1366df02fe9c5p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x6.c090b4e367d6c7ep-8L, -0x5.081c001c09df9f3p-4L, -0x1.7cb3f4f28e98b0c6p+0L, -0x1.7cb3f4f28e98b0c4p+0L }, + { -0x3.fcb8a555a704d93cp-112L, -0x1.920119c347818b36p+4120L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x4.f7a55e6bfc734b5p-132L, 0x9.188a26a4beb414p+116L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xb.ff33c19f0cbb73p-4L, 0x1.d50d6b459087ecdp-4L, 0x2.6cc4d1a540b1449cp-4L, 0x2.6cc4d1a540b144ap-4L }, + { 0x6.0dd96d442bc44b28p-4L, -0x3.e88917f9e6c0bb2p-4L, -0x9.2c0cc2bcd1b42bcp-4L, -0x9.2c0cc2bcd1b42bbp-4L }, + { 0xf.e9c0adcf6e6ebaap+80L, -0xe.6049cc9d4ea9c32p-8L, -0xe.746309506e28c41p-92L, -0xe.746309506e28c4p-92L }, + { -0xd.e0ca0ae677c56c7p-4L, -0x3.b604528c1bde4ca8p-4L, -0x2.e15bb2ef66714438p+0L, -0x2.e15bb2ef66714434p+0L }, + { 0x9.3e94ea277274ab3p-4L, 0xf.ec080621a8d9456p-4L, 0x1.0b752d4e563c12fp+0L, 0x1.0b752d4e563c12f2p+0L }, + { 0x1.96ef7e6b80e63adep-4L, 0x5.fa153b3eb3b0779p+984L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x2.c1491ea7eb7b418p+220L, -0x2.5fa1d9a3a5a2b664p-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x1.f7142c3edd746312p-76L, 0xb.79a14c17c57922dp-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x9.9b19d045170086ap-4L, -0xd.65fbae6f453f5a2p-4L, -0x2.315b8727ceee88f4p+0L, -0x2.315b8727ceee88fp+0L }, + { 0xc.7a9e15e82248878p-4L, 0x3.f5ec8986cfd785dp-4L, 0x4.ead1f3dda3a04a3p-4L, 0x4.ead1f3dda3a04a38p-4L }, + { -0x2.94c306c1808e3c18p+44L, -0x3.aa0cc319c013919p-4L, -0x3.243f6a8885a19d68p+0L, -0x3.243f6a8885a19d64p+0L }, + { -0xf.0292f4401d18d5cp-4L, -0x1.bf51089c520b29b4p-4L, -0x3.0694831553eb506p+0L, -0x3.0694831553eb505cp+0L }, + { -0x3.338096c5b380a194p+5592L, -0x5.35b41b797fb9331p-56L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x9.620bcddbdd20a79p-4L, 0x4.17376606afdde85p-4L, 0x6.93f7056b927052fp-4L, 0x6.93f7056b927052f8p-4L }, + { 0xd.1dc39e358b023ap-4L, 0xb.13430c035931444p-4L, 0xb.383ae5cd743ce8ap-4L, 0xb.383ae5cd743ce8bp-4L }, + { 0x3.606617a1673d0184p-4L, -0x8.f017932d188a998p-4L, -0x1.35a7a5999089613cp+0L, -0x1.35a7a5999089613ap+0L }, + { -0xf.3ce660b2bbefc26p-80L, -0x1.8dad3bd8dae62b26p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xf.d53ec036950502fp-4L, -0x2.a72c3e3aead35fep+14616L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x4.9ff6d398cf5c723p-4L, 0x3.c7ea3c3c2b39e2c8p+56L, 0x1.921fb54442d18454p+0L, 0x1.921fb54442d18456p+0L }, + { 0xf.7206b4c8d50f316p-4L, 0x7.5f74c3dd6c9936dp-4L, 0x7.203659231b6ebf78p-4L, 0x7.203659231b6ebf8p-4L }, + { 0x1.d1a5048e1cfadea8p-4L, 0xe.8f9244700df6721p-4L, 0x1.724f343754e1f6c2p+0L, 0x1.724f343754e1f6c4p+0L }, + { 0x3.99c86ae38d72f47cp-4L, 0x1.78aa249a87ca9a7ep-4092L, 0x6.89bb9c00e2992908p-4092L, 0x6.89bb9c00e299291p-4092L }, + { 0x9.638122087011d7dp-4L, 0xc.4c4e12b06f42474p-4L, 0xe.b33a0191f01596ap-4L, 0xe.b33a0191f01596bp-4L }, + { 0x1.ef067fd567660c6ep+124L, 0x6.c87c79c7f39458b8p-4L, 0x3.8203f86101129a1p-128L, 0x3.8203f86101129a14p-128L }, + { 0x1.7ae1a02b6be082e8p-96L, 0x6.a546c7e5065f0158p-112L, 0x4.7d81cd7fc2b19b08p-16L, 0x4.7d81cd7fc2b19b1p-16L }, + { -0x6.f866735c25236f98p-4L, -0x6.48ac3faff9ac8af8p-148L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x1.62b2ac359758568p-124L, 0xa.a22cceb5d16a7b9p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x7.9bb3d37308387268p-4L, -0xc.186ea423cfbc56dp-4L, -0x2.21dcf2dcca126d7p+0L, -0x2.21dcf2dcca126d6cp+0L }, + { 0x9.e5f3c3ae26d0dd6p-44L, -0x1.5803a5d39e417564p-4L, -0x1.921fb5443b73dd0ep+0L, -0x1.921fb5443b73dd0cp+0L }, + { -0xc.a52f12f15058ap-8L, -0x3.e058d43b80e19b7cp+32L, -0x1.921fb5444614a0ap+0L, -0x1.921fb5444614a09ep+0L }, + { -0x7.810b603203760db8p-4L, 0xd.d38ca8b0ca1dddfp-140L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x3.e726a67b179e572p+5396L, -0xc.d26229e318f0c64p-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x8.457740622adf15fp-4L, -0x7.492c117c47e7f31p-4L, -0xb.8ddcb5e4e618633p-4L, -0xb.8ddcb5e4e618632p-4L }, + { 0xb.b13b38b2bab98c4p-4L, -0xc.05a51372a620cc3p-4L, -0xc.c9f0d2797fe328dp-4L, -0xc.c9f0d2797fe328cp-4L }, + { -0xf.52d7c0f49c1b5a4p-4L, 0x6.c87dc3726b00027p-112L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x1.5c0865fc4e06a84ep-4L, 0xa.2dfc5d1f96be4bcp-4L, 0x1.b41ca3f2a679e626p+0L, 0x1.b41ca3f2a679e628p+0L }, + { -0x3.f497fcccc60e3828p+60L, 0x1.dd126ec3b3b24d64p+116L, 0x1.921fb54442d18688p+0L, 0x1.921fb54442d1868ap+0L }, + { 0x5.03f2d9b66abed898p-4L, 0xd.e1d2b8730f8408fp-4L, 0x1.395ec39fa3cbe086p+0L, 0x1.395ec39fa3cbe088p+0L }, + { -0x3.8052f809aaac9b64p-4L, 0xf.ad374726f5b37c2p+16L, 0x1.921fb8d713091e94p+0L, 0x1.921fb8d713091e96p+0L }, + { 0x3.48836233e960d588p-4L, -0x8.af10e3af7480717p-4L, -0x1.35961a95496c7024p+0L, -0x1.35961a95496c7022p+0L }, + { 0x4.d09e474f01f1a2d8p-72L, 0x2.956954f33db8ba84p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0xe.05c36356f1cc00bp-4L, -0x1.30a38fe2fc6ef3d6p-120L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x8.98fecd06210c28ep-8L, -0xa.944a9ff08e89db6p-4L, -0x1.8521cc1c24d70946p+0L, -0x1.8521cc1c24d70944p+0L }, + { -0xf.069ae41b6f97acbp-4L, -0x2.849c2bec428d3088p-4L, -0x2.f9be11bfeff191ep+0L, -0x2.f9be11bfeff191dcp+0L }, + { 0x1.ddc053fcc0b29fc6p-2068L, -0xe.aa11ca5025d7161p+352L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xe.30a7bdb7d22b3c9p-4L, -0x6.8b8840cf7db54858p+5320L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xc.289ab032c02ec2bp+96L, -0x2.4f1d0f8cfd43ef8cp+68L, -0x3.243f6a857bc45af8p+0L, -0x3.243f6a857bc45af4p+0L }, + { 0xc.b983cae10f7203p-4L, 0xb.7422dd3d2b45dc5p-4L, 0xb.b9dea242a2b569ap-4L, 0xb.b9dea242a2b569bp-4L }, + { -0xa.fbaa8d616ab8d1dp-4L, -0xe.926ef7c0fa60c33p-4L, -0x2.37778ac56a06051p+0L, -0x2.37778ac56a06050cp+0L }, + { 0xf.80c7c99d2c6404cp-4L, -0x7.2aac6d2a68c490bp+8L, -0x1.91fd18c483c4059ap+0L, -0x1.91fd18c483c40598p+0L }, + { -0xe.80d9a3a08faf173p-4L, -0x8.400e8efd60a398p-4L, -0x2.9fd8298eb95656f4p+0L, -0x2.9fd8298eb95656fp+0L }, + { -0x1.e30b1be4461dcf88p+212L, -0xc.2454aa891f5dba1p-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x1.6492e0fa29711f58p+104L, 0x3.a0caae204aa84214p-4L, 0x2.9ad20bbc8b5aa404p-108L, 0x2.9ad20bbc8b5aa408p-108L }, + { 0x6.db2d4dd8afa84408p-4L, 0x8.7fd39596a804d49p-80L, 0x1.3d5a80194777316p-76L, 0x1.3d5a801947773162p-76L }, + { 0x3.f16bc38197cbac4cp-104L, -0xb.2a83d184147cfdcp-96L, -0x1.91c54eb36a10602cp+0L, -0x1.91c54eb36a10602ap+0L }, + { 0xa.e2eae99c9fd7478p-4L, -0x2.36e2a96b54e59b58p-4L, -0x3.35f38d6e0b59fa84p-4L, -0x3.35f38d6e0b59fa8p-4L }, + { 0x3.0a86465998f852dp+128L, -0x1.43ec0bdd98b0f80cp-112L, -0x6.a83ada10badb8dep-244L, -0x6.a83ada10badb8dd8p-244L }, + { 0x6.883e7a1d34914268p-4L, 0xb.88a85700deb5549p-4L, 0x1.0e344a89b3d1ea2ep+0L, 0x1.0e344a89b3d1ea3p+0L }, + { -0xf.2b2a3a311948993p-4L, -0x3.06fe2a10fe55267cp-4L, -0x2.f1d184e7e8b146b8p+0L, -0x2.f1d184e7e8b146b4p+0L }, + { -0xd.de264368cd7459ap-4L, 0x5.567777c9aa2124c8p-4L, 0x2.c62fd64a3dffbda4p+0L, 0x2.c62fd64a3dffbda8p+0L }, + { -0x1.935a9217a5a3024p-4L, 0x7.3ccc7fe1d42ad228p-4L, 0x1.c8ffb02ef3152e56p+0L, 0x1.c8ffb02ef3152e58p+0L }, + { -0x4.bbff6d1fef17b4c8p-4L, -0x1.4134a05ac2afda6p+20L, -0x1.921fb90a3855426ep+0L, -0x1.921fb90a3855426cp+0L }, + { 0x5.265fe49d84076a68p-4L, -0xc.103986b2d38539dp-4L, -0x1.2ad51c99871cfe42p+0L, -0x1.2ad51c99871cfe4p+0L }, + { -0x2.e02038211a5e1a1cp+84L, 0x2.66bb0943c921a184p-4L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x7.5a723c24f0c64ebp-4L, 0x3.c761bdd9cf2def2cp-4L, 0x2.aab94e7e66bac71cp+0L, 0x2.aab94e7e66bac72p+0L }, + { -0x7.cf59e52998194478p+128L, -0xe.780c3928a522b73p-12L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x6.1dfcef356d3841p-4L, 0x3.4828bdd2a081f3ep-4L, 0x7.e0f6aac2c77ae808p-4L, 0x7.e0f6aac2c77ae81p-4L }, + { 0xb.dde4e379662aeeap-4L, 0xb.0226291c9bc5964p-4L, 0xb.f75cd67c86afa4cp-4L, 0xb.f75cd67c86afa4dp-4L }, + { -0xd.bf9a0da9faa3504p-4L, -0x5.c1892b0fafe1dc68p-4L, -0x2.bebed8f131223be4p+0L, -0x2.bebed8f131223bep+0L }, + { 0x1.44812a3159648466p-4L, 0xd.9d71d57ae36f89fp+1968L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x1.e8e8f49835eaacb8p-4L, 0x9.eac5efdf2c187bdp-4L, 0x1.c2d3d0e12540c0eep+0L, 0x1.c2d3d0e12540c0fp+0L }, + { 0xf.8a9cd502481f327p-4L, -0x2.9371a4cdcbd8ac4p-4L, -0x2.a0c8bb47d0fe5554p-4L, -0x2.a0c8bb47d0fe555p-4L }, + { 0xf.ec9e23f6d0a3bd2p-4L, -0x2.5fd5f4e23c3210e4p+108L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x1.80a14974eabf910ap-152L, -0x4.c2d0568402546a5p-8L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xc.976222dd345048p-68L, -0xd.6563e961e96fd5dp-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x9.e03ff635ae5b0afp-8912L, -0xa.42b9f1752ebee14p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x6.4ef2060125bf954p-4L, 0x1.949b3c6ad95e7494p-128L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0xf.d085f6fba7aa194p+11308L, 0x9.8fa092c7be00f66p+52L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { 0x2.29f54bce824a24cp-8L, -0xa.b8f81b679b49916p-4L, -0x1.8ee524e86c1ee1e4p+0L, -0x1.8ee524e86c1ee1e2p+0L }, + { -0x2.dfa40c215498cf14p-4L, -0x2.ec02031137509e54p-4L, -0x2.590d4b9283e4bb88p+0L, -0x2.590d4b9283e4bb84p+0L }, + { 0xc.95b28af67c0d0fdp-4L, -0x3.8b937ee4a5ad9044p-4L, -0x4.64b9dc9fe48f2ca8p-4L, -0x4.64b9dc9fe48f2cap-4L }, + { 0x1.96c3f2d8373481fcp-128L, 0x5.32ac5f2f72c534e8p+7120L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x3.71a836d1385ea83cp+32L, -0x2.98de885b63ec9fap-4L, -0xc.10d9073a34cf0d8p-40L, -0xc.10d9073a34cf0d7p-40L }, + { -0x2.ec64d50f08792a24p-12L, 0x7.4a3ef749c24694d8p+144L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0xe.39d4437a92edbe2p+6624L, -0x7.e597e9edb98f8dd8p-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x5.b2db0149e01e772p-4L, -0xa.4e00c5865119715p-4L, -0x2.13718dc24c8ca814p+0L, -0x2.13718dc24c8ca81p+0L }, + { 0x3.2d5ce470bbbfc05p-4L, -0x6.fef503b2cde63e88p-4L, -0x1.24fdbd6081eb3d04p+0L, -0x1.24fdbd6081eb3d02p+0L }, + { -0x2.75c4d49c73c6b714p-4L, -0x2.6f4dc7f3b45d7874p+84L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x3.be464272e1460c8p-92L, -0xc.5760c2d01b802f5p+84L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x4.58042455b6631c78p-4L, -0xf.a5425993c2d22edp-4L, -0x1.d774099a530614d4p+0L, -0x1.d774099a530614d2p+0L }, + { -0x3.331c1dd1ed766244p-352L, 0x5.6352b9b11a14c48p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x5.eeff171b7925d048p-14368L, -0xf.ff0d58e82429fafp-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x9.bd53e4167e85b42p-4L, -0x5.4c28c9b0b345941p-4L, -0x2.a4b8051a75508798p+0L, -0x2.a4b8051a75508794p+0L }, + { 0x8.fef78aad41a1338p-4L, 0xf.25b2822b10d9f65p-4L, 0x1.08ed7bc61d7d73f2p+0L, 0x1.08ed7bc61d7d73f4p+0L }, + { -0x5.cd10c03bcaf10088p-8L, -0xa.a821812c5f53b52p-4L, -0x1.9ad4845fb36d2352p+0L, -0x1.9ad4845fb36d235p+0L }, + { 0x5.94e05ec04235ac68p-4L, -0xa.09752cd4a8e9c1dp-104L, -0x1.cc59396f222b7724p-100L, -0x1.cc59396f222b7722p-100L }, + { -0xd.167af1356c9c025p-4L, -0xf.d0cd204dbb8b533p-4L, -0x2.4318bedab39b9894p+0L, -0x2.4318bedab39b989p+0L }, + { 0xa.c0e5742f317f8a3p-4L, 0xe.2242314d427e9c1p-204L, 0x1.5078fcaf7a061e0cp-200L, 0x1.5078fcaf7a061e0ep-200L }, + { -0x2.37749e13337ef694p-4L, 0x4.8513915f54085e2p-4L, 0x2.06d9395eb203ac84p+0L, 0x2.06d9395eb203ac88p+0L }, + { 0xe.23a123d6d8bcffp+5256L, 0x5.25a1ebc2fc29f1cp+84L, 0x5.d30afa61156b2b38p-5176L, 0x5.d30afa61156b2b4p-5176L }, + { -0x2.4674afe3989b3a5p-72L, -0x1.5e3fb8c6c490f9b8p-100L, -0x3.243f6a7ee695750cp+0L, -0x3.243f6a7ee6957508p+0L }, + { -0xe.920450e2df4f23ep-4L, -0x7.8a913f4c29492cdp-4L, -0x2.a9facee71eddd834p+0L, -0x2.a9facee71eddd83p+0L }, + { 0xd.f18c68c5e57c1fep-4L, 0x6.4bf6a01053290c18p+100L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xd.65b50e81ed20864p+92L, 0x8.d86e55e3f0a94b1p-4L, 0xa.905826200246659p-100L, 0xa.90582620024665ap-100L }, + { -0x5.0308adabc4a020fp-4L, -0x2.a7d9b961e2c3089p-4L, -0x2.a7822a212eff89d4p+0L, -0x2.a7822a212eff89dp+0L }, + { -0xd.227d8e4d09d7251p-4L, 0x7.d5608278690935ap-4L, 0x2.9a9469fdb763be6cp+0L, 0x2.9a9469fdb763be7p+0L }, + { -0xe.81b27c03c76f499p-48L, -0x2.b154c8162bc04cb4p-4L, -0x1.921fb5444327b72cp+0L, -0x1.921fb5444327b72ap+0L }, + { 0x4.35ecdac82f2a93c8p-4L, -0x5.771325ed71c201dp-4L, -0xe.a11a21eaf4329d6p-4L, -0xe.a11a21eaf4329d5p-4L }, + { -0x5.eae159d6c2480c9p+32L, 0x5.121392f3a25f68p-4L, 0x3.243f6a8877ed3cf8p+0L, 0x3.243f6a8877ed3cfcp+0L }, + { 0x3.dcb9a65bf445eaccp+10876L, 0x1.778ccedfa82f4736p-4L, 0x6.13cb511c0ab34e3p-10884L, 0x6.13cb511c0ab34e38p-10884L }, + { 0xb.3cc3e4cc1b25c56p-4L, -0x6.76ae6ecaf0206ea8p-4L, -0x8.5a0330d0113839fp-4L, -0x8.5a0330d0113839ep-4L }, + { 0xe.22ec92ad54501adp-4L, -0x3.f615ff2adef13ae8p+56L, -0x1.921fb54442d18432p+0L, -0x1.921fb54442d1843p+0L }, + { -0x7.e9826b314600f95p-120L, 0x4.9a9641fa150c9178p+60L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xe.99b66de48e79158p-4376L, -0x5.c1e4a9cc5e3e83e8p+52L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x5.1ce62b8e10774afp-4L, 0x7.fa8931ceaf326ac8p-4L, 0x2.24045af1101a7c0cp+0L, 0x2.24045af1101a7c1p+0L }, + { 0x5.9b4e55550b4e7078p+112L, -0xa.954d79680ea5909p-4L, -0x1.e33a9f922fb03e88p-116L, -0x1.e33a9f922fb03e86p-116L }, + { 0xb.432563e5c37e78fp+108L, 0xa.950b0bb7d84c5b3p-4L, 0xf.08a83c251380dd2p-116L, 0xf.08a83c251380dd3p-116L }, + { 0x4.3e136fbe7e156658p-4L, 0xb.9930789b19cf8a8p-4L, 0x1.385a8b82e95fe408p+0L, 0x1.385a8b82e95fe40ap+0L }, + { -0x8.1697784edf6fe07p-8L, 0x2.e9849ddc62c0d374p-4L, 0x1.be1fa44b4ee5c01ep+0L, 0x1.be1fa44b4ee5c02p+0L }, + { 0xc.d570e244c0e60bep-4L, 0xf.15d04c531718d34p-4L, 0xd.da96e59bf70d9cfp-4L, 0xd.da96e59bf70d9dp-4L }, + { 0x1.e1200b8406eda8fep-4L, 0x1.e65664694a4c5354p-1032L, 0x1.02c5fcd18c965c48p-1028L, 0x1.02c5fcd18c965c4ap-1028L }, + { -0x9.2cb86254ecdfd09p-8L, -0x4.9982beb1a0f87638p-4L, -0x1.b1dfdabe0ce0405cp+0L, -0x1.b1dfdabe0ce0405ap+0L }, + { -0xe.45cc48c61fdc121p+40L, 0x4.e07d3709dbe3fep-4L, 0x3.243f6a88859d913cp+0L, 0x3.243f6a88859d914p+0L }, + { 0x5.653d42dac0a5219p-4L, 0x9.5f1aff673a041bcp-4L, 0x1.0c64c95c41e196a2p+0L, 0x1.0c64c95c41e196a4p+0L }, + { -0x8.bcd403a004e1a23p-4L, -0x8.1c9d05645c7987cp-4L, -0x2.64b0a8416a0a6878p+0L, -0x2.64b0a8416a0a6874p+0L }, + { 0xd.13a5ae9285d253dp-4L, 0x9.4cf62e7e77f656p-4L, 0x9.e4410391f565abdp-4L, 0x9.e4410391f565abep-4L }, + { -0x2.84d9c1bc69548254p-4L, -0x4.21ac0c75a3a7dbe8p-4L, -0x2.1e4985c908e36c6cp+0L, -0x2.1e4985c908e36c68p+0L }, + { -0xd.b9bd68e165f831p-4L, 0x8.3fd61ad578cd929p-4L, 0x2.99b53d1ee1512a74p+0L, 0x2.99b53d1ee1512a78p+0L }, + { 0xf.30d46d764112444p-4L, 0xb.cd4a73dc359d737p-4L, 0xa.916e2e87f1b749dp-4L, 0xa.916e2e87f1b749ep-4L }, + { 0x1.515f582a4522a614p-112L, -0x5.9e1738c1ccd8a9a8p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x2.92f5722be8168a3p+84L, -0x4.8e012f7d7878b01p-4L, -0x1.c4fbac335198d82cp-88L, -0x1.c4fbac335198d82ap-88L }, + { -0x1.6757eda9b94c8c8cp-6468L, -0xf.789b834a9491fb6p-308L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xf.f16a11b7efb26b4p-4L, 0x7.6980774d9eb5024p-4L, 0x2.b4d71146599f1ebcp+0L, 0x2.b4d71146599f1ecp+0L }, + { 0xc.52f873b5b0d54efp-8L, 0x2.b8137644250c4bbcp-4L, 0x1.4b748a8aaca4742cp+0L, 0x1.4b748a8aaca4742ep+0L }, + { 0x8.b13bd917a919d6p-4L, 0xd.a7e60f2da06694ep-4L, 0x1.0102ec7f8667321ap+0L, 0x1.0102ec7f8667321cp+0L }, + { -0x9.6d66afe84b35074p-4L, 0x8.d45410dc1895ef4p-4L, 0x2.6391367299a3faccp+0L, 0x2.6391367299a3fadp+0L }, + { 0x8.7112de739485f11p-6744L, -0x1.4a2fc4cfe9bc534cp-13708L, -0x2.71d20e8084e1e9cp-6968L, -0x2.71d20e8084e1e9bcp-6968L }, + { -0x5.9ce42450cfaf8ee8p-4L, 0x6.efb719daf136a1cp-4L, 0x2.404921fc654263p+0L, 0x2.404921fc65426304p+0L }, + { 0x9.ba0bd38df957e82p-5860L, -0x7.f37ea4723b67675p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x2.bf5897672b745798p-4L, -0x1.2b46b769cd53c99cp-4L, -0x6.6fcf0d804412fb1p-4L, -0x6.6fcf0d804412fb08p-4L }, + { 0x8.0d256afefef3c89p-4L, -0xa.e23fca6db43882fp-4L, -0xe.f12f9edadf77c82p-4L, -0xe.f12f9edadf77c81p-4L }, + { -0x3.5d7f19c9107b35a4p-92L, -0x4.0740585229be331p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xb.2f2372351c33164p-8L, -0x1.e98b74b783fe8242p-4L, -0x1.ebd6a4be06afe44ep+0L, -0x1.ebd6a4be06afe44cp+0L }, + { -0xf.7938a9b78d6563ep-4L, -0x5.e56611314a03c688p-24L, -0x3.243f646fc449c69p+0L, -0x3.243f646fc449c68cp+0L }, + { -0x3.378249c69ce50b28p+128L, 0xd.1fe6e25acc0107ap-4L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x2.9bce90f0aac016a8p+8752L, -0x3.f9a540b88fcacaf8p+20L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x9.8f02fd2b4d10383p-4L, -0x3.10d386b4ddaa9bccp-4L, -0x2.d4cb6d7692b4340cp+0L, -0x2.d4cb6d7692b43408p+0L }, + { 0x8.a7f4a483fcced92p-4L, 0x1.0dbbaa49beedef7ap-80L, 0x1.f293f545ba902d6p-80L, 0x1.f293f545ba902d62p-80L }, + { 0xc.779757b60637763p-4L, 0xe.777fe73bf0e9a48p-4L, 0xd.c087f481f381bc4p-4L, 0xd.c087f481f381bc5p-4L }, + { -0x4.637006dbd01caa2p-48L, -0x9.0b16723fd236994p-4L, -0x1.921fb54442d94812p+0L, -0x1.921fb54442d9481p+0L }, + { -0x2.26865489613f2a3cp-16L, -0xf.5402328fd9d6fdfp-4L, -0x1.9221f3ebd1a9f3a6p+0L, -0x1.9221f3ebd1a9f3a4p+0L }, + { -0x1.9cdb9776e2fd9cd6p-88L, 0xc.d7d4b25d5ee54a4p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xf.002b8779c597ceep-4L, 0x7.903eb3c7555e4358p-4L, 0x7.78ddd72dbbbd4ep-4L, 0x7.78ddd72dbbbd4e08p-4L }, + { 0x5.216f04578c6eedf8p-28L, -0xb.887e64736056822p-4L, -0x1.921fb4d260c15a72p+0L, -0x1.921fb4d260c15a7p+0L }, + { -0x2.96746a1d6d0a835cp-12L, -0x6.bbe44e9596a2f068p-44L, -0x3.243f6a85eb741a2cp+0L, -0x3.243f6a85eb741a28p+0L }, + { 0xc.8b02c285d275bd6p-4L, -0x7.2ea947c351044f48p-4L, -0x8.5212a1fc5bb54a1p-4L, -0x8.5212a1fc5bb54ap-4L }, + { -0xc.4830d91b64528bdp-4L, -0xa.faff5d48675db64p-11172L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x1.456f46c72593c416p-4L, 0x1.66e29eea15366fa6p+144L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xd.de830895fc14d25p-4L, 0x1.d696938384c107e8p-4L, 0x2.1bbde70f3e78278p-4L, 0x2.1bbde70f3e782784p-4L }, + { 0xd.737880bffe043f4p+1748L, -0xb.0173bf64b3af081p-4L, -0xd.175a392434528acp-1756L, -0xd.175a392434528abp-1756L }, + { -0x4.d70abf0d2e83e9e8p-32L, -0x4.bded6e2f0ae69668p-4L, -0x1.921fb554978f2276p+0L, -0x1.921fb554978f2274p+0L }, + { -0x1.6f720ef4ee00435cp-104L, -0xe.794bdddad00436cp-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x8.bcfd1861de45b01p-4L, 0x2.aad3a86545c4ac24p+68L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x6.f81960839d640cdp-4L, -0x7.693a270061cf9de8p-4L, -0xd.0ed284135386fbep-4L, -0xd.0ed284135386fbdp-4L }, + { 0xe.7b0648fc94495aap+6848L, -0x5.48b5a0cfdf4fe08p+92L, -0x5.d6a5f8e290a54e2p-6760L, -0x5.d6a5f8e290a54e18p-6760L }, + { -0x6.26f604efc7da8708p+72L, -0x5.9293af393bd5fbfp-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0xd.3ea27eab88fb691p-4L, 0xe.5d425700b9dfb9p-4L, 0xd.37014b312bf4ee6p-4L, 0xd.37014b312bf4ee7p-4L }, + { -0xf.de61a9eba878612p+2584L, 0x3.0b30eb6a97ddaf6p+20L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x2.8b29e4e9b1677aap-8428L, -0xb.c9870bb9c74469p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x1.cdad015fe5b95a34p-148L, 0x3.fcdc007ba74601ap-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x1.f1d5273873448298p-140L, 0xd.38eafd3878fe2f4p-2288L, 0x6.cc9f855116729cd8p-2148L, 0x6.cc9f855116729cep-2148L }, + { 0x1.c55b237b57929914p-8L, 0xe.5512393a7c3aa68p+88L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x6.c72dbae38baf489p-4L, 0xa.9efab67bae298c4p-4L, 0x2.238931ee6f4619p+0L, 0x2.238931ee6f461904p+0L }, + { 0x6.d6fe2acf94b44bp-4L, -0x2.1052fcc75fe78e44p-4L, -0x4.b04c77d29e1352ap-4L, -0x4.b04c77d29e135298p-4L }, + { 0x7.afbf13a7baa48938p+28L, -0xc.e3f378c5ed3afabp-4L, -0x1.ad5137573db23a6ap-32L, -0x1.ad5137573db23a68p-32L }, + { -0x5.ed5d3988224f9748p-4L, 0x1.e7758010af069478p+112L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0xc.0d33ff76e10cd46p+12L, 0x4.1c590bda30ba606p-4876L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x6.57e754000acc05cp-56L, -0xb.d8b227ae135fe8fp+116L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x4.6e00ec5a491950b8p+10764L, -0x1.933e5a044e710e98p-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0xd.233e9cefca1ae41p-120L, 0x3.45dd24865b41e91p+60L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x5.475a990a52ea68a8p+64L, -0x1.8712ead1e57a5c3cp-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x1.09bc36ba214221b6p+5604L, -0x4.bf6dbbf8cca43b3p-8L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x9.4d57927720bce2ap-4L, -0xd.c24a0c2da437c45p-8L, -0x3.0ca61d2678ef9458p+0L, -0x3.0ca61d2678ef9454p+0L }, + { -0x3.bd744abad650adacp+24L, -0x5.b0583bb444fdc93p-72L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x7.2f26a663cb2f6da8p-152L, 0x9.fc2ec0983ea77b3p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x7.56ebed5f60ce8aa8p-128L, 0xe.ca8e0a5bcb1909bp-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x7.9e2690fa1674f7p-4852L, -0x6.a2b3b3cd69bd69p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x5.61e2ca1189149e08p-8L, -0x3.489ad8567c6e09dp-4L, -0x1.77fd0cf88ee2c678p+0L, -0x1.77fd0cf88ee2c676p+0L }, + { -0xd.a2d0231770a0b2fp-4L, -0xb.11f2a040958b184p+108L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xd.566e196c5299a76p-4L, -0xd.827bfd05ebedd0fp-4L, -0xc.ab3ec5d1508e531p-4L, -0xc.ab3ec5d1508e53p-4L }, + { 0xe.690353be92b1ef7p-4L, 0xc.b40a6525370a3c1p-4L, 0xb.8f77d01ae6a411cp-4L, 0xb.8f77d01ae6a411dp-4L }, + { -0x4.a16f62e1fb463d7p-4L, -0xb.6a308232b3be302p-4L, -0x1.f4c81947d7e0267p+0L, -0x1.f4c81947d7e0266ep+0L }, + { -0xa.589c3c563d348fcp+108L, 0x3.aabe12c6cdd5648p+11880L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x1.2112dc65b51a2856p+16L, -0x2.f0fad09fd8f01c5p-108L, -0x2.9ad45124fc8c3a5p-124L, -0x2.9ad45124fc8c3a4cp-124L }, + { 0x6.501f9ed256bec01p-4L, -0xa.0150779e90ebc75p-4L, -0x1.02068c4d16492b4ap+0L, -0x1.02068c4d16492b48p+0L }, + { 0x3.57784bb97c2bfa94p-3436L, -0x8.16fa985eea51244p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x4.6510b53e44e358fp+108L, -0x9.2c631a27ad6ae34p-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0xd.5153d9f62ecffddp-4L, 0x1.7345ed4ae2d9f036p+116L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x7.a68b5532b0e7f568p-4L, 0x7.9a2907c3621d33ap-4L, 0x2.5bff699f72c04828p+0L, 0x2.5bff699f72c0482cp+0L }, + { 0xc.e8479ca0a43ef6p-8L, 0x9.182ad6a367d08aep-4L, 0x1.7b7995fca66e81cep+0L, 0x1.7b7995fca66e81dp+0L }, + { -0x1.26053714fd0be6bap-44L, 0xa.52ae9411f58887cp-4L, 0x1.921fb54442edffd6p+0L, 0x1.921fb54442edffd8p+0L }, + { 0xe.a227507d931299cp-104L, -0xd.13cf8aa40b87d27p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x1.e472b4341bef26b6p-56L, -0x1.7af3bd8ca1f57c42p-7268L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0xd.f33b2053ffa6ae5p-4L, 0xa.8e75c696dc40c78p-4L, 0x2.7e69886741fe3d78p+0L, 0x2.7e69886741fe3d7cp+0L }, + { 0x9.85d3f0dd48eaf72p-4L, -0x3.541ae29b92aa4abp+72L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x1.5a3107a9603de8b4p-28L, -0x3.08af0a00602595fp-4L, -0x1.921fb4d2276f0c64p+0L, -0x1.921fb4d2276f0c62p+0L }, + { 0xf.cac159b69035579p-4L, -0x6.46e719cea85447d8p-4L, -0x6.0da354e1ed3337d8p-4L, -0x6.0da354e1ed3337dp-4L }, + { -0x5.987b05c45ed8a2ep-4L, 0x6.c4e52aa8d26db038p-4L, 0x2.42f6589620f3dab4p+0L, 0x2.42f6589620f3dab8p+0L }, + { -0x8.23b5b38feb155f2p+28L, 0x1.15a54236fe36bd4cp-56L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { 0x1.f5ea7b800785d2ccp-4L, -0x7.ef6aaf1d13c7a7dp-4L, -0x1.541d373bdb2328c8p+0L, -0x1.541d373bdb2328c6p+0L }, + { 0x3.73e18f430b288f48p+5764L, 0xc.f70837877517a74p-4L, 0x3.c14c064e7addf6f4p-5768L, 0x3.c14c064e7addf6f8p-5768L }, + { -0x7.3487f80314c54488p-4L, 0x5.4eccb9e96eb8967p-4L, 0x2.81b5de701e1c753cp+0L, 0x2.81b5de701e1c754p+0L }, + { -0x1.2888c122fac324e2p-116L, -0xd.5620dcdef8d6adep-1048L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x1.a20b309dc63a3432p+100L, 0x1.d9633c032d4a9bc4p+11900L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x5.b49471d499a4cf1p-4L, -0x9.94f5bdecfacab51p-8L, -0x3.09798474778972c8p+0L, -0x3.09798474778972c4p+0L }, + { 0xf.641993c9a620462p-4L, 0xd.a2dd238869b2787p-4L, 0xb.99ab7575d6c73c4p-4L, 0xb.99ab7575d6c73c5p-4L }, + { 0xd.4c3f10c6378bac1p-144L, -0xd.a0da38c144c364ap-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x1.6795cd67133c419cp+104L, -0xf.5afa51a915c3c2cp-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0xa.7324ede2d5b774ep-4L, 0x9.bd729cbbfe64c8ep+64L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x6.67af9a1b48f5476p-4L, -0xb.916f204d9b607e2p-4L, -0x1.10ac84512c1151bep+0L, -0x1.10ac84512c1151bcp+0L }, + { -0x9.a94b7284791aef1p-4L, -0xf.30d659afbbe444dp-4L, -0x2.2323d6dc698c7f1cp+0L, -0x2.2323d6dc698c7f18p+0L }, + { 0x1.15035f9ba3aac31ep-4L, 0xc.6f90a760827aa89p-124L, 0xb.7e126079e1ac136p-120L, 0xb.7e126079e1ac137p-120L }, + { -0xf.fef4a753b10a076p-4L, 0x6.4c2eb46758106918p-4L, 0x2.c43b45ae1e73a0e8p+0L, 0x2.c43b45ae1e73a0ecp+0L }, + { 0x1.3ef509e0c382df66p-4L, 0xc.49b63ac9b2b9eaap-4L, 0x1.78415d75aa039046p+0L, 0x1.78415d75aa039048p+0L }, + { -0x6.d057f880739cc278p-4L, -0x2.c6607086f9019804p+624L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x8.0a6f57c957a28d4p-4L, -0xb.e7e303842191512p+68L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x1.c50b391458918814p-168L, 0x2.b751311339e95d54p+40L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xb.51ba4b350a61c32p-4L, -0xc.0dfbf7e5e3212ffp-12L, -0x1.10a1458b2219c224p-8L, -0x1.10a1458b2219c222p-8L }, + { -0x7.6c639e488208ccc8p-4L, 0x3.a1d6c7b434bf3d98p-4L, 0x2.afc1c9bc173fb84cp+0L, 0x2.afc1c9bc173fb85p+0L }, + { -0x5.c358113ef832c348p-4L, -0xb.d7d98c530f97875p-4L, -0x2.060fd0c52c8ea69p+0L, -0x2.060fd0c52c8ea68cp+0L }, + { 0x1.3e90b4eb0efaf5fap-6916L, -0xa.5b3f67eed42f35ep-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x8.df34d29839f6cbap-76L, 0x8.6f95a977e54b54fp-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x1.d6566fbbd43703bcp-4L, 0x5.7c58e6c483f58898p-4L, 0x1.e4db3a1a27a3fd2ep+0L, 0x1.e4db3a1a27a3fd3p+0L }, + { -0x2.35210275477555ccp-120L, -0x8.3dccba3b25f76c1p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xd.5f0d592ded19983p-4L, 0xa.c3b832d5003b707p-8L, 0xc.deb2302702560a9p-8L, 0xc.deb2302702560aap-8L }, + { 0xa.1061f8f22c56a2p-4L, 0x7.a0e695df486975a8p-4L, 0xa.60aca0123922aa8p-4L, 0xa.60aca0123922aa9p-4L }, + { 0x2.0f49c0d924c5ef48p-4L, -0x1.4c612171c559b0d2p-4L, -0x8.ffc2ff83f8bbf35p-4L, -0x8.ffc2ff83f8bbf34p-4L }, + { 0x7.5446c6842f5c1d88p-12L, 0x7.18f85d323644c07p-4L, 0x1.91175a864f920822p+0L, 0x1.91175a864f920824p+0L }, + { -0xb.e3d76e1e4bf5645p-8L, 0xa.e3f91773dee5cbdp-4L, 0x1.a390b3558878456ap+0L, 0x1.a390b3558878456cp+0L }, + { -0x6.64a485a65ba2bb8p-4L, 0xb.ab5d793764e46aap-4L, 0x2.126e03037b78e2a4p+0L, 0x2.126e03037b78e2a8p+0L }, + { -0x4.180ed04588b6b84p-4L, -0x3.1b46b393f7f02654p-4L, -0x2.7e12fe53471d28ep+0L, -0x2.7e12fe53471d28dcp+0L }, + { -0xb.12b6b696713dd3p-4L, 0x4.65ce2cb3797b29a8p+24L, 0x1.921fb56c8c50179p+0L, 0x1.921fb56c8c501792p+0L }, + { -0xa.3485ec95ca278f3p-4L, -0xc.4eeb5c35769e37p-4L, -0x2.43572f0e1543b008p+0L, -0x2.43572f0e1543b004p+0L }, + { 0x7.9916813ff5ff3cc8p-4L, 0xe.8cc5489d5bd410dp-4L, 0x1.16ec5e1241b086b4p+0L, 0x1.16ec5e1241b086b6p+0L }, + { -0x4.332914d9e18063ap-4L, 0x2.c3783d61fd7041fcp+324L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x7.8ea9558f03ae0e7p-4L, -0xf.dee9088b413455fp-4L, -0x1.205b027c87f0ec66p+0L, -0x1.205b027c87f0ec64p+0L }, + { -0x8.2df8e53739c9b8bp-4L, -0xb.237c6168dab68dbp-4L, -0x2.344698f98d5f286p+0L, -0x2.344698f98d5f285cp+0L }, + { -0xc.ff8006e798ca57dp-4L, -0xb.402101043dda93fp-72L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x7.837abefd5e55df78p-4L, 0x1.a83077ccca0d82acp-136L, 0x3.874cdd05c1765a8p-136L, 0x3.874cdd05c1765a84p-136L }, + { 0x3.a07b4d79ba0a5338p+28L, -0x4.bb21255de4a41a5p-4L, -0x1.4dee6dffdfcabca8p-32L, -0x1.4dee6dffdfcabca6p-32L }, + { -0x5.4eee2008ac59dda8p-24L, 0x2.d2b2eaf924487474p+8820L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x6.bbde2a7543c30b38p-4L, 0xb.8edecd5dd38da0cp-4L, 0x1.0b1331d46f6de5d4p+0L, 0x1.0b1331d46f6de5d6p+0L }, + { -0x6.c15f52803f443968p-4L, 0x3.918ec1969b0edd88p-4L, 0x2.a7d4fdd140e4ebecp+0L, 0x2.a7d4fdd140e4ebfp+0L }, + { -0xe.f6471a773b022bdp-8L, 0x3.3e6b054d350dcc9p-4L, 0x1.d9f9aa2df774d312p+0L, 0x1.d9f9aa2df774d314p+0L }, + { 0x6.81487cec2e861c7p-8L, 0x4.87a7a304beeda28p-4L, 0x1.7b3580ce6e5967ep+0L, 0x1.7b3580ce6e5967e2p+0L }, + { -0xd.c7238c1ad3cafc9p+88L, 0xe.ac1774f7032d1ffp-4L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { 0x2.3f1854f194f5df1cp-128L, 0x1.014e18840001d972p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x5.040eb8c257682f18p-4L, 0xf.7346ad82e18af85p-4L, 0x1.41c34c3094d5a47cp+0L, 0x1.41c34c3094d5a47ep+0L }, + { 0xf.1cd1b7c493a3be6p-124L, 0x1.9e8c3ea1db7772dep+120L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x6.e13c582ac5e85888p-64L, 0x4.b2842fc0d4e29f8p-4L, 0x1.921fb54442d18452p+0L, 0x1.921fb54442d18454p+0L }, + { 0xf.a09a22b402060edp-4L, -0x8.e32395dc002f9bfp-8L, -0x9.1869589c28478e3p-8L, -0x9.1869589c28478e2p-8L }, + { -0xf.8c0db00bdf53596p-4L, 0x5.36e056abcab2faa8p-4L, 0x2.d167d9163e9e6a94p+0L, 0x2.d167d9163e9e6a98p+0L }, + { 0x7.6c92e56712d5affp-4L, -0x6.b6582996f57933c8p+124L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x3.0c9abaa8404f3e18p+140L, -0xa.e4299f2f9dca735p-4L, -0x3.926176c315d2215p-144L, -0x3.926176c315d2214cp-144L }, + { -0xe.d132e5394f60034p-10048L, -0x4.6ac0196a0af61fdp+72L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x9.ea2a7bd17c460dep-4L, -0x3.b176489ffeab233cp-80L, -0x5.f5c096bd8a9e69d8p-80L, -0x5.f5c096bd8a9e69dp-80L }, + { -0x7.e3d1eea20b324e7p-4L, -0x9.86088a50194e78ap-4L, -0x2.433d3f80c2defd8cp+0L, -0x2.433d3f80c2defd88p+0L }, + { 0x3.dfea4f893d4c581cp-3232L, 0xc.7be5695b1db3127p+100L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xe.e19314560029718p-4L, -0xa.e3c3bdecf1dec26p-8L, -0xb.b346fb302824719p-8L, -0xb.b346fb302824718p-8L }, + { 0x7.13c978b522f9333p-4L, -0x6.c0d55cd6c8226dd8p+16L, -0x1.921fa47fb9a46872p+0L, -0x1.921fa47fb9a4687p+0L }, + { -0x1.1d1ed153b343c44ep-4L, 0x7.6fdb8f997549cde8p-8L, 0x2.bf08ff529f82588p+0L, 0x2.bf08ff529f825884p+0L }, + { 0x2.7a077ab0456582fp+88L, 0xf.6e420d340620fd3p-4L, 0x6.3afbbdbf3e3239e8p-92L, 0x6.3afbbdbf3e3239fp-92L }, + { -0xe.6c4b7e894887c7fp-4L, -0x2.a9883b33131d202cp-4880L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0xe.22b622d6cdf1548p+8L, -0x3.af9571884b9dea6cp-4L, -0x3.243b3e7ef45eb194p+0L, -0x3.243b3e7ef45eb19p+0L }, + { -0xb.a0a2f3e13b85a66p-4L, -0x5.5d35693a073a956p-80L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x1.22c95177a19486ep-100L, -0x1.09a01a4ee447f2dp-8L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x6.290348987c0e55f8p+136L, -0x4.20c946d47a37871p+4972L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xc.ad96dfac7b95172p-4L, 0x1.1fc7d37c0ec92196p+104L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xd.0d8c22a9e6d3c5p-4L, -0x2.31c152f5ee281b54p+11172L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x5.13c1489191b10628p-4L, 0x9.40268306f3eaf37p-4L, 0x1.119f5be56987a0b4p+0L, 0x1.119f5be56987a0b6p+0L }, + { 0x9.167509d85ac5562p+60L, 0x1.4b8f74471056531ep+12628L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x3.f7343ff72e27615cp-4L, -0x3.3ce0a42e5743e218p-3160L, -0xd.103c74c735aacefp-3160L, -0xd.103c74c735aaceep-3160L }, + { -0x6.19ec462854667938p-4L, 0xe.a753d50ad228a17p-4L, 0x1.f71fe9e91d7e6d3ep+0L, 0x1.f71fe9e91d7e6d4p+0L }, + { 0xb.2326e5c709d8338p-4L, 0xe.4cbeeba038e2a66p-4L, 0xe.8ba0b620906082cp-4L, 0xe.8ba0b620906082dp-4L }, + { 0x9.90137db5d8438f6p-4L, 0x8.f6fc2825e1cf803p-4L, 0xc.0cd4a9c04892b88p-4L, 0xc.0cd4a9c04892b89p-4L }, + { 0xb.a6e18f1dc982de2p+16L, 0x7.093038cd340d2eap-4L, 0x9.a9560c2566d537p-24L, 0x9.a9560c2566d5371p-24L }, + { -0x1.7d48f31379a2fd94p+13764L, 0x7.408cc4c84d37f818p-4L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0xf.a038fe23264b69fp-4L, -0x5.d983ceba22bba45p-4L, -0x2.c88bec446ef69d7cp+0L, -0x2.c88bec446ef69d78p+0L }, + { 0x3.aaf0ce3e734d6f2p-4L, 0xf.72f358999238d68p-4L, 0x1.5673af7a281b339p+0L, 0x1.5673af7a281b3392p+0L }, + { -0x6.4d100f244be8113p-4L, -0x8.8a2584d61c785a5p+10256L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x6.e4c6b8c4d0181df8p-11840L, 0x2.88e3d82654a9a2d4p+84L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0xb.bac11f4e1e14036p-4L, -0x5.f466fe6cbdda3498p-4L, -0x2.abfd043f83efad38p+0L, -0x2.abfd043f83efad34p+0L }, + { 0x5.b28281e63f18c36p-40L, 0x1.5d03274c615fac7ep-4L, 0x1.921fb543fff47b6ap+0L, 0x1.921fb543fff47b6cp+0L }, + { 0xf.e3a0ddc922c2768p-4L, 0xa.669f21ff1f04159p-4L, 0x9.460446a2490498ep-4L, 0x9.460446a2490498fp-4L }, + { 0x8.ab617e168652f41p-4L, 0xa.9ceb33ff19c471bp-4L, 0xe.2c71acd10589374p-4L, 0xe.2c71acd10589375p-4L }, + { 0x7.e712d33d338b3f4p-4L, 0x1.bb5c92c3b346b3d2p-140L, 0x3.81a60c2164f42748p-140L, 0x3.81a60c2164f4274cp-140L }, + { 0xb.0f353c55a1bc86bp-4L, 0x2.a7aa43ef734cca24p-14752L, 0x3.d74b1fcceaff8cc4p-14752L, 0x3.d74b1fcceaff8cc8p-14752L }, + { 0x6.355f24aadd2d76cp-4L, 0x5.db625c7f505b3848p-4L, 0xc.19b1387d741a37p-4L, 0xc.19b1387d741a371p-4L }, + { 0x2.b76e057b32691f28p+56L, 0x6.dee852c47ad7ae6p-4L, 0x2.877c26e1b4786b5p-60L, 0x2.877c26e1b4786b54p-60L }, + { -0x6.bb1bf54be9664e8p-4L, -0x1.abb9e76137c068dcp-28L, -0x3.243f6a48f9ae83e8p+0L, -0x3.243f6a48f9ae83e4p+0L }, + { 0xf.db239caa0c58725p-4L, -0x1.a857f265390a97e6p+11340L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xe.d6bf659b8abbf88p-52L, -0x6.3520edf48c502b48p-4L, -0x1.921fb54442cf2076p+0L, -0x1.921fb54442cf2074p+0L }, + { -0x2.845d2338bd21f05cp-4L, -0x1.d3130e0c084f14c8p-4L, -0x2.83ae1a3982d00d2p+0L, -0x2.83ae1a3982d00d1cp+0L }, + { 0x7.e34ef80c4f7e3eep-4L, -0x5.a8b3cf39973ba25p-4L, -0x9.f50b2ea47c1075ap-4L, -0x9.f50b2ea47c10759p-4L }, + { -0x1.56bf999942c755dap+7896L, -0x9.80fe0cfc3618055p-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x1.deff9f28444c6c38p-4L, 0x9.1da1f7cda29486bp+48L, 0x1.921fb54442d187b2p+0L, 0x1.921fb54442d187b4p+0L }, + { -0x9.24964216848ef53p-4L, 0x1.f0ed69f0e4821e64p-116L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0xc.7f839e0758c0fc4p-4L, -0xa.04266867c71fecep-4L, -0x2.774af214e503f1a4p+0L, -0x2.774af214e503f1ap+0L }, + { 0x1.8d5159b50fdc3fbep-84L, -0x6.ea56e501411dee98p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x6.108af52b9d9b2bp-4L, -0xc.1cbbb5c2e434abap-88L, -0x1.ff48471de69df2e4p-84L, -0x1.ff48471de69df2e2p-84L }, + { 0x5.d6a27cfc56ca253p-36L, -0xb.3fef5d7e57e0805p-4L, -0x1.921fb543bdf581a8p+0L, -0x1.921fb543bdf581a6p+0L }, + { 0xe.b53f2b3083d023ep-4L, 0xb.f408f69524f06c2p-4L, 0xa.eb4641b720503dbp-4L, 0xa.eb4641b720503dcp-4L }, + { 0x8.03baca4a7357516p-4L, -0xa.c1abbb69e26abf7p-4L, -0xe.e31b0d044e273ap-4L, -0xe.e31b0d044e2739fp-4L }, + { 0x1.d872e7eedaaa637ep-4L, 0x4.495ee30da4659e98p-4L, 0x1.2a0c770aea65c4c6p+0L, 0x1.2a0c770aea65c4c8p+0L }, + { -0xc.150a73ee88aac4bp-4L, 0x2.8fa0b8cb59d9a58cp-8L, 0x3.20db3e407d76332p+0L, 0x3.20db3e407d763324p+0L }, + { -0x6.08720c311ad69e78p-4L, -0x7.3b6b4ffd7b8decp-8L, -0x3.111a73de1561f32p+0L, -0x3.111a73de1561f31cp+0L }, + { -0x5.80db9fe644d1e708p-4L, -0x3.ec81c27ff8544994p-76L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0xb.656227303abf84fp-4L, 0x7.b40be4642e982ab8p-4L, 0x9.82b5d74d3bcff98p-4L, 0x9.82b5d74d3bcff99p-4L }, + { 0xa.049b6be5646929ep-28L, 0x7.c2408cb283b8a548p-124L, 0xc.644b5de744c024bp-100L, 0xc.644b5de744c024cp-100L }, + { -0x1.0d0aa693e23087aep-4L, 0xa.b0a2a7b4c6b0611p+80L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x8.4b1f02dac6cd4b9p-4L, -0xc.759d3a3d2bb277bp-4L, -0x2.28783fdcb3986748p+0L, -0x2.28783fdcb3986744p+0L }, + { -0x9.5efce40ef5c193p-4L, 0x1.3acdec63c75ba85ap-4L, 0x3.02d863b62e9ce0ep+0L, 0x3.02d863b62e9ce0e4p+0L }, + { -0x3.a8862397aa33d5bcp-4L, -0x8.40b99f3260074bbp-4L, -0x1.fcf094a049d0f47p+0L, -0x1.fcf094a049d0f46ep+0L }, + { -0x1.13ba9d07bc3a2952p+84L, -0x2.71006a8cb34d554cp-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x9.1553f4826cd4c82p-4L, 0xa.cf99c7754a95e18p+96L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x3.8114a9e190ab791p-60L, -0x4.9c18fd283d9a589p-4L, -0x1.921fb54442d183a8p+0L, -0x1.921fb54442d183a6p+0L }, + { 0xc.05b3f7d8b6f7624p-4L, -0x1.954b2fada5db23c6p+104L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x5.7aa677b8b3a14efp-4L, 0x6.8d1b5b54f8172e1p-4L, 0xd.fd0cb0efb607319p-4L, 0xd.fd0cb0efb60731ap-4L }, + { -0x4.a8455a7e3a68ed78p-4L, -0x4.7b4255a8c709f0ap-16L, -0x3.2430052b6ba121b8p+0L, -0x3.2430052b6ba121b4p+0L }, + { 0xf.331d018a51a3937p-4L, -0x3.eca2bd0c8570369p-4L, -0x4.0aeef8cb409b3868p-4L, -0x4.0aeef8cb409b386p-4L }, + { 0x6.52993e0816809a4p+1080L, 0xa.8f1f3b01d061b7dp-4L, 0x1.ab87a4c2ecb907f2p-1084L, 0x1.ab87a4c2ecb907f4p-1084L }, + { 0x2.293460674db2c4p-4L, -0xd.ea0bd2fdf3193cep-4L, -0x1.6aae49a397df62c6p+0L, -0x1.6aae49a397df62c4p+0L }, + { -0x7.7cc8ad228793eeep-4L, 0x3.3eb74cb49c028ad4p-4L, 0x2.bb8e137b5adb0bc8p+0L, 0x2.bb8e137b5adb0bccp+0L }, + { 0xe.bc5331958998244p-4L, -0x1.2903edbad4d00bdep-152L, -0x1.428000ee39f15116p-152L, -0x1.428000ee39f15114p-152L }, + { 0x5.3ee964d9303fef2p-4L, 0x9.0a14cf75dc8c935p-136L, 0x1.b92274ff2c1cfc2ap-132L, 0x1.b92274ff2c1cfc2cp-132L }, + { -0x6.e59cd2b304be20bp-8L, -0xd.25ced593ff0ac61p-4L, -0x1.9a83972861c5912p+0L, -0x1.9a83972861c5911ep+0L }, + { -0x3.1617c019abd659bp-4L, -0x6.690f39e52d0c90c8p-4L, -0x2.04fdb7e0f6ca2148p+0L, -0x2.04fdb7e0f6ca2144p+0L }, + { 0x9.1050fe64665d025p-4L, -0x1.fd861374d11ff0fcp+4216L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xd.953628a90529c68p+16L, 0x1.d0ef8f8c2df971eap-52L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { 0x7.a4dabfc6c9e825b8p-4L, -0xb.f01119533e278e8p-4L, -0x1.00526ae79cfdf7bp+0L, -0x1.00526ae79cfdf7aep+0L }, + { -0x1.6396f574b56c6172p-4L, 0xf.b5e4a3223e61c14p-4L, 0x1.a8b2f2c93a739358p+0L, 0x1.a8b2f2c93a73935ap+0L }, + { -0x1.a1e72b708ae7ec3ap-84L, -0x1.cad34f8832df94b6p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xd.a82c5b229e8fe54p-4L, -0xc.337e6ec5ca09cbfp-4L, -0xb.aaa255a332a6dc7p-4L, -0xb.aaa255a332a6dc6p-4L }, + { -0x1.6666a8b8b12721dep+4L, 0x7.b2a783da083648ep-8L, 0x3.23e770d8aa1a524cp+0L, 0x3.23e770d8aa1a525p+0L }, + { -0x3.9a1204d27a81d9a4p+56L, -0x7.c2d56e73e1215768p-4L, -0x3.243f6a8885a308b4p+0L, -0x3.243f6a8885a308bp+0L }, + { -0x7.cfb667a4a3914a3p-4L, -0x2.365d2022bd55ec38p+8880L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xb.439e5356c702ad8p-4L, -0x1.c311b31d8db88c76p+12068L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xe.d87c88ea04cfc54p-4L, 0x7.5df293fec0fa7908p-4L, 0x7.5ec19b27ea9d83ap-4L, 0x7.5ec19b27ea9d83a8p-4L }, + { -0xb.f31341da10838b7p-4L, -0x4.94201f2127bae1d8p-4L, -0x2.c69340156b018bb8p+0L, -0x2.c69340156b018bb4p+0L }, + { -0xf.466813a0cb58997p-4L, 0x1.b40206802faf31f8p-4L, 0x3.07d2400cd8e729fp+0L, 0x3.07d2400cd8e729f4p+0L }, + { -0x1.73fa2d1e8f4aed4ap-8956L, -0xd.f8e6092df0a67cdp-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x3.b170aeec21cbacep-124L, -0xe.4ffa3f0dccc1904p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x6.fa8da286037d29f8p-4L, 0xf.58e77980ec0ef84p-4L, 0x1.24debdfdda0fa8c4p+0L, 0x1.24debdfdda0fa8c6p+0L }, + { 0x8.5ae9b271c862bd1p-4L, -0xa.8fdf30d83ecd512p-4L, -0xe.6cae0678d6b6b55p-4L, -0xe.6cae0678d6b6b54p-4L }, + { -0x1.e689240cdaba32p-84L, 0xe.c5e20aeb268e22p+68L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0xf.65a3e9387da5a2fp-4L, -0x2.f52bdc7095786358p-68L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x5.9a9d1446632f3aep-4L, -0x4.da74bc68acb86d9p+28L, -0x1.921fb5431b39c106p+0L, -0x1.921fb5431b39c104p+0L }, + { -0x8.7aea261756d25f3p-4L, 0xf.b5a3f9c32315f89p-4L, 0x2.10d707be6bdebe98p+0L, 0x2.10d707be6bdebe9cp+0L }, + { -0xe.7abe135a43a13e6p-4L, -0xe.63241d69fc37ac5p-88L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x3.2bf2a0a669999b48p-4L, 0x2.9affca93299785ep+5448L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x1.31c27de6118742f6p+7288L, 0x8.4ef4a64c01509a8p-4L, 0x6.f4cfe94bc3c887e8p-7292L, 0x6.f4cfe94bc3c887fp-7292L }, + { -0xd.d97824ee2873846p+60L, -0x3.d56d54e6a082a09p-9744L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x3.457eb22e95949aa4p-132L, -0x2.c7ad460f031ac6c8p-148L, -0xd.98a6edfdd4c7bcep-20L, -0xd.98a6edfdd4c7bcdp-20L }, + { 0xa.340ec3fa9c98451p-4L, -0x5.a130fe2bb18970cp-4L, -0x8.11219835b80db8cp-4L, -0x8.11219835b80db8bp-4L }, + { 0x2.36bf7820405b3b6cp-1364L, 0xb.c0ae25e2a801fc9p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x9.33aadc610c07076p-4L, 0xb.62d8d178f4ea271p-4L, 0xe.41f0912d1fc9e9ap-4L, 0xe.41f0912d1fc9e9bp-4L }, + { -0xb.de8017b99009994p-4L, 0xc.d14f3f856910093p-4L, 0x2.515ae28f032a6f08p+0L, 0x2.515ae28f032a6f0cp+0L }, + { 0x4.d809ec362c4289bp-104L, -0xc.5d2d16de94144fcp-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xd.79e031e02305347p-4L, -0xa.c010f18d71bc8c5p-4L, -0xa.c60f92816aef05p-4L, -0xa.c60f92816aef04fp-4L }, + { -0x3.39af6943075c3b8p-13668L, 0x1.720bafd1b399ec82p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x4.fac18c7be7e011e8p-4L, 0xe.e7cda687036f7d6p-8L, 0x2.f58afa694e9eab6p-4L, 0x2.f58afa694e9eab64p-4L }, + { -0x9.9c2d0517aeee533p-8L, 0x1.cae7d85a2a39e2acp-3348L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x1.d28f44d13b0d6254p-12L, -0x5.fee8120e5e04be2p-4L, -0x1.926d85fbcd378c66p+0L, -0x1.926d85fbcd378c64p+0L }, + { 0x3.f3364f18a79b3b3cp-4L, -0x3.6b2dcf47d1901574p-144L, -0xd.d8fc6e63635a2c2p-144L, -0xd.d8fc6e63635a2c1p-144L }, + { 0x6.e5d1de6f1a858028p-8428L, -0xf.f7a6695a9469f6bp-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x5.768672da4d7d0c9p-64L, 0x8.92179a4e3bb69e3p-4L, 0x1.921fb54442d1845ep+0L, 0x1.921fb54442d1846p+0L }, + { 0xb.ed688726df9befap-4L, 0x9.3f55bdfddb49b2bp-4L, 0xa.8d531b9fae50f96p-4L, 0xa.8d531b9fae50f97p-4L }, + { -0x3.9761f885a890c5f8p-148L, 0x3.fbc31466ed38546cp+112L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x6.5dbff56825b7dbb8p-4L, 0xa.e7a98283fc10855p-4L, 0x1.0ad966b89af0b16p+0L, 0x1.0ad966b89af0b162p+0L }, + { -0xc.2509016f44e196ap-4L, 0x7.861514480ac9199p-4L, 0x2.96425b66aa6752cp+0L, 0x2.96425b66aa6752c4p+0L }, + { -0xf.17da41cf884346bp-4L, -0xc.62d7c253621dcf7p+92L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x9.845c3e40ed6ad83p-8L, 0xd.68fda9eec5a66c2p-4L, 0x1.9d78b2079eeed2acp+0L, 0x1.9d78b2079eeed2aep+0L }, + { 0x8.18f925371b61292p-4L, -0x1.57f7c0849ebb346p-4L, -0x2.a182f2c02a69e4b4p-4L, -0x2.a182f2c02a69e4bp-4L }, + { -0x5.7255a940d84ebcf8p-104L, 0x7.1174b12c13aaf4e8p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0xe.880fef5908d95bdp-4L, 0x7.609718a06f5f08ap-4L, 0x2.abfc8b95e8a16a24p+0L, 0x2.abfc8b95e8a16a28p+0L }, + { -0x6.e2bdbcf507ec4778p-4L, 0xa.20544abb2f768b5p-4L, 0x2.2aff89eb7f75b724p+0L, 0x2.2aff89eb7f75b728p+0L }, + { 0x6.14aea1523dfe3aa8p-4L, 0xc.97a55c9c85f26f9p-4L, 0x1.1ef5051994890448p+0L, 0x1.1ef505199489044ap+0L }, + { -0x8.680ab975830d106p-28L, -0x3.7b5dd7324be888fcp-4L, -0x1.921fb7ae5387a11ep+0L, -0x1.921fb7ae5387a11cp+0L }, + { 0xd.ff0ee4cab1a5c92p-36L, -0xe.008f2e366ac05f5p-4L, -0x1.921fb54342ecf648p+0L, -0x1.921fb54342ecf646p+0L }, + { -0xa.b9de710cc3240eap-4L, 0xd.b8496a7f5a40118p-4L, 0x2.3bfd545148e14c4p+0L, 0x2.3bfd545148e14c44p+0L }, + { 0xb.c810c87ed94addfp-4L, -0x3.0523d455a5644e6cp-11020L, -0x4.19f89145d6fd82p-11020L, -0x4.19f89145d6fd81f8p-11020L }, + { 0x6.b4a53b079af062ep-52L, 0x1.02b5df71e26e7eeep-4L, 0x1.921fb54442cae1cp+0L, 0x1.921fb54442cae1c2p+0L }, + { -0x1.05a95b1b36f384dcp-100L, 0x5.d8b77fd6db5f46fp-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x3.b2d5aa2bd4f226c8p-4L, 0x1.3d87d39ca205f226p-4L, 0x5.2d5b7585602e1918p-4L, 0x5.2d5b7585602e192p-4L }, + { 0x7.58b591427632828p-4L, 0xd.51cbb799b3f3a26p-4L, 0x1.1116e6ac8ad3c638p+0L, 0x1.1116e6ac8ad3c63ap+0L }, + { 0x9.0e54bb10a5b7912p-4L, 0xa.7e81ca95f58d507p-76L, 0x1.28a7d33e5f568438p-72L, 0x1.28a7d33e5f56843ap-72L }, + { -0x5.1c6359354bd6cac8p-4L, -0x6.c6dd984bf0b457cp+11148L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x3.c17697f567f1596cp-7888L, -0xd.dd9a1c0c442c4c6p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x4.61b51c01df55d6d8p-4L, -0xb.dce6fd9bad9f495p-4L, -0x1.ecb365c6c3aa5084p+0L, -0x1.ecb365c6c3aa5082p+0L }, + { -0xa.b6f22a1b9f2939fp-4L, -0x3.4bb35afb05788e3p-4L, -0x2.d7db2978909722ap+0L, -0x2.d7db29789097229cp+0L }, + { -0x1.a1b675fb478bf18p+0L, -0x2.1ce57b45214ebd74p-4L, -0x3.0f9309e0cdbb0d7cp+0L, -0x3.0f9309e0cdbb0d78p+0L }, + { -0x5.067f9f48fc5b234p-8L, 0xb.a04244a598be88fp-4L, 0x1.9909c9c477bcd66cp+0L, 0x1.9909c9c477bcd66ep+0L }, + { 0xf.d97f1711de15f9cp-4L, -0x3.d24ecad1dffaabe4p-36L, -0x3.db97674bec9f4df8p-36L, -0x3.db97674bec9f4df4p-36L }, + { -0xc.deaf7691740cdefp-8L, 0xa.59b5d478c821a2ep-4L, 0x1.a5fa83821cba7646p+0L, 0x1.a5fa83821cba7648p+0L }, + { -0xd.1b186c2e3417901p-4L, 0xf.14939428966efa8p-4L, 0x2.49480ac2f173d45p+0L, 0x2.49480ac2f173d454p+0L }, + { 0xa.548931dd5b08516p-1308L, 0x3.0d860af72111fc38p-84L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x2.379420afe91ec9c8p+40L, 0x6.381df51cf6ba1e58p-4L, 0x3.243f6a888576271cp+0L, 0x3.243f6a888576272p+0L }, + { 0xb.d0fe6ed90e574e6p-4L, 0x5.f4609ad6162545cp-4608L, 0x8.101632edfcc5ab9p-4608L, 0x8.101632edfcc5abap-4608L }, + { 0x1.925eaa29d2ecb61cp+44L, -0xd.ac66274a591f9a9p-4L, -0x8.b30fadfb09888a8p-48L, -0x8.b30fadfb09888a7p-48L }, + { 0x3.a5ddc4a5f3b82868p+64L, -0x2.bab320b85305843cp+11384L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x2.a982ac56625aefc4p-4L, 0x8.056940c538fa279p-4L, 0x1.e428e4e0f8cafb9p+0L, 0x1.e428e4e0f8cafb92p+0L }, + { 0x1.66b64b9c9f79a1dep-4L, -0x3.26b75fa52c7ce30cp-4L, -0x1.2703530602efb014p+0L, -0x1.2703530602efb012p+0L }, + { -0x9.da5604fb75e8d87p-116L, 0x8.f39b1339c38973dp-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x7.677b36d2e1d48358p-4L, 0xa.996804efaa5460cp-4L, 0x2.2e38eedff366f594p+0L, 0x2.2e38eedff366f598p+0L }, + { -0x6.b6c06e4a29c88afp-4L, 0x5.a5149fe9b18171c8p-4L, 0x2.714657cddd0fa80cp+0L, 0x2.714657cddd0fa81p+0L }, + { -0x5.375a31264862647p+3840L, -0xc.55651fd1cbee3d4p-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0xe.006deb92f93d672p+1080L, 0xa.6871090121d471bp-4L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { 0xc.8ed445e1ea26da6p-4L, -0x3.70640030d409ab74p-4L, -0x4.46dbe31ace4e4798p-4L, -0x4.46dbe31ace4e479p-4L }, + { 0x8.8651cda5ac10d93p-4L, -0x6.dee1c8172006e6e8p-4L, -0xa.da9a82f5b8d481bp-4L, -0xa.da9a82f5b8d481ap-4L }, + { -0xb.b53f28201a854efp-4L, -0x1.0a2c69e331c156f6p+3472L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xd.e2cee7a54e7c7dfp-4L, -0x9.3f6896a8070ab3ep-4L, -0x9.667e289dbdd94abp-4L, -0x9.667e289dbdd94aap-4L }, + { 0x1.a1524a334652c37cp-4L, 0x1.9b7f6344a4875e14p-4L, 0xc.7435ca5edddaf34p-4L, 0xc.7435ca5edddaf35p-4L }, + { -0xb.4660bc20f1141f9p-4L, 0x6.cc440cbde57dd15p+3488L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0xf.3adad3101e81209p-4L, 0xa.79ea74b25ad8a16p-4L, 0x2.89ff542b1f7b17e8p+0L, 0x2.89ff542b1f7b17ecp+0L }, + { -0xd.4d87683a39ac568p-4L, -0xd.0f2848388d6bd4fp-4L, -0x2.5d8d3b12422814a4p+0L, -0x2.5d8d3b12422814ap+0L }, + { 0x1.767ee6689d922d76p-20L, -0x1.705dc2d9924977d6p-4L, -0x1.921eb101c57d5742p+0L, -0x1.921eb101c57d574p+0L }, + { -0xe.de1ad3b0df8a929p-4L, -0xe.4bc9f399afa1199p-4L, -0x2.6033c43349c8a4bp+0L, -0x2.6033c43349c8a4acp+0L }, + { 0x9.4bc88b56990e957p-4L, 0x3.8aa0cdd01b00999p+7580L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x7.5dedd023859c58c8p-4L, -0xe.f93cd6eb00fb07ap-4L, -0x1.1d13330bde9cdc64p+0L, -0x1.1d13330bde9cdc62p+0L }, + { -0x6.3df3c6079972141p-4L, 0xb.fe0dd62537b23a4p-2520L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { 0x4.d95e34fb8dacb328p-124L, -0x9.b353da0ba311c6dp-60L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xc.6abf9e7c57817a2p-4L, -0x4.3c1e721def125b9p-4L, -0x2.d01af5496f51c508p+0L, -0x2.d01af5496f51c504p+0L }, + { 0x7.2ddd2222b3f198a8p-4L, 0x7.db137d9811c79dep-112L, 0x1.18208ad22454d6c4p-108L, 0x1.18208ad22454d6c6p-108L }, + { -0x4.cf7eed0ba7ab4778p-4L, -0x3.cfde77dacc7baccp-96L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x3.c4fc5635219d094cp-116L, 0x3.f00c386330e300ecp-28L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xf.6b843b68893794cp-4L, 0xf.2a2645e05f54dbfp-8L, 0xf.b71cea10e6fa9dfp-8L, 0xf.b71cea10e6fa9ep-8L }, + { -0x4.baca2c1fc8c972dp+24L, 0x6.90fbdf3ee3bced38p-776L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x2.c5e571ee1dc3a27p-4L, -0x7.0180ac3e7e17ae1p-4L, -0x1.f29bd3e4a7c4ec62p+0L, -0x1.f29bd3e4a7c4ec6p+0L }, + { -0xb.fe012bea0b6470dp-8L, 0x4.e3d9edfbba7c4bcp+136L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x5.42c4c079e796e1dp-4L, 0x3.797b1939cea93534p-4L, 0x2.8ed2b02d7596067cp+0L, 0x2.8ed2b02d7596068p+0L }, + { 0x5.994c986ae0567538p-4L, -0x1.aee939e2fbdd15c2p-9024L, -0x4.cf6eca9b5e92e72p-9024L, -0x4.cf6eca9b5e92e718p-9024L }, + { -0x2.6ae2f779ed5c0b58p-10132L, 0xc.75fc43f9ad2a67ap-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x1.b4e98c673b461666p-4L, 0x6.fa4bd77c57afe13p+3972L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0xe.14620d5210a675ap+72L, 0x8.3ab9c1257774a44p-4L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { 0x6.75bfbc7f917d7158p-4L, 0x3.8750adb31a46680cp-4L, 0x7.ffbf86632db338ap-4L, 0x7.ffbf86632db338a8p-4L }, + { -0x2.a07fb251cb4cf3bcp+6416L, -0x5.b501e8056d41ca2p-88L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x9.a0eb440277239eap-4L, 0xc.50af1095969ae95p-4L, 0x2.3bffb3aafd0b1948p+0L, 0x2.3bffb3aafd0b194cp+0L }, + { -0x8.c5fdbc4b0b452f4p-60L, -0x8.c888d45b054b19ep-4L, -0x1.921fb54442d1856ap+0L, -0x1.921fb54442d18568p+0L }, + { -0x4.1a164828ad307d9p-4L, 0xd.d06990220d829b5p-6340L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { 0x3.709d5b044eff68ap-4L, 0x4.79f2d04625e53728p-4L, 0xe.a63d1a773c7886ep-4L, 0xe.a63d1a773c7886fp-4L }, + { 0x2.5d97ab2d70f6435cp-4L, 0xd.562ebf23b602612p-4L, 0x1.652ee26e7a2cbd9p+0L, 0x1.652ee26e7a2cbd92p+0L }, + { 0x1.e0fded40c3c2896ep-4L, 0x9.b2a0e063a00552bp-4L, 0x1.6121f3177cf3867ep+0L, 0x1.6121f3177cf3868p+0L }, + { -0xc.ea981936ab65ff9p-4L, -0xf.1e90b017130c6d5p-4L, -0x2.471c6550f0ab8d14p+0L, -0x2.471c6550f0ab8d1p+0L }, + { -0x8.fc9915b02547e54p-4L, 0x3.fd5dcb827e327bbcp-4L, 0x2.b9495a0e3741ecc4p+0L, 0x2.b9495a0e3741ecc8p+0L }, + { -0x1.b1ad8c2578262e12p-4L, 0x9.d1177d54049414p-4L, 0x1.bddecac7f2edd0d6p+0L, 0x1.bddecac7f2edd0d8p+0L }, + { 0x2.1253578fc85773e4p-4L, -0x9.c82e26cb2d7f53dp-4L, -0x1.5cb2d32b7dd67718p+0L, -0x1.5cb2d32b7dd67716p+0L }, + { 0xf.27497e66d5603e2p-52L, -0x1.106fbe1bb8bb675p-4L, -0x1.921fb54442c3472cp+0L, -0x1.921fb54442c3472ap+0L }, + { -0x2.834fa5093bae17c8p-4L, -0x4.be621d3bea89ab38p+64L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x8.b87762725b3d25ep-4L, -0xb.917c5b4d5562a58p-96L, -0x1.53990086a1a7d33ep-92L, -0x1.53990086a1a7d33cp-92L }, + { 0x1.232c19a7b93aed74p-4L, 0x6.c11fd7b2f21ba82p+84L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x6.ca169f967701482p-4L, 0x3.959fe15d515a94ap-20L, 0x8.727c2adf96323fcp-20L, 0x8.727c2adf96323fdp-20L }, + { 0xb.d05c1485606d27ep-4L, 0x5.4c9a1c93895dca38p-6076L, 0x7.2d4b9799a5cc26c8p-6076L, 0x7.2d4b9799a5cc26dp-6076L }, + { -0xa.aa5f16e89aaf44cp-8L, 0x1.a020e5ecd83f5f0ap+92L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x9.4873bc564770dcap-4L, 0x9.a30d5a20e7f065cp-4L, 0x2.5665d2a4b1ec940cp+0L, 0x2.5665d2a4b1ec941p+0L }, + { 0x8.fb1811913b9bf9fp-4L, -0xf.92fca557186ff76p-4L, -0x1.0c3797d9ba60eabap+0L, -0x1.0c3797d9ba60eab8p+0L }, + { 0x1.5638b03330502364p+5720L, 0xc.61775f4969ec8fep-4L, 0x9.42ee4d5147e88c7p-5724L, 0x9.42ee4d5147e88c8p-5724L }, + { 0x1.72119aad9ca3b71ep-4L, 0xe.a69471f34698825p-4L, 0x1.78f2269fea0fe2bcp+0L, 0x1.78f2269fea0fe2bep+0L }, + { 0x4.012c7e08cbaa9478p-4L, 0x9.7bae07b48f3d186p-8L, 0x2.59db176e78ca1928p-4L, 0x2.59db176e78ca192cp-4L }, + { 0x6.fd5607efb3f922bp-4L, 0xa.5d0e52cf5ec81ep-4L, 0xf.a38cbd712f445c9p-4L, 0xf.a38cbd712f445cap-4L }, + { -0xb.3d5a0ceef37dac4p-4L, 0xa.7bf3bd59441655fp-4L, 0x2.6415b8938c9c69f8p+0L, 0x2.6415b8938c9c69fcp+0L }, + { 0xa.9cecb0eb313d3bp-4L, 0x1.34e865521b1a17b6p+92L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x6.d2e474b6031561b8p+92L, -0xa.5245ba426d8cb8dp-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x3.d8775bbd6cd0492cp-4L, -0x4.e24c77188e4a7c38p-4L, -0x2.3ce04e2b601eabdcp+0L, -0x2.3ce04e2b601eabd8p+0L }, + { -0x2.208fc355984ce044p-4L, -0x5.bdde15084dbc54b8p-4L, -0x1.ecf436be968f6d2ap+0L, -0x1.ecf436be968f6d28p+0L }, + { 0xc.43cdb6d485f521ep-4L, 0x6.87c475984cf17fd8p+4L, 0x1.903eea125ad80b1ap+0L, 0x1.903eea125ad80b1cp+0L }, + { -0x4.dd382677670dd278p+0L, 0x2.a23ea828ab9892c8p-4L, 0x3.1b966a3063100448p+0L, 0x3.1b966a306310044cp+0L }, + { -0x3.8b954314786b23ap-136L, -0xa.9d6c0aac945f352p-8L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xd.2671cf0537f0221p+8056L, -0x4.d16dd659f3c0f0ap-4L, -0x5.dcbaf59e460c343p-8064L, -0x5.dcbaf59e460c3428p-8064L }, + { -0x6.feb91f876d8ea878p-4L, -0x8.81efd63e6be1cf2p-4L, -0x2.4249875056a07d8p+0L, -0x2.4249875056a07d7cp+0L }, + { 0xf.bc0fa0f885ca099p-4L, 0x5.7c08324a140957ap-4L, 0x5.5dc5ee9b879c424p-4L, 0x5.5dc5ee9b879c4248p-4L }, + { 0x4.edb009626e4967fp-4L, 0x3.37c8d44a2dd88cbp-4L, 0x9.413cc440ef46a35p-4L, 0x9.413cc440ef46a36p-4L }, + { 0x1.95eaf72aa7e08a9ep-4L, -0x8.1b7b5887913ebf5p-4L, -0x1.60ae1adef48fda1p+0L, -0x1.60ae1adef48fda0ep+0L }, + { -0xb.5359194b44145bbp-4L, -0x6.04e85f85770e42f8p+16L, -0x1.921fd35f3b27f2f2p+0L, -0x1.921fd35f3b27f2fp+0L }, + { -0xb.4501e0be159d16ap-4L, -0x1.fac44e7ef22a75e2p-8244L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x5.4c01faa961b17b48p-4L, -0x7.06bc16cdb0784c5p-4L, -0x2.377e1cc99262c594p+0L, -0x2.377e1cc99262c59p+0L }, + { -0xe.d9260d8b3735c8cp-4L, -0x8.ca13ee6d024020bp-4L, -0x2.9b6bee6c5172a15cp+0L, -0x2.9b6bee6c5172a158p+0L }, + { 0xe.1b10c6cf509583p-4L, 0xc.ce2bca2cbcab86p-4L, 0xb.cb38da4c1afe696p-4L, 0xb.cb38da4c1afe697p-4L }, + { -0x3.9a147b2294cce81cp+9392L, 0x8.35964c3a9d13241p-4L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { 0x7.2dae4682b4686c98p-4L, 0xa.762ab4fc1d5ab9bp-4L, 0xf.82b60dca04dac5ap-4L, 0xf.82b60dca04dac5bp-4L }, + { 0x1.c7999bbe18984522p+7836L, -0x5.73257b4e6064d01p-4L, -0x3.0fed7d28e284ea74p-7840L, -0x3.0fed7d28e284ea7p-7840L }, + { 0x3.8c2ba3fe7042d388p-116L, 0x7.d5dc9701e1e187bp+124L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xc.68e5a8454d59578p-4L, 0x7.1fd64b9a5df38ef8p-4L, 0x8.56a48c286152098p-4L, 0x8.56a48c286152099p-4L }, + { -0x4.881b83c2dca08bfp-116L, 0xa.91f8d787af80328p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xd.d1efe43682ae912p-4L, -0x3.528a6db95c7dfd34p-4L, -0x3.c65d2785eeb5cedp-4L, -0x3.c65d2785eeb5ceccp-4L }, + { -0x2.5775a364301f7598p+4216L, -0x5.c36184a826a997c8p-2260L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x3.7d2d5d25047b7ecp-128L, -0x7.fb0b49661b4b20b8p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x7.15fab912af52fa78p-84L, 0x1.8a9bf648a0c7536ap+136L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x1.e21c9844f30c3324p-44L, -0xa.36231bab07402b6p-8L, -0x1.921fb54445c4ebd4p+0L, -0x1.921fb54445c4ebd2p+0L }, + { -0x9.d3efb895e20c043p-4L, 0x6.44c77e7837d61e48p-4L, 0x2.92e529b4f918d0dp+0L, 0x2.92e529b4f918d0d4p+0L }, + { 0x1.b7e2cb7d51c65e38p-4L, -0x9.ab90feeee0a43a6p-4L, -0x1.651ad72533e8b13p+0L, -0x1.651ad72533e8b12ep+0L }, + { -0x1.705075c296c945a2p+8148L, -0xd.8fb34ea26dcd466p-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x4.3b9909e92aa74c08p-4L, -0x5.5c31877c53bcf0bp-160L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x2.ab275d4d45f58b1p+40L, -0xd.f1e17f7d11f6ef4p-4L, -0x3.243f6a88854f6cdp+0L, -0x3.243f6a88854f6cccp+0L }, + { 0x8.5d50acd960ea87ap-4L, -0x3.cdaf1e5edd4c86p+48L, -0x1.921fb54442d1613ap+0L, -0x1.921fb54442d16138p+0L }, + { 0x7.1c63b6c0603b465p-4L, -0x5.06c95cd2eef04c08p+7836L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xd.4ef26051ededf26p-4L, -0x1.e5ffb4e52e88dbbp-60L, -0x3.243f6a8885a308bp+0L, -0x3.243f6a8885a308acp+0L }, + { -0x3.7a1dacb5eeed287p-4L, -0x2.75255c967504f764p-4L, -0x2.86bc274ba5844bep+0L, -0x2.86bc274ba5844bdcp+0L }, + { 0x9.43cd9e2120286b3p-4L, 0x1.1f40e2b07af92cdap-144L, 0x1.f012f92279311758p-144L, 0x1.f012f9227931175ap-144L }, + { 0xe.e44b7be402e1d81p-4L, 0x2.19395d52c4ffbbep-140L, 0x2.413416ce00a833e4p-140L, 0x2.413416ce00a833e8p-140L }, + { -0xf.099c3c9b804cd09p-8L, 0x6.c417103ca3c8b37p+384L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x1.8768dd184e3fbefcp+264L, 0x9.4f4b6e56944c6fep-4L, 0x6.16c8f28c7cc0ba38p-268L, 0x6.16c8f28c7cc0ba4p-268L }, + { -0xa.9b8d5570d3354bfp-4L, -0x3.44d2e445d54ef838p-4L, -0x2.d7b9029e74d35b4p+0L, -0x2.d7b9029e74d35b3cp+0L }, + { 0x8.d490d42bb07e2c7p-4L, 0x6.1bb3f5bd906ea9d8p-4L, 0x9.aeb69331ab83233p-4L, 0x9.aeb69331ab83234p-4L }, + { -0xb.d1da672fb0a4a6cp-4L, -0x3.cd44320f7cb17634p-4L, -0x2.d494aaaf940ef35cp+0L, -0x2.d494aaaf940ef358p+0L }, + { -0xe.e798701cb00ba65p-4L, 0x6.188c517655d962b8p-4L, 0x2.c0dc1cb781eb0c04p+0L, 0x2.c0dc1cb781eb0c08p+0L }, + { -0x5.a44cc952f2f84af8p-4L, -0x7.3f72b7eca34409f8p-2908L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x1.99cd1db7dfc4219ep-8264L, 0x8.4553ceee4227da5p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x3.a5fcc10d81eb5f18p+120L, -0x1.43edbd1c91c01de4p+112L, -0x5.8c967b142642a9f8p-12L, -0x5.8c967b142642a9fp-12L }, + { 0x1.5e17b3337849e126p-4L, 0xc.21be7e1f393f14fp-4L, 0x1.75634482719a6aa6p+0L, 0x1.75634482719a6aa8p+0L }, + { 0x4.4c7fdb3702f28548p-8L, 0xa.75cd63ad7a1fc3cp-4L, 0x1.8b8cbd8921671fd6p+0L, 0x1.8b8cbd8921671fd8p+0L }, + { 0xe.8b29d8cde8987f8p-4L, 0xd.887cf89ee3f6121p-4L, 0xb.fda4e7230ad4398p-4L, 0xb.fda4e7230ad4399p-4L }, + { -0x4.94c6afdd6c82228p-4L, -0x1.05fda0e408aa74dap-4L, -0x2.ebfb96a3f9a42878p+0L, -0x2.ebfb96a3f9a42874p+0L }, + { 0xa.3670397a0014cd8p-4L, 0x3.a35da38274ac5cap-4L, 0x5.79be30299d3f009p-4L, 0x5.79be30299d3f0098p-4L }, + { -0x1.6e3230adc36fa2d4p+72L, 0x2.46b281598ef2f5a8p+68L, 0x3.0adf2743dfff3e94p+0L, 0x3.0adf2743dfff3e98p+0L }, + { 0x2.60029db4ae9896f4p-4L, 0x9.b40053c694dc073p-4L, 0x1.54abbdf7c77fd402p+0L, 0x1.54abbdf7c77fd404p+0L }, + { 0x2.b4e66bc066d0d2dp-4L, -0x5.4231e76df18908fp-4L, -0x1.186f69ed098e7cbcp+0L, -0x1.186f69ed098e7cbap+0L }, + { 0x1.b1a6f7bbb2a87d3ap+4L, 0x2.811588b8fd1e13dcp-4L, 0x1.7a73376fe2e0dffcp-8L, 0x1.7a73376fe2e0dffep-8L }, + { 0x9.818682634b4f569p+48L, -0xd.948c0f98202cba9p-4L, -0x1.6db912400d2d0042p-52L, -0x1.6db912400d2d004p-52L }, + { 0x5.c78c1527fbed2cb8p-132L, 0xf.4d427c83cc48947p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x5.9703943df8daac68p-4L, 0xb.e333189d0552193p+108L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0xd.9f9ad2fbb7114c8p-8L, 0x7.30036483bed4a05p-12L, 0x3.1bcf3458f84318fcp+0L, 0x3.1bcf3458f84319p+0L }, + { 0x2.a5a39f32557c8ep-4L, -0x3.170c659960195678p-4L, -0xd.cca65d3fe500765p-4L, -0xd.cca65d3fe500764p-4L }, + { 0x2.82da0a654e4b095cp-4L, 0x6.cf128f250e94a368p-4L, 0x1.37ac0c52f9b10dd8p+0L, 0x1.37ac0c52f9b10ddap+0L }, + { 0xd.76c3b09c76ff3e9p-4L, 0x9.07955929333661ap+116L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x5.81cb354b63bfe2p-60L, -0x1.87e903d0c3db82e4p+4L, -0x1.921fb54442d18466p+0L, -0x1.921fb54442d18464p+0L }, + { -0xa.2353060706c5cabp-4L, 0x1.fb0b63a1a1d40916p-11204L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0xd.5b6d7ec2493a866p-4L, 0xb.feeccb085d9a77fp-4L, 0x2.68eb2ca1b4fe66ccp+0L, 0x2.68eb2ca1b4fe66dp+0L }, + { 0xd.8290d23d319cf46p-4L, 0x7.8f36bd86059e0dp+60L, 0x1.921fb54442d18466p+0L, 0x1.921fb54442d18468p+0L }, + { 0x9.228ffe9d2dbc7a8p-4L, 0x3.4d0b2cb006ec1248p-76L, 0x5.c818c6860b871adp-76L, 0x5.c818c6860b871ad8p-76L }, + { 0x5.d6213cf1fe6c0418p-4L, 0x1.4fb6400683507e4p-108L, 0x3.9851a6b04169056cp-108L, 0x3.9851a6b04169057p-108L }, + { 0x1.2e57c4035227f4a4p-4L, 0x3.8b63b08dc84596bcp-44L, 0x3.004e3b1435fcb234p-40L, 0x3.004e3b1435fcb238p-40L }, + { -0x1.4360cd0166c1bb96p-96L, 0x5.6b1f6c08a8c74bd8p-48L, 0x1.921fb54442d1c016p+0L, 0x1.921fb54442d1c018p+0L }, + { 0xa.16180a40d8df5dap+5656L, -0x1.0b5029b46f526448p-4L, -0x1.a80a966ff0d212dcp-5664L, -0x1.a80a966ff0d212dap-5664L }, + { 0xf.cc3eef919eef062p-84L, 0x1.a712ef62b430fa34p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x5.f94934066073bd08p-4L, 0x6.09560f5c4171de98p-4L, 0xc.a65f6b1a7f95643p-4L, 0xc.a65f6b1a7f95644p-4L }, + { 0x7.901026e26c2bf698p-4L, -0xe.7c231718ee90eb4p-4660L, -0x1.ea50f230ad14fcbap-4656L, -0x1.ea50f230ad14fcb8p-4656L }, + { -0x3.6877a67287c33a24p-148L, -0xb.ccb04bd726e2f1cp-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xe.92b733496bc40efp+104L, 0x3.7e80673dfbabc99p+104L, 0x2.e80131ce1300ed4cp+0L, 0x2.e80131ce1300ed5p+0L }, + { 0x2.f8fd52cb8aa2f7cp-24L, 0xd.8eb4579dad84402p-4L, 0x1.921fb1c22b2c5adap+0L, 0x1.921fb1c22b2c5adcp+0L }, + { -0x5.5efd70abd2079fd8p-4L, 0x5.f015b527caae88c8p-4L, 0x2.4e5dc999616481bcp+0L, 0x2.4e5dc999616481cp+0L }, + { 0xc.5b36895077a659cp-4L, -0xe.6156c69bf7850ffp+68L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xc.41d507fb40798b9p-4L, 0x6.044acf83853e4228p-4L, 0x2.af6dd05f6ba7bd54p+0L, 0x2.af6dd05f6ba7bd58p+0L }, + { 0xd.b86c5707774a4a2p-4L, 0x7.eedd2b5801d30ddp-4L, 0x8.6340d5849f75649p-4L, 0x8.6340d5849f7564ap-4L }, + { -0x6.f6e101329750c02p+0L, -0x7.d6f975423ed1769p-4L, -0x3.124429a16a9c980cp+0L, -0x3.124429a16a9c9808p+0L }, + { -0x3.be6d312c65754ef8p-80L, 0xb.cb682f76a3f814p-60L, 0x1.921fba586c06424p+0L, 0x1.921fba586c064242p+0L }, + { 0x1.8221ab8a45beb70ap-4L, -0x3.b4684654db9a5424p+140L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x9.2d8b2c3da2a1544p-4L, 0x5.24f70f7b34e69378p-4L, 0x2.a17623dc05226ce8p+0L, 0x2.a17623dc05226cecp+0L }, + { 0x8.691578498705b78p+80L, 0xb.3bee0e72b609f1bp-4L, 0x1.55f2221d830f232ap-84L, 0x1.55f2221d830f232cp-84L }, + { -0xc.da6a20364262f65p-4L, 0x2.4877b265ab1f3a8p-13304L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x4.405714e489cdecc8p-8L, -0xc.15f1a93e28bcd0ep-4L, -0x1.97c04dd68088ca78p+0L, -0x1.97c04dd68088ca76p+0L }, + { -0xb.073911421d09748p-4L, -0x1.b5c0a4dd8c1566fcp-4L, -0x2.fcde10ab4dd76134p+0L, -0x2.fcde10ab4dd7613p+0L }, + { 0xe.d559a68601d334ep-4L, 0x2.d0d0da1fed32adecp-4L, 0x3.005d3f535fcec9ecp-4L, 0x3.005d3f535fcec9fp-4L }, + { 0xc.eb3db51a4117749p-4L, -0xe.a7ff95de9e6b04bp+32L, -0x1.921fb54434b70d58p+0L, -0x1.921fb54434b70d56p+0L }, + { -0x9.b242f08632fe79dp-4L, 0xf.7392589b824fb9dp-4L, 0x2.21976ce06de5b27cp+0L, 0x2.21976ce06de5b28p+0L }, + { -0x3.866d6f28fe022bf8p-4L, -0xf.6920f8295b7bddcp-4L, -0x1.cbb12c5cf3020402p+0L, -0x1.cbb12c5cf30204p+0L }, + { -0xd.371b90dc936973ap+1584L, -0x2.03fc72188444e274p+1388L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0xc.8841513e4940958p-8L, 0xf.dacd69f337492f8p-4L, 0x1.9ec2bc5751b6109ep+0L, 0x1.9ec2bc5751b610ap+0L }, + { -0x2.1b6b60da18fb188p+56L, -0x1.375db6599b3290d6p-144L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x8.4bc36bd85a13605p-4L, 0x7.511fbab815148398p-4L, 0x2.6b37dcb798ecddc8p+0L, 0x2.6b37dcb798ecddccp+0L }, + { -0x1.226db2320a4bbd76p-4L, 0xe.9620cf5661a993ap-4L, 0x1.a5fea59ad16975acp+0L, 0x1.a5fea59ad16975aep+0L }, + { -0xe.9dcdafd35f490bep-4L, 0xf.47291cfe1ffaef4p-4L, 0x2.558583302f17d3ccp+0L, 0x2.558583302f17d3dp+0L }, + { 0x3.73491a68bdddaaccp+144L, 0x8.aa229058b7ec91ap-4L, 0x2.82e01ab54a6a64ep-148L, 0x2.82e01ab54a6a64e4p-148L }, + { 0x4.ad7c3e0240e17358p-4L, 0xe.3ba47f6dc65238dp-4L, 0x1.40d60ca76f3b16bcp+0L, 0x1.40d60ca76f3b16bep+0L }, + { 0x3.392a62c6b703c4ecp-4L, -0xa.05c344dc8437ce9p-4L, -0x1.427790ebd5ffa4dap+0L, -0x1.427790ebd5ffa4d8p+0L }, + { -0x4.cfc2d12040fe801p-4L, 0x5.008114fbefa3ff4p+6792L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x6.430b313e463247bp-4L, 0x8.e2b7001bf08e40cp-140L, 0x1.6b43699da53b302ap-136L, 0x1.6b43699da53b302cp-136L }, + { 0x1.85dde85b05b8945p-4L, -0x2.f667e823e60719c4p-4L, -0x1.18910e0e7794c9bep+0L, -0x1.18910e0e7794c9bcp+0L }, + { 0x3.6dcf06d4e2c69044p-4L, -0x3.216851a5299104fp-4L, -0xb.d6c24b0a25b1c6dp-4L, -0xb.d6c24b0a25b1c6cp-4L }, + { 0x6.f6bb9a4c17f8e4c8p-4L, -0xf.d713d37adb465cp-4L, -0x1.2816ea59da6ddadep+0L, -0x1.2816ea59da6ddadcp+0L }, + { 0x1.0313a7bf52f62c6ap+12220L, -0x5.4b92638de9222f68p-4L, -0x5.3b792079fc7b5658p-12224L, -0x5.3b792079fc7b565p-12224L }, + { -0x5.07a5e167ee5ee938p-4L, 0xa.fe50b439a96ea55p-32L, 0x3.243f6a658d516568p+0L, 0x3.243f6a658d51656cp+0L }, + { 0x7.4d40bb5519f17438p-4L, 0x6.57ce3bc088dbf5bp-4L, 0xb.71a620269adc806p-4L, 0xb.71a620269adc807p-4L }, + { -0xb.344b56eb02935aap-4L, -0x2.aa06a7b698b0b3e4p-4L, -0x2.e87c4fa4fad0ed48p+0L, -0x2.e87c4fa4fad0ed44p+0L }, + { -0x7.d11224fd32351718p-4L, 0x3.7e5a21b23d5c1b64p-20L, 0x3.243ef81e138f1854p+0L, 0x3.243ef81e138f1858p+0L }, + { -0xf.a08ab502ee0f01p+144L, 0x6.cf1c3e55412fd6cp-128L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x6.48717c11cd853a38p+12L, -0xd.f459b71bee5f0a9p-4L, -0x3.243d31f5270113d8p+0L, -0x3.243d31f5270113d4p+0L }, + { -0x2.ae45f1d99d8191ap-4L, -0x1.6d0da510a3e13b48p+72L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x1.4f51a9b3e2d85878p-36L, -0x8.0b439abc08ea7e9p-4L, -0x1.921fb544192200cep+0L, -0x1.921fb544192200ccp+0L }, + { 0xe.7c272173ede747dp-8L, 0x2.2303df6a957df77cp+128L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xd.078697a133ad5cep-4L, 0xe.dbf635b5992761bp-4L, 0xd.9d5a5adb9750ca4p-4L, 0xd.9d5a5adb9750ca5p-4L }, + { 0xe.1ec636774861dd1p-4L, 0x6.90fde6638ef190ap-4L, 0x6.f6edca5da7e976ep-4L, 0x6.f6edca5da7e976e8p-4L }, + { 0x9.2892f7ae1a4dc1cp-4L, 0x9.59de5e82fe42ee3p-8L, 0x1.05074845332e8fbp-4L, 0x1.05074845332e8fb2p-4L }, + { 0xa.0bd8e2fed33d2fbp+48L, 0x7.1e8449954445192p-4L, 0xb.56981838fbcdfb4p-56L, 0xb.56981838fbcdfb5p-56L }, + { 0x6.9391bf7167786018p-88L, -0x5.ee980a26e834c06p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xb.c8e75dd8cc31c5fp+4172L, -0xa.56e2685bfa417eep+140L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x1.24a1e06c9ce90bacp+12L, 0x3.a60249453e7b9ccp-96L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x2.c8627289ae027344p-88L, -0x6.9b634305e9253b2p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x1.373f26e92bcb57d2p-144L, -0x2.e1e1c6f6c78bd3c4p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x9.70dc7ea202b3d6ep-4L, 0x1.a18f74fd6269755cp-4L, 0x2.f87376c50bbbb78p+0L, 0x2.f87376c50bbbb784p+0L }, + { -0x5.70d6e285f6741be8p-4L, 0x3.ba6b718acd54f7f8p-8L, 0x3.194a6a535ac8d614p+0L, 0x3.194a6a535ac8d618p+0L }, + { 0x2.6d98cc2767fd89d8p-4L, 0xc.808b2b8f5b868bp-4L, 0x1.610412f8c9e8121ap+0L, 0x1.610412f8c9e8121cp+0L }, + { 0xf.2e99194f7ef31f7p-4L, -0x2.e9a1c1b2321b87a4p-4L, -0x3.085f31e10671090cp-4L, -0x3.085f31e106710908p-4L }, + { -0x3.924e6e858ddf4824p-4L, 0x2.9a401dba30d7dcep+10456L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x6.5f0b8c236d8dc8f8p-2672L, -0x2.c8e3c20a2013488p+2656L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xd.d75e9619a100a7fp-8L, -0x4.91095f75c24e73a8p+12L, -0x1.921fe5c34e2b3f08p+0L, -0x1.921fe5c34e2b3f06p+0L }, + { 0xa.b860bc07bcd9d43p-4L, -0x1.5cffc658f2525a68p+32L, -0x1.921fb543c5005914p+0L, -0x1.921fb543c5005912p+0L }, + { 0x2.39efe79c36d491e8p-8L, -0xc.844c97b8d649ddcp-4L, -0x1.8f4732858a9cdac8p+0L, -0x1.8f4732858a9cdac6p+0L }, + { -0x3.bc36c1490d0a008cp-4L, 0x3.7373aa65594e9ba4p+28L, 0x1.921fb54557e72276p+0L, 0x1.921fb54557e72278p+0L }, + { 0x1.e030a1263fac45b6p-4L, 0x4.6a742a7f7f068b1p-4L, 0x1.2b4b21e62728d41cp+0L, 0x1.2b4b21e62728d41ep+0L }, + { 0x1.abcbe4707103d132p-36L, 0x2.63828893421a22a8p-4L, 0x1.921fb5438fba3b7ap+0L, 0x1.921fb5438fba3b7cp+0L }, + { 0xe.fa45bfa0e35be11p-4L, -0x2.6aa2a2cda06315ep-68L, -0x2.94dd051d34d86718p-68L, -0x2.94dd051d34d86714p-68L }, + { -0x5.033b46cdbeb340cp+16L, 0x3.8a8a6bba3cfe8078p-8L, 0x3.243f69d3aba38a3cp+0L, 0x3.243f69d3aba38a4p+0L }, + { -0x6.c85e2b71c3374258p-4L, -0x5.27a1297f363c8d48p-4L, -0x2.7de1bf0aef3c59b8p+0L, -0x2.7de1bf0aef3c59b4p+0L }, + { -0xd.3df3c95e345f91cp-4L, -0x2.d4dacdbb7574d32p-4L, -0x2.ee521baede0beaa8p+0L, -0x2.ee521baede0beaa4p+0L }, + { 0x3.e0f12593c01b4688p-4L, 0xf.2f0dd139a8e6154p-68L, 0x3.ea28b93c20ccdc1p-64L, 0x3.ea28b93c20ccdc14p-64L }, + { -0x7.0a9be4dfe4012efp-4L, -0x9.79c050222c1c028p-4L, -0x2.35ba688648eae5b8p+0L, -0x2.35ba688648eae5b4p+0L }, + { 0xe.69fc312b6c20148p-4L, -0xa.7ae82870e738fcdp-8L, -0xb.a0105da162b779dp-8L, -0xb.a0105da162b779cp-8L }, + { 0x1.9c08b5ae28dcf1ep-4L, 0x8.966bd426c329fd3p-4L, 0x1.62b1a3a4abfa30dap+0L, 0x1.62b1a3a4abfa30dcp+0L }, + { -0x9.7e7da70cdfaf86fp-4L, 0x5.9e39f65bc056fafp-4L, 0x2.9b75d071d8859284p+0L, 0x2.9b75d071d8859288p+0L }, + { -0x3.10308c990392d81p-4L, 0x7.5314fd852999079p-8236L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x5.2778b767dd6e12ap-4L, 0x6.8c1f80f76611751p-4L, 0x2.3cd97d6e9dd74d8cp+0L, 0x2.3cd97d6e9dd74d9p+0L }, + { -0x1.11d59a15316df40ep-88L, 0x1.b17a45abfaca7818p+84L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x8.4fc3ad0329a03fbp-24L, -0x7.730ab999d45ba668p+36L, -0x1.921fb54442d1847cp+0L, -0x1.921fb54442d1847ap+0L }, + { 0xf.4ddfc0a6a7ff926p-4L, 0xc.a51ad22241bf9a4p-3400L, 0xd.3847934faa3ce58p-3400L, 0xd.3847934faa3ce59p-3400L }, + { -0x3.749a4e30ff80721p+132L, 0x8.653a7b58a965687p-8L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x6.0147c8355dcb5118p-4L, 0xa.bbdd8af3b148586p-4L, 0x2.14b363e8be093404p+0L, 0x2.14b363e8be093408p+0L }, + { 0x9.b485a2016e89ac8p-4L, -0x6.c0577b0cfdc16538p-4L, -0x9.b9887f0bf97893p-4L, -0x9.b9887f0bf97892fp-4L }, + { 0x1.f3982a7709f0cbp+40L, 0xf.70ce68e262f1e86p-4L, 0x7.e97ada86bdfd66a8p-44L, 0x7.e97ada86bdfd66bp-44L }, + { 0xa.00f17ea146af72cp-4L, 0xd.87fd71f7ada2ddap-4L, 0xe.f2621401a87f5aap-4L, 0xe.f2621401a87f5abp-4L }, + { 0xf.8d6956f54124902p-4L, -0x3.c7f4fe11df2d42d8p+104L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xe.dc1b8debe374cf4p+116L, -0xc.0eeac80f65e8216p-4L, -0xc.fbc762d00c60c7ap-124L, -0xc.fbc762d00c60c79p-124L }, + { -0xf.b4cea5f9045b01ap-4L, 0x1.0c2e698750b7e94cp-96L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0x8.d79e88a664c070ap-4L, -0xf.9450f9ab4f8d17p-4L, -0x2.1647280289f2978cp+0L, -0x2.1647280289f29788p+0L }, + { -0x6.eebd8fca95c9ca4p-8L, -0x2.7d3fe1c0d9eb617cp-4L, -0x1.be3dea5c2a040718p+0L, -0x1.be3dea5c2a040716p+0L }, + { -0x3.afe78e9efcbac40cp+140L, -0x1.68e1081fbf7d13e6p+1008L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x7.c520bfdab8a3eep-4L, -0x1.66b5c099afee3a44p-4L, -0x2.dacc8235e43513fp-4L, -0x2.dacc8235e43513ecp-4L }, + { 0x1.e4933a2a2ddf904p+136L, 0xd.784941952fe4cecp-4L, 0x7.1db8e5d213caf838p-140L, 0x7.1db8e5d213caf84p-140L }, + { 0x4.3c17087b908950fp+7148L, -0x3.735c047b159adcccp-4L, -0xd.099540663e33b06p-7156L, -0xd.099540663e33b05p-7156L }, + { 0xc.281ad4f7e7b2506p-4L, 0xd.32303b9dcb960d7p-4L, 0xd.38d23e57b79989p-4L, 0xd.38d23e57b799891p-4L }, + { 0x7.8695060ae1f9a64p-4L, -0x2.3be9aa14143c731cp+104L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x7.62db900b9f9d9668p-4L, -0x6.cfd1fde0bfa23d8p-4L, -0xb.eb61a702cf9e3e1p-4L, -0xb.eb61a702cf9e3ep-4L }, + { -0xf.bb4bad527dbb40ep-4L, -0x5.3e9ef2b10884ee28p-10036L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x9.5778bac96c5960dp-4L, -0x1.178465778778ce2ep+14336L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x8.7ef9939b4465e16p-4L, -0x3.51600c72922bbfc4p-4L, -0x5.f4fa36d23aa5506p-4L, -0x5.f4fa36d23aa55058p-4L }, + { 0x2.5131dd015a69e96cp-2408L, 0xa.870e0a37a4eeddcp-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x2.880d15d9bf79a448p-4L, 0x2.446fd3d9665e1568p-4L, 0xb.afc7a6c62bd905fp-4L, 0xb.afc7a6c62bd906p-4L }, + { -0x2.31a4e2380b4c16cp-4L, -0x7.645911f7f5f4b208p-4L, -0x1.dbfbe65a7e307902p+0L, -0x1.dbfbe65a7e3079p+0L }, + { 0xb.2103d74317cc086p-4L, 0xf.771337e878bf499p-4L, 0xf.2704bf58b4bb6a8p-4L, 0xf.2704bf58b4bb6a9p-4L }, + { 0xe.861c26d80ccd5dfp-4L, -0x1.3d69ace2aa20b076p-36L, -0x1.5dac4c2bc3e57078p-36L, -0x1.5dac4c2bc3e57076p-36L }, + { -0x2.aff893fd182e92bp-152L, 0x4.141b510c6c3a2c78p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x8.56bda974ea2dec7p-4L, 0xa.7ba4137b5209863p-4L, 0x2.3e25e1fea85cbe24p+0L, 0x2.3e25e1fea85cbe28p+0L }, + { -0x6.80d745f6314c29dp-4L, 0x1.7c7e424cf77b8afep-76L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { 0x6.cced41d6279d2138p-4L, 0x1.c0e570d143bef0eep-4L, 0x4.09a27a95df0f54cp-4L, 0x4.09a27a95df0f54c8p-4L }, + { 0x6.5df497b7697155a8p+1564L, -0x3.ddba85629b3426e8p-4L, -0x9.b723fdc7b00661cp-1572L, -0x9.b723fdc7b00661bp-1572L }, + { -0x4.760b9460983c0a5p-4L, 0x4.8c8e8f6197ef9bd8p-4L, 0x2.58aff93ef60ec054p+0L, 0x2.58aff93ef60ec058p+0L }, + { -0xd.529973ed01b4e92p-132L, -0x3.6712c0d838d018e8p-68L, -0x1.921fb54442d1846ep+0L, -0x1.921fb54442d1846cp+0L }, + { 0xc.1f8b7a784c26504p-4L, -0xa.67183c5cde7a566p-4L, -0xb.58bfac992b804b5p-4L, -0xb.58bfac992b804b4p-4L }, + { -0x6.19f5de19ed7257a8p-4L, -0x7.3398eb375f75dfb8p-4L, -0x2.46101795deb7d9d8p+0L, -0x2.46101795deb7d9d4p+0L }, + { -0x7.36616a1fa5db84fp-4L, 0xa.2ee450fb24733e3p-4L, 0x2.2fe288a6338d798p+0L, 0x2.2fe288a6338d7984p+0L }, + { -0x4.438c4fc90d39b8ep+96L, -0x7.4f02a205338a33ap-64L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x2.c8f196a2f3e8ed9cp-9224L, -0x3.03786e351e5ebe78p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xf.2253cc715933c65p-8L, 0x5.6a7fda73f84b1c18p-4L, 0x1.65dc717427bbf3f2p+0L, 0x1.65dc717427bbf3f4p+0L }, + { -0x2.a28f500b8a00b09p+14092L, -0x1.0843d15dc3b8cafp-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0xd.fca2fa696c2274ap-4L, -0x4.0718db0d5c58c15p-4L, -0x2.dc787f077ff8e63p+0L, -0x2.dc787f077ff8e62cp+0L }, + { 0x3.9a1be41771a60404p-4L, 0x1.80953538294166f8p-12L, 0x6.ac4fe9d96a3bf4f8p-12L, 0x6.ac4fe9d96a3bf5p-12L }, + { -0xb.7124296f93e8defp-4L, -0x1.98246e4efb47458ap-4L, -0x3.00ce24c21911792p+0L, -0x3.00ce24c21911791cp+0L }, + { 0xb.839f5cfd4cd5f2cp+8436L, 0xa.61c8331ffa99071p-4L, 0xe.6d3d4051b118d3p-8444L, 0xe.6d3d4051b118d31p-8444L }, + { -0x1.6b1b156ea818eb8p-4L, 0xf.d7c5e11a00df0a5p-4L, 0x1.a8fb6c440c3be30cp+0L, 0x1.a8fb6c440c3be30ep+0L }, + { 0x8.598d995551324f1p-4L, 0xd.e18c0d942a69d5bp-4L, 0x1.077d42bee50504fcp+0L, 0x1.077d42bee50504fep+0L }, + { 0x6.93e866ab2447886p-4L, -0x2.26e07207dc8de1ep-4L, -0x5.0f06179f8f3a16fp-4L, -0x5.0f06179f8f3a16e8p-4L }, + { -0xf.1ce9f7b3ca52b8bp-4L, -0x1.399c88aa8d8d6c48p-4L, -0x3.0f8ab40146b6b5f8p+0L, -0x3.0f8ab40146b6b5f4p+0L }, + { -0xe.ff04c61a0a89012p-4L, -0x6.cb47f83a640007dp-9320L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x4.593edb241f803048p-4L, -0x9.cafddfe1d9bc214p-4L, -0x1.fd1b36f82d14fef4p+0L, -0x1.fd1b36f82d14fef2p+0L }, + { -0x3.0d234ad1e46298a4p+1408L, -0xd.cb179b353f53154p-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0xe.9bb1c73063ea02dp-4L, 0xd.8a2175b78a11721p-4L, 0x2.64e664936b63d554p+0L, 0x2.64e664936b63d558p+0L }, + { 0xc.25bdb8a9a8881b7p-4L, -0xc.89a9a53dd5661b4p-4L, -0xc.d1c03a780665391p-4L, -0xc.d1c03a78066539p-4L }, + { 0x2.977deccc5900dccp-84L, -0x2.a3636c60ad9b8408p-112L, -0x1.04971135aba73bc2p-28L, -0x1.04971135aba73bcp-28L }, + { -0x1.4529afc43bd67b0ap-4L, 0xa.bf1476588a5cb83p+80L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x8.ebeb881ae8c2fcap-6420L, 0xa.e0e4170c0a4427p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x8.e91c2aa2ea5ec68p-4L, 0x2.91145ecdbb7882f4p+28L, 0x1.921fb540ca177aacp+0L, 0x1.921fb540ca177aaep+0L }, + { -0xf.08bf0e198ffe894p-4L, 0xe.9bb609912a78d12p-4L, 0x2.5edd27ca99c98c7cp+0L, 0x2.5edd27ca99c98c8p+0L }, + { 0x6.df4e4b64d005f82p-4L, -0x3.51711830c018995cp-4L, -0x7.3271f7b631f74408p-4L, -0x7.3271f7b631f744p-4L }, + { 0x3.1bc6c41d7b8d2494p-4L, 0x2.f721c1af4835bb14p-8L, 0xf.3ec38f9992dee5cp-8L, 0xf.3ec38f9992dee5dp-8L }, + { 0xf.4bf5dfe195d4e46p+7524L, 0x3.bbc0f8f07321f77cp+128L, 0x3.e7b20446a0be4ef8p-7400L, 0x3.e7b20446a0be4efcp-7400L }, + { -0xb.bb95272e0c88a4p-4L, 0x1.fe9b64501151218ep-4L, 0x2.f923d79c3f550efp+0L, 0x2.f923d79c3f550ef4p+0L }, + { 0x4.77e9fc00fb36ca1p-4L, 0xf.5b06933a4845034p-16L, 0x3.6fbc6b1f82dbb2ecp-12L, 0x3.6fbc6b1f82dbb2fp-12L }, + { 0x4.4ec472736efece7p-4L, -0x8.3f36b704651a623p-4L, -0x1.16e56e8ac8595702p+0L, -0x1.16e56e8ac85957p+0L }, + { -0x3.debb4f1fb4f3d46cp-8L, 0x8.8d8721565b330cep+120L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x3.60900980dfa6490cp-4L, 0x4.9ad46fe7dab0a5f8p+28L, 0x1.921fb544fe921c84p+0L, 0x1.921fb544fe921c86p+0L }, + { -0x5.d267f39c0a2d5c6p+120L, -0x6.94c6171c5caa9048p-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x9.737b170f2734c17p-4L, 0x2.6fc63483927fd61p+7936L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x1.aac7d5cdfa18f4aap+12364L, 0xf.407ea5dcda35ceep+7392L, 0x9.261246ae706ee0fp-4972L, 0x9.261246ae706ee1p-4972L }, + { 0x5.10a6eb0bc1141b7p-4L, 0x1.68d8f3bd3c6056ecp-108L, 0x4.73e1f9d1f9e61ff8p-108L, 0x4.73e1f9d1f9e62p-108L }, + { -0xc.81e5dc89785e982p-4L, 0xf.821c92eadfd4d2p-4L, 0x2.3fde7bb67cf34c8cp+0L, 0x2.3fde7bb67cf34c9p+0L }, + { -0x9.6cc05530d550225p-4L, -0x3.ae26297bd368fc24p-4L, -0x2.c4f1bbd66d554dd4p+0L, -0x2.c4f1bbd66d554ddp+0L }, + { -0xf.7c61983cdd60da1p-4L, -0xa.9226fd0725f5548p+11124L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xa.bb09710051dcf8dp-92L, 0x1.d1dbba4f78416e6p-8L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x1.3f0ca6d40320444p-4L, -0xa.0d32575627bcf09p-12L, -0x3.1c2f68820068be54p+0L, -0x3.1c2f68820068be5p+0L }, + { 0x1.e12b6bdf6a41d318p-4L, -0x4.925b19d467927c58p-4L, -0x1.2e446699a3dada42p+0L, -0x1.2e446699a3dada4p+0L }, + { -0x3.b5a3dd14cc35d0f4p-80L, 0xf.f1a968c614d2c7bp-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xf.c50d2b0b4759078p-4L, 0xf.297abc86e6d6ca4p-4L, 0xc.4087639b48a9f52p-4L, 0xc.4087639b48a9f53p-4L }, + { -0xe.08a7a2500e47733p+14336L, -0x2.2abc93e7ce82e67p-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x2.02ff48a6ae8c5d58p-4L, 0x2.44174246f08b0914p-4L, 0x2.4bfc95703b29449p+0L, 0x2.4bfc95703b294494p+0L }, + { 0xc.e44944bb412fcb9p-4L, -0xd.eb1d0c38abd1094p-4L, -0xd.2dc44265a1645cp-4L, -0xd.2dc44265a1645bfp-4L }, + { -0xf.f026fffa2c76775p+40L, -0x1.a72bc5f3fc609372p-4L, -0x3.243f6a8885a16004p+0L, -0x3.243f6a8885a16p+0L }, + { 0xb.8b25e8f233c9c46p-4L, -0x5.40149751018e5d7p-4L, -0x6.d46bc98b7c992a28p-4L, -0x6.d46bc98b7c992a2p-4L }, + { -0x5.2ce714d9965b9eb8p-4L, -0x3.d352663ddebb0c3p+2848L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x6.a8e6be614c1b8df8p-4L, 0x9.1772887aa9cf3dep-4L, 0xf.0469050950c1959p-4L, 0xf.0469050950c195ap-4L }, + { 0x2.9f08f6aee7d22224p+92L, 0xb.577c8e19d32b913p-4L, 0x4.53ae4466cb3e5e78p-96L, 0x4.53ae4466cb3e5e8p-96L }, + { -0x1.66b739c29828256ap+140L, -0xb.b90281c3323087ep-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x6.78ac8bb8ab809f28p-4L, -0x7.fbc375dd3564a3e8p+12L, -0x1.921ee5c0cd46c342p+0L, -0x1.921ee5c0cd46c34p+0L }, + { -0xf.8d21bd7dfb2bab3p-4L, -0x2.720b6221072b1ec8p+48L, -0x1.921fb54442d1ea2ap+0L, -0x1.921fb54442d1ea28p+0L }, + { -0xa.b8dbb59c7b569c8p-4L, 0x1.aeedca5050d1070cp-4L, 0x2.fc61e5dba0d3a35cp+0L, 0x2.fc61e5dba0d3a36p+0L }, + { 0x6.28b837f5eb0e965p-72L, -0x5.ebeaa439a80db7ep-76L, -0xf.5d50fec9b391b43p-8L, -0xf.5d50fec9b391b42p-8L }, + { -0xe.ddd4485dc420705p-4L, -0x1.10e4f9cc5932fd56p-10872L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x1.fb13b5cd1fc66386p-4568L, 0x5.cdd697b048eb7df8p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0xc.d21e8ca674c3b8fp-8L, 0x1.7fbcd99b4b7c7f6ep-44L, 0x3.243f6a8883c423c4p+0L, 0x3.243f6a8883c423c8p+0L }, + { 0x9.4618839acbce14p-20L, 0x4.7f188b632b02a568p-4L, 0x1.921da546825dcbbap+0L, 0x1.921da546825dcbbcp+0L }, + { -0x3.bfd0635ddf97bef8p+11616L, -0xa.822efa7aeaf1e3ep-4L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x7.f80bf5f3503e7a08p-4L, -0x5.66fb0c9fd21294p-4L, -0x2.8bbc526a1520f534p+0L, -0x2.8bbc526a1520f53p+0L }, + { 0x5.8bca7ba191d1075p-4L, -0x3.e94049e7c0978424p+11256L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x7.926da2dc2eb3e0c8p-4L, 0xe.ebcfe2cc1e5917ap-4L, 0x2.0a57a10f93327888p+0L, 0x2.0a57a10f9332788cp+0L }, + { 0x9.9c87559b14bd69ep-4L, -0x3.1f5c367f6a8d3b5cp-4L, -0x5.069feaa26d81f0f8p-4L, -0x5.069feaa26d81f0fp-4L }, + { -0x1.f845d0e426ce9e3ep-92L, 0xc.f6cacd60d500638p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x1.36e65c677d6c8f6cp-8L, 0x1.d3eb9e3493db468p+72L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x9.434a0bafd4669fdp-116L, -0xc.0ab2fb511db1a65p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xa.040d4a425532027p-4L, 0xc.b3f2db4a1555938p-4L, 0x2.3d0c0848c1390774p+0L, 0x2.3d0c0848c1390778p+0L }, + { 0xf.0dd7437193656e6p-4L, -0x8.9e9261e5f0cbb96p-4L, -0x8.51ed7de5596cff5p-4L, -0x8.51ed7de5596cff4p-4L }, + { -0x5.fefa7ed009a1ad1p-4L, -0xc.d35706a15ac1dabp-4L, -0x2.02139e1fc30da4f8p+0L, -0x2.02139e1fc30da4f4p+0L }, + { -0x1.429576b6a439e36cp+8536L, -0xa.f28519810a83c71p-8L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x2.e66ff240855b11a8p-4L, 0x3.5c2fcc256af1f36cp+128L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x6.db01716e57cabb6p-4L, 0xd.c13cce87d39e616p-4L, 0x2.087db05ce82d89dp+0L, 0x2.087db05ce82d89d4p+0L }, + { -0x6.94f930f4029ebd6p-4292L, 0xc.6cd86a5a2553727p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x3.9db1698fccb05bb8p-4L, 0xf.1ca25184529230bp-4L, 0x1.55ff8e23c2cfab8p+0L, 0x1.55ff8e23c2cfab82p+0L }, + { -0x8.be66d03d7655fd6p-4L, -0x9.e5220481205cb59p+24L, -0x1.921fb552663f2e1p+0L, -0x1.921fb552663f2e0ep+0L }, + { 0x3.b723bd1111fd51acp-4L, -0x1.a4eb25964fa28b04p-8L, -0x7.142fe4a6d289e84p-8L, -0x7.142fe4a6d289e838p-8L }, + { -0xd.63ff921e325126cp-12464L, 0xf.1bc0b107e859569p+0L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x6.33fe53feb223e4f8p-4L, 0x1.8cebaea5077b3788p+24L, 0x1.921fb5844606fp+0L, 0x1.921fb5844606f002p+0L }, + { -0x5.9e2e3b14b66b70c8p-4L, 0x7.f59f3541b0d99908p-40L, 0x3.243f6a886ef7ccc4p+0L, 0x3.243f6a886ef7ccc8p+0L }, + { 0x6.f51f8676115f0248p+136L, -0x7.1da2696d46c614d8p-4L, -0x1.05d29a4a665da448p-140L, -0x1.05d29a4a665da446p-140L }, + { 0x8.0d6f53062b6d5dap-4L, -0x6.271f8f2a56b072ep-4L, -0xa.70782c23ee3d0bap-4L, -0xa.70782c23ee3d0b9p-4L }, + { -0xf.d56a354a71cc019p-7972L, 0x7.5aff86281b39de38p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xd.c44abbdbb28d90ap-4L, 0x8.4deb3d7fdbcc113p-4L, 0x8.af3d12fc8626167p-4L, 0x8.af3d12fc8626168p-4L }, + { -0xc.dd197fcdeb2df37p-1016L, 0xd.d1ae353afc701eep-24L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x7.d2c387b3911c47dp-4L, -0x1.bc0ab21990f1029p-144L, -0x3.8c2481f80c0e7ca8p-144L, -0x3.8c2481f80c0e7ca4p-144L }, + { -0x6.3cb6cb3574d1d9f8p-4L, -0x6.96d3daf1b089a66p-4L, -0x2.5429717f7e7c73bcp+0L, -0x2.5429717f7e7c73b8p+0L }, + { -0x4.39d33a8bd7344ee8p-32L, -0x3.60b3af53040b6134p+132L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x9.a8b4f46185e5f1ep-4L, 0xe.2d87496db29944bp-4L, 0xf.9060956959d726ap-4L, 0xf.9060956959d726bp-4L }, + { -0xd.667041c980fb86ap-8L, 0x8.86bc2686850d445p+44L, 0x1.921fb54442d19d8ep+0L, 0x1.921fb54442d19d9p+0L }, + { -0x4.50e215fa10553d48p+8L, -0xf.b3f92be44496d7dp+120L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xd.f212d18f02b8957p-4L, 0x1.bdfe0c435f3ecb6p-72L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { 0x2.43e5d27672761aep-4L, 0x3.5eaa54a49a4ae46p-856L, 0x1.7cd46c8fb5f07dccp-852L, 0x1.7cd46c8fb5f07dcep-852L }, + { 0x3.abc16e9612cf3498p-4L, 0x7.181a2f454b0cdc38p-4L, 0x1.17e13b779b179daep+0L, 0x1.17e13b779b179dbp+0L }, + { -0x3.effb9151b19d3bc4p-4L, -0xd.6d8e757bfced33fp-4L, -0x1.db249c4f5ddbb53p+0L, -0x1.db249c4f5ddbb52ep+0L }, + { -0x4.1c7675db4a13c528p-8L, -0x5.916912756e511cc8p-44L, -0x3.243f6a886ff7966cp+0L, -0x3.243f6a886ff79668p+0L }, + { -0x9.ae36136241e082p-4L, -0xa.e229ff39b139c49p+36L, -0x1.921fb54443b538c4p+0L, -0x1.921fb54443b538c2p+0L }, + { -0x8.ea7441c1fcae2c9p-4L, -0x3.1ec5e57752e627dp-4L, -0x2.ce114af4e63febacp+0L, -0x2.ce114af4e63feba8p+0L }, + { 0xd.2ba2276ff04dde1p-4L, -0x1.036ccaf8131b87e4p-4L, -0x1.3a8a5ba2fe62b7f6p-4L, -0x1.3a8a5ba2fe62b7f4p-4L }, + { 0xe.8b06f66a6205032p-4L, -0xd.ae112e1be26b88dp-4L, -0xc.13c3c7343dcb262p-4L, -0xc.13c3c7343dcb261p-4L }, + { -0xd.95c2feeb327b501p-4L, -0xe.f8f263f130a717ap-4L, -0x2.4ec20c3ac11aba8p+0L, -0x2.4ec20c3ac11aba7cp+0L }, + { 0x3.f769c52f22e30058p-140L, 0x8.46e4f1b98e2ba04p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x1.e4581b83724c3aeep-7320L, -0x8.53fa90b742c3c73p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x4.9d47118131cc5d58p-4L, -0xa.e9fb23a5f0ee204p-4L, -0x1.2bb947cf278427fap+0L, -0x1.2bb947cf278427f8p+0L }, + { -0x7.cbd5551ff762f788p-4L, -0x8.c9f6a15fcc211ap-8L, -0x3.123d7d5448f77928p+0L, -0x3.123d7d5448f77924p+0L }, + { -0xe.83b3579c4b7fd68p-112L, -0xd.200e63e91fae96p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x6.957c45c90a7c23ap+96L, 0xd.ce8bdb00853c926p-4L, 0x2.18d83b8b49fb8b3cp-100L, 0x2.18d83b8b49fb8b4p-100L }, + { 0xf.0b8ed1b50e825c8p-8L, 0x6.ed7085987456212p-12700L, 0x7.5dfe047fcd4cf058p-12696L, 0x7.5dfe047fcd4cf06p-12696L }, + { -0x4.176212e7c4ecbaap-4L, -0x6.93d4b9e5fd90fb28p-124L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x6.5877ca61dc57f7b8p-4L, -0x4.d2f3a82b21bdc158p-80L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x7.95f214f6efdcd0fp-4L, -0x6.68bbadffe256848p-4L, -0xb.396dd5127435ff2p-4L, -0xb.396dd5127435ff1p-4L }, + { -0xf.e9e97c18e559f59p-4L, 0x9.f5b28b8c5abdfbdp-4L, 0x2.95168d1a7a401db4p+0L, 0x2.95168d1a7a401db8p+0L }, + { 0x2.055b1777b282e33cp-1508L, 0xa.ddd851824e9cc4dp-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xb.5eaa19741f96466p-4L, 0x6.947f8b39e9330e3p-4L, 0x8.64e80eb23f4e797p-4L, 0x8.64e80eb23f4e798p-4L }, + { 0x8.0caee3998490c06p-4L, 0xb.fdd5aaea1f21087p-4L, 0xf.ac80644d42f8741p-4L, 0xf.ac80644d42f8742p-4L }, + { 0x7.2dab42195d9c94bp-4L, -0x1.1432f4dd5422d976p-40L, -0x2.679f7d784fd215a8p-40L, -0x2.679f7d784fd215a4p-40L }, + { 0x1.4606e76e580b8a0cp-4L, 0x3.0f05b15d1a1c90ccp-4L, 0x1.2d1f3eca25e48488p+0L, 0x1.2d1f3eca25e4848ap+0L }, + { -0x8.5ed70349b636516p-4L, -0x7.b69c3fd741b5e678p-12912L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x4.681599c48280feb8p-24L, 0x3.c6a8b9f4986a9634p-4L, 0x1.921fc7f043a898ep+0L, 0x1.921fc7f043a898e2p+0L }, + { 0x4.04dc8898d9c85308p+9536L, -0x2.5df4adcca608ba98p-12L, -0x9.6c5ece3961e7b91p-9552L, -0x9.6c5ece3961e7b9p-9552L }, + { 0xa.83e14bca0dac3fdp-4L, -0x1.5c01106a0de1ffeap-4L, -0x2.0e9b5df42dab89bcp-4L, -0x2.0e9b5df42dab89b8p-4L }, + { 0x8.2cdf755e03ecc16p-4L, 0x6.a1b1ca60f56fa998p-4L, 0xa.e781da0ed69665ap-4L, 0xa.e781da0ed69665bp-4L }, + { -0x3.039964d84c1627d4p+116L, 0xb.e6ab265f4ede4b9p-4L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { 0x3.3fb4865ddd19c4a4p+44L, 0xc.d231d5c4e611168p-4L, 0x3.f243987c6bb87648p-48L, 0x3.f243987c6bb8764cp-48L }, + { -0x8.72d7be8c1ce0c13p-4L, 0xc.16abe5e217ed38fp-4L, 0x2.2e4782208e9be82p+0L, 0x2.2e4782208e9be824p+0L }, + { 0x1.6310b10d9de5d426p+88L, 0x5.4a1938838acdc4fp-4L, 0x3.d04c201d8bb1fa2p-92L, 0x3.d04c201d8bb1fa24p-92L }, + { 0x8.5b4b0396d43ee47p-4L, -0x9.4834e879d5b0849p-4L, -0xd.67b2a76f016882ap-4L, -0xd.67b2a76f0168829p-4L }, + { 0x7.753bb7b8c25f952p+2888L, 0x3.e7a2599013f5192p-4L, 0x8.609439e6466766ep-2896L, 0x8.609439e6466766fp-2896L }, + { -0x1.fa942bc5b553041cp+12L, -0x6.6c53ede2a18a2428p-4L, -0x3.243c2b9225dff5d8p+0L, -0x3.243c2b9225dff5d4p+0L }, + { 0xa.47ea2dd67ff54e3p-4L, -0x7.d552135c630eca7p+140L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x5.b62f47f1376eb4d8p-4L, 0xa.1da7e265035a3c4p-4L, 0x1.0e8a0d4a9838070ep+0L, 0x1.0e8a0d4a9838071p+0L }, + { 0xd.5462bb61c9e0743p-4L, -0x3.e94008a1b69179f8p+2368L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x3.c6b50185720acab4p-4L, 0xc.e8153da96b4043fp-4L, 0x1.dafd8f82584b3aep+0L, 0x1.dafd8f82584b3ae2p+0L }, + { -0x6.6e228eb9c146093p-144L, 0xa.b6c4172198a391ap-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x2.a1bcbf92db38e4f8p-4L, 0x1.578aa97b6aa2f6a4p-120L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { 0x4.03871323508d2208p-92L, 0x1.b7b42b180b7a5baep-4908L, 0x6.d8c6e23c0a17926p-4820L, 0x6.d8c6e23c0a179268p-4820L }, + { 0x1.e866d68d12e3d6e2p+64L, 0xc.ace2470bdb01192p-4L, 0x6.a4d586910831b16p-68L, 0x6.a4d586910831b168p-68L }, + { -0x2.a5ce182e00368394p+10688L, 0x1.c403d9c62d035c8p-4L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { 0x8.cac1a823d3b98bep-4L, 0x2.4dd80bb46880fd0cp+3768L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0xa.74b0b9f237195bfp-8L, -0xd.4880b498179975bp-4L, -0x1.858a2858781939d8p+0L, -0x1.858a2858781939d6p+0L }, + { -0xd.9c03b986ebe4541p-4L, 0xb.a372ba15d4c940dp-136L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { -0xa.76ccb7d81a5c5b8p-4L, -0x7.d178643f841cbc08p-4L, -0x2.7ffa8c7878fe5444p+0L, -0x2.7ffa8c7878fe544p+0L }, + { 0x8.992f6f29de9baa1p-4L, -0x2.6df885a56ac520b8p+84L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xc.c702ea51f29dd29p-4L, 0xc.52b96380b86a72ep-4L, 0x2.5fd171ce65416f68p+0L, 0x2.5fd171ce65416f6cp+0L }, + { 0x7.7da787b409a377c8p-4L, 0x4.bf0678273f028cd8p-4L, 0x9.09413df2baa84dfp-4L, 0x9.09413df2baa84ep-4L }, + { 0x7.e356b90a1e983p-4L, 0x5.657e1e60ee4799e8p-4L, 0x9.99959836d098709p-4L, 0x9.99959836d09870ap-4L }, + { -0x6.68cb8626a1a7bd2p-4L, 0x2.9433b04900ebb9p-4L, 0x2.c250ed62efbc5ed4p+0L, 0x2.c250ed62efbc5ed8p+0L }, + { -0x7.6704a5d84d429278p-12L, -0x2.53c60f0888101e64p+48L, -0x1.921fb54442d1849ep+0L, -0x1.921fb54442d1849cp+0L }, + { 0xf.a61176890fa8bdbp-4L, -0xc.17e8c4b326c4b6ep-4L, -0xa.86e92eeee828f27p-4L, -0xa.86e92eeee828f26p-4L }, + { -0x2.c555f1be423d02fcp-464L, 0x1.7c6eeead727f952ep-8L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x1.551ff116c5c06a1ap-116L, -0x2.bbf4a7d991feb2d4p-120L, -0x3.0398704f0e5afc7cp+0L, -0x3.0398704f0e5afc78p+0L }, + { 0x4.6e41b8acdd8f85dp-4L, -0x3.f4ef9b082435ce7cp-148L, -0xe.49e3b21a45821f7p-148L, -0xe.49e3b21a45821f6p-148L }, + { -0x6.40c5ab955d01a03p+5648L, -0x2.0979098b1bd5dbp+9916L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0x6.3b075dc7d59d685p-4L, -0x2.f48fe76be3d44e1p-152L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { -0x3.f74277ed265e015cp+60L, 0xc.480fd8d360f7142p-4L, 0x3.243f6a8885a308ccp+0L, 0x3.243f6a8885a308dp+0L }, + { -0x2.b74e97b30cacec2cp-4L, 0x6.47bd6d76772ae9ep-4L, 0x1.fa9e81a87803b58ep+0L, 0x1.fa9e81a87803b59p+0L }, + { -0x3.e4752a427feefdap-4L, -0x3.648ca3460f50fc28p-4L, -0x2.6cb7357e013e0c08p+0L, -0x2.6cb7357e013e0c04p+0L }, + { -0xa.338bb51e509e044p-152L, 0xb.f2d1dac2e74ad02p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x3.a03ed9b66660c09p-4L, 0xa.794c188e703dab8p-4L, 0x1.3ccdefaeb1710678p+0L, 0x1.3ccdefaeb171067ap+0L }, + { 0xb.2f3e3d838ebed4bp-4L, -0x4.eafc2cc3463c771p-6788L, -0x7.09091cfdd29e7dfp-6788L, -0x7.09091cfdd29e7de8p-6788L }, + { -0x8.684872e3380a1fdp+6060L, -0x4.bd8d34ac79591d58p+52L, -0x3.243f6a8885a308d4p+0L, -0x3.243f6a8885a308dp+0L }, + { 0x5.6fb79843c82e2c1p+5652L, -0xa.dec92754a1fe74dp-5540L, -0x1.ffe1755d00a766b8p-11192L, -0x1.ffe1755d00a766b6p-11192L }, + { 0x5.c1b1d1b6b056b648p-108L, -0x6.4e37b8f49a0b21f8p-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0x1.1c741352a9784764p+12044L, 0x1.7ffaf524a6c9d0e4p+7808L, 0x1.59924535f3025922p-4236L, 0x1.59924535f3025924p-4236L }, + { 0xa.36099fe806b84fcp+56L, 0x2.dfb4d2b6b161659cp-6848L, 0x4.80cbe1da75a10368p-6908L, 0x4.80cbe1da75a1037p-6908L }, + { -0x4.5190f0b1846ea89p-4L, 0x1.c37f5ed30d4ba53p+48L, 0x1.921fb54442d1ab96p+0L, 0x1.921fb54442d1ab98p+0L }, + { -0x4.0a6d4d991fcb0778p+8L, 0x2.90b4f02d88546e28p-4L, 0x3.2435422f3623d1fp+0L, 0x3.2435422f3623d1f4p+0L }, + { -0x6.f97d9ace617c1f1p-4L, -0x9.e638c81b7bb9dp-4L, -0x2.2f40065b511baef4p+0L, -0x2.2f40065b511baefp+0L }, + { -0x9.99f82f11bf88bbcp-4L, 0xa.7ea03cd6316368dp-4L, 0x2.4fd0aaeea4bea7acp+0L, 0x2.4fd0aaeea4bea7bp+0L }, + { 0x8.02f1895758feb2dp-8L, -0x1.b831b2fcec2b3d52p-4L, -0x1.49953e75cd87d946p+0L, -0x1.49953e75cd87d944p+0L }, + { -0x5.07e7aa225447584p-10264L, 0x4.4629c3e0a37fba8p+68L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x5.052f08bb6e5732c8p-4L, -0x5.0d5e419c51e0f3ep+116L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { -0xc.6dfcb7adf3a11cdp-4L, 0x1.121df88ac0598a6p-4L, 0x3.0e3f9f78b370d72p+0L, 0x3.0e3f9f78b370d724p+0L }, + { 0x5.d3cac7f6bdbb7e8p-13848L, 0xa.1583e5fa5a9dd55p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x5.d272fc700a86f688p-40L, 0x5.76e058e105a436p-4L, 0x1.921fb54453dda5f6p+0L, 0x1.921fb54453dda5f8p+0L }, + { 0xb.68c49383bb035d6p-4L, 0x4.ae54afae863ae4a8p-4L, 0x6.3ab8c728eac35168p-4L, 0x6.3ab8c728eac3517p-4L }, + { -0x8.81cb17de14581dbp-4L, -0x1.c2dcac66d7f29b12p+11656L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xb.0ae3fdc98ddc34fp-4L, -0xc.0b6e288dced796bp-8L, -0x1.16ccf2c7fd07e9aap-4L, -0x1.16ccf2c7fd07e9a8p-4L }, + { 0xe.c573d472a847a96p-8L, -0xb.8ff6fcd64ef65e6p-4L, -0x1.7dba02db709d9a0ap+0L, -0x1.7dba02db709d9a08p+0L }, + { 0x1.c2eb0a9ea7a016e8p-4L, 0x2.837abafcbe11a118p+20L, 0x1.921fb490de793956p+0L, 0x1.921fb490de793958p+0L }, + { -0x6.0003437ebf49b358p-4L, -0x6.8366f772a6e5ab88p-4L, -0x2.50b11488d2e618p+0L, -0x2.50b11488d2e617fcp+0L }, + { -0x5.5180b0012d133d7p-4L, 0x1.265b051593ae50bp+36L, 0x1.921fb54447719c84p+0L, 0x1.921fb54447719c86p+0L }, + { 0x7.fb6040f1f0ff7dp-4L, -0x3.7a55504e82f7f4dcp-4L, -0x6.93193e94ff08f66p-4L, -0x6.93193e94ff08f658p-4L }, + { 0x7.0db37c7302791a18p+140L, -0x9.17638d6fe5ab606p-4L, -0x1.49f61a170196d194p-144L, -0x1.49f61a170196d192p-144L }, + { -0x9.ce06d03b8cf756cp+12212L, 0x1.dedfea0526bba7dp+4572L, 0x3.243f6a8885a308dp+0L, 0x3.243f6a8885a308d4p+0L }, + { 0xb.7859f7b209e2fadp-4L, 0x4.7d451cc9eba3b3c8p+12080L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x3.800a4ceb87c4c0dcp-4L, -0xc.6125c4bdc9fce09p-4L, -0x1.4b95805a73babb12p+0L, -0x1.4b95805a73babb1p+0L }, + { 0xe.2f27e0dfe63260cp-4L, -0x5.15611dfbb941776p-4L, -0x5.81906be9aff7f478p-4L, -0x5.81906be9aff7f47p-4L }, + { -0xe.839068311283f8ap-4L, -0x3.ec9f15b5ee5373d4p-4L, -0x2.e0a57836248d1de8p+0L, -0x2.e0a57836248d1de4p+0L }, + { 0xf.e2ae6bf1e1a61e1p-4L, 0xf.c01b51aefe3a1aap+80L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x7.b53f66013e565ap-4L, 0x1.fca730dbcec65adcp-4L, 0x2.e3a9d5c63f015c2cp+0L, 0x2.e3a9d5c63f015c3p+0L }, + { 0xd.0cf58dc63ab7324p-4L, 0x7.449c0b585a5d2f78p-4L, 0x8.214f01a14103e4p-4L, 0x8.214f01a14103e41p-4L }, + { -0x5.6bd9880a9f4986p+44L, -0x6.2ffa8922e379925p-4L, -0x3.243f6a8885a1e4a8p+0L, -0x3.243f6a8885a1e4a4p+0L }, + { 0xf.704f945653892dbp-4L, -0xb.c78f60e05acc8c6p-92L, -0xc.353165a139735efp-92L, -0xc.353165a139735eep-92L }, + { 0x9.ebfb00a0b8c2da1p-4L, -0xb.af52c658515088ep-4L, -0xd.de7a23a873b3f3ep-4L, -0xd.de7a23a873b3f3dp-4L }, + { 0x3.875f9c7fb9864ae8p+468L, -0x9.4f89ff3200affa3p-4L, -0x2.a373dfc24c5488ap-472L, -0x2.a373dfc24c54889cp-472L }, + { -0xe.d00c66c632b4331p-4L, 0x7.ec775329456f0008p-8L, 0x3.1bb12c979946dfacp+0L, 0x3.1bb12c979946dfbp+0L }, + { -0x5.5f443fc060a5186p+4L, -0x5.20a0673897bdb3p+11012L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xa.a4bce42874e01e7p-4L, -0x4.713dabcd0bf8e268p-4L, -0x6.538a5466fb3e0bp-4L, -0x6.538a5466fb3e0af8p-4L }, + { 0xd.86b3fb9862792d8p-4L, 0xb.ae5e2dfcd038356p-4L, 0xb.65b757a77df534p-4L, 0xb.65b757a77df5341p-4L }, + { -0x9.adfe099d19d2efdp-4L, 0xa.88bf6665e9494dbp-4L, 0x2.505ec334ccbb79e4p+0L, 0x2.505ec334ccbb79e8p+0L }, + { 0x2.b3ae7a75c3b22b8p-6084L, 0x9.c5c6d7173a39debp+24L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0xe.7eb5c52358f835ep-3196L, 0x8.797ad35fc309114p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { -0x9.f8c8346e4053057p-4L, 0xf.c3edebe9bb0b3eep-8L, 0x3.0b089fc3ca8e624cp+0L, 0x3.0b089fc3ca8e625p+0L }, + { 0x8.c94c984dbf4168dp-140L, 0x8.af5e9852b765959p-4L, 0x1.921fb54442d18468p+0L, 0x1.921fb54442d1846ap+0L }, + { 0x2.c2b5d9731288dc28p+11664L, 0x5.04099a913d2b78bp+84L, 0x1.d121cb458be8286ap-11580L, 0x1.d121cb458be8286cp-11580L }, + { -0x2.ace07ddf3cfef394p-4L, -0x9.34833a09fae8757p-4L, -0x1.da87e7197755b95p+0L, -0x1.da87e7197755b94ep+0L }, + { -0x9.9730cd1292b85ap-4L, 0x4.c0eb35da7752fae8p-4L, 0x2.ae7231301fba2fc8p+0L, 0x2.ae7231301fba2fccp+0L }, + { 0xd.15f9ed0a25038d3p-4L, -0xb.026f5b20c30b683p-9908L, -0xd.761645d4aa3d8eap-9908L, -0xd.761645d4aa3d8e9p-9908L }, + { 0xd.be8ae1a17d85c18p-4L, 0x7.78d4cf72d7cf81d8p-4L, 0x7.f799f5d2cfdc8abp-4L, 0x7.f799f5d2cfdc8ab8p-4L }, + { 0x7.d23da006d9cb052p+100L, -0x7.a3b09d22470dbdbp+8L, -0xf.a0c5461aa543069p-96L, -0xf.a0c5461aa543068p-96L }, + { -0x7.5c713c672b96766p-4L, 0x2.52eaea727fb51b3cp-20L, 0x3.243f19b6d5b1f9b4p+0L, 0x3.243f19b6d5b1f9b8p+0L }, + { -0x3.2d22702027067fbp-11224L, -0x8.f3611793d8dfabdp-4L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xc.0e2efd7cc5044b8p-4L, 0x9.4b4c59fac13b018p-4L, 0xa.822768942e46d48p-4L, 0xa.822768942e46d49p-4L }, + { -0xb.0f085497de93bf5p-4L, 0x9.8ba535bfbb53d43p-4L, 0x2.6df415a19533453p+0L, 0x2.6df415a195334534p+0L }, + { -0x9.da37fa21c584069p-4L, 0xa.c84cf6492b6f825p-4L, 0x2.4fa7dddb330669c4p+0L, 0x2.4fa7dddb330669c8p+0L }, + { -0x9.3bcbc7bc0fb3ed9p+88L, -0x2.79e9ad222e894dc4p+6552L, -0x1.921fb54442d1846ap+0L, -0x1.921fb54442d18468p+0L }, + { 0xa.e73a40fb29d0efep-4L, -0x2.79cf7e59fb5c72d4p-7232L, -0x3.a21696480c751084p-7232L, -0x3.a21696480c75108p-7232L }, + { 0x4.8e020087477fcaep-4L, -0xb.588ec7584c64f6dp-8L, -0x2.789fd1176ef175bp-4L, -0x2.789fd1176ef175acp-4L }, +}; + +int check_equal(long double res, long double expected) +{ + if (res != expected) { + return 0; + } + return (__builtin_copysignl(1.0L, res) == + __builtin_copysignl(1.0L, expected)); +} + +int main(void) +{ + int ret = 0; + int i; + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + long double ld_res; + __asm__ volatile ("fpatan" : "=t" (ld_res) : + "0" (tests[i].arg0), "u" (tests[i].arg1) : "st(1)"); + if (!check_equal(ld_res, tests[i].down) && + !check_equal(ld_res, tests[i].up)) { + printf("FAIL: fpatan %La %La, expected %La or %La, got %La\n", + tests[i].arg0, tests[i].arg1, tests[i].down, tests[i].up, + ld_res); + ret = 1; + } + } + return ret; +} diff --git a/tests/tcg/i386/test-i386-fscale.c b/tests/tcg/i386/test-i386-fscale.c new file mode 100644 index 0000000000000000000000000000000000000000..d23b3cfeec89e448471e75f67f7349e66b1d6358 --- /dev/null +++ b/tests/tcg/i386/test-i386-fscale.c @@ -0,0 +1,108 @@ +/* Test fscale instruction. */ + +#include +#include + +union u { + struct { uint64_t sig; uint16_t sign_exp; } s; + long double ld; +}; + +volatile long double ld_third = 1.0L / 3.0L; +volatile long double ld_four_thirds = 4.0L / 3.0L; +volatile union u ld_invalid_1 = { .s = { 1, 1234 } }; +volatile union u ld_invalid_2 = { .s = { 0, 1234 } }; +volatile union u ld_invalid_3 = { .s = { 0, 0x7fff } }; +volatile union u ld_invalid_4 = { .s = { (UINT64_C(1) << 63) - 1, 0x7fff } }; + +volatile long double ld_res; + +int isnan_ld(long double x) +{ + union u tmp = { .ld = x }; + return ((tmp.s.sign_exp & 0x7fff) == 0x7fff && + (tmp.s.sig >> 63) != 0 && + (tmp.s.sig << 1) != 0); +} + +int issignaling_ld(long double x) +{ + union u tmp = { .ld = x }; + return isnan_ld(x) && (tmp.s.sig & UINT64_C(0x4000000000000000)) == 0; +} + +int main(void) +{ + short cw; + int ret = 0; + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (2.5L), "u" (__builtin_nansl(""))); + if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { + printf("FAIL: fscale snan\n"); + ret = 1; + } + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (2.5L), "u" (ld_invalid_1.ld)); + if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { + printf("FAIL: fscale invalid 1\n"); + ret = 1; + } + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (2.5L), "u" (ld_invalid_2.ld)); + if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { + printf("FAIL: fscale invalid 2\n"); + ret = 1; + } + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (2.5L), "u" (ld_invalid_3.ld)); + if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { + printf("FAIL: fscale invalid 3\n"); + ret = 1; + } + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (2.5L), "u" (ld_invalid_4.ld)); + if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { + printf("FAIL: fscale invalid 4\n"); + ret = 1; + } + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (0.0L), "u" (__builtin_infl())); + if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { + printf("FAIL: fscale 0 up inf\n"); + ret = 1; + } + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (__builtin_infl()), "u" (-__builtin_infl())); + if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { + printf("FAIL: fscale inf down inf\n"); + ret = 1; + } + /* Set round-downward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x400; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (1.0L), "u" (__builtin_infl())); + if (ld_res != __builtin_infl()) { + printf("FAIL: fscale finite up inf\n"); + ret = 1; + } + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (-1.0L), "u" (-__builtin_infl())); + if (ld_res != -0.0L || __builtin_copysignl(1.0L, ld_res) != -1.0L) { + printf("FAIL: fscale finite down inf\n"); + ret = 1; + } + /* Set round-to-nearest with single-precision rounding. */ + cw = cw & ~0xf00; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (ld_third), "u" (2.0L)); + cw = cw | 0x300; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + if (ld_res != ld_four_thirds) { + printf("FAIL: fscale single-precision\n"); + ret = 1; + } + return ret; +} diff --git a/tests/tcg/i386/test-i386-fxam.c b/tests/tcg/i386/test-i386-fxam.c new file mode 100644 index 0000000000000000000000000000000000000000..ddd76ca42d202dbbd34d4c2478e1f6e7ba628f10 --- /dev/null +++ b/tests/tcg/i386/test-i386-fxam.c @@ -0,0 +1,143 @@ +/* Test fxam instruction. */ + +#include +#include + +union u { + struct { uint64_t sig; uint16_t sign_exp; } s; + long double ld; +}; + +volatile union u ld_pseudo_m16382 = { .s = { UINT64_C(1) << 63, 0 } }; +volatile union u ld_pseudo_nm16382 = { .s = { UINT64_C(1) << 63, 0x8000 } }; +volatile union u ld_invalid_1 = { .s = { 1, 1234 } }; +volatile union u ld_invalid_2 = { .s = { 0, 1234 } }; +volatile union u ld_invalid_3 = { .s = { 0, 0x7fff } }; +volatile union u ld_invalid_4 = { .s = { (UINT64_C(1) << 63) - 1, 0x7fff } }; +volatile union u ld_invalid_n1 = { .s = { 1, 0x8123 } }; +volatile union u ld_invalid_n2 = { .s = { 0, 0x8123 } }; +volatile union u ld_invalid_n3 = { .s = { 0, 0xffff } }; +volatile union u ld_invalid_n4 = { .s = { (UINT64_C(1) << 63) - 1, 0xffff } }; + +#define C0 (1 << 8) +#define C1 (1 << 9) +#define C2 (1 << 10) +#define C3 (1 << 14) +#define FLAGS (C0 | C1 | C2 | C3) + +int main(void) +{ + short sw; + int ret = 0; + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (0.0L)); + if ((sw & FLAGS) != C3) { + printf("FAIL: +0\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-0.0L)); + if ((sw & FLAGS) != (C3 | C1)) { + printf("FAIL: -0\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (1.0L)); + if ((sw & FLAGS) != C2) { + printf("FAIL: +normal\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-1.0L)); + if ((sw & FLAGS) != (C2 | C1)) { + printf("FAIL: -normal\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (__builtin_infl())); + if ((sw & FLAGS) != (C2 | C0)) { + printf("FAIL: +inf\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-__builtin_infl())); + if ((sw & FLAGS) != (C2 | C1 | C0)) { + printf("FAIL: -inf\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (__builtin_nanl(""))); + if ((sw & FLAGS) != C0) { + printf("FAIL: +nan\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-__builtin_nanl(""))); + if ((sw & FLAGS) != (C1 | C0)) { + printf("FAIL: -nan\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (__builtin_nansl(""))); + if ((sw & FLAGS) != C0) { + printf("FAIL: +snan\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-__builtin_nansl(""))); + if ((sw & FLAGS) != (C1 | C0)) { + printf("FAIL: -snan\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (0x1p-16445L)); + if ((sw & FLAGS) != (C3 | C2)) { + printf("FAIL: +denormal\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-0x1p-16445L)); + if ((sw & FLAGS) != (C3 | C2 | C1)) { + printf("FAIL: -denormal\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_pseudo_m16382.ld)); + if ((sw & FLAGS) != (C3 | C2)) { + printf("FAIL: +pseudo-denormal\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_pseudo_nm16382.ld)); + if ((sw & FLAGS) != (C3 | C2 | C1)) { + printf("FAIL: -pseudo-denormal\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_1.ld)); + if ((sw & FLAGS) != 0) { + printf("FAIL: +invalid 1\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_n1.ld)); + if ((sw & FLAGS) != C1) { + printf("FAIL: -invalid 1\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_2.ld)); + if ((sw & FLAGS) != 0) { + printf("FAIL: +invalid 2\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_n2.ld)); + if ((sw & FLAGS) != C1) { + printf("FAIL: -invalid 2\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_3.ld)); + if ((sw & FLAGS) != 0) { + printf("FAIL: +invalid 3\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_n3.ld)); + if ((sw & FLAGS) != C1) { + printf("FAIL: -invalid 3\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_4.ld)); + if ((sw & FLAGS) != 0) { + printf("FAIL: +invalid 4\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_n4.ld)); + if ((sw & FLAGS) != C1) { + printf("FAIL: -invalid 4\n"); + ret = 1; + } + return ret; +} diff --git a/tests/tcg/i386/test-i386-fxtract.c b/tests/tcg/i386/test-i386-fxtract.c new file mode 100644 index 0000000000000000000000000000000000000000..64fd93d333705498a51666d61edf4ea63a0a567e --- /dev/null +++ b/tests/tcg/i386/test-i386-fxtract.c @@ -0,0 +1,120 @@ +/* Test fxtract instruction. */ + +#include +#include + +union u { + struct { uint64_t sig; uint16_t sign_exp; } s; + long double ld; +}; + +volatile union u ld_pseudo_m16382 = { .s = { UINT64_C(1) << 63, 0 } }; +volatile union u ld_invalid_1 = { .s = { 1, 1234 } }; +volatile union u ld_invalid_2 = { .s = { 0, 1234 } }; +volatile union u ld_invalid_3 = { .s = { 0, 0x7fff } }; +volatile union u ld_invalid_4 = { .s = { (UINT64_C(1) << 63) - 1, 0x7fff } }; + +volatile long double ld_sig, ld_exp; + +int isnan_ld(long double x) +{ + union u tmp = { .ld = x }; + return ((tmp.s.sign_exp & 0x7fff) == 0x7fff && + (tmp.s.sig >> 63) != 0 && + (tmp.s.sig << 1) != 0); +} + +int issignaling_ld(long double x) +{ + union u tmp = { .ld = x }; + return isnan_ld(x) && (tmp.s.sig & UINT64_C(0x4000000000000000)) == 0; +} + +int main(void) +{ + int ret = 0; + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : "0" (2.5L)); + if (ld_sig != 1.25L || ld_exp != 1.0L) { + printf("FAIL: fxtract 2.5\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : "0" (0.0L)); + if (ld_sig != 0.0L || __builtin_copysignl(1.0L, ld_sig) != 1.0L || + ld_exp != -__builtin_infl()) { + printf("FAIL: fxtract 0.0\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : "0" (-0.0L)); + if (ld_sig != -0.0L || __builtin_copysignl(1.0L, ld_sig) != -1.0L || + ld_exp != -__builtin_infl()) { + printf("FAIL: fxtract -0.0\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (__builtin_infl())); + if (ld_sig != __builtin_infl() || ld_exp != __builtin_infl()) { + printf("FAIL: fxtract inf\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (-__builtin_infl())); + if (ld_sig != -__builtin_infl() || ld_exp != __builtin_infl()) { + printf("FAIL: fxtract -inf\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (__builtin_nanl(""))); + if (!isnan_ld(ld_sig) || issignaling_ld(ld_sig) || + !isnan_ld(ld_exp) || issignaling_ld(ld_exp)) { + printf("FAIL: fxtract qnan\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (__builtin_nansl(""))); + if (!isnan_ld(ld_sig) || issignaling_ld(ld_sig) || + !isnan_ld(ld_exp) || issignaling_ld(ld_exp)) { + printf("FAIL: fxtract snan\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (0x1p-16445L)); + if (ld_sig != 1.0L || ld_exp != -16445.0L) { + printf("FAIL: fxtract subnormal\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (ld_pseudo_m16382.ld)); + if (ld_sig != 1.0L || ld_exp != -16382.0L) { + printf("FAIL: fxtract pseudo\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (ld_invalid_1.ld)); + if (!isnan_ld(ld_sig) || issignaling_ld(ld_sig) || + !isnan_ld(ld_exp) || issignaling_ld(ld_exp)) { + printf("FAIL: fxtract invalid 1\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (ld_invalid_2.ld)); + if (!isnan_ld(ld_sig) || issignaling_ld(ld_sig) || + !isnan_ld(ld_exp) || issignaling_ld(ld_exp)) { + printf("FAIL: fxtract invalid 2\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (ld_invalid_3.ld)); + if (!isnan_ld(ld_sig) || issignaling_ld(ld_sig) || + !isnan_ld(ld_exp) || issignaling_ld(ld_exp)) { + printf("FAIL: fxtract invalid 3\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (ld_invalid_4.ld)); + if (!isnan_ld(ld_sig) || issignaling_ld(ld_sig) || + !isnan_ld(ld_exp) || issignaling_ld(ld_exp)) { + printf("FAIL: fxtract invalid 4\n"); + ret = 1; + } + return ret; +} diff --git a/tests/tcg/i386/test-i386-fyl2x.c b/tests/tcg/i386/test-i386-fyl2x.c new file mode 100644 index 0000000000000000000000000000000000000000..71d7a8fc9905c236337eb8155a3e855d9faf301e --- /dev/null +++ b/tests/tcg/i386/test-i386-fyl2x.c @@ -0,0 +1,1161 @@ +/* Test fyl2x instruction. */ + +#include + +struct test { + long double arg0, arg1, down, up; +}; + +const struct test tests[] = { + { 1.0L, 12345.0L, 0.0L, 0.0L }, + { 1.0L, -12345.0L, -0.0L, -0.0L }, + { 1.0L, 0.0L, 0.0L, 0.0L }, + { 1.0L, -0.0L, -0.0L, -0.0L }, + { 0.1L, 0.0L, -0.0L, -0.0L }, + { 0.1L, -0.0L, 0.0L, 0.0L }, + { 1.1L, 0.0L, 0.0L, 0.0L }, + { 1.1L, -0.0L, -0.0L, -0.0L }, + { 0.0L, __builtin_infl(), -__builtin_infl(), -__builtin_infl() }, + { 0.0L, -__builtin_infl(), __builtin_infl(), __builtin_infl() }, + { -0.0L, __builtin_infl(), -__builtin_infl(), -__builtin_infl() }, + { -0.0L, -__builtin_infl(), __builtin_infl(), __builtin_infl() }, + { 0.0L, 12345.0L, -__builtin_infl(), -__builtin_infl() }, + { 0.0L, -12345.0L, __builtin_infl(), __builtin_infl() }, + { -0.0L, 12345.0L, -__builtin_infl(), -__builtin_infl() }, + { -0.0L, -12345.0L, __builtin_infl(), __builtin_infl() }, + { 0.1L, __builtin_infl(), -__builtin_infl(), -__builtin_infl() }, + { 0.1L, -__builtin_infl(), __builtin_infl(), __builtin_infl() }, + { 1.1L, __builtin_infl(), __builtin_infl(), __builtin_infl() }, + { 1.1L, -__builtin_infl(), -__builtin_infl(), -__builtin_infl() }, + { 4.0L, 1.5L, 3.0L, 3.0L }, + { 0x1p-16400L, 1.5L, -24600.0L, -24600.0L }, + /* Randomly generated tests. */ + { 0x2.0a40b4bd6349d53p+14380L, -0x3.612a1cec52e70388p-14116L, -0xb.dd9637a24570d1ap-14104L, -0xb.dd9637a24570d19p-14104L }, + { 0xa.a3dc18b1eff7e8ap-4L, 0x7.423575b7ac0ba6a8p-7212L, -0x4.45ac6ae2f9cc1a7p-7212L, -0x4.45ac6ae2f9cc1a68p-7212L }, + { 0x1.51167cab1deec25ep-9616L, 0xb.79bece734a62216p-14512L, -0x1.af0880f05109d5c8p-14496L, -0x1.af0880f05109d5c6p-14496L }, + { 0x1.55691f3dee65eb88p+6420L, -0x2.e081398cd6691b98p-2640L, -0x4.8275aa22ebb6ebe8p-2628L, -0x4.8275aa22ebb6ebep-2628L }, + { 0x3.71cca195c06ba4d4p-6312L, -0xb.14b747fa4cc13d1p+5052L, 0x1.112301748a1cc83p+5068L, 0x1.112301748a1cc832p+5068L }, + { 0x2.0f924dde0806572p+8924L, -0x7.ece8699d62a9f76p-14464L, -0x1.144eba5c079d0fa2p-14448L, -0x1.144eba5c079d0fap-14448L }, + { 0x4.b875c0342c9f86b8p-5832L, 0xe.a37e0fa859e499cp+732L, -0x1.4d5bc95e2af0bb08p+748L, -0x1.4d5bc95e2af0bb06p+748L }, + { 0x7.23210d9474f0715p+364L, -0x5.baaf3a431730f158p-2436L, -0x8.35afbc04cd37fafp-2428L, -0x8.35afbc04cd37faep-2428L }, + { 0xd.2330923899aae43p+776L, 0x2.a68cc6ddbe3b3a5p+6528L, 0x8.12b3f5a7b346e37p+6536L, 0x8.12b3f5a7b346e38p+6536L }, + { 0x2.c18975d92e49e91p+10120L, 0x5.6a0ac0f801b69198p+9064L, 0xd.60fe44e0b41da9dp+9076L, 0xd.60fe44e0b41da9ep+9076L }, + { 0x9.0950fb020f8be81p-11076L, -0x4.69649643801fe8p+14796L, 0xb.ed1e14ac1ee3159p+14808L, 0xb.ed1e14ac1ee315ap+14808L }, + { 0x9.cbe5ac9e09f4815p+8052L, -0x1.068c69d5c31cc18ap+8068L, -0x2.04558d1bf9a219b4p+8080L, -0x2.04558d1bf9a219bp+8080L }, + { 0x2.8158a2ep-16416L, 0x1.2f720ae47b67fca8p+13452L, -0x4.c00deece9e0fbdd8p+13464L, -0x4.c00deece9e0fbddp+13464L }, + { 0x3.0acd5bcfe0779bd4p+13040L, -0xe.d3cd27fc1c72a99p+11224L, -0x2.f35c6ed58511949p+11240L, -0x2.f35c6ed58511948cp+11240L }, + { 0xb.58a8c4316eacf31p-584L, 0x1.501f01a1258b3a5ep-10084L, -0x2.fa2ce9d2db22ad5cp-10076L, -0x2.fa2ce9d2db22ad58p-10076L }, + { 0x8.97f4540aa7735bap+13532L, -0x3.b7afc1088aafbb28p-9804L, -0xc.48d1793ca776382p-9792L, -0xc.48d1793ca776381p-9792L }, + { 0x5.1f9f41429952299p-6688L, -0x1.385afe2753285ceap-632L, 0x1.fdd68ec1544cca1ap-620L, 0x1.fdd68ec1544cca1cp-620L }, + { 0x2.95674162a7a77d6cp-11476L, -0x6.9ad188a393c513bp-8912L, 0x1.280b2d9ef35a1b0ep-8896L, 0x1.280b2d9ef35a1b1p-8896L }, + { 0x1.11caeb05f30a55a2p-5048L, 0xa.6b25eb8a8fc7c1fp+6868L, -0xc.d6fd12efe012db1p+6880L, -0xc.d6fd12efe012dbp+6880L }, + { 0x3.c980e98228764804p-5832L, 0x9.5de74e6eb71dccfp+1992L, -0xd.5513ed4865b07fep+2004L, -0xd.5513ed4865b07fdp+2004L }, + { 0xd.16b2f891d20d0f8p+7300L, -0x1.ab0872107c4d7a06p+5924L, -0x2.f974d3a68daf1cacp+5936L, -0x2.f974d3a68daf1ca8p+5936L }, + { 0x6.c6090865d981a428p-8676L, -0xd.23a3619aedffe31p+5328L, 0x1.bd2789bab1d1088cp+5344L, 0x1.bd2789bab1d1088ep+5344L }, + { 0x2.0d4fa66a2d01369cp-4156L, -0x5.a0e8f41f82c193bp+6724L, 0x5.b5a6f9779b0a4488p+6736L, 0x5.b5a6f9779b0a449p+6736L }, + { 0x1.ba2a72afa5a1fc38p+0L, 0xe.027c0b9bc2929f3p+11120L, 0xb.0bbdb58c72375d9p+11120L, 0xb.0bbdb58c72375dap+11120L }, + { 0xf.cc716330a37576ep-5424L, -0xd.a67cd50b638d845p-4460L, 0x1.21011acae853070ap-4444L, 0x1.21011acae853070cp-4444L }, + { 0x2.7699390ee7b13a7cp+8364L, -0x1.d8cb9730c96f499p+432L, -0x3.c598297e793d4e98p+444L, -0x3.c598297e793d4e94p+444L }, + { 0x4.6b0173e789f64bd8p-960L, -0x2.140353c78ded1788p+8748L, 0x7.c6982a68b41c327p+8756L, 0x7.c6982a68b41c3278p+8756L }, + { 0xc.08b122dd36a9965p+11804L, -0xa.c8e6364d67421f2p+12272L, -0x1.f16e0be947126474p+12288L, -0x1.f16e0be947126472p+12288L }, + { 0x9.cafbcd348517675p+784L, 0x4.148eb9b190272998p-1420L, 0xc.8c638141b3c6b91p-1412L, 0xc.8c638141b3c6b92p-1412L }, + { 0x4.6a571cdc489d4a9p-12352L, -0x8.a8aa4198b0c3207p+7748L, 0x1.a1b789910f110f64p+7764L, 0x1.a1b789910f110f66p+7764L }, + { 0x7.e9b228c12458559p+4928L, -0xb.2c5bdfaf2ba8f24p+56L, -0xd.73740755eb037a7p+68L, -0xd.73740755eb037a6p+68L }, + { 0xd.d2e346da3ecdb39p-1636L, -0x5.8d0ce8c4cdc72a28p+12736L, 0x2.3645e062564a6de4p+12748L, 0x2.3645e062564a6de8p+12748L }, + { 0x9.b624ea7f57aab0ap-8780L, -0x2.5e13b5ceb995397p-6416L, 0x5.12ac8402317cf408p-6404L, 0x5.12ac8402317cf41p-6404L }, + { 0x7.6d8427638b963b58p+12536L, 0x4.021f2d6df523df5p-14208L, 0xc.4537f396f309b57p-14196L, 0xc.4537f396f309b58p-14196L }, + { 0x1.8273f77fc7b36adp+0L, 0x2.f4e4c4891a53eaap-4624L, 0x1.c1b52b72090b9f64p-4624L, 0x1.c1b52b72090b9f66p-4624L }, + { 0x1.c92a5ddc0ccb3c36p+11600L, 0x1.090c0001295c6822p-4904L, 0x2.eeacd7b5643f39ecp-4892L, 0x2.eeacd7b5643f39fp-4892L }, + { 0xd.32c71819b8fe7abp-1688L, -0x6.3d33ce38ee554b58p-14512L, 0x2.90c54596d3bf22ecp-14500L, 0x2.90c54596d3bf22fp-14500L }, + { 0x1.0776fe51e1d0727cp+5752L, 0x1.4264622f1e6c6f9ep+12300L, 0x1.c4bccdc673bd74bap+12312L, 0x1.c4bccdc673bd74bcp+12312L }, + { 0x1.81f41db779901632p-10716L, -0x8.66aed834cdb9d9fp+4436L, 0x1.5fa54511d99a6f4ap+4452L, 0x1.5fa54511d99a6f4cp+4452L }, + { 0xc.9b4feccafbb8f3ep-5320L, -0xe.ccfc061ce46d6dfp+13440L, 0x1.335db86628278a4cp+13456L, 0x1.335db86628278a4ep+13456L }, + { 0x6.4ffb2045e1ad1378p-6564L, 0xf.7dfd3273f5ec1a3p+9724L, -0x1.8d1141c2de30f8eap+9740L, -0x1.8d1141c2de30f8e8p+9740L }, + { 0x2.ad90d677772e099cp+13112L, -0x2.830a812d5307cc94p-6908L, -0x8.0ab53e41596b795p-6896L, -0x8.0ab53e41596b794p-6896L }, + { 0x1.7bf51909429d7df2p-520L, -0x3.3d489a77c9f992fcp+5672L, 0x6.92a309adfd41fffp+5680L, 0x6.92a309adfd41fff8p+5680L }, + { 0x1.330765dbd272224cp+13924L, 0x2.b0444ac2e0ef926p+9564L, 0x9.23bf6ee60967adp+9576L, 0x9.23bf6ee60967ad1p+9576L }, + { 0xb.067254ab6c13349p-5508L, 0xa.7a515bb500d476fp+7348L, -0xe.14b76544da68e7fp+7360L, -0xe.14b76544da68e7ep+7360L }, + { 0x1.4f1b85b1df9ca2b4p+0L, -0x2.8e9812b9a5395564p+10304L, -0xf.e4bfca8c781c9d5p+10300L, -0xf.e4bfca8c781c9d4p+10300L }, + { 0x2.d4c7f38019aa6c2p+11216L, 0xb.6a68ac4a863ccap-6380L, 0x1.f4372db1fc362048p-6364L, 0x1.f4372db1fc36204ap-6364L }, + { 0x4.d6f79ebf8f5962ap-12132L, -0x7.2fde53882a542cp-9272L, 0x1.54882a9fcea32926p-9256L, 0x1.54882a9fcea32928p-9256L }, + { 0x5.f224f48169e0aea8p+4500L, -0x2.3e6bba4532dcfb74p-4984L, -0x2.77702ff129d7eb24p-4972L, -0x2.77702ff129d7eb2p-4972L }, + { 0xf.ce42d087ed87c6dp-1636L, -0x3.b45d9ada75fad714p+4704L, 0x1.79de5728a407b37ap+4716L, 0x1.79de5728a407b37cp+4716L }, + { 0x8.c2ce2631a625123p-8668L, 0x1.bdf6302fd5c0c678p+13148L, -0x3.af6876f1ee35ebf4p+13160L, -0x3.af6876f1ee35ebfp+13160L }, + { 0x2.9fb1b2e872ad16fcp+5720L, 0xa.405432519e52763p-12388L, 0xe.51b9d7128949a09p-12376L, 0xe.51b9d7128949a0ap-12376L }, + { 0x2.0c52d8494ae2a78p-12156L, 0x2.c778146cdaf5952p+8448L, -0x8.3f4ca0808d4657fp+8460L, -0x8.3f4ca0808d4657ep+8460L }, + { 0x7.7bfdf3916d8cf8dp+8552L, -0x2.fcc721321202f8fcp+7376L, -0x6.3d508fed61bad698p+7388L, -0x6.3d508fed61bad69p+7388L }, + { 0x9.09cea2796b8226bp+12760L, -0xe.d759972da423644p-6776L, -0x2.e3ecfc770c2adf48p-6760L, -0x2.e3ecfc770c2adf44p-6760L }, + { 0x3.f7d3ba7d4699285cp-2652L, 0x1.806cf84083df3ff4p+192L, -0xf.8b6c7389e003b59p+200L, -0xf.8b6c7389e003b58p+200L }, + { 0xd.df138c6b3e2cda7p-4L, -0x3.056a73ca2e92d3f8p+2760L, 0x9.f4ace14ab975a41p+2756L, 0x9.f4ace14ab975a42p+2756L }, + { 0x3.43ad78da6c4fbdbp-88L, -0x7.e7d5025d81fd262p+11984L, 0x2.aa32f09cb4608f7p+11992L, 0x2.aa32f09cb4608f74p+11992L }, + { 0x1.9b44f75fe57ddc8p-1260L, 0x4.38ec201a4e140da8p+1488L, -0x1.4c546e4cce840414p+1500L, -0x1.4c546e4cce840412p+1500L }, + { 0x1.42d057efa3eb1b9p-6636L, -0x6.64151de2cb7dab68p+14856L, 0xa.5a83005207a7a31p+14868L, 0xa.5a83005207a7a32p+14868L }, + { 0x3.5e66ae0c3ef31cc8p-13572L, -0x1.fa8c3fd05e77645ep-2452L, 0x6.8e37bd270fc92fb8p-2440L, 0x6.8e37bd270fc92fcp-2440L }, + { 0x6.001cd5c28a310bd8p+4224L, 0x4.c1b839282f6ff928p-11728L, 0x4.e88ab9284208a73p-11716L, 0x4.e88ab9284208a738p-11716L }, + { 0x2.2523780824d5de6cp+6472L, 0x1.b994f4a4f7e37afcp-8880L, 0x2.b9da3fa65283fa3p-8868L, 0x2.b9da3fa65283fa34p-8868L }, + { 0x5.6eec466c7bffa06p-608L, -0x1.97289654800c49b6p-8972L, 0x3.c31e2f1c37735488p-8964L, 0x3.c31e2f1c3773548cp-8964L }, + { 0x1.ca72ccc65efa7b72p-6772L, 0x5.f8e4e1978952a4ap-11212L, -0x9.df7016942b5d202p-11200L, -0x9.df7016942b5d201p-11200L }, + { 0xf.c6d22b8e29913f1p+9424L, -0xe.a6d7654fc1271b1p+1136L, -0x2.1b98288c7d75e8e8p+1152L, -0x2.1b98288c7d75e8e4p+1152L }, + { 0x1.61e8e00c140fee84p-9076L, -0x8.36dc1307ce2fc6p+14524L, 0x1.23351bc9d473a88p+14540L, 0x1.23351bc9d473a882p+14540L }, + { 0xf.866338e1e8a3a1dp-8L, -0x2.0442ce4344704d5cp-560L, 0x8.277e13b5af2161dp-560L, 0x8.277e13b5af2161ep-560L }, + { 0xe.3299360868a37fcp-10400L, 0x3.e615f9a223227808p-10468L, -0x9.e54507c6991311ep-10456L, -0x9.e54507c6991311dp-10456L }, + { 0x9.b3ff5c8d9b3d3acp+1836L, 0xa.828b7a9eaf39effp-2100L, 0x4.b82b5232056d9bbp-2088L, 0x4.b82b5232056d9bb8p-2088L }, + { 0xe.ffd31418495b633p+10124L, -0xc.5c871eba0b4806fp+5684L, -0x1.e90b7ad4822936e8p+5700L, -0x1.e90b7ad4822936e6p+5700L }, + { 0x1.7b8e3d8dda2e2b02p-7084L, 0xf.bbe5d63f9e346a3p-5088L, -0x1.b35a8b7f594154ecp-5072L, -0x1.b35a8b7f594154eap-5072L }, + { 0xe.8837c0b02c82f75p+8320L, 0x3.05caa0d06bb20888p-7260L, 0x6.247e5285220e72ap-7248L, 0x6.247e5285220e72a8p-7248L }, + { 0x7.bad48611f3e40dap-12820L, -0x1.643e2a67aaa8efa2p+13488L, 0x4.5abde1190f1b7cp+13500L, 0x4.5abde1190f1b7c08p+13500L }, + { 0xd.0e541be4b24c664p-5232L, 0x3.065797f0fcc28dbp-8280L, -0x3.dc667fc93532e9c4p-8268L, -0x3.dc667fc93532e9cp-8268L }, + { 0x2.c5b8595f3f1fb5acp+10588L, 0x5.914bbd1c2a1f9d8p-7504L, 0xe.64d8944801b7e74p-7492L, 0xe.64d8944801b7e75p-7492L }, + { 0x3.e915b16b3ea952b8p-12048L, -0x3.5dde4fb68f625424p+4784L, 0x9.e6b0eef12e35a51p+4796L, 0x9.e6b0eef12e35a52p+4796L }, + { 0x8.063bbdb884d4c9fp+13076L, -0xc.690888a046c216cp+13536L, -0x2.7a0a30ea19f24dcp+13552L, -0x2.7a0a30ea19f24dbcp+13552L }, + { 0x3.33cbc218p-16416L, 0x2.577f86039916008p-5496L, -0x9.626e2d063f7c1e6p-5484L, -0x9.626e2d063f7c1e5p-5484L }, + { 0xf.97d7708bcb4c28ap+13800L, 0x1.92222235b217c128p+11344L, 0x5.4b3b99b0bd7e58cp+11356L, 0x5.4b3b99b0bd7e58c8p+11356L }, + { 0x3.7a62c19d2c7a4ef8p-1380L, 0xf.4bfc2d311b1d267p+12820L, -0x5.25a19533e5ec3898p+12832L, -0x5.25a19533e5ec389p+12832L }, + { 0x3.953c10cac334f73cp+2340L, 0x1.c610af4e1921cf5p-9256L, 0x1.039b482967f45ea8p-9244L, 0x1.039b482967f45eaap-9244L }, + { 0x2.f53d77c7f418237p+9336L, 0x3.c220b549da592788p-9580L, 0x8.9157a2d708af2c2p-9568L, 0x8.9157a2d708af2c3p-9568L }, + { 0x3.fbed3dcaaa06e4c4p-1192L, -0x3.e835e2ef87a1d7ecp-7400L, 0x1.229703d42721d65p-7388L, 0x1.229703d42721d652p-7388L }, + { 0x1.68487d450687a984p+660L, -0xf.2712729e7432756p+8724L, -0x2.71833e4eea72386cp+8736L, -0x2.71833e4eea723868p+8736L }, + { 0x3.91417fe2ad087038p+6300L, 0x7.021f29569b153f3p+4316L, 0xa.c8512daa73d6e1p+4328L, 0xa.c8512daa73d6e11p+4328L }, + { 0x3.c229138106afa45p+4436L, -0x3.676f1b1db23e0ccp+13624L, -0x3.b02d1d0112ccfa2cp+13636L, -0x3.b02d1d0112ccfa28p+13636L }, + { 0x1.aec776f7ea1c0bc6p+8464L, 0xd.28a1966f8b32e32p+11704L, 0x1.b3193facdf56a46ap+11720L, 0x1.b3193facdf56a46cp+11720L }, + { 0x1.c10c86e3b300597cp+3280L, 0x4.1a760e745f4d25cp+8252L, 0x3.4965c3cd3ca8ad3cp+8264L, 0x3.4965c3cd3ca8ad4p+8264L }, + { 0x1.b1db4fb675211df6p+0L, 0x1.6be49e4860e6d81ap+7060L, 0x1.14f3265dd400057ep+7060L, 0x1.14f3265dd400058p+7060L }, + { 0x4.b497e93cf288163p-2404L, -0x9.6961065f95443f1p-2968L, 0x5.84c8bc67a7686f48p-2956L, 0x5.84c8bc67a7686f5p-2956L }, + { 0x4.5dcb8cb337091ep+6896L, 0x5.11f25379bb653bd8p+14376L, 0x8.89e37aa0f515b74p+14388L, 0x8.89e37aa0f515b75p+14388L }, + { 0xa.7268d9e3b2e61bap+2464L, 0x7.8ebb30aae46e97dp-14932L, 0x4.8d75ec76fb62c77p-14920L, 0x4.8d75ec76fb62c778p-14920L }, + { 0x2.526a2db40e4a133p+12128L, 0x1.46f991704d64c4p-1120L, 0x3.c83fcabb8bd20458p-1108L, 0x3.c83fcabb8bd2045cp-1108L }, + { 0x8.6b4ceac3f5e0728p+13928L, 0x2.9d183c4c6fdb04a4p-9108L, 0x8.e3af724b181616bp-9096L, 0x8.e3af724b181616cp-9096L }, + { 0xb.8b98aaf25e886f9p+5156L, -0x6.d99dca78791969cp+12196L, -0x8.a0f1aedd7cc7487p+12208L, -0x8.a0f1aedd7cc7486p+12208L }, + { 0xc.075641c050086f8p+3892L, 0xe.deda4695e681519p+7992L, 0xe.2496aff9a14be97p+8004L, 0xe.2496aff9a14be98p+8004L }, + { 0x1.8c92fa660e15352ep-1228L, -0xa.5069a079cc133acp+7808L, 0x3.1733766197485eacp+7820L, 0x3.1733766197485ebp+7820L }, + { 0x2.24799a29d446fa08p-7812L, -0x4.05d8a4c62f6a18e8p-3908L, 0x7.abdfaecc0aeb94ep-3896L, 0x7.abdfaecc0aeb94e8p-3896L }, + { 0x1.a2963647b8c1e952p+1464L, -0x9.dc35dae9cfa046fp-9920L, -0x3.86a529d9cab1a628p-9908L, -0x3.86a529d9cab1a624p-9908L }, + { 0x7.42c1ce68p-16416L, -0x9.8b1dbd0b049084dp+2680L, 0x2.63dd875dd5ab9c6cp+2696L, 0x2.63dd875dd5ab9c7p+2696L }, + { 0x2.4da05a583c91938p+10540L, -0x4.25be1ba5de90e918p+932L, -0xa.ac6ed13b63a1d92p+944L, -0xa.ac6ed13b63a1d91p+944L }, + { 0x8.0e17e4b161c5a45p+2440L, -0x9.bf58078144f5743p-5248L, -0x5.d0515bfeef3843f8p-5236L, -0x5.d0515bfeef3843fp-5236L }, + { 0xd.1856d68bf52a57dp-6588L, -0x5.e570d6841b2c088p-8116L, 0x9.7a6a259ef770338p-8104L, 0x9.7a6a259ef770339p-8104L }, + { 0x9.872f5ce857da213p-1656L, 0xb.cf8a253dd36dfd2p-2832L, -0x4.c401c85ddd5c1c38p-2820L, -0x4.c401c85ddd5c1c3p-2820L }, + { 0x1.567c962075b01046p-2992L, 0x5.96dea6367a681b68p-12668L, -0x4.150f162a937d4c98p-12656L, -0x4.150f162a937d4c9p-12656L }, + { 0x2.330521783950b058p-8660L, -0x5.fd2d731707657b5p+12584L, 0xc.a91b62f8e76612cp+12596L, 0xc.a91b62f8e76612dp+12596L }, + { 0x1.6365c7132e7ab896p+14300L, 0x6.74e840f8b63c3dd8p+2708L, 0x1.68ad6bdb36c77d3ep+2724L, 0x1.68ad6bdb36c77d4p+2724L }, + { 0x1.23d9c444b8796b86p+10316L, 0x5.5531715a18534968p-13748L, 0xd.6e6068774baf9a8p-13736L, 0xd.6e6068774baf9a9p-13736L }, + { 0x7.aee9cd5902c35aa8p-404L, -0x1.79b3917e3ae0ef84p+2720L, 0x2.4fb84a5052ed5f7p+2728L, 0x2.4fb84a5052ed5f74p+2728L }, + { 0x6.800a7b095615357p+10936L, -0x3.8283a98b3d446a38p-5192L, -0x9.5f8e2dd199e2736p-5180L, -0x9.5f8e2dd199e2735p-5180L }, + { 0x1.78d6aeb5bd310056p+0L, 0x1.45e29cec4ee079d8p-3296L, 0xb.5c79c6a6c49a62bp-3300L, 0xb.5c79c6a6c49a62cp-3300L }, + { 0x4.b21a682b16590228p-13876L, -0x3.70fb6523fc99c194p+14144L, 0xb.a804c9fc9c673dfp+14156L, 0xb.a804c9fc9c673ep+14156L }, + { 0x3.23f2a35775b3a338p-8344L, 0xc.78c1635bb7ee7c4p-1084L, -0x1.966b48238708618ap-1068L, -0x1.966b482387086188p-1068L }, + { 0x3.f496d494eff66598p-12580L, 0x1.6b790fafdbb51f08p+12268L, -0x4.5c277f50b347c3f8p+12280L, -0x4.5c277f50b347c3fp+12280L }, + { 0x8.ec1b59a9caa6303p-10924L, 0x3.e8d13e253b2213ccp+628L, -0xa.6c668c91aec61d6p+640L, -0xa.6c668c91aec61d5p+640L }, + { 0xd.a1a02db93dcda76p-5712L, -0x3.07a2a2ead26ae24cp+6968L, 0x4.38ef190fdff3c19p+6980L, 0x4.38ef190fdff3c198p+6980L }, + { 0x1.a0b348b4888fa2fcp-1152L, -0xe.f9e7aa3db6ed0afp+12620L, 0x4.35a0bc4fb075f8d8p+12632L, 0x4.35a0bc4fb075f8ep+12632L }, + { 0x3.6f67cd0a4f4f4a6cp-3780L, -0xd.8095adbeaff6317p+14292L, 0xc.746980c872b61e4p+14304L, 0xc.746980c872b61e5p+14304L }, + { 0x3.c5516656a58130ccp+11040L, 0x1.c0bfa71287c3acdap-1104L, 0x4.b9ba44f7f286c4a8p-1092L, 0x4.b9ba44f7f286c4bp-1092L }, + { 0x1.d9f5b1f814163e0ep+7296L, -0x2.04efcf98cc6bd1c8p+1188L, -0x3.98e7df8daf1d5404p+1200L, -0x3.98e7df8daf1d54p+1200L }, + { 0x3.a704d93ae36e79c4p-2416L, 0xa.3c0c59ab56e5e6cp+3204L, -0x6.0839412e892258p+3216L, -0x6.0839412e892257f8p+3216L }, + { 0x1.ff1cd2d2fae4bd48p+0L, -0xc.beb414075682a59p+4332L, -0xc.b689b68cb462e06p+4332L, -0xc.b689b68cb462e05p+4332L }, + { 0x7.865db97fb832a698p-3852L, 0x3.210fd99d2fe72c7p+10992L, -0x2.f0c5e11a2cdeea2cp+11004L, -0x2.f0c5e11a2cdeea28p+11004L }, + { 0x4.2bc44b2356390acp-4624L, -0x7.cd81763c0a3f1938p-10236L, 0x8.cdfdec8404d7021p-10224L, 0x8.cdfdec8404d7022p-10224L }, + { 0xf.6e6ebaa083c4cd3p+6772L, 0x3.53aa70c4188f244p-6152L, 0x5.80e5ae2af4891598p-6140L, 0x5.80e5ae2af48915ap-6140L }, + { 0xe.77c56c623d0f0eep-3144L, 0x8.6f79329139f632dp+3132L, -0x6.7788429ecc43227p+3144L, -0x6.7788429ecc432268p+3144L }, + { 0x7.b93a559e4e12075p-9120L, -0x1.351b28adc68b89bcp-13008L, 0x2.b0057e68ca71b908p-12996L, 0x2.b0057e68ca71b90cp-12996L }, + { 0x1.80e63adf125be828p+2620L, -0x6.b3b07792c5acf1b8p+4564L, -0x4.49af36f38515eb78p+4576L, -0x4.49af36f38515eb7p+4576L }, + { 0x1.f5bda0c135772ea8p-14388L, 0x1.d2d15b323301604cp+6960L, -0x6.67ad949e9dd71688p+6972L, -0x6.67ad949e9dd7168p+6972L }, + { 0xe.eba318936113b91p-13680L, -0x7.e2bc9165ba0d4e7p-744L, 0x1.a5457d1a3b4bf81cp-728L, 0x1.a5457d1a3b4bf81ep-728L }, + { 0x1.a2e010d583127526p+3200L, 0x1.e8a7eb43e7eecf8ep-11800L, 0x1.7dd8e1e0fb4c040cp-11788L, 0x1.7dd8e1e0fb4c040ep-11788L }, + { 0x2.089221e2807b8ae8p+1780L, -0x1.67ebc2e75a0f1464p+7020L, -0x9.c803d1c26ea95eap+7028L, -0x9.c803d1c26ea95e9p+7028L }, + { 0x4.0ac05ec8p-16416L, -0xa.530c1b060238f06p-5476L, 0x2.95f89a58fc3e6abp-5460L, 0x2.95f89a58fc3e6ab4p-5460L }, + { 0x3.aa0cc319c013919p-6132L, -0xf.0292f4401d18d5cp+4904L, 0x1.676d88de1fc94da8p+4920L, 0x1.676d88de1fc94daap+4920L }, + { 0x6.fd442271482ca6dp-14508L, -0x6.67012d8b67014328p+3032L, 0x1.6ac38118c5f3b35cp+3048L, 0x1.6ac38118c5f3b35ep+3048L }, + { 0x1.4d6d06de5fee4cc4p-7248L, -0x9.620bcddbdd20a79p-8756L, 0x1.09a45a7db576a522p-8740L, 0x1.09a45a7db576a524p-8740L }, + { 0x8.2e6ecc0d5fbbd0ap-1672L, -0x1.a3b873c6b160474p-2868L, 0xa.b053f78195d37f2p-2860L, 0xa.b053f78195d37f3p-2860L }, + { 0x2.c4d0c300d64c511p+7888L, 0xd.81985e859cf4061p+14748L, 0x1.a03cff013e09efbap+14764L, 0x1.a03cff013e09efbcp+14764L }, + { 0x2.3c05e4cb4622a66p-13256L, 0x3.cf39982caefbf098p-14636L, -0xc.53df31e9a942054p-14624L, -0xc.53df31e9a942053p-14624L }, + { 0x1.8dad3bd8dae62b26p+9496L, -0x3.f54fb00da54140bcp-6956L, -0x9.2d607d3aa28d78fp-6944L, -0x9.2d607d3aa28d78ep-6944L }, + { 0x1.53961f1d7569affp-5204L, -0x9.3feda7319eb8e46p+11244L, 0xb.c03c5caa9f7303ap+11256L, 0xb.c03c5caa9f7303bp+11256L }, + { 0x1.e3f51e1e159cf164p-1700L, -0x1.ee40d6991aa1e62cp-1968L, 0xc.d0607a66892a6d7p-1960L, 0xc.d0607a66892a6d8p-1960L }, + { 0xe.bee987bad9326dap-2508L, -0x3.a34a091c39f5bd5p-4752L, 0x2.39599d7487d87de4p-4740L, 0x2.39599d7487d87de8p-4740L }, + { 0x1.d1f2488e01bece42p+0L, 0x7.3390d5c71ae5e8f8p+4120L, 0x6.38e0cf11409a5648p+4120L, 0x6.38e0cf11409a565p+4120L }, + { 0x5.e2a8926a1f2a69f8p-1008L, -0x4.b1c091043808ebe8p+10972L, 0x1.26fe52f8e473663p+10984L, 0x1.26fe52f8e4736632p+10984L }, + { 0x1.8989c2560de848e8p+14156L, -0xf.7833feab3b30637p-11276L, -0x3.577473e6616fea3p-11260L, -0x3.577473e6616fea2cp-11260L }, + { 0x6.c87c79c7f39458b8p-12544L, 0xb.d70d015b5f04174p+8408L, -0x2.4408c9a20dd4504p+8424L, -0x2.4408c9a20dd4503cp+8424L }, + { 0xd.4a8d8fca0cbe02bp+5456L, 0x6.f866735c25236f98p+1300L, 0x9.4a80b93e0752cc4p+1312L, 0x9.4a80b93e0752cc5p+1312L }, + { 0x6.48ac3faff9ac8af8p+13024L, 0x1.62b2ac359758568p+3048L, 0x4.680ee828882103ep+3060L, 0x4.680ee828882103e8p+3060L }, + { 0xa.a22cceb5d16a7b9p+12552L, 0x1.e6ecf4dcc20e1c9ap+3900L, 0x5.d490ef450521d888p+3912L, 0x5.d490ef450521d89p+3912L }, + { 0x1.830dd48479f78adap+2696L, -0x1.3cbe7875c4da1bacp+13696L, -0xd.0872cbd8e0bf46bp+13704L, -0xd.0872cbd8e0bf46ap+13704L }, + { 0xa.c01d2e9cf20bab2p-3968L, -0x3.294bc4bc541628p-3004L, 0x3.0f54180488efda18p-2992L, 0x3.0f54180488efda1cp-2992L }, + { 0x3.e058d43b80e19b7cp+11400L, -0x7.810b603203760db8p+9496L, -0x1.4e392da4e7b28d82p+9512L, -0x1.4e392da4e7b28d8p+9512L }, + { 0x1.ba7195161943bbbep+12644L, -0x1.f393533d8bcf2b9p-6464L, -0x6.063e2d250c93d678p-6452L, -0x6.063e2d250c93d67p-6452L }, + { 0x1.1f75457p-16416L, -0x3.f70754c334988a7cp+7532L, 0xf.e400c62e39970d1p+7544L, 0xf.e400c62e39970d2p+7544L }, + { 0x3.731a5226115dd018p-10664L, -0x5.a44d891b492c118p+6688L, 0xe.afa29af29c307fp+6700L, 0xe.afa29af29c307f1p+6700L }, + { 0x5.b4fdcb6dd89d9c6p+11124L, -0xb.318ae2fc05a5137p-14500L, -0x1.e680e7664b81aa66p-14484L, -0x1.e680e7664b81aa64p-14484L }, + { 0x1.79ab15d5ea5af81ep-14952L, 0x4.f22aafc2c87dc378p+5960L, -0x1.20dd46df8b6d5d0ep+5976L, -0x1.20dd46df8b6d5d0cp+5976L }, + { 0x5.7ae9f319702197fp+1424L, -0x5.2488fe3916fe2e88p+10340L, -0x1.ca7d914199218ff6p+10352L, -0x1.ca7d914199218ff4p+10352L }, + { 0x1.7e566d05fa4bfe68p-11828L, -0xf.77808166e893761p+7896L, 0x2.ca9469fa524cdc5p+7912L, 0x2.ca9469fa524cdc54p+7912L }, + { 0xa.d514038a07e5b37p+12964L, 0x1.629f9336bc3a571p+1948L, 0x4.62b1beae45dbf53p+1960L, 0x4.62b1beae45dbf538p+1960L }, + { 0x4.3bf7a1a300a5f018p+10364L, -0xf.f30d3f07ad37473p+12984L, -0x2.85d5019bf4601528p+13000L, -0x2.85d5019bf4601524p+13000L }, + { 0x2.6b5061434883623p-9208L, 0x9.a456d030af10e3ap-14264L, -0x1.5ac2c899349909fp-14248L, -0x1.5ac2c899349909eep-14248L }, + { 0xe.89c1a581a13c8eap-12176L, -0x2.da80e03a956954f4p+13388L, 0x8.7ad8ca0015fc69dp+13400L, 0x8.7ad8ca0015fc69ep+13400L }, + { 0xf.0b6de12e05c3635p+10332L, 0x1.49091d3c30a38fe2p+8540L, 0x3.3e4b2c2a174d602p+8552L, 0x3.3e4b2c2a174d6024p+8552L }, + { 0x3.1086147p-16416L, -0xa.9787fe8322a2a72p-10772L, 0x2.a723d3adbf2fd25p-10756L, 0x2.a723d3adbf2fd254p-10756L }, + { 0x2.ce0956e8786046bp-8960L, 0x7.2bd571ac8ece1a28p-14644L, -0xf.af382fad626ef52p-14632L, -0xf.af382fad626ef51p-14632L }, + { 0x5.0c6e2ff0203fe848p+13020L, -0x1.07ec467a6a9c5c22p-8240L, -0x3.4715d4de6a6a238p-8228L, -0x3.4715d4de6a6a237cp-8228L }, + { 0x1.33b9813117d5b116p-8692L, -0x3.d4488a6e55d0c3cp+8188L, 0x8.202aab93e9336b5p+8200L, 0x8.202aab93e9336b6p+8200L }, + { 0x1.45a904169e9fbd9cp-6008L, -0x1.94df821b8722bfaep+11360L, 0x2.51d50e0975a72d2cp+11372L, 0x2.51d50e0975a72d3p+11372L }, + { 0x3.f58aff984b9b3204p+9232L, -0x3.a6650315666a36fcp-14312L, -0x8.3a7d9b2f7306025p-14300L, -0x8.3a7d9b2f7306024p-14300L }, + { 0x9.39fedfcb334646bp-480L, -0x1.f25409b8f76e0daap+11056L, 0x3.a02008fe8682753p+11064L, 0x3.a02008fe86827534p+11064L }, + { 0x6.0516ed4c30287198p+8164L, -0x1.7089f60565c4e04ep-6796L, -0x2.decaa14cd6f9a774p-6784L, -0x2.decaa14cd6f9a77p-6784L }, + { 0x8.d065ef1229a853cp+11308L, -0xd.57b3e95e8e6b01cp+2380L, -0x2.4d87e3ad36e3efc8p+2396L, -0x2.4d87e3ad36e3efc4p+2396L }, + { 0x2.fa1ba053149e004cp-656L, -0x2.7fd142bf349abf18p-2276L, 0x6.639940c58c55f74p-2268L, 0x6.639940c58c55f748p-2268L }, + { 0xf.c238b2baa010058p+9912L, 0x4.59241972fc24c5a8p+11548L, 0xa.86cb9e1cc4f0be8p+11560L, 0xa.86cb9e1cc4f0be9p+11560L }, + { 0x1.d646aaa62a9383e6p+0L, 0x3.00f84a86bb91dbap-6056L, 0x2.a2aaa0b9b93a6c6p-6056L, 0x2.a2aaa0b9b93a6c64p-6056L }, + { 0x2.77f437759361e3fp-2356L, -0x3.0610c5014f9956a8p-8032L, 0x1.bcfe133b031e1e7p-8020L, 0x1.bcfe133b031e1e72p-8020L }, + { 0x1.bc5bfdb21630a828p+4076L, -0x6.3a84a13517144a38p+4628L, -0x6.330ac4906176e618p+4640L, -0x6.330ac4906176e61p+4640L }, + { 0xd.6d13288b708cd99p+5852L, -0x4.2028a34835ab7088p+13624L, -0x5.e5e9658792a973fp+13636L, -0x5.e5e9658792a973e8p+13636L }, + { 0x2.fa0781a5ce6c3e88p+6884L, 0x1.c6c301a4213c2a1p+14212L, 0x2.fc79f81093748b58p+14224L, 0x2.fc79f81093748b5cp+14224L }, + { 0x5.9f857743c692f8a8p-11492L, -0x2.8b763c9b1e5765dcp+5088L, 0x7.23630afba9bef2cp+5100L, 0x7.23630afba9bef2c8p+5100L }, + { 0x7.a2e7744675542a68p+4476L, 0x9.93f484e751c1e49p+4604L, 0xa.792fe8f5fdd5e07p+4616L, 0xa.792fe8f5fdd5e08p+4616L }, + { 0x1.11daae277d6f5364p-8812L, -0x3.d9d851412428f74p+7268L, 0x8.48e4229b98372p+7280L, 0x8.48e4229b9837201p+7280L }, + { 0x1.599e76b4add8a768p+12640L, 0xc.0312220675c48dep-8384L, 0x2.511cd2efecb3462cp-8368L, 0x2.511cd2efecb3463p-8368L }, + { 0x1.d76fce983ea18f04p+3984L, 0xd.3b162e429a284abp-7116L, 0xc.df330f0e1231f7bp-7104L, 0xc.df330f0e1231f7cp-7104L }, + { 0x1.8b74ca29e35918d2p-436L, -0x2.54fefc87c991985p+2764L, 0x3.f74bbbe1e37fc588p+2772L, 0x3.f74bbbe1e37fc58cp+2772L }, + { 0xc.fb85e61563cc723p-4L, -0x1.5cd1de7bbfdd138p-14584L, 0x6.92b84a87a4b81f6p-14588L, 0x6.92b84a87a4b81f68p-14588L }, + { 0x4.06dfa8140d8a6c8p-12744L, -0x1.44ff72f9afcc807cp+10848L, 0x3.f303f71b131fd3d4p+10860L, 0x3.f303f71b131fd3d8p+10860L }, + { 0x1.5eaf968af0056a88p+2204L, -0x7.35ddb1c4dfd4818p+8056L, -0x3.e1706bd38b2ad348p+8068L, -0x3.e1706bd38b2ad344p+8068L }, + { 0x1.f79b47daf4ce0c82p+13516L, 0x4.7522f5f4f67f2aa8p-60L, 0xe.b5ccbbe59c33412p-48L, 0xe.b5ccbbe59c33413p-48L }, + { 0x1.45e7258945383cdap+1872L, -0x3.206a35c1d871c654p+3456L, -0x1.6de1f719d8e923e2p+3468L, -0x1.6de1f719d8e923ep+3468L }, + { 0x8.c482717e9cf14a6p-7368L, -0x2.9b72ec9fe7478ae8p-716L, 0x4.b01d9179e2b0c0c8p-704L, 0x4.b01d9179e2b0c0dp-704L }, + { 0x3.5aa11443b7f48ef8p-8396L, -0x1.5837711dfe654728p+5476L, 0x2.c16e15ae8bd79e5cp+5488L, 0x2.c16e15ae8bd79e6p+5488L }, + { 0x2.53bd4242192f7ab4p+14312L, -0x2.a60390f68f368cecp+9468L, -0x9.414718fc5f5020bp+9480L, -0x9.414718fc5f5020ap+9480L }, + { 0x3.7ce54eadcdde9f24p-3904L, -0x1.501e18a96a20b756p-1544L, 0x1.4036d2b1739a047cp-1532L, 0x1.4036d2b1739a047ep-1532L }, + { 0xd.5b4db41cff6f2cap+4432L, -0x1.570fa20acb2ddc2ep+13024L, -0x1.7384184ab61b5b9p+13036L, -0x1.7384184ab61b5b8ep+13036L }, + { 0x2.88f36222719718e8p-1928L, -0x4.fbec2f96890bc5e8p+6228L, 0x2.5829a880863725e8p+6240L, 0x2.5829a880863725ecp+6240L }, + { 0x1.efcbb15e88adf09p+0L, 0xc.97d62d013af0088p+8488L, 0xc.0241b42358d14d1p+8488L, 0xc.0241b42358d14d2p+8488L }, + { 0x5.f09eeb96dc538558p-4736L, 0x5.098d7678f15a72p-4304L, -0x5.d23c6567e92e3838p-4292L, -0x5.d23c6567e92e383p-4292L }, + { 0x1.0c3d81a001f325bep-3164L, -0x8.2d7911586469751p+564L, 0x6.51177426b609ff5p+576L, 0x6.51177426b609ff58p+576L }, + { 0xb.b5dda03bd01aa1bp-2384L, 0x3.80f852e5b49c1f08p-6208L, -0x2.0949885ea1918fccp-6196L, -0x2.0949885ea1918fc8p-6196L }, + { 0x4.7683b95a2d97f8ap-5156L, -0x4.35b7f1c56a3d2cbp+1424L, 0x5.4c0d70ada064bc7p+1436L, 0x5.4c0d70ada064bc78p+1436L }, + { 0x2.bdaaef3c4b35064p+11680L, -0x2.faa1909111fad7dcp+14388L, -0x8.7ef60bf38a0dd3ep+14400L, -0x8.7ef60bf38a0dd3dp+14400L }, + { 0x5.d46d6048b5d6e628p-9212L, 0xd.71bd470441c9db9p-9948L, -0x1.e3a6a527a3ea5d7ap-9932L, -0x1.e3a6a527a3ea5d78p-9932L }, + { 0x1.5f8f1649fa66406p+6520L, -0x1.63725477bb562e8cp+1156L, -0x2.35d6a805caba07c8p+1168L, -0x2.35d6a805caba07c4p+1168L }, + { 0xe.e3fdb321f26f9c4p+6484L, -0x3.b60b3167c404578p-3056L, -0x5.e0d492e2b6ee28b8p-3044L, -0x5.e0d492e2b6ee28bp-3044L }, + { 0x7.c4487897dc41f578p-5772L, 0x6.22ee9224c3c35c1p+10016L, -0x8.a49754c89a1f8f7p+10028L, -0x8.a49754c89a1f8f6p+10028L }, + { 0x2.db79f9dd4c22fe8p-11264L, -0x9.3987a9a321c2401p+48L, 0x1.95d5583932101174p+64L, 0x1.95d5583932101176p+64L }, + { 0xb.214592ce214ecfep-4L, -0x2.e889a996b77521fcp+10320L, 0x1.85db50a2a5f1944cp+10320L, 0x1.85db50a2a5f1944ep+10320L }, + { 0x6.80b6787c7ed0c98p-7488L, 0x2.6be4487c1dcd7bfp-1488L, -0x4.6cd4aeb3074b39c8p-1476L, -0x4.6cd4aeb3074b39cp-1476L }, + { 0x6.e3da0acb9e1505fp-2772L, -0x5.f7c7fac38340451p+11136L, 0x4.08e6346af3f436b8p+11148L, 0x4.08e6346af3f436cp+11148L }, + { 0x3.313fa5881a2d6e5cp-9600L, 0x2.1ac7da26f1204bfcp-2664L, -0x4.ee8c0326a97c7bf8p-2652L, -0x4.ee8c0326a97c7bfp-2652L }, + { 0x2.62f5aab737b6705p+4216L, -0xf.65bfa7da3df8702p-5984L, -0xf.da6fef5fb57dd6p-5972L, -0xf.da6fef5fb57dd5fp-5972L }, + { 0xc.e4018849b76a23ap+14856L, 0xc.90289d1db5a105cp-192L, 0x2.d93c0adf50cdc9bp-176L, 0x2.d93c0adf50cdc9b4p-176L }, + { 0x1.c0f835ea894de5f4p-10024L, -0xa.50a22423b6723b2p-2320L, 0x1.93dcf0ad050407e8p-2304L, 0x1.93dcf0ad050407eap-2304L }, + { 0x3.6383fb20c10cc778p+14900L, -0xa.7913fd7ca999ff9p-10828L, -0x2.61a190302a99bc9p-10812L, -0x2.61a190302a99bc8cp-10812L }, + { 0x1.be2aea0c1a473f64p+14204L, 0x3.b5e9eee471131f3p+4752L, 0xc.de458efd065f26ep+4764L, 0xc.de458efd065f26fp+4764L }, + { 0x1.21bc96f47956350ep+4740L, 0x7.f8fdeae69d08eb7p+8496L, 0x9.39fa9f5f9ddd9a5p+8508L, 0x9.39fa9f5f9ddd9a6p+8508L }, + { 0x4.9f7437754e62375p-4876L, -0x4.90b85f6fbc1b8688p+8944L, 0x5.6ea6245478d9c558p+8956L, 0x5.6ea6245478d9c56p+8956L }, + { 0x7.e866902p-16416L, 0xf.317f8a3f97460cep-7188L, -0x3.ce18bf0bbbe749e4p-7172L, -0x3.ce18bf0bbbe749ep-7172L }, + { 0x6.a13f4e0f825a5edp-4440L, -0x1.99bf7b4b74e4b654p+5044L, 0x1.bbe32d09c4b547a2p+5056L, 0x1.bbe32d09c4b547a4p+5056L }, + { 0x7.54085e25bafd5bd8p+3704L, 0x1.db179fdf5aef456ap-13196L, 0x1.adf52fae66292f0ep-13184L, 0x1.adf52fae66292f1p-13184L }, + { 0x6.fc29f1b82c7f8a7p-1712L, 0x7.3136749a8e732cbp+12372L, -0x3.004f0ed0aea3e038p+12384L, -0x3.004f0ed0aea3e034p+12384L }, + { 0xe.2487cdb8e096076p-1392L, -0x2.b7d3c8f4fa93f2dcp-11416L, 0xe.bd2c23a004fef05p-11408L, 0xe.bd2c23a004fef06p-11408L }, + { 0x1.0a524b330b6d1cf8p+3992L, 0x6.f2be0ff2b50477ap-88L, 0x6.c59a9376d2d243f8p-76L, 0x6.c59a9376d2d244p-76L }, + { 0x4.53290c103cf68ddp+1876L, -0x2.7b48218ca4945d54p-184L, -0x1.234aab65fdcc0972p-172L, -0x1.234aab65fdcc097p-172L }, + { 0x5.f854a5860d3485fp+11712L, 0x3.e2501079eb01d518p-972L, 0xb.1bbd2067493cbf4p-960L, 0xb.1bbd2067493cbf5p-960L }, + { 0x7.c586111d11b319f8p-13432L, -0x1.a13ae4a3354b1b9cp-4876L, 0x5.57eb7cb8deede698p-4864L, 0x5.57eb7cb8deede6ap-4864L }, + { 0x8.d2126b4d376bf71p+6480L, -0xb.c76f499facfc4cbp+5248L, -0x1.2a4d3012ac4367c2p+5264L, -0x1.2a4d3012ac4367cp+5264L }, + { 0x8.af0132d6f3c8239p-1932L, 0x2.179549e27c305d7p-7188L, -0xf.c3748e5a2f3e907p-7180L, -0xf.c3748e5a2f3e906p-7180L }, + { 0xa.e384039aa141762p-4L, -0xd.84901915b6223efp+3372L, 0x7.816daa88ba083fbp+3372L, 0x7.816daa88ba083fb8p+3372L }, + { 0x7.a25f680376b80218p+10772L, 0x1.fa22f565869b428ep-7916L, 0x5.337133b5a9625a98p-7904L, 0x5.337133b5a9625aap-7904L }, + { 0x1.a82f4735f426182cp+708L, -0x3.06c97154863b8668p+11728L, -0x8.60f995bea7d1f3ep+11736L, -0x8.60f995bea7d1f3dp+11736L }, + { 0x6.f0206ea828b61b08p+6012L, 0x3.551406b5d024e324p-4656L, 0x4.e4b523f064ac9a2p-4644L, 0x4.e4b523f064ac9a28p-4644L }, + { 0x1.6f789d7564f928e8p-3864L, 0x5.4600f951d5eba66p-9312L, -0x4.f95deb0b036b9c7p-9300L, -0x4.f95deb0b036b9c68p-9300L }, + { 0x3.0a8648ba053122fp-1060L, 0x1.91cf22af1ab650a4p+7572L, -0x6.7d38ed8edc9459e8p+7580L, -0x6.7d38ed8edc9459ep+7580L }, + { 0x8.bc7d07ddb2c022p+5920L, 0x6.10774af59183db48p+4288L, 0x8.c4fbd3cdc063727p+4300L, 0x8.c4fbd3cdc063728p+4300L }, + { 0x3.5799356238e9851p+9016L, 0xa.169ce0f7fec2be6p+12212L, 0x1.635df4dc89456662p+12228L, 0x1.635df4dc89456664p+12228L }, + { 0x1.01d4b210da78dd4cp+11956L, -0x6.e1bf3c78ece6063p+10052L, -0x1.41672971127f38a4p+10068L, -0x1.41672971127f38a2p+10068L }, + { 0xf.d84c5b3d6730ba3p+8852L, -0x1.9f855997d2792acep-6872L, -0x3.826673c9aa64c2c4p-6860L, -0x3.826673c9aa64c2cp-6860L }, + { 0x5.8ce7c53b96255d4p+13568L, -0xe.df6fe073a22e50cp-12344L, -0x3.1466efb79f69482p-12328L, -0x3.1466efb79f69481cp-12328L }, + { 0x6.75dca56p-16416L, -0x5.d3093bb8c581a6e8p-10216L, 0x1.756d02c70d3f1626p-10200L, 0x1.756d02c70d3f1628p-10200L }, + { 0xc.d570e244c0e60bep-12400L, -0x7.8ae826298b8c69ap+11848L, 0x1.6d3c875ec58ba32ap+11864L, 0x1.6d3c875ec58ba32cp+11864L }, + { 0x7.84802e101bb6a3f8p-5756L, -0x7.995991a529314d5p+2864L, 0xa.ac5dc693017439dp+2876L, 0xa.ac5dc693017439ep+2876L }, + { 0x1.25970c4a9d9bfa12p+4480L, -0x1.2660afac683e1d8ep+14004L, -0x1.41fd632043cb071ep+14016L, -0x1.41fd632043cb071cp+14016L }, + { 0x1.c8b98918c3fb8242p-364L, 0x9.c0fa6e13b7c7fcp-2056L, -0xd.d63ea6a5acb5b84p-2048L, -0xd.d63ea6a5acb5b83p-2048L }, + { 0x2.b29ea16d605290c8p-14036L, 0x2.57c6bfd9ce8106fp-4776L, -0x8.07142545c68a338p-4764L, -0x8.07142545c68a337p-4764L }, + { 0x1.179a8074009c3446p-7324L, -0x8.1c9d05645c7987cp-4408L, 0xe.811940c7fc9af73p-4396L, 0xe.811940c7fc9af74p-4396L }, + { 0x1.a274b5d250ba4a7ap-14136L, -0x9.4cf62e7e77f656p-7444L, 0x2.018b21e6dce1dfacp-7428L, 0x2.018b21e6dce1dfbp-7428L }, + { 0x1.426ce0de34aa412ap-7048L, -0x1.086b031d68e9f6fap-7232L, 0x1.c6f6a2cc131aca9p-7220L, 0x1.c6f6a2cc131aca92p-7220L }, + { 0x6.dcdeb470b2fc188p+14208L, 0x2.0ff586b55e3364a4p-8660L, 0x7.27b75caeddd08bdp-8648L, 0x7.27b75caeddd08bd8p-8648L }, + { 0xf.30d46d764112444p+192L, -0x5.e6a539ee1aceb9b8p-2624L, -0x4.84256283872b606p-2616L, -0x4.84256283872b6058p-2616L }, + { 0xa.8afac152291530ap-4L, -0x5.9e1738c1ccd8a9a8p-20L, 0x3.617206ff8982409cp-20L, 0x3.617206ff898240ap-20L }, + { 0xa.4bd5c8afa05a28cp-10580L, -0x1.23804bdf5e1e2c04p+9232L, 0x2.f0b5da03924596b4p+9244L, 0x2.f0b5da03924596b8p+9244L }, + { 0x2.ceafdb5372991918p+2280L, 0x7.bc4dc1a54a48fdbp+5068L, 0x4.4f099a01d4cd5418p+5080L, 0x4.4f099a01d4cd542p+5080L }, + { 0x3.fc5a846dfbec9adp-9172L, 0x3.b4c03ba6cf5a812p-3940L, -0x8.4c092babb4e1d41p-3928L, -0x8.4c092babb4e1d4p-3928L }, + { 0x3.14be1ced6c3553bcp+1944L, -0xa.e04dd91094312efp-2976L, -0x5.2a8f73a173accdb8p-2964L, -0x5.2a8f73a173accdbp-2964L }, + { 0x2.2c4ef645ea46758p+8712L, 0x6.d3f30796d0334a7p+11056L, 0xe.8648bda7e0f6294p+11068L, 0xe.8648bda7e0f6295p+11068L }, + { 0x4.b6b357f4259a83ap-10956L, -0x8.d45410dc1895ef4p+11920L, 0x1.79cb3dbc67eac20cp+11936L, 0x1.79cb3dbc67eac20ep+11936L }, + { 0x4.38896f39ca42f888p-5568L, 0x5.28bf133fa6f14d3p-3772L, -0x7.02b83fde3a8b00dp-3760L, -0x7.02b83fde3a8b00c8p-3760L }, + { 0x1.6739091433ebe3bap+7952L, 0x3.77db8ced789b50ep-4560L, 0x6.bbcc5b6ebb15a848p-4548L, 0x6.bbcc5b6ebb15a85p-4548L }, + { 0x2.6e82f4e37e55fa08p+480L, 0x7.f37ea4723b67675p+10636L, 0xe.f2bedee5c61d497p+10644L, 0xe.f2bedee5c61d498p+10644L }, + { 0x1.5fac4bb395ba2bccp+4156L, -0x4.ad1adda7354f267p-4744L, -0x4.bec64886a213215p-4732L, -0x4.bec64886a2132148p-4732L }, + { 0x2.a62a7e9p-16416L, -0x1.08fba0f001a4ad6p+6040L, 0x4.25e934181bdf777p+6052L, 0x4.25e934181bdf7778p+6052L }, + { 0x1.749ae18d5c47f94ep-13280L, 0x5.d580a2b2bafe339p-6680L, -0x1.2ea0483b70c44786p-6664L, -0x1.2ea0483b70c44784p-6664L }, + { 0x1.58297b3f01d01614p+4120L, 0x1.0f95b19865e46e46p-848L, 0x1.1134515c360fd09ep-836L, 0x1.1134515c360fd0ap-836L }, + { 0x4.a3a8a81ba62dd2ep+10816L, -0x7.dc627c37bc9c54d8p-7548L, -0x1.4c30a83a929ac21ep-7532L, -0x1.4c30a83a929ac21cp-7532L }, + { 0x7.289dc72de566113p-2256L, 0x4.98b3897e6f049388p-13832L, -0x2.874a0b468128b94cp-13820L, -0x2.874a0b468128b948p-13820L }, + { 0x9.8f2b30dd1fe6e25p-4736L, -0x2.78a78fa09bce90f4p-9784L, 0x2.db00f635c2145e2cp-9772L, 0x2.db00f635c2145e3p-9772L }, + { 0x5.c89b4377f34a817p+6700L, -0x1.8aae5b4631e05fa4p-348L, -0x2.85d728f29858853cp-336L, -0x2.85d728f298588538p-336L }, + { 0x5.a8ced3fe21a70d68p-4096L, 0x5.2deec40853fa524p-1044L, -0x5.2d1f88ec24116c38p-1032L, -0x5.2d1f88ec24116c3p-1032L }, + { 0x2.7d2734d21b77549p-2196L, 0x8.aa549d7c779757cp-9208L, -0x4.a49b7a241fea8f4p-9196L, -0x4.a49b7a241fea8f38p-9196L }, + { 0x7.b8041d5b3bbff3ap+12080L, 0x6.cbce06dc637006ep-13696L, 0x1.40c5137e55d4c17ep-13680L, 0x1.40c5137e55d4c18p-13680L }, + { 0x2.fc10d82242c59c8cp-12304L, -0x7.6637c2344d0ca91p+5988L, 0x1.63952bab4a1661f6p+6004L, 0x1.63952bab4a1661f8p+6004L }, + { 0x7.eceb7efp-16416L, -0x1.0130744d8cd6c3f2p+7712L, 0x4.0694309a8adc05bp+7724L, 0x4.0694309a8adc05b8p+7724L }, + { 0x5.64bdddf529c9a6dp-9832L, -0x6.58f61fd8c5e3ec6p+3184L, 0xf.3b93e106624f0dp+3196L, 0xf.3b93e106624f0d1p+3196L }, + { 0x1.990690db94ff14d8p-2496L, -0x1.6f80a4634a39b2d2p-992L, 0xd.fe2dcfcc7595336p-984L, 0xd.fe2dcfcc7595337p-984L }, + { 0x9.fb2ddd234c8a1e1p-6780L, -0xa.5203c030e1c9aa7p-11896L, 0x1.1131d9f0246b6b0cp-11880L, 0x1.1131d9f0246b6b0ep-11880L }, + { 0xf.3050779847dc78ep-15004L, 0x3.95b4f2d22803a954p-1624L, -0xd.20c275868938d06p-1612L, -0xd.20c275868938d05p-1612L }, + { 0x6.7697c3e239db107p+10048L, 0x1.21545bdaae9fde28p-9920L, 0x2.c5f3a0898c76a22p-9908L, 0x2.c5f3a0898c76a224p-9908L }, + { 0x2.c39c3b1642e4fb18p-13664L, 0x1.1fc8462fb1f9d056p+988L, -0x3.bfebb82e0cc421ap+1000L, -0x3.bfebb82e0cc4219cp+1000L }, + { 0x2.ff120c969ae503b8p+3064L, -0x2.431fbfb49e7b4928p-9856L, -0x1.b16f8df41d25490ap-9844L, -0x1.b16f8df41d254908p-9844L }, + { 0x6.976ed0ef48c07898p-8216L, -0x4.6c8e610cee69d8dp-12772L, 0x8.deff03b117f428dp-12760L, 0x8.deff03b117f428ep-12760L }, + { 0x2.6fa1664ea3a1be14p-2884L, 0x1.63214b8ba5b95b7cp-3720L, -0xf.9efae89cadca879p-3712L, -0xf.9efae89cadca878p-3712L }, + { 0x2.e1cf29eba91248ep-152L, -0x4.589495f2b172e14p+5176L, 0x2.8df5325dc46aa2a4p+5184L, 0x2.8df5325dc46aa2a8p+5184L }, + { 0x5.bdc83bdp-16416L, -0x1.5a0086d9ae7633cep+10348L, 0x5.6a7f95f9b29fe038p+10360L, 0x5.6a7f95f9b29fe04p+10360L }, + { 0x1.3bc8b60293078f84p-11188L, -0xd.1712b08be6e7f9cp-7148L, 0x2.3c10661bfd903a2cp-7132L, 0x2.3c10661bfd903a3p-7132L }, + { 0x1.e7590332a0320ee4p+4180L, -0x8.c39f3bc3d0d8d73p+1072L, -0x8.f2247e086109516p+1084L, -0x8.f2247e086109515p+1084L }, + { 0x6.4a24ad49492e8648p-9284L, -0xf.be9fc104f449286p+7428L, 0x2.3ad3547099aaf9e8p+7444L, 0x2.3ad3547099aaf9ecp+7444L }, + { 0xf.8fb50e1402f38bp-4824L, 0x2.9deafdf9778819d4p+2484L, -0x3.1456753ac5fc7a9cp+2496L, -0x3.1456753ac5fc7a98p+2496L }, + { 0xd.3ea27eab88fb691p+14284L, -0x1.cba84ae0173bf72p+3824L, -0x6.436237e69f433458p+3836L, -0x6.436237e69f43345p+3836L }, + { 0x1.fbcc353d750f0c24p-6280L, -0xc.2cc3adaa5f76bd8p-8112L, 0x1.2a9e188779743a3ap-8096L, 0x1.2a9e188779743a3cp-8096L }, + { 0x5.1653c9d362cef54p-14708L, -0xb.c9870bb9c74469p+5028L, 0x2.a51ab90a18a8738cp+5044L, 0x2.a51ab90a18a8739p+5044L }, + { 0x7.36b4057f96e568dp+8176L, -0xf.f37001ee9d18068p-6500L, -0x1.fd9c420b6f4867fcp-6484L, -0x1.fd9c420b6f4867fap-6484L }, + { 0x1.f1d5273873448298p-7948L, -0xd.38eafd3878fe2f4p+14696L, 0x1.9a766fcad504a18cp+14712L, 0x1.9a766fcad504a18ep+14712L }, + { 0xe.2ad91bdabc94c8ap+4988L, 0x3.95448e4e9f0ea9ap-13040L, 0x4.5de17dc1f4a7fab8p-13028L, 0x4.5de17dc1f4a7facp-13028L }, + { 0x6.99d9f3e8p-16416L, -0x1.ad91e546b1cb6ebap-9228L, 0x6.b9599f96d124ec8p-9216L, 0x6.b9599f96d124ec88p-9216L }, + { 0x1.f5e39c6453df56cep+3976L, -0xd.82073d1dadfc559p-13696L, -0xd.1d89ef310c16451p-13684L, -0xd.1d89ef310c1645p-13684L }, + { 0xb.edb1abf0414bf32p+4928L, -0xd.e8fd8b2f5f7e274p-1624L, -0x1.0bf6d0071c8443aap-1608L, -0x1.0bf6d0071c8443a8p-1608L }, + { 0x2.4441537d38fcde3p-10736L, 0x6.d2a95499ed5d399p+8560L, -0x1.1e1a8f495e7a1a52p+8576L, -0x1.1e1a8f495e7a1a5p+8576L }, + { 0x8.350f634f3bac009p+8676L, -0x2.d48a8e03034cffdcp+14208L, -0x5.ff3c0112847868d8p+14220L, -0x5.ff3c0112847868dp+14220L }, + { 0x3.216932500e2c85ecp+14080L, -0x1.476cc48b95f9d5p-716L, -0x4.65a794c5d3743b58p-704L, -0x4.65a794c5d3743b5p-704L }, + { 0x2.db319188f62c89e8p+988L, 0xe.a63c4600dc01d8cp-424L, 0x3.89fbee2ba66bc188p-412L, 0x3.89fbee2ba66bc18cp-412L }, + { 0x6.6aaa7a664cf96818p-3528L, -0x7.5c73f3fe919f4e7p-888L, 0x6.55e60356eb25c59p-876L, 0x6.55e60356eb25c598p-876L }, + { 0x5.916df5368bba491p-3112L, -0x2.9cfe9de6a3ad4c88p+12520L, 0x1.fbdfdf6fbd783f8cp+12532L, 0x1.fbdfdf6fbd783f8ep+12532L }, + { 0x8.e258363c3897569p-6168L, -0x1.72e257e109bc36bap+2524L, 0x2.2e36cb7155364494p+2536L, 0x2.2e36cb7155364498p+2536L }, + { 0x4.488a31c8bf6dbcp-13868L, -0x2.d5e7d27c5355e4ap+6356L, 0x9.995b6c142be9f9fp+6368L, 0x9.995b6c142be9fap+6368L }, + { 0xc.5cffd705c24a0c2p-4L, -0x9.01d522cef5d12afp-4668L, 0x3.59cb3ebcfd0a1f08p-4668L, 0x3.59cb3ebcfd0a1f0cp-4668L }, + { 0xb.40f77e9360b0776p-8424L, -0x1.c31d691fcbc9a998p-8380L, 0x3.9f658593c3b5b0ap-8368L, 0x3.9f658593c3b5b0a4p-8368L }, + { 0x7.1c785eecfe17605p+12952L, 0x6.81abff3b56ebed6p-4116L, 0x1.4942fffbc4b683b8p-4100L, 0x1.4942fffbc4b683bap-4100L }, + { 0x7.8201396b65470528p-8188L, -0x3.463d9ddfcf13487cp-10432L, 0x6.8b114d5e19d248fp-10420L, 0x6.8b114d5e19d248f8p-10420L }, + { 0x7.70d516c2a2b3b3dp-4152L, -0x8.126b2caac3c5943p-4996L, 0x8.2d35b07156a52abp-4984L, 0x8.2d35b07156a52acp-4984L }, + { 0x3.cd97932b489ad858p+6780L, -0xf.c42863b5a2d0232p-12656L, -0x1.a1ad801137893564p-12640L, -0x1.a1ad801137893562p-12640L }, + { 0x1.9396ff2d623e5408p+14096L, 0x3.9d32507b559b865cp-1176L, 0xc.702020e071d0773p-1164L, 0xc.702020e071d0774p-1164L }, + { 0x1.ed679d88b04f7fap+6264L, -0x4.b3d263673481a9ep-12932L, -0x7.31477827f160e46p-12920L, -0x7.31477827f160e458p-12920L }, + { 0x1.eae89eef96814ca6p-1852L, 0x3.a339fc1c50b7b174p-4092L, -0x1.a4d6cc5ce493c0cep-4080L, -0x1.a4d6cc5ce493c0ccp-4080L }, + { 0x1.707c24b46d461048p-14368L, 0x2.56890e2696270f18p+3396L, -0x8.33791b84ac10fa8p+3408L, -0x8.33791b84ac10fa7p+3408L }, + { 0xa.f782f5eeaaf84b2p-8396L, 0x4.8ac0d484844b719p-12612L, -0x9.4e6fad33abacc8cp-12600L, -0x9.4e6fad33abacc8bp-12600L }, + { 0x6.75f9102p-16416L, 0x1.c215aac2787d684ep-6028L, -0x7.0b8f1e582b0f2ac8p-6016L, -0x7.0b8f1e582b0f2acp-6016L }, + { 0x1.8e028ccf9407e7b6p-10456L, 0x2.6587235c80541de4p-8072L, -0x6.1e140f05b8db7f18p-8060L, -0x6.1e140f05b8db7f1p-8060L }, + { 0x1.da364cbdabbc25dcp+3776L, -0x3.e477a90405bea618p+5096L, -0x3.96d5b3c2d4f9d27p+5108L, -0x3.96d5b3c2d4f9d26cp+5108L }, + { 0x4.8ccd46cc6510b538p-6440L, 0x3.68c9ba824b18c688p-14052L, -0x5.5bc9eef09da496f8p-14040L, -0x5.5bc9eef09da496fp-14040L }, + { 0x1.5523bc7caa2a7b4p-2360L, 0xf.e04552139a2f6a5p+7728L, -0x9.254eb8dbb10de6p+7740L, -0x9.254eb8dbb10de5fp+7740L }, + { 0x3.5e00cae7d345aa9cp-13704L, -0x5.e5c76fe79a2907cp+13180L, 0x1.3baa07aa98aaf93ep+13196L, 0x1.3baa07aa98aaf94p+13196L }, + { 0x6.d8686db27423ce58p+1772L, -0x1.dd67447223055ad4p+10804L, -0xc.edb3a82a0914dc7p+10812L, -0xc.edb3a82a0914dc6p+10812L }, + { 0x5.81ac23cc9814dc5p+8424L, -0x1.82aa76204a55d282p-6048L, -0x3.1b770e30bffad924p-6036L, -0x3.1b770e30bffad92p-6036L }, + { 0xc.6ab94dcea227508p-14696L, -0x7.9584757e89e7c55p-5412L, 0x1.b343ac0c30e5ed04p-5396L, 0x1.b343ac0c30e5ed06p-5396L }, + { 0x8.f16bb6cf2395a1bp+7192L, -0x1.1a54811d7af3bd8cp+7552L, -0x1.eff326c8340b378ap+7564L, -0x1.eff326c8340b3788p+7564L }, + { 0x3.ce0c67c37ccec814p-14228L, 0xa.955a451a8e75c69p-8560L, -0x2.4c2055cf200b6e7p-8544L, -0x2.4c2055cf200b6e6cp-8544L }, + { 0x6.a4757b88p-16416L, 0x1.e49fe1c472843028p-4008L, -0x7.95f6092fae66987p-3996L, -0x7.95f6092fae669868p-3996L }, + { 0xe.71c46c73262a925p+3408L, 0x6.65257962db253ac8p-8876L, 0x5.53b25e184835333p-8864L, 0x5.53b25e1848353338p-8864L }, + { 0x1.3780298260776f1ep+10420L, -0x1.11661cd09cc6ff86p-308L, -0x2.b787db272797c17cp-296L, -0x2.b787db272797c178p-296L }, + { 0x1.fa3248ab7314fcfep-2564L, -0x2.384d1920955542p+12332L, 0x1.639b53b49c911ccap+12344L, 0x1.639b53b49c911cccp+12344L }, + { 0x2.72eeaa978efe1234p-6844L, 0x5.9b815458ba3ed0ap-10020L, -0x9.5e216a1ccb17dd4p-10008L, -0x9.5e216a1ccb17dd3p-10008L }, + { 0x4.6b38b0944800a92p-3652L, 0x1.06c7deaa434edd72p+6760L, -0xe.a287f40f40e33c8p+6768L, -0xe.a287f40f40e33c7p+6768L }, + { 0xc.e16733773c8f71ep+7968L, 0x1.d1a8610ef9653c2cp+6540L, 0x3.8a44dbbe5691ada4p+6552L, 0x3.8a44dbbe5691ada8p+6552L }, + { 0x5.fb96128dcb851d9p+6848L, 0x2.b75c4b387bdde9e8p+6840L, 0x4.8afe7743710b6da8p+6852L, 0x4.8afe7743710b6dbp+6852L }, + { 0x3.f58649c18725aaa8p+480L, -0x1.df1ad5bab9cc8704p+5396L, -0x3.86096aedbe0ccf84p+5404L, -0x3.86096aedbe0ccf8p+5404L }, + { 0x3.8c7468635255c36cp-9848L, -0x1.2d4a9bc2537a65c2p+6172L, 0x2.d44278d5964e9308p+6184L, 0x2.d44278d5964e930cp+6184L }, + { 0x1.266933c47623dcf2p+1504L, 0x1.9f5956a11f8d8a1cp+4848L, 0x9.8880a23f0954318p+4856L, 0x9.8880a23f0954319p+4856L }, + { 0x7.ee162358p-16416L, -0x7.b20cc9e4d310231p-6740L, 0x1.ed6276e44234215ep-6724L, 0x1.ed6276e44234216p-6724L }, + { 0xd.a2dd238869b2787p-1832L, 0x1.a987e218c6f17582p-4964L, -0xb.def06e8887e84fcp-4956L, -0xb.def06e8887e84fbp-4956L }, + { 0x6.d06d1c60a261b25p+13856L, -0x5.9e57359c4cf1067p+13824L, -0x1.3029be4f0d001bb4p+13840L, -0x1.3029be4f0d001bb2p+13840L }, + { 0xf.5afa51a915c3c2cp-7724L, -0x5.399276f16adbba7p-8016L, 0x9.d90782db4be7b57p-8004L, 0x9.d90782db4be7b58p-8004L }, + { 0x1.37ae53977fcc991cp+11588L, 0xc.cf5f343691ea8ecp+3336L, 0x2.43de7490fbe55f28p+3352L, 0x2.43de7490fbe55f2cp+3352L }, + { 0xb.916f204d9b607e2p-9652L, -0x1.35296e508f235de2p+2664L, 0x2.d841a1731ad9bf24p+2676L, 0x2.d841a1731ad9bf28p+2676L }, + { 0x7.986b2cd7ddf22268p+8064L, -0x2.2a06bf374755863cp-5488L, -0x4.432291fb48046c6p-5476L, -0x4.432291fb48046c58p-5476L }, + { 0x6.37c853b0413d5448p-11920L, 0x7.ff7a53a9d88503bp-13652L, -0x1.745299d0aed002f4p-13636L, -0x1.745299d0aed002f2p-13636L }, + { 0x6.4c2eb46758106918p+14296L, 0x4.fbd427830e0b7d98p-8500L, 0x1.165c4a9036705c38p-8484L, 0x1.165c4a9036705c3ap-8484L }, + { 0x6.24db1d64d95cf55p-336L, 0x6.d057f880739cc278p+14360L, -0x8.df9aba4673d5941p+14368L, -0x8.df9aba4673d594p+14368L }, + { 0xb.1981c21be406601p-3972L, 0x2.029bd5f255e8a35p-10848L, -0x1.f297ef0c6b6837e8p-10836L, -0x1.f297ef0c6b6837e6p-10836L }, + { 0x6.74e6ebd8p-16416L, 0xb.151703cbe7e3038p+8672L, -0x2.c68a91d35a06273p+8688L, -0x2.c68a91d35a06272cp+8688L }, + { 0xa.37e2d7be2859c8bp-1596L, -0x1.c4a435d45ba8988ap+7536L, 0xb.000200ece72bb1cp+7544L, 0xb.000200ece72bb1dp+7544L }, + { 0x2.916b7b8ed46e92ccp-4368L, -0x3.037efdf978c84bfcp-8832L, 0x3.3678d0ccdadaeffp-8820L, 0x3.3678d0ccdadaeff4p-8820L }, + { 0x7.6c639e488208ccc8p-2160L, 0x3.a1d6c7b434bf3d98p-12244L, -0x1.e9b030a027bc75dp-12232L, -0x1.e9b030a027bc75cep-12232L }, + { 0x1.70d6044fbe0cb0d2p-8188L, -0x1.7afb318a61f2f0eap-536L, 0x2.f58b29b59e1cd59p-524L, 0x2.f58b29b59e1cd594p-524L }, + { 0x1.3e90b4eb0efaf5fap+7324L, -0x2.96cfd9fbb50bcd78p-1116L, -0x4.a1373950c6aeb928p-1104L, -0x4.a1373950c6aeb92p-1104L }, + { 0x4.6f9a694c1cfb65dp-8964L, -0x1.0df2b52efca96a9ep+1968L, 0x2.4ea226124824d4f4p+1980L, 0x2.4ea226124824d4f8p+1980L }, + { 0x1.d6566fbbd43703bcp-4852L, -0xa.f8b1cd8907eb113p+7616L, 0xc.fe7e9244b013f7bp+7628L, 0xc.fe7e9244b013f7cp+7628L }, + { 0x1.1a90813aa3baaae6p-3212L, 0x1.07b9974764beed82p-7712L, -0xc.ecc705b170e316ap-7704L, -0xc.ecc705b170e3169p-7704L }, + { 0x6.af86ac96f68ccc18p-5372L, -0x1.5877065aa0076e0ep+9668L, 0x1.c38b175b4ec73c6ep+9680L, 0x1.c38b175b4ec73c7p+9680L }, + { 0x5.0830fc79162b51p+732L, 0x7.a0e695df486975a8p-456L, 0x1.5e1dbcc4c6615ef2p-444L, 0x1.5e1dbcc4c6615ef4p-444L }, + { 0x4.1e9381b2498bde9p-4L, -0x5.318485c71566c348p-10692L, 0xa.2a99b81fbb45d58p-10692L, 0xa.2a99b81fbb45d59p-10692L }, + { 0x3.aa23634217ae0ec4p+8196L, -0xe.31f0ba646c8980ep-56L, -0x1.c69177d12e2f164p-40L, -0x1.c69177d12e2f163ep-40L }, + { 0x5.f1ebb70f25fab228p+148L, -0x1.5c7f22ee7bdcb97ap+12792L, -0xc.cf9b8c1bbde569fp+12796L, -0xc.cf9b8c1bbde569ep+12796L }, + { 0x6.64a485a65ba2bb8p-6848L, -0xb.ab5d793764e46aap-4044L, 0x1.3808c8a9a9457a22p-4028L, 0x1.3808c8a9a9457a24p-4028L }, + { 0x2.0c076822c45b5c2p+3820L, 0xc.6d1ace4fdfc0995p-11720L, 0xb.978e3acafba5dep-11708L, 0xb.978e3acafba5de1p-11708L }, + { 0x2.c4adada59c4f74cp+356L, 0x8.cb9c5966f2f6535p+664L, 0xc.481102c34516cep+672L, 0xc.481102c34516ce1p+672L }, + { 0x1.4690bd92b944f1e6p-1756L, 0x1.89dd6b86aed3c6ep-12820L, -0xa.8d20776fa7c107fp-12812L, -0xa.8d20776fa7c107ep-12812L }, + { 0x1.e645a04ffd7fcf32p+8988L, -0x7.4662a44eadea0868p+5320L, -0xf.f71eb1d0013d055p+5332L, -0xf.f71eb1d0013d054p+5332L }, + { 0x4.332914d9e18063ap-10904L, 0x2.c3783d61fd7041fcp+14952L, -0x7.5b010c3479470088p+14964L, -0x7.5b010c347947008p+14964L }, + { 0x7.8ea9558f03ae0e7p+3360L, -0x3.f7ba4222d04d157cp+7040L, -0x3.41f0065a9b4f0258p+7052L, -0x3.41f0065a9b4f0254p+7052L }, + { 0x4.16fc729b9ce4dc58p-12344L, 0x5.91be30b46d5b46d8p+8916L, -0x1.0c803996b4e5dd76p+8932L, -0x1.0c803996b4e5dd74p+8932L }, + { 0x1.9ff000dcf3194afap+0L, -0xb.402101043dda93fp+8464L, -0x7.e0bb855f276d611p+8464L, -0x7.e0bb855f276d6108p+8464L }, + { 0x3.c1bd5f7eaf2aefbcp-3452L, 0x3.5060ef99941b0558p-28L, -0x2.ca98723a104a705cp-16L, -0x2.ca98723a104a7058p-16L }, + { 0x7.40f69af37414a67p-4984L, 0x9.76424abbc94834ap+8128L, -0xb.81b4e09a2241edap+8140L, -0xb.81b4e09a2241ed9p+8140L }, + { 0x2.a7771004562ceed4p+14300L, 0x1.6959757c92243a3ap-3048L, 0x4.edabdfe0f6ebfd28p-3036L, 0x4.edabdfe0f6ebfd3p-3036L }, + { 0x3.5def153aa1e1859cp-12528L, 0x2.e3b7b35774e3683p-11336L, -0x8.d62de479ad0aa6p-11324L, -0x8.d62de479ad0aa5fp-11324L }, + { 0x3.60afa9401fa21cb4p+13964L, -0x3.918ec1969b0edd88p+1908L, -0xc.2adfb245bfe4ad7p+1920L, -0xc.2adfb245bfe4ad6p+1920L }, + { 0x1.dec8e34ee760457ap-3276L, -0xc.f9ac1534d437324p-4104L, 0xa.5ff4de0ac7cf5eap-4092L, 0xa.5ff4de0ac7cf5ebp-4092L }, + { 0x3.40a43e7617430e38p-6876L, -0x1.21e9e8c12fbb68ap+0L, 0x1.e68f95a0715b74ecp+12L, 0x1.e68f95a0715b74eep+12L }, + { 0x6.e391c60d69e57e48p+14204L, -0x3.ab05dd3dc0cb47fcp-5284L, -0xc.b8f4fe0c2d1d37dp-5272L, -0xc.b8f4fe0c2d1d37cp-5272L }, + { 0x4.7e30a9e329ebbe38p-3820L, -0x2.029c31080003b2e4p-2628L, 0x1.dfa972c247b7e80ep-2616L, 0x1.dfa972c247b7e81p-2616L }, + { 0x5.040eb8c257682f18p+12468L, -0x1.ee68d5b05c315f0ap-10428L, -0x5.e13c804f6f999478p-10416L, -0x5.e13c804f6f99947p-10416L }, + { 0x7.8e68dbe249d1df3p-4L, -0x1.9e8c3ea1db7772dep+1124L, 0x1.c0aca5bb6957525ep+1124L, 0x1.c0aca5bb6957526p+1124L }, + { 0x1.b84f160ab17a1622p+1796L, 0x4.b2842fc0d4e29f8p-12508L, 0x2.0f8142fc8078e574p-12496L, 0x2.0f8142fc8078e578p-12496L }, + { 0x1.f41344568040c1dap-11860L, 0x1.1c6472bb8005f37ep-6852L, -0x3.3764ada231d16af8p-6840L, -0x3.3764ada231d16af4p-6840L }, + { 0x3.e3036c02f7d4d658p-9528L, 0x5.36e056abcab2faa8p+1976L, -0xc.208372633388ae4p+1988L, -0xc.208372633388ae3p+1988L }, + { 0xe.d925cace25ab5fep+8480L, -0xd.6cb0532deaf2679p+944L, -0x1.bce4911c050e131p+960L, -0x1.bce4911c050e130ep+960L }, + { 0x6.19357550809e7c3p+5024L, 0x1.5c8533e5f3b94e6ap-10972L, 0x1.abb43335a7f7f332p-10960L, 0x1.abb43335a7f7f334p-10960L }, + { 0x3.b44cb94e53d800dp-8104L, -0x1.1ab0065a82bd87f4p-2844L, 0x2.2f2be3b82899a4e8p-2832L, 0x2.2f2be3b82899a4ecp-2832L }, + { 0x9.ea2a7bd17c460dep-8580L, -0x7.62ec913ffd564678p+2716L, 0xf.7770e8e86e4eb82p+2728L, 0xf.7770e8e86e4eb83p+2728L }, + { 0xf.c7a3dd4416649cep+6636L, 0x2.6182229406539e28p+13900L, 0x3.dc11331e9f68bf5cp+13912L, 0x3.dc11331e9f68bf6p+13912L }, + { 0xf.7fa93e24f531607p-1524L, 0x1.8f7cad2b63b6624ep-12276L, -0x9.44069d140a4f7c3p-12268L, -0x9.44069d140a4f7c2p-12268L }, + { 0x1.dc32628ac0052e3p+13788L, -0xa.e3c3bdecf1dec26p-868L, -0x2.4a8d02bd7a23b6acp-852L, -0x2.4a8d02bd7a23b6a8p-852L }, + { 0xe.2792f16a45f2666p-4L, 0x3.606aae6b641136ecp-14064L, -0x9.8d4b6f35e1bb5f7p-14068L, -0x9.8d4b6f35e1bb5f6p-14068L }, + { 0x2.3a3da2a76687889cp+7488L, 0x3.b7edc7ccbaa4e6f4p-4576L, 0x6.cc836f69a9a8fbfp-4564L, 0x6.cc836f69a9a8fbf8p-4564L }, + { 0x9.e81deac115960bcp-10784L, -0x1.edc841a680c41fa6p+904L, 0x5.13a322bc0411e47p+916L, 0x5.13a322bc0411e478p+916L }, + { 0x1.cd896fd12910f8fep+4612L, -0x5.53107666263a4058p-5612L, -0x5.ff0fb993b0e4c34p-5600L, -0x5.ff0fb993b0e4c338p-5600L }, + { 0x7.115b116b66f8aa4p+13264L, -0x7.5f2ae310973bd4d8p+14416L, -0x1.7e07aa45adacd32cp+14432L, -0x1.7e07aa45adacd32ap+14432L }, + { 0x1.74145e7c2770b4ccp+2828L, -0xa.ba6ad2740e752acp-2336L, -0x7.6891da714ff943c8p-2324L, -0x7.6891da714ff943cp-2324L }, + { 0x4.8b2545de86521b8p+13740L, -0x2.1340349dc88fe5ap+4092L, -0x6.f65c22f70b2c646p+4104L, -0x6.f65c22f70b2c6458p+4104L }, + { 0xc.52069130f81cabfp-1984L, -0x4.20c946d47a37871p+2084L, 0x1.fef232e25ad65e4p+2096L, 0x1.fef232e25ad65e42p+2096L }, + { 0x3.2b65b7eb1ee545c8p+7384L, 0x2.3f8fa6f81d92432cp-14436L, 0x4.0dd155add9d84d1p-14424L, 0x4.0dd155add9d84d18p-14424L }, + { 0x1.a1b184553cda78ap+14968L, -0x2.31c152f5ee281b54p-9292L, -0x8.04eac2f38cfa541p-9280L, -0x8.04eac2f38cfa54p-9280L }, + { 0x1.44f05224646c418ap-14972L, 0x1.2804d060de7d5e6ep+13432L, -0x4.3a013b476092fe2p+13444L, -0x4.3a013b476092fe18p+13444L }, + { 0x9.167509d85ac5562p-4L, -0x1.4b8f74471056531ep+12276L, 0x1.0e948448a0348196p+12276L, 0x1.0e948448a0348198p+12276L }, + { 0x7.ee687fee5c4ec2b8p+4644L, 0x6.79c1485cae87c43p-13504L, 0x7.58c0ee6ada14d12p-13492L, 0x7.58c0ee6ada14d128p-13492L }, + { 0x3.0cf623142a333c9cp+2336L, -0xe.a753d50ad228a17p+12460L, -0x8.5ce71421a143a5bp+12472L, -0x8.5ce71421a143a5ap+12472L }, + { 0x2.c8c9b971c2760cep-7672L, 0x3.932fbae80e38a998p-12916L, -0x6.b1db6613ef55474p-12904L, -0x6.b1db6613ef554738p-12904L }, + { 0x1.32026fb6bb0871ecp-13652L, -0x4.7b7e1412f0e7c018p+4912L, 0xe.f08781f91bd2a4dp+4924L, 0xe.f08781f91bd2a4ep+4924L }, + { 0x1.74dc31e3b9305bc4p-1120L, 0x3.84981c669a06975p+10008L, -0xf.6230ebdd8fed1ebp+10016L, -0xf.6230ebdd8fed1eap+10016L }, + { 0xb.ea47989bcd17ecap-872L, -0x3.a0466264269bfc0cp-616L, 0xc.4cf96b143aaed5p-608L, 0xc.4cf96b143aaed51p-608L }, + { 0x7.d01c7f119325b4f8p-1716L, -0xb.b3079d74457748ap-8232L, 0x4.e495c312907e048p-8220L, 0x4.e495c312907e0488p-8220L }, + { 0x1.d578671f39a6b79p+6516L, -0x3.dcbcd626648e35ap-8260L, -0x6.251d78436ccc76e8p-8248L, -0x6.251d78436ccc76ep-8248L }, + { 0x6.4d100f244be8113p+5240L, -0x8.8a2584d61c785a5p-1880L, -0xa.ee25d77822d6b9ap-1868L, -0xa.ee25d77822d6b99p-1868L }, + { 0x6.e4c6b8c4d0181df8p+11256L, -0xa.238f609952a68b5p+7056L, -0x1.bde7c574f5a56112p+7072L, -0x1.bde7c574f5a5611p+7072L }, + { 0x1.775823e9c3c2806cp+0L, 0x5.f466fe6cbdda3498p-3292L, 0x3.4993f3fbee8e12ap-3292L, 0x3.4993f3fbee8e12a4p-3292L }, + { 0x1.6ca0a0798fc630d8p-6296L, -0x1.5d03274c615fac7ep-9600L, 0x2.186d3767c5e0b77cp-9588L, 0x2.186d3767c5e0b78p-9588L }, + { 0x7.f1d06ee491613b4p+11796L, -0x2.99a7c87fc7c10564p-2268L, -0x7.7d7ed6d273782118p-2256L, -0x7.7d7ed6d27378211p-2256L }, + { 0x4.55b0bf0b43297a08p-688L, -0x5.4e7599ff8ce238d8p+5432L, 0xe.37a1a230f9d393cp+5440L, 0xe.37a1a230f9d393dp+5440L }, + { 0xf.ce25a67a67167e8p+5848L, 0xd.dae4961d9a359e9p-4336L, 0x1.3cb782addfad199ep-4320L, 0x1.3cb782addfad19ap-4320L }, + { 0x5.879a9e2ad0de4358p+1484L, 0x2.a7aa43ef734cca24p+9800L, 0xf.6a7be0d01960894p+9808L, 0xf.6a7be0d01960895p+9808L }, + { 0x1.8d57c92ab74b5dbp-9440L, 0xb.b6c4b8fea0b6709p-6916L, -0x1.afec2834b3ae434p-6900L, -0x1.afec2834b3ae433ep-6900L }, + { 0x5.6edc0af664d23e5p+10200L, 0x6.dee852c47ad7ae6p-9044L, 0x1.11d23f76b577fcfep-9028L, 0x1.11d23f76b577fdp-9028L }, + { 0x3.5d8dfaa5f4b3274p+11908L, -0xd.5dcf3b09be0346ep-12448L, -0x2.6dd7025c41524ea4p-12432L, -0x2.6dd7025c41524eap-12432L }, + { 0x7.ed91ce55062c3928p-11600L, -0x6.a15fc994e42a5f98p+13812L, 0x1.2c5c7661e2e3939cp+13828L, 0x1.2c5c7661e2e3939ep+13828L }, + { 0x1.dad7ecb371577f1p-14180L, -0x1.8d483b7d23140ad2p-3480L, 0x5.5f452e54f7efca4p-3468L, 0x5.5f452e54f7efca48p-3468L }, + { 0x7.2dc2a178p-16416L, 0xf.60597a6a11748cfp+11572L, -0x3.d9d6afdc9faabf58p+11588L, -0x3.d9d6afdc9faabf54p+11588L }, + { 0x7.ff05934f4c4c383p+6524L, 0x2.5b900e7df1a77c04p+8376L, 0x3.c1c7d76fd3351f88p+8388L, 0x3.c1c7d76fd3351f8cp+8388L }, + { 0x6.284c4489a8b3cf4p-12304L, -0x1.9ce08e5156bf999ap-956L, 0x4.d7fae0579e379fp-944L, 0x4.d7fae0579e379f08p-944L }, + { 0x3.7341a9ee603f834p-11216L, -0xe.74a4f05ef7fcf94p-10108L, 0x2.793ca67d11dad138p-10092L, 0x2.793ca67d11dad13cp-10092L }, + { 0xb.4c1201a91da1f7dp-2416L, -0x1.ff8b4a662492c844p+6384L, 0x1.2d4b53b5778f5e24p+6396L, 0x1.2d4b53b5778f5e26p+6396L }, + { 0xc.503b4e17876b4f8p+14420L, 0xd.d962de347f839ep+11944L, 0x3.0c4b1eff3371d3dcp+11960L, 0x3.0c4b1eff3371d3ep+11960L }, + { 0xf.ea4c84120426686p+8032L, 0x2.0ff0659d1aa2b36cp+13504L, 0x4.0bc5229ec619288p+13516L, 0x4.0bc5229ec6192888p+13516L }, + { 0xc.d03a3525d4adca1p-8912L, 0xf.76de125c2115ea5p+10412L, -0x2.1a212be6d70d0b54p+10428L, -0x2.1a212be6d70d0b5p+10428L }, + { 0x1.2c0b226e839776bap+10920L, -0xb.7b45dbebad44f9fp+13816L, -0x1.e9c4fd19de7db7ap+13832L, -0x1.e9c4fd19de7db79ep+13832L }, + { 0x1.7526248567fdebaep-840L, 0x8.687306d6b53f2b3p-9012L, -0x1.b922757bed236fdcp-9000L, -0x1.b922757bed236fdap-9000L }, + { 0x5.d5a66b8dfa047b5p-880L, 0x3.54d7284400eeb294p+3432L, -0xb.6b29715876e4f48p+3440L, -0xb.6b29715876e4f47p+3440L }, + { 0x1.37c211415835776cp+0L, -0x1.7bf2f1bdd872e7eep+1316L, -0x6.c0359c02dd59851p+1312L, -0x6.c0359c02dd598508p+1312L }, + { 0x5.9bf965c8495ee31p-1072L, 0xe.d2641494150a73fp+4012L, -0x3.dec2358e511f578cp+4024L, -0x3.dec2358e511f5788p+4024L }, + { 0xe.89eb0db23e82e32p-9840L, 0x8.530d8f2410e4187p+14152L, -0x1.3fd83369fbaaebfep+14168L, -0x1.3fd83369fbaaebfcp+14168L }, + { 0x1.a52fd5b0cedad4p-7932L, -0x1.44fe526e6036e7f8p-3256L, 0x2.754ce8f57959c7e8p-3244L, 0x2.754ce8f57959c7ecp-3244L }, + { 0x1.549a7733f640e13ep+12420L, 0x3.1188e7c0d95889dp-3832L, 0x9.4dff9a550c1eeb8p-3820L, 0x9.4dff9a550c1eeb9p-3820L }, + { 0x9.2e4d38476817c8dp-6436L, -0x4.abcedf3d024db5f8p-4444L, 0x7.5606bf1b0956cffp-4432L, 0x7.5606bf1b0956cff8p-4432L }, + { 0xb.f856641f8481196p+10672L, -0x8.d47787d0685534ap+1648L, -0x1.7038d6792aa77424p+1664L, -0x1.7038d6792aa77422p+1664L }, + { 0x1.69824482561454f8p+336L, 0x1.e0a9fb820963e05ap+3924L, 0x2.77ce6b1d230c7e5cp+3932L, 0x2.77ce6b1d230c7e6p+3932L }, + { 0x4.7b875bee3ace9d18p-4832L, 0x1.32f4fca22bdf9c8p-11912L, -0x1.69f37c67b419941cp-11900L, -0x1.69f37c67b419941ap-11900L }, + { 0x1.f1b6d7dd3acdec62p+1524L, 0x1.b0ec522ad44311ccp+8564L, 0xa.12de18c6f5ad5a6p+8572L, 0xa.12de18c6f5ad5a7p+8572L }, + { 0xa.077356a040b99f3p+10808L, 0x3.8f22e0e027753a1p-1952L, 0x9.64edf128ed9b026p-1940L, 0x9.64edf128ed9b027p-1940L }, + { 0xb.b5048a19c401aa4p-4L, 0x1.49cb7d1d22aa7e92p-11668L, -0x9.4a276cfbcb4689p-11672L, -0x9.4a276cfbcb4688fp-11672L }, + { 0x5.ac937fd967cce3cp+180L, 0x2.044831378114a9e4p-6504L, 0x1.700fbc6017636d7ep-6496L, 0x1.700fbc6017636d8p-6496L }, + { 0x6.5a8d06709c18fd3p-8212L, -0x3.bfed54c9016cfdf8p+564L, 0x7.83ea8701dcdca1c8p+576L, 0x7.83ea8701dcdca1dp+576L }, + { 0x1.22fb3728954b2facp+11140L, 0x2.a9bbdeb2bd533bdcp+4340L, 0x7.3e2913fd71866cap+4352L, 0x7.3e2913fd71866ca8p+4352L }, + { 0x1.a3d958faa346d6d4p-2564L, -0x7.2d5882b0a8455a8p-10740L, 0x4.7dd0b200bb918158p-10728L, 0x4.7dd0b200bb91816p-10728L }, + { 0x5.aae8c1b07b4255a8p-11416L, 0x1.a5322e33e663a032p+14936L, -0x4.95a97974b2d6be5p+14948L, -0x4.95a97974b2d6be48p+14948L }, + { 0x1.32b51a0ef6515e86p+11512L, -0x2.e5e11f37294c9f08p+6628L, -0x8.25224dfd2ae08ebp+6640L, -0x8.25224dfd2ae08eap+6640L }, + { 0x9.9f9641c28f1f3bp+3252L, -0x1.a299130160a73736p-13208L, -0x1.4cad7e3dd198472ep-13196L, -0x1.4cad7e3dd198472cp-13196L }, + { 0xa.14b3d5f6dc54435p+7340L, -0x5.9aded1ca64712fc8p+9680L, -0xa.0c71bdcb75c7ab2p+9692L, -0xa.0c71bdcb75c7ab1p+9692L }, + { 0x6.15b61d120f49268p+6220L, -0xf.7f9391555365de2p+5488L, -0x1.78b815d015e81898p+5504L, -0x1.78b815d015e81896p+5504L }, + { 0x1.4f2bc08178d6eb22p-8580L, 0xa.04e870f0bde69e8p+3968L, -0x1.4fc8994b94f2a114p+3984L, -0x1.4fc8994b94f2a112p+3984L }, + { 0x1.5a47ce0ae772d35p+0L, -0x1.2cdf2167efebf2a4p-10844L, -0x8.31e78a3e624db2bp-10848L, -0x8.31e78a3e624db2ap-10848L }, + { 0x6.f4cbf9587638df9p+5352L, 0x6.68a1cb4cc0d7c8cp-4056L, 0x8.60d658044a4bc4bp-4044L, 0x8.60d658044a4bc4cp-4044L }, + { 0x3.84a9333922f6ecb4p-9532L, 0x2.fc9ff16108dd5bd8p-1556L, -0x6.f30e7b39aef8555p-1544L, -0x6.f30e7b39aef85548p-1544L }, + { 0x4.73121c1ce9aa73dp-6892L, 0x5.84c4b307a865da78p+10880L, -0x9.4867ceb0d8c1681p+10892L, -0x9.4867ceb0d8c168p+10892L }, + { 0x1.904286dff6e1c742p+12660L, 0x1.a23ce96a1531b288p-9176L, 0x5.0cc39f45fb54f2a8p-9164L, 0x5.0cc39f45fb54f2bp-9164L }, + { 0xd.fc03b164930e19ap-4788L, -0x4.484bbdd4a58040c8p-12664L, 0x5.007dc60263b9e04p-12652L, 0x5.007dc60263b9e048p-12652L }, + { 0x3.cf945718ab43d7d8p-9660L, 0x9.75ee615c9605d82p+5592L, -0x1.64ebcc8679ceb56p+5608L, -0x1.64ebcc8679ceb55ep+5608L }, + { 0x6.133ee5675e302e6p+1264L, -0x2.ebb2e212bc306adp+4292L, -0xe.735d70c085412d7p+4300L, -0xe.735d70c085412d6p+4300L }, + { 0x1.6faa14baf33d3942p+5756L, 0x2.98fb801310e3d98p-4484L, 0x3.a69121c6a4586a9cp-4472L, 0x3.a69121c6a4586aap-4472L }, + { 0x1.8bf4374345aeebcap-352L, 0x3.433b152bfb0fcc0cp+8288L, -0x4.7a63b884113c79c8p+8296L, -0x4.7a63b884113c79cp+8296L }, + { 0xf.348c75a3c924d9dp-3128L, -0x6.d27f0cba9d98c128p-4724L, 0x5.34136c5b13a1832p-4712L, 0x5.34136c5b13a18328p-4712L }, + { 0x4.6cba404p-16416L, -0x3.b1c0ab60b7afe674p-14368L, 0xe.cde75bc3f6da7cdp-14356L, 0xe.cde75bc3f6da7cep-14356L }, + { 0x3.1b7118eb85377698p+6592L, -0x5.0267e29e12c8f49p-8896L, -0x8.106249044735cbfp-8884L, -0x8.106249044735cbep-8884L }, + { 0x3.607d3c87fbf0054cp-68L, -0x2.8420e2df1534abep+5568L, 0xa.6add61dff55ffbdp+5572L, 0xa.6add61dff55ffbep+5572L }, + { 0xa.4f75c3ab1754f75p-2464L, -0x2.32d6265dd6c5c31cp+9576L, 0x1.521e6ab64b73a75p+9588L, 0x1.521e6ab64b73a752p+9588L }, + { 0x4.bebcc7d8d84470bp-4920L, 0xc.7a576a4e9617a7ap-10204L, -0xe.fb33826c58f70a1p-10192L, -0xe.fb33826c58f70ap-10192L }, + { 0x1.be14cf99336dd968p-9392L, 0x4.439759bba9387e28p+1492L, -0x9.c6c56213fcb7fdcp+1504L, -0x9.c6c56213fcb7fdbp+1504L }, + { 0xd.ccc1903e13b59f8p-12068L, -0x6.037d29fedf54928p-12240L, 0x1.1b65b2ea6fa5deeap-12224L, 0x1.1b65b2ea6fa5deecp-12224L }, + { 0x8.ec0ef83d152f4acp-13700L, -0x1.390c57a14d17b9fp+14872L, 0x4.16d1c17c1224422p+14884L, 0x4.16d1c17c12244228p+14884L }, + { 0x2.0fb3544804b262fp+5160L, 0x3.b57463fce853545p-480L, 0x4.ac550d3435adb7d8p-468L, 0x4.ac550d3435adb7ep-468L }, + { 0x1.64d1c43e23cf40aep-10652L, 0x1.0fb4b45ff8885f8ep-12252L, -0x2.c2900d82132cfb08p-12240L, -0x2.c2900d82132cfb04p-12240L }, + { 0x1.4abc31acbc7bc518p+1336L, -0xc.c65e75c39561171p+11700L, -0x4.2aff57887c738d9p+11712L, -0x4.2aff57887c738d88p+11712L }, + { 0x1.2b2e1b630ba1b3b6p+0L, 0x1.eada4be47dcfc9f2p+3300L, 0x6.e60d5e6d365afda8p+3296L, 0x6.e60d5e6d365afdbp+3296L }, + { 0x2.c8c57e2508051b3p-3924L, 0x5.21d09f2ffed0044p-5412L, -0x4.ea2bce361f26c5ap-5400L, -0x4.ea2bce361f26c598p-5400L }, + { 0x4.fe1bd62b8bf75b7p-12596L, 0x2.69999b4a350849p+13480L, -0x7.6ae41382c2fb955p+13492L, -0x7.6ae41382c2fb9548p+13492L }, + { 0x1.94cbc2f130aac9fcp+14560L, 0x4.461d0bdbe3e5e6e8p-84L, 0xf.316874645a5d084p-72L, 0xf.316874645a5d085p-72L }, + { 0x6.00a84d432c73ad6p+14048L, -0x7.1439c231e1c871ap+5524L, -0x1.84882f27e22d69e8p+5540L, -0x1.84882f27e22d69e6p+5540L }, + { 0x1.504150487ac4b4e4p+10492L, 0x1.4aca4d52f53ae634p+14816L, 0x3.4f5bd5c26e4d5f5p+14828L, 0x3.4f5bd5c26e4d5f54p+14828L }, + { 0x1.818d6363460594dp+2580L, 0x5.4e4c228f75fecc6p-13880L, 0x3.57c39c1ba0acfc6cp-13868L, 0x3.57c39c1ba0acfc7p-13868L }, + { 0x7.b18970b8033e92d8p+5184L, 0x2.405b3b6f6bd5017cp+12636L, 0x2.d9dd8099a79debfp+12648L, 0x2.d9dd8099a79debf4p+12648L }, + { 0x1.55003f934a96adfep+7436L, 0x9.0c070751c7715e7p-13016L, 0x1.06cd1a244ad7ce72p-13000L, 0x1.06cd1a244ad7ce74p-13000L }, + { 0x8.f4ea2709aeb30cap-3688L, -0x9.90099934edea7dfp+9676L, 0x8.9a4cb3758de9216p+9688L, 0x8.9a4cb3758de9217p+9688L }, + { 0x3.5a44024ad8c0a6ap+9484L, -0x3.162144dafa472c6cp+8012L, -0x7.25d3b827636c377p+8024L, -0x7.25d3b827636c3768p+8024L }, + { 0x4.5f98d1p-16420L, 0x3.174b45b7a50513fp-10904L, -0xc.63b8389565e5a89p-10892L, -0xc.63b8389565e5a88p-10892L }, + { 0x3.5e780c7808c14d1cp+4008L, -0x1.58021e31ae37918ap-8496L, -0x1.50c3bf982d8bc07ep-8484L, -0x1.50c3bf982d8bc07cp-8484L }, + { 0x6.735ed2860eb877p-8864L, -0x5.c82ebf46ce67b208p-8940L, 0xc.823c5bf27f289adp-8928L, 0xc.823c5bf27f289aep-8928L }, + { 0x9.f58318f7cfc023dp-10580L, 0xe.e7cda687036f7d6p-3536L, -0x2.67d291ecbebf4044p-3520L, -0x2.67d291ecbebf404p-3520L }, + { 0x1.3385a0a2f5ddca66p-2148L, 0x3.95cfb0b45473c558p-8036L, -0x1.e140fd913d3cdd4ep-8024L, -0x1.e140fd913d3cdd4cp-8024L }, + { 0xe.947a2689d86b12ap-8256L, 0x2.ff7409072f025f1p+9544L, -0x6.0a2c739e5b996318p+9556L, -0x6.0a2c739e5b99631p+9556L }, + { 0x3.f3364f18a79b3b3cp-14488L, -0x3.6b2dcf47d1901574p+6084L, 0xc.172e20d1e6aa072p+6096L, 0xc.172e20d1e6aa073p+6096L }, + { 0x1.b974779bc6a1600ap+156L, -0x1.fef4cd2b528d3ed6p+4876L, -0x1.38eed99c599a6616p+4884L, -0x1.38eed99c599a6614p+4884L }, + { 0x1.5da19cb6935f4324p-12448L, 0x1.1242f349c776d3c6p-13804L, -0x3.4177c20b08c8a534p-13792L, -0x3.4177c20b08c8a53p-13792L }, + { 0x5.f6b443936fcdf7dp+8000L, 0x4.9faadefeeda4d958p-12968L, 0x9.08985174ac99b73p-12956L, 0x9.08985174ac99b74p-12956L }, + { 0x3.9761f885a890c5f8p-6896L, -0x1.fde18a33769c2a36p+13492L, 0x3.5a33efe387a603p+13504L, 0x3.5a33efe387a60304p+13504L }, + { 0x6.38ae5a4p-16416L, -0xa.2bd753c4bb7feadp+8856L, 0x2.8c207ce6520e07dcp+8872L, 0x2.8c207ce6520e07ep+8872L }, + { 0x1.ce5c78f45cf53052p-12668L, 0x2.d403d4610942405cp-15000L, -0x8.bf104029e978686p-14988L, -0x8.bf104029e978685p-14988L }, + { 0x3.83b4fdb7c30a8a24p+1780L, -0x7.47e990178bed20ep-10576L, -0x3.2ad37d867fd49f4p-10564L, -0x3.2ad37d867fd49f3cp-10564L }, + { 0x4.f47fb482316be128p+6760L, 0x1.e4ba4361308b87cap+8632L, 0x3.20435b40eefebe3cp+8644L, 0x3.20435b40eefebe4p+8644L }, + { 0x9.ecba992568fda9fp+11556L, 0x1.57a41871031f24a8p-14620L, 0x3.c9c9d2d431974ee8p-14608L, 0x3.c9c9d2d431974eecp-14608L }, + { 0x5.0527cf795fdf0218p+180L, -0x1.0ed493bb5c956a5p-14104L, -0xc.0e3e3338d3a0555p-14100L, -0xc.0e3e3338d3a0554p-14100L }, + { 0x1.9e25e3c9c45d2c4cp+10096L, 0xf.d72920ce880fef5p+7404L, 0x2.70c064489db2a254p+7420L, 0x2.70c064489db2a258p+7420L }, + { 0x3.14721fc3b04b8c5p-1656L, 0x1.9d71a05ab8af6f3ep-13688L, -0xa.6fd80e54131d7c3p-13680L, -0xa.6fd80e54131d7c2p-13680L }, + { 0x2.5ad78a50881512acp-12368L, -0x6.200f74ea14aea158p+9312L, 0x1.27e55933256dda96p+9328L, 0x1.27e55933256dda98p+9328L }, + { 0x1.bed98ef392f4ab94p-6416L, 0x3.2511f8a81a02ae5cp-6232L, -0x4.ece8b6a1658e5688p-6220L, -0x4.ece8b6a1658e568p-6220L }, + { 0x9.ca98394ded775ccp+9980L, 0x3.3e1f319d7fc3b93p+2928L, 0x7.e74746d926c576d8p+2940L, 0x7.e74746d926c576ep+2940L }, + { 0x1.b05b032ac011e5c8p+0L, -0x9.89c1d87ab9de711p+11612L, -0x7.36265c43bbe44028p+11612L, -0x7.36265c43bbe4402p+11612L }, + { 0x2.56b6d5ed6e125aap+14564L, -0xd.309c19e3c810c88p+4748L, -0x2.ee719b7b44bb0cb8p+4764L, -0x2.ee719b7b44bb0cb4p+4764L }, + { 0x3.5c49fed90523d454p+1364L, 0x3.2ccd51955a529d84p-3488L, 0x1.0f0434ad8333b286p-3476L, 0x1.0f0434ad8333b288p-3476L }, + { 0xa.8ae9762015aefb8p+7828L, -0x5.a7c6805416a56c7p-576L, -0xa.d0179929a88ed25p-564L, -0xa.d0179929a88ed24p-564L }, + { 0x4.7e2047add8b77fd8p+8844L, -0x1.9d9b7dbed96ad514p+14612L, -0x3.7d45842a9b0a778p+14624L, -0x3.7d45842a9b0a777cp+14624L }, + { 0x1.48bc20b93d87d39cp+7296L, 0x1.f1f4a3bcd62d6452p-13940L, 0x3.7706fe1a27bb84ecp-13928L, 0x3.7706fe1a27bb84fp-13928L }, + { 0x5.e20fed3aa8e5dbdp-4376L, 0x8.e74b97d10e54bb2p+5756L, -0x9.81af1001916f875p+5768L, -0x9.81af1001916f874p+5768L }, + { 0x7.fea63fbd3f40e548p-8500L, -0x8.7ccedf1a38c6b27p+8392L, 0x1.19b6906c783876a8p+8408L, 0x1.19b6906c783876aap+8408L }, + { 0x4.3aa8266ac6dd9848p-4228L, -0x1.d6194fbfe0bb4bfcp-13020L, 0x1.e50280f80b74003ep-13008L, 0x1.e50280f80b74004p-13008L }, + { 0x8.532cbb25dd9a1cp-1464L, 0xe.6973c478c36a38p-11684L, -0x5.23efdcaa87ca0d1p-11672L, -0x5.23efdcaa87ca0d08p-11672L }, + { 0x3.3872f03af739bf68p+1516L, 0x1.c137424956de4544p+12564L, 0xa.67293139ecd81bap+12572L, 0xa.67293139ecd81bbp+12572L }, + { 0x6.0af11c58p-16416L, 0x2.d7786a2a00cb9468p+12132L, -0xb.631a9a8ce1d6547p+12144L, -0xb.631a9a8ce1d6546p+12144L }, + { 0xb.0c8e827b71ff9ddp+11904L, -0x1.991e9c0fb5a8a95cp+4852L, -0x4.a55994b56a2c982p+4864L, -0x4.a55994b56a2c9818p+4864L }, + { 0x5.b2a2fc8e42885c78p-10700L, -0x1.081daf3c372a6146p-2316L, 0x2.b1ca1ae901cbbed4p-2304L, 0x2.b1ca1ae901cbbed8p-2304L }, + { 0x7.f81afe7f042b169p+3428L, 0x3.7991903d8fee1378p-8468L, 0x2.e9248ef40b9703a4p-8456L, 0x2.e9248ef40b9703a8p-8456L }, + { 0x1.053217463c55943ap-5192L, -0x1.80cc47c7e5f02abap+13832L, 0x1.e7c23e8549413a6ap+13844L, 0x1.e7c23e8549413a6cp+13844L }, + { 0xc.a34c4ecf5b0aaabp+8592L, 0x2.e10d47fb5277498p+812L, 0x6.0abd7203021fbcep+824L, 0x6.0abd7203021fbce8p+824L }, + { 0x1.9f351837670e8d28p-6308L, -0x8.befb20c310d5188p+7320L, 0xd.77bc9d6e05309cdp+7332L, 0xd.77bc9d6e05309cep+7332L }, + { 0x4.862a5be8bc9616c8p+9460L, -0x5.2e01d76fb0f858a8p-5552L, -0xb.f7363992738cdf4p-5540L, -0xb.f7363992738cdf3p-5540L }, + { 0x1.1fbaf0e92a32036cp+10360L, -0x3.532ad895dea863e4p+14340L, -0x8.68e3d68cfc8efbp+14352L, -0x8.68e3d68cfc8efafp+14352L }, + { 0x8.b1ffeda31e21d18p-820L, -0x8.d4c31482f8ed374p+856L, 0x1.c2df2c0489d2c7a6p+868L, 0x1.c2df2c0489d2c7a8p+868L }, + { 0x6.bf0de63f8aba85p-9024L, 0x2.245b98a003e208ep-9644L, -0x4.b7bb688e83688eep-9632L, -0x4.b7bb688e83688ed8p-9632L }, + { 0x5.530558a8p-16416L, 0x3.4e3e89e41c249f1cp-6384L, -0xd.3f170a5de7dc7fap-6372L, -0xd.3f170a5de7dc7f9p-6372L }, + { 0xc.fbcd0eea9797117p+8288L, 0x6.58f9c61c99d53948p-2080L, 0xc.d9810980cf5822dp-2068L, 0xc.d9810980cf5822ep-2068L }, + { 0x2.dd7a3619e921daa8p-7868L, 0x4.e1c4b9ed98971fdp-7296L, -0x9.60370599ec12297p-7284L, -0x9.60370599ec12296p-7284L }, + { 0x3.70ea41aa5607c17cp+11940L, -0x1.f54a8c18553ed762p+8868L, -0x5.b5806a96815e76d8p+8880L, -0x5.b5806a96815e76dp+8880L }, + { 0x6.29c88af64c1d2208p+9156L, -0x2.d8c0b8e7335ac6p+2464L, -0x6.5d7c4d973388c83p+2476L, -0x6.5d7c4d973388c828p+2476L }, + { 0x1.9218991c4bceca82p+3496L, -0x4.e5f71ea1e451644p-12488L, -0x4.2e7a78e719b0a1ep-12476L, -0x4.2e7a78e719b0a1d8p-12476L }, + { 0x2.be4f59cbceea3f8p-8768L, 0x9.21d471a6f899699p-11672L, -0x1.38b96068ba6bd08cp-11656L, -0x1.38b96068ba6bd08ap-11656L }, + { 0x9.ea26da61e1e9ee4p+10944L, 0x5.a81356ece0725948p+13688L, 0xf.1e3f343362aac9bp+13700L, 0xf.1e3f343362aac9cp+13700L }, + { 0x6.d6086c949b90754p+10336L, -0xe.400dcdc7097b86ap-2124L, -0x2.3f81b1fd4ef356ep-2108L, -0x2.3f81b1fd4ef356dcp-2108L }, + { 0x1.0350a9dede8123fap+7292L, -0x1.31c156f68fa864e2p+10212L, -0x2.20544d6074c3297p+10224L, -0x2.20544d6074c3296cp+10224L }, + { 0x3.539f1f79bb8d2b58p+1380L, -0x4.038559ede788f67p+10440L, -0x1.5a9f0a37b78786a2p+10452L, -0x1.5a9f0a37b78786ap+10452L }, + { 0x1.4652c37bddc46c36p+0L, -0x3.490ebc26b0621858p+3736L, -0x1.2680d02b02da8dfap+3736L, -0x1.2680d02b02da8df8p+3736L }, + { 0x1.1e2283f3e0d553d2p+11948L, 0x1.795f7455f6f5970ap+10872L, 0x4.4ccefa00fb8ddc7p+10884L, 0x4.4ccefa00fb8ddc78p+10884L }, + { 0x1.03d02412ea0fcd1ep-8536L, -0xa.5ad8a157b120ca8p+14164L, 0x1.5944eeb8cff41832p+14180L, 0x1.5944eeb8cff41834p+14180L }, + { 0x2.8e6b15a22d662794p-192L, 0x4.46b5ea7e4593773p+14680L, -0x3.2f3e1f7c0534dae8p+14688L, -0x3.2f3e1f7c0534dae4p+14688L }, + { 0xc.ec916ba1d9f3d7cp-6028L, -0x6.4925df5d8dba609p+9532L, 0x9.3eb32d1c6521b32p+9544L, 0x9.3eb32d1c6521b33p+9544L }, + { 0x8.df8a92908e3e2d5p+10460L, -0x1.35f423319cb099ecp-14232L, -0x3.17c537d732e96b68p-14220L, -0x3.17c537d732e96b64p-14220L }, + { 0xe.990e956e9d5098cp-10900L, 0x8.6c02663c1fa029ap-11932L, -0x1.667643641596bc48p-11916L, -0x1.667643641596bc46p-11916L }, + { 0xf.0b38b18a81a2e75p-9264L, 0x5.807d83c8ec8ff568p+13408L, -0xc.7043951c1e543f3p+13420L, -0xc.7043951c1e543f2p+13420L }, + { 0x1.e65c8504b82ec6a2p+14584L, -0x6.9bd91d1f5f5a1338p+12052L, -0x1.78849727fbcb985cp+12068L, -0x1.78849727fbcb985ap+12068L }, + { 0xf.1b596643482a518p+13788L, -0x5.d188e3656b87e14p-1564L, -0x1.3978336aa69399ap-1548L, -0x1.3978336aa693999ep-1548L }, + { 0xc.57817a1978c4d96p-8384L, 0x1.7bc496e53462329ep+5112L, -0x3.090057635b92403p+5124L, -0x3.090057635b92402cp+5124L }, + { 0x1.acfc662b3c39eebcp+0L, 0x4.11c79de36b71e45p+8412L, 0x3.07e74dd05087436p+8412L, 0x3.07e74dd050874364p+8412L }, + { 0x1.e9ead1df706b14a2p-6468L, -0x5.98f7597ee100d5d8p+14880L, 0x8.d678b9ee0d151bap+14892L, 0x8.d678b9ee0d151bbp+14892L }, + { 0x6.433a12950afdf158p-1436L, -0x1.98718075dc660c0ap-304L, 0x8.eee39f155669ff3p-296L, 0x8.eee39f155669ff4p-296L }, + { 0x4.449bca5d7a1edddp-8936L, -0x1.0bea9b7e8ad6b81ap+8672L, 0x2.485c45d7b9b8dd2cp+8684L, 0x2.485c45d7b9b8dd3p+8684L }, + { 0x1.f2325cb37958cfa4p-7568L, 0x3.71de7698fe1de088p+10488L, -0x6.5d2f178d80f3e77p+10500L, -0x6.5d2f178d80f3e768p+10500L }, + { 0x4.3b8744dd0317419p-2872L, 0x1.9f85eb8234b6ee9cp-9052L, -0x1.232457e89b7f36ap-9040L, -0x1.232457e89b7f369ep-9040L }, + { 0x2.82d91c368563b43p+520L, 0xf.74f8978fb20a3c3p-3316L, 0x1.f7a2121c656ba95ep-3304L, 0x1.f7a2121c656ba96p-3304L }, + { 0x5.e796e1cfc9288b08p-6856L, 0x1.e7549a99b10b7a6cp+2624L, -0x3.2f671549d02c643cp+2636L, -0x3.2f671549d02c6438p+2636L }, + { 0x6.e056753a5860b3b8p-12668L, 0x3.f7ba2b85ca9670e4p+1420L, -0xc.44b971f65cd0ba4p+1432L, -0xc.44b971f65cd0ba3p+1432L }, + { 0x7.dab816b779cd0b28p+6964L, -0x2.6b4a99eb6919b3e4p+8040L, -0x4.1d5dad8f69d2d4fp+8052L, -0x4.1d5dad8f69d2d4e8p+8052L }, + { 0x2.768c2ccae5a41844p-14664L, 0x2.2bd7f0960ffa1d4cp+11764L, -0x7.c5c9672b404b585p+11776L, -0x7.c5c9672b404b5848p+11776L }, + { 0x1.4214ceb4f8b26f84p+0L, 0x1.aeee948823e94fdp-3348L, 0x8.ec272fe563e96d8p-3352L, 0x8.ec272fe563e96d9p-3352L }, + { 0xf.22fae2a1fe73d63p+12048L, -0xc.6919a02e29e222ap+10216L, -0x2.4842ec282586fd2p+10232L, -0x2.4842ec282586fd1cp+10232L }, + { 0xf.2d33cefe0c45e86p+4200L, -0x2.b6a0e50f22f86cf8p-13716L, -0x2.c8ee53eb4bc41c2p-13704L, -0x2.c8ee53eb4bc41c1cp-13704L }, + { 0xa.77239ea21ede3cap+14536L, -0x1.b2d35d2a6452f9c2p-6280L, -0x6.077b280d797de588p-6268L, -0x6.077b280d797de58p-6268L }, + { 0xb.0b452f4738e9ba3p+1988L, 0xb.054b19e6e2203d5p+12200L, 0x5.5bb4b8962241e958p+12212L, 0x5.5bb4b8962241e96p+12212L }, + { 0x1.2b4c1f63d0b618bcp-1124L, 0xa.0d829b5cf72e0d7p-2276L, -0x2.c210d48e5f1921p-2264L, -0x2.c210d48e5f1920fcp-2264L }, + { 0x1.277fb450f434ba56p-5832L, 0x3.12f29b90db4ce928p+12224L, -0x4.60704004db7e2cb8p+12236L, -0x4.60704004db7e2cbp+12236L }, + { 0x3.70f6435c48a390ep-13484L, -0x2.ed8098445a35e71cp+14560L, 0x9.a307903a581ace3p+14572L, 0x9.a307903a581ace4p+14572L }, + { 0x1.c3c2896f8e2c3c2cp-1344L, 0x2.e80154ad5d5bfe34p+12880L, -0xf.3fa556e4f615bd4p+12888L, -0xf.3fa556e4f615bd3p+12888L }, + { 0x7.55b2ffccf81fa4b8p+7264L, -0x7.898636ae4e2f4d18p+13220L, -0xd.5f3eb3613345c3bp+13232L, -0xd.5f3eb3613345c3ap+13232L }, + { 0x4.12a3f2a71216bef8p+9288L, -0x4.fc64f774546e7168p+508L, -0xb.4ef49340f384ccfp+520L, -0xb.4ef49340f384ccep+520L }, + { 0x1.78262e13ab821e2p+0L, 0x1.80928281b3ac1d92p-2440L, 0xd.57fe1c2ddca1d6bp-2444L, 0xd.57fe1c2ddca1d6cp-2444L }, + { 0xf.215dcf89bd7792ap-13144L, -0xb.2d7f53d1195baf3p-13236L, 0x2.3dbc323174b49ab8p-13220L, 0x2.3dbc323174b49abcp-13220L }, + { 0x1.daac07c45ff52192p-13804L, -0x6.e2ed9d399f6c20a8p-7344L, 0x1.734e42351476817ap-7328L, 0x1.734e42351476817cp-7328L }, + { 0x6.775c2f8ce5a4a958p-12628L, -0x1.faa26ace0fb72f9ap-13992L, 0x6.199ff67cf30c524p-13980L, 0x6.199ff67cf30c5248p-13980L }, + { 0x1.4b67a4bdb9c98152p-5500L, -0x6.aab152bd7aff0f4p-116L, 0x8.f38be04d7e34735p-104L, 0x8.f38be04d7e34736p-104L }, + { 0x1.b93aed734b7a822ap-10328L, -0x6.f21ba81d936c2638p+9052L, 0x1.183217455957ceaep+9068L, 0x1.183217455957cebp+9068L }, + { 0x6.7701481d120c1b6p+8820L, -0x1.a8ad4a5048b28454p-13072L, -0x3.92be9e2abf346cbcp-13060L, -0x3.92be9e2abf346cb8p-13060L }, + { 0xd.606d27e348943bep+8040L, -0x3.c4aee51dff57549cp+6940L, -0x7.6672e4ca1236dbf8p+6952L, -0x7.6672e4ca1236dbfp+6952L }, + { 0x8.9aaf44bff92900ap+13008L, 0xe.c1faf84f1f451c8p-796L, 0x2.ee0e7337eb6ae698p-780L, 0x2.ee0e7337eb6ae69cp-780L }, + { 0xe.4770dc927d5eba1p+14740L, -0x4.73f832df7f78bec8p-156L, -0x1.0076638bc9f51726p-140L, -0x1.0076638bc9f51724p-140L }, + { 0x2.4ee6fe7f8bfa4f84p-1868L, -0x3.c61bfddaa521f2dp+8756L, 0x1.b85065fb85524aa2p+8768L, 0x1.b85065fb85524aa4p+8768L }, + { 0x2.d971898p-16416L, 0x1.5638b03330502364p-13028L, -0x5.5b6ee288b3cddcb8p-13016L, -0x5.5b6ee288b3cddcbp-13016L }, + { 0x3.185dd7d25a7b23f8p-13364L, 0xb.908cd56ce51db8fp-11836L, -0x2.5ba31e30c31c3dbcp-11820L, -0x2.5ba31e30c31c3db8p-11820L }, + { 0x3.a9a51c7cd1a62094p-12044L, -0x2.00963f0465d54a3cp-3104L, 0x5.e2fdc96e2c6a383p-3092L, 0x5.e2fdc96e2c6a3838p-3092L }, + { 0x9.7bae07b48f3d186p-13524L, 0x3.7eab03f7d9fc9158p+12752L, -0xb.8944ae7feb4dfc1p+12764L, -0xb.8944ae7feb4dfcp+12764L }, + { 0x2.974394b3d7b2078p+4088L, 0xb.3d5a0ceef37dac4p-6224L, 0xb.38b25dccc5a2166p-6212L, 0xb.38b25dccc5a2167p-6212L }, + { 0x5.3df9deaca20b2af8p-11080L, -0x5.4e765875989e9d8p-12400L, 0xe.59f433942d6ed78p-12388L, 0xe.59f433942d6ed79p-12388L }, + { 0x9.a7432a90d8d0bdbp+3312L, -0xd.a5c8e96c062ac37p-13004L, -0xb.0bd7b947d5a7d5bp-12992L, -0xb.0bd7b947d5a7d5ap-12992L }, + { 0xa.5245ba426d8cb8dp-8052L, 0x3.d8775bbd6cd0492cp-14992L, -0x7.8e796f0d9e08e8f8p-14980L, -0x7.8e796f0d9e08e8fp-14980L }, + { 0x2.71263b8c47253e1cp+8804L, -0x1.1047e1aacc267022p+14756L, -0x2.49546c369bf44644p+14768L, -0x2.49546c369bf4464p+14768L }, + { 0xb.7bbc2a109b78a97p-12480L, -0x3.10f36db5217d4878p-2108L, 0x9.56f8ef5d208aaa8p-2096L, 0x9.56f8ef5d208aaa9p-2096L }, + { 0x3.43e23acc2678bfecp-14844L, -0x9.ba704ceece1ba4fp-10368L, 0x2.3405ec1a1d6af318p-10352L, 0x2.3405ec1a1d6af31cp-10352L }, + { 0x5.447d50515731259p-4L, -0x3.8b954314786b23ap-2376L, 0x5.aebd2b28bf0b051p-2376L, 0x5.aebd2b28bf0b0518p-2376L }, + { 0x1.53ad8155928be6a4p-2032L, 0x1.a4ce39e0a6fe0442p+6936L, -0xd.0b7938a1f47f704p+6944L, -0xd.0b7938a1f47f703p+6944L }, + { 0x4.d16dd659f3c0f0ap-11256L, -0xd.fd723f0edb1d50fp+8416L, 0x2.66fffae75fb38a2cp+8432L, 0x2.66fffae75fb38a3p+8432L }, + { 0x1.103dfac7cd7c39e4p-5592L, -0x7.de07d07c42e504c8p+3860L, 0xa.bd947f52d4fff55p+3872L, 0xa.bd947f52d4fff56p+3872L }, + { 0x5.7c08324a140957ap+6828L, -0x1.3b6c02589b9259fcp+7784L, -0x2.0dfeb4804581daep+7796L, -0x2.0dfeb4804581dadcp+7796L }, + { 0x6.6f91a8945bb1196p+14828L, 0x6.57abdcaa9f822a78p+2452L, 0x1.6f6f1ff2fef76764p+2468L, 0x1.6f6f1ff2fef76766p+2468L }, + { 0x4.0dbdac43c89f5fa8p-8876L, 0x2.d4d64652d10516ecp+9408L, -0x6.225bdb14e1f214b8p+9420L, -0x6.225bdb14e1f214bp+9420L }, + { 0x6.04e85f85770e42f8p+11628L, -0x1.68a03c17c2b3a2d4p+9568L, -0x3.ffff406c0bdc55f4p+9580L, -0x3.ffff406c0bdc55fp+9580L }, + { 0x1.fac44e7ef22a75e2p-6660L, 0x1.53007eaa586c5ed2p-11556L, -0x2.2720ae514ec9e31p-11544L, -0x2.2720ae514ec9e30cp-11544L }, + { 0x1.c1af05b36c1e1314p-7544L, -0x1.db24c1b166e6b918p-11396L, 0x3.6b060fd951632d28p-11384L, 0x3.6b060fd951632d2cp-11384L }, + { 0x1.19427dcda0480416p-100L, 0x1.c36218d9ea12b06p-11836L, -0xb.0150a2cc8ed4846p-11832L, -0xb.0150a2cc8ed4845p-11832L }, + { 0x1.99c57945979570cp+0L, -0x3.9a147b2294cce81cp+7488L, -0x2.71cb044a663ad638p+7488L, -0x2.71cb044a663ad634p+7488L }, + { 0x8.35964c3a9d13241p-14272L, 0x1.cb6b91a0ad1a1b26p+11236L, -0x6.4073995695e99f88p+11248L, -0x6.4073995695e99f8p+11248L }, + { 0x1.4ec5569f83ab5736p-11296L, -0x3.8f33377c31308a44p-3004L, 0x9.d0d5346d7f8775ap-2992L, 0x9.d0d5346d7f8775bp-2992L }, + { 0xa.e64af69cc0c9a02p+452L, -0xe.30ae8ff9c10b4e2p-11172L, -0x1.93edb29bc02715cap-11160L, -0x1.93edb29bc02715c8p-11160L }, + { 0x1.f57725c0787861ecp+8460L, -0x1.8d1cb508a9ab2afp-4984L, -0x3.344d1e223db10d48p-4972L, -0x3.344d1e223db10d44p-4972L }, + { 0xe.3fac9734bbe71dfp+1164L, 0x1.2206e0f0b72822fcp+7496L, 0x5.2b0ee153f0bcf8a8p+7504L, 0x5.2b0ee153f0bcf8bp+7504L }, + { 0x2.a47e35e1ebe00cap-12464L, -0xd.d1efe43682ae912p+4124L, 0x2.a0c9efc557e73a04p+4140L, 0x2.a0c9efc557e73a08p+4140L }, + { 0xd.4a29b6e571f7f4dp+10012L, -0x9.5dd68d90c07dd66p+12464L, -0x1.6e74e8550fd34c12p+12480L, -0x1.6e74e8550fd34c1p+12480L }, + { 0x5.c36184a826a997c8p-14612L, 0xd.f4b5749411edfbp-3724L, -0x3.1c70415b25d650c8p-3708L, -0x3.1c70415b25d650c4p-3708L }, + { 0x1.fec2d25986d2c82ep+1752L, -0x1.c57eae44abd4be9ep-12468L, -0xc.215ee188c77742cp-12460L, -0xc.215ee188c77742bp-12460L }, + { 0xc.54dfb245063a9b5p+736L, 0xf.10e4c2279861992p-10604L, 0x2.b872c2568d3b19d4p-10592L, 0x2.b872c2568d3b19d8p-10592L }, + { 0x7.2511d87p-16416L, -0x1.8e6f895a46c46376p-3516L, 0x6.3c945f5d473002ep-3504L, 0x6.3c945f5d473002e8p-3504L }, + { 0x5.ab74bda0e9f7dc48p-11284L, -0x3.85da52552263bf3cp+188L, 0x9.b3f299cce4fce6ap+200L, 0x9.b3f299cce4fce6bp+200L }, + { 0x6.f8e5e146df8b2df8p+4628L, -0x6.801cd00cd5c87f7p-14356L, -0x7.5963f19aebc7d238p-14344L, -0x7.5963f19aebc7d23p-14344L }, + { 0x6.af69ebfdc141d71p+6980L, 0xc.78d6cd9d8fb34ebp-14544L, 0x1.5430f03a79108192p-14528L, 0x1.5430f03a79108194p-14528L }, + { 0x2.d62679fc1dcc84f8p+3140L, 0x5.fdcf1e255c31878p+1624L, 0x4.9862377e4c9b3cp+1636L, 0x4.9862377e4c9b3c08p+1636L }, + { 0x7.f8395e79564ebaap+60L, -0xf.6848263df1e17f7p+10516L, -0x3.ca941be39f8c20acp+10524L, -0x3.ca941be39f8c20a8p+10524L }, + { 0x1.8c3ff1590baa159ap-8448L, -0x2.d6a2d6b9cdaf1e5cp+5536L, 0x5.da933b48b3f2c5b8p+5548L, 0x5.da933b48b3f2c5cp+5548L }, + { 0xf.7679533e38c76d9p-13512L, -0x2.9e835f5c8364ae6cp+5928L, 0x8.a342cfd4ceeb772p+5940L, 0x8.a342cfd4ceeb773p+5940L }, + { 0xb.faf082b54ef2606p-14972L, 0x1.f3c6efc2e5ffb4e6p-7316L, -0x7.226282ff9956c7c8p-7304L, -0x7.226282ff9956c7cp-7304L }, + { 0x5.bfaf79aef43b597p-6912L, -0xf.1209a1e9d495726p+14776L, 0x1.96c0fd44f325c3fp+14792L, 0x1.96c0fd44f325c3f2p+14792L }, + { 0xf.55e7c12943cd9e3p-6360L, 0x1.30338ac91f40e2b2p-2200L, -0x1.d80d24f04b5e17bep-2188L, -0x1.d80d24f04b5e17bcp-2188L }, + { 0x2.0170ec08p-16416L, 0x3.f9d950af555b34d8p+1520L, -0xf.ef1915c00213218p+1532L, -0xf.ef1915c00213217p+1532L }, + { 0x9.438df09cbbeb10bp+11920L, -0x1.f49d11dbf4152fd8p-8844L, -0x5.b1419570741079ep-8832L, -0x5.b1419570741079d8p-8832L }, + { 0x1.39b9c285df388998p+13596L, -0xc.9214ffa074b0b5fp-10512L, -0x2.9ba203464a83d634p-10496L, -0x2.9ba203464a83d63p-10496L }, + { 0xa.5f724f2608e28b2p-4708L, 0x1.dd92386080291574p+13984L, -0x2.248896740c8620e8p+13996L, -0x2.248896740c8620e4p+13996L }, + { 0x1.2fcd33518ffb63f6p+5836L, 0xf.6172d7a361a0172p-956L, 0x1.5ea55289ffeab622p-940L, 0x1.5ea55289ffeab624p-940L }, + { 0xc.a8dc2de30b15b92p+5508L, -0x4.bbe0b101ef388428p+11952L, -0x6.5eba477cb699702p+11964L, -0x6.5eba477cb6997018p+11964L }, + { 0x2.5589af74b36b200cp+2652L, 0x1.2df972a1d9a4979p+13440L, 0xc.39b5674995e5924p+13448L, 0xc.39b5674995e5925p+13448L }, + { 0x2.6e39319255f2e85cp-12576L, -0x8.6765d8ee23089b3p+13476L, 0x1.9ccca6b0cc048174p+13492L, 0x1.9ccca6b0cc048176p+13492L }, + { 0xf.d8fad8e98f71b18p+11084L, -0xd.1751bb0b57d5a64p-8428L, -0x2.3701d5ad9aede528p-8412L, -0x2.3701d5ad9aede524p-8412L }, + { 0x1.f20b5ada21c997a6p+2796L, -0x7.4f3d7f0f8057c7fp+216L, -0x4.fdc784a368328628p+228L, -0x4.fdc784a36832862p+228L }, + { 0x2.ec355c67c4fad788p-11308L, -0x1.8877194d22dc426ep+12004L, 0x4.3b58d8f089f7b7d8p+12016L, 0x4.3b58d8f089f7b7ep+12016L }, + { 0x6.10df3f08p-16416L, 0x3.817942a0a769381cp-14720L, -0xe.0c561bbd87a62c2p-14708L, -0xe.0c561bbd87a62c1p-14708L }, + { 0x6.bd0fe1dc836eadfp-2136L, -0x6.f44c3fc5e9f0dcdp-9768L, 0x3.9f3380dc7a30e2d4p-9756L, 0x3.9f3380dc7a30e2d8p-9756L }, + { 0x1.dc7ec24162fe6b86p+6416L, 0xa.d904450a87c914dp+6880L, 0x1.0fe8b419324e5f7cp+6896L, 0x1.0fe8b419324e5f7ep+6896L }, + { 0x2.1154e9b7d8bc947cp+14296L, 0x2.8005335ce62297e4p-2280L, 0x8.b9fc12eb0b97e15p-2268L, 0x8.b9fc12eb0b97e16p-2268L }, + { 0x2.74ac5ca14051d8c8p+11348L, 0x7.0dbe8b515344edd8p-11768L, 0x1.38b667035b5453eap-11752L, 0x1.38b667035b5453ecp-11752L }, + { 0x7.1de5eb4d52288bd8p+5288L, 0x1.574c4b79e115507cp+12240L, 0x1.bb70beb675fd9e3ep+12252L, 0x1.bb70beb675fd9e4p+12252L }, + { 0xe.94dc072f915b9d6p-9840L, -0x1.33686966e730be5cp-8980L, 0x2.e2358dde81d0fe6cp-8968L, 0x2.e2358dde81d0fe7p-8968L }, + { 0x1.7c62423d8dcc70ap+12720L, 0x6.caa1f4e928c8b418p-12892L, 0x1.51783086464f7fbcp-12876L, 0x1.51783086464f7fbep-12876L }, + { 0x2.fd1e13da6acdd0bcp+11408L, -0x5.a5a7ab4fcb0ebe2p+11256L, -0xf.baeeb396d2b0e9p+11268L, -0xf.baeeb396d2b0e8fp+11268L }, + { 0x1.0405975065fa257ep-7100L, -0x3.fdf6965a0a7ce894p+14952L, 0x6.eb76bf6483135628p+14964L, 0x6.eb76bf648313563p+14964L }, + { 0x1.7989128da5ed012p-9088L, 0x2.fc6d5635215dc184p-3920L, -0x6.9ff7d0476617d7fp-3908L, -0x6.9ff7d0476617d7e8p-3908L }, + { 0xd.055219222b15826p-4L, 0x2.edc4531e12e7a84p+8956L, -0xd.edf55a814a9b1a7p+8952L, -0xd.edf55a814a9b1a6p+8952L }, + { 0x7.5b088224bb277808p-7200L, -0x5.6b6879b6303a20bp+372L, 0x9.85d403deb866612p+384L, 0x9.85d403deb866613p+384L }, + { 0x7.03716987879c6018p-10492L, 0x1.adc33e4dc78313c6p-328L, -0x4.4c8d63dc02372a48p-316L, -0x4.4c8d63dc02372a4p-316L }, + { 0x1.da61b2ff79d0db24p+264L, 0x1.2e8b11af94cc68b2p+2376L, 0x1.390ca6484829684cp+2384L, 0x1.390ca6484829684ep+2384L }, + { 0xa.f1f3b5f8ea8a2b6p+7968L, 0x1.904871e14600c2bcp-7332L, 0x3.0b034b594dda06ap-7320L, 0x3.0b034b594dda06a4p-7320L }, + { 0x3.6ae487af5a263c4p+14132L, 0x1.ae943bae4789d33ap-2168L, 0x5.cdc4a551070f1538p-2156L, 0x5.cdc4a551070f154p-2156L }, + { 0x2.91609a622daf31e4p-4876L, 0x2.dc7407749b13934cp+1904L, -0x3.67b0d6eb6b3bdf74p+1916L, -0x3.67b0d6eb6b3bdf7p+1916L }, + { 0x1.d99d97dab08ea934p+12696L, -0xd.6727a80c183e2d2p-1688L, -0x2.98bfbc1c6bf749a8p-1672L, -0x2.98bfbc1c6bf749a4p-1672L }, + { 0x1.a88e6202e69d3e36p-8164L, -0x3.3b8ff738d5bcfedcp+12568L, 0x6.7151f311b8f003b8p+12580L, 0x6.7151f311b8f003cp+12580L }, + { 0x3.9da48fd55e06d82p-2016L, 0x9.75441492e92e938p-11520L, -0x4.a69ee59d49e6ac78p-11508L, -0x4.a69ee59d49e6ac7p-11508L }, + { 0x6.e4b00b3b240142e8p+10764L, 0x6.e51718f6edc8117p+11268L, 0x1.21fbbb4d7e6a6ebep+11284L, 0x1.21fbbb4d7e6a6ecp+11284L }, + { 0x4.b95f1008p-16416L, 0x7.908b2d72dd961268p-4568L, -0x1.e503ead22ff73dbcp-4552L, -0x1.e503ead22ff73dbap-4552L }, + { 0x1.66c1bb97ab0ddaf2p-14964L, 0x2.5463a5ef35f229f8p-56L, -0x8.82bae6360805bacp-44L, -0x8.82bae6360805babp-44L }, + { 0x2.3637d76bb2135d3p-9636L, -0xb.7a932240c1b4016p-14796L, 0x1.b004a4e92f670be6p-14780L, 0x1.b004a4e92f670be8p-14780L }, + { 0x4.cf778309532b4ebp-1072L, 0xd.a187d193099d32p+14532L, -0x3.8f584e61aa9fd4f8p+14544L, -0x3.8f584e61aa9fd4f4p+14544L }, + { 0x6.6073bd067abac2c8p+11092L, -0x2.20b8ef4823854164p+13672L, -0x5.c377cd23914a472p+13684L, -0x5.c377cd23914a4718p+13684L }, + { 0x6.6c2bf697eaadaa5p+5628L, 0x2.3ba43ace18fc3068p-6200L, 0x3.11d2c48e39fe1bdcp-6188L, 0x3.11d2c48e39fe1bep-6188L }, + { 0x2.87c33a262964fd9cp+8628L, -0xf.26e2f1c7fdd8f81p-2156L, -0x1.febee3d02376b5f8p-2140L, -0x1.febee3d02376b5f6p-2140L }, + { 0x2.5af103b8c04393dcp+14240L, 0xf.eeaf2649294683ep+4684L, 0x3.76507f6f2843ac0cp+4700L, 0x3.76507f6f2843ac1p+4700L }, + { 0x1.c5517be1322d88acp-3840L, -0xd.ad84401801a45f6p-12328L, 0xc.d1f792c56fea84dp-12316L, 0xc.d1f792c56fea84ep-12316L }, + { 0x1.f481e7f5a608c8c2p-10832L, -0x7.caae88ce01de0b28p-10208L, 0x1.49a86fa297491138p-10192L, 0x1.49a86fa29749113ap-10192L }, + { 0x4.3bd32cddd2adb53p+6132L, 0x1.7ef0a1fc8c9b04ccp+9928L, 0x2.3d7b927c9e933c78p+9940L, 0x2.3d7b927c9e933c7cp+9940L }, + { 0x5.7001db08p-16416L, -0xc.41d507fb40798b9p-13684L, 0x3.11df8b0dd5773becp-13668L, 0x3.11df8b0dd5773bfp-13668L }, + { 0x6.044acf83853e4228p-9104L, -0xd.b86c5707774a4a2p-8316L, 0x1.e7cb073787416962p-8300L, 0x1.e7cb073787416964p-8300L }, + { 0x7.eedd2b5801d30ddp+7992L, -0x3.7b7080994ba8601p+11972L, -0x6.cc007b1d43a7a56p+11984L, -0x6.cc007b1d43a7a558p+11984L }, + { 0x1.f5be5d508fb45da4p+9112L, 0x1.df36989632baa77cp+8068L, 0x4.2a2d08050cc7844p+8080L, 0x4.2a2d08050cc78448p+8080L }, + { 0xb.cb682f76a3f814p-588L, 0x1.8221ab8a45beb70ap+5048L, -0x3.7186b04965becde4p+5056L, -0x3.7186b04965becdep+5056L }, + { 0x1.da34232a6dcd2a12p+6624L, 0x2.4b62cb0f68a8551p-1320L, 0x3.b60a6ac66abd2584p-1308L, 0x3.b60a6ac66abd2588p-1308L }, + { 0x1.493dc3decd39a4dep+3500L, 0x1.0d22af0930e0b6fp+4276L, 0xe.5ff7e362d36c1fcp+4284L, 0xe.5ff7e362d36c1fdp+4284L }, + { 0x1.677dc1ce56c13e36p-2052L, 0x3.369a880d9098bd94p-8212L, -0x1.9c01bbe923a7cd8ep-8200L, -0x1.9c01bbe923a7cd8cp-8200L }, + { 0x1.243bd932d58f9d4p+2232L, -0x4.405714e489cdecc8p-4048L, -0x2.511c717d4ef5a6ap-4036L, -0x2.511c717d4ef5a69cp-4036L }, + { 0x6.0af8d49f145e687p+2796L, 0x5.839c88a10e84ba4p-6556L, 0x3.c47c119946aaf368p-6544L, 0x3.c47c119946aaf36cp-6544L }, + { 0x6.d702937630559bfp-3504L, -0xe.d559a68601d334ep-376L, 0xc.adf155961d544e9p-364L, 0xc.adf155961d544eap-364L }, + { 0x5.a1a1b43fda655bd8p-4L, -0xc.eb3db51a4117749p+5524L, 0x1.37666ead2720f402p+5528L, 0x1.37666ead2720f404p+5528L }, + { 0x1.d4fff2bbd3cd6096p+14012L, -0x9.b242f08632fe79dp+4872L, -0x2.12c180026a9a0d44p+4888L, -0x2.12c180026a9a0d4p+4888L }, + { 0x3.dce49626e093ee74p-1236L, 0xe.19b5bca3f808afep-1016L, -0x4.3f8a3b4158ea32dp-1004L, -0x4.3f8a3b4158ea32c8p-1004L }, + { 0x3.da483e0a56def77p+12192L, -0x1.a6e3721b926d2e74p-10244L, -0x4.eaf46fbbec4f8428p-10232L, -0x4.eaf46fbbec4f842p-10232L }, + { 0x4.07f8e4310889c4e8p+10772L, -0xc.8841513e4940958p+11376L, -0x2.0f6e90d6698fa354p+11392L, -0x2.0f6e90d6698fa35p+11392L }, + { 0x1.fb59ad3e66e925fp-7792L, 0x4.36d6c1b431f631p+6232L, -0x8.04100041d8b6f53p+6244L, -0x8.04100041d8b6f52p+6244L }, + { 0x4.dd76d9666cca4358p-320L, 0x4.25e1b5ec2d09b028p-4464L, -0x5.25e26d6cad8dc608p-4456L, -0x5.25e26d6cad8dc6p-4456L }, + { 0x7.511fbab815148398p+9832L, -0x9.136d9190525debbp+12768L, -0x1.5cac3737912c4d42p+12784L, -0x1.5cac3737912c4d4p+12784L }, + { 0x1.d2c419eacc353274p-5220L, 0x3.a7736bf4d7d242f8p+6924L, -0x4.a7f42e68003a106p+6936L, -0x4.a7f42e68003a1058p+6936L }, + { 0x3.d1ca473f87febbdp-12640L, -0x6.e69234d17bbb5598p-11576L, 0x1.54ab1b7b62ece05ep-11560L, 0x1.54ab1b7b62ece06p-11560L }, + { 0x8.aa229058b7ec91ap+11260L, 0x2.56be1f012070b9acp+8576L, 0x6.6e69b8535265253p+8588L, 0x6.6e69b85352652538p+8588L }, + { 0x1.c7748fedb8ca471ap+0L, 0x3.392a62c6b703c4ecp+13940L, 0x2.add96e5e07d757e4p+13940L, 0x2.add96e5e07d757e8p+13940L }, + { 0x1.40b8689b9086f9d2p-14232L, 0x2.67e16890207f4008p-2292L, -0x8.5be5308a970cf1cp-2280L, -0x8.5be5308a970cf1bp-2280L }, + { 0x1.4020453efbe8ffdp-10896L, 0xc.8616627c8c648f6p+1252L, -0x2.15070ecc4a673a9cp+1268L, -0x2.15070ecc4a673a98p+1268L }, + { 0x2.38adc006fc23903p+6140L, 0x6.1777a16c16e2514p-2972L, 0x9.221dcf1a3d6e125p-2960L, 0x9.221dcf1a3d6e126p-2960L }, + { 0x5.eccfd047cc0e3388p-10440L, -0x1.b6e7836a71634822p+10592L, 0x4.5e6aacff0d156058p+10604L, 0x4.5e6aacff0d15606p+10604L }, + { 0x6.42d0a34a532209ep-7740L, -0x6.f6bb9a4c17f8e4c8p+1628L, 0xd.279623da9a5e4b7p+1640L, 0xd.279623da9a5e4b8p+1640L }, + { 0x7.eb89e9bd6da32ep+8104L, 0x2.06274f7ea5ec58d4p-3536L, 0x4.018d760dfe123718p-3524L, 0x4.018d760dfe12372p-3524L }, + { 0x1.52e498e37a488bdap-1444L, -0xa.0f4bc2cfdcbdd27p+12596L, 0x3.8ba35274a6f86ec4p+12608L, 0x3.8ba35274a6f86ec8p+12608L }, + { 0xa.fe50b439a96ea55p+10156L, -0x3.a6a05daa8cf8ba1cp+14960L, -0x9.0e3027c0c5b948dp+14972L, -0x9.0e3027c0c5b948cp+14972L }, + { 0x1.95f38ef02236fd6cp+36L, 0x5.9a25ab758149ad5p+11224L, 0xc.d673d3e22020888p+11228L, 0xc.d673d3e22020889p+11228L }, + { 0x2.aa06a7b698b0b3e4p-13208L, 0xf.a22449fa646a2e3p+14428L, -0x3.267f668663bace68p+14444L, -0x3.267f668663bace64p+14444L }, + { 0x1.bf2d10d91eae0db2p+0L, -0x1.f41156a05dc1e02p-8448L, -0x1.92676f0461939be2p-8448L, -0x1.92676f0461939bep-8448L }, + { 0x3.678e1f2aa097eb6p-9600L, -0x6.48717c11cd853a38p-4344L, 0xe.b9184d58694da4ap-4332L, 0xe.b9184d58694da4bp-4332L }, + { 0x6.fa2cdb8df72f8548p-1508L, -0x5.5c8be3b33b03234p-13204L, 0x1.f86214217fa1db1p-13192L, 0x1.f86214217fa1db12p-13192L }, + { 0x5.b43694428f84ed2p+2964L, -0x2.9ea35367c5b0b0fp-2284L, -0x1.e5b4f9fe4ab5c4fcp-2272L, -0x1.e5b4f9fe4ab5c4fap-2272L }, + { 0x1.01687357811d4fd2p+5028L, -0x7.3e1390b9f6f3a3e8p+11328L, -0x8.e3f46f26fefd7d4p+11340L, -0x8.e3f46f26fefd7d3p+11340L }, + { 0x1.1181efb54abefbbep-12372L, 0x6.83c34bd099d6ae7p+4440L, -0x1.3ad73b21743243aep+4456L, -0x1.3ad73b21743243acp+4456L }, + { 0x7.6dfb1adacc93b0d8p-1996L, -0x1.c3d8c6cee90c3ba2p-5648L, 0xd.bde2db8a05260cep-5640L, 0xd.bde2db8a05260cfp-5640L }, + { 0x1.a43f7998e3bc6428p+6660L, 0x1.25125ef5c349b838p-10488L, 0x1.dc943819311290cp-10476L, 0x1.dc943819311290c2p-10476L }, + { 0x9.59de5e82fe42ee3p-4912L, -0x2.82f638bfb4cf4becp+4548L, 0x3.028babe7dbd4e47cp+4560L, 0x3.028babe7dbd4e48p+4560L }, + { 0x1.c7a1126551114648p+7108L, 0xd.27237ee2cef0c03p+12688L, 0x1.6d3da6102aee785p+12704L, 0x1.6d3da6102aee7852p+12704L }, + { 0xb.dd30144dd06980cp-11936L, -0x1.791cebbb198638bep-2520L, 0x4.4a9a2b2b484838b8p-2508L, 0x4.4a9a2b2b484838cp-2508L }, + { 0x2.0e8711d8p-16416L, -0x1.7bb6dd104adc4d0cp+2888L, 0x5.f1ba3150ca7f0828p+2900L, 0x5.f1ba3150ca7f083p+2900L }, + { 0x1.1d43bf5824a1e06cp+4368L, -0x3.6aff33a9a6024948p-7268L, -0x3.a522b04900fbdfp-7256L, -0x3.a522b04900fbdefcp-7256L }, + { 0x2.ea4f2a6ac862728cp+2680L, -0x6.3f1754e29b634308p+10700L, -0x4.16e20a83ab3a847p+10712L, -0x4.16e20a83ab3a8468p+10712L }, + { 0x6.dc2337c4dcfc9ba8p+9292L, 0x1.db67943b70f0e37ap+732L, 0x4.36cdc5c0cbf5c598p+744L, 0x4.36cdc5c0cbf5c5ap+744L }, + { 0x2.11d8eb885c371facp-3816L, 0x9.420077450c7ba7ep+3360L, -0x8.9f61fc96a86315ep+3372L, -0x8.9f61fc96a86315dp+3372L }, + { 0x2.80989ac0b86b7144p+7248L, -0x9.6b6d7f66e9adc62p-7280L, -0x1.0abe032023d3bc7ap-7264L, -0x1.0abe032023d3bc78p-7264L }, + { 0x4.9affaf38db31985p+9560L, -0x3.9fb0ce552022caep-9264L, -0x8.75b6e9f5bba47f3p-9252L, -0x8.75b6e9f5bba47f2p-9252L }, + { 0x1.79f10252e5d32328p-11808L, 0x3.5d72f3d2e9a1c1bp+832L, -0x9.b347207cf9028e7p+844L, -0x9.b347207cf9028e6p+844L }, + { 0x1.551248fac9273744p-604L, -0x4.acf1bc3134803b78p-7060L, 0xb.061ae47f2cbbf69p-7052L, 0xb.061ae47f2cbbf6ap-7052L }, + { 0x7.7cc2f48a5f0b8c2p-13612L, -0x7.4e46d17991c7841p+2360L, 0x1.8460e567b6746cbp+2376L, 0x1.8460e567b6746cb2p+2376L }, + { 0xa.371f3fbdd75e962p+3584L, -0x5.44ff275c91095f78p+5452L, -0x4.9d79ee220fd58108p+5464L, -0x4.9d79ee220fd581p+5464L }, + { 0x3.de6cea18p-16416L, -0x2.d768065c9b0efec8p-5176L, 0xb.62f62c4094f50b5p-5164L, 0xb.62f62c4094f50b6p-5164L }, + { 0x1.dd2afe046d25b216p+13800L, 0xb.fba33f67d3e9c4ep-11144L, 0x2.85ff9be480399d14p-11128L, 0x2.85ff9be480399d18p-11128L }, + { 0x1.1829747c59eaadeep+8880L, -0x2.d7c6fd57d4a80568p+13152L, -0x6.29d2526173e85b88p+13164L, -0x6.29d2526173e85b8p+13164L }, + { 0x9.479031be3e93809p+6644L, -0x5.470f8a96fe098158p+692L, -0x8.90935ba9e5537d9p+704L, -0x8.90935ba9e5537d8p+704L }, + { 0xb.e269d2411d00a65p-12500L, 0xe.dc859359b9e1993p-7060L, -0x2.d572984be4518698p-7044L, -0x2.d572984be4518694p-7044L }, + { 0x1.fc0c45d7d5b6944ep+14064L, -0x7.c373eda7898c0138p-6140L, -0x1.aa895e0c3e0a8064p-6124L, -0x1.aa895e0c3e0a8062p-6124L }, + { 0x3.19dfe4d95f04bf3cp+8788L, 0xe.56a26033db6ec8ep+3404L, 0x1.ec4d67591c6e716cp+3420L, 0x1.ec4d67591c6e716ep+3420L }, + { 0xe.80351557405b528p+5764L, -0xb.b6c59696ddc332cp-5844L, -0x1.07ec6a44e392920ap-5828L, -0x1.07ec6a44e3929208p-5828L }, + { 0x5.edc1370a9352152p-5912L, -0x6.cb8d5970de366248p-4448L, 0x9.cdb559965ad814fp-4436L, 0x9.cdb559965ad815p-4436L }, + { 0x3.311130840d33e9b8p+1248L, 0x4.619b478aa823bf98p+14140L, 0x1.5632ae7c6fddcc8ap+14152L, 0x1.5632ae7c6fddcc8cp+14152L }, + { 0xe.fb1fa7cc5c99a7bp+2644L, 0x6.215a6f280bbf23ap+13288L, 0x3.f686a6e27cbd46ccp+13300L, 0x3.f686a6e27cbd46dp+13300L }, + { 0x6.3a39de95ec46d4bp-8L, -0xe.1e6dc0d48239149p-11560L, 0x4.bb2407581006d8c8p-11556L, 0x4.bb2407581006d8dp-11556L }, + { 0x4.24ff70bcd18c18fp+10272L, 0x1.21f37f880ee736bap-11320L, 0x2.d749d1d167a36bd4p-11308L, 0x2.d749d1d167a36bd8p-11308L }, + { 0x7.390a0da36cdc0aap+7196L, -0xc.b4b337e7f289e73p+10324L, -0x1.654b9c3d455f6008p+10340L, -0x1.654b9c3d455f6006p+10340L }, + { 0x2.10284ca11e4b7564p-1160L, -0xf.507826a098b359bp+12828L, 0x4.554a03b8742e5ebp+12840L, 0x4.554a03b8742e5eb8p+12840L }, + { 0xe.136ea4a2bb31728p+4556L, 0x1.85282eebef8dacc8p+11900L, 0x1.b1393d4db800a8a2p+11912L, 0x1.b1393d4db800a8a4p+11912L }, + { 0x1.20284f808bcc88fap+9660L, -0x6.b85cbded358fc63p+12036L, -0xf.d95f13f31f24b66p+12048L, -0xf.d95f13f31f24b65p+12048L }, + { 0x7.f78dd33fc42fe6c8p+6952L, -0x6.6f2c0f935ec5eb78p+2808L, -0xa.ece48391f9f0029p+2820L, -0xa.ece48391f9f0028p+2820L }, + { 0xc.f8724b65692d26dp-11464L, 0xc.d8d86a52dace604p-11752L, -0x2.3f1f1bf4cf514d88p-11736L, -0x2.3f1f1bf4cf514d84p-11736L }, + { 0x2.d7b18b7d7e32001p-12508L, 0x6.2e48d04a8fa4117p+10856L, -0x1.2df41cd47c378c7p+10872L, -0x1.2df41cd47c378c6ep+10872L }, + { 0x3.ffb401ff0c4f759p+13256L, -0x1.4180a10c714422fap-1496L, -0x4.10a4f72213d46648p-1484L, -0x4.10a4f72213d4664p-1484L }, + { 0x2.b76b974e31a16b8p-11156L, -0x7.5d2f72fd85a96188p-4708L, 0x1.40de39cbf5a8e2bep-4692L, 0x1.40de39cbf5a8e2cp-4692L }, + { 0xa.a6e924d5c873e25p-4L, -0x2.8d7c8afc118c282p-3080L, 0x1.7f9010b25b95f5dp-3080L, 0x1.7f9010b25b95f5d2p-3080L }, + { 0x2.d9a4ff4e3c08fb64p+12248L, -0x1.52b21398d2eb239p-10876L, -0x3.f4e77a2ce1ec901p-10864L, -0x3.f4e77a2ce1ec900cp-10864L }, + { 0x3.aee0b2eba4ea93f4p-11752L, -0x3.a608c14af6727124p+9316L, 0xa.777250fbd0a127fp+9328L, 0xa.777250fbd0a128p+9328L }, + { 0x7.f6a14a5fad86d0ap+8552L, 0xb.3506e923aabefd2p-1124L, 0x1.7684faf5fb9185c8p-1108L, 0x1.7684faf5fb9185cap-1108L }, + { 0x5.3f76be96f999fc38p+7716L, 0x6.58c19d7142062018p-108L, 0xb.f5a59acc9015199p-96L, 0xb.f5a59acc901519ap-96L }, + { 0xf.aca3cd9099be9bep+1640L, 0x6.fc8dd636b71e3f1p-1800L, 0x2.cdda9cd629895304p-1788L, 0x2.cdda9cd629895308p-1788L }, + { 0x1.91d42e0b36883b3ep+4728L, -0x3.88c36c923b28995cp+1744L, -0x4.14825bb13e4b1f18p+1756L, -0x4.14825bb13e4b1f1p+1756L }, + { 0x1.bab5220de2d5268cp-11632L, -0x2.47c45a33bea715d4p+10592L, 0x6.79b1c761cb108088p+10604L, 0x6.79b1c761cb10809p+10604L }, + { 0x2.6e042d7870e54f5p+13852L, 0x8.62d7e11cf21a5ccp+8848L, 0x1.c5cf16cabe81f1a8p+8864L, 0x1.c5cf16cabe81f1aap+8864L }, + { 0x1.c98310f63362d2a6p+1284L, -0x5.78ce0504a9a6ecbp+12692L, -0x1.b767eb9220e28388p+12704L, -0x1.b767eb9220e28386p+12704L }, + { 0x3.608d17ea6d8d0a38p-1492L, -0xa.2155d2a64e7f091p+2336L, 0x3.af87ec9ef906c52p+2348L, 0x3.af87ec9ef906c524p+2348L }, + { 0x2.e6b808fp-16416L, -0x7.f3d928344c7b47c8p+5944L, 0x1.fde88cc384e52e2ep+5960L, 0x1.fde88cc384e52e3p+5960L }, + { 0x3.72e5835930c81eap-4344L, 0x1.b87e6990fe084aaap+9196L, -0x1.d2f8e4b2d0532fccp+9208L, -0x1.d2f8e4b2d0532fcap+9208L }, + { 0x1.0a1e398ca5cf0d14p-10272L, -0x1.e7e7659b06787af2p+9104L, 0x4.c790983fed5fc48p+9116L, 0x4.c790983fed5fc488p+9116L }, + { 0x9.7f447b066f4437ep-12952L, 0x5.3edda06af98605b8p+8176L, -0x1.095393f9b90e26f4p+8192L, -0x1.095393f9b90e26f2p+8192L }, + { 0x5.0884ee2ef216ceb8p-12232L, -0x4.b62cb06b0fc0e708p+1172L, 0xe.1158b1bcde399cap+1184L, 0xe.1158b1bcde399cbp+1184L }, + { 0x1.8778ce2f2d89ba82p+6300L, -0x5.a232f0b2fd82fd1p-9100L, -0x8.aa7115611ef092dp-9088L, -0x8.aa7115611ef092cp-9088L }, + { 0x5.24577f8a1d1b998p+4436L, -0x3.5a69e9684f3f2374p+624L, -0x3.a229f193a2b1b89p+636L, -0x3.a229f193a2b1b88cp+636L }, + { 0x3.e93bb773f849539cp-7916L, 0xe.fde691265bdaf28p-520L, -0x1.cf7596412dbee2fap-504L, -0x1.cf7596412dbee2f8p-504L }, + { 0x3.665e1565d0b924cp+5944L, -0x4.16982d7fcb64e9dp-7880L, -0x5.ef3d51e83c4fcfdp-7868L, -0x5.ef3d51e83c4fcfc8p-7868L }, + { 0x3.fafa5900bf81a534p-6252L, 0xb.17cc0862a59adb9p+5632L, -0x1.0ed30f6930eee0ecp+5648L, -0x1.0ed30f6930eee0eap+5648L }, + { 0x8.78bf4985ee30992p-172L, 0x1.0199abbdde89b38cp-3592L, -0xa.9f92837c78e2a71p-3588L, -0xa.9f92837c78e2a7p-3588L }, + { 0x5.1e6faf18p-16416L, 0x4.f5a6b38aa882c1d8p+7064L, -0x1.3dfcb2a38d27ad42p+7080L, -0x1.3dfcb2a38d27ad4p+7080L }, + { 0x5.5ff127fa305d256p-2732L, 0x1.0506d4431b0e8b1ep-11852L, -0xa.df2b936c1b35f1p-11844L, -0xa.df2b936c1b35f0fp-11844L }, + { 0x1.0ad7b52e9d45bd8ep-1620L, -0xa.7ba4137b5209863p-3448L, 0x4.255c9b0e196d188p-3436L, 0x4.255c9b0e196d1888p-3436L }, + { 0x6.80d745f6314c29dp+14384L, -0xb.e3f21267bbdc57fp-676L, -0x2.9c37cf9ff975118p-660L, -0x2.9c37cf9ff975117cp-660L }, + { 0x3.6676a0eb13ce909cp-10052L, 0xe.072b868a1df7877p-3024L, -0x2.26b8c4584e8e6188p-3008L, -0x2.26b8c4584e8e6184p-3008L }, + { 0x6.5df497b7697155a8p+12256L, -0x1.eedd42b14d9a1374p-13580L, -0x5.c90ca70b1a73cdap-13568L, -0x5.c90ca70b1a73cd98p-13568L }, + { 0x1.1d82e518260f0294p+6512L, -0x9.191d1ec32fdf37bp-144L, -0xe.770435b3120105cp-132L, -0xe.770435b3120105bp-132L }, + { 0xd.529973ed01b4e92p+968L, 0x6.ce2581b071a031dp-9196L, 0x1.9d4ea26451941dap-9184L, 0x1.9d4ea26451941da2p-9184L }, + { 0x1.83f16f4f0984ca08p-6872L, -0x5.338c1e2e6f3d2b3p+5908L, 0x8.b9c9ac256e9a086p+5920L, 0x8.b9c9ac256e9a087p+5920L }, + { 0x1.867d77867b5c95eap+2628L, 0x7.3398eb375f75dfb8p-9260L, 0x4.9f210d1f21e1aa2p-9248L, 0x4.9f210d1f21e1aa28p-9248L }, + { 0x1.cd985a87e976e13cp+3076L, -0x1.45dc8a1f648e67c6p-7864L, -0xf.4c830f7af568de8p-7856L, -0xf.4c830f7af568de7p-7856L }, + { 0x1.4a4d37ap-16416L, 0x1.4e33cb5b10e313f4p+10756L, -0x5.3b63e726e0a641f8p+10768L, -0x5.3b63e726e0a641fp+10768L }, + { 0x1.3482020ad3c0a882p-816L, -0x9.872caa0b23c65a8p-5864L, 0x1.e5c4dd4b25b6778cp-5852L, 0x1.e5c4dd4b25b6778ep-5852L }, + { 0x1.0e8ff00081bc371cp-6176L, 0x1.cf4067f2e44a798ep-120L, -0x2.ba7ccd219acfff4p-108L, -0x2.ba7ccd219acfff3cp-108L }, + { 0x7.a6f445256a7fda78p+4636L, -0x6.6c725b49451ea01p+4828L, -0x7.466c2cdfef5e2efp+4840L, -0x7.466c2cdfef5e2ee8p+4840L }, + { 0x1.1a2d2bcf0843d15ep-8644L, 0x6.b3ca3aa6fe517d3p+8440L, -0xe.24dc76733d14932p+8452L, -0xe.24dc76733d14931p+8452L }, + { 0x1.7eca655a01c636c2p+52L, -0x1.dd3c2732d945f4d4p+6296L, -0x6.2053619ae4b322p+6300L, -0x6.2053619ae4b321f8p+6300L }, + { 0x1.9faf5dbf7986dc42p-412L, 0x5.54b138d415c78598p-7720L, -0x8.9092d2bfa96a01p-7712L, -0x8.9092d2bfa96a00fp-7712L }, + { 0xe.bf3d1b364fa7d78p+6240L, 0xb.c74bfc158951011p+408L, 0x1.1f4796923b917cb8p+424L, 0x1.1f4796923b917cbap+424L }, + { 0x7.2ca230e9bfee2468p+9888L, -0x3.6eb3366a69620d54p-11960L, -0x8.49d8c188f6ff293p-11948L, -0x8.49d8c188f6ff292p-11948L }, + { 0x6.c33f156ecd7b9018p-5056L, -0xa.5597ddf352c5401p+6116L, 0xc.bfdf7e5c155895dp+6128L, 0xc.bfdf7e5c155895ep+6128L }, + { 0xc.894ea5b54605326p+8424L, -0x3.29d764acd5dcadc4p+1548L, -0x6.824621f901eaa6bp+1560L, -0x6.824621f901eaa6a8p+1560L }, + { 0x4.dc0e408p-16420L, 0x2.f294ae2e03276788p-14272L, -0xb.d088f60ec237848p-14260L, -0xb.d088f60ec237847p-14260L }, + { 0x1.8d8d6c474b777c26p-6764L, 0x2.82a240469d5e47c8p+912L, -0x4.251fee784a74545p+924L, -0x4.251fee784a745448p+924L }, + { 0x3.320003e916e2c018p-11548L, 0x2.0fc01824588015bp-9448L, -0x5.cfb08c45bb157868p-9436L, -0x5.cfb08c45bb15786p-9436L }, + { 0x2.766f084c0c4d4becp-4344L, -0xf.918a628430c9869p+3260L, 0x1.08196636d42693dp+3276L, 0x1.08196636d42693d2p+3276L }, + { 0x1.a7ea62a617983f7cp+4280L, 0x4.31f5016cb7a06488p-11684L, 0x4.62645a22f39bbd8p-11672L, 0x4.62645a22f39bbd88p-11672L }, + { 0x3.e2845c867de93e5p+4116L, -0x4.d4440dbc662de6f8p+9256L, -0x4.dae4a99df679d47p+9268L, -0x4.dae4a99df679d468p+9268L }, + { 0x6.eab30da02cc2a598p+9760L, 0x1.2c806e5e622e351cp+504L, 0x2.cc3e6de19ba004fcp+516L, 0x2.cc3e6de19ba005p+516L }, + { 0xa.b66e1024516b719p+6312L, -0x2.77acf612cccf4c7p-4604L, -0x3.cdf31b042afc3218p-4592L, -0x3.cdf31b042afc3214p-4592L }, + { 0x1.114b9705d7e2df02p+14968L, -0x1.5d185f94b66e1fdep+11700L, -0x4.fbb4a016d14170f8p+11712L, -0x4.fbb4a016d14170fp+11712L }, + { 0x6.05221386e27406ep+7108L, -0xa.ea5ec6727dbced3p+5124L, -0x1.2f2fb448d3bf0a6ap+5140L, -0x1.2f2fb448d3bf0a68p+5140L }, + { 0xe.ede20bdb2751c04p-4992L, -0x2.63ffa25342447e7cp-14816L, 0x2.e94a60754ec70b58p-14804L, 0x2.e94a60754ec70b5cp-14804L }, + { 0xb.1a3a6ap-16420L, 0x7.4ddb04c8953c689p-224L, -0x1.d46456593d727256p-208L, -0x1.d46456593d727254p-208L }, + { 0x3.6fa725b26802fc1p+3976L, -0x6.a2e23061803132b8p+9584L, -0x6.71d9a5a82683f7f8p+9596L, -0x6.71d9a5a82683f7fp+9596L }, + { 0x3.1bc6c41d7b8d2494p+12084L, 0x1.7b90e0d7a41add8ap-9760L, 0x4.5ff1fc2dc73c17a8p-9748L, 0x4.5ff1fc2dc73c17bp-9748L }, + { 0xf.4bf5dfe195d4e46p-10012L, 0xe.ef03e3c1cc87ddfp-14124L, -0x2.47d0f7fb93db53b8p-14108L, -0x2.47d0f7fb93db53b4p-14108L }, + { 0x5.ddca9397064452p-10792L, 0xf.f4db22808a890c7p+4992L, -0x2.a0817b6ef96e117cp+5008L, -0x2.a0817b6ef96e1178p+5008L }, + { 0x2.3bf4fe007d9b6508p-4292L, 0xf.5b06933a4845034p+6108L, -0x1.01604b2d99b21d0cp+6124L, -0x1.01604b2d99b21d0ap+6124L }, + { 0x1.13b11c9cdbbfb39cp+324L, -0x8.3f36b704651a623p+3780L, -0xa.70e2f6da63903a9p+3788L, -0xa.70e2f6da63903a8p+3788L }, + { 0x3.debb4f1fb4f3d46cp+1624L, 0x4.46c390ab2d99867p+10104L, 0x1.b2941faa9cc9d50ep+10116L, 0x1.b2941faa9cc9d51p+10116L }, + { 0x6.c1201301bf4c9218p+6756L, -0x2.4d6a37f3ed5852fcp+2216L, -0x3.cc95f7fec27acff4p+2228L, -0x3.cc95f7fec27acffp+2228L }, + { 0x1.7499fce7028b5718p-1560L, -0x3.4a630b8e2e554824p+12228L, 0x1.40b836996da41882p+12240L, 0x1.40b836996da41884p+12240L }, + { 0x2.5cdec5c3c9cd305cp-2792L, -0x4.df8c690724ffac2p-10720L, 0x3.52007c9cd5f5bcecp-10708L, 0x3.52007c9cd5f5bcfp-10708L }, + { 0xd.563eae6fd0c7a55p-4L, 0xf.407ea5dcda35ceep+14612L, -0x4.01832b7b29c949a8p+14612L, -0x4.01832b7b29c949ap+14612L }, + { 0x2.88537585e08a0db8p+8480L, -0x2.d1b1e77a78c0add8p-11944L, -0x5.d65ec904e91d1dap-11932L, -0x5.d65ec904e91d1d98p-11932L }, + { 0x1.903cbb912f0bd304p-6664L, 0x1.f043925d5bfa9a4p-6948L, -0x3.2751f0797c3c2104p-6936L, -0x3.2751f0797c3c21p-6936L }, + { 0x1.2d980aa61aaa044ap-5788L, -0x7.5c4c52f7a6d1f848p+3612L, 0xa.6691012806f86e1p+3624L, 0xa.6691012806f86e2p+3624L }, + { 0x3.df18660f37583684p+12996L, 0xa.9226fd0725f5548p-9324L, 0x2.18b8280f88377528p-9308L, 0x2.18b8280f8837752cp-9308L }, + { 0xa.bb09710051dcf8dp-6364L, -0x3.a3b7749ef082dccp+6000L, 0x5.a6d6eb577c61432p+6012L, 0x5.a6d6eb577c614328p+6012L }, + { 0x9.f86536a0190222p-8972L, 0x2.834c95d589ef3c24p-7364L, -0x5.80949d7b13ce07bp-7352L, -0x5.80949d7b13ce07a8p-7352L }, + { 0xf.095b5efb520e98cp-14876L, -0x4.925b19d467927c58p-9252L, 0x1.0996c5412e3615b4p-9236L, 0x1.0996c5412e3615b6p-9236L }, + { 0x1.dad1ee8a661ae87ap+5708L, 0x1.fe352d18c29a58f6p+10544L, 0x2.c71d060d0cef0e34p+10556L, 0x2.c71d060d0cef0e38p+10556L }, + { 0xf.c50d2b0b4759078p+2820L, 0xf.297abc86e6d6ca4p-7248L, 0xa.74140c28fb060b3p-7236L, 0xa.74140c28fb060b4p-7236L }, + { 0x7.0453d1280723b998p-8932L, -0x8.aaf24f9f3a0b99cp-4004L, 0x1.2e54114a95896f2ep-3988L, 0x1.2e54114a95896f3p-3988L }, + { 0x4.4cfc31fp-16416L, 0xb.0d9092f80bfd229p-10520L, -0x2.c4ae93c54ad8e124p-10504L, -0x2.c4ae93c54ad8e12p-10504L }, + { 0xf.a206d4e1105d091p-8016L, -0x2.d55598a73912513p+4172L, 0x5.8accb2f3cc70fd8p+4184L, 0x5.8accb2f3cc70fd88p+4184L }, + { 0x8.2ee1b7d5eb1d0c3p-6348L, -0x7.c8f8d0eff8137ff8p+13384L, 0xc.0f3dddeec691ed5p+13396L, 0xc.0f3dddeec691ed6p+13396L }, + { 0x3.b1a407914e578be8p+8968L, -0x1.7e3c9a467164bd2p-12264L, -0x3.4510b8f20a060848p-12252L, -0x3.4510b8f20a060844p-12252L }, + { 0x3.a757d9b6a00a4ba8p-1900L, -0x7.177fa6a92ce714d8p-3624L, 0x3.495259a9dfb60448p-3612L, 0x3.495259a9dfb6044cp-3612L }, + { 0x3.be5e8801d352664p+6012L, -0x3.a12c079f54735f34p+8764L, -0x5.543ef8fe17f7f85p+8776L, -0x5.543ef8fe17f7f848p+8776L }, + { 0x2.2d8852e645dca22p+9040L, 0x2.ffff06be9f08f6acp-14752L, 0x6.9f33c0295b347e1p-14740L, 0x6.9f33c0295b347e18p-14740L }, + { 0x1.03322ae66aef91c2p-720L, -0x6.ff7e97b99adce708p+5956L, 0x1.3ae73f9a1237c138p+5968L, 0x1.3ae73f9a1237c13ap+5968L }, + { 0xd.9ec53ffbb90281cp-544L, 0x4.4c329e6a78ac8bcp+132L, -0x9.11ba60714038acbp+140L, -0x9.11ba60714038acap+140L }, + { 0x7.536fe5affbc375ep+3920L, 0x3.1222fe8be3486f6p+6204L, 0x2.f0e8a6e185c7e7bcp+6216L, 0x2.f0e8a6e185c7e7cp+6216L }, + { 0x8.15c1c9e9c82d888p+14352L, 0x1.d25ed81d571b76b2p-4888L, 0x6.627636ca6db9ff78p-4876L, 0x6.627636ca6db9ff8p-4876L }, + { 0x1.06142a4caeedca5p+0L, 0x3.0b886441145c1bf8p+8452L, 0x1.a6473f7721100534p+8448L, 0x1.a6473f7721100536p+8448L }, + { 0xa.022610dbd7d5487p-4260L, 0x1.f8669248dbba890cp-12896L, -0x2.0c2fea8c9a403c08p-12884L, -0x2.0c2fea8c9a403c04p-12884L }, + { 0x1.427e698110e4f9cep+12256L, -0xa.ceffd4a7d89dae6p-12572L, -0x2.0579b1a86fbaa90cp-12556L, -0x2.0579b1a86fbaa908p-12556L }, + { 0x6.98bfa5fdcdd697bp+4448L, -0x2.ae37715f3487a328p+6884L, -0x2.e9a4f05a20a95cc4p+6896L, -0x2.e9a4f05a20a95ccp+6896L }, + { 0x5.471706d1fef36668p+11296L, 0x2.60481b44518620e4p-2100L, 0x6.8de218514d390dbp-2088L, 0x6.8de218514d390db8p-2088L }, + { 0x1.c9dc47831fc622dap+8488L, 0x2.277891fbbfd0636p-8056L, 0x4.76e84361d1c36df8p-8044L, 0x4.76e84361d1c36ep-8044L }, + { 0x2.7aa75062a08bbeap-12220L, 0x1.855b35dcfe02fd7cp+12580L, -0x4.897afe1ff40bdd3p+12592L, -0x4.897afe1ff40bdd28p+12592L }, + { 0x4.b2b1830d66fb0c98p-13732L, 0x5.23b229f58bca7ba8p-2960L, -0x1.13a3481ea7e7e5f4p-2944L, -0x1.13a3481ea7e7e5f2p-2944L }, + { 0x8.d08fe057a50127ap-1140L, -0xb.6ba4e2f724db45bp-7688L, 0x3.2b77e4777e7a7954p-7676L, 0x3.2b77e4777e7a7958p-7676L }, + { 0x1.662b22f1dd79fc5ap-1184L, -0x9.5692b3519c8755ap-8328L, 0x2.b2be0450fbef222p-8316L, 0x2.b2be0450fbef2224p-8316L }, + { 0x1.82d56f808fae1b4p+3252L, 0xa.fe2e145fc22e872p+10868L, 0x8.bab6d6535a848adp+10880L, 0x8.bab6d6535a848aep+10880L }, + { 0x6.76cfc11e7b6566b8p-4L, 0x5.449f7a84db9971ap-8384L, -0x6.e363ec6143f817cp-8384L, -0x6.e363ec6143f817b8p-8384L }, + { 0x8.6314a48e9f5cf1bp+14264L, 0x1.02a4a8db28694176p-11124L, 0x3.84e602f86fc958e4p-11112L, 0x3.84e602f86fc958e8p-11112L }, + { 0xb.a215b32c0ab2fb5p-8296L, 0x3.b121832e8103529p+14676L, -0x7.7971416c1af6341p+14688L, -0x7.7971416c1af63408p+14688L }, + { 0x3.dda3552b2cfcb6dp-6772L, 0x7.eae66ccf86eba1b8p-12672L, -0xd.1626578ff235625p-12660L, -0xd.1626578ff235624p-12660L }, + { 0x3.d1bdac6c27a4987cp-11480L, -0xb.f0201fb3fdf4fdap+10816L, 0x2.17410c1ecf9c6a04p+10832L, 0x2.17410c1ecf9c6a08p+10832L }, + { 0x1.753b55139a6ae0d4p-9588L, -0xc.b94fdca214abb5bp-10048L, 0x1.dc8597552b0e5e98p-10032L, 0x1.dc8597552b0e5e9ap-10032L }, + { 0x7.49cfb50979428ccp+13260L, 0x6.d1ca9e09ccdfe48p-8776L, 0x1.614e15a9b7619142p-8760L, 0x1.614e15a9b7619144p-8760L }, + { 0x2.fdb3fd975c2fcc24p-8752L, -0x6.dcfc60eadb01717p+11444L, 0xe.a981b074aac6ebep+11456L, 0xe.a981b074aac6ebfp+11456L }, + { 0x5.461b7b2ee09e674p-3212L, 0x2.75ad884b4a7c987cp+1616L, -0x1.ed696c80266e3dc4p+1628L, -0x1.ed696c80266e3dc2p+1628L }, + { 0x3.fe2313c91b361a94p-11200L, -0xe.dc38443676c5a64p-10132L, 0x2.8a04ef36438bec6p-10116L, 0x2.8a04ef36438bec64p-10116L }, + { 0x7.3bc9614f8e5128c8p+4260L, 0x4.1330a0a05f33682p+14436L, 0x4.3daf7300edde6ddp+14448L, 0x4.3daf7300edde6dd8p+14448L }, + { 0x8.bd152439e522049p-4L, 0xb.92113f16dc8ef45p+13704L, -0xa.18b112a71a99ff9p+13704L, -0xa.18b112a71a99ff8p+13704L }, + { 0x2.19a9a6a149d64b2cp+7252L, 0x1.465d05fbac7ff242p-3232L, 0x2.41ea09187aa26998p-3220L, 0x2.41ea09187aa2699cp-3220L }, + { 0x1.2dfa170de378162p+1848L, 0x6.e3ccc6f233fe54p+11352L, 0x3.1be1289e5ccdfe38p+11364L, 0x3.1be1289e5ccdfe3cp+11364L }, + { 0x2.45ae50f119d75d4cp+9348L, 0x2.48cb633ccf171d88p-8776L, 0x5.36cd745dea71ace8p-8764L, 0x5.36cd745dea71acfp-8764L }, + { 0x3.ffc0ede5facf9aap+144L, -0x1.639d563ebd47e19cp-3360L, -0xc.acf9b954dff786p-3356L, -0xc.acf9b954dff785fp-3356L }, + { 0x1.320a4fa8c7689a5cp+12176L, -0x3.c102f99e035bd4c4p-5096L, -0xb.28d15096dbe0335p-5084L, -0xb.28d15096dbe0334p-5084L }, + { 0x1.06fdec9589c7e3cap-11048L, 0x1.37fe7627faad46a8p+7504L, -0x3.498717a4095b29a8p+7516L, -0x3.498717a4095b29a4p+7516L }, + { 0x3.49a93629ad7fc314p-3304L, -0x6.c1900e2ee2255dfp-10704L, 0x5.72691640c0fb8b8p-10692L, 0x5.72691640c0fb8b88p-10692L }, + { 0x7.3784858026f59eb8p-12536L, 0x1.9512838f9ba32ffap-6896L, -0x4.d775f974a9b756dp-6884L, -0x4.d775f974a9b756c8p-6884L }, + { 0x1.80ea0336ba35c6a6p+10468L, 0x3.c200d3a7e961c3dcp-11276L, 0x9.9ab1fd7e38b6ddp-11264L, 0x9.9ab1fd7e38b6dd1p-11264L }, + { 0x5.aa69355ef02ac868p-13564L, 0x1.76a1cac98f2db2cep+8268L, -0x4.d85fb08ac5441228p+8280L, -0x4.d85fb08ac544122p+8280L }, + { 0x1.b089a658p-16416L, 0x1.ea990a7a7c9093b4p+524L, -0x7.ae22285ee60e2328p+536L, -0x7.ae22285ee60e232p+536L }, + { 0x5.5307153542305dp+5812L, -0xf.a0fa3c8f422f914p-12628L, -0x1.62f865e81f9e158p-12612L, -0x1.62f865e81f9e157ep-12612L }, + { 0x3.d18c9f1fe178b66cp-5976L, 0x3.07dccc28a2dbb64cp-11924L, -0x4.6b9ae7abba0f89dp-11912L, -0x4.6b9ae7abba0f89c8p-11912L }, + { 0xb.a85358c13ac490ep+8052L, -0x1.581f0dbe008f95a6p+3224L, -0x2.a4c7405adef4cb88p+3236L, -0x2.a4c7405adef4cb84p+3236L }, + { 0x5.23afe2a0b74d62p+3396L, 0xf.eaf45db22aa5f58p+400L, 0xd.34e691543edfc8fp+412L, 0xd.34e691543edfc9p+412L }, + { 0xf.bbc8e9388c45f3ap+4960L, 0xd.adbde37244f6cd2p+4352L, 0x1.093ca1363e18977cp+4368L, 0x1.093ca1363e18977ep+4368L }, + { 0xd.0ec84ab52b6bccfp-14316L, 0x3.242368e52518021p-7596L, -0xa.f9d475f53e8f64cp-7584L, -0xa.f9d475f53e8f64bp-7584L }, + { 0xe.6fcb560f3434363p+6672L, -0x2.582d5ceb82c13698p+1228L, -0x3.d2325f4c49e3efp+1240L, -0x3.d2325f4c49e3eefcp+1240L }, + { 0x2.c32af39bbff96d5cp-14764L, 0x3.ac0794141c17ee54p+3048L, -0xd.3bfe31094bba577p+3060L, -0xd.3bfe31094bba576p+3060L }, + { 0x2.1cd826493af5d3a4p-6760L, -0x6.ae408d4f2bfec03p+4488L, 0xb.062231847cd3d58p+4500L, 0xb.062231847cd3d59p+4500L }, + { 0x8.ca91adedeaa1e77p+6300L, 0xf.acd7dd8fa7e0887p-14224L, 0x1.81f2b8e35ed12114p-14208L, 0x1.81f2b8e35ed12116p-14208L }, + { 0x3.3ff778d9323b9c5p-4L, -0xd.c2058e770c939ap+12944L, 0x1.fa34dff1e1c4bc78p+12948L, 0x1.fa34dff1e1c4bc7ap+12948L }, + { 0x1.31637c3000e438e4p+11384L, -0x4.686ea46458512aep-1676L, -0xc.405174ea19fdec5p-1664L, -0xc.405174ea19fdec4p-1664L }, + { 0xd.d9373849cbb5adbp-8496L, -0x4.f30da52b4bc6c1bp-8616L, 0xa.42f909e0e6d629dp-8604L, 0xa.42f909e0e6d629ep-8604L }, + { 0x2.aaaaea743fb846c4p-10376L, -0x8.2ff53eaf90ae7cp-13868L, 0x1.4bcc3637b01b0c72p-13852L, 0x1.4bcc3637b01b0c74p-13852L }, + { 0x8.f919db6c7b9f466p-2356L, -0x6.a312fd5cbddcec78p+12452L, 0x3.cffc82d80b2c68e4p+12464L, 0x3.cffc82d80b2c68e8p+12464L }, + { 0x1.5ef60b9d2b73390ap-1820L, 0x3.6efa517d1c5d3a28p+13140L, -0x1.8676b8655aad1cd6p+13152L, -0x1.8676b8655aad1cd4p+13152L }, + { 0x3.daffca7fb01f62b4p-14284L, -0xf.6af4c77adde2767p+11168L, 0x3.5c25cd91022ff884p+11184L, 0x3.5c25cd91022ff888p+11184L }, + { 0x3.43d37022ccb92268p+5012L, 0x7.e9ab5b70fd0bde88p+11408L, 0x9.af850ca0012c747p+11420L, 0x9.af850ca0012c748p+11420L }, + { 0x2.435d3715a985bcb8p+10736L, 0x3.aacc5c1e9457eadp-10348L, 0x9.9cf2c8d41a4e1ddp-10336L, 0x9.9cf2c8d41a4e1dep-10336L }, + { 0x6.db3d1c3421345d9p+9732L, -0x4.36066072222de638p-12688L, -0xa.0217c93e79fcf29p-12676L, -0xa.0217c93e79fcf28p-12676L }, + { 0x3.08ae8e74c266a098p-5748L, 0xe.770635edbd5eaf3p-13844L, -0x1.44b14e3d8e36c586p-13828L, -0x1.44b14e3d8e36c584p-13828L }, + { 0x1.76212ep-16420L, 0x1.3ab2fe378fa08002p+12544L, -0x4.ed85475e9e6609c8p+12556L, -0x4.ed85475e9e6609cp+12556L }, + { 0x1.fd551ae8610d128p+7480L, 0x3.769a9f2eaaf3700cp-10948L, 0x6.534e5c73be7354ap-10936L, 0x6.534e5c73be7354a8p-10936L }, + { 0xa.e0aac49fb82b00bp-7972L, 0x1.6fd07eaba5d3fd5ep+32L, -0x2.cb9062aca3ea933cp+44L, -0x2.cb9062aca3ea9338p+44L }, + { 0xa.1cb34dbd6cd395fp-1656L, 0x7.4ee3c5874237b978p+12680L, -0x2.f2dec58363c34d3cp+12692L, -0x2.f2dec58363c34d38p+12692L }, + { 0xb.9b50fe352d3c1b1p+364L, -0x8.db835f5f3c3aa14p+2212L, -0xc.b772bb6b1a9a731p+2220L, -0xc.b772bb6b1a9a73p+2220L }, + { 0x3.6d33ead8abf8a548p-13856L, -0x1.c02ccce5ca28e9c4p+2936L, 0x5.ebe5c84acb3e408p+2948L, 0x5.ebe5c84acb3e4088p+2948L }, + { 0x3.0af6574b42ede154p-11844L, 0x1.1478f312ab1800b6p-700L, -0x3.1f56ff3ec7659148p-688L, -0x3.1f56ff3ec7659144p-688L }, + { 0x1.623ac0a3f7aba0bep+8220L, -0x1.4bcc58434b1bb7aap-4960L, -0x2.99e70d80ff093388p-4948L, -0x2.99e70d80ff093384p-4948L }, + { 0x2.745f807c070fa178p-12228L, 0x1.0bdeb66d4a421602p-10224L, -0x3.1f99efcbce646dfcp-10212L, -0x3.1f99efcbce646df8p-10212L }, + { 0x1.d791a56eee5e72cp+4460L, 0xe.eeae1eb0781a412p+5380L, 0x1.04336a8490f4dae4p+5396L, 0x1.04336a8490f4dae6p+5396L }, + { 0x1.005eedfe61628706p-10904L, -0x7.0f25c96d65a172ap+7888L, 0x1.2cad2db5759ce0b4p+7904L, 0x1.2cad2db5759ce0b6p+7904L }, + { 0x8.48b67c8ab19d09dp-4L, -0x1.f888e4fc233d27dcp+6724L, 0x1.df23c41e1919f418p+6724L, 0x1.df23c41e1919f41ap+6724L }, + { 0xc.ae4e6ad45a50465p+4112L, -0x2.518b484925a2b1cp+13764L, -0x2.5464c5094de3f82p+13776L, -0x2.5464c5094de3f81cp+13776L }, + { 0x1.9c18d7876ee7376ep-14044L, 0x1.23d29c845c03c0dap+3464L, -0x3.e886d92ea80a7d1p+3476L, -0x3.e886d92ea80a7d0cp+3476L }, + { 0x2.89d5cb60a9e9af5cp-4744L, -0xd.158a1c32534c8bbp-4820L, 0xf.26591cea3a34904p-4808L, 0xf.26591cea3a34905p-4808L }, + { 0xc.4033377961e2fe8p+9052L, -0x5.b388ee53b605e2b8p-3668L, -0xc.9acd9b90883283fp-3656L, -0xc.9acd9b90883283ep-3656L }, + { 0x1.d50869ea25276784p-10972L, 0x4.d1c12faa90b5e068p-508L, -0xc.e89be19644230e7p-496L, -0xc.e89be19644230e6p-496L }, + { 0x9.febbb7fe5ed6546p-4588L, 0xb.099054e905162d5p-7288L, -0xc.5aabe646430f123p-7276L, -0xc.5aabe646430f122p-7276L }, + { 0x2.9d9c43b7825d326p+12808L, -0x2.ada1ee9ab68cb0fp-4512L, -0x8.602c4c1dc8b3b28p-4500L, -0x8.602c4c1dc8b3b27p-4500L }, + { 0x4.7c5bc0f7776b0ac8p+2520L, -0x3.0a1b28d67b2747b8p-8696L, -0x1.df2103aaf6513a14p-8684L, -0x1.df2103aaf6513a12p-8684L }, + { 0x1.2f7388d95a11e1bep-6608L, 0x5.19ffda1dd0d9c2a8p-4600L, -0x8.3addbca737209aap-4588L, -0x8.3addbca737209a9p-4588L }, + { 0x7.3e70e5fcf433aa28p-11840L, 0x1.d0de4ba9a67c312ap+3816L, -0x5.3f6f925f1b5ac89p+3828L, -0x5.3f6f925f1b5ac888p+3828L }, + { 0x7.d5521358p-16416L, 0xa.6edd69b6078e966p-7072L, -0x2.9ce63aa876c852a4p-7056L, -0x2.9ce63aa876c852ap-7056L }, + { 0x1.a06b478721ce054ep+13548L, -0x1.393c0e863c65bdb8p-6108L, -0x4.0c1d22c0912dc55p-6096L, -0x4.0c1d22c0912dc548p-6096L }, + { 0x3.b69179fa44654bbcp+1440L, -0x6.e4159565f7c389f8p+10500L, -0x2.6d004320fc3ff95cp+10512L, -0x2.6d004320fc3ff958p+10512L }, + { 0x2.5ad010f8b9d60f14p+12900L, 0xb.828c126f8807123p+10908L, 0x2.440c92f86267255p+10924L, 0x2.440c92f862672554p+10924L }, + { 0x9.98a3919087bcbddp+12296L, -0xb.6ce393db0528821p+14940L, -0x2.24eb593295e856b8p+14956L, -0x2.24eb593295e856b4p+14956L }, + { 0xb.5517b51c0f4d664p-4000L, 0x1.d4234882ba64610ep-4640L, -0x1.c8c3fb42f463b05p-4628L, -0x1.c8c3fb42f463b04ep-4628L }, + { 0x8.5bd2dd7bb1477a4p-3904L, -0x1.12e3d6e3b466d59ap-476L, 0x1.05cc87caeb220ccep-464L, 0x1.05cc87caeb220cdp-464L }, + { 0x5.ed808c966d066e28p+7324L, -0x2.00368397327e3fccp-12952L, -0x3.9433ab5ccc8a19ccp-12940L, -0x3.9433ab5ccc8a19c8p-12940L }, + { 0x4.b40d71fc6217c0ap+8936L, -0x5.e9dcc5f1571235p+1792L, -0xc.e7877da64a564eep+1804L, -0xc.e7877da64a564edp+1804L }, + { 0x1.34407e864341f828p+3440L, -0x5.1b8cadf3b9cef08p+11308L, -0x4.4a390c27f8641c38p+11320L, -0x4.4a390c27f8641c3p+11320L }, + { 0x8.179975b3956adafp-10324L, 0x1.dd7c8a838a11dd72p-4000L, -0x4.b328227e31522ce8p-3988L, -0x4.b328227e31522cep-3988L }, + { 0x1.01fdcep-16416L, 0xb.a372ba15d4c940dp-5452L, -0x2.ea50fb8dd4efd0cp-5436L, -0x2.ea50fb8dd4efd0bcp-5436L }, + { 0x5.3b665bec0d2e2dcp-2800L, -0x1.f45e190fe1072f02p-12656L, 0x1.55c1aa1fbb13f3f6p-12644L, 0x1.55c1aa1fbb13f3f8p-12644L }, + { 0x8.992f6f29de9baa1p-6444L, 0x2.6df885a56ac520b8p-14752L, -0x3.d20a120e0c03b828p-14740L, -0x3.d20a120e0c03b824p-14740L }, + { 0xc.c702ea51f29dd29p+1248L, 0x1.8a572c70170d4e5cp+12552L, 0x7.881260ccbcf27268p+12560L, 0x7.881260ccbcf2727p+12560L }, + { 0x7.7da787b409a377c8p-6564L, 0x9.7e0cf04e7e0519bp-6448L, -0xf.348702698a255aep-6436L, -0xf.348702698a255adp-6436L }, + { 0x7.e356b90a1e983p+6044L, -0x1.595f87983b91e67ap+11008L, -0x1.fde107e29925392cp+11020L, -0x1.fde107e29925392ap+11020L }, + { 0x6.68cb8626a1a7bd2p-856L, -0x5.2867609201d772p+3332L, 0x1.13146bfa618ef4acp+3344L, 0x1.13146bfa618ef4aep+3344L }, + { 0x1.d9c129761350a49ep-1456L, -0x1.29e3078444080f32p-2724L, 0x6.9d32b50a997a3358p-2716L, 0x6.9d32b50a997a336p-2716L }, + { 0x7.d308bb4487d45ed8p+8360L, 0x3.05fa312cc9b12db8p-7928L, 0x6.2c42b7a54e1f43p-7916L, 0x6.2c42b7a54e1f4308p-7916L }, + { 0xb.1557c6f908f40bfp+13336L, 0x1.7c6eeead727f952ep-3248L, 0x4.d6f5b1bc630d822p-3236L, 0x4.d6f5b1bc630d8228p-3236L }, + { 0x2.aa3fe22d8b80d434p-3748L, -0x2.bbf4a7d991feb2d4p-864L, 0x2.803ec10c3efa22f4p-852L, 0x2.803ec10c3efa22f8p-852L }, + { 0x5.4ec5032p-16416L, -0x2.6748c73e3720dc58p+11340L, 0x9.a195140488f7b6fp+11352L, 0x9.a195140488f7b7p+11352L }, + { 0x1.97e6fba1fa77cd84p+776L, 0x1.0fd2d35c90316ae6p-10104L, 0x3.38adc0961147ee3cp-10096L, 0x3.38adc0961147ee4p-10096L }, + { 0xa.ff44e18825e4262p-3300L, -0x3.a9ba576b1d83aeep+6148L, 0x2.f2b3a675e3dd0e28p+6160L, 0x2.f2b3a675e3dd0e2cp+6160L }, + { 0x7.8af9d275e91fced8p-7428L, 0x1.4317fd2efba13bf6p-9056L, -0x2.49b16335dd4b114cp-9044L, -0x2.49b16335dd4b1148p-9044L }, + { 0x7.9c3ee1462407ec68p+5156L, -0x3.e97de45eb74e97b4p+11988L, -0x4.ed61fdf674171e78p+12000L, -0x4.ed61fdf674171e7p+12000L }, + { 0x1.47be5e7291ef5b5ep+8620L, 0x1.b6bb4b3df23a952p-3860L, 0x3.9b586e9657351918p-3848L, 0x3.9b586e965735191cp-3848L }, + { 0xf.f85cf60592328d2p-9520L, 0x6.cc119db119c5da9p+9692L, -0xf.ca9a38109b4c719p+9704L, -0xf.ca9a38109b4c718p+9704L }, + { 0x2.4705d056fcb476bp-10860L, 0x3.1a2184afa03ed9b8p+9408L, -0x8.394d6f3a2c6421fp+9420L, -0x8.394d6f3a2c6421ep+9420L }, + { 0x1.efef03e24f29831p-3176L, -0x1.bfca2ff565e7c7bp+7752L, 0x1.5b1b931975e428fcp+7764L, 0x1.5b1b931975e428fep+7764L }, + { 0x7.f9560ea0eafc2cc8p+9148L, -0xe.5db4d730684872fp-4644L, -0x2.0187920d54cfb648p-4628L, -0x2.0187920d54cfb644p-4628L }, + { 0x2.1c6a49285ec69a54p+7380L, -0xb.ddf812b2df6f309p+11120L, -0x1.5627be2e7b4b330ep+11136L, -0x1.5627be2e7b4b330cp+11136L }, + { 0x2.50ff3a6p-16416L, 0x1.9d7cfb7be4e5e346p-3100L, -0x6.790f9653202121ap-3088L, -0x6.790f965320212198p-3088L }, + { 0xa.f2ce777f871a092p+8780L, -0x7.e9c5837c2b7a4378p+8600L, -0x1.0f80f46491d8b8b6p+8616L, -0x1.0f80f46491d8b8b4p+8616L }, + { 0x4.3bbff88395fe0928p+7164L, 0x3.078f7e4f50cee1fp-7468L, 0x5.4cde225bf7236df8p-7456L, 0x5.4cde225bf7236ep-7456L }, + { 0x1.40aedb75cc42f43p-3192L, -0x2.375af19fcf60d21cp-10956L, 0x1.ba17d902e7ac91cp-10944L, 0x1.ba17d902e7ac91c2p-10944L }, + { 0x2.e864c555d76d8fd8p+6104L, 0xb.a979200b6675bf5p+12664L, 0x1.1622d579502026b8p+12680L, 0x1.1622d579502026bap+12680L }, + { 0x6.752e08b00a6d4d98p-13552L, 0x1.90097d94485a7816p-11844L, -0x5.2b4c1e50cbcc733p-11832L, -0x5.2b4c1e50cbcc7328p-11832L }, + { 0x3.04f44aa97cbecd68p+9068L, 0x2.20c52243c3fe5f5cp-1352L, 0x4.b642b5821f0aeabp-1340L, 0x4.b642b5821f0aeab8p-1340L }, + { 0xb.561e8e6deeeb863p+8760L, -0x5.e1ac807eaa7b77d8p+10480L, -0xc.956e10315ea540ep+10492L, -0xc.956e10315ea540dp+10492L }, + { 0xd.22dad1146a3117p-3440L, 0x1.6479b527d613626ep+10984L, -0x1.2b0f6f8ef5196098p+10996L, -0x1.2b0f6f8ef5196096p+10996L }, + { 0x2.22be5768782c69ep-1500L, -0x7.84c022153d71427p+3364L, 0x2.c059ab76744f422p+3376L, 0x2.c059ab76744f4224p+3376L }, + { 0x1.33435c6dd3af5182p-9572L, 0x1.57376b17d4e90b76p-3676L, -0x3.220b9bf2119f92fp-3664L, -0x3.220b9bf2119f92ecp-3664L }, + { 0x6.36fe5bdp-16416L, -0x3.80b314c162ff107cp-3536L, 0xe.093a021c9f60a3ap-3524L, 0xe.093a021c9f60a3bp-3524L }, + { 0x3.5eddbf43ab12e4a8p-5700L, -0xa.5a9dd55c674fbcbp-11372L, 0xe.6777bbf7206e289p-11360L, 0xe.6777bbf7206e28ap-11360L }, + { 0x4.0a86f68d596f23e8p+7288L, -0x2.82d21b0211fc61fp+6792L, -0x4.7815c915a64ae22p+6804L, -0x4.7815c915a64ae218p+6804L }, + { 0x5.dd81aeb5f9a4f41p-12728L, -0x3.431d7252485001e4p+4252L, 0xa.2288cab8ba1862ep+4264L, 0xa.2288cab8ba1862fp+4264L }, + { 0x1.c28b03b6522311d4p+8396L, -0x3.afe5362342fa9fe4p+5704L, -0x7.8efd32fc985cb208p+5716L, -0x7.8efd32fc985cb2p+5716L }, + { 0x9.8ddc34fd380f7cdp+568L, 0xd.ced796ac550d5bp-232L, 0x1.ecfe43ab490e4fp-220L, 0x1.ecfe43ab490e4f02p-220L }, + { 0xa.a847a961d00df0ap-12848L, 0x3.93bd979611f43f78p-112L, -0xb.37a8505a07b2fcfp-100L, -0xb.37a8505a07b2fcep-100L }, + { 0x3.4f402dd17b106c64p+2848L, 0xa.f846845320f317ep+11452L, 0x7.a1d0165417058f2p+11464L, 0x7.a1d0165417058f28p+11464L }, + { 0x3.5fa4d9a9fc21151cp-1100L, -0x6.a6e5ab8e0621faap-5044L, 0x1.c89777bcbd33655ap-5032L, 0x1.c89777bcbd33655cp-5032L }, + { 0x5.2d133d77a9410b7p-2572L, -0x3.275ca162a017e318p+6740L, 0x1.fa7fbb2b9abf17f6p+6752L, 0x1.fa7fbb2b9abf17f8p+6752L }, + { 0xb.e1fef9fa3e9727bp+7852L, -0x5.05efe9b304aee998p-8292L, -0x9.a240a67e18be2fap-8280L, -0x9.a240a67e18be2f9p-8280L }, + { 0x1.c09e468785b5c354p+0L, -0xf.e5ab606d8f7b3f9p+7364L, -0xc.ddc3c7616dc446ap+7364L, -0xc.ddc3c7616dc4469p+7364L }, + { 0x1.719eead8a3620922p-180L, -0x9.35dd3e7b4a587e8p-344L, 0x6.74fe200dd9b9ac08p-336L, 0x6.74fe200dd9b9ac1p-336L }, + { 0x2.8278beb0a151763cp-8212L, 0x5.eba3b3c3cbebaa48p+8284L, -0xb.de30343dea0b754p+8296L, -0xb.de30343dea0b753p+8296L }, + { 0x3.87c4c0dbaba1349cp-12224L, 0x6.e4fe70430b5bdc7p+1680L, -0x1.4929e97c9702dfbap+1696L, -0x1.4929e97c9702dfb8p+1696L }, + { 0x7.f319306232e2f73p-6724L, -0x1.ee505dd9decefc84p-6388L, 0x3.2b1b071aed29ccap-6376L, 0x3.2b1b071aed29cca4p-6376L }, + { 0x9.1283f8a751c7f83p+12432L, 0x7.dca6e7a2f237d91p+2120L, 0x1.7de46c83437e1e1ep+2136L, 0x1.7de46c83437e1e2p+2136L }, + { 0x1.3c34c3c18ccb74p+3424L, 0x1.dfc743544c7cf47p-10028L, 0x1.9119b57694c572a8p-10016L, 0x1.9119b57694c572aap-10016L }, + { 0x5.3e565a011294bb1p-3244L, -0x7.3b196b739bfda8ep+10224L, 0x5.b8f9d0123290a33p+10236L, 0x5.b8f9d0123290a338p+10236L }, + { 0x3.8eadcc909e81db74p+8456L, -0x8.b4ba5efc626545bp-7348L, -0x1.1fa19c6bacf2da3ep-7332L, -0x1.1fa19c6bacf2da3cp-7332L }, + { 0xd.3e930c035371ebdp+1480L, 0xd.c6f32497b5fa56dp-8132L, 0x4.fd987b827f63e48p-8120L, 0x4.fd987b827f63e488p-8120L }, + { 0x1.ca7125b550edcfa2p+12328L, -0x8.5acc8c64428f007p-4880L, -0x1.925b90260d25c798p-4864L, -0x1.925b90260d25c796p-4864L }, + { 0x1.0759db8p-16416L, -0x1.3d7f601417185b42p+9944L, 0x4.f877af95374dab3p+9956L, 0x4.f877af95374dab38p+9956L }, + { 0x2.ebd4b19614542238p-14220L, -0xe.1d7e71fee6192bap-6916L, 0x3.0ff877205d61bf4p-6900L, 0x3.0ff877205d61bf44p-6900L }, + { 0x1.29f13fe64015ff46p-12340L, -0xe.d00c66c632b4331p-4136L, 0x2.ca0157bfdbd30f1cp-4120L, 0x2.ca0157bfdbd30f2p-4120L }, + { 0x3.f63ba994a2b78004p+10240L, -0x1.57d10ff018294618p+10496L, -0x3.5bb555eab8c5fb3cp+10508L, -0x3.5bb555eab8c5fb38p+10508L }, + { 0xa.4140ce712f7b66p-6044L, 0xa.a4bce42874e01e7p+7932L, -0xf.b259d473b5ba7p+7944L, -0xf.b259d473b5ba6ffp+7944L }, + { 0x2.389ed5e685fc7134p-7432L, 0x1.b0d67f730c4f25bp+2716L, -0x3.113e0ce097de504p+2728L, -0x3.113e0ce097de503cp+2728L }, + { 0x2.eb978b7f340e0d58p-12364L, -0x9.adfe099d19d2efdp+14472L, 0x1.d37051fa5ea8b54cp+14488L, 0x1.d37051fa5ea8b54ep+14488L }, + { 0x1.5117ecccbd2929b6p-984L, -0x2.b3ae7a75c3b22b8p+7932L, 0xa.61940cdf8cae1a3p+7940L, 0xa.61940cdf8cae1a4p+7940L }, + { 0x9.c5c6d7173a39debp+2136L, -0xe.7eb5c52358f835ep+764L, -0x7.920e831d2af5f778p+776L, -0x7.920e831d2af5f77p+776L }, + { 0x4.3cbd69afe18488ap-11676L, -0x4.fc641a37202982b8p+4448L, 0xe.35d02b71acd487fp+4460L, 0xe.35d02b71acd488p+4460L }, + { 0x3.f0fb7afa6ec2cfb8p-3124L, 0x8.c94c984dbf4168dp-7396L, -0x6.b27180ae20d41818p-7384L, -0x6.b27180ae20d4181p-7384L }, + { 0x1.15ebd30a56ecb2b2p+0L, -0x5.856bb2e62511b85p-6612L, -0xa.7891ddb0a39e893p-6616L, -0xa.7891ddb0a39e892p-6616L }, + { 0x1.410266a44f4ade2cp+12952L, -0x5.59c0fbbe79fde728p-3952L, -0x1.0eb6baf03c343682p-3936L, -0x1.0eb6baf03c34368p-3936L }, + { 0x4.9a419d04fd743ab8p-1156L, 0x9.9730cd1292b85ap-2352L, -0x2.b3998f683c0b5874p-2340L, -0x2.b3998f683c0b587p-2340L }, + { 0x2.60759aed3ba97d74p-6648L, -0x3.457e7b428940e34cp+6612L, 0x5.4f0968584e19d46p+6624L, 0x5.4f0968584e19d468p+6624L }, + { 0x2.c09bd6c830c2da0cp+4984L, 0x3.6fa2b8685f61706p-9464L, 0x4.2ea6cd39acdfcd5p-9452L, 0x4.2ea6cd39acdfcd58p-9452L }, + { 0x7.78d4cf72d7cf81d8p-2060L, 0x7.d23da006d9cb052p-476L, -0x3.ed916667567ea0d4p-464L, -0x3.ed916667567ea0dp-464L }, + { 0x1.e8ec274891c36f6cp-7524L, -0xe.b8e278ce572ceccp+13540L, 0x1.b0a4220a5507d7cap+13556L, 0x1.b0a4220a5507d7ccp+13556L }, + { 0x2.52eaea727fb51b3cp+1024L, 0x3.2d22702027067fbp+7032L, 0xc.b866f7b6cca84f4p+7040L, 0xc.b866f7b6cca84f5p+7040L }, + { 0x4.79b08bc9ec6fd5e8p+10104L, 0x1.81c5dfaf98a0897p+10364L, 0x3.b7d3bdf2e8856dccp+10376L, 0x3.b7d3bdf2e8856ddp+10376L }, + { 0x4.a5a62cfd609d80cp+5652L, -0x5.87842a4bef49dfa8p-7756L, -0x7.a203332a806e1458p-7744L, -0x7.a203332a806e145p-7744L }, + { 0x1.3174a6b7f76a7a86p-3852L, 0x1.3b46ff4438b080d2p+3696L, -0x1.2879ff24035ac472p+3708L, -0x1.2879ff24035ac47p+3708L }, + { 0x1.59099ec9256df04ap+0L, -0x1.277978f781f67db2p+8000L, -0x7.f3bf3708724aa25p+7996L, -0x7.f3bf3708724aa248p+7996L }, + { 0x1.3cf4d6911744a6e2p-6764L, -0x2.b9ce903eca743bf8p-8152L, 0x4.80486c57075689p-8140L, 0x4.80486c5707568908p-8140L }, + { 0x9.e73df967ed71cb5p+10888L, -0x9.1c04010e8eff95cp+200L, -0x1.838dac64b03492fp+216L, -0x1.838dac64b03492eep+216L }, + { 0x5.ac4763ac26327b68p-2172L, 0x6.d1b60df617649598p-9812L, -0x3.9ca312dc58e6275p-9800L, -0x3.9ca312dc58e6274cp-9800L }, + { 0x7.c5ae0be7d6818d3p+2488L, -0x4.dbabdbbb9c48c46p+9484L, -0x2.f454d6d39c21f13cp+9496L, -0x2.f454d6d39c21f138p+9496L }, + { 0x5.da0ebfb61ec3d02p+12980L, -0x1.581ed3ef522cbf1ap-6680L, -0x4.42b6830ac9def328p-6668L, -0x4.42b6830ac9def32p-6668L }, + { 0xc.49cd167ff1e78d8p-7248L, 0x2.5d1e3b11ab1bc11p+9356L, -0x4.2e3d9db76c4da9bp+9368L, -0x4.2e3d9db76c4da9a8p+9368L }, + { 0x2.3b097280a7388008p-11704L, -0x1.061a800d969622bap+4464L, 0x2.ecddc2fed514cc58p+4476L, 0x2.ecddc2fed514cc5cp+4476L }, + { 0x3.cb828c1d80e286fcp+9648L, 0x4.e4c85ab7c7a946f8p-4884L, 0xb.877a950bfab740bp-4872L, 0xb.877a950bfab740cp-4872L }, + { 0xc.edf760d6631b3bep+8604L, -0x1.d29ab8a4c77d5026p+12620L, -0x3.d49031197037c1fcp+12632L, -0x3.d49031197037c1f8p+12632L }, + { 0xe.225defb5c321ae6p-14048L, -0x5.74840b374f4bf2b8p+5052L, 0x1.2b44f5a5454a26a4p+5068L, 0x1.2b44f5a5454a26a6p+5068L }, + { 0x1.f568cdf552161702p+0L, -0x3.0fa175f6b0d25a68p+13292L, -0x2.f8001ffc544eaf7p+13292L, -0x2.f8001ffc544eaf6cp+13292L }, + { 0xc.720d79d29899fb8p+11764L, 0x9.7936377be97bc8ep-14464L, 0x1.b3788544a5202dp-14448L, 0x1.b3788544a5202d02p-14448L }, + { 0x1.65183aeb23c7f346p-12864L, 0x3.7e98b83d4e4ca3d4p-1628L, -0xa.f97cc9cbef6f274p-1616L, -0xa.f97cc9cbef6f273p-1616L }, + { 0x1.ef79e62dda211fbp-1948L, -0x4.d23ac0a4bc617a2p-7780L, 0x2.4ab1f4112fd17bd8p-7768L, 0x2.4ab1f4112fd17bdcp-7768L }, + { 0x2.07b821eeab20cb9p-160L, -0x3.87a37dafaa376984p-3444L, 0x2.312b08e897671c68p-3436L, 0x2.312b08e897671c6cp-3436L }, + { 0xe.72871f0890145a5p+6524L, -0x8.9b9c7083ec7bb41p+4312L, -0xd.b7ed0b19656759ep+4324L, -0xd.b7ed0b19656759dp+4324L }, + { 0x7.4749b7447d5e7338p+5256L, -0x2.62e022dcd7674688p+13968L, -0x3.104df1ed95530a84p+13980L, -0x3.104df1ed95530a8p+13980L }, + { 0x3.7b8f1a318d818b88p-652L, -0xf.181bfa7fcc16529p+14968L, 0x2.6563b23fcf087a7cp+14980L, 0x2.6563b23fcf087a8p+14980L }, + { 0x7.5c8ebd177e7ae458p+7036L, 0xe.f0ee6b7c83a4f2ap+8576L, 0x1.9ad0e0a9821d3b5ep+8592L, 0x1.9ad0e0a9821d3b6p+8592L }, + { 0xa.9952cee8bf7946cp+9776L, -0x9.ebe699f73877e14p+9532L, -0x1.7b024099ee813daep+9548L, -0x1.7b024099ee813dacp+9548L }, + { 0x5.41cd5dd4d2e6f57p-832L, 0x7.56f01406b724bdfp-1104L, -0x1.7c8f99b2a519ef76p-1092L, -0x1.7c8f99b2a519ef74p-1092L }, + { 0x7.6952ff4171fab3e8p-4L, -0x1.48ad521dcbf4fffap+2016L, 0x1.6ce9dbd767f12b1p+2016L, 0x1.6ce9dbd767f12b12p+2016L }, + { 0x1.8ea82281163d7928p-10440L, 0x7.f9f050a81e69354p+10508L, -0x1.4543b78b02164af6p+10524L, -0x1.4543b78b02164af4p+10524L }, + { 0x1.6ad2d6305e908336p-4748L, -0xb.4b631a00023d4e5p-88L, 0xd.174834bfe56bdf3p-76L, 0xd.174834bfe56bdf4p-76L }, + { 0x7.eb9bc51887342998p-10920L, -0x2.99dd95695c7be558p+14760L, 0x6.eeb8ff1797c83d48p+14772L, 0x6.eeb8ff1797c83d5p+14772L }, + { 0x4.b577a5ced64ab34p-2420L, 0x2.19c1abad13c7ff4p+6292L, -0x1.3d6c8b4378990c28p+6304L, -0x1.3d6c8b4378990c26p+6304L }, + { 0x3.5a9733b22bf6430cp+448L, -0x9.845cc05884f6906p-3452L, -0x1.0b83fc7f2a9cbfe2p-3440L, -0x1.0b83fc7f2a9cbfep-3440L }, + { 0x1.8d9e8b60d5f8a05cp-872L, -0x1.50baf7988b16437p-12748L, 0x4.7a26f37415047d8p-12740L, 0x4.7a26f37415047d88p-12740L }, + { 0x1.768be5f438d658c6p+7928L, -0xe.79a06c92bcdce18p+9292L, -0x1.c04e9286dd4bbf2ap+9308L, -0x1.c04e9286dd4bbf28p+9308L }, + { 0x5.cc20a3adbc707e28p-2948L, 0x1.418168344c0a6e5cp+10428L, -0xe.73270ee786c9bb4p+10436L, -0xe.73270ee786c9bb3p+10436L }, + { 0x2.01c7e3e1c94921a8p-116L, -0x7.49980d9c71c299dp-5404L, 0x3.4605f5bf68747d74p-5396L, 0x3.4605f5bf68747d78p-5396L }, + { 0x1.2d18c093a14af7c2p+13716L, -0x3.2206b08cd203d208p-12288L, -0xa.7dbca28d7e9a709p-12276L, -0xa.7dbca28d7e9a708p-12276L }, + { 0x1.9b11ae9e8789a284p+0L, -0xc.b66cf8836b8e5dbp-1376L, -0x8.af8b48e59260aa5p-1376L, -0x8.af8b48e59260aa4p-1376L }, + { 0x3.b06bfa9d957936c4p-4168L, -0x1.188ea5802ac70448p+8880L, 0x1.1d5c217dd118b722p+8892L, 0x1.1d5c217dd118b724p+8892L }, + { 0x7.baa53749caf9a77p+800L, -0x3.ea31eb4e2589909cp-10688L, -0xc.4768c5478ebac23p-10680L, -0xc.4768c5478ebac22p-10680L }, + { 0xc.41014580a7e7c5bp-6320L, 0x1.a46de5ad785de1bcp+8256L, -0x2.885692990a3b54ccp+8268L, -0x2.885692990a3b54c8p+8268L }, + { 0xe.6403838c15ab5c3p+5876L, -0x7.15c7d5d8dcdd2f4p-6296L, -0xa.2bb3092c3f77652p-6284L, -0xa.2bb3092c3f77651p-6284L }, + { 0x4.65c5ae737a956a58p-6604L, -0xe.3fc8bb8cbd6b77fp+7832L, 0x1.6f76fc0e8ab70b94p+7848L, 0x1.6f76fc0e8ab70b96p+7848L }, + { 0x6.8944175f279787cp+10884L, -0x3.c6fc4b6f87ef254p+7116L, -0xa.0a2397fa3e675fbp+7128L, -0xa.0a2397fa3e675fap+7128L }, + { 0x7.97bc7363ddb9f9dp-14396L, -0x1.705e3b449ab47172p-10828L, 0x5.0e6bdb7051618038p-10816L, 0x5.0e6bdb705161804p-10816L }, + { 0xf.4b3b8c6e5f4077ep-8792L, -0xe.ed14847db8e58eap+10408L, 0x2.00637d26121590cp+10424L, 0x2.00637d26121590c4p+10424L }, + { 0x2.41544dd69bee4b34p-12932L, -0x9.56c015923cb5347p+9124L, 0x1.d7b74a4ea2338eb6p+9140L, 0x1.d7b74a4ea2338eb8p+9140L }, + { 0xd.e8a92b7b9d69849p+6300L, 0x3.378443d08ca9b84p-7784L, 0x4.f36729d56447749p-7772L, 0x4.f36729d564477498p-7772L }, + { 0x2.95a69238p-16416L, -0x7.80265f26200c7ebp+3052L, 0x1.e0ef561ee038353cp+3068L, 0x1.e0ef561ee038353ep+3068L }, + { 0x3.d22d04b09cd96cp-9300L, 0xf.766def43d7f6db7p-4796L, -0x2.319c6a506e36063p-4780L, -0x2.319c6a506e36062cp-4780L }, + { 0xe.05ec56e0474d77fp-9876L, 0x6.3465a4ac0b6eea4p+3892L, -0xe.f45bdd4a240a8e9p+3904L, -0xe.f45bdd4a240a8e8p+3904L }, + { 0x1.5625d5075933e438p-12804L, -0x1.6a8b27da36acfbfcp+1128L, 0x4.6d4403e057a6ebcp+1140L, 0x4.6d4403e057a6ebc8p+1140L }, + { 0x3.ff1468eb7c6639d8p+2168L, 0x5.89011895dd2bfa1p+9524L, 0x2.eeb5173dba868ba4p+9536L, 0x2.eeb5173dba868ba8p+9536L }, + { 0x5.5e6fb8e79a725d4p-10600L, 0x3.4479f5178f043be4p+5416L, -0x8.7436da836e63732p+5428L, -0x8.7436da836e63731p+5428L }, + { 0x4.bac9e5fddf2f185p+7280L, 0x2.f6cd56a85259e42p+12372L, 0x5.45114581f9e1dacp+12384L, 0x5.45114581f9e1dac8p+12384L }, + { 0x4.483dd9562600d12p-9412L, -0xa.91077e9f213cfefp-5060L, 0x1.8465eb7223d017dep-5044L, 0x1.8465eb7223d017ep-5044L }, + { 0x6.89490ba0c6021cbp-10152L, -0x1.93dd39b70d0c7806p+3368L, 0x3.e8b771e60bf65d74p+3380L, 0x3.e8b771e60bf65d78p+3380L }, + { 0x6.a491ee61660c85b8p-8176L, -0x8.c58567eeb3bfc0fp+1020L, 0x1.180c5e553f4e3ccap+1036L, 0x1.180c5e553f4e3cccp+1036L }, + { 0xd.f08f28601b06388p+13780L, 0x1.f2be9ba2b44f15dep+7068L, 0x6.8e5e3dc0bd5a4308p+7080L, 0x6.8e5e3dc0bd5a431p+7080L }, + { 0x7.457d5fa8p-16416L, 0x5.36121d8b16e4023p+12776L, -0x1.4e1c5f378a2e9af4p+12792L, -0x1.4e1c5f378a2e9af2p+12792L }, + { 0x4.1748a66d103e0fa8p+2480L, -0xb.d4d5cce3f37beb6p-5748L, -0x7.2b5e31b51058241p-5736L, -0x7.2b5e31b510582408p-5736L }, + { 0x9.a2ade899ef170ddp-7756L, 0x1.bd8b440f03c52848p+2808L, -0x3.4b4e71fdaa1b4c3cp+2820L, -0x3.4b4e71fdaa1b4c38p+2820L }, + { 0x1.92f53c269af15d42p-2928L, -0xa.9b2b2aefde35ef1p-10024L, 0x7.947ccb13fbbf40fp-10012L, 0x7.947ccb13fbbf40f8p-10012L }, + { 0x6.5d56109347b4ece8p-5268L, -0xa.9333fe0a2e921e5p+732L, 0xd.980ed7ca91c85f8p+744L, 0xd.980ed7ca91c85f9p+744L }, + { 0x3.7331573dbbfe41p-9136L, 0xd.1d5fbf9a047f6e6p-6984L, -0x1.d3f0daca4b8e608cp-6968L, -0x1.d3f0daca4b8e608ap-6968L }, + { 0x1.22091bc1d5e9fd24p+3872L, -0x4.9486f9b8459c0e5p-1392L, -0x4.5474ca8e81c1c0c8p-1380L, -0x4.5474ca8e81c1c0cp-1380L }, + { 0x2.386cb89f395c99d8p+5940L, -0x2.96e4faa003243a54p+9812L, -0x3.c1833e77be9321d8p+9824L, -0x3.c1833e77be9321d4p+9824L }, + { 0xd.a5f4daee140e571p+14840L, -0x1.4c05492fe894fe3cp-13360L, -0x4.b33b6593c762fa18p-13348L, -0x4.b33b6593c762fa1p-13348L }, + { 0x2.fdd1ccf5dd08fa6cp+7320L, 0xc.71f7b0b27cb30f2p-8224L, 0x1.63ee6ef689e23e96p-8208L, 0x1.63ee6ef689e23e98p-8208L }, + { 0x1.18572e37370fa8eap-5800L, -0x5.6bd9b71f1fad727p-10896L, 0x7.ad2c6c0e239a106p-10884L, 0x7.ad2c6c0e239a1068p-10884L }, + { 0x4.338ea3e8p-16416L, 0x7.6d96c7989caed318p+6588L, -0x1.dc4402ce4443924cp+6604L, -0x1.dc4402ce4443924ap+6604L }, + { 0x5.b84f9fac30c5708p+7284L, 0x2.75e933325654ae8cp-9812L, 0x4.6092020d634cd7e8p-9800L, 0x4.6092020d634cd7fp-9800L }, + { 0x3.3e8858dcbe489fccp-14240L, 0x7.1714d40b275a0028p+2264L, -0x1.8a57dcc28e880ca2p+2280L, -0x1.8a57dcc28e880cap+2280L }, + { 0x9.afa19306462ec46p-4888L, -0x3.32b794a45c3dca3p-11648L, 0x3.d05e73304663623cp-11636L, 0x3.d05e73304663624p-11636L }, + { 0xd.6eaf9e68e259a17p+1236L, 0x1.cae4c43fd3dd00fcp+568L, 0x8.ae504857a6a66dap+576L, 0x8.ae504857a6a66dbp+576L }, + { 0x1.5385af8dce743fa2p+4740L, 0xc.6bc92b4c49f5ed6p-10560L, 0xe.600c818b9dbc8e6p-10548L, 0xe.600c818b9dbc8e7p-10548L }, + { 0x2.6955eff09a469d1p-5464L, 0x1.bf618641435e7edep-13260L, -0x2.54a916727d0b84p-13248L, -0x2.54a916727d0b83fcp-13248L }, + { 0xb.b90392d51073b9p+2700L, -0xb.85d9396b5e43565p-13416L, -0x7.9b09aa40c40f5878p-13404L, -0x7.9b09aa40c40f587p-13404L }, + { 0x1.4e74d9c2a57143e4p+3248L, 0x1.3eb38c672955f3f6p-14744L, 0xf.cc00ef9a86640aap-14736L, 0xf.cc00ef9a86640abp-14736L }, + { 0x2.ffdfeb1e2d7afdcp-4136L, -0x4.d00269c32889b9bp-5536L, 0x4.db90696a8a4897cp-5524L, 0x4.db90696a8a4897c8p-5524L }, + { 0x4.31404d22df9d95fp-7388L, 0x1.0fe8d9c29ebdb07ep+764L, -0x1.ea4f1ad3071fc356p+776L, -0x1.ea4f1ad3071fc354p+776L }, + { 0x5.0dda6b7p-16416L, 0x2.4106f760ba40ae1p-596L, -0x9.08499f030f1555dp-584L, -0x9.08499f030f1555cp-584L }, + { 0x7.8bae544d63ec3028p-7564L, -0xc.a0b5e26f909cb8bp+6516L, 0x1.74f7acb203909964p+6532L, 0x1.74f7acb203909966p+6532L }, + { 0x5.4c3c08113f951888p-2412L, -0x9.c30a7694e19585ep-7016L, 0x5.be22b69ad1450abp-7004L, 0x5.be22b69ad1450ab8p-7004L }, + { 0x5.afb9c4521af8ad88p-5172L, -0x5.37c3c13b646fb49p+9220L, 0x6.95d89660c2da22f8p+9232L, 0x6.95d89660c2da23p+9232L }, + { 0x1.cd7081ce9dc8e7b6p+88L, -0x1.867a488422075acp-1032L, -0x8.785f0a1c2ad14f6p-1028L, -0x8.785f0a1c2ad14f5p-1028L }, + { 0xc.eab3815fae9cc61p-4692L, 0x8.ffb864f70ff47bcp+14852L, -0xa.4cda82a0bacc544p+14864L, -0xa.4cda82a0bacc543p+14864L }, + { 0x9.034b59783532405p-14652L, 0x1.068f1b119399b4fep+8912L, -0x3.ab025bbdc4919f7p+8924L, -0x3.ab025bbdc4919f6cp+8924L }, + { 0x2.7ea6fa3a41a2ed88p+13384L, -0x1.cb41210310ca777cp-2836L, -0x5.dccc2ba4750423a8p-2824L, -0x5.dccc2ba4750423ap-2824L }, + { 0x7.07a46917c6845538p-11804L, 0xe.2919c752d6e306p+14380L, -0x2.8cc7496f5889be98p+14396L, -0x2.8cc7496f5889be94p+14396L }, + { 0x1.e93b47f4fe49cc4p+3472L, -0xc.48da1160ad2d58bp-8004L, -0xa.6a788032e89083ap-7992L, -0xa.6a788032e890839p-7992L }, +}; + +int check_equal(long double res, long double expected) +{ + if (res != expected) { + return 0; + } + return (__builtin_copysignl(1.0L, res) == + __builtin_copysignl(1.0L, expected)); +} + +int main(void) +{ + int ret = 0; + int i; + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + long double ld_res; + __asm__ volatile ("fyl2x" : "=t" (ld_res) : + "0" (tests[i].arg0), "u" (tests[i].arg1) : "st(1)"); + if (!check_equal(ld_res, tests[i].down) && + !check_equal(ld_res, tests[i].up)) { + printf("FAIL: fyl2x %La %La, expected %La or %La, got %La\n", + tests[i].arg0, tests[i].arg1, tests[i].down, tests[i].up, + ld_res); + ret = 1; + } + } + return ret; +} diff --git a/tests/tcg/i386/test-i386-fyl2xp1.c b/tests/tcg/i386/test-i386-fyl2xp1.c new file mode 100644 index 0000000000000000000000000000000000000000..99b08c188a07d8463cd864c882fbb3b0556ad270 --- /dev/null +++ b/tests/tcg/i386/test-i386-fyl2xp1.c @@ -0,0 +1,1156 @@ +/* Test fyl2xp1 instruction. */ + +#include + +struct test { + long double arg0, arg1, down, up; +}; + +const struct test tests[] = { + { 0.0L, 12345.0L, 0.0L, 0.0L }, + { 0.0L, -12345.0L, -0.0L, -0.0L }, + { -0.0L, 12345.0L, -0.0L, -0.0L }, + { -0.0L, -12345.0L, 0.0L, 0.0L }, + { 0.0L, 0.0L, 0.0L, 0.0L }, + { 0.0L, -0.0L, -0.0L, -0.0L }, + { -0.0L, 0.0L, -0.0L, -0.0L }, + { -0.0L, -0.0L, 0.0L, 0.0L }, + { 0.1L, 0.0L, 0.0L, 0.0L }, + { 0.1L, -0.0L, -0.0L, -0.0L }, + { -0.1L, 0.0L, -0.0L, -0.0L }, + { -0.1L, -0.0L, 0.0L, 0.0L }, + { 0.1L, __builtin_infl(), __builtin_infl(), __builtin_infl() }, + { 0.1L, -__builtin_infl(), -__builtin_infl(), -__builtin_infl() }, + { -0.1L, __builtin_infl(), -__builtin_infl(), -__builtin_infl() }, + { -0.1L, -__builtin_infl(), __builtin_infl(), __builtin_infl() }, + { 0x4p-4L, 0x1p-16400L, 0x5.269e12f3468p-16404L, 0x5.269e12f347p-16404L }, + /* Randomly generated tests. */ + { 0x1.31edb79669dd58b4p-4L, 0x6.c25439d8a5ce071p+14380L, 0xb.3d0da52c1f58af3p+14376L, 0xb.3d0da52c1f58af4p+14376L }, + { -0x1.8ee6680c65ce5a5p-4L, -0x7.423575b7ac0ba6a8p-2228L, 0x1.12aefa96f5501268p-2228L, 0x1.12aefa96f550126ap-2228L }, + { 0x2.a22cf9563bdd84bcp-140L, -0x2.de6fb39cd2988858p-9616L, -0xa.e65ebedd6a09e4cp-9756L, -0xa.e65ebedd6a09e4bp-9756L }, + { -0x7.d1095c8p-16416L, 0x1.faa600d255691f3cp+6420L, -0x1.6516c14a553da39ap-9992L, -0x1.6516c14a553da398p-9992L }, + { 0x4.109249df7871ecb8p-4L, 0x1.48d8eebeb8e650ccp-4976L, 0x6.b65f4ea303a8bc3p-4980L, 0x6.b65f4ea303a8bc38p-4980L }, + { -0x4.69bcd5ccca0e4b7p-4L, -0x5.8808ae941f249bb8p+5056L, 0x2.93432047c7d8a37p+5056L, 0x2.93432047c7d8a374p+5056L }, + { 0x3.311f29ec8b38ef74p-4L, -0x3.9865a5505c3ae018p+8924L, -0xf.188d6a2bba06e17p+8920L, -0xf.188d6a2bba06e16p+8920L }, + { -0x2.d60110be2e4f812p-4L, 0x9.d61827e646421b3p-11580L, -0x2.c4c3e84b6c7366c8p-11580L, -0x2.c4c3e84b6c7366c4p-11580L }, + { 0xe.e4d7ebcee10774ap-8L, 0x6.5cde5b7691984918p+732L, 0x8.4e3d353f31e18a3p+728L, 0x8.4e3d353f31e18a4p+728L }, + { -0x2.a675c1a9bd30047cp-4L, 0x7.6eae536d8312ebb8p+364L, -0x1.f116f2eaf6acba9ep+364L, -0x1.f116f2eaf6acba9cp+364L }, + { 0xb.b88ac679a0d52c7p-8L, 0x1.9e45eb57212a1f62p-8572L, 0x1.ac193570d9ac8e8p-8576L, 0x1.ac193570d9ac8e82p-8576L }, + { -0x4.64109ab4700cf108p-4L, 0x6.b8d96cb8e5f2d648p+6524L, -0x3.1c6e7c0e4e7a72cp+6524L, -0x3.1c6e7c0e4e7a72bcp+6524L }, + { 0x3.e104f8db9c02bf08p-4L, -0x9.7b905723db3fe54p+10116L, -0x2.f83eb6c0529e814p+10116L, -0x2.f83eb6c0529e813cp+10116L }, + { -0x3.906c6b45a9367874p-4L, -0x3.b4f349ff071caa64p-1868L, 0x1.5901debf0c548972p-1868L, 0x1.5901debf0c548974p-1868L }, + { 0x1.a960a3b0bddab872p-4L, -0xa.80f80d092c59d2fp+14796L, -0x1.7f4db50bf3cd7588p+14796L, -0x1.7f4db50bf3cd7586p+14796L }, + { -0x1.422d05691d16c3c2p-4L, -0x3.b7afc1088aafbb28p+8056L, 0x7.07a7a145b32d0108p+8052L, 0x7.07a7a145b32d011p+8052L }, + { 0x3.005497260bfe3efcp-4L, 0x2.70b5fc4ea650b9d4p+13164L, 0x9.af1b9b78be96p+13160L, 0x9.af1b9b78be96001p+13160L }, + { -0x3.06e1d8ce558315f4p-4L, 0xd.35a31147278a276p+13452L, -0x3.ff1a81342b225bf4p+13452L, -0x3.ff1a81342b225bfp+13452L }, + { 0x5.0312793de5c8af88p-8L, -0x1.4d64bd7151f8f83ep+13040L, -0x9.53672f561e11e6dp+13032L, -0x9.53672f561e11e6cp+13032L }, + { -0x4.6fd8156d1cd1594p-4L, 0x1.2bbce9cdd6e3b99ep+2372L, -0x8.c70a26daa3a50c9p+2368L, -0x8.c70a26daa3a50c8p+2368L }, + { 0x1.eab2d269541adaap-4L, 0x6.ac21c841f135e818p-10084L, 0x1.16d60a1c1c53feb2p-10084L, 0x1.16d60a1c1c53feb4p-10084L }, + { -0x3.f7c63bee23b61aep-4L, -0x1.a4746c335dbffc62p+13532L, 0xa.ce1e8b95a3cf783p+13528L, 0xa.ce1e8b95a3cf784p+13528L }, + { 0x2.6770b5d4fbdb93ap-4L, 0x2.d0747a0fc160c9d8p-680L, 0x9.17f6580ba6d8d8fp-684L, 0x9.17f6580ba6d8d9p-684L }, + { -0x4.0c0f16fccf171958p-4L, -0x3.809f02e6f0a4a7ccp-632L, 0x1.793819991e50c69p-632L, 0x1.793819991e50c692p-632L }, + { 0x2.810e5178p-16416L, -0x2.449b1281f31c58ccp-8912L, -0x8p-16448L, -0x0p+0L }, + { -0x9.d14aa8cda67cd5p-80L, 0x2.3ff156f07699390cp+1860L, -0x1.fdd7e7674c238f56p+1784L, -0x1.fdd7e7674c238f54p+1784L }, + { 0x4.336973fa388adee8p-4L, 0x6.68a249106b0173e8p+1992L, 0x2.27d09f940daa748cp+1992L, 0x2.27d09f940daa749p+1992L }, + { -0x2.975eb02ec54042c4p-4L, -0xe.5f17872c08b122dp+7300L, 0x3.a9ce29cce0f873bp+7300L, 0x3.a9ce29cce0f873b4p+7300L }, + { 0x3.18142b116ed172acp-4L, -0x4.c54f6758e57de6ap+2080L, -0x1.377f5497b5e407dcp+2080L, -0x1.377f5497b5e407dap+2080L }, + { -0x1.1bbc90a005c56912p-4L, -0x4.a9cd0b7c6a571cd8p+5332L, 0x7.ba3b3fc9d3dba0f8p+5328L, 0x7.ba3b3fc9d3dba1p+5328L }, + { 0x1.7e8efe16b98d3692p-8L, -0x3.dde86e3bf4d91464p-4156L, -0x8.4ff4f144076f27ep-4164L, -0x8.4ff4f144076f27dp-4164L }, + { -0xa.7e96579f3a805bp-8L, -0x7.ab5c584ae971a368p+6308L, 0x7.6906aa4947cba078p+6304L, 0x7.6906aa4947cba08p+6304L }, + { 0x1.9eca084b5e88755ep-4L, 0xf.227ce981b624ea7p+11116L, 0x2.1b30979fa829e6dcp+11116L, 0x2.1b30979fa829e6ep+11116L }, + { -0x2.1874c2d880381c8p-4L, -0x1.137b3104db6109dap-5420L, 0x3.7ca97456f9d67034p-5424L, 0x3.7ca97456f9d67038p-5424L }, + { 0x3.198e690cee01623p-4L, -0x1.adc155088273f77ep+13812L, -0x6.dcc1714e4ba0c37p+13808L, -0x6.dcc1714e4ba0c368p+13808L }, + { -0x4.6551f788f1588b28p-4L, -0x7.69f3a55b24a9777p+428L, 0x3.6f8dc0f3c3d2cf44p+428L, 0x3.6f8dc0f3c3d2cf48p+428L }, + { 0x7.88f397834128293p-8L, 0x6.bf38fb4299638c08p-960L, 0x4.849080f3ab11f818p-964L, 0x4.849080f3ab11f82p-964L }, + { -0x1.b55f0bbc95324732p-4L, 0x1.b42e17120776fe52p-13916L, -0x4.70f2c0a6bc44465p-13920L, -0x4.70f2c0a6bc444648p-13920L }, + { 0x3.32c5f1314a8c6dap-4L, -0x1.bdb2f33681f41db6p+12272L, -0x7.52da7e0b1bed5968p+12268L, -0x7.52da7e0b1bed596p+12268L }, + { -0x3.36905b81e589d9e8p-4L, 0x3.d8dded4726d3fb34p+784L, -0x1.3e840521ab659a96p+784L, -0x1.3e840521ab659a94p+784L }, + { 0x2.f78a13ae770dc39cp-4L, -0x3.cf1123d327fd9024p-9600L, -0xe.f4c0070f6303241p-9604L, -0xe.f4c0070f630324p-9604L }, + { -0x3.5c99081287a8051p-4L, -0x1.70700e3356c86b3cp+7752L, 0x7.d5e5870a6e18d73p+7748L, 0x7.d5e5870a6e18d738p+7748L }, + { 0xa.dd6d280bcc33172p-8L, -0xf.1ff631d3dfa8c85p+4928L, -0xe.82fa32a3cab9bcep+4924L, -0xe.82fa32a3cab9bcdp+4924L }, + { -0x2.ecbb3c2ebebf283p-4L, -0x3.212b343a660ecbb4p+4672L, 0xe.953534ceecbfcf2p+4668L, 0xe.953534ceecbfcf3p+4668L }, + { 0x3.75380852cb5eb234p-4L, -0x2.df562212c19c9528p+12736L, -0xc.f92b33893bdc2ap+12732L, -0xc.f92b33893bdc29fp+12732L }, + { -0x1.ad74e73c3fab3c44p-4L, -0x1.a457ed324f1b85bp-8776L, 0x4.32b38b6b976e91b8p-8780L, 0x4.32b38b6b976e91cp-8780L }, + { 0x2.18c8d7808e9812b8p-144L, 0x5.0f40c3a5a98fe708p-14212L, 0xf.4e3924951dac17fp-14356L, 0xf.4e3924951dac18p-14356L }, + { -0x9.5d0b284b6a68ac4p-184L, -0x3.68104ae46b7bcf6p+12464L, 0x2.e045d02aa9b47858p+12284L, 0x2.e045d02aa9b4785cp+12284L }, + { 0x2.2261e8b5a73122bcp-4L, 0x1.39e07d457c893d2p-4904L, 0x3.8b3a68313dff915p-4908L, 0x3.8b3a68313dff9154p-4908L }, + { -0x3.e7f8b8fdf0027474p-4L, 0xb.8b615ebfce42d08p-1688L, -0x4.a95fab921aa3a9c8p-1688L, -0x4.a95fab921aa3a9cp-1688L }, + { 0x2.90731457099d1b3p-4L, 0x3.41f7f39a30b3898cp-8352L, 0xb.2d9667a84b2a4dbp-8356L, 0xb.2d9667a84b2a4dcp-8356L }, + { -0x1.090c8ddde72dd1a2p-4L, 0x1.6a8b36c84fd8d976p+12300L, -0x2.2fd80d7e66d3f60cp+12296L, -0x2.2fd80d7e66d3f608p+12296L }, + { 0x2.40b0eeedb834a1d4p-4L, 0x3.56b6f4120c52d84cp-10716L, 0xa.26da0df382c1052p-10720L, 0xa.26da0df382c1053p-10720L }, + { -0x1.a336b1480b20b424p-4L, 0x2.2ac2bc77bdfef9ccp+8860L, -0x5.66a4f7795a77dca8p+8856L, -0x5.66a4f7795a77dcap+8856L }, + { 0xe.db656802d11a281p-8L, -0x4.2e126b3484e7514p+13440L, -0x5.717346005231cffp+13436L, -0x5.717346005231cfe8p+13436L }, + { -0x1.c4b925adab67ae7ep-4L, 0x1.a15ba1a3fbe9dd4p-6564L, -0x4.68657bab4041a828p-6568L, -0x4.68657bab4041a82p-6568L }, + { 0x3.7586cb9442c45784p-4L, -0x7.713929beef89c638p-6972L, -0x2.19fb69e21ac718acp-6972L, -0x2.19fb69e21ac718a8p-6972L }, + { -0x2.fa71ba62a32a8b7p-4L, -0xa.936c0eb50eb5e37p-6908L, 0x3.24855b9f7f8ce32p-6908L, 0x3.24855b9f7f8ce324p-6908L }, + { 0x3.67490f5787dde48p-4L, 0xf.67432f04da27bbp-524L, 0x4.492e50d2f71cf588p-524L, 0x4.492e50d2f71cf59p-524L }, + { -0x2.97b9427d1d5c7c24p-4L, 0x1.57a9f87e42d057eep+5708L, -0x5.7a6c8388322303c8p+5704L, -0x5.7a6c8388322303cp+5704L }, + { 0x1.33ef1ab5c6634e46p-4L, 0x1.d8999e72af335708p+9564L, 0x3.16c5444800c64aa8p+9560L, 0x3.16c5444800c64aacp+9560L }, + { -0xa.9a5ba7d8b6734cdp-8L, 0xa.671a839c0039ab8p-5508L, -0xa.284bae12c6dde0dp-5512L, -0xa.284bae12c6dde0cp-5512L }, + { 0xe.181100f05f0394cp-8L, -0x3.f3e2c4d22523780cp-416L, -0x4.e3ca00e35b39c898p-420L, -0x4.e3ca00e35b39c89p-420L }, + { -0x1.66f888b96b8e00e8p-4L, -0x3.8ded010cb7762338p+10300L, 0x7.867a91379ede7e08p+10296L, 0x7.867a91379ede7e1p+10296L }, + { 0x4.a6c0029c00b96fep-4L, -0x4.e87d73d329cb332p+11216L, -0x1.ce989e2a560b54b2p+11216L, -0x1.ce989e2a560b54bp+11216L }, + { -0x3.5843155f8dc36dfp-4L, -0xa.15334aafc6d22b9p-13476L, 0x3.6951d7122f8daafp-13476L, 0x3.6951d7122f8daaf4p-13476L }, + { 0x4.22701b25d6c80c3p-4L, -0x5.126eff0187a3803p-9272L, -0x1.ae8f4e7823ebfeeep-9272L, -0x1.ae8f4e7823ebfeecp-9272L }, + { -0x1.a7a0556e6f951196p-4L, 0x8.0be412ff866338fp+4496L, -0x1.44704cea9eeb28f4p+4496L, -0x1.44704cea9eeb28f2p+4496L }, + { 0x1.36be53940221672p-172L, -0x7.194c9b043451bfep+4704L, -0xc.6e75e23d8e56928p+4532L, -0xc.6e75e23d8e56927p+4532L }, + { -0x1.f30afcd111913c04p-156L, 0x9.b3ff5c8d9b3d3acp+2792L, -0x1.b49eb9a0eb4c908cp+2640L, -0x1.b49eb9a0eb4c908ap+2640L }, + { 0x3.140ad6b1e9922ec4p-4L, 0x3.bff4c5061256d8ccp-12384L, 0xf.3b1c7d17ba2c0edp-12388L, 0xf.3b1c7d17ba2c0eep-12388L }, + { -0x3.9ede658d4493b08p-4L, 0x2.f71c7b1bb45c5604p-12156L, -0x1.18f7f35b0c252984p-12156L, -0x1.18f7f35b0c252982p-12156L }, + { 0x2.4ddf39d02ae29214p-4L, -0x1.d106f81605905eeap+7920L, -0x5.a433bd60909bf0bp+7916L, -0x5.a433bd60909bf0a8p+7916L }, + { -0x1.c546cdac360a9cp-4L, -0x7.bad48611f3e40dap+7376L, 0x1.4ed08a35cb87ed0ep+7376L, 0x1.4ed08a35cb87ed1p+7376L }, + { 0x1.a15d4c117c202388p-4L, 0xd.0e541be4b24c664p+12760L, 0x1.d3e2699c368b4f18p+12760L, 0x1.d3e2699c368b4f1ap+12760L }, + { -0x7.16658416ee8125e8p-8L, 0x1.62dc2caf9f8fdad6p-5160L, -0xe.5fa5d852e85667p-5168L, -0xe.5fa5d852e85666fp-5168L }, + { 0xd.0bad0960312abe4p-12L, 0x1.f48ad8b59f54a95cp+192L, 0x2.4bda7bbd2000768p+184L, 0x2.4bda7bbd20007684p+184L }, + { -0x3.f1bddc60ebe5c3ap-4L, 0x8.063bbdb884d4c9fp-7972L, -0x3.46dc3e1d744ccba8p-7972L, -0x3.46dc3e1d744ccba4p-7972L }, + { 0xe.8a2046b2bb94931p-8L, 0x7.322c00fd114c6b78p+5120L, 0x9.2d030614c8ad44fp+5116L, 0x9.2d030614c8ad45p+5116L }, + { -0x3.7454ee5b08c8cb7cp-4L, -0x3.642f824f3db6287cp+11984L, 0x1.30a3de1a3b5cc8aap+11984L, 0x1.30a3de1a3b5cc8acp+11984L }, + { 0x3.b7e07d72b90e939p-4L, 0x4.8d8e9330b67dc858p-1260L, 0x1.5f5eb6ed8b9c0ed4p-1260L, 0x1.5f5eb6ed8b9c0ed6p-1260L }, + { -0xc.f22d7bfd55c6c94p-8L, 0x4.64873d3f77ee2338p-2776L, -0x5.430a59c679c81728p-2780L, -0x5.430a59c679c8172p-2780L }, + { 0x2.50df0103c304075cp-4L, -0x7.b4b24f138f39278p+14856L, -0x1.80b99699a7f61822p+14856L, -0x1.80b99699a7f6182p+14856L }, + { -0x3.1f0b53ee6296bd78p-4L, -0x7.0f43afd6ab41b8c8p-13572L, 0x2.35d20bba726b6ae8p-13572L, 0x2.35d20bba726b6aecp-13572L }, + { 0x2.6725591bb528453cp-4L, 0x1.ce864eaac5f98256p-8564L, 0x5.d5dc4cda5a5180a8p-8568L, 0x5.d5dc4cda5a5180bp-8568L }, + { -0x3.2290e7cdb1817facp-4L, 0x3.4d8a9f94b9a431bcp-11728L, -0x1.0a06e1a9cc7457eap-11728L, -0x1.0a06e1a9cc7457e8p-11728L }, + { 0x3.8b99e9b78a041538p-4L, -0x3.b23e0cc201793b9p+6472L, -0x1.113a80c6eb278128p+6472L, -0x1.113a80c6eb278126p+6472L }, + { -0x1.1f197acd86bd6b08p-4L, -0x1.f1665c655caaaf4ap-6144L, 0x3.425e0b5214f9cd34p-6148L, 0x3.425e0b5214f9cd38p-6148L }, + { 0xf.ed161e95b0ae352p-8L, -0x8.be9a4b8e5552e1cp-8976L, -0xc.2eacd7db48ff243p-8980L, -0xc.2eacd7db48ff242p-8980L }, + { -0x3.6a4be64691ce57a4p-4L, -0x5.839b606e3a436a78p-6768L, 0x1.e8f825b15269b6cap-6768L, 0x1.e8f825b15269b6ccp-6768L }, + { 0x5.00c1d6bp-16416L, -0x4.b497e93cf288163p+9424L, -0x2.1f671dd90f010a24p-6988L, -0x2.1f671dd90f010a2p-6988L }, + { -0x2.5a584197e5510fc4p-132L, -0x1.1772e32ccdc2478p+14528L, 0x3.b498edc574c550ccp+14396L, 0x3.b498edc574c550dp+14396L }, + { 0x2.f851cb35a14097acp-4L, -0xa.7268d9e3b2e61bap-12600L, -0x2.90f65da0448e38f8p-12600L, -0x2.90f65da0448e38f4p-12600L }, + { -0x4.6d56dca19ebe3708p-4L, -0x2.526a2db40e4a133p+760L, 0x1.15c884d416e79d9cp+760L, 0x1.15c884d416e79d9ep+760L }, + { 0x2.fe2658a2c8078de8p-4L, 0x1.0d699d587ebc0e5p-10464L, 0x4.2a59bbf556de3138p-10468L, 0x4.2a59bbf556de314p-10468L }, + { -0x3.0fe4a68e65c41494p-4L, -0x1.7173155e4bd10df2p+1836L, 0x7.13952436db99bf8p+1832L, 0x7.13952436db99bf88p+1832L }, + { 0x4.033ea3caa0b5f698p-4L, -0x6.03ab20e0280437cp-188L, -0x1.f111dcaf19286f9p-188L, -0x1.f111dcaf19286f8ep-188L }, + { -0x4.5b0056b6b6068878p-4L, -0xc.6497d33070a9a97p+5684L, 0x5.ae614b07dc079ecp+5684L, 0x5.ae614b07dc079ec8p+5684L }, + { 0x1.82adf1f869ababbcp-4L, -0x1.123ccd14ea237d04p-7084L, -0x2.3b0d91c0089d65e4p-7088L, -0x2.3b0d91c0089d65ep-7088L }, + { -0x2.5b451d0b82180d44p-4L, 0x6.8a58d91ee307a548p-8008L, -0x1.80ddcbdeb9c0f3bap-8008L, -0x1.80ddcbdeb9c0f3b8p-8008L }, + { 0x2.e352f84376e4f1d8p-4L, 0x5.8248426003120498p-7260L, 0x1.519dfeeb985eb048p-7260L, 0x1.519dfeeb985eb04ap-7260L }, + { -0xa.7b393feb80e94efp-12L, 0x2.ef48748849de0554p-12820L, -0x2.c6eff255a859ad08p-12828L, -0x2.c6eff255a859ad04p-12828L }, + { 0x1.5fbb3b2cb9a73a0ap-4L, -0x4.a27aba12e1fe1ef8p+10496L, -0x8.d048b795b632ed1p+10492L, -0x8.d048b795b632edp+10492L }, + { -0x3.809836ef223bfdacp-4L, 0x2.0d96044152595614p-8280L, -0xb.b533a267a420e5fp-8284L, -0xb.b533a267a420e5ep-8284L }, + { 0x2.71939b3f2db2b26p-4L, -0xd.d36dfd2744533a6p+10580L, -0x2.d5c54067b4f1a7ep+10580L, -0x2.d5c54067b4f1a7dcp+10580L }, + { -0x3.6b9ad80ebf1deb08p-4L, 0x6.7a681b6bb071e288p+13136L, -0x2.3f6e3d82be3f2ad4p+13136L, -0x2.3f6e3d82be3f2adp+13136L }, + { 0x2.9afe8631c4e5ce7p-4L, -0x3.83b2bda6ed10fea8p+4784L, -0xc.3d274a1edea87ebp+4780L, -0xc.3d274a1edea87eap+4780L }, + { -0x2.c4c0d66a1b99c3c8p-4L, 0x2.5b1e1eead3bb2cacp+13080L, -0xa.550eea778396ce3p+13076L, -0xa.550eea778396ce2p+13076L }, + { 0x4.08187131d98288b8p-4L, 0xc.30a692d385849d1p+3460L, 0x3.f3bcf1eaed28f854p+3460L, 0x3.f3bcf1eaed28f858p+3460L }, + { -0x2.ef6cdbc058cd31ep-4L, 0x2.75c1df05fa79e34p-5496L, -0xb.822f6abf9319caap-5500L, -0xb.822f6abf9319ca9p-5500L }, + { 0xc.80ee642b1a4020bp-8L, -0xc.f511a8dcdc0ce5ep+13800L, -0xe.43506254711d49bp+13796L, -0xe.43506254711d49ap+13796L }, + { -0x2.0992fd9466d2b79p-4L, -0x5.3b81e7664b8716fp+3608L, 0x1.0738060d1d9ad53ap+3608L, 0x1.0738060d1d9ad53cp+3608L }, + { 0x4.7e5d88ep-16416L, 0x4.b21a682b16590228p-5704L, 0x0p+0L, 0x8p-16448L }, + { -0x3.70fb6523fc99c194p-176L, 0xc.8fca8d5dd6ce8cep+9336L, -0x3.e5dc145add1549cp+9164L, -0x3.e5dc145add1549bcp+9164L }, + { 0x3.a722ebee85536cdp-4L, -0x7.e92da929dfeccb3p-11692L, -0x2.58ce8b42e26f75cp-11692L, -0x2.58ce8b42e26f75bcp-11692L }, + { -0x3.53ab833486c08db8p-4L, -0x8.ec1b59a9caa6303p-7400L, 0x3.00224e3c6217e70cp-7400L, 0x3.00224e3c6217e71p-7400L }, + { 0x4.9487cc987ce18b6p-4L, 0x1.b43405b727b9b4ecp+660L, 0x9.e6c239cbd68f84cp+656L, 0x9.e6c239cbd68f84dp+656L }, + { -0xe.32da65364dfac0fp-8L, -0x1.a0b348b4888fa2fcp-124L, 0x2.24daad6dfa91c368p-128L, 0x2.24daad6dfa91c36cp-128L }, + { 0x2.31765e800ee61554p-4L, 0xd.bd9f34293d3d29bp+4316L, 0x2.8bea4d125ba3dd28p+4316L, 0x2.8bea4d125ba3dd2cp+4316L }, + { -0x7.e8d207888e10bb28p-8L, 0xf.1545995a9604c33p+4440L, -0xa.ed3b79e2b24ae3cp+4436L, -0xa.ed3b79e2b24ae3bp+4436L }, + { 0x2.0dbde28b26dc5474p-4L, -0x1.d9f5b1f814163e0ep+3520L, -0x5.292de7ec7fde3dbp+3516L, -0x5.292de7ec7fde3da8p+3516L }, + { -0x2.5da10be7bc76adbcp-4L, 0xe.9c1364eb8db9e71p+11700L, -0x3.5f577bc6db6ff75cp+11700L, -0x3.5f577bc6db6ff758p+11700L }, + { 0x1.7fb27a800f7431d8p-4L, 0x3.fe39a5a5f5c97a9p+3280L, 0x8.40e81d2da1bfc96p+3276L, 0x8.40e81d2da1bfc97p+3276L }, + { -0x3.bb9fab7278c86f2p-4L, -0xf.0cbb72ff70654d3p-12084L, 0x5.c4ab2766bb87bf6p-12084L, 0x5.c4ab2766bb87bf68p-12084L }, + { 0x3.aa809df3dbec6abp-4L, 0x2.15e22591ab1c856p+7060L, 0x9.ee6cd49285b6905p+7056L, 0x9.ee6cd49285b6906p+7056L }, + { -0x1.248726fb26304a8ep-4L, 0xf.6e6ebaa083c4cd3p-2404L, -0x1.a64bcf5800dc981p-2404L, -0x1.a64bcf5800dc980ep-2404L }, + { 0x3.e5c9dd1ff3793c6cp-4L, -0xe.77c56c623d0f0eep-11552L, -0x4.8cec2abe53411658p-11552L, -0x4.8cec2abe5341165p-11552L }, + { -0x9.e1fb01951741bb8p-12L, 0x3.dc9d2acf270903a8p+14376L, -0x3.7207777a5f25e4bcp+14368L, -0x3.7207777a5f25e4b8p+14368L }, + { 0x2.d447d6b5e5ce3cc8p-4L, 0xc.0731d6f892df414p+2464L, 0x2.d34ea5652b7493e8p+2464L, 0x2.d34ea5652b7493ecp+2464L }, + { -0x3.ed070cb292baae74p-4L, 0x1.f5bda0c135772ea8p+5972L, -0xc.bc8d2aeea6f8d93p+5968L, -0xc.bc8d2aeea6f8d92p+5968L }, + { 0x4.45d277b639fcf9c8p-4L, 0x7.75d18c49b089dc88p-1124L, 0x2.8c2501bc216e5db4p-1124L, 0x2.8c2501bc216e5db8p-1124L }, + { -0x4.9e8c6ba757e6aa9p-4L, 0xd.170086ac1893a93p+13928L, -0x6.6ef8d754645a469p+13928L, -0x6.6ef8d754645a4688p+13928L }, + { 0x2.3c7efc4a74a8b844p-4L, 0x2.089221e2807b8ae8p+13656L, 0x6.240ef782a887ef18p+13652L, 0x6.240ef782a887ef2p+13652L }, + { -0x3.4b58e3e6f3f4be84p-4L, -0x7.011c78290d122728p+12196L, 0x2.546305cf20c52e78p+12196L, 0x2.546305cf20c52e7cp+12196L }, + { 0x3.c013919270a9d0a8p-200L, -0x4.0e8c6ae1a53296c8p+7956L, -0x1.5f31af56e9407d08p+7760L, -0x1.5f31af56e9407d06p+7760L }, + { -0x1.f7dc69dp-16416L, -0x1.bf51089c520b29b4p+4664L, 0x4.f62a54dd5dd4a83p-11752L, 0x4.f62a54dd5dd4a838p-11752L }, + { 0x1.e00da7403dc86138p-4L, -0x5.35b41b797fb9331p-3908L, -0xd.53e4f12ca294a6p-3912L, -0xd.53e4f12ca294a5fp-3912L }, + { -0x2.bf8b03274d13363cp-4L, -0x1.05cdd981abf77a14p+1464L, 0x4.72e3f9ff62128ed8p+1460L, 0x4.72e3f9ff62128eep+1460L }, + { 0x3.d7776260cc65e86p-4L, 0xb.13430c035931444p-3664L, 0x3.703d2634906f9538p-3664L, 0x3.703d2634906f953cp-3664L }, + { -0xf.d2d322382421f69p-8L, -0x8.f017932d188a998p+2680L, 0xd.29ddb607a558484p+2676L, 0xd.29ddb607a558485p+2676L }, + { 0x1.1da304350ac720aap-4L, 0x6.36b4ef636b98ac98p+10536L, 0x9.ab3f04c20130e66p+10532L, 0x9.ab3f04c20130e67p+10532L }, + { -0x4.a32b02b37caedc88p-4L, 0x5.4e587c75d5a6bfcp+14104L, -0x2.9eb7d7a4081dba88p+14104L, -0x2.9eb7d7a4081dba84p+14104L }, + { 0x1.5ac66b5ac9bb06fcp-4L, -0x3.c7ea3c3c2b39e2c8p-5248L, -0x7.17bcb1e2b4044dp-5252L, -0x7.17bcb1e2b4044cf8p-5252L }, + { -0x4.861b827cdb0400cp-4L, 0x1.d7dd30f75b264db4p-6584L, -0xe.23a4a8fbc48fd9fp-6588L, -0xe.23a4a8fbc48fd9ep-6588L }, + { 0x8.86257636294381fp-8L, 0xe.8f9244700df6721p+4408L, 0xb.02557c2fc89289bp+4404L, 0xb.02557c2fc89289cp+4404L }, + { -0x1.0dfbe47a9aca7786p-4L, 0x5.e2a8926a1f2a69f8p-2832L, -0x9.436d5defb285aa4p-2836L, -0x9.436d5defb285aa3p-2836L }, + { 0x2.bff85b9860bb1c0cp-4L, -0x1.8989c2560de848e8p-2992L, -0x5.a0b9bd60c6e9415p-2996L, -0x5.a0b9bd60c6e94148p-2996L }, + { -0x2.43f55447649b8c24p-4L, -0x1.b21f1e71fce5162ep-9792L, 0x5.f9f03cfb02f136b8p-9796L, 0x5.f9f03cfb02f136cp-9796L }, + { 0xd.df18cea4044bb26p-8L, -0x6.a546c7e5065f0158p+12584L, -0x8.184130740ad26bep+12580L, -0x8.184130740ad26bdp+12580L }, + { -0x2.0aa382fea7dd8ed4p-4L, 0x1.922b0febfe6b22bep+14300L, -0x4.f33585b409b249b8p+14296L, -0x4.f33585b409b249bp+14296L }, + { 0x1.9f8df2c594f5aba2p-4L, 0xa.a22cceb5d16a7b9p+12368L, 0x1.7b7ed32a30c1340ep+12368L, 0x1.7b7ed32a30c1341p+12368L }, + { -0x2.3a7805cc42052c88p-4L, 0x6.0c375211e7de2b68p-13748L, -0x1.4efed1a1d060daf8p-13748L, -0x1.4efed1a1d060daf6p-13748L }, + { 0xb.98b5acf06c53957p-8L, 0xa.c01d2e9cf20bab2p-408L, 0xa.fe7242406c2e29dp-412L, 0xa.fe7242406c2e29ep-412L }, + { -0x3.b426327377c1e0ccp-8L, -0x7.c0b1a87701c336f8p+4900L, 0x2.9ba51806e9e0d1c4p+4896L, 0x2.9ba51806e9e0d1c8p+4896L }, + { 0x2.32a92ffd519efa3p-4L, -0x1.ba7195161943bbbep-5192L, -0x5.2295fa8174e88c5p-5196L, -0x5.2295fa8174e88c48p-5196L }, + { -0x2.494a01edd418deacp-4L, 0x6.693114f18c78632p+10664L, -0x1.6d165465955afcb4p+10664L, -0x1.6d165465955afcb2p+10664L }, + { 0x3.36cc1fd8p-16416L, -0x3.731a5226115dd018p-13876L, -0x8p-16448L, -0x0p+0L }, + { -0x5.a44d891b492c118p-64L, 0xb.69fb96dbb13b38cp-1084L, -0x5.ce7362af963c8f38p-1144L, -0x5.ce7362af963c8f3p-1144L }, + { 0x3.474c4807a8ad6228p-4L, -0x2.f3562babd4b5f03cp-12580L, -0xc.b2050e940966a45p-12584L, -0xc.b2050e940966a44p-12584L }, + { -0x1.72da05f3ba83570cp-4L, 0x2.bd74f98cb810cbf8p-3608L, -0x6.00abe3e58945abf8p-3612L, -0x6.00abe3e58945abfp-3612L }, + { 0x3.03355b3ad678a4e4p-4L, 0x2.fcacda0bf497fcdp+624L, 0xb.e4fbcf489c92111p+620L, 0xb.e4fbcf489c92112p+620L }, + { -0x4.87b616543e6d68f8p-4L, -0x1.5aa2807140fcb66ep-5712L, 0xa.6762b975babc4a7p-5716L, 0xa.6762b975babc4a8p-5716L }, + { 0x3.3eef25ea1d0cb1a4p-4L, 0x8.77ef4346014be03p+2668L, 0x2.41b30237313d1594p+2668L, 0x2.41b30237313d1598p+2668L }, + { -0x4.abe5ee4fb3e5bap-4L, -0x9.ad41850d220d88cp+12620L, 0x4.d1f38825ce2a945p+12620L, 0x4.d1f38825ce2a9458p+12620L }, + { 0x5.a5eb695ee8c9932p-8L, 0x1.d13834b0342791d4p-3780L, 0xe.a5a311a3e533135p-3788L, 0xe.a5a311a3e533136p-3788L }, + { -0x3.57d686c40d552838p-4L, -0xf.0b6de12e05c3635p-8368L, 0x5.165c21cb97c896d8p-8368L, 0x5.165c21cb97c896ep-8368L }, + { 0x3.02fa76adc4b3f734p-4L, 0x2.c8a8a9ca263fb34p-1104L, 0xb.1512e047c64d14bp-1108L, 0xb.1512e047c64d14cp-1108L }, + { -0x2.e4dfe9c3785c81f4p-4L, 0x2.47670d17c1a6b908p+7296L, -0xa.7ee8efc4c4a9f53p+7292L, -0xa.7ee8efc4c4a9f52p+7292L }, + { 0x9.aaf264c27c54e8ap-8L, 0xb.54e2e10eee029ffp-4480L, 0x9.b23353124c7f80ap-4484L, 0x9.b23353124c7f80bp-4484L }, + { -0x1.47d8c6c7e55c7a26p-4L, 0x1.2ae861e0c614f7b8p+3208L, -0x2.3f9d8ce1381508fp+3204L, -0x2.3f9d8ce1381508ecp+3204L }, + { 0x3.cb86413e9654e6cp-8L, -0x1.8722bfac85135608p+3816L, -0x8.4dc558bd3004cd6p+3808L, -0x8.4dc558bd3004cd5p+3808L }, + { -0x2.b06c6bf6c50a6bfcp-4L, 0x3.666a36ff2e60f2bcp+12728L, -0xe.7119a8d1ccc016p+12724L, -0xe.7119a8d1ccc015fp+12724L }, + { 0x3.47ce25adf55a2814p-4L, 0x7.ddb836a97dd546bp+10988L, 0x2.1dd4bf63fa5a9bccp+10988L, 0x2.1dd4bf63fa5a9bdp+10988L }, + { -0x9.d038f0be8c9445p-8L, 0x2.cb89c09be031f264p-4624L, -0x2.859a5e7613fdf99cp-4628L, -0x2.859a5e7613fdf998p-4628L }, + { 0x5.f4040498e9510358p-8L, -0xe.8e6b01ce80d9a3bp+268L, -0x7.b965fce804203578p+264L, -0x7.b965fce80420357p+264L }, + { -0x3.9bec29ae6836c004p-4L, 0x3.349abf15c61637ccp-6152L, -0x1.2ea0fb97798d6ffcp-6152L, -0x1.2ea0fb97798d6ffap-6152L }, + { 0x3.1cb0194881148be8p-4L, -0xd.f8498b43249707dp-3144L, -0x3.950056a5b35f5a1cp-3144L, -0x3.950056a5b35f5a18p-3144L }, + { -0x2.bb9b8d7aa3c0d0a4p-4L, 0x5.7723b746db2d4dep-9424L, -0x1.7a10aa106c1d1108p-9424L, -0x1.7a10aa106c1d1106p-9424L }, + { 0xe.4d878fb87fd395ap-12L, 0x3.4f9956a9f16bc38p+2616L, 0x4.4337165130e7f47p+2608L, 0x4.4337165130e7f478p+2608L }, + { -0x1.1630a82965507a32p-16L, 0xa.2e28946ae2eae99p+6956L, -0xf.f5d543fa5f7a7cbp+6940L, -0xf.f5d543fa5f7a7cap+6940L }, + { 0x3.59c0a36418e9a6dp-4L, -0x2.1ad5b8410a86465cp-13676L, -0x9.3ce405e344231efp-13680L, -0x9.3ce405e344231eep-13680L }, + { -0x2.3acdbdd2877849ep-8L, 0x4.84f0a846883e7a18p-6060L, -0xe.99ec6628631da5bp-6068L, -0xe.99ec6628631da5ap-6068L }, + { 0x2.4706917d5d92e68p-4L, 0x3.1e5765ddcaca8e8cp-11800L, 0x9.946873401fa60ap-11804L, 0x9.946873401fa60a1p-11804L }, + { -0x3.c87f60de0535481cp-4L, -0xf.51c1e48dde26436p+1780L, 0x5.f65dcfd39a0ece18p+1780L, 0x5.f65dcfd39a0ece2p+1780L }, + { 0x3.7dc1ea97cf0b5704p-4L, 0xc.90a3dd049ad490bp+7836L, 0x3.93f379f1866fdb2p+7836L, 0x3.93f379f1866fdb24p+7836L }, + { -0x1.f798a53251ee9fbp-4L, -0xe.75c48de977feda3p-5476L, 0x2.bc9e9decff0f5cb4p-5476L, 0x2.bc9e9decff0f5cb8p-5476L }, + { 0xb.aa65757ee31da3p-8L, -0x5.4d142559265fe498p-6132L, -0x5.73e6d4277632f548p-6136L, -0x5.73e6d4277632f54p-6136L }, + { -0x4.6c8e0d8c9dc60d18p-4L, 0x3.c991984ee0203824p+14956L, -0x1.c4bb15413b7086ecp+14956L, -0x1.c4bb15413b7086eap+14956L }, + { 0x1.f5fd4ee6b1f86f46p-4L, -0xd.fee89bfeb4e4785p+3032L, -0x2.55958e192187d838p+3032L, -0x2.55958e192187d834p+3032L }, + { -0x2.5fc6fbe9f0d78b54p-4L, 0x1.afcc807af3d6794ap-7248L, -0x6.40ed6a17958f5abp-7252L, -0x6.40ed6a17958f5aa8p-7252L }, + { 0x2.451ffb9b70940624p-4L, -0x1.37f52061877f3bccp-11700L, -0x3.bb5eb351baf17c7cp-11704L, -0x3.bb5eb351baf17c78p-11704L }, + { -0x4.95757561d2aaa5p-4L, -0x1.3d9fcaab7bbc9c6ep-2868L, 0x9.aae38ba996d3919p-2872L, 0x9.aae38ba996d391ap-2872L }, + { 0x1.7d04bff149a7d55cp-4L, -0xf.61c71955bf9a0dap+7880L, -0x1.f94e4939cb229d26p+7880L, -0x1.f94e4939cb229d24p+7880L }, + { -0x4.47b25b1314f91ddp-4L, 0x1.f3a3c57544812a32p-7436L, -0xe.0645285005f95b2p-7440L, -0xe.0645285005f95b1p-7440L }, + { 0x4.5b48f6c753552e7p-4L, 0x7.f9951c9fa3a3d26p-14636L, 0x2.c54b2a5dc4af4df4p-14636L, 0x2.c54b2a5dc4af4df8p-14636L }, + { -0x2.755a177a9bcd19ecp-4L, 0x2.8f368cebe2a73544p+9496L, -0x9.db16676f3eeb8b6p+9492L, -0x9.db16676f3eeb8b5p+9492L }, + { 0x4.74f58fd716847278p-8L, 0xb.5105baafec9e23fp-1216L, 0x4.8234ae72b3afbcap-1220L, 0x4.8234ae72b3afbca8p-1220L }, + { -0xf.3a54ecf20e1f38dp-8L, -0x1.cb2ddc2e80a14976p+11248L, 0x2.8a0435ff27f289fp+11244L, 0x2.8a0435ff27f289f4p+11244L }, + { 0x1.6e76573c811c0cc8p-4L, -0x6.890bc5e24bb11168p-1700L, -0xc.ed43d94a59956a1p-1704L, -0xc.ed43d94a59956ap-1704L }, + { -0x1.cc0d76d858214824p-4L, 0x4.9d780438f01ffb18p+360L, -0xc.b13775b6b72f16cp+356L, -0xc.b13775b6b72f16bp+356L }, + { 0x2.975f7098p-16416L, -0x1.7c27bae5b714e156p+9888L, -0x5.8d31808ab8fc3f1p-6528L, -0x5.8d31808ab8fc3f08p-6528L }, + { -0x2.84c6bb3c78ad39p-156L, 0x2.187b034003e64b7cp-1008L, -0x7.9d6286f490256558p-1164L, -0x7.9d6286f49025655p-1164L }, + { 0x1.3294feaed50f486cp-4L, 0x2.ed77680ef406a86cp-5816L, 0x4.e0b890b56bc98c3p-5820L, 0x4.e0b890b56bc98c38p-5820L }, + { -0x4.1adda118b2b67118p-4L, -0x1.1da0ee568b65fe28p-11272L, 0x7.a2a8b5ea7803f64p-11276L, 0x7.a2a8b5ea7803f648p-11276L }, + { 0x2.77501a3949fd1c3cp-8L, 0xa.f6abbcf12cd419p-12544L, 0x2.6d1bb5bd9453001cp-12548L, 0x2.6d1bb5bd9453002p-12548L }, + { -0x3.7d7a59482ce42cb8p-4L, 0x1.751b58122d75b98ap-11080L, -0x8.474a285e08f1966p-11084L, -0x8.474a285e08f1965p-11084L }, + { 0x1.f807f393d863f41ep-4L, 0xa.fc78b24fd33203p+1300L, 0x1.d6e2db24a50f8948p+1300L, 0x1.d6e2db24a50f894ap+1300L }, + { -0x3.40dcfa4088fed5fp-4L, -0xe.e3fdb321f26f9c4p+13020L, 0x4.e22a8f2ea6bab6a8p+13020L, 0x4.e22a8f2ea6bab6bp+13020L }, + { 0x2.2c85d17e3ac7521p-4L, -0xf.8890f12fb883eafp+1744L, -0x2.dae202adf96b494p+1744L, -0x2.dae202adf96b493cp+1744L }, + { -0xe.60ec2578a9c34f3p-8L, 0xb.6de7e775308bfap+3896L, -0xf.401f5a2820d2433p+3892L, -0xf.401f5a2820d2432p+3892L }, + { 0xa.ceb454639d49191p-8L, 0xb.214592ce214ecfep+2692L, 0xa.9f939fed0fd998cp+2688L, 0xa.9f939fed0fd998dp+2688L }, + { -0x6.d08f79b55a47424p-8L, 0x3.405b3c3e3f6864cp+6040L, -0x2.066381858f2491acp+6036L, -0x2.066381858f2491a8p+6036L }, + { 0xb.58fe4c3ae76ed36p-8L, -0x3.71ed0565cf0a82f8p-3000L, -0x3.72f5022d0c286c9cp-3004L, -0x3.72f5022d0c286c98p-3004L }, + { -0x3.7ef417dcb2ad04fp-4L, -0x1.989fd2c40d16b72ep+11400L, 0x9.15614e994d5f1eep+11396L, 0x9.15614e994d5f1efp+11396L }, + { 0x2.773887c3a113544p-4L, -0x1.317ad55b9bdb3828p+5680L, -0x3.f2a82f605122f56cp+5676L, -0x3.f2a82f605122f568p+5676L }, + { -0x2.4141773c8bf242b8p-4L, -0xc.e4018849b76a23ap-6468L, 0x2.d33684b6ec2dc264p-6468L, 0x2.d33684b6ec2dc268p-6468L }, + { 0x3.adfdb601b76362f4p-4L, -0x7.03e0d7aa253797dp+10148L, -0x2.184ee92bef09f62cp+10148L, -0x2.184ee92bef09f628p+10148L }, + { -0x1.82b638b5edf2eadp-4L, -0xd.8e0fec8304331dep-2872L, 0x1.f07932a2326e2cb6p-2872L, 0x1.f07932a2326e2cb8p-2872L }, + { 0x3.114503e53e4715p-4L, -0x3.7c55d418348e7ec8p+6688L, -0xe.1cc12794f6aa77cp+6684L, -0xe.1cc12794f6aa77bp+6684L }, + { -0x2.2c7255ce8e0f4f9p-8L, 0x9.0de4b7a3cab1a87p+11120L, -0x1.c83a5890fd2868f2p+11116L, -0x1.c83a5890fd2868fp+11116L }, + { 0x4.ab95d9c4f778dd8p-4L, -0x1.27dd0ddd53988dd4p+628L, -0x6.d512169b928744b8p+624L, -0x6.d512169b928744bp+624L }, + { -0x5.593dab1fc941b63p-8L, 0x7.cba30673cf34e1ep+5956L, -0x3.cca43ab5aa4168d8p+5952L, -0x3.cca43ab5aa4168d4p+5952L }, + { 0x5.6072ba1p-16416L, -0x6.a13f4e0f825a5edp+10340L, -0x3.36d910a4c3e979d8p-6072L, -0x3.36d910a4c3e979d4p-6072L }, + { -0x3.2fe0a04p-16416L, -0x2.37749e13337ef694p+7896L, 0xa.311a8b6de7cbd63p-8520L, 0xa.311a8b6de7cbd64p-8520L }, + { 0x1.52e65c0c28e07afcp-4L, 0x7.11d091eb6c5e7f8p+12968L, 0xc.f8f6054ce2e09fep+12964L, 0xc.f8f6054ce2e09ffp+12964L }, + { -0x1.81ecf5c638b525dcp-4L, 0x1.233a57f1cc4d9d28p+5288L, -0x2.993f1f95e2f6901cp+5284L, -0x2.993f1f95e2f69018p+5284L }, + { 0x1.9a579596fe22accep-4L, -0xe.920450e2df4f23ep+12984L, -0x2.01c6d90f6cf53254p+12984L, -0x2.01c6d90f6cf5325p+12984L }, + { -0x2.357339367c8e7d0cp-4L, 0x6.f8c63462f2be0ffp-9208L, -0x1.7e848fd237f1492ep-9208L, -0x1.7e848fd237f1492cp-9208L }, + { 0x3.b0442b4fcd5e3a68p-4L, -0x6.b2da8740f690432p-11860L, -0x2.013a89ca88d8b8b8p-11860L, -0x2.013a89ca88d8b8b4p-11860L }, + { -0x2.973c8a33f43ce22p-4L, -0x1.40c22b6af128083cp+13388L, 0x5.1be67cad86a0b2b8p+13384L, 0x5.1be67cad86a0b2cp+13384L }, + { 0xc.71fa40b14fe60a5p-8L, -0xd.227d8e4d09d7251p+10336L, -0xe.646cd1236a17ed5p+10332L, -0xe.646cd1236a17ed4p+10332L }, + { -0x2.4b5c7f957978c8dcp-4L, 0x1.d0364f8078ede932p-4432L, -0x6.7a91bf8da9e1b3a8p-4436L, -0x6.7a91bf8da9e1b3ap-4436L }, + { 0xc.9e6826befd572b6p-8L, -0x4.35ecdac82f2a93c8p-10772L, -0x4.ad35c4fc10f2895p-10776L, -0x4.ad35c4fc10f28948p-10776L }, + { -0x1.99c78eacbd3c165cp-4L, -0x2.f570aceb61240648p-8960L, 0x7.32fbbe18c44de7f8p-8964L, 0x7.32fbbe18c44de8p-8964L }, + { 0x1.7c32a28ef3632bb6p-4L, 0xf.72e6996fd117ab3p-5888L, 0x1.fa74fbd79d515e86p-5888L, 0x1.fa74fbd79d515e88p-5888L }, + { -0x6.dfefda162cd8123p-8L, -0x1.67987c998364b8acp-8240L, 0xe.1f4baaf83c19e7bp-8248L, 0xe.1f4baaf83c19e7cp-8248L }, + { 0x1.e4a51bc43235ecccp-4L, -0x1.c45d9255aa8a035ap-8692L, -0x4.8fb7ec77333b0dep-8696L, -0x4.8fb7ec77333b0dd8p-8696L }, + { -0x2.5209ac099a829dcp-4L, 0x1.fa609acc51803e54p+10424L, -0x7.277bc27d907174bp+10420L, -0x7.277bc27d907174a8p+10420L }, + { 0x2.b266769ea2ada0bcp-4L, -0x3.a66d9b79239e456p+11364L, -0xd.1fd5b30e293c2c8p+11360L, -0xd.1fd5b30e293c2c7p+11360L }, + { -0x6.bec5f7d3b060d94p-8L, 0x1.47398ae3841dd2bcp+9232L, -0xc.9b04a2f88f16892p+9224L, -0xc.9b04a2f88f16891p+9224L }, + { 0x2.563eb303d8df1594p-4L, -0x2.cda72aaa85a7383cp-3376L, -0x8.d25687622b560eap-3380L, -0x8.d25687622b560e9p-3380L }, + { -0x3.19894f7cf9935508p-4L, -0x1.6864ac7cb86fcf1ep+11056L, 0x6.ff6e7770c8294bdp+11052L, 0x6.ff6e7770c8294bd8p+11052L }, + { 0x3.1975daa32c02ffep-4L, -0x4.3e136fbe7e156658p+8164L, -0x1.1572cd89e15a791ep+8164L, -0x1.1572cd89e15a791cp+8164L }, + { -0x3.65a7c9cfb4ec9ab8p-4L, -0x2.05a5de13b7dbf81cp-4648L, 0xb.23bea1415cf66bep-4652L, 0xb.23bea1415cf66bfp-4652L }, + { 0x5.0967e18p-16416L, -0xd.64b77ebba612778p+96L, -0x6.152b53b092754e88p-16316L, -0x6.152b53b092754e8p-16316L }, + { -0xc.6c68c8a4d570e25p-200L, -0x3.c05c0d3fc5741314p+9912L, 0x4.33ccc2e9096608dp+9716L, 0x4.33ccc2e9096608d8p+9716L }, + { 0x1.d63714ff39a598ecp-4L, -0x2.ca0aeb11ccacc8dp+10576L, -0x6.ff328ab531d34ad8p+10572L, -0x6.ff328ab531d34adp+10572L }, + { -0x3.e95c9e94baaf75ap-8L, 0x2.b37daf0e4cc15f5cp-6056L, -0xf.5c57a917b87be75p-6064L, -0xf.5c57a917b87be74p-6064L }, + { 0xd.21b0e96ae054bf4p-8L, -0x4.5ad7ee78e07d371p-2356L, -0x5.074bf1af42266298p-2360L, -0x5.074bf1af4226629p-2360L }, + { -0xc.9b1515d090b1ce3p-8L, -0x4.ada9d304af8d7fbp-5952L, 0x5.73fa016de999be4p-5956L, 0x5.73fa016de999be48p-5956L }, + { 0xe.b9d75b04d351c82p-8L, -0x3.85edaba407274158p+4628L, -0x4.8c6a7d6bd001b9c8p+4624L, -0x4.8c6a7d6bd001b9cp+4624L }, + { -0xd.34f3239dcc380fcp-8L, -0xc.06ad79f94cf62e7p+5852L, 0xe.b429eec27adfe9p+5848L, 0xe.b429eec27adfe91p+5848L }, + { 0x4.0c1e5626f9899408p-4L, 0x4.405bbb3021ac0c78p-3692L, 0x1.6215cccd7becd3a4p-3692L, 0x1.6215cccd7becd3a6p-3692L }, + { -0x7.9f4ff67b7c63b818p-8L, 0xa.5aabb9f03fd61adp+14208L, -0x7.39751aa043595f8p+14204L, -0x7.39751aa043595f78p+14204L }, + { 0x1.67e82d241b189066p-4L, -0x2.e37d4d68f3529cf4p-11492L, -0x5.9d9b8b0eb10abbb8p-11496L, -0x5.9d9b8b0eb10abbbp-11496L }, + { -0x4.38ba5d3e626fd8fp-8L, -0x3.172227f2cf0b9c64p-592L, 0x1.2fa8c214228a6956p-596L, 0x1.2fa8c214228a6958p-596L }, + { 0x3.02d0858fe476bc54p-4L, 0xa.26efe8211c025fp+4600L, 0x2.86845b1a66c4dc94p+4600L, 0x2.86845b1a66c4dc98p+4600L }, + { -0x1.7ec8305cbdb5012ap-4L, 0x1.737b8c40ef13706ap-8812L, -0x3.494ee73f4ccbe1cp-8816L, -0x3.494ee73f4ccbe1bcp-8816L }, + { 0x2.685b430bceda8654p-4L, 0x2.2f04308bb4c03ba8p+1352L, 0x7.10d31a9faf05516p+1348L, 0x7.10d31a9faf055168p+1348L }, + { -0x3.e7d21df6c6451cfp-4L, 0xf.38cac992e04dd92p-8384L, -0x6.253d3816519df5p-8384L, -0x6.253d3816519df4f8p-8384L }, + { 0x1.fbff5cc9a151f10ep-4L, 0x2.9be74a9169f983ccp+3984L, 0x7.0a7fb003231082d8p+3980L, 0x7.0a7fb003231082ep+3980L }, + { -0x2.508346b6f97e4b3cp-4L, 0x2.6d5aa9ca35150438p-6664L, -0x8.c1175295f78a7e1p-6668L, -0x8.c1175295f78a7ep-6668L }, + { 0x5.549003e0bc3a306p-8L, -0x2.70cf96f2945f89ap+2768L, -0x1.29379ea6735a5004p+2764L, -0x1.29379ea6735a5002p+2764L }, + { -0x3.fa89daadb8874124p-4L, -0x2.ab88ffd377db8cfp+1852L, 0x1.19f0ebb714ef0082p+1852L, 0x1.19f0ebb714ef0084p+1852L }, + { 0x4.86128b9686d1bdcp-4L, 0x2.078508a7f9bf523cp-14396L, 0xb.a9f3e9f70793d79p-14400L, 0xb.a9f3e9f70793d7ap-14400L }, + { -0x3.e6a1389c4ee6330cp-4L, -0x1.2345feb52b46b768p+10848L, 0x7.56ee97ddf48f583p+10844L, 0x7.56ee97ddf48f5838p+10844L }, + { 0x7.7f79e448p-16416L, -0x5.89900df823ee83c8p+8056L, -0x3.be6252f3b85d24f4p-8356L, -0x3.be6252f3b85d24fp-8356L }, + { -0x1.751bf47b749ae18ep-148L, -0x3.4c815158eac0515cp-14220L, 0x6.efb696954a1d8d3p-14368L, 0x6.efb696954a1d8d38p-14368L }, + { 0x3.d69c812f0a906bd4p-8L, -0xd.06f121a87cad8ccp+3452L, -0x4.79a468a3717e3028p+3448L, -0x4.79a468a3717e302p+3448L }, + { -0x1.4bfbe1c3d5f8ce94p-4L, 0x1.9747531df7189f0cp-7364L, -0x3.1aa2ca71ed8f5fc4p-7368L, -0x3.1aa2ca71ed8f5fcp-7368L }, + { 0xa.44e50bb5c56359cp-8L, -0x2.e250f2584c59c4cp-4520L, -0x2.9e49db540232a5f8p-4524L, -0x2.9e49db540232a5f4p-4524L }, + { -0xd.01531ce3c620f03p-8L, -0x9.056ee6b1e29e3e8p+5472L, 0xa.db6218bc99e8e2bp+5468L, 0xa.db6218bc99e8e2cp+5468L }, + { 0x1.0d530c43cda37932p-4L, 0x2.8bcc9cd9155cb68cp+14312L, 0x3.be202d0192c1a7fp+14308L, 0x3.be202d0192c1a7f4p+14308L }, + { -0x3.39a32a058fcbd9bp-4L, 0xd.4669ea4a5bdd882p+724L, -0x4.4fafa80c4d44f55p+724L, -0x4.4fafa80c4d44f548p+724L }, + { 0xc.1c22b996eb6fc7dp-8L, -0x3.eaca0e062a95276p-1544L, -0x4.2dddffac0b5068ep-1548L, -0x4.2dddffac0b5068d8p-1548L }, + { -0x1.9325d2dfab3eb5d2p-4L, -0x2.710afbcd65e7036cp+4436L, 0x5.d6e783266eb95218p+4432L, 0x5.d6e783266eb9522p+4432L }, + { 0xb.c4d70eca941742ap-8L, 0x3.bac06319b31be118p-3616L, 0x3.de917500e1ea70ep-3620L, 0x3.de917500e1ea70e4p-3620L }, + { -0x9.6a871f761f0c392p-8L, -0x1.592f777d4a7269b4p+6232L, 0x1.2a99e215b4f530d2p+6228L, 0x1.2a99e215b4f530d4p+6228L }, + { 0xe.df857e03ba44519p-8L, -0xc.c83486dca7f8a6cp-1324L, -0x1.0a99133f1e6df45cp-1324L, -0x1.0a99133f1e6df45ap-1324L }, + { -0x1.ae8e54132f4d75fep-4L, -0x2.7ecb7748d3228784p+5356L, 0x6.65a46eeaf16f3928p+5352L, 0x6.65a46eeaf16f393p+5352L }, + { 0x1.82ea01a6ac3c059p-4L, 0x7.98283bcc23ee3c7p-4304L, 0xf.d2b9c546b9e8162p-4308L, 0xf.d2b9c546b9e8163p-4308L }, + { -0x4.332911eac4b16d08p-4L, -0x1.9da5f0f88e76c41cp-3164L, 0xb.5b39fa5929f2c5fp-3168L, 0xb.5b39fa5929f2c6p-3168L }, + { 0x2.a5f0f5ce82c6a948p-4L, -0x5.8738762c85c9f63p+13360L, -0x1.38b6df6f8ec4846p+13360L, -0x1.38b6df6f8ec4845ep+13360L }, + { -0x2.a250e04abfe2cep-4L, 0x1.7f89064b4d7281dcp-6208L, -0x6.387e99c0eb366d48p-6212L, -0x6.387e99c0eb366d4p-6212L }, + { 0x1.533e34fc681e0d64p-4L, -0x6.976ed0ef48c07898p-5156L, -0xc.1b684b6e1d7a6cep-5160L, -0xc.1b684b6e1d7a6cdp-5160L }, + { -0x2.976fa0885b74a0dp-4L, 0x2.6fa1664ea3a1be14p-7544L, -0x9.efb47ad4a474badp-7548L, -0x9.efb47ad4a474bacp-7548L }, + { 0x3.401f19e03339b7d8p-4L, -0x2.e1cf29eba91248ep+14388L, -0xc.4dd22e8eb32e339p+14384L, -0xc.4dd22e8eb32e338p+14384L }, + { -0x2.8bbc0949a8a731bp-4L, 0x3.5cec679bb3f69d98p-9212L, -0xd.73f5e8ad1296da5p-9216L, -0xd.73f5e8ad1296da4p-9216L }, + { 0x7.3ca5eee8p-16416L, -0x1.3bc8b60293078f84p+6520L, -0xc.e0fd8c95f925282p-9896L, -0xc.e0fd8c95f925281p-9896L }, + { -0x3.45c4ac22f9b9fe7p-96L, -0x7.9d640cca80c83b9p-3056L, 0x2.3f397b79fe0ed3dcp-3148L, 0x2.3f397b79fe0ed3ep-3148L }, + { 0x1.48922246e164c31cp-8L, 0x3.251256a4a4974324p-5772L, 0x5.cf00a20473ec53bp-5780L, 0x5.cf00a20473ec53b8p-5780L }, + { -0x2.4e456ef4b9adcafp-4L, 0xf.8fb50e1402f38bp+5532L, -0x3.7e58facfd2d1d0c8p+5532L, -0x3.7e58facfd2d1d0c4p+5532L }, + { 0x1.886dc89c16b624d6p-4L, -0x3.4fa89faae23eda44p+44L, -0x6.fe2f4a64ea4a6c78p+40L, -0x6.fe2f4a64ea4a6c7p+40L }, + { -0x4.350b55034874941p-4L, -0x1.fbcc353d750f0c24p+9096L, 0xd.f83ecea28158477p+9092L, 0xd.f83ecea28158478p+9092L }, + { 0x3.90e10fdba85c0cacp-4L, -0x5.1653c9d362cef54p-13924L, -0x1.7a077ddbf4922fa4p-13924L, -0x1.7a077ddbf4922fa2p-13924L }, + { -0x3.73d037a3672f812cp-4L, 0x3.9b5a02bfcb72b468p-1488L, -0x1.43c84f88af1422acp-1488L, -0x1.43c84f88af1422aap-1488L }, + { 0x1.2b00b6e01f6098dep-4L, -0x7.c7549ce1cd120a6p-2776L, -0xc.a6a5dc751c89f3bp-2780L, -0xc.a6a5dc751c89f3ap-2780L }, + { -0x3.df6b64cd498a6994p-12L, -0x1.c55b237b57929914p-13212L, 0x9.e62d19737b44741p-13224L, 0x9.e62d19737b44742p-13224L }, + { 0x4.32a564d20155332p-4L, 0x1.b1cb6eb8e2ebd224p-2664L, 0x9.1cf96d8b1129d15p-2668L, 0x9.1cf96d8b1129d16p-2668L }, + { -0x3.1c5ee07b5d11cdf4p-4L, 0x1.b5bf8ab3e52d12cp+4216L, -0x8.889eebe2fc21ca4p+4212L, -0x8.889eebe2fc21ca3p+4212L }, + { 0x9.abe18d86bd60c06p-8L, -0x3.d7df89d3dd52449cp+8968L, -0x3.4a2eb51714a7023p+8964L, -0x3.4a2eb51714a7022cp+8964L }, + { -0x3.c6888595ff59158cp-4L, 0x5.ed5d3988224f9748p-192L, -0x2.4d30d9000b4ddc6p-192L, -0x2.4d30d9000b4ddc5cp-192L }, + { 0x1.1d8bff2ec4862e24p-4L, 0x3.034cffddb8433518p-10028L, 0x4.afd48a2d96496ecp-10032L, 0x4.afd48a2d96496ec8p-10032L }, + { -0x2.68737aad1b771f48p-4L, -0xc.afcea80015980b8p+6532L, 0x2.fc425811997eff4cp+6532L, 0x2.fc425811997eff5p+6532L }, + { 0x3.78418dbe89bccdc8p-4L, -0x8.dc01d8b49232a17p-10828L, -0x2.8236ebb32d22f0bp-10828L, -0x2.8236ebb32d22f0acp-10828L }, + { -0x7.61b784fcc75ec3bp-8L, 0xd.233e9cefca1ae41p+14200L, -0x8.df794bc06987c0ap+14196L, -0x8.df794bc06987c09p+14196L }, + { 0x3.d59e590f10746e48p-4L, 0x1.51d6a64294ba9a2ap-10144L, 0x6.8b55a306cdce8dc8p-10148L, 0x6.8b55a306cdce8ddp-10148L }, + { -0x7.28afaf977941c1b8p-8L, 0x4.26f0dae8850886d8p+8496L, -0x2.b7ea3e87e2b0473p+8492L, -0x2.b7ea3e87e2b0472cp+8492L }, + { 0xb.1fed2d782bad9dcp-8L, 0x4.a6abc93b905e715p-4876L, 0x4.91230a64c6e7b4bp-4880L, 0x4.91230a64c6e7b4b8p-4880L }, + { -0x4.07a79631c2281c9p-8L, 0xe.f5d12aeb5942b6bp+228L, -0x5.7ab5bf59532e948p+224L, -0x5.7ab5bf59532e9478p+224L }, + { 0x1.6ee95808p-16416L, 0x5.a07bbf49b0583bbp-9900L, 0x0p+0L, 0x8p-16448L }, + { -0x3.863ad23f9793533p-48L, -0x7.1c785eecfe17605p+3708L, 0x2.428413a21a98386cp+3664L, 0x2.428413a21a98387p+3664L }, + { 0x1.e7dd2eadf3394a16p-4L, 0x3.c1009cb5b2a38294p+4932L, 0x9.c046f0b4f3b69c4p+4928L, 0x9.c046f0b4f3b69c5p+4928L }, + { -0x3.d60f5fcdb37d8eap-4L, 0x1.dc3545b0a8acecf4p+12372L, -0xb.c54051f027930e7p+12368L, -0xb.c54051f027930e6p+12368L }, + { 0x2.5d3d714a0d0272bp-4L, 0x1.e6cbc995a44d6c2cp-1388L, 0x6.0c99b457b89474e8p-1392L, 0x6.0c99b457b89474fp-1392L }, + { -0x1.278a728bb66b64dep-4L, -0xc.9cb7f96b11f2a04p-1236L, 0x1.5cd64e58107b75aep-1236L, 0x1.5cd64e58107b75bp-1236L }, + { 0x2.1df7b3b08b64e3dp-4L, 0x3.dacf3b11609eff4p-88L, 0xb.0e98a5a6b729862p-92L, 0xb.0e98a5a6b729863p-92L }, + { -0x2.c12eb8612105f50cp-4L, -0x3.d5d13ddf2d02994cp+1880L, 0x1.0ba055798a93cce6p+1880L, 0x1.0ba055798a93cce8p+1880L }, + { 0x4.42ffed1cfdb04edp-4L, 0xb.83e125a36a30824p-8028L, 0x3.ec4c0c7e99dcab2cp-8028L, 0x3.ec4c0c7e99dcab3p-8028L }, + { -0x2.bd3a518dddcd87d8p-4L, 0xa.f782f5eeaaf84b2p-976L, -0x2.f88ebb9a09ff9754p-976L, -0x2.f88ebb9a09ff975p-976L }, + { 0xa.a48014f31d21f5p-8L, 0x1.787d684fec780e28p-13432L, 0x1.61fb236d58d214e6p-13436L, 0x1.61fb236d58d214e8p-13436L }, + { -0x1.d95a03b300a7839p-4L, -0x1.402a0ef3d21d78eap+11592L, 0x3.8b94b58f3dd5ddd8p+11588L, 0x3.8b94b58f3dd5dddcp+11588L }, + { 0x3.ea3ece65229e7c1cp-4L, -0x1.02df530bdd4a2488p+5252L, -0x5.1bf7eec74ce67c5p+5248L, -0x5.1bf7eec74ce67c48p+5248L }, + { -0xa.4c31201905c5915p-8L, 0x2.4b18c689eb5ab8dp-1928L, -0x2.2c6611b3ab947174p-1932L, -0x2.2c6611b3ab94717p-1932L }, + { 0x3.e691a4a4ec98c938p-4L, -0x5.cd17b52b8b67c0d8p-10292L, -0x1.d36cada1fee74204p-10292L, -0x1.d36cada1fee74202p-10292L }, + { -0x2.3da4f3249dc52684p-4L, -0xf.34520f86c43a674p+3372L, 0x3.4f42e88d8003846p+3372L, 0x3.4f42e88d80038464p+3372L }, + { 0x3.c7cd16a9c4870a48p-8L, -0x4.8c156b51b3e8457p+10772L, -0x1.89e922297cbf68aap+10768L, -0x1.89e922297cbf68a8p+10768L }, + { -0x2.b0eebddd240923ep-4L, -0x5.29574a08fac443ep-12084L, 0x1.5f0f8e898258fbacp-12084L, 0x1.5f0f8e898258fbaep-12084L }, + { 0x2.249c8a89d03aa864p-4L, -0xd.13cf8aa40b87d27p+11728L, -0x2.5f197166ecfbca14p+11728L, -0x2.5f197166ecfbca1p+11728L }, + { -0x4.6f21e629b4f6c5e8p-4L, -0x2.f5e77b1943eaf884p+6012L, 0x1.62d8f7d63feb95f8p+6012L, 0x1.62d8f7d63feb95fap+6012L }, + { 0x4.15fd44d5e86bc01p-4L, 0x5.473ae34b6e2063cp-4768L, 0x1.bb5a721b7a439e0ap-4768L, 0x1.bb5a721b7a439e0cp-4768L }, + { -0x2.ca05f449ee9bba2p-4L, 0x6.a835c5372554956p-9312L, -0x1.d6f4ea6ae1e36da8p-9312L, -0x1.d6f4ea6ae1e36da6p-9312L }, + { 0x3.38e23638p-16416L, 0xd.b64a7582d1883d4p+7568L, 0x3.fbe211139f2c5e74p-8844L, 0x3.fbe211139f2c5e78p-8844L }, + { -0x2.c0eede3d08af0a04p-96L, -0x1.9cc6ff87f9582b36p-8292L, 0x6.67d3fa6766d44f5p-8388L, 0x6.67d3fa6766d44f58p-8388L }, + { 0x3.657fca1541630014p-4L, 0xa.5555080b30f60b8p+12212L, 0x2.deab71182cd05b2cp+12212L, 0x2.deab71182cd05b3p+12212L }, + { -0x2.15a5a3d39fca9d74p-8L, 0x4.ba3ed0a011dad9c8p+11960L, -0xe.4691fded533e7dp+11952L, -0xe.4691fded533e7cfp+11952L }, + { 0x2.820600a7b4b8b6c8p-4L, 0x1.434edd70f5ea7b82p-7912L, 0x4.3eacdda95f716048p-7916L, 0x4.3eacdda95f71605p-7916L }, + { -0x4.76729a8ab5f9d168p-4L, -0x3.f2ca785573e18f44p-6872L, 0x1.dcdaf54fb1102d4cp-6872L, 0x1.dcdaf54fb1102d4ep-6872L }, + { 0x1.b28350368d79329p-4L, -0x5.bd5227673487f808p+13568L, -0xd.5b9b9a020b995c7p+13564L, -0xd.5b9b9a020b995c6p+13564L }, + { -0x4.422aeed297423dfp-4L, 0xd.6dbe42d94446092p-5372L, -0x5.fec8d99f836824e8p-5372L, -0x5.fec8d99f836824ep-5372L }, + { 0x2.b4c82511d6b8adbp-4L, -0x2.58c6fae544166138p-10216L, -0x8.770e6e77fa12c41p-10220L, -0x8.770e6e77fa12c4p-10220L }, + { -0x3.603dab982401c2fp-4L, 0xd.c28e13e36928e3ap-12400L, -0x4.b458ff98a77bea88p-12400L, -0x4.b458ff98a77bea8p-12400L }, + { 0x2.52993b67468165dp-4L, 0xe.abf2bcc7641993cp+4800L, 0x2.de7fd921b9b3f348p+4800L, 0x2.de7fd921b9b3f34cp+4800L }, + { -0x2.ffc62e45c4920ca8p-4L, -0x9.e0554ee54c3f10cp+2864L, 0x2.f5240374ef1e8fa4p+2864L, 0x2.f5240374ef1e8fa8p+2864L }, + { 0x1.d76afc41248078d8p-4L, 0x1.96be670b6795cd66p+4484L, 0x3.fecd39da987d611p+4480L, 0x3.fecd39da987d6114p+4480L }, + { -0x1.1fe55dbba061231cp-4L, -0x2.3f0e956a9cc93b7cp-2808L, 0x3.c768e818370d0554p-2812L, 0x3.c768e818370d0558p-2812L }, + { 0x4.7ffbbb9da4656abp-4L, 0x1.883501d399ebe686p-2052L, 0x8.c3b8d2ed744ac29p-2056L, 0x8.c3b8d2ed744ac2ap-2056L }, + { -0x2.e7771c3617428004p-4L, 0x4.aa305910d4a5b948p-14036L, -0x1.5913b10b6f6bb312p-14036L, -0x1.5913b10b6f6bb31p-14036L }, + { 0x1.f51f691570542864p-4L, -0x7.ff805590540d7e68p-8240L, -0x1.54f0cc2a744adbep-8240L, -0x1.54f0cc2a744adbdep-8240L }, + { -0x2.bc9523828d7c744p-4L, -0x5.f8c2890bff7a53a8p-4408L, 0x1.9db92d87363ce3a4p-4408L, 0x1.9db92d87363ce3a6p-4408L }, + { 0xb.cface8db66432b4p-8L, -0x1.52f8d17d3ef509ep-14136L, -0x1.60ecc5e5445bc5fap-14140L, -0x1.60ecc5e5445bc5f8p-14140L }, + { -0x3.c4fcb83a4348059p-4L, -0x6.92589a2ad057f888p+14032L, 0x2.8c0de6f4f4ad5a8p+14032L, 0x2.8c0de6f4f4ad5a84p+14032L }, + { 0xd.3e73c6c392e1b2cp-16L, -0x1.9d39baf7c3757386p-7232L, -0x1.ed6b25bf930609f2p-7244L, -0x1.ed6b25bf930609fp-7244L }, + { -0x1.2be18a59c6c0cb46p-4L, -0x5.2f34ad391bf16bep+14208L, 0x9.194f55dcdc049ddp+14204L, 0x9.194f55dcdc049dep+14204L }, + { 0x1.6ea2622p-16416L, 0xd.0a61c31aa71a8b4p+192L, 0x1.af1b0b9011702c9cp-16220L, 0x1.af1b0b9011702c9ep-16220L }, + { -0xe.24746d350747p-76L, -0x6.2cd68ac90fd809cp-20L, 0x7.dfe1c92e972b245p-92L, 0x7.dfe1c92e972b2458p-92L }, + { 0x3.172ad4e89020bdc4p-4L, -0x7.5d68336e21e50738p-10576L, -0x1.e05e86f2c4aaa87p-10576L, -0x1.e05e86f2c4aaa86ep-10576L }, + { -0x1.1cc46bd3cc5d5eep-4L, 0x8.dfe337c5f8f4ed8p-2964L, -0xe.c2e4fcc9056e939p-2968L, -0xe.c2e4fcc9056e938p-2968L }, + { 0x1.6aec81e28b750398p-4L, 0x6.d60397f1aab8875p+5068L, 0xd.65769829a5eb6bbp+5064L, 0xd.65769829a5eb6bcp+5064L }, + { -0xa.dd9db54ce301e4fp-8L, 0x2.994e7862cafbb18p-9172L, -0x2.9a10f7c79bc8a514p-9176L, -0x2.9a10f7c79bc8a51p-9176L }, + { 0x3.4c1067ae36f3df8p-4L, 0x5.e39292b71e3bd29p-14656L, 0x1.97849d850815a968p-14656L, 0x1.97849d850815a96ap-14656L }, + { -0x3.2716db715997395cp-4L, -0x3.7b95a736d2a03acp-2972L, 0x1.1a47ea03f6df2b3p-2972L, 0x1.1a47ea03f6df2b32p-2972L }, + { 0x3.511564feccb7ade4p-4L, 0xa.3be5fc2351c749fp+8708L, 0x2.c808aa921e98c90cp+8708L, 0x2.c808aa921e98c91p+8708L }, + { -0x3.69c632e288b42e7cp-4L, 0x2.6cfab89ec92c9a94p+12520L, -0xd.6f501c63d843bbp+12516L, -0xd.6f501c63d843bafp+12516L }, + { 0xd.50c03549bb8a308p-8L, -0xd.bb307fe5c0a193dp+11920L, -0x1.0125a0d31814385ap+11920L, -0x1.0125a0d318143858p+11920L }, + { -0x4.62f76781cd43fa1p-4L, 0x6.add388611cf3e0dp-5568L, -0x3.166b1e48e4d0d538p-5568L, -0x3.166b1e48e4d0d534p-5568L }, + { 0x2.af134161b98b158cp-4L, -0x6.b78672290432052p+4200L, -0x1.80b269a8acd58f28p+4200L, -0x1.80b269a8acd58f26p+4200L }, + { -0x4.07400317e3bbdf6p-4L, 0x4.6f0a1bd0504232fp-4560L, -0x1.daf3ffdcfaf5a3fcp-4560L, -0x1.daf3ffdcfaf5a3fap-4560L }, + { 0x3.e2c42f99082b0694p-8L, -0x2.23235efc5d063d1cp+484L, -0xb.e43a884083a14cdp+476L, -0xb.e43a884083a14ccp+476L }, + { -0x2.510f0edafa423e34p-4L, 0x8.ea166668cb9c597p-728L, -0x2.02f35e07c5b586ep-728L, -0x2.02f35e07c5b586dcp-728L }, + { 0x2.87d8f5995c149e84p-4L, -0x1.fd41fdd489dd6b86p-4740L, -0x6.be1d42ef4ae7d568p-4744L, -0x6.be1d42ef4ae7d56p-4744L }, + { -0x4.91cd3914269e7f4p-4L, -0x7.5908781b4662a448p+4676L, 0x3.90a7abc41bfff254p+4676L, 0x3.90a7abc41bfff258p+4676L }, + { 0x1.a5cddc11ef6ac702p-4L, -0x5.101df29586f07ac8p+14844L, -0xb.7475b0a9b9616e6p+14840L, -0xb.7475b0a9b9616e5p+14840L }, + { -0x2.59a788d1463d5708p-4L, 0x5.93f40353ef748448p-6680L, -0x1.4747090652a60d3p-6680L, -0x1.4747090652a60d2ep-6680L }, + { 0x2.70458f50e301850cp-4L, -0x2.bbcb14f8c8df1858p+4120L, -0x8.f3733a06672424fp+4116L, -0x8.f3733a06672424ep+4116L }, + { -0x1.edb5a0fdb59e0032p-4L, 0x1.8d559c866804202p-7668L, -0x4.9a064be7a218d8bp-7672L, -0x4.9a064be7a218d8a8p-7672L }, + { 0x5.5e55df7p-16416L, 0x1.d91cda789c52cbdp+4364L, 0xe.504ec49dde8ab29p-12052L, 0xe.504ec49dde8ab2ap-12052L }, + { -0x2.3345c79170f14c5p-180L, -0xb.f1c6659cf21c7f9p-4736L, 0x2.5ea6960e05da9f88p-4912L, 0x2.5ea6960e05da9f8cp-4912L }, + { 0x3.0afb26c30345b6c8p-4L, 0x2.302e0468775a2cfp+3692L, 0x8.cb4da2d9809cb86p+3688L, 0x8.cb4da2d9809cb87p+3688L }, + { -0x3.1a5317d464e8bcd8p-4L, -0xf.5f00a957d87468bp-352L, 0x4.c7dab607b60b8738p-352L, 0x4.c7dab607b60b874p-352L }, + { 0x2.f8e069607dea9234p-4L, -0x3.684738cd5ffb438p-4096L, -0xd.66adc86b056b9e4p-4100L, -0xd.66adc86b056b9e3p-4100L }, + { -0x1.68f2cde5ae072e6ep-4L, 0xb.6bb5e3b9506b364p+1724L, -0x1.851c08718da5d4e4p+1724L, -0x1.851c08718da5d4e2p+1724L }, + { 0x2.23ce11d6341a8aacp-4L, 0x1.455660f0dbaacbacp-9204L, 0x3.aea780e4a73a96e4p-9208L, 0x3.aea780e4a73a96e8p-9208L }, + { -0x2.135127bb12ede30cp-4L, 0xa.d8293b85a4bffcfp+12080L, -0x2.2c758719e47f09d8p+12080L, -0x2.2c758719e47f09d4p+12080L }, + { 0x1.33cb1ea0c84f5a1ap-4L, 0xa.2e25e1b057a53d2p-9672L, 0x1.106c68c29be5ecd4p-9672L, 0x1.106c68c29be5ecd6p-9672L }, + { -0x1.fa3c2eb2e9308f1cp-4L, -0xd.079788536be471ap+5984L, 0x2.7ad9dd04bd787d68p+5984L, 0x2.7ad9dd04bd787d6cp+5984L }, + { 0x3.5875e63760a4466p-4L, -0x1.e565eb8bd950bb6cp-6104L, -0x8.4f709e7bba8e058p-6108L, -0x8.4f709e7bba8e057p-6108L }, + { -0x1.3f197fa4514cf7c2p-4L, 0x7.dc189a6904687248p-3956L, -0xe.b70fcbf84500736p-3960L, -0xe.b70fcbf84500735p-3960L }, + { 0x2.98ff74bb0396e2a8p-4L, -0x6.cc6bb049840d2788p+3184L, -0x1.79c15ad6f10263bcp+3184L, -0x1.79c15ad6f10263bap+3184L }, + { -0x1.e92034fc00fd7a98p-4L, -0x3.e5597d53f64ac974p-2504L, 0xb.6faf807e0f4e0a3p-2508L, 0xb.6faf807e0f4e0a4p-2508L }, + { 0x4.24c32dc8985a08d8p-4L, 0xd.eaf2679d518cbcap-5988L, 0x4.9fc9e3020022b7cp-5988L, 0x4.9fc9e3020022b7c8p-5988L }, + { -0x2.a33049d338912ac4p-4L, -0x1.f3b94e68042c5dc8p-11892L, 0x8.1dde7a4bbda2816p-11896L, 0x8.1dde7a4bbda2817p-11896L }, + { 0x2.ba130b3c4d1f4e8p-4L, 0x6.0af61fcd08d308f8p-15004L, 0x1.5f378240ba9a69fep-15004L, 0x1.5f378240ba9a6ap-15004L }, + { -0xb.1ce64865e029d5fp-8L, 0x1.ff55919d9667cf4cp+13108L, -0x2.0bd3af3af36c6e6cp+13104L, -0x2.0bd3af3af36c6e68p+13104L }, + { 0xe.294e92a7a26e0f2p-12L, 0x1.0329cf12c0f4735cp-9924L, 0x1.4a5b55d460c69b9ep-9932L, 0x1.4a5b55d460c69bap-9932L }, + { -0xf.2e554c655733393p-8L, -0x1.63b6624e7048c69p-13664L, 0x1.f5f341a9df85c5ep-13668L, 0x1.f5f341a9df85c5e2p-13668L }, + { 0x4.19c6d69c8374d198p-8L, 0x3.3c77b09aeb197434p-5576L, 0x1.2fe6936fb94fa2a6p-5580L, 0x1.2fe6936fb94fa2a8p-5580L }, + { -0x6.0496537484fa208p-8L, -0x6.c8226dd9ecd375ap-9856L, 0x3.b95264ba207a26p-9860L, 0x3.b95264ba207a2604p-9860L }, + { 0x3.6687889ff8995454p-36L, -0xa.ea939bccf0c7a07p+1528L, -0x3.58de478a3f4ba21p+1496L, -0x3.58de478a3f4ba20cp+1496L }, + { -0x2.7f156648p-16416L, -0x4.f40ef5608acb05ep-1128L, 0x0p+0L, 0x8p-16448L }, + { 0x4.8500f80b4fa4a34p-4L, -0x7.3625bf44a443e3f8p+5176L, -0x2.96a1ca8ead93767p+5176L, -0x2.96a1ca8ead93766cp+5176L }, + { -0x3.1e76ef016909914cp-4L, 0x7.115b116b66f8aa4p-12752L, -0x2.36042efa2987b7a8p-12752L, -0x2.36042efa2987b7a4p-12752L }, + { 0x1.145e8982b98005cp-4L, -0x5.d05179f09dc2d33p-13872L, -0x8.c32eaca7f2e537ap-13876L, -0x8.c32eaca7f2e5379p-13876L }, + { -0x6.48d061b769787a38p-8L, -0x1.22c95177a19486ep-7144L, 0xa.6d51af264791aebp-7152L, 0xa.6d51af264791aecp-7152L }, + { 0x1.3733136f320f9f84p-4L, -0x1.8a40d2261f03957ep+4176L, -0x2.9a6c6aca7935b768p+4172L, -0x2.9a6c6aca7935b764p+4172L }, + { -0x1.358688a586adbbf8p-4L, -0x6.56cb6fd63dca8b9p+9600L, 0xb.7f5f931dd5eb2eep+9596L, 0xb.7f5f931dd5eb2efp+9596L }, + { 0x5.449fa70eef370f58p-8L, -0x1.a1b184553cda78ap+7432L, -0xc.465569d2c326a9ep+7424L, -0xc.465569d2c326a9dp+7424L }, + { -0x2.92231a70c5780dap-4L, 0xa.2782912323620c5p-4824L, -0x2.90e7e4c7728e0584p-4824L, -0x2.90e7e4c7728e058p-4824L }, + { 0x2.b59d7e039fdf9904p-4L, -0x2.459d427616b15588p+4412L, -0x8.344523d1b10cf33p+4408L, -0x8.344523d1b10cf32p+4408L }, + { -0xc.2393bad0835b34cp-8L, -0x7.ee687fee5c4ec2b8p+3820L, 0x8.e4ce378035800c9p+3816L, 0x8.e4ce378035800cap+3816L }, + { 0x3.cb172495f4e11098p-4L, -0x1.867b118a15199e4ep-6280L, -0x7.7dad976d917e1cd8p-6284L, -0x7.7dad976d917e1cdp-6284L }, + { -0x4.4abd064ca0fe822p-4L, -0x5.919372e384ec19cp-4452L, 0x2.8252a05d4039be14p-4452L, 0x2.8252a05d4039be18p-4452L }, + { 0x4.3035264bc9659e2p-4L, -0x9.90137db5d8438f6p+5028L, -0x3.3533f8369942f288p+5028L, -0x3.3533f8369942f284p+5028L }, + { -0x2.a02f7f8f2a33579p-4L, -0x1.74dc31e3b9305bc4p+8180L, 0x6.06d01869bfc02898p+8176L, 0x6.06d01869bfc028ap+8176L }, + { 0x2.0f8e4cbcc27850d8p-4L, -0x2.fa91e626f345fb28p-14588L, -0x8.549922eac21ecdp-14592L, -0x8.549922eac21eccfp-14592L }, + { -0x2.1fc557b50c931d24p-4L, -0xf.a038fe23264b69fp+14704L, 0x3.360291be1344afe4p+14704L, 0x3.360291be1344afe8p+14704L }, + { 0x1.b69ca8d925216fc6p-4L, 0x1.d578671f39a6b79p+4996L, 0x4.4e6ab61dbdffe2b8p+4992L, 0x4.4e6ab61dbdffe2cp+4992L }, + { -0x4.8660d1e7a3a18068p-4L, 0xc.9a201e4897d0226p+7292L, -0x6.0b24b9cb8f96233p+7292L, -0x6.0b24b9cb8f962328p+7292L }, + { 0x2.804eb8772ea477cp-4L, -0xd.c98d7189a0303bfp-9228L, -0x2.e39b75a1ab637314p-9228L, -0x2.e39b75a1ab63731p-9228L }, + { -0x5.f071a27eaa54e38p-8L, 0x1.775823e9c3c2806cp+3976L, -0xc.b60896a0bc1c55ep+3968L, -0xc.b60896a0bc1c55dp+3968L }, + { 0x1.7d19bf9b2f768d26p-136L, -0x2.d94140f31f8c61bp-1620L, -0x6.1e39086add179f3p-1756L, -0x6.1e39086add179f28p-1756L }, + { -0x7.e376b0bp-16416L, 0x1.3247488c5d03274ep+8560L, -0xd.9dad2138f46abb9p-7856L, -0xd.9dad2138f46abb8p-7856L }, + { 0x1.6343494b7816dd6p-4L, 0x1.24f1b7414cd3e44p+8680L, 0x2.3272b4a13c6b0828p+8676L, 0x2.3272b4a13c6b082cp+8676L }, + { -0x1.c03717a7400b18dep-4L, -0x2.32aa0ac2a73accfcp+12680L, 0x5.e131f8511a6780ap+12676L, 0x5.e131f8511a6780a8p+12676L }, + { 0x3.9639abe76c1e22b4p-4L, -0x1.aad25e3bbb5c92c2p-716L, -0x7.c8d239822cb8acep-720L, -0x7.c8d239822cb8acd8p-720L }, + { -0x1.6f8de0a23eb23f08p-4L, -0x2.a959c77ea7aa43ecp+988L, 0x5.c6b591b2a7e072ep+984L, 0x5.c6b591b2a7e072e8p+984L }, + { 0x3.0493f6bd3e7a9d08p-4L, 0x2.3b45ef80edb12e4p-7692L, 0x8.e68e11e3908f565p-7696L, 0x8.e68e11e3908f566p-7696L }, + { -0x3.4ebaefe2e6c2ffd4p-4L, -0xe.87ffc2cdbdd0a59p-888L, 0x4.dada35190941404p-888L, 0x4.dada351909414048p-888L }, + { 0x3.c04aa41676d3a1dcp-4L, 0x5.c671189eaee79d8p-3112L, 0x1.c13ec20855e228fap-3112L, 0x1.c13ec20855e228fcp-3112L }, + { -0xd.84c80ecec0dfc24p-8L, -0xa.41831a7d42bf933p+524L, 0xc.d7fd375ea441b22p+520L, 0xc.d7fd375ea441b23p+520L }, + { 0x3.9b18f252e9cc6204p-4L, -0xc.541234ac6a41dbfp+2520L, -0x3.9d66104d07c6c03cp+2520L, -0x3.9d66104d07c6c038p+2520L }, + { -0x9.01dc33c60cb85cfp-8L, 0x7.ff05934f4c4c383p-13868L, -0x6.9c7c08044a14d7b8p-13872L, -0x6.9c7c08044a14d7bp-13872L }, + { 0x2.c31e22698d11a4ecp-4L, -0x1.8a1311226a2cf3dp+14616L, -0x5.a8a6f3b45150fea8p+14612L, -0x5.a8a6f3b45150feap+14612L }, + { -0x3.c76e6f9502a10174p-4L, -0xd.cd06a7b980fe0dp-4668L, 0x5.5d5541ea4ee0ea48p-4668L, 0x5.5d5541ea4ee0ea5p-4668L }, + { 0x8.77c988605043e5bp-8L, 0x1.6982403523b43efap-8420L, 0x1.0f8f240be8bbfaa6p-8424L, 0x1.0f8f240be8bbfaa8p-8424L }, + { -0x2.574faa96bdd3213p-4L, 0xc.503b4e17876b4f8p-696L, -0x2.cf6c154995d02d98p-696L, -0x2.cf6c154995d02d94p-696L }, + { 0x4.0e6b69653c7259cp-4L, 0xf.ea4c84120426686p-4116L, 0x5.30298b34abe7e7cp-4116L, 0x5.30298b34abe7e7c8p-4116L }, + { -0x2.6a84e1dc3ed5b358p-4L, 0x6.681d1a92ea56e508p-8188L, -0x1.8359cb0bb17a3c26p-8188L, -0x1.8359cb0bb17a3c24p-8188L }, + { 0x2.43c341781144525p-4L, 0x1.2c0b226e839776bap-1564L, 0x3.94dda02c158a4d1p-1568L, 0x3.94dda02c158a4d14p-1568L }, + { -0x3.5ce4a1fe88889f1cp-4L, -0x5.d49892159ff7aeb8p-5000L, 0x1.fc1549257f8001eap-5000L, 0x1.fc1549257f8001ecp-5000L }, + { 0x9.d9c0516a61c2fd1p-8L, 0x5.d5a66b8dfa047b5p+6780L, 0x5.15ca590d0fb17b28p+6776L, 0x5.15ca590d0fb17b3p+6776L }, + { -0x7.ce5459cf45b18448p-8L, -0x1.37c211415835776cp+3656L, 0xd.ed8c6d47ece27fcp+3648L, 0xd.ed8c6d47ece27fdp+3648L }, + { 0x3.6aa98df8p-16416L, 0x3.3644cdf8f7e5e378p-5876L, 0x0p+0L, 0x8p-16448L }, + { -0x4.95ee308p-16420L, 0x7.44556257ec455fb8p-8352L, -0x8p-16448L, -0x0p+0L }, + { 0x1.f6845a417bd06bd4p-4L, 0x2.8d6b4f3f8a5ae1d8p-4092L, 0x6.d171ba168e7c00c8p-4096L, 0x6.d171ba168e7c00dp-4096L }, + { -0x3.362ee1134557b0c8p-4L, -0x6.44d1e706f42b9218p-14364L, 0x2.06becf0cbf15a76cp-14364L, 0x2.06becf0cbf15a77p-14364L }, + { 0x1.29ad0ab6b39c71e8p-4L, 0x8.3abf84f84659fbfp+6884L, 0xd.53ad29e0460e74bp+6880L, 0xd.53ad29e0460e74cp+6880L }, + { -0x2.7323c21f31ee0c94p-4L, 0x1.ac8d253b449af046p-12608L, -0x6.6bf33ea54480fb38p-12612L, -0x6.6bf33ea54480fb3p-12612L }, + { 0x3.d0edb25b17c3c3c8p-4L, -0x1.e23087ac1fc0803ep-1112L, -0x9.4ce21b7a005ec4p-1116L, -0x9.4ce21b7a005ec3fp-1116L }, + { -0x1.defb373d645dd7fcp-4L, 0x2.b1b352e26c101b48p+196L, -0x7.bbe0c9d1fb10f57p+192L, -0x7.bbe0c9d1fb10f568p+192L }, + { 0x3.db8c171e647ac154p-4L, 0x3.bd7064bc96439e88p-8072L, 0x1.2a5b636788b866a6p-8072L, 0x1.2a5b636788b866a8p-8072L }, + { -0x2.157c312f0a7331dcp-4L, 0x1.d519eadd05d80046p+3776L, -0x5.e7076a49325e2b2p+3772L, -0x5.e7076a49325e2b18p+3772L }, + { 0x6.13dd8fa1bb5a0888p-8L, 0xd.e1d14a94f3f3513p-14348L, 0x7.84c2d6dc58e0033p-14352L, 0x7.84c2d6dc58e00338p-14352L }, + { -0xc.a7a4a0836807865p-8L, 0xa.6cd4c82b6c3ad8fp-14052L, -0xc.332a5ac869f5485p-14056L, -0xc.332a5ac869f5484p-14056L }, + { 0x3.e4981e366529f448p-4L, -0x1.c855bc869ec45c56p-2360L, -0x8.f5fa49da4d36b7cp-2364L, -0x8.f5fa49da4d36b7bp-2364L }, + { -0x1.3df73a344e1df3cep-4L, -0x8.b6f7624f6d4b8fap+4364L, 0x1.0415fd3b8843c92ap+4364L, 0x1.0415fd3b8843c92cp+4364L }, + { 0xf.71e1693aabd6949p-8L, -0x9.67429de92a0cc45p+13180L, -0xc.b7344f5f174184ap+13176L, -0xc.b7344f5f1741849p+13176L }, + { -0x2.e92c6340870d1904p-4L, 0x6.3a68ed7dc2ab1b18p+1772L, -0x1.cde5ffd73bb78894p+1772L, -0x1.cde5ffd73bb78892p+1772L }, + { 0x1.6638437083b5e5cep-4L, -0xa.51a3936a6af3cc4p-9740L, -0x1.3f86597d7dfbb25ap-9740L, -0x1.3f86597d7dfbb258p-9740L }, + { -0x5.e85b2872af8b8768p-8L, -0x1.05a0268fc1493582p-6052L, 0x8.cff240ac67268dbp-6060L, 0x8.cff240ac67268dcp-6060L }, + { 0x2.dfdc0c89ab932644p-4L, -0x1.a6d9620079c35e76p-14696L, -0x6.4caa08299af24148p-14700L, -0x6.4caa08299af2414p-14700L }, + { -0x4.15f357d7796b39f8p-4L, -0xd.0f27ddc214b3d5fp+2272L, 0x5.8e1f34fcf9c6555p+2272L, 0x5.8e1f34fcf9c65558p+2272L }, + { 0x3.0e9f50108a3ff43cp-4L, -0x6.c4cc122615b61d18p+7552L, -0x1.b51cb1eca74aff38p+7552L, -0x1.b51cb1eca74aff36p+7552L }, + { -0x4.4a7f16c7046c96c8p-4L, -0x2.981ff7909e578104p-14228L, 0x1.2b286a2c567ea818p-14228L, 0x1.2b286a2c567ea81ap-14228L }, + { 0x5.ef34f4p-16420L, -0x1.214299eebb91926ap+7320L, -0x9.ac829743b8c0f05p-9100L, -0x9.ac829743b8c0f04p-9100L }, + { -0x1.691f3828p-16416L, 0x1.efebf2a3b96734aep+3408L, -0x3.f141a8e9339c907cp-13008L, -0x3.f141a8e9339c9078p-13008L }, + { 0x1.4e8c937c8e553dcp-4L, -0x1.3035f2318b0be00ep-6620L, -0x2.27538394a1b35e5cp-6624L, -0x2.27538394a1b35e58p-6624L }, + { -0x7.5976854fcf9031fp-8L, -0x6.11bab7a888287f3p-312L, 0x4.14b5a5ddbd843bdp-316L, 0x4.14b5a5ddbd843bd8p-316L }, + { 0x1.705c9e77f96a731cp-4L, 0x3.d432ed3f654d8a28p-2564L, 0x7.9c73705bb807b3p-2568L, 0x7.9c73705bb807b308p-2568L }, + { -0x4.9a5360d861aaa4e8p-4L, 0x1.1531b287e936aff2p-6580L, -0x8.7a86ebb8c48bafp-6584L, -0x8.7a86ebb8c48baefp-6584L }, + { 0x3.aed6e32454d1f618p-4L, 0x1.296010316396f574p-10016L, 0x5.8e0d53264bbb5658p-10020L, 0x5.8e0d53264bbb566p-10020L }, + { -0x6.40fd50816f8157b8p-8L, 0x6.4b02ec16879cadc8p-3652L, -0x3.97bb59c7052cc938p-3656L, -0x3.97bb59c7052cc934p-3656L }, + { 0x2.2873a4ee7791f16cp-4L, -0x1.5e183567b5058b64p-6240L, -0x3.fe783fc7ec0a3e54p-6244L, -0x3.fe783fc7ec0a3e5p-6244L }, + { -0x4.91ca4444446e025p-4L, 0x1.8871ecc06666a8b8p+6540L, -0xb.e684deb0c4ea1a1p+6536L, -0xb.e684deb0c4ea1ap+6536L }, + { 0x5.f63f2f14fa25c78p-8L, 0x7.f61f9817342409ap+6848L, 0x4.3b14e17bad193658p+6844L, 0x4.3b14e17bad19366p+6844L }, + { -0x3.73b374e9d6f1b14cp-4L, 0x1.a766304af3ed99eap-11340L, -0x9.472a21f120494b4p-11344L, -0x9.472a21f120494b3p-11344L }, + { 0x3.8a6aa9bc55f2078p-8L, -0x6.2c58a861a1cf29a8p+5396L, -0x1.f514ecea291b833ep+5392L, -0x1.f514ecea291b833cp+5392L }, + { -0xd.f5a19cfa9847764p-8L, -0x1.9ead8227db0f911cp-9848L, 0x2.18ba56217d205048p-9852L, 0x2.18ba56217d20504cp-9852L }, + { 0x1.03b2429f433bd84p-4L, 0x7.6174df81f989a0fp-5988L, 0xa.7924c7723ddc533p-5992L, 0xa.7924c7723ddc534p-5992L }, + { -0x1.1908bf815764d01ep-4L, 0x6.b0ac0d83a33409dp+4848L, -0xa.fa080088ed7f3f8p+4844L, -0xa.fa080088ed7f3f7p+4844L }, + { 0x4.187fb9c09c55f5ep-4L, -0x2.670dd27ee7f45a3cp-10212L, -0xc.a3d27b26df9ae5ep-10216L, -0xc.a3d27b26df9ae5dp-10216L }, + { -0x4.aded544e99e15d3p-4L, -0x1.fb63b223d8b85776p-12512L, 0xf.d3fc75e67e5697dp-12516L, 0xf.d3fc75e67e5697ep-12516L }, + { 0x9.f5a904e0a16b75p-12L, 0x6.b6db5486fa8da28p-4968L, 0x6.05bb9a21b9c5695p-4976L, 0x6.05bb9a21b9c56958p-4976L }, + { -0x3.7ea985070d82c5dcp-4L, 0x7.8ed5f1582d74d94p+13856L, -0x2.afe9bbfb32eedff4p+13856L, -0x2.afe9bbfb32eedffp+13856L }, + { 0x8.ceca186af1571abp-8L, -0x4.aa7a2e0b9a249038p+5868L, -0x3.a4aded1bd7f30504p+5864L, -0x3.a4aded1bd7f305p+5864L }, + { -0x8.fd7657912a84383p-8L, -0x1.1c18c670ecb47d26p-8016L, 0xe.a6fa205a23754cep-8024L, 0xe.a6fa205a23754cfp-8024L }, + { 0x1.2af0c6bp-16416L, 0x2.e55845c69ebf1658p+3336L, 0x4.e0ef355e6d13fa58p-13080L, 0x4.e0ef355e6d13fa6p-13080L }, + { -0x1.9a9d144p-16416L, -0x1.2b2e1b630ba1b3b6p+2664L, 0x2.b44f5c0dc1564e68p-13752L, 0x2.b44f5c0dc1564e6cp-13752L }, + { 0x2.3f11da078aa8a478p-4L, -0xb.2315f89420146ccp+8064L, -0x2.1c631386d9d9fc94p+8064L, -0x2.1c631386d9d9fc9p+8064L }, + { -0x3.019d6e7999c6dddcp-4L, 0x1.3f86f58ae2fdd6dcp-7640L, -0x5.ff0fffae46c8157p-7644L, -0x5.ff0fffae46c81568p-7644L }, + { 0xb.4e40f5e1d904b61p-8L, 0x6.532f0bc4c2ab27fp-13652L, 0x6.4f362dc573683e08p-13656L, 0x6.4f362dc573683e1p-13656L }, + { -0x2.80eab5330cc1f32cp-4L, -0x3.005426a19639d6bp+14296L, 0xb.c9efe6146589be6p+14292L, 0xb.c9efe6146589be7p+14292L }, + { 0x2.12c9e15ad0b4a958p-4L, 0x1.504150487ac4b4e4p-13364L, 0x3.b1cb463da2f231cp-13368L, 0x3.b1cb463da2f231c4p-13368L }, + { -0xc.1c5be79cff6476p-8L, 0xc.0c6b1b1a302ca68p+14360L, -0xd.7a7df9fc3108fap+14356L, -0xd.7a7df9fc3108f9fp+14356L }, + { 0x3.1bac1512e32d6aa8p-4L, -0xf.6312e170067d25bp-3972L, -0x3.f0d8177d9054014cp-3972L, -0x3.f0d8177d90540148p-3972L }, + { -0x1.519f2ae231695ea2p-4L, 0x5.5400fe4d2a5ab7f8p-8900L, -0xa.947c24f62e74fcdp-8904L, -0xa.947c24f62e74fccp-8904L }, + { 0x2.a65946c7f23f31acp-4L, 0x4.7a751384d759865p+8672L, 0xf.d77ddbba6b11fd9p+8668L, 0xf.d77ddbba6b11fdap+8668L }, + { -0x2.cd037a11f9213844p-4L, -0xd.6910092b63029a8p-1592L, 0x3.b91ac58ce049a54p-1592L, 0x3.b91ac58ce049a544p-1592L }, + { 0x3.9db1e0144ed66a8cp-8L, 0x1.d28289f977ace56p-32L, 0x9.70a6bb89b1c4544p-40L, 0x9.70a6bb89b1c4545p-40L }, + { -0x2.621a3f5edf1bfa3cp-4L, -0x3.5c6f2312eb314f6p-8832L, 0xc.835eabfeaf37f45p-8836L, 0xc.835eabfeaf37f46p-8836L }, + { 0x3.8c641d8c7144c56cp-4L, -0xd.9ccf64003bcfe19p-2164L, -0x3.ef094c1261084a5cp-2164L, -0x3.ef094c1261084a58p-2164L }, + { -0x4.a18f061049fc9cbp-4L, 0x1.e06defabb32ffe1ep+1648L, -0xe.cd74e842dc9ff13p+1644L, -0xe.cd74e842dc9ff12p+1644L }, + { 0x4.97f2306d8c28e9dp-4L, -0x1.2a39e2ab6ffe536p-536L, -0x6.c970e37e84181a4p-540L, -0x6.c970e37e84181a38p-540L }, + { -0x2.e236a258e6dd6b5cp-4L, 0x3.2f025f0ea7bb3938p+7324L, -0xe.9aad918f2225785p+7320L, -0xe.9aad918f2225784p+7320L }, + { 0x3.1c35592c972c292cp-4L, -0x3.d19015724427ff7p+5180L, -0xf.a85299ffafa135ep+5176L, -0xf.a85299ffafa135dp+5176L }, + { -0x4.2943e5b07a55b8cp-4L, -0xa.9469f6ae3a4e6f4p+1964L, 0x4.98efa780ae2c64e8p+1964L, 0x4.98efa780ae2c64fp+1964L }, + { 0xe.c4a37f159ae949ep-8L, 0x1.c776d3c51e49998ap-4852L, 0x2.4da7c80b031f717cp-4856L, 0x2.4da7c80b031f718p-4856L }, + { -0x8.b6721f00e89d647p-8L, -0x3.76d26cae7f3a370cp-10612L, 0x2.c4d3a29814e11f84p-10616L, 0x2.c4d3a29814e11f88p-10616L }, + { 0x1.d44862fbc3ffe4e8p-112L, 0xb.b4e151abbff7d07p-5376L, 0x1.ee4d3e9b98db0a2ap-5484L, 0x1.ee4d3e9b98db0a2cp-5484L }, + { -0x2.12dbeddf1c572d24p-140L, 0x2.ff042155d43837b8p-456L, -0x8.f6a8f33c480a7f2p-596L, -0x8.f6a8f33c480a7f1p-596L }, + { 0x2.3c7141110977a1c8p-4L, 0x2.05648cc457e12568p-13128L, 0x6.1a52ec074b18dfc8p-13132L, 0x6.1a52ec074b18dfdp-13132L }, + { -0x2.464f6995d5846fc4p-4L, 0x5.b10ee7beb80f44c8p-8176L, -0x1.4257e6f5e91cfddep-8176L, -0x1.4257e6f5e91cfddcp-8176L }, + { 0x2.9d621c7f336f1a48p-4L, -0x1.d8b4cd85d3888762p-52L, -0x6.73a5b1d70e5b209p-56L, -0x6.73a5b1d70e5b2088p-56L }, + { -0x4.6cbaaf7a0ff40348p-4L, -0x1.9ebb345e0fe9f626p+152L, 0xc.1b0a270a799060ap+148L, 0xc.1b0a270a799060bp+148L }, + { 0x2.d68e2ba3eefebbfcp-4L, 0x8.2755e9d53631d79p+13464L, 0x1.ebbd2662baaccf46p+13464L, 0x1.ebbd2662baaccf48p+13464L }, + { -0x2.a56af544d1743bfp-4L, -0x8.debe114eff2fb6p-4048L, 0x2.503fe5daad061f4cp-4048L, 0x2.503fe5daad061f5p-4048L }, + { 0x2.f272a3677efcea3p-4L, -0x1.65eed16b0fbcd18p+3820L, -0x5.74cf60355c5bfdd8p+3816L, -0x5.74cf60355c5bfddp+3816L }, + { -0x3.a8152a324eb599fcp-4L, 0x6.42f937c40f3caep-11832L, -0x2.580a107ac781e86cp-11832L, -0x2.580a107ac781e868p-11832L }, + { 0x1.fa90f8ba8eb45d18p-4L, 0x4.97d111ff563d917p+672L, 0xc.5cc95af0b67a1aap+668L, 0xc.5cc95af0b67a1abp+668L }, + { -0x3.21d6a286a61d7cc4p-4L, -0xe.6ac05f4362737a7p-1760L, 0x4.8804f700b3804178p-1760L, 0x4.8804f700b380418p-1760L }, + { 0x3.bcec63e4fa22720cp-4L, 0x1.eb48022e5de68778p-2240L, 0x9.4cf74bdc0e3abdap-2244L, 0x9.4cf74bdc0e3abdbp-2244L }, + { -0x2.2cafb74c417a862cp-4L, -0x7.4ac89cd8c8343a4p+5320L, 0x1.896adaaf74423c38p+5320L, 0x1.896adaaf74423c3ap+5320L }, + { 0x4.747d8f2cd1e0b778p-4L, -0x7.89b9fbbca8b068b8p-10904L, -0x2.abdd7d16fc67e358p-10904L, -0x2.abdd7d16fc67e354p-10904L }, + { -0x1.6c4d52d87e228112p-4L, -0x6.db5f46e906978aa8p+6068L, 0xe.be49f013bde4911p+6064L, 0xe.be49f013bde4912p+6064L }, + { 0x4.7d3fe6ab59f609d8p-4L, -0x3.440be44d83299c4p+7040L, -0x1.2a4c3c114199e58ep+7040L, -0x1.2a4c3c114199e58cp+7040L }, + { -0x1.e480cff01c28fb9cp-4L, -0x4.d9f9d12975bd7c4p-12344L, 0xe.190f113ed0925d4p-12348L, 0xe.190f113ed0925d5p-12348L }, + { 0x2.8861f994981bf17cp-4L, -0xd.f58d50699b9fcecp+1284L, -0x2.f59c17dbe51eda7p+1284L, -0x2.f59c17dbe51eda6cp+1284L }, + { -0x3.1a3b6bf5fdf6fd38p-4L, -0x1.fc2d15ef2a625dacp+8468L, 0x9.e07f594916cb5fcp+8464L, 0x9.e07f594916cb5fdp+8464L }, + { 0x3.fd8b6443df9dc76p-4L, 0x6.2216263345a9de58p-3452L, 0x1.f85e4c88ba163cd4p-3452L, 0x1.f85e4c88ba163cd6p-3452L }, + { -0x3.70a228d1d553bf4cp-4L, -0x2.eb67d254460cc304p-9620L, 0x1.0504afba5f5c67a6p-9620L, 0x1.0504afba5f5c67a8p-9620L }, + { 0x5.cf949cfc0d27367p-152L, -0x3.05788e2f35ec3cd4p+14300L, -0x1.9543d4ed5bd3f968p+14152L, -0x1.9543d4ed5bd3f966p+14152L }, + { -0x4.019728c8p-16416L, 0x6.86d9d7ed1e2fc6p-12528L, -0x8p-16448L, -0x0p+0L }, + { 0x9.e6cc5abae024698p-8L, 0x2.833fcfa47e2d91ap+3004L, 0x2.33784faf5903c048p+3000L, 0x2.33784faf5903c04cp+3000L }, + { -0x3.67b9dd9843d29348p-4L, -0xf.d97f1711de15f9cp+1908L, 0x5.78d0d081f721bp+1908L, 0x5.78d0d081f721b008p+1908L }, + { 0x4.7a28ab2398fb352p-4L, 0x1.9bd5eed22e819bdep-3276L, 0x9.2974b9b5c14f70bp-3280L, 0x9.2974b9b5c14f70cp-3280L }, + { -0x3.081509267e970864p-4L, -0xd.1b186c2e3417901p+1864L, 0x3.f8d299ebb41104fp+1864L, 0x3.f8d299ebb41104f4p+1864L }, + { 0x4.6abc9681ac49cfdp-4L, -0x2.95224c7756c21458p+0L, -0xe.8847182bcf70294p-4L, -0xe.8847182bcf70293p-4L }, + { -0x7.2739454a8f4579bp-8L, 0x4.6f28415fd23d939p+14200L, -0x2.e698128be4a28434p+14196L, -0x2.e698128be4a2843p+14196L }, + { 0x1.d251fdcff8361a78p-4L, -0xb.d0fe6ed90e574e6p+212L, -0x1.d68b3c44dd6d6312p+212L, -0x1.d68b3c44dd6d631p+212L }, + { -0x1.be7ad3ad1b0e4a4p-4L, -0x6.497aa8a74bb2d87p-2628L, 0x1.0bfe1bb4299021acp-2628L, 0x1.0bfe1bb4299021aep-2628L }, + { 0x4.013e3e7e82bd3c2p-4L, 0x7.4bbb894be77050dp+12468L, 0x2.59ee0420ec379c6p+12468L, 0x2.59ee0420ec379c64p+12468L }, + { -0x3.3293e00e66ee8678p-4L, -0x5.530558acc4b5df88p-6048L, 0x1.b66bd84ef8a7f7aep-6048L, 0x1.b66bd84ef8a7f7bp-6048L }, + { 0x2.596e2190f3ee11cp-4L, -0x2.cd6c97393ef343bcp+1120L, -0x8.dcd9e903e4f5e01p+1116L, -0x8.dcd9e903e4f5ep+1116L }, + { -0xe.c481fc40bbce19fp-8L, 0x1.3b4ac09f6ebd1b0ep+1796L, -0x1.b06e1e656074da7p+1792L, -0x1.b06e1e656074da6ep+1792L }, + { 0x2.9f321f282784f3acp-4L, -0x1.d9decdb4b87520d6p+8416L, -0x6.7bdfcc4fcaf35388p+8412L, -0x6.7bdfcc4fcaf3538p+8412L }, + { -0x3.1abd020d7e543628p-4L, 0xd.6d80dc94539115ep-6852L, -0x4.2dbeb1b3e077f1ep-6852L, -0x4.2dbeb1b3e077f1d8p-6852L }, + { 0x1.a74119aefdfb086ap-4L, 0x1.4dd68c499218991cp-9528L, 0x2.f5c7d01357aeb918p-9532L, 0x2.f5c7d01357aeb91cp-9532L }, + { -0x3.9cc7932ded57df7p-4L, 0x1.c00dbd725f27ace4p+392L, -0xa.5694f0b8c0a7444p+388L, -0xa.5694f0b8c0a7443p+388L }, + { 0x3.0c65989eee333da8p-4L, -0xc.8ed445e1ea26da6p+944L, -0x3.28d9b866e998f3p+944L, -0x3.28d9b866e998f2fcp+944L }, + { -0x1.01dc461ca1f30d7cp-4L, 0x2.219473696b04364cp+5028L, -0x3.32e1826689d1e408p+5024L, -0x3.32e1826689d1e404p+5024L }, + { 0x2.032a2322395b1f7cp-4L, -0x5.da9f94100d42a778p+4556L, -0x1.00234c58a1593fa4p+4556L, -0x1.00234c58a1593fa2p+4556L }, + { -0x1.37d775d6d37abbc6p-4L, -0xd.e2cee7a54e7c7dfp-2844L, 0x1.961ce3d5d092c2bcp-2844L, 0x1.961ce3d5d092c2bep-2844L }, + { 0x5.e788f67p-16416L, -0x1.b20009ea27ed12d4p+2716L, -0xe.70f136a6f3fd9c9p-13700L, -0xe.70f136a6f3fd9c8p-13700L }, + { -0xe.54631f1d0a92519p-108L, 0x2.3b61b0ed36fec68cp-11996L, -0x2.e245772cd7482448p-12100L, -0x2.e245772cd7482444p-12100L }, + { 0x4.78666b09054db02p-4L, 0xd.9866ac659888197p-12280L, 0x4.d525ce8fca3be678p-12280L, 0x4.d525ce8fca3be68p-12280L }, + { -0x2.b6ea5b47429cf1ccp-8L, 0x2.6614f05e9e7a9d2cp+13784L, -0x9.71b7a8a09362cc3p+13776L, -0x9.71b7a8a09362cc2p+13776L }, + { 0x1.9fc564d5cd252834p-4L, -0x7.78b432f287942418p+8704L, -0x1.0ac7c8898679cf7cp+8704L, -0x1.0ac7c8898679cf7ap+8704L }, + { -0x3.627629b0fc2138f4p-4L, 0x2.4adc5340e0bb85bp-14064L, -0xc.93a314133e66097p-14068L, -0xc.93a314133e66096p-14068L }, + { 0xd.e2670359c5e7cep-8L, 0x1.776c2223c9793e74p+7492L, 0x1.c9b37d76bc51a286p+7488L, 0x1.c9b37d76bc51a288p+7488L }, + { -0x1.ea4c7df916a93fa4p-4L, 0x1.77873596c55066eap-4292L, -0x4.512b68b4a46ce678p-4296L, -0x4.512b68b4a46ce67p-4296L }, + { 0x7.782d2513f5714bdp-8L, -0xd.cf27b2fef93cd6fp+900L, -0x9.2ae14b6070abef1p+896L, -0x9.2ae14b6070abefp+896L }, + { -0x4.40fc24e1abcef118p-4L, -0x1.acf23a9f7fc1bac6p+4612L, 0xb.f42951fd6c23841p+4608L, 0xb.f42951fd6c23842p+4608L }, + { 0x1.a8824a9a4cd5dc64p-4L, -0x1.c0f84566366a7b42p-1364L, -0x3.fdfecdec46081674p-1368L, -0x3.fdfecdec4608167p-1368L }, + { -0x2.656451181fd48ae8p-4L, -0x8.112f7800783ce43p+14416L, 0x1.e35a03c5b235c0bp+14416L, 0x1.e35a03c5b235c0b2p+14416L }, + { 0x8.870c70596055849p-8L, 0x1.07c83cf4f6c4df66p+2828L, 0xc.7855e9bc9829172p+2820L, 0xc.7855e9bc9829173p+2820L }, + { -0x2.b8afdde3454b599p-4L, 0x2.8eebc607cfde77d8p-8824L, -0xb.027de4727525e58p-8828L, -0xb.027de4727525e57p-8828L }, + { 0x2.31f1d5227156b604p-4L, -0x1.2b06750af8061c3p+4092L, -0x3.77668bc7db26768p+4088L, -0x3.77668bc7db26767cp+4088L }, + { -0x2.032456443411d81p-4L, -0xb.f31c2fef2a2645fp-1980L, 0x2.5131763f6e042228p-1980L, 0x2.5131763f6e04222cp-1980L }, + { 0x1.3042297b1a544afep-4L, 0x3.f1be09c7487defap+14152L, 0x6.8612fdbf3a6c6758p+14148L, 0x6.8612fdbf3a6c676p+14148L }, + { -0x4.20c8cc889aaca378p-4L, 0x1.6010a2abc0602b0ep-14432L, -0x9.791e17dde1c914ep-14436L, -0x9.791e17dde1c914dp-14436L }, + { 0x2.776cad4e7559584cp-8L, 0xb.e51e58c1c7b3dbfp+14964L, 0x2.a1fe9ebfdf8a86ap+14960L, 0x2.a1fe9ebfdf8a86a4p+14960L }, + { -0xf.b02a1730396127ep-8L, -0xc.11b48ff5e5ec64ep+7368L, 0x1.19e46bdcea15f47cp+7368L, 0x1.19e46bdcea15f47ep+7368L }, + { 0x4.1edb9c5a8639aaap-4L, 0x1.bbf840a1aee939e4p+13432L, 0x9.2c66ade98f2991ep+13428L, 0x9.2c66ade98f2991fp+13428L }, + { -0x2.e5ef99ea8924db7p-4L, 0x3.5a17dd1b1d7f10fcp-12416L, -0xf.76499bc4522f185p-12420L, -0xf.76499bc4522f184p-12420L }, + { 0x5.2ceb4e8ad3a63198p-56L, 0x1.10226b66be92f5ep-13504L, 0x7.efec9208539fa86p-13560L, 0x7.efec9208539fa868p-13560L }, + { -0x1.609defa4c28c41aap-68L, -0x1.9abae50c07573824p-3260L, 0x3.3032106521e2a38p-3328L, 0x3.3032106521e2a384p-3328L }, + { 0x1.17954e967e739b96p-4L, 0xf.d9c4d8361d42b6cp-12924L, 0x1.828a9fe2da6d8d6ap-12924L, 0x1.828a9fe2da6d8d6cp-12924L }, + { -0x2.9a3fed5ce81a8d6cp-4L, -0xc.5a8bd8936a03dp-13656L, 0x3.29f77393bb45b71cp-13656L, 0x3.29f77393bb45b72p-13656L }, + { 0x2.c752af068bb180e4p-4L, 0x3.de670419142bc428p-14816L, 0xe.4cd016833918784p-14820L, 0xe.4cd016833918785p-14820L }, + { -0x3.2082fc347aa2e55p-4L, 0x4.e64b83b064446a3p+10008L, -0x1.89807286643a3178p+10008L, -0x1.89807286643a3176p+10008L }, + { 0x2.79eaa550e420d934p-4L, 0x1.f2ae9ee8ba0d3204p-868L, 0x6.786a2bba8c07b1dp-872L, 0x6.786a2bba8c07b1d8p-872L }, + { -0xa.fc3eb30d9c09d39p-8L, -0x2.5ab3fc8e3cf96824p-2280L, 0x2.622ee8401eb2be9p-2284L, 0x2.622ee8401eb2be94p-2284L }, + { 0x3.d81a8d8a8d16a8e8p-4L, -0x3.ce388047558bafc8p-8232L, -0x1.2ea2546e51c6e8f4p-8232L, -0x1.2ea2546e51c6e8f2p-8232L }, + { -0x3.056f019da2d3178cp-4L, -0x1.323a89ec36541c0cp+6516L, 0x5.c74b2bd614a49e08p+6512L, 0x5.c74b2bd614a49e1p+6512L }, + { 0x2.bc32f485a0d1cda4p-4L, -0x2.80bd89a1c7a42c04p+10352L, -0x9.1e18f19057194f5p+10348L, -0x9.1e18f19057194f4p+10348L }, + { -0x1.680e5f4f178505bp-4L, -0xf.1a49a93ff5772ep-1880L, 0x2.0138ef578553b23p-1880L, 0x2.0138ef578553b234p-1880L }, + { 0x2.fc8ccc84ce54f5d4p-8L, 0x3.e472948a7445df58p+11256L, 0x1.0ac7c7a20eca1108p+11252L, 0x1.0ac7c7a20eca110ap+11252L }, + { -0x4.6e1a1a157ff363bp-4L, -0x9.7fc1e541c82e26dp+12412L, 0x4.7151555968fe228p+12412L, 0x4.7151555968fe2288p+12412L }, + { 0x2.58ccc597cdeae488p-4L, 0xf.172c9598837df0ep-3292L, 0x2.fad4e99f0ed6a2ap-3292L, 0x2.fad4e99f0ed6a2a4p-3292L }, + { -0x3.2be4288461f1d2ccp-4L, 0xf.f5f8e2e97cc43a7p-6300L, -0x5.16417a8368ea715p-6300L, -0x5.16417a8368ea7148p-6300L }, + { 0x1.fdf693f75f71c5f8p-4L, 0xf.1536891b917c5b4p-12272L, 0x2.8da7609b1e39234p-12272L, 0x2.8da7609b1e392344p-12272L }, + { -0x3.2561fe08d06ed66p-4L, -0xa.bc73aa7d823faf6p-2276L, 0x3.641e7eed6d3d515cp-2276L, 0x3.641e7eed6d3d516p-2276L }, + { 0x1.1bc04a8e9588d6d2p-8L, -0x1.c52369a0cacff0aep-688L, -0x2.d30b2a4ee51c61dcp-696L, -0x2.d30b2a4ee51c61d8p-696L }, + { -0x1.d61ba0502067409ep-4L, 0x3.73d3d6eaa64d0e48p-13916L, -0x9.b7284d8b255d1e5p-13920L, -0x9.b7284d8b255d1e4p-13920L }, + { 0x1.c4a0b08d7654ecb4p-4L, 0x1.b5b6c832a020e5ecp-4332L, 0x4.2306f7cb22efbd4p-4336L, 0x4.2306f7cb22efbd48p-4336L }, + { -0x3.a5b84c3a8b5a86d8p-4L, 0x3.33e3dabe68c35688p+1484L, -0x1.3206409c6c6fc45p+1484L, -0x1.3206409c6c6fc44ep+1484L }, + { 0x9.dcdfcf8p-16420L, -0x5.4a43e598fc3723cp-9444L, -0x8p-16448L, -0x0p+0L }, + { -0x7.c97e52a8p-16416L, -0x4.c1408d8a28bcc7ep+10200L, 0x3.56b150006e157e34p-6212L, 0x3.56b150006e157e38p-6212L }, + { 0x5.83b36a0816afd008p-8L, 0x6.728edc7190e888ap-8300L, 0x3.2bfe0fbf8883065p-8304L, 0x3.2bfe0fbf88830654p-8304L }, + { -0x1.a6bb6ebf8bf709p-4L, -0x1.32eaa51c63cff0c2p-12444L, 0x3.03b810bfb07b3e04p-12448L, 0x3.03b810bfb07b3e08p-12448L }, + { 0x3.adb8baaf789553dp-4L, 0x7.b3f922ab6d1fc2d8p-11600L, 0x2.4cbe69773df6c864p-11600L, 0x2.4cbe69773df6c868p-11600L }, + { -0x1.201e22e464402deap-4L, -0x3.bcdf6b0e23c23b8p-3112L, 0x6.4b04dff5faf1ab6p-3116L, 0x6.4b04dff5faf1ab68p-3116L }, + { 0xa.db12b542cfd4967p-8L, -0x2.cc4f4ec335a9b73p-3480L, -0x2.aeb2bfd2569213f8p-3484L, -0x2.aeb2bfd2569213f4p-3484L }, + { -0x1.4bacae5b8139ebf4p-4L, 0x3.018ab0d86a85aa18p-2564L, -0x5.dbfb9574a7700e9p-2568L, -0x5.dbfb9574a7700e88p-2568L }, + { 0xc.37926f622957e79p-8L, 0x6.d9a09257a9de7178p-9644L, 0x7.5f1b82a670566b2p-9648L, 0x7.5f1b82a670566b28p-9648L }, + { -0x2.ab328a75d78456d4p-4L, 0x3.984ce041f93d20dcp+8376L, -0xf.246f0c6123fd2c2p+8372L, -0xf.246f0c6123fd2c1p+8372L }, + { 0x5.0ac37ce140a5e408p-8L, 0xc.85f521d6b73e5cp-12304L, 0x5.a35e190d7bbadde8p-12308L, 0x5.a35e190d7bbaddfp-12308L }, + { -0x2.84eaed8e54bf7608p-4L, -0x3.b386e93fc25a36ep-120L, 0xe.a327ea760c0cc07p-124L, 0xe.a327ea760c0cc08p-124L }, + { 0x3.20e1ecc2bf932e94p-4L, -0x4.f0d6473e6cf14dbp-10104L, -0x1.45e1efc080d53264p-10104L, -0x1.45e1efc080d53262p-10104L }, + { -0x3.af399facb8e06b6cp-4L, -0x1.a6fe04423bc64194p-2412L, 0x9.fb819c61aa22e65p-2416L, 0x9.fb819c61aa22e66p-2416L }, + { 0xd.f2607f2eff81943p-8L, 0x1.db63aa1cc3714696p+5352L, 0x2.461d3054010ba93cp+5348L, 0x2.461d3054010ba94p+5348L }, + { -0x2.1ca9e269366503acp-4L, 0x8.85ca099da14eecfp+11944L, -0x1.bd9606e084b91422p+11944L, -0x1.bd9606e084b9142p+11944L }, + { 0x3.8f814c8a783b37e4p-4L, 0xc.dc92cfd134c1f43p+8032L, 0x3.ba705b78dbdfdb08p+8032L, 0x3.ba705b78dbdfdb0cp+8032L }, + { -0xa.363a7e007bb490cp-8L, 0x3.4fc1153a0181986p+2104L, -0x3.1c9855bfaf3c0b24p+2100L, -0x3.1c9855bfaf3c0b2p+2100L }, + { 0x4.8f405305d971325p-4L, 0x1.68828b76a000f3cap+10416L, 0x8.2690c5f0b9e8f9ep+10412L, 0x8.2690c5f0b9e8f9fp+10412L }, + { -0x3.338c408bb3a0c4a8p-4L, -0xe.159d1696dfd0e91p+10916L, 0x4.894cf2237970296p+10916L, 0x4.894cf22379702968p+10916L }, + { 0x4.8f4674e0d5a0d808p-4L, 0xa.c362f68453e1677p+3476L, 0x3.e4bf65fe96e2af2p+3476L, 0x3.e4bf65fe96e2af24p+3476L }, + { -0xd.54b8a67fe103072p-8L, 0x2.cdcd722c20086f78p-9008L, -0x3.7618e9e91de0ea8cp-9012L, -0x3.7618e9e91de0ea88p-9012L }, + { 0x1.7902a678p-16416L, 0x1.19427dcda0480416p+3436L, 0x2.559440aae40e6a3p-12980L, 0x2.559440aae40e6a34p-12980L }, + { -0x1.c36218d9ea12b06p-120L, -0xc.ce2bca2cbcab86p+11308L, 0x2.092f42c661962da4p+11192L, 0x2.092f42c661962da8p+11192L }, + { 0x4.3848af1238619848p-4L, 0x1.06b2c98753a26482p+4016L, 0x5.8b6a91a3e86c1628p+4012L, 0x5.8b6a91a3e86c163p+4012L }, + { -0x2.1a3e861da87eb79cp-4L, 0x1.4ec5569f83ab5736p-9836L, -0x4.40aa56c3c5c637e8p-9840L, -0x4.40aa56c3c5c637ep-9840L }, + { 0x1.0ae262cde6391e24p-4L, 0x5.73257b4e6064d01p+6604L, 0x7.f0d1589033cf2398p+6600L, 0x7.f0d1589033cf23ap+6600L }, + { -0x4.27fce65cac88f6e8p-4L, -0x1.f57725c0787861ecp-3256L, 0xd.99b231a6d0c4c1dp-3260L, 0xd.99b231a6d0c4c1ep-3260L }, + { 0x3.a27dda9eab4a71cp-4L, -0x1.c7f592e6977ce3bep+12420L, -0x8.6a945925111c26ep+12416L, -0x8.6a945925111c26dp+12416L }, + { -0x2.a793421cbf6f9968p-4L, 0x5.48fc6bc3d7c0194p+1292L, -0x1.621d63e8f5d14274p+1292L, -0x1.621d63e8f5d14272p+1292L }, + { 0x4.0c3cdf0761d114bp-4L, -0x1.a94536dcae3efe9ap-4444L, -0x8.a5f06bea2cc4c7bp-4448L, -0x8.a5f06bea2cc4c7ap-4448L }, + { -0xa.f93df896ce6a1p-8L, -0x5.c36184a826a997c8p+10672L, 0x5.d40fc05d1c8d8c78p+10668L, 0x5.d40fc05d1c8d8c8p+10668L }, + { 0x4.166c1433f1fd7bbp-4L, -0x3.fd85a4b30da5905cp+1568L, -0x1.4f4bec3a523108b4p+1568L, -0x1.4f4bec3a523108b2p+1568L }, + { -0x4.269ac20097d48278p-4L, 0x3.1537ec91418ea6d4p+3920L, -0x1.55f44918ad45177p+3920L, -0x1.55f44918ad45176ep+3920L }, + { 0x4.69a871365aa2e12p-4L, -0xa.36231bab07402b6p-4836L, -0x3.9699940c44fff68p-4836L, -0x3.9699940c44fff67cp-4836L }, + { -0x2.e0e69529aa3c2148p-4L, -0xc.898efcf06fac3c9p-10916L, 0x3.96631e40f648290cp-10916L, 0x3.96631e40f648291p-10916L }, + { 0x8.0d6f02cf24f9c97p-8L, 0x2.6ae43fbbb8290e98p+8564L, 0x1.ba711272f9e989e8p+8560L, 0x1.ba711272f9e989eap+8560L }, + { -0x3.5f039ab81ea9c368p-4L, -0xd.8fb34ea26dcd466p+10808L, 0x4.a10f4862e4c525c8p+10808L, 0x4.a10f4862e4c525dp+10808L }, + { 0x1.3d60e214e24fd8e2p-4L, -0x1.570c61df14ef3c2cp+188L, -0x2.4ef6c43084fc9dep+184L, -0x2.4ef6c43084fc9ddcp+184L }, + { -0x6.40ba95b8e8b92fc8p-8L, 0x1.be3c2fefa23edde8p-11668L, -0xf.eb712b3687d7e23p-11676L, -0xf.eb712b3687d7e22p-11676L }, + { 0x2.732d3b1aa6d2beep-4L, -0x3.cdaf1e5edd4c86p+184L, -0xc.821fcc2bcca0a5dp+180L, -0xc.821fcc2bcca0a5cp+180L }, + { -0x2.152e0397420f72fcp-4L, 0x2.8364ae6977782604p-11632L, -0x8.172bae23dd68d33p-11636L, -0x8.172bae23dd68d32p-11636L }, + { 0x3.e5df21cab65c997cp-4L, -0xf.2ffda7297446dd8p+564L, -0x4.c6f49497a19568p+564L, -0x4.c6f49497a19567f8p+564L }, + { -0x1.04b57b83b68184dep-4L, -0x4.ea4ab92cea09eec8p+11136L, 0x7.762e3332d594d7fp+11132L, 0x7.762e3332d594d7f8p+11132L }, + { 0x5.5594498p-16420L, 0x1.eabcf8252879b3c6p-2564L, 0x0p+0L, 0x8p-16448L }, + { -0x4.c0ce2b247d038ac8p-196L, 0x6.aab669b77225bdf8p+14936L, -0x2.db7821b4f7e6fe48p+14744L, -0x2.db7821b4f7e6fe44p+14744L }, + { 0x3.baced53f1471e364p-4L, 0x1.f4152fd9e1338794p+11508L, 0x9.72c9bd6a87c42aap+11504L, 0x9.72c9bd6a87c42abp+11504L }, + { -0x2.317130a7a75d4aa4p-4L, 0x4.3a585af61da3746p+10124L, -0xe.63319f6181f397cp+10120L, -0xe.63319f6181f397bp+10120L }, + { 0x4.1c54e5eb63fd28fp-4L, -0xc.0148aba29b8d557p-13200L, -0x3.f5d7e7e9f34a935cp-13200L, -0x3.f5d7e7e9f34a9358p-13200L }, + { -0x3.a93752f48b02534p-8L, 0x2.d86805c835243508p+7344L, -0xf.2300d704ac6742ep+7336L, -0xf.2300d704ac6742dp+7336L }, + { 0xc.f022cc79b221c33p-8L, -0x1.7bce210b7a3b4ce4p+13136L, -0x1.b03f9fb7b732302cp+13132L, -0x1.b03f9fb7b732302ap+13132L }, + { -0x3.2a0c0f7441062828p-4L, -0x3.b3492f1fb9e61c04p+5492L, 0x1.2d25592e5dfb1a5p+5492L, 0x1.2d25592e5dfb1a52p+5492L }, + { 0x1.5e4534702331dd36p-4L, 0xe.23089b23489992ap-8584L, 0x1.ac6bc81aca47148ep-8584L, 0x1.ac6bc81aca47149p-8584L }, + { -0xb.335bf0873459e2ap-8L, -0x2.d5f5698f339a3b6cp+12224L, 0x2.edb30cd4b7211294p+12220L, 0x2.edb30cd4b7211298p+12220L }, + { 0x2.a703a7cbf8389048p-4L, -0x3.c02be3f7a5fcc11p-10844L, -0xd.479c75b64677e6ep-10848L, -0xd.479c75b64677e6dp-10848L }, + { -0x4.6a8b51e9bd44a3d8p-4L, -0x9.16e2136af0bd999p+5352L, 0x4.3c3d2021a09b0ccp+5352L, 0x4.3c3d2021a09b0cc8p+5352L }, + { 0x2.2dedef8b8456de34p-4L, -0x1.612ac453131ff6ccp+12644L, -0x4.110b3f69085532bp+12640L, -0x4.110b3f69085532a8p+12640L }, + { -0xc.1dba691316d74bdp-8L, 0x2.ec398343a2ca763p-1556L, -0x3.456805b257b0ee1p-1560L, -0x3.456805b257b0ee0cp-1560L }, + { 0xe.ec733d0bbf8686ep-8L, -0x3.cf1395284a6357fp-6892L, -0x4.fb48374fa922b608p-6896L, -0x4.fb48374fa922b6p-6896L }, + { -0x1.edcef2a6b293fd46p-4L, -0x5.f75c87391b381cb8p+12600L, 0x1.1b1516b3d9f8b04cp+12600L, 0x1.1b1516b3d9f8b04ep+12600L }, + { 0x1.1ee70cc7cae8441ap-4L, 0xd.5bd215637191857p-9180L, 0x1.4e0453af199cc7d6p-9180L, 0x1.4e0453af199cc7d8p-9180L }, + { -0x1.3b763982b3071dd4p-4L, 0x9.e9da1b99800a76dp-4788L, -0x1.256fd3aa961492bap-4788L, -0x1.256fd3aa961492b8p-4788L }, + { 0x1.dcdb59c7c235dbc2p-4L, -0x2.d021db0eb4e66bc4p+4172L, -0x7.26a25cdf864b2e2p+4168L, -0x7.26a25cdf864b2e18p+4168L }, + { -0x7.39e6166b4e7ff328p-8L, 0xd.d257bb858d37bdep+5592L, -0x9.22a66ce89f4a1d8p+5588L, -0x9.22a66ce89f4a1d7p+5588L }, + { 0x2.cbc98bdd8b82901p-4L, 0x3.6f0885306061a098p+1264L, 0xc.c3fea6c91774964p+1260L, 0xc.c3fea6c91774965p+1260L }, + { -0x2.7c3e61d780a4f324p-4L, -0x1.da01a42e71e30548p+7012L, 0x7.37128b7293c62da8p+7008L, 0x7.37128b7293c62dbp+7008L }, + { 0x1.637d8202e9a84f9p-64L, -0x3.95f019facb81ca2p-352L, -0x7.2ef9571efed13f38p-416L, -0x7.2ef9571efed13f3p-416L }, + { -0x6.82a90c9p-16416L, 0x8.4b9ea0f6dd41af6p-3128L, -0x8p-16448L, -0x0p+0L }, + { 0xb.15e9277124ef54ap-8L, 0x3.181d10559801b24p-3016L, 0x3.071c007555f37dp-3020L, 0x3.071c007555f37d04p-3020L }, + { -0x2.34958a751bd7e2b4p-4L, -0x7.1e0c4f162e18cb3p-14368L, 0x1.85dc9e96b295d1f4p-14368L, 0x1.85dc9e96b295d1f6p-14368L }, + { 0x1.baa38808f4d9ef8p-4L, -0x1.94cc68b2b3c4a3cap+6596L, -0x3.bed8f66fe0b67d94p+6592L, -0x3.bed8f66fe0b67d9p+6592L }, + { -0x2.9c8a581b1fc5d614p-4L, -0x2.8c01857641e55648p-2264L, 0xa.79d78516d7f224p-2268L, 0xa.79d78516d7f2241p-2268L }, + { 0xf.b589bcceb220068p-8L, -0x1.4789d33b87e903d2p+5568L, -0x1.c2450650774c5p+5564L, -0x1.c2450650774c4ffep+5564L }, + { -0x2.8d5e2c4a97b5ca14p-4L, 0xa.6c4e4d3fd85b1d1p-2464L, -0x2.9cf440e73f0f258p-2464L, -0x2.9cf440e73f0f257cp-2464L }, + { 0x1.fac5b9a230ace1ccp-4L, -0xc.183e2d13feeccbp+5796L, -0x2.090f003628c73a5p+5796L, -0x2.090f003628c73a4cp+5796L }, + { -0x2.3a1aa1ebf9d944d8p-4L, 0xb.56f3fb671e6d7bp-10204L, -0x2.73b180956d044ca8p-10204L, -0x2.73b180956d044ca4p-10204L }, + { 0x3.f1ed5917ebae5ee8p-4L, 0x1.5d25d26ea685965ap-9392L, 0x6.f0398d9603c092cp-9396L, 0x6.f0398d9603c092c8p-9396L }, + { -0x4.2ed20be58e7ce458p-4L, -0x1.bb72045b4fb64006p+11436L, 0xc.1df41156acd8b46p+11432L, 0xc.1df41156acd8b47p+11432L }, + { 0x1.533ed177d8f43096p-4L, -0x6.6c5aad8f16c7612p-12240L, -0xb.cc4d7e98c47615cp-12244L, -0xb.cc4d7e98c47615bp-12244L }, + { -0x2.b3759933edcfbb8cp-4L, -0x5.be3632756b1f6c08p-13700L, 0x1.882fe94f6b50223p-13700L, 0x1.882fe94f6b502232p-13700L }, + { 0x4.71542952f2eb2118p-4L, -0xf.bc3571405a814dbp-12400L, -0x5.90065e0286f0d738p-12400L, -0x5.90065e0286f0d73p-12400L }, + { -0x2.17fa44980470472p-4L, 0xb.d365be5d38977b2p-484L, -0x2.648810e10755e434p-484L, -0x2.648810e10755e43p-484L }, + { 0x3.a3076d42e4a727a4p-4L, 0x1.16e61b22825583d6p-10652L, 0x5.269729e108bbd29p-10656L, 0x5.269729e108bbd298p-10656L }, + { -0x3.54041d65782d11a8p-4L, -0x3.82c837279f08c5c8p-2472L, 0x1.2e64f5ccd94f2862p-2472L, 0x1.2e64f5ccd94f2864p-2472L }, + { 0x4.6fa9ede403127e4p-4L, -0x1.71f2e5247996097cp+11700L, -0x8.29ca8ac57dfca06p+11696L, -0x8.29ca8ac57dfca05p+11696L }, + { -0x2.e31e7f5102321e84p-4L, -0x1.06117dc5bf40339ep+6984L, 0x4.b3d0402392c36ffp+6980L, 0x4.b3d0402392c36ff8p+6980L }, + { 0x3.b9638838b09138f4p-4L, -0x3.7b942a0763ad15e4p+10616L, -0x1.0d2953cf22d7307ap+10616L, -0x1.0d2953cf22d73078p+10616L }, + { -0x4.91ac63ed12ffa698p-4L, 0xf.ca607d23e02b6a5p-5416L, -0x7.a90ecaa3a7c85628p-5416L, -0x7.a90ecaa3a7c8562p-5416L }, + { 0x3.bd32cd8p-16420L, 0xc.64d8265a9554331p+13480L, 0x4.2db54f6499fee318p-2936L, 0x4.2db54f6499fee32p-2936L }, + { -0x7.30ab6348p-16416L, 0x2.d01e62e5954e5ecp-84L, -0x8p-16448L, -0x0p+0L }, + { 0x4.67c806cb2037368p-4L, -0x1.eee94944aabe7324p+14052L, -0xa.da76434365cbe5p+14048L, -0xa.da76434365cbe4fp+14048L }, + { -0x9.63a7f9a9b4e3772p-8L, -0x6.9750c01b7eab2c18p-6576L, 0x5.af5d76a3b96d562p-6580L, 0x5.af5d76a3b96d5628p-6580L }, + { 0x3.a890e71f965c423p-4L, 0x2.65754ef7508e6b2cp+14816L, 0xb.63ec8116f9623b9p+14812L, 0xb.63ec8116f9623bap+14812L }, + { -0x4.49c1355a26341ebp-4L, -0xa.2df5b84e07b2b1dp+2576L, 0x4.94ef7cdabf583378p+2576L, 0x4.94ef7cdabf58338p+2576L }, + { 0x3.592044d31e941f3cp-4L, -0xd.a2a1544a13a75a8p+8764L, -0x3.bcdd3b58fc6b4dccp+8764L, -0x3.bcdd3b58fc6b4dc8p+8764L }, + { -0x2.1c5be0eceea3074cp-4L, 0x9.8705b776af68ab6p+12632L, -0x1.f1d1b127094cc7d8p+12632L, -0x1.f1d1b127094cc7d6p+12632L }, + { 0x1.918ff257bb0d693cp-4L, 0xe.4262f654fe7fbd6p+7432L, 0x1.ec89a740290f2b92p+7432L, 0x1.ec89a740290f2b94p+7432L }, + { -0x4.4c3ff5e8f02ea658p-4L, 0x2.44e6f663c6e96414p+2392L, -0x1.062905420850e93p+2392L, -0x1.062905420850e92ep+2392L }, + { 0x4.25a93aaf3e8e66d8p-4L, -0xa.1d09747650d55b9p+9676L, -0x3.5cdba7179be56514p+9676L, -0x3.5cdba7179be5651p+9676L }, + { -0x7.4029c8dbfe579468p-8L, 0x1.c03a669c155fa5f8p+9484L, -0x1.29459dde5831c58ap+9480L, -0x1.29459dde5831c588p+9480L }, + { 0x4.99a9a4d5bf45f348p-8L, 0xa.41177495779f599p-6252L, 0x4.37364b1fa5c8e98p-6256L, 0x4.37364b1fa5c8e988p-6256L }, + { -0x2.24107ead42d5b40cp-8L, 0x1.c65fcf3a7b070d68p-10904L, -0x5.814bc88b1eff00f8p-10912L, -0x5.814bc88b1eff00fp-10912L }, + { 0xd.7bd18c92836d9b7p-8L, -0x2.fe022bf9a8eac0f8p+4008L, -0x3.8b9dbb6814dca604p+4004L, -0x3.8b9dbb6814dca6p+4004L }, + { -0x2.bd9ef84dc1262334p-4L, -0x1.926d2e72dc294662p+8176L, 0x6.d15c01dce8da9378p+8172L, 0x6.d15c01dce8da938p+8172L }, + { 0x1.79677266716881dep-4L, -0x3.9250255d51f10438p-8936L, -0x7.442fb2c4a2d081ap-8940L, -0x7.442fb2c4a2d08198p-8940L }, + { -0xd.23ebb0103a3412p-8L, 0x1.0c7d8c40c9f7f63cp-10576L, -0x1.4692db88dd7f76dep-10580L, -0x1.4692db88dd7f76dcp-10580L }, + { 0x3.c37ee7fcc3f66618p-4L, -0x1.0b426c0abe2f515p-10024L, -0x5.1746c07ac5fd95a8p-10028L, -0x5.1746c07ac5fd95ap-10028L }, + { -0x2.64319ac6eea8ea44p-4L, 0x2.14977aea96547074p-8036L, -0x7.c633388965b5c9p-8040L, -0x7.c633388965b5c8f8p-8040L }, + { 0x4.36557dfc7b7a0858p-4L, -0xb.5f490bd4a0d58a3p-8256L, -0x3.d58fc1d6c174b18p-8256L, -0x3.d58fc1d6c174b17cp-8256L }, + { -0x2.118c4c79edf47354p-4L, 0x5.7bbb5596a817d228p-2732L, -0x1.185caaa41d1fcbf8p-2732L, -0x1.185caaa41d1fcbf6p-2732L }, + { 0x2.2dfb2465030d9704p-120L, -0x3.2070b9ab6c091d04p+156L, -0x9.d4ffa1b506ada6fp+36L, -0x9.d4ffa1b506ada6ep+36L }, + { -0x1.b8ca4718dfb949b4p-156L, 0x2.b703c4e83381ac98p-13808L, -0x6.be79c4120e72058p-13964L, -0x6.be79c4120e720578p-13964L }, + { 0x3.aa7e6497bf65cec8p-4L, 0x2.207f40048a485988p+8000L, 0xa.20f27e1acc74886p+7996L, 0xa.20f27e1acc74887p+7996L }, + { -0x4.a61b8649abf09bdp-4L, -0x6.463247ab1fb7f22p-9052L, 0x3.1b719641a4a7976cp-9052L, 0x3.1b719641a4a7977p-9052L }, + { 0x3.7f3e92fee7a6f28p-4L, -0x2.0b71289ec2fa384cp+13492L, -0x9.546f7189f8f4635p+13488L, -0x9.546f7189f8f4634p+13488L }, + { -0x2.48a19098f3bb9008p-4L, 0xb.8b1a411e3e76627p-5852L, -0x2.90922f5ecf5c1fd4p-5852L, -0x2.90922f5ecf5c1fdp-5852L }, + { 0x3.b47754510462f6c4p-4L, -0x2.0bfc7264e887cdc8p+7904L, -0x9.d734f5619b3ab5bp+7900L, -0x9.d734f5619b3ab5ap+7900L }, + { -0x1.9703efc23286a644p-4L, 0x5.4bd8b1a807b11328p-15000L, -0xc.cb8cd9e7e25290cp-15004L, -0xc.cb8cd9e7e25290bp-15004L }, + { 0x3.765f83baff0c21fcp-4L, -0xf.dcbdd271ed9656bp+1780L, -0x4.7ba2cfd8cf705ba8p+1780L, -0x4.7ba2cfd8cf705bap+1780L }, + { -0x2.d47396eb2be5851p-4L, -0xa.33e2e879179697fp+1788L, 0x2.dd6dda56ba24386p+1788L, 0x2.dd6dda56ba243864p+1788L }, + { 0x2.a803fd68ec7649e8p-4L, 0xb.02935a9215a3cacp+8628L, 0x2.7092c54d30c5f24p+8628L, 0x2.7092c54d30c5f244p+8628L }, + { -0x3.0abba9ed50933008p-4L, -0xa.646a2e2861abb61p+11556L, 0x3.295a5daefccd137cp+11556L, 0x3.295a5daefccd138p+11556L }, + { 0x1.4fddcbc604cd0d02p-4L, 0x2.bb83c03d681805d8p-13988L, 0x4.f88acdec70c270ep-13992L, 0x4.f88acdec70c270e8p-13992L }, + { -0x3.13fe026e5c2ebb5cp-4L, -0x2.e6c29d1a543973dp-14108L, 0xe.4f547fb973cd189p-14112L, 0xe.4f547fb973cd18ap-14112L }, + { 0x6.fd3591d417b2bea8p-8L, 0x7.3b0323418d7119bp+10092L, 0x4.7edc810794e8dc88p+10088L, 0x4.7edc810794e8dc9p+10088L }, + { -0x3.d7d6efab7eaa891p-4L, -0x1.e2d85877948f2bfep+3328L, 0xb.f59e66f55ab1a34p+3324L, 0xb.f59e66f55ab1a35p+3324L }, + { 0x3.866120802df86e44p-4L, 0xb.ede747cdb5bd40ap-13692L, 0x3.6d37b2c1b0fc0a44p-13692L, 0x3.6d37b2c1b0fc0a48p-13692L }, + { -0x1.837e3a3951b222fep-4L, -0x9.33ad5ce66f0989cp-12372L, 0x1.51c022680d7198fcp-12372L, 0x1.51c022680d7198fep-12372L }, + { 0x1.fdcd9cf05688d39ap-4L, 0x7.a430ee8b67706cd8p+12908L, 0x1.4b0f5cb18c3a0502p+12908L, 0x1.4b0f5cb18c3a0504p+12908L }, + { -0x4.6d76b6c10b4f68dp-4L, 0x3.86937071555cdafp-6228L, -0x1.a5d93ae065b24362p-6228L, -0x1.a5d93ae065b2436p-6228L }, + { 0xc.e11cc48bc0890a6p-8L, -0xe.d33d2fb05570f5p+9980L, -0x1.0cc2a4739972082ep+9980L, -0x1.0cc2a4739972082cp+9980L }, + { -0x3.15cc58d05242c5c4p-4L, -0x2.b3bc30083b4d4404p+11624L, 0xd.5c643b37b5143f8p+11620L, 0xd.5c643b37b5143f9p+11620L }, + { 0x1.ba0d3017b025eae6p-32L, 0x1.198638bd324fcb54p+14568L, 0x2.bd54dd9644f2be48p+14536L, 0x2.bd54dd9644f2be4cp+14536L }, + { -0x5.fd20bf720e8711ep-172L, 0x6.73a42eb2b2605db8p-3488L, -0x3.7be27d9b5a793af4p-3656L, -0x3.7be27d9b5a793afp-3656L }, + { 0x3.ccf8a019857ed894p-4L, -0x1.d70139a2e6defee6p+7832L, -0x9.0d2c0e9df766c0fp+7828L, -0x9.0d2c0e9df766c0ep+7828L }, + { -0x3.76614c7863ec1a34p-4L, 0x9.5e5abe936c610a9p-7228L, -0x3.4bc5db18912ee0b4p-7228L, -0x3.4bc5db18912ee0bp-7228L }, + { 0x3.41a0d3833286b12p-4L, -0x2.80acf5ba59112edp+14608L, -0xa.b3a9e16bc318f8cp+14604L, -0xa.b3a9e16bc318f8bp+14604L }, + { -0x3.3e705853c67d7d8cp-4L, -0x5.f6741be9484aa37p+7296L, 0x1.f2f9757c7add715cp+7296L, 0x1.f2f9757c7add715ep+7296L }, + { 0x3.48681763319dda58p-4L, -0x3.67fd89d48c38dc8cp-1216L, -0xe.ac78d74c01e27a5p-1220L, -0xe.ac78d74c01e27a4p-1220L }, + { -0x4.7f84659f13b7e02p-4L, 0x7.bf798fb07a11662p+5760L, -0x3.b0889ae3587bbd1cp+5760L, -0x3.b0889ae3587bbd18p+5760L }, + { 0xa.4a3324d14b02089p-8L, 0xe.377d20895e5873fp-8496L, 0xc.eeb025e6099e398p-8500L, 0xc.eeb025e6099e399p-8500L }, + { -0x1.4888cb0fc88855d4p-4L, 0xe.db1b91e2caa0ba9p-5588L, -0x1.cabc6b23578f7164p-5588L, -0x1.cabc6b23578f7162p-5588L }, + { 0x2.7d6c843a1e34bb04p-4L, -0x9.a100a7ee5db1c0dp-13024L, -0x2.025e40217cfd859p-13024L, -0x2.025e40217cfd858cp-13024L }, + { -0x3.5fa0f418a95b1664p-4L, 0xf.bcd9d43d60027c9p-1464L, -0x5.6058e9841e63ffc8p-1464L, -0x5.6058e9841e63ffcp-1464L }, + { 0x4.8fa3ee4eaa7f608p-4L, 0x2.36d491e5ba55fc0cp+3820L, 0xc.d1ad707323f03c3p+3816L, 0xc.d1ad707323f03c4p+3816L }, + { -0x1.4b4df2cc6ad25ea8p-4L, 0x1.868500451829747cp+12564L, -0x2.f84f7bac1d20f1ep+12560L, -0x2.f84f7bac1d20f1dcp+12560L }, + { 0x1.f632e7d78adaa7bap-4L, 0x4.feb116d8a3c818ep+4492L, 0xd.55a8e7b75c1d99p+4488L, 0xd.55a8e7b75c1d991p+4488L }, + { -0x1.1908e7c45b2a3cdp-4L, -0x1.7103d1307c4d3a48p-3456L, 0x2.5d74775e3b76a7ap-3460L, 0x2.5d74775e3b76a7a4p-3460L }, + { 0x3.d1361d5e6ee7fc4cp-4L, -0x4.71adf08ff0311758p+4848L, -0x1.5f2ed550fa6c8e9ap+4848L, -0x1.5f2ed550fa6c8e98p+4848L }, + { -0x1.0feb13e1b3fa32cep-4L, 0x5.beb340c633bfc9b8p-10700L, -0x9.1bff6c6cb9b3392p-10704L, -0x9.1bff6c6cb9b3391p-10704L }, + { 0x2.9f4ded3ecc16efe8p-4L, -0xb.866e84a68035155p-1164L, -0x2.86054df08503d23p-1164L, -0x2.86054df08503d22cp-1164L }, + { -0x1.0e6005400df64018p-4L, 0x3.8d17e470f6e09b88p-8468L, -0x5.9906aeea3ec75f8p-8472L, -0x5.9906aeea3ec75f78p-8472L }, + { 0x2.06b035aa76cdd098p-4L, 0x1.e00da34298889842p-5192L, 0x5.293db0d00f0e8c4p-5196L, 0x5.293db0d00f0e8c48p-5196L }, + { -0x2.d44b97592a7f2cacp-4L, -0xf.c8025dd6fb1fa7dp+5864L, 0x4.6e2ea290515d3d28p+5864L, 0x4.6e2ea290515d3d3p+5864L }, + { 0xb.bf2398p-16424L, -0x9.79c050222c1c028p+2980L, -0xa.094c1b19085e6eap-13440L, -0xa.094c1b19085e6e9p-13440L }, + { -0xe.69fc312b6c20148p-188L, 0x1.4f5d050e1ce71f9ap+9460L, -0x1.b3de2a1f249a3644p+9276L, -0x1.b3de2a1f249a3642p+9276L }, + { 0x7.8ae95a742e52adf8p-8L, 0x8.966bd426c329fd3p+4712L, 0x5.c18ec9b9358e0c1p+4708L, 0x5.c18ec9b9358e0c18p+4708L }, + { -0x2.c7dfd0fb6c73cb18p-4L, -0x2.cf1cfb2de02b7d78p+14340L, 0xc.611330d26020636p+14336L, 0xc.611330d26020637p+14336L }, + { 0xe.5af0f71551e3f5cp-8L, 0x3.a98a7ec294cc83c8p-816L, 0x4.9cbd3cb9c9116e38p-820L, 0x4.9cbd3cb9c9116e4p-820L }, + { -0x1.8276da55153cfdbp-4L, -0x1.a307e03dd9845d44p+5600L, 0x3.be96b5f832a200acp+5596L, 0x3.be96b5f832a200bp+5596L }, + { 0x2.81a24543987fd82p-4L, 0xd.8bd22d5fd653c0cp-9644L, 0x2.d8128d3bec32cd3cp-9644L, 0x2.d8128d3bec32cd4p-9644L }, + { -0x1.379a979d3d9108c8p-4L, 0x7.730ab999d45ba668p+8876L, -0xd.9b19d340489c12ap+8872L, -0xd.9b19d340489c129p+8872L }, + { 0x4.7b84cbeaf9218068p-4L, 0x1.94a35a444837f348p-1060L, 0x9.02e333ae71b31c6p-1064L, 0x9.02e333ae71b31c7p-1064L }, + { -0x4.0c6068743ed7f7ap-4L, 0x8.653a7b58a965687p-2084L, -0x3.88871c668e454124p-2084L, -0x3.88871c668e45412p-2084L }, + { 0x1.c2424e1940d7455p-4L, -0x5.5deec579d8a42c3p-7868L, -0xc.eba462f43ab86e2p-7872L, -0xc.eba462f43ab86e1p-7872L }, + { -0x2.d7b31c0c9af1a328p-4L, -0x1.b015dec33f70594ep-11840L, 0x7.9eeac3e3d95935ep-11844L, 0x7.9eeac3e3d95935e8p-11844L }, + { 0x2.494fadc55b33b084p-4L, -0x3.dc339a3898bc7a18p+8868L, -0xb.e6c675431839112p+8864L, -0xb.e6c675431839111p+8864L }, + { -0x2.ee153b661645587cp-4L, -0x6.c3feb8fbd6d16edp+9160L, 0x1.f96ba24721b9912ep+9160L, 0x1.f96ba24721b9913p+9160L }, + { 0x4.8e20e07126ab5fbp-4L, 0x3.c7f4fe11df2d42d8p+2808L, 0x1.5dd9737f23ac2e7ap+2808L, 0x1.5dd9737f23ac2e7cp+2808L }, + { -0x2.2d194219b0dffcacp-4L, -0x6.07756407b2f410bp-12488L, 0x1.45898bc66612542p-12488L, 0x1.45898bc666125422p-12488L }, + { 0x4.99aacb94db2a32ep-4L, 0x2.185cd30ea16fd298p-8768L, 0xc.38d8901d530a557p-8772L, 0xc.38d8901d530a558p-8772L }, + { -0x2.96ffad178b37fbfcp-4L, -0x3.e5143e6ad3e345cp-12712L, 0xf.e0050f04899e61ap-12716L, 0xf.e0050f04899e61bp-12716L }, + { 0x2.07cf3823d73ab374p-8L, 0x4.fa7fc381b3d6c2f8p+13688L, 0xe.86ca1ccd04ba732p+13680L, 0xe.86ca1ccd04ba733p+13680L }, + { -0x2.28ed2ce3d1807394p-8L, -0x5.a384207efdf44f98p+10336L, 0x1.1a5201007023cabap+10332L, 0x1.1a5201007023cabcp+10332L }, + { 0x2.469a2200238d7444p-4L, 0x5.9ad70266bfb8e91p+2488L, 0x1.134a7e067761fe5ap+2488L, 0x1.134a7e067761fe5cp+2488L }, + { -0x2.37b70d8d4113f934p-4L, -0x1.af092832a5fc99d8p+10212L, 0x5.cc7a4fd5be1823d8p+10208L, 0x5.cc7a4fd5be1823ep+10208L }, + { 0x2.1e0b843dc844a878p-48L, -0x1.b9ae023d8acd6e66p-13528L, -0x5.453405a12d6a7e78p-13576L, -0x5.453405a12d6a7e7p-13576L }, + { -0x4.4c7b47cp-16416L, -0x3.547713310a06b54p+5744L, 0x1.4a6d0327cbe06654p-10668L, 0x1.4a6d0327cbe06656p-10668L }, + { 0x4.083830ddfa7690ep-4L, 0x1.613dfb10e1a54184p+10872L, 0x7.2893986d292e673p+10868L, 0x7.2893986d292e6738p+10868L }, + { -0x3.433014eef8a70788p-4L, -0x1.a8639abcd8b6e402p-8536L, 0x8.b9e0c375b70f81ap-8540L, 0x8.b9e0c375b70f81bp-8540L }, + { 0x2.d29ec953e7aa219p-4L, 0x1.4fa6beb2f76975acp+13676L, 0x4.ead9b52fbb5f5fc8p+13672L, 0x4.ead9b52fbb5f5fdp+13672L }, + { -0x3.5e2ea6dbdbaa02p-4L, 0x5.ee655300abbc5d6p+14676L, -0x2.05bd11a5d53281cp+14676L, -0x2.05bd11a5d53281bcp+14676L }, + { 0x8.304de71d9e9114cp-8L, 0x2.7910d5b01fbe64e4p-6028L, 0x1.cc1c6eb2df659e2ep-6032L, 0x1.cc1c6eb2df659e3p-6032L }, + { -0x2.b4d0633cb32e7d3p-4L, -0x1.f35e33822898ee8p+10012L, 0x8.57ef3448b90b49dp+10008L, 0x8.57ef3448b90b49ep+10008L }, + { 0x4.349e9799eee38c3p-4L, -0x3.85166ab0880d15d8p-14236L, -0x1.2f60a91c12616b9p-14236L, -0x1.2f60a91c12616b8ep-14236L }, + { -0x1.82c3ae4bbb10637cp-4L, 0x4.d7001bc86349c478p-10896L, -0xb.14b1458f431b427p-10900L, -0xb.14b1458f431b426p-10900L }, + { 0x1.2e5ba50de7eddadap-4L, -0x7.d3c6bad19081ebap-11612L, -0xc.de2fb1024afe26ap-11616L, -0xc.de2fb1024afe269p-11616L }, + { -0x3.83f8c7b7cb57825cp-4L, 0x5.1e6faf1b430e137p+13408L, -0x1.d50d40244e687828p+13408L, -0x1.d50d40244e687826p+13408L }, + { 0xb.41592caa2c324c4p-8L, 0x4.168f2c495ff127f8p+14584L, 0x4.0f6f7aae5e342928p+14580L, 0x4.0f6f7aae5e34293p+14580L }, + { -0x2.a3c26e78708216b4p-4L, 0x8.cbb456a056bda98p+2832L, -0x2.49b56eddf19b1a38p+2832L, -0x2.49b56eddf19b1a34p+2832L }, + { 0x2.559fafbe5db9e92p-4L, -0x1.020dcff6a035d17ep-1564L, -0x3.2b440ece5ae09ac4p-1568L, -0x3.2b440ece5ae09acp-1568L }, + { -0x1.c97f2c8d93653d48p-4L, -0x2.e37117c16676a0ecp-8384L, 0x7.e595007c6cac50dp-8388L, 0x7.e595007c6cac50d8p-8388L }, + { 0x1.9549043c3fae6d76p-4L, -0x5.6ca968825df497b8p-6632L, -0xb.d06c203591750cbp-6636L, -0xb.d06c203591750cap-6636L }, + { -0x2.938e403b0b6781e4p-4L, 0x1.cc1921f91d82e518p+8416L, -0x7.48adf070f40903dp+8412L, -0x7.48adf070f40903c8p+8412L }, + { 0x1.d3d61644611f7f54p-4L, -0x2.3bbe429554a65cfcp-6468L, -0x5.935b89809acb83fp-6472L, -0x5.935b89809acb83e8p-6472L }, + { -0x1.0e5ea40906fee1a8p-4L, 0x2.b30ab79d07e2deap-5244L, -0x4.4148a4a719f6c5a8p-5248L, -0x4.4148a4a719f6c5ap-5248L }, + { 0x1.b7e8585df0a1e78ap-4L, -0x1.1c71d650867d7786p-304L, -0x2.9dd0113be448c594p-308L, -0x2.9dd0113be448c59p-308L }, + { -0x3.c216a3f300f2fa4p-4L, -0x5.1494a94b36616a18p-8936L, 0x1.f659d5fe58f69792p-8936L, 0x1.f659d5fe58f69794p-8936L }, + { 0x1.c0f2c38245dc8a1ep-36L, 0x5.38cf2d6c438c4fdp+10484L, 0xd.363555200aa28b1p+10448L, 0xd.363555200aa28b2p+10448L }, + { -0x5.338a3398p-16416L, 0xb.9bac1859a410106p-9056L, -0x8p-16448L, -0x0p+0L }, + { 0x4.10c4032a61d96d4p-4L, -0x7.0d9040683a3fcp+520L, -0x2.4dc7081478ce8b44p+520L, -0x2.4dc7081478ce8b4p+520L }, + { -0x3.1a6581525a6ef994p-4L, -0x6.d2ef9a6ba6f44528p+10288L, 0x2.1f61e588277a8a1p+10288L, 0x2.1f61e588277a8a14p+10288L }, + { 0xb.44e6f1ad62eb1d3p-12L, 0x1.2f26e54a1a2d2bcep+2628L, 0x1.339dc2b5be6f05ccp+2620L, 0x1.339dc2b5be6f05cep+2620L }, + { -0x3.dc341dbfa33afaf8p-4L, 0x2.87da9cc0fd94cab4p-12668L, -0x1.020e3b564a370bbp-12668L, -0x1.020e3b564a370baep-12668L }, + { 0x2.2f1d94a92b73ba54p-8L, 0xc.fd7aedfbcc36e21p-2864L, 0x2.8c1d8f7d4aeaeb8p-2868L, 0x2.8c1d8f7d4aeaeb84p-2868L }, + { -0x3.1f6b10cfe59f209p-4L, -0x1.d7e7a366c9f4fafp+8040L, 0x9.3d25ebcfc0e8757p+8036L, 0x9.3d25ebcfc0e8758p+8036L }, + { 0x3.7328f5190b649058p-4L, -0x1.cb288c3a6ffb891ap-14664L, -0x8.156bb127252ce95p-14668L, -0x8.156bb127252ce94p-14668L }, + { -0x4.05760d773cce4b18p-4L, -0x3.619f8ab766bdc80cp-12980L, 0x1.697cf65320577f2ep-12980L, 0x1.697cf65320577f3p-12980L }, + { 0x3.06e0564e8648504p-4L, 0x1.9129d4b6a8c0a64cp-3348L, 0x6.446edb2686c4b438p-3352L, 0x6.446edb2686c4b44p-3352L }, + { -0x3.b4c9c714bc24a95p-4L, 0x8.0c9d9e18f2f4e02p+12048L, -0x3.0f534e9f9071cd6cp+12048L, -0x3.0f534e9f9071cd68p+12048L }, + { 0x1.8456626db4b3e754p-4L, 0xa.75791f1b98fa7c2p+7952L, 0x1.5de3cd5f95a39698p+7952L, 0x1.5de3cd5f95a3969ap+7952L }, + { -0x1.cf4a46c4585b047ap-4L, -0x2.588015b168bce7acp-13720L, 0x6.7fd06d3587654c08p-13724L, 0x6.7fd06d3587654c1p-13724L }, + { 0x1.332103e3ea9e239cp-4L, -0xc.30c9869073f6cbfp+14536L, -0x1.458a3582f79dec28p+14536L, -0x1.458a3582f79dec26p+14536L }, + { -0x2.8f2194cfbb3ca8dp-4L, -0x2.5bd03241d4e64288p+9824L, 0x9.7d31337f76bc8p+9820L, 0x9.7d31337f76bc801p+9820L }, + { 0x1.75adff2c459d542ep-4L, 0x8.cc5bcdf810d087bp+12200L, 0x1.1bb28d31bd29f1a2p+12200L, 0x1.1bb28d31bd29f1a4p+12200L }, + { -0x2.7210b844df60db2cp-4L, -0x1.622e351acabb98cep-1124L, 0x5.4c208ba7477d9a4p-1128L, 0x5.4c208ba7477d9a48p-1128L }, + { 0xe.6e7603454ee5fdap-8L, 0x2.cccf4c722416cda8p+10164L, 0x3.8b6a8a886aa48544p+10160L, 0x3.8b6a8a886aa48548p+10160L }, + { -0x4.51b2bbef5b4e2008p-4L, 0x3.6cdc3fba23bef70cp+12224L, -0x1.8e074b185d5c9a1p+12224L, -0x1.8e074b185d5c9a0ep+12224L }, + { 0x4.086bd3b7798df198p-4L, -0x5.3ede769cd9e10ad8p-13484L, -0x1.b37dba8860e6a8e8p-13484L, -0x1.b37dba8860e6a8e6p-13484L }, + { -0x3.444dbd716806ed7p-4L, -0x1.a1223f3c67d88328p+14220L, 0x8.96fbc10a6b2910cp+14216L, 0x8.96fbc10a6b2910dp+14216L }, + { 0x7.845f8708p-16416L, -0x9.2a78d116f539cddp+13612L, -0x6.3672794bc955e378p-2800L, -0x6.3672794bc955e37p-2800L }, + { -0x9.a00bf03936bb962p-188L, 0xb.006265771517025p+9288L, -0x9.8c4e23ea8f3d0ccp+9104L, -0x9.8c4e23ea8f3d0cbp+9104L }, + { 0x4.1484721ea2376538p-4L, -0x1.a41add8aeb9b4806p-7968L, -0x8.9aae06ea9963ce4p-7972L, -0x8.9aae06ea9963ce3p-7972L }, + { -0x2.ceb5ec6d975953c8p-4L, 0x1.3990fbbe138579bp-2444L, -0x5.747fa8d3ebe39c2p-2448L, -0x5.747fa8d3ebe39c18p-2448L }, + { 0x2.0eb33e95ad6976d4p-4L, -0x1.1151218de56ba42cp-13140L, -0x2.fb304a838c96f87cp-13144L, -0x2.fb304a838c96f878p-13144L }, + { -0x2.eb00c9bd97ca2dp-4L, -0x5.2422819f09d6c978p-5108L, 0x1.7e51d1ba67214bdcp-5108L, 0x1.7e51d1ba67214bdep-5108L }, + { 0x1.16afed5122a1c164p-4L, -0x6.328d311aeae95f4p-7344L, -0x9.6aa5fcce16eb342p-7348L, -0x9.6aa5fcce16eb341p-7348L }, + { -0x4.57c457a4cf259718p-8L, -0x3.96ccc33bb2e63e44p-12628L, 0x1.6ae07bf02b257026p-12632L, 0x1.6ae07bf02b257028p-12632L }, + { 0x1.aeeefbd8d00e0efep-4L, -0xf.b5614be31d80bd7p+7168L, -0x2.445bf283f4c48574p+7168L, -0x2.445bf283f4c4857p+7168L }, + { -0x2.5dce95be94cb3c98p-4L, -0x2.2e554820ae22992cp-120L, 0x8.0ec90a8240db617p-124L, 0x8.0ec90a8240db618p-124L }, + { 0x2.3818b947f150da88p-4L, -0x7.24ffac24722f38fp-10332L, -0x1.56b8a9c932ce8192p-10332L, -0x1.56b8a9c932ce819p-10332L }, + { -0x4.a1dc33e9391f4958p-4L, 0xc.da35ced9d50c067p-6524L, -0x6.567e050c8546b6c8p-6524L, -0x6.567e050c8546b6cp-6524L }, + { 0x4.8ad503c066b5bb88p-4L, -0x1.3c6056edfdb7ef2ep-13072L, -0x7.20fe70074b4f73d8p-13076L, -0x7.20fe70074b4f73dp-13076L }, + { -0x2.c614d5e5bb68713cp-4L, 0xa.dfd4d1fff016deap+8040L, -0x2.fca16bfa05891708p+8040L, -0x2.fca16bfa05891704p+8040L }, + { 0x2.9652c0875ceb61c8p-4L, 0x3.d368fc20214ae89p-2724L, 0xd.3c90696ace7402fp-2728L, 0xd.3c90696ace7403p-2728L }, + { -0x3.c49bb1a332166398p-4L, 0x1.e4beaa8e0eaf876p-792L, -0xb.bcbb8fd43fa70eap-796L, -0xb.bcbb8fd43fa70e9p-796L }, + { 0x9.bf4a383f6ca4c78p-8L, 0x2.f082dcbeb993682cp+14744L, 0x2.891890b8ea5a86dcp+14740L, 0x2.891890b8ea5a86ep+14740L }, + { -0x9.7cae2a328b898f8p-8L, 0x3.89ef3c26f0876fc8p-12636L, -0x3.15b05d09ca38963cp-12640L, -0x3.15b05d09ca389638p-12640L }, + { 0x3.50d23d5945a1409p-4L, -0x2.33c93e2e43fe6d7p+8756L, -0x9.92ea36d589899d7p+8752L, -0x9.92ea36d589899d6p+8752L }, + { -0x3.4717abe0a3cf3558p-4L, 0x3.8534b1e86f26faa4p+6740L, -0x1.2a0a5aa6bbe09072p+6740L, -0x1.2a0a5aa6bbe0907p+6740L }, + { 0x3.4daf40c873d20d78p-4L, -0x7.736b651db7cbd5a8p+14396L, -0x2.04813b9537b6064p+14396L, -0x2.04813b9537b6063cp+14396L }, + { -0x2.5c070e6f3535825p-4L, 0xf.3a0b99c5b4aab25p-11840L, -0x3.813a1682912fbe2cp-11840L, -0x3.813a1682912fbe28p-11840L }, + { 0x1.57462eab133f0c7ep-104L, -0xb.c22c24524226f33p-584L, -0x1.6bf458868d45cbaap-684L, -0x1.6bf458868d45cba8p-684L }, + { -0x7.d1036a7p-16416L, 0x1.9c8928976825f972p-9340L, -0x8p-16448L, -0x0p+0L }, + { 0x4.139c9d206a49b8e8p-4L, 0x7.f8137ffd163b3ba8p-6224L, 0x2.9c02918d1a124d84p-6224L, 0x2.9c02918d1a124d88p-6224L }, + { -0x7.bf1a44aeb781fdcp-8L, 0x5.c592f47919e4e23p-11080L, -0x4.1801d2a31591ef48p-11084L, -0x4.1801d2a31591ef4p-11084L }, + { 0x1.89ac0b1dee90fcbcp-4L, -0x5.2ce714d9965b9eb8p-7004L, -0xa.f68dd40a901fabdp-7008L, -0xa.f68dd40a901fabcp-7008L }, + { -0x8.f6b1a263d7a28bbp-8L, -0x6.a8e6be614c1b8df8p-13004L, 0x5.7aab3c44fdedc898p-13008L, 0x5.7aab3c44fdedc8ap-13008L }, + { 0x2.a9b18d178ac3225p-4L, 0x5.3e11ed5dcfa44448p-8052L, 0x1.2a1266fb395796a8p-8052L, 0x1.2a1266fb395796aap-8052L }, + { -0x3.526959569dd12bf4p-4L, -0x5.9adce70a60a095a8p+5500L, 0x1.e1bc0e901384afd6p+5500L, 0x1.e1bc0e901384afd8p+5500L }, + { 0x3.6ef9b4fb7ad8d1c4p-4L, -0x3.3c5645dc55c04f94p+14756L, -0xe.853a48486c560e4p+14752L, -0xe.853a48486c560e3p+14752L }, + { -0x4.ad357dc0f71b3c18p-4L, 0x1.f1a437afbf657566p-12476L, -0xf.834b1b792328df6p-12480L, -0xf.834b1b792328df5p-12480L }, + { 0x2.dd74eb48ec7ac348p-4L, 0x1.571b76b38f6ad39p+14116L, 0x5.189ace0fd7dbc34p+14112L, 0x5.189ace0fd7dbc348p+14112L }, + { -0x7.e37552b2966c9e38p-8L, -0x3.145c1bfaf5874b28p-10368L, 0x2.3993d2134acb4a2cp-10372L, 0x2.3993d2134acb4a3p-10372L }, + { 0x3.7800dc9da42fa068p-4L, -0xe.ddd4485dc420705p+14556L, -0x4.3563bf3edbcb7518p+14556L, -0x4.3563bf3edbcb751p+14556L }, + { -0x9.fdb9cb46bb40cb6p-8L, -0x7.ec4ed7347f198e18p-4392L, 0x7.47e1bfbdff5ed83p-4396L, 0x7.47e1bfbdff5ed838p-4396L }, + { 0x1.b3312385e89ecbd4p-4L, 0x1.9a43d194ce98771ep+6932L, 0x3.bc3ea85906d8a39p+6928L, 0x3.bc3ea85906d8a394p+6928L }, + { -0x3.832741f767b3e59p-4L, -0x9.4618839acbce14p-11256L, 0x3.50e5766c6f4962ecp-11256L, 0x3.50e5766c6f4962fp-11256L }, + { 0x1.5125eee5de5358fcp-4L, -0xe.ff418d777e5efbep+11616L, -0x1.b61ebb3ae9848ea4p+11616L, -0x1.b61ebb3ae9848ea2p+11616L }, + { -0x3.13efbef15009e7c8p-4L, -0x3.fc05faf9a81f3d04p+3860L, 0x1.3a668b8af93bf2ap+3860L, 0x1.3a668b8af93bf2a2p+3860L }, + { 0x1.9510ceed893154cep-4L, 0x5.8bca7ba191d1075p+6828L, 0xc.129f0a66d0014c7p+6824L, 0xc.129f0a66d0014c8p+6824L }, + { -0x1.254279726e925594p-8L, -0x7.926da2dc2eb3e0c8p-7000L, 0xc.8ac6eb52210a585p-7008L, 0xc.8ac6eb52210a586p-7008L }, + { 0x4.5ecc0b5462ae235p-4L, 0x2.6721d566c52f5a78p+2456L, 0xd.64f286714c83778p+2452L, 0xd.64f286714c83779p+2452L }, + { -0xe.a208f1fa6e8cbdp-8L, -0x7.e11743909b3a78f8p-8876L, 0xa.b4809b9e927b678p-8880L, 0xa.b4809b9e927b679p-8880L }, + { 0x6.3dc45d2p-16416L, 0x1.9db3f0479ed959aep+11628L, 0xe.8d16a10d0f22682p-4788L, 0xe.8d16a10d0f22683p-4788L }, + { -0x1.5127dea136e65c68p-144L, 0x1.0c629491d3eb9e36p-11556L, -0x1.fdf1f80bf0ed63d8p-11700L, -0x1.fdf1f80bf0ed63d6p-11700L }, + { 0x2.5e09e9760f0d8768p-4L, 0x1.7442b66581565f6ap-7544L, 0x4.a1b2e861f70853dp-7548L, 0x4.a1b2e861f70853d8p-7548L }, + { -0x1.14d28b05df6107a4p-4L, -0xf.768d54acb3f2db4p-4996L, 0x1.8fa16bbf1e49e9e6p-4996L, 0x1.8fa16bbf1e49e9e8p-4996L }, + { 0x4.a354a165b37aa58p-4L, 0x1.e8ded63613d24c3ep-11836L, 0xb.387636549b96063p-11840L, 0xb.387636549b96064p-11840L }, + { -0x3.7f1e516e412a78dcp-4L, 0x5.d4ed544e69ab835p-13136L, -0x2.131a7bf1093fe2b8p-13136L, -0x2.131a7bf1093fe2b4p-13136L }, + { 0x3.ba0b69e7e4e2cdc8p-4L, -0x1.d273ed425e50a33p+5924L, -0x8.ce800f5bbd5a8dep+5920L, -0x8.ce800f5bbd5a8ddp+5920L }, + { -0x1.ff549a9c9f82ec1ap-4L, 0x2.fdb3fd975c2fcc24p+11236L, -0x9.34d767e53428793p+11232L, -0x9.34d767e53428792p+11232L }, + { 0x2.029bf74b014ff484p-4L, -0x2.a30dbd97704f33ap-11300L, -0x7.3428258b7189c5f8p-11304L, -0x7.3428258b7189c5fp-11304L }, + { -0x2.e1b6a811746baae4p-4L, 0xf.f88c4f246cd86a5p-5444L, -0x4.93546cd11bc8d19p-5444L, -0x4.93546cd11bc8d188p-5444L }, + { 0x4.5a3aed0d1ae13a2p-4L, -0xe.7792c29f1ca2519p-11176L, -0x5.05a0661deb318c68p-11176L, -0x5.05a0661deb318c6p-11176L }, + { -0x2.63162683080b9cbcp-4L, -0x8.bd152439e522049p+8456L, 0x2.0972b167c0230b94p+8456L, 0x2.0972b167c0230b98p+8456L }, + { 0x1.b1c8e39b79681704p-4L, 0x4.33534d4293ac9658p+4804L, 0x9.c2a816a4d7c0fe6p+4800L, 0x9.c2a816a4d7c0fe7p+4800L }, + { -0x1.7e5bc5004f62d1d6p-4L, 0x9.6fd0b86f1bc0b1p+7492L, -0x1.558cfea5c44dab0ap+7492L, -0x1.558cfea5c44dab08p+7492L }, + { 0x4.0935c6e8ba8176cp-4L, -0x2.45ae50f119d75d4cp-12464L, -0xb.cc484240eada775p-12468L, -0xb.cc484240eada774p-12468L }, + { -0x5.5a423aabc9b990ap-8L, 0x1.ffe076f2fd67cd5p+136L, -0xf.9ab02a9a0165a16p+128L, -0xf.9ab02a9a0165a15p+128L }, + { 0x1.a0a0dfe1f0a99b6p-4L, -0x2.64149f518ed134b8p+12468L, -0x5.58a2666218ac564p+12464L, -0x5.58a2666218ac5638p+12464L }, + { -0x4.65e52871cff18e08p-4L, 0x4.1bf7b256271f8f28p-14612L, -0x1.e7cc9f85102b525cp-14612L, -0x1.e7cc9f85102b525ap-14612L }, + { 0x5.b61843dfb71d1fb8p-8L, 0x3.49a93629ad7fc314p+13540L, 0x1.acac91b8860aecfap+13536L, 0x1.acac91b8860aecfcp+13536L }, + { -0x3.f52785993c70ec3p-8L, -0x3.9bc242c0137acf5cp-12472L, 0x1.4c38af5e25f74042p-12476L, 0x1.4c38af5e25f74044p-12476L }, + { 0xe.d492edc66d3e62ep-8L, -0x6.03a80cdae8d71a98p+740L, -0x7.d1728cf552ba731p+736L, -0x7.d1728cf552ba7308p+736L }, + { -0x4.670e905322dbb63p-4L, 0x1.6a9a4d57bc0ab21ap-14452L, -0xa.8581ee4fafd174fp-14456L, -0xa.8581ee4fafd174ep-14456L }, + { 0x5.74d1d9f8p-16416L, -0x5.d7c80be9da872b28p+11784L, -0x2.dfe8427ef946d498p-4628L, -0x2.dfe8427ef946d494p-4628L }, + { -0x1.ea990a7a7c9093b4p-144L, -0x1.54c1c54d508c174p+4632L, 0x3.ae1df71c96cb2fc4p+4488L, 0x3.ae1df71c96cb2fc8p+4488L }, + { 0x4.93dbf2db2ba9b988p-4L, -0xf.46327c7f85e2d9bp+10320L, -0x5.8b67deefd704f668p+10320L, -0x5.8b67deefd704f66p+10320L }, + { -0x3.8cfabd226c133e6p-4L, 0x2.ea14d6304eb12438p-14544L, -0x1.0e1644540f887aa8p-14544L, -0x1.0e1644540f887aa6p-14544L }, + { 0x1.9329c67c6c57433p-4L, -0x2.91d7f1505ba6b1p+3140L, -0x5.919562e974081818p+3136L, -0x5.919562e97408181p+3136L }, + { -0x4.a986cc606ebb7c4p-4L, 0xf.bbc8e9388c45f3ap-10816L, -0x7.d189e02359a7d8f8p-10816L, -0x7.d189e02359a7d8fp-10816L }, + { 0x1.0068bafe2db46dc8p-4L, -0xd.0ec84ab52b6bccfp+10516L, -0x1.24d293c044903b7ap+10516L, -0x1.24d293c044903b78p+10516L }, + { -0xe.b86d33c9dc908e3p-8L, 0x3.9bf2d583cd0d0d8cp-8448L, -0x4.ef0b6998a234653p-8452L, -0x4.ef0b6998a2346528p-8452L }, + { 0x2.bf26bd5a8657f64p-4L, 0x1.619579cddffcb6aep+12140L, 0x5.0d0ffca3706c2acp+12136L, 0x5.0d0ffca3706c2ac8p+12136L }, + { -0x2.26a816730ea9fa2p-4L, -0x2.1cd826493af5d3a4p+5928L, 0x7.0a714112caed041p+5924L, 0x7.0a714112caed0418p+5924L }, + { 0x1.f4ebd7a17a5e1fd4p-4L, -0x8.ca91adedeaa1e77p-14972L, -0x1.769cbd033d773138p-14972L, -0x1.769cbd033d773136p-14972L }, + { -0x4.9755a649fce3a72p-4L, 0x1.9ffbbc6c991dce28p+2304L, -0xc.af74ccc1edf3feep+2300L, -0xc.af74ccc1edf3fedp+2300L }, + { 0x2.03c9c35825e8cce8p-4L, -0x4.c58df0c00390e39p+14776L, -0xd.1055487d9d10608p+14772L, -0xd.1055487d9d10607p+14772L }, + { -0x1.4a829868b2d07d8ap-4L, 0x6.ec9b9c24e5dad6d8p-6360L, -0xd.727e7114ad2833ep-6364L, -0xd.727e7114ad2833dp-6364L }, + { 0x2.e638feebcca21c28p-4L, 0x1.5555753a1fdc2362p-5456L, 0x5.202652e78b04ba6p-5460L, 0x5.202652e78b04ba68p-5460L }, + { -0x9.979149647a1982ap-8L, 0x1.1f233b6d8f73e8ccp+1520L, -0xf.d1e2d416d88a874p+1512L, -0xf.d1e2d416d88a873p+1512L }, + { 0x7.c696d728e20f0848p-8L, -0x1.5ef60b9d2b73390ap+11924L, -0xf.267aeee72356083p+11916L, -0xf.267aeee72356082p+11916L }, + { -0x4.05c95bb140d74508p-8L, -0x1.ed7fe53fd80fb15ap-13268L, 0xb.46b5e70ab7dc4a7p-13276L, 0xb.46b5e70ab7dc4a8p-13276L }, + { 0x1.2102593d8b22e7bep-4L, -0xd.0f4dc08b32e489ap-10512L, -0x1.48dc788829e9e252p-10512L, -0x1.48dc788829e9e25p-10512L }, + { -0x9.453822cef91e918p-8L, 0x4.86ba6e2b530b797p-4708L, -0x3.da8c9cccd9d956bp-4712L, -0x3.da8c9cccd9d956acp-4712L }, + { 0x1.12f7b7ecee83bc12p-4L, 0x3.6d9e8e1a109a2ec8p-13472L, 0x5.243f0c6c55752578p-13476L, 0x5.243f0c6c5575258p-13476L }, + { -0x2.777e0c0a02694fd4p-4L, 0x3.08ae8e74c266a098p-956L, -0xb.b9e9452b01c070cp-960L, -0xb.b9e9452b01c070bp-960L }, + { 0x6.ed708598p-16416L, -0xf.89d9753e770635ep+11952L, -0x9.b4bb0cc1c6d23bep-4460L, -0x9.b4bb0cc1c6d23bdp-4460L }, + { -0x1.3ab2fe378fa08002p-52L, -0x3.faaa35d0c21a25p-132L, 0x7.0e99197749af91cp-184L, 0x7.0e99197749af91c8p-184L }, + { 0x2.075c4fded02a10dp-4L, -0x1.5c155893f7056016p+13476L, -0x3.bf317f30aab92a88p+13472L, -0x3.bf317f30aab92a84p+13472L }, + { -0x3.5dd7c365c8f83704p-4L, 0xa.1cb34dbd6cd395fp+11084L, -0x3.724bd3f3733cf154p+11084L, -0x3.724bd3f3733cf15p+11084L }, + { 0x4.47f11be2f8a972c8p-4L, -0x1.736a1fc6a5a78362p+7336L, -0x7.f0ba632851590e18p+7332L, -0x7.f0ba632851590e1p+7332L }, + { -0x2.9823a4b955403824p-4L, -0x1.b699f56c55fc52a4p+216L, 0x6.ff120dac9ded8abp+212L, 0x6.ff120dac9ded8ab8p+212L }, + { 0x4.1a23ac74ce37c868p-4L, -0x1.857b2ba5a176f0aap-11308L, -0x8.03f0f38f6e53751p-11312L, -0x8.03f0f38f6e5375p-11312L }, + { -0xa.1f42d577650c9adp-8L, 0x2.c4758147ef57417cp+13012L, -0x2.93bcd7ecd68feaa8p+13008L, -0x2.93bcd7ecd68feaa4p+13008L }, + { 0x1.84b9cdd00271f558p-4L, 0x1.3a2fc03e0387d0bcp-14720L, 0x2.918ccc5362c1ca84p-14724L, 0x2.918ccc5362c1ca88p-14724L }, + { -0x2.73a88be3087e5338p-4L, 0xe.bc8d2b7772f396p-2136L, -0x3.894c4ef8b23ccf6p-2136L, -0x3.894c4ef8b23ccf5cp-2136L }, + { 0x1.17e8c62b745eff6ap-4L, -0x4.017bb7f9858a1c18p+12L, -0x6.1cc20f6aafe3d05p+8L, -0x6.1cc20f6aafe3d048p+8L }, + { -0x1.08a6904e103c8a42p-4L, 0x4.245b3e4558ce84e8p+6880L, -0x6.62de455bb063efc8p+6876L, -0x6.62de455bb063efcp+6876L }, + { 0x9.3c659a1e94df67fp-8L, -0x3.2b939ab516941194p+14296L, -0x2.97f72ef04ae09db8p+14292L, -0x2.97f72ef04ae09db4p+14292L }, + { -0x2.b761508254c49454p-4L, 0xc.e0c6bc3b7739bb7p-4252L, -0x3.74e9fc4c3e6a1f4cp-4252L, -0x3.74e9fc4c3e6a1f48p-4252L }, + { 0x1.55e43d50aa1de912p-4L, 0x5.13ab96c153d35eb8p-11768L, 0x9.65173e148f5a0ap-11772L, 0x9.65173e148f5a0a1p-11772L }, + { -0xf.543ac800941658ep-8L, -0x6.20199bbcb0f17f4p+5288L, 0x8.bb05c1a6d35f348p+5284L, 0x8.bb05c1a6d35f349p+5284L }, + { 0x3.56f9ca36fbdfa67p-4L, 0x1.d50869ea25276784p-8844L, 0x8.04776fbae54cc54p-8848L, 0x8.04776fbae54cc55p-8848L }, + { -0x2.d2b77bbab795dc74p-4L, -0x2.7faeedff97b59518p-8980L, 0xb.326b17219f8d2c7p-8984L, 0xb.326b17219f8d2c8p-8984L }, + { 0x3.3b96a64d429b4d74p-4L, -0x2.9d9c43b7825d326p+12716L, -0xb.1c721c34cbaf487p+12712L, -0xb.1c721c34cbaf486p+12712L }, + { -0xc.8d12f03af1ad8dp-8L, 0x1.1f16f03ddddac2b2p+2568L, -0x1.4d231dfe98d4ceacp+2564L, -0x1.4d231dfe98d4ceaap+2564L }, + { 0x3.8f9ba551c055efep-4L, -0x4.bdce2365684786f8p+11256L, -0x1.5fe3aa07b1e38e1p+11256L, -0x1.5fe3aa07b1e38e0ep+11256L }, + { -0x2.fd0968609dfabf38p-4L, -0x3.9f3872fe7a19d514p-7100L, 0x1.149160a36b1937d4p-7100L, 0x1.149160a36b1937d6p-7100L }, + { 0x3.a1bc97534cf86254p-120L, 0xe.078e9669dcc8821p-3916L, 0x4.9822a91bbcaa6d3p-4032L, 0x4.9822a91bbcaa6d38p-4032L }, + { -0x9.0e702a7e143108fp-164L, -0x4.f196f6e23fedaebp+3012L, 0x4.097b774bec74e7bp+2852L, 0x4.097b774bec74e7b8p+2852L }, + { 0x2.a7f9d0e587d0031cp-4L, -0x1.7df0e27c0ccf76bcp+372L, -0x5.4a1628b2dfeb3de8p+368L, -0x5.4a1628b2dfeb3dep+368L }, + { -0x1.98c8703e63e3b9f4p-4L, -0x7.c403891453f18a28p-10492L, 0x1.2d8c742191748b96p-10492L, 0x1.2d8c742191748b98p-10492L }, + { 0x2.7f9a121a213dffe8p-4L, 0x1.60a510438baeb314p+13976L, 0x4.9d1e27c49a25cffp+13972L, 0x4.9d1e27c49a25cff8p+13972L }, + { -0x3.883ffac36198bb74p-4L, 0x1.ba64610e5fc1c95p+2376L, -0x9.f33e8f6c9f253b3p+2372L, -0x9.f33e8f6c9f253b2p+2372L }, + { 0x1.b65b0807a6b7ed1ap-4L, -0xd.a336acdf6754e5bp+7972L, -0x2.0018f97311be95d4p+7972L, -0x2.0018f97311be95dp+7972L }, + { -0x1.e1d113619cb17674p-4L, -0xc.c9f8ff221cab8ddp-2844L, 0x2.4f1a50a2821f20b4p-2844L, 0x2.4f1a50a2821f20b8p-2844L }, + { 0x2.914e861be45c55e8p-8L, 0x1.55c48d407375e2cap-2168L, 0x4.ebb18aef8402f5c8p-2176L, 0x4.ebb18aef8402f5dp-2176L }, + { -0x2.f5709c93a8a0a9dp-4L, 0x7.b9cef07eaf4eed7p-4876L, -0x2.476edf2184857d34p-4876L, -0x2.476edf2184857d3p-4876L }, + { 0x3.648cf748ec9e27f8p-4L, 0x3.1423bae5f0affdccp-12004L, 0xd.aaad3e8f8eb0b16p-12008L, 0xd.aaad3e8f8eb0b17p-12008L }, + { -0x3.61791f35cba8863p-4L, -0x8.74595f3c5c6cb4dp-1688L, 0x2.e52c5807e549f5dcp-1688L, 0x2.e52c5807e549f5ep-1688L }, + { 0x1.b82710349d66924cp-4L, 0x7.e61a34168ab5f008p-8164L, 0x1.29c2f5adf7458efp-8164L, 0x1.29c2f5adf7458ef2p-8164L }, + { -0x3.4d11e5ccd6ac7cap-4L, -0x3.9a82f3943aa5a188p-9436L, 0x1.3388089c3b0d5588p-9436L, 0x1.3388089c3b0d558ap-9436L }, + { 0x4.9428b7da62c702b8p-4L, 0xd.1467d75f56bcf5ep-11520L, 0x4.bfbff268e075cc18p-11520L, 0x4.bfbff268e075cc2p-11520L }, + { -0x2.6b566d5498306d08p-4L, -0x3.ccde3d308a22eb5cp+10760L, 0xe.6187fe1b7bad52ap+10756L, 0xe.6187fe1b7bad52bp+10756L }, + { 0xf.c0bf63c433c05f9p-8L, 0x2.492819446118a574p+1964L, 0x3.26989997ddb6f92cp+1960L, 0x3.26989997ddb6f93p+1960L }, + { -0x3.6892bbb36e176cecp-4L, 0xf.d741a00abd03d2p-4572L, -0x5.799464669eee8fp-4572L, -0x5.799464669eee8ef8p-4572L }, + { 0x2.3ccc852342a3e2ep-4L, -0x1.092e784e29e30784p-14964L, -0x3.21364368eb287a8p-14968L, -0x3.21364368eb287a7cp-14968L }, + { -0x3.dabe1d3a5400a66cp-4L, 0x3.819f5f8d05fa313p+14716L, -0x1.64ef8bbed09c8112p+14716L, -0x1.64ef8bbed09c811p+14716L }, + { 0x2.6c673a145214ba98p-4L, -0xf.03aefac3e377757p-14792L, -0x3.0e1458d47bc4cb5cp-14792L, -0x3.0e1458d47bc4cb58p-14792L }, + { -0x4.0e4a540e71cc0288p-8L, 0x2.2419fb7ebbf4a7d8p-1068L, -0xc.a0ca66c14def27p-1076L, -0xc.a0ca66c14def26fp-1076L }, + { 0x4.dd8f85c8p-16416L, -0xf.980d0cd19d231dp+11088L, -0x6.d75c47eef8bbfbap-5324L, -0x6.d75c47eef8bbfb98p-5324L }, + { -0x7.f51abd665f9bee8p-36L, 0x1.dcd6e7960fd2d35cp-6200L, -0x1.562314b0db6f2412p-6232L, -0x1.562314b0db6f241p-6232L }, + { 0x2.3cac744f1052e66p-4L, 0x2.62280853a9ba5768p+8628L, 0x7.3321a245f69bf7ap+8624L, 0x7.3321a245f69bf7a8p+8624L }, + { -0x3.3f453518bf958f1p-4L, -0x1.8abf11344317fd2ep+5524L, 0x8.12e7dcb9203daf8p+5520L, 0x8.12e7dcb9203daf9p+5520L }, + { 0x4.a37a0a2e94817af8p-4L, 0x3.31608177e97de46p+4688L, 0x1.2c3317257700dc6cp+4688L, 0x1.2c3317257700dc6ep+4688L }, + { -0x2.759bed88d3ee0a9cp-4L, -0x1.23025455b6bb4b3cp-3840L, 0x4.611cf16d993dc978p-3844L, 0x4.611cf16d993dc98p-3844L }, + { 0x2.b2f4298813acd09p-4L, -0x1.5260cf8ab304676ep+12932L, -0x4.c193d858e5159aa8p+12928L, -0x4.c193d858e5159aap+12928L }, + { -0x3.02ab01e994f9301p-4L, -0x2.05a8427f1a2184bp-10208L, 0x9.bab237364385aefp-10212L, 0x9.bab237364385afp-10212L }, + { 0x3.9dd2497df6505db8p-4L, -0x5.ef9d56c6ff28bfdp+6132L, -0x1.bec25594dc09e1c2p+6132L, -0x1.bec25594dc09e1cp+6132L }, + { -0x3.1f36e2acdac799cp-4L, 0x1.fe0c5686cbb69ae8p+2348L, -0x9.fb9770501834541p+2344L, -0x9.fb977050183454p+2344L }, + { 0x3.f9f38bcacc608ea4p-4L, -0xc.a975585bddf812bp-13688L, -0x4.0dfd1663aa583348p-13688L, -0x4.0dfd1663aa58334p-13688L }, + { -0x1.e46e7b9f1fb532bep-4L, -0x2.bcb39ddfe1c68248p-9104L, 0x7.f3d951935813894p-9108L, 0x7.f3d9519358138948p-9108L }, + { 0x9.4556c7b62d8c8cfp-8L, -0x1.0eeffe20e57f824ap-6140L, -0xd.e7b819b422e8faep-6148L, -0xd.e7b819b422e8fadp-6148L }, + { -0x3.8ca02be25fde5288p-4L, -0x2.815db6eb9885e86p+11972L, 0xe.81398e978d87862p+11968L, 0xe.81398e978d87863p+11968L }, + { 0x2.98b2b17e1c13daccp-4L, -0x5.d0c98aabaedb1fbp+9108L, -0x1.4300e03ac130142cp+9108L, -0x1.4300e03ac130142ap+9108L }, + { -0x1.b53661215c292a9ap-4L, 0xc.ea5c116014da9b3p-1576L, -0x2.1a70dbc7c639fd2cp-1576L, -0x2.1a70dbc7c639fd28p-1576L }, + { 0x3.a9585cd202a6d0c4p-4L, 0xc.13d12aa5f2fb35ap+5048L, 0x3.9733ed35d1e948b4p+5048L, 0x3.9733ed35d1e948b8p+5048L }, + { -0x2.7e3ce1ae5b5d40fp-12L, -0x1.6ac3d1cdbddd70c6p+6624L, 0x5.19314cff3a227e4p+6612L, 0x5.19314cff3a227e48p+6612L }, + { 0x3.7200d9155209c2acp-4L, -0x1.a45b5a228d4622ep-3568L, -0x7.6449cd5931a2d96p-3572L, -0x7.6449cd5931a2d958p-3572L }, + { -0x1.a1a30e0fbfd17eb4p-4L, 0x8.8af95da1e0b1a78p+4272L, -0x1.535022cb1f7efafcp+4272L, -0x1.535022cb1f7efafap+4272L }, + { 0x2.33bf12728763519cp-4L, 0x2.6686b8dba75ea304p-2056L, 0x7.252e6bd693f1342p-2060L, 0x7.252e6bd693f13428p-2060L }, + { -0xc.90d32e60a9fdbc3p-8L, 0x3.62ff10781a5bdf74p-4852L, -0x3.ef43238141c37684p-4856L, -0x3.ef43238141c3768p-4856L }, + { 0x7.5625c9523f78c92p-152L, 0x6.33a7de5685f56b88p+2796L, 0x4.1a44ed3d49f37aep+2648L, 0x4.1a44ed3d49f37ae8p+2648L }, + { -0x1.0ac1f2f8p-16416L, 0x1.02a1bda3565bc8fap-3500L, -0x8p-16448L, -0x0p+0L }, + { 0x2.f11c7fc4f146158cp-4L, -0x1.77606bad7e693d04p+2548L, -0x5.b67ed1c0247fe558p+2544L, -0x5.b67ed1c0247fe55p+2544L }, + { -0x1.e932f553a0ce9d4p-4L, -0x1.c28b03b6522311d4p+5524L, 0x5.2ac3ccf307a22a88p+5520L, 0x5.2ac3ccf307a22a9p+5520L }, + { 0x2.28ebcd228b766488p-4L, 0x9.8ddc34fd380f7cdp+14008L, 0x1.becf6f24b98f4aap+14008L, 0x1.becf6f24b98f4aa2p+14008L }, + { -0x2.05aa67d0e7893ffp-8L, 0xa.a847a961d00df0ap+12556L, -0x1.f36dd414d6b2b91ep+12552L, -0x1.f36dd414d6b2b91cp+12552L }, + { 0x8.61b6b3ddab95935p-8L, 0x3.4f402dd17b106c64p-1012L, 0x2.761010bf33f5993cp-1016L, 0x2.761010bf33f5994p-1016L }, + { -0x1.9b432de297579e68p-4L, 0x3.5fa4d9a9fc21151cp+12192L, -0x8.3d6ac109bb4c2a7p+12188L, -0x8.3d6ac109bb4c2a6p+12188L }, + { 0x1.f2c45be62dde2318p-4L, -0xa.5a267aef528216ep+2032L, -0x1.b754d0e25e0a58dap+2032L, -0x1.b754d0e25e0a58d8p+2032L }, + { -0xe.c7886d486b1423bp-8L, -0x5.f0ff7cfd1f4b93d8p+11376L, 0x8.27cda2dd6d26dp+11372L, 0x8.27cda2dd6d26d01p+11372L }, + { 0x2.f148d81ff59e6c9cp-4L, 0x1.c09e468785b5c354p-7792L, 0x6.d43859f4941b858p-7796L, 0x6.d43859f4941b8588p-7796L }, + { -0x4.a7fa8456a5738f48p-4L, 0xb.8cf756c51b10491p-12304L, -0x5.bb23984d4ca08e1p-12304L, -0x5.bb23984d4ca08e08p-12304L }, + { 0x2.b29a39d96a13c414p-4L, 0x5.04f17d6142a2ec78p-4464L, 0x1.20d66e21c7406f52p-4464L, 0x1.20d66e21c7406f54p-4464L }, + { -0x3.77d74e76e2309764p-4L, -0x1.c3e2606dd5d09a4ep+9832L, 0x9.f4693dade8d5703p+9828L, 0x9.f4693dade8d5704p+9828L }, + { 0x4.09e8d44c0a9dec4p-8L, -0x3.f98c983119717b98p+5448L, -0x1.6fa98b37837c778ep+5444L, -0x1.6fa98b37837c778cp+5444L }, + { -0x4.863fe515ba68863p-4L, 0x2.44a0fe29d471fe0cp+6924L, -0x1.1669eef8591793ep+6924L, -0x1.1669eef8591793dep+6924L }, + { 0x2.4d7dfb360ed7fc04p-4L, -0x4.f0d30f06332ddp-12644L, -0xf.55b574e4f66676dp-12648L, -0xf.55b574e4f66676cp-12648L }, + { -0x2.321867445cc97e58p-4L, 0x2.9f2b2d00894a5d88p+4876L, -0x8.eed56b3be3be27p+4872L, -0x8.eed56b3be3be26fp+4872L }, + { 0x1.0f1653c21d88f58p-4L, 0x7.1d5b99213d03b6e8p+8576L, 0xa.8651050e953498ap+8572L, 0xa.8651050e953498bp+8572L }, + { -0x2.8cc781990c3e3904p-8L, 0x1.a7d261806a6e3d7ap+11852L, -0x6.1ef42f9c5224235p+11844L, -0x6.1ef42f9c52242348p+11844L }, + { 0x2.048284a37fa5629cp-4L, -0x3.94e24b6aa1db9f44p-8368L, -0x9.d187169aa9e30fdp-8372L, -0x9.d187169aa9e30fcp-8372L }, + { -0x2.7270920cc658bdfcp-4L, 0x2.2e30b685d8bcaea4p-2292L, -0x8.5aa759a252e70d6p-2296L, -0x8.5aa759a252e70d5p-2296L }, + { 0x5.dfbf765p-16416L, 0x1.75ea58cb0a2a111cp+1256L, 0xc.60b6aa985c7126p-15160L, 0xc.60b6aa985c71261p-15160L }, + { -0xe.1d7e71fee6192bap-40L, 0x9.4f89ff3200affa3p-10532L, -0xb.d9a41b81a0ded4cp-10568L, -0xb.d9a41b81a0ded4bp-10568L }, + { 0x4.56aa4f6cc88118d8p-4L, -0x3.f63ba994a2b78004p+10588L, -0x1.5f1214fe4a6577a8p+10588L, -0x1.5f1214fe4a6577a6p+10588L }, + { -0x6.4b399c5d6f79c53p-8L, 0x5.20a0673897bdb3p-7740L, -0x2.f23beac70fa873bp-7744L, -0x2.f23beac70fa873acp-7744L }, + { 0x3.1e0ea75bc7ed36ccp-4L, 0x8.e27b579a17f1c4dp-8756L, 0x2.481f238e55239f44p-8756L, 0x2.481f238e55239f48p-8756L }, + { -0x3.f633c649d5060228p-4L, 0x5.d72f16fe681c1abp-3536L, -0x2.65b046536bfbeb0cp-3536L, -0x2.65b046536bfbeb08p-3536L }, + { 0x2.d5c982b9a0bb948p-4L, 0x2.a22fd9997a52536cp-1444L, 0x9.eabe16ba330ce96p-1448L, 0x9.eabe16ba330ce97p-1448L }, + { -0x3.2a5af82e25817eecp-4L, 0x2.7171b5c5ce8e77acp-12700L, -0xc.6ea7205da7d336ep-12704L, -0xc.6ea7205da7d336dp-12704L }, + { 0x1.0fb5e02c9615884p-4L, -0x4.3cbd69afe18488ap+14960L, -0x6.4837d3bd5446182p+14956L, -0x6.4837d3bd54461818p+14956L }, + { -0x2.ebb14b0f25d3d54cp-4L, -0x3.f0fb7afa6ec2cfb8p+32L, 0x1.256547ff3538326ap+32L, 0x1.256547ff3538326cp+32L }, + { 0xa.4b37ca400e3e139p-8L, -0x2.2bd7a614add96564p-2988L, -0x1.f9d15a8fce18accp-2992L, -0x1.f9d15a8fce18acbep-2992L }, + { -0x1.9dfb38f66e6ce44ap-4L, 0x1.410266a44f4ade2cp+14432L, -0x3.1585cfd6c0bc80c4p+14428L, -0x3.1585cfd6c0bc80cp+14428L }, + { 0xc.89886ba4ab470fap-8L, 0x2.4d20ce827eba1d5cp-6572L, 0x2.8a31828e7806188cp-6576L, 0x2.8a31828e7806189p-6576L }, + { -0x2.cf1bd2db6eece3bp-4L, -0x9.81d66bb4eea5f5dp+8664L, 0x2.a5df5372cf8ee82p+8664L, 0x2.a5df5372cf8ee824p+8664L }, + { 0x3.d52f7205e2265278p-4L, -0x5.8137ad906185b418p-4344L, -0x1.b4981d0839394732p-4344L, -0x1.b4981d083939473p-4344L }, + { -0x4.068ea746952344c8p-4L, -0x3.bc6a67b96be7c0ecp-1508L, 0x1.8fe5914831f7a6f8p-1508L, 0x1.8fe5914831f7a6fap-1508L }, + { 0x2.4a7156c47e3c5cfp-4L, 0x7.a3b09d22470dbdbp+13304L, 0x1.798992cc1888896ep+13304L, 0x1.798992cc1888897p+13304L }, + { -0x2.27f0bcaf31f43d84p-4L, -0x2.52eaea727fb51b3cp-2292L, 0x7.c39f824994a1ee3p-2296L, 0x7.c39f824994a1ee38p-2296L }, + { 0x7.714aee9717d46d38p-8L, 0x1.1e6c22f27b1bf57ap+5028L, 0xb.d78e0ad132d5ff6p+5020L, 0xb.d78e0ad132d5ff7p+5020L }, + { -0x3.87ec179e6586821p-4L, 0x9.4b4c59fac13b018p+1888L, -0x3.57e18719fdcf879cp+1888L, -0x3.57e18719fdcf8798p+1888L }, + { 0x3.3d30b32379a65114p-4L, 0x4.c5d29adfdda9ea18p+4440L, 0x1.44f5e4b2409b9124p+4440L, 0x1.44f5e4b2409b9126p+4440L }, + { -0x2.e2bda144c2f2277p-4L, 0x5.64267b2495b7c128p-1996L, -0x1.8c024b9431e50014p-1996L, -0x1.8c024b9431e50012p-1996L }, + { 0x4.9de5e3de07d9f6c8p-68L, 0x9.e7a6b488ba25371p-10492L, 0x4.1f9017df12388bb8p-10556L, 0x4.1f9017df12388bcp-10556L }, + { -0x7.eeb8e528p-16416L, -0x7.bd9dbdb1739d2078p+4548L, 0x5.895fe80806e16bf8p-11864L, 0x5.895fe80806e16cp-11864L }, + { 0x2.8c83c5564b76a9ap-4L, 0x1.952d401223808022p+7108L, 0x5.66882b0ad5c27dep+7104L, 0x5.66882b0ad5c27de8p+7104L }, + { -0x2.4d42d236c3d3fd98p-4L, -0x1.ab5e5d1fb46d837cp-4360L, 0x5.fc465dcd2d8a37ep-4364L, 0x5.fc465dcd2d8a37e8p-4364L }, + { 0x4.6ae6b426dff3a728p-4L, -0x1.18b02e8036eaf6fp-2520L, -0x6.2bab4a04d616aaf8p-2524L, -0x6.2bab4a04d616aafp-2524L }, + { -0x2.3a083ce38aa2c904p-8L, -0x3.4db11e32b03da7ep-11912L, 0xa.a89c94dda8a851ap-11920L, 0xa.a89c94dda8a851bp-11920L }, + { 0x2.9ec8fd0020cc084p-4L, 0x1.3dcad9832e8f1d88p+12852L, 0x4.58883200d1e122cp+12848L, 0x4.58883200d1e122c8p+12848L }, + { -0x8.afe56fd65488476p-12L, -0x6.be0fd3b8186a0038p-7268L, 0x5.49768b31e35bebp-7276L, 0x5.49768b31e35beb08p-7276L }, + { 0x2.c9937a12a36f69e4p-4L, 0x2.84f3d72672642d5cp+2680L, 0x9.56e8000300c7c24p+2676L, 0x9.56e8000300c7c25p+2676L }, + { -0x3.6f1d5c73cafd067cp-4L, 0x4.59cae1c34a6ae298p+3720L, -0x1.8436b71ec7d37d58p+3720L, -0x1.8436b71ec7d37d56p+3720L }, + { 0x3.4d8e31567ec04358p-4L, 0xb.15e67692e908166p+728L, 0x3.005c2fd462395254p+728L, 0x3.005c2fd462395258p+728L }, + { -0x2.6fd4b22406dd3548p-4L, -0x5.32ae39061f42ebfp-3816L, 0x1.3d34a2d69fb46afap-3816L, 0x1.3d34a2d69fb46afcp-3816L }, + { 0x3.a481c0c1bd38eeccp-4L, 0x1.31f75b812f26c6fp-4144L, 0x5.a8a308f4e33ea0bp-4148L, 0x5.a8a308f4e33ea0b8p-4148L }, + { -0x2.74946e84015b7904p-4L, -0xe.ef2009edfa62e1p-7280L, 0x3.96e65616243fb15p-7280L, 0x3.96e65616243fb154p-7280L }, + { 0x4.6bc95d66b99cb698p-4L, 0x6.ec530160d23ac0ap+9560L, 0x2.6fd4a9c6a61334b8p+9560L, 0x2.6fd4a9c6a61334bcp+9560L }, + { -0x2.af79152508966b7p-4L, -0x3.033c0f9587a37dacp+9720L, 0xc.c6dd7b7b703686cp+9716L, 0xc.c6dd7b7b703686dp+9716L }, + { 0x4.12d04be0b70108dp-4L, 0x1.026134c613738e1p+832L, 0x5.48c0269f3bdf4c58p+828L, 0x5.48c0269f3bdf4c6p+828L }, + { -0x1.c5ad26059c8173c6p-4L, -0x1.902f5e5d3170116ep-600L, 0x4.3c6233f83fc19d08p-604L, 0x4.3c6233f83fc19d1p-604L }, + { 0x2.dccc064c67226e14p-4L, 0x6.2cbe80578c0dfd4p+3320L, 0x1.77583ce754d1405ep+3320L, 0x1.77583ce754d1406p+3320L }, + { -0x3.3fa98ff5a2971bfcp-4L, -0x8.b7bd8b1ef0ee6b8p+2360L, 0x2.daba824595904f3p+2360L, 0x2.daba824595904f34p+2360L }, + { 0x1.d8602eb4d94e28ecp-4L, -0x2.bae59a7e7af9a67cp+3584L, -0x6.e0d5db7658c5c028p+3580L, -0x6.e0d5db7658c5c02p+3580L }, + { -0x3.6c3a213e7b4881bp-4L, 0x5.494bb22b56f01408p+10044L, -0x1.d5f0eafdebb7153ep+10044L, -0x1.d5f0eafdebb7153cp+10044L }, + { 0x1.93f52cf9da54bfd2p-188L, 0x6.7a10e84122b54878p+13800L, 0xe.be9ca7b0c77d0b6p+13612L, 0xe.be9ca7b0c77d0b7p+13612L }, + { -0x4.58f5e4ap-16416L, -0x1.fe7de6b1cc44106ep+8880L, 0xc.81dd9ac770a9c4dp-7536L, 0xc.81dd9ac770a9c4ep-7536L }, + { 0x5.27c48a1ec2d6863p-8L, 0x2.977a191025cba5c4p+5568L, 0x1.315a3386fa9d6726p+5564L, 0x1.315a3386fa9d6728p+5564L }, + { -0x2.eb002870df40a93p-4L, -0x5.08c29ee62ab9a4c8p+692L, 0x1.765dc5a976721a6ap+692L, 0x1.765dc5a976721a6cp+692L }, + { 0x2.35b97b8a544150a4p-4L, -0x1.876176fc24a19868p-12496L, -0x4.90cea080288cc9c8p-12500L, -0x4.90cea080288cc9cp-12500L }, + { -0x4.20fe502368675c3p-4L, 0x2.89b504f1eeca05ep+14364L, -0x1.17c6332d638442ecp+14364L, -0x1.17c6332d638442eap+14364L }, + { 0x1.3507193d9fcdf874p-8L, -0x4.44ed38babbc1a31p-6140L, -0x7.6ae54c90c135363p-6148L, -0x7.6ae54c90c1353628p-6148L }, + { -0x4.9c77377231cc5c68p-4L, 0x3.0df98b1b24a9fd5p+8788L, -0x1.7f86156db3450b48p+8788L, -0x1.7f86156db3450b46p+8788L }, + { 0x4.6bfb936cb1cc028p-4L, 0x1.a2b46ba8847fdacap+12288L, 0x9.36677b413811f5ap+12284L, 0x9.36677b413811f5bp+12284L }, + { -0x7.fe3a8eade3847d6p-8L, -0x1.2e4dc4b59c87951ep-5840L, 0xd.d59f3e0866526ffp-5848L, 0xd.d59f3e0866527p-5848L }, + { 0x3.bd32a8458d6aa984p-4L, 0xf.95ff672171f9ce3p-5912L, 0x4.b8e4b10ffb79ebfp-5912L, 0x4.b8e4b10ffb79ebf8p-5912L }, + { -0xf.68a5c2a7fb327c8p-8L, -0xd.06212bca315272ap+7596L, 0x1.2a9aa0cc67647bc4p+7596L, 0x1.2a9aa0cc67647bc6p+7596L }, + { 0x2.d63c10403cb6b6ep-4L, 0x8.9e2a941dc61ad8fp+14140L, 0x2.078585b0204e1778p+14140L, 0x2.078585b0204e177cp+14140L }, + { -0x2.6b6b837e7eb6ae64p-4L, 0x4.23ab68b527c43a3p+2648L, -0xf.aa95c9793bf78dfp+2644L, -0xf.aa95c9793bf78dep+2644L }, + { 0x3.91cf23ec265a44bcp-4L, -0x4.bc960cdc39b32268p-9416L, -0x1.604dfff2b63b8282p-9416L, -0x1.604dfff2b63b828p-9416L }, + { -0x2.bc4062eed81cc3acp-4L, -0x1.fa0727fe515c697ap-11556L, 0x8.8df9fc101ed9003p-11560L, 0x8.8df9fc101ed9004p-11560L }, + { 0x2.b0fa1e0dd7f558a4p-4L, 0x5.8280a606a48f5318p+10272L, 0x1.3c5ed74d77afe5a6p+10272L, 0x1.3c5ed74d77afe5a8p+10272L }, + { -0x3.d2579cb3ff0ee9f8p-4L, -0x8.0b945d741ecd16ap-1048L, 0x3.2af74742433897ap-1048L, 0x3.2af74742433897a4p-1048L }, + { 0x3.c535c7bd86beae28p-4L, -0xf.2f9fb8404b10c06p+10324L, -0x4.a2c30bd72da67518p+10324L, -0x4.a2c30bd72da6751p+10324L }, + { -0x2.dff8fb970f266844p-4L, -0x3.74fd4274bff9725cp-1160L, 0xf.ce11601a35fdcdbp-1164L, 0xf.ce11601a35fdcdcp-1164L }, + { 0x1.4b5ff1e4dc2e3c8ap-4L, 0xd.153b5302441b7e9p-1056L, 0x1.77e756dd04bced5ep-1056L, 0x1.77e756dd04bced6p-1056L }, + { -0x2.2377af118d3b64d8p-4L, 0x1.4bd65cdbcd0ba822p+11900L, -0x4.4b025c7b23622dc8p+11896L, -0x4.4b025c7b23622dcp+11896L }, + { 0x6.95a6923d8b1019fp-48L, -0xe.509d14cf004cbe5p+2568L, -0x8.7fc1c0221d2a71cp+2524L, -0x8.7fc1c0221d2a71bp+2524L }, + { -0x6.35b4505c73bc73f8p-148L, -0x2.beb5ae276a22e078p-11460L, 0x1.897739142f742bcap-11604L, 0x1.897739142f742bccp-11604L }, + { 0x1.c09464de3920faa2p-4L, -0xe.76812b4dfc9816p-1364L, -0x2.2b1eea208c44b79p-1364L, -0x2.2b1eea208c44b78cp-1364L }, + { -0x4.62afbcd5d3fdceap-4L, 0x4.7c65d956f633426p+10856L, -0x2.12b9ade27f17cfep+10856L, -0x2.12b9ade27f17cfdcp+10856L }, + { 0x1.1eb7165174c4df74p-4L, 0x5.dd67d7554c7a8508p+13252L, 0x9.28d0f9cf98b2726p+13248L, 0x9.28d0f9cf98b2727p+13248L }, + { -0x6.1647cb705094df4p-8L, 0x5.ec80442e2871996p+2424L, -0x3.4a663d160a45da88p+2420L, -0x3.4a663d160a45da84p+2420L }, + { 0x4.8cdb06d2fa8dce68p-4L, -0x1.0734bf21712e7332p-4704L, -0x5.f09f4db0c1add98p-4708L, -0x5.f09f4db0c1add978p-4708L }, + { -0xe.c1625ff5573e525p-8L, 0x3.486cd98536b2738cp-1708L, -0x4.7fae5c446047168p-1712L, -0x4.7fae5c4460471678p-1712L }, + { 0x1.87006f5c5d2ec9eap-4L, -0x8.9ee3d43da2c297ep+9552L, -0x1.22491738b797491ap+9552L, -0x1.22491738b7974918p+9552L }, + { -0x3.3dfd025c24acda3p-4L, -0x8.400dba5a97204e1p-10880L, 0x2.b1fa547bf7acaf78p-10880L, 0x2.b1fa547bf7acaf7cp-10880L }, + { 0x2.5d1332c90ae9c9a4p-4L, -0x1.d15f57eac86808e4p-11748L, -0x5.c81202070960b9d8p-11752L, -0x5.c81202070960b9dp-11752L }, + { -0x2.28cec5c3aa2d0f18p-4L, -0x4.b7f858c41748a67p+9068L, 0xf.caa8d0ecd255b6ep+9064L, 0xf.caa8d0ecd255b6fp+9064L }, + { 0x2.67ce16bc94144a94p-4L, 0x9.ad9bf6e1a2ade89p-1124L, 0x1.f4a2cdc76f7d181p-1124L, 0x1.f4a2cdc76f7d1812p-1124L }, + { -0xe.f6744817cecdd4ep-8L, 0x5.ce4c9a5a4bd4f098p+7716L, -0x8.124097d64be7bd8p+7712L, -0x8.124097d64be7bd7p+7712L }, + { 0x3.22f0bacfe12728f8p-4L, -0x4.d9d086aa5d561098p+9364L, -0x1.40b41e628d5e3048p+9364L, -0x1.40b41e628d5e3046p+9364L }, + { -0x3.a65ad31a6788a01cp-4L, 0x2.2153a3d97331573cp-1800L, -0xc.bb3936c148ee21ap-1804L, -0xc.bb3936c148ee219p-1804L }, + { 0x4.9bdd0004d248afc8p-4L, -0x1.6ebf29fc22091bcp+4728L, -0x8.5eeca757bc17a6ep+4724L, -0x8.5eeca757bc17a6dp+4724L }, + { -0x3.6d1bb2ded9b5e544p-4L, -0x1.363933431c365c5p+6784L, 0x6.bd984ed7081d1dcp+6780L, 0x6.bd984ed7081d1dc8p+6780L }, + { 0x4.5c381c7800220bb8p-4L, -0x1.7a9820b7b4be9b5cp+10592L, -0x8.3a163379e86ae8dp+10588L, -0x8.3a163379e86ae8cp+10588L }, + { -0x6.12772be7f5f9adp-8L, 0x2.5ff922bcfdd1ccf4p+13856L, -0x1.50e2b035b7e3a3c6p+13852L, -0x1.50e2b035b7e3a3c4p+13852L }, + { 0x4.6f048c603adeb688p-4L, -0x7.dcd7d704615cb8ep-7496L, -0x2.c648b04027667808p-7496L, -0x2.c648b04027667804p-7496L }, + { -0x1.426147d80b509dfap-4L, -0x3.b6cb63cc4e57698cp+12696L, 0x7.0727b8bc7de37648p+12692L, 0x7.0727b8bc7de3765p+12692L }, + { 0x7.43a24958p-16416L, -0x1.20c104316e13e7eap+2340L, -0xb.d225983bb5815cp-14076L, -0xb.d225983bb5815bfp-14076L }, + { -0x4.aca95d18p-16416L, -0x4.b253ac25282630fp+5944L, 0x1.fac465fc7e12004p-10468L, 0x1.fac465fc7e120042p-10468L }, + { 0xd.346171700066942p-8L, -0x3.5c5b7a0cde7c0b9p-4344L, -0x3.e6d4bdea75d4f7c8p-4348L, -0x3.e6d4bdea75d4f7c4p-4348L }, + { -0xc.f7fe649ca9f78f1p-8L, -0xe.3a382cc6e7f5879p-4128L, 0x1.112c520281402072p-4128L, 0x1.112c520281402074p-4128L }, + { 0x2.891205a511e09d4p-4L, -0xa.3b1708de40827f3p+9100L, -0x2.2bce95e0f3eadc8p+9100L, -0x2.2bce95e0f3eadc7cp+9100L }, + { -0x2.745b23499b0ba8b8p-4L, 0x1.a50af797227d1b2p-12948L, -0x6.528e377bfd748168p-12952L, -0x6.528e377bfd74816p-12952L }, + { 0x2.e200bf44c048b27p-4L, 0x1.502214b180236b8ep+1004L, 0x5.056320e0e40dcac8p+1000L, 0x5.056320e0e40dcadp+1000L }, + { -0x1.003d0ef8adbf3c9ep-4L, -0x6.b73ddbc1c250fa2p+1172L, 0xa.03b4bfa836d3073p+1168L, 0xa.03b4bfa836d3074p+1168L }, + { 0x4.a8e3b6eba0e5cc5p-4L, -0xa.6207a616c7e6709p+6296L, -0x3.d4256c2208b55f5p+6296L, -0x3.d4256c2208b55f4cp+6296L }, + { -0x2.a92e6e1474be8348p-4L, 0x3.bb46a57c610a305p+7304L, -0xf.aabbe15fe37ce8bp+7300L, -0xf.aabbe15fe37ce8ap+7300L }, + { 0x4.96fd5f79440dfd3p-4L, -0x2.86ed35b8573a3bfcp+624L, -0xe.b63b818d676319ap+620L, -0xe.b63b818d6763199p+620L }, + { -0x3.eca5c520475dad78p-4L, -0x1.112bec17e2eb9514p-7920L, 0x6.ee6ca95de9ffe858p-7924L, 0x6.ee6ca95de9ffe86p-7924L }, + { 0x4.8f4fa442deb571ep-4L, 0x4.bd8cc4d14c3c0818p+3100L, 0x1.b701f77c99e885p+3100L, 0x1.b701f77c99e88502p+3100L }, + { -0x1.cc63ab2f4422f75ep-4L, -0x4.1bd4c5adafb9c458p-7880L, 0xb.4ef13944ce6d745p-7884L, 0xb.4ef13944ce6d746p-7884L }, + { 0x4.5a1c9f3d22df0e3p-4L, -0x4.64d5303735c2074p-6252L, -0x1.866d8aad2725025p-6252L, -0x1.866d8aad2725024ep-6252L }, + { -0x1.55b34aaaa8d19ee2p-4L, 0xf.75a8872ceab3815p-5504L, -0x1.f15dd2d15d4dc058p-5504L, -0x1.f15dd2d15d4dc056p-5504L }, + { 0x2.b3311b1a7010d558p-4L, 0x1.1ecd98b620696b2ep-3596L, 0x4.085356c3e0bf9dfp-3600L, 0x4.085356c3e0bf9df8p-3600L }, + { -0x1.68820b6e4592bfc4p-4L, -0x6.67e7a1d8fd4df47p-13612L, 0xd.9f8d17ac5abfbefp-13616L, 0xd.9f8d17ac5abfbfp-13616L }, + { 0x3.b6a73d8796b983bcp-4L, 0xa.68bc997e0f48d23p-14004L, 0x3.2261d9832d9eb434p-14004L, 0x3.2261d9832d9eb438p-14004L }, + { -0x1.aaa0ed7ab388530cp-4L, 0x5.c31f424ba4ed1fd8p-11856L, -0xe.a1394c8e746bdp-11860L, -0xe.a1394c8e746bcffp-11860L }, +}; + +int check_equal(long double res, long double expected) +{ + if (res != expected) { + return 0; + } + return (__builtin_copysignl(1.0L, res) == + __builtin_copysignl(1.0L, expected)); +} + +int main(void) +{ + int ret = 0; + int i; + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + long double ld_res; + __asm__ volatile ("fyl2xp1" : "=t" (ld_res) : + "0" (tests[i].arg0), "u" (tests[i].arg1) : "st(1)"); + if (!check_equal(ld_res, tests[i].down) && + !check_equal(ld_res, tests[i].up)) { + printf("FAIL: fyl2xp1 %La %La, expected %La or %La, got %La\n", + tests[i].arg0, tests[i].arg1, tests[i].down, tests[i].up, + ld_res); + ret = 1; + } + } + return ret; +} diff --git a/tests/tcg/i386/test-i386-pcmpistri.c b/tests/tcg/i386/test-i386-pcmpistri.c new file mode 100644 index 0000000000000000000000000000000000000000..1e81ae611acfc5ea9cf3309a192d94cc0b8b9308 --- /dev/null +++ b/tests/tcg/i386/test-i386-pcmpistri.c @@ -0,0 +1,33 @@ +/* Test pcmpistri instruction. */ + +#include +#include + +union u { + __m128i x; + unsigned char uc[16]; +}; + +union u s0 = { .uc = { 0 } }; +union u s1 = { .uc = "abcdefghijklmnop" }; +union u s2 = { .uc = "bcdefghijklmnopa" }; +union u s3 = { .uc = "bcdefghijklmnab" }; + +int +main(void) +{ + int ret = 0; + if (_mm_cmpistri(s0.x, s0.x, 0x4c) != 15) { + printf("FAIL: pcmpistri test 1\n"); + ret = 1; + } + if (_mm_cmpistri(s1.x, s2.x, 0x4c) != 15) { + printf("FAIL: pcmpistri test 2\n"); + ret = 1; + } + if (_mm_cmpistri(s1.x, s3.x, 0x4c) != 16) { + printf("FAIL: pcmpistri test 3\n"); + ret = 1; + } + return ret; +} diff --git a/tests/tcg/i386/test-i386-sse-exceptions.c b/tests/tcg/i386/test-i386-sse-exceptions.c new file mode 100644 index 0000000000000000000000000000000000000000..a104f46c11cbf64c036b7a578449bed950b5b7b5 --- /dev/null +++ b/tests/tcg/i386/test-i386-sse-exceptions.c @@ -0,0 +1,813 @@ +/* Test SSE exceptions. */ + +#include +#include +#include + +volatile float f_res; +volatile double d_res; + +volatile float f_snan = __builtin_nansf(""); +volatile float f_half = 0.5f; +volatile float f_third = 1.0f / 3.0f; +volatile float f_nan = __builtin_nanl(""); +volatile float f_inf = __builtin_inff(); +volatile float f_ninf = -__builtin_inff(); +volatile float f_one = 1.0f; +volatile float f_two = 2.0f; +volatile float f_zero = 0.0f; +volatile float f_nzero = -0.0f; +volatile float f_min = FLT_MIN; +volatile float f_true_min = 0x1p-149f; +volatile float f_max = FLT_MAX; +volatile float f_nmax = -FLT_MAX; + +volatile double d_snan = __builtin_nans(""); +volatile double d_half = 0.5; +volatile double d_third = 1.0 / 3.0; +volatile double d_nan = __builtin_nan(""); +volatile double d_inf = __builtin_inf(); +volatile double d_ninf = -__builtin_inf(); +volatile double d_one = 1.0; +volatile double d_two = 2.0; +volatile double d_zero = 0.0; +volatile double d_nzero = -0.0; +volatile double d_min = DBL_MIN; +volatile double d_true_min = 0x1p-1074; +volatile double d_max = DBL_MAX; +volatile double d_nmax = -DBL_MAX; + +volatile int32_t i32_max = INT32_MAX; + +#define IE (1 << 0) +#define ZE (1 << 2) +#define OE (1 << 3) +#define UE (1 << 4) +#define PE (1 << 5) +#define EXC (IE | ZE | OE | UE | PE) + +uint32_t mxcsr_default = 0x1f80; +uint32_t mxcsr_ftz = 0x9f80; + +int main(void) +{ + uint32_t mxcsr; + int32_t i32_res; + int ret = 0; + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = f_snan; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: widen float snan\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = d_min; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (UE | PE)) { + printf("FAIL: narrow float underflow\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = d_max; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (OE | PE)) { + printf("FAIL: narrow float overflow\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = d_third; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: narrow float inexact\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = d_snan; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: narrow float snan\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("roundss $4, %0, %0" : "=x" (f_res) : "0" (f_min)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: roundss min\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("roundss $12, %0, %0" : "=x" (f_res) : "0" (f_min)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != 0) { + printf("FAIL: roundss no-inexact min\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("roundss $4, %0, %0" : "=x" (f_res) : "0" (f_snan)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: roundss snan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("roundss $12, %0, %0" : "=x" (f_res) : "0" (f_snan)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: roundss no-inexact snan\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("roundsd $4, %0, %0" : "=x" (d_res) : "0" (d_min)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: roundsd min\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("roundsd $12, %0, %0" : "=x" (d_res) : "0" (d_min)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != 0) { + printf("FAIL: roundsd no-inexact min\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("roundsd $4, %0, %0" : "=x" (d_res) : "0" (d_snan)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: roundsd snan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("roundsd $12, %0, %0" : "=x" (d_res) : "0" (d_snan)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: roundsd no-inexact snan\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("comiss %1, %0" : : "x" (f_nan), "x" (f_zero)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: comiss nan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("ucomiss %1, %0" : : "x" (f_nan), "x" (f_zero)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != 0) { + printf("FAIL: ucomiss nan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("ucomiss %1, %0" : : "x" (f_snan), "x" (f_zero)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: ucomiss snan\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("comisd %1, %0" : : "x" (d_nan), "x" (d_zero)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: comisd nan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("ucomisd %1, %0" : : "x" (d_nan), "x" (d_zero)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != 0) { + printf("FAIL: ucomisd nan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("ucomisd %1, %0" : : "x" (d_snan), "x" (d_zero)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: ucomisd snan\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_max + f_max; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (OE | PE)) { + printf("FAIL: float add overflow\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_max + f_min; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: float add inexact\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_inf + f_ninf; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: float add inf -inf\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_snan + f_third; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: float add snan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_ftz)); + f_res = f_true_min + f_true_min; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (UE | PE)) { + printf("FAIL: float add FTZ underflow\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_max + d_max; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (OE | PE)) { + printf("FAIL: double add overflow\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_max + d_min; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: double add inexact\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_inf + d_ninf; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: double add inf -inf\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_snan + d_third; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: double add snan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_ftz)); + d_res = d_true_min + d_true_min; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (UE | PE)) { + printf("FAIL: double add FTZ underflow\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_max - f_nmax; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (OE | PE)) { + printf("FAIL: float sub overflow\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_max - f_min; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: float sub inexact\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_inf - f_inf; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: float sub inf inf\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_snan - f_third; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: float sub snan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_ftz)); + f_res = f_min - f_true_min; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (UE | PE)) { + printf("FAIL: float sub FTZ underflow\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_max - d_nmax; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (OE | PE)) { + printf("FAIL: double sub overflow\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_max - d_min; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: double sub inexact\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_inf - d_inf; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: double sub inf inf\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_snan - d_third; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: double sub snan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_ftz)); + d_res = d_min - d_true_min; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (UE | PE)) { + printf("FAIL: double sub FTZ underflow\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_max * f_max; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (OE | PE)) { + printf("FAIL: float mul overflow\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_third * f_third; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: float mul inexact\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_min * f_min; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (UE | PE)) { + printf("FAIL: float mul underflow\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_inf * f_zero; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: float mul inf 0\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_snan * f_third; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: float mul snan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_ftz)); + f_res = f_min * f_half; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (UE | PE)) { + printf("FAIL: float mul FTZ underflow\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_max * d_max; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (OE | PE)) { + printf("FAIL: double mul overflow\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_third * d_third; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: double mul inexact\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_min * d_min; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (UE | PE)) { + printf("FAIL: double mul underflow\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_inf * d_zero; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: double mul inf 0\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_snan * d_third; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: double mul snan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_ftz)); + d_res = d_min * d_half; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (UE | PE)) { + printf("FAIL: double mul FTZ underflow\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_max / f_min; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (OE | PE)) { + printf("FAIL: float div overflow\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_one / f_third; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: float div inexact\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_min / f_max; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (UE | PE)) { + printf("FAIL: float div underflow\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_one / f_zero; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != ZE) { + printf("FAIL: float div 1 0\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_inf / f_zero; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != 0) { + printf("FAIL: float div inf 0\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_nan / f_zero; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != 0) { + printf("FAIL: float div nan 0\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_zero / f_zero; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: float div 0 0\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_inf / f_inf; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: float div inf inf\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + f_res = f_snan / f_third; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: float div snan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_ftz)); + f_res = f_min / f_two; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (UE | PE)) { + printf("FAIL: float div FTZ underflow\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_max / d_min; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (OE | PE)) { + printf("FAIL: double div overflow\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_one / d_third; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: double div inexact\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_min / d_max; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (UE | PE)) { + printf("FAIL: double div underflow\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_one / d_zero; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != ZE) { + printf("FAIL: double div 1 0\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_inf / d_zero; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != 0) { + printf("FAIL: double div inf 0\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_nan / d_zero; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != 0) { + printf("FAIL: double div nan 0\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_zero / d_zero; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: double div 0 0\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_inf / d_inf; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: double div inf inf\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + d_res = d_snan / d_third; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: double div snan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_ftz)); + d_res = d_min / d_two; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != (UE | PE)) { + printf("FAIL: double div FTZ underflow\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("sqrtss %0, %0" : "=x" (f_res) : "0" (f_max)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: sqrtss inexact\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("sqrtss %0, %0" : "=x" (f_res) : "0" (f_nmax)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: sqrtss -max\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("sqrtss %0, %0" : "=x" (f_res) : "0" (f_ninf)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: sqrtss -inf\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("sqrtss %0, %0" : "=x" (f_res) : "0" (f_snan)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: sqrtss snan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("sqrtss %0, %0" : "=x" (f_res) : "0" (f_nzero)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != 0) { + printf("FAIL: sqrtss -0\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("sqrtss %0, %0" : "=x" (f_res) : + "0" (-__builtin_nanf(""))); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != 0) { + printf("FAIL: sqrtss -nan\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("sqrtsd %0, %0" : "=x" (d_res) : "0" (d_max)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: sqrtsd inexact\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("sqrtsd %0, %0" : "=x" (d_res) : "0" (d_nmax)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: sqrtsd -max\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("sqrtsd %0, %0" : "=x" (d_res) : "0" (d_ninf)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: sqrtsd -inf\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("sqrtsd %0, %0" : "=x" (d_res) : "0" (d_snan)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: sqrtsd snan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("sqrtsd %0, %0" : "=x" (d_res) : "0" (d_nzero)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != 0) { + printf("FAIL: sqrtsd -0\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("sqrtsd %0, %0" : "=x" (d_res) : + "0" (-__builtin_nan(""))); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != 0) { + printf("FAIL: sqrtsd -nan\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("maxss %1, %0" : : "x" (f_nan), "x" (f_zero)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: maxss nan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("minss %1, %0" : : "x" (f_nan), "x" (f_zero)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: minss nan\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("maxsd %1, %0" : : "x" (d_nan), "x" (d_zero)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: maxsd nan\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("minsd %1, %0" : : "x" (d_nan), "x" (d_zero)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: minsd nan\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("cvtsi2ss %1, %0" : "=x" (f_res) : "m" (i32_max)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: cvtsi2ss inexact\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("cvtsi2sd %1, %0" : "=x" (d_res) : "m" (i32_max)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != 0) { + printf("FAIL: cvtsi2sd exact\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("cvtss2si %1, %0" : "=r" (i32_res) : "x" (1.5f)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: cvtss2si inexact\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("cvtss2si %1, %0" : "=r" (i32_res) : "x" (0x1p31f)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: cvtss2si 0x1p31\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("cvtss2si %1, %0" : "=r" (i32_res) : "x" (f_inf)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: cvtss2si inf\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("cvtsd2si %1, %0" : "=r" (i32_res) : "x" (1.5)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: cvtsd2si inexact\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("cvtsd2si %1, %0" : "=r" (i32_res) : "x" (0x1p31)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: cvtsd2si 0x1p31\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("cvtsd2si %1, %0" : "=r" (i32_res) : "x" (d_inf)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: cvtsd2si inf\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("cvttss2si %1, %0" : "=r" (i32_res) : "x" (1.5f)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: cvttss2si inexact\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("cvttss2si %1, %0" : "=r" (i32_res) : "x" (0x1p31f)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: cvttss2si 0x1p31\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("cvttss2si %1, %0" : "=r" (i32_res) : "x" (f_inf)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: cvttss2si inf\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("cvttsd2si %1, %0" : "=r" (i32_res) : "x" (1.5)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != PE) { + printf("FAIL: cvttsd2si inexact\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("cvttsd2si %1, %0" : "=r" (i32_res) : "x" (0x1p31)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: cvttsd2si 0x1p31\n"); + ret = 1; + } + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("cvttsd2si %1, %0" : "=r" (i32_res) : "x" (d_inf)); + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != IE) { + printf("FAIL: cvttsd2si inf\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("rcpss %0, %0" : "=x" (f_res) : "0" (f_snan)); + f_res += f_one; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != 0) { + printf("FAIL: rcpss snan\n"); + ret = 1; + } + + __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr_default)); + __asm__ volatile ("rsqrtss %0, %0" : "=x" (f_res) : "0" (f_snan)); + f_res += f_one; + __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr)); + if ((mxcsr & EXC) != 0) { + printf("FAIL: rsqrtss snan\n"); + ret = 1; + } + + return ret; +} diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target index 51fb75ecfdd0fe6d0d70737cc61b460037dca6b6..cb49cc9ccb25d7993bec59c3dff51dff569258ab 100644 --- a/tests/tcg/multiarch/Makefile.target +++ b/tests/tcg/multiarch/Makefile.target @@ -28,6 +28,8 @@ run-float_%: float_% testthread: LDFLAGS+=-lpthread +threadcount: LDFLAGS+=-lpthread + # We define the runner for test-mmap after the individual # architectures have defined their supported pages sizes. If no # additional page sizes are defined we only run the default test. diff --git a/tests/tcg/multiarch/float_convs.c b/tests/tcg/multiarch/float_convs.c index 47e24b8b165d6a97728448b27a993570732ccf67..e9be75c2d50b5aa3a15b307e685b077e8cfe18b4 100644 --- a/tests/tcg/multiarch/float_convs.c +++ b/tests/tcg/multiarch/float_convs.c @@ -30,7 +30,9 @@ float_mapping round_flags[] = { #ifdef FE_DOWNWARD { FE_DOWNWARD, "downwards" }, #endif +#ifdef FE_TOWARDZERO { FE_TOWARDZERO, "to zero" } +#endif }; static void print_input(float input) diff --git a/tests/tcg/multiarch/float_helpers.h b/tests/tcg/multiarch/float_helpers.h index 6337bc66c1adf3184a808ca1a87768f04a464e82..309f3f4bf10d32e4370218be3cb139172e429578 100644 --- a/tests/tcg/multiarch/float_helpers.h +++ b/tests/tcg/multiarch/float_helpers.h @@ -8,6 +8,23 @@ #include +/* Some hosts do not have support for all of these; not required by ISO C. */ +#ifndef FE_OVERFLOW +#define FE_OVERFLOW 0 +#endif +#ifndef FE_UNDERFLOW +#define FE_UNDERFLOW 0 +#endif +#ifndef FE_DIVBYZERO +#define FE_DIVBYZERO 0 +#endif +#ifndef FE_INEXACT +#define FE_INEXACT 0 +#endif +#ifndef FE_INVALID +#define FE_INVALID 0 +#endif + /* Number of constants in each table */ int get_num_f16(void); int get_num_f32(void); diff --git a/tests/tcg/multiarch/float_madds.c b/tests/tcg/multiarch/float_madds.c index eceb4ae38b60cef93ce4e42d069734a9746b1765..e422608ccdac607e142a0f35cf0097511e195f36 100644 --- a/tests/tcg/multiarch/float_madds.c +++ b/tests/tcg/multiarch/float_madds.c @@ -29,7 +29,9 @@ float_mapping round_flags[] = { #ifdef FE_DOWNWARD { FE_DOWNWARD, "downwards" }, #endif +#ifdef FE_TOWARDZERO { FE_TOWARDZERO, "to zero" } +#endif }; diff --git a/tests/tcg/multiarch/gdbstub/sha1.py b/tests/tcg/multiarch/gdbstub/sha1.py index 734553b98bbce9cda93884403d981d1889edd093..2bfde49633cf290112955809295e020da1a1b604 100644 --- a/tests/tcg/multiarch/gdbstub/sha1.py +++ b/tests/tcg/multiarch/gdbstub/sha1.py @@ -65,6 +65,10 @@ def run_test(): print("SKIPPING (not connected)", file=sys.stderr) exit(0) +if gdb.parse_and_eval('$pc') == 0: + print("SKIP: PC not set") + exit(0) + try: # These are not very useful in scripts gdb.execute("set pagination off") diff --git a/tests/tcg/multiarch/linux-test.c b/tests/tcg/multiarch/linux-test.c index 8a7c15cd31201772966ba48fbf72c08762936380..96bbad58231849982d753afa61bf117ce1b0c53f 100644 --- a/tests/tcg/multiarch/linux-test.c +++ b/tests/tcg/multiarch/linux-test.c @@ -296,7 +296,7 @@ static void test_socket(void) server_fd = server_socket(); /* find out what port we got */ socklen = sizeof(server_addr); - ret = getsockname(server_fd, &server_addr, &socklen); + ret = getsockname(server_fd, (struct sockaddr *)&server_addr, &socklen); chk_error(ret); server_port = ntohs(server_addr.sin_port); diff --git a/tests/tcg/multiarch/threadcount.c b/tests/tcg/multiarch/threadcount.c new file mode 100644 index 0000000000000000000000000000000000000000..545a1c81466f4a9c6598b638793edcf2840b3d4b --- /dev/null +++ b/tests/tcg/multiarch/threadcount.c @@ -0,0 +1,64 @@ +/* + * Thread Exerciser + * + * Unlike testthread which is mainly concerned about testing thread + * semantics this test is used to exercise the thread creation and + * accounting. A version of this test found a problem with clashing + * cpu_indexes which caused a break in plugin handling. + * + * Based on the original test case by Nikolay Igotti. + * + * Copyright (c) 2020 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include +#include +#include +#include +#include + +int max_threads = 10; + +typedef struct { + int delay; +} ThreadArg; + +static void *thread_fn(void* varg) +{ + ThreadArg *arg = varg; + usleep(arg->delay); + free(arg); + return NULL; +} + +int main(int argc, char **argv) +{ + int i; + pthread_t *threads; + + if (argc > 1) { + max_threads = atoi(argv[1]); + } + threads = calloc(sizeof(pthread_t), max_threads); + + for (i = 0; i < max_threads; i++) { + ThreadArg *arg = calloc(sizeof(ThreadArg), 1); + arg->delay = i * 100; + pthread_create(threads + i, NULL, thread_fn, arg); + } + + printf("Created %d threads\n", max_threads); + + /* sleep until roughly half the threads have "finished" */ + usleep(max_threads * 50); + + for (i = 0; i < max_threads; i++) { + pthread_join(threads[i], NULL); + } + + printf("Done\n"); + + return 0; +} diff --git a/tests/tcg/xtensa/fpu.h b/tests/tcg/xtensa/fpu.h new file mode 100644 index 0000000000000000000000000000000000000000..42e32174730416d5b23bf622e2ffe95ae26eebf1 --- /dev/null +++ b/tests/tcg/xtensa/fpu.h @@ -0,0 +1,142 @@ +#if XCHAL_HAVE_DFP || XCHAL_HAVE_FP_DIV +#define DFPU 1 +#else +#define DFPU 0 +#endif + +#define FCR_RM_NEAREST 0 +#define FCR_RM_TRUNC 1 +#define FCR_RM_CEIL 2 +#define FCR_RM_FLOOR 3 + +#define FSR__ 0x00000000 +#define FSR_I 0x00000080 +#define FSR_U 0x00000100 +#define FSR_O 0x00000200 +#define FSR_Z 0x00000400 +#define FSR_V 0x00000800 + +#define FSR_UI (FSR_U | FSR_I) +#define FSR_OI (FSR_O | FSR_I) + +#define F32_0 0x00000000 +#define F32_0_5 0x3f000000 +#define F32_1 0x3f800000 +#define F32_MAX 0x7f7fffff +#define F32_PINF 0x7f800000 +#define F32_NINF 0xff800000 + +#define F32_DNAN 0x7fc00000 +#define F32_SNAN(v) (0x7f800000 | (v)) +#define F32_QNAN(v) (0x7fc00000 | (v)) + +#define F32_MINUS 0x80000000 + +#define F64_0 0x0000000000000000 +#define F64_MIN_NORM 0x0010000000000000 +#define F64_1 0x3ff0000000000000 +#define F64_MAX_2 0x7fe0000000000000 +#define F64_MAX 0x7fefffffffffffff +#define F64_PINF 0x7ff0000000000000 +#define F64_NINF 0xfff0000000000000 + +#define F64_DNAN 0x7ff8000000000000 +#define F64_SNAN(v) (0x7ff0000000000000 | (v)) +#define F64_QNAN(v) (0x7ff8000000000000 | (v)) + +#define F64_MINUS 0x8000000000000000 + +.macro test_op1_rm op, fr0, fr1, v0, r, sr + movi a2, 0 + wur a2, fsr + movfp \fr0, \v0 + \op \fr1, \fr0 + check_res \fr1, \r, \sr +.endm + +.macro test_op2_rm op, fr0, fr1, fr2, v0, v1, r, sr + movi a2, 0 + wur a2, fsr + movfp \fr0, \v0 + movfp \fr1, \v1 + \op \fr2, \fr0, \fr1 + check_res \fr2, \r, \sr +.endm + +.macro test_op3_rm op, fr0, fr1, fr2, fr3, v0, v1, v2, r, sr + movi a2, 0 + wur a2, fsr + movfp \fr0, \v0 + movfp \fr1, \v1 + movfp \fr2, \v2 + \op \fr0, \fr1, \fr2 + check_res \fr3, \r, \sr +.endm + +.macro test_op1_ex op, fr0, fr1, v0, rm, r, sr + movi a2, \rm + wur a2, fcr + test_op1_rm \op, \fr0, \fr1, \v0, \r, \sr + movi a2, (\rm) | 0x7c + wur a2, fcr + test_op1_rm \op, \fr0, \fr1, \v0, \r, \sr +.endm + +.macro test_op2_ex op, fr0, fr1, fr2, v0, v1, rm, r, sr + movi a2, \rm + wur a2, fcr + test_op2_rm \op, \fr0, \fr1, \fr2, \v0, \v1, \r, \sr + movi a2, (\rm) | 0x7c + wur a2, fcr + test_op2_rm \op, \fr0, \fr1, \fr2, \v0, \v1, \r, \sr +.endm + +.macro test_op3_ex op, fr0, fr1, fr2, fr3, v0, v1, v2, rm, r, sr + movi a2, \rm + wur a2, fcr + test_op3_rm \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, \r, \sr + movi a2, (\rm) | 0x7c + wur a2, fcr + test_op3_rm \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, \r, \sr +.endm + +.macro test_op1 op, fr0, fr1, v0, r0, r1, r2, r3, sr0, sr1, sr2, sr3 + test_op1_ex \op, \fr0, \fr1, \v0, 0, \r0, \sr0 + test_op1_ex \op, \fr0, \fr1, \v0, 1, \r1, \sr1 + test_op1_ex \op, \fr0, \fr1, \v0, 2, \r2, \sr2 + test_op1_ex \op, \fr0, \fr1, \v0, 3, \r3, \sr3 +.endm + +.macro test_op2 op, fr0, fr1, fr2, v0, v1, r0, r1, r2, r3, sr0, sr1, sr2, sr3 + test_op2_ex \op, \fr0, \fr1, \fr2, \v0, \v1, 0, \r0, \sr0 + test_op2_ex \op, \fr0, \fr1, \fr2, \v0, \v1, 1, \r1, \sr1 + test_op2_ex \op, \fr0, \fr1, \fr2, \v0, \v1, 2, \r2, \sr2 + test_op2_ex \op, \fr0, \fr1, \fr2, \v0, \v1, 3, \r3, \sr3 +.endm + +.macro test_op3 op, fr0, fr1, fr2, fr3, v0, v1, v2, r0, r1, r2, r3, sr0, sr1, sr2, sr3 + test_op3_ex \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, 0, \r0, \sr0 + test_op3_ex \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, 1, \r1, \sr1 + test_op3_ex \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, 2, \r2, \sr2 + test_op3_ex \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, 3, \r3, \sr3 +.endm + +.macro test_op2_cpe op + set_vector kernel, 2f + movi a2, 0 + wsr a2, cpenable +1: + \op f2, f0, f1 + test_fail +2: + rsr a2, excvaddr + movi a3, 1b + assert eq, a2, a3 + rsr a2, exccause + movi a3, 32 + assert eq, a2, a3 + + set_vector kernel, 0 + movi a2, 1 + wsr a2, cpenable +.endm diff --git a/tests/tcg/xtensa/macros.inc b/tests/tcg/xtensa/macros.inc index aa8f95bce879767105ede99de618483397bcfa62..f88937c7bf82981d4235c3bc5b656da78251a13e 100644 --- a/tests/tcg/xtensa/macros.inc +++ b/tests/tcg/xtensa/macros.inc @@ -3,7 +3,7 @@ .macro test_suite name .data status: .word result -result: .space 256 +result: .space 1024 .text .global main .align 4 @@ -25,9 +25,9 @@ main: movi a3, 0 beqz a2, 2f 1: - l8ui a1, a0, 0 + l32i a1, a0, 0 or a3, a3, a1 - addi a0, a0, 1 + addi a0, a0, 4 addi a2, a2, -1 bnez a2, 1b 2: @@ -65,7 +65,7 @@ test_\name: reset_ps movi a2, status l32i a3, a2, 0 - addi a3, a3, 1 + addi a3, a3, 4 s32i a3, a2, 0 .endm @@ -78,7 +78,7 @@ test_\name: movi a2, status l32i a2, a2, 0 movi a3, 1 - s8i a3, a2, 0 + s32i a3, a2, 0 #ifdef DEBUG print failed #endif diff --git a/tests/tcg/xtensa/test_dfp0_arith.S b/tests/tcg/xtensa/test_dfp0_arith.S new file mode 100644 index 0000000000000000000000000000000000000000..53bf8122d082766edc5275121e100d8f62861afc --- /dev/null +++ b/tests/tcg/xtensa/test_dfp0_arith.S @@ -0,0 +1,162 @@ +#include "macros.inc" +#include "fpu.h" + +test_suite fp0_arith + +#if XCHAL_HAVE_DFP + +.macro movfp fr, v + movi a2, ((\v) >> 32) & 0xffffffff + movi a3, ((\v) & 0xffffffff) + wfrd \fr, a2, a3 +.endm + +.macro check_res fr, r, sr + rfrd a2, \fr + dump a2 + movi a3, ((\r) >> 32) & 0xffffffff + assert eq, a2, a3 + rfr a2, \fr + dump a2 + movi a3, ((\r) & 0xffffffff) + assert eq, a2, a3 + rur a2, fsr + movi a3, \sr + assert eq, a2, a3 +.endm + +test add_d + movi a2, 1 + wsr a2, cpenable + + /* MAX_FLOAT + MAX_FLOAT = +inf/MAX_FLOAT */ + test_op2 add.d, f6, f7, f8, F64_MAX, F64_MAX, \ + F64_PINF, F64_MAX, F64_PINF, F64_MAX, \ + FSR_OI, FSR_OI, FSR_OI, FSR_OI +test_end + +test add_d_inf + /* 1 + +inf = +inf */ + test_op2 add.d, f6, f7, f8, F64_1, F64_PINF, \ + F64_PINF, F64_PINF, F64_PINF, F64_PINF, \ + FSR__, FSR__, FSR__, FSR__ + + /* +inf + -inf = default NaN */ + test_op2 add.d, f0, f1, f2, F64_PINF, F64_NINF, \ + F64_DNAN, F64_DNAN, F64_DNAN, F64_DNAN, \ + FSR_V, FSR_V, FSR_V, FSR_V +test_end + +test add_d_nan_dfpu + /* 1 + QNaN = QNaN */ + test_op2 add.d, f9, f10, f11, F64_1, F64_QNAN(1), \ + F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), \ + FSR__, FSR__, FSR__, FSR__ + /* 1 + SNaN = QNaN */ + test_op2 add.d, f12, f13, f14, F64_1, F64_SNAN(1), \ + F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), \ + FSR_V, FSR_V, FSR_V, FSR_V + + /* SNaN1 + SNaN2 = QNaN2 */ + test_op2 add.d, f15, f0, f1, F64_SNAN(1), F64_SNAN(2), \ + F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), \ + FSR_V, FSR_V, FSR_V, FSR_V + /* QNaN1 + SNaN2 = QNaN2 */ + test_op2 add.d, f5, f6, f7, F64_QNAN(1), F64_SNAN(2), \ + F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), \ + FSR_V, FSR_V, FSR_V, FSR_V + /* SNaN1 + QNaN2 = QNaN2 */ + test_op2 add.d, f8, f9, f10, F64_SNAN(1), F64_QNAN(2), \ + F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), \ + FSR_V, FSR_V, FSR_V, FSR_V +test_end + +test sub_d + /* norm - norm = denorm */ + test_op2 sub.d, f6, f7, f8, F64_MIN_NORM | 1, F64_MIN_NORM, \ + 0x00000001, 0x00000001, 0x00000001, 0x00000001, \ + FSR__, FSR__, FSR__, FSR__ +test_end + +test mul_d + test_op2 mul.d, f0, f1, f2, F64_1 | 1, F64_1 | 1, \ + F64_1 | 2, F64_1 | 2, F64_1 | 3, F64_1 | 2, \ + FSR_I, FSR_I, FSR_I, FSR_I + /* MAX_FLOAT/2 * MAX_FLOAT/2 = +inf/MAX_FLOAT */ + test_op2 mul.d, f6, f7, f8, F64_MAX_2, F64_MAX_2, \ + F64_PINF, F64_MAX, F64_PINF, F64_MAX, \ + FSR_OI, FSR_OI, FSR_OI, FSR_OI + /* min norm * min norm = 0/denorm */ + test_op2 mul.d, f6, f7, f8, F64_MIN_NORM, F64_MIN_NORM, \ + F64_0, F64_0, 0x00000001, F64_0, \ + FSR_UI, FSR_UI, FSR_UI, FSR_UI + /* inf * 0 = default NaN */ + test_op2 mul.d, f6, f7, f8, F64_PINF, F64_0, \ + F64_DNAN, F64_DNAN, F64_DNAN, F64_DNAN, \ + FSR_V, FSR_V, FSR_V, FSR_V +test_end + +test madd_d + test_op3 madd.d, f0, f1, f2, f0, F64_0, F64_1 | 1, F64_1 | 1, \ + F64_1 | 2, F64_1 | 2, F64_1 | 3, F64_1 | 2, \ + FSR_I, FSR_I, FSR_I, FSR_I +test_end + +test madd_d_precision + test_op3 madd.d, f0, f1, f2, f0, \ + F64_MINUS | F64_1 | 2, F64_1 | 1, F64_1 | 1, \ + 0x3970000000000000, 0x3970000000000000, 0x3970000000000000, 0x3970000000000000, \ + FSR__, FSR__, FSR__, FSR__ +test_end + +test madd_d_nan_dfpu + /* DFPU madd/msub NaN1, NaN2, NaN3 priority: NaN1, NaN3, NaN2 */ + test_op3 madd.d, f0, f1, f2, f0, F64_QNAN(1), F64_1, F64_1, \ + F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), \ + FSR__, FSR__, FSR__, FSR__ + test_op3 madd.d, f0, f1, f2, f0, F64_1, F64_QNAN(2), F64_1, \ + F64_QNAN(2), F64_QNAN(2), F64_QNAN(2), F64_QNAN(2), \ + FSR__, FSR__, FSR__, FSR__ + test_op3 madd.d, f0, f1, f2, f0, F64_1, F64_1, F64_QNAN(3), \ + F64_QNAN(3), F64_QNAN(3), F64_QNAN(3), F64_QNAN(3), \ + FSR__, FSR__, FSR__, FSR__ + + test_op3 madd.d, f0, f1, f2, f0, F64_QNAN(1), F64_QNAN(2), F64_1, \ + F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), \ + FSR__, FSR__, FSR__, FSR__ + test_op3 madd.d, f0, f1, f2, f0, F64_QNAN(1), F64_1, F64_QNAN(3), \ + F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), \ + FSR__, FSR__, FSR__, FSR__ + test_op3 madd.d, f0, f1, f2, f0, F64_1, F64_QNAN(2), F64_QNAN(3), \ + F64_QNAN(3), F64_QNAN(3), F64_QNAN(3), F64_QNAN(3), \ + FSR__, FSR__, FSR__, FSR__ + + test_op3 madd.d, f0, f1, f2, f0, F64_QNAN(1), F64_QNAN(2), F64_QNAN(3), \ + F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), \ + FSR__, FSR__, FSR__, FSR__ + + /* inf * 0 = default NaN */ + test_op3 madd.d, f0, f1, f2, f0, F64_1, F64_PINF, F64_0, \ + F64_DNAN, F64_DNAN, F64_DNAN, F64_DNAN, \ + FSR_V, FSR_V, FSR_V, FSR_V + /* inf * 0 + SNaN1 = QNaN1 */ + test_op3 madd.d, f0, f1, f2, f0, F64_SNAN(1), F64_PINF, F64_0, \ + F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), \ + FSR_V, FSR_V, FSR_V, FSR_V + /* inf * 0 + QNaN1 = QNaN1 */ + test_op3 madd.d, f0, f1, f2, f0, F64_QNAN(1), F64_PINF, F64_0, \ + F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), \ + FSR_V, FSR_V, FSR_V, FSR_V + + /* madd/msub SNaN turns to QNaN and sets Invalid flag */ + test_op3 madd.d, f0, f1, f2, f0, F64_SNAN(1), F64_1, F64_1, \ + F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), \ + FSR_V, FSR_V, FSR_V, FSR_V + test_op3 madd.d, f0, f1, f2, f0, F64_QNAN(1), F64_SNAN(2), F64_1, \ + F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), F64_QNAN(1), \ + FSR_V, FSR_V, FSR_V, FSR_V +test_end + +#endif + +test_suite_end diff --git a/tests/tcg/xtensa/test_fp0_arith.S b/tests/tcg/xtensa/test_fp0_arith.S index 253d033a33985d41b3fc8688395c373971509c84..7eefc1da409d4cc1db75038b11b4bae6142b5c0c 100644 --- a/tests/tcg/xtensa/test_fp0_arith.S +++ b/tests/tcg/xtensa/test_fp0_arith.S @@ -1,4 +1,5 @@ #include "macros.inc" +#include "fpu.h" test_suite fp0_arith @@ -9,84 +10,18 @@ test_suite fp0_arith wfr \fr, a2 .endm -.macro check_res fr, r +.macro check_res fr, r, sr rfr a2, \fr dump a2 movi a3, \r assert eq, a2, a3 rur a2, fsr - assert eqi, a2, 0 -.endm - -.macro test_op2_rm op, fr0, fr1, fr2, v0, v1, r - movi a2, 0 - wur a2, fsr - movfp \fr0, \v0 - movfp \fr1, \v1 - \op \fr2, \fr0, \fr1 - check_res \fr2, \r -.endm - -.macro test_op3_rm op, fr0, fr1, fr2, fr3, v0, v1, v2, r - movi a2, 0 - wur a2, fsr - movfp \fr0, \v0 - movfp \fr1, \v1 - movfp \fr2, \v2 - \op \fr0, \fr1, \fr2 - check_res \fr3, \r -.endm - -.macro test_op2_ex op, fr0, fr1, fr2, v0, v1, rm, r - movi a2, \rm - wur a2, fcr - test_op2_rm \op, \fr0, \fr1, \fr2, \v0, \v1, \r - movi a2, (\rm) | 0x7c - wur a2, fcr - test_op2_rm \op, \fr0, \fr1, \fr2, \v0, \v1, \r -.endm - -.macro test_op3_ex op, fr0, fr1, fr2, fr3, v0, v1, v2, rm, r - movi a2, \rm - wur a2, fcr - test_op3_rm \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, \r - movi a2, (\rm) | 0x7c - wur a2, fcr - test_op3_rm \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, \r -.endm - -.macro test_op2 op, fr0, fr1, fr2, v0, v1, r0, r1, r2, r3 - test_op2_ex \op, \fr0, \fr1, \fr2, \v0, \v1, 0, \r0 - test_op2_ex \op, \fr0, \fr1, \fr2, \v0, \v1, 1, \r1 - test_op2_ex \op, \fr0, \fr1, \fr2, \v0, \v1, 2, \r2 - test_op2_ex \op, \fr0, \fr1, \fr2, \v0, \v1, 3, \r3 -.endm - -.macro test_op3 op, fr0, fr1, fr2, fr3, v0, v1, v2, r0, r1, r2, r3 - test_op3_ex \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, 0, \r0 - test_op3_ex \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, 1, \r1 - test_op3_ex \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, 2, \r2 - test_op3_ex \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, 3, \r3 -.endm - -.macro test_op2_cpe op - set_vector kernel, 2f - movi a2, 0 - wsr a2, cpenable -1: - \op f2, f0, f1 - test_fail -2: - rsr a2, excvaddr - movi a3, 1b - assert eq, a2, a3 - rsr a2, exccause - movi a3, 32 +#if DFPU + movi a3, \sr assert eq, a2, a3 - - set_vector kernel, 0 - movi a2, 1 - wsr a2, cpenable +#else + assert eqi, a2, 0 +#endif .endm test add_s @@ -94,78 +29,231 @@ test add_s wsr a2, cpenable test_op2 add.s, f0, f1, f2, 0x3fc00000, 0x34400000, \ - 0x3fc00002, 0x3fc00001, 0x3fc00002, 0x3fc00001 + 0x3fc00002, 0x3fc00001, 0x3fc00002, 0x3fc00001, \ + FSR_I, FSR_I, FSR_I, FSR_I test_op2 add.s, f3, f4, f5, 0x3fc00000, 0x34a00000, \ - 0x3fc00002, 0x3fc00002, 0x3fc00003, 0x3fc00002 + 0x3fc00002, 0x3fc00002, 0x3fc00003, 0x3fc00002, \ + FSR_I, FSR_I, FSR_I, FSR_I /* MAX_FLOAT + MAX_FLOAT = +inf/MAX_FLOAT */ test_op2 add.s, f6, f7, f8, 0x7f7fffff, 0x7f7fffff, \ - 0x7f800000, 0x7f7fffff, 0x7f800000, 0x7f7fffff + 0x7f800000, 0x7f7fffff, 0x7f800000, 0x7f7fffff, \ + FSR_OI, FSR_OI, FSR_OI, FSR_OI test_end test add_s_inf /* 1 + +inf = +inf */ test_op2 add.s, f6, f7, f8, 0x3fc00000, 0x7f800000, \ - 0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000 + 0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000, \ + FSR__, FSR__, FSR__, FSR__ /* +inf + -inf = default NaN */ test_op2 add.s, f0, f1, f2, 0x7f800000, 0xff800000, \ - 0x7fc00000, 0x7fc00000, 0x7fc00000, 0x7fc00000 + 0x7fc00000, 0x7fc00000, 0x7fc00000, 0x7fc00000, \ + FSR_V, FSR_V, FSR_V, FSR_V test_end -test add_s_nan - /* 1 + NaN = NaN */ +#if DFPU +test add_s_nan_dfpu + /* 1 + QNaN = QNaN */ test_op2 add.s, f9, f10, f11, 0x3fc00000, 0x7fc00001, \ - 0x7fc00001, 0x7fc00001, 0x7fc00001, 0x7fc00001 + 0x7fc00001, 0x7fc00001, 0x7fc00001, 0x7fc00001, \ + FSR__, FSR__, FSR__, FSR__ + /* 1 + SNaN = QNaN */ test_op2 add.s, f12, f13, f14, 0x3fc00000, 0x7f800001, \ - 0x7f800001, 0x7f800001, 0x7f800001, 0x7f800001 + 0x7fc00001, 0x7fc00001, 0x7fc00001, 0x7fc00001, \ + FSR_V, FSR_V, FSR_V, FSR_V - /* NaN1 + NaN2 = NaN1 */ + /* SNaN1 + SNaN2 = QNaN2 */ + test_op2 add.s, f15, f0, f1, 0x7f800001, 0x7fbfffff, \ + 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, \ + FSR_V, FSR_V, FSR_V, FSR_V + test_op2 add.s, f2, f3, f4, 0x7fbfffff, 0x7f800001, \ + 0x7fc00001, 0x7fc00001, 0x7fc00001, 0x7fc00001, \ + FSR_V, FSR_V, FSR_V, FSR_V + /* QNaN1 + SNaN2 = QNaN2 */ + test_op2 add.s, f5, f6, f7, 0x7fc00001, 0x7fbfffff, \ + 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, \ + FSR_V, FSR_V, FSR_V, FSR_V + /* SNaN1 + QNaN2 = QNaN2 */ + test_op2 add.s, f8, f9, f10, 0x7fbfffff, 0x7fc00001, \ + 0x7fc00001, 0x7fc00001, 0x7fc00001, 0x7fc00001, \ + FSR_V, FSR_V, FSR_V, FSR_V +test_end +#else +test add_s_nan_fpu2k + /* 1 + QNaN = QNaN */ + test_op2 add.s, f9, f10, f11, 0x3fc00000, 0x7fc00001, \ + 0x7fc00001, 0x7fc00001, 0x7fc00001, 0x7fc00001, \ + FSR__, FSR__, FSR__, FSR__ + /* 1 + SNaN = SNaN */ + test_op2 add.s, f12, f13, f14, 0x3fc00000, 0x7f800001, \ + 0x7f800001, 0x7f800001, 0x7f800001, 0x7f800001, \ + FSR__, FSR__, FSR__, FSR__ + /* SNaN1 + SNaN2 = SNaN1 */ test_op2 add.s, f15, f0, f1, 0x7f800001, 0x7fbfffff, \ - 0x7f800001, 0x7f800001, 0x7f800001, 0x7f800001 + 0x7f800001, 0x7f800001, 0x7f800001, 0x7f800001, \ + FSR__, FSR__, FSR__, FSR__ test_op2 add.s, f2, f3, f4, 0x7fbfffff, 0x7f800001, \ - 0x7fbfffff, 0x7fbfffff, 0x7fbfffff, 0x7fbfffff + 0x7fbfffff, 0x7fbfffff, 0x7fbfffff, 0x7fbfffff, \ + FSR__, FSR__, FSR__, FSR__ + /* QNaN1 + SNaN2 = QNaN1 */ test_op2 add.s, f5, f6, f7, 0x7fc00001, 0x7fbfffff, \ - 0x7fc00001, 0x7fc00001, 0x7fc00001, 0x7fc00001 + 0x7fc00001, 0x7fc00001, 0x7fc00001, 0x7fc00001, \ + FSR__, FSR__, FSR__, FSR__ + /* SNaN1 + QNaN2 = SNaN1 */ test_op2 add.s, f8, f9, f10, 0x7fbfffff, 0x7fc00001, \ - 0x7fbfffff, 0x7fbfffff, 0x7fbfffff, 0x7fbfffff + 0x7fbfffff, 0x7fbfffff, 0x7fbfffff, 0x7fbfffff, \ + FSR__, FSR__, FSR__, FSR__ test_end +#endif test sub_s test_op2 sub.s, f0, f1, f0, 0x3f800001, 0x33800000, \ - 0x3f800000, 0x3f800000, 0x3f800001, 0x3f800000 + 0x3f800000, 0x3f800000, 0x3f800001, 0x3f800000, \ + FSR_I, FSR_I, FSR_I, FSR_I test_op2 sub.s, f0, f1, f1, 0x3f800002, 0x33800000, \ - 0x3f800002, 0x3f800001, 0x3f800002, 0x3f800001 + 0x3f800002, 0x3f800001, 0x3f800002, 0x3f800001, \ + FSR_I, FSR_I, FSR_I, FSR_I /* norm - norm = denorm */ test_op2 sub.s, f6, f7, f8, 0x00800001, 0x00800000, \ - 0x00000001, 0x00000001, 0x00000001, 0x00000001 + 0x00000001, 0x00000001, 0x00000001, 0x00000001, \ + FSR__, FSR__, FSR__, FSR__ test_end test mul_s test_op2 mul.s, f0, f1, f2, 0x3f800001, 0x3f800001, \ - 0x3f800002, 0x3f800002, 0x3f800003, 0x3f800002 - + 0x3f800002, 0x3f800002, 0x3f800003, 0x3f800002, \ + FSR_I, FSR_I, FSR_I, FSR_I /* MAX_FLOAT/2 * MAX_FLOAT/2 = +inf/MAX_FLOAT */ test_op2 mul.s, f6, f7, f8, 0x7f000000, 0x7f000000, \ - 0x7f800000, 0x7f7fffff, 0x7f800000, 0x7f7fffff + 0x7f800000, 0x7f7fffff, 0x7f800000, 0x7f7fffff, \ + FSR_OI, FSR_OI, FSR_OI, FSR_OI /* min norm * min norm = 0/denorm */ test_op2 mul.s, f6, f7, f8, 0x00800001, 0x00800000, \ - 0x00000000, 0x00000000, 0x00000001, 0x00000000 - + 0x00000000, 0x00000000, 0x00000001, 0x00000000, \ + FSR_UI, FSR_UI, FSR_UI, FSR_UI /* inf * 0 = default NaN */ test_op2 mul.s, f6, f7, f8, 0x7f800000, 0x00000000, \ - 0x7fc00000, 0x7fc00000, 0x7fc00000, 0x7fc00000 + 0x7fc00000, 0x7fc00000, 0x7fc00000, 0x7fc00000, \ + FSR_V, FSR_V, FSR_V, FSR_V test_end test madd_s test_op3 madd.s, f0, f1, f2, f0, 0, 0x3f800001, 0x3f800001, \ - 0x3f800002, 0x3f800002, 0x3f800003, 0x3f800002 + 0x3f800002, 0x3f800002, 0x3f800003, 0x3f800002, \ + FSR_I, FSR_I, FSR_I, FSR_I +test_end + +test madd_s_precision + test_op3 madd.s, f0, f1, f2, f0, 0xbf800002, 0x3f800001, 0x3f800001, \ + 0x28800000, 0x28800000, 0x28800000, 0x28800000, \ + FSR__, FSR__, FSR__, FSR__ +test_end + +#if DFPU +test madd_s_nan_dfpu + /* DFPU madd/msub NaN1, NaN2, NaN3 priority: NaN1, NaN3, NaN2 */ + test_op3 madd.s, f0, f1, f2, f0, F32_QNAN(1), F32_1, F32_1, \ + F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), \ + FSR__, FSR__, FSR__, FSR__ + test_op3 madd.s, f0, f1, f2, f0, F32_1, F32_QNAN(2), F32_1, \ + F32_QNAN(2), F32_QNAN(2), F32_QNAN(2), F32_QNAN(2), \ + FSR__, FSR__, FSR__, FSR__ + test_op3 madd.s, f0, f1, f2, f0, F32_1, F32_1, F32_QNAN(3), \ + F32_QNAN(3), F32_QNAN(3), F32_QNAN(3), F32_QNAN(3), \ + FSR__, FSR__, FSR__, FSR__ + + test_op3 madd.s, f0, f1, f2, f0, F32_QNAN(1), F32_QNAN(2), F32_1, \ + F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), \ + FSR__, FSR__, FSR__, FSR__ + test_op3 madd.s, f0, f1, f2, f0, F32_QNAN(1), F32_1, F32_QNAN(3), \ + F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), \ + FSR__, FSR__, FSR__, FSR__ + test_op3 madd.s, f0, f1, f2, f0, F32_1, F32_QNAN(2), F32_QNAN(3), \ + F32_QNAN(3), F32_QNAN(3), F32_QNAN(3), F32_QNAN(3), \ + FSR__, FSR__, FSR__, FSR__ + + test_op3 madd.s, f0, f1, f2, f0, F32_QNAN(1), F32_QNAN(2), F32_QNAN(3), \ + F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), \ + FSR__, FSR__, FSR__, FSR__ + + /* inf * 0 = default NaN */ + test_op3 madd.s, f0, f1, f2, f0, F32_1, F32_PINF, F32_0, \ + F32_DNAN, F32_DNAN, F32_DNAN, F32_DNAN, \ + FSR_V, FSR_V, FSR_V, FSR_V + /* inf * 0 + SNaN1 = QNaN1 */ + test_op3 madd.s, f0, f1, f2, f0, F32_SNAN(1), F32_PINF, F32_0, \ + F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), \ + FSR_V, FSR_V, FSR_V, FSR_V + /* inf * 0 + QNaN1 = QNaN1 */ + test_op3 madd.s, f0, f1, f2, f0, F32_QNAN(1), F32_PINF, F32_0, \ + F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), \ + FSR_V, FSR_V, FSR_V, FSR_V + + /* madd/msub SNaN turns to QNaN and sets Invalid flag */ + test_op3 madd.s, f0, f1, f2, f0, F32_SNAN(1), F32_1, F32_1, \ + F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), \ + FSR_V, FSR_V, FSR_V, FSR_V + test_op3 madd.s, f0, f1, f2, f0, F32_QNAN(1), F32_SNAN(2), F32_1, \ + F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), \ + FSR_V, FSR_V, FSR_V, FSR_V +test_end +#else +test madd_s_nan_fpu2k + /* FPU2000 madd/msub NaN1, NaN2, NaN3 priority: NaN2, NaN3, NaN1 */ + test_op3 madd.s, f0, f1, f2, f0, F32_QNAN(1), F32_1, F32_1, \ + F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), \ + FSR__, FSR__, FSR__, FSR__ + test_op3 madd.s, f0, f1, f2, f0, F32_1, F32_QNAN(2), F32_1, \ + F32_QNAN(2), F32_QNAN(2), F32_QNAN(2), F32_QNAN(2), \ + FSR__, FSR__, FSR__, FSR__ + test_op3 madd.s, f0, f1, f2, f0, F32_1, F32_1, F32_QNAN(3), \ + F32_QNAN(3), F32_QNAN(3), F32_QNAN(3), F32_QNAN(3), \ + FSR__, FSR__, FSR__, FSR__ + + test_op3 madd.s, f0, f1, f2, f0, F32_QNAN(1), F32_QNAN(2), F32_1, \ + F32_QNAN(2), F32_QNAN(2), F32_QNAN(2), F32_QNAN(2), \ + FSR__, FSR__, FSR__, FSR__ + test_op3 madd.s, f0, f1, f2, f0, F32_QNAN(1), F32_1, F32_QNAN(3), \ + F32_QNAN(3), F32_QNAN(3), F32_QNAN(3), F32_QNAN(3), \ + FSR__, FSR__, FSR__, FSR__ + test_op3 madd.s, f0, f1, f2, f0, F32_1, F32_QNAN(2), F32_QNAN(3), \ + F32_QNAN(2), F32_QNAN(2), F32_QNAN(2), F32_QNAN(2), \ + FSR__, FSR__, FSR__, FSR__ + + test_op3 madd.s, f0, f1, f2, f0, F32_QNAN(1), F32_QNAN(2), F32_QNAN(3), \ + F32_QNAN(2), F32_QNAN(2), F32_QNAN(2), F32_QNAN(2), \ + FSR__, FSR__, FSR__, FSR__ + + /* inf * 0 = default NaN */ + test_op3 madd.s, f0, f1, f2, f0, F32_1, F32_PINF, F32_0, \ + F32_DNAN, F32_DNAN, F32_DNAN, F32_DNAN, \ + FSR__, FSR__, FSR__, FSR__ + /* inf * 0 + SNaN1 = SNaN1 */ + test_op3 madd.s, f0, f1, f2, f0, F32_SNAN(1), F32_PINF, F32_0, \ + F32_SNAN(1), F32_SNAN(1), F32_SNAN(1), F32_SNAN(1), \ + FSR__, FSR__, FSR__, FSR__ + /* inf * 0 + QNaN1 = QNaN1 */ + test_op3 madd.s, f0, f1, f2, f0, F32_QNAN(1), F32_PINF, F32_0, \ + F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), F32_QNAN(1), \ + FSR__, FSR__, FSR__, FSR__ + + /* madd/msub SNaN is preserved */ + test_op3 madd.s, f0, f1, f2, f0, F32_SNAN(1), F32_1, F32_1, \ + F32_SNAN(1), F32_SNAN(1), F32_SNAN(1), F32_SNAN(1), \ + FSR__, FSR__, FSR__, FSR__ + test_op3 madd.s, f0, f1, f2, f0, F32_QNAN(1), F32_SNAN(2), F32_1, \ + F32_SNAN(2), F32_SNAN(2), F32_SNAN(2), F32_SNAN(2), \ + FSR__, FSR__, FSR__, FSR__ test_end +#endif test msub_s test_op3 msub.s, f0, f1, f2, f0, 0x3f800000, 0x3f800001, 0x3f800001, \ - 0xb4800000, 0xb4800000, 0xb4800000, 0xb4800001 + 0xb4800000, 0xb4800000, 0xb4800000, 0xb4800001, \ + FSR_I, FSR_I, FSR_I, FSR_I test_end #endif diff --git a/tests/tcg/xtensa/test_fp0_conv.S b/tests/tcg/xtensa/test_fp0_conv.S index 147e3d5062df3dcc4524f27cbc2d042ba229bcf8..cfee6e51790cec6f2eda2061d049c23a1412ebb3 100644 --- a/tests/tcg/xtensa/test_fp0_conv.S +++ b/tests/tcg/xtensa/test_fp0_conv.S @@ -1,4 +1,5 @@ #include "macros.inc" +#include "fpu.h" test_suite fp0_conv @@ -9,7 +10,7 @@ test_suite fp0_conv wfr \fr, a2 .endm -.macro test_ftoi_ex op, r0, fr0, v, c, r +.macro test_ftoi_ex op, r0, fr0, v, c, r, sr movi a2, 0 wur a2, fsr movfp \fr0, \v @@ -18,20 +19,25 @@ test_suite fp0_conv movi a3, \r assert eq, \r0, a3 rur a2, fsr +#if DFPU + movi a3, \sr + assert eq, a2, a3 +#else assert eqi, a2, 0 +#endif .endm -.macro test_ftoi op, r0, fr0, v, c, r +.macro test_ftoi op, r0, fr0, v, c, r, sr movi a2, 0 wur a2, fcr - test_ftoi_ex \op, \r0, \fr0, \v, \c, \r + test_ftoi_ex \op, \r0, \fr0, \v, \c, \r, \sr movi a2, 0x7c wur a2, fcr - test_ftoi_ex \op, \r0, \fr0, \v, \c, \r + test_ftoi_ex \op, \r0, \fr0, \v, \c, \r, \sr .endm -.macro test_itof_ex op, fr0, ar0, v, c, r +.macro test_itof_ex op, fr0, ar0, v, c, r, sr movi a2, 0 wur a2, fsr movi \ar0, \v @@ -42,23 +48,28 @@ test_suite fp0_conv movi a3, \r assert eq, a2, a3 rur a2, fsr +#if DFPU + movi a3, \sr + assert eq, a2, a3 +#else assert eqi, a2, 0 +#endif .endm -.macro test_itof_rm op, fr0, ar0, v, c, rm, r +.macro test_itof_rm op, fr0, ar0, v, c, rm, r, sr movi a2, \rm wur a2, fcr - test_itof_ex \op, \fr0, \ar0, \v, \c, \r + test_itof_ex \op, \fr0, \ar0, \v, \c, \r, \sr movi a2, (\rm) | 0x7c wur a2, fcr - test_itof_ex \op, \fr0, \ar0, \v, \c, \r + test_itof_ex \op, \fr0, \ar0, \v, \c, \r, \sr .endm -.macro test_itof op, fr0, ar0, v, c, r0, r1, r2, r3 - test_itof_rm \op, \fr0, \ar0, \v, \c, 0, \r0 - test_itof_rm \op, \fr0, \ar0, \v, \c, 1, \r1 - test_itof_rm \op, \fr0, \ar0, \v, \c, 2, \r2 - test_itof_rm \op, \fr0, \ar0, \v, \c, 3, \r3 +.macro test_itof op, fr0, ar0, v, c, r0, r1, r2, r3, sr + test_itof_rm \op, \fr0, \ar0, \v, \c, 0, \r0, \sr + test_itof_rm \op, \fr0, \ar0, \v, \c, 1, \r1, \sr + test_itof_rm \op, \fr0, \ar0, \v, \c, 2, \r2, \sr + test_itof_rm \op, \fr0, \ar0, \v, \c, 3, \r3, \sr .endm test round_s @@ -66,237 +77,237 @@ test round_s wsr a2, cpenable /* NaN */ - test_ftoi round.s, a2, f0, 0xffc00001, 0, 0x7fffffff - test_ftoi round.s, a2, f0, 0xff800001, 0, 0x7fffffff + test_ftoi round.s, a2, f0, 0xffc00001, 0, 0x7fffffff, FSR_V + test_ftoi round.s, a2, f0, 0xff800001, 0, 0x7fffffff, FSR_V /* -inf */ - test_ftoi round.s, a2, f0, 0xff800000, 0, 0x80000000 + test_ftoi round.s, a2, f0, 0xff800000, 0, 0x80000000, FSR_V /* negative overflow */ - test_ftoi round.s, a2, f0, 0xceffffff, 1, 0x80000000 - test_ftoi round.s, a2, f0, 0xcf000000, 0, 0x80000000 - test_ftoi round.s, a2, f0, 0xceffffff, 0, 0x80000080 + test_ftoi round.s, a2, f0, 0xceffffff, 1, 0x80000000, FSR_V + test_ftoi round.s, a2, f0, 0xcf000000, 0, 0x80000000, FSR__ + test_ftoi round.s, a2, f0, 0xceffffff, 0, 0x80000080, FSR__ /* negative */ - test_ftoi round.s, a2, f0, 0xbfa00000, 1, -2 /* -1.25 * 2 */ - test_ftoi round.s, a2, f0, 0xbfc00000, 0, -2 /* -1.5 */ - test_ftoi round.s, a2, f0, 0xbf800000, 1, -2 /* -1 * 2 */ - test_ftoi round.s, a2, f0, 0xbf800000, 0, -1 /* -1 */ - test_ftoi round.s, a2, f0, 0xbf400000, 0, -1 /* -0.75 */ - test_ftoi round.s, a2, f0, 0xbf000000, 0, 0 /* -0.5 */ + test_ftoi round.s, a2, f0, 0xbfa00000, 1, -2, FSR_I /* -1.25 * 2 */ + test_ftoi round.s, a2, f0, 0xbfc00000, 0, -2, FSR_I /* -1.5 */ + test_ftoi round.s, a2, f0, 0xbf800000, 1, -2, FSR__ /* -1 * 2 */ + test_ftoi round.s, a2, f0, 0xbf800000, 0, -1, FSR__ /* -1 */ + test_ftoi round.s, a2, f0, 0xbf400000, 0, -1, FSR_I /* -0.75 */ + test_ftoi round.s, a2, f0, 0xbf000000, 0, 0, FSR_I /* -0.5 */ /* positive */ - test_ftoi round.s, a2, f0, 0x3f000000, 0, 0 /* 0.5 */ - test_ftoi round.s, a2, f0, 0x3f400000, 0, 1 /* 0.75 */ - test_ftoi round.s, a2, f0, 0x3f800000, 0, 1 /* 1 */ - test_ftoi round.s, a2, f0, 0x3f800000, 1, 2 /* 1 * 2 */ - test_ftoi round.s, a2, f0, 0x3fc00000, 0, 2 /* 1.5 */ - test_ftoi round.s, a2, f0, 0x3fa00000, 1, 2 /* 1.25 * 2 */ + test_ftoi round.s, a2, f0, 0x3f000000, 0, 0, FSR_I /* 0.5 */ + test_ftoi round.s, a2, f0, 0x3f400000, 0, 1, FSR_I /* 0.75 */ + test_ftoi round.s, a2, f0, 0x3f800000, 0, 1, FSR__ /* 1 */ + test_ftoi round.s, a2, f0, 0x3f800000, 1, 2, FSR__ /* 1 * 2 */ + test_ftoi round.s, a2, f0, 0x3fc00000, 0, 2, FSR_I /* 1.5 */ + test_ftoi round.s, a2, f0, 0x3fa00000, 1, 2, FSR_I /* 1.25 * 2 */ /* positive overflow */ - test_ftoi round.s, a2, f0, 0x4effffff, 0, 0x7fffff80 - test_ftoi round.s, a2, f0, 0x4f000000, 0, 0x7fffffff - test_ftoi round.s, a2, f0, 0x4effffff, 1, 0x7fffffff + test_ftoi round.s, a2, f0, 0x4effffff, 0, 0x7fffff80, FSR__ + test_ftoi round.s, a2, f0, 0x4f000000, 0, 0x7fffffff, FSR_V + test_ftoi round.s, a2, f0, 0x4effffff, 1, 0x7fffffff, FSR_V /* +inf */ - test_ftoi round.s, a2, f0, 0x7f800000, 0, 0x7fffffff + test_ftoi round.s, a2, f0, 0x7f800000, 0, 0x7fffffff, FSR_V /* NaN */ - test_ftoi round.s, a2, f0, 0x7f800001, 0, 0x7fffffff - test_ftoi round.s, a2, f0, 0x7fc00000, 0, 0x7fffffff + test_ftoi round.s, a2, f0, 0x7f800001, 0, 0x7fffffff, FSR_V + test_ftoi round.s, a2, f0, 0x7fc00000, 0, 0x7fffffff, FSR_V test_end test trunc_s /* NaN */ - test_ftoi trunc.s, a2, f0, 0xffc00001, 0, 0x7fffffff - test_ftoi trunc.s, a2, f0, 0xff800001, 0, 0x7fffffff + test_ftoi trunc.s, a2, f0, 0xffc00001, 0, 0x7fffffff, FSR_V + test_ftoi trunc.s, a2, f0, 0xff800001, 0, 0x7fffffff, FSR_V /* -inf */ - test_ftoi trunc.s, a2, f0, 0xff800000, 0, 0x80000000 + test_ftoi trunc.s, a2, f0, 0xff800000, 0, 0x80000000, FSR_V /* negative overflow */ - test_ftoi trunc.s, a2, f0, 0xceffffff, 1, 0x80000000 - test_ftoi trunc.s, a2, f0, 0xcf000000, 0, 0x80000000 - test_ftoi trunc.s, a2, f0, 0xceffffff, 0, 0x80000080 + test_ftoi trunc.s, a2, f0, 0xceffffff, 1, 0x80000000, FSR_V + test_ftoi trunc.s, a2, f0, 0xcf000000, 0, 0x80000000, FSR__ + test_ftoi trunc.s, a2, f0, 0xceffffff, 0, 0x80000080, FSR__ /* negative */ - test_ftoi trunc.s, a2, f0, 0xbfa00000, 1, -2 /* -1.25 * 2 */ - test_ftoi trunc.s, a2, f0, 0xbfc00000, 0, -1 /* -1.5 */ - test_ftoi trunc.s, a2, f0, 0xbf800000, 1, -2 /* -1 * 2 */ - test_ftoi trunc.s, a2, f0, 0xbf800000, 0, -1 /* -1 */ - test_ftoi trunc.s, a2, f0, 0xbf400000, 0, 0 /* -0.75 */ - test_ftoi trunc.s, a2, f0, 0xbf000000, 0, 0 /* -0.5 */ + test_ftoi trunc.s, a2, f0, 0xbfa00000, 1, -2, FSR_I /* -1.25 * 2 */ + test_ftoi trunc.s, a2, f0, 0xbfc00000, 0, -1, FSR_I /* -1.5 */ + test_ftoi trunc.s, a2, f0, 0xbf800000, 1, -2, FSR__ /* -1 * 2 */ + test_ftoi trunc.s, a2, f0, 0xbf800000, 0, -1, FSR__ /* -1 */ + test_ftoi trunc.s, a2, f0, 0xbf400000, 0, 0, FSR_I /* -0.75 */ + test_ftoi trunc.s, a2, f0, 0xbf000000, 0, 0, FSR_I /* -0.5 */ /* positive */ - test_ftoi trunc.s, a2, f0, 0x3f000000, 0, 0 /* 0.5 */ - test_ftoi trunc.s, a2, f0, 0x3f400000, 0, 0 /* 0.75 */ - test_ftoi trunc.s, a2, f0, 0x3f800000, 0, 1 /* 1 */ - test_ftoi trunc.s, a2, f0, 0x3f800000, 1, 2 /* 1 * 2 */ - test_ftoi trunc.s, a2, f0, 0x3fc00000, 0, 1 /* 1.5 */ - test_ftoi trunc.s, a2, f0, 0x3fa00000, 1, 2 /* 1.25 * 2 */ + test_ftoi trunc.s, a2, f0, 0x3f000000, 0, 0, FSR_I /* 0.5 */ + test_ftoi trunc.s, a2, f0, 0x3f400000, 0, 0, FSR_I /* 0.75 */ + test_ftoi trunc.s, a2, f0, 0x3f800000, 0, 1, FSR__ /* 1 */ + test_ftoi trunc.s, a2, f0, 0x3f800000, 1, 2, FSR__ /* 1 * 2 */ + test_ftoi trunc.s, a2, f0, 0x3fc00000, 0, 1, FSR_I /* 1.5 */ + test_ftoi trunc.s, a2, f0, 0x3fa00000, 1, 2, FSR_I /* 1.25 * 2 */ /* positive overflow */ - test_ftoi trunc.s, a2, f0, 0x4effffff, 0, 0x7fffff80 - test_ftoi trunc.s, a2, f0, 0x4f000000, 0, 0x7fffffff - test_ftoi trunc.s, a2, f0, 0x4effffff, 1, 0x7fffffff + test_ftoi trunc.s, a2, f0, 0x4effffff, 0, 0x7fffff80, FSR__ + test_ftoi trunc.s, a2, f0, 0x4f000000, 0, 0x7fffffff, FSR_V + test_ftoi trunc.s, a2, f0, 0x4effffff, 1, 0x7fffffff, FSR_V /* +inf */ - test_ftoi trunc.s, a2, f0, 0x7f800000, 0, 0x7fffffff + test_ftoi trunc.s, a2, f0, 0x7f800000, 0, 0x7fffffff, FSR_V /* NaN */ - test_ftoi trunc.s, a2, f0, 0x7f800001, 0, 0x7fffffff - test_ftoi trunc.s, a2, f0, 0x7fc00000, 0, 0x7fffffff + test_ftoi trunc.s, a2, f0, 0x7f800001, 0, 0x7fffffff, FSR_V + test_ftoi trunc.s, a2, f0, 0x7fc00000, 0, 0x7fffffff, FSR_V test_end test floor_s /* NaN */ - test_ftoi floor.s, a2, f0, 0xffc00001, 0, 0x7fffffff - test_ftoi floor.s, a2, f0, 0xff800001, 0, 0x7fffffff + test_ftoi floor.s, a2, f0, 0xffc00001, 0, 0x7fffffff, FSR_V + test_ftoi floor.s, a2, f0, 0xff800001, 0, 0x7fffffff, FSR_V /* -inf */ - test_ftoi floor.s, a2, f0, 0xff800000, 0, 0x80000000 + test_ftoi floor.s, a2, f0, 0xff800000, 0, 0x80000000, FSR_V /* negative overflow */ - test_ftoi floor.s, a2, f0, 0xceffffff, 1, 0x80000000 - test_ftoi floor.s, a2, f0, 0xcf000000, 0, 0x80000000 - test_ftoi floor.s, a2, f0, 0xceffffff, 0, 0x80000080 + test_ftoi floor.s, a2, f0, 0xceffffff, 1, 0x80000000, FSR_V + test_ftoi floor.s, a2, f0, 0xcf000000, 0, 0x80000000, FSR__ + test_ftoi floor.s, a2, f0, 0xceffffff, 0, 0x80000080, FSR__ /* negative */ - test_ftoi floor.s, a2, f0, 0xbfa00000, 1, -3 /* -1.25 * 2 */ - test_ftoi floor.s, a2, f0, 0xbfc00000, 0, -2 /* -1.5 */ - test_ftoi floor.s, a2, f0, 0xbf800000, 1, -2 /* -1 * 2 */ - test_ftoi floor.s, a2, f0, 0xbf800000, 0, -1 /* -1 */ - test_ftoi floor.s, a2, f0, 0xbf400000, 0, -1 /* -0.75 */ - test_ftoi floor.s, a2, f0, 0xbf000000, 0, -1 /* -0.5 */ + test_ftoi floor.s, a2, f0, 0xbfa00000, 1, -3, FSR_I /* -1.25 * 2 */ + test_ftoi floor.s, a2, f0, 0xbfc00000, 0, -2, FSR_I /* -1.5 */ + test_ftoi floor.s, a2, f0, 0xbf800000, 1, -2, FSR__ /* -1 * 2 */ + test_ftoi floor.s, a2, f0, 0xbf800000, 0, -1, FSR__ /* -1 */ + test_ftoi floor.s, a2, f0, 0xbf400000, 0, -1, FSR_I /* -0.75 */ + test_ftoi floor.s, a2, f0, 0xbf000000, 0, -1, FSR_I /* -0.5 */ /* positive */ - test_ftoi floor.s, a2, f0, 0x3f000000, 0, 0 /* 0.5 */ - test_ftoi floor.s, a2, f0, 0x3f400000, 0, 0 /* 0.75 */ - test_ftoi floor.s, a2, f0, 0x3f800000, 0, 1 /* 1 */ - test_ftoi floor.s, a2, f0, 0x3f800000, 1, 2 /* 1 * 2 */ - test_ftoi floor.s, a2, f0, 0x3fc00000, 0, 1 /* 1.5 */ - test_ftoi floor.s, a2, f0, 0x3fa00000, 1, 2 /* 1.25 * 2 */ + test_ftoi floor.s, a2, f0, 0x3f000000, 0, 0, FSR_I /* 0.5 */ + test_ftoi floor.s, a2, f0, 0x3f400000, 0, 0, FSR_I /* 0.75 */ + test_ftoi floor.s, a2, f0, 0x3f800000, 0, 1, FSR__ /* 1 */ + test_ftoi floor.s, a2, f0, 0x3f800000, 1, 2, FSR__ /* 1 * 2 */ + test_ftoi floor.s, a2, f0, 0x3fc00000, 0, 1, FSR_I /* 1.5 */ + test_ftoi floor.s, a2, f0, 0x3fa00000, 1, 2, FSR_I /* 1.25 * 2 */ /* positive overflow */ - test_ftoi floor.s, a2, f0, 0x4effffff, 0, 0x7fffff80 - test_ftoi floor.s, a2, f0, 0x4f000000, 0, 0x7fffffff - test_ftoi floor.s, a2, f0, 0x4effffff, 1, 0x7fffffff + test_ftoi floor.s, a2, f0, 0x4effffff, 0, 0x7fffff80, FSR__ + test_ftoi floor.s, a2, f0, 0x4f000000, 0, 0x7fffffff, FSR_V + test_ftoi floor.s, a2, f0, 0x4effffff, 1, 0x7fffffff, FSR_V /* +inf */ - test_ftoi floor.s, a2, f0, 0x7f800000, 0, 0x7fffffff + test_ftoi floor.s, a2, f0, 0x7f800000, 0, 0x7fffffff, FSR_V /* NaN */ - test_ftoi floor.s, a2, f0, 0x7f800001, 0, 0x7fffffff - test_ftoi floor.s, a2, f0, 0x7fc00000, 0, 0x7fffffff + test_ftoi floor.s, a2, f0, 0x7f800001, 0, 0x7fffffff, FSR_V + test_ftoi floor.s, a2, f0, 0x7fc00000, 0, 0x7fffffff, FSR_V test_end test ceil_s /* NaN */ - test_ftoi ceil.s, a2, f0, 0xffc00001, 0, 0x7fffffff - test_ftoi ceil.s, a2, f0, 0xff800001, 0, 0x7fffffff + test_ftoi ceil.s, a2, f0, 0xffc00001, 0, 0x7fffffff, FSR_V + test_ftoi ceil.s, a2, f0, 0xff800001, 0, 0x7fffffff, FSR_V /* -inf */ - test_ftoi ceil.s, a2, f0, 0xff800000, 0, 0x80000000 + test_ftoi ceil.s, a2, f0, 0xff800000, 0, 0x80000000, FSR_V /* negative overflow */ - test_ftoi ceil.s, a2, f0, 0xceffffff, 1, 0x80000000 - test_ftoi ceil.s, a2, f0, 0xcf000000, 0, 0x80000000 - test_ftoi ceil.s, a2, f0, 0xceffffff, 0, 0x80000080 + test_ftoi ceil.s, a2, f0, 0xceffffff, 1, 0x80000000, FSR_V + test_ftoi ceil.s, a2, f0, 0xcf000000, 0, 0x80000000, FSR__ + test_ftoi ceil.s, a2, f0, 0xceffffff, 0, 0x80000080, FSR__ /* negative */ - test_ftoi ceil.s, a2, f0, 0xbfa00000, 1, -2 /* -1.25 * 2 */ - test_ftoi ceil.s, a2, f0, 0xbfc00000, 0, -1 /* -1.5 */ - test_ftoi ceil.s, a2, f0, 0xbf800000, 1, -2 /* -1 * 2 */ - test_ftoi ceil.s, a2, f0, 0xbf800000, 0, -1 /* -1 */ - test_ftoi ceil.s, a2, f0, 0xbf400000, 0, 0 /* -0.75 */ - test_ftoi ceil.s, a2, f0, 0xbf000000, 0, 0 /* -0.5 */ + test_ftoi ceil.s, a2, f0, 0xbfa00000, 1, -2, FSR_I /* -1.25 * 2 */ + test_ftoi ceil.s, a2, f0, 0xbfc00000, 0, -1, FSR_I /* -1.5 */ + test_ftoi ceil.s, a2, f0, 0xbf800000, 1, -2, FSR__ /* -1 * 2 */ + test_ftoi ceil.s, a2, f0, 0xbf800000, 0, -1, FSR__ /* -1 */ + test_ftoi ceil.s, a2, f0, 0xbf400000, 0, 0, FSR_I /* -0.75 */ + test_ftoi ceil.s, a2, f0, 0xbf000000, 0, 0, FSR_I /* -0.5 */ /* positive */ - test_ftoi ceil.s, a2, f0, 0x3f000000, 0, 1 /* 0.5 */ - test_ftoi ceil.s, a2, f0, 0x3f400000, 0, 1 /* 0.75 */ - test_ftoi ceil.s, a2, f0, 0x3f800000, 0, 1 /* 1 */ - test_ftoi ceil.s, a2, f0, 0x3f800000, 1, 2 /* 1 * 2 */ - test_ftoi ceil.s, a2, f0, 0x3fc00000, 0, 2 /* 1.5 */ - test_ftoi ceil.s, a2, f0, 0x3fa00000, 1, 3 /* 1.25 * 2 */ + test_ftoi ceil.s, a2, f0, 0x3f000000, 0, 1, FSR_I /* 0.5 */ + test_ftoi ceil.s, a2, f0, 0x3f400000, 0, 1, FSR_I /* 0.75 */ + test_ftoi ceil.s, a2, f0, 0x3f800000, 0, 1, FSR__ /* 1 */ + test_ftoi ceil.s, a2, f0, 0x3f800000, 1, 2, FSR__ /* 1 * 2 */ + test_ftoi ceil.s, a2, f0, 0x3fc00000, 0, 2, FSR_I /* 1.5 */ + test_ftoi ceil.s, a2, f0, 0x3fa00000, 1, 3, FSR_I /* 1.25 * 2 */ /* positive overflow */ - test_ftoi ceil.s, a2, f0, 0x4effffff, 0, 0x7fffff80 - test_ftoi ceil.s, a2, f0, 0x4f000000, 0, 0x7fffffff - test_ftoi ceil.s, a2, f0, 0x4effffff, 1, 0x7fffffff + test_ftoi ceil.s, a2, f0, 0x4effffff, 0, 0x7fffff80, FSR__ + test_ftoi ceil.s, a2, f0, 0x4f000000, 0, 0x7fffffff, FSR_V + test_ftoi ceil.s, a2, f0, 0x4effffff, 1, 0x7fffffff, FSR_V /* +inf */ - test_ftoi ceil.s, a2, f0, 0x7f800000, 0, 0x7fffffff + test_ftoi ceil.s, a2, f0, 0x7f800000, 0, 0x7fffffff, FSR_V /* NaN */ - test_ftoi ceil.s, a2, f0, 0x7f800001, 0, 0x7fffffff - test_ftoi ceil.s, a2, f0, 0x7fc00000, 0, 0x7fffffff + test_ftoi ceil.s, a2, f0, 0x7f800001, 0, 0x7fffffff, FSR_V + test_ftoi ceil.s, a2, f0, 0x7fc00000, 0, 0x7fffffff, FSR_V test_end test utrunc_s /* NaN */ - test_ftoi utrunc.s, a2, f0, 0xffc00001, 0, 0xffffffff - test_ftoi utrunc.s, a2, f0, 0xff800001, 0, 0xffffffff + test_ftoi utrunc.s, a2, f0, 0xffc00001, 0, 0xffffffff, FSR_V + test_ftoi utrunc.s, a2, f0, 0xff800001, 0, 0xffffffff, FSR_V /* -inf */ - test_ftoi utrunc.s, a2, f0, 0xff800000, 0, 0x80000000 + test_ftoi utrunc.s, a2, f0, 0xff800000, 0, 0x80000000, FSR_V /* negative overflow */ - test_ftoi utrunc.s, a2, f0, 0xceffffff, 1, 0x80000000 - test_ftoi utrunc.s, a2, f0, 0xcf000000, 0, 0x80000000 - test_ftoi utrunc.s, a2, f0, 0xceffffff, 0, 0x80000080 + test_ftoi utrunc.s, a2, f0, 0xceffffff, 1, 0x80000000, FSR_V + test_ftoi utrunc.s, a2, f0, 0xcf000000, 0, 0x80000000, FSR_V + test_ftoi utrunc.s, a2, f0, 0xceffffff, 0, 0x80000080, FSR_V /* negative */ - test_ftoi utrunc.s, a2, f0, 0xbfa00000, 1, -2 /* -1.25 * 2 */ - test_ftoi utrunc.s, a2, f0, 0xbfc00000, 0, -1 /* -1.5 */ - test_ftoi utrunc.s, a2, f0, 0xbf800000, 1, -2 /* -1 * 2 */ - test_ftoi utrunc.s, a2, f0, 0xbf800000, 0, -1 /* -1 */ - test_ftoi utrunc.s, a2, f0, 0xbf400000, 0, 0 /* -0.75 */ - test_ftoi utrunc.s, a2, f0, 0xbf000000, 0, 0 /* -0.5 */ + test_ftoi utrunc.s, a2, f0, 0xbfa00000, 1, -2, FSR_V /* -1.25 * 2 */ + test_ftoi utrunc.s, a2, f0, 0xbfc00000, 0, -1, FSR_V /* -1.5 */ + test_ftoi utrunc.s, a2, f0, 0xbf800000, 1, -2, FSR_V /* -1 * 2 */ + test_ftoi utrunc.s, a2, f0, 0xbf800000, 0, -1, FSR_V /* -1 */ + test_ftoi utrunc.s, a2, f0, 0xbf400000, 0, 0, FSR_I /* -0.75 */ + test_ftoi utrunc.s, a2, f0, 0xbf000000, 0, 0, FSR_I /* -0.5 */ /* positive */ - test_ftoi utrunc.s, a2, f0, 0x3f000000, 0, 0 /* 0.5 */ - test_ftoi utrunc.s, a2, f0, 0x3f400000, 0, 0 /* 0.75 */ - test_ftoi utrunc.s, a2, f0, 0x3f800000, 0, 1 /* 1 */ - test_ftoi utrunc.s, a2, f0, 0x3f800000, 1, 2 /* 1 * 2 */ - test_ftoi utrunc.s, a2, f0, 0x3fc00000, 0, 1 /* 1.5 */ - test_ftoi utrunc.s, a2, f0, 0x3fa00000, 1, 2 /* 1.25 * 2 */ + test_ftoi utrunc.s, a2, f0, 0x3f000000, 0, 0, FSR_I /* 0.5 */ + test_ftoi utrunc.s, a2, f0, 0x3f400000, 0, 0, FSR_I /* 0.75 */ + test_ftoi utrunc.s, a2, f0, 0x3f800000, 0, 1, FSR__ /* 1 */ + test_ftoi utrunc.s, a2, f0, 0x3f800000, 1, 2, FSR__ /* 1 * 2 */ + test_ftoi utrunc.s, a2, f0, 0x3fc00000, 0, 1, FSR_I /* 1.5 */ + test_ftoi utrunc.s, a2, f0, 0x3fa00000, 1, 2, FSR_I /* 1.25 * 2 */ /* positive overflow */ - test_ftoi utrunc.s, a2, f0, 0x4effffff, 0, 0x7fffff80 - test_ftoi utrunc.s, a2, f0, 0x4f000000, 0, 0x80000000 - test_ftoi utrunc.s, a2, f0, 0x4effffff, 1, 0xffffff00 - test_ftoi utrunc.s, a2, f0, 0x4f800000, 1, 0xffffffff + test_ftoi utrunc.s, a2, f0, 0x4effffff, 0, 0x7fffff80, FSR__ + test_ftoi utrunc.s, a2, f0, 0x4f000000, 0, 0x80000000, FSR__ + test_ftoi utrunc.s, a2, f0, 0x4effffff, 1, 0xffffff00, FSR__ + test_ftoi utrunc.s, a2, f0, 0x4f800000, 1, 0xffffffff, FSR_V /* +inf */ - test_ftoi utrunc.s, a2, f0, 0x7f800000, 0, 0xffffffff + test_ftoi utrunc.s, a2, f0, 0x7f800000, 0, 0xffffffff, FSR_V /* NaN */ - test_ftoi utrunc.s, a2, f0, 0x7f800001, 0, 0xffffffff - test_ftoi utrunc.s, a2, f0, 0x7fc00000, 0, 0xffffffff + test_ftoi utrunc.s, a2, f0, 0x7f800001, 0, 0xffffffff, FSR_V + test_ftoi utrunc.s, a2, f0, 0x7fc00000, 0, 0xffffffff, FSR_V test_end test float_s test_itof float.s, f0, a2, -1, 0, \ - 0xbf800000, 0xbf800000, 0xbf800000, 0xbf800000 - test_itof float.s, f0, a2, 0, 0, 0, 0, 0, 0 + 0xbf800000, 0xbf800000, 0xbf800000, 0xbf800000, FSR__ + test_itof float.s, f0, a2, 0, 0, 0, 0, 0, 0, FSR__ test_itof float.s, f0, a2, 1, 1, \ - 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000 + 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, FSR__ test_itof float.s, f0, a2, 1, 0, \ - 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 + 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, FSR__ test_itof float.s, f0, a2, 0x7fffffff, 0, \ - 0x4f000000, 0x4effffff, 0x4f000000, 0x4effffff + 0x4f000000, 0x4effffff, 0x4f000000, 0x4effffff, FSR_I test_end test ufloat_s - test_itof ufloat.s, f0, a2, 0, 0, 0, 0, 0, 0 + test_itof ufloat.s, f0, a2, 0, 0, 0, 0, 0, 0, FSR__ test_itof ufloat.s, f0, a2, 1, 1, \ - 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000 + 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, FSR__ test_itof ufloat.s, f0, a2, 1, 0, \ - 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 + 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, FSR__ test_itof ufloat.s, f0, a2, 0x7fffffff, 0, \ - 0x4f000000, 0x4effffff, 0x4f000000, 0x4effffff + 0x4f000000, 0x4effffff, 0x4f000000, 0x4effffff, FSR_I test_itof ufloat.s, f0, a2, 0xffffffff, 0, \ - 0x4f800000, 0x4f7fffff, 0x4f800000, 0x4f7fffff + 0x4f800000, 0x4f7fffff, 0x4f800000, 0x4f7fffff, FSR_I test_end #endif diff --git a/tests/tcg/xtensa/test_fp0_div.S b/tests/tcg/xtensa/test_fp0_div.S new file mode 100644 index 0000000000000000000000000000000000000000..c3e7ad7bb5b30c8209042f6ee5ad083b0e47aa1d --- /dev/null +++ b/tests/tcg/xtensa/test_fp0_div.S @@ -0,0 +1,82 @@ +#include "macros.inc" +#include "fpu.h" + +test_suite fp0_div + +#if XCHAL_HAVE_FP_DIV + +.macro divs_seq q, a, b, r, y, y0, an, bn, e, ex + div0.s \y0, \b + nexp01.s \bn, \b + const.s \e, 1 + maddn.s \e, \bn, \y0 + mov.s \y, \y0 + mov.s \ex, \b + nexp01.s \an, \a + maddn.s \y, \e, \y0 + const.s \e, 1 + const.s \q, 0 + neg.s \r, \an + maddn.s \e, \bn, \y + maddn.s \q, \r, \y0 + mkdadj.s \ex, \a + maddn.s \y, \e, \y + maddn.s \r, \bn, \q + const.s \e, 1 + maddn.s \e, \bn, \y + maddn.s \q, \r, \y + neg.s \r, \an + maddn.s \y, \e, \y + maddn.s \r, \bn, \q + addexpm.s \q, \ex + addexp.s \y, \ex + divn.s \q, \r, \y +.endm + +.macro div_s fr0, fr1, fr2 + divs_seq \fr0, \fr1, \fr2, f9, f10, f11, f12, f13, f14, f15 +.endm + +.macro movfp fr, v + movi a2, \v + wfr \fr, a2 +.endm + +.macro check_res fr, r, sr + rfr a2, \fr + dump a2 + movi a3, \r + assert eq, a2, a3 + rur a2, fsr + movi a3, \sr + assert eq, a2, a3 +.endm + +test div_s + movi a2, 1 + wsr a2, cpenable + + test_op2 div_s, f0, f1, f2, 0x40000000, 0x40400000, \ + 0x3f2aaaab, 0x3f2aaaaa, 0x3f2aaaab, 0x3f2aaaaa, \ + FSR_I, FSR_I, FSR_I, FSR_I + test_op2 div_s, f3, f4, f5, F32_1, F32_0, \ + F32_PINF, F32_PINF, F32_PINF, F32_PINF, \ + FSR_Z, FSR_Z, FSR_Z, FSR_Z + test_op2 div_s, f6, f7, f8, F32_0, F32_0, \ + F32_DNAN, F32_DNAN, F32_DNAN, F32_DNAN, \ + FSR_V, FSR_V, FSR_V, FSR_V + + /* MAX_FLOAT / 0.5 = +inf/MAX_FLOAT */ + test_op2 div_s, f0, f1, f2, F32_MAX, F32_0_5, \ + F32_PINF, F32_MAX, F32_PINF, F32_MAX, \ + FSR_OI, FSR_OI, FSR_OI, FSR_OI + + /* 0.5 / MAX_FLOAT = denorm */ + test_op2 div_s, f0, f1, f2, F32_0_5, F32_MAX, \ + 0x00100000, 0x00100000, 0x00100001, 0x00100000, \ + FSR_UI, FSR_UI, FSR_UI, FSR_UI +test_end + +#endif + +test_suite_end diff --git a/tests/tcg/xtensa/test_fp0_sqrt.S b/tests/tcg/xtensa/test_fp0_sqrt.S new file mode 100644 index 0000000000000000000000000000000000000000..585973dce6bc1f2579a3e6b6bded2994f67f40a9 --- /dev/null +++ b/tests/tcg/xtensa/test_fp0_sqrt.S @@ -0,0 +1,76 @@ +#include "macros.inc" +#include "fpu.h" + +test_suite fp0_sqrt + +#if XCHAL_HAVE_FP_SQRT + +.macro sqrt_seq r, a, y, t1, hn, h2, t5, h + sqrt0.s \y, \a + const.s \t1, 0 + maddn.s \t1, \y, \y + nexp01.s \hn, \a + const.s \r, 3 + addexp.s \hn, \r + maddn.s \r, \t1, \hn + nexp01.s \t1, \a + neg.s \h2, \t1 + maddn.s \y, \r, \y + const.s \r, 0 + const.s \t5, 0 + const.s \h, 0 + maddn.s \r, \h2, \y + maddn.s \t5, \y, \hn + const.s \hn, 3 + maddn.s \h, \hn, \y + maddn.s \t1, \r, \r + maddn.s \hn, \t5, \y + neg.s \y, \h + maddn.s \r, \t1, \y + maddn.s \h, \hn, \h + mksadj.s \y, \a + nexp01.s \a, \a + maddn.s \a, \r, \r + neg.s \t1, \h + addexpm.s \r, \y + addexp.s \t1, \y + divn.s \r, \a, \t1 +.endm + +.macro sqrt_s fr0, fr1 + sqrt_seq \fr0, \fr1, f10, f11, f12, f13, f14, f15 +.endm + +.macro movfp fr, v + movi a2, \v + wfr \fr, a2 +.endm + +.macro check_res fr, r, sr + rfr a2, \fr + dump a2 + movi a3, \r + assert eq, a2, a3 + rur a2, fsr + movi a3, \sr + assert eq, a2, a3 +.endm + +test sqrt_s + movi a2, 1 + wsr a2, cpenable + + test_op1 sqrt_s, f0, f1, 0x40000000, \ + 0x3fb504f3, 0x3fb504f3, 0x3fb504f4, 0x3fb504f3, \ + FSR_I, FSR_I, FSR_I, FSR_I + test_op1 sqrt_s, f3, f4, F32_1, \ + F32_1, F32_1, F32_1, F32_1, \ + FSR__, FSR__, FSR__, FSR__ + test_op1 sqrt_s, f6, f7, F32_MINUS | F32_1, \ + F32_DNAN, F32_DNAN, F32_DNAN, F32_DNAN, \ + FSR_V, FSR_V, FSR_V, FSR_V +test_end + +#endif + +test_suite_end diff --git a/tests/tcg/xtensa/test_fp1.S b/tests/tcg/xtensa/test_fp1.S index 6e182e5964bd245ba7ea1b9ad623265bda62dd06..77336a3fcf2c5ec6c6905dd1152c95982d4cf817 100644 --- a/tests/tcg/xtensa/test_fp1.S +++ b/tests/tcg/xtensa/test_fp1.S @@ -1,4 +1,5 @@ #include "macros.inc" +#include "fpu.h" test_suite fp1 @@ -9,7 +10,7 @@ test_suite fp1 wfr \fr, a2 .endm -.macro test_ord_ex op, br, fr0, fr1, v0, v1, r +.macro test_ord_ex op, br, fr0, fr1, v0, v1, r, sr movi a2, 0 wur a2, fsr movfp \fr0, \v0 @@ -20,65 +21,70 @@ test_suite fp1 movt a2, a3, \br assert eqi, a2, \r rur a2, fsr +#if DFPU + movi a3, \sr + assert eq, a2, a3 +#else assert eqi, a2, 0 +#endif .endm -.macro test_ord op, br, fr0, fr1, v0, v1, r +.macro test_ord op, br, fr0, fr1, v0, v1, r, sr movi a2, 0 wur a2, fcr - test_ord_ex \op, \br, \fr0, \fr1, \v0, \v1, \r + test_ord_ex \op, \br, \fr0, \fr1, \v0, \v1, \r, \sr movi a2, 0x7c wur a2, fcr - test_ord_ex \op, \br, \fr0, \fr1, \v0, \v1, \r + test_ord_ex \op, \br, \fr0, \fr1, \v0, \v1, \r, \sr .endm -.macro test_ord_all op, aa, ab, ba, aPI, PIa, aN, Na, II, IN, NI - test_ord \op b0, f0, f1, 0x3f800000, 0x3f800000, \aa - test_ord \op b1, f2, f3, 0x3f800000, 0x3fc00000, \ab - test_ord \op b2, f4, f5, 0x3fc00000, 0x3f800000, \ba - test_ord \op b3, f6, f7, 0x3f800000, 0x7f800000, \aPI - test_ord \op b4, f8, f9, 0x7f800000, 0x3f800000, \PIa - test_ord \op b5, f10, f11, 0x3f800000, 0xffc00001, \aN - test_ord \op b6, f12, f13, 0x3f800000, 0xff800001, \aN - test_ord \op b7, f14, f15, 0x3f800000, 0x7f800001, \aN - test_ord \op b8, f0, f1, 0x3f800000, 0x7fc00000, \aN - test_ord \op b9, f2, f3, 0xffc00001, 0x3f800000, \Na - test_ord \op b10, f4, f5, 0xff800001, 0x3f800000, \Na - test_ord \op b11, f6, f7, 0x7f800001, 0x3f800000, \Na - test_ord \op b12, f8, f9, 0x7fc00000, 0x3f800000, \Na - test_ord \op b13, f10, f11, 0x7f800000, 0x7f800000, \II - test_ord \op b14, f12, f13, 0x7f800000, 0x7fc00000, \IN - test_ord \op b15, f14, f15, 0x7fc00000, 0x7f800000, \NI +.macro test_ord_all op, aa, ab, ba, aPI, PIa, aN, Na, II, IN, NI, qnan_sr + test_ord \op b0, f0, f1, 0x3f800000, 0x3f800000, \aa, FSR__ /* ord == ord */ + test_ord \op b1, f2, f3, 0x3f800000, 0x3fc00000, \ab, FSR__ /* ord < ord */ + test_ord \op b2, f4, f5, 0x3fc00000, 0x3f800000, \ba, FSR__ /* ord > ord */ + test_ord \op b3, f6, f7, 0x3f800000, 0x7f800000, \aPI, FSR__ /* ord +INF */ + test_ord \op b4, f8, f9, 0x7f800000, 0x3f800000, \PIa, FSR__ /* +INF ord */ + test_ord \op b5, f10, f11, 0x3f800000, 0xffc00001, \aN, \qnan_sr /* ord -QNaN */ + test_ord \op b6, f12, f13, 0x3f800000, 0xff800001, \aN, FSR_V /* ord -SNaN */ + test_ord \op b7, f14, f15, 0x3f800000, 0x7f800001, \aN, FSR_V /* ord +SNaN */ + test_ord \op b8, f0, f1, 0x3f800000, 0x7fc00000, \aN, \qnan_sr /* ord +QNaN */ + test_ord \op b9, f2, f3, 0xffc00001, 0x3f800000, \Na, \qnan_sr /* -QNaN ord */ + test_ord \op b10, f4, f5, 0xff800001, 0x3f800000, \Na, FSR_V /* -SNaN ord */ + test_ord \op b11, f6, f7, 0x7f800001, 0x3f800000, \Na, FSR_V /* +SNaN ord */ + test_ord \op b12, f8, f9, 0x7fc00000, 0x3f800000, \Na, \qnan_sr /* +QNaN ord */ + test_ord \op b13, f10, f11, 0x7f800000, 0x7f800000, \II, FSR__ /* +INF +INF */ + test_ord \op b14, f12, f13, 0x7f800000, 0x7fc00000, \IN, \qnan_sr /* +INF +QNaN */ + test_ord \op b15, f14, f15, 0x7fc00000, 0x7f800000, \NI, \qnan_sr /* +QNaN +INF */ .endm test un_s movi a2, 1 wsr a2, cpenable - test_ord_all un.s, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1 + test_ord_all un.s, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, FSR__ test_end test oeq_s - test_ord_all oeq.s, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0 + test_ord_all oeq.s, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, FSR__ test_end test ueq_s - test_ord_all ueq.s, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1 + test_ord_all ueq.s, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, FSR__ test_end test olt_s - test_ord_all olt.s, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 + test_ord_all olt.s, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, FSR_V test_end test ult_s - test_ord_all ult.s, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1 + test_ord_all ult.s, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, FSR__ test_end test ole_s - test_ord_all ole.s, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0 + test_ord_all ole.s, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, FSR_V test_end test ule_s - test_ord_all ule.s, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1 + test_ord_all ule.s, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, FSR__ test_end .macro test_cond op, fr0, fr1, cr, v0, v1, r diff --git a/tests/tcg/xtensa/test_lsc.S b/tests/tcg/xtensa/test_lsc.S index 0578bf19e72ece136dd9972fc0a1d31f03354450..348822bdd3595573a34a9ce6227653d8c5f316c6 100644 --- a/tests/tcg/xtensa/test_lsc.S +++ b/tests/tcg/xtensa/test_lsc.S @@ -1,4 +1,5 @@ #include "macros.inc" +#include "fpu.h" test_suite lsc @@ -9,9 +10,14 @@ test lsi wsr a2, cpenable movi a2, 1f - lsi f0, a2, 0 lsi f1, a2, 4 +#if DFPU + lsi f2, a2, 8 + lsip f0, a2, 8 +#else + lsi f0, a2, 0 lsiu f2, a2, 8 +#endif movi a3, 1f + 8 assert eq, a2, a3 rfr a2, f0 @@ -34,13 +40,18 @@ test ssi movi a2, 1f movi a3, 0x40800000 wfr f3, a3 - ssi f3, a2, 0 movi a3, 0x40a00000 wfr f4, a3 - ssi f4, a2, 4 movi a3, 0x40c00000 wfr f5, a3 + ssi f4, a2, 4 +#if DFPU + ssi f5, a2, 8 + ssip f3, a2, 8 +#else + ssi f3, a2, 0 ssiu f5, a2, 8 +#endif movi a3, 1f + 8 assert eq, a2, a3 l32i a4, a2, -8 @@ -62,11 +73,16 @@ test_end test lsx movi a2, 1f movi a3, 0 + movi a4, 4 + movi a5, 8 + lsx f7, a2, a4 +#if DFPU + lsx f8, a2, a5 + lsxp f6, a2, a5 +#else lsx f6, a2, a3 - movi a3, 4 - lsx f7, a2, a3 - movi a3, 8 - lsxu f8, a2, a3 + lsxu f8, a2, a5 +#endif movi a3, 1f + 8 assert eq, a2, a3 rfr a2, f6 @@ -87,18 +103,23 @@ test_end test ssx movi a2, 1f - movi a3, 0 movi a4, 0x41200000 wfr f9, a4 - ssx f9, a2, a3 - movi a3, 4 movi a4, 0x41300000 wfr f10, a4 - ssx f10, a2, a3 - movi a3, 8 movi a4, 0x41400000 wfr f11, a4 - ssxu f11, a2, a3 + movi a3, 0 + movi a4, 4 + movi a5, 8 + ssx f10, a2, a4 +#if DFPU + ssx f11, a2, a5 + ssxp f9, a2, a5 +#else + ssx f9, a2, a3 + ssxu f11, a2, a5 +#endif movi a3, 1f + 8 assert eq, a2, a3 l32i a4, a2, -8 @@ -119,4 +140,127 @@ test_end #endif +#if XCHAL_HAVE_DFP + +#if XCHAL_HAVE_BE +#define F64_HIGH_OFF 0 +#else +#define F64_HIGH_OFF 4 +#endif + +.macro movdf fr, hi, lo + movi a2, \hi + movi a3, \lo + wfrd \fr, a2, a3 +.endm + +test ldi + movi a2, 1 + wsr a2, cpenable + + movi a2, 1f + ldi f1, a2, 8 + ldi f2, a2, 16 + ldip f0, a2, 16 + movi a3, 1f + 16 + assert eq, a2, a3 + rfrd a2, f0 + movi a3, 0x3ff00000 + assert eq, a2, a3 + rfrd a2, f1 + movi a3, 0x40000000 + assert eq, a2, a3 + rfrd a2, f2 + movi a3, 0x40080000 + assert eq, a2, a3 +.data + .align 8 +1: +.double 1, 2, 3 +.text +test_end + +test sdi + movdf f3, 0x40800000, 0 + movdf f4, 0x40a00000, 0 + movdf f5, 0x40c00000, 0 + movi a2, 1f + sdi f4, a2, 8 + sdi f5, a2, 16 + sdip f3, a2, 16 + movi a3, 1f + 16 + assert eq, a2, a3 + l32i a4, a2, -16 + F64_HIGH_OFF + movi a3, 0x40800000 + assert eq, a4, a3 + l32i a4, a2, -8 + F64_HIGH_OFF + movi a3, 0x40a00000 + assert eq, a4, a3 + l32i a4, a2, F64_HIGH_OFF + movi a3, 0x40c00000 + assert eq, a4, a3 +.data + .align 8 +1: +.double 0, 0, 0 +.text +test_end + +test ldx + movi a2, 1f + movi a3, 0 + movi a4, 8 + movi a5, 16 + ldx f7, a2, a4 + ldx f8, a2, a5 + ldxp f6, a2, a5 + movi a3, 1f + 16 + assert eq, a2, a3 + rfrd a2, f6 + movi a3, 0x401c0000 + assert eq, a2, a3 + rfrd a2, f7 + movi a3, 0x40200000 + assert eq, a2, a3 + rfrd a2, f8 + movi a3, 0x40220000 + assert eq, a2, a3 +.data + .align 8 +1: +.double 7, 8, 9 +.text +test_end + +test sdx + movdf f9, 0x41200000, 0 + movdf f10, 0x41300000, 0 + movdf f11, 0x41400000, 0 + movi a2, 1f + movi a3, 0 + movi a4, 8 + movi a5, 16 + sdx f10, a2, a4 + sdx f11, a2, a5 + sdxp f9, a2, a5 + movi a3, 1f + 16 + assert eq, a2, a3 + l32i a4, a2, -16 + F64_HIGH_OFF + movi a3, 0x41200000 + assert eq, a4, a3 + l32i a4, a2, -8 + F64_HIGH_OFF + movi a3, 0x41300000 + assert eq, a4, a3 + l32i a4, a2, F64_HIGH_OFF + movi a3, 0x41400000 + assert eq, a4, a3 +.data + .align 8 +1: +.double 0, 0, 0 +.text +test_end + +#endif + test_suite_end diff --git a/tests/test-aio-multithread.c b/tests/test-aio-multithread.c index d3144be7e0c493d41cd531ed8454785480a9a0ad..a555cc8835053bf69b3acd1e5d95a6a87a72209e 100644 --- a/tests/test-aio-multithread.c +++ b/tests/test-aio-multithread.c @@ -118,16 +118,16 @@ static bool schedule_next(int n) { Coroutine *co; - co = atomic_xchg(&to_schedule[n], NULL); + co = qatomic_xchg(&to_schedule[n], NULL); if (!co) { - atomic_inc(&count_retry); + qatomic_inc(&count_retry); return false; } if (n == id) { - atomic_inc(&count_here); + qatomic_inc(&count_here); } else { - atomic_inc(&count_other); + qatomic_inc(&count_other); } aio_co_schedule(ctx[n], co); @@ -143,13 +143,13 @@ static coroutine_fn void test_multi_co_schedule_entry(void *opaque) { g_assert(to_schedule[id] == NULL); - while (!atomic_mb_read(&now_stopping)) { + while (!qatomic_mb_read(&now_stopping)) { int n; n = g_test_rand_int_range(0, NUM_CONTEXTS); schedule_next(n); - atomic_mb_set(&to_schedule[id], qemu_coroutine_self()); + qatomic_mb_set(&to_schedule[id], qemu_coroutine_self()); qemu_coroutine_yield(); g_assert(to_schedule[id] == NULL); } @@ -171,7 +171,7 @@ static void test_multi_co_schedule(int seconds) g_usleep(seconds * 1000000); - atomic_mb_set(&now_stopping, true); + qatomic_mb_set(&now_stopping, true); for (i = 0; i < NUM_CONTEXTS; i++) { ctx_run(i, finish_cb, NULL); to_schedule[i] = NULL; @@ -202,7 +202,7 @@ static CoMutex comutex; static void coroutine_fn test_multi_co_mutex_entry(void *opaque) { - while (!atomic_mb_read(&now_stopping)) { + while (!qatomic_mb_read(&now_stopping)) { qemu_co_mutex_lock(&comutex); counter++; qemu_co_mutex_unlock(&comutex); @@ -212,9 +212,9 @@ static void coroutine_fn test_multi_co_mutex_entry(void *opaque) * exits before the coroutine is woken up, causing a spurious * assertion failure. */ - atomic_inc(&atomic_counter); + qatomic_inc(&atomic_counter); } - atomic_dec(&running); + qatomic_dec(&running); } static void test_multi_co_mutex(int threads, int seconds) @@ -236,7 +236,7 @@ static void test_multi_co_mutex(int threads, int seconds) g_usleep(seconds * 1000000); - atomic_mb_set(&now_stopping, true); + qatomic_mb_set(&now_stopping, true); while (running > 0) { g_usleep(100000); } @@ -296,9 +296,9 @@ static void mcs_mutex_lock(void) nodes[id].next = -1; nodes[id].locked = 1; - prev = atomic_xchg(&mutex_head, id); + prev = qatomic_xchg(&mutex_head, id); if (prev != -1) { - atomic_set(&nodes[prev].next, id); + qatomic_set(&nodes[prev].next, id); qemu_futex_wait(&nodes[id].locked, 1); } } @@ -306,13 +306,13 @@ static void mcs_mutex_lock(void) static void mcs_mutex_unlock(void) { int next; - if (atomic_read(&nodes[id].next) == -1) { - if (atomic_read(&mutex_head) == id && - atomic_cmpxchg(&mutex_head, id, -1) == id) { + if (qatomic_read(&nodes[id].next) == -1) { + if (qatomic_read(&mutex_head) == id && + qatomic_cmpxchg(&mutex_head, id, -1) == id) { /* Last item in the list, exit. */ return; } - while (atomic_read(&nodes[id].next) == -1) { + while (qatomic_read(&nodes[id].next) == -1) { /* mcs_mutex_lock did the xchg, but has not updated * nodes[prev].next yet. */ @@ -320,20 +320,20 @@ static void mcs_mutex_unlock(void) } /* Wake up the next in line. */ - next = atomic_read(&nodes[id].next); + next = qatomic_read(&nodes[id].next); nodes[next].locked = 0; qemu_futex_wake(&nodes[next].locked, 1); } static void test_multi_fair_mutex_entry(void *opaque) { - while (!atomic_mb_read(&now_stopping)) { + while (!qatomic_mb_read(&now_stopping)) { mcs_mutex_lock(); counter++; mcs_mutex_unlock(); - atomic_inc(&atomic_counter); + qatomic_inc(&atomic_counter); } - atomic_dec(&running); + qatomic_dec(&running); } static void test_multi_fair_mutex(int threads, int seconds) @@ -355,7 +355,7 @@ static void test_multi_fair_mutex(int threads, int seconds) g_usleep(seconds * 1000000); - atomic_mb_set(&now_stopping, true); + qatomic_mb_set(&now_stopping, true); while (running > 0) { g_usleep(100000); } @@ -383,13 +383,13 @@ static QemuMutex mutex; static void test_multi_mutex_entry(void *opaque) { - while (!atomic_mb_read(&now_stopping)) { + while (!qatomic_mb_read(&now_stopping)) { qemu_mutex_lock(&mutex); counter++; qemu_mutex_unlock(&mutex); - atomic_inc(&atomic_counter); + qatomic_inc(&atomic_counter); } - atomic_dec(&running); + qatomic_dec(&running); } static void test_multi_mutex(int threads, int seconds) @@ -411,7 +411,7 @@ static void test_multi_mutex(int threads, int seconds) g_usleep(seconds * 1000000); - atomic_mb_set(&now_stopping, true); + qatomic_mb_set(&now_stopping, true); while (running > 0) { g_usleep(100000); } diff --git a/tests/test-authz-list.c b/tests/test-authz-list.c index d80e6a6d4dcc9fc2266385c8ae459f5bfb080c62..5351992a01311d8ee35bb6e3b402590d58930ef0 100644 --- a/tests/test-authz-list.c +++ b/tests/test-authz-list.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/test-authz-listfile.c b/tests/test-authz-listfile.c index 26166b691b71964c4a45731e3593e7910642efc9..64d0e1500f76b2741c6781c2b15bc24a442caf85 100644 --- a/tests/test-authz-listfile.c +++ b/tests/test-authz-listfile.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/test-authz-pam.c b/tests/test-authz-pam.c index 02bb1493e7242ac962a0fc62431981c92f64a966..1baeadee03dbf4590f4bef74cf94d492aa0b8888 100644 --- a/tests/test-authz-pam.c +++ b/tests/test-authz-pam.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/test-authz-simple.c b/tests/test-authz-simple.c index d21d43e2e9eec2b427181e740953b7adc1abe0a4..6f9034d8ff2b377b3219e6d201d6cf768c3730e5 100644 --- a/tests/test-authz-simple.c +++ b/tests/test-authz-simple.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/test-base64.c b/tests/test-base64.c index ec122ceba5e33bba5fc9b3e0b605992ff676f274..3012d7be267c7624ef1d32e946224c42d986a333 100644 --- a/tests/test-base64.c +++ b/tests/test-base64.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -54,10 +54,9 @@ static void test_base64_bad(const char *input, &len, &err); - g_assert(err != NULL); + error_free_or_abort(&err); g_assert(actual == NULL); g_assert_cmpint(len, ==, 0); - error_free(err); } diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c index 11072718400aecf6f7ead81f470949eb654bc164..8a29e33e004a4c9012761e32c93949368fda93b9 100644 --- a/tests/test-bdrv-drain.c +++ b/tests/test-bdrv-drain.c @@ -594,6 +594,7 @@ static void test_graph_change_drain_all(void) g_assert_cmpint(bs_b->quiesce_counter, ==, 0); g_assert_cmpint(b_s->drain_count, ==, 0); + g_assert_cmpint(qemu_get_aio_context()->external_disable_cnt, ==, 0); bdrv_unref(bs_b); blk_unref(blk_b); @@ -1872,7 +1873,7 @@ static int coroutine_fn bdrv_replace_test_co_preadv(BlockDriverState *bs, } s->io_co = NULL; - ret = bdrv_preadv(bs->backing, offset, qiov); + ret = bdrv_co_preadv(bs->backing, offset, bytes, qiov, 0); s->has_read = true; /* Wake up drain_co if it runs */ diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c index f93f3168b047f54f725e4d36606d29f4417e9053..8cff13830e3e2cca1dd4c67fe9f9d50d70ce9b14 100644 --- a/tests/test-bdrv-graph-mod.c +++ b/tests/test-bdrv-graph-mod.c @@ -115,9 +115,7 @@ static void test_update_perm_tree(void) BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, &error_abort); bdrv_append(filter, bs, &local_err); - - g_assert_nonnull(local_err); - error_free(local_err); + error_free_or_abort(&local_err); blk_unref(root); } diff --git a/tests/test-bitmap.c b/tests/test-bitmap.c index 2f5b71458a3df1d724b27023a510ed10bdb9e370..8db4f67883fe60159cae9d7ce023c21ff9655bb4 100644 --- a/tests/test-bitmap.c +++ b/tests/test-bitmap.c @@ -8,7 +8,6 @@ * Author: Peter Xu */ -#include #include "qemu/osdep.h" #include "qemu/bitmap.h" diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c index a953794be22734b31ff5a3fbc92b1580d0566c7c..3f866a35c6cc771150251af40f904c28edb90fd8 100644 --- a/tests/test-block-iothread.c +++ b/tests/test-block-iothread.c @@ -650,8 +650,7 @@ static void test_propagate_mirror(void) blk_insert_bs(blk, src, &error_abort); bdrv_try_set_aio_context(target, ctx, &local_err); - g_assert(local_err); - error_free(local_err); + error_free_or_abort(&local_err); g_assert(blk_get_aio_context(blk) == main_ctx); g_assert(bdrv_get_aio_context(src) == main_ctx); diff --git a/tests/test-bufferiszero.c b/tests/test-bufferiszero.c index 42d194cadf45819534ec52ff1060749ba54127bb..e45fd31804c007219e4c124fe761e28e69fd5596 100644 --- a/tests/test-bufferiszero.c +++ b/tests/test-bufferiszero.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/test-char.c b/tests/test-char.c index 3afc9b1b8d59802919139012c2cb1802f0795503..9196e566e9ba671ed268a31788451ebb2335dc7d 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -6,7 +6,6 @@ #include "qemu/option.h" #include "qemu/sockets.h" #include "chardev/char-fe.h" -#include "chardev/char-mux.h" #include "sysemu/sysemu.h" #include "qapi/error.h" #include "qapi/qapi-commands-char.h" @@ -71,7 +70,7 @@ static void fe_event(void *opaque, QEMUChrEvent event) h->openclose_mismatch = true; } h->is_open = new_open_state; - /* no break */ + /* fallthrough */ default: quit = true; break; @@ -625,12 +624,14 @@ static void char_udp_test(void) typedef struct { int event; bool got_pong; + CharBackend *be; } CharSocketTestData; #define SOCKET_PING "Hello" #define SOCKET_PONG "World" +typedef void (*char_socket_cb)(void *opaque, QEMUChrEvent event); static void char_socket_event(void *opaque, QEMUChrEvent event) @@ -639,6 +640,27 @@ char_socket_event(void *opaque, QEMUChrEvent event) data->event = event; } +static void +char_socket_event_with_error(void *opaque, QEMUChrEvent event) +{ + static bool first_error; + CharSocketTestData *data = opaque; + CharBackend *be = data->be; + data->event = event; + switch (event) { + case CHR_EVENT_OPENED: + if (!first_error) { + first_error = true; + qemu_chr_fe_disconnect(be); + } + return; + case CHR_EVENT_CLOSED: + return; + default: + return; + } +} + static void char_socket_read(void *opaque, const uint8_t *buf, int size) @@ -699,19 +721,24 @@ char_socket_addr_to_opt_str(SocketAddress *addr, bool fd_pass, } -static void -char_socket_ping_pong(QIOChannel *ioc) +static int +char_socket_ping_pong(QIOChannel *ioc, Error **errp) { char greeting[sizeof(SOCKET_PING)]; const char *response = SOCKET_PONG; - qio_channel_read_all(ioc, greeting, sizeof(greeting), &error_abort); + int ret; + ret = qio_channel_read_all(ioc, greeting, sizeof(greeting), errp); + if (ret != 0) { + object_unref(OBJECT(ioc)); + return -1; + } g_assert(memcmp(greeting, SOCKET_PING, sizeof(greeting)) == 0); - qio_channel_write_all(ioc, response, sizeof(SOCKET_PONG), &error_abort); - + qio_channel_write_all(ioc, response, sizeof(SOCKET_PONG), errp); object_unref(OBJECT(ioc)); + return 0; } @@ -723,7 +750,7 @@ char_socket_server_client_thread(gpointer data) qio_channel_socket_connect_sync(ioc, addr, &error_abort); - char_socket_ping_pong(QIO_CHANNEL(ioc)); + char_socket_ping_pong(QIO_CHANNEL(ioc), &error_abort); return NULL; } @@ -783,6 +810,7 @@ static void char_socket_server_test(gconstpointer opaque) reconnect: data.event = -1; + data.be = &be; qemu_chr_fe_set_handlers(&be, NULL, NULL, char_socket_event, NULL, &data, NULL, true); @@ -855,10 +883,13 @@ char_socket_client_server_thread(gpointer data) QIOChannelSocket *ioc = data; QIOChannelSocket *cioc; +retry: cioc = qio_channel_socket_accept(ioc, &error_abort); g_assert_nonnull(cioc); - char_socket_ping_pong(QIO_CHANNEL(cioc)); + if (char_socket_ping_pong(QIO_CHANNEL(cioc), NULL) != 0) { + goto retry; + } return NULL; } @@ -869,12 +900,59 @@ typedef struct { const char *reconnect; bool wait_connected; bool fd_pass; + char_socket_cb event_cb; } CharSocketClientTestConfig; +static void char_socket_client_dupid_test(gconstpointer opaque) +{ + const CharSocketClientTestConfig *config = opaque; + QIOChannelSocket *ioc; + char *optstr; + Chardev *chr1, *chr2; + SocketAddress *addr; + QemuOpts *opts; + Error *local_err = NULL; + + /* + * Setup a listener socket and determine get its address + * so we know the TCP port for the client later + */ + ioc = qio_channel_socket_new(); + g_assert_nonnull(ioc); + qio_channel_socket_listen_sync(ioc, config->addr, 1, &error_abort); + addr = qio_channel_socket_get_local_address(ioc, &error_abort); + g_assert_nonnull(addr); + + /* + * Populate the chardev address based on what the server + * is actually listening on + */ + optstr = char_socket_addr_to_opt_str(addr, + config->fd_pass, + config->reconnect, + false); + + opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"), + optstr, true); + g_assert_nonnull(opts); + chr1 = qemu_chr_new_from_opts(opts, NULL, &error_abort); + g_assert_nonnull(chr1); + + chr2 = qemu_chr_new_from_opts(opts, NULL, &local_err); + g_assert_null(chr2); + error_free_or_abort(&local_err); + + object_unref(OBJECT(ioc)); + qemu_opts_del(opts); + object_unparent(OBJECT(chr1)); + qapi_free_SocketAddress(addr); + g_free(optstr); +} static void char_socket_client_test(gconstpointer opaque) { const CharSocketClientTestConfig *config = opaque; + const char_socket_cb event_cb = config->event_cb; QIOChannelSocket *ioc; char *optstr; Chardev *chr; @@ -938,8 +1016,9 @@ static void char_socket_client_test(gconstpointer opaque) reconnect: data.event = -1; + data.be = &be; qemu_chr_fe_set_handlers(&be, NULL, NULL, - char_socket_event, NULL, + event_cb, NULL, &data, NULL, true); if (config->reconnect) { g_assert(data.event == -1); @@ -977,7 +1056,7 @@ static void char_socket_client_test(gconstpointer opaque) /* Setup a callback to receive the reply to our greeting */ qemu_chr_fe_set_handlers(&be, char_socket_can_read, char_socket_read, - char_socket_event, NULL, + event_cb, NULL, &data, NULL, true); g_assert(data.event == CHR_EVENT_OPENED); data.event = -1; @@ -1121,7 +1200,7 @@ static void char_serial_test(void) /* test tty alias */ qemu_opt_set(opts, "backend", "tty", &error_abort); - chr = qemu_chr_new_from_opts(opts, NULL, NULL); + chr = qemu_chr_new_from_opts(opts, NULL, &error_abort); g_assert_nonnull(chr); object_unparent(OBJECT(chr)); @@ -1422,17 +1501,22 @@ int main(int argc, char **argv) #define SOCKET_CLIENT_TEST(name, addr) \ static CharSocketClientTestConfig client1 ## name = \ - { addr, NULL, false, false }; \ + { addr, NULL, false, false, char_socket_event }; \ static CharSocketClientTestConfig client2 ## name = \ - { addr, NULL, true, false }; \ + { addr, NULL, true, false, char_socket_event }; \ static CharSocketClientTestConfig client3 ## name = \ - { addr, ",reconnect=1", false }; \ + { addr, ",reconnect=1", false, false, char_socket_event }; \ static CharSocketClientTestConfig client4 ## name = \ - { addr, ",reconnect=1", true }; \ + { addr, ",reconnect=1", true, false, char_socket_event }; \ static CharSocketClientTestConfig client5 ## name = \ - { addr, NULL, false, true }; \ + { addr, NULL, false, true, char_socket_event }; \ static CharSocketClientTestConfig client6 ## name = \ - { addr, NULL, true, true }; \ + { addr, NULL, true, true, char_socket_event }; \ + static CharSocketClientTestConfig client7 ## name = \ + { addr, ",reconnect=1", true, false, \ + char_socket_event_with_error }; \ + static CharSocketClientTestConfig client8 ## name = \ + { addr, ",reconnect=1", false, false, char_socket_event }; \ g_test_add_data_func("/char/socket/client/mainloop/" # name, \ &client1 ##name, char_socket_client_test); \ g_test_add_data_func("/char/socket/client/wait-conn/" # name, \ @@ -1444,7 +1528,11 @@ int main(int argc, char **argv) g_test_add_data_func("/char/socket/client/mainloop-fdpass/" # name, \ &client5 ##name, char_socket_client_test); \ g_test_add_data_func("/char/socket/client/wait-conn-fdpass/" # name, \ - &client6 ##name, char_socket_client_test) + &client6 ##name, char_socket_client_test); \ + g_test_add_data_func("/char/socket/client/reconnect-error/" # name, \ + &client7 ##name, char_socket_client_test); \ + g_test_add_data_func("/char/socket/client/dupid-reconnect/" # name, \ + &client8 ##name, char_socket_client_dupid_test) if (has_ipv4) { SOCKET_SERVER_TEST(tcp, &tcpaddr); diff --git a/tests/test-crypto-afsplit.c b/tests/test-crypto-afsplit.c index f9f2fcd417c1a3275604b326f39db4bd0f2f7a66..00a7c180fd632eb7b053e23e6e4e13f8ae001c5d 100644 --- a/tests/test-crypto-afsplit.c +++ b/tests/test-crypto-afsplit.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/test-crypto-block.c b/tests/test-crypto-block.c index 7c1ab07855415a0c2a884b8519e8fe99440bb83b..3b1f0d509fa54df10723b095bb7dd5d08574d18e 100644 --- a/tests/test-crypto-block.c +++ b/tests/test-crypto-block.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/test-crypto-cipher.c b/tests/test-crypto-cipher.c index 07fa2fa616643e92ae67fe21a97e58778d2c3678..280319a2236162f6696ce368cc5f36033f2ecbbc 100644 --- a/tests/test-crypto-cipher.c +++ b/tests/test-crypto-cipher.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -761,10 +761,7 @@ static void test_cipher_short_plaintext(void) sizeof(plaintext1), &err); g_assert(ret == -1); - g_assert(err != NULL); - - error_free(err); - err = NULL; + error_free_or_abort(&err); /* Should report an error as plaintext is larger than * block size, but not a multiple of block size @@ -775,9 +772,8 @@ static void test_cipher_short_plaintext(void) sizeof(plaintext2), &err); g_assert(ret == -1); - g_assert(err != NULL); + error_free_or_abort(&err); - error_free(err); qcrypto_cipher_free(cipher); } diff --git a/tests/test-crypto-hash.c b/tests/test-crypto-hash.c index 214a9f72c32e265687819e630136f44d87b7590d..ce7d0ab9b579ac5cc4cdf06adc8182eec5382d8e 100644 --- a/tests/test-crypto-hash.c +++ b/tests/test-crypto-hash.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/test-crypto-ivgen.c b/tests/test-crypto-ivgen.c index a5ff5d3da640e70fbe9d52c5a89fe53e3d5916c3..f581e6aba7b154ad6a7c80f06c7163e9d03f43b3 100644 --- a/tests/test-crypto-ivgen.c +++ b/tests/test-crypto-ivgen.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/test-crypto-pbkdf.c b/tests/test-crypto-pbkdf.c index 85ed1f9b3339268f159c0020395a6d5794e4ba36..c50fd639d28012f3bf9cad04f3d38e6c3bb5c251 100644 --- a/tests/test-crypto-pbkdf.c +++ b/tests/test-crypto-pbkdf.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/test-crypto-secret.c b/tests/test-crypto-secret.c index 13fc6c4c7530d801496cc1ea83cf4ff53e1302ad..34a4aecc121c8f1449cc88cd01d75e094a8ed27b 100644 --- a/tests/test-crypto-secret.c +++ b/tests/test-crypto-secret.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -24,6 +24,10 @@ #include "crypto/secret.h" #include "qapi/error.h" #include "qemu/module.h" +#ifdef CONFIG_KEYUTILS +#include "crypto/secret_keyring.h" +#include +#endif static void test_secret_direct(void) { @@ -124,6 +128,147 @@ static void test_secret_indirect_emptyfile(void) g_free(fname); } +#ifdef CONFIG_KEYUTILS + +#define DESCRIPTION "qemu_test_secret" +#define PAYLOAD "Test Payload" + + +static void test_secret_keyring_good(void) +{ + char key_str[16]; + Object *sec; + int32_t key = add_key("user", DESCRIPTION, PAYLOAD, + strlen(PAYLOAD), KEY_SPEC_PROCESS_KEYRING); + + g_assert(key >= 0); + + snprintf(key_str, sizeof(key_str), "0x%08x", key); + sec = object_new_with_props( + TYPE_QCRYPTO_SECRET_KEYRING, + object_get_objects_root(), + "sec0", + &error_abort, + "serial", key_str, + NULL); + + assert(0 <= keyctl_unlink(key, KEY_SPEC_PROCESS_KEYRING)); + char *pw = qcrypto_secret_lookup_as_utf8("sec0", + &error_abort); + g_assert_cmpstr(pw, ==, PAYLOAD); + + object_unparent(sec); + g_free(pw); +} + + +static void test_secret_keyring_revoked_key(void) +{ + char key_str[16]; + Object *sec; + int32_t key = add_key("user", DESCRIPTION, PAYLOAD, + strlen(PAYLOAD), KEY_SPEC_PROCESS_KEYRING); + g_assert(key >= 0); + g_assert_false(keyctl_revoke(key)); + + snprintf(key_str, sizeof(key_str), "0x%08x", key); + sec = object_new_with_props( + TYPE_QCRYPTO_SECRET_KEYRING, + object_get_objects_root(), + "sec0", + NULL, + "serial", key_str, + NULL); + + g_assert(errno == EKEYREVOKED); + g_assert(sec == NULL); + + keyctl_unlink(key, KEY_SPEC_PROCESS_KEYRING); +} + + +static void test_secret_keyring_expired_key(void) +{ + char key_str[16]; + Object *sec; + int32_t key = add_key("user", DESCRIPTION, PAYLOAD, + strlen(PAYLOAD), KEY_SPEC_PROCESS_KEYRING); + g_assert(key >= 0); + g_assert_false(keyctl_set_timeout(key, 1)); + sleep(1); + + snprintf(key_str, sizeof(key_str), "0x%08x", key); + sec = object_new_with_props( + TYPE_QCRYPTO_SECRET_KEYRING, + object_get_objects_root(), + "sec0", + NULL, + "serial", key_str, + NULL); + + g_assert(errno == EKEYEXPIRED); + g_assert(sec == NULL); + + keyctl_unlink(key, KEY_SPEC_PROCESS_KEYRING); +} + + +static void test_secret_keyring_bad_serial_key(void) +{ + Object *sec; + + sec = object_new_with_props( + TYPE_QCRYPTO_SECRET_KEYRING, + object_get_objects_root(), + "sec0", + NULL, + "serial", "1", + NULL); + + g_assert(errno == ENOKEY); + g_assert(sec == NULL); +} + +/* + * TODO + * test_secret_keyring_bad_key_access_right() is not working yet. + * We don't know yet if this due a bug in the Linux kernel or + * whether it's normal syscall behavior. + * We've requested information from kernel maintainers. + * See: + * Thread: 'security/keys: remove possessor verify after key permission check' + */ + +static void test_secret_keyring_bad_key_access_right(void) +{ + char key_str[16]; + Object *sec; + + g_test_skip("TODO: Need responce from Linux kernel maintainers"); + return; + + int32_t key = add_key("user", DESCRIPTION, PAYLOAD, + strlen(PAYLOAD), KEY_SPEC_PROCESS_KEYRING); + g_assert(key >= 0); + g_assert_false(keyctl_setperm(key, KEY_POS_ALL & (~KEY_POS_READ))); + + snprintf(key_str, sizeof(key_str), "0x%08x", key); + + sec = object_new_with_props( + TYPE_QCRYPTO_SECRET_KEYRING, + object_get_objects_root(), + "sec0", + NULL, + "serial", key_str, + NULL); + + g_assert(errno == EACCES); + g_assert(sec == NULL); + + keyctl_unlink(key, KEY_SPEC_PROCESS_KEYRING); +} + +#endif /* CONFIG_KEYUTILS */ static void test_secret_noconv_base64_good(void) { @@ -426,6 +571,19 @@ int main(int argc, char **argv) g_test_add_func("/crypto/secret/indirect/emptyfile", test_secret_indirect_emptyfile); +#ifdef CONFIG_KEYUTILS + g_test_add_func("/crypto/secret/keyring/good", + test_secret_keyring_good); + g_test_add_func("/crypto/secret/keyring/revoked_key", + test_secret_keyring_revoked_key); + g_test_add_func("/crypto/secret/keyring/expired_key", + test_secret_keyring_expired_key); + g_test_add_func("/crypto/secret/keyring/bad_serial_key", + test_secret_keyring_bad_serial_key); + g_test_add_func("/crypto/secret/keyring/bad_key_access_right", + test_secret_keyring_bad_key_access_right); +#endif /* CONFIG_KEYUTILS */ + g_test_add_func("/crypto/secret/noconv/base64/good", test_secret_noconv_base64_good); g_test_add_func("/crypto/secret/noconv/base64/bad", diff --git a/tests/test-crypto-xts.c b/tests/test-crypto-xts.c index 6fb61cf635f46e4c18a51d2557f8852e3f454c98..7acbc956fd95fb8a62c5342c10d7058e800cdcfd 100644 --- a/tests/test-crypto-xts.c +++ b/tests/test-crypto-xts.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/test-fdmon-epoll.c b/tests/test-fdmon-epoll.c new file mode 100644 index 0000000000000000000000000000000000000000..11fd8a2fa9b5897b087661dea80ea69073eaddb4 --- /dev/null +++ b/tests/test-fdmon-epoll.c @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * fdmon-epoll tests + * + * Copyright (c) 2020 Red Hat, Inc. + */ + +#include "qemu/osdep.h" +#include "block/aio.h" +#include "qapi/error.h" +#include "qemu/main-loop.h" + +static AioContext *ctx; + +static void dummy_fd_handler(EventNotifier *notifier) +{ + event_notifier_test_and_clear(notifier); +} + +static void add_event_notifiers(EventNotifier *notifiers, size_t n) +{ + for (size_t i = 0; i < n; i++) { + event_notifier_init(¬ifiers[i], false); + aio_set_event_notifier(ctx, ¬ifiers[i], false, + dummy_fd_handler, NULL); + } +} + +static void remove_event_notifiers(EventNotifier *notifiers, size_t n) +{ + for (size_t i = 0; i < n; i++) { + aio_set_event_notifier(ctx, ¬ifiers[i], false, NULL, NULL); + event_notifier_cleanup(¬ifiers[i]); + } +} + +/* Check that fd handlers work when external clients are disabled */ +static void test_external_disabled(void) +{ + EventNotifier notifiers[100]; + + /* fdmon-epoll is only enabled when many fd handlers are registered */ + add_event_notifiers(notifiers, G_N_ELEMENTS(notifiers)); + + event_notifier_set(¬ifiers[0]); + assert(aio_poll(ctx, true)); + + aio_disable_external(ctx); + event_notifier_set(¬ifiers[0]); + assert(aio_poll(ctx, true)); + aio_enable_external(ctx); + + remove_event_notifiers(notifiers, G_N_ELEMENTS(notifiers)); +} + +int main(int argc, char **argv) +{ + /* + * This code relies on the fact that fdmon-io_uring disables itself when + * the glib main loop is in use. The main loop uses fdmon-poll and upgrades + * to fdmon-epoll when the number of fds exceeds a threshold. + */ + qemu_init_main_loop(&error_fatal); + ctx = qemu_get_aio_context(); + + while (g_main_context_iteration(NULL, false)) { + /* Do nothing */ + } + + g_test_init(&argc, &argv, NULL); + g_test_add_func("/fdmon-epoll/external-disabled", test_external_disabled); + return g_test_run(); +} diff --git a/tests/test-io-channel-buffer.c b/tests/test-io-channel-buffer.c index 59d6c64b0431c10e853373f1b23ac524d05c44b7..9c6724dea41943d72a2981fde2d2a869d36e4426 100644 --- a/tests/test-io-channel-buffer.c +++ b/tests/test-io-channel-buffer.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/test-io-channel-command.c b/tests/test-io-channel-command.c index 3bc52661210413776d9d0e5b4fb12dd98084262f..99056e07c0231253b56ab109db9e48c02b58c4c9 100644 --- a/tests/test-io-channel-command.c +++ b/tests/test-io-channel-command.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/test-io-channel-file.c b/tests/test-io-channel-file.c index bac2b07562c21721c3a1f65390a7a25a1e282730..29038e67b64d3a2865f628a27d832175ff51ed45 100644 --- a/tests/test-io-channel-file.c +++ b/tests/test-io-channel-file.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -28,6 +28,16 @@ #define TEST_FILE "tests/test-io-channel-file.txt" #define TEST_MASK 0600 +/* + * On Windows the stat() function in the C library checks only + * the FAT-style READONLY attribute and does not look at the ACL at all. + */ +#ifdef _WIN32 +#define TEST_MASK_EXPECT 0700 +#else +#define TEST_MASK_EXPECT 0777 +#endif + static void test_io_channel_file_helper(int flags) { QIOChannel *src, *dst; @@ -56,7 +66,7 @@ static void test_io_channel_file_helper(int flags) umask(mask); ret = stat(TEST_FILE, &st); g_assert_cmpint(ret, >, -1); - g_assert_cmpuint(TEST_MASK & ~mask, ==, st.st_mode & 0777); + g_assert_cmpuint(TEST_MASK & ~mask, ==, st.st_mode & TEST_MASK_EXPECT); unlink(TEST_FILE); object_unref(OBJECT(src)); diff --git a/tests/test-io-channel-socket.c b/tests/test-io-channel-socket.c index d43083a766713df3910da3fc1d24d23b6cd99535..c49eec1f038a76cb19eb06ef954eeb321d24a930 100644 --- a/tests/test-io-channel-socket.c +++ b/tests/test-io-channel-socket.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,6 +25,7 @@ #include "socket-helpers.h" #include "qapi/error.h" #include "qemu/module.h" +#include "qemu/main-loop.h" static void test_io_channel_set_socket_bufs(QIOChannel *src, @@ -556,6 +557,7 @@ int main(int argc, char **argv) bool has_ipv4, has_ipv6; module_call_init(MODULE_INIT_QOM); + qemu_init_main_loop(&error_abort); socket_init(); g_test_init(&argc, &argv, NULL); diff --git a/tests/test-io-task.c b/tests/test-io-task.c index aa8b653bfac26315c42ff48a5ca66dcaee3578b2..953a50ae66e3557a9f66712fbbe7d804a85af9ca 100644 --- a/tests/test-io-task.c +++ b/tests/test-io-task.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,6 +20,7 @@ #include "qemu/osdep.h" +#include "qom/object.h" #include "io/task.h" #include "qapi/error.h" #include "qemu/module.h" @@ -239,9 +240,7 @@ static void test_task_thread_failure(void) object_unref(obj); g_assert(data.source == obj); - g_assert(data.err != NULL); - - error_free(data.err); + error_free_or_abort(&data.err); self = g_thread_self(); diff --git a/tests/test-iov.c b/tests/test-iov.c index 458ca250994d800ec3ac34eba6cb932b188cbd3f..9c415e2f1ff11e5264eeae535ef2d20d0d4e1c0d 100644 --- a/tests/test-iov.c +++ b/tests/test-iov.c @@ -26,6 +26,12 @@ static void iov_free(struct iovec *iov, unsigned niov) g_free(iov); } +static bool iov_equals(const struct iovec *a, const struct iovec *b, + unsigned niov) +{ + return memcmp(a, b, sizeof(a[0]) * niov) == 0; +} + static void test_iov_bytes(struct iovec *iov, unsigned niov, size_t offset, size_t bytes) { @@ -335,6 +341,87 @@ static void test_discard_front(void) iov_free(iov, iov_cnt); } +static void test_discard_front_undo(void) +{ + IOVDiscardUndo undo; + struct iovec *iov; + struct iovec *iov_tmp; + struct iovec *iov_orig; + unsigned int iov_cnt; + unsigned int iov_cnt_tmp; + size_t size; + + /* Discard zero bytes */ + iov_random(&iov, &iov_cnt); + iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); + iov_tmp = iov; + iov_cnt_tmp = iov_cnt; + iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, 0, &undo); + iov_discard_undo(&undo); + assert(iov_equals(iov, iov_orig, iov_cnt)); + g_free(iov_orig); + iov_free(iov, iov_cnt); + + /* Discard more bytes than vector size */ + iov_random(&iov, &iov_cnt); + iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); + iov_tmp = iov; + iov_cnt_tmp = iov_cnt; + size = iov_size(iov, iov_cnt); + iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size + 1, &undo); + iov_discard_undo(&undo); + assert(iov_equals(iov, iov_orig, iov_cnt)); + g_free(iov_orig); + iov_free(iov, iov_cnt); + + /* Discard entire vector */ + iov_random(&iov, &iov_cnt); + iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); + iov_tmp = iov; + iov_cnt_tmp = iov_cnt; + size = iov_size(iov, iov_cnt); + iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo); + iov_discard_undo(&undo); + assert(iov_equals(iov, iov_orig, iov_cnt)); + g_free(iov_orig); + iov_free(iov, iov_cnt); + + /* Discard within first element */ + iov_random(&iov, &iov_cnt); + iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); + iov_tmp = iov; + iov_cnt_tmp = iov_cnt; + size = g_test_rand_int_range(1, iov->iov_len); + iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo); + iov_discard_undo(&undo); + assert(iov_equals(iov, iov_orig, iov_cnt)); + g_free(iov_orig); + iov_free(iov, iov_cnt); + + /* Discard entire first element */ + iov_random(&iov, &iov_cnt); + iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); + iov_tmp = iov; + iov_cnt_tmp = iov_cnt; + iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, iov->iov_len, &undo); + iov_discard_undo(&undo); + assert(iov_equals(iov, iov_orig, iov_cnt)); + g_free(iov_orig); + iov_free(iov, iov_cnt); + + /* Discard within second element */ + iov_random(&iov, &iov_cnt); + iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); + iov_tmp = iov; + iov_cnt_tmp = iov_cnt; + size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len); + iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo); + iov_discard_undo(&undo); + assert(iov_equals(iov, iov_orig, iov_cnt)); + g_free(iov_orig); + iov_free(iov, iov_cnt); +} + static void test_discard_back(void) { struct iovec *iov; @@ -404,6 +491,82 @@ static void test_discard_back(void) iov_free(iov, iov_cnt); } +static void test_discard_back_undo(void) +{ + IOVDiscardUndo undo; + struct iovec *iov; + struct iovec *iov_orig; + unsigned int iov_cnt; + unsigned int iov_cnt_tmp; + size_t size; + + /* Discard zero bytes */ + iov_random(&iov, &iov_cnt); + iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); + iov_cnt_tmp = iov_cnt; + iov_discard_back_undoable(iov, &iov_cnt_tmp, 0, &undo); + iov_discard_undo(&undo); + assert(iov_equals(iov, iov_orig, iov_cnt)); + g_free(iov_orig); + iov_free(iov, iov_cnt); + + /* Discard more bytes than vector size */ + iov_random(&iov, &iov_cnt); + iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); + iov_cnt_tmp = iov_cnt; + size = iov_size(iov, iov_cnt); + iov_discard_back_undoable(iov, &iov_cnt_tmp, size + 1, &undo); + iov_discard_undo(&undo); + assert(iov_equals(iov, iov_orig, iov_cnt)); + g_free(iov_orig); + iov_free(iov, iov_cnt); + + /* Discard entire vector */ + iov_random(&iov, &iov_cnt); + iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); + iov_cnt_tmp = iov_cnt; + size = iov_size(iov, iov_cnt); + iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo); + iov_discard_undo(&undo); + assert(iov_equals(iov, iov_orig, iov_cnt)); + g_free(iov_orig); + iov_free(iov, iov_cnt); + + /* Discard within last element */ + iov_random(&iov, &iov_cnt); + iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); + iov_cnt_tmp = iov_cnt; + size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len); + iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo); + iov_discard_undo(&undo); + assert(iov_equals(iov, iov_orig, iov_cnt)); + g_free(iov_orig); + iov_free(iov, iov_cnt); + + /* Discard entire last element */ + iov_random(&iov, &iov_cnt); + iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); + iov_cnt_tmp = iov_cnt; + size = iov[iov_cnt - 1].iov_len; + iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo); + iov_discard_undo(&undo); + assert(iov_equals(iov, iov_orig, iov_cnt)); + g_free(iov_orig); + iov_free(iov, iov_cnt); + + /* Discard within second-to-last element */ + iov_random(&iov, &iov_cnt); + iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); + iov_cnt_tmp = iov_cnt; + size = iov[iov_cnt - 1].iov_len + + g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len); + iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo); + iov_discard_undo(&undo); + assert(iov_equals(iov, iov_orig, iov_cnt)); + g_free(iov_orig); + iov_free(iov, iov_cnt); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); @@ -412,5 +575,7 @@ int main(int argc, char **argv) g_test_add_func("/basic/iov/io", test_io); g_test_add_func("/basic/iov/discard-front", test_discard_front); g_test_add_func("/basic/iov/discard-back", test_discard_back); + g_test_add_func("/basic/iov/discard-front-undo", test_discard_front_undo); + g_test_add_func("/basic/iov/discard-back-undo", test_discard_back_undo); return g_test_run(); } diff --git a/tests/test-keyval.c b/tests/test-keyval.c index e331a84149d3bfbb65aaca3c813f218fcf9d1dd2..ee927fe4e427154f1d14f9f47a16b33788e93861 100644 --- a/tests/test-keyval.c +++ b/tests/test-keyval.c @@ -27,27 +27,28 @@ static void test_keyval_parse(void) QDict *qdict, *sub_qdict; char long_key[129]; char *params; + bool help; /* Nothing */ - qdict = keyval_parse("", NULL, &error_abort); + qdict = keyval_parse("", NULL, NULL, &error_abort); g_assert_cmpuint(qdict_size(qdict), ==, 0); qobject_unref(qdict); /* Empty key (qemu_opts_parse() accepts this) */ - qdict = keyval_parse("=val", NULL, &err); + qdict = keyval_parse("=val", NULL, NULL, &err); error_free_or_abort(&err); g_assert(!qdict); /* Empty key fragment */ - qdict = keyval_parse(".", NULL, &err); + qdict = keyval_parse(".", NULL, NULL, &err); error_free_or_abort(&err); g_assert(!qdict); - qdict = keyval_parse("key.", NULL, &err); + qdict = keyval_parse("key.", NULL, NULL, &err); error_free_or_abort(&err); g_assert(!qdict); /* Invalid non-empty key (qemu_opts_parse() doesn't care) */ - qdict = keyval_parse("7up=val", NULL, &err); + qdict = keyval_parse("7up=val", NULL, NULL, &err); error_free_or_abort(&err); g_assert(!qdict); @@ -56,25 +57,25 @@ static void test_keyval_parse(void) long_key[127] = 'z'; long_key[128] = 0; params = g_strdup_printf("k.%s=v", long_key); - qdict = keyval_parse(params + 2, NULL, &err); + qdict = keyval_parse(params + 2, NULL, NULL, &err); error_free_or_abort(&err); g_assert(!qdict); /* Overlong key fragment */ - qdict = keyval_parse(params, NULL, &err); + qdict = keyval_parse(params, NULL, NULL, &err); error_free_or_abort(&err); g_assert(!qdict); g_free(params); /* Long key (qemu_opts_parse() accepts and truncates silently) */ params = g_strdup_printf("k.%s=v", long_key + 1); - qdict = keyval_parse(params + 2, NULL, &error_abort); + qdict = keyval_parse(params + 2, NULL, NULL, &error_abort); g_assert_cmpuint(qdict_size(qdict), ==, 1); g_assert_cmpstr(qdict_get_try_str(qdict, long_key + 1), ==, "v"); qobject_unref(qdict); /* Long key fragment */ - qdict = keyval_parse(params, NULL, &error_abort); + qdict = keyval_parse(params, NULL, NULL, &error_abort); g_assert_cmpuint(qdict_size(qdict), ==, 1); sub_qdict = qdict_get_qdict(qdict, "k"); g_assert(sub_qdict); @@ -84,25 +85,25 @@ static void test_keyval_parse(void) g_free(params); /* Crap after valid key */ - qdict = keyval_parse("key[0]=val", NULL, &err); + qdict = keyval_parse("key[0]=val", NULL, NULL, &err); error_free_or_abort(&err); g_assert(!qdict); /* Multiple keys, last one wins */ - qdict = keyval_parse("a=1,b=2,,x,a=3", NULL, &error_abort); + qdict = keyval_parse("a=1,b=2,,x,a=3", NULL, NULL, &error_abort); g_assert_cmpuint(qdict_size(qdict), ==, 2); g_assert_cmpstr(qdict_get_try_str(qdict, "a"), ==, "3"); g_assert_cmpstr(qdict_get_try_str(qdict, "b"), ==, "2,x"); qobject_unref(qdict); /* Even when it doesn't in qemu_opts_parse() */ - qdict = keyval_parse("id=foo,id=bar", NULL, &error_abort); + qdict = keyval_parse("id=foo,id=bar", NULL, NULL, &error_abort); g_assert_cmpuint(qdict_size(qdict), ==, 1); g_assert_cmpstr(qdict_get_try_str(qdict, "id"), ==, "bar"); qobject_unref(qdict); /* Dotted keys */ - qdict = keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL, &error_abort); + qdict = keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL, NULL, &error_abort); g_assert_cmpuint(qdict_size(qdict), ==, 2); sub_qdict = qdict_get_qdict(qdict, "a"); g_assert(sub_qdict); @@ -115,48 +116,48 @@ static void test_keyval_parse(void) qobject_unref(qdict); /* Inconsistent dotted keys */ - qdict = keyval_parse("a.b=1,a=2", NULL, &err); + qdict = keyval_parse("a.b=1,a=2", NULL, NULL, &err); error_free_or_abort(&err); g_assert(!qdict); - qdict = keyval_parse("a.b=1,a.b.c=2", NULL, &err); + qdict = keyval_parse("a.b=1,a.b.c=2", NULL, NULL, &err); error_free_or_abort(&err); g_assert(!qdict); /* Trailing comma is ignored */ - qdict = keyval_parse("x=y,", NULL, &error_abort); + qdict = keyval_parse("x=y,", NULL, NULL, &error_abort); g_assert_cmpuint(qdict_size(qdict), ==, 1); g_assert_cmpstr(qdict_get_try_str(qdict, "x"), ==, "y"); qobject_unref(qdict); /* Except when it isn't */ - qdict = keyval_parse(",", NULL, &err); + qdict = keyval_parse(",", NULL, NULL, &err); error_free_or_abort(&err); g_assert(!qdict); /* Value containing ,id= not misinterpreted as qemu_opts_parse() does */ - qdict = keyval_parse("x=,,id=bar", NULL, &error_abort); + qdict = keyval_parse("x=,,id=bar", NULL, NULL, &error_abort); g_assert_cmpuint(qdict_size(qdict), ==, 1); g_assert_cmpstr(qdict_get_try_str(qdict, "x"), ==, ",id=bar"); qobject_unref(qdict); /* Anti-social ID is left to caller (qemu_opts_parse() rejects it) */ - qdict = keyval_parse("id=666", NULL, &error_abort); + qdict = keyval_parse("id=666", NULL, NULL, &error_abort); g_assert_cmpuint(qdict_size(qdict), ==, 1); g_assert_cmpstr(qdict_get_try_str(qdict, "id"), ==, "666"); qobject_unref(qdict); /* Implied value not supported (unlike qemu_opts_parse()) */ - qdict = keyval_parse("an,noaus,noaus=", NULL, &err); + qdict = keyval_parse("an,noaus,noaus=", NULL, NULL, &err); error_free_or_abort(&err); g_assert(!qdict); /* Implied value, key "no" (qemu_opts_parse(): negated empty key) */ - qdict = keyval_parse("no", NULL, &err); + qdict = keyval_parse("no", NULL, NULL, &err); error_free_or_abort(&err); g_assert(!qdict); /* Implied key */ - qdict = keyval_parse("an,aus=off,noaus=", "implied", &error_abort); + qdict = keyval_parse("an,aus=off,noaus=", "implied", NULL, &error_abort); g_assert_cmpuint(qdict_size(qdict), ==, 3); g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "an"); g_assert_cmpstr(qdict_get_try_str(qdict, "aus"), ==, "off"); @@ -164,7 +165,7 @@ static void test_keyval_parse(void) qobject_unref(qdict); /* Implied dotted key */ - qdict = keyval_parse("val", "eins.zwei", &error_abort); + qdict = keyval_parse("val", "eins.zwei", NULL, &error_abort); g_assert_cmpuint(qdict_size(qdict), ==, 1); sub_qdict = qdict_get_qdict(qdict, "eins"); g_assert(sub_qdict); @@ -173,19 +174,81 @@ static void test_keyval_parse(void) qobject_unref(qdict); /* Implied key with empty value (qemu_opts_parse() accepts this) */ - qdict = keyval_parse(",", "implied", &err); + qdict = keyval_parse(",", "implied", NULL, &err); error_free_or_abort(&err); g_assert(!qdict); /* Likewise (qemu_opts_parse(): implied key with comma value) */ - qdict = keyval_parse(",,,a=1", "implied", &err); + qdict = keyval_parse(",,,a=1", "implied", NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + + /* Implied key's value can't have comma (qemu_opts_parse(): it can) */ + qdict = keyval_parse("val,,ue", "implied", NULL, &err); error_free_or_abort(&err); g_assert(!qdict); /* Empty key is not an implied key */ - qdict = keyval_parse("=val", "implied", &err); + qdict = keyval_parse("=val", "implied", NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + + /* "help" by itself, without implied key */ + qdict = keyval_parse("help", NULL, &help, &error_abort); + g_assert_cmpuint(qdict_size(qdict), ==, 0); + g_assert(help); + qobject_unref(qdict); + + /* "help" by itself, with implied key */ + qdict = keyval_parse("help", "implied", &help, &error_abort); + g_assert_cmpuint(qdict_size(qdict), ==, 0); + g_assert(help); + qobject_unref(qdict); + + /* "help" when no help is available, without implied key */ + qdict = keyval_parse("help", NULL, NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + + /* "help" when no help is available, with implied key */ + qdict = keyval_parse("help", "implied", NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + + /* Key "help" */ + qdict = keyval_parse("help=on", NULL, &help, &error_abort); + g_assert_cmpuint(qdict_size(qdict), ==, 1); + g_assert_cmpstr(qdict_get_try_str(qdict, "help"), ==, "on"); + g_assert(!help); + qobject_unref(qdict); + + /* "help" followed by crap, without implied key */ + qdict = keyval_parse("help.abc", NULL, &help, &err); error_free_or_abort(&err); g_assert(!qdict); + + /* "help" followed by crap, with implied key */ + qdict = keyval_parse("help.abc", "implied", &help, &err); + g_assert_cmpuint(qdict_size(qdict), ==, 1); + g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "help.abc"); + g_assert(!help); + qobject_unref(qdict); + + /* "help" with other stuff, without implied key */ + qdict = keyval_parse("number=42,help,foo=bar", NULL, &help, &error_abort); + g_assert_cmpuint(qdict_size(qdict), ==, 2); + g_assert_cmpstr(qdict_get_try_str(qdict, "number"), ==, "42"); + g_assert_cmpstr(qdict_get_try_str(qdict, "foo"), ==, "bar"); + g_assert(help); + qobject_unref(qdict); + + /* "help" with other stuff, with implied key */ + qdict = keyval_parse("val,help,foo=bar", "implied", &help, &error_abort); + g_assert_cmpuint(qdict_size(qdict), ==, 2); + g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "val"); + g_assert_cmpstr(qdict_get_try_str(qdict, "foo"), ==, "bar"); + g_assert(help); + qobject_unref(qdict); } static void check_list012(QList *qlist) @@ -210,26 +273,26 @@ static void test_keyval_parse_list(void) QDict *qdict, *sub_qdict; /* Root can't be a list */ - qdict = keyval_parse("0=1", NULL, &err); + qdict = keyval_parse("0=1", NULL, NULL, &err); error_free_or_abort(&err); g_assert(!qdict); /* List elements need not be in order */ - qdict = keyval_parse("list.0=null,list.2=zwei,list.1=eins", - NULL, &error_abort); + qdict = keyval_parse("list.0=null,list.2=zwei,list.1=eins", NULL, NULL, + &error_abort); g_assert_cmpint(qdict_size(qdict), ==, 1); check_list012(qdict_get_qlist(qdict, "list")); qobject_unref(qdict); /* Multiple indexes, last one wins */ qdict = keyval_parse("list.1=goner,list.0=null,list.01=eins,list.2=zwei", - NULL, &error_abort); + NULL, NULL, &error_abort); g_assert_cmpint(qdict_size(qdict), ==, 1); check_list012(qdict_get_qlist(qdict, "list")); qobject_unref(qdict); /* List at deeper nesting */ - qdict = keyval_parse("a.list.1=eins,a.list.00=null,a.list.2=zwei", + qdict = keyval_parse("a.list.1=eins,a.list.00=null,a.list.2=zwei", NULL, NULL, &error_abort); g_assert_cmpint(qdict_size(qdict), ==, 1); sub_qdict = qdict_get_qdict(qdict, "a"); @@ -238,18 +301,19 @@ static void test_keyval_parse_list(void) qobject_unref(qdict); /* Inconsistent dotted keys: both list and dictionary */ - qdict = keyval_parse("a.b.c=1,a.b.0=2", NULL, &err); + qdict = keyval_parse("a.b.c=1,a.b.0=2", NULL, NULL, &err); error_free_or_abort(&err); g_assert(!qdict); - qdict = keyval_parse("a.0.c=1,a.b.c=2", NULL, &err); + qdict = keyval_parse("a.0.c=1,a.b.c=2", NULL, NULL, &err); error_free_or_abort(&err); g_assert(!qdict); /* Missing list indexes */ - qdict = keyval_parse("list.1=lonely", NULL, &err); + qdict = keyval_parse("list.1=lonely", NULL, NULL, &err); error_free_or_abort(&err); g_assert(!qdict); - qdict = keyval_parse("list.0=null,list.2=eins,list.02=zwei", NULL, &err); + qdict = keyval_parse("list.0=null,list.2=eins,list.02=zwei", NULL, NULL, + &err); error_free_or_abort(&err); g_assert(!qdict); } @@ -261,7 +325,7 @@ static void test_keyval_visit_bool(void) QDict *qdict; bool b; - qdict = keyval_parse("bool1=on,bool2=off", NULL, &error_abort); + qdict = keyval_parse("bool1=on,bool2=off", NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -273,7 +337,7 @@ static void test_keyval_visit_bool(void) visit_end_struct(v, NULL); visit_free(v); - qdict = keyval_parse("bool1=offer", NULL, &error_abort); + qdict = keyval_parse("bool1=offer", NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -291,7 +355,7 @@ static void test_keyval_visit_number(void) uint64_t u; /* Lower limit zero */ - qdict = keyval_parse("number1=0", NULL, &error_abort); + qdict = keyval_parse("number1=0", NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -302,7 +366,7 @@ static void test_keyval_visit_number(void) visit_free(v); /* Upper limit 2^64-1 */ - qdict = keyval_parse("number1=18446744073709551615,number2=-1", + qdict = keyval_parse("number1=18446744073709551615,number2=-1", NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); @@ -316,8 +380,8 @@ static void test_keyval_visit_number(void) visit_free(v); /* Above upper limit */ - qdict = keyval_parse("number1=18446744073709551616", - NULL, &error_abort); + qdict = keyval_parse("number1=18446744073709551616", NULL, NULL, + &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -327,8 +391,8 @@ static void test_keyval_visit_number(void) visit_free(v); /* Below lower limit */ - qdict = keyval_parse("number1=-18446744073709551616", - NULL, &error_abort); + qdict = keyval_parse("number1=-18446744073709551616", NULL, NULL, + &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -338,8 +402,7 @@ static void test_keyval_visit_number(void) visit_free(v); /* Hex and octal */ - qdict = keyval_parse("number1=0x2a,number2=052", - NULL, &error_abort); + qdict = keyval_parse("number1=0x2a,number2=052", NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -352,8 +415,7 @@ static void test_keyval_visit_number(void) visit_free(v); /* Trailing crap */ - qdict = keyval_parse("number1=3.14,number2=08", - NULL, &error_abort); + qdict = keyval_parse("number1=3.14,number2=08", NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -373,7 +435,7 @@ static void test_keyval_visit_size(void) uint64_t sz; /* Lower limit zero */ - qdict = keyval_parse("sz1=0", NULL, &error_abort); + qdict = keyval_parse("sz1=0", NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -389,7 +451,7 @@ static void test_keyval_visit_size(void) qdict = keyval_parse("sz1=9007199254740991," "sz2=9007199254740992," "sz3=9007199254740993", - NULL, &error_abort); + NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -406,7 +468,7 @@ static void test_keyval_visit_size(void) /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */ qdict = keyval_parse("sz1=9223372036854774784," /* 7ffffffffffffc00 */ "sz2=9223372036854775295", /* 7ffffffffffffdff */ - NULL, &error_abort); + NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -421,7 +483,7 @@ static void test_keyval_visit_size(void) /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */ qdict = keyval_parse("sz1=18446744073709549568," /* fffffffffffff800 */ "sz2=18446744073709550591", /* fffffffffffffbff */ - NULL, &error_abort); + NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -436,7 +498,7 @@ static void test_keyval_visit_size(void) /* Beyond limits */ qdict = keyval_parse("sz1=-1," "sz2=18446744073709550592", /* fffffffffffffc00 */ - NULL, &error_abort); + NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -449,7 +511,7 @@ static void test_keyval_visit_size(void) /* Suffixes */ qdict = keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.1G,sz5=16777215T", - NULL, &error_abort); + NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -468,7 +530,7 @@ static void test_keyval_visit_size(void) visit_free(v); /* Beyond limit with suffix */ - qdict = keyval_parse("sz1=16777216T", NULL, &error_abort); + qdict = keyval_parse("sz1=16777216T", NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -478,7 +540,7 @@ static void test_keyval_visit_size(void) visit_free(v); /* Trailing crap */ - qdict = keyval_parse("sz1=0Z,sz2=16Gi", NULL, &error_abort); + qdict = keyval_parse("sz1=0Z,sz2=16Gi", NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -497,7 +559,7 @@ static void test_keyval_visit_dict(void) QDict *qdict; int64_t i; - qdict = keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL, &error_abort); + qdict = keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -515,7 +577,7 @@ static void test_keyval_visit_dict(void) visit_end_struct(v, NULL); visit_free(v); - qdict = keyval_parse("a.b=", NULL, &error_abort); + qdict = keyval_parse("a.b=", NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -537,7 +599,7 @@ static void test_keyval_visit_list(void) QDict *qdict; char *s; - qdict = keyval_parse("a.0=,a.1=I,a.2.0=II", NULL, &error_abort); + qdict = keyval_parse("a.0=,a.1=I,a.2.0=II", NULL, NULL, &error_abort); /* TODO empty list */ v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); @@ -561,7 +623,7 @@ static void test_keyval_visit_list(void) visit_end_struct(v, NULL); visit_free(v); - qdict = keyval_parse("a.0=,b.0.0=head", NULL, &error_abort); + qdict = keyval_parse("a.0=,b.0.0=head", NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -590,7 +652,7 @@ static void test_keyval_visit_optional(void) bool present; int64_t i; - qdict = keyval_parse("a.b=1", NULL, &error_abort); + qdict = keyval_parse("a.b=1", NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -626,7 +688,7 @@ static void test_keyval_visit_alternate(void) * the string variant if there is one, else an error. * TODO make it work for unambiguous cases like AltEnumBool below */ - qdict = keyval_parse("a=1,b=2,c=on", NULL, &error_abort); + qdict = keyval_parse("a=1,b=2,c=on", NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); @@ -650,7 +712,7 @@ static void test_keyval_visit_any(void) QList *qlist; QString *qstr; - qdict = keyval_parse("a.0=null,a.1=1", NULL, &error_abort); + qdict = keyval_parse("a.0=null,a.1=1", NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); diff --git a/tests/test-logging.c b/tests/test-logging.c index 8580b824202b7672282b6ae389e011ab193c4888..ccb819f193d9b5b6da6985eeb5bdfbe19b97eed4 100644 --- a/tests/test-logging.c +++ b/tests/test-logging.c @@ -113,7 +113,6 @@ static void test_logfile_write(gconstpointer data) QemuLogFile *logfile; QemuLogFile *logfile2; gchar const *dir = data; - Error *err = NULL; g_autofree gchar *file_path = NULL; g_autofree gchar *file_path1 = NULL; FILE *orig_fd; @@ -132,19 +131,17 @@ static void test_logfile_write(gconstpointer data) * Test that even if an open file handle is changed, * our handle remains valid due to RCU. */ - qemu_set_log_filename(file_path, &err); - g_assert(!err); + qemu_set_log_filename(file_path, &error_abort); rcu_read_lock(); - logfile = atomic_rcu_read(&qemu_logfile); + logfile = qatomic_rcu_read(&qemu_logfile); orig_fd = logfile->fd; g_assert(logfile && logfile->fd); fprintf(logfile->fd, "%s 1st write to file\n", __func__); fflush(logfile->fd); /* Change the logfile and ensure that the handle is still valid. */ - qemu_set_log_filename(file_path1, &err); - g_assert(!err); - logfile2 = atomic_rcu_read(&qemu_logfile); + qemu_set_log_filename(file_path1, &error_abort); + logfile2 = qatomic_rcu_read(&qemu_logfile); g_assert(logfile->fd == orig_fd); g_assert(logfile2->fd != logfile->fd); fprintf(logfile->fd, "%s 2nd write to file\n", __func__); @@ -156,7 +153,6 @@ static void test_logfile_lock(gconstpointer data) { FILE *logfile; gchar const *dir = data; - Error *err = NULL; g_autofree gchar *file_path = NULL; file_path = g_build_filename(dir, "qemu_test_logfile_lock0.log", NULL); @@ -166,7 +162,7 @@ static void test_logfile_lock(gconstpointer data) * that even if an open file handle is closed, * our handle remains valid for use due to RCU. */ - qemu_set_log_filename(file_path, &err); + qemu_set_log_filename(file_path, &error_abort); logfile = qemu_log_lock(); g_assert(logfile); fprintf(logfile, "%s 1st write to file\n", __func__); @@ -180,8 +176,6 @@ static void test_logfile_lock(gconstpointer data) fprintf(logfile, "%s 2nd write to file\n", __func__); fflush(logfile); qemu_log_unlock(logfile); - - g_assert(!err); } /* Remove a directory and all its entries (non-recursive). */ @@ -202,7 +196,7 @@ static void rmdir_full(gchar const *root) int main(int argc, char **argv) { - gchar *tmp_path = g_dir_make_tmp("qemu-test-logging.XXXXXX", NULL); + g_autofree gchar *tmp_path = g_dir_make_tmp("qemu-test-logging.XXXXXX", NULL); int rc; g_test_init(&argc, &argv, NULL); @@ -216,8 +210,9 @@ int main(int argc, char **argv) tmp_path, test_logfile_lock); rc = g_test_run(); + qemu_log_close(); + drain_call_rcu(); rmdir_full(tmp_path); - g_free(tmp_path); return rc; } diff --git a/tests/test-qdev-global-props.c b/tests/test-qdev-global-props.c index 42d3dd703051ebadf4b5915f43f4b76391fd219d..c8862cac5fef640379d097d16a8e7c8beca70139 100644 --- a/tests/test-qdev-global-props.c +++ b/tests/test-qdev-global-props.c @@ -26,23 +26,25 @@ #include "hw/qdev-properties.h" #include "qom/object.h" +#include "qapi/error.h" #include "qapi/visitor.h" #define TYPE_STATIC_PROPS "static_prop_type" -#define STATIC_TYPE(obj) \ - OBJECT_CHECK(MyType, (obj), TYPE_STATIC_PROPS) +typedef struct MyType MyType; +DECLARE_INSTANCE_CHECKER(MyType, STATIC_TYPE, + TYPE_STATIC_PROPS) #define TYPE_SUBCLASS "static_prop_subtype" #define PROP_DEFAULT 100 -typedef struct MyType { +struct MyType { DeviceState parent_obj; uint32_t prop1; uint32_t prop2; -} MyType; +}; static Property static_props[] = { DEFINE_PROP_UINT32("prop1", MyType, prop1, PROP_DEFAULT), @@ -76,7 +78,7 @@ static void test_static_prop_subprocess(void) MyType *mt; mt = STATIC_TYPE(object_new(TYPE_STATIC_PROPS)); - qdev_init_nofail(DEVICE(mt)); + qdev_realize(DEVICE(mt), NULL, &error_fatal); g_assert_cmpuint(mt->prop1, ==, PROP_DEFAULT); } @@ -111,7 +113,7 @@ static void test_static_globalprop_subprocess(void) register_global_properties(props); mt = STATIC_TYPE(object_new(TYPE_STATIC_PROPS)); - qdev_init_nofail(DEVICE(mt)); + qdev_realize(DEVICE(mt), NULL, &error_fatal); g_assert_cmpuint(mt->prop1, ==, 200); g_assert_cmpuint(mt->prop2, ==, PROP_DEFAULT); @@ -126,8 +128,8 @@ static void test_static_globalprop(void) } #define TYPE_DYNAMIC_PROPS "dynamic-prop-type" -#define DYNAMIC_TYPE(obj) \ - OBJECT_CHECK(MyType, (obj), TYPE_DYNAMIC_PROPS) +DECLARE_INSTANCE_CHECKER(MyType, DYNAMIC_TYPE, + TYPE_DYNAMIC_PROPS) #define TYPE_UNUSED_HOTPLUG "hotplug-type" #define TYPE_UNUSED_NOHOTPLUG "nohotplug-type" @@ -229,7 +231,7 @@ static void test_dynamic_globalprop_subprocess(void) register_global_properties(props); mt = DYNAMIC_TYPE(object_new(TYPE_DYNAMIC_PROPS)); - qdev_init_nofail(DEVICE(mt)); + qdev_realize(DEVICE(mt), NULL, &error_fatal); g_assert_cmpuint(mt->prop1, ==, 101); g_assert_cmpuint(mt->prop2, ==, 102); @@ -249,10 +251,13 @@ static void test_dynamic_globalprop(void) g_test_trap_assert_passed(); g_test_trap_assert_stderr_unmatched("*prop1*"); g_test_trap_assert_stderr_unmatched("*prop2*"); - g_test_trap_assert_stderr("*warning: global dynamic-prop-type-bad.prop3 has invalid class name\n*"); + g_test_trap_assert_stderr( + "*warning: global dynamic-prop-type-bad.prop3 has invalid class name*"); g_test_trap_assert_stderr_unmatched("*prop4*"); - g_test_trap_assert_stderr("*warning: global nohotplug-type.prop5=105 not used\n*"); - g_test_trap_assert_stderr("*warning: global nondevice-type.prop6 has invalid class name\n*"); + g_test_trap_assert_stderr( + "*warning: global nohotplug-type.prop5=105 not used*"); + g_test_trap_assert_stderr( + "*warning: global nondevice-type.prop6 has invalid class name*"); g_test_trap_assert_stdout(""); } @@ -272,7 +277,7 @@ static void test_subclass_global_props(void) register_global_properties(props); mt = STATIC_TYPE(object_new(TYPE_SUBCLASS)); - qdev_init_nofail(DEVICE(mt)); + qdev_realize(DEVICE(mt), NULL, &error_fatal); g_assert_cmpuint(mt->prop1, ==, 102); g_assert_cmpuint(mt->prop2, ==, 104); diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c index 2a0f42a09b01bd556e7e270ae1b5fafff2863001..297ffe79ddb4de150fbd2ebbe6aa9fa2e37a904a 100644 --- a/tests/test-qemu-opts.c +++ b/tests/test-qemu-opts.c @@ -187,7 +187,6 @@ static void test_qemu_opt_get(void) static void test_qemu_opt_get_bool(void) { - Error *err = NULL; QemuOptsList *list; QemuOpts *opts; bool opt; @@ -210,16 +209,14 @@ static void test_qemu_opt_get_bool(void) opt = qemu_opt_get_bool(opts, "bool1", false); g_assert(opt == false); - qemu_opt_set_bool(opts, "bool1", true, &err); - g_assert(!err); + qemu_opt_set_bool(opts, "bool1", true, &error_abort); /* now we have set bool1, should know about it */ opt = qemu_opt_get_bool(opts, "bool1", false); g_assert(opt == true); /* having reset the value, opt should be the reset one not defval */ - qemu_opt_set_bool(opts, "bool1", false, &err); - g_assert(!err); + qemu_opt_set_bool(opts, "bool1", false, &error_abort); opt = qemu_opt_get_bool(opts, "bool1", true); g_assert(opt == false); @@ -233,7 +230,6 @@ static void test_qemu_opt_get_bool(void) static void test_qemu_opt_get_number(void) { - Error *err = NULL; QemuOptsList *list; QemuOpts *opts; uint64_t opt; @@ -256,16 +252,14 @@ static void test_qemu_opt_get_number(void) opt = qemu_opt_get_number(opts, "number1", 5); g_assert(opt == 5); - qemu_opt_set_number(opts, "number1", 10, &err); - g_assert(!err); + qemu_opt_set_number(opts, "number1", 10, &error_abort); /* now we have set number1, should know about it */ opt = qemu_opt_get_number(opts, "number1", 5); g_assert(opt == 10); /* having reset it, the returned should be the reset one not defval */ - qemu_opt_set_number(opts, "number1", 15, &err); - g_assert(!err); + qemu_opt_set_number(opts, "number1", 15, &error_abort); opt = qemu_opt_get_number(opts, "number1", 5); g_assert(opt == 15); @@ -367,7 +361,6 @@ static void test_qemu_opt_unset(void) static void test_qemu_opts_reset(void) { - Error *err = NULL; QemuOptsList *list; QemuOpts *opts; uint64_t opt; @@ -390,8 +383,7 @@ static void test_qemu_opts_reset(void) opt = qemu_opt_get_number(opts, "number1", 5); g_assert(opt == 5); - qemu_opt_set_number(opts, "number1", 10, &err); - g_assert(!err); + qemu_opt_set_number(opts, "number1", 10, &error_abort); /* now we have set number1, should know about it */ opt = qemu_opt_get_number(opts, "number1", 5); @@ -406,7 +398,6 @@ static void test_qemu_opts_reset(void) static void test_qemu_opts_set(void) { - Error *err = NULL; QemuOptsList *list; QemuOpts *opts; const char *opt; @@ -421,8 +412,7 @@ static void test_qemu_opts_set(void) g_assert(opts == NULL); /* implicitly create opts and set str3 value */ - qemu_opts_set(list, NULL, "str3", "value", &err); - g_assert(!err); + qemu_opts_set(list, NULL, "str3", "value", &error_abort); g_assert(!QTAILQ_EMPTY(&list->head)); /* get the just created opts */ diff --git a/tests/test-qga.c b/tests/test-qga.c index d2b2435bb46e28181866a3704ad10803402cb210..c1b173b3cb21bc5bd939f870ee6bc1cfea0db850 100644 --- a/tests/test-qga.c +++ b/tests/test-qga.c @@ -4,7 +4,7 @@ #include #include -#include "libqtest.h" +#include "qtest/libqos/libqtest.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qlist.h" @@ -61,8 +61,8 @@ fixture_setup(TestFixture *fixture, gconstpointer data, gchar **envp) path = g_build_filename(fixture->test_dir, "sock", NULL); cwd = g_get_current_dir(); - cmd = g_strdup_printf("%s%cqemu-ga -m unix-listen -t %s -p %s %s %s", - cwd, G_DIR_SEPARATOR, + cmd = g_strdup_printf("%s%cqga%cqemu-ga -m unix-listen -t %s -p %s %s %s", + cwd, G_DIR_SEPARATOR, G_DIR_SEPARATOR, fixture->test_dir, path, getenv("QTEST_LOG") ? "-v" : "", extra_arg ?: ""); @@ -246,7 +246,7 @@ static void test_qga_invalid_oob(gconstpointer fix) ret = qmp_fd(fixture->fd, "{'exec-oob': 'guest-ping'}"); g_assert_nonnull(ret); - qmp_assert_error_class(ret, "GenericError"); + qmp_expect_error_and_unref(ret, "GenericError"); } static void test_qga_invalid_args(gconstpointer fix) @@ -699,8 +699,8 @@ static void test_qga_config(gconstpointer data) GKeyFile *kf; cwd = g_get_current_dir(); - cmd = g_strdup_printf("%s%cqemu-ga -D", - cwd, G_DIR_SEPARATOR); + cmd = g_strdup_printf("%s%cqga%cqemu-ga -D", + cwd, G_DIR_SEPARATOR, G_DIR_SEPARATOR); g_free(cwd); g_shell_parse_argv(cmd, NULL, &argv, &error); g_free(cmd); diff --git a/tests/test-qgraph.c b/tests/test-qgraph.c index 5c7e457075fec4b19b00eb5d7dd98bafef4447dd..ae2f7b2dd8312c3006920b52cd5da0e5f8d18428 100644 --- a/tests/test-qgraph.c +++ b/tests/test-qgraph.c @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. + * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -17,9 +17,8 @@ */ #include "qemu/osdep.h" -#include "libqtest.h" -#include "libqos/qgraph.h" -#include "libqos/qgraph_internal.h" +#include "qtest/libqos/qgraph.h" +#include "qtest/libqos/qgraph_internal.h" #define MACHINE_PC "x86_64/pc" #define MACHINE_RASPI2 "arm/raspi2" diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index d12ff47e26ab32fa9586fb35cb64b53fbef02af5..d3413bfef0ba17dac4816c8bf5efa42983616c56 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -36,6 +36,10 @@ void qmp_cmd_success_response(Error **errp) { } +void qmp_coroutine_cmd(Error **errp) +{ +} + Empty2 *qmp_user_def_cmd0(Error **errp) { return g_new0(Empty2, 1); @@ -152,7 +156,7 @@ static QObject *do_qmp_dispatch(bool allow_oob, const char *template, ...) req = qdict_from_vjsonf_nofail(template, ap); va_end(ap); - resp = qmp_dispatch(&qmp_commands, QOBJECT(req), allow_oob); + resp = qmp_dispatch(&qmp_commands, QOBJECT(req), allow_oob, NULL); g_assert(resp); ret = qdict_get(resp, "return"); g_assert(ret); @@ -175,7 +179,7 @@ static void do_qmp_dispatch_error(bool allow_oob, ErrorClass cls, req = qdict_from_vjsonf_nofail(template, ap); va_end(ap); - resp = qmp_dispatch(&qmp_commands, QOBJECT(req), allow_oob); + resp = qmp_dispatch(&qmp_commands, QOBJECT(req), allow_oob, NULL); g_assert(resp); error = qdict_get_qdict(resp, "error"); g_assert(error); @@ -231,7 +235,7 @@ static void test_dispatch_cmd_success_response(void) QDict *resp; qdict_put_str(req, "execute", "cmd-success-response"); - resp = qmp_dispatch(&qmp_commands, QOBJECT(req), false); + resp = qmp_dispatch(&qmp_commands, QOBJECT(req), false, NULL); g_assert_null(resp); qobject_unref(req); } diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c index 6bacabf063222b62d22c40bd09b1c79b72100fe8..e41b91a2a6fe71646aa74a17181ec93b3ff3cfeb 100644 --- a/tests/test-qobject-input-visitor.c +++ b/tests/test-qobject-input-visitor.c @@ -417,7 +417,7 @@ static void test_visitor_in_struct(TestInputVisitorData *data, static void test_visitor_in_struct_nested(TestInputVisitorData *data, const void *unused) { - UserDefTwo *udp = NULL; + g_autoptr(UserDefTwo) udp = NULL; Visitor *v; v = visitor_input_test_init(data, "{ 'string0': 'string0', " @@ -433,8 +433,6 @@ static void test_visitor_in_struct_nested(TestInputVisitorData *data, g_assert_cmpstr(udp->dict1->dict2->userdef->string, ==, "string"); g_assert_cmpstr(udp->dict1->dict2->string, ==, "string2"); g_assert(udp->dict1->has_dict3 == false); - - qapi_free_UserDefTwo(udp); } static void test_visitor_in_list(TestInputVisitorData *data, @@ -546,7 +544,7 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data, const void *unused) { Visitor *v; - UserDefFlatUnion *tmp; + g_autoptr(UserDefFlatUnion) tmp = NULL; UserDefUnionBase *base; v = visitor_input_test_init(data, @@ -563,8 +561,6 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data, base = qapi_UserDefFlatUnion_base(tmp); g_assert(&base->enum1 == &tmp->enum1); - - qapi_free_UserDefFlatUnion(tmp); } static void test_visitor_in_alternate(TestInputVisitorData *data, @@ -690,7 +686,7 @@ static void test_list_union_integer_helper(TestInputVisitorData *data, const void *unused, UserDefListUnionKind kind) { - UserDefListUnion *cvalue = NULL; + g_autoptr(UserDefListUnion) cvalue = NULL; Visitor *v; GString *gstr_list = g_string_new(""); GString *gstr_union = g_string_new(""); @@ -782,7 +778,6 @@ static void test_list_union_integer_helper(TestInputVisitorData *data, g_string_free(gstr_union, true); g_string_free(gstr_list, true); - qapi_free_UserDefListUnion(cvalue); } static void test_visitor_in_list_union_int(TestInputVisitorData *data, @@ -851,7 +846,7 @@ static void test_visitor_in_list_union_uint64(TestInputVisitorData *data, static void test_visitor_in_list_union_bool(TestInputVisitorData *data, const void *unused) { - UserDefListUnion *cvalue = NULL; + g_autoptr(UserDefListUnion) cvalue = NULL; boolList *elem = NULL; Visitor *v; GString *gstr_list = g_string_new(""); @@ -879,13 +874,12 @@ static void test_visitor_in_list_union_bool(TestInputVisitorData *data, g_string_free(gstr_union, true); g_string_free(gstr_list, true); - qapi_free_UserDefListUnion(cvalue); } static void test_visitor_in_list_union_string(TestInputVisitorData *data, const void *unused) { - UserDefListUnion *cvalue = NULL; + g_autoptr(UserDefListUnion) cvalue = NULL; strList *elem = NULL; Visitor *v; GString *gstr_list = g_string_new(""); @@ -914,7 +908,6 @@ static void test_visitor_in_list_union_string(TestInputVisitorData *data, g_string_free(gstr_union, true); g_string_free(gstr_list, true); - qapi_free_UserDefListUnion(cvalue); } #define DOUBLE_STR_MAX 16 @@ -922,7 +915,7 @@ static void test_visitor_in_list_union_string(TestInputVisitorData *data, static void test_visitor_in_list_union_number(TestInputVisitorData *data, const void *unused) { - UserDefListUnion *cvalue = NULL; + g_autoptr(UserDefListUnion) cvalue = NULL; numberList *elem = NULL; Visitor *v; GString *gstr_list = g_string_new(""); @@ -957,7 +950,6 @@ static void test_visitor_in_list_union_number(TestInputVisitorData *data, g_string_free(gstr_union, true); g_string_free(gstr_list, true); - qapi_free_UserDefListUnion(cvalue); } static void input_visitor_test_add(const char *testpath, @@ -1253,7 +1245,7 @@ static void test_visitor_in_fail_alternate(TestInputVisitorData *data, static void do_test_visitor_in_qmp_introspect(TestInputVisitorData *data, const QLitObject *qlit) { - SchemaInfoList *schema = NULL; + g_autoptr(SchemaInfoList) schema = NULL; QObject *obj = qobject_from_qlit(qlit); Visitor *v; @@ -1262,7 +1254,6 @@ static void do_test_visitor_in_qmp_introspect(TestInputVisitorData *data, visit_type_SchemaInfoList(v, NULL, &schema, &error_abort); g_assert(schema); - qapi_free_SchemaInfoList(schema); qobject_unref(obj); visit_free(v); } diff --git a/tests/test-rcu-list.c b/tests/test-rcu-list.c index 92be51ec505b2b231fd1d331f87cc3168539bd48..49641e193664a23313c413e3370c7b224b22bf32 100644 --- a/tests/test-rcu-list.c +++ b/tests/test-rcu-list.c @@ -106,7 +106,7 @@ static void reclaim_list_el(struct rcu_head *prcu) struct list_element *el = container_of(prcu, struct list_element, rcu); g_free(el); /* Accessed only from call_rcu thread. */ - atomic_set_i64(&n_reclaims, n_reclaims + 1); + qatomic_set_i64(&n_reclaims, n_reclaims + 1); } #if TEST_LIST_TYPE == 1 @@ -172,16 +172,16 @@ static void *rcu_q_reader(void *arg) rcu_register_thread(); *(struct rcu_reader_data **)arg = &rcu_reader; - atomic_inc(&nthreadsrunning); - while (atomic_read(&goflag) == GOFLAG_INIT) { + qatomic_inc(&nthreadsrunning); + while (qatomic_read(&goflag) == GOFLAG_INIT) { g_usleep(1000); } - while (atomic_read(&goflag) == GOFLAG_RUN) { + while (qatomic_read(&goflag) == GOFLAG_RUN) { rcu_read_lock(); TEST_LIST_FOREACH_RCU(el, &Q_list_head, entry) { n_reads_local++; - if (atomic_read(&goflag) == GOFLAG_STOP) { + if (qatomic_read(&goflag) == GOFLAG_STOP) { break; } } @@ -207,12 +207,12 @@ static void *rcu_q_updater(void *arg) struct list_element *el, *prev_el; *(struct rcu_reader_data **)arg = &rcu_reader; - atomic_inc(&nthreadsrunning); - while (atomic_read(&goflag) == GOFLAG_INIT) { + qatomic_inc(&nthreadsrunning); + while (qatomic_read(&goflag) == GOFLAG_INIT) { g_usleep(1000); } - while (atomic_read(&goflag) == GOFLAG_RUN) { + while (qatomic_read(&goflag) == GOFLAG_RUN) { target_el = select_random_el(RCU_Q_LEN); j = 0; /* FOREACH_RCU could work here but let's use both macros */ @@ -226,7 +226,7 @@ static void *rcu_q_updater(void *arg) break; } } - if (atomic_read(&goflag) == GOFLAG_STOP) { + if (qatomic_read(&goflag) == GOFLAG_STOP) { break; } target_el = select_random_el(RCU_Q_LEN); @@ -248,7 +248,7 @@ static void *rcu_q_updater(void *arg) qemu_mutex_lock(&counts_mutex); n_nodes += n_nodes_local; n_updates += n_updates_local; - atomic_set_i64(&n_nodes_removed, n_nodes_removed + n_removed_local); + qatomic_set_i64(&n_nodes_removed, n_nodes_removed + n_removed_local); qemu_mutex_unlock(&counts_mutex); return NULL; } @@ -271,13 +271,13 @@ static void rcu_qtest_init(void) static void rcu_qtest_run(int duration, int nreaders) { int nthreads = nreaders + 1; - while (atomic_read(&nthreadsrunning) < nthreads) { + while (qatomic_read(&nthreadsrunning) < nthreads) { g_usleep(1000); } - atomic_set(&goflag, GOFLAG_RUN); + qatomic_set(&goflag, GOFLAG_RUN); sleep(duration); - atomic_set(&goflag, GOFLAG_STOP); + qatomic_set(&goflag, GOFLAG_STOP); wait_all_threads(); } @@ -302,21 +302,23 @@ static void rcu_qtest(const char *test, int duration, int nreaders) n_removed_local++; } qemu_mutex_lock(&counts_mutex); - atomic_set_i64(&n_nodes_removed, n_nodes_removed + n_removed_local); + qatomic_set_i64(&n_nodes_removed, n_nodes_removed + n_removed_local); qemu_mutex_unlock(&counts_mutex); synchronize_rcu(); - while (atomic_read_i64(&n_nodes_removed) > atomic_read_i64(&n_reclaims)) { + while (qatomic_read_i64(&n_nodes_removed) > + qatomic_read_i64(&n_reclaims)) { g_usleep(100); synchronize_rcu(); } if (g_test_in_charge) { - g_assert_cmpint(atomic_read_i64(&n_nodes_removed), ==, - atomic_read_i64(&n_reclaims)); + g_assert_cmpint(qatomic_read_i64(&n_nodes_removed), ==, + qatomic_read_i64(&n_reclaims)); } else { printf("%s: %d readers; 1 updater; nodes read: " \ "%lld, nodes removed: %"PRIi64"; nodes reclaimed: %"PRIi64"\n", test, nthreadsrunning - 1, n_reads, - atomic_read_i64(&n_nodes_removed), atomic_read_i64(&n_reclaims)); + qatomic_read_i64(&n_nodes_removed), + qatomic_read_i64(&n_reclaims)); exit(0); } } diff --git a/tests/test-replication.c b/tests/test-replication.c index cbc37db2df68cf940bd45f9451a2403588ebaea9..b067240adddcfbe40070fc07b4a081677a208b0f 100644 --- a/tests/test-replication.c +++ b/tests/test-replication.c @@ -23,14 +23,14 @@ /* primary */ #define P_ID "primary-id" -static char p_local_disk[] = "/tmp/p_local_disk.XXXXXX"; +static char *p_local_disk; /* secondary */ #define S_ID "secondary-id" #define S_LOCAL_DISK_ID "secondary-local-disk-id" -static char s_local_disk[] = "/tmp/s_local_disk.XXXXXX"; -static char s_active_disk[] = "/tmp/s_active_disk.XXXXXX"; -static char s_hidden_disk[] = "/tmp/s_hidden_disk.XXXXXX"; +static char *s_local_disk; +static char *s_active_disk; +static char *s_hidden_disk; /* FIXME: steal from blockdev.c */ QemuOptsList qemu_drive_opts = { @@ -139,8 +139,6 @@ static void make_temp(char *template) static void prepare_imgs(void) { - Error *local_err = NULL; - make_temp(p_local_disk); make_temp(s_local_disk); make_temp(s_active_disk); @@ -148,19 +146,15 @@ static void prepare_imgs(void) /* Primary */ bdrv_img_create(p_local_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE, - BDRV_O_RDWR, true, &local_err); - g_assert(!local_err); + BDRV_O_RDWR, true, &error_abort); /* Secondary */ bdrv_img_create(s_local_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE, - BDRV_O_RDWR, true, &local_err); - g_assert(!local_err); + BDRV_O_RDWR, true, &error_abort); bdrv_img_create(s_active_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE, - BDRV_O_RDWR, true, &local_err); - g_assert(!local_err); + BDRV_O_RDWR, true, &error_abort); bdrv_img_create(s_hidden_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE, - BDRV_O_RDWR, true, &local_err); - g_assert(!local_err); + BDRV_O_RDWR, true, &error_abort); } static void cleanup_imgs(void) @@ -179,7 +173,6 @@ static BlockBackend *start_primary(void) BlockBackend *blk; QemuOpts *opts; QDict *qdict; - Error *local_err = NULL; char *cmdline; cmdline = g_strdup_printf("driver=replication,mode=primary,node-name=xxx," @@ -193,12 +186,10 @@ static BlockBackend *start_primary(void) qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off"); qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off"); - blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &local_err); + blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &error_abort); g_assert(blk); - g_assert(!local_err); - monitor_add_blk(blk, P_ID, &local_err); - g_assert(!local_err); + monitor_add_blk(blk, P_ID, &error_abort); qemu_opts_del(opts); @@ -248,12 +239,10 @@ static void test_primary_write(void) static void test_primary_start(void) { BlockBackend *blk = NULL; - Error *local_err = NULL; blk = start_primary(); - replication_start_all(REPLICATION_MODE_PRIMARY, &local_err); - g_assert(!local_err); + replication_start_all(REPLICATION_MODE_PRIMARY, &error_abort); /* read from 0 to IMG_SIZE */ test_blk_read(blk, 0, 0, IMG_SIZE, 0, IMG_SIZE, true); @@ -266,46 +255,35 @@ static void test_primary_start(void) static void test_primary_stop(void) { - Error *local_err = NULL; bool failover = true; start_primary(); - replication_start_all(REPLICATION_MODE_PRIMARY, &local_err); - g_assert(!local_err); + replication_start_all(REPLICATION_MODE_PRIMARY, &error_abort); - replication_stop_all(failover, &local_err); - g_assert(!local_err); + replication_stop_all(failover, &error_abort); teardown_primary(); } static void test_primary_do_checkpoint(void) { - Error *local_err = NULL; - start_primary(); - replication_start_all(REPLICATION_MODE_PRIMARY, &local_err); - g_assert(!local_err); + replication_start_all(REPLICATION_MODE_PRIMARY, &error_abort); - replication_do_checkpoint_all(&local_err); - g_assert(!local_err); + replication_do_checkpoint_all(&error_abort); teardown_primary(); } static void test_primary_get_error_all(void) { - Error *local_err = NULL; - start_primary(); - replication_start_all(REPLICATION_MODE_PRIMARY, &local_err); - g_assert(!local_err); + replication_start_all(REPLICATION_MODE_PRIMARY, &error_abort); - replication_get_error_all(&local_err); - g_assert(!local_err); + replication_get_error_all(&error_abort); teardown_primary(); } @@ -316,7 +294,6 @@ static BlockBackend *start_secondary(void) QDict *qdict; BlockBackend *blk; char *cmdline; - Error *local_err = NULL; /* add s_local_disk and forge S_LOCAL_DISK_ID */ cmdline = g_strdup_printf("file.filename=%s,driver=qcow2," @@ -329,10 +306,9 @@ static BlockBackend *start_secondary(void) qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off"); qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off"); - blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &local_err); + blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &error_abort); assert(blk); - monitor_add_blk(blk, S_LOCAL_DISK_ID, &local_err); - g_assert(!local_err); + monitor_add_blk(blk, S_LOCAL_DISK_ID, &error_abort); /* format s_local_disk with pattern "0x11" */ test_blk_write(blk, 0x11, 0, IMG_SIZE, false); @@ -356,10 +332,9 @@ static BlockBackend *start_secondary(void) qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off"); qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off"); - blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &local_err); + blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &error_abort); assert(blk); - monitor_add_blk(blk, S_ID, &local_err); - g_assert(!local_err); + monitor_add_blk(blk, S_ID, &error_abort); qemu_opts_del(opts); @@ -417,15 +392,14 @@ static void test_secondary_write(void) teardown_secondary(); } +#ifndef _WIN32 static void test_secondary_start(void) { BlockBackend *top_blk, *local_blk; - Error *local_err = NULL; bool failover = true; top_blk = start_secondary(); - replication_start_all(REPLICATION_MODE_SECONDARY, &local_err); - g_assert(!local_err); + replication_start_all(REPLICATION_MODE_SECONDARY, &error_abort); /* read from s_local_disk (0, IMG_SIZE) */ test_blk_read(top_blk, 0x11, 0, IMG_SIZE, 0, IMG_SIZE, false); @@ -446,8 +420,7 @@ static void test_secondary_start(void) 0, IMG_SIZE / 2, false); /* unblock top_bs */ - replication_stop_all(failover, &local_err); - g_assert(!local_err); + replication_stop_all(failover, &error_abort); teardown_secondary(); } @@ -456,12 +429,10 @@ static void test_secondary_start(void) static void test_secondary_stop(void) { BlockBackend *top_blk, *local_blk; - Error *local_err = NULL; bool failover = true; top_blk = start_secondary(); - replication_start_all(REPLICATION_MODE_SECONDARY, &local_err); - g_assert(!local_err); + replication_start_all(REPLICATION_MODE_SECONDARY, &error_abort); /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */ local_blk = blk_by_name(S_LOCAL_DISK_ID); @@ -475,8 +446,7 @@ static void test_secondary_stop(void) test_blk_write(top_blk, 0x33, 0, IMG_SIZE / 2, false); /* do active commit */ - replication_stop_all(failover, &local_err); - g_assert(!local_err); + replication_stop_all(failover, &error_abort); /* read from s_local_disk (0, IMG_SIZE / 2) */ test_blk_read(top_blk, 0x33, 0, IMG_SIZE / 2, @@ -493,11 +463,9 @@ static void test_secondary_stop(void) static void test_secondary_continuous_replication(void) { BlockBackend *top_blk, *local_blk; - Error *local_err = NULL; top_blk = start_secondary(); - replication_start_all(REPLICATION_MODE_SECONDARY, &local_err); - g_assert(!local_err); + replication_start_all(REPLICATION_MODE_SECONDARY, &error_abort); /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */ local_blk = blk_by_name(S_LOCAL_DISK_ID); @@ -511,22 +479,18 @@ static void test_secondary_continuous_replication(void) test_blk_write(top_blk, 0x33, 0, IMG_SIZE / 2, false); /* do failover (active commit) */ - replication_stop_all(true, &local_err); - g_assert(!local_err); + replication_stop_all(true, &error_abort); /* it should ignore all requests from now on */ /* start after failover */ - replication_start_all(REPLICATION_MODE_PRIMARY, &local_err); - g_assert(!local_err); + replication_start_all(REPLICATION_MODE_PRIMARY, &error_abort); /* checkpoint */ - replication_do_checkpoint_all(&local_err); - g_assert(!local_err); + replication_do_checkpoint_all(&error_abort); /* stop */ - replication_stop_all(true, &local_err); - g_assert(!local_err); + replication_stop_all(true, &error_abort); /* read from s_local_disk (0, IMG_SIZE / 2) */ test_blk_read(top_blk, 0x33, 0, IMG_SIZE / 2, @@ -543,12 +507,10 @@ static void test_secondary_continuous_replication(void) static void test_secondary_do_checkpoint(void) { BlockBackend *top_blk, *local_blk; - Error *local_err = NULL; bool failover = true; top_blk = start_secondary(); - replication_start_all(REPLICATION_MODE_SECONDARY, &local_err); - g_assert(!local_err); + replication_start_all(REPLICATION_MODE_SECONDARY, &error_abort); /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */ local_blk = blk_by_name(S_LOCAL_DISK_ID); @@ -559,38 +521,33 @@ static void test_secondary_do_checkpoint(void) test_blk_read(top_blk, 0x11, IMG_SIZE / 2, IMG_SIZE / 2, 0, IMG_SIZE, false); - replication_do_checkpoint_all(&local_err); - g_assert(!local_err); + replication_do_checkpoint_all(&error_abort); /* after checkpoint, read pattern 0x22 from s_local_disk */ test_blk_read(top_blk, 0x22, IMG_SIZE / 2, IMG_SIZE / 2, 0, IMG_SIZE, false); /* unblock top_bs */ - replication_stop_all(failover, &local_err); - g_assert(!local_err); + replication_stop_all(failover, &error_abort); teardown_secondary(); } static void test_secondary_get_error_all(void) { - Error *local_err = NULL; bool failover = true; start_secondary(); - replication_start_all(REPLICATION_MODE_SECONDARY, &local_err); - g_assert(!local_err); + replication_start_all(REPLICATION_MODE_SECONDARY, &error_abort); - replication_get_error_all(&local_err); - g_assert(!local_err); + replication_get_error_all(&error_abort); /* unblock top_bs */ - replication_stop_all(failover, &local_err); - g_assert(!local_err); + replication_stop_all(failover, &error_abort); teardown_secondary(); } +#endif static void sigabrt_handler(int signo) { @@ -599,6 +556,9 @@ static void sigabrt_handler(int signo) static void setup_sigabrt_handler(void) { +#ifdef _WIN32 + signal(SIGABRT, sigabrt_handler); +#else struct sigaction sigact; sigact = (struct sigaction) { @@ -607,11 +567,17 @@ static void setup_sigabrt_handler(void) }; sigemptyset(&sigact.sa_mask); sigaction(SIGABRT, &sigact, NULL); +#endif } int main(int argc, char **argv) { int ret; + const char *tmpdir = g_get_tmp_dir(); + p_local_disk = g_strdup_printf("%s/p_local_disk.XXXXXX", tmpdir); + s_local_disk = g_strdup_printf("%s/s_local_disk.XXXXXX", tmpdir); + s_active_disk = g_strdup_printf("%s/s_active_disk.XXXXXX", tmpdir); + s_hidden_disk = g_strdup_printf("%s/s_hidden_disk.XXXXXX", tmpdir); qemu_init_main_loop(&error_fatal); bdrv_init(); @@ -633,6 +599,7 @@ int main(int argc, char **argv) /* Secondary */ g_test_add_func("/replication/secondary/read", test_secondary_read); g_test_add_func("/replication/secondary/write", test_secondary_write); +#ifndef _WIN32 g_test_add_func("/replication/secondary/start", test_secondary_start); g_test_add_func("/replication/secondary/stop", test_secondary_stop); g_test_add_func("/replication/secondary/continuous_replication", @@ -641,10 +608,16 @@ int main(int argc, char **argv) test_secondary_do_checkpoint); g_test_add_func("/replication/secondary/get_error_all", test_secondary_get_error_all); +#endif ret = g_test_run(); cleanup_imgs(); + g_free(p_local_disk); + g_free(s_local_disk); + g_free(s_active_disk); + g_free(s_hidden_disk); + return ret; } diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-visitor.c index 5418e085a49eb7884251c6afc19709334f664fcb..249faafc9d7915ca6e3ee11255503ee61a8dc3cb 100644 --- a/tests/test-string-input-visitor.c +++ b/tests/test-string-input-visitor.c @@ -53,8 +53,7 @@ static void test_visitor_in_int(TestInputVisitorData *data, v = visitor_input_test_init(data, "-42"); - visit_type_int(v, NULL, &res, &err); - g_assert(!err); + visit_type_int(v, NULL, &res, &error_abort); g_assert_cmpint(res, ==, value); v = visitor_input_test_init(data, "not an int"); @@ -327,44 +326,37 @@ static void test_visitor_in_uintList(TestInputVisitorData *data, static void test_visitor_in_bool(TestInputVisitorData *data, const void *unused) { - Error *err = NULL; bool res = false; Visitor *v; v = visitor_input_test_init(data, "true"); - visit_type_bool(v, NULL, &res, &err); - g_assert(!err); + visit_type_bool(v, NULL, &res, &error_abort); g_assert_cmpint(res, ==, true); v = visitor_input_test_init(data, "yes"); - visit_type_bool(v, NULL, &res, &err); - g_assert(!err); + visit_type_bool(v, NULL, &res, &error_abort); g_assert_cmpint(res, ==, true); v = visitor_input_test_init(data, "on"); - visit_type_bool(v, NULL, &res, &err); - g_assert(!err); + visit_type_bool(v, NULL, &res, &error_abort); g_assert_cmpint(res, ==, true); v = visitor_input_test_init(data, "false"); - visit_type_bool(v, NULL, &res, &err); - g_assert(!err); + visit_type_bool(v, NULL, &res, &error_abort); g_assert_cmpint(res, ==, false); v = visitor_input_test_init(data, "no"); - visit_type_bool(v, NULL, &res, &err); - g_assert(!err); + visit_type_bool(v, NULL, &res, &error_abort); g_assert_cmpint(res, ==, false); v = visitor_input_test_init(data, "off"); - visit_type_bool(v, NULL, &res, &err); - g_assert(!err); + visit_type_bool(v, NULL, &res, &error_abort); g_assert_cmpint(res, ==, false); } @@ -377,8 +369,7 @@ static void test_visitor_in_number(TestInputVisitorData *data, v = visitor_input_test_init(data, "3.14"); - visit_type_number(v, NULL, &res, &err); - g_assert(!err); + visit_type_number(v, NULL, &res, &error_abort); g_assert_cmpfloat(res, ==, value); /* NaN and infinity has to be rejected */ @@ -399,13 +390,11 @@ static void test_visitor_in_string(TestInputVisitorData *data, const void *unused) { char *res = NULL, *value = (char *) "Q E M U"; - Error *err = NULL; Visitor *v; v = visitor_input_test_init(data, value); - visit_type_str(v, NULL, &res, &err); - g_assert(!err); + visit_type_str(v, NULL, &res, &error_abort); g_assert_cmpstr(res, ==, value); g_free(res); @@ -414,7 +403,6 @@ static void test_visitor_in_string(TestInputVisitorData *data, static void test_visitor_in_enum(TestInputVisitorData *data, const void *unused) { - Error *err = NULL; Visitor *v; EnumOne i; @@ -423,8 +411,7 @@ static void test_visitor_in_enum(TestInputVisitorData *data, v = visitor_input_test_init(data, EnumOne_str(i)); - visit_type_EnumOne(v, NULL, &res, &err); - g_assert(!err); + visit_type_EnumOne(v, NULL, &res, &error_abort); g_assert_cmpint(i, ==, res); } } diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c index 3bd732222cea9ee764d80829063cf1a7dac0b380..9f6581439adee2b1e9766d13291db482a04a592b 100644 --- a/tests/test-string-output-visitor.c +++ b/tests/test-string-output-visitor.c @@ -71,11 +71,9 @@ static void test_visitor_out_int(TestOutputVisitorData *data, const void *unused) { int64_t value = 42; - Error *err = NULL; char *str; - visit_type_int(data->ov, NULL, &value, &err); - g_assert(!err); + visit_type_int(data->ov, NULL, &value, &error_abort); str = visitor_get(data); if (data->human) { @@ -120,12 +118,10 @@ static void test_visitor_out_intList(TestOutputVisitorData *data, static void test_visitor_out_bool(TestOutputVisitorData *data, const void *unused) { - Error *err = NULL; bool value = true; char *str; - visit_type_bool(data->ov, NULL, &value, &err); - g_assert(!err); + visit_type_bool(data->ov, NULL, &value, &error_abort); str = visitor_get(data); g_assert_cmpstr(str, ==, "true"); @@ -135,11 +131,9 @@ static void test_visitor_out_number(TestOutputVisitorData *data, const void *unused) { double value = 3.14; - Error *err = NULL; char *str; - visit_type_number(data->ov, NULL, &value, &err); - g_assert(!err); + visit_type_number(data->ov, NULL, &value, &error_abort); str = visitor_get(data); g_assert_cmpstr(str, ==, "3.140000"); @@ -150,11 +144,9 @@ static void test_visitor_out_string(TestOutputVisitorData *data, { char *string = (char *) "Q E M U"; const char *string_human = "\"Q E M U\""; - Error *err = NULL; char *str; - visit_type_str(data->ov, NULL, &string, &err); - g_assert(!err); + visit_type_str(data->ov, NULL, &string, &error_abort); str = visitor_get(data); if (data->human) { diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c index 0b675923f611c6142a1e3708b93b0d9099f31e9f..70dc6314a1ef58e0eb423f6f41b166b6f4e22af1 100644 --- a/tests/test-thread-pool.c +++ b/tests/test-thread-pool.c @@ -21,15 +21,15 @@ typedef struct { static int worker_cb(void *opaque) { WorkerTestData *data = opaque; - return atomic_fetch_inc(&data->n); + return qatomic_fetch_inc(&data->n); } static int long_cb(void *opaque) { WorkerTestData *data = opaque; - if (atomic_cmpxchg(&data->n, 0, 1) == 0) { + if (qatomic_cmpxchg(&data->n, 0, 1) == 0) { g_usleep(2000000); - atomic_or(&data->n, 2); + qatomic_or(&data->n, 2); } return 0; } @@ -172,7 +172,7 @@ static void do_test_cancel(bool sync) /* Cancel the jobs that haven't been started yet. */ num_canceled = 0; for (i = 0; i < 100; i++) { - if (atomic_cmpxchg(&data[i].n, 0, 4) == 0) { + if (qatomic_cmpxchg(&data[i].n, 0, 4) == 0) { data[i].ret = -ECANCELED; if (sync) { bdrv_aio_cancel(data[i].aiocb); @@ -186,7 +186,7 @@ static void do_test_cancel(bool sync) g_assert_cmpint(num_canceled, <, 100); for (i = 0; i < 100; i++) { - if (data[i].aiocb && atomic_read(&data[i].n) < 4) { + if (data[i].aiocb && qatomic_read(&data[i].n) < 4) { if (sync) { /* Canceling the others will be a blocking operation. */ bdrv_aio_cancel(data[i].aiocb); diff --git a/tests/test-timed-average.c b/tests/test-timed-average.c index e2bcf5fe13834e64106758cdbdad7049838749bc..82c92500df8d397a99973ef3094619830ccd36d4 100644 --- a/tests/test-timed-average.c +++ b/tests/test-timed-average.c @@ -11,7 +11,7 @@ */ #include "qemu/osdep.h" - +#include "sysemu/cpu-timers.h" #include "qemu/timed-average.h" /* This is the clock for QEMU_CLOCK_VIRTUAL */ diff --git a/tests/test-util-filemonitor.c b/tests/test-util-filemonitor.c index 45009c69f41d6e9164b50420640cc0d946fbb50d..b629e10857255aea33dc07bfb0ef927baaff731e 100644 --- a/tests/test-util-filemonitor.c +++ b/tests/test-util-filemonitor.c @@ -23,6 +23,8 @@ #include "qapi/error.h" #include "qemu/filemonitor.h" +#include + #include enum { @@ -495,6 +497,7 @@ test_file_monitor_events(void) if (*op->watchid < 0) { g_printerr("Unable to add watch %s", error_get_pretty(local_err)); + error_free(local_err); goto cleanup; } if (debug) { @@ -616,7 +619,7 @@ test_file_monitor_events(void) if (debug) { g_printerr("Mkdir %s\n", pathsrc); } - if (mkdir(pathsrc, 0700) < 0) { + if (g_mkdir_with_parents(pathsrc, 0700) < 0) { g_printerr("Unable to mkdir %s: %s", pathsrc, strerror(errno)); goto cleanup; diff --git a/tests/test-util-sockets.c b/tests/test-util-sockets.c index 2ca1e99f176201b87128f150194d6e9d641ddfdb..67486055ede1920b5d12bf57ef0185fb611d51c7 100644 --- a/tests/test-util-sockets.c +++ b/tests/test-util-sockets.c @@ -52,6 +52,7 @@ static void test_fd_is_socket_good(void) static int mon_fd = -1; static const char *mon_fdname; +__thread Monitor *cur_mon; int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp) { @@ -64,17 +65,17 @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp) return dup(mon_fd); } -/* Syms in libqemustub.a are discarded at .o file granularity. - * To replace monitor_get_fd() we must ensure everything in - * stubs/monitor.c is defined, to make sure monitor.o is discarded +/* + * Syms of stubs in libqemuutil.a are discarded at .o file + * granularity. To replace monitor_get_fd() and monitor_cur(), we + * must ensure that we also replace any other symbol that is used in + * the binary and would be taken from the same stub object file, * otherwise we get duplicate syms at link time. */ -__thread Monitor *cur_mon; +Monitor *monitor_cur(void) { return cur_mon; } int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); } -void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp) {} -void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp) {} - +#ifndef _WIN32 static void test_socket_fd_pass_name_good(void) { SocketAddress addr; @@ -226,99 +227,113 @@ static void test_socket_fd_pass_num_nocli(void) g_free(addr.u.fd.str); } +#endif + +#ifdef CONFIG_LINUX + +#define ABSTRACT_SOCKET_VARIANTS 3 -#ifdef __linux__ -static gchar *abstract_sock_name; +typedef struct { + SocketAddress *server, *client[ABSTRACT_SOCKET_VARIANTS]; + bool expect_connect[ABSTRACT_SOCKET_VARIANTS]; +} abstract_socket_matrix_row; -static gpointer unix_server_thread_func(gpointer user_data) +static gpointer unix_client_thread_func(gpointer user_data) { - SocketAddress addr; + abstract_socket_matrix_row *row = user_data; Error *err = NULL; - int fd = -1; - int connfd = -1; + int i, fd; + + for (i = 0; i < ABSTRACT_SOCKET_VARIANTS; i++) { + if (row->expect_connect[i]) { + fd = socket_connect(row->client[i], &error_abort); + g_assert_cmpint(fd, >=, 0); + } else { + fd = socket_connect(row->client[i], &err); + g_assert_cmpint(fd, ==, -1); + error_free_or_abort(&err); + } + close(fd); + } + return NULL; +} + +static void test_socket_unix_abstract_row(abstract_socket_matrix_row *test) +{ + int fd, connfd, i; + GThread *cli; struct sockaddr_un un; socklen_t len = sizeof(un); - addr.type = SOCKET_ADDRESS_TYPE_UNIX; - addr.u.q_unix.path = abstract_sock_name; - addr.u.q_unix.tight = user_data != NULL; - addr.u.q_unix.abstract = true; + /* Last one must connect, or else accept() below hangs */ + assert(test->expect_connect[ABSTRACT_SOCKET_VARIANTS - 1]); - fd = socket_listen(&addr, 1, &err); + fd = socket_listen(test->server, 1, &error_abort); g_assert_cmpint(fd, >=, 0); g_assert(fd_is_socket(fd)); - connfd = accept(fd, (struct sockaddr *)&un, &len); - g_assert_cmpint(connfd, !=, -1); + cli = g_thread_new("abstract_unix_client", + unix_client_thread_func, + test); + + for (i = 0; i < ABSTRACT_SOCKET_VARIANTS; i++) { + if (test->expect_connect[i]) { + connfd = accept(fd, (struct sockaddr *)&un, &len); + g_assert_cmpint(connfd, !=, -1); + close(connfd); + } + } close(fd); - - return NULL; + g_thread_join(cli); } -static gpointer unix_client_thread_func(gpointer user_data) +static void test_socket_unix_abstract(void) { - SocketAddress addr; - Error *err = NULL; - int fd = -1; + SocketAddress addr, addr_tight, addr_padded; + abstract_socket_matrix_row matrix[ABSTRACT_SOCKET_VARIANTS] = { + { &addr, + { &addr_tight, &addr_padded, &addr }, + { true, false, true } }, + { &addr_tight, + { &addr_padded, &addr, &addr_tight }, + { false, true, true } }, + { &addr_padded, + { &addr, &addr_tight, &addr_padded }, + { false, false, true } } + }; + int i; addr.type = SOCKET_ADDRESS_TYPE_UNIX; - addr.u.q_unix.path = abstract_sock_name; - addr.u.q_unix.tight = user_data != NULL; + addr.u.q_unix.path = g_strdup_printf("unix-%d-%u", + getpid(), g_random_int()); + addr.u.q_unix.has_abstract = true; addr.u.q_unix.abstract = true; + addr.u.q_unix.has_tight = false; + addr.u.q_unix.tight = false; - fd = socket_connect(&addr, &err); + addr_tight = addr; + addr_tight.u.q_unix.has_tight = true; + addr_tight.u.q_unix.tight = true; - g_assert_cmpint(fd, >=, 0); + addr_padded = addr; + addr_padded.u.q_unix.has_tight = true; + addr_padded.u.q_unix.tight = false; - close(fd); + for (i = 0; i < ABSTRACT_SOCKET_VARIANTS; i++) { + test_socket_unix_abstract_row(&matrix[i]); + } - return NULL; + g_free(addr.u.q_unix.path); } -static void test_socket_unix_abstract_good(void) -{ - GRand *r = g_rand_new(); - - abstract_sock_name = g_strdup_printf("unix-%d-%d", getpid(), - g_rand_int_range(r, 100, 1000)); - - /* non tight socklen serv and cli */ - GThread *serv = g_thread_new("abstract_unix_server", - unix_server_thread_func, - NULL); - - sleep(1); - - GThread *cli = g_thread_new("abstract_unix_client", - unix_client_thread_func, - NULL); - - g_thread_join(cli); - g_thread_join(serv); - - /* tight socklen serv and cli */ - serv = g_thread_new("abstract_unix_server", - unix_server_thread_func, - (gpointer)1); - - sleep(1); - - cli = g_thread_new("abstract_unix_client", - unix_client_thread_func, - (gpointer)1); - - g_thread_join(cli); - g_thread_join(serv); - - g_free(abstract_sock_name); -} -#endif +#endif /* CONFIG_LINUX */ int main(int argc, char **argv) { bool has_ipv4, has_ipv6; + qemu_init_main_loop(&error_abort); socket_init(); g_test_init(&argc, &argv, NULL); @@ -338,6 +353,7 @@ int main(int argc, char **argv) test_fd_is_socket_bad); g_test_add_func("/util/socket/is-socket/good", test_fd_is_socket_good); +#ifndef _WIN32 g_test_add_func("/socket/fd-pass/name/good", test_socket_fd_pass_name_good); g_test_add_func("/socket/fd-pass/name/bad", @@ -350,11 +366,12 @@ int main(int argc, char **argv) test_socket_fd_pass_num_bad); g_test_add_func("/socket/fd-pass/num/nocli", test_socket_fd_pass_num_nocli); +#endif } -#ifdef __linux__ - g_test_add_func("/util/socket/unix-abstract/good", - test_socket_unix_abstract_good); +#ifdef CONFIG_LINUX + g_test_add_func("/util/socket/unix-abstract", + test_socket_unix_abstract); #endif end: diff --git a/tests/test-uuid.c b/tests/test-uuid.c index 22b4b0727d8fe04bf4df510dea322eaba2c821a4..c111de5fc1bc39a8a4076c2bffc7f56f6810643a 100644 --- a/tests/test-uuid.c +++ b/tests/test-uuid.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/tests/test-vmstate.c b/tests/test-vmstate.c index f7b3868881b944256eaa1a977086dbdac0a96ce7..a001879585e75853d776b38aee712730c2ea19fa 100644 --- a/tests/test-vmstate.c +++ b/tests/test-vmstate.c @@ -34,7 +34,6 @@ #include "qemu/module.h" #include "io/channel-file.h" -static char temp_file[] = "/tmp/vmst.test.XXXXXX"; static int temp_fd; @@ -881,8 +880,8 @@ static gint interval_cmp(gconstpointer a, gconstpointer b, gpointer user_data) /* ID comparison function */ static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data) { - uint ua = GPOINTER_TO_UINT(a); - uint ub = GPOINTER_TO_UINT(b); + guint ua = GPOINTER_TO_UINT(a); + guint ub = GPOINTER_TO_UINT(b); return (ua > ub) - (ua < ub); } @@ -1055,9 +1054,6 @@ static gboolean match_interval_mapping_node(gpointer key, TestGTreeMapping *map_a, *map_b; TestGTreeInterval *a, *b; struct match_node_data *d = (struct match_node_data *)data; - char *str = g_strdup_printf("dest"); - - g_free(str); a = (TestGTreeInterval *)key; b = (TestGTreeInterval *)d->key; @@ -1487,6 +1483,8 @@ static void test_tmp_struct(void) int main(int argc, char **argv) { + g_autofree char *temp_file = g_strdup_printf("%s/vmst.test.XXXXXX", + g_get_tmp_dir()); temp_fd = mkstemp(temp_file); module_call_init(MODULE_INIT_QOM); diff --git a/tests/test-x86-cpuid.c b/tests/test-x86-cpuid.c index 049030a50ebad57aeaaca439e7b3c2a72d28cc0d..bfabc0403a1a012dc16b96e1ea92ec84315b1ff9 100644 --- a/tests/test-x86-cpuid.c +++ b/tests/test-x86-cpuid.c @@ -31,12 +31,12 @@ static void test_topo_bits(void) X86CPUTopoInfo topo_info = {0}; /* simple tests for 1 thread per core, 1 core per die, 1 die per package */ - topo_info = (X86CPUTopoInfo) {0, 1, 1, 1}; + topo_info = (X86CPUTopoInfo) {1, 1, 1}; g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 0); g_assert_cmpuint(apicid_core_width(&topo_info), ==, 0); g_assert_cmpuint(apicid_die_width(&topo_info), ==, 0); - topo_info = (X86CPUTopoInfo) {0, 1, 1, 1}; + topo_info = (X86CPUTopoInfo) {1, 1, 1}; g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 0), ==, 0); g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 1), ==, 1); g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 2), ==, 2); @@ -45,39 +45,39 @@ static void test_topo_bits(void) /* Test field width calculation for multiple values */ - topo_info = (X86CPUTopoInfo) {0, 1, 1, 2}; + topo_info = (X86CPUTopoInfo) {1, 1, 2}; g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 1); - topo_info = (X86CPUTopoInfo) {0, 1, 1, 3}; + topo_info = (X86CPUTopoInfo) {1, 1, 3}; g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 2); - topo_info = (X86CPUTopoInfo) {0, 1, 1, 4}; + topo_info = (X86CPUTopoInfo) {1, 1, 4}; g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 2); - topo_info = (X86CPUTopoInfo) {0, 1, 1, 14}; + topo_info = (X86CPUTopoInfo) {1, 1, 14}; g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 4); - topo_info = (X86CPUTopoInfo) {0, 1, 1, 15}; + topo_info = (X86CPUTopoInfo) {1, 1, 15}; g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 4); - topo_info = (X86CPUTopoInfo) {0, 1, 1, 16}; + topo_info = (X86CPUTopoInfo) {1, 1, 16}; g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 4); - topo_info = (X86CPUTopoInfo) {0, 1, 1, 17}; + topo_info = (X86CPUTopoInfo) {1, 1, 17}; g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 5); - topo_info = (X86CPUTopoInfo) {0, 1, 30, 2}; + topo_info = (X86CPUTopoInfo) {1, 30, 2}; g_assert_cmpuint(apicid_core_width(&topo_info), ==, 5); - topo_info = (X86CPUTopoInfo) {0, 1, 31, 2}; + topo_info = (X86CPUTopoInfo) {1, 31, 2}; g_assert_cmpuint(apicid_core_width(&topo_info), ==, 5); - topo_info = (X86CPUTopoInfo) {0, 1, 32, 2}; + topo_info = (X86CPUTopoInfo) {1, 32, 2}; g_assert_cmpuint(apicid_core_width(&topo_info), ==, 5); - topo_info = (X86CPUTopoInfo) {0, 1, 33, 2}; + topo_info = (X86CPUTopoInfo) {1, 33, 2}; g_assert_cmpuint(apicid_core_width(&topo_info), ==, 6); - topo_info = (X86CPUTopoInfo) {0, 1, 30, 2}; + topo_info = (X86CPUTopoInfo) {1, 30, 2}; g_assert_cmpuint(apicid_die_width(&topo_info), ==, 0); - topo_info = (X86CPUTopoInfo) {0, 2, 30, 2}; + topo_info = (X86CPUTopoInfo) {2, 30, 2}; g_assert_cmpuint(apicid_die_width(&topo_info), ==, 1); - topo_info = (X86CPUTopoInfo) {0, 3, 30, 2}; + topo_info = (X86CPUTopoInfo) {3, 30, 2}; g_assert_cmpuint(apicid_die_width(&topo_info), ==, 2); - topo_info = (X86CPUTopoInfo) {0, 4, 30, 2}; + topo_info = (X86CPUTopoInfo) {4, 30, 2}; g_assert_cmpuint(apicid_die_width(&topo_info), ==, 2); /* build a weird topology and see if IDs are calculated correctly @@ -85,18 +85,18 @@ static void test_topo_bits(void) /* This will use 2 bits for thread ID and 3 bits for core ID */ - topo_info = (X86CPUTopoInfo) {0, 1, 6, 3}; + topo_info = (X86CPUTopoInfo) {1, 6, 3}; g_assert_cmpuint(apicid_smt_width(&topo_info), ==, 2); g_assert_cmpuint(apicid_core_offset(&topo_info), ==, 2); g_assert_cmpuint(apicid_die_offset(&topo_info), ==, 5); g_assert_cmpuint(apicid_pkg_offset(&topo_info), ==, 5); - topo_info = (X86CPUTopoInfo) {0, 1, 6, 3}; + topo_info = (X86CPUTopoInfo) {1, 6, 3}; g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 0), ==, 0); g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 1), ==, 1); g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 2), ==, 2); - topo_info = (X86CPUTopoInfo) {0, 1, 6, 3}; + topo_info = (X86CPUTopoInfo) {1, 6, 3}; g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 1 * 3 + 0), ==, (1 << 2) | 0); g_assert_cmpuint(x86_apicid_from_cpu_idx(&topo_info, 1 * 3 + 1), ==, diff --git a/tests/tsan/blacklist.tsan b/tests/tsan/blacklist.tsan new file mode 100644 index 0000000000000000000000000000000000000000..75e444f5dc6c212e906320b80c2a70c82723583a --- /dev/null +++ b/tests/tsan/blacklist.tsan @@ -0,0 +1,10 @@ +# This is an example blacklist. +# To enable use of the blacklist add this to configure: +# "--extra-cflags=-fsanitize-blacklist=/tests/tsan/blacklist.tsan" +# The eventual goal would be to fix these warnings. + +# TSan is not happy about setting/getting of dirty bits, +# for example, cpu_physical_memory_set_dirty_range, +# and cpu_physical_memory_get_dirty. +src:bitops.c +src:bitmap.c diff --git a/tests/tsan/suppressions.tsan b/tests/tsan/suppressions.tsan new file mode 100644 index 0000000000000000000000000000000000000000..73414b9ebd9046974f115f35bdebedb63d78058c --- /dev/null +++ b/tests/tsan/suppressions.tsan @@ -0,0 +1,14 @@ +# This is the set of runtime suppressions of TSan warnings. +# The goal would be to have here only items we do not +# plan to fix, and to explain why for each item. + +# TSan reports a double lock on RECURSIVE mutexes. +# Since the recursive lock is intentional, we choose to ignore it. +mutex:aio_context_acquire +mutex:pthread_mutex_lock + +# TSan reports a race betwen pthread_mutex_init() and +# pthread_mutex_lock(). Since this is outside of QEMU, +# we choose to ignore it. +race:pthread_mutex_init +race:pthread_mutex_lock diff --git a/tests/uefi-test-tools/.gitignore b/tests/uefi-test-tools/.gitignore deleted file mode 100644 index 9f246701dea1312e0576d2147e8a2de4742dd12a..0000000000000000000000000000000000000000 --- a/tests/uefi-test-tools/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -Build -Conf -log diff --git a/tests/uefi-test-tools/Makefile b/tests/uefi-test-tools/Makefile index 1dcddcdbbabf1c7dbea9c233d0ef45cd5ea3325d..471f0de981090b3d419b8bc7890c7a22c0bbe642 100644 --- a/tests/uefi-test-tools/Makefile +++ b/tests/uefi-test-tools/Makefile @@ -99,6 +99,7 @@ Build/bios-tables-test.%.efi: build-edk2-tools +./build.sh $(edk2_dir) BiosTablesTest $* $@ build-edk2-tools: + cd $(edk2_dir)/BaseTools && git submodule update --init --force $(MAKE) -C $(edk2_dir)/BaseTools \ PYTHON_COMMAND=$${EDK2_PYTHON_COMMAND:-python3} \ EXTRA_OPTFLAGS='$(EDK2_BASETOOLS_OPTFLAGS)' \ diff --git a/tests/vhost-user-bridge.c b/tests/vhost-user-bridge.c index 6c3d490611b5c59084d62b40d657f674721ba2d7..bd43607a4d3bda78cfbfe263319334408047eeac 100644 --- a/tests/vhost-user-bridge.c +++ b/tests/vhost-user-bridge.c @@ -520,6 +520,7 @@ vubr_accept_cb(int sock, void *ctx) VHOST_USER_BRIDGE_MAX_QUEUES, conn_fd, vubr_panic, + NULL, vubr_set_watch, vubr_remove_watch, &vuiface)) { @@ -573,6 +574,7 @@ vubr_new(const char *path, bool client) VHOST_USER_BRIDGE_MAX_QUEUES, dev->sock, vubr_panic, + NULL, vubr_set_watch, vubr_remove_watch, &vuiface)) { diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include index 1bf9693d195b8a057ce1a5e57b8c92a1efc9a7fc..e94d95ec541eb46132da298a79650d1efad43b76 100644 --- a/tests/vm/Makefile.include +++ b/tests/vm/Makefile.include @@ -2,9 +2,14 @@ .PHONY: vm-build-all vm-clean-all -IMAGES := freebsd netbsd openbsd centos fedora +EFI_AARCH64 = $(wildcard $(BUILD_DIR)/pc-bios/edk2-aarch64-code.fd) + +IMAGES := freebsd netbsd openbsd centos fedora haiku.x86_64 ifneq ($(GENISOIMAGE),) IMAGES += ubuntu.i386 centos +ifneq ($(EFI_AARCH64),) +IMAGES += ubuntu.aarch64 centos.aarch64 +endif endif IMAGES_DIR := $(HOME)/.cache/qemu-vm/images @@ -12,6 +17,10 @@ IMAGE_FILES := $(patsubst %, $(IMAGES_DIR)/%.img, $(IMAGES)) .PRECIOUS: $(IMAGE_FILES) +ifneq ($(PYTHON),) +HAVE_PYTHON_YAML = $(shell $(PYTHON) -c "import yaml" 2> /dev/null && echo yes) +endif + # 'vm-help' target was historically named 'vm-test' vm-help vm-test: @echo "vm-help: Test QEMU in preconfigured virtual machines" @@ -23,9 +32,16 @@ vm-help vm-test: ifneq ($(GENISOIMAGE),) @echo " vm-build-centos - Build QEMU in CentOS VM, with Docker" @echo " vm-build-ubuntu.i386 - Build QEMU in ubuntu i386 VM" +ifneq ($(EFI_AARCH64),) + @echo " vm-build-ubuntu.aarch64 - Build QEMU in ubuntu aarch64 VM" + @echo " vm-build-centos.aarch64 - Build QEMU in CentOS aarch64 VM" +else + @echo " (to build centos/ubuntu aarch64 images use configure --efi-aarch64)" +endif else @echo " (install genisoimage to build centos/ubuntu images)" endif + @echo " vm-build-haiku.x86_64 - Build QEMU in Haiku VM" @echo "" @echo " vm-build-all - Build QEMU in all VMs" @echo " vm-clean-all - Clean up VM images" @@ -40,9 +56,17 @@ endif @echo ' EXTRA_CONFIGURE_OPTS="..."' @echo " J=[0..9]* - Override the -jN parameter for make commands" @echo " DEBUG=1 - Enable verbose output on host and interactive debugging" + @echo " LOG_CONSOLE=1 - Log console to file in: ~/.cache/qemu-vm " @echo " V=1 - Enable verbose ouput on host and guest commands" + @echo " QEMU_LOCAL=1 - Use QEMU binary local to this build." @echo " QEMU=/path/to/qemu - Change path to QEMU binary" @echo " QEMU_IMG=/path/to/qemu-img - Change path to qemu-img tool" +ifeq ($(HAVE_PYTHON_YAML),yes) + @echo " QEMU_CONFIG=/path/conf.yml - Change path to VM configuration .yml file." +else + @echo " (install python3-yaml to enable support for yaml file to configure a VM.)" +endif + @echo " See conf_example_*.yml for file format details." vm-build-all: $(addprefix vm-build-, $(IMAGES)) @@ -56,6 +80,10 @@ $(IMAGES_DIR)/%.img: $(SRC_PATH)/tests/vm/% \ $(call quiet-command, \ $(PYTHON) $< \ $(if $(V)$(DEBUG), --debug) \ + $(if $(GENISOIMAGE),--genisoimage $(GENISOIMAGE)) \ + $(if $(QEMU_LOCAL),--build-path $(BUILD_DIR)) \ + $(if $(EFI_AARCH64),--efi-aarch64 $(EFI_AARCH64)) \ + $(if $(LOG_CONSOLE),--log-console) \ --image "$@" \ --force \ --build-image $@, \ @@ -70,6 +98,9 @@ vm-build-%: $(IMAGES_DIR)/%.img $(if $(DEBUG), --interactive) \ $(if $(J),--jobs $(J)) \ $(if $(V),--verbose) \ + $(if $(QEMU_LOCAL),--build-path $(BUILD_DIR)) \ + $(if $(EFI_AARCH64),--efi-aarch64 $(EFI_AARCH64)) \ + $(if $(LOG_CONSOLE),--log-console) \ --image "$<" \ $(if $(BUILD_TARGET),--build-target $(BUILD_TARGET)) \ --snapshot \ @@ -90,6 +121,10 @@ vm-boot-ssh-%: $(IMAGES_DIR)/%.img $(call quiet-command, \ $(PYTHON) $(SRC_PATH)/tests/vm/$* \ $(if $(J),--jobs $(J)) \ + $(if $(V)$(DEBUG), --debug) \ + $(if $(QEMU_LOCAL),--build-path $(BUILD_DIR)) \ + $(if $(EFI_AARCH64),--efi-aarch64 $(EFI_AARCH64)) \ + $(if $(LOG_CONSOLE),--log-console) \ --image "$<" \ --interactive \ false, \ diff --git a/tests/vm/aarch64vm.py b/tests/vm/aarch64vm.py new file mode 100644 index 0000000000000000000000000000000000000000..d70ab843b6b8dabe1901cde508130f044be78d18 --- /dev/null +++ b/tests/vm/aarch64vm.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 +# +# VM testing aarch64 library +# +# Copyright 2020 Linaro +# +# Authors: +# Robert Foley +# +# This code is licensed under the GPL version 2 or later. See +# the COPYING file in the top-level directory. +# +import os +import sys +import subprocess +import basevm +from qemu.accel import kvm_available + +# This is the config needed for current version of QEMU. +# This works for both kvm and tcg. +CURRENT_CONFIG = { + 'cpu' : "max", + 'machine' : "virt,gic-version=max", +} + +# The minimum minor version of QEMU we will support with aarch64 VMs is 3. +# QEMU versions less than 3 have various issues running these VMs. +QEMU_AARCH64_MIN_VERSION = 3 + +# The DEFAULT_CONFIG will default to a version of +# parameters that works for backwards compatibility. +DEFAULT_CONFIG = {'kvm' : {'cpu' : "host", + 'machine' : "virt,gic-version=host"}, + 'tcg' : {'cpu' : "cortex-a57", + 'machine' : "virt"}, +} + +def get_config_defaults(vmcls, default_config): + """Fetch the configuration defaults for this VM, + taking into consideration the defaults for + aarch64 first, followed by the defaults for this VM.""" + config = default_config + config.update(aarch_get_config_defaults(vmcls)) + return config + +def aarch_get_config_defaults(vmcls): + """Set the defaults for current version of QEMU.""" + config = CURRENT_CONFIG + args = basevm.parse_args(vmcls) + qemu_path = basevm.get_qemu_path(vmcls.arch, args.build_path) + qemu_version = basevm.get_qemu_version(qemu_path) + if qemu_version < QEMU_AARCH64_MIN_VERSION: + error = "\nThis major version of QEMU {} is to old for aarch64 VMs.\n"\ + "The major version must be at least {}.\n"\ + "To continue with the current build of QEMU, "\ + "please restart with QEMU_LOCAL=1 .\n" + print(error.format(qemu_version, QEMU_AARCH64_MIN_VERSION)) + exit(1) + if qemu_version == QEMU_AARCH64_MIN_VERSION: + # We have an older version of QEMU, + # set the config values for backwards compatibility. + if kvm_available('aarch64'): + config.update(DEFAULT_CONFIG['kvm']) + else: + config.update(DEFAULT_CONFIG['tcg']) + return config + +def create_flash_images(flash_dir="./", efi_img=""): + """Creates the appropriate pflash files + for an aarch64 VM.""" + flash0_path = get_flash_path(flash_dir, "flash0") + flash1_path = get_flash_path(flash_dir, "flash1") + fd_null = open(os.devnull, 'w') + subprocess.check_call(["dd", "if=/dev/zero", "of={}".format(flash0_path), + "bs=1M", "count=64"], + stdout=fd_null, stderr=subprocess.STDOUT) + # A reliable way to get the QEMU EFI image is via an installed package or + # via the bios included with qemu. + if not os.path.exists(efi_img): + sys.stderr.write("*** efi argument is invalid ({})\n".format(efi_img)) + sys.stderr.write("*** please check --efi-aarch64 argument or "\ + "install qemu-efi-aarch64 package\n") + exit(3) + subprocess.check_call(["dd", "if={}".format(efi_img), + "of={}".format(flash0_path), + "conv=notrunc"], + stdout=fd_null, stderr=subprocess.STDOUT) + subprocess.check_call(["dd", "if=/dev/zero", + "of={}".format(flash1_path), + "bs=1M", "count=64"], + stdout=fd_null, stderr=subprocess.STDOUT) + fd_null.close() + +def get_pflash_args(flash_dir="./"): + """Returns a string that can be used to + boot qemu using the appropriate pflash files + for aarch64.""" + flash0_path = get_flash_path(flash_dir, "flash0") + flash1_path = get_flash_path(flash_dir, "flash1") + pflash_args_str = "-drive file={},format=raw,if=pflash "\ + "-drive file={},format=raw,if=pflash" + pflash_args = pflash_args_str.format(flash0_path, flash1_path) + return pflash_args.split(" ") + +def get_flash_path(flash_dir, name): + return os.path.join(flash_dir, "{}.img".format(name)) diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py index 756ccf7acae44a0f0db71741b76c4bbe72c76a2b..00f1d5ca8daad1905b4ce6d59b2439d596f93e3a 100644 --- a/tests/vm/basevm.py +++ b/tests/vm/basevm.py @@ -23,22 +23,48 @@ from qemu.machine import QEMUMachine import subprocess import hashlib -import optparse +import argparse import atexit import tempfile import shutil import multiprocessing import traceback - -SSH_KEY = open(os.path.join(os.path.dirname(__file__), - "..", "keys", "id_rsa")).read() -SSH_PUB_KEY = open(os.path.join(os.path.dirname(__file__), - "..", "keys", "id_rsa.pub")).read() - +import shlex + +SSH_KEY_FILE = os.path.join(os.path.dirname(__file__), + "..", "keys", "id_rsa") +SSH_PUB_KEY_FILE = os.path.join(os.path.dirname(__file__), + "..", "keys", "id_rsa.pub") + +# This is the standard configuration. +# Any or all of these can be overridden by +# passing in a config argument to the VM constructor. +DEFAULT_CONFIG = { + 'cpu' : "max", + 'machine' : 'pc', + 'guest_user' : "qemu", + 'guest_pass' : "qemupass", + 'root_user' : "root", + 'root_pass' : "qemupass", + 'ssh_key_file' : SSH_KEY_FILE, + 'ssh_pub_key_file': SSH_PUB_KEY_FILE, + 'memory' : "4G", + 'extra_args' : [], + 'qemu_args' : "", + 'dns' : "", + 'ssh_port' : 0, + 'install_cmds' : "", + 'boot_dev_type' : "block", + 'ssh_timeout' : 1, +} +BOOT_DEVICE = { + 'block' : "-drive file={},if=none,id=drive0,cache=writeback "\ + "-device virtio-blk,drive=drive0,bootindex=0", + 'scsi' : "-device virtio-scsi-device,id=scsi "\ + "-drive file={},format=raw,if=none,id=hd0 "\ + "-device scsi-hd,drive=hd0,bootindex=0", +} class BaseVM(object): - GUEST_USER = "qemu" - GUEST_PASS = "qemupass" - ROOT_PASS = "qemupass" envvars = [ "https_proxy", @@ -55,48 +81,119 @@ class BaseVM(object): arch = "#arch" # command to halt the guest, can be overridden by subclasses poweroff = "poweroff" + # Time to wait for shutdown to finish. + shutdown_timeout_default = 30 # enable IPv6 networking ipv6 = True + # This is the timeout on the wait for console bytes. + socket_timeout = 120 # Scale up some timeouts under TCG. # 4 is arbitrary, but greater than 2, # since we found we need to wait more than twice as long. - tcg_ssh_timeout_multiplier = 4 - def __init__(self, debug=False, vcpus=None): + tcg_timeout_multiplier = 4 + def __init__(self, args, config=None): self._guest = None + self._genisoimage = args.genisoimage + self._build_path = args.build_path + self._efi_aarch64 = args.efi_aarch64 + # Allow input config to override defaults. + self._config = DEFAULT_CONFIG.copy() + if config != None: + self._config.update(config) + self.validate_ssh_keys() self._tmpdir = os.path.realpath(tempfile.mkdtemp(prefix="vm-test-", suffix=".tmp", dir=".")) atexit.register(shutil.rmtree, self._tmpdir) - - self._ssh_key_file = os.path.join(self._tmpdir, "id_rsa") - open(self._ssh_key_file, "w").write(SSH_KEY) - subprocess.check_call(["chmod", "600", self._ssh_key_file]) - - self._ssh_pub_key_file = os.path.join(self._tmpdir, "id_rsa.pub") - open(self._ssh_pub_key_file, "w").write(SSH_PUB_KEY) - - self.debug = debug + # Copy the key files to a temporary directory. + # Also chmod the key file to agree with ssh requirements. + self._config['ssh_key'] = \ + open(self._config['ssh_key_file']).read().rstrip() + self._config['ssh_pub_key'] = \ + open(self._config['ssh_pub_key_file']).read().rstrip() + self._ssh_tmp_key_file = os.path.join(self._tmpdir, "id_rsa") + open(self._ssh_tmp_key_file, "w").write(self._config['ssh_key']) + subprocess.check_call(["chmod", "600", self._ssh_tmp_key_file]) + + self._ssh_tmp_pub_key_file = os.path.join(self._tmpdir, "id_rsa.pub") + open(self._ssh_tmp_pub_key_file, + "w").write(self._config['ssh_pub_key']) + + self.debug = args.debug + self._console_log_path = None + if args.log_console: + self._console_log_path = \ + os.path.join(os.path.expanduser("~/.cache/qemu-vm"), + "{}.install.log".format(self.name)) self._stderr = sys.stderr self._devnull = open(os.devnull, "w") if self.debug: self._stdout = sys.stdout else: self._stdout = self._devnull + netdev = "user,id=vnet,hostfwd=:127.0.0.1:{}-:22" self._args = [ \ - "-nodefaults", "-m", "4G", - "-cpu", "max", - "-netdev", "user,id=vnet,hostfwd=:127.0.0.1:0-:22" + - (",ipv6=no" if not self.ipv6 else ""), + "-nodefaults", "-m", self._config['memory'], + "-cpu", self._config['cpu'], + "-netdev", + netdev.format(self._config['ssh_port']) + + (",ipv6=no" if not self.ipv6 else "") + + (",dns=" + self._config['dns'] if self._config['dns'] else ""), "-device", "virtio-net-pci,netdev=vnet", "-vnc", "127.0.0.1:0,to=20"] - if vcpus and vcpus > 1: - self._args += ["-smp", "%d" % vcpus] + if args.jobs and args.jobs > 1: + self._args += ["-smp", "%d" % args.jobs] if kvm_available(self.arch): + self._shutdown_timeout = self.shutdown_timeout_default self._args += ["-enable-kvm"] else: logging.info("KVM not available, not using -enable-kvm") + self._shutdown_timeout = \ + self.shutdown_timeout_default * self.tcg_timeout_multiplier self._data_args = [] + if self._config['qemu_args'] != None: + qemu_args = self._config['qemu_args'] + qemu_args = qemu_args.replace('\n',' ').replace('\r','') + # shlex groups quoted arguments together + # we need this to keep the quoted args together for when + # the QEMU command is issued later. + args = shlex.split(qemu_args) + self._config['extra_args'] = [] + for arg in args: + if arg: + # Preserve quotes around arguments. + # shlex above takes them out, so add them in. + if " " in arg: + arg = '"{}"'.format(arg) + self._config['extra_args'].append(arg) + + def validate_ssh_keys(self): + """Check to see if the ssh key files exist.""" + if 'ssh_key_file' not in self._config or\ + not os.path.exists(self._config['ssh_key_file']): + raise Exception("ssh key file not found.") + if 'ssh_pub_key_file' not in self._config or\ + not os.path.exists(self._config['ssh_pub_key_file']): + raise Exception("ssh pub key file not found.") + + def wait_boot(self, wait_string=None): + """Wait for the standard string we expect + on completion of a normal boot. + The user can also choose to override with an + alternate string to wait for.""" + if wait_string is None: + if self.login_prompt is None: + raise Exception("self.login_prompt not defined") + wait_string = self.login_prompt + # Intentionally bump up the default timeout under TCG, + # since the console wait below takes longer. + timeout = self.socket_timeout + if not kvm_available(self.arch): + timeout *= 8 + self.console_init(timeout=timeout) + self.console_wait(wait_string) + def _download_with_cache(self, url, sha256sum=None, sha512sum=None): def check_sha256sum(fname): if not sha256sum: @@ -128,8 +225,9 @@ def _ssh_do(self, user, cmd, check): "-t", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=" + os.devnull, - "-o", "ConnectTimeout=1", - "-p", self.ssh_port, "-i", self._ssh_key_file] + "-o", + "ConnectTimeout={}".format(self._config["ssh_timeout"]), + "-p", self.ssh_port, "-i", self._ssh_tmp_key_file] # If not in debug mode, set ssh to quiet mode to # avoid printing the results of commands. if not self.debug: @@ -145,16 +243,16 @@ def _ssh_do(self, user, cmd, check): return r def ssh(self, *cmd): - return self._ssh_do(self.GUEST_USER, cmd, False) + return self._ssh_do(self._config["guest_user"], cmd, False) def ssh_root(self, *cmd): - return self._ssh_do("root", cmd, False) + return self._ssh_do(self._config["root_user"], cmd, False) def ssh_check(self, *cmd): - self._ssh_do(self.GUEST_USER, cmd, True) + self._ssh_do(self._config["guest_user"], cmd, True) def ssh_root_check(self, *cmd): - self._ssh_do("root", cmd, True) + self._ssh_do(self._config["root_user"], cmd, True) def build_image(self, img): raise NotImplementedError @@ -178,26 +276,34 @@ def add_source_dir(self, src_dir): "virtio-blk,drive=%s,serial=%s,bootindex=1" % (name, name)] def boot(self, img, extra_args=[]): - args = self._args + [ - "-drive", "file=%s,if=none,id=drive0,cache=writeback" % img, - "-device", "virtio-blk,drive=drive0,bootindex=0"] - args += self._data_args + extra_args + boot_dev = BOOT_DEVICE[self._config['boot_dev_type']] + boot_params = boot_dev.format(img) + args = self._args + boot_params.split(' ') + args += self._data_args + extra_args + self._config['extra_args'] logging.debug("QEMU args: %s", " ".join(args)) - qemu_bin = os.environ.get("QEMU", "qemu-system-" + self.arch) - guest = QEMUMachine(binary=qemu_bin, args=args) - guest.set_machine('pc') + qemu_path = get_qemu_path(self.arch, self._build_path) + + # Since console_log_path is only set when the user provides the + # log_console option, we will set drain_console=True so the + # console is always drained. + guest = QEMUMachine(binary=qemu_path, args=args, + console_log=self._console_log_path, + drain_console=True) + guest.set_machine(self._config['machine']) guest.set_console() try: guest.launch() except: logging.error("Failed to launch QEMU, command line:") - logging.error(" ".join([qemu_bin] + args)) + logging.error(" ".join([qemu_path] + args)) logging.error("Log:") logging.error(guest.get_log()) logging.error("QEMU version >= 2.10 is required") raise atexit.register(self.shutdown) self._guest = guest + # Init console so we can start consuming the chars. + self.console_init() usernet_info = guest.qmp("human-monitor-command", command_line="info usernet") self.ssh_port = None @@ -209,7 +315,9 @@ def boot(self, img, extra_args=[]): raise Exception("Cannot find ssh port from 'info usernet':\n%s" % \ usernet_info) - def console_init(self, timeout = 120): + def console_init(self, timeout = None): + if timeout == None: + timeout = self.socket_timeout vm = self._guest vm.console_socket.settimeout(timeout) self.console_raw_path = os.path.join(vm._temp_dir, @@ -299,7 +407,8 @@ def console_wait_send(self, wait, command): self.console_send(command) def console_ssh_init(self, prompt, user, pw): - sshkey_cmd = "echo '%s' > .ssh/authorized_keys\n" % SSH_PUB_KEY.rstrip() + sshkey_cmd = "echo '%s' > .ssh/authorized_keys\n" \ + % self._config['ssh_pub_key'].rstrip() self.console_wait_send("login:", "%s\n" % user) self.console_wait_send("Password:", "%s\n" % pw) self.console_wait_send(prompt, "mkdir .ssh\n") @@ -317,35 +426,35 @@ def console_sshd_config(self, prompt): def print_step(self, text): sys.stderr.write("### %s ...\n" % text) - def wait_ssh(self, wait_root=False, seconds=300): + def wait_ssh(self, wait_root=False, seconds=300, cmd="exit 0"): # Allow more time for VM to boot under TCG. if not kvm_available(self.arch): - seconds *= self.tcg_ssh_timeout_multiplier + seconds *= self.tcg_timeout_multiplier starttime = datetime.datetime.now() endtime = starttime + datetime.timedelta(seconds=seconds) - guest_up = False + cmd_success = False while datetime.datetime.now() < endtime: - if wait_root and self.ssh_root("exit 0") == 0: - guest_up = True + if wait_root and self.ssh_root(cmd) == 0: + cmd_success = True break - elif self.ssh("exit 0") == 0: - guest_up = True + elif self.ssh(cmd) == 0: + cmd_success = True break seconds = (endtime - datetime.datetime.now()).total_seconds() logging.debug("%ds before timeout", seconds) time.sleep(1) - if not guest_up: + if not cmd_success: raise Exception("Timeout while waiting for guest ssh") def shutdown(self): - self._guest.shutdown() + self._guest.shutdown(timeout=self._shutdown_timeout) def wait(self): - self._guest.wait() + self._guest.wait(timeout=self._shutdown_timeout) def graceful_shutdown(self): self.ssh_root(self.poweroff) - self._guest.wait() + self._guest.wait(timeout=self._shutdown_timeout) def qmp(self, *args, **kwargs): return self._guest.qmp(*args, **kwargs) @@ -358,84 +467,165 @@ def gen_cloud_init_iso(self): "local-hostname: {}-guest\n".format(name)]) mdata.close() udata = open(os.path.join(cidir, "user-data"), "w") - print("guest user:pw {}:{}".format(self.GUEST_USER, - self.GUEST_PASS)) + print("guest user:pw {}:{}".format(self._config['guest_user'], + self._config['guest_pass'])) udata.writelines(["#cloud-config\n", "chpasswd:\n", " list: |\n", - " root:%s\n" % self.ROOT_PASS, - " %s:%s\n" % (self.GUEST_USER, - self.GUEST_PASS), + " root:%s\n" % self._config['root_pass'], + " %s:%s\n" % (self._config['guest_user'], + self._config['guest_pass']), " expire: False\n", "users:\n", - " - name: %s\n" % self.GUEST_USER, + " - name: %s\n" % self._config['guest_user'], " sudo: ALL=(ALL) NOPASSWD:ALL\n", " ssh-authorized-keys:\n", - " - %s\n" % SSH_PUB_KEY, + " - %s\n" % self._config['ssh_pub_key'], " - name: root\n", " ssh-authorized-keys:\n", - " - %s\n" % SSH_PUB_KEY, + " - %s\n" % self._config['ssh_pub_key'], "locale: en_US.UTF-8\n"]) proxy = os.environ.get("http_proxy") if not proxy is None: udata.writelines(["apt:\n", " proxy: %s" % proxy]) udata.close() - subprocess.check_call(["genisoimage", "-output", "cloud-init.iso", + subprocess.check_call([self._genisoimage, "-output", "cloud-init.iso", "-volid", "cidata", "-joliet", "-rock", "user-data", "meta-data"], - cwd=cidir, - stdin=self._devnull, stdout=self._stdout, - stderr=self._stdout) - + cwd=cidir, + stdin=self._devnull, stdout=self._stdout, + stderr=self._stdout) return os.path.join(cidir, "cloud-init.iso") +def get_qemu_path(arch, build_path=None): + """Fetch the path to the qemu binary.""" + # If QEMU environment variable set, it takes precedence + if "QEMU" in os.environ: + qemu_path = os.environ["QEMU"] + elif build_path: + qemu_path = os.path.join(build_path, arch + "-softmmu") + qemu_path = os.path.join(qemu_path, "qemu-system-" + arch) + else: + # Default is to use system path for qemu. + qemu_path = "qemu-system-" + arch + return qemu_path + +def get_qemu_version(qemu_path): + """Get the version number from the current QEMU, + and return the major number.""" + output = subprocess.check_output([qemu_path, '--version']) + version_line = output.decode("utf-8") + version_num = re.split(' |\(', version_line)[3].split('.')[0] + return int(version_num) + +def parse_config(config, args): + """ Parse yaml config and populate our config structure. + The yaml config allows the user to override the + defaults for VM parameters. In many cases these + defaults can be overridden without rebuilding the VM.""" + if args.config: + config_file = args.config + elif 'QEMU_CONFIG' in os.environ: + config_file = os.environ['QEMU_CONFIG'] + else: + return config + if not os.path.exists(config_file): + raise Exception("config file {} does not exist".format(config_file)) + # We gracefully handle importing the yaml module + # since it might not be installed. + # If we are here it means the user supplied a .yml file, + # so if the yaml module is not installed we will exit with error. + try: + import yaml + except ImportError: + print("The python3-yaml package is needed "\ + "to support config.yaml files") + # Instead of raising an exception we exit to avoid + # a raft of messy (expected) errors to stdout. + exit(1) + with open(config_file) as f: + yaml_dict = yaml.safe_load(f) + + if 'qemu-conf' in yaml_dict: + config.update(yaml_dict['qemu-conf']) + else: + raise Exception("config file {} is not valid"\ + " missing qemu-conf".format(config_file)) + return config + def parse_args(vmcls): def get_default_jobs(): - if kvm_available(vmcls.arch): - return multiprocessing.cpu_count() // 2 + if multiprocessing.cpu_count() > 1: + if kvm_available(vmcls.arch): + return multiprocessing.cpu_count() // 2 + elif os.uname().machine == "x86_64" and \ + vmcls.arch in ["aarch64", "x86_64", "i386"]: + # MTTCG is available on these arches and we can allow + # more cores. but only up to a reasonable limit. User + # can always override these limits with --jobs. + return min(multiprocessing.cpu_count() // 2, 8) else: return 1 - parser = optparse.OptionParser( - description="VM test utility. Exit codes: " - "0 = success, " - "1 = command line error, " - "2 = environment initialization failed, " - "3 = test command failed") - parser.add_option("--debug", "-D", action="store_true", - help="enable debug output") - parser.add_option("--image", "-i", default="%s.img" % vmcls.name, - help="image file name") - parser.add_option("--force", "-f", action="store_true", - help="force build image even if image exists") - parser.add_option("--jobs", type=int, default=get_default_jobs(), - help="number of virtual CPUs") - parser.add_option("--verbose", "-V", action="store_true", - help="Pass V=1 to builds within the guest") - parser.add_option("--build-image", "-b", action="store_true", - help="build image") - parser.add_option("--build-qemu", - help="build QEMU from source in guest") - parser.add_option("--build-target", - help="QEMU build target", default="check") - parser.add_option("--interactive", "-I", action="store_true", - help="Interactively run command") - parser.add_option("--snapshot", "-s", action="store_true", - help="run tests with a snapshot") - parser.disable_interspersed_args() + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + description="Utility for provisioning VMs and running builds", + epilog="""Remaining arguments are passed to the command. + Exit codes: 0 = success, 1 = command line error, + 2 = environment initialization failed, + 3 = test command failed""") + parser.add_argument("--debug", "-D", action="store_true", + help="enable debug output") + parser.add_argument("--image", "-i", default="%s.img" % vmcls.name, + help="image file name") + parser.add_argument("--force", "-f", action="store_true", + help="force build image even if image exists") + parser.add_argument("--jobs", type=int, default=get_default_jobs(), + help="number of virtual CPUs") + parser.add_argument("--verbose", "-V", action="store_true", + help="Pass V=1 to builds within the guest") + parser.add_argument("--build-image", "-b", action="store_true", + help="build image") + parser.add_argument("--build-qemu", + help="build QEMU from source in guest") + parser.add_argument("--build-target", + help="QEMU build target", default="check") + parser.add_argument("--build-path", default=None, + help="Path of build directory, "\ + "for using build tree QEMU binary. ") + parser.add_argument("--interactive", "-I", action="store_true", + help="Interactively run command") + parser.add_argument("--snapshot", "-s", action="store_true", + help="run tests with a snapshot") + parser.add_argument("--genisoimage", default="genisoimage", + help="iso imaging tool") + parser.add_argument("--config", "-c", default=None, + help="Provide config yaml for configuration. "\ + "See config_example.yaml for example.") + parser.add_argument("--efi-aarch64", + default="/usr/share/qemu-efi-aarch64/QEMU_EFI.fd", + help="Path to efi image for aarch64 VMs.") + parser.add_argument("--log-console", action="store_true", + help="Log console to file.") + parser.add_argument("commands", nargs="*", help="""Remaining + commands after -- are passed to command inside the VM""") + return parser.parse_args() -def main(vmcls): +def main(vmcls, config=None): try: - args, argv = parse_args(vmcls) - if not argv and not args.build_qemu and not args.build_image: + if config == None: + config = DEFAULT_CONFIG + args = parse_args(vmcls) + if not args.commands and not args.build_qemu and not args.build_image: print("Nothing to do?") return 1 + config = parse_config(config, args) logging.basicConfig(level=(logging.DEBUG if args.debug else logging.WARN)) - vm = vmcls(debug=args.debug, vcpus=args.jobs) + vm = vmcls(args, config=config) if args.build_image: if os.path.exists(args.image) and not args.force: sys.stderr.writelines(["Image file exists: %s\n" % args.image, @@ -445,12 +635,12 @@ def main(vmcls): if args.build_qemu: vm.add_source_dir(args.build_qemu) cmd = [vm.BUILD_SCRIPT.format( - configure_opts = " ".join(argv), + configure_opts = " ".join(args.commands), jobs=int(args.jobs), target=args.build_target, verbose = "V=1" if args.verbose else "")] else: - cmd = argv + cmd = args.commands img = args.image if args.snapshot: img += ",snapshot=on" diff --git a/tests/vm/centos b/tests/vm/centos index 0ad4ecf4190e130cebdf804454ee07e8d65208e6..efe3dbbb360c69b36d00e47f9511b6376c0c75ee 100755 --- a/tests/vm/centos +++ b/tests/vm/centos @@ -42,7 +42,7 @@ class CentosVM(basevm.BaseVM): self.wait_ssh() self.ssh_root_check("touch /etc/cloud/cloud-init.disabled") self.ssh_root_check("yum update -y") - self.ssh_root_check("yum install -y docker make git python3") + self.ssh_root_check("yum install -y docker make ninja-build git python3") self.ssh_root_check("systemctl enable docker") self.ssh_root("poweroff") self.wait() diff --git a/tests/vm/centos-8-aarch64.ks b/tests/vm/centos-8-aarch64.ks new file mode 100644 index 0000000000000000000000000000000000000000..fd6ebe4d49ed523342e20620ab3e3da963e9a0b0 --- /dev/null +++ b/tests/vm/centos-8-aarch64.ks @@ -0,0 +1,51 @@ +# CentOS aarch64 image kickstart file. +# This file is used by the CentOS installer to +# script the generation of the image. +# +# Copyright 2020 Linaro +# +ignoredisk --only-use=vda +# System bootloader configuration +bootloader --append=" crashkernel=auto" --location=mbr --boot-drive=vda +autopart --type=plain +# Partition clearing information +clearpart --linux --initlabel --drives=vda +# Use text mode install +text +repo --name="AppStream" --baseurl=file:///run/install/repo/AppStream +# Use CDROM installation media +cdrom +# Keyboard layouts +keyboard --vckeymap=us --xlayouts='' +# System language +lang en_US.UTF-8 + +# Network information +network --bootproto=dhcp --device=enp0s1 --onboot=off --ipv6=auto --no-activate +network --hostname=localhost.localdomain +# Run the Setup Agent on first boot +firstboot --enable +# Do not configure the X Window System +skipx +# System services +services --enabled="chronyd" +# System timezone +timezone America/New_York --isUtc + +# Shutdown after installation is complete. +shutdown + +%packages +@^server-product-environment +kexec-tools + +%end + +%addon com_redhat_kdump --enable --reserve-mb='auto' + +%end +%anaconda +pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty +pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok +pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty +%end diff --git a/tests/vm/centos.aarch64 b/tests/vm/centos.aarch64 new file mode 100755 index 0000000000000000000000000000000000000000..e687b93e521e357e1bdf9e56cd37588c4dc6862b --- /dev/null +++ b/tests/vm/centos.aarch64 @@ -0,0 +1,227 @@ +#!/usr/bin/env python3 +# +# Centos aarch64 image +# +# Copyright 2020 Linaro +# +# Authors: +# Robert Foley +# Originally based on ubuntu.aarch64 +# +# This code is licensed under the GPL version 2 or later. See +# the COPYING file in the top-level directory. +# + +import os +import sys +import subprocess +import basevm +import time +import traceback +import aarch64vm + +DEFAULT_CONFIG = { + 'cpu' : "max", + 'machine' : "virt,gic-version=max", + 'install_cmds' : "yum install -y make ninja-build git python3 gcc gcc-c++ flex bison, "\ + "yum install -y glib2-devel pixman-devel zlib-devel, "\ + "yum install -y perl-Test-Harness, "\ + "alternatives --set python /usr/bin/python3, "\ + "sudo dnf config-manager "\ + "--add-repo=https://download.docker.com/linux/centos/docker-ce.repo,"\ + "sudo dnf install --nobest -y docker-ce.aarch64,"\ + "systemctl enable docker", + # We increase beyond the default time since during boot + # it can take some time (many seconds) to log into the VM. + 'ssh_timeout' : 60, +} + +class CentosAarch64VM(basevm.BaseVM): + name = "centos.aarch64" + arch = "aarch64" + login_prompt = "localhost login:" + prompt = '[root@localhost ~]#' + image_name = "CentOS-8-aarch64-1905-dvd1.iso" + image_link = "http://mirrors.usc.edu/pub/linux/distributions/centos/8.0.1905/isos/aarch64/" + image_link += image_name + BUILD_SCRIPT = """ + set -e; + cd $(mktemp -d); + sudo chmod a+r /dev/vdb; + tar --checkpoint=.10 -xf /dev/vdb; + ./configure {configure_opts}; + make --output-sync {target} -j{jobs} {verbose}; + """ + def set_key_perm(self): + """Set permissions properly on certain files to allow + ssh access.""" + self.console_wait_send(self.prompt, + "/usr/sbin/restorecon -R -v /root/.ssh\n") + self.console_wait_send(self.prompt, + "/usr/sbin/restorecon -R -v "\ + "/home/{}/.ssh\n".format(self._config["guest_user"])) + + def create_kickstart(self): + """Generate the kickstart file used to generate the centos image.""" + # Start with the template for the kickstart. + ks_file = "../tests/vm/centos-8-aarch64.ks" + subprocess.check_call("cp {} ./ks.cfg".format(ks_file), shell=True) + # Append the ssh keys to the kickstart file + # as the post processing phase of installation. + with open("ks.cfg", "a") as f: + # Add in the root pw and guest user. + rootpw = "rootpw --plaintext {}\n" + f.write(rootpw.format(self._config["root_pass"])) + add_user = "user --groups=wheel --name={} "\ + "--password={} --plaintext\n" + f.write(add_user.format(self._config["guest_user"], + self._config["guest_pass"])) + # Add the ssh keys. + f.write("%post --log=/root/ks-post.log\n") + f.write("mkdir -p /root/.ssh\n") + addkey = 'echo "{}" >> /root/.ssh/authorized_keys\n' + addkey_cmd = addkey.format(self._config["ssh_pub_key"]) + f.write(addkey_cmd) + f.write('mkdir -p /home/{}/.ssh\n'.format(self._config["guest_user"])) + addkey = 'echo "{}" >> /home/{}/.ssh/authorized_keys\n' + addkey_cmd = addkey.format(self._config["ssh_pub_key"], + self._config["guest_user"]) + f.write(addkey_cmd) + f.write("%end\n") + # Take our kickstart file and create an .iso from it. + # The .iso will be provided to qemu as we boot + # from the install dvd. + # Anaconda will recognize the label "OEMDRV" and will + # start the automated installation. + gen_iso_img = 'genisoimage -output ks.iso -volid "OEMDRV" ks.cfg' + subprocess.check_call(gen_iso_img, shell=True) + + def wait_for_shutdown(self): + """We wait for qemu to shutdown the VM and exit. + While this happens we display the console view + for easier debugging.""" + # The image creation is essentially done, + # so whether or not the wait is successful we want to + # wait for qemu to exit (the self.wait()) before we return. + try: + self.console_wait("reboot: Power down") + except Exception as e: + sys.stderr.write("Exception hit\n") + if isinstance(e, SystemExit) and e.code == 0: + return 0 + traceback.print_exc() + finally: + self.wait() + + def build_base_image(self, dest_img): + """Run through the centos installer to create + a base image with name dest_img.""" + # We create the temp image, and only rename + # to destination when we are done. + img = dest_img + ".tmp" + # Create an empty image. + # We will provide this as the install destination. + qemu_img_create = "qemu-img create {} 50G".format(img) + subprocess.check_call(qemu_img_create, shell=True) + + # Create our kickstart file to be fed to the installer. + self.create_kickstart() + # Boot the install dvd with the params as our ks.iso + os_img = self._download_with_cache(self.image_link) + dvd_iso = "centos-8-dvd.iso" + subprocess.check_call(["cp", "-f", os_img, dvd_iso]) + extra_args = "-cdrom ks.iso" + extra_args += " -drive file={},if=none,id=drive1,cache=writeback" + extra_args += " -device virtio-blk,drive=drive1,bootindex=1" + extra_args = extra_args.format(dvd_iso).split(" ") + self.boot(img, extra_args=extra_args) + self.console_wait_send("change the selection", "\n") + # We seem to need to hit esc (chr(27)) twice to abort the + # media check, which takes a long time. + # Waiting a bit seems to be more reliable before hitting esc. + self.console_wait("Checking") + time.sleep(5) + self.console_wait_send("Checking", chr(27)) + time.sleep(5) + self.console_wait_send("Checking", chr(27)) + print("Found Checking") + # Give sufficient time for the installer to create the image. + self.console_init(timeout=7200) + self.wait_for_shutdown() + os.rename(img, dest_img) + print("Done with base image build: {}".format(dest_img)) + + def check_create_base_img(self, img_base, img_dest): + """Create a base image using the installer. + We will use the base image if it exists. + This helps cut down on install time in case we + need to restart image creation, + since the base image creation can take a long time.""" + if not os.path.exists(img_base): + print("Generate new base image: {}".format(img_base)) + self.build_base_image(img_base); + else: + print("Use existing base image: {}".format(img_base)) + # Save a copy of the base image and copy it to dest. + # which we will use going forward. + subprocess.check_call(["cp", img_base, img_dest]) + + def boot(self, img, extra_args=None): + aarch64vm.create_flash_images(self._tmpdir, self._efi_aarch64) + default_args = aarch64vm.get_pflash_args(self._tmpdir) + if extra_args: + extra_args.extend(default_args) + else: + extra_args = default_args + # We always add these performance tweaks + # because without them, we boot so slowly that we + # can time out finding the boot efi device. + if '-smp' not in extra_args and \ + '-smp' not in self._config['extra_args'] and \ + '-smp' not in self._args: + # Only add if not already there to give caller option to change it. + extra_args.extend(["-smp", "8"]) + # We have overridden boot() since aarch64 has additional parameters. + # Call down to the base class method. + super(CentosAarch64VM, self).boot(img, extra_args=extra_args) + + def build_image(self, img): + img_tmp = img + ".tmp" + self.check_create_base_img(img + ".base", img_tmp) + + # Boot the new image for the first time to finish installation. + self.boot(img_tmp) + self.console_init() + self.console_wait_send(self.login_prompt, "root\n") + self.console_wait_send("Password:", + "{}\n".format(self._config["root_pass"])) + + self.set_key_perm() + self.console_wait_send(self.prompt, "rpm -q centos-release\n") + enable_adapter = "sed -i 's/ONBOOT=no/ONBOOT=yes/g'" \ + " /etc/sysconfig/network-scripts/ifcfg-enp0s1\n" + self.console_wait_send(self.prompt, enable_adapter) + self.console_wait_send(self.prompt, "ifup enp0s1\n") + self.console_wait_send(self.prompt, + 'echo "qemu ALL=(ALL) NOPASSWD:ALL" | '\ + 'sudo tee /etc/sudoers.d/qemu\n') + self.console_wait(self.prompt) + + # Rest of the commands we issue through ssh. + self.wait_ssh(wait_root=True) + + # If the user chooses *not* to do the second phase, + # then we will jump right to the graceful shutdown + if self._config['install_cmds'] != "": + install_cmds = self._config['install_cmds'].split(',') + for cmd in install_cmds: + self.ssh_root(cmd) + self.ssh_root("poweroff") + self.wait_for_shutdown() + os.rename(img_tmp, img) + print("image creation complete: {}".format(img)) + return 0 + +if __name__ == "__main__": + defaults = aarch64vm.get_config_defaults(CentosAarch64VM, DEFAULT_CONFIG) + sys.exit(basevm.main(CentosAarch64VM, defaults)) diff --git a/tests/vm/conf_example_aarch64.yml b/tests/vm/conf_example_aarch64.yml new file mode 100644 index 0000000000000000000000000000000000000000..9d44ae356f7c2513f23a7c4ca4a03a5efe12d6db --- /dev/null +++ b/tests/vm/conf_example_aarch64.yml @@ -0,0 +1,51 @@ +# +# Example yaml for use by any of the scripts in tests/vm. +# Can be provided as an environment variable QEMU_CONFIG +# +qemu-conf: + + # If any of the below are not provided, we will just use the qemu defaults. + + # Login username and password(has to be sudo enabled) + guest_user: qemu + guest_pass: "qemupass" + + # Password for root user can be different from guest. + root_pass: "qemupass" + + # If one key is provided, both must be provided. + #ssh_key: /complete/path/of/your/keyfile/id_rsa + #ssh_pub_key: /complete/path/of/your/keyfile/id_rsa.pub + + cpu: max + machine: virt,gic-version=max + memory: 16G + + # The below is a example for how to configure NUMA topology with + # 4 NUMA nodes and 2 different NUMA distances. + qemu_args: "-smp cpus=16,sockets=2,cores=8 + -numa node,cpus=0-3,nodeid=0 -numa node,cpus=4-7,nodeid=1 + -numa node,cpus=8-11,nodeid=2 -numa node,cpus=12-15,nodeid=3 + -numa dist,src=0,dst=1,val=15 -numa dist,src=2,dst=3,val=15 + -numa dist,src=0,dst=2,val=20 -numa dist,src=0,dst=3,val=20 + -numa dist,src=1,dst=2,val=20 -numa dist,src=1,dst=3,val=20" + + # By default we do not set the DNS. + # You override the defaults by setting the below. + #dns: 1.234.567.89 + + # By default we will use a "block" device, but + # you can also boot from a "scsi" device. + # Just keep in mind your scripts might need to change + # As you will have /dev/sda instead of /dev/vda (for block device) + boot_dev_type: "block" + + # By default the ssh port is not fixed. + # A fixed ssh port makes it easier for automated tests. + #ssh_port: 5555 + + # To install a different set of packages, provide a command to issue + #install_cmds: "apt-get update ; apt-get build-dep -y qemu" + + # Or to skip the install entirely, just provide "" + #install_cmds: "" diff --git a/tests/vm/conf_example_x86.yml b/tests/vm/conf_example_x86.yml new file mode 100644 index 0000000000000000000000000000000000000000..78d3f5830fa21abd21679b1d749e0f49abf0820c --- /dev/null +++ b/tests/vm/conf_example_x86.yml @@ -0,0 +1,50 @@ +# +# Example yaml for use by any of the x86 based scripts in tests/vm. +# Can be provided as an environment variable QEMU_CONFIG +# +qemu-conf: + + # If any of the below are not provided, we will just use the qemu defaults. + + # Login username and password(has to be sudo enabled) + guest_user: "qemu" + guest_pass: "qemupass" + + # Password for root user can be different from guest. + root_pass: "qemupass" + + # Provide default ssh keys of current user. + # You need to edit the below for your user. + #ssh_key_file: /home//.ssh/id_rsa + #ssh_pub_key_file: /home//.ssh/id_rsa.pub + + cpu: max + machine: pc + memory: 8G + + # The below is a example for how to configure NUMA topology with + # 4 NUMA nodes and 2 different NUMA distances. + qemu_args: "-smp cpus=8,sockets=2,cores=4 + -object memory-backend-ram,size=4G,policy=bind,host-nodes=0,id=ram-node0 + -object memory-backend-ram,size=4G,policy=bind,host-nodes=0,id=ram-node1 + -object memory-backend-ram,size=4G,policy=bind,host-nodes=1,id=ram-node2 + -object memory-backend-ram,size=4G,policy=bind,host-nodes=1,id=ram-node3 + -numa node,cpus=0-1,nodeid=0 -numa node,cpus=2-3,nodeid=1 + -numa node,cpus=4-5,nodeid=2 -numa node,cpus=6-7,nodeid=3 + -numa dist,src=0,dst=1,val=15 -numa dist,src=2,dst=3,val=15 + -numa dist,src=0,dst=2,val=20 -numa dist,src=0,dst=3,val=20 + -numa dist,src=1,dst=2,val=20 -numa dist,src=1,dst=3,val=20" + + # By default we do not set the DNS. + # You override the defaults by setting the below. + #dns: "1.234.567.89" + + # By default we will use a "block" device, but + # you can also boot from a "scsi" device. + # Just keep in mind your scripts might need to change + # As you will have /dev/sda instead of /dev/vda (for block device) + boot_dev_type: "block" + + # By default the ssh port is not fixed. + # A fixed ssh port makes it easier for automated tests. + ssh_port: 5555 diff --git a/tests/vm/fedora b/tests/vm/fedora index bd9c6cf295c13c391ff11bf4d9ca046b94f2ae11..b977efe4a2eb36381da2fb7204e19dbb2cfdbf8b 100755 --- a/tests/vm/fedora +++ b/tests/vm/fedora @@ -32,8 +32,7 @@ class FedoraVM(basevm.BaseVM): pkgs = [ # tools 'git-core', - 'flex', 'bison', - 'gcc', 'binutils', 'make', + 'gcc', 'binutils', 'make', 'ninja-build', # perl 'perl-Test-Harness', @@ -109,20 +108,20 @@ class FedoraVM(basevm.BaseVM): self.console_wait_send("7) [!] Root password", "7\n") self.console_wait("Password:") - self.console_send("%s\n" % self.ROOT_PASS) + self.console_send("%s\n" % self._config["root_pass"]) self.console_wait("Password (confirm):") - self.console_send("%s\n" % self.ROOT_PASS) + self.console_send("%s\n" % self._config["root_pass"]) self.console_wait_send("8) [ ] User creation", "8\n") self.console_wait_send("1) [ ] Create user", "1\n") self.console_wait_send("3) User name", "3\n") - self.console_wait_send("ENTER:", "%s\n" % self.GUEST_USER) + self.console_wait_send("ENTER:", "%s\n" % self._config["guest_user"]) self.console_wait_send("4) [ ] Use password", "4\n") self.console_wait_send("5) Password", "5\n") self.console_wait("Password:") - self.console_send("%s\n" % self.GUEST_PASS) + self.console_send("%s\n" % self._config["guest_pass"]) self.console_wait("Password (confirm):") - self.console_send("%s\n" % self.GUEST_PASS) + self.console_send("%s\n" % self._config["guest_pass"]) self.console_wait_send("7) Groups", "c\n") while True: @@ -140,7 +139,7 @@ class FedoraVM(basevm.BaseVM): if good: break time.sleep(10) - self.console_send("r\n" % self.GUEST_PASS) + self.console_send("r\n" % self._config["guest_pass"]) self.console_wait_send("'b' to begin install", "b\n") @@ -151,12 +150,13 @@ class FedoraVM(basevm.BaseVM): # setup qemu user prompt = " ~]$" - self.console_ssh_init(prompt, self.GUEST_USER, self.GUEST_PASS) + self.console_ssh_init(prompt, self._config["guest_user"], + self._config["guest_pass"]) self.console_wait_send(prompt, "exit\n") # setup root user prompt = " ~]#" - self.console_ssh_init(prompt, "root", self.ROOT_PASS) + self.console_ssh_init(prompt, "root", self._config["root_pass"]) self.console_sshd_config(prompt) # setup virtio-blk #1 (tarfile) diff --git a/tests/vm/freebsd b/tests/vm/freebsd index 298967fe9cf4fa48c2ab5f1f815ef8712ef6bc58..09f3ee6cb824a72f6f1d17aaad61e3193d287caf 100755 --- a/tests/vm/freebsd +++ b/tests/vm/freebsd @@ -33,12 +33,13 @@ class FreeBSDVM(basevm.BaseVM): "pkgconf", "bzip2", "python37", + "ninja", # gnu tools "bash", "gmake", "gsed", - "flex", "bison", + "gettext", # libs: crypto "gnutls", @@ -114,9 +115,9 @@ class FreeBSDVM(basevm.BaseVM): # post-install configuration self.console_wait("New Password:") - self.console_send("%s\n" % self.ROOT_PASS) + self.console_send("%s\n" % self._config["root_pass"]) self.console_wait("Retype New Password:") - self.console_send("%s\n" % self.ROOT_PASS) + self.console_send("%s\n" % self._config["root_pass"]) self.console_wait_send("Network Configuration", "\n") self.console_wait_send("IPv4", "y") @@ -135,9 +136,9 @@ class FreeBSDVM(basevm.BaseVM): # qemu user self.console_wait_send("Add User Accounts", "y") self.console_wait("Username") - self.console_send("%s\n" % self.GUEST_USER) + self.console_send("%s\n" % self._config["guest_user"]) self.console_wait("Full name") - self.console_send("%s\n" % self.GUEST_USER) + self.console_send("%s\n" % self._config["guest_user"]) self.console_wait_send("Uid", "\n") self.console_wait_send("Login group", "\n") self.console_wait_send("Login group", "\n") @@ -149,9 +150,9 @@ class FreeBSDVM(basevm.BaseVM): self.console_wait_send("Use an empty password", "\n") self.console_wait_send("Use a random password", "\n") self.console_wait("Enter password:") - self.console_send("%s\n" % self.GUEST_PASS) + self.console_send("%s\n" % self._config["guest_pass"]) self.console_wait("Enter password again:") - self.console_send("%s\n" % self.GUEST_PASS) + self.console_send("%s\n" % self._config["guest_pass"]) self.console_wait_send("Lock out", "\n") self.console_wait_send("OK", "yes\n") self.console_wait_send("Add another user", "no\n") @@ -165,12 +166,12 @@ class FreeBSDVM(basevm.BaseVM): # setup qemu user prompt = "$" - self.console_ssh_init(prompt, self.GUEST_USER, self.GUEST_PASS) + self.console_ssh_init(prompt, self._config["guest_user"], self._config["guest_pass"]) self.console_wait_send(prompt, "exit\n") # setup root user prompt = "root@freebsd:~ #" - self.console_ssh_init(prompt, "root", self.ROOT_PASS) + self.console_ssh_init(prompt, "root", self._config["root_pass"]) self.console_sshd_config(prompt) # setup serial console diff --git a/tests/vm/haiku.x86_64 b/tests/vm/haiku.x86_64 new file mode 100755 index 0000000000000000000000000000000000000000..2eb736dae125f6b6150307ae7f16a3808fa0d7d1 --- /dev/null +++ b/tests/vm/haiku.x86_64 @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +# +# Haiku VM image +# +# Copyright 2020 Haiku, Inc. +# +# Authors: +# Alexander von Gluck IV +# +# This code is licensed under the GPL version 2 or later. See +# the COPYING file in the top-level directory. +# + +import os +import re +import sys +import time +import socket +import subprocess +import basevm + +VAGRANT_KEY_FILE = os.path.join(os.path.dirname(__file__), + "..", "keys", "vagrant") + +VAGRANT_PUB_KEY_FILE = os.path.join(os.path.dirname(__file__), + "..", "keys", "vagrant.pub") + +HAIKU_CONFIG = { + 'cpu' : "max", + 'machine' : 'pc', + 'guest_user' : "vagrant", + 'guest_pass' : "", + 'root_user' : "vagrant", + 'root_pass' : "", + 'ssh_key_file' : VAGRANT_KEY_FILE, + 'ssh_pub_key_file': VAGRANT_PUB_KEY_FILE, + 'memory' : "4G", + 'extra_args' : [], + 'qemu_args' : "-device VGA", + 'dns' : "", + 'ssh_port' : 0, + 'install_cmds' : "", + 'boot_dev_type' : "block", + 'ssh_timeout' : 1, +} + +class HaikuVM(basevm.BaseVM): + name = "haiku" + arch = "x86_64" + + link = "https://app.vagrantup.com/haiku-os/boxes/r1beta2-x86_64/versions/20200702/providers/libvirt.box" + csum = "41c38b316e0cbdbc66b5dbaf3612b866700a4f35807cb1eb266a5bf83e9e68d5" + + poweroff = "shutdown" + + requirements = [ + "devel:libbz2", + "devel:libcapstone", + "devel:libcurl", + "devel:libfdt", + "devel:libgcrypt", + "devel:libgl", + "devel:libglib_2.0", + "devel:libgnutls", + "devel:libgpg_error", + "devel:libintl", + "devel:libjpeg", + "devel:liblzo2", + "devel:libncursesw", + "devel:libnettle", + "devel:libpixman_1", + "devel:libpng16", + "devel:libsdl2_2.0", + "devel:libsnappy", + "devel:libssh2", + "devel:libtasn1", + "devel:libusb_1.0", + "devel:libz", + "ninja", + ] + + # https://dev.haiku-os.org/ticket/16512 virtio disk1 shows up as 0 (reversed order) + BUILD_SCRIPT = """ + set -e; + rm -rf /tmp/qemu-test.* + cd $(mktemp -d /tmp/qemu-test.XXXXXX); + mkdir src build; cd src; + tar -xf /dev/disk/virtual/virtio_block/0/raw; + mkdir -p /usr/bin + ln -s /boot/system/bin/env /usr/bin/env + cd ../build + ../src/configure --disable-slirp {configure_opts}; + make --output-sync -j{jobs} {target} {verbose}; + """ + + def build_image(self, img): + self.print_step("Downloading disk image") + tarball = self._download_with_cache(self.link, sha256sum=self.csum) + + self.print_step("Extracting disk image") + + subprocess.check_call(["tar", "xzf", tarball, "./box.img", "-O"], + stdout=open(img, 'wb')) + + self.print_step("Preparing disk image") + self.boot(img) + + # Wait for ssh to be available. + self.wait_ssh(wait_root=True, cmd="exit 0") + + # Install packages + self.ssh_root("pkgman install -y %s" % " ".join(self.requirements)) + self.graceful_shutdown() + + self.print_step("All done") + +if __name__ == "__main__": + sys.exit(basevm.main(HaikuVM, config=HAIKU_CONFIG)) diff --git a/tests/vm/netbsd b/tests/vm/netbsd index b10c9d429ded2302d47a60416b562466733c8688..b9efc269d262cea532eeb06edebd4bc08bf6796b 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.0/images/NetBSD-9.0-amd64.iso" - csum = "34da4882ee61bdbf69f241195a8933dc800949d30b43fc6988da853d57fc2b8cac50cf97a0d2adaf93250b4e329d189c1a8b83c33bd515226f37745d50c33369" + link = "https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.1/images/NetBSD-9.1-amd64.iso" + csum = "65bddc95945991c3b2021f9c8ded7f34c25f0a7611b7aa15a15fe23399e902307e926ae97fcd01dc1662ac67b5f6e4be643c6a2b581692ddcb616d30125066f9" size = "20G" pkgs = [ # tools @@ -31,12 +31,13 @@ class NetBSDVM(basevm.BaseVM): "pkgconf", "xz", "python37", + "ninja-build", # gnu tools "bash", "gmake", "gsed", - "flex", "bison", + "gettext-tools", # libs: crypto "gnutls", @@ -121,24 +122,24 @@ class NetBSDVM(basevm.BaseVM): self.console_wait_send("d: Change root password", "d\n") self.console_wait_send("a: Yes", "a\n") self.console_wait("New password:") - self.console_send("%s\n" % self.ROOT_PASS) + self.console_send("%s\n" % self._config["root_pass"]) self.console_wait("New password:") - self.console_send("%s\n" % self.ROOT_PASS) + self.console_send("%s\n" % self._config["root_pass"]) self.console_wait("Retype new password:") - self.console_send("%s\n" % self.ROOT_PASS) + self.console_send("%s\n" % self._config["root_pass"]) self.console_wait_send("o: Add a user", "o\n") self.console_wait("username") - self.console_send("%s\n" % self.GUEST_USER) + self.console_send("%s\n" % self._config["guest_user"]) self.console_wait("to group wheel") self.console_wait_send("a: Yes", "a\n") self.console_wait_send("a: /bin/sh", "a\n") self.console_wait("New password:") - self.console_send("%s\n" % self.GUEST_PASS) + self.console_send("%s\n" % self._config["guest_pass"]) self.console_wait("New password:") - self.console_send("%s\n" % self.GUEST_PASS) + self.console_send("%s\n" % self._config["guest_pass"]) self.console_wait("Retype new password:") - self.console_send("%s\n" % self.GUEST_PASS) + self.console_send("%s\n" % self._config["guest_pass"]) self.console_wait_send("a: Configure network", "a\n") self.console_wait_send("a: vioif0", "a\n") @@ -171,12 +172,13 @@ class NetBSDVM(basevm.BaseVM): # setup qemu user prompt = "localhost$" - self.console_ssh_init(prompt, self.GUEST_USER, self.GUEST_PASS) + self.console_ssh_init(prompt, self._config["guest_user"], + self._config["guest_pass"]) self.console_wait_send(prompt, "exit\n") # setup root user prompt = "localhost#" - self.console_ssh_init(prompt, "root", self.ROOT_PASS) + self.console_ssh_init(prompt, "root", self._config["root_pass"]) self.console_sshd_config(prompt) # setup virtio-blk #1 (tarfile) diff --git a/tests/vm/openbsd b/tests/vm/openbsd index 0b705f494527b7351eb020561652fdf9d6ebc3e5..4d1399378e67b8141f7a9a903451f20cb6bc5a61 100755 --- a/tests/vm/openbsd +++ b/tests/vm/openbsd @@ -22,23 +22,24 @@ class OpenBSDVM(basevm.BaseVM): name = "openbsd" arch = "x86_64" - link = "https://cdn.openbsd.org/pub/OpenBSD/6.6/amd64/install66.iso" - csum = "b22e63df56e6266de6bbeed8e9be0fbe9ee2291551c5bc03f3cc2e4ab9436ee3" + link = "https://cdn.openbsd.org/pub/OpenBSD/6.8/amd64/install68.iso" + csum = "47e291fcc2d0c1a8ae0b66329f040b33af755b6adbd21739e20bb5ad56f62b6c" size = "20G" pkgs = [ # tools "git", "pkgconf", "bzip2", "xz", + "ninja", # gnu tools "bash", "gmake", "gsed", - "bison", + "gettext-tools", # libs: usb - "libusb1", + "libusb1--", # libs: crypto "gnutls", @@ -99,9 +100,9 @@ class OpenBSDVM(basevm.BaseVM): self.console_wait_send("Which network interface", "done\n") self.console_wait_send("DNS domain name", "localnet\n") self.console_wait("Password for root account") - self.console_send("%s\n" % self.ROOT_PASS) + self.console_send("%s\n" % self._config["root_pass"]) self.console_wait("Password for root account") - self.console_send("%s\n" % self.ROOT_PASS) + self.console_send("%s\n" % self._config["root_pass"]) self.console_wait_send("Start sshd(8)", "yes\n") self.console_wait_send("X Window System", "\n") self.console_wait_send("xenodm", "\n") @@ -109,13 +110,13 @@ class OpenBSDVM(basevm.BaseVM): self.console_wait_send("Which speed", "\n") self.console_wait("Setup a user") - self.console_send("%s\n" % self.GUEST_USER) + self.console_send("%s\n" % self._config["guest_user"]) self.console_wait("Full name") - self.console_send("%s\n" % self.GUEST_USER) + self.console_send("%s\n" % self._config["guest_user"]) self.console_wait("Password") - self.console_send("%s\n" % self.GUEST_PASS) + self.console_send("%s\n" % self._config["guest_pass"]) self.console_wait("Password") - self.console_send("%s\n" % self.GUEST_PASS) + self.console_send("%s\n" % self._config["guest_pass"]) self.console_wait_send("Allow root ssh login", "yes\n") self.console_wait_send("timezone", "UTC\n") @@ -136,12 +137,13 @@ class OpenBSDVM(basevm.BaseVM): # setup qemu user prompt = "$" - self.console_ssh_init(prompt, self.GUEST_USER, self.GUEST_PASS) + self.console_ssh_init(prompt, self._config["guest_user"], + self._config["guest_pass"]) self.console_wait_send(prompt, "exit\n") # setup root user prompt = "openbsd#" - self.console_ssh_init(prompt, "root", self.ROOT_PASS) + self.console_ssh_init(prompt, "root", self._config["root_pass"]) self.console_sshd_config(prompt) # setup virtio-blk #1 (tarfile) diff --git a/tests/vm/ubuntu.aarch64 b/tests/vm/ubuntu.aarch64 new file mode 100755 index 0000000000000000000000000000000000000000..b291945a7e9d99585afcab00b426fc9a8c7c2a9b --- /dev/null +++ b/tests/vm/ubuntu.aarch64 @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +# +# Ubuntu aarch64 image +# +# Copyright 2020 Linaro +# +# Authors: +# Robert Foley +# Originally based on ubuntu.i386 Fam Zheng +# +# This code is licensed under the GPL version 2 or later. See +# the COPYING file in the top-level directory. +# + +import sys +import basevm +import aarch64vm +import ubuntuvm + +DEFAULT_CONFIG = { + 'cpu' : "cortex-a57", + 'machine' : "virt,gic-version=3", + 'install_cmds' : "apt-get update,"\ + "apt-get build-dep -y --arch-only qemu,"\ + "apt-get install -y libfdt-dev pkg-config language-pack-en ninja-build", + # We increase beyond the default time since during boot + # it can take some time (many seconds) to log into the VM + # especially using softmmu. + 'ssh_timeout' : 60, +} + +class UbuntuAarch64VM(ubuntuvm.UbuntuVM): + name = "ubuntu.aarch64" + arch = "aarch64" + image_name = "ubuntu-18.04-server-cloudimg-arm64.img" + image_link = "https://cloud-images.ubuntu.com/releases/18.04/release/" + image_name + image_sha256="0fdcba761965735a8a903d8b88df8e47f156f48715c00508e4315c506d7d3cb1" + BUILD_SCRIPT = """ + set -e; + cd $(mktemp -d); + sudo chmod a+r /dev/vdb; + tar --checkpoint=.10 -xf /dev/vdb; + ./configure {configure_opts}; + make --output-sync {target} -j{jobs} {verbose}; + """ + def boot(self, img, extra_args=None): + aarch64vm.create_flash_images(self._tmpdir, self._efi_aarch64) + default_args = aarch64vm.get_pflash_args(self._tmpdir) + if extra_args: + extra_args.extend(default_args) + else: + extra_args = default_args + # We always add these performance tweaks + # because without them, we boot so slowly that we + # can time out finding the boot efi device. + if '-smp' not in extra_args and \ + '-smp' not in self._config['extra_args'] and \ + '-smp' not in self._args: + # Only add if not already there to give caller option to change it. + extra_args.extend(["-smp", "8"]) + + # We have overridden boot() since aarch64 has additional parameters. + # Call down to the base class method. + super(UbuntuAarch64VM, self).boot(img, extra_args=extra_args) + +if __name__ == "__main__": + defaults = aarch64vm.get_config_defaults(UbuntuAarch64VM, DEFAULT_CONFIG) + sys.exit(basevm.main(UbuntuAarch64VM, defaults)) diff --git a/tests/vm/ubuntu.i386 b/tests/vm/ubuntu.i386 index 157077533532f1c5f49d2b6accb9429cc05f66ac..47681b6f87dd895882767d4ce4b2687b976de0b7 100755 --- a/tests/vm/ubuntu.i386 +++ b/tests/vm/ubuntu.i386 @@ -11,15 +11,22 @@ # the COPYING file in the top-level directory. # -import os import sys -import subprocess import basevm -import time +import ubuntuvm -class UbuntuX86VM(basevm.BaseVM): +DEFAULT_CONFIG = { + 'install_cmds' : "apt-get update,"\ + "apt-get build-dep -y qemu,"\ + "apt-get install -y libfdt-dev language-pack-en ninja-build", +} + +class UbuntuX86VM(ubuntuvm.UbuntuVM): name = "ubuntu.i386" arch = "i386" + image_link="https://cloud-images.ubuntu.com/releases/bionic/"\ + "release-20191114/ubuntu-18.04-server-cloudimg-i386.img" + image_sha256="28969840626d1ea80bb249c08eef1a4533e8904aa51a327b40f37ac4b4ff04ef" BUILD_SCRIPT = """ set -e; cd $(mktemp -d); @@ -29,34 +36,5 @@ class UbuntuX86VM(basevm.BaseVM): make --output-sync {target} -j{jobs} {verbose}; """ - def build_image(self, img): - cimg = self._download_with_cache( - "https://cloud-images.ubuntu.com/releases/bionic/release-20191114/ubuntu-18.04-server-cloudimg-i386.img", - sha256sum="28969840626d1ea80bb249c08eef1a4533e8904aa51a327b40f37ac4b4ff04ef") - img_tmp = img + ".tmp" - subprocess.check_call(["cp", "-f", cimg, img_tmp]) - self.exec_qemu_img("resize", img_tmp, "50G") - self.boot(img_tmp, extra_args = [ - "-device", "VGA", - "-cdrom", self.gen_cloud_init_iso() - ]) - self.wait_ssh() - self.ssh_root_check("touch /etc/cloud/cloud-init.disabled") - self.ssh_root_check("apt-get update") - self.ssh_root_check("apt-get install -y cloud-initramfs-growroot") - # Don't check the status in case the guest hang up too quickly - self.ssh_root("sync && reboot") - time.sleep(5) - self.wait_ssh() - # The previous update sometimes doesn't survive a reboot, so do it again - self.ssh_root_check("sed -ie s/^#\ deb-src/deb-src/g /etc/apt/sources.list") - self.ssh_root_check("apt-get update") - self.ssh_root_check("apt-get build-dep -y qemu") - self.ssh_root_check("apt-get install -y libfdt-dev flex bison language-pack-en") - self.ssh_root("poweroff") - self.wait() - os.rename(img_tmp, img) - return 0 - if __name__ == "__main__": - sys.exit(basevm.main(UbuntuX86VM)) + sys.exit(basevm.main(UbuntuX86VM, DEFAULT_CONFIG)) diff --git a/tests/vm/ubuntuvm.py b/tests/vm/ubuntuvm.py new file mode 100644 index 0000000000000000000000000000000000000000..6689ad87aa83d5fdd3caaacc28d2097bf4d8c86b --- /dev/null +++ b/tests/vm/ubuntuvm.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +# +# Ubuntu VM testing library +# +# Copyright 2017 Red Hat Inc. +# Copyright 2020 Linaro +# +# Authors: +# Robert Foley +# Originally based on ubuntu.i386 Fam Zheng +# +# This code is licensed under the GPL version 2 or later. See +# the COPYING file in the top-level directory. + +import os +import subprocess +import basevm + +class UbuntuVM(basevm.BaseVM): + + def __init__(self, args, config=None): + self.login_prompt = "ubuntu-{}-guest login:".format(self.arch) + basevm.BaseVM.__init__(self, args, config) + + def build_image(self, img): + """Build an Ubuntu VM image. The child class will + define the install_cmds to init the VM.""" + os_img = self._download_with_cache(self.image_link, + sha256sum=self.image_sha256) + img_tmp = img + ".tmp" + subprocess.check_call(["cp", "-f", os_img, img_tmp]) + self.exec_qemu_img("resize", img_tmp, "+50G") + ci_img = self.gen_cloud_init_iso() + + self.boot(img_tmp, extra_args = [ "-device", "VGA", "-cdrom", ci_img, ]) + + # First command we issue is fix for slow ssh login. + self.wait_ssh(wait_root=True, + cmd="chmod -x /etc/update-motd.d/*") + # Wait for cloud init to finish + self.wait_ssh(wait_root=True, + cmd="ls /var/lib/cloud/instance/boot-finished") + self.ssh_root("touch /etc/cloud/cloud-init.disabled") + # Disable auto upgrades. + # We want to keep the VM system state stable. + self.ssh_root('sed -ie \'s/"1"/"0"/g\' '\ + '/etc/apt/apt.conf.d/20auto-upgrades') + self.ssh_root("sed -ie s/^#\ deb-src/deb-src/g /etc/apt/sources.list") + + # If the user chooses not to do the install phase, + # then we will jump right to the graceful shutdown + if self._config['install_cmds'] != "": + # Issue the install commands. + # This can be overriden by the user in the config .yml. + install_cmds = self._config['install_cmds'].split(',') + for cmd in install_cmds: + self.ssh_root(cmd) + self.graceful_shutdown() + os.rename(img_tmp, img) + return 0 diff --git a/thunk.c b/thunk.c index 7f31cffe0968c87a83d59b27ecab2f1f79e78d99..fc5be1a502e7b511adb82b7f2676e13655940a0c 100644 --- a/thunk.c +++ b/thunk.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -271,6 +271,165 @@ const argtype *thunk_convert(void *dst, const void *src, return type_ptr; } +const argtype *thunk_print(void *arg, const argtype *type_ptr) +{ + int type; + + type = *type_ptr++; + + switch (type) { + case TYPE_CHAR: + qemu_log("%c", *(uint8_t *)arg); + break; + case TYPE_SHORT: + qemu_log("%" PRId16, tswap16(*(uint16_t *)arg)); + break; + case TYPE_INT: + qemu_log("%" PRId32, tswap32(*(uint32_t *)arg)); + break; + case TYPE_LONGLONG: + qemu_log("%" PRId64, tswap64(*(uint64_t *)arg)); + break; + case TYPE_ULONGLONG: + qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg)); + break; +#if HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 32 + case TYPE_PTRVOID: + qemu_log("0x%" PRIx32, tswap32(*(uint32_t *)arg)); + break; + case TYPE_LONG: + qemu_log("%" PRId32, tswap32(*(uint32_t *)arg)); + break; + case TYPE_ULONG: + qemu_log("%" PRIu32, tswap32(*(uint32_t *)arg)); + break; +#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32 + case TYPE_PTRVOID: + qemu_log("0x%" PRIx32, tswap32(*(uint64_t *)arg & 0xffffffff)); + break; + case TYPE_LONG: + qemu_log("%" PRId32, tswap32(*(uint64_t *)arg & 0xffffffff)); + break; + case TYPE_ULONG: + qemu_log("%" PRIu32, tswap32(*(uint64_t *)arg & 0xffffffff)); + break; +#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64 + case TYPE_PTRVOID: + qemu_log("0x%" PRIx64, tswap64(*(uint64_t *)arg)); + break; + case TYPE_LONG: + qemu_log("%" PRId64, tswap64(*(uint64_t *)arg)); + break; + case TYPE_ULONG: + qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg)); + break; +#else + case TYPE_PTRVOID: + qemu_log("0x%" PRIx64, tswap64(*(uint64_t *)arg)); + break; + case TYPE_LONG: + qemu_log("%" PRId64, tswap64(*(uint64_t *)arg)); + break; + case TYPE_ULONG: + qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg)); + break; +#endif + case TYPE_OLDDEVT: + { + uint64_t val = 0; + switch (thunk_type_size(type_ptr - 1, 1)) { + case 2: + val = *(uint16_t *)arg; + break; + case 4: + val = *(uint32_t *)arg; + break; + case 8: + val = *(uint64_t *)arg; + break; + } + switch (thunk_type_size(type_ptr - 1, 0)) { + case 2: + qemu_log("%" PRIu16, tswap16(val)); + break; + case 4: + qemu_log("%" PRIu32, tswap32(val)); + break; + case 8: + qemu_log("%" PRIu64, tswap64(val)); + break; + } + } + break; + case TYPE_ARRAY: + { + int i, array_length, arg_size; + uint8_t *a; + int is_string = 0; + + array_length = *type_ptr++; + arg_size = thunk_type_size(type_ptr, 0); + a = arg; + + if (*type_ptr == TYPE_CHAR) { + qemu_log("\""); + is_string = 1; + } else { + qemu_log("["); + } + + for (i = 0; i < array_length; i++) { + if (i > 0 && !is_string) { + qemu_log(","); + } + thunk_print(a, type_ptr); + a += arg_size; + } + + if (is_string) { + qemu_log("\""); + } else { + qemu_log("]"); + } + + type_ptr = thunk_type_next(type_ptr); + } + break; + case TYPE_STRUCT: + { + int i; + const StructEntry *se; + uint8_t *a; + const argtype *field_types; + const int *arg_offsets; + + se = struct_entries + *type_ptr++; + + if (se->print != NULL) { + se->print(arg); + } else { + a = arg; + + field_types = se->field_types; + arg_offsets = se->field_offsets[0]; + + qemu_log("{"); + for (i = 0; i < se->nb_fields; i++) { + if (i > 0) { + qemu_log(","); + } + field_types = thunk_print(a + arg_offsets[i], field_types); + } + qemu_log("}"); + } + } + break; + default: + g_assert_not_reached(); + } + return type_ptr; +} + /* from em86 */ /* Utility function: Table-driven functions to translate bitmasks diff --git a/tools/meson.build b/tools/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..76bf84df525fa91ba15802783bca133f30f7ab78 --- /dev/null +++ b/tools/meson.build @@ -0,0 +1,23 @@ +have_virtiofsd = (targetos == 'linux' and + have_tools and + 'CONFIG_SECCOMP' in config_host and + 'CONFIG_LIBCAP_NG' in config_host and + 'CONFIG_VHOST_USER' in config_host) + +if get_option('virtiofsd').enabled() + if not have_virtiofsd + if targetos != 'linux' + error('virtiofsd requires Linux') + elif 'CONFIG_SECCOMP' not in config_host or 'CONFIG_LIBCAP_NG' not in config_host + error('virtiofsd requires libcap-ng-devel and seccomp-devel') + elif not have_tools or 'CONFIG_VHOST_USER' not in config_host + error('virtiofsd needs tools and vhost-user support') + endif + endif +elif get_option('virtiofsd').disabled() or not have_system + have_virtiofsd = false +endif + +if have_virtiofsd + subdir('virtiofsd') +endif diff --git a/tools/virtiofsd/Makefile.objs b/tools/virtiofsd/Makefile.objs deleted file mode 100644 index 076f667e46b36da47980d31445689a7d7f128b41..0000000000000000000000000000000000000000 --- a/tools/virtiofsd/Makefile.objs +++ /dev/null @@ -1,12 +0,0 @@ -virtiofsd-obj-y = buffer.o \ - fuse_opt.o \ - fuse_log.o \ - fuse_lowlevel.o \ - fuse_signals.o \ - fuse_virtio.o \ - helper.o \ - passthrough_ll.o \ - seccomp.o - -seccomp.o-cflags := $(SECCOMP_CFLAGS) -seccomp.o-libs := $(SECCOMP_LIBS) diff --git a/tools/virtiofsd/buffer.c b/tools/virtiofsd/buffer.c index 27c1377f22324c5290e9e27c27078b3867151a74..bdc608c22132500167341edbdb412449c8c18b12 100644 --- a/tools/virtiofsd/buffer.c +++ b/tools/virtiofsd/buffer.c @@ -246,6 +246,10 @@ static int fuse_bufvec_advance(struct fuse_bufvec *bufv, size_t len) { const struct fuse_buf *buf = fuse_bufvec_current(bufv); + if (!buf) { + return 0; + } + bufv->off += len; assert(bufv->off <= buf->size); if (bufv->off == buf->size) { diff --git a/tools/virtiofsd/fuse_common.h b/tools/virtiofsd/fuse_common.h index 686c42c0a5281f998ee564641195a4b781aa09c0..5aee5193eb29ea10de8e6ce46b63a91d878c3405 100644 --- a/tools/virtiofsd/fuse_common.h +++ b/tools/virtiofsd/fuse_common.h @@ -352,6 +352,13 @@ struct fuse_file_info { */ #define FUSE_CAP_NO_OPENDIR_SUPPORT (1 << 24) +/** + * Indicates that the kernel supports the FUSE_ATTR_SUBMOUNT flag. + * + * Setting (or unsetting) this flag in the `want` field has *no effect*. + */ +#define FUSE_CAP_SUBMOUNTS (1 << 27) + /** * Ioctl flags * diff --git a/tools/virtiofsd/fuse_i.h b/tools/virtiofsd/fuse_i.h index 1240828208abc2a985e9b75de6bcc04efddb2ad8..492e002181e2dd8c75ef05333260b51a9f873205 100644 --- a/tools/virtiofsd/fuse_i.h +++ b/tools/virtiofsd/fuse_i.h @@ -68,6 +68,7 @@ struct fuse_session { size_t bufsize; int error; char *vu_socket_path; + char *vu_socket_group; int vu_listen_fd; int vu_socketfd; struct fv_VuDev *virtio_dev; diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c index 2dd36ec03b6edfe0dcc6f77d1706614c92bd75c0..c70fb16a9a5313160a4cc53faf86e1265cc28082 100644 --- a/tools/virtiofsd/fuse_lowlevel.c +++ b/tools/virtiofsd/fuse_lowlevel.c @@ -341,6 +341,8 @@ static void fill_entry(struct fuse_entry_out *arg, .attr_valid_nsec = calc_timeout_nsec(e->attr_timeout), }; convert_stat(&e->attr, &arg->attr); + + arg->attr.flags = e->attr_flags; } /* @@ -1988,6 +1990,9 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, bufsize = max_bufsize; } } + if (arg->flags & FUSE_SUBMOUNTS) { + se->conn.capable |= FUSE_CAP_SUBMOUNTS; + } #ifdef HAVE_SPLICE #ifdef HAVE_VMSPLICE se->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE; @@ -2523,6 +2528,7 @@ static const struct fuse_opt fuse_ll_opts[] = { LL_OPTION("--debug", debug, 1), LL_OPTION("allow_root", deny_others, 1), LL_OPTION("--socket-path=%s", vu_socket_path, 0), + LL_OPTION("--socket-group=%s", vu_socket_group, 0), LL_OPTION("--fd=%d", vu_listen_fd, 0), LL_OPTION("--thread-pool-size=%d", thread_pool_size, 0), FUSE_OPT_END @@ -2630,6 +2636,11 @@ struct fuse_session *fuse_session_new(struct fuse_args *args, "fuse: --socket-path and --fd cannot be given together\n"); goto out4; } + if (se->vu_socket_group && !se->vu_socket_path) { + fuse_log(FUSE_LOG_ERR, + "fuse: --socket-group can only be used with --socket-path\n"); + goto out4; + } se->bufsize = FUSE_MAX_MAX_PAGES * getpagesize() + FUSE_BUFFER_HEADER_SIZE; diff --git a/tools/virtiofsd/fuse_lowlevel.h b/tools/virtiofsd/fuse_lowlevel.h index 562fd5241ed400013f6fa65116ee4c4b0831e241..9c06240f9e61ea259241a3ec77e9cf2ff8d5856f 100644 --- a/tools/virtiofsd/fuse_lowlevel.h +++ b/tools/virtiofsd/fuse_lowlevel.h @@ -102,6 +102,11 @@ struct fuse_entry_param { * large value. */ double entry_timeout; + + /** + * Flags for fuse_attr.flags that do not fit into attr. + */ + uint32_t attr_flags; }; /** diff --git a/tools/virtiofsd/fuse_virtio.c b/tools/virtiofsd/fuse_virtio.c index 3b6d16a0417ae560ee46dfec9254039487251007..83ba07c6cd8023727917cb0efa83ff283691a3b6 100644 --- a/tools/virtiofsd/fuse_virtio.c +++ b/tools/virtiofsd/fuse_virtio.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include "contrib/libvhost-user/libvhost-user.h" @@ -588,7 +590,7 @@ static void *fv_queue_thread(void *opaque) struct fuse_session *se = qi->virtio_dev->se; GThreadPool *pool; - pool = g_thread_pool_new(fv_queue_worker, qi, se->thread_pool_size, TRUE, + pool = g_thread_pool_new(fv_queue_worker, qi, se->thread_pool_size, FALSE, NULL); if (!pool) { fuse_log(FUSE_LOG_ERR, "%s: g_thread_pool_new failed\n", __func__); @@ -924,15 +926,30 @@ static int fv_create_listen_socket(struct fuse_session *se) /* * Unfortunately bind doesn't let you set the mask on the socket, - * so set umask to 077 and restore it later. + * so set umask appropriately and restore it later. */ - old_umask = umask(0077); + if (se->vu_socket_group) { + old_umask = umask(S_IROTH | S_IWOTH | S_IXOTH); + } else { + old_umask = umask(S_IRGRP | S_IWGRP | S_IXGRP | + S_IROTH | S_IWOTH | S_IXOTH); + } if (bind(listen_sock, (struct sockaddr *)&un, addr_len) == -1) { fuse_log(FUSE_LOG_ERR, "vhost socket bind: %m\n"); close(listen_sock); umask(old_umask); return -1; } + if (se->vu_socket_group) { + struct group *g = getgrnam(se->vu_socket_group); + if (g) { + if (!chown(se->vu_socket_path, -1, g->gr_gid)) { + fuse_log(FUSE_LOG_WARNING, + "vhost socket failed to set group to %s (%d)\n", + se->vu_socket_group, g->gr_gid); + } + } + } umask(old_umask); if (listen(listen_sock, 1) == -1) { @@ -949,6 +966,22 @@ int virtio_session_mount(struct fuse_session *se) { int ret; + /* + * Test that unshare(CLONE_FS) works. fv_queue_worker() will need it. It's + * an unprivileged system call but some Docker/Moby versions are known to + * reject it via seccomp when CAP_SYS_ADMIN is not given. + * + * Note that the program is single-threaded here so this syscall has no + * visible effect and is safe to make. + */ + ret = unshare(CLONE_FS); + if (ret == -1 && errno == EPERM) { + fuse_log(FUSE_LOG_ERR, "unshare(CLONE_FS) failed with EPERM. If " + "running in a container please check that the container " + "runtime seccomp policy allows unshare.\n"); + return -1; + } + ret = fv_create_listen_socket(se); if (ret < 0) { return ret; @@ -980,8 +1013,11 @@ int virtio_session_mount(struct fuse_session *se) se->vu_socketfd = data_sock; se->virtio_dev->se = se; pthread_rwlock_init(&se->virtio_dev->vu_dispatch_rwlock, NULL); - vu_init(&se->virtio_dev->dev, 2, se->vu_socketfd, fv_panic, fv_set_watch, - fv_remove_watch, &fv_iface); + if (!vu_init(&se->virtio_dev->dev, 2, se->vu_socketfd, fv_panic, NULL, + fv_set_watch, fv_remove_watch, &fv_iface)) { + fuse_log(FUSE_LOG_ERR, "%s: vu_init failed\n", __func__); + return -1; + } return 0; } diff --git a/tools/virtiofsd/helper.c b/tools/virtiofsd/helper.c index 00a1ef666a510068bb687bb34756513828a6f85c..75ac48dec2534bfa972742a1ea01ceef7b0328c3 100644 --- a/tools/virtiofsd/helper.c +++ b/tools/virtiofsd/helper.c @@ -159,25 +159,38 @@ void fuse_cmdline_help(void) " -o max_idle_threads the maximum number of idle worker " "threads\n" " allowed (default: 10)\n" - " -o norace disable racy fallback\n" - " default: false\n" " -o posix_lock|no_posix_lock\n" " enable/disable remote posix lock\n" - " default: posix_lock\n" + " default: no_posix_lock\n" " -o readdirplus|no_readdirplus\n" " enable/disable readirplus\n" " default: readdirplus except with " "cache=none\n" + " -o sandbox=namespace|chroot\n" + " sandboxing mode:\n" + " - namespace: mount, pid, and net\n" + " namespaces with pivot_root(2)\n" + " into shared directory\n" + " - chroot: chroot(2) into shared\n" + " directory (use in containers)\n" + " default: namespace\n" " -o timeout= I/O timeout (seconds)\n" " default: depends on cache= option.\n" " -o writeback|no_writeback enable/disable writeback cache\n" " default: no_writeback\n" " -o xattr|no_xattr enable/disable xattr\n" " default: no_xattr\n" + " -o modcaps=CAPLIST Modify the list of capabilities\n" + " e.g. -o modcaps=+sys_admin:-chown\n" " --rlimit-nofile= set maximum number of file descriptors\n" " (0 leaves rlimit unchanged)\n" " default: min(1000000, fs.file-max - 16384)\n" " if the current rlimit is lower\n" + " -o allow_direct_io|no_allow_direct_io\n" + " retain/discard O_DIRECT flags passed down\n" + " to virtiofsd from guest applications.\n" + " default: no_allow_direct_io\n" + " -o announce_submounts Announce sub-mount points to the guest\n" ); } diff --git a/tools/virtiofsd/meson.build b/tools/virtiofsd/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..17edecf55c0aee51b2b3327fd62389ea15df2644 --- /dev/null +++ b/tools/virtiofsd/meson.build @@ -0,0 +1,19 @@ +executable('virtiofsd', files( + 'buffer.c', + 'fuse_opt.c', + 'fuse_log.c', + 'fuse_lowlevel.c', + 'fuse_signals.c', + 'fuse_virtio.c', + 'helper.c', + 'passthrough_ll.c', + 'passthrough_seccomp.c'), + link_with: libvhost_user, + dependencies: [seccomp, qemuutil, libcap_ng], + install: true, + install_dir: get_option('libexecdir')) + +configure_file(input: '50-qemu-virtiofsd.json.in', + output: '50-qemu-virtiofsd.json', + configuration: { 'libexecdir' : get_option('prefix') / get_option('libexecdir') }, + install_dir: qemu_datadir / 'vhost-user') diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c index 3ba1d90984601efb42f72c86ed59a21025eb7934..97485b22b4114228e622a0b256d9a9bfedd0ca9e 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -40,6 +40,7 @@ #include "fuse_virtio.h" #include "fuse_log.h" #include "fuse_lowlevel.h" +#include "standard-headers/linux/fuse.h" #include #include #include @@ -64,8 +65,9 @@ #include #include +#include "qemu/cutils.h" #include "passthrough_helpers.h" -#include "seccomp.h" +#include "passthrough_seccomp.h" /* Keep track of inode posix locks for each owner. */ struct lo_inode_plock { @@ -93,6 +95,7 @@ struct lo_map { struct lo_key { ino_t ino; dev_t dev; + uint64_t mnt_id; }; struct lo_inode { @@ -137,31 +140,55 @@ enum { CACHE_ALWAYS, }; +enum { + SANDBOX_NAMESPACE, + SANDBOX_CHROOT, +}; + +typedef struct xattr_map_entry { + char *key; + char *prepend; + unsigned int flags; +} XattrMapEntry; + struct lo_data { pthread_mutex_t mutex; + int sandbox; int debug; - int norace; int writeback; int flock; int posix_lock; int xattr; + char *xattrmap; char *source; + char *modcaps; double timeout; int cache; int timeout_set; int readdirplus_set; int readdirplus_clear; + int allow_direct_io; + int announce_submounts; + bool use_statx; struct lo_inode root; GHashTable *inodes; /* protected by lo->mutex */ struct lo_map ino_map; /* protected by lo->mutex */ struct lo_map dirp_map; /* protected by lo->mutex */ struct lo_map fd_map; /* protected by lo->mutex */ + XattrMapEntry *xattr_map_list; + size_t xattr_map_nentries; /* An O_PATH file descriptor to /proc/self/fd/ */ int proc_self_fd; }; static const struct fuse_opt lo_opts[] = { + { "sandbox=namespace", + offsetof(struct lo_data, sandbox), + SANDBOX_NAMESPACE }, + { "sandbox=chroot", + offsetof(struct lo_data, sandbox), + SANDBOX_CHROOT }, { "writeback", offsetof(struct lo_data, writeback), 1 }, { "no_writeback", offsetof(struct lo_data, writeback), 0 }, { "source=%s", offsetof(struct lo_data, source), 0 }, @@ -171,14 +198,18 @@ static const struct fuse_opt lo_opts[] = { { "no_posix_lock", offsetof(struct lo_data, posix_lock), 0 }, { "xattr", offsetof(struct lo_data, xattr), 1 }, { "no_xattr", offsetof(struct lo_data, xattr), 0 }, + { "xattrmap=%s", offsetof(struct lo_data, xattrmap), 0 }, + { "modcaps=%s", offsetof(struct lo_data, modcaps), 0 }, { "timeout=%lf", offsetof(struct lo_data, timeout), 0 }, { "timeout=", offsetof(struct lo_data, timeout_set), 1 }, { "cache=none", offsetof(struct lo_data, cache), CACHE_NONE }, { "cache=auto", offsetof(struct lo_data, cache), CACHE_AUTO }, { "cache=always", offsetof(struct lo_data, cache), CACHE_ALWAYS }, - { "norace", offsetof(struct lo_data, norace), 1 }, { "readdirplus", offsetof(struct lo_data, readdirplus_set), 1 }, { "no_readdirplus", offsetof(struct lo_data, readdirplus_clear), 1 }, + { "allow_direct_io", offsetof(struct lo_data, allow_direct_io), 1 }, + { "no_allow_direct_io", offsetof(struct lo_data, allow_direct_io), 0 }, + { "announce_submounts", offsetof(struct lo_data, announce_submounts), 1 }, FUSE_OPT_END }; static bool use_syslog = false; @@ -193,7 +224,8 @@ static struct { /* That we loaded cap-ng in the current thread from the saved */ static __thread bool cap_loaded = 0; -static struct lo_inode *lo_find(struct lo_data *lo, struct stat *st); +static struct lo_inode *lo_find(struct lo_data *lo, struct stat *st, + uint64_t mnt_id); static int is_dot_or_dotdot(const char *name) { @@ -572,6 +604,12 @@ static void lo_init(void *userdata, struct fuse_conn_info *conn) fuse_log(FUSE_LOG_DEBUG, "lo_init: disabling readdirplus\n"); conn->want &= ~FUSE_CAP_READDIRPLUS; } + + if (!(conn->capable & FUSE_CAP_SUBMOUNTS) && lo->announce_submounts) { + fuse_log(FUSE_LOG_WARNING, "lo_init: Cannot announce submounts, client " + "does not support it\n"); + lo->announce_submounts = false; + } } static void lo_getattr(fuse_req_t req, fuse_ino_t ino, @@ -592,136 +630,6 @@ static void lo_getattr(fuse_req_t req, fuse_ino_t ino, fuse_reply_attr(req, &buf, lo->timeout); } -/* - * Increments parent->nlookup and caller must release refcount using - * lo_inode_put(&parent). - */ -static int lo_parent_and_name(struct lo_data *lo, struct lo_inode *inode, - char path[PATH_MAX], struct lo_inode **parent) -{ - char procname[64]; - char *last; - struct stat stat; - struct lo_inode *p; - int retries = 2; - int res; - -retry: - sprintf(procname, "%i", inode->fd); - - res = readlinkat(lo->proc_self_fd, procname, path, PATH_MAX); - if (res < 0) { - fuse_log(FUSE_LOG_WARNING, "%s: readlink failed: %m\n", __func__); - goto fail_noretry; - } - - if (res >= PATH_MAX) { - fuse_log(FUSE_LOG_WARNING, "%s: readlink overflowed\n", __func__); - goto fail_noretry; - } - path[res] = '\0'; - - last = strrchr(path, '/'); - if (last == NULL) { - /* Shouldn't happen */ - fuse_log( - FUSE_LOG_WARNING, - "%s: INTERNAL ERROR: bad path read from proc\n", __func__); - goto fail_noretry; - } - if (last == path) { - p = &lo->root; - pthread_mutex_lock(&lo->mutex); - p->nlookup++; - g_atomic_int_inc(&p->refcount); - pthread_mutex_unlock(&lo->mutex); - } else { - *last = '\0'; - res = fstatat(AT_FDCWD, last == path ? "/" : path, &stat, 0); - if (res == -1) { - if (!retries) { - fuse_log(FUSE_LOG_WARNING, - "%s: failed to stat parent: %m\n", __func__); - } - goto fail; - } - p = lo_find(lo, &stat); - if (p == NULL) { - if (!retries) { - fuse_log(FUSE_LOG_WARNING, - "%s: failed to find parent\n", __func__); - } - goto fail; - } - } - last++; - res = fstatat(p->fd, last, &stat, AT_SYMLINK_NOFOLLOW); - if (res == -1) { - if (!retries) { - fuse_log(FUSE_LOG_WARNING, - "%s: failed to stat last\n", __func__); - } - goto fail_unref; - } - if (stat.st_dev != inode->key.dev || stat.st_ino != inode->key.ino) { - if (!retries) { - fuse_log(FUSE_LOG_WARNING, - "%s: failed to match last\n", __func__); - } - goto fail_unref; - } - *parent = p; - memmove(path, last, strlen(last) + 1); - - return 0; - -fail_unref: - unref_inode_lolocked(lo, p, 1); - lo_inode_put(lo, &p); -fail: - if (retries) { - retries--; - goto retry; - } -fail_noretry: - errno = EIO; - return -1; -} - -static int utimensat_empty(struct lo_data *lo, struct lo_inode *inode, - const struct timespec *tv) -{ - int res; - struct lo_inode *parent; - char path[PATH_MAX]; - - if (S_ISLNK(inode->filetype)) { - res = utimensat(inode->fd, "", tv, AT_EMPTY_PATH); - if (res == -1 && errno == EINVAL) { - /* Sorry, no race free way to set times on symlink. */ - if (lo->norace) { - errno = EPERM; - } else { - goto fallback; - } - } - return res; - } - sprintf(path, "%i", inode->fd); - - return utimensat(lo->proc_self_fd, path, tv, 0); - -fallback: - res = lo_parent_and_name(lo, inode, path, &parent); - if (res != -1) { - res = utimensat(parent->fd, path, tv, AT_SYMLINK_NOFOLLOW); - unref_inode_lolocked(lo, parent, 1); - lo_inode_put(lo, &parent); - } - - return res; -} - static int lo_fi_fd(fuse_req_t req, struct fuse_file_info *fi) { struct lo_data *lo = lo_data(req); @@ -747,7 +655,7 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, struct lo_inode *inode; int ifd; int res; - int fd; + int fd = -1; inode = lo_inode(req, ino); if (!inode) { @@ -828,7 +736,8 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, if (fi) { res = futimens(fd, tv); } else { - res = utimensat_empty(lo, inode, tv); + sprintf(procname, "%i", inode->fd); + res = utimensat(lo->proc_self_fd, procname, tv, 0); } if (res == -1) { goto out_err; @@ -844,12 +753,14 @@ out_err: fuse_reply_err(req, saverr); } -static struct lo_inode *lo_find(struct lo_data *lo, struct stat *st) +static struct lo_inode *lo_find(struct lo_data *lo, struct stat *st, + uint64_t mnt_id) { struct lo_inode *p; struct lo_key key = { .ino = st->st_ino, .dev = st->st_dev, + .mnt_id = mnt_id, }; pthread_mutex_lock(&lo->mutex); @@ -877,6 +788,60 @@ static void posix_locks_value_destroy(gpointer data) free(plock); } +static int do_statx(struct lo_data *lo, int dirfd, const char *pathname, + struct stat *statbuf, int flags, uint64_t *mnt_id) +{ + int res; + +#if defined(CONFIG_STATX) && defined(STATX_MNT_ID) + if (lo->use_statx) { + struct statx statxbuf; + + res = statx(dirfd, pathname, flags, STATX_BASIC_STATS | STATX_MNT_ID, + &statxbuf); + if (!res) { + memset(statbuf, 0, sizeof(*statbuf)); + statbuf->st_dev = makedev(statxbuf.stx_dev_major, + statxbuf.stx_dev_minor); + statbuf->st_ino = statxbuf.stx_ino; + statbuf->st_mode = statxbuf.stx_mode; + statbuf->st_nlink = statxbuf.stx_nlink; + statbuf->st_uid = statxbuf.stx_uid; + statbuf->st_gid = statxbuf.stx_gid; + statbuf->st_rdev = makedev(statxbuf.stx_rdev_major, + statxbuf.stx_rdev_minor); + statbuf->st_size = statxbuf.stx_size; + statbuf->st_blksize = statxbuf.stx_blksize; + statbuf->st_blocks = statxbuf.stx_blocks; + statbuf->st_atim.tv_sec = statxbuf.stx_atime.tv_sec; + statbuf->st_atim.tv_nsec = statxbuf.stx_atime.tv_nsec; + statbuf->st_mtim.tv_sec = statxbuf.stx_mtime.tv_sec; + statbuf->st_mtim.tv_nsec = statxbuf.stx_mtime.tv_nsec; + statbuf->st_ctim.tv_sec = statxbuf.stx_ctime.tv_sec; + statbuf->st_ctim.tv_nsec = statxbuf.stx_ctime.tv_nsec; + + if (statxbuf.stx_mask & STATX_MNT_ID) { + *mnt_id = statxbuf.stx_mnt_id; + } else { + *mnt_id = 0; + } + return 0; + } else if (errno != ENOSYS) { + return -1; + } + lo->use_statx = false; + /* fallback */ + } +#endif + res = fstatat(dirfd, pathname, statbuf, flags); + if (res == -1) { + return -1; + } + *mnt_id = 0; + + return 0; +} + /* * Increments nlookup and caller must release refcount using * lo_inode_put(&parent). @@ -887,6 +852,7 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name, int newfd; int res; int saverr; + uint64_t mnt_id; struct lo_data *lo = lo_data(req); struct lo_inode *inode = NULL; struct lo_inode *dir = lo_inode(req, parent); @@ -914,12 +880,18 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name, goto out_err; } - res = fstatat(newfd, "", &e->attr, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW); + res = do_statx(lo, newfd, "", &e->attr, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW, + &mnt_id); if (res == -1) { goto out_err; } - inode = lo_find(lo, &e->attr); + if (S_ISDIR(e->attr.st_mode) && lo->announce_submounts && + (e->attr.st_dev != dir->key.dev || mnt_id != dir->key.mnt_id)) { + e->attr_flags |= FUSE_ATTR_SUBMOUNT; + } + + inode = lo_find(lo, &e->attr, mnt_id); if (inode) { close(newfd); } else { @@ -941,6 +913,7 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name, inode->fd = newfd; inode->key.ino = e->attr.st_ino; inode->key.dev = e->attr.st_dev; + inode->key.mnt_id = mnt_id; pthread_mutex_init(&inode->plock_mutex, NULL); inode->posix_locks = g_hash_table_new_full( g_direct_hash, g_direct_equal, NULL, posix_locks_value_destroy); @@ -1129,41 +1102,6 @@ static void lo_symlink(fuse_req_t req, const char *link, fuse_ino_t parent, lo_mknod_symlink(req, parent, name, S_IFLNK, 0, link); } -static int linkat_empty_nofollow(struct lo_data *lo, struct lo_inode *inode, - int dfd, const char *name) -{ - int res; - struct lo_inode *parent; - char path[PATH_MAX]; - - if (S_ISLNK(inode->filetype)) { - res = linkat(inode->fd, "", dfd, name, AT_EMPTY_PATH); - if (res == -1 && (errno == ENOENT || errno == EINVAL)) { - /* Sorry, no race free way to hard-link a symlink. */ - if (lo->norace) { - errno = EPERM; - } else { - goto fallback; - } - } - return res; - } - - sprintf(path, "%i", inode->fd); - - return linkat(lo->proc_self_fd, path, dfd, name, AT_SYMLINK_FOLLOW); - -fallback: - res = lo_parent_and_name(lo, inode, path, &parent); - if (res != -1) { - res = linkat(parent->fd, path, dfd, name, 0); - unref_inode_lolocked(lo, parent, 1); - lo_inode_put(lo, &parent); - } - - return res; -} - static void lo_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t parent, const char *name) { @@ -1172,6 +1110,7 @@ static void lo_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t parent, struct lo_inode *parent_inode; struct lo_inode *inode; struct fuse_entry_param e; + char procname[64]; int saverr; if (!is_safe_path_component(name)) { @@ -1190,7 +1129,9 @@ static void lo_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t parent, e.attr_timeout = lo->timeout; e.entry_timeout = lo->timeout; - res = linkat_empty_nofollow(lo, inode, parent_inode->fd, name); + sprintf(procname, "%i", inode->fd); + res = linkat(lo->proc_self_fd, procname, parent_inode->fd, name, + AT_SYMLINK_FOLLOW); if (res == -1) { goto out_err; } @@ -1225,15 +1166,23 @@ static struct lo_inode *lookup_name(fuse_req_t req, fuse_ino_t parent, const char *name) { int res; + uint64_t mnt_id; struct stat attr; + struct lo_data *lo = lo_data(req); + struct lo_inode *dir = lo_inode(req, parent); - res = fstatat(lo_fd(req, parent), name, &attr, - AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW); + if (!dir) { + return NULL; + } + + res = do_statx(lo, dir->fd, name, &attr, + AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW, &mnt_id); + lo_inode_put(lo, &dir); if (res == -1) { return NULL; } - return lo_find(lo_data(req), &attr); + return lo_find(lo, &attr, mnt_id); } static void lo_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name) @@ -1677,7 +1626,8 @@ static void lo_releasedir(fuse_req_t req, fuse_ino_t ino, fuse_reply_err(req, 0); } -static void update_open_flags(int writeback, struct fuse_file_info *fi) +static void update_open_flags(int writeback, int allow_direct_io, + struct fuse_file_info *fi) { /* * With writeback cache, kernel may send read requests even @@ -1702,10 +1652,13 @@ static void update_open_flags(int writeback, struct fuse_file_info *fi) /* * O_DIRECT in guest should not necessarily mean bypassing page - * cache on host as well. If somebody needs that behavior, it - * probably should be a configuration knob in daemon. + * cache on host as well. Therefore, we discard it by default + * ('-o no_allow_direct_io'). If somebody needs that behavior, + * the '-o allow_direct_io' option should be set. */ - fi->flags &= ~O_DIRECT; + if (!allow_direct_io) { + fi->flags &= ~O_DIRECT; + } } static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name, @@ -1737,7 +1690,7 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name, goto out; } - update_open_flags(lo->writeback, fi); + update_open_flags(lo->writeback, lo->allow_direct_io, fi); fd = openat(parent_inode->fd, name, (fi->flags | O_CREAT) & ~O_NOFOLLOW, mode); @@ -1947,7 +1900,7 @@ static void lo_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) fuse_log(FUSE_LOG_DEBUG, "lo_open(ino=%" PRIu64 ", flags=%d)\n", ino, fi->flags); - update_open_flags(lo->writeback, fi); + update_open_flags(lo->writeback, lo->allow_direct_io, fi); sprintf(buf, "%i", lo_fd(req, ino)); fd = openat(lo->proc_self_fd, buf, fi->flags & ~O_NOFOLLOW); @@ -2164,20 +2117,383 @@ static void lo_flock(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, fuse_reply_err(req, res == -1 ? errno : 0); } -static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, +/* types */ +/* + * Exit; process attribute unmodified if matched. + * An empty key applies to all. + */ +#define XATTR_MAP_FLAG_OK (1 << 0) +/* + * The attribute is unwanted; + * EPERM on write, hidden on read. + */ +#define XATTR_MAP_FLAG_BAD (1 << 1) +/* + * For attr that start with 'key' prepend 'prepend' + * 'key' may be empty to prepend for all attrs + * key is defined from set/remove point of view. + * Automatically reversed on read + */ +#define XATTR_MAP_FLAG_PREFIX (1 << 2) + +/* scopes */ +/* Apply rule to get/set/remove */ +#define XATTR_MAP_FLAG_CLIENT (1 << 16) +/* Apply rule to list */ +#define XATTR_MAP_FLAG_SERVER (1 << 17) +/* Apply rule to all */ +#define XATTR_MAP_FLAG_ALL (XATTR_MAP_FLAG_SERVER | XATTR_MAP_FLAG_CLIENT) + +static void add_xattrmap_entry(struct lo_data *lo, + const XattrMapEntry *new_entry) +{ + XattrMapEntry *res = g_realloc_n(lo->xattr_map_list, + lo->xattr_map_nentries + 1, + sizeof(XattrMapEntry)); + res[lo->xattr_map_nentries++] = *new_entry; + + lo->xattr_map_list = res; +} + +static void free_xattrmap(struct lo_data *lo) +{ + XattrMapEntry *map = lo->xattr_map_list; + size_t i; + + if (!map) { + return; + } + + for (i = 0; i < lo->xattr_map_nentries; i++) { + g_free(map[i].key); + g_free(map[i].prepend); + }; + + g_free(map); + lo->xattr_map_list = NULL; + lo->xattr_map_nentries = -1; +} + +/* + * Handle the 'map' type, which is sugar for a set of commands + * for the common case of prefixing a subset or everything, + * and allowing anything not prefixed through. + * It must be the last entry in the stream, although there + * can be other entries before it. + * The form is: + * :map:key:prefix: + * + * key maybe empty in which case all entries are prefixed. + */ +static void parse_xattrmap_map(struct lo_data *lo, + const char *rule, char sep) +{ + const char *tmp; + char *key; + char *prefix; + XattrMapEntry tmp_entry; + + if (*rule != sep) { + fuse_log(FUSE_LOG_ERR, + "%s: Expecting '%c' after 'map' keyword, found '%c'\n", + __func__, sep, *rule); + exit(1); + } + + rule++; + + /* At start of 'key' field */ + tmp = strchr(rule, sep); + if (!tmp) { + fuse_log(FUSE_LOG_ERR, + "%s: Missing '%c' at end of key field in map rule\n", + __func__, sep); + exit(1); + } + + key = g_strndup(rule, tmp - rule); + rule = tmp + 1; + + /* At start of prefix field */ + tmp = strchr(rule, sep); + if (!tmp) { + fuse_log(FUSE_LOG_ERR, + "%s: Missing '%c' at end of prefix field in map rule\n", + __func__, sep); + exit(1); + } + + prefix = g_strndup(rule, tmp - rule); + rule = tmp + 1; + + /* + * This should be the end of the string, we don't allow + * any more commands after 'map'. + */ + if (*rule) { + fuse_log(FUSE_LOG_ERR, + "%s: Expecting end of command after map, found '%c'\n", + __func__, *rule); + exit(1); + } + + /* 1st: Prefix matches/everything */ + tmp_entry.flags = XATTR_MAP_FLAG_PREFIX | XATTR_MAP_FLAG_ALL; + tmp_entry.key = g_strdup(key); + tmp_entry.prepend = g_strdup(prefix); + add_xattrmap_entry(lo, &tmp_entry); + + if (!*key) { + /* Prefix all case */ + + /* 2nd: Hide any non-prefixed entries on the host */ + tmp_entry.flags = XATTR_MAP_FLAG_BAD | XATTR_MAP_FLAG_ALL; + tmp_entry.key = g_strdup(""); + tmp_entry.prepend = g_strdup(""); + add_xattrmap_entry(lo, &tmp_entry); + } else { + /* Prefix matching case */ + + /* 2nd: Hide non-prefixed but matching entries on the host */ + tmp_entry.flags = XATTR_MAP_FLAG_BAD | XATTR_MAP_FLAG_SERVER; + tmp_entry.key = g_strdup(""); /* Not used */ + tmp_entry.prepend = g_strdup(key); + add_xattrmap_entry(lo, &tmp_entry); + + /* 3rd: Stop the client accessing prefixed attributes directly */ + tmp_entry.flags = XATTR_MAP_FLAG_BAD | XATTR_MAP_FLAG_CLIENT; + tmp_entry.key = g_strdup(prefix); + tmp_entry.prepend = g_strdup(""); /* Not used */ + add_xattrmap_entry(lo, &tmp_entry); + + /* 4th: Everything else is OK */ + tmp_entry.flags = XATTR_MAP_FLAG_OK | XATTR_MAP_FLAG_ALL; + tmp_entry.key = g_strdup(""); + tmp_entry.prepend = g_strdup(""); + add_xattrmap_entry(lo, &tmp_entry); + } + + g_free(key); + g_free(prefix); +} + +static void parse_xattrmap(struct lo_data *lo) +{ + const char *map = lo->xattrmap; + const char *tmp; + + lo->xattr_map_nentries = 0; + while (*map) { + XattrMapEntry tmp_entry; + char sep; + + if (isspace(*map)) { + map++; + continue; + } + /* The separator is the first non-space of the rule */ + sep = *map++; + if (!sep) { + break; + } + + tmp_entry.flags = 0; + /* Start of 'type' */ + if (strstart(map, "prefix", &map)) { + tmp_entry.flags |= XATTR_MAP_FLAG_PREFIX; + } else if (strstart(map, "ok", &map)) { + tmp_entry.flags |= XATTR_MAP_FLAG_OK; + } else if (strstart(map, "bad", &map)) { + tmp_entry.flags |= XATTR_MAP_FLAG_BAD; + } else if (strstart(map, "map", &map)) { + /* + * map is sugar that adds a number of rules, and must be + * the last entry. + */ + parse_xattrmap_map(lo, map, sep); + return; + } else { + fuse_log(FUSE_LOG_ERR, + "%s: Unexpected type;" + "Expecting 'prefix', 'ok', 'bad' or 'map' in rule %zu\n", + __func__, lo->xattr_map_nentries); + exit(1); + } + + if (*map++ != sep) { + fuse_log(FUSE_LOG_ERR, + "%s: Missing '%c' at end of type field of rule %zu\n", + __func__, sep, lo->xattr_map_nentries); + exit(1); + } + + /* Start of 'scope' */ + if (strstart(map, "client", &map)) { + tmp_entry.flags |= XATTR_MAP_FLAG_CLIENT; + } else if (strstart(map, "server", &map)) { + tmp_entry.flags |= XATTR_MAP_FLAG_SERVER; + } else if (strstart(map, "all", &map)) { + tmp_entry.flags |= XATTR_MAP_FLAG_ALL; + } else { + fuse_log(FUSE_LOG_ERR, + "%s: Unexpected scope;" + " Expecting 'client', 'server', or 'all', in rule %zu\n", + __func__, lo->xattr_map_nentries); + exit(1); + } + + if (*map++ != sep) { + fuse_log(FUSE_LOG_ERR, + "%s: Expecting '%c' found '%c'" + " after scope in rule %zu\n", + __func__, sep, *map, lo->xattr_map_nentries); + exit(1); + } + + /* At start of 'key' field */ + tmp = strchr(map, sep); + if (!tmp) { + fuse_log(FUSE_LOG_ERR, + "%s: Missing '%c' at end of key field of rule %zu", + __func__, sep, lo->xattr_map_nentries); + exit(1); + } + tmp_entry.key = g_strndup(map, tmp - map); + map = tmp + 1; + + /* At start of 'prepend' field */ + tmp = strchr(map, sep); + if (!tmp) { + fuse_log(FUSE_LOG_ERR, + "%s: Missing '%c' at end of prepend field of rule %zu", + __func__, sep, lo->xattr_map_nentries); + exit(1); + } + tmp_entry.prepend = g_strndup(map, tmp - map); + map = tmp + 1; + + add_xattrmap_entry(lo, &tmp_entry); + /* End of rule - go around again for another rule */ + } + + if (!lo->xattr_map_nentries) { + fuse_log(FUSE_LOG_ERR, "Empty xattr map\n"); + exit(1); + } +} + +/* + * For use with getxattr/setxattr/removexattr, where the client + * gives us a name and we may need to choose a different one. + * Allocates a buffer for the result placing it in *out_name. + * If there's no change then *out_name is not set. + * Returns 0 on success + * Can return -EPERM to indicate we block a given attribute + * (in which case out_name is not allocated) + * Can return -ENOMEM to indicate out_name couldn't be allocated. + */ +static int xattr_map_client(const struct lo_data *lo, const char *client_name, + char **out_name) +{ + size_t i; + for (i = 0; i < lo->xattr_map_nentries; i++) { + const XattrMapEntry *cur_entry = lo->xattr_map_list + i; + + if ((cur_entry->flags & XATTR_MAP_FLAG_CLIENT) && + (strstart(client_name, cur_entry->key, NULL))) { + if (cur_entry->flags & XATTR_MAP_FLAG_BAD) { + return -EPERM; + } + if (cur_entry->flags & XATTR_MAP_FLAG_OK) { + /* Unmodified name */ + return 0; + } + if (cur_entry->flags & XATTR_MAP_FLAG_PREFIX) { + *out_name = g_try_malloc(strlen(client_name) + + strlen(cur_entry->prepend) + 1); + if (!*out_name) { + return -ENOMEM; + } + sprintf(*out_name, "%s%s", cur_entry->prepend, client_name); + return 0; + } + } + } + + return -EPERM; +} + +/* + * For use with listxattr where the server fs gives us a name and we may need + * to sanitize this for the client. + * Returns a pointer to the result in *out_name + * This is always the original string or the current string with some prefix + * removed; no reallocation is done. + * Returns 0 on success + * Can return -ENODATA to indicate the name should be dropped from the list. + */ +static int xattr_map_server(const struct lo_data *lo, const char *server_name, + const char **out_name) +{ + size_t i; + const char *end; + + for (i = 0; i < lo->xattr_map_nentries; i++) { + const XattrMapEntry *cur_entry = lo->xattr_map_list + i; + + if ((cur_entry->flags & XATTR_MAP_FLAG_SERVER) && + (strstart(server_name, cur_entry->prepend, &end))) { + if (cur_entry->flags & XATTR_MAP_FLAG_BAD) { + return -ENODATA; + } + if (cur_entry->flags & XATTR_MAP_FLAG_OK) { + *out_name = server_name; + return 0; + } + if (cur_entry->flags & XATTR_MAP_FLAG_PREFIX) { + /* Remove prefix */ + *out_name = end; + return 0; + } + } + } + + return -ENODATA; +} + +static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name, size_t size) { struct lo_data *lo = lo_data(req); char *value = NULL; char procname[64]; + const char *name; + char *mapped_name; struct lo_inode *inode; ssize_t ret; int saverr; int fd = -1; + mapped_name = NULL; + name = in_name; + if (lo->xattrmap) { + ret = xattr_map_client(lo, in_name, &mapped_name); + if (ret < 0) { + if (ret == -EPERM) { + ret = -ENODATA; + } + fuse_reply_err(req, -ret); + return; + } + if (mapped_name) { + name = mapped_name; + } + } + inode = lo_inode(req, ino); if (!inode) { fuse_reply_err(req, EBADF); + g_free(mapped_name); return; } @@ -2242,6 +2558,7 @@ out_err: saverr = errno; out: fuse_reply_err(req, saverr); + g_free(mapped_name); goto out_free; } @@ -2298,8 +2615,60 @@ static void lo_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) if (ret == 0) { goto out; } + + if (lo->xattr_map_list) { + /* + * Map the names back, some attributes might be dropped, + * some shortened, but not increased, so we shouldn't + * run out of room. + */ + size_t out_index, in_index; + out_index = 0; + in_index = 0; + while (in_index < ret) { + const char *map_out; + char *in_ptr = value + in_index; + /* Length of current attribute name */ + size_t in_len = strlen(value + in_index) + 1; + + int mapret = xattr_map_server(lo, in_ptr, &map_out); + if (mapret != -ENODATA && mapret != 0) { + /* Shouldn't happen */ + saverr = -mapret; + goto out; + } + if (mapret == 0) { + /* Either unchanged, or truncated */ + size_t out_len; + if (map_out != in_ptr) { + /* +1 copies the NIL */ + out_len = strlen(map_out) + 1; + } else { + /* No change */ + out_len = in_len; + } + /* + * Move result along, may still be needed for an unchanged + * entry if a previous entry was changed. + */ + memmove(value + out_index, map_out, out_len); + + out_index += out_len; + } + in_index += in_len; + } + ret = out_index; + if (ret == 0) { + goto out; + } + } fuse_reply_buf(req, value, ret); } else { + /* + * xattrmap only ever shortens the result, + * so we don't need to do anything clever with the + * allocation length here. + */ fuse_reply_xattr(req, ret); } out_free: @@ -2319,19 +2688,35 @@ out: goto out_free; } -static void lo_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name, +static void lo_setxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name, const char *value, size_t size, int flags) { char procname[64]; + const char *name; + char *mapped_name; struct lo_data *lo = lo_data(req); struct lo_inode *inode; ssize_t ret; int saverr; int fd = -1; + mapped_name = NULL; + name = in_name; + if (lo->xattrmap) { + ret = xattr_map_client(lo, in_name, &mapped_name); + if (ret < 0) { + fuse_reply_err(req, -ret); + return; + } + if (mapped_name) { + name = mapped_name; + } + } + inode = lo_inode(req, ino); if (!inode) { fuse_reply_err(req, EBADF); + g_free(mapped_name); return; } @@ -2366,21 +2751,38 @@ out: } lo_inode_put(lo, &inode); + g_free(mapped_name); fuse_reply_err(req, saverr); } -static void lo_removexattr(fuse_req_t req, fuse_ino_t ino, const char *name) +static void lo_removexattr(fuse_req_t req, fuse_ino_t ino, const char *in_name) { char procname[64]; + const char *name; + char *mapped_name; struct lo_data *lo = lo_data(req); struct lo_inode *inode; ssize_t ret; int saverr; int fd = -1; + mapped_name = NULL; + name = in_name; + if (lo->xattrmap) { + ret = xattr_map_client(lo, in_name, &mapped_name); + if (ret < 0) { + fuse_reply_err(req, -ret); + return; + } + if (mapped_name) { + name = mapped_name; + } + } + inode = lo_inode(req, ino); if (!inode) { fuse_reply_err(req, EBADF); + g_free(mapped_name); return; } @@ -2415,6 +2817,7 @@ out: } lo_inode_put(lo, &inode); + g_free(mapped_name); fuse_reply_err(req, saverr); } @@ -2547,8 +2950,6 @@ static void setup_wait_parent_capabilities(void) static void setup_namespaces(struct lo_data *lo, struct fuse_session *se) { pid_t child; - char template[] = "virtiofsd-XXXXXX"; - char *tmpdir; /* * Create a new pid namespace for *child* processes. We'll have to @@ -2612,33 +3013,23 @@ static void setup_namespaces(struct lo_data *lo, struct fuse_session *se) exit(1); } - tmpdir = mkdtemp(template); - if (!tmpdir) { - fuse_log(FUSE_LOG_ERR, "tmpdir(%s): %m\n", template); - exit(1); - } - - if (mount("/proc/self/fd", tmpdir, NULL, MS_BIND, NULL) < 0) { - fuse_log(FUSE_LOG_ERR, "mount(/proc/self/fd, %s, MS_BIND): %m\n", - tmpdir); + /* + * We only need /proc/self/fd. Prevent ".." from accessing parent + * directories of /proc/self/fd by bind-mounting it over /proc. Since / was + * previously remounted with MS_REC | MS_SLAVE this mount change only + * affects our process. + */ + if (mount("/proc/self/fd", "/proc", NULL, MS_BIND, NULL) < 0) { + fuse_log(FUSE_LOG_ERR, "mount(/proc/self/fd, MS_BIND): %m\n"); exit(1); } - /* Now we can get our /proc/self/fd directory file descriptor */ - lo->proc_self_fd = open(tmpdir, O_PATH); + /* Get the /proc (actually /proc/self/fd, see above) file descriptor */ + lo->proc_self_fd = open("/proc", O_PATH); if (lo->proc_self_fd == -1) { - fuse_log(FUSE_LOG_ERR, "open(%s, O_PATH): %m\n", tmpdir); - exit(1); - } - - if (umount2(tmpdir, MNT_DETACH) < 0) { - fuse_log(FUSE_LOG_ERR, "umount2(%s, MNT_DETACH): %m\n", tmpdir); + fuse_log(FUSE_LOG_ERR, "open(/proc, O_PATH): %m\n"); exit(1); } - - if (rmdir(tmpdir) < 0) { - fuse_log(FUSE_LOG_ERR, "rmdir(%s): %m\n", tmpdir); - } } /* @@ -2733,9 +3124,11 @@ static void setup_mounts(const char *source) /* * Only keep whitelisted capabilities that are needed for file system operation + * The (possibly NULL) modcaps_in string passed in is free'd before exit. */ -static void setup_capabilities(void) +static void setup_capabilities(char *modcaps_in) { + char *modcaps = modcaps_in; pthread_mutex_lock(&cap.mutex); capng_restore_state(&cap.saved); @@ -2752,22 +3145,113 @@ static void setup_capabilities(void) */ capng_setpid(syscall(SYS_gettid)); capng_clear(CAPNG_SELECT_BOTH); - capng_updatev(CAPNG_ADD, CAPNG_PERMITTED | CAPNG_EFFECTIVE, + if (capng_updatev(CAPNG_ADD, CAPNG_PERMITTED | CAPNG_EFFECTIVE, CAP_CHOWN, CAP_DAC_OVERRIDE, - CAP_DAC_READ_SEARCH, CAP_FOWNER, CAP_FSETID, CAP_SETGID, CAP_SETUID, CAP_MKNOD, - CAP_SETFCAP); - capng_apply(CAPNG_SELECT_BOTH); + CAP_SETFCAP, + -1)) { + fuse_log(FUSE_LOG_ERR, "%s: capng_updatev failed\n", __func__); + exit(1); + } + + /* + * The modcaps option is a colon separated list of caps, + * each preceded by either + or -. + */ + while (modcaps) { + capng_act_t action; + int cap; + + char *next = strchr(modcaps, ':'); + if (next) { + *next = '\0'; + next++; + } + + switch (modcaps[0]) { + case '+': + action = CAPNG_ADD; + break; + + case '-': + action = CAPNG_DROP; + break; + + default: + fuse_log(FUSE_LOG_ERR, + "%s: Expecting '+'/'-' in modcaps but found '%c'\n", + __func__, modcaps[0]); + exit(1); + } + cap = capng_name_to_capability(modcaps + 1); + if (cap < 0) { + fuse_log(FUSE_LOG_ERR, "%s: Unknown capability '%s'\n", __func__, + modcaps); + exit(1); + } + if (capng_update(action, CAPNG_PERMITTED | CAPNG_EFFECTIVE, cap)) { + fuse_log(FUSE_LOG_ERR, "%s: capng_update failed for '%s'\n", + __func__, modcaps); + exit(1); + } + + modcaps = next; + } + g_free(modcaps_in); + + if (capng_apply(CAPNG_SELECT_BOTH)) { + fuse_log(FUSE_LOG_ERR, "%s: capng_apply failed\n", __func__); + exit(1); + } cap.saved = capng_save_state(); + if (!cap.saved) { + fuse_log(FUSE_LOG_ERR, "%s: capng_save_state failed\n", __func__); + exit(1); + } pthread_mutex_unlock(&cap.mutex); } +/* + * Use chroot as a weaker sandbox for environments where the process is + * launched without CAP_SYS_ADMIN. + */ +static void setup_chroot(struct lo_data *lo) +{ + lo->proc_self_fd = open("/proc/self/fd", O_PATH); + if (lo->proc_self_fd == -1) { + fuse_log(FUSE_LOG_ERR, "open(\"/proc/self/fd\", O_PATH): %m\n"); + exit(1); + } + + /* + * Make the shared directory the file system root so that FUSE_OPEN + * (lo_open()) cannot escape the shared directory by opening a symlink. + * + * The chroot(2) syscall is later disabled by seccomp and the + * CAP_SYS_CHROOT capability is dropped so that tampering with the chroot + * is not possible. + * + * However, it's still possible to escape the chroot via lo->proc_self_fd + * but that requires first gaining control of the process. + */ + if (chroot(lo->source) != 0) { + fuse_log(FUSE_LOG_ERR, "chroot(\"%s\"): %m\n", lo->source); + exit(1); + } + + /* Move into the chroot */ + if (chdir("/") != 0) { + fuse_log(FUSE_LOG_ERR, "chdir(\"/\"): %m\n"); + exit(1); + } +} + /* * Lock down this process to prevent access to other processes or files outside * source directory. This reduces the impact of arbitrary code execution bugs. @@ -2775,10 +3259,15 @@ static void setup_capabilities(void) static void setup_sandbox(struct lo_data *lo, struct fuse_session *se, bool enable_syslog) { - setup_namespaces(lo, se); - setup_mounts(lo->source); + if (lo->sandbox == SANDBOX_NAMESPACE) { + setup_namespaces(lo, se); + setup_mounts(lo->source); + } else { + setup_chroot(lo); + } + setup_seccomp(enable_syslog); - setup_capabilities(); + setup_capabilities(g_strdup(lo->modcaps)); } /* Set the maximum number of open file descriptors */ @@ -2861,6 +3350,7 @@ static void setup_root(struct lo_data *lo, struct lo_inode *root) { int fd, res; struct stat stat; + uint64_t mnt_id; fd = open("/", O_PATH); if (fd == -1) { @@ -2868,7 +3358,8 @@ static void setup_root(struct lo_data *lo, struct lo_inode *root) exit(1); } - res = fstatat(fd, "", &stat, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW); + res = do_statx(lo, fd, "", &stat, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW, + &mnt_id); if (res == -1) { fuse_log(FUSE_LOG_ERR, "fstatat(%s): %m\n", lo->source); exit(1); @@ -2878,6 +3369,7 @@ static void setup_root(struct lo_data *lo, struct lo_inode *root) root->fd = fd; root->key.ino = stat.st_ino; root->key.dev = stat.st_dev; + root->key.mnt_id = mnt_id; root->nlookup = 2; g_atomic_int_set(&root->refcount, 2); } @@ -2886,7 +3378,7 @@ static guint lo_key_hash(gconstpointer key) { const struct lo_key *lkey = key; - return (guint)lkey->ino + (guint)lkey->dev; + return (guint)lkey->ino + (guint)lkey->dev + (guint)lkey->mnt_id; } static gboolean lo_key_equal(gconstpointer a, gconstpointer b) @@ -2894,7 +3386,7 @@ static gboolean lo_key_equal(gconstpointer a, gconstpointer b) const struct lo_key *la = a; const struct lo_key *lb = b; - return la->ino == lb->ino && la->dev == lb->dev; + return la->ino == lb->ino && la->dev == lb->dev && la->mnt_id == lb->mnt_id; } static void fuse_lo_data_cleanup(struct lo_data *lo) @@ -2914,6 +3406,8 @@ static void fuse_lo_data_cleanup(struct lo_data *lo) close(lo->root.fd); } + free(lo->xattrmap); + free_xattrmap(lo); free(lo->source); } @@ -2923,17 +3417,22 @@ int main(int argc, char *argv[]) struct fuse_session *se; struct fuse_cmdline_opts opts; struct lo_data lo = { + .sandbox = SANDBOX_NAMESPACE, .debug = 0, .writeback = 0, - .posix_lock = 1, + .posix_lock = 0, + .allow_direct_io = 0, .proc_self_fd = -1, }; struct lo_map_elem *root_elem; + struct lo_map_elem *reserve_elem; int ret = -1; /* Don't mask creation mode, kernel already did that */ umask(0); + qemu_init_exec_dir(argv[0]); + pthread_mutex_init(&lo.mutex, NULL); lo.inodes = g_hash_table_new(lo_key_hash, lo_key_equal); lo.root.fd = -1; @@ -2946,8 +3445,17 @@ int main(int argc, char *argv[]) * [1] Root inode */ lo_map_init(&lo.ino_map); - lo_map_reserve(&lo.ino_map, 0)->in_use = false; + reserve_elem = lo_map_reserve(&lo.ino_map, 0); + if (!reserve_elem) { + fuse_log(FUSE_LOG_ERR, "failed to alloc reserve_elem.\n"); + goto err_out1; + } + reserve_elem->in_use = false; root_elem = lo_map_reserve(&lo.ino_map, lo.root.fuse_ino); + if (!root_elem) { + fuse_log(FUSE_LOG_ERR, "failed to alloc root_elem.\n"); + goto err_out1; + } root_elem->inode = &lo.root; lo_map_init(&lo.dirp_map); @@ -2983,12 +3491,11 @@ int main(int argc, char *argv[]) goto err_out1; } - /* - * log_level is 0 if not configured via cmd options (0 is LOG_EMERG, - * and we don't use this log level). - */ if (opts.log_level != 0) { current_log_level = opts.log_level; + } else { + /* default log level is INFO */ + current_log_level = FUSE_LOG_INFO; } lo.debug = opts.debug; if (lo.debug) { @@ -3010,7 +3517,16 @@ int main(int argc, char *argv[]) } } else { lo.source = strdup("/"); + if (!lo.source) { + fuse_log(FUSE_LOG_ERR, "failed to strdup source\n"); + goto err_out1; + } } + + if (lo.xattrmap) { + parse_xattrmap(&lo); + } + if (!lo.timeout_set) { switch (lo.cache) { case CACHE_NONE: @@ -3030,6 +3546,8 @@ int main(int argc, char *argv[]) exit(1); } + lo.use_statx = true; + se = fuse_session_new(&args, &lo_oper, sizeof(lo_oper), &lo); if (se == NULL) { goto err_out1; diff --git a/tools/virtiofsd/seccomp.c b/tools/virtiofsd/passthrough_seccomp.c similarity index 96% rename from tools/virtiofsd/seccomp.c rename to tools/virtiofsd/passthrough_seccomp.c index bd9e7b083c98e1a79cc2417db91ff97ef25352d3..11623f56f20ca6ceb850ecf2cb8da36cebcf897a 100644 --- a/tools/virtiofsd/seccomp.c +++ b/tools/virtiofsd/passthrough_seccomp.c @@ -7,7 +7,7 @@ */ #include "qemu/osdep.h" -#include "seccomp.h" +#include "passthrough_seccomp.h" #include "fuse_i.h" #include "fuse_log.h" #include @@ -42,6 +42,7 @@ static const int syscall_whitelist[] = { SCMP_SYS(exit_group), SCMP_SYS(fallocate), SCMP_SYS(fchdir), + SCMP_SYS(fchmod), SCMP_SYS(fchmodat), SCMP_SYS(fchownat), SCMP_SYS(fcntl), @@ -75,6 +76,7 @@ static const int syscall_whitelist[] = { SCMP_SYS(mremap), SCMP_SYS(munmap), SCMP_SYS(newfstatat), + SCMP_SYS(statx), SCMP_SYS(open), SCMP_SYS(openat), SCMP_SYS(ppoll), @@ -92,6 +94,8 @@ static const int syscall_whitelist[] = { SCMP_SYS(rt_sigaction), SCMP_SYS(rt_sigprocmask), SCMP_SYS(rt_sigreturn), + SCMP_SYS(sched_getattr), + SCMP_SYS(sched_setattr), SCMP_SYS(sendmsg), SCMP_SYS(setresgid), SCMP_SYS(setresuid), @@ -115,6 +119,7 @@ static const int syscall_whitelist[] = { /* Syscalls used when --syslog is enabled */ static const int syscall_whitelist_syslog[] = { + SCMP_SYS(send), SCMP_SYS(sendto), }; diff --git a/tools/virtiofsd/seccomp.h b/tools/virtiofsd/passthrough_seccomp.h similarity index 100% rename from tools/virtiofsd/seccomp.h rename to tools/virtiofsd/passthrough_seccomp.h diff --git a/trace-events b/trace-events index 42107ebc697f6a9aac5f97122d24085a33b1c9fc..ac7cef9335980dc05b3a127fb8fc33e60da0a19e 100644 --- a/trace-events +++ b/trace-events @@ -25,22 +25,6 @@ # # The should be a sprintf()-compatible format string. -# ioport.c -cpu_in(unsigned int addr, char size, unsigned int val) "addr 0x%x(%c) value %u" -cpu_out(unsigned int addr, char size, unsigned int val) "addr 0x%x(%c) value %u" - -# balloon.c -# Since requests are raised via monitor, not many tracepoints are needed. -balloon_event(void *opaque, unsigned long addr) "opaque %p addr %lu" - -# vl.c -vm_state_notify(int running, int reason, const char *reason_str) "running %d reason %d (%s)" -load_file(const char *name, const char *path) "name %s location %s" -runstate_set(int current_state, const char *current_state_str, int new_state, const char *new_state_str) "current_run_state %d (%s) new_state %d (%s)" -system_wakeup_request(int reason) "reason=%d" -qemu_system_shutdown_request(int reason) "reason=%d" -qemu_system_powerdown_request(void) "" - # dma-helpers.c dma_blk_io(void *dbs, void *bs, int64_t offset, bool to_dev) "dbs=%p bs=%p offset=%" PRId64 " to_dev=%d" dma_aio_cancel(void *dbs) "dbs=%p" @@ -52,20 +36,11 @@ dma_map_wait(void *dbs) "dbs=%p" find_ram_offset(uint64_t size, uint64_t offset) "size: 0x%" PRIx64 " @ 0x%" PRIx64 find_ram_offset_loop(uint64_t size, uint64_t candidate, uint64_t offset, uint64_t next, uint64_t mingap) "trying size: 0x%" PRIx64 " @ 0x%" PRIx64 ", offset: 0x%" PRIx64" next: 0x%" PRIx64 " mingap: 0x%" PRIx64 ram_block_discard_range(const char *rbname, void *hva, size_t length, bool need_madvise, bool need_fallocate, int ret) "%s@%p + 0x%zx: madvise: %d fallocate: %d ret: %d" + +# accel/tcg/cputlb.c memory_notdirty_write_access(uint64_t vaddr, uint64_t ram_addr, unsigned size) "0x%" PRIx64 " ram_addr 0x%" PRIx64 " size %u" memory_notdirty_set_dirty(uint64_t vaddr) "0x%" PRIx64 -# memory.c -memory_region_ops_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u" -memory_region_ops_write(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u" -memory_region_subpage_read(int cpu_index, void *mr, uint64_t offset, uint64_t value, unsigned size) "cpu %d mr %p offset 0x%"PRIx64" value 0x%"PRIx64" size %u" -memory_region_subpage_write(int cpu_index, void *mr, uint64_t offset, uint64_t value, unsigned size) "cpu %d mr %p offset 0x%"PRIx64" value 0x%"PRIx64" size %u" -memory_region_ram_device_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u" -memory_region_ram_device_write(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u" -flatview_new(void *view, void *root) "%p (root %p)" -flatview_destroy(void *view, void *root) "%p (root %p)" -flatview_destroy_rcu(void *view, void *root) "%p (root %p)" - # gdbstub.c gdbstub_op_start(const char *device) "Starting gdbstub using device %s" gdbstub_op_exiting(uint8_t code) "notifying exit with code=0x%02x" @@ -161,8 +136,7 @@ vcpu guest_cpu_reset(void) # Targets: TCG(all) vcpu tcg guest_mem_before(TCGv vaddr, uint16_t info) "info=%d", "vaddr=0x%016"PRIx64" info=%d" -# linux-user/syscall.c -# bsd-user/syscall.c +# include/user/syscall-trace.h # @num: System call number. # @arg*: System call argument value. diff --git a/trace/Makefile.objs b/trace/Makefile.objs deleted file mode 100644 index c544509adf8886a93a15de5c45d86635722e1583..0000000000000000000000000000000000000000 --- a/trace/Makefile.objs +++ /dev/null @@ -1,59 +0,0 @@ -# -*- mode: makefile -*- - -$(BUILD_DIR)/trace-events-all: $(trace-events-files) - $(call quiet-command,cat $^ > $@) - - -################################################## -# Translation level - -$(obj)/generated-helpers-wrappers.h: $(obj)/generated-helpers-wrappers.h-timestamp - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ -$(obj)/generated-helpers-wrappers.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak $(tracetool-y) - $(call quiet-command,$(TRACETOOL) \ - --group=root \ - --format=tcg-helper-wrapper-h \ - --backend=$(TRACE_BACKENDS) \ - $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") - -$(obj)/generated-helpers.h: $(obj)/generated-helpers.h-timestamp - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ -$(obj)/generated-helpers.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak $(tracetool-y) - $(call quiet-command,$(TRACETOOL) \ - --group=root \ - --format=tcg-helper-h \ - --backend=$(TRACE_BACKENDS) \ - $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") - -$(obj)/generated-helpers.c: $(obj)/generated-helpers.c-timestamp - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ -$(obj)/generated-helpers.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak $(tracetool-y) - $(call quiet-command,$(TRACETOOL) \ - --group=root \ - --format=tcg-helper-c \ - --backend=$(TRACE_BACKENDS) \ - $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") - -$(obj)/generated-helpers.o: $(obj)/generated-helpers.c - -obj-y += generated-helpers.o - - -$(obj)/generated-tcg-tracers.h: $(obj)/generated-tcg-tracers.h-timestamp - @cmp $< $@ >/dev/null 2>&1 || cp $< $@ -$(obj)/generated-tcg-tracers.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak $(tracetool-y) - $(call quiet-command,$(TRACETOOL) \ - --group=root \ - --format=tcg-h \ - --backend=$(TRACE_BACKENDS) \ - $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") - - -###################################################################### -# Backend code - -util-obj-$(CONFIG_TRACE_SIMPLE) += simple.o -util-obj-$(CONFIG_TRACE_FTRACE) += ftrace.o -util-obj-y += control.o -obj-y += control-target.o -util-obj-y += qmp.o diff --git a/trace/control-target.c b/trace/control-target.c index ceb55c70ce8377b02d833b0ce6fe5ac2c8e35e10..e293eeed7c00120bf6983ca6c54275308920480f 100644 --- a/trace/control-target.c +++ b/trace/control-target.c @@ -9,7 +9,7 @@ #include "qemu/osdep.h" #include "cpu.h" -#include "trace-root.h" +#include "trace/trace-root.h" #include "trace/control.h" diff --git a/trace/control.c b/trace/control.c index 2ffe0008184869823fa5baf8ee43455dd3798900..b82fb87316daed1fe855579fbcc919c5b807511d 100644 --- a/trace/control.c +++ b/trace/control.c @@ -27,7 +27,7 @@ #include "qemu/error-report.h" #include "qemu/config-file.h" #include "monitor/monitor.h" -#include "trace-root.h" +#include "trace/trace-root.h" int trace_events_enabled_count; @@ -39,6 +39,7 @@ static TraceEventGroup *event_groups; static size_t nevent_groups; static uint32_t next_id; static uint32_t next_vcpu_id; +static bool init_trace_on_startup; QemuOptsList qemu_trace_opts = { .name = "trace", @@ -176,7 +177,7 @@ void trace_enable_events(const char *line_buf) { if (is_help_option(line_buf)) { trace_list_events(); - if (cur_mon == NULL) { + if (monitor_cur() == NULL) { exit(0); } } else { @@ -221,10 +222,15 @@ static void trace_init_events(const char *fname) loc_pop(&loc); } -void trace_init_file(const char *file) +void trace_init_file(void) { + QemuOpts *opts = qemu_find_opts_singleton("trace"); + const char *file = qemu_opt_get(opts, "file"); #ifdef CONFIG_TRACE_SIMPLE st_set_trace_file(file); + if (init_trace_on_startup) { + st_set_trace_file_enabled(true); + } #elif defined CONFIG_TRACE_LOG /* * If both the simple and the log backends are enabled, "--trace file" @@ -285,9 +291,8 @@ bool trace_init_backends(void) return true; } -char *trace_opt_parse(const char *optarg) +void trace_opt_parse(const char *optarg) { - char *trace_file; QemuOpts *opts = qemu_opts_parse_noisily(qemu_find_opts("trace"), optarg, true); if (!opts) { @@ -297,10 +302,8 @@ char *trace_opt_parse(const char *optarg) trace_enable_events(qemu_opt_get(opts, "enable")); } trace_init_events(qemu_opt_get(opts, "events")); - trace_file = g_strdup(qemu_opt_get(opts, "file")); + init_trace_on_startup = true; qemu_opts_del(opts); - - return trace_file; } uint32_t trace_get_vcpu_event_count(void) diff --git a/trace/control.h b/trace/control.h index 1f81c491b693d88f6268c22094304803b5e0c758..05b95ea4532afc77d47e943184400350480e799b 100644 --- a/trace/control.h +++ b/trace/control.h @@ -167,8 +167,6 @@ void trace_event_set_vcpu_state_dynamic(CPUState *vcpu, /** * trace_init_backends: - * @file: Name of trace output file; may be NULL. - * Corresponds to commandline option "--trace file=...". * * Initialize the tracing backend. * @@ -178,14 +176,12 @@ bool trace_init_backends(void); /** * trace_init_file: - * @file: Name of trace output file; may be NULL. - * Corresponds to commandline option "--trace file=...". * * Record the name of the output file for the tracing backend. * Exits if no selected backend does not support specifying the - * output file, and a non-NULL file was passed. + * output file, and a file was specified with "-trace file=...". */ -void trace_init_file(const char *file); +void trace_init_file(void); /** * trace_init_vcpu: @@ -229,10 +225,8 @@ extern QemuOptsList qemu_trace_opts; * @optarg: A string argument of --trace command line argument * * Initialize tracing subsystem. - * - * Returns the filename to save trace to. It must be freed with g_free(). */ -char *trace_opt_parse(const char *optarg); +void trace_opt_parse(const char *optarg); /** * trace_get_vcpu_event_count: diff --git a/trace/meson.build b/trace/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..843ea1449540a580d233c857d9b2c7e863705424 --- /dev/null +++ b/trace/meson.build @@ -0,0 +1,95 @@ +specific_ss.add(files('control-target.c')) + +trace_events_files = [] +foreach dir : [ '.' ] + trace_events_subdirs + trace_events_file = meson.source_root() / dir / 'trace-events' + trace_events_files += [ trace_events_file ] + group_name = dir == '.' ? 'root' : dir.underscorify() + group = '--group=' + group_name + fmt = '@0@-' + group_name + '.@1@' + + trace_h = custom_target(fmt.format('trace', 'h'), + output: fmt.format('trace', 'h'), + input: trace_events_file, + command: [ tracetool, group, '--format=h', '@INPUT@' ], + capture: true) + genh += trace_h + trace_c = custom_target(fmt.format('trace', 'c'), + output: fmt.format('trace', 'c'), + input: trace_events_file, + command: [ tracetool, group, '--format=c', '@INPUT@' ], + capture: true) + if 'CONFIG_TRACE_UST' in config_host + trace_ust_h = custom_target(fmt.format('trace-ust', 'h'), + output: fmt.format('trace-ust', 'h'), + input: trace_events_file, + command: [ tracetool, group, '--format=ust-events-h', '@INPUT@' ], + capture: true) + trace_ss.add(trace_ust_h, lttng, urcubp) + genh += trace_ust_h + endif + trace_ss.add(trace_h, trace_c) + if 'CONFIG_TRACE_DTRACE' in config_host + trace_dtrace = custom_target(fmt.format('trace-dtrace', 'dtrace'), + output: fmt.format('trace-dtrace', 'dtrace'), + input: trace_events_file, + command: [ tracetool, group, '--format=d', '@INPUT@' ], + capture: true) + trace_dtrace_h = custom_target(fmt.format('trace-dtrace', 'h'), + output: fmt.format('trace-dtrace', 'h'), + input: trace_dtrace, + command: [ 'dtrace', '-DSTAP_SDT_V2', '-o', '@OUTPUT@', '-h', '-s', '@INPUT@' ]) + trace_ss.add(trace_dtrace_h) + if host_machine.system() != 'darwin' + trace_dtrace_o = custom_target(fmt.format('trace-dtrace', 'o'), + output: fmt.format('trace-dtrace', 'o'), + input: trace_dtrace, + command: [ 'dtrace', '-DSTAP_SDT_V2', '-o', '@OUTPUT@', '-G', '-s', '@INPUT@' ]) + trace_ss.add(trace_dtrace_o) + endif + + genh += trace_dtrace_h + endif +endforeach + +trace_events_all = custom_target('trace-events-all', + output: 'trace-events-all', + input: trace_events_files, + command: [ 'cat', '@INPUT@' ], + capture: true, + install: true, + install_dir: qemu_datadir) + +foreach d : [ + ['generated-tcg-tracers.h', 'tcg-h'], + ['generated-helpers.c', 'tcg-helper-c'], + ['generated-helpers.h', 'tcg-helper-h'], + ['generated-helpers-wrappers.h', 'tcg-helper-wrapper-h'], +] + gen = custom_target(d[0], + output: d[0], + input: meson.source_root() / 'trace-events', + command: [ tracetool, '--group=root', '--format=@0@'.format(d[1]), '@INPUT@' ], + capture: true) + specific_ss.add(gen) +endforeach + +if 'CONFIG_TRACE_UST' in config_host + trace_ust_all_h = custom_target('trace-ust-all.h', + output: 'trace-ust-all.h', + input: trace_events_files, + command: [ tracetool, '--group=all', '--format=ust-events-h', '@INPUT@' ], + capture: true) + trace_ust_all_c = custom_target('trace-ust-all.c', + output: 'trace-ust-all.c', + input: trace_events_files, + command: [ tracetool, '--group=all', '--format=ust-events-c', '@INPUT@' ], + capture: true) + trace_ss.add(trace_ust_all_h, trace_ust_all_c) + genh += trace_ust_all_h +endif + +trace_ss.add(when: 'CONFIG_TRACE_SIMPLE', if_true: files('simple.c')) +trace_ss.add(when: 'CONFIG_TRACE_FTRACE', if_true: files('ftrace.c')) +trace_ss.add(files('control.c')) +trace_ss.add(files('qmp.c')) diff --git a/trace/simple.c b/trace/simple.c index fc7106ec496d7e4d28a65f6582e372ae8d1e4331..9cd2ed1fb3f4c90c2af4885c2a98c1bd31e8492c 100644 --- a/trace/simple.c +++ b/trace/simple.c @@ -302,10 +302,17 @@ static int st_write_event_mapping(void) return 0; } -void st_set_trace_file_enabled(bool enable) +/** + * Enable / disable tracing, return whether it was enabled. + * + * @enable: enable if %true, else disable. + */ +bool st_set_trace_file_enabled(bool enable) { + bool was_enabled = trace_fp; + if (enable == !!trace_fp) { - return; /* no change */ + return was_enabled; /* no change */ } /* Halt trace writeout */ @@ -323,14 +330,14 @@ void st_set_trace_file_enabled(bool enable) trace_fp = fopen(trace_file_name, "wb"); if (!trace_fp) { - return; + return was_enabled; } if (fwrite(&header, sizeof header, 1, trace_fp) != 1 || st_write_event_mapping() < 0) { fclose(trace_fp); trace_fp = NULL; - return; + return was_enabled; } /* Resume trace writeout */ @@ -340,6 +347,7 @@ void st_set_trace_file_enabled(bool enable) fclose(trace_fp); trace_fp = NULL; } + return was_enabled; } /** @@ -350,7 +358,7 @@ void st_set_trace_file_enabled(bool enable) */ void st_set_trace_file(const char *file) { - st_set_trace_file_enabled(false); + bool saved_enable = st_set_trace_file_enabled(false); g_free(trace_file_name); @@ -361,7 +369,7 @@ void st_set_trace_file(const char *file) trace_file_name = g_strdup_printf("%s", file); } - st_set_trace_file_enabled(true); + st_set_trace_file_enabled(saved_enable); } void st_print_trace_file_status(void) diff --git a/trace/simple.h b/trace/simple.h index 5771a0634f71c08dbc1a4f7d5b91affced126456..26ccbc8b8ae353244eb1fe5351cd6d8002b36a28 100644 --- a/trace/simple.h +++ b/trace/simple.h @@ -12,7 +12,7 @@ #define TRACE_SIMPLE_H void st_print_trace_file_status(void); -void st_set_trace_file_enabled(bool enable); +bool st_set_trace_file_enabled(bool enable); void st_set_trace_file(const char *file); bool st_init(void); void st_flush_trace_buffer(void); diff --git a/ui/Makefile.objs b/ui/Makefile.objs deleted file mode 100644 index 504b19647977f5f22edcaad1d3e85a2e19674b5c..0000000000000000000000000000000000000000 --- a/ui/Makefile.objs +++ /dev/null @@ -1,73 +0,0 @@ -vnc-obj-y += vnc.o -vnc-obj-y += vnc-enc-zlib.o vnc-enc-hextile.o -vnc-obj-y += vnc-enc-tight.o vnc-palette.o -vnc-obj-y += vnc-enc-zrle.o -vnc-obj-y += vnc-auth-vencrypt.o -vnc-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o -vnc-obj-y += vnc-ws.o -vnc-obj-y += vnc-jobs.o - -common-obj-y += keymaps.o console.o cursor.o qemu-pixman.o -common-obj-y += input.o input-keymap.o input-legacy.o kbd-state.o -common-obj-y += input-barrier.o -common-obj-$(CONFIG_LINUX) += input-linux.o -common-obj-$(CONFIG_SPICE) += spice-core.o spice-input.o spice-display.o -common-obj-$(CONFIG_COCOA) += cocoa.o -common-obj-$(CONFIG_VNC) += $(vnc-obj-y) -common-obj-$(call lnot,$(CONFIG_VNC)) += vnc-stubs.o -ifneq (,$(findstring m,$(CONFIG_SDL)$(CONFIG_GTK))) -common-obj-$(CONFIG_WIN32) += win32-kbd-hook.o -endif - -# ui-sdl module -common-obj-$(CONFIG_SDL) += sdl.mo -sdl.mo-objs := sdl2.o sdl2-input.o sdl2-2d.o -ifeq ($(CONFIG_OPENGL),y) -sdl.mo-objs += sdl2-gl.o -endif -sdl.mo-cflags := $(SDL_CFLAGS) -sdl.mo-libs := $(SDL_LIBS) - -# ui-gtk module -common-obj-$(CONFIG_GTK) += gtk.mo -gtk.mo-objs := gtk.o -gtk.mo-cflags := $(GTK_CFLAGS) $(VTE_CFLAGS) -gtk.mo-libs := $(GTK_LIBS) $(VTE_LIBS) -ifeq ($(CONFIG_OPENGL),y) -gtk.mo-objs += gtk-egl.o -gtk.mo-libs += $(OPENGL_LIBS) -ifeq ($(CONFIG_GTK_GL),y) -gtk.mo-objs += gtk-gl-area.o -endif -endif - -ifeq ($(CONFIG_X11),y) -sdl.mo-objs += x_keymap.o -gtk.mo-objs += x_keymap.o -x_keymap.o-cflags := $(X11_CFLAGS) -x_keymap.o-libs := $(X11_LIBS) -endif - -common-obj-$(CONFIG_CURSES) += curses.mo -curses.mo-objs := curses.o -curses.mo-cflags := $(CURSES_CFLAGS) $(ICONV_CFLAGS) -curses.mo-libs := $(CURSES_LIBS) $(ICONV_LIBS) - -ifeq ($(CONFIG_GIO)$(CONFIG_SPICE),yy) -common-obj-$(if $(CONFIG_MODULES),m,y) += spice-app.mo -endif -spice-app.mo-objs := spice-app.o -spice-app.mo-cflags := $(GIO_CFLAGS) -spice-app.mo-libs := $(GIO_LIBS) - -common-obj-$(CONFIG_OPENGL) += shader.o -common-obj-$(CONFIG_OPENGL) += console-gl.o -common-obj-$(CONFIG_OPENGL) += egl-helpers.o -common-obj-$(CONFIG_OPENGL) += egl-context.o -common-obj-$(CONFIG_OPENGL_DMABUF) += egl-headless.o - -shader.o-libs += $(OPENGL_LIBS) -console-gl.o-libs += $(OPENGL_LIBS) -egl-helpers.o-libs += $(OPENGL_LIBS) -egl-context.o-libs += $(OPENGL_LIBS) -egl-headless.o-libs += $(OPENGL_LIBS) diff --git a/ui/cocoa.m b/ui/cocoa.m index cb556e4e6689df83f28457905eb805fec6e567ad..f32adc3074f5abef7cf80b620194f2b60aafdcd8 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -32,8 +32,10 @@ #include "ui/input.h" #include "sysemu/sysemu.h" #include "sysemu/runstate.h" +#include "sysemu/cpu-throttle.h" #include "qapi/error.h" #include "qapi/qapi-commands-block.h" +#include "qapi/qapi-commands-machine.h" #include "qapi/qapi-commands-misc.h" #include "sysemu/blockdev.h" #include "qemu-version.h" diff --git a/ui/console.c b/ui/console.c index 865fa32635974b89fba8d6b952d5e1b772653bd6..53dee8e26b17412ae561ccf769ad3f3f23be27e5 100644 --- a/ui/console.c +++ b/ui/console.c @@ -34,6 +34,7 @@ #include "trace.h" #include "exec/memory.h" #include "io/channel-file.h" +#include "qom/object.h" #define DEFAULT_BACKSCROLL 512 #define CONSOLE_CURSOR_PERIOD 500 @@ -167,6 +168,7 @@ struct QemuConsole { QEMUFIFO out_fifo; uint8_t out_fifo_buf[16]; QEMUTimer *kbd_timer; + CoQueue dump_queue; QTAILQ_ENTRY(QemuConsole) next; }; @@ -194,7 +196,6 @@ static void dpy_refresh(DisplayState *s); static DisplayState *get_alloc_displaystate(void); static void text_console_update_cursor_timer(void); static void text_console_update_cursor(void *opaque); -static bool ppm_save(int fd, DisplaySurface *ds, Error **errp); static void gui_update(void *opaque) { @@ -263,15 +264,19 @@ static void gui_setup_refresh(DisplayState *ds) void graphic_hw_update_done(QemuConsole *con) { + if (con) { + qemu_co_queue_restart_all(&con->dump_queue); + } } void graphic_hw_update(QemuConsole *con) { bool async = false; + con = con ? con : active_console; if (!con) { - con = active_console; + return; } - if (con && con->hw_ops->gfx_update) { + if (con->hw_ops->gfx_update) { con->hw_ops->gfx_update(con->hw); async = con->hw_ops->gfx_update_async; } @@ -310,16 +315,16 @@ void graphic_hw_invalidate(QemuConsole *con) } } -static bool ppm_save(int fd, DisplaySurface *ds, Error **errp) +static bool ppm_save(int fd, pixman_image_t *image, Error **errp) { - int width = pixman_image_get_width(ds->image); - int height = pixman_image_get_height(ds->image); + int width = pixman_image_get_width(image); + int height = pixman_image_get_height(image); g_autoptr(Object) ioc = OBJECT(qio_channel_file_new_fd(fd)); g_autofree char *header = NULL; g_autoptr(pixman_image_t) linebuf = NULL; int y; - trace_ppm_save(fd, ds); + trace_ppm_save(fd, image); header = g_strdup_printf("P6\n%d %d\n%d\n", width, height, 255); if (qio_channel_write_all(QIO_CHANNEL(ioc), @@ -329,7 +334,7 @@ static bool ppm_save(int fd, DisplaySurface *ds, Error **errp) linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width); for (y = 0; y < height; y++) { - qemu_pixman_linebuf_fill(linebuf, ds->image, width, 0, y); + qemu_pixman_linebuf_fill(linebuf, image, width, 0, y); if (qio_channel_write_all(QIO_CHANNEL(ioc), (char *)pixman_image_get_data(linebuf), pixman_image_get_stride(linebuf), errp) < 0) { @@ -340,9 +345,17 @@ static bool ppm_save(int fd, DisplaySurface *ds, Error **errp) return true; } -void qmp_screendump(const char *filename, bool has_device, const char *device, - bool has_head, int64_t head, Error **errp) +static void graphic_hw_update_bh(void *con) { + graphic_hw_update(con); +} + +/* Safety: coroutine-only, concurrent-coroutine safe, main thread only */ +void coroutine_fn +qmp_screendump(const char *filename, bool has_device, const char *device, + bool has_head, int64_t head, Error **errp) +{ + g_autoptr(pixman_image_t) image = NULL; QemuConsole *con; DisplaySurface *surface; int fd; @@ -365,21 +378,38 @@ void qmp_screendump(const char *filename, bool has_device, const char *device, } } - graphic_hw_update(con); + if (qemu_co_queue_empty(&con->dump_queue)) { + /* Defer the update, it will restart the pending coroutines */ + aio_bh_schedule_oneshot(qemu_get_aio_context(), + graphic_hw_update_bh, con); + } + qemu_co_queue_wait(&con->dump_queue, NULL); + + /* + * All pending coroutines are woken up, while the BQL is held. No + * further graphic update are possible until it is released. Take + * an image ref before that. + */ surface = qemu_console_surface(con); if (!surface) { error_setg(errp, "no surface"); return; } + image = pixman_image_ref(surface->image); - fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); + fd = qemu_open_old(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); if (fd == -1) { error_setg(errp, "failed to open file '%s': %s", filename, strerror(errno)); return; } - if (!ppm_save(fd, surface, errp)) { + /* + * The image content could potentially be updated as the coroutine + * yields and releases the BQL. It could produce corrupted dump, but + * it should be otherwise safe. + */ + if (!ppm_save(fd, image, errp)) { qemu_unlink(filename); } } @@ -1082,13 +1112,15 @@ void console_select(unsigned int index) } } -typedef struct VCChardev { +struct VCChardev { Chardev parent; QemuConsole *console; -} VCChardev; +}; +typedef struct VCChardev VCChardev; #define TYPE_CHARDEV_VC "chardev-vc" -#define VC_CHARDEV(obj) OBJECT_CHECK(VCChardev, (obj), TYPE_CHARDEV_VC) +DECLARE_INSTANCE_CHECKER(VCChardev, VC_CHARDEV, + TYPE_CHARDEV_VC) static int vc_chr_write(Chardev *chr, const uint8_t *buf, int len) { @@ -1293,6 +1325,7 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type, obj = object_new(TYPE_QEMU_CONSOLE); s = QEMU_CONSOLE(obj); + qemu_co_queue_init(&s->dump_queue); s->head = head; object_property_add_link(obj, "device", TYPE_DEVICE, (Object **)&s->device, @@ -1307,6 +1340,7 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type, } s->ds = ds; s->console_type = console_type; + s->window_id = -1; if (QTAILQ_EMPTY(&consoles)) { s->index = 0; @@ -1513,6 +1547,13 @@ bool dpy_ui_info_supported(QemuConsole *con) return con->hw_ops->ui_info != NULL; } +const QemuUIInfo *dpy_get_ui_info(const QemuConsole *con) +{ + assert(con != NULL); + + return &con->ui_info; +} + int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info) { assert(con != NULL); @@ -1910,7 +1951,7 @@ QemuConsole *graphic_console_init(DeviceState *dev, uint32_t head, } graphic_console_set_hwops(s, hw_ops, opaque); if (dev) { - object_property_set_link(OBJECT(s), OBJECT(dev), "device", + object_property_set_link(OBJECT(s), "device", OBJECT(dev), &error_abort); } @@ -1937,7 +1978,7 @@ void graphic_console_close(QemuConsole *con) } trace_console_gfx_close(con->index); - object_property_set_link(OBJECT(con), NULL, "device", &error_abort); + object_property_set_link(OBJECT(con), "device", NULL, &error_abort); graphic_console_set_hwops(con, &unused_ops, NULL); if (con->gl) { @@ -2184,12 +2225,12 @@ static void text_console_do_init(Chardev *chr, DisplayState *ds) text_console_resize(s); if (chr->label) { - char msg[128]; - int len; + char *msg; s->t_attrib.bgcol = QEMU_COLOR_BLUE; - len = snprintf(msg, sizeof(msg), "%s console\r\n", chr->label); - vc_chr_write(chr, (uint8_t *)msg, len); + msg = g_strdup_printf("%s console\r\n", chr->label); + vc_chr_write(chr, (uint8_t *)msg, strlen(msg)); + g_free(msg); s->t_attrib = s->t_attrib_default; } diff --git a/ui/curses.c b/ui/curses.c index a59b23a9cf63fbee47ce75fbe354997a47ee9bb4..e4f9588c3e8ad001d74f9704ba3bf55299d98925 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -30,7 +30,6 @@ #endif #include #include -#include #include #include "qapi/error.h" @@ -263,7 +262,7 @@ static int curses2foo(const int _curses2foo[], const int _curseskey2foo[], static void curses_refresh(DisplayChangeListener *dcl) { int chr, keysym, keycode, keycode_alt; - enum maybe_keycode maybe_keycode; + enum maybe_keycode maybe_keycode = CURSES_KEYCODE; curses_winch_check(); @@ -300,7 +299,7 @@ static void curses_refresh(DisplayChangeListener *dcl) /* alt or esc key */ if (keycode == 1) { - enum maybe_keycode next_maybe_keycode; + enum maybe_keycode next_maybe_keycode = CURSES_KEYCODE; int nextchr = console_getch(&next_maybe_keycode); if (nextchr != -1) { @@ -526,6 +525,7 @@ static void font_setup(void) iconv_t nativecharset_to_ucs2; iconv_t font_conv; int i; + g_autofree gchar *local_codeset = g_get_codeset(); /* * Control characters are normally non-printable, but VGA does have @@ -566,14 +566,14 @@ static void font_setup(void) 0x25bc }; - ucs2_to_nativecharset = iconv_open(nl_langinfo(CODESET), "UCS-2"); + ucs2_to_nativecharset = iconv_open(local_codeset, "UCS-2"); if (ucs2_to_nativecharset == (iconv_t) -1) { fprintf(stderr, "Could not convert font glyphs from UCS-2: '%s'\n", strerror(errno)); exit(1); } - nativecharset_to_ucs2 = iconv_open("UCS-2", nl_langinfo(CODESET)); + nativecharset_to_ucs2 = iconv_open("UCS-2", local_codeset); if (nativecharset_to_ucs2 == (iconv_t) -1) { iconv_close(ucs2_to_nativecharset); fprintf(stderr, "Could not convert font glyphs to UCS-2: '%s'\n", @@ -581,7 +581,7 @@ static void font_setup(void) exit(1); } - font_conv = iconv_open(nl_langinfo(CODESET), font_charset); + font_conv = iconv_open(local_codeset, font_charset); if (font_conv == (iconv_t) -1) { iconv_close(ucs2_to_nativecharset); iconv_close(nativecharset_to_ucs2); @@ -602,7 +602,7 @@ static void font_setup(void) /* DEL */ convert_ucs(0x7F, 0x2302, ucs2_to_nativecharset); - if (strcmp(nl_langinfo(CODESET), "UTF-8")) { + if (strcmp(local_codeset, "UTF-8")) { /* Non-Unicode capable, use termcap equivalents for those available */ for (i = 0; i <= 0xFF; i++) { wchar_t wch[CCHARW_MAX]; diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 85f9d14c51f1ad7b46f5bed4513790ba389cb0a4..98c22d23f501dde0d8147c3f9fc7785f5d80d356 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -147,10 +147,21 @@ QEMUGLContext gd_gl_area_create_context(DisplayChangeListener *dcl, gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); window = gtk_widget_get_window(vc->gfx.drawing_area); ctx = gdk_window_create_gl_context(window, &err); + if (err) { + g_printerr("Create gdk gl context failed: %s\n", err->message); + g_error_free(err); + return NULL; + } gdk_gl_context_set_required_version(ctx, params->major_ver, params->minor_ver); gdk_gl_context_realize(ctx, &err); + if (err) { + g_printerr("Realize gdk gl context failed: %s\n", err->message); + g_error_free(err); + g_clear_object(&ctx); + return NULL; + } return ctx; } diff --git a/ui/gtk.c b/ui/gtk.c index d4b49bd7dafec875e3608664a7455c8468f1b924..a752aa22be0f4e75c90827073ea29b4156d877b2 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -33,6 +33,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qapi/qapi-commands-control.h" +#include "qapi/qapi-commands-machine.h" #include "qapi/qapi-commands-misc.h" #include "qemu/cutils.h" @@ -51,6 +52,7 @@ #include #include "trace.h" +#include "qemu/cutils.h" #include "ui/input.h" #include "sysemu/runstate.h" #include "sysemu/sysemu.h" @@ -171,14 +173,16 @@ struct GtkDisplayState { DisplayOptions *opts; }; -typedef struct VCChardev { +struct VCChardev { Chardev parent; VirtualConsole *console; bool echo; -} VCChardev; +}; +typedef struct VCChardev VCChardev; #define TYPE_CHARDEV_VC "chardev-vc" -#define VC_CHARDEV(obj) OBJECT_CHECK(VCChardev, (obj), TYPE_CHARDEV_VC) +DECLARE_INSTANCE_CHECKER(VCChardev, VC_CHARDEV, + TYPE_CHARDEV_VC) bool gtk_use_gl_area; @@ -744,6 +748,25 @@ static void gd_resize_event(GtkGLArea *area, #endif +/* + * If available, return the refresh rate of the display in milli-Hertz, + * else return 0. + */ +static int gd_refresh_rate_millihz(GtkWidget *window) +{ +#ifdef GDK_VERSION_3_22 + GdkWindow *win = gtk_widget_get_window(window); + + if (win) { + GdkDisplay *dpy = gtk_widget_get_display(window); + GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win); + + return gdk_monitor_get_refresh_rate(monitor); + } +#endif + return 0; +} + static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque) { VirtualConsole *vc = opaque; @@ -751,6 +774,7 @@ static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque) int mx, my; int ww, wh; int fbw, fbh; + int refresh_rate_millihz; #if defined(CONFIG_OPENGL) if (vc->gfx.gls) { @@ -771,6 +795,12 @@ static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque) return FALSE; } + refresh_rate_millihz = gd_refresh_rate_millihz(vc->window ? + vc->window : s->window); + if (refresh_rate_millihz) { + vc->gfx.dcl.update_interval = MILLISEC_PER_SEC / refresh_rate_millihz; + } + fbw = surface_width(vc->gfx.ds); fbh = surface_height(vc->gfx.ds); @@ -1949,31 +1979,11 @@ static GtkWidget *gd_create_menu_machine(GtkDisplayState *s) return machine_menu; } -/* - * If available, return the refresh rate of the display in milli-Hertz, - * else return 0. - */ -static int gd_refresh_rate_millihz(GtkWidget *window) -{ -#ifdef GDK_VERSION_3_22 - GdkWindow *win = gtk_widget_get_window(window); - - if (win) { - GdkDisplay *dpy = gtk_widget_get_display(window); - GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win); - - return gdk_monitor_get_refresh_rate(monitor); - } -#endif - return 0; -} - static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc, QemuConsole *con, int idx, GSList *group, GtkWidget *view_menu) { bool zoom_to_fit = false; - int refresh_rate_millihz; vc->label = qemu_console_get_label(con); vc->s = s; @@ -1996,14 +2006,10 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc, * proper replacement (native opengl support) is only * available in 3.16+. Silence the warning if possible. */ -#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif gtk_widget_set_double_buffered(vc->gfx.drawing_area, FALSE); -#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE #pragma GCC diagnostic pop -#endif vc->gfx.dcl.ops = &dcl_egl_ops; } } else @@ -2035,12 +2041,6 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc, vc->gfx.kbd = qkbd_state_init(con); vc->gfx.dcl.con = con; - refresh_rate_millihz = gd_refresh_rate_millihz(vc->window ? - vc->window : s->window); - if (refresh_rate_millihz) { - vc->gfx.dcl.update_interval = MILLISEC_PER_SEC / refresh_rate_millihz; - } - register_displaychangelistener(&vc->gfx.dcl); gd_connect_vc_gfx_signals(vc); @@ -2204,6 +2204,7 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts) GtkDisplayState *s = g_malloc0(sizeof(*s)); GdkDisplay *window_display; GtkIconTheme *theme; + char *dir; if (!gtkinit) { fprintf(stderr, "gtk initialization failed\n"); @@ -2213,7 +2214,9 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts) s->opts = opts; theme = gtk_icon_theme_get_default(); - gtk_icon_theme_prepend_search_path(theme, CONFIG_QEMU_ICONDIR); + dir = get_relocated_path(CONFIG_QEMU_ICONDIR); + gtk_icon_theme_prepend_search_path(theme, dir); + g_free(dir); g_set_prgname("qemu"); s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); @@ -2229,7 +2232,9 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts) * sure that we don't accidentally break implicit assumptions. */ setlocale(LC_MESSAGES, ""); setlocale(LC_CTYPE, "C.UTF-8"); - bindtextdomain("qemu", CONFIG_QEMU_LOCALEDIR); + dir = get_relocated_path(CONFIG_QEMU_LOCALEDIR); + bindtextdomain("qemu", dir); + g_free(dir); bind_textdomain_codeset("qemu", "UTF-8"); textdomain("qemu"); diff --git a/ui/icons/meson.build b/ui/icons/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..12c52080ebd7cbf3378c388ba608a6dcaa90c8eb --- /dev/null +++ b/ui/icons/meson.build @@ -0,0 +1,13 @@ +foreach s: [16, 24, 32, 48, 64, 128, 256, 512] + s = '@0@x@0@'.format(s.to_string()) + install_data('qemu_@0@.png'.format(s), + rename: 'qemu.png', + install_dir: qemu_icondir / 'hicolor' / s / 'apps') +endforeach + +install_data('qemu_32x32.bmp', + rename: 'qemu.bmp', + install_dir: qemu_icondir / 'hicolor' / '32x32' / 'apps') + +install_data('qemu.svg', + install_dir: qemu_icondir / 'hicolor' / 'scalable' / 'apps') diff --git a/ui/input-barrier.c b/ui/input-barrier.c index 1cdf0c5f8295e8c51d2b8c88989ed47db54572c1..81b8d04ec8dae63f8da2e70917c94b2a6869499f 100644 --- a/ui/input-barrier.c +++ b/ui/input-barrier.c @@ -13,21 +13,16 @@ #include "qom/object_interfaces.h" #include "io/channel-socket.h" #include "ui/input.h" +#include "qom/object.h" #include "ui/vnc_keysym.h" /* use name2keysym from VNC as we use X11 values */ #include "qemu/cutils.h" #include "qapi/qmp/qerror.h" #include "input-barrier.h" #define TYPE_INPUT_BARRIER "input-barrier" -#define INPUT_BARRIER(obj) \ - OBJECT_CHECK(InputBarrier, (obj), TYPE_INPUT_BARRIER) -#define INPUT_BARRIER_GET_CLASS(obj) \ - OBJECT_GET_CLASS(InputBarrierClass, (obj), TYPE_INPUT_BARRIER) -#define INPUT_BARRIER_CLASS(klass) \ - OBJECT_CLASS_CHECK(InputBarrierClass, (klass), TYPE_INPUT_BARRIER) +OBJECT_DECLARE_SIMPLE_TYPE(InputBarrier, + INPUT_BARRIER) -typedef struct InputBarrier InputBarrier; -typedef struct InputBarrierClass InputBarrierClass; #define MAX_HELLO_LENGTH 1024 @@ -49,9 +44,6 @@ struct InputBarrier { char buffer[MAX_HELLO_LENGTH]; }; -struct InputBarrierClass { - ObjectClass parent_class; -}; static const char *cmd_names[] = { [barrierCmdCNoop] = "CNOP", @@ -697,28 +689,6 @@ static void input_barrier_instance_init(Object *obj) ib->y_origin = 0; ib->width = 1920; ib->height = 1080; - - object_property_add_str(obj, "name", - input_barrier_get_name, - input_barrier_set_name); - object_property_add_str(obj, "server", - input_barrier_get_server, - input_barrier_set_server); - object_property_add_str(obj, "port", - input_barrier_get_port, - input_barrier_set_port); - object_property_add_str(obj, "x-origin", - input_barrier_get_x_origin, - input_barrier_set_x_origin); - object_property_add_str(obj, "y-origin", - input_barrier_get_y_origin, - input_barrier_set_y_origin); - object_property_add_str(obj, "width", - input_barrier_get_width, - input_barrier_set_width); - object_property_add_str(obj, "height", - input_barrier_get_height, - input_barrier_set_height); } static void input_barrier_class_init(ObjectClass *oc, void *data) @@ -726,12 +696,33 @@ static void input_barrier_class_init(ObjectClass *oc, void *data) UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); ucc->complete = input_barrier_complete; + + object_class_property_add_str(oc, "name", + input_barrier_get_name, + input_barrier_set_name); + object_class_property_add_str(oc, "server", + input_barrier_get_server, + input_barrier_set_server); + object_class_property_add_str(oc, "port", + input_barrier_get_port, + input_barrier_set_port); + object_class_property_add_str(oc, "x-origin", + input_barrier_get_x_origin, + input_barrier_set_x_origin); + object_class_property_add_str(oc, "y-origin", + input_barrier_get_y_origin, + input_barrier_set_y_origin); + object_class_property_add_str(oc, "width", + input_barrier_get_width, + input_barrier_set_width); + object_class_property_add_str(oc, "height", + input_barrier_get_height, + input_barrier_set_height); } static const TypeInfo input_barrier_info = { .name = TYPE_INPUT_BARRIER, .parent = TYPE_OBJECT, - .class_size = sizeof(InputBarrierClass), .class_init = input_barrier_class_init, .instance_size = sizeof(InputBarrier), .instance_init = input_barrier_instance_init, diff --git a/ui/input-keymap.c b/ui/input-keymap.c index c4301851bd2428f50cede5c0ab5ab6e5fc50b202..1b756a6970c0049942486efff2f8ce61815c3f26 100644 --- a/ui/input-keymap.c +++ b/ui/input-keymap.c @@ -4,23 +4,23 @@ #include "standard-headers/linux/input.h" -#include "ui/input-keymap-atset1-to-qcode.c" -#include "ui/input-keymap-linux-to-qcode.c" -#include "ui/input-keymap-qcode-to-atset1.c" -#include "ui/input-keymap-qcode-to-atset2.c" -#include "ui/input-keymap-qcode-to-atset3.c" -#include "ui/input-keymap-qcode-to-linux.c" -#include "ui/input-keymap-qcode-to-qnum.c" -#include "ui/input-keymap-qcode-to-sun.c" -#include "ui/input-keymap-qnum-to-qcode.c" -#include "ui/input-keymap-usb-to-qcode.c" -#include "ui/input-keymap-win32-to-qcode.c" -#include "ui/input-keymap-x11-to-qcode.c" -#include "ui/input-keymap-xorgevdev-to-qcode.c" -#include "ui/input-keymap-xorgkbd-to-qcode.c" -#include "ui/input-keymap-xorgxquartz-to-qcode.c" -#include "ui/input-keymap-xorgxwin-to-qcode.c" -#include "ui/input-keymap-osx-to-qcode.c" +#include "ui/input-keymap-atset1-to-qcode.c.inc" +#include "ui/input-keymap-linux-to-qcode.c.inc" +#include "ui/input-keymap-qcode-to-atset1.c.inc" +#include "ui/input-keymap-qcode-to-atset2.c.inc" +#include "ui/input-keymap-qcode-to-atset3.c.inc" +#include "ui/input-keymap-qcode-to-linux.c.inc" +#include "ui/input-keymap-qcode-to-qnum.c.inc" +#include "ui/input-keymap-qcode-to-sun.c.inc" +#include "ui/input-keymap-qnum-to-qcode.c.inc" +#include "ui/input-keymap-usb-to-qcode.c.inc" +#include "ui/input-keymap-win32-to-qcode.c.inc" +#include "ui/input-keymap-x11-to-qcode.c.inc" +#include "ui/input-keymap-xorgevdev-to-qcode.c.inc" +#include "ui/input-keymap-xorgkbd-to-qcode.c.inc" +#include "ui/input-keymap-xorgxquartz-to-qcode.c.inc" +#include "ui/input-keymap-xorgxwin-to-qcode.c.inc" +#include "ui/input-keymap-osx-to-qcode.c.inc" int qemu_input_linux_to_qcode(unsigned int lnx) { diff --git a/ui/input-linux.c b/ui/input-linux.c index 4925ce1af100d6bd37d846c37a34fe421a0e4cb7..05c0c988199a99e51dfd57967b0eb994d82276fc 100644 --- a/ui/input-linux.c +++ b/ui/input-linux.c @@ -17,6 +17,7 @@ #include #include "standard-headers/linux/input.h" +#include "qom/object.h" static bool linux_is_button(unsigned int lnx) { @@ -30,15 +31,9 @@ static bool linux_is_button(unsigned int lnx) } #define TYPE_INPUT_LINUX "input-linux" -#define INPUT_LINUX(obj) \ - OBJECT_CHECK(InputLinux, (obj), TYPE_INPUT_LINUX) -#define INPUT_LINUX_GET_CLASS(obj) \ - OBJECT_GET_CLASS(InputLinuxClass, (obj), TYPE_INPUT_LINUX) -#define INPUT_LINUX_CLASS(klass) \ - OBJECT_CLASS_CHECK(InputLinuxClass, (klass), TYPE_INPUT_LINUX) +OBJECT_DECLARE_SIMPLE_TYPE(InputLinux, + INPUT_LINUX) -typedef struct InputLinux InputLinux; -typedef struct InputLinuxClass InputLinuxClass; struct InputLinux { Object parent; @@ -70,9 +65,6 @@ struct InputLinux { QTAILQ_ENTRY(InputLinux) next; }; -struct InputLinuxClass { - ObjectClass parent_class; -}; static QTAILQ_HEAD(, InputLinux) inputs = QTAILQ_HEAD_INITIALIZER(inputs); @@ -426,6 +418,7 @@ static void input_linux_instance_finalize(Object *obj) if (il->initialized) { QTAILQ_REMOVE(&inputs, il, next); + qemu_set_fd_handler(il->fd, NULL, NULL, NULL); close(il->fd); } g_free(il->evdev); @@ -497,19 +490,6 @@ static void input_linux_set_grab_toggle(Object *obj, int value, static void input_linux_instance_init(Object *obj) { - object_property_add_str(obj, "evdev", - input_linux_get_evdev, - input_linux_set_evdev); - object_property_add_bool(obj, "grab_all", - input_linux_get_grab_all, - input_linux_set_grab_all); - object_property_add_bool(obj, "repeat", - input_linux_get_repeat, - input_linux_set_repeat); - object_property_add_enum(obj, "grab-toggle", "GrabToggleKeys", - &GrabToggleKeys_lookup, - input_linux_get_grab_toggle, - input_linux_set_grab_toggle); } static void input_linux_class_init(ObjectClass *oc, void *data) @@ -517,12 +497,25 @@ static void input_linux_class_init(ObjectClass *oc, void *data) UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); ucc->complete = input_linux_complete; + + object_class_property_add_str(oc, "evdev", + input_linux_get_evdev, + input_linux_set_evdev); + object_class_property_add_bool(oc, "grab_all", + input_linux_get_grab_all, + input_linux_set_grab_all); + object_class_property_add_bool(oc, "repeat", + input_linux_get_repeat, + input_linux_set_repeat); + object_class_property_add_enum(oc, "grab-toggle", "GrabToggleKeys", + &GrabToggleKeys_lookup, + input_linux_get_grab_toggle, + input_linux_set_grab_toggle); } static const TypeInfo input_linux_info = { .name = TYPE_INPUT_LINUX, .parent = TYPE_OBJECT, - .class_size = sizeof(InputLinuxClass), .class_init = input_linux_class_init, .instance_size = sizeof(InputLinux), .instance_init = input_linux_instance_init, diff --git a/ui/meson.build b/ui/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..013258a01c736d006fa26c8b935a937ab2effb3c --- /dev/null +++ b/ui/meson.build @@ -0,0 +1,145 @@ +softmmu_ss.add(pixman) +specific_ss.add(when: ['CONFIG_SOFTMMU'], if_true: pixman) # for the include path + +softmmu_ss.add(files( + 'console.c', + 'cursor.c', + 'input-keymap.c', + 'input-legacy.c', + 'input-barrier.c', + 'input.c', + 'kbd-state.c', + 'keymaps.c', + 'qemu-pixman.c', +)) +softmmu_ss.add([spice_headers, files('spice-module.c')]) + +softmmu_ss.add(when: 'CONFIG_LINUX', if_true: files('input-linux.c')) +softmmu_ss.add(when: cocoa, if_true: files('cocoa.m')) + +vnc_ss = ss.source_set() +vnc_ss.add(files( + 'vnc.c', + 'vnc-enc-zlib.c', + 'vnc-enc-hextile.c', + 'vnc-enc-tight.c', + 'vnc-palette.c', + 'vnc-enc-zrle.c', + 'vnc-auth-vencrypt.c', + 'vnc-ws.c', + 'vnc-jobs.c', +)) +vnc_ss.add(zlib, png, jpeg) +vnc_ss.add(when: sasl, if_true: files('vnc-auth-sasl.c')) +softmmu_ss.add_all(when: vnc, if_true: vnc_ss) +softmmu_ss.add(when: vnc, if_false: files('vnc-stubs.c')) +specific_ss.add(when: ['CONFIG_SOFTMMU'], if_true: opengl) + +ui_modules = {} + +if curses.found() + curses_ss = ss.source_set() + curses_ss.add(when: [curses, iconv], if_true: [files('curses.c'), pixman]) + ui_modules += {'curses' : curses_ss} +endif + +if config_host.has_key('CONFIG_OPENGL') + opengl_ss = ss.source_set() + opengl_ss.add(when: [opengl, pixman, 'CONFIG_OPENGL'], + if_true: files('shader.c', 'console-gl.c', 'egl-helpers.c', 'egl-context.c')) + ui_modules += {'opengl' : opengl_ss} +endif + +if config_host.has_key('CONFIG_OPENGL_DMABUF') + egl_headless_ss = ss.source_set() + egl_headless_ss.add(when: [opengl, pixman, 'CONFIG_OPENGL_DMABUF'], + if_true: files('egl-headless.c')) + ui_modules += {'egl-headless' : egl_headless_ss} +endif + +if config_host.has_key('CONFIG_GTK') + softmmu_ss.add(when: 'CONFIG_WIN32', if_true: files('win32-kbd-hook.c')) + + gtk_ss = ss.source_set() + gtk_ss.add(gtk, vte, pixman, files('gtk.c')) + gtk_ss.add(when: [x11, 'CONFIG_X11'], if_true: files('x_keymap.c')) + gtk_ss.add(when: [opengl, 'CONFIG_OPENGL'], if_true: files('gtk-egl.c')) + gtk_ss.add(when: [opengl, 'CONFIG_GTK_GL'], if_true: files('gtk-gl-area.c')) + ui_modules += {'gtk' : gtk_ss} +endif + +if sdl.found() + softmmu_ss.add(when: 'CONFIG_WIN32', if_true: files('win32-kbd-hook.c')) + + sdl_ss = ss.source_set() + sdl_ss.add(sdl, sdl_image, pixman, glib, files( + 'sdl2-2d.c', + 'sdl2-input.c', + 'sdl2.c', + )) + sdl_ss.add(when: [opengl, 'CONFIG_OPENGL'], if_true: files('sdl2-gl.c')) + sdl_ss.add(when: [x11, 'CONFIG_X11'], if_true: files('x_keymap.c')) + ui_modules += {'sdl' : sdl_ss} +endif + +if config_host.has_key('CONFIG_SPICE') + spice_core_ss = ss.source_set() + spice_core_ss.add(spice, pixman, files( + 'spice-core.c', + 'spice-input.c', + 'spice-display.c' + )) + ui_modules += {'spice-core' : spice_core_ss} +endif + +if config_host.has_key('CONFIG_SPICE') and config_host.has_key('CONFIG_GIO') + spice_ss = ss.source_set() + spice_ss.add(spice, gio, pixman, files('spice-app.c')) + ui_modules += {'spice-app': spice_ss} +endif + +keymap_gen = find_program('keycodemapdb/tools/keymap-gen') + +keymaps = [ + ['atset1', 'qcode'], + ['linux', 'qcode'], + ['qcode', 'atset1'], + ['qcode', 'atset2'], + ['qcode', 'atset3'], + ['qcode', 'linux'], + ['qcode', 'qnum'], + ['qcode', 'sun'], + ['qnum', 'qcode'], + ['usb', 'qcode'], + ['win32', 'qcode'], + ['x11', 'qcode'], + ['xorgevdev', 'qcode'], + ['xorgkbd', 'qcode'], + ['xorgxquartz', 'qcode'], + ['xorgxwin', 'qcode'], + ['osx', 'qcode'], +] + +if have_system or xkbcommon.found() + foreach e : keymaps + output = 'input-keymap-@0@-to-@1@.c.inc'.format(e[0], e[1]) + genh += custom_target(output, + output: output, + capture: true, + input: files('keycodemapdb/data/keymaps.csv'), + command: [python.full_path(), files('keycodemapdb/tools/keymap-gen'), + '--lang', 'glib2', + '--varname', 'qemu_input_map_@0@_to_@1@'.format(e[0], e[1]), + 'code-map', '@INPUT0@', e[0], e[1]]) + endforeach +endif + +subdir('shader') + +if have_system + subdir('icons') + + install_data('qemu.desktop', install_dir: qemu_desktopdir) +endif + +modules += {'ui': ui_modules} diff --git a/ui/sdl2.c b/ui/sdl2.c index b23a8f0a8ebf554ab744261b76d055e3e1287f06..189d26e2a9510e81ea04f0d98535ffa91f13e892 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "qemu/module.h" +#include "qemu/cutils.h" #include "ui/console.h" #include "ui/input.h" #include "ui/sdl2.h" @@ -83,6 +84,11 @@ void sdl2_window_create(struct sdl2_console *scon) if (scon->hidden) { flags |= SDL_WINDOW_HIDDEN; } +#ifdef CONFIG_OPENGL + if (scon->opengl) { + flags |= SDL_WINDOW_OPENGL; + } +#endif scon->real_window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, @@ -795,6 +801,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o) int i; SDL_SysWMinfo info; SDL_Surface *icon = NULL; + char *dir; assert(o->type == DISPLAY_TYPE_SDL); @@ -868,15 +875,18 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o) } #ifdef CONFIG_SDL_IMAGE - icon = IMG_Load(CONFIG_QEMU_ICONDIR "/hicolor/128x128/apps/qemu.png"); + dir = get_relocated_path(CONFIG_QEMU_ICONDIR "/hicolor/128x128/apps/qemu.png"); + icon = IMG_Load(dir); #else /* Load a 32x32x4 image. White pixels are transparent. */ - icon = SDL_LoadBMP(CONFIG_QEMU_ICONDIR "/hicolor/32x32/apps/qemu.bmp"); + dir = get_relocated_path(CONFIG_QEMU_ICONDIR "/hicolor/32x32/apps/qemu.bmp"); + icon = SDL_LoadBMP(dir); if (icon) { uint32_t colorkey = SDL_MapRGB(icon->format, 255, 255, 255); SDL_SetColorKey(icon, SDL_TRUE, colorkey); } #endif + g_free(dir); if (icon) { SDL_SetWindowIcon(sdl2_console[0].real_window, icon); } diff --git a/ui/shader.c b/ui/shader.c index d78829f43bcc41ef8f5f07a335a59c6b46c4242a..e8b8d321b7c7a0563ed9dacfd5caab24ef4c3d25 100644 --- a/ui/shader.c +++ b/ui/shader.c @@ -27,9 +27,9 @@ #include "qemu/osdep.h" #include "ui/shader.h" -#include "shader/texture-blit-vert.h" -#include "shader/texture-blit-flip-vert.h" -#include "shader/texture-blit-frag.h" +#include "ui/shader/texture-blit-vert.h" +#include "ui/shader/texture-blit-flip-vert.h" +#include "ui/shader/texture-blit-frag.h" struct QemuGLShader { GLint texture_blit_prog; diff --git a/ui/shader/meson.build b/ui/shader/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..592bf596b9a508abb51554e0d2a57ccc882f8277 --- /dev/null +++ b/ui/shader/meson.build @@ -0,0 +1,14 @@ +shaders = [ + ['texture-blit', 'frag'], + ['texture-blit', 'vert'], + ['texture-blit-flip', 'vert'], +] + +foreach e : shaders + output = '@0@-@1@.h'.format(e[0], e[1]) + genh += custom_target(output, + output: output, + capture: true, + input: files('@0@.@1@'.format(e[0], e[1])), + command: [shaderinclude, '@INPUT0@']) +endforeach diff --git a/ui/spice-app.c b/ui/spice-app.c index 40fb2ef57399ab7921158620cdc66958a87b86aa..026124ef56a0ef26fbe3cf0a1aba5e4f3450d61d 100644 --- a/ui/spice-app.c +++ b/ui/spice-app.c @@ -35,17 +35,24 @@ #include "io/channel-command.h" #include "chardev/spice.h" #include "sysemu/sysemu.h" +#include "qom/object.h" static const char *tmp_dir; static char *app_dir; static char *sock_path; -typedef struct VCChardev { +struct VCChardev { SpiceChardev parent; -} VCChardev; +}; + +struct VCChardevClass { + ChardevClass parent; + void (*parent_open)(Chardev *chr, ChardevBackend *backend, + bool *be_opened, Error **errp); +}; #define TYPE_CHARDEV_VC "chardev-vc" -#define VC_CHARDEV(obj) OBJECT_CHECK(VCChardev, (obj), TYPE_CHARDEV_VC) +OBJECT_DECLARE_TYPE(VCChardev, VCChardevClass, CHARDEV_VC) static ChardevBackend * chr_spice_backend_new(void) @@ -63,6 +70,7 @@ static void vc_chr_open(Chardev *chr, bool *be_opened, Error **errp) { + VCChardevClass *vc = CHARDEV_VC_GET_CLASS(chr); ChardevBackend *be; const char *fqdn = NULL; @@ -77,7 +85,7 @@ static void vc_chr_open(Chardev *chr, be = chr_spice_backend_new(); be->u.spiceport.data->fqdn = fqdn ? g_strdup(fqdn) : g_strdup_printf("org.qemu.console.%s", chr->label); - qemu_chr_open_spice_port(chr, be, be_opened, errp); + vc->parent_open(chr, be, be_opened, errp); qapi_free_ChardevBackend(be); } @@ -88,8 +96,11 @@ static void vc_chr_set_echo(Chardev *chr, bool echo) static void char_vc_class_init(ObjectClass *oc, void *data) { + VCChardevClass *vc = CHARDEV_VC_CLASS(oc); ChardevClass *cc = CHARDEV_CLASS(oc); + vc->parent_open = cc->open; + cc->parse = qemu_chr_parse_vc; cc->open = vc_chr_open; cc->chr_set_echo = vc_chr_set_echo; @@ -100,6 +111,7 @@ static const TypeInfo char_vc_type_info = { .parent = TYPE_CHARDEV_SPICEPORT, .instance_size = sizeof(VCChardev), .class_init = char_vc_class_init, + .class_size = sizeof(VCChardevClass), }; static void spice_app_atexit(void) @@ -117,7 +129,6 @@ static void spice_app_atexit(void) static void spice_app_display_early_init(DisplayOptions *opts) { QemuOpts *qopts; - ChardevBackend *be = chr_spice_backend_new(); GError *err = NULL; if (opts->has_full_screen) { @@ -162,6 +173,15 @@ static void spice_app_display_early_init(DisplayOptions *opts) qemu_opt_set(qopts, "gl", opts->has_gl ? "on" : "off", &error_abort); display_opengl = opts->has_gl; #endif +} + +static void spice_app_display_init(DisplayState *ds, DisplayOptions *opts) +{ + ChardevBackend *be = chr_spice_backend_new(); + QemuOpts *qopts; + GError *err = NULL; + gchar *uri; + be->u.spiceport.data->fqdn = g_strdup("org.qemu.monitor.qmp.0"); qemu_chardev_new("org.qemu.monitor.qmp", TYPE_CHARDEV_SPICEPORT, be, NULL, &error_abort); @@ -171,13 +191,6 @@ static void spice_app_display_early_init(DisplayOptions *opts) qemu_opt_set(qopts, "mode", "control", &error_abort); qapi_free_ChardevBackend(be); -} - -static void spice_app_display_init(DisplayState *ds, DisplayOptions *opts) -{ - GError *err = NULL; - gchar *uri; - uri = g_strjoin("", "spice+unix://", app_dir, "/", "spice.sock", NULL); info_report("Launching display with URI: %s", uri); g_app_info_launch_default_for_uri(uri, NULL, &err); diff --git a/ui/spice-core.c b/ui/spice-core.c index ecc2ec2c55c2ff61cc7d06a5e247cfcf71c0f9bc..eea52f538999fc14afd90dba452ded490173a174 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -48,7 +48,6 @@ static time_t auth_expires = TIME_MAX; static int spice_migration_completed; static int spice_display_is_running; static int spice_have_target_host; -int using_spice = 0; static QemuThread me; @@ -503,7 +502,7 @@ static QemuOptsList qemu_spice_opts = { }, }; -SpiceInfo *qmp_query_spice(Error **errp) +static SpiceInfo *qmp_query_spice_real(Error **errp) { QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head); int port, tls_port; @@ -634,7 +633,7 @@ static void vm_change_state_handler(void *opaque, int running, } } -void qemu_spice_init(void) +static void qemu_spice_init(void) { QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head); const char *password, *str, *x509_dir, *addr, @@ -728,7 +727,7 @@ void qemu_spice_init(void) tls_ciphers); } if (password) { - qemu_spice_set_passwd(password, false, false); + qemu_spice.set_passwd(password, false, false); } if (qemu_opt_get_bool(opts, "sasl", 0)) { if (spice_server_set_sasl(spice_server, 1) == -1) { @@ -801,10 +800,9 @@ void qemu_spice_init(void) migration_state.notify = migration_state_notifier; add_migration_state_change_notifier(&migration_state); spice_migrate.base.sif = &migrate_interface.base; - qemu_spice_add_interface(&spice_migrate.base); + qemu_spice.add_interface(&spice_migrate.base); qemu_spice_input_init(); - qemu_spice_audio_init(); qemu_add_vm_change_state_handler(vm_change_state_handler, NULL); qemu_spice_display_stop(); @@ -813,8 +811,6 @@ void qemu_spice_init(void) g_free(x509_cert_file); g_free(x509_cacert_file); - qemu_spice_register_ports(); - #ifdef HAVE_SPICE_GL if (qemu_opt_get_bool(opts, "gl", 0)) { if ((port != 0) || (tls_port != 0)) { @@ -833,7 +829,7 @@ void qemu_spice_init(void) #endif } -int qemu_spice_add_interface(SpiceBaseInstance *sin) +static int qemu_spice_add_interface(SpiceBaseInstance *sin) { if (!spice_server) { if (QTAILQ_FIRST(&qemu_spice_opts.head) != NULL) { @@ -945,8 +941,8 @@ static int qemu_spice_set_ticket(bool fail_if_conn, bool disconnect_if_conn) fail_if_conn, disconnect_if_conn); } -int qemu_spice_set_passwd(const char *passwd, - bool fail_if_conn, bool disconnect_if_conn) +static int qemu_spice_set_passwd(const char *passwd, + bool fail_if_conn, bool disconnect_if_conn) { if (strcmp(auth, "spice") != 0) { return -1; @@ -957,13 +953,13 @@ int qemu_spice_set_passwd(const char *passwd, return qemu_spice_set_ticket(fail_if_conn, disconnect_if_conn); } -int qemu_spice_set_pw_expire(time_t expires) +static int qemu_spice_set_pw_expire(time_t expires) { auth_expires = expires; return qemu_spice_set_ticket(false, false); } -int qemu_spice_display_add_client(int csock, int skipauth, int tls) +static int qemu_spice_display_add_client(int csock, int skipauth, int tls) { if (tls) { return spice_server_add_ssl_client(spice_server, csock, skipauth); @@ -997,8 +993,20 @@ int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd) return spice_display_is_running; } +static struct QemuSpiceOps real_spice_ops = { + .init = qemu_spice_init, + .display_init = qemu_spice_display_init, + .migrate_info = qemu_spice_migrate_info, + .set_passwd = qemu_spice_set_passwd, + .set_pw_expire = qemu_spice_set_pw_expire, + .display_add_client = qemu_spice_display_add_client, + .add_interface = qemu_spice_add_interface, + .qmp_query = qmp_query_spice_real, +}; + static void spice_register_config(void) { + qemu_spice = real_spice_ops; qemu_add_opts(&qemu_spice_opts); } opts_init(spice_register_config); diff --git a/ui/spice-display.c b/ui/spice-display.c index 19632fdf6c16a2c0cecdd59b18e2feb6a76f405b..0178d5766d2cd91af837eefb8f2c8ceecfa61765 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -672,30 +672,19 @@ static int interface_client_monitors_config(QXLInstance *sin, return 1; } - memset(&info, 0, sizeof(info)); - - if (mc->num_of_monitors == 1) { - /* - * New spice-server version which filters the list of monitors - * to only include those that belong to our display channel. - * - * single-head configuration (where filtering doesn't matter) - * takes this code path too. - */ - info.width = mc->monitors[0].width; - info.height = mc->monitors[0].height; - } else { - /* - * Old spice-server which gives us all monitors, so we have to - * figure ourself which entry we need. Array index is the - * channel_id, which is the qemu console index, see - * qemu_spice_add_display_interface(). - */ - head = qemu_console_get_index(ssd->dcl.con); - if (mc->num_of_monitors > head) { - info.width = mc->monitors[head].width; - info.height = mc->monitors[head].height; + info = *dpy_get_ui_info(ssd->dcl.con); + + head = qemu_console_get_index(ssd->dcl.con); + if (mc->num_of_monitors > head) { + info.width = mc->monitors[head].width; + info.height = mc->monitors[head].height; +#if SPICE_SERVER_VERSION >= 0x000e04 /* release 0.14.4 */ + if (mc->flags & VD_AGENT_CONFIG_MONITORS_FLAG_PHYSICAL_SIZE) { + VDAgentMonitorMM *mm = (void *)&mc->monitors[mc->num_of_monitors]; + info.width_mm = mm[head].width; + info.height_mm = mm[head].height; } +#endif } trace_qemu_spice_ui_info(ssd->qxl.id, info.width, info.height); diff --git a/ui/spice-input.c b/ui/spice-input.c index cd4bb0043fd9d51e6dc134a7f2858938e39c6edd..bbd502564edfe03657faca10b2cf8627c925401f 100644 --- a/ui/spice-input.c +++ b/ui/spice-input.c @@ -36,7 +36,6 @@ typedef struct QemuSpiceKbd { static void kbd_push_key(SpiceKbdInstance *sin, uint8_t frag); static uint8_t kbd_get_leds(SpiceKbdInstance *sin); -static void kbd_leds(void *opaque, int l); static const SpiceKbdInterface kbd_interface = { .base.type = SPICE_INTERFACE_KEYBOARD, @@ -123,6 +122,8 @@ static void spice_update_buttons(QemuSpicePointer *pointer, [INPUT_BUTTON_RIGHT] = 0x02, [INPUT_BUTTON_WHEEL_UP] = 0x10, [INPUT_BUTTON_WHEEL_DOWN] = 0x20, + [INPUT_BUTTON_SIDE] = 0x40, + [INPUT_BUTTON_EXTRA] = 0x80, }; if (wheel < 0) { @@ -230,7 +231,7 @@ static void mouse_mode_notifier(Notifier *notifier, void *data) } if (is_absolute) { - qemu_spice_add_interface(&pointer->tablet.base); + qemu_spice.add_interface(&pointer->tablet.base); } else { spice_server_remove_interface(&pointer->tablet.base); } @@ -244,13 +245,13 @@ void qemu_spice_input_init(void) kbd = g_malloc0(sizeof(*kbd)); kbd->sin.base.sif = &kbd_interface.base; - qemu_spice_add_interface(&kbd->sin.base); + qemu_spice.add_interface(&kbd->sin.base); qemu_add_led_event_handler(kbd_leds, kbd); pointer = g_malloc0(sizeof(*pointer)); pointer->mouse.base.sif = &mouse_interface.base; pointer->tablet.base.sif = &tablet_interface.base; - qemu_spice_add_interface(&pointer->mouse.base); + qemu_spice.add_interface(&pointer->mouse.base); pointer->absolute = false; pointer->mouse_mode.notify = mouse_mode_notifier; diff --git a/ui/spice-module.c b/ui/spice-module.c new file mode 100644 index 0000000000000000000000000000000000000000..32223358722c768593e5ccf5cac9769252bf164d --- /dev/null +++ b/ui/spice-module.c @@ -0,0 +1,85 @@ +/* + * spice module support, also spice stubs. + * + * Copyright (C) 2010 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 or + * (at your option) version 3 of the License. + * + * 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "qapi/qapi-types-ui.h" +#include "qapi/qapi-commands-ui.h" +#include "ui/qemu-spice-module.h" + +int using_spice; + +static void qemu_spice_init_stub(void) +{ +} + +static void qemu_spice_display_init_stub(void) +{ + /* This must never be called if CONFIG_SPICE is disabled */ + error_report("spice support is disabled"); + abort(); +} + +static int qemu_spice_migrate_info_stub(const char *h, int p, int t, + const char *s) +{ + return -1; +} + +static int qemu_spice_set_passwd_stub(const char *passwd, + bool fail_if_connected, + bool disconnect_if_connected) +{ + return -1; +} + +static int qemu_spice_set_pw_expire_stub(time_t expires) +{ + return -1; +} + +static int qemu_spice_display_add_client_stub(int csock, int skipauth, + int tls) +{ + return -1; +} + +struct QemuSpiceOps qemu_spice = { + .init = qemu_spice_init_stub, + .display_init = qemu_spice_display_init_stub, + .migrate_info = qemu_spice_migrate_info_stub, + .set_passwd = qemu_spice_set_passwd_stub, + .set_pw_expire = qemu_spice_set_pw_expire_stub, + .display_add_client = qemu_spice_display_add_client_stub, +}; + +#ifdef CONFIG_SPICE + +SpiceInfo *qmp_query_spice(Error **errp) +{ + if (!qemu_spice.qmp_query) { + SpiceInfo *info = g_new0(SpiceInfo, 1); + info->enabled = false; + return info; + } + return qemu_spice.qmp_query(errp); +} + +#endif diff --git a/ui/trace-events b/ui/trace-events index 5367fd3f166811456de862a85343710acb7d6f00..0ffcdb4408a6fd90ad6a9bc6db7168e0d616078b 100644 --- a/ui/trace-events +++ b/ui/trace-events @@ -15,11 +15,11 @@ displaysurface_create_pixman(void *display_surface) "surface=%p" displaysurface_free(void *display_surface) "surface=%p" displaychangelistener_register(void *dcl, const char *name) "%p [ %s ]" displaychangelistener_unregister(void *dcl, const char *name) "%p [ %s ]" -ppm_save(int fd, void *display_surface) "fd=%d surface=%p" +ppm_save(int fd, void *image) "fd=%d image=%p" -# gtk.c -# gtk-gl-area.c # gtk-egl.c +# gtk-gl-area.c +# gtk.c gd_switch(const char *tab, int width, int height) "tab=%s, width=%d, height=%d" gd_update(const char *tab, int x, int y, int w, int h) "tab=%s, x=%d, y=%d, w=%d, h=%d" gd_key_event(const char *tab, int gdk_keycode, int qkeycode, const char *action) "tab=%s, translated GDK keycode %d to QKeyCode %d (%s)" @@ -28,8 +28,8 @@ gd_ungrab(const char *tab, const char *device) "tab=%s, dev=%s" gd_keymap_windowing(const char *name) "backend=%s" # vnc-auth-sasl.c -# vnc-ws.c # vnc-auth-vencrypt.c +# vnc-ws.c # vnc.c vnc_key_guest_leds(bool caps, bool num, bool scroll) "caps %d, num %d, scroll %d" vnc_key_map_init(const char *layout) "%s" diff --git a/ui/trace.h b/ui/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..a89d769623b9b360d91b0cb09a794262ccff1983 --- /dev/null +++ b/ui/trace.h @@ -0,0 +1 @@ +#include "trace/trace-ui.h" diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c index 7b2b09f2427639ebb3e1a327fdaeb327860d4d0a..f67111a3662adb3f1b92a2a5d82df8fe5bbb0fd2 100644 --- a/ui/vnc-auth-sasl.c +++ b/ui/vnc-auth-sasl.c @@ -111,7 +111,8 @@ size_t vnc_client_write_sasl(VncState *vs) g_source_remove(vs->ioc_tag); } vs->ioc_tag = qio_channel_add_watch( - vs->ioc, G_IO_IN, vnc_client_io, vs, NULL); + vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR, + vnc_client_io, vs, NULL); } return ret; @@ -522,6 +523,7 @@ vnc_socket_ip_addr_string(QIOChannelSocket *ioc, if (addr->type != SOCKET_ADDRESS_TYPE_INET) { error_setg(errp, "Not an inet socket type"); + qapi_free_SocketAddress(addr); return NULL; } ret = g_strdup_printf("%s;%s", addr->u.inet.host, addr->u.inet.port); diff --git a/ui/vnc-auth-vencrypt.c b/ui/vnc-auth-vencrypt.c index f072e16aceb1c58de48e70ac3cfd69013653da71..d9c212ff3286c7b45977f3ddf7e0422f78c9867d 100644 --- a/ui/vnc-auth-vencrypt.c +++ b/ui/vnc-auth-vencrypt.c @@ -79,7 +79,8 @@ static void vnc_tls_handshake_done(QIOTask *task, g_source_remove(vs->ioc_tag); } vs->ioc_tag = qio_channel_add_watch( - vs->ioc, G_IO_IN | G_IO_OUT, vnc_client_io, vs, NULL); + vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_OUT, + vnc_client_io, vs, NULL); start_auth_vencrypt_subauth(vs); } } diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c index 1e0851826a842f165f8b88fd16f7f7e8c76ba0cc..cebd35841a9275ea9d3781081cf63679987b70c9 100644 --- a/ui/vnc-enc-tight.c +++ b/ui/vnc-enc-tight.c @@ -1125,7 +1125,6 @@ static int send_palette_rect(VncState *vs, int x, int y, } default: return -1; /* No palette for 8bits colors */ - break; } bytes = w * h; vs->tight->tight.offset = bytes; diff --git a/ui/vnc-enc-zrle.c b/ui/vnc-enc-zrle.c index b4f71e32cfe8ca3dd645103f999db618469d5f6d..bd33b890639f47367e22191e4b4caf89ac7a2883 100644 --- a/ui/vnc-enc-zrle.c +++ b/ui/vnc-enc-zrle.c @@ -199,56 +199,56 @@ static void zrle_write_u8(VncState *vs, uint8_t value) #define ZRLE_BPP 8 #define ZYWRLE_ENDIAN ENDIAN_NO -#include "vnc-enc-zrle.inc.c" +#include "vnc-enc-zrle.c.inc" #undef ZRLE_BPP #define ZRLE_BPP 15 #undef ZYWRLE_ENDIAN #define ZYWRLE_ENDIAN ENDIAN_LITTLE -#include "vnc-enc-zrle.inc.c" +#include "vnc-enc-zrle.c.inc" #undef ZYWRLE_ENDIAN #define ZYWRLE_ENDIAN ENDIAN_BIG -#include "vnc-enc-zrle.inc.c" +#include "vnc-enc-zrle.c.inc" #undef ZRLE_BPP #define ZRLE_BPP 16 #undef ZYWRLE_ENDIAN #define ZYWRLE_ENDIAN ENDIAN_LITTLE -#include "vnc-enc-zrle.inc.c" +#include "vnc-enc-zrle.c.inc" #undef ZYWRLE_ENDIAN #define ZYWRLE_ENDIAN ENDIAN_BIG -#include "vnc-enc-zrle.inc.c" +#include "vnc-enc-zrle.c.inc" #undef ZRLE_BPP #define ZRLE_BPP 32 #undef ZYWRLE_ENDIAN #define ZYWRLE_ENDIAN ENDIAN_LITTLE -#include "vnc-enc-zrle.inc.c" +#include "vnc-enc-zrle.c.inc" #undef ZYWRLE_ENDIAN #define ZYWRLE_ENDIAN ENDIAN_BIG -#include "vnc-enc-zrle.inc.c" +#include "vnc-enc-zrle.c.inc" #define ZRLE_COMPACT_PIXEL 24a #undef ZYWRLE_ENDIAN #define ZYWRLE_ENDIAN ENDIAN_LITTLE -#include "vnc-enc-zrle.inc.c" +#include "vnc-enc-zrle.c.inc" #undef ZYWRLE_ENDIAN #define ZYWRLE_ENDIAN ENDIAN_BIG -#include "vnc-enc-zrle.inc.c" +#include "vnc-enc-zrle.c.inc" #undef ZRLE_COMPACT_PIXEL #define ZRLE_COMPACT_PIXEL 24b #undef ZYWRLE_ENDIAN #define ZYWRLE_ENDIAN ENDIAN_LITTLE -#include "vnc-enc-zrle.inc.c" +#include "vnc-enc-zrle.c.inc" #undef ZYWRLE_ENDIAN #define ZYWRLE_ENDIAN ENDIAN_BIG -#include "vnc-enc-zrle.inc.c" +#include "vnc-enc-zrle.c.inc" #undef ZRLE_COMPACT_PIXEL #undef ZRLE_BPP diff --git a/ui/vnc-enc-zrle.inc.c b/ui/vnc-enc-zrle.c.inc similarity index 100% rename from ui/vnc-enc-zrle.inc.c rename to ui/vnc-enc-zrle.c.inc diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c index 929391f85d693fd7da3af2514b75db4e8c798f87..dbbfbefe56196b602b4c17710538d056fb672f7e 100644 --- a/ui/vnc-jobs.c +++ b/ui/vnc-jobs.c @@ -151,7 +151,8 @@ void vnc_jobs_consume_buffer(VncState *vs) } if (vs->disconnecting == FALSE) { vs->ioc_tag = qio_channel_add_watch( - vs->ioc, G_IO_IN | G_IO_OUT, vnc_client_io, vs, NULL); + vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_OUT, + vnc_client_io, vs, NULL); } } buffer_move(&vs->output, &vs->jobs_buffer); diff --git a/ui/vnc-stubs.c b/ui/vnc-stubs.c index 06c4ac6296ebcb327660f465eeaa8c4629a99c34..c6b737dcec67529e27e78b4c46f787bd32258e45 100644 --- a/ui/vnc-stubs.c +++ b/ui/vnc-stubs.c @@ -12,6 +12,9 @@ int vnc_display_pw_expire(const char *id, time_t expires) }; QemuOpts *vnc_parse(const char *str, Error **errp) { + if (strcmp(str, "none") == 0) { + return NULL; + } error_setg(errp, "VNC support is disabled"); return NULL; } diff --git a/ui/vnc-ws.c b/ui/vnc-ws.c index 95c9703c72401e7f84a742510bb37b173004f3a3..6d79f3e5a5d84e81d8645296211c9547571a23e3 100644 --- a/ui/vnc-ws.c +++ b/ui/vnc-ws.c @@ -41,13 +41,14 @@ static void vncws_tls_handshake_done(QIOTask *task, g_source_remove(vs->ioc_tag); } vs->ioc_tag = qio_channel_add_watch( - QIO_CHANNEL(vs->ioc), G_IO_IN, vncws_handshake_io, vs, NULL); + QIO_CHANNEL(vs->ioc), G_IO_IN | G_IO_HUP | G_IO_ERR, + vncws_handshake_io, vs, NULL); } } gboolean vncws_tls_handshake_io(QIOChannel *ioc G_GNUC_UNUSED, - GIOCondition condition G_GNUC_UNUSED, + GIOCondition condition, void *opaque) { VncState *vs = opaque; @@ -59,6 +60,11 @@ gboolean vncws_tls_handshake_io(QIOChannel *ioc G_GNUC_UNUSED, vs->ioc_tag = 0; } + if (condition & (G_IO_HUP | G_IO_ERR)) { + vnc_client_error(vs); + return TRUE; + } + tls = qio_channel_tls_new_server( vs->ioc, vs->vd->tlscreds, @@ -105,13 +111,14 @@ static void vncws_handshake_done(QIOTask *task, g_source_remove(vs->ioc_tag); } vs->ioc_tag = qio_channel_add_watch( - vs->ioc, G_IO_IN, vnc_client_io, vs, NULL); + vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR, + vnc_client_io, vs, NULL); } } gboolean vncws_handshake_io(QIOChannel *ioc G_GNUC_UNUSED, - GIOCondition condition G_GNUC_UNUSED, + GIOCondition condition, void *opaque) { VncState *vs = opaque; @@ -122,6 +129,11 @@ gboolean vncws_handshake_io(QIOChannel *ioc G_GNUC_UNUSED, vs->ioc_tag = 0; } + if (condition & (G_IO_HUP | G_IO_ERR)) { + vnc_client_error(vs); + return TRUE; + } + wioc = qio_channel_websock_new_server(vs->ioc); qio_channel_set_name(QIO_CHANNEL(wioc), "vnc-ws-server-websock"); diff --git a/ui/vnc.c b/ui/vnc.c index 12a12714e129c64e252eb2a55153a11b95e1b5c4..49235056f7a893f5f7c86500afbcccddd55fe117 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -458,9 +458,8 @@ static VncServerInfo2List *qmp_query_server_entry(QIOChannelSocket *ioc, Error *err = NULL; SocketAddress *addr; - addr = qio_channel_socket_get_local_address(ioc, &err); + addr = qio_channel_socket_get_local_address(ioc, NULL); if (!addr) { - error_free(err); return prev; } @@ -569,7 +568,7 @@ VncInfo2List *qmp_query_vnc_servers(Error **errp) &info->vencrypt, &info->has_vencrypt); if (vd->dcl.con) { dev = DEVICE(object_property_get_link(OBJECT(vd->dcl.con), - "device", NULL)); + "device", &error_abort)); info->has_display = true; info->display = g_strdup(dev->id); } @@ -1399,7 +1398,8 @@ static size_t vnc_client_write_plain(VncState *vs) g_source_remove(vs->ioc_tag); } vs->ioc_tag = qio_channel_add_watch( - vs->ioc, G_IO_IN, vnc_client_io, vs, NULL); + vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR, + vnc_client_io, vs, NULL); } return ret; @@ -1436,7 +1436,8 @@ static void vnc_client_write(VncState *vs) g_source_remove(vs->ioc_tag); } vs->ioc_tag = qio_channel_add_watch( - vs->ioc, G_IO_IN, vnc_client_io, vs, NULL); + vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR, + vnc_client_io, vs, NULL); } vnc_unlock_output(vs); } @@ -1552,6 +1553,12 @@ gboolean vnc_client_io(QIOChannel *ioc G_GNUC_UNUSED, VncState *vs = opaque; assert(vs->magic == VNC_MAGIC); + + if (condition & (G_IO_HUP | G_IO_ERR)) { + vnc_disconnect_start(vs); + return TRUE; + } + if (condition & G_IO_IN) { if (vnc_client_read(vs) < 0) { /* vs is free()ed here */ @@ -1613,7 +1620,8 @@ void vnc_write(VncState *vs, const void *data, size_t len) g_source_remove(vs->ioc_tag); } vs->ioc_tag = qio_channel_add_watch( - vs->ioc, G_IO_IN | G_IO_OUT, vnc_client_io, vs, NULL); + vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_OUT, + vnc_client_io, vs, NULL); } buffer_append(&vs->output, data, len); @@ -3078,14 +3086,17 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc, vs->websocket = 1; if (vd->tlscreds) { vs->ioc_tag = qio_channel_add_watch( - vs->ioc, G_IO_IN, vncws_tls_handshake_io, vs, NULL); + vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR, + vncws_tls_handshake_io, vs, NULL); } else { vs->ioc_tag = qio_channel_add_watch( - vs->ioc, G_IO_IN, vncws_handshake_io, vs, NULL); + vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR, + vncws_handshake_io, vs, NULL); } } else { vs->ioc_tag = qio_channel_add_watch( - vs->ioc, G_IO_IN, vnc_client_io, vs, NULL); + vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR, + vnc_client_io, vs, NULL); } vnc_client_cache_addr(vs); @@ -3275,13 +3286,12 @@ int vnc_display_pw_expire(const char *id, time_t expires) static void vnc_display_print_local_addr(VncDisplay *vd) { SocketAddress *addr; - Error *err = NULL; if (!vd->listener || !vd->listener->nsioc) { return; } - addr = qio_channel_socket_get_local_address(vd->listener->sioc[0], &err); + addr = qio_channel_socket_get_local_address(vd->listener->sioc[0], NULL); if (!addr) { return; } diff --git a/ui/x_keymap.c b/ui/x_keymap.c index 2bc01432e5ca3807c01e2c3e53dd80b005d3ef6a..555086fb6bd572aeb6dda17bdd159c4c707a5d30 100644 --- a/ui/x_keymap.c +++ b/ui/x_keymap.c @@ -5,7 +5,7 @@ * 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 Lesser General Public License version 2 as + * it under the terms of the GNU Lesser General Public License version 2.1 as * published by the Free Software Foundation. */ diff --git a/util/Makefile.objs b/util/Makefile.objs deleted file mode 100644 index fe339c2636ba090153d1b5908d6d23bdadf54838..0000000000000000000000000000000000000000 --- a/util/Makefile.objs +++ /dev/null @@ -1,66 +0,0 @@ -util-obj-y = osdep.o cutils.o unicode.o qemu-timer-common.o -util-obj-y += bufferiszero.o -util-obj-y += lockcnt.o -util-obj-y += aiocb.o async.o aio-wait.o thread-pool.o qemu-timer.o -util-obj-y += main-loop.o -util-obj-$(call lnot,$(CONFIG_ATOMIC64)) += atomic64.o -util-obj-$(CONFIG_POSIX) += aio-posix.o -util-obj-$(CONFIG_POSIX) += fdmon-poll.o -util-obj-$(CONFIG_EPOLL_CREATE1) += fdmon-epoll.o -util-obj-$(CONFIG_LINUX_IO_URING) += fdmon-io_uring.o -util-obj-$(CONFIG_POSIX) += compatfd.o -util-obj-$(CONFIG_POSIX) += event_notifier-posix.o -util-obj-$(CONFIG_POSIX) += mmap-alloc.o -util-obj-$(CONFIG_POSIX) += oslib-posix.o -util-obj-$(CONFIG_POSIX) += qemu-openpty.o -util-obj-$(CONFIG_POSIX) += qemu-thread-posix.o -util-obj-$(CONFIG_POSIX) += memfd.o -util-obj-$(CONFIG_WIN32) += aio-win32.o -util-obj-$(CONFIG_WIN32) += event_notifier-win32.o -util-obj-$(CONFIG_WIN32) += oslib-win32.o -util-obj-$(CONFIG_WIN32) += qemu-thread-win32.o -util-obj-y += envlist.o path.o module.o -util-obj-y += host-utils.o -util-obj-y += bitmap.o bitops.o hbitmap.o -util-obj-y += fifo8.o -util-obj-y += nvdimm-utils.o -util-obj-y += cacheinfo.o -util-obj-y += error.o qemu-error.o -util-obj-y += qemu-print.o -util-obj-y += id.o -util-obj-y += iov.o qemu-config.o qemu-sockets.o uri.o notify.o -util-obj-y += qemu-option.o qemu-progress.o -util-obj-y += keyval.o -util-obj-y += hexdump.o -util-obj-y += crc32c.o -util-obj-y += uuid.o -util-obj-y += throttle.o -util-obj-y += getauxval.o -util-obj-y += readline.o -util-obj-y += rcu.o -util-obj-$(CONFIG_MEMBARRIER) += sys_membarrier.o -util-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o -util-obj-y += qemu-coroutine-sleep.o -util-obj-y += qemu-co-shared-resource.o -util-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o -util-obj-y += buffer.o -util-obj-y += timed-average.o -util-obj-y += base64.o -util-obj-y += log.o -util-obj-y += pagesize.o -util-obj-y += qdist.o -util-obj-y += qht.o -util-obj-y += qsp.o -util-obj-y += range.o -util-obj-y += stats64.o -util-obj-y += systemd.o -util-obj-y += iova-tree.o -util-obj-$(CONFIG_INOTIFY1) += filemonitor-inotify.o -util-obj-$(call lnot,$(CONFIG_INOTIFY1)) += filemonitor-stub.o -util-obj-$(CONFIG_LINUX) += vfio-helpers.o -util-obj-$(CONFIG_POSIX) += drm.o -util-obj-y += guest-random.o -util-obj-$(CONFIG_GIO) += dbus.o -dbus.o-cflags = $(GIO_CFLAGS) -dbus.o-libs = $(GIO_LIBS) -util-obj-$(CONFIG_USER_ONLY) += selfmap.o diff --git a/util/aio-posix.c b/util/aio-posix.c index 1b2a3af65b79d4f2f6804961407a7a44ebdd91bb..30f5354b1e974259e92e10133ae0a377371d34dd 100644 --- a/util/aio-posix.c +++ b/util/aio-posix.c @@ -15,6 +15,7 @@ #include "qemu/osdep.h" #include "block/block.h" +#include "qemu/main-loop.h" #include "qemu/rcu.h" #include "qemu/rcu_queue.h" #include "qemu/sockets.h" @@ -27,7 +28,7 @@ bool aio_poll_disabled(AioContext *ctx) { - return atomic_read(&ctx->poll_disable_cnt); + return qatomic_read(&ctx->poll_disable_cnt); } void aio_add_ready_handler(AioHandlerList *ready_list, @@ -148,8 +149,8 @@ void aio_set_fd_handler(AioContext *ctx, * Changing handlers is a rare event, and a little wasted polling until * the aio_notify below is not an issue. */ - atomic_set(&ctx->poll_disable_cnt, - atomic_read(&ctx->poll_disable_cnt) + poll_disable_change); + qatomic_set(&ctx->poll_disable_cnt, + qatomic_read(&ctx->poll_disable_cnt) + poll_disable_change); ctx->fdmon_ops->update(ctx, node, new_node); if (node) { @@ -464,9 +465,6 @@ static bool remove_idle_poll_handlers(AioContext *ctx, int64_t now) * * Polls for a given time. * - * Note that ctx->notify_me must be non-zero so this function can detect - * aio_notify(). - * * Note that the caller must have incremented ctx->list_lock. * * Returns: true if progress was made, false otherwise @@ -476,7 +474,6 @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout) bool progress; int64_t start_time, elapsed_time; - assert(ctx->notify_me); assert(qemu_lockcnt_count(&ctx->list_lock) > 0); trace_run_poll_handlers_begin(ctx, max_ns, *timeout); @@ -520,8 +517,6 @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout) * @timeout: timeout for blocking wait, computed by the caller and updated if * polling succeeds. * - * ctx->notify_me must be non-zero so this function can detect aio_notify(). - * * Note that the caller must have incremented ctx->list_lock. * * Returns: true if progress was made, false otherwise @@ -556,6 +551,7 @@ bool aio_poll(AioContext *ctx, bool blocking) AioHandlerList ready_list = QLIST_HEAD_INITIALIZER(ready_list); int ret = 0; bool progress; + bool use_notify_me; int64_t timeout; int64_t start = 0; @@ -563,36 +559,47 @@ bool aio_poll(AioContext *ctx, bool blocking) * There cannot be two concurrent aio_poll calls for the same AioContext (or * an aio_poll concurrent with a GSource prepare/check/dispatch callback). * We rely on this below to avoid slow locked accesses to ctx->notify_me. + * + * aio_poll() may only be called in the AioContext's thread. iohandler_ctx + * is special in that it runs in the main thread, but that thread's context + * is qemu_aio_context. */ - assert(in_aio_context_home_thread(ctx)); + assert(in_aio_context_home_thread(ctx == iohandler_get_aio_context() ? + qemu_get_aio_context() : ctx)); + + qemu_lockcnt_inc(&ctx->list_lock); + + if (ctx->poll_max_ns) { + start = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); + } + + timeout = blocking ? aio_compute_timeout(ctx) : 0; + progress = try_poll_mode(ctx, &timeout); + assert(!(timeout && progress)); - /* aio_notify can avoid the expensive event_notifier_set if + /* + * aio_notify can avoid the expensive event_notifier_set if * everything (file descriptors, bottom halves, timers) will * be re-evaluated before the next blocking poll(). This is * already true when aio_poll is called with blocking == false; * if blocking == true, it is only true after poll() returns, * so disable the optimization now. */ - if (blocking) { - atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) + 2); + use_notify_me = timeout != 0; + if (use_notify_me) { + qatomic_set(&ctx->notify_me, qatomic_read(&ctx->notify_me) + 2); /* - * Write ctx->notify_me before computing the timeout - * (reading bottom half flags, etc.). Pairs with + * Write ctx->notify_me before reading ctx->notified. Pairs with * smp_mb in aio_notify(). */ smp_mb(); - } - - qemu_lockcnt_inc(&ctx->list_lock); - if (ctx->poll_max_ns) { - start = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); + /* Don't block if aio_notify() was called */ + if (qatomic_read(&ctx->notified)) { + timeout = 0; + } } - timeout = blocking ? aio_compute_timeout(ctx) : 0; - progress = try_poll_mode(ctx, &timeout); - assert(!(timeout && progress)); - /* If polling is allowed, non-blocking aio_poll does not need the * system call---a single round of run_poll_handlers_once suffices. */ @@ -600,12 +607,14 @@ bool aio_poll(AioContext *ctx, bool blocking) ret = ctx->fdmon_ops->wait(ctx, &ready_list, timeout); } - if (blocking) { + if (use_notify_me) { /* Finish the poll before clearing the flag. */ - atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) - 2); - aio_notify_accept(ctx); + qatomic_store_release(&ctx->notify_me, + qatomic_read(&ctx->notify_me) - 2); } + aio_notify_accept(ctx); + /* Adjust polling time */ if (ctx->poll_max_ns) { int64_t block_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - start; diff --git a/util/aio-wait.c b/util/aio-wait.c index b4877493f89c807318fbd0e0069c5be2fad14fba..bdb3d3af22ddbb0b77b52e12b4e9538acebba08e 100644 --- a/util/aio-wait.c +++ b/util/aio-wait.c @@ -36,7 +36,7 @@ static void dummy_bh_cb(void *opaque) void aio_wait_kick(void) { /* The barrier (or an atomic op) is in the caller. */ - if (atomic_read(&global_aio_wait.num_waiters)) { + if (qatomic_read(&global_aio_wait.num_waiters)) { aio_bh_schedule_oneshot(qemu_get_aio_context(), dummy_bh_cb, NULL); } } diff --git a/util/aio-win32.c b/util/aio-win32.c index 953c56ab48a2f4bcf2ece21dd070ef0bc44f1265..168717b51bd617aa0233a6025fc9ed1e4a4337c3 100644 --- a/util/aio-win32.c +++ b/util/aio-win32.c @@ -18,6 +18,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "block/block.h" +#include "qemu/main-loop.h" #include "qemu/queue.h" #include "qemu/sockets.h" #include "qapi/error.h" @@ -37,6 +38,16 @@ struct AioHandler { static void aio_remove_fd_handler(AioContext *ctx, AioHandler *node) { + /* + * If the GSource is in the process of being destroyed then + * g_source_remove_poll() causes an assertion failure. Skip + * removal in that case, because glib cleans up its state during + * destruction anyway. + */ + if (!g_source_is_destroyed(&ctx->source)) { + g_source_remove_poll(&ctx->source, &node->pfd); + } + /* If aio_poll is in progress, just mark the node as deleted */ if (qemu_lockcnt_count(&ctx->list_lock)) { node->deleted = 1; @@ -139,8 +150,6 @@ void aio_set_event_notifier(AioContext *ctx, /* Are we deleting the fd handler? */ if (!io_notify) { if (node) { - g_source_remove_poll(&ctx->source, &node->pfd); - aio_remove_fd_handler(ctx, node); } } else { @@ -325,8 +334,13 @@ bool aio_poll(AioContext *ctx, bool blocking) * There cannot be two concurrent aio_poll calls for the same AioContext (or * an aio_poll concurrent with a GSource prepare/check/dispatch callback). * We rely on this below to avoid slow locked accesses to ctx->notify_me. + * + * aio_poll() may only be called in the AioContext's thread. iohandler_ctx + * is special in that it runs in the main thread, but that thread's context + * is qemu_aio_context. */ - assert(in_aio_context_home_thread(ctx)); + assert(in_aio_context_home_thread(ctx == iohandler_get_aio_context() ? + qemu_get_aio_context() : ctx)); progress = false; /* aio_notify can avoid the expensive event_notifier_set if @@ -337,7 +351,7 @@ bool aio_poll(AioContext *ctx, bool blocking) * so disable the optimization now. */ if (blocking) { - atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) + 2); + qatomic_set(&ctx->notify_me, qatomic_read(&ctx->notify_me) + 2); /* * Write ctx->notify_me before computing the timeout * (reading bottom half flags, etc.). Pairs with @@ -376,7 +390,8 @@ bool aio_poll(AioContext *ctx, bool blocking) ret = WaitForMultipleObjects(count, events, FALSE, timeout); if (blocking) { assert(first); - atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) - 2); + qatomic_store_release(&ctx->notify_me, + qatomic_read(&ctx->notify_me) - 2); aio_notify_accept(ctx); } diff --git a/util/async.c b/util/async.c index 1319eee3bc20661c34a3a4eb0c2b21c47b66ba5e..674dbefb7c2494887b3a7a1648908cb7209f0b4c 100644 --- a/util/async.c +++ b/util/async.c @@ -70,13 +70,13 @@ static void aio_bh_enqueue(QEMUBH *bh, unsigned new_flags) unsigned old_flags; /* - * The memory barrier implicit in atomic_fetch_or makes sure that: + * The memory barrier implicit in qatomic_fetch_or makes sure that: * 1. idle & any writes needed by the callback are done before the * locations are read in the aio_bh_poll. * 2. ctx is loaded before the callback has a chance to execute and bh * could be freed. */ - old_flags = atomic_fetch_or(&bh->flags, BH_PENDING | new_flags); + old_flags = qatomic_fetch_or(&bh->flags, BH_PENDING | new_flags); if (!(old_flags & BH_PENDING)) { QSLIST_INSERT_HEAD_ATOMIC(&ctx->bh_list, bh, next); } @@ -96,13 +96,13 @@ static QEMUBH *aio_bh_dequeue(BHList *head, unsigned *flags) QSLIST_REMOVE_HEAD(head, next); /* - * The atomic_and is paired with aio_bh_enqueue(). The implicit memory + * The qatomic_and is paired with aio_bh_enqueue(). The implicit memory * barrier ensures that the callback sees all writes done by the scheduling * thread. It also ensures that the scheduling thread sees the cleared * flag before bh->cb has run, and thus will call aio_notify again if * necessary. */ - *flags = atomic_fetch_and(&bh->flags, + *flags = qatomic_fetch_and(&bh->flags, ~(BH_PENDING | BH_SCHEDULED | BH_IDLE)); return bh; } @@ -185,7 +185,7 @@ void qemu_bh_schedule(QEMUBH *bh) */ void qemu_bh_cancel(QEMUBH *bh) { - atomic_and(&bh->flags, ~BH_SCHEDULED); + qatomic_and(&bh->flags, ~BH_SCHEDULED); } /* This func is async.The bottom half will do the delete action at the finial @@ -249,7 +249,7 @@ aio_ctx_prepare(GSource *source, gint *timeout) { AioContext *ctx = (AioContext *) source; - atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) | 1); + qatomic_set(&ctx->notify_me, qatomic_read(&ctx->notify_me) | 1); /* * Write ctx->notify_me before computing the timeout @@ -276,7 +276,7 @@ aio_ctx_check(GSource *source) BHListSlice *s; /* Finish computing the timeout before clearing the flag. */ - atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) & ~1); + qatomic_store_release(&ctx->notify_me, qatomic_read(&ctx->notify_me) & ~1); aio_notify_accept(ctx); QSLIST_FOREACH_RCU(bh, &ctx->bh_list, next) { @@ -419,25 +419,32 @@ LuringState *aio_get_linux_io_uring(AioContext *ctx) void aio_notify(AioContext *ctx) { - /* Write e.g. bh->scheduled before reading ctx->notify_me. Pairs + /* + * Write e.g. bh->flags before writing ctx->notified. Pairs with smp_mb in + * aio_notify_accept. + */ + smp_wmb(); + qatomic_set(&ctx->notified, true); + + /* + * Write ctx->notified before reading ctx->notify_me. Pairs * with smp_mb in aio_ctx_prepare or aio_poll. */ smp_mb(); - if (atomic_read(&ctx->notify_me)) { + if (qatomic_read(&ctx->notify_me)) { event_notifier_set(&ctx->notifier); - atomic_mb_set(&ctx->notified, true); } } void aio_notify_accept(AioContext *ctx) { - if (atomic_xchg(&ctx->notified, false) -#ifdef WIN32 - || true -#endif - ) { - event_notifier_test_and_clear(&ctx->notifier); - } + qatomic_set(&ctx->notified, false); + + /* + * Write ctx->notified before reading e.g. bh->flags. Pairs with smp_wmb + * in aio_notify. + */ + smp_mb(); } static void aio_timerlist_notify(void *opaque, QEMUClockType type) @@ -445,17 +452,20 @@ static void aio_timerlist_notify(void *opaque, QEMUClockType type) aio_notify(opaque); } -static void event_notifier_dummy_cb(EventNotifier *e) +static void aio_context_notifier_cb(EventNotifier *e) { + AioContext *ctx = container_of(e, AioContext, notifier); + + event_notifier_test_and_clear(&ctx->notifier); } /* Returns true if aio_notify() was called (e.g. a BH was scheduled) */ -static bool event_notifier_poll(void *opaque) +static bool aio_context_notifier_poll(void *opaque) { EventNotifier *e = opaque; AioContext *ctx = container_of(e, AioContext, notifier); - return atomic_read(&ctx->notified); + return qatomic_read(&ctx->notified); } static void co_schedule_bh_cb(void *opaque) @@ -479,7 +489,7 @@ static void co_schedule_bh_cb(void *opaque) aio_context_acquire(ctx); /* Protected by write barrier in qemu_aio_coroutine_enter */ - atomic_set(&co->scheduled, NULL); + qatomic_set(&co->scheduled, NULL); qemu_aio_coroutine_enter(ctx, co); aio_context_release(ctx); } @@ -508,8 +518,8 @@ AioContext *aio_context_new(Error **errp) aio_set_event_notifier(ctx, &ctx->notifier, false, - event_notifier_dummy_cb, - event_notifier_poll); + aio_context_notifier_cb, + aio_context_notifier_poll); #ifdef CONFIG_LINUX_AIO ctx->linux_aio = NULL; #endif @@ -536,7 +546,7 @@ fail: void aio_co_schedule(AioContext *ctx, Coroutine *co) { trace_aio_co_schedule(ctx, co); - const char *scheduled = atomic_cmpxchg(&co->scheduled, NULL, + const char *scheduled = qatomic_cmpxchg(&co->scheduled, NULL, __func__); if (scheduled) { @@ -559,6 +569,36 @@ void aio_co_schedule(AioContext *ctx, Coroutine *co) aio_context_unref(ctx); } +typedef struct AioCoRescheduleSelf { + Coroutine *co; + AioContext *new_ctx; +} AioCoRescheduleSelf; + +static void aio_co_reschedule_self_bh(void *opaque) +{ + AioCoRescheduleSelf *data = opaque; + aio_co_schedule(data->new_ctx, data->co); +} + +void coroutine_fn aio_co_reschedule_self(AioContext *new_ctx) +{ + AioContext *old_ctx = qemu_get_current_aio_context(); + + if (old_ctx != new_ctx) { + AioCoRescheduleSelf data = { + .co = qemu_coroutine_self(), + .new_ctx = new_ctx, + }; + /* + * We can't directly schedule the coroutine in the target context + * because this would be racy: The other thread could try to enter the + * coroutine before it has yielded in this one. + */ + aio_bh_schedule_oneshot(old_ctx, aio_co_reschedule_self_bh, &data); + qemu_coroutine_yield(); + } +} + void aio_co_wake(struct Coroutine *co) { AioContext *ctx; @@ -567,7 +607,7 @@ void aio_co_wake(struct Coroutine *co) * qemu_coroutine_enter. */ smp_read_barrier_depends(); - ctx = atomic_read(&co->ctx); + ctx = qatomic_read(&co->ctx); aio_co_enter(ctx, co); } diff --git a/util/atomic64.c b/util/atomic64.c index b198a6c9c80288e8d252eca4000fc6590a5f98b3..93037d5b116cda0df02e445f9d9c7aa5af984bcc 100644 --- a/util/atomic64.c +++ b/util/atomic64.c @@ -51,8 +51,8 @@ static QemuSpin *addr_to_lock(const void *addr) return ret; \ } -GEN_READ(atomic_read_i64, int64_t) -GEN_READ(atomic_read_u64, uint64_t) +GEN_READ(qatomic_read_i64, int64_t) +GEN_READ(qatomic_read_u64, uint64_t) #undef GEN_READ #define GEN_SET(name, type) \ @@ -65,11 +65,11 @@ GEN_READ(atomic_read_u64, uint64_t) qemu_spin_unlock(lock); \ } -GEN_SET(atomic_set_i64, int64_t) -GEN_SET(atomic_set_u64, uint64_t) +GEN_SET(qatomic_set_i64, int64_t) +GEN_SET(qatomic_set_u64, uint64_t) #undef GEN_SET -void atomic64_init(void) +void qatomic64_init(void) { int i; diff --git a/util/base64.c b/util/base64.c index 9d3c46cbcc15d0c7c4e5a6350af9323d2776e44e..811111ac4f8cbaab7675e4665c34f9e2a6033788 100644 --- a/util/base64.c +++ b/util/base64.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/util/bitmap.c b/util/bitmap.c index 1753ff7f5bd77fad87a16246c6e68be7f8fa5b8e..1f201393aef195f098953ca3aa19bcef1b55922c 100644 --- a/util/bitmap.c +++ b/util/bitmap.c @@ -190,7 +190,7 @@ void bitmap_set_atomic(unsigned long *map, long start, long nr) /* First word */ if (nr - bits_to_set > 0) { - atomic_or(p, mask_to_set); + qatomic_or(p, mask_to_set); nr -= bits_to_set; bits_to_set = BITS_PER_LONG; mask_to_set = ~0UL; @@ -209,9 +209,9 @@ void bitmap_set_atomic(unsigned long *map, long start, long nr) /* Last word */ if (nr) { mask_to_set &= BITMAP_LAST_WORD_MASK(size); - atomic_or(p, mask_to_set); + qatomic_or(p, mask_to_set); } else { - /* If we avoided the full barrier in atomic_or(), issue a + /* If we avoided the full barrier in qatomic_or(), issue a * barrier to account for the assignments in the while loop. */ smp_mb(); @@ -253,7 +253,7 @@ bool bitmap_test_and_clear_atomic(unsigned long *map, long start, long nr) /* First word */ if (nr - bits_to_clear > 0) { - old_bits = atomic_fetch_and(p, ~mask_to_clear); + old_bits = qatomic_fetch_and(p, ~mask_to_clear); dirty |= old_bits & mask_to_clear; nr -= bits_to_clear; bits_to_clear = BITS_PER_LONG; @@ -265,7 +265,7 @@ bool bitmap_test_and_clear_atomic(unsigned long *map, long start, long nr) if (bits_to_clear == BITS_PER_LONG) { while (nr >= BITS_PER_LONG) { if (*p) { - old_bits = atomic_xchg(p, 0); + old_bits = qatomic_xchg(p, 0); dirty |= old_bits; } nr -= BITS_PER_LONG; @@ -276,7 +276,7 @@ bool bitmap_test_and_clear_atomic(unsigned long *map, long start, long nr) /* Last word */ if (nr) { mask_to_clear &= BITMAP_LAST_WORD_MASK(size); - old_bits = atomic_fetch_and(p, ~mask_to_clear); + old_bits = qatomic_fetch_and(p, ~mask_to_clear); dirty |= old_bits & mask_to_clear; } else { if (!dirty) { @@ -291,7 +291,7 @@ void bitmap_copy_and_clear_atomic(unsigned long *dst, unsigned long *src, long nr) { while (nr > 0) { - *dst = atomic_xchg(src, 0); + *dst = qatomic_xchg(src, 0); dst++; src++; nr -= BITS_PER_LONG; diff --git a/util/block-helpers.c b/util/block-helpers.c new file mode 100644 index 0000000000000000000000000000000000000000..c4851432f56601158becd975f49c62dc7dfbbb74 --- /dev/null +++ b/util/block-helpers.c @@ -0,0 +1,46 @@ +/* + * Block utility functions + * + * Copyright IBM, Corp. 2011 + * Copyright (c) 2020 Coiby Xu + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qapi/qmp/qerror.h" +#include "block-helpers.h" + +/** + * check_block_size: + * @id: The unique ID of the object + * @name: The name of the property being validated + * @value: The block size in bytes + * @errp: A pointer to an area to store an error + * + * This function checks that the block size meets the following conditions: + * 1. At least MIN_BLOCK_SIZE + * 2. No larger than MAX_BLOCK_SIZE + * 3. A power of 2 + */ +void check_block_size(const char *id, const char *name, int64_t value, + Error **errp) +{ + /* value of 0 means "unset" */ + if (value && (value < MIN_BLOCK_SIZE || value > MAX_BLOCK_SIZE)) { + error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, + id, name, value, MIN_BLOCK_SIZE, MAX_BLOCK_SIZE); + return; + } + + /* We rely on power-of-2 blocksizes for bitmasks */ + if ((value & (value - 1)) != 0) { + error_setg(errp, + "Property %s.%s doesn't take value '%" PRId64 + "', it's not a power of 2", + id, name, value); + return; + } +} diff --git a/util/block-helpers.h b/util/block-helpers.h new file mode 100644 index 0000000000000000000000000000000000000000..b53295a529a67117bcae50932066b3c43e47096c --- /dev/null +++ b/util/block-helpers.h @@ -0,0 +1,19 @@ +#ifndef BLOCK_HELPERS_H +#define BLOCK_HELPERS_H + +#include "qemu/units.h" + +/* lower limit is sector size */ +#define MIN_BLOCK_SIZE INT64_C(512) +#define MIN_BLOCK_SIZE_STR "512 B" +/* + * upper limit is arbitrary, 2 MiB looks sufficient for all sensible uses, and + * matches qcow2 cluster size limit + */ +#define MAX_BLOCK_SIZE (2 * MiB) +#define MAX_BLOCK_SIZE_STR "2 MiB" + +void check_block_size(const char *id, const char *name, int64_t value, + Error **errp); + +#endif /* BLOCK_HELPERS_H */ diff --git a/util/buffer.c b/util/buffer.c index d8bb8745343dc58004dbb69549f8796bba33dbf8..743eaa930dd66c78ec208aa0e015a2b6a6c01cdd 100644 --- a/util/buffer.c +++ b/util/buffer.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/util/cacheinfo.c b/util/cacheinfo.c index d94dc6adc8da9d9ad34cd977fca7cf22084dbb6d..7804c186b60745e3bc006f95ccd458d48ca28c1b 100644 --- a/util/cacheinfo.c +++ b/util/cacheinfo.c @@ -193,5 +193,5 @@ static void __attribute__((constructor)) init_cache_info(void) qemu_dcache_linesize = dsize; qemu_dcache_linesize_log = ctz32(dsize); - atomic64_init(); + qatomic64_init(); } diff --git a/util/compatfd.c b/util/compatfd.c index c296f55d148aa6d5d99410624e5121a4d3c6e49d..ee47dd808977d089dc92baed486fed5e3f3200f3 100644 --- a/util/compatfd.c +++ b/util/compatfd.c @@ -16,7 +16,9 @@ #include "qemu/osdep.h" #include "qemu/thread.h" +#if defined(CONFIG_SIGNALFD) #include +#endif struct sigfd_compat_info { diff --git a/util/coroutine-sigaltstack.c b/util/coroutine-sigaltstack.c index f6fc49a0e51a74bf6971e8d25aa7a364627d2480..aade82afb8c0053e7ecc2a3c06efc596b9ec31eb 100644 --- a/util/coroutine-sigaltstack.c +++ b/util/coroutine-sigaltstack.c @@ -30,6 +30,10 @@ #include "qemu-common.h" #include "qemu/coroutine_int.h" +#ifdef CONFIG_SAFESTACK +#error "SafeStack is not compatible with code run in alternate signal stacks" +#endif + typedef struct { Coroutine base; void *stack; diff --git a/util/coroutine-ucontext.c b/util/coroutine-ucontext.c index bd593e61bc0d743df7dbd3bd8b8ba228e3a97016..904b375192cab6d24c2bdea46d8c53beedb9b296 100644 --- a/util/coroutine-ucontext.c +++ b/util/coroutine-ucontext.c @@ -37,12 +37,26 @@ #endif #endif +#ifdef CONFIG_TSAN +#include +#endif + typedef struct { Coroutine base; void *stack; size_t stack_size; +#ifdef CONFIG_SAFESTACK + /* Need an unsafe stack for each coroutine */ + void *unsafe_stack; + size_t unsafe_stack_size; +#endif sigjmp_buf env; +#ifdef CONFIG_TSAN + void *tsan_co_fiber; + void *tsan_caller_fiber; +#endif + #ifdef CONFIG_VALGRIND_H unsigned int valgrind_stack_id; #endif @@ -65,7 +79,22 @@ union cc_arg { int i[2]; }; -static void finish_switch_fiber(void *fake_stack_save) +/* + * QEMU_ALWAYS_INLINE only does so if __OPTIMIZE__, so we cannot use it. + * always_inline is required to avoid TSan runtime fatal errors. + */ +static inline __attribute__((always_inline)) +void on_new_fiber(CoroutineUContext *co) +{ +#ifdef CONFIG_TSAN + co->tsan_co_fiber = __tsan_create_fiber(0); /* flags: sync on switch */ + co->tsan_caller_fiber = __tsan_get_current_fiber(); +#endif +} + +/* always_inline is required to avoid TSan runtime fatal errors. */ +static inline __attribute__((always_inline)) +void finish_switch_fiber(void *fake_stack_save) { #ifdef CONFIG_ASAN const void *bottom_old; @@ -78,13 +107,41 @@ static void finish_switch_fiber(void *fake_stack_save) leader.stack_size = size_old; } #endif +#ifdef CONFIG_TSAN + if (fake_stack_save) { + __tsan_release(fake_stack_save); + __tsan_switch_to_fiber(fake_stack_save, 0); /* 0=synchronize */ + } +#endif } -static void start_switch_fiber(void **fake_stack_save, - const void *bottom, size_t size) +/* always_inline is required to avoid TSan runtime fatal errors. */ +static inline __attribute__((always_inline)) +void start_switch_fiber_asan(CoroutineAction action, void **fake_stack_save, + const void *bottom, size_t size) { #ifdef CONFIG_ASAN - __sanitizer_start_switch_fiber(fake_stack_save, bottom, size); + __sanitizer_start_switch_fiber( + action == COROUTINE_TERMINATE ? NULL : fake_stack_save, + bottom, size); +#endif +} + +/* always_inline is required to avoid TSan runtime fatal errors. */ +static inline __attribute__((always_inline)) +void start_switch_fiber_tsan(void **fake_stack_save, + CoroutineUContext *co, + bool caller) +{ +#ifdef CONFIG_TSAN + void *new_fiber = caller ? + co->tsan_caller_fiber : + co->tsan_co_fiber; + void *curr_fiber = __tsan_get_current_fiber(); + __tsan_acquire(curr_fiber); + + *fake_stack_save = curr_fiber; + __tsan_switch_to_fiber(new_fiber, 0); /* 0=synchronize */ #endif } @@ -104,8 +161,9 @@ static void coroutine_trampoline(int i0, int i1) /* Initialize longjmp environment and switch back the caller */ if (!sigsetjmp(self->env, 0)) { - start_switch_fiber(&fake_stack_save, - leader.stack, leader.stack_size); + start_switch_fiber_asan(COROUTINE_YIELD, &fake_stack_save, leader.stack, + leader.stack_size); + start_switch_fiber_tsan(&fake_stack_save, self, true); /* true=caller */ siglongjmp(*(sigjmp_buf *)co->entry_arg, 1); } @@ -140,6 +198,10 @@ Coroutine *qemu_coroutine_new(void) co = g_malloc0(sizeof(*co)); co->stack_size = COROUTINE_STACK_SIZE; co->stack = qemu_alloc_stack(&co->stack_size); +#ifdef CONFIG_SAFESTACK + co->unsafe_stack_size = COROUTINE_STACK_SIZE; + co->unsafe_stack = qemu_alloc_stack(&co->unsafe_stack_size); +#endif co->base.entry_arg = &old_env; /* stash away our jmp_buf */ uc.uc_link = &old_uc; @@ -154,12 +216,32 @@ Coroutine *qemu_coroutine_new(void) arg.p = co; + on_new_fiber(co); makecontext(&uc, (void (*)(void))coroutine_trampoline, 2, arg.i[0], arg.i[1]); /* swapcontext() in, siglongjmp() back out */ if (!sigsetjmp(old_env, 0)) { - start_switch_fiber(&fake_stack_save, co->stack, co->stack_size); + start_switch_fiber_asan(COROUTINE_YIELD, &fake_stack_save, co->stack, + co->stack_size); + start_switch_fiber_tsan(&fake_stack_save, + co, false); /* false=not caller */ + +#ifdef CONFIG_SAFESTACK + /* + * Before we swap the context, set the new unsafe stack + * The unsafe stack grows just like the normal stack, so start from + * the last usable location of the memory area. + * NOTE: we don't have to re-set the usp afterwards because we are + * coming back to this context through a siglongjmp. + * The compiler already wrapped the corresponding sigsetjmp call with + * code that saves the usp on the (safe) stack before the call, and + * restores it right after (which is where we return with siglongjmp). + */ + void *usp = co->unsafe_stack + co->unsafe_stack_size; + __safestack_unsafe_stack_ptr = usp; +#endif + swapcontext(&old_uc, &uc); } @@ -169,8 +251,8 @@ Coroutine *qemu_coroutine_new(void) } #ifdef CONFIG_VALGRIND_H -#if defined(CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE) && !defined(__clang__) /* Work around an unused variable in the valgrind.h macro... */ +#if !defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-but-set-variable" #endif @@ -178,7 +260,7 @@ static inline void valgrind_stack_deregister(CoroutineUContext *co) { VALGRIND_STACK_DEREGISTER(co->valgrind_stack_id); } -#if defined(CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE) && !defined(__clang__) +#if !defined(__clang__) #pragma GCC diagnostic pop #endif #endif @@ -192,6 +274,9 @@ void qemu_coroutine_delete(Coroutine *co_) #endif qemu_free_stack(co->stack, co->stack_size); +#ifdef CONFIG_SAFESTACK + qemu_free_stack(co->unsafe_stack, co->unsafe_stack_size); +#endif g_free(co); } @@ -216,8 +301,10 @@ qemu_coroutine_switch(Coroutine *from_, Coroutine *to_, ret = sigsetjmp(from->env, 0); if (ret == 0) { - start_switch_fiber(action == COROUTINE_TERMINATE ? - NULL : &fake_stack_save, to->stack, to->stack_size); + start_switch_fiber_asan(action, &fake_stack_save, to->stack, + to->stack_size); + start_switch_fiber_tsan(&fake_stack_save, + to, false); /* false=not caller */ siglongjmp(to->env, action); } @@ -231,6 +318,11 @@ Coroutine *qemu_coroutine_self(void) if (!current) { current = &leader.base; } +#ifdef CONFIG_TSAN + if (!leader.tsan_co_fiber) { + leader.tsan_co_fiber = __tsan_get_current_fiber(); + } +#endif return current; } diff --git a/util/cutils.c b/util/cutils.c index 36ce712271f12ae0c19e8c94d4ad5a2b658ad64a..0b5073b33012a91a8d6a59d74965bb72327a996f 100644 --- a/util/cutils.c +++ b/util/cutils.c @@ -885,7 +885,83 @@ char *size_to_str(uint64_t val) return g_strdup_printf("%0.3g %sB", (double)val / div, suffixes[i]); } +char *freq_to_str(uint64_t freq_hz) +{ + static const char *const suffixes[] = { "", "K", "M", "G", "T", "P", "E" }; + double freq = freq_hz; + size_t idx = 0; + + while (freq >= 1000.0) { + freq /= 1000.0; + idx++; + } + assert(idx < ARRAY_SIZE(suffixes)); + + return g_strdup_printf("%0.3g %sHz", freq, suffixes[idx]); +} + int qemu_pstrcmp0(const char **str1, const char **str2) { return g_strcmp0(*str1, *str2); } + +static inline bool starts_with_prefix(const char *dir) +{ + size_t prefix_len = strlen(CONFIG_PREFIX); + return !memcmp(dir, CONFIG_PREFIX, prefix_len) && + (!dir[prefix_len] || G_IS_DIR_SEPARATOR(dir[prefix_len])); +} + +/* Return the next path component in dir, and store its length in *p_len. */ +static inline const char *next_component(const char *dir, int *p_len) +{ + int len; + while (*dir && G_IS_DIR_SEPARATOR(*dir)) { + dir++; + } + len = 0; + while (dir[len] && !G_IS_DIR_SEPARATOR(dir[len])) { + len++; + } + *p_len = len; + return dir; +} + +char *get_relocated_path(const char *dir) +{ + size_t prefix_len = strlen(CONFIG_PREFIX); + const char *bindir = CONFIG_BINDIR; + const char *exec_dir = qemu_get_exec_dir(); + GString *result; + int len_dir, len_bindir; + + /* Fail if qemu_init_exec_dir was not called. */ + assert(exec_dir[0]); + if (!starts_with_prefix(dir) || !starts_with_prefix(bindir)) { + return g_strdup(dir); + } + + result = g_string_new(exec_dir); + + /* Advance over common components. */ + len_dir = len_bindir = prefix_len; + do { + dir += len_dir; + bindir += len_bindir; + dir = next_component(dir, &len_dir); + bindir = next_component(bindir, &len_bindir); + } while (len_dir && len_dir == len_bindir && !memcmp(dir, bindir, len_dir)); + + /* Ascend from bindir to the common prefix with dir. */ + while (len_bindir) { + bindir += len_bindir; + g_string_append(result, "/.."); + bindir = next_component(bindir, &len_bindir); + } + + if (*dir) { + assert(G_IS_DIR_SEPARATOR(dir[-1])); + g_string_append(result, dir - 1); + } + return result->str; +} diff --git a/util/drm.c b/util/drm.c index a23ff2453826002b8c2d9d0b7a684a0700451f9a..dae8ffebc811672810ff0e8fb0e37bc805692ba5 100644 --- a/util/drm.c +++ b/util/drm.c @@ -24,7 +24,8 @@ int qemu_drm_rendernode_open(const char *rendernode) { DIR *dir; struct dirent *e; - int r, fd; + struct stat st; + int r, fd, ret; char *p; if (rendernode) { @@ -38,10 +39,6 @@ int qemu_drm_rendernode_open(const char *rendernode) fd = -1; while ((e = readdir(dir))) { - if (e->d_type != DT_CHR) { - continue; - } - if (strncmp(e->d_name, "renderD", 7)) { continue; } @@ -53,6 +50,18 @@ int qemu_drm_rendernode_open(const char *rendernode) g_free(p); continue; } + + /* + * prefer fstat() over checking e->d_type == DT_CHR for + * portability reasons + */ + ret = fstat(r, &st); + if (ret < 0 || (st.st_mode & S_IFMT) != S_IFCHR) { + close(r); + g_free(p); + continue; + } + fd = r; g_free(p); break; diff --git a/util/fdmon-epoll.c b/util/fdmon-epoll.c index fcd989d47d8a09baebad41bcd99c8a490954e08f..e11a8a022e9822e05c267901ca2a1f859803a9b4 100644 --- a/util/fdmon-epoll.c +++ b/util/fdmon-epoll.c @@ -65,7 +65,7 @@ static int fdmon_epoll_wait(AioContext *ctx, AioHandlerList *ready_list, struct epoll_event events[128]; /* Fall back while external clients are disabled */ - if (atomic_read(&ctx->external_disable_cnt)) { + if (qatomic_read(&ctx->external_disable_cnt)) { return fdmon_poll_ops.wait(ctx, ready_list, timeout); } @@ -132,7 +132,7 @@ bool fdmon_epoll_try_upgrade(AioContext *ctx, unsigned npfd) } /* Do not upgrade while external clients are disabled */ - if (atomic_read(&ctx->external_disable_cnt)) { + if (qatomic_read(&ctx->external_disable_cnt)) { return false; } diff --git a/util/fdmon-io_uring.c b/util/fdmon-io_uring.c index 1d14177df07fa58c8e3cfb18d608c29cf6dc3aa2..1461dfa40743ba0a33dcb3e7e795a43265f4ff3d 100644 --- a/util/fdmon-io_uring.c +++ b/util/fdmon-io_uring.c @@ -103,7 +103,7 @@ static void enqueue(AioHandlerSList *head, AioHandler *node, unsigned flags) { unsigned old_flags; - old_flags = atomic_fetch_or(&node->flags, FDMON_IO_URING_PENDING | flags); + old_flags = qatomic_fetch_or(&node->flags, FDMON_IO_URING_PENDING | flags); if (!(old_flags & FDMON_IO_URING_PENDING)) { QSLIST_INSERT_HEAD_ATOMIC(head, node, node_submitted); } @@ -127,7 +127,7 @@ static AioHandler *dequeue(AioHandlerSList *head, unsigned *flags) * telling process_cqe() to delete the AioHandler when its * IORING_OP_POLL_ADD completes. */ - *flags = atomic_fetch_and(&node->flags, ~(FDMON_IO_URING_PENDING | + *flags = qatomic_fetch_and(&node->flags, ~(FDMON_IO_URING_PENDING | FDMON_IO_URING_ADD)); return node; } @@ -233,7 +233,7 @@ static bool process_cqe(AioContext *ctx, * with enqueue() here then we can safely clear the FDMON_IO_URING_REMOVE * bit before IORING_OP_POLL_REMOVE is submitted. */ - flags = atomic_fetch_and(&node->flags, ~FDMON_IO_URING_REMOVE); + flags = qatomic_fetch_and(&node->flags, ~FDMON_IO_URING_REMOVE); if (flags & FDMON_IO_URING_REMOVE) { QLIST_INSERT_HEAD_RCU(&ctx->deleted_aio_handlers, node, node_deleted); return false; @@ -273,7 +273,7 @@ static int fdmon_io_uring_wait(AioContext *ctx, AioHandlerList *ready_list, int ret; /* Fall back while external clients are disabled */ - if (atomic_read(&ctx->external_disable_cnt)) { + if (qatomic_read(&ctx->external_disable_cnt)) { return fdmon_poll_ops.wait(ctx, ready_list, timeout); } @@ -312,7 +312,7 @@ static bool fdmon_io_uring_need_wait(AioContext *ctx) } /* Are we falling back to fdmon-poll? */ - return atomic_read(&ctx->external_disable_cnt); + return qatomic_read(&ctx->external_disable_cnt); } static const FDMonOps fdmon_io_uring_ops = { @@ -344,7 +344,7 @@ void fdmon_io_uring_destroy(AioContext *ctx) /* Move handlers due to be removed onto the deleted list */ while ((node = QSLIST_FIRST_RCU(&ctx->submit_list))) { - unsigned flags = atomic_fetch_and(&node->flags, + unsigned flags = qatomic_fetch_and(&node->flags, ~(FDMON_IO_URING_PENDING | FDMON_IO_URING_ADD | FDMON_IO_URING_REMOVE)); diff --git a/util/fdmon-poll.c b/util/fdmon-poll.c index 488067b679f9ad09250b0872373c2985740ee536..5fe3b47865a58af7e1ebba6306b6974662da363a 100644 --- a/util/fdmon-poll.c +++ b/util/fdmon-poll.c @@ -73,6 +73,7 @@ static int fdmon_poll_wait(AioContext *ctx, AioHandlerList *ready_list, /* epoll(7) is faster above a certain number of fds */ if (fdmon_epoll_try_upgrade(ctx, npfd)) { + npfd = 0; /* we won't need pollfds[], reset npfd */ return ctx->fdmon_ops->wait(ctx, ready_list, timeout); } diff --git a/util/filemonitor-inotify.c b/util/filemonitor-inotify.c index b5f4b93f3ff0639b398ef2ad380ba5b423cc18cc..2c45f7f1764bef0c3555941c711275185cc9991e 100644 --- a/util/filemonitor-inotify.c +++ b/util/filemonitor-inotify.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/util/filemonitor-stub.c b/util/filemonitor-stub.c index 2c0e97edd81f71d18b7cae552d908fb20316bb39..93fef65345d309716b0f69f7b95821fa6a6fb583 100644 --- a/util/filemonitor-stub.c +++ b/util/filemonitor-stub.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/util/getauxval.c b/util/getauxval.c index 36afdfb9e62e3b2737d8dea03b81787b91d193a2..b124107d61eadf49bd6182f0633c02802304b9bd 100644 --- a/util/getauxval.c +++ b/util/getauxval.c @@ -98,6 +98,16 @@ unsigned long qemu_getauxval(unsigned long type) return 0; } +#elif defined(__FreeBSD__) +#include + +unsigned long qemu_getauxval(unsigned long type) +{ + unsigned long aux = 0; + elf_aux_info(type, &aux, sizeof(aux)); + return aux; +} + #else unsigned long qemu_getauxval(unsigned long type) diff --git a/util/hexdump.c b/util/hexdump.c index f879ff0ad6b67492eb09e9e7c1c7d9429c554a09..2c105a8846200a044f82b7580dfd83a379e5b905 100644 --- a/util/hexdump.c +++ b/util/hexdump.c @@ -16,34 +16,50 @@ #include "qemu/osdep.h" #include "qemu-common.h" -void qemu_hexdump(const char *buf, FILE *fp, const char *prefix, size_t size) +void qemu_hexdump_line(char *line, unsigned int b, const void *bufptr, + unsigned int len, bool ascii) { - unsigned int b, len, i, c; + const char *buf = bufptr; + int i, c; - for (b = 0; b < size; b += 16) { - len = size - b; - if (len > 16) { - len = 16; + if (len > QEMU_HEXDUMP_LINE_BYTES) { + len = QEMU_HEXDUMP_LINE_BYTES; + } + + line += snprintf(line, 6, "%04x:", b); + for (i = 0; i < QEMU_HEXDUMP_LINE_BYTES; i++) { + if ((i % 4) == 0) { + *line++ = ' '; } - fprintf(fp, "%s: %04x:", prefix, b); - for (i = 0; i < 16; i++) { - if ((i % 4) == 0) { - fprintf(fp, " "); - } - if (i < len) { - fprintf(fp, " %02x", (unsigned char)buf[b + i]); - } else { - fprintf(fp, " "); - } + if (i < len) { + line += sprintf(line, " %02x", (unsigned char)buf[b + i]); + } else { + line += sprintf(line, " "); } - fprintf(fp, " "); + } + if (ascii) { + *line++ = ' '; for (i = 0; i < len; i++) { c = buf[b + i]; if (c < ' ' || c > '~') { c = '.'; } - fprintf(fp, "%c", c); + *line++ = c; } - fprintf(fp, "\n"); } + *line = '\0'; +} + +void qemu_hexdump(FILE *fp, const char *prefix, + const void *bufptr, size_t size) +{ + unsigned int b, len; + char line[QEMU_HEXDUMP_LINE_LEN]; + + for (b = 0; b < size; b += QEMU_HEXDUMP_LINE_BYTES) { + len = size - b; + qemu_hexdump_line(line, b, bufptr, len, true); + fprintf(fp, "%s: %s\n", prefix, line); + } + } diff --git a/util/iov.c b/util/iov.c index 45ef3043eec6da53386851c7ac0776790aba8011..f3a9e92a378f3eb5255b939b14039fe6680b1f52 100644 --- a/util/iov.c +++ b/util/iov.c @@ -237,7 +237,7 @@ void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt, size = size > limit ? limit : size; buf = g_malloc(size); iov_to_buf(iov, iov_cnt, 0, buf, size); - qemu_hexdump(buf, fp, prefix, size); + qemu_hexdump(fp, prefix, buf, size); g_free(buf); } @@ -636,14 +636,33 @@ void qemu_iovec_clone(QEMUIOVector *dest, const QEMUIOVector *src, void *buf) } } -size_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt, - size_t bytes) +void iov_discard_undo(IOVDiscardUndo *undo) +{ + /* Restore original iovec if it was modified */ + if (undo->modified_iov) { + *undo->modified_iov = undo->orig; + } +} + +size_t iov_discard_front_undoable(struct iovec **iov, + unsigned int *iov_cnt, + size_t bytes, + IOVDiscardUndo *undo) { size_t total = 0; struct iovec *cur; + if (undo) { + undo->modified_iov = NULL; + } + for (cur = *iov; *iov_cnt > 0; cur++) { if (cur->iov_len > bytes) { + if (undo) { + undo->modified_iov = cur; + undo->orig = *cur; + } + cur->iov_base += bytes; cur->iov_len -= bytes; total += bytes; @@ -659,12 +678,24 @@ size_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt, return total; } -size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt, - size_t bytes) +size_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt, + size_t bytes) +{ + return iov_discard_front_undoable(iov, iov_cnt, bytes, NULL); +} + +size_t iov_discard_back_undoable(struct iovec *iov, + unsigned int *iov_cnt, + size_t bytes, + IOVDiscardUndo *undo) { size_t total = 0; struct iovec *cur; + if (undo) { + undo->modified_iov = NULL; + } + if (*iov_cnt == 0) { return 0; } @@ -673,6 +704,11 @@ size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt, while (*iov_cnt > 0) { if (cur->iov_len > bytes) { + if (undo) { + undo->modified_iov = cur; + undo->orig = *cur; + } + cur->iov_len -= bytes; total += bytes; break; @@ -687,6 +723,12 @@ size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt, return total; } +size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt, + size_t bytes) +{ + return iov_discard_back_undoable(iov, iov_cnt, bytes, NULL); +} + void qemu_iovec_discard_back(QEMUIOVector *qiov, size_t bytes) { size_t total; diff --git a/util/keyval.c b/util/keyval.c index 13def4af5468dcaa65cde220356eb38fc9067d53..7f625ad33c65a41370f2834e186e6cb43171a7cc 100644 --- a/util/keyval.c +++ b/util/keyval.c @@ -14,10 +14,11 @@ * KEY=VALUE,... syntax: * * key-vals = [ key-val { ',' key-val } [ ',' ] ] - * key-val = key '=' val + * key-val = key '=' val | help * key = key-fragment { '.' key-fragment } - * key-fragment = / [^=,.]* / - * val = { / [^,]* / | ',,' } + * key-fragment = / [^=,.]+ / + * val = { / [^,]+ / | ',,' } + * help = 'help' | '?' * * Semantics defined by reduction to JSON: * @@ -54,6 +55,9 @@ * * The length of any key-fragment must be between 1 and 127. * + * If any key-val is help, the object is to be treated as a help + * request. + * * Design flaw: there is no way to denote an empty array or non-root * object. While interpreting "key absent" as empty seems natural * (removing a key-val from the input string removes the member when @@ -71,12 +75,16 @@ * Awkward. Note that we carefully restrict alternate types to avoid * similar ambiguity. * - * Additional syntax for use with an implied key: + * Alternative syntax for use with an implied key: + * + * key-vals = [ key-val-1st { ',' key-val } [ ',' ] ] + * key-val-1st = val-no-key | key-val + * val-no-key = / [^=,]+ / - help * - * key-vals-ik = val-no-key [ ',' key-vals ] - * val-no-key = / [^=,]* / + * where val-no-key is syntactic sugar for implied-key=val-no-key. * - * where no-key is syntactic sugar for implied-key=val-no-key. + * Note that you can't use the sugared form when the value contains + * '=' or ','. */ #include "qemu/osdep.h" @@ -85,6 +93,7 @@ #include "qapi/qmp/qlist.h" #include "qapi/qmp/qstring.h" #include "qemu/cutils.h" +#include "qemu/help_option.h" #include "qemu/option.h" /* @@ -158,18 +167,23 @@ static QObject *keyval_parse_put(QDict *cur, } /* - * Parse one KEY=VALUE from @params, store result in @qdict. + * Parse one parameter from @params. + * + * If we're looking at KEY=VALUE, store result in @qdict. * The first fragment of KEY applies to @qdict. Subsequent fragments * apply to nested QDicts, which are created on demand. @implied_key * is as in keyval_parse(). - * On success, return a pointer to the next KEY=VALUE, or else to '\0'. + * + * If we're looking at "help" or "?", set *help to true. + * + * On success, return a pointer to the next parameter, or else to '\0'. * On failure, return NULL. */ static const char *keyval_parse_one(QDict *qdict, const char *params, - const char *implied_key, + const char *implied_key, bool *help, Error **errp) { - const char *key, *key_end, *s, *end; + const char *key, *key_end, *val_end, *s, *end; size_t len; char key_in_cur[128]; QDict *cur; @@ -178,11 +192,23 @@ static const char *keyval_parse_one(QDict *qdict, const char *params, QString *val; key = params; + val_end = NULL; len = strcspn(params, "=,"); - if (implied_key && len && key[len] != '=') { - /* Desugar implied key */ - key = implied_key; - len = strlen(implied_key); + if (len && key[len] != '=') { + if (starts_with_help_option(key) == len) { + *help = true; + s = key + len; + if (*s == ',') { + s++; + } + return s; + } + if (implied_key) { + /* Desugar implied key */ + key = implied_key; + val_end = params + len; + len = strlen(implied_key); + } } key_end = key + len; @@ -237,7 +263,11 @@ static const char *keyval_parse_one(QDict *qdict, const char *params, if (key == implied_key) { assert(!*s); - s = params; + val = qstring_from_substr(params, 0, val_end - params); + s = val_end; + if (*s == ',') { + s++; + } } else { if (*s != '=') { error_setg(errp, "Expected '=' after parameter '%.*s'", @@ -245,19 +275,19 @@ static const char *keyval_parse_one(QDict *qdict, const char *params, return NULL; } s++; - } - val = qstring_new(); - for (;;) { - if (!*s) { - break; - } else if (*s == ',') { - s++; - if (*s != ',') { + val = qstring_new(); + for (;;) { + if (!*s) { break; + } else if (*s == ',') { + s++; + if (*s != ',') { + break; + } } + qstring_append_chr(val, *s++); } - qstring_append_chr(val, *s++); } if (!keyval_parse_put(cur, key_in_cur, val, key, key_end, errp)) { @@ -388,21 +418,32 @@ static QObject *keyval_listify(QDict *cur, GSList *key_of_cur, Error **errp) /* * Parse @params in QEMU's traditional KEY=VALUE,... syntax. + * * If @implied_key, the first KEY= can be omitted. @implied_key is * implied then, and VALUE can't be empty or contain ',' or '='. + * + * A parameter "help" or "?" without a value isn't added to the + * resulting dictionary, but instead is interpreted as help request. + * All other options are parsed and returned normally so that context + * specific help can be printed. + * + * If @p_help is not NULL, store whether help is requested there. + * If @p_help is NULL and help is requested, fail. + * * On success, return a dictionary of the parsed keys and values. * On failure, store an error through @errp and return NULL. */ QDict *keyval_parse(const char *params, const char *implied_key, - Error **errp) + bool *p_help, Error **errp) { QDict *qdict = qdict_new(); QObject *listified; const char *s; + bool help = false; s = params; while (*s) { - s = keyval_parse_one(qdict, s, implied_key, errp); + s = keyval_parse_one(qdict, s, implied_key, &help, errp); if (!s) { qobject_unref(qdict); return NULL; @@ -410,6 +451,14 @@ QDict *keyval_parse(const char *params, const char *implied_key, implied_key = NULL; } + if (p_help) { + *p_help = help; + } else if (help) { + error_setg(errp, "Help is not available for this option"); + qobject_unref(qdict); + return NULL; + } + listified = keyval_listify(qdict, NULL, errp); if (!listified) { qobject_unref(qdict); diff --git a/util/lockcnt.c b/util/lockcnt.c index 4f88dcf8b898e15d1ec8d9e7c544a7ece910245f..5da36946b1b6deb90621f4d64378586c6c8c2670 100644 --- a/util/lockcnt.c +++ b/util/lockcnt.c @@ -61,7 +61,7 @@ static bool qemu_lockcnt_cmpxchg_or_wait(QemuLockCnt *lockcnt, int *val, int expected = *val; trace_lockcnt_fast_path_attempt(lockcnt, expected, new_if_free); - *val = atomic_cmpxchg(&lockcnt->count, expected, new_if_free); + *val = qatomic_cmpxchg(&lockcnt->count, expected, new_if_free); if (*val == expected) { trace_lockcnt_fast_path_success(lockcnt, expected, new_if_free); *val = new_if_free; @@ -81,7 +81,7 @@ static bool qemu_lockcnt_cmpxchg_or_wait(QemuLockCnt *lockcnt, int *val, int new = expected - QEMU_LOCKCNT_STATE_LOCKED + QEMU_LOCKCNT_STATE_WAITING; trace_lockcnt_futex_wait_prepare(lockcnt, expected, new); - *val = atomic_cmpxchg(&lockcnt->count, expected, new); + *val = qatomic_cmpxchg(&lockcnt->count, expected, new); if (*val == expected) { *val = new; } @@ -92,7 +92,7 @@ static bool qemu_lockcnt_cmpxchg_or_wait(QemuLockCnt *lockcnt, int *val, *waited = true; trace_lockcnt_futex_wait(lockcnt, *val); qemu_futex_wait(&lockcnt->count, *val); - *val = atomic_read(&lockcnt->count); + *val = qatomic_read(&lockcnt->count); trace_lockcnt_futex_wait_resume(lockcnt, *val); continue; } @@ -110,13 +110,14 @@ static void lockcnt_wake(QemuLockCnt *lockcnt) void qemu_lockcnt_inc(QemuLockCnt *lockcnt) { - int val = atomic_read(&lockcnt->count); + int val = qatomic_read(&lockcnt->count); bool waited = false; for (;;) { if (val >= QEMU_LOCKCNT_COUNT_STEP) { int expected = val; - val = atomic_cmpxchg(&lockcnt->count, val, val + QEMU_LOCKCNT_COUNT_STEP); + val = qatomic_cmpxchg(&lockcnt->count, val, + val + QEMU_LOCKCNT_COUNT_STEP); if (val == expected) { break; } @@ -142,7 +143,7 @@ void qemu_lockcnt_inc(QemuLockCnt *lockcnt) void qemu_lockcnt_dec(QemuLockCnt *lockcnt) { - atomic_sub(&lockcnt->count, QEMU_LOCKCNT_COUNT_STEP); + qatomic_sub(&lockcnt->count, QEMU_LOCKCNT_COUNT_STEP); } /* Decrement a counter, and return locked if it is decremented to zero. @@ -151,14 +152,15 @@ void qemu_lockcnt_dec(QemuLockCnt *lockcnt) */ bool qemu_lockcnt_dec_and_lock(QemuLockCnt *lockcnt) { - int val = atomic_read(&lockcnt->count); + int val = qatomic_read(&lockcnt->count); int locked_state = QEMU_LOCKCNT_STATE_LOCKED; bool waited = false; for (;;) { if (val >= 2 * QEMU_LOCKCNT_COUNT_STEP) { int expected = val; - val = atomic_cmpxchg(&lockcnt->count, val, val - QEMU_LOCKCNT_COUNT_STEP); + val = qatomic_cmpxchg(&lockcnt->count, val, + val - QEMU_LOCKCNT_COUNT_STEP); if (val == expected) { break; } @@ -199,7 +201,7 @@ bool qemu_lockcnt_dec_and_lock(QemuLockCnt *lockcnt) */ bool qemu_lockcnt_dec_if_lock(QemuLockCnt *lockcnt) { - int val = atomic_read(&lockcnt->count); + int val = qatomic_read(&lockcnt->count); int locked_state = QEMU_LOCKCNT_STATE_LOCKED; bool waited = false; @@ -233,7 +235,7 @@ bool qemu_lockcnt_dec_if_lock(QemuLockCnt *lockcnt) void qemu_lockcnt_lock(QemuLockCnt *lockcnt) { - int val = atomic_read(&lockcnt->count); + int val = qatomic_read(&lockcnt->count); int step = QEMU_LOCKCNT_STATE_LOCKED; bool waited = false; @@ -255,12 +257,12 @@ void qemu_lockcnt_inc_and_unlock(QemuLockCnt *lockcnt) { int expected, new, val; - val = atomic_read(&lockcnt->count); + val = qatomic_read(&lockcnt->count); do { expected = val; new = (val + QEMU_LOCKCNT_COUNT_STEP) & ~QEMU_LOCKCNT_STATE_MASK; trace_lockcnt_unlock_attempt(lockcnt, val, new); - val = atomic_cmpxchg(&lockcnt->count, val, new); + val = qatomic_cmpxchg(&lockcnt->count, val, new); } while (val != expected); trace_lockcnt_unlock_success(lockcnt, val, new); @@ -273,12 +275,12 @@ void qemu_lockcnt_unlock(QemuLockCnt *lockcnt) { int expected, new, val; - val = atomic_read(&lockcnt->count); + val = qatomic_read(&lockcnt->count); do { expected = val; new = val & ~QEMU_LOCKCNT_STATE_MASK; trace_lockcnt_unlock_attempt(lockcnt, val, new); - val = atomic_cmpxchg(&lockcnt->count, val, new); + val = qatomic_cmpxchg(&lockcnt->count, val, new); } while (val != expected); trace_lockcnt_unlock_success(lockcnt, val, new); @@ -289,7 +291,7 @@ void qemu_lockcnt_unlock(QemuLockCnt *lockcnt) unsigned qemu_lockcnt_count(QemuLockCnt *lockcnt) { - return atomic_read(&lockcnt->count) >> QEMU_LOCKCNT_COUNT_SHIFT; + return qatomic_read(&lockcnt->count) >> QEMU_LOCKCNT_COUNT_SHIFT; } #else void qemu_lockcnt_init(QemuLockCnt *lockcnt) @@ -307,13 +309,13 @@ void qemu_lockcnt_inc(QemuLockCnt *lockcnt) { int old; for (;;) { - old = atomic_read(&lockcnt->count); + old = qatomic_read(&lockcnt->count); if (old == 0) { qemu_lockcnt_lock(lockcnt); qemu_lockcnt_inc_and_unlock(lockcnt); return; } else { - if (atomic_cmpxchg(&lockcnt->count, old, old + 1) == old) { + if (qatomic_cmpxchg(&lockcnt->count, old, old + 1) == old) { return; } } @@ -322,7 +324,7 @@ void qemu_lockcnt_inc(QemuLockCnt *lockcnt) void qemu_lockcnt_dec(QemuLockCnt *lockcnt) { - atomic_dec(&lockcnt->count); + qatomic_dec(&lockcnt->count); } /* Decrement a counter, and return locked if it is decremented to zero. @@ -331,9 +333,9 @@ void qemu_lockcnt_dec(QemuLockCnt *lockcnt) */ bool qemu_lockcnt_dec_and_lock(QemuLockCnt *lockcnt) { - int val = atomic_read(&lockcnt->count); + int val = qatomic_read(&lockcnt->count); while (val > 1) { - int old = atomic_cmpxchg(&lockcnt->count, val, val - 1); + int old = qatomic_cmpxchg(&lockcnt->count, val, val - 1); if (old != val) { val = old; continue; @@ -343,7 +345,7 @@ bool qemu_lockcnt_dec_and_lock(QemuLockCnt *lockcnt) } qemu_lockcnt_lock(lockcnt); - if (atomic_fetch_dec(&lockcnt->count) == 1) { + if (qatomic_fetch_dec(&lockcnt->count) == 1) { return true; } @@ -360,13 +362,13 @@ bool qemu_lockcnt_dec_and_lock(QemuLockCnt *lockcnt) bool qemu_lockcnt_dec_if_lock(QemuLockCnt *lockcnt) { /* No need for acquire semantics if we return false. */ - int val = atomic_read(&lockcnt->count); + int val = qatomic_read(&lockcnt->count); if (val > 1) { return false; } qemu_lockcnt_lock(lockcnt); - if (atomic_fetch_dec(&lockcnt->count) == 1) { + if (qatomic_fetch_dec(&lockcnt->count) == 1) { return true; } @@ -381,7 +383,7 @@ void qemu_lockcnt_lock(QemuLockCnt *lockcnt) void qemu_lockcnt_inc_and_unlock(QemuLockCnt *lockcnt) { - atomic_inc(&lockcnt->count); + qatomic_inc(&lockcnt->count); qemu_mutex_unlock(&lockcnt->mutex); } @@ -392,6 +394,6 @@ void qemu_lockcnt_unlock(QemuLockCnt *lockcnt) unsigned qemu_lockcnt_count(QemuLockCnt *lockcnt) { - return atomic_read(&lockcnt->count); + return qatomic_read(&lockcnt->count); } #endif diff --git a/util/log.c b/util/log.c index bdb3d712e88f4757418f20021c3dd875cc2e97fc..2ee1500beedf9630f162454a38333e46b23953b9 100644 --- a/util/log.c +++ b/util/log.c @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -41,7 +41,7 @@ int qemu_log(const char *fmt, ...) QemuLogFile *logfile; rcu_read_lock(); - logfile = atomic_rcu_read(&qemu_logfile); + logfile = qatomic_rcu_read(&qemu_logfile); if (logfile) { va_list ap; va_start(ap, fmt); @@ -98,7 +98,7 @@ void qemu_set_log(int log_flags) QEMU_LOCK_GUARD(&qemu_logfile_mutex); if (qemu_logfile && !need_to_open_file) { logfile = qemu_logfile; - atomic_rcu_set(&qemu_logfile, NULL); + qatomic_rcu_set(&qemu_logfile, NULL); call_rcu(logfile, qemu_logfile_free, rcu); } else if (!qemu_logfile && need_to_open_file) { logfile = g_new0(QemuLogFile, 1); @@ -135,7 +135,7 @@ void qemu_set_log(int log_flags) #endif log_append = 1; } - atomic_rcu_set(&qemu_logfile, logfile); + qatomic_rcu_set(&qemu_logfile, logfile); } } @@ -272,7 +272,7 @@ void qemu_log_flush(void) QemuLogFile *logfile; rcu_read_lock(); - logfile = atomic_rcu_read(&qemu_logfile); + logfile = qatomic_rcu_read(&qemu_logfile); if (logfile) { fflush(logfile->fd); } @@ -288,7 +288,7 @@ void qemu_log_close(void) logfile = qemu_logfile; if (logfile) { - atomic_rcu_set(&qemu_logfile, NULL); + qatomic_rcu_set(&qemu_logfile, NULL); call_rcu(logfile, qemu_logfile_free, rcu); } qemu_mutex_unlock(&qemu_logfile_mutex); diff --git a/util/main-loop.c b/util/main-loop.c index eda63fe4e081d0bd36a1ef6a44f5ef0dc2039720..6470f8eae31087ed7771f8db91afdefc1c262c86 100644 --- a/util/main-loop.c +++ b/util/main-loop.c @@ -27,7 +27,7 @@ #include "qemu/cutils.h" #include "qemu/timer.h" #include "sysemu/qtest.h" -#include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" #include "sysemu/replay.h" #include "qemu/main-loop.h" #include "block/aio.h" @@ -148,7 +148,6 @@ int qemu_init_main_loop(Error **errp) { int ret; GSource *src; - Error *local_error = NULL; init_clocks(qemu_timer_notify_cb); @@ -157,9 +156,8 @@ int qemu_init_main_loop(Error **errp) return ret; } - qemu_aio_context = aio_context_new(&local_error); + qemu_aio_context = aio_context_new(errp); if (!qemu_aio_context) { - error_propagate(errp, local_error); return -EMFILE; } qemu_notify_bh = qemu_bh_new(notify_event_cb, NULL); @@ -181,6 +179,10 @@ static int max_priority; static int glib_pollfds_idx; static int glib_n_poll_fds; +void qemu_fd_register(int fd) +{ +} + static void glib_pollfds_fill(int64_t *cur_timeout) { GMainContext *context = g_main_context_default(); @@ -519,9 +521,13 @@ void main_loop_wait(int nonblocking) mlpoll.state = ret < 0 ? MAIN_LOOP_POLL_ERR : MAIN_LOOP_POLL_OK; notifier_list_notify(&main_loop_poll_notifiers, &mlpoll); - /* CPU thread can infinitely wait for event after - missing the warp */ - qemu_start_warp_timer(); + if (icount_enabled()) { + /* + * CPU thread can infinitely wait for event after + * missing the warp + */ + icount_start_warp_timer(); + } qemu_clock_run_all_timers(); } diff --git a/util/meson.build b/util/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..f359af0d46039c7bbc01663f1b266faa9478202b --- /dev/null +++ b/util/meson.build @@ -0,0 +1,82 @@ +util_ss.add(dependency('threads')) +util_ss.add(files('osdep.c', 'cutils.c', 'unicode.c', 'qemu-timer-common.c')) +util_ss.add(when: 'CONFIG_ATOMIC64', if_false: files('atomic64.c')) +util_ss.add(when: 'CONFIG_POSIX', if_true: files('aio-posix.c')) +util_ss.add(when: 'CONFIG_POSIX', if_true: files('fdmon-poll.c')) +util_ss.add(when: 'CONFIG_EPOLL_CREATE1', if_true: files('fdmon-epoll.c')) +util_ss.add(when: ['CONFIG_LINUX_IO_URING', linux_io_uring], if_true: files('fdmon-io_uring.c')) +util_ss.add(when: 'CONFIG_POSIX', if_true: files('compatfd.c')) +util_ss.add(when: 'CONFIG_POSIX', if_true: files('event_notifier-posix.c')) +util_ss.add(when: 'CONFIG_POSIX', if_true: files('mmap-alloc.c')) +util_ss.add(when: 'CONFIG_POSIX', if_true: files('oslib-posix.c')) +util_ss.add(when: 'CONFIG_POSIX', if_true: [files('qemu-openpty.c'), util]) +util_ss.add(when: 'CONFIG_POSIX', if_true: files('qemu-thread-posix.c')) +util_ss.add(when: 'CONFIG_POSIX', if_true: files('memfd.c')) +util_ss.add(when: 'CONFIG_WIN32', if_true: files('aio-win32.c')) +util_ss.add(when: 'CONFIG_WIN32', if_true: files('event_notifier-win32.c')) +util_ss.add(when: 'CONFIG_WIN32', if_true: files('oslib-win32.c')) +util_ss.add(when: 'CONFIG_WIN32', if_true: files('qemu-thread-win32.c')) +util_ss.add(when: 'CONFIG_WIN32', if_true: winmm) +util_ss.add(files('envlist.c', 'path.c', 'module.c')) +util_ss.add(files('host-utils.c')) +util_ss.add(files('bitmap.c', 'bitops.c')) +util_ss.add(files('fifo8.c')) +util_ss.add(files('cacheinfo.c')) +util_ss.add(files('error.c', 'qemu-error.c')) +util_ss.add(files('qemu-print.c')) +util_ss.add(files('id.c')) +util_ss.add(files('qemu-config.c', 'notify.c')) +util_ss.add(files('qemu-option.c', 'qemu-progress.c')) +util_ss.add(files('keyval.c')) +util_ss.add(files('crc32c.c')) +util_ss.add(files('uuid.c')) +util_ss.add(files('getauxval.c')) +util_ss.add(files('rcu.c')) +util_ss.add(when: 'CONFIG_MEMBARRIER', if_true: files('sys_membarrier.c')) +util_ss.add(files('log.c')) +util_ss.add(files('pagesize.c')) +util_ss.add(files('qdist.c')) +util_ss.add(files('qht.c')) +util_ss.add(files('qsp.c')) +util_ss.add(files('range.c')) +util_ss.add(files('stats64.c')) +util_ss.add(files('systemd.c')) +util_ss.add(when: 'CONFIG_POSIX', if_true: files('drm.c')) +util_ss.add(files('guest-random.c')) + +if have_user + util_ss.add(files('selfmap.c')) +endif + +if have_system + util_ss.add(when: 'CONFIG_GIO', if_true: [files('dbus.c'), gio]) +endif + +if have_block + util_ss.add(files('aiocb.c', 'async.c', 'aio-wait.c')) + util_ss.add(files('base64.c')) + util_ss.add(files('buffer.c')) + util_ss.add(files('bufferiszero.c')) + util_ss.add(files('coroutine-@0@.c'.format(config_host['CONFIG_COROUTINE_BACKEND']))) + util_ss.add(files('hbitmap.c')) + util_ss.add(files('hexdump.c')) + util_ss.add(files('iova-tree.c')) + util_ss.add(files('iov.c', 'qemu-sockets.c', 'uri.c')) + util_ss.add(files('lockcnt.c')) + util_ss.add(files('main-loop.c')) + util_ss.add(files('nvdimm-utils.c')) + util_ss.add(files('qemu-coroutine.c', 'qemu-coroutine-lock.c', 'qemu-coroutine-io.c')) + util_ss.add(when: 'CONFIG_LINUX', if_true: [ + files('vhost-user-server.c'), vhost_user + ]) + util_ss.add(files('block-helpers.c')) + util_ss.add(files('qemu-coroutine-sleep.c')) + util_ss.add(files('qemu-co-shared-resource.c')) + util_ss.add(files('thread-pool.c', 'qemu-timer.c')) + util_ss.add(files('readline.c')) + util_ss.add(files('throttle.c')) + util_ss.add(files('timed-average.c')) + util_ss.add(when: 'CONFIG_INOTIFY1', if_true: files('filemonitor-inotify.c'), + if_false: files('filemonitor-stub.c')) + util_ss.add(when: 'CONFIG_LINUX', if_true: files('vfio-helpers.c')) +endif diff --git a/util/module.c b/util/module.c index e48d9aacc05ac39d3a988d2c25c65cda5b3806f3..c65060c167df236d6e2163472708cf95e69a02c7 100644 --- a/util/module.c +++ b/util/module.c @@ -19,6 +19,7 @@ #endif #include "qemu/queue.h" #include "qemu/module.h" +#include "qemu/cutils.h" #ifdef CONFIG_MODULE_UPGRADES #include "qemu-version.h" #endif @@ -109,15 +110,15 @@ void module_call_init(module_init_type type) } #ifdef CONFIG_MODULES -static int module_load_file(const char *fname) +static int module_load_file(const char *fname, bool mayfail, bool export_symbols) { GModule *g_module; void (*sym)(void); - const char *dsosuf = HOST_DSOSUF; + const char *dsosuf = CONFIG_HOST_DSOSUF; int len = strlen(fname); int suf_len = strlen(dsosuf); ModuleEntry *e, *next; - int ret; + int ret, flags; if (len <= suf_len || strcmp(&fname[len - suf_len], dsosuf)) { /* wrong suffix */ @@ -131,10 +132,16 @@ static int module_load_file(const char *fname) assert(QTAILQ_EMPTY(&dso_init_list)); - g_module = g_module_open(fname, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); + flags = 0; + if (!export_symbols) { + flags |= G_MODULE_BIND_LOCAL; + } + g_module = g_module_open(fname, flags); if (!g_module) { - fprintf(stderr, "Failed to open module: %s\n", - g_module_error()); + if (!mayfail) { + fprintf(stderr, "Failed to open module: %s\n", + g_module_error()); + } ret = -EINVAL; goto out; } @@ -164,15 +171,32 @@ static int module_load_file(const char *fname) out: return ret; } + +static const struct { + const char *name; + const char *dep; +} module_deps[] = { + { "audio-spice", "ui-spice-core" }, + { "chardev-spice", "ui-spice-core" }, + { "hw-display-qxl", "ui-spice-core" }, + { "ui-spice-app", "ui-spice-core" }, + { "ui-spice-app", "chardev-spice" }, + +#ifdef CONFIG_OPENGL + { "ui-egl-headless", "ui-opengl" }, + { "ui-gtk", "ui-opengl" }, + { "ui-sdl", "ui-opengl" }, + { "ui-spice-core", "ui-opengl" }, +#endif +}; #endif -bool module_load_one(const char *prefix, const char *lib_name) +bool module_load_one(const char *prefix, const char *lib_name, bool mayfail) { bool success = false; #ifdef CONFIG_MODULES char *fname = NULL; - char *exec_dir; #ifdef CONFIG_MODULE_UPGRADES char *version_dir; #endif @@ -180,7 +204,8 @@ bool module_load_one(const char *prefix, const char *lib_name) char *dirs[5]; char *module_name; int i = 0, n_dirs = 0; - int ret; + int ret, dep; + bool export_symbols = false; static GHashTable *loaded_modules; if (!g_module_supported()) { @@ -194,19 +219,28 @@ bool module_load_one(const char *prefix, const char *lib_name) module_name = g_strdup_printf("%s%s", prefix, lib_name); + for (dep = 0; dep < ARRAY_SIZE(module_deps); dep++) { + if (strcmp(module_name, module_deps[dep].name) == 0) { + /* we depend on another module */ + module_load_one("", module_deps[dep].dep, false); + } + if (strcmp(module_name, module_deps[dep].dep) == 0) { + /* another module depends on us */ + export_symbols = true; + } + } + if (!g_hash_table_add(loaded_modules, module_name)) { g_free(module_name); return true; } - exec_dir = qemu_get_exec_dir(); search_dir = getenv("QEMU_MODULE_DIR"); if (search_dir != NULL) { dirs[n_dirs++] = g_strdup_printf("%s", search_dir); } - dirs[n_dirs++] = g_strdup_printf("%s", CONFIG_QEMU_MODDIR); - dirs[n_dirs++] = g_strdup_printf("%s/..", exec_dir ? : ""); - dirs[n_dirs++] = g_strdup_printf("%s", exec_dir ? : ""); + dirs[n_dirs++] = get_relocated_path(CONFIG_QEMU_MODDIR); + dirs[n_dirs++] = g_strdup(qemu_get_exec_dir()); #ifdef CONFIG_MODULE_UPGRADES version_dir = g_strcanon(g_strdup(QEMU_PKGVERSION), @@ -217,13 +251,10 @@ bool module_load_one(const char *prefix, const char *lib_name) assert(n_dirs <= ARRAY_SIZE(dirs)); - g_free(exec_dir); - exec_dir = NULL; - for (i = 0; i < n_dirs; i++) { fname = g_strdup_printf("%s/%s%s", - dirs[i], module_name, HOST_DSOSUF); - ret = module_load_file(fname); + dirs[i], module_name, CONFIG_HOST_DSOSUF); + ret = module_load_file(fname, mayfail, export_symbols); g_free(fname); fname = NULL; /* Try loading until loaded a module file */ @@ -245,3 +276,77 @@ bool module_load_one(const char *prefix, const char *lib_name) #endif return success; } + +/* + * Building devices and other qom objects modular is mostly useful in + * case they have dependencies to external shared libraries, so we can + * cut down the core qemu library dependencies. Which is the case for + * only a very few devices & objects. + * + * So with the expectation that this will be rather the exception than + * the rule and the list will not gain that many entries, go with a + * simple manually maintained list for now. + * + * The list must be sorted by module (module_load_qom_all() needs this). + */ +static struct { + const char *type; + const char *prefix; + const char *module; +} const qom_modules[] = { + { "ccid-card-passthru", "hw-", "usb-smartcard" }, + { "ccid-card-emulated", "hw-", "usb-smartcard" }, + { "usb-redir", "hw-", "usb-redirect" }, + { "qxl-vga", "hw-", "display-qxl" }, + { "qxl", "hw-", "display-qxl" }, + { "virtio-gpu-device", "hw-", "display-virtio-gpu" }, + { "vhost-user-gpu", "hw-", "display-virtio-gpu" }, + { "virtio-gpu-pci-base", "hw-", "display-virtio-gpu-pci" }, + { "virtio-gpu-pci", "hw-", "display-virtio-gpu-pci" }, + { "vhost-user-gpu-pci", "hw-", "display-virtio-gpu-pci" }, + { "virtio-vga-base", "hw-", "display-virtio-vga" }, + { "virtio-vga", "hw-", "display-virtio-vga" }, + { "vhost-user-vga", "hw-", "display-virtio-vga" }, + { "chardev-braille", "chardev-", "baum" }, + { "chardev-spicevmc", "chardev-", "spice" }, + { "chardev-spiceport", "chardev-", "spice" }, +}; + +static bool module_loaded_qom_all; + +void module_load_qom_one(const char *type) +{ + int i; + + if (!type) { + return; + } + for (i = 0; i < ARRAY_SIZE(qom_modules); i++) { + if (strcmp(qom_modules[i].type, type) == 0) { + module_load_one(qom_modules[i].prefix, + qom_modules[i].module, + false); + return; + } + } +} + +void module_load_qom_all(void) +{ + int i; + + if (module_loaded_qom_all) { + return; + } + for (i = 0; i < ARRAY_SIZE(qom_modules); i++) { + if (i > 0 && (strcmp(qom_modules[i - 1].module, + qom_modules[i].module) == 0 && + strcmp(qom_modules[i - 1].prefix, + qom_modules[i].prefix) == 0)) { + /* one module implementing multiple types -> load only once */ + continue; + } + module_load_one(qom_modules[i].prefix, qom_modules[i].module, true); + } + module_loaded_qom_all = true; +} diff --git a/util/osdep.c b/util/osdep.c index 4829c07ff6edbb1508946ad789031f51b2cb6035..66d01b9160fb93e0265f53ae410b8a72535e3275 100644 --- a/util/osdep.c +++ b/util/osdep.c @@ -22,6 +22,7 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" +#include "qapi/error.h" /* Needed early for CONFIG_BSD etc. */ @@ -122,7 +123,7 @@ static int fcntl_op_getlk = -1; /* * Dups an fd and sets the flags */ -static int qemu_dup_flags(int fd, int flags) +int qemu_dup_flags(int fd, int flags) { int ret; int serrno; @@ -279,13 +280,27 @@ int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive) } #endif +static int qemu_open_cloexec(const char *name, int flags, mode_t mode) +{ + int ret; +#ifdef O_CLOEXEC + ret = open(name, flags | O_CLOEXEC, mode); +#else + ret = open(name, flags, mode); + if (ret >= 0) { + qemu_set_cloexec(ret); + } +#endif + return ret; +} + /* * Opens a file with FD_CLOEXEC set */ -int qemu_open(const char *name, int flags, ...) +static int +qemu_open_internal(const char *name, int flags, mode_t mode, Error **errp) { int ret; - int mode = 0; #ifndef _WIN32 const char *fdset_id_str; @@ -293,29 +308,19 @@ int qemu_open(const char *name, int flags, ...) /* Attempt dup of fd from fd set */ if (strstart(name, "/dev/fdset/", &fdset_id_str)) { int64_t fdset_id; - int fd, dupfd; + int dupfd; fdset_id = qemu_parse_fdset(fdset_id_str); if (fdset_id == -1) { + error_setg(errp, "Could not parse fdset %s", name); errno = EINVAL; return -1; } - fd = monitor_fdset_get_fd(fdset_id, flags); - if (fd < 0) { - errno = -fd; - return -1; - } - - dupfd = qemu_dup_flags(fd, flags); + dupfd = monitor_fdset_dup_fd_add(fdset_id, flags); if (dupfd == -1) { - return -1; - } - - ret = monitor_fdset_dup_fd_add(fdset_id, dupfd); - if (ret == -1) { - close(dupfd); - errno = EINVAL; + error_setg_errno(errp, errno, "Could not dup FD for %s flags %x", + name, flags); return -1; } @@ -323,22 +328,61 @@ int qemu_open(const char *name, int flags, ...) } #endif - if (flags & O_CREAT) { - va_list ap; + ret = qemu_open_cloexec(name, flags, mode); - va_start(ap, flags); - mode = va_arg(ap, int); - va_end(ap); + if (ret == -1) { + const char *action = flags & O_CREAT ? "create" : "open"; +#ifdef O_DIRECT + /* Give more helpful error message for O_DIRECT */ + if (errno == EINVAL && (flags & O_DIRECT)) { + ret = open(name, flags & ~O_DIRECT, mode); + if (ret != -1) { + close(ret); + error_setg(errp, "Could not %s '%s': " + "filesystem does not support O_DIRECT", + action, name); + errno = EINVAL; /* restore first open()'s errno */ + return -1; + } + } +#endif /* O_DIRECT */ + error_setg_errno(errp, errno, "Could not %s '%s'", + action, name); } -#ifdef O_CLOEXEC - ret = open(name, flags | O_CLOEXEC, mode); -#else - ret = open(name, flags, mode); - if (ret >= 0) { - qemu_set_cloexec(ret); + return ret; +} + + +int qemu_open(const char *name, int flags, Error **errp) +{ + assert(!(flags & O_CREAT)); + + return qemu_open_internal(name, flags, 0, errp); +} + + +int qemu_create(const char *name, int flags, mode_t mode, Error **errp) +{ + assert(!(flags & O_CREAT)); + + return qemu_open_internal(name, flags | O_CREAT, mode, errp); +} + + +int qemu_open_old(const char *name, int flags, ...) +{ + va_list ap; + mode_t mode = 0; + int ret; + + va_start(ap, flags); + if (flags & O_CREAT) { + mode = va_arg(ap, int); } -#endif + va_end(ap); + + ret = qemu_open_internal(name, flags, mode, NULL); #ifdef O_DIRECT if (ret == -1 && errno == EINVAL && (flags & O_DIRECT)) { @@ -392,7 +436,7 @@ int qemu_unlink(const char *name) * Set errno if fewer than `count' bytes are written. * * This function don't work with non-blocking fd's. - * Any of the possibilities with non-bloking fd's is bad: + * Any of the possibilities with non-blocking fd's is bad: * - return a short write (then name is wrong) * - busy wait adding (errno == EAGAIN) to the loop */ diff --git a/util/oslib-posix.c b/util/oslib-posix.c index 062236a1ab4109666ddc841c5b141eb021a222c4..f15234b5c030563284f710f096858fa80458a35c 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -38,7 +38,6 @@ #include "qemu/sockets.h" #include "qemu/thread.h" #include -#include #include "qemu/cutils.h" #ifdef CONFIG_LINUX @@ -48,11 +47,21 @@ #ifdef __FreeBSD__ #include #include +#include #include #endif #ifdef __NetBSD__ #include +#include +#endif + +#ifdef __APPLE__ +#include +#endif + +#ifdef __HAIKU__ +#include #endif #include "qemu/mmap-alloc.h" @@ -84,6 +93,15 @@ int qemu_get_thread_id(void) { #if defined(__linux__) return syscall(SYS_gettid); +#elif defined(__FreeBSD__) + /* thread id is up to INT_MAX */ + long tid; + thr_self(&tid); + return (int)tid; +#elif defined(__NetBSD__) + return _lwp_self(); +#elif defined(__OpenBSD__) + return getthrid(); #else return getpid(); #endif @@ -107,7 +125,7 @@ bool qemu_write_pidfile(const char *path, Error **errp) .l_len = 0, }; - fd = qemu_open(path, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR); + fd = qemu_open_old(path, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR); if (fd == -1) { error_setg_errno(errp, errno, "Cannot open pid file"); return false; @@ -244,25 +262,35 @@ void qemu_set_block(int fd) assert(f != -1); } -void qemu_set_nonblock(int fd) +int qemu_try_set_nonblock(int fd) { int f; f = fcntl(fd, F_GETFL); - assert(f != -1); - f = fcntl(fd, F_SETFL, f | O_NONBLOCK); -#ifdef __OpenBSD__ if (f == -1) { + return -errno; + } + if (fcntl(fd, F_SETFL, f | O_NONBLOCK) == -1) { +#ifdef __OpenBSD__ /* * Previous to OpenBSD 6.3, fcntl(F_SETFL) is not permitted on * memory devices and sets errno to ENODEV. * It's OK if we fail to set O_NONBLOCK on devices like /dev/null, * because they will never block anyway. */ - assert(errno == ENODEV); - } -#else - assert(f != -1); + if (errno == ENODEV) { + return 0; + } #endif + return -errno; + } + return 0; +} + +void qemu_set_nonblock(int fd) +{ + int f; + f = qemu_try_set_nonblock(fd); + assert(f == 0); } int socket_set_fast_reuse(int fd) @@ -311,8 +339,10 @@ int qemu_pipe(int pipefd[2]) char * qemu_get_local_state_pathname(const char *relative_pathname) { - return g_strdup_printf("%s/%s", CONFIG_QEMU_LOCALSTATEDIR, - relative_pathname); + g_autofree char *dir = g_strdup_printf("%s/%s", + CONFIG_QEMU_LOCALSTATEDIR, + relative_pathname); + return get_relocated_path(dir); } void qemu_set_tty_echo(int fd, bool echo) @@ -330,15 +360,16 @@ void qemu_set_tty_echo(int fd, bool echo) tcsetattr(fd, TCSANOW, &tty); } -static char exec_dir[PATH_MAX]; +static const char *exec_dir; void qemu_init_exec_dir(const char *argv0) { - char *dir; char *p = NULL; char buf[PATH_MAX]; - assert(!exec_dir[0]); + if (exec_dir) { + return; + } #if defined(__linux__) { @@ -366,28 +397,48 @@ void qemu_init_exec_dir(const char *argv0) p = buf; } } +#elif defined(__APPLE__) + { + char fpath[PATH_MAX]; + uint32_t len = sizeof(fpath); + if (_NSGetExecutablePath(fpath, &len) == 0) { + p = realpath(fpath, buf); + if (!p) { + return; + } + } + } +#elif defined(__HAIKU__) + { + image_info ii; + int32_t c = 0; + + *buf = '\0'; + while (get_next_image_info(0, &c, &ii) == B_OK) { + if (ii.type == B_APP_IMAGE) { + strncpy(buf, ii.name, sizeof(buf)); + buf[sizeof(buf) - 1] = 0; + p = buf; + break; + } + } + } #endif /* If we don't have any way of figuring out the actual executable location then try argv[0]. */ - if (!p) { - if (!argv0) { - return; - } + if (!p && argv0) { p = realpath(argv0, buf); - if (!p) { - return; - } } - dir = g_path_get_dirname(p); - - pstrcpy(exec_dir, sizeof(exec_dir), dir); - - g_free(dir); + if (p) { + exec_dir = g_path_get_dirname(p); + } else { + exec_dir = CONFIG_BINDIR; + } } -char *qemu_get_exec_dir(void) +const char *qemu_get_exec_dir(void) { - return g_strdup(exec_dir); + return exec_dir; } static void sigbus_handler(int signal) @@ -752,3 +803,53 @@ void sigaction_invoke(struct sigaction *action, } action->sa_sigaction(info->ssi_signo, &si, NULL); } + +#ifndef HOST_NAME_MAX +# ifdef _POSIX_HOST_NAME_MAX +# define HOST_NAME_MAX _POSIX_HOST_NAME_MAX +# else +# define HOST_NAME_MAX 255 +# endif +#endif + +char *qemu_get_host_name(Error **errp) +{ + long len = -1; + g_autofree char *hostname = NULL; + +#ifdef _SC_HOST_NAME_MAX + len = sysconf(_SC_HOST_NAME_MAX); +#endif /* _SC_HOST_NAME_MAX */ + + if (len < 0) { + len = HOST_NAME_MAX; + } + + /* Unfortunately, gethostname() below does not guarantee a + * NULL terminated string. Therefore, allocate one byte more + * to be sure. */ + hostname = g_new0(char, len + 1); + + if (gethostname(hostname, len) < 0) { + error_setg_errno(errp, errno, + "cannot get hostname"); + return NULL; + } + + return g_steal_pointer(&hostname); +} + +size_t qemu_get_host_physmem(void) +{ +#ifdef _SC_PHYS_PAGES + long pages = sysconf(_SC_PHYS_PAGES); + if (pages > 0) { + if (pages > SIZE_MAX / qemu_real_host_page_size) { + return SIZE_MAX; + } else { + return pages * qemu_real_host_page_size; + } + } +#endif + return 0; +} diff --git a/util/oslib-win32.c b/util/oslib-win32.c index e9b14ab17847edcbe237c41f81914a120d506288..23a7c7320b1f9b2c94a5e804c09a777beaa70c93 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -106,7 +106,7 @@ void qemu_anon_ram_free(void *ptr, size_t size) } } -#ifndef CONFIG_LOCALTIME_R +#ifndef _POSIX_THREAD_SAFE_FUNCTIONS /* FIXME: add proper locking */ struct tm *gmtime_r(const time_t *timep, struct tm *result) { @@ -130,32 +130,7 @@ struct tm *localtime_r(const time_t *timep, struct tm *result) } return p; } -#endif /* CONFIG_LOCALTIME_R */ - -void qemu_set_block(int fd) -{ - unsigned long opt = 0; - WSAEventSelect(fd, NULL, 0); - ioctlsocket(fd, FIONBIO, &opt); -} - -void qemu_set_nonblock(int fd) -{ - unsigned long opt = 1; - ioctlsocket(fd, FIONBIO, &opt); - qemu_fd_register(fd); -} - -int socket_set_fast_reuse(int fd) -{ - /* Enabling the reuse of an endpoint that was used by a socket still in - * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows - * fast reuse is the default and SO_REUSEADDR does strange things. So we - * don't have to do anything here. More info can be found at: - * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */ - return 0; -} - +#endif /* _POSIX_THREAD_SAFE_FUNCTIONS */ static int socket_error(void) { @@ -233,6 +208,38 @@ static int socket_error(void) } } +void qemu_set_block(int fd) +{ + unsigned long opt = 0; + WSAEventSelect(fd, NULL, 0); + ioctlsocket(fd, FIONBIO, &opt); +} + +int qemu_try_set_nonblock(int fd) +{ + unsigned long opt = 1; + if (ioctlsocket(fd, FIONBIO, &opt) != NO_ERROR) { + return -socket_error(); + } + qemu_fd_register(fd); + return 0; +} + +void qemu_set_nonblock(int fd) +{ + (void)qemu_try_set_nonblock(fd); +} + +int socket_set_fast_reuse(int fd) +{ + /* Enabling the reuse of an endpoint that was used by a socket still in + * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows + * fast reuse is the default and SO_REUSEADDR does strange things. So we + * don't have to do anything here. More info can be found at: + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */ + return 0; +} + int inet_aton(const char *cp, struct in_addr *ia) { uint32_t addr = inet_addr(cp); @@ -308,7 +315,7 @@ void qemu_set_tty_echo(int fd, bool echo) } } -static char exec_dir[PATH_MAX]; +static const char *exec_dir; void qemu_init_exec_dir(const char *argv0) { @@ -317,6 +324,10 @@ void qemu_init_exec_dir(const char *argv0) char buf[MAX_PATH]; DWORD len; + if (exec_dir) { + return; + } + len = GetModuleFileName(NULL, buf, sizeof(buf) - 1); if (len == 0) { return; @@ -329,13 +340,15 @@ void qemu_init_exec_dir(const char *argv0) } *p = 0; if (access(buf, R_OK) == 0) { - pstrcpy(exec_dir, sizeof(exec_dir), buf); + exec_dir = g_strdup(buf); + } else { + exec_dir = CONFIG_BINDIR; } } -char *qemu_get_exec_dir(void) +const char *qemu_get_exec_dir(void) { - return g_strdup(exec_dir); + return exec_dir; } #if !GLIB_CHECK_VERSION(2, 50, 0) @@ -360,7 +373,7 @@ char *qemu_get_exec_dir(void) * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -808,3 +821,27 @@ bool qemu_write_pidfile(const char *filename, Error **errp) } return true; } + +char *qemu_get_host_name(Error **errp) +{ + wchar_t tmp[MAX_COMPUTERNAME_LENGTH + 1]; + DWORD size = G_N_ELEMENTS(tmp); + + if (GetComputerNameW(tmp, &size) == 0) { + error_setg_win32(errp, GetLastError(), "failed close handle"); + return NULL; + } + + return g_utf16_to_utf8(tmp, size, NULL, NULL, NULL); +} + +size_t qemu_get_host_physmem(void) +{ + MEMORYSTATUSEX statex; + statex.dwLength = sizeof(statex); + + if (GlobalMemoryStatusEx(&statex)) { + return statex.ullTotalPhys; + } + return 0; +} diff --git a/util/qemu-config.c b/util/qemu-config.c index 772f5a219e9bc5469989de0db628a1958bb87284..660f47b0050f9bf54e2ee69f1f0d49315c650cb0 100644 --- a/util/qemu-config.c +++ b/util/qemu-config.c @@ -339,8 +339,7 @@ int qemu_set_option(const char *str) return -1; } - qemu_opt_set(opts, arg, str + offset + 1, &local_err); - if (local_err) { + if (!qemu_opt_set(opts, arg, str + offset + 1, &local_err)) { error_report_err(local_err); return -1; } @@ -441,8 +440,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname) error_report("no group defined"); goto out; } - qemu_opt_set(opts, arg, value, &local_err); - if (local_err) { + if (!qemu_opt_set(opts, arg, value, &local_err)) { error_report_err(local_err); goto out; } @@ -481,7 +479,6 @@ static void config_parse_qdict_section(QDict *options, QemuOptsList *opts, QemuOpts *subopts; QDict *subqdict; QList *list = NULL; - Error *local_err = NULL; size_t orig_size, enum_size; char *prefix; @@ -493,15 +490,12 @@ static void config_parse_qdict_section(QDict *options, QemuOptsList *opts, goto out; } - subopts = qemu_opts_create(opts, NULL, 0, &local_err); - if (local_err) { - error_propagate(errp, local_err); + subopts = qemu_opts_create(opts, NULL, 0, errp); + if (!subopts) { goto out; } - qemu_opts_absorb_qdict(subopts, subqdict, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(subopts, subqdict, errp)) { goto out; } @@ -538,16 +532,13 @@ static void config_parse_qdict_section(QDict *options, QemuOptsList *opts, } opt_name = g_strdup_printf("%s.%u", opts->name, i++); - subopts = qemu_opts_create(opts, opt_name, 1, &local_err); + subopts = qemu_opts_create(opts, opt_name, 1, errp); g_free(opt_name); - if (local_err) { - error_propagate(errp, local_err); + if (!subopts) { goto out; } - qemu_opts_absorb_qdict(subopts, section, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_absorb_qdict(subopts, section, errp)) { qemu_opts_del(subopts); goto out; } diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c index 5da5234155a66e648f7615e1eeeb9083ff568237..5816bf890094d4e87f72808abe0631a0cd5fb26f 100644 --- a/util/qemu-coroutine-lock.c +++ b/util/qemu-coroutine-lock.c @@ -85,15 +85,13 @@ static bool qemu_co_queue_do_restart(CoQueue *queue, bool single) return true; } -bool coroutine_fn qemu_co_queue_next(CoQueue *queue) +bool qemu_co_queue_next(CoQueue *queue) { - assert(qemu_in_coroutine()); return qemu_co_queue_do_restart(queue, true); } -void coroutine_fn qemu_co_queue_restart_all(CoQueue *queue) +void qemu_co_queue_restart_all(CoQueue *queue) { - assert(qemu_in_coroutine()); qemu_co_queue_do_restart(queue, false); } @@ -212,10 +210,10 @@ static void coroutine_fn qemu_co_mutex_lock_slowpath(AioContext *ctx, /* This is the "Responsibility Hand-Off" protocol; a lock() picks from * a concurrent unlock() the responsibility of waking somebody up. */ - old_handoff = atomic_mb_read(&mutex->handoff); + old_handoff = qatomic_mb_read(&mutex->handoff); if (old_handoff && has_waiters(mutex) && - atomic_cmpxchg(&mutex->handoff, old_handoff, 0) == old_handoff) { + qatomic_cmpxchg(&mutex->handoff, old_handoff, 0) == old_handoff) { /* There can be no concurrent pops, because there can be only * one active handoff at a time. */ @@ -250,18 +248,18 @@ void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex) */ i = 0; retry_fast_path: - waiters = atomic_cmpxchg(&mutex->locked, 0, 1); + waiters = qatomic_cmpxchg(&mutex->locked, 0, 1); if (waiters != 0) { while (waiters == 1 && ++i < 1000) { - if (atomic_read(&mutex->ctx) == ctx) { + if (qatomic_read(&mutex->ctx) == ctx) { break; } - if (atomic_read(&mutex->locked) == 0) { + if (qatomic_read(&mutex->locked) == 0) { goto retry_fast_path; } cpu_relax(); } - waiters = atomic_fetch_inc(&mutex->locked); + waiters = qatomic_fetch_inc(&mutex->locked); } if (waiters == 0) { @@ -288,7 +286,7 @@ void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex) mutex->ctx = NULL; mutex->holder = NULL; self->locks_held--; - if (atomic_fetch_dec(&mutex->locked) == 1) { + if (qatomic_fetch_dec(&mutex->locked) == 1) { /* No waiting qemu_co_mutex_lock(). Pfew, that was easy! */ return; } @@ -311,7 +309,7 @@ void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex) } our_handoff = mutex->sequence; - atomic_mb_set(&mutex->handoff, our_handoff); + qatomic_mb_set(&mutex->handoff, our_handoff); if (!has_waiters(mutex)) { /* The concurrent lock has not added itself yet, so it * will be able to pick our handoff. @@ -322,7 +320,7 @@ void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex) /* Try to do the handoff protocol ourselves; if somebody else has * already taken it, however, we're done and they're responsible. */ - if (atomic_cmpxchg(&mutex->handoff, our_handoff, 0) != our_handoff) { + if (qatomic_cmpxchg(&mutex->handoff, our_handoff, 0) != our_handoff) { break; } } diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c index 769a76e57df0950de3d9b624836becf08a67a296..8c4dac4fd75eeb12df3718b65f612de72dc7089c 100644 --- a/util/qemu-coroutine-sleep.c +++ b/util/qemu-coroutine-sleep.c @@ -28,7 +28,7 @@ struct QemuCoSleepState { void qemu_co_sleep_wake(QemuCoSleepState *sleep_state) { /* Write of schedule protected by barrier write in aio_co_schedule */ - const char *scheduled = atomic_cmpxchg(&sleep_state->co->scheduled, + const char *scheduled = qatomic_cmpxchg(&sleep_state->co->scheduled, qemu_co_sleep_ns__scheduled, NULL); assert(scheduled == qemu_co_sleep_ns__scheduled); @@ -54,7 +54,7 @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns, .user_state_pointer = sleep_state, }; - const char *scheduled = atomic_cmpxchg(&state.co->scheduled, NULL, + const char *scheduled = qatomic_cmpxchg(&state.co->scheduled, NULL, qemu_co_sleep_ns__scheduled); if (scheduled) { fprintf(stderr, diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c index c3caa6c770ca0a64d9c973a0d38c79fe24428985..38fb6d3084dad2dd2145134d9e5da8f03d7169fe 100644 --- a/util/qemu-coroutine.c +++ b/util/qemu-coroutine.c @@ -60,7 +60,7 @@ Coroutine *qemu_coroutine_create(CoroutineEntry *entry, void *opaque) * release_pool_size and the actual size of release_pool. But * it is just a heuristic, it does not need to be perfect. */ - alloc_pool_size = atomic_xchg(&release_pool_size, 0); + alloc_pool_size = qatomic_xchg(&release_pool_size, 0); QSLIST_MOVE_ATOMIC(&alloc_pool, &release_pool); co = QSLIST_FIRST(&alloc_pool); } @@ -88,7 +88,7 @@ static void coroutine_delete(Coroutine *co) if (CONFIG_COROUTINE_POOL) { if (release_pool_size < POOL_BATCH_SIZE * 2) { QSLIST_INSERT_HEAD_ATOMIC(&release_pool, co, pool_next); - atomic_inc(&release_pool_size); + qatomic_inc(&release_pool_size); return; } if (alloc_pool_size < POOL_BATCH_SIZE) { @@ -115,7 +115,7 @@ void qemu_aio_coroutine_enter(AioContext *ctx, Coroutine *co) /* Cannot rely on the read barrier for to in aio_co_wake(), as there are * callers outside of aio_co_wake() */ - const char *scheduled = atomic_mb_read(&to->scheduled); + const char *scheduled = qatomic_mb_read(&to->scheduled); QSIMPLEQ_REMOVE_HEAD(&pending, co_queue_next); diff --git a/util/qemu-error.c b/util/qemu-error.c index dac7c7dc502544678312badb985af6c960a56f4e..aa30f03564b90791f8cf9d930615610cb5e6783f 100644 --- a/util/qemu-error.c +++ b/util/qemu-error.c @@ -26,6 +26,8 @@ typedef enum { /* Prepend timestamp to messages */ bool error_with_timestamp; +bool error_with_guestname; +const char *error_guest_name; int error_printf(const char *fmt, ...) { @@ -169,7 +171,7 @@ static void print_loc(void) int i; const char *const *argp; - if (!cur_mon && progname) { + if (!monitor_cur() && progname) { fprintf(stderr, "%s:", progname); sep = " "; } @@ -206,13 +208,18 @@ static void vreport(report_type type, const char *fmt, va_list ap) GTimeVal tv; gchar *timestr; - if (error_with_timestamp && !cur_mon) { + if (error_with_timestamp && !monitor_cur()) { g_get_current_time(&tv); timestr = g_time_val_to_iso8601(&tv); error_printf("%s ", timestr); g_free(timestr); } + /* Only prepend guest name if -msg guest-name and -name guest=... are set */ + if (error_with_guestname && error_guest_name && !monitor_cur()) { + error_printf("%s ", error_guest_name); + } + print_loc(); switch (type) { diff --git a/util/qemu-openpty.c b/util/qemu-openpty.c index 2e8b43bdf571f968d975625960bd6bf07ae2222a..eb17f5b0bcec867e372d650cdc46c865ebe14ed3 100644 --- a/util/qemu-openpty.c +++ b/util/qemu-openpty.c @@ -35,7 +35,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" -#if defined(__GLIBC__) +#if defined HAVE_PTY_H # include #elif defined CONFIG_BSD # include @@ -52,7 +52,9 @@ #endif #ifdef __sun__ -/* Once Solaris has openpty(), this is going to be removed. */ + +#if !defined(HAVE_OPENPTY) +/* Once illumos has openpty(), this is going to be removed. */ static int openpty(int *amaster, int *aslave, char *name, struct termios *termp, struct winsize *winp) { @@ -93,6 +95,7 @@ err: close(mfd); return -1; } +#endif static void cfmakeraw (struct termios *termios_p) { diff --git a/util/qemu-option.c b/util/qemu-option.c index 0ebfd97a98a2a7c978787ee88f48251a7aa3e9db..acefbc23fa3c16baefc584ed6a531043f252ff25 100644 --- a/util/qemu-option.c +++ b/util/qemu-option.c @@ -96,20 +96,7 @@ const char *get_opt_value(const char *p, char **value) return offset; } -static void parse_option_bool(const char *name, const char *value, bool *ret, - Error **errp) -{ - if (!strcmp(value, "on")) { - *ret = 1; - } else if (!strcmp(value, "off")) { - *ret = 0; - } else { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, - name, "'on' or 'off'"); - } -} - -static void parse_option_number(const char *name, const char *value, +static bool parse_option_number(const char *name, const char *value, uint64_t *ret, Error **errp) { uint64_t number; @@ -119,13 +106,14 @@ static void parse_option_number(const char *name, const char *value, if (err == -ERANGE) { error_setg(errp, "Value '%s' is too large for parameter '%s'", value, name); - return; + return false; } if (err) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number"); - return; + return false; } *ret = number; + return true; } static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc, @@ -142,7 +130,14 @@ static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc, return NULL; } -void parse_option_size(const char *name, const char *value, +static const char *find_default_by_name(QemuOpts *opts, const char *name) +{ + const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name); + + return desc ? desc->def_value_str : NULL; +} + +bool parse_option_size(const char *name, const char *value, uint64_t *ret, Error **errp) { uint64_t size; @@ -152,7 +147,7 @@ void parse_option_size(const char *name, const char *value, if (err == -ERANGE) { error_setg(errp, "Value '%s' is out of range for parameter '%s'", value, name); - return; + return false; } if (err) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, @@ -160,9 +155,10 @@ void parse_option_size(const char *name, const char *value, error_append_hint(errp, "Optional suffix k, M, G, T, P or E means" " kilo-, mega-, giga-, tera-, peta-\n" "and exabytes, respectively.\n"); - return; + return false; } *ret = size; + return true; } static const char *opt_type_to_string(enum QemuOptType type) @@ -277,12 +273,10 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name) opt = qemu_opt_find(opts, name); if (!opt) { - const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name); - if (desc && desc->def_value_str) { - return desc->def_value_str; - } + return find_default_by_name(opts, name); } - return opt ? opt->str : NULL; + + return opt->str; } void qemu_opt_iter_init(QemuOptsIter *iter, QemuOpts *opts, const char *name) @@ -311,8 +305,7 @@ const char *qemu_opt_iter_next(QemuOptsIter *iter) char *qemu_opt_get_del(QemuOpts *opts, const char *name) { QemuOpt *opt; - const QemuOptDesc *desc; - char *str = NULL; + char *str; if (opts == NULL) { return NULL; @@ -320,11 +313,7 @@ char *qemu_opt_get_del(QemuOpts *opts, const char *name) opt = qemu_opt_find(opts, name); if (!opt) { - desc = find_desc_by_name(opts->list->desc, name); - if (desc && desc->def_value_str) { - str = g_strdup(desc->def_value_str); - } - return str; + return g_strdup(find_default_by_name(opts, name)); } str = opt->str; opt->str = NULL; @@ -348,6 +337,7 @@ static bool qemu_opt_get_bool_helper(QemuOpts *opts, const char *name, bool defval, bool del) { QemuOpt *opt; + const char *def_val; bool ret = defval; if (opts == NULL) { @@ -356,9 +346,9 @@ static bool qemu_opt_get_bool_helper(QemuOpts *opts, const char *name, opt = qemu_opt_find(opts, name); if (opt == NULL) { - const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name); - if (desc && desc->def_value_str) { - parse_option_bool(name, desc->def_value_str, &ret, &error_abort); + def_val = find_default_by_name(opts, name); + if (def_val) { + qapi_bool_parse(name, def_val, &ret, &error_abort); } return ret; } @@ -384,6 +374,7 @@ static uint64_t qemu_opt_get_number_helper(QemuOpts *opts, const char *name, uint64_t defval, bool del) { QemuOpt *opt; + const char *def_val; uint64_t ret = defval; if (opts == NULL) { @@ -392,9 +383,9 @@ static uint64_t qemu_opt_get_number_helper(QemuOpts *opts, const char *name, opt = qemu_opt_find(opts, name); if (opt == NULL) { - const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name); - if (desc && desc->def_value_str) { - parse_option_number(name, desc->def_value_str, &ret, &error_abort); + def_val = find_default_by_name(opts, name); + if (def_val) { + parse_option_number(name, def_val, &ret, &error_abort); } return ret; } @@ -421,6 +412,7 @@ static uint64_t qemu_opt_get_size_helper(QemuOpts *opts, const char *name, uint64_t defval, bool del) { QemuOpt *opt; + const char *def_val; uint64_t ret = defval; if (opts == NULL) { @@ -429,9 +421,9 @@ static uint64_t qemu_opt_get_size_helper(QemuOpts *opts, const char *name, opt = qemu_opt_find(opts, name); if (opt == NULL) { - const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name); - if (desc && desc->def_value_str) { - parse_option_size(name, desc->def_value_str, &ret, &error_abort); + def_val = find_default_by_name(opts, name); + if (def_val) { + parse_option_size(name, def_val, &ret, &error_abort); } return ret; } @@ -454,24 +446,23 @@ uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name, return qemu_opt_get_size_helper(opts, name, defval, true); } -static void qemu_opt_parse(QemuOpt *opt, Error **errp) +static bool qemu_opt_parse(QemuOpt *opt, Error **errp) { if (opt->desc == NULL) - return; + return true; switch (opt->desc->type) { case QEMU_OPT_STRING: /* nothing */ - return; + return true; case QEMU_OPT_BOOL: - parse_option_bool(opt->name, opt->str, &opt->value.boolean, errp); - break; + return qapi_bool_parse(opt->name, opt->str, &opt->value.boolean, errp); case QEMU_OPT_NUMBER: - parse_option_number(opt->name, opt->str, &opt->value.uint, errp); - break; + return parse_option_number(opt->name, opt->str, &opt->value.uint, + errp); case QEMU_OPT_SIZE: - parse_option_size(opt->name, opt->str, &opt->value.uint, errp); - break; + return parse_option_size(opt->name, opt->str, &opt->value.uint, + errp); default: abort(); } @@ -496,86 +487,99 @@ int qemu_opt_unset(QemuOpts *opts, const char *name) } } -static void opt_set(QemuOpts *opts, const char *name, char *value, - bool prepend, bool *help_wanted, Error **errp) +static QemuOpt *opt_create(QemuOpts *opts, const char *name, char *value, + bool prepend) { - QemuOpt *opt; - const QemuOptDesc *desc; - Error *local_err = NULL; + QemuOpt *opt = g_malloc0(sizeof(*opt)); - desc = find_desc_by_name(opts->list->desc, name); - if (!desc && !opts_accepts_any(opts)) { - g_free(value); - error_setg(errp, QERR_INVALID_PARAMETER, name); - if (help_wanted && is_help_option(name)) { - *help_wanted = true; - } - return; - } - - opt = g_malloc0(sizeof(*opt)); opt->name = g_strdup(name); + opt->str = value; opt->opts = opts; if (prepend) { QTAILQ_INSERT_HEAD(&opts->head, opt, next); } else { QTAILQ_INSERT_TAIL(&opts->head, opt, next); } + + return opt; +} + +static bool opt_validate(QemuOpt *opt, bool *help_wanted, + Error **errp) +{ + const QemuOptDesc *desc; + + desc = find_desc_by_name(opt->opts->list->desc, opt->name); + if (!desc && !opts_accepts_any(opt->opts)) { + error_setg(errp, QERR_INVALID_PARAMETER, opt->name); + if (help_wanted && is_help_option(opt->name)) { + *help_wanted = true; + } + return false; + } + opt->desc = desc; - opt->str = value; - qemu_opt_parse(opt, &local_err); - if (local_err) { - error_propagate(errp, local_err); - qemu_opt_del(opt); + if (!qemu_opt_parse(opt, errp)) { + return false; } + + return true; } -void qemu_opt_set(QemuOpts *opts, const char *name, const char *value, +bool qemu_opt_set(QemuOpts *opts, const char *name, const char *value, Error **errp) { - opt_set(opts, name, g_strdup(value), false, NULL, errp); + QemuOpt *opt = opt_create(opts, name, g_strdup(value), false); + + if (!opt_validate(opt, NULL, errp)) { + qemu_opt_del(opt); + return false; + } + return true; } -void qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val, +bool qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val, Error **errp) { QemuOpt *opt; - const QemuOptDesc *desc = opts->list->desc; + const QemuOptDesc *desc; - opt = g_malloc0(sizeof(*opt)); - opt->desc = find_desc_by_name(desc, name); - if (!opt->desc && !opts_accepts_any(opts)) { + desc = find_desc_by_name(opts->list->desc, name); + if (!desc && !opts_accepts_any(opts)) { error_setg(errp, QERR_INVALID_PARAMETER, name); - g_free(opt); - return; + return false; } + opt = g_malloc0(sizeof(*opt)); opt->name = g_strdup(name); opt->opts = opts; + opt->desc = desc; opt->value.boolean = !!val; opt->str = g_strdup(val ? "on" : "off"); QTAILQ_INSERT_TAIL(&opts->head, opt, next); + return true; } -void qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val, +bool qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val, Error **errp) { QemuOpt *opt; - const QemuOptDesc *desc = opts->list->desc; + const QemuOptDesc *desc; - opt = g_malloc0(sizeof(*opt)); - opt->desc = find_desc_by_name(desc, name); - if (!opt->desc && !opts_accepts_any(opts)) { + desc = find_desc_by_name(opts->list->desc, name); + if (!desc && !opts_accepts_any(opts)) { error_setg(errp, QERR_INVALID_PARAMETER, name); - g_free(opt); - return; + return false; } + opt = g_malloc0(sizeof(*opt)); opt->name = g_strdup(name); opt->opts = opts; + opt->desc = desc; opt->value.uint = val; opt->str = g_strdup_printf("%" PRId64, val); QTAILQ_INSERT_TAIL(&opts->head, opt, next); + return true; } /** @@ -666,18 +670,16 @@ void qemu_opts_loc_restore(QemuOpts *opts) loc_restore(&opts->loc); } -void qemu_opts_set(QemuOptsList *list, const char *id, +bool qemu_opts_set(QemuOptsList *list, const char *id, const char *name, const char *value, Error **errp) { QemuOpts *opts; - Error *local_err = NULL; - opts = qemu_opts_create(list, id, 1, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; + opts = qemu_opts_create(list, id, 1, errp); + if (!opts) { + return false; } - qemu_opt_set(opts, name, value, errp); + return qemu_opt_set(opts, name, value, errp); } const char *qemu_opts_id(QemuOpts *opts) @@ -803,13 +805,13 @@ static const char *get_opt_name_value(const char *params, return p; } -static void opts_do_parse(QemuOpts *opts, const char *params, +static bool opts_do_parse(QemuOpts *opts, const char *params, const char *firstname, bool prepend, bool *help_wanted, Error **errp) { - Error *local_err = NULL; char *option, *value; const char *p; + QemuOpt *opt; for (p = params; *p;) { p = get_opt_name_value(p, firstname, &option, &value); @@ -821,13 +823,15 @@ static void opts_do_parse(QemuOpts *opts, const char *params, continue; } - opt_set(opts, option, value, prepend, help_wanted, &local_err); + opt = opt_create(opts, option, value, prepend); g_free(option); - if (local_err) { - error_propagate(errp, local_err); - return; + if (!opt_validate(opt, help_wanted, errp)) { + qemu_opt_del(opt); + return false; } } + + return true; } static char *opts_parse_id(const char *params) @@ -873,10 +877,10 @@ bool has_help_option(const char *params) * key=, and is treated as if key was @firstname. * On error, store an error object through @errp if non-null. */ -void qemu_opts_do_parse(QemuOpts *opts, const char *params, +bool qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname, Error **errp) { - opts_do_parse(opts, params, firstname, false, NULL, errp); + return opts_do_parse(opts, params, firstname, false, NULL, errp); } static QemuOpts *opts_parse(QemuOptsList *list, const char *params, @@ -886,7 +890,6 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, const char *firstname; char *id = opts_parse_id(params); QemuOpts *opts; - Error *local_err = NULL; assert(!permit_abbrev || list->implied_opt_name); firstname = permit_abbrev ? list->implied_opt_name : NULL; @@ -899,16 +902,14 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, * (if unlikely) future misuse: */ assert(!defaults || list->merge_lists); - opts = qemu_opts_create(list, id, !defaults, &local_err); + opts = qemu_opts_create(list, id, !defaults, errp); g_free(id); if (opts == NULL) { - error_propagate(errp, local_err); return NULL; } - opts_do_parse(opts, params, firstname, defaults, help_wanted, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!opts_do_parse(opts, params, firstname, defaults, help_wanted, + errp)) { qemu_opts_del(opts); return NULL; } @@ -965,17 +966,18 @@ void qemu_opts_set_defaults(QemuOptsList *list, const char *params, assert(opts); } -static void qemu_opts_from_qdict_entry(QemuOpts *opts, +static bool qemu_opts_from_qdict_entry(QemuOpts *opts, const QDictEntry *entry, Error **errp) { const char *key = qdict_entry_key(entry); QObject *obj = qdict_entry_value(entry); - char buf[32], *tmp = NULL; + char buf[32]; + g_autofree char *tmp = NULL; const char *value; if (!strcmp(key, "id")) { - return; + return true; } switch (qobject_type(obj)) { @@ -992,11 +994,10 @@ static void qemu_opts_from_qdict_entry(QemuOpts *opts, value = buf; break; default: - return; + return true; } - qemu_opt_set(opts, key, value, errp); - g_free(tmp); + return qemu_opt_set(opts, key, value, errp); } /* @@ -1008,14 +1009,11 @@ static void qemu_opts_from_qdict_entry(QemuOpts *opts, QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict, Error **errp) { - Error *local_err = NULL; QemuOpts *opts; const QDictEntry *entry; - opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1, - &local_err); - if (local_err) { - error_propagate(errp, local_err); + opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1, errp); + if (!opts) { return NULL; } @@ -1024,9 +1022,7 @@ QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict, for (entry = qdict_first(qdict); entry; entry = qdict_next(qdict, entry)) { - qemu_opts_from_qdict_entry(opts, entry, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!qemu_opts_from_qdict_entry(opts, entry, errp)) { qemu_opts_del(opts); return NULL; } @@ -1040,28 +1036,26 @@ QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict, * from the QDict. When this function returns, the QDict contains only those * entries that couldn't be added to the QemuOpts. */ -void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp) +bool qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp) { const QDictEntry *entry, *next; entry = qdict_first(qdict); while (entry != NULL) { - Error *local_err = NULL; - next = qdict_next(qdict, entry); if (find_desc_by_name(opts->list->desc, entry->key)) { - qemu_opts_from_qdict_entry(opts, entry, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; + if (!qemu_opts_from_qdict_entry(opts, entry, errp)) { + return false; } qdict_del(qdict, entry->key); } entry = next; } + + return true; } /* @@ -1121,10 +1115,9 @@ QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict) /* Validate parsed opts against descriptions where no * descriptions were provided in the QemuOptsList. */ -void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp) +bool qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp) { QemuOpt *opt; - Error *local_err = NULL; assert(opts_accepts_any(opts)); @@ -1132,15 +1125,15 @@ void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp) opt->desc = find_desc_by_name(desc, opt->name); if (!opt->desc) { error_setg(errp, QERR_INVALID_PARAMETER, opt->name); - return; + return false; } - qemu_opt_parse(opt, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; + if (!qemu_opt_parse(opt, errp)) { + return false; } } + + return true; } /** diff --git a/util/qemu-print.c b/util/qemu-print.c index e79d6b839696ee27af4f5e5479ab6eea6520a12f..69ba612f564e04ca86afa3a5ea088c4b7b7d1209 100644 --- a/util/qemu-print.c +++ b/util/qemu-print.c @@ -20,6 +20,7 @@ */ int qemu_vprintf(const char *fmt, va_list ap) { + Monitor *cur_mon = monitor_cur(); if (cur_mon) { return monitor_vprintf(cur_mon, fmt, ap); } @@ -48,7 +49,7 @@ int qemu_printf(const char *fmt, ...) int qemu_vfprintf(FILE *stream, const char *fmt, va_list ap) { if (!stream) { - return monitor_vprintf(cur_mon, fmt, ap); + return monitor_vprintf(monitor_cur(), fmt, ap); } return vfprintf(stream, fmt, ap); } diff --git a/util/qemu-progress.c b/util/qemu-progress.c index 3c2223c1a21cd3173fe86cf96e44fce3e3bb9299..20d51f8c128b3412b8389e34bbff44b7d2e068ba 100644 --- a/util/qemu-progress.c +++ b/util/qemu-progress.c @@ -131,7 +131,7 @@ void qemu_progress_end(void) /* * Report progress. * @delta is how much progress we made. - * If @max is zero, @delta is an absolut value of the total job done. + * If @max is zero, @delta is an absolute value of the total job done. * Else, @delta is a progress delta since the last call, as a fraction * of @max. I.e. the delta is @delta * @max / 100. This allows * relative accounting of functions which may be a different fraction of diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index b37d288866c509918ef282e005488a269858eda6..8af0278f15c69fea136192e91650cef99c056e39 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -354,15 +354,15 @@ listen_ok: ((rc) == -EINPROGRESS) #endif -static int inet_connect_addr(struct addrinfo *addr, Error **errp); - -static int inet_connect_addr(struct addrinfo *addr, Error **errp) +static int inet_connect_addr(const InetSocketAddress *saddr, + struct addrinfo *addr, Error **errp) { int sock, rc; sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if (sock < 0) { - error_setg_errno(errp, errno, "Failed to create socket"); + error_setg_errno(errp, errno, "Failed to create socket family %d", + addr->ai_family); return -1; } socket_set_fast_reuse(sock); @@ -376,7 +376,8 @@ static int inet_connect_addr(struct addrinfo *addr, Error **errp) } while (rc == -EINTR); if (rc < 0) { - error_setg_errno(errp, errno, "Failed to connect socket"); + error_setg_errno(errp, errno, "Failed to connect to '%s:%s'", + saddr->host, saddr->port); closesocket(sock); return -1; } @@ -395,7 +396,7 @@ static struct addrinfo *inet_parse_connect_saddr(InetSocketAddress *saddr, memset(&ai, 0, sizeof(ai)); ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; - if (atomic_read(&useV4Mapped)) { + if (qatomic_read(&useV4Mapped)) { ai.ai_flags |= AI_V4MAPPED; } ai.ai_family = inet_ai_family_from_address(saddr, &err); @@ -416,12 +417,12 @@ static struct addrinfo *inet_parse_connect_saddr(InetSocketAddress *saddr, /* At least FreeBSD and OS-X 10.6 declare AI_V4MAPPED but * then don't implement it in their getaddrinfo(). Detect - * this and retry without the flag since that's preferrable + * this and retry without the flag since that's preferable * to a fatal error */ if (rc == EAI_BADFLAGS && (ai.ai_flags & AI_V4MAPPED)) { - atomic_set(&useV4Mapped, 0); + qatomic_set(&useV4Mapped, 0); ai.ai_flags &= ~AI_V4MAPPED; rc = getaddrinfo(saddr->host, saddr->port, &ai, &res); } @@ -455,7 +456,7 @@ int inet_connect_saddr(InetSocketAddress *saddr, Error **errp) for (e = res; e != NULL; e = e->ai_next) { error_free(local_err); local_err = NULL; - sock = inet_connect_addr(e, &local_err); + sock = inet_connect_addr(saddr, e, &local_err); if (sock >= 0) { break; } @@ -549,7 +550,8 @@ static int inet_dgram_saddr(InetSocketAddress *sraddr, /* create socket */ sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol); if (sock < 0) { - error_setg_errno(errp, errno, "Failed to create socket"); + error_setg_errno(errp, errno, "Failed to create socket family %d", + peer->ai_family); goto err; } socket_set_fast_reuse(sock); @@ -562,7 +564,8 @@ static int inet_dgram_saddr(InetSocketAddress *sraddr, /* connect to peer */ if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) { - error_setg_errno(errp, errno, "Failed to connect socket"); + error_setg_errno(errp, errno, "Failed to connect to '%s:%s'", + addr, port); goto err; } @@ -735,13 +738,15 @@ static bool vsock_parse_vaddr_to_sockaddr(const VsockSocketAddress *vaddr, return true; } -static int vsock_connect_addr(const struct sockaddr_vm *svm, Error **errp) +static int vsock_connect_addr(const VsockSocketAddress *vaddr, + const struct sockaddr_vm *svm, Error **errp) { int sock, rc; sock = qemu_socket(AF_VSOCK, SOCK_STREAM, 0); if (sock < 0) { - error_setg_errno(errp, errno, "Failed to create socket"); + error_setg_errno(errp, errno, "Failed to create socket family %d", + AF_VSOCK); return -1; } @@ -754,7 +759,8 @@ static int vsock_connect_addr(const struct sockaddr_vm *svm, Error **errp) } while (rc == -EINTR); if (rc < 0) { - error_setg_errno(errp, errno, "Failed to connect socket"); + error_setg_errno(errp, errno, "Failed to connect to '%s:%s'", + vaddr->cid, vaddr->port); closesocket(sock); return -1; } @@ -770,7 +776,7 @@ static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp) return -1; } - return vsock_connect_addr(&svm, errp); + return vsock_connect_addr(vaddr, &svm, errp); } static int vsock_listen_saddr(VsockSocketAddress *vaddr, @@ -854,10 +860,29 @@ static int vsock_parse(VsockSocketAddress *addr, const char *str, #ifndef _WIN32 +static bool saddr_is_abstract(UnixSocketAddress *saddr) +{ +#ifdef CONFIG_LINUX + return saddr->abstract; +#else + return false; +#endif +} + +static bool saddr_is_tight(UnixSocketAddress *saddr) +{ +#ifdef CONFIG_LINUX + return !saddr->has_tight || saddr->tight; +#else + return false; +#endif +} + static int unix_listen_saddr(UnixSocketAddress *saddr, int num, Error **errp) { + bool abstract = saddr_is_abstract(saddr); struct sockaddr_un un; int sock, fd; char *pathbuf = NULL; @@ -871,7 +896,7 @@ static int unix_listen_saddr(UnixSocketAddress *saddr, return -1; } - if (saddr->path && saddr->path[0]) { + if (saddr->path[0] || abstract) { path = saddr->path; } else { const char *tmpdir = getenv("TMPDIR"); @@ -881,10 +906,10 @@ static int unix_listen_saddr(UnixSocketAddress *saddr, pathlen = strlen(path); if (pathlen > sizeof(un.sun_path) || - (saddr->abstract && pathlen > (sizeof(un.sun_path) - 1))) { + (abstract && pathlen > (sizeof(un.sun_path) - 1))) { error_setg(errp, "UNIX socket path '%s' is too long", path); error_append_hint(errp, "Path must be less than %zu bytes\n", - saddr->abstract ? sizeof(un.sun_path) - 1 : + abstract ? sizeof(un.sun_path) - 1 : sizeof(un.sun_path)); goto err; } @@ -906,7 +931,7 @@ static int unix_listen_saddr(UnixSocketAddress *saddr, close(fd); } - if (!saddr->abstract && unlink(path) < 0 && errno != ENOENT) { + if (!abstract && unlink(path) < 0 && errno != ENOENT) { error_setg_errno(errp, errno, "Failed to unlink socket %s", path); goto err; @@ -916,10 +941,10 @@ static int unix_listen_saddr(UnixSocketAddress *saddr, un.sun_family = AF_UNIX; addrlen = sizeof(un); - if (saddr->abstract) { + if (abstract) { un.sun_path[0] = '\0'; memcpy(&un.sun_path[1], path, pathlen); - if (saddr->tight) { + if (saddr_is_tight(saddr)) { addrlen = offsetof(struct sockaddr_un, sun_path) + 1 + pathlen; } } else { @@ -946,6 +971,7 @@ err: static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) { + bool abstract = saddr_is_abstract(saddr); struct sockaddr_un un; int sock, rc; size_t pathlen; @@ -964,10 +990,10 @@ static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) pathlen = strlen(saddr->path); if (pathlen > sizeof(un.sun_path) || - (saddr->abstract && pathlen > (sizeof(un.sun_path) - 1))) { + (abstract && pathlen > (sizeof(un.sun_path) - 1))) { error_setg(errp, "UNIX socket path '%s' is too long", saddr->path); error_append_hint(errp, "Path must be less than %zu bytes\n", - saddr->abstract ? sizeof(un.sun_path) - 1 : + abstract ? sizeof(un.sun_path) - 1 : sizeof(un.sun_path)); goto err; } @@ -976,10 +1002,10 @@ static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) un.sun_family = AF_UNIX; addrlen = sizeof(un); - if (saddr->abstract) { + if (abstract) { un.sun_path[0] = '\0'; memcpy(&un.sun_path[1], saddr->path, pathlen); - if (saddr->tight) { + if (saddr_is_tight(saddr)) { addrlen = offsetof(struct sockaddr_un, sun_path) + 1 + pathlen; } } else { @@ -994,7 +1020,7 @@ static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) } while (rc == -EINTR); if (rc < 0) { - error_setg_errno(errp, -rc, "Failed to connect socket %s", + error_setg_errno(errp, -rc, "Failed to connect to '%s'", saddr->path); goto err; } @@ -1092,6 +1118,7 @@ fail: static int socket_get_fd(const char *fdstr, int num, Error **errp) { + Monitor *cur_mon = monitor_cur(); int fd; if (num != 1) { error_setg_errno(errp, EINVAL, "socket_get_fd: too many connections"); @@ -1263,10 +1290,20 @@ socket_sockaddr_to_address_unix(struct sockaddr_storage *sa, addr = g_new0(SocketAddress, 1); addr->type = SOCKET_ADDRESS_TYPE_UNIX; - if (su->sun_path[0]) { - addr->u.q_unix.path = g_strndup(su->sun_path, sizeof(su->sun_path)); +#ifdef CONFIG_LINUX + if (!su->sun_path[0]) { + /* Linux abstract socket */ + addr->u.q_unix.path = g_strndup(su->sun_path + 1, + sizeof(su->sun_path) - 1); + addr->u.q_unix.has_abstract = true; + addr->u.q_unix.abstract = true; + addr->u.q_unix.has_tight = true; + addr->u.q_unix.tight = salen < sizeof(*su); + return addr; } +#endif + addr->u.q_unix.path = g_strndup(su->sun_path, sizeof(su->sun_path)); return addr; } #endif /* WIN32 */ diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c index 838980aaa55b480c7b7303bdcc69d515084b0246..dcff5e7c5d676a357785c9f10f1a955cea7d5cfc 100644 --- a/util/qemu-thread-posix.c +++ b/util/qemu-thread-posix.c @@ -15,6 +15,7 @@ #include "qemu/atomic.h" #include "qemu/notify.h" #include "qemu-thread-common.h" +#include "qemu/tsan.h" static bool name_threads; @@ -413,8 +414,8 @@ void qemu_event_set(QemuEvent *ev) */ assert(ev->initialized); smp_mb(); - if (atomic_read(&ev->value) != EV_SET) { - if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) { + if (qatomic_read(&ev->value) != EV_SET) { + if (qatomic_xchg(&ev->value, EV_SET) == EV_BUSY) { /* There were waiters, wake them up. */ qemu_futex_wake(ev, INT_MAX); } @@ -426,14 +427,14 @@ void qemu_event_reset(QemuEvent *ev) unsigned value; assert(ev->initialized); - value = atomic_read(&ev->value); + value = qatomic_read(&ev->value); smp_mb_acquire(); if (value == EV_SET) { /* * If there was a concurrent reset (or even reset+wait), * do nothing. Otherwise change EV_SET->EV_FREE. */ - atomic_or(&ev->value, EV_FREE); + qatomic_or(&ev->value, EV_FREE); } } @@ -442,7 +443,7 @@ void qemu_event_wait(QemuEvent *ev) unsigned value; assert(ev->initialized); - value = atomic_read(&ev->value); + value = qatomic_read(&ev->value); smp_mb_acquire(); if (value != EV_SET) { if (value == EV_FREE) { @@ -452,7 +453,7 @@ void qemu_event_wait(QemuEvent *ev) * a concurrent busy->free transition. After the CAS, the * event will be either set or busy. */ - if (atomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) { + if (qatomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) { return; } } @@ -513,6 +514,7 @@ static void *qemu_thread_start(void *args) # endif } #endif + QEMU_TSAN_ANNOTATE_THREAD_NAME(qemu_thread_args->name); g_free(qemu_thread_args->name); g_free(qemu_thread_args); pthread_cleanup_push(qemu_thread_atexit_notify, NULL); diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c index 56a83333da6da80b4a11222a77bd9f5fa253b533..cb5aa2018c3ada10e9af087bdd729254ef3c7c5d 100644 --- a/util/qemu-thread-win32.c +++ b/util/qemu-thread-win32.c @@ -250,8 +250,8 @@ void qemu_event_set(QemuEvent *ev) * ev->value we need a full memory barrier here. */ smp_mb(); - if (atomic_read(&ev->value) != EV_SET) { - if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) { + if (qatomic_read(&ev->value) != EV_SET) { + if (qatomic_xchg(&ev->value, EV_SET) == EV_BUSY) { /* There were waiters, wake them up. */ SetEvent(ev->event); } @@ -263,13 +263,13 @@ void qemu_event_reset(QemuEvent *ev) unsigned value; assert(ev->initialized); - value = atomic_read(&ev->value); + value = qatomic_read(&ev->value); smp_mb_acquire(); if (value == EV_SET) { /* If there was a concurrent reset (or even reset+wait), * do nothing. Otherwise change EV_SET->EV_FREE. */ - atomic_or(&ev->value, EV_FREE); + qatomic_or(&ev->value, EV_FREE); } } @@ -278,7 +278,7 @@ void qemu_event_wait(QemuEvent *ev) unsigned value; assert(ev->initialized); - value = atomic_read(&ev->value); + value = qatomic_read(&ev->value); smp_mb_acquire(); if (value != EV_SET) { if (value == EV_FREE) { @@ -289,10 +289,10 @@ void qemu_event_wait(QemuEvent *ev) ResetEvent(ev->event); /* Tell qemu_event_set that there are waiters. No need to retry - * because there cannot be a concurent busy->free transition. + * because there cannot be a concurrent busy->free transition. * After the CAS, the event will be either set or busy. */ - if (atomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) { + if (qatomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) { value = EV_SET; } else { value = EV_BUSY; diff --git a/util/qemu-timer.c b/util/qemu-timer.c index b6575a2cd524f0b729ba05383d5ec81c8a305ce6..81c28af517e2a0aa399d854eb97d9f411138b5f4 100644 --- a/util/qemu-timer.c +++ b/util/qemu-timer.c @@ -26,8 +26,10 @@ #include "qemu/main-loop.h" #include "qemu/timer.h" #include "qemu/lockable.h" +#include "sysemu/cpu-timers.h" #include "sysemu/replay.h" #include "sysemu/cpus.h" +#include "sysemu/qtest.h" #ifdef CONFIG_POSIX #include @@ -134,7 +136,7 @@ static void qemu_clock_init(QEMUClockType type, QEMUTimerListNotifyCB *notify_cb bool qemu_clock_use_for_deadline(QEMUClockType type) { - return !(use_icount && (type == QEMU_CLOCK_VIRTUAL)); + return !(icount_enabled() && (type == QEMU_CLOCK_VIRTUAL)); } void qemu_clock_notify(QEMUClockType type) @@ -170,7 +172,7 @@ void qemu_clock_enable(QEMUClockType type, bool enabled) bool timerlist_has_timers(QEMUTimerList *timer_list) { - return !!atomic_read(&timer_list->active_timers); + return !!qatomic_read(&timer_list->active_timers); } bool qemu_clock_has_timers(QEMUClockType type) @@ -183,7 +185,7 @@ bool timerlist_expired(QEMUTimerList *timer_list) { int64_t expire_time; - if (!atomic_read(&timer_list->active_timers)) { + if (!qatomic_read(&timer_list->active_timers)) { return false; } @@ -213,7 +215,7 @@ int64_t timerlist_deadline_ns(QEMUTimerList *timer_list) int64_t delta; int64_t expire_time; - if (!atomic_read(&timer_list->active_timers)) { + if (!qatomic_read(&timer_list->active_timers)) { return -1; } @@ -385,7 +387,7 @@ static void timer_del_locked(QEMUTimerList *timer_list, QEMUTimer *ts) if (!t) break; if (t == ts) { - atomic_set(pt, t->next); + qatomic_set(pt, t->next); break; } pt = &t->next; @@ -408,7 +410,7 @@ static bool timer_mod_ns_locked(QEMUTimerList *timer_list, } ts->expire_time = MAX(expire_time, 0); ts->next = *pt; - atomic_set(pt, ts); + qatomic_set(pt, ts); return pt == &timer_list->active_timers; } @@ -416,8 +418,8 @@ static bool timer_mod_ns_locked(QEMUTimerList *timer_list, static void timerlist_rearm(QEMUTimerList *timer_list) { /* Interrupt execution to force deadline recalculation. */ - if (timer_list->clock->type == QEMU_CLOCK_VIRTUAL) { - qemu_start_warp_timer(); + if (icount_enabled() && timer_list->clock->type == QEMU_CLOCK_VIRTUAL) { + icount_start_warp_timer(); } timerlist_notify(timer_list); } @@ -501,9 +503,8 @@ bool timerlist_run_timers(QEMUTimerList *timer_list) bool progress = false; QEMUTimerCB *cb; void *opaque; - bool need_replay_checkpoint = false; - if (!atomic_read(&timer_list->active_timers)) { + if (!qatomic_read(&timer_list->active_timers)) { return false; } @@ -517,16 +518,6 @@ bool timerlist_run_timers(QEMUTimerList *timer_list) break; default: case QEMU_CLOCK_VIRTUAL: - if (replay_mode != REPLAY_MODE_NONE) { - /* Checkpoint for virtual clock is redundant in cases where - * it's being triggered with only non-EXTERNAL timers, because - * these timers don't change guest state directly. - * Since it has conditional dependence on specific timers, it is - * subject to race conditions and requires special handling. - * See below. - */ - need_replay_checkpoint = true; - } break; case QEMU_CLOCK_HOST: if (!replay_checkpoint(CHECKPOINT_CLOCK_HOST)) { @@ -541,7 +532,7 @@ bool timerlist_run_timers(QEMUTimerList *timer_list) } /* - * Extract expired timers from active timers list and and process them. + * Extract expired timers from active timers list and process them. * * In rr mode we need "filtered" checkpointing for virtual clock. The * checkpoint must be recorded/replayed before processing any non-EXTERNAL timer, @@ -559,19 +550,16 @@ bool timerlist_run_timers(QEMUTimerList *timer_list) */ break; } - if (need_replay_checkpoint - && !(ts->attributes & QEMU_TIMER_ATTR_EXTERNAL)) { - /* once we got here, checkpoint clock only once */ - need_replay_checkpoint = false; + /* Checkpoint for virtual clock is redundant in cases where + * it's being triggered with only non-EXTERNAL timers, because + * these timers don't change guest state directly. + */ + if (replay_mode != REPLAY_MODE_NONE + && timer_list->clock->type == QEMU_CLOCK_VIRTUAL + && !(ts->attributes & QEMU_TIMER_ATTR_EXTERNAL) + && !replay_checkpoint(CHECKPOINT_CLOCK_VIRTUAL)) { qemu_mutex_unlock(&timer_list->active_timers_lock); - if (!replay_checkpoint(CHECKPOINT_CLOCK_VIRTUAL)) { - goto out; - } - qemu_mutex_lock(&timer_list->active_timers_lock); - /* The lock was released; start over again in case the list was - * modified. - */ - continue; + goto out; } /* remove timer from the list before calling the callback */ @@ -647,11 +635,7 @@ int64_t qemu_clock_get_ns(QEMUClockType type) return get_clock(); default: case QEMU_CLOCK_VIRTUAL: - if (use_icount) { - return cpu_get_icount(); - } else { - return cpu_get_clock(); - } + return cpus_get_virtual_clock(); case QEMU_CLOCK_HOST: return REPLAY_CLOCK(REPLAY_CLOCK_HOST, get_clock_realtime()); case QEMU_CLOCK_VIRTUAL_RT: diff --git a/util/qht.c b/util/qht.c index aa51be3c52f891dc55990231ba959a9c585b5b77..079605121b1452dac9937b0e6137d88eaf029946 100644 --- a/util/qht.c +++ b/util/qht.c @@ -49,7 +49,7 @@ * it anymore. * * Writers check for concurrent resizes by comparing ht->map before and after - * acquiring their bucket lock. If they don't match, a resize has occured + * acquiring their bucket lock. If they don't match, a resize has occurred * while the bucket spinlock was being acquired. * * Related Work: @@ -131,11 +131,11 @@ static inline void qht_unlock(struct qht *ht) /* * Note: reading partially-updated pointers in @pointers could lead to - * segfaults. We thus access them with atomic_read/set; this guarantees + * segfaults. We thus access them with qatomic_read/set; this guarantees * that the compiler makes all those accesses atomic. We also need the - * volatile-like behavior in atomic_read, since otherwise the compiler + * volatile-like behavior in qatomic_read, since otherwise the compiler * might refetch the pointer. - * atomic_read's are of course not necessary when the bucket lock is held. + * qatomic_read's are of course not necessary when the bucket lock is held. * * If both ht->lock and b->lock are grabbed, ht->lock should always * be grabbed first. @@ -286,7 +286,7 @@ void qht_map_lock_buckets__no_stale(struct qht *ht, struct qht_map **pmap) { struct qht_map *map; - map = atomic_rcu_read(&ht->map); + map = qatomic_rcu_read(&ht->map); qht_map_lock_buckets(map); if (likely(!qht_map_is_stale__locked(ht, map))) { *pmap = map; @@ -318,7 +318,7 @@ struct qht_bucket *qht_bucket_lock__no_stale(struct qht *ht, uint32_t hash, struct qht_bucket *b; struct qht_map *map; - map = atomic_rcu_read(&ht->map); + map = qatomic_rcu_read(&ht->map); b = qht_map_to_bucket(map, hash); qemu_spin_lock(&b->lock); @@ -340,7 +340,8 @@ struct qht_bucket *qht_bucket_lock__no_stale(struct qht *ht, uint32_t hash, static inline bool qht_map_needs_resize(const struct qht_map *map) { - return atomic_read(&map->n_added_buckets) > map->n_added_buckets_threshold; + return qatomic_read(&map->n_added_buckets) > + map->n_added_buckets_threshold; } static inline void qht_chain_destroy(const struct qht_bucket *head) @@ -348,6 +349,7 @@ static inline void qht_chain_destroy(const struct qht_bucket *head) struct qht_bucket *curr = head->next; struct qht_bucket *prev; + qemu_spin_destroy(&head->lock); while (curr) { prev = curr; curr = curr->next; @@ -403,7 +405,7 @@ void qht_init(struct qht *ht, qht_cmp_func_t cmp, size_t n_elems, ht->mode = mode; qemu_mutex_init(&ht->lock); map = qht_map_create(n_buckets); - atomic_rcu_set(&ht->map, map); + qatomic_rcu_set(&ht->map, map); } /* call only when there are no readers/writers left */ @@ -424,8 +426,8 @@ static void qht_bucket_reset__locked(struct qht_bucket *head) if (b->pointers[i] == NULL) { goto done; } - atomic_set(&b->hashes[i], 0); - atomic_set(&b->pointers[i], NULL); + qatomic_set(&b->hashes[i], 0); + qatomic_set(&b->pointers[i], NULL); } b = b->next; } while (b); @@ -491,19 +493,19 @@ void *qht_do_lookup(const struct qht_bucket *head, qht_lookup_func_t func, do { for (i = 0; i < QHT_BUCKET_ENTRIES; i++) { - if (atomic_read(&b->hashes[i]) == hash) { + if (qatomic_read(&b->hashes[i]) == hash) { /* The pointer is dereferenced before seqlock_read_retry, * so (unlike qht_insert__locked) we need to use - * atomic_rcu_read here. + * qatomic_rcu_read here. */ - void *p = atomic_rcu_read(&b->pointers[i]); + void *p = qatomic_rcu_read(&b->pointers[i]); if (likely(p) && likely(func(p, userp))) { return p; } } } - b = atomic_rcu_read(&b->next); + b = qatomic_rcu_read(&b->next); } while (b); return NULL; @@ -531,7 +533,7 @@ void *qht_lookup_custom(const struct qht *ht, const void *userp, uint32_t hash, unsigned int version; void *ret; - map = atomic_rcu_read(&ht->map); + map = qatomic_rcu_read(&ht->map); b = qht_map_to_bucket(map, hash); version = seqlock_read_begin(&b->sequence); @@ -583,7 +585,7 @@ static void *qht_insert__locked(const struct qht *ht, struct qht_map *map, memset(b, 0, sizeof(*b)); new = b; i = 0; - atomic_inc(&map->n_added_buckets); + qatomic_inc(&map->n_added_buckets); if (unlikely(qht_map_needs_resize(map)) && needs_resize) { *needs_resize = true; } @@ -592,11 +594,11 @@ static void *qht_insert__locked(const struct qht *ht, struct qht_map *map, /* found an empty key: acquire the seqlock and write */ seqlock_write_begin(&head->sequence); if (new) { - atomic_rcu_set(&prev->next, b); + qatomic_rcu_set(&prev->next, b); } /* smp_wmb() implicit in seqlock_write_begin. */ - atomic_set(&b->hashes[i], hash); - atomic_set(&b->pointers[i], p); + qatomic_set(&b->hashes[i], hash); + qatomic_set(&b->pointers[i], p); seqlock_write_end(&head->sequence); return NULL; } @@ -667,11 +669,11 @@ qht_entry_move(struct qht_bucket *to, int i, struct qht_bucket *from, int j) qht_debug_assert(to->pointers[i]); qht_debug_assert(from->pointers[j]); - atomic_set(&to->hashes[i], from->hashes[j]); - atomic_set(&to->pointers[i], from->pointers[j]); + qatomic_set(&to->hashes[i], from->hashes[j]); + qatomic_set(&to->pointers[i], from->pointers[j]); - atomic_set(&from->hashes[j], 0); - atomic_set(&from->pointers[j], NULL); + qatomic_set(&from->hashes[j], 0); + qatomic_set(&from->pointers[j], NULL); } /* @@ -686,7 +688,7 @@ static inline void qht_bucket_remove_entry(struct qht_bucket *orig, int pos) if (qht_entry_is_last(orig, pos)) { orig->hashes[pos] = 0; - atomic_set(&orig->pointers[pos], NULL); + qatomic_set(&orig->pointers[pos], NULL); return; } do { @@ -802,7 +804,7 @@ do_qht_iter(struct qht *ht, const struct qht_iter *iter, void *userp) { struct qht_map *map; - map = atomic_rcu_read(&ht->map); + map = qatomic_rcu_read(&ht->map); qht_map_lock_buckets(map); qht_map_iter__all_locked(map, iter, userp); qht_map_unlock_buckets(map); @@ -875,7 +877,7 @@ static void qht_do_resize_reset(struct qht *ht, struct qht_map *new, bool reset) qht_map_iter__all_locked(old, &iter, &data); qht_map_debug__all_locked(new); - atomic_rcu_set(&ht->map, new); + qatomic_rcu_set(&ht->map, new); qht_map_unlock_buckets(old); call_rcu(old, qht_map_destroy, rcu); } @@ -904,7 +906,7 @@ void qht_statistics_init(const struct qht *ht, struct qht_stats *stats) const struct qht_map *map; int i; - map = atomic_rcu_read(&ht->map); + map = qatomic_rcu_read(&ht->map); stats->used_head_buckets = 0; stats->entries = 0; @@ -932,13 +934,13 @@ void qht_statistics_init(const struct qht *ht, struct qht_stats *stats) b = head; do { for (j = 0; j < QHT_BUCKET_ENTRIES; j++) { - if (atomic_read(&b->pointers[j]) == NULL) { + if (qatomic_read(&b->pointers[j]) == NULL) { break; } entries++; } buckets++; - b = atomic_rcu_read(&b->next); + b = qatomic_rcu_read(&b->next); } while (b); } while (seqlock_read_retry(&head->sequence, version)); diff --git a/util/qsp.c b/util/qsp.c index 7d5147f1b201a78c6950b02733817391db24090e..bacc5fa2f6f21d752259b70696f161c1cd08e9a6 100644 --- a/util/qsp.c +++ b/util/qsp.c @@ -245,11 +245,11 @@ static void qsp_do_init(void) static __attribute__((noinline)) void qsp_init__slowpath(void) { - if (atomic_cmpxchg(&qsp_initializing, false, true) == false) { + if (qatomic_cmpxchg(&qsp_initializing, false, true) == false) { qsp_do_init(); - atomic_set(&qsp_initialized, true); + qatomic_set(&qsp_initialized, true); } else { - while (!atomic_read(&qsp_initialized)) { + while (!qatomic_read(&qsp_initialized)) { cpu_relax(); } } @@ -258,7 +258,7 @@ static __attribute__((noinline)) void qsp_init__slowpath(void) /* qsp_init() must be called from _all_ exported functions */ static inline void qsp_init(void) { - if (likely(atomic_read(&qsp_initialized))) { + if (likely(qatomic_read(&qsp_initialized))) { return; } qsp_init__slowpath(); @@ -346,9 +346,9 @@ static QSPEntry *qsp_entry_get(const void *obj, const char *file, int line, */ static inline void do_qsp_entry_record(QSPEntry *e, int64_t delta, bool acq) { - atomic_set_u64(&e->ns, e->ns + delta); + qatomic_set_u64(&e->ns, e->ns + delta); if (acq) { - atomic_set_u64(&e->n_acqs, e->n_acqs + 1); + qatomic_set_u64(&e->n_acqs, e->n_acqs + 1); } } @@ -432,29 +432,29 @@ qsp_cond_timedwait(QemuCond *cond, QemuMutex *mutex, int ms, bool qsp_is_enabled(void) { - return atomic_read(&qemu_mutex_lock_func) == qsp_mutex_lock; + return qatomic_read(&qemu_mutex_lock_func) == qsp_mutex_lock; } void qsp_enable(void) { - atomic_set(&qemu_mutex_lock_func, qsp_mutex_lock); - atomic_set(&qemu_mutex_trylock_func, qsp_mutex_trylock); - atomic_set(&qemu_bql_mutex_lock_func, qsp_bql_mutex_lock); - atomic_set(&qemu_rec_mutex_lock_func, qsp_rec_mutex_lock); - atomic_set(&qemu_rec_mutex_trylock_func, qsp_rec_mutex_trylock); - atomic_set(&qemu_cond_wait_func, qsp_cond_wait); - atomic_set(&qemu_cond_timedwait_func, qsp_cond_timedwait); + qatomic_set(&qemu_mutex_lock_func, qsp_mutex_lock); + qatomic_set(&qemu_mutex_trylock_func, qsp_mutex_trylock); + qatomic_set(&qemu_bql_mutex_lock_func, qsp_bql_mutex_lock); + qatomic_set(&qemu_rec_mutex_lock_func, qsp_rec_mutex_lock); + qatomic_set(&qemu_rec_mutex_trylock_func, qsp_rec_mutex_trylock); + qatomic_set(&qemu_cond_wait_func, qsp_cond_wait); + qatomic_set(&qemu_cond_timedwait_func, qsp_cond_timedwait); } void qsp_disable(void) { - atomic_set(&qemu_mutex_lock_func, qemu_mutex_lock_impl); - atomic_set(&qemu_mutex_trylock_func, qemu_mutex_trylock_impl); - atomic_set(&qemu_bql_mutex_lock_func, qemu_mutex_lock_impl); - atomic_set(&qemu_rec_mutex_lock_func, qemu_rec_mutex_lock_impl); - atomic_set(&qemu_rec_mutex_trylock_func, qemu_rec_mutex_trylock_impl); - atomic_set(&qemu_cond_wait_func, qemu_cond_wait_impl); - atomic_set(&qemu_cond_timedwait_func, qemu_cond_timedwait_impl); + qatomic_set(&qemu_mutex_lock_func, qemu_mutex_lock_impl); + qatomic_set(&qemu_mutex_trylock_func, qemu_mutex_trylock_impl); + qatomic_set(&qemu_bql_mutex_lock_func, qemu_mutex_lock_impl); + qatomic_set(&qemu_rec_mutex_lock_func, qemu_rec_mutex_lock_impl); + qatomic_set(&qemu_rec_mutex_trylock_func, qemu_rec_mutex_trylock_impl); + qatomic_set(&qemu_cond_wait_func, qemu_cond_wait_impl); + qatomic_set(&qemu_cond_timedwait_func, qemu_cond_timedwait_impl); } static gint qsp_tree_cmp(gconstpointer ap, gconstpointer bp, gpointer up) @@ -538,8 +538,8 @@ static void qsp_aggregate(void *p, uint32_t h, void *up) * The entry is in the global hash table; read from it atomically (as in * "read once"). */ - agg->ns += atomic_read_u64(&e->ns); - agg->n_acqs += atomic_read_u64(&e->n_acqs); + agg->ns += qatomic_read_u64(&e->ns); + agg->n_acqs += qatomic_read_u64(&e->n_acqs); } static void qsp_iter_diff(void *p, uint32_t hash, void *htp) @@ -610,7 +610,7 @@ static void qsp_mktree(GTree *tree, bool callsite_coalesce) * with the snapshot. */ WITH_RCU_READ_LOCK_GUARD() { - QSPSnapshot *snap = atomic_rcu_read(&qsp_snapshot); + QSPSnapshot *snap = qatomic_rcu_read(&qsp_snapshot); /* Aggregate all results from the global hash table into a local one */ qht_init(&ht, qsp_entry_no_thread_cmp, QSP_INITIAL_SIZE, @@ -806,7 +806,7 @@ void qsp_reset(void) qht_iter(&qsp_ht, qsp_aggregate, &new->ht); /* replace the previous snapshot, if any */ - old = atomic_xchg(&qsp_snapshot, new); + old = qatomic_xchg(&qsp_snapshot, new); if (old) { call_rcu(old, qsp_snapshot_destroy, rcu); } diff --git a/util/rcu.c b/util/rcu.c index 60a37f72c36cb45767ec7c71f28f8a8ed4e3a2e2..13ac0f75cb2a7de3b61f13174fb545b8fd08e314 100644 --- a/util/rcu.c +++ b/util/rcu.c @@ -57,7 +57,7 @@ static inline int rcu_gp_ongoing(unsigned long *ctr) { unsigned long v; - v = atomic_read(ctr); + v = qatomic_read(ctr); return v && (v != rcu_gp_ctr); } @@ -82,14 +82,14 @@ static void wait_for_readers(void) */ qemu_event_reset(&rcu_gp_event); - /* Instead of using atomic_mb_set for index->waiting, and - * atomic_mb_read for index->ctr, memory barriers are placed + /* Instead of using qatomic_mb_set for index->waiting, and + * qatomic_mb_read for index->ctr, memory barriers are placed * manually since writes to different threads are independent. * qemu_event_reset has acquire semantics, so no memory barrier * is needed here. */ QLIST_FOREACH(index, ®istry, node) { - atomic_set(&index->waiting, true); + qatomic_set(&index->waiting, true); } /* Here, order the stores to index->waiting before the loads of @@ -106,7 +106,7 @@ static void wait_for_readers(void) /* No need for mb_set here, worst of all we * get some extra futex wakeups. */ - atomic_set(&index->waiting, false); + qatomic_set(&index->waiting, false); } } @@ -151,7 +151,7 @@ void synchronize_rcu(void) QEMU_LOCK_GUARD(&rcu_registry_lock); if (!QLIST_EMPTY(®istry)) { - /* In either case, the atomic_mb_set below blocks stores that free + /* In either case, the qatomic_mb_set below blocks stores that free * old RCU-protected pointers. */ if (sizeof(rcu_gp_ctr) < 8) { @@ -160,12 +160,12 @@ void synchronize_rcu(void) * * Switch parity: 0 -> 1, 1 -> 0. */ - atomic_mb_set(&rcu_gp_ctr, rcu_gp_ctr ^ RCU_GP_CTR); + qatomic_mb_set(&rcu_gp_ctr, rcu_gp_ctr ^ RCU_GP_CTR); wait_for_readers(); - atomic_mb_set(&rcu_gp_ctr, rcu_gp_ctr ^ RCU_GP_CTR); + qatomic_mb_set(&rcu_gp_ctr, rcu_gp_ctr ^ RCU_GP_CTR); } else { /* Increment current grace period. */ - atomic_mb_set(&rcu_gp_ctr, rcu_gp_ctr + RCU_GP_CTR); + qatomic_mb_set(&rcu_gp_ctr, rcu_gp_ctr + RCU_GP_CTR); } wait_for_readers(); @@ -188,8 +188,8 @@ static void enqueue(struct rcu_head *node) struct rcu_head **old_tail; node->next = NULL; - old_tail = atomic_xchg(&tail, &node->next); - atomic_mb_set(old_tail, node); + old_tail = qatomic_xchg(&tail, &node->next); + qatomic_mb_set(old_tail, node); } static struct rcu_head *try_dequeue(void) @@ -203,7 +203,7 @@ retry: * The tail, because it is the first step in the enqueuing. * It is only the next pointers that might be inconsistent. */ - if (head == &dummy && atomic_mb_read(&tail) == &dummy.next) { + if (head == &dummy && qatomic_mb_read(&tail) == &dummy.next) { abort(); } @@ -211,7 +211,7 @@ retry: * wrong and we need to wait until its enqueuer finishes the update. */ node = head; - next = atomic_mb_read(&head->next); + next = qatomic_mb_read(&head->next); if (!next) { return NULL; } @@ -240,7 +240,7 @@ static void *call_rcu_thread(void *opaque) for (;;) { int tries = 0; - int n = atomic_read(&rcu_call_count); + int n = qatomic_read(&rcu_call_count); /* Heuristically wait for a decent number of callbacks to pile up. * Fetch rcu_call_count now, we only must process elements that were @@ -250,7 +250,7 @@ static void *call_rcu_thread(void *opaque) g_usleep(10000); if (n == 0) { qemu_event_reset(&rcu_call_ready_event); - n = atomic_read(&rcu_call_count); + n = qatomic_read(&rcu_call_count); if (n == 0) { #if defined(CONFIG_MALLOC_TRIM) malloc_trim(4 * 1024 * 1024); @@ -258,10 +258,10 @@ static void *call_rcu_thread(void *opaque) qemu_event_wait(&rcu_call_ready_event); } } - n = atomic_read(&rcu_call_count); + n = qatomic_read(&rcu_call_count); } - atomic_sub(&rcu_call_count, n); + qatomic_sub(&rcu_call_count, n); synchronize_rcu(); qemu_mutex_lock_iothread(); while (n > 0) { @@ -289,10 +289,65 @@ void call_rcu1(struct rcu_head *node, void (*func)(struct rcu_head *node)) { node->func = func; enqueue(node); - atomic_inc(&rcu_call_count); + qatomic_inc(&rcu_call_count); qemu_event_set(&rcu_call_ready_event); } + +struct rcu_drain { + struct rcu_head rcu; + QemuEvent drain_complete_event; +}; + +static void drain_rcu_callback(struct rcu_head *node) +{ + struct rcu_drain *event = (struct rcu_drain *)node; + qemu_event_set(&event->drain_complete_event); +} + +/* + * This function ensures that all pending RCU callbacks + * on the current thread are done executing + + * drops big qemu lock during the wait to allow RCU thread + * to process the callbacks + * + */ + +void drain_call_rcu(void) +{ + struct rcu_drain rcu_drain; + bool locked = qemu_mutex_iothread_locked(); + + memset(&rcu_drain, 0, sizeof(struct rcu_drain)); + qemu_event_init(&rcu_drain.drain_complete_event, false); + + if (locked) { + qemu_mutex_unlock_iothread(); + } + + + /* + * RCU callbacks are invoked in the same order as in which they + * are registered, thus we can be sure that when 'drain_rcu_callback' + * is called, all RCU callbacks that were registered on this thread + * prior to calling this function are completed. + * + * Note that since we have only one global queue of the RCU callbacks, + * we also end up waiting for most of RCU callbacks that were registered + * on the other threads, but this is a side effect that shoudn't be + * assumed. + */ + + call_rcu1(&rcu_drain.rcu, drain_rcu_callback); + qemu_event_wait(&rcu_drain.drain_complete_event); + + if (locked) { + qemu_mutex_lock_iothread(); + } + +} + void rcu_register_thread(void) { assert(rcu_reader.ctr == 0); diff --git a/util/stats64.c b/util/stats64.c index 389c365a9ef8fe6fc58577abfcc510af45534e7b..897613c94965dee4783c8ef38fc6dc309a57a766 100644 --- a/util/stats64.c +++ b/util/stats64.c @@ -18,27 +18,27 @@ static inline void stat64_rdlock(Stat64 *s) { /* Keep out incoming writers to avoid them starving us. */ - atomic_add(&s->lock, 2); + qatomic_add(&s->lock, 2); /* If there is a concurrent writer, wait for it. */ - while (atomic_read(&s->lock) & 1) { + while (qatomic_read(&s->lock) & 1) { cpu_relax(); } } static inline void stat64_rdunlock(Stat64 *s) { - atomic_sub(&s->lock, 2); + qatomic_sub(&s->lock, 2); } static inline bool stat64_wrtrylock(Stat64 *s) { - return atomic_cmpxchg(&s->lock, 0, 1) == 0; + return qatomic_cmpxchg(&s->lock, 0, 1) == 0; } static inline void stat64_wrunlock(Stat64 *s) { - atomic_dec(&s->lock); + qatomic_dec(&s->lock); } uint64_t stat64_get(const Stat64 *s) @@ -50,8 +50,8 @@ uint64_t stat64_get(const Stat64 *s) /* 64-bit writes always take the lock, so we can read in * any order. */ - high = atomic_read(&s->high); - low = atomic_read(&s->low); + high = qatomic_read(&s->high); + low = qatomic_read(&s->low); stat64_rdunlock((Stat64 *)s); return ((uint64_t)high << 32) | low; @@ -70,9 +70,9 @@ bool stat64_add32_carry(Stat64 *s, uint32_t low, uint32_t high) * order of our update. By updating s->low first, we can check * whether we have to carry into s->high. */ - old = atomic_fetch_add(&s->low, low); + old = qatomic_fetch_add(&s->low, low); high += (old + low) < old; - atomic_add(&s->high, high); + qatomic_add(&s->high, high); stat64_wrunlock(s); return true; } @@ -87,8 +87,8 @@ bool stat64_min_slow(Stat64 *s, uint64_t value) return false; } - high = atomic_read(&s->high); - low = atomic_read(&s->low); + high = qatomic_read(&s->high); + low = qatomic_read(&s->low); orig = ((uint64_t)high << 32) | low; if (value < orig) { @@ -98,9 +98,9 @@ bool stat64_min_slow(Stat64 *s, uint64_t value) * effect on stat64_min is that the slow path may be triggered * unnecessarily. */ - atomic_set(&s->low, (uint32_t)value); + qatomic_set(&s->low, (uint32_t)value); smp_wmb(); - atomic_set(&s->high, value >> 32); + qatomic_set(&s->high, value >> 32); } stat64_wrunlock(s); return true; @@ -116,8 +116,8 @@ bool stat64_max_slow(Stat64 *s, uint64_t value) return false; } - high = atomic_read(&s->high); - low = atomic_read(&s->low); + high = qatomic_read(&s->high); + low = qatomic_read(&s->low); orig = ((uint64_t)high << 32) | low; if (value > orig) { @@ -127,9 +127,9 @@ bool stat64_max_slow(Stat64 *s, uint64_t value) * effect on stat64_max is that the slow path may be triggered * unnecessarily. */ - atomic_set(&s->low, (uint32_t)value); + qatomic_set(&s->low, (uint32_t)value); smp_wmb(); - atomic_set(&s->high, value >> 32); + qatomic_set(&s->high, value >> 32); } stat64_wrunlock(s); return true; diff --git a/util/trace-events b/util/trace-events index 0ce42822eba9f160302cca3b3bf15a1e6c09e80b..61e0d4bcdfef4d86158c74029bb9fe8e750d5751 100644 --- a/util/trace-events +++ b/util/trace-events @@ -28,7 +28,7 @@ qemu_file_monitor_add_watch(void *mon, const char *dirpath, const char *filename qemu_file_monitor_remove_watch(void *mon, const char *dirpath, int64_t id) "File monitor %p remove watch dir='%s' id=%" PRId64 qemu_file_monitor_new(void *mon, int fd) "File monitor %p created fd=%d" qemu_file_monitor_enable_watch(void *mon, const char *dirpath, int id) "File monitor %p enable watch dir='%s' id=%u" -qemu_file_monitor_disable_watch(void *mon, const char *dirpath, int id) "Fle monitor %p disable watch dir='%s' id=%u" +qemu_file_monitor_disable_watch(void *mon, const char *dirpath, int id) "File monitor %p disable watch dir='%s' id=%u" qemu_file_monitor_event(void *mon, const char *dirpath, const char *filename, int mask, unsigned int id) "File monitor %p event dir='%s' file='%s' mask=0x%x id=%u" qemu_file_monitor_dispatch(void *mon, const char *dirpath, const char *filename, int ev, void *cb, void *opaque, int64_t id) "File monitor %p dispatch dir='%s' file='%s' ev=%d cb=%p opaque=%p id=%" PRId64 @@ -44,8 +44,8 @@ qemu_co_mutex_lock_return(void *mutex, void *self) "mutex %p self %p" qemu_co_mutex_unlock_entry(void *mutex, void *self) "mutex %p self %p" qemu_co_mutex_unlock_return(void *mutex, void *self) "mutex %p self %p" -# oslib-win32.c # oslib-posix.c +# oslib-win32.c qemu_memalign(size_t alignment, size_t size, void *ptr) "alignment %zu size %zu ptr %p" qemu_anon_ram_alloc(size_t size, void *ptr) "size %zu ptr %p" qemu_vfree(void *ptr) "ptr %p" @@ -70,6 +70,8 @@ lockcnt_futex_wake(const void *lockcnt) "lockcnt %p waking up one waiter" socket_listen(int num) "backlog: %d" # qemu-thread-common.h +# qemu-thread-posix.c +# qemu-thread-win32.c qemu_mutex_lock(void *mutex, const char *file, const int line) "waiting on mutex %p (%s:%d)" qemu_mutex_locked(void *mutex, const char *file, const int line) "taken mutex %p (%s:%d)" qemu_mutex_unlock(void *mutex, const char *file, const int line) "released mutex %p (%s:%d)" @@ -78,8 +80,14 @@ qemu_mutex_unlock(void *mutex, const char *file, const int line) "released mutex qemu_vfio_dma_reset_temporary(void *s) "s %p" qemu_vfio_ram_block_added(void *s, void *p, size_t size) "s %p host %p size 0x%zx" qemu_vfio_ram_block_removed(void *s, void *p, size_t size) "s %p host %p size 0x%zx" +qemu_vfio_dump_mapping(void *host, uint64_t iova, size_t size) "vfio mapping %p to iova 0x%08" PRIx64 " size 0x%zx" qemu_vfio_find_mapping(void *s, void *p) "s %p host %p" -qemu_vfio_new_mapping(void *s, void *host, size_t size, int index, uint64_t iova) "s %p host %p size %zu index %d iova 0x%"PRIx64 -qemu_vfio_do_mapping(void *s, void *host, size_t size, uint64_t iova) "s %p host %p size %zu iova 0x%"PRIx64 -qemu_vfio_dma_map(void *s, void *host, size_t size, bool temporary, uint64_t *iova) "s %p host %p size %zu temporary %d iova %p" +qemu_vfio_new_mapping(void *s, void *host, size_t size, int index, uint64_t iova) "s %p host %p size 0x%zx index %d iova 0x%"PRIx64 +qemu_vfio_do_mapping(void *s, void *host, uint64_t iova, size_t size) "s %p host %p <-> iova 0x%"PRIx64 " size 0x%zx" +qemu_vfio_dma_map(void *s, void *host, size_t size, bool temporary, uint64_t *iova) "s %p host %p size 0x%zx temporary %d &iova %p" +qemu_vfio_dma_mapped(void *s, void *host, uint64_t iova, size_t size) "s %p host %p <-> iova 0x%"PRIx64" size 0x%zx" qemu_vfio_dma_unmap(void *s, void *host) "s %p host %p" +qemu_vfio_pci_read_config(void *buf, int ofs, int size, uint64_t region_ofs, uint64_t region_size) "read cfg ptr %p ofs 0x%x size 0x%x (region addr 0x%"PRIx64" size 0x%"PRIx64")" +qemu_vfio_pci_write_config(void *buf, int ofs, int size, uint64_t region_ofs, uint64_t region_size) "write cfg ptr %p ofs 0x%x size 0x%x (region addr 0x%"PRIx64" size 0x%"PRIx64")" +qemu_vfio_region_info(const char *desc, uint64_t region_ofs, uint64_t region_size, uint32_t cap_offset) "region '%s' addr 0x%"PRIx64" size 0x%"PRIx64" cap_ofs 0x%"PRIx32 +qemu_vfio_pci_map_bar(int index, uint64_t region_ofs, uint64_t region_size, int ofs, void *host) "map region bar#%d addr 0x%"PRIx64" size 0x%"PRIx64" ofs 0x%x host %p" diff --git a/util/trace.h b/util/trace.h new file mode 100644 index 0000000000000000000000000000000000000000..86ff7a390caf2d46b96171aa943ae1de29bbab29 --- /dev/null +++ b/util/trace.h @@ -0,0 +1 @@ +#include "trace/trace-util.h" diff --git a/util/vfio-helpers.c b/util/vfio-helpers.c index e399e330e26ad1f30143bb85677545894181a705..97dfa3fd57cc1eac43e308551ee59275740d730e 100644 --- a/util/vfio-helpers.c +++ b/util/vfio-helpers.c @@ -16,6 +16,7 @@ #include "qapi/error.h" #include "exec/ramlist.h" #include "exec/cpu-common.h" +#include "exec/memory.h" #include "trace.h" #include "qemu/error-report.h" #include "standard-headers/linux/pci_regs.h" @@ -40,6 +41,11 @@ typedef struct { uint64_t iova; } IOVAMapping; +struct IOVARange { + uint64_t start; + uint64_t end; +}; + struct QEMUVFIOState { QemuMutex lock; @@ -49,6 +55,8 @@ struct QEMUVFIOState { int device; RAMBlockNotifier ram_notifier; struct vfio_region_info config_region_info, bar_region_info[6]; + struct IOVARange *usable_iova_ranges; + uint8_t nb_iova_ranges; /* These fields are protected by @lock */ /* VFIO's IO virtual address space is managed by splitting into a few @@ -129,6 +137,7 @@ static inline void assert_bar_index_valid(QEMUVFIOState *s, int index) static int qemu_vfio_pci_init_bar(QEMUVFIOState *s, int index, Error **errp) { + g_autofree char *barname = NULL; assert_bar_index_valid(s, index); s->bar_region_info[index] = (struct vfio_region_info) { .index = VFIO_PCI_BAR0_REGION_INDEX + index, @@ -138,6 +147,10 @@ static int qemu_vfio_pci_init_bar(QEMUVFIOState *s, int index, Error **errp) error_setg_errno(errp, errno, "Failed to get BAR region info"); return -errno; } + barname = g_strdup_printf("bar[%d]", index); + trace_qemu_vfio_region_info(barname, s->bar_region_info[index].offset, + s->bar_region_info[index].size, + s->bar_region_info[index].cap_offset); return 0; } @@ -146,14 +159,17 @@ static int qemu_vfio_pci_init_bar(QEMUVFIOState *s, int index, Error **errp) * Map a PCI bar area. */ void *qemu_vfio_pci_map_bar(QEMUVFIOState *s, int index, - uint64_t offset, uint64_t size, + uint64_t offset, uint64_t size, int prot, Error **errp) { void *p; + assert(QEMU_IS_ALIGNED(offset, qemu_real_host_page_size)); assert_bar_index_valid(s, index); p = mmap(NULL, MIN(size, s->bar_region_info[index].size - offset), - PROT_READ | PROT_WRITE, MAP_SHARED, + prot, MAP_SHARED, s->device, s->bar_region_info[index].offset + offset); + trace_qemu_vfio_pci_map_bar(index, s->bar_region_info[index].offset , + size, offset, p); if (p == MAP_FAILED) { error_setg_errno(errp, errno, "Failed to map BAR region"); p = NULL; @@ -173,7 +189,7 @@ void qemu_vfio_pci_unmap_bar(QEMUVFIOState *s, int index, void *bar, } /** - * Initialize device IRQ with @irq_type and and register an event notifier. + * Initialize device IRQ with @irq_type and register an event notifier. */ int qemu_vfio_pci_init_irq(QEMUVFIOState *s, EventNotifier *e, int irq_type, Error **errp) @@ -220,6 +236,10 @@ static int qemu_vfio_pci_read_config(QEMUVFIOState *s, void *buf, { int ret; + trace_qemu_vfio_pci_read_config(buf, ofs, size, + s->config_region_info.offset, + s->config_region_info.size); + assert(QEMU_IS_ALIGNED(s->config_region_info.offset + ofs, size)); do { ret = pread(s->device, buf, size, s->config_region_info.offset + ofs); } while (ret == -1 && errno == EINTR); @@ -230,12 +250,45 @@ static int qemu_vfio_pci_write_config(QEMUVFIOState *s, void *buf, int size, int { int ret; + trace_qemu_vfio_pci_write_config(buf, ofs, size, + s->config_region_info.offset, + s->config_region_info.size); + assert(QEMU_IS_ALIGNED(s->config_region_info.offset + ofs, size)); do { ret = pwrite(s->device, buf, size, s->config_region_info.offset + ofs); } while (ret == -1 && errno == EINTR); return ret == size ? 0 : -errno; } +static void collect_usable_iova_ranges(QEMUVFIOState *s, void *buf) +{ + struct vfio_iommu_type1_info *info = (struct vfio_iommu_type1_info *)buf; + struct vfio_info_cap_header *cap = (void *)buf + info->cap_offset; + struct vfio_iommu_type1_info_cap_iova_range *cap_iova_range; + int i; + + while (cap->id != VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE) { + if (!cap->next) { + return; + } + cap = (struct vfio_info_cap_header *)(buf + cap->next); + } + + cap_iova_range = (struct vfio_iommu_type1_info_cap_iova_range *)cap; + + s->nb_iova_ranges = cap_iova_range->nr_iovas; + if (s->nb_iova_ranges > 1) { + s->usable_iova_ranges = + g_realloc(s->usable_iova_ranges, + s->nb_iova_ranges * sizeof(struct IOVARange)); + } + + for (i = 0; i < s->nb_iova_ranges; i++) { + s->usable_iova_ranges[i].start = cap_iova_range->iova_ranges[i].start; + s->usable_iova_ranges[i].end = cap_iova_range->iova_ranges[i].end; + } +} + static int qemu_vfio_init_pci(QEMUVFIOState *s, const char *device, Error **errp) { @@ -243,10 +296,13 @@ static int qemu_vfio_init_pci(QEMUVFIOState *s, const char *device, int i; uint16_t pci_cmd; struct vfio_group_status group_status = { .argsz = sizeof(group_status) }; - struct vfio_iommu_type1_info iommu_info = { .argsz = sizeof(iommu_info) }; + struct vfio_iommu_type1_info *iommu_info = NULL; + size_t iommu_info_size = sizeof(*iommu_info); struct vfio_device_info device_info = { .argsz = sizeof(device_info) }; char *group_file = NULL; + s->usable_iova_ranges = NULL; + /* Create a new container */ s->container = open("/dev/vfio/vfio", O_RDWR); @@ -261,7 +317,7 @@ static int qemu_vfio_init_pci(QEMUVFIOState *s, const char *device, } if (!ioctl(s->container, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU)) { - error_setg_errno(errp, errno, "VFIO IOMMU check failed"); + error_setg_errno(errp, errno, "VFIO IOMMU Type1 is not supported"); ret = -EINVAL; goto fail_container; } @@ -310,13 +366,35 @@ static int qemu_vfio_init_pci(QEMUVFIOState *s, const char *device, goto fail; } + iommu_info = g_malloc0(iommu_info_size); + iommu_info->argsz = iommu_info_size; + /* Get additional IOMMU info */ - if (ioctl(s->container, VFIO_IOMMU_GET_INFO, &iommu_info)) { + if (ioctl(s->container, VFIO_IOMMU_GET_INFO, iommu_info)) { error_setg_errno(errp, errno, "Failed to get IOMMU info"); ret = -errno; goto fail; } + /* + * if the kernel does not report usable IOVA regions, choose + * the legacy [QEMU_VFIO_IOVA_MIN, QEMU_VFIO_IOVA_MAX -1] region + */ + s->nb_iova_ranges = 1; + s->usable_iova_ranges = g_new0(struct IOVARange, 1); + s->usable_iova_ranges[0].start = QEMU_VFIO_IOVA_MIN; + s->usable_iova_ranges[0].end = QEMU_VFIO_IOVA_MAX - 1; + + if (iommu_info->argsz > iommu_info_size) { + iommu_info_size = iommu_info->argsz; + iommu_info = g_realloc(iommu_info, iommu_info_size); + if (ioctl(s->container, VFIO_IOMMU_GET_INFO, iommu_info)) { + ret = -errno; + goto fail; + } + collect_usable_iova_ranges(s, iommu_info); + } + s->device = ioctl(s->group, VFIO_GROUP_GET_DEVICE_FD, device); if (s->device < 0) { @@ -347,6 +425,9 @@ static int qemu_vfio_init_pci(QEMUVFIOState *s, const char *device, ret = -errno; goto fail; } + trace_qemu_vfio_region_info("config", s->config_region_info.offset, + s->config_region_info.size, + s->config_region_info.cap_offset); for (i = 0; i < ARRAY_SIZE(s->bar_region_info); i++) { ret = qemu_vfio_pci_init_bar(s, i, errp); @@ -365,8 +446,13 @@ static int qemu_vfio_init_pci(QEMUVFIOState *s, const char *device, if (ret) { goto fail; } + g_free(iommu_info); return 0; fail: + g_free(s->usable_iova_ranges); + s->usable_iova_ranges = NULL; + s->nb_iova_ranges = 0; + g_free(iommu_info); close(s->group); fail_container: close(s->container); @@ -428,8 +514,20 @@ QEMUVFIOState *qemu_vfio_open_pci(const char *device, Error **errp) int r; QEMUVFIOState *s = g_new0(QEMUVFIOState, 1); + /* + * VFIO may pin all memory inside mappings, resulting it in pinning + * all memory inside RAM blocks unconditionally. + */ + r = ram_block_discard_disable(true); + if (r) { + error_setg_errno(errp, -r, "Cannot set discarding of RAM broken"); + g_free(s); + return NULL; + } + r = qemu_vfio_init_pci(s, device, errp); if (r) { + ram_block_discard_disable(false); g_free(s); return NULL; } @@ -437,23 +535,12 @@ QEMUVFIOState *qemu_vfio_open_pci(const char *device, Error **errp) return s; } -static void qemu_vfio_dump_mapping(IOVAMapping *m) -{ - if (QEMU_VFIO_DEBUG) { - printf(" vfio mapping %p %" PRIx64 " to %" PRIx64 "\n", m->host, - (uint64_t)m->size, (uint64_t)m->iova); - } -} - static void qemu_vfio_dump_mappings(QEMUVFIOState *s) { - int i; - - if (QEMU_VFIO_DEBUG) { - printf("vfio mappings\n"); - for (i = 0; i < s->nr_mappings; ++i) { - qemu_vfio_dump_mapping(&s->mappings[i]); - } + for (int i = 0; i < s->nr_mappings; ++i) { + trace_qemu_vfio_dump_mapping(s->mappings[i].host, + s->mappings[i].iova, + s->mappings[i].size); } } @@ -505,7 +592,7 @@ static IOVAMapping *qemu_vfio_find_mapping(QEMUVFIOState *s, void *host, } /** - * Allocate IOVA and and create a new mapping record and insert it in @s. + * Allocate IOVA and create a new mapping record and insert it in @s. */ static IOVAMapping *qemu_vfio_add_mapping(QEMUVFIOState *s, void *host, size_t size, @@ -543,7 +630,7 @@ static int qemu_vfio_do_mapping(QEMUVFIOState *s, void *host, size_t size, .vaddr = (uintptr_t)host, .size = size, }; - trace_qemu_vfio_do_mapping(s, host, size, iova); + trace_qemu_vfio_do_mapping(s, host, iova, size); if (ioctl(s->container, VFIO_IOMMU_MAP_DMA, &dma_map)) { error_report("VFIO_MAP_DMA failed: %s", strerror(errno)); @@ -601,6 +688,50 @@ static bool qemu_vfio_verify_mappings(QEMUVFIOState *s) return true; } +static int +qemu_vfio_find_fixed_iova(QEMUVFIOState *s, size_t size, uint64_t *iova) +{ + int i; + + for (i = 0; i < s->nb_iova_ranges; i++) { + if (s->usable_iova_ranges[i].end < s->low_water_mark) { + continue; + } + s->low_water_mark = + MAX(s->low_water_mark, s->usable_iova_ranges[i].start); + + if (s->usable_iova_ranges[i].end - s->low_water_mark + 1 >= size || + s->usable_iova_ranges[i].end - s->low_water_mark + 1 == 0) { + *iova = s->low_water_mark; + s->low_water_mark += size; + return 0; + } + } + return -ENOMEM; +} + +static int +qemu_vfio_find_temp_iova(QEMUVFIOState *s, size_t size, uint64_t *iova) +{ + int i; + + for (i = s->nb_iova_ranges - 1; i >= 0; i--) { + if (s->usable_iova_ranges[i].start > s->high_water_mark) { + continue; + } + s->high_water_mark = + MIN(s->high_water_mark, s->usable_iova_ranges[i].end + 1); + + if (s->high_water_mark - s->usable_iova_ranges[i].start + 1 >= size || + s->high_water_mark - s->usable_iova_ranges[i].start + 1 == 0) { + *iova = s->high_water_mark - size; + s->high_water_mark = *iova; + return 0; + } + } + return -ENOMEM; +} + /* Map [host, host + size) area into a contiguous IOVA address space, and store * the result in @iova if not NULL. The caller need to make sure the area is * aligned to page size, and mustn't overlap with existing mapping areas (split @@ -627,7 +758,11 @@ int qemu_vfio_dma_map(QEMUVFIOState *s, void *host, size_t size, goto out; } if (!temporary) { - iova0 = s->low_water_mark; + if (qemu_vfio_find_fixed_iova(s, size, &iova0)) { + ret = -ENOMEM; + goto out; + } + mapping = qemu_vfio_add_mapping(s, host, size, index + 1, iova0); if (!mapping) { ret = -ENOMEM; @@ -639,17 +774,19 @@ int qemu_vfio_dma_map(QEMUVFIOState *s, void *host, size_t size, qemu_vfio_undo_mapping(s, mapping, NULL); goto out; } - s->low_water_mark += size; qemu_vfio_dump_mappings(s); } else { - iova0 = s->high_water_mark - size; + if (qemu_vfio_find_temp_iova(s, size, &iova0)) { + ret = -ENOMEM; + goto out; + } ret = qemu_vfio_do_mapping(s, host, size, iova0); if (ret) { goto out; } - s->high_water_mark -= size; } } + trace_qemu_vfio_dma_mapped(s, host, iova0, size); if (iova) { *iova = iova0; } @@ -716,8 +853,11 @@ void qemu_vfio_close(QEMUVFIOState *s) qemu_vfio_undo_mapping(s, &s->mappings[i], NULL); } ram_block_notifier_remove(&s->ram_notifier); + g_free(s->usable_iova_ranges); + s->nb_iova_ranges = 0; qemu_vfio_reset(s); close(s->device); close(s->group); close(s->container); + ram_block_discard_disable(false); } diff --git a/util/vhost-user-server.c b/util/vhost-user-server.c new file mode 100644 index 0000000000000000000000000000000000000000..783d847a6db3021d16fb1048e751167818119b24 --- /dev/null +++ b/util/vhost-user-server.c @@ -0,0 +1,446 @@ +/* + * Sharing QEMU devices via vhost-user protocol + * + * Copyright (c) Coiby Xu . + * Copyright (c) 2020 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * later. See the COPYING file in the top-level directory. + */ +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "qemu/vhost-user-server.h" +#include "block/aio-wait.h" + +/* + * Theory of operation: + * + * VuServer is started and stopped by vhost_user_server_start() and + * vhost_user_server_stop() from the main loop thread. Starting the server + * opens a vhost-user UNIX domain socket and listens for incoming connections. + * Only one connection is allowed at a time. + * + * The connection is handled by the vu_client_trip() coroutine in the + * VuServer->ctx AioContext. The coroutine consists of a vu_dispatch() loop + * where libvhost-user calls vu_message_read() to receive the next vhost-user + * protocol messages over the UNIX domain socket. + * + * When virtqueues are set up libvhost-user calls set_watch() to monitor kick + * fds. These fds are also handled in the VuServer->ctx AioContext. + * + * Both vu_client_trip() and kick fd monitoring can be stopped by shutting down + * the socket connection. Shutting down the socket connection causes + * vu_message_read() to fail since no more data can be received from the socket. + * After vu_dispatch() fails, vu_client_trip() calls vu_deinit() to stop + * libvhost-user before terminating the coroutine. vu_deinit() calls + * remove_watch() to stop monitoring kick fds and this stops virtqueue + * processing. + * + * When vu_client_trip() has finished cleaning up it schedules a BH in the main + * loop thread to accept the next client connection. + * + * When libvhost-user detects an error it calls panic_cb() and sets the + * dev->broken flag. Both vu_client_trip() and kick fd processing stop when + * the dev->broken flag is set. + * + * It is possible to switch AioContexts using + * vhost_user_server_detach_aio_context() and + * vhost_user_server_attach_aio_context(). They stop monitoring fds in the old + * AioContext and resume monitoring in the new AioContext. The vu_client_trip() + * coroutine remains in a yielded state during the switch. This is made + * possible by QIOChannel's support for spurious coroutine re-entry in + * qio_channel_yield(). The coroutine will restart I/O when re-entered from the + * new AioContext. + */ + +static void vmsg_close_fds(VhostUserMsg *vmsg) +{ + int i; + for (i = 0; i < vmsg->fd_num; i++) { + close(vmsg->fds[i]); + } +} + +static void vmsg_unblock_fds(VhostUserMsg *vmsg) +{ + int i; + for (i = 0; i < vmsg->fd_num; i++) { + qemu_set_nonblock(vmsg->fds[i]); + } +} + +static void panic_cb(VuDev *vu_dev, const char *buf) +{ + error_report("vu_panic: %s", buf); +} + +static bool coroutine_fn +vu_message_read(VuDev *vu_dev, int conn_fd, VhostUserMsg *vmsg) +{ + struct iovec iov = { + .iov_base = (char *)vmsg, + .iov_len = VHOST_USER_HDR_SIZE, + }; + int rc, read_bytes = 0; + Error *local_err = NULL; + const size_t max_fds = G_N_ELEMENTS(vmsg->fds); + VuServer *server = container_of(vu_dev, VuServer, vu_dev); + QIOChannel *ioc = server->ioc; + + vmsg->fd_num = 0; + if (!ioc) { + error_report_err(local_err); + goto fail; + } + + assert(qemu_in_coroutine()); + do { + size_t nfds = 0; + int *fds = NULL; + + /* + * qio_channel_readv_full may have short reads, keeping calling it + * until getting VHOST_USER_HDR_SIZE or 0 bytes in total + */ + rc = qio_channel_readv_full(ioc, &iov, 1, &fds, &nfds, &local_err); + if (rc < 0) { + if (rc == QIO_CHANNEL_ERR_BLOCK) { + assert(local_err == NULL); + qio_channel_yield(ioc, G_IO_IN); + continue; + } else { + error_report_err(local_err); + goto fail; + } + } + + if (nfds > 0) { + if (vmsg->fd_num + nfds > max_fds) { + error_report("A maximum of %zu fds are allowed, " + "however got %zu fds now", + max_fds, vmsg->fd_num + nfds); + g_free(fds); + goto fail; + } + memcpy(vmsg->fds + vmsg->fd_num, fds, nfds * sizeof(vmsg->fds[0])); + vmsg->fd_num += nfds; + g_free(fds); + } + + if (rc == 0) { /* socket closed */ + goto fail; + } + + iov.iov_base += rc; + iov.iov_len -= rc; + read_bytes += rc; + } while (read_bytes != VHOST_USER_HDR_SIZE); + + /* qio_channel_readv_full will make socket fds blocking, unblock them */ + vmsg_unblock_fds(vmsg); + if (vmsg->size > sizeof(vmsg->payload)) { + error_report("Error: too big message request: %d, " + "size: vmsg->size: %u, " + "while sizeof(vmsg->payload) = %zu", + vmsg->request, vmsg->size, sizeof(vmsg->payload)); + goto fail; + } + + struct iovec iov_payload = { + .iov_base = (char *)&vmsg->payload, + .iov_len = vmsg->size, + }; + if (vmsg->size) { + rc = qio_channel_readv_all_eof(ioc, &iov_payload, 1, &local_err); + if (rc != 1) { + if (local_err) { + error_report_err(local_err); + } + goto fail; + } + } + + return true; + +fail: + vmsg_close_fds(vmsg); + + return false; +} + +static coroutine_fn void vu_client_trip(void *opaque) +{ + VuServer *server = opaque; + VuDev *vu_dev = &server->vu_dev; + + while (!vu_dev->broken && vu_dispatch(vu_dev)) { + /* Keep running */ + } + + vu_deinit(vu_dev); + + /* vu_deinit() should have called remove_watch() */ + assert(QTAILQ_EMPTY(&server->vu_fd_watches)); + + object_unref(OBJECT(server->sioc)); + server->sioc = NULL; + + object_unref(OBJECT(server->ioc)); + server->ioc = NULL; + + server->co_trip = NULL; + if (server->restart_listener_bh) { + qemu_bh_schedule(server->restart_listener_bh); + } + aio_wait_kick(); +} + +/* + * a wrapper for vu_kick_cb + * + * since aio_dispatch can only pass one user data pointer to the + * callback function, pack VuDev and pvt into a struct. Then unpack it + * and pass them to vu_kick_cb + */ +static void kick_handler(void *opaque) +{ + VuFdWatch *vu_fd_watch = opaque; + VuDev *vu_dev = vu_fd_watch->vu_dev; + + vu_fd_watch->cb(vu_dev, 0, vu_fd_watch->pvt); + + /* Stop vu_client_trip() if an error occurred in vu_fd_watch->cb() */ + if (vu_dev->broken) { + VuServer *server = container_of(vu_dev, VuServer, vu_dev); + + qio_channel_shutdown(server->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); + } +} + +static VuFdWatch *find_vu_fd_watch(VuServer *server, int fd) +{ + + VuFdWatch *vu_fd_watch, *next; + QTAILQ_FOREACH_SAFE(vu_fd_watch, &server->vu_fd_watches, next, next) { + if (vu_fd_watch->fd == fd) { + return vu_fd_watch; + } + } + return NULL; +} + +static void +set_watch(VuDev *vu_dev, int fd, int vu_evt, + vu_watch_cb cb, void *pvt) +{ + + VuServer *server = container_of(vu_dev, VuServer, vu_dev); + g_assert(vu_dev); + g_assert(fd >= 0); + g_assert(cb); + + VuFdWatch *vu_fd_watch = find_vu_fd_watch(server, fd); + + if (!vu_fd_watch) { + VuFdWatch *vu_fd_watch = g_new0(VuFdWatch, 1); + + QTAILQ_INSERT_TAIL(&server->vu_fd_watches, vu_fd_watch, next); + + vu_fd_watch->fd = fd; + vu_fd_watch->cb = cb; + qemu_set_nonblock(fd); + aio_set_fd_handler(server->ioc->ctx, fd, true, kick_handler, + NULL, NULL, vu_fd_watch); + vu_fd_watch->vu_dev = vu_dev; + vu_fd_watch->pvt = pvt; + } +} + + +static void remove_watch(VuDev *vu_dev, int fd) +{ + VuServer *server; + g_assert(vu_dev); + g_assert(fd >= 0); + + server = container_of(vu_dev, VuServer, vu_dev); + + VuFdWatch *vu_fd_watch = find_vu_fd_watch(server, fd); + + if (!vu_fd_watch) { + return; + } + aio_set_fd_handler(server->ioc->ctx, fd, true, NULL, NULL, NULL, NULL); + + QTAILQ_REMOVE(&server->vu_fd_watches, vu_fd_watch, next); + g_free(vu_fd_watch); +} + + +static void vu_accept(QIONetListener *listener, QIOChannelSocket *sioc, + gpointer opaque) +{ + VuServer *server = opaque; + + if (server->sioc) { + warn_report("Only one vhost-user client is allowed to " + "connect the server one time"); + return; + } + + if (!vu_init(&server->vu_dev, server->max_queues, sioc->fd, panic_cb, + vu_message_read, set_watch, remove_watch, server->vu_iface)) { + error_report("Failed to initialize libvhost-user"); + return; + } + + /* + * Unset the callback function for network listener to make another + * vhost-user client keeping waiting until this client disconnects + */ + qio_net_listener_set_client_func(server->listener, + NULL, + NULL, + NULL); + server->sioc = sioc; + /* + * Increase the object reference, so sioc will not freed by + * qio_net_listener_channel_func which will call object_unref(OBJECT(sioc)) + */ + object_ref(OBJECT(server->sioc)); + qio_channel_set_name(QIO_CHANNEL(sioc), "vhost-user client"); + server->ioc = QIO_CHANNEL(sioc); + object_ref(OBJECT(server->ioc)); + + /* TODO vu_message_write() spins if non-blocking! */ + qio_channel_set_blocking(server->ioc, false, NULL); + + server->co_trip = qemu_coroutine_create(vu_client_trip, server); + + aio_context_acquire(server->ctx); + vhost_user_server_attach_aio_context(server, server->ctx); + aio_context_release(server->ctx); +} + +void vhost_user_server_stop(VuServer *server) +{ + aio_context_acquire(server->ctx); + + qemu_bh_delete(server->restart_listener_bh); + server->restart_listener_bh = NULL; + + if (server->sioc) { + VuFdWatch *vu_fd_watch; + + QTAILQ_FOREACH(vu_fd_watch, &server->vu_fd_watches, next) { + aio_set_fd_handler(server->ctx, vu_fd_watch->fd, true, + NULL, NULL, NULL, vu_fd_watch); + } + + qio_channel_shutdown(server->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); + + AIO_WAIT_WHILE(server->ctx, server->co_trip); + } + + aio_context_release(server->ctx); + + if (server->listener) { + qio_net_listener_disconnect(server->listener); + object_unref(OBJECT(server->listener)); + } +} + +/* + * Allow the next client to connect to the server. Called from a BH in the main + * loop. + */ +static void restart_listener_bh(void *opaque) +{ + VuServer *server = opaque; + + qio_net_listener_set_client_func(server->listener, vu_accept, server, + NULL); +} + +/* Called with ctx acquired */ +void vhost_user_server_attach_aio_context(VuServer *server, AioContext *ctx) +{ + VuFdWatch *vu_fd_watch; + + server->ctx = ctx; + + if (!server->sioc) { + return; + } + + qio_channel_attach_aio_context(server->ioc, ctx); + + QTAILQ_FOREACH(vu_fd_watch, &server->vu_fd_watches, next) { + aio_set_fd_handler(ctx, vu_fd_watch->fd, true, kick_handler, NULL, + NULL, vu_fd_watch); + } + + aio_co_schedule(ctx, server->co_trip); +} + +/* Called with server->ctx acquired */ +void vhost_user_server_detach_aio_context(VuServer *server) +{ + if (server->sioc) { + VuFdWatch *vu_fd_watch; + + QTAILQ_FOREACH(vu_fd_watch, &server->vu_fd_watches, next) { + aio_set_fd_handler(server->ctx, vu_fd_watch->fd, true, + NULL, NULL, NULL, vu_fd_watch); + } + + qio_channel_detach_aio_context(server->ioc); + } + + server->ctx = NULL; +} + +bool vhost_user_server_start(VuServer *server, + SocketAddress *socket_addr, + AioContext *ctx, + uint16_t max_queues, + const VuDevIface *vu_iface, + Error **errp) +{ + QEMUBH *bh; + QIONetListener *listener; + + if (socket_addr->type != SOCKET_ADDRESS_TYPE_UNIX && + socket_addr->type != SOCKET_ADDRESS_TYPE_FD) { + error_setg(errp, "Only socket address types 'unix' and 'fd' are supported"); + return false; + } + + listener = qio_net_listener_new(); + if (qio_net_listener_open_sync(listener, socket_addr, 1, + errp) < 0) { + object_unref(OBJECT(listener)); + return false; + } + + bh = qemu_bh_new(restart_listener_bh, server); + + /* zero out unspecified fields */ + *server = (VuServer) { + .listener = listener, + .restart_listener_bh = bh, + .vu_iface = vu_iface, + .max_queues = max_queues, + .ctx = ctx, + }; + + qio_net_listener_set_name(server->listener, "vhost-user-backend-listener"); + + qio_net_listener_set_client_func(server->listener, + vu_accept, + server, + NULL); + + QTAILQ_INIT(&server->vu_fd_watches); + return true; +}